summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/BUILD.gn142
-rw-r--r--chromium/content/DEPS30
-rw-r--r--chromium/content/OWNERS4
-rw-r--r--chromium/content/README6
-rw-r--r--chromium/content/app/BUILD.gn140
-rw-r--r--chromium/content/app/DEPS3
-rw-r--r--chromium/content/app/android/OWNERS2
-rw-r--r--chromium/content/app/android/child_process_service.cc90
-rw-r--r--chromium/content/app/android/library_loader_hooks.cc16
-rw-r--r--chromium/content/app/content_main_runner.cc114
-rw-r--r--chromium/content/app/mojo/mojo_browsertest.cc10
-rw-r--r--chromium/content/app/mojo/mojo_init.cc10
-rw-r--r--chromium/content/app/resources/BUILD.gn15
-rw-r--r--chromium/content/app/resources/README.txt108
-rw-r--r--chromium/content/app/resources/content_resources.grd89
-rw-r--r--chromium/content/app/resources/content_resources.gyp26
-rw-r--r--chromium/content/app/resources/default_100_percent/alias_cursor.pngbin0 -> 387 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/broken_image.pngbin0 -> 448 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/cell_cursor.pngbin0 -> 157 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/east_resize_cursor.pngbin0 -> 105 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/east_west_resize_cursor.pngbin0 -> 110 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/help_cursor.pngbin0 -> 190 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/link_cursor.pngbin0 -> 317 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_cast_off.pngbin0 -> 37155 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_cast_on.pngbin0 -> 37155 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption.pngbin0 -> 2499 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_disabled.pngbin0 -> 2764 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_down.pngbin0 -> 8520 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_hover.pngbin0 -> 7995 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen.pngbin0 -> 1116 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_disabled.pngbin0 -> 780 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_down.pngbin0 -> 4844 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_hover.pngbin0 -> 4649 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_overlay_cast_off.pngbin0 -> 1293 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_overlay_play.pngbin0 -> 1243 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_pause.pngbin0 -> 814 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_pause_down.pngbin0 -> 4687 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_pause_hover.pngbin0 -> 4507 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_play.pngbin0 -> 1243 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_play_disabled.pngbin0 -> 1007 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_play_down.pngbin0 -> 5591 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_play_hover.pngbin0 -> 5434 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb.pngbin0 -> 4035 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_down.pngbin0 -> 5450 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_hover.pngbin0 -> 5294 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_disabled.pngbin0 -> 1283 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0.pngbin0 -> 1051 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_down.pngbin0 -> 10516 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_hover.pngbin0 -> 10396 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1.pngbin0 -> 962 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_down.pngbin0 -> 5440 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_hover.pngbin0 -> 5257 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2.pngbin0 -> 1263 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_down.pngbin0 -> 10327 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_hover.pngbin0 -> 10113 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3.pngbin0 -> 1669 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_down.pngbin0 -> 12290 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_hover.pngbin0 -> 12122 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb.pngbin0 -> 3749 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.pngbin0 -> 2516 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.pngbin0 -> 4941 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.pngbin0 -> 4773 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/move_cursor.pngbin0 -> 139 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/none_cursor.pngbin0 -> 83 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/north_east_resize_cursor.pngbin0 -> 155 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/north_east_south_west_resize_cursor.pngbin0 -> 166 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/north_resize_cursor.pngbin0 -> 108 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/north_south_resize_cursor.pngbin0 -> 121 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/north_west_resize_cursor.pngbin0 -> 139 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/north_west_south_east_resize_cursor.pngbin0 -> 155 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/overhang_pattern.pngbin0 -> 20057 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/overhang_shadow.pngbin0 -> 151 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/pan_icon.pngbin0 -> 136 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/password_generation.pngbin0 -> 407 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/password_generation_hover.pngbin0 -> 408 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/progress_cursor.pngbin0 -> 1557 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/search_cancel.pngbin0 -> 744 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/search_cancel_pressed.pngbin0 -> 761 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/search_magnifier.pngbin0 -> 872 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/search_magnifier_results.pngbin0 -> 1040 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/solo.pngbin0 -> 696 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/south_east_resize_cursor.pngbin0 -> 135 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/south_resize_cursor.pngbin0 -> 111 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/south_west_resize_cursor.pngbin0 -> 142 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/textarea_resize_corner.pngbin0 -> 92 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/vertical_text_cursor.pngbin0 -> 100 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/wait_cursor.pngbin0 -> 109 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/west_resize_cursor.pngbin0 -> 107 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/zoom_in_cursor.pngbin0 -> 119 bytes
-rw-r--r--chromium/content/app/resources/default_100_percent/zoom_out_cursor.pngbin0 -> 113 bytes
-rw-r--r--chromium/content/app/resources/default_200_percent/broken_image.pngbin0 -> 810 bytes
-rw-r--r--chromium/content/app/resources/default_200_percent/pan_icon.pngbin0 -> 141 bytes
-rw-r--r--chromium/content/app/resources/default_200_percent/textarea_resize_corner.pngbin0 -> 147 bytes
-rw-r--r--chromium/content/app/startup_helper_win.cc2
-rw-r--r--chromium/content/app/strings/BUILD.gn69
-rw-r--r--chromium/content/app/strings/content_strings.grd727
-rw-r--r--chromium/content/app/strings/content_strings.gyp30
-rw-r--r--chromium/content/app/strings/translations/content_strings_am.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ar.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_bg.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_bn.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ca.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_cs.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_da.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_de.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_el.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_en-GB.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_es-419.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_es.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_et.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_fa.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_fi.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_fil.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_fr.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_gu.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_hr.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_hu.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_id.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_it.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_iw.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ja.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_kn.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ko.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_lt.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_lv.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ml.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_mr.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ms.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_nl.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_no.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_pl.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-BR.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-PT.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ro.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ru.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_sk.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_sl.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_sr.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_sv.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_sw.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_ta.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_te.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_th.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_tr.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_uk.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_vi.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-CN.xtb115
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-TW.xtb115
-rw-r--r--chromium/content/browser/BUILD.gn171
-rw-r--r--chromium/content/browser/DEPS20
-rw-r--r--chromium/content/browser/OWNERS4
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc191
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_browsertest.cc87
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_helper.cc25
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_helper.h5
-rw-r--r--chromium/content/browser/accessibility/accessibility_mode_helper_unittest.cc32
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.cc12
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter.h4
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm39
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc1
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc5
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.cc54
-rw-r--r--chromium/content/browser/accessibility/accessibility_ui.h2
-rw-r--r--chromium/content/browser/accessibility/accessibility_win_browsertest.cc7
-rw-r--r--chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc209
-rw-r--r--chromium/content/browser/accessibility/android_hit_testing_browsertest.cc12
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc26
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc273
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h34
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm312
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.h6
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc71
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h104
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc289
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h64
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h10
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm17
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc61
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc79
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h32
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc71
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.h22
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc150
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h645
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc77
-rw-r--r--chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc4
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc655
-rw-r--r--chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc146
-rw-r--r--chromium/content/browser/android/DEPS3
-rw-r--r--chromium/content/browser/android/OWNERS2
-rw-r--r--chromium/content/browser/android/browser_startup_controller.cc4
-rw-r--r--chromium/content/browser/android/browser_surface_texture_manager.cc136
-rw-r--r--chromium/content/browser/android/browser_surface_texture_manager.h43
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.cc52
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.h22
-rw-r--r--chromium/content/browser/android/composited_touch_handle_drawable.cc165
-rw-r--r--chromium/content/browser/android/composited_touch_handle_drawable.h48
-rw-r--r--chromium/content/browser/android/content_readback_handler.cc9
-rw-r--r--chromium/content/browser/android/content_settings.cc4
-rw-r--r--chromium/content/browser/android/content_settings.h2
-rw-r--r--chromium/content/browser/android/content_startup_flags.cc24
-rw-r--r--chromium/content/browser/android/content_startup_flags.h2
-rw-r--r--chromium/content/browser/android/content_video_view.cc80
-rw-r--r--chromium/content/browser/android/content_video_view.h23
-rw-r--r--chromium/content/browser/android/content_view_core_impl.cc784
-rw-r--r--chromium/content/browser/android/content_view_core_impl.h179
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc17
-rw-r--r--chromium/content/browser/android/content_view_render_view.h10
-rw-r--r--chromium/content/browser/android/content_view_statics.cc9
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.cc8
-rw-r--r--chromium/content/browser/android/date_time_chooser_android.h3
-rw-r--r--chromium/content/browser/android/devtools_auth.cc21
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.cc12
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.h11
-rw-r--r--chromium/content/browser/android/edge_effect.cc261
-rw-r--r--chromium/content/browser/android/edge_effect.h90
-rw-r--r--chromium/content/browser/android/edge_effect_base.h49
-rw-r--r--chromium/content/browser/android/edge_effect_l.cc286
-rw-r--r--chromium/content/browser/android/edge_effect_l.h81
-rw-r--r--chromium/content/browser/android/gesture_event_type.h27
-rw-r--r--chromium/content/browser/android/gesture_event_type_list.h33
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc189
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h36
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.cc64
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.h49
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc92
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h43
-rw-r--r--chromium/content/browser/android/in_process/synchronous_input_event_filter.h10
-rw-r--r--chromium/content/browser/android/interstitial_page_delegate_android.h8
-rw-r--r--chromium/content/browser/android/java/DEPS3
-rw-r--r--chromium/content/browser/android/java/OWNERS (renamed from chromium/content/browser/renderer_host/java/OWNERS)0
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object.cc192
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object.h96
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object_delegate.cc43
-rw-r--r--chromium/content/browser/android/java/gin_java_bound_object_delegate.h38
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc564
-rw-r--r--chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h126
-rw-r--r--chromium/content/browser/android/java/gin_java_method_invocation_helper.cc345
-rw-r--r--chromium/content/browser/android/java/gin_java_method_invocation_helper.h117
-rw-r--r--chromium/content/browser/android/java/gin_java_method_invocation_helper_unittest.cc339
-rw-r--r--chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.cc743
-rw-r--r--chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.h35
-rw-r--r--chromium/content/browser/android/java/java_method.cc209
-rw-r--r--chromium/content/browser/android/java/java_method.h50
-rw-r--r--chromium/content/browser/android/java/java_type.cc165
-rw-r--r--chromium/content/browser/android/java/java_type.h57
-rw-r--r--chromium/content/browser/android/java/java_type_unittest.cc86
-rw-r--r--chromium/content/browser/android/overscroll_glow.cc236
-rw-r--r--chromium/content/browser/android/overscroll_glow.h41
-rw-r--r--chromium/content/browser/android/popup_item_type_list.h23
-rw-r--r--chromium/content/browser/android/popup_touch_handle_drawable.cc87
-rw-r--r--chromium/content/browser/android/popup_touch_handle_drawable.h40
-rw-r--r--chromium/content/browser/android/surface_texture_peer_browser_impl.cc91
-rw-r--r--chromium/content/browser/android/surface_texture_peer_browser_impl.h37
-rw-r--r--chromium/content/browser/android/system_ui_resource_manager_impl.cc178
-rw-r--r--chromium/content/browser/android/system_ui_resource_manager_impl.h54
-rw-r--r--chromium/content/browser/android/system_ui_resource_manager_impl_unittest.cc169
-rw-r--r--chromium/content/browser/android/tracing_controller_android.cc22
-rw-r--r--chromium/content/browser/android/tracing_controller_android.h4
-rw-r--r--chromium/content/browser/android/ui_resource_provider_impl.cc14
-rw-r--r--chromium/content/browser/android/ui_resource_provider_impl.h15
-rw-r--r--chromium/content/browser/android/web_contents_observer_android.cc133
-rw-r--r--chromium/content/browser/android/web_contents_observer_android.h62
-rw-r--r--chromium/content/browser/appcache/DEPS3
-rw-r--r--chromium/content/browser/appcache/appcache.cc327
-rw-r--r--chromium/content/browser/appcache/appcache.h210
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.cc182
-rw-r--r--chromium/content/browser/appcache/appcache_backend_impl.h75
-rw-r--r--chromium/content/browser/appcache/appcache_database.cc1228
-rw-r--r--chromium/content/browser/appcache/appcache_database.h251
-rw-r--r--chromium/content/browser/appcache/appcache_database_unittest.cc20
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc372
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.h115
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache_unittest.cc28
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.cc12
-rw-r--r--chromium/content/browser/appcache/appcache_dispatcher_host.h22
-rw-r--r--chromium/content/browser/appcache/appcache_entry.h67
-rw-r--r--chromium/content/browser/appcache/appcache_executable_handler.h54
-rw-r--r--chromium/content/browser/appcache/appcache_frontend_proxy.cc12
-rw-r--r--chromium/content/browser/appcache/appcache_frontend_proxy.h35
-rw-r--r--chromium/content/browser/appcache/appcache_group.cc264
-rw-r--r--chromium/content/browser/appcache/appcache_group.h173
-rw-r--r--chromium/content/browser/appcache/appcache_group_unittest.cc95
-rw-r--r--chromium/content/browser/appcache/appcache_histograms.cc154
-rw-r--r--chromium/content/browser/appcache/appcache_histograms.h63
-rw-r--r--chromium/content/browser/appcache/appcache_host.cc552
-rw-r--r--chromium/content/browser/appcache/appcache_host.h341
-rw-r--r--chromium/content/browser/appcache/appcache_host_unittest.cc127
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.cc64
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.h39
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser.cc382
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser.h72
-rw-r--r--chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc516
-rw-r--r--chromium/content/browser/appcache/appcache_policy.h32
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.cc251
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client.h94
-rw-r--r--chromium/content/browser/appcache/appcache_quota_client_unittest.cc93
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc417
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h151
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler_unittest.cc216
-rw-r--r--chromium/content/browser/appcache/appcache_response.cc423
-rw-r--r--chromium/content/browser/appcache/appcache_response.h262
-rw-r--r--chromium/content/browser/appcache/appcache_response_unittest.cc17
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc580
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.h222
-rw-r--r--chromium/content/browser/appcache/appcache_service_unittest.cc25
-rw-r--r--chromium/content/browser/appcache/appcache_storage.cc139
-rw-r--r--chromium/content/browser/appcache/appcache_storage.h327
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.cc1866
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.h183
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl_unittest.cc255
-rw-r--r--chromium/content/browser/appcache/appcache_storage_unittest.cc16
-rw-r--r--chromium/content/browser/appcache/appcache_unittest.cc126
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc1636
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.h346
-rw-r--r--chromium/content/browser/appcache/appcache_update_job_unittest.cc117
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.cc449
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.h175
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job_unittest.cc74
-rw-r--r--chromium/content/browser/appcache/appcache_working_set.cc80
-rw-r--r--chromium/content/browser/appcache/appcache_working_set.h76
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service.cc11
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service.h24
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service_unittest.cc20
-rw-r--r--chromium/content/browser/appcache/manifest_parser_unittest.cc524
-rw-r--r--chromium/content/browser/appcache/mock_appcache_policy.h12
-rw-r--r--chromium/content/browser/appcache/mock_appcache_service.h12
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.cc17
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.h81
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage_unittest.cc69
-rw-r--r--chromium/content/browser/appcache/view_appcache_internals_job.cc111
-rw-r--r--chromium/content/browser/appcache/view_appcache_internals_job.h9
-rw-r--r--chromium/content/browser/battery_status/OWNERS1
-rw-r--r--chromium/content/browser/battery_status/battery_status_browsertest.cc76
-rw-r--r--chromium/content/browser/battery_status/battery_status_manager.h57
-rw-r--r--chromium/content/browser/battery_status/battery_status_manager_android.cc56
-rw-r--r--chromium/content/browser/battery_status/battery_status_manager_default.cc31
-rw-r--r--chromium/content/browser/battery_status/battery_status_message_filter.cc56
-rw-r--r--chromium/content/browser/battery_status/battery_status_message_filter.h4
-rw-r--r--chromium/content/browser/battery_status/battery_status_service.cc106
-rw-r--r--chromium/content/browser/battery_status/battery_status_service.h66
-rw-r--r--chromium/content/browser/battery_status/battery_status_service_unittest.cc193
-rw-r--r--chromium/content/browser/bootstrap_sandbox_mac.cc78
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc59
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h52
-rw-r--r--chromium/content/browser/browser_context.cc55
-rw-r--r--chromium/content/browser/browser_main_loop.cc195
-rw-r--r--chromium/content/browser/browser_main_loop.h29
-rw-r--r--chromium/content/browser/browser_main_runner.cc156
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.cc114
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.h37
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc599
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h178
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc57
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_message_filter.h13
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h11
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.mm5
-rw-r--r--chromium/content/browser/browser_process_sub_thread.h6
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.cc30
-rw-r--r--chromium/content/browser/browser_shutdown_profile_dumper.h14
-rw-r--r--chromium/content/browser/browser_thread_impl.cc21
-rw-r--r--chromium/content/browser/browser_thread_impl.h10
-rw-r--r--chromium/content/browser/browser_thread_unittest.cc4
-rw-r--r--chromium/content/browser/browser_url_handler_impl.cc21
-rw-r--r--chromium/content/browser/browser_url_handler_impl.h12
-rw-r--r--chromium/content/browser/browser_url_handler_impl_unittest.cc15
-rw-r--r--chromium/content/browser/byte_stream.cc22
-rw-r--r--chromium/content/browser/cert_store_impl.h10
-rw-r--r--chromium/content/browser/child_process_launcher.cc177
-rw-r--r--chromium/content/browser/child_process_launcher.h5
-rw-r--r--chromium/content/browser/child_process_launcher_browsertest.cc25
-rw-r--r--chromium/content/browser/child_process_security_policy_browsertest.cc4
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc57
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.h110
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc66
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.h56
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.mm77
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map.h66
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map.mm165
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map_unittest.mm196
-rw-r--r--chromium/content/browser/compositor/OWNERS3
-rw-r--r--chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.h136
-rw-r--r--chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.mm406
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.cc22
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h11
-rw-r--r--chromium/content/browser/compositor/browser_compositor_view_mac.h121
-rw-r--r--chromium/content/browser/compositor/browser_compositor_view_mac.mm296
-rw-r--r--chromium/content/browser/compositor/buffer_queue.cc176
-rw-r--r--chromium/content/browser/compositor/buffer_queue.h90
-rw-r--r--chromium/content/browser/compositor/buffer_queue_unittest.cc288
-rw-r--r--chromium/content/browser/compositor/delegated_frame_host.cc331
-rw-r--r--chromium/content/browser/compositor/delegated_frame_host.h80
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc73
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h19
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc194
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h53
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc100
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h44
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.cc8
-rw-r--r--chromium/content/browser/compositor/image_transport_factory.h9
-rw-r--r--chromium/content/browser/compositor/image_transport_factory_browsertest.cc10
-rw-r--r--chromium/content/browser/compositor/io_surface_context_mac.h72
-rw-r--r--chromium/content/browser/compositor/io_surface_context_mac.mm121
-rw-r--r--chromium/content/browser/compositor/io_surface_layer_mac.h161
-rw-r--r--chromium/content/browser/compositor/io_surface_layer_mac.mm302
-rw-r--r--chromium/content/browser/compositor/io_surface_texture_mac.h121
-rw-r--r--chromium/content/browser/compositor/io_surface_texture_mac.mm297
-rw-r--r--chromium/content/browser/compositor/no_transport_image_transport_factory.cc53
-rw-r--r--chromium/content/browser/compositor/no_transport_image_transport_factory.h46
-rw-r--r--chromium/content/browser/compositor/onscreen_display_client.cc87
-rw-r--r--chromium/content/browser/compositor/onscreen_display_client.h42
-rw-r--r--chromium/content/browser/compositor/overlay_candidate_validator_ozone.cc1
-rw-r--r--chromium/content/browser/compositor/overlay_candidate_validator_ozone.h2
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.h4
-rw-r--r--chromium/content/browser/compositor/reflector_impl.cc6
-rw-r--r--chromium/content/browser/compositor/reflector_impl.h4
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.cc10
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface.h8
-rw-r--r--chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc25
-rw-r--r--chromium/content/browser/compositor/software_layer_mac.h (renamed from chromium/content/browser/renderer_host/software_layer_mac.h)0
-rw-r--r--chromium/content/browser/compositor/software_layer_mac.mm68
-rw-r--r--chromium/content/browser/compositor/software_output_device_mac.h4
-rw-r--r--chromium/content/browser/compositor/software_output_device_mac.mm9
-rw-r--r--chromium/content/browser/compositor/software_output_device_ozone.cc3
-rw-r--r--chromium/content/browser/compositor/software_output_device_ozone.h6
-rw-r--r--chromium/content/browser/compositor/software_output_device_ozone_unittest.cc33
-rw-r--r--chromium/content/browser/compositor/software_output_device_win.h8
-rw-r--r--chromium/content/browser/compositor/software_output_device_x11.h4
-rw-r--r--chromium/content/browser/compositor/surface_display_output_surface.cc65
-rw-r--r--chromium/content/browser/compositor/surface_display_output_surface.h32
-rw-r--r--chromium/content/browser/cross_site_request_manager.cc42
-rw-r--r--chromium/content/browser/cross_site_request_manager.h64
-rw-r--r--chromium/content/browser/cross_site_transfer_browsertest.cc30
-rw-r--r--chromium/content/browser/database_browsertest.cc1
-rw-r--r--chromium/content/browser/database_quota_client_unittest.cc75
-rw-r--r--chromium/content/browser/database_tracker_unittest.cc106
-rw-r--r--chromium/content/browser/database_util_unittest.cc10
-rw-r--r--chromium/content/browser/databases_table_unittest.cc6
-rw-r--r--chromium/content/browser/device_monitor_mac.mm224
-rw-r--r--chromium/content/browser/device_monitor_udev.h4
-rw-r--r--chromium/content/browser/device_sensors/OWNERS1
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory.h14
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc7
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc17
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.h4
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc142
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc18
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc18
-rw-r--r--chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc109
-rw-r--r--chromium/content/browser/device_sensors/device_inertial_sensor_service.cc16
-rw-r--r--chromium/content/browser/device_sensors/device_inertial_sensor_service.h1
-rw-r--r--chromium/content/browser/device_sensors/device_light_message_filter.cc60
-rw-r--r--chromium/content/browser/device_sensors/device_light_message_filter.h33
-rw-r--r--chromium/content/browser/device_sensors/device_motion_message_filter.h4
-rw-r--r--chromium/content/browser/device_sensors/device_orientation_message_filter.h4
-rw-r--r--chromium/content/browser/device_sensors/inertial_sensor_consts.h19
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android.cc95
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android.h28
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc30
-rw-r--r--chromium/content/browser/devtools/BUILD.gn74
-rw-r--r--chromium/content/browser/devtools/OWNERS2
-rw-r--r--chromium/content/browser/devtools/browser_protocol.json34
-rw-r--r--chromium/content/browser/devtools/devtools.gyp44
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc138
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h51
-rw-r--r--chromium/content/browser/devtools/devtools_browser_target.cc180
-rw-r--r--chromium/content/browser/devtools/devtools_browser_target.h75
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host.cc96
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host.h51
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host_impl.cc56
-rw-r--r--chromium/content/browser/devtools/devtools_frontend_host_impl.h33
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_impl.cc396
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_impl.h53
-rw-r--r--chromium/content/browser/devtools/devtools_http_handler_unittest.cc125
-rw-r--r--chromium/content/browser/devtools/devtools_manager.cc130
-rw-r--r--chromium/content/browser/devtools/devtools_manager.h80
-rw-r--r--chromium/content/browser/devtools/devtools_manager_impl.cc202
-rw-r--r--chromium/content/browser/devtools/devtools_manager_impl.h113
-rw-r--r--chromium/content/browser/devtools/devtools_manager_unittest.cc338
-rw-r--r--chromium/content/browser/devtools/devtools_netlog_observer.h4
-rw-r--r--chromium/content/browser/devtools/devtools_power_handler.cc83
-rw-r--r--chromium/content/browser/devtools/devtools_power_handler.h38
-rw-r--r--chromium/content/browser/devtools/devtools_protocol.cc7
-rw-r--r--chromium/content/browser/devtools/devtools_protocol.h10
-rw-r--r--chromium/content/browser/devtools/devtools_system_info_handler.cc30
-rw-r--r--chromium/content/browser/devtools/devtools_system_info_handler.h2
-rw-r--r--chromium/content/browser/devtools/devtools_tracing_handler.cc248
-rw-r--r--chromium/content/browser/devtools/devtools_tracing_handler.h63
-rw-r--r--chromium/content/browser/devtools/embedded_worker_devtools_agent_host.cc232
-rw-r--r--chromium/content/browser/devtools/embedded_worker_devtools_agent_host.h84
-rw-r--r--chromium/content/browser/devtools/embedded_worker_devtools_manager.cc348
-rw-r--r--chromium/content/browser/devtools/embedded_worker_devtools_manager.h81
-rw-r--r--chromium/content/browser/devtools/embedded_worker_devtools_manager_unittest.cc178
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.cc29
-rw-r--r--chromium/content/browser/devtools/forwarding_agent_host.h19
-rw-r--r--chromium/content/browser/devtools/ipc_devtools_agent_host.cc31
-rw-r--r--chromium/content/browser/devtools/ipc_devtools_agent_host.h17
-rw-r--r--chromium/content/browser/devtools/protocol/color_picker.cc265
-rw-r--r--chromium/content/browser/devtools/protocol/color_picker.h57
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_client.cc97
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_client.h75
-rwxr-xr-xchromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py776
-rw-r--r--chromium/content/browser/devtools/protocol/dom_handler.cc47
-rw-r--r--chromium/content/browser/devtools/protocol/dom_handler.h38
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc111
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.h46
-rw-r--r--chromium/content/browser/devtools/protocol/inspector_handler.cc23
-rw-r--r--chromium/content/browser/devtools/protocol/inspector_handler.h31
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc52
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.h45
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc615
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h135
-rw-r--r--chromium/content/browser/devtools/protocol/power_handler.cc86
-rw-r--r--chromium/content/browser/devtools/protocol/power_handler.h45
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc215
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h77
-rw-r--r--chromium/content/browser/devtools/protocol/usage_and_quota_query.cc136
-rw-r--r--chromium/content/browser/devtools/protocol/usage_and_quota_query.h55
-rw-r--r--chromium/content/browser/devtools/protocol/worker_handler.cc30
-rw-r--r--chromium/content/browser/devtools/protocol/worker_handler.h35
-rw-r--r--chromium/content/browser/devtools/render_view_devtools_agent_host.cc275
-rw-r--r--chromium/content/browser/devtools/render_view_devtools_agent_host.h89
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler.cc1007
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler.h119
-rw-r--r--chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc102
-rw-r--r--chromium/content/browser/devtools/tethering_handler.cc263
-rw-r--r--chromium/content/browser/devtools/tethering_handler.h26
-rw-r--r--chromium/content/browser/devtools/worker_devtools_manager.cc453
-rw-r--r--chromium/content/browser/devtools/worker_devtools_manager.h110
-rw-r--r--chromium/content/browser/devtools/worker_devtools_message_filter.cc49
-rw-r--r--chromium/content/browser/devtools/worker_devtools_message_filter.h34
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area.cc12
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_area_unittest.cc6
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_browsertest.cc1
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.cc12
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl.h13
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc8
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h30
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_database_unittest.cc11
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_message_filter.h39
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc24
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_task_runner.h40
-rw-r--r--chromium/content/browser/dom_storage/local_storage_database_adapter.cc2
-rw-r--r--chromium/content/browser/dom_storage/local_storage_database_adapter.h12
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc2
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database_adapter.h9
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database_unittest.cc6
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.cc5
-rw-r--r--chromium/content/browser/dom_storage/session_storage_namespace_impl.h26
-rw-r--r--chromium/content/browser/download/base_file.cc22
-rw-r--r--chromium/content/browser/download/base_file.h14
-rw-r--r--chromium/content/browser/download/base_file_posix.cc4
-rw-r--r--chromium/content/browser/download/base_file_unittest.cc72
-rw-r--r--chromium/content/browser/download/base_file_win.cc43
-rw-r--r--chromium/content/browser/download/download_browsertest.cc131
-rw-r--r--chromium/content/browser/download/download_create_info.cc4
-rw-r--r--chromium/content/browser/download/download_create_info.h6
-rw-r--r--chromium/content/browser/download/download_file_impl.cc131
-rw-r--r--chromium/content/browser/download/download_file_impl.h59
-rw-r--r--chromium/content/browser/download/download_file_unittest.cc344
-rw-r--r--chromium/content/browser/download/download_interrupt_reasons_impl.cc29
-rw-r--r--chromium/content/browser/download/download_interrupt_reasons_impl.h5
-rw-r--r--chromium/content/browser/download/download_item_impl.cc15
-rw-r--r--chromium/content/browser/download/download_item_impl.h150
-rw-r--r--chromium/content/browser/download/download_item_impl_unittest.cc28
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc23
-rw-r--r--chromium/content/browser/download/download_manager_impl.h70
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc31
-rw-r--r--chromium/content/browser/download/download_net_log_parameters.cc5
-rw-r--r--chromium/content/browser/download/download_request_handle.h14
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc14
-rw-r--r--chromium/content/browser/download/download_resource_handler.h34
-rw-r--r--chromium/content/browser/download/download_stats.cc12
-rw-r--r--chromium/content/browser/download/download_stats.h5
-rw-r--r--chromium/content/browser/download/drag_download_file.cc6
-rw-r--r--chromium/content/browser/download/drag_download_file.h8
-rw-r--r--chromium/content/browser/download/drag_download_file_browsertest.cc23
-rw-r--r--chromium/content/browser/download/drag_download_util.h6
-rw-r--r--chromium/content/browser/download/file_metadata_linux.cc2
-rw-r--r--chromium/content/browser/download/file_metadata_unittest_linux.cc4
-rw-r--r--chromium/content/browser/download/mhtml_generation_browsertest.cc4
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc13
-rw-r--r--chromium/content/browser/download/save_file_manager.cc2
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.cc5
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.h33
-rw-r--r--chromium/content/browser/download/save_package.cc30
-rw-r--r--chromium/content/browser/download/save_package.h7
-rw-r--r--chromium/content/browser/download/save_package_browsertest.cc2
-rw-r--r--chromium/content/browser/download/save_package_unittest.cc36
-rw-r--r--chromium/content/browser/file_descriptor_info_impl.cc69
-rw-r--r--chromium/content/browser/file_descriptor_info_impl.h39
-rw-r--r--chromium/content/browser/file_descriptor_info_impl_unittest.cc86
-rw-r--r--chromium/content/browser/fileapi/OWNERS3
-rw-r--r--chromium/content/browser/fileapi/blob_storage_context_unittest.cc6
-rw-r--r--chromium/content/browser/fileapi/blob_storage_host.cc8
-rw-r--r--chromium/content/browser/fileapi/blob_storage_host.h8
-rw-r--r--chromium/content/browser/fileapi/blob_url_request_job_unittest.cc52
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.cc46
-rw-r--r--chromium/content/browser/fileapi/browser_file_system_helper.h21
-rw-r--r--chromium/content/browser/fileapi/chrome_blob_storage_context.cc25
-rw-r--r--chromium/content/browser/fileapi/chrome_blob_storage_context.h8
-rw-r--r--chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc64
-rw-r--r--chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc134
-rw-r--r--chromium/content/browser/fileapi/dragged_file_util_unittest.cc54
-rw-r--r--chromium/content/browser/fileapi/external_mount_points_unittest.cc284
-rw-r--r--chromium/content/browser/fileapi/file_system_browsertest.cc8
-rw-r--r--chromium/content/browser/fileapi/file_system_context_unittest.cc171
-rw-r--r--chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc80
-rw-r--r--chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc37
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc800
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc48
-rw-r--r--chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc21
-rw-r--r--chromium/content/browser/fileapi/file_system_quota_client_unittest.cc152
-rw-r--r--chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc83
-rw-r--r--chromium/content/browser/fileapi/file_system_url_unittest.cc18
-rw-r--r--chromium/content/browser/fileapi/file_system_usage_cache_unittest.cc10
-rw-r--r--chromium/content/browser/fileapi/file_writer_delegate_unittest.cc76
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.cc112
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h82
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc24
-rw-r--r--chromium/content/browser/fileapi/isolated_context_unittest.cc53
-rw-r--r--chromium/content/browser/fileapi/local_file_stream_reader_unittest.cc10
-rw-r--r--chromium/content/browser/fileapi/local_file_stream_writer_unittest.cc12
-rw-r--r--chromium/content/browser/fileapi/local_file_util_unittest.cc32
-rw-r--r--chromium/content/browser/fileapi/mock_file_change_observer.cc4
-rw-r--r--chromium/content/browser/fileapi/mock_file_change_observer.h26
-rw-r--r--chromium/content/browser/fileapi/mock_file_update_observer.cc42
-rw-r--r--chromium/content/browser/fileapi/mock_file_update_observer.h50
-rw-r--r--chromium/content/browser/fileapi/mock_url_request_delegate.h7
-rw-r--r--chromium/content/browser/fileapi/native_file_util_unittest.cc14
-rw-r--r--chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc257
-rw-r--r--chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc203
-rw-r--r--chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc53
-rw-r--r--chromium/content/browser/fileapi/sandbox_database_test_helper.cc6
-rw-r--r--chromium/content/browser/fileapi/sandbox_directory_database_unittest.cc10
-rw-r--r--chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc25
-rw-r--r--chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc136
-rw-r--r--chromium/content/browser/fileapi/sandbox_isolated_origin_database_unittest.cc8
-rw-r--r--chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc8
-rw-r--r--chromium/content/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc12
-rw-r--r--chromium/content/browser/fileapi/timed_task_helper_unittest.cc4
-rw-r--r--chromium/content/browser/fileapi/transient_file_util_unittest.cc50
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader.cc22
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader.h24
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc30
-rw-r--r--chromium/content/browser/frame_host/OWNERS1
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc27
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h11
-rw-r--r--chromium/content/browser/frame_host/cross_site_transferring_request.h2
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc38
-rw-r--r--chromium/content/browser/frame_host/debug_urls.h9
-rw-r--r--chromium/content/browser/frame_host/frame_accessibility.cc179
-rw-r--r--chromium/content/browser/frame_host/frame_accessibility.h79
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc173
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h44
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc122
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc13
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h4
-rw-r--r--chromium/content/browser/frame_host/frame_tree_unittest.cc68
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc116
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h156
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_navigator_impl.h11
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc252
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h39
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_delegate.h3
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc152
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h117
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc460
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc8
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h112
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc15
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc33
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h6
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc67
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h74
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.cc18
-rw-r--r--chromium/content/browser/frame_host/navigation_request_info.h40
-rw-r--r--chromium/content/browser/frame_host/navigator.cc6
-rw-r--r--chromium/content/browser/frame_host/navigator.h58
-rw-r--r--chromium/content/browser/frame_host/navigator_delegate.h19
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc542
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h124
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc480
-rw-r--r--chromium/content/browser/frame_host/popup_menu_helper_mac.h67
-rw-r--r--chromium/content/browser/frame_host/popup_menu_helper_mac.mm128
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc45
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h52
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc1126
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h405
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc1124
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h304
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc79
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc1232
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h4
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc101
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.h25
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc71
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.h173
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc6
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc223
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h168
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc9
-rw-r--r--chromium/content/browser/gamepad/canonical_axis_index_list.h16
-rw-r--r--chromium/content/browser/gamepad/canonical_button_index_list.h28
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h2
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h4
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc46
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h6
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h16
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h4
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.cc17
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.h4
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider_unittest.cc14
-rw-r--r--chromium/content/browser/gamepad/gamepad_service.cc21
-rw-r--r--chromium/content/browser/gamepad/gamepad_service.h3
-rw-r--r--chromium/content/browser/gamepad/gamepad_service_unittest.cc130
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings.cc20
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings.h53
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc322
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm381
-rw-r--r--chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc168
-rw-r--r--chromium/content/browser/gamepad/gamepad_test_helpers.cc9
-rw-r--r--chromium/content/browser/gamepad/gamepad_test_helpers.h13
-rw-r--r--chromium/content/browser/gamepad/raw_input_data_fetcher_win.h2
-rw-r--r--chromium/content/browser/gamepad/xbox_data_fetcher_mac.h6
-rw-r--r--chromium/content/browser/geofencing/OWNERS1
-rw-r--r--chromium/content/browser/geofencing/geofencing_dispatcher_host.cc111
-rw-r--r--chromium/content/browser/geofencing/geofencing_dispatcher_host.h58
-rw-r--r--chromium/content/browser/geofencing/geofencing_manager.cc371
-rw-r--r--chromium/content/browser/geofencing/geofencing_manager.h179
-rw-r--r--chromium/content/browser/geofencing/geofencing_manager_unittest.cc414
-rw-r--r--chromium/content/browser/geofencing/geofencing_provider.h44
-rw-r--r--chromium/content/browser/geofencing/geofencing_registration_delegate.h31
-rw-r--r--chromium/content/browser/geofencing/geofencing_service.cc199
-rw-r--r--chromium/content/browser/geofencing/geofencing_service.h105
-rw-r--r--chromium/content/browser/geofencing/geofencing_service_unittest.cc193
-rw-r--r--chromium/content/browser/geolocation/OWNERS1
-rw-r--r--chromium/content/browser/geolocation/empty_wifi_data_provider.cc4
-rw-r--r--chromium/content/browser/geolocation/empty_wifi_data_provider.h12
-rw-r--r--chromium/content/browser/geolocation/geolocation_dispatcher_host.cc193
-rw-r--r--chromium/content/browser/geolocation/geolocation_dispatcher_host.h59
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.h18
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc258
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_unittest.cc258
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_context.cc63
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_context.h58
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.cc155
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.h64
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.cc15
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.h20
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc17
-rw-r--r--chromium/content/browser/geolocation/location_provider_android.h10
-rw-r--r--chromium/content/browser/geolocation/location_provider_base.h8
-rw-r--r--chromium/content/browser/geolocation/mock_location_arbitrator.h9
-rw-r--r--chromium/content/browser/geolocation/mock_location_provider.cc4
-rw-r--r--chromium/content/browser/geolocation/mock_location_provider.h10
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.cc35
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.h32
-rw-r--r--chromium/content/browser/geolocation/network_location_provider_unittest.cc62
-rw-r--r--chromium/content/browser/geolocation/network_location_request.cc19
-rw-r--r--chromium/content/browser/geolocation/network_location_request.h10
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider.cc124
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider.h98
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc3
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos.h11
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc6
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common.h12
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc42
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm4
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_linux.cc7
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_linux.h6
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_mac.cc21
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_mac.h12
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_manager.cc98
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_manager.h98
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_unittest_win.cc23
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win.cc19
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win.h8
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc23
-rw-r--r--chromium/content/browser/gpu/OWNERS1
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc224
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.h71
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc250
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h77
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc145
-rw-r--r--chromium/content/browser/gpu/compositor_util.h13
-rw-r--r--chromium/content/browser/gpu/compositor_util_browsertest.cc32
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc10
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h55
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc207
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h13
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc52
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc67
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc10
-rw-r--r--chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.cc94
-rw-r--r--chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.h55
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc414
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h67
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.cc145
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.h17
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.h4
-rw-r--r--chromium/content/browser/gpu/shader_disk_cache.cc34
-rw-r--r--chromium/content/browser/gpu/shader_disk_cache_unittest.cc4
-rw-r--r--chromium/content/browser/gpu/test_support_gpu.gypi2
-rw-r--r--chromium/content/browser/histogram_internals_request_job.cc10
-rw-r--r--chromium/content/browser/histogram_internals_request_job.h10
-rw-r--r--chromium/content/browser/histogram_message_filter.cc2
-rw-r--r--chromium/content/browser/histogram_message_filter.h4
-rw-r--r--chromium/content/browser/histogram_synchronizer.h12
-rw-r--r--chromium/content/browser/host_zoom_map_impl.cc52
-rw-r--r--chromium/content/browser/host_zoom_map_impl.h58
-rw-r--r--chromium/content/browser/indexed_db/OWNERS1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db.h13
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_active_blob_registry.h21
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc55
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc607
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h535
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc196
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_blob_info.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_blob_info.h8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc87
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc135
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.h7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_class_factory.cc6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_class_factory.h8
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc156
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.cc10
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_connection.h6
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc118
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h59
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_cursor.h5
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc182
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h48
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_unittest.cc62
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc92
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h98
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.cc479
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory.h119
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc503
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.h136
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc59
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h203
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_index_writer.cc9
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc43
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.h2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc14
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h50
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc13
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.h11
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.cc48
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.h45
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc55
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.cc52
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction.h35
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc34
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc58
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc62
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc131
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h15
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_factory.h33
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_iterator.h3
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc72
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h42
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc27
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h41
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc10
-rw-r--r--chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.cc14
-rw-r--r--chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h29
-rw-r--r--chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc124
-rw-r--r--chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h9
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h14
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h12
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.cc20
-rw-r--r--chromium/content/browser/indexed_db/mock_indexed_db_factory.h85
-rw-r--r--chromium/content/browser/loader/OWNERS1
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc29
-rw-r--r--chromium/content/browser/loader/async_resource_handler.h38
-rw-r--r--chromium/content/browser/loader/buffered_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/buffered_resource_handler.h29
-rw-r--r--chromium/content/browser/loader/certificate_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/certificate_resource_handler.h35
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.cc203
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.h55
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc19
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.h43
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.cc9
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.h36
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.cc149
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.h60
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.cc37
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h62
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_delegate.h52
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_factory.h36
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc76
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h66
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.cc104
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h75
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc389
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.h8
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc15
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h32
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc39
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc616
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h105
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc367
-rw-r--r--chromium/content/browser/loader/resource_handler.h3
-rw-r--r--chromium/content/browser/loader/resource_loader.cc79
-rw-r--r--chromium/content/browser/loader/resource_loader.h52
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc101
-rw-r--r--chromium/content/browser/loader/resource_message_filter.cc4
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h34
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc49
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h72
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc607
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h113
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.cc14
-rw-r--r--chromium/content/browser/loader/resource_scheduler_filter.h4
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc1781
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.cc64
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.h48
-rw-r--r--chromium/content/browser/loader/stream_writer.cc82
-rw-r--r--chromium/content/browser/loader/stream_writer.h83
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.cc10
-rw-r--r--chromium/content/browser/loader/sync_resource_handler.h33
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.cc6
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.h12
-rw-r--r--chromium/content/browser/loader/temporary_file_stream_unittest.cc6
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.cc21
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.h25
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc36
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.h16
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder_unittest.cc91
-rw-r--r--chromium/content/browser/mach_broker_mac.h25
-rw-r--r--chromium/content/browser/mach_broker_mac.mm25
-rw-r--r--chromium/content/browser/manifest/OWNERS1
-rw-r--r--chromium/content/browser/manifest/manifest_browsertest.cc202
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.cc138
-rw-r--r--chromium/content/browser/manifest/manifest_manager_host.h54
-rw-r--r--chromium/content/browser/media/OWNERS8
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.cc6
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.h4
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc101
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h48
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc184
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.h38
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.cc162
-rw-r--r--chromium/content/browser/media/audio_stream_monitor.h153
-rw-r--r--chromium/content/browser/media/audio_stream_monitor_unittest.cc297
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.cc290
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.h144
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc525
-rw-r--r--chromium/content/browser/media/capture/content_video_capture_device_core.cc41
-rw-r--r--chromium/content/browser/media/capture/content_video_capture_device_core.h21
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc220
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.h19
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.cc100
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.h8
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc8
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_uma_types.h2
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc61
-rw-r--r--chromium/content/browser/media/capture/video_capture_oracle.cc376
-rw-r--r--chromium/content/browser/media/capture/video_capture_oracle.h193
-rw-r--r--chromium/content/browser/media/capture/video_capture_oracle_unittest.cc872
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc154
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.h36
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc101
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.cc152
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.h43
-rw-r--r--chromium/content/browser/media/capture/web_contents_capture_util.cc30
-rw-r--r--chromium/content/browser/media/capture/web_contents_capture_util.h11
-rw-r--r--chromium/content/browser/media/capture/web_contents_tracker.cc130
-rw-r--r--chromium/content/browser/media/capture/web_contents_tracker.h105
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc341
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.h36
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc151
-rw-r--r--chromium/content/browser/media/cdm/browser_cdm_manager.cc305
-rw-r--r--chromium/content/browser/media/cdm/browser_cdm_manager.h114
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc77
-rw-r--r--chromium/content/browser/media/media_browsertest.cc122
-rw-r--r--chromium/content/browser/media/media_browsertest.h19
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc1141
-rw-r--r--chromium/content/browser/media/media_internals.cc103
-rw-r--r--chromium/content/browser/media/media_internals.h48
-rw-r--r--chromium/content/browser/media/media_internals_handler.h4
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc3
-rw-r--r--chromium/content/browser/media/media_internals_proxy.h10
-rw-r--r--chromium/content/browser/media/media_internals_ui.cc2
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc223
-rw-r--r--chromium/content/browser/media/media_source_browsertest.cc20
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc83
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h29
-rw-r--r--chromium/content/browser/media/midi_dispatcher_host.cc43
-rw-r--r--chromium/content/browser/media/midi_dispatcher_host.h12
-rw-r--r--chromium/content/browser/media/midi_host.cc46
-rw-r--r--chromium/content/browser/media/midi_host.h32
-rw-r--r--chromium/content/browser/media/webrtc_aecdump_browsertest.cc233
-rw-r--r--chromium/content/browser/media/webrtc_browsertest.cc318
-rw-r--r--chromium/content/browser/media/webrtc_getusermedia_browsertest.cc125
-rw-r--r--chromium/content/browser/media/webrtc_identity_store.cc2
-rw-r--r--chromium/content/browser/media/webrtc_identity_store.h6
-rw-r--r--chromium/content/browser/media/webrtc_identity_store_backend.cc15
-rw-r--r--chromium/content/browser/media/webrtc_identity_store_backend.h6
-rw-r--r--chromium/content/browser/media/webrtc_identity_store_unittest.cc14
-rw-r--r--chromium/content/browser/media/webrtc_internals.cc41
-rw-r--r--chromium/content/browser/media/webrtc_internals.h50
-rw-r--r--chromium/content/browser/media/webrtc_internals_browsertest.cc33
-rw-r--r--chromium/content/browser/media/webrtc_internals_message_handler.h7
-rw-r--r--chromium/content/browser/media/webrtc_internals_ui.cc2
-rw-r--r--chromium/content/browser/media/webrtc_internals_unittest.cc28
-rw-r--r--chromium/content/browser/media/webrtc_webcam_browsertest.cc102
-rw-r--r--chromium/content/browser/message_port_message_filter.h8
-rw-r--r--chromium/content/browser/mime_registry_message_filter.h9
-rw-r--r--chromium/content/browser/mojo/mojo_application_host.cc22
-rw-r--r--chromium/content/browser/mojo/mojo_application_host.h49
-rw-r--r--chromium/content/browser/mojo/service_registry_android.cc97
-rw-r--r--chromium/content/browser/mojo/service_registry_android.h53
-rw-r--r--chromium/content/browser/net/browser_online_state_observer.h6
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store.cc45
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store.h22
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc4
-rw-r--r--chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc16
-rw-r--r--chromium/content/browser/net/view_blob_internals_job_factory.cc6
-rw-r--r--chromium/content/browser/net/view_blob_internals_job_factory.h9
-rw-r--r--chromium/content/browser/net/view_http_cache_job_factory.cc20
-rw-r--r--chromium/content/browser/net_info_browsertest.cc80
-rw-r--r--chromium/content/browser/notification_service_impl.h8
-rw-r--r--chromium/content/browser/notification_service_impl_unittest.cc6
-rw-r--r--chromium/content/browser/notifications/OWNERS1
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.cc89
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.h58
-rw-r--r--chromium/content/browser/notifications/page_notification_delegate.cc48
-rw-r--r--chromium/content/browser/notifications/page_notification_delegate.h32
-rw-r--r--chromium/content/browser/pepper_flash_settings_helper_impl.h19
-rw-r--r--chromium/content/browser/plugin_browsertest.cc63
-rw-r--r--chromium/content/browser/plugin_content_origin_whitelist.cc61
-rw-r--r--chromium/content/browser/plugin_content_origin_whitelist.h51
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc37
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.h4
-rw-r--r--chromium/content/browser/plugin_data_remover_impl_browsertest.cc2
-rw-r--r--chromium/content/browser/plugin_loader_posix.cc12
-rw-r--r--chromium/content/browser/plugin_loader_posix.h8
-rw-r--r--chromium/content/browser/plugin_loader_posix_unittest.cc4
-rw-r--r--chromium/content/browser/plugin_process_host.cc74
-rw-r--r--chromium/content/browser/plugin_process_host.h28
-rw-r--r--chromium/content/browser/plugin_process_host_mac.cc8
-rw-r--r--chromium/content/browser/plugin_service_impl.cc66
-rw-r--r--chromium/content/browser/plugin_service_impl.h100
-rw-r--r--chromium/content/browser/plugin_service_impl_browsertest.cc82
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster.cc7
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster.h10
-rw-r--r--chromium/content/browser/power_monitor_message_broadcaster_unittest.cc18
-rw-r--r--chromium/content/browser/power_profiler/power_data_provider.h9
-rw-r--r--chromium/content/browser/power_profiler/power_data_provider_ia_win.h5
-rw-r--r--chromium/content/browser/power_profiler/power_profiler_service.cc15
-rw-r--r--chromium/content/browser/power_profiler/power_profiler_service.h3
-rw-r--r--chromium/content/browser/power_profiler/power_profiler_service_unittest.cc14
-rw-r--r--chromium/content/browser/power_save_blocker_android.cc2
-rw-r--r--chromium/content/browser/power_save_blocker_impl.h2
-rw-r--r--chromium/content/browser/power_save_blocker_win.cc4
-rw-r--r--chromium/content/browser/power_save_blocker_x11.cc4
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc32
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.h18
-rw-r--r--chromium/content/browser/profiler_controller_impl.h8
-rw-r--r--chromium/content/browser/profiler_message_filter.h6
-rw-r--r--chromium/content/browser/push_messaging/OWNERS2
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_message_filter.cc183
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_message_filter.h76
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc104
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.h68
-rw-r--r--chromium/content/browser/push_messaging_message_filter.cc97
-rw-r--r--chromium/content/browser/push_messaging_message_filter.h54
-rw-r--r--chromium/content/browser/quota/mock_quota_manager.cc19
-rw-r--r--chromium/content/browser/quota/mock_quota_manager.h59
-rw-r--r--chromium/content/browser/quota/mock_quota_manager_proxy.cc2
-rw-r--r--chromium/content/browser/quota/mock_quota_manager_proxy.h42
-rw-r--r--chromium/content/browser/quota/mock_quota_manager_unittest.cc14
-rw-r--r--chromium/content/browser/quota/quota_backend_impl_unittest.cc74
-rw-r--r--chromium/content/browser/quota/quota_database_unittest.cc24
-rw-r--r--chromium/content/browser/quota/quota_manager_unittest.cc158
-rw-r--r--chromium/content/browser/quota/quota_reservation_manager_unittest.cc60
-rw-r--r--chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc40
-rw-r--r--chromium/content/browser/quota/storage_monitor_unittest.cc56
-rw-r--r--chromium/content/browser/quota/usage_tracker_unittest.cc52
-rw-r--r--chromium/content/browser/quota_dispatcher_host.cc40
-rw-r--r--chromium/content/browser/quota_dispatcher_host.h19
-rw-r--r--chromium/content/browser/renderer_host/DEPS2
-rw-r--r--chromium/content/browser/renderer_host/OWNERS7
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.h10
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h88
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm170
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.h71
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm234
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_mac.h331
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_mac.mm970
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc448
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h81
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc300
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.h123
-rw-r--r--chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc533
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc251
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h86
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock_aura.cc4
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock_aura.h11
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.cc34
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.h42
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_evictor.h4
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_host/file_utilities_message_filter.h10
-rw-r--r--chromium/content/browser/renderer_host/font_utils_linux.cc260
-rw-r--r--chromium/content/browser/renderer_host/font_utils_linux.h20
-rw-r--r--chromium/content/browser/renderer_host/gamepad_browser_message_filter.h14
-rw-r--r--chromium/content/browser/renderer_host/gpu_message_filter.cc1
-rw-r--r--chromium/content/browser/renderer_host/gpu_message_filter.h8
-rw-r--r--chromium/content/browser/renderer_host/image_transport_factory_android.cc24
-rw-r--r--chromium/content/browser/renderer_host/image_transport_factory_android.h9
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.cc46
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.h5
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc26
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_text_selector.cc115
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_text_selector.h72
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_text_selector_unittest.cc223
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h2
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_config_helper.cc31
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc61
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h72
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc48
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc261
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_ack_handler.h20
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h18
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_android.cc304
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_android.h132
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_android_unittest.cc174
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web.cc73
-rw-r--r--chromium/content/browser/renderer_host/input/motion_event_web.h45
-rw-r--r--chromium/content/browser/renderer_host/input/selection_event_type.h29
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc143
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h12
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h20
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h17
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h6
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc9
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h6
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h6
-rw-r--r--chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc27
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc20
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc98
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h29
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_client.h3
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc199
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.cc332
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.h58
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc515
-rw-r--r--chromium/content/browser/renderer_host/input/touch_handle.cc267
-rw-r--r--chromium/content/browser/renderer_host/input/touch_handle.h135
-rw-r--r--chromium/content/browser/renderer_host/input/touch_handle_unittest.cc491
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc30
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller.cc423
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller.h150
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_unittest.cc810
-rw-r--r--chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h6
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h6
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.cc105
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.h4
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc61
-rw-r--r--chromium/content/browser/renderer_host/java/DEPS4
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_bound_object.cc192
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_bound_object.h96
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.cc43
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.h38
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc341
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.h116
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc285
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc705
-rw-r--r--chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h33
-rw-r--r--chromium/content/browser/renderer_host/java/java_bound_object.cc1040
-rw-r--r--chromium/content/browser/renderer_host/java/java_bound_object.h96
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_channel_host.cc95
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_channel_host.h52
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc167
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h71
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc162
-rw-r--r--chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h76
-rw-r--r--chromium/content/browser/renderer_host/java/java_method.cc242
-rw-r--r--chromium/content/browser/renderer_host/java/java_method.h49
-rw-r--r--chromium/content/browser/renderer_host/java/java_type.cc114
-rw-r--r--chromium/content/browser/renderer_host/java/java_type.h50
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc152
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.h38
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win_delegate.h26
-rw-r--r--chromium/content/browser/renderer_host/media/DEPS8
-rw-r--r--chromium/content/browser/renderer_host/media/OWNERS2
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc55
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.h37
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc184
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h39
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc34
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.h20
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc145
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.h16
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc36
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.cc57
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.h16
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.cc150
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter.h81
-rw-r--r--chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc213
-rw-r--r--chromium/content/browser/renderer_host/media/media_capture_devices_impl.h6
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc84
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h74
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc151
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc261
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h81
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_requester.h14
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.h4
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc155
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h48
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc44
-rw-r--r--chromium/content/browser/renderer_host/media/mock_media_observer.h4
-rw-r--r--chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc41
-rw-r--r--chromium/content/browser/renderer_host/media/peer_connection_tracker_host.h23
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc174
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h24
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h5
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc114
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc49
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h52
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc95
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc185
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h78
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc17
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h4
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc17
-rw-r--r--chromium/content/browser/renderer_host/memory_benchmark_message_filter.h5
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event.cc2
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc27
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h5
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller_delegate.h5
-rw-r--r--chromium/content/browser/renderer_host/p2p/OWNERS2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h14
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.cc341
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h52
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc71
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.h47
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc9
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h22
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc12
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc22
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h44
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc12
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_throttler.h8
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.cc88
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h33
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc85
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc102
-rw-r--r--chromium/content/browser/renderer_host/pepper/OWNERS1
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h37
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc18
-rw-r--r--chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h39
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc27
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h15
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h14
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc59
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h34
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc40
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h55
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_message_filter.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc3
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc17
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_printing_host.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_security_helper.h4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h55
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc16
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc159
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h69
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc156
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc10
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm412
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc237
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc126
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h30
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.cc36
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.h24
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc60
-rw-r--r--chromium/content/browser/renderer_host/popup_menu_helper_mac.h67
-rw-r--r--chromium/content/browser/renderer_host/popup_menu_helper_mac.mm125
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc245
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h72
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_browsertest.cc70
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc613
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h204
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_unittest.cc61
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_browsertest.cc7
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.cc4
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate.h28
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_delegate_view.h53
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc10
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc632
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h450
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_unittest.cc120
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.cc156
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.h82
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper_mac.mm64
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc13
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h15
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc699
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h291
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc271
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc805
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h267
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc566
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h407
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc515
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc127
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h172
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc124
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc259
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h427
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm1189
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm20
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm103
-rw-r--r--chromium/content/browser/renderer_host/render_widget_resize_helper.cc356
-rw-r--r--chromium/content/browser/renderer_host/render_widget_resize_helper.h92
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.cc320
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.h6
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc307
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h99
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_host.cc107
-rw-r--r--chromium/content/browser/renderer_host/socket_stream_host.h81
-rw-r--r--chromium/content/browser/renderer_host/software_frame_manager.h4
-rw-r--r--chromium/content/browser/renderer_host/software_frame_manager_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/software_layer_mac.mm66
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm2
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.h4
-rw-r--r--chromium/content/browser/renderer_host/ui_events_helper.cc31
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.cc109
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.h4
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc75
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aurax11.cc140
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host.cc16
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host.h4
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc75
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.cc61
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.h6
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper.cc5
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper.h4
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper_unittest.cc13
-rw-r--r--chromium/content/browser/resource_context_impl.cc9
-rw-r--r--chromium/content/browser/resources/gpu/gpu_internals.html4
-rw-r--r--chromium/content/browser/resources/gpu/info_view.css6
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js19
-rw-r--r--chromium/content/browser/resources/gpu/timeline_test.html2
-rw-r--r--chromium/content/browser/resources/indexed_db/OWNERS1
-rw-r--r--chromium/content/browser/resources/indexed_db/indexeddb_internals.html10
-rw-r--r--chromium/content/browser/resources/media/OWNERS2
-rw-r--r--chromium/content/browser/resources/media/client_renderer.js61
-rw-r--r--chromium/content/browser/resources/media/disjoint_range_set_test.html2
-rw-r--r--chromium/content/browser/resources/media/dump_creator.js14
-rw-r--r--chromium/content/browser/resources/media/main.js10
-rw-r--r--chromium/content/browser/resources/media/manager.js43
-rw-r--r--chromium/content/browser/resources/media/media_internals.css44
-rw-r--r--chromium/content/browser/resources/media/media_internals.html20
-rw-r--r--chromium/content/browser/resources/media/peer_connection_update_table.js3
-rw-r--r--chromium/content/browser/resources/media/stats_table.js2
-rw-r--r--chromium/content/browser/resources/media/tab_view.js4
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.css12
-rw-r--r--chromium/content/browser/resources/media/webrtc_internals.js83
-rw-r--r--chromium/content/browser/resources/service_worker/OWNERS2
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.css3
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.html35
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.js55
-rw-r--r--chromium/content/browser/safe_util_win.cc1
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc239
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc60
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h50
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc85
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.h50
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc146
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h72
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.cc49
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.h32
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider.h28
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider_android.cc51
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_provider_android.h34
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc8
-rw-r--r--chromium/content/browser/service_worker/BUILD.gn3
-rw-r--r--chromium/content/browser/service_worker/OWNERS9
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc151
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h46
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc71
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.cc159
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_registry.h36
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc115
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h27
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc448
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache.cc1259
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache.h195
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache.proto48
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_listener.cc459
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_listener.h150
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_quota_client.cc97
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_quota_client.h54
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_storage.cc683
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_storage.h165
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_storage_manager.cc325
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_storage_manager.h144
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_storage_manager_unittest.cc631
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_unittest.cc796
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc225
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h106
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc63
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.h20
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc140
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_unittest.cc261
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc215
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h74
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc199
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h47
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc244
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc146
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.h54
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.proto3
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_task_manager.cc71
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_task_manager.h75
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_unittest.cc355
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.cc7
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.h18
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc547
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h73
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc449
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc44
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h18
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.cc26
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.h39
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle_unittest.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_histograms.cc30
-rw-r--r--chromium/content/browser/service_worker/service_worker_histograms.h38
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.cc25
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.h13
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc88
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.cc13
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc633
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc58
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h48
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.cc113
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.h42
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc54
-rw-r--r--chromium/content/browser/service_worker/service_worker_proto.gyp5
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc187
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h102
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc237
-rw-r--r--chromium/content/browser/service_worker/service_worker_quota_client.cc111
-rw-r--r--chromium/content/browser/service_worker/service_worker_quota_client.h50
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc42
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job.h25
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc533
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h123
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job_base.h8
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc310
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h145
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_handle.cc147
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_handle.h84
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_status.cc8
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration_unittest.cc161
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc83
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h53
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc158
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_cache_map.cc60
-rw-r--r--chromium/content/browser/service_worker/service_worker_script_cache_map.h28
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc859
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h172
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc739
-rw-r--r--chromium/content/browser/service_worker/service_worker_unregister_job.cc48
-rw-r--r--chromium/content/browser/service_worker/service_worker_unregister_job.h15
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc217
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h111
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc116
-rw-r--r--chromium/content/browser/service_worker/service_worker_utils.cc40
-rw-r--r--chromium/content/browser/service_worker/service_worker_utils.h19
-rw-r--r--chromium/content/browser/service_worker/service_worker_utils_unittest.cc85
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc239
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h154
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc220
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc131
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h69
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc300
-rw-r--r--chromium/content/browser/session_history_browsertest.cc4
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc45
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h12
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_instance.h2
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc4
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_message_filter.cc24
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_message_filter.h16
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc40
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h14
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc26
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc145
-rw-r--r--chromium/content/browser/shared_worker/worker_document_set.cc83
-rw-r--r--chromium/content/browser/shared_worker/worker_document_set.h96
-rw-r--r--chromium/content/browser/shared_worker/worker_storage_partition.cc103
-rw-r--r--chromium/content/browser/shared_worker/worker_storage_partition.h132
-rw-r--r--chromium/content/browser/signed_certificate_timestamp_store_impl.h11
-rw-r--r--chromium/content/browser/site_instance_impl.cc35
-rw-r--r--chromium/content/browser/site_instance_impl.h49
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc77
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc356
-rw-r--r--chromium/content/browser/site_per_process_browsertest.h30
-rw-r--r--chromium/content/browser/speech/audio_encoder.cc12
-rw-r--r--chromium/content/browser/speech/endpointer/endpointer_unittest.cc8
-rw-r--r--chromium/content/browser/speech/google_one_shot_remote_engine.h18
-rw-r--r--chromium/content/browser/speech/google_one_shot_remote_engine_unittest.cc8
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine.cc2
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine.h23
-rw-r--r--chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc12
-rw-r--r--chromium/content/browser/speech/speech_recognition_browsertest.cc34
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.cc19
-rw-r--r--chromium/content/browser/speech/speech_recognition_dispatcher_host.h46
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.cc2
-rw-r--r--chromium/content/browser/speech/speech_recognition_manager_impl.h64
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc14
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h38
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_android.h10
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl_unittest.cc31
-rw-r--r--chromium/content/browser/ssl/ssl_cert_error_handler.cc8
-rw-r--r--chromium/content/browser/ssl/ssl_cert_error_handler.h11
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.cc111
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.h58
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.cc8
-rw-r--r--chromium/content/browser/ssl/ssl_error_handler.h25
-rw-r--r--chromium/content/browser/ssl/ssl_host_state.cc71
-rw-r--r--chromium/content/browser/ssl/ssl_host_state.h84
-rw-r--r--chromium/content/browser/ssl/ssl_host_state_unittest.cc203
-rw-r--r--chromium/content/browser/ssl/ssl_manager.cc15
-rw-r--r--chromium/content/browser/ssl/ssl_manager.h5
-rw-r--r--chromium/content/browser/ssl/ssl_policy.cc59
-rw-r--r--chromium/content/browser/ssl/ssl_policy.h23
-rw-r--r--chromium/content/browser/ssl/ssl_policy_backend.cc34
-rw-r--r--chromium/content/browser/ssl/ssl_policy_backend.h26
-rw-r--r--chromium/content/browser/ssl/ssl_request_info.cc2
-rw-r--r--chromium/content/browser/ssl/ssl_request_info.h8
-rw-r--r--chromium/content/browser/startup_task_runner.cc2
-rw-r--r--chromium/content/browser/startup_task_runner_unittest.cc20
-rw-r--r--chromium/content/browser/storage_partition_impl.cc253
-rw-r--r--chromium/content/browser/storage_partition_impl.h73
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc60
-rw-r--r--chromium/content/browser/storage_partition_impl_map.h2
-rw-r--r--chromium/content/browser/storage_partition_impl_map_unittest.cc2
-rw-r--r--chromium/content/browser/storage_partition_impl_unittest.cc75
-rw-r--r--chromium/content/browser/streams/stream.cc10
-rw-r--r--chromium/content/browser/streams/stream.h6
-rw-r--r--chromium/content/browser/streams/stream_handle_impl.cc22
-rw-r--r--chromium/content/browser/streams/stream_handle_impl.h18
-rw-r--r--chromium/content/browser/streams/stream_unittest.cc18
-rw-r--r--chromium/content/browser/streams/stream_url_request_job.h21
-rw-r--r--chromium/content/browser/streams/stream_url_request_job_unittest.cc9
-rw-r--r--chromium/content/browser/system_message_window_win_unittest.cc2
-rw-r--r--chromium/content/browser/tcmalloc_internals_request_job.cc6
-rw-r--r--chromium/content/browser/tcmalloc_internals_request_job.h10
-rw-r--r--chromium/content/browser/theme_helper_mac.h8
-rw-r--r--chromium/content/browser/time_zone_monitor_chromeos.cc2
-rw-r--r--chromium/content/browser/time_zone_monitor_linux.cc4
-rw-r--r--chromium/content/browser/time_zone_monitor_mac.mm2
-rw-r--r--chromium/content/browser/time_zone_monitor_win.cc2
-rw-r--r--chromium/content/browser/tracing/BUILD.gn43
-rw-r--r--chromium/content/browser/tracing/DEPS1
-rw-r--r--chromium/content/browser/tracing/etw_system_event_consumer_win.cc2
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc16
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.h14
-rw-r--r--chromium/content/browser/tracing/trace_uploader.cc210
-rw-r--r--chromium/content/browser/tracing/trace_uploader.h92
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc172
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc400
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h90
-rw-r--r--chromium/content/browser/tracing/tracing_resources.gyp2
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc243
-rw-r--r--chromium/content/browser/tracing/tracing_ui.h13
-rw-r--r--chromium/content/browser/transition_browsertest.cc191
-rw-r--r--chromium/content/browser/transition_request_manager.cc215
-rw-r--r--chromium/content/browser/transition_request_manager.h139
-rw-r--r--chromium/content/browser/transition_request_manager_unittest.cc106
-rw-r--r--chromium/content/browser/udev_linux.cc20
-rw-r--r--chromium/content/browser/udev_linux.h12
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc46
-rw-r--r--chromium/content/browser/utility_process_host_impl.h31
-rw-r--r--chromium/content/browser/vibration/vibration_message_filter.h4
-rw-r--r--chromium/content/browser/vibration/vibration_provider_android.h4
-rw-r--r--chromium/content/browser/web_contents/OWNERS3
-rw-r--r--chromium/content/browser/web_contents/aura/OWNERS2
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple.cc23
-rw-r--r--chromium/content/browser/web_contents/aura/gesture_nav_simple.h15
-rw-r--r--chromium/content/browser/web_contents/aura/image_window_delegate.cc2
-rw-r--r--chromium/content/browser/web_contents/aura/image_window_delegate.h36
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc74
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h22
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc33
-rw-r--r--chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc4
-rw-r--r--chromium/content/browser/web_contents/aura/shadow_layer_delegate.h9
-rw-r--r--chromium/content/browser/web_contents/aura/window_slider.cc8
-rw-r--r--chromium/content/browser/web_contents/aura/window_slider.h18
-rw-r--r--chromium/content/browser/web_contents/aura/window_slider_unittest.cc58
-rw-r--r--chromium/content/browser/web_contents/opened_by_dom_browsertest.cc7
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura.cc99
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura.h62
-rw-r--r--chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc166
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc330
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h59
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc948
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h875
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc112
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc951
-rw-r--r--chromium/content/browser/web_contents/web_contents_user_data_unittest.cc6
-rw-r--r--chromium/content/browser/web_contents/web_contents_view.h30
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.cc10
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_android.h53
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc363
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h170
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc476
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.cc63
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_guest.h80
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h114
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm153
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm2
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.mm2
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm2
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.h19
-rw-r--r--chromium/content/browser/webui/generic_handler.cc7
-rw-r--r--chromium/content/browser/webui/generic_handler.h4
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.cc16
-rw-r--r--chromium/content/browser/webui/shared_resources_data_source.h12
-rw-r--r--chromium/content/browser/webui/url_data_manager.h2
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc70
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.h10
-rw-r--r--chromium/content/browser/webui/web_ui_controller_factory_registry.h18
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc44
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h41
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_unittest.cc16
-rw-r--r--chromium/content/browser/webui/web_ui_impl.cc6
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h76
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc99
-rw-r--r--chromium/content/browser/worker.sb12
-rw-r--r--chromium/content/browser/worker_host/OWNERS3
-rw-r--r--chromium/content/browser/worker_host/worker_document_set.cc83
-rw-r--r--chromium/content/browser/worker_host/worker_document_set.h96
-rw-r--r--chromium/content/browser/worker_host/worker_message_filter.cc75
-rw-r--r--chromium/content/browser/worker_host/worker_message_filter.h56
-rw-r--r--chromium/content/browser/worker_host/worker_process_host.cc830
-rw-r--r--chromium/content/browser/worker_host/worker_process_host.h288
-rw-r--r--chromium/content/browser/worker_host/worker_service_impl.cc600
-rw-r--r--chromium/content/browser/worker_host/worker_service_impl.h121
-rw-r--r--chromium/content/browser/worker_host/worker_storage_partition.cc103
-rw-r--r--chromium/content/browser/worker_host/worker_storage_partition.h134
-rw-r--r--chromium/content/browser/zygote_host/OWNERS3
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc48
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.h12
-rw-r--r--chromium/content/child/BUILD.gn63
-rw-r--r--chromium/content/child/DEPS1
-rw-r--r--chromium/content/child/OWNERS2
-rw-r--r--chromium/content/child/appcache/appcache_backend_proxy.cc6
-rw-r--r--chromium/content/child/appcache/appcache_backend_proxy.h46
-rw-r--r--chromium/content/child/appcache/appcache_dispatcher.cc12
-rw-r--r--chromium/content/child/appcache/appcache_dispatcher.h18
-rw-r--r--chromium/content/child/appcache/appcache_frontend_impl.cc66
-rw-r--r--chromium/content/child/appcache/appcache_frontend_impl.h36
-rw-r--r--chromium/content/child/appcache/web_application_cache_host_impl.cc86
-rw-r--r--chromium/content/child/appcache/web_application_cache_host_impl.h24
-rw-r--r--chromium/content/child/assert_matching_enums.cc43
-rw-r--r--chromium/content/child/blink_glue.cc29
-rw-r--r--chromium/content/child/blink_glue.h23
-rw-r--r--chromium/content/child/blink_platform_impl.cc200
-rw-r--r--chromium/content/child/blink_platform_impl.h34
-rw-r--r--chromium/content/child/blink_platform_impl_unittest.cc197
-rw-r--r--chromium/content/child/blink_platform_unittest.cc67
-rw-r--r--chromium/content/child/bluetooth/web_bluetooth_impl.cc56
-rw-r--r--chromium/content/child/bluetooth/web_bluetooth_impl.h35
-rw-r--r--chromium/content/child/browser_font_resource_trusted.cc15
-rw-r--r--chromium/content/child/browser_font_resource_trusted.h35
-rw-r--r--chromium/content/child/child_discardable_shared_memory_manager.cc40
-rw-r--r--chromium/content/child/child_discardable_shared_memory_manager.h34
-rw-r--r--chromium/content/child/child_gpu_memory_buffer_manager.cc77
-rw-r--r--chromium/content/child/child_gpu_memory_buffer_manager.h36
-rw-r--r--chromium/content/child/child_histogram_message_filter.cc4
-rw-r--r--chromium/content/child/child_histogram_message_filter.h8
-rw-r--r--chromium/content/child/child_message_filter.cc6
-rw-r--r--chromium/content/child/child_message_filter.h4
-rw-r--r--chromium/content/child/child_process.h3
-rw-r--r--chromium/content/child/child_resource_message_filter.h4
-rw-r--r--chromium/content/child/child_shared_bitmap_manager.h14
-rw-r--r--chromium/content/child/child_thread.cc126
-rw-r--r--chromium/content/child/child_thread.h93
-rw-r--r--chromium/content/child/database_util.h5
-rw-r--r--chromium/content/child/db_message_filter.h4
-rw-r--r--chromium/content/child/file_info_util.cc29
-rw-r--r--chromium/content/child/file_info_util.h22
-rw-r--r--chromium/content/child/fileapi/OWNERS6
-rw-r--r--chromium/content/child/fileapi/file_system_dispatcher.cc45
-rw-r--r--chromium/content/child/fileapi/file_system_dispatcher.h44
-rw-r--r--chromium/content/child/fileapi/webfilesystem_impl.cc140
-rw-r--r--chromium/content/child/fileapi/webfilesystem_impl.h26
-rw-r--r--chromium/content/child/fileapi/webfilewriter_base.cc4
-rw-r--r--chromium/content/child/fileapi/webfilewriter_base_unittest.cc12
-rw-r--r--chromium/content/child/fileapi/webfilewriter_impl.h9
-rw-r--r--chromium/content/child/fling_animator_impl_android.cc101
-rw-r--r--chromium/content/child/fling_animator_impl_android.h47
-rw-r--r--chromium/content/child/fling_curve_configuration.cc56
-rw-r--r--chromium/content/child/fling_curve_configuration.h58
-rw-r--r--chromium/content/child/ftp_directory_listing_response_delegate.cc8
-rw-r--r--chromium/content/child/geofencing/OWNERS1
-rw-r--r--chromium/content/child/geofencing/geofencing_dispatcher.cc218
-rw-r--r--chromium/content/child/geofencing/geofencing_dispatcher.h87
-rw-r--r--chromium/content/child/geofencing/geofencing_message_filter.cc43
-rw-r--r--chromium/content/child/geofencing/geofencing_message_filter.h38
-rw-r--r--chromium/content/child/geofencing/web_geofencing_provider_impl.cc48
-rw-r--r--chromium/content/child/geofencing/web_geofencing_provider_impl.h46
-rw-r--r--chromium/content/child/indexed_db/OWNERS4
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher.cc14
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher.h17
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc22
-rw-r--r--chromium/content/child/indexed_db/indexed_db_message_filter.h10
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl.h10
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc34
-rw-r--r--chromium/content/child/indexed_db/webidbdatabase_impl.cc14
-rw-r--r--chromium/content/child/indexed_db/webidbdatabase_impl.h12
-rw-r--r--chromium/content/child/mojo/mojo_application.cc7
-rw-r--r--chromium/content/child/mojo/mojo_application.h21
-rw-r--r--chromium/content/child/multipart_response_delegate.cc404
-rw-r--r--chromium/content/child/multipart_response_delegate.h150
-rw-r--r--chromium/content/child/multipart_response_delegate_unittest.cc14
-rw-r--r--chromium/content/child/notifications/OWNERS1
-rw-r--r--chromium/content/child/notifications/notification_dispatcher.cc70
-rw-r--r--chromium/content/child/notifications/notification_dispatcher.h55
-rw-r--r--chromium/content/child/notifications/notification_manager.cc167
-rw-r--r--chromium/content/child/notifications/notification_manager.h69
-rw-r--r--chromium/content/child/npapi/np_channel_base.cc2
-rw-r--r--chromium/content/child/npapi/np_channel_base.h39
-rw-r--r--chromium/content/child/npapi/npobject_proxy.h12
-rw-r--r--chromium/content/child/npapi/npobject_stub.cc4
-rw-r--r--chromium/content/child/npapi/npobject_stub.h12
-rw-r--r--chromium/content/child/npapi/plugin_host.cc4
-rw-r--r--chromium/content/child/npapi/plugin_instance.cc5
-rw-r--r--chromium/content/child/npapi/plugin_lib_unittest.cc2
-rw-r--r--chromium/content/child/npapi/plugin_stream.cc2
-rw-r--r--chromium/content/child/npapi/plugin_stream_posix.cc2
-rw-r--r--chromium/content/child/npapi/plugin_stream_url.h34
-rw-r--r--chromium/content/child/npapi/plugin_string_stream.h2
-rw-r--r--chromium/content/child/npapi/plugin_url_fetcher.cc53
-rw-r--r--chromium/content/child/npapi/plugin_url_fetcher.h43
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl.h98
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_win.cc43
-rw-r--r--chromium/content/child/plugin_messages.h1
-rw-r--r--chromium/content/child/power_monitor_broadcast_source.cc4
-rw-r--r--chromium/content/child/power_monitor_broadcast_source.h4
-rw-r--r--chromium/content/child/power_monitor_broadcast_source_unittest.cc2
-rw-r--r--chromium/content/child/quota_dispatcher.cc36
-rw-r--r--chromium/content/child/quota_dispatcher.h15
-rw-r--r--chromium/content/child/quota_message_filter.h8
-rw-r--r--chromium/content/child/request_extra_data.cc5
-rw-r--r--chromium/content/child/request_extra_data.h37
-rw-r--r--chromium/content/child/request_info.cc9
-rw-r--r--chromium/content/child/request_info.h25
-rw-r--r--chromium/content/child/resource_dispatcher.cc82
-rw-r--r--chromium/content/child/resource_dispatcher.h30
-rw-r--r--chromium/content/child/resource_dispatcher_unittest.cc99
-rw-r--r--chromium/content/child/resource_loader_bridge.cc13
-rw-r--r--chromium/content/child/resource_loader_bridge.h92
-rw-r--r--chromium/content/child/runtime_features.cc95
-rw-r--r--chromium/content/child/service_worker/OWNERS2
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher.cc469
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher.h134
-rw-r--r--chromium/content/child/service_worker/service_worker_handle_reference.h1
-rw-r--r--chromium/content/child/service_worker/service_worker_message_filter.cc51
-rw-r--r--chromium/content/child/service_worker/service_worker_message_filter.h35
-rw-r--r--chromium/content/child/service_worker/service_worker_network_provider.h8
-rw-r--r--chromium/content/child/service_worker/service_worker_provider_context.cc136
-rw-r--r--chromium/content/child/service_worker/service_worker_provider_context.h57
-rw-r--r--chromium/content/child/service_worker/service_worker_registration_handle_reference.cc49
-rw-r--r--chromium/content/child/service_worker/service_worker_registration_handle_reference.h52
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.cc9
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.h2
-rw-r--r--chromium/content/child/service_worker/web_service_worker_provider_impl.cc45
-rw-r--r--chromium/content/child/service_worker/web_service_worker_provider_impl.h12
-rw-r--r--chromium/content/child/service_worker/web_service_worker_registration_impl.cc119
-rw-r--r--chromium/content/child/service_worker/web_service_worker_registration_impl.h72
-rw-r--r--chromium/content/child/shared_worker_devtools_agent.cc27
-rw-r--r--chromium/content/child/shared_worker_devtools_agent.h1
-rw-r--r--chromium/content/child/simple_webmimeregistry_impl.cc10
-rw-r--r--chromium/content/child/simple_webmimeregistry_impl.h2
-rw-r--r--chromium/content/child/simple_webmimeregistry_impl_unittest.cc21
-rw-r--r--chromium/content/child/site_isolation_policy.cc8
-rw-r--r--chromium/content/child/site_isolation_policy.h10
-rw-r--r--chromium/content/child/site_isolation_policy_browsertest.cc4
-rw-r--r--chromium/content/child/socket_stream_dispatcher.cc254
-rw-r--r--chromium/content/child/socket_stream_dispatcher.h51
-rw-r--r--chromium/content/child/thread_safe_sender.cc5
-rw-r--r--chromium/content/child/thread_safe_sender.h8
-rw-r--r--chromium/content/child/threaded_data_provider.cc14
-rw-r--r--chromium/content/child/threaded_data_provider.h10
-rw-r--r--chromium/content/child/touch_fling_gesture_curve.cc163
-rw-r--r--chromium/content/child/touch_fling_gesture_curve.h55
-rw-r--r--chromium/content/child/touch_fling_gesture_curve_unittest.cc70
-rw-r--r--chromium/content/child/web_data_consumer_handle_impl.cc116
-rw-r--r--chromium/content/child/web_data_consumer_handle_impl.h40
-rw-r--r--chromium/content/child/web_data_consumer_handle_impl_unittest.cc270
-rw-r--r--chromium/content/child/web_database_observer_impl.cc62
-rw-r--r--chromium/content/child/web_database_observer_impl.h10
-rw-r--r--chromium/content/child/web_gesture_curve_impl.cc97
-rw-r--r--chromium/content/child/web_gesture_curve_impl.h53
-rw-r--r--chromium/content/child/web_gesture_curve_impl_unittest.cc72
-rw-r--r--chromium/content/child/web_socket_stream_handle_bridge.h37
-rw-r--r--chromium/content/child/web_socket_stream_handle_delegate.h44
-rw-r--r--chromium/content/child/web_socket_stream_handle_impl.cc198
-rw-r--r--chromium/content/child/web_socket_stream_handle_impl.h35
-rw-r--r--chromium/content/child/web_url_loader_impl.cc514
-rw-r--r--chromium/content/child/web_url_loader_impl.h34
-rw-r--r--chromium/content/child/web_url_loader_impl_unittest.cc707
-rw-r--r--chromium/content/child/web_url_request_util.cc218
-rw-r--r--chromium/content/child/web_url_request_util.h28
-rw-r--r--chromium/content/child/webblobregistry_impl.cc36
-rw-r--r--chromium/content/child/webblobregistry_impl.h14
-rw-r--r--chromium/content/child/webcrypto/OWNERS4
-rw-r--r--chromium/content/child/webcrypto/algorithm_dispatch.cc253
-rw-r--r--chromium/content/child/webcrypto/algorithm_dispatch.h97
-rw-r--r--chromium/content/child/webcrypto/algorithm_implementation.cc131
-rw-r--r--chromium/content/child/webcrypto/algorithm_implementation.h157
-rw-r--r--chromium/content/child/webcrypto/algorithm_registry.cc90
-rw-r--r--chromium/content/child/webcrypto/algorithm_registry.h32
-rw-r--r--chromium/content/child/webcrypto/generate_key_result.cc63
-rw-r--r--chromium/content/child/webcrypto/generate_key_result.h60
-rw-r--r--chromium/content/child/webcrypto/jwk.cc1071
-rw-r--r--chromium/content/child/webcrypto/jwk.h229
-rw-r--r--chromium/content/child/webcrypto/nss/aes_cbc_nss.cc128
-rw-r--r--chromium/content/child/webcrypto/nss/aes_gcm_nss.cc191
-rw-r--r--chromium/content/child/webcrypto/nss/aes_key_nss.cc134
-rw-r--r--chromium/content/child/webcrypto/nss/aes_key_nss.h77
-rw-r--r--chromium/content/child/webcrypto/nss/aes_kw_nss.cc206
-rw-r--r--chromium/content/child/webcrypto/nss/hmac_nss.cc240
-rw-r--r--chromium/content/child/webcrypto/nss/key_nss.cc96
-rw-r--r--chromium/content/child/webcrypto/nss/key_nss.h109
-rw-r--r--chromium/content/child/webcrypto/nss/rsa_key_nss.cc852
-rw-r--r--chromium/content/child/webcrypto/nss/rsa_key_nss.h92
-rw-r--r--chromium/content/child/webcrypto/nss/rsa_oaep_nss.cc246
-rw-r--r--chromium/content/child/webcrypto/nss/rsa_ssa_nss.cc144
-rw-r--r--chromium/content/child/webcrypto/nss/sha_nss.cc160
-rw-r--r--chromium/content/child/webcrypto/nss/sym_key_nss.cc94
-rw-r--r--chromium/content/child/webcrypto/nss/sym_key_nss.h39
-rw-r--r--chromium/content/child/webcrypto/nss/util_nss.cc95
-rw-r--r--chromium/content/child/webcrypto/nss/util_nss.h113
-rw-r--r--chromium/content/child/webcrypto/openssl/aes_cbc_openssl.cc139
-rw-r--r--chromium/content/child/webcrypto/openssl/aes_ctr_openssl.cc288
-rw-r--r--chromium/content/child/webcrypto/openssl/aes_gcm_openssl.cc88
-rw-r--r--chromium/content/child/webcrypto/openssl/aes_key_openssl.cc124
-rw-r--r--chromium/content/child/webcrypto/openssl/aes_key_openssl.h67
-rw-r--r--chromium/content/child/webcrypto/openssl/aes_kw_openssl.cc94
-rw-r--r--chromium/content/child/webcrypto/openssl/hmac_openssl.cc216
-rw-r--r--chromium/content/child/webcrypto/openssl/key_openssl.cc73
-rw-r--r--chromium/content/child/webcrypto/openssl/key_openssl.h83
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_key_openssl.cc389
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_key_openssl.h83
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_oaep_openssl.cc153
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_pss_openssl.cc67
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_sign_openssl.cc155
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_sign_openssl.h44
-rw-r--r--chromium/content/child/webcrypto/openssl/rsa_ssa_openssl.cc61
-rw-r--r--chromium/content/child/webcrypto/openssl/sha_openssl.cc140
-rw-r--r--chromium/content/child/webcrypto/openssl/sym_key_openssl.cc60
-rw-r--r--chromium/content/child/webcrypto/openssl/sym_key_openssl.h34
-rw-r--r--chromium/content/child/webcrypto/openssl/util_openssl.cc249
-rw-r--r--chromium/content/child/webcrypto/openssl/util_openssl.h87
-rw-r--r--chromium/content/child/webcrypto/platform_crypto.h283
-rw-r--r--chromium/content/child/webcrypto/platform_crypto_nss.cc1934
-rw-r--r--chromium/content/child/webcrypto/platform_crypto_openssl.cc520
-rw-r--r--chromium/content/child/webcrypto/shared_crypto.cc955
-rw-r--r--chromium/content/child/webcrypto/shared_crypto.h187
-rw-r--r--chromium/content/child/webcrypto/shared_crypto_unittest.cc4399
-rw-r--r--chromium/content/child/webcrypto/status.cc60
-rw-r--r--chromium/content/child/webcrypto/status.h47
-rw-r--r--chromium/content/child/webcrypto/structured_clone.cc136
-rw-r--r--chromium/content/child/webcrypto/structured_clone.h34
-rw-r--r--chromium/content/child/webcrypto/webcrypto_impl.cc126
-rw-r--r--chromium/content/child/webcrypto/webcrypto_impl.h9
-rw-r--r--chromium/content/child/webcrypto/webcrypto_util.cc254
-rw-r--r--chromium/content/child/webcrypto/webcrypto_util.h70
-rw-r--r--chromium/content/child/webfileutilities_impl.cc4
-rw-r--r--chromium/content/child/webmessageportchannel_impl.cc9
-rw-r--r--chromium/content/child/webmessageportchannel_impl.h23
-rw-r--r--chromium/content/child/websocket_bridge.h8
-rw-r--r--chromium/content/child/websocket_dispatcher.h4
-rw-r--r--chromium/content/child/webthemeengine_impl_mac.cc61
-rw-r--r--chromium/content/child/webthemeengine_impl_mac.h8
-rw-r--r--chromium/content/child/webthread_impl.cc15
-rw-r--r--chromium/content/child/webthread_impl.h17
-rw-r--r--chromium/content/child/weburlresponse_extradata_impl.cc19
-rw-r--r--chromium/content/child/weburlresponse_extradata_impl.h105
-rw-r--r--chromium/content/child/worker_thread_task_runner.h10
-rw-r--r--chromium/content/common/BUILD.gn144
-rw-r--r--chromium/content/common/DEPS11
-rw-r--r--chromium/content/common/OWNERS25
-rw-r--r--chromium/content/common/accessibility_messages.h79
-rw-r--r--chromium/content/common/accessibility_mode_enums.h34
-rw-r--r--chromium/content/common/android/OWNERS1
-rw-r--r--chromium/content/common/android/address_parser_internal.cc4
-rw-r--r--chromium/content/common/android/gin_java_bridge_errors.cc35
-rw-r--r--chromium/content/common/android/gin_java_bridge_errors.h28
-rw-r--r--chromium/content/common/android/surface_texture_lookup.cc27
-rw-r--r--chromium/content/common/android/surface_texture_lookup.h26
-rw-r--r--chromium/content/common/android/surface_texture_manager.cc28
-rw-r--r--chromium/content/common/android/surface_texture_manager.h41
-rw-r--r--chromium/content/common/appcache_interfaces.cc139
-rw-r--r--chromium/content/common/appcache_interfaces.h188
-rw-r--r--chromium/content/common/appcache_messages.h32
-rw-r--r--chromium/content/common/battery_status_messages.h32
-rw-r--r--chromium/content/common/browser_plugin/OWNERS3
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_constants.cc23
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_constants.h22
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_messages.h159
-rw-r--r--chromium/content/common/cc_messages.cc143
-rw-r--r--chromium/content/common/cc_messages.h25
-rw-r--r--chromium/content/common/cc_messages_perftest.cc35
-rw-r--r--chromium/content/common/cc_messages_unittest.cc271
-rw-r--r--chromium/content/common/child_process_host_impl.cc71
-rw-r--r--chromium/content/common/child_process_host_impl.h38
-rw-r--r--chromium/content/common/child_process_messages.h39
-rw-r--r--chromium/content/common/child_process_sandbox_support_impl_linux.cc61
-rw-r--r--chromium/content/common/child_process_sandbox_support_impl_linux.h26
-rw-r--r--chromium/content/common/common_param_traits_unittest.cc6
-rw-r--r--chromium/content/common/content_constants_internal.cc5
-rw-r--r--chromium/content/common/content_constants_internal.h5
-rw-r--r--chromium/content/common/content_message_generator.h12
-rw-r--r--chromium/content/common/content_param_traits.cc8
-rw-r--r--chromium/content/common/content_param_traits_macros.h11
-rw-r--r--chromium/content/common/content_paths.cc2
-rw-r--r--chromium/content/common/content_switches_internal.cc3
-rw-r--r--chromium/content/common/cursors/DEPS1
-rw-r--r--chromium/content/common/cursors/webcursor.cc5
-rw-r--r--chromium/content/common/cursors/webcursor.h7
-rw-r--r--chromium/content/common/cursors/webcursor_aurawin.cc2
-rw-r--r--chromium/content/common/cursors/webcursor_aurax11.cc13
-rw-r--r--chromium/content/common/cursors/webcursor_mac.mm7
-rw-r--r--chromium/content/common/cursors/webcursor_ozone.cc2
-rw-r--r--chromium/content/common/database_connections_unittest.cc6
-rw-r--r--chromium/content/common/database_identifier_unittest.cc12
-rw-r--r--chromium/content/common/desktop_notification_messages.h15
-rw-r--r--chromium/content/common/device_sensors/device_light_data.h23
-rw-r--r--chromium/content/common/device_sensors/device_light_hardware_buffer.h17
-rw-r--r--chromium/content/common/device_sensors/device_light_messages.h26
-rw-r--r--chromium/content/common/devtools_messages.h12
-rw-r--r--chromium/content/common/dom_storage/OWNERS3
-rw-r--r--chromium/content/common/fileapi/OWNERS6
-rw-r--r--chromium/content/common/fileapi/file_system_messages.h29
-rw-r--r--chromium/content/common/fileapi/file_system_util_unittest.cc32
-rw-r--r--chromium/content/common/fileapi/webblob_messages.h6
-rw-r--r--chromium/content/common/font_cache_dispatcher_win.h8
-rw-r--r--chromium/content/common/font_config_ipc_linux.cc2
-rw-r--r--chromium/content/common/font_config_ipc_linux.h14
-rw-r--r--chromium/content/common/frame_message_enums.h2
-rw-r--r--chromium/content/common/frame_messages.h325
-rw-r--r--chromium/content/common/frame_param_macros.h3
-rw-r--r--chromium/content/common/gamepad_seqlock_unittest.cc98
-rw-r--r--chromium/content/common/geofencing_messages.h70
-rw-r--r--chromium/content/common/geofencing_status.cc32
-rw-r--r--chromium/content/common/geofencing_status.h34
-rw-r--r--chromium/content/common/geolocation_messages.h29
-rw-r--r--chromium/content/common/geolocation_service.mojom19
-rw-r--r--chromium/content/common/gin_java_bridge_messages.h12
-rw-r--r--chromium/content/common/gpu/OWNERS8
-rw-r--r--chromium/content/common/gpu/client/command_buffer_proxy_impl.cc166
-rw-r--r--chromium/content/common/gpu/client/command_buffer_proxy_impl.h86
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.cc2
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.h30
-rw-r--r--chromium/content/common/gpu/client/gl_helper.cc417
-rw-r--r--chromium/content/common/gpu/client/gl_helper.h18
-rw-r--r--chromium/content/common/gpu/client/gl_helper_benchmark.cc30
-rw-r--r--chromium/content/common/gpu/client/gl_helper_readback_support.cc130
-rw-r--r--chromium/content/common/gpu/client/gl_helper_readback_support.h42
-rw-r--r--chromium/content/common/gpu/client/gl_helper_scaling.cc14
-rw-r--r--chromium/content/common/gpu/client/gl_helper_unittest.cc598
-rw-r--r--chromium/content/common/gpu/client/gpu_channel_host.cc49
-rw-r--r--chromium/content/common/gpu/client/gpu_channel_host.h55
-rw-r--r--chromium/content/common/gpu/client/gpu_in_process_context_tests.cc8
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.cc27
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.h20
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc65
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl.h75
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc99
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc160
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h46
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc65
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc96
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc99
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc174
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h59
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc165
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h60
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc109
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h49
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc190
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h48
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc65
-rw-r--r--chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc6
-rw-r--r--chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h29
-rw-r--r--chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc56
-rw-r--r--chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h39
-rw-r--r--chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc80
-rw-r--r--chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h39
-rw-r--r--chromium/content/common/gpu/gpu_channel.cc234
-rw-r--r--chromium/content/common/gpu/gpu_channel.h34
-rw-r--r--chromium/content/common/gpu/gpu_channel_manager.cc212
-rw-r--r--chromium/content/common/gpu/gpu_channel_manager.h61
-rw-r--r--chromium/content/common/gpu/gpu_command_buffer_stub.cc176
-rw-r--r--chromium/content/common/gpu/gpu_command_buffer_stub.h40
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory.h55
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_android.cc88
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc103
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h54
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_linux.cc67
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_mac.cc88
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_ozone.cc94
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc78
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h51
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_win.cc67
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager.cc6
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager_unittest.cc38
-rw-r--r--chromium/content/common/gpu/gpu_messages.h193
-rw-r--r--chromium/content/common/gpu/image_transport_surface.cc65
-rw-r--r--chromium/content/common/gpu/image_transport_surface.h52
-rw-r--r--chromium/content/common/gpu/image_transport_surface_android.cc63
-rw-r--r--chromium/content/common/gpu/image_transport_surface_calayer_mac.h102
-rw-r--r--chromium/content/common/gpu/image_transport_surface_calayer_mac.mm371
-rw-r--r--chromium/content/common/gpu/image_transport_surface_fbo_mac.cc345
-rw-r--r--chromium/content/common/gpu/image_transport_surface_fbo_mac.h88
-rw-r--r--chromium/content/common/gpu/image_transport_surface_fbo_mac.mm334
-rw-r--r--chromium/content/common/gpu/image_transport_surface_iosurface_mac.cc46
-rw-r--r--chromium/content/common/gpu/image_transport_surface_iosurface_mac.h30
-rw-r--r--chromium/content/common/gpu/image_transport_surface_mac.mm12
-rw-r--r--chromium/content/common/gpu/media/OWNERS3
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator.cc30
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator.h16
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc16
-rw-r--r--chromium/content/common/gpu/media/android_video_encode_accelerator.cc51
-rw-r--r--chromium/content/common/gpu/media/android_video_encode_accelerator.h15
-rw-r--r--chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc82
-rw-r--r--chromium/content/common/gpu/media/dxva_video_decode_accelerator.h32
-rw-r--r--chromium/content/common/gpu/media/exynos_v4l2_video_device.h24
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc31
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator.h26
-rw-r--r--chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc66
-rw-r--r--chromium/content/common/gpu/media/gpu_video_encode_accelerator.h30
-rw-r--r--chromium/content/common/gpu/media/h264_dpb.h1
-rw-r--r--chromium/content/common/gpu/media/rendering_helper.cc467
-rw-r--r--chromium/content/common/gpu/media/rendering_helper.h167
-rw-r--r--chromium/content/common/gpu/media/tegra_v4l2_video_device.cc12
-rw-r--r--chromium/content/common/gpu/media/tegra_v4l2_video_device.h24
-rw-r--r--chromium/content/common/gpu/media/v4l2_image_processor.cc22
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc70
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h16
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_device.cc22
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc62
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_encode_accelerator.h58
-rw-r--r--chromium/content/common/gpu/media/va.sigs2
-rw-r--r--chromium/content/common/gpu/media/vaapi_h264_decoder.cc14
-rw-r--r--chromium/content/common/gpu/media/vaapi_h264_decoder_unittest.cc16
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc23
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h16
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc1067
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_encode_accelerator.h263
-rw-r--r--chromium/content/common/gpu/media/vaapi_wrapper.cc429
-rw-r--r--chromium/content/common/gpu/media/vaapi_wrapper.h104
-rw-r--r--chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc173
-rw-r--r--chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc560
-rw-r--r--chromium/content/common/gpu/media/vt.h19
-rw-r--r--chromium/content/common/gpu/media/vt.sig16
-rw-r--r--chromium/content/common/gpu/media/vt_stubs_header.fragment84
-rw-r--r--chromium/content/common/gpu/media/vt_video_decode_accelerator.cc701
-rw-r--r--chromium/content/common/gpu/media/vt_video_decode_accelerator.h187
-rw-r--r--chromium/content/common/gpu/null_transport_surface.cc73
-rw-r--r--chromium/content/common/gpu/null_transport_surface.h43
-rw-r--r--chromium/content/common/gpu/stream_texture_android.cc19
-rw-r--r--chromium/content/common/gpu/stream_texture_android.h26
-rw-r--r--chromium/content/common/gpu/surface_handle_types_mac.cc53
-rw-r--r--chromium/content/common/gpu/surface_handle_types_mac.h35
-rw-r--r--chromium/content/common/gpu/sync_point_manager.cc6
-rw-r--r--chromium/content/common/gpu/texture_image_transport_surface.cc459
-rw-r--r--chromium/content/common/gpu/texture_image_transport_surface.h124
-rw-r--r--chromium/content/common/handle_enumerator_win.cc2
-rw-r--r--chromium/content/common/host_discardable_shared_memory_manager.cc255
-rw-r--r--chromium/content/common/host_discardable_shared_memory_manager.h100
-rw-r--r--chromium/content/common/host_discardable_shared_memory_manager_unittest.cc188
-rw-r--r--chromium/content/common/host_shared_bitmap_manager.cc5
-rw-r--r--chromium/content/common/host_shared_bitmap_manager.h25
-rw-r--r--chromium/content/common/host_shared_bitmap_manager_unittest.cc2
-rw-r--r--chromium/content/common/indexed_db/OWNERS4
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key.cc23
-rw-r--r--chromium/content/common/indexed_db/indexed_db_key.h3
-rw-r--r--chromium/content/common/indexed_db/indexed_db_messages.h42
-rw-r--r--chromium/content/common/input/did_overscroll_params.cc15
-rw-r--r--chromium/content/common/input/did_overscroll_params.h7
-rw-r--r--chromium/content/common/input/gesture_event_stream_validator.cc24
-rw-r--r--chromium/content/common/input/gesture_event_stream_validator.h3
-rw-r--r--chromium/content/common/input/gesture_event_stream_validator_unittest.cc236
-rw-r--r--chromium/content/common/input/input_param_traits.cc2
-rw-r--r--chromium/content/common/input/input_param_traits_unittest.cc6
-rw-r--r--chromium/content/common/input/synthetic_pinch_gesture_params.h4
-rw-r--r--chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h4
-rw-r--r--chromium/content/common/input/synthetic_tap_gesture_params.h4
-rw-r--r--chromium/content/common/input/touch_event_stream_validator.cc21
-rw-r--r--chromium/content/common/input/touch_event_stream_validator.h3
-rw-r--r--chromium/content/common/input/touch_event_stream_validator_unittest.cc173
-rw-r--r--chromium/content/common/input/web_input_event_traits.cc111
-rw-r--r--chromium/content/common/input/web_input_event_traits.h3
-rw-r--r--chromium/content/common/input/web_input_event_traits_unittest.cc25
-rw-r--r--chromium/content/common/input/web_touch_event_traits.cc14
-rw-r--r--chromium/content/common/input/web_touch_event_traits.h4
-rw-r--r--chromium/content/common/input_messages.h65
-rw-r--r--chromium/content/common/inter_process_time_ticks_converter.cc9
-rw-r--r--chromium/content/common/inter_process_time_ticks_converter.h10
-rw-r--r--chromium/content/common/inter_process_time_ticks_converter_unittest.cc11
-rw-r--r--chromium/content/common/java_bridge_messages.h37
-rw-r--r--chromium/content/common/mac/font_loader.mm2
-rw-r--r--chromium/content/common/manifest_manager_messages.h49
-rw-r--r--chromium/content/common/media/OWNERS8
-rw-r--r--chromium/content/common/media/audio_messages.h42
-rw-r--r--chromium/content/common/media/cdm_messages.h47
-rw-r--r--chromium/content/common/media/cdm_messages_enums.h3
-rw-r--r--chromium/content/common/media/media_param_traits.cc8
-rw-r--r--chromium/content/common/media/media_player_messages_android.h25
-rw-r--r--chromium/content/common/media/media_player_messages_enums_android.h1
-rw-r--r--chromium/content/common/media/media_stream_messages.h32
-rw-r--r--chromium/content/common/media/media_stream_options.cc12
-rw-r--r--chromium/content/common/media/midi_messages.h23
-rw-r--r--chromium/content/common/media/peer_connection_tracker_messages.h3
-rw-r--r--chromium/content/common/media/video_capture_messages.h17
-rw-r--r--chromium/content/common/message_router.h6
-rw-r--r--chromium/content/common/mojo/OWNERS2
-rw-r--r--chromium/content/common/mojo/mojo_messages.h3
-rw-r--r--chromium/content/common/mojo/mojo_service_names.cc13
-rw-r--r--chromium/content/common/mojo/mojo_service_names.h18
-rw-r--r--chromium/content/common/mojo/service_registry_impl.cc81
-rw-r--r--chromium/content/common/mojo/service_registry_impl.h64
-rw-r--r--chromium/content/common/navigation_gesture.h1
-rw-r--r--chromium/content/common/navigation_params.cc61
-rw-r--r--chromium/content/common/navigation_params.h104
-rw-r--r--chromium/content/common/net/url_request_user_data.h2
-rw-r--r--chromium/content/common/one_writer_seqlock_unittest.cc98
-rw-r--r--chromium/content/common/p2p_messages.h21
-rw-r--r--chromium/content/common/page_state_serialization.cc73
-rw-r--r--chromium/content/common/page_state_serialization.h6
-rw-r--r--chromium/content/common/page_state_serialization_unittest.cc8
-rw-r--r--chromium/content/common/pepper_file_util.cc23
-rw-r--r--chromium/content/common/pepper_file_util.h22
-rw-r--r--chromium/content/common/pepper_plugin_list.cc7
-rw-r--r--chromium/content/common/pepper_plugin_list.h5
-rw-r--r--chromium/content/common/pepper_renderer_instance_data.h4
-rw-r--r--chromium/content/common/platform_notification_messages.h54
-rw-r--r--chromium/content/common/plugin_carbon_interpose_constants_mac.cc15
-rw-r--r--chromium/content/common/plugin_carbon_interpose_constants_mac.h19
-rw-r--r--chromium/content/common/plugin_constants_win.cc2
-rw-r--r--chromium/content/common/plugin_constants_win.h2
-rw-r--r--chromium/content/common/plugin_list.cc9
-rw-r--r--chromium/content/common/plugin_list.h6
-rw-r--r--chromium/content/common/plugin_list_mac.mm2
-rw-r--r--chromium/content/common/plugin_list_win.cc41
-rw-r--r--chromium/content/common/plugin_process_messages.h8
-rw-r--r--chromium/content/common/process_type.cc2
-rw-r--r--chromium/content/common/push_messaging_messages.h44
-rw-r--r--chromium/content/common/quota_messages.h10
-rw-r--r--chromium/content/common/render_frame_setup.mojom12
-rw-r--r--chromium/content/common/resource_messages.cc33
-rw-r--r--chromium/content/common/resource_messages.h60
-rw-r--r--chromium/content/common/resource_request_body.h10
-rw-r--r--chromium/content/common/sandbox_init_mac.cc6
-rw-r--r--chromium/content/common/sandbox_init_win.cc8
-rw-r--r--chromium/content/common/sandbox_linux/OWNERS1
-rw-r--r--chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc14
-rw-r--r--chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h6
-rw-r--r--chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc44
-rw-r--r--chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h8
-rw-r--r--chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc93
-rw-r--r--chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h15
-rw-r--r--chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc17
-rw-r--r--chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h6
-rw-r--r--chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc34
-rw-r--r--chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h6
-rw-r--r--chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc60
-rw-r--r--chromium/content/common/sandbox_linux/bpf_utility_policy_linux.h27
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc14
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h21
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_init_linux.cc6
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_linux.cc34
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_linux.h10
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc87
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h9
-rw-r--r--chromium/content/common/sandbox_mac.mm29
-rw-r--r--chromium/content/common/sandbox_mac_diraccess_unittest.mm8
-rw-r--r--chromium/content/common/sandbox_mac_fontloading_unittest.mm7
-rw-r--r--chromium/content/common/sandbox_mac_system_access_unittest.mm50
-rw-r--r--chromium/content/common/sandbox_win.cc90
-rw-r--r--chromium/content/common/sandbox_win.h3
-rw-r--r--chromium/content/common/screen_orientation_messages.h38
-rw-r--r--chromium/content/common/service_worker/OWNERS5
-rw-r--r--chromium/content/common/service_worker/embedded_worker_messages.h32
-rw-r--r--chromium/content/common/service_worker/service_worker_messages.h251
-rw-r--r--chromium/content/common/service_worker/service_worker_status_code.cc4
-rw-r--r--chromium/content/common/service_worker/service_worker_status_code.h6
-rw-r--r--chromium/content/common/service_worker/service_worker_types.cc60
-rw-r--r--chromium/content/common/service_worker/service_worker_types.h158
-rw-r--r--chromium/content/common/set_process_title.cc2
-rw-r--r--chromium/content/common/shareable_file_reference_unittest.cc6
-rw-r--r--chromium/content/common/socket_stream.h14
-rw-r--r--chromium/content/common/socket_stream_handle_data.h30
-rw-r--r--chromium/content/common/socket_stream_messages.h80
-rw-r--r--chromium/content/common/speech_recognition_messages.h11
-rw-r--r--chromium/content/common/ssl_status_serialization.cc38
-rw-r--r--chromium/content/common/swapped_out_messages.cc4
-rw-r--r--chromium/content/common/user_agent.cc2
-rw-r--r--chromium/content/common/user_agent_ios.mm130
-rw-r--r--chromium/content/common/utility_messages.h6
-rw-r--r--chromium/content/common/view_message_enums.h30
-rw-r--r--chromium/content/common/view_messages.h307
-rw-r--r--chromium/content/common/web_ui_setup.mojom16
-rw-r--r--chromium/content/common/websocket.h3
-rw-r--r--chromium/content/common/websocket_messages.h5
-rw-r--r--chromium/content/common/worker_messages.h9
-rw-r--r--chromium/content/content.gyp194
-rw-r--r--chromium/content/content_app.gypi19
-rw-r--r--chromium/content/content_browser.gypi425
-rw-r--r--chromium/content/content_browsertests.isolate90
-rw-r--r--chromium/content/content_child.gypi135
-rw-r--r--chromium/content/content_common.gypi173
-rw-r--r--chromium/content/content_common_mojo_bindings.gypi18
-rw-r--r--chromium/content/content_gl_tests.isolate57
-rw-r--r--chromium/content/content_gpu.gypi32
-rw-r--r--chromium/content/content_jni.gypi8
-rw-r--r--chromium/content/content_plugin.gypi2
-rw-r--r--chromium/content/content_ppapi_plugin.gypi6
-rw-r--r--chromium/content/content_renderer.gypi225
-rw-r--r--chromium/content/content_resources.grd13
-rw-r--r--chromium/content/content_resources.gyp36
-rw-r--r--chromium/content/content_resources.gypi33
-rw-r--r--chromium/content/content_shell.gypi243
-rw-r--r--chromium/content/content_tests.gypi669
-rw-r--r--chromium/content/content_unittests.isolate50
-rw-r--r--chromium/content/content_utility.gypi2
-rw-r--r--chromium/content/content_worker.gypi30
-rw-r--r--chromium/content/gpu/BUILD.gn35
-rw-r--r--chromium/content/gpu/OWNERS5
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc20
-rw-r--r--chromium/content/gpu/gpu_child_thread.h9
-rw-r--r--chromium/content/gpu/gpu_main.cc44
-rw-r--r--chromium/content/gpu/gpu_process.h2
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.cc6
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.h23
-rw-r--r--chromium/content/gpu/in_process_gpu_thread.h6
-rw-r--r--chromium/content/plugin/BUILD.gn11
-rw-r--r--chromium/content/plugin/plugin_carbon_interpose_mac.cc128
-rw-r--r--chromium/content/plugin/plugin_channel.cc8
-rw-r--r--chromium/content/plugin/plugin_channel.h24
-rw-r--r--chromium/content/plugin/plugin_interpose_util_mac.h27
-rw-r--r--chromium/content/plugin/plugin_interpose_util_mac.mm67
-rw-r--r--chromium/content/plugin/plugin_main.cc7
-rw-r--r--chromium/content/plugin/plugin_main_mac.mm37
-rw-r--r--chromium/content/plugin/plugin_thread.cc12
-rw-r--r--chromium/content/plugin/plugin_thread.h8
-rw-r--r--chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h10
-rw-r--r--chromium/content/plugin/webplugin_delegate_stub.h6
-rw-r--r--chromium/content/plugin/webplugin_proxy.h91
-rw-r--r--chromium/content/ppapi_plugin/BUILD.gn14
-rw-r--r--chromium/content/ppapi_plugin/broker_process_dispatcher.h4
-rw-r--r--chromium/content/ppapi_plugin/plugin_process_dispatcher.h2
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc257
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h61
-rw-r--r--chromium/content/ppapi_plugin/ppapi_plugin_main.cc2
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.cc20
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.h48
-rw-r--r--chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc260
-rw-r--r--chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h62
-rw-r--r--chromium/content/public/OWNERS2
-rw-r--r--chromium/content/public/README3
-rw-r--r--chromium/content/public/android/BUILD.gn178
-rw-r--r--chromium/content/public/android/DEPS2
-rw-r--r--chromium/content/public/android/OWNERS1
-rw-r--r--chromium/content/public/app/BUILD.gn149
-rw-r--r--chromium/content/public/app/android_library_loader_hooks.h3
-rw-r--r--chromium/content/public/app/content_main_delegate.cc6
-rw-r--r--chromium/content/public/app/content_main_delegate.h7
-rw-r--r--chromium/content/public/browser/BUILD.gn30
-rw-r--r--chromium/content/public/browser/android/OWNERS1
-rw-r--r--chromium/content/public/browser/android/compositor.h4
-rw-r--r--chromium/content/public/browser/android/content_view_core.h5
-rw-r--r--chromium/content/public/browser/android/devtools_auth.h10
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.cc23
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.h25
-rw-r--r--chromium/content/public/browser/android/ui_resource_provider.h2
-rw-r--r--chromium/content/public/browser/appcache_service.h65
-rw-r--r--chromium/content/public/browser/ax_event_notification_details.cc7
-rw-r--r--chromium/content/public/browser/ax_event_notification_details.h4
-rw-r--r--chromium/content/public/browser/browser_child_process_host.h2
-rw-r--r--chromium/content/public/browser/browser_child_process_host_delegate.h2
-rw-r--r--chromium/content/public/browser/browser_context.h40
-rw-r--r--chromium/content/public/browser/browser_message_filter.cc20
-rw-r--r--chromium/content/public/browser/browser_message_filter.h4
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.cc21
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_delegate.h40
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_manager.cc13
-rw-r--r--chromium/content/public/browser/browser_plugin_guest_manager.h34
-rw-r--r--chromium/content/public/browser/browser_thread.h25
-rw-r--r--chromium/content/public/browser/child_process_security_policy.h7
-rw-r--r--chromium/content/public/browser/content_browser_client.cc70
-rw-r--r--chromium/content/public/browser/content_browser_client.h154
-rw-r--r--chromium/content/public/browser/cookie_store_factory.h6
-rw-r--r--chromium/content/public/browser/desktop_media_id.cc13
-rw-r--r--chromium/content/public/browser/desktop_notification_delegate.h3
-rw-r--r--chromium/content/public/browser/devtools_agent_host.h75
-rw-r--r--chromium/content/public/browser/devtools_agent_host_client.h34
-rw-r--r--chromium/content/public/browser/devtools_client_host.h54
-rw-r--r--chromium/content/public/browser/devtools_frontend_host.h48
-rw-r--r--chromium/content/public/browser/devtools_frontend_host_delegate.h29
-rw-r--r--chromium/content/public/browser/devtools_http_handler.h31
-rw-r--r--chromium/content/public/browser/devtools_http_handler_delegate.h16
-rw-r--r--chromium/content/public/browser/devtools_manager.h65
-rw-r--r--chromium/content/public/browser/devtools_manager_delegate.h22
-rw-r--r--chromium/content/public/browser/download_interrupt_reason_values.h6
-rw-r--r--chromium/content/public/browser/download_item.h6
-rw-r--r--chromium/content/public/browser/download_manager.h2
-rw-r--r--chromium/content/public/browser/file_descriptor_info.h47
-rw-r--r--chromium/content/public/browser/gpu_data_manager.h12
-rw-r--r--chromium/content/public/browser/gpu_data_manager_observer.h3
-rw-r--r--chromium/content/public/browser/host_zoom_map.h13
-rw-r--r--chromium/content/public/browser/indexed_db_context.h4
-rw-r--r--chromium/content/public/browser/invalidate_type.h5
-rw-r--r--chromium/content/public/browser/load_from_memory_cache_details.cc2
-rw-r--r--chromium/content/public/browser/load_from_memory_cache_details.h6
-rw-r--r--chromium/content/public/browser/load_notification_details.h6
-rw-r--r--chromium/content/public/browser/media_device_id.cc2
-rw-r--r--chromium/content/public/browser/media_observer.h25
-rw-r--r--chromium/content/public/browser/navigation_controller.cc2
-rw-r--r--chromium/content/public/browser/navigation_controller.h14
-rw-r--r--chromium/content/public/browser/navigation_entry.h6
-rw-r--r--chromium/content/public/browser/page_navigator.cc6
-rw-r--r--chromium/content/public/browser/page_navigator.h8
-rw-r--r--chromium/content/public/browser/permission_type.h28
-rw-r--r--chromium/content/public/browser/push_messaging_service.h19
-rw-r--r--chromium/content/public/browser/quota_permission_context.h2
-rw-r--r--chromium/content/public/browser/render_frame_host.h27
-rw-r--r--chromium/content/public/browser/render_process_host.h24
-rw-r--r--chromium/content/public/browser/render_process_host_observer.h1
-rw-r--r--chromium/content/public/browser/render_view_host.h35
-rw-r--r--chromium/content/public/browser/render_widget_host.h47
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h19
-rw-r--r--chromium/content/public/browser/render_widget_host_view_frame_subscriber.h14
-rw-r--r--chromium/content/public/browser/resource_context.h18
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host_delegate.cc14
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host_delegate.h100
-rw-r--r--chromium/content/public/browser/resource_request_details.cc15
-rw-r--r--chromium/content/public/browser/resource_request_details.h6
-rw-r--r--chromium/content/public/browser/resource_request_info.h30
-rw-r--r--chromium/content/public/browser/resource_throttle.h2
-rw-r--r--chromium/content/public/browser/screen_orientation_delegate.h43
-rw-r--r--chromium/content/public/browser/screen_orientation_dispatcher_host.h36
-rw-r--r--chromium/content/public/browser/screen_orientation_provider.cc209
-rw-r--r--chromium/content/public/browser/screen_orientation_provider.h80
-rw-r--r--chromium/content/public/browser/service_worker_context.h26
-rw-r--r--chromium/content/public/browser/service_worker_usage_info.cc24
-rw-r--r--chromium/content/public/browser/service_worker_usage_info.h38
-rw-r--r--chromium/content/public/browser/site_instance.h5
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.cc1
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.h1
-rw-r--r--chromium/content/public/browser/ssl_host_state_delegate.h63
-rw-r--r--chromium/content/public/browser/storage_partition.h80
-rw-r--r--chromium/content/public/browser/stream_handle.h18
-rw-r--r--chromium/content/public/browser/stream_info.cc16
-rw-r--r--chromium/content/public/browser/stream_info.h47
-rw-r--r--chromium/content/public/browser/tracing_controller.h81
-rw-r--r--chromium/content/public/browser/url_data_source.cc5
-rw-r--r--chromium/content/public/browser/url_data_source.h9
-rw-r--r--chromium/content/public/browser/utility_process_host.h11
-rw-r--r--chromium/content/public/browser/web_contents.cc4
-rw-r--r--chromium/content/public/browser/web_contents.h69
-rw-r--r--chromium/content/public/browser/web_contents_delegate.cc17
-rw-r--r--chromium/content/public/browser/web_contents_delegate.h30
-rw-r--r--chromium/content/public/browser/web_contents_observer.h96
-rw-r--r--chromium/content/public/browser/web_contents_view_delegate.cc55
-rw-r--r--chromium/content/public/browser/web_contents_view_delegate.h66
-rw-r--r--chromium/content/public/browser/web_ui.h6
-rw-r--r--chromium/content/public/browser/web_ui_data_source.h4
-rw-r--r--chromium/content/public/browser/worker_service.h3
-rw-r--r--chromium/content/public/child/BUILD.gn14
-rw-r--r--chromium/content/public/child/request_peer.h16
-rw-r--r--chromium/content/public/child/resource_dispatcher_delegate.h16
-rw-r--r--chromium/content/public/common/BUILD.gn36
-rw-r--r--chromium/content/public/common/OWNERS9
-rw-r--r--chromium/content/public/common/appcache_info.h50
-rw-r--r--chromium/content/public/common/child_process_host.h5
-rw-r--r--chromium/content/public/common/child_process_host_delegate.h2
-rw-r--r--chromium/content/public/common/common_param_traits.cc252
-rw-r--r--chromium/content/public/common/common_param_traits.h86
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h30
-rw-r--r--chromium/content/public/common/content_client.cc4
-rw-r--r--chromium/content/public/common/content_client.h4
-rw-r--r--chromium/content/public/common/content_constants.cc1
-rw-r--r--chromium/content/public/common/content_constants.h1
-rw-r--r--chromium/content/public/common/content_descriptors.h6
-rw-r--r--chromium/content/public/common/content_switches.cc266
-rw-r--r--chromium/content/public/common/content_switches.h74
-rw-r--r--chromium/content/public/common/context_menu_params.h10
-rw-r--r--chromium/content/public/common/eme_codec.h37
-rw-r--r--chromium/content/public/common/file_chooser_file_info.cc15
-rw-r--r--chromium/content/public/common/file_chooser_file_info.h35
-rw-r--r--chromium/content/public/common/file_chooser_params.cc2
-rw-r--r--chromium/content/public/common/file_chooser_params.h3
-rw-r--r--chromium/content/public/common/frame_navigate_params.cc2
-rw-r--r--chromium/content/public/common/frame_navigate_params.h4
-rw-r--r--chromium/content/public/common/main_function_params.h4
-rw-r--r--chromium/content/public/common/manifest.cc37
-rw-r--r--chromium/content/public/common/manifest.h98
-rw-r--r--chromium/content/public/common/media_stream_request.cc4
-rw-r--r--chromium/content/public/common/media_stream_request.h34
-rw-r--r--chromium/content/public/common/mojo_geoposition.mojom56
-rw-r--r--chromium/content/public/common/page_transition_types.cc89
-rw-r--r--chromium/content/public/common/page_transition_types.h71
-rw-r--r--chromium/content/public/common/page_transition_types_list.h137
-rw-r--r--chromium/content/public/common/pepper_plugin_info.h4
-rw-r--r--chromium/content/public/common/process_type.h2
-rw-r--r--chromium/content/public/common/push_messaging_status.cc38
-rw-r--r--chromium/content/public/common/push_messaging_status.h64
-rw-r--r--chromium/content/public/common/referrer.h33
-rw-r--r--chromium/content/public/common/renderer_preferences.cc22
-rw-r--r--chromium/content/public/common/renderer_preferences.h28
-rw-r--r--chromium/content/public/common/request_context_frame_type.h20
-rw-r--r--chromium/content/public/common/request_context_type.h50
-rw-r--r--chromium/content/public/common/resource_devtools_info.cc11
-rw-r--r--chromium/content/public/common/resource_devtools_info.h8
-rw-r--r--chromium/content/public/common/resource_response.cc56
-rw-r--r--chromium/content/public/common/resource_response.h16
-rw-r--r--chromium/content/public/common/resource_response_info.cc10
-rw-r--r--chromium/content/public/common/resource_response_info.h30
-rw-r--r--chromium/content/public/common/resource_type.cc13
-rw-r--r--chromium/content/public/common/resource_type.h39
-rw-r--r--chromium/content/public/common/result_codes.h25
-rw-r--r--chromium/content/public/common/result_codes_list.h30
-rw-r--r--chromium/content/public/common/sandbox_init.h8
-rw-r--r--chromium/content/public/common/sandbox_type_mac.h6
-rw-r--r--chromium/content/public/common/sandboxed_process_launcher_delegate.h4
-rw-r--r--chromium/content/public/common/screen_orientation_values.h14
-rw-r--r--chromium/content/public/common/screen_orientation_values_list.h23
-rw-r--r--chromium/content/public/common/service_registry.h76
-rw-r--r--chromium/content/public/common/show_desktop_notification_params.h6
-rw-r--r--chromium/content/public/common/speech_recognition_error.h30
-rw-r--r--chromium/content/public/common/speech_recognition_error_list.h38
-rw-r--r--chromium/content/public/common/stop_find_action.h3
-rw-r--r--chromium/content/public/common/storage_quota_params.h6
-rw-r--r--chromium/content/public/common/three_d_api_types.h4
-rw-r--r--chromium/content/public/common/top_controls_state.h8
-rw-r--r--chromium/content/public/common/top_controls_state_list.h19
-rw-r--r--chromium/content/public/common/transition_element.h23
-rw-r--r--chromium/content/public/common/url_constants.cc4
-rw-r--r--chromium/content/public/common/url_constants.h4
-rw-r--r--chromium/content/public/common/web_preferences.cc196
-rw-r--r--chromium/content/public/common/web_preferences.h203
-rw-r--r--chromium/content/public/plugin/BUILD.gn19
-rw-r--r--chromium/content/public/renderer/BUILD.gn23
-rw-r--r--chromium/content/public/renderer/browser_plugin_delegate.h40
-rw-r--r--chromium/content/public/renderer/content_renderer_client.cc64
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h42
-rw-r--r--chromium/content/public/renderer/document_state.h6
-rw-r--r--chromium/content/public/renderer/key_system_info.cc17
-rw-r--r--chromium/content/public/renderer/key_system_info.h58
-rw-r--r--chromium/content/public/renderer/media_stream_audio_sink.cc12
-rw-r--r--chromium/content/public/renderer/media_stream_audio_sink.h2
-rw-r--r--chromium/content/public/renderer/media_stream_video_sink.h2
-rw-r--r--chromium/content/public/renderer/navigation_state.cc2
-rw-r--r--chromium/content/public/renderer/navigation_state.h14
-rw-r--r--chromium/content/public/renderer/platform_event_observer.h136
-rw-r--r--chromium/content/public/renderer/render_font_warmup_win.cc164
-rw-r--r--chromium/content/public/renderer/render_frame.h39
-rw-r--r--chromium/content/public/renderer/render_frame_observer.h11
-rw-r--r--chromium/content/public/renderer/render_thread.h6
-rw-r--r--chromium/content/public/renderer/render_view.h22
-rw-r--r--chromium/content/public/renderer/render_view_observer.h9
-rw-r--r--chromium/content/public/renderer/renderer_gamepad_provider.h19
-rw-r--r--chromium/content/public/renderer/renderer_ppapi_host.h2
-rw-r--r--chromium/content/public/renderer/resource_fetcher.h12
-rw-r--r--chromium/content/public/renderer/video_encode_accelerator.cc8
-rw-r--r--chromium/content/public/renderer/web_preferences.h23
-rw-r--r--chromium/content/public/utility/BUILD.gn21
-rw-r--r--chromium/content/public/utility/content_utility_client.h2
-rw-r--r--chromium/content/public/utility/utility_thread.h2
-rw-r--r--chromium/content/renderer/BUILD.gn96
-rw-r--r--chromium/content/renderer/DEPS4
-rw-r--r--chromium/content/renderer/OWNERS6
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc58
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.cc175
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.h49
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility.cc479
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility.h139
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc216
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_complete.cc399
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_complete.h105
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc155
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h75
-rw-r--r--chromium/content/renderer/active_notification_tracker.cc16
-rw-r--r--chromium/content/renderer/active_notification_tracker.h13
-rw-r--r--chromium/content/renderer/android/OWNERS1
-rw-r--r--chromium/content/renderer/android/address_detector.h6
-rw-r--r--chromium/content/renderer/android/email_detector.h6
-rw-r--r--chromium/content/renderer/android/phone_number_detector.h6
-rw-r--r--chromium/content/renderer/android/renderer_date_time_picker.cc96
-rw-r--r--chromium/content/renderer/android/renderer_date_time_picker.h46
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_factory.h14
-rw-r--r--chromium/content/renderer/battery_status/battery_status_dispatcher.cc57
-rw-r--r--chromium/content/renderer/battery_status/battery_status_dispatcher.h31
-rw-r--r--chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc67
-rw-r--r--chromium/content/renderer/battery_status/fake_battery_status_dispatcher.cc34
-rw-r--r--chromium/content/renderer/battery_status/fake_battery_status_dispatcher.h32
-rw-r--r--chromium/content/renderer/bmp_image_decoder_unittest.cc2
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc642
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h203
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc613
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_bindings.h71
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc384
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_browsertest.h50
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager.cc101
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager.h47
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager_factory.h21
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc59
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h44
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin.cc18
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin.h27
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc74
-rw-r--r--chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h59
-rw-r--r--chromium/content/renderer/browser_render_view_browsertest.cc20
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.cc315
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.h54
-rw-r--r--chromium/content/renderer/chrome_object_extensions_utils.cc26
-rw-r--r--chromium/content/renderer/chrome_object_extensions_utils.h17
-rw-r--r--chromium/content/renderer/compositor_bindings/OWNERS2
-rw-r--r--chromium/content/renderer/compositor_bindings/PRESUBMIT.py33
-rw-r--r--chromium/content/renderer/compositor_bindings/scrollbar_impl.cc109
-rw-r--r--chromium/content/renderer/compositor_bindings/scrollbar_impl.h51
-rw-r--r--chromium/content/renderer/compositor_bindings/web_animation_curve_common.cc29
-rw-r--r--chromium/content/renderer/compositor_bindings/web_animation_curve_common.h21
-rw-r--r--chromium/content/renderer/compositor_bindings/web_animation_impl.cc160
-rw-r--r--chromium/content/renderer/compositor_bindings/web_animation_impl.h59
-rw-r--r--chromium/content/renderer/compositor_bindings/web_animation_unittest.cc60
-rw-r--r--chromium/content/renderer/compositor_bindings/web_blend_mode.h107
-rw-r--r--chromium/content/renderer/compositor_bindings/web_compositor_support_impl.cc141
-rw-r--r--chromium/content/renderer/compositor_bindings/web_compositor_support_impl.h68
-rw-r--r--chromium/content/renderer/compositor_bindings/web_content_layer_impl.cc90
-rw-r--r--chromium/content/renderer/compositor_bindings/web_content_layer_impl.h62
-rw-r--r--chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.cc47
-rw-r--r--chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.h47
-rw-r--r--chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.cc130
-rw-r--r--chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.h73
-rw-r--r--chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.cc59
-rw-r--r--chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.h51
-rw-r--r--chromium/content/renderer/compositor_bindings/web_filter_operations_impl.cc96
-rw-r--r--chromium/content/renderer/compositor_bindings/web_filter_operations_impl.h50
-rw-r--r--chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.cc60
-rw-r--r--chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.h54
-rw-r--r--chromium/content/renderer/compositor_bindings/web_float_animation_curve_unittest.cc234
-rw-r--r--chromium/content/renderer/compositor_bindings/web_image_layer_impl.cc39
-rw-r--r--chromium/content/renderer/compositor_bindings/web_image_layer_impl.h35
-rw-r--r--chromium/content/renderer/compositor_bindings/web_layer_impl.cc489
-rw-r--r--chromium/content/renderer/compositor_bindings/web_layer_impl.h161
-rw-r--r--chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc101
-rw-r--r--chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h52
-rw-r--r--chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc181
-rw-r--r--chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.cc62
-rw-r--r--chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.h42
-rw-r--r--chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc55
-rw-r--r--chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h52
-rw-r--r--chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.cc74
-rw-r--r--chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.h48
-rw-r--r--chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.cc31
-rw-r--r--chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.h34
-rw-r--r--chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc33
-rw-r--r--chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h39
-rw-r--r--chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.cc63
-rw-r--r--chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.h53
-rw-r--r--chromium/content/renderer/compositor_bindings/web_transform_operations_impl.cc69
-rw-r--r--chromium/content/renderer/compositor_bindings/web_transform_operations_impl.h42
-rw-r--r--chromium/content/renderer/context_menu_params_builder.cc13
-rw-r--r--chromium/content/renderer/device_sensors/device_light_event_pump.cc82
-rw-r--r--chromium/content/renderer/device_sensors/device_light_event_pump.h56
-rw-r--r--chromium/content/renderer/device_sensors/device_light_event_pump_unittest.cc160
-rw-r--r--chromium/content/renderer/device_sensors/device_motion_event_pump.cc32
-rw-r--r--chromium/content/renderer/device_sensors/device_motion_event_pump.h30
-rw-r--r--chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc19
-rw-r--r--chromium/content/renderer/device_sensors/device_orientation_event_pump.cc33
-rw-r--r--chromium/content/renderer/device_sensors/device_orientation_event_pump.h30
-rw-r--r--chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc59
-rw-r--r--chromium/content/renderer/device_sensors/device_sensor_event_pump.cc87
-rw-r--r--chromium/content/renderer/device_sensors/device_sensor_event_pump.h80
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.cc53
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.h34
-rw-r--r--chromium/content/renderer/devtools/devtools_agent_filter.h4
-rw-r--r--chromium/content/renderer/devtools/devtools_client.cc18
-rw-r--r--chromium/content/renderer/devtools/devtools_client.h12
-rw-r--r--chromium/content/renderer/dom_automation_controller.h8
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc18
-rw-r--r--chromium/content/renderer/dom_storage/DEPS3
-rw-r--r--chromium/content/renderer/dom_storage/OWNERS1
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc45
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc40
-rw-r--r--chromium/content/renderer/dom_utils.cc22
-rw-r--r--chromium/content/renderer/dom_utils.h23
-rw-r--r--chromium/content/renderer/external_popup_menu.cc19
-rw-r--r--chromium/content/renderer/external_popup_menu.h6
-rw-r--r--chromium/content/renderer/external_popup_menu_browsertest.cc81
-rw-r--r--chromium/content/renderer/fetchers/image_resource_fetcher.cc9
-rw-r--r--chromium/content/renderer/fetchers/image_resource_fetcher.h13
-rw-r--r--chromium/content/renderer/fetchers/manifest_fetcher.cc49
-rw-r--r--chromium/content/renderer/fetchers/manifest_fetcher.h57
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc7
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h2
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.cc93
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.h59
-rw-r--r--chromium/content/renderer/fetchers/web_url_loader_client_impl.cc75
-rw-r--r--chromium/content/renderer/fetchers/web_url_loader_client_impl.h82
-rw-r--r--chromium/content/renderer/gamepad_shared_memory_reader.cc65
-rw-r--r--chromium/content/renderer/gamepad_shared_memory_reader.h31
-rw-r--r--chromium/content/renderer/geolocation_dispatcher.cc85
-rw-r--r--chromium/content/renderer/geolocation_dispatcher.h21
-rw-r--r--chromium/content/renderer/gin_browsertest.cc8
-rw-r--r--chromium/content/renderer/gpu/OWNERS1
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.cc50
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.h13
-rw-r--r--chromium/content/renderer/gpu/compositor_software_output_device.cc22
-rw-r--r--chromium/content/renderer/gpu/compositor_software_output_device.h18
-rw-r--r--chromium/content/renderer/gpu/delegated_compositor_output_surface.cc5
-rw-r--r--chromium/content/renderer/gpu/delegated_compositor_output_surface.h7
-rw-r--r--chromium/content/renderer/gpu/frame_swap_message_queue.cc201
-rw-r--r--chromium/content/renderer/gpu/frame_swap_message_queue.h108
-rw-r--r--chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc291
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.cc1223
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.h50
-rw-r--r--chromium/content/renderer/gpu/mailbox_output_surface.cc3
-rw-r--r--chromium/content/renderer/gpu/mailbox_output_surface.h19
-rw-r--r--chromium/content/renderer/gpu/queue_message_swap_promise.cc69
-rw-r--r--chromium/content/renderer/gpu/queue_message_swap_promise.h47
-rw-r--r--chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc322
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.cc312
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.h70
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_unittest.cc77
-rw-r--r--chromium/content/renderer/gpu/stream_texture_host_android.h4
-rw-r--r--chromium/content/renderer/history_controller.cc4
-rw-r--r--chromium/content/renderer/history_entry.cc38
-rw-r--r--chromium/content/renderer/history_serialization.cc7
-rw-r--r--chromium/content/renderer/ico_image_decoder_unittest.cc2
-rw-r--r--chromium/content/renderer/idle_user_detector.h4
-rw-r--r--chromium/content/renderer/image_loading_helper.cc6
-rw-r--r--chromium/content/renderer/image_loading_helper.h4
-rw-r--r--chromium/content/renderer/in_process_renderer_thread.h6
-rw-r--r--chromium/content/renderer/input/input_event_filter.cc24
-rw-r--r--chromium/content/renderer/input/input_event_filter.h33
-rw-r--r--chromium/content/renderer/input/input_event_filter_unittest.cc10
-rw-r--r--chromium/content/renderer/input/input_handler_proxy.cc163
-rw-r--r--chromium/content/renderer/input/input_handler_proxy.h32
-rw-r--r--chromium/content/renderer/input/input_handler_proxy_client.h2
-rw-r--r--chromium/content/renderer/input/input_handler_proxy_unittest.cc348
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.cc4
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.h17
-rw-r--r--chromium/content/renderer/input/input_scroll_elasticity_controller.cc473
-rw-r--r--chromium/content/renderer/input/input_scroll_elasticity_controller.h143
-rw-r--r--chromium/content/renderer/internal_document_state_data.h12
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_dispatcher.cc8
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_dispatcher.h8
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_object.cc18
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_object.h9
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter.cc5
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter.h8
-rw-r--r--chromium/content/renderer/java/java_bridge_channel.cc63
-rw-r--r--chromium/content/renderer/java/java_bridge_channel.h43
-rw-r--r--chromium/content/renderer/java/java_bridge_dispatcher.cc118
-rw-r--r--chromium/content/renderer/java/java_bridge_dispatcher.h52
-rw-r--r--chromium/content/renderer/manifest/OWNERS1
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.cc156
-rw-r--r--chromium/content/renderer/manifest/manifest_manager.h84
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.cc328
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.h33
-rw-r--r--chromium/content/renderer/manifest/manifest_parser_unittest.cc607
-rw-r--r--chromium/content/renderer/manifest/manifest_uma_util.cc78
-rw-r--r--chromium/content/renderer/manifest/manifest_uma_util.h37
-rw-r--r--chromium/content/renderer/media/OWNERS7
-rw-r--r--chromium/content/renderer/media/active_loader.cc26
-rw-r--r--chromium/content/renderer/media/active_loader.h42
-rw-r--r--chromium/content/renderer/media/aec_dump_message_filter.h10
-rw-r--r--chromium/content/renderer/media/android/OWNERS1
-rw-r--r--chromium/content/renderer/media/android/audio_decoder_android.cc6
-rw-r--r--chromium/content/renderer/media/android/media_info_loader.cc29
-rw-r--r--chromium/content/renderer/media/android/media_info_loader.h18
-rw-r--r--chromium/content/renderer/media/android/media_info_loader_unittest.cc8
-rw-r--r--chromium/content/renderer/media/android/media_source_delegate.cc135
-rw-r--r--chromium/content/renderer/media/android/media_source_delegate.h56
-rw-r--r--chromium/content/renderer/media/android/renderer_demuxer_android.cc13
-rw-r--r--chromium/content/renderer/media/android/renderer_demuxer_android.h6
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.cc39
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.h23
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory.h23
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_impl.cc81
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_impl.h13
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc124
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h18
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.cc632
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.h151
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.cc52
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.h10
-rw-r--r--chromium/content/renderer/media/audio_message_filter.cc28
-rw-r--r--chromium/content/renderer/media/audio_message_filter.h16
-rw-r--r--chromium/content/renderer/media/audio_message_filter_unittest.cc23
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.cc15
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.h24
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc56
-rw-r--r--chromium/content/renderer/media/buffered_data_source.cc537
-rw-r--r--chromium/content/renderer/media/buffered_data_source.h231
-rw-r--r--chromium/content/renderer/media/buffered_data_source_host_impl.cc56
-rw-r--r--chromium/content/renderer/media/buffered_data_source_host_impl.h51
-rw-r--r--chromium/content/renderer/media/buffered_data_source_host_impl_unittest.cc75
-rw-r--r--chromium/content/renderer/media/buffered_data_source_unittest.cc805
-rw-r--r--chromium/content/renderer/media/buffered_resource_loader.cc786
-rw-r--r--chromium/content/renderer/media/buffered_resource_loader.h323
-rw-r--r--chromium/content/renderer/media/buffered_resource_loader_unittest.cc1131
-rw-r--r--chromium/content/renderer/media/cache_util.cc87
-rw-r--r--chromium/content/renderer/media/cache_util.h41
-rw-r--r--chromium/content/renderer/media/cache_util_unittest.cc97
-rw-r--r--chromium/content/renderer/media/cdm_session_adapter.cc119
-rw-r--r--chromium/content/renderer/media/cdm_session_adapter.h74
-rw-r--r--chromium/content/renderer/media/crypto/content_decryption_module_factory.cc73
-rw-r--r--chromium/content/renderer/media/crypto/content_decryption_module_factory.h46
-rw-r--r--chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc475
-rw-r--r--chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h130
-rw-r--r--chromium/content/renderer/media/crypto/key_systems.cc285
-rw-r--r--chromium/content/renderer/media/crypto/key_systems.h18
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_support_uma.cc45
-rw-r--r--chromium/content/renderer/media/crypto/key_systems_unittest.cc27
-rw-r--r--chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc4
-rw-r--r--chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.h4
-rw-r--r--chromium/content/renderer/media/crypto/ppapi_decryptor.cc133
-rw-r--r--chromium/content/renderer/media/crypto/ppapi_decryptor.h102
-rw-r--r--chromium/content/renderer/media/crypto/proxy_decryptor.cc178
-rw-r--r--chromium/content/renderer/media/crypto/proxy_decryptor.h60
-rw-r--r--chromium/content/renderer/media/crypto/proxy_media_keys.cc48
-rw-r--r--chromium/content/renderer/media/crypto/proxy_media_keys.h27
-rw-r--r--chromium/content/renderer/media/crypto/render_cdm_factory.cc83
-rw-r--r--chromium/content/renderer/media/crypto/render_cdm_factory.h62
-rw-r--r--chromium/content/renderer/media/crypto/renderer_cdm_manager.cc4
-rw-r--r--chromium/content/renderer/media/crypto/renderer_cdm_manager.h4
-rw-r--r--chromium/content/renderer/media/media_stream.cc2
-rw-r--r--chromium/content/renderer/media/media_stream_audio_level_calculator.cc11
-rw-r--r--chromium/content/renderer/media/media_stream_audio_level_calculator.h8
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.cc498
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.h111
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.cc107
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.h30
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_unittest.cc132
-rw-r--r--chromium/content/renderer/media/media_stream_audio_sink_owner.h32
-rw-r--r--chromium/content/renderer/media/media_stream_audio_source.cc32
-rw-r--r--chromium/content/renderer/media/media_stream_audio_source.h14
-rw-r--r--chromium/content/renderer/media/media_stream_center.cc59
-rw-r--r--chromium/content/renderer/media/media_stream_center.h38
-rw-r--r--chromium/content/renderer/media/media_stream_constraints_util.cc7
-rw-r--r--chromium/content/renderer/media/media_stream_constraints_util.h8
-rw-r--r--chromium/content/renderer/media/media_stream_constraints_util_unittest.cc42
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher.cc61
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher.h32
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher_unittest.cc101
-rw-r--r--chromium/content/renderer/media/media_stream_impl.cc938
-rw-r--r--chromium/content/renderer/media/media_stream_impl.h245
-rw-r--r--chromium/content/renderer/media/media_stream_impl_unittest.cc475
-rw-r--r--chromium/content/renderer/media/media_stream_renderer_factory.cc1
-rw-r--r--chromium/content/renderer/media/media_stream_source.h4
-rw-r--r--chromium/content/renderer/media/media_stream_track.cc24
-rw-r--r--chromium/content/renderer/media/media_stream_track.h25
-rw-r--r--chromium/content/renderer/media/media_stream_video_capture_source_unittest.cc39
-rw-r--r--chromium/content/renderer/media/media_stream_video_capturer_source.cc43
-rw-r--r--chromium/content/renderer/media/media_stream_video_capturer_source.h27
-rw-r--r--chromium/content/renderer/media/media_stream_video_source.cc123
-rw-r--r--chromium/content/renderer/media/media_stream_video_source.h21
-rw-r--r--chromium/content/renderer/media/media_stream_video_source_unittest.cc122
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.cc233
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.h19
-rw-r--r--chromium/content/renderer/media/media_stream_video_track_unittest.cc31
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.cc11
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.h2
-rw-r--r--chromium/content/renderer/media/midi_message_filter.cc272
-rw-r--r--chromium/content/renderer/media/midi_message_filter.h79
-rw-r--r--chromium/content/renderer/media/mock_media_stream_dispatcher.cc14
-rw-r--r--chromium/content/renderer/media/mock_media_stream_dispatcher.h27
-rw-r--r--chromium/content/renderer/media/mock_media_stream_registry.h3
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_sink.cc1
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_sink.h6
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_source.cc13
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_source.h24
-rw-r--r--chromium/content/renderer/media/mock_peer_connection_impl.cc160
-rw-r--r--chromium/content/renderer/media/mock_peer_connection_impl.h58
-rw-r--r--chromium/content/renderer/media/native_handle_impl.h4
-rw-r--r--chromium/content/renderer/media/peer_connection_audio_sink_owner.h32
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_service.cc105
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_service.h23
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker.cc181
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker.h24
-rw-r--r--chromium/content/renderer/media/preload.h25
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.cc493
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.h81
-rw-r--r--chromium/content/renderer/media/render_media_log.h4
-rw-r--r--chromium/content/renderer/media/render_media_log_unittest.cc2
-rw-r--r--chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc101
-rw-r--r--chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h45
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.h5
-rw-r--r--chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc2
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler.cc170
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler.h89
-rw-r--r--chromium/content/renderer/media/rtc_dtmf_sender_handler.cc39
-rw-r--r--chromium/content/renderer/media/rtc_dtmf_sender_handler.h22
-rw-r--r--chromium/content/renderer/media/rtc_media_constraints.h6
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.cc1087
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.h134
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc297
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder.cc68
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder.h64
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_factory.h8
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_unittest.cc38
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder.cc143
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder.h40
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder_factory.cc70
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder_factory.h12
-rw-r--r--chromium/content/renderer/media/rtc_video_renderer.cc8
-rw-r--r--chromium/content/renderer/media/rtc_video_renderer.h15
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink.cc190
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink.h121
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc514
-rw-r--r--chromium/content/renderer/media/test_response_generator.cc101
-rw-r--r--chromium/content/renderer/media/test_response_generator.h66
-rw-r--r--chromium/content/renderer/media/texttrack_impl.cc70
-rw-r--r--chromium/content/renderer/media/texttrack_impl.h62
-rw-r--r--chromium/content/renderer/media/user_media_client_impl.cc1070
-rw-r--r--chromium/content/renderer/media/user_media_client_impl.h258
-rw-r--r--chromium/content/renderer/media/user_media_client_impl_unittest.cc580
-rw-r--r--chromium/content/renderer/media/video_capture_impl.cc28
-rw-r--r--chromium/content/renderer/media/video_capture_impl.h39
-rw-r--r--chromium/content/renderer/media/video_capture_impl_manager_unittest.cc10
-rw-r--r--chromium/content/renderer/media/video_capture_impl_unittest.cc6
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter.cc12
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter.h12
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter_unittest.cc10
-rw-r--r--chromium/content/renderer/media/video_frame_compositor.cc77
-rw-r--r--chromium/content/renderer/media/video_frame_compositor.h71
-rw-r--r--chromium/content/renderer/media/video_frame_compositor_unittest.cc162
-rw-r--r--chromium/content/renderer/media/video_frame_deliverer.cc84
-rw-r--r--chromium/content/renderer/media/video_frame_deliverer.h82
-rw-r--r--chromium/content/renderer/media/video_source_handler.cc4
-rw-r--r--chromium/content/renderer/media/video_source_handler.h2
-rw-r--r--chromium/content/renderer/media/video_source_handler_unittest.cc21
-rw-r--r--chromium/content/renderer/media/video_track_adapter.cc239
-rw-r--r--chromium/content/renderer/media/video_track_adapter.h43
-rw-r--r--chromium/content/renderer/media/webaudio_capturer_source.cc4
-rw-r--r--chromium/content/renderer/media/webaudio_capturer_source.h4
-rw-r--r--chromium/content/renderer/media/webaudiosourceprovider_impl.cc189
-rw-r--r--chromium/content/renderer/media/webaudiosourceprovider_impl.h90
-rw-r--r--chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc240
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc52
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodule_impl.h20
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc193
-rw-r--r--chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h31
-rw-r--r--chromium/content/renderer/media/webinbandtexttrack_impl.cc58
-rw-r--r--chromium/content/renderer/media/webinbandtexttrack_impl.h45
-rw-r--r--chromium/content/renderer/media/webmediaplayer_delegate.h34
-rw-r--r--chromium/content/renderer/media/webmediaplayer_impl.cc1354
-rw-r--r--chromium/content/renderer/media/webmediaplayer_impl.h355
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.cc44
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.h28
-rw-r--r--chromium/content/renderer/media/webmediaplayer_params.cc20
-rw-r--r--chromium/content/renderer/media/webmediaplayer_params.h44
-rw-r--r--chromium/content/renderer/media/webmediaplayer_util.cc119
-rw-r--r--chromium/content/renderer/media/webmediaplayer_util.h34
-rw-r--r--chromium/content/renderer/media/webmediasource_impl.cc86
-rw-r--r--chromium/content/renderer/media/webmediasource_impl.h44
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc152
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h75
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc55
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc140
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc155
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc94
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h153
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc211
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h28
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/video_destination_handler.cc36
-rw-r--r--chromium/content/renderer/media/webrtc/video_destination_handler.h16
-rw-r--r--chromium/content/renderer/media/webrtc/video_destination_handler_unittest.cc15
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h12
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc60
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h39
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc8
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h6
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc30
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc409
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h31
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_track_adapter.h4
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer.cc117
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer.h19
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc14
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.cc153
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.h101
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_not_impl.h143
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.cc206
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.h33
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc42
-rw-r--r--chromium/content/renderer/media/webrtc_identity_service.h4
-rw-r--r--chromium/content/renderer/media/webrtc_identity_service_unittest.cc4
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_renderer.cc120
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_renderer.h37
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.cc2
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.h22
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc15
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track.cc46
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track.h17
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc60
-rw-r--r--chromium/content/renderer/media/webrtc_logging.cc4
-rw-r--r--chromium/content/renderer/media/webrtc_uma_histograms.cc11
-rw-r--r--chromium/content/renderer/media/webrtc_uma_histograms.h18
-rw-r--r--chromium/content/renderer/media/websourcebuffer_impl.cc134
-rw-r--r--chromium/content/renderer/media/websourcebuffer_impl.h57
-rw-r--r--chromium/content/renderer/memory_benchmarking_extension.cc10
-rw-r--r--chromium/content/renderer/memory_benchmarking_extension.h6
-rw-r--r--chromium/content/renderer/message_delivery_policy.h25
-rw-r--r--chromium/content/renderer/mhtml_generator.h4
-rw-r--r--chromium/content/renderer/mojo/service_registry_js_wrapper.cc52
-rw-r--r--chromium/content/renderer/mojo/service_registry_js_wrapper.h51
-rw-r--r--chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc4
-rw-r--r--chromium/content/renderer/net_info_helper.cc2
-rw-r--r--chromium/content/renderer/notification_icon_loader.cc83
-rw-r--r--chromium/content/renderer/notification_icon_loader.h73
-rw-r--r--chromium/content/renderer/notification_permission_dispatcher.cc52
-rw-r--r--chromium/content/renderer/notification_permission_dispatcher.h50
-rw-r--r--chromium/content/renderer/notification_provider.cc107
-rw-r--r--chromium/content/renderer/notification_provider.h29
-rw-r--r--chromium/content/renderer/npapi/plugin_channel_host.h16
-rw-r--r--chromium/content/renderer/npapi/webplugin_delegate_proxy.cc59
-rw-r--r--chromium/content/renderer/npapi/webplugin_delegate_proxy.h107
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl.cc28
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl.h112
-rw-r--r--chromium/content/renderer/p2p/OWNERS1
-rw-r--r--chromium/content/renderer/p2p/host_address_request.cc4
-rw-r--r--chromium/content/renderer/p2p/host_address_request.h8
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.cc83
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.h21
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager_unittest.cc115
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.cc266
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.h41
-rw-r--r--chromium/content/renderer/p2p/network_list_manager.h38
-rw-r--r--chromium/content/renderer/p2p/port_allocator.cc215
-rw-r--r--chromium/content/renderer/p2p/port_allocator.h67
-rw-r--r--chromium/content/renderer/p2p/socket_client.h4
-rw-r--r--chromium/content/renderer/p2p/socket_client_delegate.h3
-rw-r--r--chromium/content/renderer/p2p/socket_client_impl.cc16
-rw-r--r--chromium/content/renderer/p2p/socket_client_impl.h26
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.cc6
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.h32
-rw-r--r--chromium/content/renderer/pepper/OWNERS1
-rw-r--r--chromium/content/renderer/pepper/audio_helper.cc1
-rw-r--r--chromium/content/renderer/pepper/common.h19
-rw-r--r--chromium/content/renderer/pepper/content_decryptor_delegate.cc186
-rw-r--r--chromium/content/renderer/pepper/content_decryptor_delegate.h34
-rw-r--r--chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc83
-rw-r--r--chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h6
-rw-r--r--chromium/content/renderer/pepper/event_conversion.cc155
-rw-r--r--chromium/content/renderer/pepper/event_conversion.h9
-rw-r--r--chromium/content/renderer/pepper/event_conversion_unittest.cc145
-rw-r--r--chromium/content/renderer/pepper/fake_pepper_plugin_instance.h48
-rw-r--r--chromium/content/renderer/pepper/host_array_buffer_var.h15
-rw-r--r--chromium/content/renderer/pepper/host_dispatcher_wrapper.cc13
-rw-r--r--chromium/content/renderer/pepper/host_dispatcher_wrapper.h7
-rw-r--r--chromium/content/renderer/pepper/host_globals.h45
-rw-r--r--chromium/content/renderer/pepper/host_resource_var.h12
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker.cc154
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker.h110
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker_unittest.cc129
-rw-r--r--chromium/content/renderer/pepper/message_channel.cc699
-rw-r--r--chromium/content/renderer/pepper/message_channel.h162
-rw-r--r--chromium/content/renderer/pepper/mock_renderer_ppapi_host.h48
-rw-r--r--chromium/content/renderer/pepper/mock_resource.h2
-rw-r--r--chromium/content/renderer/pepper/npapi_glue.cc358
-rw-r--r--chromium/content/renderer/pepper/npapi_glue.h262
-rw-r--r--chromium/content/renderer/pepper/npobject_var.cc52
-rw-r--r--chromium/content/renderer/pepper/npobject_var.h71
-rw-r--r--chromium/content/renderer/pepper/pepper_audio_input_host.cc24
-rw-r--r--chromium/content/renderer/pepper/pepper_audio_input_host.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_broker.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_browser_connection.h4
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.cc20
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.h8
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc5
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h5
-rw-r--r--chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc19
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.cc13
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc12
-rw-r--r--chromium/content/renderer/pepper/pepper_file_ref_renderer_host.h8
-rw-r--r--chromium/content/renderer/pepper/pepper_file_system_host.cc13
-rw-r--r--chromium/content/renderer/pepper/pepper_file_system_host.h8
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc45
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.h21
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc7
-rw-r--r--chromium/content/renderer/pepper/pepper_hung_plugin_filter.h19
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc5
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_resource_creation.h42
-rw-r--r--chromium/content/renderer/pepper/pepper_in_process_router.cc6
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.cc68
-rw-r--r--chromium/content/renderer/pepper/pepper_media_device_manager.h58
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc206
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.h71
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_track_host_base.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc14
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h31
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_input.cc58
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_input.h28
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_audio_output.h13
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.cc43
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.h9
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc600
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.h375
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_throttler.cc30
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_throttler.h29
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_registry.cc1
-rw-r--r--chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h10
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font.h50
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_android.cc17
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_host.cc93
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_host.h50
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_linux.cc159
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_mac.mm408
-rw-r--r--chromium/content/renderer/pepper/pepper_truetype_font_win.cc245
-rw-r--r--chromium/content/renderer/pepper/pepper_try_catch.cc173
-rw-r--r--chromium/content/renderer/pepper/pepper_try_catch.h108
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.cc6
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_url_request_unittest.cc10
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.cc20
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.cc51
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.h26
-rw-r--r--chromium/content/renderer/pepper/pepper_video_destination_host.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_video_source_host.cc133
-rw-r--r--chromium/content/renderer/pepper/pepper_video_source_host.h26
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.cc29
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.h20
-rw-r--r--chromium/content/renderer/pepper/pepper_websocket_host.cc4
-rw-r--r--chromium/content/renderer/pepper/pepper_websocket_host.h4
-rw-r--r--chromium/content/renderer/pepper/plugin_module.cc37
-rw-r--r--chromium/content/renderer/pepper/plugin_module.h5
-rw-r--r--chromium/content/renderer/pepper/plugin_object.cc479
-rw-r--r--chromium/content/renderer/pepper/plugin_object.h89
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.cc157
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.h77
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc116
-rw-r--r--chromium/content/renderer/pepper/ppapi_preferences_builder.cc32
-rw-r--r--chromium/content/renderer/pepper/ppapi_preferences_builder.h23
-rw-r--r--chromium/content/renderer/pepper/ppb_audio_impl.cc3
-rw-r--r--chromium/content/renderer/pepper/ppb_audio_impl.h25
-rw-r--r--chromium/content/renderer/pepper/ppb_broker_impl.cc1
-rw-r--r--chromium/content/renderer/pepper/ppb_broker_impl.h12
-rw-r--r--chromium/content/renderer/pepper/ppb_buffer_impl.cc2
-rw-r--r--chromium/content/renderer/pepper/ppb_buffer_impl.h14
-rw-r--r--chromium/content/renderer/pepper/ppb_flash_message_loop_impl.h13
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc41
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.h52
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.cc5
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.h74
-rw-r--r--chromium/content/renderer/pepper/ppb_scrollbar_impl.cc2
-rw-r--r--chromium/content/renderer/pepper/ppb_scrollbar_impl.h37
-rw-r--r--chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc468
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.cc7
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.h40
-rw-r--r--chromium/content/renderer/pepper/ppb_widget_impl.h14
-rw-r--r--chromium/content/renderer/pepper/renderer_ppapi_host_impl.h48
-rw-r--r--chromium/content/renderer/pepper/resource_converter.cc32
-rw-r--r--chromium/content/renderer/pepper/resource_converter.h28
-rw-r--r--chromium/content/renderer/pepper/resource_creation_impl.cc30
-rw-r--r--chromium/content/renderer/pepper/resource_creation_impl.h221
-rw-r--r--chromium/content/renderer/pepper/url_request_info_util.cc69
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc7
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc7
-rw-r--r--chromium/content/renderer/pepper/usb_key_code_conversion_win.cc6
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter.cc74
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter.h15
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter_unittest.cc28
-rw-r--r--chromium/content/renderer/pepper/v8object_var.cc62
-rw-r--r--chromium/content/renderer/pepper/v8object_var.h66
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.cc64
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.h28
-rw-r--r--chromium/content/renderer/push_messaging_dispatcher.cc87
-rw-r--r--chromium/content/renderer/push_messaging_dispatcher.h36
-rw-r--r--chromium/content/renderer/push_permission_dispatcher.cc48
-rw-r--r--chromium/content/renderer/push_permission_dispatcher.h41
-rw-r--r--chromium/content/renderer/render_font_warmup_win.cc204
-rw-r--r--chromium/content/renderer/render_frame_impl.cc1531
-rw-r--r--chromium/content/renderer/render_frame_impl.h333
-rw-r--r--chromium/content/renderer/render_frame_impl_unittest.cc41
-rw-r--r--chromium/content/renderer/render_frame_proxy.cc240
-rw-r--r--chromium/content/renderer/render_frame_proxy.h81
-rw-r--r--chromium/content/renderer/render_process.h2
-rw-r--r--chromium/content/renderer/render_process_impl.cc9
-rw-r--r--chromium/content/renderer/render_process_impl.h6
-rw-r--r--chromium/content/renderer/render_thread_impl.cc536
-rw-r--r--chromium/content/renderer/render_thread_impl.h180
-rw-r--r--chromium/content/renderer/render_thread_impl_browsertest.cc69
-rw-r--r--chromium/content/renderer/render_thread_impl_unittest.cc5
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc562
-rw-r--r--chromium/content/renderer/render_view_browsertest_mac.mm4
-rw-r--r--chromium/content/renderer/render_view_impl.cc1042
-rw-r--r--chromium/content/renderer/render_view_impl.h281
-rw-r--r--chromium/content/renderer/render_view_impl_android.cc15
-rw-r--r--chromium/content/renderer/render_view_impl_params.cc6
-rw-r--r--chromium/content/renderer/render_view_impl_params.h7
-rw-r--r--chromium/content/renderer/render_view_linux.cc116
-rw-r--r--chromium/content/renderer/render_view_mouse_lock_dispatcher.h8
-rw-r--r--chromium/content/renderer/render_widget.cc427
-rw-r--r--chromium/content/renderer/render_widget.h105
-rw-r--r--chromium/content/renderer/render_widget_fullscreen.h2
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.cc7
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.h30
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc8
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.cc1233
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.h264
-rw-r--r--chromium/content/renderer/renderer_clipboard_client.cc14
-rw-r--r--chromium/content/renderer/renderer_clipboard_client.h43
-rw-r--r--chromium/content/renderer/renderer_date_time_picker.cc100
-rw-r--r--chromium/content/renderer/renderer_date_time_picker.h46
-rw-r--r--chromium/content/renderer/renderer_font_platform_win.cc423
-rw-r--r--chromium/content/renderer/renderer_font_platform_win.h17
-rw-r--r--chromium/content/renderer/renderer_main.cc46
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_linux.cc2
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_win.cc6
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.cc5
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.h10
-rw-r--r--chromium/content/renderer/renderer_webcolorchooser_impl.h4
-rw-r--r--chromium/content/renderer/renderer_webcookiejar_impl.cc2
-rw-r--r--chromium/content/renderer/renderer_webkitplatformsupport_impl.cc1151
-rw-r--r--chromium/content/renderer/renderer_webkitplatformsupport_impl.h240
-rw-r--r--chromium/content/renderer/resource_fetcher_browsertest.cc43
-rw-r--r--chromium/content/renderer/savable_resources.cc6
-rw-r--r--chromium/content/renderer/savable_resources_browsertest.cc2
-rw-r--r--chromium/content/renderer/scheduler/null_renderer_scheduler.cc79
-rw-r--r--chromium/content/renderer/scheduler/null_renderer_scheduler.h36
-rw-r--r--chromium/content/renderer/scheduler/renderer_scheduler.cc23
-rw-r--r--chromium/content/renderer/scheduler/renderer_scheduler.h63
-rw-r--r--chromium/content/renderer/scheduler/renderer_scheduler_impl.cc218
-rw-r--r--chromium/content/renderer/scheduler/renderer_scheduler_impl.h128
-rw-r--r--chromium/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc411
-rw-r--r--chromium/content/renderer/scheduler/renderer_task_queue_selector.cc122
-rw-r--r--chromium/content/renderer/scheduler/renderer_task_queue_selector.h91
-rw-r--r--chromium/content/renderer/scheduler/renderer_task_queue_selector_unittest.cc201
-rw-r--r--chromium/content/renderer/scheduler/single_thread_idle_task_runner.cc38
-rw-r--r--chromium/content/renderer/scheduler/single_thread_idle_task_runner.h49
-rw-r--r--chromium/content/renderer/scheduler/task_queue_manager.cc294
-rw-r--r--chromium/content/renderer/scheduler/task_queue_manager.h118
-rw-r--r--chromium/content/renderer/scheduler/task_queue_manager_unittest.cc358
-rw-r--r--chromium/content/renderer/scheduler/task_queue_selector.h37
-rw-r--r--chromium/content/renderer/scheduler/web_scheduler_impl.cc45
-rw-r--r--chromium/content/renderer/scheduler/web_scheduler_impl.h38
-rw-r--r--chromium/content/renderer/scoped_clipboard_writer_glue.cc11
-rw-r--r--chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.cc97
-rw-r--r--chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.h50
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc13
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h12
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc93
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_observer.cc33
-rw-r--r--chromium/content/renderer/screen_orientation/screen_orientation_observer.h32
-rw-r--r--chromium/content/renderer/service_worker/OWNERS1
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_context_client.cc75
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_context_client.h17
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_context_message_filter.h9
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc11
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_devtools_agent.h5
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc26
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_dispatcher.h11
-rw-r--r--chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc542
-rw-r--r--chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.h159
-rw-r--r--chromium/content/renderer/service_worker/service_worker_script_context.cc110
-rw-r--r--chromium/content/renderer/service_worker/service_worker_script_context.h32
-rw-r--r--chromium/content/renderer/shared_memory_seqlock_reader.cc2
-rw-r--r--chromium/content/renderer/shared_memory_seqlock_reader.h3
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc15
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h27
-rw-r--r--chromium/content/renderer/shared_worker_repository.cc2
-rw-r--r--chromium/content/renderer/shared_worker_repository.h6
-rw-r--r--chromium/content/renderer/skia_benchmarking_extension.cc17
-rw-r--r--chromium/content/renderer/skia_benchmarking_extension.h6
-rw-r--r--chromium/content/renderer/skia_benchmarking_extension_unittest.cc2
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.cc75
-rw-r--r--chromium/content/renderer/speech_recognition_dispatcher.h34
-rw-r--r--chromium/content/renderer/stats_collection_controller.cc5
-rw-r--r--chromium/content/renderer/stats_collection_controller.h6
-rw-r--r--chromium/content/renderer/stats_collection_observer.h6
-rw-r--r--chromium/content/renderer/text_input_client_observer.h4
-rw-r--r--chromium/content/renderer/v8_value_converter_impl.h19
-rw-r--r--chromium/content/renderer/v8_value_converter_impl_unittest.cc66
-rw-r--r--chromium/content/renderer/web_preferences.cc340
-rw-r--r--chromium/content/renderer/web_ui_extension.cc10
-rw-r--r--chromium/content/renderer/web_ui_extension_data.h4
-rw-r--r--chromium/content/renderer/web_ui_mojo.cc25
-rw-r--r--chromium/content/renderer/web_ui_mojo.h33
-rw-r--r--chromium/content/renderer/web_ui_mojo_context_state.cc26
-rw-r--r--chromium/content/renderer/web_ui_mojo_context_state.h10
-rw-r--r--chromium/content/renderer/web_ui_runner.cc16
-rw-r--r--chromium/content/renderer/web_ui_runner.h18
-rw-r--r--chromium/content/renderer/web_ui_setup_impl.cc33
-rw-r--r--chromium/content/renderer/web_ui_setup_impl.h32
-rw-r--r--chromium/content/renderer/webclipboard_impl.cc2
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.h4
-rw-r--r--chromium/content/renderer/webscrollbarbehavior_impl_gtkoraura.cc18
-rw-r--r--chromium/content/renderer/websharedworker_proxy.h2
-rw-r--r--chromium/content/utility/BUILD.gn8
-rw-r--r--chromium/content/utility/in_process_utility_thread.cc3
-rw-r--r--chromium/content/utility/in_process_utility_thread.h6
-rw-r--r--chromium/content/utility/utility_main.cc3
-rw-r--r--chromium/content/utility/utility_thread_impl.cc19
-rw-r--r--chromium/content/utility/utility_thread_impl.h20
-rw-r--r--chromium/content/worker/BUILD.gn34
-rw-r--r--chromium/content/worker/DEPS6
-rw-r--r--chromium/content/worker/OWNERS3
-rw-r--r--chromium/content/worker/shared_worker_permission_client_proxy.cc61
-rw-r--r--chromium/content/worker/shared_worker_permission_client_proxy.h47
-rw-r--r--chromium/content/worker/websharedworker_stub.cc146
-rw-r--r--chromium/content/worker/websharedworker_stub.h84
-rw-r--r--chromium/content/worker/websharedworkerclient_proxy.cc139
-rw-r--r--chromium/content/worker/websharedworkerclient_proxy.h75
-rw-r--r--chromium/content/worker/worker_main.cc74
-rw-r--r--chromium/content/worker/worker_thread.cc148
-rw-r--r--chromium/content/worker/worker_thread.h59
-rw-r--r--chromium/content/worker/worker_webapplicationcachehost_impl.cc42
-rw-r--r--chromium/content/worker/worker_webapplicationcachehost_impl.h36
-rw-r--r--chromium/content/worker/worker_webkitplatformsupport_impl.cc315
-rw-r--r--chromium/content/worker/worker_webkitplatformsupport_impl.h128
-rw-r--r--chromium/content/zygote/OWNERS3
-rw-r--r--chromium/content/zygote/zygote_linux.cc2
-rw-r--r--chromium/content/zygote/zygote_main_linux.cc62
3281 files changed, 177094 insertions, 109214 deletions
diff --git a/chromium/content/BUILD.gn b/chromium/content/BUILD.gn
index 20a553e70a8..7f246689419 100644
--- a/chromium/content/BUILD.gn
+++ b/chromium/content/BUILD.gn
@@ -9,117 +9,75 @@ config("content_implementation") {
defines = [ "CONTENT_IMPLEMENTATION" ]
}
-content_components = [
- "//content/app",
- "//content/browser",
- "//content/child",
+# When targets depend on, e.g. //content/public/browser, what happens? To
+# facilitate the complexity here, the "public" targets are groups that forward
+# to the right thing depending on the build mode. Say for additional
+# illustration, the public browser sources also depend on the public common
+# ones.
+#
+# The non-component build is easy:
+# foo ->
+# //content/public/browser (group) ->
+# //content/public/browser:browser_sources (source set) ->
+# //content/browser (source set, this is the non-public browser target)
+# //content/public/common:common_sources (source set)
+#
+# The component build is more complicated because we want everybody to depend on
+# one content shared library regardless of which public target they depend on:
+# foo ->
+# //content/public/browser (group) ->
+# //content (shared library) ->
+# //content/public/browser:browser_sources (source set) ->
+# //content/browser (source set; this is the non-public browser target)
+# //content/public/common:common_sources (source set)
+#
+# That the internal content dependencies must depend on the *_sources targets
+# to avoid dependency cycles, and external dependencies must depend on the
+# //content/public/browser and similar targets to avoid double-linking (these
+# targets make sure the dependency goes through the content shared library
+# when doing a component build).
+
+content_shared_components = [
"//content/gpu",
- "//content/plugin",
- "//content/ppapi_plugin",
- "//content/public/app",
- "//content/public/browser",
- "//content/public/child",
- "//content/public/plugin",
- "//content/public/renderer",
- "//content/renderer",
- "//content/utility",
- "//content/worker",
+ "//content/public/browser:browser_sources",
+ "//content/public/child:child_sources",
+ "//content/public/common:common_sources",
+ "//content/public/plugin:plugin_sources",
+ "//content/public/renderer:renderer_sources",
+ "//content/public/utility:utility_sources",
]
+if (enable_plugins) {
+ content_shared_components += [ "//content/ppapi_plugin" ]
+}
+
if (is_component_build) {
shared_library("content") {
- deps = content_components
+ public_deps = content_shared_components + [
+ "//content/public/app:both_sources",
+ ]
}
} else {
group("content") {
- deps = content_components
+ deps = content_shared_components
}
}
grit("resources") {
source = "content_resources.grd"
+ use_qualified_include = true
+ outputs = [
+ "grit/content_resources.h",
+ "content_resources.pak",
+ "content_resources.rc",
+ ]
}
# This target exists to "hold" the content_export header so we can do proper
# inclusion testing of it.
source_set("export") {
- visibility = "//content/*"
+ visibility = [ "//content/*" ]
sources = [
"content/common/content_export.h"
]
}
-
-# Stubs ------------------------------------------------------------------------
-
-# TODO(brettw) remove this and add a proper dependency on libjingle once that
-# target has been converted to GN. This config sets up the include directories
-# so content can compile in the meantime.
-config("libjingle_stub_config") {
- include_dirs = [
- "//third_party/libjingle/overrides",
- "//third_party/libjingle/source",
- "//third_party/libyuv/include",
- "//third_party/usrsctp",
-
-
- "//third_party/webrtc/overrides", # Must be before webrtc abd third_party.
- "//third_party/webrtc",
- "//third_party",
- ]
-
- defines = [
- "FEATURE_ENABLE_SSL",
- "FEATURE_ENABLE_VOICEMAIL",
- "EXPAT_RELATIVE_PATH",
- "GTEST_RELATIVE_PATH",
- "NO_MAIN_THREAD_WRAPPING",
- "NO_SOUND_SYSTEM",
- ]
-
- if (is_mac) {
- defines += [ "OSX" ]
- } else if (is_linux) {
- defines += [ "LINUX" ]
- } else if (is_android) {
- defines += [ "ANDROID" ]
- } else if (is_win) {
- libs = [ "secur32.lib", "crypt32.lib", "iphlpapi.lib" ]
- }
-
- if (is_posix) {
- defines += [ "POSIX" ]
- }
- if (is_chromeos) {
- defines += [ "CHROMEOS" ]
- }
-}
-
-# Sets up include dirs while webrtc is being converted to GN.
-# TODO(GYP) remove when webrtc is ready.
-config("webrtc_stub_config") {
- defines = [ "WEBRTC_CHROMIUM_BUILD" ]
- include_dirs = [
- "//third_party/webrtc/overrides", # Must be first.
- "//third_party",
- ]
-
- if (is_mac) {
- defines += [ "WEBRTC_MAC" ]
- } else if (is_win) {
- defines += [ "WEBRTC_WIN" ]
- } else if (is_linux) {
- defines += [ "WEBRTC_LINUX" ]
- } else if (is_ios) {
- defines += [ "WEBRTC_MAC", "WEBRTC_IOS" ]
- } else if (is_android) {
- defines += [ "WEBRTC_LINUX", "WEBRTC_ANDROID" ]
- import("//build/config/crypto.gni")
- if (use_openssl) {
- defines += [ "WEBRTC_ANDROID_OPENSLEQS" ]
- }
- }
-
- if (is_posix) {
- defines += [ "WEBRTC_POSIX" ]
- }
-}
diff --git a/chromium/content/DEPS b/chromium/content/DEPS
index e697611c53d..d3543fc43d6 100644
--- a/chromium/content/DEPS
+++ b/chromium/content/DEPS
@@ -4,7 +4,9 @@ include_rules = [
# The subdirectories in content/ will manually allow their own include
# directories in content/ so we disallow all of them.
"-content",
+ "+content/app/resources/grit/content_resources.h",
"+content/common",
+ "+content/grit",
"+content/public/common",
"+content/public/test",
"+content/shell", # for content_browsertests
@@ -15,7 +17,10 @@ include_rules = [
# being used as a parallel API to the Content API.
"-base/prefs",
+ "+blink",
+
"+cc",
+ "-cc/blink",
# If you want to use any of these files, move them to src/base first.
"-cc/base/scoped_ptr_algorithm.h",
"-cc/base/scoped_ptr_deque.h",
@@ -23,21 +28,15 @@ include_rules = [
"+crypto",
"+grit/blink_resources.h",
- "+grit/content_resources.h",
- "+grit/ui_resources.h",
- "+grit/ui_strings.h",
- "+grit/webkit_resources.h",
- "+grit/webkit_strings.h",
- "+grit/webui_resources.h",
- "+grit/webui_resources_map.h",
+ "+grit/content_strings.h",
"+dbus",
"+gpu",
- "+mojo/public",
- "+mojo/bindings/js",
"+mojo/common",
- "+mojo/embedder",
- "+mojo/service_manager",
+ "+mojo/edk/embedder",
+ "+mojo/edk/js",
+ "+mojo/edk/test",
+ "+mojo/public",
"+net",
"+ppapi",
"+printing",
@@ -86,9 +85,14 @@ include_rules = [
"+ui/gfx",
"+ui/gl",
"+ui/native_theme",
- "+ui/ozone",
+ "+ui/ozone/gpu",
+ "+ui/ozone/public",
+ "+ui/resources/grit/ui_resources.h",
+ "+ui/resources/grit/webui_resources.h",
+ "+ui/resources/grit/webui_resources_map.h",
"+ui/shell_dialogs",
"+ui/snapshot",
+ "+ui/strings/grit/ui_strings.h",
"+ui/surface",
"+ui/wm",
# Content knows about grd files, but the specifics of how to get a resource
@@ -103,6 +107,8 @@ include_rules = [
# explicit.
"-ui/views",
+ "+storage/browser",
+ "+storage/common",
"+webkit",
# For generated JNI includes.
diff --git a/chromium/content/OWNERS b/chromium/content/OWNERS
index a47df4de1d2..593bbb4cdd7 100644
--- a/chromium/content/OWNERS
+++ b/chromium/content/OWNERS
@@ -1,10 +1,12 @@
avi@chromium.org
-brettw@chromium.org
creis@chromium.org
darin@chromium.org
+davidben@chromium.org
jam@chromium.org
jochen@chromium.org
+nasko@chromium.org
piman@chromium.org
+sievers@chromium.org
# per-file rules:
# These are for the common case of adding or renaming files. If you're doing
diff --git a/chromium/content/README b/chromium/content/README
new file mode 100644
index 00000000000..930fedfe25c
--- /dev/null
+++ b/chromium/content/README
@@ -0,0 +1,6 @@
+Content is the core code needed to render a page using a multi-process sandboxed
+browser.
+
+Developer documentation:
+http://www.chromium.org/developers/content-module
+
diff --git a/chromium/content/app/BUILD.gn b/chromium/content/app/BUILD.gn
index 13efa00b3dc..517082d5cae 100644
--- a/chromium/content/app/BUILD.gn
+++ b/chromium/content/app/BUILD.gn
@@ -2,61 +2,105 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("app") {
- sources = [
- "android/app_jni_registrar.cc",
- "android/app_jni_registrar.h",
- "android/child_process_service.cc",
- "android/child_process_service.h",
- "android/content_main.cc",
- "android/content_main.h",
- "android/library_loader_hooks.cc",
+# TODO(GYP) enable chrome_multiple_dll support
+is_chrome_multiple_dll = false
+
+content_app_sources = [
+ "android/app_jni_registrar.cc",
+ "android/app_jni_registrar.h",
+ "android/child_process_service.cc",
+ "android/child_process_service.h",
+ "android/content_main.cc",
+ "android/content_main.h",
+ "android/library_loader_hooks.cc",
+ "content_main.cc",
+ "content_main_runner.cc",
+ "mojo/mojo_init.cc",
+ "mojo/mojo_init.h",
+ "startup_helper_win.cc",
+]
+
+content_app_deps = [
+ "//base",
+ "//base:i18n",
+ # This is needed by app/content_main_runner.cc
+ # TODO(brettw) this shouldn't be here, only final executables should be
+ # picking the allocator.
+ "//base/allocator",
+ "//content:export",
+ "//content/public/common:common_sources",
+ "//crypto",
+ "//ui/base",
+ "//ui/gfx",
+ "//ui/gfx/geometry",
+]
+
+if (is_win) {
+ content_app_deps += [ "//sandbox" ]
+} else if (is_android) {
+ content_app_sources -= [ "content_main.cc" ]
+ content_app_deps += [
+ "//content/public/android:jni",
+ "//skia",
+ "//third_party/android_tools:cpu_features"
+ ]
+}
+
+if (is_ios) {
+ content_app_sources -= [
"content_main.cc",
- "content_main_runner.cc",
"mojo/mojo_init.cc",
"mojo/mojo_init.h",
- "startup_helper_win.cc",
]
-
- configs += [ "//content:content_implementation" ]
-
- deps = [
- "//base",
- "//base:i18n",
- # This is needed by app/content_main_runner.cc
- # TODO(brettw) this shouldn't be here, only final executables should be
- # picking the allocator.
- "//base/allocator",
- "//content:export",
- "//crypto",
- "//ui/base",
- "//ui/gfx",
- "//ui/gfx/geometry",
+} else {
+ content_app_deps += [
+ "//mojo/edk/system",
+ "//mojo/environment:chromium",
+ "//mojo/public/interfaces/application",
]
+}
- if (is_win) {
- deps += [ "//sandbox" ]
- } else if (is_android) {
- sources -= [ "content_main.cc" ]
- deps += [
- "//content:content_jni_headers",
- "//skia",
- "//third_party/android_tools:cpu_features"
- ]
+content_app_extra_configs = [
+ "//build/config/compiler:wexit_time_destructors",
+ "//content:content_implementation",
+]
+
+if (!is_chrome_multiple_dll) {
+ content_app_deps += [ "//content/gpu" ]
+}
+
+# This includes the app sources for both the browser and child processes.
+source_set("both") {
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/app:*" ]
+
+ sources = content_app_sources
+ configs += content_app_extra_configs
+ deps = content_app_deps
+}
+
+if (is_chrome_multiple_dll) {
+ # It doesn't make sense to do the browser/child dll split in component mode.
+ assert(!is_component_build)
+
+ source_set("browser") {
+ visibility = [ "//content/public/app:browser" ]
+
+ sources = content_app_sources
+ configs += content_app_extra_configs
+ deps = content_app_deps
+
+ defines += [ "CHROME_MULTIPLE_DLL_BROWSER" ]
}
- if (is_ios) {
- sources -= [
- "content_main.cc",
- "mojo/mojo_init.cc",
- "mojo/mojo_init.h",
- ]
- } else {
- deps += [
- "//mojo/environment:chromium",
- "//mojo/public/interfaces/service_provider:service_provider",
- "//mojo/service_manager",
- "//mojo/system",
- ]
+ source_set("child") {
+ visibility = [ "//content/public/app:child" ]
+
+ sources = content_app_sources
+ configs += content_app_extra_configs
+ deps = content_app_deps
+
+ defines += [ "CHROME_MULTIPLE_DLL_CHILD" ]
}
}
diff --git a/chromium/content/app/DEPS b/chromium/content/app/DEPS
index 321c9ffd0ef..2f0a8fe96f4 100644
--- a/chromium/content/app/DEPS
+++ b/chromium/content/app/DEPS
@@ -1,4 +1,7 @@
include_rules = [
"+content",
+ "+device/battery",
+ # For loading V8's initial snapshot from external files.
+ "+gin/public/isolate_holder.h",
"+media/base", # For initializing media library.
]
diff --git a/chromium/content/app/android/OWNERS b/chromium/content/app/android/OWNERS
index 0ab12305574..4889e9ac727 100644
--- a/chromium/content/app/android/OWNERS
+++ b/chromium/content/app/android/OWNERS
@@ -1,4 +1,2 @@
-bulach@chromium.org
michaelbai@chromium.org
-sievers@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/app/android/child_process_service.cc b/chromium/content/app/android/child_process_service.cc
index 62c04d6623e..9d46e080c82 100644
--- a/chromium/content/app/android/child_process_service.cc
+++ b/chromium/content/app/android/child_process_service.cc
@@ -13,7 +13,7 @@
#include "base/logging.h"
#include "base/posix/global_descriptors.h"
#include "content/child/child_thread.h"
-#include "content/common/android/surface_texture_lookup.h"
+#include "content/common/android/surface_texture_manager.h"
#include "content/common/android/surface_texture_peer.h"
#include "content/common/gpu/gpu_surface_lookup.h"
#include "content/public/app/android_library_loader_hooks.h"
@@ -30,44 +30,50 @@ namespace content {
namespace {
-class SurfaceTexturePeerChildImpl : public SurfaceTexturePeer,
- public GpuSurfaceLookup,
- public SurfaceTextureLookup {
+// TODO(sievers): Use two different implementations of this depending on if
+// we're in a renderer or gpu process.
+class SurfaceTextureManagerImpl : public SurfaceTextureManager,
+ public SurfaceTexturePeer,
+ public GpuSurfaceLookup {
public:
// |service| is the instance of
// org.chromium.content.app.ChildProcessService.
- explicit SurfaceTexturePeerChildImpl(
+ explicit SurfaceTextureManagerImpl(
const base::android::ScopedJavaLocalRef<jobject>& service)
: service_(service) {
+ SurfaceTexturePeer::InitInstance(this);
GpuSurfaceLookup::InitInstance(this);
- SurfaceTextureLookup::InitInstance(this);
}
-
- virtual ~SurfaceTexturePeerChildImpl() {
+ virtual ~SurfaceTextureManagerImpl() {
+ SurfaceTexturePeer::InitInstance(NULL);
GpuSurfaceLookup::InitInstance(NULL);
- SurfaceTextureLookup::InitInstance(NULL);
}
- // Overridden from SurfaceTexturePeer:
- virtual void EstablishSurfaceTexturePeer(
- base::ProcessHandle pid,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
- int primary_id,
- int secondary_id) OVERRIDE {
+ // Overridden from SurfaceTextureManager:
+ virtual void RegisterSurfaceTexture(
+ int surface_texture_id,
+ int client_id,
+ gfx::SurfaceTexture* surface_texture) override {
JNIEnv* env = base::android::AttachCurrentThread();
- content::Java_ChildProcessService_establishSurfaceTexturePeer(
- env, service_.obj(), pid,
- surface_texture->j_surface_texture().obj(), primary_id,
- secondary_id);
- CheckException(env);
+ Java_ChildProcessService_createSurfaceTextureSurface(
+ env,
+ service_.obj(),
+ surface_texture_id,
+ client_id,
+ surface_texture->j_surface_texture().obj());
}
-
- // Overridden from GpuSurfaceLookup:
- virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) OVERRIDE {
+ virtual void UnregisterSurfaceTexture(int surface_texture_id,
+ int client_id) override {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_ChildProcessService_destroySurfaceTextureSurface(
+ env, service_.obj(), surface_texture_id, client_id);
+ }
+ virtual gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture(
+ int surface_texture_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
gfx::ScopedJavaSurface surface(
- content::Java_ChildProcessService_getViewSurface(
- env, service_.obj(), surface_id));
+ Java_ChildProcessService_getSurfaceTextureSurface(env, service_.obj(),
+ surface_texture_id));
if (surface.j_surface().is_null())
return NULL;
@@ -82,14 +88,28 @@ class SurfaceTexturePeerChildImpl : public SurfaceTexturePeer,
return native_window;
}
- // Overridden from SurfaceTextureLookup:
- virtual gfx::AcceleratedWidget AcquireNativeWidget(int primary_id,
- int secondary_id)
- OVERRIDE {
+ // Overridden from SurfaceTexturePeer:
+ virtual void EstablishSurfaceTexturePeer(
+ base::ProcessHandle pid,
+ scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ int primary_id,
+ int secondary_id) override {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ content::Java_ChildProcessService_establishSurfaceTexturePeer(
+ env,
+ service_.obj(),
+ pid,
+ surface_texture->j_surface_texture().obj(),
+ primary_id,
+ secondary_id);
+ }
+
+ // Overridden from GpuSurfaceLookup:
+ virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override {
JNIEnv* env = base::android::AttachCurrentThread();
gfx::ScopedJavaSurface surface(
- content::Java_ChildProcessService_getSurfaceTextureSurface(
- env, service_.obj(), primary_id, secondary_id));
+ content::Java_ChildProcessService_getViewSurface(
+ env, service_.obj(), surface_id));
if (surface.j_surface().is_null())
return NULL;
@@ -108,7 +128,7 @@ class SurfaceTexturePeerChildImpl : public SurfaceTexturePeer,
// The instance of org.chromium.content.app.ChildProcessService.
base::android::ScopedJavaGlobalRef<jobject> service_;
- DISALLOW_COPY_AND_ASSIGN(SurfaceTexturePeerChildImpl);
+ DISALLOW_COPY_AND_ASSIGN(SurfaceTextureManagerImpl);
};
// Chrome actually uses the renderer code path for all of its child
@@ -132,11 +152,7 @@ void InternalInitChildProcess(const std::vector<int>& file_ids,
for (size_t i = 0; i < file_ids.size(); ++i)
base::GlobalDescriptors::GetInstance()->Set(file_ids[i], file_fds[i]);
- // SurfaceTexturePeerChildImpl implements the SurfaceTextureLookup interface,
- // which need to be set before we create a compositor thread that could be
- // using it to initialize resources.
- content::SurfaceTexturePeer::InitInstance(
- new SurfaceTexturePeerChildImpl(service));
+ SurfaceTextureManager::InitInstance(new SurfaceTextureManagerImpl(service));
base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(env);
}
diff --git a/chromium/content/app/android/library_loader_hooks.cc b/chromium/content/app/android/library_loader_hooks.cc
index f69933f1367..d09e21e9622 100644
--- a/chromium/content/app/android/library_loader_hooks.cc
+++ b/chromium/content/app/android/library_loader_hooks.cc
@@ -22,6 +22,7 @@
#include "content/common/content_constants_internal.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
+#include "device/battery/android/battery_jni_registrar.h"
#include "media/base/android/media_jni_registrar.h"
#include "net/android/net_jni_registrar.h"
#include "ui/base/android/ui_base_jni_registrar.h"
@@ -62,6 +63,9 @@ bool EnsureJniRegistered(JNIEnv* env) {
if (!content::android::RegisterAppJni(env))
return false;
+ if (!device::android::RegisterBatteryJni(env))
+ return false;
+
if (!media::RegisterJni(env))
return false;
@@ -71,18 +75,16 @@ bool EnsureJniRegistered(JNIEnv* env) {
return true;
}
-bool LibraryLoaded(JNIEnv* env, jclass clazz,
- jobjectArray init_command_line) {
- base::android::InitNativeCommandLineFromJavaArray(env, init_command_line);
-
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+bool LibraryLoaded(JNIEnv* env, jclass clazz) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kTraceStartup)) {
base::debug::CategoryFilter category_filter(
command_line->GetSwitchValueASCII(switches::kTraceStartup));
- base::debug::TraceLog::GetInstance()->SetEnabled(category_filter,
+ base::debug::TraceLog::GetInstance()->SetEnabled(
+ category_filter,
base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceLog::RECORD_UNTIL_FULL);
+ base::debug::TraceOptions());
}
// Android's main browser loop is custom so we set the browser
diff --git a/chromium/content/app/content_main_runner.cc b/chromium/content/app/content_main_runner.cc
index 38bf1cb3260..05e45bd791c 100644
--- a/chromium/content/app/content_main_runner.cc
+++ b/chromium/content/app/content_main_runner.cc
@@ -50,6 +50,10 @@
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#include "gin/public/isolate_holder.h"
+#endif
+
#if defined(OS_ANDROID)
#include "content/public/common/content_descriptors.h"
#endif
@@ -78,7 +82,6 @@
#include "base/strings/string_number_conversions.h"
#include "ui/base/win/atl_module.h"
-#include "ui/base/win/dpi_setup.h"
#include "ui/gfx/win/dpi.h"
#elif defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
@@ -121,13 +124,15 @@ extern int PpapiBrokerMain(const MainFunctionParams&);
#endif
extern int RendererMain(const content::MainFunctionParams&);
extern int UtilityMain(const MainFunctionParams&);
-extern int WorkerMain(const MainFunctionParams&);
} // namespace content
namespace content {
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
base::LazyInstance<ContentBrowserClient>
g_empty_content_browser_client = LAZY_INSTANCE_INITIALIZER;
+#endif // !CHROME_MULTIPLE_DLL_CHILD
+
#if !defined(OS_IOS) && !defined(CHROME_MULTIPLE_DLL_BROWSER)
base::LazyInstance<ContentPluginClient>
g_empty_content_plugin_client = LAZY_INSTANCE_INITIALIZER;
@@ -191,7 +196,7 @@ void CommonSubprocessInit(const std::string& process_type) {
// Only needed on Windows for creating stats tables.
#if defined(OS_WIN)
-static base::ProcessId GetBrowserPid(const CommandLine& command_line) {
+static base::ProcessId GetBrowserPid(const base::CommandLine& command_line) {
base::ProcessId browser_pid = base::GetCurrentProcId();
if (command_line.HasSwitch(switches::kProcessChannelID)) {
std::string channel_name =
@@ -206,7 +211,7 @@ static base::ProcessId GetBrowserPid(const CommandLine& command_line) {
}
#endif
-static void InitializeStatsTable(const CommandLine& command_line) {
+static void InitializeStatsTable(const base::CommandLine& command_line) {
// Initialize the Stats Counters table. With this initialized,
// the StatsViewer can be utilized to read counters outside of
// Chrome. These lines can be commented out to effectively turn
@@ -243,12 +248,14 @@ class ContentClientInitializer {
static void Set(const std::string& process_type,
ContentMainDelegate* delegate) {
ContentClient* content_client = GetContentClient();
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
if (process_type.empty()) {
if (delegate)
content_client->browser_ = delegate->CreateContentBrowserClient();
if (!content_client->browser_)
content_client->browser_ = &g_empty_content_browser_client.Get();
}
+#endif // !CHROME_MULTIPLE_DLL_CHILD
#if !defined(OS_IOS) && !defined(CHROME_MULTIPLE_DLL_BROWSER)
if (process_type == switches::kPluginProcess ||
@@ -259,7 +266,7 @@ class ContentClientInitializer {
content_client->plugin_ = &g_empty_content_plugin_client.Get();
// Single process not supported in split dll mode.
} else if (process_type == switches::kRendererProcess ||
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess)) {
if (delegate)
content_client->renderer_ = delegate->CreateContentRendererClient();
@@ -268,7 +275,7 @@ class ContentClientInitializer {
}
if (process_type == switches::kUtilityProcess ||
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess)) {
if (delegate)
content_client->utility_ = delegate->CreateContentUtilityClient();
@@ -296,7 +303,6 @@ int RunZygote(const MainFunctionParams& main_function_params,
ContentMainDelegate* delegate) {
static const MainFunction kMainFunctions[] = {
{ switches::kRendererProcess, RendererMain },
- { switches::kWorkerProcess, WorkerMain },
#if defined(ENABLE_PLUGINS)
{ switches::kPpapiPluginProcess, PpapiPluginMain },
#endif
@@ -322,7 +328,8 @@ int RunZygote(const MainFunctionParams& main_function_params,
// Zygote::HandleForkRequest may have reallocated the command
// line so update it here with the new version.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
ContentClientInitializer::Set(process_type, delegate);
@@ -333,6 +340,7 @@ int RunZygote(const MainFunctionParams& main_function_params,
InitializeStatsTable(command_line);
MainFunctionParams main_params(command_line);
+ main_params.zygote_child = true;
for (size_t i = 0; i < arraysize(kMainFunctions); ++i) {
if (process_type == kMainFunctions[i].name)
@@ -349,7 +357,7 @@ int RunZygote(const MainFunctionParams& main_function_params,
#if !defined(OS_IOS)
static void RegisterMainThreadFactories() {
-#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
+#if !defined(CHROME_MULTIPLE_DLL_BROWSER) && !defined(CHROME_MULTIPLE_DLL_CHILD)
UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(
CreateInProcessUtilityThread);
RenderProcessHostImpl::RegisterRendererMainThreadFactory(
@@ -357,7 +365,7 @@ static void RegisterMainThreadFactories() {
GpuProcessHost::RegisterGpuMainThreadFactory(
CreateInProcessGpuThread);
#else
- CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kSingleProcess)) {
LOG(FATAL) <<
"--single-process is not supported in chrome multiple dll browser.";
@@ -366,7 +374,7 @@ static void RegisterMainThreadFactories() {
LOG(FATAL) <<
"--in-process-gpu is not supported in chrome multiple dll browser.";
}
-#endif
+#endif // !CHROME_MULTIPLE_DLL_BROWSER && !CHROME_MULTIPLE_DLL_CHILD
}
// Run the FooMain() for a given process type.
@@ -385,7 +393,6 @@ int RunNamedProcessTypeMain(
#if !defined(OS_LINUX)
{ switches::kPluginProcess, PluginMain },
#endif
- { switches::kWorkerProcess, WorkerMain },
{ switches::kPpapiPluginProcess, PpapiPluginMain },
{ switches::kPpapiBrokerProcess, PpapiBrokerMain },
#endif // ENABLE_PLUGINS
@@ -446,7 +453,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
#endif
}
- virtual ~ContentMainRunnerImpl() {
+ ~ContentMainRunnerImpl() override {
if (is_initialized_ && !is_shutdown_)
Shutdown();
}
@@ -476,7 +483,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
}
#endif
- virtual int Initialize(const ContentMainParams& params) OVERRIDE {
+ int Initialize(const ContentMainParams& params) override {
ui_task_ = params.ui_task;
#if defined(OS_WIN)
@@ -556,9 +563,6 @@ class ContentMainRunnerImpl : public ContentMainRunner {
is_initialized_ = true;
delegate_ = params.delegate;
- base::EnableTerminationOnHeapCorruption();
- base::EnableTerminationOnOutOfMemory();
-
// The exit manager is in charge of calling the dtors of singleton objects.
// On Android, AtExitManager is set up when library is loaded.
// On iOS, it's set up in main(), which can't call directly through to here.
@@ -594,20 +598,25 @@ class ContentMainRunnerImpl : public ContentMainRunner {
argv = params.argv;
#endif
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
+
+ if (!delegate_ || delegate_->ShouldEnableTerminationOnHeapCorruption())
+ base::EnableTerminationOnHeapCorruption();
+ base::EnableTerminationOnOutOfMemory();
#if !defined(OS_IOS)
SetProcessTitleFromCommandLine(argv);
#endif
#endif // !OS_ANDROID
- int exit_code;
+ int exit_code = 0;
if (delegate_ && delegate_->BasicStartupComplete(&exit_code))
return exit_code;
completed_basic_startup_ = true;
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
@@ -616,6 +625,21 @@ class ContentMainRunnerImpl : public ContentMainRunner {
InitializeMojo();
#endif
+#if defined(OS_WIN)
+ bool init_device_scale_factor = true;
+ if (command_line.HasSwitch(switches::kDeviceScaleFactor)) {
+ std::string scale_factor_string = command_line.GetSwitchValueASCII(
+ switches::kDeviceScaleFactor);
+ double scale_factor = 0;
+ if (base::StringToDouble(scale_factor_string, &scale_factor)) {
+ init_device_scale_factor = false;
+ gfx::InitDeviceScaleFactor(scale_factor);
+ }
+ }
+ if (init_device_scale_factor)
+ gfx::InitDeviceScaleFactor(gfx::GetDPIScale());
+#endif
+
if (!GetContentClient())
SetContentClient(&empty_content_client_);
ContentClientInitializer::Set(process_type, delegate_);
@@ -634,7 +658,8 @@ class ContentMainRunnerImpl : public ContentMainRunner {
base::debug::TraceLog::GetInstance()->SetEnabled(
category_filter,
base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceLog::RECORD_UNTIL_FULL);
+ base::debug::TraceOptions(
+ base::debug::RECORD_UNTIL_FULL));
}
#if !defined(OS_ANDROID)
// Android tracing started at the beginning of the method.
@@ -659,22 +684,6 @@ class ContentMainRunnerImpl : public ContentMainRunner {
MachBroker::ChildSendTaskPortToParent();
}
#elif defined(OS_WIN)
- if (command_line.HasSwitch(switches::kEnableHighResolutionTime))
- base::TimeTicks::SetNowIsHighResNowIfSupported();
-
- bool init_device_scale_factor = true;
- if (command_line.HasSwitch(switches::kDeviceScaleFactor)) {
- std::string scale_factor_string = command_line.GetSwitchValueASCII(
- switches::kDeviceScaleFactor);
- double scale_factor = 0;
- if (base::StringToDouble(scale_factor_string, &scale_factor)) {
- init_device_scale_factor = false;
- gfx::InitDeviceScaleFactor(scale_factor);
- }
- }
- if (init_device_scale_factor)
- ui::win::InitDeviceScaleFactor();
-
SetupCRT(command_line);
#endif
@@ -711,9 +720,26 @@ class ContentMainRunnerImpl : public ContentMainRunner {
CHECK(base::i18n::InitializeICUWithFileDescriptor(icudata_fd));
else
CHECK(base::i18n::InitializeICU());
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+ int v8_natives_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
+ kV8NativesDataDescriptor);
+ int v8_snapshot_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(
+ kV8SnapshotDataDescriptor);
+ if (v8_natives_fd != -1 && v8_snapshot_fd != -1) {
+ CHECK(gin::IsolateHolder::LoadV8SnapshotFD(v8_natives_fd,
+ v8_snapshot_fd));
+ } else {
+ CHECK(gin::IsolateHolder::LoadV8Snapshot());
+ }
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+
#else
CHECK(base::i18n::InitializeICU());
-#endif
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+ CHECK(gin::IsolateHolder::LoadV8Snapshot());
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+#endif // OS_ANDROID
InitializeStatsTable(command_line);
@@ -743,12 +769,13 @@ class ContentMainRunnerImpl : public ContentMainRunner {
return -1;
}
- virtual int Run() OVERRIDE {
+ int Run() override {
DCHECK(is_initialized_);
DCHECK(!is_shutdown_);
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
+ command_line.GetSwitchValueASCII(switches::kProcessType);
MainFunctionParams main_params(command_line);
main_params.ui_task = ui_task_;
@@ -765,12 +792,13 @@ class ContentMainRunnerImpl : public ContentMainRunner {
#endif
}
- virtual void Shutdown() OVERRIDE {
+ void Shutdown() override {
DCHECK(is_initialized_);
DCHECK(!is_shutdown_);
if (completed_basic_startup_ && delegate_) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
diff --git a/chromium/content/app/mojo/mojo_browsertest.cc b/chromium/content/app/mojo/mojo_browsertest.cc
index f578b572460..b516107333f 100644
--- a/chromium/content/app/mojo/mojo_browsertest.cc
+++ b/chromium/content/app/mojo/mojo_browsertest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "content/public/test/content_browser_test.h"
-#include "mojo/service_manager/service_manager.h"
+#include "mojo/public/c/system/core.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -13,8 +13,10 @@ class MojoTest : public ContentBrowserTest {
MojoTest() {}
protected:
- bool HasCreatedInstance() {
- return mojo::ServiceManager::TestAPI::HasCreatedInstance();
+ bool IsMojoInitialized() {
+ // Check |MojoGetTimeTicksNow()| is accessible.
+ MojoGetTimeTicksNow();
+ return true;
}
private:
@@ -23,7 +25,7 @@ class MojoTest : public ContentBrowserTest {
// Placeholder test to confirm we are initializing Mojo.
IN_PROC_BROWSER_TEST_F(MojoTest, Init) {
- EXPECT_TRUE(HasCreatedInstance());
+ EXPECT_TRUE(IsMojoInitialized());
}
} // namespace content
diff --git a/chromium/content/app/mojo/mojo_init.cc b/chromium/content/app/mojo/mojo_init.cc
index 55630b4a4ae..755b6b19b9f 100644
--- a/chromium/content/app/mojo/mojo_init.cc
+++ b/chromium/content/app/mojo/mojo_init.cc
@@ -4,15 +4,15 @@
#include "content/app/mojo/mojo_init.h"
-#include "base/logging.h"
-#include "mojo/embedder/embedder.h"
-#include "mojo/service_manager/service_manager.h"
+#include "base/memory/scoped_ptr.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/simple_platform_support.h"
namespace content {
void InitializeMojo() {
- mojo::embedder::Init();
- mojo::ServiceManager::GetInstance();
+ mojo::embedder::Init(scoped_ptr<mojo::embedder::PlatformSupport>(
+ new mojo::embedder::SimplePlatformSupport()));
}
} // namespace content
diff --git a/chromium/content/app/resources/BUILD.gn b/chromium/content/app/resources/BUILD.gn
new file mode 100644
index 00000000000..c9de61e0162
--- /dev/null
+++ b/chromium/content/app/resources/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2014 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.
+
+import("//tools/grit/grit_rule.gni")
+
+grit("resources") {
+ source = "content_resources.grd"
+ use_qualified_include = true
+ outputs = [
+ "grit/content_resources.h",
+ "content_resources_100_percent.pak",
+ "content_resources_200_percent.pak",
+ ]
+}
diff --git a/chromium/content/app/resources/README.txt b/chromium/content/app/resources/README.txt
new file mode 100644
index 00000000000..1472c31c8d6
--- /dev/null
+++ b/chromium/content/app/resources/README.txt
@@ -0,0 +1,108 @@
+The files listed below and found in this directory are copied from the
+Mozilla source tree, where they are licensed under the MPL/GPL/LGPL. While
+binary files do not contain a license block, I have pasted the relevant
+Mozilla license block below.
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/////////////////////////////////////////////////////////////////////////////
+
+The files listed below and found in this directory are copied from the WebKit
+source tree or are derivative works of files from the WebKit source tree.
+They are licensed under a BSD license. While binary files do not contain
+a license block, I have pasted the relevant WebKit license block below.
+
+pan_icon.png
+pan_east.cur
+pan_middle.cur
+pan_north.cur
+pan_north_east.cur
+pan_north_west.cur
+pan_south.cur
+pan_south_east.cur
+pan_south_west.cur
+pan_west.cur
+textarea_resize_corner.png
+alias_cursor.png
+cell_cursor.png
+east_resize_cursor.png
+east_west_resize_cursor.png
+help_cursor.png
+link_cursor.png
+move_cursor.png
+none_cursor.png
+north_east_resize_cursor.png
+north_east_south_west_resize_cursor.png
+north_resize_cursor.png
+north_south_resize_cursor.png
+north_west_resize_cursor.png
+north_west_south_east_resize_cursor.png
+progress_cursor.png
+south_east_resize_cursor.png
+south_resize_cursor.png
+south_west_resize_cursor.png
+vertical_text_cursor.png
+wait_cursor.png
+west_resize_cursor.png
+zoom_in_cursor.png
+zoom_out_cursor.png
+
+// ***** BEGIN LICENSE BLOCK *****
+
+Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ its contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chromium/content/app/resources/content_resources.grd b/chromium/content/app/resources/content_resources.grd
new file mode 100644
index 00000000000..9c4373b47a1
--- /dev/null
+++ b/chromium/content/app/resources/content_resources.grd
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1">
+ <outputs>
+ <output filename="grit/content_resources.h" type="rc_header" context="default_100_percent">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="content_resources_100_percent.pak" type="data_package" context="default_100_percent" />
+ <output filename="content_resources_200_percent.pak" type="data_package" context="default_200_percent" />
+ </outputs>
+ <release seq="1">
+ <structures fallback_to_low_resolution="true">
+ <structure type="chrome_scaled_image" name="IDR_BROKENIMAGE" file="broken_image.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PAUSE_BUTTON" file="mediaplayer_pause.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PAUSE_BUTTON_HOVER" file="mediaplayer_pause_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PAUSE_BUTTON_DOWN" file="mediaplayer_pause_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PLAY_BUTTON" file="mediaplayer_play.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PLAY_BUTTON_HOVER" file="mediaplayer_play_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PLAY_BUTTON_DOWN" file="mediaplayer_play_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_PLAY_BUTTON_DISABLED" file="mediaplayer_play_disabled.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON" file="mediaplayer_sound_level3.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_HOVER" file="mediaplayer_sound_level3_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL3_BUTTON_DOWN" file="mediaplayer_sound_level3_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON" file="mediaplayer_sound_level2.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_HOVER" file="mediaplayer_sound_level2_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL2_BUTTON_DOWN" file="mediaplayer_sound_level2_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON" file="mediaplayer_sound_level1.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_HOVER" file="mediaplayer_sound_level1_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL1_BUTTON_DOWN" file="mediaplayer_sound_level1_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON" file="mediaplayer_sound_level0.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_HOVER" file="mediaplayer_sound_level0_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_LEVEL0_BUTTON_DOWN" file="mediaplayer_sound_level0_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SOUND_DISABLED" file="mediaplayer_sound_disabled.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SLIDER_THUMB" file="mediaplayer_slider_thumb.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SLIDER_THUMB_HOVER" file="mediaplayer_slider_thumb_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_SLIDER_THUMB_DOWN" file="mediaplayer_slider_thumb_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB" file="mediaplayer_volume_slider_thumb.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_HOVER" file="mediaplayer_volume_slider_thumb_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DOWN" file="mediaplayer_volume_slider_thumb_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_VOLUME_SLIDER_THUMB_DISABLED" file="mediaplayer_volume_slider_thumb_disabled.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON" file="mediaplayer_closedcaption.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_HOVER" file="mediaplayer_closedcaption_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DOWN" file="mediaplayer_closedcaption_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CLOSEDCAPTION_BUTTON_DISABLED" file="mediaplayer_closedcaption_disabled.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_FULLSCREEN_BUTTON" file="mediaplayer_fullscreen.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER" file="mediaplayer_fullscreen_hover.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN" file="mediaplayer_fullscreen_down.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED" file="mediaplayer_fullscreen_disabled.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CAST_BUTTON_OFF" file="mediaplayer_cast_off.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_CAST_BUTTON_ON" file="mediaplayer_cast_on.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF" file="mediaplayer_overlay_cast_off.png" />
+ <structure type="chrome_scaled_image" name="IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON" file="mediaplayer_overlay_play.png" />
+ <if expr="is_macosx">
+ <structure type="chrome_scaled_image" name="IDR_OVERHANG_PATTERN" file="overhang_pattern.png" />
+ <structure type="chrome_scaled_image" name="IDR_OVERHANG_SHADOW" file="overhang_shadow.png" />
+ <structure type="chrome_scaled_image" name="IDR_ALIAS_CURSOR" file="alias_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_CELL_CURSOR" file="cell_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_EAST_RESIZE_CURSOR" file="east_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_EASTWEST_RESIZE_CURSOR" file="east_west_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_HELP_CURSOR" file="help_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_LINK_CURSOR" file="link_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_MOVE_CURSOR" file="move_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NONE_CURSOR" file="none_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NORTHEAST_RESIZE_CURSOR" file="north_east_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NORTHEASTSOUTHWEST_RESIZE_CURSOR" file="north_east_south_west_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NORTH_RESIZE_CURSOR" file="north_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NORTHSOUTH_RESIZE_CURSOR" file="north_south_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NORTHWEST_RESIZE_CURSOR" file="north_west_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_NORTHWESTSOUTHEAST_RESIZE_CURSOR" file="north_west_south_east_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_PROGRESS_CURSOR" file="progress_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_SOUTHEAST_RESIZE_CURSOR" file="south_east_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_SOUTH_RESIZE_CURSOR" file="south_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_SOUTHWEST_RESIZE_CURSOR" file="south_west_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_VERTICALTEXT_CURSOR" file="vertical_text_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_WAIT_CURSOR" file="wait_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_WEST_RESIZE_CURSOR" file="west_resize_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_ZOOMIN_CURSOR" file="zoom_in_cursor.png" />
+ <structure type="chrome_scaled_image" name="IDR_ZOOMOUT_CURSOR" file="zoom_out_cursor.png" />
+ </if>
+ <structure type="chrome_scaled_image" name="IDR_PAN_SCROLL_ICON" file="pan_icon.png" />
+ <structure type="chrome_scaled_image" name="IDR_SEARCH_CANCEL" file="search_cancel.png" />
+ <structure type="chrome_scaled_image" name="IDR_SEARCH_CANCEL_PRESSED" file="search_cancel_pressed.png" />
+ <structure type="chrome_scaled_image" name="IDR_SEARCH_MAGNIFIER" file="search_magnifier.png" />
+ <structure type="chrome_scaled_image" name="IDR_SEARCH_MAGNIFIER_RESULTS" file="search_magnifier_results.png" />
+ <structure type="chrome_scaled_image" name="IDR_TEXTAREA_RESIZER" file="textarea_resize_corner.png" />
+ <structure type="chrome_scaled_image" name="IDR_PASSWORD_GENERATION_ICON" file="password_generation.png" />
+ <structure type="chrome_scaled_image" name="IDR_PASSWORD_GENERATION_ICON_HOVER" file="password_generation_hover.png" />
+ </structures>
+ </release>
+</grit>
diff --git a/chromium/content/app/resources/content_resources.gyp b/chromium/content/app/resources/content_resources.gyp
new file mode 100644
index 00000000000..f47eb9e900a
--- /dev/null
+++ b/chromium/content/app/resources/content_resources.gyp
@@ -0,0 +1,26 @@
+# Copyright 2014 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.
+
+{
+ 'targets': [
+ {
+ # GN version: //content/app/resources
+ 'target_name': 'content_resources',
+ 'type': 'none',
+ 'variables': {
+ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/content/app/resources/',
+ },
+ 'actions': [
+ {
+ 'action_name': 'generate_content_resources',
+ 'variables': {
+ 'grit_grd_file': 'content_resources.grd',
+ },
+ 'includes': [ '../../../build/grit_action.gypi' ],
+ },
+ ],
+ 'includes': [ '../../../build/grit_target.gypi' ],
+ },
+ ]
+}
diff --git a/chromium/content/app/resources/default_100_percent/alias_cursor.png b/chromium/content/app/resources/default_100_percent/alias_cursor.png
new file mode 100644
index 00000000000..36d48d34393
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/alias_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/broken_image.png b/chromium/content/app/resources/default_100_percent/broken_image.png
new file mode 100644
index 00000000000..ad76cc1965b
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/broken_image.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/cell_cursor.png b/chromium/content/app/resources/default_100_percent/cell_cursor.png
new file mode 100644
index 00000000000..6dc266c8cb1
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/cell_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/east_resize_cursor.png b/chromium/content/app/resources/default_100_percent/east_resize_cursor.png
new file mode 100644
index 00000000000..73f9cf8c5ec
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/east_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/east_west_resize_cursor.png b/chromium/content/app/resources/default_100_percent/east_west_resize_cursor.png
new file mode 100644
index 00000000000..460f417138c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/east_west_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/help_cursor.png b/chromium/content/app/resources/default_100_percent/help_cursor.png
new file mode 100644
index 00000000000..8706f4fb2c5
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/help_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/link_cursor.png b/chromium/content/app/resources/default_100_percent/link_cursor.png
new file mode 100644
index 00000000000..e48cd588d0c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/link_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_cast_off.png b/chromium/content/app/resources/default_100_percent/mediaplayer_cast_off.png
new file mode 100644
index 00000000000..050022d2fe5
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_cast_off.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_cast_on.png b/chromium/content/app/resources/default_100_percent/mediaplayer_cast_on.png
new file mode 100644
index 00000000000..4f24bf9ea69
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_cast_on.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption.png b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption.png
new file mode 100644
index 00000000000..a92b3d2051d
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_disabled.png b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_disabled.png
new file mode 100644
index 00000000000..7ac1a898758
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_disabled.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_down.png
new file mode 100644
index 00000000000..60da8a2973f
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_hover.png
new file mode 100644
index 00000000000..a3e069f991e
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_closedcaption_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen.png b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen.png
new file mode 100644
index 00000000000..713a87796d2
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_disabled.png b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_disabled.png
new file mode 100644
index 00000000000..f0958a64c0f
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_disabled.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_down.png
new file mode 100644
index 00000000000..3a6cd5db13a
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_hover.png
new file mode 100644
index 00000000000..38e33304dfa
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_fullscreen_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_overlay_cast_off.png b/chromium/content/app/resources/default_100_percent/mediaplayer_overlay_cast_off.png
new file mode 100644
index 00000000000..e16f58e57a6
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_overlay_cast_off.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_overlay_play.png b/chromium/content/app/resources/default_100_percent/mediaplayer_overlay_play.png
new file mode 100644
index 00000000000..cfd48d74e28
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_overlay_play.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_pause.png b/chromium/content/app/resources/default_100_percent/mediaplayer_pause.png
new file mode 100644
index 00000000000..b488e97a66b
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_pause.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_pause_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_pause_down.png
new file mode 100644
index 00000000000..bf754e9c4bd
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_pause_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_pause_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_pause_hover.png
new file mode 100644
index 00000000000..ac3334c4c88
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_pause_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_play.png b/chromium/content/app/resources/default_100_percent/mediaplayer_play.png
new file mode 100644
index 00000000000..1e53d435809
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_play.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_play_disabled.png b/chromium/content/app/resources/default_100_percent/mediaplayer_play_disabled.png
new file mode 100644
index 00000000000..8e1220018cc
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_play_disabled.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_play_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_play_down.png
new file mode 100644
index 00000000000..fa6a243429b
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_play_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_play_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_play_hover.png
new file mode 100644
index 00000000000..a71c2f327a8
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_play_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb.png b/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb.png
new file mode 100644
index 00000000000..4cc24d1591a
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_down.png
new file mode 100644
index 00000000000..483101d9067
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_hover.png
new file mode 100644
index 00000000000..2a968424f5d
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_slider_thumb_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_disabled.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_disabled.png
new file mode 100644
index 00000000000..38fa4baaa95
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_disabled.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0.png
new file mode 100644
index 00000000000..22d6a109de7
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_down.png
new file mode 100644
index 00000000000..d956e5810c2
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_hover.png
new file mode 100644
index 00000000000..56214a1494c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level0_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1.png
new file mode 100644
index 00000000000..2c6809abb1b
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_down.png
new file mode 100644
index 00000000000..faa188841ec
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_hover.png
new file mode 100644
index 00000000000..1fdaf21003a
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level1_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2.png
new file mode 100644
index 00000000000..e98c51d306c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_down.png
new file mode 100644
index 00000000000..37f5d76942c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_hover.png
new file mode 100644
index 00000000000..e44356bb2ef
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level2_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3.png
new file mode 100644
index 00000000000..05caa642439
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_down.png
new file mode 100644
index 00000000000..db384048586
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_hover.png
new file mode 100644
index 00000000000..838b07f34d7
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_sound_level3_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb.png b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb.png
new file mode 100644
index 00000000000..c4620f54259
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png
new file mode 100644
index 00000000000..d32434b6d2a
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png
new file mode 100644
index 00000000000..98ee8509264
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png
new file mode 100644
index 00000000000..93cca9b325f
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/move_cursor.png b/chromium/content/app/resources/default_100_percent/move_cursor.png
new file mode 100644
index 00000000000..2d82272129f
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/move_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/none_cursor.png b/chromium/content/app/resources/default_100_percent/none_cursor.png
new file mode 100644
index 00000000000..bd36820b890
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/none_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/north_east_resize_cursor.png b/chromium/content/app/resources/default_100_percent/north_east_resize_cursor.png
new file mode 100644
index 00000000000..f2104f92b91
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/north_east_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/north_east_south_west_resize_cursor.png b/chromium/content/app/resources/default_100_percent/north_east_south_west_resize_cursor.png
new file mode 100644
index 00000000000..5db337a1d51
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/north_east_south_west_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/north_resize_cursor.png b/chromium/content/app/resources/default_100_percent/north_resize_cursor.png
new file mode 100644
index 00000000000..bdd01b9fc40
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/north_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/north_south_resize_cursor.png b/chromium/content/app/resources/default_100_percent/north_south_resize_cursor.png
new file mode 100644
index 00000000000..17971e73e9f
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/north_south_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/north_west_resize_cursor.png b/chromium/content/app/resources/default_100_percent/north_west_resize_cursor.png
new file mode 100644
index 00000000000..d03e5efa2a2
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/north_west_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/north_west_south_east_resize_cursor.png b/chromium/content/app/resources/default_100_percent/north_west_south_east_resize_cursor.png
new file mode 100644
index 00000000000..78552e7d83d
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/north_west_south_east_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/overhang_pattern.png b/chromium/content/app/resources/default_100_percent/overhang_pattern.png
new file mode 100644
index 00000000000..838e87c3238
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/overhang_pattern.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/overhang_shadow.png b/chromium/content/app/resources/default_100_percent/overhang_shadow.png
new file mode 100644
index 00000000000..4e0fc4b720c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/overhang_shadow.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/pan_icon.png b/chromium/content/app/resources/default_100_percent/pan_icon.png
new file mode 100644
index 00000000000..e07d96255b8
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/pan_icon.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/password_generation.png b/chromium/content/app/resources/default_100_percent/password_generation.png
new file mode 100644
index 00000000000..2b45ac3ac26
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/password_generation.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/password_generation_hover.png b/chromium/content/app/resources/default_100_percent/password_generation_hover.png
new file mode 100644
index 00000000000..a832cdc81ed
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/password_generation_hover.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/progress_cursor.png b/chromium/content/app/resources/default_100_percent/progress_cursor.png
new file mode 100644
index 00000000000..32ea1bef4e9
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/progress_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/search_cancel.png b/chromium/content/app/resources/default_100_percent/search_cancel.png
new file mode 100644
index 00000000000..1291bf84302
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/search_cancel.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/search_cancel_pressed.png b/chromium/content/app/resources/default_100_percent/search_cancel_pressed.png
new file mode 100644
index 00000000000..4abc0fd4ac0
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/search_cancel_pressed.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/search_magnifier.png b/chromium/content/app/resources/default_100_percent/search_magnifier.png
new file mode 100644
index 00000000000..0aea5daeded
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/search_magnifier.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/search_magnifier_results.png b/chromium/content/app/resources/default_100_percent/search_magnifier_results.png
new file mode 100644
index 00000000000..2f773c06943
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/search_magnifier_results.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/solo.png b/chromium/content/app/resources/default_100_percent/solo.png
new file mode 100644
index 00000000000..e5d24f4decb
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/solo.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/south_east_resize_cursor.png b/chromium/content/app/resources/default_100_percent/south_east_resize_cursor.png
new file mode 100644
index 00000000000..cdd6f78012d
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/south_east_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/south_resize_cursor.png b/chromium/content/app/resources/default_100_percent/south_resize_cursor.png
new file mode 100644
index 00000000000..a511157836c
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/south_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/south_west_resize_cursor.png b/chromium/content/app/resources/default_100_percent/south_west_resize_cursor.png
new file mode 100644
index 00000000000..2b3bb0fcafe
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/south_west_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/textarea_resize_corner.png b/chromium/content/app/resources/default_100_percent/textarea_resize_corner.png
new file mode 100644
index 00000000000..a379bdd3053
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/textarea_resize_corner.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/vertical_text_cursor.png b/chromium/content/app/resources/default_100_percent/vertical_text_cursor.png
new file mode 100644
index 00000000000..dd60889eb25
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/vertical_text_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/wait_cursor.png b/chromium/content/app/resources/default_100_percent/wait_cursor.png
new file mode 100644
index 00000000000..e564fb14160
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/wait_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/west_resize_cursor.png b/chromium/content/app/resources/default_100_percent/west_resize_cursor.png
new file mode 100644
index 00000000000..2d2dca9fd8b
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/west_resize_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/zoom_in_cursor.png b/chromium/content/app/resources/default_100_percent/zoom_in_cursor.png
new file mode 100644
index 00000000000..619f70a9710
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/zoom_in_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_100_percent/zoom_out_cursor.png b/chromium/content/app/resources/default_100_percent/zoom_out_cursor.png
new file mode 100644
index 00000000000..817dc8c16b9
--- /dev/null
+++ b/chromium/content/app/resources/default_100_percent/zoom_out_cursor.png
Binary files differ
diff --git a/chromium/content/app/resources/default_200_percent/broken_image.png b/chromium/content/app/resources/default_200_percent/broken_image.png
new file mode 100644
index 00000000000..45edebcd515
--- /dev/null
+++ b/chromium/content/app/resources/default_200_percent/broken_image.png
Binary files differ
diff --git a/chromium/content/app/resources/default_200_percent/pan_icon.png b/chromium/content/app/resources/default_200_percent/pan_icon.png
new file mode 100644
index 00000000000..d9c0c1592ac
--- /dev/null
+++ b/chromium/content/app/resources/default_200_percent/pan_icon.png
Binary files differ
diff --git a/chromium/content/app/resources/default_200_percent/textarea_resize_corner.png b/chromium/content/app/resources/default_200_percent/textarea_resize_corner.png
new file mode 100644
index 00000000000..77fa3cac8ba
--- /dev/null
+++ b/chromium/content/app/resources/default_200_percent/textarea_resize_corner.png
Binary files differ
diff --git a/chromium/content/app/startup_helper_win.cc b/chromium/content/app/startup_helper_win.cc
index 17fd323397f..ab85a43e806 100644
--- a/chromium/content/app/startup_helper_win.cc
+++ b/chromium/content/app/startup_helper_win.cc
@@ -56,7 +56,7 @@ void RegisterInvalidParamHandler() {
_set_new_mode(1);
}
-void SetupCRT(const CommandLine& command_line) {
+void SetupCRT(const base::CommandLine& command_line) {
#if defined(_CRTDBG_MAP_ALLOC)
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
diff --git a/chromium/content/app/strings/BUILD.gn b/chromium/content/app/strings/BUILD.gn
new file mode 100644
index 00000000000..c0dafd09c59
--- /dev/null
+++ b/chromium/content/app/strings/BUILD.gn
@@ -0,0 +1,69 @@
+# Copyright 2014 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.
+
+import("//tools/grit/grit_rule.gni")
+
+# GYP version: content/app/strings/content_strings.gyp:content_strings
+grit("strings") {
+ use_qualified_include = true
+ source = "content_strings.grd"
+ outputs = [
+ "grit/content_strings.h",
+ "content_strings_en-US.rc",
+ "content_strings_am.pak",
+ "content_strings_ar.pak",
+ "content_strings_bg.pak",
+ "content_strings_bn.pak",
+ "content_strings_ca.pak",
+ "content_strings_cs.pak",
+ "content_strings_da.pak",
+ "content_strings_de.pak",
+ "content_strings_el.pak",
+ "content_strings_en-GB.pak",
+ "content_strings_en-US.pak",
+ "content_strings_es.pak",
+ "content_strings_es-419.pak",
+ "content_strings_et.pak",
+ "content_strings_fa.pak",
+ "content_strings_fake-bidi.pak",
+ "content_strings_fi.pak",
+ "content_strings_fil.pak",
+ "content_strings_fr.pak",
+ "content_strings_gu.pak",
+ "content_strings_he.pak",
+ "content_strings_hi.pak",
+ "content_strings_hr.pak",
+ "content_strings_hu.pak",
+ "content_strings_id.pak",
+ "content_strings_it.pak",
+ "content_strings_ja.pak",
+ "content_strings_kn.pak",
+ "content_strings_ko.pak",
+ "content_strings_lt.pak",
+ "content_strings_lv.pak",
+ "content_strings_ml.pak",
+ "content_strings_mr.pak",
+ "content_strings_ms.pak",
+ "content_strings_nl.pak",
+ "content_strings_nb.pak",
+ "content_strings_pl.pak",
+ "content_strings_pt-BR.pak",
+ "content_strings_pt-PT.pak",
+ "content_strings_ro.pak",
+ "content_strings_ru.pak",
+ "content_strings_sk.pak",
+ "content_strings_sl.pak",
+ "content_strings_sr.pak",
+ "content_strings_sv.pak",
+ "content_strings_sw.pak",
+ "content_strings_ta.pak",
+ "content_strings_te.pak",
+ "content_strings_th.pak",
+ "content_strings_tr.pak",
+ "content_strings_uk.pak",
+ "content_strings_vi.pak",
+ "content_strings_zh-CN.pak",
+ "content_strings_zh-TW.pak",
+ ]
+}
diff --git a/chromium/content/app/strings/content_strings.grd b/chromium/content/app/strings/content_strings.grd
new file mode 100644
index 00000000000..0f864cb5d76
--- /dev/null
+++ b/chromium/content/app/strings/content_strings.grd
@@ -0,0 +1,727 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This file contains definitions of resources that will be translated for
+each locale. Specifically, these are UI strings that are used by content that
+need to be translated for each locale.-->
+
+<!-- Some of these strings and string descriptions were taken from
+WebKit/win/WebCoreLocalizedStrings.cpp so we include the original license
+below:
+
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+-->
+
+<grit base_dir="." latest_public_release="0" current_release="1"
+ source_lang_id="en" enc_check="möl">
+ <outputs>
+ <!-- TODO add each of your output files. Modify the three below, and add
+ your own for your various languages. See the user's guide
+ (http://wiki/Main/GritUsersGuide) for more details.
+ Note that all output references are relative to the output directory
+ which is specified at build time. -->
+ <output filename="grit/content_strings.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <!-- TODO(tony): Get rid of this .rc file. -->
+ <output filename="content_strings_en-US.rc" type="rc_all" lang="en" />
+
+ <output filename="content_strings_am.pak" type="data_package" lang="am" />
+ <output filename="content_strings_ar.pak" type="data_package" lang="ar" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_ast.pak" type="data_package" lang="ast" />
+ </if>
+ <output filename="content_strings_bg.pak" type="data_package" lang="bg" />
+ <output filename="content_strings_bn.pak" type="data_package" lang="bn" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_bs.pak" type="data_package" lang="bs" />
+ </if>
+ <output filename="content_strings_ca.pak" type="data_package" lang="ca" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_ca@valencia.pak" type="data_package" lang="ca@valencia" />
+ </if>
+ <output filename="content_strings_cs.pak" type="data_package" lang="cs" />
+ <output filename="content_strings_da.pak" type="data_package" lang="da" />
+ <output filename="content_strings_de.pak" type="data_package" lang="de" />
+ <output filename="content_strings_el.pak" type="data_package" lang="el" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_en-AU.pak" type="data_package" lang="en-AU" />
+ </if>
+ <output filename="content_strings_en-GB.pak" type="data_package" lang="en-GB" />
+ <output filename="content_strings_en-US.pak" type="data_package" lang="en" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_eo.pak" type="data_package" lang="eo" />
+ </if>
+ <output filename="content_strings_es.pak" type="data_package" lang="es" />
+ <output filename="content_strings_es-419.pak" type="data_package" lang="es-419" />
+ <output filename="content_strings_et.pak" type="data_package" lang="et" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_eu.pak" type="data_package" lang="eu" />
+ </if>
+ <output filename="content_strings_fa.pak" type="data_package" lang="fa" />
+ <output filename="content_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" />
+ <output filename="content_strings_fi.pak" type="data_package" lang="fi" />
+ <output filename="content_strings_fil.pak" type="data_package" lang="fil" />
+ <output filename="content_strings_fr.pak" type="data_package" lang="fr" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_gl.pak" type="data_package" lang="gl" />
+ </if>
+ <output filename="content_strings_gu.pak" type="data_package" lang="gu" />
+ <output filename="content_strings_he.pak" type="data_package" lang="he" />
+ <output filename="content_strings_hi.pak" type="data_package" lang="hi" />
+ <output filename="content_strings_hr.pak" type="data_package" lang="hr" />
+ <output filename="content_strings_hu.pak" type="data_package" lang="hu" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_hy.pak" type="data_package" lang="hy" />
+ <output filename="webkit_strings_ia.pak" type="data_package" lang="ia" />
+ </if>
+ <output filename="content_strings_id.pak" type="data_package" lang="id" />
+ <output filename="content_strings_it.pak" type="data_package" lang="it" />
+ <output filename="content_strings_ja.pak" type="data_package" lang="ja" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_ka.pak" type="data_package" lang="ka" />
+ </if>
+ <output filename="content_strings_kn.pak" type="data_package" lang="kn" />
+ <output filename="content_strings_ko.pak" type="data_package" lang="ko" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_ku.pak" type="data_package" lang="ku" />
+ <output filename="webkit_strings_kw.pak" type="data_package" lang="kw" />
+ </if>
+ <output filename="content_strings_lt.pak" type="data_package" lang="lt" />
+ <output filename="content_strings_lv.pak" type="data_package" lang="lv" />
+ <output filename="content_strings_ml.pak" type="data_package" lang="ml" />
+ <output filename="content_strings_mr.pak" type="data_package" lang="mr" />
+ <output filename="content_strings_ms.pak" type="data_package" lang="ms" />
+ <output filename="content_strings_nl.pak" type="data_package" lang="nl" />
+ <!-- The translation console uses 'no' for Norwegian Bokmål. It should
+ be 'nb'. -->
+ <output filename="content_strings_nb.pak" type="data_package" lang="no" />
+ <output filename="content_strings_pl.pak" type="data_package" lang="pl" />
+ <output filename="content_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
+ <output filename="content_strings_pt-PT.pak" type="data_package" lang="pt-PT" />
+ <output filename="content_strings_ro.pak" type="data_package" lang="ro" />
+ <output filename="content_strings_ru.pak" type="data_package" lang="ru" />
+ <output filename="content_strings_sk.pak" type="data_package" lang="sk" />
+ <output filename="content_strings_sl.pak" type="data_package" lang="sl" />
+ <output filename="content_strings_sr.pak" type="data_package" lang="sr" />
+ <output filename="content_strings_sv.pak" type="data_package" lang="sv" />
+ <output filename="content_strings_sw.pak" type="data_package" lang="sw" />
+ <output filename="content_strings_ta.pak" type="data_package" lang="ta" />
+ <output filename="content_strings_te.pak" type="data_package" lang="te" />
+ <output filename="content_strings_th.pak" type="data_package" lang="th" />
+ <output filename="content_strings_tr.pak" type="data_package" lang="tr" />
+ <if expr="use_third_party_translations">
+ <output filename="webkit_strings_ug.pak" type="data_package" lang="ug" />
+ </if>
+ <output filename="content_strings_uk.pak" type="data_package" lang="uk" />
+ <output filename="content_strings_vi.pak" type="data_package" lang="vi" />
+ <output filename="content_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
+ <output filename="content_strings_zh-TW.pak" type="data_package" lang="zh-TW" />
+ </outputs>
+ <translations>
+ <file path="translations/content_strings_am.xtb" lang="am" />
+ <file path="translations/content_strings_ar.xtb" lang="ar" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_ast.xtb" lang="ast" />
+ </if>
+ <file path="translations/content_strings_bg.xtb" lang="bg" />
+ <file path="translations/content_strings_bn.xtb" lang="bn" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_bs.xtb" lang="bs" />
+ </if>
+ <file path="translations/content_strings_ca.xtb" lang="ca" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_ca-valencia.xtb" lang="ca@valencia" />
+ </if>
+ <file path="translations/content_strings_cs.xtb" lang="cs" />
+ <file path="translations/content_strings_da.xtb" lang="da" />
+ <file path="translations/content_strings_de.xtb" lang="de" />
+ <file path="translations/content_strings_el.xtb" lang="el" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_en-AU.xtb" lang="en-AU" />
+ </if>
+ <file path="translations/content_strings_en-GB.xtb" lang="en-GB" />
+ <file path="translations/content_strings_es.xtb" lang="es" />
+ <file path="translations/content_strings_es-419.xtb" lang="es-419" />
+ <file path="translations/content_strings_et.xtb" lang="et" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_eu.xtb" lang="eu" />
+ </if>
+ <file path="translations/content_strings_fa.xtb" lang="fa" />
+ <file path="translations/content_strings_fi.xtb" lang="fi" />
+ <file path="translations/content_strings_fil.xtb" lang="fil" />
+ <file path="translations/content_strings_fr.xtb" lang="fr" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_gl.xtb" lang="gl" />
+ </if>
+ <file path="translations/content_strings_gu.xtb" lang="gu" />
+ <file path="translations/content_strings_hi.xtb" lang="hi" />
+ <file path="translations/content_strings_hr.xtb" lang="hr" />
+ <file path="translations/content_strings_hu.xtb" lang="hu" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_hy.xtb" lang="hy" />
+ </if>
+ <file path="translations/content_strings_id.xtb" lang="id" />
+ <file path="translations/content_strings_it.xtb" lang="it" />
+ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
+ <file path="translations/content_strings_iw.xtb" lang="he" />
+ <file path="translations/content_strings_ja.xtb" lang="ja" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_ka.xtb" lang="ka" />
+ </if>
+ <file path="translations/content_strings_kn.xtb" lang="kn" />
+ <file path="translations/content_strings_ko.xtb" lang="ko" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_ku.xtb" lang="ku" />
+ <file path="../../third_party/launchpad_translations/webkit_strings_kw.xtb" lang="kw" />
+ </if>
+ <file path="translations/content_strings_lt.xtb" lang="lt" />
+ <file path="translations/content_strings_lv.xtb" lang="lv" />
+ <file path="translations/content_strings_ml.xtb" lang="ml" />
+ <file path="translations/content_strings_mr.xtb" lang="mr" />
+ <file path="translations/content_strings_ms.xtb" lang="ms" />
+ <file path="translations/content_strings_nl.xtb" lang="nl" />
+ <file path="translations/content_strings_no.xtb" lang="no" />
+ <file path="translations/content_strings_pl.xtb" lang="pl" />
+ <file path="translations/content_strings_pt-BR.xtb" lang="pt-BR" />
+ <file path="translations/content_strings_pt-PT.xtb" lang="pt-PT" />
+ <file path="translations/content_strings_ro.xtb" lang="ro" />
+ <file path="translations/content_strings_ru.xtb" lang="ru" />
+ <file path="translations/content_strings_sk.xtb" lang="sk" />
+ <file path="translations/content_strings_sl.xtb" lang="sl" />
+ <file path="translations/content_strings_sr.xtb" lang="sr" />
+ <file path="translations/content_strings_sv.xtb" lang="sv" />
+ <file path="translations/content_strings_sw.xtb" lang="sw" />
+ <file path="translations/content_strings_ta.xtb" lang="ta" />
+ <file path="translations/content_strings_te.xtb" lang="te" />
+ <file path="translations/content_strings_th.xtb" lang="th" />
+ <file path="translations/content_strings_tr.xtb" lang="tr" />
+ <if expr="use_third_party_translations">
+ <file path="../../third_party/launchpad_translations/webkit_strings_ug.xtb" lang="ug" />
+ </if>
+ <file path="translations/content_strings_uk.xtb" lang="uk" />
+ <file path="translations/content_strings_vi.xtb" lang="vi" />
+ <file path="translations/content_strings_zh-CN.xtb" lang="zh-CN" />
+ <file path="translations/content_strings_zh-TW.xtb" lang="zh-TW" />
+ </translations>
+ <release seq="1" allow_pseudo="false">
+ <messages fallback_to_english="true">
+ <!-- TODO add all of your "string table" messages here. Remember to
+ change nontranslateable parts of the messages into placeholders (using the
+ <ph> element). You can also use the 'grit add' tool to help you identify
+ nontranslateable parts and create placeholders for them. -->
+
+ <message name="IDS_DETAILS_WITHOUT_SUMMARY_LABEL" desc="Clickable label to show detailed information or to hide the detailed information.">
+ Details
+ </message>
+ <message name="IDS_SEARCHABLE_INDEX_INTRO" desc="Text that appears at the start of nearly-obsolete webpages in the form of a 'searchable index'.">
+ This is a searchable index. Enter search keywords: '''
+ </message>
+ <message name="IDS_FORM_CALENDAR_CLEAR" desc="Label for a button which clears a date input field.">
+ Clear
+ </message>
+ <message name="IDS_FORM_CALENDAR_TODAY" desc="Label for a button which sets today to a date input field.">
+ Today
+ </message>
+ <message name="IDS_FORM_DATE_FORMAT_DAY_IN_MONTH" desc="Short word to indicate which is the day-in-month part in a date format. e.g. 'Day' in 'Month/Day/Year'">
+ Day
+ </message>
+ <message name="IDS_FORM_DATE_FORMAT_MONTH" desc="Short word to indicate which is the month part in a date format. e.g. 'Month' in 'Month/Day/Year'">
+ Month
+ </message>
+ <message name="IDS_FORM_DATE_FORMAT_YEAR" desc="Short word to indicate which is the year part in a date format. e.g. 'Year' in 'Month/Day/Year'">
+ Year
+ </message>
+ <message name="IDS_FORM_SUBMIT_LABEL" desc="Default label for Submit buttons in forms on webpages.">
+ Submit
+ </message>
+ <message name="IDS_FORM_INPUT_ALT" desc="alt text for &lt;input&gt; elements with no alt, title, or value">
+ Submit
+ </message>
+ <message name="IDS_FORM_RESET_LABEL" desc="default label for Reset buttons in forms on webpages">
+ Reset
+ </message>
+ <message name="IDS_FORM_FILE_BUTTON_LABEL" desc="title for a single file chooser button used in HTML forms">
+ Choose File
+ </message>
+ <message name="IDS_FORM_MULTIPLE_FILES_BUTTON_LABEL" desc="title for a multiple file chooser button used in HTML forms. This title should be as short as possible.">
+ Choose Files
+ </message>
+ <message name="IDS_FORM_FILE_NO_FILE_LABEL" desc="text to display in file button used in HTML forms when no file is selected">
+ No file chosen
+ </message>
+ <message name="IDS_FORM_FILE_MULTIPLE_UPLOAD" desc="text to display next to file buttons in HTML forms when 2 or more files are selected for uploading. This is not used for a case that just 1 file is selected.">
+ <ph name="NUMBER_OF_FILES">$1<ex>3</ex></ph> files
+ </message>
+ <message name="IDS_FORM_OTHER_COLOR_LABEL" desc="Label for button that opens a full color chooser so the user can choose colors other than the ones in the list.">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_DATE_LABEL" desc="Label for button that opens a full calendar picker so the user can choose dates other than the ones in the list." meaning="for date label">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_MONTH_LABEL" desc="Label for button that opens a full month picker so the user can choose dates other than the ones in the list." meaning="for month label">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_TIME_LABEL" desc="Label for button that opens a full time picker so the user can choose dates other than the ones in the list." meaning="for time label">
+ Other...
+ </message>
+ <message name="IDS_FORM_OTHER_WEEK_LABEL" desc="Label for button that opens a full week picker so the user can choose dates other than the ones in the list." meaning="for week label">
+ Other...
+ </message>
+ <message name="IDS_FORM_PLACEHOLDER_FOR_DAY_OF_MONTH_FIELD" desc="Text for denoting day of month field position in date format. Short text is preferred. See http://crbug.com/152632 for samples.">
+ dd
+ </message>
+ <message name="IDS_FORM_PLACEHOLDER_FOR_MONTH_FIELD" desc="Text for denoting month field position in date format. Short text is preferred. See http://crbug.com/152632 for samples.">
+ mm
+ </message>
+ <message name="IDS_FORM_PLACEHOLDER_FOR_YEAR_FIELD" desc="Text for denoting day of month field position in date format. Short text is preferred. See http://crbug.com/152632 for samples.">
+ yyyy
+ </message>
+ <message name="IDS_FORM_SELECT_MENU_LIST_TEXT" desc="Text for the menu list rendering of a select element.">
+ <ph name="SELECTED_COUNT">$1<ex>3</ex></ph> selected
+ </message>
+ <message name="IDS_FORM_THIS_MONTH_LABEL" desc="Label for button in month picker to select this month.">
+ This month
+ </message>
+ <message name="IDS_FORM_THIS_WEEK_LABEL" desc="Label for button in week picker to select this week.">
+ This week
+ </message>
+ <message name="IDS_FORM_WEEK_NUMBER_LABEL" desc="Label for week number column in a calendar.">
+ Week
+ </message>
+
+ <message name="IDS_RECENT_SEARCHES_NONE" desc="Label for only item in menu that appears when clicking on the search field image, when no searches have been performed">
+ No recent searches
+ </message>
+ <message name="IDS_RECENT_SEARCHES" desc="label for first item in the menu that appears when clicking on the search field image, used as embedded menu title">
+ Recent Searches
+ </message>
+ <message name="IDS_RECENT_SEARCHES_CLEAR" desc="menu item in Recent Searches menu that empties menu's contents">
+ Clear Recent Searches
+ </message>
+
+ <message name="IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR" desc="Accessible description of a button to show month selection panel in a calendar picker.">
+ Show month selection panel
+ </message>
+ <message name="IDS_AX_CALENDAR_SHOW_NEXT_MONTH" desc="Accessible description of a button to show next month in a calendar picker.">
+ Show next month
+ </message>
+ <message name="IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH" desc="Accessible description of a button to show previous month in a calendar picker.">
+ Show previous month
+ </message>
+ <message name="IDS_AX_CALENDAR_WEEK_DESCRIPTION" desc="Accessible description of a button to select a specific week.">
+ <ph name="WEEK">$1<ex>Week 38, 2014</ex></ph>, starting on <ph name="WEEK_START_DATE">$2<ex>September 15, 2014</ex></ph>
+ </message>
+
+ <message name="IDS_AX_ROLE_ARTICLE" desc="accessibility role description for article">
+ article
+ </message>
+ <message name="IDS_AX_ROLE_BANNER" desc="accessibility role description for banner">
+ banner
+ </message>
+ <message name="IDS_AX_ROLE_COMPLEMENTARY" desc="accessibility role description for complementary">
+ complementary
+ </message>
+ <message name="IDS_AX_ROLE_WEB_AREA" desc="accessibility role description for web area">
+ HTML content
+ </message>
+ <message name="IDS_AX_ROLE_LINK" desc="accessibility role description for link">
+ link
+ </message>
+ <message name="IDS_AX_ROLE_LIST_MARKER" desc="accessibility role description for list marker">
+ list marker
+ </message>
+ <message name="IDS_AX_ROLE_IMAGE_MAP" desc="accessibility role description for image map">
+ image map
+ </message>
+ <message name="IDS_AX_ROLE_HEADING" desc="accessibility role description for headings">
+ heading
+ </message>
+ <message name="IDS_AX_ROLE_REGION" desc="accessibility role description for region">
+ region
+ </message>
+ <if expr="is_macosx">
+ <message name="IDS_AX_ROLE_FOOTER" desc="accessibility role description for footers">
+ footer
+ </message>
+ <message name="IDS_AX_ROLE_STEPPER" desc="accessibility role description for a stepper - a control where you can use up/down arrows to increment or decrement it. The name 'stepper' is how this user interface element is described by VoiceOver on Mac OS X; the translation should be consistent with VoiceOver.">
+ stepper
+ </message>
+ <message name="IDS_AX_ROLE_TOGGLE_BUTTON" desc="accessibility role description for a toggle button">
+ toggle button
+ </message>
+ </if>
+ <message name="IDS_AX_ROLE_ADDRESS" desc="accessibility role description for an address (as in a person's contact information)">
+ address
+ </message>
+ <message name="IDS_AX_ROLE_MAIN_CONTENT" desc="accessibility role description for main content of the document.">
+ main
+ </message>
+ <message name="IDS_AX_ROLE_NAVIGATIONAL_LINK" desc="accessibility role description for group of navigational links.">
+ navigation
+ </message>
+
+ <message name="IDS_AX_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a button is pressed, as used by accessibility.">
+ press
+ </message>
+ <message name="IDS_AX_RADIO_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a radio button is clicked, as used by accessibility.">
+ select
+ </message>
+ <message name="IDS_AX_TEXT_FIELD_ACTION_VERB" desc="Verb stating the action that will occur when a text field is selected, as used by accessibility.">
+ activate
+ </message>
+ <message name="IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB" desc="Verb stating the action that will occur when a checked checkbox is clicked, as used by accessibility.">
+ uncheck
+ </message>
+ <message name="IDS_AX_UNCHECKED_CHECK_BOX_ACTION_VERB" desc="Verb stating the action that will occur when an unchecked checkbox is clicked, as used by accessibility.">
+ check
+ </message>
+ <message name="IDS_AX_LINK_ACTION_VERB" desc="Verb stating the action that will occur when a link is clicked, as used by accessibility.">
+ jump
+ </message>
+
+ <message name="IDS_AX_AM_PM_FIELD_TEXT" desc="Accessible description of the AM/PM field in a date/time control">
+ AM/PM
+ </message>
+
+ <message name="IDS_AX_DAY_OF_MONTH_FIELD_TEXT" desc="Accessible description of the day of month field in a date/time control">
+ Day
+ </message>
+
+ <message name="IDS_AX_DATE_TIME_FIELD_EMPTY_VALUE_TEXT" desc="Accessible description of empty value of field in a date/time control">
+ blank
+ </message>
+
+ <message name="IDS_AX_HOUR_FIELD_TEXT" desc="Accessible description of the hour field in a date/time control">
+ Hours
+ </message>
+
+ <message name="IDS_AX_MEDIA_DEFAULT" desc="Accessible description of a media control.">
+ media control
+ </message>
+
+ <message name="IDS_AX_MEDIA_AUDIO_ELEMENT" desc="Accessible description of audio">
+ audio
+ </message>
+
+ <message name="IDS_AX_MEDIA_VIDEO_ELEMENT" desc="Accessible description of video">
+ video
+ </message>
+
+ <message name="IDS_AX_MEDIA_MUTE_BUTTON" desc="accessibility role description for mute button">
+ mute
+ </message>
+
+ <message name="IDS_AX_MEDIA_UNMUTE_BUTTON" desc="accessibility role description for turn mute off button">
+ unmute
+ </message>
+
+ <message name="IDS_AX_MEDIA_PLAY_BUTTON" desc="accessibility role description for play button">
+ play
+ </message>
+
+ <message name="IDS_AX_MEDIA_PAUSE_BUTTON" desc="accessibility role description for pause button">
+ pause
+ </message>
+
+ <message name="IDS_AX_MEDIA_SLIDER" desc="accessibility role description for timeline slider">
+ movie time
+ </message>
+
+ <message name="IDS_AX_MEDIA_SLIDER_THUMB" desc="accessibility role description for timeline thumb">
+ movie timeline thumb
+ </message>
+
+ <message name="IDS_AX_MEDIA_CURRENT_TIME_DISPLAY" desc="accessibility role description for elapsed time display">
+ elapsed time
+ </message>
+
+ <message name="IDS_AX_MEDIA_TIME_REMAINING_DISPLAY" desc="accessibility role description for time remaining display">
+ remaining time
+ </message>
+
+ <message name="IDS_AX_MEDIA_STATUS_DISPLAY" desc="accessibility role description for movie status">
+ status
+ </message>
+
+ <message name="IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON" desc="accessibility role description for enter fullscreen button">
+ enter full screen
+ </message>
+
+ <message name="IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON" desc="accessibility role description for exit fullscreen button">
+ exit full screen
+ </message>
+
+ <message name="IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON" desc="accessibility role description for show closed captions button">
+ show closed captions
+ </message>
+
+ <message name="IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON" desc="accessibility role description for hide closed captions button">
+ hide closed captions
+ </message>
+
+ <message name="IDS_AX_MEDIA_CAST_OFF_BUTTON" desc="accessibility role description for remote playback button">
+ play on remote device
+ </message>
+
+ <message name="IDS_AX_MEDIA_CAST_ON_BUTTON" desc="accessibility role description for remote playback control button">
+ control remote playback
+ </message>
+
+ <message name="IDS_AX_MEDIA_AUDIO_ELEMENT_HELP" desc="Accessible help of audio controls">
+ audio
+ </message>
+
+ <message name="IDS_AX_MEDIA_VIDEO_ELEMENT_HELP" desc="Accessible help of video">
+ video
+ </message>
+
+ <message name="IDS_AX_MEDIA_MUTE_BUTTON_HELP" desc="accessibility help description for mute button">
+ mute audio track
+ </message>
+
+ <message name="IDS_AX_MEDIA_UNMUTE_BUTTON_HELP" desc="accessibility help description for turn mute off button">
+ unmute audio track
+ </message>
+
+ <message name="IDS_AX_MEDIA_PLAY_BUTTON_HELP" desc="accessibility help description for play button">
+ begin playback
+ </message>
+
+ <message name="IDS_AX_MEDIA_PAUSE_BUTTON_HELP" desc="accessibility help description for pause button">
+ pause playback
+ </message>
+
+ <message name="IDS_AX_MEDIA_SLIDER_HELP" desc="accessibility help description for timeline slider">
+ movie time scrubber
+ </message>
+
+ <message name="IDS_AX_MEDIA_SLIDER_THUMB_HELP" desc="accessibility help description for timeline thumb">
+ movie time scrubber thumb
+ </message>
+
+ <message name="IDS_AX_MEDIA_CURRENT_TIME_DISPLAY_HELP" desc="accessibility help description for elapsed time display">
+ current time in seconds
+ </message>
+
+ <message name="IDS_AX_MEDIA_TIME_REMAINING_DISPLAY_HELP" desc="accessibility help description for time remaining display">
+ number of seconds ofmovie remaining
+ </message>
+
+ <message name="IDS_AX_MEDIA_STATUS_DISPLAY_HELP" desc="accessibility help description for movie status">
+ current movie status
+ </message>
+
+ <message name="IDS_AX_MEDIA_ENTER_FULL_SCREEN_BUTTON_HELP" desc="accessibility help description for enter fullscreen button">
+ play movie in full screen mode
+ </message>
+
+ <message name="IDS_AX_MEDIA_EXIT_FULL_SCREEN_BUTTON_HELP" desc="accessibility help description for exit fullscreen button">
+ exit full screen
+ </message>
+
+ <message name="IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP" desc="accessibility help description for show closed captions button">
+ start displaying closed captions
+ </message>
+
+ <message name="IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP" desc="accessibility help description for hide closed captions button">
+ stop displaying closed captions
+ </message>
+
+ <message name="IDS_AX_MEDIA_CAST_OFF_BUTTON_HELP" desc="accessibility help description for remote playback button">
+ play on remote device
+ </message>
+
+ <message name="IDS_AX_MEDIA_CAST_ON_BUTTON_HELP" desc="accessibility help description for remote playback control button">
+ control remote playback
+ </message>
+
+ <message name="IDS_AX_MILLISECOND_FIELD_TEXT" desc="Accessible description of the millisecond field in a date/time control">
+ Milliseconds
+ </message>
+
+ <message name="IDS_AX_MINUTE_FIELD_TEXT" desc="Accessible description of the minute field in a date/time control">
+ Minutes
+ </message>
+
+ <message name="IDS_AX_MONTH_FIELD_TEXT" desc="Accessible description of the month field in a date/time control">
+ Month
+ </message>
+
+ <message name="IDS_AX_SECOND_FIELD_TEXT" desc="Accessible description of the second field in a date/time control">
+ Seconds
+ </message>
+
+ <message name="IDS_AX_WEEK_OF_YEAR_FIELD_TEXT" desc="Accessible description of the week of year field in a date/time control">
+ Week
+ </message>
+
+ <message name="IDS_AX_YEAR_FIELD_TEXT" desc="Accessible description of the year field in a date/time control">
+ Year
+ </message>
+
+ <message name="IDS_KEYGEN_HIGH_GRADE_KEY" desc="High-grade cryptographic key size menu item">
+ 2048 (High Grade)
+ </message>
+ <message name="IDS_KEYGEN_MED_GRADE_KEY" desc="Medium-grade cryptographic key size menu item">
+ 1024 (Medium Grade)
+ </message>
+
+ <message name="IDS_FORM_INPUT_WEEK_TEMPLATE" desc="A specfic week (1-53) in a specific year shown in a form control">
+ Week <ph name="WEEKNUMBER">$2<ex>51</ex></ph>, <ph name="YEAR">$1<ex>2012</ex></ph>
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_MULTIPLE_FILE" desc="Heading or short sentence shown when a file upload control in a webpage requires one or more files selected, but the user didn't specify any files.">
+ Please select one or more files.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH" desc="Heading or short sentence shown when a form control in a webpage requires specific type such as email address or URL, but the specified value does not comform to the type.">
+ Invalid value.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY" desc="Heading or short sentence shown when there is an email field in a form and a user specified an empty value.">
+ Please enter a non-empty email address.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_DOMAIN" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'user@'.">
+ Please enter a part following '<ph name="ATSIGN">$1<ex>@</ex></ph>'. '<ph name="INVALIDADDRESS">$2<ex>user@</ex></ph>' is incomplete.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_EMPTY_LOCAL" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like '@example.com'.">
+ Please enter a part followed by '<ph name="ATSIGN">$1<ex>@</ex></ph>'. '<ph name="INVALIDADDRESS">$2<ex>@example.com</ex></ph>' is incomplete.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOMAIN" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'user@example,com'.">
+ A part following '<ph name="ATSIGN">$1<ex>@</ex></ph>' should not contain the symbol '<ph name="INVALIDCHARACTER">$2<ex>,</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_DOTS" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value with wrong dots like 'user@example..com'.">
+ '<ph name="DOT">$1<ex>.</ex></ph>' is used at a wrong position in '<ph name="INVALIDDOMAIN">$2<ex>example..com</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_INVALID_LOCAL" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value like 'us,er@example.com'.">
+ A part followed by '<ph name="ATSIGN">$1<ex>@</ex></ph>' should not contain the symbol '<ph name="INVALIDCHARACTER">$2<ex>,</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL_NO_AT_SIGN" desc="Heading or short sentence shown when there is an email field in a form and a user specified an invalid value liek 'user'.">
+ Please include an '<ph name="ATSIGN">$1<ex>@</ex></ph>' in the email address. '<ph name="INVALIDADDRESS">$2<ex>user</ex></ph>' is missing an '<ph name="ATSIGN">$1<ex>@</ex></ph>'.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_MULTIPLE_EMAIL" desc="Heading or short sentence shown there is a field which accepts multiple e-mail addresses and a user specified a value which is not a comma-separated e-mail addresses.">
+ Please enter a comma separated list of email addresses.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_UNDERFLOW" desc="Heading or short sentence shown when a form control value in a webpage needs to be larger than or equal to a minimum value specified by the page author, but a user specified a too small value.">
+ Value must be greater than or equal to <ph name="MINIMUM">$1<ex>0</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_UNDERFLOW_DATETIME" desc="Heading or short sentence shown when a form control value in a webpage needs to be later or equal to a minimum date/time value specified by the page author, but a user specified an earlier date/time.">
+ Value must be <ph name="MINIMUM_DATE_OR_TIME">$1<ex>01/04/2013</ex></ph> or later.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_OVERFLOW" desc="Heading or short sentence shown when a form control value in a webpage needs to be smaller than or equal to a maximum value specified by the page author, but a user specified a too large value.">
+ Value must be less than or equal to <ph name="MAXIMUM">$1<ex>100</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_RANGE_OVERFLOW_DATETIME" desc="Heading or short sentence shown when a form control value in a webpage needs to be earlier than or equal to a maximum date/time value specified by the page author, but a user specified a later date/time.">
+ Value must be <ph name="MAXIMUM_DATE_OR_TIME">$1<ex>12/31/2013</ex></ph> or earlier.
+ </message>
+ <message name="IDS_FORM_VALIDATION_BAD_INPUT_DATETIME" desc="Heading or short sentence shown when a user specified an incomplete value or an invalid date (such as 02/31/2012) to a date/time form control in a webpage.">
+ Please enter a valid value. The field is incomplete or has an invalid date.
+ </message>
+ <message name="IDS_FORM_VALIDATION_BAD_INPUT_NUMBER" desc="Heading or short sentence shown when a user entered a non-number string to a number field in a webpage.">
+ Please enter a number.
+ </message>
+
+<!-- The following IDS_FORM_VALIDATION_* messages were taken from Mozilla's dom.properties file.
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mitch <mstoltz@netscape.com> (original author)
+# Ehsan Akhgari <ehsan.akhgari@gmail.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+-->
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING" desc="Heading or short sentence shown when a text form control in a webpage requires a value, but the user didn't specify any value.">
+ Please fill out this field.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_CHECKBOX" desc="Heading or short sentence shown when a checkbox control in a webpage must be checked, but the user didn't check it.">
+ Please check this box if you want to proceed.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_FILE" desc="Heading or short sentence shown when a file upload control in a webpage requires a file selected, but the user didn't specify any file.">
+ Please select a file.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_RADIO" desc="Heading or short sentence shown when a radio button of a radio button group in a webpage must be selected, but the user selected nothing.">
+ Please select one of these options.
+ </message>
+ <message name="IDS_FORM_VALIDATION_VALUE_MISSING_SELECT" desc="Heading or short sentence shown when a value of a menu-list control in a webpage must be selected, but the user selected nothing.">
+ Please select an item in the list.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_EMAIL" desc="Heading or short sentence shown when there is an email field in a form and a user specified a value which doesn't look like an e-mail address.">
+ Please enter an email address.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TYPE_MISMATCH_URL" desc="Heading or short sentence shown when there is a URL field in a form and a user specified a value which doesn't look like a URL.">
+ Please enter a URL.
+ </message>
+ <message name="IDS_FORM_VALIDATION_PATTERN_MISMATCH" desc="Heading or short sentence shown when a form control value needs to satisfy a pattern specified by the page author, but a user specified unmatched value.">
+ Please match the requested format.
+ </message>
+ <message name="IDS_FORM_VALIDATION_STEP_MISMATCH" desc="Heading or short sentence shown when a form control value in a webpage should be aligned to a step value specified by the page author, but a user speficified non-aligned value. e.g. A number type field, minimum value is 0, and step value is 4. If A user-specified value is not a multiple of 4, this warning message is shown.">
+ Please enter a valid value. The two nearest valid values are <ph name="VALID_VALUE_LOW">$1<ex>4</ex></ph> and <ph name="VALID_VALUE_HIGHER">$2<ex>8</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_STEP_MISMATCH_CLOSE_TO_LIMIT" desc="Heading or short sentence shown when a form control value in a webpage should be aligned to a step value specified by the page author, but a user speficified non-aligned value. e.g. A number type field, minimum value is 0, and step value is 4. If A user-specified value is not a multiple of 4, this warning message is shown.">
+ Please enter a valid value. The nearest valid value is <ph name="VALID_VALUE">$1<ex>0</ex></ph>.
+ </message>
+ <message name="IDS_FORM_VALIDATION_TOO_LONG" desc="Heading or short sentence shown when a form control in a webpage needs to be shorter than a length specified by the page author, but a user specified long value.">
+ Please shorten this text to <ph name="MAX_CHARACTERS">$2<ex>100</ex></ph> characters or less (you are currently using <ph name="CURRENT_LENGTH">$1<ex>101</ex></ph> characters).
+ </message>
+ <message name="IDS_FORM_VALIDATION_TOO_SHORT" desc="Heading or short sentence shown when a form control in a webpage needs to be longer than a length specified by the page author, but a user specified short value.">
+ Please lengthen this text to <ph name="MIN_CHARACTERS">$2<ex>101</ex></ph> characters or more (you are currently using <ph name="CURRENT_LENGTH">$1<ex>100</ex></ph> characters).
+ </message>
+
+ <message name="IDS_PLUGIN_INITIALIZATION_ERROR" desc="A message displayed when a plug-in failed to load">
+ Couldn't load plug-in.
+ </message>
+
+ </messages>
+ </release>
+</grit>
diff --git a/chromium/content/app/strings/content_strings.gyp b/chromium/content/app/strings/content_strings.gyp
new file mode 100644
index 00000000000..e8f431018f2
--- /dev/null
+++ b/chromium/content/app/strings/content_strings.gyp
@@ -0,0 +1,30 @@
+# Copyright 2014 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.
+
+{
+ 'targets': [
+ {
+ # GN version: //content/app/strings
+ 'target_name': 'content_strings',
+ 'type': 'none',
+ 'variables': {
+ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/content/app/strings',
+ },
+ 'actions': [
+ {
+ 'action_name': 'generate_content_strings',
+ 'variables': {
+ 'grit_grd_file': 'content_strings.grd',
+ },
+ 'includes': [ '../../../build/grit_action.gypi' ],
+ },
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ },
+ },
+ ]
+}
diff --git a/chromium/content/app/strings/translations/content_strings_am.xtb b/chromium/content/app/strings/translations/content_strings_am.xtb
new file mode 100644
index 00000000000..8fa754a49e0
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_am.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="am">
+<translation id="4763480195061959176">ቪዲዮ</translation>
+<translation id="5843503607508392247">ሌላ...</translation>
+<translation id="248395913932153421">ቀን</translation>
+<translation id="1729654308190250600">እባክዎ ባዶ ያልሆነ የኢሜይል አድራሻ ያስገቡ።</translation>
+<translation id="6015796118275082299">ዓመት</translation>
+<translation id="1235745349614807883">የቅርብ ጊዜ ፍለጋዎችን አጽዳ</translation>
+<translation id="7223624360433298498">ያለፈው ጊዜ</translation>
+<translation id="1171774979989969504">እባክዎ የኢሜይል አድራሻ ያስገቡ።</translation>
+<translation id="709897737746224366">እባክዎ የተጠየቀውን ቅርጸት ያዛምዱ።</translation>
+<translation id="5048533449481078685">ዝርዝር አመልካች</translation>
+<translation id="4202807286478387388">ዝለል</translation>
+<translation id="5307600278924710095">እባክዎ አንድ ክፍል ያስገቡና «<ph name="ATSIGN"/>»ን ያስከትሉ። «<ph name="INVALIDADDRESS"/>» ያልተሟላ ነው።</translation>
+<translation id="2746543609216772311">ዋጋ <ph name="MINIMUM_DATE_OR_TIME"/> ወይም ከዚያ በኋላ መሆን አለበት።</translation>
+<translation id="2572483411312390101">አጫውት</translation>
+<translation id="8785498733064193001">መልሶ ማጫወት ይጀምሩ</translation>
+<translation id="7057186640035488495">የፊልም ሰዓት</translation>
+<translation id="8199524924445686405">ዓዓዓዓ</translation>
+<translation id="795667975304826397">ምንም ፋይል አልተመረጠም</translation>
+<translation id="7789962463072032349">ላፍታ አቁም</translation>
+<translation id="6853785296079745596">የተዘጉ የስዕል መግለጫዎችን ይደብቁ</translation>
+<translation id="4360991593054037559">እባክዎ የሚሰራ ዋጋ ያስገቡ። ሁለቱ የሚቀርቡ ዋጋዎች <ph name="VALID_VALUE_LOW"/> እና <ph name="VALID_VALUE_HIGHER"/> ናቸው።</translation>
+<translation id="1758486001363313524">ሌላ...</translation>
+<translation id="8141602879876242471">ይህ ሊፈለግ የሚችል መረጃ ጠቋሚ ነው። የፍለጋ ቁልፍ ቃላት አስገባ፦</translation>
+<translation id="1930711995431081526">ሁኔታ</translation>
+<translation id="658823671542763450">ወደ ሙሉ ገጽ ዕይታ ግባ</translation>
+<translation id="7720026100085573005">ቀሪ ጊዜ</translation>
+<translation id="370665806235115550">በመጫን ላይ...</translation>
+<translation id="2723001399770238859">ድምጽ</translation>
+<translation id="6845533974506654842">ተጫን</translation>
+<translation id="8244226242650769279">የምስል ካርታ</translation>
+<translation id="310520048233152454">እባክዎ አንድ ዩአርኤል ያስገቡ።</translation>
+<translation id="4812940957355064477">እባክዎ ቁጥር ያስገቡ።</translation>
+<translation id="2548326553472216322">የቅርብ ጊዜ ፍለጋዎች የሉም</translation>
+<translation id="1938124657309484470">ዋጋ <ph name="MAXIMUM_DATE_OR_TIME"/> ወይም ከዚያ በፊት መሆን አለበት።</translation>
+<translation id="7263440858009898357">እባክዎ በዝርዝሩ ውስጥ አንድ ንጥል ይምረጡ።</translation>
+<translation id="901493112792887934">የአሁኑ ጊዜ በሰከንዶች</translation>
+<translation id="5164977714490026579">ዋጋ ከ<ph name="MINIMUM"/> የሚበልጥ ወይም ከእሱ እኩል መሆን አለበት።</translation>
+<translation id="2247351761944213033">ሳምንት <ph name="WEEKNUMBER"/>፣ <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">የተዘጉ የስዕል መግለጫዎችን ማሳየት አቁም</translation>
+<translation id="5944544982112848342">2048(ከፍተኛ ደረጃ)</translation>
+<translation id="3075154866155599887">እባክዎ የሚሰራ ዋጋ ያስገቡ። መስኩ ያልተጠናቀቀ ነው ወይም ልክ ያልሆነ ቀን አለው።</translation>
+<translation id="3040011195152428237">አገናኝ</translation>
+<translation id="1014825444426747588">ባዶ</translation>
+<translation id="9050748414552849310">የተዘጉ የስዕል መግለጫዎችን አሳይ</translation>
+<translation id="4522570452068850558">ዝርዝሮች</translation>
+<translation id="8451268428117625855">እባክዎ ፋይል ይምረጡ።</translation>
+<translation id="8117451130807776954">በዚህ ሳምንት</translation>
+<translation id="5966707198760109579">ሳምንት</translation>
+<translation id="2901282870647571346">የአሁኑ የፊልም ሁኔታ</translation>
+<translation id="2060505056492490888">«<ph name="DOT"/>» በ«<ph name="INVALIDDOMAIN"/>» ውስጥ በተሳሳተ ቦታ ላይ ነው የገባው።</translation>
+<translation id="2674318244760992338">ግርጌ</translation>
+<translation id="8987927404178983737">ወር</translation>
+<translation id="8115662671911883373">የተዘጉ የስዕል መግለጫዎችን ማሳየት ጀምር</translation>
+<translation id="7364796246159120393">ፋይል ምረጥ</translation>
+<translation id="2761667185364618470">ለመቀጠል ከፈለጉ እባክዎ ይህ ሳጥን ላይ ምልክት ያድርጉ።</translation>
+<translation id="8534579021159131403">ደቂቃዎች</translation>
+<translation id="819205353528511139">ፊልሙን በሙሉ ማያ ገጽ ሁነታ አጫውት</translation>
+<translation id="4103419683916926126">ሚሊሰኮንዶች</translation>
+<translation id="838869780401515933">አመልክት</translation>
+<translation id="2846343701378493991">1024(መካከለኛ ደረጃ)</translation>
+<translation id="1637811476055996098">ፋይሎችን ይምረጡ</translation>
+<translation id="49969490063480558">እባክዎ ከ«<ph name="ATSIGN"/>» በኋላ አንድ ክፍል ያስገቡ። «<ph name="INVALIDADDRESS"/>» ያልተሟላ ነው።</translation>
+<translation id="5476505524087279545">አታመልክት</translation>
+<translation id="2148716181193084225">ዛሬ</translation>
+<translation id="2507943997699731163">እባክዎ ይህን መስክ ይሙሉት።</translation>
+<translation id="3785482301506746191">የፊልም ሰዓት አንፏቃቂ</translation>
+<translation id="739024184232394898">ሌላ...</translation>
+<translation id="383465348367842624">ከ«<ph name="ATSIGN"/>» በፊት የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER"/>» ምልክት መያዝ የለበትም።</translation>
+<translation id="5468998798572797635">ከሙሉ ማያ ገጽ ውጣ</translation>
+<translation id="5919473608089529604">ተሰኪ መጫን አልተቻለም።</translation>
+<translation id="5546461542133609677">ድምፅ-ከልን አንሳ</translation>
+<translation id="6663448176199120256">የቅርብ ጊዜ ፍለጋዎችን</translation>
+<translation id="1020833440720551630">የድምጽ ትራክ ላይ ድምጸ-ከል አድርግ</translation>
+<translation id="2597378329261239068">ይህ ሰነድ በይለፍ ቃል የተጠበቀ ነው። እባክዎ የይለፍ ቃል ያስገቡ።</translation>
+<translation id="5466621249238537318">እባክዎ አንድ ወይም ተጨማሪ ፋይሎችን ይምረጡ።</translation>
+<translation id="9132465097189459683">ሌላ...</translation>
+<translation id="10623998915015855">የማቀያየሪያ አዝራር</translation>
+<translation id="8750798805984357768">እባክዎ ከእነዚህ አማራጮች ውስጥ አንዱን ይምረጡ።</translation>
+<translation id="7740050170769002709">የኤች ቲ ኤም ኤል ይዘት</translation>
+<translation id="6692633176391053278">አስኪያጅ</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> ተመርጠዋል</translation>
+<translation id="8541249477527128034">የማህደረ መረጃ ቁጥጥር</translation>
+<translation id="2226276347425096477">እባክዎ ይህ ጽሑፍ ወደ <ph name="MAX_CHARACTERS"/> ወይም ከዚያ በታች ቁምፊዎች ያሳጥሩት (በአሁኑ ጊዜ <ph name="CURRENT_LENGTH"/> ቁምፊዎችን እየተጠቀሙ ነዎት)።</translation>
+<translation id="6101327004457443354">የድምጹ ትራክ ድምጸ-ከል አንሳ</translation>
+<translation id="1822429046913737220">ጥዋት/ከሰዓት</translation>
+<translation id="1639239467298939599">በመጫን ላይ</translation>
+<translation id="2908441821576996758">እባክዎ በኮማ የተለዩ የኢሜይል አድራሻዎች ዝርዝር ያስገቡ።</translation>
+<translation id="5939518447894949180">ዳግም አስጀምር</translation>
+<translation id="1921819250265091946">ቀቀ</translation>
+<translation id="2613802280814924224">እባክዎ የሚሰራ ዋጋ ያስገቡ። የሚቀርበው ዋጋ <ph name="VALID_VALUE"/> ነው።</translation>
+<translation id="835897206747267392">ልክ ያልሆነ እሴት።</translation>
+<translation id="1842960171412779397">ምረጥ</translation>
+<translation id="7673697353781729403">ሰዓቶች</translation>
+<translation id="4664250907885839816">ከ«<ph name="ATSIGN"/>» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER"/>» ምልክት መያዝ የለበትም።</translation>
+<translation id="3450233048674729344">ዋጋ ከ<ph name="MAXIMUM"/> የሚያንስ ወይም ከእሱ እኩል መሆን አለበት።</translation>
+<translation id="668171684555832681">ሌላ…</translation>
+<translation id="6270583010843788609">የፊልም ሰዓት መስመር አውራ ጣት</translation>
+<translation id="5641012560118721995">መልሶ ማጫወትን ለአፍታ አቁም</translation>
+<translation id="1591562245178063882">በዚህ ወር</translation>
+<translation id="6119846243427417423">አንቃ</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ፋይሎች</translation>
+<translation id="6643016212128521049">አጽዳ</translation>
+<translation id="7888071071722539607">እባክዎ በኢሜይል አድራሻው ውስጥ «<ph name="ATSIGN"/>» ያካትቱ። «<ph name="INVALIDADDRESS"/>» ውስጥ «<ph name="ATSIGN"/>» ይጎድላል።</translation>
+<translation id="1088086359088493902">ሰኮንዶች</translation>
+<translation id="3934680773876859118">የፒ ዲ ኤፍ ሰነድ መጫን አልተሳካም</translation>
+<translation id="3632707345189162177">የፊልሙ ቀሪ ሰከንዶች</translation>
+<translation id="6359256949422175976">የፊልም ሰዓት አንፏቃቂ አውራ ጣት</translation>
+<translation id="8597182159515967513">ርዕስ</translation>
+<translation id="6843725295806269523">ድምጸ-ከል ያድርጉ</translation>
+<translation id="2653659639078652383">አስገባ</translation>
+<translation id="3732799496749320381">ሚሜ</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ar.xtb b/chromium/content/app/strings/translations/content_strings_ar.xtb
new file mode 100644
index 00000000000..0e5cb7c89c3
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ar.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ar">
+<translation id="4763480195061959176">فيديو</translation>
+<translation id="5843503607508392247">آخر...</translation>
+<translation id="248395913932153421">يوم</translation>
+<translation id="1729654308190250600">يُرجى إدخال عنوان البريد الإلكتروني وعدم ترك الحق فارغًا.</translation>
+<translation id="6015796118275082299">عام</translation>
+<translation id="1235745349614807883">محو آخر عمليات البحث</translation>
+<translation id="7223624360433298498">المدة المنقضية</translation>
+<translation id="1171774979989969504">الرجاء إدخال عنوان البريد الإلكتروني.</translation>
+<translation id="709897737746224366">الرجاء مطابقة التنسيق المطلوب.</translation>
+<translation id="5048533449481078685">محدّد القائمة</translation>
+<translation id="4202807286478387388">الدخول</translation>
+<translation id="5307600278924710095">يُرجى إدخال جزء متبوع بعلامة &quot;<ph name="ATSIGN"/>&quot;، حيث إن &quot;<ph name="INVALIDADDRESS"/>&quot; غير مكتمل.</translation>
+<translation id="2746543609216772311">يجب أن تكون القيمة <ph name="MINIMUM_DATE_OR_TIME"/> أو بعد ذلك.</translation>
+<translation id="2572483411312390101">تشغيل</translation>
+<translation id="8785498733064193001">بدء التشغيل</translation>
+<translation id="7057186640035488495">وقت الفيلم</translation>
+<translation id="8199524924445686405">سنة</translation>
+<translation id="795667975304826397">ّلم يتمّ اختيار أيّ ملفّ</translation>
+<translation id="7789962463072032349">إيقاف مؤقت</translation>
+<translation id="6853785296079745596">إخفاء التسميات التوضيحية المغلقة</translation>
+<translation id="4360991593054037559">يُرجى إدخال قيمة صالحة. علمًا بأن القيم الصالحة تتراوح بين <ph name="VALID_VALUE_LOW"/> و<ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">آخر...</translation>
+<translation id="8141602879876242471">يمكن البحث في هذا الفهرس بإدخال كلمات مفتاحية:</translation>
+<translation id="1930711995431081526">الحالة</translation>
+<translation id="658823671542763450">تشغيل وضع ملء الشاشة</translation>
+<translation id="7720026100085573005">المدة المتبقية</translation>
+<translation id="370665806235115550">تحميل...</translation>
+<translation id="2723001399770238859">الصوت</translation>
+<translation id="6845533974506654842">اضغط</translation>
+<translation id="8244226242650769279">مخطّط صورة</translation>
+<translation id="310520048233152454">‏الرجاء إدخال عنوان URL.</translation>
+<translation id="4812940957355064477">الرجاء إدخال عدد.</translation>
+<translation id="2548326553472216322">لا عمليات بحث حديثة</translation>
+<translation id="1938124657309484470">يجب أن تكون القيمة <ph name="MAXIMUM_DATE_OR_TIME"/> أو قبل ذلك.</translation>
+<translation id="7263440858009898357">الرجاء تحديد عنصر من القائمة.</translation>
+<translation id="901493112792887934">المدة الحالية بالثواني</translation>
+<translation id="5164977714490026579">يجب أن تكون القيمة أكبر من أو تساوي <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">الأسبوع <ph name="WEEKNUMBER"/>، <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">إيقاف عرض التسميات التوضيحية المغلقة</translation>
+<translation id="5944544982112848342">2048 (درجة عالية)</translation>
+<translation id="3075154866155599887">يرجى إدخال قيمة صالحة. الحقل غير مكتمل أو أن التاريخ غير صالح.</translation>
+<translation id="3040011195152428237">رابط</translation>
+<translation id="1014825444426747588">فارغ</translation>
+<translation id="9050748414552849310">عرض التسميات التوضيحية المغلقة</translation>
+<translation id="4522570452068850558">التفاصيل</translation>
+<translation id="8451268428117625855">الرجاء تحديد ملف.</translation>
+<translation id="8117451130807776954">هذا الأسبوع</translation>
+<translation id="5966707198760109579">الأسبوع</translation>
+<translation id="2901282870647571346">حالة الفيلم الحالية</translation>
+<translation id="2060505056492490888">تم استخدام &quot;<ph name="DOT"/>&quot; في موضع خاطئ في &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">تذييل</translation>
+<translation id="8987927404178983737">شهر</translation>
+<translation id="8115662671911883373">بدء عرض التسميات التوضيحية المغلقة</translation>
+<translation id="7364796246159120393">اختيار ملفّ</translation>
+<translation id="2761667185364618470">الرجاء تحديد هذا المربع إذا أردت المتابعة.</translation>
+<translation id="8534579021159131403">دقائق</translation>
+<translation id="819205353528511139">تشغيل الفيلم في وضع ملء الشاشة</translation>
+<translation id="4103419683916926126">مللي ثانية</translation>
+<translation id="838869780401515933">الاختيار</translation>
+<translation id="2846343701378493991">1024 (درجة متوسطة)</translation>
+<translation id="1637811476055996098">اختيار الملفات</translation>
+<translation id="49969490063480558">يُرجى إدخال الجزء الذي يلي العلامة &quot;<ph name="ATSIGN"/>&quot;، حيث إن &quot;<ph name="INVALIDADDRESS"/>&quot; غير مكتمل.</translation>
+<translation id="5476505524087279545">إزالة علامة الاختيار</translation>
+<translation id="2148716181193084225">اليوم</translation>
+<translation id="2507943997699731163">الرجاء ملء هذا الحقل.</translation>
+<translation id="3785482301506746191">شريط تمرير وقت الفيلم</translation>
+<translation id="739024184232394898">آخر...</translation>
+<translation id="383465348367842624">الجزء المتبوع بالعلامة &quot;<ph name="ATSIGN"/>&quot; يجب ألا يشتمل على الرمز &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">إنهاء وضع ملء الشاشة</translation>
+<translation id="5919473608089529604">تعذر تحميل المكوّن الإضافي.</translation>
+<translation id="5546461542133609677">إعادة الصوت</translation>
+<translation id="6663448176199120256">آخر عمليات البحث</translation>
+<translation id="1020833440720551630">كتم صوت المقطع الصوتي</translation>
+<translation id="2597378329261239068">هذا المستند محمي بكلمة المرور. الرجاء إدخال كلمة مرور.</translation>
+<translation id="5466621249238537318">الرجاء تحديد ملف واحد أو أكثر.</translation>
+<translation id="9132465097189459683">آخر...</translation>
+<translation id="10623998915015855">زر التبديل</translation>
+<translation id="8750798805984357768">الرجاء اختيار أحد هذه الخيارات.</translation>
+<translation id="7740050170769002709">‏محتوى HTML</translation>
+<translation id="6692633176391053278">تخطي</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> محددة</translation>
+<translation id="8541249477527128034">التحكم في الوسائط</translation>
+<translation id="2226276347425096477">الرجاء اختصار هذا النص حتى يصل إلى <ph name="MAX_CHARACTERS"/> من الحروف أو أقل (أنت الآن تستخدم <ph name="CURRENT_LENGTH"/> من الحروف).</translation>
+<translation id="6101327004457443354">إعادة صوت المقطع الصوتي</translation>
+<translation id="1822429046913737220">صباحًا/مساءً</translation>
+<translation id="1639239467298939599">جارٍ التحميل.</translation>
+<translation id="2908441821576996758">الرجاء إدخال قائمة مفصولة بفواصل لعناوين البريد الإلكتروني.</translation>
+<translation id="5939518447894949180">إعادة</translation>
+<translation id="1921819250265091946">يوم</translation>
+<translation id="2613802280814924224">يُرجى إدخال قيمة صالحة. علمًا بأن أقرب قيمة صالحة هي <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">قيمة غير صحيحة</translation>
+<translation id="1842960171412779397">الاختيار</translation>
+<translation id="7673697353781729403">ساعات</translation>
+<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة &quot;<ph name="ATSIGN"/>&quot; على الرمز &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">يجب أن تكون القيمة أقل من أو تساوي <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">ملف تعريف آخر...</translation>
+<translation id="6270583010843788609">صورة مصغرة للتسلسل الزمني للفيلم</translation>
+<translation id="5641012560118721995">إيقاف التشغيل مؤقتًا</translation>
+<translation id="1591562245178063882">هذا الشهر</translation>
+<translation id="6119846243427417423">تنشيط</translation>
+<translation id="8444882422881193423">عدد الملفات: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">محو</translation>
+<translation id="7888071071722539607">يُرجى تضمين العلامة &quot;<ph name="ATSIGN"/>&quot; في عنوان البريد الإلكتروني، حيث يفتقر &quot;<ph name="INVALIDADDRESS"/>&quot; إلى العلامة &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">ثوانٍ‬‬</translation>
+<translation id="3934680773876859118">‏إخفاق تحميل مستند PDF</translation>
+<translation id="3632707345189162177">عدد الثواني المتبقية من الفيلم</translation>
+<translation id="6359256949422175976">صورة مصغرة لشريط تمرير وقت الفيلم</translation>
+<translation id="8597182159515967513">العنوان</translation>
+<translation id="6843725295806269523">كتم الصوت</translation>
+<translation id="2653659639078652383">إرسال</translation>
+<translation id="3732799496749320381">شهر</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_bg.xtb b/chromium/content/app/strings/translations/content_strings_bg.xtb
new file mode 100644
index 00000000000..1f309af56e5
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_bg.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bg">
+<translation id="4763480195061959176">видео</translation>
+<translation id="5843503607508392247">Други...</translation>
+<translation id="248395913932153421">Ден</translation>
+<translation id="1729654308190250600">Моля, въведете имейл адрес.</translation>
+<translation id="6015796118275082299">Година</translation>
+<translation id="1235745349614807883">Изчистване на скорошните търсения</translation>
+<translation id="7223624360433298498">изминало време</translation>
+<translation id="1171774979989969504">Моля, въведете имейл адрес.</translation>
+<translation id="709897737746224366">Моля, спазвайте изисквания формат.</translation>
+<translation id="5048533449481078685">списъчен показалец</translation>
+<translation id="4202807286478387388">преминаване</translation>
+<translation id="5307600278924710095">Моля, въведете текст преди „<ph name="ATSIGN"/>“. „<ph name="INVALIDADDRESS"/>“ е непълно.</translation>
+<translation id="2746543609216772311">Стойността трябва да е <ph name="MINIMUM_DATE_OR_TIME"/> или по-късно.</translation>
+<translation id="2572483411312390101">пускане</translation>
+<translation id="8785498733064193001">начало на възпроизвеждането</translation>
+<translation id="7057186640035488495">време от филма</translation>
+<translation id="8199524924445686405">гггг</translation>
+<translation id="795667975304826397">Няма избран файл</translation>
+<translation id="7789962463072032349">поставяне на пауза</translation>
+<translation id="6853785296079745596">скриване на надписите</translation>
+<translation id="4360991593054037559">Моля, въведете валидна стойност. Двете най-близки такива са <ph name="VALID_VALUE_LOW"/> и <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Други...</translation>
+<translation id="8141602879876242471">В този индекс може да се търси. Въведете ключови думи за търсене:</translation>
+<translation id="1930711995431081526">състояние</translation>
+<translation id="658823671542763450">вход за цял екран</translation>
+<translation id="7720026100085573005">оставащо време</translation>
+<translation id="370665806235115550">Зарежда се...</translation>
+<translation id="2723001399770238859">звук</translation>
+<translation id="6845533974506654842">натискане</translation>
+<translation id="8244226242650769279">карта с изображения</translation>
+<translation id="310520048233152454">Моля, въведете URL адрес.</translation>
+<translation id="4812940957355064477">Моля, въведете номер.</translation>
+<translation id="2548326553472216322">Няма скорошни търсения</translation>
+<translation id="1938124657309484470">Стойността трябва да е <ph name="MAXIMUM_DATE_OR_TIME"/> или по-рано.</translation>
+<translation id="7263440858009898357">Моля, изберете елемент в списъка.</translation>
+<translation id="901493112792887934">текущо време в секунди</translation>
+<translation id="5164977714490026579">Стойността трябва да е по-голяма или равна на <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Седмица <ph name="WEEKNUMBER"/>, <ph name="YEAR"/> г.</translation>
+<translation id="7740016676195725605">спиране на показването на надписите</translation>
+<translation id="5944544982112848342">2048 (висока степен на сложност)</translation>
+<translation id="3075154866155599887">Моля, въведете валидна стойност. Данните в полето са непълни или датата е невалидна.</translation>
+<translation id="3040011195152428237">връзка</translation>
+<translation id="1014825444426747588">празно</translation>
+<translation id="9050748414552849310">показване на надписите</translation>
+<translation id="4522570452068850558">Подробности</translation>
+<translation id="8451268428117625855">Моля, изберете файл.</translation>
+<translation id="8117451130807776954">Тази седмица</translation>
+<translation id="5966707198760109579">Седмица</translation>
+<translation id="2901282870647571346">текущо състояние на филма</translation>
+<translation id="2060505056492490888">„<ph name="DOT"/>“ се използва на неправилна позиция в/ъв „<ph name="INVALIDDOMAIN"/>“.</translation>
+<translation id="2674318244760992338">долен колонтитул</translation>
+<translation id="8987927404178983737">Месец</translation>
+<translation id="8115662671911883373">започване на показването на надписите</translation>
+<translation id="7364796246159120393">Избор на файл</translation>
+<translation id="2761667185364618470">Моля, поставете отметка в това квадратче, ако искате да продължите.</translation>
+<translation id="8534579021159131403">Минути</translation>
+<translation id="819205353528511139">пускане на филма в режим на цял екран</translation>
+<translation id="4103419683916926126">Милисекунди</translation>
+<translation id="838869780401515933">отмятане</translation>
+<translation id="2846343701378493991">1024 (средна степен на сложност)</translation>
+<translation id="1637811476055996098">Избор на файлове</translation>
+<translation id="49969490063480558">Моля, въведете текст след „<ph name="ATSIGN"/>“. „<ph name="INVALIDADDRESS"/>“ е непълно.</translation>
+<translation id="5476505524087279545">премахване на отметката</translation>
+<translation id="2148716181193084225">Днес</translation>
+<translation id="2507943997699731163">Моля, попълнете това поле.</translation>
+<translation id="3785482301506746191">времеви плъзгач за филма</translation>
+<translation id="739024184232394898">Други...</translation>
+<translation id="383465348367842624">Текстът преди „<ph name="ATSIGN"/>“ не бива да съдържа символа „<ph name="INVALIDCHARACTER"/>“.</translation>
+<translation id="5468998798572797635">изход от цял екран</translation>
+<translation id="5919473608089529604">Приставката не можа да се зареди.</translation>
+<translation id="5546461542133609677">пускане на звука</translation>
+<translation id="6663448176199120256">Скорошни търсения</translation>
+<translation id="1020833440720551630">заглушаване на аудиозаписа</translation>
+<translation id="2597378329261239068">Този документ е защитен с парола. Моля, въведете я.</translation>
+<translation id="5466621249238537318">Моля, изберете един или повече файлове.</translation>
+<translation id="9132465097189459683">Други...</translation>
+<translation id="10623998915015855">бутон за превключване</translation>
+<translation id="8750798805984357768">Моля, изберете една от тези опции.</translation>
+<translation id="7740050170769002709">HTML съдържание</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Избрани: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">медийна контрола</translation>
+<translation id="2226276347425096477">Моля, съкратете този текст до <ph name="MAX_CHARACTERS"/> знака или по-малко (понастоящем използвате <ph name="CURRENT_LENGTH"/> знака).</translation>
+<translation id="6101327004457443354">пускане на аудиозаписа</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Зарежда се</translation>
+<translation id="2908441821576996758">Моля, въведете списък с имейл адреси, разделени със запетаи.</translation>
+<translation id="5939518447894949180">Повторно задаване</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="2613802280814924224">Моля, въведете валидна стойност. Най-близката такава е <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Невалидна стойност.</translation>
+<translation id="1842960171412779397">Избиране</translation>
+<translation id="7673697353781729403">Часове</translation>
+<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN"/>“ не бива да съдържа символа „<ph name="INVALIDCHARACTER"/>“.</translation>
+<translation id="3450233048674729344">Стойността трябва да е по-малка или равна на <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Друг...</translation>
+<translation id="6270583010843788609">миниизображение за времевата контрола за филма</translation>
+<translation id="5641012560118721995">поставяне на възпроизвеждането на пауза</translation>
+<translation id="1591562245178063882">Този месец</translation>
+<translation id="6119846243427417423">активиране</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> файла</translation>
+<translation id="6643016212128521049">Изчистване</translation>
+<translation id="7888071071722539607">Моля, включете „<ph name="ATSIGN"/>“ в имейл адреса. В/ъв „<ph name="INVALIDADDRESS"/>“ липсва „<ph name="ATSIGN"/>“.</translation>
+<translation id="1088086359088493902">Секунди</translation>
+<translation id="3934680773876859118">PDF документът не успя да се зареди</translation>
+<translation id="3632707345189162177">брой оставащи секунди от филма</translation>
+<translation id="6359256949422175976">миниизображение за времевия плъзгач за филма</translation>
+<translation id="8597182159515967513">заглавие</translation>
+<translation id="6843725295806269523">заглушаване</translation>
+<translation id="2653659639078652383">Изпращане</translation>
+<translation id="3732799496749320381">мм</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_bn.xtb b/chromium/content/app/strings/translations/content_strings_bn.xtb
new file mode 100644
index 00000000000..51d9ded66ae
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_bn.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="bn">
+<translation id="4763480195061959176">ভিডিও</translation>
+<translation id="5843503607508392247">অন্যান্য...</translation>
+<translation id="248395913932153421">দিন</translation>
+<translation id="1729654308190250600">দয়া করে একটি খালি না থাকা ইমেল ঠিকানা লিখুন৷</translation>
+<translation id="6015796118275082299">বছর</translation>
+<translation id="1235745349614807883">সাম্প্রতিক অনুসন্ধানগুলি সাফ করুন</translation>
+<translation id="7223624360433298498">অতিবাহিত সময়</translation>
+<translation id="1171774979989969504">দয়া করে কোন ইমেল ঠিকানা প্রবেশ করান:</translation>
+<translation id="709897737746224366">দয়া করে অনুরোধ হওয়া বিন্যাসটি মেলান৷</translation>
+<translation id="5048533449481078685">তালিকা নির্দেশক</translation>
+<translation id="4202807286478387388">লাফ দিন</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN"/>' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS"/>' অসম্পূর্ণ৷</translation>
+<translation id="2746543609216772311">মানকে অবশ্যই <ph name="MINIMUM_DATE_OR_TIME"/> বা পরবর্তী হতে হবে৷</translation>
+<translation id="2572483411312390101">চালনা করুন</translation>
+<translation id="8785498733064193001">প্লেব্যাক শুরু করুন</translation>
+<translation id="7057186640035488495">চলচ্চিত্রের সময়</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">কোনও ফাইল চয়ন করা হয় নি</translation>
+<translation id="7789962463072032349">বিরাম</translation>
+<translation id="6853785296079745596">বন্ধ করা পরিচয়লিপিগুলি লুকান</translation>
+<translation id="4360991593054037559">দয়া করে একটি বৈধ মান লিখুন৷ দুটি কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE_LOW"/> এবং <ph name="VALID_VALUE_HIGHER"/>৷</translation>
+<translation id="1758486001363313524">অন্যান্য...</translation>
+<translation id="8141602879876242471">এটি অনুসন্ধানযোগ্য সূচি৷ অনুসন্ধানের মূলশব্দ প্রবেশ করান:</translation>
+<translation id="1930711995431081526">স্থিতি</translation>
+<translation id="658823671542763450">পূর্ণ স্ক্রীনে প্রবেশ করুন</translation>
+<translation id="7720026100085573005">অবশিষ্ট সময়</translation>
+<translation id="370665806235115550">লোড হচ্ছে...</translation>
+<translation id="2723001399770238859">অডিও</translation>
+<translation id="6845533974506654842">টিপুন</translation>
+<translation id="8244226242650769279">ছবি মানচিত্র</translation>
+<translation id="310520048233152454">দয়া করে একটি বৈধ URL প্রবেশ করুন৷</translation>
+<translation id="4812940957355064477">দয়া করে একটি সংখ্যা লিখুন৷</translation>
+<translation id="2548326553472216322">কোন সাম্প্রতিক অনুসন্ধান নেই</translation>
+<translation id="1938124657309484470">মানকে অবশ্যই <ph name="MAXIMUM_DATE_OR_TIME"/> বা আগের হতে হবে৷</translation>
+<translation id="7263440858009898357">তালিকা থেকে একটি আইটেম নির্বাচন করুন৷ </translation>
+<translation id="901493112792887934">সেকেন্ডে বর্তমান সময়</translation>
+<translation id="5164977714490026579">মানটি অবশ্যই <ph name="MINIMUM"/>এর চেয়ে বেশি বা সমান হবে৷</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/> সপ্তাহ, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">বদ্ধ পরিচয়লিপিগুলির প্রদর্শন থামান</translation>
+<translation id="5944544982112848342">2048 (উচ্চ গ্রেড)</translation>
+<translation id="3075154866155599887">দয়া করে একটি বৈধ মান লিখুন৷ ক্ষেত্রটি অসম্পূর্ণ অথবা একটি অবৈধ তারিখ আছে৷</translation>
+<translation id="3040011195152428237">লিঙ্ক</translation>
+<translation id="1014825444426747588">খালি</translation>
+<translation id="9050748414552849310">বন্ধ করা পরিচয়লিপিগুলি দেখান</translation>
+<translation id="4522570452068850558">বিশদ বিবরণ</translation>
+<translation id="8451268428117625855">দয়া করে একটি ফাইল নির্বাচন করুন৷</translation>
+<translation id="8117451130807776954">এই সপ্তাহ</translation>
+<translation id="5966707198760109579">সপ্তাহ</translation>
+<translation id="2901282870647571346">চলচ্চিত্রের বর্তমান অবস্থা</translation>
+<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN"/>' এ একটি ভুল অবস্থানে '<ph name="DOT"/>' ব্যবহৃত হয়েছে৷</translation>
+<translation id="2674318244760992338">পাদলেখ</translation>
+<translation id="8987927404178983737">মাস</translation>
+<translation id="8115662671911883373">বন্ধ পরিচয়লিপিগুলির প্রদর্শন শুরু করুন</translation>
+<translation id="7364796246159120393">ফাইল চয়ন করুন</translation>
+<translation id="2761667185364618470">আপনি যদি এগিয়ে যেতে চান তবে দয়া করে এই বাক্সটি পরীক্ষা করুন৷</translation>
+<translation id="8534579021159131403">মিনিট</translation>
+<translation id="819205353528511139">পূর্ণ স্ক্রীন মোডে চলচ্চিত্র চালান</translation>
+<translation id="4103419683916926126">মিলিসেকেন্ড</translation>
+<translation id="838869780401515933">চেক করুন</translation>
+<translation id="2846343701378493991">1024 (মধ্যম গ্রেড)</translation>
+<translation id="1637811476055996098">ফাইল চয়ন করুন</translation>
+<translation id="49969490063480558">দয়া করে '<ph name="ATSIGN"/>' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS"/>' অসম্পূর্ণ৷</translation>
+<translation id="5476505524087279545">আনচেক</translation>
+<translation id="2148716181193084225">আজ</translation>
+<translation id="2507943997699731163">দয়া করে এই ক্ষেত্রটি পূরণ করুন৷</translation>
+<translation id="3785482301506746191">চলচ্চিত্র সময় স্ক্রাবার</translation>
+<translation id="739024184232394898">অন্যান্য...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER"/>' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="5468998798572797635">পূর্ণ স্ক্রীন বন্ধ করুন</translation>
+<translation id="5919473608089529604">প্লাগ-ইন লোড করা যায়নি৷</translation>
+<translation id="5546461542133609677">সশব্দ</translation>
+<translation id="6663448176199120256">সাম্প্রতিক অনুসন্ধানগুলি</translation>
+<translation id="1020833440720551630">অডিও ট্র্যাক নিঃশব্দ করুন</translation>
+<translation id="2597378329261239068">এই দস্তাবেজটি পাসওয়ার্ড সুরক্ষিত৷ দয়া করে একটি পাসওয়ার্ড লিখুন৷</translation>
+<translation id="5466621249238537318">দয়া করে এক বা একাধিক ফাইল নির্বাচন করুন৷</translation>
+<translation id="9132465097189459683">অন্যান্য...</translation>
+<translation id="10623998915015855">টগল বোতাম</translation>
+<translation id="8750798805984357768">দয়া করে বিকল্পগুলির একটি নির্বাচন করুন৷</translation>
+<translation id="7740050170769002709">HTML সামগ্রী</translation>
+<translation id="6692633176391053278">পদক্ষেপকারী</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/>টি নির্বাচিত</translation>
+<translation id="8541249477527128034">মিডিয়া নিয়ন্ত্রণ</translation>
+<translation id="2226276347425096477">দয়া করে এই পাঠ্যটি <ph name="MAX_CHARACTERS"/>টি অক্ষর বা তার কমে (আপনি বর্তমানে <ph name="CURRENT_LENGTH"/>টি অক্ষর ব্যবহার করছেন) সংক্ষিপ্ত করুন৷</translation>
+<translation id="6101327004457443354">অডিও ট্র্যাক সশব্দ করুন</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">লোড হচ্ছে</translation>
+<translation id="2908441821576996758">দয়া করে ইমেল ঠিকানাগুলির একটি কমা দিয়ে আলাদা করা মান প্রবেশ করান৷</translation>
+<translation id="5939518447894949180">রিসেট করুন</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">দয়া করে একটি বৈধ মান লিখুন৷ কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE"/>৷</translation>
+<translation id="835897206747267392">অকার্যকর মান৷</translation>
+<translation id="1842960171412779397">নির্বাচন করুন</translation>
+<translation id="7673697353781729403">ঘন্টা</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER"/>' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="3450233048674729344">মানটি অবশ্যই <ph name="MAXIMUM"/>এর চেয়ে কম বা সমান হবে৷</translation>
+<translation id="668171684555832681">অন্যান্য...</translation>
+<translation id="6270583010843788609">চলচ্চিত্র টাইমলাইন থাম্ব</translation>
+<translation id="5641012560118721995">প্লেব্যাক বিরতি</translation>
+<translation id="1591562245178063882">এই মাস</translation>
+<translation id="6119846243427417423">সক্রিয় করুন</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> টি ফাইল</translation>
+<translation id="6643016212128521049">সাফ করুন</translation>
+<translation id="7888071071722539607">ইমেল ঠিনাকাটিতে দয়া করে একটি '<ph name="ATSIGN"/>' অন্তর্ভুক্ত করুন৷ '<ph name="INVALIDADDRESS"/>' এ একটি '<ph name="ATSIGN"/>' অনুপস্থিত৷</translation>
+<translation id="1088086359088493902">সেকেন্ড</translation>
+<translation id="3934680773876859118">PDF দস্তাবেজ লোড হতে ব্যর্থ</translation>
+<translation id="3632707345189162177">চলচ্চিত্রের অবশিষ্ট সেকেন্ড</translation>
+<translation id="6359256949422175976">চলচ্চিত্রের সময় স্ক্রাবার থাম্ব</translation>
+<translation id="8597182159515967513">শিরোনামা</translation>
+<translation id="6843725295806269523">নিঃশব্দ</translation>
+<translation id="2653659639078652383">জমা</translation>
+<translation id="3732799496749320381">মিমি</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ca.xtb b/chromium/content/app/strings/translations/content_strings_ca.xtb
new file mode 100644
index 00000000000..6de75457c3c
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ca.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ca">
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="5843503607508392247">Altres...</translation>
+<translation id="248395913932153421">Dia</translation>
+<translation id="1729654308190250600">Introduïu una adreça electrònica.</translation>
+<translation id="6015796118275082299">Any</translation>
+<translation id="1235745349614807883">Esborra les cerques recents</translation>
+<translation id="7223624360433298498">temps transcorregut</translation>
+<translation id="1171774979989969504">Introduïu una adreça electrònica.</translation>
+<translation id="709897737746224366">Feu servir el format sol·licitat.</translation>
+<translation id="5048533449481078685">marcador de llistes</translation>
+<translation id="4202807286478387388">salta</translation>
+<translation id="5307600278924710095">Introduïu un nom d'usuari seguit de &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; no és una adreça completa.</translation>
+<translation id="2746543609216772311">El valor ha de ser <ph name="MINIMUM_DATE_OR_TIME"/> o posterior.</translation>
+<translation id="2572483411312390101">reprodueix</translation>
+<translation id="8785498733064193001">inicia la reproducció</translation>
+<translation id="7057186640035488495">moment de la pel·lícula</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">No s'ha triat cap fitxer</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="6853785296079745596">amaga els subtítols ocults</translation>
+<translation id="4360991593054037559">Introduïu un valor vàlid. Els valors vàlids més propers són <ph name="VALID_VALUE_LOW"/> i <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Altres...</translation>
+<translation id="8141602879876242471">És un índex on es poden realitzar cerques. Introdueix els termes de cerca:</translation>
+<translation id="1930711995431081526">estat</translation>
+<translation id="658823671542763450">visualitza en pantalla completa</translation>
+<translation id="7720026100085573005">temps restant</translation>
+<translation id="370665806235115550">S'està carregant...</translation>
+<translation id="2723001399770238859">àudio</translation>
+<translation id="6845533974506654842">prem</translation>
+<translation id="8244226242650769279">mapa d'imatges</translation>
+<translation id="310520048233152454">Introduïu un URL.</translation>
+<translation id="4812940957355064477">Introduïu un número.</translation>
+<translation id="2548326553472216322">No hi ha cerques recents</translation>
+<translation id="1938124657309484470">El valor ha de ser <ph name="MAXIMUM_DATE_OR_TIME"/> o anterior.</translation>
+<translation id="7263440858009898357">Seleccioneu un element de la llista.</translation>
+<translation id="901493112792887934">temps actual en segons</translation>
+<translation id="5164977714490026579">El valor ha de ser més gran o igual que <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Setmana <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">deixa de mostrar subtítols ocults</translation>
+<translation id="5944544982112848342">2048 (Gran)</translation>
+<translation id="3075154866155599887">Introduïu un valor vàlid. El camp està incomplet o conté una data no vàlida.</translation>
+<translation id="3040011195152428237">enllaç</translation>
+<translation id="1014825444426747588">buit</translation>
+<translation id="9050748414552849310">mostra els subtítols ocults</translation>
+<translation id="4522570452068850558">Detalls</translation>
+<translation id="8451268428117625855">Seleccioneu un fitxer.</translation>
+<translation id="8117451130807776954">Aquesta setmana</translation>
+<translation id="5966707198760109579">Setmana</translation>
+<translation id="2901282870647571346">estat actual de la pel·lícula</translation>
+<translation id="2060505056492490888">&quot;<ph name="DOT"/>&quot; s'ha utilitzat en una posició incorrecta a &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">peu</translation>
+<translation id="8987927404178983737">Mes</translation>
+<translation id="8115662671911883373">comença a mostrar subtítols ocults</translation>
+<translation id="7364796246159120393">Tria un fitxer</translation>
+<translation id="2761667185364618470">Marqueu aquesta casella si voleu continuar.</translation>
+<translation id="8534579021159131403">Minuts</translation>
+<translation id="819205353528511139">reprodueix la pel·lícula en mode de pantalla completa</translation>
+<translation id="4103419683916926126">Mil·lisegons</translation>
+<translation id="838869780401515933">marca</translation>
+<translation id="2846343701378493991">1024 (Mitjà)</translation>
+<translation id="1637811476055996098">Trieu els fitxers</translation>
+<translation id="49969490063480558">Introduïu un domini precedit per &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; no és una adreça electrònica completa.</translation>
+<translation id="5476505524087279545">desmarca</translation>
+<translation id="2148716181193084225">Avui</translation>
+<translation id="2507943997699731163">Empleneu aquest camp.</translation>
+<translation id="3785482301506746191">barra de moment de la pel·lícula</translation>
+<translation id="739024184232394898">Altres...</translation>
+<translation id="383465348367842624">Un nom d'usuari seguit de &quot;<ph name="ATSIGN"/>&quot; no pot contenir el símbol &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">surt de la pantalla completa</translation>
+<translation id="5919473608089529604">No s'ha pogut carregar el connector.</translation>
+<translation id="5546461542133609677">activa el so</translation>
+<translation id="6663448176199120256">Cerques recents</translation>
+<translation id="1020833440720551630">silencia la pista d'àudio</translation>
+<translation id="2597378329261239068">Aquest document està protegit mitjançant contrasenya. Introduïu una contrasenya.</translation>
+<translation id="5466621249238537318">Seleccioneu un o diversos fitxers.</translation>
+<translation id="9132465097189459683">Altres...</translation>
+<translation id="10623998915015855">botó de commutació</translation>
+<translation id="8750798805984357768">Seleccioneu una d'aquestes opcions.</translation>
+<translation id="7740050170769002709">Contingut HTML</translation>
+<translation id="6692633176391053278">desplaçador</translation>
+<translation id="4975562563186953947">Elements seleccionats: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">control de mitjans</translation>
+<translation id="2226276347425096477">Escurceu aquest text a un màxim de <ph name="MAX_CHARACTERS"/> caràcters (ara n'esteu utilitzant <ph name="CURRENT_LENGTH"/>).</translation>
+<translation id="6101327004457443354">activa el so de la pista d'àudio</translation>
+<translation id="1822429046913737220">a. m./p. m.</translation>
+<translation id="1639239467298939599">S'està carregant</translation>
+<translation id="2908441821576996758">Introduïu una llista d'adreces electròniques separades per comes.</translation>
+<translation id="5939518447894949180">Restableix</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Introduïu un valor vàlid. El valor vàlid més proper és <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valor no vàlid.</translation>
+<translation id="1842960171412779397">selecciona</translation>
+<translation id="7673697353781729403">Hores</translation>
+<translation id="4664250907885839816">Un domini precedit per &quot;<ph name="ATSIGN"/>&quot; no pot contenir el símbol &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">El valor ha de ser més petit o igual que <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Altres...</translation>
+<translation id="6270583010843788609">miniatura de cronologia de pel·lícula</translation>
+<translation id="5641012560118721995">pausa la reproducció</translation>
+<translation id="1591562245178063882">Aquest mes</translation>
+<translation id="6119846243427417423">activa</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> fitxers</translation>
+<translation id="6643016212128521049">Esborra</translation>
+<translation id="7888071071722539607">Incloeu el símbol &quot;<ph name="ATSIGN"/>&quot; a l'adreça electrònica. Al camp &quot;<ph name="INVALIDADDRESS"/>&quot; falta el símbol &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Segons</translation>
+<translation id="3934680773876859118">No es pot carregar el document en format PDF</translation>
+<translation id="3632707345189162177">nombre de segons restants de la pel·lícula</translation>
+<translation id="6359256949422175976">miniatura de la barra de moment de la pel·lícula</translation>
+<translation id="8597182159515967513">Encapçalament</translation>
+<translation id="6843725295806269523">silencia</translation>
+<translation id="2653659639078652383">Envia</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_cs.xtb b/chromium/content/app/strings/translations/content_strings_cs.xtb
new file mode 100644
index 00000000000..276a0639ed7
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_cs.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="cs">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Jiné…</translation>
+<translation id="248395913932153421">Den</translation>
+<translation id="1729654308190250600">Vyplňte e-mailovou adresu.</translation>
+<translation id="6015796118275082299">Rok</translation>
+<translation id="1235745349614807883">Smazat nedávná vyhledávání</translation>
+<translation id="7223624360433298498">přehraný čas</translation>
+<translation id="1171774979989969504">Zadejte prosím e-mailovou adresu.</translation>
+<translation id="709897737746224366">Zadejte hodnotu, která odpovídá požadovanému formátu.</translation>
+<translation id="5048533449481078685">značka seznamu</translation>
+<translation id="4202807286478387388">přejít</translation>
+<translation id="5307600278924710095">Zadejte část před znakem <ph name="ATSIGN"/>. Adresa <ph name="INVALIDADDRESS"/> není úplná.</translation>
+<translation id="2746543609216772311">Datum musí být <ph name="MINIMUM_DATE_OR_TIME"/> nebo později.</translation>
+<translation id="2572483411312390101">přehrát</translation>
+<translation id="8785498733064193001">zahájit přehrávání</translation>
+<translation id="7057186640035488495">čas filmu</translation>
+<translation id="8199524924445686405">rrrr</translation>
+<translation id="795667975304826397">Soubor nevybrán</translation>
+<translation id="7789962463072032349">pozastavit</translation>
+<translation id="6853785296079745596">skrýt titulky</translation>
+<translation id="4360991593054037559">Zadejte platnou hodnotu. Dvě nejbližší hodnoty jsou <ph name="VALID_VALUE_LOW"/> a <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Jiné…</translation>
+<translation id="8141602879876242471">Toto je prohledávatelný index. Zadejte hledaná klíčová slova:</translation>
+<translation id="1930711995431081526">stav</translation>
+<translation id="658823671542763450">přejít do režimu celé obrazovky</translation>
+<translation id="7720026100085573005">zbývající čas</translation>
+<translation id="370665806235115550">Načítání...</translation>
+<translation id="2723001399770238859">zvuk</translation>
+<translation id="6845533974506654842">zmáčknout</translation>
+<translation id="8244226242650769279">obrázková mapa</translation>
+<translation id="310520048233152454">Zadejte prosím adresu URL.</translation>
+<translation id="4812940957355064477">Zadejte prosím číslo.</translation>
+<translation id="2548326553472216322">Žádná nedávná vyhledávání</translation>
+<translation id="1938124657309484470">Datum musí být <ph name="MAXIMUM_DATE_OR_TIME"/> nebo dříve.</translation>
+<translation id="7263440858009898357">Vyberte prosím v seznamu některou položku.</translation>
+<translation id="901493112792887934">aktuální čas v sekundách</translation>
+<translation id="5164977714490026579">Hodnota musí být větší nebo rovna <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. týden, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ukončit zobrazování titulků</translation>
+<translation id="5944544982112848342">2048 (vysoká kvalita)</translation>
+<translation id="3075154866155599887">Zadejte prosím platnou hodnotu. Pole obsahuje neúplnou hodnotu nebo neplatné datum.</translation>
+<translation id="3040011195152428237">odkaz</translation>
+<translation id="1014825444426747588">prázdné</translation>
+<translation id="9050748414552849310">zobrazit titulky</translation>
+<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="8451268428117625855">Vyberte prosím soubor.</translation>
+<translation id="8117451130807776954">Tento týden</translation>
+<translation id="5966707198760109579">Týden</translation>
+<translation id="2901282870647571346">aktuální stav filmu</translation>
+<translation id="2060505056492490888">Znak <ph name="DOT"/> v doméně <ph name="INVALIDDOMAIN"/> není použitý správně.</translation>
+<translation id="2674318244760992338">zápatí</translation>
+<translation id="8987927404178983737">Měsíc</translation>
+<translation id="8115662671911883373">zahájit zobrazování titulků</translation>
+<translation id="7364796246159120393">Vybrat soubor</translation>
+<translation id="2761667185364618470">Chcete-li pokračovat, zaškrtněte toto políčko.</translation>
+<translation id="8534579021159131403">Minuty</translation>
+<translation id="819205353528511139">přehrát film v režimu celé obrazovky</translation>
+<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="838869780401515933">zaškrtnout</translation>
+<translation id="2846343701378493991">1024 (Střední kvalita)</translation>
+<translation id="1637811476055996098">Zvolit soubory</translation>
+<translation id="49969490063480558">Zadejte část za znakem <ph name="ATSIGN"/>. Adresa <ph name="INVALIDADDRESS"/> není úplná.</translation>
+<translation id="5476505524087279545">odstranit zaškrtnutí</translation>
+<translation id="2148716181193084225">Dnes</translation>
+<translation id="2507943997699731163">Vyplňte prosím toto pole.</translation>
+<translation id="3785482301506746191">posuvník filmu</translation>
+<translation id="739024184232394898">Jiné…</translation>
+<translation id="383465348367842624">Část před znakem <ph name="ATSIGN"/> nesmí obsahovat znak <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="5468998798572797635">ukončit režim celé obrazovky</translation>
+<translation id="5919473608089529604">Plugin se nepodařilo načíst.</translation>
+<translation id="5546461542133609677">zapnout zvuk</translation>
+<translation id="6663448176199120256">Nedávná vyhledávání</translation>
+<translation id="1020833440720551630">ztlumit zvukovou stopu</translation>
+<translation id="2597378329261239068">Tento dokument je chráněn heslem. Zadejte prosím heslo.</translation>
+<translation id="5466621249238537318">Vyberte prosím jeden nebo více souborů.</translation>
+<translation id="9132465097189459683">Jiné…</translation>
+<translation id="10623998915015855">přepínací tlačítko</translation>
+<translation id="8750798805984357768">Vyberte jednu z těchto možností.</translation>
+<translation id="7740050170769002709">Obsah ve formátu HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Vybráno: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">ovládání médií</translation>
+<translation id="2226276347425096477">Zkraťte prosím tento text na <ph name="MAX_CHARACTERS"/> znaků nebo méně. (Aktuálně má <ph name="CURRENT_LENGTH"/> znaků.)</translation>
+<translation id="6101327004457443354">zapnout zvukovou stopu</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Načítání</translation>
+<translation id="2908441821576996758">Zadejte seznam e-mailových adres oddělených čárkami.</translation>
+<translation id="5939518447894949180">Resetovat</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Zadejte platnou hodnotu. Nejbližší platná hodnota je <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="1842960171412779397">zvolit</translation>
+<translation id="7673697353781729403">Hodiny</translation>
+<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN"/> nesmí obsahovat znak <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="3450233048674729344">Hodnota musí být menší nebo rovna <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Další...</translation>
+<translation id="6270583010843788609">náhled na časové ose filmu</translation>
+<translation id="5641012560118721995">pozastavit přehrávání</translation>
+<translation id="1591562245178063882">Tento měsíc</translation>
+<translation id="6119846243427417423">aktivovat</translation>
+<translation id="8444882422881193423">Počet souborů: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Vymazat</translation>
+<translation id="7888071071722539607">Do e-mailové adresy zahrňte znak <ph name="ATSIGN"/>. V adrese <ph name="INVALIDADDRESS"/> chybí znak <ph name="ATSIGN"/>.</translation>
+<translation id="1088086359088493902">Sekundy</translation>
+<translation id="3934680773876859118">Načítání dokumentu PDF se nezdařilo.</translation>
+<translation id="3632707345189162177">zbývající čas filmu v sekundách</translation>
+<translation id="6359256949422175976">náhled na posuvníku filmu</translation>
+<translation id="8597182159515967513">záhlaví</translation>
+<translation id="6843725295806269523">ztlumit</translation>
+<translation id="2653659639078652383">Odeslat</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_da.xtb b/chromium/content/app/strings/translations/content_strings_da.xtb
new file mode 100644
index 00000000000..6a297603f7f
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_da.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="da">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Andet...</translation>
+<translation id="248395913932153421">Dag</translation>
+<translation id="1729654308190250600">Angiv en e-mailadresse, der ikke er tom.</translation>
+<translation id="6015796118275082299">År</translation>
+<translation id="1235745349614807883">Slet nylige søgninger</translation>
+<translation id="7223624360433298498">forløbet tid</translation>
+<translation id="1171774979989969504">Angiv en e-mailadresse.</translation>
+<translation id="709897737746224366">Find et match til det anmodede format.</translation>
+<translation id="5048533449481078685">listemarkering</translation>
+<translation id="4202807286478387388">hop</translation>
+<translation id="5307600278924710095">Angiv den del, der kommer før &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; er ufuldstændig.</translation>
+<translation id="2746543609216772311">Værdien må ikke være tidligere end <ph name="MINIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="2572483411312390101">afspil</translation>
+<translation id="8785498733064193001">start afspilning</translation>
+<translation id="7057186640035488495">filmtid</translation>
+<translation id="8199524924445686405">åååå</translation>
+<translation id="795667975304826397">Der er ikke valgt nogen fil</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="6853785296079745596">skjul undertekster</translation>
+<translation id="4360991593054037559">Angiv en gyldig værdi. De to nærmeste gyldige værdier er <ph name="VALID_VALUE_LOW"/> og <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Andet...</translation>
+<translation id="8141602879876242471">Der kan søges i dette indeks. Indtast søge-nøgleord:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">åbn fuld skærm</translation>
+<translation id="7720026100085573005">resterende tid</translation>
+<translation id="370665806235115550">Indlæser...</translation>
+<translation id="2723001399770238859">lyd</translation>
+<translation id="6845533974506654842">tryk</translation>
+<translation id="8244226242650769279">billedekort</translation>
+<translation id="310520048233152454">Angiv en webadresse.</translation>
+<translation id="4812940957355064477">Angiv et nummer.</translation>
+<translation id="2548326553472216322">Ingen nylige søgninger</translation>
+<translation id="1938124657309484470">Værdien må ikke være senere end <ph name="MAXIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="7263440858009898357">Vælg et punkt på listen.</translation>
+<translation id="901493112792887934">aktuel tid i sekunder</translation>
+<translation id="5164977714490026579">Værdien skal være større end eller lig med <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Uge <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">stop visning af undertekster</translation>
+<translation id="5944544982112848342">2048 (Høj klasse)</translation>
+<translation id="3075154866155599887">Angiv en gyldig værdi. Feltet er ufuldstændigt eller har en ugyldig dato.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">tom</translation>
+<translation id="9050748414552849310">vis undertekster</translation>
+<translation id="4522570452068850558">Detaljer</translation>
+<translation id="8451268428117625855">Vælg en fil.</translation>
+<translation id="8117451130807776954">Denne uge</translation>
+<translation id="5966707198760109579">Uge</translation>
+<translation id="2901282870647571346">aktuel filmstatus</translation>
+<translation id="2060505056492490888">&quot;<ph name="DOT"/>&quot; er placeret forkert i &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">sidefod</translation>
+<translation id="8987927404178983737">Måned</translation>
+<translation id="8115662671911883373">start visning af undertekster</translation>
+<translation id="7364796246159120393">Vælg fil</translation>
+<translation id="2761667185364618470">Markér dette felt, hvis du vil fortsætte.</translation>
+<translation id="8534579021159131403">Minutter</translation>
+<translation id="819205353528511139">afspil film i fuld skærm</translation>
+<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="838869780401515933">markér</translation>
+<translation id="2846343701378493991">1024 (Mellemklasse)</translation>
+<translation id="1637811476055996098">Vælg filer</translation>
+<translation id="49969490063480558">Angiv den del, der kommer efter &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; er ufuldstændig.</translation>
+<translation id="5476505524087279545">fjern markering</translation>
+<translation id="2148716181193084225">I dag</translation>
+<translation id="2507943997699731163">Udfyld dette felt.</translation>
+<translation id="3785482301506746191">filmtidsskyder</translation>
+<translation id="739024184232394898">Andet...</translation>
+<translation id="383465348367842624">Den del, der kommer før &quot;<ph name="ATSIGN"/>&quot;, må ikke indeholde &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">afslut fuld skærm</translation>
+<translation id="5919473608089529604">Pluginnet kunne ikke indlæses.</translation>
+<translation id="5546461542133609677">slå lyd til</translation>
+<translation id="6663448176199120256">Nylige søgninger</translation>
+<translation id="1020833440720551630">slå lydspor fra</translation>
+<translation id="2597378329261239068">Dette dokument er adgangskodebeskyttet. Indtast en adgangskode.</translation>
+<translation id="5466621249238537318">Vælg en eller flere filer.</translation>
+<translation id="9132465097189459683">Andet...</translation>
+<translation id="10623998915015855">til/fra-knap</translation>
+<translation id="8750798805984357768">Vælg en af disse muligheder.</translation>
+<translation id="7740050170769002709">HTML-indhold</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> er valgt</translation>
+<translation id="8541249477527128034">mediekontrol</translation>
+<translation id="2226276347425096477">Forkort denne tekst til <ph name="MAX_CHARACTERS"/> tegn eller færre (du bruger i øjeblikket <ph name="CURRENT_LENGTH"/> tegn).</translation>
+<translation id="6101327004457443354">slå lydspor til</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Indlæser...</translation>
+<translation id="2908441821576996758">Angiv en kommasepareret liste over e-mailadresser.</translation>
+<translation id="5939518447894949180">Nulstil</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Angiv en gyldig værdi. Den nærmeste gyldige værdi er <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Ugyldig værdi.</translation>
+<translation id="1842960171412779397">vælg</translation>
+<translation id="7673697353781729403">Timer</translation>
+<translation id="4664250907885839816">Den del, der kommer efter &quot;<ph name="ATSIGN"/>&quot;, må ikke indeholde symbolet &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Værdien skal være mindre end eller lig med <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Andre...</translation>
+<translation id="6270583010843788609">miniature for tidslinje</translation>
+<translation id="5641012560118721995">pause</translation>
+<translation id="1591562245178063882">Denne måned</translation>
+<translation id="6119846243427417423">aktiver</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> filer</translation>
+<translation id="6643016212128521049">Ryd</translation>
+<translation id="7888071071722539607">E-mailadressen skal indeholde et &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; mangler et &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Sekunder</translation>
+<translation id="3934680773876859118">PDF-dokumentet kunne ikke indlæses</translation>
+<translation id="3632707345189162177">antal sekunder tilbage af filmen</translation>
+<translation id="6359256949422175976">miniature for filmtidsskyder</translation>
+<translation id="8597182159515967513">overskrift</translation>
+<translation id="6843725295806269523">slå lyden fra</translation>
+<translation id="2653659639078652383">Indsend</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_de.xtb b/chromium/content/app/strings/translations/content_strings_de.xtb
new file mode 100644
index 00000000000..a6c1c904fef
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_de.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="de">
+<translation id="4763480195061959176">Video</translation>
+<translation id="5843503607508392247">Andere...</translation>
+<translation id="248395913932153421">Tag</translation>
+<translation id="1729654308190250600">Geben Sie eine E-Mail-Adresse ein.</translation>
+<translation id="6015796118275082299">Jahr</translation>
+<translation id="1235745349614807883">Vor Kurzem durchgeführte Suchanfragen löschen</translation>
+<translation id="7223624360433298498">Vergangene Zeit</translation>
+<translation id="1171774979989969504">Geben Sie eine E-Mail-Adresse ein.</translation>
+<translation id="709897737746224366">Ihre Eingabe muss mit dem geforderten Format übereinstimmen.</translation>
+<translation id="5048533449481078685">Listenmarkierung</translation>
+<translation id="4202807286478387388">springen</translation>
+<translation id="5307600278924710095">Geben Sie etwas vor dem <ph name="ATSIGN"/>-Zeichen ein. Die Angabe &quot;<ph name="INVALIDADDRESS"/>&quot; ist unvollständig.</translation>
+<translation id="2746543609216772311">Verwenden Sie <ph name="MINIMUM_DATE_OR_TIME"/> oder einen späteren Wert.</translation>
+<translation id="2572483411312390101">Wiedergeben</translation>
+<translation id="8785498733064193001">Wiedergabe starten</translation>
+<translation id="7057186640035488495">Filmdauer</translation>
+<translation id="8199524924445686405">jjjj</translation>
+<translation id="795667975304826397">Keine ausgewählt</translation>
+<translation id="7789962463072032349">Pausieren</translation>
+<translation id="6853785296079745596">Untertitel ausblenden</translation>
+<translation id="4360991593054037559">Geben Sie einen gültigen Wert ein. Die zwei nächstliegenden gültigen Werte sind <ph name="VALID_VALUE_LOW"/> und <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Andere...</translation>
+<translation id="8141602879876242471">Dieser Index kann durchsucht werden. Geben Sie Suchbegriffe ein:</translation>
+<translation id="1930711995431081526">Status</translation>
+<translation id="658823671542763450">Vollbildmodus aktivieren</translation>
+<translation id="7720026100085573005">Verbleibende Zeit</translation>
+<translation id="370665806235115550">Wird geladen...</translation>
+<translation id="2723001399770238859">Audio</translation>
+<translation id="6845533974506654842">klicken</translation>
+<translation id="8244226242650769279">Imagemap</translation>
+<translation id="310520048233152454">Geben Sie eine URL ein.</translation>
+<translation id="4812940957355064477">Geben Sie eine Nummer ein.</translation>
+<translation id="2548326553472216322">Keine vor Kurzem durchgeführte Suchanfragen</translation>
+<translation id="1938124657309484470">Verwenden Sie <ph name="MAXIMUM_DATE_OR_TIME"/> oder einen früheren Wert.</translation>
+<translation id="7263440858009898357">Wählen Sie ein Element in der Liste aus.</translation>
+<translation id="901493112792887934">Aktuelle Dauer in Sekunden</translation>
+<translation id="5164977714490026579">Wert muss größer als oder gleich <ph name="MINIMUM"/> sein.</translation>
+<translation id="2247351761944213033">Woche <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">Keine Untertitel mehr anzeigen</translation>
+<translation id="5944544982112848342">2048 (High Grade)</translation>
+<translation id="3075154866155599887">Geben Sie einen gültigen Wert ein. Das Feld ist nicht vollständig oder enthält ein ungültiges Datum.</translation>
+<translation id="3040011195152428237">Link</translation>
+<translation id="1014825444426747588">leer</translation>
+<translation id="9050748414552849310">Untertitel anzeigen</translation>
+<translation id="4522570452068850558">Details</translation>
+<translation id="8451268428117625855">Wählen Sie eine Datei aus.</translation>
+<translation id="8117451130807776954">Diese Woche</translation>
+<translation id="5966707198760109579">Woche</translation>
+<translation id="2901282870647571346">Aktueller Filmstatus</translation>
+<translation id="2060505056492490888">Das Punktzeichen &quot;<ph name="DOT"/>&quot; steht in &quot;<ph name="INVALIDDOMAIN"/>&quot; an einer falschen Stelle.</translation>
+<translation id="2674318244760992338">Fußzeile</translation>
+<translation id="8987927404178983737">Monat</translation>
+<translation id="8115662671911883373">Untertitel ab sofort anzeigen</translation>
+<translation id="7364796246159120393">Datei auswählen</translation>
+<translation id="2761667185364618470">Aktivieren Sie dieses Kontrollkästchen, wenn Sie fortfahren möchten.</translation>
+<translation id="8534579021159131403">Minuten</translation>
+<translation id="819205353528511139">Film im Vollbildmodus ansehen</translation>
+<translation id="4103419683916926126">Millisekunden</translation>
+<translation id="838869780401515933">auswählen</translation>
+<translation id="2846343701378493991">1024 (mittlere Stufe)</translation>
+<translation id="1637811476055996098">Dateien auswählen</translation>
+<translation id="49969490063480558">Geben Sie etwas nach dem <ph name="ATSIGN"/>-Zeichen ein. Die Angabe &quot;<ph name="INVALIDADDRESS"/>&quot; ist unvollständig.</translation>
+<translation id="5476505524087279545">Auswahl aufheben</translation>
+<translation id="2148716181193084225">Heute</translation>
+<translation id="2507943997699731163">Füllen Sie dieses Feld aus.</translation>
+<translation id="3785482301506746191">Video-Zeitachse</translation>
+<translation id="739024184232394898">Andere...</translation>
+<translation id="383465348367842624">Vor dem <ph name="ATSIGN"/>-Zeichen darf das Zeichen &quot;<ph name="INVALIDCHARACTER"/>&quot; nicht verwendet werden.</translation>
+<translation id="5468998798572797635">Vollbildmodus beenden</translation>
+<translation id="5919473608089529604">Plug-in konnte nicht geladen werden.</translation>
+<translation id="5546461542133609677">Ton an</translation>
+<translation id="6663448176199120256">Vor Kurzem durchgeführte Suchanfragen</translation>
+<translation id="1020833440720551630">Ton ausschalten</translation>
+<translation id="2597378329261239068">Dieses Dokument ist passwortgeschützt. Geben Sie ein Passwort ein.</translation>
+<translation id="5466621249238537318">Wählen Sie eine oder mehrere Dateien aus.</translation>
+<translation id="9132465097189459683">Andere...</translation>
+<translation id="10623998915015855">Schaltfläche zum Umschalten</translation>
+<translation id="8750798805984357768">Wählen Sie eine dieser Optionen aus.</translation>
+<translation id="7740050170769002709">HTML-Inhalte</translation>
+<translation id="6692633176391053278">Stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> ausgewählt</translation>
+<translation id="8541249477527128034">Mediensteuerung</translation>
+<translation id="2226276347425096477">Kürzen Sie diesen Text auf max. <ph name="MAX_CHARACTERS"/> Zeichen. Zurzeit verwenden Sie <ph name="CURRENT_LENGTH"/> Zeichen.</translation>
+<translation id="6101327004457443354">Ton anschalten</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Wird geladen...</translation>
+<translation id="2908441821576996758">Geben Sie eine durch Kommas getrennte Liste der E-Mail-Adressen ein.</translation>
+<translation id="5939518447894949180">Zurücksetzen</translation>
+<translation id="1921819250265091946">tt</translation>
+<translation id="2613802280814924224">Geben Sie einen gültigen Wert ein. Der nächstliegende gültige Wert ist <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Ungültiger Wert.</translation>
+<translation id="1842960171412779397">auswählen</translation>
+<translation id="7673697353781729403">Stunden</translation>
+<translation id="4664250907885839816">Nach dem <ph name="ATSIGN"/>-Zeichen darf das Zeichen &quot;<ph name="INVALIDCHARACTER"/>&quot; nicht verwendet werden.</translation>
+<translation id="3450233048674729344">Wert muss kleiner als oder gleich <ph name="MAXIMUM"/> sein.</translation>
+<translation id="668171684555832681">Andere...</translation>
+<translation id="6270583010843788609">Zeitachsen-Ziehpunkt</translation>
+<translation id="5641012560118721995">Wiedergabe anhalten</translation>
+<translation id="1591562245178063882">Aktueller Monat</translation>
+<translation id="6119846243427417423">aktivieren</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> Dateien</translation>
+<translation id="6643016212128521049">Löschen</translation>
+<translation id="7888071071722539607">Die E-Mail-Adresse muss ein <ph name="ATSIGN"/>-Zeichen enthalten. In der Angabe &quot;<ph name="INVALIDADDRESS"/>&quot; fehlt ein <ph name="ATSIGN"/>-Zeichen.</translation>
+<translation id="1088086359088493902">Sekunden</translation>
+<translation id="3934680773876859118">Fehler beim Laden des PDF-Dokuments</translation>
+<translation id="3632707345189162177">Verbleibende Dauer in Sekunden</translation>
+<translation id="6359256949422175976">Ziehpunkt für Video-Zeitachse</translation>
+<translation id="8597182159515967513">Kopfzeile</translation>
+<translation id="6843725295806269523">Stumm</translation>
+<translation id="2653659639078652383">Senden</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_el.xtb b/chromium/content/app/strings/translations/content_strings_el.xtb
new file mode 100644
index 00000000000..294e1cf682e
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_el.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="el">
+<translation id="4763480195061959176">βίντεο</translation>
+<translation id="5843503607508392247">Άλλες…</translation>
+<translation id="248395913932153421">Ημέρα</translation>
+<translation id="1729654308190250600">Καταχωρίστε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
+<translation id="6015796118275082299">Έτος</translation>
+<translation id="1235745349614807883">Διαγραφή πρόσφατων αναζητήσεων</translation>
+<translation id="7223624360433298498">χρόνος που παρήλθε</translation>
+<translation id="1171774979989969504">Εισαγάγετε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
+<translation id="709897737746224366">Αντιστοιχίστε τη ζητούμενη μορφή.</translation>
+<translation id="5048533449481078685">δείκτης λίστας</translation>
+<translation id="4202807286478387388">μεταπήδηση</translation>
+<translation id="5307600278924710095">Καταχωρίστε το τμήμα της διεύθυνσης πριν το σύμβολο &quot;<ph name="ATSIGN"/>&quot;. Η διεύθυνση &quot;<ph name="INVALIDADDRESS"/>&quot; δεν είναι πλήρης.</translation>
+<translation id="2746543609216772311">Η τιμή πρέπει να είναι <ph name="MINIMUM_DATE_OR_TIME"/> ή μεταγενέστερη.</translation>
+<translation id="2572483411312390101">αναπαραγωγή</translation>
+<translation id="8785498733064193001">έναρξη αναπαραγωγής</translation>
+<translation id="7057186640035488495">χρόνος ταινίας</translation>
+<translation id="8199524924445686405">εεεε</translation>
+<translation id="795667975304826397">Δεν επιλέχθηκε κανένα αρχείο.</translation>
+<translation id="7789962463072032349">παύση</translation>
+<translation id="6853785296079745596">απόκρυψη υπότιτλων</translation>
+<translation id="4360991593054037559">Καταχωρίστε μια έγκυρη τιμή. Οι δύο πιο κοντινές έγκυρες τιμές είναι <ph name="VALID_VALUE_LOW"/> και <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Άλλες…</translation>
+<translation id="8141602879876242471">Πρόκειται για ευρετήριο με δυνατότητα αναζήτησης. Πληκτρολογήστε λέξεις-κλειδιά αναζήτησης:</translation>
+<translation id="1930711995431081526">κατάσταση</translation>
+<translation id="658823671542763450">ενεργοποίηση πλήρους οθόνης</translation>
+<translation id="7720026100085573005">χρόνος που απομένει</translation>
+<translation id="370665806235115550">Φόρτωση...</translation>
+<translation id="2723001399770238859">ήχος</translation>
+<translation id="6845533974506654842">πατήστε</translation>
+<translation id="8244226242650769279">χάρτης εικόνας</translation>
+<translation id="310520048233152454">Εισαγάγετε μια διεύθυνση URL.</translation>
+<translation id="4812940957355064477">Εισαγάγετε έναν αριθμό.</translation>
+<translation id="2548326553472216322">Δεν υπάρχουν πρόσφατες αναζητήσεις</translation>
+<translation id="1938124657309484470">Η τιμή πρέπει να είναι <ph name="MAXIMUM_DATE_OR_TIME"/> ή προγενέστερη.</translation>
+<translation id="7263440858009898357">Επιλέξτε ένα στοιχείο από τη λίστα.</translation>
+<translation id="901493112792887934">τρέχων χρόνος σε δευτερόλεπτα</translation>
+<translation id="5164977714490026579">Η τιμή πρέπει να είναι μεγαλύτερη ή ίση του <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Εβδομάδα <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">διακοπή προβολής υπότιτλων</translation>
+<translation id="5944544982112848342">2048 (Υψηλός βαθμός)</translation>
+<translation id="3075154866155599887">Καταχωρίστε μια έγκυρη τιμή. Το πεδίο είναι ελλιπές ή περιέχει μη έγκυρη ημερομηνία.</translation>
+<translation id="3040011195152428237">σύνδεσμος</translation>
+<translation id="1014825444426747588">κενό</translation>
+<translation id="9050748414552849310">εμφάνιση υπότιτλων</translation>
+<translation id="4522570452068850558">Λεπτομέρειες</translation>
+<translation id="8451268428117625855">Επιλέξτε ένα αρχείο.</translation>
+<translation id="8117451130807776954">Αυτήν την εβδομάδα</translation>
+<translation id="5966707198760109579">Εβδομάδα</translation>
+<translation id="2901282870647571346">τρέχουσα κατάσταση ταινίας</translation>
+<translation id="2060505056492490888">Το σύμβολο &quot;<ph name="DOT"/>&quot; χρησιμοποιείται σε λάθος θέση στη διεύθυνση &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">υποσέλιδο</translation>
+<translation id="8987927404178983737">Μήνας</translation>
+<translation id="8115662671911883373">έναρξη προβολής υπότιτλων</translation>
+<translation id="7364796246159120393">Επιλογή αρχείου</translation>
+<translation id="2761667185364618470">Αν θέλετε να συνεχίσετε, επιλέξτε αυτό το πλαίσιο.</translation>
+<translation id="8534579021159131403">Λεπτά</translation>
+<translation id="819205353528511139">αναπαραγωγή ταινίας σε λειτουργία πλήρους οθόνης</translation>
+<translation id="4103419683916926126">Χιλιοστά του δευτερολέπτου</translation>
+<translation id="838869780401515933">ενεργοποίηση</translation>
+<translation id="2846343701378493991">1024 (Μέτριος βαθμός)</translation>
+<translation id="1637811476055996098">Επιλογή αρχείων</translation>
+<translation id="49969490063480558">Καταχωρίστε το τμήμα της διεύθυνσης μετά το σύμβολο &quot;<ph name="ATSIGN"/>&quot;. Η διεύθυνση &quot;<ph name="INVALIDADDRESS"/>&quot; δεν είναι πλήρης.</translation>
+<translation id="5476505524087279545">απενεργοποίηση</translation>
+<translation id="2148716181193084225">Σήμερα</translation>
+<translation id="2507943997699731163">Συμπληρώστε αυτό το πεδίο.</translation>
+<translation id="3785482301506746191">δείκτης χρόνου ταινίας</translation>
+<translation id="739024184232394898">Άλλες…</translation>
+<translation id="383465348367842624">Το τμήμα της διεύθυνσης πριν το σύμβολο &quot;<ph name="ATSIGN"/>&quot; δεν πρέπει να περιέχει το σύμβολο &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">έξοδος από πλήρη οθόνη</translation>
+<translation id="5919473608089529604">Αδυναμία φόρτωσης προσθήκης.</translation>
+<translation id="5546461542133609677">κατάργηση σίγασης</translation>
+<translation id="6663448176199120256">Πρόσφατες αναζητήσεις</translation>
+<translation id="1020833440720551630">σίγαση ήχου</translation>
+<translation id="2597378329261239068">Αυτό το έγγραφο προστατεύεται με κωδικό πρόσβασης. Πληκτρολογήστε έναν κωδικό πρόσβασης.</translation>
+<translation id="5466621249238537318">Επιλέξτε ένα ή περισσότερα αρχεία.</translation>
+<translation id="9132465097189459683">Άλλες…</translation>
+<translation id="10623998915015855">κουμπί εναλλαγής</translation>
+<translation id="8750798805984357768">Ορίστε μία από αυτές τις επιλογές.</translation>
+<translation id="7740050170769002709">Περιεχόμενο HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Επιλέχτηκαν <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">έλεγχος μέσων</translation>
+<translation id="2226276347425096477">Κάντε πιο σύντομο αυτό το κείμενο ώστε να έχει το πολύ <ph name="MAX_CHARACTERS"/> χαρακτήρες (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH"/> χαρακτήρες).</translation>
+<translation id="6101327004457443354">κατάργηση σίγασης ήχου</translation>
+<translation id="1822429046913737220">Π.Μ./Μ.Μ.</translation>
+<translation id="1639239467298939599">Γίνεται φόρτωση</translation>
+<translation id="2908441821576996758">Εισαγάγετε μια λίστα διευθύνσεων ηλεκτρονικού ταχυδρομείου διαχωρισμένη με κόμματα.</translation>
+<translation id="5939518447894949180">Επαναφορά</translation>
+<translation id="1921819250265091946">ηη</translation>
+<translation id="2613802280814924224">Καταχωρίστε μια έγκυρη τιμή. Η κοντινότερη έγκυρη τιμή είναι <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Μη έγκυρη τιμή.</translation>
+<translation id="1842960171412779397">επιλογή</translation>
+<translation id="7673697353781729403">Ώρες</translation>
+<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο &quot;<ph name="ATSIGN"/>&quot; δεν πρέπει να περιέχει το σύμβολο &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Η τιμή πρέπει να είναι μικρότερη ή ίση του <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Άλλο...</translation>
+<translation id="6270583010843788609">δείκτης κύλισης χρονικού πλαισίου ταινίας</translation>
+<translation id="5641012560118721995">παύση αναπαραγωγής</translation>
+<translation id="1591562245178063882">Αυτόν το μήνα</translation>
+<translation id="6119846243427417423">ενεργοποίηση</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> αρχεία</translation>
+<translation id="6643016212128521049">Διαγραφή</translation>
+<translation id="7888071071722539607">Συμπεριλάβετε το σύμβολο &quot;<ph name="ATSIGN"/>&quot; στη διεύθυνση ηλεκτρονικού ταχυδρομείου. Από τη διεύθυνση &quot;<ph name="INVALIDADDRESS"/>&quot; λείπει το σύμβολο &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Δευτερόλεπτα</translation>
+<translation id="3934680773876859118">Δεν ήταν δυνατή η φόρτωση του εγγράφου PDF</translation>
+<translation id="3632707345189162177">αριθμός δευτερολέπτων της ταινίας που απομένουν</translation>
+<translation id="6359256949422175976">δείκτης κύλισης χρόνου ταινίας</translation>
+<translation id="8597182159515967513">επικεφαλίδα</translation>
+<translation id="6843725295806269523">σίγαση</translation>
+<translation id="2653659639078652383">Υποβολή</translation>
+<translation id="3732799496749320381">μμ</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_en-GB.xtb b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
new file mode 100644
index 00000000000..ede2337381f
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="en-GB">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Other...</translation>
+<translation id="248395913932153421">Day</translation>
+<translation id="1729654308190250600">Please enter a non-empty email address.</translation>
+<translation id="6015796118275082299">Year</translation>
+<translation id="1235745349614807883">Clear Recent Searches</translation>
+<translation id="7223624360433298498">elapsed time</translation>
+<translation id="1171774979989969504">Please enter an email address.</translation>
+<translation id="709897737746224366">Please match the format requested.</translation>
+<translation id="5048533449481078685">list marker</translation>
+<translation id="4202807286478387388">jump</translation>
+<translation id="5307600278924710095">Please enter a part followed by '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' is incomplete.</translation>
+<translation id="2746543609216772311">Value must be <ph name="MINIMUM_DATE_OR_TIME"/> or later.</translation>
+<translation id="2572483411312390101">play</translation>
+<translation id="8785498733064193001">begin playback</translation>
+<translation id="7057186640035488495">film time</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">No file chosen</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="6853785296079745596">hide closed captions</translation>
+<translation id="4360991593054037559">Please enter a valid value. The two nearest valid values are <ph name="VALID_VALUE_LOW"/> and <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Other...</translation>
+<translation id="8141602879876242471">This is a searchable index. Enter search keywords:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">enter full screen</translation>
+<translation id="7720026100085573005">remaining time</translation>
+<translation id="370665806235115550">Loading...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">press</translation>
+<translation id="8244226242650769279">image map</translation>
+<translation id="310520048233152454">Please enter a URL.</translation>
+<translation id="4812940957355064477">Please enter a number.</translation>
+<translation id="2548326553472216322">No recent searches</translation>
+<translation id="1938124657309484470">Value must be <ph name="MAXIMUM_DATE_OR_TIME"/> or earlier.</translation>
+<translation id="7263440858009898357">Please select an item in the list.</translation>
+<translation id="901493112792887934">current time in seconds</translation>
+<translation id="5164977714490026579">Value must be greater than or equal to <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Week <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">stop displaying closed captions</translation>
+<translation id="5944544982112848342">2048 (High Grade)</translation>
+<translation id="3075154866155599887">Please enter a valid value. The field is incomplete or has an invalid date.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">blank</translation>
+<translation id="9050748414552849310">show closed captions</translation>
+<translation id="4522570452068850558">Details</translation>
+<translation id="8451268428117625855">Please select a file.</translation>
+<translation id="8117451130807776954">This week</translation>
+<translation id="5966707198760109579">Week</translation>
+<translation id="2901282870647571346">current film status</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' is used at a wrong position in '<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">footer</translation>
+<translation id="8987927404178983737">Month</translation>
+<translation id="8115662671911883373">start displaying closed captions</translation>
+<translation id="7364796246159120393">Choose file</translation>
+<translation id="2761667185364618470">Please tick this box if you want to proceed.</translation>
+<translation id="8534579021159131403">Minutes</translation>
+<translation id="819205353528511139">play film in full screen mode</translation>
+<translation id="4103419683916926126">Milliseconds</translation>
+<translation id="838869780401515933">tick</translation>
+<translation id="2846343701378493991">1024 (Medium Grade)</translation>
+<translation id="1637811476055996098">Choose Files</translation>
+<translation id="49969490063480558">Please enter a part following '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' is incomplete.</translation>
+<translation id="5476505524087279545">untick</translation>
+<translation id="2148716181193084225">Today</translation>
+<translation id="2507943997699731163">Please fill in this field.</translation>
+<translation id="3785482301506746191">film time scrubber</translation>
+<translation id="739024184232394898">Other...</translation>
+<translation id="383465348367842624">A part followed by '<ph name="ATSIGN"/>' should not contain the symbol '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="5468998798572797635">exit full screen</translation>
+<translation id="5919473608089529604">Couldn't load plug-in.</translation>
+<translation id="5546461542133609677">un-mute</translation>
+<translation id="6663448176199120256">Recent Searches</translation>
+<translation id="1020833440720551630">mute audio track</translation>
+<translation id="2597378329261239068">This document is password-protected. Please enter a password.</translation>
+<translation id="5466621249238537318">Please select one or more files.</translation>
+<translation id="9132465097189459683">Other...</translation>
+<translation id="10623998915015855">toggle button</translation>
+<translation id="8750798805984357768">Please select one of these options.</translation>
+<translation id="7740050170769002709">HTML content</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> selected</translation>
+<translation id="8541249477527128034">media control</translation>
+<translation id="2226276347425096477">Please shorten this text to <ph name="MAX_CHARACTERS"/> characters or less (you are currently using <ph name="CURRENT_LENGTH"/> characters).</translation>
+<translation id="6101327004457443354">un-mute audio track</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Loading</translation>
+<translation id="2908441821576996758">Please enter a comma-separated list of email addresses.</translation>
+<translation id="5939518447894949180">Reset</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Please enter a valid value. The nearest valid value is <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Invalid value.</translation>
+<translation id="1842960171412779397">select</translation>
+<translation id="7673697353781729403">Hours</translation>
+<translation id="4664250907885839816">A part following '<ph name="ATSIGN"/>' should not contain the symbol '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="3450233048674729344">Value must be less than or equal to <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Other...</translation>
+<translation id="6270583010843788609">film timeline thumb</translation>
+<translation id="5641012560118721995">pause playback</translation>
+<translation id="1591562245178063882">This month</translation>
+<translation id="6119846243427417423">activate</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> files</translation>
+<translation id="6643016212128521049">Clear</translation>
+<translation id="7888071071722539607">Please include an '<ph name="ATSIGN"/>' in the email address. '<ph name="INVALIDADDRESS"/>' is missing an '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">Seconds</translation>
+<translation id="3934680773876859118">Failed to load PDF document</translation>
+<translation id="3632707345189162177">number of seconds of film remaining</translation>
+<translation id="6359256949422175976">film time scrubber thumb</translation>
+<translation id="8597182159515967513">heading</translation>
+<translation id="6843725295806269523">mute</translation>
+<translation id="2653659639078652383">Submit</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_es-419.xtb b/chromium/content/app/strings/translations/content_strings_es-419.xtb
new file mode 100644
index 00000000000..00880020247
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_es-419.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es-419">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Otra...</translation>
+<translation id="248395913932153421">Día</translation>
+<translation id="1729654308190250600">Ingresa una dirección de correo electrónico que no esté vacía.</translation>
+<translation id="6015796118275082299">Año</translation>
+<translation id="1235745349614807883">Eliminar búsquedas recientes</translation>
+<translation id="7223624360433298498">tiempo transcurrido</translation>
+<translation id="1171774979989969504">Ingresa una dirección de correo electrónico.</translation>
+<translation id="709897737746224366">Haz coincidir el formato solicitado.</translation>
+<translation id="5048533449481078685">marcador de listas</translation>
+<translation id="4202807286478387388">saltar</translation>
+<translation id="5307600278924710095">Ingresa texto antes del signo &quot;<ph name="ATSIGN"/>&quot;. La dirección &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleta.</translation>
+<translation id="2746543609216772311">El valor debe ser igual o posterior a <ph name="MINIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="2572483411312390101">reproducir</translation>
+<translation id="8785498733064193001">comenzar la reproducción</translation>
+<translation id="7057186640035488495">horario de película</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">No se eligió archivo</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="6853785296079745596">ocultar los subtítulos</translation>
+<translation id="4360991593054037559">Ingresa un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW"/> y <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Otra...</translation>
+<translation id="8141602879876242471">Se trata de un índice que admite búsquedas. Escribe las palabras clave de búsqueda:</translation>
+<translation id="1930711995431081526">estado</translation>
+<translation id="658823671542763450">ingresar a pantalla completa</translation>
+<translation id="7720026100085573005">tiempo restante</translation>
+<translation id="370665806235115550">Cargando...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">hacer clic</translation>
+<translation id="8244226242650769279">mapa de imágenes</translation>
+<translation id="310520048233152454">Ingresa una URL.</translation>
+<translation id="4812940957355064477">Debes ingresar un número.</translation>
+<translation id="2548326553472216322">No hay búsquedas recientes</translation>
+<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
+<translation id="901493112792887934">tiempo actual en segundos</translation>
+<translation id="5164977714490026579">El valor debe ser mayor de o igual a <ph name="MINIMUM"/></translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">dejar de mostrar subtítulos</translation>
+<translation id="5944544982112848342">2048 (Grado elevado)</translation>
+<translation id="3075154866155599887">Debes ingresar un valor válido. El campo está incompleto o contiene una fecha no válida.</translation>
+<translation id="3040011195152428237">enlace</translation>
+<translation id="1014825444426747588">espacio en blanco</translation>
+<translation id="9050748414552849310">mostrar subtítulos</translation>
+<translation id="4522570452068850558">Detalles</translation>
+<translation id="8451268428117625855">Selecciona un archivo.</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="2901282870647571346">estado actual de la película</translation>
+<translation id="2060505056492490888">El signo &quot;<ph name="DOT"/>&quot; está colocado en una posición incorrecta en &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">pie de página</translation>
+<translation id="8987927404178983737">Mes</translation>
+<translation id="8115662671911883373">empezar a mostrar subtítulos</translation>
+<translation id="7364796246159120393">Seleccionar archivo</translation>
+<translation id="2761667185364618470">Controla esta casilla si deseas continuar.</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="819205353528511139">reproducir la película en modo de pantalla completa</translation>
+<translation id="4103419683916926126">Milisegundos</translation>
+<translation id="838869780401515933">marcar</translation>
+<translation id="2846343701378493991">1024 (Mediano)</translation>
+<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="49969490063480558">Ingresa texto después del signo &quot;<ph name="ATSIGN"/>&quot;. La dirección &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleta.</translation>
+<translation id="5476505524087279545">desmarcar</translation>
+<translation id="2148716181193084225">Hoy</translation>
+<translation id="2507943997699731163">Completa este campo</translation>
+<translation id="3785482301506746191">control deslizante de duración de la película</translation>
+<translation id="739024184232394898">Otra...</translation>
+<translation id="383465348367842624">El texto antes del signo &quot;<ph name="ATSIGN"/>&quot; no debe incluir el símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">salir de pantalla completa</translation>
+<translation id="5919473608089529604">No es posible cargar el complemento.</translation>
+<translation id="5546461542133609677">desactivar silencio</translation>
+<translation id="6663448176199120256">Búsquedas recientes</translation>
+<translation id="1020833440720551630">silenciar pista de audio</translation>
+<translation id="2597378329261239068">Este documento está protegido por contraseña. Ingresa una contraseña.</translation>
+<translation id="5466621249238537318">Selecciona uno o más archivos.</translation>
+<translation id="9132465097189459683">Otra...</translation>
+<translation id="10623998915015855">botón de activación</translation>
+<translation id="8750798805984357768">Selecciona una de estas opciones.</translation>
+<translation id="7740050170769002709">Contenido HTML</translation>
+<translation id="6692633176391053278">secuenciador</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> elementos seleccionados</translation>
+<translation id="8541249477527128034">control de medios</translation>
+<translation id="2226276347425096477">Acorta este texto a <ph name="MAX_CHARACTERS"/> caracteres o menos (actualmente estás usando <ph name="CURRENT_LENGTH"/> caracteres).</translation>
+<translation id="6101327004457443354">desactivar silencio de la pista de audio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Cargando</translation>
+<translation id="2908441821576996758">Ingresa una lista de direcciones de correo electrónico separadas por coma</translation>
+<translation id="5939518447894949180">Restablecer</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Ingresa un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valor no válido.</translation>
+<translation id="1842960171412779397">seleccionar</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="4664250907885839816">El texto después del signo &quot;<ph name="ATSIGN"/>&quot; no debe incluir el símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">El valor debe ser menor de o igual a <ph name="MAXIMUM"/></translation>
+<translation id="668171684555832681">Otro...</translation>
+<translation id="6270583010843788609">miniatura de línea de tiempo de la película</translation>
+<translation id="5641012560118721995">pausar reproducción</translation>
+<translation id="1591562245178063882">Este mes</translation>
+<translation id="6119846243427417423">activar</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> archivos</translation>
+<translation id="6643016212128521049">Borrar</translation>
+<translation id="7888071071722539607">Incluye un signo &quot;<ph name="ATSIGN"/>&quot; en la dirección de correo electrónico. La dirección &quot;<ph name="INVALIDADDRESS"/>&quot; no incluye el signo &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="3934680773876859118">No se pudo cargar el documento PDF</translation>
+<translation id="3632707345189162177">cantidad de segundos restantes de la película</translation>
+<translation id="6359256949422175976">miniatura del control deslizante de duración de la película</translation>
+<translation id="8597182159515967513">cabecera</translation>
+<translation id="6843725295806269523">silencio</translation>
+<translation id="2653659639078652383">Enviar</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb
new file mode 100644
index 00000000000..b34e66a0af1
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_es.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="es">
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="5843503607508392247">Otra...</translation>
+<translation id="248395913932153421">Día</translation>
+<translation id="1729654308190250600">Introduce una dirección de correo electrónico que no esté vacía.</translation>
+<translation id="6015796118275082299">Año</translation>
+<translation id="1235745349614807883">Eliminar búsquedas recientes</translation>
+<translation id="7223624360433298498">tiempo transcurrido</translation>
+<translation id="1171774979989969504">Introduce una dirección de correo electrónico</translation>
+<translation id="709897737746224366">Utiliza un formato que coincida con el solicitado</translation>
+<translation id="5048533449481078685">marcador de listas</translation>
+<translation id="4202807286478387388">saltar</translation>
+<translation id="5307600278924710095">Introduce texto seguido del signo &quot;<ph name="ATSIGN"/>&quot;. La dirección &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleta.</translation>
+<translation id="2746543609216772311">El valor debe ser igual o posterior a <ph name="MINIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="2572483411312390101">reproducir</translation>
+<translation id="8785498733064193001">iniciar reproducción</translation>
+<translation id="7057186640035488495">cronología de la película</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Ningún archivo seleccionado</translation>
+<translation id="7789962463072032349">pausar</translation>
+<translation id="6853785296079745596">ocultar subtítulos cerrados</translation>
+<translation id="4360991593054037559">Introduce un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW"/> y <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Otra...</translation>
+<translation id="8141602879876242471">Se trata de un índice que admite búsquedas. Introduce las palabras clave de búsqueda:</translation>
+<translation id="1930711995431081526">estado</translation>
+<translation id="658823671542763450">activar pantalla completa</translation>
+<translation id="7720026100085573005">tiempo restante</translation>
+<translation id="370665806235115550">Cargando...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">pulsar</translation>
+<translation id="8244226242650769279">mapa de imágenes</translation>
+<translation id="310520048233152454">Introduce una URL</translation>
+<translation id="4812940957355064477">Debes introducir un número.</translation>
+<translation id="2548326553472216322">No hay búsquedas recientes</translation>
+<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
+<translation id="901493112792887934">tiempo actual en segundos</translation>
+<translation id="5164977714490026579">El valor debe superior o igual a <ph name="MINIMUM"/></translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">dejar de mostrar subtítulos cerrados</translation>
+<translation id="5944544982112848342">2048 (Grado elevado)</translation>
+<translation id="3075154866155599887">Debes introducir un valor válido. El campo está incompleto o incluye una fecha no válida.</translation>
+<translation id="3040011195152428237">enlace</translation>
+<translation id="1014825444426747588">vacío</translation>
+<translation id="9050748414552849310">mostrar subtítulos cerrados</translation>
+<translation id="4522570452068850558">Detalles</translation>
+<translation id="8451268428117625855">Selecciona un archivo</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="2901282870647571346">estado actual de la película</translation>
+<translation id="2060505056492490888">El signo &quot;<ph name="DOT"/>&quot; está colocado en una posición incorrecta en la dirección &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">pie de página</translation>
+<translation id="8987927404178983737">Mes</translation>
+<translation id="8115662671911883373">iniciar la visualización de subtítulos cerrados</translation>
+<translation id="7364796246159120393">Seleccionar archivo</translation>
+<translation id="2761667185364618470">Selecciona esta casilla de verificación si quieres continuar</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="819205353528511139">reproducir la película en modo de pantalla completa</translation>
+<translation id="4103419683916926126">Millisegundos</translation>
+<translation id="838869780401515933">marcar</translation>
+<translation id="2846343701378493991">1024 (Mediano)</translation>
+<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="49969490063480558">Introduce texto detrás del signo &quot;<ph name="ATSIGN"/>&quot;. La dirección &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleta.</translation>
+<translation id="5476505524087279545">desmarcar</translation>
+<translation id="2148716181193084225">Hoy</translation>
+<translation id="2507943997699731163">Completa este campo</translation>
+<translation id="3785482301506746191">control deslizante de duración de la película</translation>
+<translation id="739024184232394898">Otra...</translation>
+<translation id="383465348367842624">El texto seguido del signo &quot;<ph name="ATSIGN"/>&quot; no debe incluir el símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">salir de pantalla completa</translation>
+<translation id="5919473608089529604">No se ha podido cargar el complemento.</translation>
+<translation id="5546461542133609677">activar sonido</translation>
+<translation id="6663448176199120256">Búsquedas recientes</translation>
+<translation id="1020833440720551630">silenciar pista de audio</translation>
+<translation id="2597378329261239068">Este documento está protegido por contraseña. Introduce una contraseña.</translation>
+<translation id="5466621249238537318">Selecciona uno o varios archivos</translation>
+<translation id="9132465097189459683">Otra...</translation>
+<translation id="10623998915015855">botón de activación</translation>
+<translation id="8750798805984357768">Selecciona una de estas opciones</translation>
+<translation id="7740050170769002709">Contenido HTML</translation>
+<translation id="6692633176391053278">secuenciador</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> seleccionados</translation>
+<translation id="8541249477527128034">control de medios</translation>
+<translation id="2226276347425096477">Reduce la longitud de este texto a <ph name="MAX_CHARACTERS"/> caracteres o menos (actualmente, el texto tiene <ph name="CURRENT_LENGTH"/> caracteres)</translation>
+<translation id="6101327004457443354">activar sonido de la pista de audio</translation>
+<translation id="1822429046913737220">A.M./P.M.</translation>
+<translation id="1639239467298939599">Cargando</translation>
+<translation id="2908441821576996758">Introduce una lista de direcciones de correo electrónico separada por comas</translation>
+<translation id="5939518447894949180">Restablecer</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Introduce un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valor no válido</translation>
+<translation id="1842960171412779397">seleccionar</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="4664250907885839816">El texto detrás del signo &quot;<ph name="ATSIGN"/>&quot; no debe incluir el símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">El valor debe inferior o igual a <ph name="MAXIMUM"/></translation>
+<translation id="668171684555832681">Otros...</translation>
+<translation id="6270583010843788609">miniatura de línea de tiempo de la película</translation>
+<translation id="5641012560118721995">pausar reproducción</translation>
+<translation id="1591562245178063882">Este mes</translation>
+<translation id="6119846243427417423">activar</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> archivos</translation>
+<translation id="6643016212128521049">Eliminar</translation>
+<translation id="7888071071722539607">Incluye un signo &quot;<ph name="ATSIGN"/>&quot; en la dirección de correo electrónico. La dirección &quot;<ph name="INVALIDADDRESS"/>&quot; no incluye el signo &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="3934680773876859118">Se ha producido un error al cargar el documento PDF.</translation>
+<translation id="3632707345189162177">número de segundos restantes de la película</translation>
+<translation id="6359256949422175976">miniatura del control deslizante de duración de la película</translation>
+<translation id="8597182159515967513">cabecera</translation>
+<translation id="6843725295806269523">silenciar</translation>
+<translation id="2653659639078652383">Enviar</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_et.xtb b/chromium/content/app/strings/translations/content_strings_et.xtb
new file mode 100644
index 00000000000..04d60ae91fa
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_et.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="et">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Muu ...</translation>
+<translation id="248395913932153421">päev</translation>
+<translation id="1729654308190250600">Sisestage mittetühi e-posti aadress.</translation>
+<translation id="6015796118275082299">Aasta</translation>
+<translation id="1235745349614807883">Kustuta viimased otsingud</translation>
+<translation id="7223624360433298498">möödunud aeg</translation>
+<translation id="1171774979989969504">Sisestage meiliaadress.</translation>
+<translation id="709897737746224366">Vastendage nõutav vorming.</translation>
+<translation id="5048533449481078685">loendilooja</translation>
+<translation id="4202807286478387388">liigu</translation>
+<translation id="5307600278924710095">Sisestage märgile „<ph name="ATSIGN"/>” eelnev osa. Aadress „<ph name="INVALIDADDRESS"/>” pole täielik.</translation>
+<translation id="2746543609216772311">Väärtus peab olema <ph name="MINIMUM_DATE_OR_TIME"/> või hilisem.</translation>
+<translation id="2572483411312390101">esitus</translation>
+<translation id="8785498733064193001">taasesituse alustamine</translation>
+<translation id="7057186640035488495">video aeg</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Pole valitud</translation>
+<translation id="7789962463072032349">peata</translation>
+<translation id="6853785296079745596">subtiitrite peitmine</translation>
+<translation id="4360991593054037559">Sisestage kehtiv väärtus. Kaks lähimat kehtivat väärtust on <ph name="VALID_VALUE_LOW"/> ja <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Muu ...</translation>
+<translation id="8141602879876242471">See on otsitav indeks. Sisestage otsingu jaoks märksõnad:</translation>
+<translation id="1930711995431081526">olek</translation>
+<translation id="658823671542763450">kuvamine täisekraanil</translation>
+<translation id="7720026100085573005">järelejäänud aeg</translation>
+<translation id="370665806235115550">Laadimine...</translation>
+<translation id="2723001399770238859">heli</translation>
+<translation id="6845533974506654842">vajuta</translation>
+<translation id="8244226242650769279">hüperpilt</translation>
+<translation id="310520048233152454">Sisestage URL.</translation>
+<translation id="4812940957355064477">Sisestage arv.</translation>
+<translation id="2548326553472216322">Pole viimaseid otsingud</translation>
+<translation id="1938124657309484470">Väärtus peab olema <ph name="MAXIMUM_DATE_OR_TIME"/> või varasem.</translation>
+<translation id="7263440858009898357">Valige loendist element.</translation>
+<translation id="901493112792887934">praegune aeg sekundites</translation>
+<translation id="5164977714490026579">Väärtus peab olema suurem või võrdne <ph name="MINIMUM"/>-ga.</translation>
+<translation id="2247351761944213033">Nädal <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">subtiitrite kuvamise peatamine</translation>
+<translation id="5944544982112848342">2048 (kõrge)</translation>
+<translation id="3075154866155599887">Sisestage kehtiv väärtus. Väli on täitmata või sisaldab sobimatut kuupäeva.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">tühi</translation>
+<translation id="9050748414552849310">subtiitrite kuvamine</translation>
+<translation id="4522570452068850558">Üksikasjad</translation>
+<translation id="8451268428117625855">Valige üks fail.</translation>
+<translation id="8117451130807776954">See nädal</translation>
+<translation id="5966707198760109579">Nädal</translation>
+<translation id="2901282870647571346">video praegune olek</translation>
+<translation id="2060505056492490888">Tähist „<ph name="DOT"/>” on aadressis „<ph name="INVALIDDOMAIN"/>” valesti kasutatud.</translation>
+<translation id="2674318244760992338">jalus</translation>
+<translation id="8987927404178983737">kuu</translation>
+<translation id="8115662671911883373">subtiitrite kuvamise alustamine</translation>
+<translation id="7364796246159120393">Vali fail</translation>
+<translation id="2761667185364618470">Märkige see ruut, kui soovite jätkata.</translation>
+<translation id="8534579021159131403">Minutid</translation>
+<translation id="819205353528511139">video esitus täisekraani režiimis</translation>
+<translation id="4103419683916926126">Millisekundid</translation>
+<translation id="838869780401515933">mrgista</translation>
+<translation id="2846343701378493991">1024 (keskmine)</translation>
+<translation id="1637811476055996098">Vali failid</translation>
+<translation id="49969490063480558">Sisestage märgile „<ph name="ATSIGN"/>” järgnev osa. Aadress „<ph name="INVALIDADDRESS"/>” pole täielik.</translation>
+<translation id="5476505524087279545">eemalda mrgistus</translation>
+<translation id="2148716181193084225">Täna</translation>
+<translation id="2507943997699731163">Täitke see väli.</translation>
+<translation id="3785482301506746191">video ajakursor</translation>
+<translation id="739024184232394898">Muu ...</translation>
+<translation id="383465348367842624">Märgile „<ph name="ATSIGN"/>” eelnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER"/>”.</translation>
+<translation id="5468998798572797635">täisekraanilt väljumine</translation>
+<translation id="5919473608089529604">Pistikprogrammi ei saanud laadida.</translation>
+<translation id="5546461542133609677">vaigistuse tühistamine</translation>
+<translation id="6663448176199120256">Viimased otsingud</translation>
+<translation id="1020833440720551630">heliraja vaigistamine</translation>
+<translation id="2597378329261239068">Dokument on parooliga kaitstud. Sisestage parool.</translation>
+<translation id="5466621249238537318">Valige üks või mitu faili.</translation>
+<translation id="9132465097189459683">Muu ...</translation>
+<translation id="10623998915015855">ümberlülitusnupp</translation>
+<translation id="8750798805984357768">Tehke üks nendest valikutest.</translation>
+<translation id="7740050170769002709">HTML-sisu</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Valitud on <ph name="SELECTED_COUNT"/> üksust</translation>
+<translation id="8541249477527128034">meedia juhtimine</translation>
+<translation id="2226276347425096477">Lühendage seda teksti <ph name="MAX_CHARACTERS"/> tähemärgini või rohkem (praegu kasutate <ph name="CURRENT_LENGTH"/> tähemärki).</translation>
+<translation id="6101327004457443354">heliraja vaigistamise tühistamine</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Laadimine</translation>
+<translation id="2908441821576996758">Sisestage meiliaadresside loend komadega eraldatult.</translation>
+<translation id="5939518447894949180">Lähtesta</translation>
+<translation id="1921819250265091946">pp</translation>
+<translation id="2613802280814924224">Sisestage kehtiv väärtus. Lähim kehtiv väärtus on <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Kehtetu väärtus.</translation>
+<translation id="1842960171412779397">vali</translation>
+<translation id="7673697353781729403">Tunnid</translation>
+<translation id="4664250907885839816">Märgile „<ph name="ATSIGN"/>” järgnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER"/>”.</translation>
+<translation id="3450233048674729344">Väärtus peab olema väiksem või võrdne <ph name="MAXIMUM"/>-ga.</translation>
+<translation id="668171684555832681">Muu...</translation>
+<translation id="6270583010843788609">video ajajoone pisipilt</translation>
+<translation id="5641012560118721995">taasesituse peatamine</translation>
+<translation id="1591562245178063882">See kuu</translation>
+<translation id="6119846243427417423">aktiveeri</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> faili</translation>
+<translation id="6643016212128521049">Tühjenda</translation>
+<translation id="7888071071722539607">Lisage e-posti aadressile märk „<ph name="ATSIGN"/>”. Aadressist „<ph name="INVALIDADDRESS"/>” puudub märk „<ph name="ATSIGN"/>”.</translation>
+<translation id="1088086359088493902">Sekundid</translation>
+<translation id="3934680773876859118">PDF-dokumendi laadimine nurjus</translation>
+<translation id="3632707345189162177">video järelejäänud aeg sekundites</translation>
+<translation id="6359256949422175976">video ajakursori pisipilt</translation>
+<translation id="8597182159515967513">pealkiri</translation>
+<translation id="6843725295806269523">vaigista</translation>
+<translation id="2653659639078652383">Esita</translation>
+<translation id="3732799496749320381">kk</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fa.xtb b/chromium/content/app/strings/translations/content_strings_fa.xtb
new file mode 100644
index 00000000000..f7c1c261577
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_fa.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fa">
+<translation id="4763480195061959176">ویدیو</translation>
+<translation id="5843503607508392247">موارد دیگر...</translation>
+<translation id="248395913932153421">روز</translation>
+<translation id="1729654308190250600">لطفاً یک آدرس ایمیل غیرخالی وارد کنید.</translation>
+<translation id="6015796118275082299">سال</translation>
+<translation id="1235745349614807883">پاک کردن جستجوهای اخیر</translation>
+<translation id="7223624360433298498">مدت سپری شده</translation>
+<translation id="1171774979989969504">لطفاً یک آدرس ایمیل وارد کنید.</translation>
+<translation id="709897737746224366">لطفاً با قالب درخواستی مطابقت دهید.</translation>
+<translation id="5048533449481078685">علامت گذار لیست</translation>
+<translation id="4202807286478387388">پرش</translation>
+<translation id="5307600278924710095">لطفاً قسمت قبل از «<ph name="ATSIGN"/>» را وارد کنید. «<ph name="INVALIDADDRESS"/>» ناقص است.</translation>
+<translation id="2746543609216772311">مقدار باید <ph name="MINIMUM_DATE_OR_TIME"/> یا بعد از آن باشد.</translation>
+<translation id="2572483411312390101">پخش</translation>
+<translation id="8785498733064193001">شروع پخش</translation>
+<translation id="7057186640035488495">زمان فیلم</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">فایلی انتخاب نشده است</translation>
+<translation id="7789962463072032349">توقف موقت</translation>
+<translation id="6853785296079745596">پنهان کردن توصیف‌های بسته</translation>
+<translation id="4360991593054037559">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقادیر معتبر <ph name="VALID_VALUE_LOW"/> و <ph name="VALID_VALUE_HIGHER"/> هستند.</translation>
+<translation id="1758486001363313524">موارد دیگر...</translation>
+<translation id="8141602879876242471">این نمایه قابل جستجو است. کلمات کلیدی جستجو را وارد کنید:</translation>
+<translation id="1930711995431081526">وضعیت</translation>
+<translation id="658823671542763450">رفتن به حالت تمام صفحه</translation>
+<translation id="7720026100085573005">زمان باقی‌مانده</translation>
+<translation id="370665806235115550">در حال بارگیری...</translation>
+<translation id="2723001399770238859">صدا</translation>
+<translation id="6845533974506654842">فشار دادن</translation>
+<translation id="8244226242650769279">نقشه تصویر</translation>
+<translation id="310520048233152454">‏لطفاً یک URL وارد کنید.</translation>
+<translation id="4812940957355064477">لطفاً شماره‌ای را وارد کنید.</translation>
+<translation id="2548326553472216322">جستجوی جدیدی وجود ندارد</translation>
+<translation id="1938124657309484470">مقدار باید <ph name="MAXIMUM_DATE_OR_TIME"/> یا قبل از آن باشد.</translation>
+<translation id="7263440858009898357">لطفاً یک مورد را در لیست انتخاب کنید.</translation>
+<translation id="901493112792887934">زمان کنونی به ثانیه</translation>
+<translation id="5164977714490026579">مقدار باید بیشتر یا مساوی با <ph name="MINIMUM"/> باشد.</translation>
+<translation id="2247351761944213033">هفته <ph name="WEEKNUMBER"/>، <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">توقف نمایش توصیف‌های بسته</translation>
+<translation id="5944544982112848342">2048 (درجه بالا)</translation>
+<translation id="3075154866155599887">لطفاً یک مقدار معتبر وارد کنید. این قسمت کامل نیست و یا تاریخ نامعتبر است.</translation>
+<translation id="3040011195152428237">پیوند</translation>
+<translation id="1014825444426747588">خالی</translation>
+<translation id="9050748414552849310">نمایش توصیف‌های بسته</translation>
+<translation id="4522570452068850558">جزئیات</translation>
+<translation id="8451268428117625855">لطفاً یک فایل انتخاب کنید.</translation>
+<translation id="8117451130807776954">این هفته</translation>
+<translation id="5966707198760109579">هفته</translation>
+<translation id="2901282870647571346">وضعیت کنونی فیلم</translation>
+<translation id="2060505056492490888">«<ph name="DOT"/>» در «<ph name="INVALIDDOMAIN"/>» در محل اشتباهی قرار دارد.</translation>
+<translation id="2674318244760992338">پانویس</translation>
+<translation id="8987927404178983737">ماه</translation>
+<translation id="8115662671911883373">شروع به نمایش توصیف‌های بسته</translation>
+<translation id="7364796246159120393">انتخاب فایل</translation>
+<translation id="2761667185364618470">در صورتی که می‌خواهید ادامه دهید، این کادر را انتخاب کنید.</translation>
+<translation id="8534579021159131403">دقیقه</translation>
+<translation id="819205353528511139">پخش فیلم در حالت تمام صفحه</translation>
+<translation id="4103419683916926126">میلی‌ ثانیه</translation>
+<translation id="838869780401515933">علامت‌گذاری</translation>
+<translation id="2846343701378493991">1024 (درجه متوسط)</translation>
+<translation id="1637811476055996098">انتخاب فایل‌ها</translation>
+<translation id="49969490063480558">لطفاً قسمت بعد از «<ph name="ATSIGN"/>» را وارد کنید. «<ph name="INVALIDADDRESS"/>» ناقص است.</translation>
+<translation id="5476505524087279545">برداشتن علامت</translation>
+<translation id="2148716181193084225">امروز</translation>
+<translation id="2507943997699731163">لطفاً این قسمت را تکمیل کنید.</translation>
+<translation id="3785482301506746191">حذف‌کننده زمان فیلم</translation>
+<translation id="739024184232394898">موارد دیگر...</translation>
+<translation id="383465348367842624">قسمت قبل از «<ph name="ATSIGN"/>» نباید حاوی نماد «<ph name="INVALIDCHARACTER"/>» باشد.</translation>
+<translation id="5468998798572797635">خروج از حالت تمام صفحه</translation>
+<translation id="5919473608089529604">افزونه بارگیری نشد.</translation>
+<translation id="5546461542133609677">صدادارکردن</translation>
+<translation id="6663448176199120256">جستجوهای جدید</translation>
+<translation id="1020833440720551630">بیصداکردن تراک صوتی</translation>
+<translation id="2597378329261239068">این سند توسط رمز ورود محافظت می‌شود. لطفاً یک رمز ورود وارد کنید.</translation>
+<translation id="5466621249238537318">لطفاً یک یا چند فایل را انتخاب کنید.</translation>
+<translation id="9132465097189459683">موارد دیگر...</translation>
+<translation id="10623998915015855">دکمه تغییر حالت</translation>
+<translation id="8750798805984357768">لطفاً یکی از این گزینه‌ها را انتخاب کنید.</translation>
+<translation id="7740050170769002709">‏محتوای HTML</translation>
+<translation id="6692633176391053278">گام به گام</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> انتخاب شد</translation>
+<translation id="8541249477527128034">کنترل رسانه</translation>
+<translation id="2226276347425096477">لطفاً این متن را به اندازه <ph name="MAX_CHARACTERS"/> نویسه یا کمتر کوتاه کنید (شما در حال حاضر از <ph name="CURRENT_LENGTH"/> نویسه استفاده می‌کنید).</translation>
+<translation id="6101327004457443354">صدادارکردن تراک صوتی</translation>
+<translation id="1822429046913737220">ق.ظ/ب.ظ</translation>
+<translation id="1639239467298939599">بارگیری</translation>
+<translation id="2908441821576996758">لطفاً لیستی از آدرس‌های ایمیل که با کاما از هم جدا شده‌اند را وارد کنید.</translation>
+<translation id="5939518447894949180">بازنشانی</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقدار معتبر <ph name="VALID_VALUE"/> است.</translation>
+<translation id="835897206747267392">مقدار نامعتبر.</translation>
+<translation id="1842960171412779397">انتخاب</translation>
+<translation id="7673697353781729403">ساعت</translation>
+<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN"/>» نباید حاوی نماد «<ph name="INVALIDCHARACTER"/>» باشد.</translation>
+<translation id="3450233048674729344">مقدار باید کمتر یا برابر با <ph name="MAXIMUM"/> باشد.</translation>
+<translation id="668171684555832681">دیگر...</translation>
+<translation id="6270583010843788609">نشانگر خط زمان فیلم</translation>
+<translation id="5641012560118721995">توقف موقت پخش</translation>
+<translation id="1591562245178063882">این ماه</translation>
+<translation id="6119846243427417423">فعالسازی</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> فایل</translation>
+<translation id="6643016212128521049">پاک کردن</translation>
+<translation id="7888071071722539607">لطفاً نماد «<ph name="ATSIGN"/>» را به آدرس ایمیل اضافه کنید. «<ph name="INVALIDADDRESS"/>» در «<ph name="ATSIGN"/>» موجود نیست.</translation>
+<translation id="1088086359088493902">ثانیه</translation>
+<translation id="3934680773876859118">‏بارگیری سند PDF انجام نشد</translation>
+<translation id="3632707345189162177">مقدار ثانیه‌های باقیمانده فیلم</translation>
+<translation id="6359256949422175976">نشانگر حذف‌کننده زمان فیلم</translation>
+<translation id="8597182159515967513">عنوان</translation>
+<translation id="6843725295806269523">بیصداکردن</translation>
+<translation id="2653659639078652383">ارائه</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fi.xtb b/chromium/content/app/strings/translations/content_strings_fi.xtb
new file mode 100644
index 00000000000..1ea919fe564
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_fi.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fi">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Muu...</translation>
+<translation id="248395913932153421">Päivä</translation>
+<translation id="1729654308190250600">Kirjoita ei-tyhjä sähköpostiosoite.</translation>
+<translation id="6015796118275082299">Vuosi</translation>
+<translation id="1235745349614807883">Poista viimeisimmät haut</translation>
+<translation id="7223624360433298498">kulunut aika</translation>
+<translation id="1171774979989969504">Anna sähköpostiosoite.</translation>
+<translation id="709897737746224366">Käytä pyydettyä muotoilua.</translation>
+<translation id="5048533449481078685">luettelon merkitsijä</translation>
+<translation id="4202807286478387388">siirry</translation>
+<translation id="5307600278924710095">Lisää <ph name="ATSIGN"/>-osaa ennen tuleva osa. <ph name="INVALIDADDRESS"/> on puutteellinen.</translation>
+<translation id="2746543609216772311">Arvon on oltava <ph name="MINIMUM_DATE_OR_TIME"/> tai myöhempi.</translation>
+<translation id="2572483411312390101">toista</translation>
+<translation id="8785498733064193001">aloita toisto</translation>
+<translation id="7057186640035488495">elokuvan aikajana</translation>
+<translation id="8199524924445686405">vvvv</translation>
+<translation id="795667975304826397">Ei valittua tiedostoa</translation>
+<translation id="7789962463072032349">tauko</translation>
+<translation id="6853785296079745596">piilota tekstitykset</translation>
+<translation id="4360991593054037559">Syötä kelvollinen arvo. Kaksi lähintä kelvollista arvoa ovat <ph name="VALID_VALUE_LOW"/> ja <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Muu...</translation>
+<translation id="8141602879876242471">Tämä on haettavissa oleva hakemisto. Anna hakusanat:</translation>
+<translation id="1930711995431081526">tila</translation>
+<translation id="658823671542763450">siirry koko näytön tilaan</translation>
+<translation id="7720026100085573005">jäljellä oleva aika</translation>
+<translation id="370665806235115550">Ladataan...</translation>
+<translation id="2723001399770238859">ääni</translation>
+<translation id="6845533974506654842">paina</translation>
+<translation id="8244226242650769279">kuvakartta</translation>
+<translation id="310520048233152454">Anna URL-osoite.</translation>
+<translation id="4812940957355064477">Anna numero.</translation>
+<translation id="2548326553472216322">Ei viimeisimpiä hakuja</translation>
+<translation id="1938124657309484470">Arvon on oltava <ph name="MAXIMUM_DATE_OR_TIME"/> tai aiempi.</translation>
+<translation id="7263440858009898357">Valitse kohde luettelosta.</translation>
+<translation id="901493112792887934">nykyinen toistoaika sekunteina</translation>
+<translation id="5164977714490026579">Arvon tulee olla suurempi tai yhtä suuri kuin <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Viikko <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">älä näytä tekstityksiä</translation>
+<translation id="5944544982112848342">2048 (korkea taso)</translation>
+<translation id="3075154866155599887">Anna kelvollinen arvo. Kentän arvo on puutteellinen tai annettu päivä on virheellinen.</translation>
+<translation id="3040011195152428237">linkki</translation>
+<translation id="1014825444426747588">tyhjä</translation>
+<translation id="9050748414552849310">näytä tekstitykset</translation>
+<translation id="4522570452068850558">Tiedot</translation>
+<translation id="8451268428117625855">Valitse tiedosto.</translation>
+<translation id="8117451130807776954">Tällä viikolla</translation>
+<translation id="5966707198760109579">Viikko</translation>
+<translation id="2901282870647571346">elokuvan nykyinen tila</translation>
+<translation id="2060505056492490888"><ph name="DOT"/>-merkkiä on käytetty väärässä kohdassa osoitteessa <ph name="INVALIDDOMAIN"/>.</translation>
+<translation id="2674318244760992338">alaviite</translation>
+<translation id="8987927404178983737">Kuukausi</translation>
+<translation id="8115662671911883373">näytä tekstitykset</translation>
+<translation id="7364796246159120393">Valitse tiedosto</translation>
+<translation id="2761667185364618470">Valitse tämä ruutu jatkaaksesi.</translation>
+<translation id="8534579021159131403">Minuuttia</translation>
+<translation id="819205353528511139">toista elokuva koko näytön tilassa</translation>
+<translation id="4103419683916926126">Millisekuntia</translation>
+<translation id="838869780401515933">valitse</translation>
+<translation id="2846343701378493991">1024 (keskitaso)</translation>
+<translation id="1637811476055996098">Valitse tiedostot</translation>
+<translation id="49969490063480558">Lisää <ph name="ATSIGN"/>-osaa seuraava osa. <ph name="INVALIDADDRESS"/> on puutteellinen.</translation>
+<translation id="5476505524087279545">poista valinta</translation>
+<translation id="2148716181193084225">Tänään</translation>
+<translation id="2507943997699731163">Täytä tämä kenttä.</translation>
+<translation id="3785482301506746191">elokuvan ajan säädin</translation>
+<translation id="739024184232394898">Muu...</translation>
+<translation id="383465348367842624"><ph name="ATSIGN"/>-osaa ennen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="5468998798572797635">poistu koko näytön tilasta</translation>
+<translation id="5919473608089529604">Laajennuksen lataaminen epäonnistui.</translation>
+<translation id="5546461542133609677">peruuta mykistys</translation>
+<translation id="6663448176199120256">Viimeisimmät haut</translation>
+<translation id="1020833440720551630">mykistä ääniraita</translation>
+<translation id="2597378329261239068">Tämä asiakirja on suojattu salasanalla. Anna salasana.</translation>
+<translation id="5466621249238537318">Valitse vähintään yksi tiedosto.</translation>
+<translation id="9132465097189459683">Muu...</translation>
+<translation id="10623998915015855">vaihtopainike</translation>
+<translation id="8750798805984357768">Valitse yksi vaihtoehdoista.</translation>
+<translation id="7740050170769002709">HTML-sisältö</translation>
+<translation id="6692633176391053278">askellin</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> valittu</translation>
+<translation id="8541249477527128034">median hallinta</translation>
+<translation id="2226276347425096477">Lyhennä tämä teksti alle <ph name="MAX_CHARACTERS"/> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH"/> merkkiä).</translation>
+<translation id="6101327004457443354">peruuta ääniraidan mykistys</translation>
+<translation id="1822429046913737220">AP/IP</translation>
+<translation id="1639239467298939599">Ladataan</translation>
+<translation id="2908441821576996758">Anna pilkuilla erotettu sähköpostiosoitteiden luettelo.</translation>
+<translation id="5939518447894949180">Tyhjennä</translation>
+<translation id="1921819250265091946">pp</translation>
+<translation id="2613802280814924224">Syötä kelvollinen arvo. Lähin kelvollinen arvo on <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Virheellinen arvo.</translation>
+<translation id="1842960171412779397">Valitse</translation>
+<translation id="7673697353781729403">Tuntia</translation>
+<translation id="4664250907885839816"><ph name="ATSIGN"/>-osan jälkeen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="3450233048674729344">Arvon tulee olla pienempi tai yhtä suuri kuin <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Joku muu profiili...</translation>
+<translation id="6270583010843788609">elokuvan aikajanan pikkukuva</translation>
+<translation id="5641012560118721995">keskeytä toisto</translation>
+<translation id="1591562245178063882">Tässä kuussa</translation>
+<translation id="6119846243427417423">aktivoi</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> tiedostoa</translation>
+<translation id="6643016212128521049">Tyhjennä</translation>
+<translation id="7888071071722539607">Sähköpostiosoitteeseen kuuluu <ph name="ATSIGN"/>-osa. Osoitteesta <ph name="INVALIDADDRESS"/> puuttuu <ph name="ATSIGN"/>.</translation>
+<translation id="1088086359088493902">Sekuntia</translation>
+<translation id="3934680773876859118">PDF-asiakirjan lataaminen epäonnistui</translation>
+<translation id="3632707345189162177">elokuvan jäljellä oleva aika sekunteina</translation>
+<translation id="6359256949422175976">elokuvan ajan säätimen pikkukuva</translation>
+<translation id="8597182159515967513">otsikko</translation>
+<translation id="6843725295806269523">äänetön</translation>
+<translation id="2653659639078652383">Lähetä</translation>
+<translation id="3732799496749320381">kk</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fil.xtb b/chromium/content/app/strings/translations/content_strings_fil.xtb
new file mode 100644
index 00000000000..24780470d2a
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_fil.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fil">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Iba pa...</translation>
+<translation id="248395913932153421">Araw</translation>
+<translation id="1729654308190250600">Mangyaring maglagay ng isang non-empty na email address.</translation>
+<translation id="6015796118275082299">Taon</translation>
+<translation id="1235745349614807883">Lisiman ang Kasalukuyang Mga Paghahanap</translation>
+<translation id="7223624360433298498">lumipas na oras</translation>
+<translation id="1171774979989969504">Mangyaring magpasok ng email address.</translation>
+<translation id="709897737746224366">Pakitugma ang hiniling na format.</translation>
+<translation id="5048533449481078685">Ilista ang marker</translation>
+<translation id="4202807286478387388">tumalon</translation>
+<translation id="5307600278924710095">Mangyaring maglagay ng isang bahagi na sinusundan ng '<ph name="ATSIGN"/>.' Hindi kumpleto ang '<ph name="INVALIDADDRESS"/>.'</translation>
+<translation id="2746543609216772311">Dapat <ph name="MINIMUM_DATE_OR_TIME"/> o mas bago ang value.</translation>
+<translation id="2572483411312390101">i-play</translation>
+<translation id="8785498733064193001">simulan ang pag-playback</translation>
+<translation id="7057186640035488495">oras ng pelikula</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">Walang napiling file</translation>
+<translation id="7789962463072032349">i-pause</translation>
+<translation id="6853785296079745596">itago ang mga nakasarang caption</translation>
+<translation id="4360991593054037559">Mangyaring maglagay ng isang wastong value. Ang dalawang pinakamalapit na wastong value ay <ph name="VALID_VALUE_LOW"/> at <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Iba pa...</translation>
+<translation id="8141602879876242471">Isa itong paghahanap ng index. Ipasok ang paghahanap sa mga keyword:</translation>
+<translation id="1930711995431081526">katayuan</translation>
+<translation id="658823671542763450">mag-full screen</translation>
+<translation id="7720026100085573005">natitirang oras</translation>
+<translation id="370665806235115550">Kumakarga...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">pindutin</translation>
+<translation id="8244226242650769279">mapa ng imahe</translation>
+<translation id="310520048233152454">Mangyaring magpasok ng URL.</translation>
+<translation id="4812940957355064477">Mangyaring maglagay ng numero.</translation>
+<translation id="2548326553472216322">Walang kamakailang mga paghahanap</translation>
+<translation id="1938124657309484470">Dapat <ph name="MAXIMUM_DATE_OR_TIME"/> o mas nauna ang value.</translation>
+<translation id="7263440858009898357">Mangyaring pumili ng item sa listahan.</translation>
+<translation id="901493112792887934">kasalukuyang oras ayon sa segundo</translation>
+<translation id="5164977714490026579">Dapat mas mataas kaysa sa o katumbas ng <ph name="MINIMUM"/> ang halaga.</translation>
+<translation id="2247351761944213033">Linggo <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ihinto ang pagpapakita ng mga nakasarang caption</translation>
+<translation id="5944544982112848342">2048 (Pinakamataas na Marka)</translation>
+<translation id="3075154866155599887">Mangyaring maglagay ng wastong halaga. Hindi kumpleto ang field o may isang di-wastong petsa.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">blangko</translation>
+<translation id="9050748414552849310">ipakita ang mga nakasarang caption</translation>
+<translation id="4522570452068850558">Mga Detalye</translation>
+<translation id="8451268428117625855">Mangyaring pumili ng file.</translation>
+<translation id="8117451130807776954">Linggong ito</translation>
+<translation id="5966707198760109579">Linggo</translation>
+<translation id="2901282870647571346">kasalukuyang katayuan ng pelikula</translation>
+<translation id="2060505056492490888">Ginamit ang '<ph name="DOT"/>' sa maling posisyon sa '<ph name="INVALIDDOMAIN"/>.'</translation>
+<translation id="2674318244760992338">footer</translation>
+<translation id="8987927404178983737">Buwan</translation>
+<translation id="8115662671911883373">simulan ang pagpapakita ng mga nakasarang caption</translation>
+<translation id="7364796246159120393">Pumili ng File</translation>
+<translation id="2761667185364618470">Pakitingnan ang kahon na ito kung gusto mong magpatuloy.</translation>
+<translation id="8534579021159131403">Minuto</translation>
+<translation id="819205353528511139">i-play ang pelikula sa full screen mode</translation>
+<translation id="4103419683916926126">Milliseconds</translation>
+<translation id="838869780401515933">I-tsek</translation>
+<translation id="2846343701378493991">1024 (Katamtamang Grado)</translation>
+<translation id="1637811476055996098">Pumili ng Mga File</translation>
+<translation id="49969490063480558">Mangyaring maglagay ng isang bahagi pagkatapos ng '<ph name="ATSIGN"/>.' Hindi kumpleto ang '<ph name="INVALIDADDRESS"/>.'</translation>
+<translation id="5476505524087279545">i-uncheck</translation>
+<translation id="2148716181193084225">Ngayon</translation>
+<translation id="2507943997699731163">Pakipunan ang field na ito.</translation>
+<translation id="3785482301506746191">scrubber ng oras ng pelikula</translation>
+<translation id="739024184232394898">Iba pa...</translation>
+<translation id="383465348367842624">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER"/>' ang bahagi bago ang '<ph name="ATSIGN"/>.'</translation>
+<translation id="5468998798572797635">lumabas sa full screen</translation>
+<translation id="5919473608089529604">Hindi ma-load ang plug-in.</translation>
+<translation id="5546461542133609677">i-unmute</translation>
+<translation id="6663448176199120256">Kasalukuyang Mga Paghahanap</translation>
+<translation id="1020833440720551630">i-mute ang audio track</translation>
+<translation id="2597378329261239068">Protektado ng password ang dokumentong ito. Mangyaring magpasok ng password.</translation>
+<translation id="5466621249238537318">Mangyaring pumili ng isa o higit pang mga file.</translation>
+<translation id="9132465097189459683">Iba pa...</translation>
+<translation id="10623998915015855">button sa pag-toggle</translation>
+<translation id="8750798805984357768">Mangyaring pumili ng isa sa mga opsyong ito.</translation>
+<translation id="7740050170769002709">HTML na nilalaman</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> ang napili</translation>
+<translation id="8541249477527128034">kontrol sa media</translation>
+<translation id="2226276347425096477">Mangyaring paikliin ang tekstong ito ng <ph name="MAX_CHARACTERS"/> (na) character o mas mababa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH"/> (na) character).</translation>
+<translation id="6101327004457443354">i-unmute ang audio track</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Naglo-load</translation>
+<translation id="2908441821576996758">Mangyaring magpasok ng listahan ng email address na pinaghihiwalay ng kuwit.</translation>
+<translation id="5939518447894949180">I-reset</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Mangyaring maglagay ng isang wastong value. Ang pinakamalapit na wastong value ay <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Di-wastong halaga.</translation>
+<translation id="1842960171412779397">piliin</translation>
+<translation id="7673697353781729403">Oras</translation>
+<translation id="4664250907885839816">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER"/>' ang bahagi pagkatapos ng '<ph name="ATSIGN"/>.'</translation>
+<translation id="3450233048674729344">Dapat mas mababa kaysa sa o katumbas ng <ph name="MAXIMUM"/> ang halaga.</translation>
+<translation id="668171684555832681">Iba pa...</translation>
+<translation id="6270583010843788609">thumb ng timeline ng pelikula</translation>
+<translation id="5641012560118721995">i-pause ang pag-playback</translation>
+<translation id="1591562245178063882">Buwang ito</translation>
+<translation id="6119846243427417423">isaaktibo</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> mga file</translation>
+<translation id="6643016212128521049">I-clear</translation>
+<translation id="7888071071722539607">Mangyaring magsama ng '<ph name="ATSIGN"/>' sa email address. Kulang ng '<ph name="ATSIGN"/>' ang '<ph name="INVALIDADDRESS"/>.'</translation>
+<translation id="1088086359088493902">Segundo</translation>
+<translation id="3934680773876859118">Nabigong i-load ang dokumentong PDF</translation>
+<translation id="3632707345189162177">bilang ng segundong natitira sa pelikula</translation>
+<translation id="6359256949422175976">thumb ng scrubber ng oras ng pelikula</translation>
+<translation id="8597182159515967513">heading</translation>
+<translation id="6843725295806269523">i-mute</translation>
+<translation id="2653659639078652383">Isumite</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fr.xtb b/chromium/content/app/strings/translations/content_strings_fr.xtb
new file mode 100644
index 00000000000..191e82984ad
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_fr.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="fr">
+<translation id="4763480195061959176">vidéo</translation>
+<translation id="5843503607508392247">Autre…</translation>
+<translation id="248395913932153421">Jour</translation>
+<translation id="1729654308190250600">Veuillez saisir une adresse e-mail dans le champ correspondant.</translation>
+<translation id="6015796118275082299">Année</translation>
+<translation id="1235745349614807883">Effacer les recherches récentes</translation>
+<translation id="7223624360433298498">temps écoulé</translation>
+<translation id="1171774979989969504">Veuillez saisir une adresse e-mail.</translation>
+<translation id="709897737746224366">Veuillez respecter le format requis.</translation>
+<translation id="5048533449481078685">marqueur de liste</translation>
+<translation id="4202807286478387388">accéder</translation>
+<translation id="5307600278924710095">Veuillez saisir la partie manquante avant le caractère &quot;<ph name="ATSIGN"/>&quot;. L'adresse &quot;<ph name="INVALIDADDRESS"/>&quot; est incomplète.</translation>
+<translation id="2746543609216772311">La date ou l'heure doit être égale ou postérieure à &quot;<ph name="MINIMUM_DATE_OR_TIME"/>&quot;.</translation>
+<translation id="2572483411312390101">lire</translation>
+<translation id="8785498733064193001">commencer la lecture</translation>
+<translation id="7057186640035488495">durée du film</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Aucun fichier choisi</translation>
+<translation id="7789962463072032349">pause</translation>
+<translation id="6853785296079745596">masquer les sous-titres</translation>
+<translation id="4360991593054037559">Veuillez saisir une valeur valide. Les deux valeurs valides les plus proches sont &quot;<ph name="VALID_VALUE_LOW"/>&quot; et &quot;<ph name="VALID_VALUE_HIGHER"/>&quot;.</translation>
+<translation id="1758486001363313524">Autre…</translation>
+<translation id="8141602879876242471">Vous pouvez lancer des recherches dans cet index. Pour cela, entrez des mots clés de recherche :</translation>
+<translation id="1930711995431081526">état</translation>
+<translation id="658823671542763450">activer le mode plein écran</translation>
+<translation id="7720026100085573005">temps restant</translation>
+<translation id="370665806235115550">Chargement...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">appuyer</translation>
+<translation id="8244226242650769279">image map</translation>
+<translation id="310520048233152454">Veuillez saisir une URL.</translation>
+<translation id="4812940957355064477">Veuillez saisir un nombre.</translation>
+<translation id="2548326553472216322">Aucune recherche récente</translation>
+<translation id="1938124657309484470">La date ou l'heure doit être égale ou antérieure à &quot;<ph name="MAXIMUM_DATE_OR_TIME"/>&quot;.</translation>
+<translation id="7263440858009898357">Sélectionnez un élément dans la liste.</translation>
+<translation id="901493112792887934">durée actuelle en secondes</translation>
+<translation id="5164977714490026579">Cette valeur doit être supérieure ou égale à <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Semaine <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ne plus afficher les sous-titres</translation>
+<translation id="5944544982112848342">2048 (haute sécurité)</translation>
+<translation id="3075154866155599887">Veuillez saisir une valeur valide. Le champ n'est pas complet ou contient une date non valide.</translation>
+<translation id="3040011195152428237">Lien</translation>
+<translation id="1014825444426747588">vide</translation>
+<translation id="9050748414552849310">afficher les sous-titres</translation>
+<translation id="4522570452068850558">Détails</translation>
+<translation id="8451268428117625855">Veuillez sélectionner un fichier.</translation>
+<translation id="8117451130807776954">Cette semaine</translation>
+<translation id="5966707198760109579">Semaine</translation>
+<translation id="2901282870647571346">état actuel du film</translation>
+<translation id="2060505056492490888">L'emplacement du caractère &quot;<ph name="DOT"/>&quot; est incorrect dans &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">pied de page</translation>
+<translation id="8987927404178983737">Mois</translation>
+<translation id="8115662671911883373">commencer à afficher les sous-titres</translation>
+<translation id="7364796246159120393">Choisissez un fichier</translation>
+<translation id="2761667185364618470">Veuillez cocher cette case si vous souhaitez continuer.</translation>
+<translation id="8534579021159131403">Minutes</translation>
+<translation id="819205353528511139">lire le film en mode plein écran</translation>
+<translation id="4103419683916926126">Millisecondes</translation>
+<translation id="838869780401515933">cocher</translation>
+<translation id="2846343701378493991">1024 (sécurité moyenne)</translation>
+<translation id="1637811476055996098">Sélect. fichiers</translation>
+<translation id="49969490063480558">Veuillez saisir la partie manquante après le symbole &quot;<ph name="ATSIGN"/>&quot;. L'adresse &quot;<ph name="INVALIDADDRESS"/>&quot; est incomplète.</translation>
+<translation id="5476505524087279545">décocher</translation>
+<translation id="2148716181193084225">Aujourd'hui</translation>
+<translation id="2507943997699731163">Veuillez renseigner ce champ.</translation>
+<translation id="3785482301506746191">barre de défilement de la durée du film</translation>
+<translation id="739024184232394898">Autre…</translation>
+<translation id="383465348367842624">La partie suivie du symbole &quot;<ph name="ATSIGN"/>&quot; ne doit pas contenir le caractère &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">quitter le mode plein écran</translation>
+<translation id="5919473608089529604">Impossible de charger le plug-in.</translation>
+<translation id="5546461542133609677">réactiver le son</translation>
+<translation id="6663448176199120256">Recherches récentes</translation>
+<translation id="1020833440720551630">désactiver le son de la piste audio</translation>
+<translation id="2597378329261239068">Ce document est protégé par mot de passe. Veuillez saisir ce dernier.</translation>
+<translation id="5466621249238537318">Veuillez sélectionner un ou plusieurs fichiers.</translation>
+<translation id="9132465097189459683">Autre…</translation>
+<translation id="10623998915015855">bouton d'activation/de désactivation</translation>
+<translation id="8750798805984357768">Veuillez sélectionner l'une de ces options.</translation>
+<translation id="7740050170769002709">Contenu HTML</translation>
+<translation id="6692633176391053278">curseur</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> élément(s) sélectionné(s)</translation>
+<translation id="8541249477527128034">commande multimédia</translation>
+<translation id="2226276347425096477">Veuillez réduire ce texte à <ph name="MAX_CHARACTERS"/> caractères maximum (il compte actuellement <ph name="CURRENT_LENGTH"/> caractères).</translation>
+<translation id="6101327004457443354">réactiver le son de la piste audio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Chargement en cours</translation>
+<translation id="2908441821576996758">Veuillez saisir une liste d'adresses e-mail séparées par une virgule.</translation>
+<translation id="5939518447894949180">Réinitialiser</translation>
+<translation id="1921819250265091946">jj</translation>
+<translation id="2613802280814924224">Veuillez saisir une valeur valide. La valeur valide la plus proche est &quot;<ph name="VALID_VALUE"/>&quot;.</translation>
+<translation id="835897206747267392">Valeur incorrecte</translation>
+<translation id="1842960171412779397">sélectionner</translation>
+<translation id="7673697353781729403">Heures</translation>
+<translation id="4664250907885839816">La partie précédée du symbole &quot;<ph name="ATSIGN"/>&quot; ne doit pas contenir le caractère &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Cette valeur doit être inférieure ou égale à <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Autre...</translation>
+<translation id="6270583010843788609">vignette de la chronologie du film</translation>
+<translation id="5641012560118721995">interrompre la lecture</translation>
+<translation id="1591562245178063882">Ce mois</translation>
+<translation id="6119846243427417423">activer</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> fichiers</translation>
+<translation id="6643016212128521049">Effacer</translation>
+<translation id="7888071071722539607">Veuillez inclure &quot;<ph name="ATSIGN"/>&quot; dans l'adresse e-mail. Il manque un symbole &quot;<ph name="ATSIGN"/>&quot; dans &quot;<ph name="INVALIDADDRESS"/>&quot;.</translation>
+<translation id="1088086359088493902">Secondes</translation>
+<translation id="3934680773876859118">Échec du chargement du document PDF</translation>
+<translation id="3632707345189162177">nombre de secondes du film restantes</translation>
+<translation id="6359256949422175976">vignette de la barre de défilement de la durée du film</translation>
+<translation id="8597182159515967513">en-tête</translation>
+<translation id="6843725295806269523">muet</translation>
+<translation id="2653659639078652383">Valider</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_gu.xtb b/chromium/content/app/strings/translations/content_strings_gu.xtb
new file mode 100644
index 00000000000..0d3d9d1d8de
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_gu.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="gu">
+<translation id="4763480195061959176">વિડિઓ</translation>
+<translation id="5843503607508392247">અન્ય...</translation>
+<translation id="248395913932153421">દિવસ</translation>
+<translation id="1729654308190250600">કૃપા કરીને એક બિન-ખાલી ઇમેઇલ સરનામું દાખલ કરો.</translation>
+<translation id="6015796118275082299">વર્ષ</translation>
+<translation id="1235745349614807883">હાલની શોધને સાફ કરો</translation>
+<translation id="7223624360433298498">વીતેલો સમય</translation>
+<translation id="1171774979989969504">કૃપા કરી કોઈ ઇમેઇલ સરનામું દાખલ કરો.</translation>
+<translation id="709897737746224366">કૃપા કરીને વિનંતી કરેલા ફોર્મેટ સાથે મેળ કરો.</translation>
+<translation id="5048533449481078685">સૂચિ માર્કર</translation>
+<translation id="4202807286478387388">જંપ કરો</translation>
+<translation id="5307600278924710095">કૃપા કરીને '<ph name="ATSIGN"/>' ની આગળનો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS"/>' અપૂર્ણ છે.</translation>
+<translation id="2746543609216772311">મૂલ્ય <ph name="MINIMUM_DATE_OR_TIME"/> અથવા પછીનું હોવું આવશ્યક છે.</translation>
+<translation id="2572483411312390101">ચલાવો</translation>
+<translation id="8785498733064193001">પ્લેબૅક શરૂ કરો</translation>
+<translation id="7057186640035488495">મૂવીનો સમય</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">કોઈ ફાઇલ પસંદ કરેલી નથી</translation>
+<translation id="7789962463072032349">થોભો</translation>
+<translation id="6853785296079745596">વિગતવાર ઉપશીર્ષક છુપાવો</translation>
+<translation id="4360991593054037559">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. બે નિકટતમ માન્ય મૂલ્યો <ph name="VALID_VALUE_LOW"/> અને <ph name="VALID_VALUE_HIGHER"/> છે.</translation>
+<translation id="1758486001363313524">અન્ય...</translation>
+<translation id="8141602879876242471">આ એક શોધસક્ષમ અનુક્રમણિકા છે. શોધ કીવર્ડ્સ દાખલ કરો:</translation>
+<translation id="1930711995431081526">સ્થિતિ</translation>
+<translation id="658823671542763450">પૂર્ણ સ્ક્રીનમાં દાખલ થાઓ</translation>
+<translation id="7720026100085573005">બાકીનો સમય</translation>
+<translation id="370665806235115550">લોડ કરી રહ્યું છે...</translation>
+<translation id="2723001399770238859">ઑડિઓ</translation>
+<translation id="6845533974506654842">દબાવો</translation>
+<translation id="8244226242650769279">છબી નકશો</translation>
+<translation id="310520048233152454">કૃપા કરી કોઈ URL દાખલ કરો.</translation>
+<translation id="4812940957355064477">કૃપા કરીને એક નંબર દાખલ કરો.</translation>
+<translation id="2548326553472216322">હાલની શોધો નથી</translation>
+<translation id="1938124657309484470">મૂલ્ય <ph name="MAXIMUM_DATE_OR_TIME"/> અથવા પહેલાંનું હોવું આવશ્યક છે.</translation>
+<translation id="7263440858009898357">કૃપા કરીને સૂચિમાંથી એક આઇટમ પસંદ કરો.</translation>
+<translation id="901493112792887934">સેકન્ડ્સમાં વર્તમાન સમય</translation>
+<translation id="5164977714490026579">મૂલ્ય <ph name="MINIMUM"/> જેટલું અથવા આનાથી વધુ હોવું આવશ્યક છે.</translation>
+<translation id="2247351761944213033">અઠવાડિયું <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">વિગતવાર ઉપશીર્ષકનું પ્રદર્શન અટકાવો</translation>
+<translation id="5944544982112848342">2048 (ઉચ્ચ ગ્રેડ)</translation>
+<translation id="3075154866155599887">કૃપા કરીને માન્ય કિંમત દાખલ કરો. ફીલ્ડ અપૂર્ણ છે અથવા અમાન્ય તારીખ ધરાવે છે.</translation>
+<translation id="3040011195152428237">લિંક</translation>
+<translation id="1014825444426747588">ખાલી</translation>
+<translation id="9050748414552849310">વિગતવાર ઉપશીર્ષક બતાવો</translation>
+<translation id="4522570452068850558">વિગતો</translation>
+<translation id="8451268428117625855">કૃપા કરીને કોઈ ફાઇલ પસંદ કરો.</translation>
+<translation id="8117451130807776954">આ અઠવાડિયે</translation>
+<translation id="5966707198760109579">અઠવાડિયું</translation>
+<translation id="2901282870647571346">વર્તમાન મૂવીની સ્થિતિ</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' નો ઉપયોગ '<ph name="INVALIDDOMAIN"/>' માં ખોટી જગ્યાએ થયો છે.</translation>
+<translation id="2674318244760992338">ફૂટર</translation>
+<translation id="8987927404178983737">મહિનો</translation>
+<translation id="8115662671911883373">વિગતવાર ઉપશીર્ષક પ્રદર્શન પ્રારંભ કરો</translation>
+<translation id="7364796246159120393">ફાઇલ પસંદ કરો</translation>
+<translation id="2761667185364618470">જો તમે આગળ વધવા માંગતા હો તો કૃપા કરીને આ બૉક્સને ચેક કરો.</translation>
+<translation id="8534579021159131403">મિનિટ</translation>
+<translation id="819205353528511139">પૂર્ણ સ્ક્રીન મોડમાં મૂવી ચલાવો</translation>
+<translation id="4103419683916926126">મીલીસેકન્ડ</translation>
+<translation id="838869780401515933">તપાસો</translation>
+<translation id="2846343701378493991">1024 (મધ્યમ ગ્રેડ)</translation>
+<translation id="1637811476055996098">ફાઇલો પસંદ કરો</translation>
+<translation id="49969490063480558">કૃપા કરીને '<ph name="ATSIGN"/>' ને અનુસરી રહેલો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS"/>' અપૂર્ણ છે.</translation>
+<translation id="5476505524087279545">અનચેક કરો</translation>
+<translation id="2148716181193084225">આજે</translation>
+<translation id="2507943997699731163">કૃપા કરીને આ ફીલ્ડ ભરો.</translation>
+<translation id="3785482301506746191">મૂવી સમયનું સ્ક્રબર</translation>
+<translation id="739024184232394898">અન્ય...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' દ્વારા અનુસરાઈ રહેલા ભાગમાં '<ph name="INVALIDCHARACTER"/>' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="5468998798572797635">પૂર્ણ સ્ક્રીનથી બહાર નીકળો</translation>
+<translation id="5919473608089529604">પ્લગ-ઇન લોડ કરી શકાયુ નથી.</translation>
+<translation id="5546461542133609677">અનમ્યૂટ કરો</translation>
+<translation id="6663448176199120256">તાજેતરની શોધ</translation>
+<translation id="1020833440720551630">ઑડિઓ ટ્રેક મ્યૂટ કરો</translation>
+<translation id="2597378329261239068">આ દસ્તાવેજ પાસવર્ડ સુરક્ષિત છે. કૃપા કરીને પાસવર્ડ દાખલ કરો.</translation>
+<translation id="5466621249238537318">કૃપા કરીને એક અથવા વધુ ફાઇલ પસંદ કરો. </translation>
+<translation id="9132465097189459683">અન્ય...</translation>
+<translation id="10623998915015855">ટોગલ બટન</translation>
+<translation id="8750798805984357768">કૃપા કરીને આ વિકલ્પોમાંથી કોઈ એક પસંદ કરો.</translation>
+<translation id="7740050170769002709">HTML સામગ્રી</translation>
+<translation id="6692633176391053278">સ્ટેપર</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> પસંદ કર્યા</translation>
+<translation id="8541249477527128034">મીડિયાનું નિયંત્રણ</translation>
+<translation id="2226276347425096477">કૃપા કરીને આ ટેક્સ્ટને <ph name="MAX_CHARACTERS"/> અક્ષર અથવા તેથી ઓછા સુધી નાનો કરો (તમે હાલમાં <ph name="CURRENT_LENGTH"/> અક્ષરોનો ઉપયોગ કરી રહ્યા છો).</translation>
+<translation id="6101327004457443354">ઑડિઓ ટ્રેક અનમ્યૂટ કરો</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">લોડ કરી રહ્યું છે</translation>
+<translation id="2908441821576996758">કૃપા કરીને અલ્પવિરામથી વિભાજિત ઇમેઇલ સરનામાંઓની સૂચિ દાખલ કરો.</translation>
+<translation id="5939518447894949180">રીસેટ કરો</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. નિકટતમ માન્ય મૂલ્ય <ph name="VALID_VALUE"/> છે.</translation>
+<translation id="835897206747267392">અમાન્ય મૂલ્ય.</translation>
+<translation id="1842960171412779397">પસંદ કરો</translation>
+<translation id="7673697353781729403">કલાક</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER"/>' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="3450233048674729344">મૂલ્ય <ph name="MAXIMUM"/> જેટલું અથવા આનાથી ઓછું હોવું આવશ્યક છે.</translation>
+<translation id="668171684555832681">અન્ય...</translation>
+<translation id="6270583010843788609">મૂવી સમયરેખા થમ્બ</translation>
+<translation id="5641012560118721995">પ્લેબેક થોભાવો</translation>
+<translation id="1591562245178063882">આ મહિને</translation>
+<translation id="6119846243427417423">સક્રિય કરો</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ફાઇલો</translation>
+<translation id="6643016212128521049">સાફ કરો</translation>
+<translation id="7888071071722539607">કૃપા કરીને ઇમેઇલ સરનામાંમાં '<ph name="ATSIGN"/>' શામેલ કરો. '<ph name="INVALIDADDRESS"/>' માં '<ph name="ATSIGN"/>' ખૂટી રહ્યું છે.</translation>
+<translation id="1088086359088493902">સેકંડ</translation>
+<translation id="3934680773876859118">PDF દસ્તાવેજ લોડ કરવામાં નિષ્ફળ રહ્યા</translation>
+<translation id="3632707345189162177">ofmovie ની બાકી સેકન્ડ્સની સંખ્યા</translation>
+<translation id="6359256949422175976">મૂવી સમય સ્ક્રબર થમ્બ</translation>
+<translation id="8597182159515967513">મથાળું</translation>
+<translation id="6843725295806269523">બંધ કરો</translation>
+<translation id="2653659639078652383">સબમિટ કરો</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
new file mode 100644
index 00000000000..4aeaf0b89ae
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hi">
+<translation id="4763480195061959176">वीडियो</translation>
+<translation id="5843503607508392247">अन्य...</translation>
+<translation id="248395913932153421">दिन</translation>
+<translation id="1729654308190250600">कृपया गैर-रिक्त ईमेल पता डालें.</translation>
+<translation id="6015796118275082299">वर्ष</translation>
+<translation id="1235745349614807883">हाल ही की खोजें साफ़ करें</translation>
+<translation id="7223624360433298498">बीता हुआ समय</translation>
+<translation id="1171774979989969504">कृपया ई-मेल पता दर्ज करें.</translation>
+<translation id="709897737746224366">कृपया अनुरोधित प्रारूप का मिलान करें.</translation>
+<translation id="5048533449481078685">सूची चिन्हक</translation>
+<translation id="4202807286478387388">जाएं</translation>
+<translation id="5307600278924710095">कृपया '<ph name="ATSIGN"/>' के पहले वाला भाग डालें. '<ph name="INVALIDADDRESS"/>' अधूरा है.</translation>
+<translation id="2746543609216772311">मान <ph name="MINIMUM_DATE_OR_TIME"/> या बाद का होना चाहिए.</translation>
+<translation id="2572483411312390101">चलाएं</translation>
+<translation id="8785498733064193001">प्लेबैक शुरू करें</translation>
+<translation id="7057186640035488495">फि़ल्म का समय</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">कोई फाइल नहीं चुनी गई</translation>
+<translation id="7789962463072032349">पॉज़ करें</translation>
+<translation id="6853785296079745596">बंद कैप्शन छिपाएं</translation>
+<translation id="4360991593054037559">कृपया कोई मान्य मान डालें. दो निकटतम मान्य मान <ph name="VALID_VALUE_LOW"/> और <ph name="VALID_VALUE_HIGHER"/> हैं.</translation>
+<translation id="1758486001363313524">अन्य...</translation>
+<translation id="8141602879876242471">इस अनुक्रमणिका को खोजा जा सकता है. खोज कुंजीशब्द प्रविष्ट करें:</translation>
+<translation id="1930711995431081526">स्थिति</translation>
+<translation id="658823671542763450">पूर्ण स्क्रीन में प्रवेश करें</translation>
+<translation id="7720026100085573005">शेष समय</translation>
+<translation id="370665806235115550">लोड हो रहा है...</translation>
+<translation id="2723001399770238859">ऑडियो</translation>
+<translation id="6845533974506654842">दबाएं</translation>
+<translation id="8244226242650769279">चित्र नक्शे</translation>
+<translation id="310520048233152454">कृपया URL लिखें.</translation>
+<translation id="4812940957355064477">कृपया कोई संख्या डालें.</translation>
+<translation id="2548326553472216322">हाल ही कोई खोज नहीं</translation>
+<translation id="1938124657309484470">मान <ph name="MAXIMUM_DATE_OR_TIME"/> या पहले का होना चाहिए.</translation>
+<translation id="7263440858009898357">कृपया सूची में किसी आइटम को चुनें.</translation>
+<translation id="901493112792887934">वर्तमान समय, सेकंड में</translation>
+<translation id="5164977714490026579">मान <ph name="MINIMUM"/> से कम या इसके बराबर होना चाहिए.</translation>
+<translation id="2247351761944213033">सप्ताह <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">बंद कैप्शन दिखाना रोकें</translation>
+<translation id="5944544982112848342">2048 (उच्च ग्रेड)</translation>
+<translation id="3075154866155599887">कृपया मान्य मान डालें. फ़ील्ड अधूरी है या उसमें एक अमान्य दिनांक है.</translation>
+<translation id="3040011195152428237">संपर्क</translation>
+<translation id="1014825444426747588">रिक्त</translation>
+<translation id="9050748414552849310">बंद कैप्शन दिखाएं</translation>
+<translation id="4522570452068850558">विवरण</translation>
+<translation id="8451268428117625855">कृपया किसी फ़ाइल को चुनें.</translation>
+<translation id="8117451130807776954">इस सप्ताह</translation>
+<translation id="5966707198760109579">सप्ताह</translation>
+<translation id="2901282870647571346">फ़िल्म की वर्तमान स्थिति</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' का '<ph name="INVALIDDOMAIN"/>' में गलत स्थान पर उपयोग किया गया है.</translation>
+<translation id="2674318244760992338">पाद लेख</translation>
+<translation id="8987927404178983737">माह</translation>
+<translation id="8115662671911883373">बंद कैप्शन दिखाना प्रारंभ करें</translation>
+<translation id="7364796246159120393">फ़ाइल चुनें</translation>
+<translation id="2761667185364618470">यदि आप आगे बढ़ना चाहते हैं तो इस बॉक्‍स को चेक करें.</translation>
+<translation id="8534579021159131403">मिनट</translation>
+<translation id="819205353528511139">फ़िल्म को पूर्ण स्क्रीन मोड में चलाएं</translation>
+<translation id="4103419683916926126">मिलीसेकंड</translation>
+<translation id="838869780401515933">चेक करें</translation>
+<translation id="2846343701378493991">1024 (मध्यम ग्रेड)</translation>
+<translation id="1637811476055996098">फ़ाइलें चुनें</translation>
+<translation id="49969490063480558">कृपया '<ph name="ATSIGN"/>' के बाद आने वाला भाग डालें. '<ph name="INVALIDADDRESS"/>' अधूरा है.</translation>
+<translation id="5476505524087279545">अनचेक करें</translation>
+<translation id="2148716181193084225">आज</translation>
+<translation id="2507943997699731163">कृपया इस फ़ील्ड को भरें.</translation>
+<translation id="3785482301506746191">फ़िल्म समय स्क्रबर</translation>
+<translation id="739024184232394898">अन्य...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER"/>' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="5468998798572797635">पूर्ण स्क्रीन से बाहर निकलें</translation>
+<translation id="5919473608089529604">प्लग-इन लोड नहीं किया जा सका.</translation>
+<translation id="5546461542133609677">अनम्यूट करें</translation>
+<translation id="6663448176199120256">हाल ही में की गई खोजें</translation>
+<translation id="1020833440720551630">ऑडियो ट्रैक म्यूट करें</translation>
+<translation id="2597378329261239068">यह दस्तावेज़ पासवर्ड सुरक्षित है. कृपया पासवर्ड डालें.</translation>
+<translation id="5466621249238537318">कृपया एक या अधिक फ़ाइल को चुनें.</translation>
+<translation id="9132465097189459683">अन्य...</translation>
+<translation id="10623998915015855">टॉगल बटन</translation>
+<translation id="8750798805984357768">कृपया इनमें से कोई विकल्प चुनें.</translation>
+<translation id="7740050170769002709">HTML सामग्री</translation>
+<translation id="6692633176391053278">स्टेपर</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> चुने गए</translation>
+<translation id="8541249477527128034">मीडिया नियंत्रण</translation>
+<translation id="2226276347425096477">कृपया इस टेक्स्ट को <ph name="MAX_CHARACTERS"/> वर्णों या कम तक छोटा करें (वर्तमान में आप <ph name="CURRENT_LENGTH"/> वर्णों का उपयोग कर रहे हैं).</translation>
+<translation id="6101327004457443354">ऑडियो ट्रैक अनम्यूट करें</translation>
+<translation id="1822429046913737220">पूर्वाह्न/अपराह्न</translation>
+<translation id="1639239467298939599">लोड हो रहा है</translation>
+<translation id="2908441821576996758">कृपया ईमेल पतों की अल्पविराम द्वारा विभाजित सूची दर्ज करें.</translation>
+<translation id="5939518447894949180">रीसेट करें</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">कृपया कोई मान्य मान डालें. निकटतम मान्य मान <ph name="VALID_VALUE"/> है.</translation>
+<translation id="835897206747267392">अमान्य मान.</translation>
+<translation id="1842960171412779397">चुनें</translation>
+<translation id="7673697353781729403">घंटे</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER"/>' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="3450233048674729344">मान <ph name="MAXIMUM"/> से कम या इसके बराबर होना चाहिए.</translation>
+<translation id="668171684555832681">अन्य...</translation>
+<translation id="6270583010843788609">फ़िल्म टाइमलाइन झलक</translation>
+<translation id="5641012560118721995">प्लेबैक रोकें</translation>
+<translation id="1591562245178063882">इस माह</translation>
+<translation id="6119846243427417423">सक्रिय करें</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> फ़ाइल</translation>
+<translation id="6643016212128521049">साफ़ करें</translation>
+<translation id="7888071071722539607">कृपया ईमेल पते में '<ph name="ATSIGN"/>' शामिल करें. '<ph name="INVALIDADDRESS"/>' में '<ph name="ATSIGN"/>' नहीं है.</translation>
+<translation id="1088086359088493902">सेकंड</translation>
+<translation id="3934680773876859118">PDF दस्तावेज़ लोड करने में विफल</translation>
+<translation id="3632707345189162177">फ़िल्म के शेष सेकंड</translation>
+<translation id="6359256949422175976">फ़िल्म समय स्क्रबर झलक</translation>
+<translation id="8597182159515967513">हेडिंग</translation>
+<translation id="6843725295806269523">म्यूट करें</translation>
+<translation id="2653659639078652383">सबमिट करें</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hr.xtb b/chromium/content/app/strings/translations/content_strings_hr.xtb
new file mode 100644
index 00000000000..ae8026a7835
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_hr.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hr">
+<translation id="4763480195061959176">videozapis</translation>
+<translation id="5843503607508392247">Drugo...</translation>
+<translation id="248395913932153421">Dan</translation>
+<translation id="1729654308190250600">Unesite e-adresu koja nije prazna vrijednost.</translation>
+<translation id="6015796118275082299">Godina</translation>
+<translation id="1235745349614807883">Obriši najnovija pretraživanja</translation>
+<translation id="7223624360433298498">proteklo vrijeme</translation>
+<translation id="1171774979989969504">Unesite adresu e-pošte.</translation>
+<translation id="709897737746224366">Udovoljite zadanom formatu.</translation>
+<translation id="5048533449481078685">oznaka popisa</translation>
+<translation id="4202807286478387388">skoči</translation>
+<translation id="5307600278924710095">Unesite dio adrese ispred znaka &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; nije potpuna e-adresa.</translation>
+<translation id="2746543609216772311">Vrijednost mora biti <ph name="MINIMUM_DATE_OR_TIME"/> ili nakon toga.</translation>
+<translation id="2572483411312390101">reprodukcija</translation>
+<translation id="8785498733064193001">početak reprodukcije</translation>
+<translation id="7057186640035488495">vrijeme filma</translation>
+<translation id="8199524924445686405">gggg</translation>
+<translation id="795667975304826397">Nije odabrana niti jedna datoteka.</translation>
+<translation id="7789962463072032349">pauziraj</translation>
+<translation id="6853785296079745596">sakrivanje titlova</translation>
+<translation id="4360991593054037559">Unesite važeću vrijednost. Dvije su najbliže važeće vrijednosti <ph name="VALID_VALUE_LOW"/> i <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Drugo...</translation>
+<translation id="8141602879876242471">Ovaj je indeks moguće pretraživati. Unesite ključne riječi za pretraživanje:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">otvaranje na cijelom zaslonu</translation>
+<translation id="7720026100085573005">preostalo vrijeme</translation>
+<translation id="370665806235115550">Učitavanje...</translation>
+<translation id="2723001399770238859">zvuk</translation>
+<translation id="6845533974506654842">pritisni</translation>
+<translation id="8244226242650769279">karta slika</translation>
+<translation id="310520048233152454">Unesite URL.</translation>
+<translation id="4812940957355064477">Unesite broj.</translation>
+<translation id="2548326553472216322">Nema najnovijih pretraživanja</translation>
+<translation id="1938124657309484470">Vrijednost mora biti <ph name="MAXIMUM_DATE_OR_TIME"/> ili prije toga.</translation>
+<translation id="7263440858009898357">Odaberite stavku s popisa.</translation>
+<translation id="901493112792887934">trenutačno vrijeme u sekundama</translation>
+<translation id="5164977714490026579">Vrijednost mora biti <ph name="MINIMUM"/> ili veća.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. tjedan, <ph name="YEAR"/>. godina</translation>
+<translation id="7740016676195725605">zaustavljanje prikazivanja titlova</translation>
+<translation id="5944544982112848342">2048 (visoki stupanj)</translation>
+<translation id="3075154866155599887">Unesite važeću vrijednost. Ovo je polje nepotpuno ili sadrži nevažeći datum.</translation>
+<translation id="3040011195152428237">veza</translation>
+<translation id="1014825444426747588">prazno</translation>
+<translation id="9050748414552849310">prikazivanje titlova</translation>
+<translation id="4522570452068850558">Detalji</translation>
+<translation id="8451268428117625855">Odaberite datoteku.</translation>
+<translation id="8117451130807776954">Ovaj tjedan</translation>
+<translation id="5966707198760109579">Tjedan</translation>
+<translation id="2901282870647571346">trenutačan status filma</translation>
+<translation id="2060505056492490888">Znak &quot;<ph name="DOT"/>&quot; upotrebljava se na pogrešnom položaju u domeni &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">podnožje</translation>
+<translation id="8987927404178983737">Mjesec</translation>
+<translation id="8115662671911883373">početak prikazivanja titlova</translation>
+<translation id="7364796246159120393">Odaberi datoteku</translation>
+<translation id="2761667185364618470">Označite taj okvir ako želite ići dalje.</translation>
+<translation id="8534579021159131403">Minute</translation>
+<translation id="819205353528511139">reprodukcija filma na cijelom zaslonu</translation>
+<translation id="4103419683916926126">Milisekunde</translation>
+<translation id="838869780401515933">označi</translation>
+<translation id="2846343701378493991">1024 (srednji)</translation>
+<translation id="1637811476055996098">Odabir datoteka</translation>
+<translation id="49969490063480558">Unesite dio adrese iza znaka &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; nije potpuna e-adresa.</translation>
+<translation id="5476505524087279545">ukloni oznaku</translation>
+<translation id="2148716181193084225">Danas</translation>
+<translation id="2507943997699731163">Ispunite ovo polje.</translation>
+<translation id="3785482301506746191">vremenski klizač filma</translation>
+<translation id="739024184232394898">Drugo...</translation>
+<translation id="383465348367842624">Dio adrese ispred znaka &quot;<ph name="ATSIGN"/>&quot; ne smije sadržavati simbol &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">izlazak iz cijelog zaslona</translation>
+<translation id="5919473608089529604">Nije bilo moguće učitati dodatak.</translation>
+<translation id="5546461542133609677">uključivanje zvuka</translation>
+<translation id="6663448176199120256">Najnovija pretraživanja</translation>
+<translation id="1020833440720551630">isključivanje zvučnog zapisa</translation>
+<translation id="2597378329261239068">Ovaj je dokument zaštićen zaporkom. Unesite zaporku.</translation>
+<translation id="5466621249238537318">Izaberite jednu ili više datoteka.</translation>
+<translation id="9132465097189459683">Drugo...</translation>
+<translation id="10623998915015855">preklopni gumb</translation>
+<translation id="8750798805984357768">Izaberite jednu od tih opcija.</translation>
+<translation id="7740050170769002709">HTML sadržaj</translation>
+<translation id="6692633176391053278">povećanje/smanjenje strelicama gore/dolje (stepper)</translation>
+<translation id="4975562563186953947">Odabrano: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">kontrola medija</translation>
+<translation id="2226276347425096477">Skratite taj tekst na <ph name="MAX_CHARACTERS"/> znakova ili manje (trenutačno upotrebljavate <ph name="CURRENT_LENGTH"/> znakova).</translation>
+<translation id="6101327004457443354">uključivanje zvučnog zapisa</translation>
+<translation id="1822429046913737220">prijepodne/poslijepodne</translation>
+<translation id="1639239467298939599">Učitavanje</translation>
+<translation id="2908441821576996758">Unesite popis adresa e-pošte odijeljen zarezima.</translation>
+<translation id="5939518447894949180">Ponovno postavi</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Unesite važeću vrijednost. Najbliža je važeća vrijednost <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Nevažeća vrijednost.</translation>
+<translation id="1842960171412779397">odaberi</translation>
+<translation id="7673697353781729403">Sati</translation>
+<translation id="4664250907885839816">Dio adrese iza znaka &quot;<ph name="ATSIGN"/>&quot; ne smije sadržavati simbol &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Vrijednost mora biti <ph name="MAXIMUM"/> ili manja.</translation>
+<translation id="668171684555832681">Ostalo...</translation>
+<translation id="6270583010843788609">gumb na vremenskom klizaču filma</translation>
+<translation id="5641012560118721995">pauziranje reprodukcije</translation>
+<translation id="1591562245178063882">Ovaj mjesec</translation>
+<translation id="6119846243427417423">aktiviraj</translation>
+<translation id="8444882422881193423">Broj datoteka: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Izbriši</translation>
+<translation id="7888071071722539607">Uključite znak &quot;<ph name="ATSIGN"/>&quot; u e-adresu. U adresi &quot;<ph name="INVALIDADDRESS"/>&quot; nedostaje znak &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Sekunde</translation>
+<translation id="3934680773876859118">Učitavanje dokumenta PDF nije uspjelo</translation>
+<translation id="3632707345189162177">preostali broj sekundi filma</translation>
+<translation id="6359256949422175976">gumb vremenskog klizača filma</translation>
+<translation id="8597182159515967513">naslov</translation>
+<translation id="6843725295806269523">isključi ton</translation>
+<translation id="2653659639078652383">Pošalji</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hu.xtb b/chromium/content/app/strings/translations/content_strings_hu.xtb
new file mode 100644
index 00000000000..a8ab563d594
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_hu.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="hu">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Más...</translation>
+<translation id="248395913932153421">nap</translation>
+<translation id="1729654308190250600">Kérjük, ne hagyja üresen az e-mail cím mezőjét.</translation>
+<translation id="6015796118275082299">Év</translation>
+<translation id="1235745349614807883">Friss keresések törlése</translation>
+<translation id="7223624360433298498">eltelt idő</translation>
+<translation id="1171774979989969504">Kérjük, adjon meg egy e-mail címet.</translation>
+<translation id="709897737746224366">Kérjük, tartsa magát a kívánt formátumhoz.</translation>
+<translation id="5048533449481078685">listajelölő</translation>
+<translation id="4202807286478387388">Mehet</translation>
+<translation id="5307600278924710095">Kérjük, adja meg a „<ph name="ATSIGN"/>” előtti részt is. A „<ph name="INVALIDADDRESS"/>” cím nem teljes.</translation>
+<translation id="2746543609216772311">Az érték <ph name="MINIMUM_DATE_OR_TIME"/> vagy azt követő kell, hogy legyen.</translation>
+<translation id="2572483411312390101">lejátszás</translation>
+<translation id="8785498733064193001">lejátszás indítása</translation>
+<translation id="7057186640035488495">film ideje</translation>
+<translation id="8199524924445686405">éééé</translation>
+<translation id="795667975304826397">Nincs fájl kiválasztva</translation>
+<translation id="7789962463072032349">szüneteltetés</translation>
+<translation id="6853785296079745596">feliratok elrejtése</translation>
+<translation id="4360991593054037559">Kérjük, érvényes értéket adjon meg. A két legközelebbi érvényes érték <ph name="VALID_VALUE_LOW"/> és <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Más...</translation>
+<translation id="8141602879876242471">Ez egy kereshető index. Írjon be keresési kulcsszavakat:</translation>
+<translation id="1930711995431081526">állapot</translation>
+<translation id="658823671542763450">teljes képernyős nézet</translation>
+<translation id="7720026100085573005">hátralévő idő</translation>
+<translation id="370665806235115550">Betöltés…</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">Gomb lenyomása</translation>
+<translation id="8244226242650769279">interaktív kép</translation>
+<translation id="310520048233152454">Adjon meg egy URL-t.</translation>
+<translation id="4812940957355064477">Kérjük, adjon meg egy számot.</translation>
+<translation id="2548326553472216322">Nincsenek friss keresések</translation>
+<translation id="1938124657309484470">Az érték <ph name="MAXIMUM_DATE_OR_TIME"/> vagy azt megelőző kell, hogy legyen.</translation>
+<translation id="7263440858009898357">Kérjük, válasszon egyet a lista elemei közül.</translation>
+<translation id="901493112792887934">jelenlegi idő másodpercben</translation>
+<translation id="5164977714490026579">Az érték legyen nagyobb vagy egyenlő, mint <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. hét, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">feliratok elrejtése</translation>
+<translation id="5944544982112848342">2048 (magasfokú)</translation>
+<translation id="3075154866155599887">Kérjük, adjon meg érvényes értéket. A mező hiányos, vagy érvénytelen dátum van megadva.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">üres</translation>
+<translation id="9050748414552849310">feliratok megjelenítése</translation>
+<translation id="4522570452068850558">Részletek</translation>
+<translation id="8451268428117625855">Válasszon egy fájlt.</translation>
+<translation id="8117451130807776954">Ezen a héten</translation>
+<translation id="5966707198760109579">Hét</translation>
+<translation id="2901282870647571346">a jelenlegi film állapota</translation>
+<translation id="2060505056492490888">A „<ph name="DOT"/>” rossz helyen van a(z) „<ph name="INVALIDDOMAIN"/>” címben.</translation>
+<translation id="2674318244760992338">lábléc</translation>
+<translation id="8987927404178983737">hónap</translation>
+<translation id="8115662671911883373">feliratok megjelenítése</translation>
+<translation id="7364796246159120393">Fájl kiválasztása</translation>
+<translation id="2761667185364618470">Kérjük, jelölje be ezt a jelölőnégyzetet, ha tovább kíván haladni.</translation>
+<translation id="8534579021159131403">Perc</translation>
+<translation id="819205353528511139">film lejátszása teljes képernyős nézetben</translation>
+<translation id="4103419683916926126">Ezredmásodperc</translation>
+<translation id="838869780401515933">Megjelölés</translation>
+<translation id="2846343701378493991">1024 (Közepes)</translation>
+<translation id="1637811476055996098">Fájlok kiválasztása</translation>
+<translation id="49969490063480558">Kérjük, adja meg a „<ph name="ATSIGN"/>” utáni részt is. A(z) „<ph name="INVALIDADDRESS"/>” cím nem teljes.</translation>
+<translation id="5476505524087279545">Megjelölés eltávolítása</translation>
+<translation id="2148716181193084225">Ma</translation>
+<translation id="2507943997699731163">Kérjük, töltse ki ezt a mezőt.</translation>
+<translation id="3785482301506746191">filmidővezérlő</translation>
+<translation id="739024184232394898">Más...</translation>
+<translation id="383465348367842624">A „<ph name="ATSIGN"/>” előtti rész nem tartalmazhat „<ph name="INVALIDCHARACTER"/>” karaktert.</translation>
+<translation id="5468998798572797635">kilépés a teljes képernyős nézetből</translation>
+<translation id="5919473608089529604">Nem sikerült betölteni a plug-int.</translation>
+<translation id="5546461542133609677">némítás feloldása</translation>
+<translation id="6663448176199120256">Friss keresések</translation>
+<translation id="1020833440720551630">hangsáv némítása</translation>
+<translation id="2597378329261239068">Ez a dokumentum jelszóval védett. Kérjük, adja meg a jelszót.</translation>
+<translation id="5466621249238537318">Kérjük, válasszon ki egy vagy több fájlt.</translation>
+<translation id="9132465097189459683">Más...</translation>
+<translation id="10623998915015855">átkapcsológomb</translation>
+<translation id="8750798805984357768">Kérjük, válassza ki az egyik opciót.</translation>
+<translation id="7740050170769002709">HTML-tartalom</translation>
+<translation id="6692633176391053278">léptető</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> kiválasztva</translation>
+<translation id="8541249477527128034">médiavezérlő</translation>
+<translation id="2226276347425096477">Kérjük, rövidítse le a szöveget legfeljebb <ph name="MAX_CHARACTERS"/> karakterre (jelenleg <ph name="CURRENT_LENGTH"/> karaktert használ).</translation>
+<translation id="6101327004457443354">hangsáv némításának feloldása</translation>
+<translation id="1822429046913737220">de./du.</translation>
+<translation id="1639239467298939599">Betöltés</translation>
+<translation id="2908441821576996758">Kérjük, adjon meg egy vesszőkkel elválasztott e-mail címlistát.</translation>
+<translation id="5939518447894949180">Visszaállítás</translation>
+<translation id="1921819250265091946">nn</translation>
+<translation id="2613802280814924224">Kérjük, érvényes értéket adjon meg. A legközelebbi érvényes érték <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Érvénytelen érték.</translation>
+<translation id="1842960171412779397">Kiválasztás</translation>
+<translation id="7673697353781729403">Óra</translation>
+<translation id="4664250907885839816">A „<ph name="ATSIGN"/>” utáni rész nem tartalmazhat „<ph name="INVALIDCHARACTER"/>” karaktert.</translation>
+<translation id="3450233048674729344">Az érték legyen kisebb vagy egyenlő, mint <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Egyéb...</translation>
+<translation id="6270583010843788609">film idővonalának indexképe</translation>
+<translation id="5641012560118721995">lejátszás szüneteltetése</translation>
+<translation id="1591562245178063882">Ebben a hónapban</translation>
+<translation id="6119846243427417423">Aktiválás</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> fájl</translation>
+<translation id="6643016212128521049">Törlés</translation>
+<translation id="7888071071722539607">Kérjük, írjon egy „<ph name="ATSIGN"/>” karaktert az e-mail címbe. A(z) „<ph name="INVALIDADDRESS"/>” címből hiányzik a „<ph name="ATSIGN"/>” jel.</translation>
+<translation id="1088086359088493902">Másodperc</translation>
+<translation id="3934680773876859118">PDF dokumentum betöltése sikertelen</translation>
+<translation id="3632707345189162177">a filmből hátralévő másodpercek</translation>
+<translation id="6359256949422175976">a filmidővezérlő indexképe</translation>
+<translation id="8597182159515967513">fejléc</translation>
+<translation id="6843725295806269523">némítás</translation>
+<translation id="2653659639078652383">Elküldés</translation>
+<translation id="3732799496749320381">hh</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_id.xtb b/chromium/content/app/strings/translations/content_strings_id.xtb
new file mode 100644
index 00000000000..f6e837de76f
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_id.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="id">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Lainnya...</translation>
+<translation id="248395913932153421">Hari</translation>
+<translation id="1729654308190250600">Jangan mengosongkan bidang alamat email.</translation>
+<translation id="6015796118275082299">Tahun</translation>
+<translation id="1235745349614807883">Hapus Penelusuran Barusan</translation>
+<translation id="7223624360433298498">waktu berlalu</translation>
+<translation id="1171774979989969504">Masukkan alamat email.</translation>
+<translation id="709897737746224366">Sesuaikan dengan format yang diminta.</translation>
+<translation id="5048533449481078685">penanda daftar</translation>
+<translation id="4202807286478387388">lompati</translation>
+<translation id="5307600278924710095">Masukkan bagian yang diikuti dengan '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' tidak lengkap.</translation>
+<translation id="2746543609216772311">Tanggal harus <ph name="MINIMUM_DATE_OR_TIME"/> atau setelahnya.</translation>
+<translation id="2572483411312390101">main</translation>
+<translation id="8785498733064193001">mulai pemutaran</translation>
+<translation id="7057186640035488495">waktu film</translation>
+<translation id="8199524924445686405">tttt</translation>
+<translation id="795667975304826397">Tidak ada file yang dipilih</translation>
+<translation id="7789962463072032349">jeda</translation>
+<translation id="6853785296079745596">sembunyikan teks</translation>
+<translation id="4360991593054037559">Masukkan nilai yang valid. Dua nilai valid terdekat adalah <ph name="VALID_VALUE_LOW"/> dan <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Lainnya...</translation>
+<translation id="8141602879876242471">Terdapat indeks yang dapat dicari. Masukkan kata kunci penelusuran:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">masuk layar penuh</translation>
+<translation id="7720026100085573005">sisa waktu</translation>
+<translation id="370665806235115550">Membuka...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">tekan</translation>
+<translation id="8244226242650769279">gambar peta</translation>
+<translation id="310520048233152454">Masukkan URL.</translation>
+<translation id="4812940957355064477">Masukkan nomor.</translation>
+<translation id="2548326553472216322">Tidak ada penelusuran terkini</translation>
+<translation id="1938124657309484470">Tanggal harus <ph name="MAXIMUM_DATE_OR_TIME"/> atau lebih awal.</translation>
+<translation id="7263440858009898357">Pilih item pada daftar.</translation>
+<translation id="901493112792887934">waktu saat ini dalam detik</translation>
+<translation id="5164977714490026579">Nilai harus lebih besar daripada atau sama dengan <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">berhenti menampilkan teks</translation>
+<translation id="5944544982112848342">2048 (Tingkat Tinggi)</translation>
+<translation id="3075154866155599887">Masukkan nilai yang valid. Bidang tersebut tidak lengkap atau memiliki tanggal yang tidak valid.</translation>
+<translation id="3040011195152428237">tautan</translation>
+<translation id="1014825444426747588">kosong</translation>
+<translation id="9050748414552849310">tampilkan teks</translation>
+<translation id="4522570452068850558">Detail</translation>
+<translation id="8451268428117625855">Pilih file.</translation>
+<translation id="8117451130807776954">Minggu ini</translation>
+<translation id="5966707198760109579">Minggu</translation>
+<translation id="2901282870647571346">status film saat ini</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' digunakan pada posisi yang salah di '<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">footer</translation>
+<translation id="8987927404178983737">Bulan</translation>
+<translation id="8115662671911883373">mulai menampilkan teks</translation>
+<translation id="7364796246159120393">Pilih File</translation>
+<translation id="2761667185364618470">Centang kotak ini jika Anda ingin melanjutkan.</translation>
+<translation id="8534579021159131403">Menit</translation>
+<translation id="819205353528511139">putar film dalam mode layar penuh</translation>
+<translation id="4103419683916926126">Milidetik</translation>
+<translation id="838869780401515933">centangi</translation>
+<translation id="2846343701378493991">1024 (Tingkat Menengah)</translation>
+<translation id="1637811476055996098">Pilih File</translation>
+<translation id="49969490063480558">Masukkan bagian setelah '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' tidak lengkap.</translation>
+<translation id="5476505524087279545">batalkan centang</translation>
+<translation id="2148716181193084225">Hari ini</translation>
+<translation id="2507943997699731163">Harap isi bidang ini.</translation>
+<translation id="3785482301506746191">scrubber waktu film</translation>
+<translation id="739024184232394898">Lainnya...</translation>
+<translation id="383465348367842624">Bagian sebelum '<ph name="ATSIGN"/>' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="5468998798572797635">keluar dari tampilan layar penuh</translation>
+<translation id="5919473608089529604">Tidak dapat memuat plugin.</translation>
+<translation id="5546461542133609677">suarakan</translation>
+<translation id="6663448176199120256">Penelusuran Barusan</translation>
+<translation id="1020833440720551630">bisukan trek audio</translation>
+<translation id="2597378329261239068">Dokumen ini dilindungi sandi. Masukkan sandi.</translation>
+<translation id="5466621249238537318">Pilih salah satu atau beberapa file.</translation>
+<translation id="9132465097189459683">Lainnya...</translation>
+<translation id="10623998915015855">tombol beralih</translation>
+<translation id="8750798805984357768">Pilih salah satu opsi berikut.</translation>
+<translation id="7740050170769002709">Konten HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> dipilih</translation>
+<translation id="8541249477527128034">kontrol media</translation>
+<translation id="2226276347425096477">Pendekkan teks ini menjadi <ph name="MAX_CHARACTERS"/> karakter atau kurang (saat ini Anda menggunakan <ph name="CURRENT_LENGTH"/> karakter).</translation>
+<translation id="6101327004457443354">suarakan trek audio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Memuat</translation>
+<translation id="2908441821576996758">Masukkan daftar alamat email yang dipisahkan dengan koma.</translation>
+<translation id="5939518447894949180">Atur ulang</translation>
+<translation id="1921819250265091946">hh</translation>
+<translation id="2613802280814924224">Masukkan nilai yang valid. Nilai valid terdekatnya adalah <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Nilai tidak valid.</translation>
+<translation id="1842960171412779397">pilih</translation>
+<translation id="7673697353781729403">Jam</translation>
+<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN"/>' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="3450233048674729344">Nilai harus lebih kecil atau sama dengan <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Lainnya...</translation>
+<translation id="6270583010843788609">jempol garis waktu film</translation>
+<translation id="5641012560118721995">jeda pemutaran</translation>
+<translation id="1591562245178063882">Bulan ini</translation>
+<translation id="6119846243427417423">aktifkan</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> file</translation>
+<translation id="6643016212128521049">Hapus</translation>
+<translation id="7888071071722539607">Sertakan '<ph name="ATSIGN"/>' pada alamat email. '<ph name="INVALIDADDRESS"/>' tidak memiliki '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">Detik</translation>
+<translation id="3934680773876859118">Gagal memuat dokumen PDF</translation>
+<translation id="3632707345189162177">sisa waktu film dalam detik</translation>
+<translation id="6359256949422175976">jempol scrubber waktu film</translation>
+<translation id="8597182159515967513">kepala</translation>
+<translation id="6843725295806269523">bisukan</translation>
+<translation id="2653659639078652383">Kirim</translation>
+<translation id="3732799496749320381">bb</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_it.xtb b/chromium/content/app/strings/translations/content_strings_it.xtb
new file mode 100644
index 00000000000..ef6be1affa9
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_it.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="it">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Altro...</translation>
+<translation id="248395913932153421">Giorno</translation>
+<translation id="1729654308190250600">Inserisci un indirizzo email valido.</translation>
+<translation id="6015796118275082299">Anno</translation>
+<translation id="1235745349614807883">Cancella ricerche recenti</translation>
+<translation id="7223624360433298498">tempo trascorso</translation>
+<translation id="1171774979989969504">Inserisci un indirizzo email.</translation>
+<translation id="709897737746224366">Rispetta il formato richiesto.</translation>
+<translation id="5048533449481078685">indicatore elenco</translation>
+<translation id="4202807286478387388">vai</translation>
+<translation id="5307600278924710095">Inserisci una parte seguita da &quot;<ph name="ATSIGN"/>&quot;. Il valore &quot;<ph name="INVALIDADDRESS"/>&quot; è incompleto.</translation>
+<translation id="2746543609216772311">Il valore deve essere <ph name="MINIMUM_DATE_OR_TIME"/> o successivo.</translation>
+<translation id="2572483411312390101">riproduci</translation>
+<translation id="8785498733064193001">inizia riproduzione</translation>
+<translation id="7057186640035488495">tempo filmato</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Nessun file selezionato</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="6853785296079745596">nascondi sottotitoli</translation>
+<translation id="4360991593054037559">Inserisci un valore valido. I due valori validi più vicini sono <ph name="VALID_VALUE_LOW"/> e <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Altro...</translation>
+<translation id="8141602879876242471">Questo è un indice di ricerca. Inserisci le parole chiave di ricerca:</translation>
+<translation id="1930711995431081526">stato</translation>
+<translation id="658823671542763450">passa a schermo intero</translation>
+<translation id="7720026100085573005">tempo rimanente</translation>
+<translation id="370665806235115550">Caricamento in corso...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">premi</translation>
+<translation id="8244226242650769279">image map</translation>
+<translation id="310520048233152454">Inserisci un URL.</translation>
+<translation id="4812940957355064477">Inserisci un numero.</translation>
+<translation id="2548326553472216322">Nessuna ricerca recente</translation>
+<translation id="1938124657309484470">Il valore deve essere <ph name="MAXIMUM_DATE_OR_TIME"/> o precedente.</translation>
+<translation id="7263440858009898357">Seleziona un elemento nell'elenco.</translation>
+<translation id="901493112792887934">tempo attuale in secondi</translation>
+<translation id="5164977714490026579">Il valore deve essere superiore o uguale a <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Settimana <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">interrompi la visualizzazione dei sottotitoli</translation>
+<translation id="5944544982112848342">2048 (alta qualità)</translation>
+<translation id="3075154866155599887">Inserisci un valore valido. Il campo è incompleto o presenta una data non valida.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">vuoto</translation>
+<translation id="9050748414552849310">mostra sottotitoli</translation>
+<translation id="4522570452068850558">Dettagli</translation>
+<translation id="8451268428117625855">Seleziona un file.</translation>
+<translation id="8117451130807776954">Questa settimana</translation>
+<translation id="5966707198760109579">Settimana</translation>
+<translation id="2901282870647571346">stato corrente del filmato</translation>
+<translation id="2060505056492490888">Il segno &quot;<ph name="DOT"/>&quot; è utilizzato in una posizione errata in &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">piè di pagina</translation>
+<translation id="8987927404178983737">Mese</translation>
+<translation id="8115662671911883373">avvia la visualizzazione dei sottotitoli</translation>
+<translation id="7364796246159120393">Scegli file</translation>
+<translation id="2761667185364618470">Seleziona questa casella se intendi procedere.</translation>
+<translation id="8534579021159131403">Minuti</translation>
+<translation id="819205353528511139">riproduci filmato in modalità a schermo intero</translation>
+<translation id="4103419683916926126">Millisecondi</translation>
+<translation id="838869780401515933">seleziona</translation>
+<translation id="2846343701378493991">1024 (Medium Grade)</translation>
+<translation id="1637811476055996098">Scegli file</translation>
+<translation id="49969490063480558">Inserisci una parte dopo &quot;<ph name="ATSIGN"/>&quot;. Il valore &quot;<ph name="INVALIDADDRESS"/>&quot; è incompleto.</translation>
+<translation id="5476505524087279545">deseleziona</translation>
+<translation id="2148716181193084225">Oggi</translation>
+<translation id="2507943997699731163">Compila questo campo.</translation>
+<translation id="3785482301506746191">dispositivo di scorrimento tempo filmato</translation>
+<translation id="739024184232394898">Altro...</translation>
+<translation id="383465348367842624">Una parte seguita da &quot;<ph name="ATSIGN"/>&quot; non deve contenere il simbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">esci da schermo intero</translation>
+<translation id="5919473608089529604">Impossibile caricare il plug-in.</translation>
+<translation id="5546461542133609677">riattiva audio</translation>
+<translation id="6663448176199120256">Ricerche recenti</translation>
+<translation id="1020833440720551630">disattiva traccia audio</translation>
+<translation id="2597378329261239068">Questo documento è protetto da password. Inserisci una password.</translation>
+<translation id="5466621249238537318">Seleziona uno o più file.</translation>
+<translation id="9132465097189459683">Altro...</translation>
+<translation id="10623998915015855">pulsante di attivazione/disattivazione</translation>
+<translation id="8750798805984357768">Seleziona una di queste opzioni.</translation>
+<translation id="7740050170769002709">Contenuti HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Elementi selezionati: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">controllo contenuti multimediali</translation>
+<translation id="2226276347425096477">Riduci questo testo a <ph name="MAX_CHARACTERS"/> caratteri o meno (attualmente stai utilizzando <ph name="CURRENT_LENGTH"/> caratteri).</translation>
+<translation id="6101327004457443354">riattiva traccia audio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Caricamento</translation>
+<translation id="2908441821576996758">Inserisci un elenco di indirizzi email separati da virgola.</translation>
+<translation id="5939518447894949180">Ripristina</translation>
+<translation id="1921819250265091946">gg</translation>
+<translation id="2613802280814924224">Inserisci un valore valido. Il valore valido più vicino è <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valore non valido.</translation>
+<translation id="1842960171412779397">seleziona</translation>
+<translation id="7673697353781729403">Orario</translation>
+<translation id="4664250907885839816">Una parte che segue &quot;<ph name="ATSIGN"/>&quot; non deve contenere il simbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Il valore deve essere inferiore o uguale a <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Altro...</translation>
+<translation id="6270583010843788609">cursore sequenza temporale filmato</translation>
+<translation id="5641012560118721995">sospendi riproduzione</translation>
+<translation id="1591562245178063882">Questo mese</translation>
+<translation id="6119846243427417423">attiva</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> file</translation>
+<translation id="6643016212128521049">Cancella</translation>
+<translation id="7888071071722539607">Aggiungi un simbolo &quot;<ph name="ATSIGN"/>&quot; nell'indirizzo email. In &quot;<ph name="INVALIDADDRESS"/>&quot; manca un simbolo &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Secondi</translation>
+<translation id="3934680773876859118">Caricamento del documento PDF non riuscito</translation>
+<translation id="3632707345189162177">numero di secondi di filmato rimanenti</translation>
+<translation id="6359256949422175976">cursore dispositivo di scorrimento tempo filmato</translation>
+<translation id="8597182159515967513">intestazione</translation>
+<translation id="6843725295806269523">disattiva audio</translation>
+<translation id="2653659639078652383">Invia</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_iw.xtb b/chromium/content/app/strings/translations/content_strings_iw.xtb
new file mode 100644
index 00000000000..8327556220b
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_iw.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="iw">
+<translation id="4763480195061959176">סרטוני וידאו</translation>
+<translation id="5843503607508392247">אחר...</translation>
+<translation id="248395913932153421">יום</translation>
+<translation id="1729654308190250600">הזן ערך נדרש בשדה של כתובת הדוא&quot;ל.</translation>
+<translation id="6015796118275082299">שנה</translation>
+<translation id="1235745349614807883">הסר חיפושים אחרונים</translation>
+<translation id="7223624360433298498">זמן שחלף</translation>
+<translation id="1171774979989969504">הזן כתובת דוא&quot;ל.</translation>
+<translation id="709897737746224366">התאם את הפורמט המבוקש.</translation>
+<translation id="5048533449481078685">סמן רשימה</translation>
+<translation id="4202807286478387388">קפוץ</translation>
+<translation id="5307600278924710095">הזן חלק ולאחריו '<ph name="ATSIGN"/>'‏. השדה '<ph name="INVALIDADDRESS"/>' אינו מלא.</translation>
+<translation id="2746543609216772311">על הערך להיות <ph name="MINIMUM_DATE_OR_TIME"/> ומעלה.</translation>
+<translation id="2572483411312390101">הפעל</translation>
+<translation id="8785498733064193001">התחל בהפעלה</translation>
+<translation id="7057186640035488495">משך הסרט</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">לא נבחר קובץ</translation>
+<translation id="7789962463072032349">השהה</translation>
+<translation id="6853785296079745596">הסתר כתוביות סגורות</translation>
+<translation id="4360991593054037559">הזן ערך חוקי. שני הערכים החוקיים הקרובים ביותר הם <ph name="VALID_VALUE_LOW"/> ו-<ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">אחר...</translation>
+<translation id="8141602879876242471">זהו אינדקס שניתן לבצע בו חיפוש. הזן מילות מפתח לחיפוש:</translation>
+<translation id="1930711995431081526">מצב</translation>
+<translation id="658823671542763450">היכנס למסך מלא</translation>
+<translation id="7720026100085573005">זמן שנותר</translation>
+<translation id="370665806235115550">טוען...</translation>
+<translation id="2723001399770238859">אודיו</translation>
+<translation id="6845533974506654842">לחץ</translation>
+<translation id="8244226242650769279">מפת תמונות</translation>
+<translation id="310520048233152454">הזן כתובת אתר.</translation>
+<translation id="4812940957355064477">הזן מספר.</translation>
+<translation id="2548326553472216322">אין חיפושים אחרונים</translation>
+<translation id="1938124657309484470">על הערך להיות <ph name="MAXIMUM_DATE_OR_TIME"/> או מוקדם יותר.</translation>
+<translation id="7263440858009898357">בחר פריט מהרשימה.</translation>
+<translation id="901493112792887934">זמן נוכחי בשניות</translation>
+<translation id="5164977714490026579">הערך חייב להיות גדול מ-<ph name="MINIMUM"/> או שווה לו.</translation>
+<translation id="2247351761944213033">שבוע <ph name="WEEKNUMBER"/>‏, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">הפסק להציג כתוביות סגורות</translation>
+<translation id="5944544982112848342">2048 (High Grade)</translation>
+<translation id="3075154866155599887">הזן ערך חוקי. השדה ריק או שהוא מכיל תאריך לא חוקי.</translation>
+<translation id="3040011195152428237">קישור</translation>
+<translation id="1014825444426747588">ריק</translation>
+<translation id="9050748414552849310">הצג כתוביות סגורות</translation>
+<translation id="4522570452068850558">פרטים</translation>
+<translation id="8451268428117625855">בחר קובץ.</translation>
+<translation id="8117451130807776954">השבוע</translation>
+<translation id="5966707198760109579">שבוע</translation>
+<translation id="2901282870647571346">מצב סרט נוכחי</translation>
+<translation id="2060505056492490888">נעשה שימוש ב-'<ph name="DOT"/>' במיקום שגוי ב-'<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">כותרת תחתונה</translation>
+<translation id="8987927404178983737">חודש</translation>
+<translation id="8115662671911883373">התחל להציג כתוביות סגורות</translation>
+<translation id="7364796246159120393">בחר קובץ</translation>
+<translation id="2761667185364618470">סמן תיבה זו אם אתה רוצה להמשיך.</translation>
+<translation id="8534579021159131403">דקות</translation>
+<translation id="819205353528511139">הפעל את הסרט במצב מסך מלא</translation>
+<translation id="4103419683916926126">אלפיות שנייה</translation>
+<translation id="838869780401515933">סמן</translation>
+<translation id="2846343701378493991">1024 (Medium Grade)</translation>
+<translation id="1637811476055996098">בחר קבצים</translation>
+<translation id="49969490063480558">הזן חלק ולאחריו '<ph name="ATSIGN"/>'‏. השדה '<ph name="INVALIDADDRESS"/>' אינו מלא.</translation>
+<translation id="5476505524087279545">בטל סימון</translation>
+<translation id="2148716181193084225">היום</translation>
+<translation id="2507943997699731163">מלא שדה זה.</translation>
+<translation id="3785482301506746191">מסתיר משך סרט</translation>
+<translation id="739024184232394898">אחר...</translation>
+<translation id="383465348367842624">חלק ולאחריו '<ph name="ATSIGN"/>' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="5468998798572797635">צא ממסך מלא</translation>
+<translation id="5919473608089529604">לא היתה אפשרות לטעון את הפלאגין.</translation>
+<translation id="5546461542133609677">בטל השתקה</translation>
+<translation id="6663448176199120256">חיפושים אחרונים</translation>
+<translation id="1020833440720551630">השתק רצועת אודיו</translation>
+<translation id="2597378329261239068">מסמך זה מוגן באמצעות סיסמה. הזן סיסמה.</translation>
+<translation id="5466621249238537318">בחר קובץ אחד או יותר.</translation>
+<translation id="9132465097189459683">אחר...</translation>
+<translation id="10623998915015855">לחצן החלפה</translation>
+<translation id="8750798805984357768">בחר אחת מהאפשרויות הבאות.</translation>
+<translation id="7740050170769002709">‏תוכן HTML</translation>
+<translation id="6692633176391053278">פקד חצים</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> נבחרו</translation>
+<translation id="8541249477527128034">שליטה במדיה</translation>
+<translation id="2226276347425096477">קצר טקסט זה ל-<ph name="MAX_CHARACTERS"/> תווים או פחות (אתה משתמש כעת ב-<ph name="CURRENT_LENGTH"/> תווים).</translation>
+<translation id="6101327004457443354">בטל השתקה של רצועת אודיו</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">טוען</translation>
+<translation id="2908441821576996758">הזן רשימה של כתובות דוא&quot;ל המופרדות באמצעות פסיקים.</translation>
+<translation id="5939518447894949180">אפס</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">הזן ערך חוקי. הערך החוקי הקרוב ביותר הוא <ph name="VALID_VALUE"/></translation>
+<translation id="835897206747267392">ערך לא חוקי.</translation>
+<translation id="1842960171412779397">בחר</translation>
+<translation id="7673697353781729403">שעות</translation>
+<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN"/>' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="3450233048674729344">הערך חייב להיות קטן מ-<ph name="MAXIMUM"/> או שווה לו.</translation>
+<translation id="668171684555832681">אחר...</translation>
+<translation id="6270583010843788609">תמונה ממוזערת של משך סרט</translation>
+<translation id="5641012560118721995">השהה הפעלה</translation>
+<translation id="1591562245178063882">החודש</translation>
+<translation id="6119846243427417423">הפעל</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> קבצים</translation>
+<translation id="6643016212128521049">נקה</translation>
+<translation id="7888071071722539607">כלול '<ph name="ATSIGN"/>' בכתובת הדוא&quot;ל. ב-'<ph name="INVALIDADDRESS"/>' חסר '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">שניות</translation>
+<translation id="3934680773876859118">‏הטעינה של מסמך PDF נכשלה</translation>
+<translation id="3632707345189162177">מספר שניות שנותרו עד לסיום הסרט</translation>
+<translation id="6359256949422175976">תמונה ממוזערת של מסתיר זמן סרט</translation>
+<translation id="8597182159515967513">כותרת</translation>
+<translation id="6843725295806269523">השתק</translation>
+<translation id="2653659639078652383">שלח</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ja.xtb b/chromium/content/app/strings/translations/content_strings_ja.xtb
new file mode 100644
index 00000000000..50a52fc5004
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ja.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ja">
+<translation id="4763480195061959176">動画</translation>
+<translation id="5843503607508392247">その他...</translation>
+<translation id="248395913932153421">日</translation>
+<translation id="1729654308190250600">メール アドレスを入力してください。</translation>
+<translation id="6015796118275082299">年</translation>
+<translation id="1235745349614807883">最近の検索履歴を消去</translation>
+<translation id="7223624360433298498">経過時間</translation>
+<translation id="1171774979989969504">メール アドレスを入力してください。</translation>
+<translation id="709897737746224366">指定されている形式で入力してください。</translation>
+<translation id="5048533449481078685">リスト マーカー</translation>
+<translation id="4202807286478387388">ジャンプ</translation>
+<translation id="5307600278924710095">「<ph name="ATSIGN"/>」の前の文字列を入力してください。「<ph name="INVALIDADDRESS"/>」は完全なメール アドレスではありません。</translation>
+<translation id="2746543609216772311"><ph name="MINIMUM_DATE_OR_TIME"/> 以降の値を指定する必要があります。</translation>
+<translation id="2572483411312390101">再生</translation>
+<translation id="8785498733064193001">再生を開始</translation>
+<translation id="7057186640035488495">上映時間</translation>
+<translation id="8199524924445686405"> 年 </translation>
+<translation id="795667975304826397">選択されていません</translation>
+<translation id="7789962463072032349">一時停止</translation>
+<translation id="6853785296079745596">クローズド キャプションを非表示</translation>
+<translation id="4360991593054037559">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE_LOW"/> と <ph name="VALID_VALUE_HIGHER"/> です。</translation>
+<translation id="1758486001363313524">その他...</translation>
+<translation id="8141602879876242471">このインデックスは検索できます。キーワードを入力してください:</translation>
+<translation id="1930711995431081526">ステータス</translation>
+<translation id="658823671542763450">全画面表示</translation>
+<translation id="7720026100085573005">残り時間</translation>
+<translation id="370665806235115550">読み込み中...</translation>
+<translation id="2723001399770238859">音声</translation>
+<translation id="6845533974506654842">押す</translation>
+<translation id="8244226242650769279">イメージ マップ</translation>
+<translation id="310520048233152454">URL を入力してください。</translation>
+<translation id="4812940957355064477">数字を入力してください。</translation>
+<translation id="2548326553472216322">最近の検索はありません</translation>
+<translation id="1938124657309484470"><ph name="MAXIMUM_DATE_OR_TIME"/> 以前の値を指定する必要があります。</translation>
+<translation id="7263440858009898357">リスト内の項目を選択してください。</translation>
+<translation id="901493112792887934">現在の時間(秒単位)</translation>
+<translation id="5164977714490026579">値は <ph name="MINIMUM"/> 以上にする必要があります。</translation>
+<translation id="2247351761944213033"><ph name="YEAR"/>年第<ph name="WEEKNUMBER"/>週</translation>
+<translation id="7740016676195725605">クローズド キャプションの表示を終了</translation>
+<translation id="5944544982112848342">2048 (高)</translation>
+<translation id="3075154866155599887">有効な値を入力してください。フィールドの入力が不完全か、日付が無効です。</translation>
+<translation id="3040011195152428237">リンク</translation>
+<translation id="1014825444426747588">空白</translation>
+<translation id="9050748414552849310">クローズド キャプションを表示</translation>
+<translation id="4522570452068850558">詳細</translation>
+<translation id="8451268428117625855">ファイルを選択してください。</translation>
+<translation id="8117451130807776954">今週</translation>
+<translation id="5966707198760109579">週</translation>
+<translation id="2901282870647571346">現在の映画のステータス</translation>
+<translation id="2060505056492490888">「<ph name="INVALIDDOMAIN"/>」内の「<ph name="DOT"/>」の位置が間違っています。</translation>
+<translation id="2674318244760992338">フッター</translation>
+<translation id="8987927404178983737">月</translation>
+<translation id="8115662671911883373">クローズド キャプションの表示を開始</translation>
+<translation id="7364796246159120393">ファイルを選択</translation>
+<translation id="2761667185364618470">次に進むにはこのチェックボックスをオンにしてください。</translation>
+<translation id="8534579021159131403">分</translation>
+<translation id="819205353528511139">全画面表示モードで再生</translation>
+<translation id="4103419683916926126">ミリ秒</translation>
+<translation id="838869780401515933">チェックを付ける</translation>
+<translation id="2846343701378493991">1024 (中)</translation>
+<translation id="1637811476055996098">ファイル選択</translation>
+<translation id="49969490063480558">「<ph name="ATSIGN"/>」に続く文字列を入力してください。「<ph name="INVALIDADDRESS"/>」は完全なメール アドレスではありません。</translation>
+<translation id="5476505524087279545">チェックを外す</translation>
+<translation id="2148716181193084225">今日</translation>
+<translation id="2507943997699731163">このフィールドを入力してください。</translation>
+<translation id="3785482301506746191">シークバー</translation>
+<translation id="739024184232394898">その他...</translation>
+<translation id="383465348367842624">「<ph name="ATSIGN"/>」の前の文字列に記号「<ph name="INVALIDCHARACTER"/>」を使用しないでください。</translation>
+<translation id="5468998798572797635">全画面表示を終了</translation>
+<translation id="5919473608089529604">プラグインを読み込むことができませんでした。</translation>
+<translation id="5546461542133609677">ミュートを解除</translation>
+<translation id="6663448176199120256">最近の検索</translation>
+<translation id="1020833440720551630">音声トラックをミュート</translation>
+<translation id="2597378329261239068">このドキュメントはパスワードで保護されています。パスワードを入力してください。</translation>
+<translation id="5466621249238537318">1 つ以上のファイルを選択してください。</translation>
+<translation id="9132465097189459683">その他...</translation>
+<translation id="10623998915015855">切り替えボタン</translation>
+<translation id="8750798805984357768">これらのオプションから 1 つ選択してください。</translation>
+<translation id="7740050170769002709">HTML コンテンツ</translation>
+<translation id="6692633176391053278">ステッパー</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> 件選択</translation>
+<translation id="8541249477527128034">メディア管理</translation>
+<translation id="2226276347425096477">このテキストを半角 <ph name="MAX_CHARACTERS"/> 文字以下にしてください(現時点で半角 <ph name="CURRENT_LENGTH"/> 文字です)。</translation>
+<translation id="6101327004457443354">音声トラックのミュートを解除</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">読み込み中</translation>
+<translation id="2908441821576996758">メール アドレスのカンマ区切りリストを入力してください。</translation>
+<translation id="5939518447894949180">リセット</translation>
+<translation id="1921819250265091946">日</translation>
+<translation id="2613802280814924224">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE"/> です。</translation>
+<translation id="835897206747267392">値が無効です。</translation>
+<translation id="1842960171412779397">選択</translation>
+<translation id="7673697353781729403">時間</translation>
+<translation id="4664250907885839816">「<ph name="ATSIGN"/>」に続く文字列に記号「<ph name="INVALIDCHARACTER"/>」を使用しないでください。</translation>
+<translation id="3450233048674729344">値は <ph name="MAXIMUM"/> 以下にする必要があります。</translation>
+<translation id="668171684555832681">その他...</translation>
+<translation id="6270583010843788609">タイムラインのサムネイル</translation>
+<translation id="5641012560118721995">再生を一時停止</translation>
+<translation id="1591562245178063882">今月</translation>
+<translation id="6119846243427417423">アクティブにする</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ファイル</translation>
+<translation id="6643016212128521049">クリア</translation>
+<translation id="7888071071722539607">メール アドレスに「<ph name="ATSIGN"/>」を挿入してください。「<ph name="INVALIDADDRESS"/>」内に「<ph name="ATSIGN"/>」がありません。</translation>
+<translation id="1088086359088493902">秒</translation>
+<translation id="3934680773876859118">PDF ドキュメントを読み込むことができませんでした</translation>
+<translation id="3632707345189162177">残り時間(秒)</translation>
+<translation id="6359256949422175976">シークバーのサムネイル</translation>
+<translation id="8597182159515967513">見出し</translation>
+<translation id="6843725295806269523">ミュート</translation>
+<translation id="2653659639078652383">送信</translation>
+<translation id="3732799496749320381">月</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_kn.xtb b/chromium/content/app/strings/translations/content_strings_kn.xtb
new file mode 100644
index 00000000000..ec44917a5c2
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_kn.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="kn">
+<translation id="4763480195061959176">ವೀಡಿಯೊ</translation>
+<translation id="5843503607508392247">ಇತರೆ...</translation>
+<translation id="248395913932153421">ದಿನ</translation>
+<translation id="1729654308190250600">ಖಾಲಿ-ಅಲ್ಲದ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="6015796118275082299">ವರ್ಷ</translation>
+<translation id="1235745349614807883">ಇತ್ತೀಚಿನ ಹುಡುಕಾಟವನ್ನು ತೆರವುಗೊಳಿಸಿ</translation>
+<translation id="7223624360433298498">ಕಳೆದುಹೋದ ಸಮಯ</translation>
+<translation id="1171774979989969504">ದಯವಿಟ್ಟು ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="709897737746224366">ದಯವಿಟ್ಟು ವಿನಂತಿಸಿದ ಸ್ವರೂಪವನ್ನು ಹೊಂದಿಸಿ.</translation>
+<translation id="5048533449481078685">ಪಟ್ಟಿ ಗುರುತು</translation>
+<translation id="4202807286478387388">ಹಾರು</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN"/>' ನಂತರದ ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS"/>' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
+<translation id="2746543609216772311">ಮೌಲ್ಯವು <ph name="MINIMUM_DATE_OR_TIME"/> ಅಥವಾ ನಂತರದ್ದಾಗಿರಬೇಕು.</translation>
+<translation id="2572483411312390101">ಪ್ಲೇ ಮಾಡಿ</translation>
+<translation id="8785498733064193001">ಪ್ಲೇಬ್ಯಾಕ್ ಪ್ರಾರಂಭಿಸಿ</translation>
+<translation id="7057186640035488495">ಚಲನಚಿತ್ರ ಸಮಯ</translation>
+<translation id="8199524924445686405">ವವವವ</translation>
+<translation id="795667975304826397">ಯಾವುದೇ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ</translation>
+<translation id="7789962463072032349">ವಿರಾಮ</translation>
+<translation id="6853785296079745596">ಮುಚ್ಚಿರುವ ಶೀರ್ಷಿಕೆಗಳನ್ನು ಮರೆಮಾಡಿ</translation>
+<translation id="4360991593054037559">ಮಾನ್ಯವಾದ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. <ph name="VALID_VALUE_LOW"/> ಮತ್ತು <ph name="VALID_VALUE_HIGHER"/> ಎರಡು ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯಗಳಾಗಿವೆ.</translation>
+<translation id="1758486001363313524">ಇತರೆ...</translation>
+<translation id="8141602879876242471">ಇದು ಹುಡುಕಾಡಬಹುದಾದ ಸೂಚಿಕೆ ಹುಡುಕಾಟ ಕೀವರ್ಡ್‌ಗಳನ್ನು ನಮೂದಿಸಿ:</translation>
+<translation id="1930711995431081526">ಸ್ಥಿತಿ</translation>
+<translation id="658823671542763450">ಪೂರ್ಣ ಪರದೆ ನಮೂದಿಸು</translation>
+<translation id="7720026100085573005">ಉಳಿದಿರುವ ಸಮಯ</translation>
+<translation id="370665806235115550">ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ...</translation>
+<translation id="2723001399770238859">ಆಡಿಯೋ</translation>
+<translation id="6845533974506654842">ಒತ್ತಿ</translation>
+<translation id="8244226242650769279">ಇಮೇಜ್ ನಕ್ಷೆ</translation>
+<translation id="310520048233152454">ದಯವಿಟ್ಟು URL ಅನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="4812940957355064477">ದಯವಿಟ್ಟು ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="2548326553472216322">ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು ಇಲ್ಲ</translation>
+<translation id="1938124657309484470">ಮೌಲ್ಯವು <ph name="MAXIMUM_DATE_OR_TIME"/> ಅಥವಾ ಹಿಂದಿನದ್ದಾಗಿರಬೇಕು.</translation>
+<translation id="7263440858009898357">ಪಟ್ಟಿಯಲ್ಲಿನ ಐಟಂ ಅನ್ನು ದಯವಿಟ್ಟು ಆಯ್ಕೆ ಮಾಡಿ.</translation>
+<translation id="901493112792887934">ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪ್ರಸ್ತುತ ಸಮಯ</translation>
+<translation id="5164977714490026579">ಮೌಲ್ಯವು <ph name="MINIMUM"/> ಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಾಗಿರಬೇಕು ಅಥವಾ ಸಮನಾಗಿರಬೇಕು.</translation>
+<translation id="2247351761944213033">ವಾರ <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ಮುಚ್ಚಲಾಗಿರುವ ಶೀರ್ಷಿಕೆಗಳ ಪ್ರದರ್ಶಿಸುವಿಕೆಯನ್ನು ನಿಲ್ಲಿಸಿ</translation>
+<translation id="5944544982112848342">2048 (ಉನ್ನತ ಶ್ರೇಣಿ)</translation>
+<translation id="3075154866155599887">ದಯವಿಟ್ಟು ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಕ್ಷೇತ್ರವು ಅಪೂರ್ಣವಾಗಿದೆ ಅಥವಾ ಅಮಾನ್ಯ ದಿನಾಂಕವನ್ನು ಹೊಂದಿದೆ.</translation>
+<translation id="3040011195152428237">ಲಿಂಕ್</translation>
+<translation id="1014825444426747588">ಖಾಲಿ</translation>
+<translation id="9050748414552849310">ಮುಚ್ಚಿರುವ ಶೀರ್ಷಿಕೆಗಳನ್ನು ತೋರಿಸಿ</translation>
+<translation id="4522570452068850558">ವಿವರಗಳು</translation>
+<translation id="8451268428117625855">ದಯವಿಟ್ಟು ಫೈಲ್ ಆಯ್ಕೆಮಾಡಿ.</translation>
+<translation id="8117451130807776954">ಈ ವಾರ</translation>
+<translation id="5966707198760109579">ವಾರ</translation>
+<translation id="2901282870647571346">ಪ್ರಸ್ತುತ ಚಲನಚಿತ್ರದ ಸ್ಥಿತಿ</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' ಅನ್ನು '<ph name="INVALIDDOMAIN"/>' ನಲ್ಲಿ ತಪ್ಪಾದ ಸ್ಥಾನದಲ್ಲಿ ಬಳಸಲಾಗಿದೆ.</translation>
+<translation id="2674318244760992338">ಅಡಿಟಿಪ್ಪಣಿ</translation>
+<translation id="8987927404178983737">ತಿಂಗಳು</translation>
+<translation id="8115662671911883373">ಮುಚ್ಚಲಾಗಿರುವ ಶೀರ್ಷಿಕೆಗಳ ಪ್ರದರ್ಶಿಸುವಿಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ</translation>
+<translation id="7364796246159120393">ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿ</translation>
+<translation id="2761667185364618470">ನೀವು ಮುಂದುವರೆಯಬೇಕಾದರೆ ದಯವಿಟ್ಟು ಈ ಬಾಕ್ಸ್ ಅನ್ನು ಪರೀಕ್ಷಿಸಿ.</translation>
+<translation id="8534579021159131403">ನಿಮಿಷಗಳು</translation>
+<translation id="819205353528511139">ಪೂರ್ಣ ಪರದೆಯ ಮೋಡ್‌‌ನಲ್ಲಿ ಚಲನಚಿತ್ರವನ್ನು ಪ್ಲೇ ಮಾಡಿ</translation>
+<translation id="4103419683916926126">ಮಿಲಿಸೆಕೆಂಡುಗಳು</translation>
+<translation id="838869780401515933">ಪರಿಶೀಲಿಸು</translation>
+<translation id="2846343701378493991">1024 (ಮದ್ಯಮ ಶ್ರೇಣಿ)</translation>
+<translation id="1637811476055996098">ಫೈಲ್‌ಗಳನ್ನು ಆರಿಸಿ</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN"/>' ನಂತರದ ಒಂದು ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS"/>' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
+<translation id="5476505524087279545">ಪರೀಕ್ಷಿಸಬೇಡಿ</translation>
+<translation id="2148716181193084225">ಇಂದು</translation>
+<translation id="2507943997699731163">ದಯವಿಟ್ಟು ಈ ಕ್ಷೇತ್ರವನ್ನು ಭರ್ತಿ ಮಾಡಿ.</translation>
+<translation id="3785482301506746191">ಚಲನಚಿತ್ರ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್</translation>
+<translation id="739024184232394898">ಇತರೆ...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER"/>' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="5468998798572797635">ಪೂರ್ಣಪರದೆಯಿಂದ ನಿರ್ಗಮಿಸು</translation>
+<translation id="5919473608089529604">ಪ್ಲಗ್-ಇನ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.</translation>
+<translation id="5546461542133609677">ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
+<translation id="6663448176199120256">ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು</translation>
+<translation id="1020833440720551630">ಆಡಿಯೋ ಟ್ರ್ಯಾಕ್ ಮ್ಯೂಟ್ ಮಾಡು</translation>
+<translation id="2597378329261239068">ಈ ಡಾಕ್ಯುಮೆಂಟ್‌ ಅನ್ನು ಪಾಸ್‌ವರ್ಡ್‌ನಿಂದ ರಕ್ಷಿಸಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="5466621249238537318">ದಯವಿಟ್ಟು ಒಂದು ಅಥವಾ ಹೆಚ್ಚು ಫೈಲ್‌ಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ.</translation>
+<translation id="9132465097189459683">ಇತರೆ...</translation>
+<translation id="10623998915015855">ಟಾಗಲ್ ಬಟನ್</translation>
+<translation id="8750798805984357768">ದಯವಿಟ್ಟು ಈ ಕೆಳಗಿನ ಆಯ್ಕೆಗಳಲ್ಲಿ ಒಂದನ್ನು ಆರಿಸಿ.</translation>
+<translation id="7740050170769002709">HTML ವಿಷಯ</translation>
+<translation id="6692633176391053278">ಸ್ಟೀಪರ್</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ</translation>
+<translation id="8541249477527128034">ಮಾಧ್ಯಮ ನಿಯಂತ್ರಣ</translation>
+<translation id="2226276347425096477">ದಯವಿಟ್ಟು ಈ ಪಠ್ಯವನ್ನು <ph name="MAX_CHARACTERS"/> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತವಾಗಿ <ph name="CURRENT_LENGTH"/> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
+<translation id="6101327004457443354">ಆಡಿಯೋ ಟ್ರ್ಯಾಕ್ ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">ಲೋಡ್ ಆಗುತ್ತಿದೆ</translation>
+<translation id="2908441821576996758">ದಯವಿಟ್ಟು ಅಲ್ಪ ವಿರಾಮದಿಂದ ಬೇರ್ಪಡಿಸಿದ ಇಮೇಲ್ ವಿಳಾಸಗಳ ಪಟ್ಟಿಯನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="5939518447894949180">ಮರುಹೊಂದಿಸು</translation>
+<translation id="1921819250265091946">ದಿದಿ</translation>
+<translation id="2613802280814924224">ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯವು <ph name="VALID_VALUE"/> ಆಗಿದೆ.</translation>
+<translation id="835897206747267392">ಅಮಾನ್ಯ ಮೌಲ್ಯ.</translation>
+<translation id="1842960171412779397">ಆಯ್ಕೆ ಮಾಡಿ</translation>
+<translation id="7673697353781729403">ಗಂಟೆಗಳು</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER"/>' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="3450233048674729344">ಮೌಲ್ಯವು <ph name="MAXIMUM"/> ಕ್ಕೆ ಸಮನಾಗಿರಬಹುದು ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆ ಆಗಿರಬಹುದು.</translation>
+<translation id="668171684555832681">ಇತರೆ...</translation>
+<translation id="6270583010843788609">ಚಲನಚಿತ್ರ ಸಮಯಮಿತಿಯ ಥಂಬ್‌</translation>
+<translation id="5641012560118721995">ಪ್ಲೇಬ್ಯಾಕ್ ವಿರಾಮಗೊಳಿಸು</translation>
+<translation id="1591562245178063882">ಈ ತಿಂಗಳು</translation>
+<translation id="6119846243427417423">ಸಕ್ರಿಯಗೊಳಿಸು</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ಫೈಲ್‌ಗಳು</translation>
+<translation id="6643016212128521049">ತೆರವುಗೊಳಿಸಿ</translation>
+<translation id="7888071071722539607">ಇಮೇಲ್ ವಿಳಾಸದಲ್ಲಿ ಒಂದು '<ph name="ATSIGN"/>' ಅನ್ನು ಸೇರಿಸಿ. '<ph name="ATSIGN"/>' ನಲ್ಲಿ '<ph name="INVALIDADDRESS"/>' ಕಾಣೆಯಾಗಿದೆ.</translation>
+<translation id="1088086359088493902">ಸೆಕೆಂಡುಗಳು</translation>
+<translation id="3934680773876859118">PDF ಡಾಕ್ಯುಮೆಂಟ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ</translation>
+<translation id="3632707345189162177">ಚಲನಚಿತ್ರ ಬಾಕಿ ಉಳಿದಿರುವ ಸೆಕುಂಡುಗಳ ಸಂಖ್ಯೆ</translation>
+<translation id="6359256949422175976">ಚಲನಚಿತ್ರ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್ ಥಂಬ್</translation>
+<translation id="8597182159515967513">ಶೀರ್ಷಿಕೆ</translation>
+<translation id="6843725295806269523">ಮ್ಯೂಟ್</translation>
+<translation id="2653659639078652383">ಸಲ್ಲಿಸು</translation>
+<translation id="3732799496749320381">ಮಿಮೀ</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ko.xtb b/chromium/content/app/strings/translations/content_strings_ko.xtb
new file mode 100644
index 00000000000..2d22e6b703b
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ko.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ko">
+<translation id="4763480195061959176">동영상</translation>
+<translation id="5843503607508392247">다른 시간...</translation>
+<translation id="248395913932153421">일</translation>
+<translation id="1729654308190250600">비어 있지 않은 이메일 주소를 입력해 주세요.</translation>
+<translation id="6015796118275082299">연도</translation>
+<translation id="1235745349614807883">최근 검색 삭제</translation>
+<translation id="7223624360433298498">경과 시간</translation>
+<translation id="1171774979989969504">이메일 주소를 입력하세요.</translation>
+<translation id="709897737746224366">요청한 형식과 일치시키세요.</translation>
+<translation id="5048533449481078685">목록 표시기</translation>
+<translation id="4202807286478387388">건너뛰기</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN"/>' 앞 부분을 입력해 주세요. '<ph name="INVALIDADDRESS"/>'(이)가 완전하지 않습니다.</translation>
+<translation id="2746543609216772311">값은 <ph name="MINIMUM_DATE_OR_TIME"/> 이후여야 합니다.</translation>
+<translation id="2572483411312390101">재생</translation>
+<translation id="8785498733064193001">재생 시작</translation>
+<translation id="7057186640035488495">영화 시간</translation>
+<translation id="8199524924445686405">연도</translation>
+<translation id="795667975304826397">선택된 파일 없음</translation>
+<translation id="7789962463072032349">일시중지</translation>
+<translation id="6853785296079745596">캡션 숨기기</translation>
+<translation id="4360991593054037559">유효한 값을 입력해 주세요. 가장 근접한 유효 값 2개는 <ph name="VALID_VALUE_LOW"/> 및 <ph name="VALID_VALUE_HIGHER"/>입니다.</translation>
+<translation id="1758486001363313524">다른 일자...</translation>
+<translation id="8141602879876242471">이것은 검색 색인합니다. 검색 키워드 입력:</translation>
+<translation id="1930711995431081526">상태</translation>
+<translation id="658823671542763450">전체화면 열기</translation>
+<translation id="7720026100085573005">남은 시간</translation>
+<translation id="370665806235115550">로드 중...</translation>
+<translation id="2723001399770238859">오디오</translation>
+<translation id="6845533974506654842">누르기</translation>
+<translation id="8244226242650769279">이미지 지도</translation>
+<translation id="310520048233152454">URL을 입력하세요.</translation>
+<translation id="4812940957355064477">숫자를 입력하세요.</translation>
+<translation id="2548326553472216322">최근 수행된 검색 없음</translation>
+<translation id="1938124657309484470">값은 <ph name="MAXIMUM_DATE_OR_TIME"/> 이전이어야 합니다.</translation>
+<translation id="7263440858009898357">목록에서 항목을 선택하세요.</translation>
+<translation id="901493112792887934">현재 시간(초)</translation>
+<translation id="5164977714490026579">값은 <ph name="MINIMUM"/> 이상이어야 합니다.</translation>
+<translation id="2247351761944213033"><ph name="YEAR"/>, <ph name="WEEKNUMBER"/>번째 주</translation>
+<translation id="7740016676195725605">캡션 표시 중지</translation>
+<translation id="5944544982112848342">2048(높은 등급)</translation>
+<translation id="3075154866155599887">유효한 값을 입력하세요. 입력을 완료하지 않았거나 날짜가 잘못되었습니다.</translation>
+<translation id="3040011195152428237">링크</translation>
+<translation id="1014825444426747588">비어 있음</translation>
+<translation id="9050748414552849310">캡션 표시</translation>
+<translation id="4522570452068850558">세부정보</translation>
+<translation id="8451268428117625855">파일을 선택하세요.</translation>
+<translation id="8117451130807776954">이번 주</translation>
+<translation id="5966707198760109579">주</translation>
+<translation id="2901282870647571346">현재 영화 상태</translation>
+<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN"/>'에서 '<ph name="DOT"/>'의 위치가 잘못되었습니다.</translation>
+<translation id="2674318244760992338">바닥글</translation>
+<translation id="8987927404178983737">월</translation>
+<translation id="8115662671911883373">캡션 표시 시작</translation>
+<translation id="7364796246159120393">파일 선택</translation>
+<translation id="2761667185364618470">계속하려면 이 확인란을 선택하세요.</translation>
+<translation id="8534579021159131403">분</translation>
+<translation id="819205353528511139">전체화면 모드로 영화 재생</translation>
+<translation id="4103419683916926126">밀리초</translation>
+<translation id="838869780401515933">선택</translation>
+<translation id="2846343701378493991">1024(중간 등급)</translation>
+<translation id="1637811476055996098">파일 선택</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN"/>' 뒷 부분을 입력해 주세요. '<ph name="INVALIDADDRESS"/>'(이)가 완전하지 않습니다.</translation>
+<translation id="5476505524087279545">선택취소</translation>
+<translation id="2148716181193084225">오늘</translation>
+<translation id="2507943997699731163">이 입력란을 작성하세요.</translation>
+<translation id="3785482301506746191">영화 시간 스크러버</translation>
+<translation id="739024184232394898">다른 주...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' 앞 부분에 '<ph name="INVALIDCHARACTER"/>' 기호가 포함되면 안됩니다.</translation>
+<translation id="5468998798572797635">전체화면 닫기</translation>
+<translation id="5919473608089529604">플러그인을 로드할 수 없습니다.</translation>
+<translation id="5546461542133609677">음소거 해제</translation>
+<translation id="6663448176199120256">최근 수행된 검색</translation>
+<translation id="1020833440720551630">오디오 트랙 음소거</translation>
+<translation id="2597378329261239068">문서가 비밀번호로 보호되고 있습니다. 비밀번호를 입력하세요.</translation>
+<translation id="5466621249238537318">파일을 한 개 이상 선택하세요.</translation>
+<translation id="9132465097189459683">다른 달...</translation>
+<translation id="10623998915015855">전환 버튼</translation>
+<translation id="8750798805984357768">다음 옵션 중 하나를 선택하세요.</translation>
+<translation id="7740050170769002709">HTML 콘텐츠</translation>
+<translation id="6692633176391053278">증감자</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/>개 선택됨</translation>
+<translation id="8541249477527128034">미디어 컨트롤</translation>
+<translation id="2226276347425096477">이 텍스트를 <ph name="MAX_CHARACTERS"/>자 이하로 줄이세요(현재 <ph name="CURRENT_LENGTH"/>자 사용 중).</translation>
+<translation id="6101327004457443354">오디오 트랙 음소거 해제</translation>
+<translation id="1822429046913737220">오전/오후</translation>
+<translation id="1639239467298939599">로드 중</translation>
+<translation id="2908441821576996758">이메일 주소를 쉼표로 구분하여 입력하세요.</translation>
+<translation id="5939518447894949180">재설정</translation>
+<translation id="1921819250265091946">일</translation>
+<translation id="2613802280814924224">유효한 값을 입력해 주세요. 가장 근접한 유효 값은 <ph name="VALID_VALUE"/>입니다.</translation>
+<translation id="835897206747267392">값이 잘못되었습니다.</translation>
+<translation id="1842960171412779397">선택</translation>
+<translation id="7673697353781729403">시간</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' 다음 부분에 '<ph name="INVALIDCHARACTER"/>' 기호가 포함되면 안됩니다.</translation>
+<translation id="3450233048674729344">값은 <ph name="MAXIMUM"/> 이하여야 합니다.</translation>
+<translation id="668171684555832681">기타...</translation>
+<translation id="6270583010843788609">영화 타임라인 썸</translation>
+<translation id="5641012560118721995">재생 일시중지</translation>
+<translation id="1591562245178063882">이번 달</translation>
+<translation id="6119846243427417423">활성화</translation>
+<translation id="8444882422881193423">파일 <ph name="NUMBER_OF_FILES"/>개</translation>
+<translation id="6643016212128521049">삭제</translation>
+<translation id="7888071071722539607">이메일 주소에 '<ph name="ATSIGN"/>'를 포함해 주세요. '<ph name="INVALIDADDRESS"/>'에 '<ph name="ATSIGN"/>'가 없습니다.</translation>
+<translation id="1088086359088493902">초</translation>
+<translation id="3934680773876859118">PDF 문서를 로드하지 못했습니다.</translation>
+<translation id="3632707345189162177">영화 남은 시간(초)</translation>
+<translation id="6359256949422175976">영화 시간 스크러버 썸</translation>
+<translation id="8597182159515967513">항목</translation>
+<translation id="6843725295806269523">음소거</translation>
+<translation id="2653659639078652383">제출</translation>
+<translation id="3732799496749320381">월</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_lt.xtb b/chromium/content/app/strings/translations/content_strings_lt.xtb
new file mode 100644
index 00000000000..56505b97a2a
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_lt.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lt">
+<translation id="4763480195061959176">vaizdo įrašas</translation>
+<translation id="5843503607508392247">Kita...</translation>
+<translation id="248395913932153421">Diena</translation>
+<translation id="1729654308190250600">Įveskite el. pašto adresą (nepalikite lauko tuščio).</translation>
+<translation id="6015796118275082299">Metai</translation>
+<translation id="1235745349614807883">Išvalyti pastarąsias paieškas</translation>
+<translation id="7223624360433298498">praėjęs laikas</translation>
+<translation id="1171774979989969504">Įveskite el. pašto adresą.</translation>
+<translation id="709897737746224366">Priderinkite reikalaujamą formatą.</translation>
+<translation id="5048533449481078685">sąrašo žymeklis</translation>
+<translation id="4202807286478387388">peršokti</translation>
+<translation id="5307600278924710095">Įveskite el. pašto adreso dalį iki „<ph name="ATSIGN"/>“. „<ph name="INVALIDADDRESS"/>“ nėra visas el. pašto adresas.</translation>
+<translation id="2746543609216772311">Vertė turi būti <ph name="MINIMUM_DATE_OR_TIME"/> ar vėlesnė data.</translation>
+<translation id="2572483411312390101">paleisti</translation>
+<translation id="8785498733064193001">pradėti atkūrimą</translation>
+<translation id="7057186640035488495">filmo laikas</translation>
+<translation id="8199524924445686405">mmmm</translation>
+<translation id="795667975304826397">Nepasirinktas joks failas</translation>
+<translation id="7789962463072032349">pristabdyti</translation>
+<translation id="6853785296079745596">slėpti uždaras antraštes</translation>
+<translation id="4360991593054037559">Įveskite galiojančią vertę. Dvi artimiausios vertės yra <ph name="VALID_VALUE_LOW"/> ir <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Kita...</translation>
+<translation id="8141602879876242471">Tai yra ieškotinas indeksas. Įveskite paieškos raktinių žodžių:</translation>
+<translation id="1930711995431081526">būsena</translation>
+<translation id="658823671542763450">įjungti viso ekrano režimą</translation>
+<translation id="7720026100085573005">likęs laikas</translation>
+<translation id="370665806235115550">Įkeliama...</translation>
+<translation id="2723001399770238859">garso įrašas</translation>
+<translation id="6845533974506654842">paspausti</translation>
+<translation id="8244226242650769279">paveikslėlio žemėlapis</translation>
+<translation id="310520048233152454">Įveskite URL.</translation>
+<translation id="4812940957355064477">Įveskite skaičių.</translation>
+<translation id="2548326553472216322">Pastaruoju metu paieškų nevykdyta</translation>
+<translation id="1938124657309484470">Vertė turi būti <ph name="MAXIMUM_DATE_OR_TIME"/> ar ankstesnė data.</translation>
+<translation id="7263440858009898357">Pasirinkite sąraše pateiktą elementą.</translation>
+<translation id="901493112792887934">dabartinis laikas sekundėmis</translation>
+<translation id="5164977714490026579">Vertė turi būti <ph name="MINIMUM"/> arba didesnė.</translation>
+<translation id="2247351761944213033"><ph name="YEAR"/> m. <ph name="WEEKNUMBER"/> sav.</translation>
+<translation id="7740016676195725605">nebepateikti uždarų antraščių</translation>
+<translation id="5944544982112848342">2048 (Aukšto laipsnio)</translation>
+<translation id="3075154866155599887">Įveskite tinkamą vertę. Laukas užpildytas nevisiškai arba įvesta netinkama data.</translation>
+<translation id="3040011195152428237">nuoroda</translation>
+<translation id="1014825444426747588">tuščia</translation>
+<translation id="9050748414552849310">rodyti uždaras antraštes</translation>
+<translation id="4522570452068850558">Išsami informacija</translation>
+<translation id="8451268428117625855">Pasirinkite failą.</translation>
+<translation id="8117451130807776954">Ši savaitė</translation>
+<translation id="5966707198760109579">Savaitė</translation>
+<translation id="2901282870647571346">dabartinė filmo būsena</translation>
+<translation id="2060505056492490888">„<ph name="DOT"/>“ naudojamas netinkamoje „<ph name="INVALIDDOMAIN"/>“ vietoje.</translation>
+<translation id="2674318244760992338">poraštė</translation>
+<translation id="8987927404178983737">Mėnuo</translation>
+<translation id="8115662671911883373">pateikti uždaras antraštes</translation>
+<translation id="7364796246159120393">Pasirinkti failą</translation>
+<translation id="2761667185364618470">Jei norite tęsti, pažymėkite šį laukelį.</translation>
+<translation id="8534579021159131403">Minutės</translation>
+<translation id="819205353528511139">paleisti filmą viso ekrano režimu</translation>
+<translation id="4103419683916926126">Milisekundės</translation>
+<translation id="838869780401515933">tikrinti</translation>
+<translation id="2846343701378493991">1024 (vidutinio lygio)</translation>
+<translation id="1637811476055996098">Pasirinkti failus</translation>
+<translation id="49969490063480558">Įveskite dalį po „<ph name="ATSIGN"/>“. „<ph name="INVALIDADDRESS"/>“ nėra visas el. pašto adresas.</translation>
+<translation id="5476505524087279545">Nuimti žymėjimą</translation>
+<translation id="2148716181193084225">Šiandien</translation>
+<translation id="2507943997699731163">Užpildykite šį lauką.</translation>
+<translation id="3785482301506746191">filmo laiko valdiklis</translation>
+<translation id="739024184232394898">Kita...</translation>
+<translation id="383465348367842624">Prieš „<ph name="ATSIGN"/>“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER"/>“.</translation>
+<translation id="5468998798572797635">išeiti iš viso ekrano režimo</translation>
+<translation id="5919473608089529604">Nepavyko įkelti papildinio.</translation>
+<translation id="5546461542133609677">įjungti garsą</translation>
+<translation id="6663448176199120256">Naujausios paieškos</translation>
+<translation id="1020833440720551630">nutildyti garso įrašo takelį</translation>
+<translation id="2597378329261239068">Šis dokumentas apsaugotas slaptažodžiu. Įveskite slaptažodį.</translation>
+<translation id="5466621249238537318">Pasirinkite bent vieną failą.</translation>
+<translation id="9132465097189459683">Kita...</translation>
+<translation id="10623998915015855">perjungimo mygtukas</translation>
+<translation id="8750798805984357768">Pasirinkite vieną iš šių parinkčių.</translation>
+<translation id="7740050170769002709">HTML turinys</translation>
+<translation id="6692633176391053278">ėjimo aukštyn / žemyn valdiklis</translation>
+<translation id="4975562563186953947">Pasirinkta: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">medijos valdiklis</translation>
+<translation id="2226276347425096477">Sutrumpinkite šį tekstą iki <ph name="MAX_CHARACTERS"/> simb. ar mažiau (šiuo metu naudojate <ph name="CURRENT_LENGTH"/> simb.).</translation>
+<translation id="6101327004457443354">įjungti garso įrašo takelio garsą</translation>
+<translation id="1822429046913737220">iki pietų / po pietų</translation>
+<translation id="1639239467298939599">Įkeliama</translation>
+<translation id="2908441821576996758">Įveskite kableliais atskirtą el. pašto adresų sąrašą.</translation>
+<translation id="5939518447894949180">Nustatyti iš naujo</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Įveskite tinkamą vertę. Artimiausia tinkama vertė yra <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Neteisinga vertė.</translation>
+<translation id="1842960171412779397">pasirinkti</translation>
+<translation id="7673697353781729403">Valandos</translation>
+<translation id="4664250907885839816">Po „<ph name="ATSIGN"/>“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER"/>“.</translation>
+<translation id="3450233048674729344">Vertė turi būti <ph name="MAXIMUM"/> arba mažesnė.</translation>
+<translation id="668171684555832681">Kita...</translation>
+<translation id="6270583010843788609">filmo laiko juostos miniatiūra</translation>
+<translation id="5641012560118721995">pristabdyti atkūrimą</translation>
+<translation id="1591562245178063882">Šis mėnuo</translation>
+<translation id="6119846243427417423">aktyvinti</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> failai (-ų)</translation>
+<translation id="6643016212128521049">Išvalyti</translation>
+<translation id="7888071071722539607">Į el. pašto adresą įtraukite „<ph name="ATSIGN"/>“. „<ph name="INVALIDADDRESS"/>“ trūksta „<ph name="ATSIGN"/>“.</translation>
+<translation id="1088086359088493902">Sekundės</translation>
+<translation id="3934680773876859118">Nepavyko įkelti PDF dokumento</translation>
+<translation id="3632707345189162177">likusių filmo sekundžių skaičius</translation>
+<translation id="6359256949422175976">filmo laiko valdiklio miniatiūra</translation>
+<translation id="8597182159515967513">antraštė</translation>
+<translation id="6843725295806269523">nutildyti</translation>
+<translation id="2653659639078652383">Pateikti</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_lv.xtb b/chromium/content/app/strings/translations/content_strings_lv.xtb
new file mode 100644
index 00000000000..479305be3a9
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_lv.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="lv">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Cits...</translation>
+<translation id="248395913932153421">Diena</translation>
+<translation id="1729654308190250600">Lūdzu, ievadiet e-pasta adresi.</translation>
+<translation id="6015796118275082299">Gads</translation>
+<translation id="1235745349614807883">Dzēst nesenos meklējumus</translation>
+<translation id="7223624360433298498">pagājušais laiks</translation>
+<translation id="1171774979989969504">Ievadiet e-pasta adresi.</translation>
+<translation id="709897737746224366">Pieskaņojiet vērtību prasītajam formātam.</translation>
+<translation id="5048533449481078685">sarakstu marķieris</translation>
+<translation id="4202807286478387388">lekt</translation>
+<translation id="5307600278924710095">Lūdzu, ievadiet daļu, kas atrodas pirms zīmes <ph name="ATSIGN"/>. “<ph name="INVALIDADDRESS"/>” ir nepilna adrese.</translation>
+<translation id="2746543609216772311">Vērtībai ir jābūt “<ph name="MINIMUM_DATE_OR_TIME"/>” vai vēlākam datumam vai laikam.</translation>
+<translation id="2572483411312390101">atskaņot</translation>
+<translation id="8785498733064193001">sākt atskaņošanu</translation>
+<translation id="7057186640035488495">filmas laiks</translation>
+<translation id="8199524924445686405">gggg</translation>
+<translation id="795667975304826397">Nav izvēlēts neviens fails</translation>
+<translation id="7789962463072032349">pauzēt</translation>
+<translation id="6853785296079745596">slēpt slēgtos parakstus</translation>
+<translation id="4360991593054037559">Lūdzu, ievadiet derīgu vērtību. Divas tuvākās derīgās vērtības ir <ph name="VALID_VALUE_LOW"/> un <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Cits...</translation>
+<translation id="8141602879876242471">Šis ir indekss ar meklēšanas iespējām. Ievadīt meklēšanas atslēgvārdus:</translation>
+<translation id="1930711995431081526">statuss</translation>
+<translation id="658823671542763450">atvērt pilnekrāna režīmā</translation>
+<translation id="7720026100085573005">atlikušais laiks</translation>
+<translation id="370665806235115550">Notiek ielāde...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">nospiest</translation>
+<translation id="8244226242650769279">attēlu karte</translation>
+<translation id="310520048233152454">Ievadiet URL.</translation>
+<translation id="4812940957355064477">Lūdzu, ievadiet skaitli.</translation>
+<translation id="2548326553472216322">Nav nesenu meklējumu</translation>
+<translation id="1938124657309484470">Vērtībai ir jābūt “<ph name="MAXIMUM_DATE_OR_TIME"/>” vai agrākam datumam vai laikam.</translation>
+<translation id="7263440858009898357">Atlasiet vienumu sarakstā.</translation>
+<translation id="901493112792887934">pašreizējais laiks sekundēs</translation>
+<translation id="5164977714490026579">Vērtībai ir jābūt lielākai vai vienādai ar <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. nedēļa, <ph name="YEAR"/>. gads</translation>
+<translation id="7740016676195725605">apturēt slēgto parakstu rādīšanu</translation>
+<translation id="5944544982112848342">2048 (Augsta Atzīme)</translation>
+<translation id="3075154866155599887">Lūdzu, ievadiet derīgu vērtību. Šis lauks nav pabeigts, vai tajā ir norādīts nederīgs datums.</translation>
+<translation id="3040011195152428237">saite</translation>
+<translation id="1014825444426747588">tukšs</translation>
+<translation id="9050748414552849310">rādīt slēgtos parakstus</translation>
+<translation id="4522570452068850558">Informācija</translation>
+<translation id="8451268428117625855">Lūdzu, atlasiet failu.</translation>
+<translation id="8117451130807776954">Šī nedēļa</translation>
+<translation id="5966707198760109579">Nedēļa</translation>
+<translation id="2901282870647571346">pašreizējais filmas statuss</translation>
+<translation id="2060505056492490888">Punkts (<ph name="DOT"/>) atrodas nepareizā vietā (<ph name="INVALIDDOMAIN"/>).</translation>
+<translation id="2674318244760992338">kājene</translation>
+<translation id="8987927404178983737">Mēnesis</translation>
+<translation id="8115662671911883373">sākt slēgto parakstu rādīšanu</translation>
+<translation id="7364796246159120393">Izvēlēties failu</translation>
+<translation id="2761667185364618470">Lai turpinātu, atzīmējiet šo izvēles rūtiņu.</translation>
+<translation id="8534579021159131403">Minūtes</translation>
+<translation id="819205353528511139">atskaņot filmu pilnekrāna režīmā</translation>
+<translation id="4103419683916926126">Milisekundes</translation>
+<translation id="838869780401515933">prbaudt</translation>
+<translation id="2846343701378493991">1024 (Vidēja Atzīme)</translation>
+<translation id="1637811476055996098">Izvēlēties failus</translation>
+<translation id="49969490063480558">Lūdzu, ievadiet daļu, kas atrodas aiz zīmes <ph name="ATSIGN"/>. “<ph name="INVALIDADDRESS"/>” ir nepilna adrese.</translation>
+<translation id="5476505524087279545">neprbaudt</translation>
+<translation id="2148716181193084225">Šodien</translation>
+<translation id="2507943997699731163">Aizpildiet šo lauku.</translation>
+<translation id="3785482301506746191">filmas laika slīdnis</translation>
+<translation id="739024184232394898">Cits...</translation>
+<translation id="383465348367842624">Daļā, kas atrodas pirms zīmes <ph name="ATSIGN"/>, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="5468998798572797635">iziet no pilnekrāna režīma</translation>
+<translation id="5919473608089529604">Nevarēja ielādēt spraudni.</translation>
+<translation id="5546461542133609677">rādīt</translation>
+<translation id="6663448176199120256">Neseni meklējumi</translation>
+<translation id="1020833440720551630">izslēgt audio ieraksta skaņu</translation>
+<translation id="2597378329261239068">Šis dokuments ir aizsargāts ar paroli. Lūdzu, ievadiet paroli.</translation>
+<translation id="5466621249238537318">Lūdzu, atlasiet vienu vai vairākus failus.</translation>
+<translation id="9132465097189459683">Cits...</translation>
+<translation id="10623998915015855">pārslēgšanas poga</translation>
+<translation id="8750798805984357768">Lūdzu, atlasiet vienu no šīm opcijām.</translation>
+<translation id="7740050170769002709">HTML saturs</translation>
+<translation id="6692633176391053278">pārslēdzējs</translation>
+<translation id="4975562563186953947">Atlasīti <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">multivides vadība</translation>
+<translation id="2226276347425096477">Lūdzu, saīsiniet šo tekstu līdz <ph name="MAX_CHARACTERS"/> vai mazāk zīmēm (pašreiz tas ietver <ph name="CURRENT_LENGTH"/> rakstzīmes).</translation>
+<translation id="6101327004457443354">ieslēgt audio ieraksta skaņu</translation>
+<translation id="1822429046913737220">priekšpusdienā/pēcpusdienā</translation>
+<translation id="1639239467298939599">Notiek ielāde</translation>
+<translation id="2908441821576996758">Lūdzu, ievadiet ar komatu atdalītu e-pasta adrešu sarakstu.</translation>
+<translation id="5939518447894949180">Atiestatīt</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Lūdzu, ievadiet derīgu vērtību. Tuvākā derīgā vērtība ir <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Nederīga vērtība.</translation>
+<translation id="1842960171412779397">Atlasiet</translation>
+<translation id="7673697353781729403">Stundas</translation>
+<translation id="4664250907885839816">Daļā, kas atrodas aiz zīmes <ph name="ATSIGN"/>, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="3450233048674729344">Vērtībai ir jābūt mazākai vai vienādai ar <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Cits</translation>
+<translation id="6270583010843788609">filmas laika skalas sīktēls</translation>
+<translation id="5641012560118721995">pauzēt atskaņošanu</translation>
+<translation id="1591562245178063882">Šis mēnesis</translation>
+<translation id="6119846243427417423">aktivizt</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> faili</translation>
+<translation id="6643016212128521049">Notīrīt</translation>
+<translation id="7888071071722539607">E-pasta adresē ietveriet zīmi <ph name="ATSIGN"/>. Adresē “<ph name="INVALIDADDRESS"/>” trūkst zīmes <ph name="ATSIGN"/>.</translation>
+<translation id="1088086359088493902">Sekundes</translation>
+<translation id="3934680773876859118">Neizdevās ielādēt PDF dokumentu</translation>
+<translation id="3632707345189162177">atlikušais filmas laiks sekundēs</translation>
+<translation id="6359256949422175976">filmas laika skalas slīdņa sīktēls</translation>
+<translation id="8597182159515967513">Virsraksts</translation>
+<translation id="6843725295806269523">izslēgt skaņu</translation>
+<translation id="2653659639078652383">Iesniegt</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ml.xtb b/chromium/content/app/strings/translations/content_strings_ml.xtb
new file mode 100644
index 00000000000..cd73807a298
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ml.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ml">
+<translation id="4763480195061959176">വീഡിയോ</translation>
+<translation id="5843503607508392247">മറ്റുള്ളവ...</translation>
+<translation id="248395913932153421">ദിവസം</translation>
+<translation id="1729654308190250600">ശൂന്യമായിടാതെ, ഇമെയിൽ വിലാസം നൽകുക.</translation>
+<translation id="6015796118275082299">വര്‍ഷം</translation>
+<translation id="1235745349614807883">അടുത്തിടെയുള്ള തിരയലുകള്‍ മായ്ക്കുക</translation>
+<translation id="7223624360433298498">കഴിഞ്ഞ സമയം</translation>
+<translation id="1171774979989969504">ദയവായി ഒരു ഇമെയില്‍ വിലാസം നല്‍കുക.</translation>
+<translation id="709897737746224366">അഭ്യര്‍ത്ഥി ച്ചഫോര്‍മാറ്റ് ദയവായി പൊരുത്തപ്പെടുത്തുക.</translation>
+<translation id="5048533449481078685">പട്ടിക മാര്‍ക്കര്‍</translation>
+<translation id="4202807286478387388">jump</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN"/>' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS"/>' അപൂർണ്ണമാണ്.</translation>
+<translation id="2746543609216772311">മൂല്യം <ph name="MINIMUM_DATE_OR_TIME"/> എന്നതോ അതിനുശേഷമുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
+<translation id="2572483411312390101">പ്ലേ ചെയ്യുക</translation>
+<translation id="8785498733064193001">പ്ലേബാക്ക് ആരംഭിക്കുക</translation>
+<translation id="7057186640035488495">മൂവി ടൈം</translation>
+<translation id="8199524924445686405">വർഷം</translation>
+<translation id="795667975304826397">ഒരു ഫയലും തിരഞ്ഞെടുത്തിട്ടില്ല</translation>
+<translation id="7789962463072032349">താല്‍‌ക്കാലികമായി നിര്‍‌ത്തുക</translation>
+<translation id="6853785296079745596">അടച്ച അടിക്കുറിപ്പുകൾ മറയ്‌ക്കുക</translation>
+<translation id="4360991593054037559">സാധുവായ മൂല്യം നൽകുക. സാധുവായ ഏറ്റവുമടുത്ത രണ്ട് മൂല്യങ്ങൾ <ph name="VALID_VALUE_LOW"/>, <ph name="VALID_VALUE_HIGHER"/> എന്നിവയാണ്.</translation>
+<translation id="1758486001363313524">മറ്റുള്ളവ...</translation>
+<translation id="8141602879876242471">ഇത് തിരയാവുന്ന സൂചികയാണ്. തിരയല്‍ കീവേഡുകള്‍ നല്‍കുക:</translation>
+<translation id="1930711995431081526">നില</translation>
+<translation id="658823671542763450">പൂർണ്ണ സ്‌ക്രീനിലേക്ക് പോവുക</translation>
+<translation id="7720026100085573005">അവശേഷിക്കുന്ന സമയം</translation>
+<translation id="370665806235115550">ലോഡ്ചെയ്യുന്നു...</translation>
+<translation id="2723001399770238859">ഓഡിയോ</translation>
+<translation id="6845533974506654842">അമര്‍ത്തുക</translation>
+<translation id="8244226242650769279">ഇമേജ് മാപ്പ്</translation>
+<translation id="310520048233152454">ദയവായി ഒരു URL നല്‍കുക.</translation>
+<translation id="4812940957355064477">ഒരു നമ്പർ നൽകുക.</translation>
+<translation id="2548326553472216322">സമീപകാല തിരയലുകള്‍ ഇല്ല</translation>
+<translation id="1938124657309484470">മൂല്യം <ph name="MAXIMUM_DATE_OR_TIME"/> എന്നതോ അതിനുമുമ്പുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
+<translation id="7263440858009898357">പട്ടികയിലെ ഒരു ഇനം ദയവായി തിരഞ്ഞെടുക്കുക</translation>
+<translation id="901493112792887934">നിലവിലെ സമയം നിമിഷങ്ങളിൽ</translation>
+<translation id="5164977714490026579">മൂല്യം <ph name="MINIMUM"/> എന്നതില്‍ കൂടുതലോ സമമോ ആയിരിക്കണം.</translation>
+<translation id="2247351761944213033">ആഴ്‌ച <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">അടച്ച അടിക്കുറിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നത് നിർത്തുക</translation>
+<translation id="5944544982112848342">2048 (High Grade)</translation>
+<translation id="3075154866155599887">ഒരു സാധുതയുള്ള മൂല്യം നൽകുക. ഫീൽഡ് പൂർണ്ണമല്ല അല്ലെങ്കിൽ അസാധുവായ തീയതിയിലുള്ളതാണ്.</translation>
+<translation id="3040011195152428237">ലിങ്ക്</translation>
+<translation id="1014825444426747588">ശൂന്യം</translation>
+<translation id="9050748414552849310">അടച്ച അടിക്കുറിപ്പുകൾ കാണിക്കുക</translation>
+<translation id="4522570452068850558">വിശദാംശങ്ങള്‍‌</translation>
+<translation id="8451268428117625855">ദയവായി ഒരു ഫയല്‍ തരം തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="8117451130807776954">ഈ ആഴ്‌ച</translation>
+<translation id="5966707198760109579">ആഴ്‌ച</translation>
+<translation id="2901282870647571346">നിലവിലെ മൂവി നില</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>', '<ph name="INVALIDDOMAIN"/>' എന്നതിൽ തെറ്റായ സ്ഥാനത്താണ് ഉപയോഗിച്ചിരിക്കുന്നത്.</translation>
+<translation id="2674318244760992338">അടിക്കുറിപ്പ്</translation>
+<translation id="8987927404178983737">മാസം</translation>
+<translation id="8115662671911883373">അടച്ച അടിക്കുറിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നത് ആരംഭിക്കുക</translation>
+<translation id="7364796246159120393">ഫയല്‍ തിരഞ്ഞെടുക്കൂ</translation>
+<translation id="2761667185364618470">നിങ്ങള്‍ തുടരാന്‍ താല്‍പ്പര്യപ്പെടുന്നെങ്കില്‍ ഈ ബോക്സ് ദയവായി പരിശോധിക്കുക.</translation>
+<translation id="8534579021159131403">മിനിറ്റ്</translation>
+<translation id="819205353528511139">പൂർണ്ണ സ്‌ക്രീൻ മോഡിൽ മൂവി പ്ലേ ചെയ്യുക</translation>
+<translation id="4103419683916926126">മില്ലിസെക്കൻഡ്</translation>
+<translation id="838869780401515933">പരിശോധിക്കൂ</translation>
+<translation id="2846343701378493991">1024 (മീഡിയം ഗ്രേഡ്)</translation>
+<translation id="1637811476055996098">ഫയലുകൾ തിരഞ്ഞെടുക്കുക</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN"/>' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS"/>' അപൂർണ്ണമാണ്.</translation>
+<translation id="5476505524087279545">അണ്‍ചെക്ക് ചെയ്യുക</translation>
+<translation id="2148716181193084225">ഇന്ന്</translation>
+<translation id="2507943997699731163">ദയവായി ഈ ഫീല്‍ഡ് പൂരിപ്പിക്കുക.</translation>
+<translation id="3785482301506746191">മൂവി ടൈം സ്‌ക്രബ്ബർ</translation>
+<translation id="739024184232394898">മറ്റുള്ളവ...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' എന്നതിനുശേഷം വരുന്ന ഒരു ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER"/>' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="5468998798572797635">പൂർണ്ണ സ്‌ക്രീനിൽ നിന്ന് പുറത്തുകടക്കുക</translation>
+<translation id="5919473608089529604">പ്ലഗ്-ഇൻ ലോഡുചെയ്യാൻ കഴിഞ്ഞില്ല.</translation>
+<translation id="5546461542133609677">ശബ്‌ദമുള്ളതാക്കുക</translation>
+<translation id="6663448176199120256">സമീപകാല തിരയലുകള്‍</translation>
+<translation id="1020833440720551630">ഓഡിയോ ട്രാക്ക് നിശബ്‌ദമാക്കുക</translation>
+<translation id="2597378329261239068">ഈ പ്രമാണം പാസ്‌വേഡ് പരിരക്ഷിതമാണ്. ദയവായി ഒരു പാസ്‌വേഡ് നല്‍‌കുക.</translation>
+<translation id="5466621249238537318">ഒന്നോ അതില്‍ക്കൂടുതലോ ഫയലുകള്‍ ദയവായി തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="9132465097189459683">മറ്റുള്ളവ...</translation>
+<translation id="10623998915015855">ടോഗിൾ ബട്ടൺ</translation>
+<translation id="8750798805984357768">ഈ ഓപ്ഷനുകളിലൊന്ന് ദയവായി തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="7740050170769002709">HTML ഉള്ളടക്കം</translation>
+<translation id="6692633176391053278">സ്റ്റെപ്പർ</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> തിരഞ്ഞെടുത്തു</translation>
+<translation id="8541249477527128034">മീഡിയ നിയന്ത്രണം</translation>
+<translation id="2226276347425096477">ഈ വാചകത്തെ <ph name="MAX_CHARACTERS"/> അല്ലെങ്കില്‍ അതില്‍‌ക്കുറവ് പ്രതീകങ്ങളായി ദയവായി കുറയ്ക്കുക (നിങ്ങള്‍ നിലവില്‍ <ph name="CURRENT_LENGTH"/> പ്രതീകങ്ങള്‍ ഉപയോഗിക്കുകയാണ്).</translation>
+<translation id="6101327004457443354">ഓഡിയോ ട്രാക്ക് ശബ്‌ദമുള്ളതാക്കുക</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">ലോഡുചെയ്യുന്നു</translation>
+<translation id="2908441821576996758">ഇമെയില്‍ വിലാസങ്ങളുടെ കോമയാല്‍ വേര്‍തിരിച്ച ഒരു പട്ടിക ദയവായി നല്‍കുക.</translation>
+<translation id="5939518447894949180">വീണ്ടും സജ്ജീകരിക്കുക</translation>
+<translation id="1921819250265091946">തീയതി</translation>
+<translation id="2613802280814924224">സാധുവായ ഒരു മൂല്യം നൽകുക. ഏറ്റവുമടുത്ത സാധുവായ മൂല്യം <ph name="VALID_VALUE"/> ആണ്.</translation>
+<translation id="835897206747267392">അസാധുവായ മൂല്യം.</translation>
+<translation id="1842960171412779397">തിരഞ്ഞെടുക്കൂ</translation>
+<translation id="7673697353781729403">മണിക്കൂര്‍‌</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER"/>' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="3450233048674729344">മൂല്യം <ph name="MAXIMUM"/> എന്നതില്‍ കുറവോ സമമോ ആയിരിക്കണം.</translation>
+<translation id="668171684555832681">മറ്റുള്ളവ...</translation>
+<translation id="6270583010843788609">മൂവി ടൈംലൈൻ തമ്പ്</translation>
+<translation id="5641012560118721995">പ്ലേബാക്ക് താൽക്കാലികമായി നിർത്തുക</translation>
+<translation id="1591562245178063882">ഈ മാസം</translation>
+<translation id="6119846243427417423">ആക്റ്റിവേറ്റ് ചെയ്യുക</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ഫയലുകള്‍</translation>
+<translation id="6643016212128521049">മായ്‌ക്കുക</translation>
+<translation id="7888071071722539607">ഇമെയിൽ വിലാസത്തിൽ '<ph name="ATSIGN"/>' ഉൾപ്പെടുത്തുക. '<ph name="INVALIDADDRESS"/>' എന്നതിൽ ഒരു '<ph name="ATSIGN"/>' കാണുന്നില്ല.</translation>
+<translation id="1088086359088493902">സെക്കൻഡ്</translation>
+<translation id="3934680773876859118">PDF പ്രമാണം ലോഡുചെയ്യുന്നത് പരാജയപ്പെട്ടു</translation>
+<translation id="3632707345189162177">മൂവിയുടെ അവശേഷിക്കുന്ന നിമിഷങ്ങളുടെ എണ്ണം</translation>
+<translation id="6359256949422175976">മൂവി ടൈം സ്‌ക്രബ്ബർ തമ്പ്</translation>
+<translation id="8597182159515967513">തലക്കെട്ട്</translation>
+<translation id="6843725295806269523">നിശബ്‌ദമാക്കുക</translation>
+<translation id="2653659639078652383">സമര്‍പ്പിക്കൂ</translation>
+<translation id="3732799496749320381">മാസം</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_mr.xtb b/chromium/content/app/strings/translations/content_strings_mr.xtb
new file mode 100644
index 00000000000..a8504925737
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_mr.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="mr">
+<translation id="4763480195061959176">व्हिडिओ</translation>
+<translation id="5843503607508392247">अन्य...</translation>
+<translation id="248395913932153421">दिवस</translation>
+<translation id="1729654308190250600">कृपया एक रिक्त-नसलेला ईमेल पत्ता प्रविष्ट करा.</translation>
+<translation id="6015796118275082299">वर्ष</translation>
+<translation id="1235745349614807883">अलीकडील शोध साफ करा</translation>
+<translation id="7223624360433298498">लोटलेला अवधी</translation>
+<translation id="1171774979989969504">कृपया एक ईमेल पत्ता प्रविष्ट करा.</translation>
+<translation id="709897737746224366">कृपया विनंती केलेले स्वरूपन जुळवा.</translation>
+<translation id="5048533449481078685">सूची चिन्हक</translation>
+<translation id="4202807286478387388">जंप करा</translation>
+<translation id="5307600278924710095">कृपया '<ph name="ATSIGN"/>' मागुन येणारा भाग प्रविष्ट करा. '<ph name="INVALIDADDRESS"/>' अपूर्ण आहे.</translation>
+<translation id="2746543609216772311">मूल्य <ph name="MINIMUM_DATE_OR_TIME"/> किंवा नंतरचे असणे आवश्यक आहे.</translation>
+<translation id="2572483411312390101">प्ले करा</translation>
+<translation id="8785498733064193001">प्लेबॅक आरंभ करा</translation>
+<translation id="7057186640035488495">चित्रपटाची वेळ</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">कोणतीही फाइल निवडलेली नाही</translation>
+<translation id="7789962463072032349">विराम द्या</translation>
+<translation id="6853785296079745596">बंद मथळा लपवा</translation>
+<translation id="4360991593054037559">कृपया एक वैध मूल्य प्रविष्ट करा. दोन जवळील वैध मूल्ये <ph name="VALID_VALUE_LOW"/> आणि <ph name="VALID_VALUE_HIGHER"/> आहेत.</translation>
+<translation id="1758486001363313524">अन्य...</translation>
+<translation id="8141602879876242471">ही शोध घेण्यायोग्य अनुक्रमणिका आहे. शोध कीवर्ड प्रविष्ट करा:</translation>
+<translation id="1930711995431081526">स्थिती</translation>
+<translation id="658823671542763450">पूर्ण स्क्रीन प्रविष्ट करा</translation>
+<translation id="7720026100085573005">शिल्लक वेळ</translation>
+<translation id="370665806235115550">लोड करीत आहे...</translation>
+<translation id="2723001399770238859">ऑडिओ</translation>
+<translation id="6845533974506654842">दाबा</translation>
+<translation id="8244226242650769279">प्रतिमा नकाशा</translation>
+<translation id="310520048233152454">कृपया एखादी URL प्रविष्ट करा.</translation>
+<translation id="4812940957355064477">कृपया एक नंबर प्रविष्ट करा.</translation>
+<translation id="2548326553472216322">अलीकडील शोध नाहीत</translation>
+<translation id="1938124657309484470">मूल्य <ph name="MAXIMUM_DATE_OR_TIME"/> किंवा आधीचे असणे आवश्यक आहे.</translation>
+<translation id="7263440858009898357">कृपया सूचीमधील आयटम निवडा.</translation>
+<translation id="901493112792887934">वर्तमान वेळ सेकंदांमध्ये</translation>
+<translation id="5164977714490026579">मूल्य <ph name="MINIMUM"/> पेक्षा मोठे किंवा समान असावे.</translation>
+<translation id="2247351761944213033">आठवडा <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">बंद मथळा प्रदर्शित करणे थांबवा</translation>
+<translation id="5944544982112848342">2048 (उच्च ग्रेड)</translation>
+<translation id="3075154866155599887">कृपया एक वैध मूल्य प्रविष्ट करा. फील्ड अपूर्ण आहे किंवा अवैध तारीख आहे.</translation>
+<translation id="3040011195152428237">दुवा</translation>
+<translation id="1014825444426747588">रिक्त</translation>
+<translation id="9050748414552849310">बंद मथळा दर्शवा</translation>
+<translation id="4522570452068850558">तपशील</translation>
+<translation id="8451268428117625855">कृपया एखादी फाइल निवडा.</translation>
+<translation id="8117451130807776954">या आठवड्यात</translation>
+<translation id="5966707198760109579">आठवडा</translation>
+<translation id="2901282870647571346">वर्तमान चित्रपट स्थिती</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' '<ph name="INVALIDDOMAIN"/>' मध्ये चुकीच्या स्थितीवर वापरले आहे.</translation>
+<translation id="2674318244760992338">अधोलेख</translation>
+<translation id="8987927404178983737">महिना</translation>
+<translation id="8115662671911883373">बंद मथळा प्रदर्शित करणे प्रारंभ करा</translation>
+<translation id="7364796246159120393">फाइल निवडा</translation>
+<translation id="2761667185364618470">कृपया आपण पुढे चालू ठेवू इच्छित असल्यास हा बॉक्स पहा.</translation>
+<translation id="8534579021159131403">मिनिटे</translation>
+<translation id="819205353528511139">पूर्ण स्क्रीन मोडमध्ये चित्रपट प्ले करा</translation>
+<translation id="4103419683916926126">मिलिसेकंद</translation>
+<translation id="838869780401515933">तपासा</translation>
+<translation id="2846343701378493991">1024 (मध्यम प्रत)</translation>
+<translation id="1637811476055996098">फायली निवडा</translation>
+<translation id="49969490063480558">कृपया '<ph name="ATSIGN"/>' चे अनुसरण करणारा भाग प्रविष्ट करा. '<ph name="INVALIDADDRESS"/>' अपूर्ण आहे.</translation>
+<translation id="5476505524087279545">अनचेक</translation>
+<translation id="2148716181193084225">आज</translation>
+<translation id="2507943997699731163">कृपया हे फील्ड भरा.</translation>
+<translation id="3785482301506746191">चित्रपट वेळ स्क्रबर</translation>
+<translation id="739024184232394898">अन्य...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' मागुन येणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER"/>' चिन्ह नसावे.</translation>
+<translation id="5468998798572797635">पूर्ण स्क्रीनमधून निर्गमन करा</translation>
+<translation id="5919473608089529604">प्लग-इन लोड करणे शक्य झाले नाही.</translation>
+<translation id="5546461542133609677">सशब्द करा</translation>
+<translation id="6663448176199120256">अलीकडील शोध</translation>
+<translation id="1020833440720551630">ऑडिओ ट्रॅक निःशब्द करा</translation>
+<translation id="2597378329261239068">हा दस्तऐवज संकेतशब्द संरक्षित आहे. कृपया संकेतशब्द प्रविष्ट करा.</translation>
+<translation id="5466621249238537318">कृपया एक किंवा अधिक फायली निवडा.</translation>
+<translation id="9132465097189459683">अन्य...</translation>
+<translation id="10623998915015855">टॉगल बटण</translation>
+<translation id="8750798805984357768">कृपया या पर्यायांपैकी एक निवडा.</translation>
+<translation id="7740050170769002709">HTML सामुग्री</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> निवडले</translation>
+<translation id="8541249477527128034">माध्यम नियंत्रण</translation>
+<translation id="2226276347425096477">कृपया हा मजकूर <ph name="MAX_CHARACTERS"/> वर्ण लहान किंवा कमी करा (आपण सध्या <ph name="CURRENT_LENGTH"/> वर्ण वापरत आहात).</translation>
+<translation id="6101327004457443354">ऑडिओ ट्रॅक सशब्द करा</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">लोड करीत आहे</translation>
+<translation id="2908441821576996758">कृपया ईमेल पत्त्यांची स्वल्पविरामाद्वारे विभक्त सूची प्रविष्ट करा.</translation>
+<translation id="5939518447894949180">रीसेट करा</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">कृपया एक वैध मूल्य प्रविष्ट करा. जवळील वैध मूल्य <ph name="VALID_VALUE"/> आहे.</translation>
+<translation id="835897206747267392">अवैध मूल्य.</translation>
+<translation id="1842960171412779397">निवडा</translation>
+<translation id="7673697353781729403">तास</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' चे अनुसरण करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER"/>' चिन्ह नसावे.</translation>
+<translation id="3450233048674729344">मूल्य <ph name="MAXIMUM"/> पेक्षा कमी किंवा समान असावे.</translation>
+<translation id="668171684555832681">अन्य...</translation>
+<translation id="6270583010843788609">चित्रपट टाइमलाइन थंब</translation>
+<translation id="5641012560118721995">प्लेबॅकला विराम द्या</translation>
+<translation id="1591562245178063882">या महिन्यात</translation>
+<translation id="6119846243427417423">सक्रिय करा</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> फायली</translation>
+<translation id="6643016212128521049">साफ करा</translation>
+<translation id="7888071071722539607">कृपया ईमेल पत्त्यामध्ये '<ph name="ATSIGN"/>' समाविष्ट करा. '<ph name="INVALIDADDRESS"/>' '<ph name="ATSIGN"/>' गमावत आहे.</translation>
+<translation id="1088086359088493902">सेकंद</translation>
+<translation id="3934680773876859118">PDF दस्तऐवज लोड करणे अयशस्वी</translation>
+<translation id="3632707345189162177">चित्रपटाचे शिल्लक सेकंद</translation>
+<translation id="6359256949422175976">चित्रपट वेळ स्क्रबर थंब</translation>
+<translation id="8597182159515967513">शीर्षलेख</translation>
+<translation id="6843725295806269523">नि:शब्द करा</translation>
+<translation id="2653659639078652383">सबमिट करा</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ms.xtb b/chromium/content/app/strings/translations/content_strings_ms.xtb
new file mode 100644
index 00000000000..def0378cbaf
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ms.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ms">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Lain-lain...</translation>
+<translation id="248395913932153421">Hari</translation>
+<translation id="1729654308190250600">Sila masukkan alamat e-mel bukan kosong.</translation>
+<translation id="6015796118275082299">Tahun</translation>
+<translation id="1235745349614807883">Kosongkan Carian Baru-baru Ini</translation>
+<translation id="7223624360433298498">masa berlalu</translation>
+<translation id="1171774979989969504">Sila masukkan alamat e-mel.</translation>
+<translation id="709897737746224366">Sila padankan dengan format yang diminta.</translation>
+<translation id="5048533449481078685">penanda senarai</translation>
+<translation id="4202807286478387388">lompat</translation>
+<translation id="5307600278924710095">Sila masukkan bahagian diikuti oleh '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' tidak lengkap.</translation>
+<translation id="2746543609216772311">Nilai mestilah <ph name="MINIMUM_DATE_OR_TIME"/> atau kemudian.</translation>
+<translation id="2572483411312390101">main</translation>
+<translation id="8785498733064193001">mulakan main balik</translation>
+<translation id="7057186640035488495">masa filem</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">Tiada fail dipilih</translation>
+<translation id="7789962463072032349">jeda</translation>
+<translation id="6853785296079745596">sembunyikan kapsyen tertutup</translation>
+<translation id="4360991593054037559">Sila masukkan nilai yang sah. Dua nilai sah yang terdekat ialah <ph name="VALID_VALUE_LOW"/> dan <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Lain-lain...</translation>
+<translation id="8141602879876242471">Ini adalah indeks boleh dicari. Masukkan kata kunci carian:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">memasuki skrin penuh</translation>
+<translation id="7720026100085573005">masa yang tinggal</translation>
+<translation id="370665806235115550">Memuatkan...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">tekan</translation>
+<translation id="8244226242650769279">peta imej</translation>
+<translation id="310520048233152454">Sila masukkan URL.</translation>
+<translation id="4812940957355064477">Sila masukkan nombor.</translation>
+<translation id="2548326553472216322">Tiada carian baru-baru ini</translation>
+<translation id="1938124657309484470">Nilai mestilah <ph name="MAXIMUM_DATE_OR_TIME"/> atau lebih awal.</translation>
+<translation id="7263440858009898357">Sila pilih item dalam senarai.</translation>
+<translation id="901493112792887934">masa semasa dalam saat</translation>
+<translation id="5164977714490026579">Nilai mesti lebih besar daripada atau sama dengan <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">berhenti memaparkan kapsyen tertutup</translation>
+<translation id="5944544982112848342">2048 (Gred Tinggi)</translation>
+<translation id="3075154866155599887">Sila masukkan nilai yang sah. Medan tidak lengkap atau mengandungi tarikh yang tidak sah.</translation>
+<translation id="3040011195152428237">pautan</translation>
+<translation id="1014825444426747588">kosong</translation>
+<translation id="9050748414552849310">paparkan kapsyen tertutup</translation>
+<translation id="4522570452068850558">Butiran</translation>
+<translation id="8451268428117625855">Sila pilih fail.</translation>
+<translation id="8117451130807776954">Minggu ini</translation>
+<translation id="5966707198760109579">Minggu</translation>
+<translation id="2901282870647571346">status filem semasa</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' digunakan pada kedudukan yang salah dalam '<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">pembawah</translation>
+<translation id="8987927404178983737">Bulan</translation>
+<translation id="8115662671911883373">mula memaparkan kapsyen tertutup</translation>
+<translation id="7364796246159120393">Pilih Fail</translation>
+<translation id="2761667185364618470">Sila tandakan kotak ini jika anda mahu teruskan.</translation>
+<translation id="8534579021159131403">Minit</translation>
+<translation id="819205353528511139">mainkan filem dalam mod skrin penuh</translation>
+<translation id="4103419683916926126">Milisaat</translation>
+<translation id="838869780401515933">periksa</translation>
+<translation id="2846343701378493991">1024 (Gred Sederhana)</translation>
+<translation id="1637811476055996098">Pilih Fail</translation>
+<translation id="49969490063480558">Sila masukkan bahagian selepas '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' tidak lengkap.</translation>
+<translation id="5476505524087279545">nyahpilih</translation>
+<translation id="2148716181193084225">Hari ini</translation>
+<translation id="2507943997699731163">Sila isikan medan ini.</translation>
+<translation id="3785482301506746191">pembersih masa filem</translation>
+<translation id="739024184232394898">Lain-lain...</translation>
+<translation id="383465348367842624">Bahagian yang diikuti oleh '<ph name="ATSIGN"/>' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="5468998798572797635">keluar daripada skrin penuh</translation>
+<translation id="5919473608089529604">Tidak dapat memuatkan pemalam.</translation>
+<translation id="5546461542133609677">nyahredam</translation>
+<translation id="6663448176199120256">Carian Baru-baru Ini</translation>
+<translation id="1020833440720551630">redamkan runut audio</translation>
+<translation id="2597378329261239068">Dokumen ini dilindungi kata laluan. Sila masukkan kata laluan.</translation>
+<translation id="5466621249238537318">Sila pilih satu fail atau lebih.</translation>
+<translation id="9132465097189459683">Lain-lain...</translation>
+<translation id="10623998915015855">butang togol</translation>
+<translation id="8750798805984357768">Sila pilih salah satu pilihan ini.</translation>
+<translation id="7740050170769002709">Kandungan HTML</translation>
+<translation id="6692633176391053278">pelangkah</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> dipilih</translation>
+<translation id="8541249477527128034">kawalan media</translation>
+<translation id="2226276347425096477">Sila pendekkan teks ini menjadi <ph name="MAX_CHARACTERS"/> aksara atau kurang (anda kini menggunakan <ph name="CURRENT_LENGTH"/> aksara).</translation>
+<translation id="6101327004457443354">nyahredam runut audio</translation>
+<translation id="1822429046913737220">PG / P/M</translation>
+<translation id="1639239467298939599">Memuatkan</translation>
+<translation id="2908441821576996758">Sila masukkan senarai alamat e-mel yang dipisahkan dengan koma.</translation>
+<translation id="5939518447894949180">Tetapkan semula</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Sila masukkan nilai yang sah. Nilai sah yang terdekat ialah <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Nilai tidak sah.</translation>
+<translation id="1842960171412779397">pilih</translation>
+<translation id="7673697353781729403">Jam</translation>
+<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN"/>' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="3450233048674729344">Nilai mestilah kurang daripada atau sama dengan <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Lain-lain...</translation>
+<translation id="6270583010843788609">ibu jari garis masa filem</translation>
+<translation id="5641012560118721995">jeda main balik</translation>
+<translation id="1591562245178063882">Bulan ini</translation>
+<translation id="6119846243427417423">aktifkan</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> fail</translation>
+<translation id="6643016212128521049">Kosongkan</translation>
+<translation id="7888071071722539607">Sila masukkan '<ph name="ATSIGN"/>' dalam alamat e-mel. '<ph name="INVALIDADDRESS"/>' tiada '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">Saat</translation>
+<translation id="3934680773876859118">Gagal untuk memuatkan dokumen PDF</translation>
+<translation id="3632707345189162177">bilangan saat filem yang tinggal</translation>
+<translation id="6359256949422175976">ibu jari pembersih masa filem</translation>
+<translation id="8597182159515967513">tajuk</translation>
+<translation id="6843725295806269523">redam</translation>
+<translation id="2653659639078652383">Serah</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_nl.xtb b/chromium/content/app/strings/translations/content_strings_nl.xtb
new file mode 100644
index 00000000000..6b0cd97cd62
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_nl.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="nl">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Anders...</translation>
+<translation id="248395913932153421">Dag</translation>
+<translation id="1729654308190250600">Geef een e-mailadres op.</translation>
+<translation id="6015796118275082299">Jaar</translation>
+<translation id="1235745349614807883">Recente zoekopdrachten wissen</translation>
+<translation id="7223624360433298498">verstreken tijd</translation>
+<translation id="1171774979989969504">Geef een e-mailadres op.</translation>
+<translation id="709897737746224366">Zorg dat de indeling voldoet aan de gevraagde indeling.</translation>
+<translation id="5048533449481078685">lijstmarkering</translation>
+<translation id="4202807286478387388">Gaan naar</translation>
+<translation id="5307600278924710095">Geef een naamgedeelte op, gevolgd door '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' is onvolledig.</translation>
+<translation id="2746543609216772311">Waarde moet <ph name="MINIMUM_DATE_OR_TIME"/> of later zijn.</translation>
+<translation id="2572483411312390101">afspelen</translation>
+<translation id="8785498733064193001">afspelen starten</translation>
+<translation id="7057186640035488495">tijd van de film</translation>
+<translation id="8199524924445686405">jjjj</translation>
+<translation id="795667975304826397">Geen bestand gekozen</translation>
+<translation id="7789962463072032349">onderbreken</translation>
+<translation id="6853785296079745596">ondertiteling verbergen</translation>
+<translation id="4360991593054037559">Geef een geldige waarde op. De twee dichtstbijzijnde geldige waarden zijn <ph name="VALID_VALUE_LOW"/> en <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Anders...</translation>
+<translation id="8141602879876242471">Dit is een doorzoekbare index. Geef zoekwoorden op:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">volledig scherm openen</translation>
+<translation id="7720026100085573005">resterende tijd</translation>
+<translation id="370665806235115550">Laden...</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">Indrukken</translation>
+<translation id="8244226242650769279">image map</translation>
+<translation id="310520048233152454">Geef een URL op.</translation>
+<translation id="4812940957355064477">Voer een getal in.</translation>
+<translation id="2548326553472216322">Geen recente zoekopdrachten</translation>
+<translation id="1938124657309484470">Waarde moet <ph name="MAXIMUM_DATE_OR_TIME"/> of eerder zijn.</translation>
+<translation id="7263440858009898357">Selecteer een item in de lijst.</translation>
+<translation id="901493112792887934">huidige tijd in seconden</translation>
+<translation id="5164977714490026579">Waarde moet groter dan of gelijk zijn aan <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Week <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">het weergeven van ondertiteling stoppen</translation>
+<translation id="5944544982112848342">2048 (hoog niveau)</translation>
+<translation id="3075154866155599887">Voer een geldige waarde in. Het veld is onvolledig of bevat een ongeldige datum.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">leeg</translation>
+<translation id="9050748414552849310">ondertiteling weergeven</translation>
+<translation id="4522570452068850558">Details</translation>
+<translation id="8451268428117625855">Selecteer een bestand.</translation>
+<translation id="8117451130807776954">Deze week</translation>
+<translation id="5966707198760109579">Week</translation>
+<translation id="2901282870647571346">huidige filmstatus</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' wordt op een verkeerde positie gebruikt in '<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">voettekst</translation>
+<translation id="8987927404178983737">Maand</translation>
+<translation id="8115662671911883373">het weergeven van ondertiteling starten</translation>
+<translation id="7364796246159120393">Bestand kiezen</translation>
+<translation id="2761667185364618470">Vink dit selectievakje aan als je wilt doorgaan.</translation>
+<translation id="8534579021159131403">Minuten</translation>
+<translation id="819205353528511139">film afspelen op volledig scherm</translation>
+<translation id="4103419683916926126">Milliseconden</translation>
+<translation id="838869780401515933">Selecteren</translation>
+<translation id="2846343701378493991">1024 (gemiddeld niveau)</translation>
+<translation id="1637811476055996098">Bestanden kiezen</translation>
+<translation id="49969490063480558">Geef een adresgedeelte op na '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' is onvolledig.</translation>
+<translation id="5476505524087279545">Deselecteren</translation>
+<translation id="2148716181193084225">Vandaag</translation>
+<translation id="2507943997699731163">Vul dit veld in.</translation>
+<translation id="3785482301506746191">schuifbalk met tijd van de film</translation>
+<translation id="739024184232394898">Anders...</translation>
+<translation id="383465348367842624">Het naamgedeelte vóór '<ph name="ATSIGN"/>' mag niet het teken '<ph name="INVALIDCHARACTER"/>' bevatten.</translation>
+<translation id="5468998798572797635">volledig scherm sluiten</translation>
+<translation id="5919473608089529604">Kan plug-in niet laden.</translation>
+<translation id="5546461542133609677">dempen opheffen</translation>
+<translation id="6663448176199120256">Recente zoekopdrachten</translation>
+<translation id="1020833440720551630">audiotrack dempen</translation>
+<translation id="2597378329261239068">Dit document is beveiligd met een wachtwoord. Geef een wachtwoord op.</translation>
+<translation id="5466621249238537318">Selecteer een of meer bestanden.</translation>
+<translation id="9132465097189459683">Anders...</translation>
+<translation id="10623998915015855">schakelknop</translation>
+<translation id="8750798805984357768">Selecteer een van deze opties.</translation>
+<translation id="7740050170769002709">HTML-inhoud</translation>
+<translation id="6692633176391053278">stappenregelaar</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> geselecteerd</translation>
+<translation id="8541249477527128034">mediacontrole</translation>
+<translation id="2226276347425096477">Kort deze tekst in tot <ph name="MAX_CHARACTERS"/> tekens of minder (je gebruikt momenteel <ph name="CURRENT_LENGTH"/> tekens).</translation>
+<translation id="6101327004457443354">dempen van audiotrack opheffen</translation>
+<translation id="1822429046913737220">a.m./p.m.</translation>
+<translation id="1639239467298939599">Laden</translation>
+<translation id="2908441821576996758">Voer een door komma's gescheiden lijst met e-mailadressen in.</translation>
+<translation id="5939518447894949180">Terugzetten</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Geef een geldige waarde op. De dichtstbijzijnde geldige waarde is <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Ongeldige waarde.</translation>
+<translation id="1842960171412779397">Selecteren</translation>
+<translation id="7673697353781729403">Uur</translation>
+<translation id="4664250907885839816">Het adresgedeelte na '<ph name="ATSIGN"/>' mag niet het teken '<ph name="INVALIDCHARACTER"/>' bevatten.</translation>
+<translation id="3450233048674729344">Waarde moet kleiner dan of gelijk zijn aan <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Anders...</translation>
+<translation id="6270583010843788609">miniatuur van tijdlijn van film</translation>
+<translation id="5641012560118721995">afspelen onderbreken</translation>
+<translation id="1591562245178063882">Deze maand</translation>
+<translation id="6119846243427417423">Activeren</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> bestanden</translation>
+<translation id="6643016212128521049">Wissen</translation>
+<translation id="7888071071722539607">Gebruik een '<ph name="ATSIGN"/>' in thet e-mailadres. In '<ph name="INVALIDADDRESS"/>' ontbreekt een '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">Seconden</translation>
+<translation id="3934680773876859118">PDF-document kan niet worden geladen</translation>
+<translation id="3632707345189162177">aantal seconden van resterende film</translation>
+<translation id="6359256949422175976">miniatuur van schuifbalk met tijd van de film</translation>
+<translation id="8597182159515967513">kop</translation>
+<translation id="6843725295806269523">dempen</translation>
+<translation id="2653659639078652383">Verzenden</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_no.xtb b/chromium/content/app/strings/translations/content_strings_no.xtb
new file mode 100644
index 00000000000..394354d3eeb
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_no.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="no">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Andre</translation>
+<translation id="248395913932153421">Dag</translation>
+<translation id="1729654308190250600">Skriv inn en ikke-tom e-postadresse.</translation>
+<translation id="6015796118275082299">År</translation>
+<translation id="1235745349614807883">Fjern nylige søk</translation>
+<translation id="7223624360433298498">brukt tid</translation>
+<translation id="1171774979989969504">Skriv inn en e-postadresse.</translation>
+<translation id="709897737746224366">Sørg for samsvar med det forespurte formatet.</translation>
+<translation id="5048533449481078685">listemarkør</translation>
+<translation id="4202807286478387388">hopp</translation>
+<translation id="5307600278924710095">Skriv inn en del etterfulgt av «<ph name="ATSIGN"/>». «<ph name="INVALIDADDRESS"/>» er ufullstendig.</translation>
+<translation id="2746543609216772311">Verdien må være <ph name="MINIMUM_DATE_OR_TIME"/> eller senere.</translation>
+<translation id="2572483411312390101">spill av</translation>
+<translation id="8785498733064193001">start avspillingen</translation>
+<translation id="7057186640035488495">gå til et annet tidspunkt</translation>
+<translation id="8199524924445686405">åååå</translation>
+<translation id="795667975304826397">Ingen fil valgt</translation>
+<translation id="7789962463072032349">stans midlertidig</translation>
+<translation id="6853785296079745596">skjul teksting</translation>
+<translation id="4360991593054037559">Skriv inn en gyldig verdi. De to nærmeste, gyldige verdiene er <ph name="VALID_VALUE_LOW"/> og <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Andre</translation>
+<translation id="8141602879876242471">Dette er en søkbar indeks. Angi søkeordene:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">gå til fullskjermmodus</translation>
+<translation id="7720026100085573005">tid som gjenstår</translation>
+<translation id="370665806235115550">Laster inn...</translation>
+<translation id="2723001399770238859">lyd</translation>
+<translation id="6845533974506654842">trykk</translation>
+<translation id="8244226242650769279">bildekart</translation>
+<translation id="310520048233152454">Skriv inn en nettadresse.</translation>
+<translation id="4812940957355064477">Skriv inn et tall.</translation>
+<translation id="2548326553472216322">Ingen nylige søk</translation>
+<translation id="1938124657309484470">Verdien må være <ph name="MAXIMUM_DATE_OR_TIME"/> eller før.</translation>
+<translation id="7263440858009898357">Velg en artikkel i listen.</translation>
+<translation id="901493112792887934">gjeldende tid i sekunder</translation>
+<translation id="5164977714490026579">Verdien må være større enn eller lik <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Uke <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">slå av tekstingen</translation>
+<translation id="5944544982112848342">2048 (sterk)</translation>
+<translation id="3075154866155599887">Skriv inn en gyldig verdi. Feltet er ufullstendig, eller har en ugyldig dato.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">tom</translation>
+<translation id="9050748414552849310">vis teksting</translation>
+<translation id="4522570452068850558">Detaljer</translation>
+<translation id="8451268428117625855">Velg en fil.</translation>
+<translation id="8117451130807776954">Denne uken</translation>
+<translation id="5966707198760109579">Uke</translation>
+<translation id="2901282870647571346">gjeldende filmstatus</translation>
+<translation id="2060505056492490888">«<ph name="DOT"/>» er brukt på feil sted i «<ph name="INVALIDDOMAIN"/>».</translation>
+<translation id="2674318244760992338">fotnote</translation>
+<translation id="8987927404178983737">Måned</translation>
+<translation id="8115662671911883373">slå på tekstingen</translation>
+<translation id="7364796246159120393">Velg fil</translation>
+<translation id="2761667185364618470">Kryss av denne boksen hvis du vil fortsette.</translation>
+<translation id="8534579021159131403">Minutter</translation>
+<translation id="819205353528511139">spill av filmen i fullskjermmodus</translation>
+<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="838869780401515933">merk av</translation>
+<translation id="2846343701378493991">1024 (middels)</translation>
+<translation id="1637811476055996098">Velg filer</translation>
+<translation id="49969490063480558">Skriv inn en del etterfulgt av «<ph name="ATSIGN"/>». «<ph name="INVALIDADDRESS"/>» er ufullstendig.</translation>
+<translation id="5476505524087279545">fjern merke</translation>
+<translation id="2148716181193084225">I dag</translation>
+<translation id="2507943997699731163">Vennligst fyll ut dette feltet.</translation>
+<translation id="3785482301506746191">videotidslinje</translation>
+<translation id="739024184232394898">Andre</translation>
+<translation id="383465348367842624">En del etterfulgt av «<ph name="ATSIGN"/>» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER"/>».</translation>
+<translation id="5468998798572797635">avslutt fullskjerm</translation>
+<translation id="5919473608089529604">Kunne ikke laste inn programtillegget.</translation>
+<translation id="5546461542133609677">slå på lyden</translation>
+<translation id="6663448176199120256">Nylige søk</translation>
+<translation id="1020833440720551630">slå av lydsporet</translation>
+<translation id="2597378329261239068">Dette dokumentet er passordbeskyttet. Skriv inn et passord.</translation>
+<translation id="5466621249238537318">Velg én eller flere filer.</translation>
+<translation id="9132465097189459683">Andre</translation>
+<translation id="10623998915015855">av/på-knapp</translation>
+<translation id="8750798805984357768">Velg ett av følgende alternativer.</translation>
+<translation id="7740050170769002709">HTML-innhold</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> er valgt</translation>
+<translation id="8541249477527128034">mediekontroll</translation>
+<translation id="2226276347425096477">Forkort denne teksten til <ph name="MAX_CHARACTERS"/> tegn eller færre (for øyeblikket bruker du <ph name="CURRENT_LENGTH"/> tegn).</translation>
+<translation id="6101327004457443354">slå på lydsporet</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Laster inn</translation>
+<translation id="2908441821576996758">Skriv inn en liste over e-postadresser atskilt med komma.</translation>
+<translation id="5939518447894949180">Tilbakestill</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Skriv inn en gyldig verdi. Den nærmeste, gyldige verdien er <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Ugyldig verdi</translation>
+<translation id="1842960171412779397">velg</translation>
+<translation id="7673697353781729403">Timer</translation>
+<translation id="4664250907885839816">En del etterfulgt av «<ph name="ATSIGN"/>» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER"/>».</translation>
+<translation id="3450233048674729344">Verdien må være mindre enn eller lik <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Annen</translation>
+<translation id="6270583010843788609">filmtidslinjemarkøren</translation>
+<translation id="5641012560118721995">stopp avspillingen midlertidig</translation>
+<translation id="1591562245178063882">Denne måneden</translation>
+<translation id="6119846243427417423">aktiver</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> filer</translation>
+<translation id="6643016212128521049">Tøm</translation>
+<translation id="7888071071722539607">Inkluder en «<ph name="ATSIGN"/>» i e-postadressen. «<ph name="INVALIDADDRESS"/>» mangler en «<ph name="ATSIGN"/>».</translation>
+<translation id="1088086359088493902">Sekunder</translation>
+<translation id="3934680773876859118">Kan ikke laste inn PDF-dokument</translation>
+<translation id="3632707345189162177">antall sekunder som gjenstår av filmen</translation>
+<translation id="6359256949422175976">markøren for filmtidslinjen</translation>
+<translation id="8597182159515967513">overskrift</translation>
+<translation id="6843725295806269523">kutt lyd</translation>
+<translation id="2653659639078652383">Send</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pl.xtb b/chromium/content/app/strings/translations/content_strings_pl.xtb
new file mode 100644
index 00000000000..c34757f0599
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_pl.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pl">
+<translation id="4763480195061959176">film</translation>
+<translation id="5843503607508392247">Inny...</translation>
+<translation id="248395913932153421">Dzień</translation>
+<translation id="1729654308190250600">Podaj adres e-mail.</translation>
+<translation id="6015796118275082299">Rok</translation>
+<translation id="1235745349614807883">Wyczyść ostatnie wyszukiwania</translation>
+<translation id="7223624360433298498">upłynęło czasu</translation>
+<translation id="1171774979989969504">Wprowadź adres e-mail.</translation>
+<translation id="709897737746224366">Podaj wartość w wymaganym formacie.</translation>
+<translation id="5048533449481078685">znacznik listy</translation>
+<translation id="4202807286478387388">przejdź</translation>
+<translation id="5307600278924710095">Podaj część przed znakiem „<ph name="ATSIGN"/>”. Adres „<ph name="INVALIDADDRESS"/>” jest niepełny.</translation>
+<translation id="2746543609216772311">Musisz podać wartość <ph name="MINIMUM_DATE_OR_TIME"/> lub późniejszą.</translation>
+<translation id="2572483411312390101">odtwórz</translation>
+<translation id="8785498733064193001">rozpocznij odtwarzanie</translation>
+<translation id="7057186640035488495">czas filmu</translation>
+<translation id="8199524924445686405">rrrr</translation>
+<translation id="795667975304826397">Nie wybrano pliku</translation>
+<translation id="7789962463072032349">wstrzymaj</translation>
+<translation id="6853785296079745596">ukryj napisy</translation>
+<translation id="4360991593054037559">Podaj prawidłową wartość. Dwie najbliższe prawidłowe wartości to <ph name="VALID_VALUE_LOW"/> i <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Inny...</translation>
+<translation id="8141602879876242471">Ten indeks można przeszukiwać. Wprowadź wyszukiwane słowa kluczowe:</translation>
+<translation id="1930711995431081526">stan</translation>
+<translation id="658823671542763450">przejdź do pełnego ekranu</translation>
+<translation id="7720026100085573005">pozostały czas</translation>
+<translation id="370665806235115550">Ładowanie...</translation>
+<translation id="2723001399770238859">dźwięk</translation>
+<translation id="6845533974506654842">naciśnij</translation>
+<translation id="8244226242650769279">mapa grafiki</translation>
+<translation id="310520048233152454">Wprowadź adres URL.</translation>
+<translation id="4812940957355064477">Wpisz liczbę.</translation>
+<translation id="2548326553472216322">Brak ostatnich wyszukiwań</translation>
+<translation id="1938124657309484470">Musisz podać wartość <ph name="MAXIMUM_DATE_OR_TIME"/> lub wcześniejszą.</translation>
+<translation id="7263440858009898357">Wybierz element z listy.</translation>
+<translation id="901493112792887934">bieżący czas w sekundach</translation>
+<translation id="5164977714490026579">Wartość nie może być mniejsza niż <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Tydzień <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">przestań pokazywać napisy</translation>
+<translation id="5944544982112848342">2048 (wysoki poziom)</translation>
+<translation id="3075154866155599887">Wpisz prawidłową wartość. Pole jest niekompletne lub zawiera nieprawidłową datę.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">puste</translation>
+<translation id="9050748414552849310">pokaż napisy</translation>
+<translation id="4522570452068850558">Szczegóły</translation>
+<translation id="8451268428117625855">Wybierz plik.</translation>
+<translation id="8117451130807776954">W tym tygodniu</translation>
+<translation id="5966707198760109579">Tydzień</translation>
+<translation id="2901282870647571346">bieżący stan filmu</translation>
+<translation id="2060505056492490888">„<ph name="DOT"/>” występuje w niewłaściwym miejscu w „<ph name="INVALIDDOMAIN"/>”.</translation>
+<translation id="2674318244760992338">stopka</translation>
+<translation id="8987927404178983737">Miesiąc</translation>
+<translation id="8115662671911883373">zacznij pokazywać napisy</translation>
+<translation id="7364796246159120393">Wybierz plik</translation>
+<translation id="2761667185364618470">Zaznacz to pole, jeśli chcesz kontynuować.</translation>
+<translation id="8534579021159131403">Minuty</translation>
+<translation id="819205353528511139">odtwórz film w trybie pełnoekranowym</translation>
+<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="838869780401515933">zaznacz</translation>
+<translation id="2846343701378493991">1024 (średni poziom)</translation>
+<translation id="1637811476055996098">Wybierz pliki</translation>
+<translation id="49969490063480558">Podaj część po znaku „<ph name="ATSIGN"/>”. Adres „<ph name="INVALIDADDRESS"/>” jest niepełny.</translation>
+<translation id="5476505524087279545">odznacz</translation>
+<translation id="2148716181193084225">Dzisiaj</translation>
+<translation id="2507943997699731163">Wypełnij to pole.</translation>
+<translation id="3785482301506746191">pasek czasu odtwarzania filmu</translation>
+<translation id="739024184232394898">Inny...</translation>
+<translation id="383465348367842624">Część przed znakiem „<ph name="ATSIGN"/>” nie może zawierać symbolu „<ph name="INVALIDCHARACTER"/>”.</translation>
+<translation id="5468998798572797635">zamknij pełny ekran</translation>
+<translation id="5919473608089529604">Nie można załadować wtyczki.</translation>
+<translation id="5546461542133609677">wyłącz wyciszenie</translation>
+<translation id="6663448176199120256">Ostatnie wyszukiwania</translation>
+<translation id="1020833440720551630">wycisz ścieżkę dźwiękową</translation>
+<translation id="2597378329261239068">Ten dokument jest chroniony hasłem. Wprowadź hasło.</translation>
+<translation id="5466621249238537318">Wybierz jeden lub kilka plików.</translation>
+<translation id="9132465097189459683">Inny...</translation>
+<translation id="10623998915015855">przycisk przełączania</translation>
+<translation id="8750798805984357768">Wybierz jedną z opcji.</translation>
+<translation id="7740050170769002709">Treść HTML</translation>
+<translation id="6692633176391053278">element kroczący</translation>
+<translation id="4975562563186953947">Wybrano: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">sterowanie multimediami</translation>
+<translation id="2226276347425096477">Skróć ten tekst do maksymalnie <ph name="MAX_CHARACTERS"/> znaków (w tej chwili korzystasz z <ph name="CURRENT_LENGTH"/> znaków).</translation>
+<translation id="6101327004457443354">wyłącz wyciszenie ścieżki dźwiękowej</translation>
+<translation id="1822429046913737220">rano/po południu</translation>
+<translation id="1639239467298939599">Wczytywanie</translation>
+<translation id="2908441821576996758">Podaj listę adresów e-mail rozdzielonych przecinkami.</translation>
+<translation id="5939518447894949180">Resetuj</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Podaj prawidłową wartość. Najbliższa prawidłowa wartość to <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Nieprawidłowa wartość.</translation>
+<translation id="1842960171412779397">wybierz</translation>
+<translation id="7673697353781729403">Godziny</translation>
+<translation id="4664250907885839816">Część po znaku „<ph name="ATSIGN"/>” nie może zawierać symbolu „<ph name="INVALIDCHARACTER"/>”.</translation>
+<translation id="3450233048674729344">Wartość nie może być większa niż <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Inny...</translation>
+<translation id="6270583010843788609">miniatura osi czasu filmu</translation>
+<translation id="5641012560118721995">wstrzymaj odtwarzanie</translation>
+<translation id="1591562245178063882">W tym miesiącu</translation>
+<translation id="6119846243427417423">aktywuj</translation>
+<translation id="8444882422881193423">Liczba plików: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Wyczyść</translation>
+<translation id="7888071071722539607">Uwzględnij znak „<ph name="ATSIGN"/>” w adresie e-mail. W adresie „<ph name="INVALIDADDRESS"/>” brakuje znaku „<ph name="ATSIGN"/>”.</translation>
+<translation id="1088086359088493902">Sekundy</translation>
+<translation id="3934680773876859118">Nie można wczytać dokumentu PDF</translation>
+<translation id="3632707345189162177">pozostały czas filmu w sekundach</translation>
+<translation id="6359256949422175976">miniatura paska czasu odtwarzania filmu</translation>
+<translation id="8597182159515967513">nagłówek</translation>
+<translation id="6843725295806269523">wyciszenie</translation>
+<translation id="2653659639078652383">Prześlij</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
new file mode 100644
index 00000000000..6b9da080762
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-BR">
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="5843503607508392247">Outras...</translation>
+<translation id="248395913932153421">Dia</translation>
+<translation id="1729654308190250600">Insira um endereço de e-mail que não esteja vazio.</translation>
+<translation id="6015796118275082299">Ano</translation>
+<translation id="1235745349614807883">Limpar pesquisas recentes</translation>
+<translation id="7223624360433298498">tempo decorrido</translation>
+<translation id="1171774979989969504">Insira um endereço de e-mail.</translation>
+<translation id="709897737746224366">É preciso que o formato corresponda ao exigido.</translation>
+<translation id="5048533449481078685">marcador de lista</translation>
+<translation id="4202807286478387388">pular</translation>
+<translation id="5307600278924710095">Insira uma parte seguida por &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleto.</translation>
+<translation id="2746543609216772311">O valor deve ser <ph name="MINIMUM_DATE_OR_TIME"/> ou posterior.</translation>
+<translation id="2572483411312390101">reproduzir</translation>
+<translation id="8785498733064193001">iniciar reprodução</translation>
+<translation id="7057186640035488495">tempo de filme</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Nenhum arquivo selecionado</translation>
+<translation id="7789962463072032349">pausar</translation>
+<translation id="6853785296079745596">ocultar legendas ocultas</translation>
+<translation id="4360991593054037559">Insira um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW"/> e <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Outras...</translation>
+<translation id="8141602879876242471">Este é um índice pesquisável. Insira palavras-chave de pesquisa:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">entrar no modo tela cheia</translation>
+<translation id="7720026100085573005">tempo restante</translation>
+<translation id="370665806235115550">Carregando...</translation>
+<translation id="2723001399770238859">áudio</translation>
+<translation id="6845533974506654842">pressione</translation>
+<translation id="8244226242650769279">mapa de imagens</translation>
+<translation id="310520048233152454">Insira um URL.</translation>
+<translation id="4812940957355064477">Insira um número.</translation>
+<translation id="2548326553472216322">Nenhuma pesquisa recente</translation>
+<translation id="1938124657309484470">O valor deve ser <ph name="MAXIMUM_DATE_OR_TIME"/> ou anterior.</translation>
+<translation id="7263440858009898357">Selecione um item da lista.</translation>
+<translation id="901493112792887934">tempo atual em segundos</translation>
+<translation id="5164977714490026579">O valor deve ser maior ou igual a <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">parar de exibir legendas ocultas</translation>
+<translation id="5944544982112848342">2048 (Nível alto)</translation>
+<translation id="3075154866155599887">Insira um valor válido. O campo está incompleto ou tem uma data inválida.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">em branco</translation>
+<translation id="9050748414552849310">mostrar legendas ocultas</translation>
+<translation id="4522570452068850558">Detalhes</translation>
+<translation id="8451268428117625855">Selecione um arquivo.</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="2901282870647571346">status atual do filme</translation>
+<translation id="2060505056492490888">&quot;<ph name="DOT"/>&quot; está sendo usado em uma posição incorreta em &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">rodapé</translation>
+<translation id="8987927404178983737">Mês</translation>
+<translation id="8115662671911883373">começar a exibir legendas ocultas</translation>
+<translation id="7364796246159120393">Escolher arquivo</translation>
+<translation id="2761667185364618470">Marque esta caixa se deseja continuar.</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="819205353528511139">reproduzir filme em tela cheia</translation>
+<translation id="4103419683916926126">Milésimos de segundo</translation>
+<translation id="838869780401515933">marcar</translation>
+<translation id="2846343701378493991">1024 (Nível médio)</translation>
+<translation id="1637811476055996098">Escolher arquivos</translation>
+<translation id="49969490063480558">Insira uma parte depois de &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleto.</translation>
+<translation id="5476505524087279545">desmarcar</translation>
+<translation id="2148716181193084225">Hoje</translation>
+<translation id="2507943997699731163">Preencha este campo.</translation>
+<translation id="3785482301506746191">barra de progressão do filme</translation>
+<translation id="739024184232394898">Outras...</translation>
+<translation id="383465348367842624">Uma parte seguida por &quot;<ph name="ATSIGN"/>&quot; não deve conter o símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">sair do modo tela cheia</translation>
+<translation id="5919473608089529604">Não foi possível carregar o plug-in.</translation>
+<translation id="5546461542133609677">ativar som</translation>
+<translation id="6663448176199120256">Pesquisas recentes</translation>
+<translation id="1020833440720551630">desativar som da faixa de áudio</translation>
+<translation id="2597378329261239068">Este documento está protegido por senha. Digite a senha.</translation>
+<translation id="5466621249238537318">Selecione um ou mais arquivos.</translation>
+<translation id="9132465097189459683">Outras...</translation>
+<translation id="10623998915015855">botão &quot;alternar&quot;</translation>
+<translation id="8750798805984357768">Selecione uma das opções.</translation>
+<translation id="7740050170769002709">Conteúdo HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> selecionados</translation>
+<translation id="8541249477527128034">controle de mídia</translation>
+<translation id="2226276347425096477">Reduza este texto para <ph name="MAX_CHARACTERS"/> caracteres ou menos (você está usando <ph name="CURRENT_LENGTH"/> caracteres).</translation>
+<translation id="6101327004457443354">ativar som da faixa de áudio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Carregando</translation>
+<translation id="2908441821576996758">Insira uma lista de endereços de e-mail separados por vírgula.</translation>
+<translation id="5939518447894949180">Redefinir</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Insira um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="1842960171412779397">selecione</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="4664250907885839816">A parte depois de &quot;<ph name="ATSIGN"/>&quot; não deve conter o símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">O valor deve ser menor ou igual a <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Outro...</translation>
+<translation id="6270583010843788609">miniatura da barra de progressão do filme</translation>
+<translation id="5641012560118721995">pausar reprodução</translation>
+<translation id="1591562245178063882">Este mês</translation>
+<translation id="6119846243427417423">ativar</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> arquivos</translation>
+<translation id="6643016212128521049">Limpar</translation>
+<translation id="7888071071722539607">Inclua um &quot;<ph name="ATSIGN"/>&quot; no endereço de e-mail. &quot;<ph name="INVALIDADDRESS"/>&quot; está com um &quot;<ph name="ATSIGN"/>&quot; faltando.</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="3934680773876859118">Falha ao carregar o documento PDF</translation>
+<translation id="3632707345189162177">segundos restantes do filme</translation>
+<translation id="6359256949422175976">miniatura da barra de progressão do filme</translation>
+<translation id="8597182159515967513">cabeçalho</translation>
+<translation id="6843725295806269523">sem som</translation>
+<translation id="2653659639078652383">Enviar</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
new file mode 100644
index 00000000000..e5d7fac772c
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="pt-PT">
+<translation id="4763480195061959176">vídeo</translation>
+<translation id="5843503607508392247">Outra...</translation>
+<translation id="248395913932153421">Dia</translation>
+<translation id="1729654308190250600">Introduza um endereço de email que não esteja vazio.</translation>
+<translation id="6015796118275082299">Ano</translation>
+<translation id="1235745349614807883">Limpar pesquisas recentes</translation>
+<translation id="7223624360433298498">tempo decorrido</translation>
+<translation id="1171774979989969504">Introduza um endereço de email.</translation>
+<translation id="709897737746224366">Faça corresponder o formato pedido.</translation>
+<translation id="5048533449481078685">marcador de lista</translation>
+<translation id="4202807286478387388">ir para</translation>
+<translation id="5307600278924710095">Introduza uma parte seguida de &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleto.</translation>
+<translation id="2746543609216772311">O valor tem de ser <ph name="MINIMUM_DATE_OR_TIME"/> ou posterior.</translation>
+<translation id="2572483411312390101">reproduzir</translation>
+<translation id="8785498733064193001">iniciar reprodução</translation>
+<translation id="7057186640035488495">tempo do filme</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Nenhum ficheiro selecionado</translation>
+<translation id="7789962463072032349">pausa</translation>
+<translation id="6853785296079745596">esconder legendas ocultas</translation>
+<translation id="4360991593054037559">Introduza um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW"/> e <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Outra...</translation>
+<translation id="8141602879876242471">Este índice é pesquisável. Introduza palavras-chave de pesquisa:</translation>
+<translation id="1930711995431081526">estado</translation>
+<translation id="658823671542763450">entrar no modo de ecrã inteiro</translation>
+<translation id="7720026100085573005">tempo restante</translation>
+<translation id="370665806235115550">A carregar...</translation>
+<translation id="2723001399770238859">áudio</translation>
+<translation id="6845533974506654842">premir</translation>
+<translation id="8244226242650769279">mapa de imagem</translation>
+<translation id="310520048233152454">Introduza um URL.</translation>
+<translation id="4812940957355064477">Introduza um número.</translation>
+<translation id="2548326553472216322">Nenhuma pesquisa recente</translation>
+<translation id="1938124657309484470">O valor tem de ser <ph name="MAXIMUM_DATE_OR_TIME"/> ou anterior.</translation>
+<translation id="7263440858009898357">Seleccione um item na lista.</translation>
+<translation id="901493112792887934">tempo atual em segundos</translation>
+<translation id="5164977714490026579">O valor tem de ser superior ou igual a <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER"/>, de <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">parar de apresentar legendas ocultas</translation>
+<translation id="5944544982112848342">2048 (Tamanho grande)</translation>
+<translation id="3075154866155599887">Introduza um valor válido. O campo está incompleto ou tem uma data inválida.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">em branco</translation>
+<translation id="9050748414552849310">apresentar legendas ocultas</translation>
+<translation id="4522570452068850558">Detalhes</translation>
+<translation id="8451268428117625855">Seleccione um ficheiro.</translation>
+<translation id="8117451130807776954">Esta semana</translation>
+<translation id="5966707198760109579">Semana</translation>
+<translation id="2901282870647571346">estado atual do filme</translation>
+<translation id="2060505056492490888">&quot;<ph name="DOT"/>&quot; está a ser utilizado numa posição errada em &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">rodapé</translation>
+<translation id="8987927404178983737">Mês</translation>
+<translation id="8115662671911883373">apresentar legendas ocultas</translation>
+<translation id="7364796246159120393">Escolher ficheiro</translation>
+<translation id="2761667185364618470">Seleccione esta caixa se pretender continuar.</translation>
+<translation id="8534579021159131403">Minutos</translation>
+<translation id="819205353528511139">reproduzir o filme no modo de ecrã inteiro</translation>
+<translation id="4103419683916926126">Milissegundos</translation>
+<translation id="838869780401515933">verificar</translation>
+<translation id="2846343701378493991">1024 (Tamanho médio)</translation>
+<translation id="1637811476055996098">Escolher Ficheiros</translation>
+<translation id="49969490063480558">Introduza uma parte a seguir a &quot;<ph name="ATSIGN"/>&quot;. &quot;<ph name="INVALIDADDRESS"/>&quot; está incompleto.</translation>
+<translation id="5476505524087279545">desmarcar</translation>
+<translation id="2148716181193084225">Hoje</translation>
+<translation id="2507943997699731163">Preencha este campo.</translation>
+<translation id="3785482301506746191">scrubber do tempo do filme</translation>
+<translation id="739024184232394898">Outra...</translation>
+<translation id="383465348367842624">Uma parte seguida de &quot;<ph name="ATSIGN"/>&quot; não deve conter o símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">sair do modo de ecrã inteiro</translation>
+<translation id="5919473608089529604">Não foi possível carregar o plug-in.</translation>
+<translation id="5546461542133609677">reativar som</translation>
+<translation id="6663448176199120256">Pesquisas recentes</translation>
+<translation id="1020833440720551630">desativar a faixa de áudio</translation>
+<translation id="2597378329261239068">Este documento está protegido por palavra-passe. Introduza uma palavra-passe.</translation>
+<translation id="5466621249238537318">Seleccione um ou mais ficheiros.</translation>
+<translation id="9132465097189459683">Outra...</translation>
+<translation id="10623998915015855">botão alternar</translation>
+<translation id="8750798805984357768">Seleccione uma destas opções.</translation>
+<translation id="7740050170769002709">Conteúdo HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> selecionados</translation>
+<translation id="8541249477527128034">controlo multimédia</translation>
+<translation id="2226276347425096477">Encurte este texto para <ph name="MAX_CHARACTERS"/> caracteres ou menos (está atualmente a utilizar <ph name="CURRENT_LENGTH"/> caracteres).</translation>
+<translation id="6101327004457443354">reativar a faixa de áudio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">A carregar</translation>
+<translation id="2908441821576996758">Introduza uma lista de endereços de email separados por vírgula.</translation>
+<translation id="5939518447894949180">Repor</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Introduza um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valor inválido.</translation>
+<translation id="1842960171412779397">seleccionar</translation>
+<translation id="7673697353781729403">Horas</translation>
+<translation id="4664250907885839816">Uma parte a seguir a &quot;<ph name="ATSIGN"/>&quot; não deve conter o símbolo &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">O valor tem de ser inferior ou igual a <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Outros...</translation>
+<translation id="6270583010843788609">botão da cronologia do filme</translation>
+<translation id="5641012560118721995">interromper a reprodução</translation>
+<translation id="1591562245178063882">Este mês</translation>
+<translation id="6119846243427417423">activar</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ficheiros</translation>
+<translation id="6643016212128521049">Limpar</translation>
+<translation id="7888071071722539607">Inclua um &quot;<ph name="ATSIGN"/>&quot; no endereço de email. Falta um &quot;<ph name="ATSIGN"/>&quot; em &quot;<ph name="INVALIDADDRESS"/>&quot;.</translation>
+<translation id="1088086359088493902">Segundos</translation>
+<translation id="3934680773876859118">Falha ao carregar o documento em PDF</translation>
+<translation id="3632707345189162177">segundos que restam ao filme</translation>
+<translation id="6359256949422175976">botão do scrubber do tempo do filme</translation>
+<translation id="8597182159515967513">cabeçalho</translation>
+<translation id="6843725295806269523">desativar som</translation>
+<translation id="2653659639078652383">Submeter</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ro.xtb b/chromium/content/app/strings/translations/content_strings_ro.xtb
new file mode 100644
index 00000000000..99db9732af4
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ro.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ro">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Altele...</translation>
+<translation id="248395913932153421">Zi</translation>
+<translation id="1729654308190250600">Introduceți o adresă de e-mail concretă.</translation>
+<translation id="6015796118275082299">An</translation>
+<translation id="1235745349614807883">Ștergeți căutările recente</translation>
+<translation id="7223624360433298498">timp scurs</translation>
+<translation id="1171774979989969504">Introduceți o adresă de e-mail.</translation>
+<translation id="709897737746224366">Potriviți cu formatul solicitat.</translation>
+<translation id="5048533449481078685">marcator listă</translation>
+<translation id="4202807286478387388">accesați</translation>
+<translation id="5307600278924710095">Introduceți o valoare urmată de semnul „<ph name="ATSIGN"/>”. Adresa „<ph name="INVALIDADDRESS"/>” nu este completă.</translation>
+<translation id="2746543609216772311">Valoarea pentru dată/oră trebuie să fie <ph name="MINIMUM_DATE_OR_TIME"/> sau una ulterioară.</translation>
+<translation id="2572483411312390101">redați</translation>
+<translation id="8785498733064193001">începeți redarea</translation>
+<translation id="7057186640035488495">durată film</translation>
+<translation id="8199524924445686405">aaaa</translation>
+<translation id="795667975304826397">Nu ați ales niciun fișier</translation>
+<translation id="7789962463072032349">întrerupeți</translation>
+<translation id="6853785296079745596">ascundeți subtitrările</translation>
+<translation id="4360991593054037559">Introduceți o valoare validă. Cele mai apropiate valori valide sunt <ph name="VALID_VALUE_LOW"/> și <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Altele...</translation>
+<translation id="8141602879876242471">Acesta este un index în care se poate căuta. Introduceți cuvintele cheie pentru căutare:</translation>
+<translation id="1930711995431081526">stare</translation>
+<translation id="658823671542763450">deschideți în ecran complet</translation>
+<translation id="7720026100085573005">timp rămas</translation>
+<translation id="370665806235115550">Se încarcă…</translation>
+<translation id="2723001399770238859">audio</translation>
+<translation id="6845533974506654842">apăsați</translation>
+<translation id="8244226242650769279">hartă imagine</translation>
+<translation id="310520048233152454">Introduceți o adresă URL.</translation>
+<translation id="4812940957355064477">Introduceți un număr.</translation>
+<translation id="2548326553472216322">Nicio căutare recentă</translation>
+<translation id="1938124657309484470">Valoarea pentru dată/oră trebuie să fie <ph name="MAXIMUM_DATE_OR_TIME"/> sau una anterioară.</translation>
+<translation id="7263440858009898357">Selectați un articol din listă.</translation>
+<translation id="901493112792887934">timp actual în secunde</translation>
+<translation id="5164977714490026579">Valoarea trebuie să fie mai mare sau egală cu <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Săptămâna <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">nu mai afișați subtitrările</translation>
+<translation id="5944544982112848342">2048 (nivel ridicat)</translation>
+<translation id="3075154866155599887">Introduceți o valoare validă. Câmpul este incomplet sau conține o dată nevalidă.</translation>
+<translation id="3040011195152428237">link</translation>
+<translation id="1014825444426747588">necompletat</translation>
+<translation id="9050748414552849310">afișați subtitrările</translation>
+<translation id="4522570452068850558">Detalii</translation>
+<translation id="8451268428117625855">Selectați un fișier.</translation>
+<translation id="8117451130807776954">Săptămâna aceasta</translation>
+<translation id="5966707198760109579">Săptămână</translation>
+<translation id="2901282870647571346">starea actuală a filmului</translation>
+<translation id="2060505056492490888">Semnul „<ph name="DOT"/>” apare poziționat greșit în „<ph name="INVALIDDOMAIN"/>”.</translation>
+<translation id="2674318244760992338">notă de subsol</translation>
+<translation id="8987927404178983737">Lună</translation>
+<translation id="8115662671911883373">începeți să afișați subtitrările</translation>
+<translation id="7364796246159120393">Alegeți fișierul</translation>
+<translation id="2761667185364618470">Bifați caseta dacă doriți să continuați.</translation>
+<translation id="8534579021159131403">Minute</translation>
+<translation id="819205353528511139">redați filmul în modul ecran complet</translation>
+<translation id="4103419683916926126">Milisecunde</translation>
+<translation id="838869780401515933">bifați</translation>
+<translation id="2846343701378493991">1024 (nivel mediu)</translation>
+<translation id="1637811476055996098">Alegeți fișierele</translation>
+<translation id="49969490063480558">Introduceți o valoare după semnul „<ph name="ATSIGN"/>”. Adresa „<ph name="INVALIDADDRESS"/>” nu este completă.</translation>
+<translation id="5476505524087279545">debifați</translation>
+<translation id="2148716181193084225">Astăzi</translation>
+<translation id="2507943997699731163">Completați acest câmp.</translation>
+<translation id="3785482301506746191">glisor redare film</translation>
+<translation id="739024184232394898">Altele...</translation>
+<translation id="383465348367842624">Valoarea urmată de semnul „<ph name="ATSIGN"/>” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER"/>”.</translation>
+<translation id="5468998798572797635">ieșiți din ecranul complet</translation>
+<translation id="5919473608089529604">Nu s-a putut încărca pluginul.</translation>
+<translation id="5546461542133609677">activați sunetul</translation>
+<translation id="6663448176199120256">Căutări recente</translation>
+<translation id="1020833440720551630">dezactivați sunetul înregistrării audio</translation>
+<translation id="2597378329261239068">Acest document este protejat cu parolă. Introduceți o parolă.</translation>
+<translation id="5466621249238537318">Selectați unul sau mai multe fișiere.</translation>
+<translation id="9132465097189459683">Altele...</translation>
+<translation id="10623998915015855">buton de comutare</translation>
+<translation id="8750798805984357768">Selectați una dintre aceste opțiuni.</translation>
+<translation id="7740050170769002709">Conținut HTML</translation>
+<translation id="6692633176391053278">control numeric cu incrementare/decrementare</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> selectate</translation>
+<translation id="8541249477527128034">comandă media</translation>
+<translation id="2226276347425096477">Micșorați acest text la cel mult <ph name="MAX_CHARACTERS"/> (de) caractere (în prezent utilizați <ph name="CURRENT_LENGTH"/> (de) caractere).</translation>
+<translation id="6101327004457443354">activați sunetul înregistrării audio</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Se încarcă</translation>
+<translation id="2908441821576996758">Introduceți o listă de adrese de e-mail separate prin virgulă.</translation>
+<translation id="5939518447894949180">Resetați</translation>
+<translation id="1921819250265091946">zz</translation>
+<translation id="2613802280814924224">Introduceți o valoare validă. Cea mai apropiată valoare validă este <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Valoare nevalidă.</translation>
+<translation id="1842960171412779397">selectați</translation>
+<translation id="7673697353781729403">Ore</translation>
+<translation id="4664250907885839816">Valoarea care urmează după semnul „<ph name="ATSIGN"/>” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER"/>”.</translation>
+<translation id="3450233048674729344">Valoarea trebuie să fie mai mică sau egală cu <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Altele...</translation>
+<translation id="6270583010843788609">miniatură cronologie film</translation>
+<translation id="5641012560118721995">întrerupeți redarea</translation>
+<translation id="1591562245178063882">Luna aceasta</translation>
+<translation id="6119846243427417423">activați</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> (de) fișiere</translation>
+<translation id="6643016212128521049">Ștergeți</translation>
+<translation id="7888071071722539607">Includeți semnul „<ph name="ATSIGN"/>” în adresa de e-mail. Din adresa „<ph name="INVALIDADDRESS"/>” lipsește semnul „<ph name="ATSIGN"/>”.</translation>
+<translation id="1088086359088493902">Secunde</translation>
+<translation id="3934680773876859118">Documentul PDF nu a fost încărcat</translation>
+<translation id="3632707345189162177">numărul secundelor rămase din film</translation>
+<translation id="6359256949422175976">miniatură glisor redare film</translation>
+<translation id="8597182159515967513">antet</translation>
+<translation id="6843725295806269523">dezactivați sunetul</translation>
+<translation id="2653659639078652383">Trimiteți</translation>
+<translation id="3732799496749320381">ll</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ru.xtb b/chromium/content/app/strings/translations/content_strings_ru.xtb
new file mode 100644
index 00000000000..d16bed1fc24
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ru.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ru">
+<translation id="4763480195061959176">видео</translation>
+<translation id="5843503607508392247">Другое…</translation>
+<translation id="248395913932153421">День</translation>
+<translation id="1729654308190250600">Введите адрес электронной почты.</translation>
+<translation id="6015796118275082299">Год</translation>
+<translation id="1235745349614807883">Очистить недавние поиски</translation>
+<translation id="7223624360433298498">прошедшее время</translation>
+<translation id="1171774979989969504">Введите адрес электронной почты.</translation>
+<translation id="709897737746224366">Введите данные в указанном формате.</translation>
+<translation id="5048533449481078685">маркер списка</translation>
+<translation id="4202807286478387388">перейти</translation>
+<translation id="5307600278924710095">Введите часть адреса до символа &quot;<ph name="ATSIGN"/>&quot;. Адрес &quot;<ph name="INVALIDADDRESS"/>&quot; неполный.</translation>
+<translation id="2746543609216772311">Минимальное значение должно быть <ph name="MINIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="2572483411312390101">воспроизведение</translation>
+<translation id="8785498733064193001">начать воспроизведение</translation>
+<translation id="7057186640035488495">продолжительность ролика</translation>
+<translation id="8199524924445686405">гггг</translation>
+<translation id="795667975304826397">Файл не выбран</translation>
+<translation id="7789962463072032349">Пауза</translation>
+<translation id="6853785296079745596">скрыть субтитры</translation>
+<translation id="4360991593054037559">Введите допустимое значение. Ближайшие допустимые значения: <ph name="VALID_VALUE_LOW"/> и <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Другое…</translation>
+<translation id="8141602879876242471">Это индекс с возможностью поиска. Введите ключевые слова для поиска:</translation>
+<translation id="1930711995431081526">статус</translation>
+<translation id="658823671542763450">полноэкранный режим</translation>
+<translation id="7720026100085573005">оставшееся время</translation>
+<translation id="370665806235115550">Загрузка...</translation>
+<translation id="2723001399770238859">аудио</translation>
+<translation id="6845533974506654842">нажать</translation>
+<translation id="8244226242650769279">графическая карта</translation>
+<translation id="310520048233152454">Введите URL.</translation>
+<translation id="4812940957355064477">Введите число.</translation>
+<translation id="2548326553472216322">Нет недавних поисков</translation>
+<translation id="1938124657309484470">Максимальное значение должно быть <ph name="MAXIMUM_DATE_OR_TIME"/>.</translation>
+<translation id="7263440858009898357">Выберите один из пунктов списка.</translation>
+<translation id="901493112792887934">текущее время в секундах</translation>
+<translation id="5164977714490026579">Значение должно быть больше или равно <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Неделя <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">скрыть субтитры</translation>
+<translation id="5944544982112848342">2048 (Крупный размер)</translation>
+<translation id="3075154866155599887">Введите верное значение. Поле не заполнено или введена недействительная дата.</translation>
+<translation id="3040011195152428237">ссылка</translation>
+<translation id="1014825444426747588">нет данных</translation>
+<translation id="9050748414552849310">показать субтитры</translation>
+<translation id="4522570452068850558">Подробнее</translation>
+<translation id="8451268428117625855">Выберите файл.</translation>
+<translation id="8117451130807776954">На этой неделе</translation>
+<translation id="5966707198760109579">Неделя</translation>
+<translation id="2901282870647571346">текущий статус ролика</translation>
+<translation id="2060505056492490888">Недопустимое положение символа &quot;<ph name="DOT"/>&quot; в адресе &quot;<ph name="INVALIDDOMAIN"/>&quot;.</translation>
+<translation id="2674318244760992338">нижний колонтитул</translation>
+<translation id="8987927404178983737">Месяц</translation>
+<translation id="8115662671911883373">показать субтитры</translation>
+<translation id="7364796246159120393">Выберите файл</translation>
+<translation id="2761667185364618470">Чтобы продолжить, установите этот флажок.</translation>
+<translation id="8534579021159131403">Минуты</translation>
+<translation id="819205353528511139">воспроизведение в полноэкранном режиме</translation>
+<translation id="4103419683916926126">Миллисекунды</translation>
+<translation id="838869780401515933">поставить галочку</translation>
+<translation id="2846343701378493991">1024 (Средний размер)</translation>
+<translation id="1637811476055996098">Выбрать файлы</translation>
+<translation id="49969490063480558">Введите часть адреса после символа &quot;<ph name="ATSIGN"/>&quot;. Адрес &quot;<ph name="INVALIDADDRESS"/>&quot; неполный.</translation>
+<translation id="5476505524087279545">снять галочку</translation>
+<translation id="2148716181193084225">Сегодня</translation>
+<translation id="2507943997699731163">Заполните это поле.</translation>
+<translation id="3785482301506746191">полоса прокрутки</translation>
+<translation id="739024184232394898">Другое…</translation>
+<translation id="383465348367842624">Часть адреса до символа &quot;<ph name="ATSIGN"/>&quot; не должна содержать символ &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">выход из полноэкранного режима</translation>
+<translation id="5919473608089529604">Не удалось загрузить плагин.</translation>
+<translation id="5546461542133609677">включение звука</translation>
+<translation id="6663448176199120256">Недавние поиски</translation>
+<translation id="1020833440720551630">отключение звуковой дорожки</translation>
+<translation id="2597378329261239068">Документ защищен паролем. Введите пароль.</translation>
+<translation id="5466621249238537318">Выберите один или несколько файлов.</translation>
+<translation id="9132465097189459683">Другое…</translation>
+<translation id="10623998915015855">кнопка-переключатель</translation>
+<translation id="8750798805984357768">Выберите один из вариантов.</translation>
+<translation id="7740050170769002709">HTML-содержание</translation>
+<translation id="6692633176391053278">счетчик</translation>
+<translation id="4975562563186953947">Выбрано: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">управление мультимедиа</translation>
+<translation id="2226276347425096477">Длина текста не должна превышать <ph name="MAX_CHARACTERS"/> симв. (сейчас <ph name="CURRENT_LENGTH"/> симв.).</translation>
+<translation id="6101327004457443354">включение звуковой дорожки</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Загрузка</translation>
+<translation id="2908441821576996758">Введите адреса электронной почты через запятую.</translation>
+<translation id="5939518447894949180">Сбросить</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="2613802280814924224">Введите допустимое значение. Ближайшее допустимое значение: <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Недопустимые данные.</translation>
+<translation id="1842960171412779397">выбрать</translation>
+<translation id="7673697353781729403">Часы</translation>
+<translation id="4664250907885839816">Часть адреса после символа &quot;<ph name="ATSIGN"/>&quot; не должна содержать символ &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Значение должно быть меньше или равно <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Другой...</translation>
+<translation id="6270583010843788609">бегунок временной шкалы</translation>
+<translation id="5641012560118721995">пауза</translation>
+<translation id="1591562245178063882">В этом месяце</translation>
+<translation id="6119846243427417423">активировать</translation>
+<translation id="8444882422881193423">Число файлов: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Очистить</translation>
+<translation id="7888071071722539607">Адрес электронной почты должен содержать символ &quot;<ph name="ATSIGN"/>&quot;. В адресе &quot;<ph name="INVALIDADDRESS"/>&quot; отсутствует символ &quot;<ph name="ATSIGN"/>&quot;.</translation>
+<translation id="1088086359088493902">Секунды</translation>
+<translation id="3934680773876859118">Не удалось загрузить документ PDF</translation>
+<translation id="3632707345189162177">оставшееся время в секундах</translation>
+<translation id="6359256949422175976">бегунок полосы прокрутки</translation>
+<translation id="8597182159515967513">заголовок</translation>
+<translation id="6843725295806269523">отключить звук</translation>
+<translation id="2653659639078652383">Отправить</translation>
+<translation id="3732799496749320381">мм</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sk.xtb b/chromium/content/app/strings/translations/content_strings_sk.xtb
new file mode 100644
index 00000000000..96f7e3ac9e4
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_sk.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sk">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Iné...</translation>
+<translation id="248395913932153421">Deň</translation>
+<translation id="1729654308190250600">Zadajte e-mailovú adresu, ktorá nie je prázdna hodnota.</translation>
+<translation id="6015796118275082299">Rok</translation>
+<translation id="1235745349614807883">Vyčistiť posledné vyhľadávania</translation>
+<translation id="7223624360433298498">uplynutý čas</translation>
+<translation id="1171774979989969504">Zadajte e-mailovú adresu.</translation>
+<translation id="709897737746224366">Zadajte hodnotu zodpovedajúcu požadovanému formátu.</translation>
+<translation id="5048533449481078685">ukazovateľ v zozname</translation>
+<translation id="4202807286478387388">skok</translation>
+<translation id="5307600278924710095">Zadajte časť pred znakom <ph name="ATSIGN"/>. Adresa <ph name="INVALIDADDRESS"/> je neúplná.</translation>
+<translation id="2746543609216772311">Hodnota musí byť <ph name="MINIMUM_DATE_OR_TIME"/> alebo neskôr.</translation>
+<translation id="2572483411312390101">prehrať</translation>
+<translation id="8785498733064193001">začať prehrávanie</translation>
+<translation id="7057186640035488495">čas filmu</translation>
+<translation id="8199524924445686405">rrrr</translation>
+<translation id="795667975304826397">Nie je vybratý žiadny súbor</translation>
+<translation id="7789962463072032349">pozastaviť</translation>
+<translation id="6853785296079745596">skryť skryté titulky</translation>
+<translation id="4360991593054037559">Zadajte platnú hodnotu. Najbližšie platné hodnoty sú <ph name="VALID_VALUE_LOW"/> a <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Iné...</translation>
+<translation id="8141602879876242471">Tento index sa dá prehľadávať. Zadajte kľúčové slová na vyhľadanie:</translation>
+<translation id="1930711995431081526">stav</translation>
+<translation id="658823671542763450">prejsť do režimu celej obrazovky</translation>
+<translation id="7720026100085573005">zostávajúci čas</translation>
+<translation id="370665806235115550">Načítava sa...</translation>
+<translation id="2723001399770238859">zvuk</translation>
+<translation id="6845533974506654842">stlačiť</translation>
+<translation id="8244226242650769279">mapa obrázka</translation>
+<translation id="310520048233152454">Zadajte webovú adresu.</translation>
+<translation id="4812940957355064477">Zadajte číslo.</translation>
+<translation id="2548326553472216322">Žiadne posledné vyhľadávania</translation>
+<translation id="1938124657309484470">Hodnota musí byť <ph name="MAXIMUM_DATE_OR_TIME"/> alebo skôr.</translation>
+<translation id="7263440858009898357">Vyberte položku zo zoznamu.</translation>
+<translation id="901493112792887934">aktuálny čas v sekundách</translation>
+<translation id="5164977714490026579">Hodnota musí byť väčšia alebo rovná hodnote <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. týždeň, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ukončiť zobrazovanie skrytých titulkov</translation>
+<translation id="5944544982112848342">2048 (vysoký stupeň)</translation>
+<translation id="3075154866155599887">Zadajte platnú hodnotu. Pole obsahuje neúplnú hodnotu alebo neplatný dátum.</translation>
+<translation id="3040011195152428237">odkaz</translation>
+<translation id="1014825444426747588">prázdne</translation>
+<translation id="9050748414552849310">zobraziť skryté titulky</translation>
+<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="8451268428117625855">Vyberte súbor.</translation>
+<translation id="8117451130807776954">Tento týždeň</translation>
+<translation id="5966707198760109579">Týždeň</translation>
+<translation id="2901282870647571346">aktuálny stav filmu</translation>
+<translation id="2060505056492490888">Znak <ph name="DOT"/> je v doméne <ph name="INVALIDDOMAIN"/> použitý na nesprávnej pozícii.</translation>
+<translation id="2674318244760992338">päta</translation>
+<translation id="8987927404178983737">Mesiac</translation>
+<translation id="8115662671911883373">zobrazovať skryté titulky</translation>
+<translation id="7364796246159120393">Vybrať súbor</translation>
+<translation id="2761667185364618470">Ak chcete pokračovať, začiarknite toto políčko.</translation>
+<translation id="8534579021159131403">Minúty</translation>
+<translation id="819205353528511139">prehrať film v režime celej obrazovky</translation>
+<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="838869780401515933">označiť</translation>
+<translation id="2846343701378493991">1024 (stredný stupeň)</translation>
+<translation id="1637811476055996098">Vybrať súbory</translation>
+<translation id="49969490063480558">Zadajte časť za znakom <ph name="ATSIGN"/>. Adresa <ph name="INVALIDADDRESS"/> je neúplná.</translation>
+<translation id="5476505524087279545">zrušiť označenie</translation>
+<translation id="2148716181193084225">Dnes</translation>
+<translation id="2507943997699731163">Vyplňte toto pole.</translation>
+<translation id="3785482301506746191">posúvač času filmu</translation>
+<translation id="739024184232394898">Iné...</translation>
+<translation id="383465348367842624">Časť pred znakom <ph name="ATSIGN"/> by nemala obsahovať symbol <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="5468998798572797635">ukončiť režim celej obrazovky</translation>
+<translation id="5919473608089529604">Doplnok sa nepodarilo načítať.</translation>
+<translation id="5546461542133609677">obnoviť zvuk</translation>
+<translation id="6663448176199120256">Posledné vyhľadávania</translation>
+<translation id="1020833440720551630">stlmiť zvukovú stopu</translation>
+<translation id="2597378329261239068">Tento dokument je chránený heslom. Zadajte heslo.</translation>
+<translation id="5466621249238537318">Vyberte jeden alebo viac súborov.</translation>
+<translation id="9132465097189459683">Iné...</translation>
+<translation id="10623998915015855">tlačidlo prepínania</translation>
+<translation id="8750798805984357768">Vyberte jednu z týchto možností.</translation>
+<translation id="7740050170769002709">Obsah HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Počet vybraných položiek: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">ovládanie médií</translation>
+<translation id="2226276347425096477">Tento text musíte skrátiť na <ph name="MAX_CHARACTERS"/> znakov alebo menej (súčasný počet znakov: <ph name="CURRENT_LENGTH"/>).</translation>
+<translation id="6101327004457443354">obnoviť zvukovú stopu</translation>
+<translation id="1822429046913737220">dop. / odp.</translation>
+<translation id="1639239467298939599">Prebieha načítavanie</translation>
+<translation id="2908441821576996758">Zadajte zoznam e-mailových adries oddelených čiarkou.</translation>
+<translation id="5939518447894949180">Obnoviť</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Zadajte platnú hodnotu. Najbližšia platná hodnota je <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Neplatná hodnota.</translation>
+<translation id="1842960171412779397">vybrať</translation>
+<translation id="7673697353781729403">Hodiny</translation>
+<translation id="4664250907885839816">Časť za znakom <ph name="ATSIGN"/> by nemala obsahovať symbol <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="3450233048674729344">Hodnota musí byť menšia alebo rovná hodnote <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Iný...</translation>
+<translation id="6270583010843788609">časová os filmu</translation>
+<translation id="5641012560118721995">pozastaviť prehrávanie</translation>
+<translation id="1591562245178063882">Tento mesiac</translation>
+<translation id="6119846243427417423">aktivovať</translation>
+<translation id="8444882422881193423">Počet súborov: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Vymazať</translation>
+<translation id="7888071071722539607">Uveďte v e-mailovej adrese znak <ph name="ATSIGN"/>. V adrese <ph name="INVALIDADDRESS"/> znak <ph name="ATSIGN"/> chýba.</translation>
+<translation id="1088086359088493902">Sekundy</translation>
+<translation id="3934680773876859118">Načítanie dokumentu PDF zlyhalo</translation>
+<translation id="3632707345189162177">zostávajúci čas do konca filmu v sekundách</translation>
+<translation id="6359256949422175976">posúvač času filmu</translation>
+<translation id="8597182159515967513">nadpis</translation>
+<translation id="6843725295806269523">stlmiť</translation>
+<translation id="2653659639078652383">Odoslať</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sl.xtb b/chromium/content/app/strings/translations/content_strings_sl.xtb
new file mode 100644
index 00000000000..2fc88e755d3
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_sl.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sl">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Drugo ...</translation>
+<translation id="248395913932153421">Dan</translation>
+<translation id="1729654308190250600">Vnesite e-poštni naslov (polje ne sme biti prazno).</translation>
+<translation id="6015796118275082299">Leto</translation>
+<translation id="1235745349614807883">Počisti zadnja iskanja</translation>
+<translation id="7223624360433298498">pretečeni čas</translation>
+<translation id="1171774979989969504">Vnesite e-poštni naslov</translation>
+<translation id="709897737746224366">Poskrbite za ujemanje z zahtevano obliko.</translation>
+<translation id="5048533449481078685">označevalnik seznama</translation>
+<translation id="4202807286478387388">skoči</translation>
+<translation id="5307600278924710095">Vnesite nekaj in nato <ph name="ATSIGN"/>. Naslov »<ph name="INVALIDADDRESS"/>« je nepopoln.</translation>
+<translation id="2746543609216772311">Vrednost mora biti <ph name="MINIMUM_DATE_OR_TIME"/> ali pozneje.</translation>
+<translation id="2572483411312390101">predvajanje</translation>
+<translation id="8785498733064193001">začetek predvajanja</translation>
+<translation id="7057186640035488495">čas filma</translation>
+<translation id="8199524924445686405">llll</translation>
+<translation id="795667975304826397">Nobena datoteka ni izbrana</translation>
+<translation id="7789962463072032349">premor</translation>
+<translation id="6853785296079745596">skrivanje podnapisov</translation>
+<translation id="4360991593054037559">Vnesite veljavno vrednost. Najbližji veljavni vrednosti sta <ph name="VALID_VALUE_LOW"/> in <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Drugo ...</translation>
+<translation id="8141602879876242471">To je kazalo, ki omogoča iskanje. Vnesite ključne besede za iskanje:</translation>
+<translation id="1930711995431081526">stanje</translation>
+<translation id="658823671542763450">prehod v celozaslonski način</translation>
+<translation id="7720026100085573005">preostali čas</translation>
+<translation id="370665806235115550">Nalagam ...</translation>
+<translation id="2723001399770238859">zvok</translation>
+<translation id="6845533974506654842">pritisni</translation>
+<translation id="8244226242650769279">slikovni zemljevid</translation>
+<translation id="310520048233152454">Vnesite URL.</translation>
+<translation id="4812940957355064477">Vnesite številko.</translation>
+<translation id="2548326553472216322">Ni zadnjih iskanj</translation>
+<translation id="1938124657309484470">Vrednost mora biti <ph name="MAXIMUM_DATE_OR_TIME"/> ali prej.</translation>
+<translation id="7263440858009898357">Izberite element s seznama.</translation>
+<translation id="901493112792887934">trenutni čas v sekundah</translation>
+<translation id="5164977714490026579">Vrednost mora biti večja od <ph name="MINIMUM"/> ali enaka.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. teden, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ustavitev prikazovanja podnapisov</translation>
+<translation id="5944544982112848342">2048 (visoka stopnja)</translation>
+<translation id="3075154866155599887">Vnesite veljavno vrednost. Vnos v polje je nepopoln ali vsebuje neveljaven datum.</translation>
+<translation id="3040011195152428237">povezava</translation>
+<translation id="1014825444426747588">prazno</translation>
+<translation id="9050748414552849310">prikaz podnapisov</translation>
+<translation id="4522570452068850558">Podrobnosti</translation>
+<translation id="8451268428117625855">Izberite datoteko.</translation>
+<translation id="8117451130807776954">Ta teden</translation>
+<translation id="5966707198760109579">Teden</translation>
+<translation id="2901282870647571346">trenutno stanje filma</translation>
+<translation id="2060505056492490888">»<ph name="DOT"/>« je na napačnem mestu v »<ph name="INVALIDDOMAIN"/>«.</translation>
+<translation id="2674318244760992338">noga</translation>
+<translation id="8987927404178983737">Mesec</translation>
+<translation id="8115662671911883373">začetek predvajanja podnapisov</translation>
+<translation id="7364796246159120393">Izberi datoteko</translation>
+<translation id="2761667185364618470">Potrdite to polje, če želite nadaljevati.</translation>
+<translation id="8534579021159131403">Minute</translation>
+<translation id="819205353528511139">predvajanje filma v celozaslonskem načinu</translation>
+<translation id="4103419683916926126">Milisekunde</translation>
+<translation id="838869780401515933">potrdi</translation>
+<translation id="2846343701378493991">1024 (srednja stopnja)</translation>
+<translation id="1637811476055996098">Izberi datoteke</translation>
+<translation id="49969490063480558">Vnesite nekaj po znaku »<ph name="ATSIGN"/>«. Naslov »<ph name="INVALIDADDRESS"/>« je nepopoln.</translation>
+<translation id="5476505524087279545">počisti izbor</translation>
+<translation id="2148716181193084225">Danes</translation>
+<translation id="2507943997699731163">Izpolnite to polje</translation>
+<translation id="3785482301506746191">časovni krmilnik za predvajanje filma</translation>
+<translation id="739024184232394898">Drugo ...</translation>
+<translation id="383465348367842624">Del pred »<ph name="ATSIGN"/>« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER"/>«.</translation>
+<translation id="5468998798572797635">izhod iz celozaslonskega načina</translation>
+<translation id="5919473608089529604">Vtičnika ni bilo mogoče naložiti.</translation>
+<translation id="5546461542133609677">vklop zvoka</translation>
+<translation id="6663448176199120256">Zadnja iskanja</translation>
+<translation id="1020833440720551630">izklop zvoka za zvočni posnetek</translation>
+<translation id="2597378329261239068">Dokument je zaščiten z geslom. Vnesite geslo.</translation>
+<translation id="5466621249238537318">Izberite eno ali več datotek.</translation>
+<translation id="9132465097189459683">Drugo ...</translation>
+<translation id="10623998915015855">preklopni gumb</translation>
+<translation id="8750798805984357768">Izberite eno od teh možnosti.</translation>
+<translation id="7740050170769002709">Vsebina HTML</translation>
+<translation id="6692633176391053278">kontrolnik</translation>
+<translation id="4975562563186953947">Št. izbranih: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">nadziranje predstavnosti</translation>
+<translation id="2226276347425096477">Skrajšajte to besedilo na <ph name="MAX_CHARACTERS"/> znakov ali manj (trenutno uporabljate <ph name="CURRENT_LENGTH"/> znakov).</translation>
+<translation id="6101327004457443354">vklop zvoka za zvočni posnetek</translation>
+<translation id="1822429046913737220">Dopoldne/popoldne</translation>
+<translation id="1639239467298939599">Nalaganje</translation>
+<translation id="2908441821576996758">Vnesite seznam e-poštnih naslovov, ločenih z vejicami</translation>
+<translation id="5939518447894949180">Ponastavi</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Vnesite veljavno vrednost. Najbližja veljavna vrednost je <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Neveljavna vrednost.</translation>
+<translation id="1842960171412779397">izberi</translation>
+<translation id="7673697353781729403">Ure</translation>
+<translation id="4664250907885839816">Del po »<ph name="ATSIGN"/>« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER"/>«.</translation>
+<translation id="3450233048674729344">Vrednost mora biti manjša od <ph name="MAXIMUM"/> ali enaka.</translation>
+<translation id="668171684555832681">Drugo ...</translation>
+<translation id="6270583010843788609">sličica časovne premice filma</translation>
+<translation id="5641012560118721995">začasna ustavitev predvajanja</translation>
+<translation id="1591562245178063882">Ta mesec</translation>
+<translation id="6119846243427417423">aktiviraj</translation>
+<translation id="8444882422881193423">Število datotek: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Počisti</translation>
+<translation id="7888071071722539607">V e-poštnem naslovu mora biti znak »<ph name="ATSIGN"/>«. V naslovu »<ph name="INVALIDADDRESS"/>« manjka »<ph name="ATSIGN"/>«.</translation>
+<translation id="1088086359088493902">Sekunde</translation>
+<translation id="3934680773876859118">Dokumenta PDF ni bilo mogoče naložiti</translation>
+<translation id="3632707345189162177">preostale sekunde filma</translation>
+<translation id="6359256949422175976">sličica časovnega krmilnika za predvajanje filma</translation>
+<translation id="8597182159515967513">naslov</translation>
+<translation id="6843725295806269523">nemo</translation>
+<translation id="2653659639078652383">Pošlji</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sr.xtb b/chromium/content/app/strings/translations/content_strings_sr.xtb
new file mode 100644
index 00000000000..0938474b026
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_sr.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sr">
+<translation id="4763480195061959176">видео</translation>
+<translation id="5843503607508392247">Друго...</translation>
+<translation id="248395913932153421">Дан</translation>
+<translation id="1729654308190250600">Унесите имејл адресу која није празна.</translation>
+<translation id="6015796118275082299">Година</translation>
+<translation id="1235745349614807883">Обриши недавне претраге</translation>
+<translation id="7223624360433298498">протекло време</translation>
+<translation id="1171774979989969504">Унесите имејл адресу.</translation>
+<translation id="709897737746224366">Изаберите захтевани формат.</translation>
+<translation id="5048533449481078685">означивач листе</translation>
+<translation id="4202807286478387388">прескочи</translation>
+<translation id="5307600278924710095">Унесите неки део пре „<ph name="ATSIGN"/>“. Адреса „<ph name="INVALIDADDRESS"/>“ је непотпуна.</translation>
+<translation id="2746543609216772311">Вредност мора да буде <ph name="MINIMUM_DATE_OR_TIME"/> или новија.</translation>
+<translation id="2572483411312390101">пустите</translation>
+<translation id="8785498733064193001">започните репродукцију</translation>
+<translation id="7057186640035488495">трајање филма</translation>
+<translation id="8199524924445686405">гггг</translation>
+<translation id="795667975304826397">Није одабрано</translation>
+<translation id="7789962463072032349">паузирај</translation>
+<translation id="6853785296079745596">сакријте опционални титл</translation>
+<translation id="4360991593054037559">Унесите важећу вредност. Две најближе важеће вредности су <ph name="VALID_VALUE_LOW"/> и <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Друго...</translation>
+<translation id="8141602879876242471">Ово је индекс који може да се претражује. Унесите кључне речи за претрагу:</translation>
+<translation id="1930711995431081526">статус</translation>
+<translation id="658823671542763450">пређите на режим целог екрана</translation>
+<translation id="7720026100085573005">преостало време</translation>
+<translation id="370665806235115550">Учитавање...</translation>
+<translation id="2723001399770238859">аудио</translation>
+<translation id="6845533974506654842">притисни</translation>
+<translation id="8244226242650769279">мапа слике</translation>
+<translation id="310520048233152454">Унесите URL адресу.</translation>
+<translation id="4812940957355064477">Унесите број.</translation>
+<translation id="2548326553472216322">Нема недавних претрага</translation>
+<translation id="1938124657309484470">Вредност мора да буде <ph name="MAXIMUM_DATE_OR_TIME"/> или старија.</translation>
+<translation id="7263440858009898357">Изаберите ставку са листе.</translation>
+<translation id="901493112792887934">актуелно време у секундама</translation>
+<translation id="5164977714490026579">Вредност сме да буде најмање <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. недеља, <ph name="YEAR"/>.</translation>
+<translation id="7740016676195725605">зауставите приказивање опционалног титла</translation>
+<translation id="5944544982112848342">2048 (високи степен)</translation>
+<translation id="3075154866155599887">Унесите важећу вредност. Поље није попуњено или садржи неважећи датум.</translation>
+<translation id="3040011195152428237">веза</translation>
+<translation id="1014825444426747588">празно</translation>
+<translation id="9050748414552849310">приказивање опционалног титла</translation>
+<translation id="4522570452068850558">Детаљи</translation>
+<translation id="8451268428117625855">Изаберите датотеку.</translation>
+<translation id="8117451130807776954">Ова недеља</translation>
+<translation id="5966707198760109579">Недеља</translation>
+<translation id="2901282870647571346">актуелни статус филма</translation>
+<translation id="2060505056492490888">„<ph name="DOT"/>“ је стављено на погрешно место у „<ph name="INVALIDDOMAIN"/>“.</translation>
+<translation id="2674318244760992338">подножје</translation>
+<translation id="8987927404178983737">Месец</translation>
+<translation id="8115662671911883373">започните приказивање опционалног титла</translation>
+<translation id="7364796246159120393">Одабери датотеку</translation>
+<translation id="2761667185364618470">Потврдите избор у овом пољу за потврду уколико желите да наставите.</translation>
+<translation id="8534579021159131403">Минути</translation>
+<translation id="819205353528511139">пустите филм у режиму целог екрана</translation>
+<translation id="4103419683916926126">Милисекунде</translation>
+<translation id="838869780401515933">изабери</translation>
+<translation id="2846343701378493991">1024 (средњи степен)</translation>
+<translation id="1637811476055996098">Избор датотека</translation>
+<translation id="49969490063480558">Унесите неки део после „<ph name="ATSIGN"/>“. Адреса „<ph name="INVALIDADDRESS"/>“ је непотпуна.</translation>
+<translation id="5476505524087279545">опозови избор</translation>
+<translation id="2148716181193084225">Данас</translation>
+<translation id="2507943997699731163">Попуните ово поље.</translation>
+<translation id="3785482301506746191">клизач за трајање филма</translation>
+<translation id="739024184232394898">Друго...</translation>
+<translation id="383465348367842624">Део пре „<ph name="ATSIGN"/>“ не треба да садржи симбол „<ph name="INVALIDCHARACTER"/>“.</translation>
+<translation id="5468998798572797635">изађите из режима целог екрана</translation>
+<translation id="5919473608089529604">Није могуће учитати додатну компоненту.</translation>
+<translation id="5546461542133609677">укључите звук</translation>
+<translation id="6663448176199120256">Недавне претраге</translation>
+<translation id="1020833440720551630">искључите звук аудио снимка</translation>
+<translation id="2597378329261239068">Овај документ је заштићен лозинком. Унесите лозинку.</translation>
+<translation id="5466621249238537318">Изаберите једну или више датотека.</translation>
+<translation id="9132465097189459683">Друго...</translation>
+<translation id="10623998915015855">дугме за укључивање/искључивање</translation>
+<translation id="8750798805984357768">Изаберите неку од ових опција.</translation>
+<translation id="7740050170769002709">HTML садржај</translation>
+<translation id="6692633176391053278">контрола за промене у корацима</translation>
+<translation id="4975562563186953947">Изабрано: <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">контрола за медије</translation>
+<translation id="2226276347425096477">Скратите овај текст на <ph name="MAX_CHARACTERS"/> знак(ов)а или мање (тренутно користите <ph name="CURRENT_LENGTH"/> знак(ов)а).</translation>
+<translation id="6101327004457443354">укључите звук аудио снимка</translation>
+<translation id="1822429046913737220">пре подне/по подне</translation>
+<translation id="1639239467298939599">Учитавање</translation>
+<translation id="2908441821576996758">Унесите листу имејл адреса раздвојених зарезима.</translation>
+<translation id="5939518447894949180">Ресетуј</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="2613802280814924224">Унесите важећу вредност. Најближа важећа вредност је <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Неважећа вредност.</translation>
+<translation id="1842960171412779397">изабери</translation>
+<translation id="7673697353781729403">Сати</translation>
+<translation id="4664250907885839816">Део после „<ph name="ATSIGN"/>“ не треба да садржи симбол „<ph name="INVALIDCHARACTER"/>“.</translation>
+<translation id="3450233048674729344">Вредност сме да буде највише <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Друго...</translation>
+<translation id="6270583010843788609">клизач на временској траци филма</translation>
+<translation id="5641012560118721995">паузирајте репродукцију</translation>
+<translation id="1591562245178063882">Овај месец</translation>
+<translation id="6119846243427417423">активирај</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> датотеке(а)</translation>
+<translation id="6643016212128521049">Обриши</translation>
+<translation id="7888071071722539607">Уврстите „<ph name="ATSIGN"/>“ у имејл адресу. У адреси е-поште „<ph name="INVALIDADDRESS"/>“ недостаје „<ph name="ATSIGN"/>“.</translation>
+<translation id="1088086359088493902">Секунде</translation>
+<translation id="3934680773876859118">Учитавање PDF документа није успело</translation>
+<translation id="3632707345189162177">број преосталих секунди филма</translation>
+<translation id="6359256949422175976">клизач за трајање филма</translation>
+<translation id="8597182159515967513">наслов</translation>
+<translation id="6843725295806269523">искључи звук</translation>
+<translation id="2653659639078652383">Пошаљи</translation>
+<translation id="3732799496749320381">мм</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sv.xtb b/chromium/content/app/strings/translations/content_strings_sv.xtb
new file mode 100644
index 00000000000..1b2461a5a93
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_sv.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sv">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Annat ...</translation>
+<translation id="248395913932153421">Dag</translation>
+<translation id="1729654308190250600">Ange en e-postadress som inte är tom.</translation>
+<translation id="6015796118275082299">År</translation>
+<translation id="1235745349614807883">Rensa senaste sökningar</translation>
+<translation id="7223624360433298498">förfluten tid</translation>
+<translation id="1171774979989969504">Ange en e-postadress.</translation>
+<translation id="709897737746224366">Matcha det format som anges.</translation>
+<translation id="5048533449481078685">listmarkör</translation>
+<translation id="4202807286478387388">fortsätta</translation>
+<translation id="5307600278924710095">Ange en del följt av <ph name="ATSIGN"/>. <ph name="INVALIDADDRESS"/> är ofullständig.</translation>
+<translation id="2746543609216772311">Värdet måste vara <ph name="MINIMUM_DATE_OR_TIME"/> eller senare.</translation>
+<translation id="2572483411312390101">spela upp</translation>
+<translation id="8785498733064193001">starta uppspelning</translation>
+<translation id="7057186640035488495">filmtid</translation>
+<translation id="8199524924445686405">åååå</translation>
+<translation id="795667975304826397">Ingen fil har valts</translation>
+<translation id="7789962463072032349">paus</translation>
+<translation id="6853785296079745596">dölj textning</translation>
+<translation id="4360991593054037559">Ange ett giltigt värde. De två närmaste giltiga värdena är <ph name="VALID_VALUE_LOW"/> och <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Annat ...</translation>
+<translation id="8141602879876242471">Det här är ett sökbart index. Skriv sökord:</translation>
+<translation id="1930711995431081526">status</translation>
+<translation id="658823671542763450">visa i helskärm</translation>
+<translation id="7720026100085573005">återstående tid</translation>
+<translation id="370665806235115550">Laddar...</translation>
+<translation id="2723001399770238859">ljud</translation>
+<translation id="6845533974506654842">tryck</translation>
+<translation id="8244226242650769279">bildkarta</translation>
+<translation id="310520048233152454">Ange en webbadress.</translation>
+<translation id="4812940957355064477">Ange ett nummer.</translation>
+<translation id="2548326553472216322">Inga nya sökningar</translation>
+<translation id="1938124657309484470">Värdet måste vara <ph name="MAXIMUM_DATE_OR_TIME"/> eller tidigare.</translation>
+<translation id="7263440858009898357">Välj ett alternativ i listan.</translation>
+<translation id="901493112792887934">aktuell tid i sekunder</translation>
+<translation id="5164977714490026579">Värdet måste vara större än eller lika med <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Vecka <ph name="WEEKNUMBER"/> <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">sluta visa textning</translation>
+<translation id="5944544982112848342">2048 (hög)</translation>
+<translation id="3075154866155599887">Ange ett giltigt värde. Fältet är ofullständigt eller innehåller ett ogiltigt datum.</translation>
+<translation id="3040011195152428237">länk</translation>
+<translation id="1014825444426747588">tomt</translation>
+<translation id="9050748414552849310">visa textning</translation>
+<translation id="4522570452068850558">Info</translation>
+<translation id="8451268428117625855">Välj en fil.</translation>
+<translation id="8117451130807776954">Den här veckan</translation>
+<translation id="5966707198760109579">Vecka</translation>
+<translation id="2901282870647571346">aktuell filmstatus</translation>
+<translation id="2060505056492490888"><ph name="DOT"/> används på fel plats i <ph name="INVALIDDOMAIN"/>.</translation>
+<translation id="2674318244760992338">sidfot</translation>
+<translation id="8987927404178983737">Månad</translation>
+<translation id="8115662671911883373">börja visa textning</translation>
+<translation id="7364796246159120393">Välj fil</translation>
+<translation id="2761667185364618470">Markera den här kryssrutan om du vill fortsätta.</translation>
+<translation id="8534579021159131403">Minuter</translation>
+<translation id="819205353528511139">spela upp filmen i helskärmsläge</translation>
+<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="838869780401515933">kryssa för</translation>
+<translation id="2846343701378493991">1024 (medel)</translation>
+<translation id="1637811476055996098">Välj filer</translation>
+<translation id="49969490063480558">Ange en del följt av <ph name="ATSIGN"/>. <ph name="INVALIDADDRESS"/> är ofullständig.</translation>
+<translation id="5476505524087279545">kryssa av</translation>
+<translation id="2148716181193084225">Idag</translation>
+<translation id="2507943997699731163">Fyll i det här fältet.</translation>
+<translation id="3785482301506746191">filmtidsreglage</translation>
+<translation id="739024184232394898">Annat ...</translation>
+<translation id="383465348367842624">En del följt av <ph name="ATSIGN"/> får inte innehålla symbolen <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="5468998798572797635">avsluta helskärmsläge</translation>
+<translation id="5919473608089529604">Det gick inte att läsa in plugin-programmet.</translation>
+<translation id="5546461542133609677">visa</translation>
+<translation id="6663448176199120256">Senaste sökningar</translation>
+<translation id="1020833440720551630">stäng av ljudspår</translation>
+<translation id="2597378329261239068">Dokumentet är lösenordsskyddat. Ange ett lösenord.</translation>
+<translation id="5466621249238537318">Välj en eller flera filer.</translation>
+<translation id="9132465097189459683">Annat ...</translation>
+<translation id="10623998915015855">växlingsknapp</translation>
+<translation id="8750798805984357768">Välj ett av följande alternativ.</translation>
+<translation id="7740050170769002709">HTML-innehåll</translation>
+<translation id="6692633176391053278">knappreglage</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> valda</translation>
+<translation id="8541249477527128034">mediekontroll</translation>
+<translation id="2226276347425096477">Förkorta texten till <ph name="MAX_CHARACTERS"/> tecken eller mindre (nu är texten <ph name="CURRENT_LENGTH"/> tecken).</translation>
+<translation id="6101327004457443354">spela upp ljudspåret</translation>
+<translation id="1822429046913737220">FM/EM</translation>
+<translation id="1639239467298939599">Läser in</translation>
+<translation id="2908441821576996758">Ange en kommaavgränsad lista med e-postadresser.</translation>
+<translation id="5939518447894949180">Återställ</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Ange ett giltigt värde. Det närmast giltiga värdet är <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Ogiltigt värde.</translation>
+<translation id="1842960171412779397">välj</translation>
+<translation id="7673697353781729403">Timmar</translation>
+<translation id="4664250907885839816">En del efter <ph name="ATSIGN"/> får inte innehålla symbolen <ph name="INVALIDCHARACTER"/>.</translation>
+<translation id="3450233048674729344">Värdet måste vara mindre än eller lika med <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Annan...</translation>
+<translation id="6270583010843788609">miniatyr för filmtidslinje</translation>
+<translation id="5641012560118721995">pausa uppspelning</translation>
+<translation id="1591562245178063882">Den här månaden</translation>
+<translation id="6119846243427417423">aktivera</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> filer</translation>
+<translation id="6643016212128521049">Rensa</translation>
+<translation id="7888071071722539607">Inkludera ett <ph name="ATSIGN"/> i e-postadressen. <ph name="INVALIDADDRESS"/> saknar ett <ph name="ATSIGN"/>.</translation>
+<translation id="1088086359088493902">Sekunder</translation>
+<translation id="3934680773876859118">Det gick inte att läsa in PDF-dokumentet</translation>
+<translation id="3632707345189162177">antal sekunder kvar av filmen</translation>
+<translation id="6359256949422175976">miniatyr för filmtidsreglage</translation>
+<translation id="8597182159515967513">rubrik</translation>
+<translation id="6843725295806269523">ljud av</translation>
+<translation id="2653659639078652383">Skicka</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sw.xtb b/chromium/content/app/strings/translations/content_strings_sw.xtb
new file mode 100644
index 00000000000..4e3c640a374
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_sw.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="sw">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Nyingine...</translation>
+<translation id="248395913932153421">Siku</translation>
+<translation id="1729654308190250600">Tafadhali jaza sehemu ya anwani ya barua pepe.</translation>
+<translation id="6015796118275082299">Mwaka</translation>
+<translation id="1235745349614807883">Futa Utafutaji wa Hivi Karibuni</translation>
+<translation id="7223624360433298498">muda uliokwisha</translation>
+<translation id="1171774979989969504">Tafadhali weka anwani ya barua pepe.</translation>
+<translation id="709897737746224366">Tafadhali linganisha umbizo lililoombwa.</translation>
+<translation id="5048533449481078685">kialamishi orodha</translation>
+<translation id="4202807286478387388">ruka</translation>
+<translation id="5307600278924710095">Tafadhali ingiza sehemu ikifuatiwa na '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' haijakamilika.</translation>
+<translation id="2746543609216772311">Thamani lazima iwe <ph name="MINIMUM_DATE_OR_TIME"/> au baadaye.</translation>
+<translation id="2572483411312390101">cheza</translation>
+<translation id="8785498733064193001">anza kucheza</translation>
+<translation id="7057186640035488495">muda wa filamu</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">Hakuna faili iliyochaguliwa</translation>
+<translation id="7789962463072032349">Sitisha</translation>
+<translation id="6853785296079745596">ficha manukuu yanayoweza kuonyeshwa</translation>
+<translation id="4360991593054037559">Tafadhali ingiza thamani halali. Thamani mbili halali za karibu ni <ph name="VALID_VALUE_LOW"/> na <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Nyingine...</translation>
+<translation id="8141602879876242471">Hii ni fahirisi inayoweza kutafutwa. Weka maneno muhimu ya utafutaji.</translation>
+<translation id="1930711995431081526">hali</translation>
+<translation id="658823671542763450">ingia skrini kamili</translation>
+<translation id="7720026100085573005">muda unaosalia</translation>
+<translation id="370665806235115550">Inapakia...</translation>
+<translation id="2723001399770238859">sauti</translation>
+<translation id="6845533974506654842">bofya</translation>
+<translation id="8244226242650769279">ramani ya picha</translation>
+<translation id="310520048233152454">Tafadhali ingiza URL.</translation>
+<translation id="4812940957355064477">Tafadhali ingiza nambari.</translation>
+<translation id="2548326553472216322">Hakuna utafutaji wa hivi karibuni</translation>
+<translation id="1938124657309484470">Thamani lazima iwe <ph name="MAXIMUM_DATE_OR_TIME"/> au mapema.</translation>
+<translation id="7263440858009898357">Tafadhali chagua kipengee katika orodha.</translation>
+<translation id="901493112792887934">muda wa sasa kwa sekunde</translation>
+<translation id="5164977714490026579">Lazima thamani iwe kubwa kuliko au sawa na <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Wiki <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">koma kuonyesha manukuu yanaweza kufichwa</translation>
+<translation id="5944544982112848342">2048 (Gredi ya Juu)</translation>
+<translation id="3075154866155599887">Tafadhali ingiza thamani halali. Uga umekamilika au una tarehe batili.</translation>
+<translation id="3040011195152428237">kiungo</translation>
+<translation id="1014825444426747588">tupu</translation>
+<translation id="9050748414552849310">onyesha manakuu yaliyofichwa</translation>
+<translation id="4522570452068850558">Maelezo</translation>
+<translation id="8451268428117625855">Tafadhali chagua faili.</translation>
+<translation id="8117451130807776954">Wiki hii</translation>
+<translation id="5966707198760109579">Juma</translation>
+<translation id="2901282870647571346">hali ya sasa ya filamu</translation>
+<translation id="2060505056492490888">' <ph name="DOT"/> 'imetumika kwenye nafasi isiyostahili katika '<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">kijachini</translation>
+<translation id="8987927404178983737">Mwezi</translation>
+<translation id="8115662671911883373">anza kuonyesha manukuu yaliyofungwa</translation>
+<translation id="7364796246159120393">Chagua Faili</translation>
+<translation id="2761667185364618470">Tafadhali angalia kikasha hiki iwapo unataka kuendelea.</translation>
+<translation id="8534579021159131403">Dakika</translation>
+<translation id="819205353528511139">cheza filamu katika hali ya skrini kamili</translation>
+<translation id="4103419683916926126">nukta</translation>
+<translation id="838869780401515933">chunguza</translation>
+<translation id="2846343701378493991">1024 (Gredi Wastani)</translation>
+<translation id="1637811476055996098">Chagua Faili</translation>
+<translation id="49969490063480558">Tafadhali ingiza sehemu inayofuatia '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' haijakamilika.</translation>
+<translation id="5476505524087279545">toa tiki</translation>
+<translation id="2148716181193084225">Leo</translation>
+<translation id="2507943997699731163">Tafadhali jaza sehemu hii.</translation>
+<translation id="3785482301506746191">kitelezi cha muda cha filamu</translation>
+<translation id="739024184232394898">Nyingine...</translation>
+<translation id="383465348367842624">Sehemu inayofuatwa na '<ph name="ATSIGN"/>' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="5468998798572797635">Ondoka kwenye Skrini nzima</translation>
+<translation id="5919473608089529604">Isingeweza kupakia programu jalizi.</translation>
+<translation id="5546461542133609677">rejesha sauti</translation>
+<translation id="6663448176199120256">Utafutaji wa hivi karibuni</translation>
+<translation id="1020833440720551630">nyamazisha sauti ya wimbo</translation>
+<translation id="2597378329261239068">Hati hii imelindwa kwa nenosiri. Tafadhali ingiza nenosiri.</translation>
+<translation id="5466621249238537318">Tafadhali chagua faili moja au zaidi.</translation>
+<translation id="9132465097189459683">Nyingine...</translation>
+<translation id="10623998915015855">kitufe cha kugeuza</translation>
+<translation id="8750798805984357768">Tafadhali chagua moja wapo ya chaguo hizi.</translation>
+<translation id="7740050170769002709">Maudhui ya HTML</translation>
+<translation id="6692633176391053278">stepper</translation>
+<translation id="4975562563186953947">Vipengee <ph name="SELECTED_COUNT"/> vimechaguliwa</translation>
+<translation id="8541249477527128034">udhibiti wa vyombo vya habari</translation>
+<translation id="2226276347425096477">Tafadhali fupisha maandishi haya hadi vibambo <ph name="MAX_CHARACTERS"/> au chini (kwa sasa unatumia vibambo <ph name="CURRENT_LENGTH"/> ).</translation>
+<translation id="6101327004457443354">rejesha sauti ya wimbo</translation>
+<translation id="1822429046913737220">AM / PM</translation>
+<translation id="1639239467298939599">Inapakia</translation>
+<translation id="2908441821576996758">Tafadhali weka orodha ya anwani za barua pepe zilizotenganishwa kwa vikomo.</translation>
+<translation id="5939518447894949180">Weka upya</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Tafadhali ingiza thamani halali.Thamani halali ya karibu ni <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Thamani batili.</translation>
+<translation id="1842960171412779397">chagua</translation>
+<translation id="7673697353781729403">Saa</translation>
+<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN"/>' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="3450233048674729344">Lazima thamani iwe chache kuliko au sawa na <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Mengine...</translation>
+<translation id="6270583010843788609">kijipicha cha muda wa filamu</translation>
+<translation id="5641012560118721995">sitisha kucheza</translation>
+<translation id="1591562245178063882">Mwezi huu</translation>
+<translation id="6119846243427417423">wezesha</translation>
+<translation id="8444882422881193423">faili <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Futa</translation>
+<translation id="7888071071722539607">Tafadhali jumuisha '<ph name="ATSIGN"/>' katika anwani ya barua pepe. '<ph name="INVALIDADDRESS"/>' inakosa '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">Sekunde</translation>
+<translation id="3934680773876859118">Imeshindwa kupakia hati ya PDF</translation>
+<translation id="3632707345189162177">idadi ya sekunde zinazosalia za filamu</translation>
+<translation id="6359256949422175976">kijipicha cha kitelezi cha muda wa filamu</translation>
+<translation id="8597182159515967513">kichwa</translation>
+<translation id="6843725295806269523">nyamazisha</translation>
+<translation id="2653659639078652383">Wasilisha</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ta.xtb b/chromium/content/app/strings/translations/content_strings_ta.xtb
new file mode 100644
index 00000000000..ed7e5dbba54
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_ta.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="ta">
+<translation id="4763480195061959176">வீடியோ</translation>
+<translation id="5843503607508392247">மற்றவை…</translation>
+<translation id="248395913932153421">நாள்</translation>
+<translation id="1729654308190250600">காலி அல்லாத மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
+<translation id="6015796118275082299">ஆண்டு</translation>
+<translation id="1235745349614807883">சமீபத்திய தேடல்களை சுத்தமாக்கு</translation>
+<translation id="7223624360433298498">முடிவடைந்த நேரம்</translation>
+<translation id="1171774979989969504">ஒரு மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
+<translation id="709897737746224366">கோரிய வடிவமைப்பில் தருக.</translation>
+<translation id="5048533449481078685">பட்டியல் குறிப்பான்</translation>
+<translation id="4202807286478387388">தாவு</translation>
+<translation id="5307600278924710095">'<ph name="ATSIGN"/>' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS"/>' முழுமைப் பெறாமல் உள்ளது.</translation>
+<translation id="2746543609216772311">மதிப்பானது <ph name="MINIMUM_DATE_OR_TIME"/> அல்லது அதற்குப் பின்பு இருக்க வேண்டும்.</translation>
+<translation id="2572483411312390101">இயக்கு</translation>
+<translation id="8785498733064193001">மறுஇயக்கத்தைத் தொடங்கு</translation>
+<translation id="7057186640035488495">மூவி நேரம்</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">எந்த கோப்பும் தேர்ந்தெடுக்கப்படவில்லை</translation>
+<translation id="7789962463072032349">இடைநிறுத்து</translation>
+<translation id="6853785296079745596">மூடப்பட்ட தலைப்புகளை மறை</translation>
+<translation id="4360991593054037559">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE_LOW"/> மற்றும் <ph name="VALID_VALUE_HIGHER"/> ஆகியவை மிக நெருக்கமான சரியான இரண்டு மதிப்புகளாகும்.</translation>
+<translation id="1758486001363313524">மற்றவை…</translation>
+<translation id="8141602879876242471">இது தேடக்கூடிய பொருளடக்கம். தேடல் சொற்களை உள்ளிடுக:</translation>
+<translation id="1930711995431081526">நிலை</translation>
+<translation id="658823671542763450">முழுத்திரைக்குச் செல்</translation>
+<translation id="7720026100085573005">மீதமுள்ள நேரம்</translation>
+<translation id="370665806235115550">நினைவேறுகிறது...</translation>
+<translation id="2723001399770238859">ஆடியோ</translation>
+<translation id="6845533974506654842">அழுத்துக</translation>
+<translation id="8244226242650769279">பட மேப்</translation>
+<translation id="310520048233152454">URL ஐ உள்ளிடுக.</translation>
+<translation id="4812940957355064477">எண்ணை உள்ளிடுக.</translation>
+<translation id="2548326553472216322">சமீபத்திய தேடல்கள் எதுவுமில்லை</translation>
+<translation id="1938124657309484470">மதிப்பு <ph name="MAXIMUM_DATE_OR_TIME"/> அல்லது அதற்கு முன்பு இருக்க வேண்டும்.</translation>
+<translation id="7263440858009898357">பட்டியலிலிருந்து ஒரு உருப்படியைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="901493112792887934">நடப்பு நேரம் வினாடிகளில்</translation>
+<translation id="5164977714490026579">மதிப்பானது, கண்டிப்பாக <ph name="MINIMUM"/> ஐ விட அதிகமாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
+<translation id="2247351761944213033">வாரம் <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">மூடப்பட்ட தலைப்புகளைக் காட்டுவதை நிறுத்து</translation>
+<translation id="5944544982112848342">2048 (உயர் தரம்)</translation>
+<translation id="3075154866155599887">சரியான மதிப்பை உள்ளிடவும். இந்தப் புலம் முழுமையற்றதாக உள்ளது அல்லது தவறான தேதியைக் கொண்டுள்ளது.</translation>
+<translation id="3040011195152428237">இணைப்பு</translation>
+<translation id="1014825444426747588">வெற்று</translation>
+<translation id="9050748414552849310">மூடப்பட்ட தலைப்புகளைக் காட்டு</translation>
+<translation id="4522570452068850558">விவரங்கள்</translation>
+<translation id="8451268428117625855">ஒரு கோப்பை தேர்ந்தெடுக்கவும்.</translation>
+<translation id="8117451130807776954">இந்த வாரம்</translation>
+<translation id="5966707198760109579">வாரம்</translation>
+<translation id="2901282870647571346">மூவியின் நடப்பு நிலை</translation>
+<translation id="2060505056492490888"><ph name="INVALIDDOMAIN"/> இல் தவறான இடத்தில் '<ph name="DOT"/>' பயன்படுத்தபட்டுள்ளது.</translation>
+<translation id="2674318244760992338">அடிக்குறிப்பு</translation>
+<translation id="8987927404178983737">மாதம்</translation>
+<translation id="8115662671911883373">மூடப்பட்ட தலைப்புகளைக் காட்டுவதைத் தொடங்கு</translation>
+<translation id="7364796246159120393">கோப்பைத் தேர்வு செய்க</translation>
+<translation id="2761667185364618470">தொடர விரும்பினால், இந்தப் பெட்டியைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="8534579021159131403">நிமிடங்கள்</translation>
+<translation id="819205353528511139">மூவியை முழுத்திரைப் பயன்முறையில் இயக்கு</translation>
+<translation id="4103419683916926126">மில்லிவினாடிகள்</translation>
+<translation id="838869780401515933">சரிபார்</translation>
+<translation id="2846343701378493991">1024 (இடைநிலைத் தரம்)</translation>
+<translation id="1637811476055996098">கோப்புகளைத் தேர்வுசெய்க</translation>
+<translation id="49969490063480558">'<ph name="ATSIGN"/>' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS"/>' முழுமைப்பெறாமல் உள்ளது.</translation>
+<translation id="5476505524087279545">தேர்வு நீக்கு</translation>
+<translation id="2148716181193084225">இன்று</translation>
+<translation id="2507943997699731163">இந்தப் புலத்தை நிரப்புக.</translation>
+<translation id="3785482301506746191">மூவி நேர ஸ்க்ரப்பர்</translation>
+<translation id="739024184232394898">மற்றவை…</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>' ஐத் தொடர்ந்து வரும் பகுதியில் '<ph name="INVALIDCHARACTER"/>' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="5468998798572797635">முழுத்திரையிலிருந்து வெளியேறு</translation>
+<translation id="5919473608089529604">செருகுநிரல் ஏற்றப்படவில்லை.</translation>
+<translation id="5546461542133609677">ஒலி இயக்கு</translation>
+<translation id="6663448176199120256">சமீபத்திய தேடல்கள்</translation>
+<translation id="1020833440720551630">ஆடியோ டிராக்கை முடக்கு</translation>
+<translation id="2597378329261239068">இந்த ஆவணம் கடவுச்சொல் பாதுகாக்கப்பட்ட ஒன்று. தயவுசெய்து ஒரு கடவுச்சொல்லை உள்ளிடுக.</translation>
+<translation id="5466621249238537318">ஒன்று அல்லது அதற்குமேற்பட்ட கோப்புகளைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="9132465097189459683">மற்றவை…</translation>
+<translation id="10623998915015855">நிலைமாற்றுதல் பொத்தான்</translation>
+<translation id="8750798805984357768">தயவுசெய்து இந்த விருப்பங்களில் ஒன்றைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="7740050170769002709">HTML உள்ளடக்கம்</translation>
+<translation id="6692633176391053278">ஸ்டெப்பர்</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> தேர்ந்தெடுக்கப்பட்டன</translation>
+<translation id="8541249477527128034">மீடியா கட்டுப்பாடு</translation>
+<translation id="2226276347425096477">இந்த உரையை <ph name="MAX_CHARACTERS"/> எழுத்துக்குறிகள் அல்லது அதற்கும் குறைவாக சுருக்கிடுங்கள் (நீங்கள் தற்போது <ph name="CURRENT_LENGTH"/> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்).</translation>
+<translation id="6101327004457443354">ஆடியோ டிராக்கை இயக்கு</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">ஏற்றுகிறது</translation>
+<translation id="2908441821576996758">காற்புள்ளியால் பிரிக்கப்பட்ட மின்னஞ்சல் முகவரிகளின் பட்டியலை உள்ளிடுக.</translation>
+<translation id="5939518447894949180">மீட்டமை</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE"/> என்பது நெருக்கமாக உள்ள சரியான மதிப்பாகும்.</translation>
+<translation id="835897206747267392">செல்லாத மதிப்பு.</translation>
+<translation id="1842960171412779397">தேர்ந்தெடு</translation>
+<translation id="7673697353781729403">மணிநேரம்</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER"/>' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="3450233048674729344">மதிப்பானது கண்டிப்பாக <ph name="MAXIMUM"/> ஐ விடக்குறைவாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
+<translation id="668171684555832681">மற்றவை…</translation>
+<translation id="6270583010843788609">மூவி டைம்லைன் சிறுபடம்</translation>
+<translation id="5641012560118721995">மறுஇயக்கத்தை இடைநிறுத்து</translation>
+<translation id="1591562245178063882">இந்த மாதம்</translation>
+<translation id="6119846243427417423">செயல்படுத்து</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> கோப்புகள்</translation>
+<translation id="6643016212128521049">அழி</translation>
+<translation id="7888071071722539607">மின்னஞ்சல் முகவரியில் '<ph name="ATSIGN"/>' ஐச் சேர்க்கவும். '<ph name="ATSIGN"/>' இல் '<ph name="INVALIDADDRESS"/>' இல்லை.</translation>
+<translation id="1088086359088493902">வினாடிகள்</translation>
+<translation id="3934680773876859118">PDF ஆவணத்தை ஏற்றுவது தோல்வியடைந்தது</translation>
+<translation id="3632707345189162177">மீதமுள்ள மூவியின் வினாடிகள்</translation>
+<translation id="6359256949422175976">மூவி நேர ஸ்க்ரப்பர் சிறுபடம்</translation>
+<translation id="8597182159515967513">தலைப்பு</translation>
+<translation id="6843725295806269523">ஒலியடக்கு</translation>
+<translation id="2653659639078652383">சமர்ப்பி</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_te.xtb b/chromium/content/app/strings/translations/content_strings_te.xtb
new file mode 100644
index 00000000000..fe9a8bf3e9e
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_te.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="te">
+<translation id="4763480195061959176">వీడియో</translation>
+<translation id="5843503607508392247">ఇతర...</translation>
+<translation id="248395913932153421">రోజు</translation>
+<translation id="1729654308190250600">దయచేసి ఖాళీ-కాని ఇమెయిల్ చిరునామాని నమోదు చేయండి.</translation>
+<translation id="6015796118275082299">సంవత్సరం</translation>
+<translation id="1235745349614807883">ఇటీవల శోధనలను క్లియర్ చెయ్యి</translation>
+<translation id="7223624360433298498">గడిచిన సమయం</translation>
+<translation id="1171774979989969504">దయచేసి ఇమెయిల్ చిరునామాను ఎంటర్ చెయ్యండి.</translation>
+<translation id="709897737746224366">దయచేసి అభ్యర్థించిన ఆకృతీకరణను సరిపోల్చండి.</translation>
+<translation id="5048533449481078685">జాబితా మార్కర్</translation>
+<translation id="4202807286478387388">వెళ్ళు</translation>
+<translation id="5307600278924710095">దయచేసి '<ph name="ATSIGN"/>'కి ముందు ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS"/>' అసంపూర్ణంగా ఉంది.</translation>
+<translation id="2746543609216772311">విలువ తప్పనిసరిగా <ph name="MINIMUM_DATE_OR_TIME"/> లేదా అంతకంటే తదుపరిది అయి ఉండాలి.</translation>
+<translation id="2572483411312390101">ప్లే చేయి</translation>
+<translation id="8785498733064193001">ప్లేబ్యాక్‌ను ప్రారంభించు</translation>
+<translation id="7057186640035488495">చలనచిత్ర నిడివి</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">ఫైల్ ఏదీ ఎంచుకోలేదు</translation>
+<translation id="7789962463072032349">నిలిపివేయి</translation>
+<translation id="6853785296079745596">సంవృత శీర్షికలను దాచు</translation>
+<translation id="4360991593054037559">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE_LOW"/> మరియు <ph name="VALID_VALUE_HIGHER"/> అనేవి రెండు సమీప చెల్లుబాటు విలువలు.</translation>
+<translation id="1758486001363313524">ఇతర...</translation>
+<translation id="8141602879876242471">ఇది ఒక శోధించగల సూచిక. శోధన కీవర్డ్‌లను ఎంటర్ చెయ్యండి:</translation>
+<translation id="1930711995431081526">స్థితి</translation>
+<translation id="658823671542763450">పూర్తి స్క్రీన్‌లోకి ప్రవేశించు</translation>
+<translation id="7720026100085573005">మిగిలి ఉన్న సమయం</translation>
+<translation id="370665806235115550">లోడ్ అవుతోంది...</translation>
+<translation id="2723001399770238859">ఆడియో</translation>
+<translation id="6845533974506654842">నొక్కండి</translation>
+<translation id="8244226242650769279">చిత్రం మ్యాప్‌</translation>
+<translation id="310520048233152454">దయచేసి ఒక URLని ఎంటర్ చెయ్యండి.</translation>
+<translation id="4812940957355064477">దయచేసి సంఖ్యను నమోదు చేయండి.</translation>
+<translation id="2548326553472216322">ఇటీవల శోధనలు లేవు</translation>
+<translation id="1938124657309484470">విలువ తప్పనిసరిగా <ph name="MAXIMUM_DATE_OR_TIME"/> లేదా అంతకంటే మునుపటిది అయి ఉండాలి.</translation>
+<translation id="7263440858009898357">దయచేసి జాబితాలోని ఒక అంశాన్ని ఎంచుకోండి.</translation>
+<translation id="901493112792887934">సెకన్లలో ప్రస్తుత సమయం</translation>
+<translation id="5164977714490026579">విలువ ఖచ్చితంగా <ph name="MINIMUM"/> కంటే ఎక్కువగా లేదా సమానంగా ఉండాలి.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>వ వారం, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">సంవృత శీర్షికలను ప్రదర్శించడం ఆపివేయి</translation>
+<translation id="5944544982112848342">2048 (ఉత్తమ గ్రేడ్)</translation>
+<translation id="3075154866155599887">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. ఫీల్డ్ అసంపూర్ణంగా ఉంది లేదా చెల్లని తేదీని కలిగి ఉంది.</translation>
+<translation id="3040011195152428237">లింక్</translation>
+<translation id="1014825444426747588">ఖాళీ</translation>
+<translation id="9050748414552849310">సంవృత శీర్షికలను చూపు</translation>
+<translation id="4522570452068850558">వివరాలు</translation>
+<translation id="8451268428117625855">దయచేసి ఒక ఫైల్‌ని ఎంచుకోండి.</translation>
+<translation id="8117451130807776954">ఈ వారం</translation>
+<translation id="5966707198760109579">వారం</translation>
+<translation id="2901282870647571346">ప్రస్తుతం చలనచిత్ర స్థితి</translation>
+<translation id="2060505056492490888">'<ph name="INVALIDDOMAIN"/>'లో '<ph name="DOT"/>' తప్పు స్థానంలో ఉపయోగించబడింది.</translation>
+<translation id="2674318244760992338">ఫుటర్</translation>
+<translation id="8987927404178983737">నెల</translation>
+<translation id="8115662671911883373">సంవృత శీర్షికలను ప్రదర్శించడం ప్రారంభించు</translation>
+<translation id="7364796246159120393">ఫైల్‌ను ఎంచుకోండి</translation>
+<translation id="2761667185364618470">దయచేసి మీరు కొనసాగాలనుకుంటే ఈ బాక్స్‌కి టిక్కు పెట్టండి.</translation>
+<translation id="8534579021159131403">నిమిషాలు</translation>
+<translation id="819205353528511139">చలనచిత్రాన్ని పూర్తి స్క్రీన్ మోడ్‌లో ప్లే చేయి</translation>
+<translation id="4103419683916926126">మిల్లీసెకన్లు</translation>
+<translation id="838869780401515933">తనిఖీ చెయ్యి</translation>
+<translation id="2846343701378493991">1024 (మధ్యస్థ గ్రేడ్)</translation>
+<translation id="1637811476055996098">ఫైల్‌లను ఎంచుకోండి</translation>
+<translation id="49969490063480558">దయచేసి '<ph name="ATSIGN"/>'కి తర్వాత ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS"/>' అసంపూర్ణంగా ఉంది.</translation>
+<translation id="5476505524087279545">ఎంపిక చెయ్యబడలేదు</translation>
+<translation id="2148716181193084225">ఈ రోజు</translation>
+<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ని పూర్తి చెయ్యండి.</translation>
+<translation id="3785482301506746191">చలనచిత్ర సమయ స్క్రబ్బర్</translation>
+<translation id="739024184232394898">ఇతర...</translation>
+<translation id="383465348367842624">'<ph name="ATSIGN"/>'కి ముందు ఉన్న భాగంలో '<ph name="INVALIDCHARACTER"/>' చిహ్నం ఉండకూడదు.</translation>
+<translation id="5468998798572797635">పూర్తి స్క్రీన్ నుండి నిష్క్రమించు</translation>
+<translation id="5919473608089529604">ప్లగిన్‌ని లోడ్ చేయడం సాధ్యం కాలేదు.</translation>
+<translation id="5546461542133609677">అన్‌మ్యూట్ చేయి</translation>
+<translation id="6663448176199120256">ఇటీవల శోధనలు</translation>
+<translation id="1020833440720551630">ఆడియో ట్రాక్‌ను మ్యూట్ చేయి</translation>
+<translation id="2597378329261239068">ఈ పత్రం అనుమతి పదంచే రక్షించబడింది. దయచేసి అనుమతి పదాన్ని నమోదు చేయండి.</translation>
+<translation id="5466621249238537318">దయచేసి ఒకటి లేదా మరిన్ని ఫైళ్ళను ఎంచుకోండి.</translation>
+<translation id="9132465097189459683">ఇతర...</translation>
+<translation id="10623998915015855">టోగుల్ బటన్</translation>
+<translation id="8750798805984357768">దయచేసి ఈ ఎంపికలలో ఒకదాన్ని ఎంచుకోండి.</translation>
+<translation id="7740050170769002709">HTML కంటెంట్</translation>
+<translation id="6692633176391053278">స్టెప్పర్</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> ఎంచుకోబడ్డాయి</translation>
+<translation id="8541249477527128034">మీడియా నియంత్రణ</translation>
+<translation id="2226276347425096477">దయచేసి ఈ వచనాన్ని <ph name="MAX_CHARACTERS"/> అక్షరాలకు లేదా అంతకంటే తక్కువ (మీరు ప్రస్తుతం <ph name="CURRENT_LENGTH"/> అక్షరాలను ఉపయోగిస్తున్నారు)కు తగ్గించండి.</translation>
+<translation id="6101327004457443354">ఆడియో ట్రాక్‌ను అన్‌మ్యూట్ చేయి</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">లోడ్ అవుతోంది</translation>
+<translation id="2908441821576996758">దయచేసి కామాతో వేరు చేసిన ఇమెయిల్ చిరునామాల జాబితాను ఎంటర్ చెయ్యండి.</translation>
+<translation id="5939518447894949180">తిరిగి అమర్చండి</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE"/> అనేది సమీప చెల్లుబాటు విలువ.</translation>
+<translation id="835897206747267392">చెల్లని విలువ.</translation>
+<translation id="1842960171412779397">ఎంచుకోండి</translation>
+<translation id="7673697353781729403">గంటలు</translation>
+<translation id="4664250907885839816">'<ph name="ATSIGN"/>'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER"/>' చిహ్నం ఉండకూడదు.</translation>
+<translation id="3450233048674729344">విలువ ఖచ్చితంగా <ph name="MAXIMUM"/> కంటే తగ్గువగా లేదా సమానంగా ఉండాలి.</translation>
+<translation id="668171684555832681">ఇతర...</translation>
+<translation id="6270583010843788609">చలనచిత్ర టైమ్‌లైన్ సూక్ష్మచిత్రం</translation>
+<translation id="5641012560118721995">ప్లేబ్యాక్‌ను పాజ్ చేయి</translation>
+<translation id="1591562245178063882">ఈ నెల</translation>
+<translation id="6119846243427417423">ఆక్టివేట్ చెయ్యి</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ఫైళ్ళు</translation>
+<translation id="6643016212128521049">క్లియర్ చేయి</translation>
+<translation id="7888071071722539607">దయచేసి ఇమెయిల్ చిరునామాలో '<ph name="ATSIGN"/>'ని చేర్చండి. '<ph name="INVALIDADDRESS"/>'లో '<ph name="ATSIGN"/>' లేదు.</translation>
+<translation id="1088086359088493902">సెకన్లు</translation>
+<translation id="3934680773876859118">PDF పత్రాన్ని లోడ్ చెయ్యడానికి విఫలమైంది</translation>
+<translation id="3632707345189162177">చలనచిత్రంలో మిగిలి ఉన్న సెకన్లు</translation>
+<translation id="6359256949422175976">చలనచిత్ర సమయ స్క్రబ్బర్ సూక్ష్మచిత్రం</translation>
+<translation id="8597182159515967513">శీర్షిక</translation>
+<translation id="6843725295806269523">మ్యూట్ చేయి</translation>
+<translation id="2653659639078652383">సమర్పించు</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_th.xtb b/chromium/content/app/strings/translations/content_strings_th.xtb
new file mode 100644
index 00000000000..02ee0ded1a6
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_th.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="th">
+<translation id="4763480195061959176">วิดีโอ</translation>
+<translation id="5843503607508392247">อื่นๆ...</translation>
+<translation id="248395913932153421">วัน</translation>
+<translation id="1729654308190250600">โปรดป้อนที่อยู่อีเมลที่ไม่ว่างเปล่า</translation>
+<translation id="6015796118275082299">ปี</translation>
+<translation id="1235745349614807883">ลบการค้นหาล่าสุด</translation>
+<translation id="7223624360433298498">เวลาที่ผ่านไป</translation>
+<translation id="1171774979989969504">โปรดป้อนที่อยู่อีเมล</translation>
+<translation id="709897737746224366">โปรดจับคู่รูปแบบที่ร้องขอ</translation>
+<translation id="5048533449481078685">ผู้สร้างรายการ</translation>
+<translation id="4202807286478387388">ข้าม</translation>
+<translation id="5307600278924710095">โปรดป้อนส่วนหนึ่งโดยตามด้วย &quot;<ph name="ATSIGN"/>&quot; &quot;<ph name="INVALIDADDRESS"/>&quot; นั้นไม่สมบูรณ์</translation>
+<translation id="2746543609216772311">ค่าต้องเป็น <ph name="MINIMUM_DATE_OR_TIME"/> หรือหลังจากนั้น</translation>
+<translation id="2572483411312390101">เล่น</translation>
+<translation id="8785498733064193001">เริ่มเล่น</translation>
+<translation id="7057186640035488495">เวลาของภาพยนตร์</translation>
+<translation id="8199524924445686405">ปปปป</translation>
+<translation id="795667975304826397">ไม่ได้เลือกไฟล์ใด</translation>
+<translation id="7789962463072032349">หยุดชั่วคราว</translation>
+<translation id="6853785296079745596">ซ่อนคำอธิบายภาพ</translation>
+<translation id="4360991593054037559">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องสองรายการคือ <ph name="VALID_VALUE_LOW"/> และ <ph name="VALID_VALUE_HIGHER"/></translation>
+<translation id="1758486001363313524">อื่นๆ...</translation>
+<translation id="8141602879876242471">นี่คือดัชนีที่สามารถค้นหาได้ ป้อนคำหลักในการค้นหา:</translation>
+<translation id="1930711995431081526">สถานะ</translation>
+<translation id="658823671542763450">เข้าสู่โหมดเต็มหน้าจอ</translation>
+<translation id="7720026100085573005">เวลาที่เหลือ</translation>
+<translation id="370665806235115550">กำลังโหลด...</translation>
+<translation id="2723001399770238859">เสียง</translation>
+<translation id="6845533974506654842">กด</translation>
+<translation id="8244226242650769279">แผนที่รูปภาพ</translation>
+<translation id="310520048233152454">โปรดป้อน URL</translation>
+<translation id="4812940957355064477">โปรดป้อนตัวเลข</translation>
+<translation id="2548326553472216322">ไม่พบการค้นหาล่าสุด</translation>
+<translation id="1938124657309484470">ค่าต้องเป็น <ph name="MAXIMUM_DATE_OR_TIME"/> หรือก่อนหน้านั้น</translation>
+<translation id="7263440858009898357">โปรดเลือกรายการจากหน้ารายการ</translation>
+<translation id="901493112792887934">เวลาปัจจุบันเป็นวินาที</translation>
+<translation id="5164977714490026579">ค่าต้องมากกว่าหรือเท่ากับ <ph name="MINIMUM"/></translation>
+<translation id="2247351761944213033">สัปดาห์ที่ <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">หยุดแสดงคำอธิบายภาพ</translation>
+<translation id="5944544982112848342">2048 (เกรดสูง)</translation>
+<translation id="3075154866155599887">โปรดป้อนค่าที่ถูกต้อง ฟิลด์นี้ไม่สมบูรณ์หรือมีวันที่ที่ไม่ถูกต้อง</translation>
+<translation id="3040011195152428237">ลิงก์</translation>
+<translation id="1014825444426747588">ว่าง</translation>
+<translation id="9050748414552849310">แสดงคำอธิบายภาพ</translation>
+<translation id="4522570452068850558">รายละเอียด</translation>
+<translation id="8451268428117625855">โปรดเลือกไฟล์</translation>
+<translation id="8117451130807776954">สัปดาห์นี้</translation>
+<translation id="5966707198760109579">สัปดาห์</translation>
+<translation id="2901282870647571346">สถานะปัจจุบันของภาพยนตร์</translation>
+<translation id="2060505056492490888">&quot;<ph name="DOT"/>&quot; ถูกใช้งานในตำแหน่งที่ไม่ถูกต้องใน &quot;<ph name="INVALIDDOMAIN"/>&quot;</translation>
+<translation id="2674318244760992338">ส่วนท้าย</translation>
+<translation id="8987927404178983737">เดือน</translation>
+<translation id="8115662671911883373">เริ่มแสดงคำอธิบายภาพ</translation>
+<translation id="7364796246159120393">เลือกไฟล์</translation>
+<translation id="2761667185364618470">โปรดเลือกช่องนี้หากคุณต้องการดำเนินการต่อ</translation>
+<translation id="8534579021159131403">นาที</translation>
+<translation id="819205353528511139">เล่นภาพยนตร์ในโหมดเต็มหน้าจอ</translation>
+<translation id="4103419683916926126">มิลลิวินาที</translation>
+<translation id="838869780401515933">ทำเครื่องหมาย</translation>
+<translation id="2846343701378493991">1024 (เกรดปานกลาง)</translation>
+<translation id="1637811476055996098">เลือกไฟล์</translation>
+<translation id="49969490063480558">โปรดป้อนส่วนที่ต่อท้าย &quot;<ph name="ATSIGN"/>&quot; &quot;<ph name="INVALIDADDRESS"/>&quot; นั้นไม่สมบูรณ์</translation>
+<translation id="5476505524087279545">ยกเลิกการทำเครื่องหมาย</translation>
+<translation id="2148716181193084225">วันนี้</translation>
+<translation id="2507943997699731163">โปรดกรอกฟิลด์นี้</translation>
+<translation id="3785482301506746191">ตัวควบคุมเวลาของภาพยนตร์</translation>
+<translation id="739024184232394898">อื่นๆ...</translation>
+<translation id="383465348367842624">ส่วนที่ตามด้วย &quot;<ph name="ATSIGN"/>&quot; ต้องไม่มีสัญลักษณ์ &quot;<ph name="INVALIDCHARACTER"/>&quot;</translation>
+<translation id="5468998798572797635">ออกจากการแสดงแบบเต็มหน้าจอ</translation>
+<translation id="5919473608089529604">ไม่สามารถโหลดปลั๊กอิน</translation>
+<translation id="5546461542133609677">เปิดเสียง</translation>
+<translation id="6663448176199120256">การค้นหาล่าสุด</translation>
+<translation id="1020833440720551630">ปิดไฟล์เสียง</translation>
+<translation id="2597378329261239068">เอกสารนี้ได้รับการป้องกันด้วยรหัสผ่าน โปรดป้อนรหัสผ่าน</translation>
+<translation id="5466621249238537318">โปรดเลือกอย่างน้อยหนึ่งไฟล์</translation>
+<translation id="9132465097189459683">อื่นๆ...</translation>
+<translation id="10623998915015855">ปุ่มสลับ</translation>
+<translation id="8750798805984357768">โปรดเลือกตัวเลือกอย่างหนึ่งอย่างใดเหล่านี้</translation>
+<translation id="7740050170769002709">เนื้อหา HTML</translation>
+<translation id="6692633176391053278">ตัวเพิ่ม/ลดระดับเสียง</translation>
+<translation id="4975562563186953947">เลือกไว้ <ph name="SELECTED_COUNT"/> รายการ</translation>
+<translation id="8541249477527128034">การควบคุมสื่อ</translation>
+<translation id="2226276347425096477">โปรดย่อข้อความนี้ให้เหลือไม่เกิน <ph name="MAX_CHARACTERS"/> อักขระ (ขณะนี้ข้อความของคุณมี <ph name="CURRENT_LENGTH"/> อักขระ)</translation>
+<translation id="6101327004457443354">เปิดไฟล์เสียง</translation>
+<translation id="1822429046913737220">ก่อนเที่ยง/หลังเที่ยง</translation>
+<translation id="1639239467298939599">กำลังโหลด</translation>
+<translation id="2908441821576996758">โปรดป้อนรายการที่อยู่อีเมลโดยคั่นด้วยเครื่องหมายจุลภาค</translation>
+<translation id="5939518447894949180">ตั้งค่าใหม่</translation>
+<translation id="1921819250265091946">วว</translation>
+<translation id="2613802280814924224">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องคือ <ph name="VALID_VALUE"/></translation>
+<translation id="835897206747267392">ค่าไม่ถูกต้อง</translation>
+<translation id="1842960171412779397">เลือก</translation>
+<translation id="7673697353781729403">ชั่วโมง</translation>
+<translation id="4664250907885839816">ส่วนที่ต่อท้าย &quot;<ph name="ATSIGN"/>&quot; ต้องไม่มีสัญลักษณ์ &quot;<ph name="INVALIDCHARACTER"/>&quot;</translation>
+<translation id="3450233048674729344">ค่าต้องน้อยกว่าหรือเท่ากับ <ph name="MAXIMUM"/></translation>
+<translation id="668171684555832681">อื่นๆ...</translation>
+<translation id="6270583010843788609">เส้นเวลาขนาดย่อของภาพยนตร์</translation>
+<translation id="5641012560118721995">หยุดเล่นชั่วคราว</translation>
+<translation id="1591562245178063882">เดือนนี้</translation>
+<translation id="6119846243427417423">เปิดใช้งาน</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> ไฟล์</translation>
+<translation id="6643016212128521049">ล้าง</translation>
+<translation id="7888071071722539607">โปรดใส่ &quot;<ph name="ATSIGN"/>&quot; ในที่อยู่อีเมล &quot;<ph name="INVALIDADDRESS"/>&quot; ขาด &quot;<ph name="ATSIGN"/>&quot;</translation>
+<translation id="1088086359088493902">วินาที</translation>
+<translation id="3934680773876859118">โหลดเอกสาร PDF ล้มเหลว</translation>
+<translation id="3632707345189162177">จำนวนวินาทีที่เหลือของภาพยนตร์</translation>
+<translation id="6359256949422175976">ตัวควบคุมเวลาขนาดย่อของภาพยนตร์</translation>
+<translation id="8597182159515967513">ส่วนหัว</translation>
+<translation id="6843725295806269523">ปิดเสียง</translation>
+<translation id="2653659639078652383">ส่ง</translation>
+<translation id="3732799496749320381">ดด</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_tr.xtb b/chromium/content/app/strings/translations/content_strings_tr.xtb
new file mode 100644
index 00000000000..88e86311cc3
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_tr.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="tr">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Diğer...</translation>
+<translation id="248395913932153421">Gün</translation>
+<translation id="1729654308190250600">Lütfen e-posta adresini boş bırakmayın.</translation>
+<translation id="6015796118275082299">Yıl</translation>
+<translation id="1235745349614807883">Son Aramaları Temizle</translation>
+<translation id="7223624360433298498">geçen süre</translation>
+<translation id="1171774979989969504">Lütfen e-posta adresi girin.</translation>
+<translation id="709897737746224366">Lütfen istenen biçimi eşleştirin.</translation>
+<translation id="5048533449481078685">liste işaretçisi</translation>
+<translation id="4202807286478387388">git</translation>
+<translation id="5307600278924710095">Lütfen başına &quot;<ph name="ATSIGN"/>&quot; ekleyin. &quot;<ph name="INVALIDADDRESS"/>&quot; adresi eksik.</translation>
+<translation id="2746543609216772311">Değer <ph name="MINIMUM_DATE_OR_TIME"/> veya daha ileri olmalıdır.</translation>
+<translation id="2572483411312390101">oynat</translation>
+<translation id="8785498733064193001">oynatmayı başlat</translation>
+<translation id="7057186640035488495">filmin süresi</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">Dosya seçilmedi</translation>
+<translation id="7789962463072032349">duraklat</translation>
+<translation id="6853785296079745596">alt yazıları gizle</translation>
+<translation id="4360991593054037559">Lütfen geçerli bir değer girin. En yakın iki geçerli değer şunlardır: <ph name="VALID_VALUE_LOW"/> ve <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Diğer...</translation>
+<translation id="8141602879876242471">Bu dizinde arama yapılabilir. Arama anahtar kelimeleri girin:</translation>
+<translation id="1930711995431081526">durum</translation>
+<translation id="658823671542763450">tam ekrana geç</translation>
+<translation id="7720026100085573005">kalan süre</translation>
+<translation id="370665806235115550">Yükleniyor...</translation>
+<translation id="2723001399770238859">ses</translation>
+<translation id="6845533974506654842">bas</translation>
+<translation id="8244226242650769279">resim haritası</translation>
+<translation id="310520048233152454">Lütfen bir URL girin.</translation>
+<translation id="4812940957355064477">Lütfen bir sayı girin.</translation>
+<translation id="2548326553472216322">Yeni arama yok</translation>
+<translation id="1938124657309484470">Değer <ph name="MAXIMUM_DATE_OR_TIME"/> veya daha geri olmalıdır.</translation>
+<translation id="7263440858009898357">Lütfen listeden bir öğe seçin.</translation>
+<translation id="901493112792887934">saniye olarak geçerli süre</translation>
+<translation id="5164977714490026579">Değer <ph name="MINIMUM"/> veya daha büyük olmalıdır.</translation>
+<translation id="2247351761944213033"><ph name="WEEKNUMBER"/>. hafta, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">altyazıların görüntülenmesini durdur</translation>
+<translation id="5944544982112848342">2048 (Yüksek Düzey)</translation>
+<translation id="3075154866155599887">Lütfen geçerli bir tarih girin. Alan tam doldurulmamış veya geçersiz bir tarih var.</translation>
+<translation id="3040011195152428237">bağlantı</translation>
+<translation id="1014825444426747588">boş</translation>
+<translation id="9050748414552849310">alt yazıları göster</translation>
+<translation id="4522570452068850558">Ayrıntılar</translation>
+<translation id="8451268428117625855">Lütfen bir dosya seçin.</translation>
+<translation id="8117451130807776954">Bu hafta</translation>
+<translation id="5966707198760109579">Hafta</translation>
+<translation id="2901282870647571346">filmin geçerli durumu</translation>
+<translation id="2060505056492490888">&quot;<ph name="DOT"/>&quot;, &quot;<ph name="INVALIDDOMAIN"/>&quot; adı içinde yanlış bir konumda kullanılmış.</translation>
+<translation id="2674318244760992338">altbilgi</translation>
+<translation id="8987927404178983737">Ay</translation>
+<translation id="8115662671911883373">altyazıları görüntülemeye başla</translation>
+<translation id="7364796246159120393">Dosya Seç</translation>
+<translation id="2761667185364618470">İlerlemek istiyorsanız lütfen bu kutuyu işaretleyin.</translation>
+<translation id="8534579021159131403">Dakika</translation>
+<translation id="819205353528511139">filmi tam ekran modunda oynat</translation>
+<translation id="4103419683916926126">Milisaniye</translation>
+<translation id="838869780401515933">işaretle</translation>
+<translation id="2846343701378493991">1024 (Orta Düzey)</translation>
+<translation id="1637811476055996098">Dosyaları Seç</translation>
+<translation id="49969490063480558">Lütfen başına &quot;<ph name="ATSIGN"/>&quot; ekleyin. &quot;<ph name="INVALIDADDRESS"/>&quot; eksik.</translation>
+<translation id="5476505524087279545">işareti kaldır</translation>
+<translation id="2148716181193084225">Bugün</translation>
+<translation id="2507943997699731163">Lütfen bu alanı doldurun.</translation>
+<translation id="3785482301506746191">film süresi göstergesi</translation>
+<translation id="739024184232394898">Diğer...</translation>
+<translation id="383465348367842624">Başında &quot;<ph name="ATSIGN"/>&quot; bulunan kısımda &quot;<ph name="INVALIDCHARACTER"/>&quot; simgesi bulunmamalıdır.</translation>
+<translation id="5468998798572797635">tam ekrandan çık</translation>
+<translation id="5919473608089529604">Eklenti yüklenemedi.</translation>
+<translation id="5546461542133609677">sesi aç</translation>
+<translation id="6663448176199120256">Son Aramalar</translation>
+<translation id="1020833440720551630">ses kanalını kapat</translation>
+<translation id="2597378329261239068">Doküman şifre korumalı. Lütfen şifreyi girin.</translation>
+<translation id="5466621249238537318">Lütfen bir veya daha fazla dosya seçin.</translation>
+<translation id="9132465097189459683">Diğer...</translation>
+<translation id="10623998915015855">geçiş düğmesi</translation>
+<translation id="8750798805984357768">Lütfen bu seçeneklerden birini belirleyin.</translation>
+<translation id="7740050170769002709">HTML içeriği</translation>
+<translation id="6692633176391053278">stepper (adımlayıcı)</translation>
+<translation id="4975562563186953947"><ph name="SELECTED_COUNT"/> tane seçildi</translation>
+<translation id="8541249477527128034">medya kontrolü</translation>
+<translation id="2226276347425096477">Lütfen bu metni <ph name="MAX_CHARACTERS"/> veya daha az karakter olacak şekilde kısaltın (şu anda <ph name="CURRENT_LENGTH"/> karakter kullanıyorsunuz).</translation>
+<translation id="6101327004457443354">ses kanalını aç</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">Yükleniyor</translation>
+<translation id="2908441821576996758">Lütfen e-posta adreslerinin virgülle ayrılmış listesini girin.</translation>
+<translation id="5939518447894949180">Sıfırla</translation>
+<translation id="1921819250265091946">gg</translation>
+<translation id="2613802280814924224">Lütfen geçerli bir değer girin. En yakın geçerli değer şudur: <ph name="VALID_VALUE"/></translation>
+<translation id="835897206747267392">Geçersiz değer.</translation>
+<translation id="1842960171412779397">seç</translation>
+<translation id="7673697353781729403">Saat</translation>
+<translation id="4664250907885839816">Başında &quot;<ph name="ATSIGN"/>&quot; bulunan kısımda &quot;<ph name="INVALIDCHARACTER"/>&quot; simgesi bulunmamalıdır.</translation>
+<translation id="3450233048674729344">Değer <ph name="MAXIMUM"/> veya daha küçük olmalıdır.</translation>
+<translation id="668171684555832681">Diğer...</translation>
+<translation id="6270583010843788609">film zaman çizelgesi küçük resmi</translation>
+<translation id="5641012560118721995">oynatmayı duraklat</translation>
+<translation id="1591562245178063882">Bu ay</translation>
+<translation id="6119846243427417423">etkinleştir</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> dosya</translation>
+<translation id="6643016212128521049">Temizle</translation>
+<translation id="7888071071722539607">Lütfen e-posta adresine bir &quot;<ph name="ATSIGN"/>&quot; işareti ekleyin. &quot;<ph name="INVALIDADDRESS"/>&quot; adresinde &quot;<ph name="ATSIGN"/>&quot; eksik.</translation>
+<translation id="1088086359088493902">Saniye</translation>
+<translation id="3934680773876859118">PDF dokümanı yüklenemedi</translation>
+<translation id="3632707345189162177">saniye olarak filmin kalan süresi</translation>
+<translation id="6359256949422175976">film süresi göstergesinin küçük resmi</translation>
+<translation id="8597182159515967513">başlık</translation>
+<translation id="6843725295806269523">sesi kapat</translation>
+<translation id="2653659639078652383">Gönder</translation>
+<translation id="3732799496749320381">aa</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_uk.xtb b/chromium/content/app/strings/translations/content_strings_uk.xtb
new file mode 100644
index 00000000000..dc914e323d4
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_uk.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="uk">
+<translation id="4763480195061959176">відео</translation>
+<translation id="5843503607508392247">Інші...</translation>
+<translation id="248395913932153421">День</translation>
+<translation id="1729654308190250600">Введіть електронну адресу.</translation>
+<translation id="6015796118275082299">Рік</translation>
+<translation id="1235745349614807883">Очистити останні пошуки</translation>
+<translation id="7223624360433298498">минуло часу</translation>
+<translation id="1171774979989969504">Введіть електронну адресу.</translation>
+<translation id="709897737746224366">Виберіть потрібний формат.</translation>
+<translation id="5048533449481078685">маркер списку</translation>
+<translation id="4202807286478387388">перейти</translation>
+<translation id="5307600278924710095">Введіть частину електронної адреси до знака &quot;<ph name="ATSIGN"/>&quot;. Електронна адреса &quot;<ph name="INVALIDADDRESS"/>&quot; неповна.</translation>
+<translation id="2746543609216772311">Має бути <ph name="MINIMUM_DATE_OR_TIME"/> або пізніша дата.</translation>
+<translation id="2572483411312390101">відтворити</translation>
+<translation id="8785498733064193001">розпочати відтворення</translation>
+<translation id="7057186640035488495">тривалість фільму</translation>
+<translation id="8199524924445686405">рррр</translation>
+<translation id="795667975304826397">Файл не вибрано</translation>
+<translation id="7789962463072032349">призупинити</translation>
+<translation id="6853785296079745596">сховати приховані субтирти</translation>
+<translation id="4360991593054037559">Введіть дійсне значення. Два найближчі дійсні значення: <ph name="VALID_VALUE_LOW"/> і <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Інші...</translation>
+<translation id="8141602879876242471">Цей доступний для пошуку індекс. Введіть ключові слова пошуку:</translation>
+<translation id="1930711995431081526">статус</translation>
+<translation id="658823671542763450">увійти в повноекранний режим</translation>
+<translation id="7720026100085573005">залишилось часу</translation>
+<translation id="370665806235115550">Завантаження...</translation>
+<translation id="2723001399770238859">аудіо</translation>
+<translation id="6845533974506654842">натиснути</translation>
+<translation id="8244226242650769279">мапа зображення</translation>
+<translation id="310520048233152454">Введіть URL-адресу.</translation>
+<translation id="4812940957355064477">Введіть число.</translation>
+<translation id="2548326553472216322">Немає останніх пошуків</translation>
+<translation id="1938124657309484470">Має бути <ph name="MAXIMUM_DATE_OR_TIME"/> або раніша дата.</translation>
+<translation id="7263440858009898357">Виберіть елемент зі списку.</translation>
+<translation id="901493112792887934">поточний час у секундах</translation>
+<translation id="5164977714490026579">Значення має бути більшим або дорівнювати <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Тиждень <ph name="WEEKNUMBER"/>, <ph name="YEAR"/> р.</translation>
+<translation id="7740016676195725605">сховати приховані субтитри</translation>
+<translation id="5944544982112848342">2048 (Високий рівень)</translation>
+<translation id="3075154866155599887">Введіть дійсне значення. Поле не заповнено або введено недійсну дату.</translation>
+<translation id="3040011195152428237">посилання</translation>
+<translation id="1014825444426747588">порожнє</translation>
+<translation id="9050748414552849310">показати приховані субтитри</translation>
+<translation id="4522570452068850558">Деталі</translation>
+<translation id="8451268428117625855">Виберіть файл.</translation>
+<translation id="8117451130807776954">Цей тиждень</translation>
+<translation id="5966707198760109579">Тиждень</translation>
+<translation id="2901282870647571346">поточний статус фільму</translation>
+<translation id="2060505056492490888">Символ &quot;<ph name="DOT"/>&quot; у &quot;<ph name="INVALIDDOMAIN"/>&quot; використано неправильно.</translation>
+<translation id="2674318244760992338">нижній колонтитул</translation>
+<translation id="8987927404178983737">Місяць</translation>
+<translation id="8115662671911883373">показати приховані субтитри</translation>
+<translation id="7364796246159120393">Вибрати файл</translation>
+<translation id="2761667185364618470">Поставте тут прапорець, якщо хочете продовжити.</translation>
+<translation id="8534579021159131403">Хвилини</translation>
+<translation id="819205353528511139">відтворити фільм у повноекранному режимі</translation>
+<translation id="4103419683916926126">Мілісекунди</translation>
+<translation id="838869780401515933">установити прапорець</translation>
+<translation id="2846343701378493991">1024 (Середній рівень)</translation>
+<translation id="1637811476055996098">Вибрати файли</translation>
+<translation id="49969490063480558">Введіть частину електронної адреси після знака &quot;<ph name="ATSIGN"/>&quot;. Електронна адреса &quot;<ph name="INVALIDADDRESS"/>&quot; неповна.</translation>
+<translation id="5476505524087279545">зняти прапорець</translation>
+<translation id="2148716181193084225">Сьогодні</translation>
+<translation id="2507943997699731163">Заповніть це поле.</translation>
+<translation id="3785482301506746191">повзунок перебігу фільму</translation>
+<translation id="739024184232394898">Інші...</translation>
+<translation id="383465348367842624">Частина перед знаком &quot;<ph name="ATSIGN"/>&quot; не може містити символ &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="5468998798572797635">вийти з повноекранного режиму</translation>
+<translation id="5919473608089529604">Не вдалося завантажити плагін.</translation>
+<translation id="5546461542133609677">увімкнути звук</translation>
+<translation id="6663448176199120256">Останні пошуки</translation>
+<translation id="1020833440720551630">вимкнути звукову доріжку</translation>
+<translation id="2597378329261239068">Цей документ захищено паролем. Введіть пароль.</translation>
+<translation id="5466621249238537318">Виберіть один або декілька файлів.</translation>
+<translation id="9132465097189459683">Інші...</translation>
+<translation id="10623998915015855">перемикач</translation>
+<translation id="8750798805984357768">Виберіть один із запропонованих варіантів.</translation>
+<translation id="7740050170769002709">Вміст HTML</translation>
+<translation id="6692633176391053278">повторювач stepper</translation>
+<translation id="4975562563186953947">Вибрано <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">елемент керування мультимедіа</translation>
+<translation id="2226276347425096477">Скоротіть текст до такої кількості символів або менше: <ph name="MAX_CHARACTERS"/> (наразі використано символів: <ph name="CURRENT_LENGTH"/>).</translation>
+<translation id="6101327004457443354">увімкнути звукову доріжку</translation>
+<translation id="1822429046913737220">д.п./п.п.</translation>
+<translation id="1639239467298939599">Завантаження</translation>
+<translation id="2908441821576996758">Введіть список електронних адрес, розділених комою.</translation>
+<translation id="5939518447894949180">Скинути</translation>
+<translation id="1921819250265091946">дд</translation>
+<translation id="2613802280814924224">Введіть дійсне значення. Найближче дійсне значення: <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Недійсне значення</translation>
+<translation id="1842960171412779397">вибрати</translation>
+<translation id="7673697353781729403">Години</translation>
+<translation id="4664250907885839816">Частина після знака &quot;<ph name="ATSIGN"/>&quot; не може містити символ &quot;<ph name="INVALIDCHARACTER"/>&quot;.</translation>
+<translation id="3450233048674729344">Значення має бути меншим або дорівнювати <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Інший...</translation>
+<translation id="6270583010843788609">ескіз на часовій шкалі фільму</translation>
+<translation id="5641012560118721995">призупинити відтворення</translation>
+<translation id="1591562245178063882">Цей місяць</translation>
+<translation id="6119846243427417423">активувати</translation>
+<translation id="8444882422881193423">файлів: <ph name="NUMBER_OF_FILES"/></translation>
+<translation id="6643016212128521049">Очистити</translation>
+<translation id="7888071071722539607">Електронна адреса має містити знак &quot;<ph name="ATSIGN"/>&quot;. В електронній адресі &quot;<ph name="INVALIDADDRESS"/>&quot; знака &quot;<ph name="ATSIGN"/>&quot; немає.</translation>
+<translation id="1088086359088493902">Секунди</translation>
+<translation id="3934680773876859118">Не вдалося завантажити документ PDF</translation>
+<translation id="3632707345189162177">кількість секунд до кінця фільму</translation>
+<translation id="6359256949422175976">ескіз на повзунку перебігу фільму</translation>
+<translation id="8597182159515967513">заголовок</translation>
+<translation id="6843725295806269523">вимкнути звук</translation>
+<translation id="2653659639078652383">Надіслати</translation>
+<translation id="3732799496749320381">мм</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_vi.xtb b/chromium/content/app/strings/translations/content_strings_vi.xtb
new file mode 100644
index 00000000000..d0906e24637
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_vi.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="vi">
+<translation id="4763480195061959176">video</translation>
+<translation id="5843503607508392247">Khác...</translation>
+<translation id="248395913932153421">Ngày</translation>
+<translation id="1729654308190250600">Vui lòng nhập địa chỉ email không trống.</translation>
+<translation id="6015796118275082299">Năm</translation>
+<translation id="1235745349614807883">Xóa Tìm kiếm Gần đây</translation>
+<translation id="7223624360433298498">thời gian trôi qua</translation>
+<translation id="1171774979989969504">Vui lòng nhập địa chỉ email.</translation>
+<translation id="709897737746224366">Vui lòng khớp với định dạng được yêu cầu.</translation>
+<translation id="5048533449481078685">đánh dấu danh sách</translation>
+<translation id="4202807286478387388">chuyển</translation>
+<translation id="5307600278924710095">Vui lòng nhập phần đứng trước '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' không hoàn chỉnh.</translation>
+<translation id="2746543609216772311">Giá trị phải là <ph name="MINIMUM_DATE_OR_TIME"/> hoặc muộn hơn.</translation>
+<translation id="2572483411312390101">phát</translation>
+<translation id="8785498733064193001">bắt đầu phát lại</translation>
+<translation id="7057186640035488495">thời gian phim</translation>
+<translation id="8199524924445686405">yyyy</translation>
+<translation id="795667975304826397">Không có tệp nào được chọn</translation>
+<translation id="7789962463072032349">tạm dừng</translation>
+<translation id="6853785296079745596">ẩn phụ đề chi tiết</translation>
+<translation id="4360991593054037559">Vui lòng nhập giá trị hợp lệ. Hai giá trị hợp lệ gần nhất là <ph name="VALID_VALUE_LOW"/> và <ph name="VALID_VALUE_HIGHER"/>.</translation>
+<translation id="1758486001363313524">Khác...</translation>
+<translation id="8141602879876242471">Đây là chỉ mục có thể tìm kiếm. Nhập từ khóa tìm kiếm vào:</translation>
+<translation id="1930711995431081526">trạng thái</translation>
+<translation id="658823671542763450">vào chế độ toàn màn hình</translation>
+<translation id="7720026100085573005">thời gian còn lại</translation>
+<translation id="370665806235115550">Đang tải...</translation>
+<translation id="2723001399770238859">âm thanh</translation>
+<translation id="6845533974506654842">nhấn</translation>
+<translation id="8244226242650769279">bản đồ hình ảnh</translation>
+<translation id="310520048233152454">Vui lòng nhập URL.</translation>
+<translation id="4812940957355064477">Vui lòng nhập một số.</translation>
+<translation id="2548326553472216322">Không có tìm kiếm nào gần đây</translation>
+<translation id="1938124657309484470">Giá trị phải là <ph name="MAXIMUM_DATE_OR_TIME"/> hoặc sớm hơn.</translation>
+<translation id="7263440858009898357">Vui lòng chọn một mục trong danh sách.</translation>
+<translation id="901493112792887934">thời gian hiện tại bằng giây</translation>
+<translation id="5164977714490026579">Giá trị phải lớn hơn hoặc bằng <ph name="MINIMUM"/>.</translation>
+<translation id="2247351761944213033">Tuần <ph name="WEEKNUMBER"/>, <ph name="YEAR"/></translation>
+<translation id="7740016676195725605">ngừng hiển thị phụ đề chi tiết</translation>
+<translation id="5944544982112848342">2048 (Cấp độ cao)</translation>
+<translation id="3075154866155599887">Vui lòng nhập một giá trị hợp lệ. Trường không hoàn chỉnh hoặc có giá trị không hợp lệ.</translation>
+<translation id="3040011195152428237">liên kết</translation>
+<translation id="1014825444426747588">trống</translation>
+<translation id="9050748414552849310">hiển thị phụ đề chi tiết</translation>
+<translation id="4522570452068850558">Chi tiết</translation>
+<translation id="8451268428117625855">Vui lòng chọn một tệp.</translation>
+<translation id="8117451130807776954">Tuần này</translation>
+<translation id="5966707198760109579">Tuần</translation>
+<translation id="2901282870647571346">trạng thái phim hiện tại</translation>
+<translation id="2060505056492490888">'<ph name="DOT"/>' bị sử dụng sai vị trí trong '<ph name="INVALIDDOMAIN"/>'.</translation>
+<translation id="2674318244760992338">chân trang</translation>
+<translation id="8987927404178983737">Tháng</translation>
+<translation id="8115662671911883373">bắt đầu hiển thị phụ đề chi tiết</translation>
+<translation id="7364796246159120393">Chọn tệp</translation>
+<translation id="2761667185364618470">Vui lòng chọn hộp kiểm này nếu bạn muốn tiếp tục.</translation>
+<translation id="8534579021159131403">Phút</translation>
+<translation id="819205353528511139">phát phim ở chế độ toàn màn hình</translation>
+<translation id="4103419683916926126">Mili giây</translation>
+<translation id="838869780401515933">chọn</translation>
+<translation id="2846343701378493991">1024 (Loại Trung bình)</translation>
+<translation id="1637811476055996098">Chọn tệp</translation>
+<translation id="49969490063480558">Vui lòng nhập phần đứng sau '<ph name="ATSIGN"/>'. '<ph name="INVALIDADDRESS"/>' không hoàn chỉnh.</translation>
+<translation id="5476505524087279545">bỏ chọn</translation>
+<translation id="2148716181193084225">Hôm nay</translation>
+<translation id="2507943997699731163">Vui lòng điền vào trường này.</translation>
+<translation id="3785482301506746191">trình kiểm soát thời gian phim</translation>
+<translation id="739024184232394898">Khác...</translation>
+<translation id="383465348367842624">Phần đứng trước '<ph name="ATSIGN"/>' không được chứa biểu tượng '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="5468998798572797635">thoát khỏi chế độ toàn màn hình</translation>
+<translation id="5919473608089529604">Không thể tải plugin.</translation>
+<translation id="5546461542133609677">bật tiếng</translation>
+<translation id="6663448176199120256">Tìm kiếm Gần đây</translation>
+<translation id="1020833440720551630">tắt tiếng bản âm thanh</translation>
+<translation id="2597378329261239068">Tài liệu này được bảo vệ bằng mật khẩu. Vui lòng nhập mật khẩu.</translation>
+<translation id="5466621249238537318">Vui lòng chọn một hoặc nhiều tệp.</translation>
+<translation id="9132465097189459683">Khác...</translation>
+<translation id="10623998915015855">nút chuyển đổi</translation>
+<translation id="8750798805984357768">Vui lòng chọn một trong các tùy chọn sau.</translation>
+<translation id="7740050170769002709">Nội dung HTML</translation>
+<translation id="6692633176391053278">điều khiển tăng/giảm</translation>
+<translation id="4975562563186953947">Đã chọn <ph name="SELECTED_COUNT"/></translation>
+<translation id="8541249477527128034">kiểm soát phương tiện</translation>
+<translation id="2226276347425096477">Hãy cắt ngắn văn bản này thành <ph name="MAX_CHARACTERS"/> ký tự hoặc ít hơn (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH"/> ký tự).</translation>
+<translation id="6101327004457443354">bật tiếng bản âm thanh</translation>
+<translation id="1822429046913737220">SA/CH</translation>
+<translation id="1639239467298939599">Đang tải</translation>
+<translation id="2908441821576996758">Vui lòng nhập danh sách địa chỉ email được phân cách bằng dấu phẩy.</translation>
+<translation id="5939518447894949180">Đặt lại</translation>
+<translation id="1921819250265091946">dd</translation>
+<translation id="2613802280814924224">Vui lòng nhập giá trị hợp lệ. Giá trị hợp lệ gần nhất là <ph name="VALID_VALUE"/>.</translation>
+<translation id="835897206747267392">Giá trị không hợp lệ.</translation>
+<translation id="1842960171412779397">chọn</translation>
+<translation id="7673697353781729403">Giờ</translation>
+<translation id="4664250907885839816">Phần đứng sau '<ph name="ATSIGN"/>' không được chứa biểu tượng '<ph name="INVALIDCHARACTER"/>'.</translation>
+<translation id="3450233048674729344">Giá trị phải nhỏ hơn hoặc bằng <ph name="MAXIMUM"/>.</translation>
+<translation id="668171684555832681">Khác...</translation>
+<translation id="6270583010843788609">núm dòng thời gian phim</translation>
+<translation id="5641012560118721995">tạm dừng phát lại</translation>
+<translation id="1591562245178063882">Tháng này</translation>
+<translation id="6119846243427417423">kích hoạt</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> tệp</translation>
+<translation id="6643016212128521049">Xóa</translation>
+<translation id="7888071071722539607">Vui lòng bao gồm '<ph name="ATSIGN"/>' trong địa chỉ email. '<ph name="INVALIDADDRESS"/>' bị thiếu '<ph name="ATSIGN"/>'.</translation>
+<translation id="1088086359088493902">Giây</translation>
+<translation id="3934680773876859118">Không thể tải tài liệu PDF</translation>
+<translation id="3632707345189162177">số giây còn lại của phim</translation>
+<translation id="6359256949422175976">núm trình kiểm soát thời gian phim</translation>
+<translation id="8597182159515967513">đầu đề</translation>
+<translation id="6843725295806269523">tắt tiếng</translation>
+<translation id="2653659639078652383">Gửi</translation>
+<translation id="3732799496749320381">mm</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
new file mode 100644
index 00000000000..8cf54d04ab0
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-CN">
+<translation id="4763480195061959176">视频</translation>
+<translation id="5843503607508392247">其他...</translation>
+<translation id="248395913932153421">日</translation>
+<translation id="1729654308190250600">请输入有效的电子邮件地址。</translation>
+<translation id="6015796118275082299">年</translation>
+<translation id="1235745349614807883">清除最近的搜索</translation>
+<translation id="7223624360433298498">已播放时间</translation>
+<translation id="1171774979989969504">请输入电子邮件地址。</translation>
+<translation id="709897737746224366">请与所请求的格式保持一致。</translation>
+<translation id="5048533449481078685">列表标记</translation>
+<translation id="4202807286478387388">略过</translation>
+<translation id="5307600278924710095">请在“<ph name="ATSIGN"/>”前面输入内容。“<ph name="INVALIDADDRESS"/>”不完整。</translation>
+<translation id="2746543609216772311">指定的值不得早于<ph name="MINIMUM_DATE_OR_TIME"/>。</translation>
+<translation id="2572483411312390101">播放</translation>
+<translation id="8785498733064193001">开始播放</translation>
+<translation id="7057186640035488495">电影时间</translation>
+<translation id="8199524924445686405"> 年 </translation>
+<translation id="795667975304826397">未选择任何文件</translation>
+<translation id="7789962463072032349">暂停</translation>
+<translation id="6853785296079745596">隐藏可选字幕</translation>
+<translation id="4360991593054037559">请输入有效值。两个最接近的有效值分别为<ph name="VALID_VALUE_LOW"/>和<ph name="VALID_VALUE_HIGHER"/>。</translation>
+<translation id="1758486001363313524">其他...</translation>
+<translation id="8141602879876242471">这是一个可搜索的索引。请输入搜索关键字:</translation>
+<translation id="1930711995431081526">状态</translation>
+<translation id="658823671542763450">进入全屏模式</translation>
+<translation id="7720026100085573005">剩余时间</translation>
+<translation id="370665806235115550">正在加载...</translation>
+<translation id="2723001399770238859">音频</translation>
+<translation id="6845533974506654842">按</translation>
+<translation id="8244226242650769279">图片映射</translation>
+<translation id="310520048233152454">请输入网址。</translation>
+<translation id="4812940957355064477">请输入一个数字。</translation>
+<translation id="2548326553472216322">最近未执行搜索</translation>
+<translation id="1938124657309484470">指定的值不得晚于<ph name="MAXIMUM_DATE_OR_TIME"/>。</translation>
+<translation id="7263440858009898357">请在列表中选择一项。</translation>
+<translation id="901493112792887934">目前时间(以秒为单位)</translation>
+<translation id="5164977714490026579">值必须大于或等于 <ph name="MINIMUM"/>。</translation>
+<translation id="2247351761944213033"><ph name="YEAR"/> 年第 <ph name="WEEKNUMBER"/> 周</translation>
+<translation id="7740016676195725605">停止显示可选字幕</translation>
+<translation id="5944544982112848342">2048(高强度)</translation>
+<translation id="3075154866155599887">请输入一个有效值。该字段不完整或存在无效日期。</translation>
+<translation id="3040011195152428237">链接</translation>
+<translation id="1014825444426747588">空白</translation>
+<translation id="9050748414552849310">显示可选字幕</translation>
+<translation id="4522570452068850558">详细信息</translation>
+<translation id="8451268428117625855">请选择一个文件。</translation>
+<translation id="8117451130807776954">本周</translation>
+<translation id="5966707198760109579">周</translation>
+<translation id="2901282870647571346">当前电影状态</translation>
+<translation id="2060505056492490888">“<ph name="INVALIDDOMAIN"/>”中“<ph name="DOT"/>”的位置不正确。</translation>
+<translation id="2674318244760992338">页脚</translation>
+<translation id="8987927404178983737">月</translation>
+<translation id="8115662671911883373">开始显示可选字幕</translation>
+<translation id="7364796246159120393">选择文件</translation>
+<translation id="2761667185364618470">如果要继续,请选中此框。</translation>
+<translation id="8534579021159131403">分钟</translation>
+<translation id="819205353528511139">在全屏模式下播放电影</translation>
+<translation id="4103419683916926126">毫秒</translation>
+<translation id="838869780401515933">选中</translation>
+<translation id="2846343701378493991">1024(中等强度)</translation>
+<translation id="1637811476055996098">选择文件</translation>
+<translation id="49969490063480558">请在“<ph name="ATSIGN"/>”后面输入内容。“<ph name="INVALIDADDRESS"/>”不完整。</translation>
+<translation id="5476505524087279545">取消选中</translation>
+<translation id="2148716181193084225">今天</translation>
+<translation id="2507943997699731163">请填写此字段。</translation>
+<translation id="3785482301506746191">电影时间进度条</translation>
+<translation id="739024184232394898">其他...</translation>
+<translation id="383465348367842624">“<ph name="ATSIGN"/>”前面的内容不应包含符号“<ph name="INVALIDCHARACTER"/>”。</translation>
+<translation id="5468998798572797635">退出全屏模式</translation>
+<translation id="5919473608089529604">无法加载插件。</translation>
+<translation id="5546461542133609677">取消静音</translation>
+<translation id="6663448176199120256">近期搜索</translation>
+<translation id="1020833440720551630">将音轨设为静音</translation>
+<translation id="2597378329261239068">本文档设置了密码保护,请输入密码。</translation>
+<translation id="5466621249238537318">请选择一个或多个文件。</translation>
+<translation id="9132465097189459683">其他...</translation>
+<translation id="10623998915015855">切换按钮</translation>
+<translation id="8750798805984357768">请从这些选项中选择一个。</translation>
+<translation id="7740050170769002709">HTML 内容</translation>
+<translation id="6692633176391053278">步进器</translation>
+<translation id="4975562563186953947">选择了<ph name="SELECTED_COUNT"/>项</translation>
+<translation id="8541249477527128034">媒体控件</translation>
+<translation id="2226276347425096477">请将该文本减少为 <ph name="MAX_CHARACTERS"/> 个字符或更少(您当前使用了 <ph name="CURRENT_LENGTH"/> 个字符)。</translation>
+<translation id="6101327004457443354">取消对音轨静音</translation>
+<translation id="1822429046913737220">上午/下午</translation>
+<translation id="1639239467298939599">正在加载</translation>
+<translation id="2908441821576996758">请输入用逗号分隔的电子邮件地址的列表。</translation>
+<translation id="5939518447894949180">重置</translation>
+<translation id="1921819250265091946">日</translation>
+<translation id="2613802280814924224">请输入有效值。最接近的有效值为<ph name="VALID_VALUE"/>。</translation>
+<translation id="835897206747267392">值无效。</translation>
+<translation id="1842960171412779397">选中</translation>
+<translation id="7673697353781729403">小时</translation>
+<translation id="4664250907885839816">“<ph name="ATSIGN"/>”后面的内容不应包含符号“<ph name="INVALIDCHARACTER"/>”。</translation>
+<translation id="3450233048674729344">值必须小于或等于 <ph name="MAXIMUM"/>。</translation>
+<translation id="668171684555832681">其他...</translation>
+<translation id="6270583010843788609">电影时间轴缩略图</translation>
+<translation id="5641012560118721995">暂停播放</translation>
+<translation id="1591562245178063882">本月</translation>
+<translation id="6119846243427417423">激活</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> 个文件</translation>
+<translation id="6643016212128521049">清除</translation>
+<translation id="7888071071722539607">请在电子邮件地址中包括“<ph name="ATSIGN"/>”。“<ph name="INVALIDADDRESS"/>”中缺少“<ph name="ATSIGN"/>”。</translation>
+<translation id="1088086359088493902">秒</translation>
+<translation id="3934680773876859118">无法加载 PDF 文档</translation>
+<translation id="3632707345189162177">电影剩余时间(以秒为单位)</translation>
+<translation id="6359256949422175976">电影时间进度条缩略图</translation>
+<translation id="8597182159515967513">标题</translation>
+<translation id="6843725295806269523">静音</translation>
+<translation id="2653659639078652383">提交</translation>
+<translation id="3732799496749320381">月</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
new file mode 100644
index 00000000000..24395f3e936
--- /dev/null
+++ b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
@@ -0,0 +1,115 @@
+<?xml version="1.0" ?>
+<!DOCTYPE translationbundle>
+<translationbundle lang="zh-TW">
+<translation id="4763480195061959176">影片</translation>
+<translation id="5843503607508392247">其他...</translation>
+<translation id="248395913932153421">日</translation>
+<translation id="1729654308190250600">請輸入電子郵件地址。</translation>
+<translation id="6015796118275082299">年</translation>
+<translation id="1235745349614807883">清除最近的搜尋紀錄</translation>
+<translation id="7223624360433298498">已播放時間</translation>
+<translation id="1171774979989969504">請輸入電子郵件地址。</translation>
+<translation id="709897737746224366">請符合要求的格式。</translation>
+<translation id="5048533449481078685">清單標記</translation>
+<translation id="4202807286478387388">跳至另一頁</translation>
+<translation id="5307600278924710095">請輸入「<ph name="ATSIGN"/>」後面的部分。「<ph name="INVALIDADDRESS"/>」不是完整值。</translation>
+<translation id="2746543609216772311">必須輸入 <ph name="MINIMUM_DATE_OR_TIME"/> 或之後的值。</translation>
+<translation id="2572483411312390101">播放</translation>
+<translation id="8785498733064193001">開始播放</translation>
+<translation id="7057186640035488495">電影時間</translation>
+<translation id="8199524924445686405"> 年 </translation>
+<translation id="795667975304826397">未選擇任何檔案</translation>
+<translation id="7789962463072032349">暫停</translation>
+<translation id="6853785296079745596">不顯示字幕</translation>
+<translation id="4360991593054037559">請輸入有效值。最接近的兩個有效值分別是 <ph name="VALID_VALUE_LOW"/> 和 <ph name="VALID_VALUE_HIGHER"/>。</translation>
+<translation id="1758486001363313524">其他...</translation>
+<translation id="8141602879876242471">這是可搜尋的索引,輸入搜尋關鍵字:</translation>
+<translation id="1930711995431081526">狀態</translation>
+<translation id="658823671542763450">進入全螢幕</translation>
+<translation id="7720026100085573005">剩餘時間</translation>
+<translation id="370665806235115550">載入中…</translation>
+<translation id="2723001399770238859">音訊</translation>
+<translation id="6845533974506654842">按下</translation>
+<translation id="8244226242650769279">圖片點擊區</translation>
+<translation id="310520048233152454">請輸入網址。</translation>
+<translation id="4812940957355064477">請輸入一個數字。</translation>
+<translation id="2548326553472216322">沒有近期的搜尋</translation>
+<translation id="1938124657309484470">必須輸入 <ph name="MAXIMUM_DATE_OR_TIME"/> 或之前的值。</translation>
+<translation id="7263440858009898357">請選取一個清單中的項目。</translation>
+<translation id="901493112792887934">目前時間 (以秒為單位)</translation>
+<translation id="5164977714490026579">值必須大於或等於 <ph name="MINIMUM"/>。</translation>
+<translation id="2247351761944213033"><ph name="YEAR"/> 年,第 <ph name="WEEKNUMBER"/> 週</translation>
+<translation id="7740016676195725605">停止顯示字幕</translation>
+<translation id="5944544982112848342">2048 (高級)</translation>
+<translation id="3075154866155599887">欄位內容不完整或日期無效,請輸入有效的值。</translation>
+<translation id="3040011195152428237">連結</translation>
+<translation id="1014825444426747588">空白</translation>
+<translation id="9050748414552849310">顯示字幕</translation>
+<translation id="4522570452068850558">詳細資訊</translation>
+<translation id="8451268428117625855">請選取檔案。</translation>
+<translation id="8117451130807776954">本週</translation>
+<translation id="5966707198760109579">週</translation>
+<translation id="2901282870647571346">目前電影狀態</translation>
+<translation id="2060505056492490888">「<ph name="DOT"/>」未放在「<ph name="INVALIDDOMAIN"/>」的正確位置。</translation>
+<translation id="2674318244760992338">頁尾</translation>
+<translation id="8987927404178983737">月</translation>
+<translation id="8115662671911883373">開始顯示字幕</translation>
+<translation id="7364796246159120393">選擇檔案</translation>
+<translation id="2761667185364618470">如果您要繼續執行,請勾選這個核取方塊。</translation>
+<translation id="8534579021159131403">分鐘</translation>
+<translation id="819205353528511139">使用全螢幕模式播放電影</translation>
+<translation id="4103419683916926126">毫秒</translation>
+<translation id="838869780401515933">選取</translation>
+<translation id="2846343701378493991">1024 (中等)</translation>
+<translation id="1637811476055996098">選擇檔案</translation>
+<translation id="49969490063480558">請輸入「<ph name="ATSIGN"/>」後面的部分。「<ph name="INVALIDADDRESS"/>」不是完整值。</translation>
+<translation id="5476505524087279545">取消選取</translation>
+<translation id="2148716181193084225">今天</translation>
+<translation id="2507943997699731163">請填寫這個欄位。</translation>
+<translation id="3785482301506746191">影片時間拖曳工具</translation>
+<translation id="739024184232394898">其他...</translation>
+<translation id="383465348367842624">「<ph name="ATSIGN"/>」後面的部分不應包含「<ph name="INVALIDCHARACTER"/>」符號。</translation>
+<translation id="5468998798572797635">退出全螢幕</translation>
+<translation id="5919473608089529604">無法載入外掛程式。</translation>
+<translation id="5546461542133609677">取消靜音</translation>
+<translation id="6663448176199120256">最近的搜尋</translation>
+<translation id="1020833440720551630">將音軌設為靜音</translation>
+<translation id="2597378329261239068">此文件受到密碼保護,請輸入密碼。</translation>
+<translation id="5466621249238537318">請選取一或多個檔案。</translation>
+<translation id="9132465097189459683">其他...</translation>
+<translation id="10623998915015855">切換按鈕</translation>
+<translation id="8750798805984357768">請選取其中一個選項。</translation>
+<translation id="7740050170769002709">HTML 內容</translation>
+<translation id="6692633176391053278">步進器</translation>
+<translation id="4975562563186953947">已選取 <ph name="SELECTED_COUNT"/> 個項目</translation>
+<translation id="8541249477527128034">媒體控制</translation>
+<translation id="2226276347425096477">請將這段文字刪減至 <ph name="MAX_CHARACTERS"/> 個字元以下 (目前的字元數為 <ph name="CURRENT_LENGTH"/> 個)。</translation>
+<translation id="6101327004457443354">取消音軌靜音</translation>
+<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1639239467298939599">載入中</translation>
+<translation id="2908441821576996758">請輸入以逗號分隔的電子郵件地址清單。</translation>
+<translation id="5939518447894949180">重設</translation>
+<translation id="1921819250265091946">日</translation>
+<translation id="2613802280814924224">請輸入有效值。最接近的有效值是 <ph name="VALID_VALUE"/>。</translation>
+<translation id="835897206747267392">無效的值。</translation>
+<translation id="1842960171412779397">選取</translation>
+<translation id="7673697353781729403">小時</translation>
+<translation id="4664250907885839816">「<ph name="ATSIGN"/>」後面的部分不應包含「<ph name="INVALIDCHARACTER"/>」符號。</translation>
+<translation id="3450233048674729344">值必須小於或等於 <ph name="MAXIMUM"/>。</translation>
+<translation id="668171684555832681">其他...</translation>
+<translation id="6270583010843788609">電影時間軸捲動方塊</translation>
+<translation id="5641012560118721995">暫停播放</translation>
+<translation id="1591562245178063882">本月</translation>
+<translation id="6119846243427417423">啟動</translation>
+<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES"/> 個檔案</translation>
+<translation id="6643016212128521049">清除</translation>
+<translation id="7888071071722539607">請在電子郵件地址中包含「<ph name="ATSIGN"/>」。「<ph name="INVALIDADDRESS"/>」未包含「<ph name="ATSIGN"/>」。</translation>
+<translation id="1088086359088493902">秒</translation>
+<translation id="3934680773876859118">無法載入 PDF 文件</translation>
+<translation id="3632707345189162177">電影剩餘秒數</translation>
+<translation id="6359256949422175976">影片時間拖曳工具捲動方塊</translation>
+<translation id="8597182159515967513">標題</translation>
+<translation id="6843725295806269523">忽略的項目</translation>
+<translation id="2653659639078652383">提交</translation>
+<translation id="3732799496749320381">月</translation>
+</translationbundle> \ No newline at end of file
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index d76f458c7c6..a420b9e9826 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -5,10 +5,12 @@
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//content/browser/browser.gni")
+import("//media/media_options.gni")
source_set("browser") {
- # Only targets in the content tree can depend directly on this target.
- visibility = [ "//content/*" ]
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/browser:browser_sources" ]
defines = []
libs = []
@@ -17,14 +19,18 @@ source_set("browser") {
# Shared deps. See also non-iOS deps below.
deps = [
"//base",
+ "//base:base_static",
"//content:resources",
- "//content/browser/service_worker:database_proto",
+ "//content/browser/service_worker:proto",
"//content/browser/speech/proto",
+ "//content/public/common:common_sources",
"//crypto",
+ "//device/battery",
"//google_apis",
"//net",
"//skia",
"//sql",
+ "//third_party/npapi",
"//third_party/re2",
"//third_party/WebKit/public:blink_headers",
"//third_party/zlib",
@@ -36,6 +42,8 @@ source_set("browser") {
"//ui/events:gesture_detection",
"//ui/gfx",
"//ui/gfx/geometry",
+ "//ui/gl",
+ "//ui/native_theme",
"//ui/resources",
"//ui/snapshot",
]
@@ -74,41 +82,40 @@ source_set("browser") {
"$root_gen_dir/webkit/grit/devtools_resources_map.cc",
"$root_gen_dir/webkit/grit/devtools_resources_map.h",
"$root_gen_dir/content/browser/tracing/grit/tracing_resources.h",
- "$root_gen_dir/ui/ui_resources/grit/webui_resources_map.cc",
+ "$root_gen_dir/ui/resources/grit/webui_resources_map.cc",
"$root_gen_dir/content/browser/devtools/devtools_protocol_constants.cc",
"$root_gen_dir/content/browser/devtools/devtools_protocol_constants.h",
+ "$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_handler_impl.cc",
+ "$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_handler_impl.h",
], ".")
# Non-iOS deps.
deps += [
+ "//cc",
+ "//cc/surfaces",
+ "//content/app/resources",
+ "//content/app/strings",
"//content/browser/devtools:resources",
"//content/common:mojo_bindings",
- "//cc",
- "//cc:cc_surfaces",
+ "//content/public/common:mojo_bindings",
"//mojo/public/cpp/bindings",
- "//mojo/public/interfaces/service_provider:service_provider",
- "//mojo/public/js/bindings",
+ "//mojo/public/interfaces/application",
+ "//mojo/public/js",
"//net:http_server",
+ "//storage/browser",
+ "//storage/common",
+ "//third_party/WebKit/public:resources",
+ "//third_party/angle:commit_id",
"//third_party/icu",
"//third_party/leveldatabase",
"//third_party/libyuv",
"//ui/resources",
"//ui/surface",
- "//ui/webui/resources",
- "//webkit:resources",
- "//webkit:strings",
- "//webkit/browser:storage",
- "//webkit/common",
- "//webkit/common:storage",
- # TODO(GYP)
- #"//third_party/angle:commit_id",
]
}
configs += [
"//content:content_implementation",
- "//content:libjingle_stub_config", # TODO(GYP) remove when libjingle is ready.
- "//content:webrtc_stub_config", # TODO(GYP) remove when webrtc is ready.
]
if (toolkit_views) {
@@ -122,15 +129,19 @@ source_set("browser") {
]
deps += [ "//third_party/power_gadget" ]
} else {
- sources += [ "power_profiler/power_data_provider_dummy.cc" ]
+ sources += [
+ "power_profiler/power_data_provider_dummy.cc",
+ "file_descriptor_info_impl.cc",
+ "file_descriptor_info_impl.h",
+ ]
sources -= [ "renderer_host/web_input_event_aurawin.cc" ]
}
- if (!is_win && !is_mac && (!is_linux || !use_udev)) {
+ if (!is_win && !is_mac && !is_android && (!is_linux || !use_udev)) {
sources += [ "gamepad/gamepad_platform_data_fetcher.cc" ]
}
- if (enable_printing != 0) {
+ if (enable_basic_printing || enable_print_preview) {
deps += [ "//printing" ]
}
@@ -150,24 +161,25 @@ source_set("browser") {
if (enable_webrtc) {
sources += rebase_path(content_browser_gypi_values.webrtc_browser_sources,
".", "//content")
- # TODO(GYP)
- #deps += [ "//jingle:glue" ]
+ deps += [ "//jingle:jingle_glue" ]
if (is_linux) {
- # TODO(GYP)
- #deps += [ "//third_party/libjingle:libjingle_webrtc" ]
+ deps += [ "//third_party/libjingle:libjingle_webrtc" ]
}
if (is_linux || is_mac || is_win) {
sources += [
"media/capture/desktop_capture_device.cc",
"media/capture/desktop_capture_device.h",
- "media/capture/desktop_capture_device_aura.cc",
- "media/capture/desktop_capture_device_aura.h",
"media/capture/desktop_capture_device_uma_types.cc",
"media/capture/desktop_capture_device_uma_types.h",
]
+ if (use_aura) {
+ sources += [
+ "media/capture/desktop_capture_device_aura.cc",
+ "media/capture/desktop_capture_device_aura.h",
+ ]
+ }
defines += [ "ENABLE_SCREEN_CAPTURE=1" ]
- # TODO(GYP)
- #deps += [ "//third_party/webrtc/modules:desktop_capture" ]
+ deps += [ "//third_party/webrtc/modules/desktop_capture" ]
}
}
@@ -235,6 +247,9 @@ source_set("browser") {
if (!use_ozone || use_pango) {
sources -= [ "renderer_host/pepper/pepper_truetype_font_list_ozone.cc" ]
}
+ if (!use_pango) {
+ sources -= [ "renderer_host/pepper/pepper_truetype_font_list_pango.cc" ]
+ }
}
if (is_linux && use_aura) {
@@ -243,11 +258,28 @@ source_set("browser") {
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
- } else {
- sources -= [
- "power_save_blocker_x11.cc",
- "renderer_host/web_input_event_aurax11.cc",
- ]
+ }
+
+ # Dealing with power_save_blocker_{x11,ozone}.cc is a little complicated
+ # given the interaction between os_chromeos and the feature flags for X11 and
+ # ozone, so do it all in one spot.
+ if (is_chromeos || !use_ozone) {
+ sources -= [ "power_save_blocker_ozone.cc", ]
+ }
+ if (is_chromeos || !use_x11) {
+ sources -= [ "power_save_blocker_x11.cc", ]
+ }
+
+ # Dealing with *wifi_data_provider_*.cc is also a bit complicated given
+ # android, chromeos, linux and use_dbus.
+ if (is_android) {
+ sources -= [ "geolocation/wifi_data_provider_common.cc" ]
+ }
+ if (is_chromeos || (is_linux && !use_dbus)) {
+ sources -= [ "geolocation/wifi_data_provider_linux.cc" ]
+ }
+ if (is_linux && use_dbus) {
+ sources -= [ "geolocation/empty_wifi_data_provider.cc" ]
}
if (use_pango) {
@@ -258,17 +290,13 @@ source_set("browser") {
sources += rebase_path(content_browser_gypi_values.android_browser_sources,
".", "//content")
sources -= [
- "battery_status/battery_status_manager_default.cc",
"browser_ipc_logging.cc",
"device_sensors/data_fetcher_shared_memory_default.cc",
"font_list_async.cc",
- "geolocation/device_data_provider.cc",
- "geolocation/empty_device_data_provider.cc",
"geolocation/network_location_provider.cc",
"geolocation/network_location_provider.h",
"geolocation/network_location_request.cc",
"geolocation/network_location_request.h",
- "geolocation/wifi_data_provider_common.cc",
"renderer_host/native_web_keyboard_event.cc",
"tracing/tracing_ui.cc",
"tracing/tracing_ui.h",
@@ -296,8 +324,9 @@ source_set("browser") {
"speech/speech_recognizer_impl.h",
]
deps += [
- #"//content:jni_headers", TODO(GYP)
- #"//media", TODO(GYP)
+ "//content/public/android:jni",
+ "//media",
+ "//mojo/android:libsystem_java",
]
libs += [ "jnigraphics" ]
}
@@ -312,27 +341,43 @@ source_set("browser") {
}
if (is_chromeos) {
- sources -= [
- "geolocation/wifi_data_provider_linux.cc",
- "power_save_blocker_ozone.cc",
- "power_save_blocker_x11.cc",
+ deps += [
+ "//chromeos",
+ "//chromeos:power_manager_proto",
]
- deps += [ "//chromeos:power_manager_proto" ]
}
if (use_aura) {
deps += [
"//ui/aura",
"//ui/strings",
+ "//ui/wm",
]
} else { # Not aura.
sources -= [
+ "renderer_host/input/synthetic_gesture_target_aura.cc",
+ "renderer_host/input/synthetic_gesture_target_aura.h",
+ "renderer_host/native_web_keyboard_event_aura.cc",
"renderer_host/render_widget_host_view_aura.cc",
"renderer_host/render_widget_host_view_aura.h",
- "web_contents/touch_editable_impl_aura.cc",
- "web_contents/touch_editable_impl_aura.h",
"renderer_host/ui_events_helper.cc",
"renderer_host/ui_events_helper.h",
+ "renderer_host/web_input_event_aura.cc",
+ "renderer_host/web_input_event_aura.h",
+ "web_contents/aura/gesture_nav_simple.cc",
+ "web_contents/aura/gesture_nav_simple.h",
+ "web_contents/aura/image_window_delegate.cc",
+ "web_contents/aura/image_window_delegate.h",
+ "web_contents/aura/overscroll_navigation_overlay.cc",
+ "web_contents/aura/overscroll_navigation_overlay.h",
+ "web_contents/aura/shadow_layer_delegate.cc",
+ "web_contents/aura/shadow_layer_delegate.h",
+ "web_contents/aura/window_slider.cc",
+ "web_contents/aura/window_slider.h",
+ "web_contents/touch_editable_impl_aura.cc",
+ "web_contents/touch_editable_impl_aura.h",
+ "web_contents/web_contents_view_aura.cc",
+ "web_contents/web_contents_view_aura.h",
]
}
@@ -346,25 +391,35 @@ source_set("browser") {
"compositor/software_output_device_x11.h",
]
}
+
+ if (!use_ozone) {
+ sources -= [
+ "compositor/overlay_candidate_validator_ozone.cc",
+ "compositor/overlay_candidate_validator_ozone.h",
+ "compositor/software_output_device_ozone.cc",
+ "compositor/software_output_device_ozone.h",
+ ]
+ }
deps += [ "//ui/compositor" ]
}
- if (enable_speech_input) {
+ if (enable_web_speech) {
deps += [
"//third_party/flac",
"//third_party/speex",
]
}
- if (is_linux) {
- if (use_dbus) {
- sources -= [
- "geolocation/empty_wifi_data_provider.cc",
- ]
- deps += [ "//dbus" ]
- } else {
- # This will already have gotten removed for all non-Linux cases.
- sources -= [ "geolocation/wifi_data_provider_linux.cc" ]
- }
+ if (is_linux && use_dbus) {
+ deps += [ "//dbus" ]
+ }
+
+ if (enable_browser_cdms) {
+ sources += [
+ "media/cdm/browser_cdm_manager.cc",
+ "media/cdm/browser_cdm_manager.h",
+ "media/media_web_contents_observer.cc",
+ "media/media_web_contents_observer.h",
+ ]
}
}
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index 1af4237d1f0..c99434f0d7d 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -1,9 +1,12 @@
include_rules = [
+ "+content/app/strings/grit", # For generated headers
"+content/public/browser",
+ "+device/battery", # For battery status service.
"+media/audio", # For audio input for speech input feature.
"+media/base", # For Android JNI registration.
"+media/midi", # For Web MIDI API
"+media/video", # For Video Device monitoring in Mac.
+ "+mojo",
"+sql",
"+ui/webui",
"+win8/util",
@@ -13,6 +16,10 @@ include_rules = [
# above.
"+components/tracing",
+ # In general, //content shouldn't depend on //device.
+ # This is the an exception.
+ "+device/udev_linux", # For udev utility and wrapper library.
+
# Other libraries.
"+third_party/iaccessible2",
"+third_party/isimpledom",
@@ -25,25 +32,30 @@ include_rules = [
"+chromeos",
"+third_party/cros_system_api",
- "-webkit/child",
"-webkit/renderer",
# No inclusion of WebKit from the browser, other than strictly enum/POD,
# header-only types, and some selected common code.
"-third_party/WebKit",
- "+third_party/WebKit/public/platform/WebBatteryStatus.h",
+ "+third_party/WebKit/public/platform/WebCircularGeofencingRegion.h",
"+third_party/WebKit/public/platform/WebCursorInfo.h",
"+third_party/WebKit/public/platform/WebGamepad.h",
"+third_party/WebKit/public/platform/WebGamepads.h",
+ "+third_party/WebKit/public/platform/WebGeofencingEventType.h",
"+third_party/WebKit/public/platform/WebGraphicsContext3D.h",
"+third_party/WebKit/public/platform/WebIDBDatabaseException.h",
"+third_party/WebKit/public/platform/WebIDBTypes.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
+ "+third_party/WebKit/public/platform/WebLockOrientationError.h",
+ "+third_party/WebKit/public/platform/WebNotificationPermission.h",
+ "+third_party/WebKit/public/platform/WebPushPermissionStatus.h",
"+third_party/WebKit/public/platform/WebScreenOrientationLockType.h",
"+third_party/WebKit/public/platform/WebScreenOrientationType.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
+ "+third_party/WebKit/public/platform/WebServiceWorkerCacheError.h",
"+third_party/WebKit/public/platform/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/WebServiceWorkerEventResult.h",
+ "+third_party/WebKit/public/platform/WebServiceWorkerResponseType.h",
"+third_party/WebKit/public/platform/WebServiceWorkerState.h",
"+third_party/WebKit/public/platform/WebString.h",
"+third_party/WebKit/public/platform/WebVibration.h",
@@ -63,13 +75,11 @@ include_rules = [
"+third_party/WebKit/public/web/WebPopupType.h",
"+third_party/WebKit/public/web/WebSerializedScriptValueVersion.h",
"+third_party/WebKit/public/web/WebTextDirection.h",
+ "+third_party/WebKit/public/web/WebTextInputType.h",
# These should be burned down. http://crbug.com/237267
"!third_party/WebKit/public/web/mac/WebInputEventFactory.h",
- "+ui/ozone/ozone_platform.h",
- "+ui/ozone/ozone_switches.h",
-
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
# for more information.
diff --git a/chromium/content/browser/OWNERS b/chromium/content/browser/OWNERS
index 37b5294c54f..51f5662fd5a 100644
--- a/chromium/content/browser/OWNERS
+++ b/chromium/content/browser/OWNERS
@@ -1,11 +1,7 @@
-sky@chromium.org
-
per-file child_process_security_policy_impl.*=tsepez@chromium.org
per-file child_process_security_policy_impl.*=creis@chromium.org
-per-file child_process_security_policy_impl.*=cevans@chromium.org
per-file child_process_security_unittest.cc=tsepez@chromium.org
per-file child_process_security_unittest.cc=creis@chromium.org
-per-file child_process_security_unittest.cc=cevans@chromium.org
per-file power_save_blocker_chromeos.cc=derat@chromium.org
# Mac Sandbox profiles.
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
new file mode 100644
index 00000000000..5702a33ded3
--- /dev/null
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -0,0 +1,191 @@
+// Copyright (c) 2014 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 "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/accessibility_messages.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_tree.h"
+
+namespace content {
+
+class AccessibilityIpcErrorBrowserTest : public ContentBrowserTest {
+ public:
+ AccessibilityIpcErrorBrowserTest() {}
+
+ protected:
+ // Convenience method to get the value of a particular AXNode
+ // attribute as a UTF-8 string.
+ std::string GetAttr(const ui::AXNode* node,
+ const ui::AXStringAttribute attr) {
+ const ui::AXNodeData& data = node->data();
+ for (size_t i = 0; i < data.string_attributes.size(); ++i) {
+ if (data.string_attributes[i].first == attr)
+ return data.string_attributes[i].second;
+ }
+ return std::string();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(AccessibilityIpcErrorBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
+ ResetBrowserAccessibilityManager) {
+ // Create a data url and load it.
+ const char url_str[] =
+ "data:text/html,"
+ "<div aria-live='polite'>"
+ " <p id='p1'>Paragraph One</p>"
+ " <p id='p2'>Paragraph Two</p>"
+ "</div>"
+ "<button id='button'>Button</button>";
+ GURL url(url_str);
+ NavigateToURL(shell(), url);
+
+ // Simulate a condition where the RFH can't create a
+ // BrowserAccessibilityManager - like if there's no view.
+ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ frame->set_no_create_browser_accessibility_manager_for_testing(true);
+ ASSERT_EQ(nullptr, frame->GetOrCreateBrowserAccessibilityManager());
+
+ {
+ // Enable accessibility (passing AccessibilityModeComplete to
+ // AccessibilityNotificationWaiter does this automatically) and wait for
+ // the first event.
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_LAYOUT_COMPLETE);
+ waiter.WaitForNotification();
+ }
+
+ // Make sure we still didn't create a BrowserAccessibilityManager.
+ // This means that at least one accessibility IPC was lost.
+ ASSERT_EQ(nullptr, frame->GetOrCreateBrowserAccessibilityManager());
+
+ // Now create a BrowserAccessibilityManager, simulating what would happen
+ // if the RFH's view is created now - but then disallow recreating the
+ // BrowserAccessibilityManager so that we can test that this one gets
+ // destroyed.
+ frame->set_no_create_browser_accessibility_manager_for_testing(false);
+ ASSERT_TRUE(frame->GetOrCreateBrowserAccessibilityManager() != nullptr);
+ frame->set_no_create_browser_accessibility_manager_for_testing(true);
+
+ {
+ // Hide one of the elements on the page, and wait for an accessibility
+ // notification triggered by the hide.
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_LIVE_REGION_CHANGED);
+ ASSERT_TRUE(ExecuteScript(
+ shell()->web_contents(),
+ "document.getElementById('p1').style.display = 'none';"));
+ waiter.WaitForNotification();
+ }
+
+ // Show that accessibility was reset because the frame doesn't have a
+ // BrowserAccessibilityManager anymore.
+ ASSERT_EQ(nullptr, frame->browser_accessibility_manager());
+
+ // Finally, allow creating a new accessibility manager and
+ // ensure that we didn't kill the renderer; we can still send it messages.
+ frame->set_no_create_browser_accessibility_manager_for_testing(false);
+ const ui::AXTree* tree = nullptr;
+ {
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_FOCUS);
+ ASSERT_TRUE(ExecuteScript(
+ shell()->web_contents(),
+ "document.getElementById('button').focus();"));
+ waiter.WaitForNotification();
+ tree = &waiter.GetAXTree();
+ }
+
+ // Get the accessibility tree, ensure it reflects the final state of the
+ // document.
+ const ui::AXNode* root = tree->GetRoot();
+
+ // Use this for debugging if the test fails.
+ VLOG(1) << tree->ToString();
+
+ EXPECT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, root->data().role);
+ ASSERT_EQ(2, root->child_count());
+
+ const ui::AXNode* live_region = root->ChildAtIndex(0);
+ ASSERT_EQ(1, live_region->child_count());
+ EXPECT_EQ(ui::AX_ROLE_DIV, live_region->data().role);
+
+ const ui::AXNode* para = live_region->ChildAtIndex(0);
+ EXPECT_EQ(ui::AX_ROLE_PARAGRAPH, para->data().role);
+
+ const ui::AXNode* button_container = root->ChildAtIndex(1);
+ EXPECT_EQ(ui::AX_ROLE_GROUP, button_container->data().role);
+ ASSERT_EQ(1, button_container->child_count());
+
+ const ui::AXNode* button = button_container->ChildAtIndex(0);
+ EXPECT_EQ(ui::AX_ROLE_BUTTON, button->data().role);
+ EXPECT_TRUE(button->data().state >> ui::AX_STATE_FOCUSED & 1);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
+ MultipleBadAccessibilityIPCsKillsRenderer) {
+ // Create a data url and load it.
+ const char url_str[] =
+ "data:text/html,"
+ "<button id='button'>Button</button>";
+ GURL url(url_str);
+ NavigateToURL(shell(), url);
+ RenderFrameHostImpl* frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+
+ {
+ // Enable accessibility (passing AccessibilityModeComplete to
+ // AccessibilityNotificationWaiter does this automatically) and wait for
+ // the first event.
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_LAYOUT_COMPLETE);
+ waiter.WaitForNotification();
+ }
+
+ // Construct a bad accessibility message that BrowserAccessibilityManager
+ // will reject.
+ std::vector<AccessibilityHostMsg_EventParams> bad_accessibility_event_list;
+ bad_accessibility_event_list.push_back(AccessibilityHostMsg_EventParams());
+ bad_accessibility_event_list[0].update.node_id_to_clear = -2;
+
+ // We should be able to reset accessibility |max_iterations-1| times
+ // (see render_frame_host_impl.cc - kMaxAccessibilityResets),
+ // but the subsequent time the renderer should be killed.
+ int max_iterations = RenderFrameHostImpl::kMaxAccessibilityResets;
+
+ for (int iteration = 0; iteration < max_iterations; iteration++) {
+ // Send the browser accessibility the bad message.
+ BrowserAccessibilityManager* manager =
+ frame->GetOrCreateBrowserAccessibilityManager();
+ manager->OnAccessibilityEvents(bad_accessibility_event_list);
+
+ // Now the frame should have deleted the BrowserAccessibilityManager.
+ ASSERT_EQ(nullptr, frame->browser_accessibility_manager());
+
+ if (iteration == max_iterations - 1)
+ break;
+
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_LAYOUT_COMPLETE);
+ waiter.WaitForNotification();
+ }
+
+ // Wait for the renderer to be killed.
+ if (frame->IsRenderFrameLive()) {
+ RenderProcessHostWatcher render_process_watcher(
+ frame->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ render_process_watcher.Wait();
+ }
+ ASSERT_FALSE(frame->IsRenderFrameLive());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
index 5e191bd0b0e..aa54862fa3d 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_mode_browsertest.cc
@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/accessibility/accessibility_mode_helper.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
@@ -23,79 +25,98 @@ const char kMinimalPageDataURL[] =
class AccessibilityModeTest : public ContentBrowserTest {
protected:
- WebContents* web_contents() {
- return shell()->web_contents();
- }
-
- RenderWidgetHostImpl* rwhi() {
- RenderWidgetHost* rwh =
- web_contents()->GetRenderWidgetHostView()->GetRenderWidgetHost();
- return RenderWidgetHostImpl::From(rwh);
- }
-
- RenderWidgetHostViewBase* host_view() {
- return static_cast<RenderWidgetHostViewBase*>(
- shell()->web_contents()->GetRenderWidgetHostView());
+ WebContentsImpl* web_contents() {
+ return static_cast<WebContentsImpl*>(shell()->web_contents());
}
void ExpectBrowserAccessibilityManager(bool expect_bam,
std::string message = "") {
if (expect_bam) {
- EXPECT_NE((BrowserAccessibilityManager*)NULL,
- host_view()->GetBrowserAccessibilityManager()) << message;
+ EXPECT_NE(
+ (BrowserAccessibilityManager*)NULL,
+ web_contents()->GetRootBrowserAccessibilityManager()) << message;
} else {
- EXPECT_EQ((BrowserAccessibilityManager*)NULL,
- host_view()->GetBrowserAccessibilityManager()) << message;
+ EXPECT_EQ(
+ (BrowserAccessibilityManager*)NULL,
+ web_contents()->GetRootBrowserAccessibilityManager()) << message;
+ }
+ }
+
+ AccessibilityMode CorrectedAccessibility(AccessibilityMode mode) {
+ return AddAccessibilityModeTo(GetBaseAccessibilityMode(), mode);
+ }
+
+ bool ShouldBeBrowserAccessibilityManager(AccessibilityMode mode) {
+ mode = CorrectedAccessibility(mode);
+ switch (mode) {
+ case AccessibilityModeOff:
+ case AccessibilityModeTreeOnly:
+ return false;
+ case AccessibilityModeComplete:
+ return true;
+ default:
+ NOTREACHED();
}
+ return false;
}
};
IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeOff) {
NavigateToURL(shell(), GURL(kMinimalPageDataURL));
- EXPECT_EQ(AccessibilityModeOff, rwhi()->accessibility_mode());
- ExpectBrowserAccessibilityManager(false);
+ EXPECT_EQ(CorrectedAccessibility(AccessibilityModeOff),
+ web_contents()->GetAccessibilityMode());
+ ExpectBrowserAccessibilityManager(
+ ShouldBeBrowserAccessibilityManager(AccessibilityModeOff));
}
IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeComplete) {
NavigateToURL(shell(), GURL(kMinimalPageDataURL));
- ASSERT_EQ(AccessibilityModeOff, rwhi()->accessibility_mode());
+ ASSERT_EQ(CorrectedAccessibility(AccessibilityModeOff),
+ web_contents()->GetAccessibilityMode());
AccessibilityNotificationWaiter waiter(shell());
- rwhi()->AddAccessibilityMode(AccessibilityModeComplete);
- EXPECT_EQ(AccessibilityModeComplete, rwhi()->accessibility_mode());
+ web_contents()->AddAccessibilityMode(AccessibilityModeComplete);
+ EXPECT_EQ(AccessibilityModeComplete, web_contents()->GetAccessibilityMode());
waiter.WaitForNotification();
- ExpectBrowserAccessibilityManager(true);
+ ExpectBrowserAccessibilityManager(
+ ShouldBeBrowserAccessibilityManager(AccessibilityModeComplete));
}
IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeTreeOnly) {
NavigateToURL(shell(), GURL(kMinimalPageDataURL));
- ASSERT_EQ(AccessibilityModeOff, rwhi()->accessibility_mode());
+ ASSERT_EQ(CorrectedAccessibility(AccessibilityModeOff),
+ web_contents()->GetAccessibilityMode());
AccessibilityNotificationWaiter waiter(shell());
- rwhi()->AddAccessibilityMode(AccessibilityModeTreeOnly);
- EXPECT_EQ(AccessibilityModeTreeOnly, rwhi()->accessibility_mode());
+ web_contents()->AddAccessibilityMode(AccessibilityModeTreeOnly);
+ EXPECT_EQ(CorrectedAccessibility(AccessibilityModeTreeOnly),
+ web_contents()->GetAccessibilityMode());
waiter.WaitForNotification();
// No BrowserAccessibilityManager expected for AccessibilityModeTreeOnly
- ExpectBrowserAccessibilityManager(false);
+ ExpectBrowserAccessibilityManager(
+ ShouldBeBrowserAccessibilityManager(AccessibilityModeTreeOnly));
}
IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddingModes) {
NavigateToURL(shell(), GURL(kMinimalPageDataURL));
AccessibilityNotificationWaiter waiter(shell());
- rwhi()->AddAccessibilityMode(AccessibilityModeTreeOnly);
- EXPECT_EQ(AccessibilityModeTreeOnly, rwhi()->accessibility_mode());
+ web_contents()->AddAccessibilityMode(AccessibilityModeTreeOnly);
+ EXPECT_EQ(CorrectedAccessibility(AccessibilityModeTreeOnly),
+ web_contents()->GetAccessibilityMode());
waiter.WaitForNotification();
- ExpectBrowserAccessibilityManager(false,
+ ExpectBrowserAccessibilityManager(ShouldBeBrowserAccessibilityManager(
+ AccessibilityModeTreeOnly),
"Should be no BrowserAccessibilityManager "
"for AccessibilityModeTreeOnly");
AccessibilityNotificationWaiter waiter2(shell());
- rwhi()->AddAccessibilityMode(AccessibilityModeComplete);
- EXPECT_EQ(AccessibilityModeComplete, rwhi()->accessibility_mode());
+ web_contents()->AddAccessibilityMode(AccessibilityModeComplete);
+ EXPECT_EQ(AccessibilityModeComplete, web_contents()->GetAccessibilityMode());
waiter2.WaitForNotification();
- ExpectBrowserAccessibilityManager(true,
+ ExpectBrowserAccessibilityManager(ShouldBeBrowserAccessibilityManager(
+ AccessibilityModeComplete),
"Should be a BrowserAccessibilityManager "
"for AccessibilityModeComplete");
}
diff --git a/chromium/content/browser/accessibility/accessibility_mode_helper.cc b/chromium/content/browser/accessibility/accessibility_mode_helper.cc
index 7988595aa21..9745e63e453 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_helper.cc
+++ b/chromium/content/browser/accessibility/accessibility_mode_helper.cc
@@ -2,14 +2,9 @@
// 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 "content/browser/accessibility/accessibility_mode_helper.h"
-#if defined(OS_WIN)
-#include "base/command_line.h"
-#include "base/win/windows_version.h"
-#include "content/public/common/content_switches.h"
-#endif
-
namespace content {
namespace {
@@ -19,7 +14,6 @@ AccessibilityMode CastToAccessibilityMode(unsigned int int_mode) {
switch (mode) {
case AccessibilityModeOff:
case AccessibilityModeComplete:
- case AccessibilityModeEditableTextOnly:
case AccessibilityModeTreeOnly:
return mode;
}
@@ -29,6 +23,11 @@ AccessibilityMode CastToAccessibilityMode(unsigned int int_mode) {
} // namespace
+AccessibilityMode GetBaseAccessibilityMode() {
+ AccessibilityMode accessibility_mode = AccessibilityModeOff;
+ return accessibility_mode;
+}
+
AccessibilityMode AddAccessibilityModeTo(AccessibilityMode to,
AccessibilityMode mode_to_add) {
return CastToAccessibilityMode(to | mode_to_add);
@@ -38,18 +37,6 @@ AccessibilityMode RemoveAccessibilityModeFrom(
AccessibilityMode from,
AccessibilityMode mode_to_remove) {
unsigned int new_mode = from ^ (mode_to_remove & from);
-#if defined(OS_WIN)
- // On Windows 8, always enable accessibility for editable text controls
- // so we can show the virtual keyboard when one is enabled.
- if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererAccessibility)) {
- if ((from & AccessibilityModeEditableTextOnly) ==
- AccessibilityModeEditableTextOnly)
- new_mode |= AccessibilityModeEditableTextOnly;
- }
-#endif // defined(OS_WIN)
-
return CastToAccessibilityMode(new_mode);
}
diff --git a/chromium/content/browser/accessibility/accessibility_mode_helper.h b/chromium/content/browser/accessibility/accessibility_mode_helper.h
index c12c2069d19..c741173ee7b 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_helper.h
+++ b/chromium/content/browser/accessibility/accessibility_mode_helper.h
@@ -5,11 +5,14 @@
#ifndef CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_MODE_HELPER_H_
#define CONTENT_BROWSER_ACCESSIBILITY_ACCESSIBILITY_MODE_HELPER_H_
+#include "content/common/accessibility_mode_enums.h"
#include "content/common/content_export.h"
-#include "content/common/view_message_enums.h"
namespace content {
+// Returns base accessibility mode constant, depends on OS version.
+CONTENT_EXPORT AccessibilityMode GetBaseAccessibilityMode();
+
// Adds the given accessibility mode constant to the given accessibility mode
// bitmap.
CONTENT_EXPORT AccessibilityMode
diff --git a/chromium/content/browser/accessibility/accessibility_mode_helper_unittest.cc b/chromium/content/browser/accessibility/accessibility_mode_helper_unittest.cc
index 73388a19e9f..6bef704a363 100644
--- a/chromium/content/browser/accessibility/accessibility_mode_helper_unittest.cc
+++ b/chromium/content/browser/accessibility/accessibility_mode_helper_unittest.cc
@@ -6,10 +6,6 @@
#include "content/common/view_message_enums.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
namespace content {
TEST(AccessibilityModeHelperTest, TestNoOpRemove) {
@@ -19,35 +15,17 @@ TEST(AccessibilityModeHelperTest, TestNoOpRemove) {
}
TEST(AccessibilityModeHelperTest, TestRemoveSelf) {
- AccessibilityMode kOffMode = AccessibilityModeOff;
-#if defined(OS_WIN)
- // Always preserve AccessibilityModeEditableTextOnly on Windows 8,
- // see RemoveAccessibilityModeFrom() implementation.
- // Test won't pass if switches::kDisableRendererAccessibility is set.
- if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
- kOffMode = AccessibilityModeEditableTextOnly;
- }
-#endif // defined(OS_WIN)
+ AccessibilityMode kBaseMode = GetBaseAccessibilityMode();
- EXPECT_EQ(kOffMode,
+ EXPECT_EQ(kBaseMode,
RemoveAccessibilityModeFrom(AccessibilityModeComplete,
AccessibilityModeComplete));
-
- EXPECT_EQ(
- kOffMode,
- RemoveAccessibilityModeFrom(AccessibilityModeEditableTextOnly,
- AccessibilityModeEditableTextOnly));
}
TEST(AccessibilityModeHelperTest, TestAddMode) {
- EXPECT_EQ(
- AccessibilityModeComplete,
- AddAccessibilityModeTo(AccessibilityModeEditableTextOnly,
- AccessibilityModeComplete));
- EXPECT_EQ(
- AccessibilityModeComplete,
- AddAccessibilityModeTo(AccessibilityModeEditableTextOnly,
- AccessibilityModeTreeOnly));
+ EXPECT_EQ(AccessibilityModeComplete,
+ AddAccessibilityModeTo(AccessibilityModeTreeOnly,
+ AccessibilityModeComplete));
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
index cca61a5b5c6..d4c189fb6f1 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -12,7 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
namespace content {
@@ -30,12 +30,10 @@ AccessibilityTreeFormatter::AccessibilityTreeFormatter(
// static
AccessibilityTreeFormatter* AccessibilityTreeFormatter::Create(
- RenderViewHost* rvh) {
- RenderWidgetHostViewBase* host_view = static_cast<RenderWidgetHostViewBase*>(
- WebContents::FromRenderViewHost(rvh)->GetRenderWidgetHostView());
-
+ WebContents* web_contents) {
BrowserAccessibilityManager* manager =
- host_view->GetBrowserAccessibilityManager();
+ static_cast<WebContentsImpl*>(web_contents)->
+ GetRootBrowserAccessibilityManager();
if (!manager)
return NULL;
@@ -68,7 +66,7 @@ void AccessibilityTreeFormatter::RecursiveBuildAccessibilityTree(
dict->Set(kChildrenDictAttr, children);
for (size_t i = 0; i < node.PlatformChildCount(); ++i) {
- BrowserAccessibility* child_node = node.InternalGetChild(i);
+ BrowserAccessibility* child_node = node.PlatformGetChild(i);
base::DictionaryValue* child_dict = new base::DictionaryValue;
children->Append(child_dict);
RecursiveBuildAccessibilityTree(*child_node, child_dict);
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter.h b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
index a290886aad9..39c6a4aa283 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter.h
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter.h
@@ -16,7 +16,7 @@
namespace content {
-class RenderViewHost;
+class WebContents;
// A utility class for formatting platform-specific accessibility information,
// for use in testing, debugging, and developer tools.
@@ -27,7 +27,7 @@ class CONTENT_EXPORT AccessibilityTreeFormatter {
explicit AccessibilityTreeFormatter(BrowserAccessibility* root);
virtual ~AccessibilityTreeFormatter();
- static AccessibilityTreeFormatter* Create(RenderViewHost* rvh);
+ static AccessibilityTreeFormatter* Create(WebContents* wc);
// Populates the given DictionaryValue with the accessibility tree.
// The dictionary contains a key/value pair for each attribute of the node,
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index e037d4d01bf..7d5c1bf1ee1 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -94,19 +94,35 @@ scoped_ptr<base::ListValue> PopulateArray(NSArray* array) {
scoped_ptr<base::StringValue> StringForBrowserAccessibility(
BrowserAccessibilityCocoa* obj) {
- NSString* description = [obj role];
- id value = [obj value];
+ NSMutableArray* tokens = [[NSMutableArray alloc] init];
+
+ // Always include the role
+ id role = [obj role];
+ [tokens addObject:role];
+
+ // If the role is "group", include the role description as well.
id roleDescription = [obj roleDescription];
- if (value && ![value isEqual:@""]) {
- description = [NSString stringWithFormat:@"%@ %@", description, value];
- } else if ([description isEqualToString:NSAccessibilityGroupRole] &&
- roleDescription != nil &&
- ![roleDescription isEqualToString:@""]) {
- description = [NSString stringWithFormat:@"%@ %@",
- description, roleDescription];
+ if ([role isEqualToString:NSAccessibilityGroupRole] &&
+ roleDescription != nil &&
+ ![roleDescription isEqualToString:@""]) {
+ [tokens addObject:roleDescription];
}
+
+ // Include the description, title, or value - the first one not empty.
+ id title = [obj title];
+ id description = [obj description];
+ id value = [obj value];
+ if (description && ![description isEqual:@""]) {
+ [tokens addObject:description];
+ } else if (title && ![title isEqual:@""]) {
+ [tokens addObject:title];
+ } else if (value && ![value isEqual:@""]) {
+ [tokens addObject:value];
+ }
+
+ NSString* result = [tokens componentsJoinedByString:@" "];
return scoped_ptr<base::StringValue>(
- new base::StringValue(SysNSStringToUTF16(description))).Pass();
+ new base::StringValue(SysNSStringToUTF16(result))).Pass();
}
scoped_ptr<base::Value> PopulateObject(id value) {
@@ -154,11 +170,14 @@ NSArray* BuildAllAttributesArray() {
NSAccessibilityOrientationAttribute,
@"AXRequired",
NSAccessibilityRowIndexRangeAttribute,
+ NSAccessibilitySelectedChildrenAttribute,
NSAccessibilityTitleUIElementAttribute,
NSAccessibilityURLAttribute,
NSAccessibilityVisibleCharacterRangeAttribute,
+ NSAccessibilityVisibleChildrenAttribute,
@"AXVisited",
@"AXLinkedUIElements",
+ NSAccessibilityExpandedAttribute,
nil];
return [array retain];
}
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
index 5e1d97351e1..02159bca1ad 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_utils_win.cc
@@ -197,6 +197,7 @@ AccessibilityRoleStateMap::AccessibilityRoleStateMap() {
// IAccessible2 states.
IA2_STATE_MAP(IA2_STATE_ACTIVE)
IA2_STATE_MAP(IA2_STATE_ARMED)
+ IA2_STATE_MAP(IA2_STATE_CHECKABLE)
IA2_STATE_MAP(IA2_STATE_DEFUNCT)
IA2_STATE_MAP(IA2_STATE_EDITABLE)
IA2_STATE_MAP(IA2_STATE_ICONIFIED)
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index 76db849ab55..31367b40344 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -207,11 +207,6 @@ base::string16 AccessibilityTreeFormatter::ToString(
dict.GetString("role", &role_value);
WriteAttribute(true, base::UTF16ToUTF8(role_value), &line);
- base::string16 name_value;
- dict.GetString("name", &name_value);
- WriteAttribute(true, base::StringPrintf(L"name='%ls'", name_value.c_str()),
- &line);
-
for (int i = 0; i < arraysize(ALL_ATTRIBUTES); i++) {
const char* attribute_name = ALL_ATTRIBUTES[i];
const base::Value* value;
diff --git a/chromium/content/browser/accessibility/accessibility_ui.cc b/chromium/content/browser/accessibility/accessibility_ui.cc
index 1f4df798f46..a8a5d97ad3e 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.cc
+++ b/chromium/content/browser/accessibility/accessibility_ui.cc
@@ -15,7 +15,9 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_message_enums.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
@@ -25,7 +27,6 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
-#include "grit/content_resources.h"
#include "net/base/escape.h"
static const char kDataFile[] = "targets-data.json";
@@ -63,11 +64,11 @@ base::DictionaryValue* BuildTargetDescriptor(
}
base::DictionaryValue* BuildTargetDescriptor(RenderViewHost* rvh) {
- WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
- std::string title;
- RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rvh);
- AccessibilityMode accessibility_mode = rwhi->accessibility_mode();
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderViewHost(rvh));
+ AccessibilityMode accessibility_mode = web_contents->GetAccessibilityMode();
+ std::string title;
GURL url;
GURL favicon_url;
if (web_contents) {
@@ -116,9 +117,9 @@ bool HandleRequestCallback(BrowserContext* current_context,
scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
data->Set("list", rvh_list.release());
- scoped_ptr<base::FundamentalValue> a11y_mode(base::Value::CreateIntegerValue(
- BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()));
- data->Set("global_a11y_mode", a11y_mode.release());
+ data->SetInteger(
+ "global_a11y_mode",
+ BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
std::string json_string;
base::JSONWriter::Write(data.get(), &json_string);
@@ -133,7 +134,6 @@ AccessibilityUI::AccessibilityUI(WebUI* web_ui) : WebUIController(web_ui) {
// Set up the chrome://accessibility source.
WebUIDataSource* html_source =
WebUIDataSource::Create(kChromeUIAccessibilityHost);
- html_source->SetUseJsonJSFormatV2();
web_ui->RegisterMessageCallback(
"toggleAccessibility",
@@ -178,14 +178,15 @@ void AccessibilityUI::ToggleAccessibility(const base::ListValue* args) {
RenderViewHost* rvh = RenderViewHost::FromID(process_id, route_id);
if (!rvh)
return;
- RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rvh);
- if (!rwhi)
- return;
- AccessibilityMode mode = rwhi->accessibility_mode();
- if ((mode & AccessibilityModeComplete) != AccessibilityModeComplete)
- rwhi->AddAccessibilityMode(AccessibilityModeComplete);
- else
- rwhi->ResetAccessibilityMode();
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderViewHost(rvh));
+ AccessibilityMode mode = web_contents->GetAccessibilityMode();
+ if ((mode & AccessibilityModeComplete) != AccessibilityModeComplete) {
+ web_contents->AddAccessibilityMode(AccessibilityModeComplete);
+ } else {
+ web_contents->SetAccessibilityMode(
+ BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
+ }
}
void AccessibilityUI::ToggleGlobalAccessibility(const base::ListValue* args) {
@@ -220,25 +221,10 @@ void AccessibilityUI::RequestAccessibilityTree(const base::ListValue* args) {
}
scoped_ptr<base::DictionaryValue> result(BuildTargetDescriptor(rvh));
- RenderWidgetHostViewBase* host_view = static_cast<RenderWidgetHostViewBase*>(
- WebContents::FromRenderViewHost(rvh)->GetRenderWidgetHostView());
- if (!host_view) {
- result->Set("error",
- new base::StringValue("Could not get accessibility tree."));
- web_ui()->CallJavascriptFunction("accessibility.showTree", *(result.get()));
- return;
- }
+ WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
scoped_ptr<AccessibilityTreeFormatter> formatter(
- AccessibilityTreeFormatter::Create(rvh));
+ AccessibilityTreeFormatter::Create(web_contents));
base::string16 accessibility_contents_utf16;
- BrowserAccessibilityManager* manager =
- host_view->GetBrowserAccessibilityManager();
- if (!manager) {
- result->Set("error",
- new base::StringValue("Could not get accessibility tree."));
- web_ui()->CallJavascriptFunction("accessibility.showTree", *(result.get()));
- return;
- }
std::vector<AccessibilityTreeFormatter::Filter> filters;
filters.push_back(AccessibilityTreeFormatter::Filter(
base::ASCIIToUTF16("*"),
diff --git a/chromium/content/browser/accessibility/accessibility_ui.h b/chromium/content/browser/accessibility/accessibility_ui.h
index 49227283038..014514a1363 100644
--- a/chromium/content/browser/accessibility/accessibility_ui.h
+++ b/chromium/content/browser/accessibility/accessibility_ui.h
@@ -17,7 +17,7 @@ namespace content {
class AccessibilityUI : public WebUIController {
public:
explicit AccessibilityUI(WebUI* web_ui);
- virtual ~AccessibilityUI();
+ ~AccessibilityUI() override;
private:
void ToggleAccessibility(const base::ListValue* args);
diff --git a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
index a11c026f8ad..058e033ae4e 100644
--- a/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -9,6 +9,7 @@
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_variant.h"
+#include "content/browser/accessibility/accessibility_mode_helper.h"
#include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/notification_service.h"
@@ -399,6 +400,9 @@ base::string16 AccessibleChecker::RoleVariantToString(
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
TestBusyAccessibilityTree) {
+ if (GetBaseAccessibilityMode() != AccessibilityModeOff)
+ return;
+
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
// The initial accessible returned should have state STATE_SYSTEM_BUSY while
@@ -640,8 +644,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
// If you made a change and this test now fails, check that the NativeViewHost
// that wraps the tab contents returns the IAccessible implementation
// provided by RenderWidgetHostViewWin in GetNativeViewAccessible().
+// flaky: http://crbug.com/402190
IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
- ContainsRendererAccessibilityTree) {
+ DISABLED_ContainsRendererAccessibilityTree) {
LoadInitialAccessibilityTreeFromHtml(
"<html><head><title>MyDocument</title></head>"
"<body>Content</body></html>");
diff --git a/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
new file mode 100644
index 00000000000..975da4ceeb8
--- /dev/null
+++ b/chromium/content/browser/accessibility/android_granularity_movement_browsertest.cc
@@ -0,0 +1,209 @@
+// Copyright 2014 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 <set>
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/accessibility/browser_accessibility_android.h"
+#include "content/browser/accessibility/browser_accessibility_manager_android.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+const int GRANULARITY_CHARACTER =
+ ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER;
+const int GRANULARITY_WORD =
+ ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_WORD;
+const int GRANULARITY_LINE =
+ ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_LINE;
+
+class AndroidGranularityMovementBrowserTest : public ContentBrowserTest {
+ public:
+ AndroidGranularityMovementBrowserTest() {}
+ virtual ~AndroidGranularityMovementBrowserTest() {}
+
+ BrowserAccessibility* LoadUrlAndGetAccessibilityRoot(const GURL& url) {
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ // Load the page.
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ // Get the BrowserAccessibilityManager.
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ return web_contents->GetRootBrowserAccessibilityManager()->GetRoot();
+ }
+
+ // First, set accessibility focus to a node and wait for the update that
+ // loads inline text boxes for that node. (We load inline text boxes
+ // asynchronously on Android since we only ever need them for the node
+ // with accessibility focus.)
+ //
+ // Then call NextAtGranularity repeatedly and return a string that
+ // concatenates all of the text of the returned text ranges.
+ //
+ // As an example, if the node's text is "cat dog" and you traverse by
+ // word, this returns "'cat', 'dog'".
+ //
+ // Also calls PreviousAtGranularity from the end back to the beginning
+ // and fails (by logging an error and returning the empty string) if
+ // the result when traversing backwards is not the same
+ // (but in reverse order).
+ base::string16 TraverseNodeAtGranularity(
+ BrowserAccessibility* node,
+ int granularity) {
+ AccessibilityNotificationWaiter waiter(
+ shell(), AccessibilityModeComplete,
+ ui::AX_EVENT_TREE_CHANGED);
+ node->manager()->delegate()->AccessibilitySetAccessibilityFocus(
+ node->GetId());
+ waiter.WaitForNotification();
+
+ int start_index = -1;
+ int end_index = -1;
+ BrowserAccessibilityAndroid* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node);
+ BrowserAccessibilityManagerAndroid* manager =
+ static_cast<BrowserAccessibilityManagerAndroid*>(node->manager());
+ base::string16 text = android_node->GetText();
+ base::string16 concatenated;
+ int previous_end_index = -1;
+ while (manager->NextAtGranularity(
+ granularity, end_index, android_node,
+ &start_index, &end_index)) {
+ int len = (granularity == GRANULARITY_CHARACTER) ?
+ 1 : end_index - start_index;
+ base::string16 selection = text.substr(start_index, len);
+ if (EndsWith(selection, base::ASCIIToUTF16("\n"), false))
+ selection.erase(selection.size() - 1);
+ if (!selection.empty()) {
+ if (!concatenated.empty())
+ concatenated += base::ASCIIToUTF16(", ");
+ concatenated += base::ASCIIToUTF16("'") + selection +
+ base::ASCIIToUTF16("'");
+ }
+
+ // Prevent an endless loop.
+ if (end_index == previous_end_index) {
+ LOG(ERROR) << "Bailing from loop, NextAtGranularity didn't advance";
+ break;
+ }
+ previous_end_index = end_index;
+ }
+
+ base::string16 reverse;
+ previous_end_index = -1;
+ start_index = end_index;
+ while (manager->PreviousAtGranularity(
+ granularity, start_index, android_node, &start_index, &end_index)) {
+ int len = (granularity == GRANULARITY_CHARACTER) ?
+ 1 : end_index - start_index;
+ base::string16 selection = text.substr(start_index, len);
+ if (EndsWith(selection, base::ASCIIToUTF16("\n"), false))
+ selection = selection.substr(0, selection.size() - 1);
+ if (!reverse.empty())
+ reverse = base::ASCIIToUTF16(", ") + reverse;
+ reverse = base::ASCIIToUTF16("'") + selection +
+ base::ASCIIToUTF16("'") + reverse;
+
+ // Prevent an endless loop.
+ if (end_index == previous_end_index) {
+ LOG(ERROR) << "Bailing from loop, PreviousAtGranularity didn't advance";
+ break;
+ }
+ previous_end_index = end_index;
+ }
+
+ if (concatenated != reverse) {
+ LOG(ERROR) << "Did not get the same sequence in the forwards and "
+ << "reverse directions!";
+ LOG(ERROR) << "Forwards: " << concatenated;
+ LOG(ERROR) << "Backwards " << reverse;
+ return base::string16();
+ }
+
+ return concatenated;
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest,
+ NavigateByCharacters) {
+ GURL url("data:text/html,"
+ "<body>"
+ "<p>One, two, three!</p>"
+ "<button aria-label='Seven, eight, nine!'>Four, five, six!</button>"
+ "</body></html>");
+ BrowserAccessibility* root = LoadUrlAndGetAccessibilityRoot(url);
+ ASSERT_EQ(2U, root->PlatformChildCount());
+ BrowserAccessibility* para = root->PlatformGetChild(0);
+ ASSERT_EQ(0U, para->PlatformChildCount());
+ BrowserAccessibility* button_container = root->PlatformGetChild(1);
+ ASSERT_EQ(1U, button_container->PlatformChildCount());
+ BrowserAccessibility* button = button_container->PlatformGetChild(0);
+ ASSERT_EQ(0U, button->PlatformChildCount());
+
+ ASSERT_EQ(
+ base::ASCIIToUTF16("'O', 'n', 'e', ',', ' ', 't', 'w', 'o', "
+ "',', ' ', 't', 'h', 'r', 'e', 'e', '!'"),
+ TraverseNodeAtGranularity(para, GRANULARITY_CHARACTER));
+ ASSERT_EQ(
+ base::ASCIIToUTF16("'S', 'e', 'v', 'e', 'n', ',', ' ', 'e', 'i', 'g', "
+ "'h', 't', ',', ' ', 'n', 'i', 'n', 'e', '!'"),
+ TraverseNodeAtGranularity(button, GRANULARITY_CHARACTER));
+}
+
+IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest,
+ NavigateByWords) {
+ GURL url("data:text/html,"
+ "<body>"
+ "<p>One, two, three!</p>"
+ "<button aria-label='Seven, eight, nine!'>Four, five, six!</button>"
+ "</body></html>");
+ BrowserAccessibility* root = LoadUrlAndGetAccessibilityRoot(url);
+ ASSERT_EQ(2U, root->PlatformChildCount());
+ BrowserAccessibility* para = root->PlatformGetChild(0);
+ ASSERT_EQ(0U, para->PlatformChildCount());
+ BrowserAccessibility* button_container = root->PlatformGetChild(1);
+ ASSERT_EQ(1U, button_container->PlatformChildCount());
+ BrowserAccessibility* button = button_container->PlatformGetChild(0);
+ ASSERT_EQ(0U, button->PlatformChildCount());
+
+ ASSERT_EQ(base::ASCIIToUTF16("'One', 'two', 'three'"),
+ TraverseNodeAtGranularity(para, GRANULARITY_WORD));
+ ASSERT_EQ(base::ASCIIToUTF16("'Seven', 'eight', 'nine'"),
+ TraverseNodeAtGranularity(button, GRANULARITY_WORD));
+}
+
+IN_PROC_BROWSER_TEST_F(AndroidGranularityMovementBrowserTest,
+ NavigateByLine) {
+ GURL url("data:text/html,"
+ "<body>"
+ "<pre>One,%0dtwo,%0dthree!</pre>"
+ "</body>");
+ BrowserAccessibility* root = LoadUrlAndGetAccessibilityRoot(url);
+ ASSERT_EQ(1U, root->PlatformChildCount());
+ BrowserAccessibility* pre = root->PlatformGetChild(0);
+ ASSERT_EQ(0U, pre->PlatformChildCount());
+
+ ASSERT_EQ(base::ASCIIToUTF16("'One,', 'two,', 'three!'"),
+ TraverseNodeAtGranularity(pre, GRANULARITY_LINE));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc b/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc
index 1070f6e63f2..f483286f7ca 100644
--- a/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc
+++ b/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc
@@ -7,9 +7,8 @@
#include <vector>
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/path_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -17,8 +16,7 @@
#include "content/browser/accessibility/accessibility_tree_formatter.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
@@ -59,10 +57,10 @@ IN_PROC_BROWSER_TEST_F(AndroidHitTestingBrowserTest,
waiter.WaitForNotification();
// Get the BrowserAccessibilityManager.
- RenderWidgetHostViewBase* host_view = static_cast<RenderWidgetHostViewBase*>(
- shell()->web_contents()->GetRenderWidgetHostView());
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
BrowserAccessibilityManager* manager =
- host_view->GetBrowserAccessibilityManager();
+ web_contents->GetRootBrowserAccessibilityManager();
// Send a hit test request, and wait for the hover event in response.
AccessibilityNotificationWaiter hover_waiter(
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index fe71fef965a..a700e9a9fd3 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -84,7 +84,16 @@ bool BrowserAccessibility::IsDescendantOf(
BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
uint32 child_index) const {
DCHECK(child_index < InternalChildCount());
- return InternalGetChild(child_index);
+ BrowserAccessibility* result = InternalGetChild(child_index);
+
+ if (result->HasBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
+ BrowserAccessibilityManager* child_manager =
+ manager_->delegate()->AccessibilityGetChildFrame(result->GetId());
+ if (child_manager)
+ result = child_manager->GetRoot();
+ }
+
+ return result;
}
BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() {
@@ -122,7 +131,18 @@ BrowserAccessibility* BrowserAccessibility::GetParent() const {
if (!node_ || !manager_)
return NULL;
ui::AXNode* parent = node_->parent();
- return parent ? manager_->GetFromAXNode(parent) : NULL;
+ if (parent)
+ return manager_->GetFromAXNode(parent);
+
+ if (!manager_->delegate())
+ return NULL;
+
+ BrowserAccessibility* host_node =
+ manager_->delegate()->AccessibilityGetParentFrame();
+ if (!host_node)
+ return NULL;
+
+ return host_node->GetParent();
}
int32 BrowserAccessibility::GetIndexInParent() const {
@@ -153,7 +173,7 @@ int32 BrowserAccessibility::GetState() const {
return GetData().state;
}
-const std::vector<std::pair<std::string, std::string> >&
+const BrowserAccessibility::HtmlAttributes&
BrowserAccessibility::GetHtmlAttributes() const {
return GetData().html_attributes;
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index 17f70caf675..6318e64b53d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/strings/string16.h"
+#include "base/strings/string_split.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
@@ -31,12 +32,13 @@ class BrowserAccessibilityWin;
//
// BrowserAccessibility
//
-// Class implementing the cross platform interface for the Browser-Renderer
-// communication of accessibility information, providing accessibility
-// to be used by screen readers and other assistive technology (AT).
+// A BrowserAccessibility object represents one node in the accessibility
+// tree on the browser side. It exactly corresponds to one WebAXObject from
+// Blink. It's owned by a BrowserAccessibilityManager.
//
-// An implementation for each platform handles platform specific accessibility
-// APIs.
+// There are subclasses of BrowserAccessibility for each platform where
+// we implement native accessibility APIs. This base class is used occasionally
+// for tests.
//
////////////////////////////////////////////////////////////////////////////////
class CONTENT_EXPORT BrowserAccessibility {
@@ -65,7 +67,7 @@ class CONTENT_EXPORT BrowserAccessibility {
virtual bool IsNative() const;
// Called when the location changed.
- virtual void OnLocationChanged() const {}
+ virtual void OnLocationChanged() {}
// Return true if this object is equal to or a descendant of |ancestor|.
bool IsDescendantOf(BrowserAccessibility* ancestor);
@@ -159,7 +161,7 @@ class CONTENT_EXPORT BrowserAccessibility {
int32 GetRole() const;
int32 GetState() const;
- typedef std::vector<std::pair<std::string, std::string> > HtmlAttributes;
+ typedef base::StringPairs HtmlAttributes;
const HtmlAttributes& GetHtmlAttributes() const;
#if defined(OS_MACOSX) && __OBJC__
@@ -262,7 +264,6 @@ class CONTENT_EXPORT BrowserAccessibility {
std::string name_;
std::string value_;
- private:
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibility);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 8a8514a0d80..53189cbf1d1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -4,6 +4,9 @@
#include "content/browser/accessibility/browser_accessibility_android.h"
+#include "base/i18n/break_iterator.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/common/accessibility_messages.h"
@@ -55,6 +58,10 @@ bool BrowserAccessibilityAndroid::IsNative() const {
return true;
}
+void BrowserAccessibilityAndroid::OnLocationChanged() {
+ manager()->NotifyAccessibilityEvent(ui::AX_EVENT_LOCATION_CHANGED, this);
+}
+
bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
if (InternalChildCount() == 0)
return true;
@@ -70,6 +77,10 @@ bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
if (HasFocusableChild())
return false;
+ // Date and time controls should drop their children.
+ if (GetRole() == ui::AX_ROLE_DATE || GetRole() == ui::AX_ROLE_TIME)
+ return true;
+
// Headings with text can drop their children.
base::string16 name = GetText();
if (GetRole() == ui::AX_ROLE_HEADING && !name.empty())
@@ -86,6 +97,24 @@ bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
return BrowserAccessibility::PlatformIsLeaf();
}
+bool BrowserAccessibilityAndroid::CanScrollForward() const {
+ if (!IsSlider())
+ return false;
+
+ float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
+ float max = GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE);
+ return value < max;
+}
+
+bool BrowserAccessibilityAndroid::CanScrollBackward() const {
+ if (!IsSlider())
+ return false;
+
+ float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
+ float min = GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE);
+ return value > min;
+}
+
bool BrowserAccessibilityAndroid::IsCheckable() const {
bool checkable = false;
bool is_aria_pressed_defined;
@@ -93,6 +122,8 @@ bool BrowserAccessibilityAndroid::IsCheckable() const {
GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed);
if (GetRole() == ui::AX_ROLE_CHECK_BOX ||
GetRole() == ui::AX_ROLE_RADIO_BUTTON ||
+ GetRole() == ui::AX_ROLE_MENU_ITEM_CHECK_BOX ||
+ GetRole() == ui::AX_ROLE_MENU_ITEM_RADIO ||
is_aria_pressed_defined) {
checkable = true;
}
@@ -113,6 +144,7 @@ bool BrowserAccessibilityAndroid::IsCollection() const {
return (GetRole() == ui::AX_ROLE_GRID ||
GetRole() == ui::AX_ROLE_LIST ||
GetRole() == ui::AX_ROLE_LIST_BOX ||
+ GetRole() == ui::AX_ROLE_DESCRIPTION_LIST ||
GetRole() == ui::AX_ROLE_TABLE ||
GetRole() == ui::AX_ROLE_TREE);
}
@@ -136,6 +168,12 @@ bool BrowserAccessibilityAndroid::IsDismissable() const {
return false; // No concept of "dismissable" on the web currently.
}
+bool BrowserAccessibilityAndroid::IsEditableText() const {
+ return (GetRole() == ui::AX_ROLE_EDITABLE_TEXT ||
+ GetRole() == ui::AX_ROLE_TEXT_AREA ||
+ GetRole() == ui::AX_ROLE_TEXT_FIELD);
+}
+
bool BrowserAccessibilityAndroid::IsEnabled() const {
return HasState(ui::AX_STATE_ENABLED);
}
@@ -161,6 +199,7 @@ bool BrowserAccessibilityAndroid::IsHeading() const {
bool BrowserAccessibilityAndroid::IsHierarchical() const {
return (GetRole() == ui::AX_ROLE_LIST ||
+ GetRole() == ui::AX_ROLE_DESCRIPTION_LIST ||
GetRole() == ui::AX_ROLE_TREE);
}
@@ -192,6 +231,10 @@ bool BrowserAccessibilityAndroid::IsSelected() const {
return HasState(ui::AX_STATE_SELECTED);
}
+bool BrowserAccessibilityAndroid::IsSlider() const {
+ return GetRole() == ui::AX_ROLE_SLIDER;
+}
+
bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
return !HasState(ui::AX_STATE_INVISIBLE);
}
@@ -213,12 +256,15 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
case ui::AX_ROLE_SLIDER:
class_name = "android.widget.SeekBar";
break;
+ case ui::AX_ROLE_COLOR_WELL:
case ui::AX_ROLE_COMBO_BOX:
+ case ui::AX_ROLE_DATE:
+ case ui::AX_ROLE_POP_UP_BUTTON:
+ case ui::AX_ROLE_TIME:
class_name = "android.widget.Spinner";
break;
case ui::AX_ROLE_BUTTON:
case ui::AX_ROLE_MENU_BUTTON:
- case ui::AX_ROLE_POP_UP_BUTTON:
class_name = "android.widget.Button";
break;
case ui::AX_ROLE_CHECK_BOX:
@@ -232,8 +278,10 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
break;
case ui::AX_ROLE_CANVAS:
case ui::AX_ROLE_IMAGE:
+ case ui::AX_ROLE_SVG_ROOT:
class_name = "android.widget.Image";
break;
+ case ui::AX_ROLE_METER:
case ui::AX_ROLE_PROGRESS_INDICATOR:
class_name = "android.widget.ProgressBar";
break;
@@ -246,6 +294,7 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
break;
case ui::AX_ROLE_LIST:
case ui::AX_ROLE_LIST_BOX:
+ case ui::AX_ROLE_DESCRIPTION_LIST:
class_name = "android.widget.ListView";
break;
case ui::AX_ROLE_DIALOG:
@@ -254,6 +303,11 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
case ui::AX_ROLE_ROOT_WEB_AREA:
class_name = "android.webkit.WebView";
break;
+ case ui::AX_ROLE_MENU_ITEM:
+ case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ case ui::AX_ROLE_MENU_ITEM_RADIO:
+ class_name = "android.view.MenuItem";
+ break;
default:
class_name = "android.view.View";
break;
@@ -271,15 +325,59 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
// See comment in browser_accessibility_win.cc for details.
// The difference here is that we can only expose one accessible
// name on Android, not 2 or 3 like on Windows or Mac.
- //
- // The basic rule is: prefer description (aria-labelledby or aria-label),
- // then help (title), then name (inner text), then value (control value).
- // However, if title_elem_id is set, that means there's a label element
+
+ // First, always return the |value| attribute if this is an
+ // input field.
+ if (!value().empty()) {
+ if (HasState(ui::AX_STATE_EDITABLE))
+ return base::UTF8ToUTF16(value());
+
+ switch (GetRole()) {
+ case ui::AX_ROLE_COMBO_BOX:
+ case ui::AX_ROLE_EDITABLE_TEXT:
+ case ui::AX_ROLE_POP_UP_BUTTON:
+ case ui::AX_ROLE_TEXT_AREA:
+ case ui::AX_ROLE_TEXT_FIELD:
+ return base::UTF8ToUTF16(value());
+ }
+ }
+
+ // For color wells, the color is stored in separate attributes.
+ // Perhaps we could return color names in the future?
+ if (GetRole() == ui::AX_ROLE_COLOR_WELL) {
+ int red = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_RED);
+ int green = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_GREEN);
+ int blue = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_BLUE);
+ return base::UTF8ToUTF16(
+ base::StringPrintf("#%02X%02X%02X", red, green, blue));
+ }
+
+ // Always prefer visible text if this is a link. Sites sometimes add
+ // a "title" attribute to a link with more information, but we can't
+ // lose the link text.
+ if (!name().empty() && GetRole() == ui::AX_ROLE_LINK)
+ return base::UTF8ToUTF16(name());
+
+ // If there's no text value, the basic rule is: prefer description
+ // (aria-labelledby or aria-label), then help (title), then name
+ // (inner text), then value (control value). However, if
+ // title_elem_id is set, that means there's a label element
// supplying the name and then name takes precedence over help.
// TODO(dmazzoni): clean this up by providing more granular labels in
// Blink, making the platform-specific mapping to accessible text simpler.
base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
base::string16 help = GetString16Attribute(ui::AX_ATTR_HELP);
+
+ base::string16 placeholder;
+ switch (GetRole()) {
+ case ui::AX_ROLE_DATE:
+ case ui::AX_ROLE_EDITABLE_TEXT:
+ case ui::AX_ROLE_TEXT_AREA:
+ case ui::AX_ROLE_TEXT_FIELD:
+ case ui::AX_ROLE_TIME:
+ GetHtmlAttribute("placeholder", &placeholder);
+ }
+
int title_elem_id = GetIntAttribute(
ui::AX_ATTR_TITLE_UI_ELEMENT);
base::string16 text;
@@ -291,27 +389,23 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
text = help;
else if (!name().empty())
text = base::UTF8ToUTF16(name());
+ else if (!placeholder.empty())
+ text = placeholder;
else if (!value().empty())
text = base::UTF8ToUTF16(value());
// This is called from PlatformIsLeaf, so don't call PlatformChildCount
// from within this!
- if (text.empty() && HasOnlyStaticTextChildren()) {
+ if (text.empty() &&
+ (HasOnlyStaticTextChildren() ||
+ (IsFocusable() && HasOnlyTextAndImageChildren()))) {
for (uint32 i = 0; i < InternalChildCount(); i++) {
BrowserAccessibility* child = InternalGetChild(i);
text += static_cast<BrowserAccessibilityAndroid*>(child)->GetText();
}
}
- switch(GetRole()) {
- case ui::AX_ROLE_HEADING:
- // Only append "heading" if this node already has text.
- if (!text.empty())
- text += base::ASCIIToUTF16(" Heading");
- break;
- }
-
- if (text.empty() && IsLink()) {
+ if (text.empty() && (IsLink() || GetRole() == ui::AX_ROLE_IMAGE)) {
base::string16 url = GetString16Attribute(ui::AX_ATTR_URL);
// Given a url like http://foo.com/bar/baz.png, just return the
// base name, e.g., "baz".
@@ -344,11 +438,13 @@ int BrowserAccessibilityAndroid::GetItemIndex() const {
break;
case ui::AX_ROLE_SLIDER:
case ui::AX_ROLE_PROGRESS_INDICATOR: {
- float value_for_range;
- if (GetFloatAttribute(
- ui::AX_ATTR_VALUE_FOR_RANGE, &value_for_range)) {
- index = static_cast<int>(value_for_range);
- }
+ // Return a percentage here for live feedback in an AccessibilityEvent.
+ // The exact value is returned in RangeCurrentValue.
+ float min = GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE);
+ float max = GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE);
+ float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
+ if (max > min && value >= min && value <= max)
+ index = static_cast<int>(((value - min)) * 100 / (max - min));
break;
}
}
@@ -360,17 +456,16 @@ int BrowserAccessibilityAndroid::GetItemCount() const {
switch(GetRole()) {
case ui::AX_ROLE_LIST:
case ui::AX_ROLE_LIST_BOX:
+ case ui::AX_ROLE_DESCRIPTION_LIST:
count = PlatformChildCount();
break;
case ui::AX_ROLE_SLIDER:
- case ui::AX_ROLE_PROGRESS_INDICATOR: {
- float max_value_for_range;
- if (GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE,
- &max_value_for_range)) {
- count = static_cast<int>(max_value_for_range);
- }
+ case ui::AX_ROLE_PROGRESS_INDICATOR:
+ // An AccessibilityEvent can only return integer information about a
+ // seek control, so we return a percentage. The real range is returned
+ // in RangeMin and RangeMax.
+ count = 100;
break;
- }
}
return count;
}
@@ -523,6 +618,7 @@ int BrowserAccessibilityAndroid::RowCount() const {
if (GetRole() == ui::AX_ROLE_LIST ||
GetRole() == ui::AX_ROLE_LIST_BOX ||
+ GetRole() == ui::AX_ROLE_DESCRIPTION_LIST ||
GetRole() == ui::AX_ROLE_TREE) {
return PlatformChildCount();
}
@@ -572,6 +668,116 @@ float BrowserAccessibilityAndroid::RangeCurrentValue() const {
return GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
}
+void BrowserAccessibilityAndroid::GetGranularityBoundaries(
+ int granularity,
+ std::vector<int32>* starts,
+ std::vector<int32>* ends,
+ int offset) {
+ switch (granularity) {
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_LINE:
+ GetLineBoundaries(starts, ends, offset);
+ break;
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_WORD:
+ GetWordBoundaries(starts, ends, offset);
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void BrowserAccessibilityAndroid::GetLineBoundaries(
+ std::vector<int32>* line_starts,
+ std::vector<int32>* line_ends,
+ int offset) {
+ // If this node has no children, treat it as all one line.
+ if (GetText().size() > 0 && !InternalChildCount()) {
+ line_starts->push_back(offset);
+ line_ends->push_back(offset + GetText().size());
+ }
+
+ // If this is a static text node, get the line boundaries from the
+ // inline text boxes if possible.
+ if (GetRole() == ui::AX_ROLE_STATIC_TEXT) {
+ int last_y = 0;
+ for (uint32 i = 0; i < InternalChildCount(); i++) {
+ BrowserAccessibilityAndroid* child =
+ static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
+ CHECK_EQ(ui::AX_ROLE_INLINE_TEXT_BOX, child->GetRole());
+ // TODO(dmazzoni): replace this with a proper API to determine
+ // if two inline text boxes are on the same line. http://crbug.com/421771
+ int y = child->GetLocation().y();
+ if (i == 0) {
+ line_starts->push_back(offset);
+ } else if (y != last_y) {
+ line_ends->push_back(offset);
+ line_starts->push_back(offset);
+ }
+ offset += child->GetText().size();
+ last_y = y;
+ }
+ line_ends->push_back(offset);
+ return;
+ }
+
+ // Otherwise, call GetLineBoundaries recursively on the children.
+ for (uint32 i = 0; i < InternalChildCount(); i++) {
+ BrowserAccessibilityAndroid* child =
+ static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
+ child->GetLineBoundaries(line_starts, line_ends, offset);
+ offset += child->GetText().size();
+ }
+}
+
+void BrowserAccessibilityAndroid::GetWordBoundaries(
+ std::vector<int32>* word_starts,
+ std::vector<int32>* word_ends,
+ int offset) {
+ if (GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX) {
+ const std::vector<int32>& starts = GetIntListAttribute(
+ ui::AX_ATTR_WORD_STARTS);
+ const std::vector<int32>& ends = GetIntListAttribute(
+ ui::AX_ATTR_WORD_ENDS);
+ for (size_t i = 0; i < starts.size(); ++i) {
+ word_starts->push_back(offset + starts[i]);
+ word_ends->push_back(offset + ends[i]);
+ }
+ return;
+ }
+
+ base::string16 concatenated_text;
+ for (uint32 i = 0; i < InternalChildCount(); i++) {
+ BrowserAccessibilityAndroid* child =
+ static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
+ base::string16 child_text = child->GetText();
+ concatenated_text += child->GetText();
+ }
+
+ base::string16 text = GetText();
+ if (text.empty() || concatenated_text == text) {
+ // Great - this node is just the concatenation of its children, so
+ // we can get the word boundaries recursively.
+ for (uint32 i = 0; i < InternalChildCount(); i++) {
+ BrowserAccessibilityAndroid* child =
+ static_cast<BrowserAccessibilityAndroid*>(InternalGetChild(i));
+ child->GetWordBoundaries(word_starts, word_ends, offset);
+ offset += child->GetText().size();
+ }
+ } else {
+ // This node has its own accessible text that doesn't match its
+ // visible text - like alt text for an image or something with an
+ // aria-label, so split the text into words locally.
+ base::i18n::BreakIterator iter(text, base::i18n::BreakIterator::BREAK_WORD);
+ if (!iter.Init())
+ return;
+ while (iter.Advance()) {
+ if (iter.IsWord()) {
+ word_starts->push_back(iter.prev());
+ word_ends->push_back(iter.pos());
+ }
+ }
+ }
+}
+
bool BrowserAccessibilityAndroid::HasFocusableChild() const {
// This is called from PlatformIsLeaf, so don't call PlatformChildCount
// from within this!
@@ -596,6 +802,19 @@ bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const {
return true;
}
+bool BrowserAccessibilityAndroid::HasOnlyTextAndImageChildren() const {
+ // This is called from PlatformIsLeaf, so don't call PlatformChildCount
+ // from within this!
+ for (uint32 i = 0; i < InternalChildCount(); i++) {
+ BrowserAccessibility* child = InternalGetChild(i);
+ if (child->GetRole() != ui::AX_ROLE_STATIC_TEXT &&
+ child->GetRole() != ui::AX_ROLE_IMAGE) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool BrowserAccessibilityAndroid::IsIframe() const {
base::string16 html_tag = GetString16Attribute(
ui::AX_ATTR_HTML_TAG);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index f78a96dd54d..70579ab9b85 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -10,14 +10,17 @@
namespace content {
-class BrowserAccessibilityAndroid : public BrowserAccessibility {
+class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
public:
// Overrides from BrowserAccessibility.
- virtual void OnDataChanged() OVERRIDE;
- virtual bool IsNative() const OVERRIDE;
+ virtual void OnDataChanged() override;
+ virtual bool IsNative() const override;
+ virtual void OnLocationChanged() override;
- virtual bool PlatformIsLeaf() const OVERRIDE;
+ virtual bool PlatformIsLeaf() const override;
+ bool CanScrollForward() const;
+ bool CanScrollBackward() const;
bool IsCheckable() const;
bool IsChecked() const;
bool IsClickable() const;
@@ -25,6 +28,7 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
bool IsCollectionItem() const;
bool IsContentInvalid() const;
bool IsDismissable() const;
+ bool IsEditableText() const;
bool IsEnabled() const;
bool IsFocusable() const;
bool IsFocused() const;
@@ -36,6 +40,7 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
bool IsRangeType() const;
bool IsScrollable() const;
bool IsSelected() const;
+ bool IsSlider() const;
bool IsVisibleToUser() const;
bool CanOpenPopup() const;
@@ -78,6 +83,26 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
float RangeMax() const;
float RangeCurrentValue() const;
+ // Calls GetLineBoundaries or GetWordBoundaries depending on the value
+ // of |granularity|, or fails if anything else is passed in |granularity|.
+ void GetGranularityBoundaries(int granularity,
+ std::vector<int32>* starts,
+ std::vector<int32>* ends,
+ int offset);
+
+ // Append line start and end indices for the text of this node
+ // (as returned by GetText()), adding |offset| to each one.
+ void GetLineBoundaries(std::vector<int32>* line_starts,
+ std::vector<int32>* line_ends,
+ int offset);
+
+ // Append word start and end indices for the text of this node
+ // (as returned by GetText()) to |word_starts| and |word_ends|,
+ // adding |offset| to each one.
+ void GetWordBoundaries(std::vector<int32>* word_starts,
+ std::vector<int32>* word_ends,
+ int offset);
+
private:
// This gives BrowserAccessibility::Create access to the class constructor.
friend class BrowserAccessibility;
@@ -85,6 +110,7 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility {
BrowserAccessibilityAndroid();
bool HasOnlyStaticTextChildren() const;
+ bool HasOnlyTextAndImageChildren() const;
bool IsIframe() const;
void NotifyLiveRegionUpdate(base::string16& aria_live);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index 5fc708f867b..0f01a7a8777 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -95,6 +95,7 @@
@property(nonatomic, readonly) NSArray* rowHeaders;
@property(nonatomic, readonly) NSValue* rowIndexRange;
@property(nonatomic, readonly) NSArray* rows;
+@property(nonatomic, readonly) NSArray* selectedChildren;
// The size of this object.
@property(nonatomic, readonly) NSValue* size;
// A string indicating the subrole of this object as far as accessibility
@@ -109,6 +110,7 @@
@property(nonatomic, readonly) NSString* valueDescription;
@property(nonatomic, readonly) NSValue* visibleCharacterRange;
@property(nonatomic, readonly) NSArray* visibleCells;
+@property(nonatomic, readonly) NSArray* visibleChildren;
@property(nonatomic, readonly) NSArray* visibleColumns;
@property(nonatomic, readonly) NSArray* visibleRows;
@property(nonatomic, readonly) NSNumber* visited;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 232e4827750..ac81de7ab39 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -12,10 +12,11 @@
#include "base/strings/string16.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/app/strings/grit/content_strings.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "content/public/common/content_client.h"
-#include "grit/webkit_strings.h"
+#import "ui/accessibility/platform/ax_platform_node_mac.h"
// See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5,
// 10.6, and 10.7. It allows accessibility clients to observe events posted on
@@ -39,197 +40,12 @@ NSString* NSStringForStringAttribute(
browserAccessibility->GetStringAttribute(attribute));
}
-struct MapEntry {
- ui::AXRole webKitValue;
- NSString* nativeValue;
-};
-
-typedef std::map<ui::AXRole, NSString*> RoleMap;
-
// GetState checks the bitmask used in AXNodeData to check
// if the given state was set on the accessibility object.
bool GetState(BrowserAccessibility* accessibility, ui::AXState state) {
return ((accessibility->GetState() >> state) & 1);
}
-RoleMap BuildRoleMap() {
- const MapEntry roles[] = {
- { ui::AX_ROLE_ALERT, NSAccessibilityGroupRole },
- { ui::AX_ROLE_ALERT_DIALOG, NSAccessibilityGroupRole },
- { ui::AX_ROLE_ANNOTATION, NSAccessibilityUnknownRole },
- { ui::AX_ROLE_APPLICATION, NSAccessibilityGroupRole },
- { ui::AX_ROLE_ARTICLE, NSAccessibilityGroupRole },
- { ui::AX_ROLE_BANNER, NSAccessibilityGroupRole },
- { ui::AX_ROLE_BROWSER, NSAccessibilityBrowserRole },
- { ui::AX_ROLE_BUSY_INDICATOR, NSAccessibilityBusyIndicatorRole },
- { ui::AX_ROLE_BUTTON, NSAccessibilityButtonRole },
- { ui::AX_ROLE_CANVAS, NSAccessibilityImageRole },
- { ui::AX_ROLE_CELL, @"AXCell" },
- { ui::AX_ROLE_CHECK_BOX, NSAccessibilityCheckBoxRole },
- { ui::AX_ROLE_COLOR_WELL, NSAccessibilityColorWellRole },
- { ui::AX_ROLE_COLUMN, NSAccessibilityColumnRole },
- { ui::AX_ROLE_COLUMN_HEADER, @"AXCell" },
- { ui::AX_ROLE_COMBO_BOX, NSAccessibilityComboBoxRole },
- { ui::AX_ROLE_COMPLEMENTARY, NSAccessibilityGroupRole },
- { ui::AX_ROLE_CONTENT_INFO, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DEFINITION, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DESCRIPTION_LIST_DETAIL, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DESCRIPTION_LIST_TERM, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DIALOG, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DIRECTORY, NSAccessibilityListRole },
- { ui::AX_ROLE_DISCLOSURE_TRIANGLE, NSAccessibilityDisclosureTriangleRole },
- { ui::AX_ROLE_DIV, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DOCUMENT, NSAccessibilityGroupRole },
- { ui::AX_ROLE_DRAWER, NSAccessibilityDrawerRole },
- { ui::AX_ROLE_EDITABLE_TEXT, NSAccessibilityTextFieldRole },
- { ui::AX_ROLE_FOOTER, NSAccessibilityGroupRole },
- { ui::AX_ROLE_FORM, NSAccessibilityGroupRole },
- { ui::AX_ROLE_GRID, NSAccessibilityGridRole },
- { ui::AX_ROLE_GROUP, NSAccessibilityGroupRole },
- { ui::AX_ROLE_GROW_AREA, NSAccessibilityGrowAreaRole },
- { ui::AX_ROLE_HEADING, @"AXHeading" },
- { ui::AX_ROLE_HELP_TAG, NSAccessibilityHelpTagRole },
- { ui::AX_ROLE_HORIZONTAL_RULE, NSAccessibilityGroupRole },
- { ui::AX_ROLE_IFRAME, NSAccessibilityGroupRole },
- { ui::AX_ROLE_IGNORED, NSAccessibilityUnknownRole },
- { ui::AX_ROLE_IMAGE, NSAccessibilityImageRole },
- { ui::AX_ROLE_IMAGE_MAP, NSAccessibilityGroupRole },
- { ui::AX_ROLE_IMAGE_MAP_LINK, NSAccessibilityLinkRole },
- { ui::AX_ROLE_INCREMENTOR, NSAccessibilityIncrementorRole },
- { ui::AX_ROLE_LABEL_TEXT, NSAccessibilityGroupRole },
- { ui::AX_ROLE_LINK, NSAccessibilityLinkRole },
- { ui::AX_ROLE_LIST, NSAccessibilityListRole },
- { ui::AX_ROLE_LIST_BOX, NSAccessibilityListRole },
- { ui::AX_ROLE_LIST_BOX_OPTION, NSAccessibilityStaticTextRole },
- { ui::AX_ROLE_LIST_ITEM, NSAccessibilityGroupRole },
- { ui::AX_ROLE_LIST_MARKER, @"AXListMarker" },
- { ui::AX_ROLE_LOG, NSAccessibilityGroupRole },
- { ui::AX_ROLE_MAIN, NSAccessibilityGroupRole },
- { ui::AX_ROLE_MARQUEE, NSAccessibilityGroupRole },
- { ui::AX_ROLE_MATH, NSAccessibilityGroupRole },
- { ui::AX_ROLE_MATTE, NSAccessibilityMatteRole },
- { ui::AX_ROLE_MENU, NSAccessibilityMenuRole },
- { ui::AX_ROLE_MENU_BAR, NSAccessibilityMenuBarRole },
- { ui::AX_ROLE_MENU_BUTTON, NSAccessibilityButtonRole },
- { ui::AX_ROLE_MENU_ITEM, NSAccessibilityMenuItemRole },
- { ui::AX_ROLE_MENU_LIST_OPTION, NSAccessibilityMenuItemRole },
- { ui::AX_ROLE_MENU_LIST_POPUP, NSAccessibilityUnknownRole },
- { ui::AX_ROLE_NAVIGATION, NSAccessibilityGroupRole },
- { ui::AX_ROLE_NOTE, NSAccessibilityGroupRole },
- { ui::AX_ROLE_OUTLINE, NSAccessibilityOutlineRole },
- { ui::AX_ROLE_PARAGRAPH, NSAccessibilityGroupRole },
- { ui::AX_ROLE_POP_UP_BUTTON, NSAccessibilityPopUpButtonRole },
- { ui::AX_ROLE_PRESENTATIONAL, NSAccessibilityGroupRole },
- { ui::AX_ROLE_PROGRESS_INDICATOR, NSAccessibilityProgressIndicatorRole },
- { ui::AX_ROLE_RADIO_BUTTON, NSAccessibilityRadioButtonRole },
- { ui::AX_ROLE_RADIO_GROUP, NSAccessibilityRadioGroupRole },
- { ui::AX_ROLE_REGION, NSAccessibilityGroupRole },
- { ui::AX_ROLE_ROOT_WEB_AREA, @"AXWebArea" },
- { ui::AX_ROLE_ROW, NSAccessibilityRowRole },
- { ui::AX_ROLE_ROW_HEADER, @"AXCell" },
- { ui::AX_ROLE_RULER, NSAccessibilityRulerRole },
- { ui::AX_ROLE_RULER_MARKER, NSAccessibilityRulerMarkerRole },
- { ui::AX_ROLE_SCROLL_BAR, NSAccessibilityScrollBarRole },
- { ui::AX_ROLE_SEARCH, NSAccessibilityGroupRole },
- { ui::AX_ROLE_SHEET, NSAccessibilitySheetRole },
- { ui::AX_ROLE_SLIDER, NSAccessibilitySliderRole },
- { ui::AX_ROLE_SLIDER_THUMB, NSAccessibilityValueIndicatorRole },
- { ui::AX_ROLE_SPIN_BUTTON, NSAccessibilitySliderRole },
- { ui::AX_ROLE_SPLITTER, NSAccessibilitySplitterRole },
- { ui::AX_ROLE_SPLIT_GROUP, NSAccessibilitySplitGroupRole },
- { ui::AX_ROLE_STATIC_TEXT, NSAccessibilityStaticTextRole },
- { ui::AX_ROLE_STATUS, NSAccessibilityGroupRole },
- { ui::AX_ROLE_SVG_ROOT, NSAccessibilityGroupRole },
- { ui::AX_ROLE_SYSTEM_WIDE, NSAccessibilityUnknownRole },
- { ui::AX_ROLE_TAB, NSAccessibilityRadioButtonRole },
- { ui::AX_ROLE_TABLE, NSAccessibilityTableRole },
- { ui::AX_ROLE_TABLE_HEADER_CONTAINER, NSAccessibilityGroupRole },
- { ui::AX_ROLE_TAB_LIST, NSAccessibilityTabGroupRole },
- { ui::AX_ROLE_TAB_PANEL, NSAccessibilityGroupRole },
- { ui::AX_ROLE_TEXT_AREA, NSAccessibilityTextAreaRole },
- { ui::AX_ROLE_TEXT_FIELD, NSAccessibilityTextFieldRole },
- { ui::AX_ROLE_TIMER, NSAccessibilityGroupRole },
- { ui::AX_ROLE_TOGGLE_BUTTON, NSAccessibilityCheckBoxRole },
- { ui::AX_ROLE_TOOLBAR, NSAccessibilityToolbarRole },
- { ui::AX_ROLE_TOOLTIP, NSAccessibilityGroupRole },
- { ui::AX_ROLE_TREE, NSAccessibilityOutlineRole },
- { ui::AX_ROLE_TREE_GRID, NSAccessibilityTableRole },
- { ui::AX_ROLE_TREE_ITEM, NSAccessibilityRowRole },
- { ui::AX_ROLE_VALUE_INDICATOR, NSAccessibilityValueIndicatorRole },
- { ui::AX_ROLE_WEB_AREA, @"AXWebArea" },
- { ui::AX_ROLE_WINDOW, NSAccessibilityWindowRole },
-
- // TODO(dtseng): we don't correctly support the attributes for these roles.
- // { ui::AX_ROLE_SCROLL_AREA, NSAccessibilityScrollAreaRole },
- };
-
- RoleMap role_map;
- for (size_t i = 0; i < arraysize(roles); ++i)
- role_map[roles[i].webKitValue] = roles[i].nativeValue;
- return role_map;
-}
-
-// A mapping of webkit roles to native roles.
-NSString* NativeRoleFromAXRole(
- const ui::AXRole& role) {
- CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_role,
- (BuildRoleMap()));
- RoleMap::iterator it = web_accessibility_to_native_role.find(role);
- if (it != web_accessibility_to_native_role.end())
- return it->second;
- else
- return NSAccessibilityUnknownRole;
-}
-
-RoleMap BuildSubroleMap() {
- const MapEntry subroles[] = {
- { ui::AX_ROLE_ALERT, @"AXApplicationAlert" },
- { ui::AX_ROLE_ALERT_DIALOG, @"AXApplicationAlertDialog" },
- { ui::AX_ROLE_ARTICLE, @"AXDocumentArticle" },
- { ui::AX_ROLE_DEFINITION, @"AXDefinition" },
- { ui::AX_ROLE_DESCRIPTION_LIST_DETAIL, @"AXDescription" },
- { ui::AX_ROLE_DESCRIPTION_LIST_TERM, @"AXTerm" },
- { ui::AX_ROLE_DIALOG, @"AXApplicationDialog" },
- { ui::AX_ROLE_DOCUMENT, @"AXDocument" },
- { ui::AX_ROLE_FOOTER, @"AXLandmarkContentInfo" },
- { ui::AX_ROLE_APPLICATION, @"AXLandmarkApplication" },
- { ui::AX_ROLE_BANNER, @"AXLandmarkBanner" },
- { ui::AX_ROLE_COMPLEMENTARY, @"AXLandmarkComplementary" },
- { ui::AX_ROLE_CONTENT_INFO, @"AXLandmarkContentInfo" },
- { ui::AX_ROLE_MAIN, @"AXLandmarkMain" },
- { ui::AX_ROLE_NAVIGATION, @"AXLandmarkNavigation" },
- { ui::AX_ROLE_SEARCH, @"AXLandmarkSearch" },
- { ui::AX_ROLE_LOG, @"AXApplicationLog" },
- { ui::AX_ROLE_MARQUEE, @"AXApplicationMarquee" },
- { ui::AX_ROLE_MATH, @"AXDocumentMath" },
- { ui::AX_ROLE_NOTE, @"AXDocumentNote" },
- { ui::AX_ROLE_REGION, @"AXDocumentRegion" },
- { ui::AX_ROLE_STATUS, @"AXApplicationStatus" },
- { ui::AX_ROLE_TAB_PANEL, @"AXTabPanel" },
- { ui::AX_ROLE_TIMER, @"AXApplicationTimer" },
- { ui::AX_ROLE_TOGGLE_BUTTON, @"AXToggleButton" },
- { ui::AX_ROLE_TOOLTIP, @"AXUserInterfaceTooltip" },
- { ui::AX_ROLE_TREE_ITEM, NSAccessibilityOutlineRowSubrole },
- };
-
- RoleMap subrole_map;
- for (size_t i = 0; i < arraysize(subroles); ++i)
- subrole_map[subroles[i].webKitValue] = subroles[i].nativeValue;
- return subrole_map;
-}
-
-// A mapping of webkit roles to native subroles.
-NSString* NativeSubroleFromAXRole(
- const ui::AXRole& role) {
- CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_subrole,
- (BuildSubroleMap()));
- RoleMap::iterator it = web_accessibility_to_native_subrole.find(role);
- if (it != web_accessibility_to_native_subrole.end())
- return it->second;
- else
- return nil;
-}
-
// A mapping from an accessibility attribute to its method name.
NSDictionary* attributeToMethodNameMap = nil;
@@ -253,6 +69,7 @@ NSDictionary* attributeToMethodNameMap = nil;
{ NSAccessibilityDisclosureLevelAttribute, @"disclosureLevel" },
{ NSAccessibilityDisclosedRowsAttribute, @"disclosedRows" },
{ NSAccessibilityEnabledAttribute, @"enabled" },
+ { NSAccessibilityExpandedAttribute, @"expanded" },
{ NSAccessibilityFocusedAttribute, @"focused" },
{ NSAccessibilityHeaderAttribute, @"header" },
{ NSAccessibilityHelpAttribute, @"help" },
@@ -270,6 +87,7 @@ NSDictionary* attributeToMethodNameMap = nil;
{ NSAccessibilityRowIndexRangeAttribute, @"rowIndexRange" },
{ NSAccessibilityRowsAttribute, @"rows" },
// TODO(aboxhall): expose NSAccessibilityServesAsTitleForUIElementsAttribute
+ { NSAccessibilitySelectedChildrenAttribute, @"selectedChildren" },
{ NSAccessibilitySizeAttribute, @"size" },
{ NSAccessibilitySubroleAttribute, @"subrole" },
{ NSAccessibilityTabsAttribute, @"tabs" },
@@ -281,6 +99,7 @@ NSDictionary* attributeToMethodNameMap = nil;
{ NSAccessibilityValueDescriptionAttribute, @"valueDescription" },
{ NSAccessibilityVisibleCharacterRangeAttribute, @"visibleCharacterRange" },
{ NSAccessibilityVisibleCellsAttribute, @"visibleCells" },
+ { NSAccessibilityVisibleChildrenAttribute, @"visibleChildren" },
{ NSAccessibilityVisibleColumnsAttribute, @"visibleColumns" },
{ NSAccessibilityVisibleRowsAttribute, @"visibleRows" },
{ NSAccessibilityWindowAttribute, @"window" },
@@ -511,6 +330,11 @@ NSDictionary* attributeToMethodNameMap = nil;
GetState(browserAccessibility_, ui::AX_STATE_ENABLED)];
}
+- (NSNumber*)expanded {
+ return [NSNumber numberWithBool:
+ GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)];
+}
+
- (NSNumber*)focused {
BrowserAccessibilityManager* manager = browserAccessibility_->manager();
NSNumber* ret = [NSNumber numberWithBool:
@@ -628,6 +452,11 @@ NSDictionary* attributeToMethodNameMap = nil;
if ([self internalRole] == ui::AX_ROLE_SPIN_BUTTON)
return NSAccessibilityVerticalOrientationValue;
+ if ([self internalRole] == ui::AX_ROLE_LIST ||
+ [self internalRole] == ui::AX_ROLE_LIST_BOX) {
+ return NSAccessibilityVerticalOrientationValue;
+ }
+
if (GetState(browserAccessibility_, ui::AX_STATE_VERTICAL))
return NSAccessibilityVerticalOrientationValue;
else
@@ -712,7 +541,7 @@ NSDictionary* attributeToMethodNameMap = nil;
else
return NSAccessibilityButtonRole;
}
- return NativeRoleFromAXRole(role);
+ return [AXPlatformNodeCocoa nativeRoleFromAXRole:role];
}
// Returns a string indicating the role description of this object.
@@ -752,9 +581,30 @@ NSDictionary* attributeToMethodNameMap = nil;
}
switch([self internalRole]) {
+ case ui::AX_ROLE_ARTICLE:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_ARTICLE));
+ case ui::AX_ROLE_BANNER:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_BANNER));
+ case ui::AX_ROLE_COMPLEMENTARY:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_COMPLEMENTARY));
+ case ui::AX_ROLE_CONTENT_INFO:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_ADDRESS));
case ui::AX_ROLE_FOOTER:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_FOOTER));
+ case ui::AX_ROLE_MAIN:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_MAIN_CONTENT));
+ case ui::AX_ROLE_NAVIGATION:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_NAVIGATIONAL_LINK));
+ case ui::AX_ROLE_REGION:
+ return base::SysUTF16ToNSString(content_client->GetLocalizedString(
+ IDS_AX_ROLE_REGION));
case ui::AX_ROLE_SPIN_BUTTON:
// This control is similar to what VoiceOver calls a "stepper".
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
@@ -829,6 +679,40 @@ NSDictionary* attributeToMethodNameMap = nil;
return ret;
}
+- (NSArray*)selectedChildren {
+ NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
+
+ BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ BrowserAccessibility* focusedChild =
+ manager->GetFocus(browserAccessibility_);
+ if (focusedChild && focusedChild != browserAccessibility_) {
+ // First try the focused child.
+ [ret addObject:focusedChild->ToBrowserAccessibilityCocoa()];
+ } else {
+ // Next try the active descendant.
+ int activeDescendantId;
+ if (browserAccessibility_->GetIntAttribute(
+ ui::AX_ATTR_ACTIVEDESCENDANT_ID, &activeDescendantId)) {
+ BrowserAccessibility* activeDescendant =
+ manager->GetFromID(activeDescendantId);
+ if (activeDescendant)
+ [ret addObject:activeDescendant->ToBrowserAccessibilityCocoa()];
+ } else {
+ // Otherwise return any children with the "selected" state, which
+ // may come from aria-selected.
+ uint32 childCount = browserAccessibility_->PlatformChildCount();
+ for (uint32 index = 0; index < childCount; ++index) {
+ BrowserAccessibility* child =
+ browserAccessibility_->PlatformGetChild(index);
+ if (child->HasState(ui::AX_STATE_SELECTED))
+ [ret addObject:child->ToBrowserAccessibilityCocoa()];
+ }
+ }
+ }
+
+ return ret;
+}
+
// Returns the size of this object.
- (NSValue*)size {
gfx::Rect bounds = browserAccessibility_->GetLocalBoundsRect();
@@ -843,18 +727,13 @@ NSDictionary* attributeToMethodNameMap = nil;
return @"AXSecureTextField";
}
- NSString* htmlTag = NSStringForStringAttribute(
- browserAccessibility_, ui::AX_ATTR_HTML_TAG);
+ if (browserAccessibilityRole == ui::AX_ROLE_DESCRIPTION_LIST)
+ return @"AXDescriptionList";
- if (browserAccessibilityRole == ui::AX_ROLE_LIST) {
- if ([htmlTag isEqualToString:@"dl"]) {
- return @"AXDescriptionList";
- } else {
- return @"AXContentList";
- }
- }
+ if (browserAccessibilityRole == ui::AX_ROLE_LIST)
+ return @"AXContentList";
- return NativeSubroleFromAXRole(browserAccessibilityRole);
+ return [AXPlatformNodeCocoa nativeSubroleFromAXRole:browserAccessibilityRole];
}
// Returns all tabs in this subtree.
@@ -1002,6 +881,18 @@ NSDictionary* attributeToMethodNameMap = nil;
return ret;
}
+- (NSArray*)visibleChildren {
+ NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
+ uint32 childCount = browserAccessibility_->PlatformChildCount();
+ for (uint32 index = 0; index < childCount; ++index) {
+ BrowserAccessibilityCocoa* child =
+ browserAccessibility_->PlatformGetChild(index)->
+ ToBrowserAccessibilityCocoa();
+ [ret addObject:child];
+ }
+ return ret;
+}
+
- (NSArray*)visibleColumns {
return [self columns];
}
@@ -1283,7 +1174,7 @@ NSDictionary* attributeToMethodNameMap = nil;
// Returns the count of the specified accessibility array attribute.
- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute {
if (!browserAccessibility_)
- return nil;
+ return 0;
NSArray* fullArray = [self accessibilityAttributeValue:attribute];
return [fullArray count];
@@ -1299,6 +1190,7 @@ NSDictionary* attributeToMethodNameMap = nil;
NSAccessibilityChildrenAttribute,
NSAccessibilityDescriptionAttribute,
NSAccessibilityEnabledAttribute,
+ NSAccessibilityExpandedAttribute,
NSAccessibilityFocusedAttribute,
NSAccessibilityHelpAttribute,
NSAccessibilityLinkedUIElementsAttribute,
@@ -1396,6 +1288,12 @@ NSDictionary* attributeToMethodNameMap = nil;
nil]];
}
}
+ } else if ([role isEqualToString:NSAccessibilityListRole]) {
+ [ret addObjectsFromArray:[NSArray arrayWithObjects:
+ NSAccessibilityOrientationAttribute,
+ NSAccessibilitySelectedChildrenAttribute,
+ NSAccessibilityVisibleChildrenAttribute,
+ nil]];
}
// Add the url attribute only if it has a valid url.
@@ -1439,7 +1337,7 @@ NSDictionary* attributeToMethodNameMap = nil;
// Returns the index of the child in this objects array of children.
- (NSUInteger)accessibilityGetIndexOf:(id)child {
if (!browserAccessibility_)
- return nil;
+ return 0;
NSUInteger index = 0;
for (BrowserAccessibilityCocoa* childToCheck in [self children]) {
@@ -1454,7 +1352,7 @@ NSDictionary* attributeToMethodNameMap = nil;
// accessibility API via |accessibilitySetValue:forAttribute:|.
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
if (!browserAccessibility_)
- return nil;
+ return NO;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute])
return GetState(browserAccessibility_,
@@ -1471,7 +1369,7 @@ NSDictionary* attributeToMethodNameMap = nil;
return NO;
}
-// Returns whether or not this object should be ignored in the accessibilty
+// Returns whether or not this object should be ignored in the accessibility
// tree.
- (BOOL)accessibilityIsIgnored {
if (!browserAccessibility_)
@@ -1480,7 +1378,7 @@ NSDictionary* attributeToMethodNameMap = nil;
return [self isIgnored];
}
-// Performs the given accessibilty action on the webkit accessibility object
+// Performs the given accessibility action on the webkit accessibility object
// that backs this object.
- (void)accessibilityPerformAction:(NSString*)action {
if (!browserAccessibility_)
@@ -1491,7 +1389,12 @@ NSDictionary* attributeToMethodNameMap = nil;
[self delegate]->AccessibilityDoDefaultAction(
browserAccessibility_->GetId());
} else if ([action isEqualToString:NSAccessibilityShowMenuAction]) {
- [self delegate]->AccessibilityShowMenu(browserAccessibility_->GetId());
+ NSPoint objOrigin = [self origin];
+ NSSize size = [[self size] sizeValue];
+ gfx::Point origin = [self delegate]->AccessibilityOriginInScreen(
+ gfx::Rect(objOrigin.x, objOrigin.y, size.width, size.height));
+ origin.Offset(size.width / 2, size.height / 2);
+ [self delegate]->AccessibilityShowMenu(origin);
}
}
@@ -1516,10 +1419,11 @@ NSDictionary* attributeToMethodNameMap = nil;
return;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
+ BrowserAccessibilityManager* manager = browserAccessibility_->manager();
NSNumber* focusedNumber = value;
BOOL focused = [focusedNumber intValue];
if (focused)
- [self delegate]->AccessibilitySetFocus(browserAccessibility_->GetId());
+ manager->SetFocus(browserAccessibility_, true);
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
NSRange range = [(NSValue*)value rangeValue];
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.h b/chromium/content/browser/accessibility/browser_accessibility_mac.h
index e1b5e384dc1..9802c60734f 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.h
@@ -18,9 +18,9 @@ namespace content {
class BrowserAccessibilityMac : public BrowserAccessibility {
public:
// BrowserAccessibility overrides.
- virtual void NativeReleaseReference() OVERRIDE;
- virtual bool IsNative() const OVERRIDE;
- virtual void OnDataChanged() OVERRIDE;
+ void NativeReleaseReference() override;
+ bool IsNative() const override;
+ void OnDataChanged() override;
// The BrowserAccessibilityCocoa associated with us.
BrowserAccessibilityCocoa* native_view() const {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 6bdce2d907a..1e368c6f8d8 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/common/accessibility_messages.h"
+#include "ui/accessibility/ax_tree_serializer.h"
namespace content {
@@ -48,6 +49,15 @@ BrowserAccessibility* BrowserAccessibilityFactory::Create() {
return BrowserAccessibility::Create();
}
+BrowserAccessibilityFindInPageInfo::BrowserAccessibilityFindInPageInfo()
+ : request_id(-1),
+ match_index(-1),
+ start_id(-1),
+ start_offset(0),
+ end_id(-1),
+ end_offset(-1),
+ active_request_id(-1) {}
+
#if !defined(OS_MACOSX) && \
!defined(OS_WIN) && \
!defined(OS_ANDROID) \
@@ -67,7 +77,7 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
BrowserAccessibilityFactory* factory)
: delegate_(delegate),
factory_(factory),
- tree_(new ui::AXTree()),
+ tree_(new ui::AXSerializableTree()),
focus_(NULL),
osk_state_(OSK_ALLOWED) {
tree_->SetDelegate(this);
@@ -79,7 +89,7 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
BrowserAccessibilityFactory* factory)
: delegate_(delegate),
factory_(factory),
- tree_(new ui::AXTree()),
+ tree_(new ui::AXSerializableTree()),
focus_(NULL),
osk_state_(OSK_ALLOWED) {
tree_->SetDelegate(this);
@@ -224,6 +234,43 @@ void BrowserAccessibilityManager::OnLocationChanges(
}
}
+void BrowserAccessibilityManager::OnFindInPageResult(
+ int request_id, int match_index, int start_id, int start_offset,
+ int end_id, int end_offset) {
+ find_in_page_info_.request_id = request_id;
+ find_in_page_info_.match_index = match_index;
+ find_in_page_info_.start_id = start_id;
+ find_in_page_info_.start_offset = start_offset;
+ find_in_page_info_.end_id = end_id;
+ find_in_page_info_.end_offset = end_offset;
+
+ if (find_in_page_info_.active_request_id == request_id)
+ ActivateFindInPageResult(request_id);
+}
+
+void BrowserAccessibilityManager::ActivateFindInPageResult(
+ int request_id) {
+ find_in_page_info_.active_request_id = request_id;
+ if (find_in_page_info_.request_id != request_id)
+ return;
+
+ BrowserAccessibility* node = GetFromID(find_in_page_info_.start_id);
+ if (!node)
+ return;
+
+ // If an ancestor of this node is a leaf node, fire the notification on that.
+ BrowserAccessibility* ancestor = node->GetParent();
+ while (ancestor && ancestor != GetRoot()) {
+ if (ancestor->PlatformIsLeaf())
+ node = ancestor;
+ ancestor = ancestor->GetParent();
+ }
+
+ // The "scrolled to anchor" notification is a great way to get a
+ // screen reader to jump directly to a specific location in a document.
+ NotifyAccessibilityEvent(ui::AX_EVENT_SCROLLED_TO_ANCHOR, node);
+}
+
BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus(
BrowserAccessibility* root) {
BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus(root);
@@ -283,8 +330,17 @@ void BrowserAccessibilityManager::ScrollToPoint(
}
}
+void BrowserAccessibilityManager::SetValue(
+ const BrowserAccessibility& node,
+ const base::string16& value) {
+ if (delegate_)
+ delegate_->AccessibilitySetValue(node.GetId(), value);
+}
+
void BrowserAccessibilityManager::SetTextSelection(
- const BrowserAccessibility& node, int start_offset, int end_offset) {
+ const BrowserAccessibility& node,
+ int start_offset,
+ int end_offset) {
if (delegate_) {
delegate_->AccessibilitySetTextSelection(
node.GetId(), start_offset, end_offset);
@@ -363,4 +419,13 @@ void BrowserAccessibilityManager::OnNodeChangeFinished(ui::AXNode* node) {
GetFromAXNode(node)->OnUpdateFinished();
}
+ui::AXTreeUpdate BrowserAccessibilityManager::SnapshotAXTreeForTesting() {
+ scoped_ptr<ui::AXTreeSource<const ui::AXNode*> > tree_source(
+ tree_->CreateTreeSource());
+ ui::AXTreeSerializer<const ui::AXNode*> serializer(tree_source.get());
+ ui::AXTreeUpdate update;
+ serializer.SerializeChanges(tree_->GetRoot(), &update);
+ return update;
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index ae0bc30b31f..c0e59fa1d68 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -13,7 +13,7 @@
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "ui/accessibility/ax_node_data.h"
-#include "ui/accessibility/ax_tree.h"
+#include "ui/accessibility/ax_serializable_tree.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/gfx/native_widget_types.h"
@@ -22,6 +22,7 @@ struct AccessibilityHostMsg_LocationChangeParams;
namespace content {
class BrowserAccessibility;
+class BrowserAccessibilityManager;
#if defined(OS_ANDROID)
class BrowserAccessibilityManagerAndroid;
#endif
@@ -42,25 +43,39 @@ CONTENT_EXPORT ui::AXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node9 = ui::AXNodeData());
// Class that can perform actions on behalf of the BrowserAccessibilityManager.
+// Note: BrowserAccessibilityManager should never cache any of the return
+// values from any of these interfaces, especially those that return pointers.
+// They may only be valid within this call stack. That policy eliminates any
+// concerns about ownership and lifecycle issues; none of these interfaces
+// transfer ownership and no return values are guaranteed to be valid outside
+// of the current call stack.
class CONTENT_EXPORT BrowserAccessibilityDelegate {
public:
virtual ~BrowserAccessibilityDelegate() {}
virtual void AccessibilitySetFocus(int acc_obj_id) = 0;
virtual void AccessibilityDoDefaultAction(int acc_obj_id) = 0;
- virtual void AccessibilityShowMenu(int acc_obj_id) = 0;
+ virtual void AccessibilityShowMenu(const gfx::Point& global_point) = 0;
virtual void AccessibilityScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) = 0;
+ int acc_obj_id, const gfx::Rect& subfocus) = 0;
virtual void AccessibilityScrollToPoint(
- int acc_obj_id, gfx::Point point) = 0;
+ int acc_obj_id, const gfx::Point& point) = 0;
virtual void AccessibilitySetTextSelection(
int acc_obj_id, int start_offset, int end_offset) = 0;
+ virtual void AccessibilitySetValue(
+ int acc_obj_id, const base::string16& value) = 0;
virtual bool AccessibilityViewHasFocus() const = 0;
virtual gfx::Rect AccessibilityGetViewBounds() const = 0;
virtual gfx::Point AccessibilityOriginInScreen(
const gfx::Rect& bounds) const = 0;
virtual void AccessibilityHitTest(
const gfx::Point& point) = 0;
+ virtual void AccessibilitySetAccessibilityFocus(int acc_obj_id) = 0;
virtual void AccessibilityFatalError() = 0;
+ virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() = 0;
+ virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() = 0;
+ virtual BrowserAccessibilityManager* AccessibilityGetChildFrame(
+ int accessibility_node_id) = 0;
+ virtual BrowserAccessibility* AccessibilityGetParentFrame() = 0;
};
class CONTENT_EXPORT BrowserAccessibilityFactory {
@@ -72,6 +87,26 @@ class CONTENT_EXPORT BrowserAccessibilityFactory {
virtual BrowserAccessibility* Create();
};
+// This is all of the information about the current find in page result,
+// so we can activate it if requested.
+struct BrowserAccessibilityFindInPageInfo {
+ BrowserAccessibilityFindInPageInfo();
+
+ // This data about find in text results is updated as the user types.
+ int request_id;
+ int match_index;
+ int start_id;
+ int start_offset;
+ int end_id;
+ int end_offset;
+
+ // The active request id indicates that the user committed to a find query,
+ // e.g. by pressing enter or pressing the next or previous buttons. If
+ // |active_request_id| == |request_id|, we fire an accessibility event
+ // to move screen reader focus to that event.
+ int active_request_id;
+};
+
// Manages a tree of BrowserAccessibility objects.
class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
public:
@@ -82,7 +117,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
- virtual ~BrowserAccessibilityManager();
+ ~BrowserAccessibilityManager() override;
void Initialize(const ui::AXTreeUpdate& initial_tree);
@@ -134,6 +169,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
void ScrollToPoint(
const BrowserAccessibility& node, gfx::Point point);
+ // Tell the renderer to set the value of an editable text node.
+ void SetValue(
+ const BrowserAccessibility& node, const base::string16& value);
+
// Tell the renderer to set the text selection on a node.
void SetTextSelection(
const BrowserAccessibility& node, int start_offset, int end_offset);
@@ -141,6 +180,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// Retrieve the bounds of the parent View in screen coordinates.
gfx::Rect GetViewBounds();
+ // Fire an event telling native assistive technology to move focus to the
+ // given find in page result.
+ void ActivateFindInPageResult(int request_id, int match_index);
+
// Called when the renderer process has notified us of about tree changes.
void OnAccessibilityEvents(
const std::vector<AccessibilityHostMsg_EventParams>& params);
@@ -150,6 +193,20 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
void OnLocationChanges(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
+ // Called when a new find in page result is received. We hold on to this
+ // information and don't activate it until the user requests it.
+ void OnFindInPageResult(
+ int request_id, int match_index, int start_id, int start_offset,
+ int end_id, int end_offset);
+
+ // This is called when the user has committed to a find in page query,
+ // e.g. by pressing enter or tapping on the next / previous result buttons.
+ // If a match has already been received for this request id,
+ // activate the result now by firing an accessibility event. If a match
+ // has not been received, we hold onto this request id and update it
+ // when OnFindInPageResult is called.
+ void ActivateFindInPageResult(int request_id);
+
#if defined(OS_WIN)
BrowserAccessibilityManagerWin* ToBrowserAccessibilityManagerWin();
#endif
@@ -175,14 +232,20 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibility* PreviousInTreeOrder(BrowserAccessibility* node);
// AXTreeDelegate implementation.
- virtual void OnNodeWillBeDeleted(ui::AXNode* node) OVERRIDE;
- virtual void OnNodeCreated(ui::AXNode* node) OVERRIDE;
- virtual void OnNodeChanged(ui::AXNode* node) OVERRIDE;
- virtual void OnNodeCreationFinished(ui::AXNode* node) OVERRIDE;
- virtual void OnNodeChangeFinished(ui::AXNode* node) OVERRIDE;
- virtual void OnRootChanged(ui::AXNode* new_root) OVERRIDE {}
+ void OnNodeWillBeDeleted(ui::AXNode* node) override;
+ void OnNodeCreated(ui::AXNode* node) override;
+ void OnNodeChanged(ui::AXNode* node) override;
+ void OnNodeCreationFinished(ui::AXNode* node) override;
+ void OnNodeChangeFinished(ui::AXNode* node) override;
+ void OnRootChanged(ui::AXNode* new_root) override {}
BrowserAccessibilityDelegate* delegate() const { return delegate_; }
+ void set_delegate(BrowserAccessibilityDelegate* delegate) {
+ delegate_ = delegate;
+ }
+
+ // Get a snapshot of the current tree as an AXTreeUpdate.
+ ui::AXTreeUpdate SnapshotAXTreeForTesting();
protected:
BrowserAccessibilityManager(
@@ -220,21 +283,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
OSK_ALLOWED
};
- // Update a set of nodes using data received from the renderer
- // process.
- bool UpdateNodes(const std::vector<ui::AXNodeData>& nodes);
-
- // Update one node from the tree using data received from the renderer
- // process. Returns true on success, false on fatal error.
- bool UpdateNode(const ui::AXNodeData& src);
-
- void SetRoot(BrowserAccessibility* root);
-
- BrowserAccessibility* CreateNode(
- BrowserAccessibility* parent,
- int32 id,
- int32 index_in_parent);
-
protected:
// The object that can perform actions on our behalf.
BrowserAccessibilityDelegate* delegate_;
@@ -243,7 +291,7 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
scoped_ptr<BrowserAccessibilityFactory> factory_;
// The underlying tree of accessibility objects.
- scoped_ptr<ui::AXTree> tree_;
+ scoped_ptr<ui::AXSerializableTree> tree_;
// The node that currently has focus.
ui::AXNode* focus_;
@@ -254,6 +302,8 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// The on-screen keyboard state.
OnScreenKeyboardState osk_state_;
+ BrowserAccessibilityFindInPageInfo find_in_page_info_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManager);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 07f04e71b45..fd4e0ff9fae 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -8,24 +8,20 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
+#include "base/i18n/char_iterator.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/browser/accessibility/browser_accessibility_android.h"
#include "content/common/accessibility_messages.h"
#include "jni/BrowserAccessibilityManager_jni.h"
+#include "ui/accessibility/ax_text_utils.h"
using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
namespace {
-// These are enums from android.view.accessibility.AccessibilityEvent in Java:
-enum {
- ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_CHANGED = 16,
- ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192
-};
-
enum AndroidHtmlElementType {
HTML_ELEMENT_TYPE_SECTION,
HTML_ELEMENT_TYPE_LIST,
@@ -74,8 +70,9 @@ BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
const ui::AXTreeUpdate& initial_tree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
- : BrowserAccessibilityManager(initial_tree, delegate, factory) {
+ : BrowserAccessibilityManager(delegate, factory) {
SetContentViewCore(content_view_core);
+ Initialize(initial_tree);
}
BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
@@ -119,9 +116,15 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
if (obj.is_null())
return;
+ BrowserAccessibilityAndroid* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node);
+
if (event_type == ui::AX_EVENT_HIDE)
return;
+ if (event_type == ui::AX_EVENT_TREE_CHANGED)
+ return;
+
if (event_type == ui::AX_EVENT_HOVER) {
HandleHoverEvent(node);
return;
@@ -160,15 +163,13 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
case ui::AX_EVENT_SHOW: {
// This event is fired when an object appears in a live region.
// Speak its text.
- BrowserAccessibilityAndroid* android_node =
- static_cast<BrowserAccessibilityAndroid*>(node);
Java_BrowserAccessibilityManager_announceLiveRegionText(
env, obj.obj(),
base::android::ConvertUTF16ToJavaString(
env, android_node->GetText()).obj());
break;
}
- case ui::AX_EVENT_SELECTED_TEXT_CHANGED:
+ case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
Java_BrowserAccessibilityManager_handleTextSelectionChanged(
env, obj.obj(), node->GetId());
break;
@@ -178,6 +179,9 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
if (node->IsEditableText()) {
Java_BrowserAccessibilityManager_handleEditableTextChanged(
env, obj.obj(), node->GetId());
+ } else if (android_node->IsSlider()) {
+ Java_BrowserAccessibilityManager_handleSliderChanged(
+ env, obj.obj(), node->GetId());
}
break;
default:
@@ -202,6 +206,36 @@ void BrowserAccessibilityManagerAndroid::HitTest(
delegate()->AccessibilityHitTest(gfx::Point(x, y));
}
+jboolean BrowserAccessibilityManagerAndroid::IsEditableText(
+ JNIEnv* env, jobject obj, jint id) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ return node->IsEditableText();
+}
+
+jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionStart(
+ JNIEnv* env, jobject obj, jint id) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ return node->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START);
+}
+
+jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionEnd(
+ JNIEnv* env, jobject obj, jint id) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ return node->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END);
+}
+
jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
JNIEnv* env, jobject obj, jobject info, jint id) {
BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
@@ -220,9 +254,12 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes(
env, obj, info,
id,
+ node->CanScrollForward(),
+ node->CanScrollBackward(),
node->IsCheckable(),
node->IsChecked(),
node->IsClickable(),
+ node->IsEditableText(),
node->IsEnabled(),
node->IsFocusable(),
node->IsFocused(),
@@ -233,10 +270,13 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoClassName(
env, obj, info,
base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj());
- Java_BrowserAccessibilityManager_setAccessibilityNodeInfoContentDescription(
- env, obj, info,
- base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj(),
- node->IsLink());
+ if (!node->IsPassword() ||
+ Java_BrowserAccessibilityManager_shouldExposePasswordText(env, obj)) {
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoContentDescription(
+ env, obj, info,
+ base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj(),
+ node->IsLink());
+ }
gfx::Rect absolute_rect = node->GetLocalBoundsRect();
gfx::Rect parent_relative_rect = absolute_rect;
@@ -247,6 +287,7 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
bool is_root = node->GetParent() == NULL;
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoLocation(
env, obj, info,
+ id,
absolute_rect.x(), absolute_rect.y(),
parent_relative_rect.x(), parent_relative_rect.y(),
absolute_rect.width(), absolute_rect.height(),
@@ -317,24 +358,37 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
node->GetMaxScrollY());
switch (event_type) {
- case ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_CHANGED:
+ case ANDROID_ACCESSIBILITY_EVENT_TEXT_CHANGED: {
+ base::string16 before_text, text;
+ if (!node->IsPassword() ||
+ Java_BrowserAccessibilityManager_shouldExposePasswordText(env, obj)) {
+ before_text = node->GetTextChangeBeforeText();
+ text = node->GetText();
+ }
Java_BrowserAccessibilityManager_setAccessibilityEventTextChangedAttrs(
env, obj, event,
node->GetTextChangeFromIndex(),
node->GetTextChangeAddedCount(),
node->GetTextChangeRemovedCount(),
base::android::ConvertUTF16ToJavaString(
- env, node->GetTextChangeBeforeText()).obj(),
- base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
+ env, before_text).obj(),
+ base::android::ConvertUTF16ToJavaString(env, text).obj());
break;
- case ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED:
+ }
+ case ANDROID_ACCESSIBILITY_EVENT_TEXT_SELECTION_CHANGED: {
+ base::string16 text;
+ if (!node->IsPassword() ||
+ Java_BrowserAccessibilityManager_shouldExposePasswordText(env, obj)) {
+ text = node->GetText();
+ }
Java_BrowserAccessibilityManager_setAccessibilityEventSelectionAttrs(
env, obj, event,
node->GetSelectionStart(),
node->GetSelectionEnd(),
node->GetEditableTextLength(),
- base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
+ base::android::ConvertUTF16ToJavaString(env, text).obj());
break;
+ }
default:
break;
}
@@ -355,14 +409,17 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
node->ColumnCount(),
node->IsHierarchical());
}
- if (node->IsCollectionItem() || node->IsHeading()) {
+ if (node->IsHeading()) {
+ Java_BrowserAccessibilityManager_setAccessibilityEventHeadingFlag(
+ env, obj, event, true);
+ }
+ if (node->IsCollectionItem()) {
Java_BrowserAccessibilityManager_setAccessibilityEventCollectionItemInfo(
env, obj, event,
node->RowIndex(),
node->RowSpan(),
node->ColumnIndex(),
- node->ColumnSpan(),
- node->IsHeading());
+ node->ColumnSpan());
}
if (node->IsRangeType()) {
Java_BrowserAccessibilityManager_setAccessibilityEventRangeInfo(
@@ -401,6 +458,54 @@ void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible(
ScrollToMakeVisible(*node, gfx::Rect(node->GetLocation().size()));
}
+void BrowserAccessibilityManagerAndroid::SetTextFieldValue(
+ JNIEnv* env, jobject obj, jint id, jstring value) {
+ BrowserAccessibility* node = GetFromID(id);
+ if (node) {
+ BrowserAccessibilityManager::SetValue(
+ *node, base::android::ConvertJavaStringToUTF16(env, value));
+ }
+}
+
+void BrowserAccessibilityManagerAndroid::SetSelection(
+ JNIEnv* env, jobject obj, jint id, jint start, jint end) {
+ BrowserAccessibility* node = GetFromID(id);
+ if (node)
+ SetTextSelection(*node, start, end);
+}
+
+jboolean BrowserAccessibilityManagerAndroid::AdjustSlider(
+ JNIEnv* env, jobject obj, jint id, jboolean increment) {
+ BrowserAccessibility* node = GetFromID(id);
+ if (!node)
+ return false;
+
+ BrowserAccessibilityAndroid* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node);
+
+ if (!android_node->IsSlider() || !android_node->IsEnabled())
+ return false;
+
+ float value = node->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
+ float min = node->GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE);
+ float max = node->GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE);
+ if (max <= min)
+ return false;
+
+ // To behave similarly to an Android SeekBar, move by an increment of
+ // approximately 20%.
+ float original_value = value;
+ float delta = (max - min) / 5.0f;
+ value += (increment ? delta : -delta);
+ value = std::max(std::min(value, max), min);
+ if (value != original_value) {
+ BrowserAccessibilityManager::SetValue(
+ *node, base::UTF8ToUTF16(base::DoubleToString(value)));
+ return true;
+ }
+ return false;
+}
+
void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
BrowserAccessibility* node) {
JNIEnv* env = AttachCurrentThread();
@@ -410,7 +515,7 @@ void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
BrowserAccessibilityAndroid* ancestor =
static_cast<BrowserAccessibilityAndroid*>(node->GetParent());
- while (ancestor) {
+ while (ancestor && ancestor != GetRoot()) {
if (ancestor->PlatformIsLeaf() ||
(ancestor->IsFocusable() && !ancestor->HasFocusableChild())) {
node = ancestor;
@@ -481,6 +586,144 @@ jint BrowserAccessibilityManagerAndroid::FindElementType(
return 0;
}
+jboolean BrowserAccessibilityManagerAndroid::NextAtGranularity(
+ JNIEnv* env, jobject obj, jint granularity, jboolean extend_selection,
+ jint id, jint cursor_index) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ jint start_index = -1;
+ int end_index = -1;
+ if (NextAtGranularity(granularity, cursor_index, node,
+ &start_index, &end_index)) {
+ base::string16 text;
+ if (!node->IsPassword() ||
+ Java_BrowserAccessibilityManager_shouldExposePasswordText(env, obj)) {
+ text = node->GetText();
+ }
+ Java_BrowserAccessibilityManager_finishGranularityMove(
+ env, obj, base::android::ConvertUTF16ToJavaString(
+ env, text).obj(),
+ extend_selection, start_index, end_index, true);
+ return true;
+ }
+ return false;
+}
+
+jboolean BrowserAccessibilityManagerAndroid::PreviousAtGranularity(
+ JNIEnv* env, jobject obj, jint granularity, jboolean extend_selection,
+ jint id, jint cursor_index) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ jint start_index = -1;
+ int end_index = -1;
+ if (PreviousAtGranularity(granularity, cursor_index, node,
+ &start_index, &end_index)) {
+ Java_BrowserAccessibilityManager_finishGranularityMove(
+ env, obj, base::android::ConvertUTF16ToJavaString(
+ env, node->GetText()).obj(),
+ extend_selection, start_index, end_index, false);
+ return true;
+ }
+ return false;
+}
+
+bool BrowserAccessibilityManagerAndroid::NextAtGranularity(
+ int32 granularity, int32 cursor_index,
+ BrowserAccessibilityAndroid* node, int32* start_index, int32* end_index) {
+ switch (granularity) {
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER: {
+ base::string16 text = node->GetText();
+ if (cursor_index >= static_cast<int32>(text.length()))
+ return false;
+ base::i18n::UTF16CharIterator iter(text.data(), text.size());
+ while (!iter.end() && iter.array_pos() <= cursor_index)
+ iter.Advance();
+ *start_index = iter.array_pos();
+ *end_index = iter.array_pos();
+ break;
+ }
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_WORD:
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_LINE: {
+ std::vector<int32> starts;
+ std::vector<int32> ends;
+ node->GetGranularityBoundaries(granularity, &starts, &ends, 0);
+ if (starts.size() == 0)
+ return false;
+
+ size_t index = 0;
+ while (index < starts.size() - 1 && starts[index] < cursor_index)
+ index++;
+
+ if (starts[index] < cursor_index)
+ return false;
+
+ *start_index = starts[index];
+ *end_index = ends[index];
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+
+ return true;
+}
+
+bool BrowserAccessibilityManagerAndroid::PreviousAtGranularity(
+ int32 granularity, int32 cursor_index,
+ BrowserAccessibilityAndroid* node, int32* start_index, int32* end_index) {
+ switch (granularity) {
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER: {
+ if (cursor_index <= 0)
+ return false;
+ base::string16 text = node->GetText();
+ base::i18n::UTF16CharIterator iter(text.data(), text.size());
+ int previous_index = 0;
+ while (!iter.end() && iter.array_pos() < cursor_index) {
+ previous_index = iter.array_pos();
+ iter.Advance();
+ }
+ *start_index = previous_index;
+ *end_index = previous_index;
+ break;
+ }
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_WORD:
+ case ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_LINE: {
+ std::vector<int32> starts;
+ std::vector<int32> ends;
+ node->GetGranularityBoundaries(granularity, &starts, &ends, 0);
+ if (starts.size() == 0)
+ return false;
+
+ size_t index = starts.size() - 1;
+ while (index > 0 && starts[index] >= cursor_index)
+ index--;
+
+ if (starts[index] >= cursor_index)
+ return false;
+
+ *start_index = starts[index];
+ *end_index = ends[index];
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+
+ return true;
+}
+
+void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus(
+ JNIEnv* env, jobject obj, jint id) {
+ if (delegate_)
+ delegate_->AccessibilitySetAccessibilityFocus(id);
+}
+
void BrowserAccessibilityManagerAndroid::OnRootChanged(ui::AXNode* new_root) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index a40f7e7cf88..f0e2d344ac1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -16,6 +16,22 @@ namespace aria_strings {
extern const char kAriaLiveAssertive[];
}
+// From android.view.accessibility.AccessibilityNodeInfo in Java:
+enum AndroidMovementGranularity {
+ ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER = 1,
+ ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_WORD = 2,
+ ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_LINE = 4
+};
+
+// From android.view.accessibility.AccessibilityEvent in Java:
+enum {
+ ANDROID_ACCESSIBILITY_EVENT_TEXT_CHANGED = 16,
+ ANDROID_ACCESSIBILITY_EVENT_TEXT_SELECTION_CHANGED = 8192,
+ ANDROID_ACCESSIBILITY_EVENT_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 131072
+};
+
+class BrowserAccessibilityAndroid;
+
class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
: public BrowserAccessibilityManager {
public:
@@ -34,7 +50,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
// Implementation of BrowserAccessibilityManager.
virtual void NotifyAccessibilityEvent(
- ui::AXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ ui::AXEvent event_type, BrowserAccessibility* node) override;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
@@ -45,6 +61,11 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
jboolean IsNodeValid(JNIEnv* env, jobject obj, jint id);
void HitTest(JNIEnv* env, jobject obj, jint x, jint y);
+ // Methods to get information about a specific node.
+ jboolean IsEditableText(JNIEnv* env, jobject obj, jint id);
+ jint GetEditableTextSelectionStart(JNIEnv* env, jobject obj, jint id);
+ jint GetEditableTextSelectionEnd(JNIEnv* env, jobject obj, jint id);
+
// Populate Java accessibility data structures with info about a node.
jboolean PopulateAccessibilityNodeInfo(
JNIEnv* env, jobject obj, jobject info, jint id);
@@ -55,7 +76,10 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
void Click(JNIEnv* env, jobject obj, jint id);
void Focus(JNIEnv* env, jobject obj, jint id);
void Blur(JNIEnv* env, jobject obj);
- void ScrollToMakeNodeVisible(JNIEnv* env, jobject obj, int id);
+ void ScrollToMakeNodeVisible(JNIEnv* env, jobject obj, jint id);
+ void SetTextFieldValue(JNIEnv* env, jobject obj, jint id, jstring value);
+ void SetSelection(JNIEnv* env, jobject obj, jint id, jint start, jint end);
+ jboolean AdjustSlider(JNIEnv* env, jobject obj, jint id, jboolean increment);
// Return the id of the next node in tree order in the direction given by
// |forwards|, starting with |start_id|, that matches |element_type|,
@@ -65,11 +89,43 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
jint FindElementType(JNIEnv* env, jobject obj, jint start_id,
jstring element_type, jboolean forwards);
+ // Respond to a ACTION_[NEXT/PREVIOUS]_AT_MOVEMENT_GRANULARITY action
+ // and move the cursor/selection within the given node id. We keep track
+ // of our own selection in BrowserAccessibilityManager.java for static
+ // text, but if this is an editable text node, updates the selected text
+ // in Blink, too, and either way calls
+ // Java_BrowserAccessibilityManager_finishGranularityMove with the
+ // result.
+ jboolean NextAtGranularity(JNIEnv* env, jobject obj,
+ jint granularity, jboolean extend_selection,
+ jint id, jint cursor_index);
+ jboolean PreviousAtGranularity(JNIEnv* env, jobject obj,
+ jint granularity, jboolean extend_selection,
+ jint id, jint cursor_index);
+
+ // Helper functions to compute the next start and end index when moving
+ // forwards or backwards by character, word, or line. This part is
+ // unit-tested; the Java interfaces above are just wrappers. Both of these
+ // take a single cursor index as input and return the boundaries surrounding
+ // the next word or line. If moving by character, the output start and
+ // end index will be the same.
+ bool NextAtGranularity(
+ int32 granularity, int cursor_index,
+ BrowserAccessibilityAndroid* node, int32* start_index, int32* end_index);
+ bool PreviousAtGranularity(
+ int32 granularity, int cursor_index,
+ BrowserAccessibilityAndroid* node, int32* start_index, int32* end_index);
+
+ // Set accessibility focus. This sends a message to the renderer to
+ // asynchronously load inline text boxes for this node only, enabling more
+ // accurate movement by granularities on this node.
+ void SetAccessibilityFocus(JNIEnv* env, jobject obj, jint id);
+
protected:
// AXTreeDelegate overrides.
- virtual void OnRootChanged(ui::AXNode* new_root) OVERRIDE;
+ virtual void OnRootChanged(ui::AXNode* new_root) override;
- virtual bool UseRootScrollOffsetsWhenComputingBounds() OVERRIDE;
+ virtual bool UseRootScrollOffsetsWhenComputingBounds() override;
private:
// This gives BrowserAccessibilityManager::Create access to the class
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index fb2a0eb47b0..b754a4b4468 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -22,17 +22,17 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
static ui::AXTreeUpdate GetEmptyDocument();
- virtual BrowserAccessibility* GetFocus(BrowserAccessibility* root) OVERRIDE;
+ BrowserAccessibility* GetFocus(BrowserAccessibility* root) override;
// Implementation of BrowserAccessibilityManager.
- virtual void NotifyAccessibilityEvent(
- ui::AXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ void NotifyAccessibilityEvent(ui::AXEvent event_type,
+ BrowserAccessibility* node) override;
NSView* parent_view() { return parent_view_; }
private:
- virtual void OnNodeCreationFinished(ui::AXNode* node) OVERRIDE;
- virtual void OnTreeUpdateFinished() OVERRIDE;
+ void OnNodeCreationFinished(ui::AXNode* node) override;
+ void OnTreeUpdateFinished() override;
// This gives BrowserAccessibilityManager::Create access to the class
// constructor.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 53d776bc287..2000d025acc 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -25,9 +25,10 @@ BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac(
const ui::AXTreeUpdate& initial_tree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
- : BrowserAccessibilityManager(initial_tree, delegate, factory),
+ : BrowserAccessibilityManager(delegate, factory),
parent_view_(parent_view),
created_live_region_(false) {
+ Initialize(initial_tree);
}
// static
@@ -96,12 +97,6 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
case ui::AX_EVENT_MENU_LIST_VALUE_CHANGED:
// Not used on Mac.
return;
- case ui::AX_EVENT_SHOW:
- // Not used on Mac.
- return;
- case ui::AX_EVENT_HIDE:
- // Not used on Mac.
- return;
case ui::AX_EVENT_ROW_COUNT_CHANGED:
event_id = NSAccessibilityRowCountChangedNotification;
break;
@@ -117,15 +112,9 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED:
event_id = NSAccessibilitySelectedChildrenChangedNotification;
break;
- case ui::AX_EVENT_SELECTED_TEXT_CHANGED:
+ case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
event_id = NSAccessibilitySelectedTextChangedNotification;
break;
- case ui::AX_EVENT_TEXT_INSERTED:
- // Not used on Mac.
- return;
- case ui::AX_EVENT_TEXT_REMOVED:
- // Not used on Mac.
- return;
case ui::AX_EVENT_VALUE_CHANGED:
event_id = NSAccessibilityValueChangedNotification;
break;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index ddff85fd804..8e2e3d033b9 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -22,15 +22,11 @@ class CountedBrowserAccessibility : public BrowserAccessibility {
global_obj_count_++;
native_ref_count_ = 1;
}
- virtual ~CountedBrowserAccessibility() {
- global_obj_count_--;
- }
+ ~CountedBrowserAccessibility() override { global_obj_count_--; }
- virtual void NativeAddReference() OVERRIDE {
- native_ref_count_++;
- }
+ void NativeAddReference() override { native_ref_count_++; }
- virtual void NativeReleaseReference() OVERRIDE {
+ void NativeReleaseReference() override {
native_ref_count_--;
if (native_ref_count_ == 0)
delete this;
@@ -55,8 +51,8 @@ int CountedBrowserAccessibility::global_obj_count_ = 0;
class CountedBrowserAccessibilityFactory
: public BrowserAccessibilityFactory {
public:
- virtual ~CountedBrowserAccessibilityFactory() {}
- virtual BrowserAccessibility* Create() OVERRIDE {
+ ~CountedBrowserAccessibilityFactory() override {}
+ BrowserAccessibility* Create() override {
return new CountedBrowserAccessibility();
}
};
@@ -67,29 +63,38 @@ class TestBrowserAccessibilityDelegate
TestBrowserAccessibilityDelegate()
: got_fatal_error_(false) {}
- virtual void AccessibilitySetFocus(int acc_obj_id) OVERRIDE {}
- virtual void AccessibilityDoDefaultAction(int acc_obj_id) OVERRIDE {}
- virtual void AccessibilityShowMenu(int acc_obj_id) OVERRIDE {}
- virtual void AccessibilityScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) OVERRIDE {}
- virtual void AccessibilityScrollToPoint(
- int acc_obj_id, gfx::Point point) OVERRIDE {}
- virtual void AccessibilitySetTextSelection(
- int acc_obj_id, int start_offset, int end_offset) OVERRIDE {}
- virtual bool AccessibilityViewHasFocus() const OVERRIDE {
- return false;
+ void AccessibilitySetFocus(int acc_obj_id) override {}
+ void AccessibilityDoDefaultAction(int acc_obj_id) override {}
+ void AccessibilityShowMenu(const gfx::Point& point) override {}
+ void AccessibilityScrollToMakeVisible(int acc_obj_id,
+ const gfx::Rect& subfocus) override {}
+ void AccessibilityScrollToPoint(int acc_obj_id,
+ const gfx::Point& point) override {}
+ void AccessibilitySetTextSelection(int acc_obj_id,
+ int start_offset,
+ int end_offset) override {}
+ void AccessibilitySetValue(int acc_obj_id, const base::string16& value)
+ override {}
+ bool AccessibilityViewHasFocus() const override { return false; }
+ gfx::Rect AccessibilityGetViewBounds() const override { return gfx::Rect(); }
+ gfx::Point AccessibilityOriginInScreen(
+ const gfx::Rect& bounds) const override {
+ return gfx::Point();
}
- virtual gfx::Rect AccessibilityGetViewBounds() const OVERRIDE {
- return gfx::Rect();
+ void AccessibilityHitTest(const gfx::Point& point) override {}
+ void AccessibilitySetAccessibilityFocus(int acc_obj_id) override {}
+ void AccessibilityFatalError() override { got_fatal_error_ = true; }
+ gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override {
+ return gfx::kNullAcceleratedWidget;
}
- virtual gfx::Point AccessibilityOriginInScreen(
- const gfx::Rect& bounds) const OVERRIDE {
- return gfx::Point();
+ gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override {
+ return NULL;
}
- virtual void AccessibilityHitTest(const gfx::Point& point) OVERRIDE {}
- virtual void AccessibilityFatalError() OVERRIDE {
- got_fatal_error_ = true;
+ BrowserAccessibilityManager* AccessibilityGetChildFrame(
+ int accessibility_node_id) override {
+ return NULL;
}
+ BrowserAccessibility* AccessibilityGetParentFrame() override { return NULL; }
bool got_fatal_error() const { return got_fatal_error_; }
void reset_got_fatal_error() { got_fatal_error_ = false; }
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 4e7153ab75a..b7424870cea 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -20,9 +20,7 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
const ui::AXTreeUpdate& initial_tree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory) {
- return new BrowserAccessibilityManagerWin(
- content::LegacyRenderWidgetHostHWND::Create(GetDesktopWindow()).get(),
- NULL, initial_tree, delegate, factory);
+ return new BrowserAccessibilityManagerWin(initial_tree, delegate, factory);
}
BrowserAccessibilityManagerWin*
@@ -31,22 +29,14 @@ BrowserAccessibilityManager::ToBrowserAccessibilityManagerWin() {
}
BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
- LegacyRenderWidgetHostHWND* accessible_hwnd,
- IAccessible* parent_iaccessible,
const ui::AXTreeUpdate& initial_tree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
- : BrowserAccessibilityManager(initial_tree, delegate, factory),
- parent_hwnd_(NULL),
- parent_iaccessible_(parent_iaccessible),
+ : BrowserAccessibilityManager(delegate, factory),
tracked_scroll_object_(NULL),
- accessible_hwnd_(accessible_hwnd),
focus_event_on_root_needed_(false) {
ui::win::CreateATLModuleIfNeeded();
- if (accessible_hwnd_) {
- accessible_hwnd_->set_browser_accessibility_manager(this);
- parent_hwnd_ = accessible_hwnd_->GetParent();
- }
+ Initialize(initial_tree);
}
BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
@@ -54,8 +44,6 @@ BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
tracked_scroll_object_->Release();
tracked_scroll_object_ = NULL;
}
- if (accessible_hwnd_)
- accessible_hwnd_->OnManagerDeleted();
}
// static
@@ -73,29 +61,28 @@ ui::AXTreeUpdate BrowserAccessibilityManagerWin::GetEmptyDocument() {
return update;
}
-void BrowserAccessibilityManagerWin::SetAccessibleHWND(
- LegacyRenderWidgetHostHWND* accessible_hwnd) {
- accessible_hwnd_ = accessible_hwnd;
- if (accessible_hwnd_) {
- accessible_hwnd_->set_browser_accessibility_manager(this);
- parent_hwnd_ = accessible_hwnd_->GetParent();
- }
+HWND BrowserAccessibilityManagerWin::GetParentHWND() {
+ if (!delegate_)
+ return NULL;
+ return delegate_->AccessibilityGetAcceleratedWidget();
+}
+
+IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() {
+ if (!delegate_)
+ return NULL;
+ return delegate_->AccessibilityGetNativeViewAccessible();
}
void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(DWORD event,
LONG child_id) {
- // If on Win 7 and complete accessibility is enabled, use the fake child HWND
- // to use as the root of the accessibility tree. See comments above
- // LegacyRenderWidgetHostHWND for details.
- if (accessible_hwnd_ &&
- BrowserAccessibilityStateImpl::GetInstance()->IsAccessibleBrowser()) {
- parent_hwnd_ = accessible_hwnd_->hwnd();
- parent_iaccessible_ = accessible_hwnd_->window_accessible();
- }
+ if (!delegate_)
+ return;
+
+ HWND hwnd = delegate_->AccessibilityGetAcceleratedWidget();
+ if (!hwnd)
+ return;
- // Only fire events if this view is hooked up to its parent.
- if (parent_iaccessible() && parent_hwnd())
- ::NotifyWinEvent(event, parent_hwnd(), OBJID_CLIENT, child_id);
+ ::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id);
}
@@ -142,6 +129,11 @@ void BrowserAccessibilityManagerWin::OnWindowFocused() {
void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
ui::AXEvent event_type,
BrowserAccessibility* node) {
+ if (!delegate_ || !delegate_->AccessibilityGetAcceleratedWidget())
+ return;
+
+ // Inline text boxes are an internal implementation detail, we don't
+ // expose them to Windows.
if (node->GetRole() == ui::AX_ROLE_INLINE_TEXT_BOX)
return;
@@ -232,17 +224,11 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
case ui::AX_EVENT_SELECTED_CHILDREN_CHANGED:
event_id = EVENT_OBJECT_SELECTIONWITHIN;
break;
- case ui::AX_EVENT_SELECTED_TEXT_CHANGED:
- event_id = IA2_EVENT_TEXT_CARET_MOVED;
- break;
case ui::AX_EVENT_TEXT_CHANGED:
event_id = EVENT_OBJECT_NAMECHANGE;
break;
- case ui::AX_EVENT_TEXT_INSERTED:
- event_id = IA2_EVENT_TEXT_INSERTED;
- break;
- case ui::AX_EVENT_TEXT_REMOVED:
- event_id = IA2_EVENT_TEXT_REMOVED;
+ case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
+ event_id = IA2_EVENT_TEXT_CARET_MOVED;
break;
case ui::AX_EVENT_VALUE_CHANGED:
event_id = EVENT_OBJECT_VALUECHANGE;
@@ -302,15 +288,4 @@ BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin(
return NULL;
}
-void BrowserAccessibilityManagerWin::OnAccessibleHwndDeleted() {
- // If the AccessibleHWND is deleted, |parent_hwnd_| and
- // |parent_iaccessible_| are no longer valid either, since they were
- // derived from AccessibleHWND. We don't have to restore them to
- // previous values, though, because this should only happen
- // during the destruct sequence for this window.
- accessible_hwnd_ = NULL;
- parent_hwnd_ = NULL;
- parent_iaccessible_ = NULL;
-}
-
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index 26c82b793c0..8eaa9490c85 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -14,15 +14,11 @@
namespace content {
class BrowserAccessibilityWin;
-class LegacyRenderWidgetHostHWND;
-
// Manages a tree of BrowserAccessibilityWin objects.
class CONTENT_EXPORT BrowserAccessibilityManagerWin
: public BrowserAccessibilityManager {
public:
BrowserAccessibilityManagerWin(
- content::LegacyRenderWidgetHostHWND* accessible_hwnd,
- IAccessible* parent_iaccessible,
const ui::AXTreeUpdate& initial_tree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
@@ -32,27 +28,22 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
static ui::AXTreeUpdate GetEmptyDocument();
// Get the closest containing HWND.
- HWND parent_hwnd() { return parent_hwnd_; }
+ HWND GetParentHWND();
// The IAccessible for the parent window.
- IAccessible* parent_iaccessible() { return parent_iaccessible_; }
- void set_parent_iaccessible(IAccessible* parent_iaccessible) {
- parent_iaccessible_ = parent_iaccessible;
- }
-
- void SetAccessibleHWND(LegacyRenderWidgetHostHWND* accessible_hwnd);
+ IAccessible* GetParentIAccessible();
// Calls NotifyWinEvent if the parent window's IAccessible pointer is known.
void MaybeCallNotifyWinEvent(DWORD event, LONG child_id);
// AXTree methods
- virtual void OnNodeWillBeDeleted(ui::AXNode* node) OVERRIDE;
- virtual void OnNodeCreated(ui::AXNode* node) OVERRIDE;
+ virtual void OnNodeWillBeDeleted(ui::AXNode* node) override;
+ virtual void OnNodeCreated(ui::AXNode* node) override;
// BrowserAccessibilityManager methods
- virtual void OnWindowFocused() OVERRIDE;
+ virtual void OnWindowFocused() override;
virtual void NotifyAccessibilityEvent(
- ui::AXEvent event_type, BrowserAccessibility* node) OVERRIDE;
+ ui::AXEvent event_type, BrowserAccessibility* node) override;
// Track this object and post a VISIBLE_DATA_CHANGED notification when
// its container scrolls.
@@ -68,15 +59,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
protected:
// BrowserAccessibilityManager methods
- virtual void OnRootChanged(ui::AXNode* new_root) OVERRIDE;
+ virtual void OnRootChanged(ui::AXNode* new_root) override;
private:
- // The closest ancestor HWND.
- HWND parent_hwnd_;
-
- // The accessibility instance for the parent window.
- IAccessible* parent_iaccessible_;
-
// Give BrowserAccessibilityManager::Create access to our constructor.
friend class BrowserAccessibilityManager;
@@ -89,9 +74,6 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// browser process) to accessibility ids within this page.
base::hash_map<long, int32> unique_id_to_ax_id_map_;
- // Owned by its parent; OnAccessibleHwndDeleted gets called upon deletion.
- LegacyRenderWidgetHostHWND* accessible_hwnd_;
-
// Set to true if we need to fire a focus event on the root as soon as
// possible.
bool focus_event_on_root_needed_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index f45c31d2776..597b13ac0c1 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -6,19 +6,13 @@
#include "base/command_line.h"
#include "base/metrics/histogram.h"
-#include "base/timer/timer.h"
#include "content/browser/accessibility/accessibility_mode_helper.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/common/content_switches.h"
#include "ui/gfx/sys_color_change_listener.h"
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
namespace content {
// Update the accessibility histogram 45 seconds after initialization.
@@ -63,7 +57,7 @@ BrowserAccessibilityStateImpl::~BrowserAccessibilityStateImpl() {
}
void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererAccessibility)) {
return;
}
@@ -80,17 +74,7 @@ void BrowserAccessibilityStateImpl::DisableAccessibility() {
void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
accessibility_mode_ = AccessibilityModeOff;
-#if defined(OS_WIN)
- // On Windows 8, always enable accessibility for editable text controls
- // so we can show the virtual keyboard when one is enabled.
- if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRendererAccessibility)) {
- accessibility_mode_ = AccessibilityModeEditableTextOnly;
- }
-#endif // defined(OS_WIN)
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceRendererAccessibility)) {
accessibility_mode_ = AccessibilityModeComplete;
}
@@ -99,20 +83,10 @@ void BrowserAccessibilityStateImpl::ResetAccessibilityModeValue() {
void BrowserAccessibilityStateImpl::ResetAccessibilityMode() {
ResetAccessibilityModeValue();
- // Iterate over all RenderWidgetHosts, even swapped out ones in case
- // they become active again.
- scoped_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHostImpl::GetAllRenderWidgetHosts());
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- // Ignore processes that don't have a connection, such as crashed tabs.
- if (!widget->GetProcess()->HasConnection())
- continue;
- if (!widget->IsRenderView())
- continue;
-
- RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
- rwhi->ResetAccessibilityMode();
- }
+ std::vector<WebContentsImpl*> web_contents_vector =
+ WebContentsImpl::GetAllWebContents();
+ for (size_t i = 0; i < web_contents_vector.size(); ++i)
+ web_contents_vector[i]->SetAccessibilityMode(accessibility_mode());
}
bool BrowserAccessibilityStateImpl::IsAccessibleBrowser() {
@@ -139,7 +113,7 @@ void BrowserAccessibilityStateImpl::UpdateHistograms() {
UMA_HISTOGRAM_BOOLEAN("Accessibility.InvertedColors",
gfx::IsInvertedColorScheme());
UMA_HISTOGRAM_BOOLEAN("Accessibility.ManuallyEnabled",
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceRendererAccessibility));
}
@@ -150,7 +124,7 @@ void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
void BrowserAccessibilityStateImpl::AddAccessibilityMode(
AccessibilityMode mode) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererAccessibility)) {
return;
}
@@ -158,12 +132,12 @@ void BrowserAccessibilityStateImpl::AddAccessibilityMode(
accessibility_mode_ =
content::AddAccessibilityModeTo(accessibility_mode_, mode);
- AddOrRemoveFromRenderWidgets(mode, true);
+ AddOrRemoveFromAllWebContents(mode, true);
}
void BrowserAccessibilityStateImpl::RemoveAccessibilityMode(
AccessibilityMode mode) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceRendererAccessibility) &&
mode == AccessibilityModeComplete) {
return;
@@ -172,28 +146,19 @@ void BrowserAccessibilityStateImpl::RemoveAccessibilityMode(
accessibility_mode_ =
content::RemoveAccessibilityModeFrom(accessibility_mode_, mode);
- AddOrRemoveFromRenderWidgets(mode, false);
+ AddOrRemoveFromAllWebContents(mode, false);
}
-void BrowserAccessibilityStateImpl::AddOrRemoveFromRenderWidgets(
+void BrowserAccessibilityStateImpl::AddOrRemoveFromAllWebContents(
AccessibilityMode mode,
bool add) {
- // Iterate over all RenderWidgetHosts, even swapped out ones in case
- // they become active again.
- scoped_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHostImpl::GetAllRenderWidgetHosts());
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- // Ignore processes that don't have a connection, such as crashed tabs.
- if (!widget->GetProcess()->HasConnection())
- continue;
- if (!widget->IsRenderView())
- continue;
-
- RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(widget);
+ std::vector<WebContentsImpl*> web_contents_vector =
+ WebContentsImpl::GetAllWebContents();
+ for (size_t i = 0; i < web_contents_vector.size(); ++i) {
if (add)
- rwhi->AddAccessibilityMode(mode);
+ web_contents_vector[i]->AddAccessibilityMode(mode);
else
- rwhi->RemoveAccessibilityMode(mode);
+ web_contents_vector[i]->RemoveAccessibilityMode(mode);
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
index 2a1b1c6bb4b..4c8884373d6 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.h
@@ -10,7 +10,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/singleton.h"
-#include "content/common/view_message_enums.h"
+#include "content/common/accessibility_mode_enums.h"
#include "content/public/browser/browser_accessibility_state.h"
namespace content {
@@ -40,14 +40,14 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
static BrowserAccessibilityStateImpl* GetInstance();
- virtual void EnableAccessibility() OVERRIDE;
- virtual void DisableAccessibility() OVERRIDE;
- virtual void ResetAccessibilityMode() OVERRIDE;
- virtual void OnScreenReaderDetected() OVERRIDE;
- virtual bool IsAccessibleBrowser() OVERRIDE;
- virtual void AddHistogramCallback(base::Closure callback) OVERRIDE;
+ void EnableAccessibility() override;
+ void DisableAccessibility() override;
+ void ResetAccessibilityMode() override;
+ void OnScreenReaderDetected() override;
+ bool IsAccessibleBrowser() override;
+ void AddHistogramCallback(base::Closure callback) override;
- virtual void UpdateHistogramsForTesting() OVERRIDE;
+ void UpdateHistogramsForTesting() override;
AccessibilityMode accessibility_mode() const { return accessibility_mode_; };
@@ -72,13 +72,13 @@ class CONTENT_EXPORT BrowserAccessibilityStateImpl
void UpdateHistograms();
// Leaky singleton, destructor generally won't be called.
- virtual ~BrowserAccessibilityStateImpl();
+ ~BrowserAccessibilityStateImpl() override;
void UpdatePlatformSpecificHistograms();
- // Updates the accessibility mode of all render widgets, including swapped out
+ // Updates the accessibility mode of all web contents, including swapped out
// ones. |add| specifies whether the mode should be added or removed.
- void AddOrRemoveFromRenderWidgets(AccessibilityMode mode, bool add);
+ void AddOrRemoveFromAllWebContents(AccessibilityMode mode, bool add);
AccessibilityMode accessibility_mode_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index c5fa35898ff..924ad75105b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -21,6 +21,7 @@
#include "ui/accessibility/ax_text_utils.h"
#include "ui/base/win/accessibility_ids_win.h"
#include "ui/base/win/accessibility_misc_utils.h"
+#include "ui/base/win/atl_module.h"
namespace content {
@@ -179,6 +180,7 @@ STDMETHODIMP BrowserAccessibilityRelation::get_targets(long max_targets,
// static
BrowserAccessibility* BrowserAccessibility::Create() {
+ ui::win::CreateATLModuleIfNeeded();
CComObject<BrowserAccessibilityWin>* instance;
HRESULT hr = CComObject<BrowserAccessibilityWin>::CreateInstance(&instance);
DCHECK(SUCCEEDED(hr));
@@ -498,7 +500,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accParent(IDispatch** disp_parent) {
// This happens if we're the root of the tree;
// return the IAccessible for the window.
parent_obj =
- manager()->ToBrowserAccessibilityManagerWin()->parent_iaccessible();
+ manager()->ToBrowserAccessibilityManagerWin()->GetParentIAccessible();
// |parent| can only be NULL if the manager was created before the parent
// IAccessible was known and it wasn't subsequently set before a client
// requested it. This has been fixed. |parent| may also be NULL during
@@ -738,7 +740,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_windowHandle(HWND* window_handle) {
if (!window_handle)
return E_INVALIDARG;
- *window_handle = manager()->ToBrowserAccessibilityManagerWin()->parent_hwnd();
+ *window_handle =
+ manager()->ToBrowserAccessibilityManagerWin()->GetParentHWND();
if (!*window_handle)
return E_FAIL;
@@ -994,7 +997,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_imagePosition(
if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
HWND parent_hwnd =
- manager()->ToBrowserAccessibilityManagerWin()->parent_hwnd();
+ manager()->ToBrowserAccessibilityManagerWin()->GetParentHWND();
if (!parent_hwnd)
return E_FAIL;
POINT top_left = {0, 0};
@@ -2561,7 +2564,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_computedStyleForProperties(
for (unsigned short i = 0; i < num_style_properties; ++i) {
base::string16 name = (LPCWSTR)style_properties[i];
- StringToLowerASCII(&name);
+ base::StringToLowerASCII(&name);
if (name == L"display") {
base::string16 display = GetString16Attribute(
ui::AX_ATTR_DISPLAY);
@@ -2856,35 +2859,38 @@ STDMETHODIMP BrowserAccessibilityWin::GetPropertyValue(PROPERTYID id,
// CComObjectRootEx methods.
//
+// static
HRESULT WINAPI BrowserAccessibilityWin::InternalQueryInterface(
void* this_ptr,
const _ATL_INTMAP_ENTRY* entries,
REFIID iid,
void** object) {
+ int32 ia_role =
+ reinterpret_cast<BrowserAccessibilityWin*>(this_ptr)->ia_role_;
if (iid == IID_IAccessibleImage) {
- if (ia_role_ != ROLE_SYSTEM_GRAPHIC) {
+ if (ia_role != ROLE_SYSTEM_GRAPHIC) {
*object = NULL;
return E_NOINTERFACE;
}
} else if (iid == IID_IAccessibleTable || iid == IID_IAccessibleTable2) {
- if (ia_role_ != ROLE_SYSTEM_TABLE) {
+ if (ia_role != ROLE_SYSTEM_TABLE) {
*object = NULL;
return E_NOINTERFACE;
}
} else if (iid == IID_IAccessibleTableCell) {
- if (ia_role_ != ROLE_SYSTEM_CELL) {
+ if (ia_role != ROLE_SYSTEM_CELL) {
*object = NULL;
return E_NOINTERFACE;
}
} else if (iid == IID_IAccessibleValue) {
- if (ia_role_ != ROLE_SYSTEM_PROGRESSBAR &&
- ia_role_ != ROLE_SYSTEM_SCROLLBAR &&
- ia_role_ != ROLE_SYSTEM_SLIDER) {
+ if (ia_role != ROLE_SYSTEM_PROGRESSBAR &&
+ ia_role != ROLE_SYSTEM_SCROLLBAR &&
+ ia_role != ROLE_SYSTEM_SLIDER) {
*object = NULL;
return E_NOINTERFACE;
}
} else if (iid == IID_ISimpleDOMDocument) {
- if (ia_role_ != ROLE_SYSTEM_DOCUMENT) {
+ if (ia_role != ROLE_SYSTEM_DOCUMENT) {
*object = NULL;
return E_NOINTERFACE;
}
@@ -2906,6 +2912,7 @@ void BrowserAccessibilityWin::OnDataChanged() {
// Expose the "display" and "tag" attributes.
StringAttributeToIA2(ui::AX_ATTR_DISPLAY, "display");
+ StringAttributeToIA2(ui::AX_ATTR_TEXT_INPUT_TYPE, "text-input-type");
StringAttributeToIA2(ui::AX_ATTR_HTML_TAG, "tag");
StringAttributeToIA2(ui::AX_ATTR_ROLE, "xml-roles");
@@ -2924,6 +2931,8 @@ void BrowserAccessibilityWin::OnDataChanged() {
if (ia_role_ == ROLE_SYSTEM_CHECKBUTTON ||
ia_role_ == ROLE_SYSTEM_RADIOBUTTON ||
+ ia2_role_ == IA2_ROLE_CHECK_MENU_ITEM ||
+ ia2_role_ == IA2_ROLE_RADIO_MENU_ITEM ||
ia2_role_ == IA2_ROLE_TOGGLE_BUTTON) {
ia2_attributes_.push_back(L"checkable:true");
}
@@ -3173,7 +3182,7 @@ bool BrowserAccessibilityWin::IsNative() const {
return true;
}
-void BrowserAccessibilityWin::OnLocationChanged() const {
+void BrowserAccessibilityWin::OnLocationChanged() {
manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
EVENT_OBJECT_LOCATIONCHANGE, unique_id_win());
}
@@ -3388,9 +3397,16 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_APPLICATION;
break;
case ui::AX_ROLE_ARTICLE:
+ ia_role_ = ROLE_SYSTEM_DOCUMENT;
+ ia_state_ |= STATE_SYSTEM_READONLY;
+ break;
+ case ui::AX_ROLE_BANNER:
ia_role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_HEADER;
+ break;
+ case ui::AX_ROLE_BLOCKQUOTE:
+ role_name_ = html_tag;
ia2_role_ = IA2_ROLE_SECTION;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_BUSY_INDICATOR:
ia_role_ = ROLE_SYSTEM_ANIMATION;
@@ -3420,6 +3436,7 @@ void BrowserAccessibilityWin::InitRoleAndState() {
break;
case ui::AX_ROLE_CHECK_BOX:
ia_role_ = ROLE_SYSTEM_CHECKBUTTON;
+ ia2_state_ |= IA2_STATE_CHECKABLE;
break;
case ui::AX_ROLE_COLOR_WELL:
ia_role_ = ROLE_SYSTEM_CLIENT;
@@ -3427,17 +3444,32 @@ void BrowserAccessibilityWin::InitRoleAndState() {
break;
case ui::AX_ROLE_COLUMN:
ia_role_ = ROLE_SYSTEM_COLUMN;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_COLUMN_HEADER:
ia_role_ = ROLE_SYSTEM_COLUMNHEADER;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_COMBO_BOX:
ia_role_ = ROLE_SYSTEM_COMBOBOX;
break;
+ case ui::AX_ROLE_COMPLEMENTARY:
+ ia_role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_NOTE;
+ break;
+ case ui::AX_ROLE_CONTENT_INFO:
+ ia_role_ = ROLE_SYSTEM_TEXT;
+ ia2_role_ = IA2_ROLE_PARAGRAPH;
+ break;
+ case ui::AX_ROLE_DATE:
+ ia_role_ = ROLE_SYSTEM_DROPLIST;
+ ia2_role_ = IA2_ROLE_DATE_EDITOR;
+ break;
+ case ui::AX_ROLE_DATE_TIME:
+ ia_role_ = ROLE_SYSTEM_DROPLIST;
+ ia2_role_ = IA2_ROLE_DATE_EDITOR;
+ break;
case ui::AX_ROLE_DIV:
role_name_ = L"div";
+ ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
break;
case ui::AX_ROLE_DEFINITION:
@@ -3450,17 +3482,24 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_role_ = IA2_ROLE_PARAGRAPH;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
+ case ui::AX_ROLE_DESCRIPTION_LIST:
+ role_name_ = html_tag;
+ ia_role_ = ROLE_SYSTEM_LIST;
+ ia_state_ |= STATE_SYSTEM_READONLY;
+ break;
case ui::AX_ROLE_DESCRIPTION_LIST_TERM:
ia_role_ = ROLE_SYSTEM_LISTITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
+ case ui::AX_ROLE_DETAILS:
+ role_name_ = html_tag;
+ ia_role_ = ROLE_SYSTEM_GROUPING;
+ break;
case ui::AX_ROLE_DIALOG:
ia_role_ = ROLE_SYSTEM_DIALOG;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_DISCLOSURE_TRIANGLE:
- ia_role_ = ROLE_SYSTEM_OUTLINEBUTTON;
- ia_state_ |= STATE_SYSTEM_READONLY;
+ ia_role_ = ROLE_SYSTEM_PUSHBUTTON;
break;
case ui::AX_ROLE_DOCUMENT:
case ui::AX_ROLE_ROOT_WEB_AREA:
@@ -3474,6 +3513,15 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_state_ |= IA2_STATE_SINGLE_LINE;
ia2_state_ |= IA2_STATE_EDITABLE;
break;
+ case ui::AX_ROLE_FIGCAPTION:
+ role_name_ = html_tag;
+ ia2_role_ = IA2_ROLE_CAPTION;
+ break;
+ case ui::AX_ROLE_FIGURE:
+ role_name_ = html_tag;
+ ia_role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
case ui::AX_ROLE_FORM:
role_name_ = L"form";
ia2_role_ = IA2_ROLE_FORM;
@@ -3493,6 +3541,7 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_GROUPING;
} else if (html_tag == L"li") {
ia_role_ = ROLE_SYSTEM_LISTITEM;
+ ia_state_ |= STATE_SYSTEM_READONLY;
} else {
if (html_tag.empty())
role_name_ = L"div";
@@ -3500,7 +3549,6 @@ void BrowserAccessibilityWin::InitRoleAndState() {
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_SECTION;
}
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
}
case ui::AX_ROLE_GROW_AREA:
@@ -3510,14 +3558,14 @@ void BrowserAccessibilityWin::InitRoleAndState() {
case ui::AX_ROLE_HEADING:
role_name_ = html_tag;
ia2_role_ = IA2_ROLE_HEADING;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_HORIZONTAL_RULE:
ia_role_ = ROLE_SYSTEM_SEPARATOR;
break;
case ui::AX_ROLE_IFRAME:
- ia_role_ = ROLE_SYSTEM_CLIENT;
+ ia_role_ = ROLE_SYSTEM_DOCUMENT;
ia2_role_ = IA2_ROLE_INTERNAL_FRAME;
+ ia_state_ = STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_IMAGE:
ia_role_ = ROLE_SYSTEM_GRAPHIC;
@@ -3537,15 +3585,9 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_TEXT;
ia2_role_ = IA2_ROLE_LABEL;
break;
- case ui::AX_ROLE_BANNER:
- case ui::AX_ROLE_COMPLEMENTARY:
- case ui::AX_ROLE_CONTENT_INFO:
- case ui::AX_ROLE_MAIN:
- case ui::AX_ROLE_NAVIGATION:
case ui::AX_ROLE_SEARCH:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_SECTION;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_LINK:
ia_role_ = ROLE_SYSTEM_LINK;
@@ -3570,9 +3612,15 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_LISTITEM;
ia_state_ |= STATE_SYSTEM_READONLY;
break;
- case ui::AX_ROLE_MATH_ELEMENT:
+ case ui::AX_ROLE_MAIN:
+ ia_role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_PARAGRAPH;
+ break;
+ case ui::AX_ROLE_MARQUEE:
+ ia_role_ = ROLE_SYSTEM_ANIMATION;
+ break;
+ case ui::AX_ROLE_MATH:
ia_role_ = ROLE_SYSTEM_EQUATION;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_MENU:
case ui::AX_ROLE_MENU_BUTTON:
@@ -3584,6 +3632,15 @@ void BrowserAccessibilityWin::InitRoleAndState() {
case ui::AX_ROLE_MENU_ITEM:
ia_role_ = ROLE_SYSTEM_MENUITEM;
break;
+ case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ ia_role_ = ROLE_SYSTEM_MENUITEM;
+ ia2_role_ = IA2_ROLE_CHECK_MENU_ITEM;
+ ia2_state_ |= IA2_STATE_CHECKABLE;
+ break;
+ case ui::AX_ROLE_MENU_ITEM_RADIO:
+ ia_role_ = ROLE_SYSTEM_MENUITEM;
+ ia2_role_ = IA2_ROLE_RADIO_MENU_ITEM;
+ break;
case ui::AX_ROLE_MENU_LIST_POPUP:
ia_role_ = ROLE_SYSTEM_CLIENT;
break;
@@ -3595,6 +3652,14 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_state_ |= STATE_SYSTEM_FOCUSED;
}
break;
+ case ui::AX_ROLE_METER:
+ role_name_ = html_tag;
+ ia_role_ = ROLE_SYSTEM_PROGRESSBAR;
+ break;
+ case ui::AX_ROLE_NAVIGATION:
+ ia_role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
case ui::AX_ROLE_NOTE:
ia_role_ = ROLE_SYSTEM_GROUPING;
ia2_role_ = IA2_ROLE_NOTE;
@@ -3602,7 +3667,6 @@ void BrowserAccessibilityWin::InitRoleAndState() {
break;
case ui::AX_ROLE_OUTLINE:
ia_role_ = ROLE_SYSTEM_OUTLINE;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_PARAGRAPH:
role_name_ = L"P";
@@ -3615,6 +3679,11 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_BUTTONMENU;
}
break;
+ case ui::AX_ROLE_PRE:
+ role_name_ = html_tag;
+ ia_role_ = ROLE_SYSTEM_TEXT;
+ ia2_role_ = IA2_ROLE_PARAGRAPH;
+ break;
case ui::AX_ROLE_PROGRESS_INDICATOR:
ia_role_ = ROLE_SYSTEM_PROGRESSBAR;
ia_state_ |= STATE_SYSTEM_READONLY;
@@ -3624,20 +3693,20 @@ void BrowserAccessibilityWin::InitRoleAndState() {
break;
case ui::AX_ROLE_RADIO_GROUP:
ia_role_ = ROLE_SYSTEM_GROUPING;
- ia2_role_ = IA2_ROLE_SECTION;
break;
case ui::AX_ROLE_REGION:
- ia_role_ = ROLE_SYSTEM_GROUPING;
- ia2_role_ = IA2_ROLE_SECTION;
- ia_state_ |= STATE_SYSTEM_READONLY;
+ if (html_tag == L"section") {
+ ia_role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ } else {
+ ia_role_ = ROLE_SYSTEM_PANE;
+ }
break;
case ui::AX_ROLE_ROW:
ia_role_ = ROLE_SYSTEM_ROW;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_ROW_HEADER:
ia_role_ = ROLE_SYSTEM_ROWHEADER;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_RULER:
ia_role_ = ROLE_SYSTEM_CLIENT;
@@ -3692,7 +3761,6 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role_ = ROLE_SYSTEM_OUTLINE;
} else {
ia_role_ = ROLE_SYSTEM_TABLE;
- ia_state_ |= STATE_SYSTEM_READONLY;
}
break;
}
@@ -3723,6 +3791,9 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_state_ |= IA2_STATE_EDITABLE;
ia2_state_ |= IA2_STATE_SELECTABLE_TEXT;
break;
+ case ui::AX_ROLE_TIME:
+ ia_role_ = ROLE_SYSTEM_SPINBUTTON;
+ break;
case ui::AX_ROLE_TIMER:
ia_role_ = ROLE_SYSTEM_CLOCK;
ia_state_ |= STATE_SYSTEM_READONLY;
@@ -3737,15 +3808,12 @@ void BrowserAccessibilityWin::InitRoleAndState() {
break;
case ui::AX_ROLE_TREE:
ia_role_ = ROLE_SYSTEM_OUTLINE;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_TREE_GRID:
ia_role_ = ROLE_SYSTEM_OUTLINE;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_TREE_ITEM:
ia_role_ = ROLE_SYSTEM_OUTLINEITEM;
- ia_state_ |= STATE_SYSTEM_READONLY;
break;
case ui::AX_ROLE_WINDOW:
ia_role_ = ROLE_SYSTEM_WINDOW;
@@ -3759,8 +3827,8 @@ void BrowserAccessibilityWin::InitRoleAndState() {
case ui::AX_ROLE_IGNORED:
case ui::AX_ROLE_INCREMENTOR:
case ui::AX_ROLE_LOG:
- case ui::AX_ROLE_MARQUEE:
case ui::AX_ROLE_MATTE:
+ case ui::AX_ROLE_NONE:
case ui::AX_ROLE_PRESENTATIONAL:
case ui::AX_ROLE_RULER_MARKER:
case ui::AX_ROLE_SHEET:
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.h b/chromium/content/browser/accessibility/browser_accessibility_win.h
index 8dca2a8a9c8..cd339d53c91 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -100,88 +100,94 @@ BrowserAccessibilityWin
//
// BrowserAccessibility methods.
//
- CONTENT_EXPORT virtual void OnDataChanged() OVERRIDE;
- CONTENT_EXPORT virtual void OnUpdateFinished() OVERRIDE;
- CONTENT_EXPORT virtual void NativeAddReference() OVERRIDE;
- CONTENT_EXPORT virtual void NativeReleaseReference() OVERRIDE;
- CONTENT_EXPORT virtual bool IsNative() const OVERRIDE;
- CONTENT_EXPORT virtual void OnLocationChanged() const OVERRIDE;
+ CONTENT_EXPORT virtual void OnDataChanged() override;
+ CONTENT_EXPORT virtual void OnUpdateFinished() override;
+ CONTENT_EXPORT virtual void NativeAddReference() override;
+ CONTENT_EXPORT virtual void NativeReleaseReference() override;
+ CONTENT_EXPORT virtual bool IsNative() const override;
+ CONTENT_EXPORT virtual void OnLocationChanged() override;
//
// IAccessible methods.
//
// Performs the default action on a given object.
- CONTENT_EXPORT STDMETHODIMP accDoDefaultAction(VARIANT var_id);
+ CONTENT_EXPORT STDMETHODIMP accDoDefaultAction(VARIANT var_id) override;
// Retrieves the child element or child object at a given point on the screen.
- CONTENT_EXPORT STDMETHODIMP accHitTest(LONG x_left, LONG y_top,
- VARIANT* child);
+ CONTENT_EXPORT STDMETHODIMP
+ accHitTest(LONG x_left, LONG y_top, VARIANT* child) override;
// Retrieves the specified object's current screen location.
CONTENT_EXPORT STDMETHODIMP accLocation(LONG* x_left,
LONG* y_top,
LONG* width,
LONG* height,
- VARIANT var_id);
+ VARIANT var_id) override;
// Traverses to another UI element and retrieves the object.
- CONTENT_EXPORT STDMETHODIMP accNavigate(LONG nav_dir, VARIANT start,
- VARIANT* end);
+ CONTENT_EXPORT STDMETHODIMP
+ accNavigate(LONG nav_dir, VARIANT start, VARIANT* end) override;
// Retrieves an IDispatch interface pointer for the specified child.
- CONTENT_EXPORT STDMETHODIMP get_accChild(VARIANT var_child,
- IDispatch** disp_child);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accChild(VARIANT var_child, IDispatch** disp_child) override;
// Retrieves the number of accessible children.
- CONTENT_EXPORT STDMETHODIMP get_accChildCount(LONG* child_count);
+ CONTENT_EXPORT STDMETHODIMP get_accChildCount(LONG* child_count) override;
// Retrieves a string that describes the object's default action.
- CONTENT_EXPORT STDMETHODIMP get_accDefaultAction(VARIANT var_id,
- BSTR* default_action);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accDefaultAction(VARIANT var_id, BSTR* default_action) override;
// Retrieves the object's description.
- CONTENT_EXPORT STDMETHODIMP get_accDescription(VARIANT var_id, BSTR* desc);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accDescription(VARIANT var_id, BSTR* desc) override;
// Retrieves the object that has the keyboard focus.
- CONTENT_EXPORT STDMETHODIMP get_accFocus(VARIANT* focus_child);
+ CONTENT_EXPORT STDMETHODIMP get_accFocus(VARIANT* focus_child) override;
// Retrieves the help information associated with the object.
- CONTENT_EXPORT STDMETHODIMP get_accHelp(VARIANT var_id, BSTR* heflp);
+ CONTENT_EXPORT STDMETHODIMP get_accHelp(VARIANT var_id, BSTR* heflp) override;
// Retrieves the specified object's shortcut.
- CONTENT_EXPORT STDMETHODIMP get_accKeyboardShortcut(VARIANT var_id,
- BSTR* access_key);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accKeyboardShortcut(VARIANT var_id, BSTR* access_key) override;
// Retrieves the name of the specified object.
- CONTENT_EXPORT STDMETHODIMP get_accName(VARIANT var_id, BSTR* name);
+ CONTENT_EXPORT STDMETHODIMP get_accName(VARIANT var_id, BSTR* name) override;
// Retrieves the IDispatch interface of the object's parent.
- CONTENT_EXPORT STDMETHODIMP get_accParent(IDispatch** disp_parent);
+ CONTENT_EXPORT STDMETHODIMP get_accParent(IDispatch** disp_parent) override;
// Retrieves information describing the role of the specified object.
- CONTENT_EXPORT STDMETHODIMP get_accRole(VARIANT var_id, VARIANT* role);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accRole(VARIANT var_id, VARIANT* role) override;
// Retrieves the current state of the specified object.
- CONTENT_EXPORT STDMETHODIMP get_accState(VARIANT var_id, VARIANT* state);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accState(VARIANT var_id, VARIANT* state) override;
// Returns the value associated with the object.
- CONTENT_EXPORT STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accValue(VARIANT var_id, BSTR* value) override;
// Make an object take focus or extend the selection.
- CONTENT_EXPORT STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id);
+ CONTENT_EXPORT STDMETHODIMP
+ accSelect(LONG flags_sel, VARIANT var_id) override;
- CONTENT_EXPORT STDMETHODIMP get_accHelpTopic(BSTR* help_file,
- VARIANT var_id,
- LONG* topic_id);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accHelpTopic(BSTR* help_file, VARIANT var_id, LONG* topic_id) override;
- CONTENT_EXPORT STDMETHODIMP get_accSelection(VARIANT* selected);
+ CONTENT_EXPORT STDMETHODIMP get_accSelection(VARIANT* selected) override;
// Deprecated methods, not implemented.
- CONTENT_EXPORT STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name) {
+ CONTENT_EXPORT STDMETHODIMP
+ put_accName(VARIANT var_id, BSTR put_name) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val) {
+ CONTENT_EXPORT STDMETHODIMP
+ put_accValue(VARIANT var_id, BSTR put_val) override {
return E_NOTIMPL;
}
@@ -190,95 +196,99 @@ BrowserAccessibilityWin
//
// Returns role from a longer list of possible roles.
- CONTENT_EXPORT STDMETHODIMP role(LONG* role);
+ CONTENT_EXPORT STDMETHODIMP role(LONG* role) override;
// Returns the state bitmask from a larger set of possible states.
- CONTENT_EXPORT STDMETHODIMP get_states(AccessibleStates* states);
+ CONTENT_EXPORT STDMETHODIMP get_states(AccessibleStates* states) override;
// Returns the attributes specific to this IAccessible2 object,
// such as a cell's formula.
- CONTENT_EXPORT STDMETHODIMP get_attributes(BSTR* attributes);
+ CONTENT_EXPORT STDMETHODIMP get_attributes(BSTR* attributes) override;
// Get the unique ID of this object so that the client knows if it's
// been encountered previously.
- CONTENT_EXPORT STDMETHODIMP get_uniqueID(LONG* unique_id);
+ CONTENT_EXPORT STDMETHODIMP get_uniqueID(LONG* unique_id) override;
// Get the window handle of the enclosing window.
- CONTENT_EXPORT STDMETHODIMP get_windowHandle(HWND* window_handle);
+ CONTENT_EXPORT STDMETHODIMP get_windowHandle(HWND* window_handle) override;
// Get this object's index in its parent object.
- CONTENT_EXPORT STDMETHODIMP get_indexInParent(LONG* index_in_parent);
+ CONTENT_EXPORT STDMETHODIMP get_indexInParent(LONG* index_in_parent) override;
- CONTENT_EXPORT STDMETHODIMP get_nRelations(LONG* n_relations);
+ CONTENT_EXPORT STDMETHODIMP get_nRelations(LONG* n_relations) override;
- CONTENT_EXPORT STDMETHODIMP get_relation(LONG relation_index,
- IAccessibleRelation** relation);
+ CONTENT_EXPORT STDMETHODIMP
+ get_relation(LONG relation_index, IAccessibleRelation** relation) override;
CONTENT_EXPORT STDMETHODIMP get_relations(LONG max_relations,
IAccessibleRelation** relations,
- LONG* n_relations);
+ LONG* n_relations) override;
- CONTENT_EXPORT STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type);
+ CONTENT_EXPORT STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) override;
- CONTENT_EXPORT STDMETHODIMP scrollToPoint(
- enum IA2CoordinateType coordinate_type,
- LONG x,
- LONG y);
+ CONTENT_EXPORT STDMETHODIMP
+ scrollToPoint(enum IA2CoordinateType coordinate_type,
+ LONG x,
+ LONG y) override;
- CONTENT_EXPORT STDMETHODIMP get_groupPosition(LONG* group_level,
- LONG* similar_items_in_group,
- LONG* position_in_group);
+ CONTENT_EXPORT STDMETHODIMP
+ get_groupPosition(LONG* group_level,
+ LONG* similar_items_in_group,
+ LONG* position_in_group) override;
//
// IAccessibleEx methods not implemented.
//
- CONTENT_EXPORT STDMETHODIMP get_extendedRole(BSTR* extended_role) {
+ CONTENT_EXPORT STDMETHODIMP get_extendedRole(BSTR* extended_role) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_localizedExtendedRole(
- BSTR* localized_extended_role) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_localizedExtendedRole(BSTR* localized_extended_role) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_nExtendedStates(LONG* n_extended_states) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_nExtendedStates(LONG* n_extended_states) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_extendedStates(LONG max_extended_states,
- BSTR** extended_states,
- LONG* n_extended_states) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_extendedStates(LONG max_extended_states,
+ BSTR** extended_states,
+ LONG* n_extended_states) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_localizedExtendedStates(
- LONG max_localized_extended_states,
- BSTR** localized_extended_states,
- LONG* n_localized_extended_states) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_localizedExtendedStates(LONG max_localized_extended_states,
+ BSTR** localized_extended_states,
+ LONG* n_localized_extended_states) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_locale(IA2Locale* locale) {
+ CONTENT_EXPORT STDMETHODIMP get_locale(IA2Locale* locale) override {
return E_NOTIMPL;
}
//
// IAccessibleApplication methods.
//
- CONTENT_EXPORT STDMETHODIMP get_appName(BSTR* app_name);
+ CONTENT_EXPORT STDMETHODIMP get_appName(BSTR* app_name) override;
- CONTENT_EXPORT STDMETHODIMP get_appVersion(BSTR* app_version);
+ CONTENT_EXPORT STDMETHODIMP get_appVersion(BSTR* app_version) override;
- CONTENT_EXPORT STDMETHODIMP get_toolkitName(BSTR* toolkit_name);
+ CONTENT_EXPORT STDMETHODIMP get_toolkitName(BSTR* toolkit_name) override;
- CONTENT_EXPORT STDMETHODIMP get_toolkitVersion(BSTR* toolkit_version);
+ CONTENT_EXPORT STDMETHODIMP
+ get_toolkitVersion(BSTR* toolkit_version) override;
//
// IAccessibleImage methods.
//
- CONTENT_EXPORT STDMETHODIMP get_description(BSTR* description);
+ CONTENT_EXPORT STDMETHODIMP get_description(BSTR* description) override;
- CONTENT_EXPORT STDMETHODIMP get_imagePosition(
- enum IA2CoordinateType coordinate_type,
- LONG* x,
- LONG* y);
+ CONTENT_EXPORT STDMETHODIMP
+ get_imagePosition(enum IA2CoordinateType coordinate_type,
+ LONG* x,
+ LONG* y) override;
- CONTENT_EXPORT STDMETHODIMP get_imageSize(LONG* height, LONG* width);
+ CONTENT_EXPORT STDMETHODIMP get_imageSize(LONG* height, LONG* width) override;
//
// IAccessibleTable methods.
@@ -286,102 +296,96 @@ BrowserAccessibilityWin
// get_description - also used by IAccessibleImage
- CONTENT_EXPORT STDMETHODIMP get_accessibleAt(long row,
- long column,
- IUnknown** accessible);
+ CONTENT_EXPORT STDMETHODIMP
+ get_accessibleAt(long row, long column, IUnknown** accessible) override;
- CONTENT_EXPORT STDMETHODIMP get_caption(IUnknown** accessible);
+ CONTENT_EXPORT STDMETHODIMP get_caption(IUnknown** accessible) override;
- CONTENT_EXPORT STDMETHODIMP get_childIndex(long row_index,
- long column_index,
- long* cell_index);
+ CONTENT_EXPORT STDMETHODIMP
+ get_childIndex(long row_index, long column_index, long* cell_index) override;
- CONTENT_EXPORT STDMETHODIMP get_columnDescription(long column,
- BSTR* description);
+ CONTENT_EXPORT STDMETHODIMP
+ get_columnDescription(long column, BSTR* description) override;
- CONTENT_EXPORT STDMETHODIMP get_columnExtentAt(long row,
- long column,
- long* n_columns_spanned);
+ CONTENT_EXPORT STDMETHODIMP
+ get_columnExtentAt(long row, long column, long* n_columns_spanned) override;
- CONTENT_EXPORT STDMETHODIMP get_columnHeader(
- IAccessibleTable** accessible_table,
- long* starting_row_index);
+ CONTENT_EXPORT STDMETHODIMP
+ get_columnHeader(IAccessibleTable** accessible_table,
+ long* starting_row_index) override;
- CONTENT_EXPORT STDMETHODIMP get_columnIndex(long cell_index,
- long* column_index);
+ CONTENT_EXPORT STDMETHODIMP
+ get_columnIndex(long cell_index, long* column_index) override;
- CONTENT_EXPORT STDMETHODIMP get_nColumns(long* column_count);
+ CONTENT_EXPORT STDMETHODIMP get_nColumns(long* column_count) override;
- CONTENT_EXPORT STDMETHODIMP get_nRows(long* row_count);
+ CONTENT_EXPORT STDMETHODIMP get_nRows(long* row_count) override;
- CONTENT_EXPORT STDMETHODIMP get_nSelectedChildren(long* cell_count);
+ CONTENT_EXPORT STDMETHODIMP get_nSelectedChildren(long* cell_count) override;
- CONTENT_EXPORT STDMETHODIMP get_nSelectedColumns(long* column_count);
+ CONTENT_EXPORT STDMETHODIMP get_nSelectedColumns(long* column_count) override;
- CONTENT_EXPORT STDMETHODIMP get_nSelectedRows(long *row_count);
+ CONTENT_EXPORT STDMETHODIMP get_nSelectedRows(long* row_count) override;
- CONTENT_EXPORT STDMETHODIMP get_rowDescription(long row,
- BSTR* description);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowDescription(long row, BSTR* description) override;
- CONTENT_EXPORT STDMETHODIMP get_rowExtentAt(long row,
- long column,
- long* n_rows_spanned);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowExtentAt(long row, long column, long* n_rows_spanned) override;
- CONTENT_EXPORT STDMETHODIMP get_rowHeader(IAccessibleTable** accessible_table,
- long* starting_column_index);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowHeader(IAccessibleTable** accessible_table,
+ long* starting_column_index) override;
- CONTENT_EXPORT STDMETHODIMP get_rowIndex(long cell_index,
- long* row_index);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowIndex(long cell_index, long* row_index) override;
CONTENT_EXPORT STDMETHODIMP get_selectedChildren(long max_children,
long** children,
- long* n_children);
+ long* n_children) override;
CONTENT_EXPORT STDMETHODIMP get_selectedColumns(long max_columns,
long** columns,
- long* n_columns);
+ long* n_columns) override;
- CONTENT_EXPORT STDMETHODIMP get_selectedRows(long max_rows,
- long** rows,
- long* n_rows);
+ CONTENT_EXPORT STDMETHODIMP
+ get_selectedRows(long max_rows, long** rows, long* n_rows) override;
- CONTENT_EXPORT STDMETHODIMP get_summary(IUnknown** accessible);
+ CONTENT_EXPORT STDMETHODIMP get_summary(IUnknown** accessible) override;
- CONTENT_EXPORT STDMETHODIMP get_isColumnSelected(long column,
- boolean* is_selected);
+ CONTENT_EXPORT STDMETHODIMP
+ get_isColumnSelected(long column, boolean* is_selected) override;
- CONTENT_EXPORT STDMETHODIMP get_isRowSelected(long row,
- boolean* is_selected);
+ CONTENT_EXPORT STDMETHODIMP
+ get_isRowSelected(long row, boolean* is_selected) override;
- CONTENT_EXPORT STDMETHODIMP get_isSelected(long row,
- long column,
- boolean* is_selected);
+ CONTENT_EXPORT STDMETHODIMP
+ get_isSelected(long row, long column, boolean* is_selected) override;
- CONTENT_EXPORT STDMETHODIMP get_rowColumnExtentsAtIndex(long index,
- long* row,
- long* column,
- long* row_extents,
- long* column_extents,
- boolean* is_selected);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowColumnExtentsAtIndex(long index,
+ long* row,
+ long* column,
+ long* row_extents,
+ long* column_extents,
+ boolean* is_selected) override;
- CONTENT_EXPORT STDMETHODIMP selectRow(long row) {
- return E_NOTIMPL;
- }
+ CONTENT_EXPORT STDMETHODIMP selectRow(long row) override { return E_NOTIMPL; }
- CONTENT_EXPORT STDMETHODIMP selectColumn(long column) {
+ CONTENT_EXPORT STDMETHODIMP selectColumn(long column) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP unselectRow(long row) {
+ CONTENT_EXPORT STDMETHODIMP unselectRow(long row) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP unselectColumn(long column) {
+ CONTENT_EXPORT STDMETHODIMP unselectColumn(long column) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_modelChange(
- IA2TableModelChange* model_change) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_modelChange(IA2TableModelChange* model_change) override {
return E_NOTIMPL;
}
@@ -392,132 +396,136 @@ BrowserAccessibilityWin
// unique ones are included here.)
//
- CONTENT_EXPORT STDMETHODIMP get_cellAt(long row,
- long column,
- IUnknown** cell);
+ CONTENT_EXPORT STDMETHODIMP
+ get_cellAt(long row, long column, IUnknown** cell) override;
- CONTENT_EXPORT STDMETHODIMP get_nSelectedCells(long* cell_count);
+ CONTENT_EXPORT STDMETHODIMP get_nSelectedCells(long* cell_count) override;
- CONTENT_EXPORT STDMETHODIMP get_selectedCells(IUnknown*** cells,
- long* n_selected_cells);
+ CONTENT_EXPORT STDMETHODIMP
+ get_selectedCells(IUnknown*** cells, long* n_selected_cells) override;
- CONTENT_EXPORT STDMETHODIMP get_selectedColumns(long** columns,
- long* n_columns);
+ CONTENT_EXPORT STDMETHODIMP
+ get_selectedColumns(long** columns, long* n_columns) override;
- CONTENT_EXPORT STDMETHODIMP get_selectedRows(long** rows,
- long* n_rows);
+ CONTENT_EXPORT STDMETHODIMP
+ get_selectedRows(long** rows, long* n_rows) override;
//
// IAccessibleTableCell methods.
//
- CONTENT_EXPORT STDMETHODIMP get_columnExtent(long* n_columns_spanned);
+ CONTENT_EXPORT STDMETHODIMP
+ get_columnExtent(long* n_columns_spanned) override;
- CONTENT_EXPORT STDMETHODIMP get_columnHeaderCells(
- IUnknown*** cell_accessibles,
- long* n_column_header_cells);
+ CONTENT_EXPORT STDMETHODIMP
+ get_columnHeaderCells(IUnknown*** cell_accessibles,
+ long* n_column_header_cells) override;
- CONTENT_EXPORT STDMETHODIMP get_columnIndex(long* column_index);
+ CONTENT_EXPORT STDMETHODIMP get_columnIndex(long* column_index) override;
- CONTENT_EXPORT STDMETHODIMP get_rowExtent(long* n_rows_spanned);
+ CONTENT_EXPORT STDMETHODIMP get_rowExtent(long* n_rows_spanned) override;
- CONTENT_EXPORT STDMETHODIMP get_rowHeaderCells(IUnknown*** cell_accessibles,
- long* n_row_header_cells);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowHeaderCells(IUnknown*** cell_accessibles,
+ long* n_row_header_cells) override;
- CONTENT_EXPORT STDMETHODIMP get_rowIndex(long* row_index);
+ CONTENT_EXPORT STDMETHODIMP get_rowIndex(long* row_index) override;
- CONTENT_EXPORT STDMETHODIMP get_isSelected(boolean* is_selected);
+ CONTENT_EXPORT STDMETHODIMP get_isSelected(boolean* is_selected) override;
- CONTENT_EXPORT STDMETHODIMP get_rowColumnExtents(long* row,
- long* column,
- long* row_extents,
- long* column_extents,
- boolean* is_selected);
+ CONTENT_EXPORT STDMETHODIMP
+ get_rowColumnExtents(long* row,
+ long* column,
+ long* row_extents,
+ long* column_extents,
+ boolean* is_selected) override;
- CONTENT_EXPORT STDMETHODIMP get_table(IUnknown** table);
+ CONTENT_EXPORT STDMETHODIMP get_table(IUnknown** table) override;
//
// IAccessibleText methods.
//
- CONTENT_EXPORT STDMETHODIMP get_nCharacters(LONG* n_characters);
+ CONTENT_EXPORT STDMETHODIMP get_nCharacters(LONG* n_characters) override;
- CONTENT_EXPORT STDMETHODIMP get_caretOffset(LONG* offset);
+ CONTENT_EXPORT STDMETHODIMP get_caretOffset(LONG* offset) override;
- CONTENT_EXPORT STDMETHODIMP get_characterExtents(
- LONG offset,
- enum IA2CoordinateType coord_type,
- LONG* out_x,
- LONG* out_y,
- LONG* out_width,
- LONG* out_height);
+ CONTENT_EXPORT STDMETHODIMP
+ get_characterExtents(LONG offset,
+ enum IA2CoordinateType coord_type,
+ LONG* out_x,
+ LONG* out_y,
+ LONG* out_width,
+ LONG* out_height) override;
- CONTENT_EXPORT STDMETHODIMP get_nSelections(LONG* n_selections);
+ CONTENT_EXPORT STDMETHODIMP get_nSelections(LONG* n_selections) override;
CONTENT_EXPORT STDMETHODIMP get_selection(LONG selection_index,
LONG* start_offset,
- LONG* end_offset);
+ LONG* end_offset) override;
- CONTENT_EXPORT STDMETHODIMP get_text(LONG start_offset,
- LONG end_offset,
- BSTR* text);
+ CONTENT_EXPORT STDMETHODIMP
+ get_text(LONG start_offset, LONG end_offset, BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP get_textAtOffset(
- LONG offset,
- enum IA2TextBoundaryType boundary_type,
- LONG* start_offset,
- LONG* end_offset,
- BSTR* text);
+ CONTENT_EXPORT STDMETHODIMP
+ get_textAtOffset(LONG offset,
+ enum IA2TextBoundaryType boundary_type,
+ LONG* start_offset,
+ LONG* end_offset,
+ BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP get_textBeforeOffset(
- LONG offset,
- enum IA2TextBoundaryType boundary_type,
- LONG* start_offset,
- LONG* end_offset,
- BSTR* text);
+ CONTENT_EXPORT STDMETHODIMP
+ get_textBeforeOffset(LONG offset,
+ enum IA2TextBoundaryType boundary_type,
+ LONG* start_offset,
+ LONG* end_offset,
+ BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP get_textAfterOffset(
- LONG offset,
- enum IA2TextBoundaryType boundary_type,
- LONG* start_offset,
- LONG* end_offset,
- BSTR* text);
+ CONTENT_EXPORT STDMETHODIMP
+ get_textAfterOffset(LONG offset,
+ enum IA2TextBoundaryType boundary_type,
+ LONG* start_offset,
+ LONG* end_offset,
+ BSTR* text) override;
- CONTENT_EXPORT STDMETHODIMP get_newText(IA2TextSegment* new_text);
+ CONTENT_EXPORT STDMETHODIMP get_newText(IA2TextSegment* new_text) override;
- CONTENT_EXPORT STDMETHODIMP get_oldText(IA2TextSegment* old_text);
+ CONTENT_EXPORT STDMETHODIMP get_oldText(IA2TextSegment* old_text) override;
- CONTENT_EXPORT STDMETHODIMP get_offsetAtPoint(
- LONG x,
- LONG y,
- enum IA2CoordinateType coord_type,
- LONG* offset);
+ CONTENT_EXPORT STDMETHODIMP
+ get_offsetAtPoint(LONG x,
+ LONG y,
+ enum IA2CoordinateType coord_type,
+ LONG* offset) override;
- CONTENT_EXPORT STDMETHODIMP scrollSubstringTo(
- LONG start_index,
- LONG end_index,
- enum IA2ScrollType scroll_type);
+ CONTENT_EXPORT STDMETHODIMP
+ scrollSubstringTo(LONG start_index,
+ LONG end_index,
+ enum IA2ScrollType scroll_type) override;
- CONTENT_EXPORT STDMETHODIMP scrollSubstringToPoint(
- LONG start_index,
- LONG end_index,
- enum IA2CoordinateType coordinate_type,
- LONG x, LONG y);
+ CONTENT_EXPORT STDMETHODIMP
+ scrollSubstringToPoint(LONG start_index,
+ LONG end_index,
+ enum IA2CoordinateType coordinate_type,
+ LONG x,
+ LONG y) override;
- CONTENT_EXPORT STDMETHODIMP addSelection(LONG start_offset, LONG end_offset);
+ CONTENT_EXPORT STDMETHODIMP
+ addSelection(LONG start_offset, LONG end_offset) override;
- CONTENT_EXPORT STDMETHODIMP removeSelection(LONG selection_index);
+ CONTENT_EXPORT STDMETHODIMP removeSelection(LONG selection_index) override;
- CONTENT_EXPORT STDMETHODIMP setCaretOffset(LONG offset);
+ CONTENT_EXPORT STDMETHODIMP setCaretOffset(LONG offset) override;
CONTENT_EXPORT STDMETHODIMP setSelection(LONG selection_index,
LONG start_offset,
- LONG end_offset);
+ LONG end_offset) override;
// IAccessibleText methods not implemented.
- CONTENT_EXPORT STDMETHODIMP get_attributes(LONG offset, LONG* start_offset,
+ CONTENT_EXPORT STDMETHODIMP get_attributes(LONG offset,
+ LONG* start_offset,
LONG* end_offset,
- BSTR* text_attributes) {
+ BSTR* text_attributes) override {
return E_NOTIMPL;
}
@@ -525,54 +533,54 @@ BrowserAccessibilityWin
// IAccessibleHypertext methods.
//
- CONTENT_EXPORT STDMETHODIMP get_nHyperlinks(long* hyperlink_count);
+ CONTENT_EXPORT STDMETHODIMP get_nHyperlinks(long* hyperlink_count) override;
- CONTENT_EXPORT STDMETHODIMP get_hyperlink(long index,
- IAccessibleHyperlink** hyperlink);
+ CONTENT_EXPORT STDMETHODIMP
+ get_hyperlink(long index, IAccessibleHyperlink** hyperlink) override;
- CONTENT_EXPORT STDMETHODIMP get_hyperlinkIndex(long char_index,
- long* hyperlink_index);
+ CONTENT_EXPORT STDMETHODIMP
+ get_hyperlinkIndex(long char_index, long* hyperlink_index) override;
// IAccessibleHyperlink not implemented.
- CONTENT_EXPORT STDMETHODIMP get_anchor(long index, VARIANT* anchor) {
+ CONTENT_EXPORT STDMETHODIMP get_anchor(long index, VARIANT* anchor) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_anchorTarget(long index,
- VARIANT* anchor_target) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_anchorTarget(long index, VARIANT* anchor_target) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_startIndex( long* index) {
+ CONTENT_EXPORT STDMETHODIMP get_startIndex(long* index) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_endIndex( long* index) {
+ CONTENT_EXPORT STDMETHODIMP get_endIndex(long* index) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_valid(boolean* valid) {
+ CONTENT_EXPORT STDMETHODIMP get_valid(boolean* valid) override {
return E_NOTIMPL;
}
// IAccessibleAction not implemented.
- CONTENT_EXPORT STDMETHODIMP nActions(long* n_actions) {
+ CONTENT_EXPORT STDMETHODIMP nActions(long* n_actions) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP doAction(long action_index) {
+ CONTENT_EXPORT STDMETHODIMP doAction(long action_index) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_description(long action_index,
- BSTR* description) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_description(long action_index, BSTR* description) override {
return E_NOTIMPL;
}
CONTENT_EXPORT STDMETHODIMP get_keyBinding(long action_index,
long n_max_bindings,
BSTR** key_bindings,
- long* n_bindings) {
+ long* n_bindings) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_name(long action_index, BSTR* name) {
+ CONTENT_EXPORT STDMETHODIMP get_name(long action_index, BSTR* name) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_localizedName(long action_index,
- BSTR* localized_name) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_localizedName(long action_index, BSTR* localized_name) override {
return E_NOTIMPL;
}
@@ -580,32 +588,32 @@ BrowserAccessibilityWin
// IAccessibleValue methods.
//
- CONTENT_EXPORT STDMETHODIMP get_currentValue(VARIANT* value);
+ CONTENT_EXPORT STDMETHODIMP get_currentValue(VARIANT* value) override;
- CONTENT_EXPORT STDMETHODIMP get_minimumValue(VARIANT* value);
+ CONTENT_EXPORT STDMETHODIMP get_minimumValue(VARIANT* value) override;
- CONTENT_EXPORT STDMETHODIMP get_maximumValue(VARIANT* value);
+ CONTENT_EXPORT STDMETHODIMP get_maximumValue(VARIANT* value) override;
- CONTENT_EXPORT STDMETHODIMP setCurrentValue(VARIANT new_value);
+ CONTENT_EXPORT STDMETHODIMP setCurrentValue(VARIANT new_value) override;
//
// ISimpleDOMDocument methods.
//
- CONTENT_EXPORT STDMETHODIMP get_URL(BSTR* url);
+ CONTENT_EXPORT STDMETHODIMP get_URL(BSTR* url) override;
- CONTENT_EXPORT STDMETHODIMP get_title(BSTR* title);
+ CONTENT_EXPORT STDMETHODIMP get_title(BSTR* title) override;
- CONTENT_EXPORT STDMETHODIMP get_mimeType(BSTR* mime_type);
+ CONTENT_EXPORT STDMETHODIMP get_mimeType(BSTR* mime_type) override;
- CONTENT_EXPORT STDMETHODIMP get_docType(BSTR* doc_type);
+ CONTENT_EXPORT STDMETHODIMP get_docType(BSTR* doc_type) override;
- CONTENT_EXPORT STDMETHODIMP get_nameSpaceURIForID(short name_space_id,
- BSTR* name_space_uri) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_nameSpaceURIForID(short name_space_id, BSTR* name_space_uri) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP put_alternateViewMediaTypes(
- BSTR* comma_separated_media_types) {
+ CONTENT_EXPORT STDMETHODIMP
+ put_alternateViewMediaTypes(BSTR* comma_separated_media_types) override {
return E_NOTIMPL;
}
@@ -618,57 +626,60 @@ BrowserAccessibilityWin
BSTR* node_value,
unsigned int* num_children,
unsigned int* unique_id,
- unsigned short* node_type);
+ unsigned short* node_type) override;
- CONTENT_EXPORT STDMETHODIMP get_attributes(unsigned short max_attribs,
- BSTR* attrib_names,
- short* name_space_id,
- BSTR* attrib_values,
- unsigned short* num_attribs);
+ CONTENT_EXPORT STDMETHODIMP
+ get_attributes(unsigned short max_attribs,
+ BSTR* attrib_names,
+ short* name_space_id,
+ BSTR* attrib_values,
+ unsigned short* num_attribs) override;
- CONTENT_EXPORT STDMETHODIMP get_attributesForNames(
- unsigned short num_attribs,
- BSTR* attrib_names,
- short* name_space_id,
- BSTR* attrib_values);
+ CONTENT_EXPORT STDMETHODIMP
+ get_attributesForNames(unsigned short num_attribs,
+ BSTR* attrib_names,
+ short* name_space_id,
+ BSTR* attrib_values) override;
- CONTENT_EXPORT STDMETHODIMP get_computedStyle(
- unsigned short max_style_properties,
- boolean use_alternate_view,
- BSTR *style_properties,
- BSTR *style_values,
- unsigned short *num_style_properties);
+ CONTENT_EXPORT STDMETHODIMP
+ get_computedStyle(unsigned short max_style_properties,
+ boolean use_alternate_view,
+ BSTR* style_properties,
+ BSTR* style_values,
+ unsigned short* num_style_properties) override;
- CONTENT_EXPORT STDMETHODIMP get_computedStyleForProperties(
- unsigned short num_style_properties,
- boolean use_alternate_view,
- BSTR* style_properties,
- BSTR* style_values);
+ CONTENT_EXPORT STDMETHODIMP
+ get_computedStyleForProperties(unsigned short num_style_properties,
+ boolean use_alternate_view,
+ BSTR* style_properties,
+ BSTR* style_values) override;
- CONTENT_EXPORT STDMETHODIMP scrollTo(boolean placeTopLeft);
+ CONTENT_EXPORT STDMETHODIMP scrollTo(boolean placeTopLeft) override;
- CONTENT_EXPORT STDMETHODIMP get_parentNode(ISimpleDOMNode** node);
+ CONTENT_EXPORT STDMETHODIMP get_parentNode(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_firstChild(ISimpleDOMNode** node);
+ CONTENT_EXPORT STDMETHODIMP get_firstChild(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_lastChild(ISimpleDOMNode** node);
+ CONTENT_EXPORT STDMETHODIMP get_lastChild(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_previousSibling(ISimpleDOMNode** node);
+ CONTENT_EXPORT STDMETHODIMP
+ get_previousSibling(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_nextSibling(ISimpleDOMNode** node);
+ CONTENT_EXPORT STDMETHODIMP get_nextSibling(ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_childAt(unsigned int child_index,
- ISimpleDOMNode** node);
+ CONTENT_EXPORT STDMETHODIMP
+ get_childAt(unsigned int child_index, ISimpleDOMNode** node) override;
- CONTENT_EXPORT STDMETHODIMP get_innerHTML(BSTR* innerHTML) {
+ CONTENT_EXPORT STDMETHODIMP get_innerHTML(BSTR* innerHTML) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_localInterface(void** local_interface) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_localInterface(void** local_interface) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_language(BSTR* language) {
+ CONTENT_EXPORT STDMETHODIMP get_language(BSTR* language) override {
return E_NOTIMPL;
}
@@ -676,28 +687,28 @@ BrowserAccessibilityWin
// ISimpleDOMText methods.
//
- CONTENT_EXPORT STDMETHODIMP get_domText(BSTR* dom_text);
+ CONTENT_EXPORT STDMETHODIMP get_domText(BSTR* dom_text) override;
- CONTENT_EXPORT STDMETHODIMP get_clippedSubstringBounds(
- unsigned int start_index,
- unsigned int end_index,
- int* out_x,
- int* out_y,
- int* out_width,
- int* out_height);
+ CONTENT_EXPORT STDMETHODIMP
+ get_clippedSubstringBounds(unsigned int start_index,
+ unsigned int end_index,
+ int* out_x,
+ int* out_y,
+ int* out_width,
+ int* out_height) override;
- CONTENT_EXPORT STDMETHODIMP get_unclippedSubstringBounds(
- unsigned int start_index,
- unsigned int end_index,
- int* out_x,
- int* out_y,
- int* out_width,
- int* out_height);
+ CONTENT_EXPORT STDMETHODIMP
+ get_unclippedSubstringBounds(unsigned int start_index,
+ unsigned int end_index,
+ int* out_x,
+ int* out_y,
+ int* out_width,
+ int* out_height) override;
- CONTENT_EXPORT STDMETHODIMP scrollToSubstring(unsigned int start_index,
- unsigned int end_index);
+ CONTENT_EXPORT STDMETHODIMP
+ scrollToSubstring(unsigned int start_index, unsigned int end_index) override;
- CONTENT_EXPORT STDMETHODIMP get_fontFamily(BSTR *font_family) {
+ CONTENT_EXPORT STDMETHODIMP get_fontFamily(BSTR* font_family) override {
return E_NOTIMPL;
}
@@ -705,28 +716,27 @@ BrowserAccessibilityWin
// IServiceProvider methods.
//
- CONTENT_EXPORT STDMETHODIMP QueryService(REFGUID guidService,
- REFIID riid,
- void** object);
+ CONTENT_EXPORT STDMETHODIMP
+ QueryService(REFGUID guidService, REFIID riid, void** object) override;
// IAccessibleEx methods not implemented.
- CONTENT_EXPORT STDMETHODIMP GetObjectForChild(long child_id,
- IAccessibleEx** ret) {
+ CONTENT_EXPORT STDMETHODIMP
+ GetObjectForChild(long child_id, IAccessibleEx** ret) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP GetIAccessiblePair(IAccessible** acc,
- long* child_id) {
+ CONTENT_EXPORT STDMETHODIMP
+ GetIAccessiblePair(IAccessible** acc, long* child_id) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP GetRuntimeId(SAFEARRAY** runtime_id) {
+ CONTENT_EXPORT STDMETHODIMP GetRuntimeId(SAFEARRAY** runtime_id) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP ConvertReturnedElement(
- IRawElementProviderSimple* element,
- IAccessibleEx** acc) {
+ CONTENT_EXPORT STDMETHODIMP
+ ConvertReturnedElement(IRawElementProviderSimple* element,
+ IAccessibleEx** acc) override {
return E_NOTIMPL;
}
@@ -735,19 +745,21 @@ BrowserAccessibilityWin
//
// The GetPatternProvider/GetPropertyValue methods need to be implemented for
// the on-screen keyboard to show up in Windows 8 metro.
- CONTENT_EXPORT STDMETHODIMP GetPatternProvider(PATTERNID id,
- IUnknown** provider);
- CONTENT_EXPORT STDMETHODIMP GetPropertyValue(PROPERTYID id, VARIANT* ret);
+ CONTENT_EXPORT STDMETHODIMP
+ GetPatternProvider(PATTERNID id, IUnknown** provider) override;
+ CONTENT_EXPORT STDMETHODIMP
+ GetPropertyValue(PROPERTYID id, VARIANT* ret) override;
//
// IRawElementProviderSimple methods not implemented
//
- CONTENT_EXPORT STDMETHODIMP get_ProviderOptions(enum ProviderOptions* ret) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_ProviderOptions(enum ProviderOptions* ret) override {
return E_NOTIMPL;
}
- CONTENT_EXPORT STDMETHODIMP get_HostRawElementProvider(
- IRawElementProviderSimple** provider) {
+ CONTENT_EXPORT STDMETHODIMP
+ get_HostRawElementProvider(IRawElementProviderSimple** provider) override {
return E_NOTIMPL;
}
@@ -755,11 +767,12 @@ BrowserAccessibilityWin
// CComObjectRootEx methods.
//
- CONTENT_EXPORT HRESULT WINAPI InternalQueryInterface(
- void* this_ptr,
- const _ATL_INTMAP_ENTRY* entries,
- REFIID iid,
- void** object);
+ // Called by BEGIN_COM_MAP() / END_COM_MAP().
+ static CONTENT_EXPORT HRESULT WINAPI
+ InternalQueryInterface(void* this_ptr,
+ const _ATL_INTMAP_ENTRY* entries,
+ REFIID iid,
+ void** object);
// Accessors.
int32 ia_role() const { return ia_role_; }
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index eca0d911711..ccda97873d7 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -11,7 +11,6 @@
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
-#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
#include "content/common/accessibility_messages.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/win/atl_module.h"
@@ -59,7 +58,7 @@ class CountedBrowserAccessibilityFactory : public BrowserAccessibilityFactory {
private:
virtual ~CountedBrowserAccessibilityFactory();
- virtual BrowserAccessibility* Create() OVERRIDE;
+ virtual BrowserAccessibility* Create() override;
DISALLOW_COPY_AND_ASSIGN(CountedBrowserAccessibilityFactory);
};
@@ -90,7 +89,7 @@ class BrowserAccessibilityTest : public testing::Test {
virtual ~BrowserAccessibilityTest();
private:
- virtual void SetUp() OVERRIDE;
+ virtual void SetUp() override;
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityTest);
};
@@ -605,12 +604,8 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
const int32 busy_state = 1 << ui::AX_STATE_BUSY;
const int32 readonly_state = 1 << ui::AX_STATE_READ_ONLY;
const int32 enabled_state = 1 << ui::AX_STATE_ENABLED;
- scoped_ptr<content::LegacyRenderWidgetHostHWND> accessible_hwnd(
- content::LegacyRenderWidgetHostHWND::Create(GetDesktopWindow()));
scoped_ptr<BrowserAccessibilityManager> manager(
new BrowserAccessibilityManagerWin(
- accessible_hwnd.get(),
- NULL,
BrowserAccessibilityManagerWin::GetEmptyDocument(),
NULL,
new CountedBrowserAccessibilityFactory()));
@@ -683,57 +678,29 @@ TEST_F(BrowserAccessibilityTest, TestCreateEmptyDocument) {
ASSERT_EQ(0, CountedBrowserAccessibility::num_instances());
}
-TEST(BrowserAccessibilityManagerWinTest, TestAccessibleHWND) {
- HWND desktop_hwnd = GetDesktopWindow();
- base::win::ScopedComPtr<IAccessible> desktop_hwnd_iaccessible;
- ASSERT_EQ(S_OK, AccessibleObjectFromWindow(
- desktop_hwnd, OBJID_CLIENT,
- IID_IAccessible,
- reinterpret_cast<void**>(desktop_hwnd_iaccessible.Receive())));
-
- scoped_ptr<content::LegacyRenderWidgetHostHWND> accessible_hwnd(
- content::LegacyRenderWidgetHostHWND::Create(GetDesktopWindow()));
-
+// This is a regression test for a bug where the initial empty document
+// loaded by a BrowserAccessibilityManagerWin couldn't be looked up by
+// its UniqueIDWin, because the AX Tree was loaded in
+// BrowserAccessibilityManager code before BrowserAccessibilityManagerWin
+// was initialized.
+TEST_F(BrowserAccessibilityTest, EmptyDocHasUniqueIdWin) {
scoped_ptr<BrowserAccessibilityManagerWin> manager(
new BrowserAccessibilityManagerWin(
- accessible_hwnd.get(),
- desktop_hwnd_iaccessible,
BrowserAccessibilityManagerWin::GetEmptyDocument(),
- NULL));
- ASSERT_EQ(desktop_hwnd, manager->parent_hwnd());
-
- // Enabling screen reader support and calling MaybeCallNotifyWinEvent
- // should trigger creating the AccessibleHWND, and we should now get a
- // new parent_hwnd with the right window class to fool older screen
- // readers.
- BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected();
- manager->MaybeCallNotifyWinEvent(0, 0);
- HWND new_parent_hwnd = manager->parent_hwnd();
- ASSERT_NE(desktop_hwnd, new_parent_hwnd);
- WCHAR hwnd_class_name[256];
- ASSERT_NE(0, GetClassName(new_parent_hwnd, hwnd_class_name, 256));
- ASSERT_STREQ(L"Chrome_RenderWidgetHostHWND", hwnd_class_name);
-
- // Destroy the hwnd explicitly; that should trigger clearing parent_hwnd().
- DestroyWindow(new_parent_hwnd);
- ASSERT_EQ(NULL, manager->parent_hwnd());
-
- // Now create it again.
- accessible_hwnd = content::LegacyRenderWidgetHostHWND::Create(
- GetDesktopWindow());
- manager.reset(
- new BrowserAccessibilityManagerWin(
- accessible_hwnd.get(),
- desktop_hwnd_iaccessible,
- BrowserAccessibilityManagerWin::GetEmptyDocument(),
- NULL));
- manager->MaybeCallNotifyWinEvent(0, 0);
- new_parent_hwnd = manager->parent_hwnd();
- ASSERT_FALSE(NULL == new_parent_hwnd);
-
- // This time, destroy the manager first, make sure the AccessibleHWND doesn't
- // crash on destruction (to be caught by SyzyASAN or other tools).
- manager.reset(NULL);
+ NULL,
+ new CountedBrowserAccessibilityFactory()));
+
+ // Verify the root is as we expect by default.
+ BrowserAccessibility* root = manager->GetRoot();
+ EXPECT_EQ(0, root->GetId());
+ EXPECT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, root->GetRole());
+ EXPECT_EQ(1 << ui::AX_STATE_BUSY |
+ 1 << ui::AX_STATE_READ_ONLY |
+ 1 << ui::AX_STATE_ENABLED,
+ root->GetState());
+
+ LONG unique_id_win = root->ToBrowserAccessibilityWin()->unique_id_win();
+ ASSERT_EQ(root, manager->GetFromUniqueIdWin(unique_id_win));
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 06b72962fd2..8f83ed97b10 100644
--- a/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -57,8 +57,8 @@ class CrossPlatformAccessibilityBrowserTest : public ContentBrowserTest {
}
// ContentBrowserTest
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
- virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
+ void SetUpInProcessBrowserTestFixture() override;
+ void TearDownInProcessBrowserTestFixture() override;
protected:
std::string GetAttr(const ui::AXNode* node,
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index d373f7b8757..fbe8f475b32 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -7,7 +7,7 @@
#include <vector>
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string16.h"
@@ -19,6 +19,7 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
@@ -29,6 +30,10 @@
#include "content/test/accessibility_browser_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#endif
+
// TODO(aboxhall): Create expectations on Android for these
#if defined(OS_ANDROID)
#define MAYBE(x) DISABLED_##x
@@ -90,11 +95,31 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
void AddDefaultFilters(std::vector<Filter>* filters) {
filters->push_back(Filter(base::ASCIIToUTF16("FOCUSABLE"), Filter::ALLOW));
filters->push_back(Filter(base::ASCIIToUTF16("READONLY"), Filter::ALLOW));
+ filters->push_back(Filter(base::ASCIIToUTF16("name*"), Filter::ALLOW));
filters->push_back(Filter(base::ASCIIToUTF16("*=''"), Filter::DENY));
}
- void ParseFilters(const std::string& test_html,
- std::vector<Filter>* filters) {
+ // Parse the test html file and parse special directives, usually
+ // beginning with an '@' and inside an HTML comment, that control how the
+ // test is run and how the results are interpreted.
+ //
+ // When the accessibility tree is dumped as text, each attribute is
+ // run through filters before being appended to the string. An "allow"
+ // filter specifies attribute strings that should be dumped, and a "deny"
+ // filter specifies strings that should be suppressed. As an example,
+ // @MAC-ALLOW:AXSubrole=* means that the AXSubrole attribute should be
+ // printed, while @MAC-ALLOW:AXSubrole=AXList* means that any subrole
+ // beginning with the text "AXList" should be printed.
+ //
+ // The @WAIT-FOR:text directive allows the test to specify that the document
+ // may dynamically change after initial load, and the test is to wait
+ // until the given string (e.g., "text") appears in the resulting dump.
+ // A test can make some changes to the document, then append a magic string
+ // indicating that the test is done, and this framework will wait for that
+ // string to appear before comparing the results.
+ void ParseHtmlForExtraDirectives(const std::string& test_html,
+ std::vector<Filter>* filters,
+ std::string* wait_for) {
std::vector<std::string> lines;
base::SplitString(test_html, '\n', &lines);
for (std::vector<std::string>::const_iterator iter = lines.begin();
@@ -107,6 +132,7 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
AccessibilityTreeFormatter::GetAllowString();
const std::string& deny_str =
AccessibilityTreeFormatter::GetDenyString();
+ const std::string& wait_str = "@WAIT-FOR:";
if (StartsWithASCII(line, allow_empty_str, true)) {
filters->push_back(
Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
@@ -119,14 +145,16 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
filters->push_back(Filter(base::UTF8ToUTF16(
line.substr(deny_str.size())),
Filter::DENY));
+ } else if (StartsWithASCII(line, wait_str, true)) {
+ *wait_for = line.substr(wait_str.size());
}
}
}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(base::CommandLine* command_line) override {
ContentBrowserTest::SetUpCommandLine(command_line);
// Enable <dialog>, which is used in some tests.
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
@@ -170,32 +198,52 @@ void DumpAccessibilityTreeTest::RunTest(
return;
}
+ // Parse filters and other directives in the test file.
+ std::vector<Filter> filters;
+ std::string wait_for;
+ AddDefaultFilters(&filters);
+ ParseHtmlForExtraDirectives(html_contents, &filters, &wait_for);
+
// Load the page.
base::string16 html_contents16;
html_contents16 = base::UTF8ToUTF16(html_contents);
GURL url = GetTestUrl("accessibility",
html_file.BaseName().MaybeAsASCII().c_str());
- AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
- NavigateToURL(shell(), url);
- waiter.WaitForNotification();
- RenderWidgetHostViewBase* host_view = static_cast<RenderWidgetHostViewBase*>(
- shell()->web_contents()->GetRenderWidgetHostView());
- AccessibilityTreeFormatter formatter(
- host_view->GetBrowserAccessibilityManager()->GetRoot());
+ // If there's a @WAIT-FOR directive, set up an accessibility notification
+ // waiter that returns on any event; we'll stop when we get the text we're
+ // waiting for, or time out. Otherwise just wait specifically for
+ // the "load complete" event.
+ scoped_ptr<AccessibilityNotificationWaiter> waiter;
+ if (!wait_for.empty()) {
+ waiter.reset(new AccessibilityNotificationWaiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_NONE));
+ } else {
+ waiter.reset(new AccessibilityNotificationWaiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE));
+ }
- // Parse filters in the test file.
- std::vector<Filter> filters;
- AddDefaultFilters(&filters);
- ParseFilters(html_contents, &filters);
- formatter.SetFilters(filters);
+ // Load the test html.
+ NavigateToURL(shell(), url);
+
+ // Wait for notifications. If there's a @WAIT-FOR directive, break when
+ // the text we're waiting for appears in the dump, otherwise break after
+ // the first notification, which will be a load complete.
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ shell()->web_contents());
+ std::string actual_contents;
+ do {
+ waiter->WaitForNotification();
+ base::string16 actual_contents_utf16;
+ AccessibilityTreeFormatter formatter(
+ web_contents->GetRootBrowserAccessibilityManager()->GetRoot());
+ formatter.SetFilters(filters);
+ formatter.FormatAccessibilityTree(&actual_contents_utf16);
+ actual_contents = base::UTF16ToUTF8(actual_contents_utf16);
+ } while (!wait_for.empty() &&
+ actual_contents.find(wait_for) == std::string::npos);
// Perform a diff (or write the initial baseline).
- base::string16 actual_contents_utf16;
- formatter.FormatAccessibilityTree(&actual_contents_utf16);
- std::string actual_contents = base::UTF16ToUTF8(actual_contents_utf16);
std::vector<std::string> actual_lines, expected_lines;
Tokenize(actual_contents, "\n", &actual_lines);
Tokenize(expected_contents, "\n", &expected_lines);
@@ -246,14 +294,26 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
RunTest(FILE_PATH_LITERAL("a.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAbbr) {
+ RunTest(FILE_PATH_LITERAL("abbr.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAddress) {
RunTest(FILE_PATH_LITERAL("address.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityArea) {
+ RunTest(FILE_PATH_LITERAL("area.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAName) {
RunTest(FILE_PATH_LITERAL("a-name.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityANameCalc) {
+ RunTest(FILE_PATH_LITERAL("a-name-calc.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityANoText) {
RunTest(FILE_PATH_LITERAL("a-no-text.html"));
}
@@ -263,15 +323,57 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAOnclick) {
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaActivedescendant) {
+ RunTest(FILE_PATH_LITERAL("aria-activedescendant.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaAlert) {
+ RunTest(FILE_PATH_LITERAL("aria-alert.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityAriaApplication) {
RunTest(FILE_PATH_LITERAL("aria-application.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaArticle) {
+ RunTest(FILE_PATH_LITERAL("aria-article.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaAtomic) {
+ RunTest(FILE_PATH_LITERAL("aria-atomic.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityAriaAutocomplete) {
RunTest(FILE_PATH_LITERAL("aria-autocomplete.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaBanner) {
+ RunTest(FILE_PATH_LITERAL("aria-banner.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaBusy) {
+ RunTest(FILE_PATH_LITERAL("aria-busy.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaButton) {
+ RunTest(FILE_PATH_LITERAL("aria-button.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaCheckBox) {
+ RunTest(FILE_PATH_LITERAL("aria-checkbox.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaChecked) {
+ RunTest(FILE_PATH_LITERAL("aria-checked.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaColumnHeader) {
+ RunTest(FILE_PATH_LITERAL("aria-columnheader.html"));
+}
+
// crbug.com/98976 will cause new elements to be added to the Blink a11y tree
// Re-baseline after the Blink change goes in
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
@@ -280,10 +382,48 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaComplementary) {
+ RunTest(FILE_PATH_LITERAL("aria-complementary.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaContentInfo) {
+ RunTest(FILE_PATH_LITERAL("aria-contentinfo.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaDefinition) {
+ RunTest(FILE_PATH_LITERAL("aria-definition.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaDialog) {
+ RunTest(FILE_PATH_LITERAL("aria-dialog.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaExpanded) {
+ RunTest(FILE_PATH_LITERAL("aria-expanded.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaHasPopup) {
+ RunTest(FILE_PATH_LITERAL("aria-haspopup.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaHeading) {
+ RunTest(FILE_PATH_LITERAL("aria-heading.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaHidden) {
+ RunTest(FILE_PATH_LITERAL("aria-hidden.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
MAYBE(AccessibilityAriaFlowto)) {
RunTest(FILE_PATH_LITERAL("aria-flowto.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaImg) {
+ RunTest(FILE_PATH_LITERAL("aria-img.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaInvalid) {
RunTest(FILE_PATH_LITERAL("aria-invalid.html"));
}
@@ -301,17 +441,78 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaList) {
RunTest(FILE_PATH_LITERAL("aria-list.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaListBox) {
+ RunTest(FILE_PATH_LITERAL("aria-listbox.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaListBoxActiveDescendant) {
+ RunTest(FILE_PATH_LITERAL("aria-listbox-activedescendant.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaListBoxAriaSelected) {
+ RunTest(FILE_PATH_LITERAL("aria-listbox-aria-selected.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaListBoxChildFocus) {
+ RunTest(FILE_PATH_LITERAL("aria-listbox-childfocus.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaLive) {
+ RunTest(FILE_PATH_LITERAL("aria-live.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaLog) {
+ RunTest(FILE_PATH_LITERAL("aria-log.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaMarquee) {
+ RunTest(FILE_PATH_LITERAL("aria-marquee.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaMenu) {
RunTest(FILE_PATH_LITERAL("aria-menu.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaMenuBar) {
+ RunTest(FILE_PATH_LITERAL("aria-menubar.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaMenuitemradio) {
+ AccessibilityAriaMenuItemCheckBox) {
+ RunTest(FILE_PATH_LITERAL("aria-menuitemcheckbox.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaMenuItemRadio) {
RunTest(FILE_PATH_LITERAL("aria-menuitemradio.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaNavigation) {
+ RunTest(FILE_PATH_LITERAL("aria-navigation.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaOrientation) {
+ RunTest(FILE_PATH_LITERAL("aria-orientation.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaMath) {
+ RunTest(FILE_PATH_LITERAL("aria-math.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaNone) {
+ RunTest(FILE_PATH_LITERAL("aria-none.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaPressed) {
+ AccessibilityAriaPresentation) {
+ RunTest(FILE_PATH_LITERAL("aria-presentation.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaPressed) {
RunTest(FILE_PATH_LITERAL("aria-pressed.html"));
}
@@ -321,24 +522,96 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaToolbar) {
- RunTest(FILE_PATH_LITERAL("toolbar.html"));
+ AccessibilityAriaRadiogroup) {
+ RunTest(FILE_PATH_LITERAL("aria-radiogroup.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRelevant) {
+ RunTest(FILE_PATH_LITERAL("aria-relevant.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRequired) {
+ RunTest(FILE_PATH_LITERAL("aria-required.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRow) {
+ RunTest(FILE_PATH_LITERAL("aria-row.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRowGroup) {
+ RunTest(FILE_PATH_LITERAL("aria-rowgroup.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaReadonly) {
+ RunTest(FILE_PATH_LITERAL("aria-readonly.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaRegion) {
+ RunTest(FILE_PATH_LITERAL("aria-region.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaSearch) {
+ RunTest(FILE_PATH_LITERAL("aria-search.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaSeparator) {
+ RunTest(FILE_PATH_LITERAL("aria-separator.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaSort) {
+ RunTest(FILE_PATH_LITERAL("aria-sort.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaValueMin) {
- RunTest(FILE_PATH_LITERAL("aria-valuemin.html"));
+ AccessibilityAriaSpinButton) {
+ RunTest(FILE_PATH_LITERAL("aria-spinbutton.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaTextbox) {
+ RunTest(FILE_PATH_LITERAL("aria-textbox.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaTimer) {
+ RunTest(FILE_PATH_LITERAL("aria-timer.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaValueMax) {
+ AccessibilityAriaToggleButton) {
+ RunTest(FILE_PATH_LITERAL("aria-togglebutton.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaToolbar) {
+ RunTest(FILE_PATH_LITERAL("aria-toolbar.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaTree) {
+ RunTest(FILE_PATH_LITERAL("aria-tree.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaValueMin) {
+ RunTest(FILE_PATH_LITERAL("aria-valuemin.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaValueMax) {
RunTest(FILE_PATH_LITERAL("aria-valuemax.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaValueNow) {
+ RunTest(FILE_PATH_LITERAL("aria-valuenow.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityArticle) {
RunTest(FILE_PATH_LITERAL("article.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAside) {
+ RunTest(FILE_PATH_LITERAL("aside.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAudio) {
+ RunTest(FILE_PATH_LITERAL("audio.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAWithImg) {
RunTest(FILE_PATH_LITERAL("a-with-img.html"));
}
@@ -347,10 +620,22 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBdo) {
RunTest(FILE_PATH_LITERAL("bdo.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBlockquote) {
+ RunTest(FILE_PATH_LITERAL("blockquote.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBody) {
+ RunTest(FILE_PATH_LITERAL("body.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityBR) {
RunTest(FILE_PATH_LITERAL("br.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityButton) {
+ RunTest(FILE_PATH_LITERAL("button.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityButtonNameCalc) {
RunTest(FILE_PATH_LITERAL("button-name-calc.html"));
}
@@ -359,11 +644,39 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCanvas) {
RunTest(FILE_PATH_LITERAL("canvas.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCaption) {
+ RunTest(FILE_PATH_LITERAL("caption.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityCheckboxNameCalc) {
RunTest(FILE_PATH_LITERAL("checkbox-name-calc.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCite) {
+ RunTest(FILE_PATH_LITERAL("cite.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCol) {
+ RunTest(FILE_PATH_LITERAL("col.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityColgroup) {
+ RunTest(FILE_PATH_LITERAL("colgroup.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDel) {
+ RunTest(FILE_PATH_LITERAL("del.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDetails) {
+ RunTest(FILE_PATH_LITERAL("details.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDfn) {
+ RunTest(FILE_PATH_LITERAL("dfn.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDialog) {
RunTest(FILE_PATH_LITERAL("dialog.html"));
}
@@ -376,8 +689,14 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDl) {
RunTest(FILE_PATH_LITERAL("dl.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityDt) {
+ RunTest(FILE_PATH_LITERAL("dt.html"));
+}
+
+//Disabled because of https://codereview.chromium.org/696953002 temporarily.
+//After blink code is merged, it will be enabled.
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityContenteditableDescendants) {
+ DISABLED_AccessibilityContenteditableDescendants) {
RunTest(FILE_PATH_LITERAL("contenteditable-descendants.html"));
}
@@ -385,6 +704,18 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityEm) {
RunTest(FILE_PATH_LITERAL("em.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFieldset) {
+ RunTest(FILE_PATH_LITERAL("fieldset.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFigcaption) {
+ RunTest(FILE_PATH_LITERAL("figcaption.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFigure) {
+ RunTest(FILE_PATH_LITERAL("figure.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFooter) {
RunTest(FILE_PATH_LITERAL("footer.html"));
}
@@ -393,6 +724,18 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityForm) {
RunTest(FILE_PATH_LITERAL("form.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityFrameset) {
+ RunTest(FILE_PATH_LITERAL("frameset.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHead) {
+ RunTest(FILE_PATH_LITERAL("head.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHeader) {
+ RunTest(FILE_PATH_LITERAL("header.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHeading) {
RunTest(FILE_PATH_LITERAL("heading.html"));
}
@@ -401,11 +744,23 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityHR) {
RunTest(FILE_PATH_LITERAL("hr.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityI) {
+ RunTest(FILE_PATH_LITERAL("i.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityIframe) {
+ RunTest(FILE_PATH_LITERAL("iframe.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityIframeCoordinates) {
RunTest(FILE_PATH_LITERAL("iframe-coordinates.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityImg) {
+ RunTest(FILE_PATH_LITERAL("img.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputButton) {
RunTest(FILE_PATH_LITERAL("input-button.html"));
}
@@ -415,31 +770,114 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunTest(FILE_PATH_LITERAL("input-button-in-menu.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputCheckBox) {
+ RunTest(FILE_PATH_LITERAL("input-checkbox.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityInputCheckBoxInMenu) {
+ RunTest(FILE_PATH_LITERAL("input-checkbox-in-menu.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputColor) {
RunTest(FILE_PATH_LITERAL("input-color.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputDate) {
+ RunTest(FILE_PATH_LITERAL("input-date.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputDateTime) {
+ RunTest(FILE_PATH_LITERAL("input-datetime.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityInputDateTimeLocal) {
+#if defined(OS_MACOSX)
+ // Fails on OS X 10.9 <https://crbug.com/430622>.
+ if (base::mac::IsOSMavericks())
+ return;
+#endif
+ RunTest(FILE_PATH_LITERAL("input-datetime-local.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityInputImageButtonInMenu) {
RunTest(FILE_PATH_LITERAL("input-image-button-in-menu.html"));
}
+// crbug.com/423675 - AX tree is different for Win7 and Win8.
+#if defined(OS_WIN)
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ DISABLED_AccessibilityInputMonth) {
+ RunTest(FILE_PATH_LITERAL("input-month.html"));
+}
+#else
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputMonth) {
+ RunTest(FILE_PATH_LITERAL("input-month.html"));
+}
+#endif
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputRadio) {
+ RunTest(FILE_PATH_LITERAL("input-radio.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputRange) {
RunTest(FILE_PATH_LITERAL("input-range.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputReset) {
+ RunTest(FILE_PATH_LITERAL("input-reset.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputSearch) {
+ RunTest(FILE_PATH_LITERAL("input-search.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputSubmit) {
+ RunTest(FILE_PATH_LITERAL("input-submit.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputTel) {
+ RunTest(FILE_PATH_LITERAL("input-tel.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputText) {
+ RunTest(FILE_PATH_LITERAL("input-text.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityInputTextNameCalc) {
RunTest(FILE_PATH_LITERAL("input-text-name-calc.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputTextValue) {
+ RunTest(FILE_PATH_LITERAL("input-text-value.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputTime) {
+ RunTest(FILE_PATH_LITERAL("input-time.html"));
+}
+
// crbug.com/98976 will cause new elements to be added to the Blink a11y tree
// Re-baseline after the Blink change goes in
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- DISABLED_AccessibilityInputTypes) {
+ AccessibilityInputTypes) {
RunTest(FILE_PATH_LITERAL("input-types.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputUrl) {
+ RunTest(FILE_PATH_LITERAL("input-url.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputWeek) {
+ RunTest(FILE_PATH_LITERAL("input-week.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityIns) {
+ RunTest(FILE_PATH_LITERAL("ins.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLabel) {
RunTest(FILE_PATH_LITERAL("label.html"));
}
@@ -448,10 +886,52 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLandmark) {
RunTest(FILE_PATH_LITERAL("landmark.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityListMarkers) {
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLegend) {
+ RunTest(FILE_PATH_LITERAL("legend.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityLink) {
+ RunTest(FILE_PATH_LITERAL("link.html"));
+}
+
+//Disabled because of https://codereview.chromium.org/696953002 temporarily.
+//After blink code is merged, it will be enabled.
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, DISABLED_AccessibilityList) {
+ RunTest(FILE_PATH_LITERAL("list.html"));
+}
+
+//Disabled because of https://codereview.chromium.org/696953002 temporarily.
+//After blink code is merged, it will be enabled.
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ DISABLED_AccessibilityListMarkers) {
RunTest(FILE_PATH_LITERAL("list-markers.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityMain) {
+ RunTest(FILE_PATH_LITERAL("main.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityMark) {
+ RunTest(FILE_PATH_LITERAL("mark.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityMath) {
+ RunTest(FILE_PATH_LITERAL("math.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityMenutypecontext) {
+ RunTest(FILE_PATH_LITERAL("menu-type-context.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityMeta) {
+ RunTest(FILE_PATH_LITERAL("meta.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityMeter) {
+ RunTest(FILE_PATH_LITERAL("meter.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityModalDialogClosed) {
RunTest(FILE_PATH_LITERAL("modal-dialog-closed.html"));
@@ -477,29 +957,86 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunTest(FILE_PATH_LITERAL("modal-dialog-stack.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityNavigation) {
+ RunTest(FILE_PATH_LITERAL("navigation.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityNoscript) {
+ RunTest(FILE_PATH_LITERAL("noscript.html"));
+}
+
+//Disabled because of https://codereview.chromium.org/696953002 temporarily.
+//After blink code is merged, it will be enabled.
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, DISABLED_AccessibilityOl) {
+ RunTest(FILE_PATH_LITERAL("ol.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityObject) {
+ RunTest(FILE_PATH_LITERAL("object.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityOptionindatalist) {
+ RunTest(FILE_PATH_LITERAL("option-in-datalist.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityOutput) {
+ RunTest(FILE_PATH_LITERAL("output.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityP) {
RunTest(FILE_PATH_LITERAL("p.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityRegion) {
- RunTest(FILE_PATH_LITERAL("region.html"));
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityParam) {
+ RunTest(FILE_PATH_LITERAL("param.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityPre) {
+ RunTest(FILE_PATH_LITERAL("pre.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityProgress) {
+ RunTest(FILE_PATH_LITERAL("progress.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityQ) {
+ RunTest(FILE_PATH_LITERAL("q.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityS) {
+ RunTest(FILE_PATH_LITERAL("s.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySamp) {
+ RunTest(FILE_PATH_LITERAL("samp.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySection) {
+ RunTest(FILE_PATH_LITERAL("section.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySelect) {
RunTest(FILE_PATH_LITERAL("select.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySource) {
+ RunTest(FILE_PATH_LITERAL("source.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySpan) {
RunTest(FILE_PATH_LITERAL("span.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySpinButton) {
- RunTest(FILE_PATH_LITERAL("spinbutton.html"));
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySub) {
+ RunTest(FILE_PATH_LITERAL("sub.html"));
}
-// TODO(dmazzoni): Rebaseline this test after Blink rolls past r155083.
-// See http://crbug.com/265619
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, DISABLED_AccessibilitySvg) {
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySummary) {
+ RunTest(FILE_PATH_LITERAL("summary.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilitySvg) {
RunTest(FILE_PATH_LITERAL("svg.html"));
}
@@ -511,26 +1048,48 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSimple) {
RunTest(FILE_PATH_LITERAL("table-simple.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityTableThRowHeader) {
+ RunTest(FILE_PATH_LITERAL("table-th-rowheader.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityTableTbodyTfoot) {
+ RunTest(FILE_PATH_LITERAL("table-thead-tbody-tfoot.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSpans) {
RunTest(FILE_PATH_LITERAL("table-spans.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityToggleButton) {
- RunTest(FILE_PATH_LITERAL("togglebutton.html"));
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTextArea) {
+ RunTest(FILE_PATH_LITERAL("textarea.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityUl) {
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTime) {
+ RunTest(FILE_PATH_LITERAL("time.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTitle) {
+ RunTest(FILE_PATH_LITERAL("title.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTransition) {
+ RunTest(FILE_PATH_LITERAL("transition.html"));
+}
+
+//Disabled because of https://codereview.chromium.org/696953002 temporarily.
+//After blink code is merged, it will be enabled.
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, DISABLED_AccessibilityUl) {
RunTest(FILE_PATH_LITERAL("ul.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityWbr) {
- RunTest(FILE_PATH_LITERAL("wbr.html"));
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityVar) {
+ RunTest(FILE_PATH_LITERAL("var.html"));
}
-IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaActivedescendant) {
- RunTest(FILE_PATH_LITERAL("aria-activedescendant.html"));
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityWbr) {
+ RunTest(FILE_PATH_LITERAL("wbr.html"));
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
new file mode 100644
index 00000000000..12cdc89376c
--- /dev/null
+++ b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -0,0 +1,146 @@
+// Copyright (c) 2014 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/command_line.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/frame_host/cross_process_frame_connector.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/render_frame_proxy_host.h"
+#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/site_per_process_browsertest.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class SitePerProcessAccessibilityBrowserTest
+ : public SitePerProcessBrowserTest {
+ public:
+ SitePerProcessAccessibilityBrowserTest() {}
+};
+
+// TODO(nasko): try enabling this test on more platforms once
+// SitePerProcessBrowserTest.CrossSiteIframe is enabled everywhere.
+// http://crbug.com/399775
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#define MAYBE_CrossSiteIframeAccessibility CrossSiteIframeAccessibility
+#else
+#define MAYBE_CrossSiteIframeAccessibility DISABLED_CrossSiteIframeAccessibility
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessAccessibilityBrowserTest,
+ MAYBE_CrossSiteIframeAccessibility) {
+ // Enable full accessibility for all current and future WebContents.
+ BrowserAccessibilityState::GetInstance()->EnableAccessibility();
+
+ AccessibilityNotificationWaiter main_frame_accessibility_waiter(
+ shell(), AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+ GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+
+ // Load same-site page into iframe.
+ FrameTreeNode* child = root->child_at(0);
+ GURL http_url(test_server()->GetURL("files/title1.html"));
+ NavigateFrameToURL(child, http_url);
+
+ // These must stay in scope with replace_host.
+ GURL::Replacements replace_host;
+ std::string foo_com("foo.com");
+
+ // Load cross-site page into iframe.
+ GURL cross_site_url(test_server()->GetURL("files/title2.html"));
+ replace_host.SetHostStr(foo_com);
+ cross_site_url = cross_site_url.ReplaceComponents(replace_host);
+ NavigateFrameToURL(root->child_at(0), cross_site_url);
+
+ // Ensure that we have created a new process for the subframe.
+ ASSERT_EQ(2U, root->child_count());
+ SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
+
+ // Wait until the accessibility tree from both the main frame and
+ // cross-process iframe load.
+ RenderFrameHostImpl* child_frame = static_cast<RenderFrameHostImpl*>(
+ child->current_frame_host());
+ AccessibilityNotificationWaiter child_frame_accessibility_waiter(
+ child_frame, ui::AX_EVENT_NONE);
+ main_frame_accessibility_waiter.WaitForNotification();
+ child_frame_accessibility_waiter.WaitForNotification();
+
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
+ BrowserAccessibilityManager* main_frame_manager =
+ main_frame->browser_accessibility_manager();
+ VLOG(1) << "Main frame accessibility tree:\n"
+ << main_frame_manager->SnapshotAXTreeForTesting().ToString();
+
+ BrowserAccessibilityManager* child_frame_manager =
+ child_frame->browser_accessibility_manager();
+ VLOG(1) << "Child frame accessibility tree:\n"
+ << child_frame_manager->SnapshotAXTreeForTesting().ToString();
+
+ // Assert that we can walk from the main frame down into the child frame
+ // directly, getting correct roles and data along the way.
+ BrowserAccessibility* ax_root = main_frame_manager->GetRoot();
+ ASSERT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, ax_root->GetRole());
+ ASSERT_EQ(1U, ax_root->PlatformChildCount());
+
+ BrowserAccessibility* ax_group = ax_root->PlatformGetChild(0);
+ ASSERT_EQ(ui::AX_ROLE_GROUP, ax_group->GetRole());
+ ASSERT_EQ(2U, ax_group->PlatformChildCount());
+
+ BrowserAccessibility* ax_iframe = ax_group->PlatformGetChild(0);
+ ASSERT_EQ(ui::AX_ROLE_IFRAME, ax_iframe->GetRole());
+ ASSERT_EQ(1U, ax_iframe->PlatformChildCount());
+
+ BrowserAccessibility* ax_scroll_area = ax_iframe->PlatformGetChild(0);
+ ASSERT_EQ(ui::AX_ROLE_SCROLL_AREA, ax_scroll_area->GetRole());
+ ASSERT_EQ(1U, ax_scroll_area->PlatformChildCount());
+
+ BrowserAccessibility* ax_child_frame_root =
+ ax_scroll_area->PlatformGetChild(0);
+ ASSERT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, ax_child_frame_root->GetRole());
+ ASSERT_EQ(1U, ax_child_frame_root->PlatformChildCount());
+ ASSERT_EQ("Title Of Awesomeness", ax_child_frame_root->name());
+
+ BrowserAccessibility* ax_child_frame_group =
+ ax_child_frame_root->PlatformGetChild(0);
+ ASSERT_EQ(ui::AX_ROLE_GROUP, ax_child_frame_group->GetRole());
+ ASSERT_EQ(1U, ax_child_frame_group->PlatformChildCount());
+
+ BrowserAccessibility* ax_child_frame_static_text =
+ ax_child_frame_group->PlatformGetChild(0);
+ ASSERT_EQ(ui::AX_ROLE_STATIC_TEXT, ax_child_frame_static_text->GetRole());
+ ASSERT_EQ(0U, ax_child_frame_static_text->PlatformChildCount());
+
+ // Last, check that the parent of the child frame root is correct.
+ ASSERT_EQ(ax_child_frame_root->GetParent(), ax_scroll_area);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/DEPS b/chromium/content/browser/android/DEPS
deleted file mode 100644
index 0410b36ac82..00000000000
--- a/chromium/content/browser/android/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+third_party/WebKit/public/web/WebBindings.h", # For java bridge bindings
-]
diff --git a/chromium/content/browser/android/OWNERS b/chromium/content/browser/android/OWNERS
index 4fd5d774a7c..6ba7da7c389 100644
--- a/chromium/content/browser/android/OWNERS
+++ b/chromium/content/browser/android/OWNERS
@@ -1,5 +1,3 @@
-bulach@chromium.org
-sievers@chromium.org
skyostil@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/browser/android/browser_startup_controller.cc b/chromium/content/browser/android/browser_startup_controller.cc
index 502f198edba..74e38e62839 100644
--- a/chromium/content/browser/android/browser_startup_controller.cc
+++ b/chromium/content/browser/android/browser_startup_controller.cc
@@ -28,13 +28,13 @@ bool RegisterBrowserStartupController(JNIEnv* env) {
static void SetCommandLineFlags(JNIEnv* env,
jclass clazz,
- jint max_render_process_count,
+ jboolean single_process,
jstring plugin_descriptor) {
std::string plugin_str =
(plugin_descriptor == NULL
? std::string()
: base::android::ConvertJavaStringToUTF8(env, plugin_descriptor));
- SetContentCommandLineFlags(max_render_process_count, plugin_str);
+ SetContentCommandLineFlags(static_cast<bool>(single_process), plugin_str);
}
static jboolean IsOfficialBuild(JNIEnv* env, jclass clazz) {
diff --git a/chromium/content/browser/android/browser_surface_texture_manager.cc b/chromium/content/browser/android/browser_surface_texture_manager.cc
new file mode 100644
index 00000000000..44669839f2b
--- /dev/null
+++ b/chromium/content/browser/android/browser_surface_texture_manager.cc
@@ -0,0 +1,136 @@
+// Copyright 2014 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 "content/browser/android/browser_surface_texture_manager.h"
+
+#include <android/native_window_jni.h>
+
+#include "base/android/jni_android.h"
+#include "content/browser/android/child_process_launcher_android.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/media/android/browser_media_player_manager.h"
+#include "content/browser/media/media_web_contents_observer.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "media/base/android/media_player_android.h"
+#include "ui/gl/android/scoped_java_surface.h"
+#include "ui/gl/android/surface_texture.h"
+
+namespace content {
+namespace {
+
+// Pass a java surface object to the MediaPlayerAndroid object
+// identified by render process handle, render frame ID and player ID.
+static void SetSurfacePeer(scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ base::ProcessHandle render_process_handle,
+ int render_frame_id,
+ int player_id) {
+ int render_process_id = 0;
+ RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
+ while (!it.IsAtEnd()) {
+ if (it.GetCurrentValue()->GetHandle() == render_process_handle) {
+ render_process_id = it.GetCurrentValue()->GetID();
+ break;
+ }
+ it.Advance();
+ }
+ if (!render_process_id) {
+ DVLOG(1) << "Cannot find render process for render_process_handle "
+ << render_process_handle;
+ return;
+ }
+
+ RenderFrameHostImpl* frame =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ if (!frame) {
+ DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id;
+ return;
+ }
+
+ RenderViewHostImpl* view =
+ static_cast<RenderViewHostImpl*>(frame->GetRenderViewHost());
+ BrowserMediaPlayerManager* player_manager =
+ view->media_web_contents_observer()->GetMediaPlayerManager(frame);
+ if (!player_manager) {
+ DVLOG(1) << "Cannot find the media player manager for frame " << frame;
+ return;
+ }
+
+ media::MediaPlayerAndroid* player = player_manager->GetPlayer(player_id);
+ if (!player) {
+ DVLOG(1) << "Cannot find media player for player_id " << player_id;
+ return;
+ }
+
+ if (player != player_manager->GetFullscreenPlayer()) {
+ gfx::ScopedJavaSurface scoped_surface(surface_texture.get());
+ player->SetVideoSurface(scoped_surface.Pass());
+ }
+}
+
+} // namespace
+
+BrowserSurfaceTextureManager::BrowserSurfaceTextureManager() {
+ SurfaceTexturePeer::InitInstance(this);
+}
+
+BrowserSurfaceTextureManager::~BrowserSurfaceTextureManager() {
+ SurfaceTexturePeer::InitInstance(NULL);
+}
+
+void BrowserSurfaceTextureManager::RegisterSurfaceTexture(
+ int surface_texture_id,
+ int client_id,
+ gfx::SurfaceTexture* surface_texture) {
+ content::CreateSurfaceTextureSurface(
+ surface_texture_id, client_id, surface_texture);
+}
+
+void BrowserSurfaceTextureManager::UnregisterSurfaceTexture(
+ int surface_texture_id,
+ int client_id) {
+ content::DestroySurfaceTextureSurface(surface_texture_id, client_id);
+}
+
+gfx::AcceleratedWidget
+BrowserSurfaceTextureManager::AcquireNativeWidgetForSurfaceTexture(
+ int surface_texture_id) {
+ gfx::ScopedJavaSurface surface(
+ content::GetSurfaceTextureSurface(
+ surface_texture_id,
+ BrowserGpuChannelHostFactory::instance()->GetGpuChannelId()));
+ if (surface.j_surface().is_null())
+ return NULL;
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ // Note: This ensures that any local references used by
+ // ANativeWindow_fromSurface are released immediately. This is needed as a
+ // workaround for https://code.google.com/p/android/issues/detail?id=68174
+ base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env);
+ ANativeWindow* native_window =
+ ANativeWindow_fromSurface(env, surface.j_surface().obj());
+
+ return native_window;
+}
+
+void BrowserSurfaceTextureManager::EstablishSurfaceTexturePeer(
+ base::ProcessHandle render_process_handle,
+ scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ int render_frame_id,
+ int player_id) {
+ if (!surface_texture.get())
+ return;
+
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&SetSurfacePeer,
+ surface_texture,
+ render_process_handle,
+ render_frame_id,
+ player_id));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/browser_surface_texture_manager.h b/chromium/content/browser/android/browser_surface_texture_manager.h
new file mode 100644
index 00000000000..7776d30ee7f
--- /dev/null
+++ b/chromium/content/browser/android/browser_surface_texture_manager.h
@@ -0,0 +1,43 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_BROWSER_SURFACE_TEXTURE_MANAGER_H_
+#define CONTENT_BROWSER_ANDROID_BROWSER_SURFACE_TEXTURE_MANAGER_H_
+
+#include "content/common/android/surface_texture_manager.h"
+
+#include "content/common/android/surface_texture_peer.h"
+
+namespace content {
+
+class BrowserSurfaceTextureManager : public SurfaceTextureManager,
+ public SurfaceTexturePeer {
+ public:
+ BrowserSurfaceTextureManager();
+ virtual ~BrowserSurfaceTextureManager();
+
+ // Overridden from SurfaceTextureManager:
+ virtual void RegisterSurfaceTexture(
+ int surface_texture_id,
+ int client_id,
+ gfx::SurfaceTexture* surface_texture) override;
+ virtual void UnregisterSurfaceTexture(int surface_texture_id,
+ int client_id) override;
+ virtual gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture(
+ int surface_texture_id) override;
+
+ // Overridden from SurfaceTexturePeer:
+ virtual void EstablishSurfaceTexturePeer(
+ base::ProcessHandle render_process_handle,
+ scoped_refptr<gfx::SurfaceTexture> surface_texture,
+ int render_frame_id,
+ int player_id) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BrowserSurfaceTextureManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_BROWSER_SURFACE_TEXTURE_MANAGER_H_
diff --git a/chromium/content/browser/android/child_process_launcher_android.cc b/chromium/content/browser/android/child_process_launcher_android.cc
index baac2b0a715..c937fce174a 100644
--- a/chromium/content/browser/android/child_process_launcher_android.cc
+++ b/chromium/content/browser/android/child_process_launcher_android.cc
@@ -18,7 +18,7 @@
#include "content/public/common/content_switches.h"
#include "jni/ChildProcessLauncher_jni.h"
#include "media/base/android/media_player_android.h"
-#include "ui/gl/android/scoped_java_surface.h"
+#include "ui/gl/android/surface_texture.h"
using base::android::AttachCurrentThread;
using base::android::ToJavaArrayOfStrings;
@@ -100,9 +100,9 @@ static void OnChildProcessStarted(JNIEnv*,
}
void StartChildProcess(
- const CommandLine::StringVector& argv,
+ const base::CommandLine::StringVector& argv,
int child_process_id,
- const std::vector<content::FileDescriptorInfo>& files_to_register,
+ scoped_ptr<content::FileDescriptorInfo> files_to_register,
const StartChildProcessCallback& callback) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
@@ -110,7 +110,7 @@ void StartChildProcess(
// Create the Command line String[]
ScopedJavaLocalRef<jobjectArray> j_argv = ToJavaArrayOfStrings(env, argv);
- size_t file_count = files_to_register.size();
+ size_t file_count = files_to_register->GetMappingSize();
DCHECK(file_count > 0);
ScopedJavaLocalRef<jintArray> j_file_ids(env, env->NewIntArray(file_count));
@@ -128,10 +128,14 @@ void StartChildProcess(
env->GetBooleanArrayElements(j_file_auto_close.obj(), NULL);
base::android::CheckException(env);
for (size_t i = 0; i < file_count; ++i) {
- const content::FileDescriptorInfo& fd_info = files_to_register[i];
- file_ids[i] = fd_info.id;
- file_fds[i] = fd_info.fd.fd;
- file_auto_close[i] = fd_info.fd.auto_close;
+ // Owners of passed descriptors can outlive this function and we don't know
+ // when it is safe to close() them. So we pass dup()-ed FD and
+ // let ChildProcessLauncher in java take care of their lifetimes.
+ // TODO(morrita): Drop FileDescriptorInfo.mAutoClose on Java side.
+ file_auto_close[i] = true; // This indicates ownership transfer.
+ file_ids[i] = files_to_register->GetIDAt(i);
+ file_fds[i] = dup(files_to_register->GetFDAt(i));
+ PCHECK(0 <= file_fds[i]);
}
env->ReleaseIntArrayElements(j_file_ids.obj(), file_ids, 0);
env->ReleaseIntArrayElements(j_file_fds.obj(), file_fds, 0);
@@ -193,25 +197,37 @@ void UnregisterViewSurface(int surface_id) {
Java_ChildProcessLauncher_unregisterViewSurface(env, surface_id);
}
-void RegisterChildProcessSurfaceTexture(int surface_texture_id,
- int child_process_id,
- jobject j_surface_texture) {
+void CreateSurfaceTextureSurface(int surface_texture_id,
+ int client_id,
+ gfx::SurfaceTexture* surface_texture) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- Java_ChildProcessLauncher_registerSurfaceTexture(
- env, surface_texture_id, child_process_id, j_surface_texture);
+ Java_ChildProcessLauncher_createSurfaceTextureSurface(
+ env,
+ surface_texture_id,
+ client_id,
+ surface_texture->j_surface_texture().obj());
}
-void UnregisterChildProcessSurfaceTexture(int surface_texture_id,
- int child_process_id) {
+void DestroySurfaceTextureSurface(int surface_texture_id, int client_id) {
JNIEnv* env = AttachCurrentThread();
DCHECK(env);
- Java_ChildProcessLauncher_unregisterSurfaceTexture(
- env, surface_texture_id, child_process_id);
+ Java_ChildProcessLauncher_destroySurfaceTextureSurface(
+ env, surface_texture_id, client_id);
+}
+
+gfx::ScopedJavaSurface GetSurfaceTextureSurface(int surface_texture_id,
+ int client_id) {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+ return gfx::ScopedJavaSurface::AcquireExternalSurface(
+ Java_ChildProcessLauncher_getSurfaceTextureSurface(
+ env, surface_texture_id, client_id).obj());
}
jboolean IsSingleProcess(JNIEnv* env, jclass clazz) {
- return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess);
}
bool RegisterChildProcessLauncher(JNIEnv* env) {
diff --git a/chromium/content/browser/android/child_process_launcher_android.h b/chromium/content/browser/android/child_process_launcher_android.h
index 747649fc7ac..d1de985a8f9 100644
--- a/chromium/content/browser/android/child_process_launcher_android.h
+++ b/chromium/content/browser/android/child_process_launcher_android.h
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/process/process.h"
#include "content/public/browser/file_descriptor_info.h"
+#include "ui/gl/android/scoped_java_surface.h"
namespace content {
@@ -19,11 +20,10 @@ typedef base::Callback<void(base::ProcessHandle)> StartChildProcessCallback;
// ActivityManager.
// The created process handle is returned to the |callback| on success, 0 is
// retuned if the process could not be created.
-void StartChildProcess(
- const base::CommandLine::StringVector& argv,
- int child_process_id,
- const std::vector<FileDescriptorInfo>& files_to_register,
- const StartChildProcessCallback& callback);
+void StartChildProcess(const base::CommandLine::StringVector& argv,
+ int child_process_id,
+ const scoped_ptr<FileDescriptorInfo> files_to_register,
+ const StartChildProcessCallback& callback);
// Stops a child process based on the handle returned form
// StartChildProcess.
@@ -38,12 +38,14 @@ void RegisterViewSurface(int surface_id, jobject j_surface);
void UnregisterViewSurface(int surface_id);
-void RegisterChildProcessSurfaceTexture(int surface_texture_id,
- int child_process_id,
- jobject j_surface_texture);
+void CreateSurfaceTextureSurface(int surface_texture_id,
+ int client_id,
+ gfx::SurfaceTexture* surface_texture);
-void UnregisterChildProcessSurfaceTexture(int surface_texture_id,
- int child_process_id);
+void DestroySurfaceTextureSurface(int surface_texture_id, int client_id);
+
+gfx::ScopedJavaSurface GetSurfaceTextureSurface(int surface_texture_id,
+ int client_id);
bool RegisterChildProcessLauncher(JNIEnv* env);
diff --git a/chromium/content/browser/android/composited_touch_handle_drawable.cc b/chromium/content/browser/android/composited_touch_handle_drawable.cc
new file mode 100644
index 00000000000..aa7c71920c1
--- /dev/null
+++ b/chromium/content/browser/android/composited_touch_handle_drawable.cc
@@ -0,0 +1,165 @@
+// Copyright 2014 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 "content/browser/android/composited_touch_handle_drawable.h"
+
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "cc/layers/ui_resource_layer.h"
+#include "jni/HandleViewResources_jni.h"
+#include "ui/gfx/android/java_bitmap.h"
+
+namespace content {
+
+namespace {
+
+static SkBitmap CreateSkBitmapFromJavaBitmap(
+ base::android::ScopedJavaLocalRef<jobject> jbitmap) {
+ return jbitmap.is_null()
+ ? SkBitmap()
+ : CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jbitmap.obj()));
+}
+
+class HandleResources {
+ public:
+ HandleResources() : loaded_(false) {
+ }
+
+ void LoadIfNecessary(jobject context) {
+ if (loaded_)
+ return;
+
+ loaded_ = true;
+
+ TRACE_EVENT0("browser", "HandleResources::Create");
+ JNIEnv* env = base::android::AttachCurrentThread();
+ if (!context)
+ context = base::android::GetApplicationContext();
+
+ left_bitmap_ = CreateSkBitmapFromJavaBitmap(
+ Java_HandleViewResources_getLeftHandleBitmap(env, context));
+ right_bitmap_ = CreateSkBitmapFromJavaBitmap(
+ Java_HandleViewResources_getRightHandleBitmap(env, context));
+ center_bitmap_ = CreateSkBitmapFromJavaBitmap(
+ Java_HandleViewResources_getCenterHandleBitmap(env, context));
+
+ left_bitmap_.setImmutable();
+ right_bitmap_.setImmutable();
+ center_bitmap_.setImmutable();
+ }
+
+ const SkBitmap& GetBitmap(TouchHandleOrientation orientation) {
+ DCHECK(loaded_);
+ switch (orientation) {
+ case TOUCH_HANDLE_LEFT:
+ return left_bitmap_;
+ case TOUCH_HANDLE_RIGHT:
+ return right_bitmap_;
+ case TOUCH_HANDLE_CENTER:
+ return center_bitmap_;
+ case TOUCH_HANDLE_ORIENTATION_UNDEFINED:
+ NOTREACHED() << "Invalid touch handle orientation.";
+ };
+ return center_bitmap_;
+ }
+
+ private:
+ SkBitmap left_bitmap_;
+ SkBitmap right_bitmap_;
+ SkBitmap center_bitmap_;
+ bool loaded_;
+
+ DISALLOW_COPY_AND_ASSIGN(HandleResources);
+};
+
+base::LazyInstance<HandleResources>::Leaky g_selection_resources;
+
+} // namespace
+
+CompositedTouchHandleDrawable::CompositedTouchHandleDrawable(
+ cc::Layer* root_layer,
+ float dpi_scale,
+ jobject context)
+ : dpi_scale_(dpi_scale),
+ orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
+ layer_(cc::UIResourceLayer::Create()) {
+ g_selection_resources.Get().LoadIfNecessary(context);
+ DCHECK(root_layer);
+ root_layer->AddChild(layer_.get());
+}
+
+CompositedTouchHandleDrawable::~CompositedTouchHandleDrawable() {
+ Detach();
+}
+
+void CompositedTouchHandleDrawable::SetEnabled(bool enabled) {
+ layer_->SetIsDrawable(enabled);
+}
+
+void CompositedTouchHandleDrawable::SetOrientation(
+ TouchHandleOrientation orientation) {
+ DCHECK(layer_->parent());
+ orientation_ = orientation;
+
+ const SkBitmap& bitmap = g_selection_resources.Get().GetBitmap(orientation);
+ layer_->SetBitmap(bitmap);
+ layer_->SetBounds(gfx::Size(bitmap.width(), bitmap.height()));
+
+ switch (orientation_) {
+ case TOUCH_HANDLE_LEFT:
+ focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.75f, 0);
+ break;
+ case TOUCH_HANDLE_RIGHT:
+ focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.25f, 0);
+ break;
+ case TOUCH_HANDLE_CENTER:
+ focal_offset_from_origin_ = gfx::Vector2dF(bitmap.width() * 0.5f, 0);
+ break;
+ case TOUCH_HANDLE_ORIENTATION_UNDEFINED:
+ NOTREACHED() << "Invalid touch handle orientation.";
+ break;
+ };
+
+ layer_->SetPosition(focal_position_ - focal_offset_from_origin_);
+}
+
+void CompositedTouchHandleDrawable::SetAlpha(float alpha) {
+ DCHECK(layer_->parent());
+ layer_->SetOpacity(std::max(0.f, std::min(1.f, alpha)));
+}
+
+void CompositedTouchHandleDrawable::SetFocus(const gfx::PointF& position) {
+ DCHECK(layer_->parent());
+ focal_position_ = gfx::ScalePoint(position, dpi_scale_);
+ layer_->SetPosition(focal_position_ - focal_offset_from_origin_);
+}
+
+void CompositedTouchHandleDrawable::SetVisible(bool visible) {
+ DCHECK(layer_->parent());
+ layer_->SetHideLayerAndSubtree(!visible);
+}
+
+bool CompositedTouchHandleDrawable::IntersectsWith(
+ const gfx::RectF& rect) const {
+ return BoundingRect().Intersects(gfx::ScaleRect(rect, dpi_scale_));
+}
+
+void CompositedTouchHandleDrawable::Detach() {
+ layer_->RemoveFromParent();
+}
+
+gfx::RectF CompositedTouchHandleDrawable::BoundingRect() const {
+ return gfx::RectF(layer_->position().x(),
+ layer_->position().y(),
+ layer_->bounds().width(),
+ layer_->bounds().height());
+}
+
+// static
+bool CompositedTouchHandleDrawable::RegisterHandleViewResources(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/composited_touch_handle_drawable.h b/chromium/content/browser/android/composited_touch_handle_drawable.h
new file mode 100644
index 00000000000..c4f5f45b2a1
--- /dev/null
+++ b/chromium/content/browser/android/composited_touch_handle_drawable.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_COMPOSITED_TOUCH_HANDLE_DRAWABLE_H_
+#define CONTENT_BROWSER_ANDROID_COMPOSITED_TOUCH_HANDLE_DRAWABLE_H_
+
+#include "content/browser/renderer_host/input/touch_handle.h"
+
+#include "base/android/jni_android.h"
+#include "cc/layers/ui_resource_layer.h"
+
+namespace content {
+
+// Touch handle drawable implementation backed by a cc layer.
+class CompositedTouchHandleDrawable : public TouchHandleDrawable {
+ public:
+ CompositedTouchHandleDrawable(cc::Layer* root_layer,
+ float dpi_scale,
+ jobject context);
+ virtual ~CompositedTouchHandleDrawable();
+
+ // TouchHandleDrawable implementation.
+ virtual void SetEnabled(bool enabled) override;
+ virtual void SetOrientation(TouchHandleOrientation orientation) override;
+ virtual void SetAlpha(float alpha) override;
+ virtual void SetFocus(const gfx::PointF& position) override;
+ virtual void SetVisible(bool visible) override;
+ virtual bool IntersectsWith(const gfx::RectF& rect) const override;
+
+ static bool RegisterHandleViewResources(JNIEnv* env);
+
+ private:
+ void Detach();
+ gfx::RectF BoundingRect() const;
+
+ const float dpi_scale_;
+ TouchHandleOrientation orientation_;
+ gfx::PointF focal_position_;
+ gfx::Vector2dF focal_offset_from_origin_;
+ scoped_refptr<cc::UIResourceLayer> layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositedTouchHandleDrawable);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_COMPOSITED_TOUCH_HANDLE_DRAWABLE_H_
diff --git a/chromium/content/browser/android/content_readback_handler.cc b/chromium/content/browser/android/content_readback_handler.cc
index 841ef5f051a..414bf0abe67 100644
--- a/chromium/content/browser/android/content_readback_handler.cc
+++ b/chromium/content/browser/android/content_readback_handler.cc
@@ -31,7 +31,7 @@ void OnFinishCopyOutputRequest(
}
scoped_ptr<SkBitmap> bitmap = copy_output_result->TakeBitmap();
- result_callback.Run(true, *bitmap.Pass());
+ result_callback.Run(true, *bitmap);
}
} // anonymous namespace
@@ -54,7 +54,7 @@ void ContentReadbackHandler::GetContentBitmap(JNIEnv* env,
jobject obj,
jint readback_id,
jfloat scale,
- jobject config,
+ jobject color_type,
jfloat x,
jfloat y,
jfloat width,
@@ -69,8 +69,9 @@ void ContentReadbackHandler::GetContentBitmap(JNIEnv* env,
weak_factory_.GetWeakPtr(),
readback_id);
+ SkColorType sk_color_type = gfx::ConvertToSkiaColorType(color_type);
view->GetScaledContentBitmap(
- scale, config, gfx::Rect(x, y, width, height), result_callback);
+ scale, sk_color_type, gfx::Rect(x, y, width, height), result_callback);
}
void ContentReadbackHandler::GetCompositorBitmap(JNIEnv* env,
@@ -112,7 +113,7 @@ void ContentReadbackHandler::OnFinishReadback(int readback_id,
java_bitmap = gfx::ConvertToJavaBitmap(&bitmap);
Java_ContentReadbackHandler_notifyGetBitmapFinished(
- env, java_obj_.obj(), readback_id, success, java_bitmap.obj());
+ env, java_obj_.obj(), readback_id, java_bitmap.obj());
}
// static
diff --git a/chromium/content/browser/android/content_settings.cc b/chromium/content/browser/android/content_settings.cc
index a83169c2ce9..2d32143807a 100644
--- a/chromium/content/browser/android/content_settings.cc
+++ b/chromium/content/browser/android/content_settings.cc
@@ -9,8 +9,8 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/web_preferences.h"
#include "jni/ContentSettings_jni.h"
-#include "webkit/common/webpreferences.h"
namespace content {
@@ -39,7 +39,7 @@ bool ContentSettings::GetJavaScriptEnabled(JNIEnv* env, jobject obj) {
RenderViewHost* render_view_host = web_contents()->GetRenderViewHost();
if (!render_view_host)
return false;
- return render_view_host->GetDelegate()->GetWebkitPrefs().javascript_enabled;
+ return render_view_host->GetWebkitPreferences().javascript_enabled;
}
void ContentSettings::WebContentsDestroyed() {
diff --git a/chromium/content/browser/android/content_settings.h b/chromium/content/browser/android/content_settings.h
index 0728a6afabb..79dd1da4d38 100644
--- a/chromium/content/browser/android/content_settings.h
+++ b/chromium/content/browser/android/content_settings.h
@@ -26,7 +26,7 @@ class ContentSettings : public WebContentsObserver {
virtual ~ContentSettings();
// WebContentsObserver overrides:
- virtual void WebContentsDestroyed() OVERRIDE;
+ virtual void WebContentsDestroyed() override;
// The Java counterpart to this class.
JavaObjectWeakGlobalRef content_settings_;
diff --git a/chromium/content/browser/android/content_startup_flags.cc b/chromium/content/browser/android/content_startup_flags.cc
index a771daa8170..d531dbb65a6 100644
--- a/chromium/content/browser/android/content_startup_flags.cc
+++ b/chromium/content/browser/android/content_startup_flags.cc
@@ -18,7 +18,7 @@
namespace content {
-void SetContentCommandLineFlags(int max_render_process_count,
+void SetContentCommandLineFlags(bool single_process,
const std::string& plugin_descriptor) {
// May be called multiple times, to cover all possible program entry points.
static bool already_initialized = false;
@@ -26,7 +26,8 @@ void SetContentCommandLineFlags(int max_render_process_count,
return;
already_initialized = true;
- CommandLine* parsed_command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* parsed_command_line =
+ base::CommandLine::ForCurrentProcess();
int command_line_renderer_limit = -1;
if (parsed_command_line->HasSwitch(switches::kRendererProcessLimit)) {
@@ -34,9 +35,7 @@ void SetContentCommandLineFlags(int max_render_process_count,
switches::kRendererProcessLimit);
int value;
if (base::StringToInt(limit, &value)) {
- command_line_renderer_limit = value;
- if (value <= 0)
- max_render_process_count = 0;
+ command_line_renderer_limit = std::max(0, value);
}
}
@@ -44,29 +43,22 @@ void SetContentCommandLineFlags(int max_render_process_count,
int limit = std::min(command_line_renderer_limit,
static_cast<int>(kMaxRendererProcessCount));
RenderProcessHost::SetMaxRendererProcessCount(limit);
- } else if (max_render_process_count <= 0) {
+ }
+
+ if (single_process || command_line_renderer_limit == 0) {
// Need to ensure the command line flag is consistent as a lot of chrome
// internal code checks this directly, but it wouldn't normally get set when
// we are implementing an embedded WebView.
parsed_command_line->AppendSwitch(switches::kSingleProcess);
- } else {
- int default_maximum = RenderProcessHost::GetMaxRendererProcessCount();
- DCHECK(default_maximum <= static_cast<int>(kMaxRendererProcessCount));
- if (max_render_process_count < default_maximum)
- RenderProcessHost::SetMaxRendererProcessCount(max_render_process_count);
}
- parsed_command_line->AppendSwitch(switches::kEnableThreadedCompositing);
- parsed_command_line->AppendSwitch(
- switches::kEnableCompositingForFixedPosition);
- parsed_command_line->AppendSwitch(switches::kEnableAcceleratedOverflowScroll);
parsed_command_line->AppendSwitch(switches::kEnableBeginFrameScheduling);
- parsed_command_line->AppendSwitch(switches::kEnableGestureTapHighlight);
parsed_command_line->AppendSwitch(switches::kEnablePinch);
parsed_command_line->AppendSwitch(switches::kEnableOverlayFullscreenVideo);
parsed_command_line->AppendSwitch(switches::kEnableOverlayScrollbar);
parsed_command_line->AppendSwitch(switches::kEnableOverscrollNotifications);
+ parsed_command_line->AppendSwitch(switches::kValidateInputEventStream);
// Run the GPU service as a thread in the browser instead of as a
// standalone process.
diff --git a/chromium/content/browser/android/content_startup_flags.h b/chromium/content/browser/android/content_startup_flags.h
index 836ea3c1206..8f55a0c2cf4 100644
--- a/chromium/content/browser/android/content_startup_flags.h
+++ b/chromium/content/browser/android/content_startup_flags.h
@@ -12,7 +12,7 @@ namespace content {
// Force-appends flags to the command line turning on Android-specific
// features owned by Content. This is called as soon as possible during
// initialization to make sure code sees the new flags.
-void SetContentCommandLineFlags(int max_render_process_count,
+void SetContentCommandLineFlags(bool single_process,
const std::string& plugin_descriptor);
} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index 5407032441b..68b0b5f0cad 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -7,16 +7,20 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/power_save_blocker_impl.h"
#include "content/common/android/surface_texture_peer.h"
+#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "jni/ContentVideoView_jni.h"
using base::android::AttachCurrentThread;
using base::android::CheckException;
using base::android::ScopedJavaGlobalRef;
+using base::UserMetricsAction;
+using content::RecordAction;
namespace content {
@@ -49,7 +53,6 @@ ContentVideoView::ContentVideoView(
DCHECK(!g_content_video_view);
j_content_video_view_ = CreateJavaObject();
g_content_video_view = this;
- CreatePowerSaveBlocker();
}
ContentVideoView::~ContentVideoView() {
@@ -68,7 +71,6 @@ void ContentVideoView::OpenVideo() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- CreatePowerSaveBlocker();
Java_ContentVideoView_openVideo(env, content_video_view.obj());
}
}
@@ -77,7 +79,6 @@ void ContentVideoView::OnMediaPlayerError(int error_type) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- power_save_blocker_.reset();
Java_ContentVideoView_onMediaPlayerError(env, content_video_view.obj(),
error_type);
}
@@ -105,7 +106,6 @@ void ContentVideoView::OnPlaybackComplete() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
- power_save_blocker_.reset();
Java_ContentVideoView_onPlaybackComplete(env, content_video_view.obj());
}
}
@@ -117,6 +117,40 @@ void ContentVideoView::OnExitFullscreen() {
Java_ContentVideoView_onExitFullscreen(env, content_video_view.obj());
}
+void ContentVideoView::RecordFullscreenPlayback(
+ JNIEnv*, jobject, bool is_portrait_video, bool is_orientation_portrait) {
+ UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.OrientationPortrait",
+ is_orientation_portrait);
+ UMA_HISTOGRAM_BOOLEAN("MobileFullscreenVideo.VideoPortrait",
+ is_portrait_video);
+}
+
+void ContentVideoView::RecordExitFullscreenPlayback(
+ JNIEnv*, jobject, bool is_portrait_video,
+ long playback_duration_in_milliseconds_before_orientation_change,
+ long playback_duration_in_milliseconds_after_orientation_change) {
+ bool orientation_changed = (
+ playback_duration_in_milliseconds_after_orientation_change != 0);
+ if (is_portrait_video) {
+ UMA_HISTOGRAM_COUNTS(
+ "MobileFullscreenVideo.PortraitDuration",
+ playback_duration_in_milliseconds_before_orientation_change);
+ UMA_HISTOGRAM_COUNTS(
+ "MobileFullscreenVideo.PortraitRotation", orientation_changed);
+ if (orientation_changed) {
+ UMA_HISTOGRAM_COUNTS(
+ "MobileFullscreenVideo.DurationAfterPotraitRotation",
+ playback_duration_in_milliseconds_after_orientation_change);
+ }
+ } else {
+ UMA_HISTOGRAM_COUNTS(
+ "MobileFullscreenVideo.LandscapeDuration",
+ playback_duration_in_milliseconds_before_orientation_change);
+ UMA_HISTOGRAM_COUNTS(
+ "MobileFullscreenVideo.LandscapeRotation", orientation_changed);
+ }
+}
+
void ContentVideoView::UpdateMediaMetadata() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
@@ -163,18 +197,15 @@ void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) {
}
void ContentVideoView::Play(JNIEnv*, jobject obj) {
- CreatePowerSaveBlocker();
manager_->FullscreenPlayerPlay();
}
void ContentVideoView::Pause(JNIEnv*, jobject obj) {
- power_save_blocker_.reset();
manager_->FullscreenPlayerPause();
}
void ContentVideoView::ExitFullscreen(
JNIEnv*, jobject, jboolean release_media_player) {
- power_save_blocker_.reset();
j_content_video_view_.reset();
manager_->ExitFullscreen(release_media_player);
}
@@ -196,45 +227,14 @@ ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
return j_content_video_view_.get(env);
}
-gfx::NativeView ContentVideoView::GetNativeView() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (content_video_view.is_null())
- return NULL;
-
- return reinterpret_cast<gfx::NativeView>(
- Java_ContentVideoView_getNativeViewAndroid(env,
- content_video_view.obj()));
-
-}
-
JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject() {
ContentViewCoreImpl* content_view_core = manager_->GetContentViewCore();
JNIEnv* env = AttachCurrentThread();
- bool legacyMode = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableOverlayFullscreenVideoSubtitle);
return JavaObjectWeakGlobalRef(
env,
Java_ContentVideoView_createContentVideoView(
env,
- content_view_core->GetContext().obj(),
- reinterpret_cast<intptr_t>(this),
- content_view_core->GetContentVideoViewClient().obj(),
- legacyMode).obj());
-}
-
-void ContentVideoView::CreatePowerSaveBlocker() {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableOverlayFullscreenVideoSubtitle)) {
- return;
- }
-
- if (power_save_blocker_) return;
-
- power_save_blocker_ = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
- "Playing video").Pass();
- static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())->
- InitDisplaySleepBlocker(GetNativeView());
+ content_view_core->GetJavaObject().obj(),
+ reinterpret_cast<intptr_t>(this)).obj());
}
} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.h b/chromium/content/browser/android/content_video_view.h
index faea292b5f0..7946792cf29 100644
--- a/chromium/content/browser/android/content_video_view.h
+++ b/chromium/content/browser/android/content_video_view.h
@@ -13,13 +13,11 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
#include "ui/gfx/native_widget_types.h"
namespace content {
class BrowserMediaPlayerManager;
-class PowerSaveBlocker;
// Native mirror of ContentVideoView.java. This class is responsible for
// creating the Java video view and pass all the player status change to
@@ -72,6 +70,14 @@ class ContentVideoView {
void OnPlaybackComplete();
void OnExitFullscreen();
+ // Functions called to record fullscreen playback UMA metrics.
+ void RecordFullscreenPlayback(
+ JNIEnv*, jobject, bool is_portrait_video, bool is_orientation_portrait);
+ void RecordExitFullscreenPlayback(
+ JNIEnv*, jobject, bool is_portrait_video,
+ long playback_duration_in_milliseconds_before_orientation_change,
+ long playback_duration_in_milliseconds_after_orientation_change);
+
// Return the corresponing ContentVideoView Java object if any.
base::android::ScopedJavaLocalRef<jobject> GetJavaObject(JNIEnv* env);
@@ -79,23 +85,10 @@ class ContentVideoView {
// Creates the corresponding ContentVideoView Java object.
JavaObjectWeakGlobalRef CreateJavaObject();
- // Returns the associated NativeView
- gfx::NativeView GetNativeView();
-
- void CreatePowerSaveBlocker();
-
// Object that manages the fullscreen media player. It is responsible for
// handling all the playback controls.
BrowserMediaPlayerManager* manager_;
- // PowerSaveBlock to keep screen on for fullscreen video.
- // There is already blocker when inline video started, and it requires the
- // ContentView's container displayed to take effect; but in WebView, apps
- // could use another container to hold ContentVideoView, and the blocker in
- // ContentView's container can not keep screen on; so we need another blocker
- // here, it is no harm, just an additonal blocker.
- scoped_ptr<PowerSaveBlocker> power_save_blocker_;
-
// Weak reference of corresponding Java object.
JavaObjectWeakGlobalRef j_content_video_view_;
diff --git a/chromium/content/browser/android/content_view_core_impl.cc b/chromium/content/browser/android/content_view_core_impl.cc
index fc0af4c922b..12117bf5dfb 100644
--- a/chromium/content/browser/android/content_view_core_impl.cc
+++ b/chromium/content/browser/android/content_view_core_impl.cc
@@ -9,7 +9,6 @@
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/command_line.h"
-#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
@@ -17,42 +16,40 @@
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/output/begin_frame_args.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/android/gesture_event_type.h"
#include "content/browser/android/interstitial_page_delegate_android.h"
+#include "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
#include "content/browser/android/load_url_params.h"
+#include "content/browser/android/popup_touch_handle_drawable.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
-#include "content/browser/frame_host/navigation_controller_impl.h"
-#include "content/browser/frame_host/navigation_entry_impl.h"
-#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/browser/renderer_host/compositor_impl_android.h"
#include "content/browser/renderer_host/input/motion_event_android.h"
#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
-#include "content/browser/renderer_host/java/java_bound_object.h"
-#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
-#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
-#include "content/browser/ssl/ssl_host_state.h"
+#include "content/browser/transition_request_manager.h"
#include "content/browser/web_contents/web_contents_view_android.h"
#include "content/common/frame_messages.h"
#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
-#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/screen_orientation_dispatcher_host.h"
+#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/menu_item.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/user_agent.h"
#include "jni/ContentViewCore_jni.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/android/view_android.h"
#include "ui/base/android/window_android.h"
@@ -66,7 +63,6 @@ using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertJavaStringToUTF8;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
-using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
using blink::WebGestureEvent;
using blink::WebInputEvent;
@@ -74,10 +70,17 @@ using blink::WebInputEvent;
// Describes the type and enabled state of a select popup item.
namespace {
-enum {
-#define DEFINE_POPUP_ITEM_TYPE(name, value) POPUP_ITEM_TYPE_##name = value,
-#include "content/browser/android/popup_item_type_list.h"
-#undef DEFINE_POPUP_ITEM_TYPE
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
+enum PopupItemType {
+ // Popup item is of type group
+ POPUP_ITEM_TYPE_GROUP,
+
+ // Popup item is disabled
+ POPUP_ITEM_TYPE_DISABLED,
+
+ // Popup item is enabled
+ POPUP_ITEM_TYPE_ENABLED,
};
} //namespace
@@ -112,37 +115,37 @@ ScopedJavaLocalRef<jobject> CreateJavaRect(
int ToGestureEventType(WebInputEvent::Type type) {
switch (type) {
case WebInputEvent::GestureScrollBegin:
- return SCROLL_START;
+ return GESTURE_EVENT_TYPE_SCROLL_START;
case WebInputEvent::GestureScrollEnd:
- return SCROLL_END;
+ return GESTURE_EVENT_TYPE_SCROLL_END;
case WebInputEvent::GestureScrollUpdate:
- return SCROLL_BY;
+ return GESTURE_EVENT_TYPE_SCROLL_BY;
case WebInputEvent::GestureFlingStart:
- return FLING_START;
+ return GESTURE_EVENT_TYPE_FLING_START;
case WebInputEvent::GestureFlingCancel:
- return FLING_CANCEL;
+ return GESTURE_EVENT_TYPE_FLING_CANCEL;
case WebInputEvent::GestureShowPress:
- return SHOW_PRESS;
+ return GESTURE_EVENT_TYPE_SHOW_PRESS;
case WebInputEvent::GestureTap:
- return SINGLE_TAP_CONFIRMED;
+ return GESTURE_EVENT_TYPE_SINGLE_TAP_CONFIRMED;
case WebInputEvent::GestureTapUnconfirmed:
- return SINGLE_TAP_UNCONFIRMED;
+ return GESTURE_EVENT_TYPE_SINGLE_TAP_UNCONFIRMED;
case WebInputEvent::GestureTapDown:
- return TAP_DOWN;
+ return GESTURE_EVENT_TYPE_TAP_DOWN;
case WebInputEvent::GestureTapCancel:
- return TAP_CANCEL;
+ return GESTURE_EVENT_TYPE_TAP_CANCEL;
case WebInputEvent::GestureDoubleTap:
- return DOUBLE_TAP;
+ return GESTURE_EVENT_TYPE_DOUBLE_TAP;
case WebInputEvent::GestureLongPress:
- return LONG_PRESS;
+ return GESTURE_EVENT_TYPE_LONG_PRESS;
case WebInputEvent::GestureLongTap:
- return LONG_TAP;
+ return GESTURE_EVENT_TYPE_LONG_TAP;
case WebInputEvent::GesturePinchBegin:
- return PINCH_BEGIN;
+ return GESTURE_EVENT_TYPE_PINCH_BEGIN;
case WebInputEvent::GesturePinchEnd:
- return PINCH_END;
+ return GESTURE_EVENT_TYPE_PINCH_END;
case WebInputEvent::GesturePinchUpdate:
- return PINCH_BY;
+ return GESTURE_EVENT_TYPE_PINCH_BY;
case WebInputEvent::GestureTwoFingerTap:
case WebInputEvent::GestureScrollUpdateWithoutPropagation:
default:
@@ -190,7 +193,7 @@ class ContentViewCoreImpl::ContentViewUserData
ContentViewCoreImpl* ContentViewCoreImpl::FromWebContents(
content::WebContents* web_contents) {
ContentViewCoreImpl::ContentViewUserData* data =
- reinterpret_cast<ContentViewCoreImpl::ContentViewUserData*>(
+ static_cast<ContentViewCoreImpl::ContentViewUserData*>(
web_contents->GetUserData(kContentViewUserDataKey));
return data ? data->get() : NULL;
}
@@ -226,6 +229,8 @@ ContentViewCoreImpl::ContentViewCoreImpl(
accessibility_enabled_(false) {
CHECK(web_contents) <<
"A ContentViewCoreImpl should be created with a valid WebContents.";
+ DCHECK(view_android_);
+ DCHECK(window_android_);
root_layer_->SetBackgroundColor(GetBackgroundColor(env, obj));
gfx::Size physical_size(
@@ -244,9 +249,9 @@ ContentViewCoreImpl::ContentViewCoreImpl(
BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
web_contents->SetUserAgentOverride(spoofed_ua);
- java_bridge_dispatcher_host_manager_.reset(
- new JavaBridgeDispatcherHostManager(web_contents,
- java_bridge_retained_object_set));
+ java_bridge_dispatcher_host_.reset(
+ new GinJavaBridgeDispatcherHost(web_contents,
+ java_bridge_retained_object_set));
InitWebContents();
}
@@ -270,6 +275,15 @@ void ContentViewCoreImpl::OnJavaContentViewCoreDestroyed(JNIEnv* env,
jobject obj) {
DCHECK(env->IsSameObject(java_ref_.get(env).obj(), obj));
java_ref_.reset();
+ // Java peer has gone, ContentViewCore is not functional and waits to
+ // be destroyed with WebContents.
+ // We need to reset WebContentsViewAndroid's reference, otherwise, there
+ // could have call in when swapping the WebContents,
+ // see http://crbug.com/383939 .
+ DCHECK(web_contents_);
+ static_cast<WebContentsViewAndroid*>(
+ static_cast<WebContentsImpl*>(web_contents_)->GetView())->
+ SetContentViewCore(NULL);
}
void ContentViewCoreImpl::InitWebContents() {
@@ -348,32 +362,11 @@ jint ContentViewCoreImpl::GetBackgroundColor(JNIEnv* env, jobject obj) {
return rwhva->GetCachedBackgroundColor();
}
-void ContentViewCoreImpl::OnHide(JNIEnv* env, jobject obj) {
- Hide();
-}
-
-void ContentViewCoreImpl::OnShow(JNIEnv* env, jobject obj) {
- Show();
-}
-
-void ContentViewCoreImpl::Show() {
- GetWebContents()->WasShown();
-}
-
-void ContentViewCoreImpl::Hide() {
- GetWebContents()->WasHidden();
- PauseVideo();
-}
-
-void ContentViewCoreImpl::PauseVideo() {
- RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
- web_contents_->GetRenderViewHost());
- if (rvhi)
- rvhi->media_web_contents_observer()->PauseVideo();
-}
-
void ContentViewCoreImpl::PauseOrResumeGeolocation(bool should_pause) {
- web_contents_->geolocation_dispatcher_host()->PauseOrResume(should_pause);
+ if (should_pause)
+ web_contents_->GetGeolocationServiceContext()->PauseUpdates();
+ else
+ web_contents_->GetGeolocationServiceContext()->ResumeUpdates();
}
// All positions and sizes are in CSS pixels.
@@ -386,17 +379,14 @@ void ContentViewCoreImpl::UpdateFrameInfo(
const gfx::SizeF& content_size,
const gfx::SizeF& viewport_size,
const gfx::Vector2dF& controls_offset,
- const gfx::Vector2dF& content_offset,
- float overdraw_bottom_height) {
+ const gfx::Vector2dF& content_offset) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
- if (window_android_) {
- window_android_->set_content_offset(
- gfx::ScaleVector2d(content_offset, dpi_scale_));
- }
+ window_android_->set_content_offset(
+ gfx::ScaleVector2d(content_offset, dpi_scale_));
Java_ContentViewCore_updateFrameInfo(
env, obj.obj(),
@@ -410,8 +400,7 @@ void ContentViewCoreImpl::UpdateFrameInfo(
viewport_size.width(),
viewport_size.height(),
controls_offset.y(),
- content_offset.y(),
- overdraw_bottom_height);
+ content_offset.y());
}
void ContentViewCoreImpl::SetTitle(const base::string16& title) {
@@ -434,8 +423,12 @@ void ContentViewCoreImpl::OnBackgroundColorChanged(SkColor color) {
Java_ContentViewCore_onBackgroundColorChanged(env, obj.obj(), color);
}
-void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect& bounds,
- const std::vector<MenuItem>& items, int selected_item, bool multiple) {
+void ContentViewCoreImpl::ShowSelectPopupMenu(
+ RenderFrameHost* frame,
+ const gfx::Rect& bounds,
+ const std::vector<MenuItem>& items,
+ int selected_item,
+ bool multiple) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
@@ -479,7 +472,9 @@ void ContentViewCoreImpl::ShowSelectPopupMenu(const gfx::Rect& bounds,
}
ScopedJavaLocalRef<jobjectArray> items_array(
base::android::ToJavaArrayOfStrings(env, labels));
- Java_ContentViewCore_showSelectPopup(env, j_obj.obj(),
+ Java_ContentViewCore_showSelectPopup(env,
+ j_obj.obj(),
+ reinterpret_cast<intptr_t>(frame),
bounds_rect.obj(),
items_array.obj(),
enabled_array.obj(),
@@ -549,9 +544,6 @@ void ContentViewCoreImpl::OnGestureEventAck(const blink::WebGestureEvent& event,
event.x * dpi_scale(),
event.y * dpi_scale());
break;
- case WebInputEvent::GestureDoubleTap:
- Java_ContentViewCore_onDoubleTapEventAck(env, j_obj.obj());
- break;
default:
break;
}
@@ -598,37 +590,48 @@ void ContentViewCoreImpl::OnSelectionChanged(const std::string& text) {
Java_ContentViewCore_onSelectionChanged(env, obj.obj(), jtext.obj());
}
-void ContentViewCoreImpl::OnSelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) {
+void ContentViewCoreImpl::OnSelectionEvent(SelectionEventType event,
+ const gfx::PointF& position) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (j_obj.is_null())
return;
- ScopedJavaLocalRef<jobject> anchor_rect_dip(
- CreateJavaRect(env, params.anchor_rect));
- ScopedJavaLocalRef<jobject> focus_rect_dip(
- CreateJavaRect(env, params.focus_rect));
- Java_ContentViewCore_onSelectionBoundsChanged(env, obj.obj(),
- anchor_rect_dip.obj(),
- params.anchor_dir,
- focus_rect_dip.obj(),
- params.focus_dir,
- params.is_anchor_first);
+ Java_ContentViewCore_onSelectionEvent(
+ env, j_obj.obj(), event, position.x(), position.y());
+}
+
+scoped_ptr<TouchHandleDrawable>
+ContentViewCoreImpl::CreatePopupTouchHandleDrawable() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null()) {
+ NOTREACHED();
+ return scoped_ptr<TouchHandleDrawable>();
+ }
+ return scoped_ptr<TouchHandleDrawable>(new PopupTouchHandleDrawable(
+ Java_ContentViewCore_createPopupTouchHandleDrawable(env, obj.obj()),
+ dpi_scale_));
}
void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
+ RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
+ if (!view)
+ return;
+
+ view->OnShowingPastePopup(gfx::PointF(x_dip, y_dip));
+
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
- Java_ContentViewCore_showPastePopup(env, obj.obj(),
- static_cast<jint>(x_dip),
- static_cast<jint>(y_dip));
+ Java_ContentViewCore_showPastePopupWithFeedback(env, obj.obj(),
+ static_cast<jint>(x_dip),
+ static_cast<jint>(y_dip));
}
void ContentViewCoreImpl::GetScaledContentBitmap(
float scale,
- jobject jbitmap_config,
+ SkColorType color_type,
gfx::Rect src_subrect,
const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
@@ -636,8 +639,8 @@ void ContentViewCoreImpl::GetScaledContentBitmap(
result_callback.Run(false, SkBitmap());
return;
}
- SkBitmap::Config skbitmap_format = gfx::ConvertToSkiaConfig(jbitmap_config);
- view->GetScaledContentBitmap(scale, skbitmap_format, src_subrect,
+
+ view->GetScaledContentBitmap(scale, color_type, src_subrect,
result_callback);
}
@@ -654,7 +657,7 @@ void ContentViewCoreImpl::StartContentIntent(const GURL& content_url) {
}
void ContentViewCoreImpl::ShowDisambiguationPopup(
- const gfx::Rect& target_rect,
+ const gfx::Rect& rect_pixels,
const SkBitmap& zoomed_bitmap) {
JNIEnv* env = AttachCurrentThread();
@@ -662,7 +665,7 @@ void ContentViewCoreImpl::ShowDisambiguationPopup(
if (obj.is_null())
return;
- ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, target_rect));
+ ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, rect_pixels));
ScopedJavaLocalRef<jobject> java_bitmap =
gfx::ConvertToJavaBitmap(&zoomed_bitmap);
@@ -683,26 +686,6 @@ ScopedJavaLocalRef<jobject> ContentViewCoreImpl::CreateTouchEventSynthesizer() {
return Java_ContentViewCore_createTouchEventSynthesizer(env, obj.obj());
}
-ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContentVideoViewClient() {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return ScopedJavaLocalRef<jobject>();
-
- return Java_ContentViewCore_getContentVideoViewClient(env, obj.obj());
-}
-
-ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() {
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
- return ScopedJavaLocalRef<jobject>();
-
- return Java_ContentViewCore_getContext(env, obj.obj());
-}
-
bool ContentViewCoreImpl::ShouldBlockMediaRequest(const GURL& url) {
JNIEnv* env = AttachCurrentThread();
@@ -722,10 +705,19 @@ void ContentViewCoreImpl::DidStopFlinging() {
Java_ContentViewCore_onNativeFlingStopped(env, obj.obj());
}
+ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return ScopedJavaLocalRef<jobject>();
+
+ return Java_ContentViewCore_getContext(env, obj.obj());
+}
+
gfx::Size ContentViewCoreImpl::GetViewSize() const {
gfx::Size size = GetViewportSizeDip();
- gfx::Size offset = GetViewportSizeOffsetDip();
- size.Enlarge(-offset.width(), -offset.height());
+ size.Enlarge(0, -GetTopControlsLayoutHeightDip());
return size;
}
@@ -749,14 +741,12 @@ gfx::Size ContentViewCoreImpl::GetViewportSizePix() const {
Java_ContentViewCore_getViewportHeightPix(env, j_obj.obj()));
}
-gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetPix() const {
+int ContentViewCoreImpl::GetTopControlsLayoutHeightPix() const {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
if (j_obj.is_null())
- return gfx::Size();
- return gfx::Size(
- Java_ContentViewCore_getViewportSizeOffsetWidthPix(env, j_obj.obj()),
- Java_ContentViewCore_getViewportSizeOffsetHeightPix(env, j_obj.obj()));
+ return 0;
+ return Java_ContentViewCore_getTopControlsLayoutHeightPix(env, j_obj.obj());
}
gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
@@ -764,22 +754,12 @@ gfx::Size ContentViewCoreImpl::GetViewportSizeDip() const {
gfx::ScaleSize(GetViewportSizePix(), 1.0f / dpi_scale()));
}
-gfx::Size ContentViewCoreImpl::GetViewportSizeOffsetDip() const {
- return gfx::ToCeiledSize(
- gfx::ScaleSize(GetViewportSizeOffsetPix(), 1.0f / dpi_scale()));
-}
-
-float ContentViewCoreImpl::GetOverdrawBottomHeightDip() const {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
- if (j_obj.is_null())
- return 0.f;
- return Java_ContentViewCore_getOverdrawBottomHeightPix(env, j_obj.obj())
- / dpi_scale();
+float ContentViewCoreImpl::GetTopControlsLayoutHeightDip() const {
+ return GetTopControlsLayoutHeightPix() / dpi_scale();
}
void ContentViewCoreImpl::AttachLayer(scoped_refptr<cc::Layer> layer) {
- root_layer_->AddChild(layer);
+ root_layer_->InsertChild(layer, 0);
root_layer_->SetIsDrawable(false);
}
@@ -790,20 +770,31 @@ void ContentViewCoreImpl::RemoveLayer(scoped_refptr<cc::Layer> layer) {
root_layer_->SetIsDrawable(true);
}
-void ContentViewCoreImpl::LoadUrl(
- NavigationController::LoadURLParams& params) {
- GetWebContents()->GetController().LoadURLWithParams(params);
+void ContentViewCoreImpl::MoveRangeSelectionExtent(const gfx::PointF& extent) {
+ if (!web_contents_)
+ return;
+
+ web_contents_->MoveRangeSelectionExtent(gfx::Point(extent.x(), extent.y()));
+}
+
+void ContentViewCoreImpl::SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) {
+ if (!web_contents_)
+ return;
+
+ gfx::Point base_point = gfx::Point(base.x(), base.y());
+ gfx::Point extent_point = gfx::Point(extent.x(), extent.y());
+ if (base_point == extent_point)
+ return;
+
+ web_contents_->SelectRange(base_point, extent_point);
}
ui::ViewAndroid* ContentViewCoreImpl::GetViewAndroid() const {
- // view_android_ should never be null for Chrome.
- DCHECK(view_android_);
return view_android_;
}
ui::WindowAndroid* ContentViewCoreImpl::GetWindowAndroid() const {
- // This should never be NULL for Chrome, but will be NULL for WebView.
- DCHECK(window_android_);
return window_android_;
}
@@ -815,13 +806,15 @@ scoped_refptr<cc::Layer> ContentViewCoreImpl::GetLayer() const {
// Methods called from Java via JNI
// ----------------------------------------------------------------------------
-void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
+void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env,
+ jobject obj,
+ jlong selectPopupSourceFrame,
jintArray indices) {
- RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
- web_contents_->GetRenderViewHost());
- DCHECK(rvhi);
+ RenderFrameHostImpl* rfhi =
+ reinterpret_cast<RenderFrameHostImpl*>(selectPopupSourceFrame);
+ DCHECK(rfhi);
if (indices == NULL) {
- rvhi->DidCancelPopupMenu();
+ rfhi->DidCancelPopupMenu();
return;
}
@@ -831,73 +824,7 @@ void ContentViewCoreImpl::SelectPopupMenuItems(JNIEnv* env, jobject obj,
for (int i = 0; i < selected_count; ++i)
selected_indices.push_back(indices_ptr[i]);
env->ReleaseIntArrayElements(indices, indices_ptr, JNI_ABORT);
- rvhi->DidSelectPopupMenuItems(selected_indices);
-}
-
-void ContentViewCoreImpl::LoadUrl(
- JNIEnv* env, jobject obj,
- jstring url,
- jint load_url_type,
- jint transition_type,
- jstring j_referrer_url,
- jint referrer_policy,
- jint ua_override_option,
- jstring extra_headers,
- jbyteArray post_data,
- jstring base_url_for_data_url,
- jstring virtual_url_for_data_url,
- jboolean can_load_local_resources,
- jboolean is_renderer_initiated) {
- DCHECK(url);
- NavigationController::LoadURLParams params(
- GURL(ConvertJavaStringToUTF8(env, url)));
-
- params.load_type = static_cast<NavigationController::LoadURLType>(
- load_url_type);
- params.transition_type = PageTransitionFromInt(transition_type);
- params.override_user_agent =
- static_cast<NavigationController::UserAgentOverrideOption>(
- ua_override_option);
-
- if (extra_headers)
- params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
-
- if (post_data) {
- std::vector<uint8> http_body_vector;
- base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
- params.browser_initiated_post_data =
- base::RefCountedBytes::TakeVector(&http_body_vector);
- }
-
- if (base_url_for_data_url) {
- params.base_url_for_data_url =
- GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
- }
-
- if (virtual_url_for_data_url) {
- params.virtual_url_for_data_url =
- GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
- }
-
- params.can_load_local_resources = can_load_local_resources;
- if (j_referrer_url) {
- params.referrer = content::Referrer(
- GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
- static_cast<blink::WebReferrerPolicy>(referrer_policy));
- }
-
- params.is_renderer_initiated = is_renderer_initiated;
-
- LoadUrl(params);
-}
-
-ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
- JNIEnv* env, jobject) const {
- return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
-}
-
-jboolean ContentViewCoreImpl::IsIncognito(JNIEnv* env, jobject obj) {
- return GetWebContents()->GetBrowserContext()->IsOffTheRecord();
+ rfhi->DidSelectPopupMenuItems(selected_indices);
}
WebContents* ContentViewCoreImpl::GetWebContents() const {
@@ -943,13 +870,36 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
jint pointer_id_1,
jfloat touch_major_0,
jfloat touch_major_1,
+ jfloat touch_minor_0,
+ jfloat touch_minor_1,
+ jfloat orientation_0,
+ jfloat orientation_1,
jfloat raw_pos_x,
- jfloat raw_pos_y) {
+ jfloat raw_pos_y,
+ jint android_tool_type_0,
+ jint android_tool_type_1,
+ jint android_button_state,
+ jint android_meta_state,
+ jboolean is_touch_handle_event) {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
// Avoid synthesizing a touch event if it cannot be forwarded.
if (!rwhv)
return false;
+ MotionEventAndroid::Pointer pointer0(pointer_id_0,
+ pos_x_0,
+ pos_y_0,
+ touch_major_0,
+ touch_minor_0,
+ orientation_0,
+ android_tool_type_0);
+ MotionEventAndroid::Pointer pointer1(pointer_id_1,
+ pos_x_1,
+ pos_y_1,
+ touch_major_1,
+ touch_minor_1,
+ orientation_1,
+ android_tool_type_1);
MotionEventAndroid event(1.f / dpi_scale(),
env,
motion_event,
@@ -958,18 +908,15 @@ jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
pointer_count,
history_size,
action_index,
- pos_x_0,
- pos_y_0,
- pos_x_1,
- pos_y_1,
- pointer_id_0,
- pointer_id_1,
- touch_major_0,
- touch_major_1,
- raw_pos_x,
- raw_pos_y);
+ android_button_state,
+ android_meta_state,
+ raw_pos_x - pos_x_0,
+ raw_pos_y - pos_y_0,
+ pointer0,
+ pointer1);
- return rwhv->OnTouchEvent(event);
+ return is_touch_handle_event ? rwhv->OnTouchHandleEvent(event)
+ : rwhv->OnTouchEvent(event);
}
float ContentViewCoreImpl::GetDpiScale() const {
@@ -1133,20 +1080,29 @@ void ContentViewCoreImpl::PinchBy(JNIEnv* env, jobject obj, jlong time_ms,
void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
jfloat x1, jfloat y1,
jfloat x2, jfloat y2) {
- if (!web_contents_)
- return;
-
- web_contents_->SelectRange(
- gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
- gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
+ SelectBetweenCoordinates(gfx::PointF(x1 / dpi_scale(), y1 / dpi_scale()),
+ gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
}
void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
jfloat x, jfloat y) {
- if (GetRenderWidgetHostViewAndroid()) {
- GetRenderWidgetHostViewAndroid()->MoveCaret(
- gfx::Point(x / dpi_scale(), y / dpi_scale()));
- }
+ RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+ if (rwhv)
+ rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
+}
+
+void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env, jobject obj) {
+ RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+ if (rwhv)
+ rwhv->DismissTextHandles();
+}
+
+void ContentViewCoreImpl::SetTextHandlesTemporarilyHidden(JNIEnv* env,
+ jobject obj,
+ jboolean hidden) {
+ RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+ if (rwhv)
+ rwhv->SetTextHandlesTemporarilyHidden(hidden);
}
void ContentViewCoreImpl::ResetGestureDetection(JNIEnv* env, jobject obj) {
@@ -1171,58 +1127,11 @@ void ContentViewCoreImpl::SetMultiTouchZoomSupportEnabled(JNIEnv* env,
rwhv->SetMultiTouchZoomSupportEnabled(enabled);
}
-void ContentViewCoreImpl::LoadIfNecessary(JNIEnv* env, jobject obj) {
- web_contents_->GetController().LoadIfNecessary();
-}
-
-void ContentViewCoreImpl::RequestRestoreLoad(JNIEnv* env, jobject obj) {
- web_contents_->GetController().SetNeedsReload();
-}
-
-void ContentViewCoreImpl::Reload(JNIEnv* env,
- jobject obj,
- jboolean check_for_repost) {
- if (web_contents_->GetController().NeedsReload())
- web_contents_->GetController().LoadIfNecessary();
- else
- web_contents_->GetController().Reload(check_for_repost);
-}
-
-void ContentViewCoreImpl::ReloadIgnoringCache(JNIEnv* env,
- jobject obj,
- jboolean check_for_repost) {
- web_contents_->GetController().ReloadIgnoringCache(check_for_repost);
-}
-
-void ContentViewCoreImpl::CancelPendingReload(JNIEnv* env, jobject obj) {
- web_contents_->GetController().CancelPendingReload();
-}
-
-void ContentViewCoreImpl::ContinuePendingReload(JNIEnv* env, jobject obj) {
- web_contents_->GetController().ContinuePendingReload();
-}
-
-void ContentViewCoreImpl::ClearHistory(JNIEnv* env, jobject obj) {
- // TODO(creis): Do callers of this need to know if it fails?
- if (web_contents_->GetController().CanPruneAllButLastCommitted())
- web_contents_->GetController().PruneAllButLastCommitted();
-}
-
-void ContentViewCoreImpl::AddStyleSheetByURL(
- JNIEnv* env, jobject obj, jstring url) {
- if (!web_contents_)
- return;
-
- web_contents_->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
- web_contents_->GetMainFrame()->GetRoutingID(),
- ConvertJavaStringToUTF8(env, url)));
-}
-
void ContentViewCoreImpl::SetAllowJavascriptInterfacesInspection(
JNIEnv* env,
jobject obj,
jboolean allow) {
- java_bridge_dispatcher_host_manager_->SetAllowObjectContentsInspection(allow);
+ java_bridge_dispatcher_host_->SetAllowObjectContentsInspection(allow);
}
void ContentViewCoreImpl::AddJavascriptInterface(
@@ -1233,24 +1142,15 @@ void ContentViewCoreImpl::AddJavascriptInterface(
jclass safe_annotation_clazz) {
ScopedJavaLocalRef<jobject> scoped_object(env, object);
ScopedJavaLocalRef<jclass> scoped_clazz(env, safe_annotation_clazz);
-
- // JavaBoundObject creates the NPObject with a ref count of 1, and
- // JavaBridgeDispatcherHostManager takes its own ref.
- NPObject* bound_object = JavaBoundObject::Create(
- scoped_object,
- scoped_clazz,
- java_bridge_dispatcher_host_manager_->AsWeakPtr(),
- java_bridge_dispatcher_host_manager_->GetAllowObjectContentsInspection());
- java_bridge_dispatcher_host_manager_->AddNamedObject(
- ConvertJavaStringToUTF16(env, name), bound_object);
- blink::WebBindings::releaseObject(bound_object);
+ java_bridge_dispatcher_host_->AddNamedObject(
+ ConvertJavaStringToUTF8(env, name), scoped_object, scoped_clazz);
}
void ContentViewCoreImpl::RemoveJavascriptInterface(JNIEnv* env,
jobject /* obj */,
jstring name) {
- java_bridge_dispatcher_host_manager_->RemoveNamedObject(
- ConvertJavaStringToUTF16(env, name));
+ java_bridge_dispatcher_host_->RemoveNamedObject(
+ ConvertJavaStringToUTF8(env, name));
}
void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
@@ -1268,141 +1168,6 @@ void ContentViewCoreImpl::WasResized(JNIEnv* env, jobject obj) {
}
}
-void ContentViewCoreImpl::ShowInterstitialPage(
- JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr) {
- GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
- InterstitialPageDelegateAndroid* delegate =
- reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
- InterstitialPage* interstitial = InterstitialPage::Create(
- web_contents_, false, url, delegate);
- delegate->set_interstitial_page(interstitial);
- interstitial->Show();
-}
-
-jboolean ContentViewCoreImpl::IsShowingInterstitialPage(JNIEnv* env,
- jobject obj) {
- return web_contents_->ShowingInterstitialPage();
-}
-
-jboolean ContentViewCoreImpl::IsRenderWidgetHostViewReady(JNIEnv* env,
- jobject obj) {
- RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
- return view && view->HasValidFrame();
-}
-
-void ContentViewCoreImpl::ExitFullscreen(JNIEnv* env, jobject obj) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- if (!host)
- return;
- host->ExitFullscreen();
-}
-
-void ContentViewCoreImpl::UpdateTopControlsState(JNIEnv* env,
- jobject obj,
- bool enable_hiding,
- bool enable_showing,
- bool animate) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- if (!host)
- return;
- host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
- enable_hiding,
- enable_showing,
- animate));
-}
-
-void ContentViewCoreImpl::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
-}
-
-void ContentViewCoreImpl::ScrollFocusedEditableNodeIntoView(JNIEnv* env,
- jobject obj) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
- host->GetRoutingID(), gfx::Rect()));
-}
-
-void ContentViewCoreImpl::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
- RenderViewHost* host = web_contents_->GetRenderViewHost();
- if (!host)
- return;
- host->SelectWordAroundCaret();
-}
-
-namespace {
-
-static void AddNavigationEntryToHistory(JNIEnv* env, jobject obj,
- jobject history,
- NavigationEntry* entry,
- int index) {
- // Get the details of the current entry
- ScopedJavaLocalRef<jstring> j_url(
- ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
- ScopedJavaLocalRef<jstring> j_virtual_url(
- ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
- ScopedJavaLocalRef<jstring> j_original_url(
- ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
- ScopedJavaLocalRef<jstring> j_title(
- ConvertUTF16ToJavaString(env, entry->GetTitle()));
- ScopedJavaLocalRef<jobject> j_bitmap;
- const FaviconStatus& status = entry->GetFavicon();
- if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
- j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
-
- // Add the item to the list
- Java_ContentViewCore_addToNavigationHistory(
- env, obj, history, index, j_url.obj(), j_virtual_url.obj(),
- j_original_url.obj(), j_title.obj(), j_bitmap.obj());
-}
-
-} // namespace
-
-int ContentViewCoreImpl::GetNavigationHistory(JNIEnv* env,
- jobject obj,
- jobject history) {
- // Iterate through navigation entries to populate the list
- const NavigationController& controller = web_contents_->GetController();
- int count = controller.GetEntryCount();
- for (int i = 0; i < count; ++i) {
- AddNavigationEntryToHistory(
- env, obj, history, controller.GetEntryAtIndex(i), i);
- }
-
- return controller.GetCurrentEntryIndex();
-}
-
-void ContentViewCoreImpl::GetDirectedNavigationHistory(JNIEnv* env,
- jobject obj,
- jobject history,
- jboolean is_forward,
- jint max_entries) {
- // Iterate through navigation entries to populate the list
- const NavigationController& controller = web_contents_->GetController();
- int count = controller.GetEntryCount();
- int num_added = 0;
- int increment_value = is_forward ? 1 : -1;
- for (int i = controller.GetCurrentEntryIndex() + increment_value;
- i >= 0 && i < count;
- i += increment_value) {
- if (num_added >= max_entries)
- break;
-
- AddNavigationEntryToHistory(
- env, obj, history, controller.GetEntryAtIndex(i), i);
- num_added++;
- }
-}
-
-ScopedJavaLocalRef<jstring>
-ContentViewCoreImpl::GetOriginalUrlForActiveNavigationEntry(JNIEnv* env,
- jobject obj) {
- NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
- if (entry == NULL)
- return ScopedJavaLocalRef<jstring>(env, NULL);
- return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
-}
-
long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
if (!rwhva)
@@ -1410,61 +1175,9 @@ long ContentViewCoreImpl::GetNativeImeAdapter(JNIEnv* env, jobject obj) {
return rwhva->GetNativeImeAdapter();
}
-namespace {
-void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
- const base::Value* result) {
- JNIEnv* env = base::android::AttachCurrentThread();
- std::string json;
- base::JSONWriter::Write(result, &json);
- ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
- Java_ContentViewCore_onEvaluateJavaScriptResult(env,
- j_json.obj(),
- callback.obj());
-}
-} // namespace
-
-void ContentViewCoreImpl::EvaluateJavaScript(JNIEnv* env,
- jobject obj,
- jstring script,
- jobject callback,
- jboolean start_renderer) {
- RenderViewHost* rvh = web_contents_->GetRenderViewHost();
- DCHECK(rvh);
-
- if (start_renderer && !rvh->IsRenderViewLive()) {
- if (!web_contents_->CreateRenderViewForInitialEmptyDocument()) {
- LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
- return;
- }
- }
-
- if (!callback) {
- // No callback requested.
- web_contents_->GetMainFrame()->ExecuteJavaScript(
- ConvertJavaStringToUTF16(env, script));
- return;
- }
-
- // Secure the Java callback in a scoped object and give ownership of it to the
- // base::Callback.
- ScopedJavaGlobalRef<jobject> j_callback;
- j_callback.Reset(env, callback);
- content::RenderFrameHost::JavaScriptResultCallback c_callback =
- base::Bind(&JavaScriptResultCallback, j_callback);
-
- web_contents_->GetMainFrame()->ExecuteJavaScript(
- ConvertJavaStringToUTF16(env, script),
- c_callback);
-}
-
-bool ContentViewCoreImpl::GetUseDesktopUserAgent(
- JNIEnv* env, jobject obj) {
- NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
- return entry && entry->GetIsOverridingUserAgent();
-}
-
void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
int text_input_type,
+ int text_input_flags,
const std::string& text,
int selection_start,
int selection_end,
@@ -1478,44 +1191,18 @@ void ContentViewCoreImpl::UpdateImeAdapter(long native_ime_adapter,
return;
ScopedJavaLocalRef<jstring> jstring_text = ConvertUTF8ToJavaString(env, text);
- Java_ContentViewCore_updateImeAdapter(env, obj.obj(),
- native_ime_adapter, text_input_type,
+ Java_ContentViewCore_updateImeAdapter(env,
+ obj.obj(),
+ native_ime_adapter,
+ text_input_type,
+ text_input_flags,
jstring_text.obj(),
- selection_start, selection_end,
- composition_start, composition_end,
- show_ime_if_needed, is_non_ime_change);
-}
-
-void ContentViewCoreImpl::ClearSslPreferences(JNIEnv* env, jobject obj) {
- SSLHostState* state = SSLHostState::GetFor(
- web_contents_->GetController().GetBrowserContext());
- state->Clear();
-}
-
-void ContentViewCoreImpl::SetUseDesktopUserAgent(
- JNIEnv* env,
- jobject obj,
- jboolean enabled,
- jboolean reload_on_state_change) {
- if (GetUseDesktopUserAgent(env, obj) == enabled)
- return;
-
- // Make sure the navigation entry actually exists.
- NavigationEntry* entry = web_contents_->GetController().GetVisibleEntry();
- if (!entry)
- return;
-
- // Set the flag in the NavigationEntry.
- entry->SetIsOverridingUserAgent(enabled);
-
- // Send the override to the renderer.
- if (reload_on_state_change) {
- // Reloading the page will send the override down as part of the
- // navigation IPC message.
- NavigationControllerImpl& controller =
- static_cast<NavigationControllerImpl&>(web_contents_->GetController());
- controller.ReloadOriginalRequestURL(false);
- }
+ selection_start,
+ selection_end,
+ composition_start,
+ composition_end,
+ show_ime_if_needed,
+ is_non_ime_change);
}
void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
@@ -1523,26 +1210,32 @@ void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj,
SetAccessibilityEnabledInternal(enabled);
}
+bool ContentViewCoreImpl::IsFullscreenRequiredForOrientationLock() const {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return true;
+ return Java_ContentViewCore_isFullscreenRequiredForOrientationLock(env,
+ obj.obj());
+}
+
void ContentViewCoreImpl::SetAccessibilityEnabledInternal(bool enabled) {
accessibility_enabled_ = enabled;
- RenderWidgetHostViewAndroid* host_view = GetRenderWidgetHostViewAndroid();
- if (!host_view)
- return;
- RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From(
- host_view->GetRenderWidgetHost());
- BrowserAccessibilityState* accessibility_state =
- BrowserAccessibilityState::GetInstance();
+ BrowserAccessibilityStateImpl* accessibility_state =
+ BrowserAccessibilityStateImpl::GetInstance();
if (enabled) {
// This enables accessibility globally unless it was explicitly disallowed
// by a command-line flag.
accessibility_state->OnScreenReaderDetected();
// If it was actually enabled globally, enable it for this RenderWidget now.
- if (accessibility_state->IsAccessibleBrowser() && host_impl)
- host_impl->AddAccessibilityMode(AccessibilityModeComplete);
+ if (accessibility_state->IsAccessibleBrowser() && web_contents_)
+ web_contents_->AddAccessibilityMode(AccessibilityModeComplete);
} else {
accessibility_state->ResetAccessibilityMode();
- if (host_impl)
- host_impl->ResetAccessibilityMode();
+ if (web_contents_) {
+ web_contents_->SetAccessibilityMode(
+ accessibility_state->accessibility_mode());
+ }
}
}
@@ -1550,6 +1243,9 @@ void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (rwhv)
rwhv->UpdateScreenInfo(GetViewAndroid());
+
+ static_cast<WebContentsImpl*>(web_contents())->
+ screen_orientation_dispatcher_host()->OnOrientationChange();
}
void ContentViewCoreImpl::ExtractSmartClipData(JNIEnv* env,
@@ -1576,8 +1272,12 @@ jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
void ContentViewCoreImpl::SetBackgroundOpaque(JNIEnv* env, jobject jobj,
jboolean opaque) {
- if (GetRenderWidgetHostViewAndroid())
- GetRenderWidgetHostViewAndroid()->SetBackgroundOpaque(opaque);
+ if (GetRenderWidgetHostViewAndroid()) {
+ if (opaque)
+ GetRenderWidgetHostViewAndroid()->SetBackgroundColorToDefault();
+ else
+ GetRenderWidgetHostViewAndroid()->SetBackgroundColor(SK_ColorTRANSPARENT);
+ }
}
void ContentViewCoreImpl::RequestTextSurroundingSelection(
@@ -1598,14 +1298,18 @@ void ContentViewCoreImpl::RequestTextSurroundingSelection(
}
void ContentViewCoreImpl::OnSmartClipDataExtracted(
- const base::string16& result) {
+ const base::string16& text,
+ const base::string16& html,
+ const gfx::Rect& clip_rect) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
- ScopedJavaLocalRef<jstring> jresult = ConvertUTF16ToJavaString(env, result);
+ ScopedJavaLocalRef<jstring> jtext = ConvertUTF16ToJavaString(env, text);
+ ScopedJavaLocalRef<jstring> jhtml = ConvertUTF16ToJavaString(env, html);
+ ScopedJavaLocalRef<jobject> clip_rect_object(CreateJavaRect(env, clip_rect));
Java_ContentViewCore_onSmartClipDataExtracted(
- env, obj.obj(), jresult.obj());
+ env, obj.obj(), jtext.obj(), jhtml.obj(), clip_rect_object.obj());
}
void ContentViewCoreImpl::WebContentsDestroyed() {
diff --git a/chromium/content/browser/android/content_view_core_impl.h b/chromium/content/browser/android/content_view_core_impl.h
index 3bb12913975..8a823ee72b8 100644
--- a/chromium/content/browser/android/content_view_core_impl.h
+++ b/chromium/content/browser/android/content_view_core_impl.h
@@ -28,7 +28,9 @@ class WindowAndroid;
}
namespace content {
-class JavaBridgeDispatcherHostManager;
+
+class GinJavaBridgeDispatcherHost;
+class RenderFrameHost;
class RenderWidgetHostViewAndroid;
struct MenuItem;
@@ -45,27 +47,25 @@ class ContentViewCoreImpl : public ContentViewCore,
jobject java_bridge_retained_object_set);
// ContentViewCore implementation.
- virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() OVERRIDE;
- virtual WebContents* GetWebContents() const OVERRIDE;
- virtual ui::ViewAndroid* GetViewAndroid() const OVERRIDE;
- virtual ui::WindowAndroid* GetWindowAndroid() const OVERRIDE;
- virtual scoped_refptr<cc::Layer> GetLayer() const OVERRIDE;
- virtual void LoadUrl(NavigationController::LoadURLParams& params) OVERRIDE;
- virtual void ShowPastePopup(int x, int y) OVERRIDE;
+ virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() override;
+ virtual WebContents* GetWebContents() const override;
+ virtual ui::ViewAndroid* GetViewAndroid() const override;
+ virtual ui::WindowAndroid* GetWindowAndroid() const override;
+ virtual scoped_refptr<cc::Layer> GetLayer() const override;
+ virtual void ShowPastePopup(int x, int y) override;
virtual void GetScaledContentBitmap(
float scale,
- jobject bitmap_config,
+ SkColorType color_type,
gfx::Rect src_subrect,
const base::Callback<void(bool, const SkBitmap&)>& result_callback)
- OVERRIDE;
- virtual float GetDpiScale() const OVERRIDE;
- virtual void PauseVideo() OVERRIDE;
- virtual void PauseOrResumeGeolocation(bool should_pause) OVERRIDE;
+ override;
+ virtual float GetDpiScale() const override;
+ virtual void PauseOrResumeGeolocation(bool should_pause) override;
virtual void RequestTextSurroundingSelection(
int max_length,
const base::Callback<void(const base::string16& content,
int start_offset,
- int end_offset)>& callback) OVERRIDE;
+ int end_offset)>& callback) override;
// --------------------------------------------------------------------------
// Methods called from Java via JNI
@@ -78,24 +78,10 @@ class ContentViewCoreImpl : public ContentViewCore,
// Notifies the ContentViewCore that items were selected in the currently
// showing select popup.
- void SelectPopupMenuItems(JNIEnv* env, jobject obj, jintArray indices);
-
- void LoadUrl(
- JNIEnv* env, jobject obj,
- jstring url,
- jint load_url_type,
- jint transition_type,
- jstring j_referrer_url,
- jint referrer_policy,
- jint ua_override_option,
- jstring extra_headers,
- jbyteArray post_data,
- jstring base_url_for_data_url,
- jstring virtual_url_for_data_url,
- jboolean can_load_local_resources,
- jboolean is_renderer_initiated);
- base::android::ScopedJavaLocalRef<jstring> GetURL(JNIEnv* env, jobject) const;
- jboolean IsIncognito(JNIEnv* env, jobject obj);
+ void SelectPopupMenuItems(JNIEnv* env, jobject obj,
+ jlong selectPopupSourceFrame,
+ jintArray indices);
+
void SendOrientationChangeEvent(JNIEnv* env, jobject obj, jint orientation);
jboolean OnTouchEvent(JNIEnv* env,
jobject obj,
@@ -113,8 +99,17 @@ class ContentViewCoreImpl : public ContentViewCore,
jint pointer_id_1,
jfloat touch_major_0,
jfloat touch_major_1,
+ jfloat touch_minor_0,
+ jfloat touch_minor_1,
+ jfloat orientation_0,
+ jfloat orientation_1,
jfloat raw_pos_x,
- jfloat raw_pos_y);
+ jfloat raw_pos_y,
+ jint android_tool_type_0,
+ jint android_tool_type_1,
+ jint android_button_state,
+ jint android_meta_state,
+ jboolean is_touch_handle_event);
jboolean SendMouseMoveEvent(JNIEnv* env,
jobject obj,
jlong time_ms,
@@ -148,6 +143,10 @@ class ContentViewCoreImpl : public ContentViewCore,
jfloat x1, jfloat y1,
jfloat x2, jfloat y2);
void MoveCaret(JNIEnv* env, jobject obj, jfloat x, jfloat y);
+ void DismissTextHandles(JNIEnv* env, jobject obj);
+ void SetTextHandlesTemporarilyHidden(JNIEnv* env,
+ jobject obj,
+ jboolean hidden);
void ResetGestureDetection(JNIEnv* env, jobject obj);
void SetDoubleTapSupportEnabled(JNIEnv* env, jobject obj, jboolean enabled);
@@ -155,36 +154,11 @@ class ContentViewCoreImpl : public ContentViewCore,
jobject obj,
jboolean enabled);
- void LoadIfNecessary(JNIEnv* env, jobject obj);
- void RequestRestoreLoad(JNIEnv* env, jobject obj);
- void Reload(JNIEnv* env, jobject obj, jboolean check_for_repost);
- void ReloadIgnoringCache(JNIEnv* env, jobject obj, jboolean check_for_repost);
- void CancelPendingReload(JNIEnv* env, jobject obj);
- void ContinuePendingReload(JNIEnv* env, jobject obj);
- void AddStyleSheetByURL(JNIEnv* env, jobject obj, jstring url);
- void ClearHistory(JNIEnv* env, jobject obj);
- void EvaluateJavaScript(JNIEnv* env,
- jobject obj,
- jstring script,
- jobject callback,
- jboolean start_renderer);
long GetNativeImeAdapter(JNIEnv* env, jobject obj);
void SetFocus(JNIEnv* env, jobject obj, jboolean focused);
- void ScrollFocusedEditableNodeIntoView(JNIEnv* env, jobject obj);
- void SelectWordAroundCaret(JNIEnv* env, jobject obj);
jint GetBackgroundColor(JNIEnv* env, jobject obj);
void SetBackgroundColor(JNIEnv* env, jobject obj, jint color);
- void OnShow(JNIEnv* env, jobject obj);
- void OnHide(JNIEnv* env, jobject obj);
- void ClearSslPreferences(JNIEnv* env, jobject /* obj */);
- void SetUseDesktopUserAgent(JNIEnv* env,
- jobject /* obj */,
- jboolean state,
- jboolean reload_on_state_change);
- bool GetUseDesktopUserAgent(JNIEnv* env, jobject /* obj */);
- void Show();
- void Hide();
void SetAllowJavascriptInterfacesInspection(JNIEnv* env,
jobject obj,
jboolean allow);
@@ -194,29 +168,7 @@ class ContentViewCoreImpl : public ContentViewCore,
jstring name,
jclass safe_annotation_clazz);
void RemoveJavascriptInterface(JNIEnv* env, jobject obj, jstring name);
- int GetNavigationHistory(JNIEnv* env, jobject obj, jobject history);
- void GetDirectedNavigationHistory(JNIEnv* env,
- jobject obj,
- jobject history,
- jboolean is_forward,
- jint max_entries);
- base::android::ScopedJavaLocalRef<jstring>
- GetOriginalUrlForActiveNavigationEntry(JNIEnv* env, jobject obj);
void WasResized(JNIEnv* env, jobject obj);
- jboolean IsRenderWidgetHostViewReady(JNIEnv* env, jobject obj);
- void ExitFullscreen(JNIEnv* env, jobject obj);
- void UpdateTopControlsState(JNIEnv* env,
- jobject obj,
- bool enable_hiding,
- bool enable_showing,
- bool animate);
- void ShowImeIfNeeded(JNIEnv* env, jobject obj);
-
- void ShowInterstitialPage(JNIEnv* env,
- jobject obj,
- jstring jurl,
- jlong delegate);
- jboolean IsShowingInterstitialPage(JNIEnv* env, jobject obj);
void SetAccessibilityEnabled(JNIEnv* env, jobject obj, bool enabled);
@@ -235,13 +187,16 @@ class ContentViewCoreImpl : public ContentViewCore,
// Public methods that call to Java via JNI
// --------------------------------------------------------------------------
- void OnSmartClipDataExtracted(const base::string16& result);
+ void OnSmartClipDataExtracted(const base::string16& text,
+ const base::string16& html,
+ const gfx::Rect& clip_rect);
// Creates a popup menu with |items|.
// |multiple| defines if it should support multi-select.
// If not |multiple|, |selected_item| sets the initially selected item.
// Otherwise, item's "checked" flag selects it.
- void ShowSelectPopupMenu(const gfx::Rect& bounds,
+ void ShowSelectPopupMenu(RenderFrameHost* frame,
+ const gfx::Rect& bounds,
const std::vector<MenuItem>& items,
int selected_item,
bool multiple);
@@ -255,14 +210,18 @@ class ContentViewCoreImpl : public ContentViewCore,
const gfx::SizeF& content_size,
const gfx::SizeF& viewport_size,
const gfx::Vector2dF& controls_offset,
- const gfx::Vector2dF& content_offset,
- float overdraw_bottom_height);
+ const gfx::Vector2dF& content_offset);
- void UpdateImeAdapter(long native_ime_adapter, int text_input_type,
+ void UpdateImeAdapter(long native_ime_adapter,
+ int text_input_type,
+ int text_input_flags,
const std::string& text,
- int selection_start, int selection_end,
- int composition_start, int composition_end,
- bool show_ime_if_needed, bool is_non_ime_change);
+ int selection_start,
+ int selection_end,
+ int composition_start,
+ int composition_end,
+ bool show_ime_if_needed,
+ bool is_non_ime_change);
void SetTitle(const base::string16& title);
void OnBackgroundColorChanged(SkColor color);
@@ -271,49 +230,54 @@ class ContentViewCoreImpl : public ContentViewCore,
InputEventAckState ack_result);
bool FilterInputEvent(const blink::WebInputEvent& event);
void OnSelectionChanged(const std::string& text);
- void OnSelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params);
+ void OnSelectionEvent(SelectionEventType event,
+ const gfx::PointF& anchor_position);
+ scoped_ptr<TouchHandleDrawable> CreatePopupTouchHandleDrawable();
void StartContentIntent(const GURL& content_url);
// Shows the disambiguation popup
- // |target_rect| --> window coordinates which |zoomed_bitmap| represents
+ // |rect_pixels| --> window coordinates which |zoomed_bitmap| represents
// |zoomed_bitmap| --> magnified image of potential touch targets
void ShowDisambiguationPopup(
- const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap);
+ const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap);
// Creates a java-side touch event, used for injecting touch event for
// testing/benchmarking purposes
base::android::ScopedJavaLocalRef<jobject> CreateTouchEventSynthesizer();
- base::android::ScopedJavaLocalRef<jobject> GetContentVideoViewClient();
-
- // Returns the context that the ContentViewCore was created with, it would
- // typically be an Activity context for an on screen view.
- base::android::ScopedJavaLocalRef<jobject> GetContext();
-
// Returns True if the given media should be blocked to load.
bool ShouldBlockMediaRequest(const GURL& url);
void DidStopFlinging();
+ // Returns the context with which the ContentViewCore was created, typically
+ // the Activity context.
+ base::android::ScopedJavaLocalRef<jobject> GetContext() const;
+
// Returns the viewport size after accounting for the viewport offset.
gfx::Size GetViewSize() const;
void SetAccessibilityEnabledInternal(bool enabled);
+ bool IsFullscreenRequiredForOrientationLock() const;
+
// --------------------------------------------------------------------------
// Methods called from native code
// --------------------------------------------------------------------------
gfx::Size GetPhysicalBackingSize() const;
gfx::Size GetViewportSizeDip() const;
- gfx::Size GetViewportSizeOffsetDip() const;
- float GetOverdrawBottomHeightDip() const;
+ float GetTopControlsLayoutHeightDip() const;
void AttachLayer(scoped_refptr<cc::Layer> layer);
void RemoveLayer(scoped_refptr<cc::Layer> layer);
+ void MoveRangeSelectionExtent(const gfx::PointF& extent);
+
+ void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent);
+
private:
class ContentViewUserData;
@@ -321,10 +285,10 @@ class ContentViewCoreImpl : public ContentViewCore,
virtual ~ContentViewCoreImpl();
// WebContentsObserver implementation.
- virtual void RenderViewReady() OVERRIDE;
+ virtual void RenderViewReady() override;
virtual void RenderViewHostChanged(RenderViewHost* old_host,
- RenderViewHost* new_host) OVERRIDE;
- virtual void WebContentsDestroyed() OVERRIDE;
+ RenderViewHost* new_host) override;
+ virtual void WebContentsDestroyed() override;
// --------------------------------------------------------------------------
// Other private methods and data
@@ -338,11 +302,8 @@ class ContentViewCoreImpl : public ContentViewCore,
blink::WebInputEvent::Type type, int64 time_ms, float x, float y) const;
gfx::Size GetViewportSizePix() const;
- gfx::Size GetViewportSizeOffsetPix() const;
-
- void DeleteScaledSnapshotTexture();
+ int GetTopControlsLayoutHeightPix() const;
- bool OnMotionEvent(const ui::MotionEvent& event);
void SendGestureEvent(const blink::WebGestureEvent& event);
// Update focus state of the RenderWidgetHostView.
@@ -380,8 +341,8 @@ class ContentViewCoreImpl : public ContentViewCore,
bool accessibility_enabled_;
// Manages injecting Java objects.
- scoped_ptr<JavaBridgeDispatcherHostManager>
- java_bridge_dispatcher_host_manager_;
+ scoped_ptr<GinJavaBridgeDispatcherHost>
+ java_bridge_dispatcher_host_;
DISALLOW_COPY_AND_ASSIGN(ContentViewCoreImpl);
};
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
index 06590fa7513..deae6733c4e 100644
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ b/chromium/content/browser/android/content_view_render_view.cc
@@ -16,6 +16,7 @@
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/content_view_layer_renderer.h"
#include "content/public/browser/android/layer_tree_build_helper.h"
+#include "content/public/browser/android/ui_resource_provider.h"
#include "jni/ContentViewRenderView_jni.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/size.h"
@@ -35,7 +36,7 @@ class LayerTreeBuildHelperImpl : public LayerTreeBuildHelper {
virtual ~LayerTreeBuildHelperImpl() {}
virtual scoped_refptr<cc::Layer> GetLayerTree(
- scoped_refptr<cc::Layer> content_root_layer) OVERRIDE {
+ scoped_refptr<cc::Layer> content_root_layer) override {
return content_root_layer;
}
@@ -70,6 +71,7 @@ void ContentViewRenderView::SetLayerTreeBuildHelper(JNIEnv* env,
LayerTreeBuildHelper* build_helper =
reinterpret_cast<LayerTreeBuildHelper*>(native_build_helper);
layer_tree_build_helper_.reset(build_helper);
+ InitCompositor();
}
// static
static jlong Init(JNIEnv* env,
@@ -120,6 +122,12 @@ void ContentViewRenderView::SurfaceChanged(JNIEnv* env, jobject obj,
void ContentViewRenderView::SetOverlayVideoMode(
JNIEnv* env, jobject obj, bool enabled) {
compositor_->SetHasTransparentBackground(enabled);
+ SetNeedsComposite(env, obj);
+}
+
+void ContentViewRenderView::SetNeedsComposite(JNIEnv* env, jobject obj) {
+ if (compositor_)
+ compositor_->SetNeedsComposite();
}
void ContentViewRenderView::Layout() {
@@ -136,4 +144,11 @@ void ContentViewRenderView::InitCompositor() {
if (!compositor_)
compositor_.reset(Compositor::Create(this, root_window_));
}
+
+jlong ContentViewRenderView::GetUIResourceProvider(JNIEnv* env,
+ jobject obj) {
+ if (!compositor_)
+ return 0;
+ return reinterpret_cast<intptr_t>(&compositor_->GetUIResourceProvider());
+}
} // namespace content
diff --git a/chromium/content/browser/android/content_view_render_view.h b/chromium/content/browser/android/content_view_render_view.h
index 2f1bcc1e7c7..ed3f03cc3fa 100644
--- a/chromium/content/browser/android/content_view_render_view.h
+++ b/chromium/content/browser/android/content_view_render_view.h
@@ -19,6 +19,7 @@ class Layer;
namespace content {
class Compositor;
class LayerTreeBuildHelper;
+class UIResourceProvider;
class ContentViewRenderView : public CompositorClient {
public:
@@ -41,10 +42,15 @@ class ContentViewRenderView : public CompositorClient {
jint format, jint width, jint height, jobject surface);
jboolean Composite(JNIEnv* env, jobject obj);
void SetOverlayVideoMode(JNIEnv* env, jobject obj, bool enabled);
+ void SetNeedsComposite(JNIEnv* env, jobject obj);
+
+ // TODO(yusufo): Remove this once the compositor code is
+ // refactored to use a unified system.
+ jlong GetUIResourceProvider(JNIEnv* env, jobject obj);
// CompositorClient implementation
- virtual void Layout() OVERRIDE;
- virtual void OnSwapBuffersCompleted(int pending_swap_buffers) OVERRIDE;
+ virtual void Layout() override;
+ virtual void OnSwapBuffersCompleted(int pending_swap_buffers) override;
private:
virtual ~ContentViewRenderView();
diff --git a/chromium/content/browser/android/content_view_statics.cc b/chromium/content/browser/android/content_view_statics.cc
index 00b5600493c..1c4e9035d15 100644
--- a/chromium/content/browser/android/content_view_statics.cc
+++ b/chromium/content/browser/android/content_view_statics.cc
@@ -32,7 +32,7 @@ namespace {
// This tracks the renderer processes that received a suspend request. It's
// important on resume to only resume the renderer processes that were actually
// suspended as opposed to all the current renderer processes because the
-// suspend calls are refcounted within WebKitPlatformSupport and it expects a
+// suspend calls are refcounted within BlinkPlatformImpl and it expects a
// perfectly matched number of resume calls.
// Note that this class is only accessed from the UI thread.
class SuspendedProcessWatcher : public content::RenderProcessHostObserver {
@@ -41,14 +41,13 @@ class SuspendedProcessWatcher : public content::RenderProcessHostObserver {
// If the process crashes, stop watching the corresponding RenderProcessHost
// and ensure it doesn't get over-resumed.
virtual void RenderProcessExited(content::RenderProcessHost* host,
- base::ProcessHandle handle,
base::TerminationStatus status,
- int exit_code) OVERRIDE {
+ int exit_code) override {
StopWatching(host);
}
virtual void RenderProcessHostDestroyed(
- content::RenderProcessHost* host) OVERRIDE {
+ content::RenderProcessHost* host) override {
StopWatching(host);
}
@@ -84,7 +83,7 @@ class SuspendedProcessWatcher : public content::RenderProcessHostObserver {
std::vector<int>::iterator pos = std::find(suspended_processes_.begin(),
suspended_processes_.end(),
host->GetID());
- DCHECK_NE(pos, suspended_processes_.end());
+ DCHECK(pos != suspended_processes_.end());
host->RemoveObserver(this);
suspended_processes_.erase(pos);
}
diff --git a/chromium/content/browser/android/date_time_chooser_android.cc b/chromium/content/browser/android/date_time_chooser_android.cc
index 58133ba22d9..31ff4656bef 100644
--- a/chromium/content/browser/android/date_time_chooser_android.cc
+++ b/chromium/content/browser/android/date_time_chooser_android.cc
@@ -9,11 +9,11 @@
#include "base/i18n/char_iterator.h"
#include "content/common/date_time_suggestion.h"
#include "content/common/view_messages.h"
-#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/render_view_host.h"
#include "jni/DateTimeChooserAndroid_jni.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "third_party/icu/source/common/unicode/unistr.h"
+#include "ui/base/android/window_android.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
@@ -73,7 +73,7 @@ void DateTimeChooserAndroid::CancelDialog(JNIEnv* env, jobject) {
}
void DateTimeChooserAndroid::ShowDialog(
- ContentViewCore* content,
+ gfx::NativeWindow native_window,
RenderViewHost* host,
ui::TextInputType dialog_type,
double dialog_value,
@@ -104,7 +104,7 @@ void DateTimeChooserAndroid::ShowDialog(
j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser(
env,
- content->GetJavaObject().obj(),
+ native_window->GetJavaObject().obj(),
reinterpret_cast<intptr_t>(this),
dialog_type,
dialog_value,
@@ -112,6 +112,8 @@ void DateTimeChooserAndroid::ShowDialog(
max,
step,
suggestions_array.obj()));
+ if (j_date_time_chooser_.is_null())
+ ReplaceDateTime(env, j_date_time_chooser_.obj(), dialog_value);
}
// ----------------------------------------------------------------------------
diff --git a/chromium/content/browser/android/date_time_chooser_android.h b/chromium/content/browser/android/date_time_chooser_android.h
index b47ed5ec7c5..1a29b4a0f05 100644
--- a/chromium/content/browser/android/date_time_chooser_android.h
+++ b/chromium/content/browser/android/date_time_chooser_android.h
@@ -11,6 +11,7 @@
#include "base/android/jni_weak_ref.h"
#include "base/memory/scoped_ptr.h"
#include "ui/base/ime/text_input_type.h"
+#include "ui/gfx/native_widget_types.h"
namespace content {
@@ -27,7 +28,7 @@ class DateTimeChooserAndroid {
// DateTimeChooser implementation:
// Shows the dialog. |dialog_value| is the date/time value converted to a
// number as defined in HTML. (See blink::InputType::parseToNumber())
- void ShowDialog(ContentViewCore* content,
+ void ShowDialog(gfx::NativeWindow native_window,
RenderViewHost* host,
ui::TextInputType dialog_type,
double dialog_value,
diff --git a/chromium/content/browser/android/devtools_auth.cc b/chromium/content/browser/android/devtools_auth.cc
index c89cdc0cbf1..46314c44768 100644
--- a/chromium/content/browser/android/devtools_auth.cc
+++ b/chromium/content/browser/android/devtools_auth.cc
@@ -4,19 +4,28 @@
#include "content/public/browser/android/devtools_auth.h"
+#include <pwd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
#include "base/logging.h"
namespace content {
-bool CanUserConnectToDevTools(uid_t uid, gid_t gid) {
- struct passwd* creds = getpwuid(uid);
+bool CanUserConnectToDevTools(
+ const net::UnixDomainServerSocket::Credentials& credentials) {
+ struct passwd* creds = getpwuid(credentials.user_id);
if (!creds || !creds->pw_name) {
- LOG(WARNING) << "DevTools: can't obtain creds for uid " << uid;
+ LOG(WARNING) << "DevTools: can't obtain creds for uid "
+ << credentials.user_id;
return false;
}
- if (gid == uid &&
- (strcmp("root", creds->pw_name) == 0 || // For rooted devices
- strcmp("shell", creds->pw_name) == 0)) { // For non-rooted devices
+ if (credentials.group_id == credentials.user_id &&
+ (strcmp("root", creds->pw_name) == 0 || // For rooted devices
+ strcmp("shell", creds->pw_name) == 0 || // For non-rooted devices
+
+ // From processes signed with the same key
+ credentials.user_id == getuid())) {
return true;
}
LOG(WARNING) << "DevTools: connection attempt from " << creds->pw_name;
diff --git a/chromium/content/browser/android/download_controller_android_impl.cc b/chromium/content/browser/android/download_controller_android_impl.cc
index 2d042353036..08cea4be685 100644
--- a/chromium/content/browser/android/download_controller_android_impl.cc
+++ b/chromium/content/browser/android/download_controller_android_impl.cc
@@ -22,6 +22,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/browser/resource_request_info.h"
#include "content/public/common/referrer.h"
#include "jni/DownloadController_jni.h"
#include "net/cookies/cookie_options.h"
@@ -230,7 +231,8 @@ void DownloadControllerAndroidImpl::StartAndroidDownload(
Java_DownloadController_newHttpGetDownload(
env, GetJavaObject()->Controller(env).obj(), view.obj(), jurl.obj(),
juser_agent.obj(), jcontent_disposition.obj(), jmime_type.obj(),
- jcookie.obj(), jreferer.obj(), jfilename.obj(), info.total_bytes);
+ jcookie.obj(), jreferer.obj(), info.has_user_gesture, jfilename.obj(),
+ info.total_bytes);
}
void DownloadControllerAndroidImpl::OnDownloadStarted(
@@ -401,7 +403,8 @@ void DownloadControllerAndroidImpl::DangerousDownloadValidated(
}
DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid(
- net::URLRequest* request) {
+ net::URLRequest* request)
+ : has_user_gesture(false) {
request->GetResponseHeaderByName("content-disposition", &content_disposition);
if (request->response_headers())
@@ -416,6 +419,11 @@ DownloadControllerAndroidImpl::DownloadInfoAndroid::DownloadInfoAndroid(
original_url = request->url_chain().front();
url = request->url_chain().back();
}
+
+ const content::ResourceRequestInfo* info =
+ content::ResourceRequestInfo::ForRequest(request);
+ if (info)
+ has_user_gesture = info->HasUserGesture();
}
DownloadControllerAndroidImpl::DownloadInfoAndroid::~DownloadInfoAndroid() {}
diff --git a/chromium/content/browser/android/download_controller_android_impl.h b/chromium/content/browser/android/download_controller_android_impl.h
index 26bc2a0c4f9..7bc71bf74e2 100644
--- a/chromium/content/browser/android/download_controller_android_impl.h
+++ b/chromium/content/browser/android/download_controller_android_impl.h
@@ -65,6 +65,7 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
std::string user_agent;
std::string cookie;
std::string referer;
+ bool has_user_gesture;
WebContents* web_contents;
// Default copy constructor is used for passing this struct by value.
@@ -76,16 +77,16 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
// DownloadControllerAndroid implementation.
virtual void CreateGETDownload(int render_process_id, int render_view_id,
- int request_id) OVERRIDE;
- virtual void OnDownloadStarted(DownloadItem* download_item) OVERRIDE;
+ int request_id) override;
+ virtual void OnDownloadStarted(DownloadItem* download_item) override;
virtual void StartContextMenuDownload(
const ContextMenuParams& params, WebContents* web_contents,
- bool is_link) OVERRIDE;
+ bool is_link) override;
virtual void DangerousDownloadValidated(
- WebContents* web_contents, int download_id, bool accept) OVERRIDE;
+ WebContents* web_contents, int download_id, bool accept) override;
// DownloadItem::Observer interface.
- virtual void OnDownloadUpdated(DownloadItem* item) OVERRIDE;
+ virtual void OnDownloadUpdated(DownloadItem* item) override;
typedef base::Callback<void(const DownloadInfoAndroid&)>
GetDownloadInfoCB;
diff --git a/chromium/content/browser/android/edge_effect.cc b/chromium/content/browser/android/edge_effect.cc
index 94e5b512e20..00c1aa51c0c 100644
--- a/chromium/content/browser/android/edge_effect.cc
+++ b/chromium/content/browser/android/edge_effect.cc
@@ -5,27 +5,21 @@
#include "content/browser/android/edge_effect.h"
#include "cc/layers/layer.h"
+#include "cc/layers/ui_resource_layer.h"
+#include "ui/base/android/system_ui_resource_manager.h"
namespace content {
namespace {
-enum State {
- STATE_IDLE = 0,
- STATE_PULL,
- STATE_ABSORB,
- STATE_RECEDE,
- STATE_PULL_DECAY
-};
-
// Time it will take the effect to fully recede in ms
-const int kRecedeTime = 1000;
+const int kRecedeTimeMs = 1000;
// Time it will take before a pulled glow begins receding in ms
-const int kPullTime = 167;
+const int kPullTimeMs = 167;
// Time it will take in ms for a pulled glow to decay before release
-const int kPullDecayTime = 1000;
+const int kPullDecayTimeMs = 1000;
const float kMaxAlpha = 1.f;
const float kHeldEdgeScaleY = .5f;
@@ -41,7 +35,7 @@ const float kMaxVelocity = 10000.f;
const float kEpsilon = 0.001f;
-const float kGlowHeightToWidthRatio = 0.25f;
+const float kGlowHeightWidthRatio = 0.25f;
// How much dragging should effect the height of the edge image.
// Number determined by user testing.
@@ -55,6 +49,9 @@ const float kPullDistanceAlphaGlowFactor = 1.1f;
const int kVelocityEdgeFactor = 8;
const int kVelocityGlowFactor = 12;
+const float kEdgeHeightAtMdpi = 12.f;
+const float kGlowHeightAtMdpi = 128.f;
+
template <typename T>
T Lerp(T a, T b, T t) {
return a + (b - a) * t;
@@ -62,7 +59,7 @@ T Lerp(T a, T b, T t) {
template <typename T>
T Clamp(T value, T low, T high) {
- return value < low ? low : (value > high ? high : value);
+ return value < low ? low : (value > high ? high : value);
}
template <typename T>
@@ -76,110 +73,88 @@ T Damp(T input, T factor) {
return result;
}
-gfx::Transform ComputeTransform(EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int offset,
- int height) {
- // Edge effects that require rotation are translated to the center about which
- // the layer should be rotated to align with the corresponding edge.
- switch (edge) {
- case EdgeEffect::EDGE_TOP:
- return gfx::Transform(1, 0, 0, 1, 0, offset);
- case EdgeEffect::EDGE_LEFT:
- return gfx::Transform(0, 1, -1, 0,
- (-window_size.height() + height) / 2.f + offset,
- (window_size.height() - height) / 2.f);
- case EdgeEffect::EDGE_BOTTOM:
- return gfx::Transform(-1, 0, 0, -1,
- 0, window_size.height() - height + offset);
- case EdgeEffect::EDGE_RIGHT:
- return gfx::Transform(0, -1, 1, 0,
- (-window_size.height() - height) / 2.f + window_size.width() + offset,
- (window_size.height() - height) / 2.f);
- default:
- NOTREACHED() << "Invalid edge: " << edge;
- return gfx::Transform();
- };
-}
+} // namespace
-gfx::Size ComputeBounds(EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int height) {
- switch (edge) {
- case EdgeEffect::EDGE_TOP:
- case EdgeEffect::EDGE_BOTTOM:
- return gfx::Size(window_size.width(), height);
- case EdgeEffect::EDGE_LEFT:
- case EdgeEffect::EDGE_RIGHT:
- return gfx::Size(window_size.height(), height);
- default:
- NOTREACHED() << "Invalid edge: " << edge;
- return gfx::Size();
- };
-}
+class EdgeEffect::EffectLayer {
+ public:
+ EffectLayer(ui::SystemUIResourceManager::ResourceType resource_type,
+ ui::SystemUIResourceManager* resource_manager)
+ : ui_resource_layer_(cc::UIResourceLayer::Create()),
+ resource_type_(resource_type),
+ resource_manager_(resource_manager) {}
-void DisableLayer(cc::Layer* layer) {
- DCHECK(layer);
- layer->SetIsDrawable(false);
- layer->SetTransform(gfx::Transform());
- layer->SetOpacity(1.f);
-}
+ ~EffectLayer() { ui_resource_layer_->RemoveFromParent(); }
-void UpdateLayer(cc::Layer* layer,
- EdgeEffect::Edge edge,
- const gfx::SizeF& window_size,
- int offset,
- int height,
- float opacity) {
- DCHECK(layer);
- layer->SetIsDrawable(true);
- gfx::Size bounds = ComputeBounds(edge, window_size, height);
- layer->SetTransformOrigin(
- gfx::Point3F(bounds.width() * 0.5f, bounds.height() * 0.5f, 0));
- layer->SetTransform(ComputeTransform(edge, window_size, offset, height));
- layer->SetBounds(bounds);
- layer->SetOpacity(Clamp(opacity, 0.f, 1.f));
-}
+ void SetParent(cc::Layer* parent) {
+ if (ui_resource_layer_->parent() != parent)
+ parent->AddChild(ui_resource_layer_);
+ ui_resource_layer_->SetUIResourceId(
+ resource_manager_->GetUIResourceId(resource_type_));
+ }
+
+ void Disable() { ui_resource_layer_->SetIsDrawable(false); }
+
+ void Update(const gfx::Size& size,
+ const gfx::Transform& transform,
+ float opacity) {
+ ui_resource_layer_->SetUIResourceId(
+ resource_manager_->GetUIResourceId(resource_type_));
+ ui_resource_layer_->SetIsDrawable(true);
+ ui_resource_layer_->SetTransformOrigin(
+ gfx::Point3F(size.width() * 0.5f, 0, 0));
+ ui_resource_layer_->SetTransform(transform);
+ ui_resource_layer_->SetBounds(size);
+ ui_resource_layer_->SetOpacity(Clamp(opacity, 0.f, 1.f));
+ }
+
+ scoped_refptr<cc::UIResourceLayer> ui_resource_layer_;
+ ui::SystemUIResourceManager::ResourceType resource_type_;
+ ui::SystemUIResourceManager* resource_manager_;
-} // namespace
-
-EdgeEffect::EdgeEffect(scoped_refptr<cc::Layer> edge,
- scoped_refptr<cc::Layer> glow)
- : edge_(edge)
- , glow_(glow)
- , edge_alpha_(0)
- , edge_scale_y_(0)
- , glow_alpha_(0)
- , glow_scale_y_(0)
- , edge_alpha_start_(0)
- , edge_alpha_finish_(0)
- , edge_scale_y_start_(0)
- , edge_scale_y_finish_(0)
- , glow_alpha_start_(0)
- , glow_alpha_finish_(0)
- , glow_scale_y_start_(0)
- , glow_scale_y_finish_(0)
- , state_(STATE_IDLE)
- , pull_distance_(0) {
- // Prevent the provided layers from drawing until the effect is activated.
- DisableLayer(edge_.get());
- DisableLayer(glow_.get());
+ DISALLOW_COPY_AND_ASSIGN(EffectLayer);
+};
+
+EdgeEffect::EdgeEffect(ui::SystemUIResourceManager* resource_manager,
+ float device_scale_factor)
+ : edge_(new EffectLayer(ui::SystemUIResourceManager::OVERSCROLL_EDGE,
+ resource_manager)),
+ glow_(new EffectLayer(ui::SystemUIResourceManager::OVERSCROLL_GLOW,
+ resource_manager)),
+ base_edge_height_(kEdgeHeightAtMdpi * device_scale_factor),
+ base_glow_height_(kGlowHeightAtMdpi * device_scale_factor),
+ edge_alpha_(0),
+ edge_scale_y_(0),
+ glow_alpha_(0),
+ glow_scale_y_(0),
+ edge_alpha_start_(0),
+ edge_alpha_finish_(0),
+ edge_scale_y_start_(0),
+ edge_scale_y_finish_(0),
+ glow_alpha_start_(0),
+ glow_alpha_finish_(0),
+ glow_scale_y_start_(0),
+ glow_scale_y_finish_(0),
+ state_(STATE_IDLE),
+ pull_distance_(0) {
}
-EdgeEffect::~EdgeEffect() { }
+EdgeEffect::~EdgeEffect() {
+}
bool EdgeEffect::IsFinished() const {
return state_ == STATE_IDLE;
}
void EdgeEffect::Finish() {
- DisableLayer(edge_.get());
- DisableLayer(glow_.get());
+ edge_->Disable();
+ glow_->Disable();
pull_distance_ = 0;
state_ = STATE_IDLE;
}
-void EdgeEffect::Pull(base::TimeTicks current_time, float delta_distance) {
+void EdgeEffect::Pull(base::TimeTicks current_time,
+ float delta_distance,
+ float displacement) {
if (state_ == STATE_PULL_DECAY && current_time - start_time_ < duration_) {
return;
}
@@ -189,15 +164,15 @@ void EdgeEffect::Pull(base::TimeTicks current_time, float delta_distance) {
state_ = STATE_PULL;
start_time_ = current_time;
- duration_ = base::TimeDelta::FromMilliseconds(kPullTime);
+ duration_ = base::TimeDelta::FromMilliseconds(kPullTimeMs);
float abs_delta_distance = std::abs(delta_distance);
pull_distance_ += delta_distance;
float distance = std::abs(pull_distance_);
edge_alpha_ = edge_alpha_start_ = Clamp(distance, kPullEdgeBegin, kMaxAlpha);
- edge_scale_y_ = edge_scale_y_start_
- = Clamp(distance * kPullDistanceEdgeFactor, kHeldEdgeScaleY, 1.f);
+ edge_scale_y_ = edge_scale_y_start_ =
+ Clamp(distance * kPullDistanceEdgeFactor, kHeldEdgeScaleY, 1.f);
glow_alpha_ = glow_alpha_start_ =
std::min(kMaxAlpha,
@@ -212,7 +187,8 @@ void EdgeEffect::Pull(base::TimeTicks current_time, float delta_distance) {
// Do not allow glow to get larger than kMaxGlowHeight.
glow_scale_y_ = glow_scale_y_start_ =
Clamp(glow_scale_y_ + glow_change * kPullDistanceGlowFactor,
- 0.f, kMaxGlowHeight);
+ 0.f,
+ kMaxGlowHeight);
edge_alpha_finish_ = edge_alpha_;
edge_scale_y_finish_ = edge_scale_y_;
@@ -238,7 +214,7 @@ void EdgeEffect::Release(base::TimeTicks current_time) {
glow_scale_y_finish_ = 0.f;
start_time_ = current_time;
- duration_ = base::TimeDelta::FromMilliseconds(kRecedeTime);
+ duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
}
void EdgeEffect::Absorb(base::TimeTicks current_time, float velocity) {
@@ -262,19 +238,18 @@ void EdgeEffect::Absorb(base::TimeTicks current_time, float velocity) {
// reflect the strength of the user's scrolling.
edge_alpha_finish_ = Clamp(velocity * kVelocityEdgeFactor, 0.f, 1.f);
// Edge should never get larger than the size of its asset.
- edge_scale_y_finish_ = Clamp(velocity * kVelocityEdgeFactor,
- kHeldEdgeScaleY, 1.f);
+ edge_scale_y_finish_ =
+ Clamp(velocity * kVelocityEdgeFactor, kHeldEdgeScaleY, 1.f);
// Growth for the size of the glow should be quadratic to properly
// respond
// to a user's scrolling speed. The faster the scrolling speed, the more
// intense the effect should be for both the size and the saturation.
- glow_scale_y_finish_ = std::min(
- 0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f);
+ glow_scale_y_finish_ =
+ std::min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f);
// Alpha should change for the glow as well as size.
- glow_alpha_finish_ = Clamp(glow_alpha_start_,
- velocity * kVelocityGlowFactor * .00001f,
- kMaxAlpha);
+ glow_alpha_finish_ = Clamp(
+ glow_alpha_start_, velocity * kVelocityGlowFactor * .00001f, kMaxAlpha);
}
bool EdgeEffect::Update(base::TimeTicks current_time) {
@@ -295,7 +270,7 @@ bool EdgeEffect::Update(base::TimeTicks current_time) {
case STATE_ABSORB:
state_ = STATE_RECEDE;
start_time_ = current_time;
- duration_ = base::TimeDelta::FromMilliseconds(kRecedeTime);
+ duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
edge_alpha_start_ = edge_alpha_;
edge_scale_y_start_ = edge_scale_y_;
@@ -311,7 +286,7 @@ bool EdgeEffect::Update(base::TimeTicks current_time) {
case STATE_PULL:
state_ = STATE_PULL_DECAY;
start_time_ = current_time;
- duration_ = base::TimeDelta::FromMilliseconds(kPullDecayTime);
+ duration_ = base::TimeDelta::FromMilliseconds(kPullDecayTimeMs);
edge_alpha_start_ = edge_alpha_;
edge_scale_y_start_ = edge_scale_y_;
@@ -327,10 +302,12 @@ bool EdgeEffect::Update(base::TimeTicks current_time) {
case STATE_PULL_DECAY: {
// When receding, we want edge to decrease more slowly
// than the glow.
- const float factor = glow_scale_y_finish_ != 0 ?
- 1 / (glow_scale_y_finish_ * glow_scale_y_finish_) :
- std::numeric_limits<float>::max();
- edge_scale_y_ = edge_scale_y_start_ +
+ const float factor =
+ glow_scale_y_finish_
+ ? 1 / (glow_scale_y_finish_ * glow_scale_y_finish_)
+ : std::numeric_limits<float>::max();
+ edge_scale_y_ =
+ edge_scale_y_start_ +
(edge_scale_y_finish_ - edge_scale_y_start_) * interp * factor;
state_ = STATE_RECEDE;
} break;
@@ -348,33 +325,47 @@ bool EdgeEffect::Update(base::TimeTicks current_time) {
return !IsFinished();
}
-void EdgeEffect::ApplyToLayers(gfx::SizeF window_size,
- Edge edge,
- float edge_height,
- float glow_height,
- float offset) {
+void EdgeEffect::ApplyToLayers(const gfx::SizeF& size,
+ const gfx::Transform& transform) {
if (IsFinished())
return;
// An empty window size, while meaningless, is also relatively harmless, and
// will simply prevent any drawing of the layers.
- if (window_size.IsEmpty()) {
- DisableLayer(edge_.get());
- DisableLayer(glow_.get());
+ if (size.IsEmpty()) {
+ edge_->Disable();
+ glow_->Disable();
return;
}
// Glow
const int scaled_glow_height = static_cast<int>(
- std::min(glow_height * glow_scale_y_ * kGlowHeightToWidthRatio * 0.6f,
- glow_height * kMaxGlowHeight) + 0.5f);
- UpdateLayer(
- glow_.get(), edge, window_size, offset, scaled_glow_height, glow_alpha_);
+ std::min(base_glow_height_ * glow_scale_y_ * kGlowHeightWidthRatio * 0.6f,
+ base_glow_height_ * kMaxGlowHeight) +
+ 0.5f);
+ const gfx::Size glow_size(size.width(), scaled_glow_height);
+ glow_->Update(glow_size, transform, glow_alpha_);
// Edge
- const int scaled_edge_height = static_cast<int>(edge_height * edge_scale_y_);
- UpdateLayer(
- edge_.get(), edge, window_size, offset, scaled_edge_height, edge_alpha_);
+ const int scaled_edge_height =
+ static_cast<int>(base_edge_height_ * edge_scale_y_);
+ const gfx::Size edge_size(size.width(), scaled_edge_height);
+ edge_->Update(edge_size, transform, edge_alpha_);
+}
+
+void EdgeEffect::SetParent(cc::Layer* parent) {
+ edge_->SetParent(parent);
+ glow_->SetParent(parent);
+}
+
+// static
+void EdgeEffect::PreloadResources(
+ ui::SystemUIResourceManager* resource_manager) {
+ DCHECK(resource_manager);
+ resource_manager->PreloadResource(
+ ui::SystemUIResourceManager::OVERSCROLL_EDGE);
+ resource_manager->PreloadResource(
+ ui::SystemUIResourceManager::OVERSCROLL_GLOW);
}
-} // namespace content
+} // namespace content
diff --git a/chromium/content/browser/android/edge_effect.h b/chromium/content/browser/android/edge_effect.h
index b8febba22d2..8fb5c5f55d3 100644
--- a/chromium/content/browser/android/edge_effect.h
+++ b/chromium/content/browser/android/edge_effect.h
@@ -5,63 +5,53 @@
#ifndef CONTENT_BROWSER_ANDROID_EDGE_EFFECT_H_
#define CONTENT_BROWSER_ANDROID_EDGE_EFFECT_H_
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
-#include "ui/gfx/size_f.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/android/edge_effect_base.h"
namespace cc {
class Layer;
}
+namespace ui {
+class SystemUIResourceManager;
+}
+
namespace content {
-/* |EdgeEffect| mirrors its Android counterpart, EdgeEffect.java.
- * The primary difference is ownership; the Android version manages render
- * resources directly, while this version simply applies the effect to
- * existing resources. Conscious tradeoffs were made to align this as closely
- * as possible with the original Android java version.
- * All coordinates and dimensions are in device pixels.
- */
-class EdgeEffect {
-public:
- enum Edge {
- EDGE_TOP = 0,
- EDGE_LEFT,
- EDGE_BOTTOM,
- EDGE_RIGHT,
- EDGE_COUNT
- };
-
- EdgeEffect(scoped_refptr<cc::Layer> edge, scoped_refptr<cc::Layer> glow);
- ~EdgeEffect();
-
- void Pull(base::TimeTicks current_time, float delta_distance);
- void Absorb(base::TimeTicks current_time, float velocity);
- bool Update(base::TimeTicks current_time);
- void Release(base::TimeTicks current_time);
-
- void Finish();
- bool IsFinished() const;
-
- void ApplyToLayers(gfx::SizeF window_size,
- Edge edge,
- float edge_height,
- float glow_height,
- float offset);
-
-private:
-
- enum State {
- STATE_IDLE = 0,
- STATE_PULL,
- STATE_ABSORB,
- STATE_RECEDE,
- STATE_PULL_DECAY
- };
-
- scoped_refptr<cc::Layer> edge_;
- scoped_refptr<cc::Layer> glow_;
+// |EdgeEffect| mirrors its Android counterpart, EdgeEffect.java.
+// Conscious tradeoffs were made to align this as closely as possible with the
+// the original Android java version.
+// All coordinates and dimensions are in device pixels.
+class EdgeEffect : public EdgeEffectBase {
+ public:
+ explicit EdgeEffect(ui::SystemUIResourceManager* resource_manager,
+ float device_scale_factor);
+ virtual ~EdgeEffect();
+
+ virtual void Pull(base::TimeTicks current_time,
+ float delta_distance,
+ float displacement) override;
+ virtual void Absorb(base::TimeTicks current_time, float velocity) override;
+ virtual bool Update(base::TimeTicks current_time) override;
+ virtual void Release(base::TimeTicks current_time) override;
+
+ virtual void Finish() override;
+ virtual bool IsFinished() const override;
+
+ virtual void ApplyToLayers(const gfx::SizeF& size,
+ const gfx::Transform& transform) override;
+ virtual void SetParent(cc::Layer* parent) override;
+
+ // Thread-safe trigger to load resources.
+ static void PreloadResources(ui::SystemUIResourceManager* resource_manager);
+
+ private:
+ class EffectLayer;
+ scoped_ptr<EffectLayer> edge_;
+ scoped_ptr<EffectLayer> glow_;
+
+ float base_edge_height_;
+ float base_glow_height_;
float edge_alpha_;
float edge_scale_y_;
diff --git a/chromium/content/browser/android/edge_effect_base.h b/chromium/content/browser/android/edge_effect_base.h
new file mode 100644
index 00000000000..f7df20dfe16
--- /dev/null
+++ b/chromium/content/browser/android/edge_effect_base.h
@@ -0,0 +1,49 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_EDGE_EFFECT_BASE_H_
+#define CONTENT_BROWSER_ANDROID_EDGE_EFFECT_BASE_H_
+
+#include "base/basictypes.h"
+#include "base/time/time.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/transform.h"
+
+namespace cc {
+class Layer;
+}
+
+namespace content {
+
+// A base class for overscroll-related Android effects.
+class EdgeEffectBase {
+ public:
+ enum State {
+ STATE_IDLE = 0,
+ STATE_PULL,
+ STATE_ABSORB,
+ STATE_RECEDE,
+ STATE_PULL_DECAY
+ };
+
+ virtual ~EdgeEffectBase() {}
+
+ virtual void Pull(base::TimeTicks current_time,
+ float delta_distance,
+ float displacement) = 0;
+ virtual void Absorb(base::TimeTicks current_time, float velocity) = 0;
+ virtual bool Update(base::TimeTicks current_time) = 0;
+ virtual void Release(base::TimeTicks current_time) = 0;
+
+ virtual void Finish() = 0;
+ virtual bool IsFinished() const = 0;
+
+ virtual void ApplyToLayers(const gfx::SizeF& size,
+ const gfx::Transform& transform) = 0;
+ virtual void SetParent(cc::Layer* parent) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_EDGE_EFFECT_BASE_H_
diff --git a/chromium/content/browser/android/edge_effect_l.cc b/chromium/content/browser/android/edge_effect_l.cc
new file mode 100644
index 00000000000..ccec8a41c47
--- /dev/null
+++ b/chromium/content/browser/android/edge_effect_l.cc
@@ -0,0 +1,286 @@
+// Copyright 2014 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 "content/browser/android/edge_effect_l.h"
+
+#include "cc/layers/ui_resource_layer.h"
+#include "ui/base/android/system_ui_resource_manager.h"
+
+namespace content {
+
+namespace {
+
+// Time it will take the effect to fully recede in ms
+const int kRecedeTimeMs = 600;
+
+// Time it will take before a pulled glow begins receding in ms
+const int kPullTimeMs = 167;
+
+// Time it will take for a pulled glow to decay to partial strength before
+// release
+const int kPullDecayTimeMs = 2000;
+
+const float kMaxAlpha = 0.5f;
+
+const float kPullGlowBegin = 0.f;
+
+// Min/max velocity that will be absorbed
+const float kMinVelocity = 100.f;
+const float kMaxVelocity = 10000.f;
+
+const float kEpsilon = 0.001f;
+
+const float kSin = 0.5f; // sin(PI / 6)
+const float kCos = 0.866f; // cos(PI / 6);
+
+// How much dragging should effect the height of the glow image.
+// Number determined by user testing.
+const float kPullDistanceAlphaGlowFactor = 0.8f;
+
+const int kVelocityGlowFactor = 6;
+
+const ui::SystemUIResourceManager::ResourceType kResourceType =
+ ui::SystemUIResourceManager::OVERSCROLL_GLOW_L;
+
+template <typename T>
+T Lerp(T a, T b, T t) {
+ return a + (b - a) * t;
+}
+
+template <typename T>
+T Clamp(T value, T low, T high) {
+ return value < low ? low : (value > high ? high : value);
+}
+
+template <typename T>
+T Damp(T input, T factor) {
+ T result;
+ if (factor == 1) {
+ result = 1 - (1 - input) * (1 - input);
+ } else {
+ result = 1 - std::pow(1 - input, 2 * factor);
+ }
+ return result;
+}
+
+} // namespace
+
+EdgeEffectL::EdgeEffectL(ui::SystemUIResourceManager* resource_manager)
+ : resource_manager_(resource_manager),
+ glow_(cc::UIResourceLayer::Create()),
+ glow_alpha_(0),
+ glow_scale_y_(0),
+ glow_alpha_start_(0),
+ glow_alpha_finish_(0),
+ glow_scale_y_start_(0),
+ glow_scale_y_finish_(0),
+ displacement_(0.5f),
+ target_displacement_(0.5f),
+ state_(STATE_IDLE),
+ pull_distance_(0) {
+ // Prevent the provided layers from drawing until the effect is activated.
+ glow_->SetIsDrawable(false);
+}
+
+EdgeEffectL::~EdgeEffectL() {
+ glow_->RemoveFromParent();
+}
+
+bool EdgeEffectL::IsFinished() const {
+ return state_ == STATE_IDLE;
+}
+
+void EdgeEffectL::Finish() {
+ glow_->SetIsDrawable(false);
+ pull_distance_ = 0;
+ state_ = STATE_IDLE;
+}
+
+void EdgeEffectL::Pull(base::TimeTicks current_time,
+ float delta_distance,
+ float displacement) {
+ target_displacement_ = displacement;
+ if (state_ == STATE_PULL_DECAY && current_time - start_time_ < duration_) {
+ return;
+ }
+ if (state_ != STATE_PULL) {
+ glow_scale_y_ = std::max(kPullGlowBegin, glow_scale_y_);
+ }
+ state_ = STATE_PULL;
+
+ start_time_ = current_time;
+ duration_ = base::TimeDelta::FromMilliseconds(kPullTimeMs);
+
+ float abs_delta_distance = std::abs(delta_distance);
+ pull_distance_ += delta_distance;
+
+ glow_alpha_ = glow_alpha_start_ = std::min(
+ kMaxAlpha,
+ glow_alpha_ + (abs_delta_distance * kPullDistanceAlphaGlowFactor));
+
+ if (pull_distance_ == 0) {
+ glow_scale_y_ = glow_scale_y_start_ = 0;
+ } else {
+ float scale = 1.f -
+ 1.f / std::sqrt(std::abs(pull_distance_) * bounds_.height()) -
+ 0.3f;
+ glow_scale_y_ = glow_scale_y_start_ = std::max(0.f, scale) / 0.7f;
+ }
+
+ glow_alpha_finish_ = glow_alpha_;
+ glow_scale_y_finish_ = glow_scale_y_;
+}
+
+void EdgeEffectL::Release(base::TimeTicks current_time) {
+ pull_distance_ = 0;
+
+ if (state_ != STATE_PULL && state_ != STATE_PULL_DECAY)
+ return;
+
+ state_ = STATE_RECEDE;
+ glow_alpha_start_ = glow_alpha_;
+ glow_scale_y_start_ = glow_scale_y_;
+
+ glow_alpha_finish_ = 0.f;
+ glow_scale_y_finish_ = 0.f;
+
+ start_time_ = current_time;
+ duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
+}
+
+void EdgeEffectL::Absorb(base::TimeTicks current_time, float velocity) {
+ state_ = STATE_ABSORB;
+
+ velocity = Clamp(std::abs(velocity), kMinVelocity, kMaxVelocity);
+
+ start_time_ = current_time;
+ // This should never be less than 1 millisecond.
+ duration_ = base::TimeDelta::FromMilliseconds(0.15f + (velocity * 0.02f));
+
+ // The glow depends more on the velocity, and therefore starts out
+ // nearly invisible.
+ glow_alpha_start_ = 0.3f;
+ glow_scale_y_start_ = std::max(glow_scale_y_, 0.f);
+
+ // Growth for the size of the glow should be quadratic to properly respond
+ // to a user's scrolling speed. The faster the scrolling speed, the more
+ // intense the effect should be for both the size and the saturation.
+ glow_scale_y_finish_ =
+ std::min(0.025f + (velocity * (velocity / 100) * 0.00015f) / 2.f, 1.f);
+ // Alpha should change for the glow as well as size.
+ glow_alpha_finish_ = Clamp(
+ glow_alpha_start_, velocity * kVelocityGlowFactor * .00001f, kMaxAlpha);
+ target_displacement_ = 0.5;
+}
+
+bool EdgeEffectL::Update(base::TimeTicks current_time) {
+ if (IsFinished())
+ return false;
+
+ const double dt = (current_time - start_time_).InMilliseconds();
+ const double t = std::min(dt / duration_.InMilliseconds(), 1.);
+ const float interp = static_cast<float>(Damp(t, 1.));
+
+ glow_alpha_ = Lerp(glow_alpha_start_, glow_alpha_finish_, interp);
+ glow_scale_y_ = Lerp(glow_scale_y_start_, glow_scale_y_finish_, interp);
+ displacement_ = (displacement_ + target_displacement_) / 2.f;
+
+ if (t >= 1.f - kEpsilon) {
+ switch (state_) {
+ case STATE_ABSORB:
+ state_ = STATE_RECEDE;
+ start_time_ = current_time;
+ duration_ = base::TimeDelta::FromMilliseconds(kRecedeTimeMs);
+
+ glow_alpha_start_ = glow_alpha_;
+ glow_scale_y_start_ = glow_scale_y_;
+
+ glow_alpha_finish_ = 0.f;
+ glow_scale_y_finish_ = 0.f;
+ break;
+ case STATE_PULL:
+ state_ = STATE_PULL_DECAY;
+ start_time_ = current_time;
+ duration_ = base::TimeDelta::FromMilliseconds(kPullDecayTimeMs);
+
+ glow_alpha_start_ = glow_alpha_;
+ glow_scale_y_start_ = glow_scale_y_;
+
+ // After pull, the glow should fade to nothing.
+ glow_alpha_finish_ = 0.f;
+ glow_scale_y_finish_ = 0.f;
+ break;
+ case STATE_PULL_DECAY:
+ state_ = STATE_RECEDE;
+ break;
+ case STATE_RECEDE:
+ Finish();
+ break;
+ default:
+ break;
+ }
+ }
+
+ bool one_last_frame = false;
+ if (state_ == STATE_RECEDE && glow_scale_y_ <= 0) {
+ Finish();
+ one_last_frame = true;
+ }
+
+ return !IsFinished() || one_last_frame;
+}
+
+void EdgeEffectL::ApplyToLayers(const gfx::SizeF& size,
+ const gfx::Transform& transform) {
+ if (IsFinished())
+ return;
+
+ // An empty window size, while meaningless, is also relatively harmless, and
+ // will simply prevent any drawing of the layers.
+ if (size.IsEmpty()) {
+ glow_->SetIsDrawable(false);
+ return;
+ }
+
+ const float r = size.width() * 0.75f / kSin;
+ const float y = kCos * r;
+ const float h = r - y;
+ const float o_r = size.height() * 0.75f / kSin;
+ const float o_y = kCos * o_r;
+ const float o_h = o_r - o_y;
+ const float base_glow_scale = h > 0.f ? std::min(o_h / h, 1.f) : 1.f;
+ bounds_ = gfx::Size(size.width(), (int)std::min(size.height(), h));
+ gfx::Size image_bounds(
+ r, std::min(1.f, glow_scale_y_) * base_glow_scale * bounds_.height());
+
+ glow_->SetIsDrawable(true);
+ glow_->SetUIResourceId(resource_manager_->GetUIResourceId(kResourceType));
+ glow_->SetTransformOrigin(gfx::Point3F(bounds_.width() * 0.5f, 0, 0));
+ glow_->SetBounds(image_bounds);
+ glow_->SetContentsOpaque(false);
+ glow_->SetOpacity(Clamp(glow_alpha_, 0.f, 1.f));
+
+ const float displacement = Clamp(displacement_, 0.f, 1.f) - 0.5f;
+ const float displacement_offset_x = bounds_.width() * displacement * 0.5f;
+ const float image_offset_x = (bounds_.width() - image_bounds.width()) * 0.5f;
+ gfx::Transform offset_transform;
+ offset_transform.Translate(image_offset_x - displacement_offset_x, 0);
+ offset_transform.ConcatTransform(transform);
+ glow_->SetTransform(offset_transform);
+}
+
+void EdgeEffectL::SetParent(cc::Layer* parent) {
+ if (glow_->parent() != parent)
+ parent->AddChild(glow_);
+ glow_->SetUIResourceId(resource_manager_->GetUIResourceId(kResourceType));
+}
+
+// static
+void EdgeEffectL::PreloadResources(
+ ui::SystemUIResourceManager* resource_manager) {
+ DCHECK(resource_manager);
+ resource_manager->PreloadResource(kResourceType);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/edge_effect_l.h b/chromium/content/browser/android/edge_effect_l.h
new file mode 100644
index 00000000000..a24309c8da3
--- /dev/null
+++ b/chromium/content/browser/android/edge_effect_l.h
@@ -0,0 +1,81 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_EDGE_EFFECT_L_H_
+#define CONTENT_BROWSER_ANDROID_EDGE_EFFECT_L_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/android/edge_effect_base.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace cc {
+class Layer;
+class UIResourceLayer;
+}
+
+namespace ui {
+class SystemUIResourceManager;
+}
+
+namespace content {
+
+// |EdgeEffectL| mirrors its Android L counterpart, EdgeEffect.java.
+// Conscious tradeoffs were made to align this as closely as possible with the
+// the original Android java version.
+// All coordinates and dimensions are in device pixels.
+class EdgeEffectL : public EdgeEffectBase {
+ public:
+ explicit EdgeEffectL(ui::SystemUIResourceManager* resource_manager);
+ virtual ~EdgeEffectL();
+
+ virtual void Pull(base::TimeTicks current_time,
+ float delta_distance,
+ float displacement) override;
+ virtual void Absorb(base::TimeTicks current_time, float velocity) override;
+ virtual bool Update(base::TimeTicks current_time) override;
+ virtual void Release(base::TimeTicks current_time) override;
+
+ virtual void Finish() override;
+ virtual bool IsFinished() const override;
+
+ virtual void ApplyToLayers(const gfx::SizeF& size,
+ const gfx::Transform& transform) override;
+ virtual void SetParent(cc::Layer* parent) override;
+
+ // Thread-safe trigger to load resources.
+ static void PreloadResources(ui::SystemUIResourceManager* resource_manager);
+
+ private:
+ ui::SystemUIResourceManager* const resource_manager_;
+
+ scoped_refptr<cc::UIResourceLayer> glow_;
+
+ float glow_alpha_;
+ float glow_scale_y_;
+
+ float glow_alpha_start_;
+ float glow_alpha_finish_;
+ float glow_scale_y_start_;
+ float glow_scale_y_finish_;
+
+ gfx::RectF arc_rect_;
+ gfx::Size bounds_;
+ float displacement_;
+ float target_displacement_;
+
+ base::TimeTicks start_time_;
+ base::TimeDelta duration_;
+
+ State state_;
+
+ float pull_distance_;
+
+ DISALLOW_COPY_AND_ASSIGN(EdgeEffectL);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_EDGE_EFFECT_L_H_
diff --git a/chromium/content/browser/android/gesture_event_type.h b/chromium/content/browser/android/gesture_event_type.h
index d41311c7598..ce87c901db3 100644
--- a/chromium/content/browser/android/gesture_event_type.h
+++ b/chromium/content/browser/android/gesture_event_type.h
@@ -7,10 +7,31 @@
namespace content {
+// This file contains a list of GestureEventType's usable by ContentViewCore,
+// providing a direct mapping to and from their corresponding
+// blink::WebGestureEvent types.
+//
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser
enum GestureEventType {
-#define DEFINE_GESTURE_EVENT_TYPE(name, value) name = value,
-#include "content/browser/android/gesture_event_type_list.h"
-#undef DEFINE_GESTURE_EVENT_TYPE
+ GESTURE_EVENT_TYPE_SHOW_PRESS,
+ GESTURE_EVENT_TYPE_DOUBLE_TAP,
+ GESTURE_EVENT_TYPE_SINGLE_TAP_UP,
+ GESTURE_EVENT_TYPE_SINGLE_TAP_CONFIRMED,
+ GESTURE_EVENT_TYPE_SINGLE_TAP_UNCONFIRMED,
+ GESTURE_EVENT_TYPE_LONG_PRESS,
+ GESTURE_EVENT_TYPE_SCROLL_START,
+ GESTURE_EVENT_TYPE_SCROLL_BY,
+ GESTURE_EVENT_TYPE_SCROLL_END,
+ GESTURE_EVENT_TYPE_FLING_START,
+ GESTURE_EVENT_TYPE_FLING_CANCEL,
+ GESTURE_EVENT_TYPE_FLING_END,
+ GESTURE_EVENT_TYPE_PINCH_BEGIN,
+ GESTURE_EVENT_TYPE_PINCH_BY,
+ GESTURE_EVENT_TYPE_PINCH_END,
+ GESTURE_EVENT_TYPE_TAP_CANCEL,
+ GESTURE_EVENT_TYPE_LONG_TAP,
+ GESTURE_EVENT_TYPE_TAP_DOWN,
};
} // namespace content
diff --git a/chromium/content/browser/android/gesture_event_type_list.h b/chromium/content/browser/android/gesture_event_type_list.h
deleted file mode 100644
index 85af616cb47..00000000000
--- a/chromium/content/browser/android/gesture_event_type_list.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 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 intentionally does not have header guards because this file
-// is meant to be included inside a macro to generate enum values.
-
-// This file contains a list of GestureEventType's usable by ContentViewCore,
-// providing a direct mapping to and from their corresponding
-// blink::WebGestureEvent types.
-
-#ifndef DEFINE_GESTURE_EVENT_TYPE
-#error "Please define DEFINE_GESTURE_EVENT_TYPE before including this file."
-#endif
-
-DEFINE_GESTURE_EVENT_TYPE(SHOW_PRESS, 0)
-DEFINE_GESTURE_EVENT_TYPE(DOUBLE_TAP, 1)
-DEFINE_GESTURE_EVENT_TYPE(SINGLE_TAP_UP, 2)
-DEFINE_GESTURE_EVENT_TYPE(SINGLE_TAP_CONFIRMED, 3)
-DEFINE_GESTURE_EVENT_TYPE(SINGLE_TAP_UNCONFIRMED, 4)
-DEFINE_GESTURE_EVENT_TYPE(LONG_PRESS, 5)
-DEFINE_GESTURE_EVENT_TYPE(SCROLL_START, 6)
-DEFINE_GESTURE_EVENT_TYPE(SCROLL_BY, 7)
-DEFINE_GESTURE_EVENT_TYPE(SCROLL_END, 8)
-DEFINE_GESTURE_EVENT_TYPE(FLING_START, 9)
-DEFINE_GESTURE_EVENT_TYPE(FLING_CANCEL, 10)
-DEFINE_GESTURE_EVENT_TYPE(FLING_END, 11)
-DEFINE_GESTURE_EVENT_TYPE(PINCH_BEGIN, 12)
-DEFINE_GESTURE_EVENT_TYPE(PINCH_BY, 13)
-DEFINE_GESTURE_EVENT_TYPE(PINCH_END, 14)
-DEFINE_GESTURE_EVENT_TYPE(TAP_CANCEL, 15)
-DEFINE_GESTURE_EVENT_TYPE(LONG_TAP, 16)
-DEFINE_GESTURE_EVENT_TYPE(TAP_DOWN, 17)
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
index c19173cd3cc..2bde4a45856 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
@@ -4,9 +4,12 @@
#include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
+#include "base/observer_list.h"
#include "content/browser/android/in_process/synchronous_compositor_output_surface.h"
#include "content/public/browser/browser_thread.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_surface_stub.h"
@@ -31,48 +34,55 @@ blink::WebGraphicsContext3D::Attributes GetDefaultAttribs() {
}
using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
+using webkit::gpu::WebGraphicsContext3DImpl;
scoped_ptr<gpu::GLInProcessContext> CreateOffscreenContext(
const blink::WebGraphicsContext3D::Attributes& attributes) {
const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
- gpu::GLInProcessContextAttribs in_process_attribs;
- WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
+ gpu::gles2::ContextCreationAttribHelper in_process_attribs;
+ WebGraphicsContext3DImpl::ConvertAttributes(
attributes, &in_process_attribs);
- in_process_attribs.lose_context_when_out_of_memory = 1;
-
- scoped_ptr<gpu::GLInProcessContext> context(
- gpu::GLInProcessContext::Create(NULL /* service */,
- NULL /* surface */,
- true /* is_offscreen */,
- gfx::kNullAcceleratedWidget,
- gfx::Size(1, 1),
- NULL /* share_context */,
- false /* share_resources */,
- in_process_attribs,
- gpu_preference));
+ in_process_attribs.lose_context_when_out_of_memory = true;
+
+ scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create(
+ NULL /* service */,
+ NULL /* surface */,
+ true /* is_offscreen */,
+ gfx::kNullAcceleratedWidget,
+ gfx::Size(1, 1),
+ NULL /* share_context */,
+ false /* share_resources */,
+ in_process_attribs,
+ gpu_preference,
+ gpu::GLInProcessContextSharedMemoryLimits(),
+ nullptr,
+ nullptr));
return context.Pass();
}
scoped_ptr<gpu::GLInProcessContext> CreateContext(
scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
- gpu::GLInProcessContext* share_context) {
+ const gpu::GLInProcessContextSharedMemoryLimits& mem_limits) {
const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
- gpu::GLInProcessContextAttribs in_process_attribs;
- WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
+ gpu::gles2::ContextCreationAttribHelper in_process_attribs;
+ WebGraphicsContext3DImpl::ConvertAttributes(
GetDefaultAttribs(), &in_process_attribs);
- in_process_attribs.lose_context_when_out_of_memory = 1;
-
- scoped_ptr<gpu::GLInProcessContext> context(
- gpu::GLInProcessContext::Create(service,
- NULL /* surface */,
- false /* is_offscreen */,
- gfx::kNullAcceleratedWidget,
- gfx::Size(1, 1),
- share_context,
- false /* share_resources */,
- in_process_attribs,
- gpu_preference));
+ in_process_attribs.lose_context_when_out_of_memory = true;
+
+ scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create(
+ service,
+ NULL /* surface */,
+ false /* is_offscreen */,
+ gfx::kNullAcceleratedWidget,
+ gfx::Size(1, 1),
+ NULL /* share_context */,
+ false /* share_resources */,
+ in_process_attribs,
+ gpu_preference,
+ mem_limits,
+ nullptr,
+ nullptr));
return context.Pass();
}
@@ -98,7 +108,9 @@ WrapContextWithAttributes(
context.Pass(), attributes));
}
-class VideoContextProvider
+} // namespace
+
+class SynchronousCompositorFactoryImpl::VideoContextProvider
: public StreamTextureFactorySynchronousImpl::ContextProvider {
public:
VideoContextProvider(
@@ -112,26 +124,40 @@ class VideoContextProvider
}
virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture(
- uint32 stream_id) OVERRIDE {
+ uint32 stream_id) override {
return gl_in_process_context_->GetSurfaceTexture(stream_id);
}
- virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE {
+ virtual gpu::gles2::GLES2Interface* ContextGL() override {
return context_provider_->ContextGL();
}
+ virtual void AddObserver(StreamTextureFactoryContextObserver* obs) override {
+ observer_list_.AddObserver(obs);
+ }
+
+ virtual void RemoveObserver(
+ StreamTextureFactoryContextObserver* obs) override {
+ observer_list_.RemoveObserver(obs);
+ }
+
+ void RestoreContext() {
+ FOR_EACH_OBSERVER(StreamTextureFactoryContextObserver,
+ observer_list_,
+ ResetStreamTextureProxy());
+ }
+
private:
friend class base::RefCountedThreadSafe<VideoContextProvider>;
virtual ~VideoContextProvider() {}
scoped_refptr<cc::ContextProvider> context_provider_;
gpu::GLInProcessContext* gl_in_process_context_;
+ ObserverList<StreamTextureFactoryContextObserver> observer_list_;
DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
};
-} // namespace
-
using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
@@ -153,10 +179,13 @@ SynchronousCompositorFactoryImpl::RecordFullLayer() {
}
scoped_ptr<cc::OutputSurface>
-SynchronousCompositorFactoryImpl::CreateOutputSurface(int routing_id) {
+SynchronousCompositorFactoryImpl::CreateOutputSurface(
+ int routing_id,
+ scoped_refptr<content::FrameSwapMessageQueue> frame_swap_message_queue) {
scoped_ptr<SynchronousCompositorOutputSurface> output_surface(
- new SynchronousCompositorOutputSurface(routing_id));
- return output_surface.PassAs<cc::OutputSurface>();
+ new SynchronousCompositorOutputSurface(routing_id,
+ frame_swap_message_queue));
+ return output_surface.Pass();
}
InputHandlerManagerClient*
@@ -164,43 +193,29 @@ SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
return synchronous_input_event_filter();
}
-scoped_refptr<ContextProviderWebContext> SynchronousCompositorFactoryImpl::
- GetSharedOffscreenContextProviderForMainThread() {
- bool failed = false;
- if ((!offscreen_context_for_main_thread_.get() ||
- offscreen_context_for_main_thread_->DestroyedOnMainThread())) {
- scoped_ptr<gpu::GLInProcessContext> context =
- CreateOffscreenContext(GetDefaultAttribs());
- offscreen_context_for_main_thread_ =
- webkit::gpu::ContextProviderInProcess::Create(
- WrapContext(context.Pass()),
- "Compositor-Offscreen-main-thread");
- failed = !offscreen_context_for_main_thread_.get() ||
- !offscreen_context_for_main_thread_->BindToCurrentThread();
- }
-
- if (failed) {
- offscreen_context_for_main_thread_ = NULL;
- }
- return offscreen_context_for_main_thread_;
+scoped_refptr<ContextProviderWebContext>
+SynchronousCompositorFactoryImpl::CreateOffscreenContextProvider(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ const std::string& debug_name) {
+ scoped_ptr<gpu::GLInProcessContext> context =
+ CreateOffscreenContext(attributes);
+ return webkit::gpu::ContextProviderInProcess::Create(
+ WrapContext(context.Pass()), debug_name);
}
scoped_refptr<cc::ContextProvider> SynchronousCompositorFactoryImpl::
CreateOnscreenContextProviderForCompositorThread() {
- DCHECK(service_);
+ DCHECK(service_.get());
- if (!share_context_.get())
- share_context_ = CreateContext(service_, NULL);
+ gpu::GLInProcessContextSharedMemoryLimits mem_limits;
+ // This is half of what RenderWidget uses because synchronous compositor
+ // pipeline is only one frame deep.
+ mem_limits.mapped_memory_reclaim_limit = 6 * 1024 * 1024;
return webkit::gpu::ContextProviderInProcess::Create(
- WrapContext(CreateContext(service_, share_context_.get())),
+ WrapContext(CreateContext(service_, mem_limits)),
"Child-Compositor");
}
-gpu::GLInProcessContext* SynchronousCompositorFactoryImpl::GetShareContext() {
- DCHECK(share_context_.get());
- return share_context_.get();
-}
-
scoped_refptr<StreamTextureFactory>
SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id) {
scoped_refptr<StreamTextureFactorySynchronousImpl> factory(
@@ -212,7 +227,7 @@ SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id) {
return factory;
}
-blink::WebGraphicsContext3D*
+webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl*
SynchronousCompositorFactoryImpl::CreateOffscreenGraphicsContext3D(
const blink::WebGraphicsContext3D::Attributes& attributes) {
return WrapContextWithAttributes(CreateOffscreenContext(attributes),
@@ -222,6 +237,13 @@ SynchronousCompositorFactoryImpl::CreateOffscreenGraphicsContext3D(
void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
base::AutoLock lock(num_hardware_compositor_lock_);
num_hardware_compositors_++;
+ if (num_hardware_compositors_ == 1 && main_thread_proxy_.get()) {
+ main_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &SynchronousCompositorFactoryImpl::RestoreContextOnMainThread,
+ base::Unretained(this)));
+ }
}
void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
@@ -230,6 +252,11 @@ void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
num_hardware_compositors_--;
}
+void SynchronousCompositorFactoryImpl::RestoreContextOnMainThread() {
+ if (CanCreateMainThreadContext() && video_context_provider_.get())
+ video_context_provider_->RestoreContext();
+}
+
bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
base::AutoLock lock(num_hardware_compositor_lock_);
return num_hardware_compositors_ > 0;
@@ -237,25 +264,33 @@ bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
- scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
- context_provider;
- // This check only guarantees the main thread context is created after
- // a compositor did successfully initialize hardware draw in the past.
- // In particular this does not guarantee that the main thread context
- // will fail creation when all compositors release hardware draw.
- if (CanCreateMainThreadContext() && !video_context_provider_) {
- DCHECK(service_);
- DCHECK(share_context_.get());
+ {
+ base::AutoLock lock(num_hardware_compositor_lock_);
+ main_thread_proxy_ = base::MessageLoopProxy::current();
+ }
+
+ // Always fail creation even if |video_context_provider_| is not NULL.
+ // This is to avoid synchronous calls that may deadlock. Setting
+ // |video_context_provider_| to null is also not safe since it makes
+ // synchronous destruction uncontrolled and possibly deadlock.
+ if (!CanCreateMainThreadContext()) {
+ return
+ scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>();
+ }
+
+ if (!video_context_provider_.get()) {
+ DCHECK(service_.get());
video_context_provider_ = new VideoContextProvider(
- CreateContext(service_, share_context_.get()));
+ CreateContext(service_,
+ gpu::GLInProcessContextSharedMemoryLimits()));
}
return video_context_provider_;
}
void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
- DCHECK(!service_);
+ DCHECK(!service_.get());
service_ = service;
}
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h
index ddaef409a3d..dd7467a5849 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h
@@ -31,18 +31,22 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
// SynchronousCompositorFactory
virtual scoped_refptr<base::MessageLoopProxy> GetCompositorMessageLoop()
- OVERRIDE;
- virtual bool RecordFullLayer() OVERRIDE;
- virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(int routing_id)
- OVERRIDE;
- virtual InputHandlerManagerClient* GetInputHandlerManagerClient() OVERRIDE;
+ override;
+ virtual bool RecordFullLayer() override;
+ virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
+ int routing_id,
+ scoped_refptr<content::FrameSwapMessageQueue> frame_swap_message_queue)
+ override;
+ virtual InputHandlerManagerClient* GetInputHandlerManagerClient() override;
virtual scoped_refptr<webkit::gpu::ContextProviderWebContext>
- GetSharedOffscreenContextProviderForMainThread() OVERRIDE;
+ CreateOffscreenContextProvider(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ const std::string& debug_name) override;
virtual scoped_refptr<StreamTextureFactory> CreateStreamTextureFactory(
- int view_id) OVERRIDE;
- virtual blink::WebGraphicsContext3D* CreateOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes) OVERRIDE;
-
+ int view_id) override;
+ virtual webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl*
+ CreateOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes) override;
SynchronousInputEventFilter* synchronous_input_event_filter() {
return &synchronous_input_event_filter_;
@@ -56,22 +60,19 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
scoped_refptr<cc::ContextProvider>
CreateOnscreenContextProviderForCompositorThread();
- gpu::GLInProcessContext* GetShareContext();
private:
bool CanCreateMainThreadContext();
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
TryCreateStreamTextureFactory();
+ void RestoreContextOnMainThread();
SynchronousInputEventFilter synchronous_input_event_filter_;
- scoped_refptr<webkit::gpu::ContextProviderWebContext>
- offscreen_context_for_main_thread_;
-
scoped_refptr<gpu::InProcessCommandBuffer::Service> service_;
- scoped_ptr<gpu::GLInProcessContext> share_context_;
- scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
- video_context_provider_;
+
+ class VideoContextProvider;
+ scoped_refptr<VideoContextProvider> video_context_provider_;
bool record_full_layer_;
@@ -79,6 +80,7 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
// read on renderer main thread.
base::Lock num_hardware_compositor_lock_;
unsigned int num_hardware_compositors_;
+ scoped_refptr<base::MessageLoopProxy> main_thread_proxy_;
};
} // namespace content
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc b/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
index 1b5ccb74ab5..06be5be5696 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -115,23 +115,26 @@ void SynchronousCompositorImpl::ReleaseHwDraw() {
g_factory.Get().CompositorReleasedHardwareDraw();
}
-gpu::GLInProcessContext* SynchronousCompositorImpl::GetShareContext() {
- DCHECK(CalledOnValidThread());
- return g_factory.Get().GetShareContext();
-}
-
scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
gfx::Size surface_size,
const gfx::Transform& transform,
gfx::Rect viewport,
- gfx::Rect clip) {
+ gfx::Rect clip,
+ gfx::Rect viewport_rect_for_tile_priority,
+ const gfx::Transform& transform_for_tile_priority) {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
scoped_ptr<cc::CompositorFrame> frame =
- output_surface_->DemandDrawHw(surface_size, transform, viewport, clip);
+ output_surface_->DemandDrawHw(surface_size,
+ transform,
+ viewport,
+ clip,
+ viewport_rect_for_tile_priority,
+ transform_for_tile_priority);
if (frame.get())
UpdateFrameMetaData(frame->metadata);
+
return frame.Pass();
}
@@ -157,14 +160,14 @@ void SynchronousCompositorImpl::UpdateFrameMetaData(
contents_->GetRenderWidgetHostView());
if (rwhv)
rwhv->SynchronousFrameMetadata(frame_metadata);
+ DeliverMessages();
}
-void SynchronousCompositorImpl::SetMemoryPolicy(
- const SynchronousCompositorMemoryPolicy& policy) {
+void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
- output_surface_->SetMemoryPolicy(policy);
+ output_surface_->SetMemoryPolicy(bytes_limit);
}
void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset() {
@@ -236,16 +239,31 @@ InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
contents_->GetRoutingID(), input_event);
}
+void SynchronousCompositorImpl::DeliverMessages() {
+ ScopedVector<IPC::Message> messages;
+ output_surface_->GetMessagesToDeliver(&messages);
+ RenderProcessHost* rph = contents_->GetRenderProcessHost();
+ for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
+ i != messages.end();
+ ++i) {
+ rph->OnMessageReceived(**i);
+ }
+}
+
void SynchronousCompositorImpl::DidActivatePendingTree() {
if (compositor_client_)
compositor_client_->DidUpdateContent();
}
-gfx::Vector2dF SynchronousCompositorImpl::GetTotalScrollOffset() {
+gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() {
DCHECK(CalledOnValidThread());
- if (compositor_client_)
- return compositor_client_->GetTotalRootLayerScrollOffset();
- return gfx::Vector2dF();
+ if (compositor_client_) {
+ // TODO(miletus): Make GetTotalRootLayerScrollOffset return
+ // ScrollOffset. crbug.com/414283.
+ return gfx::ScrollOffset(
+ compositor_client_->GetTotalRootLayerScrollOffset());
+ }
+ return gfx::ScrollOffset();
}
bool SynchronousCompositorImpl::IsExternalFlingActive() const {
@@ -256,8 +274,8 @@ bool SynchronousCompositorImpl::IsExternalFlingActive() const {
}
void SynchronousCompositorImpl::UpdateRootLayerState(
- const gfx::Vector2dF& total_scroll_offset,
- const gfx::Vector2dF& max_scroll_offset,
+ const gfx::ScrollOffset& total_scroll_offset,
+ const gfx::ScrollOffset& max_scroll_offset,
const gfx::SizeF& scrollable_size,
float page_scale_factor,
float min_page_scale_factor,
@@ -266,12 +284,14 @@ void SynchronousCompositorImpl::UpdateRootLayerState(
if (!compositor_client_)
return;
- compositor_client_->UpdateRootLayerState(total_scroll_offset,
- max_scroll_offset,
- scrollable_size,
- page_scale_factor,
- min_page_scale_factor,
- max_page_scale_factor);
+ // TODO(miletus): Pass in ScrollOffset. crbug.com/414283.
+ compositor_client_->UpdateRootLayerState(
+ gfx::ScrollOffsetToVector2dF(total_scroll_offset),
+ gfx::ScrollOffsetToVector2dF(max_scroll_offset),
+ scrollable_size,
+ page_scale_factor,
+ min_page_scale_factor,
+ max_page_scale_factor);
}
// Not using base::NonThreadSafe as we want to enforce a more exacting threading
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_impl.h b/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
index 6ac80cb92e6..9b92cef3781 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_IMPL_H_
#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_IMPL_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
@@ -13,6 +15,7 @@
#include "content/common/input/input_event_ack_state.h"
#include "content/public/browser/android/synchronous_compositor.h"
#include "content/public/browser/web_contents_user_data.h"
+#include "ipc/ipc_message.h"
namespace cc {
class InputHandler;
@@ -47,39 +50,40 @@ class SynchronousCompositorImpl
// SynchronousCompositor
virtual void SetClient(SynchronousCompositorClient* compositor_client)
- OVERRIDE;
- virtual bool InitializeHwDraw() OVERRIDE;
- virtual void ReleaseHwDraw() OVERRIDE;
- virtual gpu::GLInProcessContext* GetShareContext() OVERRIDE;
+ override;
+ virtual bool InitializeHwDraw() override;
+ virtual void ReleaseHwDraw() override;
virtual scoped_ptr<cc::CompositorFrame> DemandDrawHw(
gfx::Size surface_size,
const gfx::Transform& transform,
gfx::Rect viewport,
- gfx::Rect clip) OVERRIDE;
- virtual bool DemandDrawSw(SkCanvas* canvas) OVERRIDE;
+ gfx::Rect clip,
+ gfx::Rect viewport_rect_for_tile_priority,
+ const gfx::Transform& transform_for_tile_priority) override;
+ virtual bool DemandDrawSw(SkCanvas* canvas) override;
virtual void ReturnResources(
- const cc::CompositorFrameAck& frame_ack) OVERRIDE;
- virtual void SetMemoryPolicy(
- const SynchronousCompositorMemoryPolicy& policy) OVERRIDE;
- virtual void DidChangeRootLayerScrollOffset() OVERRIDE;
+ const cc::CompositorFrameAck& frame_ack) override;
+ virtual void SetMemoryPolicy(size_t bytes_limit) override;
+ virtual void DidChangeRootLayerScrollOffset() override;
// SynchronousCompositorOutputSurfaceDelegate
virtual void DidBindOutputSurface(
- SynchronousCompositorOutputSurface* output_surface) OVERRIDE;
+ SynchronousCompositorOutputSurface* output_surface) override;
virtual void DidDestroySynchronousOutputSurface(
- SynchronousCompositorOutputSurface* output_surface) OVERRIDE;
- virtual void SetContinuousInvalidate(bool enable) OVERRIDE;
- virtual void DidActivatePendingTree() OVERRIDE;
+ SynchronousCompositorOutputSurface* output_surface) override;
+ virtual void SetContinuousInvalidate(bool enable) override;
+ virtual void DidActivatePendingTree() override;
// LayerScrollOffsetDelegate
- virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE;
- virtual void UpdateRootLayerState(const gfx::Vector2dF& total_scroll_offset,
- const gfx::Vector2dF& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor) OVERRIDE;
- virtual bool IsExternalFlingActive() const OVERRIDE;
+ virtual gfx::ScrollOffset GetTotalScrollOffset() override;
+ virtual void UpdateRootLayerState(
+ const gfx::ScrollOffset& total_scroll_offset,
+ const gfx::ScrollOffset& max_scroll_offset,
+ const gfx::SizeF& scrollable_size,
+ float page_scale_factor,
+ float min_page_scale_factor,
+ float max_page_scale_factor) override;
+ virtual bool IsExternalFlingActive() const override;
void SetInputHandler(cc::InputHandler* input_handler);
void DidOverscroll(const DidOverscrollParams& params);
@@ -91,6 +95,7 @@ class SynchronousCompositorImpl
friend class WebContentsUserData<SynchronousCompositorImpl>;
void UpdateFrameMetaData(const cc::CompositorFrameMetadata& frame_info);
+ void DeliverMessages();
bool CalledOnValidThread() const;
SynchronousCompositorClient* compositor_client_;
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index 041de4ddfec..1c87cc34dac 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -14,6 +14,7 @@
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/public/browser/browser_thread.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -25,6 +26,9 @@ namespace content {
namespace {
+// Do not limit number of resources, so use an unrealistically high value.
+const size_t kNumResourcesLimit = 10 * 1000 * 1000;
+
void DidActivatePendingTree(int routing_id) {
SynchronousCompositorOutputSurfaceDelegate* delegate =
SynchronousCompositorImpl::FromRoutingID(routing_id);
@@ -41,10 +45,10 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
: surface_(surface) {
}
virtual void Resize(const gfx::Size& pixel_size,
- float scale_factor) OVERRIDE {
+ float scale_factor) override {
// Intentional no-op: canvas size is controlled by the embedder.
}
- virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE {
+ virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
if (!surface_->current_sw_canvas_) {
NOTREACHED() << "BeginPaint with no canvas set";
return &null_canvas_;
@@ -53,9 +57,9 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
<< "Mutliple calls to BeginPaint per frame";
return surface_->current_sw_canvas_;
}
- virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE {
+ virtual void EndPaint(cc::SoftwareFrameData* frame_data) override {
}
- virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE {
+ virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) override {
NOTIMPLEMENTED();
}
@@ -67,7 +71,8 @@ class SynchronousCompositorOutputSurface::SoftwareDevice
};
SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
- int routing_id)
+ int routing_id,
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
: cc::OutputSurface(
scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
routing_id_(routing_id),
@@ -75,7 +80,8 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
invoking_composite_(false),
current_sw_canvas_(NULL),
memory_policy_(0),
- output_surface_client_(NULL) {
+ output_surface_client_(NULL),
+ frame_swap_message_queue_(frame_swap_message_queue) {
capabilities_.deferred_gl_initialization = true;
capabilities_.draw_and_swap_full_viewport_every_frame = true;
capabilities_.adjust_deadline_for_parent = false;
@@ -95,14 +101,6 @@ SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {
delegate->DidDestroySynchronousOutputSurface(this);
}
-bool SynchronousCompositorOutputSurface::ForcedDrawToSoftwareDevice() const {
- // |current_sw_canvas_| indicates we're in a DemandDrawSw call. In addition
- // |invoking_composite_| == false indicates an attempt to draw outside of
- // the synchronous compositor's control: force it into SW path and hence to
- // the null canvas (and will log a warning there).
- return current_sw_canvas_ != NULL || !invoking_composite_;
-}
-
bool SynchronousCompositorOutputSurface::BindToClient(
cc::OutputSurfaceClient* surface_client) {
DCHECK(CalledOnValidThread());
@@ -155,7 +153,7 @@ bool SynchronousCompositorOutputSurface::InitializeHwDraw(
scoped_refptr<cc::ContextProvider> onscreen_context_provider) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
- DCHECK(!context_provider_);
+ DCHECK(!context_provider_.get());
return InitializeAndSetContext3d(onscreen_context_provider);
}
@@ -170,13 +168,20 @@ SynchronousCompositorOutputSurface::DemandDrawHw(
gfx::Size surface_size,
const gfx::Transform& transform,
gfx::Rect viewport,
- gfx::Rect clip) {
+ gfx::Rect clip,
+ gfx::Rect viewport_rect_for_tile_priority,
+ const gfx::Transform& transform_for_tile_priority) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
surface_size_ = surface_size;
- InvokeComposite(transform, viewport, clip, true);
+ InvokeComposite(transform,
+ viewport,
+ clip,
+ viewport_rect_for_tile_priority,
+ transform_for_tile_priority,
+ true);
return frame_holder_.Pass();
}
@@ -198,7 +203,15 @@ SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
surface_size_ = gfx::Size(canvas->getDeviceSize().width(),
canvas->getDeviceSize().height());
- InvokeComposite(transform, clip, clip, false);
+ // Pass in the cached hw viewport and transform for tile priority to avoid
+ // tile thrashing when the WebView is alternating between hardware and
+ // software draws.
+ InvokeComposite(transform,
+ clip,
+ clip,
+ cached_hw_viewport_rect_for_tile_priority_,
+ cached_hw_transform_for_tile_priority_,
+ false);
return frame_holder_.Pass();
}
@@ -207,28 +220,42 @@ void SynchronousCompositorOutputSurface::InvokeComposite(
const gfx::Transform& transform,
gfx::Rect viewport,
gfx::Rect clip,
- bool valid_for_tile_management) {
+ gfx::Rect viewport_rect_for_tile_priority,
+ gfx::Transform transform_for_tile_priority,
+ bool hardware_draw) {
DCHECK(!invoking_composite_);
DCHECK(!frame_holder_.get());
base::AutoReset<bool> invoking_composite_resetter(&invoking_composite_, true);
gfx::Transform adjusted_transform = transform;
AdjustTransform(&adjusted_transform, viewport);
- SetExternalDrawConstraints(
- adjusted_transform, viewport, clip, valid_for_tile_management);
+ SetExternalDrawConstraints(adjusted_transform,
+ viewport,
+ clip,
+ viewport_rect_for_tile_priority,
+ transform_for_tile_priority,
+ !hardware_draw);
SetNeedsRedrawRect(gfx::Rect(viewport.size()));
client_->BeginFrame(cc::BeginFrameArgs::CreateForSynchronousCompositor());
// After software draws (which might move the viewport arbitrarily), restore
// the previous hardware viewport to allow CC's tile manager to prioritize
// properly.
- if (valid_for_tile_management) {
+ if (hardware_draw) {
cached_hw_transform_ = adjusted_transform;
cached_hw_viewport_ = viewport;
cached_hw_clip_ = clip;
+ cached_hw_viewport_rect_for_tile_priority_ =
+ viewport_rect_for_tile_priority;
+ cached_hw_transform_for_tile_priority_ = transform_for_tile_priority;
} else {
- SetExternalDrawConstraints(
- cached_hw_transform_, cached_hw_viewport_, cached_hw_clip_, true);
+ bool resourceless_software_draw = false;
+ SetExternalDrawConstraints(cached_hw_transform_,
+ cached_hw_viewport_,
+ cached_hw_clip_,
+ cached_hw_viewport_rect_for_tile_priority_,
+ cached_hw_transform_for_tile_priority_,
+ resourceless_software_draw);
}
if (frame_holder_.get())
@@ -244,16 +271,23 @@ void SynchronousCompositorOutputSurface::ReturnResources(
ReclaimResources(&frame_ack);
}
-void SynchronousCompositorOutputSurface::SetMemoryPolicy(
- const SynchronousCompositorMemoryPolicy& policy) {
+void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
DCHECK(CalledOnValidThread());
- memory_policy_.bytes_limit_when_visible = policy.bytes_limit;
- memory_policy_.num_resources_limit = policy.num_resources_limit;
+ memory_policy_.bytes_limit_when_visible = bytes_limit;
+ memory_policy_.num_resources_limit = kNumResourcesLimit;
if (output_surface_client_)
output_surface_client_->SetMemoryPolicy(memory_policy_);
}
+void SynchronousCompositorOutputSurface::GetMessagesToDeliver(
+ ScopedVector<IPC::Message>* messages) {
+ DCHECK(CalledOnValidThread());
+ scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
+ frame_swap_message_queue_->AcquireSendMessageScope();
+ frame_swap_message_queue_->DrainMessages(messages);
+}
+
// Not using base::NonThreadSafe as we want to enforce a more exacting threading
// requirement: SynchronousCompositorOutputSurface() must only be used on the UI
// thread.
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h
index 3a456a433f0..d01d88b6b36 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_output_surface.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_
#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_OUTPUT_SURFACE_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
@@ -13,6 +15,7 @@
#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface.h"
#include "content/public/browser/android/synchronous_compositor.h"
+#include "ipc/ipc_message.h"
#include "ui/gfx/transform.h"
namespace cc {
@@ -20,8 +23,13 @@ class ContextProvider;
class CompositorFrameMetadata;
}
+namespace IPC {
+class Message;
+}
+
namespace content {
+class FrameSwapMessageQueue;
class SynchronousCompositorClient;
class SynchronousCompositorOutputSurface;
class WebGraphicsContext3DCommandBufferImpl;
@@ -51,27 +59,32 @@ class SynchronousCompositorOutputSurfaceDelegate {
class SynchronousCompositorOutputSurface
: NON_EXPORTED_BASE(public cc::OutputSurface) {
public:
- explicit SynchronousCompositorOutputSurface(int routing_id);
+ explicit SynchronousCompositorOutputSurface(
+ int routing_id,
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue);
virtual ~SynchronousCompositorOutputSurface();
// OutputSurface.
- virtual bool ForcedDrawToSoftwareDevice() const OVERRIDE;
- virtual bool BindToClient(cc::OutputSurfaceClient* surface_client) OVERRIDE;
- virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE;
- virtual void SetNeedsBeginFrame(bool enable) OVERRIDE;
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ virtual bool BindToClient(cc::OutputSurfaceClient* surface_client) override;
+ virtual void Reshape(const gfx::Size& size, float scale_factor) override;
+ virtual void SetNeedsBeginFrame(bool enable) override;
+ virtual void SwapBuffers(cc::CompositorFrame* frame) override;
// Partial SynchronousCompositor API implementation.
bool InitializeHwDraw(
scoped_refptr<cc::ContextProvider> onscreen_context_provider);
void ReleaseHwDraw();
- scoped_ptr<cc::CompositorFrame> DemandDrawHw(gfx::Size surface_size,
- const gfx::Transform& transform,
- gfx::Rect viewport,
- gfx::Rect clip);
+ scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+ gfx::Size surface_size,
+ const gfx::Transform& transform,
+ gfx::Rect viewport,
+ gfx::Rect clip,
+ gfx::Rect viewport_rect_for_tile_priority,
+ const gfx::Transform& transform_for_tile_priority);
void ReturnResources(const cc::CompositorFrameAck& frame_ack);
scoped_ptr<cc::CompositorFrame> DemandDrawSw(SkCanvas* canvas);
- void SetMemoryPolicy(const SynchronousCompositorMemoryPolicy& policy);
+ void SetMemoryPolicy(size_t bytes_limit);
+ void GetMessagesToDeliver(ScopedVector<IPC::Message>* messages);
private:
class SoftwareDevice;
@@ -80,7 +93,9 @@ class SynchronousCompositorOutputSurface
void InvokeComposite(const gfx::Transform& transform,
gfx::Rect viewport,
gfx::Rect clip,
- bool valid_for_tile_management);
+ gfx::Rect viewport_rect_for_tile_priority,
+ gfx::Transform transform_for_tile_priority,
+ bool hardware_draw);
bool CalledOnValidThread() const;
SynchronousCompositorOutputSurfaceDelegate* GetDelegate();
@@ -91,6 +106,8 @@ class SynchronousCompositorOutputSurface
gfx::Transform cached_hw_transform_;
gfx::Rect cached_hw_viewport_;
gfx::Rect cached_hw_clip_;
+ gfx::Rect cached_hw_viewport_rect_for_tile_priority_;
+ gfx::Transform cached_hw_transform_for_tile_priority_;
// Only valid (non-NULL) during a DemandDrawSw() call.
SkCanvas* current_sw_canvas_;
@@ -100,6 +117,8 @@ class SynchronousCompositorOutputSurface
cc::OutputSurfaceClient* output_surface_client_;
scoped_ptr<cc::CompositorFrame> frame_holder_;
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
+
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface);
};
diff --git a/chromium/content/browser/android/in_process/synchronous_input_event_filter.h b/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
index 3b81fa6f889..33200e8068e 100644
--- a/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
+++ b/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
@@ -32,13 +32,13 @@ class SynchronousInputEventFilter : public InputHandlerManagerClient {
const blink::WebInputEvent& input_event);
// InputHandlerManagerClient implementation.
- virtual void SetBoundHandler(const Handler& handler) OVERRIDE;
+ virtual void SetBoundHandler(const Handler& handler) override;
virtual void DidAddInputHandler(int routing_id,
- cc::InputHandler* input_handler) OVERRIDE;
- virtual void DidRemoveInputHandler(int routing_id) OVERRIDE;
+ cc::InputHandler* input_handler) override;
+ virtual void DidRemoveInputHandler(int routing_id) override;
virtual void DidOverscroll(int routing_id,
- const DidOverscrollParams& params) OVERRIDE;
- virtual void DidStopFlinging(int routing_id) OVERRIDE;
+ const DidOverscrollParams& params) override;
+ virtual void DidStopFlinging(int routing_id) override;
private:
void SetBoundHandlerOnUIThread(const Handler& handler);
diff --git a/chromium/content/browser/android/interstitial_page_delegate_android.h b/chromium/content/browser/android/interstitial_page_delegate_android.h
index 208717e8787..5121be161f5 100644
--- a/chromium/content/browser/android/interstitial_page_delegate_android.h
+++ b/chromium/content/browser/android/interstitial_page_delegate_android.h
@@ -35,10 +35,10 @@ class InterstitialPageDelegateAndroid : public InterstitialPageDelegate {
void DontProceed(JNIEnv* env, jobject obj);
// Implementation of InterstitialPageDelegate
- virtual std::string GetHTMLContents() OVERRIDE;
- virtual void OnProceed() OVERRIDE;
- virtual void OnDontProceed() OVERRIDE;
- virtual void CommandReceived(const std::string& command) OVERRIDE;
+ virtual std::string GetHTMLContents() override;
+ virtual void OnProceed() override;
+ virtual void OnDontProceed() override;
+ virtual void CommandReceived(const std::string& command) override;
static bool RegisterInterstitialPageDelegateAndroid(JNIEnv* env);
diff --git a/chromium/content/browser/android/java/DEPS b/chromium/content/browser/android/java/DEPS
new file mode 100644
index 00000000000..430199d518c
--- /dev/null
+++ b/chromium/content/browser/android/java/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+content/child", # For java bridge bindings
+]
diff --git a/chromium/content/browser/renderer_host/java/OWNERS b/chromium/content/browser/android/java/OWNERS
index 0cebb68c10c..0cebb68c10c 100644
--- a/chromium/content/browser/renderer_host/java/OWNERS
+++ b/chromium/content/browser/android/java/OWNERS
diff --git a/chromium/content/browser/android/java/gin_java_bound_object.cc b/chromium/content/browser/android/java/gin_java_bound_object.cc
new file mode 100644
index 00000000000..99c8b5d14e3
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_bound_object.cc
@@ -0,0 +1,192 @@
+// Copyright 2014 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 "content/browser/android/java/gin_java_bound_object.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/android/java/jni_helper.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+namespace {
+
+const char kJavaLangClass[] = "java/lang/Class";
+const char kJavaLangObject[] = "java/lang/Object";
+const char kJavaLangReflectMethod[] = "java/lang/reflect/Method";
+const char kGetClass[] = "getClass";
+const char kGetMethods[] = "getMethods";
+const char kIsAnnotationPresent[] = "isAnnotationPresent";
+const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
+const char kReturningJavaLangReflectMethodArray[] =
+ "()[Ljava/lang/reflect/Method;";
+const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z";
+
+} // namespace
+
+
+// static
+GinJavaBoundObject* GinJavaBoundObject::CreateNamed(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz) {
+ return new GinJavaBoundObject(ref, safe_annotation_clazz);
+}
+
+// static
+GinJavaBoundObject* GinJavaBoundObject::CreateTransient(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ RenderFrameHost* holder) {
+ std::set<RenderFrameHost*> holders;
+ holders.insert(holder);
+ return new GinJavaBoundObject(ref, safe_annotation_clazz, holders);
+}
+
+GinJavaBoundObject::GinJavaBoundObject(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz)
+ : ref_(ref),
+ names_count_(1),
+ object_get_class_method_id_(NULL),
+ are_methods_set_up_(false),
+ safe_annotation_clazz_(safe_annotation_clazz) {
+}
+
+GinJavaBoundObject::GinJavaBoundObject(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ const std::set<RenderFrameHost*> holders)
+ : ref_(ref),
+ names_count_(0),
+ holders_(holders),
+ object_get_class_method_id_(NULL),
+ are_methods_set_up_(false),
+ safe_annotation_clazz_(safe_annotation_clazz) {
+}
+
+GinJavaBoundObject::~GinJavaBoundObject() {
+}
+
+std::set<std::string> GinJavaBoundObject::GetMethodNames() {
+ EnsureMethodsAreSetUp();
+ std::set<std::string> result;
+ for (JavaMethodMap::const_iterator it = methods_.begin();
+ it != methods_.end();
+ ++it) {
+ result.insert(it->first);
+ }
+ return result;
+}
+
+bool GinJavaBoundObject::HasMethod(const std::string& method_name) {
+ EnsureMethodsAreSetUp();
+ return methods_.find(method_name) != methods_.end();
+}
+
+const JavaMethod* GinJavaBoundObject::FindMethod(
+ const std::string& method_name,
+ size_t num_parameters) {
+ EnsureMethodsAreSetUp();
+
+ // Get all methods with the correct name.
+ std::pair<JavaMethodMap::const_iterator, JavaMethodMap::const_iterator>
+ iters = methods_.equal_range(method_name);
+ if (iters.first == iters.second) {
+ return NULL;
+ }
+
+ // LIVECONNECT_COMPLIANCE: We just take the first method with the correct
+ // number of arguments, while the spec proposes using cost-based algorithm:
+ // https://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
+ for (JavaMethodMap::const_iterator iter = iters.first; iter != iters.second;
+ ++iter) {
+ if (iter->second->num_parameters() == num_parameters) {
+ return iter->second.get();
+ }
+ }
+
+ return NULL;
+}
+
+bool GinJavaBoundObject::IsObjectGetClassMethod(const JavaMethod* method) {
+ EnsureMethodsAreSetUp();
+ // As java.lang.Object.getClass is declared to be final, it is sufficient to
+ // compare methodIDs.
+ return method->id() == object_get_class_method_id_;
+}
+
+const base::android::JavaRef<jclass>&
+GinJavaBoundObject::GetSafeAnnotationClass() {
+ return safe_annotation_clazz_;
+}
+
+base::android::ScopedJavaLocalRef<jclass> GinJavaBoundObject::GetLocalClassRef(
+ JNIEnv* env) {
+ if (!object_get_class_method_id_) {
+ object_get_class_method_id_ = GetMethodIDFromClassName(
+ env, kJavaLangObject, kGetClass, kReturningJavaLangClass);
+ }
+ ScopedJavaLocalRef<jobject> obj = GetLocalRef(env);
+ if (obj.obj()) {
+ return base::android::ScopedJavaLocalRef<jclass>(
+ env,
+ static_cast<jclass>(
+ env->CallObjectMethod(obj.obj(), object_get_class_method_id_)));
+ } else {
+ return base::android::ScopedJavaLocalRef<jclass>();
+ }
+}
+
+void GinJavaBoundObject::EnsureMethodsAreSetUp() {
+ if (are_methods_set_up_)
+ return;
+ are_methods_set_up_ = true;
+
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jclass> clazz = GetLocalClassRef(env);
+ if (clazz.is_null()) {
+ return;
+ }
+
+ ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>(
+ env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangClass,
+ kGetMethods,
+ kReturningJavaLangReflectMethodArray))));
+
+ size_t num_methods = env->GetArrayLength(methods.obj());
+ // Java objects always have public methods.
+ DCHECK(num_methods);
+
+ for (size_t i = 0; i < num_methods; ++i) {
+ ScopedJavaLocalRef<jobject> java_method(
+ env,
+ env->GetObjectArrayElement(methods.obj(), i));
+
+ if (!safe_annotation_clazz_.is_null()) {
+ jboolean safe = env->CallBooleanMethod(java_method.obj(),
+ GetMethodIDFromClassName(
+ env,
+ kJavaLangReflectMethod,
+ kIsAnnotationPresent,
+ kTakesJavaLangClassReturningBoolean),
+ safe_annotation_clazz_.obj());
+
+ if (!safe)
+ continue;
+ }
+
+ JavaMethod* method = new JavaMethod(java_method);
+ methods_.insert(std::make_pair(method->name(), make_linked_ptr(method)));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/gin_java_bound_object.h b/chromium/content/browser/android/java/gin_java_bound_object.h
new file mode 100644
index 00000000000..ce1d403e7f6
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_bound_object.h
@@ -0,0 +1,96 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_H_
+
+#include <map>
+#include <set>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/id_map.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "content/browser/android/java/java_method.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+class GinJavaBoundObject
+ : public base::RefCountedThreadSafe<GinJavaBoundObject> {
+ public:
+ // Using scoped_refptr<> as a value type is somewhat not IDMap had been
+ // designed for (it returns T* from lookups, so we have to de-ref it), but on
+ // the other hand, this allows us to manage lifetime of GinJavaBoundObject
+ // automatically.
+ typedef IDMap<scoped_refptr<GinJavaBoundObject>, IDMapOwnPointer> ObjectMap;
+ typedef ObjectMap::KeyType ObjectID;
+
+ static GinJavaBoundObject* CreateNamed(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz);
+ static GinJavaBoundObject* CreateTransient(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ RenderFrameHost* holder);
+
+ JavaObjectWeakGlobalRef& GetWeakRef() { return ref_; }
+ base::android::ScopedJavaLocalRef<jobject> GetLocalRef(JNIEnv* env) {
+ return ref_.get(env);
+ }
+
+ bool IsNamed() { return names_count_ > 0; }
+ void AddName() { ++names_count_; }
+ void RemoveName() { --names_count_; }
+
+ bool HasHolders() { return !holders_.empty(); }
+ void AddHolder(RenderFrameHost* holder) { holders_.insert(holder); }
+ void RemoveHolder(RenderFrameHost* holder) { holders_.erase(holder); }
+
+ // The following methods are called on the background thread.
+ std::set<std::string> GetMethodNames();
+ bool HasMethod(const std::string& method_name);
+ const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters);
+ bool IsObjectGetClassMethod(const JavaMethod* method);
+ const base::android::JavaRef<jclass>& GetSafeAnnotationClass();
+ base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(JNIEnv* env);
+
+ private:
+ friend class base::RefCountedThreadSafe<GinJavaBoundObject>;
+
+ GinJavaBoundObject(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz);
+ GinJavaBoundObject(
+ const JavaObjectWeakGlobalRef& ref,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ const std::set<RenderFrameHost*> holders);
+ ~GinJavaBoundObject();
+
+ // The following methods are called on the background thread.
+ void EnsureMethodsAreSetUp();
+
+ JavaObjectWeakGlobalRef ref_;
+
+ // An object must be kept in retained_object_set_ either if it has
+ // names or if it has a non-empty holders set.
+ int names_count_;
+ std::set<RenderFrameHost*> holders_;
+
+ // The following fields are accessed on the background thread.
+ typedef std::multimap<std::string, linked_ptr<JavaMethod> > JavaMethodMap;
+ JavaMethodMap methods_;
+ jmethodID object_get_class_method_id_;
+ bool are_methods_set_up_;
+ base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_H_
diff --git a/chromium/content/browser/android/java/gin_java_bound_object_delegate.cc b/chromium/content/browser/android/java/gin_java_bound_object_delegate.cc
new file mode 100644
index 00000000000..bf964d7592f
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_bound_object_delegate.cc
@@ -0,0 +1,43 @@
+// Copyright 2014 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 "content/browser/android/java/gin_java_bound_object_delegate.h"
+
+namespace content {
+
+GinJavaBoundObjectDelegate::GinJavaBoundObjectDelegate(
+ scoped_refptr<GinJavaBoundObject> object)
+ : object_(object) {
+}
+
+GinJavaBoundObjectDelegate::~GinJavaBoundObjectDelegate() {
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+GinJavaBoundObjectDelegate::GetLocalRef(JNIEnv* env) {
+ return object_->GetLocalRef(env);
+}
+
+base::android::ScopedJavaLocalRef<jclass>
+GinJavaBoundObjectDelegate::GetLocalClassRef(JNIEnv* env) {
+ return object_->GetLocalClassRef(env);
+}
+
+const JavaMethod* GinJavaBoundObjectDelegate::FindMethod(
+ const std::string& method_name,
+ size_t num_parameters) {
+ return object_->FindMethod(method_name, num_parameters);
+}
+
+bool GinJavaBoundObjectDelegate::IsObjectGetClassMethod(
+ const JavaMethod* method) {
+ return object_->IsObjectGetClassMethod(method);
+}
+
+const base::android::JavaRef<jclass>&
+GinJavaBoundObjectDelegate::GetSafeAnnotationClass() {
+ return object_->GetSafeAnnotationClass();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/gin_java_bound_object_delegate.h b/chromium/content/browser/android/java/gin_java_bound_object_delegate.h
new file mode 100644
index 00000000000..49ff4bbca4f
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_bound_object_delegate.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_DELEGATE_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_DELEGATE_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/browser/android/java/gin_java_bound_object.h"
+#include "content/browser/android/java/gin_java_method_invocation_helper.h"
+
+namespace content {
+
+class GinJavaBoundObjectDelegate
+ : public GinJavaMethodInvocationHelper::ObjectDelegate {
+ public:
+ GinJavaBoundObjectDelegate(scoped_refptr<GinJavaBoundObject> object);
+ virtual ~GinJavaBoundObjectDelegate();
+
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
+ JNIEnv* env) override;
+ virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
+ JNIEnv* env) override;
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) override;
+ virtual bool IsObjectGetClassMethod(const JavaMethod* method) override;
+ virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass()
+ override;
+
+ private:
+ scoped_refptr<GinJavaBoundObject> object_;
+
+ DISALLOW_COPY_AND_ASSIGN(GinJavaBoundObjectDelegate);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BOUND_OBJECT_DELEGATE_H_
diff --git a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
new file mode 100644
index 00000000000..c8fb2fd9899
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -0,0 +1,564 @@
+// Copyright 2014 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 "content/browser/android/java/gin_java_bridge_dispatcher_host.h"
+
+#include "base/android/java_handler_thread.h"
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/lazy_instance.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_runner_util.h"
+#include "content/browser/android/java/gin_java_bound_object_delegate.h"
+#include "content/browser/android/java/jni_helper.h"
+#include "content/common/android/gin_java_bridge_value.h"
+#include "content/common/android/hash_set.h"
+#include "content/common/gin_java_bridge_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "ipc/ipc_message_utils.h"
+
+#if !defined(OS_ANDROID)
+#error "JavaBridge only supports OS_ANDROID"
+#endif
+
+namespace content {
+
+namespace {
+// The JavaBridge needs to use a Java thread so the callback
+// will happen on a thread with a prepared Looper.
+class JavaBridgeThread : public base::android::JavaHandlerThread {
+ public:
+ JavaBridgeThread() : base::android::JavaHandlerThread("JavaBridge") {
+ Start();
+ }
+ virtual ~JavaBridgeThread() {
+ Stop();
+ }
+};
+
+base::LazyInstance<JavaBridgeThread> g_background_thread =
+ LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+GinJavaBridgeDispatcherHost::GinJavaBridgeDispatcherHost(
+ WebContents* web_contents,
+ jobject retained_object_set)
+ : WebContentsObserver(web_contents),
+ retained_object_set_(base::android::AttachCurrentThread(),
+ retained_object_set),
+ allow_object_contents_inspection_(true) {
+ DCHECK(retained_object_set);
+}
+
+GinJavaBridgeDispatcherHost::~GinJavaBridgeDispatcherHost() {
+ DCHECK(pending_replies_.empty());
+}
+
+void GinJavaBridgeDispatcherHost::RenderFrameCreated(
+ RenderFrameHost* render_frame_host) {
+ for (NamedObjectMap::const_iterator iter = named_objects_.begin();
+ iter != named_objects_.end();
+ ++iter) {
+ render_frame_host->Send(new GinJavaBridgeMsg_AddNamedObject(
+ render_frame_host->GetRoutingID(), iter->first, iter->second));
+ }
+}
+
+void GinJavaBridgeDispatcherHost::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ IPC::Message* reply_msg = TakePendingReply(render_frame_host);
+ if (reply_msg != NULL) {
+ base::ListValue result;
+ result.Append(base::Value::CreateNullValue());
+ IPC::WriteParam(reply_msg, result);
+ IPC::WriteParam(reply_msg, kGinJavaBridgeRenderFrameDeleted);
+ render_frame_host->Send(reply_msg);
+ }
+ RemoveHolder(render_frame_host,
+ GinJavaBoundObject::ObjectMap::iterator(&objects_),
+ objects_.size());
+}
+
+GinJavaBoundObject::ObjectID GinJavaBridgeDispatcherHost::AddObject(
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ bool is_named,
+ RenderFrameHost* holder) {
+ DCHECK(is_named || holder);
+ GinJavaBoundObject::ObjectID object_id;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ JavaObjectWeakGlobalRef ref(env, object.obj());
+ if (is_named) {
+ object_id = objects_.Add(new scoped_refptr<GinJavaBoundObject>(
+ GinJavaBoundObject::CreateNamed(ref, safe_annotation_clazz)));
+ } else {
+ object_id = objects_.Add(new scoped_refptr<GinJavaBoundObject>(
+ GinJavaBoundObject::CreateTransient(
+ ref, safe_annotation_clazz, holder)));
+ }
+#if DCHECK_IS_ON
+ {
+ GinJavaBoundObject::ObjectID added_object_id;
+ DCHECK(FindObjectId(object, &added_object_id));
+ DCHECK_EQ(object_id, added_object_id);
+ }
+#endif // DCHECK_IS_ON
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_add(env, retained_object_set, object);
+ }
+ return object_id;
+}
+
+bool GinJavaBridgeDispatcherHost::FindObjectId(
+ const base::android::JavaRef<jobject>& object,
+ GinJavaBoundObject::ObjectID* object_id) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ for (GinJavaBoundObject::ObjectMap::iterator it(&objects_); !it.IsAtEnd();
+ it.Advance()) {
+ if (env->IsSameObject(
+ object.obj(),
+ it.GetCurrentValue()->get()->GetLocalRef(env).obj())) {
+ *object_id = it.GetCurrentKey();
+ return true;
+ }
+ }
+ return false;
+}
+
+JavaObjectWeakGlobalRef GinJavaBridgeDispatcherHost::GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) {
+ scoped_refptr<GinJavaBoundObject>* result = objects_.Lookup(object_id);
+ scoped_refptr<GinJavaBoundObject> object(result ? *result : NULL);
+ if (object.get())
+ return object->GetWeakRef();
+ else
+ return JavaObjectWeakGlobalRef();
+}
+
+void GinJavaBridgeDispatcherHost::RemoveHolder(
+ RenderFrameHost* holder,
+ const GinJavaBoundObject::ObjectMap::iterator& from,
+ size_t count) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ size_t i = 0;
+ for (GinJavaBoundObject::ObjectMap::iterator it(from);
+ !it.IsAtEnd() && i < count;
+ it.Advance(), ++i) {
+ scoped_refptr<GinJavaBoundObject> object(*it.GetCurrentValue());
+ if (object->IsNamed())
+ continue;
+ object->RemoveHolder(holder);
+ if (!object->HasHolders()) {
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_remove(
+ env, retained_object_set, object->GetLocalRef(env));
+ }
+ objects_.Remove(it.GetCurrentKey());
+ }
+ }
+}
+
+void GinJavaBridgeDispatcherHost::AddNamedObject(
+ const std::string& name,
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ GinJavaBoundObject::ObjectID object_id;
+ NamedObjectMap::iterator iter = named_objects_.find(name);
+ bool existing_object = FindObjectId(object, &object_id);
+ if (existing_object && iter != named_objects_.end() &&
+ iter->second == object_id) {
+ // Nothing to do.
+ return;
+ }
+ if (iter != named_objects_.end()) {
+ RemoveNamedObject(iter->first);
+ }
+ if (existing_object) {
+ (*objects_.Lookup(object_id))->AddName();
+ } else {
+ object_id = AddObject(object, safe_annotation_clazz, true, NULL);
+ }
+ named_objects_[name] = object_id;
+
+ web_contents()->SendToAllFrames(
+ new GinJavaBridgeMsg_AddNamedObject(MSG_ROUTING_NONE, name, object_id));
+}
+
+void GinJavaBridgeDispatcherHost::RemoveNamedObject(
+ const std::string& name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NamedObjectMap::iterator iter = named_objects_.find(name);
+ if (iter == named_objects_.end())
+ return;
+
+ // |name| may come from |named_objects_|. Make a copy of name so that if
+ // |name| is from |named_objects_| it'll be valid after the remove below.
+ const std::string copied_name(name);
+
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(iter->second));
+ named_objects_.erase(iter);
+ object->RemoveName();
+
+ // As the object isn't going to be removed from the JavaScript side until the
+ // next page reload, calls to it must still work, thus we should continue to
+ // hold it. All the transient objects and removed named objects will be purged
+ // during the cleansing caused by DocumentAvailableInMainFrame event.
+
+ web_contents()->SendToAllFrames(
+ new GinJavaBridgeMsg_RemoveNamedObject(MSG_ROUTING_NONE, copied_name));
+}
+
+void GinJavaBridgeDispatcherHost::SetAllowObjectContentsInspection(bool allow) {
+ allow_object_contents_inspection_ = allow;
+}
+
+void GinJavaBridgeDispatcherHost::DocumentAvailableInMainFrame() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Called when the window object has been cleared in the main frame.
+ // That means, all sub-frames have also been cleared, so only named
+ // objects survived.
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> retained_object_set =
+ retained_object_set_.get(env);
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_clear(env, retained_object_set);
+ }
+
+ // We also need to add back the named objects we have so far as they
+ // should survive navigations.
+ for (GinJavaBoundObject::ObjectMap::iterator it(&objects_); !it.IsAtEnd();
+ it.Advance()) {
+ scoped_refptr<GinJavaBoundObject> object(*it.GetCurrentValue());
+ if (object->IsNamed()) {
+ if (!retained_object_set.is_null()) {
+ JNI_Java_HashSet_add(
+ env, retained_object_set, object->GetLocalRef(env));
+ }
+ } else {
+ objects_.Remove(it.GetCurrentKey());
+ }
+ }
+}
+
+namespace {
+
+// TODO(mnaganov): Implement passing of a parameter into sync message handlers.
+class MessageForwarder : public IPC::Sender {
+ public:
+ MessageForwarder(GinJavaBridgeDispatcherHost* gjbdh,
+ RenderFrameHost* render_frame_host)
+ : gjbdh_(gjbdh), render_frame_host_(render_frame_host) {}
+ void OnGetMethods(GinJavaBoundObject::ObjectID object_id,
+ IPC::Message* reply_msg) {
+ gjbdh_->OnGetMethods(render_frame_host_,
+ object_id,
+ reply_msg);
+ }
+ void OnHasMethod(GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ IPC::Message* reply_msg) {
+ gjbdh_->OnHasMethod(render_frame_host_,
+ object_id,
+ method_name,
+ reply_msg);
+ }
+ void OnInvokeMethod(GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ const base::ListValue& arguments,
+ IPC::Message* reply_msg) {
+ gjbdh_->OnInvokeMethod(render_frame_host_,
+ object_id,
+ method_name,
+ arguments,
+ reply_msg);
+ }
+ virtual bool Send(IPC::Message* msg) override {
+ NOTREACHED();
+ return false;
+ }
+ private:
+ GinJavaBridgeDispatcherHost* gjbdh_;
+ RenderFrameHost* render_frame_host_;
+};
+
+}
+
+bool GinJavaBridgeDispatcherHost::OnMessageReceived(
+ const IPC::Message& message,
+ RenderFrameHost* render_frame_host) {
+ DCHECK(render_frame_host);
+ bool handled = true;
+ MessageForwarder forwarder(this, render_frame_host);
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(GinJavaBridgeDispatcherHost, message,
+ render_frame_host)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_GetMethods,
+ &forwarder,
+ MessageForwarder::OnGetMethods)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_HasMethod,
+ &forwarder,
+ MessageForwarder::OnHasMethod)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(GinJavaBridgeHostMsg_InvokeMethod,
+ &forwarder,
+ MessageForwarder::OnInvokeMethod)
+ IPC_MESSAGE_HANDLER(GinJavaBridgeHostMsg_ObjectWrapperDeleted,
+ OnObjectWrapperDeleted)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+namespace {
+
+class IsValidRenderFrameHostHelper
+ : public base::RefCounted<IsValidRenderFrameHostHelper> {
+ public:
+ explicit IsValidRenderFrameHostHelper(RenderFrameHost* rfh_to_match)
+ : rfh_to_match_(rfh_to_match), rfh_found_(false) {}
+
+ bool rfh_found() { return rfh_found_; }
+
+ void OnFrame(RenderFrameHost* rfh) {
+ if (rfh_to_match_ == rfh) rfh_found_ = true;
+ }
+
+ private:
+ friend class base::RefCounted<IsValidRenderFrameHostHelper>;
+
+ ~IsValidRenderFrameHostHelper() {}
+
+ RenderFrameHost* rfh_to_match_;
+ bool rfh_found_;
+
+ DISALLOW_COPY_AND_ASSIGN(IsValidRenderFrameHostHelper);
+};
+
+} // namespace
+
+bool GinJavaBridgeDispatcherHost::IsValidRenderFrameHost(
+ RenderFrameHost* render_frame_host) {
+ scoped_refptr<IsValidRenderFrameHostHelper> helper =
+ new IsValidRenderFrameHostHelper(render_frame_host);
+ web_contents()->ForEachFrame(
+ base::Bind(&IsValidRenderFrameHostHelper::OnFrame, helper));
+ return helper->rfh_found();
+}
+
+void GinJavaBridgeDispatcherHost::OnGetMethods(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ if (!allow_object_contents_inspection_) {
+ IPC::WriteParam(reply_msg, std::set<std::string>());
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+ if (!object.get()) {
+ LOG(ERROR) << "WebView: Unknown object: " << object_id;
+ IPC::WriteParam(reply_msg, std::set<std::string>());
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ DCHECK(!HasPendingReply(render_frame_host));
+ pending_replies_[render_frame_host] = reply_msg;
+ base::PostTaskAndReplyWithResult(
+ g_background_thread.Get().message_loop()->message_loop_proxy().get(),
+ FROM_HERE,
+ base::Bind(&GinJavaBoundObject::GetMethodNames, object),
+ base::Bind(&GinJavaBridgeDispatcherHost::SendMethods,
+ AsWeakPtr(),
+ render_frame_host));
+}
+
+void GinJavaBridgeDispatcherHost::SendMethods(
+ RenderFrameHost* render_frame_host,
+ const std::set<std::string>& method_names) {
+ IPC::Message* reply_msg = TakePendingReply(render_frame_host);
+ if (!reply_msg) {
+ return;
+ }
+ IPC::WriteParam(reply_msg, method_names);
+ render_frame_host->Send(reply_msg);
+}
+
+void GinJavaBridgeDispatcherHost::OnHasMethod(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+ if (!object.get()) {
+ LOG(ERROR) << "WebView: Unknown object: " << object_id;
+ IPC::WriteParam(reply_msg, false);
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ DCHECK(!HasPendingReply(render_frame_host));
+ pending_replies_[render_frame_host] = reply_msg;
+ base::PostTaskAndReplyWithResult(
+ g_background_thread.Get().message_loop()->message_loop_proxy().get(),
+ FROM_HERE,
+ base::Bind(&GinJavaBoundObject::HasMethod, object, method_name),
+ base::Bind(&GinJavaBridgeDispatcherHost::SendHasMethodReply,
+ AsWeakPtr(),
+ render_frame_host));
+}
+
+void GinJavaBridgeDispatcherHost::SendHasMethodReply(
+ RenderFrameHost* render_frame_host,
+ bool result) {
+ IPC::Message* reply_msg = TakePendingReply(render_frame_host);
+ if (!reply_msg) {
+ return;
+ }
+ IPC::WriteParam(reply_msg, result);
+ render_frame_host->Send(reply_msg);
+}
+
+void GinJavaBridgeDispatcherHost::OnInvokeMethod(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ const base::ListValue& arguments,
+ IPC::Message* reply_msg) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ scoped_refptr<GinJavaBoundObject> object(*objects_.Lookup(object_id));
+ if (!object.get()) {
+ LOG(ERROR) << "WebView: Unknown object: " << object_id;
+ base::ListValue result;
+ result.Append(base::Value::CreateNullValue());
+ IPC::WriteParam(reply_msg, result);
+ IPC::WriteParam(reply_msg, kGinJavaBridgeUnknownObjectId);
+ render_frame_host->Send(reply_msg);
+ return;
+ }
+ DCHECK(!HasPendingReply(render_frame_host));
+ pending_replies_[render_frame_host] = reply_msg;
+ scoped_refptr<GinJavaMethodInvocationHelper> result =
+ new GinJavaMethodInvocationHelper(
+ make_scoped_ptr(new GinJavaBoundObjectDelegate(object)),
+ method_name,
+ arguments);
+ result->Init(this);
+ g_background_thread.Get()
+ .message_loop()
+ ->message_loop_proxy()
+ ->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GinJavaMethodInvocationHelper::Invoke, result),
+ base::Bind(
+ &GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult,
+ AsWeakPtr(),
+ render_frame_host,
+ result));
+}
+
+void GinJavaBridgeDispatcherHost::ProcessMethodInvocationResult(
+ RenderFrameHost* render_frame_host,
+ scoped_refptr<GinJavaMethodInvocationHelper> result) {
+ if (result->HoldsPrimitiveResult()) {
+ IPC::Message* reply_msg = TakePendingReply(render_frame_host);
+ if (!reply_msg) {
+ return;
+ }
+ IPC::WriteParam(reply_msg, result->GetPrimitiveResult());
+ IPC::WriteParam(reply_msg, result->GetInvocationError());
+ render_frame_host->Send(reply_msg);
+ } else {
+ ProcessMethodInvocationObjectResult(render_frame_host, result);
+ }
+}
+
+void GinJavaBridgeDispatcherHost::ProcessMethodInvocationObjectResult(
+ RenderFrameHost* render_frame_host,
+ scoped_refptr<GinJavaMethodInvocationHelper> result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!IsValidRenderFrameHost(render_frame_host)) {
+ // In this case, we must've already sent the reply when the render frame
+ // was destroyed.
+ DCHECK(!HasPendingReply(render_frame_host));
+ return;
+ }
+
+ base::ListValue wrapped_result;
+ if (!result->GetObjectResult().is_null()) {
+ GinJavaBoundObject::ObjectID returned_object_id;
+ if (FindObjectId(result->GetObjectResult(), &returned_object_id)) {
+ (*objects_.Lookup(returned_object_id))->AddHolder(render_frame_host);
+ } else {
+ returned_object_id = AddObject(result->GetObjectResult(),
+ result->GetSafeAnnotationClass(),
+ false,
+ render_frame_host);
+ }
+ wrapped_result.Append(
+ GinJavaBridgeValue::CreateObjectIDValue(
+ returned_object_id).release());
+ } else {
+ wrapped_result.Append(base::Value::CreateNullValue());
+ }
+ IPC::Message* reply_msg = TakePendingReply(render_frame_host);
+ if (!reply_msg) {
+ return;
+ }
+ IPC::WriteParam(reply_msg, wrapped_result);
+ IPC::WriteParam(reply_msg, result->GetInvocationError());
+ render_frame_host->Send(reply_msg);
+}
+
+void GinJavaBridgeDispatcherHost::OnObjectWrapperDeleted(
+ RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(render_frame_host);
+ if (objects_.Lookup(object_id)) {
+ GinJavaBoundObject::ObjectMap::iterator iter(&objects_);
+ while (!iter.IsAtEnd() && iter.GetCurrentKey() != object_id)
+ iter.Advance();
+ DCHECK(!iter.IsAtEnd());
+ RemoveHolder(render_frame_host, iter, 1);
+ }
+}
+
+IPC::Message* GinJavaBridgeDispatcherHost::TakePendingReply(
+ RenderFrameHost* render_frame_host) {
+ if (!IsValidRenderFrameHost(render_frame_host)) {
+ DCHECK(!HasPendingReply(render_frame_host));
+ return NULL;
+ }
+
+ PendingReplyMap::iterator it = pending_replies_.find(render_frame_host);
+ // There may be no pending reply if we're called from RenderFrameDeleted and
+ // we already sent the reply through the regular route.
+ if (it == pending_replies_.end()) {
+ return NULL;
+ }
+
+ IPC::Message* reply_msg = it->second;
+ pending_replies_.erase(it);
+ return reply_msg;
+}
+
+bool GinJavaBridgeDispatcherHost::HasPendingReply(
+ RenderFrameHost* render_frame_host) const {
+ return pending_replies_.find(render_frame_host) != pending_replies_.end();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
new file mode 100644
index 00000000000..c57ba260f1e
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_bridge_dispatcher_host.h
@@ -0,0 +1,126 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
+
+#include <map>
+#include <set>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/android/java/gin_java_bound_object.h"
+#include "content/browser/android/java/gin_java_method_invocation_helper.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+
+// This class handles injecting Java objects into a single RenderView. The Java
+// object itself lives in the browser process on a background thread, while a
+// proxy object is created in the renderer. An instance of this class exists
+// for each RenderFrameHost.
+class GinJavaBridgeDispatcherHost
+ : public base::SupportsWeakPtr<GinJavaBridgeDispatcherHost>,
+ public WebContentsObserver,
+ public GinJavaMethodInvocationHelper::DispatcherDelegate {
+ public:
+
+ GinJavaBridgeDispatcherHost(WebContents* web_contents,
+ jobject retained_object_set);
+ virtual ~GinJavaBridgeDispatcherHost();
+
+ void AddNamedObject(
+ const std::string& name,
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz);
+ void RemoveNamedObject(const std::string& name);
+ void SetAllowObjectContentsInspection(bool allow);
+
+ // WebContentsObserver
+ virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
+ virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+ virtual void DocumentAvailableInMainFrame() override;
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) override;
+
+ // GinJavaMethodInvocationHelper::DispatcherDelegate
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) override;
+
+ void OnGetMethods(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ IPC::Message* reply_msg);
+ void OnHasMethod(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ IPC::Message* reply_msg);
+ void OnInvokeMethod(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id,
+ const std::string& method_name,
+ const base::ListValue& arguments,
+ IPC::Message* reply_msg);
+
+ private:
+ void OnObjectWrapperDeleted(RenderFrameHost* render_frame_host,
+ GinJavaBoundObject::ObjectID object_id);
+
+ bool IsValidRenderFrameHost(RenderFrameHost* render_frame_host);
+ void SendMethods(RenderFrameHost* render_frame_host,
+ const std::set<std::string>& method_names);
+ void SendHasMethodReply(RenderFrameHost* render_frame_host,
+ bool result);
+ void ProcessMethodInvocationResult(
+ RenderFrameHost* render_frame_host,
+ scoped_refptr<GinJavaMethodInvocationHelper> result);
+ void ProcessMethodInvocationObjectResult(
+ RenderFrameHost* render_frame_host,
+ scoped_refptr<GinJavaMethodInvocationHelper> result);
+ GinJavaBoundObject::ObjectID AddObject(
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz,
+ bool is_named,
+ RenderFrameHost* holder);
+ bool FindObjectId(const base::android::JavaRef<jobject>& object,
+ GinJavaBoundObject::ObjectID* object_id);
+ void RemoveHolder(RenderFrameHost* holder,
+ const GinJavaBoundObject::ObjectMap::iterator& from,
+ size_t count);
+ bool HasPendingReply(RenderFrameHost* render_frame_host) const;
+ IPC::Message* TakePendingReply(RenderFrameHost* render_frame_host);
+
+ // Every time a GinJavaBoundObject backed by a real Java object is
+ // created/destroyed, we insert/remove a strong ref to that Java object into
+ // this set so that it doesn't get garbage collected while it's still
+ // potentially in use. Although the set is managed native side, it's owned
+ // and defined in Java so that pushing refs into it does not create new GC
+ // roots that would prevent ContentViewCore from being garbage collected.
+ JavaObjectWeakGlobalRef retained_object_set_;
+ bool allow_object_contents_inspection_;
+ GinJavaBoundObject::ObjectMap objects_;
+ typedef std::map<std::string, GinJavaBoundObject::ObjectID> NamedObjectMap;
+ NamedObjectMap named_objects_;
+
+ // Keep track of pending calls out to Java such that we can send a synchronous
+ // reply to the renderer waiting on the response should the RenderFrame be
+ // destroyed while the reply is pending.
+ // Only used on the UI thread.
+ typedef std::map<RenderFrameHost*, IPC::Message*> PendingReplyMap;
+ PendingReplyMap pending_replies_;
+
+ DISALLOW_COPY_AND_ASSIGN(GinJavaBridgeDispatcherHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_BRIDGE_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc b/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc
new file mode 100644
index 00000000000..ae1c798fe52
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_method_invocation_helper.cc
@@ -0,0 +1,345 @@
+// Copyright 2014 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 "content/browser/android/java/gin_java_method_invocation_helper.h"
+
+#include <unistd.h>
+
+#include "base/android/event_log.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/float_util.h"
+#include "content/browser/android/java/gin_java_script_to_java_types_coercion.h"
+#include "content/browser/android/java/java_method.h"
+#include "content/browser/android/java/jni_helper.h"
+#include "content/common/android/gin_java_bridge_value.h"
+#include "content/public/browser/browser_thread.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+namespace {
+
+// See frameworks/base/core/java/android/webkit/EventLogTags.logtags
+const int kObjectGetClassInvocationAttemptLogTag = 70151;
+
+} // namespace
+
+GinJavaMethodInvocationHelper::GinJavaMethodInvocationHelper(
+ scoped_ptr<ObjectDelegate> object,
+ const std::string& method_name,
+ const base::ListValue& arguments)
+ : object_(object.Pass()),
+ method_name_(method_name),
+ arguments_(arguments.DeepCopy()),
+ invocation_error_(kGinJavaBridgeNoError) {
+}
+
+GinJavaMethodInvocationHelper::~GinJavaMethodInvocationHelper() {}
+
+void GinJavaMethodInvocationHelper::Init(DispatcherDelegate* dispatcher) {
+ // Build on the UI thread a map of object_id -> WeakRef for Java objects from
+ // |arguments_|. Then we can use this map on the background thread without
+ // accessing |dispatcher|.
+ BuildObjectRefsFromListValue(dispatcher, arguments_.get());
+}
+
+// As V8ValueConverter has finite recursion depth when serializing
+// JavaScript values, we don't bother about having a recursion threshold here.
+void GinJavaMethodInvocationHelper::BuildObjectRefsFromListValue(
+ DispatcherDelegate* dispatcher,
+ const base::Value* list_value) {
+ DCHECK(list_value->IsType(base::Value::TYPE_LIST));
+ const base::ListValue* list;
+ list_value->GetAsList(&list);
+ for (base::ListValue::const_iterator iter = list->begin();
+ iter != list->end();
+ ++iter) {
+ if (AppendObjectRef(dispatcher, *iter))
+ continue;
+ if ((*iter)->IsType(base::Value::TYPE_LIST)) {
+ BuildObjectRefsFromListValue(dispatcher, *iter);
+ } else if ((*iter)->IsType(base::Value::TYPE_DICTIONARY)) {
+ BuildObjectRefsFromDictionaryValue(dispatcher, *iter);
+ }
+ }
+}
+
+void GinJavaMethodInvocationHelper::BuildObjectRefsFromDictionaryValue(
+ DispatcherDelegate* dispatcher,
+ const base::Value* dict_value) {
+ DCHECK(dict_value->IsType(base::Value::TYPE_DICTIONARY));
+ const base::DictionaryValue* dict;
+ dict_value->GetAsDictionary(&dict);
+ for (base::DictionaryValue::Iterator iter(*dict);
+ !iter.IsAtEnd();
+ iter.Advance()) {
+ if (AppendObjectRef(dispatcher, &iter.value()))
+ continue;
+ if (iter.value().IsType(base::Value::TYPE_LIST)) {
+ BuildObjectRefsFromListValue(dispatcher, &iter.value());
+ } else if (iter.value().IsType(base::Value::TYPE_DICTIONARY)) {
+ BuildObjectRefsFromDictionaryValue(dispatcher, &iter.value());
+ }
+ }
+}
+
+bool GinJavaMethodInvocationHelper::AppendObjectRef(
+ DispatcherDelegate* dispatcher,
+ const base::Value* raw_value) {
+ if (!GinJavaBridgeValue::ContainsGinJavaBridgeValue(raw_value))
+ return false;
+ scoped_ptr<const GinJavaBridgeValue> value(
+ GinJavaBridgeValue::FromValue(raw_value));
+ if (!value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID))
+ return false;
+ GinJavaBoundObject::ObjectID object_id;
+ if (value->GetAsObjectID(&object_id)) {
+ ObjectRefs::iterator iter = object_refs_.find(object_id);
+ if (iter == object_refs_.end()) {
+ JavaObjectWeakGlobalRef object_ref(
+ dispatcher->GetObjectWeakRef(object_id));
+ if (!object_ref.is_empty()) {
+ object_refs_.insert(std::make_pair(object_id, object_ref));
+ }
+ }
+ }
+ return true;
+}
+
+void GinJavaMethodInvocationHelper::Invoke() {
+ JNIEnv* env = AttachCurrentThread();
+ const JavaMethod* method =
+ object_->FindMethod(method_name_, arguments_->GetSize());
+ if (!method) {
+ SetInvocationError(kGinJavaBridgeMethodNotFound);
+ return;
+ }
+
+ if (object_->IsObjectGetClassMethod(method)) {
+ base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag,
+ getuid());
+ SetInvocationError(kGinJavaBridgeAccessToObjectGetClassIsBlocked);
+ return;
+ }
+
+ ScopedJavaLocalRef<jobject> obj;
+ ScopedJavaLocalRef<jclass> cls;
+ if (method->is_static()) {
+ cls = object_->GetLocalClassRef(env);
+ } else {
+ obj = object_->GetLocalRef(env);
+ }
+ if (obj.is_null() && cls.is_null()) {
+ SetInvocationError(kGinJavaBridgeObjectIsGone);
+ return;
+ }
+
+ GinJavaBridgeError coercion_error = kGinJavaBridgeNoError;
+ std::vector<jvalue> parameters(method->num_parameters());
+ for (size_t i = 0; i < method->num_parameters(); ++i) {
+ const base::Value* argument;
+ arguments_->Get(i, &argument);
+ parameters[i] = CoerceJavaScriptValueToJavaValue(env,
+ argument,
+ method->parameter_type(i),
+ true,
+ object_refs_,
+ &coercion_error);
+ }
+
+ if (coercion_error == kGinJavaBridgeNoError) {
+ if (method->is_static()) {
+ InvokeMethod(
+ NULL, cls.obj(), method->return_type(), method->id(), &parameters[0]);
+ } else {
+ InvokeMethod(
+ obj.obj(), NULL, method->return_type(), method->id(), &parameters[0]);
+ }
+ } else {
+ SetInvocationError(coercion_error);
+ }
+
+ // Now that we're done with the jvalue, release any local references created
+ // by CoerceJavaScriptValueToJavaValue().
+ for (size_t i = 0; i < method->num_parameters(); ++i) {
+ ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
+ }
+}
+
+void GinJavaMethodInvocationHelper::SetInvocationError(
+ GinJavaBridgeError error) {
+ holds_primitive_result_ = true;
+ primitive_result_.reset(new base::ListValue());
+ invocation_error_ = error;
+}
+
+void GinJavaMethodInvocationHelper::SetPrimitiveResult(
+ const base::ListValue& result_wrapper) {
+ holds_primitive_result_ = true;
+ primitive_result_.reset(result_wrapper.DeepCopy());
+}
+
+void GinJavaMethodInvocationHelper::SetObjectResult(
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz) {
+ holds_primitive_result_ = false;
+ object_result_.Reset(object);
+ safe_annotation_clazz_.Reset(safe_annotation_clazz);
+}
+
+bool GinJavaMethodInvocationHelper::HoldsPrimitiveResult() {
+ return holds_primitive_result_;
+}
+
+const base::ListValue& GinJavaMethodInvocationHelper::GetPrimitiveResult() {
+ return *primitive_result_.get();
+}
+
+const base::android::JavaRef<jobject>&
+GinJavaMethodInvocationHelper::GetObjectResult() {
+ return object_result_;
+}
+
+const base::android::JavaRef<jclass>&
+GinJavaMethodInvocationHelper::GetSafeAnnotationClass() {
+ return safe_annotation_clazz_;
+}
+
+const GinJavaBridgeError GinJavaMethodInvocationHelper::GetInvocationError() {
+ return invocation_error_;
+}
+
+void GinJavaMethodInvocationHelper::InvokeMethod(jobject object,
+ jclass clazz,
+ const JavaType& return_type,
+ jmethodID id,
+ jvalue* parameters) {
+ DCHECK(object || clazz);
+ JNIEnv* env = AttachCurrentThread();
+ base::ListValue result_wrapper;
+ switch (return_type.type) {
+ case JavaType::TypeBoolean:
+ result_wrapper.AppendBoolean(
+ object ? env->CallBooleanMethodA(object, id, parameters)
+ : env->CallStaticBooleanMethodA(clazz, id, parameters));
+ break;
+ case JavaType::TypeByte:
+ result_wrapper.AppendInteger(
+ object ? env->CallByteMethodA(object, id, parameters)
+ : env->CallStaticByteMethodA(clazz, id, parameters));
+ break;
+ case JavaType::TypeChar:
+ result_wrapper.AppendInteger(
+ object ? env->CallCharMethodA(object, id, parameters)
+ : env->CallStaticCharMethodA(clazz, id, parameters));
+ break;
+ case JavaType::TypeShort:
+ result_wrapper.AppendInteger(
+ object ? env->CallShortMethodA(object, id, parameters)
+ : env->CallStaticShortMethodA(clazz, id, parameters));
+ break;
+ case JavaType::TypeInt:
+ result_wrapper.AppendInteger(
+ object ? env->CallIntMethodA(object, id, parameters)
+ : env->CallStaticIntMethodA(clazz, id, parameters));
+ break;
+ case JavaType::TypeLong:
+ result_wrapper.AppendDouble(
+ object ? env->CallLongMethodA(object, id, parameters)
+ : env->CallStaticLongMethodA(clazz, id, parameters));
+ break;
+ case JavaType::TypeFloat: {
+ float result = object
+ ? env->CallFloatMethodA(object, id, parameters)
+ : env->CallStaticFloatMethodA(clazz, id, parameters);
+ if (base::IsFinite(result)) {
+ result_wrapper.AppendDouble(result);
+ } else {
+ result_wrapper.Append(
+ GinJavaBridgeValue::CreateNonFiniteValue(result).release());
+ }
+ break;
+ }
+ case JavaType::TypeDouble: {
+ double result = object
+ ? env->CallDoubleMethodA(object, id, parameters)
+ : env->CallStaticDoubleMethodA(clazz, id, parameters);
+ if (base::IsFinite(result)) {
+ result_wrapper.AppendDouble(result);
+ } else {
+ result_wrapper.Append(
+ GinJavaBridgeValue::CreateNonFiniteValue(result).release());
+ }
+ break;
+ }
+ case JavaType::TypeVoid:
+ if (object)
+ env->CallVoidMethodA(object, id, parameters);
+ else
+ env->CallStaticVoidMethodA(clazz, id, parameters);
+ result_wrapper.Append(
+ GinJavaBridgeValue::CreateUndefinedValue().release());
+ break;
+ case JavaType::TypeArray:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that
+ // return arrays. Spec requires calling the method and converting the
+ // result to a JavaScript array.
+ result_wrapper.Append(
+ GinJavaBridgeValue::CreateUndefinedValue().release());
+ break;
+ case JavaType::TypeString: {
+ jstring java_string = static_cast<jstring>(
+ object ? env->CallObjectMethodA(object, id, parameters)
+ : env->CallStaticObjectMethodA(clazz, id, parameters));
+ // If an exception was raised, we must clear it before calling most JNI
+ // methods. ScopedJavaLocalRef is liable to make such calls, so we test
+ // first.
+ if (base::android::ClearException(env)) {
+ SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
+ return;
+ }
+ ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
+ if (!scoped_java_string.obj()) {
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined.
+ // Spec requires returning a null string.
+ result_wrapper.Append(
+ GinJavaBridgeValue::CreateUndefinedValue().release());
+ break;
+ }
+ result_wrapper.AppendString(
+ base::android::ConvertJavaStringToUTF8(scoped_java_string));
+ break;
+ }
+ case JavaType::TypeObject: {
+ // If an exception was raised, we must clear it before calling most JNI
+ // methods. ScopedJavaLocalRef is liable to make such calls, so we test
+ // first.
+ jobject java_object =
+ object ? env->CallObjectMethodA(object, id, parameters)
+ : env->CallStaticObjectMethodA(clazz, id, parameters);
+ if (base::android::ClearException(env)) {
+ SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
+ return;
+ }
+ ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
+ if (!scoped_java_object.obj()) {
+ result_wrapper.Append(base::Value::CreateNullValue());
+ break;
+ }
+ SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass());
+ return;
+ }
+ }
+ // This is for all cases except JavaType::TypeObject.
+ if (!base::android::ClearException(env)) {
+ SetPrimitiveResult(result_wrapper);
+ } else {
+ SetInvocationError(kGinJavaBridgeJavaExceptionRaised);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/gin_java_method_invocation_helper.h b/chromium/content/browser/android/java/gin_java_method_invocation_helper.h
new file mode 100644
index 00000000000..014e3113194
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_method_invocation_helper.h
@@ -0,0 +1,117 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_METHOD_INVOCATION_HELPER_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_METHOD_INVOCATION_HELPER_H_
+
+#include <map>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/ref_counted.h"
+#include "base/values.h"
+#include "content/browser/android/java/gin_java_bound_object.h"
+#include "content/browser/android/java/java_type.h"
+#include "content/common/android/gin_java_bridge_errors.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class JavaMethod;
+
+// Instances of this class are created and initialized on the UI thread, do
+// their work on the background thread, and then again examined on the UI
+// thread. They don't work on both threads simultaneously, though.
+class CONTENT_EXPORT GinJavaMethodInvocationHelper
+ : public base::RefCountedThreadSafe<GinJavaMethodInvocationHelper> {
+ public:
+ // DispatcherDelegate is used on the UI thread
+ class DispatcherDelegate {
+ public:
+ DispatcherDelegate() {}
+ virtual ~DispatcherDelegate() {}
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DispatcherDelegate);
+ };
+
+ // ObjectDelegate is used in the background thread
+ class ObjectDelegate {
+ public:
+ ObjectDelegate() {}
+ virtual ~ObjectDelegate() {}
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
+ JNIEnv* env) = 0;
+ virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
+ JNIEnv* env) = 0;
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) = 0;
+ virtual bool IsObjectGetClassMethod(const JavaMethod* method) = 0;
+ virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ObjectDelegate);
+ };
+
+ GinJavaMethodInvocationHelper(scoped_ptr<ObjectDelegate> object,
+ const std::string& method_name,
+ const base::ListValue& arguments);
+ void Init(DispatcherDelegate* dispatcher);
+
+ // Called on the background thread
+ void Invoke();
+
+ // Called on the UI thread
+ bool HoldsPrimitiveResult();
+ const base::ListValue& GetPrimitiveResult();
+ const base::android::JavaRef<jobject>& GetObjectResult();
+ const base::android::JavaRef<jclass>& GetSafeAnnotationClass();
+ const GinJavaBridgeError GetInvocationError();
+
+ private:
+ friend class base::RefCountedThreadSafe<GinJavaMethodInvocationHelper>;
+ ~GinJavaMethodInvocationHelper();
+
+ // Called on the UI thread
+ void BuildObjectRefsFromListValue(DispatcherDelegate* dispatcher,
+ const base::Value* list_value);
+ void BuildObjectRefsFromDictionaryValue(DispatcherDelegate* dispatcher,
+ const base::Value* dict_value);
+
+ bool AppendObjectRef(DispatcherDelegate* dispatcher,
+ const base::Value* raw_value);
+
+ // Called on the background thread.
+ void InvokeMethod(jobject object,
+ jclass clazz,
+ const JavaType& return_type,
+ jmethodID id,
+ jvalue* parameters);
+ void SetInvocationError(GinJavaBridgeError error);
+ void SetPrimitiveResult(const base::ListValue& result_wrapper);
+ void SetObjectResult(
+ const base::android::JavaRef<jobject>& object,
+ const base::android::JavaRef<jclass>& safe_annotation_clazz);
+
+ typedef std::map<GinJavaBoundObject::ObjectID,
+ JavaObjectWeakGlobalRef> ObjectRefs;
+
+ scoped_ptr<ObjectDelegate> object_;
+ const std::string method_name_;
+ scoped_ptr<base::ListValue> arguments_;
+ ObjectRefs object_refs_;
+ bool holds_primitive_result_;
+ scoped_ptr<base::ListValue> primitive_result_;
+ GinJavaBridgeError invocation_error_;
+ base::android::ScopedJavaGlobalRef<jobject> object_result_;
+ base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
+
+ DISALLOW_COPY_AND_ASSIGN(GinJavaMethodInvocationHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_METHOD_INVOCATION_HELPER_H_
diff --git a/chromium/content/browser/android/java/gin_java_method_invocation_helper_unittest.cc b/chromium/content/browser/android/java/gin_java_method_invocation_helper_unittest.cc
new file mode 100644
index 00000000000..ccd508355bb
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_method_invocation_helper_unittest.cc
@@ -0,0 +1,339 @@
+// Copyright 2014 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 "content/browser/android/java/gin_java_method_invocation_helper.h"
+
+#include "base/android/jni_android.h"
+#include "content/browser/android/java/jni_helper.h"
+#include "content/common/android/gin_java_bridge_value.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class NullObjectDelegate
+ : public GinJavaMethodInvocationHelper::ObjectDelegate {
+ public:
+ NullObjectDelegate() {}
+
+ virtual ~NullObjectDelegate() {}
+
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
+ JNIEnv* env) override {
+ return base::android::ScopedJavaLocalRef<jobject>();
+ }
+
+ virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
+ JNIEnv* env) override {
+ return base::android::ScopedJavaLocalRef<jclass>();
+ }
+
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) override {
+ return NULL;
+ }
+
+ virtual bool IsObjectGetClassMethod(const JavaMethod* method) override {
+ return false;
+ }
+
+ virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass()
+ override {
+ return safe_annotation_class_;
+ }
+
+ private:
+ base::android::ScopedJavaLocalRef<jclass> safe_annotation_class_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullObjectDelegate);
+};
+
+class NullDispatcherDelegate
+ : public GinJavaMethodInvocationHelper::DispatcherDelegate {
+ public:
+ NullDispatcherDelegate() {}
+
+ virtual ~NullDispatcherDelegate() {}
+
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) override {
+ return JavaObjectWeakGlobalRef();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(NullDispatcherDelegate);
+};
+
+} // namespace
+
+class GinJavaMethodInvocationHelperTest : public testing::Test {
+};
+
+namespace {
+
+class CountingDispatcherDelegate
+ : public GinJavaMethodInvocationHelper::DispatcherDelegate {
+ public:
+ CountingDispatcherDelegate() {}
+
+ virtual ~CountingDispatcherDelegate() {}
+
+ virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
+ GinJavaBoundObject::ObjectID object_id) override {
+ counters_[object_id]++;
+ return JavaObjectWeakGlobalRef();
+ }
+
+ void AssertInvocationsCount(GinJavaBoundObject::ObjectID begin_object_id,
+ GinJavaBoundObject::ObjectID end_object_id) {
+ EXPECT_EQ(end_object_id - begin_object_id,
+ static_cast<int>(counters_.size()));
+ for (GinJavaBoundObject::ObjectID i = begin_object_id;
+ i < end_object_id; ++i) {
+ EXPECT_LT(0, counters_[i]) << "ObjectID: " << i;
+ }
+ }
+
+ private:
+ typedef std::map<GinJavaBoundObject::ObjectID, int> Counters;
+ Counters counters_;
+
+ DISALLOW_COPY_AND_ASSIGN(CountingDispatcherDelegate);
+};
+
+} // namespace
+
+TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsNoObjects) {
+ base::ListValue no_objects;
+ for (int i = 0; i < 10; ++i) {
+ no_objects.AppendInteger(i);
+ }
+
+ scoped_refptr<GinJavaMethodInvocationHelper> helper =
+ new GinJavaMethodInvocationHelper(
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
+ new NullObjectDelegate()),
+ "foo",
+ no_objects);
+ CountingDispatcherDelegate counter;
+ helper->Init(&counter);
+ counter.AssertInvocationsCount(0, 0);
+}
+
+TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsHaveObjects) {
+ base::ListValue objects;
+ objects.AppendInteger(100);
+ objects.Append(GinJavaBridgeValue::CreateObjectIDValue(1).release());
+ base::ListValue* sub_list = new base::ListValue();
+ sub_list->AppendInteger(200);
+ sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(2).release());
+ objects.Append(sub_list);
+ base::DictionaryValue* sub_dict = new base::DictionaryValue();
+ sub_dict->SetInteger("1", 300);
+ sub_dict->Set("2", GinJavaBridgeValue::CreateObjectIDValue(3).release());
+ objects.Append(sub_dict);
+ base::ListValue* sub_list_with_dict = new base::ListValue();
+ base::DictionaryValue* sub_sub_dict = new base::DictionaryValue();
+ sub_sub_dict->Set("1", GinJavaBridgeValue::CreateObjectIDValue(4).release());
+ sub_list_with_dict->Append(sub_sub_dict);
+ objects.Append(sub_list_with_dict);
+ base::DictionaryValue* sub_dict_with_list = new base::DictionaryValue();
+ base::ListValue* sub_sub_list = new base::ListValue();
+ sub_sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(5).release());
+ sub_dict_with_list->Set("1", sub_sub_list);
+ objects.Append(sub_dict_with_list);
+
+ scoped_refptr<GinJavaMethodInvocationHelper> helper =
+ new GinJavaMethodInvocationHelper(
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
+ new NullObjectDelegate()),
+ "foo",
+ objects);
+ CountingDispatcherDelegate counter;
+ helper->Init(&counter);
+ counter.AssertInvocationsCount(1, 6);
+}
+
+namespace {
+
+class ObjectIsGoneObjectDelegate : public NullObjectDelegate {
+ public:
+ ObjectIsGoneObjectDelegate() :
+ get_local_ref_called_(false) {
+ // We need a Java Method object to create a valid JavaMethod instance.
+ JNIEnv* env = base::android::AttachCurrentThread();
+ jmethodID method_id =
+ GetMethodIDFromClassName(env, "java/lang/Object", "hashCode", "()I");
+ EXPECT_TRUE(method_id);
+ base::android::ScopedJavaLocalRef<jobject> method_obj(
+ env,
+ env->ToReflectedMethod(
+ base::android::GetClass(env, "java/lang/Object").obj(),
+ method_id,
+ false));
+ EXPECT_TRUE(method_obj.obj());
+ method_.reset(new JavaMethod(method_obj));
+ }
+
+ virtual ~ObjectIsGoneObjectDelegate() {}
+
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
+ JNIEnv* env) override {
+ get_local_ref_called_ = true;
+ return NullObjectDelegate::GetLocalRef(env);
+ }
+
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) override {
+ return method_.get();
+ }
+
+ bool get_local_ref_called() { return get_local_ref_called_; }
+
+ const std::string& get_method_name() { return method_->name(); }
+
+ protected:
+ scoped_ptr<JavaMethod> method_;
+ bool get_local_ref_called_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ObjectIsGoneObjectDelegate);
+};
+
+} // namespace
+
+TEST_F(GinJavaMethodInvocationHelperTest, HandleObjectIsGone) {
+ base::ListValue no_objects;
+ ObjectIsGoneObjectDelegate* object_delegate =
+ new ObjectIsGoneObjectDelegate();
+ scoped_refptr<GinJavaMethodInvocationHelper> helper =
+ new GinJavaMethodInvocationHelper(
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
+ object_delegate),
+ object_delegate->get_method_name(),
+ no_objects);
+ NullDispatcherDelegate dispatcher;
+ helper->Init(&dispatcher);
+ EXPECT_FALSE(object_delegate->get_local_ref_called());
+ EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
+ helper->Invoke();
+ EXPECT_TRUE(object_delegate->get_local_ref_called());
+ EXPECT_TRUE(helper->HoldsPrimitiveResult());
+ EXPECT_TRUE(helper->GetPrimitiveResult().empty());
+ EXPECT_EQ(kGinJavaBridgeObjectIsGone, helper->GetInvocationError());
+}
+
+namespace {
+
+class MethodNotFoundObjectDelegate : public NullObjectDelegate {
+ public:
+ MethodNotFoundObjectDelegate() : find_method_called_(false) {}
+
+ virtual ~MethodNotFoundObjectDelegate() {}
+
+ virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
+ JNIEnv* env) override {
+ return base::android::ScopedJavaLocalRef<jobject>(
+ env, static_cast<jobject>(env->FindClass("java/lang/String")));
+ }
+
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) override {
+ find_method_called_ = true;
+ return NULL;
+ }
+
+ bool find_method_called() const { return find_method_called_; }
+
+ protected:
+ bool find_method_called_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MethodNotFoundObjectDelegate);
+};
+
+} // namespace
+
+TEST_F(GinJavaMethodInvocationHelperTest, HandleMethodNotFound) {
+ base::ListValue no_objects;
+ MethodNotFoundObjectDelegate* object_delegate =
+ new MethodNotFoundObjectDelegate();
+ scoped_refptr<GinJavaMethodInvocationHelper> helper =
+ new GinJavaMethodInvocationHelper(
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
+ object_delegate),
+ "foo",
+ no_objects);
+ NullDispatcherDelegate dispatcher;
+ helper->Init(&dispatcher);
+ EXPECT_FALSE(object_delegate->find_method_called());
+ EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
+ helper->Invoke();
+ EXPECT_TRUE(object_delegate->find_method_called());
+ EXPECT_TRUE(helper->HoldsPrimitiveResult());
+ EXPECT_TRUE(helper->GetPrimitiveResult().empty());
+ EXPECT_EQ(kGinJavaBridgeMethodNotFound, helper->GetInvocationError());
+}
+
+namespace {
+
+class GetClassObjectDelegate : public MethodNotFoundObjectDelegate {
+ public:
+ GetClassObjectDelegate() : get_class_called_(false) {}
+
+ virtual ~GetClassObjectDelegate() {}
+
+ virtual const JavaMethod* FindMethod(const std::string& method_name,
+ size_t num_parameters) override {
+ find_method_called_ = true;
+ return kFakeGetClass;
+ }
+
+ virtual bool IsObjectGetClassMethod(const JavaMethod* method) override {
+ get_class_called_ = true;
+ return kFakeGetClass == method;
+ }
+
+ bool get_class_called() const { return get_class_called_; }
+
+ private:
+ static const JavaMethod* kFakeGetClass;
+ bool get_class_called_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetClassObjectDelegate);
+};
+
+// We don't expect GinJavaMethodInvocationHelper to actually invoke the
+// method, since the point of the test is to verify whether calls to
+// 'getClass' get blocked.
+const JavaMethod* GetClassObjectDelegate::kFakeGetClass =
+ (JavaMethod*)0xdeadbeef;
+
+} // namespace
+
+TEST_F(GinJavaMethodInvocationHelperTest, HandleGetClassInvocation) {
+ base::ListValue no_objects;
+ GetClassObjectDelegate* object_delegate =
+ new GetClassObjectDelegate();
+ scoped_refptr<GinJavaMethodInvocationHelper> helper =
+ new GinJavaMethodInvocationHelper(
+ scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
+ object_delegate),
+ "foo",
+ no_objects);
+ NullDispatcherDelegate dispatcher;
+ helper->Init(&dispatcher);
+ EXPECT_FALSE(object_delegate->find_method_called());
+ EXPECT_FALSE(object_delegate->get_class_called());
+ EXPECT_EQ(kGinJavaBridgeNoError, helper->GetInvocationError());
+ helper->Invoke();
+ EXPECT_TRUE(object_delegate->find_method_called());
+ EXPECT_TRUE(object_delegate->get_class_called());
+ EXPECT_TRUE(helper->HoldsPrimitiveResult());
+ EXPECT_TRUE(helper->GetPrimitiveResult().empty());
+ EXPECT_EQ(kGinJavaBridgeAccessToObjectGetClassIsBlocked,
+ helper->GetInvocationError());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.cc b/chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.cc
new file mode 100644
index 00000000000..cb4e51776b4
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.cc
@@ -0,0 +1,743 @@
+// Copyright 2014 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 "content/browser/android/java/gin_java_script_to_java_types_coercion.h"
+
+#include <unistd.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/common/android/gin_java_bridge_value.h"
+
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+
+namespace {
+
+const char kJavaLangString[] = "java/lang/String";
+const char kUndefined[] = "undefined";
+
+double RoundDoubleTowardsZero(const double& x) {
+ if (std::isnan(x)) {
+ return 0.0;
+ }
+ return x > 0.0 ? floor(x) : ceil(x);
+}
+
+// Rounds to jlong using Java's type conversion rules.
+jlong RoundDoubleToLong(const double& x) {
+ double intermediate = RoundDoubleTowardsZero(x);
+ // The int64 limits can not be converted exactly to double values, so we
+ // compare to custom constants. kint64max is 2^63 - 1, but the spacing
+ // between double values in the the range 2^62 to 2^63 is 2^10. The cast is
+ // required to silence a spurious gcc warning for integer overflow.
+ const int64 kLimit = (GG_INT64_C(1) << 63) - static_cast<uint64>(1 << 10);
+ DCHECK(kLimit > 0);
+ const double kLargestDoubleLessThanInt64Max = kLimit;
+ const double kSmallestDoubleGreaterThanInt64Min = -kLimit;
+ if (intermediate > kLargestDoubleLessThanInt64Max) {
+ return kint64max;
+ }
+ if (intermediate < kSmallestDoubleGreaterThanInt64Min) {
+ return kint64min;
+ }
+ return static_cast<jlong>(intermediate);
+}
+
+// Rounds to jint using Java's type conversion rules.
+jint RoundDoubleToInt(const double& x) {
+ double intermediate = RoundDoubleTowardsZero(x);
+ // The int32 limits cast exactly to double values.
+ intermediate = std::min(intermediate, static_cast<double>(kint32max));
+ intermediate = std::max(intermediate, static_cast<double>(kint32min));
+ return static_cast<jint>(intermediate);
+}
+
+jvalue CoerceJavaScriptIntegerToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ GinJavaBridgeError* error) {
+ // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
+
+ // For conversion to numeric types, we need to replicate Java's type
+ // conversion rules. This requires that for integer values, we simply discard
+ // all but the lowest n buts, where n is the number of bits in the target
+ // type.
+ jvalue result;
+ int int_value;
+ value->GetAsInteger(&int_value);
+ switch (target_type.type) {
+ case JavaType::TypeByte:
+ result.b = static_cast<jbyte>(int_value);
+ break;
+ case JavaType::TypeChar:
+ result.c = static_cast<jchar>(int_value);
+ break;
+ case JavaType::TypeShort:
+ result.s = static_cast<jshort>(int_value);
+ break;
+ case JavaType::TypeInt:
+ result.i = int_value;
+ break;
+ case JavaType::TypeLong:
+ result.j = int_value;
+ break;
+ case JavaType::TypeFloat:
+ result.f = int_value;
+ break;
+ case JavaType::TypeDouble:
+ result.d = int_value;
+ break;
+ case JavaType::TypeObject:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
+ // requires handling object equivalents of primitive types.
+ result.l = NULL;
+ break;
+ case JavaType::TypeString:
+ result.l = coerce_to_string
+ ? ConvertUTF8ToJavaString(
+ env, base::Int64ToString(int_value)).Release()
+ : NULL;
+ break;
+ case JavaType::TypeBoolean:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
+ // requires converting to false for 0 or NaN, true otherwise.
+ result.z = JNI_FALSE;
+ break;
+ case JavaType::TypeArray:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
+ // requires raising a JavaScript exception.
+ result.l = NULL;
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
+jvalue CoerceJavaScriptDoubleToJavaValue(JNIEnv* env,
+ double double_value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ GinJavaBridgeError* error) {
+ // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
+ // For conversion to numeric types, we need to replicate Java's type
+ // conversion rules.
+ jvalue result;
+ switch (target_type.type) {
+ case JavaType::TypeByte:
+ result.b = static_cast<jbyte>(RoundDoubleToInt(double_value));
+ break;
+ case JavaType::TypeChar:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert double to 0.
+ // Spec requires converting doubles similarly to how we convert doubles to
+ // other numeric types.
+ result.c = 0;
+ break;
+ case JavaType::TypeShort:
+ result.s = static_cast<jshort>(RoundDoubleToInt(double_value));
+ break;
+ case JavaType::TypeInt:
+ result.i = RoundDoubleToInt(double_value);
+ break;
+ case JavaType::TypeLong:
+ result.j = RoundDoubleToLong(double_value);
+ break;
+ case JavaType::TypeFloat:
+ result.f = static_cast<jfloat>(double_value);
+ break;
+ case JavaType::TypeDouble:
+ result.d = double_value;
+ break;
+ case JavaType::TypeObject:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
+ // requires handling object equivalents of primitive types.
+ result.l = NULL;
+ break;
+ case JavaType::TypeString:
+ result.l =
+ coerce_to_string
+ ? ConvertUTF8ToJavaString(
+ env, base::StringPrintf("%.6lg", double_value)).Release()
+ : NULL;
+ break;
+ case JavaType::TypeBoolean:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
+ // requires converting to false for 0 or NaN, true otherwise.
+ result.z = JNI_FALSE;
+ break;
+ case JavaType::TypeArray:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
+ // requires raising a JavaScript exception.
+ result.l = NULL;
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
+jvalue CoerceJavaScriptBooleanToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ GinJavaBridgeError* error) {
+ // See http://jdk6.java.net/plugin2/liveconnect/#JS_BOOLEAN_VALUES.
+ bool boolean_value;
+ value->GetAsBoolean(&boolean_value);
+ jvalue result;
+ switch (target_type.type) {
+ case JavaType::TypeBoolean:
+ result.z = boolean_value ? JNI_TRUE : JNI_FALSE;
+ break;
+ case JavaType::TypeObject:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
+ // requires handling java.lang.Boolean and java.lang.Object.
+ result.l = NULL;
+ break;
+ case JavaType::TypeString:
+ result.l = coerce_to_string
+ ? ConvertUTF8ToJavaString(
+ env, boolean_value ? "true" : "false").Release()
+ : NULL;
+ break;
+ case JavaType::TypeByte:
+ case JavaType::TypeChar:
+ case JavaType::TypeShort:
+ case JavaType::TypeInt:
+ case JavaType::TypeLong:
+ case JavaType::TypeFloat:
+ case JavaType::TypeDouble: {
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
+ // requires converting to 0 or 1.
+ jvalue null_value = {0};
+ result = null_value;
+ break;
+ }
+ case JavaType::TypeArray:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
+ // requires raising a JavaScript exception.
+ result.l = NULL;
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
+jvalue CoerceJavaScriptStringToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ GinJavaBridgeError* error) {
+ // See http://jdk6.java.net/plugin2/liveconnect/#JS_STRING_VALUES.
+ jvalue result;
+ switch (target_type.type) {
+ case JavaType::TypeString: {
+ std::string string_result;
+ value->GetAsString(&string_result);
+ result.l = ConvertUTF8ToJavaString(env, string_result).Release();
+ break;
+ }
+ case JavaType::TypeObject:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
+ // requires handling java.lang.Object.
+ result.l = NULL;
+ break;
+ case JavaType::TypeByte:
+ case JavaType::TypeShort:
+ case JavaType::TypeInt:
+ case JavaType::TypeLong:
+ case JavaType::TypeFloat:
+ case JavaType::TypeDouble: {
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
+ // requires using valueOf() method of corresponding object type.
+ jvalue null_value = {0};
+ result = null_value;
+ break;
+ }
+ case JavaType::TypeChar:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
+ // requires using java.lang.Short.decode().
+ result.c = 0;
+ break;
+ case JavaType::TypeBoolean:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
+ // requires converting the empty string to false, otherwise true.
+ result.z = JNI_FALSE;
+ break;
+ case JavaType::TypeArray:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
+ // requires raising a JavaScript exception.
+ result.l = NULL;
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
+// Note that this only handles primitive types and strings.
+jobject CreateJavaArray(JNIEnv* env, const JavaType& type, jsize length) {
+ switch (type.type) {
+ case JavaType::TypeBoolean:
+ return env->NewBooleanArray(length);
+ case JavaType::TypeByte:
+ return env->NewByteArray(length);
+ case JavaType::TypeChar:
+ return env->NewCharArray(length);
+ case JavaType::TypeShort:
+ return env->NewShortArray(length);
+ case JavaType::TypeInt:
+ return env->NewIntArray(length);
+ case JavaType::TypeLong:
+ return env->NewLongArray(length);
+ case JavaType::TypeFloat:
+ return env->NewFloatArray(length);
+ case JavaType::TypeDouble:
+ return env->NewDoubleArray(length);
+ case JavaType::TypeString: {
+ ScopedJavaLocalRef<jclass> clazz(
+ base::android::GetClass(env, kJavaLangString));
+ return env->NewObjectArray(length, clazz.obj(), NULL);
+ }
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ case JavaType::TypeArray:
+ case JavaType::TypeObject:
+ // Not handled.
+ NOTREACHED();
+ }
+ return NULL;
+}
+
+// Sets the specified element of the supplied array to the value of the
+// supplied jvalue. Requires that the type of the array matches that of the
+// jvalue. Handles only primitive types and strings. Note that in the case of a
+// string, the array takes a new reference to the string object.
+void SetArrayElement(JNIEnv* env,
+ jobject array,
+ const JavaType& type,
+ jsize index,
+ const jvalue& value) {
+ switch (type.type) {
+ case JavaType::TypeBoolean:
+ env->SetBooleanArrayRegion(static_cast<jbooleanArray>(array), index, 1,
+ &value.z);
+ break;
+ case JavaType::TypeByte:
+ env->SetByteArrayRegion(static_cast<jbyteArray>(array), index, 1,
+ &value.b);
+ break;
+ case JavaType::TypeChar:
+ env->SetCharArrayRegion(static_cast<jcharArray>(array), index, 1,
+ &value.c);
+ break;
+ case JavaType::TypeShort:
+ env->SetShortArrayRegion(static_cast<jshortArray>(array), index, 1,
+ &value.s);
+ break;
+ case JavaType::TypeInt:
+ env->SetIntArrayRegion(static_cast<jintArray>(array), index, 1,
+ &value.i);
+ break;
+ case JavaType::TypeLong:
+ env->SetLongArrayRegion(static_cast<jlongArray>(array), index, 1,
+ &value.j);
+ break;
+ case JavaType::TypeFloat:
+ env->SetFloatArrayRegion(static_cast<jfloatArray>(array), index, 1,
+ &value.f);
+ break;
+ case JavaType::TypeDouble:
+ env->SetDoubleArrayRegion(static_cast<jdoubleArray>(array), index, 1,
+ &value.d);
+ break;
+ case JavaType::TypeString:
+ env->SetObjectArrayElement(static_cast<jobjectArray>(array), index,
+ value.l);
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ case JavaType::TypeArray:
+ case JavaType::TypeObject:
+ // Not handled.
+ NOTREACHED();
+ }
+ base::android::CheckException(env);
+}
+
+jvalue CoerceJavaScriptNullOrUndefinedToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ GinJavaBridgeError* error) {
+ bool is_undefined = false;
+ scoped_ptr<const GinJavaBridgeValue> gin_value;
+ if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) {
+ gin_value = GinJavaBridgeValue::FromValue(value);
+ if (gin_value->IsType(GinJavaBridgeValue::TYPE_UNDEFINED)) {
+ is_undefined = true;
+ }
+ }
+ jvalue result;
+ switch (target_type.type) {
+ case JavaType::TypeObject:
+ result.l = NULL;
+ break;
+ case JavaType::TypeString:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert undefined to
+ // "undefined". Spec requires converting undefined to NULL.
+ result.l = (coerce_to_string && is_undefined)
+ ? ConvertUTF8ToJavaString(env, kUndefined).Release()
+ : NULL;
+ break;
+ case JavaType::TypeByte:
+ case JavaType::TypeChar:
+ case JavaType::TypeShort:
+ case JavaType::TypeInt:
+ case JavaType::TypeLong:
+ case JavaType::TypeFloat:
+ case JavaType::TypeDouble: {
+ jvalue null_value = {0};
+ result = null_value;
+ break;
+ }
+ case JavaType::TypeBoolean:
+ result.z = JNI_FALSE;
+ break;
+ case JavaType::TypeArray:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
+ // requires raising a JavaScript exception.
+ result.l = NULL;
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
+jobject CoerceJavaScriptListToArray(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ const ObjectRefs& object_refs,
+ GinJavaBridgeError* error) {
+ DCHECK_EQ(JavaType::TypeArray, target_type.type);
+ const JavaType& target_inner_type = *target_type.inner_type.get();
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
+ // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
+ if (target_inner_type.type == JavaType::TypeArray) {
+ return NULL;
+ }
+
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
+ // arrays. Spec requires handling object arrays.
+ if (target_inner_type.type == JavaType::TypeObject) {
+ return NULL;
+ }
+
+ const base::ListValue* list_value;
+ value->GetAsList(&list_value);
+ // Create the Java array.
+ jsize length = static_cast<jsize>(list_value->GetSize());
+ jobject result = CreateJavaArray(env, target_inner_type, length);
+ if (!result) {
+ return NULL;
+ }
+ scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
+ for (jsize i = 0; i < length; ++i) {
+ const base::Value* value_element = null_value.get();
+ list_value->Get(i, &value_element);
+ jvalue element = CoerceJavaScriptValueToJavaValue(
+ env, value_element, target_inner_type, false, object_refs, error);
+ SetArrayElement(env, result, target_inner_type, i, element);
+ // CoerceJavaScriptValueToJavaValue() creates new local references to
+ // strings, objects and arrays. Of these, only strings can occur here.
+ // SetArrayElement() causes the array to take its own reference to the
+ // string, so we can now release the local reference.
+ DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
+ DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
+ ReleaseJavaValueIfRequired(env, &element, target_inner_type);
+ }
+
+ return result;
+}
+
+jobject CoerceJavaScriptDictionaryToArray(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ const ObjectRefs& object_refs,
+ GinJavaBridgeError* error) {
+ DCHECK_EQ(JavaType::TypeArray, target_type.type);
+
+ const JavaType& target_inner_type = *target_type.inner_type.get();
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
+ // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
+ if (target_inner_type.type == JavaType::TypeArray) {
+ return NULL;
+ }
+
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
+ // arrays. Spec requires handling object arrays.
+ if (target_inner_type.type == JavaType::TypeObject) {
+ return NULL;
+ }
+
+ const base::DictionaryValue* dictionary_value;
+ value->GetAsDictionary(&dictionary_value);
+ const base::Value* length_value;
+ // If the object does not have a length property, return null.
+ if (!dictionary_value->Get("length", &length_value)) {
+ return NULL;
+ }
+
+ // If the length property does not have numeric type, or is outside the valid
+ // range for a Java array length, return null.
+ jsize length = -1;
+ if (length_value->IsType(base::Value::TYPE_INTEGER)) {
+ int int_length;
+ length_value->GetAsInteger(&int_length);
+ if (int_length >= 0 && int_length <= kint32max) {
+ length = static_cast<jsize>(int_length);
+ }
+ } else if (length_value->IsType(base::Value::TYPE_DOUBLE)) {
+ double double_length;
+ length_value->GetAsDouble(&double_length);
+ if (double_length >= 0.0 && double_length <= kint32max) {
+ length = static_cast<jsize>(double_length);
+ }
+ }
+ if (length == -1) {
+ return NULL;
+ }
+
+ jobject result = CreateJavaArray(env, target_inner_type, length);
+ if (!result) {
+ return NULL;
+ }
+ scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
+ for (jsize i = 0; i < length; ++i) {
+ const std::string key(base::IntToString(i));
+ const base::Value* value_element = null_value.get();
+ if (dictionary_value->HasKey(key)) {
+ dictionary_value->Get(key, &value_element);
+ }
+ jvalue element = CoerceJavaScriptValueToJavaValue(
+ env, value_element, target_inner_type, false, object_refs, error);
+ SetArrayElement(env, result, target_inner_type, i, element);
+ // CoerceJavaScriptValueToJavaValue() creates new local references to
+ // strings, objects and arrays. Of these, only strings can occur here.
+ // SetArrayElement() causes the array to take its own reference to the
+ // string, so we can now release the local reference.
+ DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
+ DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
+ ReleaseJavaValueIfRequired(env, &element, target_inner_type);
+ }
+
+ return result;
+}
+
+// Returns 'true' if it is possible to cast an object of class |src| to
+// an object of class |dst|.
+bool CanAssignClassVariables(JNIEnv* env,
+ const ScopedJavaLocalRef<jclass>& dst,
+ const ScopedJavaLocalRef<jclass>& src) {
+ if (dst.is_null() || src.is_null())
+ return false;
+ return env->IsAssignableFrom(src.obj(), dst.obj()) == JNI_TRUE;
+}
+
+ScopedJavaLocalRef<jclass> GetObjectClass(
+ JNIEnv* env,
+ const ScopedJavaLocalRef<jobject>& obj) {
+ jclass clazz = env->GetObjectClass(obj.obj());
+ return ScopedJavaLocalRef<jclass>(env, clazz);
+}
+
+jvalue CoerceJavaScriptObjectToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ const ObjectRefs& object_refs,
+ GinJavaBridgeError* error) {
+ // This covers both JavaScript objects (including arrays) and Java objects.
+ // See http://jdk6.java.net/plugin2/liveconnect/#JS_OTHER_OBJECTS,
+ // http://jdk6.java.net/plugin2/liveconnect/#JS_ARRAY_VALUES and
+ // http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_OBJECTS
+ jvalue result;
+ switch (target_type.type) {
+ case JavaType::TypeObject: {
+ if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) {
+ scoped_ptr<const GinJavaBridgeValue> gin_value(
+ GinJavaBridgeValue::FromValue(value));
+ DCHECK(gin_value);
+ DCHECK(gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID));
+ ScopedJavaLocalRef<jobject> obj;
+ GinJavaBoundObject::ObjectID object_id;
+ if (gin_value->GetAsObjectID(&object_id)) {
+ ObjectRefs::const_iterator iter = object_refs.find(object_id);
+ if (iter != object_refs.end()) {
+ obj.Reset(iter->second.get(env));
+ }
+ }
+ DCHECK(!target_type.class_jni_name.empty());
+ DCHECK(!obj.is_null());
+ if (CanAssignClassVariables(
+ env,
+ base::android::GetClass(env, target_type.JNIName().c_str()),
+ GetObjectClass(env, obj))) {
+ result.l = obj.Release();
+ } else {
+ result.l = NULL;
+ *error = kGinJavaBridgeNonAssignableTypes;
+ }
+ } else {
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to pass null. Spec
+ // requires converting if the target type is
+ // netscape.javascript.JSObject, otherwise raising a JavaScript
+ // exception.
+ result.l = NULL;
+ }
+ break;
+ }
+ case JavaType::TypeString:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to
+ // "undefined". Spec requires calling toString() on the Java object.
+ result.l = coerce_to_string
+ ? ConvertUTF8ToJavaString(env, kUndefined).Release()
+ : NULL;
+ break;
+ case JavaType::TypeByte:
+ case JavaType::TypeShort:
+ case JavaType::TypeInt:
+ case JavaType::TypeLong:
+ case JavaType::TypeFloat:
+ case JavaType::TypeDouble:
+ case JavaType::TypeChar: {
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
+ // requires raising a JavaScript exception.
+ jvalue null_value = {0};
+ result = null_value;
+ break;
+ }
+ case JavaType::TypeBoolean:
+ // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
+ // requires raising a JavaScript exception.
+ result.z = JNI_FALSE;
+ break;
+ case JavaType::TypeArray:
+ if (value->IsType(base::Value::TYPE_DICTIONARY)) {
+ result.l = CoerceJavaScriptDictionaryToArray(
+ env, value, target_type, object_refs, error);
+ } else if (value->IsType(base::Value::TYPE_LIST)) {
+ result.l = CoerceJavaScriptListToArray(
+ env, value, target_type, object_refs, error);
+ } else {
+ result.l = NULL;
+ }
+ break;
+ case JavaType::TypeVoid:
+ // Conversion to void must never happen.
+ NOTREACHED();
+ break;
+ }
+ return result;
+}
+
+jvalue CoerceGinJavaBridgeValueToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ const ObjectRefs& object_refs,
+ GinJavaBridgeError* error) {
+ DCHECK(GinJavaBridgeValue::ContainsGinJavaBridgeValue(value));
+ scoped_ptr<const GinJavaBridgeValue> gin_value(
+ GinJavaBridgeValue::FromValue(value));
+ switch (gin_value->GetType()) {
+ case GinJavaBridgeValue::TYPE_UNDEFINED:
+ return CoerceJavaScriptNullOrUndefinedToJavaValue(
+ env, value, target_type, coerce_to_string, error);
+ case GinJavaBridgeValue::TYPE_NONFINITE: {
+ float float_value;
+ gin_value->GetAsNonFinite(&float_value);
+ return CoerceJavaScriptDoubleToJavaValue(
+ env, float_value, target_type, coerce_to_string, error);
+ }
+ case GinJavaBridgeValue::TYPE_OBJECT_ID:
+ return CoerceJavaScriptObjectToJavaValue(
+ env, value, target_type, coerce_to_string, object_refs, error);
+ default:
+ NOTREACHED();
+ }
+ return jvalue();
+}
+
+} // namespace
+
+
+void ReleaseJavaValueIfRequired(JNIEnv* env,
+ jvalue* value,
+ const JavaType& type) {
+ if (type.type == JavaType::TypeString || type.type == JavaType::TypeObject ||
+ type.type == JavaType::TypeArray) {
+ env->DeleteLocalRef(value->l);
+ value->l = NULL;
+ }
+}
+
+jvalue CoerceJavaScriptValueToJavaValue(JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ const ObjectRefs& object_refs,
+ GinJavaBridgeError* error) {
+ // Note that in all these conversions, the relevant field of the jvalue must
+ // always be explicitly set, as jvalue does not initialize its fields.
+
+ switch (value->GetType()) {
+ case base::Value::TYPE_INTEGER:
+ return CoerceJavaScriptIntegerToJavaValue(
+ env, value, target_type, coerce_to_string, error);
+ case base::Value::TYPE_DOUBLE: {
+ double double_value;
+ value->GetAsDouble(&double_value);
+ return CoerceJavaScriptDoubleToJavaValue(
+ env, double_value, target_type, coerce_to_string, error);
+ }
+ case base::Value::TYPE_BOOLEAN:
+ return CoerceJavaScriptBooleanToJavaValue(
+ env, value, target_type, coerce_to_string, error);
+ case base::Value::TYPE_STRING:
+ return CoerceJavaScriptStringToJavaValue(env, value, target_type, error);
+ case base::Value::TYPE_DICTIONARY:
+ case base::Value::TYPE_LIST:
+ return CoerceJavaScriptObjectToJavaValue(
+ env, value, target_type, coerce_to_string, object_refs, error);
+ case base::Value::TYPE_NULL:
+ return CoerceJavaScriptNullOrUndefinedToJavaValue(
+ env, value, target_type, coerce_to_string, error);
+ case base::Value::TYPE_BINARY:
+ return CoerceGinJavaBridgeValueToJavaValue(
+ env, value, target_type, coerce_to_string, object_refs, error);
+ }
+ NOTREACHED();
+ return jvalue();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.h b/chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.h
new file mode 100644
index 00000000000..5b8fc7514b6
--- /dev/null
+++ b/chromium/content/browser/android/java/gin_java_script_to_java_types_coercion.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_SCRIPT_TO_JAVA_TYPES_COERCION_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_SCRIPT_TO_JAVA_TYPES_COERCION_H_
+
+#include <map>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/values.h"
+#include "content/browser/android/java/gin_java_bound_object.h"
+#include "content/browser/android/java/java_type.h"
+#include "content/common/android/gin_java_bridge_errors.h"
+
+namespace content {
+
+typedef std::map<GinJavaBoundObject::ObjectID, JavaObjectWeakGlobalRef>
+ ObjectRefs;
+
+jvalue CoerceJavaScriptValueToJavaValue(
+ JNIEnv* env,
+ const base::Value* value,
+ const JavaType& target_type,
+ bool coerce_to_string,
+ const ObjectRefs& object_refs,
+ GinJavaBridgeError* error);
+
+void ReleaseJavaValueIfRequired(JNIEnv* env,
+ jvalue* value,
+ const JavaType& type);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_GIN_JAVA_SCRIPT_TO_JAVA_TYPES_COERCION_H_
diff --git a/chromium/content/browser/android/java/java_method.cc b/chromium/content/browser/android/java/java_method.cc
new file mode 100644
index 00000000000..9da0102cf33
--- /dev/null
+++ b/chromium/content/browser/android/java/java_method.cc
@@ -0,0 +1,209 @@
+// Copyright 2014 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 "content/browser/android/java/java_method.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/lazy_instance.h"
+#include "base/memory/singleton.h"
+#include "content/browser/android/java/jni_helper.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::GetClass;
+using base::android::MethodID;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace content {
+namespace {
+
+const char kGetName[] = "getName";
+const char kGetDeclaringClass[] = "getDeclaringClass";
+const char kGetModifiers[] = "getModifiers";
+const char kGetParameterTypes[] = "getParameterTypes";
+const char kGetReturnType[] = "getReturnType";
+const char kIntegerReturningBoolean[] = "(I)Z";
+const char kIsStatic[] = "isStatic";
+const char kJavaLangClass[] = "java/lang/Class";
+const char kJavaLangReflectMethod[] = "java/lang/reflect/Method";
+const char kJavaLangReflectModifier[] = "java/lang/reflect/Modifier";
+const char kReturningInteger[] = "()I";
+const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
+const char kReturningJavaLangClassArray[] = "()[Ljava/lang/Class;";
+const char kReturningJavaLangString[] = "()Ljava/lang/String;";
+
+struct ModifierClassTraits :
+ public base::internal::LeakyLazyInstanceTraits<ScopedJavaGlobalRef<
+ jclass> > {
+ static ScopedJavaGlobalRef<jclass>* New(void* instance) {
+ JNIEnv* env = AttachCurrentThread();
+ // Use placement new to initialize our instance in our preallocated space.
+ return new (instance) ScopedJavaGlobalRef<jclass>(
+ GetClass(env, kJavaLangReflectModifier));
+ }
+};
+
+base::LazyInstance<ScopedJavaGlobalRef<jclass>, ModifierClassTraits>
+ g_java_lang_reflect_modifier_class = LAZY_INSTANCE_INITIALIZER;
+
+std::string BinaryNameToJNISignature(const std::string& binary_name,
+ JavaType* type) {
+ DCHECK(type);
+ *type = JavaType::CreateFromBinaryName(binary_name);
+ return type->JNISignature();
+}
+
+} // namespace
+
+JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method)
+ : java_method_(method),
+ have_calculated_num_parameters_(false),
+ id_(NULL) {
+ JNIEnv* env = AttachCurrentThread();
+ // On construction, we do nothing except get the name. Everything else is
+ // done lazily.
+ ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
+ env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangReflectMethod,
+ kGetName,
+ kReturningJavaLangString))));
+ name_ = ConvertJavaStringToUTF8(name);
+}
+
+JavaMethod::~JavaMethod() {
+}
+
+size_t JavaMethod::num_parameters() const {
+ EnsureNumParametersIsSetUp();
+ return num_parameters_;
+}
+
+bool JavaMethod::is_static() const {
+ EnsureTypesAndIDAreSetUp();
+ return is_static_;
+}
+
+const JavaType& JavaMethod::parameter_type(size_t index) const {
+ EnsureTypesAndIDAreSetUp();
+ return parameter_types_[index];
+}
+
+const JavaType& JavaMethod::return_type() const {
+ EnsureTypesAndIDAreSetUp();
+ return return_type_;
+}
+
+jmethodID JavaMethod::id() const {
+ EnsureTypesAndIDAreSetUp();
+ return id_;
+}
+
+void JavaMethod::EnsureNumParametersIsSetUp() const {
+ if (have_calculated_num_parameters_) {
+ return;
+ }
+ have_calculated_num_parameters_ = true;
+
+ // The number of parameters will be used frequently when determining
+ // whether to call this method. We don't get the ID etc until actually
+ // required.
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jarray> parameters(env, static_cast<jarray>(
+ env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangReflectMethod,
+ kGetParameterTypes,
+ kReturningJavaLangClassArray))));
+ num_parameters_ = env->GetArrayLength(parameters.obj());
+}
+
+void JavaMethod::EnsureTypesAndIDAreSetUp() const {
+ if (id_) {
+ return;
+ }
+
+ // Get the parameters
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobjectArray> parameters(env, static_cast<jobjectArray>(
+ env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangReflectMethod,
+ kGetParameterTypes,
+ kReturningJavaLangClassArray))));
+ // Usually, this will already have been called.
+ EnsureNumParametersIsSetUp();
+ DCHECK_EQ(num_parameters_,
+ static_cast<size_t>(env->GetArrayLength(parameters.obj())));
+
+ // Java gives us the argument type using an extended version of the 'binary
+ // name'. See
+ // http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Class.html#getName().
+ // If we build the signature now, there's no need to store the binary name
+ // of the arguments. We just store the simple type.
+ std::string signature("(");
+
+ // Form the signature and record the parameter types.
+ parameter_types_.resize(num_parameters_);
+ for (size_t i = 0; i < num_parameters_; ++i) {
+ ScopedJavaLocalRef<jobject> parameter(env, env->GetObjectArrayElement(
+ parameters.obj(), i));
+ ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
+ env->CallObjectMethod(parameter.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangClass,
+ kGetName,
+ kReturningJavaLangString))));
+ std::string name_utf8 = ConvertJavaStringToUTF8(name);
+ signature += BinaryNameToJNISignature(name_utf8, &parameter_types_[i]);
+ }
+ signature += ")";
+
+ // Get the return type
+ ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>(
+ env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangReflectMethod,
+ kGetReturnType,
+ kReturningJavaLangClass))));
+ ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
+ env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangClass,
+ kGetName,
+ kReturningJavaLangString))));
+ signature += BinaryNameToJNISignature(ConvertJavaStringToUTF8(name),
+ &return_type_);
+
+ // Determine whether the method is static.
+ jint modifiers = env->CallIntMethod(
+ java_method_.obj(), GetMethodIDFromClassName(env,
+ kJavaLangReflectMethod,
+ kGetModifiers,
+ kReturningInteger));
+ is_static_ = env->CallStaticBooleanMethod(
+ g_java_lang_reflect_modifier_class.Get().obj(),
+ MethodID::Get<MethodID::TYPE_STATIC>(
+ env, g_java_lang_reflect_modifier_class.Get().obj(), kIsStatic,
+ kIntegerReturningBoolean),
+ modifiers);
+
+ // Get the ID for this method.
+ ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>(
+ env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
+ env,
+ kJavaLangReflectMethod,
+ kGetDeclaringClass,
+ kReturningJavaLangClass))));
+ id_ = is_static_ ?
+ MethodID::Get<MethodID::TYPE_STATIC>(
+ env, declaring_class.obj(), name_.c_str(), signature.c_str()) :
+ MethodID::Get<MethodID::TYPE_INSTANCE>(
+ env, declaring_class.obj(), name_.c_str(), signature.c_str());
+ java_method_.Reset();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/java_method.h b/chromium/content/browser/android/java/java_method.h
new file mode 100644
index 00000000000..b5ba26a6f5f
--- /dev/null
+++ b/chromium/content/browser/android/java/java_method.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_JAVA_METHOD_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_JAVA_METHOD_H_
+
+#include <jni.h>
+#include <string>
+#include <vector>
+
+#include "base/android/scoped_java_ref.h"
+#include "content/browser/android/java/java_type.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Wrapper around java.lang.reflect.Method. This class must be used on a single
+// thread only.
+class CONTENT_EXPORT JavaMethod {
+ public:
+ explicit JavaMethod(const base::android::JavaRef<jobject>& method);
+ ~JavaMethod();
+
+ const std::string& name() const { return name_; }
+ size_t num_parameters() const;
+ bool is_static() const;
+ const JavaType& parameter_type(size_t index) const;
+ const JavaType& return_type() const;
+ jmethodID id() const;
+
+ private:
+ void EnsureNumParametersIsSetUp() const;
+ void EnsureTypesAndIDAreSetUp() const;
+
+ std::string name_;
+ mutable base::android::ScopedJavaGlobalRef<jobject> java_method_;
+ mutable bool have_calculated_num_parameters_;
+ mutable size_t num_parameters_;
+ mutable std::vector<JavaType> parameter_types_;
+ mutable JavaType return_type_;
+ mutable bool is_static_;
+ mutable jmethodID id_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JavaMethod);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_JAVA_METHOD_H_
diff --git a/chromium/content/browser/android/java/java_type.cc b/chromium/content/browser/android/java/java_type.cc
new file mode 100644
index 00000000000..5cd9b545435
--- /dev/null
+++ b/chromium/content/browser/android/java/java_type.cc
@@ -0,0 +1,165 @@
+// Copyright 2014 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 "content/browser/android/java/java_type.h"
+
+#include "base/logging.h"
+#include "base/strings/string_util.h" // For ReplaceSubstringsAfterOffset
+
+namespace content {
+namespace {
+
+// Array component type names are similar to JNI type names, except for using
+// dots as namespace separators in class names.
+scoped_ptr<JavaType> CreateFromArrayComponentTypeName(
+ const std::string& type_name) {
+ scoped_ptr<JavaType> result(new JavaType());
+ DCHECK(!type_name.empty());
+ switch (type_name[0]) {
+ case 'Z':
+ result->type = JavaType::TypeBoolean;
+ break;
+ case 'B':
+ result->type = JavaType::TypeByte;
+ break;
+ case 'C':
+ result->type = JavaType::TypeChar;
+ break;
+ case 'S':
+ result->type = JavaType::TypeShort;
+ break;
+ case 'I':
+ result->type = JavaType::TypeInt;
+ break;
+ case 'J':
+ result->type = JavaType::TypeLong;
+ break;
+ case 'F':
+ result->type = JavaType::TypeFloat;
+ break;
+ case 'D':
+ result->type = JavaType::TypeDouble;
+ break;
+ case '[':
+ result->type = JavaType::TypeArray;
+ result->inner_type =
+ CreateFromArrayComponentTypeName(type_name.substr(1));
+ break;
+ case 'L':
+ if (type_name == "Ljava.lang.String;") {
+ result->type = JavaType::TypeString;
+ result->class_jni_name = "java/lang/String";
+ } else {
+ result->type = JavaType::TypeObject;
+ result->class_jni_name = type_name.substr(1, type_name.length() - 2);
+ ReplaceSubstringsAfterOffset(&result->class_jni_name, 0, ".", "/");
+ }
+ break;
+ default:
+ // Includes void (V).
+ NOTREACHED();
+ }
+ return result.Pass();
+}
+
+} // namespace
+
+JavaType::JavaType() {
+}
+
+JavaType::JavaType(const JavaType& other) {
+ *this = other;
+}
+
+JavaType::~JavaType() {
+}
+
+JavaType& JavaType::operator=(const JavaType& other) {
+ if (this == &other)
+ return *this;
+ type = other.type;
+ if (other.inner_type) {
+ DCHECK_EQ(JavaType::TypeArray, type);
+ inner_type.reset(new JavaType(*other.inner_type));
+ } else {
+ inner_type.reset();
+ }
+ class_jni_name = other.class_jni_name;
+ return *this;
+}
+
+// static
+JavaType JavaType::CreateFromBinaryName(const std::string& binary_name) {
+ JavaType result;
+ DCHECK(!binary_name.empty());
+ if (binary_name == "boolean") {
+ result.type = JavaType::TypeBoolean;
+ } else if (binary_name == "byte") {
+ result.type = JavaType::TypeByte;
+ } else if (binary_name == "char") {
+ result.type = JavaType::TypeChar;
+ } else if (binary_name == "short") {
+ result.type = JavaType::TypeShort;
+ } else if (binary_name == "int") {
+ result.type = JavaType::TypeInt;
+ } else if (binary_name == "long") {
+ result.type = JavaType::TypeLong;
+ } else if (binary_name == "float") {
+ result.type = JavaType::TypeFloat;
+ } else if (binary_name == "double") {
+ result.type = JavaType::TypeDouble;
+ } else if (binary_name == "void") {
+ result.type = JavaType::TypeVoid;
+ } else if (binary_name[0] == '[') {
+ result.type = JavaType::TypeArray;
+ result.inner_type = CreateFromArrayComponentTypeName(binary_name.substr(1));
+ } else if (binary_name == "java.lang.String") {
+ result.type = JavaType::TypeString;
+ result.class_jni_name = "java/lang/String";
+ } else {
+ result.type = JavaType::TypeObject;
+ result.class_jni_name = binary_name;
+ ReplaceSubstringsAfterOffset(&result.class_jni_name, 0, ".", "/");
+ }
+ return result;
+}
+
+std::string JavaType::JNIName() const {
+ switch (type) {
+ case JavaType::TypeBoolean:
+ return "Z";
+ case JavaType::TypeByte:
+ return "B";
+ case JavaType::TypeChar:
+ return "C";
+ case JavaType::TypeShort:
+ return "S";
+ case JavaType::TypeInt:
+ return "I";
+ case JavaType::TypeLong:
+ return "J";
+ case JavaType::TypeFloat:
+ return "F";
+ case JavaType::TypeDouble:
+ return "D";
+ case JavaType::TypeVoid:
+ return "V";
+ case JavaType::TypeArray:
+ return "[" + inner_type->JNISignature();
+ case JavaType::TypeString:
+ case JavaType::TypeObject:
+ return class_jni_name;
+ }
+ NOTREACHED();
+ return std::string();
+}
+
+std::string JavaType::JNISignature() const {
+ if (type == JavaType::TypeString || type == JavaType::TypeObject)
+ return "L" + JNIName() + ";";
+ else
+ return JNIName();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/java/java_type.h b/chromium/content/browser/android/java/java_type.h
new file mode 100644
index 00000000000..0ad12d69840
--- /dev/null
+++ b/chromium/content/browser/android/java/java_type.h
@@ -0,0 +1,57 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_JAVA_JAVA_TYPE_H_
+#define CONTENT_BROWSER_ANDROID_JAVA_JAVA_TYPE_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// The type of a Java value. A light-weight enum-like structure intended for
+// use by value and in STL containers.
+struct CONTENT_EXPORT JavaType {
+ JavaType();
+ JavaType(const JavaType& other);
+ ~JavaType();
+ JavaType& operator=(const JavaType& other);
+
+ // Java's reflection API represents types as a string using an extended
+ // 'binary name'.
+ static JavaType CreateFromBinaryName(const std::string& binary_name);
+
+ // JNIName is used with FindClass.
+ std::string JNIName() const;
+ // JNISignature is used for creating method signatures.
+ std::string JNISignature() const;
+
+ enum Type {
+ TypeBoolean,
+ TypeByte,
+ TypeChar,
+ TypeShort,
+ TypeInt,
+ TypeLong,
+ TypeFloat,
+ TypeDouble,
+ // This is only used as a return type, so we should never convert from
+ // JavaScript with this type.
+ TypeVoid,
+ TypeArray,
+ // We special-case strings, as they get special handling when coercing.
+ TypeString,
+ TypeObject,
+ };
+
+ Type type;
+ scoped_ptr<JavaType> inner_type; // Used for TypeArray only.
+ std::string class_jni_name; // Used for TypeString and TypeObject only.
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_JAVA_JAVA_TYPE_H_
diff --git a/chromium/content/browser/android/java/java_type_unittest.cc b/chromium/content/browser/android/java/java_type_unittest.cc
new file mode 100644
index 00000000000..484b3eb43a9
--- /dev/null
+++ b/chromium/content/browser/android/java/java_type_unittest.cc
@@ -0,0 +1,86 @@
+// Copyright 2014 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 "content/browser/android/java/java_type.h"
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class JavaTypeTest : public testing::Test {
+};
+
+TEST_F(JavaTypeTest, ScalarTypes) {
+ struct {
+ const char* binary_type;
+ JavaType::Type java_type;
+ const char* jni_name;
+ const char* jni_signature;
+ } scalar_types[] = {
+ {"boolean", JavaType::TypeBoolean, "Z", "Z"},
+ {"byte", JavaType::TypeByte, "B", "B"},
+ {"char", JavaType::TypeChar, "C", "C"},
+ {"short", JavaType::TypeShort, "S", "S"},
+ {"int", JavaType::TypeInt, "I", "I"},
+ {"long", JavaType::TypeLong, "J", "J"},
+ {"float", JavaType::TypeFloat, "F", "F"},
+ {"double", JavaType::TypeDouble, "D", "D"},
+ {"void", JavaType::TypeVoid, "V", "V"},
+ {"java.lang.String", JavaType::TypeString, "java/lang/String",
+ "Ljava/lang/String;"},
+ {"java.lang.Object", JavaType::TypeObject, "java/lang/Object",
+ "Ljava/lang/Object;"},
+ {"my.nested.Type$Foo", JavaType::TypeObject, "my/nested/Type$Foo",
+ "Lmy/nested/Type$Foo;"}};
+ for (size_t i = 0; i < arraysize(scalar_types); ++i) {
+ JavaType jt = JavaType::CreateFromBinaryName(scalar_types[i].binary_type);
+ EXPECT_EQ(scalar_types[i].java_type, jt.type);
+ EXPECT_FALSE(jt.inner_type);
+ EXPECT_EQ(scalar_types[i].jni_name, jt.JNIName());
+ EXPECT_EQ(scalar_types[i].jni_signature, jt.JNISignature());
+ }
+}
+
+TEST_F(JavaTypeTest, ArrayTypes) {
+ JavaType array_of_boolean = JavaType::CreateFromBinaryName("[Z");
+ EXPECT_EQ(JavaType::TypeArray, array_of_boolean.type);
+ EXPECT_TRUE(array_of_boolean.inner_type);
+ EXPECT_EQ(JavaType::TypeBoolean, array_of_boolean.inner_type->type);
+ EXPECT_FALSE(array_of_boolean.inner_type->inner_type);
+ EXPECT_EQ("[Z", array_of_boolean.JNIName());
+ EXPECT_EQ("[Z", array_of_boolean.JNISignature());
+
+ JavaType array_of_boolean_2d = JavaType::CreateFromBinaryName("[[Z");
+ EXPECT_EQ(JavaType::TypeArray, array_of_boolean_2d.type);
+ EXPECT_TRUE(array_of_boolean_2d.inner_type);
+ EXPECT_EQ(JavaType::TypeArray, array_of_boolean_2d.inner_type->type);
+ EXPECT_TRUE(array_of_boolean_2d.inner_type->inner_type);
+ EXPECT_EQ(JavaType::TypeBoolean,
+ array_of_boolean_2d.inner_type->inner_type->type);
+ EXPECT_FALSE(array_of_boolean_2d.inner_type->inner_type->inner_type);
+ EXPECT_EQ("[[Z", array_of_boolean_2d.JNIName());
+ EXPECT_EQ("[[Z", array_of_boolean_2d.JNISignature());
+
+ JavaType array_of_string =
+ JavaType::CreateFromBinaryName("[Ljava.lang.String;");
+ EXPECT_EQ(JavaType::TypeArray, array_of_string.type);
+ EXPECT_TRUE(array_of_string.inner_type);
+ EXPECT_EQ(JavaType::TypeString, array_of_string.inner_type->type);
+ EXPECT_FALSE(array_of_string.inner_type->inner_type);
+ EXPECT_EQ("[Ljava/lang/String;", array_of_string.JNIName());
+ EXPECT_EQ("[Ljava/lang/String;", array_of_string.JNISignature());
+
+ JavaType array_of_object =
+ JavaType::CreateFromBinaryName("[Ljava.lang.Object;");
+ EXPECT_EQ(JavaType::TypeArray, array_of_object.type);
+ EXPECT_TRUE(array_of_object.inner_type);
+ EXPECT_EQ(JavaType::TypeObject, array_of_object.inner_type->type);
+ EXPECT_FALSE(array_of_object.inner_type->inner_type);
+ EXPECT_EQ("[Ljava/lang/Object;", array_of_object.JNIName());
+ EXPECT_EQ("[Ljava/lang/Object;", array_of_object.JNISignature());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/overscroll_glow.cc b/chromium/content/browser/android/overscroll_glow.cc
index fb491f3ebaa..6df795a2db2 100644
--- a/chromium/content/browser/android/overscroll_glow.cc
+++ b/chromium/content/browser/android/overscroll_glow.cc
@@ -4,13 +4,8 @@
#include "content/browser/android/overscroll_glow.h"
-#include "base/debug/trace_event.h"
-#include "base/lazy_instance.h"
-#include "base/threading/worker_pool.h"
-#include "cc/layers/image_layer.h"
-#include "content/browser/android/edge_effect.h"
-#include "skia/ext/image_operations.h"
-#include "ui/gfx/android/java_bitmap.h"
+#include "cc/layers/layer.h"
+#include "content/browser/android/edge_effect_base.h"
using std::max;
using std::min;
@@ -20,56 +15,6 @@ namespace content {
namespace {
const float kEpsilon = 1e-3f;
-const int kScaledEdgeHeight = 12;
-const int kScaledGlowHeight = 64;
-const float kEdgeHeightAtMdpi = 12.f;
-const float kGlowHeightAtMdpi = 128.f;
-
-SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
- base::android::ScopedJavaLocalRef<jobject> jobj =
- gfx::CreateJavaBitmapFromAndroidResource(name, size);
- if (jobj.is_null())
- return SkBitmap();
-
- SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
- if (bitmap.isNull())
- return bitmap;
-
- return skia::ImageOperations::Resize(
- bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
-}
-
-class OverscrollResources {
- public:
- OverscrollResources() {
- TRACE_EVENT0("browser", "OverscrollResources::Create");
- edge_bitmap_ =
- CreateSkBitmapFromAndroidResource("android:drawable/overscroll_edge",
- gfx::Size(128, kScaledEdgeHeight));
- glow_bitmap_ =
- CreateSkBitmapFromAndroidResource("android:drawable/overscroll_glow",
- gfx::Size(128, kScaledGlowHeight));
- }
-
- const SkBitmap& edge_bitmap() const { return edge_bitmap_; }
- const SkBitmap& glow_bitmap() const { return glow_bitmap_; }
-
- private:
- SkBitmap edge_bitmap_;
- SkBitmap glow_bitmap_;
-
- DISALLOW_COPY_AND_ASSIGN(OverscrollResources);
-};
-
-// Leaky to allow access from a worker thread.
-base::LazyInstance<OverscrollResources>::Leaky g_overscroll_resources =
- LAZY_INSTANCE_INITIALIZER;
-
-scoped_refptr<cc::Layer> CreateImageLayer(const SkBitmap& bitmap) {
- scoped_refptr<cc::ImageLayer> layer = cc::ImageLayer::Create();
- layer->SetBitmap(bitmap);
- return layer;
-}
bool IsApproxZero(float value) {
return std::abs(value) < kEpsilon;
@@ -83,26 +28,60 @@ gfx::Vector2dF ZeroSmallComponents(gfx::Vector2dF vector) {
return vector;
}
-// Force loading of any necessary resources. This function is thread-safe.
-void EnsureResources() {
- g_overscroll_resources.Get();
+gfx::Transform ComputeTransform(OverscrollGlow::Edge edge,
+ const gfx::SizeF& window_size,
+ float offset) {
+ // Transforms assume the edge layers are anchored to their *top center point*.
+ switch (edge) {
+ case OverscrollGlow::EDGE_TOP:
+ return gfx::Transform(1, 0, 0, 1, 0, offset);
+ case OverscrollGlow::EDGE_LEFT:
+ return gfx::Transform(0,
+ 1,
+ -1,
+ 0,
+ -window_size.height() / 2.f + offset,
+ window_size.height() / 2.f);
+ case OverscrollGlow::EDGE_BOTTOM:
+ return gfx::Transform(-1, 0, 0, -1, 0, window_size.height() + offset);
+ case OverscrollGlow::EDGE_RIGHT:
+ return gfx::Transform(
+ 0,
+ -1,
+ 1,
+ 0,
+ -window_size.height() / 2.f + window_size.width() + offset,
+ window_size.height() / 2.f);
+ default:
+ NOTREACHED() << "Invalid edge: " << edge;
+ return gfx::Transform();
+ };
}
-} // namespace
+gfx::SizeF ComputeSize(OverscrollGlow::Edge edge,
+ const gfx::SizeF& window_size) {
+ switch (edge) {
+ case OverscrollGlow::EDGE_TOP:
+ case OverscrollGlow::EDGE_BOTTOM:
+ return window_size;
+ case OverscrollGlow::EDGE_LEFT:
+ case OverscrollGlow::EDGE_RIGHT:
+ return gfx::SizeF(window_size.height(), window_size.width());
+ default:
+ NOTREACHED() << "Invalid edge: " << edge;
+ return gfx::SizeF();
+ };
+}
-scoped_ptr<OverscrollGlow> OverscrollGlow::Create(bool enabled) {
- // Don't block the main thread with effect resource loading during creation.
- // Effect instantiation is deferred until the effect overscrolls, in which
- // case the main thread may block until the resource has loaded.
- if (enabled && g_overscroll_resources == NULL)
- base::WorkerPool::PostTask(FROM_HERE, base::Bind(EnsureResources), true);
+} // namespace
- return make_scoped_ptr(new OverscrollGlow(enabled));
+OverscrollGlow::OverscrollGlow(const EdgeEffectProvider& edge_effect_provider)
+ : edge_effect_provider_(edge_effect_provider),
+ enabled_(true),
+ initialized_(false) {
+ DCHECK(!edge_effect_provider_.is_null());
}
-OverscrollGlow::OverscrollGlow(bool enabled)
- : enabled_(enabled), initialized_(false) {}
-
OverscrollGlow::~OverscrollGlow() {
Detach();
}
@@ -117,7 +96,7 @@ void OverscrollGlow::Disable() {
enabled_ = false;
if (!enabled_ && initialized_) {
Detach();
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
+ for (size_t i = 0; i < EDGE_COUNT; ++i)
edge_effects_[i]->Finish();
}
}
@@ -126,7 +105,8 @@ bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer,
base::TimeTicks current_time,
gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF overscroll_delta,
- gfx::Vector2dF velocity) {
+ gfx::Vector2dF velocity,
+ gfx::Vector2dF displacement) {
DCHECK(overscrolling_layer);
if (!enabled_)
@@ -156,16 +136,11 @@ bool OverscrollGlow::OnOverscrolled(cc::Layer* overscrolling_layer,
bool y_overscroll_started =
!IsApproxZero(overscroll_delta.y()) && IsApproxZero(old_overscroll.y());
- if (x_overscroll_started)
- ReleaseAxis(AXIS_X, current_time);
- if (y_overscroll_started)
- ReleaseAxis(AXIS_Y, current_time);
-
velocity = ZeroSmallComponents(velocity);
if (!velocity.IsZero())
Absorb(current_time, velocity, x_overscroll_started, y_overscroll_started);
else
- Pull(current_time, overscroll_delta);
+ Pull(current_time, overscroll_delta, displacement);
UpdateLayerAttachment(overscrolling_layer);
return NeedsAnimate();
@@ -177,14 +152,13 @@ bool OverscrollGlow::Animate(base::TimeTicks current_time) {
return false;
}
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
+ for (size_t i = 0; i < EDGE_COUNT; ++i) {
if (edge_effects_[i]->Update(current_time)) {
+ Edge edge = static_cast<Edge>(i);
edge_effects_[i]->ApplyToLayers(
- display_params_.size,
- static_cast<EdgeEffect::Edge>(i),
- kEdgeHeightAtMdpi * display_params_.device_scale_factor,
- kGlowHeightAtMdpi * display_params_.device_scale_factor,
- display_params_.edge_offsets[i]);
+ ComputeSize(edge, display_params_.size),
+ ComputeTransform(
+ edge, display_params_.size, display_params_.edge_offsets[i]));
}
}
@@ -203,7 +177,7 @@ void OverscrollGlow::UpdateDisplayParameters(const DisplayParameters& params) {
bool OverscrollGlow::NeedsAnimate() const {
if (!enabled_ || !initialized_)
return false;
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
+ for (size_t i = 0; i < EDGE_COUNT; ++i) {
if (!edge_effects_[i]->IsFinished())
return true;
}
@@ -212,7 +186,7 @@ bool OverscrollGlow::NeedsAnimate() const {
void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) {
DCHECK(parent);
- if (!root_layer_)
+ if (!root_layer_.get())
return;
if (!NeedsAnimate()) {
@@ -222,10 +196,13 @@ void OverscrollGlow::UpdateLayerAttachment(cc::Layer* parent) {
if (root_layer_->parent() != parent)
parent->AddChild(root_layer_);
+
+ for (size_t i = 0; i < EDGE_COUNT; ++i)
+ edge_effects_[i]->SetParent(root_layer_.get());
}
void OverscrollGlow::Detach() {
- if (root_layer_)
+ if (root_layer_.get())
root_layer_->RemoveFromParent();
}
@@ -234,21 +211,11 @@ bool OverscrollGlow::InitializeIfNecessary() {
if (initialized_)
return true;
- const SkBitmap& edge = g_overscroll_resources.Get().edge_bitmap();
- const SkBitmap& glow = g_overscroll_resources.Get().glow_bitmap();
- if (edge.isNull() || glow.isNull()) {
- Disable();
- return false;
- }
-
- DCHECK(!root_layer_);
+ DCHECK(!root_layer_.get());
root_layer_ = cc::Layer::Create();
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
- scoped_refptr<cc::Layer> edge_layer = CreateImageLayer(edge);
- scoped_refptr<cc::Layer> glow_layer = CreateImageLayer(glow);
- root_layer_->AddChild(edge_layer);
- root_layer_->AddChild(glow_layer);
- edge_effects_[i] = make_scoped_ptr(new EdgeEffect(edge_layer, glow_layer));
+ for (size_t i = 0; i < EDGE_COUNT; ++i) {
+ edge_effects_[i] = edge_effect_provider_.Run();
+ DCHECK(edge_effects_[i]);
}
initialized_ = true;
@@ -256,49 +223,59 @@ bool OverscrollGlow::InitializeIfNecessary() {
}
void OverscrollGlow::Pull(base::TimeTicks current_time,
- gfx::Vector2dF overscroll_delta) {
+ const gfx::Vector2dF& overscroll_delta,
+ const gfx::Vector2dF& overscroll_location) {
DCHECK(enabled_ && initialized_);
- overscroll_delta = ZeroSmallComponents(overscroll_delta);
- if (overscroll_delta.IsZero())
- return;
+ DCHECK(!overscroll_delta.IsZero());
+ const float inv_width = 1.f / display_params_.size.width();
+ const float inv_height = 1.f / display_params_.size.height();
gfx::Vector2dF overscroll_pull =
- gfx::ScaleVector2d(overscroll_delta,
- 1.f / display_params_.size.width(),
- 1.f / display_params_.size.height());
- float edge_overscroll_pull[EdgeEffect::EDGE_COUNT] = {
+ gfx::ScaleVector2d(overscroll_delta, inv_width, inv_height);
+ const float edge_pull[EDGE_COUNT] = {
min(overscroll_pull.y(), 0.f), // Top
min(overscroll_pull.x(), 0.f), // Left
max(overscroll_pull.y(), 0.f), // Bottom
max(overscroll_pull.x(), 0.f) // Right
};
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
- if (!edge_overscroll_pull[i])
+ gfx::Vector2dF displacement =
+ gfx::ScaleVector2d(overscroll_location, inv_width, inv_height);
+ displacement.set_x(max(0.f, min(1.f, displacement.x())));
+ displacement.set_y(max(0.f, min(1.f, displacement.y())));
+ const float edge_displacement[EDGE_COUNT] = {
+ 1.f - displacement.x(), // Top
+ displacement.y(), // Left
+ displacement.x(), // Bottom
+ 1.f - displacement.y() // Right
+ };
+
+ for (size_t i = 0; i < EDGE_COUNT; ++i) {
+ if (!edge_pull[i])
continue;
- edge_effects_[i]->Pull(current_time, std::abs(edge_overscroll_pull[i]));
+ edge_effects_[i]->Pull(
+ current_time, std::abs(edge_pull[i]), edge_displacement[i]);
GetOppositeEdge(i)->Release(current_time);
}
}
void OverscrollGlow::Absorb(base::TimeTicks current_time,
- gfx::Vector2dF velocity,
+ const gfx::Vector2dF& velocity,
bool x_overscroll_started,
bool y_overscroll_started) {
DCHECK(enabled_ && initialized_);
- if (velocity.IsZero())
- return;
+ DCHECK(!velocity.IsZero());
// Only trigger on initial overscroll at a non-zero velocity
- const float overscroll_velocities[EdgeEffect::EDGE_COUNT] = {
+ const float overscroll_velocities[EDGE_COUNT] = {
y_overscroll_started ? min(velocity.y(), 0.f) : 0, // Top
x_overscroll_started ? min(velocity.x(), 0.f) : 0, // Left
y_overscroll_started ? max(velocity.y(), 0.f) : 0, // Bottom
x_overscroll_started ? max(velocity.x(), 0.f) : 0 // Right
};
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i) {
+ for (size_t i = 0; i < EDGE_COUNT; ++i) {
if (!overscroll_velocities[i])
continue;
@@ -309,31 +286,16 @@ void OverscrollGlow::Absorb(base::TimeTicks current_time,
void OverscrollGlow::Release(base::TimeTicks current_time) {
DCHECK(initialized_);
- for (size_t i = 0; i < EdgeEffect::EDGE_COUNT; ++i)
+ for (size_t i = 0; i < EDGE_COUNT; ++i)
edge_effects_[i]->Release(current_time);
}
-void OverscrollGlow::ReleaseAxis(Axis axis, base::TimeTicks current_time) {
- DCHECK(initialized_);
- switch (axis) {
- case AXIS_X:
- edge_effects_[EdgeEffect::EDGE_LEFT]->Release(current_time);
- edge_effects_[EdgeEffect::EDGE_RIGHT]->Release(current_time);
- break;
- case AXIS_Y:
- edge_effects_[EdgeEffect::EDGE_TOP]->Release(current_time);
- edge_effects_[EdgeEffect::EDGE_BOTTOM]->Release(current_time);
- break;
- };
-}
-
-EdgeEffect* OverscrollGlow::GetOppositeEdge(int edge_index) {
+EdgeEffectBase* OverscrollGlow::GetOppositeEdge(int edge_index) {
DCHECK(initialized_);
- return edge_effects_[(edge_index + 2) % EdgeEffect::EDGE_COUNT].get();
+ return edge_effects_[(edge_index + 2) % EDGE_COUNT].get();
}
-OverscrollGlow::DisplayParameters::DisplayParameters()
- : device_scale_factor(1) {
+OverscrollGlow::DisplayParameters::DisplayParameters() {
edge_offsets[0] = edge_offsets[1] = edge_offsets[2] = edge_offsets[3] = 0.f;
}
diff --git a/chromium/content/browser/android/overscroll_glow.h b/chromium/content/browser/android/overscroll_glow.h
index 0a555d41b7a..878d39aec12 100644
--- a/chromium/content/browser/android/overscroll_glow.h
+++ b/chromium/content/browser/android/overscroll_glow.h
@@ -5,32 +5,36 @@
#ifndef CONTENT_BROWSER_ANDROID_OVERSCROLL_GLOW_H_
#define CONTENT_BROWSER_ANDROID_OVERSCROLL_GLOW_H_
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
-#include "content/browser/android/edge_effect.h"
#include "ui/gfx/size_f.h"
#include "ui/gfx/vector2d_f.h"
-class SkBitmap;
-
namespace cc {
class Layer;
}
namespace content {
+class EdgeEffectBase;
+
/* |OverscrollGlow| mirrors its Android counterpart, OverscrollGlow.java.
* Conscious tradeoffs were made to align this as closely as possible with the
* original Android Java version.
*/
class OverscrollGlow {
public:
- // Create a new effect. If |enabled| is false, the effect will remain
- // deactivated until explicitly enabled.
- // Note: No resources will be allocated until the effect is both
- // enabled and an overscroll event has occurred.
- static scoped_ptr<OverscrollGlow> Create(bool enabled);
+ enum Edge { EDGE_TOP = 0, EDGE_LEFT, EDGE_BOTTOM, EDGE_RIGHT, EDGE_COUNT };
+
+ // Allows lazy creation of the edge effects.
+ typedef base::Callback<scoped_ptr<EdgeEffectBase>(void)> EdgeEffectProvider;
+
+ // |edge_effect_provider| must be valid for the duration of the effect's
+ // lifetime. The effect is enabled by default, but will remain dormant until
+ // the first overscroll event.
+ explicit OverscrollGlow(const EdgeEffectProvider& edge_effect_provider);
~OverscrollGlow();
@@ -50,7 +54,8 @@ class OverscrollGlow {
base::TimeTicks current_time,
gfx::Vector2dF accumulated_overscroll,
gfx::Vector2dF overscroll_delta,
- gfx::Vector2dF velocity);
+ gfx::Vector2dF velocity,
+ gfx::Vector2dF overscroll_location);
// Returns true if the effect still needs animation ticks.
// Note: The effect will detach itself when no further animation is required.
@@ -61,33 +66,31 @@ class OverscrollGlow {
struct DisplayParameters {
DisplayParameters();
gfx::SizeF size;
- float edge_offsets[EdgeEffect::EDGE_COUNT];
- float device_scale_factor;
+ float edge_offsets[EDGE_COUNT];
};
void UpdateDisplayParameters(const DisplayParameters& params);
-
private:
enum Axis { AXIS_X, AXIS_Y };
- OverscrollGlow(bool enabled);
-
// Returns whether the effect is initialized.
bool InitializeIfNecessary();
bool NeedsAnimate() const;
void UpdateLayerAttachment(cc::Layer* parent);
void Detach();
- void Pull(base::TimeTicks current_time, gfx::Vector2dF overscroll_delta);
+ void Pull(base::TimeTicks current_time,
+ const gfx::Vector2dF& overscroll_delta,
+ const gfx::Vector2dF& overscroll_location);
void Absorb(base::TimeTicks current_time,
- gfx::Vector2dF velocity,
+ const gfx::Vector2dF& velocity,
bool x_overscroll_started,
bool y_overscroll_started);
void Release(base::TimeTicks current_time);
- void ReleaseAxis(Axis axis, base::TimeTicks current_time);
- EdgeEffect* GetOppositeEdge(int edge_index);
+ EdgeEffectBase* GetOppositeEdge(int edge_index);
- scoped_ptr<EdgeEffect> edge_effects_[EdgeEffect::EDGE_COUNT];
+ EdgeEffectProvider edge_effect_provider_;
+ scoped_ptr<EdgeEffectBase> edge_effects_[EDGE_COUNT];
DisplayParameters display_params_;
bool enabled_;
diff --git a/chromium/content/browser/android/popup_item_type_list.h b/chromium/content/browser/android/popup_item_type_list.h
deleted file mode 100644
index 3f50490f610..00000000000
--- a/chromium/content/browser/android/popup_item_type_list.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 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 intentionally does not have header guards because this file
-// is meant to be included inside a macro to generate enum values.
-
-// This file contains a list of sync PopupItemTypes which describe the type
-// and enabled state of a select popup item. List is used by Android when
-// displaying a new select popup menu.
-
-#ifndef DEFINE_POPUP_ITEM_TYPE
-#error "Please define DEFINE_POPUP_ITEM_TYPE before including this file."
-#endif
-
-// Popup item is of type group
-DEFINE_POPUP_ITEM_TYPE(GROUP, 0)
-
-// Popup item is disabled
-DEFINE_POPUP_ITEM_TYPE(DISABLED, 1)
-
-// Popup item is enabled
-DEFINE_POPUP_ITEM_TYPE(ENABLED, 2)
diff --git a/chromium/content/browser/android/popup_touch_handle_drawable.cc b/chromium/content/browser/android/popup_touch_handle_drawable.cc
new file mode 100644
index 00000000000..8a7cf845f70
--- /dev/null
+++ b/chromium/content/browser/android/popup_touch_handle_drawable.cc
@@ -0,0 +1,87 @@
+// Copyright 2014 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 "content/browser/android/popup_touch_handle_drawable.h"
+
+#include "jni/PopupTouchHandleDrawable_jni.h"
+
+namespace content {
+
+PopupTouchHandleDrawable::PopupTouchHandleDrawable(
+ base::android::ScopedJavaLocalRef<jobject> drawable,
+ float dpi_scale)
+ : dpi_scale_(dpi_scale), drawable_(drawable) {
+ DCHECK(drawable.obj());
+}
+
+PopupTouchHandleDrawable::~PopupTouchHandleDrawable() {
+ // Explicitly disabling ensures that any external references to the Java
+ // object are cleared, allowing it to be GC'ed in a timely fashion.
+ SetEnabled(false);
+}
+
+void PopupTouchHandleDrawable::SetEnabled(bool enabled) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ if (enabled)
+ Java_PopupTouchHandleDrawable_show(env, drawable_.obj());
+ else
+ Java_PopupTouchHandleDrawable_hide(env, drawable_.obj());
+}
+
+void PopupTouchHandleDrawable::SetOrientation(
+ TouchHandleOrientation orientation) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ jobject obj = drawable_.obj();
+ switch (orientation) {
+ case TOUCH_HANDLE_LEFT:
+ Java_PopupTouchHandleDrawable_setLeftOrientation(env, obj);
+ break;
+
+ case TOUCH_HANDLE_RIGHT:
+ Java_PopupTouchHandleDrawable_setRightOrientation(env, obj);
+ break;
+
+ case TOUCH_HANDLE_CENTER:
+ Java_PopupTouchHandleDrawable_setCenterOrientation(env, obj);
+ break;
+
+ case TOUCH_HANDLE_ORIENTATION_UNDEFINED:
+ NOTREACHED() << "Invalid touch handle orientation.";
+ };
+}
+
+void PopupTouchHandleDrawable::SetAlpha(float alpha) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_PopupTouchHandleDrawable_setOpacity(env, drawable_.obj(), alpha);
+}
+
+void PopupTouchHandleDrawable::SetFocus(const gfx::PointF& position) {
+ const gfx::PointF position_pix = gfx::ScalePoint(position, dpi_scale_);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_PopupTouchHandleDrawable_setFocus(
+ env, drawable_.obj(), position_pix.x(), position_pix.y());
+}
+
+void PopupTouchHandleDrawable::SetVisible(bool visible) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_PopupTouchHandleDrawable_setVisible(env, drawable_.obj(), visible);
+}
+
+bool PopupTouchHandleDrawable::IntersectsWith(const gfx::RectF& rect) const {
+ const gfx::RectF rect_pix = gfx::ScaleRect(rect, dpi_scale_);
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return Java_PopupTouchHandleDrawable_intersectsWith(env,
+ drawable_.obj(),
+ rect_pix.x(),
+ rect_pix.y(),
+ rect_pix.width(),
+ rect_pix.height());
+}
+
+// static
+bool PopupTouchHandleDrawable::RegisterPopupTouchHandleDrawable(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/popup_touch_handle_drawable.h b/chromium/content/browser/android/popup_touch_handle_drawable.h
new file mode 100644
index 00000000000..0e1a8ea4d1c
--- /dev/null
+++ b/chromium/content/browser/android/popup_touch_handle_drawable.h
@@ -0,0 +1,40 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_POPUP_TOUCH_HANDLE_DRAWABLE_H_
+#define CONTENT_BROWSER_ANDROID_POPUP_TOUCH_HANDLE_DRAWABLE_H_
+
+#include "content/browser/renderer_host/input/touch_handle.h"
+
+#include "base/android/jni_android.h"
+
+namespace content {
+
+// Touch handle drawable backed by an Android PopupWindow.
+class PopupTouchHandleDrawable : public TouchHandleDrawable {
+ public:
+ PopupTouchHandleDrawable(base::android::ScopedJavaLocalRef<jobject> drawable,
+ float dpi_scale);
+ virtual ~PopupTouchHandleDrawable();
+
+ // TouchHandleDrawable implementation.
+ virtual void SetEnabled(bool enabled) override;
+ virtual void SetOrientation(TouchHandleOrientation orientation) override;
+ virtual void SetAlpha(float alpha) override;
+ virtual void SetFocus(const gfx::PointF& position) override;
+ virtual void SetVisible(bool visible) override;
+ virtual bool IntersectsWith(const gfx::RectF& rect) const override;
+
+ static bool RegisterPopupTouchHandleDrawable(JNIEnv* env);
+
+ private:
+ const float dpi_scale_;
+ base::android::ScopedJavaGlobalRef<jobject> drawable_;
+
+ DISALLOW_COPY_AND_ASSIGN(PopupTouchHandleDrawable);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_POPUP_TOUCH_HANDLE_DRAWABLE_H_
diff --git a/chromium/content/browser/android/surface_texture_peer_browser_impl.cc b/chromium/content/browser/android/surface_texture_peer_browser_impl.cc
deleted file mode 100644
index 4f61887f880..00000000000
--- a/chromium/content/browser/android/surface_texture_peer_browser_impl.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/android/surface_texture_peer_browser_impl.h"
-
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/media/android/browser_media_player_manager.h"
-#include "content/browser/media/media_web_contents_observer.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "media/base/android/media_player_android.h"
-#include "ui/gl/android/scoped_java_surface.h"
-
-namespace content {
-
-namespace {
-
-// Pass a java surface object to the MediaPlayerAndroid object
-// identified by render process handle, render frame ID and player ID.
-static void SetSurfacePeer(
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
- base::ProcessHandle render_process_handle,
- int render_frame_id,
- int player_id) {
- int render_process_id = 0;
- RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
- while (!it.IsAtEnd()) {
- if (it.GetCurrentValue()->GetHandle() == render_process_handle) {
- render_process_id = it.GetCurrentValue()->GetID();
- break;
- }
- it.Advance();
- }
- if (!render_process_id) {
- DVLOG(1) << "Cannot find render process for render_process_handle "
- << render_process_handle;
- return;
- }
-
- RenderFrameHostImpl* frame =
- RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
- if (!frame) {
- DVLOG(1) << "Cannot find frame for render_frame_id " << render_frame_id;
- return;
- }
-
- RenderViewHostImpl* view =
- static_cast<RenderViewHostImpl*>(frame->GetRenderViewHost());
- BrowserMediaPlayerManager* player_manager =
- view->media_web_contents_observer()->GetMediaPlayerManager(frame);
- if (!player_manager) {
- DVLOG(1) << "Cannot find the media player manager for frame " << frame;
- return;
- }
-
- media::MediaPlayerAndroid* player = player_manager->GetPlayer(player_id);
- if (!player) {
- DVLOG(1) << "Cannot find media player for player_id " << player_id;
- return;
- }
-
- if (player != player_manager->GetFullscreenPlayer()) {
- gfx::ScopedJavaSurface scoped_surface(surface_texture);
- player->SetVideoSurface(scoped_surface.Pass());
- }
-}
-
-} // anonymous namespace
-
-SurfaceTexturePeerBrowserImpl::SurfaceTexturePeerBrowserImpl() {
-}
-
-SurfaceTexturePeerBrowserImpl::~SurfaceTexturePeerBrowserImpl() {
-}
-
-void SurfaceTexturePeerBrowserImpl::EstablishSurfaceTexturePeer(
- base::ProcessHandle render_process_handle,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
- int render_frame_id,
- int player_id) {
- if (!surface_texture.get())
- return;
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
- &SetSurfacePeer, surface_texture, render_process_handle,
- render_frame_id, player_id));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/android/surface_texture_peer_browser_impl.h b/chromium/content/browser/android/surface_texture_peer_browser_impl.h
deleted file mode 100644
index ea3fd046553..00000000000
--- a/chromium/content/browser/android/surface_texture_peer_browser_impl.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_ANDROID_SURFACE_TEXTURE_PEER_BROWSER_IMPL_H_
-#define CONTENT_BROWSER_ANDROID_SURFACE_TEXTURE_PEER_BROWSER_IMPL_H_
-
-#include "base/compiler_specific.h"
-#include "content/common/android/surface_texture_peer.h"
-
-namespace content {
-
-// The SurfaceTexturePeer implementation for browser process.
-class SurfaceTexturePeerBrowserImpl : public SurfaceTexturePeer {
- public:
- // Construct a SurfaceTexturePeerBrowserImpl object. If
- // |player_in_render_process| is true, calling EstablishSurfaceTexturePeer()
- // will send the java surface texture object to the render process through
- // ChildProcessService. Otherwise, it will pass the surface texture
- // to the MediaPlayerBridge object in the browser process.
- SurfaceTexturePeerBrowserImpl();
- virtual ~SurfaceTexturePeerBrowserImpl();
-
- // SurfaceTexturePeer implementation.
- virtual void EstablishSurfaceTexturePeer(
- base::ProcessHandle render_process_handle,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
- int render_frame_id,
- int player_id) OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SurfaceTexturePeerBrowserImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_ANDROID_SURFACE_TEXTURE_PEER_BROWSER_IMPL_H_
diff --git a/chromium/content/browser/android/system_ui_resource_manager_impl.cc b/chromium/content/browser/android/system_ui_resource_manager_impl.cc
new file mode 100644
index 00000000000..57ef6f2055d
--- /dev/null
+++ b/chromium/content/browser/android/system_ui_resource_manager_impl.cc
@@ -0,0 +1,178 @@
+// Copyright 2014 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 "content/browser/android/system_ui_resource_manager_impl.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/debug/trace_event.h"
+#include "base/location.h"
+#include "base/observer_list.h"
+#include "base/threading/worker_pool.h"
+#include "cc/resources/ui_resource_bitmap.h"
+#include "content/public/browser/android/ui_resource_client_android.h"
+#include "content/public/browser/android/ui_resource_provider.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/screen.h"
+
+namespace content {
+namespace {
+
+SkBitmap CreateOverscrollGlowLBitmap(const gfx::Size& screen_size) {
+ const float kSin = 0.5f; // sin(PI / 6)
+ const float kCos = 0.866f; // cos(PI / 6);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setAlpha(0xBB);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ const float arc_width =
+ std::min(screen_size.width(), screen_size.height()) * 0.5f / kSin;
+ const float y = kCos * arc_width;
+ const float height = arc_width - y;
+ gfx::Size bounds(arc_width, height);
+ SkRect arc_rect = SkRect::MakeXYWH(
+ -arc_width / 2.f, -arc_width - y, arc_width * 2.f, arc_width * 2.f);
+ SkBitmap glow_bitmap;
+ glow_bitmap.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()));
+ glow_bitmap.eraseColor(SK_ColorTRANSPARENT);
+
+ SkCanvas canvas(glow_bitmap);
+ canvas.clipRect(SkRect::MakeXYWH(0, 0, bounds.width(), bounds.height()));
+ canvas.drawArc(arc_rect, 45, 90, true, paint);
+ return glow_bitmap;
+}
+
+void LoadBitmap(ui::SystemUIResourceManager::ResourceType type,
+ SkBitmap* bitmap_holder,
+ const gfx::Size& screen_size) {
+ TRACE_EVENT1(
+ "browser", "SystemUIResourceManagerImpl::LoadBitmap", "type", type);
+ SkBitmap bitmap;
+ switch (type) {
+ case ui::SystemUIResourceManager::OVERSCROLL_EDGE:
+ bitmap = gfx::CreateSkBitmapFromAndroidResource(
+ "android:drawable/overscroll_edge", gfx::Size(128, 12));
+ break;
+ case ui::SystemUIResourceManager::OVERSCROLL_GLOW:
+ bitmap = gfx::CreateSkBitmapFromAndroidResource(
+ "android:drawable/overscroll_glow", gfx::Size(128, 64));
+ break;
+ case ui::SystemUIResourceManager::OVERSCROLL_GLOW_L:
+ bitmap = CreateOverscrollGlowLBitmap(screen_size);
+ break;
+ }
+ bitmap.setImmutable();
+ *bitmap_holder = bitmap;
+}
+
+} // namespace
+
+class SystemUIResourceManagerImpl::Entry
+ : public content::UIResourceClientAndroid {
+ public:
+ explicit Entry(UIResourceProvider* provider) : id_(0), provider_(provider) {
+ DCHECK(provider);
+ }
+
+ virtual ~Entry() {
+ if (id_)
+ provider_->DeleteUIResource(id_);
+ id_ = 0;
+ }
+
+ void SetBitmap(const SkBitmap& bitmap) {
+ DCHECK(!bitmap.empty());
+ DCHECK(bitmap_.empty());
+ DCHECK(!id_);
+ bitmap_ = bitmap;
+ }
+
+ cc::UIResourceId GetUIResourceId() {
+ if (bitmap_.empty())
+ return 0;
+ if (!id_)
+ id_ = provider_->CreateUIResource(this);
+ return id_;
+ }
+
+ // content::UIResourceClient implementation.
+ virtual cc::UIResourceBitmap GetBitmap(cc::UIResourceId uid,
+ bool resource_lost) override {
+ DCHECK(!bitmap_.empty());
+ return cc::UIResourceBitmap(bitmap_);
+ }
+
+ // content::UIResourceClientAndroid implementation.
+ virtual void UIResourceIsInvalid() override { id_ = 0; }
+
+ const SkBitmap& bitmap() const { return bitmap_; }
+
+ private:
+ SkBitmap bitmap_;
+ cc::UIResourceId id_;
+ UIResourceProvider* provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(Entry);
+};
+
+SystemUIResourceManagerImpl::SystemUIResourceManagerImpl(
+ UIResourceProvider* ui_resource_provider)
+ : ui_resource_provider_(ui_resource_provider), weak_factory_(this) {
+}
+
+SystemUIResourceManagerImpl::~SystemUIResourceManagerImpl() {
+}
+
+void SystemUIResourceManagerImpl::PreloadResource(ResourceType type) {
+ GetEntry(type);
+}
+
+cc::UIResourceId SystemUIResourceManagerImpl::GetUIResourceId(
+ ResourceType type) {
+ return GetEntry(type)->GetUIResourceId();
+}
+
+SystemUIResourceManagerImpl::Entry* SystemUIResourceManagerImpl::GetEntry(
+ ResourceType type) {
+ DCHECK_GE(type, RESOURCE_TYPE_FIRST);
+ DCHECK_LE(type, RESOURCE_TYPE_LAST);
+ if (!resource_map_[type]) {
+ resource_map_[type].reset(new Entry(ui_resource_provider_));
+ // Lazily build the resource.
+ BuildResource(type);
+ }
+ return resource_map_[type].get();
+}
+
+void SystemUIResourceManagerImpl::BuildResource(ResourceType type) {
+ DCHECK(GetEntry(type)->bitmap().empty());
+
+ // Instead of blocking the main thread, we post a task to load the bitmap.
+ SkBitmap* bitmap = new SkBitmap();
+ gfx::Size screen_size =
+ gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().GetSizeInPixel();
+ base::Closure load_bitmap =
+ base::Bind(&LoadBitmap, type, bitmap, screen_size);
+ base::Closure finished_load =
+ base::Bind(&SystemUIResourceManagerImpl::OnFinishedLoadBitmap,
+ weak_factory_.GetWeakPtr(),
+ type,
+ base::Owned(bitmap));
+ base::WorkerPool::PostTaskAndReply(
+ FROM_HERE, load_bitmap, finished_load, true);
+}
+
+void SystemUIResourceManagerImpl::OnFinishedLoadBitmap(
+ ResourceType type,
+ SkBitmap* bitmap_holder) {
+ DCHECK(bitmap_holder);
+ GetEntry(type)->SetBitmap(*bitmap_holder);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/system_ui_resource_manager_impl.h b/chromium/content/browser/android/system_ui_resource_manager_impl.h
new file mode 100644
index 00000000000..54b2bd39d95
--- /dev/null
+++ b/chromium/content/browser/android/system_ui_resource_manager_impl.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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 CONTENT_BROWSER_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "ui/base/android/system_ui_resource_manager.h"
+
+class SkBitmap;
+
+namespace cc {
+class UIResourceBitmap;
+}
+
+namespace content {
+
+class UIResourceProvider;
+
+class CONTENT_EXPORT SystemUIResourceManagerImpl
+ : public ui::SystemUIResourceManager {
+ public:
+ explicit SystemUIResourceManagerImpl(
+ UIResourceProvider* ui_resource_provider);
+ virtual ~SystemUIResourceManagerImpl();
+
+ virtual void PreloadResource(ResourceType type) override;
+ virtual cc::UIResourceId GetUIResourceId(ResourceType type) override;
+
+ private:
+ friend class TestSystemUIResourceManagerImpl;
+ class Entry;
+
+ // Start loading the resource bitmap. virtual for testing.
+ virtual void BuildResource(ResourceType type);
+
+ Entry* GetEntry(ResourceType type);
+ void OnFinishedLoadBitmap(ResourceType, SkBitmap* bitmap_holder);
+
+ scoped_ptr<Entry> resource_map_[RESOURCE_TYPE_LAST + 1];
+ UIResourceProvider* ui_resource_provider_;
+
+ base::WeakPtrFactory<SystemUIResourceManagerImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemUIResourceManagerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_SYSTEM_UI_RESOURCE_MANAGER_IMPL_H_
diff --git a/chromium/content/browser/android/system_ui_resource_manager_impl_unittest.cc b/chromium/content/browser/android/system_ui_resource_manager_impl_unittest.cc
new file mode 100644
index 00000000000..5ab07fc3aa1
--- /dev/null
+++ b/chromium/content/browser/android/system_ui_resource_manager_impl_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright 2014 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 "cc/resources/ui_resource_bitmap.h"
+#include "content/browser/android/system_ui_resource_manager_impl.h"
+#include "content/public/browser/android/ui_resource_client_android.h"
+#include "content/public/browser/android/ui_resource_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+
+namespace content {
+
+class TestSystemUIResourceManagerImpl
+ : public content::SystemUIResourceManagerImpl {
+ public:
+ TestSystemUIResourceManagerImpl(content::UIResourceProvider* provider)
+ : SystemUIResourceManagerImpl(provider) {}
+
+ virtual ~TestSystemUIResourceManagerImpl() {}
+
+ virtual void BuildResource(
+ ui::SystemUIResourceManager::ResourceType type) override {}
+
+ void SetResourceAsLoaded(ui::SystemUIResourceManager::ResourceType type) {
+ SkBitmap small_bitmap;
+ SkCanvas canvas(small_bitmap);
+ small_bitmap.allocPixels(
+ SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType));
+ canvas.drawColor(SK_ColorWHITE);
+ small_bitmap.setImmutable();
+ OnFinishedLoadBitmap(type, &small_bitmap);
+ }
+};
+
+namespace {
+
+const ui::SystemUIResourceManager::ResourceType TEST_RESOURCE_TYPE =
+ ui::SystemUIResourceManager::OVERSCROLL_GLOW;
+
+class MockUIResourceProvider : public content::UIResourceProvider {
+ public:
+ MockUIResourceProvider()
+ : next_ui_resource_id_(1),
+ has_layer_tree_host_(true),
+ system_ui_resource_manager_(this) {}
+
+ virtual ~MockUIResourceProvider() {}
+
+ virtual cc::UIResourceId CreateUIResource(
+ content::UIResourceClientAndroid* client) override {
+ if (!has_layer_tree_host_)
+ return 0;
+ cc::UIResourceId id = next_ui_resource_id_++;
+ client->GetBitmap(id, false);
+ ui_resource_client_map_[id] = client;
+ return id;
+ }
+
+ virtual void DeleteUIResource(cc::UIResourceId id) override {
+ CHECK(has_layer_tree_host_);
+ ui_resource_client_map_.erase(id);
+ }
+
+ virtual bool SupportsETC1NonPowerOfTwo() const override { return true; }
+
+ void LayerTreeHostCleared() {
+ has_layer_tree_host_ = false;
+ UIResourceClientMap client_map = ui_resource_client_map_;
+ ui_resource_client_map_.clear();
+ for (UIResourceClientMap::iterator iter = client_map.begin();
+ iter != client_map.end();
+ iter++) {
+ iter->second->UIResourceIsInvalid();
+ }
+ }
+
+ void LayerTreeHostReturned() { has_layer_tree_host_ = true; }
+
+ TestSystemUIResourceManagerImpl& GetSystemUIResourceManager() {
+ return system_ui_resource_manager_;
+ }
+
+ cc::UIResourceId next_ui_resource_id() const { return next_ui_resource_id_; }
+
+ private:
+ typedef base::hash_map<cc::UIResourceId, content::UIResourceClientAndroid*>
+ UIResourceClientMap;
+
+ cc::UIResourceId next_ui_resource_id_;
+ UIResourceClientMap ui_resource_client_map_;
+ bool has_layer_tree_host_;
+
+ // The UIResourceProvider owns the SystemUIResourceManager.
+ TestSystemUIResourceManagerImpl system_ui_resource_manager_;
+};
+
+} // namespace
+
+class SystemUIResourceManagerImplTest : public testing::Test {
+ public:
+ void PreloadResource(ui::SystemUIResourceManager::ResourceType type) {
+ ui_resource_provider_.GetSystemUIResourceManager().PreloadResource(type);
+ }
+
+ cc::UIResourceId GetUIResourceId(
+ ui::SystemUIResourceManager::ResourceType type) {
+ return ui_resource_provider_.GetSystemUIResourceManager().GetUIResourceId(
+ type);
+ }
+
+ void LayerTreeHostCleared() { ui_resource_provider_.LayerTreeHostCleared(); }
+
+ void LayerTreeHostReturned() {
+ ui_resource_provider_.LayerTreeHostReturned();
+ }
+
+ void SetResourceAsLoaded(ui::SystemUIResourceManager::ResourceType type) {
+ ui_resource_provider_.GetSystemUIResourceManager().SetResourceAsLoaded(
+ type);
+ }
+
+ cc::UIResourceId GetNextUIResourceId() const {
+ return ui_resource_provider_.next_ui_resource_id();
+ }
+
+ private:
+ MockUIResourceProvider ui_resource_provider_;
+};
+
+TEST_F(SystemUIResourceManagerImplTest, GetResourceAfterBitmapLoaded) {
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+}
+
+TEST_F(SystemUIResourceManagerImplTest, GetResourceBeforeLoadBitmap) {
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+}
+
+TEST_F(SystemUIResourceManagerImplTest, PreloadEnsureResource) {
+ // Preloading the resource should trigger bitmap loading, but the actual
+ // resource id will not be generated until it is explicitly requested.
+ cc::UIResourceId first_resource_id = GetNextUIResourceId();
+ PreloadResource(TEST_RESOURCE_TYPE);
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_EQ(first_resource_id, GetNextUIResourceId());
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ EXPECT_NE(first_resource_id, GetNextUIResourceId());
+}
+
+TEST_F(SystemUIResourceManagerImplTest, ResetLayerTreeHost) {
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostCleared();
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostReturned();
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+
+ SetResourceAsLoaded(TEST_RESOURCE_TYPE);
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostCleared();
+ EXPECT_EQ(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+ LayerTreeHostReturned();
+ EXPECT_NE(0, GetUIResourceId(TEST_RESOURCE_TYPE));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/tracing_controller_android.cc b/chromium/content/browser/android/tracing_controller_android.cc
index a9c5b408147..4c40bb74297 100644
--- a/chromium/content/browser/android/tracing_controller_android.cc
+++ b/chromium/content/browser/android/tracing_controller_android.cc
@@ -32,17 +32,19 @@ void TracingControllerAndroid::Destroy(JNIEnv* env, jobject obj) {
bool TracingControllerAndroid::StartTracing(JNIEnv* env,
jobject obj,
jstring jcategories,
- jboolean record_continuously) {
+ jstring jtraceoptions) {
std::string categories =
base::android::ConvertJavaStringToUTF8(env, jcategories);
+ base::debug::TraceOptions trace_options;
+ trace_options.SetFromString(
+ base::android::ConvertJavaStringToUTF8(env, jtraceoptions));
// This log is required by adb_profile_chrome.py.
LOG(WARNING) << "Logging performance trace to file";
return TracingController::GetInstance()->EnableRecording(
- categories,
- record_continuously ? TracingController::RECORD_CONTINUOUSLY
- : TracingController::DEFAULT_OPTIONS,
+ base::debug::CategoryFilter(categories),
+ trace_options,
TracingController::EnableRecordingDoneCallback());
}
@@ -52,11 +54,12 @@ void TracingControllerAndroid::StopTracing(JNIEnv* env,
base::FilePath file_path(
base::android::ConvertJavaStringToUTF8(env, jfilepath));
if (!TracingController::GetInstance()->DisableRecording(
- file_path,
- base::Bind(&TracingControllerAndroid::OnTracingStopped,
- weak_factory_.GetWeakPtr()))) {
+ TracingController::CreateFileSink(
+ file_path,
+ base::Bind(&TracingControllerAndroid::OnTracingStopped,
+ weak_factory_.GetWeakPtr())))) {
LOG(ERROR) << "EndTracingAsync failed, forcing an immediate stop";
- OnTracingStopped(file_path);
+ OnTracingStopped();
}
}
@@ -69,8 +72,7 @@ void TracingControllerAndroid::GenerateTracingFilePath(
base::android::ConvertJavaStringToUTF8(env, jfilename.obj()));
}
-void TracingControllerAndroid::OnTracingStopped(
- const base::FilePath& file_path) {
+void TracingControllerAndroid::OnTracingStopped() {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jobject> obj = weak_java_object_.get(env);
if (obj.obj())
diff --git a/chromium/content/browser/android/tracing_controller_android.h b/chromium/content/browser/android/tracing_controller_android.h
index ab426d78997..58e6b94d36b 100644
--- a/chromium/content/browser/android/tracing_controller_android.h
+++ b/chromium/content/browser/android/tracing_controller_android.h
@@ -22,14 +22,14 @@ class TracingControllerAndroid {
bool StartTracing(JNIEnv* env,
jobject obj,
jstring categories,
- jboolean record_continuously);
+ jstring trace_options);
void StopTracing(JNIEnv* env, jobject obj, jstring jfilepath);
bool GetKnownCategoryGroupsAsync(JNIEnv* env, jobject obj);
static void GenerateTracingFilePath(base::FilePath* file_path);
private:
~TracingControllerAndroid();
- void OnTracingStopped(const base::FilePath& file_path);
+ void OnTracingStopped();
void OnKnownCategoriesReceived(
const std::set<std::string>& categories_received);
diff --git a/chromium/content/browser/android/ui_resource_provider_impl.cc b/chromium/content/browser/android/ui_resource_provider_impl.cc
index f97975cc81e..cd45d7cc634 100644
--- a/chromium/content/browser/android/ui_resource_provider_impl.cc
+++ b/chromium/content/browser/android/ui_resource_provider_impl.cc
@@ -10,7 +10,10 @@
namespace content {
-UIResourceProviderImpl::UIResourceProviderImpl() : host_(NULL) {
+UIResourceProviderImpl::UIResourceProviderImpl()
+ : system_ui_resource_manager_(this), host_(NULL),
+ supports_etc1_npot_(false) {
+
}
UIResourceProviderImpl::~UIResourceProviderImpl() {
@@ -57,4 +60,13 @@ void UIResourceProviderImpl::DeleteUIResource(cc::UIResourceId ui_resource_id) {
host_->DeleteUIResource(ui_resource_id);
}
+ui::SystemUIResourceManager&
+UIResourceProviderImpl::GetSystemUIResourceManager() {
+ return system_ui_resource_manager_;
+}
+
+bool UIResourceProviderImpl::SupportsETC1NonPowerOfTwo() const {
+ return supports_etc1_npot_;
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/ui_resource_provider_impl.h b/chromium/content/browser/android/ui_resource_provider_impl.h
index 79c23014d2d..1c29a3ed117 100644
--- a/chromium/content/browser/android/ui_resource_provider_impl.h
+++ b/chromium/content/browser/android/ui_resource_provider_impl.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_ANDROID_UI_RESOURCE_PROVIDER_IMPL_H_
#include "base/containers/hash_tables.h"
+#include "content/browser/android/system_ui_resource_manager_impl.h"
#include "content/public/browser/android/ui_resource_provider.h"
namespace cc {
@@ -27,16 +28,24 @@ class UIResourceProviderImpl : public UIResourceProvider {
void UIResourcesAreInvalid();
virtual cc::UIResourceId CreateUIResource(
- UIResourceClientAndroid* client) OVERRIDE;
+ UIResourceClientAndroid* client) override;
- virtual void DeleteUIResource(cc::UIResourceId resource_id) OVERRIDE;
+ virtual void DeleteUIResource(cc::UIResourceId resource_id) override;
+
+ ui::SystemUIResourceManager& GetSystemUIResourceManager();
+
+ void SetSupportsETC1NonPowerOfTwo(bool supports_etc1_npot) {
+ supports_etc1_npot_ = supports_etc1_npot;
+ }
+ virtual bool SupportsETC1NonPowerOfTwo() const override;
private:
typedef base::hash_map<cc::UIResourceId, UIResourceClientAndroid*>
UIResourceClientMap;
UIResourceClientMap ui_resource_client_map_;
-
+ SystemUIResourceManagerImpl system_ui_resource_manager_;
cc::LayerTreeHost* host_;
+ bool supports_etc1_npot_;
DISALLOW_COPY_AND_ASSIGN(UIResourceProviderImpl);
};
diff --git a/chromium/content/browser/android/web_contents_observer_android.cc b/chromium/content/browser/android/web_contents_observer_android.cc
index 0aa9c0b3dee..acadf8d85a3 100644
--- a/chromium/content/browser/android/web_contents_observer_android.cc
+++ b/chromium/content/browser/android/web_contents_observer_android.cc
@@ -15,7 +15,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
-#include "jni/WebContentsObserverAndroid_jni.h"
+#include "jni/WebContentsObserver_jni.h"
using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
@@ -24,6 +24,9 @@ using base::android::ConvertUTF16ToJavaString;
namespace content {
+// TODO(dcheng): File a bug. This class incorrectly passes just a frame ID,
+// which is not sufficient to identify a frame (since frame IDs are scoped per
+// render process, and so may collide).
WebContentsObserverAndroid::WebContentsObserverAndroid(
JNIEnv* env,
jobject obj,
@@ -36,8 +39,8 @@ WebContentsObserverAndroid::~WebContentsObserverAndroid() {
}
jlong Init(JNIEnv* env, jobject obj, jobject java_web_contents) {
- content::WebContents* web_contents =
- content::WebContents::FromJavaWebContents(java_web_contents);
+ WebContents* web_contents =
+ WebContents::FromJavaWebContents(java_web_contents);
CHECK(web_contents);
WebContentsObserverAndroid* native_observer = new WebContentsObserverAndroid(
@@ -56,7 +59,7 @@ void WebContentsObserverAndroid::WebContentsDestroyed() {
delete this;
} else {
// The java side will destroy |this|
- Java_WebContentsObserverAndroid_detachFromWebContents(env, obj.obj());
+ Java_WebContentsObserver_detachFromWebContents(env, obj.obj());
}
}
@@ -68,7 +71,7 @@ void WebContentsObserverAndroid::RenderProcessGone(
return;
jboolean was_oom_protected =
termination_status == base::TERMINATION_STATUS_OOM_PROTECTED;
- Java_WebContentsObserverAndroid_renderProcessGone(
+ Java_WebContentsObserver_renderProcessGone(
env, obj.obj(), was_oom_protected);
}
@@ -80,7 +83,7 @@ void WebContentsObserverAndroid::DidStartLoading(
return;
ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
env, web_contents()->GetVisibleURL().spec()));
- Java_WebContentsObserverAndroid_didStartLoading(
+ Java_WebContentsObserver_didStartLoading(
env, obj.obj(), jstring_url.obj());
}
@@ -92,31 +95,32 @@ void WebContentsObserverAndroid::DidStopLoading(
return;
ScopedJavaLocalRef<jstring> jstring_url(ConvertUTF8ToJavaString(
env, web_contents()->GetLastCommittedURL().spec()));
- Java_WebContentsObserverAndroid_didStopLoading(
+ Java_WebContentsObserver_didStopLoading(
env, obj.obj(), jstring_url.obj());
}
void WebContentsObserverAndroid::DidFailProvisionalLoad(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) {
- DidFailLoadInternal(
- true, is_main_frame, error_code, error_description, validated_url);
+ const base::string16& error_description) {
+ DidFailLoadInternal(true,
+ !render_frame_host->GetParent(),
+ error_code,
+ error_description,
+ validated_url);
}
void WebContentsObserverAndroid::DidFailLoad(
- int64 frame_id,
+ RenderFrameHost* render_frame_host,
const GURL& validated_url,
- bool is_main_frame,
int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) {
- DidFailLoadInternal(
- false, is_main_frame, error_code, error_description, validated_url);
+ const base::string16& error_description) {
+ DidFailLoadInternal(false,
+ !render_frame_host->GetParent(),
+ error_code,
+ error_description,
+ validated_url);
}
void WebContentsObserverAndroid::DidNavigateMainFrame(
@@ -144,12 +148,14 @@ void WebContentsObserverAndroid::DidNavigateMainFrame(
// that would also be valid for a fragment navigation.
bool is_fragment_navigation = urls_same_ignoring_fragment &&
(details.type == NAVIGATION_TYPE_IN_PAGE || details.is_in_page);
- Java_WebContentsObserverAndroid_didNavigateMainFrame(
+ Java_WebContentsObserver_didNavigateMainFrame(
env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
- details.is_navigation_to_different_page(), is_fragment_navigation);
+ details.is_navigation_to_different_page(), is_fragment_navigation,
+ details.http_status_code);
}
void WebContentsObserverAndroid::DidNavigateAnyFrame(
+ RenderFrameHost* render_frame_host,
const LoadCommittedDetails& details,
const FrameNavigateParams& params) {
JNIEnv* env = AttachCurrentThread();
@@ -160,56 +166,62 @@ void WebContentsObserverAndroid::DidNavigateAnyFrame(
ConvertUTF8ToJavaString(env, params.url.spec()));
ScopedJavaLocalRef<jstring> jstring_base_url(
ConvertUTF8ToJavaString(env, params.base_url.spec()));
- jboolean jboolean_is_reload =
- PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_RELOAD);
+ jboolean jboolean_is_reload = ui::PageTransitionCoreTypeIs(
+ params.transition, ui::PAGE_TRANSITION_RELOAD);
- Java_WebContentsObserverAndroid_didNavigateAnyFrame(
+ Java_WebContentsObserver_didNavigateAnyFrame(
env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
jboolean_is_reload);
}
void WebContentsObserverAndroid::DidStartProvisionalLoadForFrame(
- int64 frame_id,
- int64 parent_frame_id,
- bool is_main_frame,
- const GURL& validated_url,
- bool is_error_page,
- bool is_iframe_srcdoc,
- RenderViewHost* render_view_host) {
+ RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
ScopedJavaLocalRef<jstring> jstring_url(
ConvertUTF8ToJavaString(env, validated_url.spec()));
- Java_WebContentsObserverAndroid_didStartProvisionalLoadForFrame(
- env, obj.obj(), frame_id, parent_frame_id, is_main_frame,
- jstring_url.obj(), is_error_page, is_iframe_srcdoc);
+ // TODO(dcheng): Does Java really need the parent frame ID? It doesn't appear
+ // to be used at all, and it just adds complexity here.
+ Java_WebContentsObserver_didStartProvisionalLoadForFrame(
+ env,
+ obj.obj(),
+ render_frame_host->GetRoutingID(),
+ render_frame_host->GetParent()
+ ? render_frame_host->GetParent()->GetRoutingID()
+ : -1,
+ !render_frame_host->GetParent(),
+ jstring_url.obj(),
+ is_error_page,
+ is_iframe_srcdoc);
}
void WebContentsObserverAndroid::DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
- const GURL& url,
- PageTransition transition_type,
- RenderViewHost* render_view_host) {
+ RenderFrameHost* render_frame_host,
+ const GURL& url,
+ ui::PageTransition transition_type) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
ScopedJavaLocalRef<jstring> jstring_url(
ConvertUTF8ToJavaString(env, url.spec()));
- Java_WebContentsObserverAndroid_didCommitProvisionalLoadForFrame(
- env, obj.obj(), frame_id, is_main_frame, jstring_url.obj(),
+ Java_WebContentsObserver_didCommitProvisionalLoadForFrame(
+ env,
+ obj.obj(),
+ render_frame_host->GetRoutingID(),
+ !render_frame_host->GetParent(),
+ jstring_url.obj(),
transition_type);
}
void WebContentsObserverAndroid::DidFinishLoad(
- int64 frame_id,
- const GURL& validated_url,
- bool is_main_frame,
- RenderViewHost* render_view_host) {
+ RenderFrameHost* render_frame_host,
+ const GURL& validated_url) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
@@ -224,19 +236,22 @@ void WebContentsObserverAndroid::DidFinishLoad(
ScopedJavaLocalRef<jstring> jstring_url(
ConvertUTF8ToJavaString(env, url_string));
- Java_WebContentsObserverAndroid_didFinishLoad(
- env, obj.obj(), frame_id, jstring_url.obj(), is_main_frame);
+ Java_WebContentsObserver_didFinishLoad(
+ env,
+ obj.obj(),
+ render_frame_host->GetRoutingID(),
+ jstring_url.obj(),
+ !render_frame_host->GetParent());
}
void WebContentsObserverAndroid::DocumentLoadedInFrame(
- int64 frame_id,
- RenderViewHost* render_view_host) {
+ RenderFrameHost* render_frame_host) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- Java_WebContentsObserverAndroid_documentLoadedInFrame(
- env, obj.obj(), frame_id);
+ Java_WebContentsObserver_documentLoadedInFrame(
+ env, obj.obj(), render_frame_host->GetRoutingID());
}
void WebContentsObserverAndroid::NavigationEntryCommitted(
@@ -245,7 +260,7 @@ void WebContentsObserverAndroid::NavigationEntryCommitted(
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- Java_WebContentsObserverAndroid_navigationEntryCommitted(env, obj.obj());
+ Java_WebContentsObserver_navigationEntryCommitted(env, obj.obj());
}
void WebContentsObserverAndroid::DidAttachInterstitialPage() {
@@ -253,7 +268,7 @@ void WebContentsObserverAndroid::DidAttachInterstitialPage() {
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- Java_WebContentsObserverAndroid_didAttachInterstitialPage(env, obj.obj());
+ Java_WebContentsObserver_didAttachInterstitialPage(env, obj.obj());
}
void WebContentsObserverAndroid::DidDetachInterstitialPage() {
@@ -261,7 +276,7 @@ void WebContentsObserverAndroid::DidDetachInterstitialPage() {
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- Java_WebContentsObserverAndroid_didDetachInterstitialPage(env, obj.obj());
+ Java_WebContentsObserver_didDetachInterstitialPage(env, obj.obj());
}
void WebContentsObserverAndroid::DidChangeThemeColor(SkColor color) {
@@ -269,7 +284,7 @@ void WebContentsObserverAndroid::DidChangeThemeColor(SkColor color) {
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- Java_WebContentsObserverAndroid_didChangeThemeColor(env, obj.obj(), color);
+ Java_WebContentsObserver_didChangeThemeColor(env, obj.obj(), color);
}
void WebContentsObserverAndroid::DidFailLoadInternal(
@@ -287,7 +302,7 @@ void WebContentsObserverAndroid::DidFailLoadInternal(
ScopedJavaLocalRef<jstring> jstring_url(
ConvertUTF8ToJavaString(env, url.spec()));
- Java_WebContentsObserverAndroid_didFailLoad(
+ Java_WebContentsObserver_didFailLoad(
env, obj.obj(),
is_provisional_load,
is_main_frame,
@@ -300,7 +315,7 @@ void WebContentsObserverAndroid::DidFirstVisuallyNonEmptyPaint() {
ScopedJavaLocalRef<jobject> obj(weak_java_observer_.get(env));
if (obj.is_null())
return;
- Java_WebContentsObserverAndroid_didFirstVisuallyNonEmptyPaint(
+ Java_WebContentsObserver_didFirstVisuallyNonEmptyPaint(
env, obj.obj());
}
diff --git a/chromium/content/browser/android/web_contents_observer_android.h b/chromium/content/browser/android/web_contents_observer_android.h
index e13606c3812..429290321ff 100644
--- a/chromium/content/browser/android/web_contents_observer_android.h
+++ b/chromium/content/browser/android/web_contents_observer_android.h
@@ -33,55 +33,43 @@ class WebContentsObserverAndroid : public WebContentsObserver {
private:
virtual void RenderProcessGone(
- base::TerminationStatus termination_status) OVERRIDE;
- virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE;
- virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE;
+ base::TerminationStatus termination_status) override;
+ virtual void DidStartLoading(RenderViewHost* render_view_host) override;
+ virtual void DidStopLoading(RenderViewHost* render_view_host) override;
virtual void DidFailProvisionalLoad(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) OVERRIDE;
- virtual void DidFailLoad(int64 frame_id,
+ const base::string16& error_description) override;
+ virtual void DidFailLoad(RenderFrameHost* render_frame_host,
const GURL& validated_url,
- bool is_main_frame,
int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) OVERRIDE;
+ const base::string16& error_description) override;
virtual void DidNavigateMainFrame(const LoadCommittedDetails& details,
- const FrameNavigateParams& params) OVERRIDE;
- virtual void DidNavigateAnyFrame(const LoadCommittedDetails& details,
- const FrameNavigateParams& params) OVERRIDE;
- virtual void DidFirstVisuallyNonEmptyPaint() OVERRIDE;
+ const FrameNavigateParams& params) override;
+ virtual void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override;
+ virtual void DidFirstVisuallyNonEmptyPaint() override;
virtual void DidStartProvisionalLoadForFrame(
- int64 frame_id,
- int64 parent_frame_id,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& validated_url,
bool is_error_page,
- bool is_iframe_srcdoc,
- RenderViewHost* render_view_host) OVERRIDE;
+ bool is_iframe_srcdoc) override;
virtual void DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& url,
- PageTransition transition_type,
- RenderViewHost* render_view_host) OVERRIDE;
- virtual void DidFinishLoad(int64 frame_id,
- const GURL& validated_url,
- bool is_main_frame,
- RenderViewHost* render_view_host) OVERRIDE;
- virtual void DocumentLoadedInFrame(int64 frame_id,
- RenderViewHost* render_view_host) OVERRIDE;
+ ui::PageTransition transition_type) override;
+ virtual void DidFinishLoad(RenderFrameHost* render_frame_host,
+ const GURL& validated_url) override;
+ virtual void DocumentLoadedInFrame(
+ RenderFrameHost* render_frame_host) override;
virtual void NavigationEntryCommitted(
- const LoadCommittedDetails& load_details) OVERRIDE;
- virtual void WebContentsDestroyed() OVERRIDE;
- virtual void DidAttachInterstitialPage() OVERRIDE;
- virtual void DidDetachInterstitialPage() OVERRIDE;
- virtual void DidChangeThemeColor(SkColor color) OVERRIDE;
+ const LoadCommittedDetails& load_details) override;
+ virtual void WebContentsDestroyed() override;
+ virtual void DidAttachInterstitialPage() override;
+ virtual void DidDetachInterstitialPage() override;
+ virtual void DidChangeThemeColor(SkColor color) override;
void DidFailLoadInternal(bool is_provisional_load,
bool is_main_frame,
diff --git a/chromium/content/browser/appcache/DEPS b/chromium/content/browser/appcache/DEPS
new file mode 100644
index 00000000000..8608d5ff001
--- /dev/null
+++ b/chromium/content/browser/appcache/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+net/disk_cache",
+]
diff --git a/chromium/content/browser/appcache/appcache.cc b/chromium/content/browser/appcache/appcache.cc
new file mode 100644
index 00000000000..aa0b224bd7e
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache.cc
@@ -0,0 +1,327 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "content/browser/appcache/appcache_executable_handler.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/common/appcache_interfaces.h"
+
+namespace content {
+
+AppCache::AppCache(AppCacheStorage* storage, int64 cache_id)
+ : cache_id_(cache_id),
+ owning_group_(NULL),
+ online_whitelist_all_(false),
+ is_complete_(false),
+ cache_size_(0),
+ storage_(storage) {
+ storage_->working_set()->AddCache(this);
+}
+
+AppCache::~AppCache() {
+ DCHECK(associated_hosts_.empty());
+ if (owning_group_.get()) {
+ DCHECK(is_complete_);
+ owning_group_->RemoveCache(this);
+ }
+ DCHECK(!owning_group_.get());
+ storage_->working_set()->RemoveCache(this);
+ STLDeleteContainerPairSecondPointers(
+ executable_handlers_.begin(), executable_handlers_.end());
+}
+
+void AppCache::UnassociateHost(AppCacheHost* host) {
+ associated_hosts_.erase(host);
+}
+
+void AppCache::AddEntry(const GURL& url, const AppCacheEntry& entry) {
+ DCHECK(entries_.find(url) == entries_.end());
+ entries_.insert(EntryMap::value_type(url, entry));
+ cache_size_ += entry.response_size();
+}
+
+bool AppCache::AddOrModifyEntry(const GURL& url, const AppCacheEntry& entry) {
+ std::pair<EntryMap::iterator, bool> ret =
+ entries_.insert(EntryMap::value_type(url, entry));
+
+ // Entry already exists. Merge the types of the new and existing entries.
+ if (!ret.second)
+ ret.first->second.add_types(entry.types());
+ else
+ cache_size_ += entry.response_size(); // New entry. Add to cache size.
+ return ret.second;
+}
+
+void AppCache::RemoveEntry(const GURL& url) {
+ EntryMap::iterator found = entries_.find(url);
+ DCHECK(found != entries_.end());
+ cache_size_ -= found->second.response_size();
+ entries_.erase(found);
+}
+
+AppCacheEntry* AppCache::GetEntry(const GURL& url) {
+ EntryMap::iterator it = entries_.find(url);
+ return (it != entries_.end()) ? &(it->second) : NULL;
+}
+
+const AppCacheEntry* AppCache::GetEntryAndUrlWithResponseId(
+ int64 response_id, GURL* optional_url_out) {
+ for (EntryMap::const_iterator iter = entries_.begin();
+ iter != entries_.end(); ++iter) {
+ if (iter->second.response_id() == response_id) {
+ if (optional_url_out)
+ *optional_url_out = iter->first;
+ return &iter->second;
+ }
+ }
+ return NULL;
+}
+
+AppCacheExecutableHandler* AppCache::GetExecutableHandler(int64 response_id) {
+ HandlerMap::const_iterator found = executable_handlers_.find(response_id);
+ if (found != executable_handlers_.end())
+ return found->second;
+ return NULL;
+}
+
+AppCacheExecutableHandler* AppCache::GetOrCreateExecutableHandler(
+ int64 response_id, net::IOBuffer* handler_source) {
+ AppCacheExecutableHandler* handler = GetExecutableHandler(response_id);
+ if (handler)
+ return handler;
+
+ GURL handler_url;
+ const AppCacheEntry* entry = GetEntryAndUrlWithResponseId(
+ response_id, &handler_url);
+ if (!entry || !entry->IsExecutable())
+ return NULL;
+
+ DCHECK(storage_->service()->handler_factory());
+ scoped_ptr<AppCacheExecutableHandler> own_ptr =
+ storage_->service()->handler_factory()->
+ CreateHandler(handler_url, handler_source);
+ handler = own_ptr.release();
+ if (!handler)
+ return NULL;
+ executable_handlers_[response_id] = handler;
+ return handler;
+}
+
+GURL AppCache::GetNamespaceEntryUrl(const AppCacheNamespaceVector& namespaces,
+ const GURL& namespace_url) const {
+ size_t count = namespaces.size();
+ for (size_t i = 0; i < count; ++i) {
+ if (namespaces[i].namespace_url == namespace_url)
+ return namespaces[i].target_url;
+ }
+ NOTREACHED();
+ return GURL();
+}
+
+namespace {
+bool SortNamespacesByLength(
+ const AppCacheNamespace& lhs, const AppCacheNamespace& rhs) {
+ return lhs.namespace_url.spec().length() > rhs.namespace_url.spec().length();
+}
+}
+
+void AppCache::InitializeWithManifest(AppCacheManifest* manifest) {
+ DCHECK(manifest);
+ intercept_namespaces_.swap(manifest->intercept_namespaces);
+ fallback_namespaces_.swap(manifest->fallback_namespaces);
+ online_whitelist_namespaces_.swap(manifest->online_whitelist_namespaces);
+ online_whitelist_all_ = manifest->online_whitelist_all;
+
+ // Sort the namespaces by url string length, longest to shortest,
+ // since longer matches trump when matching a url to a namespace.
+ std::sort(intercept_namespaces_.begin(), intercept_namespaces_.end(),
+ SortNamespacesByLength);
+ std::sort(fallback_namespaces_.begin(), fallback_namespaces_.end(),
+ SortNamespacesByLength);
+}
+
+void AppCache::InitializeWithDatabaseRecords(
+ const AppCacheDatabase::CacheRecord& cache_record,
+ const std::vector<AppCacheDatabase::EntryRecord>& entries,
+ const std::vector<AppCacheDatabase::NamespaceRecord>& intercepts,
+ const std::vector<AppCacheDatabase::NamespaceRecord>& fallbacks,
+ const std::vector<AppCacheDatabase::OnlineWhiteListRecord>& whitelists) {
+ DCHECK(cache_id_ == cache_record.cache_id);
+ online_whitelist_all_ = cache_record.online_wildcard;
+ update_time_ = cache_record.update_time;
+
+ for (size_t i = 0; i < entries.size(); ++i) {
+ const AppCacheDatabase::EntryRecord& entry = entries.at(i);
+ AddEntry(entry.url, AppCacheEntry(entry.flags, entry.response_id,
+ entry.response_size));
+ }
+ DCHECK(cache_size_ == cache_record.cache_size);
+
+ for (size_t i = 0; i < intercepts.size(); ++i)
+ intercept_namespaces_.push_back(intercepts.at(i).namespace_);
+
+ for (size_t i = 0; i < fallbacks.size(); ++i)
+ fallback_namespaces_.push_back(fallbacks.at(i).namespace_);
+
+ // Sort the fallback namespaces by url string length, longest to shortest,
+ // since longer matches trump when matching a url to a namespace.
+ std::sort(intercept_namespaces_.begin(), intercept_namespaces_.end(),
+ SortNamespacesByLength);
+ std::sort(fallback_namespaces_.begin(), fallback_namespaces_.end(),
+ SortNamespacesByLength);
+
+ for (size_t i = 0; i < whitelists.size(); ++i) {
+ const AppCacheDatabase::OnlineWhiteListRecord& record = whitelists.at(i);
+ online_whitelist_namespaces_.push_back(
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE,
+ record.namespace_url,
+ GURL(),
+ record.is_pattern));
+ }
+}
+
+void AppCache::ToDatabaseRecords(
+ const AppCacheGroup* group,
+ AppCacheDatabase::CacheRecord* cache_record,
+ std::vector<AppCacheDatabase::EntryRecord>* entries,
+ std::vector<AppCacheDatabase::NamespaceRecord>* intercepts,
+ std::vector<AppCacheDatabase::NamespaceRecord>* fallbacks,
+ std::vector<AppCacheDatabase::OnlineWhiteListRecord>* whitelists) {
+ DCHECK(group && cache_record && entries && fallbacks && whitelists);
+ DCHECK(entries->empty() && fallbacks->empty() && whitelists->empty());
+
+ cache_record->cache_id = cache_id_;
+ cache_record->group_id = group->group_id();
+ cache_record->online_wildcard = online_whitelist_all_;
+ cache_record->update_time = update_time_;
+ cache_record->cache_size = 0;
+
+ for (EntryMap::const_iterator iter = entries_.begin();
+ iter != entries_.end(); ++iter) {
+ entries->push_back(AppCacheDatabase::EntryRecord());
+ AppCacheDatabase::EntryRecord& record = entries->back();
+ record.url = iter->first;
+ record.cache_id = cache_id_;
+ record.flags = iter->second.types();
+ record.response_id = iter->second.response_id();
+ record.response_size = iter->second.response_size();
+ cache_record->cache_size += record.response_size;
+ }
+
+ GURL origin = group->manifest_url().GetOrigin();
+
+ for (size_t i = 0; i < intercept_namespaces_.size(); ++i) {
+ intercepts->push_back(AppCacheDatabase::NamespaceRecord());
+ AppCacheDatabase::NamespaceRecord& record = intercepts->back();
+ record.cache_id = cache_id_;
+ record.origin = origin;
+ record.namespace_ = intercept_namespaces_[i];
+ }
+
+ for (size_t i = 0; i < fallback_namespaces_.size(); ++i) {
+ fallbacks->push_back(AppCacheDatabase::NamespaceRecord());
+ AppCacheDatabase::NamespaceRecord& record = fallbacks->back();
+ record.cache_id = cache_id_;
+ record.origin = origin;
+ record.namespace_ = fallback_namespaces_[i];
+ }
+
+ for (size_t i = 0; i < online_whitelist_namespaces_.size(); ++i) {
+ whitelists->push_back(AppCacheDatabase::OnlineWhiteListRecord());
+ AppCacheDatabase::OnlineWhiteListRecord& record = whitelists->back();
+ record.cache_id = cache_id_;
+ record.namespace_url = online_whitelist_namespaces_[i].namespace_url;
+ record.is_pattern = online_whitelist_namespaces_[i].is_pattern;
+ }
+}
+
+bool AppCache::FindResponseForRequest(const GURL& url,
+ AppCacheEntry* found_entry, GURL* found_intercept_namespace,
+ AppCacheEntry* found_fallback_entry, GURL* found_fallback_namespace,
+ bool* found_network_namespace) {
+ // Ignore fragments when looking up URL in the cache.
+ GURL url_no_ref;
+ if (url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url_no_ref = url.ReplaceComponents(replacements);
+ } else {
+ url_no_ref = url;
+ }
+
+ // 6.6.6 Changes to the networking model
+
+ AppCacheEntry* entry = GetEntry(url_no_ref);
+ if (entry) {
+ *found_entry = *entry;
+ return true;
+ }
+
+ *found_network_namespace = IsInNetworkNamespace(url_no_ref);
+ if (*found_network_namespace)
+ return true;
+
+ const AppCacheNamespace* intercept_namespace =
+ FindInterceptNamespace(url_no_ref);
+ if (intercept_namespace) {
+ entry = GetEntry(intercept_namespace->target_url);
+ DCHECK(entry);
+ *found_entry = *entry;
+ *found_intercept_namespace = intercept_namespace->namespace_url;
+ return true;
+ }
+
+ const AppCacheNamespace* fallback_namespace =
+ FindFallbackNamespace(url_no_ref);
+ if (fallback_namespace) {
+ entry = GetEntry(fallback_namespace->target_url);
+ DCHECK(entry);
+ *found_fallback_entry = *entry;
+ *found_fallback_namespace = fallback_namespace->namespace_url;
+ return true;
+ }
+
+ *found_network_namespace = online_whitelist_all_;
+ return *found_network_namespace;
+}
+
+
+void AppCache::ToResourceInfoVector(AppCacheResourceInfoVector* infos) const {
+ DCHECK(infos && infos->empty());
+ for (EntryMap::const_iterator iter = entries_.begin();
+ iter != entries_.end(); ++iter) {
+ infos->push_back(AppCacheResourceInfo());
+ AppCacheResourceInfo& info = infos->back();
+ info.url = iter->first;
+ info.is_master = iter->second.IsMaster();
+ info.is_manifest = iter->second.IsManifest();
+ info.is_intercept = iter->second.IsIntercept();
+ info.is_fallback = iter->second.IsFallback();
+ info.is_foreign = iter->second.IsForeign();
+ info.is_explicit = iter->second.IsExplicit();
+ info.size = iter->second.response_size();
+ info.response_id = iter->second.response_id();
+ }
+}
+
+// static
+const AppCacheNamespace* AppCache::FindNamespace(
+ const AppCacheNamespaceVector& namespaces,
+ const GURL& url) {
+ size_t count = namespaces.size();
+ for (size_t i = 0; i < count; ++i) {
+ if (namespaces[i].IsMatch(url))
+ return &namespaces[i];
+ }
+ return NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache.h b/chromium/content/browser/appcache/appcache.h
new file mode 100644
index 00000000000..a444579a64d
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache.h
@@ -0,0 +1,210 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "content/browser/appcache/appcache_database.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_manifest_parser.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace net {
+class IOBuffer;
+}
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheTest, InitializeWithManifest);
+FORWARD_DECLARE_TEST(AppCacheTest, ToFromDatabaseRecords);
+class AppCacheExecutableHandler;
+class AppCacheGroup;
+class AppCacheHost;
+class AppCacheStorage;
+class AppCacheTest;
+class AppCacheStorageImplTest;
+class AppCacheUpdateJobTest;
+
+// Set of cached resources for an application. A cache exists as long as a
+// host is associated with it, the cache is in an appcache group or the
+// cache is being created during an appcache upate.
+class CONTENT_EXPORT AppCache
+ : public base::RefCounted<AppCache> {
+ public:
+ typedef std::map<GURL, AppCacheEntry> EntryMap;
+ typedef std::set<AppCacheHost*> AppCacheHosts;
+
+ AppCache(AppCacheStorage* storage, int64 cache_id);
+
+ int64 cache_id() const { return cache_id_; }
+
+ AppCacheGroup* owning_group() const { return owning_group_.get(); }
+
+ bool is_complete() const { return is_complete_; }
+ void set_complete(bool value) { is_complete_ = value; }
+
+ // Adds a new entry. Entry must not already be in cache.
+ void AddEntry(const GURL& url, const AppCacheEntry& entry);
+
+ // Adds a new entry or modifies an existing entry by merging the types
+ // of the new entry with the existing entry. Returns true if a new entry
+ // is added, false if the flags are merged into an existing entry.
+ bool AddOrModifyEntry(const GURL& url, const AppCacheEntry& entry);
+
+ // Removes an entry from the EntryMap, the URL must be in the set.
+ void RemoveEntry(const GURL& url);
+
+ // Do not store or delete the returned ptr, they're owned by 'this'.
+ AppCacheEntry* GetEntry(const GURL& url);
+ const AppCacheEntry* GetEntryWithResponseId(int64 response_id) {
+ return GetEntryAndUrlWithResponseId(response_id, NULL);
+ }
+ const AppCacheEntry* GetEntryAndUrlWithResponseId(
+ int64 response_id, GURL* optional_url);
+ const EntryMap& entries() const { return entries_; }
+
+ // The AppCache owns the collection of executable handlers that have
+ // been started for this instance. The getter looks up an existing
+ // handler returning null if not found, the GetOrCreate method will
+ // cons one up if not found.
+ // Do not store the returned ptrs, they're owned by 'this'.
+ AppCacheExecutableHandler* GetExecutableHandler(int64 response_id);
+ AppCacheExecutableHandler* GetOrCreateExecutableHandler(
+ int64 response_id, net::IOBuffer* handler_source);
+
+ // Returns the URL of the resource used as entry for 'namespace_url'.
+ GURL GetFallbackEntryUrl(const GURL& namespace_url) const {
+ return GetNamespaceEntryUrl(fallback_namespaces_, namespace_url);
+ }
+ GURL GetInterceptEntryUrl(const GURL& namespace_url) const {
+ return GetNamespaceEntryUrl(intercept_namespaces_, namespace_url);
+ }
+
+ AppCacheHosts& associated_hosts() { return associated_hosts_; }
+
+ bool IsNewerThan(AppCache* cache) const {
+ // TODO(michaeln): revisit, the system clock can be set
+ // back in time which would confuse this logic.
+ if (update_time_ > cache->update_time_)
+ return true;
+
+ // Tie breaker. Newer caches have a larger cache ID.
+ if (update_time_ == cache->update_time_)
+ return cache_id_ > cache->cache_id_;
+
+ return false;
+ }
+
+ base::Time update_time() const { return update_time_; }
+
+ int64 cache_size() const { return cache_size_; }
+
+ void set_update_time(base::Time ticks) { update_time_ = ticks; }
+
+ // Initializes the cache with information in the manifest.
+ // Do not use the manifest after this call.
+ void InitializeWithManifest(AppCacheManifest* manifest);
+
+ // Initializes the cache with the information in the database records.
+ void InitializeWithDatabaseRecords(
+ const AppCacheDatabase::CacheRecord& cache_record,
+ const std::vector<AppCacheDatabase::EntryRecord>& entries,
+ const std::vector<AppCacheDatabase::NamespaceRecord>& intercepts,
+ const std::vector<AppCacheDatabase::NamespaceRecord>& fallbacks,
+ const std::vector<AppCacheDatabase::OnlineWhiteListRecord>& whitelists);
+
+ // Returns the database records to be stored in the AppCacheDatabase
+ // to represent this cache.
+ void ToDatabaseRecords(
+ const AppCacheGroup* group,
+ AppCacheDatabase::CacheRecord* cache_record,
+ std::vector<AppCacheDatabase::EntryRecord>* entries,
+ std::vector<AppCacheDatabase::NamespaceRecord>* intercepts,
+ std::vector<AppCacheDatabase::NamespaceRecord>* fallbacks,
+ std::vector<AppCacheDatabase::OnlineWhiteListRecord>* whitelists);
+
+ bool FindResponseForRequest(const GURL& url,
+ AppCacheEntry* found_entry, GURL* found_intercept_namespace,
+ AppCacheEntry* found_fallback_entry, GURL* found_fallback_namespace,
+ bool* found_network_namespace);
+
+ // Populates the 'infos' vector with an element per entry in the appcache.
+ void ToResourceInfoVector(AppCacheResourceInfoVector* infos) const;
+
+ static const AppCacheNamespace* FindNamespace(
+ const AppCacheNamespaceVector& namespaces,
+ const GURL& url);
+
+ private:
+ friend class AppCacheGroup;
+ friend class AppCacheHost;
+ friend class content::AppCacheTest;
+ friend class content::AppCacheStorageImplTest;
+ friend class content::AppCacheUpdateJobTest;
+ friend class base::RefCounted<AppCache>;
+
+ ~AppCache();
+
+ // Use AppCacheGroup::Add/RemoveCache() to manipulate owning group.
+ void set_owning_group(AppCacheGroup* group) { owning_group_ = group; }
+
+ // FindResponseForRequest helpers
+ const AppCacheNamespace* FindInterceptNamespace(const GURL& url) {
+ return FindNamespace(intercept_namespaces_, url);
+ }
+ const AppCacheNamespace* FindFallbackNamespace(const GURL& url) {
+ return FindNamespace(fallback_namespaces_, url);
+ }
+ bool IsInNetworkNamespace(const GURL& url) {
+ return FindNamespace(online_whitelist_namespaces_, url) != NULL;
+ }
+
+ GURL GetNamespaceEntryUrl(const AppCacheNamespaceVector& namespaces,
+ const GURL& namespace_url) const;
+
+ // Use AppCacheHost::Associate*Cache() to manipulate host association.
+ void AssociateHost(AppCacheHost* host) {
+ associated_hosts_.insert(host);
+ }
+ void UnassociateHost(AppCacheHost* host);
+
+ const int64 cache_id_;
+ scoped_refptr<AppCacheGroup> owning_group_;
+ AppCacheHosts associated_hosts_;
+
+ EntryMap entries_; // contains entries of all types
+
+ AppCacheNamespaceVector intercept_namespaces_;
+ AppCacheNamespaceVector fallback_namespaces_;
+ AppCacheNamespaceVector online_whitelist_namespaces_;
+ bool online_whitelist_all_;
+
+ bool is_complete_;
+
+ // when this cache was last updated
+ base::Time update_time_;
+
+ int64 cache_size_;
+
+ typedef std::map<int64, AppCacheExecutableHandler*> HandlerMap;
+ HandlerMap executable_handlers_;
+
+ // to notify storage when cache is deleted
+ AppCacheStorage* storage_;
+
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, InitializeWithManifest);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, ToFromDatabaseRecords);
+ DISALLOW_COPY_AND_ASSIGN(AppCache);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_H_
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.cc b/chromium/content/browser/appcache/appcache_backend_impl.cc
new file mode 100644
index 00000000000..099c54e55ad
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_backend_impl.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2011 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 "content/browser/appcache/appcache_backend_impl.h"
+
+#include "base/stl_util.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+
+namespace content {
+
+AppCacheBackendImpl::AppCacheBackendImpl()
+ : service_(NULL),
+ frontend_(NULL),
+ process_id_(0) {
+}
+
+AppCacheBackendImpl::~AppCacheBackendImpl() {
+ STLDeleteValues(&hosts_);
+ if (service_)
+ service_->UnregisterBackend(this);
+}
+
+void AppCacheBackendImpl::Initialize(AppCacheServiceImpl* service,
+ AppCacheFrontend* frontend,
+ int process_id) {
+ DCHECK(!service_ && !frontend_ && frontend && service);
+ service_ = service;
+ frontend_ = frontend;
+ process_id_ = process_id;
+ service_->RegisterBackend(this);
+}
+
+bool AppCacheBackendImpl::RegisterHost(int id) {
+ if (GetHost(id))
+ return false;
+
+ hosts_.insert(
+ HostMap::value_type(id, new AppCacheHost(id, frontend_, service_)));
+ return true;
+}
+
+bool AppCacheBackendImpl::UnregisterHost(int id) {
+ HostMap::iterator found = hosts_.find(id);
+ if (found == hosts_.end())
+ return false;
+
+ delete found->second;
+ hosts_.erase(found);
+ return true;
+}
+
+bool AppCacheBackendImpl::SetSpawningHostId(
+ int host_id,
+ int spawning_host_id) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+ host->SetSpawningHostId(process_id_, spawning_host_id);
+ return true;
+}
+
+bool AppCacheBackendImpl::SelectCache(
+ int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->SelectCache(document_url, cache_document_was_loaded_from,
+ manifest_url);
+ return true;
+}
+
+bool AppCacheBackendImpl::SelectCacheForWorker(
+ int host_id, int parent_process_id, int parent_host_id) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->SelectCacheForWorker(parent_process_id, parent_host_id);
+ return true;
+}
+
+bool AppCacheBackendImpl::SelectCacheForSharedWorker(
+ int host_id, int64 appcache_id) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->SelectCacheForSharedWorker(appcache_id);
+ return true;
+}
+
+bool AppCacheBackendImpl::MarkAsForeignEntry(
+ int host_id,
+ const GURL& document_url,
+ int64 cache_document_was_loaded_from) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->MarkAsForeignEntry(document_url, cache_document_was_loaded_from);
+ return true;
+}
+
+bool AppCacheBackendImpl::GetStatusWithCallback(
+ int host_id, const GetStatusCallback& callback, void* callback_param) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->GetStatusWithCallback(callback, callback_param);
+ return true;
+}
+
+bool AppCacheBackendImpl::StartUpdateWithCallback(
+ int host_id, const StartUpdateCallback& callback, void* callback_param) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->StartUpdateWithCallback(callback, callback_param);
+ return true;
+}
+
+bool AppCacheBackendImpl::SwapCacheWithCallback(
+ int host_id, const SwapCacheCallback& callback, void* callback_param) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return false;
+
+ host->SwapCacheWithCallback(callback, callback_param);
+ return true;
+}
+
+void AppCacheBackendImpl::GetResourceList(
+ int host_id, std::vector<AppCacheResourceInfo>* resource_infos) {
+ AppCacheHost* host = GetHost(host_id);
+ if (!host)
+ return;
+
+ host->GetResourceList(resource_infos);
+}
+
+scoped_ptr<AppCacheHost> AppCacheBackendImpl::TransferHostOut(int host_id) {
+ HostMap::iterator found = hosts_.find(host_id);
+ if (found == hosts_.end()) {
+ NOTREACHED();
+ return scoped_ptr<AppCacheHost>();
+ }
+
+ AppCacheHost* transferree = found->second;
+
+ // Put a new empty host in its place.
+ found->second = new AppCacheHost(host_id, frontend_, service_);
+
+ // We give up ownership.
+ transferree->PrepareForTransfer();
+ return scoped_ptr<AppCacheHost>(transferree);
+}
+
+void AppCacheBackendImpl::TransferHostIn(
+ int new_host_id, scoped_ptr<AppCacheHost> host) {
+ HostMap::iterator found = hosts_.find(new_host_id);
+ if (found == hosts_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ delete found->second;
+
+ // We take onwership.
+ host->CompleteTransfer(new_host_id, frontend_);
+ found->second = host.release();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_backend_impl.h b/chromium/content/browser/appcache/appcache_backend_impl.h
new file mode 100644
index 00000000000..bd6f440823e
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_backend_impl.h
@@ -0,0 +1,75 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_BACKEND_IMPL_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_BACKEND_IMPL_H_
+
+#include "base/containers/hash_tables.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class AppCacheServiceImpl;
+
+class CONTENT_EXPORT AppCacheBackendImpl {
+ public:
+ AppCacheBackendImpl();
+ ~AppCacheBackendImpl();
+
+ void Initialize(AppCacheServiceImpl* service,
+ AppCacheFrontend* frontend,
+ int process_id);
+
+ int process_id() const { return process_id_; }
+
+ // Methods to support the AppCacheBackend interface. A false return
+ // value indicates an invalid host_id and that no action was taken
+ // by the backend impl.
+ bool RegisterHost(int host_id);
+ bool UnregisterHost(int host_id);
+ bool SetSpawningHostId(int host_id, int spawning_host_id);
+ bool SelectCache(int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url);
+ void GetResourceList(
+ int host_id, std::vector<AppCacheResourceInfo>* resource_infos);
+ bool SelectCacheForWorker(int host_id, int parent_process_id,
+ int parent_host_id);
+ bool SelectCacheForSharedWorker(int host_id, int64 appcache_id);
+ bool MarkAsForeignEntry(int host_id, const GURL& document_url,
+ int64 cache_document_was_loaded_from);
+ bool GetStatusWithCallback(int host_id, const GetStatusCallback& callback,
+ void* callback_param);
+ bool StartUpdateWithCallback(int host_id, const StartUpdateCallback& callback,
+ void* callback_param);
+ bool SwapCacheWithCallback(int host_id, const SwapCacheCallback& callback,
+ void* callback_param);
+
+ // Returns a pointer to a registered host. The backend retains ownership.
+ AppCacheHost* GetHost(int host_id) {
+ HostMap::iterator it = hosts_.find(host_id);
+ return (it != hosts_.end()) ? (it->second) : NULL;
+ }
+
+ typedef base::hash_map<int, AppCacheHost*> HostMap;
+ const HostMap& hosts() { return hosts_; }
+
+ // Methods to support cross site navigations. Hosts are transferred
+ // from process to process accordingly, deparented from the old
+ // processes backend and reparented to the new.
+ scoped_ptr<AppCacheHost> TransferHostOut(int host_id);
+ void TransferHostIn(int new_host_id, scoped_ptr<AppCacheHost> host);
+
+ private:
+ AppCacheServiceImpl* service_;
+ AppCacheFrontend* frontend_;
+ int process_id_;
+ HostMap hosts_;
+};
+
+} // namespace
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_BACKEND_IMPL_H_
diff --git a/chromium/content/browser/appcache/appcache_database.cc b/chromium/content/browser/appcache/appcache_database.cc
new file mode 100644
index 00000000000..3e502813a1b
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_database.cc
@@ -0,0 +1,1228 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_database.h"
+
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_histograms.h"
+#include "sql/connection.h"
+#include "sql/error_delegate_util.h"
+#include "sql/meta_table.h"
+#include "sql/statement.h"
+#include "sql/transaction.h"
+
+namespace content {
+
+// Schema -------------------------------------------------------------------
+namespace {
+
+#if defined(APPCACHE_USE_SIMPLE_CACHE)
+const int kCurrentVersion = 6;
+const int kCompatibleVersion = 6;
+#else
+const int kCurrentVersion = 5;
+const int kCompatibleVersion = 5;
+#endif
+
+// A mechanism to run experiments that may affect in data being persisted
+// in different ways such that when the experiment is toggled on/off via
+// cmd line flags, the database gets reset. The active flags are stored at
+// the time of database creation and compared when reopening. If different
+// the database is reset.
+const char kExperimentFlagsKey[] = "ExperimentFlags";
+
+const char kGroupsTable[] = "Groups";
+const char kCachesTable[] = "Caches";
+const char kEntriesTable[] = "Entries";
+const char kNamespacesTable[] = "Namespaces";
+const char kOnlineWhiteListsTable[] = "OnlineWhiteLists";
+const char kDeletableResponseIdsTable[] = "DeletableResponseIds";
+
+struct TableInfo {
+ const char* table_name;
+ const char* columns;
+};
+
+struct IndexInfo {
+ const char* index_name;
+ const char* table_name;
+ const char* columns;
+ bool unique;
+};
+
+const TableInfo kTables[] = {
+ { kGroupsTable,
+ "(group_id INTEGER PRIMARY KEY,"
+ " origin TEXT,"
+ " manifest_url TEXT,"
+ " creation_time INTEGER,"
+ " last_access_time INTEGER)" },
+
+ { kCachesTable,
+ "(cache_id INTEGER PRIMARY KEY,"
+ " group_id INTEGER,"
+ " online_wildcard INTEGER CHECK(online_wildcard IN (0, 1)),"
+ " update_time INTEGER,"
+ " cache_size INTEGER)" }, // intentionally not normalized
+
+ { kEntriesTable,
+ "(cache_id INTEGER,"
+ " url TEXT,"
+ " flags INTEGER,"
+ " response_id INTEGER,"
+ " response_size INTEGER)" },
+
+ { kNamespacesTable,
+ "(cache_id INTEGER,"
+ " origin TEXT," // intentionally not normalized
+ " type INTEGER,"
+ " namespace_url TEXT,"
+ " target_url TEXT,"
+ " is_pattern INTEGER CHECK(is_pattern IN (0, 1)))" },
+
+ { kOnlineWhiteListsTable,
+ "(cache_id INTEGER,"
+ " namespace_url TEXT,"
+ " is_pattern INTEGER CHECK(is_pattern IN (0, 1)))" },
+
+ { kDeletableResponseIdsTable,
+ "(response_id INTEGER NOT NULL)" },
+};
+
+const IndexInfo kIndexes[] = {
+ { "GroupsOriginIndex",
+ kGroupsTable,
+ "(origin)",
+ false },
+
+ { "GroupsManifestIndex",
+ kGroupsTable,
+ "(manifest_url)",
+ true },
+
+ { "CachesGroupIndex",
+ kCachesTable,
+ "(group_id)",
+ false },
+
+ { "EntriesCacheIndex",
+ kEntriesTable,
+ "(cache_id)",
+ false },
+
+ { "EntriesCacheAndUrlIndex",
+ kEntriesTable,
+ "(cache_id, url)",
+ true },
+
+ { "EntriesResponseIdIndex",
+ kEntriesTable,
+ "(response_id)",
+ true },
+
+ { "NamespacesCacheIndex",
+ kNamespacesTable,
+ "(cache_id)",
+ false },
+
+ { "NamespacesOriginIndex",
+ kNamespacesTable,
+ "(origin)",
+ false },
+
+ { "NamespacesCacheAndUrlIndex",
+ kNamespacesTable,
+ "(cache_id, namespace_url)",
+ true },
+
+ { "OnlineWhiteListCacheIndex",
+ kOnlineWhiteListsTable,
+ "(cache_id)",
+ false },
+
+ { "DeletableResponsesIdIndex",
+ kDeletableResponseIdsTable,
+ "(response_id)",
+ true },
+};
+
+const int kTableCount = arraysize(kTables);
+const int kIndexCount = arraysize(kIndexes);
+
+bool CreateTable(sql::Connection* db, const TableInfo& info) {
+ std::string sql("CREATE TABLE ");
+ sql += info.table_name;
+ sql += info.columns;
+ return db->Execute(sql.c_str());
+}
+
+bool CreateIndex(sql::Connection* db, const IndexInfo& info) {
+ std::string sql;
+ if (info.unique)
+ sql += "CREATE UNIQUE INDEX ";
+ else
+ sql += "CREATE INDEX ";
+ sql += info.index_name;
+ sql += " ON ";
+ sql += info.table_name;
+ sql += info.columns;
+ return db->Execute(sql.c_str());
+}
+
+std::string GetActiveExperimentFlags() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableExecutableHandlers))
+ return std::string("executableHandlersEnabled");
+ return std::string();
+}
+
+} // anon namespace
+
+// AppCacheDatabase ----------------------------------------------------------
+
+AppCacheDatabase::GroupRecord::GroupRecord()
+ : group_id(0) {
+}
+
+AppCacheDatabase::GroupRecord::~GroupRecord() {
+}
+
+AppCacheDatabase::NamespaceRecord::NamespaceRecord()
+ : cache_id(0) {
+}
+
+AppCacheDatabase::NamespaceRecord::~NamespaceRecord() {
+}
+
+
+AppCacheDatabase::AppCacheDatabase(const base::FilePath& path)
+ : db_file_path_(path),
+ is_disabled_(false),
+ is_recreating_(false),
+ was_corruption_detected_(false) {
+}
+
+AppCacheDatabase::~AppCacheDatabase() {
+}
+
+void AppCacheDatabase::Disable() {
+ VLOG(1) << "Disabling appcache database.";
+ is_disabled_ = true;
+ ResetConnectionAndTables();
+}
+
+int64 AppCacheDatabase::GetOriginUsage(const GURL& origin) {
+ std::vector<CacheRecord> records;
+ if (!FindCachesForOrigin(origin, &records))
+ return 0;
+
+ int64 origin_usage = 0;
+ std::vector<CacheRecord>::const_iterator iter = records.begin();
+ while (iter != records.end()) {
+ origin_usage += iter->cache_size;
+ ++iter;
+ }
+ return origin_usage;
+}
+
+bool AppCacheDatabase::GetAllOriginUsage(std::map<GURL, int64>* usage_map) {
+ std::set<GURL> origins;
+ if (!FindOriginsWithGroups(&origins))
+ return false;
+ for (std::set<GURL>::const_iterator origin = origins.begin();
+ origin != origins.end(); ++origin) {
+ (*usage_map)[*origin] = GetOriginUsage(*origin);
+ }
+ return true;
+}
+
+bool AppCacheDatabase::FindOriginsWithGroups(std::set<GURL>* origins) {
+ DCHECK(origins && origins->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT DISTINCT(origin) FROM Groups";
+
+ sql::Statement statement(db_->GetUniqueStatement(kSql));
+
+ while (statement.Step())
+ origins->insert(GURL(statement.ColumnString(0)));
+
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::FindLastStorageIds(
+ int64* last_group_id, int64* last_cache_id, int64* last_response_id,
+ int64* last_deletable_response_rowid) {
+ DCHECK(last_group_id && last_cache_id && last_response_id &&
+ last_deletable_response_rowid);
+
+ *last_group_id = 0;
+ *last_cache_id = 0;
+ *last_response_id = 0;
+ *last_deletable_response_rowid = 0;
+
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kMaxGroupIdSql = "SELECT MAX(group_id) FROM Groups";
+ const char* kMaxCacheIdSql = "SELECT MAX(cache_id) FROM Caches";
+ const char* kMaxResponseIdFromEntriesSql =
+ "SELECT MAX(response_id) FROM Entries";
+ const char* kMaxResponseIdFromDeletablesSql =
+ "SELECT MAX(response_id) FROM DeletableResponseIds";
+ const char* kMaxDeletableResponseRowIdSql =
+ "SELECT MAX(rowid) FROM DeletableResponseIds";
+ int64 max_group_id;
+ int64 max_cache_id;
+ int64 max_response_id_from_entries;
+ int64 max_response_id_from_deletables;
+ int64 max_deletable_response_rowid;
+ if (!RunUniqueStatementWithInt64Result(kMaxGroupIdSql, &max_group_id) ||
+ !RunUniqueStatementWithInt64Result(kMaxCacheIdSql, &max_cache_id) ||
+ !RunUniqueStatementWithInt64Result(kMaxResponseIdFromEntriesSql,
+ &max_response_id_from_entries) ||
+ !RunUniqueStatementWithInt64Result(kMaxResponseIdFromDeletablesSql,
+ &max_response_id_from_deletables) ||
+ !RunUniqueStatementWithInt64Result(kMaxDeletableResponseRowIdSql,
+ &max_deletable_response_rowid)) {
+ return false;
+ }
+
+ *last_group_id = max_group_id;
+ *last_cache_id = max_cache_id;
+ *last_response_id = std::max(max_response_id_from_entries,
+ max_response_id_from_deletables);
+ *last_deletable_response_rowid = max_deletable_response_rowid;
+ return true;
+}
+
+bool AppCacheDatabase::FindGroup(int64 group_id, GroupRecord* record) {
+ DCHECK(record);
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT group_id, origin, manifest_url,"
+ " creation_time, last_access_time"
+ " FROM Groups WHERE group_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+
+ statement.BindInt64(0, group_id);
+ if (!statement.Step())
+ return false;
+
+ ReadGroupRecord(statement, record);
+ DCHECK(record->group_id == group_id);
+ return true;
+}
+
+bool AppCacheDatabase::FindGroupForManifestUrl(
+ const GURL& manifest_url, GroupRecord* record) {
+ DCHECK(record);
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT group_id, origin, manifest_url,"
+ " creation_time, last_access_time"
+ " FROM Groups WHERE manifest_url = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, manifest_url.spec());
+
+ if (!statement.Step())
+ return false;
+
+ ReadGroupRecord(statement, record);
+ DCHECK(record->manifest_url == manifest_url);
+ return true;
+}
+
+bool AppCacheDatabase::FindGroupsForOrigin(
+ const GURL& origin, std::vector<GroupRecord>* records) {
+ DCHECK(records && records->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT group_id, origin, manifest_url,"
+ " creation_time, last_access_time"
+ " FROM Groups WHERE origin = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, origin.spec());
+
+ while (statement.Step()) {
+ records->push_back(GroupRecord());
+ ReadGroupRecord(statement, &records->back());
+ DCHECK(records->back().origin == origin);
+ }
+
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::FindGroupForCache(int64 cache_id, GroupRecord* record) {
+ DCHECK(record);
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT g.group_id, g.origin, g.manifest_url,"
+ " g.creation_time, g.last_access_time"
+ " FROM Groups g, Caches c"
+ " WHERE c.cache_id = ? AND c.group_id = g.group_id";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ if (!statement.Step())
+ return false;
+
+ ReadGroupRecord(statement, record);
+ return true;
+}
+
+bool AppCacheDatabase::UpdateGroupLastAccessTime(
+ int64 group_id, base::Time time) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char* kSql =
+ "UPDATE Groups SET last_access_time = ? WHERE group_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, time.ToInternalValue());
+ statement.BindInt64(1, group_id);
+
+ return statement.Run() && db_->GetLastChangeCount();
+}
+
+bool AppCacheDatabase::InsertGroup(const GroupRecord* record) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char* kSql =
+ "INSERT INTO Groups"
+ " (group_id, origin, manifest_url, creation_time, last_access_time)"
+ " VALUES(?, ?, ?, ?, ?)";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, record->group_id);
+ statement.BindString(1, record->origin.spec());
+ statement.BindString(2, record->manifest_url.spec());
+ statement.BindInt64(3, record->creation_time.ToInternalValue());
+ statement.BindInt64(4, record->last_access_time.ToInternalValue());
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::DeleteGroup(int64 group_id) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "DELETE FROM Groups WHERE group_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, group_id);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::FindCache(int64 cache_id, CacheRecord* record) {
+ DCHECK(record);
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, group_id, online_wildcard, update_time, cache_size"
+ " FROM Caches WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ if (!statement.Step())
+ return false;
+
+ ReadCacheRecord(statement, record);
+ return true;
+}
+
+bool AppCacheDatabase::FindCacheForGroup(int64 group_id, CacheRecord* record) {
+ DCHECK(record);
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, group_id, online_wildcard, update_time, cache_size"
+ " FROM Caches WHERE group_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, group_id);
+
+ if (!statement.Step())
+ return false;
+
+ ReadCacheRecord(statement, record);
+ return true;
+}
+
+bool AppCacheDatabase::FindCachesForOrigin(
+ const GURL& origin, std::vector<CacheRecord>* records) {
+ DCHECK(records);
+ std::vector<GroupRecord> group_records;
+ if (!FindGroupsForOrigin(origin, &group_records))
+ return false;
+
+ CacheRecord cache_record;
+ std::vector<GroupRecord>::const_iterator iter = group_records.begin();
+ while (iter != group_records.end()) {
+ if (FindCacheForGroup(iter->group_id, &cache_record))
+ records->push_back(cache_record);
+ ++iter;
+ }
+ return true;
+}
+
+bool AppCacheDatabase::InsertCache(const CacheRecord* record) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char* kSql =
+ "INSERT INTO Caches (cache_id, group_id, online_wildcard,"
+ " update_time, cache_size)"
+ " VALUES(?, ?, ?, ?, ?)";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, record->cache_id);
+ statement.BindInt64(1, record->group_id);
+ statement.BindBool(2, record->online_wildcard);
+ statement.BindInt64(3, record->update_time.ToInternalValue());
+ statement.BindInt64(4, record->cache_size);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::DeleteCache(int64 cache_id) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "DELETE FROM Caches WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::FindEntriesForCache(
+ int64 cache_id, std::vector<EntryRecord>* records) {
+ DCHECK(records && records->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, url, flags, response_id, response_size FROM Entries"
+ " WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ while (statement.Step()) {
+ records->push_back(EntryRecord());
+ ReadEntryRecord(statement, &records->back());
+ DCHECK(records->back().cache_id == cache_id);
+ }
+
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::FindEntriesForUrl(
+ const GURL& url, std::vector<EntryRecord>* records) {
+ DCHECK(records && records->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, url, flags, response_id, response_size FROM Entries"
+ " WHERE url = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, url.spec());
+
+ while (statement.Step()) {
+ records->push_back(EntryRecord());
+ ReadEntryRecord(statement, &records->back());
+ DCHECK(records->back().url == url);
+ }
+
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::FindEntry(
+ int64 cache_id, const GURL& url, EntryRecord* record) {
+ DCHECK(record);
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, url, flags, response_id, response_size FROM Entries"
+ " WHERE cache_id = ? AND url = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+ statement.BindString(1, url.spec());
+
+ if (!statement.Step())
+ return false;
+
+ ReadEntryRecord(statement, record);
+ DCHECK(record->cache_id == cache_id);
+ DCHECK(record->url == url);
+ return true;
+}
+
+bool AppCacheDatabase::InsertEntry(const EntryRecord* record) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char* kSql =
+ "INSERT INTO Entries (cache_id, url, flags, response_id, response_size)"
+ " VALUES(?, ?, ?, ?, ?)";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, record->cache_id);
+ statement.BindString(1, record->url.spec());
+ statement.BindInt(2, record->flags);
+ statement.BindInt64(3, record->response_id);
+ statement.BindInt64(4, record->response_size);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::InsertEntryRecords(
+ const std::vector<EntryRecord>& records) {
+ if (records.empty())
+ return true;
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+ std::vector<EntryRecord>::const_iterator iter = records.begin();
+ while (iter != records.end()) {
+ if (!InsertEntry(&(*iter)))
+ return false;
+ ++iter;
+ }
+ return transaction.Commit();
+}
+
+bool AppCacheDatabase::DeleteEntriesForCache(int64 cache_id) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "DELETE FROM Entries WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::AddEntryFlags(
+ const GURL& entry_url, int64 cache_id, int additional_flags) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "UPDATE Entries SET flags = flags | ? WHERE cache_id = ? AND url = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt(0, additional_flags);
+ statement.BindInt64(1, cache_id);
+ statement.BindString(2, entry_url.spec());
+
+ return statement.Run() && db_->GetLastChangeCount();
+}
+
+bool AppCacheDatabase::FindNamespacesForOrigin(
+ const GURL& origin,
+ std::vector<NamespaceRecord>* intercepts,
+ std::vector<NamespaceRecord>* fallbacks) {
+ DCHECK(intercepts && intercepts->empty());
+ DCHECK(fallbacks && fallbacks->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, origin, type, namespace_url, target_url, is_pattern"
+ " FROM Namespaces WHERE origin = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindString(0, origin.spec());
+
+ ReadNamespaceRecords(&statement, intercepts, fallbacks);
+
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::FindNamespacesForCache(
+ int64 cache_id,
+ std::vector<NamespaceRecord>* intercepts,
+ std::vector<NamespaceRecord>* fallbacks) {
+ DCHECK(intercepts && intercepts->empty());
+ DCHECK(fallbacks && fallbacks->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, origin, type, namespace_url, target_url, is_pattern"
+ " FROM Namespaces WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ ReadNamespaceRecords(&statement, intercepts, fallbacks);
+
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::InsertNamespace(
+ const NamespaceRecord* record) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char* kSql =
+ "INSERT INTO Namespaces"
+ " (cache_id, origin, type, namespace_url, target_url, is_pattern)"
+ " VALUES (?, ?, ?, ?, ?, ?)";
+
+ // Note: quick and dirty storage for the 'executable' bit w/o changing
+ // schemas, we use the high bit of 'type' field.
+ int type_with_executable_bit = record->namespace_.type;
+ if (record->namespace_.is_executable) {
+ type_with_executable_bit |= 0x8000000;
+ DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableExecutableHandlers));
+ }
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, record->cache_id);
+ statement.BindString(1, record->origin.spec());
+ statement.BindInt(2, type_with_executable_bit);
+ statement.BindString(3, record->namespace_.namespace_url.spec());
+ statement.BindString(4, record->namespace_.target_url.spec());
+ statement.BindBool(5, record->namespace_.is_pattern);
+ return statement.Run();
+}
+
+bool AppCacheDatabase::InsertNamespaceRecords(
+ const std::vector<NamespaceRecord>& records) {
+ if (records.empty())
+ return true;
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+ std::vector<NamespaceRecord>::const_iterator iter = records.begin();
+ while (iter != records.end()) {
+ if (!InsertNamespace(&(*iter)))
+ return false;
+ ++iter;
+ }
+ return transaction.Commit();
+}
+
+bool AppCacheDatabase::DeleteNamespacesForCache(int64 cache_id) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "DELETE FROM Namespaces WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::FindOnlineWhiteListForCache(
+ int64 cache_id, std::vector<OnlineWhiteListRecord>* records) {
+ DCHECK(records && records->empty());
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT cache_id, namespace_url, is_pattern FROM OnlineWhiteLists"
+ " WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ while (statement.Step()) {
+ records->push_back(OnlineWhiteListRecord());
+ this->ReadOnlineWhiteListRecord(statement, &records->back());
+ DCHECK(records->back().cache_id == cache_id);
+ }
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::InsertOnlineWhiteList(
+ const OnlineWhiteListRecord* record) {
+ if (!LazyOpen(true))
+ return false;
+
+ const char* kSql =
+ "INSERT INTO OnlineWhiteLists (cache_id, namespace_url, is_pattern)"
+ " VALUES (?, ?, ?)";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, record->cache_id);
+ statement.BindString(1, record->namespace_url.spec());
+ statement.BindBool(2, record->is_pattern);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::InsertOnlineWhiteListRecords(
+ const std::vector<OnlineWhiteListRecord>& records) {
+ if (records.empty())
+ return true;
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+ std::vector<OnlineWhiteListRecord>::const_iterator iter = records.begin();
+ while (iter != records.end()) {
+ if (!InsertOnlineWhiteList(&(*iter)))
+ return false;
+ ++iter;
+ }
+ return transaction.Commit();
+}
+
+bool AppCacheDatabase::DeleteOnlineWhiteListForCache(int64 cache_id) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "DELETE FROM OnlineWhiteLists WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, cache_id);
+
+ return statement.Run();
+}
+
+bool AppCacheDatabase::GetDeletableResponseIds(
+ std::vector<int64>* response_ids, int64 max_rowid, int limit) {
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT response_id FROM DeletableResponseIds "
+ " WHERE rowid <= ?"
+ " LIMIT ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+ statement.BindInt64(0, max_rowid);
+ statement.BindInt64(1, limit);
+
+ while (statement.Step())
+ response_ids->push_back(statement.ColumnInt64(0));
+ return statement.Succeeded();
+}
+
+bool AppCacheDatabase::InsertDeletableResponseIds(
+ const std::vector<int64>& response_ids) {
+ const char* kSql =
+ "INSERT INTO DeletableResponseIds (response_id) VALUES (?)";
+ return RunCachedStatementWithIds(SQL_FROM_HERE, kSql, response_ids);
+}
+
+bool AppCacheDatabase::DeleteDeletableResponseIds(
+ const std::vector<int64>& response_ids) {
+ const char* kSql =
+ "DELETE FROM DeletableResponseIds WHERE response_id = ?";
+ return RunCachedStatementWithIds(SQL_FROM_HERE, kSql, response_ids);
+}
+
+bool AppCacheDatabase::RunCachedStatementWithIds(
+ const sql::StatementID& statement_id, const char* sql,
+ const std::vector<int64>& ids) {
+ DCHECK(sql);
+ if (!LazyOpen(true))
+ return false;
+
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+
+ sql::Statement statement(db_->GetCachedStatement(statement_id, sql));
+
+ std::vector<int64>::const_iterator iter = ids.begin();
+ while (iter != ids.end()) {
+ statement.BindInt64(0, *iter);
+ if (!statement.Run())
+ return false;
+ statement.Reset(true);
+ ++iter;
+ }
+
+ return transaction.Commit();
+}
+
+bool AppCacheDatabase::RunUniqueStatementWithInt64Result(
+ const char* sql, int64* result) {
+ DCHECK(sql);
+ sql::Statement statement(db_->GetUniqueStatement(sql));
+ if (!statement.Step()) {
+ return false;
+ }
+ *result = statement.ColumnInt64(0);
+ return true;
+}
+
+bool AppCacheDatabase::FindResponseIdsForCacheHelper(
+ int64 cache_id, std::vector<int64>* ids_vector,
+ std::set<int64>* ids_set) {
+ DCHECK(ids_vector || ids_set);
+ DCHECK(!(ids_vector && ids_set));
+ if (!LazyOpen(false))
+ return false;
+
+ const char* kSql =
+ "SELECT response_id FROM Entries WHERE cache_id = ?";
+
+ sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
+
+ statement.BindInt64(0, cache_id);
+ while (statement.Step()) {
+ int64 id = statement.ColumnInt64(0);
+ if (ids_set)
+ ids_set->insert(id);
+ else
+ ids_vector->push_back(id);
+ }
+
+ return statement.Succeeded();
+}
+
+void AppCacheDatabase::ReadGroupRecord(
+ const sql::Statement& statement, GroupRecord* record) {
+ record->group_id = statement.ColumnInt64(0);
+ record->origin = GURL(statement.ColumnString(1));
+ record->manifest_url = GURL(statement.ColumnString(2));
+ record->creation_time =
+ base::Time::FromInternalValue(statement.ColumnInt64(3));
+ record->last_access_time =
+ base::Time::FromInternalValue(statement.ColumnInt64(4));
+}
+
+void AppCacheDatabase::ReadCacheRecord(
+ const sql::Statement& statement, CacheRecord* record) {
+ record->cache_id = statement.ColumnInt64(0);
+ record->group_id = statement.ColumnInt64(1);
+ record->online_wildcard = statement.ColumnBool(2);
+ record->update_time =
+ base::Time::FromInternalValue(statement.ColumnInt64(3));
+ record->cache_size = statement.ColumnInt64(4);
+}
+
+void AppCacheDatabase::ReadEntryRecord(
+ const sql::Statement& statement, EntryRecord* record) {
+ record->cache_id = statement.ColumnInt64(0);
+ record->url = GURL(statement.ColumnString(1));
+ record->flags = statement.ColumnInt(2);
+ record->response_id = statement.ColumnInt64(3);
+ record->response_size = statement.ColumnInt64(4);
+}
+
+void AppCacheDatabase::ReadNamespaceRecords(
+ sql::Statement* statement,
+ NamespaceRecordVector* intercepts,
+ NamespaceRecordVector* fallbacks) {
+ while (statement->Step()) {
+ AppCacheNamespaceType type = static_cast<AppCacheNamespaceType>(
+ statement->ColumnInt(2));
+ NamespaceRecordVector* records =
+ (type == APPCACHE_FALLBACK_NAMESPACE) ? fallbacks : intercepts;
+ records->push_back(NamespaceRecord());
+ ReadNamespaceRecord(statement, &records->back());
+ }
+}
+
+void AppCacheDatabase::ReadNamespaceRecord(
+ const sql::Statement* statement, NamespaceRecord* record) {
+ record->cache_id = statement->ColumnInt64(0);
+ record->origin = GURL(statement->ColumnString(1));
+ int type_with_executable_bit = statement->ColumnInt(2);
+ record->namespace_.namespace_url = GURL(statement->ColumnString(3));
+ record->namespace_.target_url = GURL(statement->ColumnString(4));
+ record->namespace_.is_pattern = statement->ColumnBool(5);
+
+ // Note: quick and dirty storage for the 'executable' bit w/o changing
+ // schemas, we use the high bit of 'type' field.
+ record->namespace_.type = static_cast<AppCacheNamespaceType>
+ (type_with_executable_bit & 0x7ffffff);
+ record->namespace_.is_executable =
+ (type_with_executable_bit & 0x80000000) != 0;
+ DCHECK(!record->namespace_.is_executable ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableExecutableHandlers));
+}
+
+void AppCacheDatabase::ReadOnlineWhiteListRecord(
+ const sql::Statement& statement, OnlineWhiteListRecord* record) {
+ record->cache_id = statement.ColumnInt64(0);
+ record->namespace_url = GURL(statement.ColumnString(1));
+ record->is_pattern = statement.ColumnBool(2);
+}
+
+bool AppCacheDatabase::LazyOpen(bool create_if_needed) {
+ if (db_)
+ return true;
+
+ // If we tried and failed once, don't try again in the same session
+ // to avoid creating an incoherent mess on disk.
+ if (is_disabled_)
+ return false;
+
+ // Avoid creating a database at all if we can.
+ bool use_in_memory_db = db_file_path_.empty();
+ if (!create_if_needed &&
+ (use_in_memory_db || !base::PathExists(db_file_path_))) {
+ return false;
+ }
+
+ db_.reset(new sql::Connection);
+ meta_table_.reset(new sql::MetaTable);
+
+ db_->set_histogram_tag("AppCache");
+
+ bool opened = false;
+ if (use_in_memory_db) {
+ opened = db_->OpenInMemory();
+ } else if (!base::CreateDirectory(db_file_path_.DirName())) {
+ LOG(ERROR) << "Failed to create appcache directory.";
+ } else {
+ opened = db_->Open(db_file_path_);
+ if (opened)
+ db_->Preload();
+ }
+
+ if (!opened || !db_->QuickIntegrityCheck() || !EnsureDatabaseVersion()) {
+ LOG(ERROR) << "Failed to open the appcache database.";
+ AppCacheHistograms::CountInitResult(
+ AppCacheHistograms::SQL_DATABASE_ERROR);
+
+ // We're unable to open the database. This is a fatal error
+ // which we can't recover from. We try to handle it by deleting
+ // the existing appcache data and starting with a clean slate in
+ // this browser session.
+ if (!use_in_memory_db && DeleteExistingAndCreateNewDatabase())
+ return true;
+
+ Disable();
+ return false;
+ }
+
+ AppCacheHistograms::CountInitResult(AppCacheHistograms::INIT_OK);
+ was_corruption_detected_ = false;
+ db_->set_error_callback(
+ base::Bind(&AppCacheDatabase::OnDatabaseError, base::Unretained(this)));
+ return true;
+}
+
+bool AppCacheDatabase::EnsureDatabaseVersion() {
+ if (!sql::MetaTable::DoesTableExist(db_.get()))
+ return CreateSchema();
+
+ if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion))
+ return false;
+
+ if (meta_table_->GetCompatibleVersionNumber() > kCurrentVersion) {
+ LOG(WARNING) << "AppCache database is too new.";
+ return false;
+ }
+
+ std::string stored_flags;
+ meta_table_->GetValue(kExperimentFlagsKey, &stored_flags);
+ if (stored_flags != GetActiveExperimentFlags())
+ return false;
+
+ if (meta_table_->GetVersionNumber() < kCurrentVersion)
+ return UpgradeSchema();
+
+#ifndef NDEBUG
+ DCHECK(sql::MetaTable::DoesTableExist(db_.get()));
+ for (int i = 0; i < kTableCount; ++i) {
+ DCHECK(db_->DoesTableExist(kTables[i].table_name));
+ }
+ for (int i = 0; i < kIndexCount; ++i) {
+ DCHECK(db_->DoesIndexExist(kIndexes[i].index_name));
+ }
+#endif
+
+ return true;
+}
+
+bool AppCacheDatabase::CreateSchema() {
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+
+ if (!meta_table_->Init(db_.get(), kCurrentVersion, kCompatibleVersion))
+ return false;
+
+ if (!meta_table_->SetValue(kExperimentFlagsKey,
+ GetActiveExperimentFlags())) {
+ return false;
+ }
+
+ for (int i = 0; i < kTableCount; ++i) {
+ if (!CreateTable(db_.get(), kTables[i]))
+ return false;
+ }
+
+ for (int i = 0; i < kIndexCount; ++i) {
+ if (!CreateIndex(db_.get(), kIndexes[i]))
+ return false;
+ }
+
+ return transaction.Commit();
+}
+
+bool AppCacheDatabase::UpgradeSchema() {
+#if defined(APPCACHE_USE_SIMPLE_CACHE)
+ return DeleteExistingAndCreateNewDatabase();
+#else
+ if (meta_table_->GetVersionNumber() == 3) {
+ // version 3 was pre 12/17/2011
+ DCHECK_EQ(strcmp(kNamespacesTable, kTables[3].table_name), 0);
+ DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[6].table_name), 0);
+ DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[7].table_name), 0);
+ DCHECK_EQ(strcmp(kNamespacesTable, kIndexes[8].table_name), 0);
+
+ const TableInfo kNamespaceTable_v4 = {
+ kNamespacesTable,
+ "(cache_id INTEGER,"
+ " origin TEXT," // intentionally not normalized
+ " type INTEGER,"
+ " namespace_url TEXT,"
+ " target_url TEXT)"
+ };
+
+ // Migrate from the old FallbackNameSpaces to the newer Namespaces table,
+ // but without the is_pattern column added in v5.
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin() ||
+ !CreateTable(db_.get(), kNamespaceTable_v4)) {
+ return false;
+ }
+
+ // Move data from the old table to the new table, setting the
+ // 'type' for all current records to the value for
+ // APPCACHE_FALLBACK_NAMESPACE.
+ DCHECK_EQ(0, static_cast<int>(APPCACHE_FALLBACK_NAMESPACE));
+ if (!db_->Execute(
+ "INSERT INTO Namespaces"
+ " SELECT cache_id, origin, 0, namespace_url, fallback_entry_url"
+ " FROM FallbackNameSpaces")) {
+ return false;
+ }
+
+ // Drop the old table, indexes on that table are also removed by this.
+ if (!db_->Execute("DROP TABLE FallbackNameSpaces"))
+ return false;
+
+ // Create new indexes.
+ if (!CreateIndex(db_.get(), kIndexes[6]) ||
+ !CreateIndex(db_.get(), kIndexes[7]) ||
+ !CreateIndex(db_.get(), kIndexes[8])) {
+ return false;
+ }
+
+ meta_table_->SetVersionNumber(4);
+ meta_table_->SetCompatibleVersionNumber(4);
+ if (!transaction.Commit())
+ return false;
+ }
+
+ if (meta_table_->GetVersionNumber() == 4) {
+ // version 4 pre 3/30/2013
+ // Add the is_pattern column to the Namespaces and OnlineWhitelists tables.
+ DCHECK_EQ(strcmp(kNamespacesTable, "Namespaces"), 0);
+ sql::Transaction transaction(db_.get());
+ if (!transaction.Begin())
+ return false;
+ if (!db_->Execute(
+ "ALTER TABLE Namespaces ADD COLUMN"
+ " is_pattern INTEGER CHECK(is_pattern IN (0, 1))")) {
+ return false;
+ }
+ if (!db_->Execute(
+ "ALTER TABLE OnlineWhitelists ADD COLUMN"
+ " is_pattern INTEGER CHECK(is_pattern IN (0, 1))")) {
+ return false;
+ }
+ meta_table_->SetVersionNumber(5);
+ meta_table_->SetCompatibleVersionNumber(5);
+ return transaction.Commit();
+ }
+
+ // If there is no upgrade path for the version on disk to the current
+ // version, nuke everything and start over.
+ return DeleteExistingAndCreateNewDatabase();
+#endif
+}
+
+void AppCacheDatabase::ResetConnectionAndTables() {
+ meta_table_.reset();
+ db_.reset();
+}
+
+bool AppCacheDatabase::DeleteExistingAndCreateNewDatabase() {
+ DCHECK(!db_file_path_.empty());
+ DCHECK(base::PathExists(db_file_path_));
+ VLOG(1) << "Deleting existing appcache data and starting over.";
+
+ ResetConnectionAndTables();
+
+ // This also deletes the disk cache data.
+ base::FilePath directory = db_file_path_.DirName();
+ if (!base::DeleteFile(directory, true))
+ return false;
+
+ // Make sure the steps above actually deleted things.
+ if (base::PathExists(directory))
+ return false;
+
+ if (!base::CreateDirectory(directory))
+ return false;
+
+ // So we can't go recursive.
+ if (is_recreating_)
+ return false;
+
+ base::AutoReset<bool> auto_reset(&is_recreating_, true);
+ return LazyOpen(true);
+}
+
+void AppCacheDatabase::OnDatabaseError(int err, sql::Statement* stmt) {
+ was_corruption_detected_ |= sql::IsErrorCatastrophic(err);
+ if (!db_->ShouldIgnoreSqliteError(err))
+ DLOG(ERROR) << db_->GetErrorMessage();
+ // TODO: Maybe use non-catostrophic errors to trigger a full integrity check?
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_database.h b/chromium/content/browser/appcache/appcache_database.h
new file mode 100644
index 00000000000..ee1c52d8be3
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_database.h
@@ -0,0 +1,251 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_DATABASE_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_DATABASE_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace sql {
+class Connection;
+class MetaTable;
+class Statement;
+class StatementID;
+}
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, CacheRecords);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, EntryRecords);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, QuickIntegrityCheck);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, NamespaceRecords);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, GroupRecords);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, LazyOpen);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, ExperimentalFlags);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, OnlineWhiteListRecords);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, ReCreate);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, DeletableResponseIds);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, OriginUsage);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema3to5);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, UpgradeSchema4to5);
+FORWARD_DECLARE_TEST(AppCacheDatabaseTest, WasCorrutionDetected);
+class AppCacheDatabaseTest;
+class AppCacheStorageImplTest;
+
+class CONTENT_EXPORT AppCacheDatabase {
+ public:
+ struct CONTENT_EXPORT GroupRecord {
+ GroupRecord();
+ ~GroupRecord();
+
+ int64 group_id;
+ GURL origin;
+ GURL manifest_url;
+ base::Time creation_time;
+ base::Time last_access_time;
+ };
+
+ struct CONTENT_EXPORT CacheRecord {
+ CacheRecord()
+ : cache_id(0), group_id(0), online_wildcard(false), cache_size(0) {}
+
+ int64 cache_id;
+ int64 group_id;
+ bool online_wildcard;
+ base::Time update_time;
+ int64 cache_size; // the sum of all response sizes in this cache
+ };
+
+ struct EntryRecord {
+ EntryRecord() : cache_id(0), flags(0), response_id(0), response_size(0) {}
+
+ int64 cache_id;
+ GURL url;
+ int flags;
+ int64 response_id;
+ int64 response_size;
+ };
+
+ struct CONTENT_EXPORT NamespaceRecord {
+ NamespaceRecord();
+ ~NamespaceRecord();
+
+ int64 cache_id;
+ GURL origin;
+ AppCacheNamespace namespace_;
+ };
+
+ typedef std::vector<NamespaceRecord> NamespaceRecordVector;
+
+ struct OnlineWhiteListRecord {
+ OnlineWhiteListRecord() : cache_id(0), is_pattern(false) {}
+
+ int64 cache_id;
+ GURL namespace_url;
+ bool is_pattern;
+ };
+
+ explicit AppCacheDatabase(const base::FilePath& path);
+ ~AppCacheDatabase();
+
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
+ bool was_corruption_detected() const { return was_corruption_detected_; }
+
+ int64 GetOriginUsage(const GURL& origin);
+ bool GetAllOriginUsage(std::map<GURL, int64>* usage_map);
+
+ bool FindOriginsWithGroups(std::set<GURL>* origins);
+ bool FindLastStorageIds(
+ int64* last_group_id, int64* last_cache_id, int64* last_response_id,
+ int64* last_deletable_response_rowid);
+
+ bool FindGroup(int64 group_id, GroupRecord* record);
+ bool FindGroupForManifestUrl(const GURL& manifest_url, GroupRecord* record);
+ bool FindGroupsForOrigin(
+ const GURL& origin, std::vector<GroupRecord>* records);
+ bool FindGroupForCache(int64 cache_id, GroupRecord* record);
+ bool UpdateGroupLastAccessTime(
+ int64 group_id, base::Time last_access_time);
+ bool InsertGroup(const GroupRecord* record);
+ bool DeleteGroup(int64 group_id);
+
+ bool FindCache(int64 cache_id, CacheRecord* record);
+ bool FindCacheForGroup(int64 group_id, CacheRecord* record);
+ bool FindCachesForOrigin(
+ const GURL& origin, std::vector<CacheRecord>* records);
+ bool InsertCache(const CacheRecord* record);
+ bool DeleteCache(int64 cache_id);
+
+ bool FindEntriesForCache(
+ int64 cache_id, std::vector<EntryRecord>* records);
+ bool FindEntriesForUrl(
+ const GURL& url, std::vector<EntryRecord>* records);
+ bool FindEntry(int64 cache_id, const GURL& url, EntryRecord* record);
+ bool InsertEntry(const EntryRecord* record);
+ bool InsertEntryRecords(
+ const std::vector<EntryRecord>& records);
+ bool DeleteEntriesForCache(int64 cache_id);
+ bool AddEntryFlags(const GURL& entry_url, int64 cache_id,
+ int additional_flags);
+ bool FindResponseIdsForCacheAsVector(
+ int64 cache_id, std::vector<int64>* response_ids) {
+ return FindResponseIdsForCacheHelper(cache_id, response_ids, NULL);
+ }
+ bool FindResponseIdsForCacheAsSet(
+ int64 cache_id, std::set<int64>* response_ids) {
+ return FindResponseIdsForCacheHelper(cache_id, NULL, response_ids);
+ }
+
+ bool FindNamespacesForOrigin(
+ const GURL& origin,
+ NamespaceRecordVector* intercepts,
+ NamespaceRecordVector* fallbacks);
+ bool FindNamespacesForCache(
+ int64 cache_id,
+ NamespaceRecordVector* intercepts,
+ std::vector<NamespaceRecord>* fallbacks);
+ bool InsertNamespaceRecords(
+ const NamespaceRecordVector& records);
+ bool InsertNamespace(const NamespaceRecord* record);
+ bool DeleteNamespacesForCache(int64 cache_id);
+
+ bool FindOnlineWhiteListForCache(
+ int64 cache_id, std::vector<OnlineWhiteListRecord>* records);
+ bool InsertOnlineWhiteList(const OnlineWhiteListRecord* record);
+ bool InsertOnlineWhiteListRecords(
+ const std::vector<OnlineWhiteListRecord>& records);
+ bool DeleteOnlineWhiteListForCache(int64 cache_id);
+
+ bool GetDeletableResponseIds(std::vector<int64>* response_ids,
+ int64 max_rowid, int limit);
+ bool InsertDeletableResponseIds(const std::vector<int64>& response_ids);
+ bool DeleteDeletableResponseIds(const std::vector<int64>& response_ids);
+
+ // So our callers can wrap operations in transactions.
+ sql::Connection* db_connection() {
+ LazyOpen(true);
+ return db_.get();
+ }
+
+ private:
+ bool RunCachedStatementWithIds(
+ const sql::StatementID& statement_id, const char* sql,
+ const std::vector<int64>& ids);
+ bool RunUniqueStatementWithInt64Result(const char* sql, int64* result);
+
+ bool FindResponseIdsForCacheHelper(
+ int64 cache_id, std::vector<int64>* ids_vector,
+ std::set<int64>* ids_set);
+
+ // Record retrieval helpers
+ void ReadGroupRecord(const sql::Statement& statement, GroupRecord* record);
+ void ReadCacheRecord(const sql::Statement& statement, CacheRecord* record);
+ void ReadEntryRecord(const sql::Statement& statement, EntryRecord* record);
+ void ReadNamespaceRecords(
+ sql::Statement* statement,
+ NamespaceRecordVector* intercepts,
+ NamespaceRecordVector* fallbacks);
+ void ReadNamespaceRecord(
+ const sql::Statement* statement, NamespaceRecord* record);
+ void ReadOnlineWhiteListRecord(
+ const sql::Statement& statement, OnlineWhiteListRecord* record);
+
+ // Database creation
+ bool LazyOpen(bool create_if_needed);
+ bool EnsureDatabaseVersion();
+ bool CreateSchema();
+ bool UpgradeSchema();
+
+ void ResetConnectionAndTables();
+
+ // Deletes the existing database file and the entire directory containing
+ // the database file including the disk cache in which response headers
+ // and bodies are stored, and then creates a new database file.
+ bool DeleteExistingAndCreateNewDatabase();
+
+ void OnDatabaseError(int err, sql::Statement* stmt);
+
+ base::FilePath db_file_path_;
+ scoped_ptr<sql::Connection> db_;
+ scoped_ptr<sql::MetaTable> meta_table_;
+ bool is_disabled_;
+ bool is_recreating_;
+ bool was_corruption_detected_;
+
+ friend class content::AppCacheDatabaseTest;
+ friend class content::AppCacheStorageImplTest;
+
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, CacheRecords);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, EntryRecords);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, QuickIntegrityCheck);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, NamespaceRecords);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, GroupRecords);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, LazyOpen);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, ExperimentalFlags);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest,
+ OnlineWhiteListRecords);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, ReCreate);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, DeletableResponseIds);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, OriginUsage);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema3to5);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, UpgradeSchema4to5);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheDatabaseTest, WasCorrutionDetected);
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheDatabase);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_DATABASE_H_
diff --git a/chromium/content/browser/appcache/appcache_database_unittest.cc b/chromium/content/browser/appcache/appcache_database_unittest.cc
index 92fa6a57d91..11aa683c87a 100644
--- a/chromium/content/browser/appcache/appcache_database_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_database_unittest.cc
@@ -3,9 +3,11 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
+#include "content/browser/appcache/appcache_database.h"
+#include "content/browser/appcache/appcache_entry.h"
#include "sql/connection.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
@@ -14,14 +16,6 @@
#include "sql/transaction.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"
-#include "webkit/browser/appcache/appcache_database.h"
-#include "webkit/browser/appcache/appcache_entry.h"
-
-using appcache::AppCacheDatabase;
-using appcache::AppCacheEntry;
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::APPCACHE_INTERCEPT_NAMESPACE;
-using appcache::APPCACHE_NETWORK_NAMESPACE;
namespace {
@@ -873,8 +867,8 @@ TEST(AppCacheDatabaseTest, UpgradeSchema3to5) {
true },
};
- const int kTableCount3 = ARRAYSIZE_UNSAFE(kTables3);
- const int kIndexCount3 = ARRAYSIZE_UNSAFE(kIndexes3);
+ const int kTableCount3 = arraysize(kTables3);
+ const int kIndexCount3 = arraysize(kIndexes3);
sql::Connection connection;
EXPECT_TRUE(connection.Open(kDbFile));
@@ -1103,8 +1097,8 @@ TEST(AppCacheDatabaseTest, UpgradeSchema4to5) {
true },
};
- const int kTableCount4 = ARRAYSIZE_UNSAFE(kTables4);
- const int kIndexCount4 = ARRAYSIZE_UNSAFE(kIndexes4);
+ const int kTableCount4 = arraysize(kTables4);
+ const int kIndexCount4 = arraysize(kIndexes4);
sql::Connection connection;
EXPECT_TRUE(connection.Open(kDbFile));
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
new file mode 100644
index 00000000000..382ed45fed2
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -0,0 +1,372 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_disk_cache.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/base/cache_type.h"
+#include "net/base/net_errors.h"
+
+namespace content {
+
+// A callback shim that provides storage for the 'backend_ptr' value
+// and will delete a resulting ptr if completion occurs after its
+// been canceled.
+class AppCacheDiskCache::CreateBackendCallbackShim
+ : public base::RefCounted<CreateBackendCallbackShim> {
+ public:
+ explicit CreateBackendCallbackShim(AppCacheDiskCache* object)
+ : appcache_diskcache_(object) {
+ }
+
+ void Cancel() {
+ appcache_diskcache_ = NULL;
+ }
+
+ void Callback(int rv) {
+ if (appcache_diskcache_)
+ appcache_diskcache_->OnCreateBackendComplete(rv);
+ }
+
+ scoped_ptr<disk_cache::Backend> backend_ptr_; // Accessed directly.
+
+ private:
+ friend class base::RefCounted<CreateBackendCallbackShim>;
+
+ ~CreateBackendCallbackShim() {
+ }
+
+ AppCacheDiskCache* appcache_diskcache_; // Unowned pointer.
+};
+
+// An implementation of AppCacheDiskCacheInterface::Entry that's a thin
+// wrapper around disk_cache::Entry.
+class AppCacheDiskCache::EntryImpl : public Entry {
+ public:
+ EntryImpl(disk_cache::Entry* disk_cache_entry,
+ AppCacheDiskCache* owner)
+ : disk_cache_entry_(disk_cache_entry), owner_(owner) {
+ DCHECK(disk_cache_entry);
+ DCHECK(owner);
+ owner_->AddOpenEntry(this);
+ }
+
+ // Entry implementation.
+ int Read(int index,
+ int64 offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ const net::CompletionCallback& callback) override {
+ if (offset < 0 || offset > kint32max)
+ return net::ERR_INVALID_ARGUMENT;
+ if (!disk_cache_entry_)
+ return net::ERR_ABORTED;
+ return disk_cache_entry_->ReadData(
+ index, static_cast<int>(offset), buf, buf_len, callback);
+ }
+
+ int Write(int index,
+ int64 offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ const net::CompletionCallback& callback) override {
+ if (offset < 0 || offset > kint32max)
+ return net::ERR_INVALID_ARGUMENT;
+ if (!disk_cache_entry_)
+ return net::ERR_ABORTED;
+ const bool kTruncate = true;
+ return disk_cache_entry_->WriteData(
+ index, static_cast<int>(offset), buf, buf_len, callback, kTruncate);
+ }
+
+ int64 GetSize(int index) override {
+ return disk_cache_entry_ ? disk_cache_entry_->GetDataSize(index) : 0L;
+ }
+
+ void Close() override {
+ if (disk_cache_entry_)
+ disk_cache_entry_->Close();
+ delete this;
+ }
+
+ void Abandon() {
+ owner_ = NULL;
+ disk_cache_entry_->Close();
+ disk_cache_entry_ = NULL;
+ }
+
+ private:
+ ~EntryImpl() override {
+ if (owner_)
+ owner_->RemoveOpenEntry(this);
+ }
+
+ disk_cache::Entry* disk_cache_entry_;
+ AppCacheDiskCache* owner_;
+};
+
+// Separate object to hold state for each Create, Delete, or Doom call
+// while the call is in-flight and to produce an EntryImpl upon completion.
+class AppCacheDiskCache::ActiveCall {
+ public:
+ explicit ActiveCall(AppCacheDiskCache* owner)
+ : entry_(NULL),
+ owner_(owner),
+ entry_ptr_(NULL) {
+ }
+
+ int CreateEntry(int64 key, Entry** entry,
+ const net::CompletionCallback& callback) {
+ int rv = owner_->disk_cache()->CreateEntry(
+ base::Int64ToString(key), &entry_ptr_,
+ base::Bind(&ActiveCall::OnAsyncCompletion, base::Unretained(this)));
+ return HandleImmediateReturnValue(rv, entry, callback);
+ }
+
+ int OpenEntry(int64 key, Entry** entry,
+ const net::CompletionCallback& callback) {
+ int rv = owner_->disk_cache()->OpenEntry(
+ base::Int64ToString(key), &entry_ptr_,
+ base::Bind(&ActiveCall::OnAsyncCompletion, base::Unretained(this)));
+ return HandleImmediateReturnValue(rv, entry, callback);
+ }
+
+ int DoomEntry(int64 key, const net::CompletionCallback& callback) {
+ int rv = owner_->disk_cache()->DoomEntry(
+ base::Int64ToString(key),
+ base::Bind(&ActiveCall::OnAsyncCompletion, base::Unretained(this)));
+ return HandleImmediateReturnValue(rv, NULL, callback);
+ }
+
+ private:
+ int HandleImmediateReturnValue(int rv, Entry** entry,
+ const net::CompletionCallback& callback) {
+ if (rv == net::ERR_IO_PENDING) {
+ // OnAsyncCompletion will be called later.
+ callback_ = callback;
+ entry_ = entry;
+ owner_->AddActiveCall(this);
+ return net::ERR_IO_PENDING;
+ }
+ if (rv == net::OK && entry)
+ *entry = new EntryImpl(entry_ptr_, owner_);
+ delete this;
+ return rv;
+ }
+
+ void OnAsyncCompletion(int rv) {
+ owner_->RemoveActiveCall(this);
+ if (rv == net::OK && entry_)
+ *entry_ = new EntryImpl(entry_ptr_, owner_);
+ callback_.Run(rv);
+ callback_.Reset();
+ delete this;
+ }
+
+ Entry** entry_;
+ net::CompletionCallback callback_;
+ AppCacheDiskCache* owner_;
+ disk_cache::Entry* entry_ptr_;
+};
+
+AppCacheDiskCache::AppCacheDiskCache()
+ : is_disabled_(false) {
+}
+
+AppCacheDiskCache::~AppCacheDiskCache() {
+ Disable();
+}
+
+int AppCacheDiskCache::InitWithDiskBackend(
+ const base::FilePath& disk_cache_directory,
+ int disk_cache_size,
+ bool force,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
+ const net::CompletionCallback& callback) {
+ return Init(net::APP_CACHE,
+ disk_cache_directory,
+ disk_cache_size,
+ force,
+ cache_thread,
+ callback);
+}
+
+int AppCacheDiskCache::InitWithMemBackend(
+ int mem_cache_size, const net::CompletionCallback& callback) {
+ return Init(net::MEMORY_CACHE, base::FilePath(), mem_cache_size, false, NULL,
+ callback);
+}
+
+void AppCacheDiskCache::Disable() {
+ if (is_disabled_)
+ return;
+
+ is_disabled_ = true;
+
+ if (create_backend_callback_.get()) {
+ create_backend_callback_->Cancel();
+ create_backend_callback_ = NULL;
+ OnCreateBackendComplete(net::ERR_ABORTED);
+ }
+
+ // We need to close open file handles in order to reinitalize the
+ // appcache system on the fly. File handles held in both entries and in
+ // the main disk_cache::Backend class need to be released.
+ for (OpenEntries::const_iterator iter = open_entries_.begin();
+ iter != open_entries_.end(); ++iter) {
+ (*iter)->Abandon();
+ }
+ open_entries_.clear();
+ disk_cache_.reset();
+ STLDeleteElements(&active_calls_);
+}
+
+int AppCacheDiskCache::CreateEntry(int64 key, Entry** entry,
+ const net::CompletionCallback& callback) {
+ DCHECK(entry);
+ DCHECK(!callback.is_null());
+ if (is_disabled_)
+ return net::ERR_ABORTED;
+
+ if (is_initializing()) {
+ pending_calls_.push_back(PendingCall(CREATE, key, entry, callback));
+ return net::ERR_IO_PENDING;
+ }
+
+ if (!disk_cache_)
+ return net::ERR_FAILED;
+
+ return (new ActiveCall(this))->CreateEntry(key, entry, callback);
+}
+
+int AppCacheDiskCache::OpenEntry(int64 key, Entry** entry,
+ const net::CompletionCallback& callback) {
+ DCHECK(entry);
+ DCHECK(!callback.is_null());
+ if (is_disabled_)
+ return net::ERR_ABORTED;
+
+ if (is_initializing()) {
+ pending_calls_.push_back(PendingCall(OPEN, key, entry, callback));
+ return net::ERR_IO_PENDING;
+ }
+
+ if (!disk_cache_)
+ return net::ERR_FAILED;
+
+ return (new ActiveCall(this))->OpenEntry(key, entry, callback);
+}
+
+int AppCacheDiskCache::DoomEntry(int64 key,
+ const net::CompletionCallback& callback) {
+ DCHECK(!callback.is_null());
+ if (is_disabled_)
+ return net::ERR_ABORTED;
+
+ if (is_initializing()) {
+ pending_calls_.push_back(PendingCall(DOOM, key, NULL, callback));
+ return net::ERR_IO_PENDING;
+ }
+
+ if (!disk_cache_)
+ return net::ERR_FAILED;
+
+ return (new ActiveCall(this))->DoomEntry(key, callback);
+}
+
+AppCacheDiskCache::PendingCall::PendingCall()
+ : call_type(CREATE),
+ key(0),
+ entry(NULL) {
+}
+
+AppCacheDiskCache::PendingCall::PendingCall(PendingCallType call_type,
+ int64 key,
+ Entry** entry,
+ const net::CompletionCallback& callback)
+ : call_type(call_type),
+ key(key),
+ entry(entry),
+ callback(callback) {
+}
+
+AppCacheDiskCache::PendingCall::~PendingCall() {}
+
+int AppCacheDiskCache::Init(
+ net::CacheType cache_type,
+ const base::FilePath& cache_directory,
+ int cache_size,
+ bool force,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
+ const net::CompletionCallback& callback) {
+ DCHECK(!is_initializing() && !disk_cache_.get());
+ is_disabled_ = false;
+ create_backend_callback_ = new CreateBackendCallbackShim(this);
+
+#if defined(APPCACHE_USE_SIMPLE_CACHE)
+ const net::BackendType backend_type = net::CACHE_BACKEND_SIMPLE;
+#else
+ const net::BackendType backend_type = net::CACHE_BACKEND_DEFAULT;
+#endif
+ int rv = disk_cache::CreateCacheBackend(
+ cache_type,
+ backend_type,
+ cache_directory,
+ cache_size,
+ force,
+ cache_thread,
+ NULL,
+ &(create_backend_callback_->backend_ptr_),
+ base::Bind(&CreateBackendCallbackShim::Callback,
+ create_backend_callback_));
+ if (rv == net::ERR_IO_PENDING)
+ init_callback_ = callback;
+ else
+ OnCreateBackendComplete(rv);
+ return rv;
+}
+
+void AppCacheDiskCache::OnCreateBackendComplete(int rv) {
+ if (rv == net::OK) {
+ disk_cache_ = create_backend_callback_->backend_ptr_.Pass();
+ }
+ create_backend_callback_ = NULL;
+
+ // Invoke our clients callback function.
+ if (!init_callback_.is_null()) {
+ init_callback_.Run(rv);
+ init_callback_.Reset();
+ }
+
+ // Service pending calls that were queued up while we were initializing.
+ for (PendingCalls::const_iterator iter = pending_calls_.begin();
+ iter < pending_calls_.end(); ++iter) {
+ int rv = net::ERR_FAILED;
+ switch (iter->call_type) {
+ case CREATE:
+ rv = CreateEntry(iter->key, iter->entry, iter->callback);
+ break;
+ case OPEN:
+ rv = OpenEntry(iter->key, iter->entry, iter->callback);
+ break;
+ case DOOM:
+ rv = DoomEntry(iter->key, iter->callback);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ if (rv != net::ERR_IO_PENDING)
+ iter->callback.Run(rv);
+ }
+ pending_calls_.clear();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.h b/chromium/content/browser/appcache/appcache_disk_cache.h
new file mode 100644
index 00000000000..8995e83cf71
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_disk_cache.h
@@ -0,0 +1,115 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_DISK_CACHE_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_DISK_CACHE_H_
+
+#include <set>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/common/content_export.h"
+#include "net/disk_cache/disk_cache.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace content {
+
+// An implementation of AppCacheDiskCacheInterface that
+// uses net::DiskCache as the backing store.
+class CONTENT_EXPORT AppCacheDiskCache
+ : public AppCacheDiskCacheInterface {
+ public:
+ AppCacheDiskCache();
+ ~AppCacheDiskCache() override;
+
+ // Initializes the object to use disk backed storage.
+ int InitWithDiskBackend(
+ const base::FilePath& disk_cache_directory,
+ int disk_cache_size,
+ bool force,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
+ const net::CompletionCallback& callback);
+
+ // Initializes the object to use memory only storage.
+ // This is used for Chrome's incognito browsing.
+ int InitWithMemBackend(int disk_cache_size,
+ const net::CompletionCallback& callback);
+
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
+
+ int CreateEntry(int64 key,
+ Entry** entry,
+ const net::CompletionCallback& callback) override;
+ int OpenEntry(int64 key,
+ Entry** entry,
+ const net::CompletionCallback& callback) override;
+ int DoomEntry(int64 key, const net::CompletionCallback& callback) override;
+
+ private:
+ class CreateBackendCallbackShim;
+ class EntryImpl;
+
+ // PendingCalls allow CreateEntry, OpenEntry, and DoomEntry to be called
+ // immediately after construction, without waiting for the
+ // underlying disk_cache::Backend to be fully constructed. Early
+ // calls are queued up and serviced once the disk_cache::Backend is
+ // really ready to go.
+ enum PendingCallType {
+ CREATE,
+ OPEN,
+ DOOM
+ };
+ struct PendingCall {
+ PendingCallType call_type;
+ int64 key;
+ Entry** entry;
+ net::CompletionCallback callback;
+
+ PendingCall();
+
+ PendingCall(PendingCallType call_type, int64 key,
+ Entry** entry, const net::CompletionCallback& callback);
+
+ ~PendingCall();
+ };
+ typedef std::vector<PendingCall> PendingCalls;
+
+ class ActiveCall;
+ typedef std::set<ActiveCall*> ActiveCalls;
+ typedef std::set<EntryImpl*> OpenEntries;
+
+ bool is_initializing() const {
+ return create_backend_callback_.get() != NULL;
+ }
+ disk_cache::Backend* disk_cache() { return disk_cache_.get(); }
+ int Init(net::CacheType cache_type,
+ const base::FilePath& directory,
+ int cache_size,
+ bool force,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread,
+ const net::CompletionCallback& callback);
+ void OnCreateBackendComplete(int rv);
+ void AddActiveCall(ActiveCall* call) { active_calls_.insert(call); }
+ void RemoveActiveCall(ActiveCall* call) { active_calls_.erase(call); }
+ void AddOpenEntry(EntryImpl* entry) { open_entries_.insert(entry); }
+ void RemoveOpenEntry(EntryImpl* entry) { open_entries_.erase(entry); }
+
+ bool is_disabled_;
+ net::CompletionCallback init_callback_;
+ scoped_refptr<CreateBackendCallbackShim> create_backend_callback_;
+ PendingCalls pending_calls_;
+ ActiveCalls active_calls_;
+ OpenEntries open_entries_;
+ scoped_ptr<disk_cache::Backend> disk_cache_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_DISK_CACHE_H_
diff --git a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
index 5e1e083ebdc..b9c67cf9a97 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache_unittest.cc
@@ -3,16 +3,15 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/browser/appcache/appcache_disk_cache.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_disk_cache.h"
-
-using appcache::AppCacheDiskCache;
namespace content {
@@ -20,17 +19,17 @@ class AppCacheDiskCacheTest : public testing::Test {
public:
AppCacheDiskCacheTest() {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
// Use the current thread for the DiskCache's cache_thread.
message_loop_.reset(new base::MessageLoopForIO());
- cache_thread_ = base::MessageLoopProxy::current();
+ cache_thread_ = base::ThreadTaskRunnerHandle::Get();
ASSERT_TRUE(directory_.CreateUniqueTempDir());
completion_callback_ = base::Bind(
&AppCacheDiskCacheTest::OnComplete,
base::Unretained(this));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
base::RunLoop().RunUntilIdle();
message_loop_.reset(NULL);
}
@@ -45,7 +44,7 @@ class AppCacheDiskCacheTest : public testing::Test {
base::ScopedTempDir directory_;
scoped_ptr<base::MessageLoop> message_loop_;
- scoped_refptr<base::MessageLoopProxy> cache_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
net::CompletionCallback completion_callback_;
std::vector<int> completion_results_;
@@ -60,8 +59,7 @@ TEST_F(AppCacheDiskCacheTest, DisablePriorToInitCompletion) {
scoped_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
disk_cache->InitWithDiskBackend(
- directory_.path(), k10MBytes, false, cache_thread_,
- completion_callback_);
+ directory_.path(), k10MBytes, false, cache_thread_, completion_callback_);
disk_cache->CreateEntry(1, &entry, completion_callback_);
disk_cache->OpenEntry(2, &entry, completion_callback_);
disk_cache->DoomEntry(3, completion_callback_);
@@ -92,8 +90,7 @@ TEST_F(AppCacheDiskCacheTest, DisableAfterInitted) {
scoped_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
disk_cache->InitWithDiskBackend(
- directory_.path(), k10MBytes, false, cache_thread_,
- completion_callback_);
+ directory_.path(), k10MBytes, false, cache_thread_, completion_callback_);
FlushCacheTasks();
EXPECT_EQ(1u, completion_results_.size());
EXPECT_EQ(net::OK, completion_results_[0]);
@@ -128,8 +125,7 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
scoped_ptr<AppCacheDiskCache> disk_cache(new AppCacheDiskCache);
EXPECT_FALSE(disk_cache->is_disabled());
disk_cache->InitWithDiskBackend(
- directory_.path(), k10MBytes, false, cache_thread_,
- completion_callback_);
+ directory_.path(), k10MBytes, false, cache_thread_, completion_callback_);
FlushCacheTasks();
EXPECT_EQ(1u, completion_results_.size());
EXPECT_EQ(net::OK, completion_results_[0]);
@@ -155,7 +151,7 @@ TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
const char* kData = "Hello";
const int kDataLen = strlen(kData) + 1;
scoped_refptr<net::IOBuffer> write_buf(new net::WrappedIOBuffer(kData));
- entry1->Write(0, 0, write_buf, kDataLen, completion_callback_);
+ entry1->Write(0, 0, write_buf.get(), kDataLen, completion_callback_);
FlushCacheTasks();
// Queue up a read and a write.
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.cc b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
index 64e46b188a5..eac1effaf97 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.cc
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.cc
@@ -103,7 +103,7 @@ void AppCacheDispatcherHost::OnSelectCache(
BadMessageReceived();
}
} else {
- frontend_proxy_.OnCacheSelected(host_id, appcache::AppCacheInfo());
+ frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
}
}
@@ -115,7 +115,7 @@ void AppCacheDispatcherHost::OnSelectCacheForWorker(
BadMessageReceived();
}
} else {
- frontend_proxy_.OnCacheSelected(host_id, appcache::AppCacheInfo());
+ frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
}
}
@@ -125,7 +125,7 @@ void AppCacheDispatcherHost::OnSelectCacheForSharedWorker(
if (!backend_impl_.SelectCacheForSharedWorker(host_id, appcache_id))
BadMessageReceived();
} else {
- frontend_proxy_.OnCacheSelected(host_id, appcache::AppCacheInfo());
+ frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
}
}
@@ -141,7 +141,7 @@ void AppCacheDispatcherHost::OnMarkAsForeignEntry(
}
void AppCacheDispatcherHost::OnGetResourceList(
- int host_id, std::vector<appcache::AppCacheResourceInfo>* params) {
+ int host_id, std::vector<AppCacheResourceInfo>* params) {
if (appcache_service_.get())
backend_impl_.GetResourceList(host_id, params);
}
@@ -162,7 +162,7 @@ void AppCacheDispatcherHost::OnGetStatus(int host_id, IPC::Message* reply_msg) {
return;
}
- GetStatusCallback(appcache::APPCACHE_STATUS_UNCACHED, reply_msg);
+ GetStatusCallback(APPCACHE_STATUS_UNCACHED, reply_msg);
}
void AppCacheDispatcherHost::OnStartUpdate(int host_id,
@@ -205,7 +205,7 @@ void AppCacheDispatcherHost::OnSwapCache(int host_id, IPC::Message* reply_msg) {
}
void AppCacheDispatcherHost::GetStatusCallback(
- appcache::AppCacheStatus status, void* param) {
+ AppCacheStatus status, void* param) {
IPC::Message* reply_msg = reinterpret_cast<IPC::Message*>(param);
DCHECK_EQ(pending_reply_msg_.get(), reply_msg);
AppCacheHostMsg_GetStatus::WriteReplyParams(reply_msg, status);
diff --git a/chromium/content/browser/appcache/appcache_dispatcher_host.h b/chromium/content/browser/appcache/appcache_dispatcher_host.h
index 8bad796d29e..c0a615ed259 100644
--- a/chromium/content/browser/appcache/appcache_dispatcher_host.h
+++ b/chromium/content/browser/appcache/appcache_dispatcher_host.h
@@ -10,9 +10,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_frontend_proxy.h"
#include "content/public/browser/browser_message_filter.h"
-#include "webkit/browser/appcache/appcache_backend_impl.h"
namespace content {
class ChromeAppCacheService;
@@ -27,14 +27,14 @@ class AppCacheDispatcherHost : public BrowserMessageFilter {
int process_id);
// BrowserIOMessageFilter implementation
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelConnected(int32 peer_pid) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~AppCacheDispatcherHost();
+ ~AppCacheDispatcherHost() override;
// BrowserMessageFilter override.
- virtual void BadMessageReceived() OVERRIDE;
+ void BadMessageReceived() override;
private:
// IPC message handlers
@@ -54,19 +54,19 @@ class AppCacheDispatcherHost : public BrowserMessageFilter {
void OnSwapCache(int host_id, IPC::Message* reply_msg);
void OnGetResourceList(
int host_id,
- std::vector<appcache::AppCacheResourceInfo>* resource_infos);
- void GetStatusCallback(appcache::AppCacheStatus status, void* param);
+ std::vector<AppCacheResourceInfo>* resource_infos);
+ void GetStatusCallback(AppCacheStatus status, void* param);
void StartUpdateCallback(bool result, void* param);
void SwapCacheCallback(bool result, void* param);
scoped_refptr<ChromeAppCacheService> appcache_service_;
AppCacheFrontendProxy frontend_proxy_;
- appcache::AppCacheBackendImpl backend_impl_;
+ AppCacheBackendImpl backend_impl_;
- appcache::GetStatusCallback get_status_callback_;
- appcache::StartUpdateCallback start_update_callback_;
- appcache::SwapCacheCallback swap_cache_callback_;
+ content::GetStatusCallback get_status_callback_;
+ content::StartUpdateCallback start_update_callback_;
+ content::SwapCacheCallback swap_cache_callback_;
scoped_ptr<IPC::Message> pending_reply_msg_;
// The corresponding ChildProcessHost object's id().
diff --git a/chromium/content/browser/appcache/appcache_entry.h b/chromium/content/browser/appcache/appcache_entry.h
new file mode 100644
index 00000000000..5c4fffd2ff5
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_entry.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_ENTRY_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_ENTRY_H_
+
+#include "content/common/appcache_interfaces.h"
+
+namespace content {
+
+// A cached entry is identified by a URL and is classified into one
+// (or more) categories. URL is not stored here as this class is stored
+// with the URL as a map key or the user of this class already knows the URL.
+class AppCacheEntry {
+ public:
+
+ // An entry can be of more than one type so use a bitmask.
+ // Note: These bit values are stored on disk.
+ enum Type {
+ MASTER = 1 << 0,
+ MANIFEST = 1 << 1,
+ EXPLICIT = 1 << 2,
+ FOREIGN = 1 << 3,
+ FALLBACK = 1 << 4,
+ INTERCEPT = 1 << 5,
+ EXECUTABLE = 1 << 6,
+ };
+
+ AppCacheEntry()
+ : types_(0), response_id_(kAppCacheNoResponseId), response_size_(0) {}
+
+ explicit AppCacheEntry(int type)
+ : types_(type), response_id_(kAppCacheNoResponseId), response_size_(0) {}
+
+ AppCacheEntry(int type, int64 response_id)
+ : types_(type), response_id_(response_id), response_size_(0) {}
+
+ AppCacheEntry(int type, int64 response_id, int64 response_size)
+ : types_(type), response_id_(response_id), response_size_(response_size) {}
+
+ int types() const { return types_; }
+ void add_types(int added_types) { types_ |= added_types; }
+ bool IsMaster() const { return (types_ & MASTER) != 0; }
+ bool IsManifest() const { return (types_ & MANIFEST) != 0; }
+ bool IsExplicit() const { return (types_ & EXPLICIT) != 0; }
+ bool IsForeign() const { return (types_ & FOREIGN) != 0; }
+ bool IsFallback() const { return (types_ & FALLBACK) != 0; }
+ bool IsIntercept() const { return (types_ & INTERCEPT) != 0; }
+ bool IsExecutable() const { return (types_ & EXECUTABLE) != 0; }
+
+ int64 response_id() const { return response_id_; }
+ void set_response_id(int64 id) { response_id_ = id; }
+ bool has_response_id() const { return response_id_ != kAppCacheNoResponseId; }
+
+ int64 response_size() const { return response_size_; }
+ void set_response_size(int64 size) { response_size_ = size; }
+
+ private:
+ int types_;
+ int64 response_id_;
+ int64 response_size_;
+};
+
+} // namespace content
+
+#endif // WEBKIT_APPCACHE_APPCACHE_RESOURCE_H_
diff --git a/chromium/content/browser/appcache/appcache_executable_handler.h b/chromium/content/browser/appcache/appcache_executable_handler.h
new file mode 100644
index 00000000000..445a6cd12a3
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_executable_handler.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2013 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 CONTENT_BROWSER_APPCACHE_APPCACHE_EXECUTABLE_HANDLER_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_EXECUTABLE_HANDLER_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace net {
+class IOBuffer;
+class URLRequest;
+}
+
+namespace content {
+
+// An interface that must be provided by the embedder to support this feature.
+class CONTENT_EXPORT AppCacheExecutableHandler {
+ public:
+ // A handler can respond in one of 4 ways, if each of the GURL fields
+ // in 'Response' are empty and use_network is false, an error response is
+ // synthesized.
+ struct Response {
+ GURL cached_resource_url;
+ GURL redirect_url;
+ bool use_network;
+ // TODO: blob + headers would be a good one to provide as well, as it would
+ // make templating possible.
+ };
+ typedef base::Callback<void(const Response&)> ResponseCallback;
+
+ // Deletion of the handler cancels all pending callbacks.
+ virtual ~AppCacheExecutableHandler() {}
+
+ virtual void HandleRequest(net::URLRequest* req,
+ ResponseCallback callback) = 0;
+};
+
+// A factory to produce instances.
+class CONTENT_EXPORT AppCacheExecutableHandlerFactory {
+ public:
+ virtual scoped_ptr<AppCacheExecutableHandler> CreateHandler(
+ const GURL& handler_url, net::IOBuffer* handler_source) = 0;
+
+ protected:
+ virtual ~AppCacheExecutableHandlerFactory() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_EXECUTABLE_HANDLER_H_
diff --git a/chromium/content/browser/appcache/appcache_frontend_proxy.cc b/chromium/content/browser/appcache/appcache_frontend_proxy.cc
index ea693e9d71e..4242304acb0 100644
--- a/chromium/content/browser/appcache/appcache_frontend_proxy.cc
+++ b/chromium/content/browser/appcache/appcache_frontend_proxy.cc
@@ -13,18 +13,18 @@ AppCacheFrontendProxy::AppCacheFrontendProxy(IPC::Sender* sender)
}
void AppCacheFrontendProxy::OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) {
+ int host_id, const AppCacheInfo& info) {
sender_->Send(new AppCacheMsg_CacheSelected(host_id, info));
}
void AppCacheFrontendProxy::OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) {
+ AppCacheStatus status) {
sender_->Send(new AppCacheMsg_StatusChanged(host_ids, status));
}
void AppCacheFrontendProxy::OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) {
- DCHECK_NE(appcache::APPCACHE_PROGRESS_EVENT,
+ AppCacheEventID event_id) {
+ DCHECK_NE(APPCACHE_PROGRESS_EVENT,
event_id); // See OnProgressEventRaised.
sender_->Send(new AppCacheMsg_EventRaised(host_ids, event_id));
}
@@ -38,12 +38,12 @@ void AppCacheFrontendProxy::OnProgressEventRaised(
void AppCacheFrontendProxy::OnErrorEventRaised(
const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details) {
+ const AppCacheErrorDetails& details) {
sender_->Send(new AppCacheMsg_ErrorEventRaised(host_ids, details));
}
void AppCacheFrontendProxy::OnLogMessage(int host_id,
- appcache::AppCacheLogLevel log_level,
+ AppCacheLogLevel log_level,
const std::string& message) {
sender_->Send(new AppCacheMsg_LogMessage(host_id, log_level, message));
}
diff --git a/chromium/content/browser/appcache/appcache_frontend_proxy.h b/chromium/content/browser/appcache/appcache_frontend_proxy.h
index 904c8aed5c1..65d03ee8d2e 100644
--- a/chromium/content/browser/appcache/appcache_frontend_proxy.h
+++ b/chromium/content/browser/appcache/appcache_frontend_proxy.h
@@ -8,33 +8,32 @@
#include <string>
#include <vector>
+#include "content/common/appcache_interfaces.h"
#include "ipc/ipc_sender.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
namespace content {
// Sends appcache related messages to a child process.
-class AppCacheFrontendProxy : public appcache::AppCacheFrontend {
+class AppCacheFrontendProxy : public AppCacheFrontend {
public:
explicit AppCacheFrontendProxy(IPC::Sender* sender);
// AppCacheFrontend methods
- virtual void OnCacheSelected(int host_id,
- const appcache::AppCacheInfo& info) OVERRIDE;
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) OVERRIDE;
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) OVERRIDE;
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total, int num_complete) OVERRIDE;
- virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details)
- OVERRIDE;
- virtual void OnLogMessage(int host_id, appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE;
- virtual void OnContentBlocked(int host_id,
- const GURL& manifest_url) OVERRIDE;
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override;
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override;
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override;
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override;
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override;
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override;
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override;
private:
IPC::Sender* sender_;
diff --git a/chromium/content/browser/appcache/appcache_group.cc b/chromium/content/browser/appcache/appcache_group.cc
new file mode 100644
index 00000000000..7ebd2890ba4
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_group.cc
@@ -0,0 +1,264 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_group.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/browser/appcache/appcache_update_job.h"
+
+namespace content {
+
+class AppCacheGroup;
+
+// Use this helper class because we cannot make AppCacheGroup a derived class
+// of AppCacheHost::Observer as it would create a circular dependency between
+// AppCacheHost and AppCacheGroup.
+class AppCacheGroup::HostObserver : public AppCacheHost::Observer {
+ public:
+ explicit HostObserver(AppCacheGroup* group) : group_(group) {}
+
+ // Methods for AppCacheHost::Observer.
+ void OnCacheSelectionComplete(AppCacheHost* host) override {} // N/A
+ void OnDestructionImminent(AppCacheHost* host) override {
+ group_->HostDestructionImminent(host);
+ }
+ private:
+ AppCacheGroup* group_;
+};
+
+AppCacheGroup::AppCacheGroup(AppCacheStorage* storage,
+ const GURL& manifest_url,
+ int64 group_id)
+ : group_id_(group_id),
+ manifest_url_(manifest_url),
+ update_status_(IDLE),
+ is_obsolete_(false),
+ is_being_deleted_(false),
+ newest_complete_cache_(NULL),
+ update_job_(NULL),
+ storage_(storage),
+ is_in_dtor_(false) {
+ storage_->working_set()->AddGroup(this);
+ host_observer_.reset(new HostObserver(this));
+}
+
+AppCacheGroup::~AppCacheGroup() {
+ DCHECK(old_caches_.empty());
+ DCHECK(!newest_complete_cache_);
+ DCHECK(restart_update_task_.IsCancelled());
+ DCHECK(queued_updates_.empty());
+
+ is_in_dtor_ = true;
+
+ if (update_job_)
+ delete update_job_;
+ DCHECK_EQ(IDLE, update_status_);
+
+ storage_->working_set()->RemoveGroup(this);
+ storage_->DeleteResponses(manifest_url_, newly_deletable_response_ids_);
+}
+
+void AppCacheGroup::AddUpdateObserver(UpdateObserver* observer) {
+ // If observer being added is a host that has been queued for later update,
+ // add observer to a different observer list.
+ AppCacheHost* host = static_cast<AppCacheHost*>(observer);
+ if (queued_updates_.find(host) != queued_updates_.end())
+ queued_observers_.AddObserver(observer);
+ else
+ observers_.AddObserver(observer);
+}
+
+void AppCacheGroup::RemoveUpdateObserver(UpdateObserver* observer) {
+ observers_.RemoveObserver(observer);
+ queued_observers_.RemoveObserver(observer);
+}
+
+void AppCacheGroup::AddCache(AppCache* complete_cache) {
+ DCHECK(complete_cache->is_complete());
+ complete_cache->set_owning_group(this);
+
+ if (!newest_complete_cache_) {
+ newest_complete_cache_ = complete_cache;
+ return;
+ }
+
+ if (complete_cache->IsNewerThan(newest_complete_cache_)) {
+ old_caches_.push_back(newest_complete_cache_);
+ newest_complete_cache_ = complete_cache;
+
+ // Update hosts of older caches to add a reference to the newest cache.
+ for (Caches::iterator it = old_caches_.begin();
+ it != old_caches_.end(); ++it) {
+ AppCache::AppCacheHosts& hosts = (*it)->associated_hosts();
+ for (AppCache::AppCacheHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ (*host_it)->SetSwappableCache(this);
+ }
+ }
+ } else {
+ old_caches_.push_back(complete_cache);
+ }
+}
+
+void AppCacheGroup::RemoveCache(AppCache* cache) {
+ DCHECK(cache->associated_hosts().empty());
+ if (cache == newest_complete_cache_) {
+ AppCache* tmp_cache = newest_complete_cache_;
+ newest_complete_cache_ = NULL;
+ tmp_cache->set_owning_group(NULL); // may cause this group to be deleted
+ } else {
+ scoped_refptr<AppCacheGroup> protect(this);
+
+ Caches::iterator it =
+ std::find(old_caches_.begin(), old_caches_.end(), cache);
+ if (it != old_caches_.end()) {
+ AppCache* tmp_cache = *it;
+ old_caches_.erase(it);
+ tmp_cache->set_owning_group(NULL); // may cause group to be released
+ }
+
+ if (!is_obsolete() && old_caches_.empty() &&
+ !newly_deletable_response_ids_.empty()) {
+ storage_->DeleteResponses(manifest_url_, newly_deletable_response_ids_);
+ newly_deletable_response_ids_.clear();
+ }
+ }
+}
+
+void AppCacheGroup::AddNewlyDeletableResponseIds(
+ std::vector<int64>* response_ids) {
+ if (is_being_deleted() || (!is_obsolete() && old_caches_.empty())) {
+ storage_->DeleteResponses(manifest_url_, *response_ids);
+ response_ids->clear();
+ return;
+ }
+
+ if (newly_deletable_response_ids_.empty()) {
+ newly_deletable_response_ids_.swap(*response_ids);
+ return;
+ }
+ newly_deletable_response_ids_.insert(
+ newly_deletable_response_ids_.end(),
+ response_ids->begin(), response_ids->end());
+ response_ids->clear();
+}
+
+void AppCacheGroup::StartUpdateWithNewMasterEntry(
+ AppCacheHost* host, const GURL& new_master_resource) {
+ DCHECK(!is_obsolete() && !is_being_deleted());
+ if (is_in_dtor_)
+ return;
+
+ if (!update_job_)
+ update_job_ = new AppCacheUpdateJob(storage_->service(), this);
+
+ update_job_->StartUpdate(host, new_master_resource);
+
+ // Run queued update immediately as an update has been started manually.
+ if (!restart_update_task_.IsCancelled()) {
+ restart_update_task_.Cancel();
+ RunQueuedUpdates();
+ }
+}
+
+void AppCacheGroup::CancelUpdate() {
+ if (update_job_) {
+ delete update_job_;
+ DCHECK(!update_job_);
+ DCHECK_EQ(IDLE, update_status_);
+ }
+}
+
+void AppCacheGroup::QueueUpdate(AppCacheHost* host,
+ const GURL& new_master_resource) {
+ DCHECK(update_job_ && host && !new_master_resource.is_empty());
+ queued_updates_.insert(QueuedUpdates::value_type(host, new_master_resource));
+
+ // Need to know when host is destroyed.
+ host->AddObserver(host_observer_.get());
+
+ // If host is already observing for updates, move host to queued observers
+ // list so that host is not notified when the current update completes.
+ if (FindObserver(host, observers_)) {
+ observers_.RemoveObserver(host);
+ queued_observers_.AddObserver(host);
+ }
+}
+
+void AppCacheGroup::RunQueuedUpdates() {
+ if (!restart_update_task_.IsCancelled())
+ restart_update_task_.Cancel();
+
+ if (queued_updates_.empty())
+ return;
+
+ QueuedUpdates updates_to_run;
+ queued_updates_.swap(updates_to_run);
+ DCHECK(queued_updates_.empty());
+
+ for (QueuedUpdates::iterator it = updates_to_run.begin();
+ it != updates_to_run.end(); ++it) {
+ AppCacheHost* host = it->first;
+ host->RemoveObserver(host_observer_.get());
+ if (FindObserver(host, queued_observers_)) {
+ queued_observers_.RemoveObserver(host);
+ observers_.AddObserver(host);
+ }
+
+ if (!is_obsolete() && !is_being_deleted())
+ StartUpdateWithNewMasterEntry(host, it->second);
+ }
+}
+
+bool AppCacheGroup::FindObserver(UpdateObserver* find_me,
+ const ObserverList<UpdateObserver>& observer_list) {
+ return observer_list.HasObserver(find_me);
+}
+
+void AppCacheGroup::ScheduleUpdateRestart(int delay_ms) {
+ DCHECK(restart_update_task_.IsCancelled());
+ restart_update_task_.Reset(
+ base::Bind(&AppCacheGroup::RunQueuedUpdates, this));
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ restart_update_task_.callback(),
+ base::TimeDelta::FromMilliseconds(delay_ms));
+}
+
+void AppCacheGroup::HostDestructionImminent(AppCacheHost* host) {
+ queued_updates_.erase(host);
+ if (queued_updates_.empty() && !restart_update_task_.IsCancelled())
+ restart_update_task_.Cancel();
+}
+
+void AppCacheGroup::SetUpdateAppCacheStatus(UpdateAppCacheStatus status) {
+ if (status == update_status_)
+ return;
+
+ update_status_ = status;
+
+ if (status != IDLE) {
+ DCHECK(update_job_);
+ } else {
+ update_job_ = NULL;
+
+ // Observers may release us in these callbacks, so we protect against
+ // deletion by adding an extra ref in this scope (but only if we're not
+ // in our destructor).
+ scoped_refptr<AppCacheGroup> protect(is_in_dtor_ ? NULL : this);
+ FOR_EACH_OBSERVER(UpdateObserver, observers_, OnUpdateComplete(this));
+ if (!queued_updates_.empty())
+ ScheduleUpdateRestart(kUpdateRestartDelayMs);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_group.h b/chromium/content/browser/appcache/appcache_group.h
new file mode 100644
index 00000000000..3c54cfec5a2
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_group.h
@@ -0,0 +1,173 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_GROUP_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_GROUP_H_
+
+#include <map>
+#include <vector>
+
+#include "base/cancelable_callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheGroupTest, StartUpdate);
+FORWARD_DECLARE_TEST(AppCacheGroupTest, CancelUpdate);
+FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate);
+FORWARD_DECLARE_TEST(AppCacheUpdateJobTest, AlreadyChecking);
+FORWARD_DECLARE_TEST(AppCacheUpdateJobTest, AlreadyDownloading);
+class AppCache;
+class AppCacheHost;
+class AppCacheStorage;
+class AppCacheUpdateJob;
+class AppCacheUpdateJobTest;
+class HostObserver;
+class MockAppCacheStorage;
+
+// Collection of application caches identified by the same manifest URL.
+// A group exists as long as it is in use by a host or is being updated.
+class CONTENT_EXPORT AppCacheGroup
+ : public base::RefCounted<AppCacheGroup> {
+ public:
+
+ class CONTENT_EXPORT UpdateObserver {
+ public:
+ // Called just after an appcache update has completed.
+ virtual void OnUpdateComplete(AppCacheGroup* group) = 0;
+ virtual ~UpdateObserver() {}
+ };
+
+ enum UpdateAppCacheStatus {
+ IDLE,
+ CHECKING,
+ DOWNLOADING,
+ };
+
+ AppCacheGroup(AppCacheStorage* storage, const GURL& manifest_url,
+ int64 group_id);
+
+ // Adds/removes an update observer, the AppCacheGroup does not take
+ // ownership of the observer.
+ void AddUpdateObserver(UpdateObserver* observer);
+ void RemoveUpdateObserver(UpdateObserver* observer);
+
+ int64 group_id() const { return group_id_; }
+ const GURL& manifest_url() const { return manifest_url_; }
+ const base::Time& creation_time() const { return creation_time_; }
+ void set_creation_time(const base::Time& time) { creation_time_ = time; }
+ bool is_obsolete() const { return is_obsolete_; }
+ void set_obsolete(bool value) { is_obsolete_ = value; }
+
+ bool is_being_deleted() const { return is_being_deleted_; }
+ void set_being_deleted(bool value) { is_being_deleted_ = value; }
+
+ AppCache* newest_complete_cache() const { return newest_complete_cache_; }
+
+ void AddCache(AppCache* complete_cache);
+ void RemoveCache(AppCache* cache);
+ bool HasCache() const { return newest_complete_cache_ != NULL; }
+
+ void AddNewlyDeletableResponseIds(std::vector<int64>* response_ids);
+
+ UpdateAppCacheStatus update_status() const { return update_status_; }
+
+ // Starts an update via update() javascript API.
+ void StartUpdate() {
+ StartUpdateWithHost(NULL);
+ }
+
+ // Starts an update for a doc loaded from an application cache.
+ void StartUpdateWithHost(AppCacheHost* host) {
+ StartUpdateWithNewMasterEntry(host, GURL());
+ }
+
+ // Starts an update for a doc loaded using HTTP GET or equivalent with
+ // an <html> tag manifest attribute value that matches this group's
+ // manifest url.
+ void StartUpdateWithNewMasterEntry(AppCacheHost* host,
+ const GURL& new_master_resource);
+
+ // Cancels an update if one is running.
+ void CancelUpdate();
+
+ private:
+ class HostObserver;
+
+ friend class base::RefCounted<AppCacheGroup>;
+ friend class content::AppCacheUpdateJobTest;
+ friend class content::MockAppCacheStorage; // for old_caches()
+ friend class AppCacheUpdateJob;
+
+ ~AppCacheGroup();
+
+ typedef std::vector<AppCache*> Caches;
+ typedef std::map<AppCacheHost*, GURL> QueuedUpdates;
+
+ static const int kUpdateRestartDelayMs = 1000;
+
+ AppCacheUpdateJob* update_job() { return update_job_; }
+ void SetUpdateAppCacheStatus(UpdateAppCacheStatus status);
+
+ void NotifyContentBlocked();
+
+ const Caches& old_caches() const { return old_caches_; }
+
+ // Update cannot be processed at this time. Queue it for a later run.
+ void QueueUpdate(AppCacheHost* host, const GURL& new_master_resource);
+ void RunQueuedUpdates();
+ bool FindObserver(UpdateObserver* find_me,
+ const ObserverList<UpdateObserver>& observer_list);
+ void ScheduleUpdateRestart(int delay_ms);
+ void HostDestructionImminent(AppCacheHost* host);
+
+ const int64 group_id_;
+ const GURL manifest_url_;
+ base::Time creation_time_;
+ UpdateAppCacheStatus update_status_;
+ bool is_obsolete_;
+ bool is_being_deleted_;
+ std::vector<int64> newly_deletable_response_ids_;
+
+ // Old complete app caches.
+ Caches old_caches_;
+
+ // Newest cache in this group to be complete, aka relevant cache.
+ AppCache* newest_complete_cache_;
+
+ // Current update job for this group, if any.
+ AppCacheUpdateJob* update_job_;
+
+ // Central storage object.
+ AppCacheStorage* storage_;
+
+ // List of objects observing this group.
+ ObserverList<UpdateObserver> observers_;
+
+ // Updates that have been queued for the next run.
+ QueuedUpdates queued_updates_;
+ ObserverList<UpdateObserver> queued_observers_;
+ base::CancelableClosure restart_update_task_;
+ scoped_ptr<HostObserver> host_observer_;
+
+ // True if we're in our destructor.
+ bool is_in_dtor_;
+
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, StartUpdate);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, CancelUpdate);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheUpdateJobTest, AlreadyChecking);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheUpdateJobTest, AlreadyDownloading);
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheGroup);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_GROUP_H_
diff --git a/chromium/content/browser/appcache/appcache_group_unittest.cc b/chromium/content/browser/appcache/appcache_group_unittest.cc
index cec20fa8c62..64e321d5525 100644
--- a/chromium/content/browser/appcache/appcache_group_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_group_unittest.cc
@@ -5,65 +5,54 @@
#include <string>
#include "base/message_loop/message_loop.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_update_job.h"
#include "content/browser/appcache/mock_appcache_service.h"
+#include "content/common/appcache_interfaces.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_host.h"
-#include "webkit/browser/appcache/appcache_update_job.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-
-using appcache::AppCache;
-using appcache::AppCacheFrontend;
-using appcache::AppCacheGroup;
-using appcache::AppCacheHost;
-using appcache::AppCacheServiceImpl;
-using appcache::AppCacheUpdateJob;
namespace {
-class TestAppCacheFrontend : public appcache::AppCacheFrontend {
+class TestAppCacheFrontend : public content::AppCacheFrontend {
public:
TestAppCacheFrontend()
: last_host_id_(-1), last_cache_id_(-1),
- last_status_(appcache::APPCACHE_STATUS_OBSOLETE) {
+ last_status_(content::APPCACHE_STATUS_OBSOLETE) {
}
- virtual void OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) OVERRIDE {
+ void OnCacheSelected(int host_id,
+ const content::AppCacheInfo& info) override {
last_host_id_ = host_id;
last_cache_id_ = info.cache_id;
last_status_ = info.status;
}
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) OVERRIDE {
- }
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ content::AppCacheStatus status) override {}
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) OVERRIDE {
- }
+ void OnEventRaised(const std::vector<int>& host_ids,
+ content::AppCacheEventID event_id) override {}
- virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details)
- OVERRIDE {}
+ void OnErrorEventRaised(
+ const std::vector<int>& host_ids,
+ const content::AppCacheErrorDetails& details) override {}
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total, int num_complete) OVERRIDE {
- }
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override {}
- virtual void OnLogMessage(int host_id, appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE {
- }
+ void OnLogMessage(int host_id,
+ content::AppCacheLogLevel log_level,
+ const std::string& message) override {}
- virtual void OnContentBlocked(int host_id,
- const GURL& manifest_url) OVERRIDE {
- }
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override {}
int last_host_id_;
int64 last_cache_id_;
- appcache::AppCacheStatus last_status_;
+ content::AppCacheStatus last_status_;
};
} // namespace anon
@@ -75,7 +64,7 @@ class TestUpdateObserver : public AppCacheGroup::UpdateObserver {
TestUpdateObserver() : update_completed_(false), group_has_cache_(false) {
}
- virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE {
+ void OnUpdateComplete(AppCacheGroup* group) override {
update_completed_ = true;
group_has_cache_ = group->HasCache();
}
@@ -95,7 +84,7 @@ class TestAppCacheHost : public AppCacheHost {
update_completed_(false) {
}
- virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE {
+ void OnUpdateComplete(AppCacheGroup* group) override {
update_completed_ = true;
}
@@ -118,60 +107,60 @@ TEST_F(AppCacheGroupTest, AddRemoveCache) {
cache1->set_complete(true);
cache1->set_update_time(now);
group->AddCache(cache1.get());
- EXPECT_EQ(cache1, group->newest_complete_cache());
+ EXPECT_EQ(cache1.get(), group->newest_complete_cache());
// Adding older cache does not change newest complete cache.
scoped_refptr<AppCache> cache2(new AppCache(service.storage(), 222));
cache2->set_complete(true);
cache2->set_update_time(now - base::TimeDelta::FromDays(1));
group->AddCache(cache2.get());
- EXPECT_EQ(cache1, group->newest_complete_cache());
+ EXPECT_EQ(cache1.get(), group->newest_complete_cache());
// Adding newer cache does change newest complete cache.
scoped_refptr<AppCache> cache3(new AppCache(service.storage(), 333));
cache3->set_complete(true);
cache3->set_update_time(now + base::TimeDelta::FromDays(1));
group->AddCache(cache3.get());
- EXPECT_EQ(cache3, group->newest_complete_cache());
+ EXPECT_EQ(cache3.get(), group->newest_complete_cache());
// Adding cache with same update time uses one with larger ID.
scoped_refptr<AppCache> cache4(new AppCache(service.storage(), 444));
cache4->set_complete(true);
cache4->set_update_time(now + base::TimeDelta::FromDays(1)); // same as 3
group->AddCache(cache4.get());
- EXPECT_EQ(cache4, group->newest_complete_cache());
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache());
// smaller id
scoped_refptr<AppCache> cache5(new AppCache(service.storage(), 55));
cache5->set_complete(true);
cache5->set_update_time(now + base::TimeDelta::FromDays(1)); // same as 4
group->AddCache(cache5.get());
- EXPECT_EQ(cache4, group->newest_complete_cache()); // no change
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache()); // no change
// Old caches can always be removed.
group->RemoveCache(cache1.get());
EXPECT_FALSE(cache1->owning_group());
- EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache()); // newest unchanged
// Remove rest of caches.
group->RemoveCache(cache2.get());
EXPECT_FALSE(cache2->owning_group());
- EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache()); // newest unchanged
group->RemoveCache(cache3.get());
EXPECT_FALSE(cache3->owning_group());
- EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache()); // newest unchanged
group->RemoveCache(cache5.get());
EXPECT_FALSE(cache5->owning_group());
- EXPECT_EQ(cache4, group->newest_complete_cache()); // newest unchanged
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache()); // newest unchanged
group->RemoveCache(cache4.get()); // newest removed
EXPECT_FALSE(cache4->owning_group());
EXPECT_FALSE(group->newest_complete_cache()); // no more newest cache
// Can remove newest cache if there are older caches.
group->AddCache(cache1.get());
- EXPECT_EQ(cache1, group->newest_complete_cache());
+ EXPECT_EQ(cache1.get(), group->newest_complete_cache());
group->AddCache(cache4.get());
- EXPECT_EQ(cache4, group->newest_complete_cache());
+ EXPECT_EQ(cache4.get(), group->newest_complete_cache());
group->RemoveCache(cache4.get()); // remove newest
EXPECT_FALSE(cache4->owning_group());
EXPECT_FALSE(group->newest_complete_cache()); // newest removed
@@ -197,12 +186,12 @@ TEST_F(AppCacheGroupTest, CleanupUnusedGroup) {
host1.AssociateCompleteCache(cache1);
EXPECT_EQ(frontend.last_host_id_, host1.host_id());
EXPECT_EQ(frontend.last_cache_id_, cache1->cache_id());
- EXPECT_EQ(frontend.last_status_, appcache::APPCACHE_STATUS_IDLE);
+ EXPECT_EQ(frontend.last_status_, APPCACHE_STATUS_IDLE);
host2.AssociateCompleteCache(cache1);
EXPECT_EQ(frontend.last_host_id_, host2.host_id());
EXPECT_EQ(frontend.last_cache_id_, cache1->cache_id());
- EXPECT_EQ(frontend.last_status_, appcache::APPCACHE_STATUS_IDLE);
+ EXPECT_EQ(frontend.last_status_, APPCACHE_STATUS_IDLE);
AppCache* cache2 = new AppCache(service.storage(), 222);
cache2->set_complete(true);
@@ -214,8 +203,8 @@ TEST_F(AppCacheGroupTest, CleanupUnusedGroup) {
host1.AssociateNoCache(GURL());
host2.AssociateNoCache(GURL());
EXPECT_EQ(frontend.last_host_id_, host2.host_id());
- EXPECT_EQ(frontend.last_cache_id_, appcache::kAppCacheNoCacheId);
- EXPECT_EQ(frontend.last_status_, appcache::APPCACHE_STATUS_UNCACHED);
+ EXPECT_EQ(frontend.last_cache_id_, kAppCacheNoCacheId);
+ EXPECT_EQ(frontend.last_status_, APPCACHE_STATUS_UNCACHED);
}
TEST_F(AppCacheGroupTest, StartUpdate) {
diff --git a/chromium/content/browser/appcache/appcache_histograms.cc b/chromium/content/browser/appcache/appcache_histograms.cc
new file mode 100644
index 00000000000..ff221b075af
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_histograms.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_histograms.h"
+
+#include "base/metrics/histogram.h"
+
+namespace content {
+
+static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
+ if (origin_url.host() == "docs.google.com")
+ return ".Docs";
+ return std::string();
+}
+
+void AppCacheHistograms::CountInitResult(InitResultType init_result) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "appcache.InitResult",
+ init_result, NUM_INIT_RESULT_TYPES);
+}
+
+void AppCacheHistograms::CountReinitAttempt(bool repeated_attempt) {
+ UMA_HISTOGRAM_BOOLEAN("appcache.ReinitAttempt", repeated_attempt);
+}
+
+void AppCacheHistograms::CountCorruptionDetected() {
+ UMA_HISTOGRAM_BOOLEAN("appcache.CorruptionDetected", true);
+}
+
+void AppCacheHistograms::CountUpdateJobResult(
+ AppCacheUpdateJob::ResultType result,
+ const GURL& origin_url) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "appcache.UpdateJobResult",
+ result, AppCacheUpdateJob::NUM_UPDATE_JOB_RESULT_TYPES);
+
+ const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
+ if (!suffix.empty()) {
+ base::LinearHistogram::FactoryGet(
+ "appcache.UpdateJobResult" + suffix,
+ 1,
+ AppCacheUpdateJob::NUM_UPDATE_JOB_RESULT_TYPES,
+ AppCacheUpdateJob::NUM_UPDATE_JOB_RESULT_TYPES + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result);
+ }
+}
+
+void AppCacheHistograms::CountCheckResponseResult(
+ CheckResponseResultType result) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "appcache.CheckResponseResult",
+ result, NUM_CHECK_RESPONSE_RESULT_TYPES);
+}
+
+void AppCacheHistograms::CountResponseRetrieval(
+ bool success, bool is_main_resource, const GURL& origin_url) {
+ std::string label;
+ if (is_main_resource) {
+ label = "appcache.MainResourceResponseRetrieval";
+ UMA_HISTOGRAM_BOOLEAN(label, success);
+ } else {
+ label = "appcache.SubResourceResponseRetrieval";
+ UMA_HISTOGRAM_BOOLEAN(label, success);
+ }
+ const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
+ if (!suffix.empty()) {
+ base::BooleanHistogram::FactoryGet(
+ label + suffix,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(success);
+ }
+}
+
+void AppCacheHistograms::LogUpdateFailureStats(
+ const GURL& origin_url,
+ int percent_complete,
+ bool was_stalled,
+ bool was_off_origin_resource_failure) {
+ const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
+
+ std::string label = "appcache.UpdateProgressAtPointOfFaliure";
+ UMA_HISTOGRAM_PERCENTAGE(label, percent_complete);
+ if (!suffix.empty()) {
+ base::LinearHistogram::FactoryGet(
+ label + suffix,
+ 1, 101, 102,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(percent_complete);
+ }
+
+ label = "appcache.UpdateWasStalledAtPointOfFailure";
+ UMA_HISTOGRAM_BOOLEAN(label, was_stalled);
+ if (!suffix.empty()) {
+ base::BooleanHistogram::FactoryGet(
+ label + suffix,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(was_stalled);
+ }
+
+ label = "appcache.UpdateWasOffOriginAtPointOfFailure";
+ UMA_HISTOGRAM_BOOLEAN(label, was_off_origin_resource_failure);
+ if (!suffix.empty()) {
+ base::BooleanHistogram::FactoryGet(
+ label + suffix,
+ base::HistogramBase::kUmaTargetedHistogramFlag)->Add(
+ was_off_origin_resource_failure);
+ }
+}
+
+void AppCacheHistograms::AddTaskQueueTimeSample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.TaskQueueTime", duration);
+}
+
+void AppCacheHistograms::AddTaskRunTimeSample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.TaskRunTime", duration);
+}
+
+void AppCacheHistograms::AddCompletionQueueTimeSample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.CompletionQueueTime", duration);
+}
+
+void AppCacheHistograms::AddCompletionRunTimeSample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.CompletionRunTime", duration);
+}
+
+void AppCacheHistograms::AddNetworkJobStartDelaySample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.JobStartDelay.Network", duration);
+}
+
+void AppCacheHistograms::AddErrorJobStartDelaySample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.JobStartDelay.Error", duration);
+}
+
+void AppCacheHistograms::AddAppCacheJobStartDelaySample(
+ const base::TimeDelta& duration) {
+ UMA_HISTOGRAM_TIMES("appcache.JobStartDelay.AppCache", duration);
+}
+
+void AppCacheHistograms::AddMissingManifestEntrySample() {
+ UMA_HISTOGRAM_BOOLEAN("appcache.MissingManifestEntry", true);
+}
+
+void AppCacheHistograms::AddMissingManifestDetectedAtCallsite(
+ MissingManifestCallsiteType callsite) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "appcache.MissingManifestDetectedAtCallsite",
+ callsite, NUM_MISSING_MANIFEST_CALLSITE_TYPES);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_histograms.h b/chromium/content/browser/appcache/appcache_histograms.h
new file mode 100644
index 00000000000..0fcc54cf65f
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_histograms.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_HISTOGRAMS_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_HISTOGRAMS_H_
+
+#include "base/basictypes.h"
+#include "content/browser/appcache/appcache_update_job.h"
+
+namespace base {
+class TimeDelta;
+}
+
+namespace content {
+
+class AppCacheHistograms {
+ public:
+ enum InitResultType {
+ INIT_OK, SQL_DATABASE_ERROR, DISK_CACHE_ERROR,
+ NUM_INIT_RESULT_TYPES
+ };
+ static void CountInitResult(InitResultType init_result);
+ static void CountReinitAttempt(bool repeated_attempt);
+ static void CountCorruptionDetected();
+ static void CountUpdateJobResult(AppCacheUpdateJob::ResultType result,
+ const GURL& origin_url);
+ enum CheckResponseResultType {
+ RESPONSE_OK, MANIFEST_OUT_OF_DATE, RESPONSE_OUT_OF_DATE, ENTRY_NOT_FOUND,
+ READ_HEADERS_ERROR, READ_DATA_ERROR, UNEXPECTED_DATA_SIZE, CHECK_CANCELED,
+ NUM_CHECK_RESPONSE_RESULT_TYPES
+ };
+ static void CountCheckResponseResult(CheckResponseResultType result);
+ static void CountResponseRetrieval(
+ bool success, bool is_main_resource, const GURL& origin_url);
+ static void LogUpdateFailureStats(
+ const GURL& origin_url,
+ int percent_complete,
+ bool was_making_progress,
+ bool off_origin_resource_failure);
+ static void AddTaskQueueTimeSample(const base::TimeDelta& duration);
+ static void AddTaskRunTimeSample(const base::TimeDelta& duration);
+ static void AddCompletionQueueTimeSample(const base::TimeDelta& duration);
+ static void AddCompletionRunTimeSample(const base::TimeDelta& duration);
+ static void AddNetworkJobStartDelaySample(const base::TimeDelta& duration);
+ static void AddErrorJobStartDelaySample(const base::TimeDelta& duration);
+ static void AddAppCacheJobStartDelaySample(const base::TimeDelta& duration);
+ static void AddMissingManifestEntrySample();
+
+ enum MissingManifestCallsiteType {
+ CALLSITE_0, CALLSITE_1, CALLSITE_2, CALLSITE_3,
+ NUM_MISSING_MANIFEST_CALLSITE_TYPES
+ };
+ static void AddMissingManifestDetectedAtCallsite(
+ MissingManifestCallsiteType type);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AppCacheHistograms);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_HISTOGRAMS_H_
diff --git a/chromium/content/browser/appcache/appcache_host.cc b/chromium/content/browser/appcache/appcache_host.cc
new file mode 100644
index 00000000000..52213a3a14e
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_host.cc
@@ -0,0 +1,552 @@
+// Copyright (c) 2011 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 "content/browser/appcache/appcache_host.h"
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_policy.h"
+#include "content/browser/appcache/appcache_request_handler.h"
+#include "net/url_request/url_request.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+
+namespace content {
+
+namespace {
+
+void FillCacheInfo(const AppCache* cache,
+ const GURL& manifest_url,
+ AppCacheStatus status, AppCacheInfo* info) {
+ info->manifest_url = manifest_url;
+ info->status = status;
+
+ if (!cache)
+ return;
+
+ info->cache_id = cache->cache_id();
+
+ if (!cache->is_complete())
+ return;
+
+ DCHECK(cache->owning_group());
+ info->is_complete = true;
+ info->group_id = cache->owning_group()->group_id();
+ info->last_update_time = cache->update_time();
+ info->creation_time = cache->owning_group()->creation_time();
+ info->size = cache->cache_size();
+}
+
+} // Anonymous namespace
+
+AppCacheHost::AppCacheHost(int host_id, AppCacheFrontend* frontend,
+ AppCacheServiceImpl* service)
+ : host_id_(host_id),
+ spawning_host_id_(kAppCacheNoHostId), spawning_process_id_(0),
+ parent_host_id_(kAppCacheNoHostId), parent_process_id_(0),
+ pending_main_resource_cache_id_(kAppCacheNoCacheId),
+ pending_selected_cache_id_(kAppCacheNoCacheId),
+ is_cache_selection_enabled_(true),
+ frontend_(frontend), service_(service),
+ storage_(service->storage()),
+ pending_callback_param_(NULL),
+ main_resource_was_namespace_entry_(false),
+ main_resource_blocked_(false),
+ associated_cache_info_pending_(false) {
+ service_->AddObserver(this);
+}
+
+AppCacheHost::~AppCacheHost() {
+ service_->RemoveObserver(this);
+ FOR_EACH_OBSERVER(Observer, observers_, OnDestructionImminent(this));
+ if (associated_cache_.get())
+ associated_cache_->UnassociateHost(this);
+ if (group_being_updated_.get())
+ group_being_updated_->RemoveUpdateObserver(this);
+ storage()->CancelDelegateCallbacks(this);
+ if (service()->quota_manager_proxy() && !origin_in_use_.is_empty())
+ service()->quota_manager_proxy()->NotifyOriginNoLongerInUse(origin_in_use_);
+}
+
+void AppCacheHost::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void AppCacheHost::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void AppCacheHost::SelectCache(const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url) {
+ DCHECK(pending_start_update_callback_.is_null() &&
+ pending_swap_cache_callback_.is_null() &&
+ pending_get_status_callback_.is_null() &&
+ !is_selection_pending());
+
+ if (!is_cache_selection_enabled_) {
+ FinishCacheSelection(NULL, NULL);
+ return;
+ }
+
+ origin_in_use_ = document_url.GetOrigin();
+ if (service()->quota_manager_proxy() && !origin_in_use_.is_empty())
+ service()->quota_manager_proxy()->NotifyOriginInUse(origin_in_use_);
+
+ if (main_resource_blocked_)
+ frontend_->OnContentBlocked(host_id_,
+ blocked_manifest_url_);
+
+ // 6.9.6 The application cache selection algorithm.
+ // The algorithm is started here and continues in FinishCacheSelection,
+ // after cache or group loading is complete.
+ // Note: Foreign entries are detected on the client side and
+ // MarkAsForeignEntry is called in that case, so that detection
+ // step is skipped here. See WebApplicationCacheHostImpl.cc
+
+ if (cache_document_was_loaded_from != kAppCacheNoCacheId) {
+ LoadSelectedCache(cache_document_was_loaded_from);
+ return;
+ }
+
+ if (!manifest_url.is_empty() &&
+ (manifest_url.GetOrigin() == document_url.GetOrigin())) {
+ DCHECK(!first_party_url_.is_empty());
+ AppCachePolicy* policy = service()->appcache_policy();
+ if (policy &&
+ !policy->CanCreateAppCache(manifest_url, first_party_url_)) {
+ FinishCacheSelection(NULL, NULL);
+ std::vector<int> host_ids(1, host_id_);
+ frontend_->OnEventRaised(host_ids, APPCACHE_CHECKING_EVENT);
+ frontend_->OnErrorEventRaised(
+ host_ids,
+ AppCacheErrorDetails(
+ "Cache creation was blocked by the content policy",
+ APPCACHE_POLICY_ERROR,
+ GURL(),
+ 0,
+ false /*is_cross_origin*/));
+ frontend_->OnContentBlocked(host_id_, manifest_url);
+ return;
+ }
+
+ // Note: The client detects if the document was not loaded using HTTP GET
+ // and invokes SelectCache without a manifest url, so that detection step
+ // is also skipped here. See WebApplicationCacheHostImpl.cc
+ set_preferred_manifest_url(manifest_url);
+ new_master_entry_url_ = document_url;
+ LoadOrCreateGroup(manifest_url);
+ return;
+ }
+
+ // TODO(michaeln): If there was a manifest URL, the user agent may report
+ // to the user that it was ignored, to aid in application development.
+ FinishCacheSelection(NULL, NULL);
+}
+
+void AppCacheHost::SelectCacheForWorker(int parent_process_id,
+ int parent_host_id) {
+ DCHECK(pending_start_update_callback_.is_null() &&
+ pending_swap_cache_callback_.is_null() &&
+ pending_get_status_callback_.is_null() &&
+ !is_selection_pending());
+
+ parent_process_id_ = parent_process_id;
+ parent_host_id_ = parent_host_id;
+ FinishCacheSelection(NULL, NULL);
+}
+
+void AppCacheHost::SelectCacheForSharedWorker(int64 appcache_id) {
+ DCHECK(pending_start_update_callback_.is_null() &&
+ pending_swap_cache_callback_.is_null() &&
+ pending_get_status_callback_.is_null() &&
+ !is_selection_pending());
+
+ if (appcache_id != kAppCacheNoCacheId) {
+ LoadSelectedCache(appcache_id);
+ return;
+ }
+ FinishCacheSelection(NULL, NULL);
+}
+
+// TODO(michaeln): change method name to MarkEntryAsForeign for consistency
+void AppCacheHost::MarkAsForeignEntry(const GURL& document_url,
+ int64 cache_document_was_loaded_from) {
+ // The document url is not the resource url in the fallback case.
+ storage()->MarkEntryAsForeign(
+ main_resource_was_namespace_entry_ ? namespace_entry_url_ : document_url,
+ cache_document_was_loaded_from);
+ SelectCache(document_url, kAppCacheNoCacheId, GURL());
+}
+
+void AppCacheHost::GetStatusWithCallback(const GetStatusCallback& callback,
+ void* callback_param) {
+ DCHECK(pending_start_update_callback_.is_null() &&
+ pending_swap_cache_callback_.is_null() &&
+ pending_get_status_callback_.is_null());
+
+ pending_get_status_callback_ = callback;
+ pending_callback_param_ = callback_param;
+ if (is_selection_pending())
+ return;
+
+ DoPendingGetStatus();
+}
+
+void AppCacheHost::DoPendingGetStatus() {
+ DCHECK_EQ(false, pending_get_status_callback_.is_null());
+
+ pending_get_status_callback_.Run(GetStatus(), pending_callback_param_);
+ pending_get_status_callback_.Reset();
+ pending_callback_param_ = NULL;
+}
+
+void AppCacheHost::StartUpdateWithCallback(const StartUpdateCallback& callback,
+ void* callback_param) {
+ DCHECK(pending_start_update_callback_.is_null() &&
+ pending_swap_cache_callback_.is_null() &&
+ pending_get_status_callback_.is_null());
+
+ pending_start_update_callback_ = callback;
+ pending_callback_param_ = callback_param;
+ if (is_selection_pending())
+ return;
+
+ DoPendingStartUpdate();
+}
+
+void AppCacheHost::DoPendingStartUpdate() {
+ DCHECK_EQ(false, pending_start_update_callback_.is_null());
+
+ // 6.9.8 Application cache API
+ bool success = false;
+ if (associated_cache_.get() && associated_cache_->owning_group()) {
+ AppCacheGroup* group = associated_cache_->owning_group();
+ if (!group->is_obsolete() && !group->is_being_deleted()) {
+ success = true;
+ group->StartUpdate();
+ }
+ }
+
+ pending_start_update_callback_.Run(success, pending_callback_param_);
+ pending_start_update_callback_.Reset();
+ pending_callback_param_ = NULL;
+}
+
+void AppCacheHost::SwapCacheWithCallback(const SwapCacheCallback& callback,
+ void* callback_param) {
+ DCHECK(pending_start_update_callback_.is_null() &&
+ pending_swap_cache_callback_.is_null() &&
+ pending_get_status_callback_.is_null());
+
+ pending_swap_cache_callback_ = callback;
+ pending_callback_param_ = callback_param;
+ if (is_selection_pending())
+ return;
+
+ DoPendingSwapCache();
+}
+
+void AppCacheHost::DoPendingSwapCache() {
+ DCHECK_EQ(false, pending_swap_cache_callback_.is_null());
+
+ // 6.9.8 Application cache API
+ bool success = false;
+ if (associated_cache_.get() && associated_cache_->owning_group()) {
+ if (associated_cache_->owning_group()->is_obsolete()) {
+ success = true;
+ AssociateNoCache(GURL());
+ } else if (swappable_cache_.get()) {
+ DCHECK(swappable_cache_.get() ==
+ swappable_cache_->owning_group()->newest_complete_cache());
+ success = true;
+ AssociateCompleteCache(swappable_cache_.get());
+ }
+ }
+
+ pending_swap_cache_callback_.Run(success, pending_callback_param_);
+ pending_swap_cache_callback_.Reset();
+ pending_callback_param_ = NULL;
+}
+
+void AppCacheHost::SetSpawningHostId(
+ int spawning_process_id, int spawning_host_id) {
+ spawning_process_id_ = spawning_process_id;
+ spawning_host_id_ = spawning_host_id;
+}
+
+const AppCacheHost* AppCacheHost::GetSpawningHost() const {
+ AppCacheBackendImpl* backend = service_->GetBackend(spawning_process_id_);
+ return backend ? backend->GetHost(spawning_host_id_) : NULL;
+}
+
+AppCacheHost* AppCacheHost::GetParentAppCacheHost() const {
+ DCHECK(is_for_dedicated_worker());
+ AppCacheBackendImpl* backend = service_->GetBackend(parent_process_id_);
+ return backend ? backend->GetHost(parent_host_id_) : NULL;
+}
+
+AppCacheRequestHandler* AppCacheHost::CreateRequestHandler(
+ net::URLRequest* request,
+ ResourceType resource_type) {
+ if (is_for_dedicated_worker()) {
+ AppCacheHost* parent_host = GetParentAppCacheHost();
+ if (parent_host)
+ return parent_host->CreateRequestHandler(request, resource_type);
+ return NULL;
+ }
+
+ if (AppCacheRequestHandler::IsMainResourceType(resource_type)) {
+ // Store the first party origin so that it can be used later in SelectCache
+ // for checking whether the creation of the appcache is allowed.
+ first_party_url_ = request->first_party_for_cookies();
+ return new AppCacheRequestHandler(this, resource_type);
+ }
+
+ if ((associated_cache() && associated_cache()->is_complete()) ||
+ is_selection_pending()) {
+ return new AppCacheRequestHandler(this, resource_type);
+ }
+ return NULL;
+}
+
+void AppCacheHost::GetResourceList(
+ AppCacheResourceInfoVector* resource_infos) {
+ if (associated_cache_.get() && associated_cache_->is_complete())
+ associated_cache_->ToResourceInfoVector(resource_infos);
+}
+
+AppCacheStatus AppCacheHost::GetStatus() {
+ // 6.9.8 Application cache API
+ AppCache* cache = associated_cache();
+ if (!cache)
+ return APPCACHE_STATUS_UNCACHED;
+
+ // A cache without an owning group represents the cache being constructed
+ // during the application cache update process.
+ if (!cache->owning_group())
+ return APPCACHE_STATUS_DOWNLOADING;
+
+ if (cache->owning_group()->is_obsolete())
+ return APPCACHE_STATUS_OBSOLETE;
+ if (cache->owning_group()->update_status() == AppCacheGroup::CHECKING)
+ return APPCACHE_STATUS_CHECKING;
+ if (cache->owning_group()->update_status() == AppCacheGroup::DOWNLOADING)
+ return APPCACHE_STATUS_DOWNLOADING;
+ if (swappable_cache_.get())
+ return APPCACHE_STATUS_UPDATE_READY;
+ return APPCACHE_STATUS_IDLE;
+}
+
+void AppCacheHost::LoadOrCreateGroup(const GURL& manifest_url) {
+ DCHECK(manifest_url.is_valid());
+ pending_selected_manifest_url_ = manifest_url;
+ storage()->LoadOrCreateGroup(manifest_url, this);
+}
+
+void AppCacheHost::OnGroupLoaded(AppCacheGroup* group,
+ const GURL& manifest_url) {
+ DCHECK(manifest_url == pending_selected_manifest_url_);
+ pending_selected_manifest_url_ = GURL();
+ FinishCacheSelection(NULL, group);
+}
+
+void AppCacheHost::LoadSelectedCache(int64 cache_id) {
+ DCHECK(cache_id != kAppCacheNoCacheId);
+ pending_selected_cache_id_ = cache_id;
+ storage()->LoadCache(cache_id, this);
+}
+
+void AppCacheHost::OnCacheLoaded(AppCache* cache, int64 cache_id) {
+ if (cache_id == pending_main_resource_cache_id_) {
+ pending_main_resource_cache_id_ = kAppCacheNoCacheId;
+ main_resource_cache_ = cache;
+ } else if (cache_id == pending_selected_cache_id_) {
+ pending_selected_cache_id_ = kAppCacheNoCacheId;
+ FinishCacheSelection(cache, NULL);
+ }
+}
+
+void AppCacheHost::FinishCacheSelection(
+ AppCache *cache, AppCacheGroup* group) {
+ DCHECK(!associated_cache());
+
+ // 6.9.6 The application cache selection algorithm
+ if (cache) {
+ // If document was loaded from an application cache, Associate document
+ // with the application cache from which it was loaded. Invoke the
+ // application cache update process for that cache and with the browsing
+ // context being navigated.
+ DCHECK(cache->owning_group());
+ DCHECK(new_master_entry_url_.is_empty());
+ DCHECK_EQ(cache->owning_group()->manifest_url(), preferred_manifest_url_);
+ AppCacheGroup* owing_group = cache->owning_group();
+ const char* kFormatString =
+ "Document was loaded from Application Cache with manifest %s";
+ frontend_->OnLogMessage(
+ host_id_, APPCACHE_LOG_INFO,
+ base::StringPrintf(
+ kFormatString, owing_group->manifest_url().spec().c_str()));
+ AssociateCompleteCache(cache);
+ if (!owing_group->is_obsolete() && !owing_group->is_being_deleted()) {
+ owing_group->StartUpdateWithHost(this);
+ ObserveGroupBeingUpdated(owing_group);
+ }
+ } else if (group && !group->is_being_deleted()) {
+ // If document was loaded using HTTP GET or equivalent, and, there is a
+ // manifest URL, and manifest URL has the same origin as document.
+ // Invoke the application cache update process for manifest URL, with
+ // the browsing context being navigated, and with document and the
+ // resource from which document was loaded as the new master resourse.
+ DCHECK(!group->is_obsolete());
+ DCHECK(new_master_entry_url_.is_valid());
+ DCHECK_EQ(group->manifest_url(), preferred_manifest_url_);
+ const char* kFormatString = group->HasCache() ?
+ "Adding master entry to Application Cache with manifest %s" :
+ "Creating Application Cache with manifest %s";
+ frontend_->OnLogMessage(
+ host_id_, APPCACHE_LOG_INFO,
+ base::StringPrintf(kFormatString,
+ group->manifest_url().spec().c_str()));
+ // The UpdateJob may produce one for us later.
+ AssociateNoCache(preferred_manifest_url_);
+ group->StartUpdateWithNewMasterEntry(this, new_master_entry_url_);
+ ObserveGroupBeingUpdated(group);
+ } else {
+ // Otherwise, the Document is not associated with any application cache.
+ new_master_entry_url_ = GURL();
+ AssociateNoCache(GURL());
+ }
+
+ // Respond to pending callbacks now that we have a selection.
+ if (!pending_get_status_callback_.is_null())
+ DoPendingGetStatus();
+ else if (!pending_start_update_callback_.is_null())
+ DoPendingStartUpdate();
+ else if (!pending_swap_cache_callback_.is_null())
+ DoPendingSwapCache();
+
+ FOR_EACH_OBSERVER(Observer, observers_, OnCacheSelectionComplete(this));
+}
+
+void AppCacheHost::OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) {
+ // We continue to use the disabled instance, but arrange for its
+ // deletion when its no longer needed.
+ if (old_storage_ref->storage() == storage())
+ disabled_storage_reference_ = old_storage_ref;
+}
+
+void AppCacheHost::ObserveGroupBeingUpdated(AppCacheGroup* group) {
+ DCHECK(!group_being_updated_.get());
+ group_being_updated_ = group;
+ newest_cache_of_group_being_updated_ = group->newest_complete_cache();
+ group->AddUpdateObserver(this);
+}
+
+void AppCacheHost::OnUpdateComplete(AppCacheGroup* group) {
+ DCHECK_EQ(group, group_being_updated_.get());
+ group->RemoveUpdateObserver(this);
+
+ // Add a reference to the newest complete cache.
+ SetSwappableCache(group);
+
+ group_being_updated_ = NULL;
+ newest_cache_of_group_being_updated_ = NULL;
+
+ if (associated_cache_info_pending_ && associated_cache_.get() &&
+ associated_cache_->is_complete()) {
+ AppCacheInfo info;
+ FillCacheInfo(
+ associated_cache_.get(), preferred_manifest_url_, GetStatus(), &info);
+ associated_cache_info_pending_ = false;
+ frontend_->OnCacheSelected(host_id_, info);
+ }
+}
+
+void AppCacheHost::SetSwappableCache(AppCacheGroup* group) {
+ if (!group) {
+ swappable_cache_ = NULL;
+ } else {
+ AppCache* new_cache = group->newest_complete_cache();
+ if (new_cache != associated_cache_.get())
+ swappable_cache_ = new_cache;
+ else
+ swappable_cache_ = NULL;
+ }
+}
+
+void AppCacheHost::LoadMainResourceCache(int64 cache_id) {
+ DCHECK(cache_id != kAppCacheNoCacheId);
+ if (pending_main_resource_cache_id_ == cache_id ||
+ (main_resource_cache_.get() &&
+ main_resource_cache_->cache_id() == cache_id)) {
+ return;
+ }
+ pending_main_resource_cache_id_ = cache_id;
+ storage()->LoadCache(cache_id, this);
+}
+
+void AppCacheHost::NotifyMainResourceIsNamespaceEntry(
+ const GURL& namespace_entry_url) {
+ main_resource_was_namespace_entry_ = true;
+ namespace_entry_url_ = namespace_entry_url;
+}
+
+void AppCacheHost::NotifyMainResourceBlocked(const GURL& manifest_url) {
+ main_resource_blocked_ = true;
+ blocked_manifest_url_ = manifest_url;
+}
+
+void AppCacheHost::PrepareForTransfer() {
+ // This can only happen prior to the document having been loaded.
+ DCHECK(!associated_cache());
+ DCHECK(!is_selection_pending());
+ DCHECK(!group_being_updated_.get());
+ host_id_ = kAppCacheNoHostId;
+ frontend_ = NULL;
+}
+
+void AppCacheHost::CompleteTransfer(int host_id, AppCacheFrontend* frontend) {
+ host_id_ = host_id;
+ frontend_ = frontend;
+}
+
+void AppCacheHost::AssociateNoCache(const GURL& manifest_url) {
+ // manifest url can be empty.
+ AssociateCacheHelper(NULL, manifest_url);
+}
+
+void AppCacheHost::AssociateIncompleteCache(AppCache* cache,
+ const GURL& manifest_url) {
+ DCHECK(cache && !cache->is_complete());
+ DCHECK(!manifest_url.is_empty());
+ AssociateCacheHelper(cache, manifest_url);
+}
+
+void AppCacheHost::AssociateCompleteCache(AppCache* cache) {
+ DCHECK(cache && cache->is_complete());
+ AssociateCacheHelper(cache, cache->owning_group()->manifest_url());
+}
+
+void AppCacheHost::AssociateCacheHelper(AppCache* cache,
+ const GURL& manifest_url) {
+ if (associated_cache_.get()) {
+ associated_cache_->UnassociateHost(this);
+ }
+
+ associated_cache_ = cache;
+ SetSwappableCache(cache ? cache->owning_group() : NULL);
+ associated_cache_info_pending_ = cache && !cache->is_complete();
+ AppCacheInfo info;
+ if (cache)
+ cache->AssociateHost(this);
+
+ FillCacheInfo(cache, manifest_url, GetStatus(), &info);
+ frontend_->OnCacheSelected(host_id_, info);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_host.h b/chromium/content/browser/appcache/appcache_host.h
new file mode 100644
index 00000000000..9f014fbb471
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_host.h
@@ -0,0 +1,341 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_HOST_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_HOST_H_
+
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/content_export.h"
+#include "content/public/common/resource_type.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLRequest;
+} // namespace net
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheGroupTest, CleanupUnusedGroup);
+FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate);
+FORWARD_DECLARE_TEST(AppCacheHostTest, Basic);
+FORWARD_DECLARE_TEST(AppCacheHostTest, SelectNoCache);
+FORWARD_DECLARE_TEST(AppCacheHostTest, ForeignEntry);
+FORWARD_DECLARE_TEST(AppCacheHostTest, FailedCacheLoad);
+FORWARD_DECLARE_TEST(AppCacheHostTest, FailedGroupLoad);
+FORWARD_DECLARE_TEST(AppCacheHostTest, SetSwappableCache);
+FORWARD_DECLARE_TEST(AppCacheHostTest, ForDedicatedWorker);
+FORWARD_DECLARE_TEST(AppCacheHostTest, SelectCacheAllowed);
+FORWARD_DECLARE_TEST(AppCacheHostTest, SelectCacheBlocked);
+FORWARD_DECLARE_TEST(AppCacheTest, CleanupUnusedCache);
+class AppCache;
+class AppCacheFrontend;
+class AppCacheGroupTest;
+class AppCacheHostTest;
+class AppCacheRequestHandler;
+class AppCacheRequestHandlerTest;
+class AppCacheStorageImplTest;
+class AppCacheTest;
+class AppCacheUpdateJobTest;
+
+typedef base::Callback<void(AppCacheStatus, void*)> GetStatusCallback;
+typedef base::Callback<void(bool, void*)> StartUpdateCallback;
+typedef base::Callback<void(bool, void*)> SwapCacheCallback;
+
+// Server-side representation of an application cache host.
+class CONTENT_EXPORT AppCacheHost
+ : public AppCacheStorage::Delegate,
+ public AppCacheGroup::UpdateObserver,
+ public AppCacheServiceImpl::Observer {
+ public:
+
+ class CONTENT_EXPORT Observer {
+ public:
+ // Called just after the cache selection algorithm completes.
+ virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0;
+
+ // Called just prior to the instance being deleted.
+ virtual void OnDestructionImminent(AppCacheHost* host) = 0;
+
+ virtual ~Observer() {}
+ };
+
+ AppCacheHost(int host_id, AppCacheFrontend* frontend,
+ AppCacheServiceImpl* service);
+ ~AppCacheHost() override;
+
+ // Adds/removes an observer, the AppCacheHost does not take
+ // ownership of the observer.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ // Support for cache selection and scriptable method calls.
+ void SelectCache(const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url);
+ void SelectCacheForWorker(int parent_process_id,
+ int parent_host_id);
+ void SelectCacheForSharedWorker(int64 appcache_id);
+ void MarkAsForeignEntry(const GURL& document_url,
+ int64 cache_document_was_loaded_from);
+ void GetStatusWithCallback(const GetStatusCallback& callback,
+ void* callback_param);
+ void StartUpdateWithCallback(const StartUpdateCallback& callback,
+ void* callback_param);
+ void SwapCacheWithCallback(const SwapCacheCallback& callback,
+ void* callback_param);
+
+ // Called prior to the main resource load. When the system contains multiple
+ // candidates for a main resource load, the appcache preferred by the host
+ // that created this host is used to break ties.
+ void SetSpawningHostId(int spawning_process_id, int spawning_host_id);
+
+ // May return NULL if the spawning host context has been closed, or if a
+ // spawning host context was never identified.
+ const AppCacheHost* GetSpawningHost() const;
+
+ const GURL& preferred_manifest_url() const {
+ return preferred_manifest_url_;
+ }
+ void set_preferred_manifest_url(const GURL& url) {
+ preferred_manifest_url_ = url;
+ }
+
+ // Support for loading resources out of the appcache.
+ // May return NULL if the request isn't subject to retrieval from an appache.
+ AppCacheRequestHandler* CreateRequestHandler(
+ net::URLRequest* request,
+ ResourceType resource_type);
+
+ // Support for devtools inspecting appcache resources.
+ void GetResourceList(std::vector<AppCacheResourceInfo>* resource_infos);
+
+ // Breaks any existing association between this host and a cache.
+ // 'manifest_url' is sent to DevTools as the manifest url that could have
+ // been associated before or could be associated later with this host.
+ // Associations are broken either thru the cache selection algorithm
+ // implemented in this class, or by the update algorithm (see
+ // AppCacheUpdateJob).
+ void AssociateNoCache(const GURL& manifest_url);
+
+ // Establishes an association between this host and an incomplete cache.
+ // 'manifest_url' is manifest url of the cache group being updated.
+ // Associations with incomplete caches are established by the update algorithm
+ // (see AppCacheUpdateJob).
+ void AssociateIncompleteCache(AppCache* cache, const GURL& manifest_url);
+
+ // Establishes an association between this host and a complete cache.
+ // Associations with complete caches are established either thru the cache
+ // selection algorithm implemented (in this class), or by the update algorithm
+ // (see AppCacheUpdateJob).
+ void AssociateCompleteCache(AppCache* cache);
+
+ // Adds a reference to the newest complete cache in a group, unless it's the
+ // same as the cache that is currently associated with the host.
+ void SetSwappableCache(AppCacheGroup* group);
+
+ // Used to ensure that a loaded appcache survives a frame navigation.
+ void LoadMainResourceCache(int64 cache_id);
+
+ // Used to notify the host that a namespace resource is being delivered as
+ // the main resource of the page and to provide its url.
+ void NotifyMainResourceIsNamespaceEntry(const GURL& namespace_entry_url);
+
+ // Used to notify the host that the main resource was blocked by a policy. To
+ // work properly, this method needs to by invoked prior to cache selection.
+ void NotifyMainResourceBlocked(const GURL& manifest_url);
+
+ // Used by the update job to keep track of which hosts are associated
+ // with which pending master entries.
+ const GURL& pending_master_entry_url() const {
+ return new_master_entry_url_;
+ }
+
+ int host_id() const { return host_id_; }
+ AppCacheServiceImpl* service() const { return service_; }
+ AppCacheStorage* storage() const { return storage_; }
+ AppCacheFrontend* frontend() const { return frontend_; }
+ AppCache* associated_cache() const { return associated_cache_.get(); }
+
+ void enable_cache_selection(bool enable) {
+ is_cache_selection_enabled_ = enable;
+ }
+
+ bool is_selection_pending() const {
+ return pending_selected_cache_id_ != kAppCacheNoCacheId ||
+ !pending_selected_manifest_url_.is_empty();
+ }
+
+ const GURL& first_party_url() const { return first_party_url_; }
+
+ // Methods to support cross site navigations.
+ void PrepareForTransfer();
+ void CompleteTransfer(int host_id, AppCacheFrontend* frontend);
+
+ private:
+ friend class content::AppCacheHostTest;
+ friend class content::AppCacheStorageImplTest;
+ friend class content::AppCacheRequestHandlerTest;
+ friend class content::AppCacheUpdateJobTest;
+
+ AppCacheStatus GetStatus();
+ void LoadSelectedCache(int64 cache_id);
+ void LoadOrCreateGroup(const GURL& manifest_url);
+
+ // See public Associate*Host() methods above.
+ void AssociateCacheHelper(AppCache* cache, const GURL& manifest_url);
+
+ // AppCacheStorage::Delegate impl
+ void OnCacheLoaded(AppCache* cache, int64 cache_id) override;
+ void OnGroupLoaded(AppCacheGroup* group, const GURL& manifest_url) override;
+ // AppCacheServiceImpl::Observer impl
+ void OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) override;
+
+ void FinishCacheSelection(AppCache* cache, AppCacheGroup* group);
+ void DoPendingGetStatus();
+ void DoPendingStartUpdate();
+ void DoPendingSwapCache();
+
+ void ObserveGroupBeingUpdated(AppCacheGroup* group);
+
+ // AppCacheGroup::UpdateObserver methods.
+ void OnUpdateComplete(AppCacheGroup* group) override;
+
+ // Returns true if this host is for a dedicated worker context.
+ bool is_for_dedicated_worker() const {
+ return parent_host_id_ != kAppCacheNoHostId;
+ }
+
+ // Returns the parent context's host instance. This is only valid
+ // to call when this instance is_for_dedicated_worker.
+ AppCacheHost* GetParentAppCacheHost() const;
+
+ // Identifies the corresponding appcache host in the child process.
+ int host_id_;
+
+ // Information about the host that created this one; the manifest
+ // preferred by our creator influences which cache our main resource
+ // should be loaded from.
+ int spawning_host_id_;
+ int spawning_process_id_;
+ GURL preferred_manifest_url_;
+
+ // Hosts for dedicated workers are special cased to shunt
+ // request handling off to the dedicated worker's parent.
+ // The scriptable api is not accessible in dedicated workers
+ // so the other aspects of this class are not relevant for
+ // these special case instances.
+ int parent_host_id_;
+ int parent_process_id_;
+
+ // Defined prior to refs to AppCaches and Groups because destruction
+ // order matters, the disabled_storage_reference_ must outlive those
+ // objects. See additional comments for the storage_ member.
+ scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
+
+ // The cache associated with this host, if any.
+ scoped_refptr<AppCache> associated_cache_;
+
+ // Hold a reference to the newest complete cache (if associated cache is
+ // not the newest) to keep the newest cache in existence while the app cache
+ // group is in use. The newest complete cache may have no associated hosts
+ // holding any references to it and would otherwise be deleted prematurely.
+ scoped_refptr<AppCache> swappable_cache_;
+
+ // Keep a reference to the group being updated until the update completes.
+ scoped_refptr<AppCacheGroup> group_being_updated_;
+
+ // Similarly, keep a reference to the newest cache of the group until the
+ // update completes. When adding a new master entry to a cache that is not
+ // in use in any other host, this reference keeps the cache in memory.
+ scoped_refptr<AppCache> newest_cache_of_group_being_updated_;
+
+ // Keep a reference to the cache of the main resource so it survives frame
+ // navigations.
+ scoped_refptr<AppCache> main_resource_cache_;
+ int64 pending_main_resource_cache_id_;
+
+ // Cache loading is async, if we're loading a specific cache or group
+ // for the purposes of cache selection, one or the other of these will
+ // indicate which cache or group is being loaded.
+ int64 pending_selected_cache_id_;
+ GURL pending_selected_manifest_url_;
+
+ // Used to avoid stepping on pages controlled by ServiceWorkers.
+ bool is_cache_selection_enabled_;
+
+ // A new master entry to be added to the cache, may be empty.
+ GURL new_master_entry_url_;
+
+ // The frontend proxy to deliver notifications to the child process.
+ AppCacheFrontend* frontend_;
+
+ // Our central service object.
+ AppCacheServiceImpl* service_;
+
+ // And the equally central storage object, with a twist. In some error
+ // conditions the storage object gets recreated and reinitialized. The
+ // disabled_storage_reference_ (defined earlier) allows for cleanup of an
+ // instance that got disabled after we had latched onto it. In normal
+ // circumstances, disabled_storage_reference_ is expected to be NULL.
+ // When non-NULL both storage_ and disabled_storage_reference_ refer to the
+ // same instance.
+ AppCacheStorage* storage_;
+
+ // Since these are synchronous scriptable API calls in the client, there can
+ // only be one type of callback pending. Also, we have to wait until we have a
+ // cache selection prior to responding to these calls, as cache selection
+ // involves async loading of a cache or a group from storage.
+ GetStatusCallback pending_get_status_callback_;
+ StartUpdateCallback pending_start_update_callback_;
+ SwapCacheCallback pending_swap_cache_callback_;
+ void* pending_callback_param_;
+
+ // True if an intercept or fallback namespace resource was
+ // delivered as the main resource.
+ bool main_resource_was_namespace_entry_;
+ GURL namespace_entry_url_;
+
+ // True if requests for this host were blocked by a policy.
+ bool main_resource_blocked_;
+ GURL blocked_manifest_url_;
+
+ // Tells if info about associated cache is pending. Info is pending
+ // when update job has not returned success yet.
+ bool associated_cache_info_pending_;
+
+ // List of objects observing us.
+ ObserverList<Observer> observers_;
+
+ // Used to inform the QuotaManager of what origins are currently in use.
+ GURL origin_in_use_;
+
+ // First party url to be used in policy checks.
+ GURL first_party_url_;
+
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, CleanupUnusedGroup);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, Basic);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectNoCache);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, ForeignEntry);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, FailedCacheLoad);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, FailedGroupLoad);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SetSwappableCache);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, ForDedicatedWorker);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectCacheAllowed);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectCacheBlocked);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, CleanupUnusedCache);
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_HOST_H_
diff --git a/chromium/content/browser/appcache/appcache_host_unittest.cc b/chromium/content/browser/appcache/appcache_host_unittest.cc
index 6b9970dc4ff..817e8c0c924 100644
--- a/chromium/content/browser/appcache/appcache_host_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_host_unittest.cc
@@ -6,29 +6,15 @@
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/mock_appcache_policy.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/url_request/url_request.h"
+#include "storage/browser/quota/quota_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_backend_impl.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_host.h"
-#include "webkit/browser/quota/quota_manager.h"
-
-using appcache::AppCache;
-using appcache::AppCacheBackendImpl;
-using appcache::AppCacheEntry;
-using appcache::AppCacheFrontend;
-using appcache::AppCacheGroup;
-using appcache::AppCacheHost;
-using appcache::kAppCacheNoCacheId;
-using appcache::APPCACHE_ERROR_EVENT;
-using appcache::APPCACHE_STATUS_OBSOLETE;
-using appcache::APPCACHE_OBSOLETE_EVENT;
-using appcache::APPCACHE_PROGRESS_EVENT;
-using appcache::AppCacheStatus;
-using appcache::APPCACHE_STATUS_UNCACHED;
namespace content {
@@ -50,88 +36,81 @@ class AppCacheHostTest : public testing::Test {
public:
MockFrontend()
: last_host_id_(-222), last_cache_id_(-222),
- last_status_(appcache::APPCACHE_STATUS_OBSOLETE),
- last_status_changed_(appcache::APPCACHE_STATUS_OBSOLETE),
- last_event_id_(appcache::APPCACHE_OBSOLETE_EVENT),
+ last_status_(APPCACHE_STATUS_OBSOLETE),
+ last_status_changed_(APPCACHE_STATUS_OBSOLETE),
+ last_event_id_(APPCACHE_OBSOLETE_EVENT),
content_blocked_(false) {
}
- virtual void OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) OVERRIDE {
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override {
last_host_id_ = host_id;
last_cache_id_ = info.cache_id;
last_status_ = info.status;
}
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) OVERRIDE {
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override {
last_status_changed_ = status;
}
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) OVERRIDE {
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override {
last_event_id_ = event_id;
}
- virtual void OnErrorEventRaised(
- const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details) OVERRIDE {
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override {
last_event_id_ = APPCACHE_ERROR_EVENT;
}
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total,
- int num_complete) OVERRIDE {
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override {
last_event_id_ = APPCACHE_PROGRESS_EVENT;
}
- virtual void OnLogMessage(int host_id,
- appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE {
- }
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override {}
- virtual void OnContentBlocked(int host_id,
- const GURL& manifest_url) OVERRIDE {
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override {
content_blocked_ = true;
}
int last_host_id_;
int64 last_cache_id_;
- appcache::AppCacheStatus last_status_;
- appcache::AppCacheStatus last_status_changed_;
- appcache::AppCacheEventID last_event_id_;
+ AppCacheStatus last_status_;
+ AppCacheStatus last_status_changed_;
+ AppCacheEventID last_event_id_;
bool content_blocked_;
};
- class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
+ class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
public:
MockQuotaManagerProxy() : QuotaManagerProxy(NULL, NULL) {}
// Not needed for our tests.
- virtual void RegisterClient(quota::QuotaClient* client) OVERRIDE {}
- virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type) OVERRIDE {}
- virtual void NotifyStorageModified(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- int64 delta) OVERRIDE {}
- virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- bool enabled) OVERRIDE {}
- virtual void GetUsageAndQuota(
- base::SequencedTaskRunner* original_task_runner,
- const GURL& origin,
- quota::StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE {}
-
- virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {
- inuse_[origin] += 1;
- }
-
- virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {
+ void RegisterClient(storage::QuotaClient* client) override {}
+ void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type) override {}
+ void NotifyStorageModified(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ int64 delta) override {}
+ void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ bool enabled) override {}
+ void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
+ const GURL& origin,
+ storage::StorageType type,
+ const GetUsageAndQuotaCallback& callback) override {}
+
+ void NotifyOriginInUse(const GURL& origin) override { inuse_[origin] += 1; }
+
+ void NotifyOriginNoLongerInUse(const GURL& origin) override {
inuse_[origin] -= 1;
}
@@ -147,7 +126,7 @@ class AppCacheHostTest : public testing::Test {
std::map<GURL, int> inuse_;
protected:
- virtual ~MockQuotaManagerProxy() {}
+ ~MockQuotaManagerProxy() override {}
};
void GetStatusCallback(AppCacheStatus status, void* param) {
@@ -172,9 +151,9 @@ class AppCacheHostTest : public testing::Test {
MockFrontend mock_frontend_;
// Mock callbacks we expect to receive from the 'host'
- appcache::GetStatusCallback get_status_callback_;
- appcache::StartUpdateCallback start_update_callback_;
- appcache::SwapCacheCallback swap_cache_callback_;
+ content::GetStatusCallback get_status_callback_;
+ content::StartUpdateCallback start_update_callback_;
+ content::SwapCacheCallback swap_cache_callback_;
AppCacheStatus last_status_result_;
bool last_swap_result_;
@@ -387,11 +366,11 @@ TEST_F(AppCacheHostTest, SetSwappableCache) {
host.AssociateCompleteCache(cache1);
EXPECT_FALSE(host.swappable_cache_.get()); // was same as associated cache
- EXPECT_EQ(appcache::APPCACHE_STATUS_IDLE, host.GetStatus());
+ EXPECT_EQ(APPCACHE_STATUS_IDLE, host.GetStatus());
// verify OnCacheSelected was called
EXPECT_EQ(host.host_id(), mock_frontend_.last_host_id_);
EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_);
- EXPECT_EQ(appcache::APPCACHE_STATUS_IDLE, mock_frontend_.last_status_);
+ EXPECT_EQ(APPCACHE_STATUS_IDLE, mock_frontend_.last_status_);
AppCache* cache2 = new AppCache(service_.storage(), 222);
cache2->set_complete(true);
diff --git a/chromium/content/browser/appcache/appcache_interceptor.cc b/chromium/content/browser/appcache/appcache_interceptor.cc
index ac7dbc3b607..adc6d2c6979 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.cc
+++ b/chromium/content/browser/appcache/appcache_interceptor.cc
@@ -4,41 +4,63 @@
#include "content/browser/appcache/appcache_interceptor.h"
-#include "webkit/browser/appcache/appcache_backend_impl.h"
-#include "webkit/browser/appcache/appcache_host.h"
-#include "webkit/browser/appcache/appcache_request_handler.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
-#include "webkit/browser/appcache/appcache_url_request_job.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-
-using appcache::AppCacheBackendImpl;
-using appcache::AppCacheHost;
-using appcache::AppCacheRequestHandler;
-using appcache::AppCacheServiceImpl;
-using appcache::kAppCacheNoCacheId;
-using appcache::kAppCacheNoHostId;
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_request_handler.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_url_request_job.h"
+#include "content/common/appcache_interfaces.h"
namespace content {
+class AppCacheInterceptor::StartInterceptor
+ : public net::URLRequestInterceptor {
+ public:
+ StartInterceptor() {}
+ ~StartInterceptor() override {}
+ net::URLRequestJob* MaybeInterceptRequest(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ AppCacheRequestHandler* handler = GetHandler(request);
+ if (!handler)
+ return NULL;
+ return handler->MaybeLoadResource(request, network_delegate);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StartInterceptor);
+};
+
+
// static
AppCacheInterceptor* AppCacheInterceptor::GetInstance() {
return Singleton<AppCacheInterceptor>::get();
}
-void AppCacheInterceptor::SetHandler(
- net::URLRequest* request, AppCacheRequestHandler* handler) {
+// static
+scoped_ptr<net::URLRequestInterceptor>
+AppCacheInterceptor::CreateStartInterceptor() {
+ return scoped_ptr<net::URLRequestInterceptor>(
+ new StartInterceptor);
+}
+
+void AppCacheInterceptor::SetHandler(net::URLRequest* request,
+ AppCacheRequestHandler* handler) {
request->SetUserData(GetInstance(), handler); // request takes ownership
}
AppCacheRequestHandler* AppCacheInterceptor::GetHandler(
net::URLRequest* request) {
- return reinterpret_cast<AppCacheRequestHandler*>(
+ return static_cast<AppCacheRequestHandler*>(
request->GetUserData(GetInstance()));
}
void AppCacheInterceptor::SetExtraRequestInfo(
- net::URLRequest* request, AppCacheServiceImpl* service, int process_id,
- int host_id, ResourceType::Type resource_type) {
+ net::URLRequest* request,
+ AppCacheServiceImpl* service,
+ int process_id,
+ int host_id,
+ ResourceType resource_type) {
if (!service || (host_id == kAppCacheNoHostId))
return;
@@ -100,10 +122,8 @@ AppCacheInterceptor::~AppCacheInterceptor() {
net::URLRequestJob* AppCacheInterceptor::MaybeIntercept(
net::URLRequest* request, net::NetworkDelegate* network_delegate) {
- AppCacheRequestHandler* handler = GetHandler(request);
- if (!handler)
- return NULL;
- return handler->MaybeLoadResource(request, network_delegate);
+ // Intentionally empty, handled by class StartInterceptor.
+ return NULL;
}
net::URLRequestJob* AppCacheInterceptor::MaybeInterceptRedirect(
diff --git a/chromium/content/browser/appcache/appcache_interceptor.h b/chromium/content/browser/appcache/appcache_interceptor.h
index d8da18190f4..049fd7a5732 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.h
+++ b/chromium/content/browser/appcache/appcache_interceptor.h
@@ -7,16 +7,14 @@
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
+#include "content/public/common/resource_type.h"
#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_interceptor.h"
#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
-namespace appcache {
+namespace content {
class AppCacheRequestHandler;
class AppCacheServiceImpl;
-}
-
-namespace content {
// An interceptor to hijack requests and potentially service them out of
// the appcache.
@@ -31,10 +29,10 @@ class CONTENT_EXPORT AppCacheInterceptor
// Must be called to make a request eligible for retrieval from an appcache.
static void SetExtraRequestInfo(net::URLRequest* request,
- appcache::AppCacheServiceImpl* service,
+ AppCacheServiceImpl* service,
int process_id,
int host_id,
- ResourceType::Type resource_type);
+ ResourceType resource_type);
// May be called after response headers are complete to retrieve extra
// info about the response.
@@ -51,28 +49,37 @@ class CONTENT_EXPORT AppCacheInterceptor
static AppCacheInterceptor* GetInstance();
+ // The appcache system employs two different interceptors. The singleton
+ // AppCacheInterceptor derives URLRequest::Interceptor and is used
+ // to hijack request handling upon receipt of the response or a redirect.
+ // A separate URLRequestInterceptor derivative is used to hijack handling
+ // at the very start of request processing. The separate handler allows the
+ // content lib to order its collection of net::URLRequestInterceptors.
+ static scoped_ptr<net::URLRequestInterceptor> CreateStartInterceptor();
+
protected:
// Override from net::URLRequest::Interceptor:
- virtual net::URLRequestJob* MaybeIntercept(
+ net::URLRequestJob* MaybeIntercept(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) OVERRIDE;
- virtual net::URLRequestJob* MaybeInterceptResponse(
+ net::NetworkDelegate* network_delegate) override;
+ net::URLRequestJob* MaybeInterceptResponse(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) OVERRIDE;
- virtual net::URLRequestJob* MaybeInterceptRedirect(
+ net::NetworkDelegate* network_delegate) override;
+ net::URLRequestJob* MaybeInterceptRedirect(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- const GURL& location) OVERRIDE;
+ const GURL& location) override;
private:
friend struct DefaultSingletonTraits<AppCacheInterceptor>;
+ class StartInterceptor;
AppCacheInterceptor();
- virtual ~AppCacheInterceptor();
+ ~AppCacheInterceptor() override;
static void SetHandler(net::URLRequest* request,
- appcache::AppCacheRequestHandler* handler);
- static appcache::AppCacheRequestHandler* GetHandler(net::URLRequest* request);
+ AppCacheRequestHandler* handler);
+ static AppCacheRequestHandler* GetHandler(net::URLRequest* request);
DISALLOW_COPY_AND_ASSIGN(AppCacheInterceptor);
};
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser.cc b/chromium/content/browser/appcache/appcache_manifest_parser.cc
new file mode 100644
index 00000000000..99f5e87f379
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_manifest_parser.cc
@@ -0,0 +1,382 @@
+// Copyright 2014 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 is a port of ManifestParser.cc from WebKit/WebCore/loader/appcache.
+
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "content/browser/appcache/appcache_manifest_parser.h"
+
+#include "base/command_line.h"
+#include "base/i18n/icu_string_conversions.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// Helper function used to identify 'isPattern' annotations.
+bool HasPatternMatchingAnnotation(const wchar_t* line_p,
+ const wchar_t* line_end) {
+ // Skip whitespace separating the resource url from the annotation.
+ // Note: trailing whitespace has already been trimmed from the line.
+ while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
+ ++line_p;
+ if (line_p == line_end)
+ return false;
+ std::wstring annotation(line_p, line_end - line_p);
+ return annotation == L"isPattern";
+}
+
+}
+
+enum Mode {
+ EXPLICIT,
+ INTERCEPT,
+ FALLBACK,
+ ONLINE_WHITELIST,
+ UNKNOWN_MODE,
+};
+
+enum InterceptVerb {
+ RETURN,
+ EXECUTE,
+ UNKNOWN_VERB,
+};
+
+AppCacheManifest::AppCacheManifest()
+ : online_whitelist_all(false),
+ did_ignore_intercept_namespaces(false) {
+}
+
+AppCacheManifest::~AppCacheManifest() {}
+
+bool ParseManifest(const GURL& manifest_url, const char* data, int length,
+ ParseMode parse_mode, AppCacheManifest& manifest) {
+ // This is an implementation of the parsing algorithm specified in
+ // the HTML5 offline web application docs:
+ // http://www.w3.org/TR/html5/offline.html
+ // Do not modify it without consulting those docs.
+ // Though you might be tempted to convert these wstrings to UTF-8 or
+ // base::string16, this implementation seems simpler given the constraints.
+
+ const wchar_t kSignature[] = L"CACHE MANIFEST";
+ const size_t kSignatureLength = arraysize(kSignature) - 1;
+ const wchar_t kChromiumSignature[] = L"CHROMIUM CACHE MANIFEST";
+ const size_t kChromiumSignatureLength = arraysize(kChromiumSignature) - 1;
+
+ DCHECK(manifest.explicit_urls.empty());
+ DCHECK(manifest.fallback_namespaces.empty());
+ DCHECK(manifest.online_whitelist_namespaces.empty());
+ DCHECK(!manifest.online_whitelist_all);
+ DCHECK(!manifest.did_ignore_intercept_namespaces);
+
+ Mode mode = EXPLICIT;
+
+ std::wstring data_string;
+ // TODO(jennb): cannot do UTF8ToWide(data, length, &data_string);
+ // until UTF8ToWide uses 0xFFFD Unicode replacement character.
+ base::CodepageToWide(std::string(data, length), base::kCodepageUTF8,
+ base::OnStringConversionError::SUBSTITUTE, &data_string);
+ const wchar_t* p = data_string.c_str();
+ const wchar_t* end = p + data_string.length();
+
+ // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?"
+ // Example: "CACHE MANIFEST #comment" is a valid signature.
+ // Example: "CACHE MANIFEST;V2" is not.
+
+ // When the input data starts with a UTF-8 Byte-Order-Mark
+ // (0xEF, 0xBB, 0xBF), the UTF8ToWide() function converts it to a
+ // Unicode BOM (U+FEFF). Skip a converted Unicode BOM if it exists.
+ int bom_offset = 0;
+ if (!data_string.empty() && data_string[0] == 0xFEFF) {
+ bom_offset = 1;
+ ++p;
+ }
+
+ if (p >= end)
+ return false;
+
+ // Check for a supported signature and skip p past it.
+ if (0 == data_string.compare(bom_offset, kSignatureLength,
+ kSignature)) {
+ p += kSignatureLength;
+ } else if (0 == data_string.compare(bom_offset, kChromiumSignatureLength,
+ kChromiumSignature)) {
+ p += kChromiumSignatureLength;
+ } else {
+ return false;
+ }
+
+ // Character after "CACHE MANIFEST" must be whitespace.
+ if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r')
+ return false;
+
+ // Skip to the end of the line.
+ while (p < end && *p != '\r' && *p != '\n')
+ ++p;
+
+ while (1) {
+ // Skip whitespace
+ while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
+ ++p;
+
+ if (p == end)
+ break;
+
+ const wchar_t* line_start = p;
+
+ // Find the end of the line
+ while (p < end && *p != '\r' && *p != '\n')
+ ++p;
+
+ // Check if we have a comment
+ if (*line_start == '#')
+ continue;
+
+ // Get rid of trailing whitespace
+ const wchar_t* tmp = p - 1;
+ while (tmp > line_start && (*tmp == ' ' || *tmp == '\t'))
+ --tmp;
+
+ std::wstring line(line_start, tmp - line_start + 1);
+
+ if (line == L"CACHE:") {
+ mode = EXPLICIT;
+ } else if (line == L"FALLBACK:") {
+ mode = FALLBACK;
+ } else if (line == L"NETWORK:") {
+ mode = ONLINE_WHITELIST;
+ } else if (line == L"CHROMIUM-INTERCEPT:") {
+ mode = INTERCEPT;
+ } else if (*(line.end() - 1) == ':') {
+ mode = UNKNOWN_MODE;
+ } else if (mode == UNKNOWN_MODE) {
+ continue;
+ } else if (line == L"*" && mode == ONLINE_WHITELIST) {
+ manifest.online_whitelist_all = true;
+ continue;
+ } else if (mode == EXPLICIT || mode == ONLINE_WHITELIST) {
+ const wchar_t *line_p = line.c_str();
+ const wchar_t *line_end = line_p + line.length();
+
+ // Look for whitespace separating the URL from subsequent ignored tokens.
+ while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
+ ++line_p;
+
+ base::string16 url16;
+ base::WideToUTF16(line.c_str(), line_p - line.c_str(), &url16);
+ GURL url = manifest_url.Resolve(url16);
+ if (!url.is_valid())
+ continue;
+ if (url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url = url.ReplaceComponents(replacements);
+ }
+
+ // Scheme component must be the same as the manifest URL's.
+ if (url.scheme() != manifest_url.scheme()) {
+ continue;
+ }
+
+ // See http://code.google.com/p/chromium/issues/detail?id=69594
+ // We willfully violate the HTML5 spec at this point in order
+ // to support the appcaching of cross-origin HTTPS resources.
+ // Per the spec, EXPLICIT cross-origin HTTS resources should be
+ // ignored here. We've opted for a milder constraint and allow
+ // caching unless the resource has a "no-store" header. That
+ // condition is enforced in AppCacheUpdateJob.
+
+ if (mode == EXPLICIT) {
+ manifest.explicit_urls.insert(url.spec());
+ } else {
+ bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end);
+ manifest.online_whitelist_namespaces.push_back(
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, url, GURL(),
+ is_pattern));
+ }
+ } else if (mode == INTERCEPT) {
+ if (parse_mode != PARSE_MANIFEST_ALLOWING_INTERCEPTS) {
+ manifest.did_ignore_intercept_namespaces = true;
+ continue;
+ }
+
+ // Lines of the form,
+ // <urlnamespace> <intercept_type> <targeturl>
+ const wchar_t* line_p = line.c_str();
+ const wchar_t* line_end = line_p + line.length();
+
+ // Look for first whitespace separating the url namespace from
+ // the intercept type.
+ while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
+ ++line_p;
+
+ if (line_p == line_end)
+ continue; // There was no whitespace separating the URLs.
+
+ base::string16 namespace_url16;
+ base::WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16);
+ GURL namespace_url = manifest_url.Resolve(namespace_url16);
+ if (!namespace_url.is_valid())
+ continue;
+ if (namespace_url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ namespace_url = namespace_url.ReplaceComponents(replacements);
+ }
+
+ // The namespace URL must have the same scheme, host and port
+ // as the manifest's URL.
+ if (manifest_url.GetOrigin() != namespace_url.GetOrigin())
+ continue;
+
+ // Skip whitespace separating namespace from the type.
+ while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
+ ++line_p;
+
+ // Look for whitespace separating the type from the target url.
+ const wchar_t* type_start = line_p;
+ while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
+ ++line_p;
+
+ // Look for a type value we understand, otherwise skip the line.
+ InterceptVerb verb = UNKNOWN_VERB;
+ std::wstring type(type_start, line_p - type_start);
+ if (type == L"return") {
+ verb = RETURN;
+ } else if (type == L"execute" &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ kEnableExecutableHandlers)) {
+ verb = EXECUTE;
+ }
+ if (verb == UNKNOWN_VERB)
+ continue;
+
+ // Skip whitespace separating type from the target_url.
+ while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
+ ++line_p;
+
+ // Look for whitespace separating the URL from subsequent ignored tokens.
+ const wchar_t* target_url_start = line_p;
+ while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
+ ++line_p;
+
+ base::string16 target_url16;
+ base::WideToUTF16(target_url_start, line_p - target_url_start,
+ &target_url16);
+ GURL target_url = manifest_url.Resolve(target_url16);
+ if (!target_url.is_valid())
+ continue;
+
+ if (target_url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ target_url = target_url.ReplaceComponents(replacements);
+ }
+ if (manifest_url.GetOrigin() != target_url.GetOrigin())
+ continue;
+
+ bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end);
+ manifest.intercept_namespaces.push_back(
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, namespace_url,
+ target_url, is_pattern, verb == EXECUTE));
+ } else if (mode == FALLBACK) {
+ const wchar_t* line_p = line.c_str();
+ const wchar_t* line_end = line_p + line.length();
+
+ // Look for whitespace separating the two URLs
+ while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
+ ++line_p;
+
+ if (line_p == line_end) {
+ // There was no whitespace separating the URLs.
+ continue;
+ }
+
+ base::string16 namespace_url16;
+ base::WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16);
+ GURL namespace_url = manifest_url.Resolve(namespace_url16);
+ if (!namespace_url.is_valid())
+ continue;
+ if (namespace_url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ namespace_url = namespace_url.ReplaceComponents(replacements);
+ }
+
+ // Fallback namespace URL must have the same scheme, host and port
+ // as the manifest's URL.
+ if (manifest_url.GetOrigin() != namespace_url.GetOrigin()) {
+ continue;
+ }
+
+ // Skip whitespace separating fallback namespace from URL.
+ while (line_p < line_end && (*line_p == '\t' || *line_p == ' '))
+ ++line_p;
+
+ // Look for whitespace separating the URL from subsequent ignored tokens.
+ const wchar_t* fallback_start = line_p;
+ while (line_p < line_end && *line_p != '\t' && *line_p != ' ')
+ ++line_p;
+
+ base::string16 fallback_url16;
+ base::WideToUTF16(fallback_start, line_p - fallback_start,
+ &fallback_url16);
+ GURL fallback_url = manifest_url.Resolve(fallback_url16);
+ if (!fallback_url.is_valid())
+ continue;
+ if (fallback_url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ fallback_url = fallback_url.ReplaceComponents(replacements);
+ }
+
+ // Fallback entry URL must have the same scheme, host and port
+ // as the manifest's URL.
+ if (manifest_url.GetOrigin() != fallback_url.GetOrigin()) {
+ continue;
+ }
+
+ bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end);
+
+ // Store regardless of duplicate namespace URL. Only first match
+ // will ever be used.
+ manifest.fallback_namespaces.push_back(
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, namespace_url,
+ fallback_url, is_pattern));
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser.h b/chromium/content/browser/appcache/appcache_manifest_parser.h
new file mode 100644
index 00000000000..19685f8e705
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_manifest_parser.h
@@ -0,0 +1,72 @@
+// Copyright 2014 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 is a port of ManifestParser.h from WebKit/WebCore/loader/appcache.
+
+/*
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_MANIFEST_PARSER_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_MANIFEST_PARSER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace content {
+
+struct CONTENT_EXPORT AppCacheManifest {
+ AppCacheManifest();
+ ~AppCacheManifest();
+
+ base::hash_set<std::string> explicit_urls;
+ AppCacheNamespaceVector intercept_namespaces;
+ AppCacheNamespaceVector fallback_namespaces;
+ AppCacheNamespaceVector online_whitelist_namespaces;
+ bool online_whitelist_all;
+ bool did_ignore_intercept_namespaces;
+};
+
+enum ParseMode {
+ PARSE_MANIFEST_PER_STANDARD,
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS
+};
+
+CONTENT_EXPORT bool ParseManifest(
+ const GURL& manifest_url,
+ const char* data,
+ int length,
+ ParseMode parse_mode,
+ AppCacheManifest& manifest);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_MANIFEST_PARSER_H_
diff --git a/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
new file mode 100644
index 00000000000..6dd8c279121
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -0,0 +1,516 @@
+// Copyright 2014 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 <string>
+
+#include "content/browser/appcache/appcache_manifest_parser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class AppCacheManifestParserTest : public testing::Test {
+};
+
+TEST(AppCacheManifestParserTest, NoData) {
+ GURL url;
+ AppCacheManifest manifest;
+ EXPECT_FALSE(ParseManifest(url, "", 0,
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_FALSE(ParseManifest(url, "CACHE MANIFEST\r", 0, // Len is 0.
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+}
+
+TEST(AppCacheManifestParserTest, CheckSignature) {
+ GURL url;
+ AppCacheManifest manifest;
+
+ const std::string kBadSignatures[] = {
+ "foo",
+ "CACHE MANIFEST;V2\r", // not followed by whitespace
+ "CACHE MANIFEST#bad\r", // no whitespace before comment
+ "cache manifest ", // wrong case
+ "#CACHE MANIFEST\r", // comment
+ "xCACHE MANIFEST\n", // bad first char
+ " CACHE MANIFEST\r", // begins with whitespace
+ "\xEF\xBE\xBF" "CACHE MANIFEST\r", // bad UTF-8 BOM value
+ };
+
+ for (size_t i = 0; i < arraysize(kBadSignatures); ++i) {
+ const std::string bad = kBadSignatures[i];
+ EXPECT_FALSE(ParseManifest(url, bad.c_str(), bad.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ }
+
+ const std::string kGoodSignatures[] = {
+ "CACHE MANIFEST",
+ "CACHE MANIFEST ",
+ "CACHE MANIFEST\r",
+ "CACHE MANIFEST\n",
+ "CACHE MANIFEST\r\n",
+ "CACHE MANIFEST\t# ignore me\r",
+ "CACHE MANIFEST ignore\r\n",
+ "CHROMIUM CACHE MANIFEST\r\n",
+ "\xEF\xBB\xBF" "CACHE MANIFEST \r\n", // BOM present
+ };
+
+ for (size_t i = 0; i < arraysize(kGoodSignatures); ++i) {
+ const std::string good = kGoodSignatures[i];
+ EXPECT_TRUE(ParseManifest(url, good.c_str(), good.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ }
+}
+
+TEST(AppCacheManifestParserTest, NoManifestUrl) {
+ AppCacheManifest manifest;
+ const std::string kData("CACHE MANIFEST\r"
+ "relative/tobase.com\r"
+ "http://absolute.com/addme.com");
+ const GURL kUrl;
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.explicit_urls.empty());
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+}
+
+TEST(AppCacheManifestParserTest, ExplicitUrls) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://www.foo.com");
+ const std::string kData("CACHE MANIFEST\r"
+ "relative/one\r"
+ "# some comment\r"
+ "http://www.foo.com/two#strip\r\n"
+ "NETWORK:\r"
+ " \t CACHE:\r"
+ "HTTP://www.diff.com/three\r"
+ "FALLBACK:\r"
+ " \t # another comment with leading whitespace\n"
+ "IGNORE:\r"
+ "http://www.foo.com/ignore\r"
+ "CACHE: \r"
+ "garbage:#!@\r"
+ "https://www.foo.com/diffscheme \t \r"
+ " \t relative/four#stripme\n\r"
+ "*\r");
+
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+
+ base::hash_set<std::string> urls = manifest.explicit_urls;
+ const size_t kExpected = 5;
+ ASSERT_EQ(kExpected, urls.size());
+ EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end());
+
+ // Wildcard is treated as a relative URL in explicit section.
+ EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end());
+
+ // We should get the same results with intercepts disallowed.
+ manifest = AppCacheManifest();
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_PER_STANDARD, manifest));
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+
+ urls = manifest.explicit_urls;
+ ASSERT_EQ(kExpected, urls.size());
+ EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end());
+
+ // Wildcard is treated as a relative URL in explicit section.
+ EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end());
+}
+
+TEST(AppCacheManifestParserTest, WhitelistUrls) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://www.bar.com");
+ const std::string kData("CACHE MANIFEST\r"
+ "NETWORK:\r"
+ "relative/one\r"
+ "# a comment\r"
+ "http://www.bar.com/two\r"
+ "HTTP://www.diff.com/three#strip\n\r"
+ "FALLBACK:\r"
+ "garbage\r"
+ "UNKNOWN:\r"
+ "http://www.bar.com/ignore\r"
+ "CACHE:\r"
+ "NETWORK:\r"
+ "https://www.wrongscheme.com\n"
+ "relative/four#stripref \t \r"
+ "http://www.five.com\r\n"
+ "*foo\r");
+
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.explicit_urls.empty());
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.intercept_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+
+ const AppCacheNamespaceVector& online = manifest.online_whitelist_namespaces;
+ const size_t kExpected = 6;
+ ASSERT_EQ(kExpected, online.size());
+ EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, online[0].type);
+ EXPECT_FALSE(online[0].is_pattern);
+ EXPECT_TRUE(online[0].target_url.is_empty());
+ EXPECT_EQ(GURL("http://www.bar.com/relative/one"), online[0].namespace_url);
+ EXPECT_EQ(GURL("http://www.bar.com/two"), online[1].namespace_url);
+ EXPECT_EQ(GURL("http://www.diff.com/three"), online[2].namespace_url);
+ EXPECT_EQ(GURL("http://www.bar.com/relative/four"), online[3].namespace_url);
+ EXPECT_EQ(GURL("http://www.five.com"), online[4].namespace_url);
+ EXPECT_EQ(GURL("http://www.bar.com/*foo"), online[5].namespace_url);
+}
+
+TEST(AppCacheManifestParserTest, FallbackUrls) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://glorp.com");
+ const std::string kData("CACHE MANIFEST\r"
+ "# a comment\r"
+ "CACHE:\r"
+ "NETWORK:\r"
+ "UNKNOWN:\r"
+ "FALLBACK:\r"
+ "relative/one \t \t http://glorp.com/onefb \t \r"
+ "*\r"
+ "https://glorp.com/wrong http://glorp.com/wrongfb\r"
+ "http://glorp.com/two#strip relative/twofb\r"
+ "HTTP://glorp.com/three relative/threefb#strip\n"
+ "http://glorp.com/three http://glorp.com/three-dup\r"
+ "http://glorp.com/solo \t \r\n"
+ "http://diff.com/ignore http://glorp.com/wronghost\r"
+ "http://glorp.com/wronghost http://diff.com/ohwell\r"
+ "relative/badscheme ftp://glorp.com/ignored\r"
+ "garbage\r\n"
+ "CACHE:\r"
+ "# only fallback urls in this test\r"
+ "FALLBACK:\n"
+ "relative/four#strip relative/fourfb#strip\r"
+ "http://www.glorp.com/notsame relative/skipped\r");
+
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.explicit_urls.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+
+ const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces;
+ const size_t kExpected = 5;
+ ASSERT_EQ(kExpected, fallbacks.size());
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[2].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[3].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[4].type);
+ EXPECT_EQ(GURL("http://glorp.com/relative/one"),
+ fallbacks[0].namespace_url);
+ EXPECT_EQ(GURL("http://glorp.com/onefb"),
+ fallbacks[0].target_url);
+ EXPECT_EQ(GURL("http://glorp.com/two"),
+ fallbacks[1].namespace_url);
+ EXPECT_EQ(GURL("http://glorp.com/relative/twofb"),
+ fallbacks[1].target_url);
+ EXPECT_EQ(GURL("http://glorp.com/three"),
+ fallbacks[2].namespace_url);
+ EXPECT_EQ(GURL("http://glorp.com/relative/threefb"),
+ fallbacks[2].target_url);
+ EXPECT_EQ(GURL("http://glorp.com/three"), // duplicates are stored
+ fallbacks[3].namespace_url);
+ EXPECT_EQ(GURL("http://glorp.com/three-dup"),
+ fallbacks[3].target_url);
+ EXPECT_EQ(GURL("http://glorp.com/relative/four"),
+ fallbacks[4].namespace_url);
+ EXPECT_EQ(GURL("http://glorp.com/relative/fourfb"),
+ fallbacks[4].target_url);
+
+ EXPECT_TRUE(manifest.intercept_namespaces.empty());
+}
+
+TEST(AppCacheManifestParserTest, FallbackUrlsWithPort) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://www.portme.com:1234");
+ const std::string kData("CACHE MANIFEST\r"
+ "FALLBACK:\r"
+ "http://www.portme.com:1234/one relative/onefb\r"
+ "HTTP://www.portme.com:9876/wrong http://www.portme.com:1234/ignore\r"
+ "http://www.portme.com:1234/stillwrong http://www.portme.com:42/boo\r"
+ "relative/two relative/twofb\r"
+ "http://www.portme.com:1234/three HTTP://www.portme.com:1234/threefb\r"
+ "http://www.portme.com/noport http://www.portme.com:1234/skipped\r"
+ "http://www.portme.com:1234/skipme http://www.portme.com/noport\r");
+
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.explicit_urls.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+
+ const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces;
+ const size_t kExpected = 3;
+ ASSERT_EQ(kExpected, fallbacks.size());
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[2].type);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/one"),
+ fallbacks[0].namespace_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/relative/onefb"),
+ fallbacks[0].target_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"),
+ fallbacks[1].namespace_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/relative/twofb"),
+ fallbacks[1].target_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/three"),
+ fallbacks[2].namespace_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/threefb"),
+ fallbacks[2].target_url);
+
+ EXPECT_TRUE(manifest.intercept_namespaces.empty());
+}
+
+TEST(AppCacheManifestParserTest, InterceptUrls) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://www.portme.com:1234");
+ const std::string kData("CHROMIUM CACHE MANIFEST\r"
+ "CHROMIUM-INTERCEPT:\r"
+ "http://www.portme.com:1234/one return relative/int1\r"
+ "HTTP://www.portme.com:9/wrong return http://www.portme.com:1234/ignore\r"
+ "http://www.portme.com:1234/wrong return http://www.portme.com:9/boo\r"
+ "relative/two return relative/int2\r"
+ "relative/three wrong relative/threefb\r"
+ "http://www.portme.com:1234/three return HTTP://www.portme.com:1234/int3\r"
+ "http://www.portme.com/noport return http://www.portme.com:1234/skipped\r"
+ "http://www.portme.com:1234/skipme return http://www.portme.com/noport\r"
+ "relative/wrong/again missing/intercept_type\r");
+
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.explicit_urls.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+
+ const AppCacheNamespaceVector& intercepts = manifest.intercept_namespaces;
+ const size_t kExpected = 3;
+ ASSERT_EQ(kExpected, intercepts.size());
+ EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[0].type);
+ EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[1].type);
+ EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[2].type);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/one"),
+ intercepts[0].namespace_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int1"),
+ intercepts[0].target_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"),
+ intercepts[1].namespace_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int2"),
+ intercepts[1].target_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/three"),
+ intercepts[2].namespace_url);
+ EXPECT_EQ(GURL("http://www.portme.com:1234/int3"),
+ intercepts[2].target_url);
+
+ // Disallow intercepts ths time.
+ manifest = AppCacheManifest();
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_PER_STANDARD, manifest));
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.explicit_urls.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+ EXPECT_TRUE(manifest.intercept_namespaces.empty());
+ EXPECT_FALSE(manifest.online_whitelist_all);
+}
+
+TEST(AppCacheManifestParserTest, ComboUrls) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://combo.com:42");
+ const std::string kData("CACHE MANIFEST\r"
+ "relative/explicit-1\r"
+ "# some comment\r"
+ "http://combo.com:99/explicit-2#strip\r"
+ "NETWORK:\r"
+ "http://combo.com/whitelist-1\r"
+ "HTTP://www.diff.com/whitelist-2#strip\r"
+ "*\r"
+ "CACHE:\n\r"
+ "http://www.diff.com/explicit-3\r"
+ "FALLBACK:\r"
+ "http://combo.com:42/fallback-1 http://combo.com:42/fallback-1b\r"
+ "relative/fallback-2 relative/fallback-2b\r"
+ "UNKNOWN:\r\n"
+ "http://combo.com/ignoreme\r"
+ "relative/still-ignored\r"
+ "NETWORK:\r\n"
+ "relative/whitelist-3#strip\r"
+ "http://combo.com:99/whitelist-4\r");
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.online_whitelist_all);
+
+ base::hash_set<std::string> urls = manifest.explicit_urls;
+ size_t expected = 3;
+ ASSERT_EQ(expected, urls.size());
+ EXPECT_TRUE(urls.find("http://combo.com:42/relative/explicit-1") !=
+ urls.end());
+ EXPECT_TRUE(urls.find("http://combo.com:99/explicit-2") != urls.end());
+ EXPECT_TRUE(urls.find("http://www.diff.com/explicit-3") != urls.end());
+
+ const AppCacheNamespaceVector& online = manifest.online_whitelist_namespaces;
+ expected = 4;
+ ASSERT_EQ(expected, online.size());
+ EXPECT_EQ(GURL("http://combo.com/whitelist-1"),
+ online[0].namespace_url);
+ EXPECT_EQ(GURL("http://www.diff.com/whitelist-2"),
+ online[1].namespace_url);
+ EXPECT_EQ(GURL("http://combo.com:42/relative/whitelist-3"),
+ online[2].namespace_url);
+ EXPECT_EQ(GURL("http://combo.com:99/whitelist-4"),
+ online[3].namespace_url);
+
+ const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces;
+ expected = 2;
+ ASSERT_EQ(expected, fallbacks.size());
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
+ EXPECT_EQ(GURL("http://combo.com:42/fallback-1"),
+ fallbacks[0].namespace_url);
+ EXPECT_EQ(GURL("http://combo.com:42/fallback-1b"),
+ fallbacks[0].target_url);
+ EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2"),
+ fallbacks[1].namespace_url);
+ EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2b"),
+ fallbacks[1].target_url);
+
+ EXPECT_TRUE(manifest.intercept_namespaces.empty());
+}
+
+TEST(AppCacheManifestParserTest, UnusualUtf8) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://bad.com");
+ const std::string kData("CACHE MANIFEST\r"
+ "\xC0" "invalidutf8\r"
+ "nonbmp" "\xF1\x84\xAB\xBC\r");
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ base::hash_set<std::string> urls = manifest.explicit_urls;
+ EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end());
+ EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end());
+}
+
+TEST(AppCacheManifestParserTest, IgnoreAfterSpace) {
+ AppCacheManifest manifest;
+ const GURL kUrl("http://smorg.borg");
+ const std::string kData(
+ "CACHE MANIFEST\r"
+ "resource.txt this stuff after the white space should be ignored\r");
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+
+ base::hash_set<std::string> urls = manifest.explicit_urls;
+ EXPECT_TRUE(urls.find("http://smorg.borg/resource.txt") != urls.end());
+}
+
+TEST(AppCacheManifestParserTest, DifferentOriginUrlWithSecureScheme) {
+ AppCacheManifest manifest;
+ const GURL kUrl("https://www.foo.com");
+ const std::string kData("CACHE MANIFEST\r"
+ "CACHE: \r"
+ "relative/secureschemesameorigin\r"
+ "https://www.foo.com/secureschemesameorigin\r"
+ "http://www.xyz.com/secureschemedifforigin\r"
+ "https://www.xyz.com/secureschemedifforigin\r");
+
+ EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.fallback_namespaces.empty());
+ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
+
+ base::hash_set<std::string> urls = manifest.explicit_urls;
+ const size_t kExpected = 3;
+ ASSERT_EQ(kExpected, urls.size());
+ EXPECT_TRUE(urls.find("https://www.foo.com/relative/secureschemesameorigin")
+ != urls.end());
+ EXPECT_TRUE(urls.find("https://www.foo.com/secureschemesameorigin") !=
+ urls.end());
+ EXPECT_FALSE(urls.find("http://www.xyz.com/secureschemedifforigin") !=
+ urls.end());
+ EXPECT_TRUE(urls.find("https://www.xyz.com/secureschemedifforigin") !=
+ urls.end());
+}
+
+TEST(AppCacheManifestParserTest, PatternMatching) {
+ const GURL kUrl("http://foo.com/manifest");
+ const std::string kManifestBody(
+ "CACHE MANIFEST\r"
+ "CACHE: \r"
+ "http://foo.com/page.html\r"
+ "CHROMIUM-INTERCEPT:\r"
+ "http://foo.com/intercept_prefix return /prefix\r"
+ "http://foo.com/intercept_pattern return /pattern isPattern\r"
+ "http://foo.com/*/intercept_pattern?query return /pattern isPattern\r"
+ "FALLBACK:\r"
+ "http://foo.com/fallback_prefix /prefix wrongAnnotation\r"
+ "http://foo.com/fallback_pattern* /pattern\tisPattern \r"
+ "NETWORK:\r"
+ "*\r"
+ "isPattern\r" // should not be interpretted as a pattern
+ "http://foo.com/network_pattern* isPattern\r");
+
+
+ AppCacheManifest manifest;
+ EXPECT_TRUE(ParseManifest(kUrl, kManifestBody.c_str(),
+ kManifestBody.length(),
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
+ EXPECT_TRUE(manifest.online_whitelist_all);
+ EXPECT_EQ(1u, manifest.explicit_urls.size());
+ EXPECT_EQ(3u, manifest.intercept_namespaces.size());
+ EXPECT_EQ(2u, manifest.fallback_namespaces.size());
+ EXPECT_EQ(2u, manifest.online_whitelist_namespaces.size());
+ EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE,
+ manifest.intercept_namespaces[0].type);
+ EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, manifest.fallback_namespaces[0].type);
+ EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE,
+ manifest.online_whitelist_namespaces[0].type);
+ EXPECT_FALSE(manifest.intercept_namespaces[0].is_pattern);
+ EXPECT_TRUE(manifest.intercept_namespaces[1].is_pattern);
+ EXPECT_TRUE(manifest.intercept_namespaces[2].is_pattern);
+ EXPECT_FALSE(manifest.fallback_namespaces[0].is_pattern);
+ EXPECT_TRUE(manifest.fallback_namespaces[1].is_pattern);
+ EXPECT_FALSE(manifest.online_whitelist_namespaces[0].is_pattern);
+ EXPECT_TRUE(manifest.online_whitelist_namespaces[1].is_pattern);
+ EXPECT_EQ(
+ GURL("http://foo.com/*/intercept_pattern?query"),
+ manifest.intercept_namespaces[2].namespace_url);
+ EXPECT_EQ(
+ GURL("http://foo.com/pattern"),
+ manifest.intercept_namespaces[2].target_url);
+ EXPECT_EQ(
+ GURL("http://foo.com/fallback_pattern*"),
+ manifest.fallback_namespaces[1].namespace_url);
+ EXPECT_EQ(
+ GURL("http://foo.com/pattern"),
+ manifest.fallback_namespaces[1].target_url);
+ EXPECT_EQ(
+ GURL("http://foo.com/isPattern"),
+ manifest.online_whitelist_namespaces[0].namespace_url);
+ EXPECT_EQ(
+ GURL(),
+ manifest.online_whitelist_namespaces[0].target_url);
+ EXPECT_EQ(
+ GURL("http://foo.com/network_pattern*"),
+ manifest.online_whitelist_namespaces[1].namespace_url);
+ EXPECT_EQ(
+ GURL(),
+ manifest.online_whitelist_namespaces[1].target_url);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_policy.h b/chromium/content/browser/appcache/appcache_policy.h
new file mode 100644
index 00000000000..e7ef6f1b7e5
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_policy.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_POLICY_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_POLICY_H_
+
+class GURL;
+
+namespace content {
+
+class AppCachePolicy {
+ public:
+ AppCachePolicy() {}
+
+ // Called prior to loading a main resource from the appache.
+ // Returns true if allowed. This is expected to return immediately
+ // without any user prompt.
+ virtual bool CanLoadAppCache(const GURL& manifest_url,
+ const GURL& first_party) = 0;
+
+ // Called prior to creating a new appcache. Returns true if allowed.
+ virtual bool CanCreateAppCache(const GURL& manifest_url,
+ const GURL& first_party) = 0;
+
+ protected:
+ ~AppCachePolicy() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_POLICY_H_
diff --git a/chromium/content/browser/appcache/appcache_quota_client.cc b/chromium/content/browser/appcache/appcache_quota_client.cc
new file mode 100644
index 00000000000..cff86402674
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_quota_client.cc
@@ -0,0 +1,251 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_quota_client.h"
+
+#include <algorithm>
+#include <map>
+#include <set>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+
+using storage::QuotaClient;
+
+namespace {
+storage::QuotaStatusCode NetErrorCodeToQuotaStatus(int code) {
+ if (code == net::OK)
+ return storage::kQuotaStatusOk;
+ else if (code == net::ERR_ABORTED)
+ return storage::kQuotaErrorAbort;
+ else
+ return storage::kQuotaStatusUnknown;
+}
+
+void RunFront(content::AppCacheQuotaClient::RequestQueue* queue) {
+ base::Closure request = queue->front();
+ queue->pop_front();
+ request.Run();
+}
+} // namespace
+
+namespace content {
+
+AppCacheQuotaClient::AppCacheQuotaClient(AppCacheServiceImpl* service)
+ : service_(service),
+ appcache_is_ready_(false),
+ quota_manager_is_destroyed_(false) {
+}
+
+AppCacheQuotaClient::~AppCacheQuotaClient() {
+ DCHECK(pending_batch_requests_.empty());
+ DCHECK(pending_serial_requests_.empty());
+ DCHECK(current_delete_request_callback_.is_null());
+}
+
+QuotaClient::ID AppCacheQuotaClient::id() const {
+ return kAppcache;
+}
+
+void AppCacheQuotaClient::OnQuotaManagerDestroyed() {
+ DeletePendingRequests();
+ if (!current_delete_request_callback_.is_null()) {
+ current_delete_request_callback_.Reset();
+ GetServiceDeleteCallback()->Cancel();
+ }
+
+ quota_manager_is_destroyed_ = true;
+ if (!service_)
+ delete this;
+}
+
+void AppCacheQuotaClient::GetOriginUsage(const GURL& origin,
+ storage::StorageType type,
+ const GetUsageCallback& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(!quota_manager_is_destroyed_);
+
+ if (!service_) {
+ callback.Run(0);
+ return;
+ }
+
+ if (!appcache_is_ready_) {
+ pending_batch_requests_.push_back(
+ base::Bind(&AppCacheQuotaClient::GetOriginUsage,
+ base::Unretained(this), origin, type, callback));
+ return;
+ }
+
+ if (type != storage::kStorageTypeTemporary) {
+ callback.Run(0);
+ return;
+ }
+
+ const AppCacheStorage::UsageMap* map = GetUsageMap();
+ AppCacheStorage::UsageMap::const_iterator found = map->find(origin);
+ if (found == map->end()) {
+ callback.Run(0);
+ return;
+ }
+ callback.Run(found->second);
+}
+
+void AppCacheQuotaClient::GetOriginsForType(
+ storage::StorageType type,
+ const GetOriginsCallback& callback) {
+ GetOriginsHelper(type, std::string(), callback);
+}
+
+void AppCacheQuotaClient::GetOriginsForHost(
+ storage::StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) {
+ DCHECK(!callback.is_null());
+ if (host.empty()) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+ GetOriginsHelper(type, host, callback);
+}
+
+void AppCacheQuotaClient::DeleteOriginData(const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) {
+ DCHECK(!quota_manager_is_destroyed_);
+
+ if (!service_) {
+ callback.Run(storage::kQuotaErrorAbort);
+ return;
+ }
+
+ if (!appcache_is_ready_ || !current_delete_request_callback_.is_null()) {
+ pending_serial_requests_.push_back(
+ base::Bind(&AppCacheQuotaClient::DeleteOriginData,
+ base::Unretained(this), origin, type, callback));
+ return;
+ }
+
+ current_delete_request_callback_ = callback;
+ if (type != storage::kStorageTypeTemporary) {
+ DidDeleteAppCachesForOrigin(net::OK);
+ return;
+ }
+
+ service_->DeleteAppCachesForOrigin(
+ origin, GetServiceDeleteCallback()->callback());
+}
+
+bool AppCacheQuotaClient::DoesSupport(storage::StorageType type) const {
+ return type == storage::kStorageTypeTemporary;
+}
+
+void AppCacheQuotaClient::DidDeleteAppCachesForOrigin(int rv) {
+ DCHECK(service_);
+ if (quota_manager_is_destroyed_)
+ return;
+
+ // Finish the request by calling our callers callback.
+ current_delete_request_callback_.Run(NetErrorCodeToQuotaStatus(rv));
+ current_delete_request_callback_.Reset();
+ if (pending_serial_requests_.empty())
+ return;
+
+ // Start the next in the queue.
+ RunFront(&pending_serial_requests_);
+}
+
+void AppCacheQuotaClient::GetOriginsHelper(storage::StorageType type,
+ const std::string& opt_host,
+ const GetOriginsCallback& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(!quota_manager_is_destroyed_);
+
+ if (!service_) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+
+ if (!appcache_is_ready_) {
+ pending_batch_requests_.push_back(
+ base::Bind(&AppCacheQuotaClient::GetOriginsHelper,
+ base::Unretained(this), type, opt_host, callback));
+ return;
+ }
+
+ if (type != storage::kStorageTypeTemporary) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+
+ const AppCacheStorage::UsageMap* map = GetUsageMap();
+ std::set<GURL> origins;
+ for (AppCacheStorage::UsageMap::const_iterator iter = map->begin();
+ iter != map->end(); ++iter) {
+ if (opt_host.empty() || iter->first.host() == opt_host)
+ origins.insert(iter->first);
+ }
+ callback.Run(origins);
+}
+
+void AppCacheQuotaClient::ProcessPendingRequests() {
+ DCHECK(appcache_is_ready_);
+ while (!pending_batch_requests_.empty())
+ RunFront(&pending_batch_requests_);
+
+ if (!pending_serial_requests_.empty())
+ RunFront(&pending_serial_requests_);
+}
+
+void AppCacheQuotaClient::DeletePendingRequests() {
+ pending_batch_requests_.clear();
+ pending_serial_requests_.clear();
+}
+
+const AppCacheStorage::UsageMap* AppCacheQuotaClient::GetUsageMap() {
+ DCHECK(service_);
+ return service_->storage()->usage_map();
+}
+
+net::CancelableCompletionCallback*
+AppCacheQuotaClient::GetServiceDeleteCallback() {
+ // Lazily created due to CancelableCompletionCallback's threading
+ // restrictions, there is no way to detach from the thread created on.
+ if (!service_delete_callback_) {
+ service_delete_callback_.reset(
+ new net::CancelableCompletionCallback(
+ base::Bind(&AppCacheQuotaClient::DidDeleteAppCachesForOrigin,
+ base::Unretained(this))));
+ }
+ return service_delete_callback_.get();
+}
+
+void AppCacheQuotaClient::NotifyAppCacheReady() {
+ // Can reoccur during reinitialization.
+ if (!appcache_is_ready_) {
+ appcache_is_ready_ = true;
+ ProcessPendingRequests();
+ }
+}
+
+void AppCacheQuotaClient::NotifyAppCacheDestroyed() {
+ service_ = NULL;
+ while (!pending_batch_requests_.empty())
+ RunFront(&pending_batch_requests_);
+
+ while (!pending_serial_requests_.empty())
+ RunFront(&pending_serial_requests_);
+
+ if (!current_delete_request_callback_.is_null()) {
+ current_delete_request_callback_.Run(storage::kQuotaErrorAbort);
+ current_delete_request_callback_.Reset();
+ GetServiceDeleteCallback()->Cancel();
+ }
+
+ if (quota_manager_is_destroyed_)
+ delete this;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_quota_client.h b/chromium/content/browser/appcache/appcache_quota_client.h
new file mode 100644
index 00000000000..2af0fbe29bc
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_quota_client.h
@@ -0,0 +1,94 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_QUOTA_CLIENT_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_QUOTA_CLIENT_H_
+
+#include <deque>
+#include <map>
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_task.h"
+#include "storage/common/quota/quota_types.h"
+
+namespace content {
+class AppCacheQuotaClientTest;
+class AppCacheServiceImpl;
+class AppCacheStorageImpl;
+
+// A QuotaClient implementation to integrate the appcache service
+// with the quota management system. The QuotaClient interface is
+// used on the IO thread by the quota manager. This class deletes
+// itself when both the quota manager and the appcache service have
+// been destroyed.
+class AppCacheQuotaClient : public storage::QuotaClient {
+ public:
+ typedef std::deque<base::Closure> RequestQueue;
+
+ ~AppCacheQuotaClient() override;
+
+ // QuotaClient method overrides
+ ID id() const override;
+ void OnQuotaManagerDestroyed() override;
+ void GetOriginUsage(const GURL& origin,
+ storage::StorageType type,
+ const GetUsageCallback& callback) override;
+ void GetOriginsForType(storage::StorageType type,
+ const GetOriginsCallback& callback) override;
+ void GetOriginsForHost(storage::StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) override;
+ void DeleteOriginData(const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) override;
+ bool DoesSupport(storage::StorageType type) const override;
+
+ private:
+ friend class content::AppCacheQuotaClientTest;
+ friend class AppCacheServiceImpl; // for NotifyAppCacheIsDestroyed
+ friend class AppCacheStorageImpl; // for NotifyAppCacheIsReady
+
+ CONTENT_EXPORT
+ explicit AppCacheQuotaClient(AppCacheServiceImpl* service);
+
+ void DidDeleteAppCachesForOrigin(int rv);
+ void GetOriginsHelper(storage::StorageType type,
+ const std::string& opt_host,
+ const GetOriginsCallback& callback);
+ void ProcessPendingRequests();
+ void DeletePendingRequests();
+ const AppCacheStorage::UsageMap* GetUsageMap();
+ net::CancelableCompletionCallback* GetServiceDeleteCallback();
+
+ // For use by appcache internals during initialization and shutdown.
+ CONTENT_EXPORT void NotifyAppCacheReady();
+ CONTENT_EXPORT void NotifyAppCacheDestroyed();
+
+ // Prior to appcache service being ready, we have to queue
+ // up reqeusts and defer acting on them until we're ready.
+ RequestQueue pending_batch_requests_;
+ RequestQueue pending_serial_requests_;
+
+ // And once it's ready, we can only handle one delete request at a time,
+ // so we queue up additional requests while one is in already in progress.
+ DeletionCallback current_delete_request_callback_;
+ scoped_ptr<net::CancelableCompletionCallback> service_delete_callback_;
+
+ AppCacheServiceImpl* service_;
+ bool appcache_is_ready_;
+ bool quota_manager_is_destroyed_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheQuotaClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_QUOTA_CLIENT_H_
diff --git a/chromium/content/browser/appcache/appcache_quota_client_unittest.cc b/chromium/content/browser/appcache/appcache_quota_client_unittest.cc
index 3a32e95dd2f..a453ee1c773 100644
--- a/chromium/content/browser/appcache/appcache_quota_client_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_quota_client_unittest.cc
@@ -8,18 +8,16 @@
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
+#include "content/browser/appcache/appcache_quota_client.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_quota_client.h"
-
-using appcache::AppCacheQuotaClient;
namespace content {
// Declared to shorten the line lengths.
-static const quota::StorageType kTemp = quota::kStorageTypeTemporary;
-static const quota::StorageType kPerm = quota::kStorageTypePersistent;
+static const storage::StorageType kTemp = storage::kStorageTypeTemporary;
+static const storage::StorageType kPerm = storage::kStorageTypePersistent;
// Base class for our test fixtures.
class AppCacheQuotaClientTest : public testing::Test {
@@ -33,85 +31,76 @@ class AppCacheQuotaClientTest : public testing::Test {
kOriginB("http://host:8000"),
kOriginOther("http://other"),
usage_(0),
- delete_status_(quota::kQuotaStatusUnknown),
+ delete_status_(storage::kQuotaStatusUnknown),
num_get_origin_usage_completions_(0),
num_get_origins_completions_(0),
num_delete_origins_completions_(0),
- weak_factory_(this) {
- }
+ weak_factory_(this) {}
- int64 GetOriginUsage(
- quota::QuotaClient* client,
- const GURL& origin,
- quota::StorageType type) {
+ int64 GetOriginUsage(storage::QuotaClient* client,
+ const GURL& origin,
+ storage::StorageType type) {
usage_ = -1;
AsyncGetOriginUsage(client, origin, type);
base::RunLoop().RunUntilIdle();
return usage_;
}
- const std::set<GURL>& GetOriginsForType(
- quota::QuotaClient* client,
- quota::StorageType type) {
+ const std::set<GURL>& GetOriginsForType(storage::QuotaClient* client,
+ storage::StorageType type) {
origins_.clear();
AsyncGetOriginsForType(client, type);
base::RunLoop().RunUntilIdle();
return origins_;
}
- const std::set<GURL>& GetOriginsForHost(
- quota::QuotaClient* client,
- quota::StorageType type,
- const std::string& host) {
+ const std::set<GURL>& GetOriginsForHost(storage::QuotaClient* client,
+ storage::StorageType type,
+ const std::string& host) {
origins_.clear();
AsyncGetOriginsForHost(client, type, host);
base::RunLoop().RunUntilIdle();
return origins_;
}
- quota::QuotaStatusCode DeleteOriginData(
- quota::QuotaClient* client,
- quota::StorageType type,
- const GURL& origin) {
- delete_status_ = quota::kQuotaStatusUnknown;
+ storage::QuotaStatusCode DeleteOriginData(storage::QuotaClient* client,
+ storage::StorageType type,
+ const GURL& origin) {
+ delete_status_ = storage::kQuotaStatusUnknown;
AsyncDeleteOriginData(client, type, origin);
base::RunLoop().RunUntilIdle();
return delete_status_;
}
- void AsyncGetOriginUsage(
- quota::QuotaClient* client,
- const GURL& origin,
- quota::StorageType type) {
+ void AsyncGetOriginUsage(storage::QuotaClient* client,
+ const GURL& origin,
+ storage::StorageType type) {
client->GetOriginUsage(
origin, type,
base::Bind(&AppCacheQuotaClientTest::OnGetOriginUsageComplete,
weak_factory_.GetWeakPtr()));
}
- void AsyncGetOriginsForType(
- quota::QuotaClient* client,
- quota::StorageType type) {
+ void AsyncGetOriginsForType(storage::QuotaClient* client,
+ storage::StorageType type) {
client->GetOriginsForType(
type,
base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete,
weak_factory_.GetWeakPtr()));
}
- void AsyncGetOriginsForHost(
- quota::QuotaClient* client,
- quota::StorageType type,
- const std::string& host) {
+ void AsyncGetOriginsForHost(storage::QuotaClient* client,
+ storage::StorageType type,
+ const std::string& host) {
client->GetOriginsForHost(
type, host,
base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete,
weak_factory_.GetWeakPtr()));
}
- void AsyncDeleteOriginData(
- quota::QuotaClient* client,
- quota::StorageType type,
- const GURL& origin) {
+ void AsyncDeleteOriginData(storage::QuotaClient* client,
+ storage::StorageType type,
+ const GURL& origin) {
client->DeleteOriginData(
origin, type,
base::Bind(&AppCacheQuotaClientTest::OnDeleteOriginDataComplete,
@@ -149,7 +138,7 @@ class AppCacheQuotaClientTest : public testing::Test {
origins_ = origins;
}
- void OnDeleteOriginDataComplete(quota::QuotaStatusCode status) {
+ void OnDeleteOriginDataComplete(storage::QuotaStatusCode status) {
++num_delete_origins_completions_;
delete_status_ = status;
}
@@ -157,7 +146,7 @@ class AppCacheQuotaClientTest : public testing::Test {
base::MessageLoop message_loop_;
int64 usage_;
std::set<GURL> origins_;
- quota::QuotaStatusCode delete_status_;
+ storage::QuotaStatusCode delete_status_;
int num_get_origin_usage_completions_;
int num_get_origins_completions_;
int num_delete_origins_completions_;
@@ -183,8 +172,8 @@ TEST_F(AppCacheQuotaClientTest, EmptyService) {
EXPECT_TRUE(GetOriginsForType(client, kPerm).empty());
EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty());
EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty());
- EXPECT_EQ(quota::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA));
- EXPECT_EQ(quota::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA));
+ EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA));
+ EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA));
Call_NotifyAppCacheDestroyed(client);
Call_OnQuotaManagerDestroyed(client);
@@ -201,9 +190,9 @@ TEST_F(AppCacheQuotaClientTest, NoService) {
EXPECT_TRUE(GetOriginsForType(client, kPerm).empty());
EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty());
EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty());
- EXPECT_EQ(quota::kQuotaErrorAbort,
+ EXPECT_EQ(storage::kQuotaErrorAbort,
DeleteOriginData(client, kTemp, kOriginA));
- EXPECT_EQ(quota::kQuotaErrorAbort,
+ EXPECT_EQ(storage::kQuotaErrorAbort,
DeleteOriginData(client, kPerm, kOriginA));
Call_OnQuotaManagerDestroyed(client);
@@ -278,17 +267,15 @@ TEST_F(AppCacheQuotaClientTest, DeleteOriginData) {
// Perm deletions are short circuited in the Client and
// should not reach the AppCacheServiceImpl.
- EXPECT_EQ(quota::kQuotaStatusOk,
- DeleteOriginData(client, kPerm, kOriginA));
+ EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA));
EXPECT_EQ(0, mock_service_.delete_called_count());
- EXPECT_EQ(quota::kQuotaStatusOk,
- DeleteOriginData(client, kTemp, kOriginA));
+ EXPECT_EQ(storage::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA));
EXPECT_EQ(1, mock_service_.delete_called_count());
mock_service_.set_mock_delete_appcaches_for_origin_result(
net::ERR_ABORTED);
- EXPECT_EQ(quota::kQuotaErrorAbort,
+ EXPECT_EQ(storage::kQuotaErrorAbort,
DeleteOriginData(client, kTemp, kOriginA));
EXPECT_EQ(2, mock_service_.delete_called_count());
@@ -370,7 +357,7 @@ TEST_F(AppCacheQuotaClientTest, DestroyServiceWithPending) {
EXPECT_EQ(3, num_delete_origins_completions_);
EXPECT_EQ(0, usage_);
EXPECT_TRUE(origins_.empty());
- EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_);
+ EXPECT_EQ(storage::kQuotaErrorAbort, delete_status_);
Call_OnQuotaManagerDestroyed(client);
}
@@ -423,13 +410,13 @@ TEST_F(AppCacheQuotaClientTest, DestroyWithDeleteInProgress) {
// Should have been aborted.
EXPECT_EQ(1, num_delete_origins_completions_);
- EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_);
+ EXPECT_EQ(storage::kQuotaErrorAbort, delete_status_);
// A real completion callback from the service should
// be dropped if it comes in after NotifyAppCacheDestroyed.
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, num_delete_origins_completions_);
- EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_);
+ EXPECT_EQ(storage::kQuotaErrorAbort, delete_status_);
Call_OnQuotaManagerDestroyed(client);
}
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
new file mode 100644
index 00000000000..a21337c1111
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -0,0 +1,417 @@
+// Copyright (c) 2011 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 "content/browser/appcache/appcache_request_handler.h"
+
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_policy.h"
+#include "content/browser/appcache/appcache_url_request_job.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_job.h"
+
+namespace content {
+
+AppCacheRequestHandler::AppCacheRequestHandler(AppCacheHost* host,
+ ResourceType resource_type)
+ : host_(host),
+ resource_type_(resource_type),
+ is_waiting_for_cache_selection_(false),
+ found_group_id_(0),
+ found_cache_id_(0),
+ found_network_namespace_(false),
+ cache_entry_not_found_(false),
+ maybe_load_resource_executed_(false) {
+ DCHECK(host_);
+ host_->AddObserver(this);
+}
+
+AppCacheRequestHandler::~AppCacheRequestHandler() {
+ if (host_) {
+ storage()->CancelDelegateCallbacks(this);
+ host_->RemoveObserver(this);
+ }
+}
+
+AppCacheStorage* AppCacheRequestHandler::storage() const {
+ DCHECK(host_);
+ return host_->storage();
+}
+
+AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadResource(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) {
+ maybe_load_resource_executed_ = true;
+ if (!host_ || !IsSchemeAndMethodSupportedForAppCache(request) ||
+ cache_entry_not_found_)
+ return NULL;
+
+ // This method can get called multiple times over the life
+ // of a request. The case we detect here is having scheduled
+ // delivery of a "network response" using a job setup on an
+ // earlier call thru this method. To send the request thru
+ // to the network involves restarting the request altogether,
+ // which will call thru to our interception layer again.
+ // This time thru, we return NULL so the request hits the wire.
+ if (job_.get()) {
+ DCHECK(job_->is_delivering_network_response() ||
+ job_->cache_entry_not_found());
+ if (job_->cache_entry_not_found())
+ cache_entry_not_found_ = true;
+ job_ = NULL;
+ storage()->CancelDelegateCallbacks(this);
+ return NULL;
+ }
+
+ // Clear out our 'found' fields since we're starting a request for a
+ // new resource, any values in those fields are no longer valid.
+ found_entry_ = AppCacheEntry();
+ found_fallback_entry_ = AppCacheEntry();
+ found_cache_id_ = kAppCacheNoCacheId;
+ found_manifest_url_ = GURL();
+ found_network_namespace_ = false;
+
+ if (is_main_resource())
+ MaybeLoadMainResource(request, network_delegate);
+ else
+ MaybeLoadSubResource(request, network_delegate);
+
+ // If its been setup to deliver a network response, we can just delete
+ // it now and return NULL instead to achieve that since it couldn't
+ // have been started yet.
+ if (job_.get() && job_->is_delivering_network_response()) {
+ DCHECK(!job_->has_been_started());
+ job_ = NULL;
+ }
+
+ return job_.get();
+}
+
+AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) {
+ if (!host_ || !IsSchemeAndMethodSupportedForAppCache(request) ||
+ cache_entry_not_found_)
+ return NULL;
+ if (is_main_resource())
+ return NULL;
+ // TODO(vabr) This is a temporary fix (see crbug/141114). We should get rid of
+ // it once a more general solution to crbug/121325 is in place.
+ if (!maybe_load_resource_executed_)
+ return NULL;
+ if (request->url().GetOrigin() == location.GetOrigin())
+ return NULL;
+
+ DCHECK(!job_.get()); // our jobs never generate redirects
+
+ if (found_fallback_entry_.has_response_id()) {
+ // 6.9.6, step 4: If this results in a redirect to another origin,
+ // get the resource of the fallback entry.
+ job_ = new AppCacheURLRequestJob(request, network_delegate,
+ storage(), host_, is_main_resource());
+ DeliverAppCachedResponse(
+ found_fallback_entry_, found_cache_id_, found_group_id_,
+ found_manifest_url_, true, found_namespace_entry_url_);
+ } else if (!found_network_namespace_) {
+ // 6.9.6, step 6: Fail the resource load.
+ job_ = new AppCacheURLRequestJob(request, network_delegate,
+ storage(), host_, is_main_resource());
+ DeliverErrorResponse();
+ } else {
+ // 6.9.6 step 3 and 5: Fetch the resource normally.
+ }
+
+ return job_.get();
+}
+
+AppCacheURLRequestJob* AppCacheRequestHandler::MaybeLoadFallbackForResponse(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) {
+ if (!host_ || !IsSchemeAndMethodSupportedForAppCache(request) ||
+ cache_entry_not_found_)
+ return NULL;
+ if (!found_fallback_entry_.has_response_id())
+ return NULL;
+
+ if (request->status().status() == net::URLRequestStatus::CANCELED) {
+ // 6.9.6, step 4: But not if the user canceled the download.
+ return NULL;
+ }
+
+ // We don't fallback for responses that we delivered.
+ if (job_.get()) {
+ DCHECK(!job_->is_delivering_network_response());
+ return NULL;
+ }
+
+ if (request->status().is_success()) {
+ int code_major = request->GetResponseCode() / 100;
+ if (code_major !=4 && code_major != 5)
+ return NULL;
+
+ // Servers can override the fallback behavior with a response header.
+ const std::string kFallbackOverrideHeader(
+ "x-chromium-appcache-fallback-override");
+ const std::string kFallbackOverrideValue(
+ "disallow-fallback");
+ std::string header_value;
+ request->GetResponseHeaderByName(kFallbackOverrideHeader, &header_value);
+ if (header_value == kFallbackOverrideValue)
+ return NULL;
+ }
+
+ // 6.9.6, step 4: If this results in a 4xx or 5xx status code
+ // or there were network errors, get the resource of the fallback entry.
+ job_ = new AppCacheURLRequestJob(request, network_delegate,
+ storage(), host_, is_main_resource());
+ DeliverAppCachedResponse(
+ found_fallback_entry_, found_cache_id_, found_group_id_,
+ found_manifest_url_, true, found_namespace_entry_url_);
+ return job_.get();
+}
+
+void AppCacheRequestHandler::GetExtraResponseInfo(
+ int64* cache_id, GURL* manifest_url) {
+ if (job_.get() && job_->is_delivering_appcache_response()) {
+ *cache_id = job_->cache_id();
+ *manifest_url = job_->manifest_url();
+ }
+}
+
+void AppCacheRequestHandler::PrepareForCrossSiteTransfer(int old_process_id) {
+ if (!host_)
+ return;
+ AppCacheBackendImpl* backend = host_->service()->GetBackend(old_process_id);
+ host_for_cross_site_transfer_ = backend->TransferHostOut(host_->host_id());
+ DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
+}
+
+void AppCacheRequestHandler::CompleteCrossSiteTransfer(
+ int new_process_id, int new_host_id) {
+ if (!host_for_cross_site_transfer_.get())
+ return;
+ DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
+ AppCacheBackendImpl* backend = host_->service()->GetBackend(new_process_id);
+ backend->TransferHostIn(new_host_id, host_for_cross_site_transfer_.Pass());
+}
+
+void AppCacheRequestHandler::OnDestructionImminent(AppCacheHost* host) {
+ storage()->CancelDelegateCallbacks(this);
+ host_ = NULL; // no need to RemoveObserver, the host is being deleted
+
+ // Since the host is being deleted, we don't have to complete any job
+ // that is current running. It's destined for the bit bucket anyway.
+ if (job_.get()) {
+ job_->Kill();
+ job_ = NULL;
+ }
+}
+
+void AppCacheRequestHandler::DeliverAppCachedResponse(
+ const AppCacheEntry& entry, int64 cache_id, int64 group_id,
+ const GURL& manifest_url, bool is_fallback,
+ const GURL& namespace_entry_url) {
+ DCHECK(host_ && job_.get() && job_->is_waiting());
+ DCHECK(entry.has_response_id());
+
+ if (IsResourceTypeFrame(resource_type_) && !namespace_entry_url.is_empty())
+ host_->NotifyMainResourceIsNamespaceEntry(namespace_entry_url);
+
+ job_->DeliverAppCachedResponse(manifest_url, group_id, cache_id,
+ entry, is_fallback);
+}
+
+void AppCacheRequestHandler::DeliverErrorResponse() {
+ DCHECK(job_.get() && job_->is_waiting());
+ job_->DeliverErrorResponse();
+}
+
+void AppCacheRequestHandler::DeliverNetworkResponse() {
+ DCHECK(job_.get() && job_->is_waiting());
+ job_->DeliverNetworkResponse();
+}
+
+// Main-resource handling ----------------------------------------------
+
+void AppCacheRequestHandler::MaybeLoadMainResource(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) {
+ DCHECK(!job_.get());
+ DCHECK(host_);
+
+ // If a page falls into the scope of a ServiceWorker, any matching AppCaches
+ // should be ignored. This depends on the ServiceWorker handler being invoked
+ // prior to the AppCache handler.
+ if (ServiceWorkerRequestHandler::IsControlledByServiceWorker(request)) {
+ host_->enable_cache_selection(false);
+ return;
+ }
+
+ host_->enable_cache_selection(true);
+
+ const AppCacheHost* spawning_host =
+ (resource_type_ == RESOURCE_TYPE_SHARED_WORKER) ?
+ host_ : host_->GetSpawningHost();
+ GURL preferred_manifest_url = spawning_host ?
+ spawning_host->preferred_manifest_url() : GURL();
+
+ // We may have to wait for our storage query to complete, but
+ // this query can also complete syncrhonously.
+ job_ = new AppCacheURLRequestJob(request, network_delegate,
+ storage(), host_, is_main_resource());
+ storage()->FindResponseForMainRequest(
+ request->url(), preferred_manifest_url, this);
+}
+
+void AppCacheRequestHandler::OnMainResponseFound(
+ const GURL& url, const AppCacheEntry& entry,
+ const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
+ int64 cache_id, int64 group_id, const GURL& manifest_url) {
+ DCHECK(job_.get());
+ DCHECK(host_);
+ DCHECK(is_main_resource());
+ DCHECK(!entry.IsForeign());
+ DCHECK(!fallback_entry.IsForeign());
+ DCHECK(!(entry.has_response_id() && fallback_entry.has_response_id()));
+
+ if (!job_.get())
+ return;
+
+ AppCachePolicy* policy = host_->service()->appcache_policy();
+ bool was_blocked_by_policy = !manifest_url.is_empty() && policy &&
+ !policy->CanLoadAppCache(manifest_url, host_->first_party_url());
+
+ if (was_blocked_by_policy) {
+ if (IsResourceTypeFrame(resource_type_)) {
+ host_->NotifyMainResourceBlocked(manifest_url);
+ } else {
+ DCHECK_EQ(resource_type_, RESOURCE_TYPE_SHARED_WORKER);
+ host_->frontend()->OnContentBlocked(host_->host_id(), manifest_url);
+ }
+ DeliverNetworkResponse();
+ return;
+ }
+
+ if (IsResourceTypeFrame(resource_type_) && cache_id != kAppCacheNoCacheId) {
+ // AppCacheHost loads and holds a reference to the main resource cache
+ // for two reasons, firstly to preload the cache into the working set
+ // in advance of subresource loads happening, secondly to prevent the
+ // AppCache from falling out of the working set on frame navigations.
+ host_->LoadMainResourceCache(cache_id);
+ host_->set_preferred_manifest_url(manifest_url);
+ }
+
+ // 6.11.1 Navigating across documents, steps 10 and 14.
+
+ found_entry_ = entry;
+ found_namespace_entry_url_ = namespace_entry_url;
+ found_fallback_entry_ = fallback_entry;
+ found_cache_id_ = cache_id;
+ found_group_id_ = group_id;
+ found_manifest_url_ = manifest_url;
+ found_network_namespace_ = false; // not applicable to main requests
+
+ if (found_entry_.has_response_id()) {
+ DCHECK(!found_fallback_entry_.has_response_id());
+ DeliverAppCachedResponse(
+ found_entry_, found_cache_id_, found_group_id_, found_manifest_url_,
+ false, found_namespace_entry_url_);
+ } else {
+ DeliverNetworkResponse();
+ }
+}
+
+// Sub-resource handling ----------------------------------------------
+
+void AppCacheRequestHandler::MaybeLoadSubResource(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) {
+ DCHECK(!job_.get());
+
+ if (host_->is_selection_pending()) {
+ // We have to wait until cache selection is complete and the
+ // selected cache is loaded.
+ is_waiting_for_cache_selection_ = true;
+ job_ = new AppCacheURLRequestJob(request, network_delegate,
+ storage(), host_, is_main_resource());
+ return;
+ }
+
+ if (!host_->associated_cache() ||
+ !host_->associated_cache()->is_complete() ||
+ host_->associated_cache()->owning_group()->is_being_deleted()) {
+ return;
+ }
+
+ job_ = new AppCacheURLRequestJob(request, network_delegate,
+ storage(), host_, is_main_resource());
+ ContinueMaybeLoadSubResource();
+}
+
+void AppCacheRequestHandler::ContinueMaybeLoadSubResource() {
+ // 6.9.6 Changes to the networking model
+ // If the resource is not to be fetched using the HTTP GET mechanism or
+ // equivalent ... then fetch the resource normally.
+ DCHECK(job_.get());
+ DCHECK(host_->associated_cache() && host_->associated_cache()->is_complete());
+
+ const GURL& url = job_->request()->url();
+ AppCache* cache = host_->associated_cache();
+ storage()->FindResponseForSubRequest(
+ host_->associated_cache(), url,
+ &found_entry_, &found_fallback_entry_, &found_network_namespace_);
+
+ if (found_entry_.has_response_id()) {
+ // Step 2: If there's an entry, get it instead.
+ DCHECK(!found_network_namespace_ &&
+ !found_fallback_entry_.has_response_id());
+ found_cache_id_ = cache->cache_id();
+ found_group_id_ = cache->owning_group()->group_id();
+ found_manifest_url_ = cache->owning_group()->manifest_url();
+ DeliverAppCachedResponse(
+ found_entry_, found_cache_id_, found_group_id_, found_manifest_url_,
+ false, GURL());
+ return;
+ }
+
+ if (found_fallback_entry_.has_response_id()) {
+ // Step 4: Fetch the resource normally, if this results
+ // in certain conditions, then use the fallback.
+ DCHECK(!found_network_namespace_ &&
+ !found_entry_.has_response_id());
+ found_cache_id_ = cache->cache_id();
+ found_manifest_url_ = cache->owning_group()->manifest_url();
+ DeliverNetworkResponse();
+ return;
+ }
+
+ if (found_network_namespace_) {
+ // Step 3 and 5: Fetch the resource normally.
+ DCHECK(!found_entry_.has_response_id() &&
+ !found_fallback_entry_.has_response_id());
+ DeliverNetworkResponse();
+ return;
+ }
+
+ // Step 6: Fail the resource load.
+ DeliverErrorResponse();
+}
+
+void AppCacheRequestHandler::OnCacheSelectionComplete(AppCacheHost* host) {
+ DCHECK(host == host_);
+ if (is_main_resource())
+ return;
+ if (!is_waiting_for_cache_selection_)
+ return;
+
+ is_waiting_for_cache_selection_ = false;
+
+ if (!host_->associated_cache() ||
+ !host_->associated_cache()->is_complete()) {
+ DeliverNetworkResponse();
+ return;
+ }
+
+ ContinueMaybeLoadSubResource();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
new file mode 100644
index 00000000000..cf0297b35dd
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -0,0 +1,151 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_REQUEST_HANDLER_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_REQUEST_HANDLER_H_
+
+#include "base/compiler_specific.h"
+#include "base/supports_user_data.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/common/content_export.h"
+#include "content/public/common/resource_type.h"
+
+namespace net {
+class NetworkDelegate;
+class URLRequest;
+class URLRequestJob;
+} // namespace net
+
+namespace content {
+class AppCacheRequestHandlerTest;
+class AppCacheURLRequestJob;
+
+// An instance is created for each net::URLRequest. The instance survives all
+// http transactions involved in the processing of its net::URLRequest, and is
+// given the opportunity to hijack the request along the way. Callers
+// should use AppCacheHost::CreateRequestHandler to manufacture instances
+// that can retrieve resources for a particular host.
+class CONTENT_EXPORT AppCacheRequestHandler
+ : public base::SupportsUserData::Data,
+ public AppCacheHost::Observer,
+ public AppCacheStorage::Delegate {
+ public:
+ ~AppCacheRequestHandler() override;
+
+ // These are called on each request intercept opportunity.
+ AppCacheURLRequestJob* MaybeLoadResource(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate);
+ AppCacheURLRequestJob* MaybeLoadFallbackForRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location);
+ AppCacheURLRequestJob* MaybeLoadFallbackForResponse(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate);
+
+ void GetExtraResponseInfo(int64* cache_id, GURL* manifest_url);
+
+ // Methods to support cross site navigations.
+ void PrepareForCrossSiteTransfer(int old_process_id);
+ void CompleteCrossSiteTransfer(int new_process_id, int new_host_id);
+
+ static bool IsMainResourceType(ResourceType type) {
+ return IsResourceTypeFrame(type) ||
+ type == RESOURCE_TYPE_SHARED_WORKER;
+ }
+
+ private:
+ friend class AppCacheHost;
+
+ // Callers should use AppCacheHost::CreateRequestHandler.
+ AppCacheRequestHandler(AppCacheHost* host, ResourceType resource_type);
+
+ // AppCacheHost::Observer override
+ void OnDestructionImminent(AppCacheHost* host) override;
+
+ // Helpers to instruct a waiting job with what response to
+ // deliver for the request we're handling.
+ void DeliverAppCachedResponse(const AppCacheEntry& entry, int64 cache_id,
+ int64 group_id, const GURL& manifest_url,
+ bool is_fallback,
+ const GURL& namespace_entry_url);
+ void DeliverNetworkResponse();
+ void DeliverErrorResponse();
+
+ // Helper to retrieve a pointer to the storage object.
+ AppCacheStorage* storage() const;
+
+ bool is_main_resource() const {
+ return IsMainResourceType(resource_type_);
+ }
+
+ // Main-resource loading -------------------------------------
+ // Frame and SharedWorker main resources are handled here.
+
+ void MaybeLoadMainResource(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate);
+
+ // AppCacheStorage::Delegate methods
+ void OnMainResponseFound(const GURL& url,
+ const AppCacheEntry& entry,
+ const GURL& fallback_url,
+ const AppCacheEntry& fallback_entry,
+ int64 cache_id,
+ int64 group_id,
+ const GURL& mainfest_url) override;
+
+ // Sub-resource loading -------------------------------------
+ // Dedicated worker and all manner of sub-resources are handled here.
+
+ void MaybeLoadSubResource(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate);
+ void ContinueMaybeLoadSubResource();
+
+ // AppCacheHost::Observer override
+ void OnCacheSelectionComplete(AppCacheHost* host) override;
+
+ // Data members -----------------------------------------------
+
+ // What host we're servicing a request for.
+ AppCacheHost* host_;
+
+ // Frame vs subresource vs sharedworker loads are somewhat different.
+ ResourceType resource_type_;
+
+ // Subresource requests wait until after cache selection completes.
+ bool is_waiting_for_cache_selection_;
+
+ // Info about the type of response we found for delivery.
+ // These are relevant for both main and subresource requests.
+ int64 found_group_id_;
+ int64 found_cache_id_;
+ AppCacheEntry found_entry_;
+ AppCacheEntry found_fallback_entry_;
+ GURL found_namespace_entry_url_;
+ GURL found_manifest_url_;
+ bool found_network_namespace_;
+
+ // True if a cache entry this handler attempted to return was
+ // not found in the disk cache. Once set, the handler will take
+ // no action on all subsequent intercept opportunities, so the
+ // request and any redirects will be handled by the network library.
+ bool cache_entry_not_found_;
+
+ // True if this->MaybeLoadResource(...) has been called in the past.
+ bool maybe_load_resource_executed_;
+
+ // The job we use to deliver a response.
+ scoped_refptr<AppCacheURLRequestJob> job_;
+
+ // During a cross site navigation, we transfer ownership the AppcacheHost
+ // from the old processes structures over to the new structures.
+ scoped_ptr<AppCacheHost> host_for_cross_site_transfer_;
+
+ friend class content::AppCacheRequestHandlerTest;
+ DISALLOW_COPY_AND_ASSIGN(AppCacheRequestHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_REQUEST_HANDLER_H_
diff --git a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
index df6fb330d24..9543f7e65d7 100644
--- a/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler_unittest.cc
@@ -12,6 +12,10 @@
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_request_handler.h"
+#include "content/browser/appcache/appcache_url_request_job.h"
#include "content/browser/appcache/mock_appcache_policy.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/base/net_errors.h"
@@ -22,21 +26,6 @@
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_backend_impl.h"
-#include "webkit/browser/appcache/appcache_request_handler.h"
-#include "webkit/browser/appcache/appcache_url_request_job.h"
-
-using appcache::AppCache;
-using appcache::AppCacheBackendImpl;
-using appcache::AppCacheEntry;
-using appcache::AppCacheFrontend;
-using appcache::AppCacheGroup;
-using appcache::AppCacheHost;
-using appcache::AppCacheInfo;
-using appcache::AppCacheRequestHandler;
-using appcache::AppCacheURLRequestJob;
-using appcache::kAppCacheNoCacheId;
namespace content {
@@ -46,32 +35,27 @@ class AppCacheRequestHandlerTest : public testing::Test {
public:
class MockFrontend : public AppCacheFrontend {
public:
- virtual void OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) OVERRIDE {}
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override {}
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) OVERRIDE {}
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override {}
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) OVERRIDE {}
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override {}
- virtual void OnErrorEventRaised(
- const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details) OVERRIDE {}
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override {}
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total,
- int num_complete) OVERRIDE {
- }
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override {}
- virtual void OnLogMessage(int host_id,
- appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE {
- }
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override {}
- virtual void OnContentBlocked(int host_id,
- const GURL& manifest_url) OVERRIDE {}
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override {}
};
// Helper callback to run a test on our io_thread. The io_thread is spun up
@@ -86,10 +70,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
// exercise fallback code paths.
class MockURLRequestDelegate : public net::URLRequest::Delegate {
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {}
- virtual void OnReadCompleted(net::URLRequest* request,
- int bytes_read) OVERRIDE {
- }
+ void OnResponseStarted(net::URLRequest* request) override {}
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override {}
};
class MockURLRequestJob : public net::URLRequestJob {
@@ -108,22 +90,17 @@ class AppCacheRequestHandlerTest : public testing::Test {
has_response_info_(true),
response_info_(info) {}
- protected:
- virtual ~MockURLRequestJob() {}
- virtual void Start() OVERRIDE {
- NotifyHeadersComplete();
- }
- virtual int GetResponseCode() const OVERRIDE {
- return response_code_;
- }
- virtual void GetResponseInfo(
- net::HttpResponseInfo* info) OVERRIDE {
+ protected:
+ ~MockURLRequestJob() override {}
+ void Start() override { NotifyHeadersComplete(); }
+ int GetResponseCode() const override { return response_code_; }
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
if (!has_response_info_)
return;
*info = response_info_;
}
- private:
+ private:
int response_code_;
bool has_response_info_;
net::HttpResponseInfo response_info_;
@@ -134,18 +111,16 @@ class AppCacheRequestHandlerTest : public testing::Test {
MockURLRequestJobFactory() : job_(NULL) {
}
- virtual ~MockURLRequestJobFactory() {
- DCHECK(!job_);
- }
+ ~MockURLRequestJobFactory() override { DCHECK(!job_); }
void SetJob(net::URLRequestJob* job) {
job_ = job;
}
- virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
if (job_) {
net::URLRequestJob* temp = job_;
job_ = NULL;
@@ -159,15 +134,28 @@ class AppCacheRequestHandlerTest : public testing::Test {
}
}
- virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return nullptr;
+ }
+
+ bool IsHandledProtocol(const std::string& scheme) const override {
return scheme == "http";
};
- virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+ bool IsHandledURL(const GURL& url) const override {
return url.SchemeIs("http");
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
@@ -175,15 +163,6 @@ class AppCacheRequestHandlerTest : public testing::Test {
mutable net::URLRequestJob* job_;
};
- class MockURLRequest : public net::URLRequest {
- public:
- MockURLRequest(const GURL& url, net::URLRequestContext* context)
- : net::URLRequest(url, net::DEFAULT_PRIORITY, NULL, context) {}
-
-
- MockURLRequestDelegate delegate_;
- };
-
static void SetUpTestCase() {
io_thread_.reset(new base::Thread("AppCacheRequestHandlerTest Thread"));
base::Thread::Options options(base::MessageLoop::TYPE_IO, 0);
@@ -274,9 +253,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Miss,
base::Unretained(this)));
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
@@ -321,9 +301,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Hit,
base::Unretained(this)));
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_storage()->SimulateFindMainResource(
@@ -369,9 +350,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Fallback,
base::Unretained(this)));
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_storage()->SimulateFindMainResource(
@@ -406,7 +388,6 @@ class AppCacheRequestHandlerTest : public testing::Test {
new MockURLRequestJob(
request_.get(),
request_->context()->network_delegate(), info));
- request_->set_delegate(&request_->delegate_);
request_->Start();
}
@@ -450,10 +431,11 @@ class AppCacheRequestHandlerTest : public testing::Test {
&AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride,
base::Unretained(this)));
- request_.reset(new MockURLRequest(GURL("http://blah/fallback-override"),
- &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/fallback-override"), net::DEFAULT_PRIORITY,
+ &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_storage()->SimulateFindMainResource(
@@ -503,9 +485,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
// SubResource_Miss_WithNoCacheSelected ----------------------------------
void SubResource_Miss_WithNoCacheSelected() {
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
// We avoid creating handler when possible, sub-resource requests are not
// subject to retrieval from an appcache when there's no associated cache.
@@ -521,9 +504,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
// in a network or fallback namespace, should result in a failed request.
host_->AssociateCompleteCache(MakeNewCache());
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
@@ -552,9 +536,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
host_->pending_selected_cache_id_ = cache->cache_id();
host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
request_->context()->network_delegate());
@@ -586,9 +571,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
request_->context()->network_delegate());
@@ -618,9 +604,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
request_->context()->network_delegate());
@@ -651,9 +638,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
request_->context()->network_delegate());
@@ -685,9 +673,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(), AppCacheEntry(), true);
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
request_->context()->network_delegate());
@@ -714,9 +703,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
mock_storage()->SimulateFindSubResource(
AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
backend_impl_->UnregisterHost(1);
@@ -740,9 +730,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
// Precondition, the host is waiting on cache selection.
host_->pending_selected_cache_id_ = 1;
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
@@ -772,9 +763,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
// Precondition, the host is waiting on cache selection.
host_->pending_selected_cache_id_ = 1;
- request_.reset(new MockURLRequest(GURL("ftp://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("ftp://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::SUB_RESOURCE));
+ RESOURCE_TYPE_SUB_RESOURCE));
EXPECT_TRUE(handler_.get()); // we could redirect to http (conceivably)
EXPECT_FALSE(handler_->MaybeLoadResource(
@@ -792,9 +784,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
// CanceledRequest -----------------------------
void CanceledRequest() {
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
job_ = handler_->MaybeLoadResource(request_.get(),
@@ -803,7 +796,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_TRUE(job_->is_waiting());
EXPECT_FALSE(job_->has_been_started());
- job_factory_->SetJob(job_);
+ job_factory_->SetJob(job_.get());
request_->Start();
EXPECT_TRUE(job_->has_been_started());
@@ -820,15 +813,16 @@ class AppCacheRequestHandlerTest : public testing::Test {
void WorkerRequest() {
EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
- ResourceType::SUB_FRAME));
+ RESOURCE_TYPE_SUB_FRAME));
EXPECT_TRUE(AppCacheRequestHandler::IsMainResourceType(
- ResourceType::SHARED_WORKER));
+ RESOURCE_TYPE_SHARED_WORKER));
EXPECT_FALSE(AppCacheRequestHandler::IsMainResourceType(
- ResourceType::WORKER));
+ RESOURCE_TYPE_WORKER));
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
const int kParentHostId = host_->host_id();
const int kWorkerHostId = 2;
@@ -839,7 +833,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
AppCacheHost* worker_host = backend_impl_->GetHost(kWorkerHostId);
worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId);
handler_.reset(worker_host->CreateRequestHandler(
- request_.get(), ResourceType::SHARED_WORKER));
+ request_.get(), RESOURCE_TYPE_SHARED_WORKER));
EXPECT_TRUE(handler_.get());
// Verify that the handler is associated with the parent host.
EXPECT_EQ(host_, handler_->host_);
@@ -852,7 +846,7 @@ class AppCacheRequestHandlerTest : public testing::Test {
EXPECT_EQ(NULL, backend_impl_->GetHost(kNonExsitingHostId));
worker_host->SelectCacheForWorker(kNonExsitingHostId, kMockProcessId);
handler_.reset(worker_host->CreateRequestHandler(
- request_.get(), ResourceType::SHARED_WORKER));
+ request_.get(), RESOURCE_TYPE_SHARED_WORKER));
EXPECT_FALSE(handler_.get());
TestFinished();
@@ -865,9 +859,10 @@ class AppCacheRequestHandlerTest : public testing::Test {
base::Bind(&AppCacheRequestHandlerTest::Verify_MainResource_Blocked,
base::Unretained(this)));
- request_.reset(new MockURLRequest(GURL("http://blah/"), &empty_context_));
+ request_ = empty_context_.CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, &delegate_, NULL);
handler_.reset(host_->CreateRequestHandler(request_.get(),
- ResourceType::MAIN_FRAME));
+ RESOURCE_TYPE_MAIN_FRAME));
EXPECT_TRUE(handler_.get());
mock_policy_->can_load_return_value_ = false;
@@ -927,7 +922,8 @@ class AppCacheRequestHandlerTest : public testing::Test {
AppCacheHost* host_;
net::URLRequestContext empty_context_;
scoped_ptr<MockURLRequestJobFactory> job_factory_;
- scoped_ptr<MockURLRequest> request_;
+ MockURLRequestDelegate delegate_;
+ scoped_ptr<net::URLRequest> request_;
scoped_ptr<AppCacheRequestHandler> handler_;
scoped_refptr<AppCacheURLRequestJob> job_;
diff --git a/chromium/content/browser/appcache/appcache_response.cc b/chromium/content/browser/appcache/appcache_response.cc
new file mode 100644
index 00000000000..0d8b5b4039d
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_response.cc
@@ -0,0 +1,423 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_response.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/pickle.h"
+#include "base/strings/string_util.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+
+namespace content {
+
+namespace {
+
+// Disk cache entry data indices.
+enum {
+ kResponseInfoIndex,
+ kResponseContentIndex
+};
+
+// An IOBuffer that wraps a pickle's data. Ownership of the
+// pickle is transfered to the WrappedPickleIOBuffer object.
+class WrappedPickleIOBuffer : public net::WrappedIOBuffer {
+ public:
+ explicit WrappedPickleIOBuffer(const Pickle* pickle) :
+ net::WrappedIOBuffer(reinterpret_cast<const char*>(pickle->data())),
+ pickle_(pickle) {
+ DCHECK(pickle->data());
+ }
+
+ private:
+ ~WrappedPickleIOBuffer() override {}
+
+ scoped_ptr<const Pickle> pickle_;
+};
+
+} // anon namespace
+
+
+// AppCacheResponseInfo ----------------------------------------------
+
+AppCacheResponseInfo::AppCacheResponseInfo(
+ AppCacheStorage* storage, const GURL& manifest_url,
+ int64 response_id, net::HttpResponseInfo* http_info,
+ int64 response_data_size)
+ : manifest_url_(manifest_url), response_id_(response_id),
+ http_response_info_(http_info), response_data_size_(response_data_size),
+ storage_(storage) {
+ DCHECK(http_info);
+ DCHECK(response_id != kAppCacheNoResponseId);
+ storage_->working_set()->AddResponseInfo(this);
+}
+
+AppCacheResponseInfo::~AppCacheResponseInfo() {
+ storage_->working_set()->RemoveResponseInfo(this);
+}
+
+// HttpResponseInfoIOBuffer ------------------------------------------
+
+HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer()
+ : response_data_size(kUnkownResponseDataSize) {}
+
+HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer(net::HttpResponseInfo* info)
+ : http_info(info), response_data_size(kUnkownResponseDataSize) {}
+
+HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() {}
+
+// AppCacheResponseIO ----------------------------------------------
+
+AppCacheResponseIO::AppCacheResponseIO(
+ int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache)
+ : response_id_(response_id),
+ group_id_(group_id),
+ disk_cache_(disk_cache),
+ entry_(NULL),
+ buffer_len_(0),
+ weak_factory_(this) {
+}
+
+AppCacheResponseIO::~AppCacheResponseIO() {
+ if (entry_)
+ entry_->Close();
+}
+
+void AppCacheResponseIO::ScheduleIOCompletionCallback(int result) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&AppCacheResponseIO::OnIOComplete,
+ weak_factory_.GetWeakPtr(), result));
+}
+
+void AppCacheResponseIO::InvokeUserCompletionCallback(int result) {
+ // Clear the user callback and buffers prior to invoking the callback
+ // so the caller can schedule additional operations in the callback.
+ buffer_ = NULL;
+ info_buffer_ = NULL;
+ net::CompletionCallback cb = callback_;
+ callback_.Reset();
+ cb.Run(result);
+}
+
+void AppCacheResponseIO::ReadRaw(int index, int offset,
+ net::IOBuffer* buf, int buf_len) {
+ DCHECK(entry_);
+ int rv = entry_->Read(
+ index, offset, buf, buf_len,
+ base::Bind(&AppCacheResponseIO::OnRawIOComplete,
+ weak_factory_.GetWeakPtr()));
+ if (rv != net::ERR_IO_PENDING)
+ ScheduleIOCompletionCallback(rv);
+}
+
+void AppCacheResponseIO::WriteRaw(int index, int offset,
+ net::IOBuffer* buf, int buf_len) {
+ DCHECK(entry_);
+ int rv = entry_->Write(
+ index, offset, buf, buf_len,
+ base::Bind(&AppCacheResponseIO::OnRawIOComplete,
+ weak_factory_.GetWeakPtr()));
+ if (rv != net::ERR_IO_PENDING)
+ ScheduleIOCompletionCallback(rv);
+}
+
+void AppCacheResponseIO::OnRawIOComplete(int result) {
+ DCHECK_NE(net::ERR_IO_PENDING, result);
+ OnIOComplete(result);
+}
+
+
+// AppCacheResponseReader ----------------------------------------------
+
+AppCacheResponseReader::AppCacheResponseReader(
+ int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache)
+ : AppCacheResponseIO(response_id, group_id, disk_cache),
+ range_offset_(0),
+ range_length_(kint32max),
+ read_position_(0),
+ weak_factory_(this) {
+}
+
+AppCacheResponseReader::~AppCacheResponseReader() {
+}
+
+void AppCacheResponseReader::ReadInfo(HttpResponseInfoIOBuffer* info_buf,
+ const net::CompletionCallback& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(!IsReadPending());
+ DCHECK(info_buf);
+ DCHECK(!info_buf->http_info.get());
+ DCHECK(!buffer_.get());
+ DCHECK(!info_buffer_.get());
+
+ info_buffer_ = info_buf;
+ callback_ = callback; // cleared on completion
+ OpenEntryIfNeededAndContinue();
+}
+
+void AppCacheResponseReader::ContinueReadInfo() {
+ if (!entry_) {
+ ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
+ return;
+ }
+
+ int size = entry_->GetSize(kResponseInfoIndex);
+ if (size <= 0) {
+ ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
+ return;
+ }
+
+ buffer_ = new net::IOBuffer(size);
+ ReadRaw(kResponseInfoIndex, 0, buffer_.get(), size);
+}
+
+void AppCacheResponseReader::ReadData(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(!IsReadPending());
+ DCHECK(buf);
+ DCHECK(buf_len >= 0);
+ DCHECK(!buffer_.get());
+ DCHECK(!info_buffer_.get());
+
+ buffer_ = buf;
+ buffer_len_ = buf_len;
+ callback_ = callback; // cleared on completion
+ OpenEntryIfNeededAndContinue();
+}
+
+void AppCacheResponseReader::ContinueReadData() {
+ if (!entry_) {
+ ScheduleIOCompletionCallback(net::ERR_CACHE_MISS);
+ return;
+ }
+
+ if (read_position_ + buffer_len_ > range_length_) {
+ // TODO(michaeln): What about integer overflows?
+ DCHECK(range_length_ >= read_position_);
+ buffer_len_ = range_length_ - read_position_;
+ }
+ ReadRaw(kResponseContentIndex,
+ range_offset_ + read_position_,
+ buffer_.get(),
+ buffer_len_);
+}
+
+void AppCacheResponseReader::SetReadRange(int offset, int length) {
+ DCHECK(!IsReadPending() && !read_position_);
+ range_offset_ = offset;
+ range_length_ = length;
+}
+
+void AppCacheResponseReader::OnIOComplete(int result) {
+ if (result >= 0) {
+ if (info_buffer_.get()) {
+ // Deserialize the http info structure, ensuring we got headers.
+ Pickle pickle(buffer_->data(), result);
+ scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
+ bool response_truncated = false;
+ if (!info->InitFromPickle(pickle, &response_truncated) ||
+ !info->headers.get()) {
+ InvokeUserCompletionCallback(net::ERR_FAILED);
+ return;
+ }
+ DCHECK(!response_truncated);
+ info_buffer_->http_info.reset(info.release());
+
+ // Also return the size of the response body
+ DCHECK(entry_);
+ info_buffer_->response_data_size =
+ entry_->GetSize(kResponseContentIndex);
+ } else {
+ read_position_ += result;
+ }
+ }
+ InvokeUserCompletionCallback(result);
+}
+
+void AppCacheResponseReader::OpenEntryIfNeededAndContinue() {
+ int rv;
+ AppCacheDiskCacheInterface::Entry** entry_ptr = NULL;
+ if (entry_) {
+ rv = net::OK;
+ } else if (!disk_cache_) {
+ rv = net::ERR_FAILED;
+ } else {
+ entry_ptr = new AppCacheDiskCacheInterface::Entry*;
+ open_callback_ =
+ base::Bind(&AppCacheResponseReader::OnOpenEntryComplete,
+ weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
+ rv = disk_cache_->OpenEntry(response_id_, entry_ptr, open_callback_);
+ }
+
+ if (rv != net::ERR_IO_PENDING)
+ OnOpenEntryComplete(entry_ptr, rv);
+}
+
+void AppCacheResponseReader::OnOpenEntryComplete(
+ AppCacheDiskCacheInterface::Entry** entry, int rv) {
+ DCHECK(info_buffer_.get() || buffer_.get());
+
+ if (!open_callback_.is_null()) {
+ if (rv == net::OK) {
+ DCHECK(entry);
+ entry_ = *entry;
+ }
+ open_callback_.Reset();
+ }
+
+ if (info_buffer_.get())
+ ContinueReadInfo();
+ else
+ ContinueReadData();
+}
+
+// AppCacheResponseWriter ----------------------------------------------
+
+AppCacheResponseWriter::AppCacheResponseWriter(
+ int64 response_id, int64 group_id, AppCacheDiskCacheInterface* disk_cache)
+ : AppCacheResponseIO(response_id, group_id, disk_cache),
+ info_size_(0),
+ write_position_(0),
+ write_amount_(0),
+ creation_phase_(INITIAL_ATTEMPT),
+ weak_factory_(this) {
+}
+
+AppCacheResponseWriter::~AppCacheResponseWriter() {
+}
+
+void AppCacheResponseWriter::WriteInfo(
+ HttpResponseInfoIOBuffer* info_buf,
+ const net::CompletionCallback& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(!IsWritePending());
+ DCHECK(info_buf);
+ DCHECK(info_buf->http_info.get());
+ DCHECK(!buffer_.get());
+ DCHECK(!info_buffer_.get());
+ DCHECK(info_buf->http_info->headers.get());
+
+ info_buffer_ = info_buf;
+ callback_ = callback; // cleared on completion
+ CreateEntryIfNeededAndContinue();
+}
+
+void AppCacheResponseWriter::ContinueWriteInfo() {
+ if (!entry_) {
+ ScheduleIOCompletionCallback(net::ERR_FAILED);
+ return;
+ }
+
+ const bool kSkipTransientHeaders = true;
+ const bool kTruncated = false;
+ Pickle* pickle = new Pickle;
+ info_buffer_->http_info->Persist(pickle, kSkipTransientHeaders, kTruncated);
+ write_amount_ = static_cast<int>(pickle->size());
+ buffer_ = new WrappedPickleIOBuffer(pickle); // takes ownership of pickle
+ WriteRaw(kResponseInfoIndex, 0, buffer_.get(), write_amount_);
+}
+
+void AppCacheResponseWriter::WriteData(
+ net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(!IsWritePending());
+ DCHECK(buf);
+ DCHECK(buf_len >= 0);
+ DCHECK(!buffer_.get());
+ DCHECK(!info_buffer_.get());
+
+ buffer_ = buf;
+ write_amount_ = buf_len;
+ callback_ = callback; // cleared on completion
+ CreateEntryIfNeededAndContinue();
+}
+
+void AppCacheResponseWriter::ContinueWriteData() {
+ if (!entry_) {
+ ScheduleIOCompletionCallback(net::ERR_FAILED);
+ return;
+ }
+ WriteRaw(
+ kResponseContentIndex, write_position_, buffer_.get(), write_amount_);
+}
+
+void AppCacheResponseWriter::OnIOComplete(int result) {
+ if (result >= 0) {
+ DCHECK(write_amount_ == result);
+ if (!info_buffer_.get())
+ write_position_ += result;
+ else
+ info_size_ = result;
+ }
+ InvokeUserCompletionCallback(result);
+}
+
+void AppCacheResponseWriter::CreateEntryIfNeededAndContinue() {
+ int rv;
+ AppCacheDiskCacheInterface::Entry** entry_ptr = NULL;
+ if (entry_) {
+ creation_phase_ = NO_ATTEMPT;
+ rv = net::OK;
+ } else if (!disk_cache_) {
+ creation_phase_ = NO_ATTEMPT;
+ rv = net::ERR_FAILED;
+ } else {
+ creation_phase_ = INITIAL_ATTEMPT;
+ entry_ptr = new AppCacheDiskCacheInterface::Entry*;
+ create_callback_ =
+ base::Bind(&AppCacheResponseWriter::OnCreateEntryComplete,
+ weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
+ rv = disk_cache_->CreateEntry(response_id_, entry_ptr, create_callback_);
+ }
+ if (rv != net::ERR_IO_PENDING)
+ OnCreateEntryComplete(entry_ptr, rv);
+}
+
+void AppCacheResponseWriter::OnCreateEntryComplete(
+ AppCacheDiskCacheInterface::Entry** entry, int rv) {
+ DCHECK(info_buffer_.get() || buffer_.get());
+
+ if (creation_phase_ == INITIAL_ATTEMPT) {
+ if (rv != net::OK) {
+ // We may try to overwrite existing entries.
+ creation_phase_ = DOOM_EXISTING;
+ rv = disk_cache_->DoomEntry(response_id_, create_callback_);
+ if (rv != net::ERR_IO_PENDING)
+ OnCreateEntryComplete(NULL, rv);
+ return;
+ }
+ } else if (creation_phase_ == DOOM_EXISTING) {
+ creation_phase_ = SECOND_ATTEMPT;
+ AppCacheDiskCacheInterface::Entry** entry_ptr =
+ new AppCacheDiskCacheInterface::Entry*;
+ create_callback_ =
+ base::Bind(&AppCacheResponseWriter::OnCreateEntryComplete,
+ weak_factory_.GetWeakPtr(), base::Owned(entry_ptr));
+ rv = disk_cache_->CreateEntry(response_id_, entry_ptr, create_callback_);
+ if (rv != net::ERR_IO_PENDING)
+ OnCreateEntryComplete(entry_ptr, rv);
+ return;
+ }
+
+ if (!create_callback_.is_null()) {
+ if (rv == net::OK)
+ entry_ = *entry;
+
+ create_callback_.Reset();
+ }
+
+ if (info_buffer_.get())
+ ContinueWriteInfo();
+ else
+ ContinueWriteData();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_response.h b/chromium/content/browser/appcache/appcache_response.h
new file mode 100644
index 00000000000..4b7a32c6767
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_response.h
@@ -0,0 +1,262 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_RESPONSE_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_RESPONSE_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
+#include "net/http/http_response_info.h"
+#include "url/gurl.h"
+
+namespace net {
+class IOBuffer;
+}
+
+namespace content {
+class AppCacheStorage;
+class MockAppCacheStorage;
+
+static const int kUnkownResponseDataSize = -1;
+
+// Response info for a particular response id. Instances are tracked in
+// the working set.
+class CONTENT_EXPORT AppCacheResponseInfo
+ : public base::RefCounted<AppCacheResponseInfo> {
+ public:
+ // AppCacheResponseInfo takes ownership of the http_info.
+ AppCacheResponseInfo(AppCacheStorage* storage, const GURL& manifest_url,
+ int64 response_id, net::HttpResponseInfo* http_info,
+ int64 response_data_size);
+
+ const GURL& manifest_url() const { return manifest_url_; }
+ int64 response_id() const { return response_id_; }
+ const net::HttpResponseInfo* http_response_info() const {
+ return http_response_info_.get();
+ }
+ int64 response_data_size() const { return response_data_size_; }
+
+ private:
+ friend class base::RefCounted<AppCacheResponseInfo>;
+ virtual ~AppCacheResponseInfo();
+
+ const GURL manifest_url_;
+ const int64 response_id_;
+ const scoped_ptr<net::HttpResponseInfo> http_response_info_;
+ const int64 response_data_size_;
+ AppCacheStorage* storage_;
+};
+
+// A refcounted wrapper for HttpResponseInfo so we can apply the
+// refcounting semantics used with IOBuffer with these structures too.
+struct CONTENT_EXPORT HttpResponseInfoIOBuffer
+ : public base::RefCountedThreadSafe<HttpResponseInfoIOBuffer> {
+ scoped_ptr<net::HttpResponseInfo> http_info;
+ int response_data_size;
+
+ HttpResponseInfoIOBuffer();
+ explicit HttpResponseInfoIOBuffer(net::HttpResponseInfo* info);
+
+ protected:
+ friend class base::RefCountedThreadSafe<HttpResponseInfoIOBuffer>;
+ virtual ~HttpResponseInfoIOBuffer();
+};
+
+// Low level storage API used by the response reader and writer.
+class CONTENT_EXPORT AppCacheDiskCacheInterface {
+ public:
+ class Entry {
+ public:
+ virtual int Read(int index, int64 offset, net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) = 0;
+ virtual int Write(int index, int64 offset, net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback) = 0;
+ virtual int64 GetSize(int index) = 0;
+ virtual void Close() = 0;
+ protected:
+ virtual ~Entry() {}
+ };
+
+ virtual int CreateEntry(int64 key, Entry** entry,
+ const net::CompletionCallback& callback) = 0;
+ virtual int OpenEntry(int64 key, Entry** entry,
+ const net::CompletionCallback& callback) = 0;
+ virtual int DoomEntry(int64 key, const net::CompletionCallback& callback) = 0;
+
+ protected:
+ friend class base::RefCounted<AppCacheDiskCacheInterface>;
+ virtual ~AppCacheDiskCacheInterface() {}
+};
+
+// Common base class for response reader and writer.
+class CONTENT_EXPORT AppCacheResponseIO {
+ public:
+ virtual ~AppCacheResponseIO();
+ int64 response_id() const { return response_id_; }
+
+ protected:
+ AppCacheResponseIO(int64 response_id,
+ int64 group_id,
+ AppCacheDiskCacheInterface* disk_cache);
+
+ virtual void OnIOComplete(int result) = 0;
+
+ bool IsIOPending() { return !callback_.is_null(); }
+ void ScheduleIOCompletionCallback(int result);
+ void InvokeUserCompletionCallback(int result);
+ void ReadRaw(int index, int offset, net::IOBuffer* buf, int buf_len);
+ void WriteRaw(int index, int offset, net::IOBuffer* buf, int buf_len);
+
+ const int64 response_id_;
+ const int64 group_id_;
+ AppCacheDiskCacheInterface* disk_cache_;
+ AppCacheDiskCacheInterface::Entry* entry_;
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
+ scoped_refptr<net::IOBuffer> buffer_;
+ int buffer_len_;
+ net::CompletionCallback callback_;
+ base::WeakPtrFactory<AppCacheResponseIO> weak_factory_;
+
+ private:
+ void OnRawIOComplete(int result);
+};
+
+// Reads existing response data from storage. If the object is deleted
+// and there is a read in progress, the implementation will return
+// immediately but will take care of any side effect of cancelling the
+// operation. In other words, instances are safe to delete at will.
+class CONTENT_EXPORT AppCacheResponseReader
+ : public AppCacheResponseIO {
+ public:
+ ~AppCacheResponseReader() override;
+
+ // Reads http info from storage. Always returns the result of the read
+ // asynchronously through the 'callback'. Returns the number of bytes read
+ // or a net:: error code. Guaranteed to not perform partial reads of
+ // the info data. The reader acquires a reference to the 'info_buf' until
+ // completion at which time the callback is invoked with either a negative
+ // error code or the number of bytes read. The 'info_buf' argument should
+ // contain a NULL http_info when ReadInfo is called. The 'callback' is a
+ // required parameter.
+ // Should only be called where there is no Read operation in progress.
+ // (virtual for testing)
+ virtual void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
+ const net::CompletionCallback& callback);
+
+ // Reads data from storage. Always returns the result of the read
+ // asynchronously through the 'callback'. Returns the number of bytes read
+ // or a net:: error code. EOF is indicated with a return value of zero.
+ // The reader acquires a reference to the provided 'buf' until completion
+ // at which time the callback is invoked with either a negative error code
+ // or the number of bytes read. The 'callback' is a required parameter.
+ // Should only be called where there is no Read operation in progress.
+ // (virtual for testing)
+ virtual void ReadData(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback);
+
+ // Returns true if there is a read operation, for data or info, pending.
+ bool IsReadPending() { return IsIOPending(); }
+
+ // Used to support range requests. If not called, the reader will
+ // read the entire response body. If called, this must be called prior
+ // to the first call to the ReadData method.
+ void SetReadRange(int offset, int length);
+
+ protected:
+ friend class AppCacheStorageImpl;
+ friend class content::MockAppCacheStorage;
+
+ // Should only be constructed by the storage class and derivatives.
+ AppCacheResponseReader(int64 response_id,
+ int64 group_id,
+ AppCacheDiskCacheInterface* disk_cache);
+
+ void OnIOComplete(int result) override;
+ void ContinueReadInfo();
+ void ContinueReadData();
+ void OpenEntryIfNeededAndContinue();
+ void OnOpenEntryComplete(AppCacheDiskCacheInterface::Entry** entry, int rv);
+
+ int range_offset_;
+ int range_length_;
+ int read_position_;
+ net::CompletionCallback open_callback_;
+ base::WeakPtrFactory<AppCacheResponseReader> weak_factory_;
+};
+
+// Writes new response data to storage. If the object is deleted
+// and there is a write in progress, the implementation will return
+// immediately but will take care of any side effect of cancelling the
+// operation. In other words, instances are safe to delete at will.
+class CONTENT_EXPORT AppCacheResponseWriter
+ : public AppCacheResponseIO {
+ public:
+ ~AppCacheResponseWriter() override;
+
+ // Writes the http info to storage. Always returns the result of the write
+ // asynchronously through the 'callback'. Returns the number of bytes written
+ // or a net:: error code. The writer acquires a reference to the 'info_buf'
+ // until completion at which time the callback is invoked with either a
+ // negative error code or the number of bytes written. The 'callback' is a
+ // required parameter. The contents of 'info_buf' are not modified.
+ // Should only be called where there is no Write operation in progress.
+ void WriteInfo(HttpResponseInfoIOBuffer* info_buf,
+ const net::CompletionCallback& callback);
+
+ // Writes data to storage. Always returns the result of the write
+ // asynchronously through the 'callback'. Returns the number of bytes written
+ // or a net:: error code. Guaranteed to not perform partial writes.
+ // The writer acquires a reference to the provided 'buf' until completion at
+ // which time the callback is invoked with either a negative error code or
+ // the number of bytes written. The 'callback' is a required parameter.
+ // The contents of 'buf' are not modified.
+ // Should only be called where there is no Write operation in progress.
+ void WriteData(net::IOBuffer* buf, int buf_len,
+ const net::CompletionCallback& callback);
+
+ // Returns true if there is a write pending.
+ bool IsWritePending() { return IsIOPending(); }
+
+ // Returns the amount written, info and data.
+ int64 amount_written() { return info_size_ + write_position_; }
+
+ protected:
+ // Should only be constructed by the storage class and derivatives.
+ AppCacheResponseWriter(int64 response_id,
+ int64 group_id,
+ AppCacheDiskCacheInterface* disk_cache);
+
+ private:
+ friend class AppCacheStorageImpl;
+ friend class content::MockAppCacheStorage;
+
+ enum CreationPhase {
+ NO_ATTEMPT,
+ INITIAL_ATTEMPT,
+ DOOM_EXISTING,
+ SECOND_ATTEMPT
+ };
+
+ void OnIOComplete(int result) override;
+ void ContinueWriteInfo();
+ void ContinueWriteData();
+ void CreateEntryIfNeededAndContinue();
+ void OnCreateEntryComplete(AppCacheDiskCacheInterface::Entry** entry, int rv);
+
+ int info_size_;
+ int write_position_;
+ int write_amount_;
+ CreationPhase creation_phase_;
+ net::CompletionCallback create_callback_;
+ base::WeakPtrFactory<AppCacheResponseWriter> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_RESPONSE_H_
diff --git a/chromium/content/browser/appcache/appcache_response_unittest.cc b/chromium/content/browser/appcache/appcache_response_unittest.cc
index 935fd7cd773..815e69789c8 100644
--- a/chromium/content/browser/appcache/appcache_response_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_response_unittest.cc
@@ -13,18 +13,13 @@
#include "base/pickle.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/browser/appcache/appcache_response.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_response.h"
-using appcache::AppCacheStorage;
-using appcache::AppCacheResponseInfo;
-using appcache::AppCacheResponseReader;
-using appcache::AppCacheResponseWriter;
-using appcache::HttpResponseInfoIOBuffer;
using net::IOBuffer;
using net::WrappedIOBuffer;
@@ -36,7 +31,6 @@ static const int kNoSuchResponseId = 123;
class AppCacheResponseTest : public testing::Test {
public:
-
// Test Harness -------------------------------------------------------------
// Helper class used to verify test results
@@ -46,8 +40,8 @@ class AppCacheResponseTest : public testing::Test {
: loaded_info_id_(0), test_(test) {
}
- virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
- int64 response_id) OVERRIDE {
+ void OnResponseInfoLoaded(AppCacheResponseInfo* info,
+ int64 response_id) override {
loaded_info_ = info;
loaded_info_id_ = response_id;
test_->ScheduleNextTask();
@@ -160,7 +154,7 @@ class AppCacheResponseTest : public testing::Test {
void WriteBasicResponse() {
static const char kHttpHeaders[] =
"HTTP/1.0 200 OK\0Content-Length: 5\0\0";
- static const char* kHttpBody = "Hello";
+ static const char kHttpBody[] = "Hello";
scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
WriteResponse(
@@ -382,8 +376,7 @@ class AppCacheResponseTest : public testing::Test {
// AmountWritten ----------------------------------------------------
void AmountWritten() {
- static const char kHttpHeaders[] =
- "HTTP/1.0 200 OK\0\0";
+ static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
net::HttpResponseInfo* head = MakeHttpResponseInfo(raw_headers);
int expected_amount_written =
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
new file mode 100644
index 00000000000..0c784dfd3dc
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -0,0 +1,580 @@
+// Copyright 2014 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 "content/browser/appcache/appcache_service_impl.h"
+
+#include <functional>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_executable_handler.h"
+#include "content/browser/appcache/appcache_histograms.h"
+#include "content/browser/appcache/appcache_policy.h"
+#include "content/browser/appcache/appcache_quota_client.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage_impl.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "storage/browser/quota/special_storage_policy.h"
+
+namespace content {
+
+namespace {
+
+void DeferredCallback(const net::CompletionCallback& callback, int rv) {
+ callback.Run(rv);
+}
+
+} // namespace
+
+AppCacheInfoCollection::AppCacheInfoCollection() {}
+
+AppCacheInfoCollection::~AppCacheInfoCollection() {}
+
+// AsyncHelper -------
+
+class AppCacheServiceImpl::AsyncHelper
+ : public AppCacheStorage::Delegate {
+ public:
+ AsyncHelper(AppCacheServiceImpl* service,
+ const net::CompletionCallback& callback)
+ : service_(service), callback_(callback) {
+ service_->pending_helpers_.insert(this);
+ }
+
+ ~AsyncHelper() override {
+ if (service_)
+ service_->pending_helpers_.erase(this);
+ }
+
+ virtual void Start() = 0;
+ virtual void Cancel();
+
+ protected:
+ void CallCallback(int rv) {
+ if (!callback_.is_null()) {
+ // Defer to guarantee async completion.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&DeferredCallback, callback_, rv));
+ }
+ callback_.Reset();
+ }
+
+ AppCacheServiceImpl* service_;
+ net::CompletionCallback callback_;
+};
+
+void AppCacheServiceImpl::AsyncHelper::Cancel() {
+ if (!callback_.is_null()) {
+ callback_.Run(net::ERR_ABORTED);
+ callback_.Reset();
+ }
+ service_->storage()->CancelDelegateCallbacks(this);
+ service_ = NULL;
+}
+
+// CanHandleOfflineHelper -------
+
+class AppCacheServiceImpl::CanHandleOfflineHelper : AsyncHelper {
+ public:
+ CanHandleOfflineHelper(
+ AppCacheServiceImpl* service, const GURL& url,
+ const GURL& first_party, const net::CompletionCallback& callback)
+ : AsyncHelper(service, callback),
+ url_(url),
+ first_party_(first_party) {
+ }
+
+ void Start() override {
+ AppCachePolicy* policy = service_->appcache_policy();
+ if (policy && !policy->CanLoadAppCache(url_, first_party_)) {
+ CallCallback(net::ERR_FAILED);
+ delete this;
+ return;
+ }
+
+ service_->storage()->FindResponseForMainRequest(url_, GURL(), this);
+ }
+
+ private:
+ // AppCacheStorage::Delegate implementation.
+ void OnMainResponseFound(const GURL& url,
+ const AppCacheEntry& entry,
+ const GURL& fallback_url,
+ const AppCacheEntry& fallback_entry,
+ int64 cache_id,
+ int64 group_id,
+ const GURL& mainfest_url) override;
+
+ GURL url_;
+ GURL first_party_;
+
+ DISALLOW_COPY_AND_ASSIGN(CanHandleOfflineHelper);
+};
+
+void AppCacheServiceImpl::CanHandleOfflineHelper::OnMainResponseFound(
+ const GURL& url, const AppCacheEntry& entry,
+ const GURL& fallback_url, const AppCacheEntry& fallback_entry,
+ int64 cache_id, int64 group_id, const GURL& manifest_url) {
+ bool can = (entry.has_response_id() || fallback_entry.has_response_id());
+ CallCallback(can ? net::OK : net::ERR_FAILED);
+ delete this;
+}
+
+// DeleteHelper -------
+
+class AppCacheServiceImpl::DeleteHelper : public AsyncHelper {
+ public:
+ DeleteHelper(
+ AppCacheServiceImpl* service, const GURL& manifest_url,
+ const net::CompletionCallback& callback)
+ : AsyncHelper(service, callback), manifest_url_(manifest_url) {
+ }
+
+ void Start() override {
+ service_->storage()->LoadOrCreateGroup(manifest_url_, this);
+ }
+
+ private:
+ // AppCacheStorage::Delegate implementation.
+ void OnGroupLoaded(AppCacheGroup* group, const GURL& manifest_url) override;
+ void OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) override;
+
+ GURL manifest_url_;
+ DISALLOW_COPY_AND_ASSIGN(DeleteHelper);
+};
+
+void AppCacheServiceImpl::DeleteHelper::OnGroupLoaded(
+ AppCacheGroup* group, const GURL& manifest_url) {
+ if (group) {
+ group->set_being_deleted(true);
+ group->CancelUpdate();
+ service_->storage()->MakeGroupObsolete(group, this, 0);
+ } else {
+ CallCallback(net::ERR_FAILED);
+ delete this;
+ }
+}
+
+void AppCacheServiceImpl::DeleteHelper::OnGroupMadeObsolete(
+ AppCacheGroup* group,
+ bool success,
+ int response_code) {
+ CallCallback(success ? net::OK : net::ERR_FAILED);
+ delete this;
+}
+
+// DeleteOriginHelper -------
+
+class AppCacheServiceImpl::DeleteOriginHelper : public AsyncHelper {
+ public:
+ DeleteOriginHelper(
+ AppCacheServiceImpl* service, const GURL& origin,
+ const net::CompletionCallback& callback)
+ : AsyncHelper(service, callback), origin_(origin),
+ num_caches_to_delete_(0), successes_(0), failures_(0) {
+ }
+
+ void Start() override {
+ // We start by listing all caches, continues in OnAllInfo().
+ service_->storage()->GetAllInfo(this);
+ }
+
+ private:
+ // AppCacheStorage::Delegate implementation.
+ void OnAllInfo(AppCacheInfoCollection* collection) override;
+ void OnGroupLoaded(AppCacheGroup* group, const GURL& manifest_url) override;
+ void OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) override;
+
+ void CacheCompleted(bool success);
+
+ GURL origin_;
+ int num_caches_to_delete_;
+ int successes_;
+ int failures_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteOriginHelper);
+};
+
+void AppCacheServiceImpl::DeleteOriginHelper::OnAllInfo(
+ AppCacheInfoCollection* collection) {
+ if (!collection) {
+ // Failed to get a listing.
+ CallCallback(net::ERR_FAILED);
+ delete this;
+ return;
+ }
+
+ std::map<GURL, AppCacheInfoVector>::iterator found =
+ collection->infos_by_origin.find(origin_);
+ if (found == collection->infos_by_origin.end() || found->second.empty()) {
+ // No caches for this origin.
+ CallCallback(net::OK);
+ delete this;
+ return;
+ }
+
+ // We have some caches to delete.
+ const AppCacheInfoVector& caches_to_delete = found->second;
+ successes_ = 0;
+ failures_ = 0;
+ num_caches_to_delete_ = static_cast<int>(caches_to_delete.size());
+ for (AppCacheInfoVector::const_iterator iter = caches_to_delete.begin();
+ iter != caches_to_delete.end(); ++iter) {
+ service_->storage()->LoadOrCreateGroup(iter->manifest_url, this);
+ }
+}
+
+void AppCacheServiceImpl::DeleteOriginHelper::OnGroupLoaded(
+ AppCacheGroup* group, const GURL& manifest_url) {
+ if (group) {
+ group->set_being_deleted(true);
+ group->CancelUpdate();
+ service_->storage()->MakeGroupObsolete(group, this, 0);
+ } else {
+ CacheCompleted(false);
+ }
+}
+
+void AppCacheServiceImpl::DeleteOriginHelper::OnGroupMadeObsolete(
+ AppCacheGroup* group,
+ bool success,
+ int response_code) {
+ CacheCompleted(success);
+}
+
+void AppCacheServiceImpl::DeleteOriginHelper::CacheCompleted(bool success) {
+ if (success)
+ ++successes_;
+ else
+ ++failures_;
+ if ((successes_ + failures_) < num_caches_to_delete_)
+ return;
+
+ CallCallback(!failures_ ? net::OK : net::ERR_FAILED);
+ delete this;
+}
+
+
+// GetInfoHelper -------
+
+class AppCacheServiceImpl::GetInfoHelper : AsyncHelper {
+ public:
+ GetInfoHelper(
+ AppCacheServiceImpl* service, AppCacheInfoCollection* collection,
+ const net::CompletionCallback& callback)
+ : AsyncHelper(service, callback), collection_(collection) {
+ }
+
+ void Start() override { service_->storage()->GetAllInfo(this); }
+
+ private:
+ // AppCacheStorage::Delegate implementation.
+ void OnAllInfo(AppCacheInfoCollection* collection) override;
+
+ scoped_refptr<AppCacheInfoCollection> collection_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetInfoHelper);
+};
+
+void AppCacheServiceImpl::GetInfoHelper::OnAllInfo(
+ AppCacheInfoCollection* collection) {
+ if (collection)
+ collection->infos_by_origin.swap(collection_->infos_by_origin);
+ CallCallback(collection ? net::OK : net::ERR_FAILED);
+ delete this;
+}
+
+// CheckResponseHelper -------
+
+class AppCacheServiceImpl::CheckResponseHelper : AsyncHelper {
+ public:
+ CheckResponseHelper(
+ AppCacheServiceImpl* service, const GURL& manifest_url, int64 cache_id,
+ int64 response_id)
+ : AsyncHelper(service, net::CompletionCallback()),
+ manifest_url_(manifest_url),
+ cache_id_(cache_id),
+ response_id_(response_id),
+ kIOBufferSize(32 * 1024),
+ expected_total_size_(0),
+ amount_headers_read_(0),
+ amount_data_read_(0) {
+ }
+
+ void Start() override {
+ service_->storage()->LoadOrCreateGroup(manifest_url_, this);
+ }
+
+ void Cancel() override {
+ AppCacheHistograms::CountCheckResponseResult(
+ AppCacheHistograms::CHECK_CANCELED);
+ response_reader_.reset();
+ AsyncHelper::Cancel();
+ }
+
+ private:
+ void OnGroupLoaded(AppCacheGroup* group, const GURL& manifest_url) override;
+ void OnReadInfoComplete(int result);
+ void OnReadDataComplete(int result);
+
+ // Inputs describing what to check.
+ GURL manifest_url_;
+ int64 cache_id_;
+ int64 response_id_;
+
+ // Internals used to perform the checks.
+ const int kIOBufferSize;
+ scoped_refptr<AppCache> cache_;
+ scoped_ptr<AppCacheResponseReader> response_reader_;
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
+ scoped_refptr<net::IOBuffer> data_buffer_;
+ int64 expected_total_size_;
+ int amount_headers_read_;
+ int amount_data_read_;
+ DISALLOW_COPY_AND_ASSIGN(CheckResponseHelper);
+};
+
+void AppCacheServiceImpl::CheckResponseHelper::OnGroupLoaded(
+ AppCacheGroup* group, const GURL& manifest_url) {
+ DCHECK_EQ(manifest_url_, manifest_url);
+ if (!group || !group->newest_complete_cache() || group->is_being_deleted() ||
+ group->is_obsolete()) {
+ AppCacheHistograms::CountCheckResponseResult(
+ AppCacheHistograms::MANIFEST_OUT_OF_DATE);
+ delete this;
+ return;
+ }
+
+ cache_ = group->newest_complete_cache();
+ const AppCacheEntry* entry = cache_->GetEntryWithResponseId(response_id_);
+ if (!entry) {
+ if (cache_->cache_id() == cache_id_) {
+ AppCacheHistograms::CountCheckResponseResult(
+ AppCacheHistograms::ENTRY_NOT_FOUND);
+ service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ } else {
+ AppCacheHistograms::CountCheckResponseResult(
+ AppCacheHistograms::RESPONSE_OUT_OF_DATE);
+ }
+ delete this;
+ return;
+ }
+
+ // Verify that we can read the response info and data.
+ expected_total_size_ = entry->response_size();
+ response_reader_.reset(service_->storage()->CreateResponseReader(
+ manifest_url_, group->group_id(), response_id_));
+ info_buffer_ = new HttpResponseInfoIOBuffer();
+ response_reader_->ReadInfo(
+ info_buffer_.get(),
+ base::Bind(&CheckResponseHelper::OnReadInfoComplete,
+ base::Unretained(this)));
+}
+
+void AppCacheServiceImpl::CheckResponseHelper::OnReadInfoComplete(int result) {
+ if (result < 0) {
+ AppCacheHistograms::CountCheckResponseResult(
+ AppCacheHistograms::READ_HEADERS_ERROR);
+ service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ delete this;
+ return;
+ }
+ amount_headers_read_ = result;
+
+ // Start reading the data.
+ data_buffer_ = new net::IOBuffer(kIOBufferSize);
+ response_reader_->ReadData(
+ data_buffer_.get(),
+ kIOBufferSize,
+ base::Bind(&CheckResponseHelper::OnReadDataComplete,
+ base::Unretained(this)));
+}
+
+void AppCacheServiceImpl::CheckResponseHelper::OnReadDataComplete(int result) {
+ if (result > 0) {
+ // Keep reading until we've read thru everything or failed to read.
+ amount_data_read_ += result;
+ response_reader_->ReadData(
+ data_buffer_.get(),
+ kIOBufferSize,
+ base::Bind(&CheckResponseHelper::OnReadDataComplete,
+ base::Unretained(this)));
+ return;
+ }
+
+ AppCacheHistograms::CheckResponseResultType check_result;
+ if (result < 0)
+ check_result = AppCacheHistograms::READ_DATA_ERROR;
+ else if (info_buffer_->response_data_size != amount_data_read_ ||
+ expected_total_size_ != amount_data_read_ + amount_headers_read_)
+ check_result = AppCacheHistograms::UNEXPECTED_DATA_SIZE;
+ else
+ check_result = AppCacheHistograms::RESPONSE_OK;
+ AppCacheHistograms::CountCheckResponseResult(check_result);
+
+ if (check_result != AppCacheHistograms::RESPONSE_OK)
+ service_->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ delete this;
+}
+
+// AppCacheStorageReference ------
+
+AppCacheStorageReference::AppCacheStorageReference(
+ scoped_ptr<AppCacheStorage> storage)
+ : storage_(storage.Pass()) {}
+AppCacheStorageReference::~AppCacheStorageReference() {}
+
+// AppCacheServiceImpl -------
+
+AppCacheServiceImpl::AppCacheServiceImpl(
+ storage::QuotaManagerProxy* quota_manager_proxy)
+ : appcache_policy_(NULL),
+ quota_client_(NULL),
+ handler_factory_(NULL),
+ quota_manager_proxy_(quota_manager_proxy),
+ request_context_(NULL),
+ force_keep_session_state_(false) {
+ if (quota_manager_proxy_.get()) {
+ quota_client_ = new AppCacheQuotaClient(this);
+ quota_manager_proxy_->RegisterClient(quota_client_);
+ }
+}
+
+AppCacheServiceImpl::~AppCacheServiceImpl() {
+ DCHECK(backends_.empty());
+ std::for_each(pending_helpers_.begin(),
+ pending_helpers_.end(),
+ std::mem_fun(&AsyncHelper::Cancel));
+ STLDeleteElements(&pending_helpers_);
+ if (quota_client_)
+ quota_client_->NotifyAppCacheDestroyed();
+
+ // Destroy storage_ first; ~AppCacheStorageImpl accesses other data members
+ // (special_storage_policy_).
+ storage_.reset();
+}
+
+void AppCacheServiceImpl::Initialize(
+ const base::FilePath& cache_directory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread) {
+ DCHECK(!storage_.get());
+ cache_directory_ = cache_directory;
+ db_thread_ = db_thread;
+ cache_thread_ = cache_thread;
+ AppCacheStorageImpl* storage = new AppCacheStorageImpl(this);
+ storage->Initialize(cache_directory, db_thread, cache_thread);
+ storage_.reset(storage);
+}
+
+void AppCacheServiceImpl::ScheduleReinitialize() {
+ if (reinit_timer_.IsRunning())
+ return;
+
+ // Reinitialization only happens when corruption has been noticed.
+ // We don't want to thrash the disk but we also don't want to
+ // leave the appcache disabled for an indefinite period of time. Some
+ // users never shutdown the browser.
+
+ const base::TimeDelta kZeroDelta;
+ const base::TimeDelta kOneHour(base::TimeDelta::FromHours(1));
+ const base::TimeDelta k30Seconds(base::TimeDelta::FromSeconds(30));
+
+ // If the system managed to stay up for long enough, reset the
+ // delay so a new failure won't incur a long wait to get going again.
+ base::TimeDelta up_time = base::Time::Now() - last_reinit_time_;
+ if (next_reinit_delay_ != kZeroDelta && up_time > kOneHour)
+ next_reinit_delay_ = kZeroDelta;
+
+ reinit_timer_.Start(FROM_HERE, next_reinit_delay_,
+ this, &AppCacheServiceImpl::Reinitialize);
+
+ // Adjust the delay for next time.
+ base::TimeDelta increment = std::max(k30Seconds, next_reinit_delay_);
+ next_reinit_delay_ = std::min(next_reinit_delay_ + increment, kOneHour);
+}
+
+void AppCacheServiceImpl::Reinitialize() {
+ AppCacheHistograms::CountReinitAttempt(!last_reinit_time_.is_null());
+ last_reinit_time_ = base::Time::Now();
+
+ // Inform observers of about this and give them a chance to
+ // defer deletion of the old storage object.
+ scoped_refptr<AppCacheStorageReference>
+ old_storage_ref(new AppCacheStorageReference(storage_.Pass()));
+ FOR_EACH_OBSERVER(Observer, observers_,
+ OnServiceReinitialized(old_storage_ref.get()));
+
+ Initialize(cache_directory_, db_thread_, cache_thread_);
+}
+
+void AppCacheServiceImpl::CanHandleMainResourceOffline(
+ const GURL& url,
+ const GURL& first_party,
+ const net::CompletionCallback& callback) {
+ CanHandleOfflineHelper* helper =
+ new CanHandleOfflineHelper(this, url, first_party, callback);
+ helper->Start();
+}
+
+void AppCacheServiceImpl::GetAllAppCacheInfo(
+ AppCacheInfoCollection* collection,
+ const net::CompletionCallback& callback) {
+ DCHECK(collection);
+ GetInfoHelper* helper = new GetInfoHelper(this, collection, callback);
+ helper->Start();
+}
+
+void AppCacheServiceImpl::DeleteAppCacheGroup(
+ const GURL& manifest_url,
+ const net::CompletionCallback& callback) {
+ DeleteHelper* helper = new DeleteHelper(this, manifest_url, callback);
+ helper->Start();
+}
+
+void AppCacheServiceImpl::DeleteAppCachesForOrigin(
+ const GURL& origin, const net::CompletionCallback& callback) {
+ DeleteOriginHelper* helper = new DeleteOriginHelper(this, origin, callback);
+ helper->Start();
+}
+
+void AppCacheServiceImpl::CheckAppCacheResponse(const GURL& manifest_url,
+ int64 cache_id,
+ int64 response_id) {
+ CheckResponseHelper* helper = new CheckResponseHelper(
+ this, manifest_url, cache_id, response_id);
+ helper->Start();
+}
+
+void AppCacheServiceImpl::set_special_storage_policy(
+ storage::SpecialStoragePolicy* policy) {
+ special_storage_policy_ = policy;
+}
+
+void AppCacheServiceImpl::RegisterBackend(
+ AppCacheBackendImpl* backend_impl) {
+ DCHECK(backends_.find(backend_impl->process_id()) == backends_.end());
+ backends_.insert(
+ BackendMap::value_type(backend_impl->process_id(), backend_impl));
+}
+
+void AppCacheServiceImpl::UnregisterBackend(
+ AppCacheBackendImpl* backend_impl) {
+ backends_.erase(backend_impl->process_id());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_service_impl.h b/chromium/content/browser/appcache/appcache_service_impl.h
new file mode 100644
index 00000000000..cb61f3a47d6
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_service_impl.h
@@ -0,0 +1,222 @@
+// Copyright 2014 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 CONTENT_BROWSER_APPCACHE_APPCACHE_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_SERVICE_IMPL_H_
+
+#include <map>
+#include <set>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/appcache_service.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_errors.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+
+namespace base {
+class FilePath;
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace net {
+class URLRequestContext;
+} // namespace net
+
+namespace storage {
+class SpecialStoragePolicy;
+} // namespace storage
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheServiceImplTest, ScheduleReinitialize);
+class AppCacheBackendImpl;
+class AppCacheExecutableHandlerFactory;
+class AppCacheQuotaClient;
+class AppCachePolicy;
+class AppCacheServiceImplTest;
+class AppCacheStorageImplTest;
+class AppCacheStorage;
+
+// Refcounted container to manage the lifetime of the old storage instance
+// during Reinitialization.
+class CONTENT_EXPORT AppCacheStorageReference
+ : public base::RefCounted<AppCacheStorageReference> {
+public:
+ AppCacheStorage* storage() const { return storage_.get(); }
+private:
+ friend class AppCacheServiceImpl;
+ friend class base::RefCounted<AppCacheStorageReference>;
+ AppCacheStorageReference(scoped_ptr<AppCacheStorage> storage);
+ ~AppCacheStorageReference();
+
+ scoped_ptr<AppCacheStorage> storage_;
+};
+
+// Class that manages the application cache service. Sends notifications
+// to many frontends. One instance per user-profile. Each instance has
+// exclusive access to its cache_directory on disk.
+class CONTENT_EXPORT AppCacheServiceImpl
+ : public AppCacheService {
+ public:
+
+ class CONTENT_EXPORT Observer {
+ public:
+ // An observer method to inform consumers of reinitialzation. Managing
+ // the lifetime of the old storage instance is a delicate process.
+ // Consumers can keep the old disabled instance alive by hanging on to the
+ // ref provided.
+ virtual void OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) = 0;
+ virtual ~Observer() {}
+ };
+
+ // If not using quota management, the proxy may be NULL.
+ explicit AppCacheServiceImpl(storage::QuotaManagerProxy* quota_manager_proxy);
+ ~AppCacheServiceImpl() override;
+
+ void Initialize(
+ const base::FilePath& cache_directory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread);
+
+ void AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+ }
+
+ void RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+ }
+
+ // For use in catastrophic failure modes to reboot the appcache system
+ // without relaunching the browser.
+ void ScheduleReinitialize();
+
+ // AppCacheService implementation:
+ void CanHandleMainResourceOffline(
+ const GURL& url,
+ const GURL& first_party,
+ const net::CompletionCallback& callback) override;
+ void GetAllAppCacheInfo(AppCacheInfoCollection* collection,
+ const net::CompletionCallback& callback) override;
+ void DeleteAppCacheGroup(const GURL& manifest_url,
+ const net::CompletionCallback& callback) override;
+
+ // Deletes all appcaches for the origin, 'callback' is invoked upon
+ // completion. This method always completes asynchronously.
+ // (virtual for unit testing)
+ virtual void DeleteAppCachesForOrigin(
+ const GURL& origin, const net::CompletionCallback& callback);
+
+ // Checks the integrity of 'response_id' by reading the headers and data.
+ // If it cannot be read, the cache group for 'manifest_url' is deleted.
+ void CheckAppCacheResponse(const GURL& manifest_url, int64 cache_id,
+ int64 response_id);
+
+ // Context for use during cache updates, should only be accessed
+ // on the IO thread. We do NOT add a reference to the request context,
+ // it is the callers responsibility to ensure that the pointer
+ // remains valid while set.
+ net::URLRequestContext* request_context() const { return request_context_; }
+ void set_request_context(net::URLRequestContext* context) {
+ request_context_ = context;
+ }
+
+ // The appcache policy, may be null, in which case access is always allowed.
+ // The service does NOT assume ownership of the policy, it is the callers
+ // responsibility to ensure that the pointer remains valid while set.
+ AppCachePolicy* appcache_policy() const { return appcache_policy_; }
+ void set_appcache_policy(AppCachePolicy* policy) {
+ appcache_policy_ = policy;
+ }
+
+ // The factory may be null, in which case invocations of exe handlers
+ // will result in an error response.
+ // The service does NOT assume ownership of the factory, it is the callers
+ // responsibility to ensure that the pointer remains valid while set.
+ AppCacheExecutableHandlerFactory* handler_factory() const {
+ return handler_factory_;
+ }
+ void set_handler_factory(
+ AppCacheExecutableHandlerFactory* factory) {
+ handler_factory_ = factory;
+ }
+
+ storage::SpecialStoragePolicy* special_storage_policy() const {
+ return special_storage_policy_.get();
+ }
+ void set_special_storage_policy(storage::SpecialStoragePolicy* policy);
+
+ storage::QuotaManagerProxy* quota_manager_proxy() const {
+ return quota_manager_proxy_.get();
+ }
+
+ AppCacheQuotaClient* quota_client() const {
+ return quota_client_;
+ }
+
+ // Each child process in chrome uses a distinct backend instance.
+ // See chrome/browser/AppCacheDispatcherHost.
+ void RegisterBackend(AppCacheBackendImpl* backend_impl);
+ void UnregisterBackend(AppCacheBackendImpl* backend_impl);
+ AppCacheBackendImpl* GetBackend(int id) const {
+ BackendMap::const_iterator it = backends_.find(id);
+ return (it != backends_.end()) ? it->second : NULL;
+ }
+
+ AppCacheStorage* storage() const { return storage_.get(); }
+
+ // Disables the exit-time deletion of session-only data.
+ void set_force_keep_session_state() { force_keep_session_state_ = true; }
+ bool force_keep_session_state() const { return force_keep_session_state_; }
+
+ protected:
+ friend class content::AppCacheServiceImplTest;
+ friend class content::AppCacheStorageImplTest;
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheServiceImplTest,
+ ScheduleReinitialize);
+
+ class AsyncHelper;
+ class CanHandleOfflineHelper;
+ class DeleteHelper;
+ class DeleteOriginHelper;
+ class GetInfoHelper;
+ class CheckResponseHelper;
+
+ typedef std::set<AsyncHelper*> PendingAsyncHelpers;
+ typedef std::map<int, AppCacheBackendImpl*> BackendMap;
+
+ void Reinitialize();
+
+ base::FilePath cache_directory_;
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
+ AppCachePolicy* appcache_policy_;
+ AppCacheQuotaClient* quota_client_;
+ AppCacheExecutableHandlerFactory* handler_factory_;
+ scoped_ptr<AppCacheStorage> storage_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+ PendingAsyncHelpers pending_helpers_;
+ BackendMap backends_; // One 'backend' per child process.
+ // Context for use during cache updates.
+ net::URLRequestContext* request_context_;
+ // If true, nothing (not even session-only data) should be deleted on exit.
+ bool force_keep_session_state_;
+ base::Time last_reinit_time_;
+ base::TimeDelta next_reinit_delay_;
+ base::OneShotTimer<AppCacheServiceImpl> reinit_timer_;
+ ObserverList<Observer> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/appcache/appcache_service_unittest.cc b/chromium/content/browser/appcache/appcache_service_unittest.cc
index 80016a94784..b3532f5a25a 100644
--- a/chromium/content/browser/appcache/appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_service_unittest.cc
@@ -8,23 +8,13 @@
#include "base/bind_helpers.h"
#include "base/pickle.h"
#include "base/run_loop.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/appcache/mock_appcache_storage.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
-
-using appcache::AppCache;
-using appcache::AppCacheEntry;
-using appcache::AppCacheGroup;
-using appcache::AppCacheInfo;
-using appcache::AppCacheInfoCollection;
-using appcache::AppCacheInfoVector;
-using appcache::AppCacheResponseReader;
-using appcache::AppCacheServiceImpl;
-using appcache::HttpResponseInfoIOBuffer;
namespace content {
namespace {
@@ -48,8 +38,8 @@ class MockResponseReader : public AppCacheResponseReader {
info_(info), info_size_(info_size),
data_(data), data_size_(data_size) {
}
- virtual void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
- const net::CompletionCallback& callback) OVERRIDE {
+ void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
+ const net::CompletionCallback& callback) override {
info_buffer_ = info_buf;
callback_ = callback; // Cleared on completion.
@@ -58,8 +48,9 @@ class MockResponseReader : public AppCacheResponseReader {
info_buffer_->response_data_size = data_size_;
ScheduleUserCallback(rv);
}
- virtual void ReadData(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback) OVERRIDE {
+ void ReadData(net::IOBuffer* buf,
+ int buf_len,
+ const net::CompletionCallback& callback) override {
buffer_ = buf;
buffer_len_ = buf_len;
callback_ = callback; // Cleared on completion.
@@ -199,7 +190,7 @@ TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
delete_completion_count_ = 0;
// Should succeed given an empty info collection.
- mock_storage()->SimulateGetAllInfo(new AppCacheInfoCollection);
+ mock_storage()->SimulateGetAllInfo(new content::AppCacheInfoCollection);
service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback_);
EXPECT_EQ(0, delete_completion_count_);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/appcache/appcache_storage.cc b/chromium/content/browser/appcache/appcache_storage.cc
new file mode 100644
index 00000000000..077000616ae
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_storage.cc
@@ -0,0 +1,139 @@
+// 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 "content/browser/appcache/appcache_storage.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/stl_util.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+
+namespace content {
+
+// static
+const int64 AppCacheStorage::kUnitializedId = -1;
+
+AppCacheStorage::AppCacheStorage(AppCacheServiceImpl* service)
+ : last_cache_id_(kUnitializedId), last_group_id_(kUnitializedId),
+ last_response_id_(kUnitializedId), service_(service) {
+}
+
+AppCacheStorage::~AppCacheStorage() {
+ STLDeleteValues(&pending_info_loads_);
+ DCHECK(delegate_references_.empty());
+}
+
+AppCacheStorage::DelegateReference::DelegateReference(
+ Delegate* delegate, AppCacheStorage* storage)
+ : delegate(delegate), storage(storage) {
+ storage->delegate_references_.insert(
+ DelegateReferenceMap::value_type(delegate, this));
+}
+
+AppCacheStorage::DelegateReference::~DelegateReference() {
+ if (delegate)
+ storage->delegate_references_.erase(delegate);
+}
+
+AppCacheStorage::ResponseInfoLoadTask::ResponseInfoLoadTask(
+ const GURL& manifest_url,
+ int64 group_id,
+ int64 response_id,
+ AppCacheStorage* storage)
+ : storage_(storage),
+ manifest_url_(manifest_url),
+ group_id_(group_id),
+ response_id_(response_id),
+ info_buffer_(new HttpResponseInfoIOBuffer) {
+ storage_->pending_info_loads_.insert(
+ PendingResponseInfoLoads::value_type(response_id, this));
+}
+
+AppCacheStorage::ResponseInfoLoadTask::~ResponseInfoLoadTask() {
+}
+
+void AppCacheStorage::ResponseInfoLoadTask::StartIfNeeded() {
+ if (reader_)
+ return;
+ reader_.reset(
+ storage_->CreateResponseReader(manifest_url_, group_id_, response_id_));
+ reader_->ReadInfo(info_buffer_.get(),
+ base::Bind(&ResponseInfoLoadTask::OnReadComplete,
+ base::Unretained(this)));
+}
+
+void AppCacheStorage::ResponseInfoLoadTask::OnReadComplete(int result) {
+ storage_->pending_info_loads_.erase(response_id_);
+ scoped_refptr<AppCacheResponseInfo> info;
+ if (result >= 0) {
+ info = new AppCacheResponseInfo(storage_, manifest_url_,
+ response_id_,
+ info_buffer_->http_info.release(),
+ info_buffer_->response_data_size);
+ }
+ FOR_EACH_DELEGATE(delegates_, OnResponseInfoLoaded(info.get(), response_id_));
+ delete this;
+}
+
+void AppCacheStorage::LoadResponseInfo(
+ const GURL& manifest_url, int64 group_id, int64 id, Delegate* delegate) {
+ AppCacheResponseInfo* info = working_set_.GetResponseInfo(id);
+ if (info) {
+ delegate->OnResponseInfoLoaded(info, id);
+ return;
+ }
+ ResponseInfoLoadTask* info_load =
+ GetOrCreateResponseInfoLoadTask(manifest_url, group_id, id);
+ DCHECK(manifest_url == info_load->manifest_url());
+ DCHECK(group_id == info_load->group_id());
+ DCHECK(id == info_load->response_id());
+ info_load->AddDelegate(GetOrCreateDelegateReference(delegate));
+ info_load->StartIfNeeded();
+}
+
+void AppCacheStorage::UpdateUsageMapAndNotify(
+ const GURL& origin, int64 new_usage) {
+ DCHECK_GE(new_usage, 0);
+ int64 old_usage = usage_map_[origin];
+ if (new_usage > 0)
+ usage_map_[origin] = new_usage;
+ else
+ usage_map_.erase(origin);
+ if (new_usage != old_usage && service()->quota_manager_proxy()) {
+ service()->quota_manager_proxy()->NotifyStorageModified(
+ storage::QuotaClient::kAppcache,
+ origin,
+ storage::kStorageTypeTemporary,
+ new_usage - old_usage);
+ }
+}
+
+void AppCacheStorage::ClearUsageMapAndNotify() {
+ if (service()->quota_manager_proxy()) {
+ for (UsageMap::const_iterator iter = usage_map_.begin();
+ iter != usage_map_.end(); ++iter) {
+ service()->quota_manager_proxy()->NotifyStorageModified(
+ storage::QuotaClient::kAppcache,
+ iter->first,
+ storage::kStorageTypeTemporary,
+ -(iter->second));
+ }
+ }
+ usage_map_.clear();
+}
+
+void AppCacheStorage::NotifyStorageAccessed(const GURL& origin) {
+ if (service()->quota_manager_proxy() &&
+ usage_map_.find(origin) != usage_map_.end())
+ service()->quota_manager_proxy()->NotifyStorageAccessed(
+ storage::QuotaClient::kAppcache,
+ origin,
+ storage::kStorageTypeTemporary);
+}
+
+} // namespace content
+
diff --git a/chromium/content/browser/appcache/appcache_storage.h b/chromium/content/browser/appcache/appcache_storage.h
new file mode 100644
index 00000000000..edc059b9381
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_storage.h
@@ -0,0 +1,327 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_
+
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/appcache/appcache_working_set.h"
+#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
+
+class GURL;
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheStorageTest, DelegateReferences);
+FORWARD_DECLARE_TEST(AppCacheStorageTest, UsageMap);
+class AppCache;
+class AppCacheEntry;
+class AppCacheGroup;
+class AppCacheQuotaClientTest;
+class AppCacheResponseReader;
+class AppCacheResponseTest;
+class AppCacheResponseWriter;
+class AppCacheServiceImpl;
+class AppCacheStorageTest;
+struct AppCacheInfoCollection;
+struct HttpResponseInfoIOBuffer;
+
+class CONTENT_EXPORT AppCacheStorage {
+ public:
+ typedef std::map<GURL, int64> UsageMap;
+
+ class CONTENT_EXPORT Delegate {
+ public:
+ // If retrieval fails, 'collection' will be NULL.
+ virtual void OnAllInfo(AppCacheInfoCollection* collection) {}
+
+ // If a load fails the 'cache' will be NULL.
+ virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) {}
+
+ // If a load fails the 'group' will be NULL.
+ virtual void OnGroupLoaded(
+ AppCacheGroup* group, const GURL& manifest_url) {}
+
+ // If successfully stored 'success' will be true.
+ virtual void OnGroupAndNewestCacheStored(
+ AppCacheGroup* group, AppCache* newest_cache, bool success,
+ bool would_exceed_quota) {}
+
+ // If the operation fails, success will be false.
+ virtual void OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) {}
+
+ // If a load fails the 'response_info' will be NULL.
+ virtual void OnResponseInfoLoaded(
+ AppCacheResponseInfo* response_info, int64 response_id) {}
+
+ // If no response is found, entry.response_id() and
+ // fallback_entry.response_id() will be kAppCacheNoResponseId.
+ // If the response is the entry for an intercept or fallback
+ // namespace, the url of the namespece entry is returned.
+ // If a response is found, the cache id and manifest url of the
+ // containing cache and group are also returned.
+ virtual void OnMainResponseFound(
+ const GURL& url, const AppCacheEntry& entry,
+ const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
+ int64 cache_id, int64 group_id, const GURL& mainfest_url) {}
+
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ explicit AppCacheStorage(AppCacheServiceImpl* service);
+ virtual ~AppCacheStorage();
+
+ // Schedules a task to retrieve basic info about all groups and caches
+ // stored in the system. Upon completion the delegate will be called
+ // with the results.
+ virtual void GetAllInfo(Delegate* delegate) = 0;
+
+ // Schedules a cache to be loaded from storage. Upon load completion
+ // the delegate will be called back. If the cache already resides in
+ // memory, the delegate will be called back immediately without returning
+ // to the message loop. If the load fails, the delegate will be called
+ // back with a NULL cache pointer.
+ virtual void LoadCache(int64 id, Delegate* delegate) = 0;
+
+ // Schedules a group and its newest cache, if any, to be loaded from storage.
+ // Upon load completion the delegate will be called back. If the group
+ // and newest cache already reside in memory, the delegate will be called
+ // back immediately without returning to the message loop. If the load fails,
+ // the delegate will be called back with a NULL group pointer.
+ virtual void LoadOrCreateGroup(
+ const GURL& manifest_url, Delegate* delegate) = 0;
+
+ // Schedules response info to be loaded from storage.
+ // Upon load completion the delegate will be called back. If the data
+ // already resides in memory, the delegate will be called back
+ // immediately without returning to the message loop. If the load fails,
+ // the delegate will be called back with a NULL pointer.
+ virtual void LoadResponseInfo(
+ const GURL& manifest_url, int64 group_id, int64 response_id,
+ Delegate* delegate);
+
+ // Schedules a group and its newest complete cache to be initially stored or
+ // incrementally updated with new changes. Upon completion the delegate
+ // will be called back. A group without a newest cache cannot be stored.
+ // It's a programming error to call this method without a newest cache. A
+ // side effect of storing a new newest cache is the removal of the group's
+ // old caches and responses from persistent storage (although they may still
+ // linger in the in-memory working set until no longer needed). The new
+ // cache will be added as the group's newest complete cache only if storage
+ // succeeds.
+ virtual void StoreGroupAndNewestCache(
+ AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) = 0;
+
+ // Schedules a query to identify a response for a main request. Upon
+ // completion the delegate will be called back.
+ virtual void FindResponseForMainRequest(
+ const GURL& url,
+ const GURL& preferred_manifest_url,
+ Delegate* delegate) = 0;
+
+ // Performs an immediate lookup of the in-memory cache to
+ // identify a response for a sub resource request.
+ virtual void FindResponseForSubRequest(
+ AppCache* cache, const GURL& url,
+ AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
+ bool* found_network_namespace) = 0;
+
+ // Immediately updates in-memory storage, if the cache is in memory,
+ // and schedules a task to update persistent storage. If the cache is
+ // already scheduled to be loaded, upon loading completion the entry
+ // will be marked. There is no delegate completion callback.
+ virtual void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) = 0;
+
+ // Schedules a task to update persistent storage and doom the group and all
+ // related caches and responses for deletion. Upon completion the in-memory
+ // instance is marked as obsolete and the delegate callback is called.
+ virtual void MakeGroupObsolete(AppCacheGroup* group,
+ Delegate* delegate,
+ int response_code) = 0;
+
+ // Cancels all pending callbacks for the delegate. The delegate callbacks
+ // will not be invoked after, however any scheduled operations will still
+ // take place. The callbacks for subsequently scheduled operations are
+ // unaffected.
+ void CancelDelegateCallbacks(Delegate* delegate) {
+ DelegateReference* delegate_reference = GetDelegateReference(delegate);
+ if (delegate_reference)
+ delegate_reference->CancelReference();
+ }
+
+ // Creates a reader to read a response from storage.
+ virtual AppCacheResponseReader* CreateResponseReader(
+ const GURL& manifest_url, int64 group_id, int64 response_id) = 0;
+
+ // Creates a writer to write a new response to storage. This call
+ // establishes a new response id.
+ virtual AppCacheResponseWriter* CreateResponseWriter(
+ const GURL& manifest_url, int64 group_id) = 0;
+
+ // Schedules the lazy deletion of responses and saves the ids
+ // persistently such that the responses will be deleted upon restart
+ // if they aren't deleted prior to shutdown.
+ virtual void DoomResponses(
+ const GURL& manifest_url, const std::vector<int64>& response_ids) = 0;
+
+ // Schedules the lazy deletion of responses without persistently saving
+ // the response ids.
+ virtual void DeleteResponses(
+ const GURL& manifest_url, const std::vector<int64>& response_ids) = 0;
+
+ // Generates unique storage ids for different object types.
+ int64 NewCacheId() {
+ return ++last_cache_id_;
+ }
+ int64 NewGroupId() {
+ return ++last_group_id_;
+ }
+
+ // The working set of object instances currently in memory.
+ AppCacheWorkingSet* working_set() { return &working_set_; }
+
+ // A map of origins to usage.
+ const UsageMap* usage_map() { return &usage_map_; }
+
+ // Simple ptr back to the service object that owns us.
+ AppCacheServiceImpl* service() { return service_; }
+
+ protected:
+ friend class content::AppCacheQuotaClientTest;
+ friend class content::AppCacheResponseTest;
+ friend class content::AppCacheStorageTest;
+
+ // Helper to call a collection of delegates.
+ #define FOR_EACH_DELEGATE(delegates, func_and_args) \
+ do { \
+ for (DelegateReferenceVector::iterator it = delegates.begin(); \
+ it != delegates.end(); ++it) { \
+ if (it->get()->delegate) \
+ it->get()->delegate->func_and_args; \
+ } \
+ } while (0)
+
+ // Helper used to manage multiple references to a 'delegate' and to
+ // allow all pending callbacks to that delegate to be easily cancelled.
+ struct CONTENT_EXPORT DelegateReference :
+ public base::RefCounted<DelegateReference> {
+ Delegate* delegate;
+ AppCacheStorage* storage;
+
+ DelegateReference(Delegate* delegate, AppCacheStorage* storage);
+
+ void CancelReference() {
+ storage->delegate_references_.erase(delegate);
+ storage = NULL;
+ delegate = NULL;
+ }
+
+ private:
+ friend class base::RefCounted<DelegateReference>;
+
+ virtual ~DelegateReference();
+ };
+ typedef std::map<Delegate*, DelegateReference*> DelegateReferenceMap;
+ typedef std::vector<scoped_refptr<DelegateReference> >
+ DelegateReferenceVector;
+
+ // Helper used to manage an async LoadResponseInfo calls on behalf of
+ // multiple callers.
+ class ResponseInfoLoadTask {
+ public:
+ ResponseInfoLoadTask(const GURL& manifest_url, int64 group_id,
+ int64 response_id, AppCacheStorage* storage);
+ ~ResponseInfoLoadTask();
+
+ int64 response_id() const { return response_id_; }
+ const GURL& manifest_url() const { return manifest_url_; }
+ int64 group_id() const { return group_id_; }
+
+ void AddDelegate(DelegateReference* delegate_reference) {
+ delegates_.push_back(delegate_reference);
+ }
+
+ void StartIfNeeded();
+
+ private:
+ void OnReadComplete(int result);
+
+ AppCacheStorage* storage_;
+ GURL manifest_url_;
+ int64 group_id_;
+ int64 response_id_;
+ scoped_ptr<AppCacheResponseReader> reader_;
+ DelegateReferenceVector delegates_;
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
+ };
+
+ typedef std::map<int64, ResponseInfoLoadTask*> PendingResponseInfoLoads;
+
+ DelegateReference* GetDelegateReference(Delegate* delegate) {
+ DelegateReferenceMap::iterator iter =
+ delegate_references_.find(delegate);
+ if (iter != delegate_references_.end())
+ return iter->second;
+ return NULL;
+ }
+
+ DelegateReference* GetOrCreateDelegateReference(Delegate* delegate) {
+ DelegateReference* reference = GetDelegateReference(delegate);
+ if (reference)
+ return reference;
+ return new DelegateReference(delegate, this);
+ }
+
+ ResponseInfoLoadTask* GetOrCreateResponseInfoLoadTask(
+ const GURL& manifest_url, int64 group_id, int64 response_id) {
+ PendingResponseInfoLoads::iterator iter =
+ pending_info_loads_.find(response_id);
+ if (iter != pending_info_loads_.end())
+ return iter->second;
+ return new ResponseInfoLoadTask(manifest_url, group_id, response_id, this);
+ }
+
+ // Should only be called when creating a new response writer.
+ int64 NewResponseId() {
+ return ++last_response_id_;
+ }
+
+ // Helpers to query and notify the QuotaManager.
+ void UpdateUsageMapAndNotify(const GURL& origin, int64 new_usage);
+ void ClearUsageMapAndNotify();
+ void NotifyStorageAccessed(const GURL& origin);
+
+ // The last storage id used for different object types.
+ int64 last_cache_id_;
+ int64 last_group_id_;
+ int64 last_response_id_;
+
+ UsageMap usage_map_; // maps origin to usage
+ AppCacheWorkingSet working_set_;
+ AppCacheServiceImpl* service_;
+ DelegateReferenceMap delegate_references_;
+ PendingResponseInfoLoads pending_info_loads_;
+
+ // The set of last ids must be retrieved from storage prior to being used.
+ static const int64 kUnitializedId;
+
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheStorageTest, DelegateReferences);
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheStorageTest, UsageMap);
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheStorage);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.cc b/chromium/content/browser/appcache/appcache_storage_impl.cc
new file mode 100644
index 00000000000..5df1d3ebdd1
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_storage_impl.cc
@@ -0,0 +1,1866 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_storage_impl.h"
+
+#include <algorithm>
+#include <functional>
+#include <set>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_database.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_histograms.h"
+#include "content/browser/appcache/appcache_quota_client.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "net/base/cache_type.h"
+#include "net/base/net_errors.h"
+#include "sql/connection.h"
+#include "sql/transaction.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/special_storage_policy.h"
+
+namespace content {
+
+// Hard coded default when not using quota management.
+static const int kDefaultQuota = 5 * 1024 * 1024;
+
+static const int kMaxDiskCacheSize = 250 * 1024 * 1024;
+static const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
+static const base::FilePath::CharType kDiskCacheDirectoryName[] =
+ FILE_PATH_LITERAL("Cache");
+
+namespace {
+
+// Helpers for clearing data from the AppCacheDatabase.
+bool DeleteGroupAndRelatedRecords(AppCacheDatabase* database,
+ int64 group_id,
+ std::vector<int64>* deletable_response_ids) {
+ AppCacheDatabase::CacheRecord cache_record;
+ bool success = false;
+ if (database->FindCacheForGroup(group_id, &cache_record)) {
+ database->FindResponseIdsForCacheAsVector(cache_record.cache_id,
+ deletable_response_ids);
+ success =
+ database->DeleteGroup(group_id) &&
+ database->DeleteCache(cache_record.cache_id) &&
+ database->DeleteEntriesForCache(cache_record.cache_id) &&
+ database->DeleteNamespacesForCache(cache_record.cache_id) &&
+ database->DeleteOnlineWhiteListForCache(cache_record.cache_id) &&
+ database->InsertDeletableResponseIds(*deletable_response_ids);
+ } else {
+ NOTREACHED() << "A existing group without a cache is unexpected";
+ success = database->DeleteGroup(group_id);
+ }
+ return success;
+}
+
+// Destroys |database|. If there is appcache data to be deleted
+// (|force_keep_session_state| is false), deletes session-only appcache data.
+void ClearSessionOnlyOrigins(
+ AppCacheDatabase* database,
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy,
+ bool force_keep_session_state) {
+ scoped_ptr<AppCacheDatabase> database_to_delete(database);
+
+ // If saving session state, only delete the database.
+ if (force_keep_session_state)
+ return;
+
+ bool has_session_only_appcaches =
+ special_storage_policy.get() &&
+ special_storage_policy->HasSessionOnlyOrigins();
+
+ // Clearning only session-only databases, and there are none.
+ if (!has_session_only_appcaches)
+ return;
+
+ std::set<GURL> origins;
+ database->FindOriginsWithGroups(&origins);
+ if (origins.empty())
+ return; // nothing to delete
+
+ sql::Connection* connection = database->db_connection();
+ if (!connection) {
+ NOTREACHED() << "Missing database connection.";
+ return;
+ }
+
+ std::set<GURL>::const_iterator origin;
+ DCHECK(special_storage_policy.get());
+ for (origin = origins.begin(); origin != origins.end(); ++origin) {
+ if (!special_storage_policy->IsStorageSessionOnly(*origin))
+ continue;
+ if (special_storage_policy->IsStorageProtected(*origin))
+ continue;
+
+ std::vector<AppCacheDatabase::GroupRecord> groups;
+ database->FindGroupsForOrigin(*origin, &groups);
+ std::vector<AppCacheDatabase::GroupRecord>::const_iterator group;
+ for (group = groups.begin(); group != groups.end(); ++group) {
+ sql::Transaction transaction(connection);
+ if (!transaction.Begin()) {
+ NOTREACHED() << "Failed to start transaction";
+ return;
+ }
+ std::vector<int64> deletable_response_ids;
+ bool success = DeleteGroupAndRelatedRecords(database,
+ group->group_id,
+ &deletable_response_ids);
+ success = success && transaction.Commit();
+ DCHECK(success);
+ } // for each group
+ } // for each origin
+}
+
+} // namespace
+
+// DatabaseTask -----------------------------------------
+
+class AppCacheStorageImpl::DatabaseTask
+ : public base::RefCountedThreadSafe<DatabaseTask> {
+ public:
+ explicit DatabaseTask(AppCacheStorageImpl* storage)
+ : storage_(storage), database_(storage->database_),
+ io_thread_(base::MessageLoopProxy::current()) {
+ DCHECK(io_thread_.get());
+ }
+
+ void AddDelegate(DelegateReference* delegate_reference) {
+ delegates_.push_back(make_scoped_refptr(delegate_reference));
+ }
+
+ // Schedules a task to be Run() on the DB thread. Tasks
+ // are run in the order in which they are scheduled.
+ void Schedule();
+
+ // Called on the DB thread.
+ virtual void Run() = 0;
+
+ // Called on the IO thread after Run() has completed.
+ virtual void RunCompleted() {}
+
+ // Once scheduled a task cannot be cancelled, but the
+ // call to RunCompleted may be. This method should only be
+ // called on the IO thread. This is used by AppCacheStorageImpl
+ // to cancel the completion calls when AppCacheStorageImpl is
+ // destructed. This method may be overriden to release or delete
+ // additional data associated with the task that is not DB thread
+ // safe. If overriden, this base class method must be called from
+ // within the override.
+ virtual void CancelCompletion();
+
+ protected:
+ friend class base::RefCountedThreadSafe<DatabaseTask>;
+ virtual ~DatabaseTask() {}
+
+ AppCacheStorageImpl* storage_;
+ AppCacheDatabase* database_;
+ DelegateReferenceVector delegates_;
+
+ private:
+ void CallRun(base::TimeTicks schedule_time);
+ void CallRunCompleted(base::TimeTicks schedule_time);
+ void OnFatalError();
+
+ scoped_refptr<base::MessageLoopProxy> io_thread_;
+};
+
+void AppCacheStorageImpl::DatabaseTask::Schedule() {
+ DCHECK(storage_);
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ if (!storage_->database_)
+ return;
+
+ if (storage_->db_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&DatabaseTask::CallRun, this, base::TimeTicks::Now()))) {
+ storage_->scheduled_database_tasks_.push_back(this);
+ } else {
+ NOTREACHED() << "Thread for database tasks is not running.";
+ }
+}
+
+void AppCacheStorageImpl::DatabaseTask::CancelCompletion() {
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ delegates_.clear();
+ storage_ = NULL;
+}
+
+void AppCacheStorageImpl::DatabaseTask::CallRun(
+ base::TimeTicks schedule_time) {
+ AppCacheHistograms::AddTaskQueueTimeSample(
+ base::TimeTicks::Now() - schedule_time);
+ if (!database_->is_disabled()) {
+ base::TimeTicks run_time = base::TimeTicks::Now();
+ Run();
+ AppCacheHistograms::AddTaskRunTimeSample(
+ base::TimeTicks::Now() - run_time);
+
+ if (database_->was_corruption_detected()) {
+ AppCacheHistograms::CountCorruptionDetected();
+ database_->Disable();
+ }
+ if (database_->is_disabled()) {
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&DatabaseTask::OnFatalError, this));
+ }
+ }
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&DatabaseTask::CallRunCompleted, this,
+ base::TimeTicks::Now()));
+}
+
+void AppCacheStorageImpl::DatabaseTask::CallRunCompleted(
+ base::TimeTicks schedule_time) {
+ AppCacheHistograms::AddCompletionQueueTimeSample(
+ base::TimeTicks::Now() - schedule_time);
+ if (storage_) {
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(storage_->scheduled_database_tasks_.front() == this);
+ storage_->scheduled_database_tasks_.pop_front();
+ base::TimeTicks run_time = base::TimeTicks::Now();
+ RunCompleted();
+ AppCacheHistograms::AddCompletionRunTimeSample(
+ base::TimeTicks::Now() - run_time);
+ delegates_.clear();
+ }
+}
+
+void AppCacheStorageImpl::DatabaseTask::OnFatalError() {
+ if (storage_) {
+ DCHECK(io_thread_->BelongsToCurrentThread());
+ storage_->Disable();
+ storage_->DeleteAndStartOver();
+ }
+}
+
+// InitTask -------
+
+class AppCacheStorageImpl::InitTask : public DatabaseTask {
+ public:
+ explicit InitTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage), last_group_id_(0),
+ last_cache_id_(0), last_response_id_(0),
+ last_deletable_response_rowid_(0) {
+ if (!storage->is_incognito_) {
+ db_file_path_ =
+ storage->cache_directory_.Append(kAppCacheDatabaseName);
+ disk_cache_directory_ =
+ storage->cache_directory_.Append(kDiskCacheDirectoryName);
+ }
+ }
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~InitTask() override {}
+
+ private:
+ base::FilePath db_file_path_;
+ base::FilePath disk_cache_directory_;
+ int64 last_group_id_;
+ int64 last_cache_id_;
+ int64 last_response_id_;
+ int64 last_deletable_response_rowid_;
+ std::map<GURL, int64> usage_map_;
+};
+
+void AppCacheStorageImpl::InitTask::Run() {
+ // If there is no sql database, ensure there is no disk cache either.
+ if (!db_file_path_.empty() &&
+ !base::PathExists(db_file_path_) &&
+ base::DirectoryExists(disk_cache_directory_)) {
+ base::DeleteFile(disk_cache_directory_, true);
+ if (base::DirectoryExists(disk_cache_directory_)) {
+ database_->Disable(); // This triggers OnFatalError handling.
+ return;
+ }
+ }
+
+ database_->FindLastStorageIds(
+ &last_group_id_, &last_cache_id_, &last_response_id_,
+ &last_deletable_response_rowid_);
+ database_->GetAllOriginUsage(&usage_map_);
+}
+
+void AppCacheStorageImpl::InitTask::RunCompleted() {
+ storage_->last_group_id_ = last_group_id_;
+ storage_->last_cache_id_ = last_cache_id_;
+ storage_->last_response_id_ = last_response_id_;
+ storage_->last_deletable_response_rowid_ = last_deletable_response_rowid_;
+
+ if (!storage_->is_disabled()) {
+ storage_->usage_map_.swap(usage_map_);
+ const base::TimeDelta kDelay = base::TimeDelta::FromMinutes(5);
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&AppCacheStorageImpl::DelayedStartDeletingUnusedResponses,
+ storage_->weak_factory_.GetWeakPtr()),
+ kDelay);
+ }
+
+ if (storage_->service()->quota_client())
+ storage_->service()->quota_client()->NotifyAppCacheReady();
+}
+
+// DisableDatabaseTask -------
+
+class AppCacheStorageImpl::DisableDatabaseTask : public DatabaseTask {
+ public:
+ explicit DisableDatabaseTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage) {}
+
+ // DatabaseTask:
+ void Run() override { database_->Disable(); }
+
+ protected:
+ ~DisableDatabaseTask() override {}
+};
+
+// GetAllInfoTask -------
+
+class AppCacheStorageImpl::GetAllInfoTask : public DatabaseTask {
+ public:
+ explicit GetAllInfoTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage),
+ info_collection_(new AppCacheInfoCollection()) {
+ }
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~GetAllInfoTask() override {}
+
+ private:
+ scoped_refptr<AppCacheInfoCollection> info_collection_;
+};
+
+void AppCacheStorageImpl::GetAllInfoTask::Run() {
+ std::set<GURL> origins;
+ database_->FindOriginsWithGroups(&origins);
+ for (std::set<GURL>::const_iterator origin = origins.begin();
+ origin != origins.end(); ++origin) {
+ AppCacheInfoVector& infos =
+ info_collection_->infos_by_origin[*origin];
+ std::vector<AppCacheDatabase::GroupRecord> groups;
+ database_->FindGroupsForOrigin(*origin, &groups);
+ for (std::vector<AppCacheDatabase::GroupRecord>::const_iterator
+ group = groups.begin();
+ group != groups.end(); ++group) {
+ AppCacheDatabase::CacheRecord cache_record;
+ database_->FindCacheForGroup(group->group_id, &cache_record);
+ AppCacheInfo info;
+ info.manifest_url = group->manifest_url;
+ info.creation_time = group->creation_time;
+ info.size = cache_record.cache_size;
+ info.last_access_time = group->last_access_time;
+ info.last_update_time = cache_record.update_time;
+ info.cache_id = cache_record.cache_id;
+ info.group_id = group->group_id;
+ info.is_complete = true;
+ infos.push_back(info);
+ }
+ }
+}
+
+void AppCacheStorageImpl::GetAllInfoTask::RunCompleted() {
+ DCHECK_EQ(1U, delegates_.size());
+ FOR_EACH_DELEGATE(delegates_, OnAllInfo(info_collection_.get()));
+}
+
+// StoreOrLoadTask -------
+
+class AppCacheStorageImpl::StoreOrLoadTask : public DatabaseTask {
+ protected:
+ explicit StoreOrLoadTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage) {}
+ ~StoreOrLoadTask() override {}
+
+ bool FindRelatedCacheRecords(int64 cache_id);
+ void CreateCacheAndGroupFromRecords(
+ scoped_refptr<AppCache>* cache, scoped_refptr<AppCacheGroup>* group);
+
+ AppCacheDatabase::GroupRecord group_record_;
+ AppCacheDatabase::CacheRecord cache_record_;
+ std::vector<AppCacheDatabase::EntryRecord> entry_records_;
+ std::vector<AppCacheDatabase::NamespaceRecord>
+ intercept_namespace_records_;
+ std::vector<AppCacheDatabase::NamespaceRecord>
+ fallback_namespace_records_;
+ std::vector<AppCacheDatabase::OnlineWhiteListRecord>
+ online_whitelist_records_;
+};
+
+bool AppCacheStorageImpl::StoreOrLoadTask::FindRelatedCacheRecords(
+ int64 cache_id) {
+ return database_->FindEntriesForCache(cache_id, &entry_records_) &&
+ database_->FindNamespacesForCache(
+ cache_id, &intercept_namespace_records_,
+ &fallback_namespace_records_) &&
+ database_->FindOnlineWhiteListForCache(
+ cache_id, &online_whitelist_records_);
+}
+
+void AppCacheStorageImpl::StoreOrLoadTask::CreateCacheAndGroupFromRecords(
+ scoped_refptr<AppCache>* cache, scoped_refptr<AppCacheGroup>* group) {
+ DCHECK(storage_ && cache && group);
+
+ (*cache) = storage_->working_set_.GetCache(cache_record_.cache_id);
+ if (cache->get()) {
+ (*group) = cache->get()->owning_group();
+ DCHECK(group->get());
+ DCHECK_EQ(group_record_.group_id, group->get()->group_id());
+
+ // TODO(michaeln): histogram is fishing for clues to crbug/95101
+ if (!cache->get()->GetEntry(group_record_.manifest_url)) {
+ AppCacheHistograms::AddMissingManifestDetectedAtCallsite(
+ AppCacheHistograms::CALLSITE_0);
+ }
+
+ storage_->NotifyStorageAccessed(group_record_.origin);
+ return;
+ }
+
+ (*cache) = new AppCache(storage_, cache_record_.cache_id);
+ cache->get()->InitializeWithDatabaseRecords(
+ cache_record_, entry_records_,
+ intercept_namespace_records_,
+ fallback_namespace_records_,
+ online_whitelist_records_);
+ cache->get()->set_complete(true);
+
+ (*group) = storage_->working_set_.GetGroup(group_record_.manifest_url);
+ if (group->get()) {
+ DCHECK(group_record_.group_id == group->get()->group_id());
+ group->get()->AddCache(cache->get());
+
+ // TODO(michaeln): histogram is fishing for clues to crbug/95101
+ if (!cache->get()->GetEntry(group_record_.manifest_url)) {
+ AppCacheHistograms::AddMissingManifestDetectedAtCallsite(
+ AppCacheHistograms::CALLSITE_1);
+ }
+ } else {
+ (*group) = new AppCacheGroup(
+ storage_, group_record_.manifest_url,
+ group_record_.group_id);
+ group->get()->set_creation_time(group_record_.creation_time);
+ group->get()->AddCache(cache->get());
+
+ // TODO(michaeln): histogram is fishing for clues to crbug/95101
+ if (!cache->get()->GetEntry(group_record_.manifest_url)) {
+ AppCacheHistograms::AddMissingManifestDetectedAtCallsite(
+ AppCacheHistograms::CALLSITE_2);
+ }
+ }
+ DCHECK(group->get()->newest_complete_cache() == cache->get());
+
+ // We have to update foriegn entries if MarkEntryAsForeignTasks
+ // are in flight.
+ std::vector<GURL> urls;
+ storage_->GetPendingForeignMarkingsForCache(cache->get()->cache_id(), &urls);
+ for (std::vector<GURL>::iterator iter = urls.begin();
+ iter != urls.end(); ++iter) {
+ DCHECK(cache->get()->GetEntry(*iter));
+ cache->get()->GetEntry(*iter)->add_types(AppCacheEntry::FOREIGN);
+ }
+
+ storage_->NotifyStorageAccessed(group_record_.origin);
+
+ // TODO(michaeln): Maybe verify that the responses we expect to exist
+ // do actually exist in the disk_cache (and if not then what?)
+}
+
+// CacheLoadTask -------
+
+class AppCacheStorageImpl::CacheLoadTask : public StoreOrLoadTask {
+ public:
+ CacheLoadTask(int64 cache_id, AppCacheStorageImpl* storage)
+ : StoreOrLoadTask(storage), cache_id_(cache_id),
+ success_(false) {}
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~CacheLoadTask() override {}
+
+ private:
+ int64 cache_id_;
+ bool success_;
+};
+
+void AppCacheStorageImpl::CacheLoadTask::Run() {
+ success_ =
+ database_->FindCache(cache_id_, &cache_record_) &&
+ database_->FindGroup(cache_record_.group_id, &group_record_) &&
+ FindRelatedCacheRecords(cache_id_);
+
+ if (success_)
+ database_->UpdateGroupLastAccessTime(group_record_.group_id,
+ base::Time::Now());
+}
+
+void AppCacheStorageImpl::CacheLoadTask::RunCompleted() {
+ storage_->pending_cache_loads_.erase(cache_id_);
+ scoped_refptr<AppCache> cache;
+ scoped_refptr<AppCacheGroup> group;
+ if (success_ && !storage_->is_disabled()) {
+ DCHECK(cache_record_.cache_id == cache_id_);
+ CreateCacheAndGroupFromRecords(&cache, &group);
+ }
+ FOR_EACH_DELEGATE(delegates_, OnCacheLoaded(cache.get(), cache_id_));
+}
+
+// GroupLoadTask -------
+
+class AppCacheStorageImpl::GroupLoadTask : public StoreOrLoadTask {
+ public:
+ GroupLoadTask(GURL manifest_url, AppCacheStorageImpl* storage)
+ : StoreOrLoadTask(storage), manifest_url_(manifest_url),
+ success_(false) {}
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~GroupLoadTask() override {}
+
+ private:
+ GURL manifest_url_;
+ bool success_;
+};
+
+void AppCacheStorageImpl::GroupLoadTask::Run() {
+ success_ =
+ database_->FindGroupForManifestUrl(manifest_url_, &group_record_) &&
+ database_->FindCacheForGroup(group_record_.group_id, &cache_record_) &&
+ FindRelatedCacheRecords(cache_record_.cache_id);
+
+ if (success_)
+ database_->UpdateGroupLastAccessTime(group_record_.group_id,
+ base::Time::Now());
+}
+
+void AppCacheStorageImpl::GroupLoadTask::RunCompleted() {
+ storage_->pending_group_loads_.erase(manifest_url_);
+ scoped_refptr<AppCacheGroup> group;
+ scoped_refptr<AppCache> cache;
+ if (!storage_->is_disabled()) {
+ if (success_) {
+ DCHECK(group_record_.manifest_url == manifest_url_);
+ CreateCacheAndGroupFromRecords(&cache, &group);
+ } else {
+ group = storage_->working_set_.GetGroup(manifest_url_);
+ if (!group.get()) {
+ group =
+ new AppCacheGroup(storage_, manifest_url_, storage_->NewGroupId());
+ }
+ }
+ }
+ FOR_EACH_DELEGATE(delegates_, OnGroupLoaded(group.get(), manifest_url_));
+}
+
+// StoreGroupAndCacheTask -------
+
+class AppCacheStorageImpl::StoreGroupAndCacheTask : public StoreOrLoadTask {
+ public:
+ StoreGroupAndCacheTask(AppCacheStorageImpl* storage, AppCacheGroup* group,
+ AppCache* newest_cache);
+
+ void GetQuotaThenSchedule();
+ void OnQuotaCallback(storage::QuotaStatusCode status,
+ int64 usage,
+ int64 quota);
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+ void CancelCompletion() override;
+
+ protected:
+ ~StoreGroupAndCacheTask() override {}
+
+ private:
+ scoped_refptr<AppCacheGroup> group_;
+ scoped_refptr<AppCache> cache_;
+ bool success_;
+ bool would_exceed_quota_;
+ int64 space_available_;
+ int64 new_origin_usage_;
+ std::vector<int64> newly_deletable_response_ids_;
+};
+
+AppCacheStorageImpl::StoreGroupAndCacheTask::StoreGroupAndCacheTask(
+ AppCacheStorageImpl* storage, AppCacheGroup* group, AppCache* newest_cache)
+ : StoreOrLoadTask(storage), group_(group), cache_(newest_cache),
+ success_(false), would_exceed_quota_(false),
+ space_available_(-1), new_origin_usage_(-1) {
+ group_record_.group_id = group->group_id();
+ group_record_.manifest_url = group->manifest_url();
+ group_record_.origin = group_record_.manifest_url.GetOrigin();
+ newest_cache->ToDatabaseRecords(
+ group,
+ &cache_record_, &entry_records_,
+ &intercept_namespace_records_,
+ &fallback_namespace_records_,
+ &online_whitelist_records_);
+}
+
+void AppCacheStorageImpl::StoreGroupAndCacheTask::GetQuotaThenSchedule() {
+ storage::QuotaManager* quota_manager = NULL;
+ if (storage_->service()->quota_manager_proxy()) {
+ quota_manager =
+ storage_->service()->quota_manager_proxy()->quota_manager();
+ }
+
+ if (!quota_manager) {
+ if (storage_->service()->special_storage_policy() &&
+ storage_->service()->special_storage_policy()->IsStorageUnlimited(
+ group_record_.origin))
+ space_available_ = kint64max;
+ Schedule();
+ return;
+ }
+
+ // We have to ask the quota manager for the value.
+ storage_->pending_quota_queries_.insert(this);
+ quota_manager->GetUsageAndQuota(
+ group_record_.origin,
+ storage::kStorageTypeTemporary,
+ base::Bind(&StoreGroupAndCacheTask::OnQuotaCallback, this));
+}
+
+void AppCacheStorageImpl::StoreGroupAndCacheTask::OnQuotaCallback(
+ storage::QuotaStatusCode status,
+ int64 usage,
+ int64 quota) {
+ if (storage_) {
+ if (status == storage::kQuotaStatusOk)
+ space_available_ = std::max(static_cast<int64>(0), quota - usage);
+ else
+ space_available_ = 0;
+ storage_->pending_quota_queries_.erase(this);
+ Schedule();
+ }
+}
+
+void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
+ DCHECK(!success_);
+ sql::Connection* connection = database_->db_connection();
+ if (!connection)
+ return;
+
+ sql::Transaction transaction(connection);
+ if (!transaction.Begin())
+ return;
+
+ int64 old_origin_usage = database_->GetOriginUsage(group_record_.origin);
+
+ AppCacheDatabase::GroupRecord existing_group;
+ success_ = database_->FindGroup(group_record_.group_id, &existing_group);
+ if (!success_) {
+ group_record_.creation_time = base::Time::Now();
+ group_record_.last_access_time = base::Time::Now();
+ success_ = database_->InsertGroup(&group_record_);
+ } else {
+ DCHECK(group_record_.group_id == existing_group.group_id);
+ DCHECK(group_record_.manifest_url == existing_group.manifest_url);
+ DCHECK(group_record_.origin == existing_group.origin);
+
+ database_->UpdateGroupLastAccessTime(group_record_.group_id,
+ base::Time::Now());
+
+ AppCacheDatabase::CacheRecord cache;
+ if (database_->FindCacheForGroup(group_record_.group_id, &cache)) {
+ // Get the set of response ids in the old cache.
+ std::set<int64> existing_response_ids;
+ database_->FindResponseIdsForCacheAsSet(cache.cache_id,
+ &existing_response_ids);
+
+ // Remove those that remain in the new cache.
+ std::vector<AppCacheDatabase::EntryRecord>::const_iterator entry_iter =
+ entry_records_.begin();
+ while (entry_iter != entry_records_.end()) {
+ existing_response_ids.erase(entry_iter->response_id);
+ ++entry_iter;
+ }
+
+ // The rest are deletable.
+ std::set<int64>::const_iterator id_iter = existing_response_ids.begin();
+ while (id_iter != existing_response_ids.end()) {
+ newly_deletable_response_ids_.push_back(*id_iter);
+ ++id_iter;
+ }
+
+ success_ =
+ database_->DeleteCache(cache.cache_id) &&
+ database_->DeleteEntriesForCache(cache.cache_id) &&
+ database_->DeleteNamespacesForCache(cache.cache_id) &&
+ database_->DeleteOnlineWhiteListForCache(cache.cache_id) &&
+ database_->InsertDeletableResponseIds(newly_deletable_response_ids_);
+ // TODO(michaeln): store group_id too with deletable ids
+ } else {
+ NOTREACHED() << "A existing group without a cache is unexpected";
+ }
+ }
+
+ success_ =
+ success_ &&
+ database_->InsertCache(&cache_record_) &&
+ database_->InsertEntryRecords(entry_records_) &&
+ database_->InsertNamespaceRecords(intercept_namespace_records_) &&
+ database_->InsertNamespaceRecords(fallback_namespace_records_) &&
+ database_->InsertOnlineWhiteListRecords(online_whitelist_records_);
+
+ if (!success_)
+ return;
+
+ new_origin_usage_ = database_->GetOriginUsage(group_record_.origin);
+
+ // Only check quota when the new usage exceeds the old usage.
+ if (new_origin_usage_ <= old_origin_usage) {
+ success_ = transaction.Commit();
+ return;
+ }
+
+ // Use a simple hard-coded value when not using quota management.
+ if (space_available_ == -1) {
+ if (new_origin_usage_ > kDefaultQuota) {
+ would_exceed_quota_ = true;
+ success_ = false;
+ return;
+ }
+ success_ = transaction.Commit();
+ return;
+ }
+
+ // Check limits based on the space availbable given to us via the
+ // quota system.
+ int64 delta = new_origin_usage_ - old_origin_usage;
+ if (delta > space_available_) {
+ would_exceed_quota_ = true;
+ success_ = false;
+ return;
+ }
+
+ success_ = transaction.Commit();
+}
+
+void AppCacheStorageImpl::StoreGroupAndCacheTask::RunCompleted() {
+ if (success_) {
+ storage_->UpdateUsageMapAndNotify(
+ group_->manifest_url().GetOrigin(), new_origin_usage_);
+ if (cache_.get() != group_->newest_complete_cache()) {
+ cache_->set_complete(true);
+ group_->AddCache(cache_.get());
+ }
+ if (group_->creation_time().is_null())
+ group_->set_creation_time(group_record_.creation_time);
+ group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_);
+ }
+ FOR_EACH_DELEGATE(
+ delegates_,
+ OnGroupAndNewestCacheStored(
+ group_.get(), cache_.get(), success_, would_exceed_quota_));
+ group_ = NULL;
+ cache_ = NULL;
+
+ // TODO(michaeln): if (would_exceed_quota_) what if the current usage
+ // also exceeds the quota? http://crbug.com/83968
+}
+
+void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() {
+ // Overriden to safely drop our reference to the group and cache
+ // which are not thread safe refcounted.
+ DatabaseTask::CancelCompletion();
+ group_ = NULL;
+ cache_ = NULL;
+}
+
+// FindMainResponseTask -------
+
+// Helpers for FindMainResponseTask::Run()
+namespace {
+class SortByCachePreference
+ : public std::binary_function<
+ AppCacheDatabase::EntryRecord,
+ AppCacheDatabase::EntryRecord,
+ bool> {
+ public:
+ SortByCachePreference(int64 preferred_id, const std::set<int64>& in_use_ids)
+ : preferred_id_(preferred_id), in_use_ids_(in_use_ids) {
+ }
+ bool operator()(
+ const AppCacheDatabase::EntryRecord& lhs,
+ const AppCacheDatabase::EntryRecord& rhs) {
+ return compute_value(lhs) > compute_value(rhs);
+ }
+ private:
+ int compute_value(const AppCacheDatabase::EntryRecord& entry) {
+ if (entry.cache_id == preferred_id_)
+ return 100;
+ else if (in_use_ids_.find(entry.cache_id) != in_use_ids_.end())
+ return 50;
+ return 0;
+ }
+ int64 preferred_id_;
+ const std::set<int64>& in_use_ids_;
+};
+
+bool SortByLength(
+ const AppCacheDatabase::NamespaceRecord& lhs,
+ const AppCacheDatabase::NamespaceRecord& rhs) {
+ return lhs.namespace_.namespace_url.spec().length() >
+ rhs.namespace_.namespace_url.spec().length();
+}
+
+class NetworkNamespaceHelper {
+ public:
+ explicit NetworkNamespaceHelper(AppCacheDatabase* database)
+ : database_(database) {
+ }
+
+ bool IsInNetworkNamespace(const GURL& url, int64 cache_id) {
+ typedef std::pair<WhiteListMap::iterator, bool> InsertResult;
+ InsertResult result = namespaces_map_.insert(
+ WhiteListMap::value_type(cache_id, AppCacheNamespaceVector()));
+ if (result.second)
+ GetOnlineWhiteListForCache(cache_id, &result.first->second);
+ return AppCache::FindNamespace(result.first->second, url) != NULL;
+ }
+
+ private:
+ void GetOnlineWhiteListForCache(
+ int64 cache_id, AppCacheNamespaceVector* namespaces) {
+ DCHECK(namespaces && namespaces->empty());
+ typedef std::vector<AppCacheDatabase::OnlineWhiteListRecord>
+ WhiteListVector;
+ WhiteListVector records;
+ if (!database_->FindOnlineWhiteListForCache(cache_id, &records))
+ return;
+ WhiteListVector::const_iterator iter = records.begin();
+ while (iter != records.end()) {
+ namespaces->push_back(
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, iter->namespace_url,
+ GURL(), iter->is_pattern));
+ ++iter;
+ }
+ }
+
+ // Key is cache id
+ typedef std::map<int64, AppCacheNamespaceVector> WhiteListMap;
+ WhiteListMap namespaces_map_;
+ AppCacheDatabase* database_;
+};
+
+} // namespace
+
+class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask {
+ public:
+ FindMainResponseTask(AppCacheStorageImpl* storage,
+ const GURL& url,
+ const GURL& preferred_manifest_url,
+ const AppCacheWorkingSet::GroupMap* groups_in_use)
+ : DatabaseTask(storage), url_(url),
+ preferred_manifest_url_(preferred_manifest_url),
+ cache_id_(kAppCacheNoCacheId), group_id_(0) {
+ if (groups_in_use) {
+ for (AppCacheWorkingSet::GroupMap::const_iterator it =
+ groups_in_use->begin();
+ it != groups_in_use->end(); ++it) {
+ AppCacheGroup* group = it->second;
+ AppCache* cache = group->newest_complete_cache();
+ if (group->is_obsolete() || !cache)
+ continue;
+ cache_ids_in_use_.insert(cache->cache_id());
+ }
+ }
+ }
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~FindMainResponseTask() override {}
+
+ private:
+ typedef std::vector<AppCacheDatabase::NamespaceRecord*>
+ NamespaceRecordPtrVector;
+
+ bool FindExactMatch(int64 preferred_id);
+ bool FindNamespaceMatch(int64 preferred_id);
+ bool FindNamespaceHelper(
+ int64 preferred_cache_id,
+ AppCacheDatabase::NamespaceRecordVector* namespaces,
+ NetworkNamespaceHelper* network_namespace_helper);
+ bool FindFirstValidNamespace(const NamespaceRecordPtrVector& namespaces);
+
+ GURL url_;
+ GURL preferred_manifest_url_;
+ std::set<int64> cache_ids_in_use_;
+ AppCacheEntry entry_;
+ AppCacheEntry fallback_entry_;
+ GURL namespace_entry_url_;
+ int64 cache_id_;
+ int64 group_id_;
+ GURL manifest_url_;
+};
+
+void AppCacheStorageImpl::FindMainResponseTask::Run() {
+ // NOTE: The heuristics around choosing amoungst multiple candidates
+ // is underspecified, and just plain not fully understood. This needs
+ // to be refined.
+
+ // The 'preferred_manifest_url' is the url of the manifest associated
+ // with the page that opened or embedded the page being loaded now.
+ // We have a strong preference to use resources from that cache.
+ // We also have a lesser bias to use resources from caches that are currently
+ // being used by other unrelated pages.
+ // TODO(michaeln): come up with a 'preferred_manifest_url' in more cases
+ // - when navigating a frame whose current contents are from an appcache
+ // - when clicking an href in a frame that is appcached
+ int64 preferred_cache_id = kAppCacheNoCacheId;
+ if (!preferred_manifest_url_.is_empty()) {
+ AppCacheDatabase::GroupRecord preferred_group;
+ AppCacheDatabase::CacheRecord preferred_cache;
+ if (database_->FindGroupForManifestUrl(
+ preferred_manifest_url_, &preferred_group) &&
+ database_->FindCacheForGroup(
+ preferred_group.group_id, &preferred_cache)) {
+ preferred_cache_id = preferred_cache.cache_id;
+ }
+ }
+
+ if (FindExactMatch(preferred_cache_id) ||
+ FindNamespaceMatch(preferred_cache_id)) {
+ // We found something.
+ DCHECK(cache_id_ != kAppCacheNoCacheId && !manifest_url_.is_empty() &&
+ group_id_ != 0);
+ return;
+ }
+
+ // We didn't find anything.
+ DCHECK(cache_id_ == kAppCacheNoCacheId && manifest_url_.is_empty() &&
+ group_id_ == 0);
+}
+
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindExactMatch(int64 preferred_cache_id) {
+ std::vector<AppCacheDatabase::EntryRecord> entries;
+ if (database_->FindEntriesForUrl(url_, &entries) && !entries.empty()) {
+ // Sort them in order of preference, from the preferred_cache first,
+ // followed by hits from caches that are 'in use', then the rest.
+ std::sort(entries.begin(), entries.end(),
+ SortByCachePreference(preferred_cache_id, cache_ids_in_use_));
+
+ // Take the first with a valid, non-foreign entry.
+ std::vector<AppCacheDatabase::EntryRecord>::iterator iter;
+ for (iter = entries.begin(); iter < entries.end(); ++iter) {
+ AppCacheDatabase::GroupRecord group_record;
+ if ((iter->flags & AppCacheEntry::FOREIGN) ||
+ !database_->FindGroupForCache(iter->cache_id, &group_record)) {
+ continue;
+ }
+ manifest_url_ = group_record.manifest_url;
+ group_id_ = group_record.group_id;
+ entry_ = AppCacheEntry(iter->flags, iter->response_id);
+ cache_id_ = iter->cache_id;
+ return true; // We found an exact match.
+ }
+ }
+ return false;
+}
+
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindNamespaceMatch(int64 preferred_cache_id) {
+ AppCacheDatabase::NamespaceRecordVector all_intercepts;
+ AppCacheDatabase::NamespaceRecordVector all_fallbacks;
+ if (!database_->FindNamespacesForOrigin(
+ url_.GetOrigin(), &all_intercepts, &all_fallbacks)
+ || (all_intercepts.empty() && all_fallbacks.empty())) {
+ return false;
+ }
+
+ NetworkNamespaceHelper network_namespace_helper(database_);
+ if (FindNamespaceHelper(preferred_cache_id,
+ &all_intercepts,
+ &network_namespace_helper) ||
+ FindNamespaceHelper(preferred_cache_id,
+ &all_fallbacks,
+ &network_namespace_helper)) {
+ return true;
+ }
+ return false;
+}
+
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindNamespaceHelper(
+ int64 preferred_cache_id,
+ AppCacheDatabase::NamespaceRecordVector* namespaces,
+ NetworkNamespaceHelper* network_namespace_helper) {
+ // Sort them by length, longer matches within the same cache/bucket take
+ // precedence.
+ std::sort(namespaces->begin(), namespaces->end(), SortByLength);
+
+ NamespaceRecordPtrVector preferred_namespaces;
+ NamespaceRecordPtrVector inuse_namespaces;
+ NamespaceRecordPtrVector other_namespaces;
+ std::vector<AppCacheDatabase::NamespaceRecord>::iterator iter;
+ for (iter = namespaces->begin(); iter < namespaces->end(); ++iter) {
+ // Skip those that aren't a match.
+ if (!iter->namespace_.IsMatch(url_))
+ continue;
+
+ // Skip namespaces where the requested url falls into a network
+ // namespace of its containing appcache.
+ if (network_namespace_helper->IsInNetworkNamespace(url_, iter->cache_id))
+ continue;
+
+ // Bin them into one of our three buckets.
+ if (iter->cache_id == preferred_cache_id)
+ preferred_namespaces.push_back(&(*iter));
+ else if (cache_ids_in_use_.find(iter->cache_id) != cache_ids_in_use_.end())
+ inuse_namespaces.push_back(&(*iter));
+ else
+ other_namespaces.push_back(&(*iter));
+ }
+
+ if (FindFirstValidNamespace(preferred_namespaces) ||
+ FindFirstValidNamespace(inuse_namespaces) ||
+ FindFirstValidNamespace(other_namespaces))
+ return true; // We found one.
+
+ // We didn't find anything.
+ return false;
+}
+
+bool AppCacheStorageImpl::
+FindMainResponseTask::FindFirstValidNamespace(
+ const NamespaceRecordPtrVector& namespaces) {
+ // Take the first with a valid, non-foreign entry.
+ NamespaceRecordPtrVector::const_iterator iter;
+ for (iter = namespaces.begin(); iter < namespaces.end(); ++iter) {
+ AppCacheDatabase::EntryRecord entry_record;
+ if (database_->FindEntry((*iter)->cache_id, (*iter)->namespace_.target_url,
+ &entry_record)) {
+ AppCacheDatabase::GroupRecord group_record;
+ if ((entry_record.flags & AppCacheEntry::FOREIGN) ||
+ !database_->FindGroupForCache(entry_record.cache_id, &group_record)) {
+ continue;
+ }
+ manifest_url_ = group_record.manifest_url;
+ group_id_ = group_record.group_id;
+ cache_id_ = (*iter)->cache_id;
+ namespace_entry_url_ = (*iter)->namespace_.target_url;
+ if ((*iter)->namespace_.type == APPCACHE_FALLBACK_NAMESPACE)
+ fallback_entry_ = AppCacheEntry(entry_record.flags,
+ entry_record.response_id);
+ else
+ entry_ = AppCacheEntry(entry_record.flags, entry_record.response_id);
+ return true; // We found one.
+ }
+ }
+ return false; // We didn't find a match.
+}
+
+void AppCacheStorageImpl::FindMainResponseTask::RunCompleted() {
+ storage_->CallOnMainResponseFound(
+ &delegates_, url_, entry_, namespace_entry_url_, fallback_entry_,
+ cache_id_, group_id_, manifest_url_);
+}
+
+// MarkEntryAsForeignTask -------
+
+class AppCacheStorageImpl::MarkEntryAsForeignTask : public DatabaseTask {
+ public:
+ MarkEntryAsForeignTask(
+ AppCacheStorageImpl* storage, const GURL& url, int64 cache_id)
+ : DatabaseTask(storage), cache_id_(cache_id), entry_url_(url) {}
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~MarkEntryAsForeignTask() override {}
+
+ private:
+ int64 cache_id_;
+ GURL entry_url_;
+};
+
+void AppCacheStorageImpl::MarkEntryAsForeignTask::Run() {
+ database_->AddEntryFlags(entry_url_, cache_id_, AppCacheEntry::FOREIGN);
+}
+
+void AppCacheStorageImpl::MarkEntryAsForeignTask::RunCompleted() {
+ DCHECK(storage_->pending_foreign_markings_.front().first == entry_url_ &&
+ storage_->pending_foreign_markings_.front().second == cache_id_);
+ storage_->pending_foreign_markings_.pop_front();
+}
+
+// MakeGroupObsoleteTask -------
+
+class AppCacheStorageImpl::MakeGroupObsoleteTask : public DatabaseTask {
+ public:
+ MakeGroupObsoleteTask(AppCacheStorageImpl* storage,
+ AppCacheGroup* group,
+ int response_code);
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+ void CancelCompletion() override;
+
+ protected:
+ ~MakeGroupObsoleteTask() override {}
+
+ private:
+ scoped_refptr<AppCacheGroup> group_;
+ int64 group_id_;
+ GURL origin_;
+ bool success_;
+ int response_code_;
+ int64 new_origin_usage_;
+ std::vector<int64> newly_deletable_response_ids_;
+};
+
+AppCacheStorageImpl::MakeGroupObsoleteTask::MakeGroupObsoleteTask(
+ AppCacheStorageImpl* storage,
+ AppCacheGroup* group,
+ int response_code)
+ : DatabaseTask(storage),
+ group_(group),
+ group_id_(group->group_id()),
+ origin_(group->manifest_url().GetOrigin()),
+ success_(false),
+ response_code_(response_code),
+ new_origin_usage_(-1) {}
+
+void AppCacheStorageImpl::MakeGroupObsoleteTask::Run() {
+ DCHECK(!success_);
+ sql::Connection* connection = database_->db_connection();
+ if (!connection)
+ return;
+
+ sql::Transaction transaction(connection);
+ if (!transaction.Begin())
+ return;
+
+ AppCacheDatabase::GroupRecord group_record;
+ if (!database_->FindGroup(group_id_, &group_record)) {
+ // This group doesn't exists in the database, nothing todo here.
+ new_origin_usage_ = database_->GetOriginUsage(origin_);
+ success_ = true;
+ return;
+ }
+
+ DCHECK_EQ(group_record.origin, origin_);
+ success_ = DeleteGroupAndRelatedRecords(database_,
+ group_id_,
+ &newly_deletable_response_ids_);
+
+ new_origin_usage_ = database_->GetOriginUsage(origin_);
+ success_ = success_ && transaction.Commit();
+}
+
+void AppCacheStorageImpl::MakeGroupObsoleteTask::RunCompleted() {
+ if (success_) {
+ group_->set_obsolete(true);
+ if (!storage_->is_disabled()) {
+ storage_->UpdateUsageMapAndNotify(origin_, new_origin_usage_);
+ group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_);
+
+ // Also remove from the working set, caches for an 'obsolete' group
+ // may linger in use, but the group itself cannot be looked up by
+ // 'manifest_url' in the working set any longer.
+ storage_->working_set()->RemoveGroup(group_.get());
+ }
+ }
+ FOR_EACH_DELEGATE(
+ delegates_, OnGroupMadeObsolete(group_.get(), success_, response_code_));
+ group_ = NULL;
+}
+
+void AppCacheStorageImpl::MakeGroupObsoleteTask::CancelCompletion() {
+ // Overriden to safely drop our reference to the group
+ // which is not thread safe refcounted.
+ DatabaseTask::CancelCompletion();
+ group_ = NULL;
+}
+
+// GetDeletableResponseIdsTask -------
+
+class AppCacheStorageImpl::GetDeletableResponseIdsTask : public DatabaseTask {
+ public:
+ GetDeletableResponseIdsTask(AppCacheStorageImpl* storage, int64 max_rowid)
+ : DatabaseTask(storage), max_rowid_(max_rowid) {}
+
+ // DatabaseTask:
+ void Run() override;
+ void RunCompleted() override;
+
+ protected:
+ ~GetDeletableResponseIdsTask() override {}
+
+ private:
+ int64 max_rowid_;
+ std::vector<int64> response_ids_;
+};
+
+void AppCacheStorageImpl::GetDeletableResponseIdsTask::Run() {
+ const int kSqlLimit = 1000;
+ database_->GetDeletableResponseIds(&response_ids_, max_rowid_, kSqlLimit);
+ // TODO(michaeln): retrieve group_ids too
+}
+
+void AppCacheStorageImpl::GetDeletableResponseIdsTask::RunCompleted() {
+ if (!response_ids_.empty())
+ storage_->StartDeletingResponses(response_ids_);
+}
+
+// InsertDeletableResponseIdsTask -------
+
+class AppCacheStorageImpl::InsertDeletableResponseIdsTask
+ : public DatabaseTask {
+ public:
+ explicit InsertDeletableResponseIdsTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage) {}
+
+ // DatabaseTask:
+ void Run() override;
+
+ std::vector<int64> response_ids_;
+
+ protected:
+ ~InsertDeletableResponseIdsTask() override {}
+};
+
+void AppCacheStorageImpl::InsertDeletableResponseIdsTask::Run() {
+ database_->InsertDeletableResponseIds(response_ids_);
+ // TODO(michaeln): store group_ids too
+}
+
+// DeleteDeletableResponseIdsTask -------
+
+class AppCacheStorageImpl::DeleteDeletableResponseIdsTask
+ : public DatabaseTask {
+ public:
+ explicit DeleteDeletableResponseIdsTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage) {}
+
+ // DatabaseTask:
+ void Run() override;
+
+ std::vector<int64> response_ids_;
+
+ protected:
+ ~DeleteDeletableResponseIdsTask() override {}
+};
+
+void AppCacheStorageImpl::DeleteDeletableResponseIdsTask::Run() {
+ database_->DeleteDeletableResponseIds(response_ids_);
+}
+
+// UpdateGroupLastAccessTimeTask -------
+
+class AppCacheStorageImpl::UpdateGroupLastAccessTimeTask
+ : public DatabaseTask {
+ public:
+ UpdateGroupLastAccessTimeTask(
+ AppCacheStorageImpl* storage, AppCacheGroup* group, base::Time time)
+ : DatabaseTask(storage), group_id_(group->group_id()),
+ last_access_time_(time) {
+ storage->NotifyStorageAccessed(group->manifest_url().GetOrigin());
+ }
+
+ // DatabaseTask:
+ void Run() override;
+
+ protected:
+ ~UpdateGroupLastAccessTimeTask() override {}
+
+ private:
+ int64 group_id_;
+ base::Time last_access_time_;
+};
+
+void AppCacheStorageImpl::UpdateGroupLastAccessTimeTask::Run() {
+ database_->UpdateGroupLastAccessTime(group_id_, last_access_time_);
+}
+
+
+// AppCacheStorageImpl ---------------------------------------------------
+
+AppCacheStorageImpl::AppCacheStorageImpl(AppCacheServiceImpl* service)
+ : AppCacheStorage(service),
+ is_incognito_(false),
+ is_response_deletion_scheduled_(false),
+ did_start_deleting_responses_(false),
+ last_deletable_response_rowid_(0),
+ database_(NULL),
+ is_disabled_(false),
+ weak_factory_(this) {
+}
+
+AppCacheStorageImpl::~AppCacheStorageImpl() {
+ std::for_each(pending_quota_queries_.begin(),
+ pending_quota_queries_.end(),
+ std::mem_fun(&DatabaseTask::CancelCompletion));
+ std::for_each(scheduled_database_tasks_.begin(),
+ scheduled_database_tasks_.end(),
+ std::mem_fun(&DatabaseTask::CancelCompletion));
+
+ if (database_ &&
+ !db_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&ClearSessionOnlyOrigins,
+ database_,
+ make_scoped_refptr(service_->special_storage_policy()),
+ service()->force_keep_session_state()))) {
+ delete database_;
+ }
+ database_ = NULL; // So no further database tasks can be scheduled.
+}
+
+void AppCacheStorageImpl::Initialize(
+ const base::FilePath& cache_directory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread) {
+ DCHECK(db_thread.get());
+
+ cache_directory_ = cache_directory;
+ is_incognito_ = cache_directory_.empty();
+
+ base::FilePath db_file_path;
+ if (!is_incognito_)
+ db_file_path = cache_directory_.Append(kAppCacheDatabaseName);
+ database_ = new AppCacheDatabase(db_file_path);
+
+ db_thread_ = db_thread;
+ cache_thread_ = cache_thread;
+
+ scoped_refptr<InitTask> task(new InitTask(this));
+ task->Schedule();
+}
+
+void AppCacheStorageImpl::Disable() {
+ if (is_disabled_)
+ return;
+ VLOG(1) << "Disabling appcache storage.";
+ is_disabled_ = true;
+ ClearUsageMapAndNotify();
+ working_set()->Disable();
+ if (disk_cache_)
+ disk_cache_->Disable();
+ scoped_refptr<DisableDatabaseTask> task(new DisableDatabaseTask(this));
+ task->Schedule();
+}
+
+void AppCacheStorageImpl::GetAllInfo(Delegate* delegate) {
+ DCHECK(delegate);
+ scoped_refptr<GetAllInfoTask> task(new GetAllInfoTask(this));
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->Schedule();
+}
+
+void AppCacheStorageImpl::LoadCache(int64 id, Delegate* delegate) {
+ DCHECK(delegate);
+ if (is_disabled_) {
+ delegate->OnCacheLoaded(NULL, id);
+ return;
+ }
+
+ AppCache* cache = working_set_.GetCache(id);
+ if (cache) {
+ delegate->OnCacheLoaded(cache, id);
+ if (cache->owning_group()) {
+ scoped_refptr<DatabaseTask> update_task(
+ new UpdateGroupLastAccessTimeTask(
+ this, cache->owning_group(), base::Time::Now()));
+ update_task->Schedule();
+ }
+ return;
+ }
+ scoped_refptr<CacheLoadTask> task(GetPendingCacheLoadTask(id));
+ if (task.get()) {
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ return;
+ }
+ task = new CacheLoadTask(id, this);
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->Schedule();
+ pending_cache_loads_[id] = task.get();
+}
+
+void AppCacheStorageImpl::LoadOrCreateGroup(
+ const GURL& manifest_url, Delegate* delegate) {
+ DCHECK(delegate);
+ if (is_disabled_) {
+ delegate->OnGroupLoaded(NULL, manifest_url);
+ return;
+ }
+
+ AppCacheGroup* group = working_set_.GetGroup(manifest_url);
+ if (group) {
+ delegate->OnGroupLoaded(group, manifest_url);
+ scoped_refptr<DatabaseTask> update_task(
+ new UpdateGroupLastAccessTimeTask(
+ this, group, base::Time::Now()));
+ update_task->Schedule();
+ return;
+ }
+
+ scoped_refptr<GroupLoadTask> task(GetPendingGroupLoadTask(manifest_url));
+ if (task.get()) {
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ return;
+ }
+
+ if (usage_map_.find(manifest_url.GetOrigin()) == usage_map_.end()) {
+ // No need to query the database, return a new group immediately.
+ scoped_refptr<AppCacheGroup> group(new AppCacheGroup(
+ this, manifest_url, NewGroupId()));
+ delegate->OnGroupLoaded(group.get(), manifest_url);
+ return;
+ }
+
+ task = new GroupLoadTask(manifest_url, this);
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->Schedule();
+ pending_group_loads_[manifest_url] = task.get();
+}
+
+void AppCacheStorageImpl::StoreGroupAndNewestCache(
+ AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) {
+ // TODO(michaeln): distinguish between a simple update of an existing
+ // cache that just adds new master entry(s), and the insertion of a
+ // whole new cache. The StoreGroupAndCacheTask as written will handle
+ // the simple update case in a very heavy weight way (delete all and
+ // the reinsert all over again).
+ DCHECK(group && delegate && newest_cache);
+ scoped_refptr<StoreGroupAndCacheTask> task(
+ new StoreGroupAndCacheTask(this, group, newest_cache));
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->GetQuotaThenSchedule();
+
+ // TODO(michaeln): histogram is fishing for clues to crbug/95101
+ if (!newest_cache->GetEntry(group->manifest_url())) {
+ AppCacheHistograms::AddMissingManifestDetectedAtCallsite(
+ AppCacheHistograms::CALLSITE_3);
+ }
+}
+
+void AppCacheStorageImpl::FindResponseForMainRequest(
+ const GURL& url, const GURL& preferred_manifest_url,
+ Delegate* delegate) {
+ DCHECK(delegate);
+
+ const GURL* url_ptr = &url;
+ GURL url_no_ref;
+ if (url.has_ref()) {
+ GURL::Replacements replacements;
+ replacements.ClearRef();
+ url_no_ref = url.ReplaceComponents(replacements);
+ url_ptr = &url_no_ref;
+ }
+
+ const GURL origin = url.GetOrigin();
+
+ // First look in our working set for a direct hit without having to query
+ // the database.
+ const AppCacheWorkingSet::GroupMap* groups_in_use =
+ working_set()->GetGroupsInOrigin(origin);
+ if (groups_in_use) {
+ if (!preferred_manifest_url.is_empty()) {
+ AppCacheWorkingSet::GroupMap::const_iterator found =
+ groups_in_use->find(preferred_manifest_url);
+ if (found != groups_in_use->end() &&
+ FindResponseForMainRequestInGroup(
+ found->second, *url_ptr, delegate)) {
+ return;
+ }
+ } else {
+ for (AppCacheWorkingSet::GroupMap::const_iterator it =
+ groups_in_use->begin();
+ it != groups_in_use->end(); ++it) {
+ if (FindResponseForMainRequestInGroup(
+ it->second, *url_ptr, delegate)) {
+ return;
+ }
+ }
+ }
+ }
+
+ if (IsInitTaskComplete() && usage_map_.find(origin) == usage_map_.end()) {
+ // No need to query the database, return async'ly but without going thru
+ // the DB thread.
+ scoped_refptr<AppCacheGroup> no_group;
+ scoped_refptr<AppCache> no_cache;
+ ScheduleSimpleTask(
+ base::Bind(&AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
+ weak_factory_.GetWeakPtr(), url, AppCacheEntry(), no_group,
+ no_cache,
+ make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
+ return;
+ }
+
+ // We have to query the database, schedule a database task to do so.
+ scoped_refptr<FindMainResponseTask> task(
+ new FindMainResponseTask(this, *url_ptr, preferred_manifest_url,
+ groups_in_use));
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->Schedule();
+}
+
+bool AppCacheStorageImpl::FindResponseForMainRequestInGroup(
+ AppCacheGroup* group, const GURL& url, Delegate* delegate) {
+ AppCache* cache = group->newest_complete_cache();
+ if (group->is_obsolete() || !cache)
+ return false;
+
+ AppCacheEntry* entry = cache->GetEntry(url);
+ if (!entry || entry->IsForeign())
+ return false;
+
+ ScheduleSimpleTask(
+ base::Bind(&AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
+ weak_factory_.GetWeakPtr(), url, *entry,
+ make_scoped_refptr(group), make_scoped_refptr(cache),
+ make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
+ return true;
+}
+
+void AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse(
+ const GURL& url,
+ const AppCacheEntry& found_entry,
+ scoped_refptr<AppCacheGroup> group,
+ scoped_refptr<AppCache> cache,
+ scoped_refptr<DelegateReference> delegate_ref) {
+ if (delegate_ref->delegate) {
+ DelegateReferenceVector delegates(1, delegate_ref);
+ CallOnMainResponseFound(
+ &delegates, url, found_entry,
+ GURL(), AppCacheEntry(),
+ cache.get() ? cache->cache_id() : kAppCacheNoCacheId,
+ group.get() ? group->group_id() : kAppCacheNoCacheId,
+ group.get() ? group->manifest_url() : GURL());
+ }
+}
+
+void AppCacheStorageImpl::CallOnMainResponseFound(
+ DelegateReferenceVector* delegates,
+ const GURL& url, const AppCacheEntry& entry,
+ const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
+ int64 cache_id, int64 group_id, const GURL& manifest_url) {
+ FOR_EACH_DELEGATE(
+ (*delegates),
+ OnMainResponseFound(url, entry,
+ namespace_entry_url, fallback_entry,
+ cache_id, group_id, manifest_url));
+}
+
+void AppCacheStorageImpl::FindResponseForSubRequest(
+ AppCache* cache, const GURL& url,
+ AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
+ bool* found_network_namespace) {
+ DCHECK(cache && cache->is_complete());
+
+ // When a group is forcibly deleted, all subresource loads for pages
+ // using caches in the group will result in a synthesized network errors.
+ // Forcible deletion is not a function that is covered by the HTML5 spec.
+ if (cache->owning_group()->is_being_deleted()) {
+ *found_entry = AppCacheEntry();
+ *found_fallback_entry = AppCacheEntry();
+ *found_network_namespace = false;
+ return;
+ }
+
+ GURL fallback_namespace_not_used;
+ GURL intercept_namespace_not_used;
+ cache->FindResponseForRequest(
+ url, found_entry, &intercept_namespace_not_used,
+ found_fallback_entry, &fallback_namespace_not_used,
+ found_network_namespace);
+}
+
+void AppCacheStorageImpl::MarkEntryAsForeign(
+ const GURL& entry_url, int64 cache_id) {
+ AppCache* cache = working_set_.GetCache(cache_id);
+ if (cache) {
+ AppCacheEntry* entry = cache->GetEntry(entry_url);
+ DCHECK(entry);
+ if (entry)
+ entry->add_types(AppCacheEntry::FOREIGN);
+ }
+ scoped_refptr<MarkEntryAsForeignTask> task(
+ new MarkEntryAsForeignTask(this, entry_url, cache_id));
+ task->Schedule();
+ pending_foreign_markings_.push_back(std::make_pair(entry_url, cache_id));
+}
+
+void AppCacheStorageImpl::MakeGroupObsolete(AppCacheGroup* group,
+ Delegate* delegate,
+ int response_code) {
+ DCHECK(group && delegate);
+ scoped_refptr<MakeGroupObsoleteTask> task(
+ new MakeGroupObsoleteTask(this, group, response_code));
+ task->AddDelegate(GetOrCreateDelegateReference(delegate));
+ task->Schedule();
+}
+
+AppCacheResponseReader* AppCacheStorageImpl::CreateResponseReader(
+ const GURL& manifest_url, int64 group_id, int64 response_id) {
+ return new AppCacheResponseReader(response_id, group_id, disk_cache());
+}
+
+AppCacheResponseWriter* AppCacheStorageImpl::CreateResponseWriter(
+ const GURL& manifest_url, int64 group_id) {
+ return new AppCacheResponseWriter(NewResponseId(), group_id, disk_cache());
+}
+
+void AppCacheStorageImpl::DoomResponses(
+ const GURL& manifest_url, const std::vector<int64>& response_ids) {
+ if (response_ids.empty())
+ return;
+
+ // Start deleting them from the disk cache lazily.
+ StartDeletingResponses(response_ids);
+
+ // Also schedule a database task to record these ids in the
+ // deletable responses table.
+ // TODO(michaeln): There is a race here. If the browser crashes
+ // prior to committing these rows to the database and prior to us
+ // having deleted them from the disk cache, we'll never delete them.
+ scoped_refptr<InsertDeletableResponseIdsTask> task(
+ new InsertDeletableResponseIdsTask(this));
+ task->response_ids_ = response_ids;
+ task->Schedule();
+}
+
+void AppCacheStorageImpl::DeleteResponses(
+ const GURL& manifest_url, const std::vector<int64>& response_ids) {
+ if (response_ids.empty())
+ return;
+ StartDeletingResponses(response_ids);
+}
+
+void AppCacheStorageImpl::DelayedStartDeletingUnusedResponses() {
+ // Only if we haven't already begun.
+ if (!did_start_deleting_responses_) {
+ scoped_refptr<GetDeletableResponseIdsTask> task(
+ new GetDeletableResponseIdsTask(this, last_deletable_response_rowid_));
+ task->Schedule();
+ }
+}
+
+void AppCacheStorageImpl::StartDeletingResponses(
+ const std::vector<int64>& response_ids) {
+ DCHECK(!response_ids.empty());
+ did_start_deleting_responses_ = true;
+ deletable_response_ids_.insert(
+ deletable_response_ids_.end(),
+ response_ids.begin(), response_ids.end());
+ if (!is_response_deletion_scheduled_)
+ ScheduleDeleteOneResponse();
+}
+
+void AppCacheStorageImpl::ScheduleDeleteOneResponse() {
+ DCHECK(!is_response_deletion_scheduled_);
+ const base::TimeDelta kDelay = base::TimeDelta::FromMilliseconds(10);
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&AppCacheStorageImpl::DeleteOneResponse,
+ weak_factory_.GetWeakPtr()),
+ kDelay);
+ is_response_deletion_scheduled_ = true;
+}
+
+void AppCacheStorageImpl::DeleteOneResponse() {
+ DCHECK(is_response_deletion_scheduled_);
+ DCHECK(!deletable_response_ids_.empty());
+
+ if (!disk_cache()) {
+ DCHECK(is_disabled_);
+ deletable_response_ids_.clear();
+ deleted_response_ids_.clear();
+ is_response_deletion_scheduled_ = false;
+ return;
+ }
+
+ // TODO(michaeln): add group_id to DoomEntry args
+ int64 id = deletable_response_ids_.front();
+ int rv = disk_cache_->DoomEntry(
+ id, base::Bind(&AppCacheStorageImpl::OnDeletedOneResponse,
+ base::Unretained(this)));
+ if (rv != net::ERR_IO_PENDING)
+ OnDeletedOneResponse(rv);
+}
+
+void AppCacheStorageImpl::OnDeletedOneResponse(int rv) {
+ is_response_deletion_scheduled_ = false;
+ if (is_disabled_)
+ return;
+
+ int64 id = deletable_response_ids_.front();
+ deletable_response_ids_.pop_front();
+ if (rv != net::ERR_ABORTED)
+ deleted_response_ids_.push_back(id);
+
+ const size_t kBatchSize = 50U;
+ if (deleted_response_ids_.size() >= kBatchSize ||
+ deletable_response_ids_.empty()) {
+ scoped_refptr<DeleteDeletableResponseIdsTask> task(
+ new DeleteDeletableResponseIdsTask(this));
+ task->response_ids_.swap(deleted_response_ids_);
+ task->Schedule();
+ }
+
+ if (deletable_response_ids_.empty()) {
+ scoped_refptr<GetDeletableResponseIdsTask> task(
+ new GetDeletableResponseIdsTask(this, last_deletable_response_rowid_));
+ task->Schedule();
+ return;
+ }
+
+ ScheduleDeleteOneResponse();
+}
+
+AppCacheStorageImpl::CacheLoadTask*
+AppCacheStorageImpl::GetPendingCacheLoadTask(int64 cache_id) {
+ PendingCacheLoads::iterator found = pending_cache_loads_.find(cache_id);
+ if (found != pending_cache_loads_.end())
+ return found->second;
+ return NULL;
+}
+
+AppCacheStorageImpl::GroupLoadTask*
+AppCacheStorageImpl::GetPendingGroupLoadTask(const GURL& manifest_url) {
+ PendingGroupLoads::iterator found = pending_group_loads_.find(manifest_url);
+ if (found != pending_group_loads_.end())
+ return found->second;
+ return NULL;
+}
+
+void AppCacheStorageImpl::GetPendingForeignMarkingsForCache(
+ int64 cache_id, std::vector<GURL>* urls) {
+ PendingForeignMarkings::iterator iter = pending_foreign_markings_.begin();
+ while (iter != pending_foreign_markings_.end()) {
+ if (iter->second == cache_id)
+ urls->push_back(iter->first);
+ ++iter;
+ }
+}
+
+void AppCacheStorageImpl::ScheduleSimpleTask(const base::Closure& task) {
+ pending_simple_tasks_.push_back(task);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AppCacheStorageImpl::RunOnePendingSimpleTask,
+ weak_factory_.GetWeakPtr()));
+}
+
+void AppCacheStorageImpl::RunOnePendingSimpleTask() {
+ DCHECK(!pending_simple_tasks_.empty());
+ base::Closure task = pending_simple_tasks_.front();
+ pending_simple_tasks_.pop_front();
+ task.Run();
+}
+
+AppCacheDiskCache* AppCacheStorageImpl::disk_cache() {
+ DCHECK(IsInitTaskComplete());
+
+ if (is_disabled_)
+ return NULL;
+
+ if (!disk_cache_) {
+ int rv = net::OK;
+ disk_cache_.reset(new AppCacheDiskCache);
+ if (is_incognito_) {
+ rv = disk_cache_->InitWithMemBackend(
+ kMaxMemDiskCacheSize,
+ base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized,
+ base::Unretained(this)));
+ } else {
+ rv = disk_cache_->InitWithDiskBackend(
+ cache_directory_.Append(kDiskCacheDirectoryName),
+ kMaxDiskCacheSize,
+ false,
+ cache_thread_.get(),
+ base::Bind(&AppCacheStorageImpl::OnDiskCacheInitialized,
+ base::Unretained(this)));
+ }
+
+ if (rv != net::ERR_IO_PENDING)
+ OnDiskCacheInitialized(rv);
+ }
+ return disk_cache_.get();
+}
+
+void AppCacheStorageImpl::OnDiskCacheInitialized(int rv) {
+ if (rv != net::OK) {
+ LOG(ERROR) << "Failed to open the appcache diskcache.";
+ AppCacheHistograms::CountInitResult(AppCacheHistograms::DISK_CACHE_ERROR);
+
+ // We're unable to open the disk cache, this is a fatal error that we can't
+ // really recover from. We handle it by temporarily disabling the appcache
+ // deleting the directory on disk and reinitializing the appcache system.
+ Disable();
+ if (rv != net::ERR_ABORTED)
+ DeleteAndStartOver();
+ }
+}
+
+void AppCacheStorageImpl::DeleteAndStartOver() {
+ DCHECK(is_disabled_);
+ if (!is_incognito_) {
+ VLOG(1) << "Deleting existing appcache data and starting over.";
+ // We can have tasks in flight to close file handles on both the db
+ // and cache threads, we need to allow those tasks to cycle thru
+ // prior to deleting the files and calling reinit.
+ cache_thread_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&base::DoNothing),
+ base::Bind(&AppCacheStorageImpl::DeleteAndStartOverPart2,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+void AppCacheStorageImpl::DeleteAndStartOverPart2() {
+ db_thread_->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&base::DeleteFile), cache_directory_, true),
+ base::Bind(&AppCacheStorageImpl::CallScheduleReinitialize,
+ weak_factory_.GetWeakPtr()));
+}
+
+void AppCacheStorageImpl::CallScheduleReinitialize() {
+ service_->ScheduleReinitialize();
+ // note: 'this' may be deleted at this point.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.h b/chromium/content/browser/appcache/appcache_storage_impl.h
new file mode 100644
index 00000000000..ca6d76b314b
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_storage_impl.h
@@ -0,0 +1,183 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
+
+#include <deque>
+#include <map>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/appcache/appcache_database.h"
+#include "content/browser/appcache/appcache_disk_cache.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/common/content_export.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
+namespace content {
+class AppCacheStorageImplTest;
+class ChromeAppCacheServiceTest;
+
+class AppCacheStorageImpl : public AppCacheStorage {
+ public:
+ explicit AppCacheStorageImpl(AppCacheServiceImpl* service);
+ ~AppCacheStorageImpl() override;
+
+ void Initialize(
+ const base::FilePath& cache_directory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& db_thread,
+ const scoped_refptr<base::SingleThreadTaskRunner>& cache_thread);
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
+
+ // AppCacheStorage methods, see the base class for doc comments.
+ void GetAllInfo(Delegate* delegate) override;
+ void LoadCache(int64 id, Delegate* delegate) override;
+ void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate) override;
+ void StoreGroupAndNewestCache(AppCacheGroup* group,
+ AppCache* newest_cache,
+ Delegate* delegate) override;
+ void FindResponseForMainRequest(const GURL& url,
+ const GURL& preferred_manifest_url,
+ Delegate* delegate) override;
+ void FindResponseForSubRequest(AppCache* cache,
+ const GURL& url,
+ AppCacheEntry* found_entry,
+ AppCacheEntry* found_fallback_entry,
+ bool* found_network_namespace) override;
+ void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) override;
+ void MakeGroupObsolete(AppCacheGroup* group,
+ Delegate* delegate,
+ int response_code) override;
+ AppCacheResponseReader* CreateResponseReader(const GURL& manifest_url,
+ int64 group_id,
+ int64 response_id) override;
+ AppCacheResponseWriter* CreateResponseWriter(const GURL& manifest_url,
+ int64 group_id) override;
+ void DoomResponses(const GURL& manifest_url,
+ const std::vector<int64>& response_ids) override;
+ void DeleteResponses(const GURL& manifest_url,
+ const std::vector<int64>& response_ids) override;
+
+ private:
+ // The AppCacheStorageImpl class methods and datamembers may only be
+ // accessed on the IO thread. This class manufactures seperate DatabaseTasks
+ // which access the DB on a seperate background thread.
+ class DatabaseTask;
+ class InitTask;
+ class DisableDatabaseTask;
+ class GetAllInfoTask;
+ class StoreOrLoadTask;
+ class CacheLoadTask;
+ class GroupLoadTask;
+ class StoreGroupAndCacheTask;
+ class FindMainResponseTask;
+ class MarkEntryAsForeignTask;
+ class MakeGroupObsoleteTask;
+ class GetDeletableResponseIdsTask;
+ class InsertDeletableResponseIdsTask;
+ class DeleteDeletableResponseIdsTask;
+ class UpdateGroupLastAccessTimeTask;
+
+ typedef std::deque<DatabaseTask*> DatabaseTaskQueue;
+ typedef std::map<int64, CacheLoadTask*> PendingCacheLoads;
+ typedef std::map<GURL, GroupLoadTask*> PendingGroupLoads;
+ typedef std::deque<std::pair<GURL, int64> > PendingForeignMarkings;
+ typedef std::set<StoreGroupAndCacheTask*> PendingQuotaQueries;
+
+ bool IsInitTaskComplete() {
+ return last_cache_id_ != AppCacheStorage::kUnitializedId;
+ }
+
+ CacheLoadTask* GetPendingCacheLoadTask(int64 cache_id);
+ GroupLoadTask* GetPendingGroupLoadTask(const GURL& manifest_url);
+ void GetPendingForeignMarkingsForCache(
+ int64 cache_id, std::vector<GURL>* urls);
+
+ void ScheduleSimpleTask(const base::Closure& task);
+ void RunOnePendingSimpleTask();
+
+ void DelayedStartDeletingUnusedResponses();
+ void StartDeletingResponses(const std::vector<int64>& response_ids);
+ void ScheduleDeleteOneResponse();
+ void DeleteOneResponse();
+
+ void OnDeletedOneResponse(int rv);
+ void OnDiskCacheInitialized(int rv);
+ void DeleteAndStartOver();
+ void DeleteAndStartOverPart2();
+ void CallScheduleReinitialize();
+
+ // Sometimes we can respond without having to query the database.
+ bool FindResponseForMainRequestInGroup(
+ AppCacheGroup* group, const GURL& url, Delegate* delegate);
+ void DeliverShortCircuitedFindMainResponse(
+ const GURL& url,
+ const AppCacheEntry& found_entry,
+ scoped_refptr<AppCacheGroup> group,
+ scoped_refptr<AppCache> newest_cache,
+ scoped_refptr<DelegateReference> delegate_ref);
+
+ void CallOnMainResponseFound(
+ DelegateReferenceVector* delegates,
+ const GURL& url, const AppCacheEntry& entry,
+ const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
+ int64 cache_id, int64 group_id, const GURL& manifest_url);
+
+ CONTENT_EXPORT AppCacheDiskCache* disk_cache();
+
+ // The directory in which we place files in the file system.
+ base::FilePath cache_directory_;
+ bool is_incognito_;
+
+ // This class operates primarily on the IO thread, but schedules
+ // its DatabaseTasks on the db thread. Separately, the disk_cache uses
+ // the cache thread.
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> cache_thread_;
+
+ // Structures to keep track of DatabaseTasks that are in-flight.
+ DatabaseTaskQueue scheduled_database_tasks_;
+ PendingCacheLoads pending_cache_loads_;
+ PendingGroupLoads pending_group_loads_;
+ PendingForeignMarkings pending_foreign_markings_;
+ PendingQuotaQueries pending_quota_queries_;
+
+ // Structures to keep track of lazy response deletion.
+ std::deque<int64> deletable_response_ids_;
+ std::vector<int64> deleted_response_ids_;
+ bool is_response_deletion_scheduled_;
+ bool did_start_deleting_responses_;
+ int64 last_deletable_response_rowid_;
+
+ // Created on the IO thread, but only used on the DB thread.
+ AppCacheDatabase* database_;
+
+ // Set if we discover a fatal error like a corrupt SQL database or
+ // disk cache and cannot continue.
+ bool is_disabled_;
+
+ scoped_ptr<AppCacheDiskCache> disk_cache_;
+
+ // Used to short-circuit certain operations without having to schedule
+ // any tasks on the background database thread.
+ std::deque<base::Closure> pending_simple_tasks_;
+ base::WeakPtrFactory<AppCacheStorageImpl> weak_factory_;
+
+ friend class content::AppCacheStorageImplTest;
+ friend class content::ChromeAppCacheServiceTest;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_STORAGE_IMPL_H_
diff --git a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
index 4c467a1a2dc..330d9aba390 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl_unittest.cc
@@ -7,13 +7,22 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_backend_impl.h"
+#include "content/browser/appcache/appcache_database.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/appcache_interceptor.h"
+#include "content/browser/appcache/appcache_request_handler.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage_impl.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
@@ -22,40 +31,8 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "sql/test/test_helpers.h"
+#include "storage/browser/quota/quota_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_backend_impl.h"
-#include "webkit/browser/appcache/appcache_database.h"
-#include "webkit/browser/appcache/appcache_entry.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_host.h"
-#include "webkit/browser/appcache/appcache_request_handler.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
-#include "webkit/browser/appcache/appcache_storage_impl.h"
-#include "webkit/browser/quota/quota_manager.h"
-
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::APPCACHE_NETWORK_NAMESPACE;
-using appcache::AppCacheBackendImpl;
-using appcache::AppCacheDatabase;
-using appcache::AppCacheEntry;
-using appcache::AppCacheFrontend;
-using appcache::AppCacheHost;
-using appcache::AppCacheInfo;
-using appcache::AppCacheGroup;
-using appcache::AppCacheServiceImpl;
-using appcache::AppCacheStorage;
-using appcache::AppCacheStorageImpl;
-using appcache::AppCacheStorageReference;
-using appcache::AppCache;
-using appcache::AppCacheErrorDetails;
-using appcache::AppCacheEventID;
-using appcache::kAppCacheNoCacheId;
-using appcache::kAppCacheNoResponseId;
-using appcache::APPCACHE_INTERCEPT_NAMESPACE;
-using appcache::AppCacheLogLevel;
-using appcache::Namespace;
-using appcache::AppCacheStatus;
namespace content {
@@ -149,11 +126,23 @@ class MockHttpServer {
class MockHttpServerJobFactory
: public net::URLRequestJobFactory::ProtocolHandler {
public:
- virtual net::URLRequestJob* MaybeCreateJob(
+ MockHttpServerJobFactory(
+ scoped_ptr<net::URLRequestInterceptor> appcache_start_interceptor)
+ : appcache_start_interceptor_(appcache_start_interceptor.Pass()) {
+ }
+
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
+ net::URLRequestJob* appcache_job =
+ appcache_start_interceptor_->MaybeInterceptRequest(
+ request, network_delegate);
+ if (appcache_job)
+ return appcache_job;
return MockHttpServer::CreateJob(request, network_delegate);
}
+ private:
+ scoped_ptr<net::URLRequestInterceptor> appcache_start_interceptor_;
};
class IOThread : public base::Thread {
@@ -162,25 +151,26 @@ class IOThread : public base::Thread {
: base::Thread(name) {
}
- virtual ~IOThread() {
- Stop();
- }
+ ~IOThread() override { Stop(); }
net::URLRequestContext* request_context() {
return request_context_.get();
}
- virtual void Init() OVERRIDE {
+ void Init() override {
scoped_ptr<net::URLRequestJobFactoryImpl> factory(
new net::URLRequestJobFactoryImpl());
- factory->SetProtocolHandler("http", new MockHttpServerJobFactory);
+ factory->SetProtocolHandler(
+ "http",
+ new MockHttpServerJobFactory(
+ AppCacheInterceptor::CreateStartInterceptor()));
job_factory_ = factory.Pass();
request_context_.reset(new net::TestURLRequestContext());
request_context_->set_job_factory(job_factory_.get());
AppCacheInterceptor::EnsureRegistered();
}
- virtual void CleanUp() OVERRIDE {
+ void CleanUp() override {
request_context_.reset();
job_factory_.reset();
}
@@ -205,14 +195,14 @@ class AppCacheStorageImplTest : public testing::Test {
found_cache_id_(kAppCacheNoCacheId), test_(test) {
}
- virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE {
+ void OnCacheLoaded(AppCache* cache, int64 cache_id) override {
loaded_cache_ = cache;
loaded_cache_id_ = cache_id;
test_->ScheduleNextTask();
}
- virtual void OnGroupLoaded(AppCacheGroup* group,
- const GURL& manifest_url) OVERRIDE {
+ void OnGroupLoaded(AppCacheGroup* group,
+ const GURL& manifest_url) override {
loaded_group_ = group;
loaded_manifest_url_ = manifest_url;
loaded_groups_newest_cache_ = group ? group->newest_complete_cache()
@@ -220,30 +210,31 @@ class AppCacheStorageImplTest : public testing::Test {
test_->ScheduleNextTask();
}
- virtual void OnGroupAndNewestCacheStored(
- AppCacheGroup* group, AppCache* newest_cache, bool success,
- bool would_exceed_quota) OVERRIDE {
+ void OnGroupAndNewestCacheStored(AppCacheGroup* group,
+ AppCache* newest_cache,
+ bool success,
+ bool would_exceed_quota) override {
stored_group_ = group;
stored_group_success_ = success;
would_exceed_quota_ = would_exceed_quota;
test_->ScheduleNextTask();
}
- virtual void OnGroupMadeObsolete(AppCacheGroup* group,
- bool success,
- int response_code) OVERRIDE {
+ void OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) override {
obsoleted_group_ = group;
obsoleted_success_ = success;
test_->ScheduleNextTask();
}
- virtual void OnMainResponseFound(const GURL& url,
- const AppCacheEntry& entry,
- const GURL& namespace_entry_url,
- const AppCacheEntry& fallback_entry,
- int64 cache_id,
- int64 group_id,
- const GURL& manifest_url) OVERRIDE {
+ void OnMainResponseFound(const GURL& url,
+ const AppCacheEntry& entry,
+ const GURL& namespace_entry_url,
+ const AppCacheEntry& fallback_entry,
+ int64 cache_id,
+ int64 group_id,
+ const GURL& manifest_url) override {
found_url_ = url;
found_entry_ = entry;
found_namespace_entry_url_ = namespace_entry_url;
@@ -274,7 +265,7 @@ class AppCacheStorageImplTest : public testing::Test {
AppCacheStorageImplTest* test_;
};
- class MockQuotaManager : public quota::QuotaManager {
+ class MockQuotaManager : public storage::QuotaManager {
public:
MockQuotaManager()
: QuotaManager(true /* is_incognito */,
@@ -284,11 +275,10 @@ class AppCacheStorageImplTest : public testing::Test {
NULL),
async_(false) {}
- virtual void GetUsageAndQuota(
- const GURL& origin,
- quota::StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE {
- EXPECT_EQ(quota::kStorageTypeTemporary, type);
+ void GetUsageAndQuota(const GURL& origin,
+ storage::StorageType type,
+ const GetUsageAndQuotaCallback& callback) override {
+ EXPECT_EQ(storage::kStorageTypeTemporary, type);
if (async_) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -301,16 +291,16 @@ class AppCacheStorageImplTest : public testing::Test {
}
void CallCallback(const GetUsageAndQuotaCallback& callback) {
- callback.Run(quota::kQuotaStatusOk, 0, kMockQuota);
+ callback.Run(storage::kQuotaStatusOk, 0, kMockQuota);
}
bool async_;
protected:
- virtual ~MockQuotaManager() {}
+ ~MockQuotaManager() override {}
};
- class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
+ class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
public:
MockQuotaManagerProxy()
: QuotaManagerProxy(NULL, NULL),
@@ -321,39 +311,38 @@ class AppCacheStorageImplTest : public testing::Test {
manager_ = mock_manager_.get();
}
- virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type) OVERRIDE {
- EXPECT_EQ(quota::QuotaClient::kAppcache, client_id);
- EXPECT_EQ(quota::kStorageTypeTemporary, type);
+ void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type) override {
+ EXPECT_EQ(storage::QuotaClient::kAppcache, client_id);
+ EXPECT_EQ(storage::kStorageTypeTemporary, type);
++notify_storage_accessed_count_;
last_origin_ = origin;
}
- virtual void NotifyStorageModified(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- int64 delta) OVERRIDE {
- EXPECT_EQ(quota::QuotaClient::kAppcache, client_id);
- EXPECT_EQ(quota::kStorageTypeTemporary, type);
+ void NotifyStorageModified(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ int64 delta) override {
+ EXPECT_EQ(storage::QuotaClient::kAppcache, client_id);
+ EXPECT_EQ(storage::kStorageTypeTemporary, type);
++notify_storage_modified_count_;
last_origin_ = origin;
last_delta_ = delta;
}
// Not needed for our tests.
- virtual void RegisterClient(quota::QuotaClient* client) OVERRIDE {}
- virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
- virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
- virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- bool enabled) OVERRIDE {}
- virtual void GetUsageAndQuota(
- base::SequencedTaskRunner* original_task_runner,
- const GURL& origin,
- quota::StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE {}
+ void RegisterClient(storage::QuotaClient* client) override {}
+ void NotifyOriginInUse(const GURL& origin) override {}
+ void NotifyOriginNoLongerInUse(const GURL& origin) override {}
+ void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ bool enabled) override {}
+ void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
+ const GURL& origin,
+ storage::StorageType type,
+ const GetUsageAndQuotaCallback& callback) override {}
int notify_storage_accessed_count_;
int notify_storage_modified_count_;
@@ -362,7 +351,7 @@ class AppCacheStorageImplTest : public testing::Test {
scoped_refptr<MockQuotaManager> mock_manager_;
protected:
- virtual ~MockQuotaManagerProxy() {}
+ ~MockQuotaManagerProxy() override {}
};
template <class Method>
@@ -421,8 +410,7 @@ class AppCacheStorageImplTest : public testing::Test {
void SetUpTest() {
DCHECK(base::MessageLoop::current() == io_thread->message_loop());
service_.reset(new AppCacheServiceImpl(NULL));
- service_->Initialize(
- base::FilePath(), db_thread->message_loop_proxy().get(), NULL);
+ service_->Initialize(base::FilePath(), db_thread->task_runner(), NULL);
mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
delegate_.reset(new MockStorageDelegate(this));
@@ -734,7 +722,7 @@ class AppCacheStorageImplTest : public testing::Test {
base::Unretained(this), now));
// Conduct the test.
- EXPECT_EQ(cache_, group_->newest_complete_cache());
+ EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
EXPECT_FALSE(delegate()->stored_group_success_);
}
@@ -742,7 +730,7 @@ class AppCacheStorageImplTest : public testing::Test {
void Verify_StoreExistingGroupExistingCache(
base::Time expected_update_time) {
EXPECT_TRUE(delegate()->stored_group_success_);
- EXPECT_EQ(cache_, group_->newest_complete_cache());
+ EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
AppCacheDatabase::CacheRecord cache_record;
EXPECT_TRUE(database()->FindCache(1, &cache_record));
@@ -1054,12 +1042,12 @@ class AppCacheStorageImplTest : public testing::Test {
cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
cache_->fallback_namespaces_.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
kFallbackNamespace2,
kEntryUrl2,
false));
cache_->fallback_namespaces_.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
kFallbackNamespace,
kEntryUrl,
false));
@@ -1132,10 +1120,10 @@ class AppCacheStorageImplTest : public testing::Test {
cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::INTERCEPT, 2));
cache_->intercept_namespaces_.push_back(
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace2,
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace2,
kEntryUrl2, false));
cache_->intercept_namespaces_.push_back(
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace,
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace,
kEntryUrl, false));
AppCacheDatabase::CacheRecord cache_record;
std::vector<AppCacheDatabase::EntryRecord> entries;
@@ -1202,8 +1190,8 @@ class AppCacheStorageImplTest : public testing::Test {
MakeCacheAndGroup(kManifestUrl, 2, 1, true);
cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
cache_->intercept_namespaces_.push_back(
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptPatternNamespace,
- kEntryUrl, true));
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
+ kInterceptPatternNamespace, kEntryUrl, true));
AppCacheDatabase::CacheRecord cache_record;
std::vector<AppCacheDatabase::EntryRecord> entries;
std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
@@ -1289,8 +1277,8 @@ class AppCacheStorageImplTest : public testing::Test {
MakeCacheAndGroup(kManifestUrl, 2, 1, true);
cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
cache_->fallback_namespaces_.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackPatternNamespace,
- kEntryUrl, true));
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
+ kFallbackPatternNamespace, kEntryUrl, true));
AppCacheDatabase::CacheRecord cache_record;
std::vector<AppCacheDatabase::EntryRecord> entries;
std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
@@ -1420,7 +1408,7 @@ class AppCacheStorageImplTest : public testing::Test {
fallback_namespace_record.origin = manifest_url.GetOrigin();
EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
cache_->fallback_namespaces_.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
kFallbackNamespace,
kEntryUrl2,
false));
@@ -1435,7 +1423,7 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
- // Conduct another test perferring kManifestUrl
+ // Conduct another test preferring kManifestUrl
delegate_.reset(new MockStorageDelegate(this));
PushNextTask(base::Bind(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits2,
@@ -1453,7 +1441,7 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
- // Conduct the another test perferring kManifestUrl2
+ // Conduct the another test preferring kManifestUrl2
delegate_.reset(new MockStorageDelegate(this));
PushNextTask(base::Bind(
&AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits3,
@@ -1535,16 +1523,16 @@ class AppCacheStorageImplTest : public testing::Test {
AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, 1));
cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
cache_->fallback_namespaces_.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
kFallbackNamespace,
kEntryUrl2,
false));
cache_->online_whitelist_namespaces_.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespace,
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespace,
GURL(), false));
cache_->online_whitelist_namespaces_.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceWithinFallback,
- GURL(), false));
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE,
+ kOnlineNamespaceWithinFallback, GURL(), false));
AppCacheDatabase::EntryRecord entry_record;
entry_record.cache_id = 1;
@@ -1622,8 +1610,8 @@ class AppCacheStorageImplTest : public testing::Test {
explicit MockServiceObserver(AppCacheStorageImplTest* test)
: test_(test) {}
- virtual void OnServiceReinitialized(
- AppCacheStorageReference* old_storage_ref) OVERRIDE {
+ void OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) override {
observed_old_storage_ = old_storage_ref;
test_->ScheduleNextTask();
}
@@ -1636,25 +1624,23 @@ class AppCacheStorageImplTest : public testing::Test {
public:
MockAppCacheFrontend() : error_event_was_raised_(false) {}
- virtual void OnCacheSelected(
- int host_id, const AppCacheInfo& info) OVERRIDE {}
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- AppCacheStatus status) OVERRIDE {}
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- AppCacheEventID event_id) OVERRIDE {}
- virtual void OnProgressEventRaised(
- const std::vector<int>& host_ids,
- const GURL& url,
- int num_total, int num_complete) OVERRIDE {}
- virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
- const AppCacheErrorDetails& details)
- OVERRIDE {
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override {}
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override {}
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override {}
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override {}
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override {
error_event_was_raised_ = true;
}
- virtual void OnLogMessage(int host_id, AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE {}
- virtual void OnContentBlocked(
- int host_id, const GURL& manifest_url) OVERRIDE {}
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override {}
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override {}
bool error_event_was_raised_;
};
@@ -1733,10 +1719,9 @@ class AppCacheStorageImplTest : public testing::Test {
// Recreate the service to point at the db and corruption on disk.
service_.reset(new AppCacheServiceImpl(NULL));
service_->set_request_context(io_thread->request_context());
- service_->Initialize(
- temp_directory_.path(),
- db_thread->message_loop_proxy().get(),
- db_thread->message_loop_proxy().get());
+ service_->Initialize(temp_directory_.path(),
+ db_thread->task_runner(),
+ db_thread->task_runner());
mock_quota_manager_proxy_ = new MockQuotaManagerProxy();
service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
delegate_.reset(new MockStorageDelegate(this));
@@ -1791,7 +1776,7 @@ class AppCacheStorageImplTest : public testing::Test {
AppCacheInterceptor::SetExtraRequestInfo(
request_.get(), service_.get(),
backend_->process_id(), host2->host_id(),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
request_->Start();
}
@@ -1823,7 +1808,7 @@ class AppCacheStorageImplTest : public testing::Test {
EXPECT_TRUE(frontend_.error_event_was_raised_);
AppCacheHost* host1 = backend_->GetHost(1);
EXPECT_FALSE(host1->associated_cache());
- EXPECT_FALSE(host1->group_being_updated_);
+ EXPECT_FALSE(host1->group_being_updated_.get());
EXPECT_TRUE(host1->disabled_storage_reference_.get());
} else {
ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
diff --git a/chromium/content/browser/appcache/appcache_storage_unittest.cc b/chromium/content/browser/appcache/appcache_storage_unittest.cc
index fa696968e72..c6b50bf043a 100644
--- a/chromium/content/browser/appcache/appcache_storage_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_storage_unittest.cc
@@ -3,24 +3,18 @@
// found in the LICENSE file.
#include "base/message_loop/message_loop.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_storage.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_storage.h"
-
-using appcache::AppCache;
-using appcache::AppCacheGroup;
-using appcache::AppCacheResponseInfo;
-using appcache::AppCacheStorage;
-using appcache::kUnkownResponseDataSize;
namespace content {
namespace {
-const quota::StorageType kTemp = quota::kStorageTypeTemporary;
+const storage::StorageType kTemp = storage::kStorageTypeTemporary;
}
class AppCacheStorageTest : public testing::Test {
diff --git a/chromium/content/browser/appcache/appcache_unittest.cc b/chromium/content/browser/appcache/appcache_unittest.cc
index 32c4e89dee0..4062498e95e 100644
--- a/chromium/content/browser/appcache/appcache_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_unittest.cc
@@ -2,30 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_host.h"
-
-using appcache::AppCache;
-using appcache::AppCacheDatabase;
-using appcache::AppCacheEntry;
-using appcache::AppCacheFrontend;
-using appcache::AppCacheGroup;
-using appcache::AppCacheHost;
-using appcache::AppCacheInfo;
-using appcache::AppCacheErrorDetails;
-using appcache::AppCacheEventID;
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::APPCACHE_INTERCEPT_NAMESPACE;
-using appcache::AppCacheLogLevel;
-using appcache::Manifest;
-using appcache::Namespace;
-using appcache::NamespaceVector;
-using appcache::APPCACHE_NETWORK_NAMESPACE;
-using appcache::PARSE_MANIFEST_ALLOWING_INTERCEPTS;
-using appcache::PARSE_MANIFEST_PER_STANDARD;
-using appcache::AppCacheStatus;
namespace content {
@@ -33,23 +13,21 @@ namespace {
class MockAppCacheFrontend : public AppCacheFrontend {
public:
- virtual void OnCacheSelected(int host_id, const AppCacheInfo& info) OVERRIDE {
- }
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- AppCacheStatus status) OVERRIDE {}
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- AppCacheEventID event_id) OVERRIDE {}
- virtual void OnProgressEventRaised(
- const std::vector<int>& host_ids,
- const GURL& url,
- int num_total, int num_complete) OVERRIDE {}
- virtual void OnErrorEventRaised(
- const std::vector<int>& host_ids,
- const AppCacheErrorDetails& details) OVERRIDE {}
- virtual void OnLogMessage(int host_id, AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE {}
- virtual void OnContentBlocked(
- int host_id, const GURL& manifest_url) OVERRIDE {}
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override {}
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override {}
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override {}
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override {}
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override {}
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override {}
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override {}
};
} // namespace
@@ -128,27 +106,30 @@ TEST(AppCacheTest, InitializeWithManifest) {
EXPECT_TRUE(cache->online_whitelist_namespaces_.empty());
EXPECT_FALSE(cache->online_whitelist_all_);
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.explicit_urls.insert("http://one.com");
manifest.explicit_urls.insert("http://two.com");
manifest.fallback_namespaces.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, GURL("http://fb1.com"),
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, GURL("http://fb1.com"),
GURL("http://fbone.com"), true));
manifest.online_whitelist_namespaces.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, GURL("http://w1.com"), GURL(), false));
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, GURL("http://w1.com"),
+ GURL(), false));
manifest.online_whitelist_namespaces.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, GURL("http://w2.com"), GURL(), false));
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, GURL("http://w2.com"),
+ GURL(), false));
manifest.online_whitelist_all = true;
cache->InitializeWithManifest(&manifest);
- const std::vector<Namespace>& fallbacks =
+ const std::vector<AppCacheNamespace>& fallbacks =
cache->fallback_namespaces_;
size_t expected = 1;
EXPECT_EQ(expected, fallbacks.size());
EXPECT_EQ(GURL("http://fb1.com"), fallbacks[0].namespace_url);
EXPECT_EQ(GURL("http://fbone.com"), fallbacks[0].target_url);
EXPECT_TRUE(fallbacks[0].is_pattern);
- const NamespaceVector& whitelist = cache->online_whitelist_namespaces_;
+ const AppCacheNamespaceVector& whitelist =
+ cache->online_whitelist_namespaces_;
expected = 2;
EXPECT_EQ(expected, whitelist.size());
EXPECT_EQ(GURL("http://w1.com"), whitelist[0].namespace_url);
@@ -191,26 +172,25 @@ TEST(AppCacheTest, FindResponseForRequest) {
const int64 kExplicitInOnlineNamespaceResponseId = 5;
const int64 kInterceptResponseId = 6;
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.online_whitelist_namespaces.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl,
- GURL(), false));
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl,
+ GURL(), false));
manifest.online_whitelist_namespaces.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE,
- kOnlineNamespaceWithinOtherNamespaces,
- GURL(), false));
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE,
+ kOnlineNamespaceWithinOtherNamespaces, GURL(), false));
manifest.fallback_namespaces.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
- kFallbackEntryUrl1, false));
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
+ kFallbackEntryUrl1, false));
manifest.fallback_namespaces.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
- kFallbackEntryUrl2, false));
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
+ kFallbackEntryUrl2, false));
manifest.intercept_namespaces.push_back(
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace,
- kInterceptNamespaceEntry, false));
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace,
+ kInterceptNamespaceEntry, false));
manifest.intercept_namespaces.push_back(
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespaceWithinFallback,
- kInterceptNamespaceEntry, false));
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
+ kInterceptNamespaceWithinFallback, kInterceptNamespaceEntry, false));
// Create a cache with some namespaces and entries.
scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
@@ -383,10 +363,10 @@ TEST(AppCacheTest, FindInterceptPatternResponseForRequest) {
kInterceptNamespaceBase.Resolve("*.hit*"));
const GURL kInterceptNamespaceEntry("http://blah/intercept_resource");
const int64 kInterceptResponseId = 1;
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.intercept_namespaces.push_back(
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptPatternNamespace,
- kInterceptNamespaceEntry, true));
+ AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
+ kInterceptPatternNamespace, kInterceptNamespaceEntry, true));
scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
cache->InitializeWithManifest(&manifest);
cache->AddEntry(
@@ -454,9 +434,9 @@ TEST(AppCacheTest, FindFallbackPatternResponseForRequest) {
kFallbackNamespaceBase.Resolve("*.hit*"));
const GURL kFallbackNamespaceEntry("http://blah/fallback_resource");
const int64 kFallbackResponseId = 1;
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.fallback_namespaces.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackPatternNamespace,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackPatternNamespace,
kFallbackNamespaceEntry, true));
scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
cache->InitializeWithManifest(&manifest);
@@ -524,9 +504,9 @@ TEST(AppCacheTest, FindNetworkNamespacePatternResponseForRequest) {
const GURL kNetworkNamespaceBase("http://blah/network_namespace/");
const GURL kNetworkPatternNamespace(
kNetworkNamespaceBase.Resolve("*.hit*"));
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.online_whitelist_namespaces.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, kNetworkPatternNamespace,
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kNetworkPatternNamespace,
GURL(), true));
manifest.online_whitelist_all = false;
scoped_refptr<AppCache> cache(new AppCache(service.storage(), 1234));
@@ -580,7 +560,7 @@ TEST(AppCacheTest, ToFromDatabaseRecords) {
scoped_refptr<AppCacheGroup> group =
new AppCacheGroup(service.storage(), kManifestUrl, kGroupId);
scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
- Manifest manifest;
+ AppCacheManifest manifest;
EXPECT_TRUE(ParseManifest(kManifestUrl, kData.c_str(), kData.length(),
PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
cache->InitializeWithManifest(&manifest);
@@ -644,7 +624,7 @@ TEST(AppCacheTest, ToFromDatabaseRecords) {
}
TEST(AppCacheTest, IsNamespaceMatch) {
- Namespace prefix;
+ AppCacheNamespace prefix;
prefix.namespace_url = GURL("http://foo.com/prefix");
prefix.is_pattern = false;
EXPECT_TRUE(prefix.IsMatch(
@@ -652,7 +632,7 @@ TEST(AppCacheTest, IsNamespaceMatch) {
EXPECT_FALSE(prefix.IsMatch(
GURL("http://foo.com/nope")));
- Namespace bar_no_star;
+ AppCacheNamespace bar_no_star;
bar_no_star.namespace_url = GURL("http://foo.com/bar");
bar_no_star.is_pattern = true;
EXPECT_TRUE(bar_no_star.IsMatch(
@@ -660,7 +640,7 @@ TEST(AppCacheTest, IsNamespaceMatch) {
EXPECT_FALSE(bar_no_star.IsMatch(
GURL("http://foo.com/bar/nope")));
- Namespace bar_star;
+ AppCacheNamespace bar_star;
bar_star.namespace_url = GURL("http://foo.com/bar/*");
bar_star.is_pattern = true;
EXPECT_TRUE(bar_star.IsMatch(
@@ -670,7 +650,7 @@ TEST(AppCacheTest, IsNamespaceMatch) {
EXPECT_FALSE(bar_star.IsMatch(
GURL("http://foo.com/not_bar/should_not_match")));
- Namespace star_bar_star;
+ AppCacheNamespace star_bar_star;
star_bar_star.namespace_url = GURL("http://foo.com/*/bar/*");
star_bar_star.is_pattern = true;
EXPECT_TRUE(star_bar_star.IsMatch(
@@ -680,7 +660,7 @@ TEST(AppCacheTest, IsNamespaceMatch) {
EXPECT_FALSE(star_bar_star.IsMatch(
GURL("http://foo.com/any/not_bar/no_match")));
- Namespace query_star_edit;
+ AppCacheNamespace query_star_edit;
query_star_edit.namespace_url = GURL("http://foo.com/query?id=*&verb=edit*");
query_star_edit.is_pattern = true;
EXPECT_TRUE(query_star_edit.IsMatch(
@@ -692,7 +672,7 @@ TEST(AppCacheTest, IsNamespaceMatch) {
EXPECT_TRUE(query_star_edit.IsMatch(
GURL("http://foo.com/query?id=123&verb=print&verb=edit")));
- Namespace star_greediness;
+ AppCacheNamespace star_greediness;
star_greediness.namespace_url = GURL("http://foo.com/*/b");
star_greediness.is_pattern = true;
EXPECT_TRUE(star_greediness.IsMatch(
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
new file mode 100644
index 00000000000..af47342e97c
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -0,0 +1,1636 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_update_job.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_histograms.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/io_buffer.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request_context.h"
+
+namespace {
+bool IsDataReductionProxy(const net::HostPortPair& proxy_server) {
+ return (
+ proxy_server.Equals(net::HostPortPair("proxy.googlezip.net", 443)) ||
+ proxy_server.Equals(net::HostPortPair("compress.googlezip.net", 80)) ||
+ proxy_server.Equals(net::HostPortPair("proxy-dev.googlezip.net", 80)));
+}
+} // namspace
+
+namespace content {
+
+static const int kBufferSize = 32768;
+static const size_t kMaxConcurrentUrlFetches = 2;
+static const int kMax503Retries = 3;
+
+static std::string FormatUrlErrorMessage(
+ const char* format, const GURL& url,
+ AppCacheUpdateJob::ResultType error,
+ int response_code) {
+ // Show the net response code if we have one.
+ int code = response_code;
+ if (error != AppCacheUpdateJob::SERVER_ERROR)
+ code = static_cast<int>(error);
+ return base::StringPrintf(format, code, url.spec().c_str());
+}
+
+// Helper class for collecting hosts per frontend when sending notifications
+// so that only one notification is sent for all hosts using the same frontend.
+class HostNotifier {
+ public:
+ typedef std::vector<int> HostIds;
+ typedef std::map<AppCacheFrontend*, HostIds> NotifyHostMap;
+
+ // Caller is responsible for ensuring there will be no duplicate hosts.
+ void AddHost(AppCacheHost* host) {
+ std::pair<NotifyHostMap::iterator , bool> ret = hosts_to_notify.insert(
+ NotifyHostMap::value_type(host->frontend(), HostIds()));
+ ret.first->second.push_back(host->host_id());
+ }
+
+ void AddHosts(const std::set<AppCacheHost*>& hosts) {
+ for (std::set<AppCacheHost*>::const_iterator it = hosts.begin();
+ it != hosts.end(); ++it) {
+ AddHost(*it);
+ }
+ }
+
+ void SendNotifications(AppCacheEventID event_id) {
+ for (NotifyHostMap::iterator it = hosts_to_notify.begin();
+ it != hosts_to_notify.end(); ++it) {
+ AppCacheFrontend* frontend = it->first;
+ frontend->OnEventRaised(it->second, event_id);
+ }
+ }
+
+ void SendProgressNotifications(
+ const GURL& url, int num_total, int num_complete) {
+ for (NotifyHostMap::iterator it = hosts_to_notify.begin();
+ it != hosts_to_notify.end(); ++it) {
+ AppCacheFrontend* frontend = it->first;
+ frontend->OnProgressEventRaised(it->second, url,
+ num_total, num_complete);
+ }
+ }
+
+ void SendErrorNotifications(const AppCacheErrorDetails& details) {
+ DCHECK(!details.message.empty());
+ for (NotifyHostMap::iterator it = hosts_to_notify.begin();
+ it != hosts_to_notify.end(); ++it) {
+ AppCacheFrontend* frontend = it->first;
+ frontend->OnErrorEventRaised(it->second, details);
+ }
+ }
+
+ void SendLogMessage(const std::string& message) {
+ for (NotifyHostMap::iterator it = hosts_to_notify.begin();
+ it != hosts_to_notify.end(); ++it) {
+ AppCacheFrontend* frontend = it->first;
+ for (HostIds::iterator id = it->second.begin();
+ id != it->second.end(); ++id) {
+ frontend->OnLogMessage(*id, APPCACHE_LOG_WARNING, message);
+ }
+ }
+ }
+
+ private:
+ NotifyHostMap hosts_to_notify;
+};
+
+AppCacheUpdateJob::UrlToFetch::UrlToFetch(const GURL& url,
+ bool checked,
+ AppCacheResponseInfo* info)
+ : url(url),
+ storage_checked(checked),
+ existing_response_info(info) {
+}
+
+AppCacheUpdateJob::UrlToFetch::~UrlToFetch() {
+}
+
+// Helper class to fetch resources. Depending on the fetch type,
+// can either fetch to an in-memory string or write the response
+// data out to the disk cache.
+AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url,
+ FetchType fetch_type,
+ AppCacheUpdateJob* job)
+ : url_(url),
+ job_(job),
+ fetch_type_(fetch_type),
+ retry_503_attempts_(0),
+ buffer_(new net::IOBuffer(kBufferSize)),
+ request_(job->service_->request_context()
+ ->CreateRequest(url, net::DEFAULT_PRIORITY, this, NULL)),
+ result_(UPDATE_OK),
+ redirect_response_code_(-1) {}
+
+AppCacheUpdateJob::URLFetcher::~URLFetcher() {
+}
+
+void AppCacheUpdateJob::URLFetcher::Start() {
+ request_->set_first_party_for_cookies(job_->manifest_url_);
+ request_->SetLoadFlags(request_->load_flags() |
+ net::LOAD_DISABLE_INTERCEPT);
+ if (existing_response_headers_.get())
+ AddConditionalHeaders(existing_response_headers_.get());
+ request_->Start();
+}
+
+void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect(
+ net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) {
+ DCHECK(request_ == request);
+ // TODO(bengr): Remove this special case logic when crbug.com/429505 is
+ // resolved. Until then, the data reduction proxy client logic uses the
+ // redirect mechanism to resend requests over a direct connection when
+ // the proxy instructs it to do so. The redirect is to the same location
+ // as the original URL.
+ if ((request->load_flags() & net::LOAD_BYPASS_PROXY) &&
+ IsDataReductionProxy(request->proxy_server())) {
+ DCHECK_EQ(request->original_url(), request->url());
+ return;
+ }
+ // Redirect is not allowed by the update process.
+ job_->MadeProgress();
+ redirect_response_code_ = request->GetResponseCode();
+ request->Cancel();
+ result_ = REDIRECT_ERROR;
+ OnResponseCompleted();
+}
+
+void AppCacheUpdateJob::URLFetcher::OnResponseStarted(
+ net::URLRequest *request) {
+ DCHECK(request == request_);
+ int response_code = -1;
+ if (request->status().is_success()) {
+ response_code = request->GetResponseCode();
+ job_->MadeProgress();
+ }
+
+ if ((response_code / 100) != 2) {
+ if (response_code > 0)
+ result_ = SERVER_ERROR;
+ else
+ result_ = NETWORK_ERROR;
+ OnResponseCompleted();
+ return;
+ }
+
+ if (url_.SchemeIsSecure()) {
+ // Do not cache content with cert errors.
+ // Also, we willfully violate the HTML5 spec at this point in order
+ // to support the appcaching of cross-origin HTTPS resources.
+ // We've opted for a milder constraint and allow caching unless
+ // the resource has a "no-store" header. A spec change has been
+ // requested on the whatwg list.
+ // See http://code.google.com/p/chromium/issues/detail?id=69594
+ // TODO(michaeln): Consider doing this for cross-origin HTTP too.
+ if (net::IsCertStatusError(request->ssl_info().cert_status) ||
+ (url_.GetOrigin() != job_->manifest_url_.GetOrigin() &&
+ request->response_headers()->
+ HasHeaderValue("cache-control", "no-store"))) {
+ DCHECK_EQ(-1, redirect_response_code_);
+ request->Cancel();
+ result_ = SECURITY_ERROR;
+ OnResponseCompleted();
+ return;
+ }
+ }
+
+ // Write response info to storage for URL fetches. Wait for async write
+ // completion before reading any response data.
+ if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) {
+ response_writer_.reset(job_->CreateResponseWriter());
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
+ new HttpResponseInfoIOBuffer(
+ new net::HttpResponseInfo(request->response_info())));
+ response_writer_->WriteInfo(
+ io_buffer.get(),
+ base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
+ } else {
+ ReadResponseData();
+ }
+}
+
+void AppCacheUpdateJob::URLFetcher::OnReadCompleted(
+ net::URLRequest* request, int bytes_read) {
+ DCHECK(request_ == request);
+ bool data_consumed = true;
+ if (request->status().is_success() && bytes_read > 0) {
+ job_->MadeProgress();
+ data_consumed = ConsumeResponseData(bytes_read);
+ if (data_consumed) {
+ bytes_read = 0;
+ while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) {
+ if (bytes_read > 0) {
+ data_consumed = ConsumeResponseData(bytes_read);
+ if (!data_consumed)
+ break; // wait for async data processing, then read more
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ if (data_consumed && !request->status().is_io_pending()) {
+ DCHECK_EQ(UPDATE_OK, result_);
+ OnResponseCompleted();
+ }
+}
+
+void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
+ const net::HttpResponseHeaders* headers) {
+ DCHECK(request_.get() && headers);
+ net::HttpRequestHeaders extra_headers;
+
+ // Add If-Modified-Since header if response info has Last-Modified header.
+ const std::string last_modified = "Last-Modified";
+ std::string last_modified_value;
+ headers->EnumerateHeader(NULL, last_modified, &last_modified_value);
+ if (!last_modified_value.empty()) {
+ extra_headers.SetHeader(net::HttpRequestHeaders::kIfModifiedSince,
+ last_modified_value);
+ }
+
+ // Add If-None-Match header if response info has ETag header.
+ const std::string etag = "ETag";
+ std::string etag_value;
+ headers->EnumerateHeader(NULL, etag, &etag_value);
+ if (!etag_value.empty()) {
+ extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch,
+ etag_value);
+ }
+ if (!extra_headers.IsEmpty())
+ request_->SetExtraRequestHeaders(extra_headers);
+}
+
+void AppCacheUpdateJob::URLFetcher::OnWriteComplete(int result) {
+ if (result < 0) {
+ request_->Cancel();
+ result_ = DISKCACHE_ERROR;
+ OnResponseCompleted();
+ return;
+ }
+ ReadResponseData();
+}
+
+void AppCacheUpdateJob::URLFetcher::ReadResponseData() {
+ InternalUpdateState state = job_->internal_state_;
+ if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED)
+ return;
+ int bytes_read = 0;
+ request_->Read(buffer_.get(), kBufferSize, &bytes_read);
+ OnReadCompleted(request_.get(), bytes_read);
+}
+
+// Returns false if response data is processed asynchronously, in which
+// case ReadResponseData will be invoked when it is safe to continue
+// reading more response data from the request.
+bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) {
+ DCHECK_GT(bytes_read, 0);
+ switch (fetch_type_) {
+ case MANIFEST_FETCH:
+ case MANIFEST_REFETCH:
+ manifest_data_.append(buffer_->data(), bytes_read);
+ break;
+ case URL_FETCH:
+ case MASTER_ENTRY_FETCH:
+ DCHECK(response_writer_.get());
+ response_writer_->WriteData(
+ buffer_.get(),
+ bytes_read,
+ base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this)));
+ return false; // wait for async write completion to continue reading
+ default:
+ NOTREACHED();
+ }
+ return true;
+}
+
+void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() {
+ if (request_->status().is_success())
+ job_->MadeProgress();
+
+ // Retry for 503s where retry-after is 0.
+ if (request_->status().is_success() &&
+ request_->GetResponseCode() == 503 &&
+ MaybeRetryRequest()) {
+ return;
+ }
+
+ switch (fetch_type_) {
+ case MANIFEST_FETCH:
+ job_->HandleManifestFetchCompleted(this);
+ break;
+ case URL_FETCH:
+ job_->HandleUrlFetchCompleted(this);
+ break;
+ case MASTER_ENTRY_FETCH:
+ job_->HandleMasterEntryFetchCompleted(this);
+ break;
+ case MANIFEST_REFETCH:
+ job_->HandleManifestRefetchCompleted(this);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ delete this;
+}
+
+bool AppCacheUpdateJob::URLFetcher::MaybeRetryRequest() {
+ if (retry_503_attempts_ >= kMax503Retries ||
+ !request_->response_headers()->HasHeaderValue("retry-after", "0")) {
+ return false;
+ }
+ ++retry_503_attempts_;
+ result_ = UPDATE_OK;
+ request_ = job_->service_->request_context()->CreateRequest(
+ url_, net::DEFAULT_PRIORITY, this, NULL);
+ Start();
+ return true;
+}
+
+AppCacheUpdateJob::AppCacheUpdateJob(AppCacheServiceImpl* service,
+ AppCacheGroup* group)
+ : service_(service),
+ manifest_url_(group->manifest_url()),
+ group_(group),
+ update_type_(UNKNOWN_TYPE),
+ internal_state_(FETCH_MANIFEST),
+ master_entries_completed_(0),
+ url_fetches_completed_(0),
+ manifest_fetcher_(NULL),
+ manifest_has_valid_mime_type_(false),
+ stored_state_(UNSTORED),
+ storage_(service->storage()) {
+ service_->AddObserver(this);
+}
+
+AppCacheUpdateJob::~AppCacheUpdateJob() {
+ if (service_)
+ service_->RemoveObserver(this);
+ if (internal_state_ != COMPLETED)
+ Cancel();
+
+ DCHECK(!manifest_fetcher_);
+ DCHECK(pending_url_fetches_.empty());
+ DCHECK(!inprogress_cache_.get());
+ DCHECK(pending_master_entries_.empty());
+ DCHECK(master_entry_fetches_.empty());
+
+ if (group_)
+ group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE);
+}
+
+void AppCacheUpdateJob::StartUpdate(AppCacheHost* host,
+ const GURL& new_master_resource) {
+ DCHECK(group_->update_job() == this);
+ DCHECK(!group_->is_obsolete());
+
+ bool is_new_pending_master_entry = false;
+ if (!new_master_resource.is_empty()) {
+ DCHECK(new_master_resource == host->pending_master_entry_url());
+ DCHECK(!new_master_resource.has_ref());
+ DCHECK(new_master_resource.GetOrigin() == manifest_url_.GetOrigin());
+
+ // Cannot add more to this update if already terminating.
+ if (IsTerminating()) {
+ group_->QueueUpdate(host, new_master_resource);
+ return;
+ }
+
+ std::pair<PendingMasters::iterator, bool> ret =
+ pending_master_entries_.insert(
+ PendingMasters::value_type(new_master_resource, PendingHosts()));
+ is_new_pending_master_entry = ret.second;
+ ret.first->second.push_back(host);
+ host->AddObserver(this);
+ }
+
+ // Notify host (if any) if already checking or downloading.
+ AppCacheGroup::UpdateAppCacheStatus update_status = group_->update_status();
+ if (update_status == AppCacheGroup::CHECKING ||
+ update_status == AppCacheGroup::DOWNLOADING) {
+ if (host) {
+ NotifySingleHost(host, APPCACHE_CHECKING_EVENT);
+ if (update_status == AppCacheGroup::DOWNLOADING)
+ NotifySingleHost(host, APPCACHE_DOWNLOADING_EVENT);
+
+ // Add to fetch list or an existing entry if already fetched.
+ if (!new_master_resource.is_empty()) {
+ AddMasterEntryToFetchList(host, new_master_resource,
+ is_new_pending_master_entry);
+ }
+ }
+ return;
+ }
+
+ // Begin update process for the group.
+ MadeProgress();
+ group_->SetUpdateAppCacheStatus(AppCacheGroup::CHECKING);
+ if (group_->HasCache()) {
+ update_type_ = UPGRADE_ATTEMPT;
+ NotifyAllAssociatedHosts(APPCACHE_CHECKING_EVENT);
+ } else {
+ update_type_ = CACHE_ATTEMPT;
+ DCHECK(host);
+ NotifySingleHost(host, APPCACHE_CHECKING_EVENT);
+ }
+
+ if (!new_master_resource.is_empty()) {
+ AddMasterEntryToFetchList(host, new_master_resource,
+ is_new_pending_master_entry);
+ }
+
+ FetchManifest(true);
+}
+
+AppCacheResponseWriter* AppCacheUpdateJob::CreateResponseWriter() {
+ AppCacheResponseWriter* writer =
+ storage_->CreateResponseWriter(manifest_url_,
+ group_->group_id());
+ stored_response_ids_.push_back(writer->response_id());
+ return writer;
+}
+
+void AppCacheUpdateJob::HandleCacheFailure(
+ const AppCacheErrorDetails& error_details,
+ ResultType result,
+ const GURL& failed_resource_url) {
+ // 6.9.4 cache failure steps 2-8.
+ DCHECK(internal_state_ != CACHE_FAILURE);
+ DCHECK(!error_details.message.empty());
+ DCHECK(result != UPDATE_OK);
+ internal_state_ = CACHE_FAILURE;
+ LogHistogramStats(result, failed_resource_url);
+ CancelAllUrlFetches();
+ CancelAllMasterEntryFetches(error_details);
+ NotifyAllError(error_details);
+ DiscardInprogressCache();
+ internal_state_ = COMPLETED;
+ DeleteSoon(); // To unwind the stack prior to deletion.
+}
+
+void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
+ DCHECK(!manifest_fetcher_);
+ manifest_fetcher_ = new URLFetcher(
+ manifest_url_,
+ is_first_fetch ? URLFetcher::MANIFEST_FETCH :
+ URLFetcher::MANIFEST_REFETCH,
+ this);
+
+ // Add any necessary Http headers before sending fetch request.
+ if (is_first_fetch) {
+ AppCacheEntry* entry = (update_type_ == UPGRADE_ATTEMPT) ?
+ group_->newest_complete_cache()->GetEntry(manifest_url_) : NULL;
+ if (entry) {
+ // Asynchronously load response info for manifest from newest cache.
+ storage_->LoadResponseInfo(manifest_url_, group_->group_id(),
+ entry->response_id(), this);
+ } else {
+ manifest_fetcher_->Start();
+ }
+ } else {
+ DCHECK(internal_state_ == REFETCH_MANIFEST);
+ DCHECK(manifest_response_info_.get());
+ manifest_fetcher_->set_existing_response_headers(
+ manifest_response_info_->headers.get());
+ manifest_fetcher_->Start();
+ }
+}
+
+
+void AppCacheUpdateJob::HandleManifestFetchCompleted(
+ URLFetcher* fetcher) {
+ DCHECK_EQ(internal_state_, FETCH_MANIFEST);
+ DCHECK_EQ(manifest_fetcher_, fetcher);
+ manifest_fetcher_ = NULL;
+
+ net::URLRequest* request = fetcher->request();
+ int response_code = -1;
+ bool is_valid_response_code = false;
+ if (request->status().is_success()) {
+ response_code = request->GetResponseCode();
+ is_valid_response_code = (response_code / 100 == 2);
+
+ std::string mime_type;
+ request->GetMimeType(&mime_type);
+ manifest_has_valid_mime_type_ = (mime_type == "text/cache-manifest");
+ }
+
+ if (is_valid_response_code) {
+ manifest_data_ = fetcher->manifest_data();
+ manifest_response_info_.reset(
+ new net::HttpResponseInfo(request->response_info()));
+ if (update_type_ == UPGRADE_ATTEMPT)
+ CheckIfManifestChanged(); // continues asynchronously
+ else
+ ContinueHandleManifestFetchCompleted(true);
+ } else if (response_code == 304 && update_type_ == UPGRADE_ATTEMPT) {
+ ContinueHandleManifestFetchCompleted(false);
+ } else if ((response_code == 404 || response_code == 410) &&
+ update_type_ == UPGRADE_ATTEMPT) {
+ storage_->MakeGroupObsolete(group_, this, response_code); // async
+ } else {
+ const char* kFormatString = "Manifest fetch failed (%d) %s";
+ std::string message = FormatUrlErrorMessage(
+ kFormatString, manifest_url_, fetcher->result(), response_code);
+ HandleCacheFailure(AppCacheErrorDetails(message,
+ APPCACHE_MANIFEST_ERROR,
+ manifest_url_,
+ response_code,
+ false /*is_cross_origin*/),
+ fetcher->result(),
+ GURL());
+ }
+}
+
+void AppCacheUpdateJob::OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) {
+ DCHECK(master_entry_fetches_.empty());
+ CancelAllMasterEntryFetches(AppCacheErrorDetails(
+ "The cache has been made obsolete, "
+ "the manifest file returned 404 or 410",
+ APPCACHE_MANIFEST_ERROR,
+ GURL(),
+ response_code,
+ false /*is_cross_origin*/));
+ if (success) {
+ DCHECK(group->is_obsolete());
+ NotifyAllAssociatedHosts(APPCACHE_OBSOLETE_EVENT);
+ internal_state_ = COMPLETED;
+ MaybeCompleteUpdate();
+ } else {
+ // Treat failure to mark group obsolete as a cache failure.
+ HandleCacheFailure(AppCacheErrorDetails(
+ "Failed to mark the cache as obsolete",
+ APPCACHE_UNKNOWN_ERROR,
+ GURL(),
+ 0,
+ false /*is_cross_origin*/),
+ DB_ERROR,
+ GURL());
+ }
+}
+
+void AppCacheUpdateJob::ContinueHandleManifestFetchCompleted(bool changed) {
+ DCHECK(internal_state_ == FETCH_MANIFEST);
+
+ if (!changed) {
+ DCHECK(update_type_ == UPGRADE_ATTEMPT);
+ internal_state_ = NO_UPDATE;
+
+ // Wait for pending master entries to download.
+ FetchMasterEntries();
+ MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps
+ return;
+ }
+
+ AppCacheManifest manifest;
+ if (!ParseManifest(manifest_url_, manifest_data_.data(),
+ manifest_data_.length(),
+ manifest_has_valid_mime_type_ ?
+ PARSE_MANIFEST_ALLOWING_INTERCEPTS :
+ PARSE_MANIFEST_PER_STANDARD,
+ manifest)) {
+ const char* kFormatString = "Failed to parse manifest %s";
+ const std::string message = base::StringPrintf(kFormatString,
+ manifest_url_.spec().c_str());
+ HandleCacheFailure(
+ AppCacheErrorDetails(
+ message, APPCACHE_SIGNATURE_ERROR, GURL(), 0,
+ false /*is_cross_origin*/),
+ MANIFEST_ERROR,
+ GURL());
+ VLOG(1) << message;
+ return;
+ }
+
+ // Proceed with update process. Section 6.9.4 steps 8-20.
+ internal_state_ = DOWNLOADING;
+ inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId());
+ BuildUrlFileList(manifest);
+ inprogress_cache_->InitializeWithManifest(&manifest);
+
+ // Associate all pending master hosts with the newly created cache.
+ for (PendingMasters::iterator it = pending_master_entries_.begin();
+ it != pending_master_entries_.end(); ++it) {
+ PendingHosts& hosts = it->second;
+ for (PendingHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ (*host_it)
+ ->AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_);
+ }
+ }
+
+ if (manifest.did_ignore_intercept_namespaces) {
+ // Must be done after associating all pending master hosts.
+ std::string message(
+ "Ignoring the INTERCEPT section of the application cache manifest "
+ "because the content type is not text/cache-manifest");
+ LogConsoleMessageToAll(message);
+ }
+
+ group_->SetUpdateAppCacheStatus(AppCacheGroup::DOWNLOADING);
+ NotifyAllAssociatedHosts(APPCACHE_DOWNLOADING_EVENT);
+ FetchUrls();
+ FetchMasterEntries();
+ MaybeCompleteUpdate(); // if not done, continues when async fetches complete
+}
+
+void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) {
+ DCHECK(internal_state_ == DOWNLOADING);
+
+ net::URLRequest* request = fetcher->request();
+ const GURL& url = request->original_url();
+ pending_url_fetches_.erase(url);
+ NotifyAllProgress(url);
+ ++url_fetches_completed_;
+
+ int response_code = request->status().is_success()
+ ? request->GetResponseCode()
+ : fetcher->redirect_response_code();
+
+ AppCacheEntry& entry = url_file_list_.find(url)->second;
+
+ if (response_code / 100 == 2) {
+ // Associate storage with the new entry.
+ DCHECK(fetcher->response_writer());
+ entry.set_response_id(fetcher->response_writer()->response_id());
+ entry.set_response_size(fetcher->response_writer()->amount_written());
+ if (!inprogress_cache_->AddOrModifyEntry(url, entry))
+ duplicate_response_ids_.push_back(entry.response_id());
+
+ // TODO(michaeln): Check for <html manifest=xxx>
+ // See http://code.google.com/p/chromium/issues/detail?id=97930
+ // if (entry.IsMaster() && !(entry.IsExplicit() || fallback || intercept))
+ // if (!manifestAttribute) skip it
+
+ // Foreign entries will be detected during cache selection.
+ // Note: 6.9.4, step 17.9 possible optimization: if resource is HTML or XML
+ // file whose root element is an html element with a manifest attribute
+ // whose value doesn't match the manifest url of the application cache
+ // being processed, mark the entry as being foreign.
+ } else {
+ VLOG(1) << "Request status: " << request->status().status()
+ << " error: " << request->status().error()
+ << " response code: " << response_code;
+ if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) {
+ if (response_code == 304 && fetcher->existing_entry().has_response_id()) {
+ // Keep the existing response.
+ entry.set_response_id(fetcher->existing_entry().response_id());
+ entry.set_response_size(fetcher->existing_entry().response_size());
+ inprogress_cache_->AddOrModifyEntry(url, entry);
+ } else {
+ const char* kFormatString = "Resource fetch failed (%d) %s";
+ std::string message = FormatUrlErrorMessage(
+ kFormatString, url, fetcher->result(), response_code);
+ ResultType result = fetcher->result();
+ bool is_cross_origin = url.GetOrigin() != manifest_url_.GetOrigin();
+ switch (result) {
+ case DISKCACHE_ERROR:
+ HandleCacheFailure(
+ AppCacheErrorDetails(
+ message, APPCACHE_UNKNOWN_ERROR, GURL(), 0,
+ is_cross_origin),
+ result,
+ url);
+ break;
+ case NETWORK_ERROR:
+ HandleCacheFailure(
+ AppCacheErrorDetails(message, APPCACHE_RESOURCE_ERROR, url, 0,
+ is_cross_origin),
+ result,
+ url);
+ break;
+ default:
+ HandleCacheFailure(AppCacheErrorDetails(message,
+ APPCACHE_RESOURCE_ERROR,
+ url,
+ response_code,
+ is_cross_origin),
+ result,
+ url);
+ break;
+ }
+ return;
+ }
+ } else if (response_code == 404 || response_code == 410) {
+ // Entry is skipped. They are dropped from the cache.
+ } else if (update_type_ == UPGRADE_ATTEMPT &&
+ fetcher->existing_entry().has_response_id()) {
+ // Keep the existing response.
+ // TODO(michaeln): Not sure this is a good idea. This is spec compliant
+ // but the old resource may or may not be compatible with the new contents
+ // of the cache. Impossible to know one way or the other.
+ entry.set_response_id(fetcher->existing_entry().response_id());
+ entry.set_response_size(fetcher->existing_entry().response_size());
+ inprogress_cache_->AddOrModifyEntry(url, entry);
+ }
+ }
+
+ // Fetch another URL now that one request has completed.
+ DCHECK(internal_state_ != CACHE_FAILURE);
+ FetchUrls();
+ MaybeCompleteUpdate();
+}
+
+void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(
+ URLFetcher* fetcher) {
+ DCHECK(internal_state_ == NO_UPDATE || internal_state_ == DOWNLOADING);
+
+ // TODO(jennb): Handle downloads completing during cache failure when update
+ // no longer fetches master entries directly. For now, we cancel all pending
+ // master entry fetches when entering cache failure state so this will never
+ // be called in CACHE_FAILURE state.
+
+ net::URLRequest* request = fetcher->request();
+ const GURL& url = request->original_url();
+ master_entry_fetches_.erase(url);
+ ++master_entries_completed_;
+
+ int response_code = request->status().is_success()
+ ? request->GetResponseCode() : -1;
+
+ PendingMasters::iterator found = pending_master_entries_.find(url);
+ DCHECK(found != pending_master_entries_.end());
+ PendingHosts& hosts = found->second;
+
+ // Section 6.9.4. No update case: step 7.3, else step 22.
+ if (response_code / 100 == 2) {
+ // Add fetched master entry to the appropriate cache.
+ AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get()
+ : group_->newest_complete_cache();
+ DCHECK(fetcher->response_writer());
+ AppCacheEntry master_entry(AppCacheEntry::MASTER,
+ fetcher->response_writer()->response_id(),
+ fetcher->response_writer()->amount_written());
+ if (cache->AddOrModifyEntry(url, master_entry))
+ added_master_entries_.push_back(url);
+ else
+ duplicate_response_ids_.push_back(master_entry.response_id());
+
+ // In no-update case, associate host with the newest cache.
+ if (!inprogress_cache_.get()) {
+ // TODO(michaeln): defer until the updated cache has been stored
+ DCHECK(cache == group_->newest_complete_cache());
+ for (PendingHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ (*host_it)->AssociateCompleteCache(cache);
+ }
+ }
+ } else {
+ HostNotifier host_notifier;
+ for (PendingHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ AppCacheHost* host = *host_it;
+ host_notifier.AddHost(host);
+
+ // In downloading case, disassociate host from inprogress cache.
+ if (inprogress_cache_.get())
+ host->AssociateNoCache(GURL());
+
+ host->RemoveObserver(this);
+ }
+ hosts.clear();
+
+ const char* kFormatString = "Manifest fetch failed (%d) %s";
+ std::string message = FormatUrlErrorMessage(
+ kFormatString, request->url(), fetcher->result(), response_code);
+ host_notifier.SendErrorNotifications(
+ AppCacheErrorDetails(message,
+ APPCACHE_MANIFEST_ERROR,
+ request->url(),
+ response_code,
+ false /*is_cross_origin*/));
+
+ // In downloading case, update result is different if all master entries
+ // failed vs. only some failing.
+ if (inprogress_cache_.get()) {
+ // Only count successful downloads to know if all master entries failed.
+ pending_master_entries_.erase(found);
+ --master_entries_completed_;
+
+ // Section 6.9.4, step 22.3.
+ if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
+ HandleCacheFailure(AppCacheErrorDetails(message,
+ APPCACHE_MANIFEST_ERROR,
+ request->url(),
+ response_code,
+ false /*is_cross_origin*/),
+ fetcher->result(),
+ GURL());
+ return;
+ }
+ }
+ }
+
+ DCHECK(internal_state_ != CACHE_FAILURE);
+ FetchMasterEntries();
+ MaybeCompleteUpdate();
+}
+
+void AppCacheUpdateJob::HandleManifestRefetchCompleted(
+ URLFetcher* fetcher) {
+ DCHECK(internal_state_ == REFETCH_MANIFEST);
+ DCHECK(manifest_fetcher_ == fetcher);
+ manifest_fetcher_ = NULL;
+
+ net::URLRequest* request = fetcher->request();
+ int response_code = request->status().is_success()
+ ? request->GetResponseCode() : -1;
+ if (response_code == 304 || manifest_data_ == fetcher->manifest_data()) {
+ // Only need to store response in storage if manifest is not already
+ // an entry in the cache.
+ AppCacheEntry* entry = inprogress_cache_->GetEntry(manifest_url_);
+ if (entry) {
+ entry->add_types(AppCacheEntry::MANIFEST);
+ StoreGroupAndCache();
+ } else {
+ manifest_response_writer_.reset(CreateResponseWriter());
+ scoped_refptr<HttpResponseInfoIOBuffer> io_buffer(
+ new HttpResponseInfoIOBuffer(manifest_response_info_.release()));
+ manifest_response_writer_->WriteInfo(
+ io_buffer.get(),
+ base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete,
+ base::Unretained(this)));
+ }
+ } else {
+ VLOG(1) << "Request status: " << request->status().status()
+ << " error: " << request->status().error()
+ << " response code: " << response_code;
+ ScheduleUpdateRetry(kRerunDelayMs);
+ if (response_code == 200) {
+ HandleCacheFailure(AppCacheErrorDetails("Manifest changed during update",
+ APPCACHE_CHANGED_ERROR,
+ GURL(),
+ 0,
+ false /*is_cross_origin*/),
+ MANIFEST_ERROR,
+ GURL());
+ } else {
+ const char* kFormatString = "Manifest re-fetch failed (%d) %s";
+ std::string message = FormatUrlErrorMessage(
+ kFormatString, manifest_url_, fetcher->result(), response_code);
+ HandleCacheFailure(AppCacheErrorDetails(message,
+ APPCACHE_MANIFEST_ERROR,
+ GURL(),
+ response_code,
+ false /*is_cross_origin*/),
+ fetcher->result(),
+ GURL());
+ }
+ }
+}
+
+void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) {
+ if (result > 0) {
+ scoped_refptr<net::StringIOBuffer> io_buffer(
+ new net::StringIOBuffer(manifest_data_));
+ manifest_response_writer_->WriteData(
+ io_buffer.get(),
+ manifest_data_.length(),
+ base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete,
+ base::Unretained(this)));
+ } else {
+ HandleCacheFailure(
+ AppCacheErrorDetails("Failed to write the manifest headers to storage",
+ APPCACHE_UNKNOWN_ERROR,
+ GURL(),
+ 0,
+ false /*is_cross_origin*/),
+ DISKCACHE_ERROR,
+ GURL());
+ }
+}
+
+void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) {
+ if (result > 0) {
+ AppCacheEntry entry(AppCacheEntry::MANIFEST,
+ manifest_response_writer_->response_id(),
+ manifest_response_writer_->amount_written());
+ if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry))
+ duplicate_response_ids_.push_back(entry.response_id());
+ StoreGroupAndCache();
+ } else {
+ HandleCacheFailure(
+ AppCacheErrorDetails("Failed to write the manifest data to storage",
+ APPCACHE_UNKNOWN_ERROR,
+ GURL(),
+ 0,
+ false /*is_cross_origin*/),
+ DISKCACHE_ERROR,
+ GURL());
+ }
+}
+
+void AppCacheUpdateJob::StoreGroupAndCache() {
+ DCHECK(stored_state_ == UNSTORED);
+ stored_state_ = STORING;
+ scoped_refptr<AppCache> newest_cache;
+ if (inprogress_cache_.get())
+ newest_cache.swap(inprogress_cache_);
+ else
+ newest_cache = group_->newest_complete_cache();
+ newest_cache->set_update_time(base::Time::Now());
+
+ // TODO(michaeln): dcheck is fishing for clues to crbug/95101
+ DCHECK_EQ(manifest_url_, group_->manifest_url());
+ storage_->StoreGroupAndNewestCache(group_, newest_cache.get(), this);
+}
+
+void AppCacheUpdateJob::OnGroupAndNewestCacheStored(AppCacheGroup* group,
+ AppCache* newest_cache,
+ bool success,
+ bool would_exceed_quota) {
+ DCHECK(stored_state_ == STORING);
+ if (success) {
+ stored_state_ = STORED;
+ MaybeCompleteUpdate(); // will definitely complete
+ } else {
+ stored_state_ = UNSTORED;
+
+ // Restore inprogress_cache_ to get the proper events delivered
+ // and the proper cleanup to occur.
+ if (newest_cache != group->newest_complete_cache())
+ inprogress_cache_ = newest_cache;
+
+ ResultType result = DB_ERROR;
+ AppCacheErrorReason reason = APPCACHE_UNKNOWN_ERROR;
+ std::string message("Failed to commit new cache to storage");
+ if (would_exceed_quota) {
+ message.append(", would exceed quota");
+ result = QUOTA_ERROR;
+ reason = APPCACHE_QUOTA_ERROR;
+ }
+ HandleCacheFailure(
+ AppCacheErrorDetails(message, reason, GURL(), 0,
+ false /*is_cross_origin*/),
+ result,
+ GURL());
+ }
+}
+
+void AppCacheUpdateJob::NotifySingleHost(AppCacheHost* host,
+ AppCacheEventID event_id) {
+ std::vector<int> ids(1, host->host_id());
+ host->frontend()->OnEventRaised(ids, event_id);
+}
+
+void AppCacheUpdateJob::NotifyAllAssociatedHosts(AppCacheEventID event_id) {
+ HostNotifier host_notifier;
+ AddAllAssociatedHostsToNotifier(&host_notifier);
+ host_notifier.SendNotifications(event_id);
+}
+
+void AppCacheUpdateJob::NotifyAllProgress(const GURL& url) {
+ HostNotifier host_notifier;
+ AddAllAssociatedHostsToNotifier(&host_notifier);
+ host_notifier.SendProgressNotifications(
+ url, url_file_list_.size(), url_fetches_completed_);
+}
+
+void AppCacheUpdateJob::NotifyAllFinalProgress() {
+ DCHECK(url_file_list_.size() == url_fetches_completed_);
+ NotifyAllProgress(GURL());
+}
+
+void AppCacheUpdateJob::NotifyAllError(const AppCacheErrorDetails& details) {
+ HostNotifier host_notifier;
+ AddAllAssociatedHostsToNotifier(&host_notifier);
+ host_notifier.SendErrorNotifications(details);
+}
+
+void AppCacheUpdateJob::LogConsoleMessageToAll(const std::string& message) {
+ HostNotifier host_notifier;
+ AddAllAssociatedHostsToNotifier(&host_notifier);
+ host_notifier.SendLogMessage(message);
+}
+
+void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier(
+ HostNotifier* host_notifier) {
+ // Collect hosts so we only send one notification per frontend.
+ // A host can only be associated with a single cache so no need to worry
+ // about duplicate hosts being added to the notifier.
+ if (inprogress_cache_.get()) {
+ DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE);
+ host_notifier->AddHosts(inprogress_cache_->associated_hosts());
+ }
+
+ AppCacheGroup::Caches old_caches = group_->old_caches();
+ for (AppCacheGroup::Caches::const_iterator it = old_caches.begin();
+ it != old_caches.end(); ++it) {
+ host_notifier->AddHosts((*it)->associated_hosts());
+ }
+
+ AppCache* newest_cache = group_->newest_complete_cache();
+ if (newest_cache)
+ host_notifier->AddHosts(newest_cache->associated_hosts());
+}
+
+void AppCacheUpdateJob::OnDestructionImminent(AppCacheHost* host) {
+ // The host is about to be deleted; remove from our collection.
+ PendingMasters::iterator found =
+ pending_master_entries_.find(host->pending_master_entry_url());
+ DCHECK(found != pending_master_entries_.end());
+ PendingHosts& hosts = found->second;
+ PendingHosts::iterator it = std::find(hosts.begin(), hosts.end(), host);
+ DCHECK(it != hosts.end());
+ hosts.erase(it);
+}
+
+void AppCacheUpdateJob::OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) {
+ // We continue to use the disabled instance, but arrange for its
+ // deletion when its no longer needed.
+ if (old_storage_ref->storage() == storage_)
+ disabled_storage_reference_ = old_storage_ref;
+}
+
+void AppCacheUpdateJob::CheckIfManifestChanged() {
+ DCHECK(update_type_ == UPGRADE_ATTEMPT);
+ AppCacheEntry* entry = NULL;
+ if (group_->newest_complete_cache())
+ entry = group_->newest_complete_cache()->GetEntry(manifest_url_);
+ if (!entry) {
+ // TODO(michaeln): This is just a bandaid to avoid a crash.
+ // http://code.google.com/p/chromium/issues/detail?id=95101
+ if (service_->storage() == storage_) {
+ // Use a local variable because service_ is reset in HandleCacheFailure.
+ AppCacheServiceImpl* service = service_;
+ HandleCacheFailure(
+ AppCacheErrorDetails("Manifest entry not found in existing cache",
+ APPCACHE_UNKNOWN_ERROR,
+ GURL(),
+ 0,
+ false /*is_cross_origin*/),
+ DB_ERROR,
+ GURL());
+ AppCacheHistograms::AddMissingManifestEntrySample();
+ service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
+ }
+ return;
+ }
+
+ // Load manifest data from storage to compare against fetched manifest.
+ manifest_response_reader_.reset(
+ storage_->CreateResponseReader(manifest_url_,
+ group_->group_id(),
+ entry->response_id()));
+ read_manifest_buffer_ = new net::IOBuffer(kBufferSize);
+ manifest_response_reader_->ReadData(
+ read_manifest_buffer_.get(),
+ kBufferSize,
+ base::Bind(&AppCacheUpdateJob::OnManifestDataReadComplete,
+ base::Unretained(this))); // async read
+}
+
+void AppCacheUpdateJob::OnManifestDataReadComplete(int result) {
+ if (result > 0) {
+ loaded_manifest_data_.append(read_manifest_buffer_->data(), result);
+ manifest_response_reader_->ReadData(
+ read_manifest_buffer_.get(),
+ kBufferSize,
+ base::Bind(&AppCacheUpdateJob::OnManifestDataReadComplete,
+ base::Unretained(this))); // read more
+ } else {
+ read_manifest_buffer_ = NULL;
+ manifest_response_reader_.reset();
+ ContinueHandleManifestFetchCompleted(
+ result < 0 || manifest_data_ != loaded_manifest_data_);
+ }
+}
+
+void AppCacheUpdateJob::BuildUrlFileList(const AppCacheManifest& manifest) {
+ for (base::hash_set<std::string>::const_iterator it =
+ manifest.explicit_urls.begin();
+ it != manifest.explicit_urls.end(); ++it) {
+ AddUrlToFileList(GURL(*it), AppCacheEntry::EXPLICIT);
+ }
+
+ const std::vector<AppCacheNamespace>& intercepts =
+ manifest.intercept_namespaces;
+ for (std::vector<AppCacheNamespace>::const_iterator it = intercepts.begin();
+ it != intercepts.end(); ++it) {
+ int flags = AppCacheEntry::INTERCEPT;
+ if (it->is_executable)
+ flags |= AppCacheEntry::EXECUTABLE;
+ AddUrlToFileList(it->target_url, flags);
+ }
+
+ const std::vector<AppCacheNamespace>& fallbacks =
+ manifest.fallback_namespaces;
+ for (std::vector<AppCacheNamespace>::const_iterator it = fallbacks.begin();
+ it != fallbacks.end(); ++it) {
+ AddUrlToFileList(it->target_url, AppCacheEntry::FALLBACK);
+ }
+
+ // Add all master entries from newest complete cache.
+ if (update_type_ == UPGRADE_ATTEMPT) {
+ const AppCache::EntryMap& entries =
+ group_->newest_complete_cache()->entries();
+ for (AppCache::EntryMap::const_iterator it = entries.begin();
+ it != entries.end(); ++it) {
+ const AppCacheEntry& entry = it->second;
+ if (entry.IsMaster())
+ AddUrlToFileList(it->first, AppCacheEntry::MASTER);
+ }
+ }
+}
+
+void AppCacheUpdateJob::AddUrlToFileList(const GURL& url, int type) {
+ std::pair<AppCache::EntryMap::iterator, bool> ret = url_file_list_.insert(
+ AppCache::EntryMap::value_type(url, AppCacheEntry(type)));
+
+ if (ret.second)
+ urls_to_fetch_.push_back(UrlToFetch(url, false, NULL));
+ else
+ ret.first->second.add_types(type); // URL already exists. Merge types.
+}
+
+void AppCacheUpdateJob::FetchUrls() {
+ DCHECK(internal_state_ == DOWNLOADING);
+
+ // Fetch each URL in the list according to section 6.9.4 step 17.1-17.3.
+ // Fetch up to the concurrent limit. Other fetches will be triggered as each
+ // each fetch completes.
+ while (pending_url_fetches_.size() < kMaxConcurrentUrlFetches &&
+ !urls_to_fetch_.empty()) {
+ UrlToFetch url_to_fetch = urls_to_fetch_.front();
+ urls_to_fetch_.pop_front();
+
+ AppCache::EntryMap::iterator it = url_file_list_.find(url_to_fetch.url);
+ DCHECK(it != url_file_list_.end());
+ AppCacheEntry& entry = it->second;
+ if (ShouldSkipUrlFetch(entry)) {
+ NotifyAllProgress(url_to_fetch.url);
+ ++url_fetches_completed_;
+ } else if (AlreadyFetchedEntry(url_to_fetch.url, entry.types())) {
+ NotifyAllProgress(url_to_fetch.url);
+ ++url_fetches_completed_; // saved a URL request
+ } else if (!url_to_fetch.storage_checked &&
+ MaybeLoadFromNewestCache(url_to_fetch.url, entry)) {
+ // Continues asynchronously after data is loaded from newest cache.
+ } else {
+ URLFetcher* fetcher = new URLFetcher(
+ url_to_fetch.url, URLFetcher::URL_FETCH, this);
+ if (url_to_fetch.existing_response_info.get()) {
+ DCHECK(group_->newest_complete_cache());
+ AppCacheEntry* existing_entry =
+ group_->newest_complete_cache()->GetEntry(url_to_fetch.url);
+ DCHECK(existing_entry);
+ DCHECK(existing_entry->response_id() ==
+ url_to_fetch.existing_response_info->response_id());
+ fetcher->set_existing_response_headers(
+ url_to_fetch.existing_response_info->http_response_info()->headers
+ .get());
+ fetcher->set_existing_entry(*existing_entry);
+ }
+ fetcher->Start();
+ pending_url_fetches_.insert(
+ PendingUrlFetches::value_type(url_to_fetch.url, fetcher));
+ }
+ }
+}
+
+void AppCacheUpdateJob::CancelAllUrlFetches() {
+ // Cancel any pending URL requests.
+ for (PendingUrlFetches::iterator it = pending_url_fetches_.begin();
+ it != pending_url_fetches_.end(); ++it) {
+ delete it->second;
+ }
+
+ url_fetches_completed_ +=
+ pending_url_fetches_.size() + urls_to_fetch_.size();
+ pending_url_fetches_.clear();
+ urls_to_fetch_.clear();
+}
+
+bool AppCacheUpdateJob::ShouldSkipUrlFetch(const AppCacheEntry& entry) {
+ // 6.6.4 Step 17
+ // If the resource URL being processed was flagged as neither an
+ // "explicit entry" nor or a "fallback entry", then the user agent
+ // may skip this URL.
+ if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept())
+ return false;
+
+ // TODO(jennb): decide if entry should be skipped to expire it from cache
+ return false;
+}
+
+bool AppCacheUpdateJob::AlreadyFetchedEntry(const GURL& url,
+ int entry_type) {
+ DCHECK(internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE);
+ AppCacheEntry* existing =
+ inprogress_cache_.get() ? inprogress_cache_->GetEntry(url)
+ : group_->newest_complete_cache()->GetEntry(url);
+ if (existing) {
+ existing->add_types(entry_type);
+ return true;
+ }
+ return false;
+}
+
+void AppCacheUpdateJob::AddMasterEntryToFetchList(AppCacheHost* host,
+ const GURL& url,
+ bool is_new) {
+ DCHECK(!IsTerminating());
+
+ if (internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE) {
+ AppCache* cache;
+ if (inprogress_cache_.get()) {
+ // always associate
+ host->AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_);
+ cache = inprogress_cache_.get();
+ } else {
+ cache = group_->newest_complete_cache();
+ }
+
+ // Update existing entry if it has already been fetched.
+ AppCacheEntry* entry = cache->GetEntry(url);
+ if (entry) {
+ entry->add_types(AppCacheEntry::MASTER);
+ if (internal_state_ == NO_UPDATE && !inprogress_cache_.get()) {
+ // only associate if have entry
+ host->AssociateCompleteCache(cache);
+ }
+ if (is_new)
+ ++master_entries_completed_; // pretend fetching completed
+ return;
+ }
+ }
+
+ // Add to fetch list if not already fetching.
+ if (master_entry_fetches_.find(url) == master_entry_fetches_.end()) {
+ master_entries_to_fetch_.insert(url);
+ if (internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE)
+ FetchMasterEntries();
+ }
+}
+
+void AppCacheUpdateJob::FetchMasterEntries() {
+ DCHECK(internal_state_ == NO_UPDATE || internal_state_ == DOWNLOADING);
+
+ // Fetch each master entry in the list, up to the concurrent limit.
+ // Additional fetches will be triggered as each fetch completes.
+ while (master_entry_fetches_.size() < kMaxConcurrentUrlFetches &&
+ !master_entries_to_fetch_.empty()) {
+ const GURL& url = *master_entries_to_fetch_.begin();
+
+ if (AlreadyFetchedEntry(url, AppCacheEntry::MASTER)) {
+ ++master_entries_completed_; // saved a URL request
+
+ // In no update case, associate hosts to newest cache in group
+ // now that master entry has been "successfully downloaded".
+ if (internal_state_ == NO_UPDATE) {
+ // TODO(michaeln): defer until the updated cache has been stored.
+ DCHECK(!inprogress_cache_.get());
+ AppCache* cache = group_->newest_complete_cache();
+ PendingMasters::iterator found = pending_master_entries_.find(url);
+ DCHECK(found != pending_master_entries_.end());
+ PendingHosts& hosts = found->second;
+ for (PendingHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ (*host_it)->AssociateCompleteCache(cache);
+ }
+ }
+ } else {
+ URLFetcher* fetcher = new URLFetcher(
+ url, URLFetcher::MASTER_ENTRY_FETCH, this);
+ fetcher->Start();
+ master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher));
+ }
+
+ master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
+ }
+}
+
+void AppCacheUpdateJob::CancelAllMasterEntryFetches(
+ const AppCacheErrorDetails& error_details) {
+ // For now, cancel all in-progress fetches for master entries and pretend
+ // all master entries fetches have completed.
+ // TODO(jennb): Delete this when update no longer fetches master entries
+ // directly.
+
+ // Cancel all in-progress fetches.
+ for (PendingUrlFetches::iterator it = master_entry_fetches_.begin();
+ it != master_entry_fetches_.end(); ++it) {
+ delete it->second;
+ master_entries_to_fetch_.insert(it->first); // back in unfetched list
+ }
+ master_entry_fetches_.clear();
+
+ master_entries_completed_ += master_entries_to_fetch_.size();
+
+ // Cache failure steps, step 2.
+ // Pretend all master entries that have not yet been fetched have completed
+ // downloading. Unassociate hosts from any appcache and send ERROR event.
+ HostNotifier host_notifier;
+ while (!master_entries_to_fetch_.empty()) {
+ const GURL& url = *master_entries_to_fetch_.begin();
+ PendingMasters::iterator found = pending_master_entries_.find(url);
+ DCHECK(found != pending_master_entries_.end());
+ PendingHosts& hosts = found->second;
+ for (PendingHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ AppCacheHost* host = *host_it;
+ host->AssociateNoCache(GURL());
+ host_notifier.AddHost(host);
+ host->RemoveObserver(this);
+ }
+ hosts.clear();
+
+ master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
+ }
+ host_notifier.SendErrorNotifications(error_details);
+}
+
+bool AppCacheUpdateJob::MaybeLoadFromNewestCache(const GURL& url,
+ AppCacheEntry& entry) {
+ if (update_type_ != UPGRADE_ATTEMPT)
+ return false;
+
+ AppCache* newest = group_->newest_complete_cache();
+ AppCacheEntry* copy_me = newest->GetEntry(url);
+ if (!copy_me || !copy_me->has_response_id())
+ return false;
+
+ // Load HTTP headers for entry from newest cache.
+ loading_responses_.insert(
+ LoadingResponses::value_type(copy_me->response_id(), url));
+ storage_->LoadResponseInfo(manifest_url_, group_->group_id(),
+ copy_me->response_id(),
+ this);
+ // Async: wait for OnResponseInfoLoaded to complete.
+ return true;
+}
+
+void AppCacheUpdateJob::OnResponseInfoLoaded(
+ AppCacheResponseInfo* response_info, int64 response_id) {
+ const net::HttpResponseInfo* http_info = response_info ?
+ response_info->http_response_info() : NULL;
+
+ // Needed response info for a manifest fetch request.
+ if (internal_state_ == FETCH_MANIFEST) {
+ if (http_info)
+ manifest_fetcher_->set_existing_response_headers(
+ http_info->headers.get());
+ manifest_fetcher_->Start();
+ return;
+ }
+
+ LoadingResponses::iterator found = loading_responses_.find(response_id);
+ DCHECK(found != loading_responses_.end());
+ const GURL& url = found->second;
+
+ if (!http_info) {
+ LoadFromNewestCacheFailed(url, NULL); // no response found
+ } else {
+ // Check if response can be re-used according to HTTP caching semantics.
+ // Responses with a "vary" header get treated as expired.
+ const std::string name = "vary";
+ std::string value;
+ void* iter = NULL;
+ if (!http_info->headers.get() ||
+ http_info->headers->RequiresValidation(http_info->request_time,
+ http_info->response_time,
+ base::Time::Now()) ||
+ http_info->headers->EnumerateHeader(&iter, name, &value)) {
+ LoadFromNewestCacheFailed(url, response_info);
+ } else {
+ DCHECK(group_->newest_complete_cache());
+ AppCacheEntry* copy_me = group_->newest_complete_cache()->GetEntry(url);
+ DCHECK(copy_me);
+ DCHECK(copy_me->response_id() == response_id);
+
+ AppCache::EntryMap::iterator it = url_file_list_.find(url);
+ DCHECK(it != url_file_list_.end());
+ AppCacheEntry& entry = it->second;
+ entry.set_response_id(response_id);
+ entry.set_response_size(copy_me->response_size());
+ inprogress_cache_->AddOrModifyEntry(url, entry);
+ NotifyAllProgress(url);
+ ++url_fetches_completed_;
+ }
+ }
+ loading_responses_.erase(found);
+
+ MaybeCompleteUpdate();
+}
+
+void AppCacheUpdateJob::LoadFromNewestCacheFailed(
+ const GURL& url, AppCacheResponseInfo* response_info) {
+ if (internal_state_ == CACHE_FAILURE)
+ return;
+
+ // Re-insert url at front of fetch list. Indicate storage has been checked.
+ urls_to_fetch_.push_front(UrlToFetch(url, true, response_info));
+ FetchUrls();
+}
+
+void AppCacheUpdateJob::MaybeCompleteUpdate() {
+ DCHECK(internal_state_ != CACHE_FAILURE);
+
+ // Must wait for any pending master entries or url fetches to complete.
+ if (master_entries_completed_ != pending_master_entries_.size() ||
+ url_fetches_completed_ != url_file_list_.size()) {
+ DCHECK(internal_state_ != COMPLETED);
+ return;
+ }
+
+ switch (internal_state_) {
+ case NO_UPDATE:
+ if (master_entries_completed_ > 0) {
+ switch (stored_state_) {
+ case UNSTORED:
+ StoreGroupAndCache();
+ return;
+ case STORING:
+ return;
+ case STORED:
+ break;
+ }
+ }
+ // 6.9.4 steps 7.3-7.7.
+ NotifyAllAssociatedHosts(APPCACHE_NO_UPDATE_EVENT);
+ DiscardDuplicateResponses();
+ internal_state_ = COMPLETED;
+ break;
+ case DOWNLOADING:
+ internal_state_ = REFETCH_MANIFEST;
+ FetchManifest(false);
+ break;
+ case REFETCH_MANIFEST:
+ DCHECK(stored_state_ == STORED);
+ NotifyAllFinalProgress();
+ if (update_type_ == CACHE_ATTEMPT)
+ NotifyAllAssociatedHosts(APPCACHE_CACHED_EVENT);
+ else
+ NotifyAllAssociatedHosts(APPCACHE_UPDATE_READY_EVENT);
+ DiscardDuplicateResponses();
+ internal_state_ = COMPLETED;
+ LogHistogramStats(UPDATE_OK, GURL());
+ break;
+ case CACHE_FAILURE:
+ NOTREACHED(); // See HandleCacheFailure
+ break;
+ default:
+ break;
+ }
+
+ // Let the stack unwind before deletion to make it less risky as this
+ // method is called from multiple places in this file.
+ if (internal_state_ == COMPLETED)
+ DeleteSoon();
+}
+
+void AppCacheUpdateJob::ScheduleUpdateRetry(int delay_ms) {
+ // TODO(jennb): post a delayed task with the "same parameters" as this job
+ // to retry the update at a later time. Need group, URLs of pending master
+ // entries and their hosts.
+}
+
+void AppCacheUpdateJob::Cancel() {
+ internal_state_ = CANCELLED;
+
+ LogHistogramStats(CANCELLED_ERROR, GURL());
+
+ if (manifest_fetcher_) {
+ delete manifest_fetcher_;
+ manifest_fetcher_ = NULL;
+ }
+
+ for (PendingUrlFetches::iterator it = pending_url_fetches_.begin();
+ it != pending_url_fetches_.end(); ++it) {
+ delete it->second;
+ }
+ pending_url_fetches_.clear();
+
+ for (PendingUrlFetches::iterator it = master_entry_fetches_.begin();
+ it != master_entry_fetches_.end(); ++it) {
+ delete it->second;
+ }
+ master_entry_fetches_.clear();
+
+ ClearPendingMasterEntries();
+ DiscardInprogressCache();
+
+ // Delete response writer to avoid any callbacks.
+ if (manifest_response_writer_)
+ manifest_response_writer_.reset();
+
+ storage_->CancelDelegateCallbacks(this);
+}
+
+void AppCacheUpdateJob::ClearPendingMasterEntries() {
+ for (PendingMasters::iterator it = pending_master_entries_.begin();
+ it != pending_master_entries_.end(); ++it) {
+ PendingHosts& hosts = it->second;
+ for (PendingHosts::iterator host_it = hosts.begin();
+ host_it != hosts.end(); ++host_it) {
+ (*host_it)->RemoveObserver(this);
+ }
+ }
+
+ pending_master_entries_.clear();
+}
+
+void AppCacheUpdateJob::DiscardInprogressCache() {
+ if (stored_state_ == STORING) {
+ // We can make no assumptions about whether the StoreGroupAndCacheTask
+ // actually completed or not. This condition should only be reachable
+ // during shutdown. Free things up and return to do no harm.
+ inprogress_cache_ = NULL;
+ added_master_entries_.clear();
+ return;
+ }
+
+ storage_->DoomResponses(manifest_url_, stored_response_ids_);
+
+ if (!inprogress_cache_.get()) {
+ // We have to undo the changes we made, if any, to the existing cache.
+ if (group_ && group_->newest_complete_cache()) {
+ for (std::vector<GURL>::iterator iter = added_master_entries_.begin();
+ iter != added_master_entries_.end(); ++iter) {
+ group_->newest_complete_cache()->RemoveEntry(*iter);
+ }
+ }
+ added_master_entries_.clear();
+ return;
+ }
+
+ AppCache::AppCacheHosts& hosts = inprogress_cache_->associated_hosts();
+ while (!hosts.empty())
+ (*hosts.begin())->AssociateNoCache(GURL());
+
+ inprogress_cache_ = NULL;
+ added_master_entries_.clear();
+}
+
+void AppCacheUpdateJob::DiscardDuplicateResponses() {
+ storage_->DoomResponses(manifest_url_, duplicate_response_ids_);
+}
+
+void AppCacheUpdateJob::LogHistogramStats(
+ ResultType result, const GURL& failed_resource_url) {
+ AppCacheHistograms::CountUpdateJobResult(result, manifest_url_.GetOrigin());
+ if (result == UPDATE_OK)
+ return;
+
+ int percent_complete = 0;
+ if (url_file_list_.size() > 0) {
+ size_t actual_fetches_completed = url_fetches_completed_;
+ if (!failed_resource_url.is_empty() && actual_fetches_completed)
+ --actual_fetches_completed;
+ percent_complete = (static_cast<double>(actual_fetches_completed) /
+ static_cast<double>(url_file_list_.size())) * 100.0;
+ percent_complete = std::min(percent_complete, 99);
+ }
+
+ bool was_making_progress =
+ base::Time::Now() - last_progress_time_ <
+ base::TimeDelta::FromMinutes(5);
+
+ bool off_origin_resource_failure =
+ !failed_resource_url.is_empty() &&
+ (failed_resource_url.GetOrigin() != manifest_url_.GetOrigin());
+
+ AppCacheHistograms::LogUpdateFailureStats(
+ manifest_url_.GetOrigin(),
+ percent_complete,
+ was_making_progress,
+ off_origin_resource_failure);
+}
+
+void AppCacheUpdateJob::DeleteSoon() {
+ ClearPendingMasterEntries();
+ manifest_response_writer_.reset();
+ storage_->CancelDelegateCallbacks(this);
+ service_->RemoveObserver(this);
+ service_ = NULL;
+
+ // Break the connection with the group so the group cannot call delete
+ // on this object after we've posted a task to delete ourselves.
+ group_->SetUpdateAppCacheStatus(AppCacheGroup::IDLE);
+ group_ = NULL;
+
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_update_job.h b/chromium/content/browser/appcache/appcache_update_job.h
new file mode 100644
index 00000000000..4d2d896ea74
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_update_job.h
@@ -0,0 +1,346 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
+
+#include <deque>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
+#include "url/gurl.h"
+
+namespace content {
+FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate);
+class AppCacheGroupTest;
+class AppCacheUpdateJobTest;
+class HostNotifier;
+
+// Application cache Update algorithm and state.
+class CONTENT_EXPORT AppCacheUpdateJob
+ : public AppCacheStorage::Delegate,
+ public AppCacheHost::Observer,
+ public AppCacheServiceImpl::Observer {
+ public:
+ // Used for uma stats only for now, so new values are append only.
+ enum ResultType {
+ UPDATE_OK, DB_ERROR, DISKCACHE_ERROR, QUOTA_ERROR, REDIRECT_ERROR,
+ MANIFEST_ERROR, NETWORK_ERROR, SERVER_ERROR, CANCELLED_ERROR,
+ SECURITY_ERROR, NUM_UPDATE_JOB_RESULT_TYPES
+ };
+
+ AppCacheUpdateJob(AppCacheServiceImpl* service, AppCacheGroup* group);
+ ~AppCacheUpdateJob() override;
+
+ // Triggers the update process or adds more info if this update is already
+ // in progress.
+ void StartUpdate(AppCacheHost* host, const GURL& new_master_resource);
+
+ private:
+ friend class content::AppCacheGroupTest;
+ friend class content::AppCacheUpdateJobTest;
+ class URLFetcher;
+
+ // Master entries have multiple hosts, for example, the same page is opened
+ // in different tabs.
+ typedef std::vector<AppCacheHost*> PendingHosts;
+ typedef std::map<GURL, PendingHosts> PendingMasters;
+ typedef std::map<GURL, URLFetcher*> PendingUrlFetches;
+ typedef std::map<int64, GURL> LoadingResponses;
+
+ static const int kRerunDelayMs = 1000;
+
+ // TODO(michaeln): Rework the set of states vs update types vs stored states.
+ // The NO_UPDATE state is really more of an update type. For all update types
+ // storing the results is relevant.
+
+ enum UpdateType {
+ UNKNOWN_TYPE,
+ UPGRADE_ATTEMPT,
+ CACHE_ATTEMPT,
+ };
+
+ enum InternalUpdateState {
+ FETCH_MANIFEST,
+ NO_UPDATE,
+ DOWNLOADING,
+
+ // Every state after this comment indicates the update is terminating.
+ REFETCH_MANIFEST,
+ CACHE_FAILURE,
+ CANCELLED,
+ COMPLETED,
+ };
+
+ enum StoredState {
+ UNSTORED,
+ STORING,
+ STORED,
+ };
+
+ struct UrlToFetch {
+ UrlToFetch(const GURL& url, bool checked, AppCacheResponseInfo* info);
+ ~UrlToFetch();
+
+ GURL url;
+ bool storage_checked;
+ scoped_refptr<AppCacheResponseInfo> existing_response_info;
+ };
+
+ class URLFetcher : public net::URLRequest::Delegate {
+ public:
+ enum FetchType {
+ MANIFEST_FETCH,
+ URL_FETCH,
+ MASTER_ENTRY_FETCH,
+ MANIFEST_REFETCH,
+ };
+ URLFetcher(const GURL& url,
+ FetchType fetch_type,
+ AppCacheUpdateJob* job);
+ ~URLFetcher() override;
+ void Start();
+ FetchType fetch_type() const { return fetch_type_; }
+ net::URLRequest* request() const { return request_.get(); }
+ const AppCacheEntry& existing_entry() const { return existing_entry_; }
+ const std::string& manifest_data() const { return manifest_data_; }
+ AppCacheResponseWriter* response_writer() const {
+ return response_writer_.get();
+ }
+ void set_existing_response_headers(net::HttpResponseHeaders* headers) {
+ existing_response_headers_ = headers;
+ }
+ void set_existing_entry(const AppCacheEntry& entry) {
+ existing_entry_ = entry;
+ }
+ ResultType result() const { return result_; }
+ int redirect_response_code() const { return redirect_response_code_; }
+
+ private:
+ // URLRequest::Delegate overrides
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) override;
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
+
+ void AddConditionalHeaders(const net::HttpResponseHeaders* headers);
+ void OnWriteComplete(int result);
+ void ReadResponseData();
+ bool ConsumeResponseData(int bytes_read);
+ void OnResponseCompleted();
+ bool MaybeRetryRequest();
+
+ GURL url_;
+ AppCacheUpdateJob* job_;
+ FetchType fetch_type_;
+ int retry_503_attempts_;
+ scoped_refptr<net::IOBuffer> buffer_;
+ scoped_ptr<net::URLRequest> request_;
+ AppCacheEntry existing_entry_;
+ scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
+ std::string manifest_data_;
+ ResultType result_;
+ int redirect_response_code_;
+ scoped_ptr<AppCacheResponseWriter> response_writer_;
+ }; // class URLFetcher
+
+ AppCacheResponseWriter* CreateResponseWriter();
+
+ // Methods for AppCacheStorage::Delegate.
+ void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
+ int64 response_id) override;
+ void OnGroupAndNewestCacheStored(AppCacheGroup* group,
+ AppCache* newest_cache,
+ bool success,
+ bool would_exceed_quota) override;
+ void OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) override;
+
+ // Methods for AppCacheHost::Observer.
+ void OnCacheSelectionComplete(AppCacheHost* host) override {} // N/A
+ void OnDestructionImminent(AppCacheHost* host) override;
+
+ // Methods for AppCacheServiceImpl::Observer.
+ void OnServiceReinitialized(AppCacheStorageReference* old_storage) override;
+
+ void HandleCacheFailure(const AppCacheErrorDetails& details,
+ ResultType result,
+ const GURL& failed_resource_url);
+
+ void FetchManifest(bool is_first_fetch);
+ void HandleManifestFetchCompleted(URLFetcher* fetcher);
+ void ContinueHandleManifestFetchCompleted(bool changed);
+
+ void HandleUrlFetchCompleted(URLFetcher* fetcher);
+ void HandleMasterEntryFetchCompleted(URLFetcher* fetcher);
+
+ void HandleManifestRefetchCompleted(URLFetcher* fetcher);
+ void OnManifestInfoWriteComplete(int result);
+ void OnManifestDataWriteComplete(int result);
+
+ void StoreGroupAndCache();
+
+ void NotifySingleHost(AppCacheHost* host, AppCacheEventID event_id);
+ void NotifyAllAssociatedHosts(AppCacheEventID event_id);
+ void NotifyAllProgress(const GURL& url);
+ void NotifyAllFinalProgress();
+ void NotifyAllError(const AppCacheErrorDetails& detals);
+ void LogConsoleMessageToAll(const std::string& message);
+ void AddAllAssociatedHostsToNotifier(HostNotifier* notifier);
+
+ // Checks if manifest is byte for byte identical with the manifest
+ // in the newest application cache.
+ void CheckIfManifestChanged();
+ void OnManifestDataReadComplete(int result);
+
+ // Creates the list of files that may need to be fetched and initiates
+ // fetches. Section 6.9.4 steps 12-17
+ void BuildUrlFileList(const AppCacheManifest& manifest);
+ void AddUrlToFileList(const GURL& url, int type);
+ void FetchUrls();
+ void CancelAllUrlFetches();
+ bool ShouldSkipUrlFetch(const AppCacheEntry& entry);
+
+ // If entry already exists in the cache currently being updated, merge
+ // the entry type information with the existing entry.
+ // Returns true if entry exists in cache currently being updated.
+ bool AlreadyFetchedEntry(const GURL& url, int entry_type);
+
+ // TODO(jennb): Delete when update no longer fetches master entries directly.
+ // Creates the list of master entries that need to be fetched and initiates
+ // fetches.
+ void AddMasterEntryToFetchList(AppCacheHost* host, const GURL& url,
+ bool is_new);
+ void FetchMasterEntries();
+ void CancelAllMasterEntryFetches(const AppCacheErrorDetails& details);
+
+ // Asynchronously loads the entry from the newest complete cache if the
+ // HTTP caching semantics allow.
+ // Returns false if immediately obvious that data cannot be loaded from
+ // newest complete cache.
+ bool MaybeLoadFromNewestCache(const GURL& url, AppCacheEntry& entry);
+ void LoadFromNewestCacheFailed(const GURL& url,
+ AppCacheResponseInfo* newest_response_info);
+
+ // Does nothing if update process is still waiting for pending master
+ // entries or URL fetches to complete downloading. Otherwise, completes
+ // the update process.
+ void MaybeCompleteUpdate();
+
+ // Schedules a rerun of the entire update with the same parameters as
+ // this update job after a short delay.
+ void ScheduleUpdateRetry(int delay_ms);
+
+ void Cancel();
+ void ClearPendingMasterEntries();
+ void DiscardInprogressCache();
+ void DiscardDuplicateResponses();
+
+ void LogHistogramStats(ResultType result, const GURL& failed_resource_url);
+ void MadeProgress() { last_progress_time_ = base::Time::Now(); }
+
+ // Deletes this object after letting the stack unwind.
+ void DeleteSoon();
+
+ bool IsTerminating() { return internal_state_ >= REFETCH_MANIFEST ||
+ stored_state_ != UNSTORED; }
+
+ AppCacheServiceImpl* service_;
+ const GURL manifest_url_; // here for easier access
+
+ // Defined prior to refs to AppCaches and Groups because destruction
+ // order matters, the disabled_storage_reference_ must outlive those
+ // objects.
+ scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
+
+ scoped_refptr<AppCache> inprogress_cache_;
+
+ AppCacheGroup* group_;
+
+ UpdateType update_type_;
+ InternalUpdateState internal_state_;
+ base::Time last_progress_time_;
+
+ PendingMasters pending_master_entries_;
+ size_t master_entries_completed_;
+
+ // TODO(jennb): Delete when update no longer fetches master entries directly.
+ // Helper containers to track which pending master entries have yet to be
+ // fetched and which are currently being fetched. Master entries that
+ // are listed in the manifest may be fetched as a regular URL instead of
+ // as a separate master entry fetch to optimize against duplicate fetches.
+ std::set<GURL> master_entries_to_fetch_;
+ PendingUrlFetches master_entry_fetches_;
+
+ // URLs of files to fetch along with their flags.
+ AppCache::EntryMap url_file_list_;
+ size_t url_fetches_completed_;
+
+ // Helper container to track which urls have not been fetched yet. URLs are
+ // removed when the fetch is initiated. Flag indicates whether an attempt
+ // to load the URL from storage has already been tried and failed.
+ std::deque<UrlToFetch> urls_to_fetch_;
+
+ // Helper container to track which urls are being loaded from response
+ // storage.
+ LoadingResponses loading_responses_;
+
+ // Keep track of pending URL requests so we can cancel them if necessary.
+ URLFetcher* manifest_fetcher_;
+ PendingUrlFetches pending_url_fetches_;
+
+ // Temporary storage of manifest response data for parsing and comparison.
+ std::string manifest_data_;
+ scoped_ptr<net::HttpResponseInfo> manifest_response_info_;
+ scoped_ptr<AppCacheResponseWriter> manifest_response_writer_;
+ scoped_refptr<net::IOBuffer> read_manifest_buffer_;
+ std::string loaded_manifest_data_;
+ scoped_ptr<AppCacheResponseReader> manifest_response_reader_;
+ bool manifest_has_valid_mime_type_;
+
+ // New master entries added to the cache by this job, used to cleanup
+ // in error conditions.
+ std::vector<GURL> added_master_entries_;
+
+ // Response ids stored by this update job, used to cleanup in
+ // error conditions.
+ std::vector<int64> stored_response_ids_;
+
+ // In some cases we fetch the same resource multiple times, and then
+ // have to delete the duplicates upon successful update. These ids
+ // are also in the stored_response_ids_ collection so we only schedule
+ // these for deletion on success.
+ // TODO(michaeln): Rework when we no longer fetches master entries directly.
+ std::vector<int64> duplicate_response_ids_;
+
+ // Whether we've stored the resulting group/cache yet.
+ StoredState stored_state_;
+
+ AppCacheStorage* storage_;
+
+ FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate);
+
+ DISALLOW_COPY_AND_ASSIGN(AppCacheUpdateJob);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_UPDATE_JOB_H_
diff --git a/chromium/content/browser/appcache/appcache_update_job_unittest.cc b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
index bc3957e6bea..4955a71d780 100644
--- a/chromium/content/browser/appcache/appcache_update_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_update_job_unittest.cc
@@ -7,6 +7,10 @@
#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_update_job.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
@@ -15,35 +19,6 @@
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_host.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_update_job.h"
-
-using appcache::AppCache;
-using appcache::AppCacheEntry;
-using appcache::AppCacheFrontend;
-using appcache::AppCacheHost;
-using appcache::AppCacheGroup;
-using appcache::AppCacheResponseInfo;
-using appcache::AppCacheUpdateJob;
-using appcache::AppCacheResponseWriter;
-using appcache::APPCACHE_CACHED_EVENT;
-using appcache::APPCACHE_CHECKING_EVENT;
-using appcache::APPCACHE_DOWNLOADING_EVENT;
-using appcache::APPCACHE_ERROR_EVENT;
-using appcache::AppCacheEventID;
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::HttpResponseInfoIOBuffer;
-using appcache::kAppCacheNoCacheId;
-using appcache::kAppCacheNoResponseId;
-using appcache::Namespace;
-using appcache::APPCACHE_NETWORK_NAMESPACE;
-using appcache::APPCACHE_NO_UPDATE_EVENT;
-using appcache::APPCACHE_OBSOLETE_EVENT;
-using appcache::APPCACHE_PROGRESS_EVENT;
-using appcache::APPCACHE_UPDATE_READY_EVENT;
-using appcache::AppCacheStatus;
namespace content {
class AppCacheUpdateJobTest;
@@ -220,14 +195,15 @@ class MockHttpServer {
class MockHttpServerJobFactory
: public net::URLRequestJobFactory::ProtocolHandler {
public:
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
return MockHttpServer::JobFactory(request, network_delegate);
}
};
-inline bool operator==(const Namespace& lhs, const Namespace& rhs) {
+inline bool operator==(const AppCacheNamespace& lhs,
+ const AppCacheNamespace& rhs) {
return lhs.type == rhs.type &&
lhs.namespace_url == rhs.namespace_url &&
lhs.target_url == rhs.target_url;
@@ -243,16 +219,13 @@ class MockFrontend : public AppCacheFrontend {
start_update_trigger_(APPCACHE_CHECKING_EVENT), update_(NULL) {
}
- virtual void OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) OVERRIDE {
- }
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override {}
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- AppCacheStatus status) OVERRIDE {
- }
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override {}
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- AppCacheEventID event_id) OVERRIDE {
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override {
raised_events_.push_back(RaisedEvent(host_ids, event_id));
// Trigger additional updates if requested.
@@ -267,17 +240,16 @@ class MockFrontend : public AppCacheFrontend {
}
}
- virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details)
- OVERRIDE {
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override {
error_message_ = details.message;
OnEventRaised(host_ids, APPCACHE_ERROR_EVENT);
}
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total,
- int num_complete) OVERRIDE {
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override {
if (!ignore_progress_events_)
OnEventRaised(host_ids, APPCACHE_PROGRESS_EVENT);
@@ -305,14 +277,11 @@ class MockFrontend : public AppCacheFrontend {
}
}
- virtual void OnLogMessage(int host_id,
- appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE {
- }
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override {}
- virtual void OnContentBlocked(int host_id,
- const GURL& manifest_url) OVERRIDE {
- }
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override {}
void AddExpectedEvent(const std::vector<int>& host_ids,
AppCacheEventID event_id) {
@@ -369,9 +338,9 @@ class MockFrontend : public AppCacheFrontend {
// Helper factories to simulate redirected URL responses for tests.
class RedirectFactory : public net::URLRequestJobFactory::ProtocolHandler {
public:
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
return new net::URLRequestTestJob(
request,
network_delegate,
@@ -423,10 +392,10 @@ class RetryRequestTestJob : public net::URLRequestTestJob {
}
}
- virtual int GetResponseCode() const OVERRIDE { return response_code_; }
+ int GetResponseCode() const override { return response_code_; }
private:
- virtual ~RetryRequestTestJob() {}
+ ~RetryRequestTestJob() override {}
static std::string retry_headers() {
const char no_retry_after[] =
@@ -485,9 +454,9 @@ class RetryRequestTestJob : public net::URLRequestTestJob {
class RetryRequestTestJobFactory
: public net::URLRequestJobFactory::ProtocolHandler {
public:
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
return RetryRequestTestJob::RetryFactory(request, network_delegate);
}
};
@@ -545,7 +514,7 @@ class HttpHeadersRequestTestJob : public net::URLRequestTestJob {
}
protected:
- virtual ~HttpHeadersRequestTestJob() {}
+ ~HttpHeadersRequestTestJob() override {}
private:
static std::string expect_if_modified_since_;
@@ -565,9 +534,9 @@ bool HttpHeadersRequestTestJob::already_checked_ = false;
class IfModifiedSinceJobFactory
: public net::URLRequestJobFactory::ProtocolHandler {
public:
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
return HttpHeadersRequestTestJob::IfModifiedSinceFactory(
request, network_delegate);
}
@@ -579,9 +548,7 @@ class IOThread : public base::Thread {
: base::Thread(name) {
}
- virtual ~IOThread() {
- Stop();
- }
+ ~IOThread() override { Stop(); }
net::URLRequestContext* request_context() {
return request_context_.get();
@@ -593,7 +560,7 @@ class IOThread : public base::Thread {
request_context_->set_job_factory(job_factory_.get());
}
- virtual void Init() OVERRIDE {
+ void Init() override {
scoped_ptr<net::URLRequestJobFactoryImpl> factory(
new net::URLRequestJobFactoryImpl());
factory->SetProtocolHandler("http", new MockHttpServerJobFactory);
@@ -603,7 +570,7 @@ class IOThread : public base::Thread {
request_context_->set_job_factory(job_factory_.get());
}
- virtual void CleanUp() OVERRIDE {
+ void CleanUp() override {
request_context_.reset();
job_factory_.reset();
}
@@ -3041,8 +3008,8 @@ class AppCacheUpdateJobTest : public testing::Test,
group_->AddUpdateObserver(this);
}
- virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE {
- ASSERT_EQ(group_, group);
+ void OnUpdateComplete(AppCacheGroup* group) override {
+ ASSERT_EQ(group_.get(), group);
protect_newest_cache_ = group->newest_complete_cache();
UpdateFinished();
}
@@ -3216,7 +3183,7 @@ class AppCacheUpdateJobTest : public testing::Test,
if (tested_manifest_) {
AppCache* cache = group_->newest_complete_cache();
ASSERT_TRUE(cache != NULL);
- EXPECT_EQ(group_, cache->owning_group());
+ EXPECT_EQ(group_.get(), cache->owning_group());
EXPECT_TRUE(cache->is_complete());
switch (tested_manifest_) {
@@ -3273,7 +3240,7 @@ class AppCacheUpdateJobTest : public testing::Test,
expected = 1;
ASSERT_EQ(expected, cache->fallback_namespaces_.size());
EXPECT_TRUE(cache->fallback_namespaces_[0] ==
- Namespace(
+ AppCacheNamespace(
APPCACHE_FALLBACK_NAMESPACE,
MockHttpServer::GetMockUrl("files/fallback1"),
MockHttpServer::GetMockUrl("files/fallback1a"),
@@ -3301,7 +3268,7 @@ class AppCacheUpdateJobTest : public testing::Test,
expected = 1;
ASSERT_EQ(expected, cache->fallback_namespaces_.size());
EXPECT_TRUE(cache->fallback_namespaces_[0] ==
- Namespace(
+ AppCacheNamespace(
APPCACHE_FALLBACK_NAMESPACE,
MockHttpServer::GetMockUrl("files/fallback1"),
MockHttpServer::GetMockUrl("files/explicit1"),
@@ -3309,7 +3276,7 @@ class AppCacheUpdateJobTest : public testing::Test,
EXPECT_EQ(expected, cache->online_whitelist_namespaces_.size());
EXPECT_TRUE(cache->online_whitelist_namespaces_[0] ==
- Namespace(
+ AppCacheNamespace(
APPCACHE_NETWORK_NAMESPACE,
MockHttpServer::GetMockUrl("files/online1"),
GURL(), false));
@@ -3498,7 +3465,7 @@ TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
EXPECT_EQ(expected, events[1].first.size());
EXPECT_EQ(host.host_id(), events[1].first[0]);
- EXPECT_EQ(appcache::APPCACHE_DOWNLOADING_EVENT, events[1].second);
+ EXPECT_EQ(APPCACHE_DOWNLOADING_EVENT, events[1].second);
EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
}
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.cc b/chromium/content/browser/appcache/appcache_url_request_job.cc
new file mode 100644
index 00000000000..b12a5b6db5f
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_url_request_job.cc
@@ -0,0 +1,449 @@
+// Copyright (c) 2012 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 "content/browser/appcache/appcache_url_request_job.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_histograms.h"
+#include "content/browser/appcache/appcache_host.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_status.h"
+
+namespace content {
+
+AppCacheURLRequestJob::AppCacheURLRequestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheStorage* storage,
+ AppCacheHost* host,
+ bool is_main_resource)
+ : net::URLRequestJob(request, network_delegate),
+ host_(host),
+ storage_(storage),
+ has_been_started_(false), has_been_killed_(false),
+ delivery_type_(AWAITING_DELIVERY_ORDERS),
+ group_id_(0), cache_id_(kAppCacheNoCacheId), is_fallback_(false),
+ is_main_resource_(is_main_resource),
+ cache_entry_not_found_(false),
+ weak_factory_(this) {
+ DCHECK(storage_);
+}
+
+void AppCacheURLRequestJob::DeliverAppCachedResponse(
+ const GURL& manifest_url, int64 group_id, int64 cache_id,
+ const AppCacheEntry& entry, bool is_fallback) {
+ DCHECK(!has_delivery_orders());
+ DCHECK(entry.has_response_id());
+ delivery_type_ = APPCACHED_DELIVERY;
+ manifest_url_ = manifest_url;
+ group_id_ = group_id;
+ cache_id_ = cache_id;
+ entry_ = entry;
+ is_fallback_ = is_fallback;
+ MaybeBeginDelivery();
+}
+
+void AppCacheURLRequestJob::DeliverNetworkResponse() {
+ DCHECK(!has_delivery_orders());
+ delivery_type_ = NETWORK_DELIVERY;
+ storage_ = NULL; // not needed
+ MaybeBeginDelivery();
+}
+
+void AppCacheURLRequestJob::DeliverErrorResponse() {
+ DCHECK(!has_delivery_orders());
+ delivery_type_ = ERROR_DELIVERY;
+ storage_ = NULL; // not needed
+ MaybeBeginDelivery();
+}
+
+void AppCacheURLRequestJob::MaybeBeginDelivery() {
+ if (has_been_started() && has_delivery_orders()) {
+ // Start asynchronously so that all error reporting and data
+ // callbacks happen as they would for network requests.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AppCacheURLRequestJob::BeginDelivery,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+void AppCacheURLRequestJob::BeginDelivery() {
+ DCHECK(has_delivery_orders() && has_been_started());
+
+ if (has_been_killed())
+ return;
+
+ switch (delivery_type_) {
+ case NETWORK_DELIVERY:
+ AppCacheHistograms::AddNetworkJobStartDelaySample(
+ base::TimeTicks::Now() - start_time_tick_);
+ // To fallthru to the network, we restart the request which will
+ // cause a new job to be created to retrieve the resource from the
+ // network. Our caller is responsible for arranging to not re-intercept
+ // the same request.
+ NotifyRestartRequired();
+ break;
+
+ case ERROR_DELIVERY:
+ AppCacheHistograms::AddErrorJobStartDelaySample(
+ base::TimeTicks::Now() - start_time_tick_);
+ request()->net_log().AddEvent(
+ net::NetLog::TYPE_APPCACHE_DELIVERING_ERROR_RESPONSE);
+ NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ break;
+
+ case APPCACHED_DELIVERY:
+ if (entry_.IsExecutable()) {
+ BeginExecutableHandlerDelivery();
+ return;
+ }
+ AppCacheHistograms::AddAppCacheJobStartDelaySample(
+ base::TimeTicks::Now() - start_time_tick_);
+ request()->net_log().AddEvent(
+ is_fallback_ ?
+ net::NetLog::TYPE_APPCACHE_DELIVERING_FALLBACK_RESPONSE :
+ net::NetLog::TYPE_APPCACHE_DELIVERING_CACHED_RESPONSE);
+ storage_->LoadResponseInfo(
+ manifest_url_, group_id_, entry_.response_id(), this);
+ break;
+
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void AppCacheURLRequestJob::BeginExecutableHandlerDelivery() {
+ DCHECK(CommandLine::ForCurrentProcess()->
+ HasSwitch(kEnableExecutableHandlers));
+ if (!storage_->service()->handler_factory()) {
+ BeginErrorDelivery("missing handler factory");
+ return;
+ }
+
+ request()->net_log().AddEvent(
+ net::NetLog::TYPE_APPCACHE_DELIVERING_EXECUTABLE_RESPONSE);
+
+ // We defer job delivery until the executable handler is spun up and
+ // provides a response. The sequence goes like this...
+ //
+ // 1. First we load the cache.
+ // 2. Then if the handler is not spun up, we load the script resource which
+ // is needed to spin it up.
+ // 3. Then we ask then we ask the handler to compute a response.
+ // 4. Finally we deilver that response to the caller.
+ storage_->LoadCache(cache_id_, this);
+}
+
+void AppCacheURLRequestJob::OnCacheLoaded(AppCache* cache, int64 cache_id) {
+ DCHECK_EQ(cache_id_, cache_id);
+ DCHECK(!has_been_killed());
+
+ if (!cache) {
+ BeginErrorDelivery("cache load failed");
+ return;
+ }
+
+ // Keep references to ensure they don't go out of scope until job completion.
+ cache_ = cache;
+ group_ = cache->owning_group();
+
+ // If the handler is spun up, ask it to compute a response.
+ AppCacheExecutableHandler* handler =
+ cache->GetExecutableHandler(entry_.response_id());
+ if (handler) {
+ InvokeExecutableHandler(handler);
+ return;
+ }
+
+ // Handler is not spun up yet, load the script resource to do that.
+ // NOTE: This is not ideal since multiple jobs may be doing this,
+ // concurrently but close enough for now, the first to load the script
+ // will win.
+
+ // Read the script data, truncating if its too large.
+ // NOTE: we just issue one read and don't bother chaining if the resource
+ // is very (very) large, close enough for now.
+ const int64 kLimit = 500 * 1000;
+ handler_source_buffer_ = new net::GrowableIOBuffer();
+ handler_source_buffer_->SetCapacity(kLimit);
+ handler_source_reader_.reset(storage_->CreateResponseReader(
+ manifest_url_, group_id_, entry_.response_id()));
+ handler_source_reader_->ReadData(
+ handler_source_buffer_.get(),
+ kLimit,
+ base::Bind(&AppCacheURLRequestJob::OnExecutableSourceLoaded,
+ base::Unretained(this)));
+}
+
+void AppCacheURLRequestJob::OnExecutableSourceLoaded(int result) {
+ DCHECK(!has_been_killed());
+ handler_source_reader_.reset();
+ if (result < 0) {
+ BeginErrorDelivery("script source load failed");
+ return;
+ }
+
+ handler_source_buffer_->SetCapacity(result); // Free up some memory.
+
+ AppCacheExecutableHandler* handler = cache_->GetOrCreateExecutableHandler(
+ entry_.response_id(), handler_source_buffer_.get());
+ handler_source_buffer_ = NULL; // not needed anymore
+ if (handler) {
+ InvokeExecutableHandler(handler);
+ return;
+ }
+
+ BeginErrorDelivery("factory failed to produce a handler");
+}
+
+void AppCacheURLRequestJob::InvokeExecutableHandler(
+ AppCacheExecutableHandler* handler) {
+ handler->HandleRequest(
+ request(),
+ base::Bind(&AppCacheURLRequestJob::OnExecutableResponseCallback,
+ weak_factory_.GetWeakPtr()));
+}
+
+void AppCacheURLRequestJob::OnExecutableResponseCallback(
+ const AppCacheExecutableHandler::Response& response) {
+ DCHECK(!has_been_killed());
+ if (response.use_network) {
+ delivery_type_ = NETWORK_DELIVERY;
+ storage_ = NULL;
+ BeginDelivery();
+ return;
+ }
+
+ if (!response.cached_resource_url.is_empty()) {
+ AppCacheEntry* entry_ptr = cache_->GetEntry(response.cached_resource_url);
+ if (entry_ptr && !entry_ptr->IsExecutable()) {
+ entry_ = *entry_ptr;
+ BeginDelivery();
+ return;
+ }
+ }
+
+ if (!response.redirect_url.is_empty()) {
+ // TODO(michaeln): playback a redirect
+ // response_headers_(new HttpResponseHeaders(response_headers)),
+ // fallthru for now to deliver an error
+ }
+
+ // Otherwise, return an error.
+ BeginErrorDelivery("handler returned an invalid response");
+}
+
+void AppCacheURLRequestJob::BeginErrorDelivery(const char* message) {
+ if (host_)
+ host_->frontend()->OnLogMessage(host_->host_id(), APPCACHE_LOG_ERROR,
+ message);
+ delivery_type_ = ERROR_DELIVERY;
+ storage_ = NULL;
+ BeginDelivery();
+}
+
+AppCacheURLRequestJob::~AppCacheURLRequestJob() {
+ if (storage_)
+ storage_->CancelDelegateCallbacks(this);
+}
+
+void AppCacheURLRequestJob::OnResponseInfoLoaded(
+ AppCacheResponseInfo* response_info, int64 response_id) {
+ DCHECK(is_delivering_appcache_response());
+ scoped_refptr<AppCacheURLRequestJob> protect(this);
+ if (response_info) {
+ info_ = response_info;
+ reader_.reset(storage_->CreateResponseReader(
+ manifest_url_, group_id_, entry_.response_id()));
+
+ if (is_range_request())
+ SetupRangeResponse();
+
+ NotifyHeadersComplete();
+ } else {
+ if (storage_->service()->storage() == storage_) {
+ // A resource that is expected to be in the appcache is missing.
+ // See http://code.google.com/p/chromium/issues/detail?id=50657
+ // Instead of failing the request, we restart the request. The retry
+ // attempt will fallthru to the network instead of trying to load
+ // from the appcache.
+ storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
+ entry_.response_id());
+ AppCacheHistograms::CountResponseRetrieval(
+ false, is_main_resource_, manifest_url_.GetOrigin());
+ }
+ cache_entry_not_found_ = true;
+ NotifyRestartRequired();
+ }
+}
+
+const net::HttpResponseInfo* AppCacheURLRequestJob::http_info() const {
+ if (!info_.get())
+ return NULL;
+ if (range_response_info_)
+ return range_response_info_.get();
+ return info_->http_response_info();
+}
+
+void AppCacheURLRequestJob::SetupRangeResponse() {
+ DCHECK(is_range_request() && info_.get() && reader_.get() &&
+ is_delivering_appcache_response());
+ int resource_size = static_cast<int>(info_->response_data_size());
+ if (resource_size < 0 || !range_requested_.ComputeBounds(resource_size)) {
+ range_requested_ = net::HttpByteRange();
+ return;
+ }
+
+ DCHECK(range_requested_.IsValid());
+ int offset = static_cast<int>(range_requested_.first_byte_position());
+ int length = static_cast<int>(range_requested_.last_byte_position() -
+ range_requested_.first_byte_position() + 1);
+
+ // Tell the reader about the range to read.
+ reader_->SetReadRange(offset, length);
+
+ // Make a copy of the full response headers and fix them up
+ // for the range we'll be returning.
+ range_response_info_.reset(
+ new net::HttpResponseInfo(*info_->http_response_info()));
+ net::HttpResponseHeaders* headers = range_response_info_->headers.get();
+ headers->UpdateWithNewRange(
+ range_requested_, resource_size, true /* replace status line */);
+}
+
+void AppCacheURLRequestJob::OnReadComplete(int result) {
+ DCHECK(is_delivering_appcache_response());
+ if (result == 0) {
+ NotifyDone(net::URLRequestStatus());
+ AppCacheHistograms::CountResponseRetrieval(
+ true, is_main_resource_, manifest_url_.GetOrigin());
+ } else if (result < 0) {
+ if (storage_->service()->storage() == storage_) {
+ storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
+ entry_.response_id());
+ }
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
+ AppCacheHistograms::CountResponseRetrieval(
+ false, is_main_resource_, manifest_url_.GetOrigin());
+ } else {
+ SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
+ }
+ NotifyReadComplete(result);
+}
+
+// net::URLRequestJob overrides ------------------------------------------------
+
+void AppCacheURLRequestJob::Start() {
+ DCHECK(!has_been_started());
+ has_been_started_ = true;
+ start_time_tick_ = base::TimeTicks::Now();
+ MaybeBeginDelivery();
+}
+
+void AppCacheURLRequestJob::Kill() {
+ if (!has_been_killed_) {
+ has_been_killed_ = true;
+ reader_.reset();
+ handler_source_reader_.reset();
+ if (storage_) {
+ storage_->CancelDelegateCallbacks(this);
+ storage_ = NULL;
+ }
+ host_ = NULL;
+ info_ = NULL;
+ cache_ = NULL;
+ group_ = NULL;
+ range_response_info_.reset();
+ net::URLRequestJob::Kill();
+ weak_factory_.InvalidateWeakPtrs();
+ }
+}
+
+net::LoadState AppCacheURLRequestJob::GetLoadState() const {
+ if (!has_been_started())
+ return net::LOAD_STATE_IDLE;
+ if (!has_delivery_orders())
+ return net::LOAD_STATE_WAITING_FOR_APPCACHE;
+ if (delivery_type_ != APPCACHED_DELIVERY)
+ return net::LOAD_STATE_IDLE;
+ if (!info_.get())
+ return net::LOAD_STATE_WAITING_FOR_APPCACHE;
+ if (reader_.get() && reader_->IsReadPending())
+ return net::LOAD_STATE_READING_RESPONSE;
+ return net::LOAD_STATE_IDLE;
+}
+
+bool AppCacheURLRequestJob::GetMimeType(std::string* mime_type) const {
+ if (!http_info())
+ return false;
+ return http_info()->headers->GetMimeType(mime_type);
+}
+
+bool AppCacheURLRequestJob::GetCharset(std::string* charset) {
+ if (!http_info())
+ return false;
+ return http_info()->headers->GetCharset(charset);
+}
+
+void AppCacheURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
+ if (!http_info())
+ return;
+ *info = *http_info();
+}
+
+int AppCacheURLRequestJob::GetResponseCode() const {
+ if (!http_info())
+ return -1;
+ return http_info()->headers->response_code();
+}
+
+bool AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size,
+ int *bytes_read) {
+ DCHECK(is_delivering_appcache_response());
+ DCHECK_NE(buf_size, 0);
+ DCHECK(bytes_read);
+ DCHECK(!reader_->IsReadPending());
+ reader_->ReadData(
+ buf, buf_size, base::Bind(&AppCacheURLRequestJob::OnReadComplete,
+ base::Unretained(this)));
+ SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
+ return false;
+}
+
+void AppCacheURLRequestJob::SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) {
+ std::string value;
+ std::vector<net::HttpByteRange> ranges;
+ if (!headers.GetHeader(net::HttpRequestHeaders::kRange, &value) ||
+ !net::HttpUtil::ParseRangeHeader(value, &ranges)) {
+ return;
+ }
+
+ // If multiple ranges are requested, we play dumb and
+ // return the entire response with 200 OK.
+ if (ranges.size() == 1U)
+ range_requested_ = ranges[0];
+}
+
+} // namespace content
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.h b/chromium/content/browser/appcache/appcache_url_request_job.h
new file mode 100644
index 00000000000..580b86a58a2
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_url_request_job.h
@@ -0,0 +1,175 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_APPCACHE_APPCACHE_URL_REQUEST_JOB_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_URL_REQUEST_JOB_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_executable_handler.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_storage.h"
+#include "content/common/content_export.h"
+#include "net/http/http_byte_range.h"
+#include "net/url_request/url_request_job.h"
+
+namespace net {
+class GrowableIOBuffer;
+};
+
+namespace content {
+class AppCacheHost;
+class AppCacheRequestHandlerTest;
+class AppCacheURLRequestJobTest;
+
+// A net::URLRequestJob derivative that knows how to return a response stored
+// in the appcache.
+class CONTENT_EXPORT AppCacheURLRequestJob
+ : public net::URLRequestJob,
+ public AppCacheStorage::Delegate {
+ public:
+ AppCacheURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ AppCacheStorage* storage,
+ AppCacheHost* host,
+ bool is_main_resource);
+
+ // Informs the job of what response it should deliver. Only one of these
+ // methods should be called, and only once per job. A job will sit idle and
+ // wait indefinitely until one of the deliver methods is called.
+ void DeliverAppCachedResponse(const GURL& manifest_url, int64 group_id,
+ int64 cache_id, const AppCacheEntry& entry,
+ bool is_fallback);
+ void DeliverNetworkResponse();
+ void DeliverErrorResponse();
+
+ bool is_waiting() const {
+ return delivery_type_ == AWAITING_DELIVERY_ORDERS;
+ }
+
+ bool is_delivering_appcache_response() const {
+ return delivery_type_ == APPCACHED_DELIVERY;
+ }
+
+ bool is_delivering_network_response() const {
+ return delivery_type_ == NETWORK_DELIVERY;
+ }
+
+ bool is_delivering_error_response() const {
+ return delivery_type_ == ERROR_DELIVERY;
+ }
+
+ // Accessors for the info about the appcached response, if any,
+ // that this job has been instructed to deliver. These are only
+ // valid to call if is_delivering_appcache_response.
+ const GURL& manifest_url() const { return manifest_url_; }
+ int64 group_id() const { return group_id_; }
+ int64 cache_id() const { return cache_id_; }
+ const AppCacheEntry& entry() const { return entry_; }
+
+ // net::URLRequestJob's Kill method is made public so the users of this
+ // class in the appcache namespace can call it.
+ void Kill() override;
+
+ // Returns true if the job has been started by the net library.
+ bool has_been_started() const {
+ return has_been_started_;
+ }
+
+ // Returns true if the job has been killed.
+ bool has_been_killed() const {
+ return has_been_killed_;
+ }
+
+ // Returns true if the cache entry was not found in the disk cache.
+ bool cache_entry_not_found() const {
+ return cache_entry_not_found_;
+ }
+
+ protected:
+ ~AppCacheURLRequestJob() override;
+
+ private:
+ friend class content::AppCacheRequestHandlerTest;
+ friend class content::AppCacheURLRequestJobTest;
+
+ enum DeliveryType {
+ AWAITING_DELIVERY_ORDERS,
+ APPCACHED_DELIVERY,
+ NETWORK_DELIVERY,
+ ERROR_DELIVERY
+ };
+
+ // Returns true if one of the Deliver methods has been called.
+ bool has_delivery_orders() const {
+ return !is_waiting();
+ }
+
+ void MaybeBeginDelivery();
+ void BeginDelivery();
+
+ // For executable response handling.
+ void BeginExecutableHandlerDelivery();
+ void OnExecutableSourceLoaded(int result);
+ void InvokeExecutableHandler(AppCacheExecutableHandler* handler);
+ void OnExecutableResponseCallback(
+ const AppCacheExecutableHandler::Response& response);
+ void BeginErrorDelivery(const char* message);
+
+ // AppCacheStorage::Delegate methods
+ void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
+ int64 response_id) override;
+ void OnCacheLoaded(AppCache* cache, int64 cache_id) override;
+
+ const net::HttpResponseInfo* http_info() const;
+ bool is_range_request() const { return range_requested_.IsValid(); }
+ void SetupRangeResponse();
+
+ // AppCacheResponseReader completion callback
+ void OnReadComplete(int result);
+
+ // net::URLRequestJob methods, see url_request_job.h for doc comments
+ void Start() override;
+ net::LoadState GetLoadState() const override;
+ bool GetCharset(std::string* charset) override;
+ void GetResponseInfo(net::HttpResponseInfo* info) override;
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
+
+ // Sets extra request headers for Job types that support request headers.
+ // This is how we get informed of range-requests.
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
+
+ // FilterContext methods
+ bool GetMimeType(std::string* mime_type) const override;
+ int GetResponseCode() const override;
+
+ AppCacheHost* host_;
+ AppCacheStorage* storage_;
+ base::TimeTicks start_time_tick_;
+ bool has_been_started_;
+ bool has_been_killed_;
+ DeliveryType delivery_type_;
+ GURL manifest_url_;
+ int64 group_id_;
+ int64 cache_id_;
+ AppCacheEntry entry_;
+ bool is_fallback_;
+ bool is_main_resource_; // Used for histogram logging.
+ bool cache_entry_not_found_;
+ scoped_refptr<AppCacheResponseInfo> info_;
+ scoped_refptr<net::GrowableIOBuffer> handler_source_buffer_;
+ scoped_ptr<AppCacheResponseReader> handler_source_reader_;
+ net::HttpByteRange range_requested_;
+ scoped_ptr<net::HttpResponseInfo> range_response_info_;
+ scoped_ptr<AppCacheResponseReader> reader_;
+ scoped_refptr<AppCache> cache_;
+ scoped_refptr<AppCacheGroup> group_;
+ base::WeakPtrFactory<AppCacheURLRequestJob> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_REQUEST_HANDLER_H_
diff --git a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
index edaa07e8e38..8acc71c7c9c 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job_unittest.cc
@@ -9,9 +9,13 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_url_request_job.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -22,17 +26,8 @@
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_url_request_job.h"
-
-using appcache::AppCacheEntry;
-using appcache::AppCacheStorage;
-using appcache::AppCacheResponseInfo;
-using appcache::AppCacheResponseReader;
-using appcache::AppCacheResponseWriter;
-using appcache::AppCacheURLRequestJob;
-using appcache::HttpResponseInfoIOBuffer;
-using appcache::kAppCacheNoCacheId;
+#include "url/gurl.h"
+
using net::IOBuffer;
using net::WrappedIOBuffer;
@@ -51,9 +46,7 @@ class MockURLRequestJobFactory : public net::URLRequestJobFactory {
MockURLRequestJobFactory() : job_(NULL) {
}
- virtual ~MockURLRequestJobFactory() {
- DCHECK(!job_);
- }
+ ~MockURLRequestJobFactory() override { DCHECK(!job_); }
void SetJob(net::URLRequestJob* job) {
job_ = job;
@@ -64,10 +57,10 @@ class MockURLRequestJobFactory : public net::URLRequestJobFactory {
}
// net::URLRequestJobFactory implementation.
- virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
if (job_) {
net::URLRequestJob* temp = job_;
job_ = NULL;
@@ -79,20 +72,33 @@ class MockURLRequestJobFactory : public net::URLRequestJobFactory {
}
}
- virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return nullptr;
+ }
+
+ bool IsHandledProtocol(const std::string& scheme) const override {
return scheme == "http";
};
- virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+ bool IsHandledURL(const GURL& url) const override {
return url.SchemeIs("http");
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
- private:
- mutable net::URLRequestJob* job_;
+ private:
+ mutable net::URLRequestJob* job_;
};
class AppCacheURLRequestJobTest : public testing::Test {
@@ -107,8 +113,8 @@ class AppCacheURLRequestJobTest : public testing::Test {
: loaded_info_id_(0), test_(test) {
}
- virtual void OnResponseInfoLoaded(AppCacheResponseInfo* info,
- int64 response_id) OVERRIDE {
+ void OnResponseInfoLoaded(AppCacheResponseInfo* info,
+ int64 response_id) override {
loaded_info_ = info;
loaded_info_id_ = response_id;
test_->ScheduleNextTask();
@@ -128,7 +134,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
kill_after_amount_received_(0), kill_with_io_pending_(false) {
}
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE {
+ void OnResponseStarted(net::URLRequest* request) override {
amount_received_ = 0;
did_receive_headers_ = false;
if (request->status().is_success()) {
@@ -141,8 +147,7 @@ class AppCacheURLRequestJobTest : public testing::Test {
}
}
- virtual void OnReadCompleted(net::URLRequest* request,
- int bytes_read) OVERRIDE {
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override {
if (bytes_read > 0) {
amount_received_ += bytes_read;
@@ -424,14 +429,13 @@ class AppCacheURLRequestJobTest : public testing::Test {
// Basic -------------------------------------------------------------------
void Basic() {
AppCacheStorage* storage = service_->storage();
- net::URLRequest request(GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL,
- empty_context_.get());
+ scoped_ptr<net::URLRequest> request(empty_context_->CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, NULL));
scoped_refptr<AppCacheURLRequestJob> job;
// Create an instance and see that it looks as expected.
- job = new AppCacheURLRequestJob(
- &request, NULL, storage, NULL, false);
+ job = new AppCacheURLRequestJob(request.get(), NULL, storage, NULL, false);
EXPECT_TRUE(job->is_waiting());
EXPECT_FALSE(job->is_delivering_appcache_response());
EXPECT_FALSE(job->is_delivering_network_response());
@@ -448,24 +452,24 @@ class AppCacheURLRequestJobTest : public testing::Test {
// DeliveryOrders -----------------------------------------------------
void DeliveryOrders() {
AppCacheStorage* storage = service_->storage();
- net::URLRequest request(GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL,
- empty_context_.get());
+ scoped_ptr<net::URLRequest> request(empty_context_->CreateRequest(
+ GURL("http://blah/"), net::DEFAULT_PRIORITY, NULL, NULL));
scoped_refptr<AppCacheURLRequestJob> job;
// Create an instance, give it a delivery order and see that
// it looks as expected.
- job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
+ job = new AppCacheURLRequestJob(request.get(), NULL, storage, NULL, false);
job->DeliverErrorResponse();
EXPECT_TRUE(job->is_delivering_error_response());
EXPECT_FALSE(job->has_been_started());
- job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
+ job = new AppCacheURLRequestJob(request.get(), NULL, storage, NULL, false);
job->DeliverNetworkResponse();
EXPECT_TRUE(job->is_delivering_network_response());
EXPECT_FALSE(job->has_been_started());
- job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
+ job = new AppCacheURLRequestJob(request.get(), NULL, storage, NULL, false);
const GURL kManifestUrl("http://blah/");
const int64 kCacheId(1);
const int64 kGroupId(1);
diff --git a/chromium/content/browser/appcache/appcache_working_set.cc b/chromium/content/browser/appcache/appcache_working_set.cc
new file mode 100644
index 00000000000..4394097aee0
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_working_set.cc
@@ -0,0 +1,80 @@
+// 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 "content/browser/appcache/appcache_working_set.h"
+
+#include "base/logging.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_response.h"
+
+namespace content {
+
+AppCacheWorkingSet::AppCacheWorkingSet() : is_disabled_(false) {}
+
+AppCacheWorkingSet::~AppCacheWorkingSet() {
+ DCHECK(caches_.empty());
+ DCHECK(groups_.empty());
+ DCHECK(groups_by_origin_.empty());
+}
+
+void AppCacheWorkingSet::Disable() {
+ if (is_disabled_)
+ return;
+ is_disabled_ = true;
+ caches_.clear();
+ groups_.clear();
+ groups_by_origin_.clear();
+ response_infos_.clear();
+}
+
+void AppCacheWorkingSet::AddCache(AppCache* cache) {
+ if (is_disabled_)
+ return;
+ DCHECK(cache->cache_id() != kAppCacheNoCacheId);
+ int64 cache_id = cache->cache_id();
+ DCHECK(caches_.find(cache_id) == caches_.end());
+ caches_.insert(CacheMap::value_type(cache_id, cache));
+}
+
+void AppCacheWorkingSet::RemoveCache(AppCache* cache) {
+ caches_.erase(cache->cache_id());
+}
+
+void AppCacheWorkingSet::AddGroup(AppCacheGroup* group) {
+ if (is_disabled_)
+ return;
+ const GURL& url = group->manifest_url();
+ DCHECK(groups_.find(url) == groups_.end());
+ groups_.insert(GroupMap::value_type(url, group));
+ groups_by_origin_[url.GetOrigin()].insert(GroupMap::value_type(url, group));
+}
+
+void AppCacheWorkingSet::RemoveGroup(AppCacheGroup* group) {
+ const GURL& url = group->manifest_url();
+ groups_.erase(url);
+
+ GURL origin_url = url.GetOrigin();
+ GroupMap* groups_in_origin = GetMutableGroupsInOrigin(origin_url);
+ if (groups_in_origin) {
+ groups_in_origin->erase(url);
+ if (groups_in_origin->empty())
+ groups_by_origin_.erase(origin_url);
+ }
+}
+
+void AppCacheWorkingSet::AddResponseInfo(AppCacheResponseInfo* info) {
+ if (is_disabled_)
+ return;
+ DCHECK(info->response_id() != kAppCacheNoResponseId);
+ int64 response_id = info->response_id();
+ DCHECK(response_infos_.find(response_id) == response_infos_.end());
+ response_infos_.insert(ResponseInfoMap::value_type(response_id, info));
+}
+
+void AppCacheWorkingSet::RemoveResponseInfo(AppCacheResponseInfo* info) {
+ response_infos_.erase(info->response_id());
+}
+
+} // namespace
diff --git a/chromium/content/browser/appcache/appcache_working_set.h b/chromium/content/browser/appcache/appcache_working_set.h
new file mode 100644
index 00000000000..5b9d00a1e1c
--- /dev/null
+++ b/chromium/content/browser/appcache/appcache_working_set.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2011 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 CONTENT_BROWSER_APPCACHE_APPCACHE_WORKING_SET_H_
+#define CONTENT_BROWSER_APPCACHE_APPCACHE_WORKING_SET_H_
+
+#include <map>
+
+#include "base/containers/hash_tables.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class AppCache;
+class AppCacheGroup;
+class AppCacheResponseInfo;
+
+// Represents the working set of appcache object instances
+// currently in memory.
+class CONTENT_EXPORT AppCacheWorkingSet {
+ public:
+ typedef std::map<GURL, AppCacheGroup*> GroupMap;
+
+ AppCacheWorkingSet();
+ ~AppCacheWorkingSet();
+
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
+
+ void AddCache(AppCache* cache);
+ void RemoveCache(AppCache* cache);
+ AppCache* GetCache(int64 id) {
+ CacheMap::iterator it = caches_.find(id);
+ return (it != caches_.end()) ? it->second : NULL;
+ }
+
+ void AddGroup(AppCacheGroup* group);
+ void RemoveGroup(AppCacheGroup* group);
+ AppCacheGroup* GetGroup(const GURL& manifest_url) {
+ GroupMap::iterator it = groups_.find(manifest_url);
+ return (it != groups_.end()) ? it->second : NULL;
+ }
+
+ const GroupMap* GetGroupsInOrigin(const GURL& origin_url) {
+ return GetMutableGroupsInOrigin(origin_url);
+ }
+
+ void AddResponseInfo(AppCacheResponseInfo* response_info);
+ void RemoveResponseInfo(AppCacheResponseInfo* response_info);
+ AppCacheResponseInfo* GetResponseInfo(int64 id) {
+ ResponseInfoMap::iterator it = response_infos_.find(id);
+ return (it != response_infos_.end()) ? it->second : NULL;
+ }
+
+ private:
+ typedef base::hash_map<int64, AppCache*> CacheMap;
+ typedef std::map<GURL, GroupMap> GroupsByOriginMap;
+ typedef base::hash_map<int64, AppCacheResponseInfo*> ResponseInfoMap;
+
+ GroupMap* GetMutableGroupsInOrigin(const GURL& origin_url) {
+ GroupsByOriginMap::iterator it = groups_by_origin_.find(origin_url);
+ return (it != groups_by_origin_.end()) ? &it->second : NULL;
+ }
+
+ CacheMap caches_;
+ GroupMap groups_;
+ GroupsByOriginMap groups_by_origin_; // origin -> (manifest -> group)
+ ResponseInfoMap response_infos_;
+ bool is_disabled_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_APPCACHE_APPCACHE_WORKING_SET_H_
diff --git a/chromium/content/browser/appcache/chrome_appcache_service.cc b/chromium/content/browser/appcache/chrome_appcache_service.cc
index c72c21812ac..e4dbf7e00a1 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service.cc
@@ -5,27 +5,26 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "base/files/file_path.h"
+#include "content/browser/appcache/appcache_storage_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_context_getter.h"
-#include "webkit/browser/appcache/appcache_storage_impl.h"
-#include "webkit/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager.h"
namespace content {
ChromeAppCacheService::ChromeAppCacheService(
- quota::QuotaManagerProxy* quota_manager_proxy)
- : AppCacheServiceImpl(quota_manager_proxy),
- resource_context_(NULL) {
+ storage::QuotaManagerProxy* quota_manager_proxy)
+ : AppCacheServiceImpl(quota_manager_proxy), resource_context_(NULL) {
}
void ChromeAppCacheService::InitializeOnIOThread(
const base::FilePath& cache_path,
ResourceContext* resource_context,
net::URLRequestContextGetter* request_context_getter,
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) {
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
cache_path_ = cache_path;
diff --git a/chromium/content/browser/appcache/chrome_appcache_service.h b/chromium/content/browser/appcache/chrome_appcache_service.h
index 2f33d9b0f24..6976d873007 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service.h
+++ b/chromium/content/browser/appcache/chrome_appcache_service.h
@@ -8,10 +8,10 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
+#include "content/browser/appcache/appcache_policy.h"
+#include "content/browser/appcache/appcache_service_impl.h"
#include "content/common/content_export.h"
-#include "webkit/browser/appcache/appcache_policy.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
-#include "webkit/browser/quota/special_storage_policy.h"
+#include "storage/browser/quota/special_storage_policy.h"
namespace base {
class FilePath;
@@ -40,26 +40,26 @@ struct ChromeAppCacheServiceDeleter;
class CONTENT_EXPORT ChromeAppCacheService
: public base::RefCountedThreadSafe<ChromeAppCacheService,
ChromeAppCacheServiceDeleter>,
- NON_EXPORTED_BASE(public appcache::AppCacheServiceImpl),
- NON_EXPORTED_BASE(public appcache::AppCachePolicy) {
+ NON_EXPORTED_BASE(public AppCacheServiceImpl),
+ NON_EXPORTED_BASE(public AppCachePolicy) {
public:
- explicit ChromeAppCacheService(quota::QuotaManagerProxy* proxy);
+ explicit ChromeAppCacheService(storage::QuotaManagerProxy* proxy);
// If |cache_path| is empty we will use in-memory structs.
void InitializeOnIOThread(
const base::FilePath& cache_path,
ResourceContext* resource_context,
net::URLRequestContextGetter* request_context_getter,
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy);
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy);
// AppCachePolicy overrides
- virtual bool CanLoadAppCache(const GURL& manifest_url,
- const GURL& first_party) OVERRIDE;
- virtual bool CanCreateAppCache(const GURL& manifest_url,
- const GURL& first_party) OVERRIDE;
+ bool CanLoadAppCache(const GURL& manifest_url,
+ const GURL& first_party) override;
+ bool CanCreateAppCache(const GURL& manifest_url,
+ const GURL& first_party) override;
protected:
- virtual ~ChromeAppCacheService();
+ ~ChromeAppCacheService() override;
private:
friend class base::DeleteHelper<ChromeAppCacheService>;
diff --git a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
index 1800d0bf328..450bfe2c49e 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
+#include "content/browser/appcache/appcache_database.h"
+#include "content/browser/appcache/appcache_storage_impl.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/browser_thread_impl.h"
#include "content/public/browser/resource_context.h"
@@ -15,8 +17,6 @@
#include "content/test/appcache_test_helper.h"
#include "net/url_request/url_request_context_getter.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache_database.h"
-#include "webkit/browser/appcache/appcache_storage_impl.h"
#include <set>
@@ -39,17 +39,15 @@ class MockURLRequestContextGetter : public net::URLRequestContextGetter {
: context_(context), message_loop_proxy_(message_loop_proxy) {
}
- virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
- return context_;
- }
+ net::URLRequestContext* GetURLRequestContext() override { return context_; }
- virtual scoped_refptr<base::SingleThreadTaskRunner>
- GetNetworkTaskRunner() const OVERRIDE {
+ scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
+ const override {
return message_loop_proxy_;
}
protected:
- virtual ~MockURLRequestContextGetter() {}
+ ~MockURLRequestContextGetter() override {}
private:
net::URLRequestContext* context_;
@@ -116,8 +114,8 @@ ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
// Steps needed to initialize the storage of AppCache data.
message_loop_.RunUntilIdle();
if (init_storage) {
- appcache::AppCacheStorageImpl* storage =
- static_cast<appcache::AppCacheStorageImpl*>(
+ AppCacheStorageImpl* storage =
+ static_cast<AppCacheStorageImpl*>(
appcache_service->storage());
storage->database_->db_connection();
storage->disk_cache();
diff --git a/chromium/content/browser/appcache/manifest_parser_unittest.cc b/chromium/content/browser/appcache/manifest_parser_unittest.cc
deleted file mode 100644
index 8a44376d774..00000000000
--- a/chromium/content/browser/appcache/manifest_parser_unittest.cc
+++ /dev/null
@@ -1,524 +0,0 @@
-// Copyright 2014 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 <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "webkit/browser/appcache/manifest_parser.h"
-
-using appcache::Manifest;
-using appcache::NamespaceVector;
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::APPCACHE_INTERCEPT_NAMESPACE;
-using appcache::APPCACHE_NETWORK_NAMESPACE;
-using appcache::PARSE_MANIFEST_ALLOWING_INTERCEPTS;
-using appcache::PARSE_MANIFEST_PER_STANDARD;
-
-namespace content {
-
-class AppCacheManifestParserTest : public testing::Test {
-};
-
-TEST(AppCacheManifestParserTest, NoData) {
- GURL url;
- Manifest manifest;
- EXPECT_FALSE(ParseManifest(url, "", 0,
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_FALSE(ParseManifest(url, "CACHE MANIFEST\r", 0, // Len is 0.
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
-}
-
-TEST(AppCacheManifestParserTest, CheckSignature) {
- GURL url;
- Manifest manifest;
-
- const std::string kBadSignatures[] = {
- "foo",
- "CACHE MANIFEST;V2\r", // not followed by whitespace
- "CACHE MANIFEST#bad\r", // no whitespace before comment
- "cache manifest ", // wrong case
- "#CACHE MANIFEST\r", // comment
- "xCACHE MANIFEST\n", // bad first char
- " CACHE MANIFEST\r", // begins with whitespace
- "\xEF\xBE\xBF" "CACHE MANIFEST\r", // bad UTF-8 BOM value
- };
-
- for (size_t i = 0; i < arraysize(kBadSignatures); ++i) {
- const std::string bad = kBadSignatures[i];
- EXPECT_FALSE(ParseManifest(url, bad.c_str(), bad.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- }
-
- const std::string kGoodSignatures[] = {
- "CACHE MANIFEST",
- "CACHE MANIFEST ",
- "CACHE MANIFEST\r",
- "CACHE MANIFEST\n",
- "CACHE MANIFEST\r\n",
- "CACHE MANIFEST\t# ignore me\r",
- "CACHE MANIFEST ignore\r\n",
- "CHROMIUM CACHE MANIFEST\r\n",
- "\xEF\xBB\xBF" "CACHE MANIFEST \r\n", // BOM present
- };
-
- for (size_t i = 0; i < arraysize(kGoodSignatures); ++i) {
- const std::string good = kGoodSignatures[i];
- EXPECT_TRUE(ParseManifest(url, good.c_str(), good.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- }
-}
-
-TEST(AppCacheManifestParserTest, NoManifestUrl) {
- Manifest manifest;
- const std::string kData("CACHE MANIFEST\r"
- "relative/tobase.com\r"
- "http://absolute.com/addme.com");
- const GURL kUrl;
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.explicit_urls.empty());
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-}
-
-TEST(AppCacheManifestParserTest, ExplicitUrls) {
- Manifest manifest;
- const GURL kUrl("http://www.foo.com");
- const std::string kData("CACHE MANIFEST\r"
- "relative/one\r"
- "# some comment\r"
- "http://www.foo.com/two#strip\r\n"
- "NETWORK:\r"
- " \t CACHE:\r"
- "HTTP://www.diff.com/three\r"
- "FALLBACK:\r"
- " \t # another comment with leading whitespace\n"
- "IGNORE:\r"
- "http://www.foo.com/ignore\r"
- "CACHE: \r"
- "garbage:#!@\r"
- "https://www.foo.com/diffscheme \t \r"
- " \t relative/four#stripme\n\r"
- "*\r");
-
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-
- base::hash_set<std::string> urls = manifest.explicit_urls;
- const size_t kExpected = 5;
- ASSERT_EQ(kExpected, urls.size());
- EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end());
- EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end());
- EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end());
- EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end());
-
- // Wildcard is treated as a relative URL in explicit section.
- EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end());
-
- // We should get the same results with intercepts disallowed.
- manifest = Manifest();
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_PER_STANDARD, manifest));
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-
- urls = manifest.explicit_urls;
- ASSERT_EQ(kExpected, urls.size());
- EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end());
- EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end());
- EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end());
- EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end());
-
- // Wildcard is treated as a relative URL in explicit section.
- EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end());
-}
-
-TEST(AppCacheManifestParserTest, WhitelistUrls) {
- Manifest manifest;
- const GURL kUrl("http://www.bar.com");
- const std::string kData("CACHE MANIFEST\r"
- "NETWORK:\r"
- "relative/one\r"
- "# a comment\r"
- "http://www.bar.com/two\r"
- "HTTP://www.diff.com/three#strip\n\r"
- "FALLBACK:\r"
- "garbage\r"
- "UNKNOWN:\r"
- "http://www.bar.com/ignore\r"
- "CACHE:\r"
- "NETWORK:\r"
- "https://www.wrongscheme.com\n"
- "relative/four#stripref \t \r"
- "http://www.five.com\r\n"
- "*foo\r");
-
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.explicit_urls.empty());
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.intercept_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-
- const NamespaceVector& online = manifest.online_whitelist_namespaces;
- const size_t kExpected = 6;
- ASSERT_EQ(kExpected, online.size());
- EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, online[0].type);
- EXPECT_FALSE(online[0].is_pattern);
- EXPECT_TRUE(online[0].target_url.is_empty());
- EXPECT_EQ(GURL("http://www.bar.com/relative/one"), online[0].namespace_url);
- EXPECT_EQ(GURL("http://www.bar.com/two"), online[1].namespace_url);
- EXPECT_EQ(GURL("http://www.diff.com/three"), online[2].namespace_url);
- EXPECT_EQ(GURL("http://www.bar.com/relative/four"), online[3].namespace_url);
- EXPECT_EQ(GURL("http://www.five.com"), online[4].namespace_url);
- EXPECT_EQ(GURL("http://www.bar.com/*foo"), online[5].namespace_url);
-}
-
-TEST(AppCacheManifestParserTest, FallbackUrls) {
- Manifest manifest;
- const GURL kUrl("http://glorp.com");
- const std::string kData("CACHE MANIFEST\r"
- "# a comment\r"
- "CACHE:\r"
- "NETWORK:\r"
- "UNKNOWN:\r"
- "FALLBACK:\r"
- "relative/one \t \t http://glorp.com/onefb \t \r"
- "*\r"
- "https://glorp.com/wrong http://glorp.com/wrongfb\r"
- "http://glorp.com/two#strip relative/twofb\r"
- "HTTP://glorp.com/three relative/threefb#strip\n"
- "http://glorp.com/three http://glorp.com/three-dup\r"
- "http://glorp.com/solo \t \r\n"
- "http://diff.com/ignore http://glorp.com/wronghost\r"
- "http://glorp.com/wronghost http://diff.com/ohwell\r"
- "relative/badscheme ftp://glorp.com/ignored\r"
- "garbage\r\n"
- "CACHE:\r"
- "# only fallback urls in this test\r"
- "FALLBACK:\n"
- "relative/four#strip relative/fourfb#strip\r"
- "http://www.glorp.com/notsame relative/skipped\r");
-
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.explicit_urls.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-
- const NamespaceVector& fallbacks = manifest.fallback_namespaces;
- const size_t kExpected = 5;
- ASSERT_EQ(kExpected, fallbacks.size());
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[2].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[3].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[4].type);
- EXPECT_EQ(GURL("http://glorp.com/relative/one"),
- fallbacks[0].namespace_url);
- EXPECT_EQ(GURL("http://glorp.com/onefb"),
- fallbacks[0].target_url);
- EXPECT_EQ(GURL("http://glorp.com/two"),
- fallbacks[1].namespace_url);
- EXPECT_EQ(GURL("http://glorp.com/relative/twofb"),
- fallbacks[1].target_url);
- EXPECT_EQ(GURL("http://glorp.com/three"),
- fallbacks[2].namespace_url);
- EXPECT_EQ(GURL("http://glorp.com/relative/threefb"),
- fallbacks[2].target_url);
- EXPECT_EQ(GURL("http://glorp.com/three"), // duplicates are stored
- fallbacks[3].namespace_url);
- EXPECT_EQ(GURL("http://glorp.com/three-dup"),
- fallbacks[3].target_url);
- EXPECT_EQ(GURL("http://glorp.com/relative/four"),
- fallbacks[4].namespace_url);
- EXPECT_EQ(GURL("http://glorp.com/relative/fourfb"),
- fallbacks[4].target_url);
-
- EXPECT_TRUE(manifest.intercept_namespaces.empty());
-}
-
-TEST(AppCacheManifestParserTest, FallbackUrlsWithPort) {
- Manifest manifest;
- const GURL kUrl("http://www.portme.com:1234");
- const std::string kData("CACHE MANIFEST\r"
- "FALLBACK:\r"
- "http://www.portme.com:1234/one relative/onefb\r"
- "HTTP://www.portme.com:9876/wrong http://www.portme.com:1234/ignore\r"
- "http://www.portme.com:1234/stillwrong http://www.portme.com:42/boo\r"
- "relative/two relative/twofb\r"
- "http://www.portme.com:1234/three HTTP://www.portme.com:1234/threefb\r"
- "http://www.portme.com/noport http://www.portme.com:1234/skipped\r"
- "http://www.portme.com:1234/skipme http://www.portme.com/noport\r");
-
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.explicit_urls.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-
- const NamespaceVector& fallbacks = manifest.fallback_namespaces;
- const size_t kExpected = 3;
- ASSERT_EQ(kExpected, fallbacks.size());
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[2].type);
- EXPECT_EQ(GURL("http://www.portme.com:1234/one"),
- fallbacks[0].namespace_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/relative/onefb"),
- fallbacks[0].target_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"),
- fallbacks[1].namespace_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/relative/twofb"),
- fallbacks[1].target_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/three"),
- fallbacks[2].namespace_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/threefb"),
- fallbacks[2].target_url);
-
- EXPECT_TRUE(manifest.intercept_namespaces.empty());
-}
-
-TEST(AppCacheManifestParserTest, InterceptUrls) {
- Manifest manifest;
- const GURL kUrl("http://www.portme.com:1234");
- const std::string kData("CHROMIUM CACHE MANIFEST\r"
- "CHROMIUM-INTERCEPT:\r"
- "http://www.portme.com:1234/one return relative/int1\r"
- "HTTP://www.portme.com:9/wrong return http://www.portme.com:1234/ignore\r"
- "http://www.portme.com:1234/wrong return http://www.portme.com:9/boo\r"
- "relative/two return relative/int2\r"
- "relative/three wrong relative/threefb\r"
- "http://www.portme.com:1234/three return HTTP://www.portme.com:1234/int3\r"
- "http://www.portme.com/noport return http://www.portme.com:1234/skipped\r"
- "http://www.portme.com:1234/skipme return http://www.portme.com/noport\r"
- "relative/wrong/again missing/intercept_type\r");
-
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.explicit_urls.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-
- const NamespaceVector& intercepts = manifest.intercept_namespaces;
- const size_t kExpected = 3;
- ASSERT_EQ(kExpected, intercepts.size());
- EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[0].type);
- EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[1].type);
- EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[2].type);
- EXPECT_EQ(GURL("http://www.portme.com:1234/one"),
- intercepts[0].namespace_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int1"),
- intercepts[0].target_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"),
- intercepts[1].namespace_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int2"),
- intercepts[1].target_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/three"),
- intercepts[2].namespace_url);
- EXPECT_EQ(GURL("http://www.portme.com:1234/int3"),
- intercepts[2].target_url);
-
- // Disallow intercepts ths time.
- manifest = Manifest();
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_PER_STANDARD, manifest));
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.explicit_urls.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
- EXPECT_TRUE(manifest.intercept_namespaces.empty());
- EXPECT_FALSE(manifest.online_whitelist_all);
-}
-
-TEST(AppCacheManifestParserTest, ComboUrls) {
- Manifest manifest;
- const GURL kUrl("http://combo.com:42");
- const std::string kData("CACHE MANIFEST\r"
- "relative/explicit-1\r"
- "# some comment\r"
- "http://combo.com:99/explicit-2#strip\r"
- "NETWORK:\r"
- "http://combo.com/whitelist-1\r"
- "HTTP://www.diff.com/whitelist-2#strip\r"
- "*\r"
- "CACHE:\n\r"
- "http://www.diff.com/explicit-3\r"
- "FALLBACK:\r"
- "http://combo.com:42/fallback-1 http://combo.com:42/fallback-1b\r"
- "relative/fallback-2 relative/fallback-2b\r"
- "UNKNOWN:\r\n"
- "http://combo.com/ignoreme\r"
- "relative/still-ignored\r"
- "NETWORK:\r\n"
- "relative/whitelist-3#strip\r"
- "http://combo.com:99/whitelist-4\r");
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.online_whitelist_all);
-
- base::hash_set<std::string> urls = manifest.explicit_urls;
- size_t expected = 3;
- ASSERT_EQ(expected, urls.size());
- EXPECT_TRUE(urls.find("http://combo.com:42/relative/explicit-1") !=
- urls.end());
- EXPECT_TRUE(urls.find("http://combo.com:99/explicit-2") != urls.end());
- EXPECT_TRUE(urls.find("http://www.diff.com/explicit-3") != urls.end());
-
- const NamespaceVector& online = manifest.online_whitelist_namespaces;
- expected = 4;
- ASSERT_EQ(expected, online.size());
- EXPECT_EQ(GURL("http://combo.com/whitelist-1"),
- online[0].namespace_url);
- EXPECT_EQ(GURL("http://www.diff.com/whitelist-2"),
- online[1].namespace_url);
- EXPECT_EQ(GURL("http://combo.com:42/relative/whitelist-3"),
- online[2].namespace_url);
- EXPECT_EQ(GURL("http://combo.com:99/whitelist-4"),
- online[3].namespace_url);
-
- const NamespaceVector& fallbacks = manifest.fallback_namespaces;
- expected = 2;
- ASSERT_EQ(expected, fallbacks.size());
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
- EXPECT_EQ(GURL("http://combo.com:42/fallback-1"),
- fallbacks[0].namespace_url);
- EXPECT_EQ(GURL("http://combo.com:42/fallback-1b"),
- fallbacks[0].target_url);
- EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2"),
- fallbacks[1].namespace_url);
- EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2b"),
- fallbacks[1].target_url);
-
- EXPECT_TRUE(manifest.intercept_namespaces.empty());
-}
-
-TEST(AppCacheManifestParserTest, UnusualUtf8) {
- Manifest manifest;
- const GURL kUrl("http://bad.com");
- const std::string kData("CACHE MANIFEST\r"
- "\xC0" "invalidutf8\r"
- "nonbmp" "\xF1\x84\xAB\xBC\r");
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- base::hash_set<std::string> urls = manifest.explicit_urls;
- EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end());
- EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end());
-}
-
-TEST(AppCacheManifestParserTest, IgnoreAfterSpace) {
- Manifest manifest;
- const GURL kUrl("http://smorg.borg");
- const std::string kData(
- "CACHE MANIFEST\r"
- "resource.txt this stuff after the white space should be ignored\r");
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
-
- base::hash_set<std::string> urls = manifest.explicit_urls;
- EXPECT_TRUE(urls.find("http://smorg.borg/resource.txt") != urls.end());
-}
-
-TEST(AppCacheManifestParserTest, DifferentOriginUrlWithSecureScheme) {
- Manifest manifest;
- const GURL kUrl("https://www.foo.com");
- const std::string kData("CACHE MANIFEST\r"
- "CACHE: \r"
- "relative/secureschemesameorigin\r"
- "https://www.foo.com/secureschemesameorigin\r"
- "http://www.xyz.com/secureschemedifforigin\r"
- "https://www.xyz.com/secureschemedifforigin\r");
-
- EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.fallback_namespaces.empty());
- EXPECT_TRUE(manifest.online_whitelist_namespaces.empty());
-
- base::hash_set<std::string> urls = manifest.explicit_urls;
- const size_t kExpected = 3;
- ASSERT_EQ(kExpected, urls.size());
- EXPECT_TRUE(urls.find("https://www.foo.com/relative/secureschemesameorigin")
- != urls.end());
- EXPECT_TRUE(urls.find("https://www.foo.com/secureschemesameorigin") !=
- urls.end());
- EXPECT_FALSE(urls.find("http://www.xyz.com/secureschemedifforigin") !=
- urls.end());
- EXPECT_TRUE(urls.find("https://www.xyz.com/secureschemedifforigin") !=
- urls.end());
-}
-
-TEST(AppCacheManifestParserTest, PatternMatching) {
- const GURL kUrl("http://foo.com/manifest");
- const std::string kManifestBody(
- "CACHE MANIFEST\r"
- "CACHE: \r"
- "http://foo.com/page.html\r"
- "CHROMIUM-INTERCEPT:\r"
- "http://foo.com/intercept_prefix return /prefix\r"
- "http://foo.com/intercept_pattern return /pattern isPattern\r"
- "http://foo.com/*/intercept_pattern?query return /pattern isPattern\r"
- "FALLBACK:\r"
- "http://foo.com/fallback_prefix /prefix wrongAnnotation\r"
- "http://foo.com/fallback_pattern* /pattern\tisPattern \r"
- "NETWORK:\r"
- "*\r"
- "isPattern\r" // should not be interpretted as a pattern
- "http://foo.com/network_pattern* isPattern\r");
-
-
- Manifest manifest;
- EXPECT_TRUE(ParseManifest(kUrl, kManifestBody.c_str(),
- kManifestBody.length(),
- PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest));
- EXPECT_TRUE(manifest.online_whitelist_all);
- EXPECT_EQ(1u, manifest.explicit_urls.size());
- EXPECT_EQ(3u, manifest.intercept_namespaces.size());
- EXPECT_EQ(2u, manifest.fallback_namespaces.size());
- EXPECT_EQ(2u, manifest.online_whitelist_namespaces.size());
- EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE,
- manifest.intercept_namespaces[0].type);
- EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, manifest.fallback_namespaces[0].type);
- EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE,
- manifest.online_whitelist_namespaces[0].type);
- EXPECT_FALSE(manifest.intercept_namespaces[0].is_pattern);
- EXPECT_TRUE(manifest.intercept_namespaces[1].is_pattern);
- EXPECT_TRUE(manifest.intercept_namespaces[2].is_pattern);
- EXPECT_FALSE(manifest.fallback_namespaces[0].is_pattern);
- EXPECT_TRUE(manifest.fallback_namespaces[1].is_pattern);
- EXPECT_FALSE(manifest.online_whitelist_namespaces[0].is_pattern);
- EXPECT_TRUE(manifest.online_whitelist_namespaces[1].is_pattern);
- EXPECT_EQ(
- GURL("http://foo.com/*/intercept_pattern?query"),
- manifest.intercept_namespaces[2].namespace_url);
- EXPECT_EQ(
- GURL("http://foo.com/pattern"),
- manifest.intercept_namespaces[2].target_url);
- EXPECT_EQ(
- GURL("http://foo.com/fallback_pattern*"),
- manifest.fallback_namespaces[1].namespace_url);
- EXPECT_EQ(
- GURL("http://foo.com/pattern"),
- manifest.fallback_namespaces[1].target_url);
- EXPECT_EQ(
- GURL("http://foo.com/isPattern"),
- manifest.online_whitelist_namespaces[0].namespace_url);
- EXPECT_EQ(
- GURL(),
- manifest.online_whitelist_namespaces[0].target_url);
- EXPECT_EQ(
- GURL("http://foo.com/network_pattern*"),
- manifest.online_whitelist_namespaces[1].namespace_url);
- EXPECT_EQ(
- GURL(),
- manifest.online_whitelist_namespaces[1].target_url);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/appcache/mock_appcache_policy.h b/chromium/content/browser/appcache/mock_appcache_policy.h
index bc7576412b9..a571e25efb6 100644
--- a/chromium/content/browser/appcache/mock_appcache_policy.h
+++ b/chromium/content/browser/appcache/mock_appcache_policy.h
@@ -6,20 +6,20 @@
#define CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_POLICY_H_
#include "base/compiler_specific.h"
+#include "content/browser/appcache/appcache_policy.h"
#include "url/gurl.h"
-#include "webkit/browser/appcache/appcache_policy.h"
namespace content {
-class MockAppCachePolicy : public appcache::AppCachePolicy {
+class MockAppCachePolicy : public AppCachePolicy {
public:
MockAppCachePolicy();
virtual ~MockAppCachePolicy();
- virtual bool CanLoadAppCache(const GURL& manifest_url,
- const GURL& first_party) OVERRIDE;
- virtual bool CanCreateAppCache(const GURL& manifest_url,
- const GURL& first_party) OVERRIDE;
+ bool CanLoadAppCache(const GURL& manifest_url,
+ const GURL& first_party) override;
+ bool CanCreateAppCache(const GURL& manifest_url,
+ const GURL& first_party) override;
bool can_load_return_value_;
bool can_create_return_value_;
diff --git a/chromium/content/browser/appcache/mock_appcache_service.h b/chromium/content/browser/appcache/mock_appcache_service.h
index 691736baa60..5e384201e4c 100644
--- a/chromium/content/browser/appcache/mock_appcache_service.h
+++ b/chromium/content/browser/appcache/mock_appcache_service.h
@@ -6,11 +6,9 @@
#define CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_SERVICE_H_
#include "base/compiler_specific.h"
+#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/appcache/mock_appcache_storage.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
-#include "webkit/browser/quota/quota_manager.h"
-
-using appcache::AppCacheServiceImpl;
+#include "storage/browser/quota/quota_manager.h"
namespace content {
@@ -26,11 +24,11 @@ class MockAppCacheService : public AppCacheServiceImpl {
// Just returns a canned completion code without actually
// removing groups and caches in our mock storage instance.
- virtual void DeleteAppCachesForOrigin(
+ void DeleteAppCachesForOrigin(
const GURL& origin,
- const net::CompletionCallback& callback) OVERRIDE;
+ const net::CompletionCallback& callback) override;
- void set_quota_manager_proxy(quota::QuotaManagerProxy* proxy) {
+ void set_quota_manager_proxy(storage::QuotaManagerProxy* proxy) {
quota_manager_proxy_ = proxy;
}
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.cc b/chromium/content/browser/appcache/mock_appcache_storage.cc
index ea9673df497..91630f7d351 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.cc
+++ b/chromium/content/browser/appcache/mock_appcache_storage.cc
@@ -9,11 +9,11 @@
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_entry.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_entry.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
// This is a quick and easy 'mock' implementation of the storage interface
// that doesn't put anything to disk.
@@ -25,13 +25,6 @@
// happen with a real disk-backed storage impl that involves IO on a
// background thread.
-using appcache::AppCacheResponseWriter;
-using appcache::AppCacheServiceImpl;
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::APPCACHE_INTERCEPT_NAMESPACE;
-using appcache::kAppCacheNoCacheId;
-using appcache::AppCacheNamespaceType;
-
namespace content {
MockAppCacheStorage::MockAppCacheStorage(AppCacheServiceImpl* service)
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.h b/chromium/content/browser/appcache/mock_appcache_storage.h
index 5d31748da43..a6ece438ef1 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.h
+++ b/chromium/content/browser/appcache/mock_appcache_storage.h
@@ -14,22 +14,11 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_disk_cache.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_storage.h"
-
-using appcache::AppCache;
-using appcache::AppCacheDiskCache;
-using appcache::AppCacheEntry;
-using appcache::AppCacheGroup;
-using appcache::AppCacheInfoCollection;
-using appcache::AppCacheResponseReader;
-using appcache::AppCacheResponseWriter;
-using appcache::AppCacheServiceImpl;
-using appcache::AppCacheStorage;
-using appcache::kAppCacheNoCacheId;
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_disk_cache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_storage.h"
namespace content {
FORWARD_DECLARE_TEST(AppCacheServiceImplTest, DeleteAppCachesForOrigin);
@@ -58,37 +47,35 @@ class MockAppCacheStorageTest;
class MockAppCacheStorage : public AppCacheStorage {
public:
explicit MockAppCacheStorage(AppCacheServiceImpl* service);
- virtual ~MockAppCacheStorage();
-
- virtual void GetAllInfo(Delegate* delegate) OVERRIDE;
- virtual void LoadCache(int64 id, Delegate* delegate) OVERRIDE;
- virtual void LoadOrCreateGroup(const GURL& manifest_url,
- Delegate* delegate) OVERRIDE;
- virtual void StoreGroupAndNewestCache(AppCacheGroup* group,
- AppCache* newest_cache,
- Delegate* delegate) OVERRIDE;
- virtual void FindResponseForMainRequest(const GURL& url,
- const GURL& preferred_manifest_url,
- Delegate* delegate) OVERRIDE;
- virtual void FindResponseForSubRequest(
- AppCache* cache, const GURL& url,
- AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
- bool * found_network_namespace) OVERRIDE;
- virtual void MarkEntryAsForeign(const GURL& entry_url,
- int64 cache_id) OVERRIDE;
- virtual void MakeGroupObsolete(AppCacheGroup* group,
- Delegate* delegate,
- int response_code) OVERRIDE;
- virtual AppCacheResponseReader* CreateResponseReader(
- const GURL& manifest_url, int64 group_id, int64 response_id) OVERRIDE;
- virtual AppCacheResponseWriter* CreateResponseWriter(
- const GURL& manifest_url, int64 group_id) OVERRIDE;
- virtual void DoomResponses(
- const GURL& manifest_url,
- const std::vector<int64>& response_ids) OVERRIDE;
- virtual void DeleteResponses(
- const GURL& manifest_url,
- const std::vector<int64>& response_ids) OVERRIDE;
+ ~MockAppCacheStorage() override;
+
+ void GetAllInfo(Delegate* delegate) override;
+ void LoadCache(int64 id, Delegate* delegate) override;
+ void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate) override;
+ void StoreGroupAndNewestCache(AppCacheGroup* group,
+ AppCache* newest_cache,
+ Delegate* delegate) override;
+ void FindResponseForMainRequest(const GURL& url,
+ const GURL& preferred_manifest_url,
+ Delegate* delegate) override;
+ void FindResponseForSubRequest(AppCache* cache,
+ const GURL& url,
+ AppCacheEntry* found_entry,
+ AppCacheEntry* found_fallback_entry,
+ bool* found_network_namespace) override;
+ void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) override;
+ void MakeGroupObsolete(AppCacheGroup* group,
+ Delegate* delegate,
+ int response_code) override;
+ AppCacheResponseReader* CreateResponseReader(const GURL& manifest_url,
+ int64 group_id,
+ int64 response_id) override;
+ AppCacheResponseWriter* CreateResponseWriter(const GURL& manifest_url,
+ int64 group_id) override;
+ void DoomResponses(const GURL& manifest_url,
+ const std::vector<int64>& response_ids) override;
+ void DeleteResponses(const GURL& manifest_url,
+ const std::vector<int64>& response_ids) override;
private:
friend class AppCacheRequestHandlerTest;
diff --git a/chromium/content/browser/appcache/mock_appcache_storage_unittest.cc b/chromium/content/browser/appcache/mock_appcache_storage_unittest.cc
index f1c9149102c..8f52912d39f 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage_unittest.cc
+++ b/chromium/content/browser/appcache/mock_appcache_storage_unittest.cc
@@ -3,24 +3,12 @@
// found in the LICENSE file.
#include "base/run_loop.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_storage.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_storage.h"
-
-using appcache::AppCache;
-using appcache::AppCacheEntry;
-using appcache::AppCacheGroup;
-using appcache::AppCacheStorage;
-using appcache::APPCACHE_FALLBACK_NAMESPACE;
-using appcache::APPCACHE_INTERCEPT_NAMESPACE;
-using appcache::kAppCacheNoCacheId;
-using appcache::kAppCacheNoResponseId;
-using appcache::Manifest;
-using appcache::Namespace;
-using appcache::APPCACHE_NETWORK_NAMESPACE;
namespace content {
@@ -33,38 +21,39 @@ class MockAppCacheStorageTest : public testing::Test {
obsoleted_success_(false), found_cache_id_(kAppCacheNoCacheId) {
}
- virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE {
+ void OnCacheLoaded(AppCache* cache, int64 cache_id) override {
loaded_cache_ = cache;
loaded_cache_id_ = cache_id;
}
- virtual void OnGroupLoaded(AppCacheGroup* group,
- const GURL& manifest_url) OVERRIDE {
+ void OnGroupLoaded(AppCacheGroup* group,
+ const GURL& manifest_url) override {
loaded_group_ = group;
loaded_manifest_url_ = manifest_url;
}
- virtual void OnGroupAndNewestCacheStored(
- AppCacheGroup* group, AppCache* newest_cache, bool success,
- bool would_exceed_quota) OVERRIDE {
+ void OnGroupAndNewestCacheStored(AppCacheGroup* group,
+ AppCache* newest_cache,
+ bool success,
+ bool would_exceed_quota) override {
stored_group_ = group;
stored_group_success_ = success;
}
- virtual void OnGroupMadeObsolete(AppCacheGroup* group,
- bool success,
- int response_code) OVERRIDE {
+ void OnGroupMadeObsolete(AppCacheGroup* group,
+ bool success,
+ int response_code) override {
obsoleted_group_ = group;
obsoleted_success_ = success;
}
- virtual void OnMainResponseFound(const GURL& url,
- const AppCacheEntry& entry,
- const GURL& fallback_url,
- const AppCacheEntry& fallback_entry,
- int64 cache_id,
- int64 group_id,
- const GURL& manifest_url) OVERRIDE {
+ void OnMainResponseFound(const GURL& url,
+ const AppCacheEntry& entry,
+ const GURL& fallback_url,
+ const AppCacheEntry& fallback_entry,
+ int64 cache_id,
+ int64 group_id,
+ const GURL& manifest_url) override {
found_url_ = url;
found_entry_ = entry;
found_fallback_url_ = fallback_url;
@@ -249,7 +238,7 @@ TEST_F(MockAppCacheStorageTest, StoreNewGroup) {
EXPECT_TRUE(delegate.stored_group_success_);
EXPECT_FALSE(storage->stored_caches_.empty());
EXPECT_FALSE(storage->stored_groups_.empty());
- EXPECT_EQ(cache, group->newest_complete_cache());
+ EXPECT_EQ(cache.get(), group->newest_complete_cache());
EXPECT_TRUE(cache->is_complete());
}
@@ -318,7 +307,7 @@ TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) {
// Hold our refs to simulate the UpdateJob holding these refs.
// Change the group's newest cache.
- EXPECT_EQ(cache, group->newest_complete_cache());
+ EXPECT_EQ(cache.get(), group->newest_complete_cache());
GURL entry_url("http://blah/blah");
cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::MASTER));
@@ -336,7 +325,7 @@ TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) {
EXPECT_EQ(size_t(1), storage->stored_caches_.size());
EXPECT_EQ(size_t(1), storage->stored_groups_.size());
EXPECT_TRUE(storage->IsCacheStored(cache.get()));
- EXPECT_EQ(cache, group->newest_complete_cache());
+ EXPECT_EQ(cache.get(), group->newest_complete_cache());
EXPECT_TRUE(cache->GetEntry(entry_url));
}
@@ -481,12 +470,12 @@ TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) {
const int64 kResponseId1 = 1;
const int64 kResponseId2 = 2;
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.fallback_namespaces.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1,
kFallbackEntryUrl1, false));
manifest.fallback_namespaces.push_back(
- Namespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
+ AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2,
kFallbackEntryUrl2, false));
scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
@@ -593,9 +582,9 @@ TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) {
const GURL kOnlineNamespaceUrl("http://blah/online_namespace");
const int64 kResponseId = 1;
- Manifest manifest;
+ AppCacheManifest manifest;
manifest.online_whitelist_namespaces.push_back(
- Namespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl,
+ AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl,
GURL(), false));
scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId));
cache->InitializeWithManifest(&manifest);
diff --git a/chromium/content/browser/appcache/view_appcache_internals_job.cc b/chromium/content/browser/appcache/view_appcache_internals_job.cc
index 0cc64c361f0..5e793bbb760 100644
--- a/chromium/content/browser/appcache/view_appcache_internals_job.cc
+++ b/chromium/content/browser/appcache/view_appcache_internals_job.cc
@@ -13,10 +13,17 @@
#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/appcache/appcache.h"
+#include "content/browser/appcache/appcache_group.h"
+#include "content/browser/appcache/appcache_policy.h"
+#include "content/browser/appcache/appcache_response.h"
+#include "content/browser/appcache/appcache_service_impl.h"
+#include "content/browser/appcache/appcache_storage.h"
#include "net/base/escape.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -24,24 +31,6 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_simple_job.h"
#include "net/url_request/view_cache_helper.h"
-#include "webkit/browser/appcache/appcache.h"
-#include "webkit/browser/appcache/appcache_group.h"
-#include "webkit/browser/appcache/appcache_policy.h"
-#include "webkit/browser/appcache/appcache_response.h"
-#include "webkit/browser/appcache/appcache_service_impl.h"
-#include "webkit/browser/appcache/appcache_storage.h"
-
-using appcache::AppCacheGroup;
-using appcache::AppCacheInfo;
-using appcache::AppCacheInfoCollection;
-using appcache::AppCacheInfoVector;
-using appcache::AppCacheServiceImpl;
-using appcache::AppCacheStorage;
-using appcache::AppCacheStorageReference;
-using appcache::AppCacheResourceInfo;
-using appcache::AppCacheResourceInfoVector;
-using appcache::AppCacheResponseInfo;
-using appcache::AppCacheResponseReader;
namespace content {
namespace {
@@ -332,12 +321,10 @@ class BaseInternalsJob : public net::URLRequestSimpleJob,
appcache_service_->AddObserver(this);
}
- virtual ~BaseInternalsJob() {
- appcache_service_->RemoveObserver(this);
- }
+ ~BaseInternalsJob() override { appcache_service_->RemoveObserver(this); }
- virtual void OnServiceReinitialized(
- AppCacheStorageReference* old_storage_ref) OVERRIDE {
+ void OnServiceReinitialized(
+ AppCacheStorageReference* old_storage_ref) override {
if (old_storage_ref->storage() == appcache_storage_)
disabled_storage_reference_ = old_storage_ref;
}
@@ -357,7 +344,7 @@ class MainPageJob : public BaseInternalsJob {
weak_factory_(this) {
}
- virtual void Start() OVERRIDE {
+ void Start() override {
DCHECK(request_);
info_collection_ = new AppCacheInfoCollection;
appcache_service_->GetAllAppCacheInfo(
@@ -367,10 +354,14 @@ class MainPageJob : public BaseInternalsJob {
}
// Produces a page containing the listing
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* out,
- const net::CompletionCallback& callback) const OVERRIDE {
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* out,
+ const net::CompletionCallback& callback) const override {
+ // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("422489 MainPageJob::GetData"));
+
mime_type->assign("text/html");
charset->assign("UTF-8");
@@ -399,7 +390,7 @@ class MainPageJob : public BaseInternalsJob {
}
private:
- virtual ~MainPageJob() {}
+ ~MainPageJob() override {}
void OnGotInfoComplete(int rv) {
if (rv != net::OK)
@@ -420,22 +411,21 @@ class RedirectToMainPageJob : public BaseInternalsJob {
AppCacheServiceImpl* service)
: BaseInternalsJob(request, network_delegate, service) {}
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* data,
- const net::CompletionCallback& callback) const OVERRIDE {
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const override {
return net::OK; // IsRedirectResponse induces a redirect.
}
- virtual bool IsRedirectResponse(GURL* location,
- int* http_status_code) OVERRIDE {
+ bool IsRedirectResponse(GURL* location, int* http_status_code) override {
*location = ClearQuery(request_->url());
*http_status_code = 307;
return true;
}
protected:
- virtual ~RedirectToMainPageJob() {}
+ ~RedirectToMainPageJob() override {}
};
// Job that removes an appcache and then redirects back to the main page.
@@ -451,7 +441,7 @@ class RemoveAppCacheJob : public RedirectToMainPageJob {
weak_factory_(this) {
}
- virtual void Start() OVERRIDE {
+ void Start() override {
DCHECK(request_);
appcache_service_->DeleteAppCacheGroup(
@@ -460,7 +450,7 @@ class RemoveAppCacheJob : public RedirectToMainPageJob {
}
private:
- virtual ~RemoveAppCacheJob() {}
+ ~RemoveAppCacheJob() override {}
void OnDeleteAppCacheComplete(int rv) {
StartAsync(); // Causes the base class to redirect.
@@ -483,16 +473,20 @@ class ViewAppCacheJob : public BaseInternalsJob,
: BaseInternalsJob(request, network_delegate, service),
manifest_url_(manifest_url) {}
- virtual void Start() OVERRIDE {
+ void Start() override {
DCHECK(request_);
appcache_storage_->LoadOrCreateGroup(manifest_url_, this);
}
// Produces a page containing the entries listing.
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* out,
- const net::CompletionCallback& callback) const OVERRIDE {
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* out,
+ const net::CompletionCallback& callback) const override {
+ // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("422489 ViewAppCacheJob::GetData"));
+
mime_type->assign("text/html");
charset->assign("UTF-8");
out->clear();
@@ -513,13 +507,12 @@ class ViewAppCacheJob : public BaseInternalsJob,
}
private:
- virtual ~ViewAppCacheJob() {
+ ~ViewAppCacheJob() override {
appcache_storage_->CancelDelegateCallbacks(this);
}
// AppCacheStorage::Delegate override
- virtual void OnGroupLoaded(
- AppCacheGroup* group, const GURL& manifest_url) OVERRIDE {
+ void OnGroupLoaded(AppCacheGroup* group, const GURL& manifest_url) override {
DCHECK_EQ(manifest_url_, manifest_url);
if (group && group->newest_complete_cache()) {
appcache_info_.manifest_url = manifest_url;
@@ -558,17 +551,21 @@ class ViewEntryJob : public BaseInternalsJob,
response_id_(response_id), group_id_(group_id), amount_read_(0) {
}
- virtual void Start() OVERRIDE {
+ void Start() override {
DCHECK(request_);
appcache_storage_->LoadResponseInfo(
manifest_url_, group_id_, response_id_, this);
}
// Produces a page containing the response headers and data.
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* out,
- const net::CompletionCallback& callback) const OVERRIDE {
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* out,
+ const net::CompletionCallback& callback) const override {
+ // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION("422489 ViewEntryJob::GetData"));
+
mime_type->assign("text/html");
charset->assign("UTF-8");
out->clear();
@@ -598,12 +595,10 @@ class ViewEntryJob : public BaseInternalsJob,
}
private:
- virtual ~ViewEntryJob() {
- appcache_storage_->CancelDelegateCallbacks(this);
- }
+ ~ViewEntryJob() override { appcache_storage_->CancelDelegateCallbacks(this); }
- virtual void OnResponseInfoLoaded(
- AppCacheResponseInfo* response_info, int64 response_id) OVERRIDE {
+ void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
+ int64 response_id) override {
if (!response_info) {
StartAsync();
return;
@@ -664,8 +659,8 @@ net::URLRequestJob* ViewAppCacheInternalsJobFactory::CreateJobForRequest(
DecodeBase64URL(param));
std::vector<std::string> tokens;
- int64 response_id;
- int64 group_id;
+ int64 response_id = 0;
+ int64 group_id = 0;
if (command == kViewEntryCommand && Tokenize(param, "|", &tokens) == 4u &&
base::StringToInt64(tokens[2], &response_id) &&
base::StringToInt64(tokens[3], &group_id)) {
diff --git a/chromium/content/browser/appcache/view_appcache_internals_job.h b/chromium/content/browser/appcache/view_appcache_internals_job.h
index f11b68e5875..5118212cd51 100644
--- a/chromium/content/browser/appcache/view_appcache_internals_job.h
+++ b/chromium/content/browser/appcache/view_appcache_internals_job.h
@@ -13,23 +13,20 @@ class URLRequest;
class URLRequestJob;
}
-namespace appcache {
-class AppCacheServiceImpl;
-}
-
namespace content {
+class AppCacheServiceImpl;
class ViewAppCacheInternalsJobFactory {
public:
static net::URLRequestJob* CreateJobForRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- appcache::AppCacheServiceImpl* service);
+ AppCacheServiceImpl* service);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ViewAppCacheInternalsJobFactory);
};
-} // namespace appcache
+} // namespace content
#endif // CONTENT_BROWSER_APPCACHE_VIEW_APPCACHE_INTERNALS_JOB_H_
diff --git a/chromium/content/browser/battery_status/OWNERS b/chromium/content/browser/battery_status/OWNERS
deleted file mode 100644
index 1fd89e0e2eb..00000000000
--- a/chromium/content/browser/battery_status/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-timvolodine@chromium.org
diff --git a/chromium/content/browser/battery_status/battery_status_browsertest.cc b/chromium/content/browser/battery_status/battery_status_browsertest.cc
index 76878315054..7da7f86d082 100644
--- a/chromium/content/browser/battery_status/battery_status_browsertest.cc
+++ b/chromium/content/browser/battery_status/battery_status_browsertest.cc
@@ -4,8 +4,7 @@
#include "base/command_line.h"
#include "base/synchronization/waitable_event.h"
-#include "content/browser/battery_status/battery_status_manager.h"
-#include "content/browser/battery_status/battery_status_service.h"
+#include "base/thread_task_runner_handle.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
@@ -13,36 +12,38 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "device/battery/battery_status_manager.h"
+#include "device/battery/battery_status_service.h"
namespace content {
namespace {
-class FakeBatteryManager : public BatteryStatusManager {
+class FakeBatteryManager : public device::BatteryStatusManager {
public:
explicit FakeBatteryManager(
- const BatteryStatusService::BatteryUpdateCallback& callback)
- : battery_status_available_(true),
- started_(false) {
- callback_ = callback;
- }
- virtual ~FakeBatteryManager() { }
+ const device::BatteryStatusService::BatteryUpdateCallback& callback)
+ : callback_(callback), battery_status_available_(true), started_(false) {}
+ ~FakeBatteryManager() override {}
// Methods from BatteryStatusManager.
- virtual bool StartListeningBatteryChange() OVERRIDE {
+ bool StartListeningBatteryChange() override {
started_ = true;
if (battery_status_available_)
InvokeUpdateCallback();
return battery_status_available_;
}
- virtual void StopListeningBatteryChange() OVERRIDE { }
+ void StopListeningBatteryChange() override {}
void InvokeUpdateCallback() {
- callback_.Run(status_);
+ // Invoke asynchronously to mimic the OS-specific battery managers.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(callback_, status_));
}
- void set_battery_status(const blink::WebBatteryStatus& status) {
+ void set_battery_status(const device::BatteryStatus& status) {
status_ = status;
}
@@ -55,9 +56,10 @@ class FakeBatteryManager : public BatteryStatusManager {
}
private:
+ device::BatteryStatusService::BatteryUpdateCallback callback_;
bool battery_status_available_;
bool started_;
- blink::WebBatteryStatus status_;
+ device::BatteryStatus status_;
DISALLOW_COPY_AND_ASSIGN(FakeBatteryManager);
};
@@ -65,33 +67,32 @@ class FakeBatteryManager : public BatteryStatusManager {
class BatteryStatusBrowserTest : public ContentBrowserTest {
public:
BatteryStatusBrowserTest()
- : battery_manager_(0),
- battery_service_(0),
- io_loop_finished_event_(false, false) {
+ : battery_manager_(NULL),
+ battery_service_(NULL) {
}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
}
- virtual void SetUpOnMainThread() OVERRIDE {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&BatteryStatusBrowserTest::SetUpOnIOThread, this));
- io_loop_finished_event_.Wait();
- }
+ void SetUpOnMainThread() override {
+ battery_service_ = device::BatteryStatusService::GetInstance();
+
+ // We keep a raw pointer to the FakeBatteryManager, which we expect to
+ // remain valid for the lifetime of the BatteryStatusService.
+ scoped_ptr<FakeBatteryManager> battery_manager(new FakeBatteryManager(
+ battery_service_->GetUpdateCallbackForTesting()));
+ battery_manager_ = battery_manager.get();
- void SetUpOnIOThread() {
- battery_service_ = BatteryStatusService::GetInstance();
- battery_manager_ = new FakeBatteryManager(
- battery_service_->GetUpdateCallbackForTesting());
- battery_service_->SetBatteryManagerForTesting(battery_manager_);
- io_loop_finished_event_.Signal();
+ battery_service_->SetBatteryManagerForTesting(
+ battery_manager.Pass());
}
- virtual void TearDown() OVERRIDE {
- battery_service_->SetBatteryManagerForTesting(0);
+ void TearDown() override {
+ battery_service_->SetBatteryManagerForTesting(
+ scoped_ptr<device::BatteryStatusManager>());
+ battery_manager_ = NULL;
}
FakeBatteryManager* battery_manager() {
@@ -100,8 +101,7 @@ class BatteryStatusBrowserTest : public ContentBrowserTest {
private:
FakeBatteryManager* battery_manager_;
- BatteryStatusService* battery_service_;
- base::WaitableEvent io_loop_finished_event_;
+ device::BatteryStatusService* battery_service_;
DISALLOW_COPY_AND_ASSIGN(BatteryStatusBrowserTest);
};
@@ -122,10 +122,10 @@ IN_PROC_BROWSER_TEST_F(BatteryStatusBrowserTest, BatteryManagerResolvePromise) {
// Set the fake battery manager to return predefined battery status values.
// From JavaScript request a promise for the battery status information and
// once it resolves check the values and navigate to #pass.
- blink::WebBatteryStatus status;
+ device::BatteryStatus status;
status.charging = true;
- status.chargingTime = 100;
- status.dischargingTime = std::numeric_limits<double>::infinity();
+ status.charging_time = 100;
+ status.discharging_time = std::numeric_limits<double>::infinity();
status.level = 0.5;
battery_manager()->set_battery_status(status);
@@ -143,7 +143,7 @@ IN_PROC_BROWSER_TEST_F(BatteryStatusBrowserTest,
// Once it resolves add an event listener for battery level change. Set
// battery level to 0.6 and invoke update. Check that the event listener
// is invoked with the correct value for level and navigate to #pass.
- blink::WebBatteryStatus status;
+ device::BatteryStatus status;
battery_manager()->set_battery_status(status);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
diff --git a/chromium/content/browser/battery_status/battery_status_manager.h b/chromium/content/browser/battery_status/battery_status_manager.h
deleted file mode 100644
index 20e71edfbb1..00000000000
--- a/chromium/content/browser/battery_status/battery_status_manager.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 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_BATTERY_STATUS_BATTERY_STATUS_MANAGER_H_
-#define CHROME_BROWSER_BATTERY_STATUS_BATTERY_STATUS_MANAGER_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/scoped_java_ref.h"
-#endif
-
-#include "content/browser/battery_status/battery_status_service.h"
-
-namespace content {
-
-// Platform specific manager class for fetching battery status data.
-class CONTENT_EXPORT BatteryStatusManager {
- public:
- explicit BatteryStatusManager(
- const BatteryStatusService::BatteryUpdateCallback& callback);
- virtual ~BatteryStatusManager();
-
- // Start listening for battery status changes. New updates are signalled
- // by invoking the callback provided at construction time.
- virtual bool StartListeningBatteryChange();
-
- // Stop listening for battery status changes.
- virtual void StopListeningBatteryChange();
-
-#if defined(OS_ANDROID)
- // Must be called at startup.
- static bool Register(JNIEnv* env);
-
- // Called from Java via JNI.
- void GotBatteryStatus(JNIEnv*, jobject, jboolean charging,
- jdouble charging_time, jdouble discharging_time,
- jdouble level);
-#endif
-
- protected:
- BatteryStatusManager();
- BatteryStatusService::BatteryUpdateCallback callback_;
-
- private:
-#if defined(OS_ANDROID)
- // Java provider of battery status info.
- base::android::ScopedJavaGlobalRef<jobject> j_manager_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusManager);
-};
-
-} // namespace content
-
-#endif // CHROME_BROWSER_BATTERY_STATUS_BATTERY_STATUS_MANAGER_H_
diff --git a/chromium/content/browser/battery_status/battery_status_manager_android.cc b/chromium/content/browser/battery_status/battery_status_manager_android.cc
deleted file mode 100644
index a8438b85572..00000000000
--- a/chromium/content/browser/battery_status/battery_status_manager_android.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 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 "content/browser/battery_status/battery_status_manager.h"
-
-#include "base/android/jni_android.h"
-#include "base/metrics/histogram.h"
-#include "jni/BatteryStatusManager_jni.h"
-
-using base::android::AttachCurrentThread;
-
-namespace content {
-
-BatteryStatusManager::BatteryStatusManager(
- const BatteryStatusService::BatteryUpdateCallback& callback)
- : callback_(callback) {
- j_manager_.Reset(
- Java_BatteryStatusManager_getInstance(
- AttachCurrentThread(), base::android::GetApplicationContext()));
-}
-
-BatteryStatusManager::BatteryStatusManager() {
-}
-
-BatteryStatusManager::~BatteryStatusManager() {
-}
-
-bool BatteryStatusManager::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-void BatteryStatusManager::GotBatteryStatus(JNIEnv*, jobject,
- jboolean charging, jdouble charging_time, jdouble discharging_time,
- jdouble level) {
- blink::WebBatteryStatus status;
- status.charging = charging;
- status.chargingTime = charging_time;
- status.dischargingTime = discharging_time;
- status.level = level;
- callback_.Run(status);
-}
-
-bool BatteryStatusManager::StartListeningBatteryChange() {
- bool result = Java_BatteryStatusManager_start(AttachCurrentThread(),
- j_manager_.obj(), reinterpret_cast<intptr_t>(this));
- UMA_HISTOGRAM_BOOLEAN("BatteryStatus.StartAndroid", result);
- return result;
-}
-
-void BatteryStatusManager::StopListeningBatteryChange() {
- Java_BatteryStatusManager_stop(
- AttachCurrentThread(), j_manager_.obj());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/battery_status/battery_status_manager_default.cc b/chromium/content/browser/battery_status/battery_status_manager_default.cc
deleted file mode 100644
index a8d066bdefd..00000000000
--- a/chromium/content/browser/battery_status/battery_status_manager_default.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 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 "content/browser/battery_status/battery_status_manager.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-BatteryStatusManager::BatteryStatusManager(
- const BatteryStatusService::BatteryUpdateCallback& callback)
- : callback_(callback) {
-}
-
-BatteryStatusManager::BatteryStatusManager() {
-}
-
-BatteryStatusManager::~BatteryStatusManager() {
-}
-
-bool BatteryStatusManager::StartListeningBatteryChange() {
- NOTIMPLEMENTED();
- return false;
-}
-
-void BatteryStatusManager::StopListeningBatteryChange() {
- NOTIMPLEMENTED();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/battery_status/battery_status_message_filter.cc b/chromium/content/browser/battery_status/battery_status_message_filter.cc
deleted file mode 100644
index 19a21b80787..00000000000
--- a/chromium/content/browser/battery_status/battery_status_message_filter.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 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 "content/browser/battery_status/battery_status_message_filter.h"
-
-#include "content/common/battery_status_messages.h"
-
-namespace content {
-
-BatteryStatusMessageFilter::BatteryStatusMessageFilter()
- : BrowserMessageFilter(BatteryStatusMsgStart),
- is_started_(false) {
- callback_ = base::Bind(&BatteryStatusMessageFilter::SendBatteryChange,
- base::Unretained(this));
-}
-
-BatteryStatusMessageFilter::~BatteryStatusMessageFilter() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (is_started_)
- subscription_.reset();
-}
-
-bool BatteryStatusMessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BatteryStatusMessageFilter, message)
- IPC_MESSAGE_HANDLER(BatteryStatusHostMsg_Start, OnBatteryStatusStart)
- IPC_MESSAGE_HANDLER(BatteryStatusHostMsg_Stop, OnBatteryStatusStop)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void BatteryStatusMessageFilter::OnBatteryStatusStart() {
- DCHECK(!is_started_);
- if (is_started_)
- return;
- is_started_ = true;
- subscription_ = BatteryStatusService::GetInstance()->AddCallback(callback_);
-}
-
-void BatteryStatusMessageFilter::OnBatteryStatusStop() {
- DCHECK(is_started_);
- if (!is_started_)
- return;
- is_started_ = false;
- subscription_.reset();
-}
-
-void BatteryStatusMessageFilter::SendBatteryChange(
- const blink::WebBatteryStatus& status) {
- Send(new BatteryStatusMsg_DidChange(status));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/battery_status/battery_status_message_filter.h b/chromium/content/browser/battery_status/battery_status_message_filter.h
index 9484114c576..efe94303c4e 100644
--- a/chromium/content/browser/battery_status/battery_status_message_filter.h
+++ b/chromium/content/browser/battery_status/battery_status_message_filter.h
@@ -15,10 +15,10 @@ class BatteryStatusMessageFilter : public BrowserMessageFilter {
BatteryStatusMessageFilter();
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~BatteryStatusMessageFilter();
+ ~BatteryStatusMessageFilter() override;
void OnBatteryStatusStart();
void OnBatteryStatusStop();
diff --git a/chromium/content/browser/battery_status/battery_status_service.cc b/chromium/content/browser/battery_status/battery_status_service.cc
deleted file mode 100644
index 21d59d3780d..00000000000
--- a/chromium/content/browser/battery_status/battery_status_service.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 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 "content/browser/battery_status/battery_status_service.h"
-
-#include "base/bind.h"
-#include "content/browser/battery_status/battery_status_manager.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-BatteryStatusService::BatteryStatusService()
- : update_callback_(base::Bind(&BatteryStatusService::UpdateBatteryStatus,
- base::Unretained(this))),
- status_updated_(false),
- is_shutdown_(false) {
- callback_list_.set_removal_callback(
- base::Bind(&BatteryStatusService::ConsumersChanged,
- base::Unretained(this)));
-}
-
-BatteryStatusService::~BatteryStatusService() {
-}
-
-BatteryStatusService* BatteryStatusService::GetInstance() {
- return Singleton<BatteryStatusService,
- LeakySingletonTraits<BatteryStatusService> >::get();
-}
-
-scoped_ptr<BatteryStatusService::BatteryUpdateSubscription>
-BatteryStatusService::AddCallback(const BatteryUpdateCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(!is_shutdown_);
-
- if (!battery_fetcher_)
- battery_fetcher_.reset(new BatteryStatusManager(update_callback_));
-
- if (callback_list_.empty()) {
- bool success = battery_fetcher_->StartListeningBatteryChange();
- if (!success) {
- // Make sure the promise resolves with the default values in Blink.
- callback.Run(blink::WebBatteryStatus());
- }
- }
-
- if (status_updated_) {
- // Send recent status to the new callback if already available.
- callback.Run(status_);
- }
-
- return callback_list_.Add(callback);
-}
-
-void BatteryStatusService::ConsumersChanged() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(!is_shutdown_);
-
- if (callback_list_.empty()) {
- battery_fetcher_->StopListeningBatteryChange();
- status_updated_ = false;
- }
-}
-
-void BatteryStatusService::UpdateBatteryStatus(
- const blink::WebBatteryStatus& status) {
- DCHECK(!is_shutdown_);
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&BatteryStatusService::NotifyConsumers,
- base::Unretained(this), status));
-}
-
-void BatteryStatusService::NotifyConsumers(
- const blink::WebBatteryStatus& status) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- if (callback_list_.empty())
- return;
-
- status_ = status;
- status_updated_ = true;
- callback_list_.Notify(status);
-}
-
-void BatteryStatusService::Shutdown() {
- if (!callback_list_.empty())
- battery_fetcher_->StopListeningBatteryChange();
- battery_fetcher_.reset();
- is_shutdown_ = true;
-}
-
-const BatteryStatusService::BatteryUpdateCallback&
-BatteryStatusService::GetUpdateCallbackForTesting() const {
- return update_callback_;
-}
-
-void BatteryStatusService::SetBatteryManagerForTesting(
- BatteryStatusManager* test_battery_manager) {
- battery_fetcher_.reset(test_battery_manager);
- blink::WebBatteryStatus status;
- status_ = status;
- status_updated_ = false;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/battery_status/battery_status_service.h b/chromium/content/browser/battery_status/battery_status_service.h
deleted file mode 100644
index 1c1e3648363..00000000000
--- a/chromium/content/browser/battery_status/battery_status_service.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_BATTERY_STATUS_BATTERY_STATUS_SERVICE_H_
-#define CONTENT_BROWSER_BATTERY_STATUS_BATTERY_STATUS_SERVICE_H_
-
-#include "base/callback_list.h"
-#include "base/memory/singleton.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatus.h"
-
-namespace content {
-class BatteryStatusManager;
-
-class CONTENT_EXPORT BatteryStatusService {
- public:
- typedef base::Callback<void(const blink::WebBatteryStatus&)>
- BatteryUpdateCallback;
- typedef base::CallbackList<void(const blink::WebBatteryStatus&)>
- BatteryUpdateCallbackList;
- typedef BatteryUpdateCallbackList::Subscription BatteryUpdateSubscription;
-
- // Returns the BatteryStatusService singleton.
- static BatteryStatusService* GetInstance();
-
- // Adds a callback to receive battery status updates.
- // Must be called on the I/O thread.
- scoped_ptr<BatteryUpdateSubscription> AddCallback(
- const BatteryUpdateCallback& callback);
-
- // Gracefully clean-up.
- void Shutdown();
-
- // Injects a custom battery status manager for testing purposes.
- // This class takes ownership of the injected object.
- void SetBatteryManagerForTesting(BatteryStatusManager* test_battery_manager);
-
- // Returns callback to invoke when battery is changed. Used for testing.
- const BatteryUpdateCallback& GetUpdateCallbackForTesting() const;
-
- private:
- friend struct DefaultSingletonTraits<BatteryStatusService>;
-
- BatteryStatusService();
- virtual ~BatteryStatusService();
-
- // Updates current battery status and sends new status to interested
- // render processes. Can be called on any thread via a callback.
- void UpdateBatteryStatus(const blink::WebBatteryStatus& status);
- void NotifyConsumers(const blink::WebBatteryStatus& status);
- void ConsumersChanged();
-
- scoped_ptr<BatteryStatusManager> battery_fetcher_;
- BatteryUpdateCallbackList callback_list_;
- BatteryUpdateCallback update_callback_;
- blink::WebBatteryStatus status_;
- bool status_updated_;
- bool is_shutdown_;
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusService);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BATTERY_STATUS_BATTERY_STATUS_SERVICE_H_
diff --git a/chromium/content/browser/battery_status/battery_status_service_unittest.cc b/chromium/content/browser/battery_status/battery_status_service_unittest.cc
deleted file mode 100644
index f92c8766fc8..00000000000
--- a/chromium/content/browser/battery_status/battery_status_service_unittest.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2014 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 "content/browser/battery_status/battery_status_service.h"
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "content/browser/battery_status/battery_status_manager.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-
-namespace content {
-
-namespace {
-
-class FakeBatteryManager : public BatteryStatusManager {
- public:
- explicit FakeBatteryManager(
- const BatteryStatusService::BatteryUpdateCallback& callback)
- : start_invoked_count_(0),
- stop_invoked_count_(0) {
- callback_ = callback;
- }
- virtual ~FakeBatteryManager() { }
-
- // Methods from Battery Status Manager
- virtual bool StartListeningBatteryChange() OVERRIDE {
- start_invoked_count_++;
- return true;
- }
-
- virtual void StopListeningBatteryChange() OVERRIDE {
- stop_invoked_count_++;
- }
-
- void InvokeUpdateCallback(const blink::WebBatteryStatus& status) {
- callback_.Run(status);
- }
-
- int start_invoked_count() const { return start_invoked_count_; }
- int stop_invoked_count() const { return stop_invoked_count_; }
-
- private:
- int start_invoked_count_;
- int stop_invoked_count_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeBatteryManager);
-};
-
-class BatteryStatusServiceTest : public testing::Test {
- public:
- BatteryStatusServiceTest()
- : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
- battery_service_(0),
- battery_manager_(0),
- callback1_invoked_count_(0),
- callback2_invoked_count_(0) {
- }
- virtual ~BatteryStatusServiceTest() { }
-
- protected:
- typedef BatteryStatusService::BatteryUpdateSubscription BatterySubscription;
-
- virtual void SetUp() OVERRIDE {
- callback1_ = base::Bind(&BatteryStatusServiceTest::Callback1,
- base::Unretained(this));
- callback2_ = base::Bind(&BatteryStatusServiceTest::Callback2,
- base::Unretained(this));
- battery_service_ = BatteryStatusService::GetInstance();
- battery_manager_ = new FakeBatteryManager(
- battery_service_->GetUpdateCallbackForTesting());
- battery_service_->SetBatteryManagerForTesting(battery_manager_);
- }
-
- virtual void TearDown() OVERRIDE {
- base::RunLoop().RunUntilIdle();
- battery_service_->SetBatteryManagerForTesting(0);
- }
-
- FakeBatteryManager* battery_manager() {
- return battery_manager_;
- }
-
- scoped_ptr<BatterySubscription> AddCallback(
- const BatteryStatusService::BatteryUpdateCallback& callback) {
- return battery_service_->AddCallback(callback);
- }
-
- int callback1_invoked_count() const {
- return callback1_invoked_count_;
- }
-
- int callback2_invoked_count() const {
- return callback2_invoked_count_;
- }
-
- const blink::WebBatteryStatus& battery_status() const {
- return battery_status_;
- }
-
- const BatteryStatusService::BatteryUpdateCallback& callback1() const {
- return callback1_;
- }
-
- const BatteryStatusService::BatteryUpdateCallback& callback2() const {
- return callback2_;
- }
-
- private:
- void Callback1(const blink::WebBatteryStatus& status) {
- callback1_invoked_count_++;
- battery_status_ = status;
- }
-
- void Callback2(const blink::WebBatteryStatus& status) {
- callback2_invoked_count_++;
- battery_status_ = status;
- }
-
- content::TestBrowserThreadBundle thread_bundle_;
- BatteryStatusService* battery_service_;
- FakeBatteryManager* battery_manager_;
- BatteryStatusService::BatteryUpdateCallback callback1_;
- BatteryStatusService::BatteryUpdateCallback callback2_;
- int callback1_invoked_count_;
- int callback2_invoked_count_;
- blink::WebBatteryStatus battery_status_;
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusServiceTest);
-};
-
-TEST_F(BatteryStatusServiceTest, AddFirstCallback) {
- scoped_ptr<BatterySubscription> subscription1 = AddCallback(callback1());
- EXPECT_EQ(1, battery_manager()->start_invoked_count());
- EXPECT_EQ(0, battery_manager()->stop_invoked_count());
- subscription1.reset();
- EXPECT_EQ(1, battery_manager()->start_invoked_count());
- EXPECT_EQ(1, battery_manager()->stop_invoked_count());
-}
-
-TEST_F(BatteryStatusServiceTest, AddCallbackAfterUpdate) {
- scoped_ptr<BatterySubscription> subscription1 = AddCallback(callback1());
- blink::WebBatteryStatus status;
- battery_manager()->InvokeUpdateCallback(status);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, callback1_invoked_count());
- EXPECT_EQ(0, callback2_invoked_count());
-
- scoped_ptr<BatterySubscription> subscription2 = AddCallback(callback2());
- EXPECT_EQ(1, callback1_invoked_count());
- EXPECT_EQ(1, callback2_invoked_count());
-}
-
-TEST_F(BatteryStatusServiceTest, TwoCallbacksUpdate) {
- scoped_ptr<BatterySubscription> subscription1 = AddCallback(callback1());
- scoped_ptr<BatterySubscription> subscription2 = AddCallback(callback2());
-
- blink::WebBatteryStatus status;
- status.charging = true;
- status.chargingTime = 100;
- status.dischargingTime = 200;
- status.level = 0.5;
- battery_manager()->InvokeUpdateCallback(status);
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, callback1_invoked_count());
- EXPECT_EQ(1, callback2_invoked_count());
- EXPECT_EQ(status.charging, battery_status().charging);
- EXPECT_EQ(status.chargingTime, battery_status().chargingTime);
- EXPECT_EQ(status.dischargingTime, battery_status().dischargingTime);
- EXPECT_EQ(status.level, battery_status().level);
-}
-
-TEST_F(BatteryStatusServiceTest, RemoveOneCallback) {
- scoped_ptr<BatterySubscription> subscription1 = AddCallback(callback1());
- scoped_ptr<BatterySubscription> subscription2 = AddCallback(callback2());
-
- blink::WebBatteryStatus status;
- battery_manager()->InvokeUpdateCallback(status);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, callback1_invoked_count());
- EXPECT_EQ(1, callback2_invoked_count());
-
- subscription1.reset();
- battery_manager()->InvokeUpdateCallback(status);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, callback1_invoked_count());
- EXPECT_EQ(2, callback2_invoked_count());
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/browser/bootstrap_sandbox_mac.cc b/chromium/content/browser/bootstrap_sandbox_mac.cc
index 040a23783ea..2361563b197 100644
--- a/chromium/content/browser/bootstrap_sandbox_mac.cc
+++ b/chromium/content/browser/bootstrap_sandbox_mac.cc
@@ -8,16 +8,9 @@
#include "base/mac/mac_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
-#include "content/browser/mach_broker_mac.h"
#include "content/common/sandbox_init_mac.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/child_process_data.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_process_host.h"
#include "content/public/common/sandbox_type_mac.h"
#include "sandbox/mac/bootstrap_sandbox.h"
@@ -27,8 +20,7 @@ namespace {
// This class is responsible for creating the BootstrapSandbox global
// singleton, as well as registering all associated policies with it.
-class BootstrapSandboxPolicy : public BrowserChildProcessObserver,
- public NotificationObserver {
+class BootstrapSandboxPolicy : public BrowserChildProcessObserver {
public:
static BootstrapSandboxPolicy* GetInstance();
@@ -37,27 +29,16 @@ class BootstrapSandboxPolicy : public BrowserChildProcessObserver,
}
// BrowserChildProcessObserver:
- virtual void BrowserChildProcessHostDisconnected(
- const ChildProcessData& data) OVERRIDE;
- virtual void BrowserChildProcessCrashed(
- const ChildProcessData& data) OVERRIDE;
-
- // NotificationObserver:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void BrowserChildProcessHostDisconnected(
+ const ChildProcessData& data) override;
+ void BrowserChildProcessCrashed(const ChildProcessData& data) override;
private:
friend struct DefaultSingletonTraits<BootstrapSandboxPolicy>;
BootstrapSandboxPolicy();
- virtual ~BootstrapSandboxPolicy();
+ ~BootstrapSandboxPolicy() override;
void RegisterSandboxPolicies();
- void RegisterRendererPolicy();
-
- void AddBaselinePolicy(sandbox::BootstrapSandboxPolicy* policy);
-
- NotificationRegistrar notification_registrar_;
scoped_ptr<sandbox::BootstrapSandbox> sandbox_;
};
@@ -76,26 +57,10 @@ void BootstrapSandboxPolicy::BrowserChildProcessCrashed(
sandbox()->ChildDied(data.handle);
}
-void BootstrapSandboxPolicy::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- switch (type) {
- case NOTIFICATION_RENDERER_PROCESS_CLOSED:
- sandbox()->ChildDied(
- Details<RenderProcessHost::RendererClosedDetails>(details)->handle);
- break;
- default:
- NOTREACHED() << "Unexpected notification " << type;
- break;
- }
-}
-
BootstrapSandboxPolicy::BootstrapSandboxPolicy()
: sandbox_(sandbox::BootstrapSandbox::Create()) {
CHECK(sandbox_.get());
BrowserChildProcessObserver::Add(this);
- notification_registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
- NotificationService::AllBrowserContextsAndSources());
RegisterSandboxPolicies();
}
@@ -104,42 +69,13 @@ BootstrapSandboxPolicy::~BootstrapSandboxPolicy() {
}
void BootstrapSandboxPolicy::RegisterSandboxPolicies() {
- RegisterRendererPolicy();
-}
-
-void BootstrapSandboxPolicy::RegisterRendererPolicy() {
- sandbox::BootstrapSandboxPolicy policy;
- AddBaselinePolicy(&policy);
-
- // Permit font queries.
- policy.rules["com.apple.FontServer"] = sandbox::Rule(sandbox::POLICY_ALLOW);
- policy.rules["com.apple.FontObjectsServer"] =
- sandbox::Rule(sandbox::POLICY_ALLOW);
-
- // Allow access to the windowserver. This is needed to get the colorspace
- // during sandbox warmup. Since NSColorSpace conforms to NSCoding, this
- // should be plumbed over IPC instead <http://crbug.com/265709>.
- policy.rules["com.apple.windowserver.active"] =
- sandbox::Rule(sandbox::POLICY_ALLOW);
-
- sandbox_->RegisterSandboxPolicy(SANDBOX_TYPE_RENDERER, policy);
-}
-
-void BootstrapSandboxPolicy::AddBaselinePolicy(
- sandbox::BootstrapSandboxPolicy* policy) {
- auto& rules = policy->rules;
-
- // Allow the child to send its task port to the MachBroker.
- rules[MachBroker::GetMachPortName()] = sandbox::Rule(sandbox::POLICY_ALLOW);
-
- // Allow logging to the syslog.
- rules["com.apple.system.logger"] = sandbox::Rule(sandbox::POLICY_ALLOW);
}
} // namespace
bool ShouldEnableBootstrapSandbox() {
- return false;
+ return base::mac::IsOSMountainLionOrEarlier() ||
+ base::mac::IsOSMavericks();
}
sandbox::BootstrapSandbox* GetBootstrapSandbox() {
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index c2d31b8a697..b22ee21aae6 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -11,7 +11,6 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
@@ -106,14 +105,12 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
g_child_process_list.Get().push_back(this);
GetContentClient()->browser()->BrowserChildProcessHostCreated(this);
+
+ power_monitor_message_broadcaster_.Init();
}
BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
g_child_process_list.Get().remove(this);
-
-#if defined(OS_WIN)
- DeleteProcessWaitableEvent(early_exit_watcher_.GetWatchedEvent());
-#endif
}
// static
@@ -130,13 +127,14 @@ void BrowserChildProcessHostImpl::TerminateAll() {
void BrowserChildProcessHostImpl::Launch(
SandboxedProcessLauncherDelegate* delegate,
- CommandLine* cmd_line) {
+ base::CommandLine* cmd_line) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
GetContentClient()->browser()->AppendExtraCommandLineSwitches(
cmd_line, data_.id);
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
static const char* kForwardSwitches[] = {
switches::kDisableLogging,
switches::kEnableLogging,
@@ -145,9 +143,6 @@ void BrowserChildProcessHostImpl::Launch(
switches::kTraceToConsole,
switches::kV,
switches::kVModule,
-#if defined(OS_WIN)
- switches::kEnableHighResolutionTime,
-#endif
};
cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
@@ -173,9 +168,9 @@ base::ProcessHandle BrowserChildProcessHostImpl::GetHandle() const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(child_process_.get())
<< "Requesting a child process handle before launching.";
- DCHECK(child_process_->GetHandle())
+ DCHECK(child_process_->GetProcess().IsValid())
<< "Requesting a child process handle before launch has completed OK.";
- return child_process_->GetHandle();
+ return child_process_->GetProcess().Handle();
}
void BrowserChildProcessHostImpl::SetName(const base::string16& name) {
@@ -239,7 +234,6 @@ void BrowserChildProcessHostImpl::OnChannelConnected(int32 peer_pid) {
#if defined(OS_WIN)
// From this point onward, the exit of the child process is detected by an
// error on the IPC channel.
- DeleteProcessWaitableEvent(early_exit_watcher_.GetWatchedEvent());
early_exit_watcher_.StopWatching();
#endif
@@ -270,8 +264,12 @@ bool BrowserChildProcessHostImpl::CanShutdown() {
void BrowserChildProcessHostImpl::OnChildDisconnected() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+#if defined(OS_WIN)
+ // OnChildDisconnected may be called without OnChannelConnected, so stop the
+ // early exit watcher so GetTerminationStatus can close the process handle.
+ early_exit_watcher_.StopWatching();
+#endif
if (child_process_.get() || data_.handle) {
- DCHECK(data_.handle != base::kNullProcessHandle);
int exit_code;
base::TerminationStatus status = GetTerminationStatus(
true /* known_dead */, &exit_code);
@@ -321,45 +319,26 @@ void BrowserChildProcessHostImpl::OnProcessLaunchFailed() {
}
void BrowserChildProcessHostImpl::OnProcessLaunched() {
- base::ProcessHandle handle = child_process_->GetHandle();
- if (!handle) {
- delete delegate_; // Will delete us
- return;
- }
+ const base::Process& process = child_process_->GetProcess();
+ DCHECK(process.IsValid());
#if defined(OS_WIN)
// Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
// child process exits. This watcher is stopped once the IPC channel is
// connected and the exit of the child process is detecter by an error on the
// IPC channel thereafter.
- DCHECK(!early_exit_watcher_.GetWatchedEvent());
- early_exit_watcher_.StartWatching(
- new base::WaitableEvent(handle),
- base::Bind(&BrowserChildProcessHostImpl::OnProcessExitedEarly,
- base::Unretained(this)));
+ DCHECK(!early_exit_watcher_.GetWatchedObject());
+ early_exit_watcher_.StartWatching(process.Handle(), this);
#endif
- data_.handle = handle;
+ // TODO(rvargas) crbug.com/417532: Don't store a handle.
+ data_.handle = process.Handle();
delegate_->OnProcessLaunched();
}
#if defined(OS_WIN)
-void BrowserChildProcessHostImpl::DeleteProcessWaitableEvent(
- base::WaitableEvent* event) {
- if (!event)
- return;
-
- // The WaitableEvent does not own the process handle so ensure it does not
- // close it.
- event->Release();
-
- delete event;
-}
-
-void BrowserChildProcessHostImpl::OnProcessExitedEarly(
- base::WaitableEvent* event) {
- DeleteProcessWaitableEvent(event);
+void BrowserChildProcessHostImpl::OnObjectSignaled(HANDLE object) {
OnChildDisconnected();
}
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index b196551532e..4490b99e142 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -17,6 +17,10 @@
#include "content/public/browser/child_process_data.h"
#include "content/public/common/child_process_host_delegate.h"
+#if defined(OS_WIN)
+#include "base/win/object_watcher.h"
+#endif
+
namespace base {
class CommandLine;
}
@@ -33,37 +37,39 @@ class BrowserMessageFilter;
class CONTENT_EXPORT BrowserChildProcessHostImpl
: public BrowserChildProcessHost,
public NON_EXPORTED_BASE(ChildProcessHostDelegate),
+#if defined(OS_WIN)
+ public base::win::ObjectWatcher::Delegate,
+#endif
public ChildProcessLauncher::Client {
public:
BrowserChildProcessHostImpl(
int process_type,
BrowserChildProcessHostDelegate* delegate);
- virtual ~BrowserChildProcessHostImpl();
+ ~BrowserChildProcessHostImpl() override;
// Terminates all child processes and deletes each BrowserChildProcessHost
// instance.
static void TerminateAll();
// BrowserChildProcessHost implementation:
- virtual bool Send(IPC::Message* message) OVERRIDE;
- virtual void Launch(
- SandboxedProcessLauncherDelegate* delegate,
- base::CommandLine* cmd_line) OVERRIDE;
- virtual const ChildProcessData& GetData() const OVERRIDE;
- virtual ChildProcessHost* GetHost() const OVERRIDE;
- virtual base::TerminationStatus GetTerminationStatus(
- bool known_dead, int* exit_code) OVERRIDE;
- virtual void SetName(const base::string16& name) OVERRIDE;
- virtual void SetHandle(base::ProcessHandle handle) OVERRIDE;
+ bool Send(IPC::Message* message) override;
+ void Launch(SandboxedProcessLauncherDelegate* delegate,
+ base::CommandLine* cmd_line) override;
+ const ChildProcessData& GetData() const override;
+ ChildProcessHost* GetHost() const override;
+ base::TerminationStatus GetTerminationStatus(bool known_dead,
+ int* exit_code) override;
+ void SetName(const base::string16& name) override;
+ void SetHandle(base::ProcessHandle handle) override;
// ChildProcessHostDelegate implementation:
- virtual bool CanShutdown() OVERRIDE;
- virtual void OnChildDisconnected() OVERRIDE;
- virtual base::ProcessHandle GetHandle() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
- virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool CanShutdown() override;
+ void OnChildDisconnected() override;
+ base::ProcessHandle GetHandle() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
+ void OnBadMessageReceived(const IPC::Message& message) override;
// Removes this host from the host list. Calls ChildProcessHost::ForceShutdown
void ForceShutdown();
@@ -96,12 +102,12 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
static void RemoveObserver(BrowserChildProcessObserver* observer);
// ChildProcessLauncher::Client implementation.
- virtual void OnProcessLaunched() OVERRIDE;
- virtual void OnProcessLaunchFailed() OVERRIDE;
+ void OnProcessLaunched() override;
+ void OnProcessLaunchFailed() override;
#if defined(OS_WIN)
- void DeleteProcessWaitableEvent(base::WaitableEvent* event);
- void OnProcessExitedEarly(base::WaitableEvent* event);
+ // ObjectWatcher::Delegate implementation.
+ void OnObjectSignaled(HANDLE object) override;
#endif
ChildProcessData data_;
@@ -116,7 +122,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
// Watches to see if the child process exits before the IPC channel has
// been connected. Thereafter, its exit is determined by an error on the
// IPC channel.
- base::WaitableEventWatcher early_exit_watcher_;
+ base::win::ObjectWatcher early_exit_watcher_;
#endif
};
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index dbc5949317a..76188331198 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -9,6 +9,7 @@
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/push_messaging/push_messaging_router.h"
#include "content/browser/storage_partition_impl_map.h"
#include "content/common/child_process_host_impl.h"
#include "content/public/browser/blob_handle.h"
@@ -17,12 +18,12 @@
#include "content/public/browser/site_instance.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
-#include "net/ssl/server_bound_cert_service.h"
-#include "net/ssl/server_bound_cert_store.h"
+#include "net/ssl/channel_id_service.h"
+#include "net/ssl/channel_id_store.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
-#include "webkit/browser/database/database_tracker.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
+#include "storage/browser/database/database_tracker.h"
+#include "storage/browser/fileapi/external_mount_points.h"
#endif // !OS_IOS
using base::UserDataAdapter;
@@ -69,11 +70,11 @@ StoragePartition* GetStoragePartitionFromConfig(
void SaveSessionStateOnIOThread(
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
- appcache::AppCacheServiceImpl* appcache_service) {
+ AppCacheServiceImpl* appcache_service) {
net::URLRequestContext* context = context_getter->GetURLRequestContext();
context->cookie_store()->GetCookieMonster()->
SetForceKeepSessionState();
- context->server_bound_cert_service()->GetCertStore()->
+ context->channel_id_service()->GetChannelIDStore()->
SetForceKeepSessionState();
appcache_service->set_force_keep_session_state();
}
@@ -83,6 +84,13 @@ void SaveSessionStateOnIndexedDBThread(
indexed_db_context->SetForceKeepSessionState();
}
+void ShutdownServiceWorkerContext(StoragePartition* partition) {
+ ServiceWorkerContextWrapper* wrapper =
+ static_cast<ServiceWorkerContextWrapper*>(
+ partition->GetServiceWorkerContext());
+ wrapper->process_manager()->Shutdown();
+}
+
} // namespace
// static
@@ -124,7 +132,7 @@ DownloadManager* BrowserContext::GetDownloadManager(
}
// static
-fileapi::ExternalMountPoints* BrowserContext::GetMountPoints(
+storage::ExternalMountPoints* BrowserContext::GetMountPoints(
BrowserContext* context) {
// Ensure that these methods are called on the UI thread, except for
// unittests where a UI thread might not have been created.
@@ -133,15 +141,15 @@ fileapi::ExternalMountPoints* BrowserContext::GetMountPoints(
#if defined(OS_CHROMEOS)
if (!context->GetUserData(kMountPointsKey)) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points =
- fileapi::ExternalMountPoints::CreateRefCounted();
+ scoped_refptr<storage::ExternalMountPoints> mount_points =
+ storage::ExternalMountPoints::CreateRefCounted();
context->SetUserData(
kMountPointsKey,
- new UserDataAdapter<fileapi::ExternalMountPoints>(mount_points.get()));
+ new UserDataAdapter<storage::ExternalMountPoints>(mount_points.get()));
}
- return UserDataAdapter<fileapi::ExternalMountPoints>::Get(
- context, kMountPointsKey);
+ return UserDataAdapter<storage::ExternalMountPoints>::Get(context,
+ kMountPointsKey);
#else
return NULL;
#endif
@@ -212,6 +220,27 @@ void BrowserContext::CreateMemoryBackedBlob(BrowserContext* browser_context,
callback);
}
+// static
+void BrowserContext::DeliverPushMessage(
+ BrowserContext* browser_context,
+ const GURL& origin,
+ int64 service_worker_registration_id,
+ const std::string& data,
+ const base::Callback<void(PushDeliveryStatus)>& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ PushMessagingRouter::DeliverMessage(
+ browser_context, origin, service_worker_registration_id, data, callback);
+}
+
+// static
+void BrowserContext::NotifyWillBeDestroyed(BrowserContext* browser_context) {
+ // Service Workers must shutdown before the browser context is destroyed,
+ // since they keep render process hosts alive and the codebase assumes that
+ // render process hosts die before their profile (browser context) dies.
+ ForEachStoragePartition(browser_context,
+ base::Bind(ShutdownServiceWorkerContext));
+}
+
void BrowserContext::EnsureResourceContextInitialized(BrowserContext* context) {
// This will be enough to tickle initialization of BrowserContext if
// necessary, which initializes ResourceContext. The reason we don't call
@@ -236,7 +265,7 @@ void BrowserContext::SaveSessionState(BrowserContext* browser_context) {
base::Bind(
&SaveSessionStateOnIOThread,
make_scoped_refptr(browser_context->GetRequestContext()),
- static_cast<appcache::AppCacheServiceImpl*>(
+ static_cast<AppCacheServiceImpl*>(
storage_partition->GetAppCacheService())));
}
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 8bcc3d33b9d..c7dd81bcf36 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -7,12 +7,10 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/path_service.h"
#include "base/pending_task.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
@@ -23,7 +21,6 @@
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/hi_res_timer_manager.h"
-#include "content/browser/battery_status/battery_status_service.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/browser/download/save_file_manager.h"
@@ -35,10 +32,8 @@
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/histogram_synchronizer.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
-#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/net/browser_online_state_observer.h"
-#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/startup_task_runner.h"
@@ -54,6 +49,7 @@
#include "content/public/common/main_function_params.h"
#include "content/public/common/result_codes.h"
#include "crypto/nss_util.h"
+#include "device/battery/battery_status_service.h"
#include "media/audio/audio_manager.h"
#include "media/base/media.h"
#include "media/base/user_input_monitor.h"
@@ -79,13 +75,16 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
#include "content/browser/android/browser_startup_controller.h"
-#include "content/browser/android/surface_texture_peer_browser_impl.h"
+#include "content/browser/android/browser_surface_texture_manager.h"
#include "content/browser/android/tracing_controller_android.h"
+#include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
+#include "content/public/browser/screen_orientation_provider.h"
#include "ui/gl/gl_surface.h"
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "content/browser/bootstrap_sandbox_mac.h"
+#include "content/browser/cocoa/system_hotkey_helper_mac.h"
#include "content/browser/theme_helper_mac.h"
#endif
@@ -116,6 +115,10 @@
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
#endif
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_service_impl.h"
+#endif
+
#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
#endif
@@ -134,7 +137,7 @@ namespace content {
namespace {
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
-void SetupSandbox(const CommandLine& parsed_command_line) {
+void SetupSandbox(const base::CommandLine& parsed_command_line) {
TRACE_EVENT0("startup", "SetupSandbox");
base::FilePath sandbox_binary;
@@ -238,6 +241,47 @@ bool ShouldInitializeBrowserGpuChannelAndTransportSurface() {
}
#endif
+// Disable optimizations for this block of functions so the compiler doesn't
+// merge them all together. This makes it possible to tell what thread was
+// unresponsive by inspecting the callstack.
+MSVC_DISABLE_OPTIMIZE()
+MSVC_PUSH_DISABLE_WARNING(4748)
+
+NOINLINE void ResetThread_DB(scoped_ptr<BrowserProcessSubThread> thread) {
+ thread.reset();
+}
+
+NOINLINE void ResetThread_FILE(scoped_ptr<BrowserProcessSubThread> thread) {
+ thread.reset();
+}
+
+NOINLINE void ResetThread_FILE_USER_BLOCKING(
+ scoped_ptr<BrowserProcessSubThread> thread) {
+ thread.reset();
+}
+
+NOINLINE void ResetThread_PROCESS_LAUNCHER(
+ scoped_ptr<BrowserProcessSubThread> thread) {
+ thread.reset();
+}
+
+NOINLINE void ResetThread_CACHE(scoped_ptr<BrowserProcessSubThread> thread) {
+ thread.reset();
+}
+
+NOINLINE void ResetThread_IO(scoped_ptr<BrowserProcessSubThread> thread) {
+ thread.reset();
+}
+
+#if !defined(OS_IOS)
+NOINLINE void ResetThread_IndexedDb(scoped_ptr<base::Thread> thread) {
+ thread.reset();
+}
+#endif
+
+MSVC_POP_WARNING()
+MSVC_ENABLE_OPTIMIZE();
+
} // namespace
// The currently-running BrowserMainLoop. There can be one or zero.
@@ -271,12 +315,11 @@ void ImmediateShutdownAndExitProcess() {
class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver {
public:
MemoryObserver() {}
- virtual ~MemoryObserver() {}
+ ~MemoryObserver() override {}
- virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
- }
+ void WillProcessTask(const base::PendingTask& pending_task) override {}
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
+ void DidProcessTask(const base::PendingTask& pending_task) override {
#if !defined(OS_IOS) // No ProcessMetrics on IOS.
scoped_ptr<base::ProcessMetrics> process_metrics(
base::ProcessMetrics::CreateProcessMetrics(
@@ -287,7 +330,7 @@ class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver {
#endif
size_t private_bytes;
process_metrics->GetMemoryBytes(&private_bytes, NULL);
- HISTOGRAM_MEMORY_KB("Memory.BrowserUsed", private_bytes >> 10);
+ LOCAL_HISTOGRAM_MEMORY_KB("Memory.BrowserUsed", private_bytes >> 10);
#endif
}
private:
@@ -465,10 +508,6 @@ void BrowserMainLoop::MainMessageLoopStart() {
}
{
- TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:AudioMirroringManager");
- audio_mirroring_manager_.reset(new AudioMirroringManager());
- }
- {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:OnlineStateObserver");
online_state_observer_.reset(new BrowserOnlineStateObserver);
}
@@ -498,8 +537,16 @@ void BrowserMainLoop::MainMessageLoopStart() {
#if defined(OS_ANDROID)
{
- TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SurfaceTexturePeer");
- SurfaceTexturePeer::InitInstance(new SurfaceTexturePeerBrowserImpl());
+ TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SurfaceTextureManager");
+ SurfaceTextureManager::InitInstance(new BrowserSurfaceTextureManager);
+ }
+
+ {
+ TRACE_EVENT0("startup",
+ "BrowserMainLoop::Subsystem:ScreenOrientationProvider");
+ screen_orientation_delegate_.reset(
+ new ScreenOrientationDelegateAndroid());
+ ScreenOrientationProvider::SetDelegate(screen_orientation_delegate_.get());
}
#endif
@@ -598,7 +645,6 @@ void BrowserMainLoop::CreateStartupTasks() {
int BrowserMainLoop::CreateThreads() {
TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads");
- base::Thread::Options default_options;
base::Thread::Options io_message_loop_options;
io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO;
base::Thread::Options ui_message_loop_options;
@@ -613,7 +659,7 @@ int BrowserMainLoop::CreateThreads() {
thread_id < BrowserThread::ID_COUNT;
++thread_id) {
scoped_ptr<BrowserProcessSubThread>* thread_to_start = NULL;
- base::Thread::Options* options = &default_options;
+ base::Thread::Options options;
switch (thread_id) {
case BrowserThread::DB:
@@ -621,6 +667,7 @@ int BrowserMainLoop::CreateThreads() {
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::DB");
thread_to_start = &db_thread_;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
break;
case BrowserThread::FILE_USER_BLOCKING:
TRACE_EVENT_BEGIN1("startup",
@@ -637,30 +684,33 @@ int BrowserMainLoop::CreateThreads() {
// On Windows, the FILE thread needs to be have a UI message loop
// which pumps messages in such a way that Google Update can
// communicate back to us.
- options = &ui_message_loop_options;
+ options = ui_message_loop_options;
#else
- options = &io_message_loop_options;
+ options = io_message_loop_options;
#endif
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
break;
case BrowserThread::PROCESS_LAUNCHER:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::PROCESS_LAUNCHER");
thread_to_start = &process_launcher_thread_;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
break;
case BrowserThread::CACHE:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::CACHE");
thread_to_start = &cache_thread_;
- options = &io_message_loop_options;
+ options = io_message_loop_options;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
break;
case BrowserThread::IO:
TRACE_EVENT_BEGIN1("startup",
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::IO");
thread_to_start = &io_thread_;
- options = &io_message_loop_options;
+ options = io_message_loop_options;
break;
case BrowserThread::UI:
case BrowserThread::ID_COUNT:
@@ -673,7 +723,9 @@ int BrowserMainLoop::CreateThreads() {
if (thread_to_start) {
(*thread_to_start).reset(new BrowserProcessSubThread(id));
- (*thread_to_start)->StartWithOptions(*options);
+ if (!(*thread_to_start)->StartWithOptions(options)) {
+ LOG(FATAL) << "Failed to start the browser thread: id == " << id;
+ }
} else {
NOTREACHED();
}
@@ -803,42 +855,42 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
// - (Not sure why DB stops last.)
switch (thread_id) {
case BrowserThread::DB: {
- TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread");
- db_thread_.reset();
- }
- break;
- case BrowserThread::FILE_USER_BLOCKING: {
- TRACE_EVENT0("shutdown",
- "BrowserMainLoop::Subsystem:FileUserBlockingThread");
- file_user_blocking_thread_.reset();
- }
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DBThread");
+ ResetThread_DB(db_thread_.Pass());
break;
+ }
case BrowserThread::FILE: {
- TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread");
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:FileThread");
#if !defined(OS_IOS)
- // Clean up state that lives on or uses the file_thread_ before
- // it goes away.
- if (resource_dispatcher_host_)
- resource_dispatcher_host_.get()->save_file_manager()->Shutdown();
+ // Clean up state that lives on or uses the file_thread_ before
+ // it goes away.
+ if (resource_dispatcher_host_)
+ resource_dispatcher_host_.get()->save_file_manager()->Shutdown();
#endif // !defined(OS_IOS)
- file_thread_.reset();
- }
+ ResetThread_FILE(file_thread_.Pass());
+ break;
+ }
+ case BrowserThread::FILE_USER_BLOCKING: {
+ TRACE_EVENT0("shutdown",
+ "BrowserMainLoop::Subsystem:FileUserBlockingThread");
+ ResetThread_FILE_USER_BLOCKING(file_user_blocking_thread_.Pass());
break;
+ }
case BrowserThread::PROCESS_LAUNCHER: {
- TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread");
- process_launcher_thread_.reset();
- }
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:LauncherThread");
+ ResetThread_PROCESS_LAUNCHER(process_launcher_thread_.Pass());
break;
+ }
case BrowserThread::CACHE: {
- TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread");
- cache_thread_.reset();
- }
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:CacheThread");
+ ResetThread_CACHE(cache_thread_.Pass());
break;
+ }
case BrowserThread::IO: {
- TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread");
- io_thread_.reset();
- }
+ TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread");
+ ResetThread_IO(io_thread_.Pass());
break;
+ }
case BrowserThread::UI:
case BrowserThread::ID_COUNT:
default:
@@ -850,7 +902,7 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
#if !defined(OS_IOS)
{
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IndexedDBThread");
- indexed_db_thread_.reset();
+ ResetThread_IndexedDb(indexed_db_thread_.Pass());
}
#endif
@@ -886,7 +938,7 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
{
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:BatteryStatusService");
- BatteryStatusService::GetInstance()->Shutdown();
+ device::BatteryStatusService::GetInstance()->Shutdown();
}
{
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DeleteDataSources");
@@ -900,6 +952,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
}
+void BrowserMainLoop::StopStartupTracingTimer() {
+ startup_trace_timer_.Stop();
+}
+
void BrowserMainLoop::InitializeMainThread() {
TRACE_EVENT0("startup", "BrowserMainLoop::InitializeMainThread");
const char* kThreadName = "CrBrowserMain";
@@ -959,8 +1015,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
ImageTransportFactory::Initialize();
#if defined(USE_AURA)
if (aura::Env::GetInstance()) {
- aura::Env::GetInstance()->set_context_factory(
- content::GetContextFactory());
+ aura::Env::GetInstance()->set_context_factory(GetContextFactory());
}
#endif
}
@@ -1041,6 +1096,7 @@ int BrowserMainLoop::BrowserThreadsStarted() {
#if defined(OS_MACOSX)
ThemeHelperMac::GetInstance();
+ SystemHotkeyHelperMac::GetInstance()->DeferredLoadSystemHotkeys();
if (ShouldEnableBootstrapSandbox()) {
TRACE_EVENT0("startup",
"BrowserMainLoop::BrowserThreadsStarted:BootstrapSandbox");
@@ -1104,16 +1160,15 @@ void BrowserMainLoop::MainMessageLoopRun() {
#endif
}
-void BrowserMainLoop::InitStartupTracing(const CommandLine& command_line) {
- DCHECK(is_tracing_startup_);
-
+base::FilePath BrowserMainLoop::GetStartupTraceFileName(
+ const base::CommandLine& command_line) const {
base::FilePath trace_file = command_line.GetSwitchValuePath(
switches::kTraceStartupFile);
// trace_file = "none" means that startup events will show up for the next
// begin/end tracing (via about:tracing or AutomationProxy::BeginTracing/
// EndTracing, for example).
if (trace_file == base::FilePath().AppendASCII("none"))
- return;
+ return trace_file;
if (trace_file.empty()) {
#if defined(OS_ANDROID)
@@ -1124,6 +1179,15 @@ void BrowserMainLoop::InitStartupTracing(const CommandLine& command_line) {
#endif
}
+ return trace_file;
+}
+
+void BrowserMainLoop::InitStartupTracing(
+ const base::CommandLine& command_line) {
+ DCHECK(is_tracing_startup_);
+
+ startup_trace_file_ = GetStartupTraceFileName(parsed_command_line_);
+
std::string delay_str = command_line.GetSwitchValueASCII(
switches::kTraceStartupDuration);
int delay_secs = 5;
@@ -1133,17 +1197,18 @@ void BrowserMainLoop::InitStartupTracing(const CommandLine& command_line) {
delay_secs = 5;
}
- BrowserThread::PostDelayedTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&BrowserMainLoop::EndStartupTracing,
- base::Unretained(this), trace_file),
- base::TimeDelta::FromSeconds(delay_secs));
+ startup_trace_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(delay_secs),
+ this,
+ &BrowserMainLoop::EndStartupTracing);
}
-void BrowserMainLoop::EndStartupTracing(const base::FilePath& trace_file) {
+void BrowserMainLoop::EndStartupTracing() {
is_tracing_startup_ = false;
TracingController::GetInstance()->DisableRecording(
- trace_file, base::Bind(&OnStoppedStartupTracing));
+ TracingController::CreateFileSink(
+ startup_trace_file_,
+ base::Bind(OnStoppedStartupTracing, startup_trace_file_)));
}
} // namespace content
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index f38ac4234ab..188aa3209d3 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -6,8 +6,10 @@
#define CONTENT_BROWSER_BROWSER_MAIN_LOOP_H_
#include "base/basictypes.h"
+#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/timer/timer.h"
#include "content/browser/browser_process_sub_thread.h"
#include "content/public/browser/browser_main_runner.h"
@@ -35,7 +37,6 @@ class NetworkChangeNotifier;
} // namespace net
namespace content {
-class AudioMirroringManager;
class BrowserMainParts;
class BrowserOnlineStateObserver;
class BrowserShutdownImpl;
@@ -47,7 +48,9 @@ class StartupTaskRunner;
class TimeZoneMonitor;
struct MainFunctionParams;
-#if defined(OS_LINUX)
+#if defined(OS_ANDROID)
+class ScreenOrientationDelegate;
+#elif defined(OS_LINUX)
class DeviceMonitorLinux;
#elif defined(OS_MACOSX)
class DeviceMonitorMac;
@@ -90,9 +93,6 @@ class CONTENT_EXPORT BrowserMainLoop {
int GetResultCode() const { return result_code_; }
media::AudioManager* audio_manager() const { return audio_manager_.get(); }
- AudioMirroringManager* audio_mirroring_manager() const {
- return audio_mirroring_manager_.get();
- }
MediaStreamManager* media_stream_manager() const {
return media_stream_manager_.get();
}
@@ -104,6 +104,12 @@ class CONTENT_EXPORT BrowserMainLoop {
bool is_tracing_startup() const { return is_tracing_startup_; }
+ const base::FilePath& startup_trace_file() const {
+ return startup_trace_file_;
+ }
+
+ void StopStartupTracingTimer();
+
#if defined(OS_MACOSX) && !defined(OS_IOS)
DeviceMonitorMac* device_monitor_mac() const {
return device_monitor_mac_.get();
@@ -130,8 +136,10 @@ class CONTENT_EXPORT BrowserMainLoop {
void MainMessageLoopRun();
+ base::FilePath GetStartupTraceFileName(
+ const base::CommandLine& command_line) const;
void InitStartupTracing(const base::CommandLine& command_line);
- void EndStartupTracing(const base::FilePath& trace_file);
+ void EndStartupTracing();
// Members initialized on construction ---------------------------------------
const MainFunctionParams& parameters_;
@@ -150,7 +158,6 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<media::UserInputMonitor> user_input_monitor_;
scoped_ptr<media::AudioManager> audio_manager_;
scoped_ptr<media::MidiManager> midi_manager_;
- scoped_ptr<AudioMirroringManager> audio_mirroring_manager_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
// Per-process listener for online state changes.
scoped_ptr<BrowserOnlineStateObserver> online_state_observer_;
@@ -161,6 +168,10 @@ class CONTENT_EXPORT BrowserMainLoop {
#elif defined(OS_MACOSX) && !defined(OS_IOS)
scoped_ptr<DeviceMonitorMac> device_monitor_mac_;
#endif
+#if defined(OS_ANDROID)
+ // Android implementation of ScreenOrientationDelegate
+ scoped_ptr<ScreenOrientationDelegate> screen_orientation_delegate_;
+#endif
// The startup task runner is created by CreateStartupTasks()
scoped_ptr<StartupTaskRunner> startup_task_runner_;
@@ -190,6 +201,10 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<base::debug::TraceEventSystemStatsMonitor> system_stats_monitor_;
bool is_tracing_startup_;
+ base::FilePath startup_trace_file_;
+
+ // This timer initiates trace file saving.
+ base::OneShotTimer<BrowserMainLoop> startup_trace_timer_;
DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop);
};
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index c41fc9541c9..4a74b6eb5f8 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -20,25 +20,146 @@
#include "ui/base/ime/input_method_initializer.h"
#if defined(OS_WIN)
+#include <dwrite.h>
+#include "base/win/win_util.h"
#include "base/win/windows_version.h"
+#include "net/cert/sha256_legacy_support_win.h"
+#include "sandbox/win/src/sidestep/preamble_patcher.h"
+#include "skia/ext/fontmgr_default_win.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
#include "ui/base/win/scoped_ole_initializer.h"
+#include "ui/gfx/platform_font_win.h"
+#include "ui/gfx/switches.h"
+#include "ui/gfx/win/direct_write.h"
#endif
bool g_exited_main_message_loop = false;
namespace content {
+#if defined(OS_WIN)
+namespace {
+
+// Pointer to the original CryptVerifyCertificateSignatureEx function.
+net::sha256_interception::CryptVerifyCertificateSignatureExFunc
+ g_real_crypt_verify_signature_stub = NULL;
+
+// Stub function that is called whenever the Crypt32 function
+// CryptVerifyCertificateSignatureEx is called. It just defers to net to perform
+// the actual verification.
+BOOL WINAPI CryptVerifyCertificateSignatureExStub(
+ HCRYPTPROV_LEGACY provider,
+ DWORD encoding_type,
+ DWORD subject_type,
+ void* subject_data,
+ DWORD issuer_type,
+ void* issuer_data,
+ DWORD flags,
+ void* extra) {
+ return net::sha256_interception::CryptVerifyCertificateSignatureExHook(
+ g_real_crypt_verify_signature_stub, provider, encoding_type, subject_type,
+ subject_data, issuer_type, issuer_data, flags, extra);
+}
+
+// If necessary, install an interception
+void InstallSha256LegacyHooks() {
+#if defined(_WIN64)
+ // Interception on x64 is not supported.
+ return;
+#else
+ if (base::win::MaybeHasSHA256Support())
+ return;
+
+ net::sha256_interception::CryptVerifyCertificateSignatureExFunc
+ cert_verify_signature_ptr = reinterpret_cast<
+ net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
+ ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"),
+ "CryptVerifyCertificateSignatureEx"));
+ CHECK(cert_verify_signature_ptr);
+
+ DWORD old_protect = 0;
+ if (!::VirtualProtect(cert_verify_signature_ptr, 5, PAGE_EXECUTE_READWRITE,
+ &old_protect)) {
+ return;
+ }
+
+ g_real_crypt_verify_signature_stub =
+ reinterpret_cast<
+ net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
+ VirtualAllocEx(::GetCurrentProcess(), NULL,
+ sidestep::kMaxPreambleStubSize, MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE));
+ if (g_real_crypt_verify_signature_stub == NULL) {
+ CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
+ &old_protect));
+ return;
+ }
+
+ sidestep::SideStepError patch_result =
+ sidestep::PreamblePatcher::Patch(
+ cert_verify_signature_ptr, CryptVerifyCertificateSignatureExStub,
+ g_real_crypt_verify_signature_stub, sidestep::kMaxPreambleStubSize);
+ if (patch_result != sidestep::SIDESTEP_SUCCESS) {
+ CHECK(::VirtualFreeEx(::GetCurrentProcess(),
+ g_real_crypt_verify_signature_stub, 0,
+ MEM_RELEASE));
+ CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
+ &old_protect));
+ return;
+ }
+
+ DWORD dummy = 0;
+ CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, &dummy));
+ CHECK(::VirtualProtect(g_real_crypt_verify_signature_stub,
+ sidestep::kMaxPreambleStubSize, old_protect,
+ &old_protect));
+#endif // _WIN64
+}
+
+void MaybeEnableDirectWriteFontRendering() {
+ if (gfx::win::ShouldUseDirectWrite() &&
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDirectWriteForUI) &&
+ !CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableHarfBuzzRenderText)) {
+ typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
+ HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
+ if (!dwrite_dll)
+ return;
+
+ DWriteCreateFactoryProc dwrite_create_factory_proc =
+ reinterpret_cast<DWriteCreateFactoryProc>(
+ GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
+ // Not finding the DWriteCreateFactory function indicates a corrupt dll.
+ CHECK(dwrite_create_factory_proc);
+
+ IDWriteFactory* factory = NULL;
+
+ CHECK(SUCCEEDED(
+ dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown**>(&factory))));
+ SetDefaultSkiaFactory(SkFontMgr_New_DirectWrite(factory));
+ gfx::PlatformFontWin::set_use_skia_for_font_metrics(true);
+ }
+}
+
+} // namespace
+
+#endif // OS_WIN
+
class BrowserMainRunnerImpl : public BrowserMainRunner {
public:
BrowserMainRunnerImpl()
: initialization_started_(false), is_shutdown_(false) {}
- virtual ~BrowserMainRunnerImpl() {
+ ~BrowserMainRunnerImpl() override {
if (initialization_started_ && !is_shutdown_)
Shutdown();
}
- virtual int Initialize(const MainFunctionParams& parameters) OVERRIDE {
+ int Initialize(const MainFunctionParams& parameters) override {
TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
// On Android we normally initialize the browser in a series of UI thread
// tasks. While this is happening a second request can come from the OS or
@@ -64,6 +185,7 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// Win32 API here directly.
ImmDisableTextFrameService(static_cast<DWORD>(-1));
}
+ InstallSha256LegacyHooks();
#endif // OS_WIN
base::StatisticsRecorder::Initialize();
@@ -75,6 +197,8 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// (Text Services Framework) module can interact with the message pump
// on Windows 8 Metro mode.
ole_initializer_.reset(new ui::ScopedOleInitializer);
+ // Enable DirectWrite font rendering if needed.
+ MaybeEnableDirectWriteFontRendering();
#endif // OS_WIN
main_loop_.reset(new BrowserMainLoop(parameters));
@@ -112,14 +236,14 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
return -1;
}
- virtual int Run() OVERRIDE {
+ int Run() override {
DCHECK(initialization_started_);
DCHECK(!is_shutdown_);
main_loop_->RunMainMessageLoopParts();
return main_loop_->GetResultCode();
}
- virtual void Shutdown() OVERRIDE {
+ void Shutdown() override {
DCHECK(initialization_started_);
DCHECK(!is_shutdown_);
#ifdef LEAK_SANITIZER
@@ -130,13 +254,29 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// If leaks are found, the process will exit here.
__lsan_do_leak_check();
#endif
+ // If startup tracing has not been finished yet, replace it's dumper
+ // with special version, which would save trace file on exit (i.e.
+ // startup tracing becomes a version of shutdown tracing).
+ scoped_ptr<BrowserShutdownProfileDumper> startup_profiler;
+ if (main_loop_->is_tracing_startup()) {
+ main_loop_->StopStartupTracingTimer();
+ if (main_loop_->startup_trace_file() !=
+ base::FilePath().AppendASCII("none")) {
+ startup_profiler.reset(
+ new BrowserShutdownProfileDumper(main_loop_->startup_trace_file()));
+ }
+ }
+
// The shutdown tracing got enabled in AttemptUserExit earlier, but someone
// needs to write the result to disc. For that a dumper needs to get created
// which will dump the traces to disc when it gets destroyed.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- scoped_ptr<BrowserShutdownProfileDumper> profiler;
- if (command_line.HasSwitch(switches::kTraceShutdown))
- profiler.reset(new BrowserShutdownProfileDumper());
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ scoped_ptr<BrowserShutdownProfileDumper> shutdown_profiler;
+ if (command_line.HasSwitch(switches::kTraceShutdown)) {
+ shutdown_profiler.reset(new BrowserShutdownProfileDumper(
+ BrowserShutdownProfileDumper::GetShutdownProfileFileName()));
+ }
{
// The trace event has to stay between profiler creation and destruction.
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
index 30b47890802..cb471594ac8 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -22,12 +22,14 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "net/base/escape.h"
+#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace content {
BrowserPluginEmbedder::BrowserPluginEmbedder(WebContentsImpl* web_contents)
: WebContentsObserver(web_contents),
+ guest_drag_ending_(false),
weak_ptr_factory_(this) {
}
@@ -54,6 +56,7 @@ void BrowserPluginEmbedder::DragLeftGuest(BrowserPluginGuest* guest) {
void BrowserPluginEmbedder::StartDrag(BrowserPluginGuest* guest) {
guest_started_drag_ = guest->AsWeakPtr();
+ guest_drag_ending_ = false;
}
WebContentsImpl* BrowserPluginEmbedder::GetWebContents() const {
@@ -65,6 +68,20 @@ BrowserPluginEmbedder::GetBrowserPluginGuestManager() const {
return GetWebContents()->GetBrowserContext()->GetGuestManager();
}
+void BrowserPluginEmbedder::ClearGuestDragStateIfApplicable() {
+ // The order at which we observe SystemDragEnded() and DragSourceEndedAt() is
+ // platform dependent.
+ // In OSX, we see SystemDragEnded() first, where in aura, we see
+ // DragSourceEndedAt() first. For this reason, we check if both methods were
+ // called before resetting |guest_started_drag_|.
+ if (guest_drag_ending_) {
+ if (guest_started_drag_)
+ guest_started_drag_.reset();
+ } else {
+ guest_drag_ending_ = true;
+ }
+}
+
bool BrowserPluginEmbedder::DidSendScreenRectsCallback(
WebContents* guest_web_contents) {
static_cast<RenderViewHostImpl*>(
@@ -93,64 +110,93 @@ bool BrowserPluginEmbedder::OnMessageReceived(const IPC::Message& message) {
void BrowserPluginEmbedder::DragSourceEndedAt(int client_x, int client_y,
int screen_x, int screen_y, blink::WebDragOperation operation) {
- if (guest_started_drag_.get()) {
+ if (guest_started_drag_) {
gfx::Point guest_offset =
guest_started_drag_->GetScreenCoordinates(gfx::Point());
guest_started_drag_->DragSourceEndedAt(client_x - guest_offset.x(),
client_y - guest_offset.y(), screen_x, screen_y, operation);
}
+ ClearGuestDragStateIfApplicable();
}
void BrowserPluginEmbedder::SystemDragEnded() {
// When the embedder's drag/drop operation ends, we need to pass the message
// to the guest that initiated the drag/drop operation. This will ensure that
// the guest's RVH state is reset properly.
- if (guest_started_drag_.get())
+ if (guest_started_drag_)
guest_started_drag_->EndSystemDrag();
- guest_started_drag_.reset();
guest_dragging_over_.reset();
+ ClearGuestDragStateIfApplicable();
}
void BrowserPluginEmbedder::OnUpdateDragCursor(bool* handled) {
*handled = (guest_dragging_over_.get() != NULL);
}
-void BrowserPluginEmbedder::OnGuestCallback(
- int instance_id,
- const BrowserPluginHostMsg_Attach_Params& params,
- const base::DictionaryValue* extra_params,
- WebContents* guest_web_contents) {
- BrowserPluginGuest* guest = guest_web_contents ?
- static_cast<WebContentsImpl*>(guest_web_contents)->
- GetBrowserPluginGuest() : NULL;
- if (!guest) {
- scoped_ptr<base::DictionaryValue> copy_extra_params(
- extra_params->DeepCopy());
- guest_web_contents = GetBrowserPluginGuestManager()->CreateGuest(
- GetWebContents()->GetSiteInstance(),
- instance_id,
- copy_extra_params.Pass());
- guest = guest_web_contents
- ? static_cast<WebContentsImpl*>(guest_web_contents)
- ->GetBrowserPluginGuest()
- : NULL;
+void BrowserPluginEmbedder::OnAttach(
+ int browser_plugin_instance_id,
+ const BrowserPluginHostMsg_Attach_Params& params) {
+ WebContents* guest_web_contents =
+ GetBrowserPluginGuestManager()->GetGuestByInstanceID(
+ GetWebContents(), browser_plugin_instance_id);
+ if (!guest_web_contents)
+ return;
+ BrowserPluginGuest* guest = static_cast<WebContentsImpl*>(guest_web_contents)
+ ->GetBrowserPluginGuest();
+ guest->Attach(browser_plugin_instance_id, GetWebContents(), params);
+}
+
+bool BrowserPluginEmbedder::HandleKeyboardEvent(
+ const NativeWebKeyboardEvent& event) {
+ if ((event.windowsKeyCode != ui::VKEY_ESCAPE) ||
+ (event.modifiers & blink::WebInputEvent::InputModifiers)) {
+ return false;
}
- if (guest)
- guest->Attach(GetWebContents(), params, *extra_params);
+ bool event_consumed = false;
+ GetBrowserPluginGuestManager()->ForEachGuest(
+ GetWebContents(),
+ base::Bind(&BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback,
+ base::Unretained(this),
+ &event_consumed));
+
+ return event_consumed;
}
-void BrowserPluginEmbedder::OnAttach(
- int instance_id,
- const BrowserPluginHostMsg_Attach_Params& params,
- const base::DictionaryValue& extra_params) {
- GetBrowserPluginGuestManager()->MaybeGetGuestByInstanceIDOrKill(
- instance_id, GetWebContents()->GetRenderProcessHost()->GetID(),
- base::Bind(&BrowserPluginEmbedder::OnGuestCallback,
+bool BrowserPluginEmbedder::Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options) {
+ return GetBrowserPluginGuestManager()->ForEachGuest(
+ GetWebContents(),
+ base::Bind(&BrowserPluginEmbedder::FindInGuest,
base::Unretained(this),
- instance_id,
- params,
- &extra_params));
+ request_id,
+ search_text,
+ options));
+}
+
+bool BrowserPluginEmbedder::UnlockMouseIfNecessaryCallback(bool* mouse_unlocked,
+ WebContents* guest) {
+ *mouse_unlocked |= static_cast<WebContentsImpl*>(guest)
+ ->GetBrowserPluginGuest()
+ ->mouse_locked();
+ guest->GotResponseToLockMouseRequest(false);
+
+ // Returns false to iterate over all guests.
+ return false;
+}
+
+bool BrowserPluginEmbedder::FindInGuest(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options,
+ WebContents* guest) {
+ if (static_cast<WebContentsImpl*>(guest)->GetBrowserPluginGuest()->Find(
+ request_id, search_text, options)) {
+ // There can only ever currently be one browser plugin that handles find so
+ // we can break the iteration at this point.
+ return true;
+ }
+ return false;
}
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
index 3c35bef17a7..7ea98f7773a 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.h
@@ -39,7 +39,7 @@ struct NativeWebKeyboardEvent;
class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
public:
- virtual ~BrowserPluginEmbedder();
+ ~BrowserPluginEmbedder() override;
static BrowserPluginEmbedder* Create(WebContentsImpl* web_contents);
@@ -50,7 +50,7 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
void DidSendScreenRects();
// WebContentsObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void DragSourceEndedAt(int client_x, int client_y, int screen_x,
int screen_y, blink::WebDragOperation operation);
@@ -67,30 +67,34 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
// operation, if there's any.
void SystemDragEnded();
+ // Used to handle special keyboard events.
+ bool HandleKeyboardEvent(const NativeWebKeyboardEvent& event);
+
+ // Find the given |search_text| in the page. Returns true if the find request
+ // is handled by this browser plugin embedder.
+ bool Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options);
+
private:
explicit BrowserPluginEmbedder(WebContentsImpl* web_contents);
BrowserPluginGuestManager* GetBrowserPluginGuestManager() const;
- bool DidSendScreenRectsCallback(WebContents* guest_web_contents);
+ void ClearGuestDragStateIfApplicable();
- bool SetZoomLevelCallback(double level, WebContents* guest_web_contents);
+ bool DidSendScreenRectsCallback(WebContents* guest_web_contents);
- bool UnlockMouseIfNecessaryCallback(const NativeWebKeyboardEvent& event,
- WebContents* guest);
+ bool UnlockMouseIfNecessaryCallback(bool* mouse_unlocked, WebContents* guest);
- // Called by the content embedder when a guest exists with the provided
- // |instance_id|.
- void OnGuestCallback(int instance_id,
- const BrowserPluginHostMsg_Attach_Params& params,
- const base::DictionaryValue* extra_params,
- WebContents* guest_web_contents);
+ bool FindInGuest(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options,
+ WebContents* guest);
// Message handlers.
-
void OnAttach(int instance_id,
- const BrowserPluginHostMsg_Attach_Params& params,
- const base::DictionaryValue& extra_params);
+ const BrowserPluginHostMsg_Attach_Params& params);
void OnPluginAtPositionResponse(int instance_id,
int request_id,
const gfx::Point& position);
@@ -106,6 +110,9 @@ class CONTENT_EXPORT BrowserPluginEmbedder : public WebContentsObserver {
// status messages to the correct guest.
base::WeakPtr<BrowserPluginGuest> guest_started_drag_;
+ // Keeps track of "dragend" state.
+ bool guest_drag_ending_;
+
base::WeakPtrFactory<BrowserPluginEmbedder> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserPluginEmbedder);
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index b3bd05a6b21..c2db313eedd 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/message_loop/message_loop.h"
+#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_thread_impl.h"
@@ -19,9 +20,12 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
+#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_constants_internal.h"
#include "content/common/drag_messages.h"
+#include "content/common/frame_messages.h"
+#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
@@ -31,7 +35,7 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/drop_data.h"
-#include "third_party/WebKit/public/platform/WebCursorInfo.h"
+#include "ui/gfx/geometry/size_conversions.h"
#if defined(OS_MACOSX)
#include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
@@ -47,15 +51,14 @@ class BrowserPluginGuest::EmbedderWebContentsObserver
browser_plugin_guest_(guest) {
}
- virtual ~EmbedderWebContentsObserver() {
- }
+ ~EmbedderWebContentsObserver() override {}
// WebContentsObserver implementation.
- virtual void WasShown() OVERRIDE {
+ void WasShown() override {
browser_plugin_guest_->EmbedderVisibilityChanged(true);
}
- virtual void WasHidden() OVERRIDE {
+ void WasHidden() override {
browser_plugin_guest_->EmbedderVisibilityChanged(false);
}
@@ -65,43 +68,72 @@ class BrowserPluginGuest::EmbedderWebContentsObserver
DISALLOW_COPY_AND_ASSIGN(EmbedderWebContentsObserver);
};
-BrowserPluginGuest::BrowserPluginGuest(
- int instance_id,
- bool has_render_view,
- WebContentsImpl* web_contents)
+BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
+ WebContentsImpl* web_contents,
+ BrowserPluginGuestDelegate* delegate)
: WebContentsObserver(web_contents),
embedder_web_contents_(NULL),
- instance_id_(instance_id),
+ browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
guest_device_scale_factor_(1.0f),
focused_(false),
mouse_locked_(false),
pending_lock_request_(false),
guest_visible_(false),
- guest_opaque_(true),
embedder_visible_(true),
- auto_size_enabled_(false),
- copy_request_id_(0),
+ is_full_page_plugin_(false),
has_render_view_(has_render_view),
- last_seen_auto_size_enabled_(false),
is_in_destruction_(false),
last_text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
last_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
+ last_input_flags_(0),
last_can_compose_inline_(true),
- delegate_(NULL),
+ guest_proxy_routing_id_(MSG_ROUTING_NONE),
+ delegate_(delegate),
weak_ptr_factory_(this) {
DCHECK(web_contents);
+ DCHECK(delegate);
+ RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
+ web_contents->SetBrowserPluginGuest(this);
+ delegate->RegisterDestructionCallback(
+ base::Bind(&BrowserPluginGuest::WillDestroy, AsWeakPtr()));
}
void BrowserPluginGuest::WillDestroy() {
is_in_destruction_ = true;
embedder_web_contents_ = NULL;
- delegate_ = NULL;
}
base::WeakPtr<BrowserPluginGuest> BrowserPluginGuest::AsWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
+void BrowserPluginGuest::SetFocus(RenderWidgetHost* rwh, bool focused) {
+ focused_ = focused;
+ if (!rwh)
+ return;
+
+ rwh->Send(new InputMsg_SetFocus(rwh->GetRoutingID(), focused));
+ if (!focused && mouse_locked_)
+ OnUnlockMouse();
+
+ // Restore the last seen state of text input to the view.
+ RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
+ rwh->GetView());
+ if (rwhv) {
+ rwhv->TextInputTypeChanged(last_text_input_type_, last_input_mode_,
+ last_can_compose_inline_, last_input_flags_);
+ }
+}
+
+void BrowserPluginGuest::SetTooltipText(const base::string16& tooltip_text) {
+ if (tooltip_text == current_tooltip_text_)
+ return;
+ current_tooltip_text_ = tooltip_text;
+
+ SendMessageToEmbedder(new BrowserPluginMsg_SetTooltipText(
+ browser_plugin_instance_id_, tooltip_text));
+}
+
bool BrowserPluginGuest::LockMouse(bool allowed) {
if (!attached() || (mouse_locked_ == allowed))
return false;
@@ -109,43 +141,47 @@ bool BrowserPluginGuest::LockMouse(bool allowed) {
return embedder_web_contents()->GotResponseToLockMouseRequest(allowed);
}
-void BrowserPluginGuest::Destroy() {
- if (!delegate_)
- return;
- delegate_->Destroy();
+WebContentsImpl* BrowserPluginGuest::CreateNewGuestWindow(
+ const WebContents::CreateParams& params) {
+ WebContentsImpl* new_contents =
+ static_cast<WebContentsImpl*>(delegate_->CreateNewGuestWindow(params));
+ DCHECK(new_contents);
+ return new_contents;
}
bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
const IPC::Message& message) {
+ RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
+ web_contents()->GetRenderWidgetHostView());
+ if (rwhv &&
+ rwhv->OnMessageReceivedFromEmbedder(
+ message,
+ static_cast<RenderViewHostImpl*>(
+ embedder_web_contents()->GetRenderViewHost()))) {
+ return true;
+ }
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
OnCompositorFrameSwappedACK)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
- OnCopyFromCompositingSurfaceAck)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
OnDragStatusUpdate)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExecuteEditCommand,
OnExecuteEditCommand)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ExtendSelectionAndDelete,
OnExtendSelectionAndDelete)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
- OnHandleInputEvent)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeConfirmComposition,
OnImeConfirmComposition)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
OnImeSetComposition)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_PluginDestroyed, OnPluginDestroyed)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
OnReclaimCompositorResources)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ResizeGuest, OnResizeGuest)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetAutoSize, OnSetAutoSize)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetContentsOpaque,
- OnSetContentsOpaque)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetVisibility, OnSetVisibility)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UnlockMouse_ACK, OnUnlockMouseAck)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_UpdateGeometry, OnUpdateGeometry)
@@ -155,26 +191,25 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
}
void BrowserPluginGuest::Initialize(
+ int browser_plugin_instance_id,
const BrowserPluginHostMsg_Attach_Params& params,
- WebContentsImpl* embedder_web_contents,
- const base::DictionaryValue& extra_params) {
+ WebContentsImpl* embedder_web_contents) {
+ browser_plugin_instance_id_ = browser_plugin_instance_id;
focused_ = params.focused;
guest_visible_ = params.visible;
- guest_opaque_ = params.opaque;
+ is_full_page_plugin_ = params.is_full_page_plugin;
guest_window_rect_ = gfx::Rect(params.origin,
params.resize_guest_params.view_size);
- auto_size_enabled_ = params.auto_size_params.enable;
- max_auto_size_ = params.auto_size_params.max_size;
- min_auto_size_ = params.auto_size_params.min_size;
+ WebContentsViewGuest* new_view =
+ static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
+ if (attached())
+ new_view->OnGuestDetached(embedder_web_contents_->GetView());
// Once a BrowserPluginGuest has an embedder WebContents, it's considered to
// be attached.
embedder_web_contents_ = embedder_web_contents;
-
- WebContentsViewGuest* new_view =
- static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
- new_view->OnGuestInitialized(embedder_web_contents->GetView());
+ new_view->OnGuestAttached(embedder_web_contents->GetView());
RendererPreferences* renderer_prefs =
GetWebContents()->GetMutableRendererPrefs();
@@ -200,19 +235,12 @@ void BrowserPluginGuest::Initialize(
embedder_web_contents_observer_.reset(new EmbedderWebContentsObserver(this));
- OnSetAutoSize(
- instance_id_, params.auto_size_params, params.resize_guest_params);
-
- // Create a swapped out RenderView for the guest in the embedder render
- // process, so that the embedder can access the guest's window object.
- int guest_routing_id =
- GetWebContents()->CreateSwappedOutRenderView(
- embedder_web_contents_->GetSiteInstance());
- SendMessageToEmbedder(
- new BrowserPluginMsg_GuestContentWindowReady(instance_id_,
- guest_routing_id));
+ OnResizeGuest(browser_plugin_instance_id_, params.resize_guest_params);
- WebPreferences prefs = GetWebContents()->GetWebkitPrefs();
+ // TODO(chrishtr): this code is wrong. The navigate_on_drag_drop field will
+ // be reset again the next time preferences are updated.
+ WebPreferences prefs =
+ GetWebContents()->GetRenderViewHost()->GetWebkitPreferences();
prefs.navigate_on_drag_drop = false;
GetWebContents()->GetRenderViewHost()->UpdateWebkitPreferences(prefs);
@@ -225,7 +253,8 @@ void BrowserPluginGuest::Initialize(
}
// Inform the embedder of the guest's attachment.
- SendMessageToEmbedder(new BrowserPluginMsg_Attach_ACK(instance_id_));
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_Attach_ACK(browser_plugin_instance_id_));
}
BrowserPluginGuest::~BrowserPluginGuest() {
@@ -233,35 +262,10 @@ BrowserPluginGuest::~BrowserPluginGuest() {
// static
BrowserPluginGuest* BrowserPluginGuest::Create(
- int instance_id,
- SiteInstance* guest_site_instance,
WebContentsImpl* web_contents,
- scoped_ptr<base::DictionaryValue> extra_params,
- BrowserPluginGuest* opener) {
- RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
- BrowserPluginGuest* guest = new BrowserPluginGuest(
- instance_id, web_contents->opener() != NULL, web_contents);
- web_contents->SetBrowserPluginGuest(guest);
- WebContents* opener_web_contents = NULL;
- if (opener) {
- opener_web_contents = opener->GetWebContents();
- guest_site_instance = opener_web_contents->GetSiteInstance();
- }
- BrowserPluginGuestDelegate* delegate = NULL;
- GetContentClient()->browser()->GuestWebContentsCreated(
- instance_id,
- guest_site_instance,
- web_contents,
- opener_web_contents,
- &delegate,
- extra_params.Pass());
- if (delegate) {
- delegate->RegisterDestructionCallback(
- base::Bind(&BrowserPluginGuest::WillDestroy,
- base::Unretained(guest)));
- guest->set_delegate(delegate);
- }
- return guest;
+ BrowserPluginGuestDelegate* delegate) {
+ return new BrowserPluginGuest(
+ web_contents->opener() != NULL, web_contents, delegate);
}
// static
@@ -283,17 +287,7 @@ RenderWidgetHostView* BrowserPluginGuest::GetEmbedderRenderWidgetHostView() {
}
void BrowserPluginGuest::UpdateVisibility() {
- OnSetVisibility(instance_id_, visible());
-}
-
-void BrowserPluginGuest::CopyFromCompositingSurface(
- gfx::Rect src_subrect,
- gfx::Size dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback) {
- copy_request_callbacks_.insert(std::make_pair(++copy_request_id_, callback));
- SendMessageToEmbedder(
- new BrowserPluginMsg_CopyFromCompositingSurface(instance_id(),
- copy_request_id_, src_subrect, dst_size));
+ OnSetVisibility(browser_plugin_instance_id(), visible());
}
BrowserPluginGuestManager*
@@ -301,13 +295,6 @@ BrowserPluginGuest::GetBrowserPluginGuestManager() const {
return GetWebContents()->GetBrowserContext()->GetGuestManager();
}
-// screen.
-gfx::Rect BrowserPluginGuest::ToGuestRect(const gfx::Rect& bounds) {
- gfx::Rect guest_rect(bounds);
- guest_rect.Offset(guest_window_rect_.OffsetFromOrigin());
- return guest_rect;
-}
-
void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
embedder_visible_ = visible;
UpdateVisibility();
@@ -315,7 +302,46 @@ void BrowserPluginGuest::EmbedderVisibilityChanged(bool visible) {
void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
SendMessageToEmbedder(
- new BrowserPluginMsg_SetMouseLock(instance_id(), allow));
+ new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow));
+}
+
+void BrowserPluginGuest::SwapCompositorFrame(
+ uint32 output_surface_id,
+ int host_process_id,
+ int host_routing_id,
+ scoped_ptr<cc::CompositorFrame> frame) {
+ cc::RenderPass* root_pass =
+ frame->delegated_frame_data->render_pass_list.back();
+ gfx::Size view_size(gfx::ToFlooredSize(gfx::ScaleSize(
+ root_pass->output_rect.size(),
+ 1.0f / frame->metadata.device_scale_factor)));
+
+ if (last_seen_view_size_ != view_size) {
+ delegate_->GuestSizeChanged(last_seen_view_size_, view_size);
+ last_seen_view_size_ = view_size;
+ }
+
+ FrameMsg_CompositorFrameSwapped_Params guest_params;
+ frame->AssignTo(&guest_params.frame);
+ guest_params.output_surface_id = output_surface_id;
+ guest_params.producing_route_id = host_routing_id;
+ guest_params.producing_host_id = host_process_id;
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_CompositorFrameSwapped(
+ browser_plugin_instance_id(), guest_params));
+}
+
+void BrowserPluginGuest::SetContentsOpaque(bool opaque) {
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_SetContentsOpaque(
+ browser_plugin_instance_id(), opaque));
+}
+
+bool BrowserPluginGuest::Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options) {
+ return delegate_->Find(request_id, search_text, options,
+ is_full_page_plugin_);
}
WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
@@ -324,16 +350,19 @@ WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
gfx::Point BrowserPluginGuest::GetScreenCoordinates(
const gfx::Point& relative_position) const {
+ if (!attached())
+ return relative_position;
+
gfx::Point screen_pos(relative_position);
screen_pos += guest_window_rect_.OffsetFromOrigin();
+ if (embedder_web_contents()->GetBrowserPluginGuest()) {
+ BrowserPluginGuest* embedder_guest =
+ embedder_web_contents()->GetBrowserPluginGuest();
+ screen_pos += embedder_guest->guest_window_rect_.OffsetFromOrigin();
+ }
return screen_pos;
}
-bool BrowserPluginGuest::InAutoSizeBounds(const gfx::Size& size) const {
- return size.width() <= max_auto_size_.width() &&
- size.height() <= max_auto_size_.height();
-}
-
void BrowserPluginGuest::SendMessageToEmbedder(IPC::Message* msg) {
if (!attached()) {
// Some pages such as data URLs, javascript URLs, and about:blank
@@ -372,12 +401,9 @@ void BrowserPluginGuest::SendQueuedMessages() {
}
void BrowserPluginGuest::DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& url,
- PageTransition transition_type,
- RenderViewHost* render_view_host) {
+ ui::PageTransition transition_type) {
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
}
@@ -387,19 +413,14 @@ void BrowserPluginGuest::RenderViewReady() {
// here (see http://crbug.com/158151).
Send(new InputMsg_SetFocus(routing_id(), focused_));
UpdateVisibility();
- if (auto_size_enabled_)
- rvh->EnableAutoResize(min_auto_size_, max_auto_size_);
- else
- rvh->DisableAutoResize(full_size_);
-
- OnSetContentsOpaque(instance_id_, guest_opaque_);
RenderWidgetHostImpl::From(rvh)->set_hung_renderer_delay_ms(
base::TimeDelta::FromMilliseconds(kHungRendererDelayMs));
}
void BrowserPluginGuest::RenderProcessGone(base::TerminationStatus status) {
- SendMessageToEmbedder(new BrowserPluginMsg_GuestGone(instance_id()));
+ SendMessageToEmbedder(
+ new BrowserPluginMsg_GuestGone(browser_plugin_instance_id()));
switch (status) {
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
@@ -421,7 +442,6 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
const IPC::Message& message) {
switch (message.type()) {
case BrowserPluginHostMsg_CompositorFrameSwappedACK::ID:
- case BrowserPluginHostMsg_CopyFromCompositingSurfaceAck::ID:
case BrowserPluginHostMsg_DragStatusUpdate::ID:
case BrowserPluginHostMsg_ExecuteEditCommand::ID:
case BrowserPluginHostMsg_ExtendSelectionAndDelete::ID:
@@ -429,13 +449,10 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
case BrowserPluginHostMsg_ImeConfirmComposition::ID:
case BrowserPluginHostMsg_ImeSetComposition::ID:
case BrowserPluginHostMsg_LockMouse_ACK::ID:
- case BrowserPluginHostMsg_PluginDestroyed::ID:
case BrowserPluginHostMsg_ReclaimCompositorResources::ID:
case BrowserPluginHostMsg_ResizeGuest::ID:
- case BrowserPluginHostMsg_SetAutoSize::ID:
case BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent::ID:
case BrowserPluginHostMsg_SetFocus::ID:
- case BrowserPluginHostMsg_SetContentsOpaque::ID:
case BrowserPluginHostMsg_SetVisibility::ID:
case BrowserPluginHostMsg_UnlockMouse_ACK::ID:
case BrowserPluginHostMsg_UpdateGeometry::ID:
@@ -448,66 +465,96 @@ bool BrowserPluginGuest::ShouldForwardToBrowserPluginGuest(
bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
+ IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
+ OnImeCancelComposition)
+#if defined(OS_MACOSX) || defined(USE_AURA)
+ IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
+ OnImeCompositionRangeChanged)
+#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
OnHasTouchEventHandlers)
IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
- #if defined(OS_MACOSX)
- // MacOSX creates and populates platform-specific select drop-down menus
- // whereas other platforms merely create a popup window that the guest
- // renderer process paints inside.
- IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
- #endif
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
- IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
- OnTextInputStateChanged)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
- OnImeCancelComposition)
-#if defined(OS_MACOSX) || defined(USE_AURA)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
- OnImeCompositionRangeChanged)
-#endif
+ IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
+ OnTextInputTypeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+bool BrowserPluginGuest::OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) {
+ // This will eventually be the home for more IPC handlers that depend on
+ // RenderFrameHost. Until more are moved here, though, the IPC_* macros won't
+ // compile if there are no handlers for a platform. So we have both #if guards
+ // around the whole thing (unfortunate but temporary), and #if guards where
+ // they belong, only around the one IPC handler. TODO(avi): Move more of the
+ // frame-based handlers to this function and remove the outer #if layer.
+#if defined(OS_MACOSX)
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(BrowserPluginGuest, message,
+ render_frame_host)
+#if defined(OS_MACOSX)
+ // MacOS X creates and populates platform-specific select drop-down menus
+ // whereas other platforms merely create a popup window that the guest
+ // renderer process paints inside.
+ IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
+#endif
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+#else
+ return false;
+#endif
+}
+
void BrowserPluginGuest::Attach(
+ int browser_plugin_instance_id,
WebContentsImpl* embedder_web_contents,
- const BrowserPluginHostMsg_Attach_Params& params,
- const base::DictionaryValue& extra_params) {
- if (attached())
- return;
-
- if (delegate_)
- delegate_->WillAttach(embedder_web_contents, extra_params);
+ const BrowserPluginHostMsg_Attach_Params& params) {
+ delegate_->WillAttach(embedder_web_contents, browser_plugin_instance_id);
// If a RenderView has already been created for this new window, then we need
// to initialize the browser-side state now so that the RenderFrameHostManager
// does not create a new RenderView on navigation.
if (has_render_view_) {
+ // This will trigger a callback to RenderViewReady after a round-trip IPC.
static_cast<RenderViewHostImpl*>(
GetWebContents()->GetRenderViewHost())->Init();
- WebContentsViewGuest* new_view =
+ WebContentsViewGuest* web_contents_view =
static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
- new_view->CreateViewForWidget(web_contents()->GetRenderViewHost());
+ if (!web_contents()->GetRenderViewHost()->GetView()) {
+ web_contents_view->CreateViewForWidget(
+ web_contents()->GetRenderViewHost(), true);
+ }
}
- Initialize(params, embedder_web_contents, extra_params);
+ Initialize(browser_plugin_instance_id, params, embedder_web_contents);
SendQueuedMessages();
- if (delegate_)
- delegate_->DidAttach();
+ // Create a swapped out RenderView for the guest in the embedder render
+ // process, so that the embedder can access the guest's window object.
+ // On reattachment, we can reuse the same swapped out RenderView because
+ // the embedder process will always be the same even if the embedder
+ // WebContents changes.
+ if (guest_proxy_routing_id_ == MSG_ROUTING_NONE) {
+ guest_proxy_routing_id_ =
+ GetWebContents()->CreateSwappedOutRenderView(
+ embedder_web_contents_->GetSiteInstance());
+ }
+
+ delegate_->DidAttach(guest_proxy_routing_id_);
+
+ has_render_view_ = true;
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
}
void BrowserPluginGuest::OnCompositorFrameSwappedACK(
- int instance_id,
+ int browser_plugin_instance_id,
const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
params.output_surface_id,
@@ -515,7 +562,7 @@ void BrowserPluginGuest::OnCompositorFrameSwappedACK(
params.ack);
}
-void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
+void BrowserPluginGuest::OnDragStatusUpdate(int browser_plugin_instance_id,
blink::WebDragStatus drag_status,
const DropData& drop_data,
blink::WebDragOperationsMask mask,
@@ -543,34 +590,34 @@ void BrowserPluginGuest::OnDragStatusUpdate(int instance_id,
}
}
-void BrowserPluginGuest::OnExecuteEditCommand(int instance_id,
+void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
const std::string& name) {
Send(new InputMsg_ExecuteEditCommand(routing_id(), name, std::string()));
}
void BrowserPluginGuest::OnImeSetComposition(
- int instance_id,
+ int browser_plugin_instance_id,
const std::string& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) {
- Send(new ViewMsg_ImeSetComposition(routing_id(),
- base::UTF8ToUTF16(text), underlines,
- selection_start, selection_end));
+ Send(new InputMsg_ImeSetComposition(routing_id(),
+ base::UTF8ToUTF16(text), underlines,
+ selection_start, selection_end));
}
void BrowserPluginGuest::OnImeConfirmComposition(
- int instance_id,
+ int browser_plugin_instance_id,
const std::string& text,
bool keep_selection) {
- Send(new ViewMsg_ImeConfirmComposition(routing_id(),
- base::UTF8ToUTF16(text),
- gfx::Range::InvalidRange(),
- keep_selection));
+ Send(new InputMsg_ImeConfirmComposition(routing_id(),
+ base::UTF8ToUTF16(text),
+ gfx::Range::InvalidRange(),
+ keep_selection));
}
void BrowserPluginGuest::OnExtendSelectionAndDelete(
- int instance_id,
+ int browser_plugin_instance_id,
int before,
int after) {
RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
@@ -580,7 +627,7 @@ void BrowserPluginGuest::OnExtendSelectionAndDelete(
}
void BrowserPluginGuest::OnReclaimCompositorResources(
- int instance_id,
+ int browser_plugin_instance_id,
const FrameHostMsg_ReclaimCompositorResources_Params& params) {
RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
params.output_surface_id,
@@ -588,61 +635,6 @@ void BrowserPluginGuest::OnReclaimCompositorResources(
params.ack);
}
-void BrowserPluginGuest::OnHandleInputEvent(
- int instance_id,
- const gfx::Rect& guest_window_rect,
- const blink::WebInputEvent* event) {
- guest_window_rect_ = guest_window_rect;
- // If the embedder's RWHV is destroyed then that means that the embedder's
- // window has been closed but the embedder's WebContents has not yet been
- // destroyed. Computing screen coordinates of a BrowserPlugin only makes sense
- // if there is a visible embedder.
- if (embedder_web_contents_->GetRenderWidgetHostView()) {
- guest_screen_rect_ = guest_window_rect;
- guest_screen_rect_.Offset(
- embedder_web_contents_->GetRenderWidgetHostView()->
- GetViewBounds().OffsetFromOrigin());
- }
- RenderViewHostImpl* guest_rvh = static_cast<RenderViewHostImpl*>(
- GetWebContents()->GetRenderViewHost());
-
- if (blink::WebInputEvent::isMouseEventType(event->type)) {
- guest_rvh->ForwardMouseEvent(
- *static_cast<const blink::WebMouseEvent*>(event));
- return;
- }
-
- if (event->type == blink::WebInputEvent::MouseWheel) {
- guest_rvh->ForwardWheelEvent(
- *static_cast<const blink::WebMouseWheelEvent*>(event));
- return;
- }
-
- if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
- RenderViewHostImpl* embedder_rvh = static_cast<RenderViewHostImpl*>(
- embedder_web_contents_->GetRenderViewHost());
- if (!embedder_rvh->GetLastKeyboardEvent())
- return;
- NativeWebKeyboardEvent keyboard_event(
- *embedder_rvh->GetLastKeyboardEvent());
- guest_rvh->ForwardKeyboardEvent(keyboard_event);
- return;
- }
-
- if (blink::WebInputEvent::isTouchEventType(event->type)) {
- guest_rvh->ForwardTouchEventWithLatencyInfo(
- *static_cast<const blink::WebTouchEvent*>(event),
- ui::LatencyInfo());
- return;
- }
-
- if (blink::WebInputEvent::isGestureEventType(event->type)) {
- guest_rvh->ForwardGestureEvent(
- *static_cast<const blink::WebGestureEvent*>(event));
- return;
- }
-}
-
void BrowserPluginGuest::OnLockMouse(bool user_gesture,
bool last_unlocked_by_target,
bool privileged) {
@@ -653,9 +645,6 @@ void BrowserPluginGuest::OnLockMouse(bool user_gesture,
return;
}
- if (!delegate_)
- return;
-
pending_lock_request_ = true;
delegate_->RequestPointerLockPermission(
@@ -665,113 +654,56 @@ void BrowserPluginGuest::OnLockMouse(bool user_gesture,
weak_ptr_factory_.GetWeakPtr()));
}
-void BrowserPluginGuest::OnLockMouseAck(int instance_id, bool succeeded) {
+void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
+ bool succeeded) {
Send(new ViewMsg_LockMouse_ACK(routing_id(), succeeded));
pending_lock_request_ = false;
if (succeeded)
mouse_locked_ = true;
}
-void BrowserPluginGuest::OnPluginDestroyed(int instance_id) {
- Destroy();
-}
-
void BrowserPluginGuest::OnResizeGuest(
- int instance_id,
+ int browser_plugin_instance_id,
const BrowserPluginHostMsg_ResizeGuest_Params& params) {
- if (!params.size_changed)
- return;
- // BrowserPlugin manages resize flow control itself and does not depend
- // on RenderWidgetHost's mechanisms for flow control, so we reset those flags
- // here. If we are setting the size for the first time before navigating then
+ // If we are setting the size for the first time before navigating then
// BrowserPluginGuest does not yet have a RenderViewHost.
- if (GetWebContents()->GetRenderViewHost()) {
+ if (guest_device_scale_factor_ != params.scale_factor &&
+ GetWebContents()->GetRenderViewHost()) {
RenderWidgetHostImpl* render_widget_host =
RenderWidgetHostImpl::From(GetWebContents()->GetRenderViewHost());
- render_widget_host->ResetSizeAndRepaintPendingFlags();
-
- if (guest_device_scale_factor_ != params.scale_factor) {
- guest_device_scale_factor_ = params.scale_factor;
- render_widget_host->NotifyScreenInfoChanged();
- }
+ guest_device_scale_factor_ = params.scale_factor;
+ render_widget_host->NotifyScreenInfoChanged();
}
- // When autosize is turned off and as a result there is a layout change, we
- // send a sizechanged event.
- if (!auto_size_enabled_ && last_seen_auto_size_enabled_ &&
- !params.view_size.IsEmpty() && delegate_) {
- delegate_->SizeChanged(last_seen_view_size_, params.view_size);
- last_seen_auto_size_enabled_ = false;
+
+ if (last_seen_browser_plugin_size_ != params.view_size) {
+ delegate_->ElementSizeChanged(last_seen_browser_plugin_size_,
+ params.view_size);
+ last_seen_browser_plugin_size_ = params.view_size;
}
+
// Just resize the WebContents and repaint if needed.
- full_size_ = params.view_size;
if (!params.view_size.IsEmpty())
GetWebContents()->GetView()->SizeContents(params.view_size);
if (params.repaint)
Send(new ViewMsg_Repaint(routing_id(), params.view_size));
}
-void BrowserPluginGuest::OnSetFocus(int instance_id, bool focused) {
- focused_ = focused;
- Send(new InputMsg_SetFocus(routing_id(), focused));
- if (!focused && mouse_locked_)
- OnUnlockMouse();
-
- // Restore the last seen state of text input to the view.
- RenderWidgetHostViewBase* rwhv = static_cast<RenderWidgetHostViewBase*>(
- web_contents()->GetRenderWidgetHostView());
- if (rwhv) {
- ViewHostMsg_TextInputState_Params params;
- params.type = last_text_input_type_;
- params.mode = last_input_mode_;
- params.can_compose_inline = last_can_compose_inline_;
- rwhv->TextInputStateChanged(params);
- }
-}
-
-void BrowserPluginGuest::OnSetAutoSize(
- int instance_id,
- const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
- const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params) {
- bool old_auto_size_enabled = auto_size_enabled_;
- gfx::Size old_max_size = max_auto_size_;
- gfx::Size old_min_size = min_auto_size_;
- auto_size_enabled_ = auto_size_params.enable;
- max_auto_size_ = auto_size_params.max_size;
- min_auto_size_ = auto_size_params.min_size;
- if (auto_size_enabled_ && (!old_auto_size_enabled ||
- (old_max_size != max_auto_size_) ||
- (old_min_size != min_auto_size_))) {
- RecordAction(
- base::UserMetricsAction("BrowserPlugin.Guest.EnableAutoResize"));
- GetWebContents()->GetRenderViewHost()->EnableAutoResize(
- min_auto_size_, max_auto_size_);
- // TODO(fsamuel): If we're changing autosize parameters, then we force
- // the guest to completely repaint itself.
- // Ideally, we shouldn't need to do this unless |max_auto_size_| has
- // changed.
- // However, even in that case, layout may not change and so we may
- // not get a full frame worth of pixels.
- Send(new ViewMsg_Repaint(routing_id(), max_auto_size_));
- } else if (!auto_size_enabled_ && old_auto_size_enabled) {
- GetWebContents()->GetRenderViewHost()->DisableAutoResize(
- resize_guest_params.view_size);
- }
- OnResizeGuest(instance_id_, resize_guest_params);
+void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id,
+ bool focused) {
+ RenderWidgetHostView* rwhv = web_contents()->GetRenderWidgetHostView();
+ RenderWidgetHost* rwh = rwhv ? rwhv->GetRenderWidgetHost() : NULL;
+ SetFocus(rwh, focused);
}
void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
- int instance_id,
+ int browser_plugin_instance_id,
const std::vector<EditCommand>& edit_commands) {
Send(new InputMsg_SetEditCommandsForNextKeyEvent(routing_id(),
edit_commands));
}
-void BrowserPluginGuest::OnSetContentsOpaque(int instance_id, bool opaque) {
- guest_opaque_ = opaque;
- Send(new ViewMsg_SetBackgroundOpaque(routing_id(), guest_opaque_));
-}
-
-void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
+void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
+ bool visible) {
guest_visible_ = visible;
if (embedder_visible_ && guest_visible_)
GetWebContents()->WasShown();
@@ -781,10 +713,10 @@ void BrowserPluginGuest::OnSetVisibility(int instance_id, bool visible) {
void BrowserPluginGuest::OnUnlockMouse() {
SendMessageToEmbedder(
- new BrowserPluginMsg_SetMouseLock(instance_id(), false));
+ new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), false));
}
-void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
+void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
// mouse_locked_ could be false here if the lock attempt was cancelled due
// to window focus, or for various other reasons before the guest was informed
// of the lock's success.
@@ -793,19 +725,7 @@ void BrowserPluginGuest::OnUnlockMouseAck(int instance_id) {
mouse_locked_ = false;
}
-void BrowserPluginGuest::OnCopyFromCompositingSurfaceAck(
- int instance_id,
- int request_id,
- const SkBitmap& bitmap) {
- CHECK(copy_request_callbacks_.count(request_id));
- if (!copy_request_callbacks_.count(request_id))
- return;
- const CopyRequestCallback& callback = copy_request_callbacks_[request_id];
- callback.Run(!bitmap.empty() && !bitmap.isNull(), bitmap);
- copy_request_callbacks_.erase(request_id);
-}
-
-void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
+void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id,
const gfx::Rect& view_rect) {
// The plugin has moved within the embedder without resizing or the
// embedder/container's view rect changing.
@@ -818,21 +738,18 @@ void BrowserPluginGuest::OnUpdateGeometry(int instance_id,
void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
SendMessageToEmbedder(
- new BrowserPluginMsg_ShouldAcceptTouchEvents(instance_id(), accept));
-}
-
-void BrowserPluginGuest::OnSetCursor(const WebCursor& cursor) {
- SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(instance_id(), cursor));
+ new BrowserPluginMsg_ShouldAcceptTouchEvents(
+ browser_plugin_instance_id(), accept));
}
#if defined(OS_MACOSX)
void BrowserPluginGuest::OnShowPopup(
- const ViewHostMsg_ShowPopup_Params& params) {
+ RenderFrameHost* render_frame_host,
+ const FrameHostMsg_ShowPopup_Params& params) {
gfx::Rect translated_bounds(params.bounds);
translated_bounds.Offset(guest_window_rect_.OffsetFromOrigin());
BrowserPluginPopupMenuHelper popup_menu_helper(
- embedder_web_contents_->GetRenderViewHost(),
- GetWebContents()->GetRenderViewHost());
+ embedder_web_contents_->GetRenderViewHost(), render_frame_host);
popup_menu_helper.ShowPopupMenu(translated_bounds,
params.item_height,
params.item_font_size,
@@ -850,40 +767,22 @@ void BrowserPluginGuest::OnShowWidget(int route_id,
void BrowserPluginGuest::OnTakeFocus(bool reverse) {
SendMessageToEmbedder(
- new BrowserPluginMsg_AdvanceFocus(instance_id(), reverse));
-}
-
-void BrowserPluginGuest::OnUpdateRect(
- const ViewHostMsg_UpdateRect_Params& params) {
- BrowserPluginMsg_UpdateRect_Params relay_params;
- relay_params.view_size = params.view_size;
- relay_params.scale_factor = params.scale_factor;
- relay_params.is_resize_ack = ViewHostMsg_UpdateRect_Flags::is_resize_ack(
- params.flags);
-
- bool size_changed = last_seen_view_size_ != params.view_size;
- gfx::Size old_size = last_seen_view_size_;
- last_seen_view_size_ = params.view_size;
-
- if ((auto_size_enabled_ || last_seen_auto_size_enabled_) &&
- size_changed && delegate_) {
- delegate_->SizeChanged(old_size, last_seen_view_size_);
- }
- last_seen_auto_size_enabled_ = auto_size_enabled_;
-
- SendMessageToEmbedder(
- new BrowserPluginMsg_UpdateRect(instance_id(), relay_params));
+ new BrowserPluginMsg_AdvanceFocus(browser_plugin_instance_id(), reverse));
}
-void BrowserPluginGuest::OnTextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) {
+void BrowserPluginGuest::OnTextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
// Save the state of text input so we can restore it on focus.
- last_text_input_type_ = params.type;
- last_input_mode_ = params.mode;
- last_can_compose_inline_ = params.can_compose_inline;
+ last_text_input_type_ = type;
+ last_input_mode_ = input_mode;
+ last_input_flags_ = flags;
+ last_can_compose_inline_ = can_compose_inline;
static_cast<RenderWidgetHostViewBase*>(
- web_contents()->GetRenderWidgetHostView())->TextInputStateChanged(params);
+ web_contents()->GetRenderWidgetHostView())->TextInputTypeChanged(
+ type, input_mode, can_compose_inline, flags);
}
void BrowserPluginGuest::OnImeCancelComposition() {
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index d1bd4ba36c7..cb1ba7eef8e 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -38,32 +38,33 @@
#include "ui/gfx/rect.h"
class SkBitmap;
-struct BrowserPluginHostMsg_AutoSize_Params;
struct BrowserPluginHostMsg_Attach_Params;
struct BrowserPluginHostMsg_ResizeGuest_Params;
struct FrameHostMsg_CompositorFrameSwappedACK_Params;
struct FrameHostMsg_ReclaimCompositorResources_Params;
#if defined(OS_MACOSX)
-struct ViewHostMsg_ShowPopup_Params;
+struct FrameHostMsg_ShowPopup_Params;
#endif
-struct ViewHostMsg_TextInputState_Params;
-struct ViewHostMsg_UpdateRect_Params;
namespace blink {
class WebInputEvent;
-}
+} // namespace blink
+
+namespace cc {
+class CompositorFrame;
+} // namespace cc
namespace gfx {
class Range;
-}
+} // namespace gfx
namespace content {
class BrowserPluginGuestManager;
class RenderViewHostImpl;
+class RenderWidgetHost;
class RenderWidgetHostView;
class SiteInstance;
-class WebCursor;
struct DropData;
// A browser plugin guest provides functionality for WebContents to operate in
@@ -78,7 +79,7 @@ struct DropData;
// which means it can share storage and can script this guest.
class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
public:
- virtual ~BrowserPluginGuest();
+ ~BrowserPluginGuest() override;
// The WebContents passed into the factory method here has not been
// initialized yet and so it does not yet hold a SiteInstance.
@@ -87,12 +88,8 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
// type of WebContentsView to construct on initialization. The content
// embedder needs to be aware of |guest_site_instance| on the guest's
// construction and so we pass it in here.
- static BrowserPluginGuest* Create(
- int instance_id,
- SiteInstance* guest_site_instance,
- WebContentsImpl* web_contents,
- scoped_ptr<base::DictionaryValue> extra_params,
- BrowserPluginGuest* opener);
+ static BrowserPluginGuest* Create(WebContentsImpl* web_contents,
+ BrowserPluginGuestDelegate* delegate);
// Returns whether the given WebContents is a BrowserPlugin guest.
static bool IsGuest(WebContentsImpl* web_contents);
@@ -103,20 +100,30 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
// Returns a WeakPtr to this BrowserPluginGuest.
base::WeakPtr<BrowserPluginGuest> AsWeakPtr();
+ // Sets the focus state of the current RenderWidgetHostView.
+ void SetFocus(RenderWidgetHost* rwh, bool focused);
+
+ // Sets the tooltip text.
+ void SetTooltipText(const base::string16& tooltip_text);
+
// Sets the lock state of the pointer. Returns true if |allowed| is true and
// the mouse has been successfully locked.
bool LockMouse(bool allowed);
+ // Return true if the mouse is locked.
+ bool mouse_locked() const { return mouse_locked_; }
+
// Called when the embedder WebContents changes visibility.
void EmbedderVisibilityChanged(bool visible);
- // Destroys the guest WebContents and all its associated state, including
- // this BrowserPluginGuest, and its new unattached windows.
- void Destroy();
+ // Creates a new guest WebContentsImpl with the provided |params| with |this|
+ // as the |opener|.
+ WebContentsImpl* CreateNewGuestWindow(
+ const WebContents::CreateParams& params);
// Returns the identifier that uniquely identifies a browser plugin guest
// within an embedder.
- int instance_id() const { return instance_id_; }
+ int browser_plugin_instance_id() const { return browser_plugin_instance_id_; }
bool OnMessageReceivedFromEmbedder(const IPC::Message& message);
@@ -132,30 +139,21 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
bool visible() const { return guest_visible_; }
bool is_in_destruction() { return is_in_destruction_; }
- // Returns the BrowserPluginGuest that created this guest, if any.
- BrowserPluginGuest* GetOpener() const;
-
void UpdateVisibility();
- void CopyFromCompositingSurface(
- gfx::Rect src_subrect,
- gfx::Size dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback);
-
BrowserPluginGuestManager* GetBrowserPluginGuestManager() const;
// WebContentsObserver implementation.
- virtual void DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ void DidCommitProvisionalLoadForFrame(
+ RenderFrameHost* render_frame_host,
const GURL& url,
- PageTransition transition_type,
- RenderViewHost* render_view_host) OVERRIDE;
+ ui::PageTransition transition_type) override;
- virtual void RenderViewReady() OVERRIDE;
- virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void RenderViewReady() override;
+ void RenderProcessGone(base::TerminationStatus status) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) override;
// Exposes the protected web_contents() from WebContentsObserver.
WebContentsImpl* GetWebContents() const;
@@ -172,17 +170,14 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
// Attaches this BrowserPluginGuest to the provided |embedder_web_contents|
// and initializes the guest with the provided |params|. Attaching a guest
// to an embedder implies that this guest's lifetime is no longer managed
- // by its opener, and it can begin loading resources. |extra_params| are
- // parameters passed into BrowserPlugin from JavaScript to be forwarded to
- // the content embedder.
- void Attach(WebContentsImpl* embedder_web_contents,
- const BrowserPluginHostMsg_Attach_Params& params,
- const base::DictionaryValue& extra_params);
+ // by its opener, and it can begin loading resources.
+ void Attach(int browser_plugin_instance_id,
+ WebContentsImpl* embedder_web_contents,
+ const BrowserPluginHostMsg_Attach_Params& params);
// Returns whether BrowserPluginGuest is interested in receiving the given
// |message|.
static bool ShouldForwardToBrowserPluginGuest(const IPC::Message& message);
- gfx::Rect ToGuestRect(const gfx::Rect& rect);
void DragSourceEndedAt(int client_x, int client_y, int screen_x,
int screen_y, blink::WebDragOperation operation);
@@ -190,42 +185,47 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
// Called when the drag started by this guest ends at an OS-level.
void EndSystemDrag();
- void set_delegate(BrowserPluginGuestDelegate* delegate) {
- DCHECK(!delegate_);
- delegate_ = delegate;
- }
-
void RespondToPermissionRequest(int request_id,
bool should_allow,
const std::string& user_input);
void PointerLockPermissionResponse(bool allow);
+ void SwapCompositorFrame(uint32 output_surface_id,
+ int host_process_id,
+ int host_routing_id,
+ scoped_ptr<cc::CompositorFrame> frame);
+
+ void SetContentsOpaque(bool opaque);
+
+ // Find the given |search_text| in the page. Returns true if the find request
+ // is handled by this browser plugin guest.
+ bool Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options);
+
private:
class EmbedderWebContentsObserver;
// BrowserPluginGuest is a WebContentsObserver of |web_contents| and
// |web_contents| has to stay valid for the lifetime of BrowserPluginGuest.
- BrowserPluginGuest(int instance_id,
- bool has_render_view,
- WebContentsImpl* web_contents);
+ BrowserPluginGuest(bool has_render_view,
+ WebContentsImpl* web_contents,
+ BrowserPluginGuestDelegate* delegate);
void WillDestroy();
- void Initialize(const BrowserPluginHostMsg_Attach_Params& params,
- WebContentsImpl* embedder_web_contents,
- const base::DictionaryValue& extra_params);
+ void Initialize(int browser_plugin_instance_id,
+ const BrowserPluginHostMsg_Attach_Params& params,
+ WebContentsImpl* embedder_web_contents);
bool InAutoSizeBounds(const gfx::Size& size) const;
// Message handlers for messages from embedder.
-
void OnCompositorFrameSwappedACK(
int instance_id,
const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
- void OnCopyFromCompositingSurfaceAck(int instance_id,
- int request_id,
- const SkBitmap& bitmap);
+
// Handles drag events from the embedder.
// When dragging, the drag events go to the embedder first, and if the drag
// happens on the browser plugin, then the plugin sends a corresponding
@@ -245,14 +245,10 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
int instance_id,
const FrameHostMsg_ReclaimCompositorResources_Params& params);
- void OnHandleInputEvent(int instance_id,
- const gfx::Rect& guest_window_rect,
- const blink::WebInputEvent* event);
void OnLockMouse(bool user_gesture,
bool last_unlocked_by_target,
bool privileged);
void OnLockMouseAck(int instance_id, bool succeeded);
- void OnPluginDestroyed(int instance_id);
// Resizes the guest's web contents.
void OnResizeGuest(
int instance_id, const BrowserPluginHostMsg_ResizeGuest_Params& params);
@@ -261,14 +257,9 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
// access it.
void OnSetName(int instance_id, const std::string& name);
// Updates the size state of the guest.
- void OnSetAutoSize(
- int instance_id,
- const BrowserPluginHostMsg_AutoSize_Params& auto_size_params,
- const BrowserPluginHostMsg_ResizeGuest_Params& resize_guest_params);
void OnSetEditCommandsForNextKeyEvent(
int instance_id,
const std::vector<EditCommand>& edit_commands);
- void OnSetContentsOpaque(int instance_id, bool opaque);
// The guest WebContents is visible if both its embedder is visible and
// the browser plugin element is visible. If either one is not then the
// WebContents is marked as hidden. A hidden WebContents will consume
@@ -289,9 +280,10 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
void OnUnlockMouseAck(int instance_id);
void OnUpdateGeometry(int instance_id, const gfx::Rect& view_rect);
- void OnTextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params);
-
+ void OnTextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags);
void OnImeSetComposition(
int instance_id,
const std::string& text,
@@ -311,55 +303,42 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
#endif
// Message handlers for messages from guest.
-
- void OnDragStopped();
void OnHandleInputEventAck(
blink::WebInputEvent::Type event_type,
InputEventAckState ack_result);
void OnHasTouchEventHandlers(bool accept);
- void OnSetCursor(const WebCursor& cursor);
- // On MacOSX popups are painted by the browser process. We handle them here
- // so that they are positioned correctly.
#if defined(OS_MACOSX)
- void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
+ // On MacOS X popups are painted by the browser process. We handle them here
+ // so that they are positioned correctly.
+ void OnShowPopup(RenderFrameHost* render_frame_host,
+ const FrameHostMsg_ShowPopup_Params& params);
#endif
void OnShowWidget(int route_id, const gfx::Rect& initial_pos);
void OnTakeFocus(bool reverse);
void OnUpdateFrameName(int frame_id,
bool is_top_level,
const std::string& name);
- void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
// Forwards all messages from the |pending_messages_| queue to the embedder.
void SendQueuedMessages();
+ // The last tooltip that was set with SetTooltipText().
+ base::string16 current_tooltip_text_;
+
scoped_ptr<EmbedderWebContentsObserver> embedder_web_contents_observer_;
WebContentsImpl* embedder_web_contents_;
- // An identifier that uniquely identifies a browser plugin guest within an
- // embedder.
- int instance_id_;
+ // An identifier that uniquely identifies a browser plugin within an embedder.
+ int browser_plugin_instance_id_;
float guest_device_scale_factor_;
gfx::Rect guest_window_rect_;
- gfx::Rect guest_screen_rect_;
bool focused_;
bool mouse_locked_;
bool pending_lock_request_;
bool guest_visible_;
- bool guest_opaque_;
bool embedder_visible_;
- std::string name_;
- bool auto_size_enabled_;
- gfx::Size max_auto_size_;
- gfx::Size min_auto_size_;
- gfx::Size full_size_;
-
- // Each copy-request is identified by a unique number. The unique number is
- // used to keep track of the right callback.
- int copy_request_id_;
- typedef base::Callback<void(bool, const SkBitmap&)> CopyRequestCallback;
- typedef std::map<int, const CopyRequestCallback> CopyRequestMap;
- CopyRequestMap copy_request_callbacks_;
+ // Whether the browser plugin is inside a plugin document.
+ bool is_full_page_plugin_;
// Indicates that this BrowserPluginGuest has associated renderer-side state.
// This is used to determine whether or not to create a new RenderView when
@@ -368,23 +347,28 @@ class CONTENT_EXPORT BrowserPluginGuest : public WebContentsObserver {
// maintains a JavaScript reference to its opener.
bool has_render_view_;
- // Last seen size of guest contents (by OnUpdateRect).
+ // Last seen size of guest contents (by SwapCompositorFrame).
gfx::Size last_seen_view_size_;
- // Last seen autosize attribute state (by OnUpdateRect).
- bool last_seen_auto_size_enabled_;
+ // Last seen size of BrowserPlugin (by OnResizeGuest).
+ gfx::Size last_seen_browser_plugin_size_;
bool is_in_destruction_;
// Text input type states.
ui::TextInputType last_text_input_type_;
ui::TextInputMode last_input_mode_;
+ int last_input_flags_;
bool last_can_compose_inline_;
+ // The is the routing ID for a swapped out RenderView for the guest
+ // WebContents in the embedder's process.
+ int guest_proxy_routing_id_;
+
// This is a queue of messages that are destined to be sent to the embedder
// once the guest is attached to a particular embedder.
std::deque<linked_ptr<IPC::Message> > pending_messages_;
- BrowserPluginGuestDelegate* delegate_;
+ BrowserPluginGuestDelegate* const delegate_;
// Weak pointer used to ask GeolocationPermissionContext about geolocation
// permission.
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc
index e82fb7a031a..c39476d2fbc 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.cc
@@ -10,7 +10,6 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/browser_plugin/browser_plugin_constants.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
@@ -39,14 +38,7 @@ bool BrowserPluginMessageFilter::OnMessageReceived(
// thread.
return true;
}
- bool handled = true;
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- IPC_BEGIN_MESSAGE_MAP(BrowserPluginMessageFilter, message)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_BuffersSwappedACK,
- OnSwapBuffersACK)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
+ return false;
}
void BrowserPluginMessageFilter::OnDestruct() const {
@@ -59,45 +51,32 @@ void BrowserPluginMessageFilter::OverrideThreadForMessage(
*thread = BrowserThread::UI;
}
-static void BrowserPluginGuestMessageCallback(const IPC::Message& message,
- WebContents* guest_web_contents) {
- if (!guest_web_contents)
- return;
- static_cast<WebContentsImpl*>(guest_web_contents)->GetBrowserPluginGuest()->
- OnMessageReceivedFromEmbedder(message);
-}
-
void BrowserPluginMessageFilter::ForwardMessageToGuest(
const IPC::Message& message) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
- RenderProcessHost::FromID(render_process_id_));
- if (!host)
+ RenderViewHost* rvh = RenderViewHost::FromID(render_process_id_,
+ message.routing_id());
+ if (!rvh)
return;
- int instance_id = 0;
+ WebContents* embedder_web_contents = WebContents::FromRenderViewHost(rvh);
+
+ int browser_plugin_instance_id = 0;
// All allowed messages must have instance_id as their first parameter.
PickleIterator iter(message);
- bool success = iter.ReadInt(&instance_id);
+ bool success = iter.ReadInt(&browser_plugin_instance_id);
DCHECK(success);
- host->GetBrowserContext()->GetGuestManager()->
- MaybeGetGuestByInstanceIDOrKill(
- instance_id,
- render_process_id_,
- base::Bind(&BrowserPluginGuestMessageCallback,
- message));
-}
-
-void BrowserPluginMessageFilter::OnSwapBuffersACK(
- const FrameHostMsg_BuffersSwappedACK_Params& params) {
- GpuProcessHost* gpu_host = GpuProcessHost::FromID(params.gpu_host_id);
- if (!gpu_host)
+ WebContents* guest_web_contents =
+ embedder_web_contents->GetBrowserContext()
+ ->GetGuestManager()
+ ->GetGuestByInstanceID(embedder_web_contents,
+ browser_plugin_instance_id);
+ if (!guest_web_contents)
return;
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.mailbox = params.mailbox;
- ack_params.sync_point = params.sync_point;
- gpu_host->Send(new AcceleratedSurfaceMsg_BufferPresented(params.gpu_route_id,
- ack_params));
+
+ static_cast<WebContentsImpl*>(guest_web_contents)
+ ->GetBrowserPluginGuest()
+ ->OnMessageReceivedFromEmbedder(message);
}
} // namespace content
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h
index 136c6cc58e6..672f6de51b6 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_message_filter.h
@@ -20,22 +20,19 @@ class BrowserPluginMessageFilter : public BrowserMessageFilter {
BrowserPluginMessageFilter(int render_process_id);
// BrowserMessageFilter implementation.
- virtual void OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() const override;
private:
friend class BrowserThread;
friend class base::DeleteHelper<BrowserPluginMessageFilter>;
- virtual ~BrowserPluginMessageFilter();
+ ~BrowserPluginMessageFilter() override;
void ForwardMessageToGuest(const IPC::Message& message);
- void OnSwapBuffersACK(const FrameHostMsg_BuffersSwappedACK_Params& params);
-
int render_process_id_;
DISALLOW_COPY_AND_ASSIGN(BrowserPluginMessageFilter);
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h b/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h
index 2b462371001..31c198031b1 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h
@@ -5,24 +5,27 @@
#ifndef CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_POPUP_MENU_HELPER_MAC_H_
#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_POPUP_MENU_HELPER_MAC_H_
-#include "content/browser/renderer_host/popup_menu_helper_mac.h"
+#include "content/browser/frame_host/popup_menu_helper_mac.h"
namespace content {
+
class RenderViewHost;
class RenderViewHostImpl;
+class RenderFrameHost;
+class RenderFrameHostImpl;
// This class is similiar to PopupMenuHelperMac but positions the popup relative
// to the embedder, and issues a reply to the guest.
class BrowserPluginPopupMenuHelper : public PopupMenuHelper {
public:
// Creates a BrowserPluginPopupMenuHelper that positions popups relative to
- // |embedder_rvh| and will notify |guest_rvh| when a user selects or cancels
+ // |embedder_rvh| and will notify |guest_rfh| when a user selects or cancels
// the popup.
BrowserPluginPopupMenuHelper(RenderViewHost* embedder_rvh,
- RenderViewHost* guest_rvh);
+ RenderFrameHost* guest_rfh);
private:
- virtual RenderWidgetHostViewMac* GetRenderWidgetHostView() const OVERRIDE;
+ RenderWidgetHostViewMac* GetRenderWidgetHostView() const override;
RenderViewHostImpl* embedder_rvh_;
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.mm b/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.mm
index e2b5da55c00..413c96fd16b 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.mm
+++ b/chromium/content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.mm
@@ -4,14 +4,15 @@
#include "content/browser/browser_plugin/browser_plugin_popup_menu_helper_mac.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
namespace content {
BrowserPluginPopupMenuHelper::BrowserPluginPopupMenuHelper(
- RenderViewHost* embedder_rvh, RenderViewHost* guest_rvh)
- : PopupMenuHelper(guest_rvh),
+ RenderViewHost* embedder_rvh, RenderFrameHost* guest_rfh)
+ : PopupMenuHelper(guest_rfh),
embedder_rvh_(static_cast<RenderViewHostImpl*>(embedder_rvh)) {
}
diff --git a/chromium/content/browser/browser_process_sub_thread.h b/chromium/content/browser/browser_process_sub_thread.h
index e006388783b..5899fa31906 100644
--- a/chromium/content/browser/browser_process_sub_thread.h
+++ b/chromium/content/browser/browser_process_sub_thread.h
@@ -35,11 +35,11 @@ namespace content {
class CONTENT_EXPORT BrowserProcessSubThread : public BrowserThreadImpl {
public:
explicit BrowserProcessSubThread(BrowserThread::ID identifier);
- virtual ~BrowserProcessSubThread();
+ ~BrowserProcessSubThread() override;
protected:
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void CleanUp() override;
private:
// These methods encapsulate cleanup that needs to happen on the IO thread
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.cc b/chromium/content/browser/browser_shutdown_profile_dumper.cc
index 3e74e063b0c..c2533a09604 100644
--- a/chromium/content/browser/browser_shutdown_profile_dumper.cc
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.cc
@@ -8,8 +8,8 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_impl.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
@@ -18,17 +18,18 @@
namespace content {
-BrowserShutdownProfileDumper::BrowserShutdownProfileDumper()
- : blocks_(0),
+BrowserShutdownProfileDumper::BrowserShutdownProfileDumper(
+ const base::FilePath& dump_file_name)
+ : dump_file_name_(dump_file_name),
+ blocks_(0),
dump_file_(NULL) {
}
BrowserShutdownProfileDumper::~BrowserShutdownProfileDumper() {
- WriteTracesToDisc(GetFileName());
+ WriteTracesToDisc();
}
-void BrowserShutdownProfileDumper::WriteTracesToDisc(
- const base::FilePath& file_name) {
+void BrowserShutdownProfileDumper::WriteTracesToDisc() {
// Note: I have seen a usage of 0.000xx% when dumping - which fits easily.
// Since the tracer stops when the trace buffer is filled, we'd rather save
// what we have than nothing since we might see from the amount of events
@@ -37,10 +38,10 @@ void BrowserShutdownProfileDumper::WriteTracesToDisc(
base::debug::TraceLog::GetInstance()->GetBufferPercentFull() <<
" full.";
DCHECK(!dump_file_);
- dump_file_ = base::OpenFile(file_name, "w+");
+ dump_file_ = base::OpenFile(dump_file_name_, "w+");
if (!IsFileValid()) {
- LOG(ERROR) << "Failed to open performance trace file: " <<
- file_name.value();
+ LOG(ERROR) << "Failed to open performance trace file: "
+ << dump_file_name_.value();
return;
}
WriteString("{\"traceEvents\":");
@@ -72,8 +73,10 @@ void BrowserShutdownProfileDumper::EndTraceAndFlush(
base::Unretained(flush_complete_event)));
}
-base::FilePath BrowserShutdownProfileDumper::GetFileName() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+// static
+base::FilePath BrowserShutdownProfileDumper::GetShutdownProfileFileName() {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
base::FilePath trace_file =
command_line.GetSwitchValuePath(switches::kTraceShutdownFile);
@@ -122,8 +125,9 @@ void BrowserShutdownProfileDumper::WriteChars(const char* chars, size_t size) {
size_t written = fwrite(chars, 1, size, dump_file_);
if (written != size) {
- LOG(ERROR) << "Error " << ferror(dump_file_) <<
- " in fwrite() to trace file";
+ LOG(ERROR) << "Error " << ferror(dump_file_)
+ << " in fwrite() to trace file '" << dump_file_name_.value()
+ << "'";
CloseFile();
}
}
diff --git a/chromium/content/browser/browser_shutdown_profile_dumper.h b/chromium/content/browser/browser_shutdown_profile_dumper.h
index f98a32cb9ca..cc8666ef69d 100644
--- a/chromium/content/browser/browser_shutdown_profile_dumper.h
+++ b/chromium/content/browser/browser_shutdown_profile_dumper.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "content/common/content_export.h"
@@ -29,19 +30,19 @@ namespace content {
// |SequencedWorkerPool| will get killed in the shutdown process.
class BrowserShutdownProfileDumper {
public:
- BrowserShutdownProfileDumper();
+ explicit BrowserShutdownProfileDumper(const base::FilePath& dump_file_name);
~BrowserShutdownProfileDumper();
+ // Returns the file name where we should save the shutdown trace dump to.
+ static base::FilePath GetShutdownProfileFileName();
+
private:
// Writes all traces which happened to disk.
- void WriteTracesToDisc(const base::FilePath& file_name);
+ void WriteTracesToDisc();
void EndTraceAndFlush(base::WaitableEvent* flush_complete_event);
- // Returns the file name where we should save the trace dump to.
- base::FilePath GetFileName();
-
// The callback for the |TraceLog::Flush| function. It saves all traces to
// disc.
void WriteTraceDataCollected(
@@ -61,6 +62,9 @@ class BrowserShutdownProfileDumper {
// Closes the dump file.
void CloseFile();
+ // The name of the dump file.
+ const base::FilePath dump_file_name_;
+
// The number of blocks we have already written.
int blocks_;
// For dumping the content to disc.
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index 641056ffb78..33bfeb951e5 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -15,6 +15,7 @@
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread_delegate.h"
+#include "net/disk_cache/simple/simple_backend_impl.h"
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
@@ -44,26 +45,25 @@ class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
}
// MessageLoopProxy implementation.
- virtual bool PostDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task, base::TimeDelta delay) OVERRIDE {
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override {
return BrowserThread::PostDelayedTask(id_, from_here, task, delay);
}
- virtual bool PostNonNestableDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task,
- base::TimeDelta delay) OVERRIDE {
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override {
return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
delay);
}
- virtual bool RunsTasksOnCurrentThread() const OVERRIDE {
+ bool RunsTasksOnCurrentThread() const override {
return BrowserThread::CurrentlyOn(id_);
}
protected:
- virtual ~BrowserThreadMessageLoopProxy() {}
+ ~BrowserThreadMessageLoopProxy() override {}
private:
BrowserThread::ID id_;
@@ -141,11 +141,12 @@ void BrowserThreadImpl::ShutdownThreadPool() {
}
// static
-void BrowserThreadImpl::FlushThreadPoolHelper() {
+void BrowserThreadImpl::FlushThreadPoolHelperForTesting() {
// We don't want to create a pool if none exists.
if (g_globals == NULL)
return;
g_globals.Get().blocking_pool->FlushForTesting();
+ disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
}
void BrowserThreadImpl::Init() {
diff --git a/chromium/content/browser/browser_thread_impl.h b/chromium/content/browser/browser_thread_impl.h
index 167cc3b85a1..72915ea393f 100644
--- a/chromium/content/browser/browser_thread_impl.h
+++ b/chromium/content/browser/browser_thread_impl.h
@@ -23,14 +23,14 @@ class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread,
// thread already exists.
BrowserThreadImpl(BrowserThread::ID identifier,
base::MessageLoop* message_loop);
- virtual ~BrowserThreadImpl();
+ ~BrowserThreadImpl() override;
static void ShutdownThreadPool();
protected:
- virtual void Init() OVERRIDE;
- virtual void Run(base::MessageLoop* message_loop) OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void Run(base::MessageLoop* message_loop) override;
+ void CleanUp() override;
private:
// We implement all the functionality of the public BrowserThread
@@ -61,7 +61,7 @@ class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread,
// For testing.
friend class ContentTestSuiteBaseListener;
friend class TestBrowserThreadBundle;
- static void FlushThreadPoolHelper();
+ static void FlushThreadPoolHelperForTesting();
// The identifier of this thread. Only one thread can exist with a given
// identifier at a given time.
diff --git a/chromium/content/browser/browser_thread_unittest.cc b/chromium/content/browser/browser_thread_unittest.cc
index 4083b782caf..3f1f8cdd2ee 100644
--- a/chromium/content/browser/browser_thread_unittest.cc
+++ b/chromium/content/browser/browser_thread_unittest.cc
@@ -23,14 +23,14 @@ class BrowserThreadTest : public testing::Test {
}
protected:
- virtual void SetUp() {
+ void SetUp() override {
ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI));
file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE));
ui_thread_->Start();
file_thread_->Start();
}
- virtual void TearDown() {
+ void TearDown() override {
ui_thread_->Stop();
file_thread_->Stop();
}
diff --git a/chromium/content/browser/browser_url_handler_impl.cc b/chromium/content/browser/browser_url_handler_impl.cc
index 1b7050f8ddf..7ea7ff787b9 100644
--- a/chromium/content/browser/browser_url_handler_impl.cc
+++ b/chromium/content/browser/browser_url_handler_impl.cc
@@ -4,9 +4,7 @@
#include "content/browser/browser_url_handler_impl.h"
-#include "base/command_line.h"
#include "base/strings/string_util.h"
-#include "cc/base/switches.h"
#include "content/browser/frame_host/debug_urls.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/public/browser/content_browser_client.h"
@@ -64,27 +62,12 @@ static bool ReverseViewSource(GURL* url, BrowserContext* browser_context) {
// No action necessary if the URL is already view-source:
if (url->SchemeIs(kViewSourceScheme))
return false;
-
- url::Replacements<char> repl;
- repl.SetScheme(kViewSourceScheme,
- url::Component(0, strlen(kViewSourceScheme)));
- repl.SetPath(url->spec().c_str(), url::Component(0, url->spec().size()));
- *url = url->ReplaceComponents(repl);
+ // Recreate the url with the view-source scheme.
+ *url = GURL(kViewSourceScheme + std::string(":") + url->spec());
return true;
}
static bool DebugURLHandler(GURL* url, BrowserContext* browser_context) {
- // If running inside the Telemetry test harness, allow automated
- // navigations to access browser-side debug URLs. They must use the
- // chrome:// scheme, since the about: scheme won't be rewritten in
- // this code path.
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kEnableGpuBenchmarking)) {
- if (HandleDebugURL(*url, PAGE_TRANSITION_FROM_ADDRESS_BAR)) {
- return true;
- }
- }
-
// Circumvent processing URLs that the renderer process will handle.
return IsRendererDebugURL(*url);
}
diff --git a/chromium/content/browser/browser_url_handler_impl.h b/chromium/content/browser/browser_url_handler_impl.h
index d0a150452ba..240554b7681 100644
--- a/chromium/content/browser/browser_url_handler_impl.h
+++ b/chromium/content/browser/browser_url_handler_impl.h
@@ -23,12 +23,11 @@ class CONTENT_EXPORT BrowserURLHandlerImpl : public BrowserURLHandler {
static BrowserURLHandlerImpl* GetInstance();
// BrowserURLHandler implementation:
- virtual void RewriteURLIfNecessary(GURL* url,
- BrowserContext* browser_context,
- bool* reverse_on_redirect) OVERRIDE;
+ void RewriteURLIfNecessary(GURL* url,
+ BrowserContext* browser_context,
+ bool* reverse_on_redirect) override;
// Add the specified handler pair to the list of URL handlers.
- virtual void AddHandlerPair(URLHandler handler,
- URLHandler reverse_handler) OVERRIDE;
+ void AddHandlerPair(URLHandler handler, URLHandler reverse_handler) override;
// Reverses the rewriting that was done for |original| using the new |url|.
bool ReverseURLRewrite(GURL* url, const GURL& original,
@@ -37,7 +36,7 @@ class CONTENT_EXPORT BrowserURLHandlerImpl : public BrowserURLHandler {
private:
// This object is a singleton:
BrowserURLHandlerImpl();
- virtual ~BrowserURLHandlerImpl();
+ ~BrowserURLHandlerImpl() override;
friend struct DefaultSingletonTraits<BrowserURLHandlerImpl>;
// The list of known URLHandlers, optionally with reverse-rewriters.
@@ -46,6 +45,7 @@ class CONTENT_EXPORT BrowserURLHandlerImpl : public BrowserURLHandler {
FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, BasicRewriteAndReverse);
FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, NullHandlerReverse);
+ FRIEND_TEST_ALL_PREFIXES(BrowserURLHandlerImplTest, ViewSourceReverse);
DISALLOW_COPY_AND_ASSIGN(BrowserURLHandlerImpl);
};
diff --git a/chromium/content/browser/browser_url_handler_impl_unittest.cc b/chromium/content/browser/browser_url_handler_impl_unittest.cc
index 4e8dc2115fd..daceffcee47 100644
--- a/chromium/content/browser/browser_url_handler_impl_unittest.cc
+++ b/chromium/content/browser/browser_url_handler_impl_unittest.cc
@@ -79,4 +79,19 @@ TEST_F(BrowserURLHandlerImplTest, NullHandlerReverse) {
ASSERT_EQ("foo://foo", url.spec());
}
+// Verify that the reverse handler for view-source does not duplicate query
+// parameters.
+TEST_F(BrowserURLHandlerImplTest, ViewSourceReverse) {
+ TestBrowserContext browser_context;
+ BrowserURLHandlerImpl handler;
+
+ GURL url("http://foo/?a=1");
+ GURL original_url("view-source:http://some_url");
+ bool reversed = handler.ReverseURLRewrite(&url,
+ original_url,
+ &browser_context);
+ ASSERT_TRUE(reversed);
+ ASSERT_EQ("view-source:http://foo/?a=1", url.spec());
+}
+
} // namespace content
diff --git a/chromium/content/browser/byte_stream.cc b/chromium/content/browser/byte_stream.cc
index 0cd3cd8c1b2..5c836bd6a0a 100644
--- a/chromium/content/browser/byte_stream.cc
+++ b/chromium/content/browser/byte_stream.cc
@@ -48,7 +48,7 @@ class ByteStreamWriterImpl : public ByteStreamWriter {
ByteStreamWriterImpl(scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<LifetimeFlag> lifetime_flag,
size_t buffer_size);
- virtual ~ByteStreamWriterImpl();
+ ~ByteStreamWriterImpl() override;
// Must be called before any operations are performed.
void SetPeer(ByteStreamReaderImpl* peer,
@@ -56,12 +56,11 @@ class ByteStreamWriterImpl : public ByteStreamWriter {
scoped_refptr<LifetimeFlag> peer_lifetime_flag);
// Overridden from ByteStreamWriter.
- virtual bool Write(scoped_refptr<net::IOBuffer> buffer,
- size_t byte_count) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Close(int status) OVERRIDE;
- virtual void RegisterCallback(const base::Closure& source_callback) OVERRIDE;
- virtual size_t GetTotalBufferedBytes() const OVERRIDE;
+ bool Write(scoped_refptr<net::IOBuffer> buffer, size_t byte_count) override;
+ void Flush() override;
+ void Close(int status) override;
+ void RegisterCallback(const base::Closure& source_callback) override;
+ size_t GetTotalBufferedBytes() const override;
// PostTask target from |ByteStreamReaderImpl::MaybeUpdateInput|.
static void UpdateWindow(scoped_refptr<LifetimeFlag> lifetime_flag,
@@ -108,7 +107,7 @@ class ByteStreamReaderImpl : public ByteStreamReader {
ByteStreamReaderImpl(scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<LifetimeFlag> lifetime_flag,
size_t buffer_size);
- virtual ~ByteStreamReaderImpl();
+ ~ByteStreamReaderImpl() override;
// Must be called before any operations are performed.
void SetPeer(ByteStreamWriterImpl* peer,
@@ -116,10 +115,9 @@ class ByteStreamReaderImpl : public ByteStreamReader {
scoped_refptr<LifetimeFlag> peer_lifetime_flag);
// Overridden from ByteStreamReader.
- virtual StreamState Read(scoped_refptr<net::IOBuffer>* data,
- size_t* length) OVERRIDE;
- virtual int GetStatus() const OVERRIDE;
- virtual void RegisterCallback(const base::Closure& sink_callback) OVERRIDE;
+ StreamState Read(scoped_refptr<net::IOBuffer>* data, size_t* length) override;
+ int GetStatus() const override;
+ void RegisterCallback(const base::Closure& sink_callback) override;
// PostTask target from |ByteStreamWriterImpl::Write| and
// |ByteStreamWriterImpl::Close|.
diff --git a/chromium/content/browser/cert_store_impl.h b/chromium/content/browser/cert_store_impl.h
index cba87207d27..d8b689c17b0 100644
--- a/chromium/content/browser/cert_store_impl.h
+++ b/chromium/content/browser/cert_store_impl.h
@@ -18,14 +18,14 @@ class CertStoreImpl : public CertStore {
static CertStoreImpl* GetInstance();
// CertStore implementation:
- virtual int StoreCert(net::X509Certificate* cert,
- int render_process_host_id) OVERRIDE;
- virtual bool RetrieveCert(int cert_id,
- scoped_refptr<net::X509Certificate>* cert) OVERRIDE;
+ int StoreCert(net::X509Certificate* cert,
+ int render_process_host_id) override;
+ bool RetrieveCert(int cert_id,
+ scoped_refptr<net::X509Certificate>* cert) override;
protected:
CertStoreImpl();
- virtual ~CertStoreImpl();
+ ~CertStoreImpl() override;
private:
friend struct DefaultSingletonTraits<CertStoreImpl>;
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index 5e65042301c..e47bebc3bdf 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -45,6 +45,7 @@
#if defined(OS_POSIX)
#include "base/metrics/stats_table.h"
#include "base/posix/global_descriptors.h"
+#include "content/browser/file_descriptor_info_impl.h"
#endif
namespace content {
@@ -74,11 +75,10 @@ class ChildProcessLauncher::Context
{
}
- void Launch(
- SandboxedProcessLauncherDelegate* delegate,
- CommandLine* cmd_line,
- int child_process_id,
- Client* client) {
+ void Launch(SandboxedProcessLauncherDelegate* delegate,
+ base::CommandLine* cmd_line,
+ int child_process_id,
+ Client* client) {
client_ = client;
CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
@@ -87,17 +87,16 @@ class ChildProcessLauncher::Context
// We need to close the client end of the IPC channel to reliably detect
// child termination. We will close this fd after we create the child
// process which is asynchronous on Android.
- ipcfd_ = delegate->GetIpcFd();
+ ipcfd_.reset(delegate->TakeIpcFd().release());
#endif
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(
- &Context::LaunchInternal,
- make_scoped_refptr(this),
- client_thread_id_,
- child_process_id,
- delegate,
- cmd_line));
+ base::Bind(&Context::LaunchInternal,
+ make_scoped_refptr(this),
+ client_thread_id_,
+ child_process_id,
+ delegate,
+ cmd_line));
}
#if defined(OS_ANDROID)
@@ -111,14 +110,14 @@ class ChildProcessLauncher::Context
if (BrowserThread::CurrentlyOn(client_thread_id)) {
// This is always invoked on the UI thread which is commonly the
// |client_thread_id| so we can shortcut one PostTask.
- this_object->Notify(handle);
+ this_object->Notify(base::Process(handle));
} else {
BrowserThread::PostTask(
client_thread_id, FROM_HERE,
base::Bind(
&ChildProcessLauncher::Context::Notify,
this_object,
- handle));
+ base::Passed(base::Process(handle))));
}
}
#endif
@@ -134,6 +133,19 @@ class ChildProcessLauncher::Context
terminate_child_on_shutdown_ = terminate_on_shutdown;
}
+ void GetTerminationStatus() {
+ termination_status_ =
+ base::GetTerminationStatus(process_.Handle(), &exit_code_);
+ }
+
+ void SetProcessBackgrounded(bool background) {
+ base::Process to_pass = process_.Duplicate();
+ BrowserThread::PostTask(
+ BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+ base::Bind(&Context::SetProcessBackgroundedInternal,
+ base::Passed(&to_pass), background));
+ }
+
private:
friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
friend class ChildProcessLauncher;
@@ -172,21 +184,21 @@ class ChildProcessLauncher::Context
BrowserThread::ID client_thread_id,
int child_process_id,
SandboxedProcessLauncherDelegate* delegate,
- CommandLine* cmd_line) {
+ base::CommandLine* cmd_line) {
scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
#if defined(OS_WIN)
bool launch_elevated = delegate->ShouldLaunchElevated();
#elif defined(OS_ANDROID)
- int ipcfd = delegate->GetIpcFd();
+ // Uses |ipcfd_| instead of |ipcfd| on Android.
#elif defined(OS_MACOSX)
base::EnvironmentMap env = delegate->GetEnvironment();
- int ipcfd = delegate->GetIpcFd();
+ base::ScopedFD ipcfd = delegate->TakeIpcFd();
#elif defined(OS_POSIX)
bool use_zygote = delegate->ShouldUseZygote();
base::EnvironmentMap env = delegate->GetEnvironment();
- int ipcfd = delegate->GetIpcFd();
+ base::ScopedFD ipcfd = delegate->TakeIpcFd();
#endif
- scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
+ scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
base::TimeTicks begin_launch_time = base::TimeTicks::Now();
#if defined(OS_WIN)
@@ -201,17 +213,21 @@ class ChildProcessLauncher::Context
#elif defined(OS_POSIX)
std::string process_type =
cmd_line->GetSwitchValueASCII(switches::kProcessType);
- std::vector<FileDescriptorInfo> files_to_register;
- files_to_register.push_back(
- FileDescriptorInfo(kPrimaryIPCChannel,
- base::FileDescriptor(ipcfd, false)));
+ scoped_ptr<FileDescriptorInfo> files_to_register(
+ FileDescriptorInfoImpl::Create());
+
+#if defined(OS_ANDROID)
+ files_to_register->Share(kPrimaryIPCChannel, this_object->ipcfd_.get());
+#else
+ files_to_register->Transfer(kPrimaryIPCChannel, ipcfd.Pass());
+#endif
base::StatsTable* stats_table = base::StatsTable::current();
if (stats_table &&
base::SharedMemory::IsHandleValid(
stats_table->GetSharedMemoryHandle())) {
- files_to_register.push_back(
- FileDescriptorInfo(kStatsTableSharedMemFd,
- stats_table->GetSharedMemoryHandle()));
+ base::FileDescriptor fd = stats_table->GetSharedMemoryHandle();
+ DCHECK(!fd.auto_close);
+ files_to_register->Share(kStatsTableSharedMemFd, fd.fd);
}
#endif
@@ -220,40 +236,37 @@ class ChildProcessLauncher::Context
// when running in single process mode.
CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
- GetContentClient()->browser()->
- GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
- &files_to_register);
+ GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess(
+ *cmd_line, child_process_id, files_to_register.get());
- StartChildProcess(cmd_line->argv(), child_process_id, files_to_register,
+ StartChildProcess(
+ cmd_line->argv(),
+ child_process_id,
+ files_to_register.Pass(),
base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted,
- this_object, client_thread_id, begin_launch_time));
+ this_object,
+ client_thread_id,
+ begin_launch_time));
#elif defined(OS_POSIX)
base::ProcessHandle handle = base::kNullProcessHandle;
// We need to close the client end of the IPC channel to reliably detect
// child termination.
- base::ScopedFD ipcfd_closer(ipcfd);
#if !defined(OS_MACOSX)
- GetContentClient()->browser()->
- GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
- &files_to_register);
+ GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess(
+ *cmd_line, child_process_id, files_to_register.get());
if (use_zygote) {
- handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
- files_to_register,
- process_type);
+ handle = ZygoteHostImpl::GetInstance()->ForkRequest(
+ cmd_line->argv(), files_to_register.Pass(), process_type);
} else
// Fall through to the normal posix case below when we're not zygoting.
#endif // !defined(OS_MACOSX)
{
// Convert FD mapping to FileHandleMappingVector
- base::FileHandleMappingVector fds_to_map;
- for (size_t i = 0; i < files_to_register.size(); ++i) {
- fds_to_map.push_back(std::make_pair(
- files_to_register[i].fd.fd,
- files_to_register[i].id +
- base::GlobalDescriptors::kBaseDescriptor));
- }
+ base::FileHandleMappingVector fds_to_map =
+ files_to_register->GetMappingWithIDAdjustment(
+ base::GlobalDescriptors::kBaseDescriptor);
#if !defined(OS_MACOSX)
if (process_type == switches::kRendererProcess) {
@@ -325,7 +338,7 @@ class ChildProcessLauncher::Context
#if defined(OS_POSIX) && !defined(OS_MACOSX)
use_zygote,
#endif
- handle));
+ base::Passed(base::Process(handle))));
#endif // !defined(OS_ANDROID)
}
@@ -333,21 +346,21 @@ class ChildProcessLauncher::Context
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
bool zygote,
#endif
- base::ProcessHandle handle) {
+ base::Process process) {
#if defined(OS_ANDROID)
// Finally close the ipcfd
- base::ScopedFD ipcfd_closer(ipcfd_);
+ base::ScopedFD ipcfd_closer = ipcfd_.Pass();
#endif
starting_ = false;
- process_.set_handle(handle);
- if (!handle)
+ process_ = process.Pass();
+ if (!process_.IsValid())
LOG(ERROR) << "Failed to launch child process";
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
zygote_ = zygote;
#endif
if (client_) {
- if (handle) {
+ if (process_.IsValid()) {
client_->OnProcessLaunched();
} else {
client_->OnProcessLaunchFailed();
@@ -358,7 +371,7 @@ class ChildProcessLauncher::Context
}
void Terminate() {
- if (!process_.handle())
+ if (!process_.IsValid())
return;
if (!terminate_child_on_shutdown_)
@@ -373,16 +386,14 @@ class ChildProcessLauncher::Context
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
zygote_,
#endif
- process_.handle()));
- process_.set_handle(base::kNullProcessHandle);
+ base::Passed(&process_)));
}
- static void SetProcessBackgrounded(base::ProcessHandle handle,
- bool background) {
- base::Process process(handle);
+ static void SetProcessBackgroundedInternal(base::Process process,
+ bool background) {
process.SetProcessBackgrounded(background);
#if defined(OS_ANDROID)
- SetChildProcessInForeground(handle, !background);
+ SetChildProcessInForeground(process.Handle(), !background);
#endif
}
@@ -390,12 +401,12 @@ class ChildProcessLauncher::Context
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
bool zygote,
#endif
- base::ProcessHandle handle) {
+ base::Process process) {
#if defined(OS_ANDROID)
- VLOG(0) << "ChromeProcess: Stopping process with handle " << handle;
- StopChildProcess(handle);
+ VLOG(1) << "ChromeProcess: Stopping process with handle "
+ << process.Handle();
+ StopChildProcess(process.Handle());
#else
- base::Process process(handle);
// Client has gone away, so just kill the process. Using exit code 0
// means that UMA won't treat this as a crash.
process.Terminate(RESULT_CODE_NORMAL_EXIT);
@@ -405,14 +416,13 @@ class ChildProcessLauncher::Context
if (zygote) {
// If the renderer was created via a zygote, we have to proxy the reaping
// through the zygote process.
- ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle);
+ ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(process.Handle());
} else
#endif // !OS_MACOSX
{
- base::EnsureProcessTerminated(handle);
+ base::EnsureProcessTerminated(process.Handle());
}
#endif // OS_POSIX
- process.Close();
#endif // defined(OS_ANDROID)
}
@@ -427,7 +437,7 @@ class ChildProcessLauncher::Context
bool terminate_child_on_shutdown_;
#if defined(OS_ANDROID)
// The fd to close after creating the process.
- int ipcfd_;
+ base::ScopedFD ipcfd_;
#elif defined(OS_POSIX) && !defined(OS_MACOSX)
bool zygote_;
#endif
@@ -436,7 +446,7 @@ class ChildProcessLauncher::Context
ChildProcessLauncher::ChildProcessLauncher(
SandboxedProcessLauncherDelegate* delegate,
- CommandLine* cmd_line,
+ base::CommandLine* cmd_line,
int child_process_id,
Client* client) {
context_ = new Context();
@@ -455,16 +465,15 @@ bool ChildProcessLauncher::IsStarting() {
return context_->starting_;
}
-base::ProcessHandle ChildProcessLauncher::GetHandle() {
+const base::Process& ChildProcessLauncher::GetProcess() const {
DCHECK(!context_->starting_);
- return context_->process_.handle();
+ return context_->process_;
}
base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
bool known_dead,
int* exit_code) {
- base::ProcessHandle handle = context_->process_.handle();
- if (handle == base::kNullProcessHandle) {
+ if (!context_->process_.IsValid()) {
// Process is already gone, so return the cached termination status.
if (exit_code)
*exit_code = context_->exit_code_;
@@ -473,25 +482,27 @@ base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
if (context_->zygote_) {
context_->termination_status_ = ZygoteHostImpl::GetInstance()->
- GetTerminationStatus(handle, known_dead, &context_->exit_code_);
+ GetTerminationStatus(context_->process_.Handle(), known_dead,
+ &context_->exit_code_);
} else if (known_dead) {
context_->termination_status_ =
- base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
+ base::GetKnownDeadTerminationStatus(context_->process_.Handle(),
+ &context_->exit_code_);
} else {
#elif defined(OS_MACOSX)
if (known_dead) {
context_->termination_status_ =
- base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
+ base::GetKnownDeadTerminationStatus(context_->process_.Handle(),
+ &context_->exit_code_);
} else {
#elif defined(OS_ANDROID)
- if (IsChildProcessOomProtected(handle)) {
- context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
+ if (IsChildProcessOomProtected(context_->process_.Handle())) {
+ context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
} else {
#else
{
#endif
- context_->termination_status_ =
- base::GetTerminationStatus(handle, &context_->exit_code_);
+ context_->GetTerminationStatus();
}
if (exit_code)
@@ -510,11 +521,7 @@ base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus(
}
void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
- BrowserThread::PostTask(
- BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
- base::Bind(
- &ChildProcessLauncher::Context::SetProcessBackgrounded,
- GetHandle(), background));
+ context_->SetProcessBackgrounded(background);
}
void ChildProcessLauncher::SetTerminateChildOnShutdown(
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index cc8b3f52cef..de890a92e40 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
+#include "base/process/process.h"
#include "content/common/content_export.h"
namespace base {
@@ -50,8 +51,8 @@ class CONTENT_EXPORT ChildProcessLauncher {
// True if the process is being launched and so the handle isn't available.
bool IsStarting();
- // Getter for the process handle. Only call after the process has started.
- base::ProcessHandle GetHandle();
+ // Getter for the process. Only call after the process has started.
+ const base::Process& GetProcess() const;
// Call this when the child process exits to know what happened to it.
// |known_dead| can be true if we already know the process is dead as it can
diff --git a/chromium/content/browser/child_process_launcher_browsertest.cc b/chromium/content/browser/child_process_launcher_browsertest.cc
new file mode 100644
index 00000000000..fe3fa1da32b
--- /dev/null
+++ b/chromium/content/browser/child_process_launcher_browsertest.cc
@@ -0,0 +1,25 @@
+// Copyright 2014 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/command_line.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+
+namespace content {
+
+typedef ContentBrowserTest ChildProcessLauncherBrowserTest;
+
+class StatsTableBrowserTest : public ChildProcessLauncherBrowserTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kEnableStatsTable);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(StatsTableBrowserTest, StartWithStatTable) {
+ NavigateToURL(shell(), GURL("about:blank"));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/child_process_security_policy_browsertest.cc b/chromium/content/browser/child_process_security_policy_browsertest.cc
index 67d36e4eabf..b509a494706 100644
--- a/chromium/content/browser/child_process_security_policy_browsertest.cc
+++ b/chromium/content/browser/child_process_security_policy_browsertest.cc
@@ -20,14 +20,14 @@ namespace content {
class ChildProcessSecurityPolicyInProcessBrowserTest
: public ContentBrowserTest {
public:
- virtual void SetUp() {
+ void SetUp() override {
EXPECT_EQ(
ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size(),
0U);
ContentBrowserTest::SetUp();
}
- virtual void TearDown() {
+ void TearDown() override {
EXPECT_EQ(
ChildProcessSecurityPolicyImpl::GetInstance()->security_state_.size(),
0U);
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 68f4e81fbef..34caa5a4923 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -20,11 +20,11 @@
#include "content/public/common/url_constants.h"
#include "net/base/filename_util.h"
#include "net/url_request/url_request.h"
+#include "storage/browser/fileapi/file_permission_policy.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_permission_policy.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/common/fileapi/file_system_util.h"
namespace content {
@@ -76,8 +76,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
~SecurityState() {
scheme_policy_.clear();
- fileapi::IsolatedContext* isolated_context =
- fileapi::IsolatedContext::GetInstance();
+ storage::IsolatedContext* isolated_context =
+ storage::IsolatedContext::GetInstance();
for (FileSystemMap::iterator iter = filesystem_permissions_.begin();
iter != filesystem_permissions_.end();
++iter) {
@@ -121,7 +121,7 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
void GrantPermissionsForFileSystem(const std::string& filesystem_id,
int permissions) {
if (!ContainsKey(filesystem_permissions_, filesystem_id))
- fileapi::IsolatedContext::GetInstance()->AddReference(filesystem_id);
+ storage::IsolatedContext::GetInstance()->AddReference(filesystem_id);
filesystem_permissions_[filesystem_id] |= permissions;
}
@@ -241,7 +241,8 @@ class ChildProcessSecurityPolicyImpl::SecurityState {
// compatibility with many sites. The similar --site-per-process flag only
// blocks JavaScript access to cross-site cookies (in
// CanAccessCookiesForOrigin).
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(switches::kEnableStrictSiteIsolation))
return true;
@@ -580,14 +581,14 @@ void ChildProcessSecurityPolicyImpl::RevokeReadRawCookies(int child_id) {
state->second->RevokeReadRawCookies();
}
-bool ChildProcessSecurityPolicyImpl::CanLoadPage(
- int child_id,
- const GURL& url,
- ResourceType::Type resource_type) {
+bool ChildProcessSecurityPolicyImpl::CanLoadPage(int child_id,
+ const GURL& url,
+ ResourceType resource_type) {
// If --site-per-process flag is passed, we should enforce
// stronger security restrictions on page navigation.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
- ResourceType::IsFrame(resource_type)) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess) &&
+ IsResourceTypeFrame(resource_type)) {
// TODO(nasko): Do the proper check for site-per-process, once
// out-of-process iframes is ready to go.
return true;
@@ -696,7 +697,9 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFile(
}
bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
- int child_id, const fileapi::FileSystemURL& url, int permissions) {
+ int child_id,
+ const storage::FileSystemURL& url,
+ int permissions) {
if (!url.is_valid())
return false;
@@ -704,12 +707,12 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
return false;
// Any write access is disallowed on the root path.
- if (fileapi::VirtualPath::IsRootPath(url.path()) &&
+ if (storage::VirtualPath::IsRootPath(url.path()) &&
(permissions & ~READ_FILE_GRANT)) {
return false;
}
- if (url.mount_type() == fileapi::kFileSystemTypeIsolated) {
+ if (url.mount_type() == storage::kFileSystemTypeIsolated) {
// When Isolated filesystems is overlayed on top of another filesystem,
// its per-filesystem permission overrides the underlying filesystem
// permissions).
@@ -722,15 +725,15 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
if (found == file_system_policy_map_.end())
return false;
- if ((found->second & fileapi::FILE_PERMISSION_READ_ONLY) &&
+ if ((found->second & storage::FILE_PERMISSION_READ_ONLY) &&
permissions & ~READ_FILE_GRANT) {
return false;
}
- if (found->second & fileapi::FILE_PERMISSION_USE_FILE_PERMISSION)
+ if (found->second & storage::FILE_PERMISSION_USE_FILE_PERMISSION)
return HasPermissionsForFile(child_id, url.path(), permissions);
- if (found->second & fileapi::FILE_PERMISSION_SANDBOX)
+ if (found->second & storage::FILE_PERMISSION_SANDBOX)
return true;
return false;
@@ -738,38 +741,38 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystemFile(
bool ChildProcessSecurityPolicyImpl::CanReadFileSystemFile(
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url, READ_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile(
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url, WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCreateFileSystemFile(
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url, CREATE_NEW_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCreateReadWriteFileSystemFile(
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url,
CREATE_READ_WRITE_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanCopyIntoFileSystemFile(
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url, COPY_INTO_FILE_GRANT);
}
bool ChildProcessSecurityPolicyImpl::CanDeleteFileSystemFile(
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return HasPermissionsForFileSystemFile(child_id, url, DELETE_FILE_GRANT);
}
@@ -874,7 +877,7 @@ bool ChildProcessSecurityPolicyImpl::HasPermissionsForFileSystem(
}
void ChildProcessSecurityPolicyImpl::RegisterFileSystemPermissionPolicy(
- fileapi::FileSystemType type,
+ storage::FileSystemType type,
int policy) {
base::AutoLock lock(lock_);
file_system_policy_map_[type] = policy;
diff --git a/chromium/content/browser/child_process_security_policy_impl.h b/chromium/content/browser/child_process_security_policy_impl.h
index 005292cdf2b..dcc1b887fab 100644
--- a/chromium/content/browser/child_process_security_policy_impl.h
+++ b/chromium/content/browser/child_process_security_policy_impl.h
@@ -15,8 +15,8 @@
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/child_process_security_policy.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/resource_type.h"
+#include "content/public/common/resource_type.h"
+#include "storage/common/fileapi/file_system_types.h"
class GURL;
@@ -24,7 +24,7 @@ namespace base {
class FilePath;
}
-namespace fileapi {
+namespace storage {
class FileSystemURL;
}
@@ -35,51 +35,44 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
public:
// Object can only be created through GetInstance() so the constructor is
// private.
- virtual ~ChildProcessSecurityPolicyImpl();
+ ~ChildProcessSecurityPolicyImpl() override;
static ChildProcessSecurityPolicyImpl* GetInstance();
// ChildProcessSecurityPolicy implementation.
- virtual void RegisterWebSafeScheme(const std::string& scheme) OVERRIDE;
- virtual bool IsWebSafeScheme(const std::string& scheme) OVERRIDE;
- virtual void GrantReadFile(int child_id, const base::FilePath& file) OVERRIDE;
- virtual void GrantCreateReadWriteFile(int child_id,
- const base::FilePath& file) OVERRIDE;
- virtual void GrantCopyInto(int child_id, const base::FilePath& dir) OVERRIDE;
- virtual void GrantDeleteFrom(int child_id,
- const base::FilePath& dir) OVERRIDE;
- virtual void GrantReadFileSystem(
+ void RegisterWebSafeScheme(const std::string& scheme) override;
+ bool IsWebSafeScheme(const std::string& scheme) override;
+ void GrantReadFile(int child_id, const base::FilePath& file) override;
+ void GrantCreateReadWriteFile(int child_id,
+ const base::FilePath& file) override;
+ void GrantCopyInto(int child_id, const base::FilePath& dir) override;
+ void GrantDeleteFrom(int child_id, const base::FilePath& dir) override;
+ void GrantReadFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ void GrantWriteFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ void GrantCreateFileForFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ void GrantCreateReadWriteFileSystem(
int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual void GrantWriteFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual void GrantCreateFileForFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual void GrantCreateReadWriteFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual void GrantCopyIntoFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual void GrantDeleteFromFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual void GrantScheme(int child_id, const std::string& scheme) OVERRIDE;
- virtual bool CanReadFile(int child_id, const base::FilePath& file) OVERRIDE;
- virtual bool CanCreateReadWriteFile(int child_id,
- const base::FilePath& file) OVERRIDE;
- virtual bool CanReadFileSystem(int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual bool CanReadWriteFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual bool CanCopyIntoFileSystem(int child_id,
- const std::string& filesystem_id) OVERRIDE;
- virtual bool CanDeleteFromFileSystem(
- int child_id,
- const std::string& filesystem_id) OVERRIDE;
+ const std::string& filesystem_id) override;
+ void GrantCopyIntoFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ void GrantDeleteFromFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ void GrantScheme(int child_id, const std::string& scheme) override;
+ bool CanReadFile(int child_id, const base::FilePath& file) override;
+ bool CanCreateReadWriteFile(int child_id,
+ const base::FilePath& file) override;
+ bool CanReadFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ bool CanReadWriteFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ bool CanCopyIntoFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ bool CanDeleteFromFileSystem(int child_id,
+ const std::string& filesystem_id) override;
+ bool HasWebUIBindings(int child_id) override;
// Pseudo schemes are treated differently than other schemes because they
// cannot be requested like normal URLs. There is no mechanism for revoking
@@ -139,23 +132,17 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Only might return false if --site-per-process flag is used.
bool CanLoadPage(int child_id,
const GURL& url,
- ResourceType::Type resource_type);
+ ResourceType resource_type);
// Explicit permissions checks for FileSystemURL specified files.
- bool CanReadFileSystemFile(int child_id, const fileapi::FileSystemURL& url);
- bool CanWriteFileSystemFile(int child_id, const fileapi::FileSystemURL& url);
- bool CanCreateFileSystemFile(int child_id, const fileapi::FileSystemURL& url);
+ bool CanReadFileSystemFile(int child_id, const storage::FileSystemURL& url);
+ bool CanWriteFileSystemFile(int child_id, const storage::FileSystemURL& url);
+ bool CanCreateFileSystemFile(int child_id, const storage::FileSystemURL& url);
bool CanCreateReadWriteFileSystemFile(int child_id,
- const fileapi::FileSystemURL& url);
+ const storage::FileSystemURL& url);
bool CanCopyIntoFileSystemFile(int child_id,
- const fileapi::FileSystemURL& url);
- bool CanDeleteFileSystemFile(int child_id,
- const fileapi::FileSystemURL& url);
-
- // Returns true if the specified child_id has been granted WebUIBindings.
- // The browser should check this property before assuming the child process is
- // allowed to use WebUIBindings.
- bool HasWebUIBindings(int child_id);
+ const storage::FileSystemURL& url);
+ bool CanDeleteFileSystemFile(int child_id, const storage::FileSystemURL& url);
// Returns true if the specified child_id has been granted ReadRawCookies.
bool CanReadRawCookies(int child_id);
@@ -181,10 +168,9 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Register FileSystem type and permission policy which should be used
// for the type. The |policy| must be a bitwise-or'd value of
- // fileapi::FilePermissionPolicy.
- void RegisterFileSystemPermissionPolicy(
- fileapi::FileSystemType type,
- int policy);
+ // storage::FilePermissionPolicy.
+ void RegisterFileSystemPermissionPolicy(storage::FileSystemType type,
+ int policy);
// Returns true if sending system exclusive messages is allowed.
bool CanSendMidiSysExMessage(int child_id);
@@ -201,7 +187,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
typedef std::set<std::string> SchemeSet;
typedef std::map<int, SecurityState*> SecurityStateMap;
typedef std::map<int, int> WorkerToMainProcessMap;
- typedef std::map<fileapi::FileSystemType, int> FileSystemPermissionPolicyMap;
+ typedef std::map<storage::FileSystemType, int> FileSystemPermissionPolicyMap;
// Obtain an instance of ChildProcessSecurityPolicyImpl via GetInstance().
ChildProcessSecurityPolicyImpl();
@@ -241,7 +227,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Determines if certain permissions were granted for a file in FileSystem
// API. |permissions| is an internally defined bit-set.
bool HasPermissionsForFileSystemFile(int child_id,
- const fileapi::FileSystemURL& url,
+ const storage::FileSystemURL& url,
int permissions);
// Determines if certain permissions were granted for a file system.
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 97c1889b3d7..678e3d207f8 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -10,12 +10,12 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/common/url_constants.h"
#include "content/test/test_content_browser_client.h"
+#include "storage/browser/fileapi/file_permission_policy.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/common/fileapi/file_system_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_permission_policy.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/common/fileapi/file_system_types.h"
namespace content {
namespace {
@@ -34,7 +34,7 @@ class ChildProcessSecurityPolicyTestBrowserClient
public:
ChildProcessSecurityPolicyTestBrowserClient() {}
- virtual bool IsHandledURL(const GURL& url) OVERRIDE {
+ bool IsHandledURL(const GURL& url) override {
return schemes_.find(url.scheme()) != schemes_.end();
}
@@ -57,7 +57,7 @@ class ChildProcessSecurityPolicyTest : public testing::Test {
ChildProcessSecurityPolicyTest() : old_browser_client_(NULL) {
}
- virtual void SetUp() {
+ void SetUp() override {
old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
// Claim to always handle chrome:// URLs because the CPSP's notion of
@@ -71,7 +71,7 @@ class ChildProcessSecurityPolicyTest : public testing::Test {
test_browser_client_.AddScheme(url::kFileScheme);
}
- virtual void TearDown() {
+ void TearDown() override {
test_browser_client_.ClearSchemes();
SetBrowserClientForTesting(old_browser_client_);
}
@@ -98,7 +98,7 @@ class ChildProcessSecurityPolicyTest : public testing::Test {
void CheckHasNoFileSystemFilePermission(ChildProcessSecurityPolicyImpl* p,
const base::FilePath& file,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
EXPECT_FALSE(p->CanReadFile(kRendererID, file));
EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
@@ -308,22 +308,24 @@ TEST_F(ChildProcessSecurityPolicyTest, FileSystemGrantsTest) {
ChildProcessSecurityPolicyImpl::GetInstance();
p->Add(kRendererID);
- std::string read_id = fileapi::IsolatedContext::GetInstance()->
- RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
- "read_filesystem",
- base::FilePath());
- std::string read_write_id = fileapi::IsolatedContext::GetInstance()->
- RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
- "read_write_filesystem",
- base::FilePath());
- std::string copy_into_id = fileapi::IsolatedContext::GetInstance()->
- RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
- "copy_into_filesystem",
- base::FilePath());
- std::string delete_from_id = fileapi::IsolatedContext::GetInstance()->
- RegisterFileSystemForVirtualPath(fileapi::kFileSystemTypeTest,
- "delete_from_filesystem",
- base::FilePath());
+ std::string read_id =
+ storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+ storage::kFileSystemTypeTest, "read_filesystem", base::FilePath());
+ std::string read_write_id =
+ storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+ storage::kFileSystemTypeTest,
+ "read_write_filesystem",
+ base::FilePath());
+ std::string copy_into_id =
+ storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+ storage::kFileSystemTypeTest,
+ "copy_into_filesystem",
+ base::FilePath());
+ std::string delete_from_id =
+ storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
+ storage::kFileSystemTypeTest,
+ "delete_from_filesystem",
+ base::FilePath());
// Test initially having no permissions.
CheckHasNoFileSystemPermission(p, read_id);
@@ -373,10 +375,10 @@ TEST_F(ChildProcessSecurityPolicyTest, FileSystemGrantsTest) {
// Cleanup.
p->Remove(kRendererID);
- fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(read_id);
- fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(read_write_id);
- fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(copy_into_id);
- fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(delete_from_id);
+ storage::IsolatedContext::GetInstance()->RevokeFileSystem(read_id);
+ storage::IsolatedContext::GetInstance()->RevokeFileSystem(read_write_id);
+ storage::IsolatedContext::GetInstance()->RevokeFileSystem(copy_into_id);
+ storage::IsolatedContext::GetInstance()->RevokeFileSystem(delete_from_id);
}
TEST_F(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) {
@@ -384,14 +386,14 @@ TEST_F(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) {
ChildProcessSecurityPolicyImpl::GetInstance();
p->RegisterFileSystemPermissionPolicy(
- fileapi::kFileSystemTypeTest,
- fileapi::FILE_PERMISSION_USE_FILE_PERMISSION);
+ storage::kFileSystemTypeTest,
+ storage::FILE_PERMISSION_USE_FILE_PERMISSION);
p->Add(kRendererID);
base::FilePath file(TEST_PATH("/dir/testfile"));
file = file.NormalizePathSeparators();
- fileapi::FileSystemURL url = fileapi::FileSystemURL::CreateForTest(
- GURL("http://foo/"), fileapi::kFileSystemTypeTest, file);
+ storage::FileSystemURL url = storage::FileSystemURL::CreateForTest(
+ GURL("http://foo/"), storage::kFileSystemTypeTest, file);
// Test initially having no permissions.
CheckHasNoFileSystemFilePermission(p, file, url);
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.h b/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
new file mode 100644
index 00000000000..63d9e514854
--- /dev/null
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
@@ -0,0 +1,56 @@
+// Copyright 2014 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 CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_HELPER_MAC_H_
+#define CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_HELPER_MAC_H_
+
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+
+#ifdef __OBJC__
+@class NSDictionary;
+#else
+class NSDictionary;
+#endif
+
+namespace content {
+
+class SystemHotkeyMap;
+
+// This singleton holds a global mapping of hotkeys reserved by OSX.
+class SystemHotkeyHelperMac {
+ public:
+ // Return pointer to the singleton instance for the current process.
+ static SystemHotkeyHelperMac* GetInstance();
+
+ // Loads the system hot keys after a brief delay, to reduce file system access
+ // immediately after launch.
+ void DeferredLoadSystemHotkeys();
+
+ // Guaranteed to not be NULL.
+ SystemHotkeyMap* map() { return map_.get(); }
+
+ private:
+ friend struct DefaultSingletonTraits<SystemHotkeyHelperMac>;
+
+ SystemHotkeyHelperMac();
+ ~SystemHotkeyHelperMac();
+
+ // Must be called from the FILE thread. Loads the file containing the system
+ // hotkeys into a NSDictionary* object, and passes the result to FileDidLoad
+ // on the UI thread.
+ void LoadSystemHotkeys();
+
+ // Must be called from the UI thread. This takes ownership of |dictionary|.
+ // Parses the system hotkeys from the plist stored in |dictionary|.
+ void FileDidLoad(NSDictionary* dictionary);
+
+ scoped_ptr<SystemHotkeyMap> map_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemHotkeyHelperMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_HELPER_MAC_H_
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
new file mode 100644
index 00000000000..68c52820ef3
--- /dev/null
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.mm
@@ -0,0 +1,77 @@
+// Copyright 2014 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 "content/browser/cocoa/system_hotkey_helper_mac.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/mac/foundation_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "content/browser/cocoa/system_hotkey_map.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+NSString* kSystemHotkeyPlistExtension =
+ @"/Preferences/com.apple.symbolichotkeys.plist";
+
+// Amount of time to delay loading the hotkeys in seconds.
+const int kLoadHotkeysDelaySeconds = 10;
+
+} // namespace
+
+namespace content {
+
+// static
+SystemHotkeyHelperMac* SystemHotkeyHelperMac::GetInstance() {
+ return Singleton<SystemHotkeyHelperMac>::get();
+}
+
+void SystemHotkeyHelperMac::DeferredLoadSystemHotkeys() {
+ BrowserThread::PostDelayedTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&SystemHotkeyHelperMac::LoadSystemHotkeys,
+ base::Unretained(this)),
+ base::TimeDelta::FromSeconds(kLoadHotkeysDelaySeconds));
+}
+
+SystemHotkeyHelperMac::SystemHotkeyHelperMac() : map_(new SystemHotkeyMap) {
+}
+
+SystemHotkeyHelperMac::~SystemHotkeyHelperMac() {
+}
+
+void SystemHotkeyHelperMac::LoadSystemHotkeys() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ std::string library_path(base::mac::GetUserLibraryPath().value());
+ NSString* expanded_file_path =
+ [NSString stringWithFormat:@"%s%@",
+ library_path.c_str(),
+ kSystemHotkeyPlistExtension];
+
+ // Loads the file into memory.
+ NSData* data = [NSData dataWithContentsOfFile:expanded_file_path];
+ // Intentionally create the object with +1 retain count, as FileDidLoad
+ // will destroy the object.
+ NSDictionary* dictionary = [SystemHotkeyMap::DictionaryFromData(data) retain];
+
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&SystemHotkeyHelperMac::FileDidLoad,
+ base::Unretained(this),
+ dictionary));
+}
+
+void SystemHotkeyHelperMac::FileDidLoad(NSDictionary* dictionary) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ bool success = map()->ParseDictionary(dictionary);
+ UMA_HISTOGRAM_BOOLEAN("OSX.SystemHotkeyMap.LoadSuccess", success);
+ [dictionary release];
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cocoa/system_hotkey_map.h b/chromium/content/browser/cocoa/system_hotkey_map.h
new file mode 100644
index 00000000000..1909aa53b88
--- /dev/null
+++ b/chromium/content/browser/cocoa/system_hotkey_map.h
@@ -0,0 +1,66 @@
+// Copyright 2014 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 CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_MAP_H_
+#define CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_MAP_H_
+
+#import <Cocoa/Cocoa.h>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+struct SystemHotkey;
+
+// Maintains a listing of all OSX system hotkeys. e.g. (cmd + `) These hotkeys
+// should have higher priority than web content, so NSEvents that correspond to
+// a system hotkey should not be passed to the renderer.
+class CONTENT_EXPORT SystemHotkeyMap {
+ public:
+ SystemHotkeyMap();
+ ~SystemHotkeyMap();
+
+ // Converts the plist stored in |data| into an NSDictionary. Returns nil on
+ // error.
+ static NSDictionary* DictionaryFromData(NSData* data);
+
+ // Parses the property list data commonly stored at
+ // ~/Library/Preferences/com.apple.symbolichotkeys.plist
+ // Returns false on encountering an irrecoverable error.
+ // Can be called multiple times. Only the results from the most recent
+ // invocation are stored.
+ bool ParseDictionary(NSDictionary* dictionary);
+
+ // Whether the event corresponds to a hotkey that has been reserved by the
+ // system.
+ bool IsEventReserved(NSEvent* event) const;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(SystemHotkeyMapTest, Parse);
+ FRIEND_TEST_ALL_PREFIXES(SystemHotkeyMapTest, ParseCustomEntries);
+ FRIEND_TEST_ALL_PREFIXES(SystemHotkeyMapTest, ParseMouse);
+
+ // Whether the hotkey has been reserved by the user.
+ bool IsHotkeyReserved(unsigned short key_code, NSUInteger modifiers) const;
+
+ // Create at least one record of a hotkey that is reserved by the user.
+ // Certain system hotkeys automatically reserve multiple key combinations.
+ void ReserveHotkey(unsigned short key_code,
+ NSUInteger modifiers,
+ NSString* system_effect);
+
+ // Create a record of a hotkey that is reserved by the user.
+ void ReserveHotkey(unsigned short key_code, NSUInteger modifiers);
+
+ std::vector<SystemHotkey> system_hotkeys_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemHotkeyMap);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_MAP_H_
diff --git a/chromium/content/browser/cocoa/system_hotkey_map.mm b/chromium/content/browser/cocoa/system_hotkey_map.mm
new file mode 100644
index 00000000000..da04fa8b844
--- /dev/null
+++ b/chromium/content/browser/cocoa/system_hotkey_map.mm
@@ -0,0 +1,165 @@
+// Copyright 2014 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.
+
+#import "content/browser/cocoa/system_hotkey_map.h"
+
+#pragma mark - NSDictionary Helper Functions
+
+namespace {
+
+// All 4 following functions return nil if the object doesn't exist, or isn't of
+// the right class.
+id ObjectForKey(NSDictionary* dict, NSString* key, Class aClass) {
+ id object = [dict objectForKey:key];
+ if (![object isKindOfClass:aClass])
+ return nil;
+ return object;
+}
+
+NSDictionary* DictionaryForKey(NSDictionary* dict, NSString* key) {
+ return ObjectForKey(dict, key, [NSDictionary class]);
+}
+
+NSArray* ArrayForKey(NSDictionary* dict, NSString* key) {
+ return ObjectForKey(dict, key, [NSArray class]);
+}
+
+NSNumber* NumberForKey(NSDictionary* dict, NSString* key) {
+ return ObjectForKey(dict, key, [NSNumber class]);
+}
+
+NSString* StringForKey(NSDictionary* dict, NSString* key) {
+ return ObjectForKey(dict, key, [NSString class]);
+}
+
+} // namespace
+
+#pragma mark - SystemHotkey
+
+namespace content {
+
+struct SystemHotkey {
+ unsigned short key_code;
+ NSUInteger modifiers;
+};
+
+#pragma mark - SystemHotkeyMap
+
+SystemHotkeyMap::SystemHotkeyMap() {
+}
+SystemHotkeyMap::~SystemHotkeyMap() {
+}
+
+NSDictionary* SystemHotkeyMap::DictionaryFromData(NSData* data) {
+ if (!data)
+ return nil;
+
+ NSError* error = nil;
+ NSPropertyListFormat format;
+ NSDictionary* dictionary =
+ [NSPropertyListSerialization propertyListWithData:data
+ options:0
+ format:&format
+ error:&error];
+
+ if (![dictionary isKindOfClass:[NSDictionary class]])
+ return nil;
+
+ return dictionary;
+}
+
+bool SystemHotkeyMap::ParseDictionary(NSDictionary* dictionary) {
+ system_hotkeys_.clear();
+
+ if (!dictionary)
+ return false;
+
+ NSDictionary* hotkey_dictionaries =
+ DictionaryForKey(dictionary, @"AppleSymbolicHotKeys");
+ if (!hotkey_dictionaries)
+ return false;
+
+ for (NSString* hotkey_system_effect in [hotkey_dictionaries allKeys]) {
+ if (![hotkey_system_effect isKindOfClass:[NSString class]])
+ continue;
+
+ NSDictionary* hotkey_dictionary =
+ [hotkey_dictionaries objectForKey:hotkey_system_effect];
+ if (![hotkey_dictionary isKindOfClass:[NSDictionary class]])
+ continue;
+
+ NSNumber* enabled = NumberForKey(hotkey_dictionary, @"enabled");
+ if (!enabled || enabled.boolValue == NO)
+ continue;
+
+ NSDictionary* value = DictionaryForKey(hotkey_dictionary, @"value");
+ if (!value)
+ continue;
+
+ NSString* type = StringForKey(value, @"type");
+ if (!type || ![type isEqualToString:@"standard"])
+ continue;
+
+ NSArray* parameters = ArrayForKey(value, @"parameters");
+ if (!parameters || [parameters count] != 3)
+ continue;
+
+ NSNumber* key_code = [parameters objectAtIndex:1];
+ if (![key_code isKindOfClass:[NSNumber class]])
+ continue;
+
+ NSNumber* modifiers = [parameters objectAtIndex:2];
+ if (![modifiers isKindOfClass:[NSNumber class]])
+ continue;
+
+ ReserveHotkey(key_code.unsignedShortValue,
+ modifiers.unsignedIntegerValue,
+ hotkey_system_effect);
+ }
+
+ return true;
+}
+
+bool SystemHotkeyMap::IsEventReserved(NSEvent* event) const {
+ return IsHotkeyReserved(event.keyCode, event.modifierFlags);
+}
+
+bool SystemHotkeyMap::IsHotkeyReserved(unsigned short key_code,
+ NSUInteger modifiers) const {
+ modifiers &= NSDeviceIndependentModifierFlagsMask;
+ std::vector<SystemHotkey>::const_iterator it;
+ for (it = system_hotkeys_.begin(); it != system_hotkeys_.end(); ++it) {
+ if (it->key_code == key_code && it->modifiers == modifiers)
+ return true;
+ }
+ return false;
+}
+
+void SystemHotkeyMap::ReserveHotkey(unsigned short key_code,
+ NSUInteger modifiers,
+ NSString* system_effect) {
+ ReserveHotkey(key_code, modifiers);
+
+ // If a hotkey exists for toggling through the windows of an application, then
+ // adding shift to that hotkey toggles through the windows backwards.
+ if ([system_effect isEqualToString:@"27"])
+ ReserveHotkey(key_code, modifiers | NSShiftKeyMask);
+}
+
+void SystemHotkeyMap::ReserveHotkey(unsigned short key_code,
+ NSUInteger modifiers) {
+ // Hotkeys require at least one of control, command, or alternate keys to be
+ // down.
+ NSUInteger required_modifiers =
+ NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask;
+ if ((modifiers & required_modifiers) == 0)
+ return;
+
+ SystemHotkey hotkey;
+ hotkey.key_code = key_code;
+ hotkey.modifiers = modifiers;
+ system_hotkeys_.push_back(hotkey);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
new file mode 100644
index 00000000000..6b2652fb426
--- /dev/null
+++ b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
@@ -0,0 +1,196 @@
+// Copyright 2014 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 <gtest/gtest.h>
+
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+
+#include "base/files/file_path.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/path_service.h"
+#import "content/browser/cocoa/system_hotkey_map.h"
+#include "content/public/common/content_paths.h"
+
+namespace content {
+
+class SystemHotkeyMapTest : public ::testing::Test {
+ protected:
+ SystemHotkeyMapTest() {}
+
+ NSData* DataFromTestFile(const char* file) {
+ base::FilePath test_data_dir;
+ bool result = PathService::Get(DIR_TEST_DATA, &test_data_dir);
+ if (!result)
+ return nil;
+
+ base::FilePath test_path = test_data_dir.AppendASCII(file);
+ std::string test_path_string = test_path.AsUTF8Unsafe();
+ NSString* file_path =
+ [NSString stringWithUTF8String:test_path_string.c_str()];
+ return [NSData dataWithContentsOfFile:file_path];
+ }
+
+ void AddEntryToDictionary(BOOL enabled,
+ unsigned short key_code,
+ NSUInteger modifiers) {
+ NSMutableArray* parameters = [NSMutableArray array];
+ // The first parameter is unused.
+ [parameters addObject:[NSNumber numberWithInt:65535]];
+ [parameters addObject:[NSNumber numberWithUnsignedShort:key_code]];
+ [parameters addObject:[NSNumber numberWithUnsignedInteger:modifiers]];
+
+ NSMutableDictionary* value_dictionary = [NSMutableDictionary dictionary];
+ [value_dictionary setObject:parameters forKey:@"parameters"];
+ [value_dictionary setObject:@"standard" forKey:@"type"];
+
+ NSMutableDictionary* outer_dictionary = [NSMutableDictionary dictionary];
+ [outer_dictionary setObject:value_dictionary forKey:@"value"];
+
+ NSNumber* enabled_number = [NSNumber numberWithBool:enabled];
+ [outer_dictionary setObject:enabled_number forKey:@"enabled"];
+
+ NSString* key = [NSString stringWithFormat:@"%d", count_];
+ [system_hotkey_inner_dictionary_ setObject:outer_dictionary forKey:key];
+ ++count_;
+ }
+
+ virtual void SetUp() override {
+ system_hotkey_dictionary_.reset([[NSMutableDictionary alloc] init]);
+ system_hotkey_inner_dictionary_.reset([[NSMutableDictionary alloc] init]);
+ [system_hotkey_dictionary_ setObject:system_hotkey_inner_dictionary_
+ forKey:@"AppleSymbolicHotKeys"];
+ count_ = 100;
+ }
+
+ virtual void TearDown() override {
+ system_hotkey_dictionary_.reset();
+ system_hotkey_inner_dictionary_.reset();
+ }
+
+ // A constructed dictionary that matches the format of the one that would be
+ // parsed from the system hotkeys plist.
+ base::scoped_nsobject<NSMutableDictionary> system_hotkey_dictionary_;
+
+ private:
+ // A reference to the mutable dictionary to which new entries are added.
+ base::scoped_nsobject<NSMutableDictionary> system_hotkey_inner_dictionary_;
+ // Each entry in the system_hotkey_inner_dictionary_ needs to have a unique
+ // key. This count is used to generate those unique keys.
+ int count_;
+};
+
+TEST_F(SystemHotkeyMapTest, Parse) {
+ // This plist was pulled from a real machine. It is extensively populated,
+ // and has no missing or incomplete entries.
+ NSData* data = DataFromTestFile("mac/mac_system_hotkeys.plist");
+ ASSERT_TRUE(data);
+
+ NSDictionary* dictionary = SystemHotkeyMap::DictionaryFromData(data);
+ ASSERT_TRUE(dictionary);
+
+ SystemHotkeyMap map;
+ bool result = map.ParseDictionary(dictionary);
+ EXPECT_TRUE(result);
+
+ // Command + ` is a common key binding. It should exist.
+ unsigned short key_code = kVK_ANSI_Grave;
+ NSUInteger modifiers = NSCommandKeyMask;
+ EXPECT_TRUE(map.IsHotkeyReserved(key_code, modifiers));
+
+ // Command + Shift + ` is a common key binding. It should exist.
+ modifiers = NSCommandKeyMask | NSShiftKeyMask;
+ EXPECT_TRUE(map.IsHotkeyReserved(key_code, modifiers));
+
+ // Command + Shift + Ctr + ` is not a common key binding.
+ modifiers = NSCommandKeyMask | NSShiftKeyMask | NSControlKeyMask;
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, modifiers));
+
+ // Command + L is not a common key binding.
+ key_code = kVK_ANSI_L;
+ modifiers = NSCommandKeyMask;
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, modifiers));
+}
+
+TEST_F(SystemHotkeyMapTest, ParseNil) {
+ NSDictionary* dictionary = nil;
+
+ SystemHotkeyMap map;
+ bool result = map.ParseDictionary(dictionary);
+ EXPECT_FALSE(result);
+}
+
+TEST_F(SystemHotkeyMapTest, ParseMouse) {
+ // This plist was pulled from a real machine. It has missing entries,
+ // incomplete entries, and mouse hotkeys.
+ NSData* data = DataFromTestFile("mac/mac_system_hotkeys_sparse.plist");
+ ASSERT_TRUE(data);
+
+ NSDictionary* dictionary = SystemHotkeyMap::DictionaryFromData(data);
+ ASSERT_TRUE(dictionary);
+
+ SystemHotkeyMap map;
+ bool result = map.ParseDictionary(dictionary);
+ EXPECT_TRUE(result);
+
+ // Command + ` is a common key binding. It is missing.
+ // TODO(erikchen): OSX uses the default value when the keybinding is missing,
+ // so the hotkey should still be reserved.
+ // http://crbug.com/383558
+ unsigned short key_code = kVK_ANSI_Grave;
+ NSUInteger modifiers = NSCommandKeyMask;
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, modifiers));
+
+ // There is a mouse keybinding for 0x08. It should not apply to keyboard
+ // hotkeys.
+ key_code = kVK_ANSI_C;
+ modifiers = 0;
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, modifiers));
+
+ // Command + Alt + = is an accessibility shortcut. Its entry in the plist is
+ // incomplete.
+ // TODO(erikchen): OSX uses the default bindings, so this hotkey should still
+ // be reserved.
+ // http://crbug.com/383558
+ key_code = kVK_ANSI_Equal;
+ modifiers = NSCommandKeyMask | NSAlternateKeyMask;
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, modifiers));
+}
+
+TEST_F(SystemHotkeyMapTest, ParseCustomEntries) {
+ unsigned short key_code = kVK_ANSI_C;
+
+ AddEntryToDictionary(YES, key_code, 0);
+ AddEntryToDictionary(YES, key_code, NSAlphaShiftKeyMask);
+ AddEntryToDictionary(YES, key_code, NSShiftKeyMask);
+ AddEntryToDictionary(YES, key_code, NSControlKeyMask);
+ AddEntryToDictionary(YES, key_code, NSFunctionKeyMask);
+ AddEntryToDictionary(YES, key_code, NSFunctionKeyMask | NSControlKeyMask);
+ AddEntryToDictionary(NO, key_code, NSAlternateKeyMask);
+
+ SystemHotkeyMap map;
+
+ bool result = map.ParseDictionary(system_hotkey_dictionary_.get());
+ EXPECT_TRUE(result);
+
+ // Entries without control, command, or alternate key mask should not be
+ // reserved.
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, 0));
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, NSAlphaShiftKeyMask));
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, NSShiftKeyMask));
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, NSFunctionKeyMask));
+
+ // Unlisted entries should not be reserved.
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, NSCommandKeyMask));
+
+ // Disabled entries should not be reserved.
+ EXPECT_FALSE(map.IsHotkeyReserved(key_code, NSAlternateKeyMask));
+
+ // Other entries should be reserved.
+ EXPECT_TRUE(map.IsHotkeyReserved(key_code, NSControlKeyMask));
+ EXPECT_TRUE(
+ map.IsHotkeyReserved(key_code, NSFunctionKeyMask | NSControlKeyMask));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/OWNERS b/chromium/content/browser/compositor/OWNERS
index 3b61cda8291..44b33c441b6 100644
--- a/chromium/content/browser/compositor/OWNERS
+++ b/chromium/content/browser/compositor/OWNERS
@@ -1,4 +1,3 @@
-piman@chromium.org
danakj@chromium.org
-sievers@chromium.org
jbauman@chromium.org
+ccameron@chromium.org
diff --git a/chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.h b/chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.h
new file mode 100644
index 00000000000..b342035ed5f
--- /dev/null
+++ b/chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.h
@@ -0,0 +1,136 @@
+// Copyright 2014 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 CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_CA_LAYER_TREE_MAC_H_
+#define CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_CA_LAYER_TREE_MAC_H_
+
+#include <IOSurface/IOSurfaceAPI.h>
+
+#include "content/browser/compositor/browser_compositor_view_mac.h"
+
+#if defined(__OBJC__)
+#include <Cocoa/Cocoa.h>
+#include "base/mac/scoped_nsobject.h"
+#include "content/browser/compositor/io_surface_layer_mac.h"
+#include "content/browser/compositor/software_layer_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+#endif // __OBJC__
+
+namespace content {
+
+#if defined(__OBJC__)
+
+// BrowserCompositorCALayerTreeMac owns tree of CALayer and a ui::Compositor
+// that is used to draw the layers. The CALayer tree can be attached to the
+// NSView of a BrowserCompositorViewMac
+class BrowserCompositorCALayerTreeMac
+ : public IOSurfaceLayerClient {
+ public:
+ BrowserCompositorCALayerTreeMac();
+ virtual ~BrowserCompositorCALayerTreeMac();
+ static BrowserCompositorCALayerTreeMac* FromAcceleratedWidget(
+ gfx::AcceleratedWidget widget);
+
+ void SetView(BrowserCompositorViewMac* view);
+ void ResetView();
+
+ ui::Compositor* compositor() const { return compositor_.get(); }
+
+ // Return true if the last frame swapped has a size in DIP of |dip_size|.
+ bool HasFrameOfSize(const gfx::Size& dip_size) const;
+
+ // Return the CGL renderer ID for the surface, if one is available.
+ int GetRendererID() const;
+
+ // Return true if the renderer should not be throttled by GPU back-pressure.
+ bool IsRendererThrottlingDisabled() const;
+
+ // Mark a bracket in which new frames are being pumped in a restricted nested
+ // run loop.
+ void BeginPumpingFrames();
+ void EndPumpingFrames();
+
+ void GotAcceleratedFrame(
+ uint64 surface_handle, int output_surface_id,
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::Size pixel_size, float scale_factor);
+
+ void GotSoftwareFrame(
+ cc::SoftwareFrameData* frame_data, float scale_factor, SkCanvas* canvas);
+
+private:
+ // IOSurfaceLayerClient implementation:
+ bool IOSurfaceLayerShouldAckImmediately() const override;
+ void IOSurfaceLayerDidDrawFrame() override;
+ void IOSurfaceLayerHitError() override;
+
+ void GotAcceleratedCAContextFrame(
+ CAContextID ca_context_id, gfx::Size pixel_size, float scale_factor);
+
+ void GotAcceleratedIOSurfaceFrame(
+ IOSurfaceID io_surface_id, gfx::Size pixel_size, float scale_factor);
+
+ // Remove a layer from the heirarchy and destroy it. Because the accelerated
+ // layer types may be replaced by a layer of the same type, the layer to
+ // destroy is parameterized, and, if it is the current layer, the current
+ // layer is reset.
+ void DestroyCAContextLayer(
+ base::scoped_nsobject<CALayerHost> ca_context_layer);
+ void DestroyIOSurfaceLayer(
+ base::scoped_nsobject<IOSurfaceLayer> io_surface_layer);
+ void DestroySoftwareLayer();
+
+ // The BrowserCompositorViewMac that is using this as its internals.
+ BrowserCompositorViewMac* view_;
+
+ // A phony NSView handle used to identify this.
+ gfx::AcceleratedWidget native_widget_;
+
+ // The compositor drawing the contents of this view.
+ scoped_ptr<ui::Compositor> compositor_;
+
+ // A flipped layer, which acts as the parent of the compositing and software
+ // layers. This layer is flipped so that the we don't need to recompute the
+ // origin for sub-layers when their position changes (this is impossible when
+ // using remote layers, as their size change cannot be synchronized with the
+ // window). This indirection is needed because flipping hosted layers (like
+ // |background_layer_| of RenderWidgetHostViewCocoa) leads to unpredictable
+ // behavior.
+ base::scoped_nsobject<CALayer> flipped_layer_;
+
+ // The accelerated CoreAnimation layer hosted by the GPU process.
+ base::scoped_nsobject<CALayerHost> ca_context_layer_;
+
+ // The locally drawn accelerated CoreAnimation layer.
+ base::scoped_nsobject<IOSurfaceLayer> io_surface_layer_;
+
+ // The locally drawn software layer.
+ base::scoped_nsobject<SoftwareLayer> software_layer_;
+
+ // The output surface and latency info of the last accelerated surface that
+ // was swapped. Sent back to the renderer when the accelerated surface is
+ // drawn.
+ int accelerated_output_surface_id_;
+ std::vector<ui::LatencyInfo> accelerated_latency_info_;
+
+ // The size in DIP of the last swap received from |compositor_|.
+ gfx::Size last_swap_size_dip_;
+};
+
+#endif // __OBJC__
+
+void BrowserCompositorCALayerTreeMacGotAcceleratedFrame(
+ gfx::AcceleratedWidget widget,
+ uint64 surface_handle, int surface_id,
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::Size pixel_size, float scale_factor,
+ bool* disable_throttling, int* renderer_id);
+
+void BrowserCompositorCALayerTreeMacGotSoftwareFrame(
+ gfx::AcceleratedWidget widget,
+ cc::SoftwareFrameData* frame_data, float scale_factor, SkCanvas* canvas);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_CA_LAYER_TREE_MAC_H_
diff --git a/chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.mm b/chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.mm
new file mode 100644
index 00000000000..3abee8cd763
--- /dev/null
+++ b/chromium/content/browser/compositor/browser_compositor_ca_layer_tree_mac.mm
@@ -0,0 +1,406 @@
+// Copyright 2014 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 "content/browser/compositor/browser_compositor_ca_layer_tree_mac.h"
+
+#include <map>
+
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/compositor/gpu_process_transport_factory.h"
+#include "content/browser/compositor/io_surface_layer_mac.h"
+#include "content/browser/compositor/software_layer_mac.h"
+#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/render_widget_resize_helper.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
+#include "content/public/browser/context_factory.h"
+#include "ui/base/cocoa/animation_utils.h"
+#include "ui/gl/scoped_cgl.h"
+
+namespace content {
+namespace {
+
+typedef std::map<gfx::AcceleratedWidget,BrowserCompositorCALayerTreeMac*>
+ WidgetToInternalsMap;
+base::LazyInstance<WidgetToInternalsMap> g_widget_to_internals_map;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BrowserCompositorCALayerTreeMac
+
+BrowserCompositorCALayerTreeMac::BrowserCompositorCALayerTreeMac()
+ : view_(NULL),
+ accelerated_output_surface_id_(0) {
+ // Disable the fade-in animation as the layers are added.
+ ScopedCAActionDisabler disabler;
+
+ // Add a flipped transparent layer as a child, so that we don't need to
+ // fiddle with the position of sub-layers -- they will always be at the
+ // origin.
+ flipped_layer_.reset([[CALayer alloc] init]);
+ [flipped_layer_ setGeometryFlipped:YES];
+ [flipped_layer_ setAnchorPoint:CGPointMake(0, 0)];
+ [flipped_layer_
+ setAutoresizingMask:kCALayerWidthSizable|kCALayerHeightSizable];
+
+ // Use a sequence number as the accelerated widget handle that we can use
+ // to look up the internals structure.
+ static uintptr_t last_sequence_number = 0;
+ last_sequence_number += 1;
+ native_widget_ = reinterpret_cast<gfx::AcceleratedWidget>(
+ last_sequence_number);
+ g_widget_to_internals_map.Pointer()->insert(
+ std::make_pair(native_widget_, this));
+
+ // Create a compositor to draw the contents of this view.
+ compositor_.reset(new ui::Compositor(
+ native_widget_,
+ content::GetContextFactory(),
+ RenderWidgetResizeHelper::Get()->task_runner()));
+ compositor_->SetVisible(false);
+}
+
+BrowserCompositorCALayerTreeMac::~BrowserCompositorCALayerTreeMac() {
+ DCHECK(!view_);
+ g_widget_to_internals_map.Pointer()->erase(native_widget_);
+}
+
+void BrowserCompositorCALayerTreeMac::SetView(
+ BrowserCompositorViewMac* view) {
+ // Disable the fade-in animation as the view is added.
+ ScopedCAActionDisabler disabler;
+
+ DCHECK(view && !view_);
+ view_ = view;
+ compositor_->SetRootLayer(view_->ui_root_layer());
+
+ CALayer* background_layer = [view_->native_view() layer];
+ DCHECK(background_layer);
+ [flipped_layer_ setBounds:[background_layer bounds]];
+ [background_layer addSublayer:flipped_layer_];
+ compositor_->SetVisible(true);
+}
+
+void BrowserCompositorCALayerTreeMac::ResetView() {
+ if (!view_)
+ return;
+
+ // Disable the fade-out animation as the view is removed.
+ ScopedCAActionDisabler disabler;
+
+ [flipped_layer_ removeFromSuperlayer];
+ DestroyIOSurfaceLayer(io_surface_layer_);
+ DestroyCAContextLayer(ca_context_layer_);
+ DestroySoftwareLayer();
+
+ accelerated_output_surface_id_ = 0;
+ last_swap_size_dip_ = gfx::Size();
+
+ compositor_->SetVisible(false);
+ compositor_->SetScaleAndSize(1.0, gfx::Size(0, 0));
+ compositor_->SetRootLayer(NULL);
+ view_ = NULL;
+}
+
+bool BrowserCompositorCALayerTreeMac::HasFrameOfSize(
+ const gfx::Size& dip_size) const {
+ return last_swap_size_dip_ == dip_size;
+}
+
+int BrowserCompositorCALayerTreeMac::GetRendererID() const {
+ if (io_surface_layer_)
+ return [io_surface_layer_ rendererID];
+ return 0;
+}
+
+bool BrowserCompositorCALayerTreeMac::IsRendererThrottlingDisabled() const {
+ if (view_)
+ return view_->client()->BrowserCompositorViewShouldAckImmediately();
+ return false;
+}
+
+void BrowserCompositorCALayerTreeMac::BeginPumpingFrames() {
+ [io_surface_layer_ beginPumpingFrames];
+}
+
+void BrowserCompositorCALayerTreeMac::EndPumpingFrames() {
+ [io_surface_layer_ endPumpingFrames];
+}
+
+void BrowserCompositorCALayerTreeMac::GotAcceleratedFrame(
+ uint64 surface_handle, int output_surface_id,
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::Size pixel_size, float scale_factor) {
+ // Record the surface and latency info to use when acknowledging this frame.
+ DCHECK(!accelerated_output_surface_id_);
+ accelerated_output_surface_id_ = output_surface_id;
+ accelerated_latency_info_.insert(accelerated_latency_info_.end(),
+ latency_info.begin(), latency_info.end());
+
+ // If there is no view and therefore no superview to draw into, early-out.
+ if (!view_) {
+ IOSurfaceLayerDidDrawFrame();
+ return;
+ }
+
+ // Disable the fade-in or fade-out effect if we create or remove layers.
+ ScopedCAActionDisabler disabler;
+
+ last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size);
+ switch (GetSurfaceHandleType(surface_handle)) {
+ case kSurfaceHandleTypeIOSurface: {
+ IOSurfaceID io_surface_id = IOSurfaceIDFromSurfaceHandle(surface_handle);
+ GotAcceleratedIOSurfaceFrame(io_surface_id, pixel_size, scale_factor);
+ break;
+ }
+ case kSurfaceHandleTypeCAContext: {
+ CAContextID ca_context_id = CAContextIDFromSurfaceHandle(surface_handle);
+ GotAcceleratedCAContextFrame(ca_context_id, pixel_size, scale_factor);
+ break;
+ }
+ default:
+ LOG(ERROR) << "Unrecognized accelerated frame type.";
+ return;
+ }
+}
+
+void BrowserCompositorCALayerTreeMac::GotAcceleratedCAContextFrame(
+ CAContextID ca_context_id,
+ gfx::Size pixel_size,
+ float scale_factor) {
+ // In the layer is replaced, keep the old one around until after the new one
+ // is installed to avoid flashes.
+ base::scoped_nsobject<CALayerHost> old_ca_context_layer =
+ ca_context_layer_;
+
+ // Create the layer to host the layer exported by the GPU process with this
+ // particular CAContext ID.
+ if ([ca_context_layer_ contextId] != ca_context_id) {
+ ca_context_layer_.reset([[CALayerHost alloc] init]);
+ [ca_context_layer_ setContextId:ca_context_id];
+ [ca_context_layer_
+ setAutoresizingMask:kCALayerMaxXMargin|kCALayerMaxYMargin];
+ [flipped_layer_ addSublayer:ca_context_layer_];
+ }
+
+ // Acknowledge the frame to unblock the compositor immediately (the GPU
+ // process will do any required throttling).
+ IOSurfaceLayerDidDrawFrame();
+
+ // If this replacing a same-type layer, remove it now that the new layer is
+ // in the hierarchy.
+ if (old_ca_context_layer != ca_context_layer_)
+ DestroyCAContextLayer(old_ca_context_layer);
+
+ // Remove any different-type layers that this is replacing.
+ DestroyIOSurfaceLayer(io_surface_layer_);
+ DestroySoftwareLayer();
+}
+
+void BrowserCompositorCALayerTreeMac::GotAcceleratedIOSurfaceFrame(
+ IOSurfaceID io_surface_id,
+ gfx::Size pixel_size,
+ float scale_factor) {
+ // In the layer is replaced, keep the old one around until after the new one
+ // is installed to avoid flashes.
+ base::scoped_nsobject<IOSurfaceLayer> old_io_surface_layer =
+ io_surface_layer_;
+
+ // Create or re-create an IOSurface layer if needed. If there already exists
+ // a layer but it has the wrong scale factor or it was poisoned, re-create the
+ // layer.
+ bool needs_new_layer =
+ !io_surface_layer_ ||
+ [io_surface_layer_ hasBeenPoisoned] ||
+ [io_surface_layer_ scaleFactor] != scale_factor;
+ if (needs_new_layer) {
+ io_surface_layer_.reset(
+ [[IOSurfaceLayer alloc] initWithClient:this
+ withScaleFactor:scale_factor]);
+ if (io_surface_layer_)
+ [flipped_layer_ addSublayer:io_surface_layer_];
+ else
+ LOG(ERROR) << "Failed to create IOSurfaceLayer";
+ }
+
+ // Open the provided IOSurface.
+ if (io_surface_layer_) {
+ bool result = [io_surface_layer_ gotFrameWithIOSurface:io_surface_id
+ withPixelSize:pixel_size
+ withScaleFactor:scale_factor];
+ if (!result) {
+ DestroyIOSurfaceLayer(io_surface_layer_);
+ LOG(ERROR) << "Failed open IOSurface in IOSurfaceLayer";
+ }
+ }
+
+ // Give a final complaint if anything with the layer's creation went wrong.
+ // This frame will appear blank, the compositor will try to create another,
+ // and maybe that will go better.
+ if (!io_surface_layer_) {
+ LOG(ERROR) << "IOSurfaceLayer is nil, tab will be blank";
+ IOSurfaceLayerHitError();
+ }
+
+ // Make the CALayer draw and set its size appropriately.
+ if (io_surface_layer_) {
+ [io_surface_layer_ gotNewFrame];
+
+ // Set the bounds of the accelerated layer to match the size of the frame.
+ // If the bounds changed, force the content to be displayed immediately.
+ CGRect new_layer_bounds = CGRectMake(
+ 0, 0, last_swap_size_dip_.width(), last_swap_size_dip_.height());
+ bool bounds_changed = !CGRectEqualToRect(
+ new_layer_bounds, [io_surface_layer_ bounds]);
+ [io_surface_layer_ setBounds:new_layer_bounds];
+ if (bounds_changed)
+ [io_surface_layer_ setNeedsDisplayAndDisplayAndAck];
+ }
+
+ // If this replacing a same-type layer, remove it now that the new layer is
+ // in the hierarchy.
+ if (old_io_surface_layer != io_surface_layer_)
+ DestroyIOSurfaceLayer(old_io_surface_layer);
+
+ // Remove any different-type layers that this is replacing.
+ DestroyCAContextLayer(ca_context_layer_);
+ DestroySoftwareLayer();
+}
+
+void BrowserCompositorCALayerTreeMac::GotSoftwareFrame(
+ cc::SoftwareFrameData* frame_data,
+ float scale_factor,
+ SkCanvas* canvas) {
+ if (!frame_data || !canvas || !view_)
+ return;
+
+ // Disable the fade-in or fade-out effect if we create or remove layers.
+ ScopedCAActionDisabler disabler;
+
+ // If there is not a layer for software frames, create one.
+ if (!software_layer_) {
+ software_layer_.reset([[SoftwareLayer alloc] init]);
+ [flipped_layer_ addSublayer:software_layer_];
+ }
+
+ // Set the software layer to draw the provided canvas.
+ SkImageInfo info;
+ size_t row_bytes;
+ const void* pixels = canvas->peekPixels(&info, &row_bytes);
+ gfx::Size pixel_size(info.fWidth, info.fHeight);
+ [software_layer_ setContentsToData:pixels
+ withRowBytes:row_bytes
+ withPixelSize:pixel_size
+ withScaleFactor:scale_factor];
+ last_swap_size_dip_ = ConvertSizeToDIP(scale_factor, pixel_size);
+
+ // Remove any different-type layers that this is replacing.
+ DestroyCAContextLayer(ca_context_layer_);
+ DestroyIOSurfaceLayer(io_surface_layer_);
+}
+
+void BrowserCompositorCALayerTreeMac::DestroyCAContextLayer(
+ base::scoped_nsobject<CALayerHost> ca_context_layer) {
+ if (!ca_context_layer)
+ return;
+ [ca_context_layer removeFromSuperlayer];
+ if (ca_context_layer == ca_context_layer_)
+ ca_context_layer_.reset();
+}
+
+void BrowserCompositorCALayerTreeMac::DestroyIOSurfaceLayer(
+ base::scoped_nsobject<IOSurfaceLayer> io_surface_layer) {
+ if (!io_surface_layer)
+ return;
+ [io_surface_layer resetClient];
+ [io_surface_layer removeFromSuperlayer];
+ if (io_surface_layer == io_surface_layer_)
+ io_surface_layer_.reset();
+}
+
+void BrowserCompositorCALayerTreeMac::DestroySoftwareLayer() {
+ if (!software_layer_)
+ return;
+ [software_layer_ removeFromSuperlayer];
+ software_layer_.reset();
+}
+
+bool BrowserCompositorCALayerTreeMac::IOSurfaceLayerShouldAckImmediately()
+ const {
+ // If there is no view then the accelerated layer is not in the hierarchy
+ // and will never draw.
+ if (!view_)
+ return true;
+ return view_->client()->BrowserCompositorViewShouldAckImmediately();
+}
+
+void BrowserCompositorCALayerTreeMac::IOSurfaceLayerDidDrawFrame() {
+ if (accelerated_output_surface_id_) {
+ content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed(
+ accelerated_output_surface_id_);
+ accelerated_output_surface_id_ = 0;
+ }
+
+ if (view_) {
+ view_->client()->BrowserCompositorViewFrameSwapped(
+ accelerated_latency_info_);
+ }
+
+ accelerated_latency_info_.clear();
+}
+
+void BrowserCompositorCALayerTreeMac::IOSurfaceLayerHitError() {
+ // Perform all acks that would have been done if the frame had succeeded, to
+ // un-block the compositor and renderer.
+ IOSurfaceLayerDidDrawFrame();
+
+ // Poison the context being used and request a mulligan.
+ [io_surface_layer_ poisonContextAndSharegroup];
+ compositor_->ScheduleFullRedraw();
+}
+
+// static
+BrowserCompositorCALayerTreeMac* BrowserCompositorCALayerTreeMac::
+ FromAcceleratedWidget(gfx::AcceleratedWidget widget) {
+ WidgetToInternalsMap::const_iterator found =
+ g_widget_to_internals_map.Pointer()->find(widget);
+ // This can end up being accessed after the underlying widget has been
+ // destroyed, but while the ui::Compositor is still being destroyed.
+ // Return NULL in these cases.
+ if (found == g_widget_to_internals_map.Pointer()->end())
+ return NULL;
+ return found->second;
+}
+
+void BrowserCompositorCALayerTreeMacGotAcceleratedFrame(
+ gfx::AcceleratedWidget widget,
+ uint64 surface_handle, int surface_id,
+ const std::vector<ui::LatencyInfo>& latency_info,
+ gfx::Size pixel_size, float scale_factor,
+ bool* disable_throttling, int* renderer_id) {
+ BrowserCompositorCALayerTreeMac* ca_layer_tree =
+ BrowserCompositorCALayerTreeMac::FromAcceleratedWidget(widget);
+ if (ca_layer_tree) {
+ ca_layer_tree->GotAcceleratedFrame(
+ surface_handle, surface_id, latency_info, pixel_size, scale_factor);
+ *disable_throttling = ca_layer_tree->IsRendererThrottlingDisabled();
+ *renderer_id = ca_layer_tree->GetRendererID();
+ } else {
+ *disable_throttling = false;
+ *renderer_id = 0;
+ }
+}
+
+void BrowserCompositorCALayerTreeMacGotSoftwareFrame(
+ gfx::AcceleratedWidget widget,
+ cc::SoftwareFrameData* frame_data, float scale_factor, SkCanvas* canvas) {
+ BrowserCompositorCALayerTreeMac* ca_layer_tree =
+ BrowserCompositorCALayerTreeMac::FromAcceleratedWidget(widget);
+ if (ca_layer_tree)
+ ca_layer_tree->GotSoftwareFrame(frame_data, scale_factor, canvas);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.cc b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
index 40576b2aeaf..0c650ca9f3e 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.cc
@@ -5,12 +5,10 @@
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/location.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "ui/compositor/compositor_switches.h"
namespace content {
@@ -40,9 +38,9 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
DCHECK(CalledOnValidThread());
- if (reflector_)
+ if (reflector_.get())
reflector_->DetachFromOutputSurface();
- DCHECK(!reflector_);
+ DCHECK(!reflector_.get());
if (!HasClient())
return;
output_surface_map_->Remove(surface_id_);
@@ -64,20 +62,12 @@ bool BrowserCompositorOutputSurface::BindToClient(
return false;
output_surface_map_->AddWithID(this, surface_id_);
- if (reflector_)
+ if (reflector_.get())
reflector_->OnSourceSurfaceReady(this);
vsync_manager_->AddObserver(this);
return true;
}
-void BrowserCompositorOutputSurface::OnSwapBuffersComplete() {
- // On Mac, delay acknowledging the swap to the output surface client until
- // it has been drawn.
-#if !defined(OS_MACOSX)
- cc::OutputSurface::OnSwapBuffersComplete();
-#endif
-}
-
void BrowserCompositorOutputSurface::OnUpdateVSyncParameters(
base::TimeTicks timebase,
base::TimeDelta interval) {
@@ -98,10 +88,4 @@ void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) {
reflector_ = reflector;
}
-#if defined(OS_MACOSX)
-void BrowserCompositorOutputSurface::OnSurfaceDisplayed() {
- cc::OutputSurface::OnSwapBuffersComplete();
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index e622f41c497..dd538769e76 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -25,15 +25,14 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
public ui::CompositorVSyncManager::Observer,
public base::NonThreadSafe {
public:
- virtual ~BrowserCompositorOutputSurface();
+ ~BrowserCompositorOutputSurface() override;
// cc::OutputSurface implementation.
- virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
- virtual void OnSwapBuffersComplete() OVERRIDE;
+ bool BindToClient(cc::OutputSurfaceClient* client) override;
// ui::CompositorOutputSurface::Observer implementation.
- virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE;
+ void OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) override;
void OnUpdateVSyncParametersFromGpu(base::TimeTicks tiembase,
base::TimeDelta interval);
@@ -41,7 +40,7 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
void SetReflector(ReflectorImpl* reflector);
#if defined(OS_MACOSX)
- void OnSurfaceDisplayed();
+ virtual void OnSurfaceDisplayed() = 0;
#endif
protected:
diff --git a/chromium/content/browser/compositor/browser_compositor_view_mac.h b/chromium/content/browser/compositor/browser_compositor_view_mac.h
index 5d22b873dae..619aef55edd 100644
--- a/chromium/content/browser/compositor/browser_compositor_view_mac.h
+++ b/chromium/content/browser/compositor/browser_compositor_view_mac.h
@@ -5,60 +5,87 @@
#ifndef CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_VIEW_MAC_H_
#define CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_VIEW_MAC_H_
-#import <Cocoa/Cocoa.h>
-#include <IOSurface/IOSurfaceAPI.h>
+#include <vector>
-#include "base/mac/scoped_nsobject.h"
#include "cc/output/software_frame_data.h"
-#include "content/browser/renderer_host/compositing_iosurface_layer_mac.h"
-#include "content/browser/renderer_host/software_layer_mac.h"
#include "skia/ext/platform_canvas.h"
#include "ui/compositor/compositor.h"
+#include "ui/events/latency_info.h"
#include "ui/gfx/geometry/size.h"
namespace content {
-class BrowserCompositorViewMacHelper;
-} // namespace content
-// Additions to the NSView interface for compositor frames.
-@interface NSView (BrowserCompositorView)
-- (void)gotAcceleratedIOSurfaceFrame:(IOSurfaceID)surface_handle
- withOutputSurfaceID:(int)surface_id
- withPixelSize:(gfx::Size)pixel_size
- withScaleFactor:(float)scale_factor;
-
-- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
- withScaleFactor:(float)scale_factor
- withCanvas:(SkCanvas*)canvas;
-@end // NSView (BrowserCompositorView)
-
-// NSView drawn by a ui::Compositor. The superview of this view is responsible
-// for changing the ui::Compositor SizeAndScale and calling layoutLayers when
-// the size of the parent view may change. This interface is patterned after
-// the needs of RenderWidgetHostViewCocoa, and could change.
-@interface BrowserCompositorViewMac : NSView {
- scoped_ptr<ui::Compositor> compositor_;
-
- base::scoped_nsobject<CALayer> background_layer_;
- base::scoped_nsobject<CompositingIOSurfaceLayer> accelerated_layer_;
- int accelerated_layer_output_surface_id_;
- base::scoped_nsobject<SoftwareLayer> software_layer_;
-
- scoped_ptr<content::BrowserCompositorViewMacHelper> helper_;
-}
-
-// Initialize to render the content of a specific superview.
-- (id)initWithSuperview:(NSView*)view;
-
-// Re-position the layers to the correct place when this view's superview
-// changes size, or when the accelerated or software content changes.
-- (void)layoutLayers;
-
-// Disallow further access to the client.
-- (void)resetClient;
-
-// Access the underlying ui::Compositor for this view.
-- (ui::Compositor*)compositor;
-@end // BrowserCompositorViewMac
+class BrowserCompositorCALayerTreeMac;
+
+// The interface through which BrowserCompositorViewMac calls back into
+// RenderWidgetHostViewMac (or any other structure that wishes to draw a
+// NSView backed by a ui::Compositor).
+// TODO(ccameron): This interface should be in the ui namespace.
+class BrowserCompositorViewMacClient {
+ public:
+ // Drawing is usually throttled by the rate at which CoreAnimation draws
+ // frames to the screen. This can be used to disable throttling.
+ virtual bool BrowserCompositorViewShouldAckImmediately() const = 0;
+
+ // Called when a frame is drawn, and used to pass latency info back to the
+ // renderer (if any).
+ virtual void BrowserCompositorViewFrameSwapped(
+ const std::vector<ui::LatencyInfo>& latency_info) = 0;
+};
+
+// The class to hold the ui::Compositor which is used to draw a NSView.
+// TODO(ccameron): This should implement an interface in the ui namespace.
+class BrowserCompositorViewMac {
+ public:
+ // This will install the NSView which is drawn by the ui::Compositor into
+ // the NSView provided by the client. Note that |client|, |native_view|, and
+ // |ui_root_layer| outlive their BrowserCompositorViewMac object.
+ BrowserCompositorViewMac(
+ BrowserCompositorViewMacClient* client,
+ NSView* native_view,
+ ui::Layer* ui_root_layer);
+ ~BrowserCompositorViewMac();
+
+ BrowserCompositorViewMacClient* client() const { return client_; }
+ NSView* native_view() const { return native_view_; }
+ ui::Layer* ui_root_layer() const { return ui_root_layer_; }
+
+ // The ui::Compositor being used to render the NSView.
+ // TODO(ccameron): This should be in the ui namespace interface.
+ ui::Compositor* GetCompositor() const;
+
+ // Return true if the last frame swapped has a size in DIP of |dip_size|.
+ bool HasFrameOfSize(const gfx::Size& dip_size) const;
+
+ // Mark a bracket in which new frames are pumped in a restricted nested run
+ // loop because the the target window is resizing or because the view is being
+ // shown after previously being hidden.
+ void BeginPumpingFrames();
+ void EndPumpingFrames();
+
+ private:
+ BrowserCompositorViewMacClient* client_;
+ NSView* native_view_;
+ ui::Layer* ui_root_layer_;
+
+ // Because a ui::Compositor is expensive in terms of resources and
+ // re-allocating a ui::Compositor is expensive in terms of work, this class
+ // is largely used to manage recycled instances of
+ // BrowserCompositorCALayerTreeMac, which actually has a ui::Compositor
+ // instance and modifies the CALayers used to draw the NSView.
+ scoped_ptr<BrowserCompositorCALayerTreeMac> ca_layer_tree_;
+};
+
+// A class to keep around whenever a BrowserCompositorViewMac may be created.
+// While at least one instance of this class exists, a spare
+// BrowserCompositorViewCocoa will be kept around to be recycled so that the
+// next BrowserCompositorViewMac to be created will be be created quickly.
+class BrowserCompositorViewPlaceholderMac {
+ public:
+ BrowserCompositorViewPlaceholderMac();
+ ~BrowserCompositorViewPlaceholderMac();
+};
+
+} // namespace content
#endif // CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_VIEW_MAC_H_
diff --git a/chromium/content/browser/compositor/browser_compositor_view_mac.mm b/chromium/content/browser/compositor/browser_compositor_view_mac.mm
index 0a89e691075..b38edce89ae 100644
--- a/chromium/content/browser/compositor/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/compositor/browser_compositor_view_mac.mm
@@ -5,252 +5,94 @@
#include "content/browser/compositor/browser_compositor_view_mac.h"
#include "base/debug/trace_event.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "content/browser/compositor/gpu_process_transport_factory.h"
-#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_mac.h"
-#include "content/browser/renderer_host/software_layer_mac.h"
-#include "content/public/browser/context_factory.h"
-#include "ui/base/cocoa/animation_utils.h"
-#include "ui/gl/scoped_cgl.h"
+#include "base/lazy_instance.h"
+#include "content/browser/gpu/gpu_process_host_ui_shim.h"
+#include "content/browser/compositor/browser_compositor_ca_layer_tree_mac.h"
+#include "content/common/gpu/gpu_messages.h"
-@interface BrowserCompositorViewMac (Private)
-- (void)layerDidDrawFrame;
-- (void)gotAcceleratedLayerError;
-@end // BrowserCompositorViewMac (Private)
+////////////////////////////////////////////////////////////////////////////////
+// BrowserCompositorViewMac
namespace content {
-
-// The CompositingIOSurfaceLayerClient interface needs to be implemented as a
-// C++ class to operate on, rather than Objective C class. This helper class
-// provides a bridge between the two.
-class BrowserCompositorViewMacHelper : public CompositingIOSurfaceLayerClient {
- public:
- BrowserCompositorViewMacHelper(BrowserCompositorViewMac* view)
- : view_(view) {}
- virtual ~BrowserCompositorViewMacHelper() {}
-
- private:
- // CompositingIOSurfaceLayerClient implementation:
- virtual void AcceleratedLayerDidDrawFrame(bool succeeded) OVERRIDE {
- [view_ layerDidDrawFrame];
- if (!succeeded)
- [view_ gotAcceleratedLayerError];
- }
-
- BrowserCompositorViewMac* view_;
-};
-
-} // namespace content
-
-
-// The default implementation of additions to the NSView interface for browser
-// compositing should never be called. Log an error if they are.
-@implementation NSView (BrowserCompositorView)
-
-- (void)gotAcceleratedIOSurfaceFrame:(IOSurfaceID)surface_handle
- withOutputSurfaceID:(int)surface_id
- withPixelSize:(gfx::Size)pixel_size
- withScaleFactor:(float)scale_factor {
- DLOG(ERROR) << "-[NSView gotAcceleratedIOSurfaceFrame] called on "
- << "non-overriden class.";
-}
-
-- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
- withScaleFactor:(float)scale_factor
- withCanvas:(SkCanvas*)canvas {
- DLOG(ERROR) << "-[NSView gotSoftwareFrame] called on non-overridden class.";
-}
-
-@end // NSView (BrowserCompositorView)
-
-@implementation BrowserCompositorViewMac : NSView
-
-- (id)initWithSuperview:(NSView*)view {
- if (self = [super init]) {
- accelerated_layer_output_surface_id_ = 0;
- helper_.reset(new content::BrowserCompositorViewMacHelper(self));
-
- // Disable the fade-in animation as the layer and view are added.
- ScopedCAActionDisabler disabler;
-
- // Make this view host a transparent layer.
- background_layer_.reset([[CALayer alloc] init]);
- [background_layer_ setContentsGravity:kCAGravityTopLeft];
- [self setLayer:background_layer_];
- [self setWantsLayer:YES];
-
- compositor_.reset(new ui::Compositor(self, content::GetContextFactory()));
- [view addSubview:self];
- }
- return self;
+namespace {
+
+// The number of placeholder objects allocated. If this reaches zero, then
+// the BrowserCompositorCALayerTreeMac being held on to for recycling,
+// |g_recyclable_ca_layer_tree|, will be freed.
+uint32 g_placeholder_count = 0;
+
+// A spare BrowserCompositorCALayerTreeMac kept around for recycling.
+base::LazyInstance<scoped_ptr<BrowserCompositorCALayerTreeMac>>
+ g_recyclable_ca_layer_tree;
+
+} // namespace
+
+BrowserCompositorViewMac::BrowserCompositorViewMac(
+ BrowserCompositorViewMacClient* client,
+ NSView* native_view,
+ ui::Layer* ui_root_layer)
+ : client_(client),
+ native_view_(native_view),
+ ui_root_layer_(ui_root_layer) {
+ // Try to use the recyclable BrowserCompositorCALayerTreeMac if there is one,
+ // otherwise allocate a new one.
+ // TODO(ccameron): If there exists a frame in flight (swap has been called
+ // by the compositor, but the frame has not arrived from the GPU process
+ // yet), then that frame may inappropriately flash in the new view.
+ ca_layer_tree_ = g_recyclable_ca_layer_tree.Get().Pass();
+ if (!ca_layer_tree_)
+ ca_layer_tree_.reset(new BrowserCompositorCALayerTreeMac);
+ ca_layer_tree_->SetView(this);
}
-- (void)gotAcceleratedLayerError {
- if (!accelerated_layer_)
- return;
+BrowserCompositorViewMac::~BrowserCompositorViewMac() {
+ // Make this BrowserCompositorCALayerTreeMac recyclable for future instances.
+ ca_layer_tree_->ResetView();
+ g_recyclable_ca_layer_tree.Get() = ca_layer_tree_.Pass();
- [accelerated_layer_ context]->PoisonContextAndSharegroup();
- compositor_->ScheduleFullRedraw();
+ // If there are no placeholders allocated, destroy the recyclable
+ // BrowserCompositorCALayerTreeMac that we just populated.
+ if (!g_placeholder_count)
+ g_recyclable_ca_layer_tree.Get().reset();
}
-// This function closely mirrors RenderWidgetHostViewMac::LayoutLayers. When
-// only delegated rendering is supported, only one copy of this code will
-// need to exist.
-- (void)layoutLayers {
- // Disable animation of the layers' resizing or repositioning.
- ScopedCAActionDisabler disabler;
-
- NSSize superview_frame_size = [[self superview] frame].size;
- [self setFrame:NSMakeRect(
- 0, 0, superview_frame_size.width, superview_frame_size.height)];
-
- CGRect new_background_frame = CGRectMake(
- 0,
- 0,
- superview_frame_size.width,
- superview_frame_size.height);
- [background_layer_ setFrame:new_background_frame];
-
- // The bounds of the accelerated layer determine the size of the GL surface
- // that will be drawn to. Make sure that this is big enough to draw the
- // IOSurface.
- if (accelerated_layer_) {
- CGRect layer_bounds = CGRectMake(
- 0,
- 0,
- [accelerated_layer_ iosurface]->dip_io_surface_size().width(),
- [accelerated_layer_ iosurface]->dip_io_surface_size().height());
- CGPoint layer_position = CGPointMake(
- 0,
- CGRectGetHeight(new_background_frame) - CGRectGetHeight(layer_bounds));
- bool bounds_changed = !CGRectEqualToRect(
- layer_bounds, [accelerated_layer_ bounds]);
- [accelerated_layer_ setBounds:layer_bounds];
- [accelerated_layer_ setPosition:layer_position];
- if (bounds_changed) {
- [accelerated_layer_ setNeedsDisplay];
- [accelerated_layer_ displayIfNeeded];
- }
- }
-
- // The content area of the software layer is the size of the image provided.
- // Make the bounds of the layer match the superview's bounds, to ensure that
- // the visible contents are drawn.
- [software_layer_ setBounds:new_background_frame];
+ui::Compositor* BrowserCompositorViewMac::GetCompositor() const {
+ DCHECK(ca_layer_tree_);
+ return ca_layer_tree_->compositor();
}
-- (void)resetClient {
- [accelerated_layer_ resetClient];
+bool BrowserCompositorViewMac::HasFrameOfSize(
+ const gfx::Size& dip_size) const {
+ if (ca_layer_tree_)
+ return ca_layer_tree_->HasFrameOfSize(dip_size);
+ return false;
}
-- (ui::Compositor*)compositor {
- return compositor_.get();
+void BrowserCompositorViewMac::BeginPumpingFrames() {
+ if (ca_layer_tree_)
+ ca_layer_tree_->BeginPumpingFrames();
}
-- (void)gotAcceleratedIOSurfaceFrame:(IOSurfaceID)surface_handle
- withOutputSurfaceID:(int)surface_id
- withPixelSize:(gfx::Size)pixel_size
- withScaleFactor:(float)scale_factor {
- DCHECK(!accelerated_layer_output_surface_id_);
- accelerated_layer_output_surface_id_ = surface_id;
-
- ScopedCAActionDisabler disabler;
-
- // If there is already an accelerated layer, but it has the wrong scale
- // factor or it was poisoned, remove the old layer and replace it.
- base::scoped_nsobject<CompositingIOSurfaceLayer> old_accelerated_layer;
- if (accelerated_layer_ && (
- [accelerated_layer_ context]->HasBeenPoisoned() ||
- [accelerated_layer_ iosurface]->scale_factor() != scale_factor)) {
- old_accelerated_layer = accelerated_layer_;
- accelerated_layer_.reset();
- }
-
- // If there is not a layer for accelerated frames, create one.
- if (!accelerated_layer_) {
- // Disable the fade-in animation as the layer is added.
- ScopedCAActionDisabler disabler;
- scoped_refptr<content::CompositingIOSurfaceMac> iosurface =
- content::CompositingIOSurfaceMac::Create();
- accelerated_layer_.reset([[CompositingIOSurfaceLayer alloc]
- initWithIOSurface:iosurface
- withScaleFactor:scale_factor
- withClient:helper_.get()]);
- [[self layer] addSublayer:accelerated_layer_];
- }
-
- {
- bool result = true;
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- [accelerated_layer_ context]->cgl_context());
- result = [accelerated_layer_ iosurface]->SetIOSurfaceWithContextCurrent(
- [accelerated_layer_ context], surface_handle, pixel_size, scale_factor);
- if (!result)
- LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
- }
- [accelerated_layer_ gotNewFrame];
- [self layoutLayers];
-
- // If there was a software layer or an old accelerated layer, remove it.
- // Disable the fade-out animation as the layer is removed.
- {
- ScopedCAActionDisabler disabler;
- [software_layer_ removeFromSuperlayer];
- software_layer_.reset();
- [old_accelerated_layer resetClient];
- [old_accelerated_layer removeFromSuperlayer];
- old_accelerated_layer.reset();
- }
+void BrowserCompositorViewMac::EndPumpingFrames() {
+ if (ca_layer_tree_)
+ ca_layer_tree_->EndPumpingFrames();
}
-- (void)gotSoftwareFrame:(cc::SoftwareFrameData*)frame_data
- withScaleFactor:(float)scale_factor
- withCanvas:(SkCanvas*)canvas {
- if (!frame_data || !canvas)
- return;
-
- // If there is not a layer for software frames, create one.
- if (!software_layer_) {
- // Disable the fade-in animation as the layer is added.
- ScopedCAActionDisabler disabler;
- software_layer_.reset([[SoftwareLayer alloc] init]);
- [[self layer] addSublayer:software_layer_];
- }
+////////////////////////////////////////////////////////////////////////////////
+// BrowserCompositorViewPlaceholderMac
- SkImageInfo info;
- size_t row_bytes;
- const void* pixels = canvas->peekPixels(&info, &row_bytes);
- [software_layer_ setContentsToData:pixels
- withRowBytes:row_bytes
- withPixelSize:gfx::Size(info.fWidth, info.fHeight)
- withScaleFactor:scale_factor];
- [self layoutLayers];
-
- // If there was an accelerated layer, remove it.
- // Disable the fade-out animation as the layer is removed.
- {
- ScopedCAActionDisabler disabler;
- [accelerated_layer_ resetClient];
- [accelerated_layer_ removeFromSuperlayer];
- accelerated_layer_.reset();
- }
-
- // This call can be nested insider ui::Compositor commit calls, and can also
- // make additional ui::Compositor commit calls. Avoid the potential recursion
- // by acknowledging the frame asynchronously.
- [self performSelector:@selector(layerDidDrawFrame)
- withObject:nil
- afterDelay:0];
+BrowserCompositorViewPlaceholderMac::BrowserCompositorViewPlaceholderMac() {
+ g_placeholder_count += 1;
}
-- (void)layerDidDrawFrame {
- if (!accelerated_layer_output_surface_id_)
- return;
+BrowserCompositorViewPlaceholderMac::~BrowserCompositorViewPlaceholderMac() {
+ DCHECK_GT(g_placeholder_count, 0u);
+ g_placeholder_count -= 1;
- content::ImageTransportFactory::GetInstance()->OnSurfaceDisplayed(
- accelerated_layer_output_surface_id_);
- accelerated_layer_output_surface_id_ = 0;
+ // If there are no placeholders allocated, destroy the recyclable
+ // BrowserCompositorCALayerTreeMac.
+ if (!g_placeholder_count)
+ g_recyclable_ca_layer_tree.Get().reset();
}
-@end // BrowserCompositorViewMac
+} // namespace content
diff --git a/chromium/content/browser/compositor/buffer_queue.cc b/chromium/content/browser/compositor/buffer_queue.cc
new file mode 100644
index 00000000000..ebb01658ccb
--- /dev/null
+++ b/chromium/content/browser/compositor/buffer_queue.cc
@@ -0,0 +1,176 @@
+// Copyright 2014 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 "content/browser/compositor/buffer_queue.h"
+
+#include "content/browser/compositor/image_transport_factory.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/gpu/client/gl_helper.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkRegion.h"
+
+namespace content {
+
+BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider,
+ unsigned int internalformat,
+ GLHelper* gl_helper)
+ : context_provider_(context_provider),
+ fbo_(0),
+ allocated_count_(0),
+ internalformat_(internalformat),
+ gl_helper_(gl_helper) {
+}
+
+BufferQueue::~BufferQueue() {
+ FreeAllSurfaces();
+
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ if (fbo_)
+ gl->DeleteFramebuffers(1, &fbo_);
+}
+
+bool BufferQueue::Initialize() {
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->GenFramebuffers(1, &fbo_);
+ return fbo_ != 0;
+}
+
+void BufferQueue::BindFramebuffer() {
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+
+ if (!current_surface_.texture) {
+ current_surface_ = GetNextSurface();
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ current_surface_.texture,
+ 0);
+ }
+}
+
+void BufferQueue::CopyBufferDamage(int texture,
+ int source_texture,
+ const gfx::Rect& new_damage,
+ const gfx::Rect& old_damage) {
+ gl_helper_->CopySubBufferDamage(
+ texture,
+ source_texture,
+ SkRegion(SkIRect::MakeXYWH(new_damage.x(),
+ new_damage.y(),
+ new_damage.width(),
+ new_damage.height())),
+ SkRegion(SkIRect::MakeXYWH(old_damage.x(),
+ old_damage.y(),
+ old_damage.width(),
+ old_damage.height())));
+}
+
+void BufferQueue::UpdateBufferDamage(const gfx::Rect& damage) {
+ for (size_t i = 0; i < available_surfaces_.size(); i++)
+ available_surfaces_[i].damage.Union(damage);
+ for (std::deque<AllocatedSurface>::iterator it =
+ in_flight_surfaces_.begin();
+ it != in_flight_surfaces_.end();
+ ++it)
+ it->damage.Union(damage);
+}
+
+void BufferQueue::SwapBuffers(const gfx::Rect& damage) {
+ if (damage != gfx::Rect(size_)) {
+ // We must have a frame available to copy from.
+ DCHECK(!in_flight_surfaces_.empty());
+ CopyBufferDamage(current_surface_.texture,
+ in_flight_surfaces_.back().texture,
+ damage,
+ current_surface_.damage);
+ }
+ UpdateBufferDamage(damage);
+ current_surface_.damage = gfx::Rect();
+ in_flight_surfaces_.push_back(current_surface_);
+ current_surface_.texture = 0;
+ current_surface_.image = 0;
+}
+
+void BufferQueue::Reshape(const gfx::Size& size, float scale_factor) {
+ DCHECK(!current_surface_.texture);
+ if (size == size_)
+ return;
+ size_ = size;
+
+ // TODO: add stencil buffer when needed.
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
+ gl->FramebufferTexture2D(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+
+ FreeAllSurfaces();
+}
+
+void BufferQueue::PageFlipComplete() {
+ if (in_flight_surfaces_.size() > 1) {
+ available_surfaces_.push_back(in_flight_surfaces_.front());
+ in_flight_surfaces_.pop_front();
+ }
+}
+
+void BufferQueue::FreeAllSurfaces() {
+ FreeSurface(&current_surface_);
+ while (!in_flight_surfaces_.empty()) {
+ FreeSurface(&in_flight_surfaces_.front());
+ in_flight_surfaces_.pop_front();
+ }
+ for (size_t i = 0; i < available_surfaces_.size(); i++)
+ FreeSurface(&available_surfaces_[i]);
+ available_surfaces_.clear();
+}
+
+void BufferQueue::FreeSurface(AllocatedSurface* surface) {
+ if (surface->texture) {
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->BindTexture(GL_TEXTURE_2D, surface->texture);
+ gl->ReleaseTexImage2DCHROMIUM(GL_TEXTURE_2D, surface->image);
+ gl->DeleteTextures(1, &surface->texture);
+ gl->DestroyImageCHROMIUM(surface->image);
+ surface->image = 0;
+ surface->texture = 0;
+ allocated_count_--;
+ }
+}
+
+BufferQueue::AllocatedSurface BufferQueue::GetNextSurface() {
+ if (!available_surfaces_.empty()) {
+ AllocatedSurface surface = available_surfaces_.back();
+ available_surfaces_.pop_back();
+ return surface;
+ }
+
+ unsigned int texture = 0;
+ gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
+ gl->GenTextures(1, &texture);
+ if (!texture)
+ return AllocatedSurface();
+
+ // We don't want to allow anything more than triple buffering.
+ DCHECK_LT(allocated_count_, 4U);
+
+ unsigned int id =
+ gl->CreateGpuMemoryBufferImageCHROMIUM(size_.width(),
+ size_.height(),
+ internalformat_,
+ GL_SCANOUT_CHROMIUM);
+ if (!id) {
+ LOG(ERROR) << "Failed to allocate backing image surface";
+ gl->DeleteTextures(1, &texture);
+ return AllocatedSurface();
+ }
+ allocated_count_++;
+ gl->BindTexture(GL_TEXTURE_2D, texture);
+ gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, id);
+ return AllocatedSurface(texture, id, gfx::Rect(size_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/buffer_queue.h b/chromium/content/browser/compositor/buffer_queue.h
new file mode 100644
index 00000000000..dca9c38c0d4
--- /dev/null
+++ b/chromium/content/browser/compositor/buffer_queue.h
@@ -0,0 +1,90 @@
+// Copyright 2014 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 CONTENT_BROWSER_COMPOSITOR_BUFFERED_OUTPUT_SURFACE_H_
+#define CONTENT_BROWSER_COMPOSITOR_BUFFERED_OUTPUT_SURFACE_H_
+
+#include <queue>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+class ContextProvider;
+}
+
+namespace content {
+
+class GLHelper;
+
+// Provides a surface that manages its own buffers, backed by GpuMemoryBuffers
+// created using CHROMIUM_gpu_memory_buffer_image. Double/triple buffering is
+// implemented internally. Doublebuffering occurs if PageFlipComplete is called
+// before the next BindFramebuffer call, otherwise it creates extra buffers.
+class CONTENT_EXPORT BufferQueue {
+ public:
+ BufferQueue(scoped_refptr<cc::ContextProvider> context_provider,
+ unsigned int internalformat,
+ GLHelper* gl_helper);
+ virtual ~BufferQueue();
+
+ bool Initialize();
+
+ void BindFramebuffer();
+ void SwapBuffers(const gfx::Rect& damage);
+ void PageFlipComplete();
+ void Reshape(const gfx::Size& size, float scale_factor);
+
+ unsigned int current_texture_id() { return current_surface_.texture; }
+
+ private:
+ friend class BufferQueueTest;
+
+ struct AllocatedSurface {
+ AllocatedSurface() : texture(0), image(0) {}
+ AllocatedSurface(unsigned int texture,
+ unsigned int image,
+ const gfx::Rect& rect)
+ : texture(texture), image(image), damage(rect) {}
+ unsigned int texture;
+ unsigned int image;
+ gfx::Rect damage; // This is the damage for this frame from the previous.
+ };
+
+ void FreeAllSurfaces();
+
+ void FreeSurface(AllocatedSurface* surface);
+
+ // Copy everything that is in |copy_rect|, except for what is in
+ // |exclude_rect| from |source_texture| to |texture|.
+ virtual void CopyBufferDamage(int texture,
+ int source_texture,
+ const gfx::Rect& new_damage,
+ const gfx::Rect& old_damage);
+
+ void UpdateBufferDamage(const gfx::Rect& damage);
+
+ // Return a surface, available to be drawn into.
+ AllocatedSurface GetNextSurface();
+
+ gfx::Size size_;
+ scoped_refptr<cc::ContextProvider> context_provider_;
+ unsigned int fbo_;
+ size_t allocated_count_;
+ unsigned int internalformat_;
+ AllocatedSurface current_surface_; // This surface is currently bound.
+ std::vector<AllocatedSurface> available_surfaces_; // These are free for use.
+ std::deque<AllocatedSurface> in_flight_surfaces_;
+ GLHelper* gl_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_BUFFERED_OUTPUT_SURFACE_H_
diff --git a/chromium/content/browser/compositor/buffer_queue_unittest.cc b/chromium/content/browser/compositor/buffer_queue_unittest.cc
new file mode 100644
index 00000000000..1a2c4feeddc
--- /dev/null
+++ b/chromium/content/browser/compositor/buffer_queue_unittest.cc
@@ -0,0 +1,288 @@
+// Copyright 2014 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 <set>
+
+#include "cc/test/test_context_provider.h"
+#include "cc/test/test_web_graphics_context_3d.h"
+#include "content/browser/compositor/buffer_queue.h"
+#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+
+using ::testing::_;
+using ::testing::Expectation;
+using ::testing::Ne;
+using ::testing::Return;
+
+namespace content {
+class MockBufferQueue : public BufferQueue {
+ public:
+ MockBufferQueue(scoped_refptr<cc::ContextProvider> context_provider,
+ unsigned int internalformat)
+ : BufferQueue(context_provider, internalformat, nullptr) {}
+ MOCK_METHOD4(CopyBufferDamage,
+ void(int, int, const gfx::Rect&, const gfx::Rect&));
+};
+
+class BufferQueueTest : public ::testing::Test {
+ public:
+ BufferQueueTest() : doublebuffering_(true), first_frame_(true) {}
+
+ void SetUp() override {
+ scoped_refptr<cc::TestContextProvider> context_provider =
+ cc::TestContextProvider::Create(cc::TestWebGraphicsContext3D::Create());
+ context_provider->BindToCurrentThread();
+ output_surface_.reset(new MockBufferQueue(context_provider, GL_RGBA));
+ output_surface_->Initialize();
+ }
+
+ unsigned current_surface() { return output_surface_->current_surface_.image; }
+ const std::vector<BufferQueue::AllocatedSurface>& available_surfaces() {
+ return output_surface_->available_surfaces_;
+ }
+ const std::deque<BufferQueue::AllocatedSurface>& in_flight_surfaces() {
+ return output_surface_->in_flight_surfaces_;
+ }
+
+ const BufferQueue::AllocatedSurface& last_frame() {
+ return output_surface_->in_flight_surfaces_.back();
+ }
+ const BufferQueue::AllocatedSurface& next_frame() {
+ return output_surface_->available_surfaces_.back();
+ }
+ const gfx::Size size() { return output_surface_->size_; }
+
+ int CountBuffers() {
+ int n = available_surfaces().size() + in_flight_surfaces().size();
+ if (current_surface())
+ n++;
+ return n;
+ }
+
+ // Check that each buffer is unique if present.
+ void CheckUnique() {
+ std::set<unsigned> buffers;
+ EXPECT_TRUE(InsertUnique(&buffers, current_surface()));
+ for (size_t i = 0; i < available_surfaces().size(); i++)
+ EXPECT_TRUE(InsertUnique(&buffers, available_surfaces()[i].image));
+ for (std::deque<BufferQueue::AllocatedSurface>::const_iterator it =
+ in_flight_surfaces().begin();
+ it != in_flight_surfaces().end();
+ ++it)
+ EXPECT_TRUE(InsertUnique(&buffers, it->image));
+ }
+
+ void SwapBuffers() {
+ output_surface_->SwapBuffers(gfx::Rect(output_surface_->size_));
+ }
+
+ void SendDamagedFrame(const gfx::Rect& damage) {
+ // We don't care about the GL-level implementation here, just how it uses
+ // damage rects.
+ output_surface_->BindFramebuffer();
+ output_surface_->SwapBuffers(damage);
+ if (doublebuffering_ || !first_frame_)
+ output_surface_->PageFlipComplete();
+ first_frame_ = false;
+ }
+
+ void SendFullFrame() { SendDamagedFrame(gfx::Rect(output_surface_->size_)); }
+
+ protected:
+ bool InsertUnique(std::set<unsigned>* set, unsigned value) {
+ if (!value)
+ return true;
+ if (set->find(value) != set->end())
+ return false;
+ set->insert(value);
+ return true;
+ }
+
+ scoped_ptr<MockBufferQueue> output_surface_;
+ bool doublebuffering_;
+ bool first_frame_;
+};
+
+namespace {
+const gfx::Size screen_size = gfx::Size(30, 30);
+const gfx::Rect screen_rect = gfx::Rect(screen_size);
+const gfx::Rect small_damage = gfx::Rect(gfx::Size(10, 10));
+const gfx::Rect large_damage = gfx::Rect(gfx::Size(20, 20));
+const gfx::Rect overlapping_damage = gfx::Rect(gfx::Size(5, 20));
+
+class MockedContext : public cc::TestWebGraphicsContext3D {
+ public:
+ MOCK_METHOD2(bindFramebuffer, void(GLenum, GLuint));
+ MOCK_METHOD2(bindTexture, void(GLenum, GLuint));
+ MOCK_METHOD2(bindTexImage2DCHROMIUM, void(GLenum, GLint));
+ MOCK_METHOD4(createGpuMemoryBufferImageCHROMIUM,
+ GLuint(GLsizei, GLsizei, GLenum, GLenum));
+ MOCK_METHOD1(destroyImageCHROMIUM, void(GLuint));
+ MOCK_METHOD5(framebufferTexture2D,
+ void(GLenum, GLenum, GLenum, GLuint, GLint));
+};
+
+scoped_ptr<BufferQueue> CreateOutputSurfaceWithMock(MockedContext** context) {
+ *context = new MockedContext();
+ scoped_refptr<cc::TestContextProvider> context_provider =
+ cc::TestContextProvider::Create(
+ scoped_ptr<cc::TestWebGraphicsContext3D>(*context));
+ context_provider->BindToCurrentThread();
+ scoped_ptr<BufferQueue> buffer_queue(
+ new BufferQueue(context_provider, GL_RGBA, nullptr));
+ buffer_queue->Initialize();
+ return buffer_queue.Pass();
+}
+
+TEST(BufferQueueStandaloneTest, FboInitialization) {
+ MockedContext* context;
+ scoped_ptr<BufferQueue> output_surface =
+ CreateOutputSurfaceWithMock(&context);
+
+ EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
+ ON_CALL(*context, framebufferTexture2D(_, _, _, _, _))
+ .WillByDefault(Return());
+
+ output_surface->Reshape(gfx::Size(10, 20), 1.0f);
+}
+
+TEST(BufferQueueStandaloneTest, FboBinding) {
+ MockedContext* context;
+ scoped_ptr<BufferQueue> output_surface =
+ CreateOutputSurfaceWithMock(&context);
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, Ne(0U)));
+ EXPECT_CALL(*context, destroyImageCHROMIUM(1));
+ Expectation image =
+ EXPECT_CALL(*context,
+ createGpuMemoryBufferImageCHROMIUM(
+ 0, 0, GL_RGBA, GL_SCANOUT_CHROMIUM)).WillOnce(Return(1));
+ Expectation fb =
+ EXPECT_CALL(*context, bindFramebuffer(GL_FRAMEBUFFER, Ne(0U)));
+ Expectation tex = EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, Ne(0U)));
+ Expectation bind_tex =
+ EXPECT_CALL(*context, bindTexImage2DCHROMIUM(GL_TEXTURE_2D, 1))
+ .After(tex, image);
+ EXPECT_CALL(
+ *context,
+ framebufferTexture2D(
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Ne(0U), _))
+ .After(fb, bind_tex);
+
+ output_surface->BindFramebuffer();
+}
+
+TEST_F(BufferQueueTest, PartialSwapReuse) {
+ // Check that
+ output_surface_->Reshape(screen_size, 1.0f);
+ ASSERT_TRUE(doublebuffering_);
+ EXPECT_CALL(*output_surface_,
+ CopyBufferDamage(_, _, small_damage, screen_rect)).Times(1);
+ EXPECT_CALL(*output_surface_,
+ CopyBufferDamage(_, _, small_damage, small_damage)).Times(1);
+ EXPECT_CALL(*output_surface_,
+ CopyBufferDamage(_, _, large_damage, small_damage)).Times(1);
+ SendFullFrame();
+ SendDamagedFrame(small_damage);
+ SendDamagedFrame(small_damage);
+ SendDamagedFrame(large_damage);
+ // Verify that the damage has propagated.
+ EXPECT_EQ(next_frame().damage, large_damage);
+}
+
+TEST_F(BufferQueueTest, PartialSwapFullFrame) {
+ output_surface_->Reshape(screen_size, 1.0f);
+ ASSERT_TRUE(doublebuffering_);
+ EXPECT_CALL(*output_surface_,
+ CopyBufferDamage(_, _, small_damage, screen_rect)).Times(1);
+ SendFullFrame();
+ SendDamagedFrame(small_damage);
+ SendFullFrame();
+ SendFullFrame();
+ EXPECT_EQ(next_frame().damage, screen_rect);
+}
+
+TEST_F(BufferQueueTest, PartialSwapOverlapping) {
+ output_surface_->Reshape(screen_size, 1.0f);
+ ASSERT_TRUE(doublebuffering_);
+ EXPECT_CALL(*output_surface_,
+ CopyBufferDamage(_, _, small_damage, screen_rect)).Times(1);
+ EXPECT_CALL(*output_surface_,
+ CopyBufferDamage(_, _, overlapping_damage, small_damage))
+ .Times(1);
+
+ SendFullFrame();
+ SendDamagedFrame(small_damage);
+ SendDamagedFrame(overlapping_damage);
+ EXPECT_EQ(next_frame().damage, overlapping_damage);
+}
+
+TEST_F(BufferQueueTest, MultipleBindCalls) {
+ // Check that multiple bind calls do not create or change surfaces.
+ output_surface_->BindFramebuffer();
+ EXPECT_EQ(1, CountBuffers());
+ unsigned int fb = current_surface();
+ output_surface_->BindFramebuffer();
+ EXPECT_EQ(1, CountBuffers());
+ EXPECT_EQ(fb, current_surface());
+}
+
+TEST_F(BufferQueueTest, CheckDoubleBuffering) {
+ // Check buffer flow through double buffering path.
+ EXPECT_EQ(0, CountBuffers());
+ output_surface_->BindFramebuffer();
+ EXPECT_EQ(1, CountBuffers());
+ EXPECT_NE(0U, current_surface());
+ SwapBuffers();
+ EXPECT_EQ(1U, in_flight_surfaces().size());
+ output_surface_->PageFlipComplete();
+ EXPECT_EQ(1U, in_flight_surfaces().size());
+ output_surface_->BindFramebuffer();
+ EXPECT_EQ(2, CountBuffers());
+ CheckUnique();
+ EXPECT_NE(0U, current_surface());
+ EXPECT_EQ(1U, in_flight_surfaces().size());
+ SwapBuffers();
+ CheckUnique();
+ EXPECT_EQ(2U, in_flight_surfaces().size());
+ output_surface_->PageFlipComplete();
+ CheckUnique();
+ EXPECT_EQ(1U, in_flight_surfaces().size());
+ EXPECT_EQ(1U, available_surfaces().size());
+ output_surface_->BindFramebuffer();
+ EXPECT_EQ(2, CountBuffers());
+ CheckUnique();
+ EXPECT_TRUE(available_surfaces().empty());
+}
+
+TEST_F(BufferQueueTest, CheckTripleBuffering) {
+ // Check buffer flow through triple buffering path.
+
+ // This bit is the same sequence tested in the doublebuffering case.
+ output_surface_->BindFramebuffer();
+ SwapBuffers();
+ output_surface_->PageFlipComplete();
+ output_surface_->BindFramebuffer();
+ SwapBuffers();
+
+ EXPECT_EQ(2, CountBuffers());
+ CheckUnique();
+ EXPECT_EQ(2U, in_flight_surfaces().size());
+ output_surface_->BindFramebuffer();
+ EXPECT_EQ(3, CountBuffers());
+ CheckUnique();
+ EXPECT_NE(0U, current_surface());
+ EXPECT_EQ(2U, in_flight_surfaces().size());
+ output_surface_->PageFlipComplete();
+ EXPECT_EQ(3, CountBuffers());
+ CheckUnique();
+ EXPECT_NE(0U, current_surface());
+ EXPECT_EQ(1U, in_flight_surfaces().size());
+ EXPECT_EQ(1U, available_surfaces().size());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/browser/compositor/delegated_frame_host.cc b/chromium/content/browser/compositor/delegated_frame_host.cc
index 5db69b70b4c..5dbaed130f5 100644
--- a/chromium/content/browser/compositor/delegated_frame_host.cc
+++ b/chromium/content/browser/compositor/delegated_frame_host.cc
@@ -11,16 +11,46 @@
#include "cc/output/copy_output_request.h"
#include "cc/resources/single_release_callback.h"
#include "cc/resources/texture_mailbox.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_manager.h"
#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/common/content_switches.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/effects/SkLumaColorFilter.h"
+#include "ui/gfx/frame_time.h"
namespace content {
+namespace {
+
+void SatisfyCallback(cc::SurfaceManager* manager,
+ cc::SurfaceSequence sequence) {
+ std::vector<uint32_t> sequences;
+ sequences.push_back(sequence.sequence);
+ manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+}
+
+void RequireCallback(cc::SurfaceManager* manager,
+ cc::SurfaceId id,
+ cc::SurfaceSequence sequence) {
+ cc::Surface* surface = manager->GetSurfaceForId(id);
+ if (!surface) {
+ LOG(ERROR) << "Attempting to require callback on nonexistent surface";
+ return;
+ }
+ surface->AddDestructionDependency(sequence);
+}
+
+} // namespace
+
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHostClient
@@ -48,6 +78,7 @@ void DelegatedFrameHostClient::RequestCopyOfOutput(
DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
: client_(client),
+ use_surfaces_(UseSurfacesEnabled()),
last_output_surface_id_(0),
pending_delegated_ack_count_(0),
skipped_frames_(false),
@@ -56,14 +87,24 @@ DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
ImageTransportFactory::GetInstance()->AddObserver(this);
}
-void DelegatedFrameHost::WasShown() {
+void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) {
delegated_frame_evictor_->SetVisible(true);
- if (!released_front_lock_.get()) {
+ if (surface_id_.is_null() && !frame_provider_.get() &&
+ !released_front_lock_.get()) {
ui::Compositor* compositor = client_->GetCompositor();
if (compositor)
released_front_lock_ = compositor->GetCompositorLock();
}
+
+ ui::Compositor* compositor = client_->GetCompositor();
+ if (compositor) {
+ compositor->SetLatencyInfo(latency_info);
+ }
+}
+
+bool DelegatedFrameHost::HasSavedFrame() {
+ return delegated_frame_evictor_->HasFrame();
}
void DelegatedFrameHost::WasHidden() {
@@ -118,29 +159,26 @@ void DelegatedFrameHost::RequestCopyOfOutput(
void DelegatedFrameHost::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) {
+ const gfx::Size& output_size,
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) {
// Only ARGB888 and RGB565 supported as of now.
- bool format_support = ((config == SkBitmap::kRGB_565_Config) ||
- (config == SkBitmap::kARGB_8888_Config));
+ bool format_support = ((color_type == kAlpha_8_SkColorType) ||
+ (color_type == kRGB_565_SkColorType) ||
+ (color_type == kN32_SkColorType));
DCHECK(format_support);
if (!CanCopyToBitmap()) {
callback.Run(false, SkBitmap());
return;
}
- const gfx::Size& dst_size_in_pixel =
- client_->ConvertViewSizeToPixel(dst_size);
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(base::Bind(
&DelegatedFrameHost::CopyFromCompositingSurfaceHasResult,
- dst_size_in_pixel,
- config,
+ output_size,
+ color_type,
callback));
- gfx::Rect src_subrect_in_pixel =
- ConvertRectToPixel(client_->CurrentDeviceScaleFactor(), src_subrect);
- request->set_area(src_subrect_in_pixel);
+ request->set_area(src_subrect);
client_->RequestCopyOfOutput(request.Pass());
}
@@ -173,9 +211,7 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame(
subscriber_texture,
target,
callback));
- gfx::Rect src_subrect_in_pixel =
- ConvertRectToPixel(client_->CurrentDeviceScaleFactor(), src_subrect);
- request->set_area(src_subrect_in_pixel);
+ request->set_area(src_subrect);
if (subscriber_texture.get()) {
request->SetTextureMailbox(
cc::TextureMailbox(subscriber_texture->mailbox(),
@@ -222,6 +258,9 @@ bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const {
}
void DelegatedFrameHost::WasResized() {
+ if (client_->DesiredFrameSize() != current_frame_size_in_dip_ &&
+ client_->GetHost()->is_hidden())
+ EvictDelegatedFrame();
MaybeCreateResizeLock();
}
@@ -248,18 +287,28 @@ void DelegatedFrameHost::CheckResizeLock() {
}
}
-void DelegatedFrameHost::DidReceiveFrameFromRenderer() {
- if (frame_subscriber() && CanCopyToVideoFrame()) {
- const base::TimeTicks present_time = base::TimeTicks::Now();
- scoped_refptr<media::VideoFrame> frame;
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
- if (frame_subscriber()->ShouldCaptureFrame(present_time,
- &frame, &callback)) {
- CopyFromCompositingSurfaceToVideoFrame(
- gfx::Rect(current_frame_size_in_dip_),
- frame,
- base::Bind(callback, present_time));
- }
+void DelegatedFrameHost::DidReceiveFrameFromRenderer(
+ const gfx::Rect& damage_rect) {
+ if (!frame_subscriber() || !CanCopyToVideoFrame())
+ return;
+
+ const base::TimeTicks now = gfx::FrameTime::Now();
+ base::TimeTicks present_time;
+ if (vsync_timebase_.is_null() || vsync_interval_ <= base::TimeDelta()) {
+ present_time = now;
+ } else {
+ const int64 intervals_elapsed = (now - vsync_timebase_) / vsync_interval_;
+ present_time = vsync_timebase_ + (intervals_elapsed + 1) * vsync_interval_;
+ }
+
+ scoped_refptr<media::VideoFrame> frame;
+ RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
+ if (frame_subscriber()->ShouldCaptureFrame(damage_rect, present_time,
+ &frame, &callback)) {
+ CopyFromCompositingSurfaceToVideoFrame(
+ gfx::Rect(current_frame_size_in_dip_),
+ frame,
+ base::Bind(callback, present_time));
}
}
@@ -317,6 +366,10 @@ void DelegatedFrameHost::SwapDelegatedFrame(
// the DelegatedRendererLayer.
EvictDelegatedFrame();
+ surface_factory_.reset();
+ if (!surface_returned_resources_.empty())
+ SendReturnedDelegatedResources(last_output_surface_id_);
+
// Drop the cc::DelegatedFrameResourceCollection so that we will not return
// any resources from the old output surface with the new output surface id.
if (resource_collection_.get()) {
@@ -329,41 +382,86 @@ void DelegatedFrameHost::SwapDelegatedFrame(
}
last_output_surface_id_ = output_surface_id;
}
+ ui::Compositor* compositor = client_->GetCompositor();
if (frame_size.IsEmpty()) {
DCHECK(frame_data->resource_list.empty());
EvictDelegatedFrame();
} else {
- if (!resource_collection_) {
- resource_collection_ = new cc::DelegatedFrameResourceCollection;
- resource_collection_->SetClient(this);
- }
- // If the physical frame size changes, we need a new |frame_provider_|. If
- // the physical frame size is the same, but the size in DIP changed, we
- // need to adjust the scale at which the frames will be drawn, and we do
- // this by making a new |frame_provider_| also to ensure the scale change
- // is presented in sync with the new frame content.
- if (!frame_provider_.get() || frame_size != frame_provider_->frame_size() ||
- frame_size_in_dip != current_frame_size_in_dip_) {
- frame_provider_ = new cc::DelegatedFrameProvider(
- resource_collection_.get(), frame_data.Pass());
- client_->GetLayer()->SetShowDelegatedContent(frame_provider_.get(),
- frame_size_in_dip);
+ if (use_surfaces_) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ if (!surface_factory_) {
+ id_allocator_ =
+ factory->GetContextFactory()->CreateSurfaceIdAllocator();
+ surface_factory_ =
+ make_scoped_ptr(new cc::SurfaceFactory(manager, this));
+ }
+ if (surface_id_.is_null() || frame_size != current_surface_size_ ||
+ frame_size_in_dip != current_frame_size_in_dip_) {
+ if (!surface_id_.is_null())
+ surface_factory_->Destroy(surface_id_);
+ surface_id_ = id_allocator_->GenerateId();
+ surface_factory_->Create(surface_id_, frame_size);
+ // manager must outlive compositors using it.
+ client_->GetLayer()->SetShowSurface(
+ surface_id_,
+ base::Bind(&SatisfyCallback, base::Unretained(manager)),
+ base::Bind(&RequireCallback, base::Unretained(manager)), frame_size,
+ frame_size_in_dip);
+ current_surface_size_ = frame_size;
+ }
+ scoped_ptr<cc::CompositorFrame> compositor_frame =
+ make_scoped_ptr(new cc::CompositorFrame());
+ compositor_frame->delegated_frame_data = frame_data.Pass();
+
+ compositor_frame->metadata.latency_info.swap(skipped_latency_info_list_);
+ compositor_frame->metadata.latency_info.insert(
+ compositor_frame->metadata.latency_info.end(),
+ latency_info.begin(),
+ latency_info.end());
+
+ base::Closure ack_callback;
+ if (compositor) {
+ ack_callback = base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
+ AsWeakPtr(),
+ output_surface_id);
+ }
+ surface_factory_->SubmitFrame(
+ surface_id_, compositor_frame.Pass(), ack_callback);
} else {
- frame_provider_->SetFrameData(frame_data.Pass());
+ if (!resource_collection_.get()) {
+ resource_collection_ = new cc::DelegatedFrameResourceCollection;
+ resource_collection_->SetClient(this);
+ }
+ // If the physical frame size changes, we need a new |frame_provider_|. If
+ // the physical frame size is the same, but the size in DIP changed, we
+ // need to adjust the scale at which the frames will be drawn, and we do
+ // this by making a new |frame_provider_| also to ensure the scale change
+ // is presented in sync with the new frame content.
+ if (!frame_provider_.get() ||
+ frame_size != frame_provider_->frame_size() ||
+ frame_size_in_dip != current_frame_size_in_dip_) {
+ frame_provider_ = new cc::DelegatedFrameProvider(
+ resource_collection_.get(), frame_data.Pass());
+ client_->GetLayer()->SetShowDelegatedContent(frame_provider_.get(),
+ frame_size_in_dip);
+ } else {
+ frame_provider_->SetFrameData(frame_data.Pass());
+ }
}
}
released_front_lock_ = NULL;
current_frame_size_in_dip_ = frame_size_in_dip;
CheckResizeLock();
- client_->SchedulePaintInRect(damage_rect_in_dip);
+ if (!damage_rect_in_dip.IsEmpty())
+ client_->GetLayer()->OnDelegatedFrameDamage(damage_rect_in_dip);
pending_delegated_ack_count_++;
- ui::Compositor* compositor = client_->GetCompositor();
if (!compositor) {
SendDelegatedFrameAck(output_surface_id);
- } else {
+ } else if (!use_surfaces_) {
std::vector<ui::LatencyInfo>::const_iterator it;
for (it = latency_info.begin(); it != latency_info.end(); ++it)
compositor->SetLatencyInfo(*it);
@@ -377,9 +475,11 @@ void DelegatedFrameHost::SwapDelegatedFrame(
base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
AsWeakPtr(),
output_surface_id));
+ } else {
+ AddOnCommitCallbackAndDisableLocks(base::Closure());
}
- DidReceiveFrameFromRenderer();
- if (frame_provider_.get())
+ DidReceiveFrameFromRenderer(damage_rect);
+ if (frame_provider_.get() || !surface_id_.is_null())
delegated_frame_evictor_->SwappedFrame(!host->is_hidden());
// Note: the frame may have been evicted immediately.
}
@@ -387,7 +487,9 @@ void DelegatedFrameHost::SwapDelegatedFrame(
void DelegatedFrameHost::SendDelegatedFrameAck(uint32 output_surface_id) {
RenderWidgetHostImpl* host = client_->GetHost();
cc::CompositorFrameAck ack;
- if (resource_collection_)
+ if (!surface_returned_resources_.empty())
+ ack.resources.swap(surface_returned_resources_);
+ if (resource_collection_.get())
resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
RenderWidgetHostImpl::SendSwapCompositorFrameAck(host->GetRoutingID(),
output_surface_id,
@@ -407,10 +509,14 @@ void DelegatedFrameHost::UnusedResourcesAreAvailable() {
void DelegatedFrameHost::SendReturnedDelegatedResources(
uint32 output_surface_id) {
RenderWidgetHostImpl* host = client_->GetHost();
- DCHECK(resource_collection_);
cc::CompositorFrameAck ack;
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ if (!surface_returned_resources_.empty()) {
+ ack.resources.swap(surface_returned_resources_);
+ } else {
+ DCHECK(resource_collection_.get());
+ resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
+ }
DCHECK(!ack.resources.empty());
RenderWidgetHostImpl::SendReclaimCompositorResources(
@@ -420,16 +526,31 @@ void DelegatedFrameHost::SendReturnedDelegatedResources(
ack);
}
+void DelegatedFrameHost::ReturnResources(
+ const cc::ReturnedResourceArray& resources) {
+ if (resources.empty())
+ return;
+ std::copy(resources.begin(),
+ resources.end(),
+ std::back_inserter(surface_returned_resources_));
+ if (!pending_delegated_ack_count_)
+ SendReturnedDelegatedResources(last_output_surface_id_);
+}
+
void DelegatedFrameHost::EvictDelegatedFrame() {
- client_->GetLayer()->SetShowPaintedContent();
+ client_->GetLayer()->SetShowSolidColorContent();
frame_provider_ = NULL;
+ if (!surface_id_.is_null()) {
+ surface_factory_->Destroy(surface_id_);
+ surface_id_ = cc::SurfaceId();
+ }
delegated_frame_evictor_->DiscardedFrame();
}
// static
void DelegatedFrameHost::CopyFromCompositingSurfaceHasResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result) {
if (result->IsEmpty() || result->size().IsEmpty()) {
@@ -438,14 +559,16 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResult(
}
if (result->HasTexture()) {
- PrepareTextureCopyOutputResult(dst_size_in_pixel, config,
+ // GPU-accelerated path
+ PrepareTextureCopyOutputResult(dst_size_in_pixel, color_type,
callback,
result.Pass());
return;
}
DCHECK(result->HasBitmap());
- PrepareBitmapCopyOutputResult(dst_size_in_pixel, config, callback,
+ // Software path
+ PrepareBitmapCopyOutputResult(dst_size_in_pixel, color_type, callback,
result.Pass());
}
@@ -471,18 +594,21 @@ static void CopyFromCompositingSurfaceFinished(
// static
void DelegatedFrameHost::PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result) {
DCHECK(result->HasTexture());
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, false, SkBitmap()));
+ // TODO(sikugu): We should be able to validate the format here using
+ // GLHelper::IsReadbackConfigSupported before we processs the result.
+ // See crbug.com/415682.
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- bitmap->setConfig(config,
- dst_size_in_pixel.width(), dst_size_in_pixel.height(),
- 0, kOpaque_SkAlphaType);
- if (!bitmap->allocPixels())
+ if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
+ dst_size_in_pixel.height(),
+ color_type,
+ kOpaque_SkAlphaType)))
return;
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -508,7 +634,7 @@ void DelegatedFrameHost::PrepareTextureCopyOutputResult(
gfx::Rect(result->size()),
dst_size_in_pixel,
pixels,
- config,
+ color_type,
base::Bind(&CopyFromCompositingSurfaceFinished,
callback,
base::Passed(&release_callback),
@@ -520,10 +646,10 @@ void DelegatedFrameHost::PrepareTextureCopyOutputResult(
// static
void DelegatedFrameHost::PrepareBitmapCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result) {
- if (config != SkBitmap::kARGB_8888_Config) {
+ if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
NOTIMPLEMENTED();
callback.Run(false, SkBitmap());
return;
@@ -531,12 +657,41 @@ void DelegatedFrameHost::PrepareBitmapCopyOutputResult(
DCHECK(result->HasBitmap());
scoped_ptr<SkBitmap> source = result->TakeBitmap();
DCHECK(source);
- SkBitmap bitmap = skia::ImageOperations::Resize(
- *source,
- skia::ImageOperations::RESIZE_BEST,
- dst_size_in_pixel.width(),
- dst_size_in_pixel.height());
- callback.Run(true, bitmap);
+ SkBitmap scaled_bitmap;
+ if (source->width() != dst_size_in_pixel.width() ||
+ source->height() != dst_size_in_pixel.height()) {
+ scaled_bitmap =
+ skia::ImageOperations::Resize(*source,
+ skia::ImageOperations::RESIZE_BEST,
+ dst_size_in_pixel.width(),
+ dst_size_in_pixel.height());
+ } else {
+ scaled_bitmap = *source;
+ }
+ if (color_type == kN32_SkColorType) {
+ DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
+ callback.Run(true, scaled_bitmap);
+ return;
+ }
+ DCHECK_EQ(color_type, kAlpha_8_SkColorType);
+ // The software path currently always returns N32 bitmap regardless of the
+ // |color_type| we ask for.
+ DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
+ // Paint |scaledBitmap| to alpha-only |grayscale_bitmap|.
+ SkBitmap grayscale_bitmap;
+ bool success = grayscale_bitmap.tryAllocPixels(
+ SkImageInfo::MakeA8(scaled_bitmap.width(), scaled_bitmap.height()));
+ if (!success) {
+ callback.Run(false, SkBitmap());
+ return;
+ }
+ SkCanvas canvas(grayscale_bitmap);
+ SkPaint paint;
+ skia::RefPtr<SkColorFilter> filter =
+ skia::AdoptRef(SkLumaColorFilter::Create());
+ paint.setColorFilter(filter.get());
+ canvas.drawBitmap(scaled_bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
+ callback.Run(true, grayscale_bitmap);
}
// static
@@ -555,6 +710,7 @@ void DelegatedFrameHost::ReturnSubscriberTexture(
dfh->idle_frame_subscriber_textures_.push_back(subscriber_texture);
}
+// static
void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
base::WeakPtr<DelegatedFrameHost> dfh,
const base::Callback<void(bool)>& callback,
@@ -571,7 +727,7 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo(
if (release_callback) {
// A release callback means the texture came from the compositor, so there
// should be no |subscriber_texture|.
- DCHECK(!subscriber_texture);
+ DCHECK(!subscriber_texture.get());
bool lost_resource = sync_point == 0;
release_callback->Run(sync_point, lost_resource);
}
@@ -670,7 +826,8 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
quality_switch = switches::kTabCaptureUpscaleQuality;
std::string switch_value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(quality_switch);
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ quality_switch);
if (switch_value == "fast")
quality = GLHelper::SCALER_QUALITY_FAST;
else if (switch_value == "good")
@@ -750,6 +907,8 @@ void DelegatedFrameHost::OnCompositingLockStateChanged(
void DelegatedFrameHost::OnUpdateVSyncParameters(
base::TimeTicks timebase,
base::TimeDelta interval) {
+ vsync_timebase_ = timebase;
+ vsync_interval_ = interval;
RenderWidgetHostImpl* host = client_->GetHost();
if (client_->IsVisible())
host->UpdateVSyncParameters(timebase, interval);
@@ -760,7 +919,7 @@ void DelegatedFrameHost::OnUpdateVSyncParameters(
void DelegatedFrameHost::OnLostResources() {
RenderWidgetHostImpl* host = client_->GetHost();
- if (frame_provider_.get())
+ if (frame_provider_.get() || !surface_id_.is_null())
EvictDelegatedFrame();
idle_frame_subscriber_textures_.clear();
yuv_readback_pipeline_.reset();
@@ -774,10 +933,12 @@ void DelegatedFrameHost::OnLostResources() {
DelegatedFrameHost::~DelegatedFrameHost() {
ImageTransportFactory::GetInstance()->RemoveObserver(this);
+ if (!surface_id_.is_null())
+ surface_factory_->Destroy(surface_id_);
if (resource_collection_.get())
resource_collection_->SetClient(NULL);
- DCHECK(!vsync_manager_);
+ DCHECK(!vsync_manager_.get());
}
void DelegatedFrameHost::RunOnCommitCallbacks() {
@@ -798,13 +959,14 @@ void DelegatedFrameHost::AddOnCommitCallbackAndDisableLocks(
compositor->AddObserver(this);
can_lock_compositor_ = NO_PENDING_COMMIT;
- on_compositing_did_commit_callbacks_.push_back(callback);
+ if (!callback.is_null())
+ on_compositing_did_commit_callbacks_.push_back(callback);
}
void DelegatedFrameHost::AddedToWindow() {
ui::Compositor* compositor = client_->GetCompositor();
if (compositor) {
- DCHECK(!vsync_manager_);
+ DCHECK(!vsync_manager_.get());
vsync_manager_ = compositor->vsync_manager();
vsync_manager_->AddObserver(this);
}
@@ -818,19 +980,19 @@ void DelegatedFrameHost::RemovingFromWindow() {
if (compositor && compositor->HasObserver(this))
compositor->RemoveObserver(this);
- if (vsync_manager_) {
+ if (vsync_manager_.get()) {
vsync_manager_->RemoveObserver(this);
vsync_manager_ = NULL;
}
}
void DelegatedFrameHost::LockResources() {
- DCHECK(frame_provider_);
+ DCHECK(frame_provider_.get() || !surface_id_.is_null());
delegated_frame_evictor_->LockFrame();
}
void DelegatedFrameHost::UnlockResources() {
- DCHECK(frame_provider_);
+ DCHECK(frame_provider_.get() || !surface_id_.is_null());
delegated_frame_evictor_->UnlockFrame();
}
@@ -846,7 +1008,14 @@ void DelegatedFrameHost::OnLayerRecreated(ui::Layer* old_layer,
new_layer->SetShowDelegatedContent(frame_provider_.get(),
current_frame_size_in_dip_);
}
+ if (!surface_id_.is_null()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ new_layer->SetShowSurface(
+ surface_id_, base::Bind(&SatisfyCallback, base::Unretained(manager)),
+ base::Bind(&RequireCallback, base::Unretained(manager)),
+ current_surface_size_, current_frame_size_in_dip_);
+ }
}
} // namespace content
-
diff --git a/chromium/content/browser/compositor/delegated_frame_host.h b/chromium/content/browser/compositor/delegated_frame_host.h
index bcbc758ffad..a789ef6e1f0 100644
--- a/chromium/content/browser/compositor/delegated_frame_host.h
+++ b/chromium/content/browser/compositor/delegated_frame_host.h
@@ -8,11 +8,13 @@
#include "cc/layers/delegated_frame_provider.h"
#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/output/copy_output_result.h"
+#include "cc/surfaces/surface_factory_client.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/browser/renderer_host/delegated_frame_evictor.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/public/browser/render_process_host.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
@@ -21,6 +23,10 @@
#include "ui/compositor/layer_owner_delegate.h"
#include "ui/gfx/rect_conversions.h"
+namespace cc {
+class SurfaceFactory;
+}
+
namespace media {
class VideoFrame;
}
@@ -41,7 +47,6 @@ class CONTENT_EXPORT DelegatedFrameHostClient {
virtual ui::Compositor* GetCompositor() const = 0;
virtual ui::Layer* GetLayer() = 0;
virtual RenderWidgetHostImpl* GetHost() = 0;
- virtual void SchedulePaintInRect(const gfx::Rect& damage_rect_in_dip) = 0;
virtual bool IsVisible() = 0;
virtual scoped_ptr<ResizeLock> CreateResizeLock(
bool defer_compositor_lock) = 0;
@@ -72,10 +77,11 @@ class CONTENT_EXPORT DelegatedFrameHost
public ImageTransportFactoryObserver,
public DelegatedFrameEvictorClient,
public cc::DelegatedFrameResourceCollectionClient,
+ public cc::SurfaceFactoryClient,
public base::SupportsWeakPtr<DelegatedFrameHost> {
public:
DelegatedFrameHost(DelegatedFrameHostClient* client);
- virtual ~DelegatedFrameHost();
+ ~DelegatedFrameHost() override;
bool CanCopyToBitmap() const;
@@ -86,16 +92,16 @@ class CONTENT_EXPORT DelegatedFrameHost
float frame_device_scale_factor,
const std::vector<ui::LatencyInfo>& latency_info);
void WasHidden();
- void WasShown();
+ void WasShown(const ui::LatencyInfo& latency_info);
void WasResized();
+ bool HasSavedFrame();
gfx::Size GetRequestedRendererSize() const;
void AddedToWindow();
void RemovingFromWindow();
- void CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config);
+ void CopyFromCompositingSurface(const gfx::Rect& src_subrect,
+ const gfx::Size& output_size,
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type);
void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
@@ -105,15 +111,20 @@ class CONTENT_EXPORT DelegatedFrameHost
void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber);
void EndFrameSubscription();
+ bool HasFrameSubscriber() const { return frame_subscriber_; }
// Exposed for tests.
cc::DelegatedFrameProvider* FrameProviderForTesting() const {
return frame_provider_.get();
}
+ cc::SurfaceId SurfaceIdForTesting() const { return surface_id_; }
void OnCompositingDidCommitForTesting(ui::Compositor* compositor) {
OnCompositingDidCommit(compositor);
}
bool ShouldCreateResizeLockForTesting() { return ShouldCreateResizeLock(); }
+ bool ReleasedFrontLockActiveForTesting() const {
+ return !!released_front_lock_.get();
+ }
private:
friend class DelegatedFrameHostClient;
@@ -134,24 +145,22 @@ class CONTENT_EXPORT DelegatedFrameHost
void UnlockResources();
// Overridden from ui::CompositorObserver:
- virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE;
- virtual void OnCompositingStarted(ui::Compositor* compositor,
- base::TimeTicks start_time) OVERRIDE;
- virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE;
- virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE;
- virtual void OnCompositingLockStateChanged(
- ui::Compositor* compositor) OVERRIDE;
+ void OnCompositingDidCommit(ui::Compositor* compositor) override;
+ void OnCompositingStarted(ui::Compositor* compositor,
+ base::TimeTicks start_time) override;
+ void OnCompositingEnded(ui::Compositor* compositor) override;
+ void OnCompositingAborted(ui::Compositor* compositor) override;
+ void OnCompositingLockStateChanged(ui::Compositor* compositor) override;
// Overridden from ui::CompositorVSyncManager::Observer:
- virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE;
+ void OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) override;
// Overridden from ui::LayerOwnerObserver:
- virtual void OnLayerRecreated(ui::Layer* old_layer,
- ui::Layer* new_layer) OVERRIDE;
+ void OnLayerRecreated(ui::Layer* old_layer, ui::Layer* new_layer) override;
// Overridden from ImageTransportFactoryObserver:
- virtual void OnLostResources() OVERRIDE;
+ void OnLostResources() override;
bool ShouldSkipFrame(gfx::Size size_in_dip) const;
@@ -172,17 +181,17 @@ class CONTENT_EXPORT DelegatedFrameHost
// of the copy.
static void CopyFromCompositingSurfaceHasResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result);
static void PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result);
static void PrepareBitmapCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result);
static void CopyFromCompositingSurfaceHasResultForVideo(
@@ -206,20 +215,32 @@ class CONTENT_EXPORT DelegatedFrameHost
void SendReturnedDelegatedResources(uint32 output_surface_id);
// DelegatedFrameEvictorClient implementation.
- virtual void EvictDelegatedFrame() OVERRIDE;
+ void EvictDelegatedFrame() override;
// cc::DelegatedFrameProviderClient implementation.
- virtual void UnusedResourcesAreAvailable() OVERRIDE;
+ void UnusedResourcesAreAvailable() override;
- void DidReceiveFrameFromRenderer();
+ // cc::SurfaceFactoryClient implementation.
+ void ReturnResources(const cc::ReturnedResourceArray& resources) override;
+
+ void DidReceiveFrameFromRenderer(const gfx::Rect& damage_rect);
DelegatedFrameHostClient* client_;
+ // True if this renders into a Surface, false if it renders into a delegated
+ // layer.
+ bool use_surfaces_;
+
std::vector<base::Closure> on_compositing_did_commit_callbacks_;
// The vsync manager we are observing for changes, if any.
scoped_refptr<ui::CompositorVSyncManager> vsync_manager_;
+ // The current VSync timebase and interval. These are zero until the first
+ // call to OnUpdateVSyncParameters().
+ base::TimeTicks vsync_timebase_;
+ base::TimeDelta vsync_interval_;
+
// With delegated renderer, this is the last output surface, used to
// disambiguate resources with the same id coming from different output
// surfaces.
@@ -242,6 +263,13 @@ class CONTENT_EXPORT DelegatedFrameHost
// Provides delegated frame updates to the cc::DelegatedRendererLayer.
scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
+ // State for rendering into a Surface.
+ scoped_ptr<cc::SurfaceIdAllocator> id_allocator_;
+ scoped_ptr<cc::SurfaceFactory> surface_factory_;
+ cc::SurfaceId surface_id_;
+ gfx::Size current_surface_size_;
+ cc::ReturnedResourceArray surface_returned_resources_;
+
// This lock is the one waiting for a frame of the right size to come back
// from the renderer/GPU process. It is set from the moment the aura window
// got resized, to the moment we committed the renderer frame of the same
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index 3b79d546d42..e68c5c8fd20 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -5,8 +5,12 @@
#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
#include "cc/output/compositor_frame.h"
+#include "cc/output/output_surface_client.h"
#include "content/browser/compositor/reflector_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/public/browser/browser_thread.h"
+#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
namespace content {
@@ -20,23 +24,41 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
: BrowserCompositorOutputSurface(context,
surface_id,
output_surface_map,
- vsync_manager) {
+ vsync_manager),
+ swap_buffers_completion_callback_(
+ base::Bind(&GpuBrowserCompositorOutputSurface::OnSwapBuffersCompleted,
+ base::Unretained(this))) {
overlay_candidate_validator_ = overlay_candidate_validator.Pass();
}
GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
-void GpuBrowserCompositorOutputSurface::SwapBuffers(
- cc::CompositorFrame* frame) {
- DCHECK(frame->gl_frame_data);
-
+CommandBufferProxyImpl*
+GpuBrowserCompositorOutputSurface::GetCommandBufferProxy() {
ContextProviderCommandBuffer* provider_command_buffer =
- static_cast<ContextProviderCommandBuffer*>(context_provider_.get());
+ static_cast<content::ContextProviderCommandBuffer*>(
+ context_provider_.get());
CommandBufferProxyImpl* command_buffer_proxy =
provider_command_buffer->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
- context_provider_->ContextGL()->ShallowFlushCHROMIUM();
- command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
+ return command_buffer_proxy;
+}
+
+bool GpuBrowserCompositorOutputSurface::BindToClient(
+ cc::OutputSurfaceClient* client) {
+ if (!BrowserCompositorOutputSurface::BindToClient(client))
+ return false;
+
+ GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
+ swap_buffers_completion_callback_.callback());
+ return true;
+}
+
+void GpuBrowserCompositorOutputSurface::SwapBuffers(
+ cc::CompositorFrame* frame) {
+ DCHECK(frame->gl_frame_data);
+
+ GetCommandBufferProxy()->SetLatencyInfo(frame->metadata.latency_info);
if (reflector_.get()) {
if (frame->gl_frame_data->sub_buffer_rect ==
@@ -46,7 +68,40 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers(
reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect);
}
- OutputSurface::SwapBuffers(frame);
+ if (frame->gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame->gl_frame_data->size)) {
+ context_provider_->ContextSupport()->Swap();
+ } else {
+ context_provider_->ContextSupport()->PartialSwapBuffers(
+ frame->gl_frame_data->sub_buffer_rect);
+ }
+
+ client_->DidSwapBuffers();
+}
+
+void GpuBrowserCompositorOutputSurface::OnSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+#if defined(OS_MACOSX)
+ // On Mac, delay acknowledging the swap to the output surface client until
+ // it has been drawn, see OnSurfaceDisplayed();
+ NOTREACHED();
+#else
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&RenderWidgetHostImpl::CompositorFrameDrawn, latency_info));
+ }
+ OnSwapBuffersComplete();
+#endif
+}
+
+#if defined(OS_MACOSX)
+void GpuBrowserCompositorOutputSurface::OnSurfaceDisplayed() {
+ cc::OutputSurface::OnSwapBuffersComplete();
}
+#endif
} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
index dd1ac3f693d..c558b56c04b 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_COMPOSITOR_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#define CONTENT_BROWSER_COMPOSITOR_GPU_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
+#include "base/cancelable_callback.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
namespace ui {
@@ -16,6 +17,7 @@ class OverlayCandidateValidator;
}
namespace content {
+class CommandBufferProxyImpl;
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
// cc::OutputSurface that also handles vsync parameter updates
@@ -30,11 +32,22 @@ class GpuBrowserCompositorOutputSurface
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator);
- virtual ~GpuBrowserCompositorOutputSurface();
+ ~GpuBrowserCompositorOutputSurface() override;
- private:
+ protected:
// cc::OutputSurface implementation.
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ void SwapBuffers(cc::CompositorFrame* frame) override;
+ bool BindToClient(cc::OutputSurfaceClient* client) override;
+
+#if defined(OS_MACOSX)
+ void OnSurfaceDisplayed() override;
+#endif
+
+ CommandBufferProxyImpl* GetCommandBufferProxy();
+ void OnSwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info);
+
+ base::CancelableCallback<void(const std::vector<ui::LatencyInfo>&)>
+ swap_buffers_completion_callback_;
DISALLOW_COPY_AND_ASSIGN(GpuBrowserCompositorOutputSurface);
};
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index bdf7cb4904a..24e721f4201 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -18,11 +18,14 @@
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/browser_compositor_output_surface_proxy.h"
#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
+#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
#include "content/browser/compositor/onscreen_display_client.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/compositor/software_browser_compositor_output_surface.h"
#include "content/browser/compositor/surface_display_output_surface.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -67,11 +70,12 @@ struct GpuProcessTransportFactory::PerCompositorData {
};
GpuProcessTransportFactory::GpuProcessTransportFactory()
- : callback_factory_(this) {
+ : next_surface_id_namespace_(1u),
+ callback_factory_(this) {
output_surface_proxy_ = new BrowserCompositorOutputSurfaceProxy(
&output_surface_map_);
#if defined(OS_CHROMEOS)
- bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch(
+ bool use_thread = !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUIDisableThreadedCompositing);
#else
bool use_thread = false;
@@ -80,10 +84,8 @@ GpuProcessTransportFactory::GpuProcessTransportFactory()
compositor_thread_.reset(new base::Thread("Browser Compositor"));
compositor_thread_->Start();
}
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseSurfaces)) {
+ if (UseSurfacesEnabled())
surface_manager_ = make_scoped_ptr(new cc::SurfaceManager);
- }
}
GpuProcessTransportFactory::~GpuProcessTransportFactory() {
@@ -95,7 +97,11 @@ GpuProcessTransportFactory::~GpuProcessTransportFactory() {
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
- return CreateContextCommon(0);
+ CauseForGpuLaunch cause =
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
+ return CreateContextCommon(gpu_channel_host, 0);
}
scoped_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
@@ -123,8 +129,9 @@ scoped_ptr<cc::OverlayCandidateValidator> CreateOverlayCandidateValidator(
#if defined(USE_OZONE)
ui::OverlayCandidatesOzone* overlay_candidates =
ui::SurfaceFactoryOzone::GetInstance()->GetOverlayCandidates(widget);
- if (overlay_candidates && CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableHardwareOverlays)) {
+ if (overlay_candidates &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableHardwareOverlays)) {
return scoped_ptr<cc::OverlayCandidateValidator>(
new OverlayCandidateValidatorOzone(widget, overlay_candidates));
}
@@ -132,11 +139,13 @@ scoped_ptr<cc::OverlayCandidateValidator> CreateOverlayCandidateValidator(
return scoped_ptr<cc::OverlayCandidateValidator>();
}
-scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
- ui::Compositor* compositor, bool software_fallback) {
- PerCompositorData* data = per_compositor_data_[compositor];
+void GpuProcessTransportFactory::CreateOutputSurface(
+ base::WeakPtr<ui::Compositor> compositor,
+ bool software_fallback) {
+ DCHECK(!!compositor);
+ PerCompositorData* data = per_compositor_data_[compositor.get()];
if (!data)
- data = CreatePerCompositorData(compositor);
+ data = CreatePerCompositorData(compositor.get());
bool create_software_renderer = software_fallback;
#if defined(OS_CHROMEOS)
@@ -148,50 +157,89 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
create_software_renderer = true;
}
#endif
-
- scoped_refptr<ContextProviderCommandBuffer> context_provider;
+ if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
+ create_software_renderer = true;
if (!create_software_renderer) {
+ CauseForGpuLaunch cause =
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+ BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(
+ cause,
+ base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel,
+ callback_factory_.GetWeakPtr(),
+ compositor,
+ create_software_renderer));
+ } else {
+ EstablishedGpuChannel(compositor, create_software_renderer);
+ }
+}
+
+void GpuProcessTransportFactory::EstablishedGpuChannel(
+ base::WeakPtr<ui::Compositor> compositor,
+ bool create_software_renderer) {
+ if (!compositor)
+ return;
+ PerCompositorData* data = per_compositor_data_[compositor.get()];
+ DCHECK(data);
+ scoped_refptr<GpuChannelHost> gpu_channel_host =
+ BrowserGpuChannelHostFactory::instance()->GetGpuChannel();
+ scoped_refptr<ContextProviderCommandBuffer> context_provider;
+ if (gpu_channel_host.get() && !create_software_renderer) {
context_provider = ContextProviderCommandBuffer::Create(
- GpuProcessTransportFactory::CreateContextCommon(data->surface_id),
+ GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host,
+ data->surface_id),
"Compositor");
}
- UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor", !!context_provider);
+ UMA_HISTOGRAM_BOOLEAN("Aura.CreatedGpuBrowserCompositor",
+ !!context_provider.get());
+
+ if (context_provider.get()) {
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner =
+ GetCompositorMessageLoop();
+ if (!compositor_thread_task_runner.get())
+ compositor_thread_task_runner = base::MessageLoopProxy::current();
+
+ // Here we know the GpuProcessHost has been set up, because we created a
+ // context.
+ output_surface_proxy_->ConnectToGpuProcessHost(
+ compositor_thread_task_runner.get());
+ }
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseSurfaces)) {
+ if (UseSurfacesEnabled()) {
// This gets a bit confusing. Here we have a ContextProvider configured to
// render directly to this widget. We need to make an OnscreenDisplayClient
// associated with this context, then return a SurfaceDisplayOutputSurface
// set up to draw to the display's surface.
cc::SurfaceManager* manager = surface_manager_.get();
- scoped_ptr<cc::OutputSurface> software_surface;
- if (!context_provider) {
- software_surface =
+ scoped_ptr<cc::OutputSurface> display_surface;
+ if (!context_provider.get()) {
+ display_surface =
make_scoped_ptr(new SoftwareBrowserCompositorOutputSurface(
output_surface_proxy_,
- CreateSoftwareOutputDevice(compositor),
- per_compositor_data_[compositor]->surface_id,
+ CreateSoftwareOutputDevice(compositor.get()),
+ data->surface_id,
&output_surface_map_,
compositor->vsync_manager()));
+ } else {
+ display_surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface(
+ context_provider,
+ data->surface_id,
+ &output_surface_map_,
+ compositor->vsync_manager(),
+ CreateOverlayCandidateValidator(compositor->widget())));
}
scoped_ptr<OnscreenDisplayClient> display_client(new OnscreenDisplayClient(
- context_provider, software_surface.Pass(), manager));
- // TODO(jamesr): Need to set up filtering for the
- // GpuHostMsg_UpdateVSyncParameters message.
-
- scoped_refptr<cc::ContextProvider> offscreen_context_provider;
- if (context_provider) {
- offscreen_context_provider = ContextProviderCommandBuffer::Create(
- GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
- "Offscreen-Compositor");
- }
+ display_surface.Pass(), manager, compositor->task_runner()));
+
scoped_ptr<SurfaceDisplayOutputSurface> output_surface(
new SurfaceDisplayOutputSurface(
- display_client->display(), manager, offscreen_context_provider));
+ manager, compositor->surface_id_allocator(), context_provider));
+ display_client->set_surface_output_surface(output_surface.get());
+ output_surface->set_display_client(display_client.get());
data->display_client = display_client.Pass();
- return output_surface.PassAs<cc::OutputSurface>();
+ compositor->SetOutputSurface(output_surface.Pass());
+ return;
}
if (!context_provider.get()) {
@@ -203,34 +251,39 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
scoped_ptr<SoftwareBrowserCompositorOutputSurface> surface(
new SoftwareBrowserCompositorOutputSurface(
output_surface_proxy_,
- CreateSoftwareOutputDevice(compositor),
- per_compositor_data_[compositor]->surface_id,
+ CreateSoftwareOutputDevice(compositor.get()),
+ data->surface_id,
&output_surface_map_,
compositor->vsync_manager()));
- return surface.PassAs<cc::OutputSurface>();
+ compositor->SetOutputSurface(surface.Pass());
+ return;
}
- scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner =
- GetCompositorMessageLoop();
- if (!compositor_thread_task_runner.get())
- compositor_thread_task_runner = base::MessageLoopProxy::current();
-
- // Here we know the GpuProcessHost has been set up, because we created a
- // context.
- output_surface_proxy_->ConnectToGpuProcessHost(
- compositor_thread_task_runner.get());
+ scoped_ptr<BrowserCompositorOutputSurface> surface;
+#if defined(USE_OZONE)
+ if (ui::SurfaceFactoryOzone::GetInstance()->CanShowPrimaryPlaneAsOverlay()) {
+ surface.reset(new GpuSurfacelessBrowserCompositorOutputSurface(
+ context_provider,
+ data->surface_id,
+ &output_surface_map_,
+ compositor->vsync_manager(),
+ CreateOverlayCandidateValidator(compositor->widget()),
+ GL_RGB,
+ compositor_thread_ != nullptr));
+ }
+#endif
+ if (!surface)
+ surface.reset(new GpuBrowserCompositorOutputSurface(
+ context_provider,
+ data->surface_id,
+ &output_surface_map_,
+ compositor->vsync_manager(),
+ CreateOverlayCandidateValidator(compositor->widget())));
- scoped_ptr<BrowserCompositorOutputSurface> surface(
- new GpuBrowserCompositorOutputSurface(
- context_provider,
- per_compositor_data_[compositor]->surface_id,
- &output_surface_map_,
- compositor->vsync_manager(),
- CreateOverlayCandidateValidator(compositor->widget())));
if (data->reflector.get())
data->reflector->ReattachToOutputSurfaceFromMainThread(surface.get());
- return surface.PassAs<cc::OutputSurface>();
+ compositor->SetOutputSurface(surface.Pass());
}
scoped_refptr<ui::Reflector> GpuProcessTransportFactory::CreateReflector(
@@ -292,6 +345,11 @@ cc::SharedBitmapManager* GpuProcessTransportFactory::GetSharedBitmapManager() {
return HostSharedBitmapManager::current();
}
+gpu::GpuMemoryBufferManager*
+GpuProcessTransportFactory::GetGpuMemoryBufferManager() {
+ return BrowserGpuMemoryBufferManager::current();
+}
+
ui::ContextFactory* GpuProcessTransportFactory::GetContextFactory() {
return this;
}
@@ -299,17 +357,27 @@ ui::ContextFactory* GpuProcessTransportFactory::GetContextFactory() {
base::MessageLoopProxy* GpuProcessTransportFactory::GetCompositorMessageLoop() {
if (!compositor_thread_)
return NULL;
- return compositor_thread_->message_loop_proxy();
+ return compositor_thread_->message_loop_proxy().get();
}
gfx::GLSurfaceHandle GpuProcessTransportFactory::GetSharedSurfaceHandle() {
gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle(
- gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
+ gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
handle.parent_client_id =
BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
return handle;
}
+scoped_ptr<cc::SurfaceIdAllocator>
+GpuProcessTransportFactory::CreateSurfaceIdAllocator() {
+ return make_scoped_ptr(
+ new cc::SurfaceIdAllocator(next_surface_id_namespace_++));
+}
+
+cc::SurfaceManager* GpuProcessTransportFactory::GetSurfaceManager() {
+ return surface_manager_.get();
+}
+
GLHelper* GpuProcessTransportFactory::GetGLHelper() {
if (!gl_helper_ && !per_compositor_data_.empty()) {
scoped_refptr<cc::ContextProvider> provider =
@@ -353,7 +421,7 @@ GpuProcessTransportFactory::SharedMainThreadContextProvider() {
GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(),
"Offscreen-MainThread");
- if (shared_main_thread_contexts_) {
+ if (shared_main_thread_contexts_.get()) {
shared_main_thread_contexts_->SetLostContextCallback(
base::Bind(&GpuProcessTransportFactory::
OnLostMainThreadSharedContextInsideCallback,
@@ -384,7 +452,9 @@ GpuProcessTransportFactory::CreatePerCompositorData(
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
-GpuProcessTransportFactory::CreateContextCommon(int surface_id) {
+GpuProcessTransportFactory::CreateContextCommon(
+ scoped_refptr<GpuChannelHost> gpu_channel_host,
+ int surface_id) {
if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
blink::WebGraphicsContext3D::Attributes attrs;
@@ -394,11 +464,7 @@ GpuProcessTransportFactory::CreateContextCommon(int surface_id) {
attrs.antialias = false;
attrs.noAutomaticFlushes = true;
bool lose_context_when_out_of_memory = true;
- CauseForGpuLaunch cause =
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
- scoped_refptr<GpuChannelHost> gpu_channel_host(
- BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
- if (!gpu_channel_host) {
+ if (!gpu_channel_host.get()) {
LOG(ERROR) << "Failed to establish GPU channel.";
return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
}
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index b9c1bee1209..25cfbc0c53a 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "content/browser/compositor/image_transport_factory.h"
+#include "content/common/gpu/client/gpu_channel_host.h"
#include "ui/compositor/compositor.h"
namespace base {
@@ -37,43 +38,45 @@ class GpuProcessTransportFactory
public:
GpuProcessTransportFactory();
- virtual ~GpuProcessTransportFactory();
+ ~GpuProcessTransportFactory() override;
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
CreateOffscreenCommandBufferContext();
// ui::ContextFactory implementation.
- virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
- ui::Compositor* compositor, bool software_fallback) OVERRIDE;
- virtual scoped_refptr<ui::Reflector> CreateReflector(
- ui::Compositor* source,
- ui::Layer* target) OVERRIDE;
- virtual void RemoveReflector(
- scoped_refptr<ui::Reflector> reflector) OVERRIDE;
- virtual void RemoveCompositor(ui::Compositor* compositor) OVERRIDE;
- virtual scoped_refptr<cc::ContextProvider>
- SharedMainThreadContextProvider() OVERRIDE;
- virtual bool DoesCreateTestContexts() OVERRIDE;
- virtual cc::SharedBitmapManager* GetSharedBitmapManager() OVERRIDE;
- virtual base::MessageLoopProxy* GetCompositorMessageLoop() OVERRIDE;
+ void CreateOutputSurface(base::WeakPtr<ui::Compositor> compositor,
+ bool software_fallback) override;
+ scoped_refptr<ui::Reflector> CreateReflector(ui::Compositor* source,
+ ui::Layer* target) override;
+ void RemoveReflector(scoped_refptr<ui::Reflector> reflector) override;
+ void RemoveCompositor(ui::Compositor* compositor) override;
+ scoped_refptr<cc::ContextProvider> SharedMainThreadContextProvider() override;
+ bool DoesCreateTestContexts() override;
+ cc::SharedBitmapManager* GetSharedBitmapManager() override;
+ gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
+ base::MessageLoopProxy* GetCompositorMessageLoop() override;
+ scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() override;
// ImageTransportFactory implementation.
- virtual ui::ContextFactory* GetContextFactory() OVERRIDE;
- virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() OVERRIDE;
- virtual GLHelper* GetGLHelper() OVERRIDE;
- virtual void AddObserver(ImageTransportFactoryObserver* observer) OVERRIDE;
- virtual void RemoveObserver(
- ImageTransportFactoryObserver* observer) OVERRIDE;
+ ui::ContextFactory* GetContextFactory() override;
+ gfx::GLSurfaceHandle GetSharedSurfaceHandle() override;
+ cc::SurfaceManager* GetSurfaceManager() override;
+ GLHelper* GetGLHelper() override;
+ void AddObserver(ImageTransportFactoryObserver* observer) override;
+ void RemoveObserver(ImageTransportFactoryObserver* observer) override;
#if defined(OS_MACOSX)
- virtual void OnSurfaceDisplayed(int surface_id) OVERRIDE;
+ void OnSurfaceDisplayed(int surface_id) override;
#endif
private:
struct PerCompositorData;
PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor);
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
- CreateContextCommon(int surface_id);
+ void EstablishedGpuChannel(base::WeakPtr<ui::Compositor> compositor,
+ bool create_software_renderer);
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContextCommon(
+ scoped_refptr<GpuChannelHost> gpu_channel_host,
+ int surface_id);
void OnLostMainThreadSharedContextInsideCallback();
void OnLostMainThreadSharedContext();
@@ -84,8 +87,8 @@ class GpuProcessTransportFactory
scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
scoped_ptr<GLHelper> gl_helper_;
ObserverList<ImageTransportFactoryObserver> observer_list_;
- base::WeakPtrFactory<GpuProcessTransportFactory> callback_factory_;
scoped_ptr<cc::SurfaceManager> surface_manager_;
+ uint32_t next_surface_id_namespace_;
// The contents of this map and its methods may only be used on the compositor
// thread.
@@ -93,6 +96,8 @@ class GpuProcessTransportFactory
scoped_refptr<BrowserCompositorOutputSurfaceProxy> output_surface_proxy_;
+ base::WeakPtrFactory<GpuProcessTransportFactory> callback_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GpuProcessTransportFactory);
};
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
new file mode 100644
index 00000000000..c3d9cbbc056
--- /dev/null
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
@@ -0,0 +1,100 @@
+// Copyright 2014 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 "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
+
+#include "cc/output/compositor_frame.h"
+#include "content/browser/compositor/buffer_queue.h"
+#include "content/browser/compositor/reflector_impl.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/gpu/client/gl_helper.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+
+namespace content {
+
+GpuSurfacelessBrowserCompositorOutputSurface::
+ GpuSurfacelessBrowserCompositorOutputSurface(
+ const scoped_refptr<ContextProviderCommandBuffer>& context,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
+ scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator,
+ unsigned internalformat,
+ bool use_own_gl_helper)
+ : GpuBrowserCompositorOutputSurface(context,
+ surface_id,
+ output_surface_map,
+ vsync_manager,
+ overlay_candidate_validator.Pass()),
+ internalformat_(internalformat),
+ use_own_gl_helper_(use_own_gl_helper) {
+ capabilities_.uses_default_gl_framebuffer = false;
+ capabilities_.flipped_output_surface = true;
+}
+
+GpuSurfacelessBrowserCompositorOutputSurface::
+ ~GpuSurfacelessBrowserCompositorOutputSurface() {
+}
+
+void GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers(
+ cc::CompositorFrame* frame) {
+ DCHECK(output_surface_);
+
+ GLuint texture = output_surface_->current_texture_id();
+ output_surface_->SwapBuffers(frame->gl_frame_data->sub_buffer_rect);
+ const gfx::Size& size = frame->gl_frame_data->size;
+ context_provider_->ContextGL()->ScheduleOverlayPlaneCHROMIUM(
+ 0,
+ GL_OVERLAY_TRANSFORM_NONE_CHROMIUM,
+ texture,
+ 0,
+ 0,
+ size.width(),
+ size.height(),
+ 0,
+ 0,
+ 1.0f,
+ 1.0f);
+ GpuBrowserCompositorOutputSurface::SwapBuffers(frame);
+}
+
+void GpuSurfacelessBrowserCompositorOutputSurface::OnSwapBuffersComplete() {
+ DCHECK(output_surface_);
+ output_surface_->PageFlipComplete();
+ GpuBrowserCompositorOutputSurface::OnSwapBuffersComplete();
+}
+
+void GpuSurfacelessBrowserCompositorOutputSurface::BindFramebuffer() {
+ DCHECK(output_surface_);
+ output_surface_->BindFramebuffer();
+}
+
+void GpuSurfacelessBrowserCompositorOutputSurface::Reshape(
+ const gfx::Size& size,
+ float scale_factor) {
+ GpuBrowserCompositorOutputSurface::Reshape(size, scale_factor);
+ DCHECK(output_surface_);
+ output_surface_->Reshape(SurfaceSize(), scale_factor);
+}
+
+bool GpuSurfacelessBrowserCompositorOutputSurface::BindToClient(
+ cc::OutputSurfaceClient* client) {
+ if (!GpuBrowserCompositorOutputSurface::BindToClient(client))
+ return false;
+ GLHelper* helper;
+ if (use_own_gl_helper_) {
+ gl_helper_.reset(new GLHelper(context_provider_->ContextGL(),
+ context_provider_->ContextSupport()));
+ helper = gl_helper_.get();
+ } else {
+ helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+ }
+ output_surface_.reset(
+ new BufferQueue(context_provider_, internalformat_, helper));
+ return output_surface_->Initialize();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
new file mode 100644
index 00000000000..e95ab7a5223
--- /dev/null
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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 CONTENT_BROWSER_COMPOSITOR_GPU_SURFACELESS_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
+#define CONTENT_BROWSER_COMPOSITOR_GPU_SURFACELESS_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
+
+#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
+
+namespace content {
+
+class BufferQueue;
+class GLHelper;
+
+class GpuSurfacelessBrowserCompositorOutputSurface
+ : public GpuBrowserCompositorOutputSurface {
+ public:
+ GpuSurfacelessBrowserCompositorOutputSurface(
+ const scoped_refptr<ContextProviderCommandBuffer>& context,
+ int surface_id,
+ IDMap<BrowserCompositorOutputSurface>* output_surface_map,
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager,
+ scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator,
+ unsigned internalformat,
+ bool use_own_gl_helper);
+ ~GpuSurfacelessBrowserCompositorOutputSurface() override;
+
+ private:
+ // cc::OutputSurface implementation.
+ void SwapBuffers(cc::CompositorFrame* frame) override;
+ void OnSwapBuffersComplete() override;
+ void BindFramebuffer() override;
+ void Reshape(const gfx::Size& size, float scale_factor) override;
+ bool BindToClient(cc::OutputSurfaceClient* client) override;
+
+ unsigned int internalformat_;
+ bool use_own_gl_helper_;
+ scoped_ptr<GLHelper> gl_helper_;
+ scoped_ptr<BufferQueue> output_surface_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_GPU_SURFACELESS_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
diff --git a/chromium/content/browser/compositor/image_transport_factory.cc b/chromium/content/browser/compositor/image_transport_factory.cc
index 66d484f51eb..6f06a973168 100644
--- a/chromium/content/browser/compositor/image_transport_factory.cc
+++ b/chromium/content/browser/compositor/image_transport_factory.cc
@@ -6,7 +6,6 @@
#include "base/command_line.h"
#include "content/browser/compositor/gpu_process_transport_factory.h"
-#include "content/browser/compositor/no_transport_image_transport_factory.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gl/gl_implementation.h"
@@ -33,16 +32,17 @@ void ImageTransportFactory::Initialize() {
}
void ImageTransportFactory::InitializeForUnitTests(
- scoped_ptr<ui::ContextFactory> test_factory) {
+ scoped_ptr<ImageTransportFactory> factory) {
DCHECK(!g_factory);
DCHECK(!g_initialized_for_unit_tests);
g_initialized_for_unit_tests = true;
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnablePixelOutputInTests))
g_disable_null_draw = new gfx::DisableNullDrawGLBindings;
- SetFactory(new NoTransportImageTransportFactory(test_factory.Pass()));
+ SetFactory(factory.release());
}
// static
diff --git a/chromium/content/browser/compositor/image_transport_factory.h b/chromium/content/browser/compositor/image_transport_factory.h
index f53c4a7028f..4b5dec10629 100644
--- a/chromium/content/browser/compositor/image_transport_factory.h
+++ b/chromium/content/browser/compositor/image_transport_factory.h
@@ -9,9 +9,14 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "cc/surfaces/surface_id_allocator.h"
#include "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
+namespace cc {
+class SurfaceManager;
+}
+
namespace gfx {
class Size;
}
@@ -55,8 +60,7 @@ class CONTENT_EXPORT ImageTransportFactory {
// Initializes the global transport factory for unit tests using the provided
// context factory.
- static void InitializeForUnitTests(
- scoped_ptr<ui::ContextFactory> test_factory);
+ static void InitializeForUnitTests(scoped_ptr<ImageTransportFactory> factory);
// Terminates the global transport factory.
static void Terminate();
@@ -68,6 +72,7 @@ class CONTENT_EXPORT ImageTransportFactory {
virtual ui::ContextFactory* GetContextFactory() = 0;
virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() = 0;
+ virtual cc::SurfaceManager* GetSurfaceManager() = 0;
// Gets a GLHelper instance, associated with the shared context. This
// GLHelper will get destroyed whenever the shared context is lost
diff --git a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
index 61f1bbf107f..327db05f62f 100644
--- a/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
+++ b/chromium/content/browser/compositor/image_transport_factory_browsertest.cc
@@ -24,9 +24,9 @@ class MockImageTransportFactoryObserver : public ImageTransportFactoryObserver {
MOCK_METHOD0(OnLostResources, void());
};
-// This crashes on Mac ASAN
-// http://crbug.com/335083
-#if defined(OS_MACOSX)
+// This crashes on Mac ASAN: http://crbug.com/335083
+// Flaky on ChromeOS: crbug.com/394083
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
#define MAYBE_TestLostContext DISABLED_TestLostContext
#else
#define MAYBE_TestLostContext TestLostContext
@@ -72,8 +72,8 @@ class ImageTransportFactoryTearDownBrowserTest : public ContentBrowserTest {
public:
ImageTransportFactoryTearDownBrowserTest() {}
- virtual void TearDown() {
- if (mailbox_)
+ void TearDown() override {
+ if (mailbox_.get())
EXPECT_TRUE(mailbox_->mailbox().IsZero());
ContentBrowserTest::TearDown();
}
diff --git a/chromium/content/browser/compositor/io_surface_context_mac.h b/chromium/content/browser/compositor/io_surface_context_mac.h
new file mode 100644
index 00000000000..4e5802a0175
--- /dev/null
+++ b/chromium/content/browser/compositor/io_surface_context_mac.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2013 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 CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_CONTEXT_MAC_H_
+#define CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_CONTEXT_MAC_H_
+
+#include <OpenGL/OpenGL.h>
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gl/gpu_switching_observer.h"
+#include "ui/gl/scoped_cgl.h"
+
+namespace content {
+
+class IOSurfaceContext
+ : public base::RefCounted<IOSurfaceContext>,
+ public ui::GpuSwitchingObserver {
+ public:
+ enum Type {
+ // The number used to look up the context used for async readback and for
+ // initializing the IOSurface.
+ kOffscreenContext = -2,
+ // The number used to look up the context used by CAOpenGLLayers.
+ kCALayerContext = -3,
+ };
+
+ // Get or create a GL context of the specified type. Share these GL contexts
+ // as much as possible because creating and destroying them can be expensive.
+ // http://crbug.com/180463
+ static scoped_refptr<IOSurfaceContext> Get(Type type);
+
+ // Mark that all the GL contexts in the same sharegroup as this context as
+ // invalid, so they shouldn't be returned anymore by Get, but rather, new
+ // contexts should be created. This is called as a precaution when unexpected
+ // GL errors occur, or after a GPU switch.
+ void PoisonContextAndSharegroup();
+ bool HasBeenPoisoned() const { return poisoned_; }
+
+ CGLContextObj cgl_context() const { return cgl_context_; }
+
+ // content::GpuDataManagerObserver implementation.
+ void OnGpuSwitched() override;
+
+ private:
+ friend class base::RefCounted<IOSurfaceContext>;
+
+ IOSurfaceContext(
+ Type type,
+ base::ScopedTypeRef<CGLContextObj> clg_context_strong);
+ virtual ~IOSurfaceContext();
+
+ Type type_;
+ base::ScopedTypeRef<CGLContextObj> cgl_context_;
+
+ bool poisoned_;
+
+ // The global map from window number and window ordering to
+ // context data.
+ typedef std::map<Type, IOSurfaceContext*> TypeMap;
+ static base::LazyInstance<TypeMap> type_map_;
+ static TypeMap* type_map();
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_CONTEXT_MAC_H_
diff --git a/chromium/content/browser/compositor/io_surface_context_mac.mm b/chromium/content/browser/compositor/io_surface_context_mac.mm
new file mode 100644
index 00000000000..82c81b1a949
--- /dev/null
+++ b/chromium/content/browser/compositor/io_surface_context_mac.mm
@@ -0,0 +1,121 @@
+// Copyright (c) 2013 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 "content/browser/compositor/io_surface_context_mac.h"
+
+#include <OpenGL/gl.h>
+#include <OpenGL/OpenGL.h>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/gl/gl_switches.h"
+#include "ui/gl/gpu_switching_manager.h"
+
+namespace content {
+
+// static
+scoped_refptr<IOSurfaceContext>
+IOSurfaceContext::Get(Type type) {
+ TRACE_EVENT0("browser", "IOSurfaceContext::Get");
+
+ // Return the context for this type, if it exists.
+ TypeMap::iterator found = type_map()->find(type);
+ if (found != type_map()->end()) {
+ DCHECK(!found->second->poisoned_);
+ return found->second;
+ }
+
+ base::ScopedTypeRef<CGLContextObj> cgl_context;
+ CGLError error = kCGLNoError;
+
+ // Create the pixel format object for the context.
+ std::vector<CGLPixelFormatAttribute> attribs;
+ attribs.push_back(kCGLPFADepthSize);
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
+ if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
+ attribs.push_back(kCGLPFAAllowOfflineRenderers);
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>(1));
+ }
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
+ GLint number_virtual_screens = 0;
+ base::ScopedTypeRef<CGLPixelFormatObj> pixel_format;
+ error = CGLChoosePixelFormat(&attribs.front(),
+ pixel_format.InitializeInto(),
+ &number_virtual_screens);
+ if (error != kCGLNoError) {
+ LOG(ERROR) << "Failed to create pixel format object.";
+ return NULL;
+ }
+
+ // Create all contexts in the same share group so that the textures don't
+ // need to be recreated when transitioning contexts.
+ CGLContextObj share_context = NULL;
+ if (!type_map()->empty())
+ share_context = type_map()->begin()->second->cgl_context();
+ error = CGLCreateContext(
+ pixel_format, share_context, cgl_context.InitializeInto());
+ if (error != kCGLNoError) {
+ LOG(ERROR) << "Failed to create context object.";
+ return NULL;
+ }
+
+ return new IOSurfaceContext(type, cgl_context);
+}
+
+void IOSurfaceContext::PoisonContextAndSharegroup() {
+ if (poisoned_)
+ return;
+
+ for (TypeMap::iterator it = type_map()->begin();
+ it != type_map()->end();
+ ++it) {
+ it->second->poisoned_ = true;
+ }
+ type_map()->clear();
+}
+
+IOSurfaceContext::IOSurfaceContext(
+ Type type, base::ScopedTypeRef<CGLContextObj> cgl_context)
+ : type_(type), cgl_context_(cgl_context), poisoned_(false) {
+ DCHECK(type_map()->find(type_) == type_map()->end());
+ type_map()->insert(std::make_pair(type_, this));
+
+ ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
+}
+
+IOSurfaceContext::~IOSurfaceContext() {
+ ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
+
+ if (!poisoned_) {
+ DCHECK(type_map()->find(type_) != type_map()->end());
+ DCHECK(type_map()->find(type_)->second == this);
+ type_map()->erase(type_);
+ } else {
+ TypeMap::const_iterator found = type_map()->find(type_);
+ if (found != type_map()->end())
+ DCHECK(found->second != this);
+ }
+}
+
+void IOSurfaceContext::OnGpuSwitched() {
+ // Recreate all browser-side GL contexts whenever the GPU switches. If this
+ // is not done, performance will suffer.
+ // http://crbug.com/361493
+ PoisonContextAndSharegroup();
+}
+
+// static
+IOSurfaceContext::TypeMap*
+ IOSurfaceContext::type_map() {
+ return type_map_.Pointer();
+}
+
+// static
+base::LazyInstance<IOSurfaceContext::TypeMap>
+ IOSurfaceContext::type_map_;
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/io_surface_layer_mac.h b/chromium/content/browser/compositor/io_surface_layer_mac.h
new file mode 100644
index 00000000000..5a218e8f665
--- /dev/null
+++ b/chromium/content/browser/compositor/io_surface_layer_mac.h
@@ -0,0 +1,161 @@
+// Copyright 2013 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 CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_LAYER_MAC_H_
+#define CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_LAYER_MAC_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ref_counted.h"
+#include "base/timer/timer.h"
+#include "ui/gfx/size.h"
+
+@class IOSurfaceLayer;
+
+namespace content {
+class IOSurfaceTexture;
+class IOSurfaceContext;
+
+// The interface through which the IOSurfaceLayer calls back into
+// the structrue that created it (RenderWidgetHostViewMac or
+// BrowserCompositorViewMac).
+class IOSurfaceLayerClient {
+ public:
+ // Used to indicate that the layer should attempt to draw immediately and
+ // should (even if the draw is elided by the system), ack the frame
+ // immediately.
+ virtual bool IOSurfaceLayerShouldAckImmediately() const = 0;
+
+ // Called when a frame is drawn or when, because the layer is not visible, it
+ // is known that the frame will never drawn.
+ virtual void IOSurfaceLayerDidDrawFrame() = 0;
+
+ // Called when an error prevents the frame from being drawn.
+ virtual void IOSurfaceLayerHitError() = 0;
+};
+
+// IOSurfaceLayerHelper provides C++ functionality needed for the
+// IOSurfaceLayer class, and does most of the heavy lifting for the
+// class.
+// TODO(ccameron): This class should own IOSurfaceLayer, rather than
+// vice versa.
+class IOSurfaceLayerHelper {
+ public:
+ IOSurfaceLayerHelper(IOSurfaceLayerClient* client,
+ IOSurfaceLayer* layer);
+ ~IOSurfaceLayerHelper();
+
+ // Called when the IOSurfaceLayer gets a new frame.
+ void GotNewFrame();
+
+ // Called whenever -[IOSurfaceLayer setNeedsDisplay] is called.
+ void SetNeedsDisplay();
+
+ // Called whenever -[IOSurfaceLayer canDrawInCGLContext] is called,
+ // to determine if a new frame should be drawn.
+ bool CanDraw();
+
+ // Called whenever -[IOSurfaceLayer drawInCGLContext] draws a
+ // frame.
+ void DidDraw(bool success);
+
+ // Immediately re-draw the layer, even if the content has not changed, and
+ // ensure that the frame be acked.
+ void SetNeedsDisplayAndDisplayAndAck();
+
+ // Immediately draw the layer, only if one is pending, and ensure that the
+ // frame be acked.
+ void DisplayIfNeededAndAck();
+
+ // Mark a bracket in which new frames are being pumped in a restricted nested
+ // run loop. During this time frames are acked immediately and draws are
+ // deferred until the bracket ends.
+ void BeginPumpingFrames();
+ void EndPumpingFrames();
+
+ private:
+ // Called whenever the frame provided in GotNewFrame should be acknowledged
+ // (this may be because it was drawn, or it may be to unblock the
+ // compositor).
+ void AckPendingFrame(bool success);
+
+ void TimerFired();
+
+ // The client that the owning layer was created with.
+ content::IOSurfaceLayerClient* const client_;
+
+ // The layer that owns this helper.
+ IOSurfaceLayer* const layer_;
+
+ // Used to track when canDrawInCGLContext should return YES. This can be
+ // in response to receiving a new compositor frame, or from any of the events
+ // that cause setNeedsDisplay to be called on the layer.
+ bool needs_display_;
+
+ // This is set when a frame is received, and un-set when the frame is drawn.
+ bool has_pending_frame_;
+
+ // Incremented every time that this layer is asked to draw but does not have
+ // new content to draw.
+ uint64 did_not_draw_counter_;
+
+ // Set when inside a BeginPumpingFrames/EndPumpingFrames block.
+ bool is_pumping_frames_;
+
+ // The browser places back-pressure on the GPU by not acknowledging swap
+ // calls until they appear on the screen. This can lead to hangs if the
+ // view is moved offscreen (among other things). Prevent hangs by always
+ // acknowledging the frame after timeout of 1/6th of a second has passed.
+ base::DelayTimer<IOSurfaceLayerHelper> timer_;
+};
+
+} // namespace content
+
+// The CoreAnimation layer for drawing accelerated content.
+@interface IOSurfaceLayer : CAOpenGLLayer {
+ @private
+ scoped_refptr<content::IOSurfaceTexture> iosurface_;
+ scoped_refptr<content::IOSurfaceContext> context_;
+
+ scoped_ptr<content::IOSurfaceLayerHelper> helper_;
+}
+
+- (id)initWithClient:(content::IOSurfaceLayerClient*)client
+ withScaleFactor:(float)scale_factor;
+
+- (bool)gotFrameWithIOSurface:(IOSurfaceID)io_surface_id
+ withPixelSize:(gfx::Size)pixel_size
+ withScaleFactor:(float)scale_factor;
+
+// Context poison accessors.
+- (void)poisonContextAndSharegroup;
+- (bool)hasBeenPoisoned;
+
+- (float)scaleFactor;
+
+// The CGL renderer ID.
+- (int)rendererID;
+
+// Mark that the client is no longer valid and cannot be called back into. This
+// must be called before the layer is destroyed.
+- (void)resetClient;
+
+// Called when a new frame is received.
+- (void)gotNewFrame;
+
+// Force a draw immediately (even if this means re-displaying a previously
+// displayed frame).
+- (void)setNeedsDisplayAndDisplayAndAck;
+
+// Force a draw immediately, but only if one was requested.
+- (void)displayIfNeededAndAck;
+
+// Mark a bracket in which new frames are being pumped in a restricted nested
+// run loop.
+- (void)beginPumpingFrames;
+- (void)endPumpingFrames;
+@end
+
+#endif // CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_LAYER_MAC_H_
diff --git a/chromium/content/browser/compositor/io_surface_layer_mac.mm b/chromium/content/browser/compositor/io_surface_layer_mac.mm
new file mode 100644
index 00000000000..d09f24c4902
--- /dev/null
+++ b/chromium/content/browser/compositor/io_surface_layer_mac.mm
@@ -0,0 +1,302 @@
+// Copyright 2013 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 "content/browser/compositor/io_surface_layer_mac.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <OpenGL/CGLIOSurface.h>
+#include <OpenGL/CGLRenderers.h>
+#include <OpenGL/gl.h>
+#include <OpenGL/OpenGL.h>
+
+#include "base/mac/mac_util.h"
+#include "base/mac/sdk_forward_declarations.h"
+#include "content/browser/compositor/io_surface_context_mac.h"
+#include "content/browser/compositor/io_surface_texture_mac.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#include "ui/base/cocoa/animation_utils.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/gl/gpu_switching_manager.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// IOSurfaceLayerHelper
+
+namespace content {
+
+IOSurfaceLayerHelper::IOSurfaceLayerHelper(
+ IOSurfaceLayerClient* client,
+ IOSurfaceLayer* layer)
+ : client_(client),
+ layer_(layer),
+ needs_display_(false),
+ has_pending_frame_(false),
+ did_not_draw_counter_(0),
+ is_pumping_frames_(false),
+ timer_(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(1) / 6,
+ this,
+ &IOSurfaceLayerHelper::TimerFired) {}
+
+IOSurfaceLayerHelper::~IOSurfaceLayerHelper() {
+ // Any acks that were waiting on this layer to draw will not occur, so ack
+ // them now to prevent blocking the renderer.
+ AckPendingFrame(true);
+}
+
+void IOSurfaceLayerHelper::GotNewFrame() {
+ // A trace value of 2 indicates that there is a pending swap ack. See
+ // canDrawInCGLContext for other value meanings.
+ TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, 2);
+
+ has_pending_frame_ = true;
+ needs_display_ = true;
+ timer_.Reset();
+
+ // If reqested, draw immediately and don't bother trying to use the
+ // isAsynchronous property to ensure smooth animation. If this is while
+ // frames are being pumped then ack and display immediately to get a
+ // correct-sized frame displayed as soon as possible.
+ if (is_pumping_frames_ || client_->IOSurfaceLayerShouldAckImmediately()) {
+ SetNeedsDisplayAndDisplayAndAck();
+ } else {
+ if (![layer_ isAsynchronous])
+ [layer_ setAsynchronous:YES];
+ }
+}
+
+void IOSurfaceLayerHelper::SetNeedsDisplay() {
+ needs_display_ = true;
+}
+
+bool IOSurfaceLayerHelper::CanDraw() {
+ // If we return NO 30 times in a row, switch to being synchronous to avoid
+ // burning CPU cycles on this callback.
+ if (needs_display_) {
+ did_not_draw_counter_ = 0;
+ } else {
+ did_not_draw_counter_ += 1;
+ if (did_not_draw_counter_ == 30)
+ [layer_ setAsynchronous:NO];
+ }
+
+ // Add an instantaneous blip to the PendingSwapAck state to indicate
+ // that CoreAnimation asked if a frame is ready. A blip up to to 3 (usually
+ // from 2, indicating that a swap ack is pending) indicates that we
+ // requested a draw. A blip up to 1 (usually from 0, indicating there is no
+ // pending swap ack) indicates that we did not request a draw. This would
+ // be more natural to do with a tracing pseudo-thread
+ // http://crbug.com/366300
+ TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, needs_display_ ? 3 : 1);
+ TRACE_COUNTER_ID1("browser", "PendingSwapAck", this,
+ has_pending_frame_ ? 2 : 0);
+
+ return needs_display_;
+}
+
+void IOSurfaceLayerHelper::DidDraw(bool success) {
+ needs_display_ = false;
+ AckPendingFrame(success);
+}
+
+void IOSurfaceLayerHelper::AckPendingFrame(bool success) {
+ if (!has_pending_frame_)
+ return;
+ has_pending_frame_ = false;
+ if (success)
+ client_->IOSurfaceLayerDidDrawFrame();
+ else
+ client_->IOSurfaceLayerHitError();
+ // A trace value of 0 indicates that there is no longer a pending swap ack.
+ TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, 0);
+}
+
+void IOSurfaceLayerHelper::SetNeedsDisplayAndDisplayAndAck() {
+ // Drawing using setNeedsDisplay and displayIfNeeded will result in
+ // subsequent canDrawInCGLContext callbacks getting dropped, and jerky
+ // animation. Disable asynchronous drawing before issuing these calls as a
+ // workaround.
+ // http://crbug.com/395827
+ if ([layer_ isAsynchronous])
+ [layer_ setAsynchronous:NO];
+
+ [layer_ setNeedsDisplay];
+ DisplayIfNeededAndAck();
+}
+
+void IOSurfaceLayerHelper::DisplayIfNeededAndAck() {
+ if (!needs_display_)
+ return;
+
+ // As in SetNeedsDisplayAndDisplayAndAck, disable asynchronous drawing before
+ // issuing displayIfNeeded.
+ // http://crbug.com/395827
+ if ([layer_ isAsynchronous])
+ [layer_ setAsynchronous:NO];
+
+ // Do not bother drawing while pumping new frames -- wait until the waiting
+ // block ends to draw any of the new frames.
+ if (!is_pumping_frames_)
+ [layer_ displayIfNeeded];
+
+ // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
+ // rapidly (e.g, with vsync off). This is unacceptable because the failure
+ // to ack a single frame will hang the renderer. Ensure that the renderer
+ // not be blocked by lying and claiming that we drew the frame.
+ AckPendingFrame(true);
+}
+
+void IOSurfaceLayerHelper::TimerFired() {
+ DisplayIfNeededAndAck();
+}
+
+void IOSurfaceLayerHelper::BeginPumpingFrames() {
+ is_pumping_frames_ = true;
+}
+
+void IOSurfaceLayerHelper::EndPumpingFrames() {
+ is_pumping_frames_ = false;
+ DisplayIfNeededAndAck();
+}
+
+} // namespace content
+
+////////////////////////////////////////////////////////////////////////////////
+// IOSurfaceLayer
+
+@implementation IOSurfaceLayer
+
+- (id)initWithClient:(content::IOSurfaceLayerClient*)client
+ withScaleFactor:(float)scale_factor {
+ if (self = [super init]) {
+ helper_.reset(new content::IOSurfaceLayerHelper(client, self));
+
+ iosurface_ = content::IOSurfaceTexture::Create();
+ context_ = content::IOSurfaceContext::Get(
+ content::IOSurfaceContext::kCALayerContext);
+ if (!iosurface_.get() || !context_.get()) {
+ LOG(ERROR) << "Failed create CompositingIOSurface or context";
+ [self resetClient];
+ [self release];
+ return nil;
+ }
+
+ [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
+ [self setAnchorPoint:CGPointMake(0, 0)];
+ // Setting contents gravity is necessary to prevent the layer from being
+ // scaled during dyanmic resizes (especially with devtools open).
+ [self setContentsGravity:kCAGravityTopLeft];
+ if ([self respondsToSelector:(@selector(setContentsScale:))]) {
+ [self setContentsScale:scale_factor];
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ DCHECK(!helper_);
+ [super dealloc];
+}
+
+- (bool)gotFrameWithIOSurface:(IOSurfaceID)io_surface_id
+ withPixelSize:(gfx::Size)pixel_size
+ withScaleFactor:(float)scale_factor {
+ return iosurface_->SetIOSurface(io_surface_id, pixel_size);
+}
+
+- (void)poisonContextAndSharegroup {
+ context_->PoisonContextAndSharegroup();
+}
+
+- (bool)hasBeenPoisoned {
+ return context_->HasBeenPoisoned();
+}
+
+- (float)scaleFactor {
+ if ([self respondsToSelector:(@selector(contentsScale))])
+ return [self contentsScale];
+ return 1;
+}
+
+- (int)rendererID {
+ GLint current_renderer_id = -1;
+ if (CGLGetParameter(context_->cgl_context(),
+ kCGLCPCurrentRendererID,
+ &current_renderer_id) == kCGLNoError) {
+ return current_renderer_id & kCGLRendererIDMatchingMask;
+ }
+ return -1;
+}
+
+- (void)resetClient {
+ helper_.reset();
+}
+
+- (void)gotNewFrame {
+ helper_->GotNewFrame();
+}
+
+- (void)setNeedsDisplayAndDisplayAndAck {
+ helper_->SetNeedsDisplayAndDisplayAndAck();
+}
+
+- (void)displayIfNeededAndAck {
+ helper_->DisplayIfNeededAndAck();
+}
+
+- (void)beginPumpingFrames {
+ helper_->BeginPumpingFrames();
+}
+
+- (void)endPumpingFrames {
+ helper_->EndPumpingFrames();
+}
+
+// The remaining methods implement the CAOpenGLLayer interface.
+
+- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
+ if (!context_.get())
+ return [super copyCGLPixelFormatForDisplayMask:mask];
+ return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context()));
+}
+
+- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
+ if (!context_.get())
+ return [super copyCGLContextForPixelFormat:pixelFormat];
+ return CGLRetainContext(context_->cgl_context());
+}
+
+- (void)setNeedsDisplay {
+ if (helper_)
+ helper_->SetNeedsDisplay();
+ [super setNeedsDisplay];
+}
+
+- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ if (helper_)
+ return helper_->CanDraw();
+ return NO;
+}
+
+- (void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ TRACE_EVENT0("browser", "IOSurfaceLayer::drawInCGLContext");
+
+ bool draw_succeeded = iosurface_->DrawIOSurface();
+ if (helper_)
+ helper_->DidDraw(draw_succeeded);
+
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
+}
+
+@end
diff --git a/chromium/content/browser/compositor/io_surface_texture_mac.h b/chromium/content/browser/compositor/io_surface_texture_mac.h
new file mode 100644
index 00000000000..595c91232dc
--- /dev/null
+++ b/chromium/content/browser/compositor/io_surface_texture_mac.h
@@ -0,0 +1,121 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_TEXTURE_MAC_H_
+#define CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_TEXTURE_MAC_H_
+
+#include <deque>
+#include <list>
+#include <vector>
+
+#import <Cocoa/Cocoa.h>
+#include <IOSurface/IOSurfaceAPI.h>
+#include <QuartzCore/QuartzCore.h>
+
+#include "base/callback.h"
+#include "base/lazy_instance.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "media/base/video_frame.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/size.h"
+
+class SkBitmap;
+
+namespace gfx {
+class Rect;
+}
+
+namespace content {
+
+class IOSurfaceContext;
+class RenderWidgetHostViewFrameSubscriber;
+class RenderWidgetHostViewMac;
+
+// This class manages an OpenGL context and IOSurfaceTexture for the accelerated
+// compositing code path. The GL context is attached to
+// RenderWidgetHostViewCocoa for blitting the IOSurfaceTexture.
+class IOSurfaceTexture
+ : public base::RefCounted<IOSurfaceTexture> {
+ public:
+ // Returns NULL if IOSurfaceTexture or GL API calls fail.
+ static scoped_refptr<IOSurfaceTexture> Create();
+
+ // Set IOSurfaceTexture that will be drawn on the next NSView drawRect.
+ bool SetIOSurface(
+ IOSurfaceID io_surface_id,
+ const gfx::Size& pixel_size) WARN_UNUSED_RESULT;
+
+ // Blit the IOSurface to the rectangle specified by |window_rect| in DIPs,
+ // with the origin in the lower left corner. If the window rect's size is
+ // larger than the IOSurface, the remaining right and bottom edges will be
+ // white. |window_scale_factor| is 1 in normal views, 2 in HiDPI views.
+ bool DrawIOSurface() WARN_UNUSED_RESULT;
+
+ // Returns true if the offscreen context used by this surface has been
+ // poisoned.
+ bool HasBeenPoisoned() const;
+
+ private:
+ friend class base::RefCounted<IOSurfaceTexture>;
+
+ IOSurfaceTexture(
+ const scoped_refptr<IOSurfaceContext>& context);
+ ~IOSurfaceTexture();
+
+ // Unref the IOSurfaceTexture and delete the associated GL texture. If the GPU
+ // process is no longer referencing it, this will delete the IOSurface.
+ void ReleaseIOSurfaceAndTexture();
+
+ // Check for GL errors and store the result in error_. Only return new
+ // errors
+ GLenum GetAndSaveGLError();
+
+ // Offscreen context used for all operations other than drawing to the
+ // screen. This is in the same share group as the contexts used for
+ // drawing, and is the same for all IOSurfaces in all windows.
+ scoped_refptr<IOSurfaceContext> offscreen_context_;
+
+ // The IOSurface and its non-rounded size.
+ base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
+ gfx::Size pixel_size_;
+
+ // The "live" OpenGL texture referring to this IOSurfaceRef. Note
+ // that per the CGLTexImageIOSurface2D API we do not need to
+ // explicitly update this texture's contents once created. All we
+ // need to do is ensure it is re-bound before attempting to draw
+ // with it.
+ GLuint texture_;
+
+ // Error saved by GetAndSaveGLError
+ GLint gl_error_;
+
+ // Aggressive IOSurface eviction logic. When using CoreAnimation, IOSurfaces
+ // are used only transiently to transfer from the GPU process to the browser
+ // process. Once the IOSurface has been drawn to its CALayer, the CALayer
+ // will not need updating again until its view is hidden and re-shown.
+ // Aggressively evict surfaces when more than 8 (the number allowed by the
+ // memory manager for fast tab switching) are allocated.
+ enum {
+ kMaximumUnevictedSurfaces = 8,
+ };
+ typedef std::list<IOSurfaceTexture*> EvictionQueue;
+ void EvictionMarkUpdated();
+ void EvictionMarkEvicted();
+ EvictionQueue::iterator eviction_queue_iterator_;
+ bool eviction_has_been_drawn_since_updated_;
+
+ static void EvictionScheduleDoEvict();
+ static void EvictionDoEvict();
+ static base::LazyInstance<EvictionQueue> eviction_queue_;
+ static bool eviction_scheduled_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_COMPOSITOR_IO_SURFACE_TEXTURE_MAC_H_
diff --git a/chromium/content/browser/compositor/io_surface_texture_mac.mm b/chromium/content/browser/compositor/io_surface_texture_mac.mm
new file mode 100644
index 00000000000..dea6b287682
--- /dev/null
+++ b/chromium/content/browser/compositor/io_surface_texture_mac.mm
@@ -0,0 +1,297 @@
+// Copyright (c) 2012 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 "content/browser/compositor/io_surface_texture_mac.h"
+
+#include <OpenGL/CGLIOSurface.h>
+#include <OpenGL/CGLRenderers.h>
+#include <OpenGL/OpenGL.h>
+#include <OpenGL/gl.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/mac/bind_objc_block.h"
+#include "base/mac/mac_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/threading/platform_thread.h"
+#include "content/browser/compositor/io_surface_context_mac.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#include "content/common/content_constants_internal.h"
+#include "gpu/config/gpu_driver_bug_workaround_type.h"
+#include "media/base/video_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/gl/gl_context.h"
+
+namespace content {
+
+// static
+scoped_refptr<IOSurfaceTexture> IOSurfaceTexture::Create() {
+ scoped_refptr<IOSurfaceContext> offscreen_context =
+ IOSurfaceContext::Get(
+ IOSurfaceContext::kOffscreenContext);
+ if (!offscreen_context.get()) {
+ LOG(ERROR) << "Failed to create context for offscreen operations";
+ return NULL;
+ }
+
+ return new IOSurfaceTexture(offscreen_context);
+}
+
+IOSurfaceTexture::IOSurfaceTexture(
+ const scoped_refptr<IOSurfaceContext>& offscreen_context)
+ : offscreen_context_(offscreen_context),
+ texture_(0),
+ gl_error_(GL_NO_ERROR),
+ eviction_queue_iterator_(eviction_queue_.Get().end()),
+ eviction_has_been_drawn_since_updated_(false) {
+ CHECK(offscreen_context_.get());
+}
+
+IOSurfaceTexture::~IOSurfaceTexture() {
+ ReleaseIOSurfaceAndTexture();
+ offscreen_context_ = NULL;
+ DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
+}
+
+bool IOSurfaceTexture::DrawIOSurface() {
+ TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface");
+
+ // If we have release the IOSurface, clear the screen to light grey and
+ // early-out.
+ if (!io_surface_) {
+ glClearColor(0.9, 0.9, 0.9, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ return false;
+ }
+
+ // The viewport is the size of the CALayer, which should always match the
+ // IOSurface pixel size.
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
+ DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString());
+
+ // Set the projection matrix to match 1 unit to 1 pixel.
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, viewport_rect.width(), 0, viewport_rect.height(), -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // Draw a quad the size of the IOSurface. This should cover the full viewport.
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex2f(0, 0);
+ glTexCoord2f(pixel_size_.width(), 0);
+ glVertex2f(pixel_size_.width(), 0);
+ glTexCoord2f(pixel_size_.width(), pixel_size_.height());
+ glVertex2f(pixel_size_.width(), pixel_size_.height());
+ glTexCoord2f(0, pixel_size_.height());
+ glVertex2f(0, pixel_size_.height());
+ glEnd();
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ // Workaround for issue 158469. Issue a dummy draw call with texture_ not
+ // bound to a texture, in order to shake all references to the IOSurface out
+ // of the driver.
+ glBegin(GL_TRIANGLES);
+ glEnd();
+
+ bool workaround_needed =
+ GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
+ gpu::FORCE_GL_FINISH_AFTER_COMPOSITING);
+ if (workaround_needed) {
+ TRACE_EVENT0("gpu", "glFinish");
+ glFinish();
+ }
+
+ // Check if any of the drawing calls result in an error.
+ GetAndSaveGLError();
+ bool result = true;
+ if (gl_error_ != GL_NO_ERROR) {
+ LOG(ERROR) << "GL error in DrawIOSurface: " << gl_error_;
+ result = false;
+ // If there was an error, clear the screen to a light grey to avoid
+ // rendering artifacts.
+ glClearColor(0.8, 0.8, 0.8, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ eviction_has_been_drawn_since_updated_ = true;
+ return result;
+}
+
+bool IOSurfaceTexture::SetIOSurface(
+ IOSurfaceID io_surface_id,
+ const gfx::Size& pixel_size) {
+ TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture");
+
+ // Destroy the old IOSurface and texture if it is no longer needed.
+ bool needs_new_iosurface =
+ !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_);
+ if (needs_new_iosurface)
+ ReleaseIOSurfaceAndTexture();
+
+ // Note that because IOSurface sizes are rounded, the same IOSurface may have
+ // two different sizes associated with it, so update the sizes before the
+ // early-out.
+ pixel_size_ = pixel_size;
+
+ // Early-out if the IOSurface has not changed.
+ if (!needs_new_iosurface)
+ return true;
+
+ // If we early-out at any point from now on, it's because of an error, and we
+ // should destroy the texture and release the IOSurface.
+ base::ScopedClosureRunner error_runner(base::BindBlock(^{
+ ReleaseIOSurfaceAndTexture();
+ }));
+
+ // Open the IOSurface handle.
+ io_surface_.reset(IOSurfaceLookup(io_surface_id));
+ if (!io_surface_)
+ return false;
+
+ // Actual IOSurface size is rounded up to reduce reallocations during window
+ // resize. Get the actual size to properly map the texture.
+ gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_),
+ IOSurfaceGetHeight(io_surface_));
+
+ // Create the GL texture and set it to be backed by the IOSurface.
+ CGLError cgl_error = kCGLNoError;
+ {
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+ offscreen_context_->cgl_context());
+ glGenTextures(1, &texture_);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
+ glTexParameterf(
+ GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(
+ GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ cgl_error = CGLTexImageIOSurface2D(
+ offscreen_context_->cgl_context(),
+ GL_TEXTURE_RECTANGLE_ARB,
+ GL_RGBA,
+ rounded_size.width(),
+ rounded_size.height(),
+ GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8_REV,
+ io_surface_.get(),
+ 0 /* plane */);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ GetAndSaveGLError();
+ }
+
+ // Return failure if an error was encountered by CGL or GL.
+ if (cgl_error != kCGLNoError) {
+ LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error;
+ return false;
+ }
+ if (gl_error_ != GL_NO_ERROR) {
+ LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_;
+ return false;
+ }
+
+ ignore_result(error_runner.Release());
+ return true;
+}
+
+void IOSurfaceTexture::ReleaseIOSurfaceAndTexture() {
+ gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+ offscreen_context_->cgl_context());
+
+ if (texture_) {
+ glDeleteTextures(1, &texture_);
+ texture_ = 0;
+ }
+ pixel_size_ = gfx::Size();
+ io_surface_.reset();
+
+ EvictionMarkEvicted();
+}
+
+bool IOSurfaceTexture::HasBeenPoisoned() const {
+ return offscreen_context_->HasBeenPoisoned();
+}
+
+GLenum IOSurfaceTexture::GetAndSaveGLError() {
+ GLenum gl_error = glGetError();
+ if (gl_error_ == GL_NO_ERROR)
+ gl_error_ = gl_error;
+ return gl_error;
+}
+
+void IOSurfaceTexture::EvictionMarkUpdated() {
+ EvictionMarkEvicted();
+ eviction_queue_.Get().push_back(this);
+ eviction_queue_iterator_ = --eviction_queue_.Get().end();
+ eviction_has_been_drawn_since_updated_ = false;
+ EvictionScheduleDoEvict();
+}
+
+void IOSurfaceTexture::EvictionMarkEvicted() {
+ if (eviction_queue_iterator_ == eviction_queue_.Get().end())
+ return;
+ eviction_queue_.Get().erase(eviction_queue_iterator_);
+ eviction_queue_iterator_ = eviction_queue_.Get().end();
+ eviction_has_been_drawn_since_updated_ = false;
+}
+
+// static
+void IOSurfaceTexture::EvictionScheduleDoEvict() {
+ if (eviction_scheduled_)
+ return;
+ if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
+ return;
+
+ eviction_scheduled_ = true;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&IOSurfaceTexture::EvictionDoEvict));
+}
+
+// static
+void IOSurfaceTexture::EvictionDoEvict() {
+ eviction_scheduled_ = false;
+ // Walk the list of allocated surfaces from least recently used to most
+ // recently used.
+ for (EvictionQueue::iterator it = eviction_queue_.Get().begin();
+ it != eviction_queue_.Get().end();) {
+ IOSurfaceTexture* surface = *it;
+ ++it;
+
+ // If the number of IOSurfaces allocated is less than the threshold,
+ // stop walking the list of surfaces.
+ if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
+ break;
+
+ // Don't evict anything that has not yet been drawn.
+ if (!surface->eviction_has_been_drawn_since_updated_)
+ continue;
+
+ // Evict the surface.
+ surface->ReleaseIOSurfaceAndTexture();
+ }
+}
+
+// static
+base::LazyInstance<IOSurfaceTexture::EvictionQueue>
+ IOSurfaceTexture::eviction_queue_;
+
+// static
+bool IOSurfaceTexture::eviction_scheduled_ = false;
+
+} // namespace content
diff --git a/chromium/content/browser/compositor/no_transport_image_transport_factory.cc b/chromium/content/browser/compositor/no_transport_image_transport_factory.cc
deleted file mode 100644
index 03289c0f685..00000000000
--- a/chromium/content/browser/compositor/no_transport_image_transport_factory.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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 "content/browser/compositor/no_transport_image_transport_factory.h"
-
-#include "cc/output/context_provider.h"
-#include "content/common/gpu/client/gl_helper.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "ui/compositor/compositor.h"
-
-namespace content {
-
-NoTransportImageTransportFactory::NoTransportImageTransportFactory(
- scoped_ptr<ui::ContextFactory> context_factory)
- : context_factory_(context_factory.Pass()) {}
-
-NoTransportImageTransportFactory::~NoTransportImageTransportFactory() {
- scoped_ptr<GLHelper> lost_gl_helper = gl_helper_.Pass();
- FOR_EACH_OBSERVER(ImageTransportFactoryObserver,
- observer_list_,
- OnLostResources());
-}
-
-ui::ContextFactory* NoTransportImageTransportFactory::GetContextFactory() {
- return context_factory_.get();
-}
-
-gfx::GLSurfaceHandle
-NoTransportImageTransportFactory::GetSharedSurfaceHandle() {
- return gfx::GLSurfaceHandle();
-}
-
-GLHelper* NoTransportImageTransportFactory::GetGLHelper() {
- if (!gl_helper_) {
- context_provider_ = context_factory_->SharedMainThreadContextProvider();
- gl_helper_.reset(new GLHelper(context_provider_->ContextGL(),
- context_provider_->ContextSupport()));
- }
- return gl_helper_.get();
-}
-
-void NoTransportImageTransportFactory::AddObserver(
- ImageTransportFactoryObserver* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void NoTransportImageTransportFactory::RemoveObserver(
- ImageTransportFactoryObserver* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/compositor/no_transport_image_transport_factory.h b/chromium/content/browser/compositor/no_transport_image_transport_factory.h
deleted file mode 100644
index fd5f6bf1be5..00000000000
--- a/chromium/content/browser/compositor/no_transport_image_transport_factory.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_COMPOSITOR_NO_TRANSPORT_IMAGE_TRANSPORT_FACTORY_H_
-#define CONTENT_BROWSER_COMPOSITOR_NO_TRANSPORT_IMAGE_TRANSPORT_FACTORY_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "content/browser/compositor/image_transport_factory.h"
-
-namespace cc {
-class ContextProvider;
-}
-
-namespace content {
-
-// An ImageTransportFactory that disables transport.
-class NoTransportImageTransportFactory : public ImageTransportFactory {
- public:
- explicit NoTransportImageTransportFactory(
- scoped_ptr<ui::ContextFactory> context_factory);
- virtual ~NoTransportImageTransportFactory();
-
- // ImageTransportFactory implementation.
- virtual ui::ContextFactory* GetContextFactory() OVERRIDE;
- virtual gfx::GLSurfaceHandle GetSharedSurfaceHandle() OVERRIDE;
- virtual GLHelper* GetGLHelper() OVERRIDE;
- virtual void AddObserver(ImageTransportFactoryObserver* observer) OVERRIDE;
- virtual void RemoveObserver(ImageTransportFactoryObserver* observer) OVERRIDE;
-#if defined(OS_MACOSX)
- virtual void OnSurfaceDisplayed(int surface_id) OVERRIDE {}
-#endif
-
- private:
- scoped_ptr<ui::ContextFactory> context_factory_;
- scoped_refptr<cc::ContextProvider> context_provider_;
- scoped_ptr<GLHelper> gl_helper_;
- ObserverList<ImageTransportFactoryObserver> observer_list_;
-
- DISALLOW_COPY_AND_ASSIGN(NoTransportImageTransportFactory);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_COMPOSITOR_NO_TRANSPORT_IMAGE_TRANSPORT_FACTORY_H_
diff --git a/chromium/content/browser/compositor/onscreen_display_client.cc b/chromium/content/browser/compositor/onscreen_display_client.cc
index 814f0fcc53e..6e2241d6cb1 100644
--- a/chromium/content/browser/compositor/onscreen_display_client.cc
+++ b/chromium/content/browser/compositor/onscreen_display_client.cc
@@ -4,28 +4,93 @@
#include "content/browser/compositor/onscreen_display_client.h"
+#include "base/debug/trace_event.h"
#include "cc/output/output_surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_manager.h"
+#include "content/browser/compositor/surface_display_output_surface.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
namespace content {
OnscreenDisplayClient::OnscreenDisplayClient(
- const scoped_refptr<cc::ContextProvider>& onscreen_context_provider,
- scoped_ptr<cc::OutputSurface> software_surface,
- cc::SurfaceManager* manager)
- : onscreen_context_provider_(onscreen_context_provider),
- software_surface_(software_surface.Pass()),
- display_(this, manager, HostSharedBitmapManager::current()) {
+ scoped_ptr<cc::OutputSurface> output_surface,
+ cc::SurfaceManager* manager,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : output_surface_(output_surface.Pass()),
+ display_(new cc::Display(this,
+ manager,
+ HostSharedBitmapManager::current(),
+ BrowserGpuMemoryBufferManager::current())),
+ task_runner_(task_runner),
+ scheduled_draw_(false),
+ output_surface_lost_(false),
+ deferred_draw_(false),
+ pending_frames_(0),
+ weak_ptr_factory_(this) {
}
OnscreenDisplayClient::~OnscreenDisplayClient() {
}
-scoped_ptr<cc::OutputSurface> OnscreenDisplayClient::CreateOutputSurface() {
- if (!onscreen_context_provider_)
- return software_surface_.Pass();
- return make_scoped_ptr(new cc::OutputSurface(onscreen_context_provider_))
- .Pass();
+bool OnscreenDisplayClient::Initialize() {
+ return display_->Initialize(output_surface_.Pass());
+}
+
+void OnscreenDisplayClient::CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ surface_display_output_surface_->ReceivedVSyncParameters(timebase, interval);
+}
+
+void OnscreenDisplayClient::DisplayDamaged() {
+ if (scheduled_draw_ || deferred_draw_)
+ return;
+ TRACE_EVENT0("content", "OnscreenDisplayClient::DisplayDamaged");
+ if (pending_frames_ >= display_->GetMaxFramesPending()) {
+ deferred_draw_ = true;
+ } else {
+ ScheduleDraw();
+ }
+}
+
+void OnscreenDisplayClient::ScheduleDraw() {
+ DCHECK(!deferred_draw_);
+ DCHECK(!scheduled_draw_);
+ scheduled_draw_ = true;
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&OnscreenDisplayClient::Draw, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void OnscreenDisplayClient::OutputSurfaceLost() {
+ output_surface_lost_ = true;
+ surface_display_output_surface_->DidLoseOutputSurface();
+}
+
+void OnscreenDisplayClient::Draw() {
+ TRACE_EVENT0("content", "OnscreenDisplayClient::Draw");
+ if (output_surface_lost_)
+ return;
+ scheduled_draw_ = false;
+ display_->Draw();
+}
+
+void OnscreenDisplayClient::DidSwapBuffers() {
+ pending_frames_++;
+}
+
+void OnscreenDisplayClient::DidSwapBuffersComplete() {
+ pending_frames_--;
+ if ((pending_frames_ < display_->GetMaxFramesPending()) && deferred_draw_) {
+ deferred_draw_ = false;
+ ScheduleDraw();
+ }
+}
+
+void OnscreenDisplayClient::SetMemoryPolicy(
+ const cc::ManagedMemoryPolicy& policy) {
+ surface_display_output_surface_->SetMemoryPolicy(policy);
}
} // namespace content
diff --git a/chromium/content/browser/compositor/onscreen_display_client.h b/chromium/content/browser/compositor/onscreen_display_client.h
index 7ab6ff7d02b..206f79a322c 100644
--- a/chromium/content/browser/compositor/onscreen_display_client.h
+++ b/chromium/content/browser/compositor/onscreen_display_client.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "cc/surfaces/display.h"
namespace cc {
@@ -17,26 +18,49 @@ class SurfaceManager;
}
namespace content {
+class SurfaceDisplayOutputSurface;
// This class provides a DisplayClient implementation for drawing directly to an
// onscreen context.
class OnscreenDisplayClient : cc::DisplayClient {
public:
OnscreenDisplayClient(
- const scoped_refptr<cc::ContextProvider>& onscreen_context_provider,
- scoped_ptr<cc::OutputSurface> software_surface,
- cc::SurfaceManager* manager);
- virtual ~OnscreenDisplayClient();
+ scoped_ptr<cc::OutputSurface> output_surface,
+ cc::SurfaceManager* manager,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ ~OnscreenDisplayClient() override;
- cc::Display* display() { return &display_; }
+ bool Initialize();
+ cc::Display* display() { return display_.get(); }
+ void set_surface_output_surface(SurfaceDisplayOutputSurface* surface) {
+ surface_display_output_surface_ = surface;
+ }
// cc::DisplayClient implementation.
- virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface() OVERRIDE;
+ void DisplayDamaged() override;
+ void DidSwapBuffers() override;
+ void DidSwapBuffersComplete() override;
+ void CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) override;
+ void OutputSurfaceLost() override;
+ void SetMemoryPolicy(const cc::ManagedMemoryPolicy& policy) override;
private:
- scoped_refptr<cc::ContextProvider> onscreen_context_provider_;
- scoped_ptr<cc::OutputSurface> software_surface_;
- cc::Display display_;
+ void ScheduleDraw();
+ void Draw();
+
+ scoped_ptr<cc::OutputSurface> output_surface_;
+ scoped_ptr<cc::Display> display_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ SurfaceDisplayOutputSurface* surface_display_output_surface_;
+ bool scheduled_draw_;
+ bool output_surface_lost_;
+ // True if a draw should be scheduled, but it's hit the limit on max frames
+ // pending.
+ bool deferred_draw_;
+ int pending_frames_;
+
+ base::WeakPtrFactory<OnscreenDisplayClient> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OnscreenDisplayClient);
};
diff --git a/chromium/content/browser/compositor/overlay_candidate_validator_ozone.cc b/chromium/content/browser/compositor/overlay_candidate_validator_ozone.cc
index b4a3cfeace0..a92dc1011de 100644
--- a/chromium/content/browser/compositor/overlay_candidate_validator_ozone.cc
+++ b/chromium/content/browser/compositor/overlay_candidate_validator_ozone.cc
@@ -15,6 +15,7 @@ static ui::SurfaceFactoryOzone::BufferFormat GetOzoneFormat(
return ui::SurfaceFactoryOzone::RGBA_8888;
case cc::RGBA_4444:
case cc::BGRA_8888:
+ case cc::ALPHA_8:
case cc::LUMINANCE_8:
case cc::RGB_565:
case cc::ETC1:
diff --git a/chromium/content/browser/compositor/overlay_candidate_validator_ozone.h b/chromium/content/browser/compositor/overlay_candidate_validator_ozone.h
index 8fb690b5196..0e81d53e7c0 100644
--- a/chromium/content/browser/compositor/overlay_candidate_validator_ozone.h
+++ b/chromium/content/browser/compositor/overlay_candidate_validator_ozone.h
@@ -25,7 +25,7 @@ class CONTENT_EXPORT OverlayCandidateValidatorOzone
virtual ~OverlayCandidateValidatorOzone();
// cc::OverlayCandidateValidator implementation.
- virtual void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) OVERRIDE;
+ virtual void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override;
private:
gfx::AcceleratedWidget widget_;
diff --git a/chromium/content/browser/compositor/owned_mailbox.h b/chromium/content/browser/compositor/owned_mailbox.h
index 3926c81e0fd..c8868148f4d 100644
--- a/chromium/content/browser/compositor/owned_mailbox.h
+++ b/chromium/content/browser/compositor/owned_mailbox.h
@@ -31,10 +31,10 @@ class CONTENT_EXPORT OwnedMailbox : public base::RefCounted<OwnedMailbox>,
void Destroy();
protected:
- virtual ~OwnedMailbox();
+ ~OwnedMailbox() override;
// ImageTransportFactoryObserver implementation.
- virtual void OnLostResources() OVERRIDE;
+ void OnLostResources() override;
private:
friend class base::RefCounted<OwnedMailbox>;
diff --git a/chromium/content/browser/compositor/reflector_impl.cc b/chromium/content/browser/compositor/reflector_impl.cc
index 2ccded325fe..ac3bdda748e 100644
--- a/chromium/content/browser/compositor/reflector_impl.cc
+++ b/chromium/content/browser/compositor/reflector_impl.cc
@@ -88,7 +88,7 @@ void ReflectorImpl::OnSourceSurfaceReady(
void ReflectorImpl::Shutdown() {
MainThreadData& main = GetMain();
main.mailbox = NULL;
- main.mirroring_layer->SetShowPaintedContent();
+ main.mirroring_layer->SetShowSolidColorContent();
main.mirroring_layer = NULL;
impl_message_loop_->PostTask(
FROM_HERE, base::Bind(&ReflectorImpl::ShutdownOnImplThread, this));
@@ -122,7 +122,7 @@ void ReflectorImpl::ReattachToOutputSurfaceFromMainThread(
GLHelper* helper = ImageTransportFactory::GetInstance()->GetGLHelper();
main.mailbox = new OwnedMailbox(helper);
main.needs_set_mailbox = true;
- main.mirroring_layer->SetShowPaintedContent();
+ main.mirroring_layer->SetShowSolidColorContent();
impl_message_loop_->PostTask(
FROM_HERE,
base::Bind(&ReflectorImpl::AttachToOutputSurfaceOnImplThread,
@@ -201,7 +201,7 @@ void ReflectorImpl::AttachToOutputSurfaceOnImplThread(
void ReflectorImpl::UpdateTextureSizeOnMainThread(gfx::Size size) {
MainThreadData& main = GetMain();
- if (!main.mirroring_layer || !main.mailbox ||
+ if (!main.mirroring_layer || !main.mailbox.get() ||
main.mailbox->mailbox().IsZero())
return;
if (main.needs_set_mailbox) {
diff --git a/chromium/content/browser/compositor/reflector_impl.h b/chromium/content/browser/compositor/reflector_impl.h
index 0a9af98ca61..f771fe46c33 100644
--- a/chromium/content/browser/compositor/reflector_impl.h
+++ b/chromium/content/browser/compositor/reflector_impl.h
@@ -53,7 +53,7 @@ class ReflectorImpl : public base::SupportsWeakPtr<ReflectorImpl>,
BrowserCompositorOutputSurface* surface);
// ui::Reflector implementation.
- virtual void OnMirroringCompositorResized() OVERRIDE;
+ void OnMirroringCompositorResized() override;
// Called in |BrowserCompositorOutputSurface::SwapBuffers| to copy
// the full screen image to the |texture_id_|. This must be called
@@ -99,7 +99,7 @@ class ReflectorImpl : public base::SupportsWeakPtr<ReflectorImpl>,
gpu::MailboxHolder mailbox_holder;
};
- virtual ~ReflectorImpl();
+ ~ReflectorImpl() override;
void AttachToOutputSurfaceOnImplThread(
const gpu::MailboxHolder& mailbox_holder,
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
index 369fe930dbd..98c707f6611 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -8,6 +8,7 @@
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "cc/output/compositor_frame.h"
+#include "cc/output/output_surface_client.h"
#include "cc/output/software_output_device.h"
#include "content/browser/compositor/browser_compositor_output_surface_proxy.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -51,6 +52,15 @@ void SoftwareBrowserCompositorOutputSurface::SwapBuffers(
output_surface_proxy_,
surface_id_));
}
+ PostSwapBuffersComplete();
+ client_->DidSwapBuffers();
}
+#if defined(OS_MACOSX)
+void SoftwareBrowserCompositorOutputSurface::OnSurfaceDisplayed() {
+ // See GpuBrowserCompositorOutputSurface for when and how this is used.
+ NOTREACHED() << "Not expected for software surfaces.";
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
index 788d9daa9e6..1df9b366edd 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -31,10 +31,14 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager);
- virtual ~SoftwareBrowserCompositorOutputSurface();
+ ~SoftwareBrowserCompositorOutputSurface() override;
private:
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ void SwapBuffers(cc::CompositorFrame* frame) override;
+
+#if defined(OS_MACOSX)
+ void OnSurfaceDisplayed() override;
+#endif
// On the software path we need to explicitly call the proxy to update the
// VSync parameters.
diff --git a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
index 79c3364d890..904fca2d2f4 100644
--- a/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
+++ b/chromium/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
@@ -4,6 +4,7 @@
#include "base/message_loop/message_loop.h"
#include "cc/output/compositor_frame.h"
+#include "cc/test/fake_output_surface_client.h"
#include "content/browser/compositor/browser_compositor_output_surface_proxy.h"
#include "content/browser/compositor/software_browser_compositor_output_surface.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,10 +17,9 @@ namespace {
class FakeVSyncProvider : public gfx::VSyncProvider {
public:
FakeVSyncProvider() : call_count_(0) {}
- virtual ~FakeVSyncProvider() {}
+ ~FakeVSyncProvider() override {}
- virtual void GetVSyncParameters(const UpdateVSyncCallback& callback)
- OVERRIDE {
+ void GetVSyncParameters(const UpdateVSyncCallback& callback) override {
callback.Run(timebase_, interval_);
call_count_++;
}
@@ -41,9 +41,9 @@ class FakeVSyncProvider : public gfx::VSyncProvider {
class FakeSoftwareOutputDevice : public cc::SoftwareOutputDevice {
public:
FakeSoftwareOutputDevice() : vsync_provider_(new FakeVSyncProvider()) {}
- virtual ~FakeSoftwareOutputDevice() {}
+ ~FakeSoftwareOutputDevice() override {}
- virtual gfx::VSyncProvider* GetVSyncProvider() OVERRIDE {
+ gfx::VSyncProvider* GetVSyncProvider() override {
return vsync_provider_.get();
}
@@ -58,10 +58,10 @@ class FakeSoftwareOutputDevice : public cc::SoftwareOutputDevice {
class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
public:
SoftwareBrowserCompositorOutputSurfaceTest();
- virtual ~SoftwareBrowserCompositorOutputSurfaceTest();
+ ~SoftwareBrowserCompositorOutputSurfaceTest() override;
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
+ void SetUp() override;
+ void TearDown() override;
scoped_ptr<content::BrowserCompositorOutputSurface> CreateSurface(
scoped_ptr<cc::SoftwareOutputDevice> device);
@@ -94,7 +94,8 @@ void SoftwareBrowserCompositorOutputSurfaceTest::SetUp() {
ui::InitializeContextFactoryForTests(enable_pixel_output);
compositor_.reset(new ui::Compositor(gfx::kNullAcceleratedWidget,
- context_factory));
+ context_factory,
+ base::MessageLoopProxy::current()));
surface_proxy_ =
new content::BrowserCompositorOutputSurfaceProxy(&surface_map_);
}
@@ -122,20 +123,25 @@ SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
+ cc::FakeOutputSurfaceClient output_surface_client;
scoped_ptr<cc::SoftwareOutputDevice> software_device(
new cc::SoftwareOutputDevice());
output_surface_ = CreateSurface(software_device.Pass());
+ CHECK(output_surface_->BindToClient(&output_surface_client));
cc::CompositorFrame frame;
output_surface_->SwapBuffers(&frame);
+ EXPECT_EQ(1, output_surface_client.swap_count());
EXPECT_EQ(NULL, output_surface_->software_device()->GetVSyncProvider());
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
+ cc::FakeOutputSurfaceClient output_surface_client;
scoped_ptr<cc::SoftwareOutputDevice> software_device(
new FakeSoftwareOutputDevice());
output_surface_ = CreateSurface(software_device.Pass());
+ CHECK(output_surface_->BindToClient(&output_surface_client));
FakeVSyncProvider* vsync_provider = static_cast<FakeVSyncProvider*>(
output_surface_->software_device()->GetVSyncProvider());
@@ -144,5 +150,6 @@ TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, VSyncProviderUpdates) {
cc::CompositorFrame frame;
output_surface_->SwapBuffers(&frame);
+ EXPECT_EQ(1, output_surface_client.swap_count());
EXPECT_EQ(1, vsync_provider->call_count());
}
diff --git a/chromium/content/browser/renderer_host/software_layer_mac.h b/chromium/content/browser/compositor/software_layer_mac.h
index 687070e500e..687070e500e 100644
--- a/chromium/content/browser/renderer_host/software_layer_mac.h
+++ b/chromium/content/browser/compositor/software_layer_mac.h
diff --git a/chromium/content/browser/compositor/software_layer_mac.mm b/chromium/content/browser/compositor/software_layer_mac.mm
new file mode 100644
index 00000000000..eb2f03c2547
--- /dev/null
+++ b/chromium/content/browser/compositor/software_layer_mac.mm
@@ -0,0 +1,68 @@
+// Copyright 2014 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 "content/browser/compositor/software_layer_mac.h"
+
+#include "base/debug/trace_event.h"
+#include "base/mac/mac_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/sdk_forward_declarations.h"
+#include "ui/base/cocoa/animation_utils.h"
+
+@implementation SoftwareLayer
+
+- (id)init {
+ if (self = [super init]) {
+ [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
+ [self setAnchorPoint:CGPointMake(0, 0)];
+ // Setting contents gravity is necessary to prevent the layer from being
+ // scaled during dyanmic resizes (especially with devtools open).
+ [self setContentsGravity:kCAGravityTopLeft];
+ }
+ return self;
+}
+
+- (void)setContentsToData:(const void *)data
+ withRowBytes:(size_t)rowBytes
+ withPixelSize:(gfx::Size)pixelSize
+ withScaleFactor:(float)scaleFactor {
+ TRACE_EVENT0("browser", "-[SoftwareLayer setContentsToData]");
+
+ // Disable animating the contents change or the scale factor change.
+ ScopedCAActionDisabler disabler;
+
+ // Set the contents of the software CALayer to be a CGImage with the provided
+ // pixel data. Make a copy of the data before backing the image with them,
+ // because the same buffer will be reused for the next frame.
+ base::ScopedCFTypeRef<CFDataRef> dataCopy(
+ CFDataCreate(NULL,
+ static_cast<const UInt8 *>(data),
+ rowBytes * pixelSize.height()));
+ base::ScopedCFTypeRef<CGDataProviderRef> dataProvider(
+ CGDataProviderCreateWithCFData(dataCopy));
+ base::ScopedCFTypeRef<CGImageRef> image(
+ CGImageCreate(pixelSize.width(),
+ pixelSize.height(),
+ 8,
+ 32,
+ rowBytes,
+ base::mac::GetSystemColorSpace(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ dataProvider,
+ NULL,
+ false,
+ kCGRenderingIntentDefault));
+ [self setContents:(id)image.get()];
+ [self setBounds:CGRectMake(
+ 0, 0, pixelSize.width() / scaleFactor, pixelSize.height() / scaleFactor)];
+
+ // Set the contents scale of the software CALayer.
+ if ([self respondsToSelector:(@selector(contentsScale))] &&
+ [self respondsToSelector:(@selector(setContentsScale:))] &&
+ [self contentsScale] != scaleFactor) {
+ [self setContentsScale:scaleFactor];
+ }
+}
+
+@end
diff --git a/chromium/content/browser/compositor/software_output_device_mac.h b/chromium/content/browser/compositor/software_output_device_mac.h
index 8220a3bd14f..4721c61881e 100644
--- a/chromium/content/browser/compositor/software_output_device_mac.h
+++ b/chromium/content/browser/compositor/software_output_device_mac.h
@@ -20,9 +20,9 @@ namespace content {
class SoftwareOutputDeviceMac : public cc::SoftwareOutputDevice {
public:
explicit SoftwareOutputDeviceMac(ui::Compositor* compositor);
- virtual ~SoftwareOutputDeviceMac();
+ ~SoftwareOutputDeviceMac() override;
- virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+ void EndPaint(cc::SoftwareFrameData* frame_data) override;
private:
ui::Compositor* compositor_;
diff --git a/chromium/content/browser/compositor/software_output_device_mac.mm b/chromium/content/browser/compositor/software_output_device_mac.mm
index ab734078f73..6fc3aefb0ec 100644
--- a/chromium/content/browser/compositor/software_output_device_mac.mm
+++ b/chromium/content/browser/compositor/software_output_device_mac.mm
@@ -6,7 +6,7 @@
#include "content/browser/compositor/software_output_device_mac.h"
-#include "content/browser/compositor/browser_compositor_view_mac.h"
+#include "content/browser/compositor/browser_compositor_ca_layer_tree_mac.h"
#include "ui/compositor/compositor.h"
namespace content {
@@ -20,11 +20,8 @@ SoftwareOutputDeviceMac::~SoftwareOutputDeviceMac() {
void SoftwareOutputDeviceMac::EndPaint(cc::SoftwareFrameData* frame_data) {
SoftwareOutputDevice::EndPaint(frame_data);
-
- NSView* view = compositor_->widget();
- [view gotSoftwareFrame:frame_data
- withScaleFactor:scale_factor_
- withCanvas:canvas_.get()];
+ BrowserCompositorCALayerTreeMacGotSoftwareFrame(
+ compositor_->widget(), frame_data, scale_factor_, canvas_.get());
}
} // namespace content
diff --git a/chromium/content/browser/compositor/software_output_device_ozone.cc b/chromium/content/browser/compositor/software_output_device_ozone.cc
index b97b8b746a2..62d8bce3347 100644
--- a/chromium/content/browser/compositor/software_output_device_ozone.cc
+++ b/chromium/content/browser/compositor/software_output_device_ozone.cc
@@ -16,9 +16,6 @@ SoftwareOutputDeviceOzone::SoftwareOutputDeviceOzone(ui::Compositor* compositor)
: compositor_(compositor) {
ui::SurfaceFactoryOzone* factory = ui::SurfaceFactoryOzone::GetInstance();
- if (factory->InitializeHardware() != ui::SurfaceFactoryOzone::INITIALIZED)
- LOG(FATAL) << "Failed to initialize hardware in OZONE";
-
surface_ozone_ = factory->CreateCanvasForWidget(compositor_->widget());
if (!surface_ozone_)
diff --git a/chromium/content/browser/compositor/software_output_device_ozone.h b/chromium/content/browser/compositor/software_output_device_ozone.h
index 600138ff96e..ef947e16c44 100644
--- a/chromium/content/browser/compositor/software_output_device_ozone.h
+++ b/chromium/content/browser/compositor/software_output_device_ozone.h
@@ -26,9 +26,9 @@ class CONTENT_EXPORT SoftwareOutputDeviceOzone
virtual ~SoftwareOutputDeviceOzone();
virtual void Resize(const gfx::Size& viewport_pixel_size,
- float scale_factor) OVERRIDE;
- virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
- virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+ float scale_factor) override;
+ virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
+ virtual void EndPaint(cc::SoftwareFrameData* frame_data) override;
private:
ui::Compositor* compositor_;
diff --git a/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc b/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc
index a2176a6ffc0..8b720055d8f 100644
--- a/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc
+++ b/chromium/content/browser/compositor/software_output_device_ozone_unittest.cc
@@ -7,6 +7,7 @@
#include "cc/output/software_frame_data.h"
#include "content/browser/compositor/software_output_device_ozone.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/test/context_factories_for_test.h"
@@ -25,15 +26,15 @@ class MockSurfaceOzone : public ui::SurfaceOzoneCanvas {
virtual ~MockSurfaceOzone() {}
// ui::SurfaceOzoneCanvas overrides:
- virtual void ResizeCanvas(const gfx::Size& size) OVERRIDE {
+ virtual void ResizeCanvas(const gfx::Size& size) override {
surface_ = skia::AdoptRef(SkSurface::NewRaster(
SkImageInfo::MakeN32Premul(size.width(), size.height())));
}
- virtual skia::RefPtr<SkCanvas> GetCanvas() OVERRIDE {
+ virtual skia::RefPtr<SkCanvas> GetCanvas() override {
return skia::SharePtr(surface_->getCanvas());
}
- virtual void PresentCanvas(const gfx::Rect& damage) OVERRIDE {}
- virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() OVERRIDE {
+ virtual void PresentCanvas(const gfx::Rect& damage) override {}
+ virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider() override {
return scoped_ptr<gfx::VSyncProvider>();
}
@@ -48,19 +49,13 @@ class MockSurfaceFactoryOzone : public ui::SurfaceFactoryOzone {
MockSurfaceFactoryOzone() {}
virtual ~MockSurfaceFactoryOzone() {}
- virtual HardwareState InitializeHardware() OVERRIDE {
- return SurfaceFactoryOzone::INITIALIZED;
- }
-
- virtual void ShutdownHardware() OVERRIDE {}
- virtual gfx::AcceleratedWidget GetAcceleratedWidget() OVERRIDE { return 1; }
virtual bool LoadEGLGLES2Bindings(
AddGLLibraryCallback add_gl_library,
- SetGLGetProcAddressProcCallback set_gl_get_proc_address) OVERRIDE {
+ SetGLGetProcAddressProcCallback set_gl_get_proc_address) override {
return false;
}
virtual scoped_ptr<ui::SurfaceOzoneCanvas> CreateCanvasForWidget(
- gfx::AcceleratedWidget widget) OVERRIDE {
+ gfx::AcceleratedWidget widget) override {
return make_scoped_ptr<ui::SurfaceOzoneCanvas>(new MockSurfaceOzone());
}
@@ -75,8 +70,8 @@ class SoftwareOutputDeviceOzoneTest : public testing::Test {
SoftwareOutputDeviceOzoneTest();
virtual ~SoftwareOutputDeviceOzoneTest();
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
+ virtual void SetUp() override;
+ virtual void TearDown() override;
protected:
scoped_ptr<content::SoftwareOutputDeviceOzone> output_device_;
@@ -105,9 +100,11 @@ void SoftwareOutputDeviceOzoneTest::SetUp() {
surface_factory_.reset(new MockSurfaceFactoryOzone());
const gfx::Size size(500, 400);
- compositor_.reset(new ui::Compositor(
- ui::SurfaceFactoryOzone::GetInstance()->GetAcceleratedWidget(),
- context_factory));
+ const gfx::AcceleratedWidget kTestAcceleratedWidget = 1;
+ compositor_.reset(
+ new ui::Compositor(kTestAcceleratedWidget,
+ context_factory,
+ base::MessageLoopProxy::current()));
compositor_->SetScaleAndSize(1.0f, size);
output_device_.reset(new content::SoftwareOutputDeviceOzone(
@@ -125,7 +122,7 @@ void SoftwareOutputDeviceOzoneTest::TearDown() {
class SoftwareOutputDeviceOzonePixelTest
: public SoftwareOutputDeviceOzoneTest {
protected:
- virtual void SetUp() OVERRIDE;
+ virtual void SetUp() override;
};
void SoftwareOutputDeviceOzonePixelTest::SetUp() {
diff --git a/chromium/content/browser/compositor/software_output_device_win.h b/chromium/content/browser/compositor/software_output_device_win.h
index 3724f0217f5..85873fb12b6 100644
--- a/chromium/content/browser/compositor/software_output_device_win.h
+++ b/chromium/content/browser/compositor/software_output_device_win.h
@@ -26,10 +26,10 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
virtual ~SoftwareOutputDeviceWin();
virtual void Resize(const gfx::Size& viewport_pixel_size,
- float scale_factor) OVERRIDE;
- virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
- virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
- virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE;
+ float scale_factor) override;
+ virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
+ virtual void EndPaint(cc::SoftwareFrameData* frame_data) override;
+ virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) override;
private:
HWND hwnd_;
diff --git a/chromium/content/browser/compositor/software_output_device_x11.h b/chromium/content/browser/compositor/software_output_device_x11.h
index 20ae6428e63..88c80a32f6c 100644
--- a/chromium/content/browser/compositor/software_output_device_x11.h
+++ b/chromium/content/browser/compositor/software_output_device_x11.h
@@ -20,9 +20,9 @@ class SoftwareOutputDeviceX11 : public cc::SoftwareOutputDevice {
public:
explicit SoftwareOutputDeviceX11(ui::Compositor* compositor);
- virtual ~SoftwareOutputDeviceX11();
+ ~SoftwareOutputDeviceX11() override;
- virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
+ void EndPaint(cc::SoftwareFrameData* frame_data) override;
private:
ui::Compositor* compositor_;
diff --git a/chromium/content/browser/compositor/surface_display_output_surface.cc b/chromium/content/browser/compositor/surface_display_output_surface.cc
index 46c4ad75f95..d3971dadbaa 100644
--- a/chromium/content/browser/compositor/surface_display_output_surface.cc
+++ b/chromium/content/browser/compositor/surface_display_output_surface.cc
@@ -5,44 +5,85 @@
#include "content/browser/compositor/surface_display_output_surface.h"
#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
#include "cc/surfaces/display.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_manager.h"
+#include "content/browser/compositor/onscreen_display_client.h"
namespace content {
SurfaceDisplayOutputSurface::SurfaceDisplayOutputSurface(
- cc::Display* display,
cc::SurfaceManager* surface_manager,
+ cc::SurfaceIdAllocator* allocator,
const scoped_refptr<cc::ContextProvider>& context_provider)
: cc::OutputSurface(context_provider,
scoped_ptr<cc::SoftwareOutputDevice>()),
- display_(display),
- surface_manager_(surface_manager) {
+ display_client_(NULL),
+ surface_manager_(surface_manager),
+ factory_(surface_manager, this),
+ allocator_(allocator) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
}
SurfaceDisplayOutputSurface::~SurfaceDisplayOutputSurface() {
+ client_ = NULL;
+ if (!surface_id_.is_null()) {
+ factory_.Destroy(surface_id_);
+ }
+}
+
+void SurfaceDisplayOutputSurface::ReceivedVSyncParameters(
+ base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ CommitVSyncParameters(timebase, interval);
}
void SurfaceDisplayOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
gfx::Size frame_size =
frame->delegated_frame_data->render_pass_list.back()->output_rect.size();
- display_->Resize(frame_size);
- cc::SurfaceId surface_id = display_->CurrentSurfaceId();
- cc::Surface* surface = surface_manager_->GetSurfaceForId(surface_id);
- if (!surface)
- return;
+ if (frame_size != display_size_) {
+ if (!surface_id_.is_null()) {
+ factory_.Destroy(surface_id_);
+ }
+ surface_id_ = allocator_->GenerateId();
+ factory_.Create(surface_id_, frame_size);
+ display_size_ = frame_size;
+ }
+ display_client_->display()->Resize(
+ surface_id_, frame_size, frame->metadata.device_scale_factor);
scoped_ptr<cc::CompositorFrame> frame_copy(new cc::CompositorFrame());
frame->AssignTo(frame_copy.get());
- surface->QueueFrame(frame_copy.Pass());
-
- if (!display_->Draw())
- return;
+ factory_.SubmitFrame(
+ surface_id_,
+ frame_copy.Pass(),
+ base::Bind(&SurfaceDisplayOutputSurface::SwapBuffersComplete,
+ base::Unretained(this)));
client_->DidSwapBuffers();
+}
+
+bool SurfaceDisplayOutputSurface::BindToClient(
+ cc::OutputSurfaceClient* client) {
+ DCHECK(client);
+ DCHECK(display_client_);
+ client_ = client;
+ // Avoid initializing GL context here, as this should be sharing the
+ // Display's context.
+ return display_client_->Initialize();
+}
+
+void SurfaceDisplayOutputSurface::ReturnResources(
+ const cc::ReturnedResourceArray& resources) {
+ cc::CompositorFrameAck ack;
+ ack.resources = resources;
+ if (client_)
+ client_->ReclaimResources(&ack);
+}
+
+void SurfaceDisplayOutputSurface::SwapBuffersComplete() {
client_->DidSwapBuffersComplete();
}
diff --git a/chromium/content/browser/compositor/surface_display_output_surface.h b/chromium/content/browser/compositor/surface_display_output_surface.h
index 185e0ffc1d2..698b9f5553c 100644
--- a/chromium/content/browser/compositor/surface_display_output_surface.h
+++ b/chromium/content/browser/compositor/surface_display_output_surface.h
@@ -6,6 +6,9 @@
#define CONTENT_BROWSER_COMPOSITOR_SURFACE_DISPLAY_OUTPUT_SURFACE_H_
#include "cc/output/output_surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_id_allocator.h"
namespace cc {
class Display;
@@ -13,25 +16,44 @@ class SurfaceManager;
}
namespace content {
+class OnscreenDisplayClient;
// This class is maps a compositor OutputSurface to the surface system's Display
// concept, allowing a compositor client to submit frames for a native root
// window or physical display.
-class SurfaceDisplayOutputSurface : public cc::OutputSurface {
+class SurfaceDisplayOutputSurface : public cc::OutputSurface,
+ public cc::SurfaceFactoryClient {
public:
// The underlying cc::Display and cc::SurfaceManager must outlive this class.
SurfaceDisplayOutputSurface(
- cc::Display* display,
cc::SurfaceManager* surface_manager,
+ cc::SurfaceIdAllocator* allocator,
const scoped_refptr<cc::ContextProvider>& context_provider);
- virtual ~SurfaceDisplayOutputSurface();
+ ~SurfaceDisplayOutputSurface() override;
+
+ void set_display_client(OnscreenDisplayClient* display_client) {
+ display_client_ = display_client;
+ }
+ cc::SurfaceFactory* factory() { return &factory_; }
+ void ReceivedVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval);
// cc::OutputSurface implementation.
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ void SwapBuffers(cc::CompositorFrame* frame) override;
+ bool BindToClient(cc::OutputSurfaceClient* client) override;
+
+ // cc::SurfaceFactoryClient implementation.
+ void ReturnResources(const cc::ReturnedResourceArray& resources) override;
private:
- cc::Display* display_;
+ void SwapBuffersComplete();
+
+ OnscreenDisplayClient* display_client_;
cc::SurfaceManager* surface_manager_;
+ cc::SurfaceFactory factory_;
+ gfx::Size display_size_;
+ cc::SurfaceId surface_id_;
+ cc::SurfaceIdAllocator* allocator_;
DISALLOW_COPY_AND_ASSIGN(SurfaceDisplayOutputSurface);
};
diff --git a/chromium/content/browser/cross_site_request_manager.cc b/chromium/content/browser/cross_site_request_manager.cc
deleted file mode 100644
index 2fa38b185ab..00000000000
--- a/chromium/content/browser/cross_site_request_manager.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2011 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 "content/browser/cross_site_request_manager.h"
-
-#include "base/memory/singleton.h"
-
-namespace content {
-
-bool CrossSiteRequestManager::HasPendingCrossSiteRequest(int renderer_id,
- int render_view_id) {
- base::AutoLock lock(lock_);
-
- std::pair<int, int> key(renderer_id, render_view_id);
- return pending_cross_site_views_.find(key) !=
- pending_cross_site_views_.end();
-}
-
-void CrossSiteRequestManager::SetHasPendingCrossSiteRequest(int renderer_id,
- int render_view_id,
- bool has_pending) {
- base::AutoLock lock(lock_);
-
- std::pair<int, int> key(renderer_id, render_view_id);
- if (has_pending) {
- pending_cross_site_views_.insert(key);
- } else {
- pending_cross_site_views_.erase(key);
- }
-}
-
-CrossSiteRequestManager::CrossSiteRequestManager() {}
-
-CrossSiteRequestManager::~CrossSiteRequestManager() {}
-
-// static
-CrossSiteRequestManager* CrossSiteRequestManager::GetInstance() {
- return Singleton<CrossSiteRequestManager>::get();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/cross_site_request_manager.h b/chromium/content/browser/cross_site_request_manager.h
deleted file mode 100644
index 29417d7a868..00000000000
--- a/chromium/content/browser/cross_site_request_manager.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_CROSS_SITE_REQUEST_MANAGER_H_
-#define CONTENT_BROWSER_CROSS_SITE_REQUEST_MANAGER_H_
-
-#include <set>
-#include <utility>
-
-#include "base/basictypes.h"
-#include "base/synchronization/lock.h"
-
-template <typename T> struct DefaultSingletonTraits;
-
-namespace content {
-
-// CrossSiteRequestManager is used to handle bookkeeping for cross-site
-// requests and responses between the UI and IO threads. Such requests involve
-// a transition from one RenderViewHost to another within WebContentsImpl, and
-// involve coordination with ResourceDispatcherHost.
-//
-// CrossSiteRequestManager is a singleton that may be used on any thread.
-//
-class CrossSiteRequestManager {
- public:
- // Returns the singleton instance.
- static CrossSiteRequestManager* GetInstance();
-
- // Returns whether the RenderViewHost specified by the given IDs currently
- // has a pending cross-site request. If so, we will have to delay the
- // response until the previous RenderViewHost runs its onunload handler.
- // Called by ResourceDispatcherHost on the IO thread and RenderViewHost on
- // the UI thread.
- bool HasPendingCrossSiteRequest(int renderer_id, int render_view_id);
-
- // Sets whether the RenderViewHost specified by the given IDs currently has a
- // pending cross-site request. Called by RenderViewHost on the UI thread.
- void SetHasPendingCrossSiteRequest(int renderer_id,
- int render_view_id,
- bool has_pending);
-
- private:
- friend struct DefaultSingletonTraits<CrossSiteRequestManager>;
- typedef std::set<std::pair<int, int> > RenderViewSet;
-
- CrossSiteRequestManager();
- ~CrossSiteRequestManager();
-
- // You must acquire this lock before reading or writing any members of this
- // class. You must not block while holding this lock.
- base::Lock lock_;
-
- // Set of (render_process_host_id, render_view_id) pairs of all
- // RenderViewHosts that have pending cross-site requests. Used to pass
- // information about the RenderViewHosts between the UI and IO threads.
- RenderViewSet pending_cross_site_views_;
-
- DISALLOW_COPY_AND_ASSIGN(CrossSiteRequestManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_CROSS_SITE_REQUEST_MANAGER_H_
diff --git a/chromium/content/browser/cross_site_transfer_browsertest.cc b/chromium/content/browser/cross_site_transfer_browsertest.cc
index fff180d72c4..f611030bf9a 100644
--- a/chromium/content/browser/cross_site_transfer_browsertest.cc
+++ b/chromium/content/browser/cross_site_transfer_browsertest.cc
@@ -33,18 +33,14 @@ class TrackingResourceDispatcherHostDelegate
TrackingResourceDispatcherHostDelegate() : throttle_created_(false) {
}
- virtual void RequestBeginning(
- net::URLRequest* request,
- ResourceContext* resource_context,
- appcache::AppCacheService* appcache_service,
- ResourceType::Type resource_type,
- int child_id,
- int route_id,
- ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
+ void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles) override {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ShellResourceDispatcherHostDelegate::RequestBeginning(
- request, resource_context, appcache_service, resource_type, child_id,
- route_id, throttles);
+ request, resource_context, appcache_service, resource_type, throttles);
// Expect only a single request for the tracked url.
ASSERT_FALSE(throttle_created_);
// If this is a request for the tracked URL, add a throttle to track it.
@@ -91,7 +87,7 @@ class TrackingResourceDispatcherHostDelegate
: request_(request), tracker_(tracker) {
}
- virtual ~TrackingThrottle() {
+ ~TrackingThrottle() override {
// If the request is deleted without being cancelled, its status will
// indicate it succeeded, so have to check if the request is still pending
// as well.
@@ -100,7 +96,7 @@ class TrackingResourceDispatcherHostDelegate
}
// ResourceThrottle implementation:
- virtual const char* GetNameForLogging() const OVERRIDE {
+ const char* GetNameForLogging() const override {
return "TrackingThrottle";
}
@@ -147,8 +143,8 @@ class NoTransferRequestDelegate : public WebContentsDelegate {
public:
NoTransferRequestDelegate() {}
- virtual WebContents* OpenURLFromTab(WebContents* source,
- const OpenURLParams& params) OVERRIDE {
+ WebContents* OpenURLFromTab(WebContents* source,
+ const OpenURLParams& params) override {
bool is_transfer =
(params.transferred_global_request_id != GlobalRequestID());
if (is_transfer)
@@ -175,7 +171,7 @@ class CrossSiteTransferTest : public ContentBrowserTest {
}
// ContentBrowserTest implementation:
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(
@@ -183,7 +179,7 @@ class CrossSiteTransferTest : public ContentBrowserTest {
base::Unretained(this)));
}
- virtual void TearDownOnMainThread() OVERRIDE {
+ void TearDownOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(
@@ -208,7 +204,7 @@ class CrossSiteTransferTest : public ContentBrowserTest {
load_observer.Wait();
}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
// Use --site-per-process to force process swaps for cross-site transfers.
command_line->AppendSwitch(switches::kSitePerProcess);
}
diff --git a/chromium/content/browser/database_browsertest.cc b/chromium/content/browser/database_browsertest.cc
index d3cc669d256..e38e4173744 100644
--- a/chromium/content/browser/database_browsertest.cc
+++ b/chromium/content/browser/database_browsertest.cc
@@ -14,7 +14,6 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "content/test/net/url_request_mock_http_job.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
diff --git a/chromium/content/browser/database_quota_client_unittest.cc b/chromium/content/browser/database_quota_client_unittest.cc
index 4ac6cb3cb2d..a439b5176d4 100644
--- a/chromium/content/browser/database_quota_client_unittest.cc
+++ b/chromium/content/browser/database_quota_client_unittest.cc
@@ -11,21 +11,21 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
+#include "storage/browser/database/database_quota_client.h"
+#include "storage/browser/database/database_tracker.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/database/database_quota_client.h"
-#include "webkit/browser/database/database_tracker.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/common/database/database_identifier.h"
-using webkit_database::DatabaseQuotaClient;
-using webkit_database::DatabaseTracker;
-using webkit_database::OriginInfo;
+using storage::DatabaseQuotaClient;
+using storage::DatabaseTracker;
+using storage::OriginInfo;
namespace content {
// Declared to shorten the line lengths.
-static const quota::StorageType kTemp = quota::kStorageTypeTemporary;
-static const quota::StorageType kPerm = quota::kStorageTypePersistent;
+static const storage::StorageType kTemp = storage::kStorageTypeTemporary;
+static const storage::StorageType kPerm = storage::kStorageTypePersistent;
// Mock tracker class the mocks up those methods of the tracker
// that are used by the QuotaClient.
@@ -36,20 +36,19 @@ class MockDatabaseTracker : public DatabaseTracker {
delete_called_count_(0),
async_delete_(false) {}
- virtual bool GetOriginInfo(
- const std::string& origin_identifier,
- OriginInfo* info) OVERRIDE {
+ bool GetOriginInfo(const std::string& origin_identifier,
+ OriginInfo* info) override {
std::map<GURL, MockOriginInfo>::const_iterator found =
mock_origin_infos_.find(
- webkit_database::GetOriginFromIdentifier(origin_identifier));
+ storage::GetOriginFromIdentifier(origin_identifier));
if (found == mock_origin_infos_.end())
return false;
*info = OriginInfo(found->second);
return true;
}
- virtual bool GetAllOriginIdentifiers(
- std::vector<std::string>* origins_identifiers) OVERRIDE {
+ bool GetAllOriginIdentifiers(
+ std::vector<std::string>* origins_identifiers) override {
std::map<GURL, MockOriginInfo>::const_iterator iter;
for (iter = mock_origin_infos_.begin();
iter != mock_origin_infos_.end();
@@ -59,8 +58,7 @@ class MockDatabaseTracker : public DatabaseTracker {
return true;
}
- virtual bool GetAllOriginsInfo(
- std::vector<OriginInfo>* origins_info) OVERRIDE {
+ bool GetAllOriginsInfo(std::vector<OriginInfo>* origins_info) override {
std::map<GURL, MockOriginInfo>::const_iterator iter;
for (iter = mock_origin_infos_.begin();
iter != mock_origin_infos_.end();
@@ -70,9 +68,8 @@ class MockDatabaseTracker : public DatabaseTracker {
return true;
}
- virtual int DeleteDataForOrigin(
- const std::string& origin_identifier,
- const net::CompletionCallback& callback) OVERRIDE {
+ int DeleteDataForOrigin(const std::string& origin_identifier,
+ const net::CompletionCallback& callback) override {
++delete_called_count_;
if (async_delete()) {
base::MessageLoopProxy::current()->PostTask(
@@ -90,7 +87,7 @@ class MockDatabaseTracker : public DatabaseTracker {
void AddMockDatabase(const GURL& origin, const char* name, int size) {
MockOriginInfo& info = mock_origin_infos_[origin];
- info.set_origin(webkit_database::GetIdentifierFromOrigin(origin));
+ info.set_origin(storage::GetIdentifierFromOrigin(origin));
info.AddMockDatabase(base::ASCIIToUTF16(name), size);
}
@@ -99,7 +96,7 @@ class MockDatabaseTracker : public DatabaseTracker {
void set_async_delete(bool async) { async_delete_ = async; }
protected:
- virtual ~MockDatabaseTracker() {}
+ ~MockDatabaseTracker() override {}
private:
class MockOriginInfo : public OriginInfo {
@@ -137,10 +134,9 @@ class DatabaseQuotaClientTest : public testing::Test {
weak_factory_(this) {
}
- int64 GetOriginUsage(
- quota::QuotaClient* client,
- const GURL& origin,
- quota::StorageType type) {
+ int64 GetOriginUsage(storage::QuotaClient* client,
+ const GURL& origin,
+ storage::StorageType type) {
usage_ = 0;
client->GetOriginUsage(
origin, type,
@@ -150,9 +146,8 @@ class DatabaseQuotaClientTest : public testing::Test {
return usage_;
}
- const std::set<GURL>& GetOriginsForType(
- quota::QuotaClient* client,
- quota::StorageType type) {
+ const std::set<GURL>& GetOriginsForType(storage::QuotaClient* client,
+ storage::StorageType type) {
origins_.clear();
client->GetOriginsForType(
type,
@@ -162,10 +157,9 @@ class DatabaseQuotaClientTest : public testing::Test {
return origins_;
}
- const std::set<GURL>& GetOriginsForHost(
- quota::QuotaClient* client,
- quota::StorageType type,
- const std::string& host) {
+ const std::set<GURL>& GetOriginsForHost(storage::QuotaClient* client,
+ storage::StorageType type,
+ const std::string& host) {
origins_.clear();
client->GetOriginsForHost(
type, host,
@@ -175,17 +169,16 @@ class DatabaseQuotaClientTest : public testing::Test {
return origins_;
}
- bool DeleteOriginData(
- quota::QuotaClient* client,
- quota::StorageType type,
- const GURL& origin) {
- delete_status_ = quota::kQuotaStatusUnknown;
+ bool DeleteOriginData(storage::QuotaClient* client,
+ storage::StorageType type,
+ const GURL& origin) {
+ delete_status_ = storage::kQuotaStatusUnknown;
client->DeleteOriginData(
origin, type,
base::Bind(&DatabaseQuotaClientTest::OnDeleteOriginDataComplete,
weak_factory_.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
- return delete_status_ == quota::kQuotaStatusOk;
+ return delete_status_ == storage::kQuotaStatusOk;
}
MockDatabaseTracker* mock_tracker() { return mock_tracker_.get(); }
@@ -200,14 +193,14 @@ class DatabaseQuotaClientTest : public testing::Test {
origins_ = origins;
}
- void OnDeleteOriginDataComplete(quota::QuotaStatusCode status) {
+ void OnDeleteOriginDataComplete(storage::QuotaStatusCode status) {
delete_status_ = status;
}
base::MessageLoop message_loop_;
int64 usage_;
std::set<GURL> origins_;
- quota::QuotaStatusCode delete_status_;
+ storage::QuotaStatusCode delete_status_;
scoped_refptr<MockDatabaseTracker> mock_tracker_;
base::WeakPtrFactory<DatabaseQuotaClientTest> weak_factory_;
};
diff --git a/chromium/content/browser/database_tracker_unittest.cc b/chromium/content/browser/database_tracker_unittest.cc
index baece0a4bfd..14557de29c8 100644
--- a/chromium/content/browser/database_tracker_unittest.cc
+++ b/chromium/content/browser/database_tracker_unittest.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
@@ -14,23 +14,23 @@
#include "content/public/test/mock_special_storage_policy.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
+#include "storage/browser/database/database_tracker.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"
-#include "webkit/browser/database/database_tracker.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/common/database/database_identifier.h"
using base::ASCIIToUTF16;
-using webkit_database::DatabaseConnections;
-using webkit_database::DatabaseTracker;
-using webkit_database::OriginInfo;
+using storage::DatabaseConnections;
+using storage::DatabaseTracker;
+using storage::OriginInfo;
namespace {
const char kOrigin1Url[] = "http://origin1";
const char kOrigin2Url[] = "http://protected_origin2";
-class TestObserver : public webkit_database::DatabaseTracker::Observer {
+class TestObserver : public storage::DatabaseTracker::Observer {
public:
TestObserver()
: new_notification_received_(false),
@@ -43,10 +43,10 @@ class TestObserver : public webkit_database::DatabaseTracker::Observer {
observe_scheduled_deletions_(observe_scheduled_deletions) {
}
- virtual ~TestObserver() {}
- virtual void OnDatabaseSizeChanged(const std::string& origin_identifier,
- const base::string16& database_name,
- int64 database_size) OVERRIDE {
+ ~TestObserver() override {}
+ void OnDatabaseSizeChanged(const std::string& origin_identifier,
+ const base::string16& database_name,
+ int64 database_size) override {
if (!observe_size_changes_)
return;
new_notification_received_ = true;
@@ -54,9 +54,9 @@ class TestObserver : public webkit_database::DatabaseTracker::Observer {
database_name_ = database_name;
database_size_ = database_size;
}
- virtual void OnDatabaseScheduledForDeletion(
+ void OnDatabaseScheduledForDeletion(
const std::string& origin_identifier,
- const base::string16& database_name) OVERRIDE {
+ const base::string16& database_name) override {
if (!observe_scheduled_deletions_)
return;
new_notification_received_ = true;
@@ -96,48 +96,47 @@ void CheckNotificationReceived(TestObserver* observer,
observer->GetNotificationDatabaseSize());
}
-class TestQuotaManagerProxy : public quota::QuotaManagerProxy {
+class TestQuotaManagerProxy : public storage::QuotaManagerProxy {
public:
TestQuotaManagerProxy()
: QuotaManagerProxy(NULL, NULL),
registered_client_(NULL) {
}
- virtual void RegisterClient(quota::QuotaClient* client) OVERRIDE {
+ void RegisterClient(storage::QuotaClient* client) override {
EXPECT_FALSE(registered_client_);
registered_client_ = client;
}
- virtual void NotifyStorageAccessed(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type) OVERRIDE {
- EXPECT_EQ(quota::QuotaClient::kDatabase, client_id);
- EXPECT_EQ(quota::kStorageTypeTemporary, type);
+ void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type) override {
+ EXPECT_EQ(storage::QuotaClient::kDatabase, client_id);
+ EXPECT_EQ(storage::kStorageTypeTemporary, type);
accesses_[origin] += 1;
}
- virtual void NotifyStorageModified(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- int64 delta) OVERRIDE {
- EXPECT_EQ(quota::QuotaClient::kDatabase, client_id);
- EXPECT_EQ(quota::kStorageTypeTemporary, type);
+ void NotifyStorageModified(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ int64 delta) override {
+ EXPECT_EQ(storage::QuotaClient::kDatabase, client_id);
+ EXPECT_EQ(storage::kStorageTypeTemporary, type);
modifications_[origin].first += 1;
modifications_[origin].second += delta;
}
// Not needed for our tests.
- virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
- virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
- virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- bool enabled) OVERRIDE {}
- virtual void GetUsageAndQuota(
- base::SequencedTaskRunner* original_task_runner,
- const GURL& origin,
- quota::StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE {}
+ void NotifyOriginInUse(const GURL& origin) override {}
+ void NotifyOriginNoLongerInUse(const GURL& origin) override {}
+ void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ bool enabled) override {}
+ void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
+ const GURL& origin,
+ storage::StorageType type,
+ const GetUsageAndQuotaCallback& callback) override {}
void SimulateQuotaManagerDestroyed() {
if (registered_client_) {
@@ -160,7 +159,7 @@ class TestQuotaManagerProxy : public quota::QuotaManagerProxy {
modifications_.clear();
}
- quota::QuotaClient* registered_client_;
+ storage::QuotaClient* registered_client_;
// Map from origin to count of access notifications.
std::map<GURL, int> accesses_;
@@ -169,9 +168,7 @@ class TestQuotaManagerProxy : public quota::QuotaManagerProxy {
std::map<GURL, std::pair<int, int64> > modifications_;
protected:
- virtual ~TestQuotaManagerProxy() {
- EXPECT_FALSE(registered_client_);
- }
+ ~TestQuotaManagerProxy() override { EXPECT_FALSE(registered_client_); }
};
@@ -211,9 +208,9 @@ class DatabaseTracker_TestHelper_Test {
// Create and open three databases.
int64 database_size = 0;
const std::string kOrigin1 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
const std::string kOrigin2 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin2Url));
const base::string16 kDB1 = ASCIIToUTF16("db1");
const base::string16 kDB2 = ASCIIToUTF16("db2");
const base::string16 kDB3 = ASCIIToUTF16("db3");
@@ -325,9 +322,9 @@ class DatabaseTracker_TestHelper_Test {
// Open three new databases.
int64 database_size = 0;
const std::string kOrigin1 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
const std::string kOrigin2 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin2Url));
const base::string16 kDB1 = ASCIIToUTF16("db1");
const base::string16 kDB2 = ASCIIToUTF16("db2");
const base::string16 kDB3 = ASCIIToUTF16("db3");
@@ -452,8 +449,7 @@ class DatabaseTracker_TestHelper_Test {
static void DatabaseTrackerQuotaIntegration() {
const GURL kOrigin(kOrigin1Url);
- const std::string kOriginId =
- webkit_database::GetIdentifierFromOrigin(kOrigin);
+ const std::string kOriginId = storage::GetIdentifierFromOrigin(kOrigin);
const base::string16 kName = ASCIIToUTF16("name");
const base::string16 kDescription = ASCIIToUTF16("description");
@@ -551,9 +547,9 @@ class DatabaseTracker_TestHelper_Test {
static void DatabaseTrackerClearSessionOnlyDatabasesOnExit() {
int64 database_size = 0;
const std::string kOrigin1 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
const std::string kOrigin2 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin2Url));
const base::string16 kDB1 = ASCIIToUTF16("db1");
const base::string16 kDB2 = ASCIIToUTF16("db2");
const base::string16 kDescription = ASCIIToUTF16("database_description");
@@ -631,9 +627,9 @@ class DatabaseTracker_TestHelper_Test {
static void DatabaseTrackerSetForceKeepSessionState() {
int64 database_size = 0;
const std::string kOrigin1 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin1Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin1Url));
const std::string kOrigin2 =
- webkit_database::GetIdentifierFromOrigin(GURL(kOrigin2Url));
+ storage::GetIdentifierFromOrigin(GURL(kOrigin2Url));
const base::string16 kDB1 = ASCIIToUTF16("db1");
const base::string16 kDB2 = ASCIIToUTF16("db2");
const base::string16 kDescription = ASCIIToUTF16("database_description");
@@ -708,8 +704,7 @@ class DatabaseTracker_TestHelper_Test {
static void EmptyDatabaseNameIsValid() {
const GURL kOrigin(kOrigin1Url);
- const std::string kOriginId =
- webkit_database::GetIdentifierFromOrigin(kOrigin);
+ const std::string kOriginId = storage::GetIdentifierFromOrigin(kOrigin);
const base::string16 kEmptyName;
const base::string16 kDescription(ASCIIToUTF16("description"));
const base::string16 kChangedDescription(
@@ -757,8 +752,7 @@ class DatabaseTracker_TestHelper_Test {
static void HandleSqliteError() {
const GURL kOrigin(kOrigin1Url);
- const std::string kOriginId =
- webkit_database::GetIdentifierFromOrigin(kOrigin);
+ const std::string kOriginId = storage::GetIdentifierFromOrigin(kOrigin);
const base::string16 kName(ASCIIToUTF16("name"));
const base::string16 kDescription(ASCIIToUTF16("description"));
diff --git a/chromium/content/browser/database_util_unittest.cc b/chromium/content/browser/database_util_unittest.cc
index 23f0a47900d..50d68952b4a 100644
--- a/chromium/content/browser/database_util_unittest.cc
+++ b/chromium/content/browser/database_util_unittest.cc
@@ -4,12 +4,12 @@
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/common/database/database_identifier.h"
using base::ASCIIToUTF16;
-using webkit_database::DatabaseUtil;
+using storage::DatabaseUtil;
static void TestVfsFilePath(bool expected_result,
const char* vfs_file_name,
@@ -30,8 +30,8 @@ static void TestVfsFilePath(bool expected_result,
}
static GURL ToAndFromOriginIdentifier(const GURL origin_url) {
- std::string id = webkit_database::GetIdentifierFromOrigin(origin_url);
- return webkit_database::GetOriginFromIdentifier(id);
+ std::string id = storage::GetIdentifierFromOrigin(origin_url);
+ return storage::GetOriginFromIdentifier(id);
}
static void TestValidOriginIdentifier(bool expected_result,
diff --git a/chromium/content/browser/databases_table_unittest.cc b/chromium/content/browser/databases_table_unittest.cc
index b82176fe247..ee864cd3a8e 100644
--- a/chromium/content/browser/databases_table_unittest.cc
+++ b/chromium/content/browser/databases_table_unittest.cc
@@ -8,13 +8,13 @@
#include "sql/connection.h"
#include "sql/statement.h"
#include "sql/test/scoped_error_ignorer.h"
+#include "storage/browser/database/databases_table.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/sqlite/sqlite3.h"
-#include "webkit/browser/database/databases_table.h"
using base::ASCIIToUTF16;
-using webkit_database::DatabaseDetails;
-using webkit_database::DatabasesTable;
+using storage::DatabaseDetails;
+using storage::DatabasesTable;
namespace content {
diff --git a/chromium/content/browser/device_monitor_mac.mm b/chromium/content/browser/device_monitor_mac.mm
index eb429afe640..f33c09752ea 100644
--- a/chromium/content/browser/device_monitor_mac.mm
+++ b/chromium/content/browser/device_monitor_mac.mm
@@ -10,10 +10,13 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
+#include "base/mac/bind_objc_block.h"
#include "base/mac/scoped_nsobject.h"
#include "base/threading/thread_checker.h"
#include "content/public/browser/browser_thread.h"
-#import "media/video/capture/mac/avfoundation_glue.h"
+#import "media/base/mac/avfoundation_glue.h"
+
+using content::BrowserThread;
namespace {
@@ -133,9 +136,10 @@ void DeviceMonitorMacImpl::ConsolidateDevicesListAndNotify(
class QTKitMonitorImpl : public DeviceMonitorMacImpl {
public:
explicit QTKitMonitorImpl(content::DeviceMonitorMac* monitor);
- virtual ~QTKitMonitorImpl();
+ ~QTKitMonitorImpl() override;
+
+ void OnDeviceChanged() override;
- virtual void OnDeviceChanged() OVERRIDE;
private:
void CountDevices();
void OnAttributeChanged(NSNotification* notification);
@@ -216,57 +220,131 @@ class SuspendObserverDelegate;
// This class is a Key-Value Observer (KVO) shim. It is needed because C++
// classes cannot observe Key-Values directly. Created, manipulated, and
-// destroyed on the Device Thread by SuspendedObserverDelegate.
+// destroyed on the UI Thread by SuspendObserverDelegate.
@interface CrAVFoundationDeviceObserver : NSObject {
@private
- SuspendObserverDelegate* receiver_; // weak
+ // Callback for device changed, has to run on Device Thread.
+ base::Closure onDeviceChangedCallback_;
+
// Member to keep track of the devices we are already monitoring.
- std::set<CrAVCaptureDevice*> monitoredDevices_;
+ std::set<base::scoped_nsobject<CrAVCaptureDevice> > monitoredDevices_;
}
-- (id)initWithChangeReceiver:(SuspendObserverDelegate*)receiver;
-- (void)startObserving:(CrAVCaptureDevice*)device;
+- (id)initWithOnChangedCallback:(const base::Closure&)callback;
+- (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device;
- (void)stopObserving:(CrAVCaptureDevice*)device;
+- (void)clearOnDeviceChangedCallback;
@end
namespace {
// This class owns and manages the lifetime of a CrAVFoundationDeviceObserver.
-// Provides a callback for this device observer to indicate that there has been
-// a device change of some kind. Created by AVFoundationMonitorImpl in UI thread
-// but living in Device Thread.
+// It is created and destroyed in UI thread by AVFoundationMonitorImpl, and it
+// operates on this thread except for the expensive device enumerations which
+// are run on Device Thread.
class SuspendObserverDelegate :
public base::RefCountedThreadSafe<SuspendObserverDelegate> {
public:
- explicit SuspendObserverDelegate(DeviceMonitorMacImpl* monitor)
- : avfoundation_monitor_impl_(monitor) {
- device_thread_checker_.DetachFromThread();
- }
-
- void OnDeviceChanged();
- void StartObserver();
- void ResetDeviceMonitorOnUIThread();
+ explicit SuspendObserverDelegate(DeviceMonitorMacImpl* monitor);
+
+ // Create |suspend_observer_| for all devices and register OnDeviceChanged()
+ // as its change callback. Schedule bottom half in DoStartObserver().
+ void StartObserver(
+ const scoped_refptr<base::SingleThreadTaskRunner>& device_thread);
+ // Enumerate devices in |device_thread| and run the bottom half in
+ // DoOnDeviceChange(). |suspend_observer_| calls back here on suspend event,
+ // and our parent AVFoundationMonitorImpl calls on connect/disconnect device.
+ void OnDeviceChanged(
+ const scoped_refptr<base::SingleThreadTaskRunner>& device_thread);
+ // Remove the device monitor's weak reference. Remove ourselves as suspend
+ // notification observer from |suspend_observer_|.
+ void ResetDeviceMonitor();
private:
friend class base::RefCountedThreadSafe<SuspendObserverDelegate>;
- virtual ~SuspendObserverDelegate() {}
+ virtual ~SuspendObserverDelegate();
- void OnDeviceChangedOnUIThread(
- const std::vector<DeviceInfo>& snapshot_devices);
+ // Bottom half of StartObserver(), starts |suspend_observer_| for all devices.
+ // Assumes that |devices| has been retained prior to being called, and
+ // releases it internally.
+ void DoStartObserver(NSArray* devices);
+ // Bottom half of OnDeviceChanged(), starts |suspend_observer_| for current
+ // devices and composes a snapshot of them to send it to
+ // |avfoundation_monitor_impl_|. Assumes that |devices| has been retained
+ // prior to being called, and releases it internally.
+ void DoOnDeviceChanged(NSArray* devices);
- base::ThreadChecker device_thread_checker_;
base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_;
DeviceMonitorMacImpl* avfoundation_monitor_impl_;
};
-void SuspendObserverDelegate::OnDeviceChanged() {
- DCHECK(device_thread_checker_.CalledOnValidThread());
- NSArray* devices = [AVCaptureDeviceGlue devices];
+SuspendObserverDelegate::SuspendObserverDelegate(DeviceMonitorMacImpl* monitor)
+ : avfoundation_monitor_impl_(monitor) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+void SuspendObserverDelegate::StartObserver(
+ const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ base::Closure on_device_changed_callback =
+ base::Bind(&SuspendObserverDelegate::OnDeviceChanged,
+ this, device_thread);
+ suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc]
+ initWithOnChangedCallback:on_device_changed_callback]);
+
+ // Enumerate the devices in Device thread and post the observers start to be
+ // done on UI thread. The devices array is retained in |device_thread| and
+ // released in DoStartObserver().
+ base::PostTaskAndReplyWithResult(
+ device_thread.get(),
+ FROM_HERE,
+ base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }),
+ base::Bind(&SuspendObserverDelegate::DoStartObserver, this));
+}
+
+void SuspendObserverDelegate::OnDeviceChanged(
+ const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Enumerate the devices in Device thread and post the consolidation of the
+ // new devices and the old ones to be done on UI thread. The devices array
+ // is retained in |device_thread| and released in DoOnDeviceChanged().
+ PostTaskAndReplyWithResult(
+ device_thread.get(),
+ FROM_HERE,
+ base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }),
+ base::Bind(&SuspendObserverDelegate::DoOnDeviceChanged, this));
+}
+
+void SuspendObserverDelegate::ResetDeviceMonitor() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ avfoundation_monitor_impl_ = NULL;
+ [suspend_observer_ clearOnDeviceChangedCallback];
+}
+
+SuspendObserverDelegate::~SuspendObserverDelegate() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
+void SuspendObserverDelegate::DoStartObserver(NSArray* devices) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ base::scoped_nsobject<NSArray> auto_release(devices);
+ for (CrAVCaptureDevice* device in devices) {
+ base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]);
+ [suspend_observer_ startObserving:device_ptr];
+ }
+}
+
+void SuspendObserverDelegate::DoOnDeviceChanged(NSArray* devices) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ base::scoped_nsobject<NSArray> auto_release(devices);
std::vector<DeviceInfo> snapshot_devices;
for (CrAVCaptureDevice* device in devices) {
- [suspend_observer_ startObserving:device];
+ base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]);
+ [suspend_observer_ startObserving:device_ptr];
+
BOOL suspended = [device respondsToSelector:@selector(isSuspended)] &&
[device isSuspended];
DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
@@ -282,28 +360,7 @@ void SuspendObserverDelegate::OnDeviceChanged() {
snapshot_devices.push_back(DeviceInfo([[device uniqueID] UTF8String],
device_type));
}
- // Post the consolidation of enumerated devices to be done on UI thread.
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&SuspendObserverDelegate::OnDeviceChangedOnUIThread,
- this, snapshot_devices));
-}
-void SuspendObserverDelegate::StartObserver() {
- DCHECK(device_thread_checker_.CalledOnValidThread());
- suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc]
- initWithChangeReceiver:this]);
- for (CrAVCaptureDevice* device in [AVCaptureDeviceGlue devices])
- [suspend_observer_ startObserving:device];
-}
-
-void SuspendObserverDelegate::ResetDeviceMonitorOnUIThread() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- avfoundation_monitor_impl_ = NULL;
-}
-
-void SuspendObserverDelegate::OnDeviceChangedOnUIThread(
- const std::vector<DeviceInfo>& snapshot_devices) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
// |avfoundation_monitor_impl_| might have been NULLed asynchronously before
// arriving at this line.
if (avfoundation_monitor_impl_) {
@@ -314,21 +371,18 @@ void SuspendObserverDelegate::OnDeviceChangedOnUIThread(
// AVFoundation implementation of the Mac Device Monitor, registers as a global
// device connect/disconnect observer and plugs suspend/wake up device observers
-// per device. Owns a SuspendObserverDelegate living in |device_task_runner_|
-// and gets notified when a device is suspended/resumed. This class is created
-// and lives in UI thread;
+// per device. This class is created and lives in UI thread. Owns a
+// SuspendObserverDelegate that notifies when a device is suspended/resumed.
class AVFoundationMonitorImpl : public DeviceMonitorMacImpl {
public:
AVFoundationMonitorImpl(
content::DeviceMonitorMac* monitor,
const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
- virtual ~AVFoundationMonitorImpl();
+ ~AVFoundationMonitorImpl() override;
- virtual void OnDeviceChanged() OVERRIDE;
+ void OnDeviceChanged() override;
private:
- base::ThreadChecker thread_checker_;
-
// {Video,AudioInput}DeviceManager's "Device" thread task runner used for
// posting tasks to |suspend_observer_delegate_|; valid after
// MediaStreamManager calls StartMonitoring().
@@ -345,6 +399,7 @@ AVFoundationMonitorImpl::AVFoundationMonitorImpl(
: DeviceMonitorMacImpl(monitor),
device_task_runner_(device_task_runner),
suspend_observer_delegate_(new SuspendObserverDelegate(this)) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
device_arrival_ =
[nc addObserverForName:AVFoundationGlue::
@@ -360,86 +415,97 @@ AVFoundationMonitorImpl::AVFoundationMonitorImpl(
queue:nil
usingBlock:^(NSNotification* notification) {
OnDeviceChanged();}];
- device_task_runner_->PostTask(FROM_HERE,
- base::Bind(&SuspendObserverDelegate::StartObserver,
- suspend_observer_delegate_));
+ suspend_observer_delegate_->StartObserver(device_task_runner_);
}
AVFoundationMonitorImpl::~AVFoundationMonitorImpl() {
- DCHECK(thread_checker_.CalledOnValidThread());
- suspend_observer_delegate_->ResetDeviceMonitorOnUIThread();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ suspend_observer_delegate_->ResetDeviceMonitor();
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:device_arrival_];
[nc removeObserver:device_removal_];
}
void AVFoundationMonitorImpl::OnDeviceChanged() {
- DCHECK(thread_checker_.CalledOnValidThread());
- device_task_runner_->PostTask(FROM_HERE,
- base::Bind(&SuspendObserverDelegate::OnDeviceChanged,
- suspend_observer_delegate_));
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ suspend_observer_delegate_->OnDeviceChanged(device_task_runner_);
}
} // namespace
@implementation CrAVFoundationDeviceObserver
-- (id)initWithChangeReceiver:(SuspendObserverDelegate*)receiver {
+- (id)initWithOnChangedCallback:(const base::Closure&)callback {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if ((self = [super init])) {
- DCHECK(receiver != NULL);
- receiver_ = receiver;
+ DCHECK(!callback.is_null());
+ onDeviceChangedCallback_ = callback;
}
return self;
}
- (void)dealloc {
- std::set<CrAVCaptureDevice*>::iterator it = monitoredDevices_.begin();
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator it =
+ monitoredDevices_.begin();
while (it != monitoredDevices_.end())
- [self stopObserving:*it++];
+ [self removeObservers:*(it++)];
[super dealloc];
}
-- (void)startObserving:(CrAVCaptureDevice*)device {
+- (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(device != nil);
// Skip this device if there are already observers connected to it.
if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) !=
- monitoredDevices_.end()) {
+ monitoredDevices_.end()) {
return;
}
[device addObserver:self
forKeyPath:@"suspended"
options:0
- context:device];
+ context:device.get()];
[device addObserver:self
forKeyPath:@"connected"
options:0
- context:device];
+ context:device.get()];
monitoredDevices_.insert(device);
}
- (void)stopObserving:(CrAVCaptureDevice*)device {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(device != nil);
- std::set<CrAVCaptureDevice*>::iterator found =
+
+ std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator found =
std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device);
DCHECK(found != monitoredDevices_.end());
- // Every so seldom, |device| might be gone when getting here, in that case
- // removing the observer causes a crash. Try to avoid it by checking sanity of
- // the |device| via its -observationInfo. http://crbug.com/371271.
+ [self removeObservers:*found];
+ monitoredDevices_.erase(found);
+}
+
+- (void)clearOnDeviceChangedCallback {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ onDeviceChangedCallback_.Reset();
+}
+
+- (void)removeObservers:(CrAVCaptureDevice*)device {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // Check sanity of |device| via its -observationInfo. http://crbug.com/371271.
if ([device observationInfo]) {
[device removeObserver:self
forKeyPath:@"suspended"];
[device removeObserver:self
forKeyPath:@"connected"];
}
- monitoredDevices_.erase(found);
}
- (void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if ([keyPath isEqual:@"suspended"])
- receiver_->OnDeviceChanged();
+ onDeviceChangedCallback_.Run();
if ([keyPath isEqual:@"connected"])
[self stopObserving:static_cast<CrAVCaptureDevice*>(context)];
}
diff --git a/chromium/content/browser/device_monitor_udev.h b/chromium/content/browser/device_monitor_udev.h
index b65cfc5a29b..4a879ef5d4d 100644
--- a/chromium/content/browser/device_monitor_udev.h
+++ b/chromium/content/browser/device_monitor_udev.h
@@ -23,13 +23,13 @@ class UdevLinux;
class DeviceMonitorLinux : public base::MessageLoop::DestructionObserver {
public:
DeviceMonitorLinux();
- virtual ~DeviceMonitorLinux();
+ ~DeviceMonitorLinux() override;
private:
// This object is deleted on the UI thread after the IO thread has been
// destroyed. Need to know when IO thread is being destroyed so that
// we can delete udev_.
- virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
+ void WillDestroyCurrentMessageLoop() override;
void Initialize();
void OnDevicesChanged(udev_device* device);
diff --git a/chromium/content/browser/device_sensors/OWNERS b/chromium/content/browser/device_sensors/OWNERS
index d523461a382..9bf80a3a416 100644
--- a/chromium/content/browser/device_sensors/OWNERS
+++ b/chromium/content/browser/device_sensors/OWNERS
@@ -1,4 +1,3 @@
hans@chromium.org
-bulach@chromium.org
leandrogracia@chromium.org
timvolodine@chromium.org
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h b/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
index ec6e1a2bfbc..e42f45f9528 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory.h
@@ -8,6 +8,7 @@
#include "content/browser/device_sensors/data_fetcher_shared_memory_base.h"
#if !defined(OS_ANDROID)
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
#endif
@@ -26,19 +27,20 @@ class CONTENT_EXPORT DataFetcherSharedMemory
public:
DataFetcherSharedMemory();
- virtual ~DataFetcherSharedMemory();
+ ~DataFetcherSharedMemory() override;
private:
- virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE;
- virtual bool Stop(ConsumerType consumer_type) OVERRIDE;
+ bool Start(ConsumerType consumer_type, void* buffer) override;
+ bool Stop(ConsumerType consumer_type) override;
#if !defined(OS_ANDROID)
DeviceMotionHardwareBuffer* motion_buffer_;
DeviceOrientationHardwareBuffer* orientation_buffer_;
+ DeviceLightHardwareBuffer* light_buffer_;
#endif
#if defined(OS_MACOSX)
- virtual void Fetch(unsigned consumer_bitmask) OVERRIDE;
- virtual FetcherType GetType() const OVERRIDE;
+ void Fetch(unsigned consumer_bitmask) override;
+ FetcherType GetType() const override;
scoped_ptr<SuddenMotionSensor> sudden_motion_sensor_;
#elif defined(OS_WIN)
@@ -46,7 +48,7 @@ class CONTENT_EXPORT DataFetcherSharedMemory
class SensorEventSinkMotion;
class SensorEventSinkOrientation;
- virtual FetcherType GetType() const OVERRIDE;
+ virtual FetcherType GetType() const override;
bool RegisterForSensor(REFSENSOR_TYPE_ID sensor_type, ISensor** sensor,
scoped_refptr<SensorEventSink> event_sink);
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
index 2ed5f7fc0f9..477be76585a 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_android.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "content/browser/device_sensors/sensor_manager_android.h"
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
@@ -29,6 +30,9 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
return SensorManagerAndroid::GetInstance()->
StartFetchingDeviceOrientationData(
static_cast<DeviceOrientationHardwareBuffer*>(buffer));
+ case CONSUMER_TYPE_LIGHT:
+ return SensorManagerAndroid::GetInstance()->StartFetchingDeviceLightData(
+ static_cast<DeviceLightHardwareBuffer*>(buffer));
default:
NOTREACHED();
}
@@ -43,6 +47,9 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
case CONSUMER_TYPE_ORIENTATION:
SensorManagerAndroid::GetInstance()->StopFetchingDeviceOrientationData();
return true;
+ case CONSUMER_TYPE_LIGHT:
+ SensorManagerAndroid::GetInstance()->StopFetchingDeviceLightData();
+ return true;
default:
NOTREACHED();
}
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc
index 6a9b7d287d3..d997537c059 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.cc
@@ -9,6 +9,7 @@
#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "base/timer/timer.h"
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
@@ -22,6 +23,8 @@ static size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
return sizeof(DeviceMotionHardwareBuffer);
case CONSUMER_TYPE_ORIENTATION:
return sizeof(DeviceOrientationHardwareBuffer);
+ case CONSUMER_TYPE_LIGHT:
+ return sizeof(DeviceLightHardwareBuffer);
default:
NOTREACHED();
}
@@ -33,7 +36,7 @@ static size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
public:
PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher);
- virtual ~PollingThread();
+ ~PollingThread() override;
void AddConsumer(ConsumerType consumer_type, void* buffer);
void RemoveConsumer(ConsumerType consumer_type);
@@ -104,8 +107,7 @@ DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
}
DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
- StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
- StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+ DCHECK_EQ(0u, started_consumers_);
// make sure polling thread stops asap.
if (polling_thread_)
@@ -163,6 +165,12 @@ bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
return true;
}
+void DataFetcherSharedMemoryBase::StopFetchingAllDeviceData() {
+ StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
+ StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
+ StopFetchingDeviceData(CONSUMER_TYPE_LIGHT);
+}
+
base::SharedMemoryHandle
DataFetcherSharedMemoryBase::GetSharedMemoryHandleForProcess(
ConsumerType consumer_type, base::ProcessHandle process) {
@@ -199,7 +207,7 @@ DataFetcherSharedMemoryBase::GetType() const {
}
base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
- return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
+ return base::TimeDelta::FromMicroseconds(kInertialSensorIntervalMicroseconds);
}
base::SharedMemory* DataFetcherSharedMemoryBase::GetSharedMemory(
@@ -240,5 +248,4 @@ bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
}
-
} // namespace content
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.h b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.h
index c959e8254fd..fc1f031d499 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.h
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base.h
@@ -31,6 +31,10 @@ class CONTENT_EXPORT DataFetcherSharedMemoryBase {
// relevant sensors could be successfully deactivated.
bool StopFetchingDeviceData(ConsumerType consumer_type);
+ // Should be called before destruction to make sure all active
+ // sensors are unregistered.
+ void StopFetchingAllDeviceData();
+
// Returns the shared memory handle of the device sensor data
// duplicated into the given process. This method should only be
// called after a call to StartFetchingDeviceData method with
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
index 3a86108b7b5..aa1a9a93153 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_base_unittest.cc
@@ -8,6 +8,7 @@
#include "base/process/process_handle.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,16 +20,19 @@ namespace {
class FakeDataFetcher : public DataFetcherSharedMemoryBase {
public:
FakeDataFetcher()
- : start_motion_(false, false),
+ : start_light_(false, false),
+ start_motion_(false, false),
start_orientation_(false, false),
+ stop_light_(false, false),
stop_motion_(false, false),
stop_orientation_(false, false),
+ updated_light_(false, false),
updated_motion_(false, false),
updated_orientation_(false, false),
+ light_buffer_(NULL),
motion_buffer_(NULL),
- orientation_buffer_(NULL) {
- }
- virtual ~FakeDataFetcher() { }
+ orientation_buffer_(NULL) {}
+ ~FakeDataFetcher() override {}
bool Init(ConsumerType consumer_type, void* buffer) {
EXPECT_TRUE(buffer);
@@ -41,17 +45,29 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
orientation_buffer_ =
static_cast<DeviceOrientationHardwareBuffer*>(buffer);
break;
+ case CONSUMER_TYPE_LIGHT:
+ light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer);
+ break;
default:
return false;
}
return true;
}
+ void UpdateLight() {
+ DeviceLightHardwareBuffer* buffer = GetLightBuffer();
+ ASSERT_TRUE(buffer);
+ buffer->seqlock.WriteBegin();
+ buffer->data.value = 100;
+ buffer->seqlock.WriteEnd();
+ updated_light_.Signal();
+ }
+
void UpdateMotion() {
DeviceMotionHardwareBuffer* buffer = GetMotionBuffer();
ASSERT_TRUE(buffer);
buffer->seqlock.WriteBegin();
- buffer->data.interval = kInertialSensorIntervalMillis;
+ buffer->data.interval = kInertialSensorIntervalMicroseconds / 1000.;
buffer->seqlock.WriteEnd();
updated_motion_.Signal();
}
@@ -65,6 +81,8 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
updated_orientation_.Signal();
}
+ DeviceLightHardwareBuffer* GetLightBuffer() const { return light_buffer_; }
+
DeviceMotionHardwareBuffer* GetMotionBuffer() const {
return motion_buffer_;
}
@@ -81,6 +99,9 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
case CONSUMER_TYPE_ORIENTATION:
start_orientation_.Wait();
break;
+ case CONSUMER_TYPE_LIGHT:
+ start_light_.Wait();
+ break;
}
}
@@ -92,6 +113,9 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
case CONSUMER_TYPE_ORIENTATION:
stop_orientation_.Wait();
break;
+ case CONSUMER_TYPE_LIGHT:
+ stop_light_.Wait();
+ break;
}
}
@@ -103,18 +127,25 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
case CONSUMER_TYPE_ORIENTATION:
updated_orientation_.Wait();
break;
+ case CONSUMER_TYPE_LIGHT:
+ updated_light_.Wait();
+ break;
}
}
protected:
+ base::WaitableEvent start_light_;
base::WaitableEvent start_motion_;
base::WaitableEvent start_orientation_;
+ base::WaitableEvent stop_light_;
base::WaitableEvent stop_motion_;
base::WaitableEvent stop_orientation_;
+ base::WaitableEvent updated_light_;
base::WaitableEvent updated_motion_;
base::WaitableEvent updated_orientation_;
private:
+ DeviceLightHardwareBuffer* light_buffer_;
DeviceMotionHardwareBuffer* motion_buffer_;
DeviceOrientationHardwareBuffer* orientation_buffer_;
@@ -124,9 +155,9 @@ class FakeDataFetcher : public DataFetcherSharedMemoryBase {
class FakeNonPollingDataFetcher : public FakeDataFetcher {
public:
FakeNonPollingDataFetcher() { }
- virtual ~FakeNonPollingDataFetcher() { }
+ ~FakeNonPollingDataFetcher() override {}
- virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ bool Start(ConsumerType consumer_type, void* buffer) override {
Init(consumer_type, buffer);
switch (consumer_type) {
case CONSUMER_TYPE_MOTION:
@@ -137,13 +168,17 @@ class FakeNonPollingDataFetcher : public FakeDataFetcher {
UpdateOrientation();
start_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ UpdateLight();
+ start_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ bool Stop(ConsumerType consumer_type) override {
switch (consumer_type) {
case CONSUMER_TYPE_MOTION:
stop_motion_.Signal();
@@ -151,20 +186,21 @@ class FakeNonPollingDataFetcher : public FakeDataFetcher {
case CONSUMER_TYPE_ORIENTATION:
stop_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ stop_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ void Fetch(unsigned consumer_bitmask) override {
FAIL() << "fetch should not be called, "
<< "because this is a non-polling fetcher";
}
- virtual FetcherType GetType() const OVERRIDE {
- return FakeDataFetcher::GetType();
- }
+ FetcherType GetType() const override { return FakeDataFetcher::GetType(); }
private:
DISALLOW_COPY_AND_ASSIGN(FakeNonPollingDataFetcher);
@@ -173,9 +209,9 @@ class FakeNonPollingDataFetcher : public FakeDataFetcher {
class FakePollingDataFetcher : public FakeDataFetcher {
public:
FakePollingDataFetcher() { }
- virtual ~FakePollingDataFetcher() { }
+ ~FakePollingDataFetcher() override {}
- virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ bool Start(ConsumerType consumer_type, void* buffer) override {
EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
Init(consumer_type, buffer);
@@ -186,13 +222,16 @@ class FakePollingDataFetcher : public FakeDataFetcher {
case CONSUMER_TYPE_ORIENTATION:
start_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ start_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ bool Stop(ConsumerType consumer_type) override {
EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
switch (consumer_type) {
@@ -202,26 +241,30 @@ class FakePollingDataFetcher : public FakeDataFetcher {
case CONSUMER_TYPE_ORIENTATION:
stop_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ stop_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ void Fetch(unsigned consumer_bitmask) override {
EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
EXPECT_TRUE(consumer_bitmask & CONSUMER_TYPE_ORIENTATION ||
- consumer_bitmask & CONSUMER_TYPE_MOTION);
+ consumer_bitmask & CONSUMER_TYPE_MOTION ||
+ consumer_bitmask & CONSUMER_TYPE_LIGHT);
if (consumer_bitmask & CONSUMER_TYPE_ORIENTATION)
UpdateOrientation();
if (consumer_bitmask & CONSUMER_TYPE_MOTION)
UpdateMotion();
+ if (consumer_bitmask & CONSUMER_TYPE_LIGHT)
+ UpdateLight();
}
- virtual FetcherType GetType() const OVERRIDE {
- return FETCHER_TYPE_POLLING_CALLBACK;
- }
+ FetcherType GetType() const override { return FETCHER_TYPE_POLLING_CALLBACK; }
private:
DISALLOW_COPY_AND_ASSIGN(FakePollingDataFetcher);
@@ -230,9 +273,9 @@ class FakePollingDataFetcher : public FakeDataFetcher {
class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
public:
FakeZeroDelayPollingDataFetcher() { }
- virtual ~FakeZeroDelayPollingDataFetcher() { }
+ ~FakeZeroDelayPollingDataFetcher() override {}
- virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ bool Start(ConsumerType consumer_type, void* buffer) override {
EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
Init(consumer_type, buffer);
@@ -243,13 +286,16 @@ class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
case CONSUMER_TYPE_ORIENTATION:
start_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ start_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ bool Stop(ConsumerType consumer_type) override {
EXPECT_TRUE(base::MessageLoop::current() == GetPollingMessageLoop());
switch (consumer_type) {
@@ -259,19 +305,20 @@ class FakeZeroDelayPollingDataFetcher : public FakeDataFetcher {
case CONSUMER_TYPE_ORIENTATION:
stop_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ stop_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ void Fetch(unsigned consumer_bitmask) override {
FAIL() << "fetch should not be called";
}
- virtual FetcherType GetType() const OVERRIDE {
- return FETCHER_TYPE_SEPARATE_THREAD;
- }
+ FetcherType GetType() const override { return FETCHER_TYPE_SEPARATE_THREAD; }
bool IsPollingTimerRunningForTesting() const {
return FakeDataFetcher::IsPollingTimerRunningForTesting();
@@ -290,8 +337,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesStartMotion) {
EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_MOTION));
fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
- EXPECT_EQ(kInertialSensorIntervalMillis,
- fake_data_fetcher.GetMotionBuffer()->data.interval);
+ EXPECT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
+ fake_data_fetcher.GetMotionBuffer()->data.interval);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
fake_data_fetcher.WaitForStop(CONSUMER_TYPE_MOTION);
@@ -312,6 +359,20 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesStartOrientation) {
fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION);
}
+TEST(DataFetcherSharedMemoryBaseTest, DoesStartLight) {
+ FakeNonPollingDataFetcher fake_data_fetcher;
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_DEFAULT,
+ fake_data_fetcher.GetType());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_LIGHT));
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_LIGHT);
+
+ EXPECT_EQ(100, fake_data_fetcher.GetLightBuffer()->data.value);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_LIGHT);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_LIGHT);
+}
+
TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) {
FakePollingDataFetcher fake_data_fetcher;
EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
@@ -321,8 +382,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotion) {
fake_data_fetcher.WaitForStart(CONSUMER_TYPE_MOTION);
fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_MOTION);
- EXPECT_EQ(kInertialSensorIntervalMillis,
- fake_data_fetcher.GetMotionBuffer()->data.interval);
+ EXPECT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
+ fake_data_fetcher.GetMotionBuffer()->data.interval);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
fake_data_fetcher.WaitForStop(CONSUMER_TYPE_MOTION);
@@ -344,6 +405,21 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollOrientation) {
fake_data_fetcher.WaitForStop(CONSUMER_TYPE_ORIENTATION);
}
+TEST(DataFetcherSharedMemoryBaseTest, DoesPollLight) {
+ FakePollingDataFetcher fake_data_fetcher;
+ EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
+ fake_data_fetcher.GetType());
+
+ EXPECT_TRUE(fake_data_fetcher.StartFetchingDeviceData(CONSUMER_TYPE_LIGHT));
+ fake_data_fetcher.WaitForStart(CONSUMER_TYPE_LIGHT);
+ fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_LIGHT);
+
+ EXPECT_EQ(100, fake_data_fetcher.GetLightBuffer()->data.value);
+
+ fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_LIGHT);
+ fake_data_fetcher.WaitForStop(CONSUMER_TYPE_LIGHT);
+}
+
TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
FakePollingDataFetcher fake_data_fetcher;
EXPECT_EQ(DataFetcherSharedMemoryBase::FETCHER_TYPE_POLLING_CALLBACK,
@@ -370,8 +446,8 @@ TEST(DataFetcherSharedMemoryBaseTest, DoesPollMotionAndOrientation) {
fake_data_fetcher.WaitForUpdate(CONSUMER_TYPE_MOTION);
EXPECT_EQ(1, fake_data_fetcher.GetOrientationBuffer()->data.alpha);
- EXPECT_EQ(kInertialSensorIntervalMillis,
- fake_data_fetcher.GetMotionBuffer()->data.interval);
+ EXPECT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
+ fake_data_fetcher.GetMotionBuffer()->data.interval);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
fake_data_fetcher.StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc
index 457fd8d5b47..5294e8ee5db 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_default.cc
@@ -29,12 +29,22 @@ static bool SetOrientationBuffer(
return true;
}
+static bool SetLightBuffer(content::DeviceLightHardwareBuffer* buffer,
+ double lux) {
+ if (!buffer)
+ return false;
+ buffer->seqlock.WriteBegin();
+ buffer->data.value = lux;
+ buffer->seqlock.WriteEnd();
+ return true;
+}
+
} // namespace
namespace content {
DataFetcherSharedMemory::DataFetcherSharedMemory()
- : motion_buffer_(NULL), orientation_buffer_(NULL) {
+ : motion_buffer_(NULL), orientation_buffer_(NULL), light_buffer_(NULL) {
}
DataFetcherSharedMemory::~DataFetcherSharedMemory() {
@@ -54,6 +64,10 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationDefaultAvailable",
false);
return SetOrientationBuffer(orientation_buffer_, true);
+ case CONSUMER_TYPE_LIGHT:
+ light_buffer_ = static_cast<DeviceLightHardwareBuffer*>(buffer);
+ return SetLightBuffer(light_buffer_,
+ std::numeric_limits<double>::infinity());
default:
NOTREACHED();
}
@@ -66,6 +80,8 @@ bool DataFetcherSharedMemory::Stop(ConsumerType consumer_type) {
return SetMotionBuffer(motion_buffer_, false);
case CONSUMER_TYPE_ORIENTATION:
return SetOrientationBuffer(orientation_buffer_, false);
+ case CONSUMER_TYPE_LIGHT:
+ return SetLightBuffer(light_buffer_, -1);
default:
NOTREACHED();
}
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
index 96f4a14215e..c537e032551 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
@@ -30,15 +30,15 @@ class DataFetcherSharedMemory::SensorEventSink
virtual ~SensorEventSink() {}
// IUnknown interface
- virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE {
+ virtual ULONG STDMETHODCALLTYPE AddRef() override {
return IUnknownImpl::AddRef();
}
- virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE {
+ virtual ULONG STDMETHODCALLTYPE Release() override {
return IUnknownImpl::Release();
}
- virtual STDMETHODIMP QueryInterface(REFIID riid, void** ppv) OVERRIDE {
+ virtual STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override {
if (riid == __uuidof(ISensorEvents)) {
*ppv = static_cast<ISensorEvents*>(this);
AddRef();
@@ -50,20 +50,20 @@ class DataFetcherSharedMemory::SensorEventSink
// ISensorEvents interface
STDMETHODIMP OnEvent(ISensor* sensor,
REFGUID event_id,
- IPortableDeviceValues* event_data) OVERRIDE {
+ IPortableDeviceValues* event_data) override {
return S_OK;
}
- STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) OVERRIDE {
+ STDMETHODIMP OnLeave(REFSENSOR_ID sensor_id) override {
return S_OK;
}
- STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) OVERRIDE {
+ STDMETHODIMP OnStateChanged(ISensor* sensor, SensorState state) override {
return S_OK;
}
STDMETHODIMP OnDataUpdated(ISensor* sensor,
- ISensorDataReport* new_data) OVERRIDE {
+ ISensorDataReport* new_data) override {
if (NULL == new_data || NULL == sensor)
return E_INVALIDARG;
return UpdateSharedMemoryBuffer(sensor, new_data) ? S_OK : E_FAIL;
@@ -102,7 +102,7 @@ class DataFetcherSharedMemory::SensorEventSinkOrientation
protected:
virtual bool UpdateSharedMemoryBuffer(
- ISensor* sensor, ISensorDataReport* new_data) OVERRIDE {
+ ISensor* sensor, ISensorDataReport* new_data) override {
double alpha, beta, gamma;
bool has_alpha, has_beta, has_gamma;
@@ -145,7 +145,7 @@ class DataFetcherSharedMemory::SensorEventSinkMotion
protected:
virtual bool UpdateSharedMemoryBuffer(
- ISensor* sensor, ISensorDataReport* new_data) OVERRIDE {
+ ISensor* sensor, ISensorDataReport* new_data) override {
SENSOR_TYPE_ID sensor_type = GUID_NULL;
if (!SUCCEEDED(sensor->GetType(&sensor_type)))
diff --git a/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc b/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc
index ff65895e5ac..3380d8a2e74 100644
--- a/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc
+++ b/chromium/content/browser/device_sensors/device_inertial_sensor_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/threading/platform_thread.h"
#include "content/browser/device_sensors/data_fetcher_shared_memory.h"
#include "content/browser/device_sensors/device_inertial_sensor_service.h"
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
#include "content/public/browser/browser_thread.h"
@@ -30,11 +31,12 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
stopped_orientation_(false, false),
started_motion_(false, false),
stopped_motion_(false, false),
- sensor_data_available_(true) {
- }
- virtual ~FakeDataFetcher() { }
+ started_light_(false, false),
+ stopped_light_(false, false),
+ sensor_data_available_(true) {}
+ ~FakeDataFetcher() override {}
- virtual bool Start(ConsumerType consumer_type, void* buffer) OVERRIDE {
+ bool Start(ConsumerType consumer_type, void* buffer) override {
EXPECT_TRUE(buffer);
switch (consumer_type) {
@@ -58,13 +60,24 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
started_orientation_.Signal();
}
break;
+ case CONSUMER_TYPE_LIGHT:
+ {
+ DeviceLightHardwareBuffer* light_buffer =
+ static_cast<DeviceLightHardwareBuffer*>(buffer);
+ UpdateLight(light_buffer,
+ sensor_data_available_
+ ? 100
+ : std::numeric_limits<double>::infinity());
+ started_light_.Signal();
+ }
+ break;
default:
return false;
}
return true;
}
- virtual bool Stop(ConsumerType consumer_type) OVERRIDE {
+ bool Stop(ConsumerType consumer_type) override {
switch (consumer_type) {
case CONSUMER_TYPE_MOTION:
stopped_motion_.Signal();
@@ -72,19 +85,20 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
case CONSUMER_TYPE_ORIENTATION:
stopped_orientation_.Signal();
break;
+ case CONSUMER_TYPE_LIGHT:
+ stopped_light_.Signal();
+ break;
default:
return false;
}
return true;
}
- virtual void Fetch(unsigned consumer_bitmask) OVERRIDE {
+ void Fetch(unsigned consumer_bitmask) override {
FAIL() << "fetch should not be called";
}
- virtual FetcherType GetType() const OVERRIDE {
- return FETCHER_TYPE_DEFAULT;
- }
+ FetcherType GetType() const override { return FETCHER_TYPE_DEFAULT; }
void SetSensorDataAvailable(bool available) {
sensor_data_available_ = available;
@@ -142,10 +156,18 @@ class FakeDataFetcher : public DataFetcherSharedMemory {
buffer->seqlock.WriteEnd();
}
+ void UpdateLight(DeviceLightHardwareBuffer* buffer, double lux) {
+ buffer->seqlock.WriteBegin();
+ buffer->data.value = lux;
+ buffer->seqlock.WriteEnd();
+ }
+
base::WaitableEvent started_orientation_;
base::WaitableEvent stopped_orientation_;
base::WaitableEvent started_motion_;
base::WaitableEvent stopped_motion_;
+ base::WaitableEvent started_light_;
+ base::WaitableEvent stopped_light_;
bool sensor_data_available_;
private:
@@ -160,7 +182,7 @@ class DeviceInertialSensorBrowserTest : public ContentBrowserTest {
io_loop_finished_event_(false, false) {
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&DeviceInertialSensorBrowserTest::SetUpOnIOThread, this));
@@ -197,13 +219,11 @@ class DeviceInertialSensorBrowserTest : public ContentBrowserTest {
base::WaitableEvent io_loop_finished_event_;
};
-
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) {
// The test page will register an event handler for orientation events,
// expects to get an event with fake values, then removes the event
// handler and navigates to #pass.
- GURL test_url = GetTestUrl(
- "device_orientation", "device_orientation_test.html");
+ GURL test_url = GetTestUrl("device_sensors", "device_orientation_test.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
@@ -211,12 +231,31 @@ IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, OrientationTest) {
fetcher_->stopped_orientation_.Wait();
}
+IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, LightTest) {
+ // The test page will register an event handler for light events,
+ // expects to get an event with fake values, then removes the event
+ // handler and navigates to #pass.
+ GURL test_url = GetTestUrl("device_sensors", "device_light_test.html");
+
+ // TODO(riju): remove command line args when the feature goes stable.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
+
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+ fetcher_->started_light_.Wait();
+ fetcher_->stopped_light_.Wait();
+}
+
IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) {
// The test page will register an event handler for motion events,
// expects to get an event with fake values, then removes the event
// handler and navigates to #pass.
- GURL test_url = GetTestUrl(
- "device_orientation", "device_motion_test.html");
+ GURL test_url = GetTestUrl("device_sensors", "device_motion_test.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
@@ -224,6 +263,36 @@ IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest, MotionTest) {
fetcher_->stopped_motion_.Wait();
}
+// crbug/416406. The test is flaky.
+IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
+ DISABLED_LightOneOffInfintyTest) {
+ // The test page will register an event handler for light events,
+ // expects to get an event with value equal to Infinity. This tests that the
+ // one-off infinity event still propagates to window after the alert is
+ // dismissed and the callback is invoked which navigates to #pass.
+ fetcher_->SetSensorDataAvailable(false);
+
+ // TODO(riju): remove command line args when the feature goes stable.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+
+ TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
+
+ GURL test_url =
+ GetTestUrl("device_sensors", "device_light_infinity_test.html");
+ shell()->LoadURL(test_url);
+
+ WaitForAlertDialogAndQuitAfterDelay(base::TimeDelta::FromMilliseconds(1000));
+
+ fetcher_->started_light_.Wait();
+ fetcher_->stopped_light_.Wait();
+ same_tab_observer.Wait();
+ EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
+}
+
// Flaking in the android try bot. See http://crbug.com/360578.
#if defined(OS_ANDROID)
#define MAYBE_OrientationNullTestWithAlert DISABLED_OrientationNullTestWithAlert
@@ -240,8 +309,8 @@ IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
fetcher_->SetSensorDataAvailable(false);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
- GURL test_url = GetTestUrl(
- "device_orientation", "device_orientation_null_test_with_alert.html");
+ GURL test_url = GetTestUrl("device_sensors",
+ "device_orientation_null_test_with_alert.html");
shell()->LoadURL(test_url);
// TODO(timvolodine): investigate if it is possible to test this without
@@ -255,7 +324,7 @@ IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
}
// Flaking in the android try bot. See http://crbug.com/360578.
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_WIN)
#define MAYBE_MotionNullTestWithAlert DISABLED_MotionNullTestWithAlert
#else
#define MAYBE_MotionNullTestWithAlert MotionNullTestWithAlert
@@ -270,8 +339,8 @@ IN_PROC_BROWSER_TEST_F(DeviceInertialSensorBrowserTest,
fetcher_->SetSensorDataAvailable(false);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
- GURL test_url = GetTestUrl(
- "device_orientation", "device_motion_null_test_with_alert.html");
+ GURL test_url =
+ GetTestUrl("device_sensors", "device_motion_null_test_with_alert.html");
shell()->LoadURL(test_url);
// TODO(timvolodine): investigate if it is possible to test this without
diff --git a/chromium/content/browser/device_sensors/device_inertial_sensor_service.cc b/chromium/content/browser/device_sensors/device_inertial_sensor_service.cc
index cf96820649e..840ce254bc1 100644
--- a/chromium/content/browser/device_sensors/device_inertial_sensor_service.cc
+++ b/chromium/content/browser/device_sensors/device_inertial_sensor_service.cc
@@ -12,7 +12,8 @@
namespace content {
DeviceInertialSensorService::DeviceInertialSensorService()
- : num_motion_readers_(0),
+ : num_light_readers_(0),
+ num_motion_readers_(0),
num_orientation_readers_(0),
is_shutdown_(false) {
}
@@ -59,6 +60,10 @@ bool DeviceInertialSensorService::ChangeNumberConsumers(
num_orientation_readers_ += delta;
DCHECK_GE(num_orientation_readers_ , 0);
return true;
+ case CONSUMER_TYPE_LIGHT:
+ num_light_readers_ += delta;
+ DCHECK_GE(num_light_readers_, 0);
+ return true;
default:
NOTREACHED();
}
@@ -72,6 +77,8 @@ int DeviceInertialSensorService::GetNumberConsumers(
return num_motion_readers_;
case CONSUMER_TYPE_ORIENTATION:
return num_orientation_readers_;
+ case CONSUMER_TYPE_LIGHT:
+ return num_light_readers_;
default:
NOTREACHED();
}
@@ -86,12 +93,17 @@ DeviceInertialSensorService::GetSharedMemoryHandleForProcess(
}
void DeviceInertialSensorService::Shutdown() {
- data_fetcher_.reset();
+ if (data_fetcher_) {
+ data_fetcher_->StopFetchingAllDeviceData();
+ data_fetcher_.reset();
+ }
is_shutdown_ = true;
}
void DeviceInertialSensorService::SetDataFetcherForTesting(
DataFetcherSharedMemory* test_data_fetcher) {
+ if (data_fetcher_)
+ data_fetcher_->StopFetchingAllDeviceData();
data_fetcher_.reset(test_data_fetcher);
}
diff --git a/chromium/content/browser/device_sensors/device_inertial_sensor_service.h b/chromium/content/browser/device_sensors/device_inertial_sensor_service.h
index 1d8cfd14497..c372903ad30 100644
--- a/chromium/content/browser/device_sensors/device_inertial_sensor_service.h
+++ b/chromium/content/browser/device_sensors/device_inertial_sensor_service.h
@@ -57,6 +57,7 @@ class CONTENT_EXPORT DeviceInertialSensorService {
int delta);
int GetNumberConsumers(ConsumerType consumer_type) const;
+ int num_light_readers_;
int num_motion_readers_;
int num_orientation_readers_;
bool is_shutdown_;
diff --git a/chromium/content/browser/device_sensors/device_light_message_filter.cc b/chromium/content/browser/device_sensors/device_light_message_filter.cc
new file mode 100644
index 00000000000..751b6f11ce3
--- /dev/null
+++ b/chromium/content/browser/device_sensors/device_light_message_filter.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 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 "content/browser/device_sensors/device_light_message_filter.h"
+
+#include "content/browser/device_sensors/device_inertial_sensor_service.h"
+#include "content/common/device_sensors/device_light_messages.h"
+
+namespace content {
+
+DeviceLightMessageFilter::DeviceLightMessageFilter()
+ : BrowserMessageFilter(DeviceLightMsgStart), is_started_(false) {
+}
+
+DeviceLightMessageFilter::~DeviceLightMessageFilter() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (is_started_) {
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(
+ CONSUMER_TYPE_LIGHT);
+ }
+}
+
+bool DeviceLightMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DeviceLightMessageFilter, message)
+ IPC_MESSAGE_HANDLER(DeviceLightHostMsg_StartPolling,
+ OnDeviceLightStartPolling)
+ IPC_MESSAGE_HANDLER(DeviceLightHostMsg_StopPolling, OnDeviceLightStopPolling)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void DeviceLightMessageFilter::OnDeviceLightStartPolling() {
+ DCHECK(!is_started_);
+ if (is_started_)
+ return;
+ is_started_ = true;
+ DeviceInertialSensorService::GetInstance()->AddConsumer(CONSUMER_TYPE_LIGHT);
+ DidStartDeviceLightPolling();
+}
+
+void DeviceLightMessageFilter::OnDeviceLightStopPolling() {
+ DCHECK(is_started_);
+ if (!is_started_)
+ return;
+ is_started_ = false;
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(
+ CONSUMER_TYPE_LIGHT);
+}
+
+void DeviceLightMessageFilter::DidStartDeviceLightPolling() {
+ Send(new DeviceLightMsg_DidStartPolling(
+ DeviceInertialSensorService::GetInstance()
+ ->GetSharedMemoryHandleForProcess(CONSUMER_TYPE_LIGHT,
+ PeerHandle())));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_light_message_filter.h b/chromium/content/browser/device_sensors/device_light_message_filter.h
new file mode 100644
index 00000000000..eb10bbfab24
--- /dev/null
+++ b/chromium/content/browser/device_sensors/device_light_message_filter.h
@@ -0,0 +1,33 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_LIGHT_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_LIGHT_MESSAGE_FILTER_H_
+
+#include "content/public/browser/browser_message_filter.h"
+
+namespace content {
+
+class DeviceLightMessageFilter : public BrowserMessageFilter {
+ public:
+ DeviceLightMessageFilter();
+
+ // BrowserMessageFilter implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ private:
+ ~DeviceLightMessageFilter() override;
+
+ void OnDeviceLightStartPolling();
+ void OnDeviceLightStopPolling();
+ void DidStartDeviceLightPolling();
+
+ bool is_started_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceLightMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_LIGHT_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/device_sensors/device_motion_message_filter.h b/chromium/content/browser/device_sensors/device_motion_message_filter.h
index cd4859472d5..ffe9ff76c9b 100644
--- a/chromium/content/browser/device_sensors/device_motion_message_filter.h
+++ b/chromium/content/browser/device_sensors/device_motion_message_filter.h
@@ -14,10 +14,10 @@ class DeviceMotionMessageFilter : public BrowserMessageFilter {
DeviceMotionMessageFilter();
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~DeviceMotionMessageFilter();
+ ~DeviceMotionMessageFilter() override;
void OnDeviceMotionStartPolling();
void OnDeviceMotionStopPolling();
diff --git a/chromium/content/browser/device_sensors/device_orientation_message_filter.h b/chromium/content/browser/device_sensors/device_orientation_message_filter.h
index 56893c83a16..acc772d48e5 100644
--- a/chromium/content/browser/device_sensors/device_orientation_message_filter.h
+++ b/chromium/content/browser/device_sensors/device_orientation_message_filter.h
@@ -14,10 +14,10 @@ class DeviceOrientationMessageFilter : public BrowserMessageFilter {
DeviceOrientationMessageFilter();
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~DeviceOrientationMessageFilter();
+ ~DeviceOrientationMessageFilter() override;
void OnDeviceOrientationStartPolling();
void OnDeviceOrientationStopPolling();
diff --git a/chromium/content/browser/device_sensors/inertial_sensor_consts.h b/chromium/content/browser/device_sensors/inertial_sensor_consts.h
index 6ca6a98e96a..1f665bdbb5d 100644
--- a/chromium/content/browser/device_sensors/inertial_sensor_consts.h
+++ b/chromium/content/browser/device_sensors/inertial_sensor_consts.h
@@ -5,20 +5,31 @@
#ifndef CONTENT_BROWSER_DEVICE_SENSORS_INERTIAL_SENSOR_CONSTS_H_
#define CONTENT_BROWSER_DEVICE_SENSORS_INERTIAL_SENSOR_CONSTS_H_
+#include "base/time/time.h"
+
namespace content {
-// Constants related to the Device Motion/Device Orientation APIs.
+// Constants related to the Device {Motion|Orientation|Light} APIs.
enum ConsumerType {
CONSUMER_TYPE_MOTION = 1 << 0,
CONSUMER_TYPE_ORIENTATION = 1 << 1,
+ CONSUMER_TYPE_LIGHT = 1 << 2,
};
-// Specifies the minimal interval between subsequent sensor data updates.
+// Specifies the sampling rate for sensor data updates.
// Note that when changing this value it is desirable to have an adequate
-// matching value |DeviceSensorEventPump::kDefaultPumpDelayMillis| in
+// matching value |DeviceSensorEventPump::kDefaultPumpFrequencyHz| in
// content/renderer/device_orientation/device_sensor_event_pump.cc.
-const int kInertialSensorIntervalMillis = 50;
+const int kInertialSensorSamplingRateHz = 60;
+const int kInertialSensorIntervalMicroseconds =
+ base::Time::kMicrosecondsPerSecond / kInertialSensorSamplingRateHz;
+
+// Corresponding |kDefaultLightPumpFrequencyHz| is in
+// content/renderer/device_sensors/device_light_event_pump.cc.
+const int kLightSensorSamplingRateHz = 5;
+const int kLightSensorIntervalMicroseconds =
+ base::Time::kMicrosecondsPerSecond / kLightSensorSamplingRateHz;
} // namespace content
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android.cc b/chromium/content/browser/device_sensors/sensor_manager_android.cc
index 400adfa355b..11de85ae68c 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_android.cc
@@ -26,15 +26,16 @@ namespace content {
SensorManagerAndroid::SensorManagerAndroid()
: number_active_device_motion_sensors_(0),
+ device_light_buffer_(NULL),
device_motion_buffer_(NULL),
device_orientation_buffer_(NULL),
+ is_light_buffer_ready_(false),
is_motion_buffer_ready_(false),
- is_orientation_buffer_ready_(false) {
+ is_orientation_buffer_ready_(false),
+ is_using_backup_sensors_for_orientation_(false) {
memset(received_motion_data_, 0, sizeof(received_motion_data_));
- device_orientation_.Reset(
- Java_DeviceSensors_getInstance(
- AttachCurrentThread(),
- base::android::GetApplicationContext()));
+ device_sensors_.Reset(Java_DeviceSensors_getInstance(
+ AttachCurrentThread(), base::android::GetApplicationContext()));
}
SensorManagerAndroid::~SensorManagerAndroid() {
@@ -67,7 +68,7 @@ void SensorManagerAndroid::GotOrientation(
if (!is_orientation_buffer_ready_) {
SetOrientationBufferReadyStatus(true);
- updateRotationVectorHistogram(true);
+ updateRotationVectorHistogram(!is_using_backup_sensors_for_orientation_);
}
}
@@ -137,30 +138,84 @@ void SensorManagerAndroid::GotRotationRate(
}
}
+void SensorManagerAndroid::GotLight(JNIEnv*, jobject, double value) {
+ base::AutoLock autolock(light_buffer_lock_);
+
+ if (!device_light_buffer_)
+ return;
+
+ device_light_buffer_->seqlock.WriteBegin();
+ device_light_buffer_->data.value = value;
+ device_light_buffer_->seqlock.WriteEnd();
+}
+
bool SensorManagerAndroid::Start(EventType event_type) {
- DCHECK(!device_orientation_.is_null());
- return Java_DeviceSensors_start(
- AttachCurrentThread(), device_orientation_.obj(),
- reinterpret_cast<intptr_t>(this), static_cast<jint>(event_type),
- kInertialSensorIntervalMillis);
+ DCHECK(!device_sensors_.is_null());
+ int rate_in_microseconds = (event_type == kTypeLight)
+ ? kLightSensorIntervalMicroseconds
+ : kInertialSensorIntervalMicroseconds;
+ return Java_DeviceSensors_start(AttachCurrentThread(),
+ device_sensors_.obj(),
+ reinterpret_cast<intptr_t>(this),
+ static_cast<jint>(event_type),
+ rate_in_microseconds);
}
void SensorManagerAndroid::Stop(EventType event_type) {
- DCHECK(!device_orientation_.is_null());
- Java_DeviceSensors_stop(
- AttachCurrentThread(), device_orientation_.obj(),
- static_cast<jint>(event_type));
+ DCHECK(!device_sensors_.is_null());
+ Java_DeviceSensors_stop(AttachCurrentThread(),
+ device_sensors_.obj(),
+ static_cast<jint>(event_type));
}
int SensorManagerAndroid::GetNumberActiveDeviceMotionSensors() {
- DCHECK(!device_orientation_.is_null());
+ DCHECK(!device_sensors_.is_null());
return Java_DeviceSensors_getNumberActiveDeviceMotionSensors(
- AttachCurrentThread(), device_orientation_.obj());
+ AttachCurrentThread(), device_sensors_.obj());
}
+bool SensorManagerAndroid::isUsingBackupSensorsForOrientation() {
+ DCHECK(!device_sensors_.is_null());
+ return Java_DeviceSensors_isUsingBackupSensorsForOrientation(
+ AttachCurrentThread(), device_sensors_.obj());
+}
// ----- Shared memory API methods
+// --- Device Light
+
+bool SensorManagerAndroid::StartFetchingDeviceLightData(
+ DeviceLightHardwareBuffer* buffer) {
+ DCHECK(buffer);
+ {
+ base::AutoLock autolock(light_buffer_lock_);
+ device_light_buffer_ = buffer;
+ SetLightBufferValue(-1);
+ }
+ bool success = Start(kTypeLight);
+ if (!success) {
+ base::AutoLock autolock(light_buffer_lock_);
+ SetLightBufferValue(std::numeric_limits<double>::infinity());
+ }
+ return success;
+}
+
+void SensorManagerAndroid::StopFetchingDeviceLightData() {
+ Stop(kTypeLight);
+ {
+ base::AutoLock autolock(light_buffer_lock_);
+ if (device_light_buffer_) {
+ SetLightBufferValue(-1);
+ device_light_buffer_ = NULL;
+ }
+ }
+}
+
+void SensorManagerAndroid::SetLightBufferValue(double lux) {
+ device_light_buffer_->seqlock.WriteBegin();
+ device_light_buffer_->data.value = lux;
+ device_light_buffer_->seqlock.WriteEnd();
+}
// --- Device Motion
bool SensorManagerAndroid::StartFetchingDeviceMotionData(
@@ -201,7 +256,8 @@ void SensorManagerAndroid::CheckMotionBufferReadyToRead() {
received_motion_data_[RECEIVED_MOTION_DATA_ROTATION_RATE] ==
number_active_device_motion_sensors_) {
device_motion_buffer_->seqlock.WriteBegin();
- device_motion_buffer_->data.interval = kInertialSensorIntervalMillis;
+ device_motion_buffer_->data.interval =
+ kInertialSensorIntervalMicroseconds / 1000.;
device_motion_buffer_->seqlock.WriteEnd();
SetMotionBufferReadyStatus(true);
@@ -258,6 +314,9 @@ bool SensorManagerAndroid::StartFetchingDeviceOrientationData(
if (!success)
updateRotationVectorHistogram(false);
+ else
+ is_using_backup_sensors_for_orientation_ =
+ isUsingBackupSensorsForOrientation();
return success;
}
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android.h b/chromium/content/browser/device_sensors/sensor_manager_android.h
index f2a552ecf5c..714b8ec0416 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android.h
+++ b/chromium/content/browser/device_sensors/sensor_manager_android.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
#include "content/common/device_sensors/device_motion_hardware_buffer.h"
#include "content/common/device_sensors/device_orientation_hardware_buffer.h"
@@ -16,7 +17,7 @@ template<typename T> struct DefaultSingletonTraits;
namespace content {
-// Android implementation of Device Orientation API.
+// Android implementation of Device {Motion|Orientation|Light} API.
//
// Android's SensorManager has a push API, so when Got*() methods are called
// by the system the browser process puts the received data into a shared
@@ -30,6 +31,7 @@ class CONTENT_EXPORT SensorManagerAndroid {
static SensorManagerAndroid* GetInstance();
// Called from Java via JNI.
+ void GotLight(JNIEnv*, jobject, double value);
void GotOrientation(JNIEnv*, jobject,
double alpha, double beta, double gamma);
void GotAcceleration(JNIEnv*, jobject,
@@ -40,6 +42,9 @@ class CONTENT_EXPORT SensorManagerAndroid {
double alpha, double beta, double gamma);
// Shared memory related methods.
+ bool StartFetchingDeviceLightData(DeviceLightHardwareBuffer* buffer);
+ void StopFetchingDeviceLightData();
+
bool StartFetchingDeviceMotionData(DeviceMotionHardwareBuffer* buffer);
void StopFetchingDeviceMotionData();
@@ -49,11 +54,12 @@ class CONTENT_EXPORT SensorManagerAndroid {
protected:
enum EventType {
- // These constants should match DEVICE_ORIENTATION and DEVICE_MOTION
- // constants in content/public/android/java/src/org/chromium/content/
- // browser/DeviceMotionAndOrientation.java
+ // These constants should match DEVICE_ORIENTATION, DEVICE_MOTION and
+ // DEVICE_LIGHT constants in content/public/android/java/src/org/
+ // chromium/content/browser/DeviceSensors.java
kTypeOrientation = 0,
- kTypeMotion = 1
+ kTypeMotion = 1,
+ kTypeLight = 2
};
SensorManagerAndroid();
@@ -73,24 +79,32 @@ class CONTENT_EXPORT SensorManagerAndroid {
RECEIVED_MOTION_DATA_MAX = 3,
};
+ void SetLightBufferValue(double lux);
+
void CheckMotionBufferReadyToRead();
void SetMotionBufferReadyStatus(bool ready);
void ClearInternalMotionBuffers();
void SetOrientationBufferReadyStatus(bool ready);
+ bool isUsingBackupSensorsForOrientation();
- // The Java provider of orientation info.
- base::android::ScopedJavaGlobalRef<jobject> device_orientation_;
+ // The Java provider of sensors info.
+ base::android::ScopedJavaGlobalRef<jobject> device_sensors_;
int number_active_device_motion_sensors_;
int received_motion_data_[RECEIVED_MOTION_DATA_MAX];
+ DeviceLightHardwareBuffer* device_light_buffer_;
DeviceMotionHardwareBuffer* device_motion_buffer_;
DeviceOrientationHardwareBuffer* device_orientation_buffer_;
+ bool is_light_buffer_ready_;
bool is_motion_buffer_ready_;
bool is_orientation_buffer_ready_;
+ base::Lock light_buffer_lock_;
base::Lock motion_buffer_lock_;
base::Lock orientation_buffer_lock_;
+ bool is_using_backup_sensors_for_orientation_;
+
DISALLOW_COPY_AND_ASSIGN(SensorManagerAndroid);
};
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc b/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc
index 8299164c910..b5f0c5fb933 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_android_unittest.cc
@@ -19,7 +19,7 @@ class FakeSensorManagerAndroid : public SensorManagerAndroid {
FakeSensorManagerAndroid() { }
virtual ~FakeSensorManagerAndroid() { }
- virtual int GetNumberActiveDeviceMotionSensors() OVERRIDE {
+ virtual int GetNumberActiveDeviceMotionSensors() override {
return number_active_sensors_;
}
@@ -28,11 +28,11 @@ class FakeSensorManagerAndroid : public SensorManagerAndroid {
}
protected:
- virtual bool Start(EventType event_type) OVERRIDE {
+ virtual bool Start(EventType event_type) override {
return true;
}
- virtual void Stop(EventType event_type) OVERRIDE {
+ virtual void Stop(EventType event_type) override {
}
private:
@@ -42,10 +42,12 @@ class FakeSensorManagerAndroid : public SensorManagerAndroid {
class AndroidSensorManagerTest : public testing::Test {
protected:
AndroidSensorManagerTest() {
+ light_buffer_.reset(new DeviceLightHardwareBuffer);
motion_buffer_.reset(new DeviceMotionHardwareBuffer);
orientation_buffer_.reset(new DeviceOrientationHardwareBuffer);
}
+ scoped_ptr<DeviceLightHardwareBuffer> light_buffer_;
scoped_ptr<DeviceMotionHardwareBuffer> motion_buffer_;
scoped_ptr<DeviceOrientationHardwareBuffer> orientation_buffer_;
};
@@ -84,7 +86,8 @@ TEST_F(AndroidSensorManagerTest, ThreeDeviceMotionSensorsActive) {
ASSERT_TRUE(motion_buffer_->data.hasRotationRateBeta);
ASSERT_EQ(9, motion_buffer_->data.rotationRateGamma);
ASSERT_TRUE(motion_buffer_->data.hasRotationRateGamma);
- ASSERT_EQ(kInertialSensorIntervalMillis, motion_buffer_->data.interval);
+ ASSERT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
+ motion_buffer_->data.interval);
sensorManager.StopFetchingDeviceMotionData();
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
@@ -103,7 +106,8 @@ TEST_F(AndroidSensorManagerTest, TwoDeviceMotionSensorsActive) {
sensorManager.GotAccelerationIncludingGravity(0, 0, 1, 2, 3);
ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kInertialSensorIntervalMillis, motion_buffer_->data.interval);
+ ASSERT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
+ motion_buffer_->data.interval);
sensorManager.StopFetchingDeviceMotionData();
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
@@ -116,7 +120,8 @@ TEST_F(AndroidSensorManagerTest, ZeroDeviceMotionSensorsActive) {
sensorManager.StartFetchingDeviceMotionData(motion_buffer_.get());
ASSERT_TRUE(motion_buffer_->data.allAvailableSensorsAreActive);
- ASSERT_EQ(kInertialSensorIntervalMillis, motion_buffer_->data.interval);
+ ASSERT_EQ(kInertialSensorIntervalMicroseconds / 1000.,
+ motion_buffer_->data.interval);
sensorManager.StopFetchingDeviceMotionData();
ASSERT_FALSE(motion_buffer_->data.allAvailableSensorsAreActive);
@@ -142,6 +147,19 @@ TEST_F(AndroidSensorManagerTest, DeviceOrientationSensorsActive) {
ASSERT_FALSE(orientation_buffer_->data.allAvailableSensorsAreActive);
}
+// DeviceLight
+TEST_F(AndroidSensorManagerTest, DeviceLightSensorsActive) {
+ FakeSensorManagerAndroid::Register(base::android::AttachCurrentThread());
+ FakeSensorManagerAndroid sensorManager;
+
+ sensorManager.StartFetchingDeviceLightData(light_buffer_.get());
+
+ sensorManager.GotLight(0, 0, 100);
+ ASSERT_EQ(100, light_buffer_->data.value);
+
+ sensorManager.StopFetchingDeviceLightData();
+ ASSERT_EQ(-1, light_buffer_->data.value);
+}
} // namespace
diff --git a/chromium/content/browser/devtools/BUILD.gn b/chromium/content/browser/devtools/BUILD.gn
index 4aab2bab11e..75777316dcd 100644
--- a/chromium/content/browser/devtools/BUILD.gn
+++ b/chromium/content/browser/devtools/BUILD.gn
@@ -9,40 +9,27 @@ group("resources") {
deps = [
":devtools_resources",
":devtools_protocol_constants",
+ ":devtools_protocol_handler",
]
}
# In GYP: devtools_resources action in the devtools_resources target.
-action("devtools_resources") {
- visibility = ":resources"
+grit("devtools_resources") {
+ source = "$root_gen_dir/devtools/devtools_resources.grd"
- # This can't use grit_rule.gni because the grd file is generated at build
- # time, so the trick of using grit_info to get the real inputs/outputs at GYP
- # time isn't possible.
- script = "//tools/grit/grit.py"
-
- grdfile = "$root_gen_dir/devtools/devtools_resources.grd"
-
- source_prereqs = [ grdfile ] +
- rebase_path(exec_script("//tools/grit/grit_info.py", [ "--inputs" ],
- "list lines"),
- ".", "//")
-
- out_dir = "$root_gen_dir/webkit"
+ # TOOD(brettw) remove this so the output file goes into the target_gen_dir,
+ # but keep this for not for GYP compat.
+ output_dir = "$root_gen_dir/webkit"
outputs = [
- "$out_dir/grit/devtools_resources.h",
- "$out_dir/devtools_resources.pak",
- "$out_dir/grit/devtools_resources_map.cc",
- "$out_dir/grit/devtools_resources_map.h",
+ "grit/devtools_resources.h",
+ "devtools_resources.pak",
+ "grit/devtools_resources_map.cc",
+ "grit/devtools_resources_map.h",
]
- args = [
- "-i", rebase_path(grdfile, root_build_dir), "build",
- "-f", rebase_path("//tools/gritsettings/resource_ids", root_build_dir),
- "-o", rebase_path(out_dir, root_build_dir),
- "-D", "SHARED_INTERMEDIATE_DIR=" +
- rebase_path(root_gen_dir, root_build_dir),
- ] + grit_defines
+ defines = [
+ "SHARED_INTERMEDIATE_DIR=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
deps = [
# This is the action that generates out .grd input file.
@@ -50,14 +37,14 @@ action("devtools_resources") {
]
}
-action("devtools_protocol_constants") {
- visibility = ":resources"
+action("gen_devtools_protocol_constants") {
+ visibility = [ ":devtools_protocol_constants" ]
script = "//content/public/browser/devtools_protocol_constants_generator.py"
blink_protocol = "//third_party/WebKit/Source/devtools/protocol.json"
browser_protocol = "browser_protocol.json"
- source_prereqs = [ blink_protocol, browser_protocol ]
+ inputs = [ blink_protocol, browser_protocol ]
outputs = [
"$target_gen_dir/devtools_protocol_constants.cc",
@@ -69,3 +56,32 @@ action("devtools_protocol_constants") {
rebase_path(browser_protocol, root_build_dir),
]
}
+
+action("gen_devtools_protocol_handler") {
+ visibility = [ ":devtools_protocol_handler" ]
+
+ script = "//content/browser/devtools/protocol/" +
+ "devtools_protocol_handler_generator.py"
+
+ blink_protocol = "//third_party/WebKit/Source/devtools/protocol.json"
+ inputs = [ blink_protocol ]
+
+ outputs = [
+ "$target_gen_dir/protocol/devtools_protocol_handler_impl.cc",
+ "$target_gen_dir/protocol/devtools_protocol_handler_impl.h",
+ ]
+
+ args = [
+ rebase_path(blink_protocol, root_build_dir),
+ ] + rebase_path(outputs, root_build_dir)
+}
+
+source_set("devtools_protocol_constants") {
+ visibility = [ ":resources" ]
+ sources = get_target_outputs(":gen_devtools_protocol_constants")
+}
+
+source_set("devtools_protocol_handler") {
+ visibility = [ ":resources" ]
+ sources = get_target_outputs(":gen_devtools_protocol_handler")
+}
diff --git a/chromium/content/browser/devtools/OWNERS b/chromium/content/browser/devtools/OWNERS
index d995b0f999c..88a3d57bb91 100644
--- a/chromium/content/browser/devtools/OWNERS
+++ b/chromium/content/browser/devtools/OWNERS
@@ -1,4 +1,4 @@
-kaznacheev@chromium.org
+dgozman@chromium.org
pfeldman@chromium.org
vsevik@chromium.org
yurys@chromium.org
diff --git a/chromium/content/browser/devtools/browser_protocol.json b/chromium/content/browser/devtools/browser_protocol.json
index dfb462febf2..f4b67407d2e 100644
--- a/chromium/content/browser/devtools/browser_protocol.json
+++ b/chromium/content/browser/devtools/browser_protocol.json
@@ -47,5 +47,39 @@
"handlers": ["browser"]
}
]
+ },
+ {
+ "domain": "Tethering",
+ "description": "The Tethering domain defines methods and events for browser port binding.",
+ "hidden": true,
+ "commands": [
+ {
+ "name": "bind",
+ "description": "Request browser port binding.",
+ "parameters": [
+ { "name": "port", "type": "number", "description": "Port number to bind." }
+ ],
+ "handlers": ["browser"]
+ },
+ {
+ "name": "unbind",
+ "description": "Request browser port unbinding.",
+ "parameters": [
+ { "name": "port", "type": "number", "description": "Port number to unbind." }
+ ],
+ "handlers": ["browser"]
+ }
+ ],
+ "events": [
+ {
+ "name": "accepted",
+ "description": "Informs that port was successfully bound and got a specified connection id.",
+ "parameters": [
+ {"name": "port", "type": "number", "description": "Port number that was successfully bound." },
+ {"name": "connectionId", "type": "string", "description": "Connection id to be used." }
+ ],
+ "handlers": ["browser"]
+ }
+ ]
}]
}
diff --git a/chromium/content/browser/devtools/devtools.gyp b/chromium/content/browser/devtools/devtools.gyp
new file mode 100644
index 00000000000..a67eca87890
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools.gyp
@@ -0,0 +1,44 @@
+# Copyright 2014 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'devtools_protocol_handler',
+ 'type': 'none',
+ 'actions': [
+ {
+ 'action_name': 'devtools_protocol_handler',
+ 'variables': {
+ 'blink_protocol': '../../../third_party/WebKit/Source/devtools/protocol.json',
+ 'generator': 'protocol/devtools_protocol_handler_generator.py',
+ 'output_cc': '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_handler_impl.cc',
+ 'output_h': '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_handler_impl.h',
+ },
+ 'inputs': [
+ '<(blink_protocol)',
+ '<(generator)',
+ ],
+ 'outputs': [
+ '<(output_cc)',
+ '<(output_h)',
+ ],
+ 'action':[
+ 'python',
+ '<(generator)',
+ '<(blink_protocol)',
+ '<(output_cc)',
+ '<(output_h)',
+ ],
+ 'message': 'Generating DevTools protocol browser-side handlers from <(blink_protocol)'
+ },
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ]
+ },
+ },
+ ],
+}
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index bcb60b55b78..b7f9b24b59f 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -5,24 +5,45 @@
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include <map>
+#include <vector>
#include "base/basictypes.h"
#include "base/guid.h"
#include "base/lazy_instance.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/devtools/embedded_worker_devtools_manager.h"
#include "content/browser/devtools/forwarding_agent_host.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/devtools_manager_delegate.h"
namespace content {
namespace {
typedef std::map<std::string, DevToolsAgentHostImpl*> Instances;
base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
+
+typedef std::vector<const DevToolsAgentHost::AgentStateCallback*>
+ AgentStateCallbacks;
+base::LazyInstance<AgentStateCallbacks>::Leaky g_callbacks =
+ LAZY_INSTANCE_INITIALIZER;
} // namespace
+// static
+DevToolsAgentHost::List DevToolsAgentHost::GetOrCreateAll() {
+ List result = EmbeddedWorkerDevToolsManager::GetInstance()
+ ->GetOrCreateAllAgentHosts();
+ std::vector<WebContents*> wc_list =
+ DevToolsAgentHostImpl::GetInspectableWebContents();
+ for (std::vector<WebContents*>::iterator it = wc_list.begin();
+ it != wc_list.end(); ++it) {
+ result.push_back(GetOrCreateFor(*it));
+ }
+ return result;
+}
+
DevToolsAgentHostImpl::DevToolsAgentHostImpl()
- : close_listener_(NULL),
- id_(base::GenerateGUID()) {
+ : id_(base::GenerateGUID()),
+ client_(NULL) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
g_instances.Get()[id_] = this;
}
@@ -32,7 +53,7 @@ DevToolsAgentHostImpl::~DevToolsAgentHostImpl() {
g_instances.Get().erase(g_instances.Get().find(id_));
}
-//static
+// static
scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForId(
const std::string& id) {
if (g_instances == NULL)
@@ -49,8 +70,29 @@ scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::Create(
return new ForwardingAgentHost(delegate);
}
+void DevToolsAgentHostImpl::AttachClient(DevToolsAgentHostClient* client) {
+ scoped_refptr<DevToolsAgentHostImpl> protect(this);
+ if (client_) {
+ client_->AgentHostClosed(this, true);
+ Detach();
+ }
+ client_ = client;
+ Attach();
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
+}
+
+void DevToolsAgentHostImpl::DetachClient() {
+ if (!client_)
+ return;
+
+ scoped_refptr<DevToolsAgentHostImpl> protect(this);
+ client_ = NULL;
+ Detach();
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
+}
+
bool DevToolsAgentHostImpl::IsAttached() {
- return !!DevToolsManagerImpl::GetInstance()->GetDevToolsClientHostFor(this);
+ return !!client_;
}
void DevToolsAgentHostImpl::InspectElement(int x, int y) {
@@ -60,24 +102,94 @@ std::string DevToolsAgentHostImpl::GetId() {
return id_;
}
-RenderViewHost* DevToolsAgentHostImpl::GetRenderViewHost() {
+WebContents* DevToolsAgentHostImpl::GetWebContents() {
return NULL;
}
-void DevToolsAgentHostImpl::DisconnectRenderViewHost() {}
+void DevToolsAgentHostImpl::DisconnectWebContents() {
+}
-void DevToolsAgentHostImpl::ConnectRenderViewHost(RenderViewHost* rvh) {}
+void DevToolsAgentHostImpl::ConnectWebContents(WebContents* wc) {
+}
bool DevToolsAgentHostImpl::IsWorker() const {
return false;
}
-void DevToolsAgentHostImpl::NotifyCloseListener() {
- if (close_listener_) {
- scoped_refptr<DevToolsAgentHostImpl> protect(this);
- close_listener_->AgentHostClosing(this);
- close_listener_ = NULL;
+void DevToolsAgentHostImpl::HostClosed() {
+ if (!client_)
+ return;
+
+ scoped_refptr<DevToolsAgentHostImpl> protect(this);
+ // Clear |client_| before notifying it.
+ DevToolsAgentHostClient* client = client_;
+ client_ = NULL;
+ client->AgentHostClosed(this, false);
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
+}
+
+void DevToolsAgentHostImpl::SendMessageToClient(const std::string& message) {
+ if (!client_)
+ return;
+ client_->DispatchProtocolMessage(this, message);
+}
+
+// static
+void DevToolsAgentHost::DetachAllClients() {
+ if (g_instances == NULL)
+ return;
+
+ // Make a copy, since detaching may lead to agent destruction, which
+ // removes it from the instances.
+ Instances copy = g_instances.Get();
+ for (Instances::iterator it(copy.begin()); it != copy.end(); ++it) {
+ DevToolsAgentHostImpl* agent_host = it->second;
+ if (agent_host->client_) {
+ scoped_refptr<DevToolsAgentHostImpl> protect(agent_host);
+ // Clear |client_| before notifying it.
+ DevToolsAgentHostClient* client = agent_host->client_;
+ agent_host->client_ = NULL;
+ client->AgentHostClosed(agent_host, true);
+ agent_host->Detach();
+ DevToolsManager::GetInstance()->AgentHostChanged(protect);
+ }
}
}
+// static
+void DevToolsAgentHost::AddAgentStateCallback(
+ const AgentStateCallback& callback) {
+ g_callbacks.Get().push_back(&callback);
+}
+
+// static
+void DevToolsAgentHost::RemoveAgentStateCallback(
+ const AgentStateCallback& callback) {
+ if (g_callbacks == NULL)
+ return;
+
+ AgentStateCallbacks* callbacks_ = g_callbacks.Pointer();
+ AgentStateCallbacks::iterator it =
+ std::find(callbacks_->begin(), callbacks_->end(), &callback);
+ DCHECK(it != callbacks_->end());
+ callbacks_->erase(it);
+}
+
+// static
+void DevToolsAgentHostImpl::NotifyCallbacks(
+ DevToolsAgentHostImpl* agent_host, bool attached) {
+ AgentStateCallbacks copy(g_callbacks.Get());
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ if (manager->delegate())
+ manager->delegate()->DevToolsAgentStateChanged(agent_host, attached);
+ for (AgentStateCallbacks::iterator it = copy.begin(); it != copy.end(); ++it)
+ (*it)->Run(agent_host, attached);
+}
+
+void DevToolsAgentHostImpl::Inspect(BrowserContext* browser_context) {
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ if (manager->delegate())
+ manager->delegate()->Inspect(browser_context, this);
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index d0fad668b49..694590acf1c 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -17,15 +17,13 @@ class Message;
namespace content {
+class BrowserContext;
+
// Describes interface for managing devtools agents from the browser process.
class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
public:
- class CONTENT_EXPORT CloseListener {
- public:
- virtual void AgentHostClosing(DevToolsAgentHostImpl*) = 0;
- protected:
- virtual ~CloseListener() {}
- };
+ // Returns a list of all existing WebContents that can be debugged.
+ static std::vector<WebContents*> GetInspectableWebContents();
// Informs the hosted agent that a client host has attached.
virtual void Attach() = 0;
@@ -33,37 +31,36 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
// Informs the hosted agent that a client host has detached.
virtual void Detach() = 0;
- // Sends a message to the agent hosted by this object.
- virtual void DispatchOnInspectorBackend(const std::string& message) = 0;
+ // Sends a message to the agent.
+ virtual void DispatchProtocolMessage(const std::string& message) = 0;
- void set_close_listener(CloseListener* listener) {
- close_listener_ = listener;
- }
+ // Opens the inspector for this host.
+ void Inspect(BrowserContext* browser_context);
// DevToolsAgentHost implementation.
- virtual bool IsAttached() OVERRIDE;
-
- virtual void InspectElement(int x, int y) OVERRIDE;
-
- virtual std::string GetId() OVERRIDE;
-
- virtual RenderViewHost* GetRenderViewHost() OVERRIDE;
-
- virtual void DisconnectRenderViewHost() OVERRIDE;
-
- virtual void ConnectRenderViewHost(RenderViewHost* rvh) OVERRIDE;
-
- virtual bool IsWorker() const OVERRIDE;
+ void AttachClient(DevToolsAgentHostClient* client) override;
+ void DetachClient() override;
+ bool IsAttached() override;
+ void InspectElement(int x, int y) override;
+ std::string GetId() override;
+ WebContents* GetWebContents() override;
+ void DisconnectWebContents() override;
+ void ConnectWebContents(WebContents* wc) override;
+ bool IsWorker() const override;
protected:
DevToolsAgentHostImpl();
- virtual ~DevToolsAgentHostImpl();
+ ~DevToolsAgentHostImpl() override;
- void NotifyCloseListener();
+ void HostClosed();
+ void SendMessageToClient(const std::string& message);
+ static void NotifyCallbacks(DevToolsAgentHostImpl* agent_host, bool attached);
private:
- CloseListener* close_listener_;
+ friend class DevToolsAgentHost; // for static methods
+
const std::string id_;
+ DevToolsAgentHostClient* client_;
};
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_browser_target.cc b/chromium/content/browser/devtools/devtools_browser_target.cc
deleted file mode 100644
index b050152d2e4..00000000000
--- a/chromium/content/browser/devtools/devtools_browser_target.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/devtools/devtools_browser_target.h"
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/server/http_server.h"
-
-namespace content {
-
-DevToolsBrowserTarget::DevToolsBrowserTarget(
- net::HttpServer* http_server,
- int connection_id)
- : message_loop_proxy_(base::MessageLoopProxy::current()),
- http_server_(http_server),
- connection_id_(connection_id),
- weak_factory_(this) {
-}
-
-void DevToolsBrowserTarget::RegisterDomainHandler(
- const std::string& domain,
- DevToolsProtocol::Handler* handler,
- bool handle_on_ui_thread) {
- DCHECK_EQ(message_loop_proxy_, base::MessageLoopProxy::current());
-
- DCHECK(handlers_.find(domain) == handlers_.end());
- handlers_[domain] = handler;
- if (handle_on_ui_thread) {
- handle_on_ui_thread_.insert(domain);
- handler->SetNotifier(base::Bind(&DevToolsBrowserTarget::RespondFromUIThread,
- weak_factory_.GetWeakPtr()));
- } else {
- handler->SetNotifier(base::Bind(&DevToolsBrowserTarget::Respond,
- base::Unretained(this)));
- }
-}
-
-typedef std::map<std::string, DevToolsBrowserTarget*> DomainMap;
-base::LazyInstance<DomainMap>::Leaky g_used_domains = LAZY_INSTANCE_INITIALIZER;
-
-void DevToolsBrowserTarget::HandleMessage(const std::string& data) {
- DCHECK_EQ(message_loop_proxy_, base::MessageLoopProxy::current());
- std::string error_response;
- scoped_refptr<DevToolsProtocol::Command> command =
- DevToolsProtocol::ParseCommand(data, &error_response);
- if (!command) {
- Respond(error_response);
- return;
- }
-
- DomainHandlerMap::iterator it = handlers_.find(command->domain());
- if (it == handlers_.end()) {
- Respond(command->NoSuchMethodErrorResponse()->Serialize());
- return;
- }
- DomainMap& used_domains(g_used_domains.Get());
- std::string domain = command->domain();
- DomainMap::iterator jt = used_domains.find(domain);
- if (jt == used_domains.end()) {
- used_domains[domain] = this;
- } else if (jt->second != this) {
- std::string message =
- base::StringPrintf("'%s' is held by another connection",
- domain.c_str());
- Respond(command->ServerErrorResponse(message)->Serialize());
- return;
- }
-
- DevToolsProtocol::Handler* handler = it->second;
- bool handle_directly = handle_on_ui_thread_.find(domain) ==
- handle_on_ui_thread_.end();
- if (handle_directly) {
- scoped_refptr<DevToolsProtocol::Response> response =
- handler->HandleCommand(command);
- if (response && response->is_async_promise())
- return;
- if (response)
- Respond(response->Serialize());
- else
- Respond(command->NoSuchMethodErrorResponse()->Serialize());
- return;
- }
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&DevToolsBrowserTarget::HandleCommandOnUIThread,
- this,
- handler,
- command));
-}
-
-void DevToolsBrowserTarget::Detach() {
- DCHECK_EQ(message_loop_proxy_, base::MessageLoopProxy::current());
- DCHECK(http_server_);
-
- http_server_ = NULL;
-
- DomainMap& used_domains(g_used_domains.Get());
- for (DomainMap::iterator it = used_domains.begin();
- it != used_domains.end();) {
- if (it->second == this) {
- DomainMap::iterator to_erase = it;
- ++it;
- used_domains.erase(to_erase);
- } else {
- ++it;
- }
- }
-
- std::vector<DevToolsProtocol::Handler*> ui_handlers;
- for (std::set<std::string>::iterator domain_it = handle_on_ui_thread_.begin();
- domain_it != handle_on_ui_thread_.end();
- ++domain_it) {
- DomainHandlerMap::iterator handler_it = handlers_.find(*domain_it);
- CHECK(handler_it != handlers_.end());
- ui_handlers.push_back(handler_it->second);
- handlers_.erase(handler_it);
- }
-
- STLDeleteValues(&handlers_);
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&DevToolsBrowserTarget::DeleteHandlersOnUIThread,
- this,
- ui_handlers));
-}
-
-DevToolsBrowserTarget::~DevToolsBrowserTarget() {
- // DCHECK that Detach has been called or no handler has ever been registered.
- DCHECK(handlers_.empty());
-}
-
-void DevToolsBrowserTarget::HandleCommandOnUIThread(
- DevToolsProtocol::Handler* handler,
- scoped_refptr<DevToolsProtocol::Command> command) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_refptr<DevToolsProtocol::Response> response =
- handler->HandleCommand(command);
- if (response && response->is_async_promise())
- return;
-
- if (response)
- RespondFromUIThread(response->Serialize());
- else
- RespondFromUIThread(command->NoSuchMethodErrorResponse()->Serialize());
-}
-
-void DevToolsBrowserTarget::DeleteHandlersOnUIThread(
- std::vector<DevToolsProtocol::Handler*> handlers) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- STLDeleteElements(&handlers);
-}
-
-void DevToolsBrowserTarget::Respond(const std::string& message) {
- DCHECK_EQ(message_loop_proxy_, base::MessageLoopProxy::current());
- if (!http_server_)
- return;
- http_server_->SendOverWebSocket(connection_id_, message);
-}
-
-void DevToolsBrowserTarget::RespondFromUIThread(const std::string& message) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- message_loop_proxy_->PostTask(
- FROM_HERE,
- base::Bind(&DevToolsBrowserTarget::Respond, this, message));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_browser_target.h b/chromium/content/browser/devtools/devtools_browser_target.h
deleted file mode 100644
index 0dda59b2ad4..00000000000
--- a/chromium/content/browser/devtools/devtools_browser_target.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_TARGET_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_TARGET_H_
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/devtools/devtools_protocol.h"
-
-namespace base {
-class DictionaryValue;
-class MessageLoopProxy;
-class Value;
-} // namespace base
-
-namespace net {
-class HttpServer;
-} // namespace net
-
-namespace content {
-
-// This class handles the "Browser" target for remote debugging.
-class DevToolsBrowserTarget
- : public base::RefCountedThreadSafe<DevToolsBrowserTarget> {
- public:
- DevToolsBrowserTarget(net::HttpServer* server, int connection_id);
-
- int connection_id() const { return connection_id_; }
-
- // Takes ownership of |handler|.
- void RegisterDomainHandler(const std::string& domain,
- DevToolsProtocol::Handler* handler,
- bool handle_on_ui_thread);
-
- void HandleMessage(const std::string& data);
-
- void Detach();
-
- private:
- friend class base::RefCountedThreadSafe<DevToolsBrowserTarget>;
- ~DevToolsBrowserTarget();
-
- void HandleCommandOnUIThread(
- DevToolsProtocol::Handler*,
- scoped_refptr<DevToolsProtocol::Command> command);
-
- void DeleteHandlersOnUIThread(
- std::vector<DevToolsProtocol::Handler*> handlers);
-
- void Respond(const std::string& message);
- void RespondFromUIThread(const std::string& message);
-
- scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
- net::HttpServer* http_server_;
- const int connection_id_;
-
- typedef std::map<std::string, DevToolsProtocol::Handler*> DomainHandlerMap;
- DomainHandlerMap handlers_;
- std::set<std::string> handle_on_ui_thread_;
- base::WeakPtrFactory<DevToolsBrowserTarget> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(DevToolsBrowserTarget);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_BROWSER_TARGET_H_
diff --git a/chromium/content/browser/devtools/devtools_frontend_host.cc b/chromium/content/browser/devtools/devtools_frontend_host.cc
deleted file mode 100644
index bfa623a140e..00000000000
--- a/chromium/content/browser/devtools/devtools_frontend_host.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/devtools/devtools_frontend_host.h"
-
-#include "content/browser/devtools/devtools_manager_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/devtools_messages.h"
-#include "content/public/browser/devtools_client_host.h"
-#include "content/public/browser/devtools_frontend_host_delegate.h"
-
-namespace content {
-
-// static
-DevToolsClientHost* DevToolsClientHost::CreateDevToolsFrontendHost(
- WebContents* client_web_contents,
- DevToolsFrontendHostDelegate* delegate) {
- return new DevToolsFrontendHost(
- static_cast<WebContentsImpl*>(client_web_contents), delegate);
-}
-
-// static
-void DevToolsClientHost::SetupDevToolsFrontendClient(
- RenderViewHost* frontend_rvh) {
- frontend_rvh->Send(new DevToolsMsg_SetupDevToolsClient(
- frontend_rvh->GetRoutingID()));
-}
-
-DevToolsFrontendHost::DevToolsFrontendHost(
- WebContentsImpl* web_contents,
- DevToolsFrontendHostDelegate* delegate)
- : WebContentsObserver(web_contents),
- delegate_(delegate) {
-}
-
-DevToolsFrontendHost::~DevToolsFrontendHost() {
- DevToolsManager::GetInstance()->ClientHostClosing(this);
-}
-
-void DevToolsFrontendHost::DispatchOnInspectorFrontend(
- const std::string& message) {
- if (!web_contents())
- return;
- RenderViewHostImpl* target_host =
- static_cast<RenderViewHostImpl*>(web_contents()->GetRenderViewHost());
- target_host->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
- target_host->GetRoutingID(),
- message));
-}
-
-void DevToolsFrontendHost::InspectedContentsClosing() {
- delegate_->InspectedContentsClosing();
-}
-
-void DevToolsFrontendHost::ReplacedWithAnotherClient() {
-}
-
-bool DevToolsFrontendHost::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(DevToolsFrontendHost, message)
- IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
- OnDispatchOnInspectorBackend)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_DispatchOnEmbedder,
- OnDispatchOnEmbedder)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void DevToolsFrontendHost::RenderProcessGone(
- base::TerminationStatus status) {
- switch(status) {
- case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
- case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
- case base::TERMINATION_STATUS_PROCESS_CRASHED:
- DevToolsManager::GetInstance()->ClientHostClosing(this);
- break;
- default:
- break;
- }
-}
-
-void DevToolsFrontendHost::OnDispatchOnInspectorBackend(
- const std::string& message) {
- DevToolsManagerImpl::GetInstance()->DispatchOnInspectorBackend(this, message);
-}
-
-void DevToolsFrontendHost::OnDispatchOnEmbedder(
- const std::string& message) {
- delegate_->DispatchOnEmbedder(message);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_frontend_host.h b/chromium/content/browser/devtools/devtools_frontend_host.h
deleted file mode 100644
index 469d162bf9c..00000000000
--- a/chromium/content/browser/devtools/devtools_frontend_host.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "content/public/browser/devtools_client_host.h"
-#include "content/public/browser/web_contents_observer.h"
-
-namespace content {
-
-class DevToolsFrontendHostDelegate;
-class WebContentsImpl;
-
-// This class handles messages from DevToolsClient and calls corresponding
-// methods on DevToolsFrontendHostDelegate which is implemented by the
-// embedder. This allows us to avoid exposing DevTools client messages through
-// the content public API.
-class DevToolsFrontendHost : public DevToolsClientHost,
- public WebContentsObserver {
- public:
- DevToolsFrontendHost(WebContentsImpl* web_contents,
- DevToolsFrontendHostDelegate* delegate);
-
- private:
- virtual ~DevToolsFrontendHost();
-
- // DevToolsClientHost implementation.
- virtual void DispatchOnInspectorFrontend(const std::string& message) OVERRIDE;
- virtual void InspectedContentsClosing() OVERRIDE;
- virtual void ReplacedWithAnotherClient() OVERRIDE;
-
- // WebContentsObserver overrides.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
-
- void OnDispatchOnInspectorBackend(const std::string& message);
- void OnDispatchOnEmbedder(const std::string& message);
-
- DevToolsFrontendHostDelegate* delegate_;
- DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_H_
diff --git a/chromium/content/browser/devtools/devtools_frontend_host_impl.cc b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
new file mode 100644
index 00000000000..a73e88cb50a
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_frontend_host_impl.cc
@@ -0,0 +1,56 @@
+// Copyright 2014 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 "content/browser/devtools/devtools_frontend_host_impl.h"
+
+#include "content/common/devtools_messages.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+// static
+DevToolsFrontendHost* DevToolsFrontendHost::Create(
+ RenderViewHost* frontend_rvh,
+ DevToolsFrontendHost::Delegate* delegate) {
+ return new DevToolsFrontendHostImpl(frontend_rvh, delegate);
+}
+
+DevToolsFrontendHostImpl::DevToolsFrontendHostImpl(
+ RenderViewHost* frontend_rvh,
+ DevToolsFrontendHost::Delegate* delegate)
+ : WebContentsObserver(WebContents::FromRenderViewHost(frontend_rvh)),
+ delegate_(delegate) {
+ frontend_rvh->Send(new DevToolsMsg_SetupDevToolsClient(
+ frontend_rvh->GetRoutingID()));
+}
+
+DevToolsFrontendHostImpl::~DevToolsFrontendHostImpl() {
+}
+
+bool DevToolsFrontendHostImpl::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DevToolsFrontendHostImpl, message)
+ IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
+ OnDispatchOnInspectorBackend)
+ IPC_MESSAGE_HANDLER(DevToolsHostMsg_DispatchOnEmbedder,
+ OnDispatchOnEmbedder)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void DevToolsFrontendHostImpl::OnDispatchOnInspectorBackend(
+ const std::string& message) {
+ delegate_->HandleMessageFromDevToolsFrontendToBackend(message);
+}
+
+void DevToolsFrontendHostImpl::OnDispatchOnEmbedder(
+ const std::string& message) {
+ delegate_->HandleMessageFromDevToolsFrontend(message);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_frontend_host_impl.h b/chromium/content/browser/devtools/devtools_frontend_host_impl.h
new file mode 100644
index 00000000000..98b907497a1
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_frontend_host_impl.h
@@ -0,0 +1,33 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_IMPL_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_IMPL_H_
+
+#include "content/public/browser/devtools_frontend_host.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+
+class DevToolsFrontendHostImpl : public DevToolsFrontendHost,
+ public WebContentsObserver {
+ public:
+ DevToolsFrontendHostImpl(RenderViewHost* frontend_rvh,
+ DevToolsFrontendHost::Delegate* delegate);
+ ~DevToolsFrontendHostImpl() override;
+
+ private:
+ // WebContentsObserver overrides.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnDispatchOnInspectorBackend(const std::string& message);
+ void OnDispatchOnEmbedder(const std::string& message);
+
+ DevToolsFrontendHost::Delegate* delegate_;
+ DISALLOW_COPY_AND_ASSIGN(DevToolsFrontendHostImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_FRONTEND_HOST_IMPL_H_
diff --git a/chromium/content/browser/devtools/devtools_http_handler_impl.cc b/chromium/content/browser/devtools/devtools_http_handler_impl.cc
index d1b5b1e6724..e7b7fb9b99e 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_impl.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_impl.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
@@ -17,23 +17,21 @@
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread.h"
#include "base/values.h"
-#include "content/browser/devtools/devtools_browser_target.h"
+#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_protocol.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/browser/devtools/devtools_system_info_handler.h"
-#include "content/browser/devtools/devtools_tracing_handler.h"
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+#include "content/browser/devtools/protocol/tracing_handler.h"
#include "content/browser/devtools/tethering_handler.h"
#include "content/common/devtools_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
-#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/devtools_target.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/user_agent.h"
-#include "content/public/common/user_agent.h"
#include "grit/devtools_resources_map.h"
#include "net/base/escape.h"
#include "net/base/io_buffer.h"
@@ -41,6 +39,7 @@
#include "net/base/net_errors.h"
#include "net/server/http_server_request_info.h"
#include "net/server/http_server_response_info.h"
+#include "net/socket/server_socket.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
@@ -69,64 +68,79 @@ const char kTargetFaviconUrlField[] = "faviconUrl";
const char kTargetWebSocketDebuggerUrlField[] = "webSocketDebuggerUrl";
const char kTargetDevtoolsFrontendUrlField[] = "devtoolsFrontendUrl";
-// An internal implementation of DevToolsClientHost that delegates
-// messages sent for DevToolsClient to a DebuggerShell instance.
-class DevToolsClientHostImpl : public DevToolsClientHost {
+// Maximum write buffer size of devtools http/websocket connectinos.
+const int32 kSendBufferSizeForDevTools = 100 * 1024 * 1024; // 100Mb
+
+// DevToolsAgentHostClientImpl -----------------------------------------------
+
+// An internal implementation of DevToolsAgentHostClient that delegates
+// messages sent to a DebuggerShell instance.
+class DevToolsAgentHostClientImpl : public DevToolsAgentHostClient {
public:
- DevToolsClientHostImpl(base::MessageLoop* message_loop,
- net::HttpServer* server,
- int connection_id)
+ DevToolsAgentHostClientImpl(base::MessageLoop* message_loop,
+ net::HttpServer* server,
+ int connection_id,
+ DevToolsAgentHost* agent_host)
: message_loop_(message_loop),
server_(server),
connection_id_(connection_id),
- is_closed_(false),
- detach_reason_("target_closed") {}
+ agent_host_(agent_host) {
+ agent_host_->AttachClient(this);
+ }
- virtual ~DevToolsClientHostImpl() {}
+ ~DevToolsAgentHostClientImpl() override {
+ if (agent_host_.get())
+ agent_host_->DetachClient();
+ }
- // DevToolsClientHost interface
- virtual void InspectedContentsClosing() OVERRIDE {
- if (is_closed_)
- return;
- is_closed_ = true;
+ void AgentHostClosed(DevToolsAgentHost* agent_host,
+ bool replaced_with_another_client) override {
+ DCHECK(agent_host == agent_host_.get());
+ agent_host_ = NULL;
base::DictionaryValue notification;
notification.SetString(
- devtools::Inspector::detached::kParamReason, detach_reason_);
+ devtools::Inspector::detached::kParamReason,
+ replaced_with_another_client ?
+ "replaced_with_devtools" : "target_closed");
std::string response = DevToolsProtocol::CreateNotification(
devtools::Inspector::detached::kName,
notification.DeepCopy())->Serialize();
message_loop_->PostTask(
FROM_HERE,
base::Bind(&net::HttpServer::SendOverWebSocket,
- server_,
+ base::Unretained(server_),
connection_id_,
response));
message_loop_->PostTask(
FROM_HERE,
- base::Bind(&net::HttpServer::Close, server_, connection_id_));
+ base::Bind(&net::HttpServer::Close,
+ base::Unretained(server_),
+ connection_id_));
}
- virtual void DispatchOnInspectorFrontend(const std::string& data) OVERRIDE {
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override {
+ DCHECK(agent_host == agent_host_.get());
message_loop_->PostTask(
FROM_HERE,
base::Bind(&net::HttpServer::SendOverWebSocket,
- server_,
+ base::Unretained(server_),
connection_id_,
- data));
+ message));
}
- virtual void ReplacedWithAnotherClient() OVERRIDE {
- detach_reason_ = "replaced_with_devtools";
+ void OnMessage(const std::string& message) {
+ if (agent_host_.get())
+ agent_host_->DispatchProtocolMessage(message);
}
private:
- base::MessageLoop* message_loop_;
- net::HttpServer* server_;
- int connection_id_;
- bool is_closed_;
- std::string detach_reason_;
+ base::MessageLoop* const message_loop_;
+ net::HttpServer* const server_;
+ const int connection_id_;
+ scoped_refptr<DevToolsAgentHost> agent_host_;
};
static bool TimeComparator(const DevToolsTarget* target1,
@@ -136,6 +150,83 @@ static bool TimeComparator(const DevToolsTarget* target1,
} // namespace
+// DevToolsHttpHandlerImpl::BrowserTarget ------------------------------------
+
+class DevToolsHttpHandlerImpl::BrowserTarget {
+ public:
+ BrowserTarget(base::MessageLoop* message_loop,
+ net::HttpServer* server,
+ int connection_id)
+ : message_loop_(message_loop),
+ server_(server),
+ connection_id_(connection_id),
+ tracing_handler_(new devtools::tracing::TracingHandler(
+ devtools::tracing::TracingHandler::Browser)),
+ protocol_handler_(new DevToolsProtocolHandlerImpl()) {
+ protocol_handler_->SetNotifier(
+ base::Bind(&BrowserTarget::Respond, base::Unretained(this)));
+ protocol_handler_->SetTracingHandler(tracing_handler_.get());
+ }
+
+ ~BrowserTarget() {
+ STLDeleteElements(&handlers_);
+ }
+
+ // Takes ownership.
+ void RegisterHandler(DevToolsProtocol::Handler* handler) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ handler->SetNotifier(
+ base::Bind(&BrowserTarget::Respond, base::Unretained(this)));
+ handlers_.push_back(handler);
+ }
+
+ void HandleMessage(const std::string& message) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ std::string error_response;
+ scoped_refptr<DevToolsProtocol::Command> command =
+ DevToolsProtocol::ParseCommand(message, &error_response);
+ if (!command.get()) {
+ Respond(error_response);
+ return;
+ }
+
+ scoped_refptr<DevToolsProtocol::Response> response =
+ protocol_handler_->HandleCommand(command);
+ for (const auto& handler : handlers_) {
+ if (response.get())
+ break;
+ response = handler->HandleCommand(command);
+ }
+
+ if (response.get()) {
+ if (!response->is_async_promise())
+ Respond(response->Serialize());
+ } else {
+ Respond(command->NoSuchMethodErrorResponse()->Serialize());
+ }
+ }
+
+ void Respond(const std::string& message) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&net::HttpServer::SendOverWebSocket,
+ base::Unretained(server_),
+ connection_id_,
+ message));
+ }
+
+ private:
+ base::MessageLoop* const message_loop_;
+ net::HttpServer* const server_;
+ const int connection_id_;
+ scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_;
+ scoped_ptr<DevToolsProtocolHandlerImpl> protocol_handler_;
+ std::vector<DevToolsProtocol::Handler*> handlers_;
+};
+
+// DevToolsHttpHandler -------------------------------------------------------
+
// static
bool DevToolsHttpHandler::IsSupportedProtocolVersion(
const std::string& version) {
@@ -153,12 +244,12 @@ int DevToolsHttpHandler::GetFrontendResourceId(const std::string& name) {
// static
DevToolsHttpHandler* DevToolsHttpHandler::Start(
- const net::StreamListenSocketFactory* socket_factory,
+ scoped_ptr<ServerSocketFactory> server_socket_factory,
const std::string& frontend_url,
DevToolsHttpHandlerDelegate* delegate,
const base::FilePath& active_port_output_directory) {
DevToolsHttpHandlerImpl* http_handler =
- new DevToolsHttpHandlerImpl(socket_factory,
+ new DevToolsHttpHandlerImpl(server_socket_factory.Pass(),
frontend_url,
delegate,
active_port_output_directory);
@@ -166,6 +257,32 @@ DevToolsHttpHandler* DevToolsHttpHandler::Start(
return http_handler;
}
+// DevToolsHttpHandler::ServerSocketFactory ----------------------------------
+
+DevToolsHttpHandler::ServerSocketFactory::ServerSocketFactory(
+ const std::string& address,
+ int port,
+ int backlog)
+ : address_(address),
+ port_(port),
+ backlog_(backlog) {
+}
+
+DevToolsHttpHandler::ServerSocketFactory::~ServerSocketFactory() {
+}
+
+scoped_ptr<net::ServerSocket>
+DevToolsHttpHandler::ServerSocketFactory::CreateAndListen() const {
+ scoped_ptr<net::ServerSocket> socket = Create();
+ if (socket &&
+ socket->ListenWithAddressAndPort(address_, port_, backlog_) == net::OK) {
+ return socket.Pass();
+ }
+ return scoped_ptr<net::ServerSocket>();
+}
+
+// DevToolsHttpHandlerImpl ---------------------------------------------------
+
DevToolsHttpHandlerImpl::~DevToolsHttpHandlerImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Stop() must be called prior to destruction.
@@ -201,6 +318,7 @@ void DevToolsHttpHandlerImpl::StartHandlerThread() {
void DevToolsHttpHandlerImpl::ResetHandlerThread() {
thread_.reset();
+ server_ip_address_.reset();
}
void DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease() {
@@ -217,11 +335,19 @@ void DevToolsHttpHandlerImpl::Stop() {
base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThreadAndRelease, this));
}
+void DevToolsHttpHandlerImpl::StopWithoutRelease() {
+ if (!thread_)
+ return;
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DevToolsHttpHandlerImpl::StopHandlerThread, this),
+ base::Bind(&DevToolsHttpHandlerImpl::ResetHandlerThread, this));
+}
+
GURL DevToolsHttpHandlerImpl::GetFrontendURL() {
- net::IPEndPoint ip_address;
- if (server_->GetLocalAddress(&ip_address))
+ if (!server_ip_address_)
return GURL();
- return GURL(std::string("http://") + ip_address.ToString() + frontend_url_);
+ return GURL(std::string("http://") + server_ip_address_->ToString() + frontend_url_);
}
static std::string PathWithoutParams(const std::string& path) {
@@ -255,6 +381,8 @@ static std::string GetMimeType(const std::string& filename) {
void DevToolsHttpHandlerImpl::OnHttpRequest(
int connection_id,
const net::HttpServerRequestInfo& info) {
+ server_->SetSendBufferSize(connection_id, kSendBufferSizeForDevTools);
+
if (info.path.find("/json") == 0) {
BrowserThread::PostTask(
BrowserThread::UI,
@@ -314,7 +442,7 @@ void DevToolsHttpHandlerImpl::OnHttpRequest(
int resource_id = DevToolsHttpHandler::GetFrontendResourceId(filename);
if (resource_id != -1) {
base::StringPiece data = GetContentClient()->GetDataResource(
- resource_id, ui::SCALE_FACTOR_NONE);
+ resource_id, ui::SCALE_FACTOR_NONE);
server_->Send200(connection_id, data.as_string(), mime_type);
return;
}
@@ -325,29 +453,6 @@ void DevToolsHttpHandlerImpl::OnHttpRequest(
void DevToolsHttpHandlerImpl::OnWebSocketRequest(
int connection_id,
const net::HttpServerRequestInfo& request) {
- std::string browser_prefix = "/devtools/browser";
- size_t browser_pos = request.path.find(browser_prefix);
- if (browser_pos == 0) {
- scoped_refptr<DevToolsBrowserTarget> browser_target =
- new DevToolsBrowserTarget(server_.get(), connection_id);
- browser_target->RegisterDomainHandler(
- devtools::Tracing::kName,
- new DevToolsTracingHandler(DevToolsTracingHandler::Browser),
- true /* handle on UI thread */);
- browser_target->RegisterDomainHandler(
- TetheringHandler::kDomain,
- new TetheringHandler(delegate_.get()),
- false /* handle on this thread */);
- browser_target->RegisterDomainHandler(
- devtools::SystemInfo::kName,
- new DevToolsSystemInfoHandler(),
- true /* handle on UI thread */);
- browser_targets_[connection_id] = browser_target;
-
- server_->AcceptWebSocket(connection_id, request);
- return;
- }
-
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -361,12 +466,6 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequest(
void DevToolsHttpHandlerImpl::OnWebSocketMessage(
int connection_id,
const std::string& data) {
- BrowserTargets::iterator it = browser_targets_.find(connection_id);
- if (it != browser_targets_.end()) {
- it->second->HandleMessage(data);
- return;
- }
-
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -378,13 +477,6 @@ void DevToolsHttpHandlerImpl::OnWebSocketMessage(
}
void DevToolsHttpHandlerImpl::OnClose(int connection_id) {
- BrowserTargets::iterator it = browser_targets_.find(connection_id);
- if (it != browser_targets_.end()) {
- it->second->Detach();
- browser_targets_.erase(it);
- return;
- }
-
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -476,9 +568,16 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
if (command == "list") {
std::string host = info.headers["host"];
AddRef(); // Balanced in OnTargetListReceived.
- delegate_->EnumerateTargets(
- base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceived,
- this, connection_id, host));
+ DevToolsManagerDelegate* manager_delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (manager_delegate) {
+ manager_delegate->EnumerateTargets(
+ base::Bind(&DevToolsHttpHandlerImpl::OnTargetListReceived,
+ this, connection_id, host));
+ } else {
+ DevToolsManagerDelegate::TargetList empty_list;
+ OnTargetListReceived(connection_id, host, empty_list);
+ }
return;
}
@@ -487,7 +586,11 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
query, net::UnescapeRule::URL_SPECIAL_CHARS));
if (!url.is_valid())
url = GURL(url::kAboutBlankURL);
- scoped_ptr<DevToolsTarget> target(delegate_->CreateNewTarget(url));
+ scoped_ptr<DevToolsTarget> target;
+ DevToolsManagerDelegate* manager_delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (manager_delegate)
+ target = manager_delegate->CreateNewTarget(url);
if (!target) {
SendJson(connection_id,
net::HTTP_INTERNAL_SERVER_ERROR,
@@ -548,13 +651,13 @@ void DevToolsHttpHandlerImpl::OnJsonRequestUI(
void DevToolsHttpHandlerImpl::OnTargetListReceived(
int connection_id,
const std::string& host,
- const DevToolsHttpHandlerDelegate::TargetList& targets) {
- DevToolsHttpHandlerDelegate::TargetList sorted_targets = targets;
+ const DevToolsManagerDelegate::TargetList& targets) {
+ DevToolsManagerDelegate::TargetList sorted_targets = targets;
std::sort(sorted_targets.begin(), sorted_targets.end(), TimeComparator);
STLDeleteValues(&target_map_);
base::ListValue list_value;
- for (DevToolsHttpHandlerDelegate::TargetList::const_iterator it =
+ for (DevToolsManagerDelegate::TargetList::const_iterator it =
sorted_targets.begin(); it != sorted_targets.end(); ++it) {
DevToolsTarget* target = *it;
target_map_[target->GetId()] = target;
@@ -573,7 +676,10 @@ DevToolsTarget* DevToolsHttpHandlerImpl::GetTarget(const std::string& id) {
void DevToolsHttpHandlerImpl::OnThumbnailRequestUI(
int connection_id, const GURL& page_url) {
- std::string data = delegate_->GetPageThumbnailData(page_url);
+ DevToolsManagerDelegate* manager_delegate =
+ DevToolsManager::GetInstance()->delegate();
+ std::string data =
+ manager_delegate ? manager_delegate->GetPageThumbnailData(page_url) : "";
if (!data.empty())
Send200(connection_id, data, "image/png");
else
@@ -591,6 +697,20 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
if (!thread_)
return;
+ std::string browser_prefix = "/devtools/browser";
+ size_t browser_pos = request.path.find(browser_prefix);
+ if (browser_pos == 0) {
+ BrowserTarget* browser_target = new BrowserTarget(
+ thread_->message_loop(), server_.get(), connection_id);
+ browser_target->RegisterHandler(
+ new TetheringHandler(delegate_.get(), thread_->message_loop_proxy()));
+ browser_target->RegisterHandler(
+ new DevToolsSystemInfoHandler());
+ browser_targets_[connection_id] = browser_target;
+ AcceptWebSocket(connection_id, request);
+ return;
+ }
+
size_t pos = request.path.find(kPageUrlPrefix);
if (pos != 0) {
Send404(connection_id);
@@ -601,7 +721,7 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
DevToolsTarget* target = GetTarget(page_id);
scoped_refptr<DevToolsAgentHost> agent =
target ? target->GetAgentHost() : NULL;
- if (!agent) {
+ if (!agent.get()) {
Send500(connection_id, "No such target id: " + page_id);
return;
}
@@ -612,12 +732,9 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
return;
}
- DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl(
- thread_->message_loop(), server_.get(), connection_id);
- connection_to_client_host_ui_[connection_id] = client_host;
-
- DevToolsManager::GetInstance()->
- RegisterDevToolsClientHostFor(agent, client_host);
+ DevToolsAgentHostClientImpl* client_host = new DevToolsAgentHostClientImpl(
+ thread_->message_loop(), server_.get(), connection_id, agent.get());
+ connection_to_client_ui_[connection_id] = client_host;
AcceptWebSocket(connection_id, request);
}
@@ -625,38 +742,56 @@ void DevToolsHttpHandlerImpl::OnWebSocketRequestUI(
void DevToolsHttpHandlerImpl::OnWebSocketMessageUI(
int connection_id,
const std::string& data) {
- ConnectionToClientHostMap::iterator it =
- connection_to_client_host_ui_.find(connection_id);
- if (it == connection_to_client_host_ui_.end())
+ BrowserTargets::iterator browser_it = browser_targets_.find(connection_id);
+ if (browser_it != browser_targets_.end()) {
+ browser_it->second->HandleMessage(data);
+ return;
+ }
+
+ ConnectionToClientMap::iterator it =
+ connection_to_client_ui_.find(connection_id);
+ if (it == connection_to_client_ui_.end())
return;
- DevToolsManager* manager = DevToolsManager::GetInstance();
- manager->DispatchOnInspectorBackend(it->second, data);
+ DevToolsAgentHostClientImpl* client =
+ static_cast<DevToolsAgentHostClientImpl*>(it->second);
+ client->OnMessage(data);
}
void DevToolsHttpHandlerImpl::OnCloseUI(int connection_id) {
- ConnectionToClientHostMap::iterator it =
- connection_to_client_host_ui_.find(connection_id);
- if (it != connection_to_client_host_ui_.end()) {
- DevToolsClientHostImpl* client_host =
- static_cast<DevToolsClientHostImpl*>(it->second);
- DevToolsManager::GetInstance()->ClientHostClosing(client_host);
- delete client_host;
- connection_to_client_host_ui_.erase(connection_id);
+ BrowserTargets::iterator browser_it = browser_targets_.find(connection_id);
+ if (browser_it != browser_targets_.end()) {
+ delete browser_it->second;
+ browser_targets_.erase(connection_id);
+ return;
+ }
+
+ ConnectionToClientMap::iterator it =
+ connection_to_client_ui_.find(connection_id);
+ if (it != connection_to_client_ui_.end()) {
+ DevToolsAgentHostClientImpl* client =
+ static_cast<DevToolsAgentHostClientImpl*>(it->second);
+ delete client;
+ connection_to_client_ui_.erase(connection_id);
}
}
+void DevToolsHttpHandlerImpl::OnHttpServerInitialized(
+ const net::IPEndPoint& ip_address) {
+ server_ip_address_.reset(new net::IPEndPoint(ip_address));
+}
+
DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
- const net::StreamListenSocketFactory* socket_factory,
+ scoped_ptr<ServerSocketFactory> server_socket_factory,
const std::string& frontend_url,
DevToolsHttpHandlerDelegate* delegate,
const base::FilePath& active_port_output_directory)
: frontend_url_(frontend_url),
- socket_factory_(socket_factory),
+ server_socket_factory_(server_socket_factory.Pass()),
delegate_(delegate),
active_port_output_directory_(active_port_output_directory) {
if (frontend_url_.empty())
- frontend_url_ = "/devtools/devtools.html";
+ frontend_url_ = "/devtools/devtools.html";
// Balanced in ResetHandlerThreadAndRelease().
AddRef();
@@ -664,14 +799,30 @@ DevToolsHttpHandlerImpl::DevToolsHttpHandlerImpl(
// Runs on the handler thread
void DevToolsHttpHandlerImpl::Init() {
- server_ = new net::HttpServer(*socket_factory_.get(), this);
+ scoped_ptr<net::ServerSocket> server_socket =
+ server_socket_factory_->CreateAndListen();
+ if (!server_socket) {
+ LOG(ERROR) << "Cannot start http server for devtools. Stop devtools.";
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DevToolsHttpHandlerImpl::StopWithoutRelease, this));
+ return;
+ }
+
+ server_.reset(new net::HttpServer(server_socket.Pass(), this));
+ net::IPEndPoint ip_address;
+ server_->GetLocalAddress(&ip_address);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DevToolsHttpHandlerImpl::OnHttpServerInitialized,
+ this, ip_address));
if (!active_port_output_directory_.empty())
WriteActivePortToUserProfile();
}
// Runs on the handler thread
void DevToolsHttpHandlerImpl::Teardown() {
- server_ = NULL;
+ server_.reset();
}
// Runs on FILE thread to make sure that it is serialized against
@@ -729,7 +880,7 @@ void DevToolsHttpHandlerImpl::SendJson(int connection_id,
thread_->message_loop()->PostTask(
FROM_HERE,
base::Bind(&net::HttpServer::SendResponse,
- server_.get(),
+ base::Unretained(server_.get()),
connection_id,
response));
}
@@ -742,7 +893,7 @@ void DevToolsHttpHandlerImpl::Send200(int connection_id,
thread_->message_loop()->PostTask(
FROM_HERE,
base::Bind(&net::HttpServer::Send200,
- server_.get(),
+ base::Unretained(server_.get()),
connection_id,
data,
mime_type));
@@ -753,7 +904,9 @@ void DevToolsHttpHandlerImpl::Send404(int connection_id) {
return;
thread_->message_loop()->PostTask(
FROM_HERE,
- base::Bind(&net::HttpServer::Send404, server_.get(), connection_id));
+ base::Bind(&net::HttpServer::Send404,
+ base::Unretained(server_.get()),
+ connection_id));
}
void DevToolsHttpHandlerImpl::Send500(int connection_id,
@@ -762,7 +915,9 @@ void DevToolsHttpHandlerImpl::Send500(int connection_id,
return;
thread_->message_loop()->PostTask(
FROM_HERE,
- base::Bind(&net::HttpServer::Send500, server_.get(), connection_id,
+ base::Bind(&net::HttpServer::Send500,
+ base::Unretained(server_.get()),
+ connection_id,
message));
}
@@ -773,8 +928,16 @@ void DevToolsHttpHandlerImpl::AcceptWebSocket(
return;
thread_->message_loop()->PostTask(
FROM_HERE,
- base::Bind(&net::HttpServer::AcceptWebSocket, server_.get(),
- connection_id, request));
+ base::Bind(&net::HttpServer::SetSendBufferSize,
+ base::Unretained(server_.get()),
+ connection_id,
+ kSendBufferSizeForDevTools));
+ thread_->message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&net::HttpServer::AcceptWebSocket,
+ base::Unretained(server_.get()),
+ connection_id,
+ request));
}
base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget(
@@ -799,7 +962,10 @@ base::DictionaryValue* DevToolsHttpHandlerImpl::SerializeTarget(
if (favicon_url.is_valid())
dictionary->SetString(kTargetFaviconUrlField, favicon_url.spec());
- if (!delegate_->GetPageThumbnailData(url).empty()) {
+ DevToolsManagerDelegate* manager_delegate =
+ DevToolsManager::GetInstance()->delegate();
+ if (manager_delegate &&
+ !manager_delegate->GetPageThumbnailData(url).empty()) {
dictionary->SetString(kTargetThumbnailUrlField,
std::string(kThumbUrlPrefix) + id);
}
diff --git a/chromium/content/browser/devtools/devtools_http_handler_impl.h b/chromium/content/browser/devtools/devtools_http_handler_impl.h
index 0d08d9897aa..5750dede955 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_impl.h
+++ b/chromium/content/browser/devtools/devtools_http_handler_impl.h
@@ -13,8 +13,10 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
+#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
+#include "content/public/browser/devtools_manager_delegate.h"
#include "net/http/http_status_code.h"
#include "net/server/http_server.h"
@@ -26,15 +28,12 @@ class Value;
}
namespace net {
-class StreamListenSocketFactory;
+class ServerSocketFactory;
class URLRequestContextGetter;
}
namespace content {
-class DevToolsBrowserTarget;
-class DevToolsClientHost;
-
class DevToolsHttpHandlerImpl
: public DevToolsHttpHandler,
public base::RefCountedThreadSafe<DevToolsHttpHandlerImpl>,
@@ -43,27 +42,27 @@ class DevToolsHttpHandlerImpl
friend class base::RefCountedThreadSafe<DevToolsHttpHandlerImpl>;
friend class DevToolsHttpHandler;
- // Takes ownership over |socket_factory|.
- DevToolsHttpHandlerImpl(const net::StreamListenSocketFactory* socket_factory,
+ class BrowserTarget;
+
+ DevToolsHttpHandlerImpl(scoped_ptr<ServerSocketFactory> server_socket_factory,
const std::string& frontend_url,
DevToolsHttpHandlerDelegate* delegate,
const base::FilePath& active_port_output_directory);
- virtual ~DevToolsHttpHandlerImpl();
+ ~DevToolsHttpHandlerImpl() override;
void Start();
// DevToolsHttpHandler implementation.
- virtual void Stop() OVERRIDE;
- virtual GURL GetFrontendURL() OVERRIDE;
+ void Stop() override;
+ GURL GetFrontendURL() override;
// net::HttpServer::Delegate implementation.
- virtual void OnHttpRequest(int connection_id,
- const net::HttpServerRequestInfo& info) OVERRIDE;
- virtual void OnWebSocketRequest(
- int connection_id,
- const net::HttpServerRequestInfo& info) OVERRIDE;
- virtual void OnWebSocketMessage(int connection_id,
- const std::string& data) OVERRIDE;
- virtual void OnClose(int connection_id) OVERRIDE;
+ void OnConnect(int connection_id) override {}
+ void OnHttpRequest(int connection_id,
+ const net::HttpServerRequestInfo& info) override;
+ void OnWebSocketRequest(int connection_id,
+ const net::HttpServerRequestInfo& info) override;
+ void OnWebSocketMessage(int connection_id, const std::string& data) override;
+ void OnClose(int connection_id) override;
void OnJsonRequestUI(int connection_id,
const net::HttpServerRequestInfo& info);
@@ -81,7 +80,9 @@ class DevToolsHttpHandlerImpl
void OnTargetListReceived(
int connection_id,
const std::string& host,
- const DevToolsHttpHandlerDelegate::TargetList& targets);
+ const DevToolsManagerDelegate::TargetList& targets);
+
+ void OnHttpServerInitialized(const net::IPEndPoint& ip_address);
DevToolsTarget* GetTarget(const std::string& id);
@@ -90,6 +91,7 @@ class DevToolsHttpHandlerImpl
void StartHandlerThread();
void StopHandlerThread();
+ void StopWithoutRelease();
void WriteActivePortToUserProfile();
@@ -117,15 +119,16 @@ class DevToolsHttpHandlerImpl
scoped_ptr<base::Thread> thread_;
std::string frontend_url_;
- scoped_ptr<const net::StreamListenSocketFactory> socket_factory_;
- scoped_refptr<net::HttpServer> server_;
- typedef std::map<int, DevToolsClientHost*> ConnectionToClientHostMap;
- ConnectionToClientHostMap connection_to_client_host_ui_;
- scoped_ptr<DevToolsHttpHandlerDelegate> delegate_;
- base::FilePath active_port_output_directory_;
+ const scoped_ptr<ServerSocketFactory> server_socket_factory_;
+ scoped_ptr<net::HttpServer> server_;
+ scoped_ptr<net::IPEndPoint> server_ip_address_;
+ typedef std::map<int, DevToolsAgentHostClient*> ConnectionToClientMap;
+ ConnectionToClientMap connection_to_client_ui_;
+ const scoped_ptr<DevToolsHttpHandlerDelegate> delegate_;
+ const base::FilePath active_port_output_directory_;
typedef std::map<std::string, DevToolsTarget*> TargetMap;
TargetMap target_map_;
- typedef std::map<int, scoped_refptr<DevToolsBrowserTarget> > BrowserTargets;
+ typedef std::map<int, BrowserTarget*> BrowserTargets;
BrowserTargets browser_targets_;
DISALLOW_COPY_AND_ASSIGN(DevToolsHttpHandlerImpl);
};
diff --git a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
index 88710924c2a..28630ead75a 100644
--- a/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_http_handler_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -13,7 +13,7 @@
#include "content/public/browser/devtools_target.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/socket/stream_listen_socket.h"
+#include "net/socket/server_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -23,72 +23,70 @@ const int kDummyPort = 4321;
const base::FilePath::CharType kDevToolsActivePortFileName[] =
FILE_PATH_LITERAL("DevToolsActivePort");
-using net::StreamListenSocket;
-
-class DummyListenSocket : public StreamListenSocket,
- public StreamListenSocket::Delegate {
+class DummyServerSocket : public net::ServerSocket {
public:
- DummyListenSocket()
- : StreamListenSocket(net::kInvalidSocket, this) {}
-
- // StreamListenSocket::Delegate "implementation"
- virtual void DidAccept(StreamListenSocket* server,
- scoped_ptr<StreamListenSocket> connection) OVERRIDE {}
- virtual void DidRead(StreamListenSocket* connection,
- const char* data,
- int len) OVERRIDE {}
- virtual void DidClose(StreamListenSocket* sock) OVERRIDE {}
- protected:
- virtual ~DummyListenSocket() {}
- virtual void Accept() OVERRIDE {}
- virtual int GetLocalAddress(net::IPEndPoint* address) OVERRIDE {
+ DummyServerSocket() {}
+
+ // net::ServerSocket "implementation"
+ int Listen(const net::IPEndPoint& address, int backlog) override {
+ return net::OK;
+ }
+
+ int ListenWithAddressAndPort(const std::string& ip_address,
+ int port,
+ int backlog) override {
+ return net::OK;
+ }
+
+ int GetLocalAddress(net::IPEndPoint* address) const override {
net::IPAddressNumber number;
EXPECT_TRUE(net::ParseIPLiteralToNumber("127.0.0.1", &number));
*address = net::IPEndPoint(number, kDummyPort);
return net::OK;
}
+
+ int Accept(scoped_ptr<net::StreamSocket>* socket,
+ const net::CompletionCallback& callback) override {
+ return net::ERR_IO_PENDING;
+ }
};
-class DummyListenSocketFactory : public net::StreamListenSocketFactory {
+class DummyServerSocketFactory
+ : public DevToolsHttpHandler::ServerSocketFactory {
public:
- DummyListenSocketFactory(
- base::Closure quit_closure_1, base::Closure quit_closure_2)
- : quit_closure_1_(quit_closure_1), quit_closure_2_(quit_closure_2) {}
- virtual ~DummyListenSocketFactory() {
+ DummyServerSocketFactory(base::Closure quit_closure_1,
+ base::Closure quit_closure_2)
+ : DevToolsHttpHandler::ServerSocketFactory("", 0, 0),
+ quit_closure_1_(quit_closure_1),
+ quit_closure_2_(quit_closure_2) {}
+
+ ~DummyServerSocketFactory() override {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, quit_closure_2_);
}
- virtual scoped_ptr<StreamListenSocket> CreateAndListen(
- StreamListenSocket::Delegate* delegate) const OVERRIDE {
+ private:
+ scoped_ptr<net::ServerSocket> Create() const override {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, quit_closure_1_);
- return scoped_ptr<net::StreamListenSocket>(new DummyListenSocket());
+ return scoped_ptr<net::ServerSocket>(new DummyServerSocket());
}
- private:
+
base::Closure quit_closure_1_;
base::Closure quit_closure_2_;
};
class DummyDelegate : public DevToolsHttpHandlerDelegate {
public:
- virtual std::string GetDiscoveryPageHTML() OVERRIDE { return std::string(); }
- virtual bool BundlesFrontendResources() OVERRIDE { return true; }
- virtual base::FilePath GetDebugFrontendDir() OVERRIDE {
- return base::FilePath();
- }
- virtual std::string GetPageThumbnailData(const GURL& url) OVERRIDE {
- return std::string();
- }
- virtual scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) OVERRIDE {
- return scoped_ptr<DevToolsTarget>();
- }
- virtual void EnumerateTargets(TargetCallback callback) OVERRIDE {
- callback.Run(TargetList());
- }
- virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
- net::StreamListenSocket::Delegate* delegate,
- std::string* name) OVERRIDE {
+ std::string GetDiscoveryPageHTML() override { return std::string(); }
+
+ bool BundlesFrontendResources() override { return true; }
+
+ base::FilePath GetDebugFrontendDir() override { return base::FilePath(); }
+
+ scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
+ net::StreamListenSocket::Delegate* delegate,
+ std::string* name) override {
return scoped_ptr<net::StreamListenSocket>();
}
};
@@ -100,14 +98,15 @@ class DevToolsHttpHandlerTest : public testing::Test {
DevToolsHttpHandlerTest()
: ui_thread_(BrowserThread::UI, &message_loop_) {
}
+
protected:
- virtual void SetUp() {
+ void SetUp() override {
file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE));
file_thread_->Start();
}
- virtual void TearDown() {
- file_thread_->Stop();
- }
+
+ void TearDown() override { file_thread_->Stop(); }
+
private:
base::MessageLoopForIO message_loop_;
BrowserThreadImpl ui_thread_;
@@ -116,13 +115,14 @@ class DevToolsHttpHandlerTest : public testing::Test {
TEST_F(DevToolsHttpHandlerTest, TestStartStop) {
base::RunLoop run_loop, run_loop_2;
+ scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> factory(
+ new DummyServerSocketFactory(run_loop.QuitClosure(),
+ run_loop_2.QuitClosure()));
content::DevToolsHttpHandler* devtools_http_handler_ =
- content::DevToolsHttpHandler::Start(
- new DummyListenSocketFactory(run_loop.QuitClosure(),
- run_loop_2.QuitClosure()),
- std::string(),
- new DummyDelegate(),
- base::FilePath());
+ content::DevToolsHttpHandler::Start(factory.Pass(),
+ std::string(),
+ new DummyDelegate(),
+ base::FilePath());
// Our dummy socket factory will post a quit message once the server will
// become ready.
run_loop.Run();
@@ -135,13 +135,14 @@ TEST_F(DevToolsHttpHandlerTest, TestDevToolsActivePort) {
base::RunLoop run_loop, run_loop_2;
base::ScopedTempDir temp_dir;
EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
+ scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> factory(
+ new DummyServerSocketFactory(run_loop.QuitClosure(),
+ run_loop_2.QuitClosure()));
content::DevToolsHttpHandler* devtools_http_handler_ =
- content::DevToolsHttpHandler::Start(
- new DummyListenSocketFactory(run_loop.QuitClosure(),
- run_loop_2.QuitClosure()),
- std::string(),
- new DummyDelegate(),
- temp_dir.path());
+ content::DevToolsHttpHandler::Start(factory.Pass(),
+ std::string(),
+ new DummyDelegate(),
+ temp_dir.path());
// Our dummy socket factory will post a quit message once the server will
// become ready.
run_loop.Run();
diff --git a/chromium/content/browser/devtools/devtools_manager.cc b/chromium/content/browser/devtools/devtools_manager.cc
new file mode 100644
index 00000000000..f405185a24d
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_manager.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2012 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 "content/browser/devtools/devtools_manager.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/devtools_netlog_observer.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/devtools_target.h"
+
+namespace content {
+
+namespace {
+
+int kObserverThrottleInterval = 500; // ms
+
+} // namespace
+
+// static
+DevToolsManager* DevToolsManager::GetInstance() {
+ return Singleton<DevToolsManager>::get();
+}
+
+DevToolsManager::DevToolsManager()
+ : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()),
+ update_target_list_required_(false),
+ update_target_list_scheduled_(false),
+ update_target_list_callback_(base::Bind(
+ &DevToolsManager::UpdateTargetListThrottled,
+ base::Unretained(this))) {
+}
+
+DevToolsManager::~DevToolsManager() {
+ DCHECK(!attached_hosts_.size());
+ update_target_list_callback_.Cancel();
+}
+
+void DevToolsManager::RenderViewCreated(
+ WebContents* web_contents, RenderViewHost* rvh) {
+ if (observer_list_.might_have_observers()) {
+ // Force agent host creation.
+ DevToolsAgentHost::GetOrCreateFor(web_contents);
+ }
+}
+
+void DevToolsManager::AgentHostChanged(
+ scoped_refptr<DevToolsAgentHost> agent_host) {
+ bool was_attached =
+ attached_hosts_.find(agent_host.get()) != attached_hosts_.end();
+ if (agent_host->IsAttached() && !was_attached) {
+ if (!attached_hosts_.size()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&DevToolsNetLogObserver::Attach));
+ }
+ attached_hosts_.insert(agent_host.get());
+ } else if (!agent_host->IsAttached() && was_attached) {
+ attached_hosts_.erase(agent_host.get());
+ if (!attached_hosts_.size()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&DevToolsNetLogObserver::Detach));
+ }
+ }
+
+ UpdateTargetList();
+}
+
+void DevToolsManager::AddObserver(Observer* observer) {
+ observer_list_.AddObserver(observer);
+ UpdateTargetList();
+}
+
+void DevToolsManager::RemoveObserver(Observer* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+void DevToolsManager::UpdateTargetList() {
+ if (!observer_list_.might_have_observers())
+ return;
+
+ update_target_list_required_ = true;
+ if (!update_target_list_scheduled_)
+ UpdateTargetListThrottled();
+}
+
+void DevToolsManager::UpdateTargetListThrottled() {
+ if (!update_target_list_required_) {
+ update_target_list_scheduled_ = false;
+ return;
+ }
+
+ update_target_list_scheduled_ = true;
+ if (scheduler_.is_null()) {
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ update_target_list_callback_.callback(),
+ base::TimeDelta::FromMilliseconds(kObserverThrottleInterval));
+ } else {
+ scheduler_.Run(update_target_list_callback_.callback());
+ }
+
+ update_target_list_required_ = false;
+ if (!delegate_) {
+ Observer::TargetList empty_list;
+ NotifyTargetListChanged(empty_list);
+ return;
+ }
+ delegate_->EnumerateTargets(base::Bind(
+ &DevToolsManager::NotifyTargetListChanged,
+ base::Unretained(this)));
+}
+
+void DevToolsManager::NotifyTargetListChanged(
+ const Observer::TargetList& targets) {
+ FOR_EACH_OBSERVER(Observer, observer_list_, TargetListChanged(targets));
+ STLDeleteContainerPointers(targets.begin(), targets.end());
+}
+
+void DevToolsManager::SetSchedulerForTest(Scheduler scheduler) {
+ scheduler_ = scheduler;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_manager.h b/chromium/content/browser/devtools/devtools_manager.h
new file mode 100644
index 00000000000..979424f1c66
--- /dev/null
+++ b/chromium/content/browser/devtools/devtools_manager.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_H_
+#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/cancelable_callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/singleton.h"
+#include "base/observer_list.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/devtools_manager_delegate.h"
+
+namespace content {
+
+class DevToolsAgentHost;
+class RenderViewHost;
+class WebContents;
+
+// This class is a singleton that manage global DevTools state for the whole
+// browser.
+class CONTENT_EXPORT DevToolsManager {
+ public:
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ typedef DevToolsManagerDelegate::TargetList TargetList;
+
+ // Called when any target information changed. Targets in the list are
+ // owned by DevToolsManager, so they should not be accessed outside of
+ // this method.
+ virtual void TargetListChanged(const TargetList& targets) {}
+ };
+
+ // Returns single instance of this class. The instance is destroyed on the
+ // browser main loop exit so this method MUST NOT be called after that point.
+ static DevToolsManager* GetInstance();
+
+ DevToolsManager();
+ virtual ~DevToolsManager();
+
+ DevToolsManagerDelegate* delegate() const { return delegate_.get(); }
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ void RenderViewCreated(WebContents* web_contents, RenderViewHost* rvh);
+ void AgentHostChanged(scoped_refptr<DevToolsAgentHost> agent_host);
+
+ typedef base::Callback<void(base::Closure)> Scheduler;
+ void SetSchedulerForTest(Scheduler scheduler);
+
+ private:
+ friend struct DefaultSingletonTraits<DevToolsManager>;
+
+ void UpdateTargetList();
+ void UpdateTargetListThrottled();
+ void NotifyTargetListChanged(const Observer::TargetList& targets);
+
+ scoped_ptr<DevToolsManagerDelegate> delegate_;
+ ObserverList<Observer> observer_list_;
+ std::set<DevToolsAgentHost*> attached_hosts_;
+ bool update_target_list_required_;
+ bool update_target_list_scheduled_;
+ base::CancelableClosure update_target_list_callback_;
+ Scheduler scheduler_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_H_
diff --git a/chromium/content/browser/devtools/devtools_manager_impl.cc b/chromium/content/browser/devtools/devtools_manager_impl.cc
deleted file mode 100644
index 3aafd1c2e2e..00000000000
--- a/chromium/content/browser/devtools/devtools_manager_impl.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/devtools/devtools_manager_impl.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "content/browser/devtools/devtools_netlog_observer.h"
-#include "content/browser/devtools/render_view_devtools_agent_host.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/devtools_client_host.h"
-#include "content/public/browser/devtools_manager_delegate.h"
-
-namespace content {
-
-// static
-DevToolsManager* DevToolsManager::GetInstance() {
- return DevToolsManagerImpl::GetInstance();
-}
-
-// static
-DevToolsManagerImpl* DevToolsManagerImpl::GetInstance() {
- return Singleton<DevToolsManagerImpl>::get();
-}
-
-DevToolsManagerImpl::DevToolsManagerImpl()
- : delegate_(GetContentClient()->browser()->GetDevToolsManagerDelegate()) {
-}
-
-DevToolsManagerImpl::~DevToolsManagerImpl() {
- DCHECK(agent_to_client_host_.empty());
- DCHECK(client_to_agent_host_.empty());
-}
-
-void DevToolsManagerImpl::Inspect(BrowserContext* browser_context,
- DevToolsAgentHost* agent_host) {
- if (delegate_)
- delegate_->Inspect(browser_context, agent_host);
-}
-
-DevToolsClientHost* DevToolsManagerImpl::GetDevToolsClientHostFor(
- DevToolsAgentHostImpl* agent_host_impl) {
- AgentToClientHostMap::iterator it =
- agent_to_client_host_.find(agent_host_impl);
- if (it != agent_to_client_host_.end())
- return it->second;
- return NULL;
-}
-
-DevToolsAgentHost* DevToolsManagerImpl::GetDevToolsAgentHostFor(
- DevToolsClientHost* client_host) {
- ClientToAgentHostMap::iterator it = client_to_agent_host_.find(client_host);
- if (it != client_to_agent_host_.end())
- return it->second.get();
- return NULL;
-}
-
-void DevToolsManagerImpl::RegisterDevToolsClientHostFor(
- DevToolsAgentHost* agent_host,
- DevToolsClientHost* client_host) {
- DevToolsAgentHostImpl* agent_host_impl =
- static_cast<DevToolsAgentHostImpl*>(agent_host);
- DevToolsClientHost* old_client_host =
- GetDevToolsClientHostFor(agent_host_impl);
- if (old_client_host) {
- old_client_host->ReplacedWithAnotherClient();
- UnregisterDevToolsClientHostFor(agent_host_impl);
- }
- BindClientHost(agent_host_impl, client_host);
- agent_host_impl->Attach();
-}
-
-bool DevToolsManagerImpl::DispatchOnInspectorBackend(
- DevToolsClientHost* from,
- const std::string& message) {
- DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(from);
- if (!agent_host)
- return false;
- DevToolsAgentHostImpl* agent_host_impl =
- static_cast<DevToolsAgentHostImpl*>(agent_host);
- agent_host_impl->DispatchOnInspectorBackend(message);
- return true;
-}
-
-void DevToolsManagerImpl::DispatchOnInspectorFrontend(
- DevToolsAgentHost* agent_host,
- const std::string& message) {
- DevToolsAgentHostImpl* agent_host_impl =
- static_cast<DevToolsAgentHostImpl*>(agent_host);
- DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
- if (!client_host) {
- // Client window was closed while there were messages
- // being sent to it.
- return;
- }
- client_host->DispatchOnInspectorFrontend(message);
-}
-
-void DevToolsManagerImpl::ClientHostClosing(DevToolsClientHost* client_host) {
- DevToolsAgentHost* agent_host = GetDevToolsAgentHostFor(client_host);
- if (!agent_host)
- return;
- DevToolsAgentHostImpl* agent_host_impl =
- static_cast<DevToolsAgentHostImpl*>(agent_host);
- UnbindClientHost(agent_host_impl, client_host);
-}
-
-void DevToolsManagerImpl::AgentHostClosing(DevToolsAgentHostImpl* agent_host) {
- UnregisterDevToolsClientHostFor(agent_host);
-}
-
-void DevToolsManagerImpl::UnregisterDevToolsClientHostFor(
- DevToolsAgentHostImpl* agent_host_impl) {
- DevToolsClientHost* client_host = GetDevToolsClientHostFor(agent_host_impl);
- if (!client_host)
- return;
- UnbindClientHost(agent_host_impl, client_host);
- client_host->InspectedContentsClosing();
-}
-
-void DevToolsManagerImpl::BindClientHost(
- DevToolsAgentHostImpl* agent_host,
- DevToolsClientHost* client_host) {
- DCHECK(agent_to_client_host_.find(agent_host) ==
- agent_to_client_host_.end());
- DCHECK(client_to_agent_host_.find(client_host) ==
- client_to_agent_host_.end());
-
- if (client_to_agent_host_.empty()) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&DevToolsNetLogObserver::Attach));
- }
- agent_to_client_host_[agent_host] = client_host;
- client_to_agent_host_[client_host] = agent_host;
- agent_host->set_close_listener(this);
-}
-
-void DevToolsManagerImpl::UnbindClientHost(DevToolsAgentHostImpl* agent_host,
- DevToolsClientHost* client_host) {
- DCHECK(agent_host);
- scoped_refptr<DevToolsAgentHostImpl> protect(agent_host);
- DCHECK(agent_to_client_host_.find(agent_host)->second ==
- client_host);
- DCHECK(client_to_agent_host_.find(client_host)->second.get() == agent_host);
- agent_host->set_close_listener(NULL);
-
- agent_to_client_host_.erase(agent_host);
- client_to_agent_host_.erase(client_host);
-
- if (client_to_agent_host_.empty()) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&DevToolsNetLogObserver::Detach));
- }
- // Lazy agent hosts can be deleted from within detach.
- // Do not access agent_host below this line.
- agent_host->Detach();
-}
-
-void DevToolsManagerImpl::CloseAllClientHosts() {
- std::vector<DevToolsAgentHostImpl*> agents;
- for (AgentToClientHostMap::iterator it =
- agent_to_client_host_.begin();
- it != agent_to_client_host_.end(); ++it) {
- agents.push_back(it->first);
- }
- for (std::vector<DevToolsAgentHostImpl*>::iterator it = agents.begin();
- it != agents.end(); ++it) {
- UnregisterDevToolsClientHostFor(*it);
- }
-}
-
-void DevToolsManagerImpl::AddAgentStateCallback(const Callback& callback) {
- callbacks_.push_back(&callback);
-}
-
-void DevToolsManagerImpl::RemoveAgentStateCallback(const Callback& callback) {
- CallbackContainer::iterator it =
- std::find(callbacks_.begin(), callbacks_.end(), &callback);
- DCHECK(it != callbacks_.end());
- callbacks_.erase(it);
-}
-
-void DevToolsManagerImpl::NotifyObservers(DevToolsAgentHost* agent_host,
- bool attached) {
- CallbackContainer copy(callbacks_);
- if (delegate_)
- delegate_->DevToolsAgentStateChanged(agent_host, attached);
- for (CallbackContainer::iterator it = copy.begin(); it != copy.end(); ++it)
- (*it)->Run(agent_host, attached);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_manager_impl.h b/chromium/content/browser/devtools/devtools_manager_impl.h
deleted file mode 100644
index 19b6918518b..00000000000
--- a/chromium/content/browser/devtools/devtools_manager_impl.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_IMPL_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_IMPL_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/memory/singleton.h"
-#include "content/browser/devtools/devtools_agent_host_impl.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/devtools_client_host.h"
-#include "content/public/browser/devtools_manager.h"
-
-class GURL;
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-
-class BrowserContext;
-class DevToolsManagerDelegate;
-class RenderViewHost;
-
-// This class is a singleton that manages DevToolsClientHost instances and
-// routes messages between developer tools clients and agents.
-//
-// Methods below that accept inspected RenderViewHost as a parameter are
-// just convenience methods that call corresponding methods accepting
-// DevToolAgentHost.
-class CONTENT_EXPORT DevToolsManagerImpl
- : public DevToolsAgentHostImpl::CloseListener,
- public DevToolsManager {
- public:
- // Returns single instance of this class. The instance is destroyed on the
- // browser main loop exit so this method MUST NOT be called after that point.
- static DevToolsManagerImpl* GetInstance();
-
- DevToolsManagerImpl();
- virtual ~DevToolsManagerImpl();
-
- // Opens the inspector for |agent_host|.
- void Inspect(BrowserContext* browser_context, DevToolsAgentHost* agent_host);
-
- void DispatchOnInspectorFrontend(DevToolsAgentHost* agent_host,
- const std::string& message);
-
- DevToolsManagerDelegate* delegate() const { return delegate_.get(); }
-
- // DevToolsManager implementation
- virtual bool DispatchOnInspectorBackend(DevToolsClientHost* from,
- const std::string& message) OVERRIDE;
- virtual void CloseAllClientHosts() OVERRIDE;
- virtual DevToolsAgentHost* GetDevToolsAgentHostFor(
- DevToolsClientHost* client_host) OVERRIDE;
- virtual void RegisterDevToolsClientHostFor(
- DevToolsAgentHost* agent_host,
- DevToolsClientHost* client_host) OVERRIDE;
- virtual void ClientHostClosing(DevToolsClientHost* host) OVERRIDE;
- virtual void AddAgentStateCallback(const Callback& callback) OVERRIDE;
- virtual void RemoveAgentStateCallback(const Callback& callback) OVERRIDE;
-
- private:
- friend class DevToolsAgentHostImpl;
- friend class RenderViewDevToolsAgentHost;
- friend struct DefaultSingletonTraits<DevToolsManagerImpl>;
-
- // DevToolsAgentHost::CloseListener implementation.
- virtual void AgentHostClosing(DevToolsAgentHostImpl* host) OVERRIDE;
-
- void BindClientHost(DevToolsAgentHostImpl* agent_host,
- DevToolsClientHost* client_host);
- void UnbindClientHost(DevToolsAgentHostImpl* agent_host,
- DevToolsClientHost* client_host);
-
- DevToolsClientHost* GetDevToolsClientHostFor(
- DevToolsAgentHostImpl* agent_host);
-
- void UnregisterDevToolsClientHostFor(DevToolsAgentHostImpl* agent_host);
-
- void NotifyObservers(DevToolsAgentHost* agent_host, bool attached);
-
- // These two maps are for tracking dependencies between inspected contents and
- // their DevToolsClientHosts. They are useful for routing devtools messages
- // and allow us to have at most one devtools client host per contents.
- //
- // DevToolsManagerImpl starts listening to DevToolsClientHosts when they are
- // put into these maps and removes them when they are closing.
- typedef std::map<DevToolsAgentHostImpl*, DevToolsClientHost*>
- AgentToClientHostMap;
- AgentToClientHostMap agent_to_client_host_;
-
- typedef std::map<DevToolsClientHost*, scoped_refptr<DevToolsAgentHostImpl> >
- ClientToAgentHostMap;
- ClientToAgentHostMap client_to_agent_host_;
-
- typedef std::vector<const Callback*> CallbackContainer;
- CallbackContainer callbacks_;
-
- scoped_ptr<DevToolsManagerDelegate> delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(DevToolsManagerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_MANAGER_IMPL_H_
diff --git a/chromium/content/browser/devtools/devtools_manager_unittest.cc b/chromium/content/browser/devtools/devtools_manager_unittest.cc
index 75c527388b4..988ffb752fb 100644
--- a/chromium/content/browser/devtools/devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/devtools_manager_unittest.cc
@@ -5,15 +5,20 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_manager.h"
+#include "content/browser/devtools/embedded_worker_devtools_manager.h"
#include "content/browser/devtools/render_view_devtools_agent_host.h"
+#include "content/browser/shared_worker/shared_worker_instance.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_external_agent_proxy.h"
#include "content/public/browser/devtools_external_agent_proxy_delegate.h"
+#include "content/public/browser/devtools_target.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
@@ -24,35 +29,38 @@ using base::TimeDelta;
namespace content {
namespace {
-class TestDevToolsClientHost : public DevToolsClientHost {
+class TestDevToolsClientHost : public DevToolsAgentHostClient {
public:
TestDevToolsClientHost()
: last_sent_message(NULL),
closed_(false) {
}
- virtual ~TestDevToolsClientHost() {
- EXPECT_TRUE(closed_);
- }
+ ~TestDevToolsClientHost() override { EXPECT_TRUE(closed_); }
- virtual void Close(DevToolsManager* manager) {
+ void Close() {
EXPECT_FALSE(closed_);
close_counter++;
- manager->ClientHostClosing(this);
+ agent_host_->DetachClient();
closed_ = true;
}
- virtual void InspectedContentsClosing() OVERRIDE {
+
+ void AgentHostClosed(DevToolsAgentHost* agent_host, bool replaced) override {
FAIL();
}
- virtual void DispatchOnInspectorFrontend(
- const std::string& message) OVERRIDE {
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override {
last_sent_message = &message;
}
- virtual void ReplacedWithAnotherClient() OVERRIDE {
+ void InspectAgentHost(DevToolsAgentHost* agent_host) {
+ agent_host_ = agent_host;
+ agent_host_->AttachClient(this);
}
+ DevToolsAgentHost* agent_host() { return agent_host_.get(); }
+
static void ResetCounters() {
close_counter = 0;
}
@@ -63,6 +71,7 @@ class TestDevToolsClientHost : public DevToolsClientHost {
private:
bool closed_;
+ scoped_refptr<DevToolsAgentHost> agent_host_;
DISALLOW_COPY_AND_ASSIGN(TestDevToolsClientHost);
};
@@ -75,7 +84,7 @@ class TestWebContentsDelegate : public WebContentsDelegate {
TestWebContentsDelegate() : renderer_unresponsive_received_(false) {}
// Notification that the contents is hung.
- virtual void RendererUnresponsive(WebContents* source) OVERRIDE {
+ void RendererUnresponsive(WebContents* source) override {
renderer_unresponsive_received_ = true;
}
@@ -87,53 +96,143 @@ class TestWebContentsDelegate : public WebContentsDelegate {
bool renderer_unresponsive_received_;
};
+class TestTarget : public DevToolsTarget {
+ public:
+ explicit TestTarget(scoped_refptr<DevToolsAgentHost> agent_host)
+ : agent_host_(agent_host) {}
+ ~TestTarget() override {}
+
+ std::string GetId() const override { return agent_host_->GetId(); }
+ std::string GetParentId() const override { return std::string(); }
+ std::string GetType() const override { return std::string(); }
+ std::string GetTitle() const override { return agent_host_->GetTitle(); }
+ std::string GetDescription() const override { return std::string(); }
+ GURL GetURL() const override { return agent_host_->GetURL(); }
+ GURL GetFaviconURL() const override { return GURL(); }
+ base::TimeTicks GetLastActivityTime() const override {
+ return base::TimeTicks();
+ }
+ bool IsAttached() const override { return agent_host_->IsAttached(); }
+ scoped_refptr<DevToolsAgentHost> GetAgentHost() const override {
+ return agent_host_;
+ }
+ bool Activate() const override { return agent_host_->Activate(); }
+ bool Close() const override { return agent_host_->Close(); }
+
+ private:
+ scoped_refptr<DevToolsAgentHost> agent_host_;
+};
+
+class TestDevToolsManagerDelegate : public DevToolsManagerDelegate {
+ public:
+ ~TestDevToolsManagerDelegate() override {}
+
+ void Inspect(BrowserContext* browser_context,
+ DevToolsAgentHost* agent_host) override {}
+
+ void DevToolsAgentStateChanged(DevToolsAgentHost* agent_host,
+ bool attached) override {}
+
+ base::DictionaryValue* HandleCommand(
+ DevToolsAgentHost* agent_host,
+ base::DictionaryValue* command) override {
+ return NULL;
+ }
+
+ scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) override {
+ return scoped_ptr<DevToolsTarget>();
+ }
+
+ void EnumerateTargets(TargetCallback callback) override {
+ TargetList result;
+ DevToolsAgentHost::List agents = DevToolsAgentHost::GetOrCreateAll();
+ for (DevToolsAgentHost::List::iterator it = agents.begin();
+ it != agents.end(); ++it) {
+ if ((*it)->GetType() == DevToolsAgentHost::TYPE_WEB_CONTENTS)
+ result.insert(result.begin(), new TestTarget(*it));
+ else
+ result.push_back(new TestTarget(*it));
+ }
+ callback.Run(result);
+ }
+
+ std::string GetPageThumbnailData(const GURL& url) override {
+ return std::string();
+ }
+};
+
+class ContentBrowserClientWithDevTools : public TestContentBrowserClient {
+ public:
+ ~ContentBrowserClientWithDevTools() override {}
+ content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override {
+ return new TestDevToolsManagerDelegate();
+ }
+};
+
+class TestDevToolsManagerObserver : public DevToolsManager::Observer {
+ public:
+ TestDevToolsManagerObserver()
+ : updates_count_(0) {}
+ ~TestDevToolsManagerObserver() override {}
+
+ int updates_count() { return updates_count_; }
+ const std::vector<scoped_refptr<DevToolsAgentHost>> hosts() {
+ return hosts_;
+ }
+
+ void TargetListChanged(const TargetList& targets) override {
+ updates_count_++;
+ hosts_.clear();
+ for (TargetList::const_iterator it = targets.begin();
+ it != targets.end(); ++it) {
+ hosts_.push_back((*it)->GetAgentHost());
+ }
+ }
+
+ private:
+ int updates_count_;
+ std::vector<scoped_refptr<DevToolsAgentHost>> hosts_;
+};
+
} // namespace
class DevToolsManagerTest : public RenderViewHostImplTestHarness {
+ public:
+ DevToolsManagerTest()
+ : old_browser_client_(NULL) {}
+
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
TestDevToolsClientHost::ResetCounters();
+ old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
+ }
+
+ void TearDown() override {
+ SetBrowserClientForTesting(old_browser_client_);
+ RenderViewHostImplTestHarness::TearDown();
}
+
+ ContentBrowserClientWithDevTools browser_client_;
+ ContentBrowserClient* old_browser_client_;
};
TEST_F(DevToolsManagerTest, OpenAndManuallyCloseDevToolsClientHost) {
- DevToolsManager* manager = DevToolsManager::GetInstance();
-
scoped_refptr<DevToolsAgentHost> agent(
- DevToolsAgentHost::GetOrCreateFor(rvh()));
+ DevToolsAgentHost::GetOrCreateFor(web_contents()));
EXPECT_FALSE(agent->IsAttached());
TestDevToolsClientHost client_host;
- manager->RegisterDevToolsClientHostFor(agent.get(), &client_host);
+ client_host.InspectAgentHost(agent.get());
// Test that the connection is established.
EXPECT_TRUE(agent->IsAttached());
- EXPECT_EQ(agent, manager->GetDevToolsAgentHostFor(&client_host));
EXPECT_EQ(0, TestDevToolsClientHost::close_counter);
- client_host.Close(manager);
+ client_host.Close();
EXPECT_EQ(1, TestDevToolsClientHost::close_counter);
EXPECT_FALSE(agent->IsAttached());
}
-TEST_F(DevToolsManagerTest, ForwardMessageToClient) {
- DevToolsManagerImpl* manager = DevToolsManagerImpl::GetInstance();
-
- TestDevToolsClientHost client_host;
- scoped_refptr<DevToolsAgentHost> agent_host(
- DevToolsAgentHost::GetOrCreateFor(rvh()));
- manager->RegisterDevToolsClientHostFor(agent_host.get(), &client_host);
- EXPECT_EQ(0, TestDevToolsClientHost::close_counter);
-
- std::string m = "test message";
- agent_host = DevToolsAgentHost::GetOrCreateFor(rvh());
- manager->DispatchOnInspectorFrontend(agent_host.get(), m);
- EXPECT_TRUE(&m == client_host.last_sent_message);
-
- client_host.Close(manager);
- EXPECT_EQ(1, TestDevToolsClientHost::close_counter);
-}
-
TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
TestRenderViewHost* inspected_rvh = test_rvh();
inspected_rvh->set_render_view_created(true);
@@ -142,10 +241,9 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
contents()->SetDelegate(&delegate);
TestDevToolsClientHost client_host;
- scoped_refptr<DevToolsAgentHost> agent_host(
- DevToolsAgentHost::GetOrCreateFor(inspected_rvh));
- DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
- agent_host.get(), &client_host);
+ scoped_refptr<DevToolsAgentHost> agent_host(DevToolsAgentHost::GetOrCreateFor(
+ WebContents::FromRenderViewHost(inspected_rvh)));
+ client_host.InspectAgentHost(agent_host.get());
// Start with a short timeout.
inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
@@ -158,7 +256,7 @@ TEST_F(DevToolsManagerTest, NoUnresponsiveDialogInInspectedContents) {
EXPECT_FALSE(delegate.renderer_unresponsive_received());
// Now close devtools and check that the notification is delivered.
- client_host.Close(DevToolsManager::GetInstance());
+ client_host.Close();
// Start with a short timeout.
inspected_rvh->StartHangMonitorTimeout(TimeDelta::FromMilliseconds(10));
// Wait long enough for first timeout and see if it fired.
@@ -176,31 +274,32 @@ TEST_F(DevToolsManagerTest, ReattachOnCancelPendingNavigation) {
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(
+ contents()->GetMainFrame(), 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
TestDevToolsClientHost client_host;
- DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
- devtools_manager->RegisterDevToolsClientHostFor(
- DevToolsAgentHost::GetOrCreateFor(rvh()).get(), &client_host);
+ client_host.InspectAgentHost(
+ DevToolsAgentHost::GetOrCreateFor(web_contents()).get());
// Navigate to new site which should get a new RenderViewHost.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_EQ(devtools_manager->GetDevToolsAgentHostFor(&client_host),
- DevToolsAgentHost::GetOrCreateFor(pending_rvh()));
+ EXPECT_EQ(client_host.agent_host(),
+ DevToolsAgentHost::GetOrCreateFor(web_contents()).get());
// Interrupt pending navigation and navigate back to the original site.
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(rvh(), 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(
+ contents()->GetMainFrame(), 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(devtools_manager->GetDevToolsAgentHostFor(&client_host),
- DevToolsAgentHost::GetOrCreateFor(rvh()));
- client_host.Close(DevToolsManager::GetInstance());
+ EXPECT_EQ(client_host.agent_host(),
+ DevToolsAgentHost::GetOrCreateFor(web_contents()).get());
+ client_host.Close();
}
class TestExternalAgentDelegate: public DevToolsExternalAgentProxyDelegate {
@@ -216,20 +315,18 @@ class TestExternalAgentDelegate: public DevToolsExternalAgentProxyDelegate {
EXPECT_EQ(count, event_counter_[name]);
}
- virtual void Attach(DevToolsExternalAgentProxy* proxy) OVERRIDE {
+ void Attach(DevToolsExternalAgentProxy* proxy) override {
recordEvent("Attach");
};
- virtual void Detach() OVERRIDE {
- recordEvent("Detach");
- };
+ void Detach() override { recordEvent("Detach"); };
- virtual void SendMessageToBackend(const std::string& message) OVERRIDE {
+ void SendMessageToBackend(const std::string& message) override {
recordEvent(std::string("SendMessageToBackend.") + message);
};
public :
- virtual ~TestExternalAgentDelegate() {
+ ~TestExternalAgentDelegate() override {
expectEvent(1, "Attach");
expectEvent(1, "Detach");
expectEvent(0, "SendMessageToBackend.message0");
@@ -245,16 +342,119 @@ TEST_F(DevToolsManagerTest, TestExternalProxy) {
DevToolsAgentHost::Create(delegate);
EXPECT_EQ(agent_host, DevToolsAgentHost::GetForId(agent_host->GetId()));
- DevToolsManager* manager = DevToolsManager::GetInstance();
-
TestDevToolsClientHost client_host;
- manager->RegisterDevToolsClientHostFor(agent_host.get(), &client_host);
+ client_host.InspectAgentHost(agent_host.get());
+ agent_host->DispatchProtocolMessage("message1");
+ agent_host->DispatchProtocolMessage("message2");
+ agent_host->DispatchProtocolMessage("message2");
- manager->DispatchOnInspectorBackend(&client_host, "message1");
- manager->DispatchOnInspectorBackend(&client_host, "message2");
- manager->DispatchOnInspectorBackend(&client_host, "message2");
+ client_host.Close();
+}
- client_host.Close(manager);
+class TestDevToolsManagerScheduler {
+ public:
+ DevToolsManager::Scheduler callback() {
+ return base::Bind(&TestDevToolsManagerScheduler::Schedule,
+ base::Unretained(this));
+ }
+
+ void Run() {
+ ASSERT_FALSE(closure_.is_null());
+ base::Closure copy = closure_;
+ closure_.Reset();
+ copy.Run();
+ }
+
+ bool IsEmpty() {
+ return closure_.is_null();
+ }
+
+ private:
+ void Schedule(base::Closure closure) {
+ EXPECT_TRUE(closure_.is_null());
+ closure_ = closure;
+ }
+
+ base::Closure closure_;
+};
+
+TEST_F(DevToolsManagerTest, TestObserver) {
+ GURL url1("data:text/html,<body>Body1</body>");
+ GURL url2("data:text/html,<body>Body2</body>");
+ GURL url3("data:text/html,<body>Body3</body>");
+
+ TestDevToolsManagerScheduler scheduler;
+ DevToolsManager* manager = DevToolsManager::GetInstance();
+ manager->SetSchedulerForTest(scheduler.callback());
+
+ contents()->NavigateAndCommit(url1);
+ RunAllPendingInMessageLoop();
+
+ scoped_ptr<TestDevToolsManagerObserver> observer(
+ new TestDevToolsManagerObserver());
+ manager->AddObserver(observer.get());
+ // Added observer should get an update.
+ EXPECT_EQ(1, observer->updates_count());
+ ASSERT_EQ(1u, observer->hosts().size());
+ EXPECT_EQ(contents(), observer->hosts()[0]->GetWebContents());
+ EXPECT_EQ(url1.spec(), observer->hosts()[0]->GetURL().spec());
+
+ contents()->NavigateAndCommit(url2);
+ RunAllPendingInMessageLoop();
+ contents()->NavigateAndCommit(url3);
+ scheduler.Run();
+ // Updates should be coalesced.
+ EXPECT_EQ(2, observer->updates_count());
+ ASSERT_EQ(1u, observer->hosts().size());
+ EXPECT_EQ(contents(), observer->hosts()[0]->GetWebContents());
+ EXPECT_EQ(url3.spec(), observer->hosts()[0]->GetURL().spec());
+
+ // Check there were no extra updates.
+ scheduler.Run();
+ EXPECT_TRUE(scheduler.IsEmpty());
+ EXPECT_EQ(2, observer->updates_count());
+
+ scoped_ptr<WorkerStoragePartition> partition(new WorkerStoragePartition(
+ browser_context()->GetRequestContext(),
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL));
+ WorkerStoragePartitionId partition_id(*partition.get());
+
+ GURL shared_worker_url("http://example.com/shared_worker.js");
+ SharedWorkerInstance shared_worker(
+ shared_worker_url,
+ base::string16(),
+ base::string16(),
+ blink::WebContentSecurityPolicyTypeReport,
+ browser_context()->GetResourceContext(),
+ partition_id);
+ EmbeddedWorkerDevToolsManager::GetInstance()->SharedWorkerCreated(
+ 1, 1, shared_worker);
+ contents()->NavigateAndCommit(url2);
+
+ EXPECT_EQ(3, observer->updates_count());
+ ASSERT_EQ(2u, observer->hosts().size());
+ EXPECT_EQ(contents(), observer->hosts()[0]->GetWebContents());
+ EXPECT_EQ(url2.spec(), observer->hosts()[0]->GetURL().spec());
+ EXPECT_EQ(DevToolsAgentHost::TYPE_SHARED_WORKER,
+ observer->hosts()[1]->GetType());
+ EXPECT_EQ(shared_worker_url.spec(), observer->hosts()[1]->GetURL().spec());
+
+ EmbeddedWorkerDevToolsManager::GetInstance()->WorkerDestroyed(1, 1);
+ scheduler.Run();
+ EXPECT_EQ(4, observer->updates_count());
+ ASSERT_EQ(1u, observer->hosts().size());
+ EXPECT_EQ(contents(), observer->hosts()[0]->GetWebContents());
+ EXPECT_EQ(url2.spec(), observer->hosts()[0]->GetURL().spec());
+
+ // Check there were no extra updates.
+ scheduler.Run();
+ EXPECT_TRUE(scheduler.IsEmpty());
+ EXPECT_EQ(4, observer->updates_count());
+
+ manager->RemoveObserver(observer.get());
+
+ EXPECT_TRUE(scheduler.IsEmpty());
+ manager->SetSchedulerForTest(DevToolsManager::Scheduler());
}
} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_netlog_observer.h b/chromium/content/browser/devtools/devtools_netlog_observer.h
index f063a3d432c..2155f06a11f 100644
--- a/chromium/content/browser/devtools/devtools_netlog_observer.h
+++ b/chromium/content/browser/devtools/devtools_netlog_observer.h
@@ -29,7 +29,7 @@ class DevToolsNetLogObserver : public net::NetLog::ThreadSafeObserver {
public:
// net::NetLog::ThreadSafeObserver implementation:
- virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE;
+ void OnAddEntry(const net::NetLog::Entry& entry) override;
void OnAddURLRequestEntry(const net::NetLog::Entry& entry);
@@ -46,7 +46,7 @@ class DevToolsNetLogObserver : public net::NetLog::ThreadSafeObserver {
static DevToolsNetLogObserver* instance_;
DevToolsNetLogObserver();
- virtual ~DevToolsNetLogObserver();
+ ~DevToolsNetLogObserver() override;
ResourceInfo* GetResourceInfo(uint32 id);
diff --git a/chromium/content/browser/devtools/devtools_power_handler.cc b/chromium/content/browser/devtools/devtools_power_handler.cc
deleted file mode 100644
index 43772b47607..00000000000
--- a/chromium/content/browser/devtools/devtools_power_handler.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2014 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 "content/browser/devtools/devtools_power_handler.h"
-
-#include "base/bind.h"
-#include "base/values.h"
-#include "content/browser/devtools/devtools_protocol_constants.h"
-#include "content/browser/power_profiler/power_profiler_service.h"
-
-namespace content {
-
-DevToolsPowerHandler::DevToolsPowerHandler() {
- RegisterCommandHandler(devtools::Power::start::kName,
- base::Bind(&DevToolsPowerHandler::OnStart,
- base::Unretained(this)));
- RegisterCommandHandler(devtools::Power::end::kName,
- base::Bind(&DevToolsPowerHandler::OnEnd,
- base::Unretained(this)));
- RegisterCommandHandler(devtools::Power::canProfilePower::kName,
- base::Bind(&DevToolsPowerHandler::OnCanProfilePower,
- base::Unretained(this)));
-}
-
-DevToolsPowerHandler::~DevToolsPowerHandler() {
- PowerProfilerService::GetInstance()->RemoveObserver(this);
-}
-
-void DevToolsPowerHandler::OnPowerEvent(const PowerEventVector& events) {
- base::DictionaryValue* params = new base::DictionaryValue();
- base::ListValue* event_list = new base::ListValue();
-
- std::vector<PowerEvent>::const_iterator iter;
- for (iter = events.begin(); iter != events.end(); ++iter) {
- base::DictionaryValue* event_body = new base::DictionaryValue();
-
- DCHECK(iter->type < PowerEvent::ID_COUNT);
- event_body->SetString("type", kPowerTypeNames[iter->type]);
- // Use internal value to be consistent with Blink's
- // monotonicallyIncreasingTime.
- event_body->SetDouble("timestamp", iter->time.ToInternalValue() /
- static_cast<double>(base::Time::kMicrosecondsPerMillisecond));
- event_body->SetDouble("value", iter->value);
- event_list->Append(event_body);
- }
-
- params->Set(devtools::Power::dataAvailable::kParamValue, event_list);
- SendNotification(devtools::Power::dataAvailable::kName, params);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-DevToolsPowerHandler::OnStart(
- scoped_refptr<DevToolsProtocol::Command> command) {
- if (PowerProfilerService::GetInstance()->IsAvailable()) {
- PowerProfilerService::GetInstance()->AddObserver(this);
- return command->SuccessResponse(NULL);
- }
-
- return command->InternalErrorResponse("Power profiler service unavailable");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-DevToolsPowerHandler::OnEnd(scoped_refptr<DevToolsProtocol::Command> command) {
- if (PowerProfilerService::GetInstance()->IsAvailable()) {
- PowerProfilerService::GetInstance()->RemoveObserver(this);
- return command->SuccessResponse(NULL);
- }
-
- return command->InternalErrorResponse("Power profiler service unavailable");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-DevToolsPowerHandler::OnCanProfilePower(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* result = new base::DictionaryValue();
- result->SetBoolean(devtools::kResult,
- PowerProfilerService::GetInstance()->IsAvailable());
-
- return command->SuccessResponse(result);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_power_handler.h b/chromium/content/browser/devtools/devtools_power_handler.h
deleted file mode 100644
index f645392a199..00000000000
--- a/chromium/content/browser/devtools/devtools_power_handler.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_POWER_HANDLER_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_POWER_HANDLER_H_
-
-#include "base/time/time.h"
-#include "content/browser/devtools/devtools_protocol.h"
-#include "content/browser/power_profiler/power_profiler_observer.h"
-
-namespace content {
-
-// This class provides power information to DevTools.
-class DevToolsPowerHandler
- : public DevToolsProtocol::Handler,
- public PowerProfilerObserver {
- public:
- DevToolsPowerHandler();
- virtual ~DevToolsPowerHandler();
-
- // PowerProfilerObserver override.
- virtual void OnPowerEvent(const PowerEventVector&) OVERRIDE;
-
- private:
- scoped_refptr<DevToolsProtocol::Response> OnStart(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> OnEnd(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> OnCanProfilePower(
- scoped_refptr<DevToolsProtocol::Command> command);
-
- DISALLOW_COPY_AND_ASSIGN(DevToolsPowerHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_POWER_HANDLER_H_
diff --git a/chromium/content/browser/devtools/devtools_protocol.cc b/chromium/content/browser/devtools/devtools_protocol.cc
index 5e127f1dcba..e3d531489d5 100644
--- a/chromium/content/browser/devtools/devtools_protocol.cc
+++ b/chromium/content/browser/devtools/devtools_protocol.cc
@@ -119,8 +119,11 @@ std::string DevToolsProtocol::Response::Serialize() {
error_object->SetInteger(kErrorCodeParam, error_code_);
if (!error_message_.empty())
error_object->SetString(kErrorMessageParam, error_message_);
- } else if (result_) {
- response.Set(kResultParam, result_->DeepCopy());
+ } else {
+ if (result_)
+ response.Set(kResultParam, result_->DeepCopy());
+ else
+ response.Set(kResultParam, new base::DictionaryValue());
}
std::string json_response;
diff --git a/chromium/content/browser/devtools/devtools_protocol.h b/chromium/content/browser/devtools/devtools_protocol.h
index cbc075b3715..50dc8a649dc 100644
--- a/chromium/content/browser/devtools/devtools_protocol.h
+++ b/chromium/content/browser/devtools/devtools_protocol.h
@@ -50,7 +50,7 @@ class DevToolsProtocol {
public:
int id() { return id_; }
- virtual std::string Serialize() OVERRIDE;
+ std::string Serialize() override;
// Creates success response. Takes ownership of |result|.
scoped_refptr<Response> SuccessResponse(base::DictionaryValue* result);
@@ -71,7 +71,7 @@ class DevToolsProtocol {
scoped_refptr<Response> AsyncResponsePromise();
protected:
- virtual ~Command();
+ ~Command() override;
private:
friend class DevToolsProtocol;
@@ -109,12 +109,12 @@ class DevToolsProtocol {
class Notification : public Message {
public:
-
- virtual std::string Serialize() OVERRIDE;
+ std::string Serialize() override;
private:
friend class DevToolsProtocol;
- virtual ~Notification();
+ friend class DevToolsProtocolClient;
+ ~Notification() override;
// Takes ownership of |params|.
Notification(const std::string& method,
diff --git a/chromium/content/browser/devtools/devtools_system_info_handler.cc b/chromium/content/browser/devtools/devtools_system_info_handler.cc
index 6e0336d2c08..15261b3e466 100644
--- a/chromium/content/browser/devtools/devtools_system_info_handler.cc
+++ b/chromium/content/browser/devtools/devtools_system_info_handler.cc
@@ -34,45 +34,43 @@ class AuxGPUInfoEnumerator : public gpu::GPUInfo::Enumerator {
: dictionary_(dictionary),
in_aux_attributes_(false) { }
- virtual void AddInt64(const char* name, int64 value) OVERRIDE {
+ void AddInt64(const char* name, int64 value) override {
if (in_aux_attributes_)
dictionary_->SetDouble(name, value);
}
- virtual void AddInt(const char* name, int value) OVERRIDE {
+ void AddInt(const char* name, int value) override {
if (in_aux_attributes_)
dictionary_->SetInteger(name, value);
}
- virtual void AddString(const char* name, const std::string& value) OVERRIDE {
+ void AddString(const char* name, const std::string& value) override {
if (in_aux_attributes_)
dictionary_->SetString(name, value);
}
- virtual void AddBool(const char* name, bool value) OVERRIDE {
+ void AddBool(const char* name, bool value) override {
if (in_aux_attributes_)
dictionary_->SetBoolean(name, value);
}
- virtual void AddTimeDeltaInSecondsF(const char* name,
- const base::TimeDelta& value) OVERRIDE {
+ void AddTimeDeltaInSecondsF(const char* name,
+ const base::TimeDelta& value) override {
if (in_aux_attributes_)
dictionary_->SetDouble(name, value.InSecondsF());
}
- virtual void BeginGPUDevice() OVERRIDE {
- }
+ void BeginGPUDevice() override {}
- virtual void EndGPUDevice() OVERRIDE {
- }
+ void EndGPUDevice() override {}
- virtual void BeginAuxAttributes() OVERRIDE {
- in_aux_attributes_ = true;
- }
+ void BeginVideoEncodeAcceleratorSupportedProfile() override {}
- virtual void EndAuxAttributes() OVERRIDE {
- in_aux_attributes_ = false;
- }
+ void EndVideoEncodeAcceleratorSupportedProfile() override {}
+
+ void BeginAuxAttributes() override { in_aux_attributes_ = true; }
+
+ void EndAuxAttributes() override { in_aux_attributes_ = false; }
private:
base::DictionaryValue* dictionary_;
diff --git a/chromium/content/browser/devtools/devtools_system_info_handler.h b/chromium/content/browser/devtools/devtools_system_info_handler.h
index afaf042b5b6..6217f7aef1c 100644
--- a/chromium/content/browser/devtools/devtools_system_info_handler.h
+++ b/chromium/content/browser/devtools/devtools_system_info_handler.h
@@ -14,7 +14,7 @@ class DevToolsSystemInfoHandler
: public DevToolsProtocol::Handler {
public:
DevToolsSystemInfoHandler();
- virtual ~DevToolsSystemInfoHandler();
+ ~DevToolsSystemInfoHandler() override;
private:
scoped_refptr<DevToolsProtocol::Response> OnGetInfo(
diff --git a/chromium/content/browser/devtools/devtools_tracing_handler.cc b/chromium/content/browser/devtools/devtools_tracing_handler.cc
deleted file mode 100644
index 7d308642212..00000000000
--- a/chromium/content/browser/devtools/devtools_tracing_handler.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/devtools/devtools_tracing_handler.h"
-
-#include <cmath>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/file_util.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/location.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "base/values.h"
-#include "content/browser/devtools/devtools_http_handler_impl.h"
-#include "content/browser/devtools/devtools_protocol_constants.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/tracing_controller.h"
-
-namespace content {
-
-namespace {
-
-const char kRecordUntilFull[] = "record-until-full";
-const char kRecordContinuously[] = "record-continuously";
-const char kEnableSampling[] = "enable-sampling";
-
-void ReadFile(
- const base::FilePath& path,
- const base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
- callback) {
- std::string trace_data;
- if (!base::ReadFileToString(path, &trace_data))
- LOG(ERROR) << "Failed to read file: " << path.value();
- base::DeleteFile(path, false);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(callback, make_scoped_refptr(
- base::RefCountedString::TakeString(&trace_data))));
-}
-
-} // namespace
-
-DevToolsTracingHandler::DevToolsTracingHandler(
- DevToolsTracingHandler::Target target)
- : weak_factory_(this), target_(target) {
- RegisterCommandHandler(devtools::Tracing::start::kName,
- base::Bind(&DevToolsTracingHandler::OnStart,
- base::Unretained(this)));
- RegisterCommandHandler(devtools::Tracing::end::kName,
- base::Bind(&DevToolsTracingHandler::OnEnd,
- base::Unretained(this)));
- RegisterCommandHandler(devtools::Tracing::getCategories::kName,
- base::Bind(&DevToolsTracingHandler::OnGetCategories,
- base::Unretained(this)));
-}
-
-DevToolsTracingHandler::~DevToolsTracingHandler() {
-}
-
-void DevToolsTracingHandler::BeginReadingRecordingResult(
- const base::FilePath& path) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&ReadFile, path,
- base::Bind(&DevToolsTracingHandler::ReadRecordingResult,
- weak_factory_.GetWeakPtr())));
-}
-
-void DevToolsTracingHandler::ReadRecordingResult(
- const scoped_refptr<base::RefCountedString>& trace_data) {
- if (trace_data->data().size()) {
- scoped_ptr<base::Value> trace_value(base::JSONReader::Read(
- trace_data->data()));
- base::DictionaryValue* dictionary = NULL;
- bool ok = trace_value->GetAsDictionary(&dictionary);
- DCHECK(ok);
- base::ListValue* list = NULL;
- ok = dictionary->GetList("traceEvents", &list);
- DCHECK(ok);
- std::string buffer;
- for (size_t i = 0; i < list->GetSize(); ++i) {
- std::string item;
- base::Value* item_value;
- list->Get(i, &item_value);
- base::JSONWriter::Write(item_value, &item);
- if (buffer.size())
- buffer.append(",");
- buffer.append(item);
- if (i % 1000 == 0) {
- OnTraceDataCollected(buffer);
- buffer.clear();
- }
- }
- if (buffer.size())
- OnTraceDataCollected(buffer);
- }
-
- SendNotification(devtools::Tracing::tracingComplete::kName, NULL);
-}
-
-void DevToolsTracingHandler::OnTraceDataCollected(
- const std::string& trace_fragment) {
- // Hand-craft protocol notification message so we can substitute JSON
- // that we already got as string as a bare object, not a quoted string.
- std::string message = base::StringPrintf(
- "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }",
- devtools::Tracing::dataCollected::kName,
- devtools::Tracing::dataCollected::kParamValue,
- trace_fragment.c_str());
- SendRawMessage(message);
-}
-
-TracingController::Options DevToolsTracingHandler::TraceOptionsFromString(
- const std::string& options) {
- std::vector<std::string> split;
- std::vector<std::string>::iterator iter;
- int ret = 0;
-
- base::SplitString(options, ',', &split);
- for (iter = split.begin(); iter != split.end(); ++iter) {
- if (*iter == kRecordUntilFull) {
- ret &= ~TracingController::RECORD_CONTINUOUSLY;
- } else if (*iter == kRecordContinuously) {
- ret |= TracingController::RECORD_CONTINUOUSLY;
- } else if (*iter == kEnableSampling) {
- ret |= TracingController::ENABLE_SAMPLING;
- }
- }
- return static_cast<TracingController::Options>(ret);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-DevToolsTracingHandler::OnStart(
- scoped_refptr<DevToolsProtocol::Command> command) {
- std::string categories;
- base::DictionaryValue* params = command->params();
- if (params)
- params->GetString(devtools::Tracing::start::kParamCategories, &categories);
-
- TracingController::Options options = TracingController::DEFAULT_OPTIONS;
- if (params && params->HasKey(devtools::Tracing::start::kParamOptions)) {
- std::string options_param;
- params->GetString(devtools::Tracing::start::kParamOptions, &options_param);
- options = TraceOptionsFromString(options_param);
- }
-
- if (params && params->HasKey(
- devtools::Tracing::start::kParamBufferUsageReportingInterval)) {
- double usage_reporting_interval = 0.0;
- params->GetDouble(
- devtools::Tracing::start::kParamBufferUsageReportingInterval,
- &usage_reporting_interval);
- if (usage_reporting_interval > 0) {
- base::TimeDelta interval = base::TimeDelta::FromMilliseconds(
- std::ceil(usage_reporting_interval));
- buffer_usage_poll_timer_.reset(new base::Timer(
- FROM_HERE,
- interval,
- base::Bind(
- base::IgnoreResult(&TracingController::GetTraceBufferPercentFull),
- base::Unretained(TracingController::GetInstance()),
- base::Bind(&DevToolsTracingHandler::OnBufferUsage,
- weak_factory_.GetWeakPtr())),
- true));
- buffer_usage_poll_timer_->Reset();
- }
- }
-
- // If inspected target is a render process Tracing.start will be handled by
- // tracing agent in the renderer.
- if (target_ == Renderer) {
- TracingController::GetInstance()->EnableRecording(
- categories, options, TracingController::EnableRecordingDoneCallback());
- return NULL;
- }
-
- TracingController::GetInstance()->EnableRecording(
- categories, options,
- base::Bind(&DevToolsTracingHandler::OnTracingStarted,
- weak_factory_.GetWeakPtr(),
- command));
-
- return command->AsyncResponsePromise();
-}
-
-void DevToolsTracingHandler::OnTracingStarted(
- scoped_refptr<DevToolsProtocol::Command> command) {
- SendAsyncResponse(command->SuccessResponse(NULL));
-}
-
-void DevToolsTracingHandler::OnBufferUsage(float usage) {
- base::DictionaryValue* params = new base::DictionaryValue();
- params->SetDouble(devtools::Tracing::bufferUsage::kParamValue, usage);
- SendNotification(devtools::Tracing::bufferUsage::kName, params);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-DevToolsTracingHandler::OnEnd(
- scoped_refptr<DevToolsProtocol::Command> command) {
- DisableRecording(
- base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
- weak_factory_.GetWeakPtr()));
- return command->SuccessResponse(NULL);
-}
-
-void DevToolsTracingHandler::DisableRecording(
- const TracingController::TracingFileResultCallback& callback) {
- buffer_usage_poll_timer_.reset();
- TracingController::GetInstance()->DisableRecording(base::FilePath(),
- callback);
-}
-
-void DevToolsTracingHandler::OnClientDetached() {
- DisableRecording();
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-DevToolsTracingHandler::OnGetCategories(
- scoped_refptr<DevToolsProtocol::Command> command) {
- TracingController::GetInstance()->GetCategories(
- base::Bind(&DevToolsTracingHandler::OnCategoriesReceived,
- weak_factory_.GetWeakPtr(),
- command));
- return command->AsyncResponsePromise();
-}
-
-void DevToolsTracingHandler::OnCategoriesReceived(
- scoped_refptr<DevToolsProtocol::Command> command,
- const std::set<std::string>& category_set) {
- base::DictionaryValue* response = new base::DictionaryValue;
- base::ListValue* category_list = new base::ListValue;
- for (std::set<std::string>::const_iterator it = category_set.begin();
- it != category_set.end(); ++it) {
- category_list->AppendString(*it);
- }
-
- response->Set(devtools::Tracing::getCategories::kResponseCategories,
- category_list);
- SendAsyncResponse(command->SuccessResponse(response));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/devtools_tracing_handler.h b/chromium/content/browser/devtools/devtools_tracing_handler.h
deleted file mode 100644
index 7c3b8e645e4..00000000000
--- a/chromium/content/browser/devtools/devtools_tracing_handler.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_
-#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_
-
-#include <set>
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "content/browser/devtools/devtools_protocol.h"
-#include "content/public/browser/tracing_controller.h"
-
-namespace base {
-class RefCountedString;
-class Timer;
-}
-
-namespace content {
-
-// This class bridges DevTools remote debugging server with the trace
-// infrastructure.
-class DevToolsTracingHandler : public DevToolsProtocol::Handler {
- public:
- enum Target { Browser, Renderer };
- explicit DevToolsTracingHandler(Target target);
- virtual ~DevToolsTracingHandler();
-
- void OnClientDetached();
-
- private:
- void BeginReadingRecordingResult(const base::FilePath& path);
- void ReadRecordingResult(const scoped_refptr<base::RefCountedString>& result);
- void OnTraceDataCollected(const std::string& trace_fragment);
- void OnTracingStarted(scoped_refptr<DevToolsProtocol::Command> command);
- void OnBufferUsage(float usage);
-
- scoped_refptr<DevToolsProtocol::Response> OnStart(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> OnEnd(
- scoped_refptr<DevToolsProtocol::Command> command);
-
- scoped_refptr<DevToolsProtocol::Response> OnGetCategories(
- scoped_refptr<DevToolsProtocol::Command> command);
- void OnCategoriesReceived(scoped_refptr<DevToolsProtocol::Command> command,
- const std::set<std::string>& category_set);
-
- TracingController::Options TraceOptionsFromString(const std::string& options);
-
- void DisableRecording(
- const TracingController::TracingFileResultCallback& callback =
- TracingController::TracingFileResultCallback());
-
- base::WeakPtrFactory<DevToolsTracingHandler> weak_factory_;
- scoped_ptr<base::Timer> buffer_usage_poll_timer_;
- Target target_;
- DISALLOW_COPY_AND_ASSIGN(DevToolsTracingHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_TRACING_HANDLER_H_
diff --git a/chromium/content/browser/devtools/embedded_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/embedded_worker_devtools_agent_host.cc
new file mode 100644
index 00000000000..dede4d93d8a
--- /dev/null
+++ b/chromium/content/browser/devtools/embedded_worker_devtools_agent_host.cc
@@ -0,0 +1,232 @@
+// Copyright 2014 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 "content/browser/devtools/embedded_worker_devtools_agent_host.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/devtools/devtools_protocol.h"
+#include "content/browser/devtools/devtools_protocol_constants.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/browser/shared_worker/shared_worker_service_impl.h"
+#include "content/common/devtools_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace content {
+
+namespace {
+
+void TerminateSharedWorkerOnIO(
+ EmbeddedWorkerDevToolsAgentHost::WorkerId worker_id) {
+ SharedWorkerServiceImpl::GetInstance()->TerminateWorker(
+ worker_id.first, worker_id.second);
+}
+
+void StatusNoOp(ServiceWorkerStatusCode status) {
+}
+
+void TerminateServiceWorkerOnIO(
+ base::WeakPtr<ServiceWorkerContextCore> context_weak,
+ int64 version_id) {
+ if (ServiceWorkerContextCore* context = context_weak.get()) {
+ if (ServiceWorkerVersion* version = context->GetLiveVersion(version_id))
+ version->StopWorker(base::Bind(&StatusNoOp));
+ }
+}
+
+}
+
+EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
+ WorkerId worker_id,
+ const SharedWorkerInstance& shared_worker)
+ : shared_worker_(new SharedWorkerInstance(shared_worker)),
+ state_(WORKER_UNINSPECTED),
+ worker_id_(worker_id) {
+ WorkerCreated();
+}
+
+EmbeddedWorkerDevToolsAgentHost::EmbeddedWorkerDevToolsAgentHost(
+ WorkerId worker_id,
+ const ServiceWorkerIdentifier& service_worker,
+ bool debug_service_worker_on_start)
+ : service_worker_(new ServiceWorkerIdentifier(service_worker)),
+ state_(WORKER_UNINSPECTED),
+ worker_id_(worker_id) {
+ if (debug_service_worker_on_start)
+ state_ = WORKER_PAUSED_FOR_DEBUG_ON_START;
+ WorkerCreated();
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::IsWorker() const {
+ return true;
+}
+
+DevToolsAgentHost::Type EmbeddedWorkerDevToolsAgentHost::GetType() {
+ return shared_worker_ ? TYPE_SHARED_WORKER : TYPE_SERVICE_WORKER;
+}
+
+std::string EmbeddedWorkerDevToolsAgentHost::GetTitle() {
+ if (shared_worker_ && shared_worker_->name().length())
+ return base::UTF16ToUTF8(shared_worker_->name());
+ if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
+ return base::StringPrintf("Worker pid:%d",
+ base::GetProcId(host->GetHandle()));
+ }
+ return "";
+}
+
+GURL EmbeddedWorkerDevToolsAgentHost::GetURL() {
+ if (shared_worker_)
+ return shared_worker_->url();
+ if (service_worker_)
+ return service_worker_->url();
+ return GURL();
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::Activate() {
+ return false;
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::Close() {
+ if (shared_worker_) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&TerminateSharedWorkerOnIO, worker_id_));
+ return true;
+ }
+ if (service_worker_) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&TerminateServiceWorkerOnIO,
+ service_worker_->context_weak(),
+ service_worker_->version_id()));
+ return true;
+ }
+ return false;
+}
+
+void EmbeddedWorkerDevToolsAgentHost::SendMessageToAgent(
+ IPC::Message* message_raw) {
+ scoped_ptr<IPC::Message> message(message_raw);
+ if (state_ != WORKER_INSPECTED)
+ return;
+ if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) {
+ message->set_routing_id(worker_id_.second);
+ host->Send(message.release());
+ }
+}
+
+void EmbeddedWorkerDevToolsAgentHost::Attach() {
+ if (state_ != WORKER_INSPECTED) {
+ state_ = WORKER_INSPECTED;
+ AttachToWorker();
+ }
+ IPCDevToolsAgentHost::Attach();
+}
+
+void EmbeddedWorkerDevToolsAgentHost::OnClientDetached() {
+ if (state_ == WORKER_INSPECTED) {
+ state_ = WORKER_UNINSPECTED;
+ DetachFromWorker();
+ } else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
+ state_ = WORKER_UNINSPECTED;
+ }
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::OnMessageReceived(
+ const IPC::Message& msg) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDevToolsAgentHost, msg)
+ IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
+ OnDispatchOnInspectorFrontend)
+ IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
+ OnSaveAgentRuntimeState)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void EmbeddedWorkerDevToolsAgentHost::WorkerReadyForInspection() {
+ if (state_ == WORKER_PAUSED_FOR_DEBUG_ON_START) {
+ RenderProcessHost* rph = RenderProcessHost::FromID(worker_id_.first);
+ Inspect(rph->GetBrowserContext());
+ } else if (state_ == WORKER_PAUSED_FOR_REATTACH) {
+ DCHECK(IsAttached());
+ state_ = WORKER_INSPECTED;
+ AttachToWorker();
+ Reattach(saved_agent_state_);
+ }
+}
+
+void EmbeddedWorkerDevToolsAgentHost::WorkerRestarted(WorkerId worker_id) {
+ DCHECK_EQ(WORKER_TERMINATED, state_);
+ state_ = IsAttached() ? WORKER_PAUSED_FOR_REATTACH : WORKER_UNINSPECTED;
+ worker_id_ = worker_id;
+ WorkerCreated();
+}
+
+void EmbeddedWorkerDevToolsAgentHost::WorkerDestroyed() {
+ DCHECK_NE(WORKER_TERMINATED, state_);
+ if (state_ == WORKER_INSPECTED) {
+ DCHECK(IsAttached());
+ // Client host is debugging this worker agent host.
+ std::string notification =
+ DevToolsProtocol::CreateNotification(
+ devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize();
+ SendMessageToClient(notification);
+ DetachFromWorker();
+ }
+ state_ = WORKER_TERMINATED;
+ Release(); // Balanced in WorkerCreated()
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::Matches(
+ const SharedWorkerInstance& other) {
+ return shared_worker_ && shared_worker_->Matches(other);
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::Matches(
+ const ServiceWorkerIdentifier& other) {
+ return service_worker_ && service_worker_->Matches(other);
+}
+
+bool EmbeddedWorkerDevToolsAgentHost::IsTerminated() {
+ return state_ == WORKER_TERMINATED;
+}
+
+EmbeddedWorkerDevToolsAgentHost::~EmbeddedWorkerDevToolsAgentHost() {
+ DCHECK_EQ(WORKER_TERMINATED, state_);
+ EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
+ worker_id_);
+}
+
+void EmbeddedWorkerDevToolsAgentHost::AttachToWorker() {
+ if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
+ host->AddRoute(worker_id_.second, this);
+}
+
+void EmbeddedWorkerDevToolsAgentHost::DetachFromWorker() {
+ if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
+ host->RemoveRoute(worker_id_.second);
+}
+
+void EmbeddedWorkerDevToolsAgentHost::WorkerCreated() {
+ AddRef(); // Balanced in WorkerDestroyed()
+}
+
+void EmbeddedWorkerDevToolsAgentHost::OnDispatchOnInspectorFrontend(
+ const std::string& message,
+ uint32 total_size) {
+ if (!IsAttached())
+ return;
+
+ ProcessChunkedMessageFromAgent(message, total_size);
+}
+
+void EmbeddedWorkerDevToolsAgentHost::OnSaveAgentRuntimeState(
+ const std::string& state) {
+ saved_agent_state_ = state;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/embedded_worker_devtools_agent_host.h b/chromium/content/browser/devtools/embedded_worker_devtools_agent_host.h
new file mode 100644
index 00000000000..cb0e45f3369
--- /dev/null
+++ b/chromium/content/browser/devtools/embedded_worker_devtools_agent_host.h
@@ -0,0 +1,84 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_AGENT_HOST_H_
+#define CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_AGENT_HOST_H_
+
+#include "content/browser/devtools/embedded_worker_devtools_manager.h"
+#include "content/browser/devtools/ipc_devtools_agent_host.h"
+#include "ipc/ipc_listener.h"
+
+namespace content {
+
+class SharedWorkerInstance;
+
+class EmbeddedWorkerDevToolsAgentHost : public IPCDevToolsAgentHost,
+ public IPC::Listener {
+ public:
+ typedef EmbeddedWorkerDevToolsManager::WorkerId WorkerId;
+ typedef EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier
+ ServiceWorkerIdentifier;
+
+ EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id,
+ const SharedWorkerInstance& shared_worker);
+
+ EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id,
+ const ServiceWorkerIdentifier& service_worker,
+ bool debug_service_worker_on_start);
+
+ // DevToolsAgentHost override.
+ bool IsWorker() const override;
+ Type GetType() override;
+ std::string GetTitle() override;
+ GURL GetURL() override;
+ bool Activate() override;
+ bool Close() override;
+
+ // IPCDevToolsAgentHost implementation.
+ void SendMessageToAgent(IPC::Message* message) override;
+ void Attach() override;
+ void OnClientAttached() override {}
+ void OnClientDetached() override;
+
+ // IPC::Listener implementation.
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
+ void WorkerReadyForInspection();
+ void WorkerRestarted(WorkerId worker_id);
+ void WorkerDestroyed();
+ bool Matches(const SharedWorkerInstance& other);
+ bool Matches(const ServiceWorkerIdentifier& other);
+ bool IsTerminated();
+
+ private:
+ friend class EmbeddedWorkerDevToolsManagerTest;
+
+ ~EmbeddedWorkerDevToolsAgentHost() override;
+
+ enum WorkerState {
+ WORKER_UNINSPECTED,
+ WORKER_INSPECTED,
+ WORKER_TERMINATED,
+ WORKER_PAUSED_FOR_DEBUG_ON_START,
+ WORKER_PAUSED_FOR_REATTACH,
+ };
+
+ void AttachToWorker();
+ void DetachFromWorker();
+ void WorkerCreated();
+ void OnDispatchOnInspectorFrontend(const std::string& message,
+ uint32 total_size);
+ void OnSaveAgentRuntimeState(const std::string& state);
+
+ scoped_ptr<SharedWorkerInstance> shared_worker_;
+ scoped_ptr<ServiceWorkerIdentifier> service_worker_;
+ WorkerState state_;
+ WorkerId worker_id_;
+ std::string saved_agent_state_;
+ DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDevToolsAgentHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_AGENT_HOST_H_
diff --git a/chromium/content/browser/devtools/embedded_worker_devtools_manager.cc b/chromium/content/browser/devtools/embedded_worker_devtools_manager.cc
index 3ba61aafeea..be0bbbf9bc2 100644
--- a/chromium/content/browser/devtools/embedded_worker_devtools_manager.cc
+++ b/chromium/content/browser/devtools/embedded_worker_devtools_manager.cc
@@ -4,9 +4,10 @@
#include "content/browser/devtools/embedded_worker_devtools_manager.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_protocol.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
+#include "content/browser/devtools/embedded_worker_devtools_agent_host.h"
#include "content/browser/devtools/ipc_devtools_agent_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/common/devtools_messages.h"
@@ -17,197 +18,75 @@
namespace content {
-namespace {
-
-bool SendMessageToWorker(
- const EmbeddedWorkerDevToolsManager::WorkerId& worker_id,
- IPC::Message* message) {
- RenderProcessHost* host = RenderProcessHost::FromID(worker_id.first);
- if (!host) {
- delete message;
- return false;
- }
- message->set_routing_id(worker_id.second);
- host->Send(message);
- return true;
+// Called on the UI thread.
+// static
+scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker(
+ int worker_process_id,
+ int worker_route_id) {
+ return EmbeddedWorkerDevToolsManager::GetInstance()
+ ->GetDevToolsAgentHostForWorker(worker_process_id, worker_route_id);
}
-} // namespace
-
EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
- const ServiceWorkerContextCore* const service_worker_context,
- int64 service_worker_version_id)
- : service_worker_context_(service_worker_context),
- service_worker_version_id_(service_worker_version_id) {
+ const ServiceWorkerContextCore* context,
+ base::WeakPtr<ServiceWorkerContextCore> context_weak,
+ int64 version_id,
+ const GURL& url)
+ : context_(context),
+ context_weak_(context_weak),
+ version_id_(version_id),
+ url_(url) {
}
EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
const ServiceWorkerIdentifier& other)
- : service_worker_context_(other.service_worker_context_),
- service_worker_version_id_(other.service_worker_version_id_) {
+ : context_(other.context_),
+ context_weak_(other.context_weak_),
+ version_id_(other.version_id_),
+ url_(other.url_) {
}
-bool EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::Matches(
- const ServiceWorkerIdentifier& other) const {
- return service_worker_context_ == other.service_worker_context_ &&
- service_worker_version_id_ == other.service_worker_version_id_;
+EmbeddedWorkerDevToolsManager::
+ServiceWorkerIdentifier::~ServiceWorkerIdentifier() {
}
-EmbeddedWorkerDevToolsManager::WorkerInfo::WorkerInfo(
- const SharedWorkerInstance& instance)
- : shared_worker_instance_(new SharedWorkerInstance(instance)),
- state_(WORKER_UNINSPECTED),
- agent_host_(NULL) {
+bool EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::Matches(
+ const ServiceWorkerIdentifier& other) const {
+ return context_ == other.context_ && version_id_ == other.version_id_;
}
-EmbeddedWorkerDevToolsManager::WorkerInfo::WorkerInfo(
- const ServiceWorkerIdentifier& service_worker_id)
- : service_worker_id_(new ServiceWorkerIdentifier(service_worker_id)),
- state_(WORKER_UNINSPECTED),
- agent_host_(NULL) {
+const ServiceWorkerContextCore*
+EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::context() const {
+ return context_;
}
-bool EmbeddedWorkerDevToolsManager::WorkerInfo::Matches(
- const SharedWorkerInstance& other) {
- if (!shared_worker_instance_)
- return false;
- return shared_worker_instance_->Matches(other);
+base::WeakPtr<ServiceWorkerContextCore>
+EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::context_weak() const {
+ return context_weak_;
}
-bool EmbeddedWorkerDevToolsManager::WorkerInfo::Matches(
- const ServiceWorkerIdentifier& other) {
- if (!service_worker_id_)
- return false;
- return service_worker_id_->Matches(other);
+int64
+EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::version_id() const {
+ return version_id_;
}
-EmbeddedWorkerDevToolsManager::WorkerInfo::~WorkerInfo() {
+GURL EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::url() const {
+ return url_;
}
-class EmbeddedWorkerDevToolsManager::EmbeddedWorkerDevToolsAgentHost
- : public IPCDevToolsAgentHost,
- public IPC::Listener {
- public:
- explicit EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id)
- : worker_id_(worker_id), worker_attached_(false) {
- AttachToWorker();
- }
-
- // DevToolsAgentHost override.
- virtual bool IsWorker() const OVERRIDE { return true; }
-
- // IPCDevToolsAgentHost implementation.
- virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE {
- if (worker_attached_)
- SendMessageToWorker(worker_id_, message);
- else
- delete message;
- }
- virtual void Attach() OVERRIDE {
- AttachToWorker();
- IPCDevToolsAgentHost::Attach();
- }
- virtual void OnClientAttached() OVERRIDE {}
- virtual void OnClientDetached() OVERRIDE { DetachFromWorker(); }
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDevToolsAgentHost, msg)
- IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
- OnDispatchOnInspectorFrontend)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
- OnSaveAgentRuntimeState)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
- }
-
- void ReattachToWorker(WorkerId worker_id) {
- CHECK(!worker_attached_);
- worker_id_ = worker_id;
- if (!IsAttached())
- return;
- AttachToWorker();
- Reattach(state_);
- }
-
- void DetachFromWorker() {
- if (!worker_attached_)
- return;
- worker_attached_ = false;
- if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
- host->RemoveRoute(worker_id_.second);
- Release();
- }
-
- WorkerId worker_id() const { return worker_id_; }
-
- private:
- virtual ~EmbeddedWorkerDevToolsAgentHost() {
- CHECK(!worker_attached_);
- EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
- this);
- }
-
- void OnDispatchOnInspectorFrontend(const std::string& message) {
- DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(this,
- message);
- }
-
- void OnSaveAgentRuntimeState(const std::string& state) { state_ = state; }
-
- void AttachToWorker() {
- if (worker_attached_)
- return;
- worker_attached_ = true;
- AddRef();
- if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
- host->AddRoute(worker_id_.second, this);
- }
-
- WorkerId worker_id_;
- bool worker_attached_;
- std::string state_;
- DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDevToolsAgentHost);
-};
-
// static
EmbeddedWorkerDevToolsManager* EmbeddedWorkerDevToolsManager::GetInstance() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return Singleton<EmbeddedWorkerDevToolsManager>::get();
}
-DevToolsAgentHost* EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
+DevToolsAgentHostImpl*
+EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
int worker_process_id,
int worker_route_id) {
- WorkerId id(worker_process_id, worker_route_id);
-
- WorkerInfoMap::iterator it = workers_.find(id);
- if (it == workers_.end())
- return NULL;
-
- WorkerInfo* info = it->second;
- if (info->state() != WORKER_UNINSPECTED &&
- info->state() != WORKER_PAUSED_FOR_DEBUG_ON_START) {
- return info->agent_host();
- }
-
- EmbeddedWorkerDevToolsAgentHost* agent_host =
- new EmbeddedWorkerDevToolsAgentHost(id);
- info->set_agent_host(agent_host);
- info->set_state(WORKER_INSPECTED);
- return agent_host;
-}
-
-DevToolsAgentHost*
-EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForServiceWorker(
- const ServiceWorkerIdentifier& service_worker_id) {
- WorkerInfoMap::iterator it = FindExistingServiceWorkerInfo(service_worker_id);
- if (it == workers_.end())
- return NULL;
- return GetDevToolsAgentHostForWorker(it->first.first, it->first.second);
+ AgentHostMap::iterator it = workers_.find(
+ WorkerId(worker_process_id, worker_route_id));
+ return it == workers_.end() ? NULL : it->second;
}
EmbeddedWorkerDevToolsManager::EmbeddedWorkerDevToolsManager()
@@ -223,13 +102,13 @@ bool EmbeddedWorkerDevToolsManager::SharedWorkerCreated(
const SharedWorkerInstance& instance) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const WorkerId id(worker_process_id, worker_route_id);
- WorkerInfoMap::iterator it = FindExistingSharedWorkerInfo(instance);
+ AgentHostMap::iterator it = FindExistingSharedWorkerAgentHost(instance);
if (it == workers_.end()) {
- scoped_ptr<WorkerInfo> info(new WorkerInfo(instance));
- workers_.set(id, info.Pass());
+ workers_[id] = new EmbeddedWorkerDevToolsAgentHost(id, instance);
+ DevToolsManager::GetInstance()->AgentHostChanged(workers_[id]);
return false;
}
- MoveToPausedState(id, it);
+ WorkerRestarted(id, it);
return true;
}
@@ -239,15 +118,15 @@ bool EmbeddedWorkerDevToolsManager::ServiceWorkerCreated(
const ServiceWorkerIdentifier& service_worker_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const WorkerId id(worker_process_id, worker_route_id);
- WorkerInfoMap::iterator it = FindExistingServiceWorkerInfo(service_worker_id);
+ AgentHostMap::iterator it =
+ FindExistingServiceWorkerAgentHost(service_worker_id);
if (it == workers_.end()) {
- scoped_ptr<WorkerInfo> info(new WorkerInfo(service_worker_id));
- if (debug_service_worker_on_start_)
- info->set_state(WORKER_PAUSED_FOR_DEBUG_ON_START);
- workers_.set(id, info.Pass());
+ workers_[id] = new EmbeddedWorkerDevToolsAgentHost(
+ id, service_worker_id, debug_service_worker_on_start_);
+ DevToolsManager::GetInstance()->AgentHostChanged(workers_[id]);
return debug_service_worker_on_start_;
}
- MoveToPausedState(id, it);
+ WorkerRestarted(id, it);
return true;
}
@@ -255,96 +134,32 @@ void EmbeddedWorkerDevToolsManager::WorkerDestroyed(int worker_process_id,
int worker_route_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const WorkerId id(worker_process_id, worker_route_id);
- WorkerInfoMap::iterator it = workers_.find(id);
+ AgentHostMap::iterator it = workers_.find(id);
DCHECK(it != workers_.end());
- WorkerInfo* info = it->second;
- switch (info->state()) {
- case WORKER_UNINSPECTED:
- case WORKER_PAUSED_FOR_DEBUG_ON_START:
- workers_.erase(it);
- break;
- case WORKER_INSPECTED: {
- EmbeddedWorkerDevToolsAgentHost* agent_host = info->agent_host();
- info->set_state(WORKER_TERMINATED);
- if (!agent_host->IsAttached()) {
- agent_host->DetachFromWorker();
- return;
- }
- // Client host is debugging this worker agent host.
- std::string notification =
- DevToolsProtocol::CreateNotification(
- devtools::Worker::disconnectedFromWorker::kName, NULL)
- ->Serialize();
- DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
- agent_host, notification);
- agent_host->DetachFromWorker();
- break;
- }
- case WORKER_TERMINATED:
- NOTREACHED();
- break;
- case WORKER_PAUSED_FOR_REATTACH: {
- scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(it);
- worker_info->set_state(WORKER_TERMINATED);
- const WorkerId old_id = worker_info->agent_host()->worker_id();
- workers_.set(old_id, worker_info.Pass());
- break;
- }
- }
+ scoped_refptr<EmbeddedWorkerDevToolsAgentHost> agent_host(it->second);
+ agent_host->WorkerDestroyed();
+ DevToolsManager::GetInstance()->AgentHostChanged(agent_host);
}
-void EmbeddedWorkerDevToolsManager::WorkerContextStarted(int worker_process_id,
- int worker_route_id) {
+void EmbeddedWorkerDevToolsManager::WorkerReadyForInspection(
+ int worker_process_id,
+ int worker_route_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
const WorkerId id(worker_process_id, worker_route_id);
- WorkerInfoMap::iterator it = workers_.find(id);
+ AgentHostMap::iterator it = workers_.find(id);
DCHECK(it != workers_.end());
- WorkerInfo* info = it->second;
- if (info->state() == WORKER_PAUSED_FOR_DEBUG_ON_START) {
- RenderProcessHost* rph = RenderProcessHost::FromID(worker_process_id);
- scoped_refptr<DevToolsAgentHost> agent_host(
- GetDevToolsAgentHostForWorker(worker_process_id, worker_route_id));
- DevToolsManagerImpl::GetInstance()->Inspect(rph->GetBrowserContext(),
- agent_host.get());
- } else if (info->state() == WORKER_PAUSED_FOR_REATTACH) {
- info->agent_host()->ReattachToWorker(id);
- info->set_state(WORKER_INSPECTED);
- }
+ it->second->WorkerReadyForInspection();
}
-void EmbeddedWorkerDevToolsManager::RemoveInspectedWorkerData(
- EmbeddedWorkerDevToolsAgentHost* agent_host) {
+void EmbeddedWorkerDevToolsManager::RemoveInspectedWorkerData(WorkerId id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- const WorkerId id(agent_host->worker_id());
- scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(id);
- if (worker_info) {
- DCHECK_EQ(worker_info->agent_host(), agent_host);
- if (worker_info->state() == WORKER_TERMINATED)
- return;
- DCHECK_EQ(worker_info->state(), WORKER_INSPECTED);
- worker_info->set_agent_host(NULL);
- worker_info->set_state(WORKER_UNINSPECTED);
- workers_.set(id, worker_info.Pass());
- return;
- }
- for (WorkerInfoMap::iterator it = workers_.begin(); it != workers_.end();
- ++it) {
- if (it->second->agent_host() == agent_host) {
- DCHECK_EQ(WORKER_PAUSED_FOR_REATTACH, it->second->state());
- SendMessageToWorker(
- it->first,
- new DevToolsAgentMsg_ResumeWorkerContext(it->first.second));
- it->second->set_agent_host(NULL);
- it->second->set_state(WORKER_UNINSPECTED);
- return;
- }
- }
+ workers_.erase(id);
}
-EmbeddedWorkerDevToolsManager::WorkerInfoMap::iterator
-EmbeddedWorkerDevToolsManager::FindExistingSharedWorkerInfo(
+EmbeddedWorkerDevToolsManager::AgentHostMap::iterator
+EmbeddedWorkerDevToolsManager::FindExistingSharedWorkerAgentHost(
const SharedWorkerInstance& instance) {
- WorkerInfoMap::iterator it = workers_.begin();
+ AgentHostMap::iterator it = workers_.begin();
for (; it != workers_.end(); ++it) {
if (it->second->Matches(instance))
break;
@@ -352,10 +167,10 @@ EmbeddedWorkerDevToolsManager::FindExistingSharedWorkerInfo(
return it;
}
-EmbeddedWorkerDevToolsManager::WorkerInfoMap::iterator
-EmbeddedWorkerDevToolsManager::FindExistingServiceWorkerInfo(
+EmbeddedWorkerDevToolsManager::AgentHostMap::iterator
+EmbeddedWorkerDevToolsManager::FindExistingServiceWorkerAgentHost(
const ServiceWorkerIdentifier& service_worker_id) {
- WorkerInfoMap::iterator it = workers_.begin();
+ AgentHostMap::iterator it = workers_.begin();
for (; it != workers_.end(); ++it) {
if (it->second->Matches(service_worker_id))
break;
@@ -363,13 +178,26 @@ EmbeddedWorkerDevToolsManager::FindExistingServiceWorkerInfo(
return it;
}
-void EmbeddedWorkerDevToolsManager::MoveToPausedState(
+DevToolsAgentHost::List
+EmbeddedWorkerDevToolsManager::GetOrCreateAllAgentHosts() {
+ DevToolsAgentHost::List result;
+ EmbeddedWorkerDevToolsManager* instance = GetInstance();
+ for (AgentHostMap::iterator it = instance->workers_.begin();
+ it != instance->workers_.end(); ++it) {
+ if (!it->second->IsTerminated())
+ result.push_back(it->second);
+ }
+ return result;
+}
+
+void EmbeddedWorkerDevToolsManager::WorkerRestarted(
const WorkerId& id,
- const WorkerInfoMap::iterator& it) {
- DCHECK_EQ(WORKER_TERMINATED, it->second->state());
- scoped_ptr<WorkerInfo> info = workers_.take_and_erase(it);
- info->set_state(WORKER_PAUSED_FOR_REATTACH);
- workers_.set(id, info.Pass());
+ const AgentHostMap::iterator& it) {
+ EmbeddedWorkerDevToolsAgentHost* agent_host = it->second;
+ agent_host->WorkerRestarted(id);
+ workers_.erase(it);
+ workers_[id] = agent_host;
+ DevToolsManager::GetInstance()->AgentHostChanged(agent_host);
}
void EmbeddedWorkerDevToolsManager::ResetForTesting() {
diff --git a/chromium/content/browser/devtools/embedded_worker_devtools_manager.h b/chromium/content/browser/devtools/embedded_worker_devtools_manager.h
index 3b15c8f2099..7103877be11 100644
--- a/chromium/content/browser/devtools/embedded_worker_devtools_manager.h
+++ b/chromium/content/browser/devtools/embedded_worker_devtools_manager.h
@@ -5,11 +5,13 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_MANAGER_H_
#define CONTENT_BROWSER_DEVTOOLS_EMBEDDED_WORKER_DEVTOOLS_MANAGER_H_
+#include <map>
+
#include "base/basictypes.h"
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/common/content_export.h"
@@ -17,6 +19,8 @@
namespace content {
class DevToolsAgentHost;
+class DevToolsAgentHostImpl;
+class EmbeddedWorkerDevToolsAgentHost;
class ServiceWorkerContextCore;
// EmbeddedWorkerDevToolsManager is used instead of WorkerDevToolsManager when
@@ -25,30 +29,38 @@ class ServiceWorkerContextCore;
class CONTENT_EXPORT EmbeddedWorkerDevToolsManager {
public:
typedef std::pair<int, int> WorkerId;
- class EmbeddedWorkerDevToolsAgentHost;
class ServiceWorkerIdentifier {
public:
ServiceWorkerIdentifier(
- const ServiceWorkerContextCore* const service_worker_context,
- int64 service_worker_version_id);
- explicit ServiceWorkerIdentifier(const ServiceWorkerIdentifier& other);
- ~ServiceWorkerIdentifier() {}
+ const ServiceWorkerContextCore* context,
+ base::WeakPtr<ServiceWorkerContextCore> context_weak,
+ int64 version_id,
+ const GURL& url);
+ ServiceWorkerIdentifier(const ServiceWorkerIdentifier& other);
+ ~ServiceWorkerIdentifier();
bool Matches(const ServiceWorkerIdentifier& other) const;
+ const ServiceWorkerContextCore* context() const;
+ base::WeakPtr<ServiceWorkerContextCore> context_weak() const;
+ int64 version_id() const;
+ GURL url() const;
+
private:
- const ServiceWorkerContextCore* const service_worker_context_;
- const int64 service_worker_version_id_;
+ const ServiceWorkerContextCore* const context_;
+ const base::WeakPtr<ServiceWorkerContextCore> context_weak_;
+ const int64 version_id_;
+ const GURL url_;
};
// Returns the EmbeddedWorkerDevToolsManager singleton.
static EmbeddedWorkerDevToolsManager* GetInstance();
- DevToolsAgentHost* GetDevToolsAgentHostForWorker(int worker_process_id,
+ DevToolsAgentHostImpl* GetDevToolsAgentHostForWorker(int worker_process_id,
int worker_route_id);
- DevToolsAgentHost* GetDevToolsAgentHostForServiceWorker(
- const ServiceWorkerIdentifier& service_worker_id);
+
+ std::vector<scoped_refptr<DevToolsAgentHost> > GetOrCreateAllAgentHosts();
// Returns true when the worker must be paused on start because a DevTool
// window for the same former SharedWorkerInstance is still opened.
@@ -61,7 +73,7 @@ class CONTENT_EXPORT EmbeddedWorkerDevToolsManager {
bool ServiceWorkerCreated(int worker_process_id,
int worker_route_id,
const ServiceWorkerIdentifier& service_worker_id);
- void WorkerContextStarted(int worker_process_id, int worker_route_id);
+ void WorkerReadyForInspection(int worker_process_id, int worker_route_id);
void WorkerDestroyed(int worker_process_id, int worker_route_id);
void set_debug_service_worker_on_start(bool debug_on_start) {
@@ -73,60 +85,29 @@ class CONTENT_EXPORT EmbeddedWorkerDevToolsManager {
private:
friend struct DefaultSingletonTraits<EmbeddedWorkerDevToolsManager>;
+ friend class EmbeddedWorkerDevToolsAgentHost;
friend class EmbeddedWorkerDevToolsManagerTest;
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerDevToolsManagerTest, BasicTest);
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerDevToolsManagerTest, AttachTest);
- enum WorkerState {
- WORKER_UNINSPECTED,
- WORKER_INSPECTED,
- WORKER_TERMINATED,
- WORKER_PAUSED_FOR_DEBUG_ON_START,
- WORKER_PAUSED_FOR_REATTACH,
- };
-
- class WorkerInfo {
- public:
- // Creates WorkerInfo for SharedWorker.
- explicit WorkerInfo(const SharedWorkerInstance& instance);
- // Creates WorkerInfo for ServiceWorker.
- explicit WorkerInfo(const ServiceWorkerIdentifier& service_worker_id);
- ~WorkerInfo();
-
- WorkerState state() { return state_; }
- void set_state(WorkerState new_state) { state_ = new_state; }
- EmbeddedWorkerDevToolsAgentHost* agent_host() { return agent_host_; }
- void set_agent_host(EmbeddedWorkerDevToolsAgentHost* agent_host) {
- agent_host_ = agent_host;
- }
- bool Matches(const SharedWorkerInstance& other);
- bool Matches(const ServiceWorkerIdentifier& other);
-
- private:
- scoped_ptr<SharedWorkerInstance> shared_worker_instance_;
- scoped_ptr<ServiceWorkerIdentifier> service_worker_id_;
- WorkerState state_;
- EmbeddedWorkerDevToolsAgentHost* agent_host_;
- };
-
- typedef base::ScopedPtrHashMap<WorkerId, WorkerInfo> WorkerInfoMap;
+ typedef std::map<WorkerId, EmbeddedWorkerDevToolsAgentHost*> AgentHostMap;
EmbeddedWorkerDevToolsManager();
virtual ~EmbeddedWorkerDevToolsManager();
- void RemoveInspectedWorkerData(EmbeddedWorkerDevToolsAgentHost* agent_host);
+ void RemoveInspectedWorkerData(WorkerId id);
- WorkerInfoMap::iterator FindExistingSharedWorkerInfo(
+ AgentHostMap::iterator FindExistingSharedWorkerAgentHost(
const SharedWorkerInstance& instance);
- WorkerInfoMap::iterator FindExistingServiceWorkerInfo(
+ AgentHostMap::iterator FindExistingServiceWorkerAgentHost(
const ServiceWorkerIdentifier& service_worker_id);
- void MoveToPausedState(const WorkerId& id, const WorkerInfoMap::iterator& it);
+ void WorkerRestarted(const WorkerId& id, const AgentHostMap::iterator& it);
// Resets to its initial state as if newly created.
void ResetForTesting();
- WorkerInfoMap workers_;
+ AgentHostMap workers_;
bool debug_service_worker_on_start_;
diff --git a/chromium/content/browser/devtools/embedded_worker_devtools_manager_unittest.cc b/chromium/content/browser/devtools/embedded_worker_devtools_manager_unittest.cc
index 69b23052425..35a0b301ac2 100644
--- a/chromium/content/browser/devtools/embedded_worker_devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/embedded_worker_devtools_manager_unittest.cc
@@ -8,33 +8,41 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
+#include "content/browser/devtools/embedded_worker_devtools_agent_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
-#include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/devtools_client_host.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
-class TestDevToolsClientHost : public DevToolsClientHost {
+class TestDevToolsClientHost : public DevToolsAgentHostClient {
public:
TestDevToolsClientHost() {}
- virtual ~TestDevToolsClientHost() {}
- virtual void DispatchOnInspectorFrontend(
- const std::string& message) OVERRIDE {}
- virtual void InspectedContentsClosing() OVERRIDE {}
- virtual void ReplacedWithAnotherClient() OVERRIDE {}
+ ~TestDevToolsClientHost() override {}
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override {}
+ void AgentHostClosed(DevToolsAgentHost* agent_host, bool replaced) override {}
+ void InspectAgentHost(DevToolsAgentHost* agent_host) {
+ if (agent_host_.get())
+ agent_host_->DetachClient();
+ agent_host_ = agent_host;
+ if (agent_host_.get())
+ agent_host_->AttachClient(this);
+ }
private:
+ scoped_refptr<DevToolsAgentHost> agent_host_;
DISALLOW_COPY_AND_ASSIGN(TestDevToolsClientHost);
};
}
class EmbeddedWorkerDevToolsManagerTest : public testing::Test {
public:
+ typedef EmbeddedWorkerDevToolsAgentHost::WorkerState WorkerState;
+
EmbeddedWorkerDevToolsManagerTest()
: ui_thread_(BrowserThread::UI, &message_loop_),
browser_context_(new TestBrowserContext()),
@@ -50,22 +58,22 @@ class EmbeddedWorkerDevToolsManagerTest : public testing::Test {
partition_id_(*partition_.get()) {}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
manager_ = EmbeddedWorkerDevToolsManager::GetInstance();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
EmbeddedWorkerDevToolsManager::GetInstance()->ResetForTesting();
}
void CheckWorkerState(int worker_process_id,
int worker_route_id,
- EmbeddedWorkerDevToolsManager::WorkerState state) {
+ WorkerState state) {
const EmbeddedWorkerDevToolsManager::WorkerId id(worker_process_id,
worker_route_id);
- EmbeddedWorkerDevToolsManager::WorkerInfoMap::iterator it =
+ EmbeddedWorkerDevToolsManager::AgentHostMap::iterator it =
manager_->workers_.find(id);
EXPECT_TRUE(manager_->workers_.end() != it);
- EXPECT_EQ(state, it->second->state());
+ EXPECT_EQ(state, it->second->state_);
}
void CheckWorkerNotExist(int worker_process_id, int worker_route_id) {
@@ -78,16 +86,6 @@ class EmbeddedWorkerDevToolsManagerTest : public testing::Test {
EXPECT_EQ(size, manager_->workers_.size());
}
- void RegisterDevToolsClientHostFor(DevToolsAgentHost* agent_host,
- DevToolsClientHost* client_host) {
- DevToolsManagerImpl::GetInstance()->RegisterDevToolsClientHostFor(
- agent_host, client_host);
- }
-
- void ClientHostClosing(DevToolsClientHost* client_host) {
- DevToolsManagerImpl::GetInstance()->ClientHostClosing(client_host);
- }
-
base::MessageLoopForIO message_loop_;
BrowserThreadImpl ui_thread_;
scoped_ptr<TestBrowserContext> browser_context_;
@@ -97,7 +95,7 @@ class EmbeddedWorkerDevToolsManagerTest : public testing::Test {
};
TEST_F(EmbeddedWorkerDevToolsManagerTest, BasicTest) {
- scoped_refptr<DevToolsAgentHost> agent_host;
+ scoped_refptr<DevToolsAgentHostImpl> agent_host;
SharedWorkerInstance instance1(GURL("http://example.com/w.js"),
base::string16(),
@@ -112,75 +110,75 @@ TEST_F(EmbeddedWorkerDevToolsManagerTest, BasicTest) {
// Created -> Started -> Destroyed
CheckWorkerNotExist(1, 1);
manager_->SharedWorkerCreated(1, 1, instance1);
- CheckWorkerState(1, 1, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
- manager_->WorkerContextStarted(1, 1);
- CheckWorkerState(1, 1, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(1, 1, WorkerState::WORKER_UNINSPECTED);
+ manager_->WorkerReadyForInspection(1, 1);
+ CheckWorkerState(1, 1, WorkerState::WORKER_UNINSPECTED);
manager_->WorkerDestroyed(1, 1);
CheckWorkerNotExist(1, 1);
// Created -> GetDevToolsAgentHost -> Started -> Destroyed
CheckWorkerNotExist(1, 2);
manager_->SharedWorkerCreated(1, 2, instance1);
- CheckWorkerState(1, 2, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED);
agent_host = manager_->GetDevToolsAgentHostForWorker(1, 2);
EXPECT_TRUE(agent_host.get());
- CheckWorkerState(1, 2, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED);
EXPECT_EQ(agent_host.get(), manager_->GetDevToolsAgentHostForWorker(1, 2));
- manager_->WorkerContextStarted(1, 2);
- CheckWorkerState(1, 2, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ manager_->WorkerReadyForInspection(1, 2);
+ CheckWorkerState(1, 2, WorkerState::WORKER_UNINSPECTED);
manager_->WorkerDestroyed(1, 2);
- CheckWorkerState(1, 2, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(1, 2, WorkerState::WORKER_TERMINATED);
agent_host = NULL;
CheckWorkerNotExist(1, 2);
// Created -> Started -> GetDevToolsAgentHost -> Destroyed
CheckWorkerNotExist(1, 3);
manager_->SharedWorkerCreated(1, 3, instance1);
- CheckWorkerState(1, 3, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
- manager_->WorkerContextStarted(1, 3);
- CheckWorkerState(1, 3, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED);
+ manager_->WorkerReadyForInspection(1, 3);
+ CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED);
agent_host = manager_->GetDevToolsAgentHostForWorker(1, 3);
EXPECT_TRUE(agent_host.get());
- CheckWorkerState(1, 3, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ CheckWorkerState(1, 3, WorkerState::WORKER_UNINSPECTED);
manager_->WorkerDestroyed(1, 3);
- CheckWorkerState(1, 3, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(1, 3, WorkerState::WORKER_TERMINATED);
agent_host = NULL;
CheckWorkerNotExist(1, 3);
// Created -> Destroyed
CheckWorkerNotExist(1, 4);
manager_->SharedWorkerCreated(1, 4, instance1);
- CheckWorkerState(1, 4, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(1, 4, WorkerState::WORKER_UNINSPECTED);
manager_->WorkerDestroyed(1, 4);
CheckWorkerNotExist(1, 4);
// Created -> GetDevToolsAgentHost -> Destroyed
CheckWorkerNotExist(1, 5);
manager_->SharedWorkerCreated(1, 5, instance1);
- CheckWorkerState(1, 5, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(1, 5, WorkerState::WORKER_UNINSPECTED);
agent_host = manager_->GetDevToolsAgentHostForWorker(1, 5);
EXPECT_TRUE(agent_host.get());
- CheckWorkerState(1, 5, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ CheckWorkerState(1, 5, WorkerState::WORKER_UNINSPECTED);
manager_->WorkerDestroyed(1, 5);
- CheckWorkerState(1, 5, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(1, 5, WorkerState::WORKER_TERMINATED);
agent_host = NULL;
CheckWorkerNotExist(1, 5);
// Created -> GetDevToolsAgentHost -> Free agent_host -> Destroyed
CheckWorkerNotExist(1, 6);
manager_->SharedWorkerCreated(1, 6, instance1);
- CheckWorkerState(1, 6, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(1, 6, WorkerState::WORKER_UNINSPECTED);
agent_host = manager_->GetDevToolsAgentHostForWorker(1, 6);
EXPECT_TRUE(agent_host.get());
- CheckWorkerState(1, 6, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ CheckWorkerState(1, 6, WorkerState::WORKER_UNINSPECTED);
agent_host = NULL;
manager_->WorkerDestroyed(1, 6);
CheckWorkerNotExist(1, 6);
}
TEST_F(EmbeddedWorkerDevToolsManagerTest, AttachTest) {
- scoped_refptr<DevToolsAgentHost> agent_host1;
- scoped_refptr<DevToolsAgentHost> agent_host2;
+ scoped_refptr<DevToolsAgentHostImpl> agent_host1;
+ scoped_refptr<DevToolsAgentHostImpl> agent_host2;
SharedWorkerInstance instance1(GURL("http://example.com/w1.js"),
base::string16(),
@@ -199,69 +197,66 @@ TEST_F(EmbeddedWorkerDevToolsManagerTest, AttachTest) {
scoped_ptr<TestDevToolsClientHost> client_host1(new TestDevToolsClientHost());
CheckWorkerNotExist(2, 1);
manager_->SharedWorkerCreated(2, 1, instance1);
- CheckWorkerState(2, 1, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(2, 1, WorkerState::WORKER_UNINSPECTED);
agent_host1 = manager_->GetDevToolsAgentHostForWorker(2, 1);
EXPECT_TRUE(agent_host1.get());
- CheckWorkerState(2, 1, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ CheckWorkerState(2, 1, WorkerState::WORKER_UNINSPECTED);
EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 1));
- RegisterDevToolsClientHostFor(agent_host1.get(), client_host1.get());
- CheckWorkerState(2, 1, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
- manager_->WorkerContextStarted(2, 1);
- CheckWorkerState(2, 1, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ client_host1->InspectAgentHost(agent_host1.get());
+ CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED);
+ manager_->WorkerReadyForInspection(2, 1);
+ CheckWorkerState(2, 1, WorkerState::WORKER_INSPECTED);
manager_->WorkerDestroyed(2, 1);
- CheckWorkerState(2, 1, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(2, 1, WorkerState::WORKER_TERMINATED);
EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 1));
// Created -> Started -> GetDevToolsAgentHost -> Register -> Destroyed
scoped_ptr<TestDevToolsClientHost> client_host2(new TestDevToolsClientHost());
manager_->SharedWorkerCreated(2, 2, instance2);
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
- manager_->WorkerContextStarted(2, 2);
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_UNINSPECTED);
+ CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED);
+ manager_->WorkerReadyForInspection(2, 2);
+ CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED);
agent_host2 = manager_->GetDevToolsAgentHostForWorker(2, 2);
EXPECT_TRUE(agent_host2.get());
EXPECT_NE(agent_host1.get(), agent_host2.get());
EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 2));
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
- RegisterDevToolsClientHostFor(agent_host2.get(), client_host2.get());
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
+ CheckWorkerState(2, 2, WorkerState::WORKER_UNINSPECTED);
+ client_host2->InspectAgentHost(agent_host2.get());
+ CheckWorkerState(2, 2, WorkerState::WORKER_INSPECTED);
manager_->WorkerDestroyed(2, 2);
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(2, 2, WorkerState::WORKER_TERMINATED);
EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 2));
// Re-created -> Started -> ClientHostClosing -> Destroyed
- CheckWorkerState(2, 1, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(2, 1, WorkerState::WORKER_TERMINATED);
manager_->SharedWorkerCreated(2, 3, instance1);
CheckWorkerNotExist(2, 1);
- CheckWorkerState(
- 2, 3, EmbeddedWorkerDevToolsManager::WORKER_PAUSED_FOR_REATTACH);
+ CheckWorkerState(2, 3, WorkerState::WORKER_PAUSED_FOR_REATTACH);
EXPECT_EQ(agent_host1.get(), manager_->GetDevToolsAgentHostForWorker(2, 3));
- manager_->WorkerContextStarted(2, 3);
- CheckWorkerState(2, 3, EmbeddedWorkerDevToolsManager::WORKER_INSPECTED);
- ClientHostClosing(client_host1.get());
+ manager_->WorkerReadyForInspection(2, 3);
+ CheckWorkerState(2, 3, WorkerState::WORKER_INSPECTED);
+ client_host1->InspectAgentHost(NULL);
manager_->WorkerDestroyed(2, 3);
- CheckWorkerState(2, 3, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(2, 3, WorkerState::WORKER_TERMINATED);
agent_host1 = NULL;
CheckWorkerNotExist(2, 3);
// Re-created -> Destroyed
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerState(2, 2, WorkerState::WORKER_TERMINATED);
manager_->SharedWorkerCreated(2, 4, instance2);
CheckWorkerNotExist(2, 2);
- CheckWorkerState(
- 2, 4, EmbeddedWorkerDevToolsManager::WORKER_PAUSED_FOR_REATTACH);
+ CheckWorkerState(2, 4, WorkerState::WORKER_PAUSED_FOR_REATTACH);
EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 4));
manager_->WorkerDestroyed(2, 4);
- CheckWorkerNotExist(2, 4);
- CheckWorkerState(2, 2, EmbeddedWorkerDevToolsManager::WORKER_TERMINATED);
+ CheckWorkerNotExist(2, 2);
+ CheckWorkerState(2, 4, WorkerState::WORKER_TERMINATED);
// Re-created -> ClientHostClosing -> Destroyed
manager_->SharedWorkerCreated(2, 5, instance2);
CheckWorkerNotExist(2, 2);
- CheckWorkerState(
- 2, 5, EmbeddedWorkerDevToolsManager::WORKER_PAUSED_FOR_REATTACH);
+ CheckWorkerState(2, 5, WorkerState::WORKER_PAUSED_FOR_REATTACH);
EXPECT_EQ(agent_host2.get(), manager_->GetDevToolsAgentHostForWorker(2, 5));
- ClientHostClosing(client_host2.get());
+ client_host2->InspectAgentHost(NULL);
CheckWorkerCount(1);
agent_host2 = NULL;
CheckWorkerCount(1);
@@ -269,4 +264,35 @@ TEST_F(EmbeddedWorkerDevToolsManagerTest, AttachTest) {
CheckWorkerCount(0);
}
+TEST_F(EmbeddedWorkerDevToolsManagerTest, ReattachTest) {
+ SharedWorkerInstance instance(GURL("http://example.com/w3.js"),
+ base::string16(),
+ base::string16(),
+ blink::WebContentSecurityPolicyTypeReport,
+ browser_context_->GetResourceContext(),
+ partition_id_);
+ scoped_ptr<TestDevToolsClientHost> client_host(new TestDevToolsClientHost());
+ // Created -> GetDevToolsAgentHost -> Register -> Destroyed
+ manager_->SharedWorkerCreated(3, 1, instance);
+ CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED);
+ scoped_refptr<DevToolsAgentHost> agent_host(
+ manager_->GetDevToolsAgentHostForWorker(3, 1));
+ EXPECT_TRUE(agent_host.get());
+ CheckWorkerState(3, 1, WorkerState::WORKER_UNINSPECTED);
+ client_host->InspectAgentHost(agent_host.get());
+ CheckWorkerState(3, 1, WorkerState::WORKER_INSPECTED);
+ manager_->WorkerDestroyed(3, 1);
+ CheckWorkerState(3, 1, WorkerState::WORKER_TERMINATED);
+ // ClientHostClosing -> Re-created -> release agent_host -> Destroyed
+ client_host->InspectAgentHost(NULL);
+ CheckWorkerState(3, 1, WorkerState::WORKER_TERMINATED);
+ manager_->SharedWorkerCreated(3, 2, instance);
+ CheckWorkerState(3, 2, WorkerState::WORKER_UNINSPECTED);
+ agent_host = NULL;
+ CheckWorkerState(3, 2, WorkerState::WORKER_UNINSPECTED);
+ manager_->WorkerDestroyed(3, 2);
+ CheckWorkerNotExist(3, 2);
+ CheckWorkerCount(0);
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.cc b/chromium/content/browser/devtools/forwarding_agent_host.cc
index f1524e1b7e1..4d3e4fff0b0 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.cc
+++ b/chromium/content/browser/devtools/forwarding_agent_host.cc
@@ -4,8 +4,6 @@
#include "content/browser/devtools/forwarding_agent_host.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
-
namespace content {
ForwardingAgentHost::ForwardingAgentHost(
@@ -17,12 +15,11 @@ ForwardingAgentHost::~ForwardingAgentHost() {
}
void ForwardingAgentHost::DispatchOnClientHost(const std::string& message) {
- DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
- this, message);
+ SendMessageToClient(message);
}
void ForwardingAgentHost::ConnectionClosed() {
- NotifyCloseListener();
+ HostClosed();
}
void ForwardingAgentHost::Attach() {
@@ -33,9 +30,29 @@ void ForwardingAgentHost::Detach() {
delegate_->Detach();
}
-void ForwardingAgentHost::DispatchOnInspectorBackend(
+void ForwardingAgentHost::DispatchProtocolMessage(
const std::string& message) {
delegate_->SendMessageToBackend(message);
}
+DevToolsAgentHost::Type ForwardingAgentHost::GetType() {
+ return TYPE_EXTERNAL;
+}
+
+std::string ForwardingAgentHost::GetTitle() {
+ return "";
+}
+
+GURL ForwardingAgentHost::GetURL() {
+ return GURL();
+}
+
+bool ForwardingAgentHost::Activate() {
+ return false;
+}
+
+bool ForwardingAgentHost::Close() {
+ return false;
+}
+
} // content
diff --git a/chromium/content/browser/devtools/forwarding_agent_host.h b/chromium/content/browser/devtools/forwarding_agent_host.h
index 81e4aed5419..7f9bcec5ff9 100644
--- a/chromium/content/browser/devtools/forwarding_agent_host.h
+++ b/chromium/content/browser/devtools/forwarding_agent_host.h
@@ -20,16 +20,23 @@ class ForwardingAgentHost
ForwardingAgentHost(DevToolsExternalAgentProxyDelegate* delegate);
private:
- virtual ~ForwardingAgentHost();
+ ~ForwardingAgentHost() override;
// DevToolsExternalAgentProxy implementation.
- virtual void DispatchOnClientHost(const std::string& message) OVERRIDE;
- virtual void ConnectionClosed() OVERRIDE;
+ void DispatchOnClientHost(const std::string& message) override;
+ void ConnectionClosed() override;
// DevToolsAgentHostImpl implementation.
- virtual void Attach() OVERRIDE;
- virtual void Detach() OVERRIDE;
- virtual void DispatchOnInspectorBackend(const std::string& message) OVERRIDE;
+ void Attach() override;
+ void Detach() override;
+ void DispatchProtocolMessage(const std::string& message) override;
+
+ // DevToolsAgentHost implementation
+ Type GetType() override;
+ std::string GetTitle() override;
+ GURL GetURL() override;
+ bool Activate() override;
+ bool Close() override;
scoped_ptr<DevToolsExternalAgentProxyDelegate> delegate_;
};
diff --git a/chromium/content/browser/devtools/ipc_devtools_agent_host.cc b/chromium/content/browser/devtools/ipc_devtools_agent_host.cc
index 294a679c7f6..9218d5809bb 100644
--- a/chromium/content/browser/devtools/ipc_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/ipc_devtools_agent_host.cc
@@ -18,7 +18,7 @@ void IPCDevToolsAgentHost::Detach() {
OnClientDetached();
}
-void IPCDevToolsAgentHost::DispatchOnInspectorBackend(
+void IPCDevToolsAgentHost::DispatchProtocolMessage(
const std::string& message) {
SendMessageToAgent(new DevToolsAgentMsg_DispatchOnInspectorBackend(
MSG_ROUTING_NONE, message));
@@ -29,6 +29,10 @@ void IPCDevToolsAgentHost::InspectElement(int x, int y) {
GetId(), x, y));
}
+IPCDevToolsAgentHost::IPCDevToolsAgentHost()
+ : message_buffer_size_(0) {
+}
+
IPCDevToolsAgentHost::~IPCDevToolsAgentHost() {
}
@@ -38,4 +42,29 @@ void IPCDevToolsAgentHost::Reattach(const std::string& saved_agent_state) {
OnClientAttached();
}
+void IPCDevToolsAgentHost::ProcessChunkedMessageFromAgent(
+ const std::string& message, uint32 total_size) {
+ if (total_size && total_size == message.length()) {
+ DCHECK(message_buffer_size_ == 0);
+ SendMessageToClient(message);
+ return;
+ }
+
+ if (total_size) {
+ DCHECK(message_buffer_size_ == 0);
+ message_buffer_ = std::string();
+ message_buffer_.reserve(total_size);
+ message_buffer_size_ = total_size;
+ }
+
+ message_buffer_.append(message);
+
+ if (message_buffer_.size() >= message_buffer_size_) {
+ DCHECK(message_buffer_.size() == message_buffer_size_);
+ SendMessageToClient(message_buffer_);
+ message_buffer_ = std::string();
+ message_buffer_size_ = 0;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/ipc_devtools_agent_host.h b/chromium/content/browser/devtools/ipc_devtools_agent_host.h
index 98c2794ac6e..a952588f758 100644
--- a/chromium/content/browser/devtools/ipc_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/ipc_devtools_agent_host.h
@@ -16,19 +16,26 @@ namespace content {
class CONTENT_EXPORT IPCDevToolsAgentHost : public DevToolsAgentHostImpl {
public:
// DevToolsAgentHostImpl implementation.
- virtual void Attach() OVERRIDE;
- virtual void Detach() OVERRIDE;
- virtual void DispatchOnInspectorBackend(const std::string& message) OVERRIDE;
- virtual void InspectElement(int x, int y) OVERRIDE;
+ void Attach() override;
+ void Detach() override;
+ void DispatchProtocolMessage(const std::string& message) override;
+ void InspectElement(int x, int y) override;
protected:
- virtual ~IPCDevToolsAgentHost();
+ IPCDevToolsAgentHost();
+ ~IPCDevToolsAgentHost() override;
void Reattach(const std::string& saved_agent_state);
+ void ProcessChunkedMessageFromAgent(const std::string& message,
+ uint32 total_size);
virtual void SendMessageToAgent(IPC::Message* msg) = 0;
virtual void OnClientAttached() = 0;
virtual void OnClientDetached() = 0;
+
+ private:
+ std::string message_buffer_;
+ uint32 message_buffer_size_;
};
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/color_picker.cc b/chromium/content/browser/devtools/protocol/color_picker.cc
new file mode 100644
index 00000000000..dec4f3103b3
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/color_picker.cc
@@ -0,0 +1,265 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/color_picker.h"
+
+#include "base/bind.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/common/cursors/webcursor.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/gfx/size_conversions.h"
+
+namespace content {
+namespace devtools {
+namespace page {
+
+ColorPicker::ColorPicker(ColorPickedCallback callback)
+ : callback_(callback),
+ enabled_(false),
+ last_cursor_x_(-1),
+ last_cursor_y_(-1),
+ host_(nullptr),
+ weak_factory_(this) {
+ mouse_event_callback_ = base::Bind(
+ &ColorPicker::HandleMouseEvent,
+ base::Unretained(this));
+}
+
+ColorPicker::~ColorPicker() {
+}
+
+void ColorPicker::SetRenderViewHost(RenderViewHostImpl* host) {
+ if (host_ == host)
+ return;
+
+ if (host_)
+ host_->RemoveMouseEventCallback(mouse_event_callback_);
+ ResetFrame();
+ host_ = host;
+ if (enabled_ && host)
+ host->AddMouseEventCallback(mouse_event_callback_);
+}
+
+void ColorPicker::SetEnabled(bool enabled) {
+ if (enabled_ == enabled)
+ return;
+
+ enabled_ = enabled;
+ if (!host_)
+ return;
+
+ if (enabled) {
+ host_->AddMouseEventCallback(mouse_event_callback_);
+ UpdateFrame();
+ } else {
+ host_->RemoveMouseEventCallback(mouse_event_callback_);
+ ResetFrame();
+
+ WebCursor pointer_cursor;
+ WebCursor::CursorInfo cursor_info;
+ cursor_info.type = blink::WebCursorInfo::TypePointer;
+ pointer_cursor.InitFromCursorInfo(cursor_info);
+ host_->SetCursor(pointer_cursor);
+ }
+}
+
+void ColorPicker::OnSwapCompositorFrame() {
+ if (enabled_)
+ UpdateFrame();
+}
+
+void ColorPicker::UpdateFrame() {
+ if (!host_)
+ return;
+ RenderWidgetHostViewBase* view =
+ static_cast<RenderWidgetHostViewBase*>(host_->GetView());
+ if (!view)
+ return;
+
+ gfx::Size size = view->GetViewBounds().size();
+ view->CopyFromCompositingSurface(
+ gfx::Rect(size), size,
+ base::Bind(&ColorPicker::FrameUpdated,
+ weak_factory_.GetWeakPtr()),
+ kN32_SkColorType);
+}
+
+void ColorPicker::ResetFrame() {
+ frame_.reset();
+ last_cursor_x_ = -1;
+ last_cursor_y_ = -1;
+}
+
+void ColorPicker::FrameUpdated(bool succeeded, const SkBitmap& bitmap) {
+ if (!enabled_)
+ return;
+
+ if (succeeded) {
+ frame_ = bitmap;
+ UpdateCursor();
+ }
+}
+
+bool ColorPicker::HandleMouseEvent(const blink::WebMouseEvent& event) {
+ last_cursor_x_ = event.x;
+ last_cursor_y_ = event.y;
+ if (frame_.drawsNothing())
+ return true;
+
+ if (event.button == blink::WebMouseEvent::ButtonLeft &&
+ event.type == blink::WebInputEvent::MouseDown) {
+ if (last_cursor_x_ < 0 || last_cursor_x_ >= frame_.width() ||
+ last_cursor_y_ < 0 || last_cursor_y_ >= frame_.height()) {
+ return true;
+ }
+
+ SkAutoLockPixels lock_image(frame_);
+ SkColor sk_color = frame_.getColor(last_cursor_x_, last_cursor_y_);
+ callback_.Run(SkColorGetR(sk_color), SkColorGetG(sk_color),
+ SkColorGetB(sk_color), SkColorGetA(sk_color));
+ }
+ UpdateCursor();
+ return true;
+}
+
+void ColorPicker::UpdateCursor() {
+ if (!host_ || frame_.drawsNothing())
+ return;
+
+ if (last_cursor_x_ < 0 || last_cursor_x_ >= frame_.width() ||
+ last_cursor_y_ < 0 || last_cursor_y_ >= frame_.height()) {
+ return;
+ }
+
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ host_->GetView());
+ if (!view)
+ return;
+
+ // Due to platform limitations, we are using two different cursors
+ // depending on the platform. Mac and Win have large cursors with two circles
+ // for original spot and its magnified projection; Linux gets smaller (64 px)
+ // magnified projection only with centered hotspot.
+ // Mac Retina requires cursor to be > 120px in order to render smoothly.
+
+#if defined(OS_LINUX)
+ const float kCursorSize = 63;
+ const float kDiameter = 63;
+ const float kHotspotOffset = 32;
+ const float kHotspotRadius = 0;
+ const float kPixelSize = 9;
+#else
+ const float kCursorSize = 150;
+ const float kDiameter = 110;
+ const float kHotspotOffset = 25;
+ const float kHotspotRadius = 5;
+ const float kPixelSize = 10;
+#endif
+
+ blink::WebScreenInfo screen_info;
+ view->GetScreenInfo(&screen_info);
+ double device_scale_factor = screen_info.deviceScaleFactor;
+
+ skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(SkCanvas::NewRasterN32(
+ kCursorSize * device_scale_factor,
+ kCursorSize * device_scale_factor));
+ canvas->scale(device_scale_factor, device_scale_factor);
+ canvas->translate(0.5f, 0.5f);
+
+ SkPaint paint;
+
+ // Paint original spot with cross.
+ if (kHotspotRadius) {
+ paint.setStrokeWidth(1);
+ paint.setAntiAlias(false);
+ paint.setColor(SK_ColorDKGRAY);
+ paint.setStyle(SkPaint::kStroke_Style);
+
+ canvas->drawLine(kHotspotOffset, kHotspotOffset - 2 * kHotspotRadius,
+ kHotspotOffset, kHotspotOffset - kHotspotRadius,
+ paint);
+ canvas->drawLine(kHotspotOffset, kHotspotOffset + kHotspotRadius,
+ kHotspotOffset, kHotspotOffset + 2 * kHotspotRadius,
+ paint);
+ canvas->drawLine(kHotspotOffset - 2 * kHotspotRadius, kHotspotOffset,
+ kHotspotOffset - kHotspotRadius, kHotspotOffset,
+ paint);
+ canvas->drawLine(kHotspotOffset + kHotspotRadius, kHotspotOffset,
+ kHotspotOffset + 2 * kHotspotRadius, kHotspotOffset,
+ paint);
+
+ paint.setStrokeWidth(2);
+ paint.setAntiAlias(true);
+ canvas->drawCircle(kHotspotOffset, kHotspotOffset, kHotspotRadius, paint);
+ }
+
+ // Clip circle for magnified projection.
+ float padding = (kCursorSize - kDiameter) / 2;
+ SkPath clip_path;
+ clip_path.addOval(SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter));
+ clip_path.close();
+ canvas->clipPath(clip_path, SkRegion::kIntersect_Op, true);
+
+ // Project pixels.
+ int pixel_count = kDiameter / kPixelSize;
+ SkRect src_rect = SkRect::MakeXYWH(last_cursor_x_ - pixel_count / 2,
+ last_cursor_y_ - pixel_count / 2,
+ pixel_count, pixel_count);
+ SkRect dst_rect = SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter);
+ canvas->drawBitmapRectToRect(frame_, &src_rect, dst_rect);
+
+ // Paint grid.
+ paint.setStrokeWidth(1);
+ paint.setAntiAlias(false);
+ paint.setColor(SK_ColorGRAY);
+ for (int i = 0; i < pixel_count; ++i) {
+ canvas->drawLine(padding + i * kPixelSize, padding,
+ padding + i * kPixelSize, kCursorSize - padding, paint);
+ canvas->drawLine(padding, padding + i * kPixelSize,
+ kCursorSize - padding, padding + i * kPixelSize, paint);
+ }
+
+ // Paint central pixel in red.
+ SkRect pixel = SkRect::MakeXYWH((kCursorSize - kPixelSize) / 2,
+ (kCursorSize - kPixelSize) / 2,
+ kPixelSize, kPixelSize);
+ paint.setColor(SK_ColorRED);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(pixel, paint);
+
+ // Paint outline.
+ paint.setStrokeWidth(2);
+ paint.setColor(SK_ColorDKGRAY);
+ paint.setAntiAlias(true);
+ canvas->drawCircle(kCursorSize / 2, kCursorSize / 2, kDiameter / 2, paint);
+
+ SkBitmap result;
+ result.allocN32Pixels(kCursorSize * device_scale_factor,
+ kCursorSize * device_scale_factor);
+ canvas->readPixels(&result, 0, 0);
+
+ WebCursor cursor;
+ WebCursor::CursorInfo cursor_info;
+ cursor_info.type = blink::WebCursorInfo::TypeCustom;
+ cursor_info.image_scale_factor = device_scale_factor;
+ cursor_info.custom_image = result;
+ cursor_info.hotspot =
+ gfx::Point(kHotspotOffset * device_scale_factor,
+ kHotspotOffset * device_scale_factor);
+#if defined(OS_WIN)
+ cursor_info.external_handle = 0;
+#endif
+
+ cursor.InitFromCursorInfo(cursor_info);
+ DCHECK(host_);
+ host_->SetCursor(cursor);
+}
+
+} // namespace page
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/color_picker.h b/chromium/content/browser/devtools/protocol/color_picker.h
new file mode 100644
index 00000000000..e59a35137fd
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/color_picker.h
@@ -0,0 +1,57 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_COLOR_PICKER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_COLOR_PICKER_H_
+
+#include "base/callback.h"
+#include "content/public/browser/render_widget_host.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace blink {
+class WebMouseEvent;
+}
+
+namespace content {
+
+class RenderViewHostImpl;
+
+namespace devtools {
+namespace page {
+
+class ColorPicker {
+ public:
+ typedef base::Callback<void(int, int, int, int)> ColorPickedCallback;
+
+ explicit ColorPicker(ColorPickedCallback callback);
+ virtual ~ColorPicker();
+
+ void SetRenderViewHost(RenderViewHostImpl* host);
+ void SetEnabled(bool enabled);
+ void OnSwapCompositorFrame();
+
+ private:
+ void UpdateFrame();
+ void ResetFrame();
+ void FrameUpdated(bool succeeded, const SkBitmap& bitmap);
+ bool HandleMouseEvent(const blink::WebMouseEvent& event);
+ void UpdateCursor();
+
+ ColorPickedCallback callback_;
+ bool enabled_;
+ SkBitmap frame_;
+ int last_cursor_x_;
+ int last_cursor_y_;
+ RenderWidgetHost::MouseEventCallback mouse_event_callback_;
+ RenderViewHostImpl* host_;
+ base::WeakPtrFactory<ColorPicker> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ColorPicker);
+};
+
+} // namespace page
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_COLOR_PICKER_H_
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_client.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_client.cc
new file mode 100644
index 00000000000..a34189e0efc
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_client.cc
@@ -0,0 +1,97 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/devtools_protocol_client.h"
+
+namespace content {
+
+DevToolsProtocolClient::DevToolsProtocolClient(
+ const RawMessageCallback& raw_message_callback)
+ : raw_message_callback_(raw_message_callback) {
+}
+
+DevToolsProtocolClient::~DevToolsProtocolClient() {
+}
+
+void DevToolsProtocolClient::SendNotification(const std::string& method,
+ base::DictionaryValue* params) {
+ scoped_refptr<DevToolsProtocol::Notification> notification =
+ new DevToolsProtocol::Notification(method, params);
+ SendRawMessage(notification->Serialize());
+}
+
+void DevToolsProtocolClient::SendAsyncResponse(
+ scoped_refptr<DevToolsProtocol::Response> response) {
+ SendRawMessage(response->Serialize());
+}
+
+void DevToolsProtocolClient::SendRawMessage(const std::string& message) {
+ raw_message_callback_.Run(message);
+}
+
+void DevToolsProtocolClient::SendInvalidParamsResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message) {
+ SendAsyncResponse(command->InvalidParamResponse(message));
+}
+
+void DevToolsProtocolClient::SendInternalErrorResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message) {
+ SendAsyncResponse(command->InternalErrorResponse(message));
+}
+
+void DevToolsProtocolClient::SendServerErrorResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message) {
+ SendAsyncResponse(command->ServerErrorResponse(message));
+}
+
+typedef DevToolsProtocolClient::Response Response;
+
+Response Response::FallThrough() {
+ Response response;
+ response.status_ = ResponseStatus::RESPONSE_STATUS_FALLTHROUGH;
+ return response;
+}
+
+Response Response::OK() {
+ Response response;
+ response.status_ = ResponseStatus::RESPONSE_STATUS_OK;
+ return response;
+}
+
+Response Response::InvalidParams(const std::string& message) {
+ Response response;
+ response.status_ = ResponseStatus::RESPONSE_STATUS_INVALID_PARAMS;
+ response.message_ = message;
+ return response;
+}
+
+Response Response::InternalError(const std::string& message) {
+ Response response;
+ response.status_ = ResponseStatus::RESPONSE_STATUS_INTERNAL_ERROR;
+ response.message_ = message;
+ return response;
+}
+
+Response Response::ServerError(const std::string& message) {
+ Response response;
+ response.status_ = ResponseStatus::RESPONSE_STATUS_SERVER_ERROR;
+ response.message_ = message;
+ return response;
+}
+
+DevToolsProtocolClient::ResponseStatus Response::status() const {
+ return status_;
+}
+
+const std::string& Response::message() const {
+ return message_;
+}
+
+Response::Response() {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_client.h b/chromium/content/browser/devtools/protocol/devtools_protocol_client.h
new file mode 100644
index 00000000000..620a7c14995
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_client.h
@@ -0,0 +1,75 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_CLIENT_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_CLIENT_H_
+
+#include "content/browser/devtools/devtools_protocol.h"
+
+namespace content {
+
+class DevToolsProtocolClient {
+ public:
+ typedef base::Callback<void(const std::string& message)>
+ RawMessageCallback;
+
+ enum ResponseStatus {
+ RESPONSE_STATUS_FALLTHROUGH,
+ RESPONSE_STATUS_OK,
+ RESPONSE_STATUS_INVALID_PARAMS,
+ RESPONSE_STATUS_INTERNAL_ERROR,
+ RESPONSE_STATUS_SERVER_ERROR,
+ };
+
+ struct Response {
+ public:
+ static Response FallThrough();
+ static Response OK();
+ static Response InvalidParams(const std::string& message);
+ static Response InternalError(const std::string& message);
+ static Response ServerError(const std::string& message);
+
+ ResponseStatus status() const;
+ const std::string& message() const;
+
+ private:
+ Response();
+
+ ResponseStatus status_;
+ std::string message_;
+ };
+
+ void SendInvalidParamsResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message);
+ void SendInternalErrorResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message);
+ void SendServerErrorResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message);
+
+ // Sends message to client, the caller is presumed to properly
+ // format the message. Do not use unless you must.
+ void SendRawMessage(const std::string& message);
+
+ protected:
+ DevToolsProtocolClient(const RawMessageCallback& raw_message_callback);
+
+ virtual ~DevToolsProtocolClient();
+
+ void SendNotification(const std::string& method,
+ base::DictionaryValue* params);
+
+ void SendAsyncResponse(scoped_refptr<DevToolsProtocol::Response> response);
+
+ private:
+ RawMessageCallback raw_message_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(DevToolsProtocolClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_CLIENT_H_
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
new file mode 100755
index 00000000000..dd165faec5f
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -0,0 +1,776 @@
+#!/usr/bin/env python
+# Copyright 2014 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.
+
+import sys
+import string
+import json
+
+input_json_path = sys.argv[1]
+output_cc_path = sys.argv[2]
+output_h_path = sys.argv[3]
+
+header = """\
+// Copyright 2014 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 IS AUTOGENERATED. DO NOT EDIT.
+// Generated by
+// content/public/browser/devtools_protocol_handler_generator.py from
+// third_party/WebKit/Source/devtools/protocol.json
+"""
+
+template_h = string.Template(header + """\
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_HANDLER_IMPL_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_HANDLER_IMPL_H_
+
+#include "content/browser/devtools/devtools_protocol.h"
+#include "content/browser/devtools/protocol/devtools_protocol_client.h"
+
+namespace content {
+
+class DevToolsProtocolHandlerImpl;
+
+namespace devtools {
+
+${types}\
+
+} // namespace devtools
+
+class DevToolsProtocolHandlerImpl : public DevToolsProtocol::Handler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+ typedef DevToolsProtocolClient::ResponseStatus ResponseStatus;
+
+ DevToolsProtocolHandlerImpl();
+ virtual ~DevToolsProtocolHandlerImpl();
+
+${setters}\
+
+ private:
+${friends}\
+
+${methods}\
+
+${fields}\
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_HANDLER_IMPL_H_
+""")
+
+tmpl_typedef = string.Template("""\
+namespace ${domain} {
+typedef ${param_type} ${declared_name};
+} // namespace ${domain}
+""")
+
+tmpl_struct = string.Template("""\
+namespace ${domain} {
+struct ${declared_name} {
+ public:
+ ${declared_name}();
+
+${methods}\
+
+ private:
+ friend class ::content::DevToolsProtocolHandlerImpl;
+
+${fields}\
+};
+} // namespace ${domain}
+""")
+
+tmpl_struct_setter = string.Template("""\
+ void set_${param}(${pass_type} ${param});
+""")
+
+tmpl_struct_field = string.Template("""\
+ ${param_type} ${param}_;
+ bool has_${param}_;
+""")
+
+tmpl_enum = string.Template("""\
+namespace ${domain} {
+namespace ${subdomain} {
+${values}\
+} // namespace ${subdomain}
+} // namespace ${domain}
+""")
+
+tmpl_enum_value = string.Template("""\
+extern const char k${Param}${Value}[];
+""")
+
+tmpl_enum_value_def = string.Template("""\
+const char k${Param}${Value}[] = "${value}";
+""")
+
+tmpl_handler = string.Template("""\
+namespace ${domain} {
+class ${Domain}Handler;
+} // namespace domain
+""")
+
+tmpl_client = string.Template("""\
+namespace ${domain} {
+class Client : public DevToolsProtocolClient {
+ public:
+ Client(const RawMessageCallback& raw_message_callback);
+ virtual ~Client();
+
+${methods}\
+};
+} // namespace ${domain}
+""")
+
+tmpl_event = string.Template("""\
+ void ${Command}(
+ const ${Command}Params& params);
+""")
+
+tmpl_response = string.Template("""\
+ void Send${Command}Response(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const ${Command}Response& params);
+""")
+
+tmpl_setter = string.Template("""\
+ void Set${Domain}Handler(
+ devtools::${domain}::${Domain}Handler* ${domain}_handler);
+""")
+
+tmpl_friend = string.Template("""\
+ friend class devtools::${domain}::Client;
+""")
+
+tmpl_callback = string.Template("""\
+ scoped_refptr<DevToolsProtocol::Response>
+ On${Domain}${Command}(
+ scoped_refptr<DevToolsProtocol::Command> command);
+""")
+
+tmpl_to_value = string.Template("""\
+ static base::DictionaryValue* ToValue(
+ const devtools::${domain}::${declared_name}& src);
+""")
+
+tmpl_field = string.Template("""\
+ devtools::${domain}::${Domain}Handler* ${domain}_handler_;
+""")
+
+template_cc = string.Template(header + """\
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+#include "base/bind.h"
+${includes}\
+
+namespace content {
+
+DevToolsProtocolHandlerImpl::DevToolsProtocolHandlerImpl()
+ : ${fields_init} {
+}
+
+DevToolsProtocolHandlerImpl::~DevToolsProtocolHandlerImpl() {
+}
+
+namespace {
+
+typedef DevToolsProtocolClient::ResponseStatus ResponseStatus;
+
+bool CreateCommonResponse(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const DevToolsProtocolClient::Response& response,
+ scoped_refptr<DevToolsProtocol::Response>* protocol_response) {
+ switch (response.status()) {
+ case ResponseStatus::RESPONSE_STATUS_FALLTHROUGH:
+ *protocol_response = NULL;
+ break;
+ case ResponseStatus::RESPONSE_STATUS_OK:
+ return false;
+ case ResponseStatus::RESPONSE_STATUS_INVALID_PARAMS:
+ *protocol_response = command->InvalidParamResponse(response.message());
+ break;
+ case ResponseStatus::RESPONSE_STATUS_INTERNAL_ERROR:
+ *protocol_response = command->InternalErrorResponse(response.message());
+ break;
+ case ResponseStatus::RESPONSE_STATUS_SERVER_ERROR:
+ *protocol_response = command->ServerErrorResponse(response.message());
+ break;
+ }
+ return true;
+}
+
+} // namespace
+
+${methods}\
+
+namespace devtools {
+
+${types}\
+
+} // namespace devtools
+
+} // namespace content
+""")
+
+tmpl_include = string.Template("""\
+#include "content/browser/devtools/protocol/${domain}_handler.h"
+""")
+
+tmpl_field_init = string.Template("${domain}_handler_(NULL)")
+
+tmpl_setter_impl = string.Template("""\
+void DevToolsProtocolHandlerImpl::Set${Domain}Handler(
+ devtools::${domain}::${Domain}Handler* ${domain}_handler) {
+ DCHECK(!${domain}_handler_);
+ ${domain}_handler_ = ${domain}_handler;
+${initializations}\
+}
+""")
+
+tmpl_register = string.Template("""\
+ RegisterCommandHandler(
+ "${Domain}.${command}",
+ base::Bind(
+ &DevToolsProtocolHandlerImpl::On${Domain}${Command},
+ base::Unretained(this)));
+""")
+
+tmpl_init_client = string.Template("""\
+ ${domain}_handler_->SetClient(make_scoped_ptr(
+ new devtools::${domain}::Client(
+ base::Bind(&DevToolsProtocolHandlerImpl::SendRawMessage,
+ base::Unretained(this)))));
+""")
+
+tmpl_callback_impl = string.Template("""\
+scoped_refptr<DevToolsProtocol::Response>
+DevToolsProtocolHandlerImpl::On${Domain}${Command}(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+${prep}\
+ Response response = ${domain}_handler_->${Command}(${args});
+ scoped_refptr<DevToolsProtocol::Response> protocol_response;
+ if (CreateCommonResponse(command, response, &protocol_response))
+ return protocol_response;
+ base::DictionaryValue* dict = new base::DictionaryValue();
+${wrap}\
+ return command->SuccessResponse(dict);
+}
+""")
+
+tmpl_callback_async_impl = string.Template("""\
+scoped_refptr<DevToolsProtocol::Response>
+DevToolsProtocolHandlerImpl::On${Domain}${Command}(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+${prep}\
+ return ${domain}_handler_->${Command}(${args});
+}
+""")
+
+params_prep = """\
+ base::DictionaryValue* params = command->params();
+"""
+
+tmpl_prep_req = string.Template("""\
+ ${param_type} in_${param}${init};
+ if (!params ||
+ !params->Get${Type}("${proto_param}", &in_${param}))
+ return command->InvalidParamResponse("${proto_param}");
+""")
+
+tmpl_prep_req_list = string.Template("""\
+ base::ListValue* list_${param} = NULL;
+ if (!params || !params->GetList("${proto_param}", &list_${param}))
+ return command->InvalidParamResponse("${proto_param}");
+ ${param_type} in_${param};
+ for (base::ListValue::const_iterator it =
+ list_${param}->begin(); it != list_${param}->end(); ++it) {
+ ${item_type} item${item_init};
+ if (!(*it)->GetAs${ItemType}(&item))
+ return command->InvalidParamResponse("${proto_param}");
+ in_${param}.push_back(item);
+ }
+""")
+
+tmpl_prep_opt = string.Template("""\
+ ${param_type} in_${param}${init};
+ bool ${param}_found = params && params->Get${Type}(
+ "${proto_param}",
+ &in_${param});
+""")
+
+tmpl_prep_output = string.Template("""\
+ ${param_type} out_${param}${init};
+""")
+
+tmpl_arg_req = string.Template("in_${param}")
+
+tmpl_arg_opt = string.Template(
+ "${param}_found ?\n &in_${param} : NULL")
+
+tmpl_arg_output = string.Template("&out_${param}")
+
+tmpl_to_value_impl = string.Template("""\
+// static
+base::DictionaryValue* DevToolsProtocolHandlerImpl::ToValue(
+ const devtools::${domain}::${declared_name}& src) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+${dchecks}\
+${wrap}\
+ return dict;
+}
+""")
+
+tmpl_dcheck = string.Template("""\
+ DCHECK(${cond_name});
+""")
+
+tmpl_struct_impl = string.Template("""\
+namespace ${domain} {
+
+${declared_name}::${declared_name}()${fields} {
+}
+
+${methods}\
+
+} // namespace ${domain}
+""")
+
+tmpl_struct_field_init = string.Template("has_${param}_(false)")
+
+tmpl_struct_setter_impl = string.Template("""\
+void ${declared_name}::set_${param}(
+ ${pass_type} ${param}) {
+ ${param}_ = ${param};
+ has_${param}_ = true;
+}
+""")
+
+tmpl_client_impl = string.Template("""\
+namespace ${domain} {
+
+Client::Client(const RawMessageCallback& raw_message_callback)
+ : DevToolsProtocolClient(raw_message_callback) {
+}
+
+Client::~Client() {
+}
+
+${methods}\
+
+} // namespace ${domain}
+""")
+
+tmpl_event_impl = string.Template("""\
+void Client::${Command}(
+ const ${Command}Params& params) {
+ SendNotification("${Domain}.${command}",
+ DevToolsProtocolHandlerImpl::ToValue(params));
+}
+""")
+
+tmpl_response_impl = string.Template("""\
+void Client::Send${Command}Response(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const ${Command}Response& params) {
+ SendAsyncResponse(
+ command->SuccessResponse(DevToolsProtocolHandlerImpl::ToValue(params)));
+}
+""")
+
+tmpl_wrap = string.Template("""\
+ dict->Set${Type}("${proto_param}", ${var_name});
+""")
+
+tmpl_wrap_dict = string.Template("""\
+ dict->Set("${proto_param}",
+ DevToolsProtocolHandlerImpl::ToValue(${var_name}));
+""")
+
+tmpl_wrap_obj = string.Template("""\
+ dict->Set("${proto_param}", ${var_name});
+""")
+
+tmpl_wrap_list = string.Template("""\
+ base::ListValue* list_${param} = new base::ListValue();
+ for (${param_type}::const_iterator it =
+ ${var_name}.begin(); it != ${var_name}.end(); ++it) {
+${append}\
+ }
+ dict->Set("${proto_param}", list_${param});
+""")
+
+tmpl_append = string.Template("""\
+ list_${param}->Append${Type}(*it);
+""")
+
+tmpl_append_dict = string.Template("""\
+ list_${param}->Append(DevToolsProtocolHandlerImpl::ToValue(*it));
+""")
+
+tmpl_append_obj = string.Template("""\
+ list_${param}->Append(*it);
+""")
+
+tmpl_wrap_opt = string.Template("""\
+ if (${cond_name})
+ dict->Set${Type}("${proto_param}", ${var_name});
+""")
+
+tmpl_typename = string.Template("devtools::${domain}::${declared_name}")
+
+def Capitalize(s):
+ return s[:1].upper() + s[1:]
+
+def Decapitalize(s):
+ return s.lower()
+
+def Uncamelcase(s):
+ result = ""
+ for i, c in enumerate(s):
+ if c.isupper():
+ if (i > 0) and ((i < len(s)-1) and s[i+1].islower() or s[i-1].islower()):
+ result += "_"
+ result += c.lower()
+ else:
+ result += c
+ return result
+
+types = {}
+json_api = json.loads(open(input_json_path, "r").read())
+type_decls = []
+type_impls = []
+handler_methods = []
+handler_method_impls = []
+
+for json_domain in json_api["domains"]:
+ if "types" in json_domain:
+ for json_type in json_domain["types"]:
+ types["%s.%s" % (json_domain["domain"], json_type["id"])] = json_type
+
+def DeclareStruct(json_properties, mapping):
+ methods = []
+ fields = []
+ fields_init = []
+ method_impls = []
+ dchecks = []
+ wrap = []
+ for json_prop in json_properties:
+ prop_map = mapping.copy()
+ prop_map["proto_param"] = json_prop["name"]
+ prop_map["param"] = Uncamelcase(json_prop["name"])
+ prop_map["var_name"] = "src.%s_" % prop_map["param"]
+ prop_map["cond_name"] = "src.has_%s_" % prop_map["param"]
+ ResolveType(json_prop, prop_map)
+ prop_map["declared_name"] = mapping["declared_name"]
+ methods.append(tmpl_struct_setter.substitute(prop_map))
+ fields.append(tmpl_struct_field.substitute(prop_map))
+ fields_init.append(tmpl_struct_field_init.substitute(prop_map))
+ method_impls.append(tmpl_struct_setter_impl.substitute(prop_map))
+ if json_prop.get("optional"):
+ if param_map["Type"] in ["List", "Dictionary"]:
+ # TODO(vkuzkokov) Implement.
+ raise Exception(
+ "Optional array and object properties are not implemented")
+ wrap.append(tmpl_wrap_opt.substitute(prop_map))
+ else:
+ dchecks.append(tmpl_dcheck.substitute(prop_map));
+ if not "wrap" in prop_map:
+ raise Exception("Arrays of arrays are not implemented")
+ wrap.append(prop_map["wrap"])
+
+ type_decls.append(tmpl_struct.substitute(mapping,
+ methods = "".join(methods),
+ fields = "".join(fields)))
+ fields_init_str = ""
+ if len(fields_init) > 0:
+ fields_init_str = "\n : " + (",\n ".join(fields_init))
+ type_impls.append(tmpl_struct_impl.substitute(mapping,
+ fields = fields_init_str,
+ methods = "\n".join(method_impls)))
+ handler_methods.append(tmpl_to_value.substitute(mapping))
+ handler_method_impls.append(tmpl_to_value_impl.substitute(mapping,
+ dchecks = "".join(dchecks),
+ wrap = "".join(wrap)))
+
+def ResolveRef(json, mapping):
+ dot_pos = json["$ref"].find(".")
+ if dot_pos == -1:
+ domain_name = mapping["Domain"]
+ type_name = json["$ref"]
+ else:
+ domain_name = json["$ref"][:dot_pos]
+ type_name = json["$ref"][dot_pos + 1:]
+ json_type = types["%s.%s" % (domain_name, type_name)]
+ mapping["declared_name"] = Capitalize(type_name)
+ mapping["Domain"] = domain_name
+ mapping["domain"] = Decapitalize(domain_name)
+ mapping["param_type"] = tmpl_typename.substitute(mapping)
+ if json_type.get("enum"):
+ # TODO(vkuzkokov) Implement. Approximate template:
+ # namespace ${domain} { const char k${declared_name}${Value}; }
+ raise Exception("Named enumerations are not implemented")
+ ResolveType(json_type, mapping)
+ if not "___struct_declared" in json_type:
+ json_type["___struct_declared"] = True;
+ if (json_type.get("type") == "object") and ("properties" in json_type):
+ DeclareStruct(json_type["properties"], mapping)
+ else:
+ type_decls.append(tmpl_typedef.substitute(mapping))
+ mapping["param_type"] = tmpl_typename.substitute(mapping)
+
+def ResolveArray(json, mapping):
+ items_map = mapping.copy()
+ ResolveType(json["items"], items_map)
+ mapping["param_type"] = "std::vector<%s>" % items_map["param_type"]
+ mapping["Type"] = "List"
+ if "append" in items_map:
+ mapping["wrap"] = tmpl_wrap_list.substitute(mapping,
+ append = items_map["append"])
+ mapping["pass_type"] = "const %s&" % mapping["param_type"]
+ mapping["prep_req"] = tmpl_prep_req_list.substitute(mapping,
+ item_type = items_map["param_type"],
+ item_init = items_map["init"],
+ ItemType = items_map["Type"])
+ # TODO(vkuzkokov) mapping["append"]: template for array of arrays.
+
+def ResolveObject(json, mapping):
+ mapping["Type"] = "Dictionary"
+ if "properties" in json:
+ if not "declared_name" in mapping:
+ mapping["declared_name"] = ("%s%s" %
+ (mapping["Command"], Capitalize(mapping["proto_param"])))
+ mapping["param_type"] = tmpl_typename.substitute(mapping)
+ DeclareStruct(json["properties"], mapping)
+ mapping["append"] = tmpl_append_dict.substitute(mapping)
+ mapping["wrap"] = tmpl_wrap_dict.substitute(mapping)
+ mapping["pass_type"] = "const %s&" % mapping["param_type"]
+ else:
+ mapping["param_type"] = "base::DictionaryValue*"
+ mapping["append"] = tmpl_append_obj.substitute(mapping)
+ mapping["wrap"] = tmpl_wrap_obj.substitute(mapping)
+ mapping["pass_type"] = mapping["param_type"]
+
+def ResolvePrimitive(json, mapping):
+ jsonrpc_type = json["type"]
+ if jsonrpc_type == "boolean":
+ mapping["param_type"] = "bool"
+ mapping["Type"] = "Boolean"
+ mapping["init"] = " = false"
+ elif jsonrpc_type == "integer":
+ mapping["param_type"] = "int"
+ mapping["Type"] = "Integer"
+ mapping["init"] = " = 0"
+ elif jsonrpc_type == "number":
+ mapping["param_type"] = "double"
+ mapping["Type"] = "Double"
+ mapping["init"] = " = 0.0"
+ elif jsonrpc_type == "string":
+ mapping["param_type"] = "std::string"
+ mapping["pass_type"] = "const std::string&"
+ mapping["Type"] = "String"
+ if "enum" in json:
+ values = []
+ value_defs = []
+ if "declared_name" in mapping:
+ mapping["subdomain"] = Uncamelcase(mapping["declared_name"])
+ else:
+ mapping["subdomain"] = Uncamelcase(mapping["command"])
+ mapping["Param"] = Capitalize(mapping["proto_param"])
+ for enum_value in json["enum"]:
+ values.append(tmpl_enum_value.substitute(mapping,
+ Value = Capitalize(enum_value)))
+ value_defs.append(tmpl_enum_value_def.substitute(mapping,
+ value = enum_value,
+ Value = Capitalize(enum_value)))
+ type_decls.append(tmpl_enum.substitute(mapping,
+ values = "".join(values)))
+ type_impls.append(tmpl_enum.substitute(mapping,
+ values = "".join(value_defs)))
+ else:
+ raise Exception("Unknown type: %s" % json_type)
+ mapping["wrap"] = tmpl_wrap.substitute(mapping)
+ mapping["append"] = tmpl_append.substitute(mapping)
+ mapping["prep_req"] = tmpl_prep_req.substitute(mapping)
+ if jsonrpc_type != "string":
+ mapping["pass_type"] = mapping["param_type"]
+
+def ResolveType(json, mapping):
+ mapping["init"] = ""
+ if "$ref" in json:
+ ResolveRef(json, mapping)
+ elif "type" in json:
+ jsonrpc_type = json["type"]
+ if jsonrpc_type == "array":
+ ResolveArray(json, mapping)
+ elif jsonrpc_type == "object":
+ ResolveObject(json, mapping)
+ else:
+ ResolvePrimitive(json, mapping)
+ else:
+ raise Exception("Unknown type at %s.%s %s" %
+ (mapping["Domain"], mapping["command"], mapping["proto_param"]))
+
+setters = []
+friends = []
+fields = []
+
+includes = []
+fields_init = []
+
+for json_domain in json_api["domains"]:
+ domain_map = {}
+ domain_map["Domain"] = json_domain["domain"]
+ domain_map["domain"] = Decapitalize(json_domain["domain"])
+
+ initializations = []
+ client_methods = []
+ client_method_impls = []
+ domain_empty = True
+ domain_needs_client = False
+
+ if "commands" in json_domain:
+ for json_command in json_domain["commands"]:
+ if (not ("handlers" in json_command) or
+ not ("browser" in json_command["handlers"])):
+ continue
+ domain_empty = False
+
+ command_map = domain_map.copy()
+ command_map["command"] = json_command["name"]
+ command_map["Command"] = Capitalize(json_command["name"])
+
+ prep = []
+ args = []
+
+ if "parameters" in json_command:
+ for json_param in json_command["parameters"]:
+ param_map = command_map.copy()
+ param_map["proto_param"] = json_param["name"]
+ param_map["param"] = Uncamelcase(json_param["name"])
+ param_map["var_name"] = "in_%s" % param_map["param"]
+
+ ResolveType(json_param, param_map)
+ if len(prep) == 0:
+ prep.append(params_prep)
+ if json_param.get("optional"):
+ if param_map["Type"] in ["List", "Dictionary"]:
+ # TODO(vkuzkokov) Implement transformation of base::ListValue
+ # to std::vector and base::DictonaryValue to struct.
+ raise Exception(
+ "Optional array and object parameters are not implemented")
+ prep.append(tmpl_prep_opt.substitute(param_map))
+ args.append(tmpl_arg_opt.substitute(param_map))
+ else:
+ prep.append(param_map["prep_req"])
+ args.append(tmpl_arg_req.substitute(param_map))
+
+ if json_command.get("async"):
+ domain_needs_client = True
+ json_returns = []
+ if "returns" in json_command:
+ json_returns = json_command["returns"]
+ command_map["declared_name"] = "%sResponse" % command_map["Command"]
+ DeclareStruct(json_returns, command_map)
+ # TODO(vkuzkokov) Pass async callback instance similar to how
+ # InspectorBackendDispatcher does it. This, however, can work
+ # only if Blink and Chrome are in the same repo.
+ args.append("command")
+ handler_method_impls.append(
+ tmpl_callback_async_impl.substitute(command_map,
+ prep = "".join(prep),
+ args = "\n " + ",\n ".join(args)))
+ client_methods.append(tmpl_response.substitute(command_map))
+ client_method_impls.append(tmpl_response_impl.substitute(command_map))
+ else:
+ wrap = []
+ if "returns" in json_command:
+ for json_param in json_command["returns"]:
+ param_map = command_map.copy()
+ param_map["proto_param"] = json_param["name"]
+ param_map["param"] = Uncamelcase(json_param["name"])
+ param_map["var_name"] = "out_%s" % param_map["param"]
+
+ if json_param.get("optional"):
+ # TODO(vkuzkokov) Implement Optional<T> for value types.
+ raise Exception("Optional return values are not implemented")
+ ResolveType(json_param, param_map)
+ prep.append(tmpl_prep_output.substitute(param_map))
+ args.append(tmpl_arg_output.substitute(param_map))
+ if not "wrap" in param_map:
+ raise Exception("Arrays of arrays are not implemented")
+ wrap.append(param_map["wrap"])
+
+ args_str = ""
+ if len(args) > 0:
+ args_str = "\n " + ",\n ".join(args)
+ handler_method_impls.append(tmpl_callback_impl.substitute(command_map,
+ prep = "".join(prep),
+ args = args_str,
+ wrap = "".join(wrap)))
+
+ initializations.append(tmpl_register.substitute(command_map))
+ handler_methods.append(tmpl_callback.substitute(command_map))
+
+ if "events" in json_domain:
+ for json_event in json_domain["events"]:
+ if (not ("handlers" in json_event) or
+ not ("browser" in json_event["handlers"])):
+ continue
+ domain_empty = False
+ domain_needs_client = True
+
+ event_map = domain_map.copy()
+ event_map["command"] = json_event["name"]
+ event_map["Command"] = Capitalize(json_event["name"])
+
+ json_parameters = []
+ if "parameters" in json_event:
+ json_parameters = json_event["parameters"]
+ event_map["declared_name"] = "%sParams" % event_map["Command"]
+ DeclareStruct(json_parameters, event_map);
+
+ client_methods.append(tmpl_event.substitute(event_map))
+ client_method_impls.append(tmpl_event_impl.substitute(event_map))
+
+ if domain_empty:
+ continue
+ type_decls.append(tmpl_handler.substitute(domain_map))
+ setters.append(tmpl_setter.substitute(domain_map))
+ fields.append(tmpl_field.substitute(domain_map))
+ includes.append(tmpl_include.substitute(domain_map))
+ fields_init.append(tmpl_field_init.substitute(domain_map))
+ if domain_needs_client:
+ type_decls.append(tmpl_client.substitute(domain_map,
+ methods = "".join(client_methods)))
+ friends.append(tmpl_friend.substitute(domain_map))
+ initializations.append(tmpl_init_client.substitute(domain_map))
+ type_impls.append(tmpl_client_impl.substitute(domain_map,
+ methods = "\n".join(client_method_impls)))
+ handler_method_impls.append(tmpl_setter_impl.substitute(domain_map,
+ initializations = "".join(initializations)))
+
+
+output_h_file = open(output_h_path, "w")
+output_cc_file = open(output_cc_path, "w")
+
+output_h_file.write(template_h.substitute({},
+ types = "\n".join(type_decls),
+ setters = "".join(setters),
+ friends = "".join(friends),
+ methods = "".join(handler_methods),
+ fields = "".join(fields)))
+output_h_file.close()
+
+output_cc_file.write(template_cc.substitute({},
+ includes = "".join(sorted(includes)),
+ fields_init = ",\n ".join(fields_init),
+ methods = "\n".join(handler_method_impls),
+ types = "\n".join(type_impls)))
+output_cc_file.close()
diff --git a/chromium/content/browser/devtools/protocol/dom_handler.cc b/chromium/content/browser/devtools/protocol/dom_handler.cc
new file mode 100644
index 00000000000..9ddf4092b52
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/dom_handler.cc
@@ -0,0 +1,47 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/dom_handler.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+
+namespace content {
+namespace devtools {
+namespace dom {
+
+typedef DevToolsProtocolClient::Response Response;
+
+DOMHandler::DOMHandler() : host_(nullptr) {
+}
+
+DOMHandler::~DOMHandler() {
+}
+
+void DOMHandler::SetRenderViewHost(RenderViewHostImpl* host) {
+ host_ = host;
+}
+
+Response DOMHandler::SetFileInputFiles(NodeId node_id,
+ const std::vector<std::string>& files) {
+ if (host_) {
+ for (const auto& file : files) {
+#if defined(OS_WIN)
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
+ host_->GetProcess()->GetID(),
+ base::FilePath(base::UTF8ToUTF16(file)));
+#else
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
+ host_->GetProcess()->GetID(),
+ base::FilePath(file));
+#endif // OS_WIN
+ }
+ }
+ return Response::FallThrough();
+}
+
+} // namespace dom
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/dom_handler.h b/chromium/content/browser/devtools/protocol/dom_handler.h
new file mode 100644
index 00000000000..d2b20e24e0c
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/dom_handler.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DOM_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DOM_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+namespace content {
+
+class RenderViewHostImpl;
+
+namespace devtools {
+namespace dom {
+
+class DOMHandler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ DOMHandler();
+ virtual ~DOMHandler();
+
+ void SetRenderViewHost(RenderViewHostImpl* host);
+
+ Response SetFileInputFiles(NodeId node_id,
+ const std::vector<std::string>& files);
+
+ private:
+ RenderViewHostImpl* host_;
+ DISALLOW_COPY_AND_ASSIGN(DOMHandler);
+};
+
+} // namespace dom
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DOM_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
new file mode 100644
index 00000000000..05cff6195a1
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -0,0 +1,111 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/input_handler.h"
+
+#include "base/strings/stringprintf.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+namespace devtools {
+namespace input {
+
+typedef DevToolsProtocolClient::Response Response;
+
+InputHandler::InputHandler()
+ : host_(NULL) {
+}
+
+InputHandler::~InputHandler() {
+}
+
+void InputHandler::SetRenderViewHost(RenderViewHostImpl* host) {
+ host_ = host;
+}
+
+Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
+ int x,
+ int y,
+ double timestamp,
+ const std::string& button,
+ double* delta_x,
+ double* delta_y,
+ int* modifiers,
+ int* click_count) {
+ blink::WebMouseWheelEvent wheel_event;
+ blink::WebMouseEvent mouse_event;
+ blink::WebMouseEvent* event = &mouse_event;
+
+ if (type == emulate_touch_from_mouse_event::kTypeMousePressed) {
+ event->type = blink::WebInputEvent::MouseDown;
+ } else if (type == emulate_touch_from_mouse_event::kTypeMouseReleased) {
+ event->type = blink::WebInputEvent::MouseUp;
+ } else if (type == emulate_touch_from_mouse_event::kTypeMouseMoved) {
+ event->type = blink::WebInputEvent::MouseMove;
+ } else if (type == emulate_touch_from_mouse_event::kTypeMouseWheel) {
+ if (!delta_x || !delta_y) {
+ return Response::InvalidParams(
+ "'deltaX' and 'deltaY' are expected for mouseWheel event");
+ }
+ wheel_event.deltaX = static_cast<float>(*delta_x);
+ wheel_event.deltaY = static_cast<float>(*delta_y);
+ event = &wheel_event;
+ event->type = blink::WebInputEvent::MouseWheel;
+ } else {
+ return Response::InvalidParams(
+ base::StringPrintf("Unexpected event type '%s'", type.c_str()));
+ }
+
+ if (modifiers) {
+ if (*modifiers & 1)
+ event->modifiers |= blink::WebInputEvent::AltKey;
+ if (*modifiers & 2)
+ event->modifiers |= blink::WebInputEvent::ControlKey;
+ if (*modifiers & 4)
+ event->modifiers |= blink::WebInputEvent::MetaKey;
+ if (*modifiers & 8)
+ event->modifiers |= blink::WebInputEvent::ShiftKey;
+ }
+
+ event->timeStampSeconds = timestamp;
+ event->x = x;
+ event->y = y;
+ event->windowX = x;
+ event->windowY = y;
+ event->globalX = x;
+ event->globalY = y;
+
+ if (click_count)
+ event->clickCount = *click_count;
+
+ if (button == emulate_touch_from_mouse_event::kButtonNone) {
+ event->button = blink::WebMouseEvent::ButtonNone;
+ } else if (button == emulate_touch_from_mouse_event::kButtonLeft) {
+ event->button = blink::WebMouseEvent::ButtonLeft;
+ event->modifiers |= blink::WebInputEvent::LeftButtonDown;
+ } else if (button == emulate_touch_from_mouse_event::kButtonMiddle) {
+ event->button = blink::WebMouseEvent::ButtonMiddle;
+ event->modifiers |= blink::WebInputEvent::MiddleButtonDown;
+ } else if (button == emulate_touch_from_mouse_event::kButtonRight) {
+ event->button = blink::WebMouseEvent::ButtonRight;
+ event->modifiers |= blink::WebInputEvent::RightButtonDown;
+ } else {
+ return Response::InvalidParams(
+ base::StringPrintf("Unexpected mouse button '%s'", button.c_str()));
+ }
+
+ if (!host_)
+ return Response::ServerError("Could not connect to view");
+
+ if (event->type == blink::WebInputEvent::MouseWheel)
+ host_->ForwardWheelEvent(wheel_event);
+ else
+ host_->ForwardMouseEvent(mouse_event);
+ return Response::OK();
+}
+
+} // namespace input
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/input_handler.h b/chromium/content/browser/devtools/protocol/input_handler.h
new file mode 100644
index 00000000000..1a85b2a48c8
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/input_handler.h
@@ -0,0 +1,46 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INPUT_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INPUT_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+namespace content {
+
+class RenderViewHostImpl;
+
+namespace devtools {
+namespace input {
+
+class InputHandler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ InputHandler();
+ virtual ~InputHandler();
+
+ void SetRenderViewHost(RenderViewHostImpl* host);
+
+ Response EmulateTouchFromMouseEvent(const std::string& type,
+ int x,
+ int y,
+ double timestamp,
+ const std::string& button,
+ double* delta_x,
+ double* delta_y,
+ int* modifiers,
+ int* click_count);
+
+ private:
+ RenderViewHostImpl* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputHandler);
+};
+
+} // namespace inpue
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INPUT_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.cc b/chromium/content/browser/devtools/protocol/inspector_handler.cc
new file mode 100644
index 00000000000..4dbbd045449
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/inspector_handler.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/inspector_handler.h"
+
+namespace content {
+namespace devtools {
+namespace inspector {
+
+InspectorHandler::InspectorHandler() {
+}
+
+InspectorHandler::~InspectorHandler() {
+}
+
+void InspectorHandler::SetClient(scoped_ptr<Client> client) {
+ client_.swap(client);
+}
+
+} // namespace inspector
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.h b/chromium/content/browser/devtools/protocol/inspector_handler.h
new file mode 100644
index 00000000000..d6b449e8d11
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/inspector_handler.h
@@ -0,0 +1,31 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INSPECTOR_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INSPECTOR_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+namespace content {
+namespace devtools {
+namespace inspector {
+
+class InspectorHandler {
+ public:
+ InspectorHandler();
+ virtual ~InspectorHandler();
+
+ void SetClient(scoped_ptr<Client> client);
+
+ private:
+ scoped_ptr<Client> client_;
+
+ DISALLOW_COPY_AND_ASSIGN(InspectorHandler);
+};
+
+} // namespace inspector
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_INSPECTOR_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
new file mode 100644
index 00000000000..d5b8f77a867
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/network_handler.h"
+
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+
+namespace content {
+namespace devtools {
+namespace network {
+
+typedef DevToolsProtocolClient::Response Response;
+
+NetworkHandler::NetworkHandler() : host_(nullptr) {
+}
+
+NetworkHandler::~NetworkHandler() {
+}
+
+void NetworkHandler::SetRenderViewHost(RenderViewHost* host) {
+ host_ = host;
+}
+
+Response NetworkHandler::ClearBrowserCache() {
+ if (host_)
+ GetContentClient()->browser()->ClearCache(host_);
+ return Response::OK();
+}
+
+Response NetworkHandler::ClearBrowserCookies() {
+ if (host_)
+ GetContentClient()->browser()->ClearCookies(host_);
+ return Response::OK();
+}
+
+Response NetworkHandler::CanEmulateNetworkConditions(bool* result) {
+ *result = false;
+ return Response::OK();
+}
+
+Response NetworkHandler::EmulateNetworkConditions(bool offline,
+ double latency,
+ double download_throughput,
+ double upload_throughput) {
+ return Response::FallThrough();
+}
+
+} // namespace dom
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/network_handler.h b/chromium/content/browser/devtools/protocol/network_handler.h
new file mode 100644
index 00000000000..c045a86f2de
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/network_handler.h
@@ -0,0 +1,45 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+namespace content {
+
+class RenderViewHost;
+
+namespace devtools {
+namespace network {
+
+class NetworkHandler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ NetworkHandler();
+ virtual ~NetworkHandler();
+
+ void SetRenderViewHost(RenderViewHost* host);
+
+ Response ClearBrowserCache();
+ Response ClearBrowserCookies();
+ Response CanEmulateNetworkConditions(bool* result);
+
+ Response EmulateNetworkConditions(bool offline,
+ double latency,
+ double download_throughput,
+ double upload_throughput);
+
+ private:
+ RenderViewHost* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkHandler);
+};
+
+} // namespace network
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
new file mode 100644
index 00000000000..b336d8cb6c8
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -0,0 +1,615 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/page_handler.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/devtools/protocol/color_picker.h"
+#include "content/browser/devtools/protocol/usage_and_quota_query.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/javascript_dialog_manager.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/referrer.h"
+#include "content/public/common/url_constants.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/page_transition_types.h"
+#include "ui/gfx/codec/jpeg_codec.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/snapshot/snapshot.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace devtools {
+namespace page {
+
+namespace {
+
+static const char kPng[] = "png";
+static const char kJpeg[] = "jpeg";
+static int kDefaultScreenshotQuality = 80;
+static int kFrameRateThresholdMs = 100;
+static int kCaptureRetryLimit = 2;
+
+void QueryUsageAndQuotaCompletedOnIOThread(
+ const UsageAndQuotaQuery::Callback& callback,
+ scoped_ptr<QueryUsageAndQuotaResponse> response) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, base::Passed(&response)));
+}
+
+void QueryUsageAndQuotaOnIOThread(
+ scoped_refptr<storage::QuotaManager> quota_manager,
+ const GURL& security_origin,
+ const UsageAndQuotaQuery::Callback& callback) {
+ new UsageAndQuotaQuery(
+ quota_manager,
+ security_origin,
+ base::Bind(&QueryUsageAndQuotaCompletedOnIOThread,
+ callback));
+}
+
+} // namespace
+
+typedef DevToolsProtocolClient::Response Response;
+
+PageHandler::PageHandler()
+ : enabled_(false),
+ touch_emulation_enabled_(false),
+ screencast_enabled_(false),
+ screencast_quality_(kDefaultScreenshotQuality),
+ screencast_max_width_(-1),
+ screencast_max_height_(-1),
+ capture_retry_count_(0),
+ has_last_compositor_frame_metadata_(false),
+ color_picker_(new ColorPicker(base::Bind(
+ &PageHandler::OnColorPicked, base::Unretained(this)))),
+ host_(nullptr),
+ weak_factory_(this) {
+}
+
+PageHandler::~PageHandler() {
+}
+
+void PageHandler::SetRenderViewHost(RenderViewHostImpl* host) {
+ if (host_ == host)
+ return;
+
+ color_picker_->SetRenderViewHost(host);
+ host_ = host;
+ UpdateTouchEventEmulationState();
+}
+
+void PageHandler::SetClient(scoped_ptr<Client> client) {
+ client_.swap(client);
+}
+
+void PageHandler::Detached() {
+ Disable();
+}
+
+void PageHandler::OnSwapCompositorFrame(
+ const cc::CompositorFrameMetadata& frame_metadata) {
+ last_compositor_frame_metadata_ = frame_metadata;
+ has_last_compositor_frame_metadata_ = true;
+
+ if (screencast_enabled_)
+ InnerSwapCompositorFrame();
+ color_picker_->OnSwapCompositorFrame();
+}
+
+void PageHandler::OnVisibilityChanged(bool visible) {
+ if (!screencast_enabled_)
+ return;
+ NotifyScreencastVisibility(visible);
+}
+
+void PageHandler::DidAttachInterstitialPage() {
+ if (!enabled_)
+ return;
+ InterstitialShownParams params;
+ client_->InterstitialShown(params);
+}
+
+void PageHandler::DidDetachInterstitialPage() {
+ if (!enabled_)
+ return;
+ InterstitialHiddenParams params;
+ client_->InterstitialHidden(params);
+}
+
+Response PageHandler::Enable() {
+ enabled_ = true;
+ return Response::FallThrough();
+}
+
+Response PageHandler::Disable() {
+ enabled_ = false;
+ touch_emulation_enabled_ = false;
+ screencast_enabled_ = false;
+ UpdateTouchEventEmulationState();
+ color_picker_->SetEnabled(false);
+ return Response::FallThrough();
+}
+
+Response PageHandler::Reload(const bool* ignoreCache,
+ const std::string* script_to_evaluate_on_load,
+ const std::string* script_preprocessor) {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContents* web_contents = WebContents::FromRenderViewHost(host_);
+ if (!web_contents)
+ return Response::InternalError("No WebContents to reload");
+
+ // Handle in browser only if it is crashed.
+ if (!web_contents->IsCrashed())
+ return Response::FallThrough();
+
+ web_contents->GetController().Reload(false);
+ return Response::OK();
+}
+
+Response PageHandler::Navigate(const std::string& url,
+ FrameId* frame_id) {
+ GURL gurl(url);
+ if (!gurl.is_valid())
+ return Response::InternalError("Cannot navigate to invalid URL");
+
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContents* web_contents = WebContents::FromRenderViewHost(host_);
+ if (!web_contents)
+ return Response::InternalError("No WebContents to navigate");
+
+ web_contents->GetController()
+ .LoadURL(gurl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ return Response::FallThrough();
+}
+
+Response PageHandler::GetNavigationHistory(
+ int* current_index,
+ std::vector<NavigationEntry>* entries) {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContents* web_contents = WebContents::FromRenderViewHost(host_);
+ if (!web_contents)
+ return Response::InternalError("No WebContents to navigate");
+
+ NavigationController& controller = web_contents->GetController();
+ *current_index = controller.GetCurrentEntryIndex();
+ for (int i = 0; i != controller.GetEntryCount(); ++i) {
+ NavigationEntry entry;
+ entry.set_id(controller.GetEntryAtIndex(i)->GetUniqueID());
+ entry.set_url(controller.GetEntryAtIndex(i)->GetURL().spec());
+ entry.set_title(
+ base::UTF16ToUTF8(controller.GetEntryAtIndex(i)->GetTitle()));
+ entries->push_back(entry);
+ }
+ return Response::OK();
+}
+
+Response PageHandler::NavigateToHistoryEntry(int entry_id) {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContents* web_contents = WebContents::FromRenderViewHost(host_);
+ if (!web_contents)
+ return Response::InternalError("No WebContents to navigate");
+
+ NavigationController& controller = web_contents->GetController();
+ for (int i = 0; i != controller.GetEntryCount(); ++i) {
+ if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) {
+ controller.GoToIndex(i);
+ return Response::OK();
+ }
+ }
+
+ return Response::InvalidParams("No entry with passed id");
+}
+
+Response PageHandler::SetGeolocationOverride(double* latitude,
+ double* longitude,
+ double* accuracy) {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderViewHost(host_));
+ if (!web_contents)
+ return Response::InternalError("No WebContents to override");
+
+ GeolocationServiceContext* geolocation_context =
+ web_contents->GetGeolocationServiceContext();
+ scoped_ptr<Geoposition> geoposition(new Geoposition());
+ if (latitude && longitude && accuracy) {
+ geoposition->latitude = *latitude;
+ geoposition->longitude = *longitude;
+ geoposition->accuracy = *accuracy;
+ geoposition->timestamp = base::Time::Now();
+ if (!geoposition->Validate()) {
+ return Response::InternalError("Invalid geolocation");
+ }
+ } else {
+ geoposition->error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
+ }
+ geolocation_context->SetOverride(geoposition.Pass());
+ return Response::OK();
+}
+
+Response PageHandler::ClearGeolocationOverride() {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderViewHost(host_));
+ if (!web_contents)
+ return Response::InternalError("No WebContents to override");
+
+ GeolocationServiceContext* geolocation_context =
+ web_contents->GetGeolocationServiceContext();
+ geolocation_context->ClearOverride();
+ return Response::OK();
+}
+
+Response PageHandler::SetTouchEmulationEnabled(bool enabled) {
+ touch_emulation_enabled_ = enabled;
+ UpdateTouchEventEmulationState();
+ return Response::FallThrough();
+}
+
+Response PageHandler::SetTouchEmulationEnabled(
+ bool enabled, const std::string* configuration) {
+ touch_emulation_enabled_ = enabled;
+ touch_emulation_configuration_ =
+ configuration ? *configuration : std::string();
+ UpdateTouchEventEmulationState();
+ return Response::FallThrough();
+}
+
+scoped_refptr<DevToolsProtocol::Response> PageHandler::CaptureScreenshot(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ if (!host_ || !host_->GetView())
+ return command->InternalErrorResponse("Could not connect to view");
+
+ host_->GetSnapshotFromBrowser(
+ base::Bind(&PageHandler::ScreenshotCaptured,
+ weak_factory_.GetWeakPtr(), command));
+ return command->AsyncResponsePromise();
+}
+
+Response PageHandler::CanScreencast(bool* result) {
+#if defined(OS_ANDROID)
+ *result = true;
+#else
+ *result = false;
+#endif // defined(OS_ANDROID)
+ return Response::OK();
+}
+
+Response PageHandler::CanEmulate(bool* result) {
+#if defined(OS_ANDROID)
+ *result = false;
+#else
+ if (host_) {
+ if (WebContents* web_contents = WebContents::FromRenderViewHost(host_)) {
+ *result = !web_contents->GetVisibleURL().SchemeIs(kChromeDevToolsScheme);
+ } else {
+ *result = true;
+ }
+ } else {
+ *result = true;
+ }
+#endif // defined(OS_ANDROID)
+ return Response::OK();
+}
+
+Response PageHandler::StartScreencast(const std::string* format,
+ const int* quality,
+ const int* max_width,
+ const int* max_height) {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ screencast_enabled_ = true;
+ screencast_format_ = format ? *format : kPng;
+ screencast_quality_ = quality ? *quality : kDefaultScreenshotQuality;
+ if (screencast_quality_ < 0 || screencast_quality_ > 100)
+ screencast_quality_ = kDefaultScreenshotQuality;
+ screencast_max_width_ = max_width ? *max_width : -1;
+ screencast_max_height_ = max_height ? *max_height : -1;
+
+ UpdateTouchEventEmulationState();
+ bool visible = !host_->is_hidden();
+ NotifyScreencastVisibility(visible);
+ if (visible) {
+ if (has_last_compositor_frame_metadata_)
+ InnerSwapCompositorFrame();
+ else
+ host_->Send(new ViewMsg_ForceRedraw(host_->GetRoutingID(), 0));
+ }
+ return Response::FallThrough();
+}
+
+Response PageHandler::StopScreencast() {
+ last_frame_time_ = base::TimeTicks();
+ screencast_enabled_ = false;
+ UpdateTouchEventEmulationState();
+ return Response::FallThrough();
+}
+
+Response PageHandler::HandleJavaScriptDialog(bool accept,
+ const std::string* prompt_text) {
+ base::string16 prompt_override;
+ if (prompt_text)
+ prompt_override = base::UTF8ToUTF16(*prompt_text);
+
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ WebContents* web_contents = WebContents::FromRenderViewHost(host_);
+ if (!web_contents)
+ return Response::InternalError("No JavaScript dialog to handle");
+
+ JavaScriptDialogManager* manager =
+ web_contents->GetDelegate()->GetJavaScriptDialogManager();
+ if (manager && manager->HandleJavaScriptDialog(
+ web_contents, accept, prompt_text ? &prompt_override : nullptr)) {
+ return Response::OK();
+ }
+
+ return Response::InternalError("Could not handle JavaScript dialog");
+}
+
+scoped_refptr<DevToolsProtocol::Response> PageHandler::QueryUsageAndQuota(
+ const std::string& security_origin,
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ if (!host_)
+ return command->InternalErrorResponse("Could not connect to view");
+
+ scoped_refptr<storage::QuotaManager> quota_manager =
+ host_->GetProcess()->GetStoragePartition()->GetQuotaManager();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&QueryUsageAndQuotaOnIOThread,
+ quota_manager,
+ GURL(security_origin),
+ base::Bind(&PageHandler::QueryUsageAndQuotaCompleted,
+ weak_factory_.GetWeakPtr(),
+ command)));
+
+ return command->AsyncResponsePromise();
+}
+
+Response PageHandler::SetColorPickerEnabled(bool enabled) {
+ if (!host_)
+ return Response::InternalError("Could not connect to view");
+
+ color_picker_->SetEnabled(enabled);
+ return Response::OK();
+}
+
+void PageHandler::UpdateTouchEventEmulationState() {
+ if (!host_)
+ return;
+ bool enabled = touch_emulation_enabled_ || screencast_enabled_;
+ // TODO(dgozman): pass |touch_emulation_configuration_| once supported.
+ host_->SetTouchEventEmulationEnabled(enabled);
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderViewHost(host_));
+ if (web_contents)
+ web_contents->SetForceDisableOverscrollContent(enabled);
+}
+
+void PageHandler::NotifyScreencastVisibility(bool visible) {
+ if (visible)
+ capture_retry_count_ = kCaptureRetryLimit;
+ ScreencastVisibilityChangedParams params;
+ params.set_visible(visible);
+ client_->ScreencastVisibilityChanged(params);
+}
+
+void PageHandler::InnerSwapCompositorFrame() {
+ if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() <
+ kFrameRateThresholdMs) {
+ return;
+ }
+
+ if (!host_ || !host_->GetView())
+ return;
+
+ last_frame_time_ = base::TimeTicks::Now();
+
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ host_->GetView());
+ // TODO(vkuzkokov): do not use previous frame metadata.
+ cc::CompositorFrameMetadata& metadata = last_compositor_frame_metadata_;
+
+ gfx::SizeF viewport_size_dip = gfx::ScaleSize(
+ metadata.scrollable_viewport_size, metadata.page_scale_factor);
+ gfx::SizeF screen_size_dip = gfx::ScaleSize(view->GetPhysicalBackingSize(),
+ 1 / metadata.device_scale_factor);
+
+ blink::WebScreenInfo screen_info;
+ view->GetScreenInfo(&screen_info);
+ double device_scale_factor = screen_info.deviceScaleFactor;
+ double scale = 1;
+
+ if (screencast_max_width_ > 0) {
+ double max_width_dip = screencast_max_width_ / device_scale_factor;
+ scale = std::min(scale, max_width_dip / screen_size_dip.width());
+ }
+ if (screencast_max_height_ > 0) {
+ double max_height_dip = screencast_max_height_ / device_scale_factor;
+ scale = std::min(scale, max_height_dip / screen_size_dip.height());
+ }
+
+ if (scale <= 0)
+ scale = 0.1;
+
+ gfx::Size snapshot_size_dip(gfx::ToRoundedSize(
+ gfx::ScaleSize(viewport_size_dip, scale)));
+
+ if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) {
+ gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip));
+ view->CopyFromCompositingSurface(
+ viewport_bounds_dip,
+ snapshot_size_dip,
+ base::Bind(&PageHandler::ScreencastFrameCaptured,
+ weak_factory_.GetWeakPtr(),
+ screencast_format_,
+ screencast_quality_,
+ last_compositor_frame_metadata_),
+ kN32_SkColorType);
+ }
+}
+
+void PageHandler::ScreencastFrameCaptured(
+ const std::string& format,
+ int quality,
+ const cc::CompositorFrameMetadata& metadata,
+ bool success,
+ const SkBitmap& bitmap) {
+ if (!success) {
+ if (capture_retry_count_) {
+ --capture_retry_count_;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&PageHandler::InnerSwapCompositorFrame,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kFrameRateThresholdMs));
+ }
+ return;
+ }
+
+ std::vector<unsigned char> data;
+ SkAutoLockPixels lock_image(bitmap);
+ bool encoded;
+ if (format == kPng) {
+ encoded = gfx::PNGCodec::Encode(
+ reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
+ gfx::PNGCodec::FORMAT_SkBitmap,
+ gfx::Size(bitmap.width(), bitmap.height()),
+ bitmap.width() * bitmap.bytesPerPixel(),
+ false, std::vector<gfx::PNGCodec::Comment>(), &data);
+ } else if (format == kJpeg) {
+ encoded = gfx::JPEGCodec::Encode(
+ reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
+ gfx::JPEGCodec::FORMAT_SkBitmap,
+ bitmap.width(),
+ bitmap.height(),
+ bitmap.width() * bitmap.bytesPerPixel(),
+ quality, &data);
+ } else {
+ encoded = false;
+ }
+
+ if (!encoded)
+ return;
+
+ std::string base_64_data;
+ base::Base64Encode(
+ base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()),
+ &base_64_data);
+
+ ScreencastFrameMetadata param_metadata;
+ // Consider metadata empty in case it has no device scale factor.
+ if (metadata.device_scale_factor != 0 && host_) {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ host_->GetView());
+ if (!view)
+ return;
+
+ gfx::SizeF viewport_size_dip = gfx::ScaleSize(
+ metadata.scrollable_viewport_size, metadata.page_scale_factor);
+ gfx::SizeF screen_size_dip = gfx::ScaleSize(
+ view->GetPhysicalBackingSize(), 1 / metadata.device_scale_factor);
+
+ param_metadata.set_device_scale_factor(metadata.device_scale_factor);
+ param_metadata.set_page_scale_factor(metadata.page_scale_factor);
+ param_metadata.set_page_scale_factor_min(metadata.min_page_scale_factor);
+ param_metadata.set_page_scale_factor_max(metadata.max_page_scale_factor);
+ param_metadata.set_offset_top(
+ metadata.location_bar_content_translation.y());
+ param_metadata.set_offset_bottom(screen_size_dip.height() -
+ metadata.location_bar_content_translation.y() -
+ viewport_size_dip.height());
+ param_metadata.set_device_width(screen_size_dip.width());
+ param_metadata.set_device_height(screen_size_dip.height());
+ param_metadata.set_scroll_offset_x(metadata.root_scroll_offset.x());
+ param_metadata.set_scroll_offset_y(metadata.root_scroll_offset.y());
+
+ devtools::dom::Rect viewport;
+ viewport.set_x(metadata.root_scroll_offset.x());
+ viewport.set_y(metadata.root_scroll_offset.y());
+ viewport.set_width(metadata.scrollable_viewport_size.width());
+ viewport.set_height(metadata.scrollable_viewport_size.height());
+ param_metadata.set_viewport(viewport);
+ }
+
+ ScreencastFrameParams params;
+ params.set_data(base_64_data);
+ params.set_metadata(param_metadata);
+ client_->ScreencastFrame(params);
+}
+
+void PageHandler::ScreenshotCaptured(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const unsigned char* png_data,
+ size_t png_size) {
+ if (!png_data || !png_size) {
+ client_->SendInternalErrorResponse(command,
+ "Unable to capture screenshot");
+ return;
+ }
+
+ std::string base_64_data;
+ base::Base64Encode(
+ base::StringPiece(reinterpret_cast<const char*>(png_data), png_size),
+ &base_64_data);
+
+ CaptureScreenshotResponse response;
+ response.set_data(base_64_data);
+ client_->SendCaptureScreenshotResponse(command, response);
+}
+
+void PageHandler::OnColorPicked(int r, int g, int b, int a) {
+ dom::RGBA color;
+ color.set_r(r);
+ color.set_g(g);
+ color.set_b(b);
+ color.set_a(a);
+ ColorPickedParams params;
+ params.set_color(color);
+ client_->ColorPicked(params);
+}
+
+void PageHandler::QueryUsageAndQuotaCompleted(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ scoped_ptr<QueryUsageAndQuotaResponse> response_data) {
+ client_->SendQueryUsageAndQuotaResponse(command, *response_data);
+}
+
+} // namespace page
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
new file mode 100644
index 00000000000..913655d7b06
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -0,0 +1,135 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "cc/output/compositor_frame_metadata.h"
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+class SkBitmap;
+
+namespace content {
+
+class RenderViewHostImpl;
+
+namespace devtools {
+namespace page {
+
+class ColorPicker;
+
+class PageHandler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ PageHandler();
+ virtual ~PageHandler();
+
+ void SetRenderViewHost(RenderViewHostImpl* host);
+ void SetClient(scoped_ptr<Client> client);
+ void Detached();
+ void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata);
+ void OnVisibilityChanged(bool visible);
+ void DidAttachInterstitialPage();
+ void DidDetachInterstitialPage();
+
+ Response Enable();
+ Response Disable();
+
+ Response Reload(const bool* ignoreCache,
+ const std::string* script_to_evaluate_on_load,
+ const std::string* script_preprocessor);
+
+ Response Navigate(const std::string& url, FrameId* frame_id);
+
+ Response GetNavigationHistory(int* current_index,
+ std::vector<NavigationEntry>* entries);
+
+ Response NavigateToHistoryEntry(int entry_id);
+
+ Response SetGeolocationOverride(double* latitude,
+ double* longitude,
+ double* accuracy);
+
+ Response ClearGeolocationOverride();
+
+ Response SetTouchEmulationEnabled(bool enabled);
+ Response SetTouchEmulationEnabled(bool enabled,
+ const std::string* configuration);
+
+ scoped_refptr<DevToolsProtocol::Response> CaptureScreenshot(
+ scoped_refptr<DevToolsProtocol::Command> command);
+
+ Response CanScreencast(bool* result);
+ Response CanEmulate(bool* result);
+
+ Response StartScreencast(const std::string* format,
+ const int* quality,
+ const int* max_width,
+ const int* max_height);
+
+ Response StopScreencast();
+ Response HandleJavaScriptDialog(bool accept, const std::string* prompt_text);
+
+ scoped_refptr<DevToolsProtocol::Response> QueryUsageAndQuota(
+ const std::string& security_origin,
+ scoped_refptr<DevToolsProtocol::Command> command);
+
+ Response SetColorPickerEnabled(bool enabled);
+
+ private:
+ void UpdateTouchEventEmulationState();
+
+ void NotifyScreencastVisibility(bool visible);
+ void InnerSwapCompositorFrame();
+ void ScreencastFrameCaptured(
+ const std::string& format,
+ int quality,
+ const cc::CompositorFrameMetadata& metadata,
+ bool success,
+ const SkBitmap& bitmap);
+
+ void ScreenshotCaptured(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const unsigned char* png_data,
+ size_t png_size);
+
+ void OnColorPicked(int r, int g, int b, int a);
+
+ void QueryUsageAndQuotaCompleted(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ scoped_ptr<QueryUsageAndQuotaResponse> response);
+
+ bool enabled_;
+ bool touch_emulation_enabled_;
+ std::string touch_emulation_configuration_;
+
+ bool screencast_enabled_;
+ std::string screencast_format_;
+ int screencast_quality_;
+ int screencast_max_width_;
+ int screencast_max_height_;
+ int capture_retry_count_;
+ bool has_last_compositor_frame_metadata_;
+ cc::CompositorFrameMetadata last_compositor_frame_metadata_;
+ base::TimeTicks last_frame_time_;
+
+ scoped_ptr<ColorPicker> color_picker_;
+
+ RenderViewHostImpl* host_;
+ scoped_ptr<Client> client_;
+ base::WeakPtrFactory<PageHandler> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageHandler);
+};
+
+} // namespace page
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/power_handler.cc b/chromium/content/browser/devtools/protocol/power_handler.cc
new file mode 100644
index 00000000000..c121ac3cf2d
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/power_handler.cc
@@ -0,0 +1,86 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/power_handler.h"
+
+#include "content/browser/power_profiler/power_profiler_service.h"
+
+namespace content {
+namespace devtools {
+namespace power {
+
+typedef DevToolsProtocolClient::Response Response;
+
+PowerHandler::PowerHandler() : enabled_(false) {
+}
+
+PowerHandler::~PowerHandler() {
+ if (enabled_)
+ PowerProfilerService::GetInstance()->RemoveObserver(this);
+}
+
+void PowerHandler::SetClient(scoped_ptr<Client> client) {
+ client_.swap(client);
+}
+
+void PowerHandler::OnPowerEvent(const PowerEventVector& events) {
+ std::vector<PowerEvent> event_list;
+ for (const auto& event : events) {
+ PowerEvent event_body;
+ DCHECK(event.type < content::PowerEvent::ID_COUNT);
+ event_body.set_type(kPowerTypeNames[event.type]);
+ // Use internal value to be consistent with Blink's
+ // monotonicallyIncreasingTime.
+ event_body.set_timestamp(event.time.ToInternalValue() /
+ static_cast<double>(base::Time::kMicrosecondsPerMillisecond));
+ event_body.set_value(event.value);
+ event_list.push_back(event_body);
+ }
+ DataAvailableParams params;
+ params.set_value(event_list);
+ client_->DataAvailable(params);
+}
+
+void PowerHandler::Detached() {
+ if (enabled_) {
+ PowerProfilerService::GetInstance()->RemoveObserver(this);
+ enabled_ = false;
+ }
+}
+
+Response PowerHandler::Start() {
+ if (!PowerProfilerService::GetInstance()->IsAvailable())
+ return Response::InternalError("Power profiler service unavailable");
+ if (!enabled_) {
+ PowerProfilerService::GetInstance()->AddObserver(this);
+ enabled_ = true;
+ }
+ return Response::OK();
+}
+
+Response PowerHandler::End() {
+ if (!PowerProfilerService::GetInstance()->IsAvailable())
+ return Response::InternalError("Power profiler service unavailable");
+ if (enabled_) {
+ PowerProfilerService::GetInstance()->RemoveObserver(this);
+ enabled_ = false;
+ }
+ return Response::OK();
+}
+
+Response PowerHandler::CanProfilePower(bool* result) {
+ *result = PowerProfilerService::GetInstance()->IsAvailable();
+ return Response::OK();
+}
+
+Response PowerHandler::GetAccuracyLevel(std::string* result) {
+ if (!PowerProfilerService::GetInstance()->IsAvailable())
+ return Response::InternalError("Power profiler service unavailable");
+ *result = PowerProfilerService::GetInstance()->GetAccuracyLevel();
+ return Response::OK();
+}
+
+} // namespace power
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/power_handler.h b/chromium/content/browser/devtools/protocol/power_handler.h
new file mode 100644
index 00000000000..f0892c70c3f
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/power_handler.h
@@ -0,0 +1,45 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_POWER_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_POWER_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+#include "content/browser/power_profiler/power_profiler_observer.h"
+
+namespace content {
+namespace devtools {
+namespace power {
+
+class PowerHandler : public PowerProfilerObserver {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ PowerHandler();
+ ~PowerHandler() override;
+
+ void SetClient(scoped_ptr<Client> client);
+
+ // PowerProfilerObserver override.
+ void OnPowerEvent(const PowerEventVector& events) override;
+
+ void Detached();
+
+ Response Start();
+ Response End();
+ Response CanProfilePower(bool* result);
+ Response GetAccuracyLevel(std::string* result);
+
+ private:
+ scoped_ptr<Client> client_;
+ bool enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(PowerHandler);
+};
+
+} // namespace power
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_POWER_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
new file mode 100644
index 00000000000..7515da87b74
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -0,0 +1,215 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/tracing_handler.h"
+
+#include <cmath>
+
+#include "base/bind.h"
+#include "base/debug/trace_event_impl.h"
+#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+
+namespace content {
+namespace devtools {
+namespace tracing {
+
+typedef DevToolsProtocolClient::Response Response;
+
+namespace {
+
+const char kRecordUntilFull[] = "record-until-full";
+const char kRecordContinuously[] = "record-continuously";
+const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible";
+const char kEnableSampling[] = "enable-sampling";
+const double kMinimumReportingInterval = 250.0;
+
+class DevToolsTraceSinkProxy : public TracingController::TraceDataSink {
+ public:
+ explicit DevToolsTraceSinkProxy(base::WeakPtr<TracingHandler> handler)
+ : tracing_handler_(handler) {}
+
+ void AddTraceChunk(const std::string& chunk) override {
+ if (TracingHandler* h = tracing_handler_.get())
+ h->OnTraceDataCollected(chunk);
+ }
+ void Close() override {
+ if (TracingHandler* h = tracing_handler_.get())
+ h->OnTraceComplete();
+ }
+
+ private:
+ ~DevToolsTraceSinkProxy() override {}
+
+ base::WeakPtr<TracingHandler> tracing_handler_;
+};
+
+} // namespace
+
+TracingHandler::TracingHandler(TracingHandler::Target target)
+ : target_(target),
+ is_recording_(false),
+ weak_factory_(this) {
+}
+
+TracingHandler::~TracingHandler() {
+}
+
+void TracingHandler::SetClient(scoped_ptr<Client> client) {
+ client_.swap(client);
+}
+
+void TracingHandler::Detached() {
+ if (is_recording_)
+ DisableRecording(true);
+}
+
+void TracingHandler::OnTraceDataCollected(const std::string& trace_fragment) {
+ // Hand-craft protocol notification message so we can substitute JSON
+ // that we already got as string as a bare object, not a quoted string.
+ std::string message(
+ "{ \"method\": \"Tracing.dataCollected\", \"params\": { \"value\": [");
+ const size_t messageSuffixSize = 10;
+ message.reserve(message.size() + trace_fragment.size() + messageSuffixSize);
+ message += trace_fragment;
+ message += "] } }";
+ client_->SendRawMessage(message);
+}
+
+void TracingHandler::OnTraceComplete() {
+ TracingCompleteParams params;
+ client_->TracingComplete(params);
+}
+
+scoped_refptr<DevToolsProtocol::Response> TracingHandler::Start(
+ const std::string* categories,
+ const std::string* options_str,
+ const double* buffer_usage_reporting_interval,
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ if (is_recording_)
+ return command->InternalErrorResponse("Tracing is already started");
+ is_recording_ = true;
+
+ base::debug::TraceOptions options = TraceOptionsFromString(options_str);
+ base::debug::CategoryFilter filter(categories ? *categories : std::string());
+ if (buffer_usage_reporting_interval)
+ SetupTimer(*buffer_usage_reporting_interval);
+
+ // If inspected target is a render process Tracing.start will be handled by
+ // tracing agent in the renderer.
+ if (target_ == Renderer) {
+ TracingController::GetInstance()->EnableRecording(
+ filter,
+ options,
+ TracingController::EnableRecordingDoneCallback());
+ return nullptr;
+ }
+
+ TracingController::GetInstance()->EnableRecording(
+ filter,
+ options,
+ base::Bind(&TracingHandler::OnRecordingEnabled,
+ weak_factory_.GetWeakPtr(),
+ command));
+ return command->AsyncResponsePromise();
+}
+
+scoped_refptr<DevToolsProtocol::Response> TracingHandler::End(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ if (!is_recording_)
+ return command->InternalErrorResponse("Tracing is not started");
+ DisableRecording(false);
+ // If inspected target is a render process Tracing.end will be handled by
+ // tracing agent in the renderer.
+ if (target_ == Renderer)
+ return nullptr;
+ return command->SuccessResponse(nullptr);
+}
+
+scoped_refptr<DevToolsProtocol::Response> TracingHandler::GetCategories(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ TracingController::GetInstance()->GetCategories(
+ base::Bind(&TracingHandler::OnCategoriesReceived,
+ weak_factory_.GetWeakPtr(),
+ command));
+ return command->AsyncResponsePromise();
+}
+
+void TracingHandler::OnRecordingEnabled(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ StartResponse response;
+ client_->SendStartResponse(command, response);
+}
+
+void TracingHandler::OnBufferUsage(float usage) {
+ BufferUsageParams params;
+ params.set_value(usage);
+ client_->BufferUsage(params);
+}
+
+void TracingHandler::OnCategoriesReceived(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::set<std::string>& category_set) {
+ std::vector<std::string> categories(category_set.begin(), category_set.end());
+ GetCategoriesResponse response;
+ response.set_categories(categories);
+ client_->SendGetCategoriesResponse(command, response);
+}
+
+base::debug::TraceOptions TracingHandler::TraceOptionsFromString(
+ const std::string* options) {
+ base::debug::TraceOptions ret;
+ if (!options)
+ return ret;
+
+ std::vector<std::string> split;
+ std::vector<std::string>::iterator iter;
+
+ base::SplitString(*options, ',', &split);
+ for (iter = split.begin(); iter != split.end(); ++iter) {
+ if (*iter == kRecordUntilFull) {
+ ret.record_mode = base::debug::RECORD_UNTIL_FULL;
+ } else if (*iter == kRecordContinuously) {
+ ret.record_mode = base::debug::RECORD_CONTINUOUSLY;
+ } else if (*iter == kRecordAsMuchAsPossible) {
+ ret.record_mode = base::debug::RECORD_AS_MUCH_AS_POSSIBLE;
+ } else if (*iter == kEnableSampling) {
+ ret.enable_sampling = true;
+ }
+ }
+ return ret;
+}
+
+void TracingHandler::SetupTimer(double usage_reporting_interval) {
+ if (usage_reporting_interval == 0) return;
+
+ if (usage_reporting_interval < kMinimumReportingInterval)
+ usage_reporting_interval = kMinimumReportingInterval;
+
+ base::TimeDelta interval = base::TimeDelta::FromMilliseconds(
+ std::ceil(usage_reporting_interval));
+ buffer_usage_poll_timer_.reset(new base::Timer(
+ FROM_HERE,
+ interval,
+ base::Bind(
+ base::IgnoreResult(&TracingController::GetTraceBufferPercentFull),
+ base::Unretained(TracingController::GetInstance()),
+ base::Bind(&TracingHandler::OnBufferUsage,
+ weak_factory_.GetWeakPtr())),
+ true));
+ buffer_usage_poll_timer_->Reset();
+}
+
+void TracingHandler::DisableRecording(bool abort) {
+ is_recording_ = false;
+ buffer_usage_poll_timer_.reset();
+ TracingController::GetInstance()->DisableRecording(
+ abort ? nullptr : new DevToolsTraceSinkProxy(weak_factory_.GetWeakPtr()));
+}
+
+} // namespace tracing
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
new file mode 100644
index 00000000000..b20e5854a3b
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -0,0 +1,77 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TRACING_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TRACING_HANDLER_H_
+
+#include <set>
+#include <string>
+
+#include "base/debug/trace_event.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+#include "content/public/browser/tracing_controller.h"
+
+namespace base {
+class RefCountedString;
+class Timer;
+}
+
+namespace content {
+namespace devtools {
+namespace tracing {
+
+class TracingHandler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ enum Target { Browser, Renderer };
+ explicit TracingHandler(Target target);
+ virtual ~TracingHandler();
+
+ void SetClient(scoped_ptr<Client> client);
+ void Detached();
+
+ void OnTraceDataCollected(const std::string& trace_fragment);
+ void OnTraceComplete();
+
+ scoped_refptr<DevToolsProtocol::Response> Start(
+ const std::string* categories,
+ const std::string* options,
+ const double* buffer_usage_reporting_interval,
+ scoped_refptr<DevToolsProtocol::Command> command);
+
+ scoped_refptr<DevToolsProtocol::Response> End(
+ scoped_refptr<DevToolsProtocol::Command> command);
+ scoped_refptr<DevToolsProtocol::Response> GetCategories(
+ scoped_refptr<DevToolsProtocol::Command> command);
+
+ private:
+ void OnRecordingEnabled(scoped_refptr<DevToolsProtocol::Command> command);
+ void OnBufferUsage(float usage);
+
+ void OnCategoriesReceived(scoped_refptr<DevToolsProtocol::Command> command,
+ const std::set<std::string>& category_set);
+
+ base::debug::TraceOptions TraceOptionsFromString(const std::string* options);
+
+ void SetupTimer(double usage_reporting_interval);
+
+ void DisableRecording(bool abort);
+
+ scoped_ptr<base::Timer> buffer_usage_poll_timer_;
+ Target target_;
+ bool is_recording_;
+
+ scoped_ptr<Client> client_;
+ base::WeakPtrFactory<TracingHandler> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TracingHandler);
+};
+
+} // namespace tracing
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TRACING_HANDLER_H_
diff --git a/chromium/content/browser/devtools/protocol/usage_and_quota_query.cc b/chromium/content/browser/devtools/protocol/usage_and_quota_query.cc
new file mode 100644
index 00000000000..2936fe1e079
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/usage_and_quota_query.cc
@@ -0,0 +1,136 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/usage_and_quota_query.h"
+
+#include "net/base/net_util.h"
+
+namespace content {
+namespace devtools {
+namespace page {
+
+namespace {
+
+class UsageQuery : public base::RefCounted<UsageQuery> {
+ public:
+ using Callback = base::Callback<void(const std::vector<UsageItem>&)>;
+
+ UsageQuery(scoped_refptr<storage::QuotaManager> quota_manager,
+ const std::string& host,
+ storage::StorageType storage_type,
+ const Callback& callback)
+ : quota_manager_(quota_manager),
+ host_(host),
+ storage_type_(storage_type),
+ callback_(callback) {
+ AddRef();
+ GetForClient(storage::QuotaClient::kFileSystem,
+ usage_item::kIdFilesystem);
+ GetForClient(storage::QuotaClient::kDatabase,
+ usage_item::kIdDatabase);
+ GetForClient(storage::QuotaClient::kAppcache,
+ usage_item::kIdAppcache);
+ GetForClient(storage::QuotaClient::kIndexedDatabase,
+ usage_item::kIdIndexeddatabase);
+ Release();
+ }
+
+ private:
+ friend class base::RefCounted<UsageQuery>;
+
+ ~UsageQuery() {
+ callback_.Run(usage_list_);
+ }
+
+ void GetForClient(storage::QuotaClient::ID client_id,
+ const std::string& client_name) {
+ if (!quota_manager_->IsTrackingHostUsage(storage_type_, client_id))
+ return;
+ quota_manager_->GetHostUsage(
+ host_, storage_type_, client_id,
+ base::Bind(&UsageQuery::DidGetForClient, this, client_name));
+ }
+
+ void DidGetForClient(const std::string& client_name, int64 value) {
+ UsageItem usage_item;
+ usage_item.set_id(client_name);
+ usage_item.set_value(value);
+ usage_list_.push_back(usage_item);
+ }
+
+ scoped_refptr<storage::QuotaManager> quota_manager_;
+ std::string host_;
+ storage::StorageType storage_type_;
+ std::vector<UsageItem> usage_list_;
+ Callback callback_;
+};
+
+} // namespace
+
+UsageAndQuotaQuery::UsageAndQuotaQuery(
+ scoped_refptr<storage::QuotaManager> quota_manager,
+ const GURL& security_origin,
+ const Callback& callback)
+ : quota_manager_(quota_manager),
+ security_origin_(security_origin),
+ callback_(callback) {
+ AddRef();
+ quota_manager->GetUsageAndQuotaForWebApps(
+ security_origin,
+ storage::kStorageTypeTemporary,
+ base::Bind(&UsageAndQuotaQuery::DidGetTemporaryQuota, this));
+ quota_manager->GetPersistentHostQuota(
+ net::GetHostOrSpecFromURL(security_origin),
+ base::Bind(&UsageAndQuotaQuery::DidGetPersistentQuota, this));
+ GetHostUsage(storage::kStorageTypeTemporary,
+ base::Bind(&Usage::set_temporary, base::Unretained(&usage_)));
+ GetHostUsage(storage::kStorageTypePersistent,
+ base::Bind(&Usage::set_persistent, base::Unretained(&usage_)));
+ GetHostUsage(storage::kStorageTypeSyncable,
+ base::Bind(&Usage::set_syncable, base::Unretained(&usage_)));
+ Release();
+}
+
+UsageAndQuotaQuery::~UsageAndQuotaQuery() {
+ scoped_ptr<QueryUsageAndQuotaResponse> response(
+ new QueryUsageAndQuotaResponse);
+ response->set_quota(quota_);
+ response->set_usage(usage_);
+ callback_.Run(response.Pass());
+}
+
+void UsageAndQuotaQuery::DidGetTemporaryQuota(storage::QuotaStatusCode status,
+ int64 used_bytes,
+ int64 quota_in_bytes) {
+ if (status == storage::kQuotaStatusOk)
+ quota_.set_temporary(quota_in_bytes);
+}
+
+void UsageAndQuotaQuery::DidGetPersistentQuota(storage::QuotaStatusCode status,
+ int64 value) {
+ if (status == storage::kQuotaStatusOk)
+ quota_.set_persistent(value);
+}
+
+void UsageAndQuotaQuery::GetHostUsage(
+ storage::StorageType storage_type,
+ const UsageItemsCallback& items_callback) {
+ // |base::Bind| is used instead of passing |items_callback| directly
+ // so that |this| is retained.
+ new UsageQuery(quota_manager_,
+ net::GetHostOrSpecFromURL(security_origin_),
+ storage_type,
+ base::Bind(&UsageAndQuotaQuery::DidGetHostUsage,
+ this, items_callback));
+}
+
+void UsageAndQuotaQuery::DidGetHostUsage(
+ const UsageItemsCallback& items_callback,
+ const std::vector<UsageItem>& usage_list) {
+ items_callback.Run(usage_list);
+}
+
+} // namespace page
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/usage_and_quota_query.h b/chromium/content/browser/devtools/protocol/usage_and_quota_query.h
new file mode 100644
index 00000000000..ffbf7010a18
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/usage_and_quota_query.h
@@ -0,0 +1,55 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_QUOTA_AND_USAGE_QUERY_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_QUOTA_AND_USAGE_QUERY_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+#include "storage/browser/quota/quota_manager.h"
+
+namespace content {
+namespace devtools {
+namespace page {
+
+// This class can only be used on IO thread.
+class UsageAndQuotaQuery : public base::RefCounted<UsageAndQuotaQuery> {
+ public:
+ using Callback = base::Callback<void(scoped_ptr<QueryUsageAndQuotaResponse>)>;
+
+ UsageAndQuotaQuery(scoped_refptr<storage::QuotaManager> quota_manager,
+ const GURL& security_origin,
+ const Callback& callback);
+
+ private:
+ friend class base::RefCounted<UsageAndQuotaQuery>;
+
+ virtual ~UsageAndQuotaQuery();
+
+ void DidGetTemporaryQuota(storage::QuotaStatusCode status,
+ int64 used_bytes,
+ int64 quota_in_bytes);
+
+ void DidGetPersistentQuota(storage::QuotaStatusCode status, int64 value);
+
+ using UsageItemsCallback =
+ base::Callback<void(const std::vector<UsageItem>&)>;
+
+ void GetHostUsage(storage::StorageType storage_type,
+ const UsageItemsCallback& items_callback);
+
+ void DidGetHostUsage(const UsageItemsCallback& items_callback,
+ const std::vector<UsageItem>& usage_list);
+
+ scoped_refptr<storage::QuotaManager> quota_manager_;
+ GURL security_origin_;
+ Callback callback_;
+ Quota quota_;
+ Usage usage_;
+};
+
+} // namespace page
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_QUOTA_AND_USAGE_QUERY_H_
diff --git a/chromium/content/browser/devtools/protocol/worker_handler.cc b/chromium/content/browser/devtools/protocol/worker_handler.cc
new file mode 100644
index 00000000000..fd8fc09a253
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/worker_handler.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 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 "content/browser/devtools/protocol/worker_handler.h"
+
+namespace content {
+namespace devtools {
+namespace worker {
+
+typedef DevToolsProtocolClient::Response Response;
+typedef DevToolsProtocolClient::ResponseStatus ResponseStatus;
+
+WorkerHandler::WorkerHandler() {
+}
+
+WorkerHandler::~WorkerHandler() {
+}
+
+void WorkerHandler::SetClient(scoped_ptr<Client> client) {
+ client_.swap(client);
+}
+
+Response WorkerHandler::DisconnectFromWorker(int worker_id) {
+ return Response::FallThrough();
+}
+
+} // namespace worker
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/worker_handler.h b/chromium/content/browser/devtools/protocol/worker_handler.h
new file mode 100644
index 00000000000..1c1faafed2b
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/worker_handler.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WORKER_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WORKER_HANDLER_H_
+
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+
+namespace content {
+namespace devtools {
+namespace worker {
+
+class WorkerHandler {
+ public:
+ typedef DevToolsProtocolClient::Response Response;
+
+ WorkerHandler();
+ virtual ~WorkerHandler();
+
+ void SetClient(scoped_ptr<Client> client);
+
+ Response DisconnectFromWorker(int worker_id);
+
+ private:
+ scoped_ptr<Client> client_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerHandler);
+};
+
+} // namespace worker
+} // namespace devtools
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_WORKER_HANDLER_H_
diff --git a/chromium/content/browser/devtools/render_view_devtools_agent_host.cc b/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
index 82df7ed2f0d..5115ba21e45 100644
--- a/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -6,13 +6,18 @@
#include "base/basictypes.h"
#include "base/lazy_instance.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
-#include "content/browser/devtools/devtools_power_handler.h"
+#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/devtools/devtools_protocol.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
-#include "content/browser/devtools/devtools_tracing_handler.h"
-#include "content/browser/devtools/renderer_overrides_handler.h"
+#include "content/browser/devtools/protocol/devtools_protocol_handler_impl.h"
+#include "content/browser/devtools/protocol/dom_handler.h"
+#include "content/browser/devtools/protocol/input_handler.h"
+#include "content/browser/devtools/protocol/network_handler.h"
+#include "content/browser/devtools/protocol/page_handler.h"
+#include "content/browser/devtools/protocol/power_handler.h"
+#include "content/browser/devtools/protocol/tracing_handler.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
@@ -24,6 +29,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/web_contents_delegate.h"
#if defined(OS_ANDROID)
#include "content/browser/power_save_blocker_impl.h"
@@ -42,23 +48,9 @@ base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
static RenderViewDevToolsAgentHost* FindAgentHost(WebContents* web_contents) {
if (g_instances == NULL)
return NULL;
- RenderViewHostDelegate* delegate =
- static_cast<WebContentsImpl*>(web_contents);
for (Instances::iterator it = g_instances.Get().begin();
it != g_instances.Get().end(); ++it) {
- RenderViewHost* rvh = (*it)->render_view_host();
- if (rvh && rvh->GetDelegate() == delegate)
- return *it;
- }
- return NULL;
-}
-
-static RenderViewDevToolsAgentHost* FindAgentHost(RenderViewHost* rvh) {
- if (g_instances == NULL)
- return NULL;
- for (Instances::iterator it = g_instances.Get().begin();
- it != g_instances.Get().end(); ++it) {
- if (rvh == (*it)->render_view_host())
+ if ((*it)->GetWebContents() == web_contents)
return *it;
}
return NULL;
@@ -75,42 +67,19 @@ DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
}
// static
-scoped_refptr<DevToolsAgentHost>
-DevToolsAgentHost::GetOrCreateFor(RenderViewHost* rvh) {
- RenderViewDevToolsAgentHost* result = FindAgentHost(rvh);
- if (!result)
- result = new RenderViewDevToolsAgentHost(rvh);
- return result;
-}
-
-// static
-bool DevToolsAgentHost::HasFor(RenderViewHost* rvh) {
- return FindAgentHost(rvh) != NULL;
+bool DevToolsAgentHost::HasFor(WebContents* web_contents) {
+ return FindAgentHost(web_contents) != NULL;
}
// static
bool DevToolsAgentHost::IsDebuggerAttached(WebContents* web_contents) {
- if (g_instances == NULL)
- return false;
- DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
- if (!devtools_manager)
- return false;
- RenderViewHostDelegate* delegate =
- static_cast<WebContentsImpl*>(web_contents);
- for (Instances::iterator it = g_instances.Get().begin();
- it != g_instances.Get().end(); ++it) {
- RenderViewHost* rvh = (*it)->render_view_host_;
- if (rvh && rvh->GetDelegate() != delegate)
- continue;
- if ((*it)->IsAttached())
- return true;
- }
- return false;
+ RenderViewDevToolsAgentHost* agent_host = FindAgentHost(web_contents);
+ return agent_host && agent_host->IsAttached();
}
//static
-std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
- std::vector<RenderViewHost*> result;
+std::vector<WebContents*> DevToolsAgentHostImpl::GetInspectableWebContents() {
+ std::set<WebContents*> set;
scoped_ptr<RenderWidgetHostIterator> widgets(
RenderWidgetHost::GetRenderWidgetHosts());
while (RenderWidgetHost* widget = widgets->GetNextHost()) {
@@ -122,23 +91,11 @@ std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
RenderViewHost* rvh = RenderViewHost::From(widget);
WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
- if (!web_contents)
- continue;
-
- // Don't report a RenderViewHost if it is not the current RenderViewHost
- // for some WebContents (this filters out pre-render RVHs and similar).
- // However report a RenderViewHost created for an out of process iframe.
- // TODO (kaznacheev): Revisit this when it is clear how OOP iframes
- // interact with pre-rendering.
- // TODO (kaznacheev): GetMainFrame() call is a temporary hack. Iterate over
- // all RenderFrameHost instances when multiple OOP frames are supported.
- if (rvh != web_contents->GetRenderViewHost() &&
- !rvh->GetMainFrame()->IsCrossProcessSubframe()) {
- continue;
- }
-
- result.push_back(rvh);
+ if (web_contents)
+ set.insert(web_contents);
}
+ std::vector<WebContents*> result(set.size());
+ std::copy(set.begin(), set.end(), result.begin());
return result;
}
@@ -146,44 +103,46 @@ std::vector<RenderViewHost*> DevToolsAgentHost::GetValidRenderViewHosts() {
void RenderViewDevToolsAgentHost::OnCancelPendingNavigation(
RenderViewHost* pending,
RenderViewHost* current) {
- RenderViewDevToolsAgentHost* agent_host = FindAgentHost(pending);
+ WebContents* web_contents = WebContents::FromRenderViewHost(pending);
+ RenderViewDevToolsAgentHost* agent_host = FindAgentHost(web_contents);
if (!agent_host)
return;
agent_host->DisconnectRenderViewHost();
agent_host->ConnectRenderViewHost(current);
}
-// static
-bool RenderViewDevToolsAgentHost::DispatchIPCMessage(
- RenderViewHost* source,
- const IPC::Message& message) {
- RenderViewDevToolsAgentHost* agent_host = FindAgentHost(source);
- return agent_host && agent_host->DispatchIPCMessage(message);
-}
-
RenderViewDevToolsAgentHost::RenderViewDevToolsAgentHost(RenderViewHost* rvh)
: render_view_host_(NULL),
- overrides_handler_(new RendererOverridesHandler(this)),
- tracing_handler_(
- new DevToolsTracingHandler(DevToolsTracingHandler::Renderer)),
- power_handler_(new DevToolsPowerHandler()),
+ dom_handler_(new devtools::dom::DOMHandler()),
+ input_handler_(new devtools::input::InputHandler()),
+ network_handler_(new devtools::network::NetworkHandler()),
+ page_handler_(new devtools::page::PageHandler()),
+ power_handler_(new devtools::power::PowerHandler()),
+ tracing_handler_(new devtools::tracing::TracingHandler(
+ devtools::tracing::TracingHandler::Renderer)),
+ handler_impl_(new DevToolsProtocolHandlerImpl()),
reattaching_(false) {
+ handler_impl_->SetDOMHandler(dom_handler_.get());
+ handler_impl_->SetInputHandler(input_handler_.get());
+ handler_impl_->SetNetworkHandler(network_handler_.get());
+ handler_impl_->SetPageHandler(page_handler_.get());
+ handler_impl_->SetPowerHandler(power_handler_.get());
+ handler_impl_->SetTracingHandler(tracing_handler_.get());
SetRenderViewHost(rvh);
DevToolsProtocol::Notifier notifier(base::Bind(
- &RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend,
+ &RenderViewDevToolsAgentHost::DispatchOnInspectorFrontend,
base::Unretained(this)));
- overrides_handler_->SetNotifier(notifier);
- tracing_handler_->SetNotifier(notifier);
- power_handler_->SetNotifier(notifier);
+ handler_impl_->SetNotifier(notifier);
g_instances.Get().push_back(this);
AddRef(); // Balanced in RenderViewHostDestroyed.
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
}
-RenderViewHost* RenderViewDevToolsAgentHost::GetRenderViewHost() {
- return render_view_host_;
+WebContents* RenderViewDevToolsAgentHost::GetWebContents() {
+ return web_contents();
}
-void RenderViewDevToolsAgentHost::DispatchOnInspectorBackend(
+void RenderViewDevToolsAgentHost::DispatchProtocolMessage(
const std::string& message) {
std::string error_message;
@@ -192,11 +151,11 @@ void RenderViewDevToolsAgentHost::DispatchOnInspectorBackend(
scoped_refptr<DevToolsProtocol::Command> command =
DevToolsProtocol::ParseCommand(message_dict.get(), &error_message);
- if (command) {
+ if (command.get()) {
scoped_refptr<DevToolsProtocol::Response> overridden_response;
DevToolsManagerDelegate* delegate =
- DevToolsManagerImpl::GetInstance()->delegate();
+ DevToolsManager::GetInstance()->delegate();
if (delegate) {
scoped_ptr<base::DictionaryValue> overridden_response_value(
delegate->HandleCommand(this, message_dict.get()));
@@ -204,20 +163,16 @@ void RenderViewDevToolsAgentHost::DispatchOnInspectorBackend(
overridden_response = DevToolsProtocol::ParseResponse(
overridden_response_value.get());
}
- if (!overridden_response)
- overridden_response = overrides_handler_->HandleCommand(command);
- if (!overridden_response)
- overridden_response = tracing_handler_->HandleCommand(command);
- if (!overridden_response)
- overridden_response = power_handler_->HandleCommand(command);
- if (overridden_response) {
+ if (!overridden_response.get())
+ overridden_response = handler_impl_->HandleCommand(command);
+ if (overridden_response.get()) {
if (!overridden_response->is_async_promise())
- OnDispatchOnInspectorFrontend(overridden_response->Serialize());
+ DispatchOnInspectorFrontend(overridden_response->Serialize());
return;
}
}
- IPCDevToolsAgentHost::DispatchOnInspectorBackend(message);
+ IPCDevToolsAgentHost::DispatchProtocolMessage(message);
}
void RenderViewDevToolsAgentHost::SendMessageToAgent(IPC::Message* msg) {
@@ -233,10 +188,10 @@ void RenderViewDevToolsAgentHost::OnClientAttached() {
InnerOnClientAttached();
- // TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
+ // TODO(kaznacheev): Move this call back to DevToolsManager when
// extensions::ProcessManager no longer relies on this notification.
if (!reattaching_)
- DevToolsManagerImpl::GetInstance()->NotifyObservers(this, true);
+ DevToolsAgentHostImpl::NotifyCallbacks(this, true);
}
void RenderViewDevToolsAgentHost::InnerOnClientAttached() {
@@ -260,9 +215,15 @@ void RenderViewDevToolsAgentHost::OnClientDetached() {
#if defined(OS_ANDROID)
power_save_blocker_.reset();
#endif
- overrides_handler_->OnClientDetached();
- tracing_handler_->OnClientDetached();
+ page_handler_->Detached();
+ power_handler_->Detached();
+ tracing_handler_->Detached();
ClientDetachedFromRenderer();
+
+ // TODO(kaznacheev): Move this call back to DevToolsManager when
+ // extensions::ProcessManager no longer relies on this notification.
+ if (!reattaching_)
+ DevToolsAgentHostImpl::NotifyCallbacks(this, false);
}
void RenderViewDevToolsAgentHost::ClientDetachedFromRenderer() {
@@ -270,11 +231,6 @@ void RenderViewDevToolsAgentHost::ClientDetachedFromRenderer() {
return;
InnerClientDetachedFromRenderer();
-
- // TODO(kaznacheev): Move this call back to DevToolsManagerImpl when
- // extensions::ProcessManager no longer relies on this notification.
- if (!reattaching_)
- DevToolsManagerImpl::GetInstance()->NotifyObservers(this, false);
}
void RenderViewDevToolsAgentHost::InnerClientDetachedFromRenderer() {
@@ -284,7 +240,7 @@ void RenderViewDevToolsAgentHost::InnerClientDetachedFromRenderer() {
it != g_instances.Get().end(); ++it) {
if (*it == this || !(*it)->IsAttached())
continue;
- RenderViewHost* rvh = (*it)->render_view_host();
+ RenderViewHost* rvh = (*it)->render_view_host_;
if (rvh && rvh->GetProcess() == render_process_host)
process_has_agents = true;
}
@@ -309,8 +265,8 @@ void RenderViewDevToolsAgentHost::AboutToNavigateRenderView(
if (!render_view_host_)
return;
- if (render_view_host_ == dest_rvh && static_cast<RenderViewHostImpl*>(
- render_view_host_)->render_view_termination_status() ==
+ if (render_view_host_ == dest_rvh &&
+ render_view_host_->render_view_termination_status() ==
base::TERMINATION_STATUS_STILL_RUNNING)
return;
ReattachToRenderViewHost(dest_rvh);
@@ -341,8 +297,9 @@ void RenderViewDevToolsAgentHost::RenderViewDeleted(RenderViewHost* rvh) {
DCHECK(render_view_host_);
scoped_refptr<RenderViewDevToolsAgentHost> protect(this);
- NotifyCloseListener();
+ HostClosed();
ClearRenderViewHost();
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
Release();
}
@@ -362,7 +319,20 @@ void RenderViewDevToolsAgentHost::RenderProcessGone(
}
}
+bool RenderViewDevToolsAgentHost::OnMessageReceived(
+ const IPC::Message& message,
+ RenderFrameHost* render_frame_host) {
+ return DispatchIPCMessage(message);
+}
+
+bool RenderViewDevToolsAgentHost::OnMessageReceived(
+ const IPC::Message& message) {
+ return DispatchIPCMessage(message);
+}
+
void RenderViewDevToolsAgentHost::DidAttachInterstitialPage() {
+ page_handler_->DidAttachInterstitialPage();
+
if (!render_view_host_)
return;
// The rvh set in AboutToNavigateRenderView turned out to be interstitial.
@@ -375,20 +345,38 @@ void RenderViewDevToolsAgentHost::DidAttachInterstitialPage() {
ConnectRenderViewHost(web_contents->GetRenderViewHost());
}
+void RenderViewDevToolsAgentHost::DidDetachInterstitialPage() {
+ page_handler_->DidDetachInterstitialPage();
+}
+
+void RenderViewDevToolsAgentHost::TitleWasSet(
+ NavigationEntry* entry, bool explicit_set) {
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
+}
+
+void RenderViewDevToolsAgentHost::NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) {
+ DevToolsManager::GetInstance()->AgentHostChanged(this);
+}
+
void RenderViewDevToolsAgentHost::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
if (type == content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
bool visible = *Details<bool>(details).ptr();
- overrides_handler_->OnVisibilityChanged(visible);
+ page_handler_->OnVisibilityChanged(visible);
}
}
void RenderViewDevToolsAgentHost::SetRenderViewHost(RenderViewHost* rvh) {
DCHECK(!render_view_host_);
- render_view_host_ = rvh;
+ render_view_host_ = static_cast<RenderViewHostImpl*>(rvh);
WebContentsObserver::Observe(WebContents::FromRenderViewHost(rvh));
+ dom_handler_->SetRenderViewHost(render_view_host_);
+ input_handler_->SetRenderViewHost(render_view_host_);
+ network_handler_->SetRenderViewHost(render_view_host_);
+ page_handler_->SetRenderViewHost(render_view_host_);
registrar_.Add(
this,
@@ -402,7 +390,52 @@ void RenderViewDevToolsAgentHost::ClearRenderViewHost() {
this,
content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
content::Source<RenderWidgetHost>(render_view_host_));
- render_view_host_ = NULL;
+ render_view_host_ = nullptr;
+ dom_handler_->SetRenderViewHost(nullptr);
+ input_handler_->SetRenderViewHost(nullptr);
+ network_handler_->SetRenderViewHost(nullptr);
+ page_handler_->SetRenderViewHost(nullptr);
+}
+
+void RenderViewDevToolsAgentHost::DisconnectWebContents() {
+ DisconnectRenderViewHost();
+}
+
+void RenderViewDevToolsAgentHost::ConnectWebContents(WebContents* wc) {
+ ConnectRenderViewHost(wc->GetRenderViewHost());
+}
+
+DevToolsAgentHost::Type RenderViewDevToolsAgentHost::GetType() {
+ return TYPE_WEB_CONTENTS;
+}
+
+std::string RenderViewDevToolsAgentHost::GetTitle() {
+ if (WebContents* web_contents = GetWebContents())
+ return base::UTF16ToUTF8(web_contents->GetTitle());
+ return "";
+}
+
+GURL RenderViewDevToolsAgentHost::GetURL() {
+ if (WebContents* web_contents = GetWebContents())
+ return web_contents->GetVisibleURL();
+ return render_view_host_ ?
+ render_view_host_->GetMainFrame()->GetLastCommittedURL() : GURL();
+}
+
+bool RenderViewDevToolsAgentHost::Activate() {
+ if (render_view_host_) {
+ render_view_host_->GetDelegate()->Activate();
+ return true;
+ }
+ return false;
+}
+
+bool RenderViewDevToolsAgentHost::Close() {
+ if (render_view_host_) {
+ render_view_host_->ClosePage();
+ return true;
+ }
+ return false;
}
void RenderViewDevToolsAgentHost::ConnectRenderViewHost(RenderViewHost* rvh) {
@@ -420,8 +453,7 @@ void RenderViewDevToolsAgentHost::RenderViewCrashed() {
scoped_refptr<DevToolsProtocol::Notification> notification =
DevToolsProtocol::CreateNotification(
devtools::Inspector::targetCrashed::kName, NULL);
- DevToolsManagerImpl::GetInstance()->
- DispatchOnInspectorFrontend(this, notification->Serialize());
+ SendMessageToClient(notification->Serialize());
}
bool RenderViewDevToolsAgentHost::DispatchIPCMessage(
@@ -447,14 +479,14 @@ void RenderViewDevToolsAgentHost::OnSwapCompositorFrame(
ViewHostMsg_SwapCompositorFrame::Param param;
if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
return;
- overrides_handler_->OnSwapCompositorFrame(param.b.metadata);
+ page_handler_->OnSwapCompositorFrame(param.b.metadata);
}
void RenderViewDevToolsAgentHost::SynchronousSwapCompositorFrame(
const cc::CompositorFrameMetadata& frame_metadata) {
if (!render_view_host_)
return;
- overrides_handler_->OnSwapCompositorFrame(frame_metadata);
+ page_handler_->OnSwapCompositorFrame(frame_metadata);
}
void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState(
@@ -465,11 +497,18 @@ void RenderViewDevToolsAgentHost::OnSaveAgentRuntimeState(
}
void RenderViewDevToolsAgentHost::OnDispatchOnInspectorFrontend(
+ const std::string& message,
+ uint32 total_size) {
+ if (!IsAttached() || !render_view_host_)
+ return;
+ ProcessChunkedMessageFromAgent(message, total_size);
+}
+
+void RenderViewDevToolsAgentHost::DispatchOnInspectorFrontend(
const std::string& message) {
- if (!render_view_host_)
+ if (!IsAttached() || !render_view_host_)
return;
- DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
- this, message);
+ SendMessageToClient(message);
}
} // namespace content
diff --git a/chromium/content/browser/devtools/render_view_devtools_agent_host.h b/chromium/content/browser/devtools/render_view_devtools_agent_host.h
index f4e9baf4a5f..204d87e8544 100644
--- a/chromium/content/browser/devtools/render_view_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_view_devtools_agent_host.h
@@ -22,15 +22,23 @@ class CompositorFrameMetadata;
namespace content {
-class DevToolsPowerHandler;
-class DevToolsTracingHandler;
-class RendererOverridesHandler;
+class DevToolsProtocolHandlerImpl;
class RenderViewHost;
+class RenderViewHostImpl;
#if defined(OS_ANDROID)
class PowerSaveBlockerImpl;
#endif
+namespace devtools {
+namespace dom { class DOMHandler; }
+namespace input { class InputHandler; }
+namespace network { class NetworkHandler; }
+namespace page { class PageHandler; }
+namespace power { class PowerHandler; }
+namespace tracing { class TracingHandler; }
+}
+
class CONTENT_EXPORT RenderViewDevToolsAgentHost
: public IPCDevToolsAgentHost,
private WebContentsObserver,
@@ -39,45 +47,53 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
static void OnCancelPendingNavigation(RenderViewHost* pending,
RenderViewHost* current);
- static bool DispatchIPCMessage(RenderViewHost* source,
- const IPC::Message& message);
-
RenderViewDevToolsAgentHost(RenderViewHost*);
- RenderViewHost* render_view_host() { return render_view_host_; }
-
void SynchronousSwapCompositorFrame(
const cc::CompositorFrameMetadata& frame_metadata);
+ // DevTooolsAgentHost overrides.
+ void DisconnectWebContents() override;
+ void ConnectWebContents(WebContents* web_contents) override;
+ WebContents* GetWebContents() override;
+ Type GetType() override;
+ std::string GetTitle() override;
+ GURL GetURL() override;
+ bool Activate() override;
+ bool Close() override;
+
private:
friend class DevToolsAgentHost;
-
- virtual ~RenderViewDevToolsAgentHost();
-
- // DevTooolsAgentHost overrides.
- virtual void DisconnectRenderViewHost() OVERRIDE;
- virtual void ConnectRenderViewHost(RenderViewHost* rvh) OVERRIDE;
- virtual RenderViewHost* GetRenderViewHost() OVERRIDE;
+ ~RenderViewDevToolsAgentHost() override;
// IPCDevToolsAgentHost overrides.
- virtual void DispatchOnInspectorBackend(const std::string& message) OVERRIDE;
- virtual void SendMessageToAgent(IPC::Message* msg) OVERRIDE;
- virtual void OnClientAttached() OVERRIDE;
- virtual void OnClientDetached() OVERRIDE;
+ void DispatchProtocolMessage(const std::string& message) override;
+ void SendMessageToAgent(IPC::Message* msg) override;
+ void OnClientAttached() override;
+ void OnClientDetached() override;
// WebContentsObserver overrides.
- virtual void AboutToNavigateRenderView(RenderViewHost* dest_rvh) OVERRIDE;
- virtual void RenderViewHostChanged(RenderViewHost* old_host,
- RenderViewHost* new_host) OVERRIDE;
- virtual void RenderViewDeleted(RenderViewHost* rvh) OVERRIDE;
- virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
- virtual void DidAttachInterstitialPage() OVERRIDE;
+ void AboutToNavigateRenderView(RenderViewHost* dest_rvh) override;
+ void RenderViewHostChanged(RenderViewHost* old_host,
+ RenderViewHost* new_host) override;
+ void RenderViewDeleted(RenderViewHost* rvh) override;
+ void RenderProcessGone(base::TerminationStatus status) override;
+ bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void DidAttachInterstitialPage() override;
+ void DidDetachInterstitialPage() override;
+ void TitleWasSet(NavigationEntry* entry, bool explicit_set) override;
+ void NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) override;
// NotificationObserver overrides:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
+ void DisconnectRenderViewHost();
+ void ConnectRenderViewHost(RenderViewHost* rvh);
void ReattachToRenderViewHost(RenderViewHost* rvh);
bool DispatchIPCMessage(const IPC::Message& message);
@@ -87,8 +103,11 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
void RenderViewCrashed();
void OnSwapCompositorFrame(const IPC::Message& message);
+ bool OnSetTouchEventEmulationEnabled(const IPC::Message& message);
- void OnDispatchOnInspectorFrontend(const std::string& message);
+ void OnDispatchOnInspectorFrontend(const std::string& message,
+ uint32 total_size);
+ void DispatchOnInspectorFrontend(const std::string& message);
void OnSaveAgentRuntimeState(const std::string& state);
void ClientDetachedFromRenderer();
@@ -96,10 +115,14 @@ class CONTENT_EXPORT RenderViewDevToolsAgentHost
void InnerOnClientAttached();
void InnerClientDetachedFromRenderer();
- RenderViewHost* render_view_host_;
- scoped_ptr<RendererOverridesHandler> overrides_handler_;
- scoped_ptr<DevToolsTracingHandler> tracing_handler_;
- scoped_ptr<DevToolsPowerHandler> power_handler_;
+ RenderViewHostImpl* render_view_host_;
+ scoped_ptr<devtools::dom::DOMHandler> dom_handler_;
+ scoped_ptr<devtools::input::InputHandler> input_handler_;
+ scoped_ptr<devtools::network::NetworkHandler> network_handler_;
+ scoped_ptr<devtools::page::PageHandler> page_handler_;
+ scoped_ptr<devtools::power::PowerHandler> power_handler_;
+ scoped_ptr<devtools::tracing::TracingHandler> tracing_handler_;
+ scoped_ptr<DevToolsProtocolHandlerImpl> handler_impl_;
#if defined(OS_ANDROID)
scoped_ptr<PowerSaveBlockerImpl> power_save_blocker_;
#endif
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler.cc b/chromium/content/browser/devtools/renderer_overrides_handler.cc
deleted file mode 100644
index 7370275cd45..00000000000
--- a/chromium/content/browser/devtools/renderer_overrides_handler.cc
+++ /dev/null
@@ -1,1007 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/devtools/renderer_overrides_handler.h"
-
-#include <map>
-#include <string>
-
-#include "base/barrier_closure.h"
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_path.h"
-#include "base/strings/string16.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/values.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/devtools_protocol_constants.h"
-#include "content/browser/devtools/devtools_tracing_handler.h"
-#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/common/view_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/devtools_agent_host.h"
-#include "content/public/browser/javascript_dialog_manager.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/page_transition_types.h"
-#include "content/public/common/referrer.h"
-#include "ipc/ipc_sender.h"
-#include "net/base/net_util.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/gfx/codec/jpeg_codec.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/display.h"
-#include "ui/gfx/screen.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/snapshot/snapshot.h"
-#include "url/gurl.h"
-#include "webkit/browser/quota/quota_manager.h"
-
-using blink::WebGestureEvent;
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
-
-namespace content {
-
-namespace {
-
-static const char kPng[] = "png";
-static const char kJpeg[] = "jpeg";
-static int kDefaultScreenshotQuality = 80;
-static int kFrameRateThresholdMs = 100;
-static int kCaptureRetryLimit = 2;
-
-void ParseGenericInputParams(base::DictionaryValue* params,
- WebInputEvent* event) {
- int modifiers = 0;
- if (params->GetInteger(devtools::Input::dispatchMouseEvent::kParamModifiers,
- &modifiers)) {
- if (modifiers & 1)
- event->modifiers |= WebInputEvent::AltKey;
- if (modifiers & 2)
- event->modifiers |= WebInputEvent::ControlKey;
- if (modifiers & 4)
- event->modifiers |= WebInputEvent::MetaKey;
- if (modifiers & 8)
- event->modifiers |= WebInputEvent::ShiftKey;
- }
-
- params->GetDouble(devtools::Input::dispatchMouseEvent::kParamTimestamp,
- &event->timeStampSeconds);
-}
-
-} // namespace
-
-RendererOverridesHandler::RendererOverridesHandler(DevToolsAgentHost* agent)
- : agent_(agent),
- capture_retry_count_(0),
- weak_factory_(this) {
- RegisterCommandHandler(
- devtools::DOM::setFileInputFiles::kName,
- base::Bind(
- &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Network::clearBrowserCache::kName,
- base::Bind(
- &RendererOverridesHandler::ClearBrowserCache,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Network::clearBrowserCookies::kName,
- base::Bind(
- &RendererOverridesHandler::ClearBrowserCookies,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::disable::kName,
- base::Bind(
- &RendererOverridesHandler::PageDisable, base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::handleJavaScriptDialog::kName,
- base::Bind(
- &RendererOverridesHandler::PageHandleJavaScriptDialog,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::navigate::kName,
- base::Bind(
- &RendererOverridesHandler::PageNavigate,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::reload::kName,
- base::Bind(
- &RendererOverridesHandler::PageReload,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::getNavigationHistory::kName,
- base::Bind(
- &RendererOverridesHandler::PageGetNavigationHistory,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::navigateToHistoryEntry::kName,
- base::Bind(
- &RendererOverridesHandler::PageNavigateToHistoryEntry,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::captureScreenshot::kName,
- base::Bind(
- &RendererOverridesHandler::PageCaptureScreenshot,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::canScreencast::kName,
- base::Bind(
- &RendererOverridesHandler::PageCanScreencast,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::startScreencast::kName,
- base::Bind(
- &RendererOverridesHandler::PageStartScreencast,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::stopScreencast::kName,
- base::Bind(
- &RendererOverridesHandler::PageStopScreencast,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Page::queryUsageAndQuota::kName,
- base::Bind(
- &RendererOverridesHandler::PageQueryUsageAndQuota,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Input::dispatchMouseEvent::kName,
- base::Bind(
- &RendererOverridesHandler::InputDispatchMouseEvent,
- base::Unretained(this)));
- RegisterCommandHandler(
- devtools::Input::dispatchGestureEvent::kName,
- base::Bind(
- &RendererOverridesHandler::InputDispatchGestureEvent,
- base::Unretained(this)));
-}
-
-RendererOverridesHandler::~RendererOverridesHandler() {}
-
-void RendererOverridesHandler::OnClientDetached() {
- screencast_command_ = NULL;
-}
-
-void RendererOverridesHandler::OnSwapCompositorFrame(
- const cc::CompositorFrameMetadata& frame_metadata) {
- last_compositor_frame_metadata_ = frame_metadata;
-
- if (screencast_command_)
- InnerSwapCompositorFrame();
-}
-
-void RendererOverridesHandler::OnVisibilityChanged(bool visible) {
- if (!screencast_command_)
- return;
- NotifyScreencastVisibility(visible);
-}
-
-void RendererOverridesHandler::InnerSwapCompositorFrame() {
- if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() <
- kFrameRateThresholdMs) {
- return;
- }
-
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (!host->GetView())
- return;
-
- last_frame_time_ = base::TimeTicks::Now();
- std::string format;
- int quality = kDefaultScreenshotQuality;
- double scale = 1;
- ParseCaptureParameters(screencast_command_.get(), &format, &quality, &scale);
-
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
- float device_scale_factor = display.device_scale_factor();
-
- gfx::Rect view_bounds = host->GetView()->GetViewBounds();
- gfx::Size snapshot_size(gfx::ToCeiledSize(
- gfx::ScaleSize(view_bounds.size(), scale / device_scale_factor)));
-
- RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
- host->GetView());
- view->CopyFromCompositingSurface(
- view_bounds, snapshot_size,
- base::Bind(&RendererOverridesHandler::ScreencastFrameCaptured,
- weak_factory_.GetWeakPtr(),
- format, quality, last_compositor_frame_metadata_),
- SkBitmap::kARGB_8888_Config);
-}
-
-void RendererOverridesHandler::ParseCaptureParameters(
- DevToolsProtocol::Command* command,
- std::string* format,
- int* quality,
- double* scale) {
- *quality = kDefaultScreenshotQuality;
- *scale = 1;
- double max_width = -1;
- double max_height = -1;
- base::DictionaryValue* params = command->params();
- if (params) {
- params->GetString(devtools::Page::startScreencast::kParamFormat,
- format);
- params->GetInteger(devtools::Page::startScreencast::kParamQuality,
- quality);
- params->GetDouble(devtools::Page::startScreencast::kParamMaxWidth,
- &max_width);
- params->GetDouble(devtools::Page::startScreencast::kParamMaxHeight,
- &max_height);
- }
-
- RenderViewHost* host = agent_->GetRenderViewHost();
- CHECK(host->GetView());
- gfx::Rect view_bounds = host->GetView()->GetViewBounds();
- if (max_width > 0)
- *scale = std::min(*scale, max_width / view_bounds.width());
- if (max_height > 0)
- *scale = std::min(*scale, max_height / view_bounds.height());
-
- if (format->empty())
- *format = kPng;
- if (*quality < 0 || *quality > 100)
- *quality = kDefaultScreenshotQuality;
- if (*scale <= 0)
- *scale = 0.1;
- if (*scale > 5)
- *scale = 5;
-}
-
-base::DictionaryValue* RendererOverridesHandler::CreateScreenshotResponse(
- const std::vector<unsigned char>& png_data) {
- std::string base_64_data;
- base::Base64Encode(
- base::StringPiece(reinterpret_cast<const char*>(&png_data[0]),
- png_data.size()),
- &base_64_data);
-
- base::DictionaryValue* response = new base::DictionaryValue();
- response->SetString(
- devtools::Page::captureScreenshot::kResponseData, base_64_data);
- return response;
-}
-
-// DOM agent handlers --------------------------------------------------------
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::GrantPermissionsForSetFileInputFiles(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- base::ListValue* file_list = NULL;
- const char* param =
- devtools::DOM::setFileInputFiles::kParamFiles;
- if (!params || !params->GetList(param, &file_list))
- return command->InvalidParamResponse(param);
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (!host)
- return NULL;
-
- for (size_t i = 0; i < file_list->GetSize(); ++i) {
- base::FilePath::StringType file;
- if (!file_list->GetString(i, &file))
- return command->InvalidParamResponse(param);
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- host->GetProcess()->GetID(), base::FilePath(file));
- }
- return NULL;
-}
-
-
-// Network agent handlers ----------------------------------------------------
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::ClearBrowserCache(
- scoped_refptr<DevToolsProtocol::Command> command) {
- GetContentClient()->browser()->ClearCache(agent_->GetRenderViewHost());
- return command->SuccessResponse(NULL);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::ClearBrowserCookies(
- scoped_refptr<DevToolsProtocol::Command> command) {
- GetContentClient()->browser()->ClearCookies(agent_->GetRenderViewHost());
- return command->SuccessResponse(NULL);
-}
-
-
-// Page agent handlers -------------------------------------------------------
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageDisable(
- scoped_refptr<DevToolsProtocol::Command> command) {
- screencast_command_ = NULL;
- return NULL;
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageHandleJavaScriptDialog(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- const char* paramAccept =
- devtools::Page::handleJavaScriptDialog::kParamAccept;
- bool accept;
- if (!params || !params->GetBoolean(paramAccept, &accept))
- return command->InvalidParamResponse(paramAccept);
- base::string16 prompt_override;
- base::string16* prompt_override_ptr = &prompt_override;
- if (!params || !params->GetString(
- devtools::Page::handleJavaScriptDialog::kParamPromptText,
- prompt_override_ptr)) {
- prompt_override_ptr = NULL;
- }
-
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (host) {
- WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
- if (web_contents) {
- JavaScriptDialogManager* manager =
- web_contents->GetDelegate()->GetJavaScriptDialogManager();
- if (manager && manager->HandleJavaScriptDialog(
- web_contents, accept, prompt_override_ptr)) {
- return command->SuccessResponse(new base::DictionaryValue());
- }
- }
- }
- return command->InternalErrorResponse("No JavaScript dialog to handle");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageNavigate(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- std::string url;
- const char* param = devtools::Page::navigate::kParamUrl;
- if (!params || !params->GetString(param, &url))
- return command->InvalidParamResponse(param);
- GURL gurl(url);
- if (!gurl.is_valid()) {
- return command->InternalErrorResponse("Cannot navigate to invalid URL");
- }
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (host) {
- WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
- if (web_contents) {
- web_contents->GetController()
- .LoadURL(gurl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- return command->SuccessResponse(new base::DictionaryValue());
- }
- }
- return command->InternalErrorResponse("No WebContents to navigate");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageReload(
- scoped_refptr<DevToolsProtocol::Command> command) {
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (host) {
- WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
- if (web_contents) {
- // Override only if it is crashed.
- if (!web_contents->IsCrashed())
- return NULL;
-
- web_contents->GetController().Reload(false);
- return command->SuccessResponse(NULL);
- }
- }
- return command->InternalErrorResponse("No WebContents to reload");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageGetNavigationHistory(
- scoped_refptr<DevToolsProtocol::Command> command) {
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (host) {
- WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
- if (web_contents) {
- base::DictionaryValue* result = new base::DictionaryValue();
- NavigationController& controller = web_contents->GetController();
- result->SetInteger(
- devtools::Page::getNavigationHistory::kResponseCurrentIndex,
- controller.GetCurrentEntryIndex());
- base::ListValue* entries = new base::ListValue();
- for (int i = 0; i != controller.GetEntryCount(); ++i) {
- const NavigationEntry* entry = controller.GetEntryAtIndex(i);
- base::DictionaryValue* entry_value = new base::DictionaryValue();
- entry_value->SetInteger(
- devtools::Page::NavigationEntry::kParamId,
- entry->GetUniqueID());
- entry_value->SetString(
- devtools::Page::NavigationEntry::kParamUrl,
- entry->GetURL().spec());
- entry_value->SetString(
- devtools::Page::NavigationEntry::kParamTitle,
- entry->GetTitle());
- entries->Append(entry_value);
- }
- result->Set(
- devtools::Page::getNavigationHistory::kResponseEntries,
- entries);
- return command->SuccessResponse(result);
- }
- }
- return command->InternalErrorResponse("No WebContents to navigate");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageNavigateToHistoryEntry(
- scoped_refptr<DevToolsProtocol::Command> command) {
- int entry_id;
-
- base::DictionaryValue* params = command->params();
- const char* param = devtools::Page::navigateToHistoryEntry::kParamEntryId;
- if (!params || !params->GetInteger(param, &entry_id)) {
- return command->InvalidParamResponse(param);
- }
-
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (host) {
- WebContents* web_contents = host->GetDelegate()->GetAsWebContents();
- if (web_contents) {
- NavigationController& controller = web_contents->GetController();
- for (int i = 0; i != controller.GetEntryCount(); ++i) {
- if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) {
- controller.GoToIndex(i);
- return command->SuccessResponse(new base::DictionaryValue());
- }
- }
- return command->InvalidParamResponse(param);
- }
- }
- return command->InternalErrorResponse("No WebContents to navigate");
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageCaptureScreenshot(
- scoped_refptr<DevToolsProtocol::Command> command) {
- RenderViewHost* host = agent_->GetRenderViewHost();
- if (!host->GetView())
- return command->InternalErrorResponse("Unable to access the view");
-
- gfx::Rect view_bounds = host->GetView()->GetViewBounds();
- gfx::Rect snapshot_bounds(view_bounds.size());
- gfx::Size snapshot_size = snapshot_bounds.size();
-
- std::vector<unsigned char> png_data;
- if (ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
- &png_data,
- snapshot_bounds)) {
- if (png_data.size())
- return command->SuccessResponse(CreateScreenshotResponse(png_data));
- else
- return command->InternalErrorResponse("Unable to capture screenshot");
- }
-
- ui::GrabViewSnapshotAsync(
- host->GetView()->GetNativeView(),
- snapshot_bounds,
- base::ThreadTaskRunnerHandle::Get(),
- base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
- weak_factory_.GetWeakPtr(), command));
- return command->AsyncResponsePromise();
-}
-
-void RendererOverridesHandler::ScreenshotCaptured(
- scoped_refptr<DevToolsProtocol::Command> command,
- scoped_refptr<base::RefCountedBytes> png_data) {
- if (png_data) {
- SendAsyncResponse(
- command->SuccessResponse(CreateScreenshotResponse(png_data->data())));
- } else {
- SendAsyncResponse(
- command->InternalErrorResponse("Unable to capture screenshot"));
- }
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageCanScreencast(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* result = new base::DictionaryValue();
-#if defined(OS_ANDROID)
- result->SetBoolean(devtools::kResult, true);
-#else
- result->SetBoolean(devtools::kResult, false);
-#endif // defined(OS_ANDROID)
- return command->SuccessResponse(result);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageStartScreencast(
- scoped_refptr<DevToolsProtocol::Command> command) {
- screencast_command_ = command;
- RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
- agent_->GetRenderViewHost());
- bool visible = !host->is_hidden();
- NotifyScreencastVisibility(visible);
- if (visible)
- InnerSwapCompositorFrame();
- return command->SuccessResponse(NULL);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageStopScreencast(
- scoped_refptr<DevToolsProtocol::Command> command) {
- last_frame_time_ = base::TimeTicks();
- screencast_command_ = NULL;
- return command->SuccessResponse(NULL);
-}
-
-void RendererOverridesHandler::ScreencastFrameCaptured(
- const std::string& format,
- int quality,
- const cc::CompositorFrameMetadata& metadata,
- bool success,
- const SkBitmap& bitmap) {
- if (!success) {
- if (capture_retry_count_) {
- --capture_retry_count_;
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&RendererOverridesHandler::InnerSwapCompositorFrame,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kFrameRateThresholdMs));
- }
- return;
- }
-
- std::vector<unsigned char> data;
- SkAutoLockPixels lock_image(bitmap);
- bool encoded;
- if (format == kPng) {
- encoded = gfx::PNGCodec::Encode(
- reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
- gfx::PNGCodec::FORMAT_SkBitmap,
- gfx::Size(bitmap.width(), bitmap.height()),
- bitmap.width() * bitmap.bytesPerPixel(),
- false, std::vector<gfx::PNGCodec::Comment>(), &data);
- } else if (format == kJpeg) {
- encoded = gfx::JPEGCodec::Encode(
- reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)),
- gfx::JPEGCodec::FORMAT_SkBitmap,
- bitmap.width(),
- bitmap.height(),
- bitmap.width() * bitmap.bytesPerPixel(),
- quality, &data);
- } else {
- encoded = false;
- }
-
- if (!encoded)
- return;
-
- std::string base_64_data;
- base::Base64Encode(
- base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()),
- &base_64_data);
-
- base::DictionaryValue* response = new base::DictionaryValue();
- response->SetString(devtools::Page::screencastFrame::kParamData,
- base_64_data);
-
- // Consider metadata empty in case it has no device scale factor.
- if (metadata.device_scale_factor != 0) {
- base::DictionaryValue* response_metadata = new base::DictionaryValue();
-
- response_metadata->SetDouble(
- devtools::Page::ScreencastFrameMetadata::kParamDeviceScaleFactor,
- metadata.device_scale_factor);
- response_metadata->SetDouble(
- devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactor,
- metadata.page_scale_factor);
- response_metadata->SetDouble(
- devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMin,
- metadata.min_page_scale_factor);
- response_metadata->SetDouble(
- devtools::Page::ScreencastFrameMetadata::kParamPageScaleFactorMax,
- metadata.max_page_scale_factor);
- response_metadata->SetDouble(
- devtools::Page::ScreencastFrameMetadata::kParamOffsetTop,
- metadata.location_bar_content_translation.y());
- response_metadata->SetDouble(
- devtools::Page::ScreencastFrameMetadata::kParamOffsetBottom,
- metadata.overdraw_bottom_height);
-
- base::DictionaryValue* viewport = new base::DictionaryValue();
- viewport->SetDouble(devtools::DOM::Rect::kParamX,
- metadata.root_scroll_offset.x());
- viewport->SetDouble(devtools::DOM::Rect::kParamY,
- metadata.root_scroll_offset.y());
- viewport->SetDouble(devtools::DOM::Rect::kParamWidth,
- metadata.viewport_size.width());
- viewport->SetDouble(devtools::DOM::Rect::kParamHeight,
- metadata.viewport_size.height());
- response_metadata->Set(
- devtools::Page::ScreencastFrameMetadata::kParamViewport, viewport);
-
- response->Set(devtools::Page::screencastFrame::kParamMetadata,
- response_metadata);
- }
-
- SendNotification(devtools::Page::screencastFrame::kName, response);
-}
-
-// Quota and Usage ------------------------------------------
-
-namespace {
-
-typedef base::Callback<void(scoped_ptr<base::DictionaryValue>)>
- ResponseCallback;
-
-void QueryUsageAndQuotaCompletedOnIOThread(
- scoped_ptr<base::DictionaryValue> quota,
- scoped_ptr<base::DictionaryValue> usage,
- ResponseCallback callback) {
-
- scoped_ptr<base::DictionaryValue> response_data(new base::DictionaryValue);
- response_data->Set(devtools::Page::queryUsageAndQuota::kResponseQuota,
- quota.release());
- response_data->Set(devtools::Page::queryUsageAndQuota::kResponseUsage,
- usage.release());
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(callback, base::Passed(&response_data)));
-}
-
-void DidGetHostUsage(
- base::ListValue* list,
- const std::string& client_id,
- const base::Closure& barrier,
- int64 value) {
- base::DictionaryValue* usage_item = new base::DictionaryValue;
- usage_item->SetString(devtools::Page::UsageItem::kParamId, client_id);
- usage_item->SetDouble(devtools::Page::UsageItem::kParamValue, value);
- list->Append(usage_item);
- barrier.Run();
-}
-
-void DidGetQuotaValue(
- base::DictionaryValue* dictionary,
- const std::string& item_name,
- const base::Closure& barrier,
- quota::QuotaStatusCode status,
- int64 value) {
- if (status == quota::kQuotaStatusOk)
- dictionary->SetDouble(item_name, value);
- barrier.Run();
-}
-
-void DidGetUsageAndQuotaForWebApps(
- base::DictionaryValue* quota,
- const std::string& item_name,
- const base::Closure& barrier,
- quota::QuotaStatusCode status,
- int64 used_bytes,
- int64 quota_in_bytes) {
- if (status == quota::kQuotaStatusOk)
- quota->SetDouble(item_name, quota_in_bytes);
- barrier.Run();
-}
-
-std::string GetStorageTypeName(quota::StorageType type) {
- switch (type) {
- case quota::kStorageTypeTemporary:
- return devtools::Page::Usage::kParamTemporary;
- case quota::kStorageTypePersistent:
- return devtools::Page::Usage::kParamPersistent;
- case quota::kStorageTypeSyncable:
- return devtools::Page::Usage::kParamSyncable;
- case quota::kStorageTypeQuotaNotManaged:
- case quota::kStorageTypeUnknown:
- NOTREACHED();
- }
- return "";
-}
-
-std::string GetQuotaClientName(quota::QuotaClient::ID id) {
- switch (id) {
- case quota::QuotaClient::kFileSystem:
- return devtools::Page::UsageItem::Id::kEnumFilesystem;
- case quota::QuotaClient::kDatabase:
- return devtools::Page::UsageItem::Id::kEnumDatabase;
- case quota::QuotaClient::kAppcache:
- return devtools::Page::UsageItem::Id::kEnumAppcache;
- case quota::QuotaClient::kIndexedDatabase:
- return devtools::Page::UsageItem::Id::kEnumIndexeddatabase;
- default:
- NOTREACHED();
- return "";
- }
-}
-
-void QueryUsageAndQuotaOnIOThread(
- scoped_refptr<quota::QuotaManager> quota_manager,
- const GURL& security_origin,
- const ResponseCallback& callback) {
- scoped_ptr<base::DictionaryValue> quota(new base::DictionaryValue);
- scoped_ptr<base::DictionaryValue> usage(new base::DictionaryValue);
-
- static quota::QuotaClient::ID kQuotaClients[] = {
- quota::QuotaClient::kFileSystem,
- quota::QuotaClient::kDatabase,
- quota::QuotaClient::kAppcache,
- quota::QuotaClient::kIndexedDatabase
- };
-
- static const size_t kStorageTypeCount = quota::kStorageTypeUnknown;
- std::map<quota::StorageType, base::ListValue*> storage_type_lists;
-
- for (size_t i = 0; i != kStorageTypeCount; i++) {
- const quota::StorageType type = static_cast<quota::StorageType>(i);
- if (type == quota::kStorageTypeQuotaNotManaged)
- continue;
- storage_type_lists[type] = new base::ListValue;
- usage->Set(GetStorageTypeName(type), storage_type_lists[type]);
- }
-
- const int kExpectedResults =
- 2 + arraysize(kQuotaClients) * storage_type_lists.size();
- base::DictionaryValue* quota_raw_ptr = quota.get();
-
- // Takes ownership on usage and quota.
- base::Closure barrier = BarrierClosure(
- kExpectedResults,
- base::Bind(&QueryUsageAndQuotaCompletedOnIOThread,
- base::Passed(&quota),
- base::Passed(&usage),
- callback));
- std::string host = net::GetHostOrSpecFromURL(security_origin);
-
- quota_manager->GetUsageAndQuotaForWebApps(
- security_origin,
- quota::kStorageTypeTemporary,
- base::Bind(&DidGetUsageAndQuotaForWebApps, quota_raw_ptr,
- std::string(devtools::Page::Quota::kParamTemporary), barrier));
-
- quota_manager->GetPersistentHostQuota(
- host,
- base::Bind(&DidGetQuotaValue, quota_raw_ptr,
- std::string(devtools::Page::Quota::kParamPersistent),
- barrier));
-
- for (size_t i = 0; i != arraysize(kQuotaClients); i++) {
- std::map<quota::StorageType, base::ListValue*>::const_iterator iter;
- for (iter = storage_type_lists.begin();
- iter != storage_type_lists.end(); ++iter) {
- const quota::StorageType type = (*iter).first;
- if (!quota_manager->IsTrackingHostUsage(type, kQuotaClients[i])) {
- barrier.Run();
- continue;
- }
- quota_manager->GetHostUsage(
- host, type, kQuotaClients[i],
- base::Bind(&DidGetHostUsage, (*iter).second,
- GetQuotaClientName(kQuotaClients[i]),
- barrier));
- }
- }
-}
-
-} // namespace
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::PageQueryUsageAndQuota(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- std::string security_origin;
- if (!params || !params->GetString(
- devtools::Page::queryUsageAndQuota::kParamSecurityOrigin,
- &security_origin)) {
- return command->InvalidParamResponse(
- devtools::Page::queryUsageAndQuota::kParamSecurityOrigin);
- }
-
- ResponseCallback callback = base::Bind(
- &RendererOverridesHandler::PageQueryUsageAndQuotaCompleted,
- weak_factory_.GetWeakPtr(),
- command);
-
- scoped_refptr<quota::QuotaManager> quota_manager =
- agent_->GetRenderViewHost()->GetProcess()->
- GetStoragePartition()->GetQuotaManager();
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &QueryUsageAndQuotaOnIOThread,
- quota_manager,
- GURL(security_origin),
- callback));
-
- return command->AsyncResponsePromise();
-}
-
-void RendererOverridesHandler::PageQueryUsageAndQuotaCompleted(
- scoped_refptr<DevToolsProtocol::Command> command,
- scoped_ptr<base::DictionaryValue> response_data) {
- SendAsyncResponse(command->SuccessResponse(response_data.release()));
-}
-
-void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) {
- if (visible)
- capture_retry_count_ = kCaptureRetryLimit;
- base::DictionaryValue* params = new base::DictionaryValue();
- params->SetBoolean(
- devtools::Page::screencastVisibilityChanged::kParamVisible, visible);
- SendNotification(
- devtools::Page::screencastVisibilityChanged::kName, params);
-}
-
-// Input agent handlers ------------------------------------------------------
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::InputDispatchMouseEvent(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- if (!params)
- return NULL;
-
- bool device_space = false;
- if (!params->GetBoolean(
- devtools::Input::dispatchMouseEvent::kParamDeviceSpace,
- &device_space) ||
- !device_space) {
- return NULL;
- }
-
- RenderViewHost* host = agent_->GetRenderViewHost();
- blink::WebMouseEvent mouse_event;
- ParseGenericInputParams(params, &mouse_event);
-
- std::string type;
- if (params->GetString(devtools::Input::dispatchMouseEvent::kParamType,
- &type)) {
- if (type ==
- devtools::Input::dispatchMouseEvent::Type::kEnumMousePressed)
- mouse_event.type = WebInputEvent::MouseDown;
- else if (type ==
- devtools::Input::dispatchMouseEvent::Type::kEnumMouseReleased)
- mouse_event.type = WebInputEvent::MouseUp;
- else if (type ==
- devtools::Input::dispatchMouseEvent::Type::kEnumMouseMoved)
- mouse_event.type = WebInputEvent::MouseMove;
- else
- return NULL;
- } else {
- return NULL;
- }
-
- if (!params->GetInteger(devtools::Input::dispatchMouseEvent::kParamX,
- &mouse_event.x) ||
- !params->GetInteger(devtools::Input::dispatchMouseEvent::kParamY,
- &mouse_event.y)) {
- return NULL;
- }
-
- mouse_event.windowX = mouse_event.x;
- mouse_event.windowY = mouse_event.y;
- mouse_event.globalX = mouse_event.x;
- mouse_event.globalY = mouse_event.y;
-
- params->GetInteger(devtools::Input::dispatchMouseEvent::kParamClickCount,
- &mouse_event.clickCount);
-
- std::string button;
- if (!params->GetString(devtools::Input::dispatchMouseEvent::kParamButton,
- &button)) {
- return NULL;
- }
-
- if (button == "none") {
- mouse_event.button = WebMouseEvent::ButtonNone;
- } else if (button == "left") {
- mouse_event.button = WebMouseEvent::ButtonLeft;
- mouse_event.modifiers |= WebInputEvent::LeftButtonDown;
- } else if (button == "middle") {
- mouse_event.button = WebMouseEvent::ButtonMiddle;
- mouse_event.modifiers |= WebInputEvent::MiddleButtonDown;
- } else if (button == "right") {
- mouse_event.button = WebMouseEvent::ButtonRight;
- mouse_event.modifiers |= WebInputEvent::RightButtonDown;
- } else {
- return NULL;
- }
-
- host->ForwardMouseEvent(mouse_event);
- return command->SuccessResponse(NULL);
-}
-
-scoped_refptr<DevToolsProtocol::Response>
-RendererOverridesHandler::InputDispatchGestureEvent(
- scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- if (!params)
- return NULL;
-
- RenderViewHostImpl* host = static_cast<RenderViewHostImpl*>(
- agent_->GetRenderViewHost());
- blink::WebGestureEvent event;
- ParseGenericInputParams(params, &event);
- event.sourceDevice = blink::WebGestureDeviceTouchscreen;
-
- std::string type;
- if (params->GetString(devtools::Input::dispatchGestureEvent::kParamType,
- &type)) {
- if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumScrollBegin)
- event.type = WebInputEvent::GestureScrollBegin;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumScrollUpdate)
- event.type = WebInputEvent::GestureScrollUpdate;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumScrollEnd)
- event.type = WebInputEvent::GestureScrollEnd;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumTapDown)
- event.type = WebInputEvent::GestureTapDown;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumTap)
- event.type = WebInputEvent::GestureTap;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumPinchBegin)
- event.type = WebInputEvent::GesturePinchBegin;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumPinchUpdate)
- event.type = WebInputEvent::GesturePinchUpdate;
- else if (type ==
- devtools::Input::dispatchGestureEvent::Type::kEnumPinchEnd)
- event.type = WebInputEvent::GesturePinchEnd;
- else
- return NULL;
- } else {
- return NULL;
- }
-
- if (!params->GetInteger(devtools::Input::dispatchGestureEvent::kParamX,
- &event.x) ||
- !params->GetInteger(devtools::Input::dispatchGestureEvent::kParamY,
- &event.y)) {
- return NULL;
- }
- event.globalX = event.x;
- event.globalY = event.y;
-
- if (type == "scrollUpdate") {
- int dx;
- int dy;
- if (!params->GetInteger(
- devtools::Input::dispatchGestureEvent::kParamDeltaX, &dx) ||
- !params->GetInteger(
- devtools::Input::dispatchGestureEvent::kParamDeltaY, &dy)) {
- return NULL;
- }
- event.data.scrollUpdate.deltaX = dx;
- event.data.scrollUpdate.deltaY = dy;
- }
-
- if (type == "pinchUpdate") {
- double scale;
- if (!params->GetDouble(
- devtools::Input::dispatchGestureEvent::kParamPinchScale,
- &scale)) {
- return NULL;
- }
- event.data.pinchUpdate.scale = static_cast<float>(scale);
- }
-
- host->ForwardGestureEvent(event);
- return command->SuccessResponse(NULL);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler.h b/chromium/content/browser/devtools/renderer_overrides_handler.h
deleted file mode 100644
index 0f7f8bc6cba..00000000000
--- a/chromium/content/browser/devtools/renderer_overrides_handler.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_BROWSER_DEVTOOLS_RENDERER_OVERRIDES_HANDLER_H_
-#define CONTENT_BROWSER_DEVTOOLS_RENDERER_OVERRIDES_HANDLER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "cc/output/compositor_frame_metadata.h"
-#include "content/browser/devtools/devtools_protocol.h"
-#include "content/common/content_export.h"
-
-class SkBitmap;
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-
-class DevToolsAgentHost;
-class DevToolsTracingHandler;
-
-// Overrides Inspector commands before they are sent to the renderer.
-// May override the implementation completely, ignore it, or handle
-// additional browser process implementation details.
-class CONTENT_EXPORT RendererOverridesHandler
- : public DevToolsProtocol::Handler {
- public:
- explicit RendererOverridesHandler(DevToolsAgentHost* agent);
- virtual ~RendererOverridesHandler();
-
- void OnClientDetached();
- void OnSwapCompositorFrame(const cc::CompositorFrameMetadata& frame_metadata);
- void OnVisibilityChanged(bool visible);
-
- private:
- void InnerSwapCompositorFrame();
- void ParseCaptureParameters(DevToolsProtocol::Command* command,
- std::string* format, int* quality,
- double* scale);
- base::DictionaryValue* CreateScreenshotResponse(
- const std::vector<unsigned char>& png_data);
-
- // DOM domain.
- scoped_refptr<DevToolsProtocol::Response>
- GrantPermissionsForSetFileInputFiles(
- scoped_refptr<DevToolsProtocol::Command> command);
-
- // Network domain.
- scoped_refptr<DevToolsProtocol::Response> ClearBrowserCache(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> ClearBrowserCookies(
- scoped_refptr<DevToolsProtocol::Command> command);
-
- // Page domain.
- scoped_refptr<DevToolsProtocol::Response> PageDisable(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageHandleJavaScriptDialog(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageNavigate(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageReload(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageGetNavigationHistory(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageNavigateToHistoryEntry(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageCaptureScreenshot(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageCanScreencast(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageStartScreencast(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageStopScreencast(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> PageQueryUsageAndQuota(
- scoped_refptr<DevToolsProtocol::Command>);
-
- void ScreenshotCaptured(
- scoped_refptr<DevToolsProtocol::Command> command,
- scoped_refptr<base::RefCountedBytes> png_data);
-
- void ScreencastFrameCaptured(
- const std::string& format,
- int quality,
- const cc::CompositorFrameMetadata& metadata,
- bool success,
- const SkBitmap& bitmap);
-
- void PageQueryUsageAndQuotaCompleted(
- scoped_refptr<DevToolsProtocol::Command>,
- scoped_ptr<base::DictionaryValue> response_data);
-
- void NotifyScreencastVisibility(bool visible);
-
- // Input domain.
- scoped_refptr<DevToolsProtocol::Response> InputDispatchMouseEvent(
- scoped_refptr<DevToolsProtocol::Command> command);
- scoped_refptr<DevToolsProtocol::Response> InputDispatchGestureEvent(
- scoped_refptr<DevToolsProtocol::Command> command);
-
- DevToolsAgentHost* agent_;
- scoped_refptr<DevToolsProtocol::Command> screencast_command_;
- cc::CompositorFrameMetadata last_compositor_frame_metadata_;
- base::TimeTicks last_frame_time_;
- int capture_retry_count_;
- base::WeakPtrFactory<RendererOverridesHandler> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(RendererOverridesHandler);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_RENDERER_OVERRIDES_HANDLER_H_
diff --git a/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc b/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc
index d869d9d6e6c..fd02c091234 100644
--- a/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc
+++ b/chromium/content/browser/devtools/renderer_overrides_handler_browsertest.cc
@@ -2,37 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/basictypes.h"
+#include "base/base64.h"
+#include "base/command_line.h"
#include "base/json/json_reader.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/devtools/renderer_overrides_handler.h"
+#include "content/browser/devtools/devtools_protocol.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/gfx/codec/png_codec.h"
namespace content {
-class RendererOverridesHandlerTest : public ContentBrowserTest {
+class RendererOverridesHandlerTest : public ContentBrowserTest,
+ public DevToolsAgentHostClient {
protected:
- scoped_refptr<DevToolsProtocol::Response> SendCommand(
- const std::string& method,
- base::DictionaryValue* params) {
- scoped_ptr<RendererOverridesHandler> handler(CreateHandler());
- scoped_refptr<DevToolsProtocol::Command> command(
- DevToolsProtocol::CreateCommand(1, method, params));
- return handler->HandleCommand(command);
- }
-
- void SendAsyncCommand(const std::string& method,
- base::DictionaryValue* params) {
- scoped_ptr<RendererOverridesHandler> handler(CreateHandler());
- scoped_refptr<DevToolsProtocol::Command> command(
- DevToolsProtocol::CreateCommand(1, method, params));
- scoped_refptr<DevToolsProtocol::Response> response =
- handler->HandleCommand(command);
- EXPECT_TRUE(response->is_async_promise());
+ void SendCommand(const std::string& method,
+ base::DictionaryValue* params) {
+ agent_host_->DispatchProtocolMessage(
+ DevToolsProtocol::CreateCommand(1, method, params)->Serialize());
base::MessageLoop::current()->Run();
}
@@ -62,32 +53,38 @@ class RendererOverridesHandlerTest : public ContentBrowserTest {
}
scoped_ptr<base::DictionaryValue> result_;
+ scoped_refptr<DevToolsAgentHost> agent_host_;
private:
- RendererOverridesHandler* CreateHandler() {
- RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
- DevToolsAgentHost* agent = DevToolsAgentHost::GetOrCreateFor(rvh).get();
- scoped_ptr<RendererOverridesHandler> handler(
- new RendererOverridesHandler(agent));
- handler->SetNotifier(base::Bind(
- &RendererOverridesHandlerTest::OnMessageSent, base::Unretained(this)));
- return handler.release();
+ void SetUpOnMainThread() override {
+ agent_host_ = DevToolsAgentHost::GetOrCreateFor(shell()->web_contents());
+ agent_host_->AttachClient(this);
+ }
+
+ void TearDownOnMainThread() override {
+ agent_host_->DetachClient();
+ agent_host_ = NULL;
}
- void OnMessageSent(const std::string& message) {
+ void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) override {
scoped_ptr<base::DictionaryValue> root(
static_cast<base::DictionaryValue*>(base::JSONReader::Read(message)));
base::DictionaryValue* result;
- root->GetDictionary("result", &result);
+ EXPECT_TRUE(root->GetDictionary("result", &result));
result_.reset(result->DeepCopy());
base::MessageLoop::current()->QuitNow();
}
+
+ void AgentHostClosed(DevToolsAgentHost* agent_host, bool replaced) override {
+ EXPECT_TRUE(false);
+ }
};
IN_PROC_BROWSER_TEST_F(RendererOverridesHandlerTest, QueryUsageAndQuota) {
base::DictionaryValue* params = new base::DictionaryValue();
params->SetString("securityOrigin", "http://example.com");
- SendAsyncCommand("Page.queryUsageAndQuota", params);
+ SendCommand("Page.queryUsageAndQuota", params);
EXPECT_TRUE(HasValue("quota.persistent"));
EXPECT_TRUE(HasValue("quota.temporary"));
@@ -98,4 +95,43 @@ IN_PROC_BROWSER_TEST_F(RendererOverridesHandlerTest, QueryUsageAndQuota) {
EXPECT_TRUE(HasListItem("usage.persistent", "id", "filesystem"));
}
+class CaptureScreenshotTest : public RendererOverridesHandlerTest {
+ private:
+#if !defined(OS_ANDROID)
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
+ }
+#endif
+};
+
+// Does not link on Android
+#if defined(OS_ANDROID)
+#define MAYBE_CaptureScreenshot DISABLED_CaptureScreenshot
+#elif defined(OS_MACOSX) // Fails on 10.9. http://crbug.com/430620
+#define MAYBE_CaptureScreenshot DISABLED_CaptureScreenshot
+#elif defined(MEMORY_SANITIZER)
+// Also fails under MSAN. http://crbug.com/423583
+#define MAYBE_CaptureScreenshot DISABLED_CaptureScreenshot
+#else
+#define MAYBE_CaptureScreenshot CaptureScreenshot
+#endif
+IN_PROC_BROWSER_TEST_F(CaptureScreenshotTest, MAYBE_CaptureScreenshot) {
+ shell()->LoadURL(GURL("about:blank"));
+ EXPECT_TRUE(content::ExecuteScript(
+ shell()->web_contents()->GetRenderViewHost(),
+ "document.body.style.background = '#123456'"));
+ SendCommand("Page.captureScreenshot", new base::DictionaryValue());
+ std::string base64;
+ EXPECT_TRUE(result_->GetString("data", &base64));
+ std::string png;
+ EXPECT_TRUE(base::Base64Decode(base64, &png));
+ SkBitmap bitmap;
+ gfx::PNGCodec::Decode(reinterpret_cast<const unsigned char*>(png.data()),
+ png.size(), &bitmap);
+ SkColor color(bitmap.getColor(0, 0));
+ EXPECT_TRUE(std::abs(0x12-(int)SkColorGetR(color)) <= 1);
+ EXPECT_TRUE(std::abs(0x34-(int)SkColorGetG(color)) <= 1);
+ EXPECT_TRUE(std::abs(0x56-(int)SkColorGetB(color)) <= 1);
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/tethering_handler.cc b/chromium/content/browser/devtools/tethering_handler.cc
index 9b3b7fa005a..e0c083dd8ea 100644
--- a/chromium/content/browser/devtools/tethering_handler.cc
+++ b/chromium/content/browser/devtools/tethering_handler.cc
@@ -9,7 +9,8 @@
#include "base/stl_util.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_http_handler_impl.h"
-#include "content/public/browser/devtools_client_host.h"
+#include "content/browser/devtools/devtools_protocol_constants.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_http_handler_delegate.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
@@ -23,21 +24,13 @@ namespace content {
namespace {
-const char kTetheringBind[] = "Tethering.bind";
-const char kTetheringUnbind[] = "Tethering.unbind";
-
-const char kTetheringAccepted[] = "Tethering.accepted";
-
-const char kPortParam[] = "port";
-const char kConnectionIdParam[] = "connectionId";
-
const char kLocalhost[] = "127.0.0.1";
const int kListenBacklog = 5;
const int kBufferSize = 16 * 1024;
-const int kMinTetheringPort = 5000;
-const int kMaxTetheringPort = 10000;
+const int kMinTetheringPort = 1024;
+const int kMaxTetheringPort = 32767;
class SocketPump : public net::StreamListenSocket::Delegate {
public:
@@ -57,11 +50,11 @@ class SocketPump : public net::StreamListenSocket::Delegate {
return channel_name;
}
- virtual ~SocketPump() { }
+ ~SocketPump() override {}
private:
- virtual void DidAccept(net::StreamListenSocket* server,
- scoped_ptr<net::StreamListenSocket> socket) OVERRIDE {
+ void DidAccept(net::StreamListenSocket* server,
+ scoped_ptr<net::StreamListenSocket> socket) override {
if (accepted_socket_.get())
return;
@@ -78,9 +71,9 @@ class SocketPump : public net::StreamListenSocket::Delegate {
OnClientRead(result);
}
- virtual void DidRead(net::StreamListenSocket* socket,
- const char* data,
- int len) OVERRIDE {
+ void DidRead(net::StreamListenSocket* socket,
+ const char* data,
+ int len) override {
int old_size = wire_buffer_size_;
wire_buffer_size_ += len;
while (wire_buffer_->capacity() < wire_buffer_size_)
@@ -91,9 +84,7 @@ class SocketPump : public net::StreamListenSocket::Delegate {
OnClientWrite(0);
}
- virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE {
- SelfDestruct();
- }
+ void DidClose(net::StreamListenSocket* socket) override { SelfDestruct(); }
void OnClientRead(int result) {
if (result <= 0) {
@@ -111,8 +102,10 @@ class SocketPump : public net::StreamListenSocket::Delegate {
}
void OnClientWrite(int result) {
- if (result < 0)
+ if (result < 0) {
SelfDestruct();
+ return;
+ }
wire_buffer_->set_offset(wire_buffer_->offset() + result);
@@ -149,7 +142,7 @@ class SocketPump : public net::StreamListenSocket::Delegate {
}
void SelfDestruct() {
- if (wire_buffer_ && wire_buffer_->offset() != wire_buffer_size_) {
+ if (wire_buffer_.get() && wire_buffer_->offset() != wire_buffer_size_) {
pending_destruction_ = true;
return;
}
@@ -167,15 +160,24 @@ class SocketPump : public net::StreamListenSocket::Delegate {
bool pending_destruction_;
};
-} // namespace
-
-const char TetheringHandler::kDomain[] = "Tethering";
+static int GetPort(scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& paramName) {
+ base::DictionaryValue* params = command->params();
+ int port = 0;
+ if (!params ||
+ !params->GetInteger(paramName, &port) ||
+ port < kMinTetheringPort || port > kMaxTetheringPort)
+ return 0;
+ return port;
+}
-class TetheringHandler::BoundSocket {
+class BoundSocket {
public:
- BoundSocket(TetheringHandler* handler,
+ typedef base::Callback<void(int, const std::string&)> AcceptedCallback;
+
+ BoundSocket(AcceptedCallback accepted_callback,
DevToolsHttpHandlerDelegate* delegate)
- : handler_(handler),
+ : accepted_callback_(accepted_callback),
delegate_(delegate),
socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
port_(0) {
@@ -232,77 +234,208 @@ class TetheringHandler::BoundSocket {
SocketPump* pump = new SocketPump(delegate_, accept_socket_.release());
std::string name = pump->Init();
if (!name.empty())
- handler_->Accepted(port_, name);
+ accepted_callback_.Run(port_, name);
}
- TetheringHandler* handler_;
+ AcceptedCallback accepted_callback_;
DevToolsHttpHandlerDelegate* delegate_;
scoped_ptr<net::ServerSocket> socket_;
scoped_ptr<net::StreamSocket> accept_socket_;
int port_;
};
-TetheringHandler::TetheringHandler(DevToolsHttpHandlerDelegate* delegate)
- : delegate_(delegate) {
- RegisterCommandHandler(kTetheringBind,
+} // namespace
+
+// TetheringHandler::TetheringImpl -------------------------------------------
+
+class TetheringHandler::TetheringImpl {
+ public:
+ TetheringImpl(
+ base::WeakPtr<TetheringHandler> handler,
+ DevToolsHttpHandlerDelegate* delegate);
+ ~TetheringImpl();
+
+ void Bind(scoped_refptr<DevToolsProtocol::Command> command, int port);
+ void Unbind(scoped_refptr<DevToolsProtocol::Command> command, int port);
+ void Accepted(int port, const std::string& name);
+
+ private:
+ void SendInternalError(scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message);
+
+ base::WeakPtr<TetheringHandler> handler_;
+ DevToolsHttpHandlerDelegate* delegate_;
+
+ typedef std::map<int, BoundSocket*> BoundSockets;
+ BoundSockets bound_sockets_;
+};
+
+TetheringHandler::TetheringImpl::TetheringImpl(
+ base::WeakPtr<TetheringHandler> handler,
+ DevToolsHttpHandlerDelegate* delegate)
+ : handler_(handler),
+ delegate_(delegate) {
+}
+
+TetheringHandler::TetheringImpl::~TetheringImpl() {
+ STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
+ bound_sockets_.end());
+}
+
+void TetheringHandler::TetheringImpl::Bind(
+ scoped_refptr<DevToolsProtocol::Command> command, int port) {
+ if (bound_sockets_.find(port) != bound_sockets_.end()) {
+ SendInternalError(command, "Port already bound");
+ return;
+ }
+
+ BoundSocket::AcceptedCallback callback = base::Bind(
+ &TetheringHandler::TetheringImpl::Accepted, base::Unretained(this));
+ scoped_ptr<BoundSocket> bound_socket(new BoundSocket(callback, delegate_));
+ if (!bound_socket->Listen(port)) {
+ SendInternalError(command, "Could not bind port");
+ return;
+ }
+
+ bound_sockets_[port] = bound_socket.release();
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&TetheringHandler::SendBindSuccess, handler_, command));
+}
+
+void TetheringHandler::TetheringImpl::Unbind(
+ scoped_refptr<DevToolsProtocol::Command> command, int port) {
+
+ BoundSockets::iterator it = bound_sockets_.find(port);
+ if (it == bound_sockets_.end()) {
+ SendInternalError(command, "Port is not bound");
+ return;
+ }
+
+ delete it->second;
+ bound_sockets_.erase(it);
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&TetheringHandler::SendUnbindSuccess, handler_, command));
+}
+
+void TetheringHandler::TetheringImpl::Accepted(
+ int port, const std::string& name) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&TetheringHandler::Accepted, handler_, port, name));
+}
+
+void TetheringHandler::TetheringImpl::SendInternalError(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&TetheringHandler::SendInternalError, handler_,
+ command, message));
+}
+
+
+// TetheringHandler ----------------------------------------------------------
+
+// static
+TetheringHandler::TetheringImpl* TetheringHandler::impl_ = nullptr;
+
+TetheringHandler::TetheringHandler(
+ DevToolsHttpHandlerDelegate* delegate,
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy)
+ : delegate_(delegate),
+ message_loop_proxy_(message_loop_proxy),
+ is_active_(false),
+ weak_factory_(this) {
+ RegisterCommandHandler(devtools::Tethering::bind::kName,
base::Bind(&TetheringHandler::OnBind,
base::Unretained(this)));
- RegisterCommandHandler(kTetheringUnbind,
+ RegisterCommandHandler(devtools::Tethering::unbind::kName,
base::Bind(&TetheringHandler::OnUnbind,
base::Unretained(this)));
}
TetheringHandler::~TetheringHandler() {
- STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
- bound_sockets_.end());
+ if (is_active_) {
+ message_loop_proxy_->DeleteSoon(FROM_HERE, impl_);
+ impl_ = nullptr;
+ }
}
void TetheringHandler::Accepted(int port, const std::string& name) {
base::DictionaryValue* params = new base::DictionaryValue();
- params->SetInteger(kPortParam, port);
- params->SetString(kConnectionIdParam, name);
- SendNotification(kTetheringAccepted, params);
+ params->SetInteger(devtools::Tethering::accepted::kParamPort, port);
+ params->SetString(devtools::Tethering::accepted::kParamConnectionId, name);
+ SendNotification(devtools::Tethering::accepted::kName, params);
}
-static int GetPort(scoped_refptr<DevToolsProtocol::Command> command) {
- base::DictionaryValue* params = command->params();
- int port = 0;
- if (!params || !params->GetInteger(kPortParam, &port) ||
- port < kMinTetheringPort || port > kMaxTetheringPort)
- return 0;
- return port;
+bool TetheringHandler::Activate() {
+ if (is_active_)
+ return true;
+ if (impl_)
+ return false;
+ is_active_ = true;
+ impl_ = new TetheringImpl(weak_factory_.GetWeakPtr(), delegate_);
+ return true;
}
scoped_refptr<DevToolsProtocol::Response>
TetheringHandler::OnBind(scoped_refptr<DevToolsProtocol::Command> command) {
- int port = GetPort(command);
+ const std::string& portParamName = devtools::Tethering::bind::kParamPort;
+ int port = GetPort(command, portParamName);
if (port == 0)
- return command->InvalidParamResponse(kPortParam);
-
- if (bound_sockets_.find(port) != bound_sockets_.end())
- return command->InternalErrorResponse("Port already bound");
+ return command->InvalidParamResponse(portParamName);
- scoped_ptr<BoundSocket> bound_socket(new BoundSocket(this, delegate_));
- if (!bound_socket->Listen(port))
- return command->InternalErrorResponse("Could not bind port");
-
- bound_sockets_[port] = bound_socket.release();
- return command->SuccessResponse(NULL);
+ if (!Activate()) {
+ return command->ServerErrorResponse(
+ "Tethering is used by another connection");
+ }
+ DCHECK(impl_);
+ message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&TetheringImpl::Bind, base::Unretained(impl_),
+ command, port));
+ return command->AsyncResponsePromise();
}
scoped_refptr<DevToolsProtocol::Response>
TetheringHandler::OnUnbind(scoped_refptr<DevToolsProtocol::Command> command) {
- int port = GetPort(command);
+ const std::string& portParamName = devtools::Tethering::unbind::kParamPort;
+ int port = GetPort(command, portParamName);
if (port == 0)
- return command->InvalidParamResponse(kPortParam);
+ return command->InvalidParamResponse(portParamName);
- BoundSockets::iterator it = bound_sockets_.find(port);
- if (it == bound_sockets_.end())
- return command->InternalErrorResponse("Port is not bound");
+ if (!Activate()) {
+ return command->ServerErrorResponse(
+ "Tethering is used by another connection");
+ }
+ DCHECK(impl_);
+ message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&TetheringImpl::Unbind, base::Unretained(impl_),
+ command, port));
+ return command->AsyncResponsePromise();
+}
- delete it->second;
- bound_sockets_.erase(it);
- return command->SuccessResponse(NULL);
+void TetheringHandler::SendBindSuccess(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ SendAsyncResponse(command->SuccessResponse(nullptr));
+}
+
+void TetheringHandler::SendUnbindSuccess(
+ scoped_refptr<DevToolsProtocol::Command> command) {
+ SendAsyncResponse(command->SuccessResponse(nullptr));
+}
+
+void TetheringHandler::SendInternalError(
+ scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message) {
+ SendAsyncResponse(command->InternalErrorResponse(message));
}
} // namespace content
diff --git a/chromium/content/browser/devtools/tethering_handler.h b/chromium/content/browser/devtools/tethering_handler.h
index 7086e1747db..d6e56b592fd 100644
--- a/chromium/content/browser/devtools/tethering_handler.h
+++ b/chromium/content/browser/devtools/tethering_handler.h
@@ -7,6 +7,8 @@
#include <map>
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/devtools/devtools_protocol.h"
namespace content {
@@ -16,23 +18,33 @@ class DevToolsHttpHandlerDelegate;
// This class implements reversed tethering handler.
class TetheringHandler : public DevToolsProtocol::Handler {
public:
- static const char kDomain[];
+ TetheringHandler(DevToolsHttpHandlerDelegate* delegate,
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy);
+ ~TetheringHandler() override;
- TetheringHandler(DevToolsHttpHandlerDelegate* delegate);
- virtual ~TetheringHandler();
+ private:
+ class TetheringImpl;
void Accepted(int port, const std::string& name);
+ bool Activate();
- private:
- class BoundSocket;
scoped_refptr<DevToolsProtocol::Response> OnBind(
scoped_refptr<DevToolsProtocol::Command> command);
scoped_refptr<DevToolsProtocol::Response> OnUnbind(
scoped_refptr<DevToolsProtocol::Command> command);
- typedef std::map<int, BoundSocket*> BoundSockets;
- BoundSockets bound_sockets_;
+ void SendBindSuccess(scoped_refptr<DevToolsProtocol::Command> command);
+ void SendUnbindSuccess(scoped_refptr<DevToolsProtocol::Command> command);
+ void SendInternalError(scoped_refptr<DevToolsProtocol::Command> command,
+ const std::string& message);
+
DevToolsHttpHandlerDelegate* delegate_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ bool is_active_;
+ base::WeakPtrFactory<TetheringHandler> weak_factory_;
+
+ static TetheringImpl* impl_;
+
DISALLOW_COPY_AND_ASSIGN(TetheringHandler);
};
diff --git a/chromium/content/browser/devtools/worker_devtools_manager.cc b/chromium/content/browser/devtools/worker_devtools_manager.cc
deleted file mode 100644
index 0658c353c64..00000000000
--- a/chromium/content/browser/devtools/worker_devtools_manager.cc
+++ /dev/null
@@ -1,453 +0,0 @@
-// Copyright (c) 2011 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 "content/browser/devtools/worker_devtools_manager.h"
-
-#include <list>
-#include <map>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
-#include "content/browser/devtools/devtools_protocol.h"
-#include "content/browser/devtools/devtools_protocol_constants.h"
-#include "content/browser/devtools/embedded_worker_devtools_manager.h"
-#include "content/browser/devtools/ipc_devtools_agent_host.h"
-#include "content/browser/devtools/worker_devtools_message_filter.h"
-#include "content/browser/worker_host/worker_service_impl.h"
-#include "content/common/devtools_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_data.h"
-#include "content/public/common/process_type.h"
-
-namespace content {
-
-// Called on the UI thread.
-// static
-scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker(
- int worker_process_id,
- int worker_route_id) {
- if (WorkerService::EmbeddedSharedWorkerEnabled()) {
- return EmbeddedWorkerDevToolsManager::GetInstance()
- ->GetDevToolsAgentHostForWorker(worker_process_id, worker_route_id);
- } else {
- return WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
- worker_process_id, worker_route_id);
- }
-}
-
-namespace {
-
-typedef std::map<WorkerDevToolsManager::WorkerId,
- WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts;
-base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-struct WorkerDevToolsManager::TerminatedInspectedWorker {
- TerminatedInspectedWorker(WorkerId id,
- const GURL& url,
- const base::string16& name)
- : old_worker_id(id),
- worker_url(url),
- worker_name(name) {}
- WorkerId old_worker_id;
- GURL worker_url;
- base::string16 worker_name;
-};
-
-
-class WorkerDevToolsManager::WorkerDevToolsAgentHost
- : public IPCDevToolsAgentHost {
- public:
- explicit WorkerDevToolsAgentHost(WorkerId worker_id)
- : has_worker_id_(false) {
- SetWorkerId(worker_id, false);
- }
-
- void SetWorkerId(WorkerId worker_id, bool reattach) {
- worker_id_ = worker_id;
- if (!has_worker_id_)
- AddRef(); // Balanced in ResetWorkerId.
- has_worker_id_ = true;
- g_agent_map.Get()[worker_id_] = this;
-
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &ConnectToWorker,
- worker_id.first,
- worker_id.second));
-
- if (reattach)
- Reattach(state_);
- }
-
- void ResetWorkerId() {
- g_agent_map.Get().erase(worker_id_);
- has_worker_id_ = false;
- Release(); // Balanced in SetWorkerId.
- }
-
- void SaveAgentRuntimeState(const std::string& state) {
- state_ = state;
- }
-
- void ConnectionFailed() {
- NotifyCloseListener();
- // Object can be deleted here.
- }
-
- private:
- virtual ~WorkerDevToolsAgentHost();
-
- static void ConnectToWorker(
- int worker_process_id,
- int worker_route_id) {
- WorkerDevToolsManager::GetInstance()->ConnectDevToolsAgentHostToWorker(
- worker_process_id, worker_route_id);
- }
-
- static void ForwardToWorkerDevToolsAgent(
- int worker_process_id,
- int worker_route_id,
- IPC::Message* message) {
- WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent(
- worker_process_id, worker_route_id, *message);
- }
-
- // IPCDevToolsAgentHost implementation.
- virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE {
- if (!has_worker_id_) {
- delete message;
- return;
- }
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent,
- worker_id_.first,
- worker_id_.second,
- base::Owned(message)));
- }
-
- virtual void OnClientAttached() OVERRIDE {}
- virtual void OnClientDetached() OVERRIDE {}
-
- bool has_worker_id_;
- WorkerId worker_id_;
- std::string state_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost);
-};
-
-
-class WorkerDevToolsManager::DetachedClientHosts {
- public:
- static void WorkerReloaded(WorkerId old_id, WorkerId new_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AgentHosts::iterator it = g_orphan_map.Get().find(old_id);
- if (it != g_orphan_map.Get().end()) {
- it->second->SetWorkerId(new_id, true);
- g_orphan_map.Get().erase(old_id);
- return;
- }
- RemovePendingWorkerData(old_id);
- }
-
- static void WorkerDestroyed(WorkerId id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- AgentHosts::iterator it = g_agent_map.Get().find(id);
- if (it == g_agent_map.Get().end()) {
- RemovePendingWorkerData(id);
- return;
- }
-
- WorkerDevToolsAgentHost* agent = it->second;
- DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance();
- if (!agent->IsAttached()) {
- // Agent has no client hosts -> delete it.
- RemovePendingWorkerData(id);
- return;
- }
-
- // Client host is debugging this worker agent host.
- std::string notification = DevToolsProtocol::CreateNotification(
- devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize();
- devtools_manager->DispatchOnInspectorFrontend(agent, notification);
- g_orphan_map.Get()[id] = agent;
- agent->ResetWorkerId();
- }
-
- static void RemovePendingWorkerData(WorkerId id) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&RemoveInspectedWorkerDataOnIOThread, id));
- }
-
- private:
- DetachedClientHosts() {}
- ~DetachedClientHosts() {}
-
- static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) {
- WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id);
- }
-};
-
-struct WorkerDevToolsManager::InspectedWorker {
- InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url,
- const base::string16& name)
- : host(host),
- route_id(route_id),
- worker_url(url),
- worker_name(name) {}
- WorkerProcessHost* const host;
- int const route_id;
- GURL worker_url;
- base::string16 worker_name;
-};
-
-// static
-WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() {
- DCHECK(!WorkerService::EmbeddedSharedWorkerEnabled());
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return Singleton<WorkerDevToolsManager>::get();
-}
-
-// static
-DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker(
- int worker_process_id,
- int worker_route_id) {
- DCHECK(!WorkerService::EmbeddedSharedWorkerEnabled());
- WorkerId id(worker_process_id, worker_route_id);
- AgentHosts::iterator it = g_agent_map.Get().find(id);
- if (it == g_agent_map.Get().end())
- return new WorkerDevToolsAgentHost(id);
- return it->second;
-}
-
-WorkerDevToolsManager::WorkerDevToolsManager() {
-}
-
-WorkerDevToolsManager::~WorkerDevToolsManager() {
-}
-
-bool WorkerDevToolsManager::WorkerCreated(
- WorkerProcessHost* worker,
- const WorkerProcessHost::WorkerInstance& instance) {
- for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin();
- it != terminated_workers_.end(); ++it) {
- if (instance.Matches(it->worker_url, it->worker_name,
- instance.partition(),
- instance.resource_context())) {
- WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id());
- paused_workers_[new_worker_id] = it->old_worker_id;
- terminated_workers_.erase(it);
- return true;
- }
- }
- return false;
-}
-
-void WorkerDevToolsManager::WorkerDestroyed(
- WorkerProcessHost* worker,
- int worker_route_id) {
- InspectedWorkersList::iterator it = FindInspectedWorker(
- worker->GetData().id,
- worker_route_id);
- if (it == inspected_workers_.end())
- return;
-
- WorkerId worker_id(worker->GetData().id, worker_route_id);
- terminated_workers_.push_back(TerminatedInspectedWorker(
- worker_id,
- it->worker_url,
- it->worker_name));
- inspected_workers_.erase(it);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id));
-}
-
-void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process,
- int worker_route_id) {
- WorkerId new_worker_id(process->GetData().id, worker_route_id);
- PausedWorkers::iterator it = paused_workers_.find(new_worker_id);
- if (it == paused_workers_.end())
- return;
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &DetachedClientHosts::WorkerReloaded,
- it->second,
- new_worker_id));
- paused_workers_.erase(it);
-}
-
-void WorkerDevToolsManager::RemoveInspectedWorkerData(
- const WorkerId& id) {
- for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin();
- it != terminated_workers_.end(); ++it) {
- if (it->old_worker_id == id) {
- terminated_workers_.erase(it);
- return;
- }
- }
-
- for (PausedWorkers::iterator it = paused_workers_.begin();
- it != paused_workers_.end(); ++it) {
- if (it->second == id) {
- SendResumeToWorker(it->first);
- paused_workers_.erase(it);
- return;
- }
- }
-}
-
-WorkerDevToolsManager::InspectedWorkersList::iterator
-WorkerDevToolsManager::FindInspectedWorker(
- int host_id, int route_id) {
- InspectedWorkersList::iterator it = inspected_workers_.begin();
- while (it != inspected_workers_.end()) {
- if (it->host->GetData().id == host_id && it->route_id == route_id)
- break;
- ++it;
- }
- return it;
-}
-
-static WorkerProcessHost* FindWorkerProcess(int worker_process_id) {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter.GetData().id == worker_process_id)
- return *iter;
- }
- return NULL;
-}
-
-void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker(
- int worker_process_id,
- int worker_route_id) {
- if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) {
- const WorkerProcessHost::Instances& instances = process->instances();
- for (WorkerProcessHost::Instances::const_iterator i = instances.begin();
- i != instances.end(); ++i) {
- if (i->worker_route_id() == worker_route_id) {
- DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) ==
- inspected_workers_.end());
- inspected_workers_.push_back(
- InspectedWorker(process, worker_route_id, i->url(), i->name()));
- return;
- }
- }
- }
- NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id);
-}
-
-void WorkerDevToolsManager::ForwardToDevToolsClient(
- int worker_process_id,
- int worker_route_id,
- const std::string& message) {
- if (FindInspectedWorker(worker_process_id, worker_route_id) ==
- inspected_workers_.end()) {
- NOTREACHED();
- return;
- }
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &ForwardToDevToolsClientOnUIThread,
- worker_process_id,
- worker_route_id,
- message));
-}
-
-void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id,
- int worker_route_id,
- const std::string& state) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &SaveAgentRuntimeStateOnUIThread,
- worker_process_id,
- worker_route_id,
- state));
-}
-
-void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent(
- int worker_process_id,
- int worker_route_id,
- const IPC::Message& message) {
- InspectedWorkersList::iterator it = FindInspectedWorker(
- worker_process_id,
- worker_route_id);
- if (it == inspected_workers_.end())
- return;
- IPC::Message* msg = new IPC::Message(message);
- msg->set_routing_id(worker_route_id);
- it->host->Send(msg);
-}
-
-// static
-void WorkerDevToolsManager::ForwardToDevToolsClientOnUIThread(
- int worker_process_id,
- int worker_route_id,
- const std::string& message) {
- AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id,
- worker_route_id));
- if (it == g_agent_map.Get().end())
- return;
- DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(it->second,
- message);
-}
-
-// static
-void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread(
- int worker_process_id,
- int worker_route_id,
- const std::string& state) {
- AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id,
- worker_route_id));
- if (it == g_agent_map.Get().end())
- return;
- it->second->SaveAgentRuntimeState(state);
-}
-
-// static
-void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread(
- int worker_process_id,
- int worker_route_id) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread,
- worker_process_id,
- worker_route_id));
-}
-
-// static
-void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread(
- int worker_process_id,
- int worker_route_id) {
- AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id,
- worker_route_id));
- if (it != g_agent_map.Get().end())
- it->second->ConnectionFailed();
-}
-
-// static
-void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) {
- if (WorkerProcessHost* process = FindWorkerProcess(id.first))
- process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second));
-}
-
-WorkerDevToolsManager::WorkerDevToolsAgentHost::~WorkerDevToolsAgentHost() {
- DetachedClientHosts::RemovePendingWorkerData(worker_id_);
- g_agent_map.Get().erase(worker_id_);
- g_orphan_map.Get().erase(worker_id_);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/worker_devtools_manager.h b/chromium/content/browser/devtools/worker_devtools_manager.h
deleted file mode 100644
index 73916c30fe2..00000000000
--- a/chromium/content/browser/devtools/worker_devtools_manager.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MANAGER_H_
-#define CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MANAGER_H_
-
-#include <list>
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/singleton.h"
-#include "content/browser/worker_host/worker_process_host.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class DevToolsAgentHost;
-
-// All methods are supposed to be called on the IO thread.
-// This class is not used when "enable-embedded-shared-worker" flag is set.
-class WorkerDevToolsManager {
- public:
- typedef std::pair<int, int> WorkerId;
- class WorkerDevToolsAgentHost;
-
- // Returns the WorkerDevToolsManager singleton.
- static WorkerDevToolsManager* GetInstance();
-
- // Called on the UI thread.
- static DevToolsAgentHost* GetDevToolsAgentHostForWorker(
- int worker_process_id,
- int worker_route_id);
-
- void ForwardToDevToolsClient(int worker_process_id,
- int worker_route_id,
- const std::string& message);
- void SaveAgentRuntimeState(int worker_process_id,
- int worker_route_id,
- const std::string& state);
-
- // Called on the IO thread.
- // Returns true when the worker must be paused on start.
- bool WorkerCreated(WorkerProcessHost* process,
- const WorkerProcessHost::WorkerInstance& instance);
- void WorkerDestroyed(WorkerProcessHost* process, int worker_route_id);
- void WorkerContextStarted(WorkerProcessHost* process, int worker_route_id);
-
- private:
- friend struct DefaultSingletonTraits<WorkerDevToolsManager>;
- class DetachedClientHosts;
- struct InspectedWorker;
- typedef std::list<InspectedWorker> InspectedWorkersList;
-
- WorkerDevToolsManager();
- virtual ~WorkerDevToolsManager();
-
- void RemoveInspectedWorkerData(const WorkerId& id);
- InspectedWorkersList::iterator FindInspectedWorker(int host_id, int route_id);
-
- void ConnectDevToolsAgentHostToWorker(int worker_process_id,
- int worker_route_id);
- void ForwardToWorkerDevToolsAgent(int worker_process_host_id,
- int worker_route_id,
- const IPC::Message& message);
- static void ForwardToDevToolsClientOnUIThread(
- int worker_process_id,
- int worker_route_id,
- const std::string& message);
- static void SaveAgentRuntimeStateOnUIThread(
- int worker_process_id,
- int worker_route_id,
- const std::string& state);
- static void NotifyConnectionFailedOnIOThread(int worker_process_id,
- int worker_route_id);
- static void NotifyConnectionFailedOnUIThread(int worker_process_id,
- int worker_route_id);
- static void SendResumeToWorker(const WorkerId& id);
-
- InspectedWorkersList inspected_workers_;
-
- struct TerminatedInspectedWorker;
- typedef std::list<TerminatedInspectedWorker> TerminatedInspectedWorkers;
- // List of terminated workers for which there may be a devtools client on
- // the UI thread. Worker entry is added into this list when inspected worker
- // is terminated and will be removed in one of two cases:
- // - shared worker with the same URL and name is started(in wich case we will
- // try to reattach existing DevTools client to the new worker).
- // - DevTools client which was inspecting terminated worker is closed on the
- // UI thread and and WorkerDevToolsManager is notified about that on the IO
- // thread.
- TerminatedInspectedWorkers terminated_workers_;
-
- typedef std::map<WorkerId, WorkerId> PausedWorkers;
- // Map from old to new worker id for the inspected workers that have been
- // terminated and started again in paused state. Worker data will be removed
- // from this list in one of two cases:
- // - DevTools client is closed on the UI thread, WorkerDevToolsManager was
- // notified about that on the IO thread and sent "resume" message to the
- // worker.
- // - Existing DevTools client was reattached to the new worker.
- PausedWorkers paused_workers_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MANAGER_H_
diff --git a/chromium/content/browser/devtools/worker_devtools_message_filter.cc b/chromium/content/browser/devtools/worker_devtools_message_filter.cc
deleted file mode 100644
index 23c068b5405..00000000000
--- a/chromium/content/browser/devtools/worker_devtools_message_filter.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2011 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 "content/browser/devtools/worker_devtools_message_filter.h"
-
-#include "content/browser/devtools/worker_devtools_manager.h"
-#include "content/common/devtools_messages.h"
-#include "content/common/worker_messages.h"
-
-namespace content {
-
-WorkerDevToolsMessageFilter::WorkerDevToolsMessageFilter(
- int worker_process_host_id)
- : BrowserMessageFilter(DevToolsMsgStart),
- worker_process_host_id_(worker_process_host_id),
- current_routing_id_(0) {
-}
-
-WorkerDevToolsMessageFilter::~WorkerDevToolsMessageFilter() {
-}
-
-bool WorkerDevToolsMessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- current_routing_id_ = message.routing_id();
- IPC_BEGIN_MESSAGE_MAP(WorkerDevToolsMessageFilter, message)
- IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
- OnDispatchOnInspectorFrontend)
- IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState,
- OnSaveAgentRumtimeState)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void WorkerDevToolsMessageFilter::OnDispatchOnInspectorFrontend(
- const std::string& message) {
- WorkerDevToolsManager::GetInstance()->ForwardToDevToolsClient(
- worker_process_host_id_, current_routing_id_, message);
-}
-
-void WorkerDevToolsMessageFilter::OnSaveAgentRumtimeState(
- const std::string& state) {
- WorkerDevToolsManager::GetInstance()->SaveAgentRuntimeState(
- worker_process_host_id_, current_routing_id_, state);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/devtools/worker_devtools_message_filter.h b/chromium/content/browser/devtools/worker_devtools_message_filter.h
deleted file mode 100644
index c80658e8dbf..00000000000
--- a/chromium/content/browser/devtools/worker_devtools_message_filter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MESSAGE_FILTER_H_
-
-#include "base/callback_forward.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace content {
-
-class WorkerDevToolsMessageFilter : public BrowserMessageFilter {
- public:
- explicit WorkerDevToolsMessageFilter(int worker_process_host_id);
-
- private:
- virtual ~WorkerDevToolsMessageFilter();
-
- // BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- // Message handlers.
- void OnDispatchOnInspectorFrontend(const std::string& message);
- void OnSaveAgentRumtimeState(const std::string& state);
-
- int worker_process_host_id_;
- int current_routing_id_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVTOOLS_WORKER_DEVTOOLS_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/dom_storage/dom_storage_area.cc b/chromium/content/browser/dom_storage/dom_storage_area.cc
index b1e803a148d..90a55a0ed8b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area.cc
@@ -17,11 +17,11 @@
#include "content/browser/dom_storage/session_storage_database_adapter.h"
#include "content/common/dom_storage/dom_storage_map.h"
#include "content/common/dom_storage/dom_storage_types.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/common/database/database_identifier.h"
-#include "webkit/common/fileapi/file_system_util.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/common/database/database_identifier.h"
+#include "storage/common/fileapi/file_system_util.h"
-using webkit_database::DatabaseUtil;
+using storage::DatabaseUtil;
namespace content {
@@ -39,7 +39,7 @@ const base::FilePath::CharType DOMStorageArea::kDatabaseFileExtension[] =
// static
base::FilePath DOMStorageArea::DatabaseFileNameFromOrigin(const GURL& origin) {
- std::string filename = webkit_database::GetIdentifierFromOrigin(origin);
+ std::string filename = storage::GetIdentifierFromOrigin(origin);
// There is no base::FilePath.AppendExtension() method, so start with just the
// extension as the filename, and then InsertBeforeExtension the desired
// name.
@@ -52,7 +52,7 @@ GURL DOMStorageArea::OriginFromDatabaseFileName(const base::FilePath& name) {
DCHECK(name.MatchesExtension(kDatabaseFileExtension));
std::string origin_id =
name.BaseName().RemoveExtension().MaybeAsASCII();
- return webkit_database::GetOriginFromIdentifier(origin_id);
+ return storage::GetOriginFromIdentifier(origin_id);
}
DOMStorageArea::DOMStorageArea(
diff --git a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
index c4d290c6a4d..c074cc0709b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_area_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
@@ -58,7 +58,7 @@ class DOMStorageAreaTest : public testing::Test {
class VerifyChangesCommittedDatabase : public DOMStorageDatabase {
public:
VerifyChangesCommittedDatabase() {}
- virtual ~VerifyChangesCommittedDatabase() {
+ ~VerifyChangesCommittedDatabase() override {
const base::string16 kKey(ASCIIToUTF16("key"));
const base::string16 kValue(ASCIIToUTF16("value"));
DOMStorageValuesMap values;
@@ -443,7 +443,7 @@ TEST_F(DOMStorageAreaTest, DatabaseFileNames) {
"file__0.localstorage-journal" },
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCases); ++i) {
+ for (size_t i = 0; i < arraysize(kCases); ++i) {
GURL origin = GURL(kCases[i].origin).GetOrigin();
base::FilePath file_name =
base::FilePath().AppendASCII(kCases[i].file_name);
diff --git a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
index 8d9e31d9d6c..b0c1c63d65f 100644
--- a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_browsertest.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 "base/path_service.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/common/content_paths.h"
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
index 05a65870587..d8e7ac50411 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.cc
@@ -6,8 +6,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/file_util.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/location.h"
#include "base/time/time.h"
@@ -20,7 +20,7 @@
#include "content/public/browser/dom_storage_context.h"
#include "content/public/browser/local_storage_usage_info.h"
#include "content/public/browser/session_storage_usage_info.h"
-#include "webkit/browser/quota/special_storage_policy.h"
+#include "storage/browser/quota/special_storage_policy.h"
namespace content {
@@ -29,7 +29,7 @@ static const int kSessionStoraceScavengingSeconds = 60;
DOMStorageContextImpl::DOMStorageContextImpl(
const base::FilePath& localstorage_directory,
const base::FilePath& sessionstorage_directory,
- quota::SpecialStoragePolicy* special_storage_policy,
+ storage::SpecialStoragePolicy* special_storage_policy,
DOMStorageTaskRunner* task_runner)
: localstorage_directory_(localstorage_directory),
sessionstorage_directory_(sessionstorage_directory),
@@ -278,7 +278,7 @@ void DOMStorageContextImpl::DeleteSessionNamespace(
} else {
if (should_persist_data)
it->second->set_must_persist_at_shutdown(true);
- MaybeShutdownSessionNamespace(it->second);
+ MaybeShutdownSessionNamespace(it->second.get());
}
}
@@ -485,11 +485,11 @@ DOMStorageContextImpl::MergeSessionStorage(
StorageNamespaceMap::const_iterator it = namespaces_.find(namespace1_id);
if (it == namespaces_.end())
return SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND;
- DOMStorageNamespace* ns1 = it->second;
+ DOMStorageNamespace* ns1 = it->second.get();
it = namespaces_.find(namespace2_id);
if (it == namespaces_.end())
return SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND;
- DOMStorageNamespace* ns2 = it->second;
+ DOMStorageNamespace* ns2 = it->second.get();
return ns1->Merge(actually_merge, process_id, ns2, this);
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl.h b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
index d256d9c5723..bd1acbfba22 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl.h
@@ -27,7 +27,7 @@ class NullableString16;
class Time;
}
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
}
@@ -91,11 +91,10 @@ class CONTENT_EXPORT DOMStorageContextImpl
// |localstorage_directory| and |sessionstorage_directory| may be empty
// for incognito browser contexts.
- DOMStorageContextImpl(
- const base::FilePath& localstorage_directory,
- const base::FilePath& sessionstorage_directory,
- quota::SpecialStoragePolicy* special_storage_policy,
- DOMStorageTaskRunner* task_runner);
+ DOMStorageContextImpl(const base::FilePath& localstorage_directory,
+ const base::FilePath& sessionstorage_directory,
+ storage::SpecialStoragePolicy* special_storage_policy,
+ DOMStorageTaskRunner* task_runner);
// Returns the directory path for localStorage, or an empty directory, if
// there is no backing on disk.
@@ -231,7 +230,7 @@ class CONTENT_EXPORT DOMStorageContextImpl
bool is_shutdown_;
bool force_keep_session_state_;
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
scoped_refptr<SessionStorageDatabase> session_storage_database_;
// For cleaning up unused namespaces gradually.
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
index d29741f62ea..f3744ab157b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
@@ -40,7 +40,7 @@ class DOMStorageContextImplTest : public testing::Test {
const bool kDontIncludeFileInfo;
const bool kDoIncludeFileInfo;
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
storage_policy_ = new MockSpecialStoragePolicy;
task_runner_ =
@@ -51,9 +51,7 @@ class DOMStorageContextImplTest : public testing::Test {
task_runner_.get());
}
- virtual void TearDown() {
- base::MessageLoop::current()->RunUntilIdle();
- }
+ void TearDown() override { base::MessageLoop::current()->RunUntilIdle(); }
void VerifySingleOriginRemains(const GURL& origin) {
// Use a new instance to examine the contexts of temp_dir_.
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
index 47d5b05be9a..d483d9b57a7 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -64,7 +64,7 @@ void GetSessionStorageUsageHelper(
DOMStorageContextWrapper::DOMStorageContextWrapper(
const base::FilePath& data_path,
- quota::SpecialStoragePolicy* special_storage_policy) {
+ storage::SpecialStoragePolicy* special_storage_policy) {
base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
context_ = new DOMStorageContextImpl(
data_path.empty() ? data_path
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
index 0ed95076a20..efd50914890 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -13,7 +13,7 @@ namespace base {
class FilePath;
}
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
}
@@ -28,21 +28,21 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
public base::RefCountedThreadSafe<DOMStorageContextWrapper> {
public:
// If |data_path| is empty, nothing will be saved to disk.
- DOMStorageContextWrapper(const base::FilePath& data_path,
- quota::SpecialStoragePolicy* special_storage_policy);
+ DOMStorageContextWrapper(
+ const base::FilePath& data_path,
+ storage::SpecialStoragePolicy* special_storage_policy);
// DOMStorageContext implementation.
- virtual void GetLocalStorageUsage(
- const GetLocalStorageUsageCallback& callback) OVERRIDE;
- virtual void GetSessionStorageUsage(
- const GetSessionStorageUsageCallback& callback) OVERRIDE;
- virtual void DeleteLocalStorage(const GURL& origin) OVERRIDE;
- virtual void DeleteSessionStorage(
- const SessionStorageUsageInfo& usage_info) OVERRIDE;
- virtual void SetSaveSessionStorageOnDisk() OVERRIDE;
- virtual scoped_refptr<SessionStorageNamespace>
- RecreateSessionStorage(const std::string& persistent_id) OVERRIDE;
- virtual void StartScavengingUnusedSessionStorage() OVERRIDE;
+ void GetLocalStorageUsage(
+ const GetLocalStorageUsageCallback& callback) override;
+ void GetSessionStorageUsage(
+ const GetSessionStorageUsageCallback& callback) override;
+ void DeleteLocalStorage(const GURL& origin) override;
+ void DeleteSessionStorage(const SessionStorageUsageInfo& usage_info) override;
+ void SetSaveSessionStorageOnDisk() override;
+ scoped_refptr<SessionStorageNamespace> RecreateSessionStorage(
+ const std::string& persistent_id) override;
+ void StartScavengingUnusedSessionStorage() override;
// Used by content settings to alter the behavior around
// what data to keep and what data to discard at shutdown.
@@ -58,7 +58,7 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
friend class SessionStorageNamespaceImpl; // ditto
friend class base::RefCountedThreadSafe<DOMStorageContextWrapper>;
- virtual ~DOMStorageContextWrapper();
+ ~DOMStorageContextWrapper() override;
DOMStorageContextImpl* context() const { return context_.get(); }
scoped_refptr<DOMStorageContextImpl> context_;
diff --git a/chromium/content/browser/dom_storage/dom_storage_database.cc b/chromium/content/browser/dom_storage/dom_storage_database.cc
index aaf6bb03447..1e0166f68f8 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database.cc
@@ -5,7 +5,7 @@
#include "content/browser/dom_storage/dom_storage_database.h"
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "sql/statement.h"
#include "sql/transaction.h"
diff --git a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
index e20e399ec6c..20b714c039b 100644
--- a/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_database_unittest.cc
@@ -4,11 +4,12 @@
#include "content/browser/dom_storage/dom_storage_database.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/content_paths.h"
#include "sql/statement.h"
#include "sql/test/scoped_error_ignorer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -309,11 +310,9 @@ TEST(DOMStorageDatabaseTest, TestSimpleRemoveOneValue) {
}
TEST(DOMStorageDatabaseTest, TestCanOpenAndReadWebCoreDatabase) {
- base::FilePath webcore_database;
- PathService::Get(base::DIR_SOURCE_ROOT, &webcore_database);
- webcore_database = webcore_database.AppendASCII("webkit");
- webcore_database = webcore_database.AppendASCII("data");
- webcore_database = webcore_database.AppendASCII("dom_storage");
+ base::FilePath dir_test_data;
+ ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
+ base::FilePath webcore_database = dir_test_data.AppendASCII("dom_storage");
webcore_database =
webcore_database.AppendASCII("webcore_test_database.localstorage");
diff --git a/chromium/content/browser/dom_storage/dom_storage_message_filter.h b/chromium/content/browser/dom_storage/dom_storage_message_filter.h
index 346a8ff5654..d93acfd06f6 100644
--- a/chromium/content/browser/dom_storage/dom_storage_message_filter.h
+++ b/chromium/content/browser/dom_storage/dom_storage_message_filter.h
@@ -34,17 +34,17 @@ class DOMStorageMessageFilter
DOMStorageContextWrapper* context);
private:
- virtual ~DOMStorageMessageFilter();
+ ~DOMStorageMessageFilter() override;
void InitializeInSequence();
void UninitializeInSequence();
// BrowserMessageFilter implementation
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Message Handlers.
void OnOpenStorageArea(int connection_id, int64 namespace_id,
@@ -63,21 +63,18 @@ class DOMStorageMessageFilter
// DOMStorageContextImpl::EventObserver implementation which
// sends events back to our renderer process.
- virtual void OnDOMStorageItemSet(
- const DOMStorageArea* area,
- const base::string16& key,
- const base::string16& new_value,
- const base::NullableString16& old_value,
- const GURL& page_url) OVERRIDE;
- virtual void OnDOMStorageItemRemoved(
- const DOMStorageArea* area,
- const base::string16& key,
- const base::string16& old_value,
- const GURL& page_url) OVERRIDE;
- virtual void OnDOMStorageAreaCleared(
- const DOMStorageArea* area,
- const GURL& page_url) OVERRIDE;
- virtual void OnDOMSessionStorageReset(int64 namespace_id) OVERRIDE;
+ void OnDOMStorageItemSet(const DOMStorageArea* area,
+ const base::string16& key,
+ const base::string16& new_value,
+ const base::NullableString16& old_value,
+ const GURL& page_url) override;
+ void OnDOMStorageItemRemoved(const DOMStorageArea* area,
+ const base::string16& key,
+ const base::string16& old_value,
+ const GURL& page_url) override;
+ void OnDOMStorageAreaCleared(const DOMStorageArea* area,
+ const GURL& page_url) override;
+ void OnDOMSessionStorageReset(int64 namespace_id) override;
void SendDOMStorageEvent(
const DOMStorageArea* area,
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index d36147f076e..fb76b6764ed 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -63,7 +63,7 @@ DOMStorageNamespace::~DOMStorageNamespace() {
}
DOMStorageArea* DOMStorageNamespace::OpenStorageArea(const GURL& origin) {
- if (alias_master_namespace_)
+ if (alias_master_namespace_.get())
return alias_master_namespace_->OpenStorageArea(origin);
if (AreaHolder* holder = GetAreaHolder(origin)) {
++(holder->open_count_);
@@ -83,7 +83,7 @@ DOMStorageArea* DOMStorageNamespace::OpenStorageArea(const GURL& origin) {
void DOMStorageNamespace::CloseStorageArea(DOMStorageArea* area) {
AreaHolder* holder = GetAreaHolder(area->origin());
- if (alias_master_namespace_) {
+ if (alias_master_namespace_.get()) {
DCHECK(!holder);
if (old_master_for_close_area_)
old_master_for_close_area_->CloseStorageArea(area);
@@ -99,7 +99,7 @@ void DOMStorageNamespace::CloseStorageArea(DOMStorageArea* area) {
}
DOMStorageArea* DOMStorageNamespace::GetOpenStorageArea(const GURL& origin) {
- if (alias_master_namespace_)
+ if (alias_master_namespace_.get())
return alias_master_namespace_->GetOpenStorageArea(origin);
AreaHolder* holder = GetAreaHolder(origin);
if (holder && holder->open_count_)
@@ -110,7 +110,7 @@ DOMStorageArea* DOMStorageNamespace::GetOpenStorageArea(const GURL& origin) {
DOMStorageNamespace* DOMStorageNamespace::Clone(
int64 clone_namespace_id,
const std::string& clone_persistent_namespace_id) {
- if (alias_master_namespace_) {
+ if (alias_master_namespace_.get()) {
return alias_master_namespace_->Clone(clone_namespace_id,
clone_persistent_namespace_id);
}
@@ -153,8 +153,8 @@ DOMStorageNamespace* DOMStorageNamespace::CreateAlias(
DOMStorageNamespace* alias = new DOMStorageNamespace(
alias_namespace_id, persistent_namespace_id_,
session_storage_database_.get(), task_runner_.get());
- if (alias_master_namespace_ != NULL) {
- DCHECK(alias_master_namespace_->alias_master_namespace_ == NULL);
+ if (alias_master_namespace_.get() != NULL) {
+ DCHECK(alias_master_namespace_->alias_master_namespace_.get() == NULL);
alias->alias_master_namespace_ = alias_master_namespace_;
} else {
alias->alias_master_namespace_ = this;
@@ -179,7 +179,7 @@ void DOMStorageNamespace::DeleteLocalStorageOrigin(const GURL& origin) {
}
void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL& origin) {
- if (alias_master_namespace_) {
+ if (alias_master_namespace_.get()) {
alias_master_namespace_->DeleteSessionStorageOrigin(origin);
return;
}
@@ -189,7 +189,7 @@ void DOMStorageNamespace::DeleteSessionStorageOrigin(const GURL& origin) {
}
void DOMStorageNamespace::PurgeMemory(PurgeOption option) {
- if (alias_master_namespace_) {
+ if (alias_master_namespace_.get()) {
alias_master_namespace_->PurgeMemory(option);
return;
}
@@ -228,7 +228,7 @@ void DOMStorageNamespace::Shutdown() {
}
unsigned int DOMStorageNamespace::CountInMemoryAreas() const {
- if (alias_master_namespace_)
+ if (alias_master_namespace_.get())
return alias_master_namespace_->CountInMemoryAreas();
unsigned int area_count = 0;
for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it) {
@@ -375,7 +375,7 @@ void DOMStorageNamespace::AddTransaction(
}
bool DOMStorageNamespace::DecrementMasterAliasCount() {
- if (!alias_master_namespace_ || master_alias_count_decremented_)
+ if (!alias_master_namespace_.get() || master_alias_count_decremented_)
return false;
DCHECK_GT(alias_master_namespace_->num_aliases_, 0);
alias_master_namespace_->num_aliases_--;
@@ -391,8 +391,8 @@ void DOMStorageNamespace::SwitchToNewAliasMaster(
if (new_master->alias_master_namespace())
new_master = new_master->alias_master_namespace();
DCHECK(!new_master->alias_master_namespace());
- DCHECK(old_master != this);
- DCHECK(old_master != new_master);
+ DCHECK(old_master.get() != this);
+ DCHECK(old_master.get() != new_master);
DecrementMasterAliasCount();
alias_master_namespace_ = new_master;
alias_master_namespace_->num_aliases_++;
diff --git a/chromium/content/browser/dom_storage/dom_storage_task_runner.h b/chromium/content/browser/dom_storage/dom_storage_task_runner.h
index 1fb8a19e73b..a2000a08c14 100644
--- a/chromium/content/browser/dom_storage/dom_storage_task_runner.h
+++ b/chromium/content/browser/dom_storage/dom_storage_task_runner.h
@@ -49,7 +49,7 @@ class CONTENT_EXPORT DOMStorageTaskRunner
// The TaskRunner override returns true if the current thread is running
// on the primary sequence.
- virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
+ bool RunsTasksOnCurrentThread() const override;
// Returns true if the current thread is running on the given |sequence_id|.
virtual bool IsRunningOnSequence(SequenceID sequence_id) const = 0;
@@ -61,7 +61,7 @@ class CONTENT_EXPORT DOMStorageTaskRunner
}
protected:
- virtual ~DOMStorageTaskRunner() {}
+ ~DOMStorageTaskRunner() override {}
};
// A derived class used in chromium that utilizes a SequenceWorkerPool
@@ -76,20 +76,18 @@ class CONTENT_EXPORT DOMStorageWorkerPoolTaskRunner :
base::SequencedWorkerPool::SequenceToken commit_sequence_token,
base::MessageLoopProxy* delayed_task_loop);
- virtual bool PostDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task,
- base::TimeDelta delay) OVERRIDE;
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
- virtual bool PostShutdownBlockingTask(
- const tracked_objects::Location& from_here,
- SequenceID sequence_id,
- const base::Closure& task) OVERRIDE;
+ bool PostShutdownBlockingTask(const tracked_objects::Location& from_here,
+ SequenceID sequence_id,
+ const base::Closure& task) override;
- virtual bool IsRunningOnSequence(SequenceID sequence_id) const OVERRIDE;
+ bool IsRunningOnSequence(SequenceID sequence_id) const override;
protected:
- virtual ~DOMStorageWorkerPoolTaskRunner();
+ ~DOMStorageWorkerPoolTaskRunner() override;
private:
@@ -111,20 +109,18 @@ class CONTENT_EXPORT MockDOMStorageTaskRunner :
public:
explicit MockDOMStorageTaskRunner(base::MessageLoopProxy* message_loop);
- virtual bool PostDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task,
- base::TimeDelta delay) OVERRIDE;
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
- virtual bool PostShutdownBlockingTask(
- const tracked_objects::Location& from_here,
- SequenceID sequence_id,
- const base::Closure& task) OVERRIDE;
+ bool PostShutdownBlockingTask(const tracked_objects::Location& from_here,
+ SequenceID sequence_id,
+ const base::Closure& task) override;
- virtual bool IsRunningOnSequence(SequenceID sequence_id) const OVERRIDE;
+ bool IsRunningOnSequence(SequenceID sequence_id) const override;
protected:
- virtual ~MockDOMStorageTaskRunner();
+ ~MockDOMStorageTaskRunner() override;
private:
const scoped_refptr<base::MessageLoopProxy> message_loop_;
diff --git a/chromium/content/browser/dom_storage/local_storage_database_adapter.cc b/chromium/content/browser/dom_storage/local_storage_database_adapter.cc
index f5d87e31c19..0be1cc0927c 100644
--- a/chromium/content/browser/dom_storage/local_storage_database_adapter.cc
+++ b/chromium/content/browser/dom_storage/local_storage_database_adapter.cc
@@ -4,7 +4,7 @@
#include "content/browser/dom_storage/local_storage_database_adapter.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "content/browser/dom_storage/dom_storage_database.h"
namespace content {
diff --git a/chromium/content/browser/dom_storage/local_storage_database_adapter.h b/chromium/content/browser/dom_storage/local_storage_database_adapter.h
index 1298d9c3e30..fca55d0c4e0 100644
--- a/chromium/content/browser/dom_storage/local_storage_database_adapter.h
+++ b/chromium/content/browser/dom_storage/local_storage_database_adapter.h
@@ -22,12 +22,12 @@ class CONTENT_EXPORT LocalStorageDatabaseAdapter :
public DOMStorageDatabaseAdapter {
public:
explicit LocalStorageDatabaseAdapter(const base::FilePath& path);
- virtual ~LocalStorageDatabaseAdapter();
- virtual void ReadAllValues(DOMStorageValuesMap* result) OVERRIDE;
- virtual bool CommitChanges(bool clear_all_first,
- const DOMStorageValuesMap& changes) OVERRIDE;
- virtual void DeleteFiles() OVERRIDE;
- virtual void Reset() OVERRIDE;
+ ~LocalStorageDatabaseAdapter() override;
+ void ReadAllValues(DOMStorageValuesMap* result) override;
+ bool CommitChanges(bool clear_all_first,
+ const DOMStorageValuesMap& changes) override;
+ void DeleteFiles() override;
+ void Reset() override;
protected:
// Constructor that uses an in-memory sqlite database, for testing.
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index 30d3d86577e..6e47a1fdf1c 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -4,7 +4,7 @@
#include "content/browser/dom_storage/session_storage_database.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
diff --git a/chromium/content/browser/dom_storage/session_storage_database_adapter.h b/chromium/content/browser/dom_storage/session_storage_database_adapter.h
index 9db5f173341..1b5a91dd7da 100644
--- a/chromium/content/browser/dom_storage/session_storage_database_adapter.h
+++ b/chromium/content/browser/dom_storage/session_storage_database_adapter.h
@@ -18,10 +18,11 @@ class SessionStorageDatabaseAdapter : public DOMStorageDatabaseAdapter {
SessionStorageDatabaseAdapter(SessionStorageDatabase* db,
const std::string& permanent_namespace_id,
const GURL& origin);
- virtual ~SessionStorageDatabaseAdapter();
- virtual void ReadAllValues(DOMStorageValuesMap* result) OVERRIDE;
- virtual bool CommitChanges(bool clear_all_first,
- const DOMStorageValuesMap& changes) OVERRIDE;
+ ~SessionStorageDatabaseAdapter() override;
+ void ReadAllValues(DOMStorageValuesMap* result) override;
+ bool CommitChanges(bool clear_all_first,
+ const DOMStorageValuesMap& changes) override;
+
private:
scoped_refptr<SessionStorageDatabase> db_;
std::string permanent_namespace_id_;
diff --git a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
index 71c8063ef44..f8397ace3ea 100644
--- a/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database_unittest.cc
@@ -9,7 +9,7 @@
#include <map>
#include <string>
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
@@ -26,8 +26,8 @@ namespace content {
class SessionStorageDatabaseTest : public testing::Test {
public:
SessionStorageDatabaseTest();
- virtual ~SessionStorageDatabaseTest();
- virtual void SetUp() OVERRIDE;
+ ~SessionStorageDatabaseTest() override;
+ void SetUp() override;
protected:
typedef std::map<std::string, std::string> DataMap;
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
index dab20332d53..ee861b2fbf0 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -28,7 +28,7 @@ SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
SessionStorageNamespaceImpl* master_session_storage_namespace)
: session_(new DOMStorageSession(
- master_session_storage_namespace->session_)) {
+ master_session_storage_namespace->session_.get())) {
}
@@ -81,7 +81,8 @@ void SessionStorageNamespaceImpl::Merge(
const MergeResultCallback& callback) {
SessionStorageNamespaceImpl* other_impl =
static_cast<SessionStorageNamespaceImpl*>(other);
- session_->Merge(actually_merge, process_id, other_impl->session_, callback);
+ session_->Merge(
+ actually_merge, process_id, other_impl->session_.get(), callback);
}
bool SessionStorageNamespaceImpl::IsAliasOf(SessionStorageNamespace* other) {
diff --git a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
index ad010857243..025ee8729da 100644
--- a/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
+++ b/chromium/content/browser/dom_storage/session_storage_namespace_impl.h
@@ -40,26 +40,26 @@ class SessionStorageNamespaceImpl
SessionStorageNamespaceImpl* master_session_storage_namespace);
// SessionStorageNamespace implementation.
- virtual int64 id() const OVERRIDE;
- virtual const std::string& persistent_id() const OVERRIDE;
- virtual void SetShouldPersist(bool should_persist) OVERRIDE;
- virtual bool should_persist() const OVERRIDE;
+ int64 id() const override;
+ const std::string& persistent_id() const override;
+ void SetShouldPersist(bool should_persist) override;
+ bool should_persist() const override;
SessionStorageNamespaceImpl* Clone();
bool IsFromContext(DOMStorageContextWrapper* context);
- virtual void AddTransactionLogProcessId(int process_id) OVERRIDE;
- virtual void RemoveTransactionLogProcessId(int process_id) OVERRIDE;
- virtual void Merge(bool actually_merge,
- int process_id,
- SessionStorageNamespace* other,
- const MergeResultCallback& callback) OVERRIDE;
- virtual bool IsAliasOf(SessionStorageNamespace* other) OVERRIDE;
- virtual SessionStorageNamespace* CreateAlias() OVERRIDE;
+ void AddTransactionLogProcessId(int process_id) override;
+ void RemoveTransactionLogProcessId(int process_id) override;
+ void Merge(bool actually_merge,
+ int process_id,
+ SessionStorageNamespace* other,
+ const MergeResultCallback& callback) override;
+ bool IsAliasOf(SessionStorageNamespace* other) override;
+ SessionStorageNamespace* CreateAlias() override;
private:
explicit SessionStorageNamespaceImpl(DOMStorageSession* clone);
- virtual ~SessionStorageNamespaceImpl();
+ ~SessionStorageNamespaceImpl() override;
scoped_refptr<DOMStorageSession> session_;
diff --git a/chromium/content/browser/download/base_file.cc b/chromium/content/browser/download/base_file.cc
index 362f64ea1e0..5bca7831a44 100644
--- a/chromium/content/browser/download/base_file.cc
+++ b/chromium/content/browser/download/base_file.cc
@@ -5,8 +5,8 @@
#include "content/browser/download/base_file.h"
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/pickle.h"
@@ -159,15 +159,18 @@ DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {
// permissions / security descriptors that makes sense in the new directory.
rename_result = MoveFileAndAdjustPermissions(new_path);
- if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ if (rename_result == DOWNLOAD_INTERRUPT_REASON_NONE)
full_path_ = new_path;
- // Re-open the file if we were still using it.
- if (was_in_progress)
- rename_result = Open();
- }
+
+ // Re-open the file if we were still using it regardless of the interrupt
+ // reason.
+ DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE;
+ if (was_in_progress)
+ open_result = Open();
bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED);
- return rename_result;
+ return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result
+ : rename_result;
}
void BaseFile::Detach() {
@@ -326,11 +329,10 @@ DownloadInterruptReason BaseFile::LogSystemError(
const char* operation,
logging::SystemErrorCode os_error) {
// There's no direct conversion from a system error to an interrupt reason.
- net::Error net_error = net::MapSystemError(os_error);
+ base::File::Error file_error = base::File::OSErrorToFileError(os_error);
return LogInterruptReason(
operation, os_error,
- ConvertNetErrorToInterruptReason(
- net_error, DOWNLOAD_INTERRUPT_FROM_DISK));
+ ConvertFileErrorToInterruptReason(file_error));
}
DownloadInterruptReason BaseFile::LogInterruptReason(
diff --git a/chromium/content/browser/download/base_file.h b/chromium/content/browser/download/base_file.h
index a14c5daef31..037aecca3b5 100644
--- a/chromium/content/browser/download/base_file.h
+++ b/chromium/content/browser/download/base_file.h
@@ -56,7 +56,10 @@ class CONTENT_EXPORT BaseFile {
DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len);
// Rename the download file. Returns a DownloadInterruptReason indicating the
- // result of the operation.
+ // result of the operation. A return code of NONE indicates that the rename
+ // was successful. After a failure, the full_path() and in_progress() can be
+ // used to determine the last known filename and whether the file is available
+ // for writing or retrying the rename.
virtual DownloadInterruptReason Rename(const base::FilePath& full_path);
// Detach the file so it is not deleted on destruction.
@@ -79,8 +82,15 @@ class CONTENT_EXPORT BaseFile {
// Windows to ensure the correct app client ID is available.
DownloadInterruptReason AnnotateWithSourceInformation();
- base::FilePath full_path() const { return full_path_; }
+ // Returns the last known path to the download file. Can be empty if there's
+ // no file.
+ const base::FilePath& full_path() const { return full_path_; }
+
+ // Returns true if the file is open. If true, the file can be written to or
+ // renamed.
bool in_progress() const { return file_.IsValid(); }
+
+ // Returns the number of bytes in the file pointed to by full_path().
int64 bytes_so_far() const { return bytes_so_far_; }
// Fills |hash| with the hash digest for the file.
diff --git a/chromium/content/browser/download/base_file_posix.cc b/chromium/content/browser/download/base_file_posix.cc
index 4cf987c8b20..b5d8e014422 100644
--- a/chromium/content/browser/download/base_file_posix.cc
+++ b/chromium/content/browser/download/base_file_posix.cc
@@ -4,7 +4,7 @@
#include "content/browser/download/base_file.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "content/public/browser/download_interrupt_reasons.h"
namespace content {
@@ -27,8 +27,6 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
if (!stat_succeeded)
LogSystemError("stat", errno);
- // TODO(estade): Move() falls back to copying and deleting when a simple
- // rename fails. Copying sucks for large downloads. crbug.com/8737
if (!base::Move(full_path_, new_path))
return LogSystemError("Move", errno);
diff --git a/chromium/content/browser/download/base_file_unittest.cc b/chromium/content/browser/download/base_file_unittest.cc
index 8b45ce9ca0f..7e27ffe0969 100644
--- a/chromium/content/browser/download/base_file_unittest.cc
+++ b/chromium/content/browser/download/base_file_unittest.cc
@@ -4,8 +4,8 @@
#include "content/browser/download/base_file.h"
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
@@ -45,7 +45,7 @@ class BaseFileTest : public testing::Test {
file_thread_(BrowserThread::FILE, &message_loop_) {
}
- virtual void SetUp() {
+ void SetUp() override {
ResetHash();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base_file_.reset(new BaseFile(base::FilePath(),
@@ -58,7 +58,7 @@ class BaseFileTest : public testing::Test {
net::BoundNetLog()));
}
- virtual void TearDown() {
+ void TearDown() override {
EXPECT_FALSE(base_file_->in_progress());
if (!expected_error_) {
EXPECT_EQ(static_cast<int64>(expected_data_.size()),
@@ -195,6 +195,12 @@ class BaseFileTest : public testing::Test {
expected_error_ = err;
}
+ void ExpectPermissionError(DownloadInterruptReason err) {
+ EXPECT_TRUE(err == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR ||
+ err == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED)
+ << "Interrupt reason = " << err;
+ }
+
protected:
// BaseClass instance we are testing.
scoped_ptr<BaseFile> base_file_;
@@ -467,15 +473,63 @@ TEST_F(BaseFileTest, RenameWithError) {
EXPECT_FALSE(base::PathExists(new_path));
{
- file_util::PermissionRestorer restore_permissions_for(test_dir);
- ASSERT_TRUE(file_util::MakeFileUnwritable(test_dir));
- EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
- base_file_->Rename(new_path));
+ base::FilePermissionRestorer restore_permissions_for(test_dir);
+ ASSERT_TRUE(base::MakeFileUnwritable(test_dir));
+ ExpectPermissionError(base_file_->Rename(new_path));
}
base_file_->Finish();
}
+// Test that if a rename fails for an in-progress BaseFile, it remains writeable
+// and renameable.
+TEST_F(BaseFileTest, RenameWithErrorInProgress) {
+ ASSERT_TRUE(InitializeFile());
+
+ base::FilePath test_dir(temp_dir_.path().AppendASCII("TestDir"));
+ ASSERT_TRUE(base::CreateDirectory(test_dir));
+
+ base::FilePath new_path(test_dir.AppendASCII("TestFile"));
+ EXPECT_FALSE(base::PathExists(new_path));
+
+ // Write some data to start with.
+ ASSERT_TRUE(AppendDataToFile(kTestData1));
+ ASSERT_TRUE(base_file_->in_progress());
+
+ base::FilePath old_path = base_file_->full_path();
+
+ {
+ base::FilePermissionRestorer restore_permissions_for(test_dir);
+ ASSERT_TRUE(base::MakeFileUnwritable(test_dir));
+ ExpectPermissionError(base_file_->Rename(new_path));
+
+ // The file should still be open and we should be able to continue writing
+ // to it.
+ ASSERT_TRUE(base_file_->in_progress());
+ ASSERT_TRUE(AppendDataToFile(kTestData2));
+ ASSERT_EQ(old_path.value(), base_file_->full_path().value());
+
+ // Try to rename again, just for kicks. It should still fail.
+ ExpectPermissionError(base_file_->Rename(new_path));
+ }
+
+ // Now that TestDir is writeable again, we should be able to successfully
+ // rename the file.
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, base_file_->Rename(new_path));
+ ASSERT_EQ(new_path.value(), base_file_->full_path().value());
+ ASSERT_TRUE(AppendDataToFile(kTestData3));
+
+ base_file_->Finish();
+
+ // The contents of the file should be intact.
+ std::string file_contents;
+ std::string expected_contents(kTestData1);
+ expected_contents += kTestData2;
+ expected_contents += kTestData3;
+ ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
+ EXPECT_EQ(expected_contents, file_contents);
+}
+
// Test that a failed write reports an error.
TEST_F(BaseFileTest, WriteWithError) {
base::FilePath path;
@@ -558,10 +612,10 @@ TEST_F(BaseFileTest, ReadonlyBaseFile) {
base::FilePath readonly_file_name = CreateTestFile();
// Restore permissions to the file when we are done with this test.
- file_util::PermissionRestorer restore_permissions(readonly_file_name);
+ base::FilePermissionRestorer restore_permissions(readonly_file_name);
// Make it read-only.
- EXPECT_TRUE(file_util::MakeFileUnwritable(readonly_file_name));
+ EXPECT_TRUE(base::MakeFileUnwritable(readonly_file_name));
// Try to overwrite it.
base_file_.reset(new BaseFile(readonly_file_name,
diff --git a/chromium/content/browser/download/base_file_win.cc b/chromium/content/browser/download/base_file_win.cc
index 252f0495d7d..fec1454d57b 100644
--- a/chromium/content/browser/download/base_file_win.cc
+++ b/chromium/content/browser/download/base_file_win.cc
@@ -9,7 +9,8 @@
#include <objbase.h>
#include <shellapi.h>
-#include "base/file_util.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
@@ -25,6 +26,8 @@ namespace {
const int kAllSpecialShFileOperationCodes[] = {
// Should be kept in sync with the case statement below.
ERROR_ACCESS_DENIED,
+ ERROR_SHARING_VIOLATION,
+ ERROR_INVALID_PARAMETER,
0x71,
0x72,
0x73,
@@ -68,11 +71,28 @@ DownloadInterruptReason MapShFileOperationCodes(int code) {
// This switch statement should be kept in sync with the list of codes
// above.
switch (code) {
- // Not a pre-Win32 error code; here so that this particular
- // case shows up in our histograms. This is redundant with the
- // mapping function net::MapSystemError used later.
+ // Not a pre-Win32 error code; here so that this particular case shows up in
+ // our histograms. Unfortunately, it is used not just to signal actual
+ // ACCESS_DENIED errors, but many other errors as well. So we treat it as a
+ // transient error.
case ERROR_ACCESS_DENIED: // Access is denied.
- result = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
+ result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
+ break;
+
+ // This isn't documented but returned from SHFileOperation. Sharing
+ // violations indicate that another process had the file open while we were
+ // trying to rename. Anti-virus is believed to be the cause of this error in
+ // the wild. Treated as a transient error on the assumption that the file
+ // will be made available for renaming at a later time.
+ case ERROR_SHARING_VIOLATION:
+ result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
+ break;
+
+ // This is also not a documented return value of SHFileOperation, but has
+ // been observed in the wild. We are treating it as a transient error based
+ // on the cases we have seen so far. See http://crbug.com/368455.
+ case ERROR_INVALID_PARAMETER:
+ result = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
break;
// The source and destination files are the same file.
@@ -250,12 +270,20 @@ DownloadInterruptReason MapShFileOperationCodes(int code) {
arraysize(kAllSpecialShFileOperationCodes)));
}
+ if (result == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR) {
+ UMA_HISTOGRAM_CUSTOM_ENUMERATION(
+ "Download.MapWinShErrorTransientError", code,
+ base::CustomHistogram::ArrayToCustomRanges(
+ kAllSpecialShFileOperationCodes,
+ arraysize(kAllSpecialShFileOperationCodes)));
+ }
+
if (result != DOWNLOAD_INTERRUPT_REASON_NONE)
return result;
// If not one of the above codes, it should be a standard Windows error code.
- return ConvertNetErrorToInterruptReason(
- net::MapSystemError(code), DOWNLOAD_INTERRUPT_FROM_DISK);
+ return ConvertFileErrorToInterruptReason(
+ base::File::OSErrorToFileError(code));
}
// Maps a return code from ScanAndSaveDownloadedFile() to a
@@ -310,6 +338,7 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
move_info.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI |
FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS;
+ base::TimeTicks now = base::TimeTicks::Now();
int result = SHFileOperation(&move_info);
DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE;
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index 8f35b63e576..a011fc90015 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -6,9 +6,10 @@
// in a pure content context. Over time tests should be migrated here.
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
@@ -19,7 +20,6 @@
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
-#include "content/browser/plugin_service_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/power_save_blocker.h"
#include "content/public/common/content_switches.h"
@@ -34,16 +34,20 @@
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/shell/browser/shell_network_delegate.h"
-#include "content/test/net/url_request_mock_http_job.h"
#include "content/test/net/url_request_slow_download_job.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "net/test/url_request/url_request_mock_http_job.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_service_impl.h"
+#endif
+
using ::net::test_server::EmbeddedTestServer;
using ::testing::AllOf;
using ::testing::Field;
@@ -118,17 +122,15 @@ class DownloadFileWithDelay : public DownloadFileImpl {
base::WeakPtr<DownloadDestinationObserver> observer,
base::WeakPtr<DownloadFileWithDelayFactory> owner);
- virtual ~DownloadFileWithDelay();
+ ~DownloadFileWithDelay() override;
// Wraps DownloadFileImpl::Rename* and intercepts the return callback,
// storing it in the factory that produced this object for later
// retrieval.
- virtual void RenameAndUniquify(
- const base::FilePath& full_path,
- const RenameCompletionCallback& callback) OVERRIDE;
- virtual void RenameAndAnnotate(
- const base::FilePath& full_path,
- const RenameCompletionCallback& callback) OVERRIDE;
+ void RenameAndUniquify(const base::FilePath& full_path,
+ const RenameCompletionCallback& callback) override;
+ void RenameAndAnnotate(const base::FilePath& full_path,
+ const RenameCompletionCallback& callback) override;
private:
static void RenameCallbackWrapper(
@@ -151,10 +153,10 @@ class DownloadFileWithDelay : public DownloadFileImpl {
class DownloadFileWithDelayFactory : public DownloadFileFactory {
public:
DownloadFileWithDelayFactory();
- virtual ~DownloadFileWithDelayFactory();
+ ~DownloadFileWithDelayFactory() override;
// DownloadFileFactory interface.
- virtual DownloadFile* CreateFile(
+ DownloadFile* CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
const GURL& url,
@@ -162,7 +164,7 @@ class DownloadFileWithDelayFactory : public DownloadFileFactory {
bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
- base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE;
+ base::WeakPtr<DownloadDestinationObserver> observer) override;
void AddRenameCallback(base::Closure callback);
void GetAllRenameCallbacks(std::vector<base::Closure>* results);
@@ -288,12 +290,12 @@ class CountingDownloadFile : public DownloadFileImpl {
url, referrer_url, calculate_hash,
stream.Pass(), bound_net_log, observer) {}
- virtual ~CountingDownloadFile() {
+ ~CountingDownloadFile() override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
active_files_--;
}
- virtual void Initialize(const InitializeCallback& callback) OVERRIDE {
+ void Initialize(const InitializeCallback& callback) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
active_files_++;
return DownloadFileImpl::Initialize(callback);
@@ -327,18 +329,18 @@ int CountingDownloadFile::active_files_ = 0;
class CountingDownloadFileFactory : public DownloadFileFactory {
public:
CountingDownloadFileFactory() {}
- virtual ~CountingDownloadFileFactory() {}
+ ~CountingDownloadFileFactory() override {}
// DownloadFileFactory interface.
- virtual DownloadFile* CreateFile(
- scoped_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
- scoped_ptr<ByteStreamReader> stream,
- const net::BoundNetLog& bound_net_log,
- base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE {
+ DownloadFile* CreateFile(
+ scoped_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ const GURL& url,
+ const GURL& referrer_url,
+ bool calculate_hash,
+ scoped_ptr<ByteStreamReader> stream,
+ const net::BoundNetLog& bound_net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer) override {
scoped_ptr<PowerSaveBlocker> psb(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
@@ -354,11 +356,11 @@ class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
public:
TestShellDownloadManagerDelegate()
: delay_download_open_(false) {}
- virtual ~TestShellDownloadManagerDelegate() {}
+ ~TestShellDownloadManagerDelegate() override {}
- virtual bool ShouldOpenDownload(
+ bool ShouldOpenDownload(
DownloadItem* item,
- const DownloadOpenDelayedCallback& callback) OVERRIDE {
+ const DownloadOpenDelayedCallback& callback) override {
if (delay_download_open_) {
delayed_callbacks_.push_back(callback);
return false;
@@ -396,9 +398,7 @@ class RecordingDownloadObserver : DownloadItem::Observer {
download_->AddObserver(this);
}
- virtual ~RecordingDownloadObserver() {
- RemoveObserver();
- }
+ ~RecordingDownloadObserver() override { RemoveObserver(); }
void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
EXPECT_EQ(size, record_.size());
@@ -411,7 +411,7 @@ class RecordingDownloadObserver : DownloadItem::Observer {
}
private:
- virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
+ void OnDownloadUpdated(DownloadItem* download) override {
DCHECK_EQ(download_, download);
DownloadItem::DownloadState state = download->GetState();
int bytes = download->GetReceivedBytes();
@@ -422,7 +422,7 @@ class RecordingDownloadObserver : DownloadItem::Observer {
}
}
- virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
+ void OnDownloadDestroyed(DownloadItem* download) override {
DCHECK_EQ(download_, download);
RemoveObserver();
}
@@ -449,20 +449,20 @@ class DownloadCreateObserver : DownloadManager::Observer {
manager_->AddObserver(this);
}
- virtual ~DownloadCreateObserver() {
+ ~DownloadCreateObserver() override {
if (manager_)
manager_->RemoveObserver(this);
manager_ = NULL;
}
- virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
+ void ManagerGoingDown(DownloadManager* manager) override {
DCHECK_EQ(manager_, manager);
manager_->RemoveObserver(this);
manager_ = NULL;
}
- virtual void OnDownloadCreated(DownloadManager* manager,
- DownloadItem* download) OVERRIDE {
+ void OnDownloadCreated(DownloadManager* manager,
+ DownloadItem* download) override {
if (!item_)
item_ = download;
@@ -518,7 +518,7 @@ scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse(
response->set_code(net::HTTP_FOUND);
response->AddCustomHeader("Location", target_url.spec());
}
- return response.PassAs<net::test_server::HttpResponse>();
+ return response.Pass();
}
// Creates a request handler for EmbeddedTestServer that responds with a HTTP
@@ -542,7 +542,7 @@ scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse(
response->set_content_type(content_type);
response->set_content(body);
}
- return response.PassAs<net::test_server::HttpResponse>();
+ return response.Pass();
}
// Creates a request handler for an EmbeddedTestServer that response with an
@@ -570,7 +570,7 @@ class DownloadContentTest : public ContentBrowserTest {
ByteStreamWriter::kFractionBufferBeforeSending) + 1;
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
test_delegate_.reset(new TestShellDownloadManagerDelegate());
@@ -585,8 +585,12 @@ class DownloadContentTest : public ContentBrowserTest {
base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler));
base::FilePath mock_base(GetTestFilePath("download", ""));
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestMockHTTPJob::AddUrlHandler, mock_base));
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &net::URLRequestMockHTTPJob::AddUrlHandler,
+ mock_base,
+ make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
}
TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() {
@@ -798,7 +802,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
// Start the second download and wait until it's done.
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
// Download the file and wait.
NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
@@ -853,7 +857,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
// The following is served with a Content-Type of application/octet-stream.
- GURL url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
+ GURL url(
+ net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
}
#endif
@@ -870,7 +875,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
// Create a download
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));
+ NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
// Wait until the first (intermediate file) rename and execute the callback.
file_factory->WaitForSomeCallback();
@@ -919,7 +924,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
// Create a download
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));
+ NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
// Wait until the first (intermediate file) rename and execute the callback.
file_factory->WaitForSomeCallback();
@@ -1029,7 +1034,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
// Create a download
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));
+ NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
// Wait until the first (intermediate file) rename and execute the callback.
file_factory->WaitForSomeCallback();
@@ -1070,7 +1075,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
}
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1137,7 +1142,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
// Confirm restart fallback happens if a range request is bounced.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1186,7 +1191,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
// Confirm restart fallback happens if a precondition is failed.
IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ResumeInterruptedDownloadBadPrecondition) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1238,7 +1243,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
// Confirm we don't try to resume if we don't have a verifier.
IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ResumeInterruptedDownloadNoVerifiers) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1282,7 +1287,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
}
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1333,10 +1338,10 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
}
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
// Setup the error injector.
scoped_refptr<TestFileErrorInjector> injector(
@@ -1384,10 +1389,10 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ResumeWithFileIntermediateRenameError) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
// Setup the error injector.
scoped_refptr<TestFileErrorInjector> injector(
@@ -1436,10 +1441,10 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
}
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
- GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
// Setup the error injector.
scoped_refptr<TestFileErrorInjector> injector(
@@ -1489,7 +1494,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
// An interrupted download should remove the intermediate file when it is
// cancelled.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1519,7 +1524,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
}
IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1554,7 +1559,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
{
// Start the second download and wait until it's done.
base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
- GURL url2(URLRequestMockHTTPJob::GetMockUrl(file2));
+ GURL url2(net::URLRequestMockHTTPJob::GetMockUrl(file2));
scoped_ptr<DownloadTestObserver> completion_observer(
CreateWaiter(shell(), 1));
DownloadItem* download(StartDownloadAndReturnItem(url2));
@@ -1574,7 +1579,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
SetupEnsureNoPendingDownloads();
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
@@ -1621,7 +1626,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
SetupEnsureNoPendingDownloads();
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
ASSERT_TRUE(test_server()->Start());
diff --git a/chromium/content/browser/download/download_create_info.cc b/chromium/content/browser/download/download_create_info.cc
index e381fa854bd..05b0992a26d 100644
--- a/chromium/content/browser/download/download_create_info.cc
+++ b/chromium/content/browser/download/download_create_info.cc
@@ -15,7 +15,7 @@ DownloadCreateInfo::DownloadCreateInfo(const base::Time& start_time,
int64 total_bytes,
const net::BoundNetLog& bound_net_log,
bool has_user_gesture,
- PageTransition transition_type,
+ ui::PageTransition transition_type,
scoped_ptr<DownloadSaveInfo> save_info)
: start_time(start_time),
total_bytes(total_bytes),
@@ -29,7 +29,7 @@ DownloadCreateInfo::DownloadCreateInfo()
: total_bytes(0),
download_id(DownloadItem::kInvalidId),
has_user_gesture(false),
- transition_type(PAGE_TRANSITION_LINK),
+ transition_type(ui::PAGE_TRANSITION_LINK),
save_info(new DownloadSaveInfo()) {
}
diff --git a/chromium/content/browser/download/download_create_info.h b/chromium/content/browser/download/download_create_info.h
index e8e1443b93a..cbf87119aa2 100644
--- a/chromium/content/browser/download/download_create_info.h
+++ b/chromium/content/browser/download/download_create_info.h
@@ -15,8 +15,8 @@
#include "content/browser/download/download_request_handle.h"
#include "content/common/content_export.h"
#include "content/public/browser/download_save_info.h"
-#include "content/public/common/page_transition_types.h"
#include "net/base/net_log.h"
+#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace content {
@@ -28,7 +28,7 @@ struct CONTENT_EXPORT DownloadCreateInfo {
int64 total_bytes,
const net::BoundNetLog& bound_net_log,
bool has_user_gesture,
- PageTransition transition_type,
+ ui::PageTransition transition_type,
scoped_ptr<DownloadSaveInfo> save_info);
DownloadCreateInfo();
~DownloadCreateInfo();
@@ -63,7 +63,7 @@ struct CONTENT_EXPORT DownloadCreateInfo {
// True if the download was initiated by user action.
bool has_user_gesture;
- PageTransition transition_type;
+ ui::PageTransition transition_type;
// The content-disposition string from the response header.
std::string content_disposition;
diff --git a/chromium/content/browser/download/download_file_impl.cc b/chromium/content/browser/download/download_file_impl.cc
index 11e98cb726b..91b25dac35b 100644
--- a/chromium/content/browser/download/download_file_impl.cc
+++ b/chromium/content/browser/download/download_file_impl.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
@@ -25,6 +25,12 @@ namespace content {
const int kUpdatePeriodMs = 500;
const int kMaxTimeBlockingFileThreadMs = 1000;
+// These constants control the default retry behavior for failing renames. Each
+// retry is performed after a delay that is twice the previous delay. The
+// initial delay is specified by kInitialRenameRetryDelayMs.
+const int kMaxRenameRetries = 3;
+const int kInitialRenameRetryDelayMs = 200;
+
int DownloadFile::number_active_objects_ = 0;
DownloadFileImpl::DownloadFileImpl(
@@ -36,20 +42,20 @@ DownloadFileImpl::DownloadFileImpl(
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer)
- : file_(save_info->file_path,
- url,
- referrer_url,
- save_info->offset,
- calculate_hash,
- save_info->hash_state,
- save_info->file.Pass(),
- bound_net_log),
- default_download_directory_(default_download_directory),
- stream_reader_(stream.Pass()),
- bytes_seen_(0),
- bound_net_log_(bound_net_log),
- observer_(observer),
- weak_factory_(this) {
+ : file_(save_info->file_path,
+ url,
+ referrer_url,
+ save_info->offset,
+ calculate_hash,
+ save_info->hash_state,
+ save_info->file.Pass(),
+ bound_net_log),
+ default_download_directory_(default_download_directory),
+ stream_reader_(stream.Pass()),
+ bytes_seen_(0),
+ bound_net_log_(bound_net_log),
+ observer_(observer),
+ weak_factory_(this) {
}
DownloadFileImpl::~DownloadFileImpl() {
@@ -103,47 +109,84 @@ DownloadInterruptReason DownloadFileImpl::AppendDataToFile(
void DownloadFileImpl::RenameAndUniquify(
const base::FilePath& full_path,
const RenameCompletionCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- base::FilePath new_path(full_path);
-
- int uniquifier = base::GetUniquePathNumber(
- new_path, base::FilePath::StringType());
- if (uniquifier > 0) {
- new_path = new_path.InsertBeforeExtensionASCII(
- base::StringPrintf(" (%d)", uniquifier));
- }
-
- DownloadInterruptReason reason = file_.Rename(new_path);
- if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
- // Make sure our information is updated, since we're about to
- // error out.
- SendUpdate();
+ RenameWithRetryInternal(
+ full_path, UNIQUIFY, kMaxRenameRetries, base::TimeTicks(), callback);
+}
- // Null out callback so that we don't do any more stream processing.
- stream_reader_->RegisterCallback(base::Closure());
+void DownloadFileImpl::RenameAndAnnotate(
+ const base::FilePath& full_path,
+ const RenameCompletionCallback& callback) {
+ RenameWithRetryInternal(full_path,
+ ANNOTATE_WITH_SOURCE_INFORMATION,
+ kMaxRenameRetries,
+ base::TimeTicks(),
+ callback);
+}
- new_path.clear();
- }
+base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename(
+ int attempt_number) {
+ DCHECK_GE(attempt_number, 0);
+ // |delay| starts at kInitialRenameRetryDelayMs and increases by a factor of
+ // 2 at each subsequent retry. Assumes that |retries_left| starts at
+ // kMaxRenameRetries. Also assumes that kMaxRenameRetries is less than the
+ // number of bits in an int.
+ return base::TimeDelta::FromMilliseconds(kInitialRenameRetryDelayMs) *
+ (1 << attempt_number);
+}
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(callback, reason, new_path));
+bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) {
+ return reason == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
}
-void DownloadFileImpl::RenameAndAnnotate(
+void DownloadFileImpl::RenameWithRetryInternal(
const base::FilePath& full_path,
+ RenameOption option,
+ int retries_left,
+ base::TimeTicks time_of_first_failure,
const RenameCompletionCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::FilePath new_path(full_path);
- DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE;
- // Short circuit null rename.
- if (full_path != file_.full_path())
- reason = file_.Rename(new_path);
+ if ((option & UNIQUIFY) && full_path != file_.full_path()) {
+ int uniquifier =
+ base::GetUniquePathNumber(new_path, base::FilePath::StringType());
+ if (uniquifier > 0)
+ new_path = new_path.InsertBeforeExtensionASCII(
+ base::StringPrintf(" (%d)", uniquifier));
+ }
+
+ DownloadInterruptReason reason = file_.Rename(new_path);
+
+ // Attempt to retry the rename if possible. If the rename failed and the
+ // subsequent open also failed, then in_progress() would be false. We don't
+ // try to retry renames if the in_progress() was false to begin with since we
+ // have less assurance that the file at file_.full_path() was the one we were
+ // working with.
+ if (ShouldRetryFailedRename(reason) && file_.in_progress() &&
+ retries_left > 0) {
+ int attempt_number = kMaxRenameRetries - retries_left;
+ BrowserThread::PostDelayedTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&DownloadFileImpl::RenameWithRetryInternal,
+ weak_factory_.GetWeakPtr(),
+ full_path,
+ option,
+ --retries_left,
+ time_of_first_failure.is_null() ? base::TimeTicks::Now()
+ : time_of_first_failure,
+ callback),
+ GetRetryDelayForFailedRename(attempt_number));
+ return;
+ }
+
+ if (!time_of_first_failure.is_null())
+ RecordDownloadFileRenameResultAfterRetry(
+ base::TimeTicks::Now() - time_of_first_failure, reason);
- if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ if (reason == DOWNLOAD_INTERRUPT_REASON_NONE &&
+ (option & ANNOTATE_WITH_SOURCE_INFORMATION)) {
// Doing the annotation after the rename rather than before leaves
// a very small window during which the file has the final name but
// hasn't been marked with the Mark Of The Web. However, it allows
diff --git a/chromium/content/browser/download/download_file_impl.h b/chromium/content/browser/download/download_file_impl.h
index 2ba3d8d058e..9ff3f8583db 100644
--- a/chromium/content/browser/download/download_file_impl.h
+++ b/chromium/content/browser/download/download_file_impl.h
@@ -44,31 +44,58 @@ class CONTENT_EXPORT DownloadFileImpl : virtual public DownloadFile {
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer);
- virtual ~DownloadFileImpl();
+ ~DownloadFileImpl() override;
// DownloadFile functions.
- virtual void Initialize(const InitializeCallback& callback) OVERRIDE;
- virtual void RenameAndUniquify(
- const base::FilePath& full_path,
- const RenameCompletionCallback& callback) OVERRIDE;
- virtual void RenameAndAnnotate(
- const base::FilePath& full_path,
- const RenameCompletionCallback& callback) OVERRIDE;
- virtual void Detach() OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual base::FilePath FullPath() const OVERRIDE;
- virtual bool InProgress() const OVERRIDE;
- virtual int64 CurrentSpeed() const OVERRIDE;
- virtual bool GetHash(std::string* hash) OVERRIDE;
- virtual std::string GetHashState() OVERRIDE;
- virtual void SetClientGuid(const std::string& guid) OVERRIDE;
+ void Initialize(const InitializeCallback& callback) override;
+ void RenameAndUniquify(const base::FilePath& full_path,
+ const RenameCompletionCallback& callback) override;
+ void RenameAndAnnotate(const base::FilePath& full_path,
+ const RenameCompletionCallback& callback) override;
+ void Detach() override;
+ void Cancel() override;
+ base::FilePath FullPath() const override;
+ bool InProgress() const override;
+ int64 CurrentSpeed() const override;
+ bool GetHash(std::string* hash) override;
+ std::string GetHashState() override;
+ void SetClientGuid(const std::string& guid) override;
protected:
// For test class overrides.
virtual DownloadInterruptReason AppendDataToFile(
const char* data, size_t data_len);
+ virtual base::TimeDelta GetRetryDelayForFailedRename(int attempt_number);
+
+ virtual bool ShouldRetryFailedRename(DownloadInterruptReason reason);
+
private:
+ friend class DownloadFileTest;
+
+ // Options for RenameWithRetryInternal.
+ enum RenameOption {
+ UNIQUIFY = 1 << 0, // If there's already a file on disk that conflicts with
+ // |new_path|, try to create a unique file by appending
+ // a uniquifier.
+ ANNOTATE_WITH_SOURCE_INFORMATION = 1 << 1
+ };
+
+ // Rename file_ to |new_path|.
+ // |option| specifies additional operations to be performed during the rename.
+ // See RenameOption above.
+ // |retries_left| indicates how many times to retry the operation if the
+ // rename fails with a transient error.
+ // |time_of_first_failure| Set to an empty base::TimeTicks during the first
+ // call. Once the first failure is seen, subsequent calls of
+ // RenameWithRetryInternal will have a non-empty value keeping track of
+ // the time of first observed failure. Used for UMA.
+ void RenameWithRetryInternal(const base::FilePath& new_path,
+ RenameOption option,
+ int retries_left,
+ base::TimeTicks time_of_first_failure,
+ const RenameCompletionCallback& callback);
+
// Send an update on our progress.
void SendUpdate();
diff --git a/chromium/content/browser/download/download_file_unittest.cc b/chromium/content/browser/download/download_file_unittest.cc
index 1127908c260..620efa36ff0 100644
--- a/chromium/content/browser/download/download_file_unittest.cc
+++ b/chromium/content/browser/download/download_file_unittest.cc
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/file_util.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/test_file_util.h"
#include "content/browser/browser_thread_impl.h"
@@ -59,6 +61,46 @@ class MockDownloadDestinationObserver : public DownloadDestinationObserver {
MATCHER(IsNullCallback, "") { return (arg.is_null()); }
+typedef void (DownloadFile::*DownloadFileRenameMethodType)(
+ const base::FilePath&,
+ const DownloadFile::RenameCompletionCallback&);
+
+// This is a test DownloadFileImpl that has no retry delay and, on Posix,
+// retries renames failed due to ACCESS_DENIED.
+class TestDownloadFileImpl : public DownloadFileImpl {
+ public:
+ TestDownloadFileImpl(scoped_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ const GURL& url,
+ const GURL& referrer_url,
+ bool calculate_hash,
+ scoped_ptr<ByteStreamReader> stream,
+ const net::BoundNetLog& bound_net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer)
+ : DownloadFileImpl(save_info.Pass(),
+ default_downloads_directory,
+ url,
+ referrer_url,
+ calculate_hash,
+ stream.Pass(),
+ bound_net_log,
+ observer) {}
+
+ protected:
+ base::TimeDelta GetRetryDelayForFailedRename(int attempt_count) override {
+ return base::TimeDelta::FromMilliseconds(0);
+ }
+
+#if !defined(OS_WIN)
+ // On Posix, we don't encounter transient errors during renames, except
+ // possibly EAGAIN, which is difficult to replicate reliably. So we resort to
+ // simulating a transient error using ACCESS_DENIED instead.
+ bool ShouldRetryFailedRename(DownloadInterruptReason reason) override {
+ return reason == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
+ }
+#endif
+};
+
} // namespace
class DownloadFileTest : public testing::Test {
@@ -83,8 +125,7 @@ class DownloadFileTest : public testing::Test {
file_thread_(BrowserThread::FILE, &loop_) {
}
- virtual ~DownloadFileTest() {
- }
+ ~DownloadFileTest() override {}
void SetUpdateDownloadInfo(int64 bytes, int64 bytes_per_sec,
const std::string& hash_state) {
@@ -97,22 +138,22 @@ class DownloadFileTest : public testing::Test {
observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_, hash_state_);
}
- virtual void SetUp() {
+ void SetUp() override {
EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo));
}
// Mock calls to this function are forwarded here.
- void RegisterCallback(base::Closure sink_callback) {
+ void RegisterCallback(const base::Closure& sink_callback) {
sink_callback_ = sink_callback;
}
- void SetInterruptReasonCallback(bool* was_called,
+ void SetInterruptReasonCallback(const base::Closure& closure,
DownloadInterruptReason* reason_p,
DownloadInterruptReason reason) {
- *was_called = true;
*reason_p = reason;
+ closure.Run();
}
bool CreateDownloadFile(int offset, bool calculate_hash) {
@@ -128,30 +169,29 @@ class DownloadFileTest : public testing::Test {
.RetiresOnSaturation();
scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
- download_file_.reset(
- new DownloadFileImpl(save_info.Pass(),
- base::FilePath(),
- GURL(), // Source
- GURL(), // Referrer
- calculate_hash,
- scoped_ptr<ByteStreamReader>(input_stream_),
- net::BoundNetLog(),
- observer_factory_.GetWeakPtr()));
- download_file_->SetClientGuid(
- "12345678-ABCD-1234-DCBA-123456789ABC");
+ scoped_ptr<TestDownloadFileImpl> download_file_impl(
+ new TestDownloadFileImpl(save_info.Pass(),
+ base::FilePath(),
+ GURL(), // Source
+ GURL(), // Referrer
+ calculate_hash,
+ scoped_ptr<ByteStreamReader>(input_stream_),
+ net::BoundNetLog(),
+ observer_factory_.GetWeakPtr()));
+ download_file_impl->SetClientGuid("12345678-ABCD-1234-DCBA-123456789ABC");
+ download_file_ = download_file_impl.Pass();
EXPECT_CALL(*input_stream_, Read(_, _))
.WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
.RetiresOnSaturation();
base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
- bool called = false;
- DownloadInterruptReason result;
+ DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
+ base::RunLoop loop_runner;
download_file_->Initialize(base::Bind(
&DownloadFileTest::SetInterruptReasonCallback,
- weak_ptr_factory.GetWeakPtr(), &called, &result));
- loop_.RunUntilIdle();
- EXPECT_TRUE(called);
+ weak_ptr_factory.GetWeakPtr(), loop_runner.QuitClosure(), &result));
+ loop_runner.Run();
::testing::Mock::VerifyAndClearExpectations(input_stream_);
return result == DOWNLOAD_INTERRUPT_REASON_NONE;
@@ -243,42 +283,42 @@ class DownloadFileTest : public testing::Test {
DownloadInterruptReason RenameAndUniquify(
const base::FilePath& full_path,
base::FilePath* result_path_p) {
- base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
- DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
- bool callback_was_called(false);
- base::FilePath result_path;
+ return InvokeRenameMethodAndWaitForCallback(
+ &DownloadFile::RenameAndUniquify, full_path, result_path_p);
+ }
- download_file_->RenameAndUniquify(
- full_path, base::Bind(&DownloadFileTest::SetRenameResult,
- weak_ptr_factory.GetWeakPtr(),
- &callback_was_called,
- &result_reason, result_path_p));
- loop_.RunUntilIdle();
+ DownloadInterruptReason RenameAndAnnotate(
+ const base::FilePath& full_path,
+ base::FilePath* result_path_p) {
+ return InvokeRenameMethodAndWaitForCallback(
+ &DownloadFile::RenameAndAnnotate, full_path, result_path_p);
+ }
- EXPECT_TRUE(callback_was_called);
- return result_reason;
+ void ExpectPermissionError(DownloadInterruptReason err) {
+ EXPECT_TRUE(err == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR ||
+ err == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED)
+ << "Interrupt reason = " << err;
}
- DownloadInterruptReason RenameAndAnnotate(
+ protected:
+ DownloadInterruptReason InvokeRenameMethodAndWaitForCallback(
+ DownloadFileRenameMethodType method,
const base::FilePath& full_path,
base::FilePath* result_path_p) {
- base::WeakPtrFactory<DownloadFileTest> weak_ptr_factory(this);
DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
- bool callback_was_called(false);
base::FilePath result_path;
- download_file_->RenameAndAnnotate(
- full_path, base::Bind(&DownloadFileTest::SetRenameResult,
- weak_ptr_factory.GetWeakPtr(),
- &callback_was_called,
- &result_reason, result_path_p));
- loop_.RunUntilIdle();
-
- EXPECT_TRUE(callback_was_called);
+ base::RunLoop loop_runner;
+ ((*download_file_).*method)(full_path,
+ base::Bind(&DownloadFileTest::SetRenameResult,
+ base::Unretained(this),
+ loop_runner.QuitClosure(),
+ &result_reason,
+ result_path_p));
+ loop_runner.Run();
return result_reason;
}
- protected:
scoped_ptr<StrictMock<MockDownloadDestinationObserver> > observer_;
base::WeakPtrFactory<DownloadDestinationObserver> observer_factory_;
@@ -300,17 +340,16 @@ class DownloadFileTest : public testing::Test {
base::MessageLoop loop_;
private:
- void SetRenameResult(bool* called_p,
+ void SetRenameResult(const base::Closure& closure,
DownloadInterruptReason* reason_p,
base::FilePath* result_path_p,
DownloadInterruptReason reason,
const base::FilePath& result_path) {
- if (called_p)
- *called_p = true;
if (reason_p)
*reason_p = reason;
if (result_path_p)
*result_path_p = result_path;
+ closure.Run();
}
// UI thread.
@@ -322,6 +361,33 @@ class DownloadFileTest : public testing::Test {
std::string expected_data_;
};
+// DownloadFile::RenameAndAnnotate and DownloadFile::RenameAndUniquify have a
+// considerable amount of functional overlap. In order to re-use test logic, we
+// are going to introduce this value parameterized test fixture. It will take a
+// DownloadFileRenameMethodType value which can be either of the two rename
+// methods.
+class DownloadFileTestWithRename
+ : public DownloadFileTest,
+ public ::testing::WithParamInterface<DownloadFileRenameMethodType> {
+ protected:
+ DownloadInterruptReason InvokeSelectedRenameMethod(
+ const base::FilePath& full_path,
+ base::FilePath* result_path_p) {
+ return InvokeRenameMethodAndWaitForCallback(
+ GetParam(), full_path, result_path_p);
+ }
+};
+
+// And now instantiate all DownloadFileTestWithRename tests using both
+// DownloadFile rename methods. Each test of the form
+// DownloadFileTestWithRename.<FooTest> will be instantiated once with
+// RenameAndAnnotate as the value parameter and once with RenameAndUniquify as
+// the value parameter.
+INSTANTIATE_TEST_CASE_P(DownloadFile,
+ DownloadFileTestWithRename,
+ ::testing::Values(&DownloadFile::RenameAndAnnotate,
+ &DownloadFile::RenameAndUniquify));
+
const char* DownloadFileTest::kTestData1 =
"Let's write some data to the file!\n";
const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
@@ -335,7 +401,7 @@ const int DownloadFileTest::kDummyRequestId = 67;
// Rename the file before any data is downloaded, after some has, after it all
// has, and after it's closed.
-TEST_F(DownloadFileTest, RenameFileFinal) {
+TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
ASSERT_TRUE(CreateDownloadFile(0, true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
@@ -343,12 +409,11 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
base::FilePath path_2(initial_path.InsertBeforeExtensionASCII("_2"));
base::FilePath path_3(initial_path.InsertBeforeExtensionASCII("_3"));
base::FilePath path_4(initial_path.InsertBeforeExtensionASCII("_4"));
- base::FilePath path_5(initial_path.InsertBeforeExtensionASCII("_5"));
base::FilePath output_path;
// Rename the file before downloading any data.
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- RenameAndUniquify(path_1, &output_path));
+ InvokeSelectedRenameMethod(path_1, &output_path));
base::FilePath renamed_path = download_file_->FullPath();
EXPECT_EQ(path_1, renamed_path);
EXPECT_EQ(path_1, output_path);
@@ -363,7 +428,7 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
// Rename the file after downloading some data.
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- RenameAndUniquify(path_2, &output_path));
+ InvokeSelectedRenameMethod(path_2, &output_path));
renamed_path = download_file_->FullPath();
EXPECT_EQ(path_2, renamed_path);
EXPECT_EQ(path_2, output_path);
@@ -377,7 +442,7 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
// Rename the file after downloading all the data.
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- RenameAndUniquify(path_3, &output_path));
+ InvokeSelectedRenameMethod(path_3, &output_path));
renamed_path = download_file_->FullPath();
EXPECT_EQ(path_3, renamed_path);
EXPECT_EQ(path_3, output_path);
@@ -394,7 +459,7 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
// Rename the file after downloading all the data and closing the file.
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- RenameAndUniquify(path_4, &output_path));
+ InvokeSelectedRenameMethod(path_4, &output_path));
renamed_path = download_file_->FullPath();
EXPECT_EQ(path_4, renamed_path);
EXPECT_EQ(path_4, output_path);
@@ -407,29 +472,42 @@ TEST_F(DownloadFileTest, RenameFileFinal) {
EXPECT_TRUE(download_file_->GetHash(&hash));
EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));
- // Check that a rename with overwrite to an existing file succeeds.
- std::string file_contents;
- ASSERT_FALSE(base::PathExists(path_5));
+ DestroyDownloadFile(0);
+}
+
+// Test to make sure the rename overwrites when requested. This is separate from
+// the above test because it only applies to RenameAndAnnotate().
+// RenameAndUniquify() doesn't overwrite by design.
+TEST_F(DownloadFileTest, RenameOverwrites) {
+ ASSERT_TRUE(CreateDownloadFile(0, true));
+ base::FilePath initial_path(download_file_->FullPath());
+ EXPECT_TRUE(base::PathExists(initial_path));
+ base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
+
+ ASSERT_FALSE(base::PathExists(path_1));
static const char file_data[] = "xyzzy";
- ASSERT_EQ(static_cast<int>(sizeof(file_data) - 1),
- base::WriteFile(path_5, file_data, sizeof(file_data) - 1));
- ASSERT_TRUE(base::PathExists(path_5));
- EXPECT_TRUE(base::ReadFileToString(path_5, &file_contents));
- EXPECT_EQ(std::string(file_data), file_contents);
+ ASSERT_EQ(static_cast<int>(sizeof(file_data)),
+ base::WriteFile(path_1, file_data, sizeof(file_data)));
+ ASSERT_TRUE(base::PathExists(path_1));
+ base::FilePath new_path;
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- RenameAndAnnotate(path_5, &output_path));
- EXPECT_EQ(path_5, output_path);
+ RenameAndAnnotate(path_1, &new_path));
+ EXPECT_EQ(path_1.value(), new_path.value());
- file_contents = "";
- EXPECT_TRUE(base::ReadFileToString(path_5, &file_contents));
+ std::string file_contents;
+ ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
EXPECT_NE(std::string(file_data), file_contents);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ loop_.RunUntilIdle();
DestroyDownloadFile(0);
}
// Test to make sure the rename uniquifies if we aren't overwriting
-// and there's a file where we're aiming.
+// and there's a file where we're aiming. As above, not a
+// DownloadFileTestWithRename test because this only applies to
+// RenameAndUniquify().
TEST_F(DownloadFileTest, RenameUniquifies) {
ASSERT_TRUE(CreateDownloadFile(0, true));
base::FilePath initial_path(download_file_->FullPath());
@@ -451,16 +529,35 @@ TEST_F(DownloadFileTest, RenameUniquifies) {
DestroyDownloadFile(0);
}
+// Test that RenameAndUniquify doesn't try to uniquify in the case where the
+// target filename is the same as the current filename.
+TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) {
+ ASSERT_TRUE(CreateDownloadFile(0, true));
+ base::FilePath initial_path(download_file_->FullPath());
+ EXPECT_TRUE(base::PathExists(initial_path));
+
+ base::FilePath new_path;
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ RenameAndUniquify(initial_path, &new_path));
+ EXPECT_TRUE(base::PathExists(initial_path));
+
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ loop_.RunUntilIdle();
+ DestroyDownloadFile(0);
+ EXPECT_EQ(initial_path.value(), new_path.value());
+}
+
// Test to make sure we get the proper error on failure.
-TEST_F(DownloadFileTest, RenameError) {
+TEST_P(DownloadFileTestWithRename, RenameError) {
ASSERT_TRUE(CreateDownloadFile(0, true));
base::FilePath initial_path(download_file_->FullPath());
// Create a subdirectory.
- base::FilePath tempdir(
- initial_path.DirName().Append(FILE_PATH_LITERAL("tempdir")));
- ASSERT_TRUE(base::CreateDirectory(tempdir));
- base::FilePath target_path(tempdir.Append(initial_path.BaseName()));
+ base::FilePath target_dir(
+ initial_path.DirName().Append(FILE_PATH_LITERAL("TargetDir")));
+ ASSERT_FALSE(base::DirectoryExists(target_dir));
+ ASSERT_TRUE(base::CreateDirectory(target_dir));
+ base::FilePath target_path(target_dir.Append(initial_path.BaseName()));
// Targets
base::FilePath target_path_suffixed(
@@ -470,13 +567,12 @@ TEST_F(DownloadFileTest, RenameError) {
// Make the directory unwritable and try to rename within it.
{
- file_util::PermissionRestorer restorer(tempdir);
- ASSERT_TRUE(file_util::MakeFileUnwritable(tempdir));
+ base::FilePermissionRestorer restorer(target_dir);
+ ASSERT_TRUE(base::MakeFileUnwritable(target_dir));
// Expect nulling out of further processing.
EXPECT_CALL(*input_stream_, RegisterCallback(IsNullCallback()));
- EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
- RenameAndAnnotate(target_path, NULL));
+ ExpectPermissionError(InvokeSelectedRenameMethod(target_path, NULL));
EXPECT_FALSE(base::PathExists(target_path_suffixed));
}
@@ -485,6 +581,98 @@ TEST_F(DownloadFileTest, RenameError) {
DestroyDownloadFile(0);
}
+namespace {
+
+void TestRenameCompletionCallback(const base::Closure& closure,
+ bool* did_run_callback,
+ DownloadInterruptReason interrupt_reason,
+ const base::FilePath& new_path) {
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
+ *did_run_callback = true;
+ closure.Run();
+}
+
+} // namespace
+
+// Test that the retry logic works. This test assumes that DownloadFileImpl will
+// post tasks to the current message loop (acting as the FILE thread)
+// asynchronously to retry the renames. We will stuff RunLoop::QuitClosures()
+// in between the retry tasks to stagger them and then allow the rename to
+// succeed.
+//
+// Note that there is only one queue of tasks to run, and that is in the tests'
+// base::MessageLoop::current(). Each RunLoop processes that queue until it sees
+// a QuitClosure() targeted at itself, at which point it stops processing.
+TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
+ ASSERT_TRUE(CreateDownloadFile(0, true));
+ base::FilePath initial_path(download_file_->FullPath());
+
+ // Create a subdirectory.
+ base::FilePath target_dir(
+ initial_path.DirName().Append(FILE_PATH_LITERAL("TargetDir")));
+ ASSERT_FALSE(base::DirectoryExists(target_dir));
+ ASSERT_TRUE(base::CreateDirectory(target_dir));
+ base::FilePath target_path(target_dir.Append(initial_path.BaseName()));
+
+ bool did_run_callback = false;
+
+ // Each RunLoop can be used the run the MessageLoop until the corresponding
+ // QuitClosure() is run. This one is used to produce the QuitClosure() that
+ // will be run when the entire rename operation is complete.
+ base::RunLoop succeeding_run;
+ {
+ // (Scope for the base::File or base::FilePermissionRestorer below.)
+#if defined(OS_WIN)
+ // On Windows we test with an actual transient error, a sharing violation.
+ // The rename will fail because we are holding the file open for READ. On
+ // Posix this doesn't cause a failure.
+ base::File locked_file(initial_path,
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ ASSERT_TRUE(locked_file.IsValid());
+#else
+ // Simulate a transient failure by revoking write permission for target_dir.
+ // The TestDownloadFileImpl class treats this error as transient even though
+ // DownloadFileImpl itself doesn't.
+ base::FilePermissionRestorer restore_permissions_for(target_dir);
+ ASSERT_TRUE(base::MakeFileUnwritable(target_dir));
+#endif
+
+ // The Rename() should fail here and enqueue a retry task without invoking
+ // the completion callback.
+ ((*download_file_).*GetParam())(target_path,
+ base::Bind(&TestRenameCompletionCallback,
+ succeeding_run.QuitClosure(),
+ &did_run_callback));
+ EXPECT_FALSE(did_run_callback);
+
+ base::RunLoop first_failing_run;
+ // Queue the QuitClosure() on the MessageLoop now. Any tasks queued by the
+ // Rename() will be in front of the QuitClosure(). Running the message loop
+ // now causes the just the first retry task to be run. The rename still
+ // fails, so another retry task would get queued behind the QuitClosure().
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ first_failing_run.QuitClosure());
+ first_failing_run.Run();
+ EXPECT_FALSE(did_run_callback);
+
+ // Running another loop should have the same effect as the above as long as
+ // kMaxRenameRetries is greater than 2.
+ base::RunLoop second_failing_run;
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ second_failing_run.QuitClosure());
+ second_failing_run.Run();
+ EXPECT_FALSE(did_run_callback);
+ }
+
+ // This time the QuitClosure from succeeding_run should get executed.
+ succeeding_run.Run();
+ EXPECT_TRUE(did_run_callback);
+
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ loop_.RunUntilIdle();
+ DestroyDownloadFile(0);
+}
+
// Various tests of the StreamActive method.
TEST_F(DownloadFileTest, StreamEmptySuccess) {
ASSERT_TRUE(CreateDownloadFile(0, true));
diff --git a/chromium/content/browser/download/download_interrupt_reasons_impl.cc b/chromium/content/browser/download/download_interrupt_reasons_impl.cc
index 9a01f484f1d..2ed8f147ee0 100644
--- a/chromium/content/browser/download/download_interrupt_reasons_impl.cc
+++ b/chromium/content/browser/download/download_interrupt_reasons_impl.cc
@@ -8,6 +8,35 @@
namespace content {
+DownloadInterruptReason ConvertFileErrorToInterruptReason(
+ base::File::Error file_error) {
+ switch (file_error) {
+ case base::File::FILE_OK:
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+
+ case base::File::FILE_ERROR_IN_USE:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
+
+ case base::File::FILE_ERROR_ACCESS_DENIED:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
+
+ case base::File::FILE_ERROR_TOO_MANY_OPENED:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
+
+ case base::File::FILE_ERROR_NO_MEMORY:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR;
+
+ case base::File::FILE_ERROR_NO_SPACE:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE;
+
+ case base::File::FILE_ERROR_SECURITY:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED;
+
+ default:
+ return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
+ }
+}
+
DownloadInterruptReason ConvertNetErrorToInterruptReason(
net::Error net_error, DownloadInterruptSource source) {
switch (net_error) {
diff --git a/chromium/content/browser/download/download_interrupt_reasons_impl.h b/chromium/content/browser/download/download_interrupt_reasons_impl.h
index 137dcb2abc5..61ccae1a441 100644
--- a/chromium/content/browser/download/download_interrupt_reasons_impl.h
+++ b/chromium/content/browser/download/download_interrupt_reasons_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_INTERRUPT_REASONS_IMPL_H_
#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_INTERRUPT_REASONS_IMPL_H_
+#include "base/files/file.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "net/base/net_errors.h"
@@ -22,6 +23,10 @@ enum DownloadInterruptSource {
DownloadInterruptReason CONTENT_EXPORT ConvertNetErrorToInterruptReason(
net::Error file_error, DownloadInterruptSource source);
+// Safe to call from any thread.
+DownloadInterruptReason CONTENT_EXPORT ConvertFileErrorToInterruptReason(
+ base::File::Error file_error);
+
} // namespace content
#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_INTERRUPT_REASONS_IMPL_H_
diff --git a/chromium/content/browser/download/download_item_impl.cc b/chromium/content/browser/download/download_item_impl.cc
index 433ac78f48b..f681486cdcb 100644
--- a/chromium/content/browser/download/download_item_impl.cc
+++ b/chromium/content/browser/download/download_item_impl.cc
@@ -28,7 +28,7 @@
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
@@ -93,7 +93,7 @@ static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) {
}
bool IsDownloadResumptionEnabled() {
- return CommandLine::ForCurrentProcess()->HasSwitch(
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableDownloadResumption);
}
@@ -133,7 +133,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
target_disposition_(TARGET_DISPOSITION_OVERWRITE),
url_chain_(url_chain),
referrer_url_(referrer_url),
- transition_type_(PAGE_TRANSITION_LINK),
+ transition_type_(ui::PAGE_TRANSITION_LINK),
has_user_gesture_(false),
mime_type_(mime_type),
original_mime_type_(original_mime_type),
@@ -242,7 +242,7 @@ DownloadItemImpl::DownloadItemImpl(
target_disposition_(TARGET_DISPOSITION_OVERWRITE),
url_chain_(1, url),
referrer_url_(GURL()),
- transition_type_(PAGE_TRANSITION_LINK),
+ transition_type_(ui::PAGE_TRANSITION_LINK),
has_user_gesture_(false),
mime_type_(mime_type),
original_mime_type_(mime_type),
@@ -588,7 +588,7 @@ bool DownloadItemImpl::HasUserGesture() const {
return has_user_gesture_;
};
-PageTransition DownloadItemImpl::GetTransitionType() const {
+ui::PageTransition DownloadItemImpl::GetTransitionType() const {
return transition_type_;
};
@@ -927,6 +927,8 @@ DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
case DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
case DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
+ case DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
+ case DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
mode = RESUME_MODE_INVALID;
break;
}
@@ -1680,7 +1682,8 @@ void DownloadItemImpl::ResumeInterruptedDownload() {
// If the flag for downloads resumption isn't enabled, ignore
// this request.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(switches::kEnableDownloadResumption))
return;
diff --git a/chromium/content/browser/download/download_item_impl.h b/chromium/content/browser/download/download_item_impl.h
index 34916ff6fd9..b6394f7469d 100644
--- a/chromium/content/browser/download/download_item_impl.h
+++ b/chromium/content/browser/download/download_item_impl.h
@@ -14,7 +14,6 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
#include "content/browser/download/download_net_log_parameters.h"
#include "content/browser/download/download_request_handle.h"
#include "content/common/content_export.h"
@@ -87,77 +86,76 @@ class CONTENT_EXPORT DownloadItemImpl
scoped_ptr<DownloadRequestHandleInterface> request_handle,
const net::BoundNetLog& bound_net_log);
- virtual ~DownloadItemImpl();
+ ~DownloadItemImpl() override;
// DownloadItem
- virtual void AddObserver(DownloadItem::Observer* observer) OVERRIDE;
- virtual void RemoveObserver(DownloadItem::Observer* observer) OVERRIDE;
- virtual void UpdateObservers() OVERRIDE;
- virtual void ValidateDangerousDownload() OVERRIDE;
- virtual void StealDangerousDownload(const AcquireFileCallback& callback)
- OVERRIDE;
- virtual void Pause() OVERRIDE;
- virtual void Resume() OVERRIDE;
- virtual void Cancel(bool user_cancel) OVERRIDE;
- virtual void Remove() OVERRIDE;
- virtual void OpenDownload() OVERRIDE;
- virtual void ShowDownloadInShell() OVERRIDE;
- virtual uint32 GetId() const OVERRIDE;
- virtual DownloadState GetState() const OVERRIDE;
- virtual DownloadInterruptReason GetLastReason() const OVERRIDE;
- virtual bool IsPaused() const OVERRIDE;
- virtual bool IsTemporary() const OVERRIDE;
- virtual bool CanResume() const OVERRIDE;
- virtual bool IsDone() const OVERRIDE;
- virtual const GURL& GetURL() const OVERRIDE;
- virtual const std::vector<GURL>& GetUrlChain() const OVERRIDE;
- virtual const GURL& GetOriginalUrl() const OVERRIDE;
- virtual const GURL& GetReferrerUrl() const OVERRIDE;
- virtual const GURL& GetTabUrl() const OVERRIDE;
- virtual const GURL& GetTabReferrerUrl() const OVERRIDE;
- virtual std::string GetSuggestedFilename() const OVERRIDE;
- virtual std::string GetContentDisposition() const OVERRIDE;
- virtual std::string GetMimeType() const OVERRIDE;
- virtual std::string GetOriginalMimeType() const OVERRIDE;
- virtual std::string GetRemoteAddress() const OVERRIDE;
- virtual bool HasUserGesture() const OVERRIDE;
- virtual PageTransition GetTransitionType() const OVERRIDE;
- virtual const std::string& GetLastModifiedTime() const OVERRIDE;
- virtual const std::string& GetETag() const OVERRIDE;
- virtual bool IsSavePackageDownload() const OVERRIDE;
- virtual const base::FilePath& GetFullPath() const OVERRIDE;
- virtual const base::FilePath& GetTargetFilePath() const OVERRIDE;
- virtual const base::FilePath& GetForcedFilePath() const OVERRIDE;
- virtual base::FilePath GetFileNameToReportUser() const OVERRIDE;
- virtual TargetDisposition GetTargetDisposition() const OVERRIDE;
- virtual const std::string& GetHash() const OVERRIDE;
- virtual const std::string& GetHashState() const OVERRIDE;
- virtual bool GetFileExternallyRemoved() const OVERRIDE;
- virtual void DeleteFile(const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool IsDangerous() const OVERRIDE;
- virtual DownloadDangerType GetDangerType() const OVERRIDE;
- virtual bool TimeRemaining(base::TimeDelta* remaining) const OVERRIDE;
- virtual int64 CurrentSpeed() const OVERRIDE;
- virtual int PercentComplete() const OVERRIDE;
- virtual bool AllDataSaved() const OVERRIDE;
- virtual int64 GetTotalBytes() const OVERRIDE;
- virtual int64 GetReceivedBytes() const OVERRIDE;
- virtual base::Time GetStartTime() const OVERRIDE;
- virtual base::Time GetEndTime() const OVERRIDE;
- virtual bool CanShowInFolder() OVERRIDE;
- virtual bool CanOpenDownload() OVERRIDE;
- virtual bool ShouldOpenFileBasedOnExtension() OVERRIDE;
- virtual bool GetOpenWhenComplete() const OVERRIDE;
- virtual bool GetAutoOpened() OVERRIDE;
- virtual bool GetOpened() const OVERRIDE;
- virtual BrowserContext* GetBrowserContext() const OVERRIDE;
- virtual WebContents* GetWebContents() const OVERRIDE;
- virtual void OnContentCheckCompleted(DownloadDangerType danger_type) OVERRIDE;
- virtual void SetOpenWhenComplete(bool open) OVERRIDE;
- virtual void SetIsTemporary(bool temporary) OVERRIDE;
- virtual void SetOpened(bool opened) OVERRIDE;
- virtual void SetDisplayName(const base::FilePath& name) OVERRIDE;
- virtual std::string DebugString(bool verbose) const OVERRIDE;
+ void AddObserver(DownloadItem::Observer* observer) override;
+ void RemoveObserver(DownloadItem::Observer* observer) override;
+ void UpdateObservers() override;
+ void ValidateDangerousDownload() override;
+ void StealDangerousDownload(const AcquireFileCallback& callback) override;
+ void Pause() override;
+ void Resume() override;
+ void Cancel(bool user_cancel) override;
+ void Remove() override;
+ void OpenDownload() override;
+ void ShowDownloadInShell() override;
+ uint32 GetId() const override;
+ DownloadState GetState() const override;
+ DownloadInterruptReason GetLastReason() const override;
+ bool IsPaused() const override;
+ bool IsTemporary() const override;
+ bool CanResume() const override;
+ bool IsDone() const override;
+ const GURL& GetURL() const override;
+ const std::vector<GURL>& GetUrlChain() const override;
+ const GURL& GetOriginalUrl() const override;
+ const GURL& GetReferrerUrl() const override;
+ const GURL& GetTabUrl() const override;
+ const GURL& GetTabReferrerUrl() const override;
+ std::string GetSuggestedFilename() const override;
+ std::string GetContentDisposition() const override;
+ std::string GetMimeType() const override;
+ std::string GetOriginalMimeType() const override;
+ std::string GetRemoteAddress() const override;
+ bool HasUserGesture() const override;
+ ui::PageTransition GetTransitionType() const override;
+ const std::string& GetLastModifiedTime() const override;
+ const std::string& GetETag() const override;
+ bool IsSavePackageDownload() const override;
+ const base::FilePath& GetFullPath() const override;
+ const base::FilePath& GetTargetFilePath() const override;
+ const base::FilePath& GetForcedFilePath() const override;
+ base::FilePath GetFileNameToReportUser() const override;
+ TargetDisposition GetTargetDisposition() const override;
+ const std::string& GetHash() const override;
+ const std::string& GetHashState() const override;
+ bool GetFileExternallyRemoved() const override;
+ void DeleteFile(const base::Callback<void(bool)>& callback) override;
+ bool IsDangerous() const override;
+ DownloadDangerType GetDangerType() const override;
+ bool TimeRemaining(base::TimeDelta* remaining) const override;
+ int64 CurrentSpeed() const override;
+ int PercentComplete() const override;
+ bool AllDataSaved() const override;
+ int64 GetTotalBytes() const override;
+ int64 GetReceivedBytes() const override;
+ base::Time GetStartTime() const override;
+ base::Time GetEndTime() const override;
+ bool CanShowInFolder() override;
+ bool CanOpenDownload() override;
+ bool ShouldOpenFileBasedOnExtension() override;
+ bool GetOpenWhenComplete() const override;
+ bool GetAutoOpened() override;
+ bool GetOpened() const override;
+ BrowserContext* GetBrowserContext() const override;
+ WebContents* GetWebContents() const override;
+ void OnContentCheckCompleted(DownloadDangerType danger_type) override;
+ void SetOpenWhenComplete(bool open) override;
+ void SetIsTemporary(bool temporary) override;
+ void SetOpened(bool opened) override;
+ void SetDisplayName(const base::FilePath& name) override;
+ std::string DebugString(bool verbose) const override;
// All remaining public interfaces virtual to allow for DownloadItemImpl
// mocks.
@@ -210,11 +208,11 @@ class CONTENT_EXPORT DownloadItemImpl
virtual void MarkAsComplete();
// DownloadDestinationObserver
- virtual void DestinationUpdate(int64 bytes_so_far,
- int64 bytes_per_sec,
- const std::string& hash_state) OVERRIDE;
- virtual void DestinationError(DownloadInterruptReason reason) OVERRIDE;
- virtual void DestinationCompleted(const std::string& final_hash) OVERRIDE;
+ void DestinationUpdate(int64 bytes_so_far,
+ int64 bytes_per_sec,
+ const std::string& hash_state) override;
+ void DestinationError(DownloadInterruptReason reason) override;
+ void DestinationCompleted(const std::string& final_hash) override;
private:
// Fine grained states of a download. Note that active downloads are created
@@ -437,7 +435,7 @@ class CONTENT_EXPORT DownloadItemImpl
base::FilePath forced_file_path_;
// Page transition that triggerred the download.
- PageTransition transition_type_;
+ ui::PageTransition transition_type_;
// Whether the download was triggered with a user gesture.
bool has_user_gesture_;
diff --git a/chromium/content/browser/download/download_item_impl_unittest.cc b/chromium/content/browser/download/download_item_impl_unittest.cc
index 1291ce11350..acbc55e2ef8 100644
--- a/chromium/content/browser/download/download_item_impl_unittest.cc
+++ b/chromium/content/browser/download/download_item_impl_unittest.cc
@@ -54,7 +54,7 @@ class MockDelegate : public DownloadItemImplDelegate {
MOCK_METHOD1(CheckForFileRemoval, void(DownloadItemImpl*));
virtual void ResumeInterruptedDownload(
- scoped_ptr<DownloadUrlParameters> params, uint32 id) OVERRIDE {
+ scoped_ptr<DownloadUrlParameters> params, uint32 id) override {
MockResumeInterruptedDownload(params.get(), id);
}
MOCK_METHOD2(MockResumeInterruptedDownload,
@@ -121,17 +121,17 @@ class DownloadItemTest : public testing::Test {
item_->AddObserver(this);
}
- virtual ~MockObserver() {
+ ~MockObserver() override {
if (item_) item_->RemoveObserver(this);
}
- virtual void OnDownloadRemoved(DownloadItem* download) OVERRIDE {
+ void OnDownloadRemoved(DownloadItem* download) override {
DVLOG(20) << " " << __FUNCTION__
<< " download = " << download->DebugString(false);
removed_ = true;
}
- virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
+ void OnDownloadUpdated(DownloadItem* download) override {
DVLOG(20) << " " << __FUNCTION__
<< " download = " << download->DebugString(false);
updated_ = true;
@@ -147,12 +147,12 @@ class DownloadItemTest : public testing::Test {
last_state_ = new_state;
}
- virtual void OnDownloadOpened(DownloadItem* download) OVERRIDE {
+ void OnDownloadOpened(DownloadItem* download) override {
DVLOG(20) << " " << __FUNCTION__
<< " download = " << download->DebugString(false);
}
- virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
+ void OnDownloadDestroyed(DownloadItem* download) override {
DVLOG(20) << " " << __FUNCTION__
<< " download = " << download->DebugString(false);
destroyed_ = true;
@@ -409,7 +409,7 @@ TEST_F(DownloadItemTest, NotificationAfterDestroyed) {
}
TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
DownloadItemImpl* item = CreateDownloadItem();
@@ -437,7 +437,7 @@ TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
// Same as above, but with a non-continuable interrupt.
TEST_F(DownloadItemTest, RestartAfterInterrupted) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
DownloadItemImpl* item = CreateDownloadItem();
@@ -461,7 +461,7 @@ TEST_F(DownloadItemTest, RestartAfterInterrupted) {
// Check we do correct cleanup for RESUME_MODE_INVALID interrupts.
TEST_F(DownloadItemTest, UnresumableInterrupt) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
DownloadItemImpl* item = CreateDownloadItem();
@@ -491,7 +491,7 @@ TEST_F(DownloadItemTest, UnresumableInterrupt) {
}
TEST_F(DownloadItemTest, LimitRestartsAfterInterrupted) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
DownloadItemImpl* item = CreateDownloadItem();
@@ -813,7 +813,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
// intermediate path should be retained when the download is interrupted after
// the intermediate rename succeeds.
TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
@@ -848,7 +848,7 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
// As above. If the intermediate rename fails, then the interrupt reason should
// be set to the destination error and the intermediate path should be empty.
TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
@@ -1248,7 +1248,7 @@ TEST_F(DownloadItemTest, StealDangerousDownload) {
}
TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
base::FilePath returned_path;
DownloadItemImpl* item = CreateDownloadItem();
@@ -1274,7 +1274,7 @@ TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
}
TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableDownloadResumption);
base::FilePath returned_path;
DownloadItemImpl* item = CreateDownloadItem();
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 2bd747d5595..30296cb82e7 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -39,10 +39,10 @@
#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/referrer.h"
+#include "net/base/elements_upload_data_stream.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
-#include "net/base/upload_data_stream.h"
#include "net/url_request/url_request_context.h"
namespace content {
@@ -63,8 +63,8 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
const std::string& body = params->post_body();
scoped_ptr<net::UploadElementReader> reader(
net::UploadOwnedBytesElementReader::CreateWithString(body));
- request->set_upload(make_scoped_ptr(
- net::UploadDataStream::CreateWithReader(reader.Pass(), 0)));
+ request->set_upload(
+ net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0));
}
if (params->post_id() >= 0) {
// The POST in this case does not have an actual body, and only works
@@ -75,7 +75,8 @@ void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
DCHECK_EQ("POST", params->method());
ScopedVector<net::UploadElementReader> element_readers;
request->set_upload(make_scoped_ptr(
- new net::UploadDataStream(element_readers.Pass(), params->post_id())));
+ new net::ElementsUploadDataStream(element_readers.Pass(),
+ params->post_id())));
}
// If we're not at the beginning of the file, retrieve only the remaining
@@ -160,9 +161,9 @@ class MapValueIteratorAdapter {
class DownloadItemFactoryImpl : public DownloadItemFactory {
public:
DownloadItemFactoryImpl() {}
- virtual ~DownloadItemFactoryImpl() {}
+ ~DownloadItemFactoryImpl() override {}
- virtual DownloadItemImpl* CreatePersistedItem(
+ DownloadItemImpl* CreatePersistedItem(
DownloadItemImplDelegate* delegate,
uint32 download_id,
const base::FilePath& current_path,
@@ -181,7 +182,7 @@ class DownloadItemFactoryImpl : public DownloadItemFactory {
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
bool opened,
- const net::BoundNetLog& bound_net_log) OVERRIDE {
+ const net::BoundNetLog& bound_net_log) override {
return new DownloadItemImpl(
delegate,
download_id,
@@ -204,22 +205,22 @@ class DownloadItemFactoryImpl : public DownloadItemFactory {
bound_net_log);
}
- virtual DownloadItemImpl* CreateActiveItem(
+ DownloadItemImpl* CreateActiveItem(
DownloadItemImplDelegate* delegate,
uint32 download_id,
const DownloadCreateInfo& info,
- const net::BoundNetLog& bound_net_log) OVERRIDE {
+ const net::BoundNetLog& bound_net_log) override {
return new DownloadItemImpl(delegate, download_id, info, bound_net_log);
}
- virtual DownloadItemImpl* CreateSavePageItem(
+ DownloadItemImpl* CreateSavePageItem(
DownloadItemImplDelegate* delegate,
uint32 download_id,
const base::FilePath& path,
const GURL& url,
const std::string& mime_type,
scoped_ptr<DownloadRequestHandleInterface> request_handle,
- const net::BoundNetLog& bound_net_log) OVERRIDE {
+ const net::BoundNetLog& bound_net_log) override {
return new DownloadItemImpl(delegate, download_id, path, url,
mime_type, request_handle.Pass(),
bound_net_log);
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index 630c83252a8..0c9c33bbbad 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -40,7 +40,7 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
// Caller guarantees that |net_log| will remain valid
// for the lifetime of DownloadManagerImpl (until Shutdown() is called).
DownloadManagerImpl(net::NetLog* net_log, BrowserContext* browser_context);
- virtual ~DownloadManagerImpl();
+ ~DownloadManagerImpl() override;
// Implementation functions (not part of the DownloadManager interface).
@@ -58,22 +58,22 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
void OnSavePackageSuccessfullyFinished(DownloadItem* download_item);
// DownloadManager functions.
- virtual void SetDelegate(DownloadManagerDelegate* delegate) OVERRIDE;
- virtual DownloadManagerDelegate* GetDelegate() const OVERRIDE;
- virtual void Shutdown() OVERRIDE;
- virtual void GetAllDownloads(DownloadVector* result) OVERRIDE;
- virtual void StartDownload(
+ void SetDelegate(DownloadManagerDelegate* delegate) override;
+ DownloadManagerDelegate* GetDelegate() const override;
+ void Shutdown() override;
+ void GetAllDownloads(DownloadVector* result) override;
+ void StartDownload(
scoped_ptr<DownloadCreateInfo> info,
scoped_ptr<ByteStreamReader> stream,
- const DownloadUrlParameters::OnStartedCallback& on_started) OVERRIDE;
- virtual int RemoveDownloadsBetween(base::Time remove_begin,
- base::Time remove_end) OVERRIDE;
- virtual int RemoveDownloads(base::Time remove_begin) OVERRIDE;
- virtual int RemoveAllDownloads() OVERRIDE;
- virtual void DownloadUrl(scoped_ptr<DownloadUrlParameters> params) OVERRIDE;
- virtual void AddObserver(Observer* observer) OVERRIDE;
- virtual void RemoveObserver(Observer* observer) OVERRIDE;
- virtual content::DownloadItem* CreateDownloadItem(
+ const DownloadUrlParameters::OnStartedCallback& on_started) override;
+ int RemoveDownloadsBetween(base::Time remove_begin,
+ base::Time remove_end) override;
+ int RemoveDownloads(base::Time remove_begin) override;
+ int RemoveAllDownloads() override;
+ void DownloadUrl(scoped_ptr<DownloadUrlParameters> params) override;
+ void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
+ content::DownloadItem* CreateDownloadItem(
uint32 id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -90,12 +90,12 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
content::DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
- bool opened) OVERRIDE;
- virtual int InProgressCount() const OVERRIDE;
- virtual int NonMaliciousInProgressCount() const OVERRIDE;
- virtual BrowserContext* GetBrowserContext() const OVERRIDE;
- virtual void CheckForHistoryFilesRemoval() OVERRIDE;
- virtual DownloadItem* GetDownload(uint32 id) OVERRIDE;
+ bool opened) override;
+ int InProgressCount() const override;
+ int NonMaliciousInProgressCount() const override;
+ BrowserContext* GetBrowserContext() const override;
+ void CheckForHistoryFilesRemoval() override;
+ DownloadItem* GetDownload(uint32 id) override;
// For testing; specifically, accessed from TestFileErrorInjector.
void SetDownloadItemFactoryForTesting(
@@ -144,22 +144,20 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
// Overridden from DownloadItemImplDelegate
// (Note that |GetBrowserContext| are present in both interfaces.)
- virtual void DetermineDownloadTarget(
- DownloadItemImpl* item, const DownloadTargetCallback& callback) OVERRIDE;
- virtual bool ShouldCompleteDownload(
- DownloadItemImpl* item, const base::Closure& complete_callback) OVERRIDE;
- virtual bool ShouldOpenFileBasedOnExtension(
- const base::FilePath& path) OVERRIDE;
- virtual bool ShouldOpenDownload(
- DownloadItemImpl* item,
- const ShouldOpenDownloadCallback& callback) OVERRIDE;
- virtual void CheckForFileRemoval(DownloadItemImpl* download_item) OVERRIDE;
- virtual void ResumeInterruptedDownload(
+ void DetermineDownloadTarget(DownloadItemImpl* item,
+ const DownloadTargetCallback& callback) override;
+ bool ShouldCompleteDownload(DownloadItemImpl* item,
+ const base::Closure& complete_callback) override;
+ bool ShouldOpenFileBasedOnExtension(const base::FilePath& path) override;
+ bool ShouldOpenDownload(DownloadItemImpl* item,
+ const ShouldOpenDownloadCallback& callback) override;
+ void CheckForFileRemoval(DownloadItemImpl* download_item) override;
+ void ResumeInterruptedDownload(
scoped_ptr<content::DownloadUrlParameters> params,
- uint32 id) OVERRIDE;
- virtual void OpenDownload(DownloadItemImpl* download) OVERRIDE;
- virtual void ShowDownloadInShell(DownloadItemImpl* download) OVERRIDE;
- virtual void DownloadRemoved(DownloadItemImpl* download) OVERRIDE;
+ uint32 id) override;
+ void OpenDownload(DownloadItemImpl* download) override;
+ void ShowDownloadInShell(DownloadItemImpl* download) override;
+ void DownloadRemoved(DownloadItemImpl* download) override;
// Factory for creation of downloads items.
scoped_ptr<DownloadItemFactory> item_factory_;
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 66430b4443a..0c5eb523966 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -111,7 +111,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_METHOD0(OnDownloadedFileRemoved, void());
virtual void Start(
scoped_ptr<DownloadFile> download_file,
- scoped_ptr<DownloadRequestHandleInterface> req_handle) OVERRIDE {
+ scoped_ptr<DownloadRequestHandleInterface> req_handle) override {
MockStart(download_file.get(), req_handle.get());
}
@@ -159,7 +159,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_METHOD0(GetAutoOpened, bool());
MOCK_CONST_METHOD0(GetForcedFilePath, const base::FilePath&());
MOCK_CONST_METHOD0(HasUserGesture, bool());
- MOCK_CONST_METHOD0(GetTransitionType, PageTransition());
+ MOCK_CONST_METHOD0(GetTransitionType, ui::PageTransition());
MOCK_CONST_METHOD0(IsTemporary, bool());
MOCK_METHOD1(SetIsTemporary, void(bool));
MOCK_METHOD1(SetOpened, void(bool));
@@ -173,7 +173,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_METHOD1(SetDisplayName, void(const base::FilePath&));
MOCK_METHOD0(NotifyRemoved, void());
// May be called when vlog is on.
- virtual std::string DebugString(bool verbose) const OVERRIDE {
+ virtual std::string DebugString(bool verbose) const override {
return std::string();
}
};
@@ -211,7 +211,7 @@ class MockDownloadItemFactory
public base::SupportsWeakPtr<MockDownloadItemFactory> {
public:
MockDownloadItemFactory();
- virtual ~MockDownloadItemFactory();
+ ~MockDownloadItemFactory() override;
// Access to map of created items.
// TODO(rdsmith): Could add type (save page, persisted, etc.)
@@ -229,7 +229,7 @@ class MockDownloadItemFactory
void RemoveItem(int id);
// Overridden methods from DownloadItemFactory.
- virtual DownloadItemImpl* CreatePersistedItem(
+ DownloadItemImpl* CreatePersistedItem(
DownloadItemImplDelegate* delegate,
uint32 download_id,
const base::FilePath& current_path,
@@ -248,20 +248,20 @@ class MockDownloadItemFactory
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
bool opened,
- const net::BoundNetLog& bound_net_log) OVERRIDE;
- virtual DownloadItemImpl* CreateActiveItem(
+ const net::BoundNetLog& bound_net_log) override;
+ DownloadItemImpl* CreateActiveItem(
DownloadItemImplDelegate* delegate,
uint32 download_id,
const DownloadCreateInfo& info,
- const net::BoundNetLog& bound_net_log) OVERRIDE;
- virtual DownloadItemImpl* CreateSavePageItem(
+ const net::BoundNetLog& bound_net_log) override;
+ DownloadItemImpl* CreateSavePageItem(
DownloadItemImplDelegate* delegate,
uint32 download_id,
const base::FilePath& path,
const GURL& url,
- const std::string& mime_type,
+ const std::string& mime_type,
scoped_ptr<DownloadRequestHandleInterface> request_handle,
- const net::BoundNetLog& bound_net_log) OVERRIDE;
+ const net::BoundNetLog& bound_net_log) override;
private:
std::map<uint32, MockDownloadItemImpl*> items_;
@@ -415,8 +415,9 @@ class MockBrowserContext : public BrowserContext {
MOCK_METHOD0(GetResourceContext, ResourceContext*());
MOCK_METHOD0(GetDownloadManagerDelegate, DownloadManagerDelegate*());
MOCK_METHOD0(GetGuestManager, BrowserPluginGuestManager* ());
- MOCK_METHOD0(GetSpecialStoragePolicy, quota::SpecialStoragePolicy*());
+ MOCK_METHOD0(GetSpecialStoragePolicy, storage::SpecialStoragePolicy*());
MOCK_METHOD0(GetPushMessagingService, PushMessagingService*());
+ MOCK_METHOD0(GetSSLHostStateDelegate, SSLHostStateDelegate*());
};
class MockDownloadManagerObserver : public DownloadManager::Observer {
@@ -445,12 +446,12 @@ class DownloadManagerTest : public testing::Test {
}
// We tear down everything in TearDown().
- virtual ~DownloadManagerTest() {}
+ ~DownloadManagerTest() override {}
// Create a MockDownloadItemFactory and MockDownloadManagerDelegate,
// then create a DownloadManager that points
// at all of those.
- virtual void SetUp() {
+ void SetUp() override {
DCHECK(!download_manager_);
mock_download_item_factory_ = (new MockDownloadItemFactory())->AsWeakPtr();
@@ -476,7 +477,7 @@ class DownloadManagerTest : public testing::Test {
download_manager_->SetDelegate(mock_download_manager_delegate_.get());
}
- virtual void TearDown() {
+ void TearDown() override {
while (MockDownloadItemImpl*
item = mock_download_item_factory_->PopItem()) {
EXPECT_CALL(*item, GetState())
diff --git a/chromium/content/browser/download/download_net_log_parameters.cc b/chromium/content/browser/download/download_net_log_parameters.cc
index 45321362273..36e7e1e2210 100644
--- a/chromium/content/browser/download/download_net_log_parameters.cc
+++ b/chromium/content/browser/download/download_net_log_parameters.cc
@@ -34,10 +34,9 @@ static const char* download_danger_names[] = {
"POTENTIALLY_UNWANTED"
};
-COMPILE_ASSERT(ARRAYSIZE_UNSAFE(download_type_names) == SRC_SAVE_PAGE_AS + 1,
+COMPILE_ASSERT(arraysize(download_type_names) == SRC_SAVE_PAGE_AS + 1,
download_type_enum_has_changed);
-COMPILE_ASSERT(ARRAYSIZE_UNSAFE(download_danger_names) ==
- DOWNLOAD_DANGER_TYPE_MAX,
+COMPILE_ASSERT(arraysize(download_danger_names) == DOWNLOAD_DANGER_TYPE_MAX,
download_danger_enum_has_changed);
} // namespace
diff --git a/chromium/content/browser/download/download_request_handle.h b/chromium/content/browser/download/download_request_handle.h
index de1d8ae83d1..76affae249e 100644
--- a/chromium/content/browser/download/download_request_handle.h
+++ b/chromium/content/browser/download/download_request_handle.h
@@ -45,7 +45,7 @@ class CONTENT_EXPORT DownloadRequestHandleInterface {
class CONTENT_EXPORT DownloadRequestHandle
: public DownloadRequestHandleInterface {
public:
- virtual ~DownloadRequestHandle();
+ ~DownloadRequestHandle() override;
// Create a null DownloadRequestHandle: getters will return null, and
// all actions are no-ops.
@@ -63,12 +63,12 @@ class CONTENT_EXPORT DownloadRequestHandle
int request_id);
// Implement DownloadRequestHandleInterface interface.
- virtual WebContents* GetWebContents() const OVERRIDE;
- virtual DownloadManager* GetDownloadManager() const OVERRIDE;
- virtual void PauseRequest() const OVERRIDE;
- virtual void ResumeRequest() const OVERRIDE;
- virtual void CancelRequest() const OVERRIDE;
- virtual std::string DebugString() const OVERRIDE;
+ WebContents* GetWebContents() const override;
+ DownloadManager* GetDownloadManager() const override;
+ void PauseRequest() const override;
+ void ResumeRequest() const override;
+ void CancelRequest() const override;
+ std::string DebugString() const override;
private:
base::WeakPtr<DownloadResourceHandler> handler_;
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index 0a19163c9c3..f2fb2a5b267 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -141,12 +141,9 @@ bool DownloadResourceHandler::OnUploadProgress(uint64 position,
}
bool DownloadResourceHandler::OnRequestRedirected(
- const GURL& url,
+ const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) {
- // We treat a download as a main frame load, and thus update the policy URL
- // on redirects.
- request()->set_first_party_for_cookies(url);
return true;
}
@@ -383,7 +380,10 @@ void DownloadResourceHandler::OnResponseCompleted(
// to a user action.
// TODO(ahendrickson) -- Find a better set of codes to use here, as
// CANCELED/ERR_ABORTED can occur for reasons other than user cancel.
- reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
+ if (net::IsCertStatusError(request()->ssl_info().cert_status))
+ reason = DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM;
+ else
+ reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
}
if (status.is_success() &&
@@ -414,6 +414,10 @@ void DownloadResourceHandler::OnResponseCompleted(
// If we haven't received data when we get this error, we won't.
reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
break;
+ case net::HTTP_UNAUTHORIZED:
+ // Server didn't authorize this request.
+ reason = DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
+ break;
default: // All other errors.
// Redirection and informational codes should have been handled earlier
// in the stack.
diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h
index de6efef2fe6..89587831496 100644
--- a/chromium/content/browser/download/download_resource_handler.h
+++ b/chromium/content/browser/download/download_resource_handler.h
@@ -9,7 +9,6 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
-#include "base/timer/timer.h"
#include "content/browser/loader/resource_handler.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_manager.h"
@@ -46,36 +45,35 @@ class CONTENT_EXPORT DownloadResourceHandler
const DownloadUrlParameters::OnStartedCallback& started_cb,
scoped_ptr<DownloadSaveInfo> save_info);
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
// Send the download creation information to the download thread.
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
// Pass-through implementation.
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnWillStart(const GURL& url, bool* defer) override;
// Pass-through implementation.
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
// Create a new buffer, which will be handed to the download thread for file
// writing and deletion.
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
// N/A to this flavor of DownloadHandler.
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ void OnDataDownloaded(int bytes_downloaded) override;
void PauseRequest();
void ResumeRequest();
@@ -86,7 +84,7 @@ class CONTENT_EXPORT DownloadResourceHandler
std::string DebugString() const;
private:
- virtual ~DownloadResourceHandler();
+ ~DownloadResourceHandler() override;
// Arrange for started_cb_ to be called on the UI thread with the
// below values, nulling out started_cb_. Should only be called
diff --git a/chromium/content/browser/download/download_stats.cc b/chromium/content/browser/download/download_stats.cc
index 66716cac415..d88eef2c4e2 100644
--- a/chromium/content/browser/download/download_stats.cc
+++ b/chromium/content/browser/download/download_stats.cc
@@ -611,6 +611,18 @@ void RecordFileBandwidth(size_t length,
disk_write_time_ms * 100 / elapsed_time_ms);
}
+void RecordDownloadFileRenameResultAfterRetry(
+ base::TimeDelta time_since_first_failure,
+ DownloadInterruptReason interrupt_reason) {
+ if (interrupt_reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ UMA_HISTOGRAM_TIMES("Download.TimeToRenameSuccessAfterInitialFailure",
+ time_since_first_failure);
+ } else {
+ UMA_HISTOGRAM_TIMES("Download.TimeToRenameFailureAfterInitialFailure",
+ time_since_first_failure);
+ }
+}
+
void RecordSavePackageEvent(SavePackageEvent event) {
UMA_HISTOGRAM_ENUMERATION("Download.SavePackage",
event,
diff --git a/chromium/content/browser/download/download_stats.h b/chromium/content/browser/download/download_stats.h
index 65fad8d6b4a..3ae2612f8ea 100644
--- a/chromium/content/browser/download/download_stats.h
+++ b/chromium/content/browser/download/download_stats.h
@@ -200,6 +200,11 @@ void RecordFileBandwidth(size_t length,
base::TimeDelta disk_write_time,
base::TimeDelta elapsed_time);
+// Record the result of a download file rename.
+void RecordDownloadFileRenameResultAfterRetry(
+ base::TimeDelta time_since_first_failure,
+ DownloadInterruptReason interrupt_reason);
+
enum SavePackageEvent {
// The user has started to save a page as a package.
SAVE_PACKAGE_STARTED,
diff --git a/chromium/content/browser/download/drag_download_file.cc b/chromium/content/browser/download/drag_download_file.cc
index 29b8b5caa5c..ca68740a257 100644
--- a/chromium/content/browser/download/drag_download_file.cc
+++ b/chromium/content/browser/download/drag_download_file.cc
@@ -83,7 +83,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
}
private:
- virtual ~DragDownloadFileUI() {
+ ~DragDownloadFileUI() override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (download_item_)
download_item_->RemoveObserver(this);
@@ -103,7 +103,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
}
// DownloadItem::Observer:
- virtual void OnDownloadUpdated(DownloadItem* item) OVERRIDE {
+ void OnDownloadUpdated(DownloadItem* item) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(download_item_, item);
DownloadItem::DownloadState state = download_item_->GetState();
@@ -121,7 +121,7 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
// Ignore other states.
}
- virtual void OnDownloadDestroyed(DownloadItem* item) OVERRIDE {
+ void OnDownloadDestroyed(DownloadItem* item) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK_EQ(download_item_, item);
if (!on_completed_.is_null()) {
diff --git a/chromium/content/browser/download/drag_download_file.h b/chromium/content/browser/download/drag_download_file.h
index 62e4ec2aa28..825f73668aa 100644
--- a/chromium/content/browser/download/drag_download_file.h
+++ b/chromium/content/browser/download/drag_download_file.h
@@ -42,15 +42,15 @@ class CONTENT_EXPORT DragDownloadFile : public ui::DownloadFileProvider {
WebContents* web_contents);
// DownloadFileProvider methods.
- virtual void Start(ui::DownloadFileObserver* observer) OVERRIDE;
- virtual bool Wait() OVERRIDE;
- virtual void Stop() OVERRIDE;
+ void Start(ui::DownloadFileObserver* observer) override;
+ bool Wait() override;
+ void Stop() override;
private:
class DragDownloadFileUI;
enum State {INITIALIZED, STARTED, SUCCESS, FAILURE};
- virtual ~DragDownloadFile();
+ ~DragDownloadFile() override;
void DownloadCompleted(bool is_successful);
void CheckThread();
diff --git a/chromium/content/browser/download/drag_download_file_browsertest.cc b/chromium/content/browser/download/drag_download_file_browsertest.cc
index 136fac3cf32..0b1de7d6fcd 100644
--- a/chromium/content/browser/download/drag_download_file_browsertest.cc
+++ b/chromium/content/browser/download/drag_download_file_browsertest.cc
@@ -4,6 +4,7 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
#include "content/browser/download/download_file_factory.h"
#include "content/browser/download/download_file_impl.h"
#include "content/browser/download/download_item_impl.h"
@@ -21,8 +22,8 @@
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
-#include "content/test/net/url_request_mock_http_job.h"
#include "content/test/net/url_request_slow_download_job.h"
+#include "net/test/url_request/url_request_mock_http_job.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -48,7 +49,7 @@ class MockDownloadFileObserver : public ui::DownloadFileObserver {
class DragDownloadFileTest : public ContentBrowserTest {
public:
DragDownloadFileTest() {}
- virtual ~DragDownloadFileTest() {}
+ ~DragDownloadFileTest() override {}
void Succeed() {
BrowserThread::PostTask(BrowserThread::UI,
@@ -61,7 +62,7 @@ class DragDownloadFileTest : public ContentBrowserTest {
}
protected:
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
ShellDownloadManagerDelegate* delegate =
static_cast<ShellDownloadManagerDelegate*>(
@@ -73,8 +74,12 @@ class DragDownloadFileTest : public ContentBrowserTest {
void SetUpServer() {
base::FilePath mock_base(GetTestFilePath("download", ""));
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestMockHTTPJob::AddUrlHandler, mock_base));
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &net::URLRequestMockHTTPJob::AddUrlHandler,
+ mock_base,
+ make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
}
const base::FilePath& downloads_directory() const {
@@ -90,8 +95,8 @@ class DragDownloadFileTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_NetError) {
base::FilePath name(downloads_directory().AppendASCII(
"DragDownloadFileTest_NetError.txt"));
- GURL url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(FILE_PATH_LITERAL(
- "download-test.lib"))));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath(FILE_PATH_LITERAL("download-test.lib"))));
Referrer referrer;
std::string referrer_encoding;
scoped_refptr<DragDownloadFile> file(
@@ -110,8 +115,8 @@ IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_NetError) {
IN_PROC_BROWSER_TEST_F(DragDownloadFileTest, DragDownloadFileTest_Complete) {
base::FilePath name(downloads_directory().AppendASCII(
"DragDownloadFileTest_Complete.txt"));
- GURL url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(FILE_PATH_LITERAL(
- "download-test.lib"))));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath(FILE_PATH_LITERAL("download-test.lib"))));
Referrer referrer;
std::string referrer_encoding;
SetUpServer();
diff --git a/chromium/content/browser/download/drag_download_util.h b/chromium/content/browser/download/drag_download_util.h
index 76b4e61068c..38b516c5854 100644
--- a/chromium/content/browser/download/drag_download_util.h
+++ b/chromium/content/browser/download/drag_download_util.h
@@ -45,11 +45,11 @@ class PromiseFileFinalizer : public ui::DownloadFileObserver {
explicit PromiseFileFinalizer(DragDownloadFile* drag_file_downloader);
// DownloadFileObserver methods.
- virtual void OnDownloadCompleted(const base::FilePath& file_path) OVERRIDE;
- virtual void OnDownloadAborted() OVERRIDE;
+ void OnDownloadCompleted(const base::FilePath& file_path) override;
+ void OnDownloadAborted() override;
protected:
- virtual ~PromiseFileFinalizer();
+ ~PromiseFileFinalizer() override;
private:
void Cleanup();
diff --git a/chromium/content/browser/download/file_metadata_linux.cc b/chromium/content/browser/download/file_metadata_linux.cc
index c06d3f1a90f..1864d29a717 100644
--- a/chromium/content/browser/download/file_metadata_linux.cc
+++ b/chromium/content/browser/download/file_metadata_linux.cc
@@ -7,8 +7,8 @@
#include <sys/types.h>
#include <sys/xattr.h>
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "url/gurl.h"
diff --git a/chromium/content/browser/download/file_metadata_unittest_linux.cc b/chromium/content/browser/download/file_metadata_unittest_linux.cc
index 96db2646470..ab7eb3c8044 100644
--- a/chromium/content/browser/download/file_metadata_unittest_linux.cc
+++ b/chromium/content/browser/download/file_metadata_unittest_linux.cc
@@ -10,8 +10,8 @@
#include <sstream>
#include <string>
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
@@ -50,7 +50,7 @@ class FileMetadataLinuxTest : public testing::Test {
}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &test_file_));
int result = setxattr(test_file_.value().c_str(),
diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc
index 283e53ac1e0..fbe9a1f6db9 100644
--- a/chromium/content/browser/download/mhtml_generation_browsertest.cc
+++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "content/public/browser/web_contents.h"
@@ -28,7 +28,7 @@ class MHTMLGenerationTest : public ContentBrowserTest {
}
protected:
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ContentBrowserTest::SetUp();
}
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index db4ba30533f..d02d509996a 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -19,7 +19,7 @@ namespace content {
class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
public:
Job();
- virtual ~Job();
+ ~Job() override;
void SetWebContents(WebContents* web_contents);
@@ -33,12 +33,10 @@ class MHTMLGenerationManager::Job : public RenderProcessHostObserver {
void set_callback(GenerateMHTMLCallback callback) { callback_ = callback; }
// RenderProcessHostObserver:
- virtual void RenderProcessExited(RenderProcessHost* host,
- base::ProcessHandle handle,
- base::TerminationStatus status,
- int exit_code) OVERRIDE;
- virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
-
+ void RenderProcessExited(RenderProcessHost* host,
+ base::TerminationStatus status,
+ int exit_code) override;
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override;
private:
// The handle to the file the MHTML is saved to for the browser process.
@@ -76,7 +74,6 @@ void MHTMLGenerationManager::Job::SetWebContents(WebContents* web_contents) {
void MHTMLGenerationManager::Job::RenderProcessExited(
RenderProcessHost* host,
- base::ProcessHandle handle,
base::TerminationStatus status,
int exit_code) {
MHTMLGenerationManager::GetInstance()->RenderProcessExited(this);
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index 80ab95eefd0..e9c03f484ff 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -7,7 +7,7 @@
#include "content/browser/download/save_file_manager.h"
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
diff --git a/chromium/content/browser/download/save_file_resource_handler.cc b/chromium/content/browser/download/save_file_resource_handler.cc
index e1fc32b7fc4..17c29ed6593 100644
--- a/chromium/content/browser/download/save_file_resource_handler.cc
+++ b/chromium/content/browser/download/save_file_resource_handler.cc
@@ -11,6 +11,7 @@
#include "content/browser/download/save_file_manager.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
+#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_status.h"
namespace content {
@@ -37,10 +38,10 @@ bool SaveFileResourceHandler::OnUploadProgress(uint64 position, uint64 size) {
}
bool SaveFileResourceHandler::OnRequestRedirected(
- const GURL& url,
+ const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) {
- final_url_ = url;
+ final_url_ = redirect_info.new_url;
return true;
}
diff --git a/chromium/content/browser/download/save_file_resource_handler.h b/chromium/content/browser/download/save_file_resource_handler.h
index 5adbc5c229a..b7425b49b01 100644
--- a/chromium/content/browser/download/save_file_resource_handler.h
+++ b/chromium/content/browser/download/save_file_resource_handler.h
@@ -26,42 +26,41 @@ class SaveFileResourceHandler : public ResourceHandler {
int render_view_id,
const GURL& url,
SaveFileManager* manager);
- virtual ~SaveFileResourceHandler();
+ ~SaveFileResourceHandler() override;
// ResourceHandler Implementation:
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
// Saves the redirected URL to final_url_, we need to use the original
// URL to match original request.
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
// Sends the download creation information to the download thread.
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
// Pass-through implementation.
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnWillStart(const GURL& url, bool* defer) override;
// Pass-through implementation.
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
// Creates a new buffer, which will be handed to the download thread for file
// writing and deletion.
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
// Passes the buffer to the download file writer.
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
// N/A to this flavor of SaveFileResourceHandler.
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ void OnDataDownloaded(int bytes_downloaded) override;
// If the content-length header is not present (or contains something other
// than numbers), StringToInt64 returns 0, which indicates 'unknown size' and
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 90ab2a5056d..486cb1057d1 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -7,8 +7,8 @@
#include <algorithm>
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/i18n/file_util_icu.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
@@ -113,16 +113,14 @@ class SavePackageRequestHandle : public DownloadRequestHandleInterface {
: save_package_(save_package) {}
// DownloadRequestHandleInterface
- virtual WebContents* GetWebContents() const OVERRIDE {
+ WebContents* GetWebContents() const override {
return save_package_.get() ? save_package_->web_contents() : NULL;
}
- virtual DownloadManager* GetDownloadManager() const OVERRIDE {
- return NULL;
- }
- virtual void PauseRequest() const OVERRIDE {}
- virtual void ResumeRequest() const OVERRIDE {}
- virtual void CancelRequest() const OVERRIDE {}
- virtual std::string DebugString() const OVERRIDE {
+ DownloadManager* GetDownloadManager() const override { return NULL; }
+ void PauseRequest() const override {}
+ void ResumeRequest() const override {}
+ void CancelRequest() const override {}
+ std::string DebugString() const override {
return "SavePackage DownloadRequestHandle";
}
@@ -133,11 +131,7 @@ class SavePackageRequestHandle : public DownloadRequestHandleInterface {
} // namespace
const base::FilePath::CharType SavePackage::kDefaultHtmlExtension[] =
-#if defined(OS_WIN)
- FILE_PATH_LITERAL("htm");
-#else
FILE_PATH_LITERAL("html");
-#endif
SavePackage::SavePackage(WebContents* web_contents,
SavePageType save_type,
@@ -471,7 +465,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
file_path.RemoveExtension().BaseName().value();
base::FilePath::StringType file_name_ext = file_path.Extension();
- // If it is HTML resource, use ".htm{l,}" as its extension.
+ // If it is HTML resource, use ".html" as its extension.
if (need_html_ext) {
file_name_ext = FILE_PATH_LITERAL(".");
file_name_ext.append(kDefaultHtmlExtension);
@@ -1248,7 +1242,7 @@ base::FilePath SavePackage::GetSuggestedNameForSaveAs(
name_with_proper_ext = EnsureHtmlExtension(name_with_proper_ext);
base::FilePath::StringType file_name = name_with_proper_ext.value();
- file_util::ReplaceIllegalCharactersInPath(&file_name, ' ');
+ base::i18n::ReplaceIllegalCharactersInPath(&file_name, ' ');
return base::FilePath(file_name);
}
@@ -1301,17 +1295,13 @@ const base::FilePath::CharType* SavePackage::ExtensionForMimeType(
#elif defined(OS_WIN)
base::FilePath::StringType mime_type(base::UTF8ToWide(contents_mime_type));
#endif // OS_WIN
- for (uint32 i = 0; i < ARRAYSIZE_UNSAFE(extensions); ++i) {
+ for (uint32 i = 0; i < arraysize(extensions); ++i) {
if (mime_type == extensions[i].mime_type)
return extensions[i].suggested_extension;
}
return FILE_PATH_LITERAL("");
}
-WebContents* SavePackage::web_contents() const {
- return WebContentsObserver::web_contents();
-}
-
void SavePackage::GetSaveInfo() {
// Can't use web_contents_ in the file thread, so get the data that we need
// before calling to it.
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index 1ab429e16b9..3507b1760b4 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -117,7 +117,6 @@ class CONTENT_EXPORT SavePackage
SavePageType save_type() const { return save_type_; }
int contents_id() const { return contents_id_; }
int id() const { return unique_id_; }
- WebContents* web_contents() const;
void GetSaveInfo();
@@ -136,7 +135,7 @@ class CONTENT_EXPORT SavePackage
const base::FilePath& file_full_path,
const base::FilePath& directory_full_path);
- virtual ~SavePackage();
+ ~SavePackage() override;
// Notes from Init() above applies here as well.
void InternalInit();
@@ -147,10 +146,10 @@ class CONTENT_EXPORT SavePackage
void DoSavingProcess();
// WebContentsObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// DownloadItem::Observer implementation.
- virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE;
+ void OnDownloadDestroyed(DownloadItem* download) override;
// Update the download history of this item upon completion.
void FinalizeDownloadEntry();
diff --git a/chromium/content/browser/download/save_package_browsertest.cc b/chromium/content/browser/download/save_package_browsertest.cc
index 2c7a652dd0d..5b3bc173634 100644
--- a/chromium/content/browser/download/save_package_browsertest.cc
+++ b/chromium/content/browser/download/save_package_browsertest.cc
@@ -14,7 +14,7 @@ const char kTestFile[] = "files/simple_page.html";
class SavePackageBrowserTest : public ContentBrowserTest {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
ContentBrowserTest::SetUp();
}
diff --git a/chromium/content/browser/download/save_package_unittest.cc b/chromium/content/browser/download/save_package_unittest.cc
index b0e38c0f18d..c0dcbf0a7eb 100644
--- a/chromium/content/browser/download/save_package_unittest.cc
+++ b/chromium/content/browser/download/save_package_unittest.cc
@@ -6,25 +6,23 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/download/save_package.h"
-#include "content/test/net/url_request_mock_http_job.h"
+#include "content/public/common/url_constants.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
+#include "net/test/url_request/url_request_mock_http_job.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
#define FPL FILE_PATH_LITERAL
+#define HTML_EXTENSION ".html"
#if defined(OS_WIN)
-#define HTML_EXTENSION ".htm"
-// This second define is needed because MSVC is broken.
-#define FPL_HTML_EXTENSION L".htm"
+#define FPL_HTML_EXTENSION L".html"
#else
-#define HTML_EXTENSION ".html"
#define FPL_HTML_EXTENSION ".html"
#endif
@@ -95,7 +93,7 @@ class SavePackageTest : public RenderViewHostImplTestHarness {
}
protected:
- virtual void SetUp() {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
// Do the initialization in SetUp so contents() is initialized by
@@ -176,7 +174,7 @@ static const struct {
};
TEST_F(SavePackageTest, TestSuccessfullyGenerateSavePackageFilename) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGeneratedFiles); ++i) {
+ for (size_t i = 0; i < arraysize(kGeneratedFiles); ++i) {
base::FilePath::StringType file_name;
bool ok = GetGeneratedFilename(true,
kGeneratedFiles[i].disposition,
@@ -189,7 +187,7 @@ TEST_F(SavePackageTest, TestSuccessfullyGenerateSavePackageFilename) {
}
TEST_F(SavePackageTest, TestUnSuccessfullyGenerateSavePackageFilename) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGeneratedFiles); ++i) {
+ for (size_t i = 0; i < arraysize(kGeneratedFiles); ++i) {
base::FilePath::StringType file_name;
bool ok = GetGeneratedFilename(false,
kGeneratedFiles[i].disposition,
@@ -244,7 +242,7 @@ TEST_F(SavePackageTest, MAYBE_TestLongSafePureFilename) {
const base::FilePath::StringType ext(FPL_HTML_EXTENSION);
base::FilePath::StringType filename =
#if defined(OS_WIN)
- base::ASCIIToWide(long_file_name);
+ base::ASCIIToUTF16(long_file_name);
#else
long_file_name;
#endif
@@ -282,7 +280,7 @@ static const struct {
#define MAYBE_TestEnsureHtmlExtension TestEnsureHtmlExtension
#endif
TEST_F(SavePackageTest, MAYBE_TestEnsureHtmlExtension) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExtensionTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kExtensionTestCases); ++i) {
base::FilePath original = base::FilePath(kExtensionTestCases[i].page_title);
base::FilePath expected =
base::FilePath(kExtensionTestCases[i].expected_name);
@@ -327,7 +325,7 @@ TEST_F(SavePackageTest, MAYBE_TestEnsureMimeExtension) {
{ FPL("filename.abc"), FPL("filename.abc"), "unknown/unknown" },
{ FPL("filename"), FPL("filename"), "unknown/unknown" },
};
- for (uint32 i = 0; i < ARRAYSIZE_UNSAFE(kExtensionTests); ++i) {
+ for (uint32 i = 0; i < arraysize(kExtensionTests); ++i) {
base::FilePath original = base::FilePath(kExtensionTests[i].page_title);
base::FilePath expected = base::FilePath(kExtensionTests[i].expected_name);
std::string mime_type(kExtensionTests[i].contents_mime_type);
@@ -416,8 +414,8 @@ static const base::FilePath::CharType* kTestDir =
// GetUrlToBeSaved method should return correct url to be saved.
TEST_F(SavePackageTest, TestGetUrlToBeSaved) {
base::FilePath file_name(FILE_PATH_LITERAL("a.htm"));
- GURL url = URLRequestMockHTTPJob::GetMockUrl(
- base::FilePath(kTestDir).Append(file_name));
+ GURL url = net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath(kTestDir).Append(file_name));
NavigateAndCommit(url);
EXPECT_EQ(url, GetUrlToBeSaved());
}
@@ -428,10 +426,12 @@ TEST_F(SavePackageTest, TestGetUrlToBeSaved) {
// when user types view-source:http://www.google.com
TEST_F(SavePackageTest, TestGetUrlToBeSavedViewSource) {
base::FilePath file_name(FILE_PATH_LITERAL("a.htm"));
- GURL view_source_url = URLRequestMockHTTPJob::GetMockViewSourceUrl(
- base::FilePath(kTestDir).Append(file_name));
- GURL actual_url = URLRequestMockHTTPJob::GetMockUrl(
- base::FilePath(kTestDir).Append(file_name));
+ GURL mock_url = net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath(kTestDir).Append(file_name));
+ GURL view_source_url =
+ GURL(kViewSourceScheme + std::string(":") + mock_url.spec());
+ GURL actual_url = net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath(kTestDir).Append(file_name));
NavigateAndCommit(view_source_url);
EXPECT_EQ(actual_url, GetUrlToBeSaved());
EXPECT_EQ(view_source_url, contents()->GetLastCommittedURL());
diff --git a/chromium/content/browser/file_descriptor_info_impl.cc b/chromium/content/browser/file_descriptor_info_impl.cc
new file mode 100644
index 00000000000..c1f055bc76d
--- /dev/null
+++ b/chromium/content/browser/file_descriptor_info_impl.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 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 "content/browser/file_descriptor_info_impl.h"
+
+namespace content {
+
+// static
+scoped_ptr<FileDescriptorInfo> FileDescriptorInfoImpl::Create() {
+ return scoped_ptr<FileDescriptorInfo>(new FileDescriptorInfoImpl());
+}
+
+FileDescriptorInfoImpl::FileDescriptorInfoImpl() {
+}
+
+FileDescriptorInfoImpl::~FileDescriptorInfoImpl() {
+}
+
+void FileDescriptorInfoImpl::Share(int id, base::PlatformFile fd) {
+ AddToMapping(id, fd);
+}
+
+void FileDescriptorInfoImpl::Transfer(int id, base::ScopedFD fd) {
+ AddToMapping(id, fd.get());
+ owned_descriptors_.push_back(new base::ScopedFD(fd.Pass()));
+}
+
+base::PlatformFile FileDescriptorInfoImpl::GetFDAt(size_t i) const {
+ return mapping_[i].first;
+}
+
+int FileDescriptorInfoImpl::GetIDAt(size_t i) const {
+ return mapping_[i].second;
+}
+
+size_t FileDescriptorInfoImpl::GetMappingSize() const {
+ return mapping_.size();
+}
+
+bool FileDescriptorInfoImpl::HasID(int id) const {
+ for (unsigned i = 0; i < mapping_.size(); ++i) {
+ if (mapping_[i].second == id)
+ return true;
+ }
+
+ return false;
+}
+
+void FileDescriptorInfoImpl::AddToMapping(int id, base::PlatformFile fd) {
+ DCHECK(!HasID(id));
+ mapping_.push_back(std::make_pair(fd, id));
+}
+
+const base::FileHandleMappingVector& FileDescriptorInfoImpl::GetMapping()
+ const {
+ return mapping_;
+}
+
+base::FileHandleMappingVector
+FileDescriptorInfoImpl::GetMappingWithIDAdjustment(int delta) const {
+ base::FileHandleMappingVector result = mapping_;
+ // Adding delta to each ID.
+ for (unsigned i = 0; i < mapping_.size(); ++i)
+ result[i].second += delta;
+ return result;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/file_descriptor_info_impl.h b/chromium/content/browser/file_descriptor_info_impl.h
new file mode 100644
index 00000000000..78d746e22d4
--- /dev/null
+++ b/chromium/content/browser/file_descriptor_info_impl.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2012 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 CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_IMPL_H_
+#define CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/file_descriptor_info.h"
+
+namespace content {
+
+class FileDescriptorInfoImpl : public FileDescriptorInfo {
+ public:
+ CONTENT_EXPORT static scoped_ptr<FileDescriptorInfo> Create();
+
+ ~FileDescriptorInfoImpl() override;
+ void Share(int id, base::PlatformFile fd) override;
+ void Transfer(int id, base::ScopedFD fd) override;
+ const base::FileHandleMappingVector& GetMapping() const override;
+ base::FileHandleMappingVector GetMappingWithIDAdjustment(
+ int delta) const override;
+ base::PlatformFile GetFDAt(size_t i) const override;
+ int GetIDAt(size_t i) const override;
+ size_t GetMappingSize() const override;
+
+ private:
+ FileDescriptorInfoImpl();
+
+ void AddToMapping(int id, base::PlatformFile fd);
+ bool HasID(int id) const;
+ base::FileHandleMappingVector mapping_;
+ ScopedVector<base::ScopedFD> owned_descriptors_;
+};
+}
+
+#endif // CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_IMPL_H_
diff --git a/chromium/content/browser/file_descriptor_info_impl_unittest.cc b/chromium/content/browser/file_descriptor_info_impl_unittest.cc
new file mode 100644
index 00000000000..9724a7cff64
--- /dev/null
+++ b/chromium/content/browser/file_descriptor_info_impl_unittest.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 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 "content/browser/file_descriptor_info_impl.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "base/basictypes.h"
+#include "base/posix/eintr_wrapper.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Get a safe file descriptor for test purposes.
+// TODO(morrita) Merge with things in file_descriptor_set_posix_unittest.cc
+int GetSafeFd() {
+ return open("/dev/null", O_RDONLY);
+}
+
+// Returns true if fd was already closed. Closes fd if not closed.
+// TODO(morrita) Merge with things in file_descriptor_set_posix_unittest.cc
+bool VerifyClosed(int fd) {
+ const int duped = dup(fd);
+ if (duped != -1) {
+ EXPECT_NE(IGNORE_EINTR(close(duped)), -1);
+ EXPECT_NE(IGNORE_EINTR(close(fd)), -1);
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+namespace content {
+
+typedef testing::Test FileDescriptorInfoTest;
+
+TEST_F(FileDescriptorInfoTest, Transfer) {
+ int testingId = 42;
+ scoped_ptr<FileDescriptorInfo> target(FileDescriptorInfoImpl::Create());
+ base::ScopedFD fd(GetSafeFd());
+
+ int raw_fd = fd.get();
+ target->Transfer(testingId, fd.Pass());
+ ASSERT_EQ(1U, target->GetMappingSize());
+ ASSERT_EQ(target->GetFDAt(0), raw_fd);
+ ASSERT_EQ(target->GetIDAt(0), testingId);
+
+ target.reset();
+
+ ASSERT_TRUE(VerifyClosed(raw_fd));
+}
+
+TEST_F(FileDescriptorInfoTest, Share) {
+ int testingId = 42;
+ scoped_ptr<FileDescriptorInfo> target(FileDescriptorInfoImpl::Create());
+ base::ScopedFD fd(GetSafeFd());
+
+ int raw_fd = fd.get();
+ target->Share(testingId, fd.get());
+ ASSERT_EQ(1U, target->GetMappingSize());
+ ASSERT_EQ(target->GetFDAt(0), raw_fd);
+ ASSERT_EQ(target->GetIDAt(0), testingId);
+
+ target.reset();
+
+ ASSERT_TRUE(!VerifyClosed(fd.release()));
+}
+
+TEST_F(FileDescriptorInfoTest, GetMappingWithIDAdjustment) {
+ int testingId1 = 42;
+ int testingId2 = 43;
+ scoped_ptr<FileDescriptorInfo> target(FileDescriptorInfoImpl::Create());
+
+ target->Transfer(testingId1, base::ScopedFD(GetSafeFd()));
+ target->Transfer(testingId2, base::ScopedFD(GetSafeFd()));
+
+ base::FileHandleMappingVector mapping =
+ target->GetMappingWithIDAdjustment(100);
+ ASSERT_EQ(mapping[0].second, 142);
+ ASSERT_EQ(mapping[1].second, 143);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/fileapi/OWNERS b/chromium/content/browser/fileapi/OWNERS
index f7cc33cc7c2..43601cc9435 100644
--- a/chromium/content/browser/fileapi/OWNERS
+++ b/chromium/content/browser/fileapi/OWNERS
@@ -1,4 +1,5 @@
-ericu@chromium.org
kinuko@chromium.org
michaeln@chromium.org
jianli@chromium.org
+tzik@chromium.org
+nhiroki@chromium.org
diff --git a/chromium/content/browser/fileapi/blob_storage_context_unittest.cc b/chromium/content/browser/fileapi/blob_storage_context_unittest.cc
index 823679e585c..6ac1832894c 100644
--- a/chromium/content/browser/fileapi/blob_storage_context_unittest.cc
+++ b/chromium/content/browser/fileapi/blob_storage_context_unittest.cc
@@ -9,11 +9,11 @@
#include "base/run_loop.h"
#include "base/time/time.h"
#include "content/browser/fileapi/blob_storage_host.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-using webkit_blob::BlobDataHandle;
+using storage::BlobDataHandle;
namespace content {
diff --git a/chromium/content/browser/fileapi/blob_storage_host.cc b/chromium/content/browser/fileapi/blob_storage_host.cc
index cc51dbb37a7..87e675ce5d1 100644
--- a/chromium/content/browser/fileapi/blob_storage_host.cc
+++ b/chromium/content/browser/fileapi/blob_storage_host.cc
@@ -6,12 +6,12 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-using webkit_blob::BlobStorageContext;
-using webkit_blob::BlobData;
+using storage::BlobStorageContext;
+using storage::BlobData;
namespace content {
diff --git a/chromium/content/browser/fileapi/blob_storage_host.h b/chromium/content/browser/fileapi/blob_storage_host.h
index 5d10d204dce..3544f398b7d 100644
--- a/chromium/content/browser/fileapi/blob_storage_host.h
+++ b/chromium/content/browser/fileapi/blob_storage_host.h
@@ -12,18 +12,18 @@
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
-#include "webkit/common/blob/blob_data.h"
+#include "storage/common/blob/blob_data.h"
class GURL;
-namespace webkit_blob {
+namespace storage {
class BlobDataHandle;
class BlobStorageHost;
class BlobStorageContext;
}
-using webkit_blob::BlobStorageContext;
-using webkit_blob::BlobData;
+using storage::BlobStorageContext;
+using storage::BlobData;
namespace content {
diff --git a/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc b/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
index 5ce43121433..79824772be6 100644
--- a/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
@@ -4,8 +4,8 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -22,15 +22,15 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory_impl.h"
+#include "storage/browser/blob/blob_url_request_job.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/common/blob/blob_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/blob/blob_url_request_job.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/common/blob/blob_data.h"
-using webkit_blob::BlobData;
-using webkit_blob::BlobURLRequestJob;
+using storage::BlobData;
+using storage::BlobURLRequestJob;
namespace content {
@@ -47,8 +47,8 @@ const char kTestContentType[] = "foo/bar";
const char kTestContentDisposition[] = "attachment; filename=foo.txt";
const char kFileSystemURLOrigin[] = "http://remote";
-const fileapi::FileSystemType kFileSystemType =
- fileapi::kFileSystemTypeTemporary;
+const storage::FileSystemType kFileSystemType =
+ storage::kFileSystemTypeTemporary;
} // namespace
@@ -61,9 +61,9 @@ class BlobURLRequestJobTest : public testing::Test {
MockProtocolHandler(BlobURLRequestJobTest* test) : test_(test) {}
// net::URLRequestJobFactory::ProtocolHandler override.
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
return new BlobURLRequestJob(request,
network_delegate,
test_->blob_data_.get(),
@@ -79,7 +79,7 @@ class BlobURLRequestJobTest : public testing::Test {
: blob_data_(new BlobData()),
expected_status_code_(0) {}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
temp_file1_ = temp_dir_.path().AppendASCII("BlobFile1.dat");
@@ -103,8 +103,7 @@ class BlobURLRequestJobTest : public testing::Test {
url_request_context_.set_job_factory(&url_request_job_factory_);
}
- virtual void TearDown() {
- }
+ void TearDown() override {}
void SetUpFileSystem() {
// Prepare file system.
@@ -114,7 +113,7 @@ class BlobURLRequestJobTest : public testing::Test {
file_system_context_->OpenFileSystem(
GURL(kFileSystemURLOrigin),
kFileSystemType,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&BlobURLRequestJobTest::OnValidateFileSystem,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -140,7 +139,7 @@ class BlobURLRequestJobTest : public testing::Test {
void WriteFileSystemFile(const std::string& filename,
const char* buf, int buf_size,
base::Time* modification_time) {
- fileapi::FileSystemURL url =
+ storage::FileSystemURL url =
file_system_context_->CreateCrackedFileSystemURL(
GURL(kFileSystemURLOrigin),
kFileSystemType,
@@ -148,12 +147,12 @@ class BlobURLRequestJobTest : public testing::Test {
ASSERT_EQ(base::File::FILE_OK,
content::AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
+ file_system_context_.get(), url, buf, buf_size));
base::File::Info file_info;
ASSERT_EQ(base::File::FILE_OK,
content::AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
+ file_system_context_.get(), url, &file_info));
if (modification_time)
*modification_time = file_info.last_modified;
}
@@ -243,7 +242,7 @@ class BlobURLRequestJobTest : public testing::Test {
base::Time temp_file_system_file_modification_time2_;
base::MessageLoopForIO message_loop_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
scoped_refptr<BlobData> blob_data_;
net::URLRequestJobFactoryImpl url_request_job_factory_;
net::URLRequestContext url_request_context_;
@@ -260,7 +259,7 @@ TEST_F(BlobURLRequestJobTest, TestGetSimpleDataRequest) {
}
TEST_F(BlobURLRequestJobTest, TestGetSimpleFileRequest) {
- blob_data_->AppendFile(temp_file1_, 0, -1, base::Time());
+ blob_data_->AppendFile(temp_file1_, 0, kuint64max, base::Time());
TestSuccessNonrangeRequest(kTestFileData1, arraysize(kTestFileData1) - 1);
}
@@ -274,14 +273,14 @@ TEST_F(BlobURLRequestJobTest, TestGetLargeFileRequest) {
ASSERT_EQ(static_cast<int>(large_data.size()),
base::WriteFile(large_temp_file, large_data.data(),
large_data.size()));
- blob_data_->AppendFile(large_temp_file, 0, -1, base::Time());
+ blob_data_->AppendFile(large_temp_file, 0, kuint64max, base::Time());
TestSuccessNonrangeRequest(large_data, large_data.size());
}
TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileRequest) {
base::FilePath non_existent_file =
temp_file1_.InsertBeforeExtension(FILE_PATH_LITERAL("-na"));
- blob_data_->AppendFile(non_existent_file, 0, -1, base::Time());
+ blob_data_->AppendFile(non_existent_file, 0, kuint64max, base::Time());
TestErrorRequest(404);
}
@@ -300,7 +299,7 @@ TEST_F(BlobURLRequestJobTest, TestGetSlicedFileRequest) {
TEST_F(BlobURLRequestJobTest, TestGetSimpleFileSystemFileRequest) {
SetUpFileSystem();
- blob_data_->AppendFileSystemFile(temp_file_system_file1_, 0, -1,
+ blob_data_->AppendFileSystemFile(temp_file_system_file1_, 0, kuint64max,
base::Time());
TestSuccessNonrangeRequest(kTestFileSystemFileData1,
arraysize(kTestFileSystemFileData1) - 1);
@@ -316,7 +315,7 @@ TEST_F(BlobURLRequestJobTest, TestGetLargeFileSystemFileRequest) {
const char kFilename[] = "LargeBlob.dat";
WriteFileSystemFile(kFilename, large_data.data(), large_data.size(), NULL);
- blob_data_->AppendFileSystemFile(GetFileSystemURL(kFilename), 0, -1,
+ blob_data_->AppendFileSystemFile(GetFileSystemURL(kFilename), 0, kuint64max,
base::Time());
TestSuccessNonrangeRequest(large_data, large_data.size());
}
@@ -324,7 +323,8 @@ TEST_F(BlobURLRequestJobTest, TestGetLargeFileSystemFileRequest) {
TEST_F(BlobURLRequestJobTest, TestGetNonExistentFileSystemFileRequest) {
SetUpFileSystem();
GURL non_existent_file = GetFileSystemURL("non-existent.dat");
- blob_data_->AppendFileSystemFile(non_existent_file, 0, -1, base::Time());
+ blob_data_->AppendFileSystemFile(non_existent_file, 0, kuint64max,
+ base::Time());
TestErrorRequest(404);
}
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.cc b/chromium/content/browser/fileapi/browser_file_system_helper.cc
index d89d6cab25b..b3221612116 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.cc
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.cc
@@ -17,20 +17,20 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_permission_policy.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/file_system_options.h"
+#include "storage/browser/quota/quota_manager.h"
#include "url/url_constants.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_permission_policy.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/file_system_options.h"
-#include "webkit/browser/quota/quota_manager.h"
namespace content {
namespace {
-using fileapi::FileSystemOptions;
+using storage::FileSystemOptions;
FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
FileSystemOptions::ProfileMode profile_mode =
@@ -48,12 +48,11 @@ FileSystemOptions CreateBrowserFileSystemOptions(bool is_incognito) {
} // namespace
-scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
+scoped_refptr<storage::FileSystemContext> CreateFileSystemContext(
BrowserContext* browser_context,
const base::FilePath& profile_path,
bool is_incognito,
- quota::QuotaManagerProxy* quota_manager_proxy) {
-
+ storage::QuotaManagerProxy* quota_manager_proxy) {
base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
scoped_refptr<base::SequencedTaskRunner> file_task_runner =
pool->GetSequencedTaskRunnerWithShutdownBehavior(
@@ -61,20 +60,20 @@ scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
// Setting up additional filesystem backends.
- ScopedVector<fileapi::FileSystemBackend> additional_backends;
+ ScopedVector<storage::FileSystemBackend> additional_backends;
GetContentClient()->browser()->GetAdditionalFileSystemBackends(
browser_context,
profile_path,
&additional_backends);
// Set up the auto mount handlers for url requests.
- std::vector<fileapi::URLRequestAutoMountHandler>
+ std::vector<storage::URLRequestAutoMountHandler>
url_request_auto_mount_handlers;
GetContentClient()->browser()->GetURLRequestAutoMountHandlers(
&url_request_auto_mount_handlers);
- scoped_refptr<fileapi::FileSystemContext> file_system_context =
- new fileapi::FileSystemContext(
+ scoped_refptr<storage::FileSystemContext> file_system_context =
+ new storage::FileSystemContext(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
file_task_runner.get(),
BrowserContext::GetMountPoints(browser_context),
@@ -85,28 +84,27 @@ scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext(
profile_path,
CreateBrowserFileSystemOptions(is_incognito));
- std::vector<fileapi::FileSystemType> types;
+ std::vector<storage::FileSystemType> types;
file_system_context->GetFileSystemTypes(&types);
for (size_t i = 0; i < types.size(); ++i) {
- ChildProcessSecurityPolicyImpl::GetInstance()->
- RegisterFileSystemPermissionPolicy(
+ ChildProcessSecurityPolicyImpl::GetInstance()
+ ->RegisterFileSystemPermissionPolicy(
types[i],
- fileapi::FileSystemContext::GetPermissionPolicy(types[i]));
+ storage::FileSystemContext::GetPermissionPolicy(types[i]));
}
return file_system_context;
}
-bool FileSystemURLIsValid(
- fileapi::FileSystemContext* context,
- const fileapi::FileSystemURL& url) {
+bool FileSystemURLIsValid(storage::FileSystemContext* context,
+ const storage::FileSystemURL& url) {
if (!url.is_valid())
return false;
return context->GetFileSystemBackend(url.type()) != NULL;
}
-void SyncGetPlatformPath(fileapi::FileSystemContext* context,
+void SyncGetPlatformPath(storage::FileSystemContext* context,
int process_id,
const GURL& path,
base::FilePath* platform_path) {
@@ -114,7 +112,7 @@ void SyncGetPlatformPath(fileapi::FileSystemContext* context,
RunsTasksOnCurrentThread());
DCHECK(platform_path);
*platform_path = base::FilePath();
- fileapi::FileSystemURL url(context->CrackURL(path));
+ storage::FileSystemURL url(context->CrackURL(path));
if (!FileSystemURLIsValid(context, url))
return;
diff --git a/chromium/content/browser/fileapi/browser_file_system_helper.h b/chromium/content/browser/fileapi/browser_file_system_helper.h
index ad44ced5064..de63da54435 100644
--- a/chromium/content/browser/fileapi/browser_file_system_helper.h
+++ b/chromium/content/browser/fileapi/browser_file_system_helper.h
@@ -7,9 +7,9 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-#include "webkit/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
-namespace fileapi {
+namespace storage {
class ExternalMountPoints;
class FileSystemContext;
class FileSystemURL;
@@ -21,20 +21,19 @@ class BrowserContext;
// Helper method that returns FileSystemContext constructed for
// the browser process.
-CONTENT_EXPORT scoped_refptr<fileapi::FileSystemContext>
-CreateFileSystemContext(
- BrowserContext* browser_context,
- const base::FilePath& profile_path,
- bool is_incognito,
- quota::QuotaManagerProxy* quota_manager_proxy);
+CONTENT_EXPORT scoped_refptr<storage::FileSystemContext>
+ CreateFileSystemContext(BrowserContext* browser_context,
+ const base::FilePath& profile_path,
+ bool is_incognito,
+ storage::QuotaManagerProxy* quota_manager_proxy);
// Verifies that |url| is valid and has a registered backend in |context|.
-CONTENT_EXPORT bool FileSystemURLIsValid(fileapi::FileSystemContext* context,
- const fileapi::FileSystemURL& url);
+CONTENT_EXPORT bool FileSystemURLIsValid(storage::FileSystemContext* context,
+ const storage::FileSystemURL& url);
// Get the platform path from a file system URL. This needs to be called
// on the FILE thread.
-CONTENT_EXPORT void SyncGetPlatformPath(fileapi::FileSystemContext* context,
+CONTENT_EXPORT void SyncGetPlatformPath(storage::FileSystemContext* context,
int process_id,
const GURL& path,
base::FilePath* platform_path);
diff --git a/chromium/content/browser/fileapi/chrome_blob_storage_context.cc b/chromium/content/browser/fileapi/chrome_blob_storage_context.cc
index fce0bed9066..f085242f689 100644
--- a/chromium/content/browser/fileapi/chrome_blob_storage_context.cc
+++ b/chromium/content/browser/fileapi/chrome_blob_storage_context.cc
@@ -9,36 +9,34 @@
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
using base::UserDataAdapter;
-using webkit_blob::BlobStorageContext;
+using storage::BlobStorageContext;
namespace content {
namespace {
+const char kBlobStorageContextKeyName[] = "content_blob_storage_context";
+
class BlobHandleImpl : public BlobHandle {
public:
- BlobHandleImpl(scoped_ptr<webkit_blob::BlobDataHandle> handle)
+ explicit BlobHandleImpl(scoped_ptr<storage::BlobDataHandle> handle)
: handle_(handle.Pass()) {
}
- virtual ~BlobHandleImpl() {}
+ ~BlobHandleImpl() override {}
- virtual std::string GetUUID() OVERRIDE {
- return handle_->uuid();
- }
+ std::string GetUUID() override { return handle_->uuid(); }
private:
- scoped_ptr<webkit_blob::BlobDataHandle> handle_;
+ scoped_ptr<storage::BlobDataHandle> handle_;
};
} // namespace
-static const char* kBlobStorageContextKeyName = "content_blob_storage_context";
-
ChromeBlobStorageContext::ChromeBlobStorageContext() {}
ChromeBlobStorageContext* ChromeBlobStorageContext::GetFor(
@@ -71,11 +69,10 @@ scoped_ptr<BlobHandle> ChromeBlobStorageContext::CreateMemoryBackedBlob(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
std::string uuid(base::GenerateGUID());
- scoped_refptr<webkit_blob::BlobData> blob_data =
- new webkit_blob::BlobData(uuid);
+ scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid);
blob_data->AppendData(data, length);
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle =
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle =
context_->AddFinishedBlob(blob_data.get());
if (!blob_data_handle)
return scoped_ptr<BlobHandle>();
diff --git a/chromium/content/browser/fileapi/chrome_blob_storage_context.h b/chromium/content/browser/fileapi/chrome_blob_storage_context.h
index 1dccd99faf0..8d8a5f226b4 100644
--- a/chromium/content/browser/fileapi/chrome_blob_storage_context.h
+++ b/chromium/content/browser/fileapi/chrome_blob_storage_context.h
@@ -10,7 +10,7 @@
#include "base/sequenced_task_runner_helpers.h"
#include "content/common/content_export.h"
-namespace webkit_blob {
+namespace storage {
class BlobStorageContext;
}
@@ -37,9 +37,7 @@ class CONTENT_EXPORT ChromeBlobStorageContext
void InitializeOnIOThread();
- webkit_blob::BlobStorageContext* context() const {
- return context_.get();
- }
+ storage::BlobStorageContext* context() const { return context_.get(); }
// Returns a NULL scoped_ptr on failure.
scoped_ptr<BlobHandle> CreateMemoryBackedBlob(const char* data,
@@ -56,7 +54,7 @@ class CONTENT_EXPORT ChromeBlobStorageContext
void DeleteOnCorrectThread() const;
- scoped_ptr<webkit_blob::BlobStorageContext> context_;
+ scoped_ptr<storage::BlobStorageContext> context_;
};
struct ChromeBlobStorageContextDeleter {
diff --git a/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc b/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc
index eaff4d38f54..ea2ba898940 100644
--- a/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc
+++ b/chromium/content/browser/fileapi/copy_or_move_file_validator_unittest.cc
@@ -11,28 +11,28 @@
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_file_system_backend.h"
#include "content/public/test/test_file_system_context.h"
+#include "storage/browser/fileapi/copy_or_move_file_validator.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/common/blob/shareable_file_reference.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/common/fileapi/file_system_util.h"
using content::AsyncFileTestHelper;
-using fileapi::CopyOrMoveFileValidator;
-using fileapi::CopyOrMoveFileValidatorFactory;
-using fileapi::FileSystemURL;
+using storage::CopyOrMoveFileValidator;
+using storage::CopyOrMoveFileValidatorFactory;
+using storage::FileSystemURL;
namespace content {
namespace {
-const fileapi::FileSystemType kNoValidatorType =
- fileapi::kFileSystemTypeTemporary;
-const fileapi::FileSystemType kWithValidatorType = fileapi::kFileSystemTypeTest;
+const storage::FileSystemType kNoValidatorType =
+ storage::kFileSystemTypeTemporary;
+const storage::FileSystemType kWithValidatorType = storage::kFileSystemTypeTest;
void ExpectOk(const GURL& origin_url,
const std::string& name,
@@ -43,8 +43,8 @@ void ExpectOk(const GURL& origin_url,
class CopyOrMoveFileValidatorTestHelper {
public:
CopyOrMoveFileValidatorTestHelper(const GURL& origin,
- fileapi::FileSystemType src_type,
- fileapi::FileSystemType dest_type)
+ storage::FileSystemType src_type,
+ storage::FileSystemType dest_type)
: origin_(origin), src_type_(src_type), dest_type_(dest_type) {}
~CopyOrMoveFileValidatorTestHelper() {
@@ -59,17 +59,17 @@ class CopyOrMoveFileValidatorTestHelper {
file_system_context_ = CreateFileSystemContextForTesting(NULL, base_dir);
// Set up TestFileSystemBackend to require CopyOrMoveFileValidator.
- fileapi::FileSystemBackend* test_file_system_backend =
+ storage::FileSystemBackend* test_file_system_backend =
file_system_context_->GetFileSystemBackend(kWithValidatorType);
static_cast<TestFileSystemBackend*>(test_file_system_backend)->
set_require_copy_or_move_validator(true);
// Sets up source.
- fileapi::FileSystemBackend* src_file_system_backend =
+ storage::FileSystemBackend* src_file_system_backend =
file_system_context_->GetFileSystemBackend(src_type_);
src_file_system_backend->ResolveURL(
FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()),
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&ExpectOk));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::File::FILE_OK, CreateDirectory(SourceURL("")));
@@ -93,7 +93,7 @@ class CopyOrMoveFileValidatorTestHelper {
}
void SetMediaCopyOrMoveFileValidatorFactory(
- scoped_ptr<fileapi::CopyOrMoveFileValidatorFactory> factory) {
+ scoped_ptr<storage::CopyOrMoveFileValidatorFactory> factory) {
TestFileSystemBackend* backend = static_cast<TestFileSystemBackend*>(
file_system_context_->GetFileSystemBackend(kWithValidatorType));
backend->InitializeCopyOrMoveFileValidatorFactory(factory.Pass());
@@ -167,13 +167,13 @@ class CopyOrMoveFileValidatorTestHelper {
const GURL origin_;
- const fileapi::FileSystemType src_type_;
- const fileapi::FileSystemType dest_type_;
+ const storage::FileSystemType src_type_;
+ const storage::FileSystemType dest_type_;
std::string src_fsid_;
std::string dest_fsid_;
base::MessageLoop message_loop_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
FileSystemURL copy_src_;
FileSystemURL copy_dest_;
@@ -191,17 +191,17 @@ enum Validity {
};
class TestCopyOrMoveFileValidatorFactory
- : public fileapi::CopyOrMoveFileValidatorFactory {
+ : public storage::CopyOrMoveFileValidatorFactory {
public:
// A factory that creates validators that accept everything or nothing.
// TODO(gbillock): switch args to enum or something
explicit TestCopyOrMoveFileValidatorFactory(Validity validity)
: validity_(validity) {}
- virtual ~TestCopyOrMoveFileValidatorFactory() {}
+ ~TestCopyOrMoveFileValidatorFactory() override {}
- virtual fileapi::CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
+ storage::CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
const FileSystemURL& /*src_url*/,
- const base::FilePath& /*platform_path*/) OVERRIDE {
+ const base::FilePath& /*platform_path*/) override {
return new TestCopyOrMoveFileValidator(validity_);
}
@@ -216,18 +216,18 @@ class TestCopyOrMoveFileValidatorFactory
base::File::FILE_OK :
base::File::FILE_ERROR_SECURITY) {
}
- virtual ~TestCopyOrMoveFileValidator() {}
+ ~TestCopyOrMoveFileValidator() override {}
- virtual void StartPreWriteValidation(
- const ResultCallback& result_callback) OVERRIDE {
+ void StartPreWriteValidation(
+ const ResultCallback& result_callback) override {
// Post the result since a real validator must do work asynchronously.
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(result_callback, result_));
}
- virtual void StartPostWriteValidation(
+ void StartPostWriteValidation(
const base::FilePath& dest_platform_path,
- const ResultCallback& result_callback) OVERRIDE {
+ const ResultCallback& result_callback) override {
// Post the result since a real validator must do work asynchronously.
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(result_callback, write_result_));
diff --git a/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
index f2c00fcf9df..a50d4a054a6 100644
--- a/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ b/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -7,7 +7,7 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -18,27 +18,27 @@
#include "content/public/test/test_file_system_backend.h"
#include "content/public/test/test_file_system_context.h"
#include "content/test/fileapi_test_file_set.h"
+#include "storage/browser/blob/file_stream_reader.h"
+#include "storage/browser/fileapi/copy_or_move_file_validator.h"
+#include "storage/browser/fileapi/copy_or_move_operation_delegate.h"
+#include "storage/browser/fileapi/file_stream_writer.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/blob/file_stream_reader.h"
-#include "webkit/browser/fileapi/copy_or_move_file_validator.h"
-#include "webkit/browser/fileapi/copy_or_move_operation_delegate.h"
-#include "webkit/browser/fileapi/file_stream_writer.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/fileapi/file_system_util.h"
using content::AsyncFileTestHelper;
-using fileapi::CopyOrMoveOperationDelegate;
-using fileapi::FileStreamWriter;
-using fileapi::FileSystemOperation;
-using fileapi::FileSystemURL;
+using storage::CopyOrMoveOperationDelegate;
+using storage::FileStreamWriter;
+using storage::FileSystemOperation;
+using storage::FileSystemURL;
namespace content {
-typedef fileapi::FileSystemOperation::FileEntryList FileEntryList;
+typedef storage::FileSystemOperation::FileEntryList FileEntryList;
namespace {
@@ -48,21 +48,21 @@ void ExpectOk(const GURL& origin_url,
ASSERT_EQ(base::File::FILE_OK, error);
}
-class TestValidatorFactory : public fileapi::CopyOrMoveFileValidatorFactory {
+class TestValidatorFactory : public storage::CopyOrMoveFileValidatorFactory {
public:
// A factory that creates validators that accept everything or nothing.
TestValidatorFactory() {}
- virtual ~TestValidatorFactory() {}
+ ~TestValidatorFactory() override {}
- virtual fileapi::CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
+ storage::CopyOrMoveFileValidator* CreateCopyOrMoveFileValidator(
const FileSystemURL& /*src_url*/,
- const base::FilePath& /*platform_path*/) OVERRIDE {
+ const base::FilePath& /*platform_path*/) override {
// Move arg management to TestValidator?
return new TestValidator(true, true, std::string("2"));
}
private:
- class TestValidator : public fileapi::CopyOrMoveFileValidator {
+ class TestValidator : public storage::CopyOrMoveFileValidator {
public:
explicit TestValidator(bool pre_copy_valid,
bool post_copy_valid,
@@ -73,18 +73,18 @@ class TestValidatorFactory : public fileapi::CopyOrMoveFileValidatorFactory {
base::File::FILE_ERROR_SECURITY),
reject_string_(reject_string) {
}
- virtual ~TestValidator() {}
+ ~TestValidator() override {}
- virtual void StartPreWriteValidation(
- const ResultCallback& result_callback) OVERRIDE {
+ void StartPreWriteValidation(
+ const ResultCallback& result_callback) override {
// Post the result since a real validator must do work asynchronously.
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(result_callback, result_));
}
- virtual void StartPostWriteValidation(
+ void StartPostWriteValidation(
const base::FilePath& dest_platform_path,
- const ResultCallback& result_callback) OVERRIDE {
+ const ResultCallback& result_callback) override {
base::File::Error result = write_result_;
std::string unsafe = dest_platform_path.BaseName().AsUTF8Unsafe();
if (unsafe.find(reject_string_) != std::string::npos) {
@@ -106,14 +106,14 @@ class TestValidatorFactory : public fileapi::CopyOrMoveFileValidatorFactory {
// Records CopyProgressCallback invocations.
struct ProgressRecord {
- fileapi::FileSystemOperation::CopyProgressType type;
+ storage::FileSystemOperation::CopyProgressType type;
FileSystemURL source_url;
FileSystemURL dest_url;
int64 size;
};
void RecordProgressCallback(std::vector<ProgressRecord>* records,
- fileapi::FileSystemOperation::CopyProgressType type,
+ storage::FileSystemOperation::CopyProgressType type,
const FileSystemURL& source_url,
const FileSystemURL& dest_url,
int64 size) {
@@ -165,8 +165,8 @@ class ScopedThreadStopper {
class CopyOrMoveOperationTestHelper {
public:
CopyOrMoveOperationTestHelper(const GURL& origin,
- fileapi::FileSystemType src_type,
- fileapi::FileSystemType dest_type)
+ storage::FileSystemType src_type,
+ storage::FileSystemType dest_type)
: origin_(origin), src_type_(src_type), dest_type_(dest_type) {}
~CopyOrMoveOperationTestHelper() {
@@ -201,17 +201,17 @@ class CopyOrMoveOperationTestHelper {
CreateFileSystemContextForTesting(quota_manager_proxy_.get(), base_dir);
// Prepare the origin's root directory.
- fileapi::FileSystemBackend* backend =
+ storage::FileSystemBackend* backend =
file_system_context_->GetFileSystemBackend(src_type_);
backend->ResolveURL(
FileSystemURL::CreateForTest(origin_, src_type_, base::FilePath()),
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&ExpectOk));
backend = file_system_context_->GetFileSystemBackend(dest_type_);
- if (dest_type_ == fileapi::kFileSystemTypeTest) {
+ if (dest_type_ == storage::kFileSystemTypeTest) {
TestFileSystemBackend* test_backend =
static_cast<TestFileSystemBackend*>(backend);
- scoped_ptr<fileapi::CopyOrMoveFileValidatorFactory> factory(
+ scoped_ptr<storage::CopyOrMoveFileValidatorFactory> factory(
new TestValidatorFactory);
test_backend->set_require_copy_or_move_validator(
require_copy_or_move_validator);
@@ -220,18 +220,18 @@ class CopyOrMoveOperationTestHelper {
}
backend->ResolveURL(
FileSystemURL::CreateForTest(origin_, dest_type_, base::FilePath()),
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&ExpectOk));
base::RunLoop().RunUntilIdle();
// Grant relatively big quota initially.
quota_manager_->SetQuota(
origin_,
- fileapi::FileSystemTypeToQuotaStorageType(src_type_),
+ storage::FileSystemTypeToQuotaStorageType(src_type_),
1024 * 1024);
quota_manager_->SetQuota(
origin_,
- fileapi::FileSystemTypeToQuotaStorageType(dest_type_),
+ storage::FileSystemTypeToQuotaStorageType(dest_type_),
1024 * 1024);
}
@@ -373,23 +373,23 @@ class CopyOrMoveOperationTestHelper {
}
private:
- void GetUsageAndQuota(fileapi::FileSystemType type,
+ void GetUsageAndQuota(storage::FileSystemType type,
int64* usage,
int64* quota) {
- quota::QuotaStatusCode status = AsyncFileTestHelper::GetUsageAndQuota(
+ storage::QuotaStatusCode status = AsyncFileTestHelper::GetUsageAndQuota(
quota_manager_.get(), origin_, type, usage, quota);
- ASSERT_EQ(quota::kQuotaStatusOk, status);
+ ASSERT_EQ(storage::kQuotaStatusOk, status);
}
private:
base::ScopedTempDir base_;
const GURL origin_;
- const fileapi::FileSystemType src_type_;
- const fileapi::FileSystemType dest_type_;
+ const storage::FileSystemType src_type_;
+ const storage::FileSystemType dest_type_;
base::MessageLoopForIO message_loop_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
scoped_refptr<MockQuotaManager> quota_manager_;
@@ -398,8 +398,8 @@ class CopyOrMoveOperationTestHelper {
TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFile) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -427,8 +427,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFile) {
TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleFile) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -456,8 +456,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleFile) {
TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleDirectory) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -485,8 +485,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleDirectory) {
TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleDirectory) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -514,8 +514,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, MoveSingleDirectory) {
TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -554,8 +554,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopyDirectory) {
TEST(LocalFileSystemCopyOrMoveOperationTest, MoveDirectory) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -592,8 +592,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, MoveDirectory) {
TEST(LocalFileSystemCopyOrMoveOperationTest,
MoveDirectoryFailPostWriteValidation) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypeTest);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypeTest);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -625,8 +625,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest,
TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypeTest);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypeTest);
helper.SetUpNoValidator();
FileSystemURL src = helper.SourceURL("a");
@@ -643,8 +643,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, CopySingleFileNoValidator) {
TEST(LocalFileSystemCopyOrMoveOperationTest, ProgressCallback) {
CopyOrMoveOperationTestHelper helper(GURL("http://foo"),
- fileapi::kFileSystemTypeTemporary,
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypeTemporary,
+ storage::kFileSystemTypePersistent);
helper.SetUp();
FileSystemURL src = helper.SourceURL("a");
@@ -730,8 +730,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelper) {
scoped_refptr<base::MessageLoopProxy> task_runner =
file_thread.message_loop_proxy();
- scoped_ptr<webkit_blob::FileStreamReader> reader(
- webkit_blob::FileStreamReader::CreateForLocalFile(
+ scoped_ptr<storage::FileStreamReader> reader(
+ storage::FileStreamReader::CreateForLocalFile(
task_runner.get(), source_path, 0, base::Time()));
scoped_ptr<FileStreamWriter> writer(FileStreamWriter::CreateForLocalFile(
@@ -786,8 +786,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelperWithFlush) {
scoped_refptr<base::MessageLoopProxy> task_runner =
file_thread.message_loop_proxy();
- scoped_ptr<webkit_blob::FileStreamReader> reader(
- webkit_blob::FileStreamReader::CreateForLocalFile(
+ scoped_ptr<storage::FileStreamReader> reader(
+ storage::FileStreamReader::CreateForLocalFile(
task_runner.get(), source_path, 0, base::Time()));
scoped_ptr<FileStreamWriter> writer(FileStreamWriter::CreateForLocalFile(
@@ -837,8 +837,8 @@ TEST(LocalFileSystemCopyOrMoveOperationTest, StreamCopyHelper_Cancel) {
scoped_refptr<base::MessageLoopProxy> task_runner =
file_thread.message_loop_proxy();
- scoped_ptr<webkit_blob::FileStreamReader> reader(
- webkit_blob::FileStreamReader::CreateForLocalFile(
+ scoped_ptr<storage::FileStreamReader> reader(
+ storage::FileStreamReader::CreateForLocalFile(
task_runner.get(), source_path, 0, base::Time()));
scoped_ptr<FileStreamWriter> writer(FileStreamWriter::CreateForLocalFile(
diff --git a/chromium/content/browser/fileapi/dragged_file_util_unittest.cc b/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
index 6bd6e100253..98b2ceec421 100644
--- a/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
@@ -8,8 +8,8 @@
#include <string>
#include <vector>
-#include "base/file_util.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
@@ -18,19 +18,19 @@
#include "content/public/test/async_file_test_helper.h"
#include "content/public/test/test_file_system_context.h"
#include "content/test/fileapi_test_file_set.h"
+#include "storage/browser/fileapi/dragged_file_util.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/browser/fileapi/local_file_util.h"
+#include "storage/browser/fileapi/native_file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/dragged_file_util.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/browser/fileapi/native_file_util.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemOperationContext;
-using fileapi::FileSystemType;
-using fileapi::FileSystemURL;
+using storage::FileSystemContext;
+using storage::FileSystemOperationContext;
+using storage::FileSystemType;
+using storage::FileSystemURL;
namespace content {
@@ -97,10 +97,10 @@ class DraggedFileUtilTest : public testing::Test {
public:
DraggedFileUtilTest() {}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
ASSERT_TRUE(partition_dir_.CreateUniqueTempDir());
- file_util_.reset(new fileapi::DraggedFileUtil());
+ file_util_.reset(new storage::DraggedFileUtil());
// Register the files/directories of RegularTestCases (with random
// root paths) as dropped files.
@@ -113,13 +113,13 @@ class DraggedFileUtilTest : public testing::Test {
isolated_context()->AddReference(filesystem_id_);
}
- virtual void TearDown() {
+ void TearDown() override {
isolated_context()->RemoveReference(filesystem_id_);
}
protected:
- fileapi::IsolatedContext* isolated_context() const {
- return fileapi::IsolatedContext::GetInstance();
+ storage::IsolatedContext* isolated_context() const {
+ return storage::IsolatedContext::GetInstance();
}
const base::FilePath& root_path() const {
return data_dir_.path();
@@ -127,7 +127,7 @@ class DraggedFileUtilTest : public testing::Test {
FileSystemContext* file_system_context() const {
return file_system_context_.get();
}
- fileapi::FileSystemFileUtil* file_util() const { return file_util_.get(); }
+ storage::FileSystemFileUtil* file_util() const { return file_util_.get(); }
std::string filesystem_id() const { return filesystem_id_; }
base::FilePath GetTestCasePlatformPath(
@@ -148,14 +148,14 @@ class DraggedFileUtilTest : public testing::Test {
filesystem_id()).Append(path);
return file_system_context_->CreateCrackedFileSystemURL(
GURL("http://example.com"),
- fileapi::kFileSystemTypeIsolated,
+ storage::kFileSystemTypeIsolated,
virtual_path);
}
FileSystemURL GetOtherFileSystemURL(const base::FilePath& path) const {
return file_system_context()->CreateCrackedFileSystemURL(
GURL("http://example.com"),
- fileapi::kFileSystemTypeTemporary,
+ storage::kFileSystemTypeTemporary,
base::FilePath().AppendASCII("dest").Append(path));
}
@@ -247,9 +247,9 @@ class DraggedFileUtilTest : public testing::Test {
}
}
- scoped_ptr<fileapi::FileSystemOperationContext> GetOperationContext() {
- return make_scoped_ptr(
- new fileapi::FileSystemOperationContext(file_system_context())).Pass();
+ scoped_ptr<storage::FileSystemOperationContext> GetOperationContext() {
+ return make_scoped_ptr(new storage::FileSystemOperationContext(
+ file_system_context())).Pass();
}
@@ -257,7 +257,7 @@ class DraggedFileUtilTest : public testing::Test {
void SimulateDropFiles() {
size_t root_path_index = 0;
- fileapi::IsolatedContext::FileInfoSet toplevels;
+ storage::IsolatedContext::FileInfoSet toplevels;
for (size_t i = 0; i < kRegularFileSystemTestCaseSize; ++i) {
const FileSystemTestCaseRecord& test_case =
kRegularFileSystemTestCases[i];
@@ -286,7 +286,7 @@ class DraggedFileUtilTest : public testing::Test {
std::string filesystem_id_;
scoped_refptr<FileSystemContext> file_system_context_;
std::map<base::FilePath, base::FilePath> toplevel_root_map_;
- scoped_ptr<fileapi::DraggedFileUtil> file_util_;
+ scoped_ptr<storage::DraggedFileUtil> file_util_;
DISALLOW_COPY_AND_ASSIGN(DraggedFileUtilTest);
};
@@ -361,7 +361,7 @@ TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
<< ": " << test_case.path);
// Read entries in the directory to construct the expected results map.
- typedef std::map<base::FilePath::StringType, fileapi::DirectoryEntry>
+ typedef std::map<base::FilePath::StringType, storage::DirectoryEntry>
EntryMap;
EntryMap expected_entry_map;
@@ -372,7 +372,7 @@ TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
base::FilePath current;
while (!(current = file_enum.Next()).empty()) {
base::FileEnumerator::FileInfo file_info = file_enum.GetInfo();
- fileapi::DirectoryEntry entry;
+ storage::DirectoryEntry entry;
entry.is_directory = file_info.IsDirectory();
entry.name = current.BaseName().value();
entry.size = file_info.GetSize();
@@ -399,7 +399,7 @@ TEST_F(DraggedFileUtilTest, ReadDirectoryTest) {
EXPECT_EQ(expected_entry_map.size(), entries.size());
for (size_t i = 0; i < entries.size(); ++i) {
- const fileapi::DirectoryEntry& entry = entries[i];
+ const storage::DirectoryEntry& entry = entries[i];
EntryMap::iterator found = expected_entry_map.find(entry.name);
EXPECT_TRUE(found != expected_entry_map.end());
EXPECT_EQ(found->second.name, entry.name);
diff --git a/chromium/content/browser/fileapi/external_mount_points_unittest.cc b/chromium/content/browser/fileapi/external_mount_points_unittest.cc
index fa0d1f5bbc2..447eb7348a7 100644
--- a/chromium/content/browser/fileapi/external_mount_points_unittest.cc
+++ b/chromium/content/browser/fileapi/external_mount_points_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/external_mount_points.h"
#include <string>
#include "base/files/file_path.h"
+#include "storage/browser/fileapi/file_system_url.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_url.h"
#define FPL FILE_PATH_LITERAL
@@ -18,13 +18,13 @@
#define DRIVE
#endif
-using fileapi::FileSystemURL;
+using storage::FileSystemURL;
namespace content {
TEST(ExternalMountPointsTest, AddMountPoint) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points(
- fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<storage::ExternalMountPoints> mount_points(
+ storage::ExternalMountPoints::CreateRefCounted());
struct TestCase {
// The mount point's name.
@@ -106,19 +106,19 @@ TEST(ExternalMountPointsTest, AddMountPoint) {
};
// Test adding mount points.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
- EXPECT_EQ(kTestCases[i].success,
- mount_points->RegisterFileSystem(
- kTestCases[i].name,
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
- base::FilePath(kTestCases[i].path)))
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
+ EXPECT_EQ(
+ kTestCases[i].success,
+ mount_points->RegisterFileSystem(kTestCases[i].name,
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
+ base::FilePath(kTestCases[i].path)))
<< "Adding mount point: " << kTestCases[i].name << " with path "
<< kTestCases[i].path;
}
// Test that final mount point presence state is as expected.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
base::FilePath found_path;
EXPECT_EQ(kTestCases[i].registered_path != NULL,
mount_points->GetRegisteredPath(kTestCases[i].name, &found_path))
@@ -132,35 +132,35 @@ TEST(ExternalMountPointsTest, AddMountPoint) {
}
TEST(ExternalMountPointsTest, GetVirtualPath) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points(
- fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<storage::ExternalMountPoints> mount_points(
+ storage::ExternalMountPoints::CreateRefCounted());
mount_points->RegisterFileSystem("c",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
// Note that "/a/b/c" < "/a/b/c(1)" < "/a/b/c/".
mount_points->RegisterFileSystem("c(1)",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
mount_points->RegisterFileSystem("x",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/z/y/x")));
mount_points->RegisterFileSystem("o",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/m/n/o")));
// A mount point whose name does not match its path base name.
mount_points->RegisterFileSystem("mount",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root/foo")));
// A mount point with an empty path.
mount_points->RegisterFileSystem("empty_path",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath());
struct TestCase {
@@ -214,7 +214,7 @@ TEST(ExternalMountPointsTest, GetVirtualPath) {
#endif
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
// Initialize virtual path with a value.
base::FilePath virtual_path(DRIVE FPL("/mount"));
base::FilePath local_path(kTestCases[i].local_path);
@@ -234,57 +234,57 @@ TEST(ExternalMountPointsTest, GetVirtualPath) {
}
TEST(ExternalMountPointsTest, HandlesFileSystemMountType) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points(
- fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<storage::ExternalMountPoints> mount_points(
+ storage::ExternalMountPoints::CreateRefCounted());
const GURL test_origin("http://chromium.org");
const base::FilePath test_path(FPL("/mount"));
// Should handle External File System.
EXPECT_TRUE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeExternal));
+ storage::kFileSystemTypeExternal));
// Shouldn't handle the rest.
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeIsolated));
- EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeTemporary));
+ storage::kFileSystemTypeIsolated));
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypePersistent));
+ storage::kFileSystemTypeTemporary));
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeTest));
+ storage::kFileSystemTypePersistent));
+ EXPECT_FALSE(
+ mount_points->HandlesFileSystemMountType(storage::kFileSystemTypeTest));
// Not even if it's external subtype.
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeNativeLocal));
- EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeRestrictedNativeLocal));
+ storage::kFileSystemTypeNativeLocal));
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeDrive));
+ storage::kFileSystemTypeRestrictedNativeLocal));
+ EXPECT_FALSE(
+ mount_points->HandlesFileSystemMountType(storage::kFileSystemTypeDrive));
EXPECT_FALSE(mount_points->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeSyncable));
+ storage::kFileSystemTypeSyncable));
}
TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points(
- fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<storage::ExternalMountPoints> mount_points(
+ storage::ExternalMountPoints::CreateRefCounted());
const GURL kTestOrigin("http://chromium.org");
mount_points->RegisterFileSystem("c",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
mount_points->RegisterFileSystem("c(1)",
- fileapi::kFileSystemTypeDrive,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeDrive,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
mount_points->RegisterFileSystem("empty_path",
- fileapi::kFileSystemTypeSyncable,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeSyncable,
+ storage::FileSystemMountOption(),
base::FilePath());
mount_points->RegisterFileSystem("mount",
- fileapi::kFileSystemTypeDrive,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeDrive,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root")));
// Try cracking invalid GURL.
@@ -293,69 +293,62 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
// Try cracking isolated path.
FileSystemURL isolated = mount_points->CreateCrackedFileSystemURL(
- kTestOrigin, fileapi::kFileSystemTypeIsolated, base::FilePath(FPL("c")));
+ kTestOrigin, storage::kFileSystemTypeIsolated, base::FilePath(FPL("c")));
EXPECT_FALSE(isolated.is_valid());
// Try native local which is not cracked.
FileSystemURL native_local = mount_points->CreateCrackedFileSystemURL(
kTestOrigin,
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
base::FilePath(FPL("c")));
EXPECT_FALSE(native_local.is_valid());
struct TestCase {
const base::FilePath::CharType* const path;
bool expect_valid;
- fileapi::FileSystemType expect_type;
+ storage::FileSystemType expect_type;
const base::FilePath::CharType* const expect_path;
const char* const expect_fs_id;
};
const TestCase kTestCases[] = {
- { FPL("c/d/e"),
- true, fileapi::kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"), "c" },
- { FPL("c(1)/d/e"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/a/b/c(1)/d/e"), "c(1)" },
- { FPL("c(1)"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/a/b/c(1)"), "c(1)" },
- { FPL("empty_path/a"),
- true, fileapi::kFileSystemTypeSyncable, FPL("a"), "empty_path" },
- { FPL("empty_path"),
- true, fileapi::kFileSystemTypeSyncable, FPL(""), "empty_path" },
- { FPL("mount/a/b"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/root/a/b"), "mount" },
- { FPL("mount"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/root"), "mount" },
- { FPL("cc"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL(""),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL(".."),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
+ {FPL("c/d/e"), true, storage::kFileSystemTypeNativeLocal,
+ DRIVE FPL("/a/b/c/d/e"), "c"},
+ {FPL("c(1)/d/e"), true, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/a/b/c(1)/d/e"), "c(1)"},
+ {FPL("c(1)"), true, storage::kFileSystemTypeDrive, DRIVE FPL("/a/b/c(1)"),
+ "c(1)"},
+ {FPL("empty_path/a"), true, storage::kFileSystemTypeSyncable, FPL("a"),
+ "empty_path"},
+ {FPL("empty_path"), true, storage::kFileSystemTypeSyncable, FPL(""),
+ "empty_path"},
+ {FPL("mount/a/b"), true, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/root/a/b"), "mount"},
+ {FPL("mount"), true, storage::kFileSystemTypeDrive, DRIVE FPL("/root"),
+ "mount"},
+ {FPL("cc"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL(""), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL(".."), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
// Absolte paths.
- { FPL("/c/d/e"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL("/c(1)/d/e"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL("/empty_path"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
+ {FPL("/c/d/e"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL("/c(1)/d/e"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL("/empty_path"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
// PAth references parent.
- { FPL("c/d/../e"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL("/empty_path/a/../b"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
+ {FPL("c/d/../e"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL("/empty_path/a/../b"), false, storage::kFileSystemTypeUnknown, FPL(""),
+ ""},
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("c/d\\e"),
- true, fileapi::kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"), "c" },
- { FPL("mount\\a\\b"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/root/a/b"), "mount" },
+ {FPL("c/d\\e"), true, storage::kFileSystemTypeNativeLocal,
+ DRIVE FPL("/a/b/c/d/e"), "c"},
+ {FPL("mount\\a\\b"), true, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/root/a/b"), "mount"},
#endif
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
FileSystemURL cracked = mount_points->CreateCrackedFileSystemURL(
kTestOrigin,
- fileapi::kFileSystemTypeExternal,
+ storage::kFileSystemTypeExternal,
base::FilePath(kTestCases[i].path));
EXPECT_EQ(kTestCases[i].expect_valid, cracked.is_valid())
@@ -376,89 +369,82 @@ TEST(ExternalMountPointsTest, CreateCrackedFileSystemURL) {
<< "Test case index: " << i;
EXPECT_EQ(kTestCases[i].expect_fs_id, cracked.filesystem_id())
<< "Test case index: " << i;
- EXPECT_EQ(fileapi::kFileSystemTypeExternal, cracked.mount_type())
+ EXPECT_EQ(storage::kFileSystemTypeExternal, cracked.mount_type())
<< "Test case index: " << i;
}
}
TEST(ExternalMountPointsTest, CrackVirtualPath) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points(
- fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<storage::ExternalMountPoints> mount_points(
+ storage::ExternalMountPoints::CreateRefCounted());
const GURL kTestOrigin("http://chromium.org");
mount_points->RegisterFileSystem("c",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c")));
mount_points->RegisterFileSystem("c(1)",
- fileapi::kFileSystemTypeDrive,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeDrive,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/a/b/c(1)")));
mount_points->RegisterFileSystem("empty_path",
- fileapi::kFileSystemTypeSyncable,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeSyncable,
+ storage::FileSystemMountOption(),
base::FilePath());
mount_points->RegisterFileSystem("mount",
- fileapi::kFileSystemTypeDrive,
- fileapi::FileSystemMountOption(),
+ storage::kFileSystemTypeDrive,
+ storage::FileSystemMountOption(),
base::FilePath(DRIVE FPL("/root")));
struct TestCase {
const base::FilePath::CharType* const path;
bool expect_valid;
- fileapi::FileSystemType expect_type;
+ storage::FileSystemType expect_type;
const base::FilePath::CharType* const expect_path;
const char* const expect_name;
};
const TestCase kTestCases[] = {
- { FPL("c/d/e"),
- true, fileapi::kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"), "c" },
- { FPL("c(1)/d/e"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/a/b/c(1)/d/e"), "c(1)" },
- { FPL("c(1)"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/a/b/c(1)"), "c(1)" },
- { FPL("empty_path/a"),
- true, fileapi::kFileSystemTypeSyncable, FPL("a"), "empty_path" },
- { FPL("empty_path"),
- true, fileapi::kFileSystemTypeSyncable, FPL(""), "empty_path" },
- { FPL("mount/a/b"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/root/a/b"), "mount" },
- { FPL("mount"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/root"), "mount" },
- { FPL("cc"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL(""),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL(".."),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
+ {FPL("c/d/e"), true, storage::kFileSystemTypeNativeLocal,
+ DRIVE FPL("/a/b/c/d/e"), "c"},
+ {FPL("c(1)/d/e"), true, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/a/b/c(1)/d/e"), "c(1)"},
+ {FPL("c(1)"), true, storage::kFileSystemTypeDrive, DRIVE FPL("/a/b/c(1)"),
+ "c(1)"},
+ {FPL("empty_path/a"), true, storage::kFileSystemTypeSyncable, FPL("a"),
+ "empty_path"},
+ {FPL("empty_path"), true, storage::kFileSystemTypeSyncable, FPL(""),
+ "empty_path"},
+ {FPL("mount/a/b"), true, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/root/a/b"), "mount"},
+ {FPL("mount"), true, storage::kFileSystemTypeDrive, DRIVE FPL("/root"),
+ "mount"},
+ {FPL("cc"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL(""), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL(".."), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
// Absolte paths.
- { FPL("/c/d/e"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL("/c(1)/d/e"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL("/empty_path"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
+ {FPL("/c/d/e"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL("/c(1)/d/e"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL("/empty_path"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
// PAth references parent.
- { FPL("c/d/../e"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
- { FPL("/empty_path/a/../b"),
- false, fileapi::kFileSystemTypeUnknown, FPL(""), "" },
+ {FPL("c/d/../e"), false, storage::kFileSystemTypeUnknown, FPL(""), ""},
+ {FPL("/empty_path/a/../b"), false, storage::kFileSystemTypeUnknown, FPL(""),
+ ""},
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("c/d\\e"),
- true, fileapi::kFileSystemTypeNativeLocal, DRIVE FPL("/a/b/c/d/e"), "c" },
- { FPL("mount\\a\\b"),
- true, fileapi::kFileSystemTypeDrive, DRIVE FPL("/root/a/b"), "mount" },
+ {FPL("c/d\\e"), true, storage::kFileSystemTypeNativeLocal,
+ DRIVE FPL("/a/b/c/d/e"), "c"},
+ {FPL("mount\\a\\b"), true, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/root/a/b"), "mount"},
#endif
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
std::string cracked_name;
- fileapi::FileSystemType cracked_type;
+ storage::FileSystemType cracked_type;
std::string cracked_id;
base::FilePath cracked_path;
- fileapi::FileSystemMountOption cracked_option;
+ storage::FileSystemMountOption cracked_option;
EXPECT_EQ(kTestCases[i].expect_valid,
mount_points->CrackVirtualPath(base::FilePath(kTestCases[i].path),
&cracked_name, &cracked_type, &cracked_id, &cracked_path,
@@ -482,33 +468,33 @@ TEST(ExternalMountPointsTest, CrackVirtualPath) {
}
TEST(ExternalMountPointsTest, MountOption) {
- scoped_refptr<fileapi::ExternalMountPoints> mount_points(
- fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<storage::ExternalMountPoints> mount_points(
+ storage::ExternalMountPoints::CreateRefCounted());
mount_points->RegisterFileSystem(
"nosync",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_NO_SYNC),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(storage::COPY_SYNC_OPTION_NO_SYNC),
base::FilePath(DRIVE FPL("/nosync")));
mount_points->RegisterFileSystem(
"sync",
- fileapi::kFileSystemTypeNativeLocal,
- fileapi::FileSystemMountOption(fileapi::COPY_SYNC_OPTION_SYNC),
+ storage::kFileSystemTypeNativeLocal,
+ storage::FileSystemMountOption(storage::COPY_SYNC_OPTION_SYNC),
base::FilePath(DRIVE FPL("/sync")));
std::string name;
- fileapi::FileSystemType type;
+ storage::FileSystemType type;
std::string cracked_id;
- fileapi::FileSystemMountOption option;
+ storage::FileSystemMountOption option;
base::FilePath path;
EXPECT_TRUE(mount_points->CrackVirtualPath(
base::FilePath(FPL("nosync/file")), &name, &type, &cracked_id, &path,
&option));
- EXPECT_EQ(fileapi::COPY_SYNC_OPTION_NO_SYNC, option.copy_sync_option());
+ EXPECT_EQ(storage::COPY_SYNC_OPTION_NO_SYNC, option.copy_sync_option());
EXPECT_TRUE(mount_points->CrackVirtualPath(
base::FilePath(FPL("sync/file")), &name, &type, &cracked_id, &path,
&option));
- EXPECT_EQ(fileapi::COPY_SYNC_OPTION_SYNC, option.copy_sync_option());
+ EXPECT_EQ(storage::COPY_SYNC_OPTION_SYNC, option.copy_sync_option());
}
} // namespace content
diff --git a/chromium/content/browser/fileapi/file_system_browsertest.cc b/chromium/content/browser/fileapi/file_system_browsertest.cc
index 51fc4164dab..804f04e9fd9 100644
--- a/chromium/content/browser/fileapi/file_system_browsertest.cc
+++ b/chromium/content/browser/fileapi/file_system_browsertest.cc
@@ -16,9 +16,9 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
-#include "webkit/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager.h"
-using quota::QuotaManager;
+using storage::QuotaManager;
namespace content {
@@ -51,7 +51,7 @@ class FileSystemBrowserTest : public ContentBrowserTest {
class FileSystemBrowserTestWithLowQuota : public FileSystemBrowserTest {
public:
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
const int kInitialQuotaKilobytes = 5000;
const int kTemporaryStorageQuotaMaxSize =
kInitialQuotaKilobytes * 1024 * QuotaManager::kPerHostTemporaryPortion;
@@ -70,7 +70,7 @@ class FileSystemBrowserTestWithLowQuota : public FileSystemBrowserTest {
return;
}
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- qm->SetTemporaryGlobalOverrideQuota(bytes, quota::QuotaCallback());
+ qm->SetTemporaryGlobalOverrideQuota(bytes, storage::QuotaCallback());
// Don't return until the quota has been set.
scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get()));
diff --git a/chromium/content/browser/fileapi/file_system_context_unittest.cc b/chromium/content/browser/fileapi/file_system_context_unittest.cc
index e746a6a3ad3..454a8f385e6 100644
--- a/chromium/content/browser/fileapi/file_system_context_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_context_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
@@ -10,10 +10,10 @@
#include "content/browser/quota/mock_quota_manager.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_file_system_options.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/isolated_context.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/isolated_context.h"
#define FPL(x) FILE_PATH_LITERAL(x)
@@ -23,12 +23,12 @@
#define DRIVE
#endif
-using fileapi::ExternalMountPoints;
-using fileapi::FileSystemBackend;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemMountOption;
-using fileapi::FileSystemURL;
-using fileapi::IsolatedContext;
+using storage::ExternalMountPoints;
+using storage::FileSystemBackend;
+using storage::FileSystemContext;
+using storage::FileSystemMountOption;
+using storage::FileSystemURL;
+using storage::IsolatedContext;
namespace content {
@@ -49,7 +49,7 @@ class FileSystemContextTest : public testing::Test {
public:
FileSystemContextTest() {}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
storage_policy_ = new MockSpecialStoragePolicy();
@@ -64,7 +64,7 @@ class FileSystemContextTest : public testing::Test {
protected:
FileSystemContext* CreateFileSystemContextForTest(
- fileapi::ExternalMountPoints* external_mount_points) {
+ storage::ExternalMountPoints* external_mount_points) {
return new FileSystemContext(
base::MessageLoopProxy::current().get(),
base::MessageLoopProxy::current().get(),
@@ -72,7 +72,7 @@ class FileSystemContextTest : public testing::Test {
storage_policy_.get(),
mock_quota_manager_->proxy(),
ScopedVector<FileSystemBackend>(),
- std::vector<fileapi::URLRequestAutoMountHandler>(),
+ std::vector<storage::URLRequestAutoMountHandler>(),
data_dir_.path(),
CreateAllowFileAccessOptions());
}
@@ -80,8 +80,8 @@ class FileSystemContextTest : public testing::Test {
// Verifies a *valid* filesystem url has expected values.
void ExpectFileSystemURLMatches(const FileSystemURL& url,
const GURL& expect_origin,
- fileapi::FileSystemType expect_mount_type,
- fileapi::FileSystemType expect_type,
+ storage::FileSystemType expect_mount_type,
+ storage::FileSystemType expect_type,
const base::FilePath& expect_path,
const base::FilePath& expect_virtual_path,
const std::string& expect_filesystem_id) {
@@ -98,7 +98,7 @@ class FileSystemContextTest : public testing::Test {
private:
base::ScopedTempDir data_dir_;
base::MessageLoop message_loop_;
- scoped_refptr<quota::SpecialStoragePolicy> storage_policy_;
+ scoped_refptr<storage::SpecialStoragePolicy> storage_policy_;
scoped_refptr<MockQuotaManager> mock_quota_manager_;
};
@@ -113,14 +113,14 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) {
std::string isolated_name = "root";
std::string isolated_id =
IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
std::string(),
base::FilePath(DRIVE FPL("/test/isolated/root")),
&isolated_name);
// Register system external mount point.
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
"system",
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/sys/"))));
@@ -130,12 +130,13 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) {
ExpectFileSystemURLMatches(
cracked_isolated,
GURL(kTestOrigin),
- fileapi::kFileSystemTypeIsolated,
- fileapi::kFileSystemTypeNativeLocal,
- base::FilePath(
- DRIVE FPL("/test/isolated/root/file")).NormalizePathSeparators(),
- base::FilePath::FromUTF8Unsafe(isolated_id).Append(FPL("root/file")).
- NormalizePathSeparators(),
+ storage::kFileSystemTypeIsolated,
+ storage::kFileSystemTypeNativeLocal,
+ base::FilePath(DRIVE FPL("/test/isolated/root/file"))
+ .NormalizePathSeparators(),
+ base::FilePath::FromUTF8Unsafe(isolated_id)
+ .Append(FPL("root/file"))
+ .NormalizePathSeparators(),
isolated_id);
FileSystemURL cracked_external = file_system_context->CrackURL(
@@ -144,14 +145,13 @@ TEST_F(FileSystemContextTest, NullExternalMountPoints) {
ExpectFileSystemURLMatches(
cracked_external,
GURL(kTestOrigin),
- fileapi::kFileSystemTypeExternal,
- fileapi::kFileSystemTypeNativeLocal,
- base::FilePath(
- DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
+ storage::kFileSystemTypeExternal,
+ storage::kFileSystemTypeNativeLocal,
+ base::FilePath(DRIVE FPL("/test/sys/root/file"))
+ .NormalizePathSeparators(),
base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
"system");
-
IsolatedContext::GetInstance()->RevokeFileSystem(isolated_id);
ExternalMountPoints::GetSystemInstance()->RevokeFileSystem("system");
}
@@ -164,7 +164,7 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
// Register system external mount point.
ASSERT_TRUE(mount_points->RegisterFileSystem(
"system",
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/sys/"))));
@@ -182,10 +182,10 @@ TEST_F(FileSystemContextTest, FileSystemContextKeepsMountPointsAlive) {
ExpectFileSystemURLMatches(
cracked_external,
GURL(kTestOrigin),
- fileapi::kFileSystemTypeExternal,
- fileapi::kFileSystemTypeNativeLocal,
- base::FilePath(
- DRIVE FPL("/test/sys/root/file")).NormalizePathSeparators(),
+ storage::kFileSystemTypeExternal,
+ storage::kFileSystemTypeNativeLocal,
+ base::FilePath(DRIVE FPL("/test/sys/root/file"))
+ .NormalizePathSeparators(),
base::FilePath(FPL("system/root/file")).NormalizePathSeparators(),
"system");
@@ -203,35 +203,35 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) {
std::string isolated_file_system_name = "root";
const std::string kIsolatedFileSystemID =
IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
std::string(),
base::FilePath(DRIVE FPL("/test/isolated/root")),
&isolated_file_system_name);
// Register system external mount point.
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
"system",
- fileapi::kFileSystemTypeDrive,
+ storage::kFileSystemTypeDrive,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/sys/"))));
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
"ext",
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/ext"))));
// Register a system external mount point with the same name/id as the
// registered isolated mount point.
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
kIsolatedFileSystemID,
- fileapi::kFileSystemTypeRestrictedNativeLocal,
+ storage::kFileSystemTypeRestrictedNativeLocal,
FileSystemMountOption(),
base::FilePath(DRIVE FPL("/test/system/isolated"))));
// Add a mount points with the same name as a system mount point to
// FileSystemContext's external mount points.
ASSERT_TRUE(external_mount_points->RegisterFileSystem(
"ext",
- fileapi::kFileSystemTypeNativeLocal,
- FileSystemMountOption(),
- base::FilePath(DRIVE FPL("/test/local/ext/"))));
+ storage::kFileSystemTypeNativeLocal,
+ FileSystemMountOption(),
+ base::FilePath(DRIVE FPL("/test/local/ext/"))));
const GURL kTestOrigin = GURL("http://chromium.org/");
const base::FilePath kVirtualPathNoRoot = base::FilePath(FPL("root/file"));
@@ -243,8 +243,8 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) {
// Expected test results.
bool expect_is_valid;
- fileapi::FileSystemType expect_mount_type;
- fileapi::FileSystemType expect_type;
+ storage::FileSystemType expect_mount_type;
+ storage::FileSystemType expect_type;
const base::FilePath::CharType* expect_path;
std::string expect_filesystem_id;
};
@@ -252,63 +252,45 @@ TEST_F(FileSystemContextTest, CrackFileSystemURL) {
const TestCase kTestCases[] = {
// Following should not be handled by the url crackers:
{
- "pers_mount", "persistent", true /* is_valid */,
- fileapi::kFileSystemTypePersistent, fileapi::kFileSystemTypePersistent,
- FPL("pers_mount/root/file"),
- std::string() /* filesystem id */
+ "pers_mount", "persistent", true /* is_valid */,
+ storage::kFileSystemTypePersistent, storage::kFileSystemTypePersistent,
+ FPL("pers_mount/root/file"), std::string() /* filesystem id */
},
{
- "temp_mount", "temporary", true /* is_valid */,
- fileapi::kFileSystemTypeTemporary, fileapi::kFileSystemTypeTemporary,
- FPL("temp_mount/root/file"),
- std::string() /* filesystem id */
+ "temp_mount", "temporary", true /* is_valid */,
+ storage::kFileSystemTypeTemporary, storage::kFileSystemTypeTemporary,
+ FPL("temp_mount/root/file"), std::string() /* filesystem id */
},
// Should be cracked by isolated mount points:
- {
- kIsolatedFileSystemID, "isolated", true /* is_valid */,
- fileapi::kFileSystemTypeIsolated, fileapi::kFileSystemTypeNativeLocal,
- DRIVE FPL("/test/isolated/root/file"),
- kIsolatedFileSystemID
- },
+ {kIsolatedFileSystemID, "isolated", true /* is_valid */,
+ storage::kFileSystemTypeIsolated, storage::kFileSystemTypeNativeLocal,
+ DRIVE FPL("/test/isolated/root/file"), kIsolatedFileSystemID},
// Should be cracked by system mount points:
- {
- "system", "external", true /* is_valid */,
- fileapi::kFileSystemTypeExternal, fileapi::kFileSystemTypeDrive,
- DRIVE FPL("/test/sys/root/file"),
- "system"
- },
- {
- kIsolatedFileSystemID, "external", true /* is_valid */,
- fileapi::kFileSystemTypeExternal,
- fileapi::kFileSystemTypeRestrictedNativeLocal,
- DRIVE FPL("/test/system/isolated/root/file"),
- kIsolatedFileSystemID
- },
+ {"system", "external", true /* is_valid */,
+ storage::kFileSystemTypeExternal, storage::kFileSystemTypeDrive,
+ DRIVE FPL("/test/sys/root/file"), "system"},
+ {kIsolatedFileSystemID, "external", true /* is_valid */,
+ storage::kFileSystemTypeExternal,
+ storage::kFileSystemTypeRestrictedNativeLocal,
+ DRIVE FPL("/test/system/isolated/root/file"), kIsolatedFileSystemID},
// Should be cracked by FileSystemContext's ExternalMountPoints.
- {
- "ext", "external", true /* is_valid */,
- fileapi::kFileSystemTypeExternal, fileapi::kFileSystemTypeNativeLocal,
- DRIVE FPL("/test/local/ext/root/file"),
- "ext"
- },
+ {"ext", "external", true /* is_valid */, storage::kFileSystemTypeExternal,
+ storage::kFileSystemTypeNativeLocal,
+ DRIVE FPL("/test/local/ext/root/file"), "ext"},
// Test for invalid filesystem url (made invalid by adding invalid
// filesystem type).
- {
- "sytem", "external", false /* is_valid */,
- // The rest of values will be ignored.
- fileapi::kFileSystemTypeUnknown, fileapi::kFileSystemTypeUnknown,
- FPL(""), std::string()
- },
+ {"sytem", "external", false /* is_valid */,
+ // The rest of values will be ignored.
+ storage::kFileSystemTypeUnknown, storage::kFileSystemTypeUnknown,
+ FPL(""), std::string()},
// Test for URL with non-existing filesystem id.
- {
- "invalid", "external", false /* is_valid */,
- // The rest of values will be ignored.
- fileapi::kFileSystemTypeUnknown, fileapi::kFileSystemTypeUnknown,
- FPL(""), std::string()
- },
+ {"invalid", "external", false /* is_valid */,
+ // The rest of values will be ignored.
+ storage::kFileSystemTypeUnknown, storage::kFileSystemTypeUnknown,
+ FPL(""), std::string()},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kTestCases); ++i) {
const base::FilePath virtual_path =
base::FilePath::FromUTF8Unsafe(
kTestCases[i].root).Append(kVirtualPathNoRoot);
@@ -351,31 +333,32 @@ TEST_F(FileSystemContextTest, CanServeURLRequest) {
// A request for a sandbox mount point should be served.
FileSystemURL cracked_url =
context->CrackURL(CreateRawFileSystemURL("persistent", "pers_mount"));
- EXPECT_EQ(fileapi::kFileSystemTypePersistent, cracked_url.mount_type());
+ EXPECT_EQ(storage::kFileSystemTypePersistent, cracked_url.mount_type());
EXPECT_TRUE(context->CanServeURLRequest(cracked_url));
// A request for an isolated mount point should NOT be served.
std::string isolated_fs_name = "root";
std::string isolated_fs_id =
IsolatedContext::GetInstance()->RegisterFileSystemForPath(
- fileapi::kFileSystemTypeNativeLocal,
+ storage::kFileSystemTypeNativeLocal,
std::string(),
base::FilePath(DRIVE FPL("/test/isolated/root")),
&isolated_fs_name);
cracked_url = context->CrackURL(
CreateRawFileSystemURL("isolated", isolated_fs_id));
- EXPECT_EQ(fileapi::kFileSystemTypeIsolated, cracked_url.mount_type());
+ EXPECT_EQ(storage::kFileSystemTypeIsolated, cracked_url.mount_type());
EXPECT_FALSE(context->CanServeURLRequest(cracked_url));
// A request for an external mount point should be served.
const std::string kExternalMountName = "ext_mount";
ASSERT_TRUE(ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- kExternalMountName, fileapi::kFileSystemTypeDrive,
+ kExternalMountName,
+ storage::kFileSystemTypeDrive,
FileSystemMountOption(),
base::FilePath()));
cracked_url = context->CrackURL(
CreateRawFileSystemURL("external", kExternalMountName));
- EXPECT_EQ(fileapi::kFileSystemTypeExternal, cracked_url.mount_type());
+ EXPECT_EQ(storage::kFileSystemTypeExternal, cracked_url.mount_type());
EXPECT_TRUE(context->CanServeURLRequest(cracked_url));
ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
diff --git a/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
index 8741cff294b..e496954c229 100644
--- a/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.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 "webkit/browser/fileapi/file_system_dir_url_request_job.h"
+#include "storage/browser/fileapi/file_system_dir_url_request_job.h"
#include <string>
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/memory/scoped_vector.h"
@@ -26,17 +26,17 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/icu/source/i18n/unicode/regex.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-using fileapi::FileSystemContext;
-using fileapi::FileSystemOperationContext;
-using fileapi::FileSystemURL;
+using storage::FileSystemContext;
+using storage::FileSystemOperationContext;
+using storage::FileSystemURL;
namespace content {
namespace {
@@ -50,7 +50,7 @@ const char kValidExternalMountPoint[] = "mnt_name";
// "automount", but will only succeed for the mount point "mnt_name".
bool TestAutoMountForURLRequest(
const net::URLRequest* /*url_request*/,
- const fileapi::FileSystemURL& filesystem_url,
+ const storage::FileSystemURL& filesystem_url,
const std::string& storage_domain,
const base::Callback<void(base::File::Error result)>& callback) {
if (storage_domain != "automount")
@@ -61,9 +61,11 @@ bool TestAutoMountForURLRequest(
std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe();
if (mount_point == kValidExternalMountPoint) {
- fileapi::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- kValidExternalMountPoint, fileapi::kFileSystemTypeTest,
- fileapi::FileSystemMountOption(), base::FilePath());
+ storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ kValidExternalMountPoint,
+ storage::kFileSystemTypeTest,
+ storage::FileSystemMountOption(),
+ base::FilePath());
callback.Run(base::File::FILE_OK);
} else {
callback.Run(base::File::FILE_ERROR_NOT_FOUND);
@@ -78,23 +80,34 @@ class FileSystemDirURLRequestJobFactory : public net::URLRequestJobFactory {
: storage_domain_(storage_domain), file_system_context_(context) {
}
- virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
- return new fileapi::FileSystemDirURLRequestJob(
+ net::NetworkDelegate* network_delegate) const override {
+ return new storage::FileSystemDirURLRequestJob(
request, network_delegate, storage_domain_, file_system_context_);
}
- virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
- return true;
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return nullptr;
}
- virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+ bool IsHandledProtocol(const std::string& scheme) const override {
return true;
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsHandledURL(const GURL& url) const override { return true; }
+
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
@@ -112,7 +125,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
: weak_factory_(this) {
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
special_storage_policy_ = new MockSpecialStoragePolicy;
@@ -120,14 +133,15 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
NULL, temp_dir_.path());
file_system_context_->OpenFileSystem(
- GURL("http://remote/"), fileapi::kFileSystemTypeTemporary,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ GURL("http://remote/"),
+ storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&FileSystemDirURLRequestJobTest::OnOpenFileSystem,
weak_factory_.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// NOTE: order matters, request must die before delegate
request_.reset(NULL);
delegate_.reset(NULL);
@@ -137,11 +151,11 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
*mnt_point = temp_dir_.path().AppendASCII("auto_mount_dir");
ASSERT_TRUE(base::CreateDirectory(*mnt_point));
- ScopedVector<fileapi::FileSystemBackend> additional_providers;
+ ScopedVector<storage::FileSystemBackend> additional_providers;
additional_providers.push_back(new TestFileSystemBackend(
base::MessageLoopProxy::current().get(), *mnt_point));
- std::vector<fileapi::URLRequestAutoMountHandler> handlers;
+ std::vector<storage::URLRequestAutoMountHandler> handlers;
handlers.push_back(base::Bind(&TestAutoMountForURLRequest));
file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting(
@@ -185,9 +199,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
FileSystemURL CreateURL(const base::FilePath& file_path) {
return file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://remote"),
- fileapi::kFileSystemTypeTemporary,
- file_path);
+ GURL("http://remote"), storage::kFileSystemTypeTemporary, file_path);
}
FileSystemOperationContext* NewOperationContext() {
@@ -268,7 +280,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
return GURL(kFileSystemURLPrefix + path);
}
- fileapi::FileSystemFileUtil* file_util() {
+ storage::FileSystemFileUtil* file_util() {
return file_system_context_->sandbox_delegate()->sync_file_util();
}
@@ -406,7 +418,7 @@ TEST_F(FileSystemDirURLRequestJobTest, AutoMountDirectoryListing) {
VerifyListingEntry(listing_entries[1], "foo", "foo", true, -1);
ASSERT_TRUE(
- fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
kValidExternalMountPoint));
}
@@ -420,7 +432,7 @@ TEST_F(FileSystemDirURLRequestJobTest, AutoMountInvalidRoot) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
ASSERT_FALSE(
- fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
"invalid"));
}
@@ -434,7 +446,7 @@ TEST_F(FileSystemDirURLRequestJobTest, AutoMountNoHandler) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
ASSERT_FALSE(
- fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
kValidExternalMountPoint));
}
diff --git a/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc b/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc
index fe1d25e5ddf..5e13f15c288 100644
--- a/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_file_stream_reader_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/file_system_file_stream_reader.h"
+#include "storage/browser/fileapi/file_system_file_stream_reader.h"
#include <limits>
#include <string>
@@ -15,16 +15,16 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemFileStreamReader;
-using fileapi::FileSystemType;
-using fileapi::FileSystemURL;
+using storage::FileSystemContext;
+using storage::FileSystemFileStreamReader;
+using storage::FileSystemType;
+using storage::FileSystemURL;
namespace content {
@@ -35,7 +35,7 @@ const char kTestFileName[] = "test.dat";
const char kTestData[] = "0123456789";
const int kTestDataSize = arraysize(kTestData) - 1;
-void ReadFromReader(fileapi::FileSystemFileStreamReader* reader,
+void ReadFromReader(storage::FileSystemFileStreamReader* reader,
std::string* data,
size_t size,
int* result) {
@@ -67,15 +67,16 @@ class FileSystemFileStreamReaderTest : public testing::Test {
public:
FileSystemFileStreamReaderTest() {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
file_system_context_ = CreateFileSystemContextForTesting(
NULL, temp_dir_.path());
file_system_context_->OpenFileSystem(
- GURL(kURLOrigin), fileapi::kFileSystemTypeTemporary,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ GURL(kURLOrigin),
+ storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&OnOpenFileSystem));
base::RunLoop().RunUntilIdle();
@@ -83,12 +84,10 @@ class FileSystemFileStreamReaderTest : public testing::Test {
&test_file_modification_time_);
}
- virtual void TearDown() OVERRIDE {
- base::RunLoop().RunUntilIdle();
- }
+ void TearDown() override { base::RunLoop().RunUntilIdle(); }
protected:
- fileapi::FileSystemFileStreamReader* CreateFileReader(
+ storage::FileSystemFileStreamReader* CreateFileReader(
const std::string& file_name,
int64 initial_offset,
const base::Time& expected_modification_time) {
@@ -110,12 +109,12 @@ class FileSystemFileStreamReaderTest : public testing::Test {
ASSERT_EQ(base::File::FILE_OK,
content::AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
+ file_system_context_.get(), url, buf, buf_size));
base::File::Info file_info;
ASSERT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
+ file_system_context_.get(), url, &file_info));
if (modification_time)
*modification_time = file_info.last_modified;
}
@@ -130,7 +129,7 @@ class FileSystemFileStreamReaderTest : public testing::Test {
FileSystemURL GetFileSystemURL(const std::string& file_name) {
return file_system_context_->CreateCrackedFileSystemURL(
GURL(kURLOrigin),
- fileapi::kFileSystemTypeTemporary,
+ storage::kFileSystemTypeTemporary,
base::FilePath().AppendASCII(file_name));
}
diff --git a/chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc
index 2f8e82ec094..23a8c2d679b 100644
--- a/chromium/content/browser/fileapi/file_system_operation_impl_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_operation_impl_unittest.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 "webkit/browser/fileapi/file_system_operation_impl.h"
+#include "storage/browser/fileapi/file_system_operation_impl.h"
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -13,58 +13,47 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "content/browser/fileapi/mock_file_change_observer.h"
+#include "content/browser/fileapi/mock_file_update_observer.h"
#include "content/browser/quota/mock_quota_manager.h"
#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "content/public/test/async_file_test_helper.h"
#include "content/public/test/sandbox_file_system_test_helper.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/blob/shareable_file_reference.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/common/fileapi/file_system_util.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemOperation;
-using fileapi::FileSystemOperationContext;
-using fileapi::FileSystemOperationRunner;
-using fileapi::FileSystemURL;
-using quota::QuotaManager;
-using quota::QuotaManagerProxy;
-using webkit_blob::ShareableFileReference;
+using storage::FileSystemOperation;
+using storage::FileSystemOperationContext;
+using storage::FileSystemOperationRunner;
+using storage::FileSystemURL;
+using storage::QuotaManager;
+using storage::QuotaManagerProxy;
+using storage::ShareableFileReference;
namespace content {
-namespace {
-
-const int kFileOperationStatusNotSet = 1;
-
-void AssertFileErrorEq(const tracked_objects::Location& from_here,
- base::File::Error expected,
- base::File::Error actual) {
- ASSERT_EQ(expected, actual) << from_here.ToString();
-}
-
-} // namespace
-
// Test class for FileSystemOperationImpl.
class FileSystemOperationImplTest
: public testing::Test {
public:
- FileSystemOperationImplTest()
- : status_(kFileOperationStatusNotSet),
- weak_factory_(this) {}
+ FileSystemOperationImplTest() : weak_factory_(this) {}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
EXPECT_TRUE(base_.CreateUniqueTempDir());
- change_observers_ = fileapi::MockFileChangeObserver::CreateList(
- &change_observer_);
+ change_observers_ =
+ storage::MockFileChangeObserver::CreateList(&change_observer_);
+ update_observers_ =
+ storage::MockFileUpdateObserver::CreateList(&update_observer_);
base::FilePath base_dir = base_.path().AppendASCII("filesystem");
quota_manager_ =
@@ -77,9 +66,11 @@ class FileSystemOperationImplTest
quota_manager(), base::MessageLoopProxy::current().get());
sandbox_file_system_.SetUp(base_dir, quota_manager_proxy_.get());
sandbox_file_system_.AddFileChangeObserver(&change_observer_);
+ sandbox_file_system_.AddFileUpdateObserver(&update_observer_);
+ update_observer_.Disable();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// Let the client go away before dropping a ref of the quota manager proxy.
quota_manager_proxy()->SimulateQuotaManagerDestroyed();
quota_manager_ = NULL;
@@ -91,10 +82,9 @@ class FileSystemOperationImplTest
return sandbox_file_system_.operation_runner();
}
- int status() const { return status_; }
const base::File::Info& info() const { return info_; }
const base::FilePath& path() const { return path_; }
- const std::vector<fileapi::DirectoryEntry>& entries() const {
+ const std::vector<storage::DirectoryEntry>& entries() const {
return entries_;
}
@@ -111,11 +101,11 @@ class FileSystemOperationImplTest
quota_manager_proxy_.get());
}
- fileapi::FileSystemFileUtil* file_util() {
+ storage::FileSystemFileUtil* file_util() {
return sandbox_file_system_.file_util();
}
- fileapi::MockFileChangeObserver* change_observer() {
+ storage::MockFileChangeObserver* change_observer() {
return &change_observer_;
}
@@ -172,54 +162,80 @@ class FileSystemOperationImplTest
}
// Callbacks for recording test results.
- FileSystemOperation::StatusCallback RecordStatusCallback() {
+ FileSystemOperation::StatusCallback RecordStatusCallback(
+ const base::Closure& closure,
+ base::File::Error* status) {
return base::Bind(&FileSystemOperationImplTest::DidFinish,
- weak_factory_.GetWeakPtr());
+ weak_factory_.GetWeakPtr(),
+ closure,
+ status);
}
- FileSystemOperation::ReadDirectoryCallback
- RecordReadDirectoryCallback() {
+ FileSystemOperation::ReadDirectoryCallback RecordReadDirectoryCallback(
+ const base::Closure& closure,
+ base::File::Error* status) {
return base::Bind(&FileSystemOperationImplTest::DidReadDirectory,
- weak_factory_.GetWeakPtr());
+ weak_factory_.GetWeakPtr(),
+ closure,
+ status);
}
- FileSystemOperation::GetMetadataCallback RecordMetadataCallback() {
+ FileSystemOperation::GetMetadataCallback RecordMetadataCallback(
+ const base::Closure& closure,
+ base::File::Error* status) {
return base::Bind(&FileSystemOperationImplTest::DidGetMetadata,
- weak_factory_.GetWeakPtr());
+ weak_factory_.GetWeakPtr(),
+ closure,
+ status);
}
- FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback() {
+ FileSystemOperation::SnapshotFileCallback RecordSnapshotFileCallback(
+ const base::Closure& closure,
+ base::File::Error* status) {
return base::Bind(&FileSystemOperationImplTest::DidCreateSnapshotFile,
- weak_factory_.GetWeakPtr());
+ weak_factory_.GetWeakPtr(),
+ closure,
+ status);
}
- void DidFinish(base::File::Error status) {
- status_ = status;
+ void DidFinish(const base::Closure& closure,
+ base::File::Error* status,
+ base::File::Error actual) {
+ *status = actual;
+ closure.Run();
}
- void DidReadDirectory(
- base::File::Error status,
- const std::vector<fileapi::DirectoryEntry>& entries,
- bool /* has_more */) {
+ void DidReadDirectory(const base::Closure& closure,
+ base::File::Error* status,
+ base::File::Error actual,
+ const std::vector<storage::DirectoryEntry>& entries,
+ bool /* has_more */) {
entries_ = entries;
- status_ = status;
+ *status = actual;
+ closure.Run();
}
- void DidGetMetadata(base::File::Error status,
+ void DidGetMetadata(const base::Closure& closure,
+ base::File::Error* status,
+ base::File::Error actual,
const base::File::Info& info) {
info_ = info;
- status_ = status;
+ *status = actual;
+ closure.Run();
}
void DidCreateSnapshotFile(
- base::File::Error status,
+ const base::Closure& closure,
+ base::File::Error* status,
+ base::File::Error actual,
const base::File::Info& info,
const base::FilePath& platform_path,
const scoped_refptr<ShareableFileReference>& shareable_file_ref) {
info_ = info;
path_ = platform_path;
- status_ = status;
+ *status = actual;
shareable_file_ref_ = shareable_file_ref;
+ closure.Run();
}
int64 GetDataSizeOnDisk() {
@@ -228,14 +244,14 @@ class FileSystemOperationImplTest
}
void GetUsageAndQuota(int64* usage, int64* quota) {
- quota::QuotaStatusCode status =
+ storage::QuotaStatusCode status =
AsyncFileTestHelper::GetUsageAndQuota(quota_manager_.get(),
sandbox_file_system_.origin(),
sandbox_file_system_.type(),
usage,
quota);
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(quota::kQuotaStatusOk, status);
+ ASSERT_EQ(storage::kQuotaStatusOk, status);
}
int64 ComputePathCost(const FileSystemURL& url) {
@@ -244,10 +260,8 @@ class FileSystemOperationImplTest
AsyncFileTestHelper::CreateFile(
sandbox_file_system_.file_system_context(), url);
- operation_runner()->Remove(url, false /* recursive */,
- base::Bind(&AssertFileErrorEq, FROM_HERE,
- base::File::FILE_OK));
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK, Remove(url, false /* recursive */));
+
change_observer()->ResetCount();
int64 total_usage;
@@ -277,8 +291,175 @@ class FileSystemOperationImplTest
quota + quota_delta);
}
+ base::File::Error Move(
+ const FileSystemURL& src,
+ const FileSystemURL& dest,
+ storage::FileSystemOperation::CopyOrMoveOption option) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->Move(
+ src,
+ dest,
+ option,
+ RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error Copy(
+ const FileSystemURL& src,
+ const FileSystemURL& dest,
+ storage::FileSystemOperation::CopyOrMoveOption option) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->Copy(
+ src,
+ dest,
+ option,
+ FileSystemOperationRunner::CopyProgressCallback(),
+ RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error CopyInForeignFile(const base::FilePath& src,
+ const FileSystemURL& dest) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->CopyInForeignFile(
+ src, dest, RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error Truncate(const FileSystemURL& url, int size) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->Truncate(
+ url, size, RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error CreateFile(const FileSystemURL& url, bool exclusive) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->CreateFile(
+ url, exclusive, RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error Remove(const FileSystemURL& url, bool recursive) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->Remove(
+ url, recursive, RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error CreateDirectory(const FileSystemURL& url,
+ bool exclusive,
+ bool recursive) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->CreateDirectory(
+ url,
+ exclusive,
+ recursive,
+ RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error GetMetadata(const FileSystemURL& url) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->GetMetadata(
+ url, RecordMetadataCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error ReadDirectory(const FileSystemURL& url) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->ReadDirectory(
+ url, RecordReadDirectoryCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error CreateSnapshotFile(const FileSystemURL& url) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->CreateSnapshotFile(
+ url, RecordSnapshotFileCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error FileExists(const FileSystemURL& url) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->FileExists(
+ url, RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error DirectoryExists(const FileSystemURL& url) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->DirectoryExists(
+ url, RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
+ base::File::Error TouchFile(const FileSystemURL& url,
+ const base::Time& last_access_time,
+ const base::Time& last_modified_time) {
+ base::File::Error status;
+ base::RunLoop run_loop;
+ update_observer_.Enable();
+ operation_runner()->TouchFile(
+ url,
+ last_access_time,
+ last_modified_time,
+ RecordStatusCallback(run_loop.QuitClosure(), &status));
+ run_loop.Run();
+ update_observer_.Disable();
+ return status;
+ }
+
private:
- base::MessageLoop message_loop_;
+ base::MessageLoopForIO message_loop_;
scoped_refptr<QuotaManager> quota_manager_;
scoped_refptr<QuotaManagerProxy> quota_manager_proxy_;
@@ -288,14 +469,15 @@ class FileSystemOperationImplTest
SandboxFileSystemTestHelper sandbox_file_system_;
// For post-operation status.
- int status_;
base::File::Info info_;
base::FilePath path_;
- std::vector<fileapi::DirectoryEntry> entries_;
+ std::vector<storage::DirectoryEntry> entries_;
scoped_refptr<ShareableFileReference> shareable_file_ref_;
- fileapi::MockFileChangeObserver change_observer_;
- fileapi::ChangeObserverList change_observers_;
+ storage::MockFileChangeObserver change_observer_;
+ storage::ChangeObserverList change_observers_;
+ storage::MockFileUpdateObserver update_observer_;
+ storage::UpdateObserverList update_observers_;
base::WeakPtrFactory<FileSystemOperationImplTest> weak_factory_;
@@ -304,11 +486,9 @@ class FileSystemOperationImplTest
TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDoesntExist) {
change_observer()->ResetCount();
- operation_runner()->Move(URLForPath("a"), URLForPath("b"),
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(
+ base::File::FILE_ERROR_NOT_FOUND,
+ Move(URLForPath("a"), URLForPath("b"), FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -316,11 +496,8 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureContainsPath) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL dest_dir(CreateDirectory("src/dest"));
- operation_runner()->Move(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
+ Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -330,11 +507,8 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcDirExistsDestFile) {
FileSystemURL dest_dir(CreateDirectory("dest"));
FileSystemURL dest_file(CreateFile("dest/file"));
- operation_runner()->Move(src_dir, dest_file,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
+ Move(src_dir, dest_file, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -345,11 +519,8 @@ TEST_F(FileSystemOperationImplTest,
FileSystemURL dest_dir(CreateDirectory("dest"));
FileSystemURL dest_file(CreateFile("dest/file"));
- operation_runner()->Move(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
+ Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -359,22 +530,18 @@ TEST_F(FileSystemOperationImplTest, TestMoveFailureSrcFileExistsDestDir) {
FileSystemURL src_file(CreateFile("src/file"));
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Move(src_file, dest_dir,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
+ Move(src_file, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestMoveFailureDestParentDoesntExist) {
// Dest. parent path does not exist.
FileSystemURL src_dir(CreateDirectory("src"));
- operation_runner()->Move(src_dir, URLForPath("nonexistent/deset"),
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ Move(src_dir,
+ URLForPath("nonexistent/deset"),
+ FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -382,11 +549,8 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) {
FileSystemURL src_file(CreateFile("src"));
FileSystemURL dest_file(CreateFile("dest"));
- operation_runner()->Move(src_file, dest_file,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Move(src_file, dest_file, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(FileExists("dest"));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
@@ -399,11 +563,9 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndOverwrite) {
TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcFileAndNew) {
FileSystemURL src_file(CreateFile("src"));
- operation_runner()->Move(src_file, URLForPath("new"),
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(
+ base::File::FILE_OK,
+ Move(src_file, URLForPath("new"), FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(FileExists("new"));
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
@@ -415,11 +577,8 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndOverwrite) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Move(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_FALSE(DirectoryExists("src"));
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
@@ -435,11 +594,9 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirAndNew) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Move(src_dir, URLForPath("dest/new"),
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(
+ base::File::FILE_OK,
+ Move(src_dir, URLForPath("dest/new"), FileSystemOperation::OPTION_NONE));
EXPECT_FALSE(DirectoryExists("src"));
EXPECT_TRUE(DirectoryExists("dest/new"));
@@ -455,11 +612,8 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSrcDirRecursive) {
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Move(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Move(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(DirectoryExists("dest/dir"));
EXPECT_TRUE(FileExists("dest/dir/sub"));
@@ -475,11 +629,8 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSamePath) {
CreateDirectory("src/dir");
CreateFile("src/dir/sub");
- operation_runner()->Move(src_dir, src_dir,
- FileSystemOperation::OPTION_NONE,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Move(src_dir, src_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(DirectoryExists("src/dir"));
EXPECT_TRUE(FileExists("src/dir/sub"));
@@ -491,12 +642,9 @@ TEST_F(FileSystemOperationImplTest, TestMoveSuccessSamePath) {
}
TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDoesntExist) {
- operation_runner()->Copy(URLForPath("a"), URLForPath("b"),
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(
+ base::File::FILE_ERROR_NOT_FOUND,
+ Copy(URLForPath("a"), URLForPath("b"), FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -504,12 +652,8 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureContainsPath) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL dest_dir(CreateDirectory("src/dir"));
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
+ Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -519,12 +663,8 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcDirExistsDestFile) {
FileSystemURL dest_dir(CreateDirectory("dest"));
FileSystemURL dest_file(CreateFile("dest/file"));
- operation_runner()->Copy(src_dir, dest_file,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
+ Copy(src_dir, dest_file, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -535,12 +675,8 @@ TEST_F(FileSystemOperationImplTest,
FileSystemURL dest_dir(CreateDirectory("dest"));
FileSystemURL dest_file(CreateFile("dest/file"));
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
+ Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -549,12 +685,8 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureSrcFileExistsDestDir) {
FileSystemURL src_file(CreateFile("src"));
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Copy(src_file, dest_dir,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION, status());
+ EXPECT_EQ(base::File::FILE_ERROR_INVALID_OPERATION,
+ Copy(src_file, dest_dir, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -562,12 +694,10 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureDestParentDoesntExist) {
// Dest. parent path does not exist.
FileSystemURL src_dir(CreateDirectory("src"));
- operation_runner()->Copy(src_dir, URLForPath("nonexistent/dest"),
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ Copy(src_dir,
+ URLForPath("nonexistent/dest"),
+ FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -575,9 +705,7 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL src_file(CreateFile("src/file"));
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Truncate(src_file, 6, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, Truncate(src_file, 6));
EXPECT_EQ(6, GetFileSize("src/file"));
FileSystemURL dest_file(URLForPath("dest/file"));
@@ -585,12 +713,8 @@ TEST_F(FileSystemOperationImplTest, TestCopyFailureByQuota) {
GrantQuotaForCurrentUsage();
AddQuota(6 + dest_path_cost - 1);
- operation_runner()->Copy(src_file, dest_file,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE,
+ Copy(src_file, dest_file, FileSystemOperation::OPTION_NONE));
EXPECT_FALSE(FileExists("dest/file"));
}
@@ -598,32 +722,27 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndOverwrite) {
FileSystemURL src_file(CreateFile("src"));
FileSystemURL dest_file(CreateFile("dest"));
- operation_runner()->Copy(src_file, dest_file,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src_file, dest_file, FileSystemOperation::OPTION_NONE));
+
EXPECT_TRUE(FileExists("dest"));
- EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
+ EXPECT_EQ(4, quota_manager_proxy()->notify_storage_accessed_count());
+ EXPECT_EQ(2, change_observer()->get_and_reset_modify_file_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcFileAndNew) {
FileSystemURL src_file(CreateFile("src"));
- operation_runner()->Copy(src_file, URLForPath("new"),
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(
+ base::File::FILE_OK,
+ Copy(src_file, URLForPath("new"), FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(FileExists("new"));
- EXPECT_EQ(2, quota_manager_proxy()->notify_storage_accessed_count());
+ EXPECT_EQ(4, quota_manager_proxy()->notify_storage_accessed_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -631,20 +750,16 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndOverwrite) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
// Make sure we've overwritten but not copied the source under the |dest_dir|.
EXPECT_TRUE(DirectoryExists("dest"));
EXPECT_FALSE(DirectoryExists("dest/src"));
EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 3);
- EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -652,12 +767,8 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirAndNew) {
FileSystemURL src_dir(CreateDirectory("src"));
FileSystemURL dest_dir_new(URLForPath("dest"));
- operation_runner()->Copy(src_dir, dest_dir_new,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src_dir, dest_dir_new, FileSystemOperation::OPTION_NONE));
EXPECT_TRUE(DirectoryExists("dest"));
EXPECT_GE(quota_manager_proxy()->notify_storage_accessed_count(), 2);
@@ -672,13 +783,9 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) {
FileSystemURL dest_dir(CreateDirectory("dest"));
- operation_runner()->Copy(src_dir, dest_dir,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src_dir, dest_dir, FileSystemOperation::OPTION_NONE));
- EXPECT_EQ(base::File::FILE_OK, status());
EXPECT_TRUE(DirectoryExists("dest/dir"));
EXPECT_TRUE(FileExists("dest/dir/sub"));
@@ -687,7 +794,8 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSrcDirRecursive) {
EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count());
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
- EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
+ EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -696,13 +804,9 @@ TEST_F(FileSystemOperationImplTest, TestCopySuccessSamePath) {
CreateDirectory("src/dir");
CreateFile("src/dir/sub");
- operation_runner()->Copy(src_dir, src_dir,
- FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src_dir, src_dir, FileSystemOperation::OPTION_NONE));
- EXPECT_EQ(base::File::FILE_OK, status());
EXPECT_TRUE(DirectoryExists("src/dir"));
EXPECT_TRUE(FileExists("src/dir/sub"));
@@ -716,7 +820,7 @@ TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) {
base::FilePath src_local_disk_file_path;
base::CreateTemporaryFile(&src_local_disk_file_path);
const char test_data[] = "foo";
- int data_size = ARRAYSIZE_UNSAFE(test_data);
+ int data_size = arraysize(test_data);
base::WriteFile(src_local_disk_file_path, test_data, data_size);
FileSystemURL dest_dir(CreateDirectory("dest"));
@@ -725,13 +829,11 @@ TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileSuccess) {
GetUsageAndQuota(&before_usage, NULL);
// Check that the file copied and corresponding usage increased.
- operation_runner()->CopyInForeignFile(src_local_disk_file_path,
- URLForPath("dest/file"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ base::File::FILE_OK,
+ CopyInForeignFile(src_local_disk_file_path, URLForPath("dest/file")));
EXPECT_EQ(1, change_observer()->create_file_count());
- EXPECT_EQ(base::File::FILE_OK, status());
EXPECT_TRUE(FileExists("dest/file"));
int64 after_usage;
GetUsageAndQuota(&after_usage, NULL);
@@ -749,37 +851,30 @@ TEST_F(FileSystemOperationImplTest, TestCopyInForeignFileFailureByQuota) {
base::FilePath src_local_disk_file_path;
base::CreateTemporaryFile(&src_local_disk_file_path);
const char test_data[] = "foo";
- base::WriteFile(src_local_disk_file_path, test_data,
- ARRAYSIZE_UNSAFE(test_data));
+ base::WriteFile(src_local_disk_file_path, test_data, arraysize(test_data));
FileSystemURL dest_dir(CreateDirectory("dest"));
GrantQuotaForCurrentUsage();
- operation_runner()->CopyInForeignFile(src_local_disk_file_path,
- URLForPath("dest/file"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(
+ base::File::FILE_ERROR_NO_SPACE,
+ CopyInForeignFile(src_local_disk_file_path, URLForPath("dest/file")));
EXPECT_FALSE(FileExists("dest/file"));
EXPECT_EQ(0, change_observer()->create_file_count());
- EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
}
TEST_F(FileSystemOperationImplTest, TestCreateFileFailure) {
// Already existing file and exclusive true.
FileSystemURL file(CreateFile("file"));
- operation_runner()->CreateFile(file, true, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status());
+ EXPECT_EQ(base::File::FILE_ERROR_EXISTS, CreateFile(file, true));
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) {
// Already existing file and exclusive false.
FileSystemURL file(CreateFile("file"));
- operation_runner()->CreateFile(file, false, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, CreateFile(file, false));
EXPECT_TRUE(FileExists("file"));
// The file was already there; did nothing.
@@ -788,98 +883,70 @@ TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileExists) {
TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessExclusive) {
// File doesn't exist but exclusive is true.
- operation_runner()->CreateFile(URLForPath("new"), true,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, CreateFile(URLForPath("new"), true));
EXPECT_TRUE(FileExists("new"));
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
}
TEST_F(FileSystemOperationImplTest, TestCreateFileSuccessFileDoesntExist) {
// Non existing file.
- operation_runner()->CreateFile(URLForPath("nonexistent"), false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, CreateFile(URLForPath("nonexistent"), false));
EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count());
}
TEST_F(FileSystemOperationImplTest,
TestCreateDirFailureDestParentDoesntExist) {
// Dest. parent path does not exist.
- operation_runner()->CreateDirectory(
- URLForPath("nonexistent/dir"), false, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ CreateDirectory(URLForPath("nonexistent/dir"), false, false));
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestCreateDirFailureDirExists) {
// Exclusive and dir existing at path.
FileSystemURL dir(CreateDirectory("dir"));
- operation_runner()->CreateDirectory(dir, true, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status());
+ EXPECT_EQ(base::File::FILE_ERROR_EXISTS, CreateDirectory(dir, true, false));
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestCreateDirFailureFileExists) {
// Exclusive true and file existing at path.
FileSystemURL file(CreateFile("file"));
- operation_runner()->CreateDirectory(file, true, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_EXISTS, status());
+ EXPECT_EQ(base::File::FILE_ERROR_EXISTS, CreateDirectory(file, true, false));
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestCreateDirSuccess) {
// Dir exists and exclusive is false.
FileSystemURL dir(CreateDirectory("dir"));
- operation_runner()->CreateDirectory(dir, false, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, CreateDirectory(dir, false, false));
EXPECT_TRUE(change_observer()->HasNoChange());
// Dir doesn't exist.
- operation_runner()->CreateDirectory(URLForPath("new"), false, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ CreateDirectory(URLForPath("new"), false, false));
EXPECT_TRUE(DirectoryExists("new"));
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
}
TEST_F(FileSystemOperationImplTest, TestCreateDirSuccessExclusive) {
// Dir doesn't exist.
- operation_runner()->CreateDirectory(URLForPath("new"), true, false,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ CreateDirectory(URLForPath("new"), true, false));
EXPECT_TRUE(DirectoryExists("new"));
EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count());
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataFailure) {
- operation_runner()->GetMetadata(URLForPath("nonexistent"),
- RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
-
- operation_runner()->FileExists(URLForPath("nonexistent"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
-
- operation_runner()->DirectoryExists(URLForPath("nonexistent"),
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ GetMetadata(URLForPath("nonexistent")));
+
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ FileExists(URLForPath("nonexistent")));
+
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ DirectoryExists(URLForPath("nonexistent")));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -888,25 +955,17 @@ TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) {
FileSystemURL file(CreateFile("dir/file"));
int read_access = 0;
- operation_runner()->DirectoryExists(dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, DirectoryExists(dir));
++read_access;
- operation_runner()->GetMetadata(dir, RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, GetMetadata(dir));
EXPECT_TRUE(info().is_directory);
++read_access;
- operation_runner()->FileExists(file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, FileExists(file));
++read_access;
- operation_runner()->GetMetadata(file, RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, GetMetadata(file));
EXPECT_FALSE(info().is_directory);
++read_access;
@@ -917,28 +976,20 @@ TEST_F(FileSystemOperationImplTest, TestExistsAndMetadataSuccess) {
TEST_F(FileSystemOperationImplTest, TestTypeMismatchErrors) {
FileSystemURL dir(CreateDirectory("dir"));
- operation_runner()->FileExists(dir, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_A_FILE, FileExists(dir));
FileSystemURL file(CreateFile("file"));
- operation_runner()->DirectoryExists(file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, DirectoryExists(file));
}
TEST_F(FileSystemOperationImplTest, TestReadDirFailure) {
// Path doesn't exist
- operation_runner()->ReadDirectory(URLForPath("nonexistent"),
- RecordReadDirectoryCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ ReadDirectory(URLForPath("nonexistent")));
// File exists.
FileSystemURL file(CreateFile("file"));
- operation_runner()->ReadDirectory(file, RecordReadDirectoryCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY, ReadDirectory(file));
EXPECT_TRUE(change_observer()->HasNoChange());
}
@@ -951,9 +1002,7 @@ TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) {
FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
FileSystemURL child_file(CreateFile("dir/child_file"));
- operation_runner()->ReadDirectory(parent_dir, RecordReadDirectoryCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, ReadDirectory(parent_dir));
EXPECT_EQ(2u, entries().size());
for (size_t i = 0; i < entries().size(); ++i) {
@@ -968,10 +1017,8 @@ TEST_F(FileSystemOperationImplTest, TestReadDirSuccess) {
TEST_F(FileSystemOperationImplTest, TestRemoveFailure) {
// Path doesn't exist.
- operation_runner()->Remove(URLForPath("nonexistent"), false /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND,
+ Remove(URLForPath("nonexistent"), false /* recursive */));
// It's an error to try to remove a non-empty directory if recursive flag
// is false.
@@ -983,20 +1030,15 @@ TEST_F(FileSystemOperationImplTest, TestRemoveFailure) {
FileSystemURL child_dir(CreateDirectory("dir/child_dir"));
FileSystemURL child_file(CreateFile("dir/child_file"));
- operation_runner()->Remove(parent_dir, false /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NOT_EMPTY,
+ Remove(parent_dir, false /* recursive */));
EXPECT_TRUE(change_observer()->HasNoChange());
}
TEST_F(FileSystemOperationImplTest, TestRemoveSuccess) {
FileSystemURL empty_dir(CreateDirectory("empty_dir"));
EXPECT_TRUE(DirectoryExists("empty_dir"));
- operation_runner()->Remove(empty_dir, false /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, Remove(empty_dir, false /* recursive */));
EXPECT_FALSE(DirectoryExists("empty_dir"));
EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count());
@@ -1019,10 +1061,7 @@ TEST_F(FileSystemOperationImplTest, TestRemoveSuccessRecursive) {
for (int i = 0; i < 8; ++i)
CreateFile(base::StringPrintf("dir/child_dir/file-%d", i));
- operation_runner()->Remove(parent_dir, true /* recursive */,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, Remove(parent_dir, true /* recursive */));
EXPECT_FALSE(DirectoryExists("parent_dir"));
EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count());
@@ -1040,17 +1079,13 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) {
base::WriteFile(platform_path, test_data, data_size));
// Check that its length is the size of the data written.
- operation_runner()->GetMetadata(file, RecordMetadataCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, GetMetadata(file));
EXPECT_FALSE(info().is_directory);
EXPECT_EQ(data_size, info().size);
// Extend the file by truncating it.
int length = 17;
- operation_runner()->Truncate(file, length, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, Truncate(file, length));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1069,9 +1104,7 @@ TEST_F(FileSystemOperationImplTest, TestTruncate) {
// Shorten the file by truncating it.
length = 3;
- operation_runner()->Truncate(file, length, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, Truncate(file, length));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1094,17 +1127,13 @@ TEST_F(FileSystemOperationImplTest, TestTruncateFailureByQuota) {
GrantQuotaForCurrentUsage();
AddQuota(10);
- operation_runner()->Truncate(file, 10, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, Truncate(file, 10));
EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count());
EXPECT_TRUE(change_observer()->HasNoChange());
EXPECT_EQ(10, GetFileSize("dir/file"));
- operation_runner()->Truncate(file, 11, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, status());
+ EXPECT_EQ(base::File::FILE_ERROR_NO_SPACE, Truncate(file, 11));
EXPECT_TRUE(change_observer()->HasNoChange());
EXPECT_EQ(10, GetFileSize("dir/file"));
@@ -1127,10 +1156,8 @@ TEST_F(FileSystemOperationImplTest, TestTouchFile) {
ASSERT_NE(last_modified, new_modified_time);
ASSERT_NE(last_accessed, new_accessed_time);
- operation_runner()->TouchFile(file, new_accessed_time, new_modified_time,
- RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK,
+ TouchFile(file, new_accessed_time, new_modified_time));
EXPECT_TRUE(change_observer()->HasNoChange());
EXPECT_TRUE(base::GetFileInfo(platform_path, &info));
@@ -1145,19 +1172,15 @@ TEST_F(FileSystemOperationImplTest, TestCreateSnapshotFile) {
FileSystemURL dir(CreateDirectory("dir"));
// Create a file for the testing.
- operation_runner()->DirectoryExists(dir, RecordStatusCallback());
+ EXPECT_EQ(base::File::FILE_OK, DirectoryExists(dir));
FileSystemURL file(CreateFile("dir/file"));
- operation_runner()->FileExists(file, RecordStatusCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, FileExists(file));
// See if we can get a 'snapshot' file info for the file.
// Since FileSystemOperationImpl assumes the file exists in the local
// directory it should just returns the same metadata and platform_path
// as the file itself.
- operation_runner()->CreateSnapshotFile(file, RecordSnapshotFileCallback());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(base::File::FILE_OK, status());
+ EXPECT_EQ(base::File::FILE_OK, CreateSnapshotFile(file));
EXPECT_FALSE(info().is_directory);
EXPECT_EQ(PlatformPath("dir/file"), path());
EXPECT_TRUE(change_observer()->HasNoChange());
@@ -1182,28 +1205,17 @@ TEST_F(FileSystemOperationImplTest,
int total_path_cost = GetUsage();
EXPECT_EQ(0, GetDataSizeOnDisk());
- operation_runner()->Truncate(
- child_file1, 5000,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- operation_runner()->Truncate(
- child_file2, 400,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- operation_runner()->Truncate(
- grandchild_file1, 30,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- operation_runner()->Truncate(
- grandchild_file2, 2,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK, Truncate(child_file1, 5000));
+ EXPECT_EQ(base::File::FILE_OK, Truncate(child_file2, 400));
+ EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file1, 30));
+ EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file2, 2));
const int64 all_file_size = 5000 + 400 + 30 + 2;
EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
EXPECT_EQ(all_file_size + total_path_cost, GetUsage());
- operation_runner()->Move(
- src, dest, FileSystemOperation::OPTION_NONE,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK,
+ Move(src, dest, FileSystemOperation::OPTION_NONE));
EXPECT_FALSE(DirectoryExists("src/dir"));
EXPECT_FALSE(FileExists("src/dir/file2"));
@@ -1235,19 +1247,10 @@ TEST_F(FileSystemOperationImplTest,
EXPECT_EQ(0, GetDataSizeOnDisk());
- operation_runner()->Truncate(
- child_file1, 8000,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- operation_runner()->Truncate(
- child_file2, 700,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- operation_runner()->Truncate(
- grandchild_file1, 60,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- operation_runner()->Truncate(
- grandchild_file2, 5,
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK, Truncate(child_file1, 8000));
+ EXPECT_EQ(base::File::FILE_OK, Truncate(child_file2, 700));
+ EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file1, 60));
+ EXPECT_EQ(base::File::FILE_OK, Truncate(grandchild_file2, 5));
const int64 child_file_size = 8000 + 700;
const int64 grandchild_file_size = 60 + 5;
@@ -1258,12 +1261,8 @@ TEST_F(FileSystemOperationImplTest,
EXPECT_EQ(all_file_size, GetDataSizeOnDisk());
EXPECT_EQ(expected_usage, usage);
- // Copy src to dest1.
- operation_runner()->Copy(
- src, dest1, FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src, dest1, FileSystemOperation::OPTION_NONE));
expected_usage += all_file_size + child_path_cost + grandchild_path_cost;
EXPECT_TRUE(DirectoryExists("src/dir"));
@@ -1274,12 +1273,8 @@ TEST_F(FileSystemOperationImplTest,
EXPECT_EQ(2 * all_file_size, GetDataSizeOnDisk());
EXPECT_EQ(expected_usage, GetUsage());
- // Copy src/dir to dest2.
- operation_runner()->Copy(
- child_dir, dest2, FileSystemOperation::OPTION_NONE,
- FileSystemOperationRunner::CopyProgressCallback(),
- base::Bind(&AssertFileErrorEq, FROM_HERE, base::File::FILE_OK));
- base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(child_dir, dest2, FileSystemOperation::OPTION_NONE));
expected_usage += grandchild_file_size + grandchild_path_cost;
usage = GetUsage();
@@ -1288,4 +1283,15 @@ TEST_F(FileSystemOperationImplTest,
EXPECT_EQ(expected_usage, usage);
}
+TEST_F(FileSystemOperationImplTest,
+ TestCopySuccessSrcFileWithDifferentFileSize) {
+ FileSystemURL src_file(CreateFile("src"));
+ FileSystemURL dest_file(CreateFile("dest"));
+
+ EXPECT_EQ(base::File::FILE_OK, Truncate(dest_file, 6));
+ EXPECT_EQ(base::File::FILE_OK,
+ Copy(src_file, dest_file, FileSystemOperation::OPTION_NONE));
+ EXPECT_EQ(0, GetFileSize("dest"));
+}
+
} // namespace content
diff --git a/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
index 47b0e2d122b..9d3c181fdce 100644
--- a/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_operation_impl_write_unittest.cc
@@ -18,21 +18,21 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory_impl.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/local_file_util.h"
+#include "storage/common/blob/blob_data.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/blob/blob_url_request_job.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/common/blob/blob_data.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-using fileapi::FileSystemOperation;
-using fileapi::FileSystemOperationRunner;
-using fileapi::FileSystemURL;
+
+using storage::FileSystemOperation;
+using storage::FileSystemOperationRunner;
+using storage::FileSystemURL;
using content::MockBlobURLRequestContext;
using content::ScopedTextBlob;
@@ -41,7 +41,7 @@ namespace content {
namespace {
const GURL kOrigin("http://example.com");
-const fileapi::FileSystemType kFileSystemType = fileapi::kFileSystemTypeTest;
+const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
void AssertStatusEq(base::File::Error expected,
base::File::Error actual) {
@@ -59,11 +59,11 @@ class FileSystemOperationImplWriteTest
bytes_written_(0),
complete_(false),
weak_factory_(this) {
- change_observers_ = fileapi::MockFileChangeObserver::CreateList(
- &change_observer_);
+ change_observers_ =
+ storage::MockFileChangeObserver::CreateList(&change_observer_);
}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(dir_.CreateUniqueTempDir());
quota_manager_ =
@@ -88,7 +88,7 @@ class FileSystemOperationImplWriteTest
->AddFileChangeObserver(change_observer());
}
- virtual void TearDown() {
+ void TearDown() override {
quota_manager_ = NULL;
file_system_context_ = NULL;
base::RunLoop().RunUntilIdle();
@@ -105,11 +105,11 @@ class FileSystemOperationImplWriteTest
bool complete() const { return complete_; }
protected:
- const fileapi::ChangeObserverList& change_observers() const {
+ const storage::ChangeObserverList& change_observers() const {
return change_observers_;
}
- fileapi::MockFileChangeObserver* change_observer() {
+ storage::MockFileChangeObserver* change_observer() {
return &change_observer_;
}
@@ -152,7 +152,7 @@ class FileSystemOperationImplWriteTest
return *url_request_context_;
}
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
scoped_refptr<MockQuotaManager> quota_manager_;
base::MessageLoopForIO loop_;
@@ -168,8 +168,8 @@ class FileSystemOperationImplWriteTest
scoped_ptr<MockBlobURLRequestContext> url_request_context_;
- fileapi::MockFileChangeObserver change_observer_;
- fileapi::ChangeObserverList change_observers_;
+ storage::MockFileChangeObserver change_observer_;
+ storage::ChangeObserverList change_observers_;
base::WeakPtrFactory<FileSystemOperationImplWriteTest> weak_factory_;
@@ -209,7 +209,7 @@ TEST_F(FileSystemOperationImplWriteTest, TestWriteZero) {
TEST_F(FileSystemOperationImplWriteTest, TestWriteInvalidBlobUrl) {
- scoped_ptr<webkit_blob::BlobDataHandle> null_handle;
+ scoped_ptr<storage::BlobDataHandle> null_handle;
file_system_context_->operation_runner()->Write(
&url_request_context(), URLForPath(virtual_path_),
null_handle.Pass(), 0, RecordWriteCallback());
diff --git a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
index af5f8e74ba9..12ba010a318 100644
--- a/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_operation_runner_unittest.cc
@@ -7,14 +7,14 @@
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "content/public/test/test_file_system_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-using fileapi::FileSystemContext;
-using fileapi::FileSystemOperationRunner;
-using fileapi::FileSystemType;
-using fileapi::FileSystemURL;
+using storage::FileSystemContext;
+using storage::FileSystemOperationRunner;
+using storage::FileSystemType;
+using storage::FileSystemURL;
namespace content {
@@ -40,23 +40,24 @@ void GetCancelStatus(bool* operation_done,
class FileSystemOperationRunnerTest : public testing::Test {
protected:
FileSystemOperationRunnerTest() {}
- virtual ~FileSystemOperationRunnerTest() {}
+ ~FileSystemOperationRunnerTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(base_.CreateUniqueTempDir());
base::FilePath base_dir = base_.path();
file_system_context_ =
CreateFileSystemContextForTesting(NULL, base_dir);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
file_system_context_ = NULL;
base::RunLoop().RunUntilIdle();
}
FileSystemURL URL(const std::string& path) {
return file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://example.com"), fileapi::kFileSystemTypeTemporary,
+ GURL("http://example.com"),
+ storage::kFileSystemTypeTemporary,
base::FilePath::FromUTF8Unsafe(path));
}
diff --git a/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc b/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
index 65eaf57d164..747c6626d6e 100644
--- a/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
@@ -4,25 +4,25 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "content/public/test/async_file_test_helper.h"
#include "content/public/test/test_file_system_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_quota_client.h"
+#include "storage/browser/fileapi/file_system_usage_cache.h"
+#include "storage/browser/fileapi/obfuscated_file_util.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/fileapi/file_system_util.h"
+#include "storage/common/quota/quota_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_quota_client.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/obfuscated_file_util.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/fileapi/file_system_util.h"
-#include "webkit/common/quota/quota_types.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemQuotaClient;
-using fileapi::FileSystemURL;
+using storage::FileSystemQuotaClient;
+using storage::FileSystemURL;
namespace content {
namespace {
@@ -32,8 +32,8 @@ const char kDummyURL2[] = "http://www.example.com";
const char kDummyURL3[] = "http://www.bleh";
// Declared to shorten the variable names.
-const quota::StorageType kTemporary = quota::kStorageTypeTemporary;
-const quota::StorageType kPersistent = quota::kStorageTypePersistent;
+const storage::StorageType kTemporary = storage::kStorageTypeTemporary;
+const storage::StorageType kPersistent = storage::kStorageTypePersistent;
} // namespace
@@ -42,10 +42,9 @@ class FileSystemQuotaClientTest : public testing::Test {
FileSystemQuotaClientTest()
: weak_factory_(this),
additional_callback_count_(0),
- deletion_status_(quota::kQuotaStatusUnknown) {
- }
+ deletion_status_(storage::kQuotaStatusUnknown) {}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
file_system_context_ = CreateFileSystemContextForTesting(
NULL, data_dir_.path());
@@ -56,7 +55,7 @@ class FileSystemQuotaClientTest : public testing::Test {
const char* name;
int64 size;
const char* origin_url;
- quota::StorageType type;
+ storage::StorageType type;
};
protected:
@@ -66,7 +65,7 @@ class FileSystemQuotaClientTest : public testing::Test {
void GetOriginUsageAsync(FileSystemQuotaClient* quota_client,
const std::string& origin_url,
- quota::StorageType type) {
+ storage::StorageType type) {
quota_client->GetOriginUsage(
GURL(origin_url), type,
base::Bind(&FileSystemQuotaClientTest::OnGetUsage,
@@ -75,15 +74,14 @@ class FileSystemQuotaClientTest : public testing::Test {
int64 GetOriginUsage(FileSystemQuotaClient* quota_client,
const std::string& origin_url,
- quota::StorageType type) {
+ storage::StorageType type) {
GetOriginUsageAsync(quota_client, origin_url, type);
base::RunLoop().RunUntilIdle();
return usage_;
}
- const std::set<GURL>& GetOriginsForType(
- FileSystemQuotaClient* quota_client,
- quota::StorageType type) {
+ const std::set<GURL>& GetOriginsForType(FileSystemQuotaClient* quota_client,
+ storage::StorageType type) {
origins_.clear();
quota_client->GetOriginsForType(
type,
@@ -93,10 +91,9 @@ class FileSystemQuotaClientTest : public testing::Test {
return origins_;
}
- const std::set<GURL>& GetOriginsForHost(
- FileSystemQuotaClient* quota_client,
- quota::StorageType type,
- const std::string& host) {
+ const std::set<GURL>& GetOriginsForHost(FileSystemQuotaClient* quota_client,
+ storage::StorageType type,
+ const std::string& host) {
origins_.clear();
quota_client->GetOriginsForHost(
type, host,
@@ -106,10 +103,9 @@ class FileSystemQuotaClientTest : public testing::Test {
return origins_;
}
- void RunAdditionalOriginUsageTask(
- FileSystemQuotaClient* quota_client,
- const std::string& origin_url,
- quota::StorageType type) {
+ void RunAdditionalOriginUsageTask(FileSystemQuotaClient* quota_client,
+ const std::string& origin_url,
+ storage::StorageType type) {
quota_client->GetOriginUsage(
GURL(origin_url), type,
base::Bind(&FileSystemQuotaClientTest::OnGetAdditionalUsage,
@@ -118,36 +114,36 @@ class FileSystemQuotaClientTest : public testing::Test {
bool CreateFileSystemDirectory(const base::FilePath& file_path,
const std::string& origin_url,
- quota::StorageType storage_type) {
- fileapi::FileSystemType type =
- fileapi::QuotaStorageTypeToFileSystemType(storage_type);
+ storage::StorageType storage_type) {
+ storage::FileSystemType type =
+ storage::QuotaStorageTypeToFileSystemType(storage_type);
FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
GURL(origin_url), type, file_path);
base::File::Error result =
- AsyncFileTestHelper::CreateDirectory(file_system_context_, url);
+ AsyncFileTestHelper::CreateDirectory(file_system_context_.get(), url);
return result == base::File::FILE_OK;
}
bool CreateFileSystemFile(const base::FilePath& file_path,
int64 file_size,
const std::string& origin_url,
- quota::StorageType storage_type) {
+ storage::StorageType storage_type) {
if (file_path.empty())
return false;
- fileapi::FileSystemType type =
- fileapi::QuotaStorageTypeToFileSystemType(storage_type);
+ storage::FileSystemType type =
+ storage::QuotaStorageTypeToFileSystemType(storage_type);
FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
GURL(origin_url), type, file_path);
base::File::Error result =
- AsyncFileTestHelper::CreateFile(file_system_context_, url);
+ AsyncFileTestHelper::CreateFile(file_system_context_.get(), url);
if (result != base::File::FILE_OK)
return false;
result = AsyncFileTestHelper::TruncateFile(
- file_system_context_, url, file_size);
+ file_system_context_.get(), url, file_size);
return result == base::File::FILE_OK;
}
@@ -182,15 +178,15 @@ class FileSystemQuotaClientTest : public testing::Test {
int64 ComputeFilePathsCostForOriginAndType(const TestFile* files,
int num_files,
const std::string& origin_url,
- quota::StorageType type) {
+ storage::StorageType type) {
int64 file_paths_cost = 0;
for (int i = 0; i < num_files; i++) {
if (files[i].type == type &&
GURL(files[i].origin_url) == GURL(origin_url)) {
base::FilePath path = base::FilePath().AppendASCII(files[i].name);
if (!path.empty()) {
- file_paths_cost += fileapi::ObfuscatedFileUtil::ComputeFilePathCost(
- path);
+ file_paths_cost +=
+ storage::ObfuscatedFileUtil::ComputeFilePathCost(path);
}
}
}
@@ -199,8 +195,8 @@ class FileSystemQuotaClientTest : public testing::Test {
void DeleteOriginData(FileSystemQuotaClient* quota_client,
const std::string& origin,
- quota::StorageType type) {
- deletion_status_ = quota::kQuotaStatusUnknown;
+ storage::StorageType type) {
+ deletion_status_ = storage::kQuotaStatusUnknown;
quota_client->DeleteOriginData(
GURL(origin), type,
base::Bind(&FileSystemQuotaClientTest::OnDeleteOrigin,
@@ -208,7 +204,7 @@ class FileSystemQuotaClientTest : public testing::Test {
}
int64 usage() const { return usage_; }
- quota::QuotaStatusCode status() { return deletion_status_; }
+ storage::QuotaStatusCode status() { return deletion_status_; }
int additional_callback_count() const { return additional_callback_count_; }
void set_additional_callback_count(int count) {
additional_callback_count_ = count;
@@ -227,18 +223,18 @@ class FileSystemQuotaClientTest : public testing::Test {
++additional_callback_count_;
}
- void OnDeleteOrigin(quota::QuotaStatusCode status) {
+ void OnDeleteOrigin(storage::QuotaStatusCode status) {
deletion_status_ = status;
}
base::ScopedTempDir data_dir_;
base::MessageLoop message_loop_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
base::WeakPtrFactory<FileSystemQuotaClientTest> weak_factory_;
int64 usage_;
int additional_callback_count_;
std::set<GURL> origins_;
- quota::QuotaStatusCode deletion_status_;
+ storage::QuotaStatusCode deletion_status_;
DISALLOW_COPY_AND_ASSIGN(FileSystemQuotaClientTest);
};
@@ -254,7 +250,7 @@ TEST_F(FileSystemQuotaClientTest, NoFileTest) {
const TestFile kFiles[] = {
{true, NULL, 0, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
for (int i = 0; i < 2; i++) {
EXPECT_EQ(0, GetOriginUsage(quota_client.get(), kDummyURL1, kTemporary));
@@ -267,9 +263,9 @@ TEST_F(FileSystemQuotaClientTest, OneFileTest) {
{true, NULL, 0, kDummyURL1, kTemporary},
{false, "foo", 4921, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(4921 + file_paths_cost,
@@ -284,9 +280,9 @@ TEST_F(FileSystemQuotaClientTest, TwoFilesTest) {
{false, "foo", 10310, kDummyURL1, kTemporary},
{false, "bar", 41, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(10310 + 41 + file_paths_cost,
@@ -302,9 +298,9 @@ TEST_F(FileSystemQuotaClientTest, EmptyFilesTest) {
{false, "bar", 0, kDummyURL1, kTemporary},
{false, "baz", 0, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(file_paths_cost,
@@ -320,9 +316,9 @@ TEST_F(FileSystemQuotaClientTest, SubDirectoryTest) {
{false, "dirtest/foo", 11921, kDummyURL1, kTemporary},
{false, "bar", 4814, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(11921 + 4814 + file_paths_cost,
@@ -342,11 +338,11 @@ TEST_F(FileSystemQuotaClientTest, MultiTypeTest) {
{false, "dirtest/foo", 193, kDummyURL1, kPersistent},
{false, "bar", 9, kDummyURL1, kPersistent},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost_temporary = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
const int64 file_paths_cost_persistent = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
for (int i = 0; i < 2; i++) {
EXPECT_EQ(133 + 14 + file_paths_cost_temporary,
@@ -376,16 +372,16 @@ TEST_F(FileSystemQuotaClientTest, MultiDomainTest) {
{false, "dom/fan", 2013, kDummyURL2, kPersistent},
{false, "baz", 18, kDummyURL2, kPersistent},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost_temporary1 = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
const int64 file_paths_cost_persistent1 =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
kDummyURL1, kPersistent);
const int64 file_paths_cost_temporary2 = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL2, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL2, kTemporary);
const int64 file_paths_cost_persistent2 =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
kDummyURL2, kPersistent);
for (int i = 0; i < 2; i++) {
@@ -407,9 +403,9 @@ TEST_F(FileSystemQuotaClientTest, GetUsage_MultipleTasks) {
{false, "foo", 11, kDummyURL1, kTemporary},
{false, "bar", 22, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost = ComputeFilePathsCostForOriginAndType(
- kFiles, ARRAYSIZE_UNSAFE(kFiles), kDummyURL1, kTemporary);
+ kFiles, arraysize(kFiles), kDummyURL1, kTemporary);
// Dispatching three GetUsage tasks.
set_additional_callback_count(0);
@@ -437,7 +433,7 @@ TEST_F(FileSystemQuotaClientTest, GetOriginsForType) {
{true, NULL, 0, kDummyURL2, kTemporary},
{true, NULL, 0, kDummyURL3, kPersistent},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
std::set<GURL> origins = GetOriginsForType(quota_client.get(), kTemporary);
EXPECT_EQ(2U, origins.size());
@@ -460,7 +456,7 @@ TEST_F(FileSystemQuotaClientTest, GetOriginsForHost) {
{true, NULL, 0, kURL4, kTemporary},
{true, NULL, 0, kURL5, kPersistent},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
std::set<GURL> origins = GetOriginsForHost(
quota_client.get(), kTemporary, "foo.com");
@@ -478,7 +474,7 @@ TEST_F(FileSystemQuotaClientTest, IncognitoTest) {
{true, NULL, 0, kDummyURL1, kTemporary},
{false, "foo", 10, kDummyURL1, kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
// Having files in the usual directory wouldn't affect the result
// queried in incognito mode.
@@ -509,34 +505,34 @@ TEST_F(FileSystemQuotaClientTest, DeleteOriginTest) {
{true, NULL, 0, "https://bar.com/", kTemporary},
{false, "g", 64, "https://bar.com/", kTemporary},
};
- InitializeOriginFiles(quota_client.get(), kFiles, ARRAYSIZE_UNSAFE(kFiles));
+ InitializeOriginFiles(quota_client.get(), kFiles, arraysize(kFiles));
const int64 file_paths_cost_temporary_foo_https =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
"https://foo.com/", kTemporary);
const int64 file_paths_cost_persistent_foo =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
"http://foo.com/", kPersistent);
const int64 file_paths_cost_temporary_bar =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
"http://bar.com/", kTemporary);
const int64 file_paths_cost_temporary_bar_https =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
"https://bar.com/", kTemporary);
const int64 file_paths_cost_persistent_bar_https =
- ComputeFilePathsCostForOriginAndType(kFiles, ARRAYSIZE_UNSAFE(kFiles),
+ ComputeFilePathsCostForOriginAndType(kFiles, arraysize(kFiles),
"https://bar.com/", kPersistent);
DeleteOriginData(quota_client.get(), "http://foo.com/", kTemporary);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(quota::kQuotaStatusOk, status());
+ EXPECT_EQ(storage::kQuotaStatusOk, status());
DeleteOriginData(quota_client.get(), "http://bar.com/", kPersistent);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(quota::kQuotaStatusOk, status());
+ EXPECT_EQ(storage::kQuotaStatusOk, status());
DeleteOriginData(quota_client.get(), "http://buz.com/", kTemporary);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(quota::kQuotaStatusOk, status());
+ EXPECT_EQ(storage::kQuotaStatusOk, status());
EXPECT_EQ(0, GetOriginUsage(
quota_client.get(), "http://foo.com/", kTemporary));
diff --git a/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
index 4f3d0abde39..4dcba3baac6 100644
--- a/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/file_system_url_request_job.h"
+#include "storage/browser/fileapi/file_system_url_request_job.h"
#include <string>
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/memory/scoped_vector.h"
@@ -33,15 +33,15 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemURL;
-using fileapi::FileSystemURLRequestJob;
+using storage::FileSystemContext;
+using storage::FileSystemURL;
+using storage::FileSystemURLRequestJob;
namespace content {
namespace {
@@ -60,7 +60,7 @@ const char kValidExternalMountPoint[] = "mnt_name";
// "automount", but will only succeed for the mount point "mnt_name".
bool TestAutoMountForURLRequest(
const net::URLRequest* /*url_request*/,
- const fileapi::FileSystemURL& filesystem_url,
+ const storage::FileSystemURL& filesystem_url,
const std::string& storage_domain,
const base::Callback<void(base::File::Error result)>& callback) {
if (storage_domain != "automount")
@@ -70,9 +70,11 @@ bool TestAutoMountForURLRequest(
std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe();
if (mount_point == kValidExternalMountPoint) {
- fileapi::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
- kValidExternalMountPoint, fileapi::kFileSystemTypeTest,
- fileapi::FileSystemMountOption(), base::FilePath());
+ storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ kValidExternalMountPoint,
+ storage::kFileSystemTypeTest,
+ storage::FileSystemMountOption(),
+ base::FilePath());
callback.Run(base::File::FILE_OK);
} else {
callback.Run(base::File::FILE_ERROR_NOT_FOUND);
@@ -87,23 +89,34 @@ class FileSystemURLRequestJobFactory : public net::URLRequestJobFactory {
: storage_domain_(storage_domain), file_system_context_(context) {
}
- virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
- return new fileapi::FileSystemURLRequestJob(
+ net::NetworkDelegate* network_delegate) const override {
+ return new storage::FileSystemURLRequestJob(
request, network_delegate, storage_domain_, file_system_context_);
}
- virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
- return true;
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return nullptr;
}
- virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+ bool IsHandledProtocol(const std::string& scheme) const override {
return true;
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsHandledURL(const GURL& url) const override { return true; }
+
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
@@ -119,7 +132,7 @@ class FileSystemURLRequestJobTest : public testing::Test {
FileSystemURLRequestJobTest() : weak_factory_(this) {
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
// We use the main thread so that we can get the root path synchronously.
@@ -128,14 +141,15 @@ class FileSystemURLRequestJobTest : public testing::Test {
CreateFileSystemContextForTesting(NULL, temp_dir_.path());
file_system_context_->OpenFileSystem(
- GURL("http://remote/"), fileapi::kFileSystemTypeTemporary,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ GURL("http://remote/"),
+ storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&FileSystemURLRequestJobTest::OnOpenFileSystem,
weak_factory_.GetWeakPtr()));
base::RunLoop().RunUntilIdle();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// FileReader posts a task to close the file in destructor.
base::RunLoop().RunUntilIdle();
}
@@ -144,11 +158,11 @@ class FileSystemURLRequestJobTest : public testing::Test {
base::FilePath mnt_point = temp_dir_.path().AppendASCII("auto_mount_dir");
ASSERT_TRUE(base::CreateDirectory(mnt_point));
- ScopedVector<fileapi::FileSystemBackend> additional_providers;
+ ScopedVector<storage::FileSystemBackend> additional_providers;
additional_providers.push_back(new TestFileSystemBackend(
base::MessageLoopProxy::current().get(), mnt_point));
- std::vector<fileapi::URLRequestAutoMountHandler> handlers;
+ std::vector<storage::URLRequestAutoMountHandler> handlers;
handlers.push_back(base::Bind(&TestAutoMountForURLRequest));
file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting(
@@ -210,21 +224,22 @@ class FileSystemURLRequestJobTest : public testing::Test {
void CreateDirectory(const base::StringPiece& dir_name) {
FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
GURL("http://remote"),
- fileapi::kFileSystemTypeTemporary,
+ storage::kFileSystemTypeTemporary,
base::FilePath().AppendASCII(dir_name));
- ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateDirectory(
- file_system_context_, url));
+ ASSERT_EQ(
+ base::File::FILE_OK,
+ AsyncFileTestHelper::CreateDirectory(file_system_context_.get(), url));
}
void WriteFile(const base::StringPiece& file_name,
const char* buf, int buf_size) {
FileSystemURL url = file_system_context_->CreateCrackedFileSystemURL(
GURL("http://remote"),
- fileapi::kFileSystemTypeTemporary,
+ storage::kFileSystemTypeTemporary,
base::FilePath().AppendASCII(file_name));
ASSERT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
+ file_system_context_.get(), url, buf, buf_size));
}
GURL CreateFileSystemURL(const std::string& path) {
@@ -235,7 +250,7 @@ class FileSystemURLRequestJobTest : public testing::Test {
base::MessageLoopForIO message_loop_;
base::ScopedTempDir temp_dir_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
base::WeakPtrFactory<FileSystemURLRequestJobTest> weak_factory_;
net::URLRequestContext empty_context_;
@@ -430,7 +445,7 @@ TEST_F(FileSystemURLRequestJobTest, AutoMountFileTest) {
EXPECT_EQ("no-cache", cache_control);
ASSERT_TRUE(
- fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
kValidExternalMountPoint));
}
@@ -443,7 +458,7 @@ TEST_F(FileSystemURLRequestJobTest, AutoMountInvalidRoot) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
ASSERT_FALSE(
- fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
"invalid"));
}
@@ -456,7 +471,7 @@ TEST_F(FileSystemURLRequestJobTest, AutoMountNoHandler) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error());
ASSERT_FALSE(
- fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
kValidExternalMountPoint));
}
diff --git a/chromium/content/browser/fileapi/file_system_url_unittest.cc b/chromium/content/browser/fileapi/file_system_url_unittest.cc
index 4aa23dd8ab4..e4dd5e2b3f5 100644
--- a/chromium/content/browser/fileapi/file_system_url_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_url_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/file_system_url.h"
#include "base/files/file_path.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/fileapi/file_system_util.h"
#define FPL FILE_PATH_LITERAL
@@ -18,12 +18,12 @@
#define DRIVE FPL("/a/")
#endif
-using fileapi::FileSystemURL;
-using fileapi::kFileSystemTypeExternal;
-using fileapi::kFileSystemTypeIsolated;
-using fileapi::kFileSystemTypePersistent;
-using fileapi::kFileSystemTypeTemporary;
-using fileapi::VirtualPath;
+using storage::FileSystemURL;
+using storage::kFileSystemTypeExternal;
+using storage::kFileSystemTypeIsolated;
+using storage::kFileSystemTypePersistent;
+using storage::kFileSystemTypeTemporary;
+using storage::VirtualPath;
namespace content {
diff --git a/chromium/content/browser/fileapi/file_system_usage_cache_unittest.cc b/chromium/content/browser/fileapi/file_system_usage_cache_unittest.cc
index 0a54b891075..13f1d659d30 100644
--- a/chromium/content/browser/fileapi/file_system_usage_cache_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_usage_cache_unittest.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
+#include "storage/browser/fileapi/file_system_usage_cache.h"
#include "base/basictypes.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
-using fileapi::FileSystemUsageCache;
+using storage::FileSystemUsageCache;
namespace content {
@@ -19,9 +19,7 @@ class FileSystemUsageCacheTest : public testing::Test {
FileSystemUsageCacheTest()
: usage_cache_(base::MessageLoopProxy::current().get()) {}
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- }
+ void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); }
protected:
base::FilePath GetUsageFilePath() {
diff --git a/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc b/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc
index ccbc4a563df..d907843695a 100644
--- a/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc
+++ b/chromium/content/browser/fileapi/file_writer_delegate_unittest.cc
@@ -20,26 +20,26 @@
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_status.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_quota_util.h"
+#include "storage/browser/fileapi/file_writer_delegate.h"
+#include "storage/browser/fileapi/sandbox_file_stream_writer.h"
#include "testing/platform_test.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_quota_util.h"
-#include "webkit/browser/fileapi/file_writer_delegate.h"
-#include "webkit/browser/fileapi/sandbox_file_stream_writer.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemURL;
-using fileapi::FileWriterDelegate;
+using storage::FileSystemURL;
+using storage::FileWriterDelegate;
namespace content {
namespace {
const GURL kOrigin("http://example.com");
-const fileapi::FileSystemType kFileSystemType = fileapi::kFileSystemTypeTest;
+const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
const char kData[] = "The quick brown fox jumps over the lazy dog.\n";
-const int kDataSize = ARRAYSIZE_UNSAFE(kData) - 1;
+const int kDataSize = arraysize(kData) - 1;
class Result {
public:
@@ -84,8 +84,8 @@ class FileWriterDelegateTest : public PlatformTest {
FileWriterDelegateTest() {}
protected:
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
+ void SetUp() override;
+ void TearDown() override;
int64 usage() {
return file_system_context_->GetQuotaUtil(kFileSystemType)
@@ -103,7 +103,7 @@ class FileWriterDelegateTest : public PlatformTest {
base::File::Info file_info;
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
+ file_system_context_.get(), url, &file_info));
return file_info.size;
}
@@ -116,16 +116,15 @@ class FileWriterDelegateTest : public PlatformTest {
const char* test_file_path,
int64 offset,
int64 allowed_growth) {
- fileapi::SandboxFileStreamWriter* writer =
- new fileapi::SandboxFileStreamWriter(
+ storage::SandboxFileStreamWriter* writer =
+ new storage::SandboxFileStreamWriter(
file_system_context_.get(),
GetFileSystemURL(test_file_path),
offset,
*file_system_context_->GetUpdateObservers(kFileSystemType));
writer->set_default_quota(allowed_growth);
- return new FileWriterDelegate(
- scoped_ptr<fileapi::FileStreamWriter>(writer),
- FileWriterDelegate::FLUSH_ON_COMPLETION);
+ return new FileWriterDelegate(scoped_ptr<storage::FileStreamWriter>(writer),
+ FileWriterDelegate::FLUSH_ON_COMPLETION);
}
FileWriterDelegate::DelegateWriteCallback GetWriteCallback(Result* result) {
@@ -147,7 +146,7 @@ class FileWriterDelegateTest : public PlatformTest {
// This should be alive until the very end of this instance.
base::MessageLoopForIO loop_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
net::URLRequestContext empty_context_;
scoped_ptr<FileWriterDelegate> file_writer_delegate_;
@@ -176,15 +175,13 @@ class FileWriterDelegateTestJob : public net::URLRequestJob {
cursor_(0) {
}
- virtual void Start() OVERRIDE {
+ void Start() override {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&FileWriterDelegateTestJob::NotifyHeadersComplete, this));
}
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int *bytes_read) OVERRIDE {
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override {
if (remaining_bytes_ < buf_size)
buf_size = static_cast<int>(remaining_bytes_);
@@ -197,12 +194,10 @@ class FileWriterDelegateTestJob : public net::URLRequestJob {
return true;
}
- virtual int GetResponseCode() const OVERRIDE {
- return 200;
- }
+ int GetResponseCode() const override { return 200; }
protected:
- virtual ~FileWriterDelegateTestJob() {}
+ ~FileWriterDelegateTestJob() override {}
private:
std::string content_;
@@ -216,23 +211,36 @@ class BlobURLRequestJobFactory : public net::URLRequestJobFactory {
: content_data_(content_data) {
}
- virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
return new FileWriterDelegateTestJob(
request, network_delegate, *content_data_);
}
- virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override {
+ return nullptr;
+ }
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ return nullptr;
+ }
+
+ bool IsHandledProtocol(const std::string& scheme) const override {
return scheme == "blob";
}
- virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+ bool IsHandledURL(const GURL& url) const override {
return url.SchemeIs("blob");
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return true;
}
@@ -250,8 +258,8 @@ void FileWriterDelegateTest::SetUp() {
file_system_context_ = CreateFileSystemContextForTesting(
NULL, dir_.path());
ASSERT_EQ(base::File::FILE_OK,
- AsyncFileTestHelper::CreateFile(
- file_system_context_, GetFileSystemURL("test")));
+ AsyncFileTestHelper::CreateFile(file_system_context_.get(),
+ GetFileSystemURL("test")));
job_factory_.reset(new BlobURLRequestJobFactory(&content_));
empty_context_.set_job_factory(job_factory_.get());
}
@@ -348,8 +356,8 @@ TEST_F(FileWriterDelegateTest, WriteSuccessWithoutQuotaLimitConcurrent) {
scoped_ptr<net::URLRequest> request2;
ASSERT_EQ(base::File::FILE_OK,
- AsyncFileTestHelper::CreateFile(
- file_system_context_, GetFileSystemURL("test2")));
+ AsyncFileTestHelper::CreateFile(file_system_context_.get(),
+ GetFileSystemURL("test2")));
const GURL kBlobURL("blob:nolimitconcurrent");
const GURL kBlobURL2("blob:nolimitconcurrent2");
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.cc b/chromium/content/browser/fileapi/fileapi_message_filter.cc
index 2eb601a7c6d..3fe4199272a 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.cc
@@ -27,25 +27,25 @@
#include "net/base/mime_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/fileapi/file_observers.h"
+#include "storage/browser/fileapi/file_permission_policy.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/common/blob/blob_data.h"
+#include "storage/common/blob/shareable_file_reference.h"
+#include "storage/common/fileapi/directory_entry.h"
+#include "storage/common/fileapi/file_system_info.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/fileapi/file_observers.h"
-#include "webkit/browser/fileapi/file_permission_policy.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/common/blob/blob_data.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-#include "webkit/common/fileapi/directory_entry.h"
-#include "webkit/common/fileapi/file_system_info.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/fileapi/file_system_util.h"
-
-using fileapi::FileSystemFileUtil;
-using fileapi::FileSystemBackend;
-using fileapi::FileSystemOperation;
-using fileapi::FileSystemURL;
-using webkit_blob::BlobData;
-using webkit_blob::BlobStorageContext;
+
+using storage::FileSystemFileUtil;
+using storage::FileSystemBackend;
+using storage::FileSystemOperation;
+using storage::FileSystemURL;
+using storage::BlobData;
+using storage::BlobStorageContext;
namespace content {
@@ -66,11 +66,11 @@ void RevokeFilePermission(int child_id, const base::FilePath& path) {
FileAPIMessageFilter::FileAPIMessageFilter(
int process_id,
net::URLRequestContextGetter* request_context_getter,
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
ChromeBlobStorageContext* blob_storage_context,
StreamContext* stream_context)
- : BrowserMessageFilter(
- kFilteredMessageClasses, arraysize(kFilteredMessageClasses)),
+ : BrowserMessageFilter(kFilteredMessageClasses,
+ arraysize(kFilteredMessageClasses)),
process_id_(process_id),
context_(file_system_context),
security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
@@ -87,11 +87,11 @@ FileAPIMessageFilter::FileAPIMessageFilter(
FileAPIMessageFilter::FileAPIMessageFilter(
int process_id,
net::URLRequestContext* request_context,
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
ChromeBlobStorageContext* blob_storage_context,
StreamContext* stream_context)
- : BrowserMessageFilter(
- kFilteredMessageClasses, arraysize(kFilteredMessageClasses)),
+ : BrowserMessageFilter(kFilteredMessageClasses,
+ arraysize(kFilteredMessageClasses)),
process_id_(process_id),
context_(file_system_context),
security_policy_(ChildProcessSecurityPolicyImpl::GetInstance()),
@@ -203,15 +203,15 @@ void FileAPIMessageFilter::BadMessageReceived() {
void FileAPIMessageFilter::OnOpenFileSystem(int request_id,
const GURL& origin_url,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (type == fileapi::kFileSystemTypeTemporary) {
+ if (type == storage::kFileSystemTypeTemporary) {
RecordAction(base::UserMetricsAction("OpenFileSystemTemporary"));
- } else if (type == fileapi::kFileSystemTypePersistent) {
+ } else if (type == storage::kFileSystemTypePersistent) {
RecordAction(base::UserMetricsAction("OpenFileSystemPersistent"));
}
- fileapi::OpenFileSystemMode mode =
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT;
+ storage::OpenFileSystemMode mode =
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT;
context_->OpenFileSystem(origin_url, type, mode, base::Bind(
&FileAPIMessageFilter::DidOpenFileSystem, this, request_id));
}
@@ -233,10 +233,9 @@ void FileAPIMessageFilter::OnResolveURL(
&FileAPIMessageFilter::DidResolveURL, this, request_id));
}
-void FileAPIMessageFilter::OnDeleteFileSystem(
- int request_id,
- const GURL& origin_url,
- fileapi::FileSystemType type) {
+void FileAPIMessageFilter::OnDeleteFileSystem(int request_id,
+ const GURL& origin_url,
+ storage::FileSystemType type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
context_->DeleteFileSystem(origin_url, type, base::Bind(
&FileAPIMessageFilter::DidDeleteFileSystem, this, request_id));
@@ -260,8 +259,9 @@ void FileAPIMessageFilter::OnMove(
}
operations_[request_id] = operation_runner()->Move(
- src_url, dest_url,
- fileapi::FileSystemOperation::OPTION_NONE,
+ src_url,
+ dest_url,
+ storage::FileSystemOperation::OPTION_NONE,
base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}
@@ -282,9 +282,10 @@ void FileAPIMessageFilter::OnCopy(
}
operations_[request_id] = operation_runner()->Copy(
- src_url, dest_url,
- fileapi::FileSystemOperation::OPTION_NONE,
- fileapi::FileSystemOperationRunner::CopyProgressCallback(),
+ src_url,
+ dest_url,
+ storage::FileSystemOperation::OPTION_NONE,
+ storage::FileSystemOperationRunner::CopyProgressCallback(),
base::Bind(&FileAPIMessageFilter::DidFinish, this, request_id));
}
@@ -406,7 +407,7 @@ void FileAPIMessageFilter::OnWrite(
return;
}
- scoped_ptr<webkit_blob::BlobDataHandle> blob =
+ scoped_ptr<storage::BlobDataHandle> blob =
blob_storage_context_->context()->GetBlobDataFromUUID(blob_uuid);
operations_[request_id] = operation_runner()->Write(
@@ -671,7 +672,7 @@ void FileAPIMessageFilter::OnCloneStream(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Abort if there's no Stream instance for |src_url| (source Stream which
// we're going to make |url| point to) in the registry.
- if (!GetStreamForURL(src_url))
+ if (!GetStreamForURL(src_url).get())
return;
stream_context_->registry()->CloneStream(url, src_url);
@@ -726,7 +727,7 @@ void FileAPIMessageFilter::DidGetMetadataForStreaming(
void FileAPIMessageFilter::DidReadDirectory(
int request_id,
base::File::Error result,
- const std::vector<fileapi::DirectoryEntry>& entries,
+ const std::vector<storage::DirectoryEntry>& entries,
bool has_more) {
if (result == base::File::FILE_OK) {
if (!entries.empty() || !has_more)
@@ -771,19 +772,21 @@ void FileAPIMessageFilter::DidOpenFileSystem(int request_id,
void FileAPIMessageFilter::DidResolveURL(
int request_id,
base::File::Error result,
- const fileapi::FileSystemInfo& info,
+ const storage::FileSystemInfo& info,
const base::FilePath& file_path,
- fileapi::FileSystemContext::ResolvedEntryType type) {
+ storage::FileSystemContext::ResolvedEntryType type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (result == base::File::FILE_OK &&
- type == fileapi::FileSystemContext::RESOLVED_ENTRY_NOT_FOUND)
+ type == storage::FileSystemContext::RESOLVED_ENTRY_NOT_FOUND)
result = base::File::FILE_ERROR_NOT_FOUND;
if (result == base::File::FILE_OK) {
DCHECK(info.root_url.is_valid());
Send(new FileSystemMsg_DidResolveURL(
- request_id, info, file_path,
- type == fileapi::FileSystemContext::RESOLVED_ENTRY_DIRECTORY));
+ request_id,
+ info,
+ file_path,
+ type == storage::FileSystemContext::RESOLVED_ENTRY_DIRECTORY));
} else {
Send(new FileSystemMsg_DidFail(request_id, result));
}
@@ -803,11 +806,11 @@ void FileAPIMessageFilter::DidDeleteFileSystem(
void FileAPIMessageFilter::DidCreateSnapshot(
int request_id,
- const fileapi::FileSystemURL& url,
+ const storage::FileSystemURL& url,
base::File::Error result,
const base::File::Info& info,
const base::FilePath& platform_path,
- const scoped_refptr<webkit_blob::ShareableFileReference>& /* unused */) {
+ const scoped_refptr<storage::ShareableFileReference>& /* unused */) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
operations_.erase(request_id);
@@ -816,8 +819,8 @@ void FileAPIMessageFilter::DidCreateSnapshot(
return;
}
- scoped_refptr<webkit_blob::ShareableFileReference> file_ref =
- webkit_blob::ShareableFileReference::Get(platform_path);
+ scoped_refptr<storage::ShareableFileReference> file_ref =
+ storage::ShareableFileReference::Get(platform_path);
if (!security_policy_->CanReadFile(process_id_, platform_path)) {
// Give per-file read permission to the snapshot file if it hasn't it yet.
// In order for the renderer to be able to read the file via File object,
@@ -831,9 +834,9 @@ void FileAPIMessageFilter::DidCreateSnapshot(
// is dropped.
if (!file_ref.get()) {
// Create a reference for temporary permission handling.
- file_ref = webkit_blob::ShareableFileReference::GetOrCreate(
+ file_ref = storage::ShareableFileReference::GetOrCreate(
platform_path,
- webkit_blob::ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
+ storage::ShareableFileReference::DONT_DELETE_ON_FINAL_RELEASE,
context_->default_file_task_runner());
}
file_ref->AddFinalReleaseCallback(
@@ -851,7 +854,8 @@ void FileAPIMessageFilter::DidCreateSnapshot(
}
bool FileAPIMessageFilter::ValidateFileSystemURL(
- int request_id, const fileapi::FileSystemURL& url) {
+ int request_id,
+ const storage::FileSystemURL& url) {
if (!FileSystemURLIsValid(context_, url)) {
Send(new FileSystemMsg_DidFail(request_id,
base::File::FILE_ERROR_INVALID_URL));
@@ -861,7 +865,7 @@ bool FileAPIMessageFilter::ValidateFileSystemURL(
// Deny access to files in PluginPrivate FileSystem from JavaScript.
// TODO(nhiroki): Move this filter somewhere else since this is not for
// validation.
- if (url.type() == fileapi::kFileSystemTypePluginPrivate) {
+ if (url.type() == storage::kFileSystemTypePluginPrivate) {
Send(new FileSystemMsg_DidFail(request_id,
base::File::FILE_ERROR_SECURITY));
return false;
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.h b/chromium/content/browser/fileapi/fileapi_message_filter.h
index 7a98b1483c9..297213d722d 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.h
@@ -18,11 +18,11 @@
#include "content/browser/streams/stream_context.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/common/blob/blob_data.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/common/blob/blob_data.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/quota/quota_types.h"
class GURL;
@@ -31,7 +31,7 @@ class FilePath;
class Time;
}
-namespace fileapi {
+namespace storage {
class FileSystemURL;
class FileSystemOperationRunner;
struct DirectoryEntry;
@@ -47,7 +47,7 @@ namespace content {
class BlobStorageHost;
}
-namespace webkit_blob {
+namespace storage {
class ShareableFileReference;
}
@@ -60,43 +60,41 @@ class ChromeBlobStorageContext;
class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
public:
// Used by the renderer process host on the UI thread.
- FileAPIMessageFilter(
- int process_id,
- net::URLRequestContextGetter* request_context_getter,
- fileapi::FileSystemContext* file_system_context,
- ChromeBlobStorageContext* blob_storage_context,
- StreamContext* stream_context);
+ FileAPIMessageFilter(int process_id,
+ net::URLRequestContextGetter* request_context_getter,
+ storage::FileSystemContext* file_system_context,
+ ChromeBlobStorageContext* blob_storage_context,
+ StreamContext* stream_context);
// Used by the worker process host on the IO thread.
- FileAPIMessageFilter(
- int process_id,
- net::URLRequestContext* request_context,
- fileapi::FileSystemContext* file_system_context,
- ChromeBlobStorageContext* blob_storage_context,
- StreamContext* stream_context);
+ FileAPIMessageFilter(int process_id,
+ net::URLRequestContext* request_context,
+ storage::FileSystemContext* file_system_context,
+ ChromeBlobStorageContext* blob_storage_context,
+ StreamContext* stream_context);
// BrowserMessageFilter implementation.
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelClosing() override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~FileAPIMessageFilter();
+ ~FileAPIMessageFilter() override;
- virtual void BadMessageReceived() OVERRIDE;
+ void BadMessageReceived() override;
private:
- typedef fileapi::FileSystemOperationRunner::OperationID OperationID;
+ typedef storage::FileSystemOperationRunner::OperationID OperationID;
void OnOpenFileSystem(int request_id,
const GURL& origin_url,
- fileapi::FileSystemType type);
+ storage::FileSystemType type);
void OnResolveURL(int request_id,
const GURL& filesystem_url);
void OnDeleteFileSystem(int request_id,
const GURL& origin_url,
- fileapi::FileSystemType type);
+ storage::FileSystemType type);
void OnMove(int request_id,
const GURL& src_path,
const GURL& dest_path);
@@ -132,7 +130,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
void OnStartBuildingBlob(const std::string& uuid);
void OnAppendBlobDataItemToBlob(const std::string& uuid,
- const webkit_blob::BlobData::Item& item);
+ const storage::BlobData::Item& item);
void OnAppendSharedMemoryToBlob(const std::string& uuid,
base::SharedMemoryHandle handle,
size_t buffer_size);
@@ -152,8 +150,8 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
//
// TODO(tyoshino): Set |content_type| to the stream.
void OnStartBuildingStream(const GURL& url, const std::string& content_type);
- void OnAppendBlobDataItemToStream(
- const GURL& url, const webkit_blob::BlobData::Item& item);
+ void OnAppendBlobDataItemToStream(const GURL& url,
+ const storage::BlobData::Item& item);
void OnAppendSharedMemoryToStream(
const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size);
void OnFinishBuildingStream(const GURL& url);
@@ -171,7 +169,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const base::File::Info& info);
void DidReadDirectory(int request_id,
base::File::Error result,
- const std::vector<fileapi::DirectoryEntry>& entries,
+ const std::vector<storage::DirectoryEntry>& entries,
bool has_more);
void DidWrite(int request_id,
base::File::Error result,
@@ -183,34 +181,34 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
base::File::Error result);
void DidResolveURL(int request_id,
base::File::Error result,
- const fileapi::FileSystemInfo& info,
+ const storage::FileSystemInfo& info,
const base::FilePath& file_path,
- fileapi::FileSystemContext::ResolvedEntryType type);
+ storage::FileSystemContext::ResolvedEntryType type);
void DidDeleteFileSystem(int request_id,
base::File::Error result);
void DidCreateSnapshot(
int request_id,
- const fileapi::FileSystemURL& url,
+ const storage::FileSystemURL& url,
base::File::Error result,
const base::File::Info& info,
const base::FilePath& platform_path,
- const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref);
+ const scoped_refptr<storage::ShareableFileReference>& file_ref);
// Sends a FileSystemMsg_DidFail and returns false if |url| is invalid.
- bool ValidateFileSystemURL(int request_id, const fileapi::FileSystemURL& url);
+ bool ValidateFileSystemURL(int request_id, const storage::FileSystemURL& url);
// Retrieves the Stream object for |url| from |stream_context_|. Returns unset
// scoped_refptr when there's no Stream instance for the given |url|
// registered with stream_context_->registry().
scoped_refptr<Stream> GetStreamForURL(const GURL& url);
- fileapi::FileSystemOperationRunner* operation_runner() {
+ storage::FileSystemOperationRunner* operation_runner() {
return operation_runner_.get();
}
int process_id_;
- fileapi::FileSystemContext* context_;
+ storage::FileSystemContext* context_;
ChildProcessSecurityPolicyImpl* security_policy_;
// Keeps map from request_id to OperationID for ongoing operations.
@@ -226,7 +224,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
scoped_refptr<StreamContext> stream_context_;
- scoped_ptr<fileapi::FileSystemOperationRunner> operation_runner_;
+ scoped_ptr<storage::FileSystemOperationRunner> operation_runner_;
// Keeps track of blobs used in this process and cleans up
// when the renderer process dies.
@@ -238,7 +236,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
// Used to keep snapshot files alive while a DidCreateSnapshot
// is being sent to the renderer.
- std::map<int, scoped_refptr<webkit_blob::ShareableFileReference> >
+ std::map<int, scoped_refptr<storage::ShareableFileReference> >
in_transit_snapshot_files_;
DISALLOW_COPY_AND_ASSIGN(FileAPIMessageFilter);
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
index 3a4c47e93eb..b3a66595420 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/streams/stream_registry.h"
@@ -23,10 +23,10 @@
#include "content/public/test/test_browser_thread.h"
#include "content/public/test/test_file_system_context.h"
#include "net/base/io_buffer.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/common/blob/blob_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/common/blob/blob_data.h"
namespace content {
@@ -48,17 +48,17 @@ class FileAPIMessageFilterTest : public testing::Test {
}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
file_system_context_ =
CreateFileSystemContextForTesting(NULL, base::FilePath());
- std::vector<fileapi::FileSystemType> types;
+ std::vector<storage::FileSystemType> types;
file_system_context_->GetFileSystemTypes(&types);
for (size_t i = 0; i < types.size(); ++i) {
- ChildProcessSecurityPolicyImpl::GetInstance()->
- RegisterFileSystemPermissionPolicy(
+ ChildProcessSecurityPolicyImpl::GetInstance()
+ ->RegisterFileSystemPermissionPolicy(
types[i],
- fileapi::FileSystemContext::GetPermissionPolicy(types[i]));
+ storage::FileSystemContext::GetPermissionPolicy(types[i]));
}
stream_context_ = StreamContext::GetFor(&browser_context_);
@@ -79,7 +79,7 @@ class FileAPIMessageFilterTest : public testing::Test {
TestBrowserThread io_browser_thread_;
TestBrowserContext browser_context_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
StreamContext* stream_context_;
ChromeBlobStorageContext* blob_storage_context_;
@@ -197,7 +197,7 @@ TEST_F(FileAPIMessageFilterTest, BuildNonEmptyStream) {
StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
EXPECT_TRUE(filter_->OnMessageReceived(start_message));
- webkit_blob::BlobData::Item item;
+ storage::BlobData::Item item;
const std::string kFakeData = "foobarbaz";
item.SetToBytes(kFakeData.data(), kFakeData.size());
StreamHostMsg_AppendBlobDataItem append_message(kUrl, item);
@@ -236,7 +236,7 @@ TEST_F(FileAPIMessageFilterTest, BuildStreamWithSharedMemory) {
// OnAppendSharedMemoryToStream passes the peer process's handle to
// SharedMemory's constructor. If it's incorrect, DuplicateHandle won't work
// correctly.
- filter_->set_peer_pid_for_testing(base::Process::Current().pid());
+ filter_->set_peer_pid_for_testing(base::GetCurrentProcId());
StreamHostMsg_StartBuilding start_message(kUrl, kFakeContentType);
EXPECT_TRUE(filter_->OnMessageReceived(start_message));
diff --git a/chromium/content/browser/fileapi/isolated_context_unittest.cc b/chromium/content/browser/fileapi/isolated_context_unittest.cc
index be5cc8e1c00..72969344505 100644
--- a/chromium/content/browser/fileapi/isolated_context_unittest.cc
+++ b/chromium/content/browser/fileapi/isolated_context_unittest.cc
@@ -6,9 +6,9 @@
#include "base/basictypes.h"
#include "base/logging.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/isolated_context.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/isolated_context.h"
#define FPL(x) FILE_PATH_LITERAL(x)
@@ -18,12 +18,12 @@
#define DRIVE
#endif
-using fileapi::FileSystemMountOption;
-using fileapi::FileSystemURL;
-using fileapi::IsolatedContext;
-using fileapi::kFileSystemTypeDragged;
-using fileapi::kFileSystemTypeIsolated;
-using fileapi::kFileSystemTypeNativeLocal;
+using storage::FileSystemMountOption;
+using storage::FileSystemURL;
+using storage::IsolatedContext;
+using storage::kFileSystemTypeDragged;
+using storage::kFileSystemTypeIsolated;
+using storage::kFileSystemTypeNativeLocal;
namespace content {
@@ -55,7 +55,7 @@ class IsolatedContextTest : public testing::Test {
fileset_.insert(kTestPaths[i].NormalizePathSeparators());
}
- virtual void SetUp() {
+ void SetUp() override {
IsolatedContext::FileInfoSet files;
for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
std::string name;
@@ -68,7 +68,7 @@ class IsolatedContextTest : public testing::Test {
ASSERT_FALSE(id_.empty());
}
- virtual void TearDown() {
+ void TearDown() override {
IsolatedContext::GetInstance()->RemoveReference(id_);
}
@@ -103,7 +103,7 @@ TEST_F(IsolatedContextTest, RegisterAndRevokeTest) {
std::string cracked_id;
base::FilePath cracked_path;
std::string cracked_inner_id;
- fileapi::FileSystemType cracked_type;
+ storage::FileSystemType cracked_type;
FileSystemMountOption cracked_option;
ASSERT_TRUE(isolated_context()->CrackVirtualPath(
virtual_path, &cracked_id, &cracked_type, &cracked_inner_id,
@@ -195,7 +195,7 @@ TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
};
for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
- for (size_t j = 0; j < ARRAYSIZE_UNSAFE(relatives); ++j) {
+ for (size_t j = 0; j < arraysize(relatives); ++j) {
SCOPED_TRACE(testing::Message() << "Testing "
<< kTestPaths[i].value() << " " << relatives[j].path);
base::FilePath virtual_path =
@@ -203,7 +203,7 @@ TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
names_[i]).Append(relatives[j].path);
std::string cracked_id;
base::FilePath cracked_path;
- fileapi::FileSystemType cracked_type;
+ storage::FileSystemType cracked_type;
std::string cracked_inner_id;
FileSystemMountOption cracked_option;
if (!relatives[j].valid) {
@@ -245,7 +245,7 @@ TEST_F(IsolatedContextTest, CrackURLWithRelativePaths) {
};
for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
- for (size_t j = 0; j < ARRAYSIZE_UNSAFE(relatives); ++j) {
+ for (size_t j = 0; j < arraysize(relatives); ++j) {
SCOPED_TRACE(testing::Message() << "Testing "
<< kTestPaths[i].value() << " " << relatives[j].path);
base::FilePath virtual_path =
@@ -299,35 +299,36 @@ TEST_F(IsolatedContextTest, CanHandleURL) {
// Should handle isolated file system.
EXPECT_TRUE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeIsolated));
+ storage::kFileSystemTypeIsolated));
// Shouldn't handle the rest.
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeExternal));
+ storage::kFileSystemTypeExternal));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeTemporary));
+ storage::kFileSystemTypeTemporary));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypePersistent));
+ storage::kFileSystemTypePersistent));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeTest));
+ storage::kFileSystemTypeTest));
// Not even if it's isolated subtype.
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeNativeLocal));
+ storage::kFileSystemTypeNativeLocal));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeDragged));
+ storage::kFileSystemTypeDragged));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeNativeMedia));
+ storage::kFileSystemTypeNativeMedia));
EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
- fileapi::kFileSystemTypeDeviceMedia));
+ storage::kFileSystemTypeDeviceMedia));
}
TEST_F(IsolatedContextTest, VirtualFileSystemTests) {
// Should be able to register empty and non-absolute paths
std::string empty_fsid = isolated_context()->RegisterFileSystemForVirtualPath(
- fileapi::kFileSystemTypeIsolated, "_", base::FilePath());
+ storage::kFileSystemTypeIsolated, "_", base::FilePath());
std::string relative_fsid =
isolated_context()->RegisterFileSystemForVirtualPath(
- fileapi::kFileSystemTypeIsolated, "_",
+ storage::kFileSystemTypeIsolated,
+ "_",
base::FilePath(FPL("relpath")));
ASSERT_FALSE(empty_fsid.empty());
ASSERT_FALSE(relative_fsid.empty());
@@ -336,7 +337,7 @@ TEST_F(IsolatedContextTest, VirtualFileSystemTests) {
base::FilePath database_root = base::FilePath(DRIVE FPL("/database_path"));
std::string database_fsid =
isolated_context()->RegisterFileSystemForVirtualPath(
- fileapi::kFileSystemTypeIsolated, "_", database_root);
+ storage::kFileSystemTypeIsolated, "_", database_root);
base::FilePath test_virtual_path =
base::FilePath().AppendASCII("virtualdir").AppendASCII("virtualfile.txt");
diff --git a/chromium/content/browser/fileapi/local_file_stream_reader_unittest.cc b/chromium/content/browser/fileapi/local_file_stream_reader_unittest.cc
index c9547ed770c..461aa606c6c 100644
--- a/chromium/content/browser/fileapi/local_file_stream_reader_unittest.cc
+++ b/chromium/content/browser/fileapi/local_file_stream_reader_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/blob/local_file_stream_reader.h"
+#include "storage/browser/blob/local_file_stream_reader.h"
#include <string>
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
@@ -18,7 +18,7 @@
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
-using webkit_blob::LocalFileStreamReader;
+using storage::LocalFileStreamReader;
namespace content {
@@ -64,7 +64,7 @@ class LocalFileStreamReaderTest : public testing::Test {
LocalFileStreamReaderTest()
: file_thread_("FileUtilProxyTestFileThread") {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(file_thread_.Start());
ASSERT_TRUE(dir_.CreateUniqueTempDir());
@@ -74,7 +74,7 @@ class LocalFileStreamReaderTest : public testing::Test {
test_file_modification_time_ = info.last_modified;
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// Give another chance for deleted streams to perform Close.
base::RunLoop().RunUntilIdle();
file_thread_.Stop();
diff --git a/chromium/content/browser/fileapi/local_file_stream_writer_unittest.cc b/chromium/content/browser/fileapi/local_file_stream_writer_unittest.cc
index 97e5e1ecc1a..48f5560ff8b 100644
--- a/chromium/content/browser/fileapi/local_file_stream_writer_unittest.cc
+++ b/chromium/content/browser/fileapi/local_file_stream_writer_unittest.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 "webkit/browser/fileapi/local_file_stream_writer.h"
+#include "storage/browser/fileapi/local_file_stream_writer.h"
#include <string>
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -18,8 +18,8 @@
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
-using fileapi::FileStreamWriter;
-using fileapi::LocalFileStreamWriter;
+using storage::FileStreamWriter;
+using storage::LocalFileStreamWriter;
namespace content {
@@ -28,12 +28,12 @@ class LocalFileStreamWriterTest : public testing::Test {
LocalFileStreamWriterTest()
: file_thread_("FileUtilProxyTestFileThread") {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(file_thread_.Start());
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// Give another chance for deleted streams to perform Close.
base::RunLoop().RunUntilIdle();
file_thread_.Stop();
diff --git a/chromium/content/browser/fileapi/local_file_util_unittest.cc b/chromium/content/browser/fileapi/local_file_util_unittest.cc
index a20b18d3bff..bf2f2f874a3 100644
--- a/chromium/content/browser/fileapi/local_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/local_file_util_unittest.cc
@@ -4,9 +4,9 @@
#include <string>
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
@@ -14,28 +14,28 @@
#include "base/strings/utf_string_conversions.h"
#include "content/public/test/async_file_test_helper.h"
#include "content/public/test/test_file_system_context.h"
+#include "storage/browser/fileapi/async_file_util_adapter.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/local_file_util.h"
+#include "storage/browser/fileapi/native_file_util.h"
+#include "storage/common/fileapi/file_system_types.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/async_file_util_adapter.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/local_file_util.h"
-#include "webkit/browser/fileapi/native_file_util.h"
-#include "webkit/common/fileapi/file_system_types.h"
using content::AsyncFileTestHelper;
-using fileapi::AsyncFileUtilAdapter;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemOperationContext;
-using fileapi::FileSystemURL;
-using fileapi::LocalFileUtil;
+using storage::AsyncFileUtilAdapter;
+using storage::FileSystemContext;
+using storage::FileSystemOperationContext;
+using storage::FileSystemURL;
+using storage::LocalFileUtil;
namespace content {
namespace {
const GURL kOrigin("http://foo/");
-const fileapi::FileSystemType kFileSystemType = fileapi::kFileSystemTypeTest;
+const storage::FileSystemType kFileSystemType = storage::kFileSystemTypeTest;
} // namespace
@@ -43,13 +43,13 @@ class LocalFileUtilTest : public testing::Test {
public:
LocalFileUtilTest() {}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
file_system_context_ = CreateFileSystemContextForTesting(
NULL, data_dir_.path());
}
- virtual void TearDown() {
+ void TearDown() override {
file_system_context_ = NULL;
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/content/browser/fileapi/mock_file_change_observer.cc b/chromium/content/browser/fileapi/mock_file_change_observer.cc
index c37f175d953..f6a86e964a0 100644
--- a/chromium/content/browser/fileapi/mock_file_change_observer.cc
+++ b/chromium/content/browser/fileapi/mock_file_change_observer.cc
@@ -4,7 +4,7 @@
#include "content/browser/fileapi/mock_file_change_observer.h"
-namespace fileapi {
+namespace storage {
MockFileChangeObserver::MockFileChangeObserver()
: create_file_count_(0),
@@ -48,4 +48,4 @@ void MockFileChangeObserver::OnRemoveDirectory(const FileSystemURL& url) {
remove_directory_count_++;
}
-} // namespace fileapi
+} // namespace storage
diff --git a/chromium/content/browser/fileapi/mock_file_change_observer.h b/chromium/content/browser/fileapi/mock_file_change_observer.h
index 4c1bcb2d1a4..3465a7a1f5d 100644
--- a/chromium/content/browser/fileapi/mock_file_change_observer.h
+++ b/chromium/content/browser/fileapi/mock_file_change_observer.h
@@ -7,29 +7,29 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "webkit/browser/fileapi/file_observers.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
+#include "storage/browser/fileapi/file_observers.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/task_runner_bound_observer_list.h"
-namespace fileapi {
+namespace storage {
// Mock file change observer.
class MockFileChangeObserver : public FileChangeObserver {
public:
MockFileChangeObserver();
- virtual ~MockFileChangeObserver();
+ ~MockFileChangeObserver() override;
// Creates a ChangeObserverList which only contains given |observer|.
static ChangeObserverList CreateList(MockFileChangeObserver* observer);
// FileChangeObserver overrides.
- virtual void OnCreateFile(const FileSystemURL& url) OVERRIDE;
- virtual void OnCreateFileFrom(const FileSystemURL& url,
- const FileSystemURL& src) OVERRIDE;
- virtual void OnRemoveFile(const FileSystemURL& url) OVERRIDE;
- virtual void OnModifyFile(const FileSystemURL& url) OVERRIDE;
- virtual void OnCreateDirectory(const FileSystemURL& url) OVERRIDE;
- virtual void OnRemoveDirectory(const FileSystemURL& url) OVERRIDE;
+ void OnCreateFile(const FileSystemURL& url) override;
+ void OnCreateFileFrom(const FileSystemURL& url,
+ const FileSystemURL& src) override;
+ void OnRemoveFile(const FileSystemURL& url) override;
+ void OnModifyFile(const FileSystemURL& url) override;
+ void OnCreateDirectory(const FileSystemURL& url) override;
+ void OnRemoveDirectory(const FileSystemURL& url) override;
void ResetCount() {
create_file_count_ = 0;
@@ -98,6 +98,6 @@ class MockFileChangeObserver : public FileChangeObserver {
DISALLOW_COPY_AND_ASSIGN(MockFileChangeObserver);
};
-} // namespace fileapi
+} // namespace storage
#endif // WEBKIT_BROWSER_FILEAPI_MOCK_FILE_CHANGE_OBSERVER_H_
diff --git a/chromium/content/browser/fileapi/mock_file_update_observer.cc b/chromium/content/browser/fileapi/mock_file_update_observer.cc
new file mode 100644
index 00000000000..2951d3ec77e
--- /dev/null
+++ b/chromium/content/browser/fileapi/mock_file_update_observer.cc
@@ -0,0 +1,42 @@
+// Copyright 2014 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/thread_task_runner_handle.h"
+#include "content/browser/fileapi/mock_file_update_observer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+
+MockFileUpdateObserver::MockFileUpdateObserver() : is_ready_(false) {
+}
+
+MockFileUpdateObserver::~MockFileUpdateObserver() {
+}
+
+// static
+UpdateObserverList MockFileUpdateObserver::CreateList(
+ MockFileUpdateObserver* observer) {
+ UpdateObserverList list;
+ return list.AddObserver(observer, base::ThreadTaskRunnerHandle::Get().get());
+}
+
+void MockFileUpdateObserver::OnStartUpdate(const FileSystemURL& url) {
+ if (is_ready_)
+ ++start_update_count_[url];
+}
+
+void MockFileUpdateObserver::OnUpdate(const FileSystemURL& url, int64 delta) {
+ if (!is_ready_)
+ return;
+ int start = start_update_count_[url];
+ int end = end_update_count_[url];
+ EXPECT_LT(0, start - end);
+}
+
+void MockFileUpdateObserver::OnEndUpdate(const FileSystemURL& url) {
+ if (is_ready_)
+ ++end_update_count_[url];
+}
+
+} // namespace storage
diff --git a/chromium/content/browser/fileapi/mock_file_update_observer.h b/chromium/content/browser/fileapi/mock_file_update_observer.h
new file mode 100644
index 00000000000..78aef9fae25
--- /dev/null
+++ b/chromium/content/browser/fileapi/mock_file_update_observer.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 WEBKIT_BROWSER_FILEAPI_MOCK_FILE_UPDATE_OBSERVER_H_
+#define WEBKIT_BROWSER_FILEAPI_MOCK_FILE_UPDATE_OBSERVER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "storage/browser/fileapi/file_observers.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/task_runner_bound_observer_list.h"
+
+namespace storage {
+
+// Mock file change observer.
+class MockFileUpdateObserver : public FileUpdateObserver {
+ public:
+ MockFileUpdateObserver();
+ ~MockFileUpdateObserver() override;
+
+ // Creates a ChangeObserverList which only contains given |observer|.
+ static UpdateObserverList CreateList(MockFileUpdateObserver* observer);
+
+ // FileUpdateObserver overrides.
+ void OnStartUpdate(const FileSystemURL& url) override;
+ void OnUpdate(const FileSystemURL& url, int64 delta) override;
+ void OnEndUpdate(const FileSystemURL& url) override;
+
+ void Enable() { is_ready_ = true; }
+
+ void Disable() {
+ start_update_count_.clear();
+ end_update_count_.clear();
+ is_ready_ = false;
+ }
+
+ private:
+ std::map<FileSystemURL, int, FileSystemURL::Comparator> start_update_count_;
+ std::map<FileSystemURL, int, FileSystemURL::Comparator> end_update_count_;
+ bool is_ready_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockFileUpdateObserver);
+};
+
+} // namespace storage
+
+#endif // WEBKIT_BROWSER_FILEAPI_MOCK_FILE_UPDATE_OBSERVER_H_
diff --git a/chromium/content/browser/fileapi/mock_url_request_delegate.h b/chromium/content/browser/fileapi/mock_url_request_delegate.h
index 137b11426e8..a628f6ea5a4 100644
--- a/chromium/content/browser/fileapi/mock_url_request_delegate.h
+++ b/chromium/content/browser/fileapi/mock_url_request_delegate.h
@@ -17,11 +17,10 @@ namespace content {
class MockURLRequestDelegate : public net::URLRequest::Delegate {
public:
MockURLRequestDelegate();
- virtual ~MockURLRequestDelegate();
+ ~MockURLRequestDelegate() override;
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
- virtual void OnReadCompleted(net::URLRequest* request,
- int bytes_read) OVERRIDE;
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
const std::string& response_data() const { return response_data_; }
private:
diff --git a/chromium/content/browser/fileapi/native_file_util_unittest.cc b/chromium/content/browser/fileapi/native_file_util_unittest.cc
index e20914d6610..85aadb672f7 100644
--- a/chromium/content/browser/fileapi/native_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/native_file_util_unittest.cc
@@ -4,16 +4,16 @@
#include <set>
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "storage/browser/fileapi/native_file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/native_file_util.h"
-using fileapi::FileSystemFileUtil;
-using fileapi::FileSystemOperation;
-using fileapi::NativeFileUtil;
+using storage::FileSystemFileUtil;
+using storage::FileSystemOperation;
+using storage::NativeFileUtil;
namespace content {
@@ -21,9 +21,7 @@ class NativeFileUtilTest : public testing::Test {
public:
NativeFileUtilTest() {}
- virtual void SetUp() {
- ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- }
+ void SetUp() override { ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); }
protected:
base::FilePath Path() {
diff --git a/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc b/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
index 089cef8d73d..cef39901405 100644
--- a/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/obfuscated_file_util_unittest.cc
@@ -7,9 +7,9 @@
#include <vector>
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
@@ -19,31 +19,31 @@
#include "content/public/test/sandbox_file_system_test_helper.h"
#include "content/public/test/test_file_system_context.h"
#include "content/test/fileapi_test_file_set.h"
+#include "storage/browser/fileapi/external_mount_points.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_usage_cache.h"
+#include "storage/browser/fileapi/obfuscated_file_util.h"
+#include "storage/browser/fileapi/sandbox_directory_database.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
+#include "storage/browser/fileapi/sandbox_origin_database.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/common/database/database_identifier.h"
+#include "storage/common/quota/quota_types.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/external_mount_points.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/obfuscated_file_util.h"
-#include "webkit/browser/fileapi/sandbox_directory_database.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
-#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
-#include "webkit/browser/fileapi/sandbox_origin_database.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/database/database_identifier.h"
-#include "webkit/common/quota/quota_types.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemOperation;
-using fileapi::FileSystemOperationContext;
-using fileapi::FileSystemURL;
-using fileapi::ObfuscatedFileUtil;
-using fileapi::SandboxDirectoryDatabase;
-using fileapi::SandboxIsolatedOriginDatabase;
-using fileapi::kFileSystemTypeTemporary;
-using fileapi::kFileSystemTypePersistent;
+using storage::FileSystemContext;
+using storage::FileSystemOperation;
+using storage::FileSystemOperationContext;
+using storage::FileSystemURL;
+using storage::ObfuscatedFileUtil;
+using storage::SandboxDirectoryDatabase;
+using storage::SandboxIsolatedOriginDatabase;
+using storage::kFileSystemTypeTemporary;
+using storage::kFileSystemTypePersistent;
namespace content {
@@ -121,16 +121,17 @@ FileSystemURL FileSystemURLAppendUTF8(
FileSystemURL FileSystemURLDirName(const FileSystemURL& url) {
return FileSystemURL::CreateForTest(
- url.origin(), url.mount_type(),
- fileapi::VirtualPath::DirName(url.virtual_path()));
+ url.origin(),
+ url.mount_type(),
+ storage::VirtualPath::DirName(url.virtual_path()));
}
-std::string GetTypeString(fileapi::FileSystemType type) {
- return fileapi::SandboxFileSystemBackendDelegate::GetTypeString(type);
+std::string GetTypeString(storage::FileSystemType type) {
+ return storage::SandboxFileSystemBackendDelegate::GetTypeString(type);
}
bool HasFileSystemType(ObfuscatedFileUtil::AbstractOriginEnumerator* enumerator,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
return enumerator->HasTypeDirectory(GetTypeString(type));
}
@@ -144,24 +145,23 @@ class ObfuscatedFileUtilTest : public testing::Test {
public:
ObfuscatedFileUtilTest()
: origin_(GURL("http://www.example.com")),
- type_(fileapi::kFileSystemTypeTemporary),
+ type_(storage::kFileSystemTypeTemporary),
weak_factory_(this),
sandbox_file_system_(origin_, type_),
- quota_status_(quota::kQuotaStatusUnknown),
- usage_(-1) {
- }
+ quota_status_(storage::kQuotaStatusUnknown),
+ usage_(-1) {}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
storage_policy_ = new MockSpecialStoragePolicy();
quota_manager_ =
- new quota::QuotaManager(false /* is_incognito */,
- data_dir_.path(),
- base::MessageLoopProxy::current().get(),
- base::MessageLoopProxy::current().get(),
- storage_policy_.get());
+ new storage::QuotaManager(false /* is_incognito */,
+ data_dir_.path(),
+ base::MessageLoopProxy::current().get(),
+ base::MessageLoopProxy::current().get(),
+ storage_policy_.get());
// Every time we create a new sandbox_file_system helper,
// it creates another context, which creates another path manager,
@@ -173,11 +173,11 @@ class ObfuscatedFileUtilTest : public testing::Test {
sandbox_file_system_.SetUp(file_system_context_.get());
- change_observers_ = fileapi::MockFileChangeObserver::CreateList(
- &change_observer_);
+ change_observers_ =
+ storage::MockFileChangeObserver::CreateList(&change_observer_);
}
- virtual void TearDown() {
+ void TearDown() override {
quota_manager_ = NULL;
sandbox_file_system_.TearDown();
}
@@ -208,11 +208,11 @@ class ObfuscatedFileUtilTest : public testing::Test {
return context;
}
- const fileapi::ChangeObserverList& change_observers() const {
+ const storage::ChangeObserverList& change_observers() const {
return change_observers_;
}
- fileapi::MockFileChangeObserver* change_observer() {
+ storage::MockFileChangeObserver* change_observer() {
return &change_observer_;
}
@@ -220,8 +220,8 @@ class ObfuscatedFileUtilTest : public testing::Test {
// and obfuscated_file_util_.
// Use this for tests which need to run in multiple origins; we need a test
// helper per origin.
- SandboxFileSystemTestHelper* NewFileSystem(
- const GURL& origin, fileapi::FileSystemType type) {
+ SandboxFileSystemTestHelper* NewFileSystem(const GURL& origin,
+ storage::FileSystemType type) {
SandboxFileSystemTestHelper* file_system =
new SandboxFileSystemTestHelper(origin, type);
@@ -230,7 +230,7 @@ class ObfuscatedFileUtilTest : public testing::Test {
}
scoped_ptr<ObfuscatedFileUtil> CreateObfuscatedFileUtil(
- quota::SpecialStoragePolicy* storage_policy) {
+ storage::SpecialStoragePolicy* storage_policy) {
return scoped_ptr<ObfuscatedFileUtil>(
ObfuscatedFileUtil::CreateForTesting(
storage_policy, data_dir_path(), NULL,
@@ -249,9 +249,7 @@ class ObfuscatedFileUtilTest : public testing::Test {
return origin_;
}
- fileapi::FileSystemType type() const {
- return type_;
- }
+ storage::FileSystemType type() const { return type_; }
std::string type_string() const {
return GetTypeString(type_);
@@ -270,7 +268,7 @@ class ObfuscatedFileUtilTest : public testing::Test {
sandbox_file_system_.type(),
&usage_,
&quota);
- EXPECT_EQ(quota::kQuotaStatusOk, quota_status_);
+ EXPECT_EQ(storage::kQuotaStatusOk, quota_status_);
}
void RevokeUsageCache() {
@@ -303,7 +301,7 @@ class ObfuscatedFileUtilTest : public testing::Test {
}
int64 usage() const { return usage_; }
- fileapi::FileSystemUsageCache* usage_cache() {
+ storage::FileSystemUsageCache* usage_cache() {
return sandbox_file_system_.usage_cache();
}
@@ -440,7 +438,7 @@ class ObfuscatedFileUtilTest : public testing::Test {
std::set<base::FilePath::StringType>* files,
std::set<base::FilePath::StringType>* directories) {
scoped_ptr<FileSystemOperationContext> context;
- std::vector<fileapi::DirectoryEntry> entries;
+ std::vector<storage::DirectoryEntry> entries;
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::ReadDirectory(file_system_context(),
root_url, &entries));
@@ -482,17 +480,17 @@ class ObfuscatedFileUtilTest : public testing::Test {
FillTestDirectory(root_url, &files, &directories);
scoped_ptr<FileSystemOperationContext> context;
- std::vector<fileapi::DirectoryEntry> entries;
+ std::vector<storage::DirectoryEntry> entries;
context.reset(NewContext(NULL));
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::ReadDirectory(
file_system_context(), root_url, &entries));
- std::vector<fileapi::DirectoryEntry>::iterator entry_iter;
+ std::vector<storage::DirectoryEntry>::iterator entry_iter;
EXPECT_EQ(files.size() + directories.size(), entries.size());
EXPECT_TRUE(change_observer()->HasNoChange());
for (entry_iter = entries.begin(); entry_iter != entries.end();
++entry_iter) {
- const fileapi::DirectoryEntry& entry = *entry_iter;
+ const storage::DirectoryEntry& entry = *entry_iter;
std::set<base::FilePath::StringType>::iterator iter =
files.find(entry.name);
if (iter != files.end()) {
@@ -711,8 +709,8 @@ class ObfuscatedFileUtilTest : public testing::Test {
ASSERT_TRUE(db != NULL);
// Destory it.
- ASSERT_TRUE(file_util->DestroyDirectoryDatabase(
- url.origin(), GetTypeString(url.type())));
+ file_util->DestroyDirectoryDatabase(
+ url.origin(), GetTypeString(url.type()));
ASSERT_TRUE(file_util->directories_.empty());
}
@@ -745,8 +743,7 @@ class ObfuscatedFileUtilTest : public testing::Test {
// Initialize the directory with one origin using
// SandboxIsolatedOriginDatabase.
{
- std::string origin_string =
- webkit_database::GetIdentifierFromOrigin(origin_);
+ std::string origin_string = storage::GetIdentifierFromOrigin(origin_);
SandboxIsolatedOriginDatabase database_old(
origin_string, data_dir_path(),
base::FilePath(
@@ -799,18 +796,18 @@ class ObfuscatedFileUtilTest : public testing::Test {
protected:
base::ScopedTempDir data_dir_;
- base::MessageLoop message_loop_;
+ base::MessageLoopForIO message_loop_;
scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
- scoped_refptr<quota::QuotaManager> quota_manager_;
+ scoped_refptr<storage::QuotaManager> quota_manager_;
scoped_refptr<FileSystemContext> file_system_context_;
GURL origin_;
- fileapi::FileSystemType type_;
+ storage::FileSystemType type_;
base::WeakPtrFactory<ObfuscatedFileUtilTest> weak_factory_;
SandboxFileSystemTestHelper sandbox_file_system_;
- quota::QuotaStatusCode quota_status_;
+ storage::QuotaStatusCode quota_status_;
int64 usage_;
- fileapi::MockFileChangeObserver change_observer_;
- fileapi::ChangeObserverList change_observers_;
+ storage::MockFileChangeObserver change_observer_;
+ storage::ChangeObserverList change_observers_;
private:
DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest);
@@ -1217,7 +1214,7 @@ TEST_F(ObfuscatedFileUtilTest, TestReadDirectoryOnFile) {
ofu()->EnsureFileExists(context.get(), url, &created));
ASSERT_TRUE(created);
- std::vector<fileapi::DirectoryEntry> entries;
+ std::vector<storage::DirectoryEntry> entries;
EXPECT_EQ(base::File::FILE_ERROR_NOT_A_DIRECTORY,
AsyncFileTestHelper::ReadDirectory(file_system_context(), url,
&entries));
@@ -1787,7 +1784,7 @@ TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
const FileSystemURL empty_path = CreateURL(base::FilePath());
scoped_ptr<FileSystemOperationContext> context;
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPath); ++i) {
+ for (size_t i = 0; i < arraysize(kPath); ++i) {
bool created = false;
context.reset(NewContext(NULL));
EXPECT_EQ(base::File::FILE_OK,
@@ -1795,7 +1792,7 @@ TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
EXPECT_TRUE(created);
}
- std::vector<fileapi::DirectoryEntry> entries;
+ std::vector<storage::DirectoryEntry> entries;
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::ReadDirectory(
file_system_context(), empty_path, &entries));
@@ -1810,7 +1807,7 @@ TEST_F(ObfuscatedFileUtilTest, TestIncompleteDirectoryReading) {
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::ReadDirectory(
file_system_context(), empty_path, &entries));
- EXPECT_EQ(ARRAYSIZE_UNSAFE(kPath) - 1, entries.size());
+ EXPECT_EQ(arraysize(kPath) - 1, entries.size());
}
TEST_F(ObfuscatedFileUtilTest, TestDirectoryTimestampForCreation) {
@@ -2040,7 +2037,7 @@ TEST_F(ObfuscatedFileUtilTest, TestFileEnumeratorTimestamp) {
base::Time()));
context.reset(NewContext(NULL));
- scoped_ptr<fileapi::FileSystemFileUtil::AbstractFileEnumerator> file_enum(
+ scoped_ptr<storage::FileSystemFileUtil::AbstractFileEnumerator> file_enum(
ofu()->CreateFileEnumerator(context.get(), dir, false));
int count = 0;
@@ -2190,7 +2187,6 @@ TEST_F(ObfuscatedFileUtilTest, TestQuotaOnMoveFile) {
from_file, from_file_size));
ASSERT_EQ(expected_total_file_size, ComputeTotalFileSize());
- int64 to_file_size ALLOW_UNUSED = from_file_size;
from_file_size = 0;
ASSERT_EQ(base::File::FILE_OK,
ofu()->CopyOrMoveFile(
@@ -2453,4 +2449,123 @@ TEST_F(ObfuscatedFileUtilTest, CreateDirectory_NotADirectoryInRecursive) {
true /* recursive */));
}
+TEST_F(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType) {
+ const GURL origin1("http://www.example.com:12");
+ const GURL origin2("http://www.example.com:1234");
+
+ // Create origin directories.
+ scoped_ptr<SandboxFileSystemTestHelper> fs1(
+ NewFileSystem(origin1, kFileSystemTypeTemporary));
+ scoped_ptr<SandboxFileSystemTestHelper> fs2(
+ NewFileSystem(origin1, kFileSystemTypePersistent));
+ scoped_ptr<SandboxFileSystemTestHelper> fs3(
+ NewFileSystem(origin2, kFileSystemTypeTemporary));
+ scoped_ptr<SandboxFileSystemTestHelper> fs4(
+ NewFileSystem(origin2, kFileSystemTypePersistent));
+
+ // Make sure directories for origin1 exist.
+ base::File::Error error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Make sure directories for origin2 exist.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Delete a directory for origin1's persistent filesystem.
+ ofu()->DeleteDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypePersistent));
+
+ // The directory for origin1's temporary filesystem should not be removed.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // The directory for origin1's persistent filesystem should be removed.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
+
+ // The directories for origin2 should not be removed.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+}
+
+TEST_F(ObfuscatedFileUtilTest, DeleteDirectoryForOriginAndType_DeleteAll) {
+ const GURL origin1("http://www.example.com:12");
+ const GURL origin2("http://www.example.com:1234");
+
+ // Create origin directories.
+ scoped_ptr<SandboxFileSystemTestHelper> fs1(
+ NewFileSystem(origin1, kFileSystemTypeTemporary));
+ scoped_ptr<SandboxFileSystemTestHelper> fs2(
+ NewFileSystem(origin1, kFileSystemTypePersistent));
+ scoped_ptr<SandboxFileSystemTestHelper> fs3(
+ NewFileSystem(origin2, kFileSystemTypeTemporary));
+ scoped_ptr<SandboxFileSystemTestHelper> fs4(
+ NewFileSystem(origin2, kFileSystemTypePersistent));
+
+ // Make sure directories for origin1 exist.
+ base::File::Error error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Make sure directories for origin2 exist.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Delete all directories for origin1.
+ ofu()->DeleteDirectoryForOriginAndType(origin1, std::string());
+
+ // The directories for origin1 should be removed.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin1, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_ERROR_NOT_FOUND, error);
+
+ // The directories for origin2 should not be removed.
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypeTemporary), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+ error = base::File::FILE_ERROR_FAILED;
+ ofu()->GetDirectoryForOriginAndType(
+ origin2, GetTypeString(kFileSystemTypePersistent), false, &error);
+ ASSERT_EQ(base::File::FILE_OK, error);
+}
+
} // namespace content
diff --git a/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc b/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc
index 08fb9e0fbc7..ef88fed2f83 100644
--- a/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc
+++ b/chromium/content/browser/fileapi/plugin_private_file_system_backend_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/basictypes.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
@@ -12,26 +12,27 @@
#include "content/public/test/async_file_test_helper.h"
#include "content/public/test/test_file_system_context.h"
#include "content/public/test/test_file_system_options.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/browser/fileapi/obfuscated_file_util.h"
+#include "storage/browser/fileapi/plugin_private_file_system_backend.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/obfuscated_file_util.h"
-#include "webkit/browser/fileapi/plugin_private_file_system_backend.h"
-#include "webkit/common/fileapi/file_system_util.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemURL;
-using fileapi::IsolatedContext;
+using storage::FileSystemContext;
+using storage::FileSystemURL;
+using storage::IsolatedContext;
namespace content {
namespace {
-const GURL kOrigin("http://www.example.com");
+const GURL kOrigin1("http://www.example.com");
+const GURL kOrigin2("https://www.example.com");
const std::string kPlugin1("plugin1");
const std::string kPlugin2("plugin2");
-const fileapi::FileSystemType kType = fileapi::kFileSystemTypePluginPrivate;
+const storage::FileSystemType kType = storage::kFileSystemTypePluginPrivate;
const std::string kRootName = "pluginprivate";
void DidOpenFileSystem(base::File::Error* error_out,
@@ -48,7 +49,7 @@ std::string RegisterFileSystem() {
class PluginPrivateFileSystemBackendTest : public testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
context_ = CreateFileSystemContextForTesting(
NULL /* quota_manager_proxy */,
@@ -63,7 +64,7 @@ class PluginPrivateFileSystemBackendTest : public testing::Test {
root.virtual_path().AppendASCII(relative));
}
- fileapi::PluginPrivateFileSystemBackend* backend() const {
+ storage::PluginPrivateFileSystemBackend* backend() const {
return context_->plugin_private_backend();
}
@@ -72,15 +73,20 @@ class PluginPrivateFileSystemBackendTest : public testing::Test {
base::ScopedTempDir data_dir_;
base::MessageLoop message_loop_;
scoped_refptr<FileSystemContext> context_;
- std::string filesystem_id_;
};
+// TODO(kinuko,nhiroki): There are a lot of duplicate code in these tests. Write
+// helper functions to simplify the tests.
+
TEST_F(PluginPrivateFileSystemBackendTest, OpenFileSystemBasic) {
const std::string filesystem_id1 = RegisterFileSystem();
base::File::Error error = base::File::FILE_ERROR_FAILED;
backend()->OpenPrivateFileSystem(
- kOrigin, kType, filesystem_id1, kPlugin1,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ kOrigin1,
+ kType,
+ filesystem_id1,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&DidOpenFileSystem, &error));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::File::FILE_OK, error);
@@ -89,15 +95,17 @@ TEST_F(PluginPrivateFileSystemBackendTest, OpenFileSystemBasic) {
const std::string filesystem_id2 = RegisterFileSystem();
error = base::File::FILE_ERROR_FAILED;
backend()->OpenPrivateFileSystem(
- kOrigin, kType, filesystem_id2, kPlugin1,
- fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ kOrigin1,
+ kType,
+ filesystem_id2,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
base::Bind(&DidOpenFileSystem, &error));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::File::FILE_OK, error);
- const GURL root_url(
- fileapi::GetIsolatedFileSystemRootURIString(
- kOrigin, filesystem_id1, kRootName));
+ const GURL root_url(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin1, filesystem_id1, kRootName));
FileSystemURL file = CreateURL(root_url, "foo");
base::FilePath platform_path;
EXPECT_EQ(base::File::FILE_OK,
@@ -114,8 +122,11 @@ TEST_F(PluginPrivateFileSystemBackendTest, PluginIsolation) {
const std::string filesystem_id1 = RegisterFileSystem();
base::File::Error error = base::File::FILE_ERROR_FAILED;
backend()->OpenPrivateFileSystem(
- kOrigin, kType, filesystem_id1, kPlugin1,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ kOrigin1,
+ kType,
+ filesystem_id1,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&DidOpenFileSystem, &error));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::File::FILE_OK, error);
@@ -123,33 +134,157 @@ TEST_F(PluginPrivateFileSystemBackendTest, PluginIsolation) {
const std::string filesystem_id2 = RegisterFileSystem();
error = base::File::FILE_ERROR_FAILED;
backend()->OpenPrivateFileSystem(
- kOrigin, kType, filesystem_id2, kPlugin2,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ kOrigin1,
+ kType,
+ filesystem_id2,
+ kPlugin2,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&DidOpenFileSystem, &error));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::File::FILE_OK, error);
// Create 'foo' in kPlugin1.
- const GURL root_url1(
- fileapi::GetIsolatedFileSystemRootURIString(
- kOrigin, filesystem_id1, kRootName));
+ const GURL root_url1(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin1, filesystem_id1, kRootName));
FileSystemURL file1 = CreateURL(root_url1, "foo");
- base::FilePath platform_path;
EXPECT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::CreateFile(context_.get(), file1));
EXPECT_TRUE(AsyncFileTestHelper::FileExists(
context_.get(), file1, AsyncFileTestHelper::kDontCheckSize));
// See the same path is not available in kPlugin2.
- const GURL root_url2(
- fileapi::GetIsolatedFileSystemRootURIString(
- kOrigin, filesystem_id2, kRootName));
+ const GURL root_url2(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin1, filesystem_id2, kRootName));
FileSystemURL file2 = CreateURL(root_url2, "foo");
EXPECT_FALSE(AsyncFileTestHelper::FileExists(
context_.get(), file2, AsyncFileTestHelper::kDontCheckSize));
}
-// TODO(kinuko,nhiroki): also test if DeleteOriginDataOnFileThread
-// works fine when there's multiple plugin partitions.
+TEST_F(PluginPrivateFileSystemBackendTest, OriginIsolation) {
+ // Open filesystem for kOrigin1 and kOrigin2.
+ const std::string filesystem_id1 = RegisterFileSystem();
+ base::File::Error error = base::File::FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin1,
+ kType,
+ filesystem_id1,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ const std::string filesystem_id2 = RegisterFileSystem();
+ error = base::File::FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin2,
+ kType,
+ filesystem_id2,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Create 'foo' in kOrigin1.
+ const GURL root_url1(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin1, filesystem_id1, kRootName));
+ FileSystemURL file1 = CreateURL(root_url1, "foo");
+ EXPECT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::CreateFile(context_.get(), file1));
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file1, AsyncFileTestHelper::kDontCheckSize));
+
+ // See the same path is not available in kOrigin2.
+ const GURL root_url2(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin2, filesystem_id2, kRootName));
+ FileSystemURL file2 = CreateURL(root_url2, "foo");
+ EXPECT_FALSE(AsyncFileTestHelper::FileExists(
+ context_.get(), file2, AsyncFileTestHelper::kDontCheckSize));
+}
+
+TEST_F(PluginPrivateFileSystemBackendTest, DeleteOriginDirectory) {
+ // Open filesystem for kOrigin1 and kOrigin2.
+ const std::string filesystem_id1 = RegisterFileSystem();
+ base::File::Error error = base::File::FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin1,
+ kType,
+ filesystem_id1,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ const std::string filesystem_id2 = RegisterFileSystem();
+ error = base::File::FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin2,
+ kType,
+ filesystem_id2,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Create 'foo' in kOrigin1.
+ const GURL root_url1(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin1, filesystem_id1, kRootName));
+ FileSystemURL file1 = CreateURL(root_url1, "foo");
+ EXPECT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::CreateFile(context_.get(), file1));
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file1, AsyncFileTestHelper::kDontCheckSize));
+
+ // Create 'foo' in kOrigin2.
+ const GURL root_url2(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin2, filesystem_id2, kRootName));
+ FileSystemURL file2 = CreateURL(root_url2, "foo");
+ EXPECT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::CreateFile(context_.get(), file2));
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file2, AsyncFileTestHelper::kDontCheckSize));
+
+ // Delete data for kOrigin1.
+ error = backend()->DeleteOriginDataOnFileTaskRunner(
+ context_.get(), NULL, kOrigin1, kType);
+ EXPECT_EQ(base::File::FILE_OK, error);
+
+ // Confirm 'foo' in kOrigin1 is deleted.
+ EXPECT_FALSE(AsyncFileTestHelper::FileExists(
+ context_.get(), file1, AsyncFileTestHelper::kDontCheckSize));
+
+ // Confirm 'foo' in kOrigin2 is NOT deleted.
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file2, AsyncFileTestHelper::kDontCheckSize));
+
+ // Re-open filesystem for kOrigin1.
+ const std::string filesystem_id3 = RegisterFileSystem();
+ error = base::File::FILE_ERROR_FAILED;
+ backend()->OpenPrivateFileSystem(
+ kOrigin1,
+ kType,
+ filesystem_id3,
+ kPlugin1,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ base::Bind(&DidOpenFileSystem, &error));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(base::File::FILE_OK, error);
+
+ // Re-create 'foo' in kOrigin1.
+ const GURL root_url3(storage::GetIsolatedFileSystemRootURIString(
+ kOrigin1, filesystem_id3, kRootName));
+ FileSystemURL file3 = CreateURL(root_url3, "foo");
+ EXPECT_EQ(base::File::FILE_OK,
+ AsyncFileTestHelper::CreateFile(context_.get(), file3));
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file3, AsyncFileTestHelper::kDontCheckSize));
+
+ // Confirm 'foo' in kOrigin1 is re-created.
+ EXPECT_TRUE(AsyncFileTestHelper::FileExists(
+ context_.get(), file3, AsyncFileTestHelper::kDontCheckSize));
+}
} // namespace content
diff --git a/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc b/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
index a96a21213a2..38853844628 100644
--- a/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
+++ b/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/recursive_operation_delegate.h"
+#include "storage/browser/fileapi/recursive_operation_delegate.h"
#include <vector>
@@ -14,19 +14,19 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "content/public/test/sandbox_file_system_test_helper.h"
+#include "storage/browser/fileapi/file_system_file_util.h"
+#include "storage/browser/fileapi/file_system_operation.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_file_util.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-using fileapi::FileSystemContext;
-using fileapi::FileSystemOperationContext;
-using fileapi::FileSystemURL;
+using storage::FileSystemContext;
+using storage::FileSystemOperationContext;
+using storage::FileSystemURL;
namespace content {
namespace {
-class LoggingRecursiveOperation : public fileapi::RecursiveOperationDelegate {
+class LoggingRecursiveOperation : public storage::RecursiveOperationDelegate {
public:
struct LogEntry {
enum Type {
@@ -41,26 +41,21 @@ class LoggingRecursiveOperation : public fileapi::RecursiveOperationDelegate {
LoggingRecursiveOperation(FileSystemContext* file_system_context,
const FileSystemURL& root,
const StatusCallback& callback)
- : fileapi::RecursiveOperationDelegate(file_system_context),
+ : storage::RecursiveOperationDelegate(file_system_context),
root_(root),
callback_(callback),
- weak_factory_(this) {
- }
- virtual ~LoggingRecursiveOperation() {}
+ weak_factory_(this) {}
+ ~LoggingRecursiveOperation() override {}
const std::vector<LogEntry>& log_entries() const { return log_entries_; }
// RecursiveOperationDelegate overrides.
- virtual void Run() OVERRIDE {
- NOTREACHED();
- }
+ void Run() override { NOTREACHED(); }
- virtual void RunRecursively() OVERRIDE {
- StartRecursiveOperation(root_, callback_);
- }
+ void RunRecursively() override { StartRecursiveOperation(root_, callback_); }
- virtual void ProcessFile(const FileSystemURL& url,
- const StatusCallback& callback) OVERRIDE {
+ void ProcessFile(const FileSystemURL& url,
+ const StatusCallback& callback) override {
RecordLogEntry(LogEntry::PROCESS_FILE, url);
operation_runner()->GetMetadata(
url,
@@ -68,14 +63,14 @@ class LoggingRecursiveOperation : public fileapi::RecursiveOperationDelegate {
weak_factory_.GetWeakPtr(), callback));
}
- virtual void ProcessDirectory(const FileSystemURL& url,
- const StatusCallback& callback) OVERRIDE {
+ void ProcessDirectory(const FileSystemURL& url,
+ const StatusCallback& callback) override {
RecordLogEntry(LogEntry::PROCESS_DIRECTORY, url);
callback.Run(base::File::FILE_OK);
}
- virtual void PostProcessDirectory(const FileSystemURL& url,
- const StatusCallback& callback) OVERRIDE {
+ void PostProcessDirectory(const FileSystemURL& url,
+ const StatusCallback& callback) override {
RecordLogEntry(LogEntry::POST_PROCESS_DIRECTORY, url);
callback.Run(base::File::FILE_OK);
}
@@ -117,7 +112,7 @@ void ReportStatus(base::File::Error* out_error,
// To test the Cancel() during operation, calls Cancel() of |operation|
// after |counter| times message posting.
-void CallCancelLater(fileapi::RecursiveOperationDelegate* operation,
+void CallCancelLater(storage::RecursiveOperationDelegate* operation,
int counter) {
if (counter > 0) {
base::MessageLoopProxy::current()->PostTask(
@@ -133,14 +128,12 @@ void CallCancelLater(fileapi::RecursiveOperationDelegate* operation,
class RecursiveOperationDelegateTest : public testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
EXPECT_TRUE(base_.CreateUniqueTempDir());
sandbox_file_system_.SetUp(base_.path().AppendASCII("filesystem"));
}
- virtual void TearDown() OVERRIDE {
- sandbox_file_system_.TearDown();
- }
+ void TearDown() override { sandbox_file_system_.TearDown(); }
scoped_ptr<FileSystemOperationContext> NewContext() {
FileSystemOperationContext* context =
@@ -150,7 +143,7 @@ class RecursiveOperationDelegateTest : public testing::Test {
return make_scoped_ptr(context);
}
- fileapi::FileSystemFileUtil* file_util() {
+ storage::FileSystemFileUtil* file_util() {
return sandbox_file_system_.file_util();
}
diff --git a/chromium/content/browser/fileapi/sandbox_database_test_helper.cc b/chromium/content/browser/fileapi/sandbox_database_test_helper.cc
index 3e295679590..205b653e370 100644
--- a/chromium/content/browser/fileapi/sandbox_database_test_helper.cc
+++ b/chromium/content/browser/fileapi/sandbox_database_test_helper.cc
@@ -8,14 +8,14 @@
#include <functional>
#include <vector>
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/stl_util.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/fileapi/file_system_util.h"
-using fileapi::FilePathToString;
+using storage::FilePathToString;
namespace content {
diff --git a/chromium/content/browser/fileapi/sandbox_directory_database_unittest.cc b/chromium/content/browser/fileapi/sandbox_directory_database_unittest.cc
index 6bc3c5669fa..dcb74a272c2 100644
--- a/chromium/content/browser/fileapi/sandbox_directory_database_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_directory_database_unittest.cc
@@ -2,26 +2,26 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/sandbox_directory_database.h"
+#include "storage/browser/fileapi/sandbox_directory_database.h"
#include <math.h>
#include <limits>
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "content/browser/fileapi/sandbox_database_test_helper.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
-#include "webkit/common/fileapi/file_system_util.h"
#define FPL(x) FILE_PATH_LITERAL(x)
-using fileapi::FilePathToString;
-using fileapi::SandboxDirectoryDatabase;
+using storage::FilePathToString;
+using storage::SandboxDirectoryDatabase;
namespace content {
diff --git a/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc b/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
index 935f6ce2fe4..1b5b19b122c 100644
--- a/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_file_system_backend_delegate_unittest.cc
@@ -2,20 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
#include "base/basictypes.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "content/public/test/test_file_system_options.h"
+#include "storage/browser/fileapi/file_system_url.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-using fileapi::FileSystemURL;
+using storage::FileSystemURL;
namespace content {
@@ -23,8 +23,9 @@ namespace {
FileSystemURL CreateFileSystemURL(const char* path) {
const GURL kOrigin("http://foo/");
- return fileapi::FileSystemURL::CreateForTest(
- kOrigin, fileapi::kFileSystemTypeTemporary,
+ return storage::FileSystemURL::CreateForTest(
+ kOrigin,
+ storage::kFileSystemTypeTemporary,
base::FilePath::FromUTF8Unsafe(path));
}
@@ -32,9 +33,9 @@ FileSystemURL CreateFileSystemURL(const char* path) {
class SandboxFileSystemBackendDelegateTest : public testing::Test {
protected:
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
- delegate_.reset(new fileapi::SandboxFileSystemBackendDelegate(
+ delegate_.reset(new storage::SandboxFileSystemBackendDelegate(
NULL /* quota_manager_proxy */,
base::MessageLoopProxy::current().get(),
data_dir_.path(),
@@ -48,7 +49,7 @@ class SandboxFileSystemBackendDelegateTest : public testing::Test {
base::ScopedTempDir data_dir_;
base::MessageLoop message_loop_;
- scoped_ptr<fileapi::SandboxFileSystemBackendDelegate> delegate_;
+ scoped_ptr<storage::SandboxFileSystemBackendDelegate> delegate_;
};
TEST_F(SandboxFileSystemBackendDelegateTest, IsAccessValid) {
@@ -60,9 +61,9 @@ TEST_F(SandboxFileSystemBackendDelegateTest, IsAccessValid) {
// Access from non-allowed scheme should be disallowed.
EXPECT_FALSE(IsAccessValid(
- FileSystemURL::CreateForTest(
- GURL("unknown://bar"), fileapi::kFileSystemTypeTemporary,
- base::FilePath::FromUTF8Unsafe("foo"))));
+ FileSystemURL::CreateForTest(GURL("unknown://bar"),
+ storage::kFileSystemTypeTemporary,
+ base::FilePath::FromUTF8Unsafe("foo"))));
// Access with restricted name should be disallowed.
EXPECT_FALSE(IsAccessValid(CreateFileSystemURL(".")));
diff --git a/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc b/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc
index eda34612be8..efa7259fd44 100644
--- a/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_file_system_backend_unittest.cc
@@ -2,27 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend.h"
#include <set>
#include "base/basictypes.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "content/public/test/test_file_system_options.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend_delegate.h"
-#include "webkit/common/fileapi/file_system_util.h"
-using fileapi::FileSystemURL;
-using fileapi::SandboxFileSystemBackend;
-using fileapi::SandboxFileSystemBackendDelegate;
+using storage::FileSystemURL;
+using storage::SandboxFileSystemBackend;
+using storage::SandboxFileSystemBackendDelegate;
// PS stands for path separator.
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
@@ -36,38 +36,28 @@ namespace content {
namespace {
const struct RootPathTest {
- fileapi::FileSystemType type;
+ storage::FileSystemType type;
const char* origin_url;
const char* expected_path;
} kRootPathTestCases[] = {
- { fileapi::kFileSystemTypeTemporary, "http://foo:1/",
- "000" PS "t" },
- { fileapi::kFileSystemTypePersistent, "http://foo:1/",
- "000" PS "p" },
- { fileapi::kFileSystemTypeTemporary, "http://bar.com/",
- "001" PS "t" },
- { fileapi::kFileSystemTypePersistent, "http://bar.com/",
- "001" PS "p" },
- { fileapi::kFileSystemTypeTemporary, "https://foo:2/",
- "002" PS "t" },
- { fileapi::kFileSystemTypePersistent, "https://foo:2/",
- "002" PS "p" },
- { fileapi::kFileSystemTypeTemporary, "https://bar.com/",
- "003" PS "t" },
- { fileapi::kFileSystemTypePersistent, "https://bar.com/",
- "003" PS "p" },
+ {storage::kFileSystemTypeTemporary, "http://foo:1/", "000" PS "t"},
+ {storage::kFileSystemTypePersistent, "http://foo:1/", "000" PS "p"},
+ {storage::kFileSystemTypeTemporary, "http://bar.com/", "001" PS "t"},
+ {storage::kFileSystemTypePersistent, "http://bar.com/", "001" PS "p"},
+ {storage::kFileSystemTypeTemporary, "https://foo:2/", "002" PS "t"},
+ {storage::kFileSystemTypePersistent, "https://foo:2/", "002" PS "p"},
+ {storage::kFileSystemTypeTemporary, "https://bar.com/", "003" PS "t"},
+ {storage::kFileSystemTypePersistent, "https://bar.com/", "003" PS "p"},
};
const struct RootPathFileURITest {
- fileapi::FileSystemType type;
+ storage::FileSystemType type;
const char* origin_url;
const char* expected_path;
const char* virtual_path;
} kRootPathFileURITestCases[] = {
- { fileapi::kFileSystemTypeTemporary, "file:///",
- "000" PS "t", NULL },
- { fileapi::kFileSystemTypePersistent, "file:///",
- "000" PS "p", NULL },
+ {storage::kFileSystemTypeTemporary, "file:///", "000" PS "t", NULL},
+ {storage::kFileSystemTypePersistent, "file:///", "000" PS "p", NULL},
};
void DidOpenFileSystem(base::File::Error* error_out,
@@ -81,12 +71,12 @@ void DidOpenFileSystem(base::File::Error* error_out,
class SandboxFileSystemBackendTest : public testing::Test {
protected:
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
SetUpNewDelegate(CreateAllowFileAccessOptions());
}
- void SetUpNewDelegate(const fileapi::FileSystemOptions& options) {
+ void SetUpNewDelegate(const storage::FileSystemOptions& options) {
delegate_.reset(new SandboxFileSystemBackendDelegate(
NULL /* quota_manager_proxy */,
base::MessageLoopProxy::current().get(),
@@ -95,18 +85,18 @@ class SandboxFileSystemBackendTest : public testing::Test {
options));
}
- void SetUpNewBackend(const fileapi::FileSystemOptions& options) {
+ void SetUpNewBackend(const storage::FileSystemOptions& options) {
SetUpNewDelegate(options);
backend_.reset(new SandboxFileSystemBackend(delegate_.get()));
}
- fileapi::SandboxFileSystemBackendDelegate::OriginEnumerator*
+ storage::SandboxFileSystemBackendDelegate::OriginEnumerator*
CreateOriginEnumerator() const {
return backend_->CreateOriginEnumerator();
}
void CreateOriginTypeDirectory(const GURL& origin,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
base::FilePath target = delegate_->
GetBaseDirectoryForOriginAndType(origin, type, true);
ASSERT_TRUE(!target.empty());
@@ -114,8 +104,8 @@ class SandboxFileSystemBackendTest : public testing::Test {
}
bool GetRootPath(const GURL& origin_url,
- fileapi::FileSystemType type,
- fileapi::OpenFileSystemMode mode,
+ storage::FileSystemType type,
+ storage::OpenFileSystemMode mode,
base::FilePath* root_path) {
base::File::Error error = base::File::FILE_OK;
backend_->ResolveURL(
@@ -140,8 +130,8 @@ class SandboxFileSystemBackendTest : public testing::Test {
base::ScopedTempDir data_dir_;
base::MessageLoop message_loop_;
- scoped_ptr<fileapi::SandboxFileSystemBackendDelegate> delegate_;
- scoped_ptr<fileapi::SandboxFileSystemBackend> backend_;
+ scoped_ptr<storage::SandboxFileSystemBackendDelegate> delegate_;
+ scoped_ptr<storage::SandboxFileSystemBackend> backend_;
};
TEST_F(SandboxFileSystemBackendTest, Empty) {
@@ -165,17 +155,17 @@ TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) {
"http://www.foo.com:8080/",
"http://www.foo.com:80/",
};
- size_t temporary_size = ARRAYSIZE_UNSAFE(temporary_origins);
- size_t persistent_size = ARRAYSIZE_UNSAFE(persistent_origins);
+ size_t temporary_size = arraysize(temporary_origins);
+ size_t persistent_size = arraysize(persistent_origins);
std::set<GURL> temporary_set, persistent_set;
for (size_t i = 0; i < temporary_size; ++i) {
CreateOriginTypeDirectory(GURL(temporary_origins[i]),
- fileapi::kFileSystemTypeTemporary);
+ storage::kFileSystemTypeTemporary);
temporary_set.insert(GURL(temporary_origins[i]));
}
for (size_t i = 0; i < persistent_size; ++i) {
CreateOriginTypeDirectory(GURL(persistent_origins[i]),
- fileapi::kFileSystemTypePersistent);
+ storage::kFileSystemTypePersistent);
persistent_set.insert(GURL(persistent_origins[i]));
}
@@ -186,11 +176,11 @@ TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) {
GURL current;
while (!(current = enumerator->Next()).is_empty()) {
SCOPED_TRACE(testing::Message() << "EnumerateOrigin " << current.spec());
- if (enumerator->HasFileSystemType(fileapi::kFileSystemTypeTemporary)) {
+ if (enumerator->HasFileSystemType(storage::kFileSystemTypeTemporary)) {
ASSERT_TRUE(temporary_set.find(current) != temporary_set.end());
++temporary_actual_size;
}
- if (enumerator->HasFileSystemType(fileapi::kFileSystemTypePersistent)) {
+ if (enumerator->HasFileSystemType(storage::kFileSystemTypePersistent)) {
ASSERT_TRUE(persistent_set.find(current) != persistent_set.end());
++persistent_actual_size;
}
@@ -201,19 +191,18 @@ TEST_F(SandboxFileSystemBackendTest, EnumerateOrigins) {
}
TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) {
- std::vector<base::FilePath> returned_root_path(
- ARRAYSIZE_UNSAFE(kRootPathTestCases));
+ std::vector<base::FilePath> returned_root_path(arraysize(kRootPathTestCases));
SetUpNewBackend(CreateAllowFileAccessOptions());
// Create a new root directory.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
SCOPED_TRACE(testing::Message() << "RootPath (create) #" << i << " "
<< kRootPathTestCases[i].expected_path);
base::FilePath root_path;
EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
kRootPathTestCases[i].type,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
&root_path));
base::FilePath expected = file_system_path().AppendASCII(
@@ -226,14 +215,14 @@ TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) {
// Get the root directory with create=false and see if we get the
// same directory.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
SCOPED_TRACE(testing::Message() << "RootPath (get) #" << i << " "
<< kRootPathTestCases[i].expected_path);
base::FilePath root_path;
EXPECT_TRUE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
kRootPathTestCases[i].type,
- fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
&root_path));
ASSERT_TRUE(returned_root_path.size() > i);
EXPECT_EQ(returned_root_path[i].value(), root_path.value());
@@ -242,21 +231,22 @@ TEST_F(SandboxFileSystemBackendTest, GetRootPathCreateAndExamine) {
TEST_F(SandboxFileSystemBackendTest,
GetRootPathCreateAndExamineWithNewBackend) {
- std::vector<base::FilePath> returned_root_path(
- ARRAYSIZE_UNSAFE(kRootPathTestCases));
+ std::vector<base::FilePath> returned_root_path(arraysize(kRootPathTestCases));
SetUpNewBackend(CreateAllowFileAccessOptions());
GURL origin_url("http://foo.com:1/");
base::FilePath root_path1;
- EXPECT_TRUE(GetRootPath(origin_url, fileapi::kFileSystemTypeTemporary,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ EXPECT_TRUE(GetRootPath(origin_url,
+ storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
&root_path1));
SetUpNewBackend(CreateDisallowFileAccessOptions());
base::FilePath root_path2;
- EXPECT_TRUE(GetRootPath(origin_url, fileapi::kFileSystemTypeTemporary,
- fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ EXPECT_TRUE(GetRootPath(origin_url,
+ storage::kFileSystemTypeTemporary,
+ storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
&root_path2));
EXPECT_EQ(root_path1.value(), root_path2.value());
@@ -266,12 +256,12 @@ TEST_F(SandboxFileSystemBackendTest, GetRootPathGetWithoutCreate) {
SetUpNewBackend(CreateDisallowFileAccessOptions());
// Try to get a root directory without creating.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
SCOPED_TRACE(testing::Message() << "RootPath (create=false) #" << i << " "
<< kRootPathTestCases[i].expected_path);
EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
kRootPathTestCases[i].type,
- fileapi::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_FAIL_IF_NONEXISTENT,
NULL));
}
}
@@ -280,39 +270,37 @@ TEST_F(SandboxFileSystemBackendTest, GetRootPathInIncognito) {
SetUpNewBackend(CreateIncognitoFileSystemOptions());
// Try to get a root directory.
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kRootPathTestCases); ++i) {
SCOPED_TRACE(testing::Message() << "RootPath (incognito) #" << i << " "
<< kRootPathTestCases[i].expected_path);
- EXPECT_FALSE(
- GetRootPath(GURL(kRootPathTestCases[i].origin_url),
- kRootPathTestCases[i].type,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- NULL));
+ EXPECT_FALSE(GetRootPath(GURL(kRootPathTestCases[i].origin_url),
+ kRootPathTestCases[i].type,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ NULL));
}
}
TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURI) {
SetUpNewBackend(CreateDisallowFileAccessOptions());
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kRootPathFileURITestCases); ++i) {
SCOPED_TRACE(testing::Message() << "RootPathFileURI (disallow) #"
<< i << " " << kRootPathFileURITestCases[i].expected_path);
- EXPECT_FALSE(
- GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
- kRootPathFileURITestCases[i].type,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
- NULL));
+ EXPECT_FALSE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
+ kRootPathFileURITestCases[i].type,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ NULL));
}
}
TEST_F(SandboxFileSystemBackendTest, GetRootPathFileURIWithAllowFlag) {
SetUpNewBackend(CreateAllowFileAccessOptions());
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathFileURITestCases); ++i) {
+ for (size_t i = 0; i < arraysize(kRootPathFileURITestCases); ++i) {
SCOPED_TRACE(testing::Message() << "RootPathFileURI (allow) #"
<< i << " " << kRootPathFileURITestCases[i].expected_path);
base::FilePath root_path;
EXPECT_TRUE(GetRootPath(GURL(kRootPathFileURITestCases[i].origin_url),
kRootPathFileURITestCases[i].type,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
&root_path));
base::FilePath expected = file_system_path().AppendASCII(
kRootPathFileURITestCases[i].expected_path);
diff --git a/chromium/content/browser/fileapi/sandbox_isolated_origin_database_unittest.cc b/chromium/content/browser/fileapi/sandbox_isolated_origin_database_unittest.cc
index fbf6a5eb25d..5f7f55f8005 100644
--- a/chromium/content/browser/fileapi/sandbox_isolated_origin_database_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_isolated_origin_database_unittest.cc
@@ -3,13 +3,13 @@
// found in the LICENSE file.
#include "base/basictypes.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "storage/browser/fileapi/sandbox_isolated_origin_database.h"
+#include "storage/browser/fileapi/sandbox_origin_database.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/sandbox_isolated_origin_database.h"
-#include "webkit/browser/fileapi/sandbox_origin_database.h"
-using fileapi::SandboxIsolatedOriginDatabase;
+using storage::SandboxIsolatedOriginDatabase;
namespace content {
diff --git a/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc b/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc
index cda5b77d9a8..44dad2032d7 100644
--- a/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc
@@ -8,19 +8,19 @@
#include <string>
#include <vector>
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/stl_util.h"
#include "content/browser/fileapi/sandbox_database_test_helper.h"
+#include "storage/browser/fileapi/sandbox_origin_database.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/db/filename.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
-#include "webkit/browser/fileapi/sandbox_origin_database.h"
-#include "webkit/common/fileapi/file_system_util.h"
-using fileapi::SandboxOriginDatabase;
+using storage::SandboxOriginDatabase;
namespace content {
diff --git a/chromium/content/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc b/chromium/content/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc
index e81dc7d18a0..0fb01153a57 100644
--- a/chromium/content/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc
@@ -3,15 +3,15 @@
// found in the LICENSE file.
#include "base/basictypes.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "storage/browser/fileapi/sandbox_origin_database.h"
+#include "storage/browser/fileapi/sandbox_prioritized_origin_database.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/sandbox_origin_database.h"
-#include "webkit/browser/fileapi/sandbox_prioritized_origin_database.h"
-using fileapi::SandboxOriginDatabase;
-using fileapi::SandboxOriginDatabaseInterface;
-using fileapi::SandboxPrioritizedOriginDatabase;
+using storage::SandboxOriginDatabase;
+using storage::SandboxOriginDatabaseInterface;
+using storage::SandboxPrioritizedOriginDatabase;
namespace content {
diff --git a/chromium/content/browser/fileapi/timed_task_helper_unittest.cc b/chromium/content/browser/fileapi/timed_task_helper_unittest.cc
index 59e465c98c5..5a6ac8df0e5 100644
--- a/chromium/content/browser/fileapi/timed_task_helper_unittest.cc
+++ b/chromium/content/browser/fileapi/timed_task_helper_unittest.cc
@@ -9,10 +9,10 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "base/time/time.h"
+#include "storage/browser/fileapi/timed_task_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/timed_task_helper.h"
-using fileapi::TimedTaskHelper;
+using storage::TimedTaskHelper;
namespace content {
diff --git a/chromium/content/browser/fileapi/transient_file_util_unittest.cc b/chromium/content/browser/fileapi/transient_file_util_unittest.cc
index 96df84f4fcf..faf20caa4c5 100644
--- a/chromium/content/browser/fileapi/transient_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/transient_file_util_unittest.cc
@@ -3,37 +3,37 @@
// found in the LICENSE file.
#include "base/basictypes.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "content/public/test/test_file_system_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/browser/fileapi/transient_file_util.h"
+#include "storage/common/blob/scoped_file.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/fileapi/transient_file_util.h"
-#include "webkit/common/blob/scoped_file.h"
-using fileapi::FileSystemURL;
+using storage::FileSystemURL;
namespace content {
class TransientFileUtilTest : public testing::Test {
public:
TransientFileUtilTest() {}
- virtual ~TransientFileUtilTest() {}
+ ~TransientFileUtilTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
file_system_context_ = CreateFileSystemContextForTesting(
NULL, base::FilePath(FILE_PATH_LITERAL("dummy")));
- transient_file_util_.reset(new fileapi::TransientFileUtil);
+ transient_file_util_.reset(new storage::TransientFileUtil);
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
file_system_context_ = NULL;
base::RunLoop().RunUntilIdle();
}
@@ -42,11 +42,11 @@ class TransientFileUtilTest : public testing::Test {
FileSystemURL* file_url,
base::FilePath* file_path) {
EXPECT_TRUE(base::CreateTemporaryFileInDir(data_dir_.path(), file_path));
- fileapi::IsolatedContext* isolated_context =
- fileapi::IsolatedContext::GetInstance();
+ storage::IsolatedContext* isolated_context =
+ storage::IsolatedContext::GetInstance();
std::string name = "tmp";
std::string fsid = isolated_context->RegisterFileSystemForPath(
- fileapi::kFileSystemTypeForTransientFile,
+ storage::kFileSystemTypeForTransientFile,
std::string(),
*file_path,
&name);
@@ -54,25 +54,23 @@ class TransientFileUtilTest : public testing::Test {
base::FilePath virtual_path = isolated_context->CreateVirtualRootPath(
fsid).AppendASCII(name);
*file_url = file_system_context_->CreateCrackedFileSystemURL(
- GURL("http://foo"),
- fileapi::kFileSystemTypeIsolated,
- virtual_path);
+ GURL("http://foo"), storage::kFileSystemTypeIsolated, virtual_path);
}
- scoped_ptr<fileapi::FileSystemOperationContext> NewOperationContext() {
+ scoped_ptr<storage::FileSystemOperationContext> NewOperationContext() {
return make_scoped_ptr(
- new fileapi::FileSystemOperationContext(file_system_context_.get()));
+ new storage::FileSystemOperationContext(file_system_context_.get()));
}
- fileapi::FileSystemFileUtil* file_util() {
+ storage::FileSystemFileUtil* file_util() {
return transient_file_util_.get();
}
private:
base::MessageLoop message_loop_;
base::ScopedTempDir data_dir_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
- scoped_ptr<fileapi::TransientFileUtil> transient_file_util_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
+ scoped_ptr<storage::TransientFileUtil> transient_file_util_;
DISALLOW_COPY_AND_ASSIGN(TransientFileUtilTest);
};
@@ -94,12 +92,8 @@ TEST_F(TransientFileUtilTest, TransientFile) {
// Create a snapshot file.
{
- webkit_blob::ScopedFile scoped_file =
- file_util()->CreateSnapshotFile(NewOperationContext().get(),
- temp_url,
- &error,
- &file_info,
- &path);
+ storage::ScopedFile scoped_file = file_util()->CreateSnapshotFile(
+ NewOperationContext().get(), temp_url, &error, &file_info, &path);
ASSERT_EQ(base::File::FILE_OK, error);
ASSERT_EQ(temp_path, path);
ASSERT_FALSE(file_info.is_directory);
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.cc b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.cc
index 9e6a288758e..a6a99ca0c75 100644
--- a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.cc
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.cc
@@ -5,17 +5,19 @@
#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
#include <algorithm>
+#include <limits>
#include "base/bind.h"
+#include "base/numerics/safe_conversions.h"
#include "net/base/net_errors.h"
-#include "webkit/browser/blob/file_stream_reader.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
+#include "storage/browser/blob/file_stream_reader.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
namespace content {
UploadFileSystemFileElementReader::UploadFileSystemFileElementReader(
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
const GURL& url,
uint64 range_offset,
uint64 range_length,
@@ -41,11 +43,13 @@ int UploadFileSystemFileElementReader::Init(
position_ = 0;
// Initialize the stream reader and the length.
- stream_reader_ =
- file_system_context_->CreateFileStreamReader(
- file_system_context_->CrackURL(url_),
- range_offset_,
- expected_modification_time_);
+ stream_reader_ = file_system_context_->CreateFileStreamReader(
+ file_system_context_->CrackURL(url_),
+ range_offset_,
+ range_length_ == std::numeric_limits<uint64>::max()
+ ? storage::kMaximumLength
+ : base::checked_cast<int64>(range_length_),
+ expected_modification_time_);
DCHECK(stream_reader_);
const int64 result = stream_reader_->GetLength(
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
index 1b33489d1b2..bc2a6f7a71a 100644
--- a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
@@ -11,11 +11,11 @@
#include "net/base/upload_element_reader.h"
#include "url/gurl.h"
-namespace webkit_blob {
+namespace storage {
class FileStreamReader;
}
-namespace fileapi {
+namespace storage {
class FileSystemContext;
}
@@ -26,32 +26,32 @@ class CONTENT_EXPORT UploadFileSystemFileElementReader :
NON_EXPORTED_BASE(public net::UploadElementReader) {
public:
UploadFileSystemFileElementReader(
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
const GURL& url,
uint64 range_offset,
uint64 range_length,
const base::Time& expected_modification_time);
- virtual ~UploadFileSystemFileElementReader();
+ ~UploadFileSystemFileElementReader() override;
// UploadElementReader overrides:
- virtual int Init(const net::CompletionCallback& callback) OVERRIDE;
- virtual uint64 GetContentLength() const OVERRIDE;
- virtual uint64 BytesRemaining() const OVERRIDE;
- virtual int Read(net::IOBuffer* buf,
- int buf_length,
- const net::CompletionCallback& callback) OVERRIDE;
+ int Init(const net::CompletionCallback& callback) override;
+ uint64 GetContentLength() const override;
+ uint64 BytesRemaining() const override;
+ int Read(net::IOBuffer* buf,
+ int buf_length,
+ const net::CompletionCallback& callback) override;
private:
void OnGetLength(const net::CompletionCallback& callback, int64 result);
void OnRead(const net::CompletionCallback& callback, int result);
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
const GURL url_;
const uint64 range_offset_;
const uint64 range_length_;
const base::Time expected_modification_time_;
- scoped_ptr<webkit_blob::FileStreamReader> stream_reader_;
+ scoped_ptr<storage::FileStreamReader> stream_reader_;
uint64 stream_length_;
uint64 position_;
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc b/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
index 641b96852ca..7e16a725039 100644
--- a/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader_unittest.cc
@@ -11,24 +11,24 @@
#include "content/public/test/test_file_system_context.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
+#include "storage/browser/fileapi/file_system_backend.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_context.h"
+#include "storage/browser/fileapi/file_system_url.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/file_system_backend.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/file_system_url.h"
using content::AsyncFileTestHelper;
-using fileapi::FileSystemContext;
-using fileapi::FileSystemType;
-using fileapi::FileSystemURL;
+using storage::FileSystemContext;
+using storage::FileSystemType;
+using storage::FileSystemURL;
namespace content {
namespace {
const char kFileSystemURLOrigin[] = "http://remote";
-const fileapi::FileSystemType kFileSystemType =
- fileapi::kFileSystemTypeTemporary;
+const storage::FileSystemType kFileSystemType =
+ storage::kFileSystemTypeTemporary;
} // namespace
@@ -36,7 +36,7 @@ class UploadFileSystemFileElementReaderTest : public testing::Test {
public:
UploadFileSystemFileElementReaderTest() {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
file_system_context_ = CreateFileSystemContextForTesting(
@@ -45,7 +45,7 @@ class UploadFileSystemFileElementReaderTest : public testing::Test {
file_system_context_->OpenFileSystem(
GURL(kFileSystemURLOrigin),
kFileSystemType,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&UploadFileSystemFileElementReaderTest::OnOpenFileSystem,
base::Unretained(this)));
base::RunLoop().RunUntilIdle();
@@ -74,7 +74,7 @@ class UploadFileSystemFileElementReaderTest : public testing::Test {
EXPECT_FALSE(reader_->IsInMemory());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
reader_.reset();
base::RunLoop().RunUntilIdle();
}
@@ -88,7 +88,7 @@ class UploadFileSystemFileElementReaderTest : public testing::Test {
const char* buf,
int buf_size,
base::Time* modification_time) {
- fileapi::FileSystemURL url =
+ storage::FileSystemURL url =
file_system_context_->CreateCrackedFileSystemURL(
GURL(kFileSystemURLOrigin),
kFileSystemType,
@@ -96,12 +96,12 @@ class UploadFileSystemFileElementReaderTest : public testing::Test {
ASSERT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::CreateFileWithData(
- file_system_context_, url, buf, buf_size));
+ file_system_context_.get(), url, buf, buf_size));
base::File::Info file_info;
ASSERT_EQ(base::File::FILE_OK,
AsyncFileTestHelper::GetMetadata(
- file_system_context_, url, &file_info));
+ file_system_context_.get(), url, &file_info));
*modification_time = file_info.last_modified;
}
diff --git a/chromium/content/browser/frame_host/OWNERS b/chromium/content/browser/frame_host/OWNERS
deleted file mode 100644
index df8aeac9541..00000000000
--- a/chromium/content/browser/frame_host/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-nasko@chromium.org
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.cc b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
index 7701f63d7ea..43efd017fe1 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -30,7 +30,6 @@ bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_BuffersSwappedACK, OnBuffersSwappedACK)
IPC_MESSAGE_HANDLER(FrameHostMsg_CompositorFrameSwappedACK,
OnCompositorFrameSwappedACK)
IPC_MESSAGE_HANDLER(FrameHostMsg_ReclaimCompositorResources,
@@ -65,20 +64,6 @@ void CrossProcessFrameConnector::RenderProcessGone() {
frame_proxy_in_parent_renderer_->GetRoutingID()));
}
-void CrossProcessFrameConnector::ChildFrameBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& gpu_params,
- int gpu_host_id) {
-
- FrameMsg_BuffersSwapped_Params params;
- params.size = gpu_params.size;
- params.mailbox = gpu_params.mailbox;
- params.gpu_route_id = gpu_params.route_id;
- params.gpu_host_id = gpu_host_id;
-
- frame_proxy_in_parent_renderer_->Send(new FrameMsg_BuffersSwapped(
- frame_proxy_in_parent_renderer_->GetRoutingID(), params));
-}
-
void CrossProcessFrameConnector::ChildFrameCompositorFrameSwapped(
uint32 output_surface_id,
int host_id,
@@ -93,18 +78,6 @@ void CrossProcessFrameConnector::ChildFrameCompositorFrameSwapped(
frame_proxy_in_parent_renderer_->GetRoutingID(), params));
}
-void CrossProcessFrameConnector::OnBuffersSwappedACK(
- const FrameHostMsg_BuffersSwappedACK_Params& params) {
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.mailbox = params.mailbox;
- ack_params.sync_point = params.sync_point;
- RenderWidgetHostImpl::AcknowledgeBufferPresent(params.gpu_route_id,
- params.gpu_host_id,
- ack_params);
-
- // TODO(kenrb): Special case stuff for Win + Mac.
-}
-
void CrossProcessFrameConnector::OnCompositorFrameSwappedACK(
const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.h b/chromium/content/browser/frame_host/cross_process_frame_connector.h
index 82452243f5b..dffeba2675d 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -16,10 +16,8 @@ namespace IPC {
class Message;
}
-struct FrameHostMsg_BuffersSwappedACK_Params;
struct FrameHostMsg_CompositorFrameSwappedACK_Params;
struct FrameHostMsg_ReclaimCompositorResources_Params;
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
namespace content {
class RenderFrameProxyHost;
@@ -78,13 +76,6 @@ class CrossProcessFrameConnector {
void RenderProcessGone();
- // 'Platform' functionality exposed to RenderWidgetHostViewChildFrame.
- // These methods can forward messages to the child frame proxy in the parent
- // frame's renderer or attempt to handle them within the browser process.
- void ChildFrameBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id);
-
void ChildFrameCompositorFrameSwapped(uint32 output_surface_id,
int host_id,
int route_id,
@@ -94,8 +85,6 @@ class CrossProcessFrameConnector {
private:
// Handlers for messages received from the parent frame.
- void OnBuffersSwappedACK(
- const FrameHostMsg_BuffersSwappedACK_Params& params);
void OnCompositorFrameSwappedACK(
const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
void OnReclaimCompositorResources(
diff --git a/chromium/content/browser/frame_host/cross_site_transferring_request.h b/chromium/content/browser/frame_host/cross_site_transferring_request.h
index a78684be77b..0d696a3d69a 100644
--- a/chromium/content/browser/frame_host/cross_site_transferring_request.h
+++ b/chromium/content/browser/frame_host/cross_site_transferring_request.h
@@ -26,6 +26,8 @@ class CONTENT_EXPORT CrossSiteTransferringRequest {
// control of it.
void ReleaseRequest();
+ GlobalRequestID request_id() const { return global_request_id_; }
+
private:
// No need for a weak pointer here - nothing should have ownership of the
// cross site request until after |this| is deleted, or ReleaseRequest is
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index ae454ae64a7..0b2ca863388 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -6,17 +6,22 @@
#include <vector>
+#include "base/command_line.h"
#include "base/debug/asan_invalid_access.h"
#include "base/debug/profiler.h"
#include "base/strings/utf_string_conversions.h"
+#include "cc/base/switches.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
-#include "content/browser/ppapi_plugin_process_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "url/gurl.h"
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/ppapi_plugin_process_host.h"
+#endif
+
namespace content {
namespace {
@@ -105,18 +110,22 @@ bool HandleAsanDebugURL(const GURL& url) {
} // namespace
-bool HandleDebugURL(const GURL& url, PageTransition transition) {
- // Ensure that the user explicitly navigated to this URL.
- if (!(transition & PAGE_TRANSITION_FROM_ADDRESS_BAR))
- return false;
+bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
+ // Ensure that the user explicitly navigated to this URL, unless
+ // kEnableGpuBenchmarking is enabled by Telemetry.
+ bool is_telemetry_navigation =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ cc::switches::kEnableGpuBenchmarking) &&
+ (transition & ui::PAGE_TRANSITION_TYPED);
- // NOTE: when you add handling of any URLs to this function, also
- // update IsDebugURL, below.
+ if (!(transition & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) &&
+ !is_telemetry_navigation)
+ return false;
if (IsAsanDebugURL(url))
return HandleAsanDebugURL(url);
- if (url.host() == kChromeUIBrowserCrashHost) {
+ if (url == GURL(kChromeUIBrowserCrashURL)) {
// Induce an intentional crash in the browser process.
CHECK(false);
return true;
@@ -153,19 +162,6 @@ bool HandleDebugURL(const GURL& url, PageTransition transition) {
return false;
}
-bool IsDebugURL(const GURL& url) {
- // NOTE: when you add any URLs to this list, also update
- // HandleDebugURL, above.
- return IsRendererDebugURL(url) || IsAsanDebugURL(url) ||
- (url.is_valid() &&
- (url.host() == kChromeUIBrowserCrashHost ||
- url == GURL(kChromeUIGpuCleanURL) ||
- url == GURL(kChromeUIGpuCrashURL) ||
- url == GURL(kChromeUIGpuHangURL) ||
- url == GURL(kChromeUIPpapiFlashCrashURL) ||
- url == GURL(kChromeUIPpapiFlashHangURL)));
-}
-
bool IsRendererDebugURL(const GURL& url) {
if (!url.is_valid())
return false;
diff --git a/chromium/content/browser/frame_host/debug_urls.h b/chromium/content/browser/frame_host/debug_urls.h
index 2c871948ef2..413cd0f3387 100644
--- a/chromium/content/browser/frame_host/debug_urls.h
+++ b/chromium/content/browser/frame_host/debug_urls.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_BROWSER_FRAME_HOST_DEBUG_URLS_H_
#define CONTENT_BROWSER_FRAME_HOST_DEBUG_URLS_H_
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
class GURL;
@@ -13,12 +13,7 @@ namespace content {
// Checks if the given url is a url used for debugging purposes, and if so
// handles it and returns true.
-bool HandleDebugURL(const GURL& url, PageTransition transition);
-
-// Returns whether this given url is a debugging url. It is a superset
-// of IsRendererDebugURL, below, and debugging urls that are handled
-// in the browser process.
-bool IsDebugURL(const GURL& url);
+bool HandleDebugURL(const GURL& url, ui::PageTransition transition);
// Returns whether the given url is either a debugging url handled in the
// renderer process, such as one that crashes or hangs the renderer, or a
diff --git a/chromium/content/browser/frame_host/frame_accessibility.cc b/chromium/content/browser/frame_host/frame_accessibility.cc
new file mode 100644
index 00000000000..aa2c32667bf
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_accessibility.cc
@@ -0,0 +1,179 @@
+// Copyright 2014 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 "content/browser/frame_host/frame_accessibility.h"
+
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_context.h"
+
+namespace content {
+
+// static
+FrameAccessibility* FrameAccessibility::GetInstance() {
+ return Singleton<FrameAccessibility>::get();
+}
+
+FrameAccessibility::ChildFrameMapping::ChildFrameMapping()
+ : parent_frame_host(NULL),
+ accessibility_node_id(0),
+ child_frame_tree_node_id(0),
+ browser_plugin_instance_id(0) {}
+
+FrameAccessibility::FrameAccessibility() {}
+
+FrameAccessibility::~FrameAccessibility() {}
+
+void FrameAccessibility::AddChildFrame(
+ RenderFrameHostImpl* parent_frame_host,
+ int accessibility_node_id,
+ int64 child_frame_tree_node_id) {
+ for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
+ iter != mappings_.end();
+ ++iter) {
+ // TODO(dmazzoni): the renderer should keep track of these mappings
+ // and clear an existing mapping before setting a new one, that would
+ // be safer than just updating existing mappings. http://crbug.com/413464
+ if (iter->parent_frame_host == parent_frame_host &&
+ (iter->accessibility_node_id == accessibility_node_id ||
+ iter->child_frame_tree_node_id == child_frame_tree_node_id)) {
+ iter->accessibility_node_id = accessibility_node_id;
+ iter->child_frame_tree_node_id = child_frame_tree_node_id;
+ return;
+ }
+ }
+
+ ChildFrameMapping new_mapping;
+ new_mapping.parent_frame_host = parent_frame_host;
+ new_mapping.accessibility_node_id = accessibility_node_id;
+ new_mapping.child_frame_tree_node_id = child_frame_tree_node_id;
+ mappings_.push_back(new_mapping);
+}
+
+void FrameAccessibility::AddGuestWebContents(
+ RenderFrameHostImpl* parent_frame_host,
+ int accessibility_node_id,
+ int browser_plugin_instance_id) {
+ for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
+ iter != mappings_.end();
+ ++iter) {
+ // TODO(dmazzoni): the renderer should keep track of these mappings
+ // and clear an existing mapping before setting a new one, that would
+ // be safer than just updating existing mappings. http://crbug.com/413464
+ if (iter->parent_frame_host == parent_frame_host &&
+ (iter->accessibility_node_id == accessibility_node_id ||
+ iter->browser_plugin_instance_id == browser_plugin_instance_id)) {
+ iter->accessibility_node_id = accessibility_node_id;
+ iter->browser_plugin_instance_id = browser_plugin_instance_id;
+ return;
+ }
+ }
+
+ ChildFrameMapping new_mapping;
+ new_mapping.parent_frame_host = parent_frame_host;
+ new_mapping.accessibility_node_id = accessibility_node_id;
+ new_mapping.browser_plugin_instance_id = browser_plugin_instance_id;
+ mappings_.push_back(new_mapping);
+}
+
+void FrameAccessibility::OnRenderFrameHostDestroyed(
+ RenderFrameHostImpl* render_frame_host) {
+ // Since the order doesn't matter, the fastest way to remove all items
+ // with this render_frame_host is to iterate over the vector backwards,
+ // swapping each one with the back element if we need to delete it.
+ int initial_len = static_cast<int>(mappings_.size());
+ for (int i = initial_len - 1; i >= 0; i--) {
+ if (mappings_[i].parent_frame_host == render_frame_host) {
+ mappings_[i] = mappings_.back();
+ mappings_.pop_back();
+ }
+ }
+}
+
+RenderFrameHostImpl* FrameAccessibility::GetChild(
+ RenderFrameHostImpl* parent_frame_host,
+ int accessibility_node_id) {
+ for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
+ iter != mappings_.end();
+ ++iter) {
+ if (iter->parent_frame_host != parent_frame_host ||
+ iter->accessibility_node_id != accessibility_node_id) {
+ continue;
+ }
+
+ if (iter->child_frame_tree_node_id) {
+ FrameTreeNode* child_node =
+ FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
+ if (!child_node)
+ return NULL;
+
+ // We should have gotten a node in the same frame tree.
+ if (child_node->frame_tree() !=
+ parent_frame_host->frame_tree_node()->frame_tree()) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ return child_node->current_frame_host();
+ }
+
+ if (iter->browser_plugin_instance_id) {
+ RenderFrameHost* guest =
+ parent_frame_host->delegate()->GetGuestByInstanceID(
+ iter->browser_plugin_instance_id);
+ if (guest)
+ return static_cast<RenderFrameHostImpl*>(guest);
+ }
+ }
+
+ return NULL;
+}
+
+bool FrameAccessibility::GetParent(
+ RenderFrameHostImpl* child_frame_host,
+ RenderFrameHostImpl** out_parent_frame_host,
+ int* out_accessibility_node_id) {
+ for (std::vector<ChildFrameMapping>::iterator iter = mappings_.begin();
+ iter != mappings_.end();
+ ++iter) {
+ if (iter->child_frame_tree_node_id) {
+ FrameTreeNode* child_node =
+ FrameTree::GloballyFindByID(iter->child_frame_tree_node_id);
+ if (child_node &&
+ child_node->current_frame_host() == child_frame_host) {
+ // We should have gotten a node in the same frame tree.
+ if (child_node->frame_tree() !=
+ iter->parent_frame_host->frame_tree_node()->frame_tree()) {
+ NOTREACHED();
+ return false;
+ }
+
+ if (out_parent_frame_host)
+ *out_parent_frame_host = iter->parent_frame_host;
+ if (out_accessibility_node_id)
+ *out_accessibility_node_id = iter->accessibility_node_id;
+ return true;
+ }
+ }
+
+ if (iter->browser_plugin_instance_id) {
+ RenderFrameHost* guest =
+ iter->parent_frame_host->delegate()->GetGuestByInstanceID(
+ iter->browser_plugin_instance_id);
+ if (guest == child_frame_host) {
+ if (out_parent_frame_host)
+ *out_parent_frame_host = iter->parent_frame_host;
+ if (out_accessibility_node_id)
+ *out_accessibility_node_id = iter->accessibility_node_id;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_accessibility.h b/chromium/content/browser/frame_host/frame_accessibility.h
new file mode 100644
index 00000000000..253ba19b054
--- /dev/null
+++ b/chromium/content/browser/frame_host/frame_accessibility.h
@@ -0,0 +1,79 @@
+// Copyright 2014 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 CONTENT_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
+#define CONTENT_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class RenderFrameHostImpl;
+
+// This singleton class maintains the mappings necessary to link child frames
+// and guest frames into a single tree for accessibility. This class is only
+// used if accessibility is enabled.
+class CONTENT_EXPORT FrameAccessibility {
+ public:
+ static FrameAccessibility* GetInstance();
+
+ // Add a mapping between an accessibility node of |parent_frame_host|
+ // and the child frame with the given frame tree node id, in the same
+ // frame tree.
+ void AddChildFrame(RenderFrameHostImpl* parent_frame_host,
+ int accessibility_node_id,
+ int64 child_frame_tree_node_id);
+
+ // Add a mapping between an accessibility node of |parent_frame_host|
+ // and the main frame of the guest Webcontents with the given
+ // browser plugin instance id.
+ void AddGuestWebContents(RenderFrameHostImpl* parent_frame_host,
+ int accessibility_node_id,
+ int browser_plugin_instance_id);
+
+ // This is called when a RenderFrameHostImpl is deleted, so invalid
+ // mappings can be removed from this data structure.
+ void OnRenderFrameHostDestroyed(RenderFrameHostImpl* render_frame_host);
+
+ // Given a parent RenderFrameHostImpl and an accessibility node id, look up
+ // a child frame or guest frame that was previously associated with this
+ // frame and node id. If a mapping exists, return the resulting frame if
+ // it's valid. If it doesn't resolve to a valid RenderFrameHostImpl,
+ // returns NULL.
+ RenderFrameHostImpl* GetChild(RenderFrameHostImpl* parent_frame_host,
+ int accessibility_node_id);
+
+ // Given a RenderFrameHostImpl, check the mapping table to see if it's
+ // the child of a node in some other frame. If so, return true and
+ // set the parent frame and accessibility node id in the parent frame,
+ // otherwise return false.
+ bool GetParent(RenderFrameHostImpl* child_frame_host,
+ RenderFrameHostImpl** out_parent_frame_host,
+ int* out_accessibility_node_id);
+
+ private:
+ FrameAccessibility();
+ virtual ~FrameAccessibility();
+
+ struct ChildFrameMapping {
+ ChildFrameMapping();
+
+ RenderFrameHostImpl* parent_frame_host;
+ int accessibility_node_id;
+ int64 child_frame_tree_node_id;
+ int browser_plugin_instance_id;
+ };
+
+ std::vector<ChildFrameMapping> mappings_;
+
+ friend struct DefaultSingletonTraits<FrameAccessibility>;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_FRAME_ACCESSIBILITY_H_
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index 1accb0e9d1b..b1ccf6f9c79 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -8,18 +8,30 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_factory.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/public/browser/browser_thread.h"
namespace content {
namespace {
+
+// This is a global map between frame_tree_node_ids and pointer to
+// FrameTreeNodes.
+typedef base::hash_map<int64, FrameTreeNode*> FrameTreeNodeIDMap;
+
+base::LazyInstance<FrameTreeNodeIDMap> g_frame_tree_node_id_map =
+ LAZY_INSTANCE_INITIALIZER;
+
// Used with FrameTree::ForEach() to search for the FrameTreeNode
-// corresponding to |frame_tree_node_id|.
+// corresponding to |frame_tree_node_id| whithin a specific FrameTree.
bool FrameTreeNodeForId(int64 frame_tree_node_id,
FrameTreeNode** out_node,
FrameTreeNode* node) {
@@ -31,26 +43,27 @@ bool FrameTreeNodeForId(int64 frame_tree_node_id,
return true;
}
-bool FrameTreeNodeForRoutingId(int routing_id,
- int process_id,
- FrameTreeNode** out_node,
- FrameTreeNode* node) {
- // TODO(creis): Look through the swapped out RFHs as well.
- if (node->current_frame_host()->GetProcess()->GetID() == process_id &&
- node->current_frame_host()->GetRoutingID() == routing_id) {
- *out_node = node;
- // Terminate iteration once the node has been found.
- return false;
- }
- return true;
-}
-
// Iterate over the FrameTree to reset any node affected by the loss of the
// given RenderViewHost's process.
bool ResetNodesForNewProcess(RenderViewHost* render_view_host,
FrameTreeNode* node) {
- if (render_view_host == node->current_frame_host()->render_view_host())
+ if (render_view_host == node->current_frame_host()->render_view_host()) {
+ // Ensure that if the frame host is reused for a new RenderFrame, it will
+ // set up the Mojo connection with that frame.
+ node->current_frame_host()->InvalidateMojoConnection();
node->ResetForNewProcess();
+ }
+ return true;
+}
+
+bool CreateProxyForSiteInstance(const scoped_refptr<SiteInstance>& instance,
+ FrameTreeNode* node) {
+ // If a new frame is created in the current SiteInstance, other frames in
+ // that SiteInstance don't need a proxy for the new frame.
+ SiteInstance* current_instance =
+ node->render_manager()->current_frame_host()->GetSiteInstance();
+ if (current_instance != instance.get())
+ node->render_manager()->CreateRenderFrameProxy(instance.get());
return true;
}
@@ -73,9 +86,22 @@ FrameTree::FrameTree(Navigator* navigator,
manager_delegate,
std::string())),
focused_frame_tree_node_id_(-1) {
+ std::pair<FrameTreeNodeIDMap::iterator, bool> result =
+ g_frame_tree_node_id_map.Get().insert(
+ std::make_pair(root_->frame_tree_node_id(), root_.get()));
+ CHECK(result.second);
}
FrameTree::~FrameTree() {
+ g_frame_tree_node_id_map.Get().erase(root_->frame_tree_node_id());
+}
+
+// static
+FrameTreeNode* FrameTree::GloballyFindByID(int64 frame_tree_node_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ FrameTreeNodeIDMap* nodes = g_frame_tree_node_id_map.Pointer();
+ FrameTreeNodeIDMap::iterator it = nodes->find(frame_tree_node_id);
+ return it == nodes->end() ? NULL : it->second;
}
FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) {
@@ -85,20 +111,42 @@ FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) {
}
FrameTreeNode* FrameTree::FindByRoutingID(int routing_id, int process_id) {
- FrameTreeNode* node = NULL;
- ForEach(
- base::Bind(&FrameTreeNodeForRoutingId, routing_id, process_id, &node));
- return node;
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(process_id, routing_id);
+ if (render_frame_host) {
+ FrameTreeNode* result = render_frame_host->frame_tree_node();
+ if (this == result->frame_tree())
+ return result;
+ }
+
+ RenderFrameProxyHost* render_frame_proxy_host =
+ RenderFrameProxyHost::FromID(process_id, routing_id);
+ if (render_frame_proxy_host) {
+ FrameTreeNode* result = render_frame_proxy_host->frame_tree_node();
+ if (this == result->frame_tree())
+ return result;
+ }
+
+ return NULL;
}
void FrameTree::ForEach(
const base::Callback<bool(FrameTreeNode*)>& on_node) const {
+ ForEach(on_node, NULL);
+}
+
+void FrameTree::ForEach(
+ const base::Callback<bool(FrameTreeNode*)>& on_node,
+ FrameTreeNode* skip_this_subtree) const {
std::queue<FrameTreeNode*> queue;
queue.push(root_.get());
while (!queue.empty()) {
FrameTreeNode* node = queue.front();
queue.pop();
+ if (skip_this_subtree == node)
+ continue;
+
if (!on_node.Run(node))
break;
@@ -108,14 +156,26 @@ void FrameTree::ForEach(
}
RenderFrameHostImpl* FrameTree::AddFrame(FrameTreeNode* parent,
+ int process_id,
int new_routing_id,
const std::string& frame_name) {
+ // A child frame always starts with an initial empty document, which means
+ // it is in the same SiteInstance as the parent frame. Ensure that the process
+ // which requested a child frame to be added is the same as the process of the
+ // parent node.
+ if (parent->current_frame_host()->GetProcess()->GetID() != process_id)
+ return nullptr;
+
scoped_ptr<FrameTreeNode> node(new FrameTreeNode(
this, parent->navigator(), render_frame_delegate_, render_view_delegate_,
render_widget_delegate_, manager_delegate_, frame_name));
+ std::pair<FrameTreeNodeIDMap::iterator, bool> result =
+ g_frame_tree_node_id_map.Get().insert(
+ std::make_pair(node->frame_tree_node_id(), node.get()));
+ CHECK(result.second);
FrameTreeNode* node_ptr = node.get();
// AddChild is what creates the RenderFrameHost.
- parent->AddChild(node.Pass(), new_routing_id);
+ parent->AddChild(node.Pass(), process_id, new_routing_id);
return node_ptr->current_frame_host();
}
@@ -129,14 +189,38 @@ void FrameTree::RemoveFrame(FrameTreeNode* child) {
// Notify observers of the frame removal.
RenderFrameHostImpl* render_frame_host = child->current_frame_host();
if (!on_frame_removed_.is_null()) {
- on_frame_removed_.Run(
- render_frame_host->render_view_host(),
- render_frame_host->GetRoutingID());
+ on_frame_removed_.Run(render_frame_host);
}
-
+ g_frame_tree_node_id_map.Get().erase(child->frame_tree_node_id());
parent->RemoveChild(child);
}
+void FrameTree::CreateProxiesForSiteInstance(
+ FrameTreeNode* source,
+ SiteInstance* site_instance) {
+ // Create the swapped out RVH for the new SiteInstance. This will create
+ // a top-level swapped out RFH as well, which will then be wrapped by a
+ // RenderFrameProxyHost.
+ if (!source->IsMainFrame()) {
+ RenderViewHostImpl* render_view_host =
+ source->frame_tree()->GetRenderViewHost(site_instance);
+ if (!render_view_host) {
+ root()->render_manager()->CreateRenderFrame(site_instance,
+ MSG_ROUTING_NONE,
+ true,
+ false,
+ true);
+ }
+ }
+
+ scoped_refptr<SiteInstance> instance(site_instance);
+
+ // Proxies are created in the FrameTree in response to a node navigating to a
+ // new SiteInstance. Since |source|'s navigation will replace the currently
+ // loaded document, the entire subtree under |source| will be removed.
+ ForEach(base::Bind(&CreateProxyForSiteInstance, instance), source);
+}
+
void FrameTree::ResetForMainFrameSwap() {
root_->ResetForNewProcess();
focused_frame_tree_node_id_ = -1;
@@ -165,29 +249,33 @@ void FrameTree::SetFocusedFrame(FrameTreeNode* node) {
}
void FrameTree::SetFrameRemoveListener(
- const base::Callback<void(RenderViewHostImpl*, int)>& on_frame_removed) {
+ const base::Callback<void(RenderFrameHost*)>& on_frame_removed) {
on_frame_removed_ = on_frame_removed;
}
-RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame(
- SiteInstance* site_instance,
- int routing_id,
- int main_frame_routing_id,
- bool swapped_out,
- bool hidden) {
+RenderViewHostImpl* FrameTree::CreateRenderViewHost(SiteInstance* site_instance,
+ int routing_id,
+ int main_frame_routing_id,
+ bool swapped_out,
+ bool hidden) {
DCHECK(main_frame_routing_id != MSG_ROUTING_NONE);
RenderViewHostMap::iterator iter =
render_view_host_map_.find(site_instance->GetId());
if (iter != render_view_host_map_.end()) {
- // If a RenderViewHost is pending shutdown for this |site_instance|, put it
- // in the map of RenderViewHosts pending shutdown. Otherwise there should
- // not be a RenderViewHost for the SiteInstance.
- CHECK_EQ(RenderViewHostImpl::STATE_PENDING_SHUTDOWN,
- iter->second->rvh_state());
- render_view_host_pending_shutdown_map_.insert(
- std::pair<int, RenderViewHostImpl*>(site_instance->GetId(),
- iter->second));
- render_view_host_map_.erase(iter);
+ // If a RenderViewHost's main frame is pending deletion for this
+ // |site_instance|, put it in the map of RenderViewHosts pending shutdown.
+ // Otherwise return the existing RenderViewHost for the SiteInstance.
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ iter->second->GetMainFrame());
+ if (main_frame->frame_tree_node()->render_manager()->IsPendingDeletion(
+ main_frame)) {
+ render_view_host_pending_shutdown_map_.insert(
+ std::pair<int, RenderViewHostImpl*>(site_instance->GetId(),
+ iter->second));
+ render_view_host_map_.erase(iter);
+ } else {
+ return iter->second;
+ }
}
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
RenderViewHostFactory::Create(site_instance,
@@ -202,8 +290,7 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHostForMainFrame(
return rvh;
}
-RenderViewHostImpl* FrameTree::GetRenderViewHostForSubFrame(
- SiteInstance* site_instance) {
+RenderViewHostImpl* FrameTree::GetRenderViewHost(SiteInstance* site_instance) {
RenderViewHostMap::iterator iter =
render_view_host_map_.find(site_instance->GetId());
// TODO(creis): Mirror the frame tree so this check can't fail.
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
index c7fdc4eaf7a..b312265fe4e 100644
--- a/chromium/content/browser/frame_host/frame_tree.h
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -50,9 +50,13 @@ class CONTENT_EXPORT FrameTree {
RenderFrameHostManager::Delegate* manager_delegate);
~FrameTree();
+ // Returns the FrameTreeNode with the given |frame_tree_node_id|.
+ static FrameTreeNode* GloballyFindByID(int64 frame_tree_node_id);
+
FrameTreeNode* root() const { return root_.get(); }
- // Returns the FrameTreeNode with the given |frame_tree_node_id|.
+ // Returns the FrameTreeNode with the given |frame_tree_node_id| if it is part
+ // of this FrameTree.
FrameTreeNode* FindByID(int64 frame_tree_node_id);
// Returns the FrameTreeNode with the given renderer-specific |routing_id|.
@@ -67,10 +71,19 @@ class CONTENT_EXPORT FrameTree {
// Frame tree manipulation routines.
RenderFrameHostImpl* AddFrame(FrameTreeNode* parent,
+ int process_id,
int new_routing_id,
const std::string& frame_name);
void RemoveFrame(FrameTreeNode* child);
+ // This method walks the entire frame tree and creates a RenderFrameProxyHost
+ // for the given |site_instance| in each node except the |source| one --
+ // the source will have a RenderFrameHost. It assumes that no frame tree
+ // nodes already have RenderFrameProxyHost for the given |site_instance|.
+ void CreateProxiesForSiteInstance(
+ FrameTreeNode* source,
+ SiteInstance* site_instance);
+
// Clears process specific-state after a main frame process swap.
// This destroys most of the frame tree but retains the root node so that
// navigation state may be kept on it between process swaps. Used to
@@ -97,24 +110,22 @@ class CONTENT_EXPORT FrameTree {
// Allows a client to listen for frame removal. The listener should expect
// to receive the RenderViewHostImpl containing the frame and the renderer-
// specific frame routing ID of the removed frame.
- // TODO(creis): These parameters will later change to be the RenderFrameHost.
void SetFrameRemoveListener(
- const base::Callback<void(RenderViewHostImpl*, int)>& on_frame_removed);
+ const base::Callback<void(RenderFrameHost*)>& on_frame_removed);
- // Creates a RenderViewHost for a new main frame RenderFrameHost in the given
+ // Creates a RenderViewHost for a new RenderFrameHost in the given
// |site_instance|. The RenderViewHost will have its Shutdown method called
// when all of the RenderFrameHosts using it are deleted.
- RenderViewHostImpl* CreateRenderViewHostForMainFrame(
- SiteInstance* site_instance,
- int routing_id,
- int main_frame_routing_id,
- bool swapped_out,
- bool hidden);
-
- // Returns the existing RenderViewHost for a new subframe RenderFrameHost.
+ RenderViewHostImpl* CreateRenderViewHost(SiteInstance* site_instance,
+ int routing_id,
+ int main_frame_routing_id,
+ bool swapped_out,
+ bool hidden);
+
+ // Returns the existing RenderViewHost for a new RenderFrameHost.
// There should always be such a RenderViewHost, because the main frame
// RenderFrameHost for each SiteInstance should be created before subframes.
- RenderViewHostImpl* GetRenderViewHostForSubFrame(SiteInstance* site_instance);
+ RenderViewHostImpl* GetRenderViewHost(SiteInstance* site_instance);
// Keeps track of which RenderFrameHosts are using each RenderViewHost. When
// the number drops to zero, we call Shutdown on the RenderViewHost.
@@ -125,6 +136,11 @@ class CONTENT_EXPORT FrameTree {
typedef base::hash_map<int, RenderViewHostImpl*> RenderViewHostMap;
typedef std::multimap<int, RenderViewHostImpl*> RenderViewHostMultiMap;
+ // A variation to the public ForEach method with a difference that the subtree
+ // starting at |skip_this_subtree| will not be recursed into.
+ void ForEach(const base::Callback<bool(FrameTreeNode*)>& on_node,
+ FrameTreeNode* skip_this_subtree) const;
+
// These delegates are installed into all the RenderViewHosts and
// RenderFrameHosts that we create.
RenderFrameHostDelegate* render_frame_delegate_;
@@ -153,7 +169,7 @@ class CONTENT_EXPORT FrameTree {
int64 focused_frame_tree_node_id_;
- base::Callback<void(RenderViewHostImpl*, int)> on_frame_removed_;
+ base::Callback<void(RenderFrameHost*)> on_frame_removed_;
DISALLOW_COPY_AND_ASSIGN(FrameTree);
};
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index bc5f1cb04ff..9f16066cd38 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -2,12 +2,14 @@
// 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 "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -15,6 +17,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
namespace content {
@@ -102,6 +105,13 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeAfterCrash) {
NavigateToURL(shell(),
test_server()->GetURL("files/frame_tree/top.html"));
+ // Ensure the view and frame are live.
+ RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
+ RenderFrameHostImpl* rfh =
+ static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame());
+ EXPECT_TRUE(rvh->IsRenderViewLive());
+ EXPECT_TRUE(rfh->IsRenderFrameLive());
+
// Crash the renderer so that it doesn't send any FrameDetached messages.
RenderProcessHostWatcher crash_observer(
shell()->web_contents(),
@@ -114,11 +124,19 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeAfterCrash) {
FrameTreeNode* root = wc->GetFrameTree()->root();
EXPECT_EQ(0UL, root->child_count());
+ // Ensure the view and frame aren't live anymore.
+ EXPECT_FALSE(rvh->IsRenderViewLive());
+ EXPECT_FALSE(rfh->IsRenderFrameLive());
+
// Navigate to a new URL.
GURL url(test_server()->GetURL("files/title1.html"));
NavigateToURL(shell(), url);
EXPECT_EQ(0UL, root->child_count());
EXPECT_EQ(url, root->current_url());
+
+ // Ensure the view and frame are live again.
+ EXPECT_TRUE(rvh->IsRenderViewLive());
+ EXPECT_TRUE(rfh->IsRenderFrameLive());
}
// Test that we can navigate away if the previous renderer doesn't clean up its
@@ -155,4 +173,108 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateWithLeftoverFrames) {
EXPECT_EQ(0UL, root->child_count());
}
+// Ensure that IsRenderFrameLive is true for main frames and same-site iframes.
+IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, IsRenderFrameLive) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+ GURL main_url(test_server()->GetURL("files/frame_tree/top.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()->root();
+
+ // The root and subframe should each have a live RenderFrame.
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+
+ // Load a same-site page into iframe and it should still be live.
+ GURL http_url(test_server()->GetURL("files/title1.html"));
+ NavigateFrameToURL(root->child_at(0), http_url);
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+}
+
+class CrossProcessFrameTreeBrowserTest : public ContentBrowserTest {
+ public:
+ CrossProcessFrameTreeBrowserTest() {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kSitePerProcess);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CrossProcessFrameTreeBrowserTest);
+};
+
+// Ensure that we can complete a cross-process subframe navigation.
+#if defined(OS_ANDROID)
+#define MAYBE_CreateCrossProcessSubframeProxies DISABLED_CreateCrossProcessSubframeProxies
+#else
+#define MAYBE_CreateCrossProcessSubframeProxies CreateCrossProcessSubframeProxies
+#endif
+IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest,
+ MAYBE_CreateCrossProcessSubframeProxies) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(test_server()->Start());
+ GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()->root();
+
+ // There should not be a proxy for the root's own SiteInstance.
+ SiteInstance* root_instance = root->current_frame_host()->GetSiteInstance();
+ EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance));
+
+ // Load same-site page into iframe.
+ GURL http_url(test_server()->GetURL("files/title1.html"));
+ NavigateFrameToURL(root->child_at(0), http_url);
+
+ // These must stay in scope with replace_host.
+ GURL::Replacements replace_host;
+ std::string foo_com("foo.com");
+
+ // Load cross-site page into iframe.
+ GURL cross_site_url(test_server()->GetURL("files/title2.html"));
+ replace_host.SetHostStr(foo_com);
+ cross_site_url = cross_site_url.ReplaceComponents(replace_host);
+ NavigateFrameToURL(root->child_at(0), cross_site_url);
+
+ // Ensure that we have created a new process for the subframe.
+ ASSERT_EQ(2U, root->child_count());
+ FrameTreeNode* child = root->child_at(0);
+ SiteInstance* child_instance = child->current_frame_host()->GetSiteInstance();
+ RenderViewHost* rvh = child->current_frame_host()->render_view_host();
+ RenderProcessHost* rph = child->current_frame_host()->GetProcess();
+
+ EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), child_instance);
+ EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
+
+ // Ensure that the root node has a proxy for the child node's SiteInstance.
+ EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(child_instance));
+
+ // Also ensure that the child has a proxy for the root node's SiteInstance.
+ EXPECT_TRUE(child->render_manager()->GetRenderFrameProxyHost(root_instance));
+
+ // The nodes should not have proxies for their own SiteInstance.
+ EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance));
+ EXPECT_FALSE(
+ child->render_manager()->GetRenderFrameProxyHost(child_instance));
+
+ // Ensure that the RenderViews and RenderFrames are all live.
+ EXPECT_TRUE(
+ root->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(
+ child->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index ebc542e56e3..41be622302e 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -6,11 +6,13 @@
#include <queue>
+#include "base/command_line.h"
#include "base/stl_util.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/public/common/content_switches.h"
namespace content {
@@ -35,6 +37,10 @@ FrameTreeNode::FrameTreeNode(FrameTree* frame_tree,
parent_(NULL) {}
FrameTreeNode::~FrameTreeNode() {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ navigator_->CancelNavigation(this);
+ }
}
bool FrameTreeNode::IsMainFrame() const {
@@ -42,7 +48,11 @@ bool FrameTreeNode::IsMainFrame() const {
}
void FrameTreeNode::AddChild(scoped_ptr<FrameTreeNode> child,
+ int process_id,
int frame_routing_id) {
+ // Child frame must always be created in the same process as the parent.
+ CHECK_EQ(process_id, render_manager_.current_host()->GetProcess()->GetID());
+
// Initialize the RenderFrameHost for the new node. We always create child
// frames in the same SiteInstance as the current frame, and they can swap to
// a different one if they navigate away.
@@ -76,6 +86,9 @@ void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
void FrameTreeNode::ResetForNewProcess() {
current_url_ = GURL();
+ // The RenderFrame no longer exists and will need to be created again.
+ current_frame_host()->set_render_frame_created(false);
+
// The children may not have been cleared if a cross-process navigation
// commits before the old process cleans everything up. Make sure the child
// nodes get deleted before swapping to a new process.
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
index 3b5e6acb6b3..5974fd29bf5 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.h
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -41,7 +41,9 @@ class CONTENT_EXPORT FrameTreeNode {
bool IsMainFrame() const;
- void AddChild(scoped_ptr<FrameTreeNode> child, int frame_routing_id);
+ void AddChild(scoped_ptr<FrameTreeNode> child,
+ int process_id,
+ int frame_routing_id);
void RemoveChild(FrameTreeNode* child);
// Clears process specific-state in this node to prepare for a new process.
diff --git a/chromium/content/browser/frame_host/frame_tree_unittest.cc b/chromium/content/browser/frame_host/frame_tree_unittest.cc
index a894061f32c..bb705c7f881 100644
--- a/chromium/content/browser/frame_host/frame_tree_unittest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_unittest.cc
@@ -16,11 +16,13 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
+
namespace {
// Appends a description of the structure of the frame tree to |result|.
@@ -49,7 +51,7 @@ class TreeWalkingWebContentsLogger : public WebContentsObserver {
explicit TreeWalkingWebContentsLogger(WebContents* web_contents)
: WebContentsObserver(web_contents) {}
- virtual ~TreeWalkingWebContentsLogger() {
+ ~TreeWalkingWebContentsLogger() override {
EXPECT_EQ("", log_) << "Activity logged that was not expected";
}
@@ -61,15 +63,22 @@ class TreeWalkingWebContentsLogger : public WebContentsObserver {
}
// content::WebContentsObserver implementation.
- virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE {
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
LogWhatHappened("RenderFrameCreated", render_frame_host);
}
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE {
+ void RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) override {
+ if (old_host)
+ LogWhatHappened("RenderFrameChanged(old)", old_host);
+ LogWhatHappened("RenderFrameChanged(new)", new_host);
+ }
+
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
LogWhatHappened("RenderFrameDeleted", render_frame_host);
}
- virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
+ void RenderProcessGone(base::TerminationStatus status) override {
LogWhatHappened("RenderProcessGone");
}
@@ -94,6 +103,8 @@ class TreeWalkingWebContentsLogger : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(TreeWalkingWebContentsLogger);
};
+} // namespace
+
class FrameTreeTest : public RenderViewHostImplTestHarness {
protected:
// Prints a FrameTree, for easy assertions of the tree hierarchy.
@@ -115,17 +126,18 @@ TEST_F(FrameTreeTest, Shape) {
std::string no_children_node("no children node");
std::string deep_subtree("node with deep subtree");
+ int process_id = root->current_frame_host()->GetProcess()->GetID();
ASSERT_EQ("1: []", GetTreeState(frame_tree));
// Simulate attaching a series of frames to build the frame tree.
- frame_tree->AddFrame(root, 14, std::string());
- frame_tree->AddFrame(root, 15, std::string());
- frame_tree->AddFrame(root, 16, std::string());
+ frame_tree->AddFrame(root, process_id, 14, std::string());
+ frame_tree->AddFrame(root, process_id, 15, std::string());
+ frame_tree->AddFrame(root, process_id, 16, std::string());
- frame_tree->AddFrame(root->child_at(0), 244, std::string());
- frame_tree->AddFrame(root->child_at(1), 255, no_children_node);
- frame_tree->AddFrame(root->child_at(0), 245, std::string());
+ frame_tree->AddFrame(root->child_at(0), process_id, 244, std::string());
+ frame_tree->AddFrame(root->child_at(1), process_id, 255, no_children_node);
+ frame_tree->AddFrame(root->child_at(0), process_id, 245, std::string());
ASSERT_EQ("1: [14: [244: [], 245: []], "
"15: [255 'no children node': []], "
@@ -133,18 +145,19 @@ TEST_F(FrameTreeTest, Shape) {
GetTreeState(frame_tree));
FrameTreeNode* child_16 = root->child_at(2);
- frame_tree->AddFrame(child_16, 264, std::string());
- frame_tree->AddFrame(child_16, 265, std::string());
- frame_tree->AddFrame(child_16, 266, std::string());
- frame_tree->AddFrame(child_16, 267, deep_subtree);
- frame_tree->AddFrame(child_16, 268, std::string());
+ frame_tree->AddFrame(child_16, process_id, 264, std::string());
+ frame_tree->AddFrame(child_16, process_id, 265, std::string());
+ frame_tree->AddFrame(child_16, process_id, 266, std::string());
+ frame_tree->AddFrame(child_16, process_id, 267, deep_subtree);
+ frame_tree->AddFrame(child_16, process_id, 268, std::string());
FrameTreeNode* child_267 = child_16->child_at(3);
- frame_tree->AddFrame(child_267, 365, std::string());
- frame_tree->AddFrame(child_267->child_at(0), 455, std::string());
- frame_tree->AddFrame(child_267->child_at(0)->child_at(0), 555, std::string());
- frame_tree->AddFrame(child_267->child_at(0)->child_at(0)->child_at(0), 655,
+ frame_tree->AddFrame(child_267, process_id, 365, std::string());
+ frame_tree->AddFrame(child_267->child_at(0), process_id, 455, std::string());
+ frame_tree->AddFrame(child_267->child_at(0)->child_at(0), process_id, 555,
std::string());
+ frame_tree->AddFrame(child_267->child_at(0)->child_at(0)->child_at(0),
+ process_id, 655, std::string());
// Now that's it's fully built, verify the tree structure is as expected.
ASSERT_EQ("1: [14: [244: [], 245: []], "
@@ -186,6 +199,8 @@ TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
FrameTree* frame_tree = contents()->GetFrameTree();
FrameTreeNode* root = frame_tree->root();
+ EXPECT_EQ("", activity.GetLog());
+
// Simulate attaching a series of frames to build the frame tree.
main_test_rfh()->OnCreateChildFrame(14, std::string());
EXPECT_EQ("RenderFrameCreated(14) -> 1: [14: []]", activity.GetLog());
@@ -217,5 +232,18 @@ TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
activity.GetLog());
}
-} // namespace
+// Ensure that frames are not added to the tree, if the process passed in
+// is different than the process of the parent node.
+TEST_F(FrameTreeTest, FailAddFrameWithWrongProcessId) {
+ FrameTree* frame_tree = contents()->GetFrameTree();
+ FrameTreeNode* root = frame_tree->root();
+ int process_id = root->current_frame_host()->GetProcess()->GetID();
+
+ ASSERT_EQ("1: []", GetTreeState(frame_tree));
+
+ // Simulate attaching a frame from mismatched process id.
+ ASSERT_FALSE(frame_tree->AddFrame(root, process_id + 1, 1, std::string()));
+ ASSERT_EQ("1: []", GetTreeState(frame_tree));
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index a4ea2997bf7..72fd2043faf 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -40,9 +40,9 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/bindings_policy.h"
-#include "content/public/common/page_transition_types.h"
#include "net/base/escape.h"
#include "net/url_request/url_request_context_getter.h"
+#include "ui/base/page_transition_types.h"
using blink::WebDragOperation;
using blink::WebDragOperationsMask;
@@ -78,23 +78,24 @@ class InterstitialPageImpl::InterstitialPageRVHDelegateView
// RenderViewHostDelegateView implementation:
#if defined(OS_MACOSX) || defined(OS_ANDROID)
- virtual void ShowPopupMenu(const gfx::Rect& bounds,
- int item_height,
- double item_font_size,
- int selected_item,
- const std::vector<MenuItem>& items,
- bool right_aligned,
- bool allow_multiple_selection) OVERRIDE;
- virtual void HidePopupMenu() OVERRIDE;
+ void ShowPopupMenu(RenderFrameHost* render_frame_host,
+ const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection) override;
+ void HidePopupMenu() override;
#endif
- virtual void StartDragging(const DropData& drop_data,
- WebDragOperationsMask operations_allowed,
- const gfx::ImageSkia& image,
- const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(WebDragOperation operation) OVERRIDE;
- virtual void GotFocus() OVERRIDE;
- virtual void TakeFocus(bool reverse) OVERRIDE;
+ void StartDragging(const DropData& drop_data,
+ WebDragOperationsMask operations_allowed,
+ const gfx::ImageSkia& image,
+ const gfx::Vector2d& image_offset,
+ const DragEventSourceInfo& event_info) override;
+ void UpdateDragCursor(WebDragOperation operation) override;
+ void GotFocus() override;
+ void TakeFocus(bool reverse) override;
virtual void OnFindReply(int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
@@ -148,7 +149,7 @@ InterstitialPageImpl::InterstitialPageImpl(
bool new_navigation,
const GURL& url,
InterstitialPageDelegate* delegate)
- : WebContentsObserver(web_contents),
+ : underlying_content_observer_(web_contents, this),
web_contents_(web_contents),
controller_(static_cast<NavigationControllerImpl*>(
&web_contents->GetController())),
@@ -243,13 +244,13 @@ void InterstitialPageImpl::Show() {
}
DCHECK(!render_view_host_);
- render_view_host_ = static_cast<RenderViewHostImpl*>(CreateRenderViewHost());
+ render_view_host_ = CreateRenderViewHost();
render_view_host_->AttachToFrameTree();
CreateWebContentsView();
std::string data_url = "data:text/html;charset=utf-8," +
net::EscapePath(delegate_->GetHTMLContents());
- render_view_host_->NavigateToURL(GURL(data_url));
+ frame_tree_.root()->current_frame_host()->NavigateToURL(GURL(data_url));
notification_registrar_.Add(this, NOTIFICATION_NAV_ENTRY_PENDING,
Source<NavigationController>(controller_));
@@ -351,32 +352,13 @@ void InterstitialPageImpl::Observe(
}
}
-void InterstitialPageImpl::NavigationEntryCommitted(
- const LoadCommittedDetails& load_details) {
- OnNavigatingAwayOrTabClosing();
-}
-
-void InterstitialPageImpl::WebContentsDestroyed() {
- OnNavigatingAwayOrTabClosing();
-}
-
-bool InterstitialPageImpl::OnMessageReceived(
- const IPC::Message& message,
- RenderFrameHost* render_frame_host) {
- return OnMessageReceived(message);
-}
-
bool InterstitialPageImpl::OnMessageReceived(RenderFrameHost* render_frame_host,
const IPC::Message& message) {
- return OnMessageReceived(message);
-}
-
-bool InterstitialPageImpl::OnMessageReceived(RenderViewHost* render_view_host,
- const IPC::Message& message) {
- return OnMessageReceived(message);
-}
-
-bool InterstitialPageImpl::OnMessageReceived(const IPC::Message& message) {
+ if (render_frame_host->GetRenderViewHost() != render_view_host_) {
+ DCHECK(!render_view_host_)
+ << "We expect an interstitial page to have only a single RVH";
+ return false;
+ }
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(InterstitialPageImpl, message)
@@ -388,6 +370,11 @@ bool InterstitialPageImpl::OnMessageReceived(const IPC::Message& message) {
return handled;
}
+bool InterstitialPageImpl::OnMessageReceived(RenderViewHost* render_view_host,
+ const IPC::Message& message) {
+ return false;
+}
+
void InterstitialPageImpl::RenderFrameCreated(
RenderFrameHost* render_frame_host) {
// Note this is only for subframes in the interstitial, the notification for
@@ -432,6 +419,13 @@ void InterstitialPageImpl::UpdateTitle(
controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE);
}
+AccessibilityMode InterstitialPageImpl::GetAccessibilityMode() const {
+ if (web_contents_)
+ return static_cast<WebContentsImpl*>(web_contents_)->GetAccessibilityMode();
+ else
+ return AccessibilityModeOff;
+}
+
RenderViewHostDelegateView* InterstitialPageImpl::GetDelegateView() {
return rvh_delegate_view_.get();
}
@@ -462,8 +456,8 @@ void InterstitialPageImpl::DidNavigate(
DontProceed();
return;
}
- if (PageTransitionCoreTypeIs(params.transition,
- PAGE_TRANSITION_AUTO_SUBFRAME)) {
+ if (ui::PageTransitionCoreTypeIs(params.transition,
+ ui::PAGE_TRANSITION_AUTO_SUBFRAME)) {
// No need to handle navigate message from iframe in the interstitial page.
return;
}
@@ -502,11 +496,11 @@ RendererPreferences InterstitialPageImpl::GetRendererPrefs(
return renderer_preferences_;
}
-WebPreferences InterstitialPageImpl::GetWebkitPrefs() {
+WebPreferences InterstitialPageImpl::ComputeWebkitPrefs() {
if (!enabled())
return WebPreferences();
- return render_view_host_->GetWebkitPrefs(url_);
+ return render_view_host_->ComputeWebkitPrefs(url_);
}
void InterstitialPageImpl::RenderWidgetDeleted(
@@ -533,7 +527,11 @@ void InterstitialPageImpl::HandleKeyboardEvent(
#if defined(OS_WIN)
gfx::NativeViewAccessible
InterstitialPageImpl::GetParentNativeViewAccessible() {
- return render_widget_host_delegate_->GetParentNativeViewAccessible();
+ if (web_contents_) {
+ WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_);
+ return wci->GetParentNativeViewAccessible();
+ }
+ return NULL;
}
#endif
@@ -541,7 +539,7 @@ WebContents* InterstitialPageImpl::web_contents() const {
return web_contents_;
}
-RenderViewHost* InterstitialPageImpl::CreateRenderViewHost() {
+RenderViewHostImpl* InterstitialPageImpl::CreateRenderViewHost() {
if (!enabled())
return NULL;
@@ -569,7 +567,7 @@ WebContentsView* InterstitialPageImpl::CreateWebContentsView() {
WebContentsView* wcv =
static_cast<WebContentsImpl*>(web_contents())->GetView();
RenderWidgetHostViewBase* view =
- wcv->CreateViewForWidget(render_view_host_);
+ wcv->CreateViewForWidget(render_view_host_, false);
render_view_host_->SetView(view);
render_view_host_->AllowBindings(BINDINGS_POLICY_DOM_AUTOMATION);
@@ -852,6 +850,7 @@ InterstitialPageImpl::InterstitialPageRVHDelegateView::
#if defined(OS_MACOSX) || defined(OS_ANDROID)
void InterstitialPageImpl::InterstitialPageRVHDelegateView::ShowPopupMenu(
+ RenderFrameHost* render_frame_host,
const gfx::Rect& bounds,
int item_height,
double item_font_size,
@@ -905,4 +904,19 @@ void InterstitialPageImpl::InterstitialPageRVHDelegateView::OnFindReply(
int active_match_ordinal, bool final_update) {
}
+InterstitialPageImpl::UnderlyingContentObserver::UnderlyingContentObserver(
+ WebContents* web_contents,
+ InterstitialPageImpl* interstitial)
+ : WebContentsObserver(web_contents), interstitial_(interstitial) {
+}
+
+void InterstitialPageImpl::UnderlyingContentObserver::NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) {
+ interstitial_->OnNavigatingAwayOrTabClosing();
+}
+
+void InterstitialPageImpl::UnderlyingContentObserver::WebContentsDestroyed() {
+ interstitial_->OnNavigatingAwayOrTabClosing();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 8068fd34e01..9f6ce8445aa 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -37,7 +37,6 @@ enum ResourceRequestAction {
class CONTENT_EXPORT InterstitialPageImpl
: public NON_EXPORTED_BASE(InterstitialPage),
public NotificationObserver,
- public WebContentsObserver,
public NON_EXPORTED_BASE(RenderFrameHostDelegate),
public RenderViewHostDelegate,
public RenderWidgetHostDelegate,
@@ -55,18 +54,18 @@ class CONTENT_EXPORT InterstitialPageImpl
bool new_navigation,
const GURL& url,
InterstitialPageDelegate* delegate);
- virtual ~InterstitialPageImpl();
+ ~InterstitialPageImpl() override;
// InterstitialPage implementation:
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual void DontProceed() OVERRIDE;
- virtual void Proceed() OVERRIDE;
- virtual RenderViewHost* GetRenderViewHostForTesting() const OVERRIDE;
- virtual InterstitialPageDelegate* GetDelegateForTesting() OVERRIDE;
- virtual void DontCreateViewForTesting() OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void Focus() OVERRIDE;
+ void Show() override;
+ void Hide() override;
+ void DontProceed() override;
+ void Proceed() override;
+ RenderViewHost* GetRenderViewHostForTesting() const override;
+ InterstitialPageDelegate* GetDelegateForTesting() override;
+ void DontCreateViewForTesting() override;
+ void SetSize(const gfx::Size& size) override;
+ void Focus() override;
// Allows the user to navigate away by disabling the interstitial, canceling
// the pending request, and unblocking the hidden renderer. The interstitial
@@ -99,83 +98,67 @@ class CONTENT_EXPORT InterstitialPageImpl
protected:
// NotificationObserver method:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
-
- // WebContentsObserver implementation:
- virtual bool OnMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void WebContentsDestroyed() OVERRIDE;
- virtual void NavigationEntryCommitted(
- const LoadCommittedDetails& load_details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
// RenderFrameHostDelegate implementation:
- virtual bool OnMessageReceived(RenderFrameHost* render_frame_host,
- const IPC::Message& message) OVERRIDE;
- virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void UpdateTitle(RenderFrameHost* render_frame_host,
- int32 page_id,
- const base::string16& title,
- base::i18n::TextDirection title_direction) OVERRIDE;
+ bool OnMessageReceived(RenderFrameHost* render_frame_host,
+ const IPC::Message& message) override;
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
+ void UpdateTitle(RenderFrameHost* render_frame_host,
+ int32 page_id,
+ const base::string16& title,
+ base::i18n::TextDirection title_direction) override;
+ AccessibilityMode GetAccessibilityMode() const override;
// RenderViewHostDelegate implementation:
- virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE;
- virtual bool OnMessageReceived(RenderViewHost* render_view_host,
- const IPC::Message& message) OVERRIDE;
- virtual const GURL& GetMainFrameLastCommittedURL() const OVERRIDE;
- virtual void RenderViewTerminated(RenderViewHost* render_view_host,
- base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual RendererPreferences GetRendererPrefs(
- BrowserContext* browser_context) const OVERRIDE;
- virtual WebPreferences GetWebkitPrefs() OVERRIDE;
- virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
- virtual void CreateNewWindow(
+ RenderViewHostDelegateView* GetDelegateView() override;
+ bool OnMessageReceived(RenderViewHost* render_view_host,
+ const IPC::Message& message) override;
+ const GURL& GetMainFrameLastCommittedURL() const override;
+ void RenderViewTerminated(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code) override;
+ RendererPreferences GetRendererPrefs(
+ BrowserContext* browser_context) const override;
+ WebPreferences ComputeWebkitPrefs() override;
+ gfx::Rect GetRootWindowResizerRect() const override;
+ void CreateNewWindow(
int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
- SessionStorageNamespace* session_storage_namespace) OVERRIDE;
- virtual void CreateNewWidget(int render_process_id,
- int route_id,
- blink::WebPopupType popup_type) OVERRIDE;
- virtual void CreateNewFullscreenWidget(int render_process_id,
- int route_id) OVERRIDE;
- virtual void ShowCreatedWindow(int route_id,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_pos,
- bool user_gesture) OVERRIDE;
- virtual void ShowCreatedWidget(int route_id,
- const gfx::Rect& initial_pos) OVERRIDE;
- virtual void ShowCreatedFullscreenWidget(int route_id) OVERRIDE;
-
- virtual SessionStorageNamespace* GetSessionStorageNamespace(
- SiteInstance* instance) OVERRIDE;
-
- virtual FrameTree* GetFrameTree() OVERRIDE;
+ SessionStorageNamespace* session_storage_namespace) override;
+ void CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) override;
+ void CreateNewFullscreenWidget(int render_process_id, int route_id) override;
+ void ShowCreatedWindow(int route_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) override;
+ void ShowCreatedWidget(int route_id, const gfx::Rect& initial_pos) override;
+ void ShowCreatedFullscreenWidget(int route_id) override;
+
+ SessionStorageNamespace* GetSessionStorageNamespace(
+ SiteInstance* instance) override;
+
+ FrameTree* GetFrameTree() override;
// RenderWidgetHostDelegate implementation:
- virtual void RenderWidgetDeleted(
- RenderWidgetHostImpl* render_widget_host) OVERRIDE;
- virtual bool PreHandleKeyboardEvent(
- const NativeWebKeyboardEvent& event,
- bool* is_keyboard_shortcut) OVERRIDE;
- virtual void HandleKeyboardEvent(
- const NativeWebKeyboardEvent& event) OVERRIDE;
+ void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
+ bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) override;
+ void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
#if defined(OS_WIN)
- virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
+ virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
#endif
bool enabled() const { return enabled_; }
WebContents* web_contents() const;
const GURL& url() const { return url_; }
- // Creates the RenderViewHost containing the interstitial content.
- // Overriden in unit tests.
- virtual RenderViewHost* CreateRenderViewHost();
-
// Creates the WebContentsView that shows the interstitial RVH.
// Overriden in unit tests.
virtual WebContentsView* CreateWebContentsView();
@@ -185,6 +168,27 @@ class CONTENT_EXPORT InterstitialPageImpl
private:
class InterstitialPageRVHDelegateView;
+ class UnderlyingContentObserver : public WebContentsObserver {
+ public:
+ UnderlyingContentObserver(WebContents* web_contents,
+ InterstitialPageImpl* interstitial);
+
+ // WebContentsObserver implementation:
+ void WebContentsDestroyed() override;
+ void NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) override;
+
+ // This observer does not override OnMessageReceived or otherwise handle
+ // messages from the underlying content, because the interstitial should not
+ // care about them. Messages from the interstitial page (which has its own
+ // FrameTree) arrive through the RenderFrameHostDelegate interface, not
+ // WebContentsObserver.
+
+ private:
+ InterstitialPageImpl* const interstitial_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnderlyingContentObserver);
+ };
// Disable the interstitial:
// - if it is not yet showing, then it won't be shown.
@@ -205,6 +209,12 @@ class CONTENT_EXPORT InterstitialPageImpl
void OnDomOperationResponse(const std::string& json_string,
int automation_id);
+ // Creates the RenderViewHost containing the interstitial content.
+ RenderViewHostImpl* CreateRenderViewHost();
+
+ // Watches the underlying WebContents for reasons to cancel the interstitial.
+ UnderlyingContentObserver underlying_content_observer_;
+
// The contents in which we are displayed. This is valid until Hide is
// called, at which point it will be set to NULL because the WebContents
// itself may be deleted.
@@ -281,10 +291,10 @@ class CONTENT_EXPORT InterstitialPageImpl
scoped_ptr<InterstitialPageDelegate> delegate_;
- base::WeakPtrFactory<InterstitialPageImpl> weak_ptr_factory_;
-
scoped_refptr<SessionStorageNamespace> session_storage_namespace_;
+ base::WeakPtrFactory<InterstitialPageImpl> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(InterstitialPageImpl);
};
diff --git a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
index 707754661e0..2f9661440c0 100644
--- a/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_navigator_impl.h
@@ -22,14 +22,13 @@ class CONTENT_EXPORT InterstitialPageNavigatorImpl : public Navigator {
InterstitialPageImpl* interstitial,
NavigationControllerImpl* navigation_controller);
- virtual NavigationController* GetController() OVERRIDE;
- virtual void DidNavigate(
- RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params&
- input_params) OVERRIDE;
+ NavigationController* GetController() override;
+ void DidNavigate(RenderFrameHostImpl* render_frame_host,
+ const FrameHostMsg_DidCommitProvisionalLoad_Params&
+ input_params) override;
private:
- virtual ~InterstitialPageNavigatorImpl() {}
+ ~InterstitialPageNavigatorImpl() override {}
// The InterstitialPage with which this navigator object is associated.
// Non owned pointer.
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 536e17dd3ec..52ef78ee5d1 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -5,10 +5,64 @@
#include "content/browser/frame_host/navigation_controller_android.h"
#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/ssl_host_state_delegate.h"
#include "jni/NavigationControllerImpl_jni.h"
+#include "ui/gfx/android/java_bitmap.h"
using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF16;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF16ToJavaString;
+using base::android::ConvertUTF8ToJavaString;
+namespace {
+
+// static
+static base::android::ScopedJavaLocalRef<jobject> CreateJavaNavigationEntry(
+ JNIEnv* env,
+ content::NavigationEntry* entry,
+ int index) {
+ DCHECK(entry);
+
+ // Get the details of the current entry
+ ScopedJavaLocalRef<jstring> j_url(
+ ConvertUTF8ToJavaString(env, entry->GetURL().spec()));
+ ScopedJavaLocalRef<jstring> j_virtual_url(
+ ConvertUTF8ToJavaString(env, entry->GetVirtualURL().spec()));
+ ScopedJavaLocalRef<jstring> j_original_url(
+ ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec()));
+ ScopedJavaLocalRef<jstring> j_title(
+ ConvertUTF16ToJavaString(env, entry->GetTitle()));
+ ScopedJavaLocalRef<jobject> j_bitmap;
+ const content::FaviconStatus& status = entry->GetFavicon();
+ if (status.valid && status.image.ToSkBitmap()->getSize() > 0)
+ j_bitmap = gfx::ConvertToJavaBitmap(status.image.ToSkBitmap());
+
+ return content::Java_NavigationControllerImpl_createNavigationEntry(
+ env,
+ index,
+ j_url.obj(),
+ j_virtual_url.obj(),
+ j_original_url.obj(),
+ j_title.obj(),
+ j_bitmap.obj());
+}
+
+static void AddNavigationEntryToHistory(JNIEnv* env,
+ jobject history,
+ content::NavigationEntry* entry,
+ int index) {
+ content::Java_NavigationControllerImpl_addToNavigationHistory(
+ env,
+ history,
+ CreateJavaNavigationEntry(env, entry, index).obj());
+}
+
+} // namespace
namespace content {
@@ -64,10 +118,208 @@ void NavigationControllerAndroid::GoToOffset(JNIEnv* env,
navigation_controller_->GoToOffset(offset);
}
+void NavigationControllerAndroid::LoadIfNecessary(JNIEnv* env, jobject obj) {
+ navigation_controller_->LoadIfNecessary();
+}
+
+void NavigationControllerAndroid::ContinuePendingReload(JNIEnv* env,
+ jobject obj) {
+ navigation_controller_->ContinuePendingReload();
+}
+
+void NavigationControllerAndroid::Reload(JNIEnv* env,
+ jobject obj,
+ jboolean check_for_repost) {
+ navigation_controller_->Reload(check_for_repost);
+}
+
+void NavigationControllerAndroid::ReloadIgnoringCache(
+ JNIEnv* env,
+ jobject obj,
+ jboolean check_for_repost) {
+ navigation_controller_->ReloadIgnoringCache(check_for_repost);
+}
+
+void NavigationControllerAndroid::RequestRestoreLoad(JNIEnv* env, jobject obj) {
+ navigation_controller_->SetNeedsReload();
+}
+
+void NavigationControllerAndroid::CancelPendingReload(JNIEnv* env,
+ jobject obj) {
+ navigation_controller_->CancelPendingReload();
+}
+
void NavigationControllerAndroid::GoToNavigationIndex(JNIEnv* env,
jobject obj,
jint index) {
navigation_controller_->GoToIndex(index);
}
+void NavigationControllerAndroid::LoadUrl(JNIEnv* env,
+ jobject obj,
+ jstring url,
+ jint load_url_type,
+ jint transition_type,
+ jstring j_referrer_url,
+ jint referrer_policy,
+ jint ua_override_option,
+ jstring extra_headers,
+ jbyteArray post_data,
+ jstring base_url_for_data_url,
+ jstring virtual_url_for_data_url,
+ jboolean can_load_local_resources,
+ jboolean is_renderer_initiated) {
+ DCHECK(url);
+ NavigationController::LoadURLParams params(
+ GURL(ConvertJavaStringToUTF8(env, url)));
+
+ params.load_type =
+ static_cast<NavigationController::LoadURLType>(load_url_type);
+ params.transition_type = ui::PageTransitionFromInt(transition_type);
+ params.override_user_agent =
+ static_cast<NavigationController::UserAgentOverrideOption>(
+ ua_override_option);
+ params.can_load_local_resources = can_load_local_resources;
+ params.is_renderer_initiated = is_renderer_initiated;
+
+ if (extra_headers)
+ params.extra_headers = ConvertJavaStringToUTF8(env, extra_headers);
+
+ if (post_data) {
+ std::vector<uint8> http_body_vector;
+ base::android::JavaByteArrayToByteVector(env, post_data, &http_body_vector);
+ params.browser_initiated_post_data =
+ base::RefCountedBytes::TakeVector(&http_body_vector);
+ }
+
+ if (base_url_for_data_url) {
+ params.base_url_for_data_url =
+ GURL(ConvertJavaStringToUTF8(env, base_url_for_data_url));
+ }
+
+ if (virtual_url_for_data_url) {
+ params.virtual_url_for_data_url =
+ GURL(ConvertJavaStringToUTF8(env, virtual_url_for_data_url));
+ }
+
+ if (j_referrer_url) {
+ params.referrer = content::Referrer(
+ GURL(ConvertJavaStringToUTF8(env, j_referrer_url)),
+ static_cast<blink::WebReferrerPolicy>(referrer_policy));
+ }
+
+ navigation_controller_->LoadURLWithParams(params);
+}
+
+void NavigationControllerAndroid::ClearHistory(JNIEnv* env, jobject obj) {
+ // TODO(creis): Do callers of this need to know if it fails?
+ if (navigation_controller_->CanPruneAllButLastCommitted())
+ navigation_controller_->PruneAllButLastCommitted();
+}
+
+jint NavigationControllerAndroid::GetNavigationHistory(JNIEnv* env,
+ jobject obj,
+ jobject history) {
+ // Iterate through navigation entries to populate the list
+ int count = navigation_controller_->GetEntryCount();
+ for (int i = 0; i < count; ++i) {
+ AddNavigationEntryToHistory(
+ env, history, navigation_controller_->GetEntryAtIndex(i), i);
+ }
+
+ return navigation_controller_->GetCurrentEntryIndex();
+}
+
+void NavigationControllerAndroid::GetDirectedNavigationHistory(
+ JNIEnv* env,
+ jobject obj,
+ jobject history,
+ jboolean is_forward,
+ jint max_entries) {
+ // Iterate through navigation entries to populate the list
+ int count = navigation_controller_->GetEntryCount();
+ int num_added = 0;
+ int increment_value = is_forward ? 1 : -1;
+ for (int i = navigation_controller_->GetCurrentEntryIndex() + increment_value;
+ i >= 0 && i < count;
+ i += increment_value) {
+ if (num_added >= max_entries)
+ break;
+
+ AddNavigationEntryToHistory(
+ env, history, navigation_controller_->GetEntryAtIndex(i), i);
+ num_added++;
+ }
+}
+
+ScopedJavaLocalRef<jstring>
+NavigationControllerAndroid::GetOriginalUrlForVisibleNavigationEntry(
+ JNIEnv* env,
+ jobject obj) {
+ NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
+ if (entry == NULL)
+ return ScopedJavaLocalRef<jstring>(env, NULL);
+ return ConvertUTF8ToJavaString(env, entry->GetOriginalRequestURL().spec());
+}
+
+void NavigationControllerAndroid::ClearSslPreferences(JNIEnv* env,
+ jobject obj) {
+ content::SSLHostStateDelegate* delegate =
+ navigation_controller_->GetBrowserContext()->GetSSLHostStateDelegate();
+ if (delegate)
+ delegate->Clear();
+}
+
+bool NavigationControllerAndroid::GetUseDesktopUserAgent(JNIEnv* env,
+ jobject obj) {
+ NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
+ return entry && entry->GetIsOverridingUserAgent();
+}
+
+void NavigationControllerAndroid::SetUseDesktopUserAgent(
+ JNIEnv* env,
+ jobject obj,
+ jboolean enabled,
+ jboolean reload_on_state_change) {
+ if (GetUseDesktopUserAgent(env, obj) == enabled)
+ return;
+
+ // Make sure the navigation entry actually exists.
+ NavigationEntry* entry = navigation_controller_->GetVisibleEntry();
+ if (!entry)
+ return;
+
+ // Set the flag in the NavigationEntry.
+ entry->SetIsOverridingUserAgent(enabled);
+
+ // Send the override to the renderer.
+ if (reload_on_state_change) {
+ // Reloading the page will send the override down as part of the
+ // navigation IPC message.
+ navigation_controller_->ReloadOriginalRequestURL(false);
+ }
+}
+
+base::android::ScopedJavaLocalRef<jobject>
+NavigationControllerAndroid::GetPendingEntry(JNIEnv* env, jobject obj) {
+ content::NavigationEntry* entry = navigation_controller_->GetPendingEntry();
+
+ if (!entry)
+ return base::android::ScopedJavaLocalRef<jobject>();
+
+ return CreateJavaNavigationEntry(
+ env, entry, navigation_controller_->GetPendingEntryIndex());
+}
+
+jint NavigationControllerAndroid::GetLastCommittedEntryIndex(JNIEnv* env,
+ jobject obj) {
+ return navigation_controller_->GetLastCommittedEntryIndex();
+}
+
+jboolean NavigationControllerAndroid::RemoveEntryAtIndex(JNIEnv* env,
+ jobject obj,
+ jint index) {
+ return navigation_controller_->RemoveEntryAtIndex(index);
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
index e0c96a63a0c..9b9a8c67062 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.h
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -39,7 +39,46 @@ class CONTENT_EXPORT NavigationControllerAndroid {
void GoBack(JNIEnv* env, jobject obj);
void GoForward(JNIEnv* env, jobject obj);
void GoToOffset(JNIEnv* env, jobject obj, jint offset);
+ void LoadIfNecessary(JNIEnv* env, jobject obj);
+ void ContinuePendingReload(JNIEnv* env, jobject obj);
+ void Reload(JNIEnv* env, jobject obj, jboolean check_for_repost);
+ void ReloadIgnoringCache(JNIEnv* env, jobject obj, jboolean check_for_repost);
+ void RequestRestoreLoad(JNIEnv* env, jobject obj);
+ void CancelPendingReload(JNIEnv* env, jobject obj);
void GoToNavigationIndex(JNIEnv* env, jobject obj, jint index);
+ void LoadUrl(JNIEnv* env,
+ jobject obj,
+ jstring url,
+ jint load_url_type,
+ jint transition_type,
+ jstring j_referrer_url,
+ jint referrer_policy,
+ jint ua_override_option,
+ jstring extra_headers,
+ jbyteArray post_data,
+ jstring base_url_for_data_url,
+ jstring virtual_url_for_data_url,
+ jboolean can_load_local_resources,
+ jboolean is_renderer_initiated);
+ void ClearSslPreferences(JNIEnv* env, jobject /* obj */);
+ bool GetUseDesktopUserAgent(JNIEnv* env, jobject /* obj */);
+ void SetUseDesktopUserAgent(JNIEnv* env,
+ jobject /* obj */,
+ jboolean state,
+ jboolean reload_on_state_change);
+ base::android::ScopedJavaLocalRef<jobject> GetPendingEntry(JNIEnv* env,
+ jobject /* obj */);
+ int GetNavigationHistory(JNIEnv* env, jobject obj, jobject history);
+ void GetDirectedNavigationHistory(JNIEnv* env,
+ jobject obj,
+ jobject history,
+ jboolean is_forward,
+ jint max_entries);
+ base::android::ScopedJavaLocalRef<jstring>
+ GetOriginalUrlForVisibleNavigationEntry(JNIEnv* env, jobject obj);
+ void ClearHistory(JNIEnv* env, jobject obj);
+ int GetLastCommittedEntryIndex(JNIEnv* env, jobject obj);
+ jboolean RemoveEntryAtIndex(JNIEnv* env, jobject obj, jint index);
private:
NavigationController* navigation_controller_;
diff --git a/chromium/content/browser/frame_host/navigation_controller_delegate.h b/chromium/content/browser/frame_host/navigation_controller_delegate.h
index 49dfc60bef0..52567ef3c62 100644
--- a/chromium/content/browser/frame_host/navigation_controller_delegate.h
+++ b/chromium/content/browser/frame_host/navigation_controller_delegate.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_CONTROLLER_DELEGATE_H_
#include <string>
+#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
@@ -34,7 +35,7 @@ class NavigationControllerDelegate {
virtual RenderViewHost* GetRenderViewHost() const = 0;
virtual InterstitialPage* GetInterstitialPage() const = 0;
virtual const std::string& GetContentsMimeType() const = 0;
- virtual void NotifyNavigationStateChanged(unsigned changed_flags) = 0;
+ virtual void NotifyNavigationStateChanged(InvalidateTypes changed_flags) = 0;
virtual void Stop() = 0;
virtual SiteInstance* GetPendingSiteInstance() const = 0;
virtual int32 GetMaxPageID() = 0;
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 6d1c597d760..4be5a3ce4a0 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -46,8 +46,6 @@
namespace content {
namespace {
-const int kInvalidateAll = 0xFFFFFFFF;
-
// Invoked when entries have been pruned, or removed. For example, if the
// current entries are [google, digg, yahoo], with the current entry google,
// and the user types in cnet, then digg and yahoo are pruned.
@@ -97,31 +95,44 @@ void ConfigureEntriesForRestore(
for (size_t i = 0; i < entries->size(); ++i) {
// Use a transition type of reload so that we don't incorrectly increase
// the typed count.
- (*entries)[i]->SetTransitionType(PAGE_TRANSITION_RELOAD);
+ (*entries)[i]->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
(*entries)[i]->set_restore_type(ControllerRestoreTypeToEntryType(type));
// NOTE(darin): This code is only needed for backwards compat.
SetPageStateIfEmpty((*entries)[i].get());
}
}
-// See NavigationController::IsURLInPageNavigation for how this works and why.
+// There are two general cases where a navigation is in page:
+// 1. A fragment navigation, in which the url is kept the same except for the
+// reference fragment.
+// 2. A history API navigation (pushState and replaceState). This case is
+// always in-page, but the urls are not guaranteed to match excluding the
+// fragment. The relevant spec allows pushState/replaceState to any URL on
+// the same origin.
+// However, due to reloads, even identical urls are *not* guaranteed to be
+// in-page navigations, we have to trust the renderer almost entirely.
+// The one thing we do know is that cross-origin navigations will *never* be
+// in-page. Therefore, trust the renderer if the URLs are on the same origin,
+// and assume the renderer is malicious if a cross-origin navigation claims to
+// be in-page.
bool AreURLsInPageNavigation(const GURL& existing_url,
const GURL& new_url,
bool renderer_says_in_page,
- NavigationType navigation_type) {
- if (existing_url.GetOrigin() == new_url.GetOrigin())
- return renderer_says_in_page;
-
- if (!new_url.has_ref()) {
- // When going back from the ref URL to the non ref one the navigation type
- // is IN_PAGE.
- return navigation_type == NAVIGATION_TYPE_IN_PAGE;
- }
-
- url::Replacements<char> replacements;
- replacements.ClearRef();
- return existing_url.ReplaceComponents(replacements) ==
- new_url.ReplaceComponents(replacements);
+ RenderFrameHost* rfh) {
+ WebPreferences prefs = rfh->GetRenderViewHost()->GetWebkitPreferences();
+ bool is_same_origin = existing_url.is_empty() ||
+ // TODO(japhet): We should only permit navigations
+ // originating from about:blank to be in-page if the
+ // about:blank is the first document that frame loaded.
+ // We don't have sufficient information to identify
+ // that case at the moment, so always allow about:blank
+ // for now.
+ existing_url == GURL(url::kAboutBlankURL) ||
+ existing_url.GetOrigin() == new_url.GetOrigin() ||
+ !prefs.web_security_enabled;
+ if (!is_same_origin && renderer_says_in_page)
+ rfh->GetProcess()->ReceivedBadMessage();
+ return is_same_origin && renderer_says_in_page;
}
// Determines whether or not we should be carrying over a user agent override
@@ -134,7 +145,7 @@ bool ShouldKeepOverride(const NavigationEntry* last_entry) {
// NavigationControllerImpl ----------------------------------------------------
-const size_t kMaxEntryCountForTestingNotSet = -1;
+const size_t kMaxEntryCountForTestingNotSet = static_cast<size_t>(-1);
// static
size_t NavigationControllerImpl::max_entry_count_for_testing_ =
@@ -148,7 +159,7 @@ static bool g_check_for_repost = true;
NavigationEntry* NavigationController::CreateNavigationEntry(
const GURL& url,
const Referrer& referrer,
- PageTransition transition,
+ ui::PageTransition transition,
bool is_renderer_initiated,
const std::string& extra_headers,
BrowserContext* browser_context) {
@@ -277,7 +288,7 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
return;
LoadURL(transient_entry->GetURL(),
Referrer(),
- PAGE_TRANSITION_RELOAD,
+ ui::PAGE_TRANSITION_RELOAD,
transient_entry->extra_headers());
return;
}
@@ -365,7 +376,7 @@ void NavigationControllerImpl::ReloadInternal(bool check_for_repost,
// See Chromium issue 96041.
pending_entry_->SetTitle(base::string16());
- pending_entry_->SetTransitionType(PAGE_TRANSITION_RELOAD);
+ pending_entry_->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
}
NavigateToPendingEntry(reload_type);
@@ -541,9 +552,9 @@ void NavigationControllerImpl::GoBack() {
pending_entry_index_ = current_index - 1;
entries_[pending_entry_index_]->SetTransitionType(
- PageTransitionFromInt(
+ ui::PageTransitionFromInt(
entries_[pending_entry_index_]->GetTransitionType() |
- PAGE_TRANSITION_FORWARD_BACK));
+ ui::PAGE_TRANSITION_FORWARD_BACK));
NavigateToPendingEntry(NO_RELOAD);
}
@@ -567,9 +578,9 @@ void NavigationControllerImpl::GoForward() {
pending_entry_index_++;
entries_[pending_entry_index_]->SetTransitionType(
- PageTransitionFromInt(
+ ui::PageTransitionFromInt(
entries_[pending_entry_index_]->GetTransitionType() |
- PAGE_TRANSITION_FORWARD_BACK));
+ ui::PAGE_TRANSITION_FORWARD_BACK));
NavigateToPendingEntry(NO_RELOAD);
}
@@ -594,9 +605,9 @@ void NavigationControllerImpl::GoToIndex(int index) {
pending_entry_index_ = index;
entries_[pending_entry_index_]->SetTransitionType(
- PageTransitionFromInt(
+ ui::PageTransitionFromInt(
entries_[pending_entry_index_]->GetTransitionType() |
- PAGE_TRANSITION_FORWARD_BACK));
+ ui::PAGE_TRANSITION_FORWARD_BACK));
NavigateToPendingEntry(NO_RELOAD);
}
@@ -628,7 +639,7 @@ void NavigationControllerImpl::UpdateVirtualURLToURL(
void NavigationControllerImpl::LoadURL(
const GURL& url,
const Referrer& referrer,
- PageTransition transition,
+ ui::PageTransition transition,
const std::string& extra_headers) {
LoadURLParams params(url);
params.referrer = referrer;
@@ -638,9 +649,16 @@ void NavigationControllerImpl::LoadURL(
}
void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
- TRACE_EVENT0("browser", "NavigationControllerImpl::LoadURLWithParams");
- if (HandleDebugURL(params.url, params.transition_type))
- return;
+ TRACE_EVENT1("browser,navigation",
+ "NavigationControllerImpl::LoadURLWithParams",
+ "url", params.url.possibly_invalid_spec());
+ if (HandleDebugURL(params.url, params.transition_type)) {
+ // If Telemetry is running, allow the URL load to proceed as if it's
+ // unhandled, otherwise Telemetry can't tell if Navigation completed.
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ cc::switches::kEnableGpuBenchmarking))
+ return;
+ }
// Any renderer-side debug URLs or javascript: URLs should be ignored if the
// renderer process is not live, unless it is the initial navigation of the
@@ -766,8 +784,8 @@ bool NavigationControllerImpl::RendererDidNavigate(
details->type = ClassifyNavigation(rfh, params);
// is_in_page must be computed before the entry gets committed.
- details->is_in_page = IsURLInPageNavigation(
- params.url, params.was_within_same_page, details->type);
+ details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(),
+ params.url, params.was_within_same_page, rfh);
switch (details->type) {
case NAVIGATION_TYPE_NEW_PAGE:
@@ -842,7 +860,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
// The active entry's SiteInstance should match our SiteInstance.
// TODO(creis): This check won't pass for subframes until we create entries
// for subframe navigations.
- if (PageTransitionIsMainFrame(params.transition))
+ if (ui::PageTransitionIsMainFrame(params.transition))
CHECK(active_entry->site_instance() == rfh->GetSiteInstance());
// Remember the bindings the renderer process has at this point, so that
@@ -853,7 +871,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
// Now prep the rest of the details for the notification and broadcast.
details->entry = active_entry;
details->is_main_frame =
- PageTransitionIsMainFrame(params.transition);
+ ui::PageTransitionIsMainFrame(params.transition);
details->serialized_security_info = params.security_info;
details->http_status_code = params.http_status_code;
NotifyNavigationEntryCommitted(details);
@@ -865,6 +883,15 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
RenderFrameHost* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const {
if (params.page_id == -1) {
+ // TODO(nasko, creis): An out-of-process child frame has no way of
+ // knowing the page_id of its parent, so it is passing back -1. The
+ // semantics here should be re-evaluated during session history refactor
+ // (see http://crbug.com/236848). For now, we assume this means the
+ // child frame loaded and proceed. Note that this may do the wrong thing
+ // for cross-process AUTO_SUBFRAME navigations.
+ if (rfh->IsCrossProcessSubframe())
+ return NAVIGATION_TYPE_NEW_SUBFRAME;
+
// The renderer generates the page IDs, and so if it gives us the invalid
// page ID (-1) we know it didn't actually navigate. This happens in a few
// cases:
@@ -891,7 +918,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
// Greater page IDs than we've ever seen before are new pages. We may or may
// not have a pending entry for the page, and this may or may not be the
// main frame.
- if (PageTransitionIsMainFrame(params.transition))
+ if (ui::PageTransitionIsMainFrame(params.transition))
return NAVIGATION_TYPE_NEW_PAGE;
// When this is a new subframe navigation, we should have a committed page
@@ -956,7 +983,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
}
NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get();
- if (!PageTransitionIsMainFrame(params.transition)) {
+ if (!ui::PageTransitionIsMainFrame(params.transition)) {
// All manual subframes would get new IDs and were handled above, so we
// know this is auto. Since the current page was found in the navigation
// entry list, we're guaranteed to have a last committed entry.
@@ -986,8 +1013,7 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
// navigations that don't actually navigate, but it can happen when there is
// an encoding override (it always sends a navigation request).
if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url,
- params.was_within_same_page,
- NAVIGATION_TYPE_UNKNOWN)) {
+ params.was_within_same_page, rfh)) {
return NAVIGATION_TYPE_IN_PAGE;
}
@@ -1023,18 +1049,8 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
// update the virtual URL when replaceState is called after a pushState.
GURL url = params.url;
bool needs_update = false;
- // We call RewriteURLIfNecessary twice: once when page navigation
- // begins in CreateNavigationEntry, and once here when it commits.
- // With the kEnableGpuBenchmarking flag, the rewriting includes
- // handling debug URLs which cause an action to occur, and thus we
- // should not rewrite them a second time.
- bool skip_rewrite =
- IsDebugURL(url) && base::CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kEnableGpuBenchmarking);
- if (!skip_rewrite) {
- BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary(
- &url, browser_context_, &needs_update);
- }
+ BrowserURLHandlerImpl::GetInstance()->RewriteURLIfNecessary(
+ &url, browser_context_, &needs_update);
new_entry->set_update_virtual_url_with_url(needs_update);
// When navigating to a new page, give the browser URL handler a chance to
@@ -1044,6 +1060,8 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
update_virtual_url = needs_update;
}
+ if (params.url_is_unreachable)
+ new_entry->set_page_type(PAGE_TYPE_ERROR);
new_entry->SetURL(params.url);
if (update_virtual_url)
UpdateVirtualURLToURL(new_entry, params.url);
@@ -1059,9 +1077,11 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
// history.pushState() is classified as a navigation to a new page, but
// sets was_within_same_page to true. In this case, we already have the
- // title available, so set it immediately.
- if (params.was_within_same_page && GetLastCommittedEntry())
+ // title and favicon available, so set them immediately.
+ if (params.was_within_same_page && GetLastCommittedEntry()) {
new_entry->SetTitle(GetLastCommittedEntry()->GetTitle());
+ new_entry->GetFavicon() = GetLastCommittedEntry()->GetFavicon();
+ }
DCHECK(!params.history_list_was_cleared || !replace_entry);
// The browser requested to clear the session history when it initiated the
@@ -1080,7 +1100,7 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
RenderFrameHost* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
// We should only get here for main frame navigations.
- DCHECK(PageTransitionIsMainFrame(params.transition));
+ DCHECK(ui::PageTransitionIsMainFrame(params.transition));
// This is a back/forward navigation. The existing page for the ID is
// guaranteed to exist by ClassifyNavigation, and we just need to update it
@@ -1099,7 +1119,7 @@ void NavigationControllerImpl::RendererDidNavigateToExistingPage(
// The redirected to page should not inherit the favicon from the previous
// page.
- if (PageTransitionIsRedirect(params.transition))
+ if (ui::PageTransitionIsRedirect(params.transition))
entry->GetFavicon() = FaviconStatus();
// The site instance will normally be the same except during session restore,
@@ -1160,7 +1180,7 @@ void NavigationControllerImpl::RendererDidNavigateInPage(
RenderFrameHost* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
bool* did_replace_entry) {
- DCHECK(PageTransitionIsMainFrame(params.transition)) <<
+ DCHECK(ui::PageTransitionIsMainFrame(params.transition)) <<
"WebKit should only tell us about in-page navs for the main frame.";
// We're guaranteed to have an entry for this one.
NavigationEntryImpl* existing_entry = GetEntryWithPageID(
@@ -1191,8 +1211,8 @@ void NavigationControllerImpl::RendererDidNavigateInPage(
void NavigationControllerImpl::RendererDidNavigateNewSubframe(
RenderFrameHost* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
- if (PageTransitionCoreTypeIs(params.transition,
- PAGE_TRANSITION_AUTO_SUBFRAME)) {
+ if (ui::PageTransitionCoreTypeIs(params.transition,
+ ui::PAGE_TRANSITION_AUTO_SUBFRAME)) {
// This is not user-initiated. Ignore.
DiscardNonCommittedEntriesInternal();
return;
@@ -1253,10 +1273,10 @@ int NavigationControllerImpl::GetIndexOfEntry(
bool NavigationControllerImpl::IsURLInPageNavigation(
const GURL& url,
bool renderer_says_in_page,
- NavigationType navigation_type) const {
+ RenderFrameHost* rfh) const {
NavigationEntry* last_committed = GetLastCommittedEntry();
return last_committed && AreURLsInPageNavigation(
- last_committed->GetURL(), url, renderer_says_in_page, navigation_type);
+ last_committed->GetURL(), url, renderer_says_in_page, rfh);
}
void NavigationControllerImpl::CopyStateFrom(
@@ -1509,7 +1529,7 @@ void NavigationControllerImpl::DiscardNonCommittedEntries() {
// If there was a transient entry, invalidate everything so the new active
// entry state is shown.
if (transient) {
- delegate_->NotifyNavigationStateChanged(kInvalidateAll);
+ delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_ALL);
}
}
@@ -1523,7 +1543,7 @@ int NavigationControllerImpl::GetPendingEntryIndex() const {
void NavigationControllerImpl::InsertOrReplaceEntry(NavigationEntryImpl* entry,
bool replace) {
- DCHECK(entry->GetTransitionType() != PAGE_TRANSITION_AUTO_SUBFRAME);
+ DCHECK(entry->GetTransitionType() != ui::PAGE_TRANSITION_AUTO_SUBFRAME);
// Copy the pending entry's unique ID to the committed entry.
// I don't know if pending_entry_index_ can be other than -1 here.
@@ -1588,7 +1608,7 @@ void NavigationControllerImpl::NavigateToPendingEntry(ReloadType reload_type) {
(entries_[pending_entry_index_]->restore_type() ==
NavigationEntryImpl::RESTORE_NONE) &&
(entries_[pending_entry_index_]->GetTransitionType() &
- PAGE_TRANSITION_FORWARD_BACK)) {
+ ui::PAGE_TRANSITION_FORWARD_BACK)) {
delegate_->Stop();
// If an interstitial page is showing, we want to close it to get back
@@ -1643,7 +1663,7 @@ void NavigationControllerImpl::NotifyNavigationEntryCommitted(
// when it wants to draw. See http://crbug.com/11157
ssl_manager_.DidCommitProvisionalLoad(*details);
- delegate_->NotifyNavigationStateChanged(kInvalidateAll);
+ delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_ALL);
delegate_->NotifyNavigationEntryCommitted(*details);
// TODO(avi): Remove. http://crbug.com/170921
@@ -1752,7 +1772,7 @@ void NavigationControllerImpl::SetTransientEntry(NavigationEntry* entry) {
entries_.begin() + index, linked_ptr<NavigationEntryImpl>(
NavigationEntryImpl::FromNavigationEntry(entry)));
transient_entry_index_ = index;
- delegate_->NotifyNavigationStateChanged(kInvalidateAll);
+ delegate_->NotifyNavigationStateChanged(INVALIDATE_TYPE_ALL);
}
void NavigationControllerImpl::InsertEntriesFrom(
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index 7a06ba663b6..a646646f35f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -31,68 +31,63 @@ class CONTENT_EXPORT NavigationControllerImpl
NavigationControllerImpl(
NavigationControllerDelegate* delegate,
BrowserContext* browser_context);
- virtual ~NavigationControllerImpl();
+ ~NavigationControllerImpl() override;
// NavigationController implementation:
- virtual WebContents* GetWebContents() const OVERRIDE;
- virtual BrowserContext* GetBrowserContext() const OVERRIDE;
- virtual void SetBrowserContext(
- BrowserContext* browser_context) OVERRIDE;
- virtual void Restore(
- int selected_navigation,
- RestoreType type,
- std::vector<NavigationEntry*>* entries) OVERRIDE;
- virtual NavigationEntry* GetActiveEntry() const OVERRIDE;
- virtual NavigationEntry* GetVisibleEntry() const OVERRIDE;
- virtual int GetCurrentEntryIndex() const OVERRIDE;
- virtual NavigationEntry* GetLastCommittedEntry() const OVERRIDE;
- virtual int GetLastCommittedEntryIndex() const OVERRIDE;
- virtual bool CanViewSource() const OVERRIDE;
- virtual int GetEntryCount() const OVERRIDE;
- virtual NavigationEntry* GetEntryAtIndex(int index) const OVERRIDE;
- virtual NavigationEntry* GetEntryAtOffset(int offset) const OVERRIDE;
- virtual void DiscardNonCommittedEntries() OVERRIDE;
- virtual NavigationEntry* GetPendingEntry() const OVERRIDE;
- virtual int GetPendingEntryIndex() const OVERRIDE;
- virtual NavigationEntry* GetTransientEntry() const OVERRIDE;
- virtual void SetTransientEntry(NavigationEntry* entry) OVERRIDE;
- virtual void LoadURL(const GURL& url,
- const Referrer& referrer,
- PageTransition type,
- const std::string& extra_headers) OVERRIDE;
- virtual void LoadURLWithParams(const LoadURLParams& params) OVERRIDE;
- virtual void LoadIfNecessary() OVERRIDE;
- virtual bool CanGoBack() const OVERRIDE;
- virtual bool CanGoForward() const OVERRIDE;
- virtual bool CanGoToOffset(int offset) const OVERRIDE;
- virtual void GoBack() OVERRIDE;
- virtual void GoForward() OVERRIDE;
- virtual void GoToIndex(int index) OVERRIDE;
- virtual void GoToOffset(int offset) OVERRIDE;
- virtual bool RemoveEntryAtIndex(int index) OVERRIDE;
- virtual const SessionStorageNamespaceMap&
- GetSessionStorageNamespaceMap() const OVERRIDE;
- virtual SessionStorageNamespace*
- GetDefaultSessionStorageNamespace() OVERRIDE;
- virtual void SetMaxRestoredPageID(int32 max_id) OVERRIDE;
- virtual int32 GetMaxRestoredPageID() const OVERRIDE;
- virtual bool NeedsReload() const OVERRIDE;
- virtual void SetNeedsReload() OVERRIDE;
- virtual void CancelPendingReload() OVERRIDE;
- virtual void ContinuePendingReload() OVERRIDE;
- virtual bool IsInitialNavigation() const OVERRIDE;
- virtual void Reload(bool check_for_repost) OVERRIDE;
- virtual void ReloadIgnoringCache(bool check_for_repost) OVERRIDE;
- virtual void ReloadOriginalRequestURL(bool check_for_repost) OVERRIDE;
- virtual void NotifyEntryChanged(const NavigationEntry* entry,
- int index) OVERRIDE;
- virtual void CopyStateFrom(
- const NavigationController& source) OVERRIDE;
- virtual void CopyStateFromAndPrune(NavigationController* source,
- bool replace_entry) OVERRIDE;
- virtual bool CanPruneAllButLastCommitted() OVERRIDE;
- virtual void PruneAllButLastCommitted() OVERRIDE;
- virtual void ClearAllScreenshots() OVERRIDE;
+ WebContents* GetWebContents() const override;
+ BrowserContext* GetBrowserContext() const override;
+ void SetBrowserContext(BrowserContext* browser_context) override;
+ void Restore(int selected_navigation,
+ RestoreType type,
+ std::vector<NavigationEntry*>* entries) override;
+ NavigationEntry* GetActiveEntry() const override;
+ NavigationEntry* GetVisibleEntry() const override;
+ int GetCurrentEntryIndex() const override;
+ NavigationEntry* GetLastCommittedEntry() const override;
+ int GetLastCommittedEntryIndex() const override;
+ bool CanViewSource() const override;
+ int GetEntryCount() const override;
+ NavigationEntry* GetEntryAtIndex(int index) const override;
+ NavigationEntry* GetEntryAtOffset(int offset) const override;
+ void DiscardNonCommittedEntries() override;
+ NavigationEntry* GetPendingEntry() const override;
+ int GetPendingEntryIndex() const override;
+ NavigationEntry* GetTransientEntry() const override;
+ void SetTransientEntry(NavigationEntry* entry) override;
+ void LoadURL(const GURL& url,
+ const Referrer& referrer,
+ ui::PageTransition type,
+ const std::string& extra_headers) override;
+ void LoadURLWithParams(const LoadURLParams& params) override;
+ void LoadIfNecessary() override;
+ bool CanGoBack() const override;
+ bool CanGoForward() const override;
+ bool CanGoToOffset(int offset) const override;
+ void GoBack() override;
+ void GoForward() override;
+ void GoToIndex(int index) override;
+ void GoToOffset(int offset) override;
+ bool RemoveEntryAtIndex(int index) override;
+ const SessionStorageNamespaceMap& GetSessionStorageNamespaceMap()
+ const override;
+ SessionStorageNamespace* GetDefaultSessionStorageNamespace() override;
+ void SetMaxRestoredPageID(int32 max_id) override;
+ int32 GetMaxRestoredPageID() const override;
+ bool NeedsReload() const override;
+ void SetNeedsReload() override;
+ void CancelPendingReload() override;
+ void ContinuePendingReload() override;
+ bool IsInitialNavigation() const override;
+ void Reload(bool check_for_repost) override;
+ void ReloadIgnoringCache(bool check_for_repost) override;
+ void ReloadOriginalRequestURL(bool check_for_repost) override;
+ void NotifyEntryChanged(const NavigationEntry* entry, int index) override;
+ void CopyStateFrom(const NavigationController& source) override;
+ void CopyStateFromAndPrune(NavigationController* source,
+ bool replace_entry) override;
+ bool CanPruneAllButLastCommitted() override;
+ void PruneAllButLastCommitted() override;
+ void ClearAllScreenshots() override;
// Whether this is the initial navigation in an unmodified new tab. In this
// case, we know there is no content displayed in the page.
@@ -167,7 +162,7 @@ class CONTENT_EXPORT NavigationControllerImpl
bool IsURLInPageNavigation(
const GURL& url,
bool renderer_says_in_page,
- NavigationType navigation_type) const;
+ RenderFrameHost* rfh) const;
// Sets the SessionStorageNamespace for the given |partition_id|. This is
// used during initialization of a new NavigationController to allow
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 956288c33d9..ae7ad90f1e4 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -4,9 +4,8 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/memory/scoped_ptr.h"
-#include "base/path_service.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -31,6 +30,7 @@
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_notification_tracker.h"
#include "content/public/test/test_utils.h"
+#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "net/base/net_util.h"
@@ -44,8 +44,7 @@ namespace {
// Creates an image with a 1x1 SkBitmap of the specified |color|.
gfx::Image CreateImage(SkColor color) {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(1, 1);
bitmap.eraseColor(color);
return gfx::Image::CreateFrom1xBitmap(bitmap);
}
@@ -74,13 +73,12 @@ class MockScreenshotManager : public content::NavigationEntryScreenshotManager {
encoding_screenshot_in_progress_(false) {
}
- virtual ~MockScreenshotManager() {
- }
+ ~MockScreenshotManager() override {}
void TakeScreenshotFor(content::NavigationEntryImpl* entry) {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bitmap.allocPixels();
+ bitmap.allocPixels(SkImageInfo::Make(
+ 1, 1, kAlpha_8_SkColorType, kPremul_SkAlphaType));
bitmap.eraseARGB(0, 0, 0, 0);
encoding_screenshot_in_progress_ = true;
OnScreenshotTaken(entry->GetUniqueID(), true, bitmap);
@@ -100,12 +98,10 @@ class MockScreenshotManager : public content::NavigationEntryScreenshotManager {
private:
// Overridden from content::NavigationEntryScreenshotManager:
- virtual void TakeScreenshotImpl(
- content::RenderViewHost* host,
- content::NavigationEntryImpl* entry) OVERRIDE {
- }
+ void TakeScreenshotImpl(content::RenderViewHost* host,
+ content::NavigationEntryImpl* entry) override {}
- virtual void OnScreenshotSet(content::NavigationEntryImpl* entry) OVERRIDE {
+ void OnScreenshotSet(content::NavigationEntryImpl* entry) override {
encoding_screenshot_in_progress_ = false;
NavigationEntryScreenshotManager::OnScreenshotSet(entry);
if (message_loop_runner_.get())
@@ -188,7 +184,7 @@ class NavigationControllerTest
NavigationControllerTest() : navigation_entry_committed_counter_(0) {
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
WebContents* web_contents = RenderViewHostImplTestHarness::web_contents();
ASSERT_TRUE(web_contents); // The WebContents should be created by now.
@@ -196,14 +192,14 @@ class NavigationControllerTest
}
// WebContentsObserver:
- virtual void DidStartNavigationToPendingEntry(
+ void DidStartNavigationToPendingEntry(
const GURL& url,
- NavigationController::ReloadType reload_type) OVERRIDE {
+ NavigationController::ReloadType reload_type) override {
navigated_url_ = url;
}
- virtual void NavigationEntryCommitted(
- const LoadCommittedDetails& load_details) OVERRIDE {
+ void NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) override {
navigation_entry_committed_counter_++;
}
@@ -247,12 +243,12 @@ class TestWebContentsDelegate : public WebContentsDelegate {
}
// Keep track of whether the tab has notified us of a navigation state change.
- virtual void NavigationStateChanged(const WebContents* source,
- unsigned changed_flags) OVERRIDE {
+ void NavigationStateChanged(const WebContents* source,
+ InvalidateTypes changed_flags) override {
navigation_state_change_count_++;
}
- virtual void ShowRepostFormWarningDialog(WebContents* source) OVERRIDE {
+ void ShowRepostFormWarningDialog(WebContents* source) override {
repost_form_warning_count_++;
}
@@ -354,7 +350,8 @@ TEST_F(NavigationControllerTest, LoadURL) {
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Creating a pending notification should not have issued any of the
// notifications we're listening for.
EXPECT_EQ(0U, notifications.size());
@@ -398,7 +395,8 @@ TEST_F(NavigationControllerTest, LoadURL) {
EXPECT_FALSE(controller.GetVisibleEntry()->GetTimestamp().is_null());
// Load another...
- controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// The load should now be pending.
EXPECT_EQ(controller.GetEntryCount(), 1);
@@ -416,9 +414,8 @@ TEST_F(NavigationControllerTest, LoadURL) {
// Simulate the beforeunload ack for the cross-site transition, and then the
// commit.
- test_rvh()->SendBeforeUnloadACK(true);
- static_cast<TestRenderViewHost*>(
- contents()->GetPendingRenderViewHost())->SendNavigate(1, url2);
+ main_test_rfh()->SendBeforeUnloadACK(true);
+ contents()->GetPendingMainFrame()->SendNavigate(1, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -456,18 +453,20 @@ TEST_F(NavigationControllerTest, LoadURLSameTime) {
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// Load another...
- controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Simulate the beforeunload ack for the cross-site transition, and then the
// commit.
- test_rvh()->SendBeforeUnloadACK(true);
+ main_test_rfh()->SendBeforeUnloadACK(true);
main_test_rfh()->SendNavigate(1, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -503,8 +502,8 @@ void CheckNavigationEntryMatchLoadParams(
load_params.override_user_agent);
EXPECT_EQ(should_override, entry->GetIsOverridingUserAgent());
}
- EXPECT_EQ(load_params.browser_initiated_post_data,
- entry->GetBrowserInitiatedPostData());
+ EXPECT_EQ(load_params.browser_initiated_post_data.get(),
+ entry->GetBrowserInitiatedPostData());
EXPECT_EQ(load_params.transferred_global_request_id,
entry->transferred_global_request_id());
}
@@ -515,7 +514,7 @@ TEST_F(NavigationControllerTest, LoadURLWithParams) {
NavigationController::LoadURLParams load_params(GURL("http://foo"));
load_params.referrer =
Referrer(GURL("http://referrer"), blink::WebReferrerPolicyDefault);
- load_params.transition_type = PAGE_TRANSITION_GENERATED;
+ load_params.transition_type = ui::PAGE_TRANSITION_GENERATED;
load_params.extra_headers = "content-type: text/plain";
load_params.load_type = NavigationController::LOAD_TYPE_DEFAULT;
load_params.is_renderer_initiated = true;
@@ -556,7 +555,7 @@ TEST_F(NavigationControllerTest, LoadURLWithExtraParams_HttpPost) {
NavigationControllerImpl& controller = controller_impl();
NavigationController::LoadURLParams load_params(GURL("https://posturl"));
- load_params.transition_type = PAGE_TRANSITION_TYPED;
+ load_params.transition_type = ui::PAGE_TRANSITION_TYPED;
load_params.load_type =
NavigationController::LOAD_TYPE_BROWSER_INITIATED_HTTP_POST;
load_params.override_user_agent = NavigationController::UA_OVERRIDE_TRUE;
@@ -589,7 +588,8 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
const GURL url1("http://foo1");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -599,7 +599,8 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage) {
const base::Time timestamp = controller.GetVisibleEntry()->GetTimestamp();
EXPECT_FALSE(timestamp.is_null());
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -631,11 +632,12 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
const GURL url1("http://foo1");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url1;
- params.transition = PAGE_TRANSITION_TYPED;
+ params.transition = ui::PAGE_TRANSITION_TYPED;
params.is_post = true;
params.post_id = 123;
params.page_state = PageState::CreateForTesting(url1, false, 0, 0);
@@ -647,7 +649,8 @@ TEST_F(NavigationControllerTest, LoadURL_SamePage_DifferentMethod) {
EXPECT_TRUE(entry->GetHasPostData());
EXPECT_EQ(entry->GetPostID(), 123);
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
// We should not have produced a new session history entry.
@@ -667,7 +670,8 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -677,7 +681,8 @@ TEST_F(NavigationControllerTest, LoadURL_Discarded) {
const base::Time timestamp = controller.GetVisibleEntry()->GetTimestamp();
EXPECT_FALSE(timestamp.is_null());
- controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
controller.DiscardNonCommittedEntries();
EXPECT_EQ(0U, notifications.size());
@@ -705,7 +710,7 @@ TEST_F(NavigationControllerTest, LoadURL_NoPending) {
// First make an existing committed entry.
const GURL kExistingURL1("http://eh");
controller.LoadURL(
- kExistingURL1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -735,7 +740,7 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
// First make an existing committed entry.
const GURL kExistingURL1("http://eh");
controller.LoadURL(
- kExistingURL1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -743,14 +748,13 @@ TEST_F(NavigationControllerTest, LoadURL_NewPending) {
// Make a pending entry to somewhere new.
const GURL kExistingURL2("http://bee");
controller.LoadURL(
- kExistingURL2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
// After the beforeunload but before it commits, do a new navigation.
- test_rvh()->SendBeforeUnloadACK(true);
+ main_test_rfh()->SendBeforeUnloadACK(true);
const GURL kNewURL("http://see");
- static_cast<TestRenderViewHost*>(
- contents()->GetPendingRenderViewHost())->SendNavigate(3, kNewURL);
+ contents()->GetPendingMainFrame()->SendNavigate(3, kNewURL);
// There should no longer be any pending entry, and the third navigation we
// just made should be committed.
@@ -772,14 +776,14 @@ TEST_F(NavigationControllerTest, LoadURL_ExistingPending) {
// First make some history.
const GURL kExistingURL1("http://foo/eh");
controller.LoadURL(
- kExistingURL1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
const GURL kExistingURL2("http://foo/bee");
controller.LoadURL(
- kExistingURL2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(1, kExistingURL2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -816,9 +820,9 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
// First make some history, starting with a privileged URL.
const GURL kExistingURL1("http://privileged");
controller.LoadURL(
- kExistingURL1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Pretend it has bindings so we can tell if we incorrectly copy it.
- test_rvh()->AllowBindings(2);
+ main_test_rfh()->GetRenderViewHost()->AllowBindings(2);
main_test_rfh()->SendNavigate(0, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -826,18 +830,17 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
// Navigate cross-process to a second URL.
const GURL kExistingURL2("http://foo/eh");
controller.LoadURL(
- kExistingURL2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- test_rvh()->SendBeforeUnloadACK(true);
- TestRenderViewHost* foo_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetPendingRenderViewHost());
- foo_rvh->SendNavigate(1, kExistingURL2);
+ kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ main_test_rfh()->SendBeforeUnloadACK(true);
+ TestRenderFrameHost* foo_rfh = contents()->GetPendingMainFrame();
+ foo_rfh->SendNavigate(1, kExistingURL2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// Now make a pending back/forward navigation to a privileged entry.
// The zeroth entry should be pending.
controller.GoBack();
- foo_rvh->SendBeforeUnloadACK(true);
+ foo_rfh->SendBeforeUnloadACK(true);
EXPECT_EQ(0U, notifications.size());
EXPECT_EQ(0, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -847,7 +850,7 @@ TEST_F(NavigationControllerTest, LoadURL_PrivilegedPending) {
// Before that commits, do a new navigation.
const GURL kNewURL("http://foo/bee");
LoadCommittedDetails details;
- foo_rvh->SendNavigate(3, kNewURL);
+ foo_rfh->SendNavigate(3, kNewURL);
// There should no longer be any pending entry, and the third navigation we
// just made should be committed.
@@ -871,14 +874,14 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
// First make some history.
const GURL kExistingURL1("http://foo/eh");
controller.LoadURL(
- kExistingURL1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, kExistingURL1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
const GURL kExistingURL2("http://foo/bee");
controller.LoadURL(
- kExistingURL2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(1, kExistingURL2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -886,7 +889,7 @@ TEST_F(NavigationControllerTest, LoadURL_BackPreemptsPending) {
// Now make a pending new navigation.
const GURL kNewURL("http://foo/see");
controller.LoadURL(
- kNewURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kNewURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
@@ -922,7 +925,7 @@ TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {
// Now make a pending new navigation.
const GURL kNewURL("http://eh");
controller.LoadURL(
- kNewURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kNewURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_TRUE(controller.GetPendingEntry());
@@ -959,7 +962,7 @@ TEST_F(NavigationControllerTest, LoadURL_AbortDoesntCancelPending) {
// Start with a pending new navigation.
const GURL kNewURL("http://eh");
controller.LoadURL(
- kNewURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kNewURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_TRUE(controller.GetPendingEntry());
@@ -1005,8 +1008,8 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
// First make an existing committed entry.
const GURL kExistingURL("http://foo/eh");
controller.LoadURL(kExistingURL, content::Referrer(),
- content::PAGE_TRANSITION_TYPED, std::string());
- main_test_rfh()->SendNavigate(0, kExistingURL);
+ ui::PAGE_TRANSITION_TYPED, std::string());
+ main_test_rfh()->SendNavigate(1, kExistingURL);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1018,7 +1021,7 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
// Now make a pending new navigation, initiated by the renderer.
const GURL kNewURL("http://foo/bee");
NavigationController::LoadURLParams load_url_params(kNewURL);
- load_url_params.transition_type = PAGE_TRANSITION_TYPED;
+ load_url_params.transition_type = ui::PAGE_TRANSITION_TYPED;
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
EXPECT_EQ(0U, notifications.size());
@@ -1030,13 +1033,8 @@ TEST_F(NavigationControllerTest, LoadURL_RedirectAbortDoesntShowPendingURL) {
// The visible entry should be the last committed URL, not the pending one.
EXPECT_EQ(kExistingURL, controller.GetVisibleEntry()->GetURL());
- // Now the navigation redirects.
+ // Now the navigation redirects. (There is no corresponding message here.)
const GURL kRedirectURL("http://foo/see");
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidRedirectProvisionalLoad(0, // routing_id
- -1, // pending page_id
- kNewURL, // old url
- kRedirectURL)); // new url
// We don't want to change the NavigationEntry's url, in case it cancels.
// Prevents regression of http://crbug.com/77786.
@@ -1079,39 +1077,35 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
const GURL url2("http://foo2");
// Navigate to a first, unprivileged URL.
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(NavigationEntryImpl::kInvalidBindings,
NavigationEntryImpl::FromNavigationEntry(
controller.GetPendingEntry())->bindings());
// Commit.
- TestRenderViewHost* orig_rvh = static_cast<TestRenderViewHost*>(test_rvh());
- orig_rvh->SendNavigate(0, url1);
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
+ orig_rfh->SendNavigate(0, url1);
EXPECT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(0, NavigationEntryImpl::FromNavigationEntry(
controller.GetLastCommittedEntry())->bindings());
- // Manually increase the number of active views in the SiteInstance
- // that orig_rvh belongs to, to prevent it from being destroyed when
- // it gets swapped out, so that we can reuse orig_rvh when the
+ // Manually increase the number of active frames in the SiteInstance
+ // that orig_rfh belongs to, to prevent it from being destroyed when
+ // it gets swapped out, so that we can reuse orig_rfh when the
// controller goes back.
- static_cast<SiteInstanceImpl*>(orig_rvh->GetSiteInstance())->
- increment_active_view_count();
+ orig_rfh->GetSiteInstance()->increment_active_frame_count();
// Navigate to a second URL, simulate the beforeunload ack for the cross-site
- // transition, run the unload handler, and set bindings on the pending
- // RenderViewHost to simulate a privileged url.
- controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- orig_rvh->SendBeforeUnloadACK(true);
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
- TestRenderViewHost* new_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
- new_rvh->AllowBindings(1);
- new_rvh->SendNavigate(1, url2);
+ // transition, and set bindings on the pending RenderViewHost to simulate a
+ // privileged url.
+ controller.LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ orig_rfh->SendBeforeUnloadACK(true);
+ TestRenderFrameHost* new_rfh = contents()->GetPendingMainFrame();
+ new_rfh->GetRenderViewHost()->AllowBindings(1);
+ new_rfh->SendNavigate(1, url2);
// The second load should be committed, and bindings should be remembered.
EXPECT_EQ(controller.GetEntryCount(), 2);
@@ -1122,12 +1116,8 @@ TEST_F(NavigationControllerTest, LoadURL_WithBindings) {
// Going back, the first entry should still appear unprivileged.
controller.GoBack();
- new_rvh->SendBeforeUnloadACK(true);
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
- orig_rvh->SendNavigate(0, url1);
+ new_rfh->SendBeforeUnloadACK(true);
+ orig_rfh->SendNavigate(0, url1);
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
EXPECT_EQ(0, NavigationEntryImpl::FromNavigationEntry(
controller.GetLastCommittedEntry())->bindings());
@@ -1140,7 +1130,8 @@ TEST_F(NavigationControllerTest, Reload) {
const GURL url1("http://foo1");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
@@ -1193,7 +1184,8 @@ TEST_F(NavigationControllerTest, Reload_GeneratesNewPage) {
const GURL url1("http://foo1");
const GURL url2("http://foo2");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1222,7 +1214,8 @@ TEST_F(NavigationControllerTest, ReloadWithGuest) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
ASSERT_TRUE(controller.GetVisibleEntry());
@@ -1257,7 +1250,7 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
// Load up the original URL, but get redirected.
controller.LoadURL(
- original_url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ original_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->SendNavigateWithOriginalRequestURL(
0, final_url, original_url);
@@ -1312,7 +1305,8 @@ TEST_F(NavigationControllerTest, ReloadOriginalRequestURL) {
TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Set up some sample values.
const unsigned char* raw_data =
@@ -1358,7 +1352,8 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
TEST_F(NavigationControllerTest, RedirectsAreNotResetByCommit) {
NavigationControllerImpl& controller = controller_impl();
const GURL url1("http://foo1");
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Set up some redirect values.
std::vector<GURL> redirects;
@@ -1449,12 +1444,13 @@ TEST_F(NavigationControllerTest, Back_GeneratesNewPage) {
const GURL url3("http://foo/3");
controller.LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(1, url2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1501,13 +1497,14 @@ TEST_F(NavigationControllerTest, Back_NewPending) {
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- // controller.LoadURL(kUrl2, PAGE_TRANSITION_TYPED);
+ // controller.LoadURL(kUrl2, ui::PAGE_TRANSITION_TYPED);
main_test_rfh()->SendNavigate(1, kUrl2);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
// Now start a new pending navigation and go back before it commits.
- controller.LoadURL(kUrl3, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ kUrl3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_EQ(kUrl3, controller.GetPendingEntry()->GetURL());
controller.GoBack();
@@ -1690,7 +1687,8 @@ TEST_F(NavigationControllerTest, Redirect) {
const GURL url2("http://foo2"); // Redirection target
// First request
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(0U, notifications.size());
main_test_rfh()->SendNavigate(0, url2);
@@ -1698,7 +1696,8 @@ TEST_F(NavigationControllerTest, Redirect) {
navigation_entry_committed_counter_ = 0;
// Second request
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
@@ -1707,7 +1706,7 @@ TEST_F(NavigationControllerTest, Redirect) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url2;
- params.transition = PAGE_TRANSITION_SERVER_REDIRECT;
+ params.transition = ui::PAGE_TRANSITION_SERVER_REDIRECT;
params.redirects.push_back(GURL("http://foo1"));
params.redirects.push_back(GURL("http://foo2"));
params.should_update_history = false;
@@ -1747,7 +1746,8 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
const GURL url2("http://foo2"); // Redirection target
// First request as POST
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
controller.GetVisibleEntry()->SetHasPostData(true);
EXPECT_EQ(0U, notifications.size());
@@ -1756,7 +1756,8 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
navigation_entry_committed_counter_ = 0;
// Second request
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
@@ -1765,7 +1766,7 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url2;
- params.transition = PAGE_TRANSITION_SERVER_REDIRECT;
+ params.transition = ui::PAGE_TRANSITION_SERVER_REDIRECT;
params.redirects.push_back(GURL("http://foo1"));
params.redirects.push_back(GURL("http://foo2"));
params.should_update_history = false;
@@ -1804,7 +1805,8 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
const GURL url2("http://foo2"); // Redirection target
// First request
- controller.LoadURL(url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(controller.GetPendingEntryIndex(), -1);
@@ -1813,7 +1815,7 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url2;
- params.transition = PAGE_TRANSITION_SERVER_REDIRECT;
+ params.transition = ui::PAGE_TRANSITION_SERVER_REDIRECT;
params.redirects.push_back(GURL("http://foo1"));
params.redirects.push_back(GURL("http://foo2"));
params.should_update_history = false;
@@ -1857,7 +1859,7 @@ TEST_F(NavigationControllerTest, NewSubframe) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.url = url2;
- params.transition = PAGE_TRANSITION_MANUAL_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -1894,7 +1896,7 @@ TEST_F(NavigationControllerTest, SubframeOnEmptyPage) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.url = url;
- params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
params.should_update_history = false;
params.gesture = NavigationGestureAuto;
params.is_post = false;
@@ -1922,7 +1924,7 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url2;
- params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -1955,7 +1957,7 @@ TEST_F(NavigationControllerTest, BackSubframe) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.url = url2;
- params.transition = PAGE_TRANSITION_MANUAL_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -2049,7 +2051,7 @@ TEST_F(NavigationControllerTest, InPage) {
FrameHostMsg_DidCommitProvisionalLoad_Params self_params;
self_params.page_id = 0;
self_params.url = url1;
- self_params.transition = PAGE_TRANSITION_LINK;
+ self_params.transition = ui::PAGE_TRANSITION_LINK;
self_params.should_update_history = false;
self_params.gesture = NavigationGestureUser;
self_params.is_post = false;
@@ -2070,7 +2072,7 @@ TEST_F(NavigationControllerTest, InPage) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.url = url2;
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -2158,7 +2160,7 @@ TEST_F(NavigationControllerTest, InPage_Replace) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0; // Same page_id
params.url = url2;
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -2209,7 +2211,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1; // Same page_id
params.url = url;
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
params.redirects.push_back(url);
params.should_update_history = true;
params.gesture = NavigationGestureUnknown;
@@ -2234,7 +2236,7 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 2; // New page_id
params.url = url;
- params.transition = PAGE_TRANSITION_CLIENT_REDIRECT;
+ params.transition = ui::PAGE_TRANSITION_CLIENT_REDIRECT;
params.redirects.push_back(GURL("http://foo2/#a"));
params.redirects.push_back(url);
params.should_update_history = true;
@@ -2272,7 +2274,7 @@ TEST_F(NavigationControllerTest, PushStateWithoutPreviousEntry)
params.url = url;
params.page_state = PageState::CreateFromURL(url);
params.was_within_same_page = true;
- test_rvh()->SendNavigateWithParams(&params);
+ contents()->GetMainFrame()->SendNavigateWithParams(&params);
// We pass if we don't crash.
}
@@ -2286,9 +2288,9 @@ class PrunedListener : public NotificationObserver {
Source<NavigationController>(controller));
}
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE {
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override {
if (type == NOTIFICATION_NAV_LIST_PRUNED) {
notification_count_++;
details_ = *(Details<PrunedDetails>(details).ptr());
@@ -2320,7 +2322,7 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
for (url_index = 0; url_index < kMaxEntryCount; url_index++) {
GURL url(base::StringPrintf("http://www.a.com/%d", url_index));
controller.LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(url_index, url);
}
@@ -2332,7 +2334,7 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
// Navigate some more.
GURL url(base::StringPrintf("http://www.a.com/%d", url_index));
controller.LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(url_index, url);
url_index++;
@@ -2350,7 +2352,7 @@ TEST_F(NavigationControllerTest, EnforceMaxNavigationCount) {
for (int i = 0; i < 3; i++) {
url = GURL(base::StringPrintf("http:////www.a.com/%d", url_index));
controller.LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(url_index, url);
url_index++;
}
@@ -2369,7 +2371,7 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
GURL url("http://foo");
std::vector<NavigationEntry*> entries;
NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
- url, Referrer(), PAGE_TRANSITION_RELOAD, false, std::string(),
+ url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false, std::string(),
browser_context());
entry->SetPageID(0);
entry->SetTitle(base::ASCIIToUTF16("Title"));
@@ -2415,7 +2417,7 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url;
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -2449,7 +2451,7 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
GURL url("http://foo");
std::vector<NavigationEntry*> entries;
NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
- url, Referrer(), PAGE_TRANSITION_RELOAD, false, std::string(),
+ url, Referrer(), ui::PAGE_TRANSITION_RELOAD, false, std::string(),
browser_context());
entry->SetPageID(0);
entry->SetTitle(base::ASCIIToUTF16("Title"));
@@ -2498,7 +2500,7 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = url;
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
params.should_update_history = false;
params.gesture = NavigationGestureUser;
params.is_post = false;
@@ -2526,13 +2528,13 @@ TEST_F(NavigationControllerTest, Interstitial) {
// First navigate somewhere normal.
const GURL url1("http://foo");
controller.LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
// Now navigate somewhere with an interstitial.
const GURL url2("http://bar");
controller.LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
set_page_type(PAGE_TYPE_INTERSTITIAL);
@@ -2557,19 +2559,19 @@ TEST_F(NavigationControllerTest, RemoveEntry) {
const GURL default_url("http://foo/default");
controller.LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url1);
controller.LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(1, url2);
controller.LoadURL(
- url3, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(2, url3);
controller.LoadURL(
- url4, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(3, url4);
controller.LoadURL(
- url5, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url5, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(4, url5);
// Try to remove the last entry. Will fail because it is the current entry.
@@ -2605,6 +2607,45 @@ TEST_F(NavigationControllerTest, RemoveEntry) {
EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
}
+TEST_F(NavigationControllerTest, RemoveEntryWithPending) {
+ NavigationControllerImpl& controller = controller_impl();
+ const GURL url1("http://foo/1");
+ const GURL url2("http://foo/2");
+ const GURL url3("http://foo/3");
+ const GURL default_url("http://foo/default");
+
+ controller.LoadURL(
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ main_test_rfh()->SendNavigate(0, url1);
+ controller.LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ main_test_rfh()->SendNavigate(1, url2);
+ controller.LoadURL(
+ url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ main_test_rfh()->SendNavigate(2, url3);
+
+ // Go back, but don't commit yet. Check that we can't delete the current
+ // and pending entries.
+ controller.GoBack();
+ EXPECT_FALSE(controller.RemoveEntryAtIndex(2));
+ EXPECT_FALSE(controller.RemoveEntryAtIndex(1));
+
+ // Remove the first entry, while there is a pending entry. This is expected
+ // to discard the pending entry.
+ EXPECT_TRUE(controller.RemoveEntryAtIndex(0));
+ EXPECT_FALSE(controller.GetPendingEntry());
+ EXPECT_EQ(-1, controller.GetPendingEntryIndex());
+
+ // We should update the last committed entry index.
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ // Now commit and ensure we land on the right entry.
+ main_test_rfh()->SendNavigate(1, url2);
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ EXPECT_FALSE(controller.GetPendingEntry());
+}
+
// Tests the transient entry, making sure it goes away with all navigations.
TEST_F(NavigationControllerTest, TransientEntry) {
NavigationControllerImpl& controller = controller_impl();
@@ -2620,10 +2661,10 @@ TEST_F(NavigationControllerTest, TransientEntry) {
const GURL transient_url("http://foo/transient");
controller.LoadURL(
- url0, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url0);
controller.LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(1, url1);
notifications.Reset();
@@ -2649,7 +2690,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
// Navigate.
controller.LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(2, url2);
// We should have navigated, transient entry should be gone.
@@ -2668,7 +2709,7 @@ TEST_F(NavigationControllerTest, TransientEntry) {
// Initiate a navigation, add a transient then commit navigation.
controller.LoadURL(
- url4, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
transient_entry = new NavigationEntryImpl;
transient_entry->SetURL(transient_url);
controller.SetTransientEntry(transient_entry);
@@ -2760,10 +2801,10 @@ TEST_F(NavigationControllerTest, ReloadTransient) {
// Load |url0|, and start a pending navigation to |url1|.
controller.LoadURL(
- url0, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
main_test_rfh()->SendNavigate(0, url0);
controller.LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// A transient entry is added, interrupting the navigation.
NavigationEntryImpl* transient_entry = new NavigationEntryImpl;
@@ -2803,7 +2844,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
// We create pending entries for renderer-initiated navigations so that we
// can show them in new tabs when it is safe.
- navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url1);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), url1, false);
// Simulate what happens if a BrowserURLHandler rewrites the URL, causing
// the virtual URL to differ from the URL.
@@ -2817,7 +2858,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
is_renderer_initiated());
// If the user clicks another link, we should replace the pending entry.
- navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url2);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), url2, false);
EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
@@ -2827,18 +2868,18 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
// We should not replace the pending entry for an error URL.
- navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url1);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), url1, false);
EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
- navigator->DidStartProvisionalLoad(
- main_test_rfh(), -1, GURL(kUnreachableWebDataURL));
+ navigator->DidStartProvisionalLoad(main_test_rfh(),
+ GURL(kUnreachableWebDataURL), false);
EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
// We should remember if the pending entry will replace the current one.
// http://crbug.com/308444.
- navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url1);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), url1, false);
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
set_should_replace_entry(true);
- navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url2);
+ navigator->DidStartProvisionalLoad(main_test_rfh(), url2, false);
EXPECT_TRUE(
NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
should_replace_entry());
@@ -2862,7 +2903,8 @@ TEST_F(NavigationControllerTest, DontShowRendererURLUntilCommit) {
// For typed navigations (browser-initiated), both pending and visible entries
// should update before commit.
- controller.LoadURL(url0, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller.LoadURL(
+ url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(url0, controller.GetPendingEntry()->GetURL());
EXPECT_EQ(url0, controller.GetVisibleEntry()->GetURL());
main_test_rfh()->SendNavigate(0, url0);
@@ -2905,7 +2947,7 @@ TEST_F(NavigationControllerTest, ShowRendererURLInNewTabUntilModified) {
// we show the pending entry's URL as long as the about:blank page is not
// modified.
NavigationController::LoadURLParams load_url_params(url);
- load_url_params.transition_type = PAGE_TRANSITION_LINK;
+ load_url_params.transition_type = ui::PAGE_TRANSITION_LINK;
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
@@ -2945,7 +2987,7 @@ TEST_F(NavigationControllerTest, ShowBrowserURLAfterFailUntilModified) {
// modified. This is possible in cases that the user types a URL into a popup
// tab created with a slow URL.
NavigationController::LoadURLParams load_url_params(url);
- load_url_params.transition_type = PAGE_TRANSITION_TYPED;
+ load_url_params.transition_type = ui::PAGE_TRANSITION_TYPED;
load_url_params.is_renderer_initiated = false;
controller.LoadURLWithParams(load_url_params);
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
@@ -2996,7 +3038,7 @@ TEST_F(NavigationControllerTest, ShowRendererURLAfterFailUntilModified) {
// we show the pending entry's URL as long as the about:blank page is not
// modified.
NavigationController::LoadURLParams load_url_params(url);
- load_url_params.transition_type = PAGE_TRANSITION_LINK;
+ load_url_params.transition_type = ui::PAGE_TRANSITION_LINK;
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
@@ -3043,7 +3085,7 @@ TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
// we show the pending entry's URL as long as the about:blank page is not
// modified.
NavigationController::LoadURLParams load_url_params(url1);
- load_url_params.transition_type = PAGE_TRANSITION_LINK;
+ load_url_params.transition_type = ui::PAGE_TRANSITION_LINK;
load_url_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url_params);
EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL());
@@ -3056,7 +3098,7 @@ TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
// Simulate a commit and then starting a new pending navigation.
main_test_rfh()->SendNavigate(0, url1);
NavigationController::LoadURLParams load_url2_params(url2);
- load_url2_params.transition_type = PAGE_TRANSITION_LINK;
+ load_url2_params.transition_type = ui::PAGE_TRANSITION_LINK;
load_url2_params.is_renderer_initiated = true;
controller.LoadURLWithParams(load_url2_params);
@@ -3074,54 +3116,71 @@ TEST_F(NavigationControllerTest, DontShowRendererURLInNewTabAfterCommit) {
// regression for bug 1126349.
TEST_F(NavigationControllerTest, IsInPageNavigation) {
NavigationControllerImpl& controller = controller_impl();
- // Navigate to URL with no refs.
const GURL url("http://www.google.com/home.html");
+
+ // If the renderer claims it performed an in-page navigation from
+ // about:blank, trust the renderer.
+ // This can happen when an iframe is created and populated via
+ // document.write(), then tries to perform a fragment navigation.
+ // TODO(japhet): We should only trust the renderer if the about:blank
+ // was the first document in the given frame, but we don't have enough
+ // information to identify that case currently.
+ const GURL blank_url(url::kAboutBlankURL);
+ main_test_rfh()->SendNavigate(0, blank_url);
+ EXPECT_TRUE(controller.IsURLInPageNavigation(url, true,
+ main_test_rfh()));
+
+ // Navigate to URL with no refs.
main_test_rfh()->SendNavigate(0, url);
// Reloading the page is not an in-page navigation.
EXPECT_FALSE(controller.IsURLInPageNavigation(url, false,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
const GURL other_url("http://www.google.com/add.html");
EXPECT_FALSE(controller.IsURLInPageNavigation(other_url, false,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
const GURL url_with_ref("http://www.google.com/home.html#my_ref");
EXPECT_TRUE(controller.IsURLInPageNavigation(url_with_ref, true,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
// Navigate to URL with refs.
main_test_rfh()->SendNavigate(1, url_with_ref);
// Reloading the page is not an in-page navigation.
EXPECT_FALSE(controller.IsURLInPageNavigation(url_with_ref, false,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
EXPECT_FALSE(controller.IsURLInPageNavigation(url, false,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
EXPECT_FALSE(controller.IsURLInPageNavigation(other_url, false,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
const GURL other_url_with_ref("http://www.google.com/home.html#my_other_ref");
EXPECT_TRUE(controller.IsURLInPageNavigation(other_url_with_ref, true,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
// Going to the same url again will be considered in-page
// if the renderer says it is even if the navigation type isn't IN_PAGE.
EXPECT_TRUE(controller.IsURLInPageNavigation(url_with_ref, true,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
// Going back to the non ref url will be considered in-page if the navigation
// type is IN_PAGE.
EXPECT_TRUE(controller.IsURLInPageNavigation(url, true,
- NAVIGATION_TYPE_IN_PAGE));
+ main_test_rfh()));
// If the renderer says this is a same-origin in-page navigation, believe it.
// This is the pushState/replaceState case.
EXPECT_TRUE(controller.IsURLInPageNavigation(other_url, true,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
// Don't believe the renderer if it claims a cross-origin navigation is
// in-page.
const GURL different_origin_url("http://www.example.com");
+ MockRenderProcessHost* rph =
+ static_cast<MockRenderProcessHost*>(main_test_rfh()->GetProcess());
+ EXPECT_EQ(0, rph->bad_msg_count());
EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true,
- NAVIGATION_TYPE_UNKNOWN));
+ main_test_rfh()));
+ EXPECT_EQ(1, rph->bad_msg_count());
}
// Some pages can have subframes with the same base URL (minus the reference) as
@@ -3143,7 +3202,7 @@ TEST_F(NavigationControllerTest, SameSubframe) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.url = subframe;
- params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
params.should_update_history = false;
params.gesture = NavigationGestureAuto;
params.is_post = false;
@@ -3251,7 +3310,7 @@ TEST_F(NavigationControllerTest, SubframeWhilePending) {
// Now start a pending load to a totally different page, but don't commit it.
const GURL url2("http://bar/");
controller.LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Send a subframe update from the first page, as if one had just
// automatically loaded. Auto subframes don't increment the page ID.
@@ -3259,7 +3318,7 @@ TEST_F(NavigationControllerTest, SubframeWhilePending) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = controller.GetLastCommittedEntry()->GetPageID();
params.url = url1_sub;
- params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
params.should_update_history = false;
params.gesture = NavigationGestureAuto;
params.is_post = false;
@@ -3522,7 +3581,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending) {
NavigationControllerImpl& other_controller = other_contents->GetController();
other_contents->NavigateAndCommit(url3);
other_controller.LoadURL(
- url4, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
other_contents->ExpectSetHistoryLengthAndPrune(
GetSiteInstanceFromEntry(other_controller.GetEntryAtIndex(0)), 1,
other_controller.GetEntryAtIndex(0)->GetPageID());
@@ -3566,7 +3625,7 @@ TEST_F(NavigationControllerTest, CopyStateFromAndPruneTargetPending2) {
other_contents->NavigateAndCommit(url2a);
// Simulate a client redirect, which has the same page ID as entry 2a.
other_controller.LoadURL(
- url2b, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ url2b, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
other_controller.GetPendingEntry()->SetPageID(
other_controller.GetLastCommittedEntry()->GetPageID());
@@ -3802,7 +3861,7 @@ TEST_F(NavigationControllerTest, CopyRestoredStateAndNavigate) {
std::vector<NavigationEntry*> entries;
for (size_t i = 0; i < arraysize(kRestoredUrls); ++i) {
NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
- kRestoredUrls[i], Referrer(), PAGE_TRANSITION_RELOAD, false,
+ kRestoredUrls[i], Referrer(), ui::PAGE_TRANSITION_RELOAD, false,
std::string(), browser_context());
entry->SetPageID(static_cast<int>(i));
entries.push_back(entry);
@@ -3871,7 +3930,7 @@ TEST_F(NavigationControllerTest, HistoryNavigate) {
ASSERT_TRUE(message != NULL);
Tuple1<FrameMsg_Navigate_Params> nav_params;
FrameMsg_Navigate::Read(message, &nav_params);
- EXPECT_EQ(url1, nav_params.a.url);
+ EXPECT_EQ(url1, nav_params.a.common_params.url);
process()->sink().ClearMessages();
// Now test history.forward()
@@ -3883,7 +3942,7 @@ TEST_F(NavigationControllerTest, HistoryNavigate) {
message = process()->sink().GetFirstMessageMatching(FrameMsg_Navigate::ID);
ASSERT_TRUE(message != NULL);
FrameMsg_Navigate::Read(message, &nav_params);
- EXPECT_EQ(url3, nav_params.a.url);
+ EXPECT_EQ(url3, nav_params.a.common_params.url);
process()->sink().ClearMessages();
controller.DiscardNonCommittedEntries();
@@ -3971,7 +4030,7 @@ TEST_F(NavigationControllerTest, PruneAllButLastCommittedForPendingNotInList) {
// Create a pending entry that is not in the entry list.
controller.LoadURL(
- url3, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(controller.GetPendingEntry());
EXPECT_EQ(2, controller.GetEntryCount());
@@ -4038,7 +4097,7 @@ TEST_F(NavigationControllerTest, IsInitialNavigation) {
// After starting a new navigation, it stays false.
const GURL url2("http://foo2");
controller.LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
}
// Check that the favicon is not reused across a client redirect.
@@ -4071,7 +4130,7 @@ TEST_F(NavigationControllerTest, ClearFaviconOnRedirect) {
main_test_rfh()->SendNavigateWithTransition(
0, // same page ID.
kPageWithoutFavicon,
- PAGE_TRANSITION_CLIENT_REDIRECT);
+ ui::PAGE_TRANSITION_CLIENT_REDIRECT);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -4113,7 +4172,7 @@ TEST_F(NavigationControllerTest, BackNavigationDoesNotClearFavicon) {
main_test_rfh()->SendNavigateWithTransition(
0,
kUrl1,
- PAGE_TRANSITION_FORWARD_BACK);
+ ui::PAGE_TRANSITION_FORWARD_BACK);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -4220,14 +4279,17 @@ TEST_F(NavigationControllerTest, MAYBE_PurgeScreenshot) {
}
}
-TEST_F(NavigationControllerTest, PushStateUpdatesTitle) {
-
- // Navigate
- test_rvh()->SendNavigate(1, GURL("http://foo"));
+TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) {
+ // Navigate.
+ contents()->GetMainFrame()->SendNavigate(1, GURL("http://foo"));
- // Set title
+ // Set title and favicon.
base::string16 title(base::ASCIIToUTF16("Title"));
+ FaviconStatus favicon;
+ favicon.valid = true;
+ favicon.url = GURL("http://foo/favicon.ico");
controller().GetLastCommittedEntry()->SetTitle(title);
+ controller().GetLastCommittedEntry()->GetFavicon() = favicon;
// history.pushState() is called.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -4236,12 +4298,16 @@ TEST_F(NavigationControllerTest, PushStateUpdatesTitle) {
params.url = url;
params.page_state = PageState::CreateFromURL(url);
params.was_within_same_page = true;
- test_rvh()->SendNavigateWithParams(&params);
+ contents()->GetMainFrame()->SendNavigateWithParams(&params);
// The title should immediately be visible on the new NavigationEntry.
base::string16 new_title =
controller().GetLastCommittedEntry()->GetTitleForDisplay(std::string());
EXPECT_EQ(title, new_title);
+ FaviconStatus new_favicon =
+ controller().GetLastCommittedEntry()->GetFavicon();
+ EXPECT_EQ(favicon.valid, new_favicon.valid);
+ EXPECT_EQ(favicon.url, new_favicon.url);
}
// Test that the navigation controller clears its session history when a
@@ -4277,8 +4343,8 @@ TEST_F(NavigationControllerTest, ClearHistoryList) {
ASSERT_TRUE(entry);
EXPECT_TRUE(entry->should_clear_history_list());
- // Assume that the RV correctly cleared its history and commit the navigation.
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost())->
+ // Assume that the RF correctly cleared its history and commit the navigation.
+ contents()->GetPendingMainFrame()->
set_simulate_history_list_was_cleared(true);
contents()->CommitPendingNavigation();
@@ -4303,25 +4369,25 @@ TEST_F(NavigationControllerTest, PostThenReplaceStateThenReload) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.url = url;
- params.transition = PAGE_TRANSITION_FORM_SUBMIT;
+ params.transition = ui::PAGE_TRANSITION_FORM_SUBMIT;
params.gesture = NavigationGestureUser;
params.page_state = PageState::CreateFromURL(url);
params.was_within_same_page = false;
params.is_post = true;
params.post_id = 2;
- test_rvh()->SendNavigateWithParams(&params);
+ contents()->GetMainFrame()->SendNavigateWithParams(&params);
// history.replaceState() is called.
GURL replace_url("http://foo#foo");
params.page_id = 1;
params.url = replace_url;
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
params.gesture = NavigationGestureUser;
params.page_state = PageState::CreateFromURL(replace_url);
params.was_within_same_page = true;
params.is_post = false;
params.post_id = -1;
- test_rvh()->SendNavigateWithParams(&params);
+ contents()->GetMainFrame()->SendNavigateWithParams(&params);
// Now reload. replaceState overrides the POST, so we should not show a
// repost warning dialog.
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index b021d5eda18..7105608f774 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -43,7 +43,7 @@ NavigationEntryImpl::NavigationEntryImpl()
page_type_(PAGE_TYPE_NORMAL),
update_virtual_url_with_url_(false),
page_id_(-1),
- transition_type_(PAGE_TRANSITION_LINK),
+ transition_type_(ui::PAGE_TRANSITION_LINK),
has_post_data_(false),
post_id_(-1),
restore_type_(RESTORE_NONE),
@@ -61,7 +61,7 @@ NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
const GURL& url,
const Referrer& referrer,
const base::string16& title,
- PageTransition transition_type,
+ ui::PageTransition transition_type,
bool is_renderer_initiated)
: unique_id_(GetUniqueIDInConstructor()),
site_instance_(instance),
@@ -202,11 +202,11 @@ bool NavigationEntryImpl::IsViewSourceMode() const {
}
void NavigationEntryImpl::SetTransitionType(
- PageTransition transition_type) {
+ ui::PageTransition transition_type) {
transition_type_ = transition_type;
}
-PageTransition NavigationEntryImpl::GetTransitionType() const {
+ui::PageTransition NavigationEntryImpl::GetTransitionType() const {
return transition_type_;
}
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index 613f45edb42..37de18213cb 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -30,65 +30,63 @@ class CONTENT_EXPORT NavigationEntryImpl
const GURL& url,
const Referrer& referrer,
const base::string16& title,
- PageTransition transition_type,
+ ui::PageTransition transition_type,
bool is_renderer_initiated);
- virtual ~NavigationEntryImpl();
+ ~NavigationEntryImpl() override;
// NavigationEntry implementation:
- virtual int GetUniqueID() const OVERRIDE;
- virtual PageType GetPageType() const OVERRIDE;
- virtual void SetURL(const GURL& url) OVERRIDE;
- virtual const GURL& GetURL() const OVERRIDE;
- virtual void SetBaseURLForDataURL(const GURL& url) OVERRIDE;
- virtual const GURL& GetBaseURLForDataURL() const OVERRIDE;
- virtual void SetReferrer(const Referrer& referrer) OVERRIDE;
- virtual const Referrer& GetReferrer() const OVERRIDE;
- virtual void SetVirtualURL(const GURL& url) OVERRIDE;
- virtual const GURL& GetVirtualURL() const OVERRIDE;
- virtual void SetTitle(const base::string16& title) OVERRIDE;
- virtual const base::string16& GetTitle() const OVERRIDE;
- virtual void SetPageState(const PageState& state) OVERRIDE;
- virtual const PageState& GetPageState() const OVERRIDE;
- virtual void SetPageID(int page_id) OVERRIDE;
- virtual int32 GetPageID() const OVERRIDE;
- virtual const base::string16& GetTitleForDisplay(
- const std::string& languages) const OVERRIDE;
- virtual bool IsViewSourceMode() const OVERRIDE;
- virtual void SetTransitionType(PageTransition transition_type) OVERRIDE;
- virtual PageTransition GetTransitionType() const OVERRIDE;
- virtual const GURL& GetUserTypedURL() const OVERRIDE;
- virtual void SetHasPostData(bool has_post_data) OVERRIDE;
- virtual bool GetHasPostData() const OVERRIDE;
- virtual void SetPostID(int64 post_id) OVERRIDE;
- virtual int64 GetPostID() const OVERRIDE;
- virtual void SetBrowserInitiatedPostData(
- const base::RefCountedMemory* data) OVERRIDE;
- virtual const base::RefCountedMemory*
- GetBrowserInitiatedPostData() const OVERRIDE;
- virtual const FaviconStatus& GetFavicon() const OVERRIDE;
- virtual FaviconStatus& GetFavicon() OVERRIDE;
- virtual const SSLStatus& GetSSL() const OVERRIDE;
- virtual SSLStatus& GetSSL() OVERRIDE;
- virtual void SetOriginalRequestURL(const GURL& original_url) OVERRIDE;
- virtual const GURL& GetOriginalRequestURL() const OVERRIDE;
- virtual void SetIsOverridingUserAgent(bool override) OVERRIDE;
- virtual bool GetIsOverridingUserAgent() const OVERRIDE;
- virtual void SetTimestamp(base::Time timestamp) OVERRIDE;
- virtual base::Time GetTimestamp() const OVERRIDE;
- virtual void SetCanLoadLocalResources(bool allow) OVERRIDE;
- virtual bool GetCanLoadLocalResources() const OVERRIDE;
- virtual void SetFrameToNavigate(const std::string& frame_name) OVERRIDE;
- virtual const std::string& GetFrameToNavigate() const OVERRIDE;
- virtual void SetExtraData(const std::string& key,
- const base::string16& data) OVERRIDE;
- virtual bool GetExtraData(const std::string& key,
- base::string16* data) const OVERRIDE;
- virtual void ClearExtraData(const std::string& key) OVERRIDE;
- virtual void SetHttpStatusCode(int http_status_code) OVERRIDE;
- virtual int GetHttpStatusCode() const OVERRIDE;
- virtual void SetRedirectChain(const std::vector<GURL>& redirects) OVERRIDE;
- virtual const std::vector<GURL>& GetRedirectChain() const OVERRIDE;
- virtual bool IsRestored() const OVERRIDE;
+ int GetUniqueID() const override;
+ PageType GetPageType() const override;
+ void SetURL(const GURL& url) override;
+ const GURL& GetURL() const override;
+ void SetBaseURLForDataURL(const GURL& url) override;
+ const GURL& GetBaseURLForDataURL() const override;
+ void SetReferrer(const Referrer& referrer) override;
+ const Referrer& GetReferrer() const override;
+ void SetVirtualURL(const GURL& url) override;
+ const GURL& GetVirtualURL() const override;
+ void SetTitle(const base::string16& title) override;
+ const base::string16& GetTitle() const override;
+ void SetPageState(const PageState& state) override;
+ const PageState& GetPageState() const override;
+ void SetPageID(int page_id) override;
+ int32 GetPageID() const override;
+ const base::string16& GetTitleForDisplay(
+ const std::string& languages) const override;
+ bool IsViewSourceMode() const override;
+ void SetTransitionType(ui::PageTransition transition_type) override;
+ ui::PageTransition GetTransitionType() const override;
+ const GURL& GetUserTypedURL() const override;
+ void SetHasPostData(bool has_post_data) override;
+ bool GetHasPostData() const override;
+ void SetPostID(int64 post_id) override;
+ int64 GetPostID() const override;
+ void SetBrowserInitiatedPostData(const base::RefCountedMemory* data) override;
+ const base::RefCountedMemory* GetBrowserInitiatedPostData() const override;
+ const FaviconStatus& GetFavicon() const override;
+ FaviconStatus& GetFavicon() override;
+ const SSLStatus& GetSSL() const override;
+ SSLStatus& GetSSL() override;
+ void SetOriginalRequestURL(const GURL& original_url) override;
+ const GURL& GetOriginalRequestURL() const override;
+ void SetIsOverridingUserAgent(bool override) override;
+ bool GetIsOverridingUserAgent() const override;
+ void SetTimestamp(base::Time timestamp) override;
+ base::Time GetTimestamp() const override;
+ void SetCanLoadLocalResources(bool allow) override;
+ bool GetCanLoadLocalResources() const override;
+ void SetFrameToNavigate(const std::string& frame_name) override;
+ const std::string& GetFrameToNavigate() const override;
+ void SetExtraData(const std::string& key,
+ const base::string16& data) override;
+ bool GetExtraData(const std::string& key,
+ base::string16* data) const override;
+ void ClearExtraData(const std::string& key) override;
+ void SetHttpStatusCode(int http_status_code) override;
+ int GetHttpStatusCode() const override;
+ void SetRedirectChain(const std::vector<GURL>& redirects) override;
+ const std::vector<GURL>& GetRedirectChain() const override;
+ bool IsRestored() const override;
// Once a navigation entry is committed, we should no longer track several
// pieces of non-persisted state, as documented on the members below.
@@ -241,7 +239,7 @@ class CONTENT_EXPORT NavigationEntryImpl
PageState page_state_;
int32 page_id_;
SSLStatus ssl_;
- PageTransition transition_type_;
+ ui::PageTransition transition_type_;
GURL user_typed_url_;
bool has_post_data_;
int64 post_id_;
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
index 79768019179..663386a1316 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -20,7 +20,7 @@ class NavigationEntryTest : public testing::Test {
NavigationEntryTest() : instance_(NULL) {
}
- virtual void SetUp() {
+ void SetUp() override {
entry1_.reset(new NavigationEntryImpl);
#if !defined(OS_IOS)
@@ -31,12 +31,11 @@ class NavigationEntryTest : public testing::Test {
GURL("test:url"),
Referrer(GURL("from"), blink::WebReferrerPolicyDefault),
ASCIIToUTF16("title"),
- PAGE_TRANSITION_TYPED,
+ ui::PAGE_TRANSITION_TYPED,
false));
}
- virtual void TearDown() {
- }
+ void TearDown() override {}
protected:
scoped_ptr<NavigationEntryImpl> entry1_;
@@ -156,10 +155,10 @@ TEST_F(NavigationEntryTest, NavigationEntryAccessors) {
EXPECT_EQ(2, entry2_->GetPageID());
// Transition type
- EXPECT_EQ(PAGE_TRANSITION_LINK, entry1_->GetTransitionType());
- EXPECT_EQ(PAGE_TRANSITION_TYPED, entry2_->GetTransitionType());
- entry2_->SetTransitionType(PAGE_TRANSITION_RELOAD);
- EXPECT_EQ(PAGE_TRANSITION_RELOAD, entry2_->GetTransitionType());
+ EXPECT_EQ(ui::PAGE_TRANSITION_LINK, entry1_->GetTransitionType());
+ EXPECT_EQ(ui::PAGE_TRANSITION_TYPED, entry2_->GetTransitionType());
+ entry2_->SetTransitionType(ui::PAGE_TRANSITION_RELOAD);
+ EXPECT_EQ(ui::PAGE_TRANSITION_RELOAD, entry2_->GetTransitionType());
// Is renderer initiated
EXPECT_FALSE(entry1_->is_renderer_initiated());
diff --git a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
index 1e476827703..162cfb79043 100644
--- a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.cc
@@ -13,9 +13,6 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/effects/SkLumaColorFilter.h"
#include "ui/gfx/codec/png_codec.h"
namespace {
@@ -27,7 +24,7 @@ const int kMinScreenshotIntervalMS = 1000;
namespace content {
-// Converts SkBitmap to grayscale and encodes to PNG data in a worker thread.
+// Encodes the A8 SkBitmap to grayscale PNG in a worker thread.
class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> {
public:
ScreenshotData() {
@@ -52,22 +49,10 @@ class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> {
}
void EncodeOnWorker(const SkBitmap& bitmap) {
+ DCHECK_EQ(bitmap.colorType(), kAlpha_8_SkColorType);
+ // Encode the A8 bitmap to grayscale PNG treating alpha as color intensity.
std::vector<unsigned char> data;
- // Paint |bitmap| to a kA8_Config SkBitmap
- SkBitmap a8Bitmap;
- a8Bitmap.setConfig(SkBitmap::kA8_Config,
- bitmap.width(),
- bitmap.height(),
- 0);
- a8Bitmap.allocPixels();
- SkCanvas canvas(a8Bitmap);
- SkPaint paint;
- SkColorFilter* filter = SkLumaColorFilter::Create();
- paint.setColorFilter(filter);
- filter->unref();
- canvas.drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
- // Encode the a8Bitmap to grayscale PNG treating alpha as color intensity
- if (gfx::PNGCodec::EncodeA8SkBitmap(a8Bitmap, &data))
+ if (gfx::PNGCodec::EncodeA8SkBitmap(bitmap, &data))
data_ = new base::RefCountedBytes(data);
}
@@ -79,15 +64,16 @@ class ScreenshotData : public base::RefCountedThreadSafe<ScreenshotData> {
NavigationEntryScreenshotManager::NavigationEntryScreenshotManager(
NavigationControllerImpl* owner)
: owner_(owner),
- screenshot_factory_(this),
- min_screenshot_interval_ms_(kMinScreenshotIntervalMS) {
+ min_screenshot_interval_ms_(kMinScreenshotIntervalMS),
+ screenshot_factory_(this) {
+
}
NavigationEntryScreenshotManager::~NavigationEntryScreenshotManager() {
}
void NavigationEntryScreenshotManager::TakeScreenshot() {
- static bool overscroll_enabled = CommandLine::ForCurrentProcess()->
+ static bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
if (!overscroll_enabled)
return;
@@ -134,14 +120,13 @@ void NavigationEntryScreenshotManager::TakeScreenshotImpl(
NavigationEntryImpl* entry) {
DCHECK(host && host->GetView());
DCHECK(entry);
- SkBitmap::Config preferred_format = host->PreferredReadbackFormat();
host->CopyFromBackingStore(
gfx::Rect(),
host->GetView()->GetViewBounds().size(),
base::Bind(&NavigationEntryScreenshotManager::OnScreenshotTaken,
screenshot_factory_.GetWeakPtr(),
entry->GetUniqueID()),
- preferred_format);
+ kAlpha_8_SkColorType);
}
void NavigationEntryScreenshotManager::SetMinScreenshotIntervalMS(
diff --git a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h
index 072d6fd4a7f..21c78f18e62 100644
--- a/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h
+++ b/chromium/content/browser/frame_host/navigation_entry_screenshot_manager.h
@@ -74,14 +74,14 @@ class CONTENT_EXPORT NavigationEntryScreenshotManager {
// The navigation controller that owns this screenshot-manager.
NavigationControllerImpl* owner_;
+ base::Time last_screenshot_time_;
+ int min_screenshot_interval_ms_;
+
// Taking a screenshot and encoding them can be async. So use a weakptr for
// the callback to make sure that the screenshot/encoding completion callback
// does not trigger on a destroyed NavigationEntryScreenshotManager.
base::WeakPtrFactory<NavigationEntryScreenshotManager> screenshot_factory_;
- base::Time last_screenshot_time_;
- int min_screenshot_interval_ms_;
-
DISALLOW_COPY_AND_ASSIGN(NavigationEntryScreenshotManager);
};
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
new file mode 100644
index 00000000000..57f5479727c
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -0,0 +1,67 @@
+// Copyright 2014 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 "content/browser/frame_host/navigation_request.h"
+
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/browser/loader/navigation_url_loader.h"
+#include "content/common/resource_request_body.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/stream_handle.h"
+#include "net/url_request/redirect_info.h"
+
+namespace content {
+
+NavigationRequest::NavigationRequest(
+ FrameTreeNode* frame_tree_node,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params)
+ : frame_tree_node_(frame_tree_node),
+ common_params_(common_params),
+ commit_params_(commit_params) {
+}
+
+NavigationRequest::~NavigationRequest() {
+}
+
+void NavigationRequest::BeginNavigation(
+ scoped_ptr<NavigationRequestInfo> info,
+ scoped_refptr<ResourceRequestBody> request_body) {
+ DCHECK(!loader_);
+ loader_ = NavigationURLLoader::Create(
+ frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
+ frame_tree_node_->frame_tree_node_id(), common_params_, info.Pass(),
+ request_body.get(), this);
+
+ // TODO(davidben): Fire (and add as necessary) observer methods such as
+ // DidStartProvisionalLoadForFrame for the navigation.
+}
+
+void NavigationRequest::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response) {
+ // TODO(davidben): Track other changes from redirects. These are important
+ // for, e.g., reloads.
+ common_params_.url = redirect_info.new_url;
+
+ // TODO(davidben): This where prerender and navigation_interceptor should be
+ // integrated. For now, just always follow all redirects.
+ loader_->FollowRedirect();
+}
+
+void NavigationRequest::OnResponseStarted(
+ const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body) {
+ frame_tree_node_->navigator()->CommitNavigation(frame_tree_node_,
+ response.get(), body.Pass());
+}
+
+void NavigationRequest::OnRequestFailed(int net_error) {
+ // TODO(davidben): Network failures should display a network error page.
+ NOTIMPLEMENTED();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
new file mode 100644
index 00000000000..eb537211374
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -0,0 +1,74 @@
+// Copyright 2014 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 CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/common/content_export.h"
+#include "content/common/navigation_params.h"
+
+namespace content {
+
+class FrameTreeNode;
+class NavigationURLLoader;
+class ResourceRequestBody;
+struct NavigationRequestInfo;
+
+// PlzNavigate
+// A UI thread object that owns a navigation request until it commits. It
+// ensures the UI thread can start a navigation request in the
+// ResourceDispatcherHost (that lives on the IO thread).
+// TODO(clamy): Describe the interactions between the UI and IO thread during
+// the navigation following its refactoring.
+class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
+ public:
+ NavigationRequest(FrameTreeNode* frame_tree_node,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params);
+
+ ~NavigationRequest() override;
+
+ // Called on the UI thread by the RenderFrameHostManager which owns the
+ // NavigationRequest. Takes ownership of |info|. After calling this function,
+ // |body| can no longer be manipulated on the UI thread.
+ void BeginNavigation(scoped_ptr<NavigationRequestInfo> info,
+ scoped_refptr<ResourceRequestBody> body);
+
+ CommonNavigationParams& common_params() { return common_params_; }
+
+ const CommitNavigationParams& commit_params() const { return commit_params_; }
+
+ NavigationURLLoader* loader_for_testing() const { return loader_.get(); }
+
+ private:
+ // NavigationURLLoaderDelegate implementation.
+ void OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response) override;
+ void OnResponseStarted(const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body) override;
+ void OnRequestFailed(int net_error) override;
+
+ FrameTreeNode* frame_tree_node_;
+
+ // Initialized on creation of the NavigationRequest. Sent to the renderer when
+ // the navigation is ready to commit.
+ // Note: When the navigation is ready to commit, the url in |common_params|
+ // will be set to the final navigation url, obtained after following all
+ // redirects.
+ CommonNavigationParams common_params_;
+ const CommitNavigationParams commit_params_;
+
+ scoped_ptr<NavigationURLLoader> loader_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_H_
diff --git a/chromium/content/browser/frame_host/navigation_request_info.cc b/chromium/content/browser/frame_host/navigation_request_info.cc
new file mode 100644
index 00000000000..91568ad36df
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_request_info.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 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 "content/browser/frame_host/navigation_request_info.h"
+
+#include "content/common/resource_request_body.h"
+
+namespace content {
+
+NavigationRequestInfo::NavigationRequestInfo(
+ const FrameHostMsg_BeginNavigation_Params& params)
+ : navigation_params(params),
+ is_main_frame(true),
+ parent_is_main_frame(false) {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request_info.h b/chromium/content/browser/frame_host/navigation_request_info.h
new file mode 100644
index 00000000000..70bb78729dd
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_request_info.h
@@ -0,0 +1,40 @@
+// Copyright 2014 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 CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_INFO_H_
+#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_INFO_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "content/common/frame_messages.h"
+#include "content/public/common/referrer.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// A struct to hold the parameters needed to start a navigation request in
+// ResourceDispatcherHost. It is initialized on the UI thread, and then passed
+// to the IO thread by a NavigationRequest object.
+struct CONTENT_EXPORT NavigationRequestInfo {
+ explicit NavigationRequestInfo(
+ const FrameHostMsg_BeginNavigation_Params& params);
+
+ const FrameHostMsg_BeginNavigation_Params navigation_params;
+
+ // ---------------------------------------------------------------------------
+ // The following parameters should be filled in by RenderFrameHostManager
+ // before the navigation request is sent to the ResourceDispatcherHost.
+
+ // Usually the URL of the document in the top-level window, which may be
+ // checked by the third-party cookie blocking policy.
+ GURL first_party_for_cookies;
+ bool is_main_frame;
+ bool parent_is_main_frame;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_REQUEST_INFO_H_
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index 3d5eb8f906b..3f5d6cb5f99 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -5,6 +5,7 @@
#include "content/browser/frame_host/navigator.h"
#include "base/time/time.h"
+#include "content/public/browser/stream_handle.h"
namespace content {
@@ -22,4 +23,9 @@ base::TimeTicks Navigator::GetCurrentLoadStart() {
return base::TimeTicks::Now();
}
+void Navigator::CommitNavigation(FrameTreeNode* frame_tree_node,
+ ResourceResponse* response,
+ scoped_ptr<StreamHandle> body) {
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index a64edeb717b..5063faf20e5 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -6,11 +6,13 @@
#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_H_
#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_controller.h"
#include "ui/base/window_open_disposition.h"
class GURL;
+struct FrameHostMsg_BeginNavigation_Params;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
@@ -20,10 +22,15 @@ class TimeTicks;
namespace content {
+class FrameTreeNode;
class NavigationControllerImpl;
class NavigationEntryImpl;
+class NavigationRequest;
class NavigatorDelegate;
class RenderFrameHostImpl;
+class StreamHandle;
+struct CommonNavigationParams;
+struct ResourceResponse;
// Implementations of this interface are responsible for performing navigations
// in a node of the FrameTree. Its lifetime is bound to all FrameTreeNode
@@ -37,13 +44,12 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
// Returns the NavigationController associated with this Navigator.
virtual NavigationController* GetController();
-
// Notifications coming from the RenderFrameHosts ----------------------------
// The RenderFrameHostImpl started a provisional load.
virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
- int parent_routing_id,
- const GURL& url) {};
+ const GURL& url,
+ bool is_transition_navigation) {};
// The RenderFrameHostImpl has failed a provisional load.
virtual void DidFailProvisionalLoadWithError(
@@ -57,17 +63,6 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
int error_code,
const base::string16& error_description) {}
- // The RenderFrameHostImpl processed a redirect during a provisional load.
- //
- // TODO(creis): Remove this method and have the pre-rendering code listen to
- // WebContentsObserver::DidGetRedirectForResourceRequest instead.
- // See http://crbug.com/78512.
- virtual void DidRedirectProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- int32 page_id,
- const GURL& source_url,
- const GURL& target_url) {}
-
// The RenderFrameHostImpl has committed a navigation.
virtual void DidNavigate(
RenderFrameHostImpl* render_frame_host,
@@ -113,12 +108,45 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
const GURL& url,
const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
WindowOpenDisposition disposition,
const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
bool user_gesture) {}
+ // PlzNavigate: Used to start a navigation. OnBeginNavigation is called
+ // directly by RequestNavigation when there is no live renderer. Otherwise, it
+ // is called following a BeginNavigation IPC from the renderer (which in
+ // browser-initiated navigation also happens after RequestNavigation has been
+ // called).
+ virtual void OnBeginNavigation(
+ FrameTreeNode* frame_tree_node,
+ const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params) {}
+
+ // PlzNavigate
+ // Signal |render_frame_host| that a navigation is ready to commit (the
+ // response to the navigation request has been received).
+ virtual void CommitNavigation(FrameTreeNode* frame_tree_node,
+ ResourceResponse* response,
+ scoped_ptr<StreamHandle> body);
+
+ // PlzNavigate
+ // Cancel a NavigationRequest for |frame_tree_node|. Called when
+ // |frame_tree_node| is destroyed.
+ virtual void CancelNavigation(FrameTreeNode* frame_tree_node) {}
+
+ // Called when the first resource request for a given navigation is executed
+ // so that it can be tracked into an histogram.
+ virtual void LogResourceRequestTime(
+ base::TimeTicks timestamp, const GURL& url) {};
+
+ // Called to record the time it took to execute the before unload hook for the
+ // current navigation.
+ virtual void LogBeforeUnloadTime(
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time) {}
+
protected:
friend class base::RefCounted<Navigator>;
virtual ~Navigator() {}
diff --git a/chromium/content/browser/frame_host/navigator_delegate.h b/chromium/content/browser/frame_host/navigator_delegate.h
index 0835fe04a49..80ed2135223 100644
--- a/chromium/content/browser/frame_host/navigator_delegate.h
+++ b/chromium/content/browser/frame_host/navigator_delegate.h
@@ -8,7 +8,7 @@
#include "base/strings/string16.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
class GURL;
@@ -29,11 +29,14 @@ class CONTENT_EXPORT NavigatorDelegate {
// represented by |render_frame_host|.
virtual void DidStartProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
- int parent_routing_id,
const GURL& validated_url,
bool is_error_page,
bool is_iframe_srcdoc) {}
+ // The |render_frame_host| started a transition-flagged navigation.
+ virtual void DidStartNavigationTransition(
+ RenderFrameHostImpl* render_frame_host) {}
+
// A provisional load in |render_frame_host| failed.
virtual void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
@@ -46,23 +49,15 @@ class CONTENT_EXPORT NavigatorDelegate {
int error_code,
const base::string16& error_description) {}
- // A redirect was processed in |render_frame_host| during a provisional load.
- virtual void DidRedirectProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& validated_target_url) {}
-
// A navigation was committed in |render_frame_host|.
virtual void DidCommitProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
- const base::string16& frame_unique_name,
- bool is_main_frame,
const GURL& url,
- PageTransition transition_type) {}
+ ui::PageTransition transition_type) {}
// Handles post-navigation tasks in navigation BEFORE the entry has been
// committed to the NavigationController.
- virtual void DidNavigateMainFramePreCommit(
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {}
+ virtual void DidNavigateMainFramePreCommit(bool navigation_is_within_page) {}
// Handles post-navigation tasks in navigation AFTER the entry has been
// committed to the NavigationController. Note that the NavigationEntry is
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index e12df2ac420..e3b56215d4d 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -5,17 +5,21 @@
#include "content/browser/frame_host/navigator_impl.h"
#include "base/command_line.h"
+#include "base/metrics/histogram.h"
+#include "base/time/time.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_request.h"
+#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
-#include "content/common/frame_messages.h"
+#include "content/common/navigation_params.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
@@ -25,11 +29,16 @@
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/stream_handle.h"
+#include "content/public/browser/user_metrics.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
namespace content {
@@ -61,13 +70,89 @@ FrameMsg_Navigate_Type::Value GetNavigationType(
return FrameMsg_Navigate_Type::NORMAL;
}
+// PlzNavigate
+// Returns the net load flags to use based on the navigation type.
+// TODO(clamy): unify the code with what is happening on the renderer side.
+int LoadFlagFromNavigationType(FrameMsg_Navigate_Type::Value navigation_type) {
+ int load_flags = net::LOAD_NORMAL;
+ switch (navigation_type) {
+ case FrameMsg_Navigate_Type::RELOAD:
+ case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
+ load_flags |= net::LOAD_VALIDATE_CACHE;
+ break;
+ case FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE:
+ load_flags |= net::LOAD_BYPASS_CACHE;
+ break;
+ case FrameMsg_Navigate_Type::RESTORE:
+ load_flags |= net::LOAD_PREFERRING_CACHE;
+ break;
+ case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
+ load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ break;
+ case FrameMsg_Navigate_Type::NORMAL:
+ default:
+ break;
+ }
+ return load_flags;
+}
+
+// PlzNavigate
+// Generates a default FrameHostMsg_BeginNavigation_Params to be used when there
+// is no live renderer.
+FrameHostMsg_BeginNavigation_Params MakeDefaultBeginNavigation(
+ const RequestNavigationParams& request_params,
+ FrameMsg_Navigate_Type::Value navigation_type) {
+ FrameHostMsg_BeginNavigation_Params begin_navigation_params;
+ begin_navigation_params.method = request_params.is_post ? "POST" : "GET";
+ begin_navigation_params.load_flags =
+ LoadFlagFromNavigationType(navigation_type);
+
+ // TODO(clamy): Post data from the browser should be put in the request body.
+ // Headers should be filled in as well.
+
+ begin_navigation_params.has_user_gesture = false;
+ return begin_navigation_params;
+}
+
+RenderFrameHostManager* GetRenderManager(RenderFrameHostImpl* rfh) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess))
+ return rfh->frame_tree_node()->render_manager();
+
+ return rfh->frame_tree_node()->frame_tree()->root()->render_manager();
+}
+
void MakeNavigateParams(const NavigationEntryImpl& entry,
- const NavigationControllerImpl& controller,
+ NavigationControllerImpl* controller,
NavigationController::ReloadType reload_type,
+ base::TimeTicks navigation_start,
FrameMsg_Navigate_Params* params) {
+ params->common_params = CommonNavigationParams(
+ entry.GetURL(), entry.GetReferrer(), entry.GetTransitionType(),
+ GetNavigationType(controller->GetBrowserContext(), entry, reload_type),
+ !entry.IsViewSourceMode());
+ params->request_params = RequestNavigationParams(
+ entry.GetHasPostData(),
+ entry.extra_headers(),
+ entry.GetBrowserInitiatedPostData());
+ params->commit_params = CommitNavigationParams(
+ entry.GetPageState(), entry.GetIsOverridingUserAgent(), navigation_start);
+ if (!entry.GetBaseURLForDataURL().is_empty()) {
+ params->base_url_for_data_url = entry.GetBaseURLForDataURL();
+ params->history_url_for_data_url = entry.GetVirtualURL();
+ }
+ params->should_replace_current_entry = entry.should_replace_entry();
+ // This is used by the old performance infrastructure to set up DocumentState
+ // associated with the RenderView.
+ // TODO(ppi): make it go away.
+ params->request_time = base::Time::Now();
+ params->transferred_request_child_id =
+ entry.transferred_global_request_id().child_id;
+ params->transferred_request_request_id =
+ entry.transferred_global_request_id().request_id;
+
params->page_id = entry.GetPageID();
params->should_clear_history_list = entry.should_clear_history_list();
- params->should_replace_current_entry = entry.should_replace_entry();
if (entry.should_clear_history_list()) {
// Set the history list related parameters to the same values a
// NavigationController would return before its first navigation. This will
@@ -76,41 +161,14 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
params->current_history_list_offset = -1;
params->current_history_list_length = 0;
} else {
- params->pending_history_list_offset = controller.GetIndexOfEntry(&entry);
+ params->pending_history_list_offset = controller->GetIndexOfEntry(&entry);
params->current_history_list_offset =
- controller.GetLastCommittedEntryIndex();
- params->current_history_list_length = controller.GetEntryCount();
+ controller->GetLastCommittedEntryIndex();
+ params->current_history_list_length = controller->GetEntryCount();
}
- params->url = entry.GetURL();
- if (!entry.GetBaseURLForDataURL().is_empty()) {
- params->base_url_for_data_url = entry.GetBaseURLForDataURL();
- params->history_url_for_data_url = entry.GetVirtualURL();
- }
- params->referrer = entry.GetReferrer();
- params->transition = entry.GetTransitionType();
- params->page_state = entry.GetPageState();
- params->navigation_type =
- GetNavigationType(controller.GetBrowserContext(), entry, reload_type);
- params->request_time = base::Time::Now();
- params->extra_headers = entry.extra_headers();
- params->transferred_request_child_id =
- entry.transferred_global_request_id().child_id;
- params->transferred_request_request_id =
- entry.transferred_global_request_id().request_id;
- params->is_overriding_user_agent = entry.GetIsOverridingUserAgent();
- // Avoid downloading when in view-source mode.
- params->allow_download = !entry.IsViewSourceMode();
- params->is_post = entry.GetHasPostData();
- if (entry.GetBrowserInitiatedPostData()) {
- params->browser_initiated_post_data.assign(
- entry.GetBrowserInitiatedPostData()->front(),
- entry.GetBrowserInitiatedPostData()->front() +
- entry.GetBrowserInitiatedPostData()->size());
- }
-
// Set the redirect chain to the navigation's redirects, unless we are
// returning to a completed navigation (whose previous redirects don't apply).
- if (PageTransitionIsNewNavigation(params->transition)) {
+ if (ui::PageTransitionIsNewNavigation(params->common_params.transition)) {
params->redirects = entry.GetRedirectChain();
} else {
params->redirects.clear();
@@ -120,15 +178,25 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
params->frame_to_navigate = entry.GetFrameToNavigate();
}
-RenderFrameHostManager* GetRenderManager(RenderFrameHostImpl* rfh) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
- return rfh->frame_tree_node()->render_manager();
-
- return rfh->frame_tree_node()->frame_tree()->root()->render_manager();
-}
-
} // namespace
+struct NavigatorImpl::NavigationMetricsData {
+ NavigationMetricsData(base::TimeTicks start_time,
+ GURL url,
+ NavigationEntryImpl::RestoreType restore_type)
+ : start_time_(start_time), url_(url) {
+ is_restoring_from_last_session_ =
+ (restore_type ==
+ NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY ||
+ restore_type == NavigationEntryImpl::RESTORE_LAST_SESSION_CRASHED);
+ }
+
+ base::TimeTicks start_time_;
+ GURL url_;
+ bool is_restoring_from_last_session_;
+ base::TimeTicks url_job_start_time_;
+ base::TimeDelta before_unload_delay_;
+};
NavigatorImpl::NavigatorImpl(
NavigationControllerImpl* navigation_controller,
@@ -137,14 +205,16 @@ NavigatorImpl::NavigatorImpl(
delegate_(delegate) {
}
+NavigatorImpl::~NavigatorImpl() {}
+
NavigationController* NavigatorImpl::GetController() {
return controller_;
}
void NavigatorImpl::DidStartProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
- int parent_routing_id,
- const GURL& url) {
+ const GURL& url,
+ bool is_transition_navigation) {
bool is_error_page = (url.spec() == kUnreachableWebDataURL);
bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL);
GURL validated_url(url);
@@ -166,7 +236,7 @@ void NavigatorImpl::DidStartProvisionalLoad(
NavigationEntryImpl* entry = NavigationEntryImpl::FromNavigationEntry(
controller_->CreateNavigationEntry(validated_url,
content::Referrer(),
- content::PAGE_TRANSITION_LINK,
+ ui::PAGE_TRANSITION_LINK,
true /* is_renderer_initiated */,
std::string(),
controller_->GetBrowserContext()));
@@ -185,13 +255,15 @@ void NavigatorImpl::DidStartProvisionalLoad(
if (delegate_)
delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
}
+
+ if (delegate_ && is_transition_navigation)
+ delegate_->DidStartNavigationTransition(render_frame_host);
}
if (delegate_) {
// Notify the observer about the start of the provisional load.
delegate_->DidStartProvisionalLoad(
- render_frame_host, parent_routing_id,
- validated_url, is_error_page, is_iframe_srcdoc);
+ render_frame_host, validated_url, is_error_page, is_iframe_srcdoc);
}
}
@@ -281,40 +353,11 @@ void NavigatorImpl::DidFailLoadWithError(
}
}
-void NavigatorImpl::DidRedirectProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- int32 page_id,
- const GURL& source_url,
- const GURL& target_url) {
- // TODO(creis): Remove this method and have the pre-rendering code listen to
- // WebContentsObserver::DidGetRedirectForResourceRequest instead.
- // See http://crbug.com/78512.
- GURL validated_source_url(source_url);
- GURL validated_target_url(target_url);
- RenderProcessHost* render_process_host = render_frame_host->GetProcess();
- render_process_host->FilterURL(false, &validated_source_url);
- render_process_host->FilterURL(false, &validated_target_url);
- NavigationEntry* entry;
- if (page_id == -1) {
- entry = controller_->GetPendingEntry();
- } else {
- entry = controller_->GetEntryWithPageID(
- render_frame_host->GetSiteInstance(), page_id);
- }
- if (!entry || entry->GetURL() != validated_source_url)
- return;
-
- if (delegate_) {
- delegate_->DidRedirectProvisionalLoad(
- render_frame_host, validated_target_url);
- }
-}
-
bool NavigatorImpl::NavigateToEntry(
RenderFrameHostImpl* render_frame_host,
const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type) {
- TRACE_EVENT0("browser", "NavigatorImpl::NavigateToEntry");
+ TRACE_EVENT0("browser,navigation", "NavigatorImpl::NavigateToEntry");
// The renderer will reject IPC messages with URLs longer than
// this limit, so don't attempt to navigate with a longer URL.
@@ -324,8 +367,26 @@ bool NavigatorImpl::NavigateToEntry(
return false;
}
+ // This will be used to set the Navigation Timing API navigationStart
+ // parameter for browser navigations in new tabs (intents, tabs opened through
+ // "Open link in new tab"). We need to keep it above RFHM::Navigate() call to
+ // capture the time needed for the RenderFrameHost initialization.
+ base::TimeTicks navigation_start = base::TimeTicks::Now();
+
RenderFrameHostManager* manager =
render_frame_host->frame_tree_node()->render_manager();
+
+ // PlzNavigate: the RenderFrameHosts are no longer asked to navigate.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ navigation_data_.reset(new NavigationMetricsData(
+ navigation_start, entry.GetURL(), entry.restore_type()));
+ return RequestNavigation(render_frame_host->frame_tree_node(),
+ entry,
+ reload_type,
+ navigation_start);
+ }
+
RenderFrameHostImpl* dest_render_frame_host = manager->Navigate(entry);
if (!dest_render_frame_host)
return false; // Unable to create the desired RenderFrameHost.
@@ -335,29 +396,38 @@ bool NavigatorImpl::NavigateToEntry(
// For security, we should never send non-Web-UI URLs to a Web UI renderer.
// Double check that here.
- int enabled_bindings =
- dest_render_frame_host->render_view_host()->GetEnabledBindings();
- bool is_allowed_in_web_ui_renderer =
- WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
- controller_->GetBrowserContext(), entry.GetURL());
- if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
- !is_allowed_in_web_ui_renderer) {
- // Log the URL to help us diagnose any future failures of this CHECK.
- GetContentClient()->SetActiveURL(entry.GetURL());
- CHECK(0);
- }
+ CheckWebUIRendererDoesNotDisplayNormalURL(
+ dest_render_frame_host, entry.GetURL());
// Notify observers that we will navigate in this RenderFrame.
if (delegate_)
delegate_->AboutToNavigateRenderFrame(dest_render_frame_host);
- // Used for page load time metrics.
- current_load_start_ = base::TimeTicks::Now();
+ // Create the navigation parameters.
+ // TODO(vitalybuka): Move this before AboutToNavigateRenderFrame once
+ // http://crbug.com/408684 is fixed.
+ FrameMsg_Navigate_Params navigate_params;
+ MakeNavigateParams(
+ entry, controller_, reload_type, navigation_start, &navigate_params);
// Navigate in the desired RenderFrameHost.
- FrameMsg_Navigate_Params navigate_params;
- MakeNavigateParams(entry, *controller_, reload_type, &navigate_params);
- dest_render_frame_host->Navigate(navigate_params);
+ // We can skip this step in the rare case that this is a transfer navigation
+ // which began in the chosen RenderFrameHost, since the request has already
+ // been issued. In that case, simply resume the response.
+ bool is_transfer_to_same =
+ navigate_params.transferred_request_child_id != -1 &&
+ navigate_params.transferred_request_child_id ==
+ dest_render_frame_host->GetProcess()->GetID();
+ if (!is_transfer_to_same) {
+ navigation_data_.reset(new NavigationMetricsData(
+ navigation_start, entry.GetURL(), entry.restore_type()));
+ dest_render_frame_host->Navigate(navigate_params);
+ } else {
+ // No need to navigate again. Just resume the deferred request.
+ dest_render_frame_host->GetProcess()->ResumeDeferredNavigation(
+ GlobalRequestID(navigate_params.transferred_request_child_id,
+ navigate_params.transferred_request_request_id));
+ }
// Make sure no code called via RFH::Navigate clears the pending entry.
CHECK_EQ(controller_->GetPendingEntry(), &entry);
@@ -374,7 +444,7 @@ bool NavigatorImpl::NavigateToEntry(
// Notify observers about navigation.
if (delegate_) {
- delegate_->DidStartNavigationToPendingEntry(render_frame_host,
+ delegate_->DidStartNavigationToPendingEntry(dest_render_frame_host,
entry.GetURL(),
reload_type);
}
@@ -391,17 +461,22 @@ bool NavigatorImpl::NavigateToPendingEntry(
reload_type);
}
-base::TimeTicks NavigatorImpl::GetCurrentLoadStart() {
- return current_load_start_;
-}
-
void NavigatorImpl::DidNavigate(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) {
+ // PlzNavigate
+ // The navigation request has been committed so the browser process doesn't
+ // need to care about it anymore.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ navigation_request_map_.erase(
+ render_frame_host->frame_tree_node()->frame_tree_node_id());
+ }
+
FrameHostMsg_DidCommitProvisionalLoad_Params params(input_params);
FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree();
- bool use_site_per_process =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess);
+ bool use_site_per_process = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess);
if (use_site_per_process) {
// TODO(creis): Until we mirror the frame tree in the subframe's process,
@@ -414,11 +489,11 @@ void NavigatorImpl::DidNavigate(
pending_entry &&
pending_entry->frame_tree_node_id() ==
render_frame_host->frame_tree_node()->frame_tree_node_id()) {
- params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
}
}
- if (PageTransitionIsMainFrame(params.transition)) {
+ if (ui::PageTransitionIsMainFrame(params.transition)) {
if (delegate_) {
// When overscroll navigation gesture is enabled, a screenshot of the page
// in its current state is taken so that it can be used during the
@@ -436,7 +511,9 @@ void NavigatorImpl::DidNavigate(
}
// Run tasks that must execute just before the commit.
- delegate_->DidNavigateMainFramePreCommit(params);
+ bool is_navigation_within_page = controller_->IsURLInPageNavigation(
+ params.url, params.was_within_same_page, render_frame_host);
+ delegate_->DidNavigateMainFramePreCommit(is_navigation_within_page);
}
if (!use_site_per_process)
@@ -472,7 +549,7 @@ void NavigatorImpl::DidNavigate(
// TODO(nasko): Verify the correctness of the above comment, since some of the
// code doesn't exist anymore. Also, move this code in the
// PageTransitionIsMainFrame code block above.
- if (PageTransitionIsMainFrame(params.transition) && delegate_)
+ if (ui::PageTransitionIsMainFrame(params.transition) && delegate_)
delegate_->SetMainFrameMimeType(params.contents_mime_type);
LoadCommittedDetails details;
@@ -488,25 +565,20 @@ void NavigatorImpl::DidNavigate(
// different from the NAV_ENTRY_COMMITTED notification which doesn't include
// the actual URL navigated to and isn't sent for AUTO_SUBFRAME navigations.
if (details.type != NAVIGATION_TYPE_NAV_IGNORE && delegate_) {
- // For AUTO_SUBFRAME navigations, an event for the main frame is generated
- // that is not recorded in the navigation history. For the purpose of
- // tracking navigation events, we treat this event as a sub frame navigation
- // event.
- bool is_main_frame = did_navigate ? details.is_main_frame : false;
- PageTransition transition_type = params.transition;
+ DCHECK_EQ(!render_frame_host->GetParent(),
+ did_navigate ? details.is_main_frame : false);
+ ui::PageTransition transition_type = params.transition;
// Whether or not a page transition was triggered by going backward or
// forward in the history is only stored in the navigation controller's
// entry list.
if (did_navigate &&
(controller_->GetLastCommittedEntry()->GetTransitionType() &
- PAGE_TRANSITION_FORWARD_BACK)) {
- transition_type = PageTransitionFromInt(
- params.transition | PAGE_TRANSITION_FORWARD_BACK);
+ ui::PAGE_TRANSITION_FORWARD_BACK)) {
+ transition_type = ui::PageTransitionFromInt(
+ params.transition | ui::PAGE_TRANSITION_FORWARD_BACK);
}
delegate_->DidCommitProvisionalLoad(render_frame_host,
- params.frame_unique_name,
- is_main_frame,
params.url,
transition_type);
}
@@ -519,6 +591,10 @@ void NavigatorImpl::DidNavigate(
// DidNavigateMainFramePostCommit / DidNavigateAnyFramePostCommit (only if
// necessary, please).
+ // TODO(carlosk): Move this out when PlzNavigate implementation properly calls
+ // the observer methods.
+ RecordNavigationMetrics(details, params, site_instance);
+
// Run post-commit tasks.
if (delegate_) {
if (details.is_main_frame)
@@ -550,9 +626,10 @@ void NavigatorImpl::RequestOpenURL(
SiteInstance* current_site_instance =
GetRenderManager(render_frame_host)->current_frame_host()->
GetSiteInstance();
- // If this came from a swapped out RenderViewHost, we only allow the request
+ // If this came from a swapped out RenderFrameHost, we only allow the request
// if we are still in the same BrowsingInstance.
- if (render_frame_host->render_view_host()->IsSwappedOut() &&
+ // TODO(creis): Move this to RenderFrameProxyHost::OpenURL.
+ if (render_frame_host->is_swapped_out() &&
!render_frame_host->GetSiteInstance()->IsRelatedSiteInstance(
current_site_instance)) {
return;
@@ -563,10 +640,15 @@ void NavigatorImpl::RequestOpenURL(
// TODO(creis): Pass the redirect_chain into this method to support client
// redirects. http://crbug.com/311721.
std::vector<GURL> redirect_chain;
- RequestTransferURL(
- render_frame_host, url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
- disposition, GlobalRequestID(),
- should_replace_current_entry, user_gesture);
+ RequestTransferURL(render_frame_host,
+ url,
+ redirect_chain,
+ referrer,
+ ui::PAGE_TRANSITION_LINK,
+ disposition,
+ GlobalRequestID(),
+ should_replace_current_entry,
+ user_gesture);
}
void NavigatorImpl::RequestTransferURL(
@@ -574,7 +656,7 @@ void NavigatorImpl::RequestTransferURL(
const GURL& url,
const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
WindowOpenDisposition disposition,
const GlobalRequestID& transferred_global_request_id,
bool should_replace_current_entry,
@@ -589,7 +671,8 @@ void NavigatorImpl::RequestTransferURL(
}
int64 frame_tree_node_id = -1;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
frame_tree_node_id =
render_frame_host->frame_tree_node()->frame_tree_node_id();
}
@@ -607,7 +690,8 @@ void NavigatorImpl::RequestTransferURL(
// link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
// automatically generated suggestions). We don't override other types
// like TYPED because they have different implications (e.g., autocomplete).
- if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
+ if (ui::PageTransitionCoreTypeIs(
+ params.transition, ui::PAGE_TRANSITION_LINK))
params.transition =
GetRenderManager(render_frame_host)->web_ui()->
GetLinkTransitionType();
@@ -626,4 +710,216 @@ void NavigatorImpl::RequestTransferURL(
delegate_->RequestOpenURL(render_frame_host, params);
}
+// PlzNavigate
+void NavigatorImpl::OnBeginNavigation(
+ FrameTreeNode* frame_tree_node,
+ const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ DCHECK(frame_tree_node);
+
+ // TODO(clamy): In case of a renderer initiated navigation create a new
+ // NavigationRequest.
+ NavigationRequest* navigation_request =
+ navigation_request_map_.get(frame_tree_node->frame_tree_node_id());
+ DCHECK(navigation_request);
+
+ // Update the referrer with the one received from the renderer.
+ navigation_request->common_params().referrer = common_params.referrer;
+
+ scoped_ptr<NavigationRequestInfo> info(new NavigationRequestInfo(params));
+
+ info->first_party_for_cookies =
+ frame_tree_node->IsMainFrame()
+ ? navigation_request->common_params().url
+ : frame_tree_node->frame_tree()->root()->current_url();
+ info->is_main_frame = frame_tree_node->IsMainFrame();
+ info->parent_is_main_frame = !frame_tree_node->parent() ?
+ false : frame_tree_node->parent()->IsMainFrame();
+
+ // TODO(clamy): Inform the RenderFrameHostManager that a navigation is about
+ // to begin, so that it can speculatively spawn a new renderer if needed.
+
+ navigation_request->BeginNavigation(info.Pass(), params.request_body);
+}
+
+// PlzNavigate
+void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node,
+ ResourceResponse* response,
+ scoped_ptr<StreamHandle> body) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+
+ // HTTP 204 (No Content) and HTTP 205 (Reset Content) responses should not
+ // commit; they leave the frame showing the previous page.
+ if (response->head.headers.get() &&
+ (response->head.headers->response_code() == 204 ||
+ response->head.headers->response_code() == 205)) {
+ CancelNavigation(frame_tree_node);
+ return;
+ }
+
+ NavigationRequest* navigation_request =
+ navigation_request_map_.get(frame_tree_node->frame_tree_node_id());
+ DCHECK(navigation_request);
+
+ // Select an appropriate renderer to commit the navigation.
+ RenderFrameHostImpl* render_frame_host =
+ frame_tree_node->render_manager()->GetFrameHostForNavigation(
+ navigation_request->common_params().url,
+ navigation_request->common_params().transition);
+ CheckWebUIRendererDoesNotDisplayNormalURL(
+ render_frame_host, navigation_request->common_params().url);
+
+ render_frame_host->CommitNavigation(response, body.Pass(),
+ navigation_request->common_params(),
+ navigation_request->commit_params());
+}
+
+// PlzNavigate
+void NavigatorImpl::CancelNavigation(FrameTreeNode* frame_tree_node) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ navigation_request_map_.erase(frame_tree_node->frame_tree_node_id());
+}
+
+void NavigatorImpl::LogResourceRequestTime(
+ base::TimeTicks timestamp, const GURL& url) {
+ if (navigation_data_ && navigation_data_->url_ == url) {
+ navigation_data_->url_job_start_time_ = timestamp;
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToURLJobStart",
+ navigation_data_->url_job_start_time_ - navigation_data_->start_time_);
+ }
+}
+
+void NavigatorImpl::LogBeforeUnloadTime(
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time) {
+ // Only stores the beforeunload delay if we're tracking a browser initiated
+ // navigation and it happened later than the navigation request.
+ if (navigation_data_ &&
+ renderer_before_unload_start_time > navigation_data_->start_time_) {
+ navigation_data_->before_unload_delay_ =
+ renderer_before_unload_end_time - renderer_before_unload_start_time;
+ }
+}
+
+void NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url) {
+ int enabled_bindings =
+ render_frame_host->render_view_host()->GetEnabledBindings();
+ bool is_allowed_in_web_ui_renderer =
+ WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
+ controller_->GetBrowserContext(), url);
+ if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
+ !is_allowed_in_web_ui_renderer) {
+ // Log the URL to help us diagnose any future failures of this CHECK.
+ GetContentClient()->SetActiveURL(url);
+ CHECK(0);
+ }
+}
+
+// PlzNavigate
+bool NavigatorImpl::RequestNavigation(
+ FrameTreeNode* frame_tree_node,
+ const NavigationEntryImpl& entry,
+ NavigationController::ReloadType reload_type,
+ base::TimeTicks navigation_start) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ DCHECK(frame_tree_node);
+ int64 frame_tree_node_id = frame_tree_node->frame_tree_node_id();
+ FrameMsg_Navigate_Type::Value navigation_type =
+ GetNavigationType(controller_->GetBrowserContext(), entry, reload_type);
+ scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest(
+ frame_tree_node,
+ CommonNavigationParams(entry.GetURL(),
+ entry.GetReferrer(),
+ entry.GetTransitionType(),
+ navigation_type,
+ !entry.IsViewSourceMode()),
+ CommitNavigationParams(entry.GetPageState(),
+ entry.GetIsOverridingUserAgent(),
+ navigation_start)));
+ RequestNavigationParams request_params(entry.GetHasPostData(),
+ entry.extra_headers(),
+ entry.GetBrowserInitiatedPostData());
+ // TODO(clamy): Check if navigations are blocked and if so store the
+ // parameters.
+
+ // If there is an ongoing request, replace it.
+ navigation_request_map_.set(frame_tree_node_id, navigation_request.Pass());
+
+ if (frame_tree_node->current_frame_host()->IsRenderFrameLive()) {
+ frame_tree_node->current_frame_host()->Send(new FrameMsg_RequestNavigation(
+ frame_tree_node->current_frame_host()->GetRoutingID(),
+ navigation_request_map_.get(frame_tree_node_id)->common_params(),
+ request_params));
+ return true;
+ }
+
+ // The navigation request is sent directly to the IO thread.
+ OnBeginNavigation(
+ frame_tree_node,
+ MakeDefaultBeginNavigation(request_params, navigation_type),
+ navigation_request_map_.get(frame_tree_node_id)->common_params());
+ return true;
+}
+
+void NavigatorImpl::RecordNavigationMetrics(
+ const LoadCommittedDetails& details,
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ SiteInstance* site_instance) {
+ DCHECK(site_instance->HasProcess());
+
+ if (!details.is_in_page)
+ RecordAction(base::UserMetricsAction("FrameLoad"));
+
+ if (!details.is_main_frame || !navigation_data_ ||
+ navigation_data_->url_ != params.original_request_url) {
+ return;
+ }
+
+ base::TimeDelta time_to_commit =
+ base::TimeTicks::Now() - navigation_data_->start_time_;
+ UMA_HISTOGRAM_TIMES("Navigation.TimeToCommit", time_to_commit);
+
+ time_to_commit -= navigation_data_->before_unload_delay_;
+ base::TimeDelta time_to_network = navigation_data_->url_job_start_time_ -
+ navigation_data_->start_time_ -
+ navigation_data_->before_unload_delay_;
+ if (navigation_data_->is_restoring_from_last_session_) {
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToCommit_SessionRestored_BeforeUnloadDiscounted",
+ time_to_commit);
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToURLJobStart_SessionRestored_BeforeUnloadDiscounted",
+ time_to_network);
+ navigation_data_.reset();
+ return;
+ }
+ bool navigation_created_new_renderer_process =
+ site_instance->GetProcess()->GetInitTimeForNavigationMetrics() >
+ navigation_data_->start_time_;
+ if (navigation_created_new_renderer_process) {
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToCommit_NewRenderer_BeforeUnloadDiscounted",
+ time_to_commit);
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToURLJobStart_NewRenderer_BeforeUnloadDiscounted",
+ time_to_network);
+ } else {
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToCommit_ExistingRenderer_BeforeUnloadDiscounted",
+ time_to_commit);
+ UMA_HISTOGRAM_TIMES(
+ "Navigation.TimeToURLJobStart_ExistingRenderer_BeforeUnloadDiscounted",
+ time_to_network);
+ }
+ navigation_data_.reset();
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index 1aa9a609c09..e142b3fd1ff 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -5,16 +5,28 @@
#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_
#define CONTENT_BROWSER_FRAME_HOST_NAVIGATOR_IMPL_H_
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "base/tuple.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+class GURL;
+struct FrameMsg_Navigate_Params;
namespace content {
class NavigationControllerImpl;
class NavigatorDelegate;
+class NavigatorTest;
struct LoadCommittedDetails;
+struct CommitNavigationParams;
+struct CommonNavigationParams;
+struct RequestNavigationParams;
// This class is an implementation of Navigator, responsible for managing
// navigations in regular browser tabs.
@@ -24,51 +36,58 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
NavigatorDelegate* delegate);
// Navigator implementation.
- virtual NavigationController* GetController() OVERRIDE;
- virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
- int parent_routing_id,
- const GURL& url) OVERRIDE;
- virtual void DidFailProvisionalLoadWithError(
+ NavigationController* GetController() override;
+ void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ bool is_transition_navigation) override;
+ void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params)
- OVERRIDE;
- virtual void DidFailLoadWithError(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- int error_code,
- const base::string16& error_description) OVERRIDE;
- virtual void DidRedirectProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- int32 page_id,
- const GURL& source_url,
- const GURL& target_url) OVERRIDE;
- virtual void DidNavigate(
- RenderFrameHostImpl* render_frame_host,
- const FrameHostMsg_DidCommitProvisionalLoad_Params&
- input_params) OVERRIDE;
- virtual bool NavigateToPendingEntry(
- RenderFrameHostImpl* render_frame_host,
- NavigationController::ReloadType reload_type) OVERRIDE;
- virtual base::TimeTicks GetCurrentLoadStart() OVERRIDE;
- virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- bool should_replace_current_entry,
- bool user_gesture) OVERRIDE;
- virtual void RequestTransferURL(
+ override;
+ void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description) override;
+ void DidNavigate(RenderFrameHostImpl* render_frame_host,
+ const FrameHostMsg_DidCommitProvisionalLoad_Params&
+ input_params) override;
+ bool NavigateToPendingEntry(
RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const Referrer& referrer,
- PageTransition page_transition,
- WindowOpenDisposition disposition,
- const GlobalRequestID& transferred_global_request_id,
- bool should_replace_current_entry,
- bool user_gesture) OVERRIDE;
+ NavigationController::ReloadType reload_type) override;
+ void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ bool should_replace_current_entry,
+ bool user_gesture) override;
+ void RequestTransferURL(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const std::vector<GURL>& redirect_chain,
+ const Referrer& referrer,
+ ui::PageTransition page_transition,
+ WindowOpenDisposition disposition,
+ const GlobalRequestID& transferred_global_request_id,
+ bool should_replace_current_entry,
+ bool user_gesture) override;
+ void OnBeginNavigation(FrameTreeNode* frame_tree_node,
+ const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params) override;
+ void CommitNavigation(FrameTreeNode* frame_tree_node,
+ ResourceResponse* response,
+ scoped_ptr<StreamHandle> body) override;
+ void LogResourceRequestTime(base::TimeTicks timestamp,
+ const GURL& url) override;
+ void LogBeforeUnloadTime(
+ const base::TimeTicks& renderer_before_unload_start_time,
+ const base::TimeTicks& renderer_before_unload_end_time) override;
+ void CancelNavigation(FrameTreeNode* frame_tree_node) override;
private:
- virtual ~NavigatorImpl() {}
+ // Holds data used to track browser side navigation metrics.
+ struct NavigationMetricsData;
+
+ friend class NavigatorTest;
+ ~NavigatorImpl() override;
// Navigates to the given entry, which must be the pending entry. Private
// because all callers should use NavigateToPendingEntry.
@@ -79,6 +98,23 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
bool ShouldAssignSiteForURL(const GURL& url);
+ void CheckWebUIRendererDoesNotDisplayNormalURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url);
+
+ // PlzNavigate: sends a RequestNavigation IPC to the renderer to ask it to
+ // navigate. If no live renderer is present, then the navigation request will
+ // be sent directly to the ResourceDispatcherHost.
+ bool RequestNavigation(FrameTreeNode* frame_tree_node,
+ const NavigationEntryImpl& entry,
+ NavigationController::ReloadType reload_type,
+ base::TimeTicks navigation_start);
+
+ void RecordNavigationMetrics(
+ const LoadCommittedDetails& details,
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ SiteInstance* site_instance);
+
// The NavigationController that will keep track of session history for all
// RenderFrameHost objects using this NavigatorImpl.
// TODO(nasko): Move ownership of the NavigationController from
@@ -89,8 +125,12 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
// events. Can be NULL in tests.
NavigatorDelegate* delegate_;
- // System time at which the current load was started.
- base::TimeTicks current_load_start_;
+ scoped_ptr<NavigatorImpl::NavigationMetricsData> navigation_data_;
+
+ // PlzNavigate: used to track the various ongoing NavigationRequests in the
+ // different FrameTreeNodes, based on the frame_tree_node_id.
+ typedef base::ScopedPtrHashMap<int64, NavigationRequest> NavigationRequestMap;
+ NavigationRequestMap navigation_request_map_;
DISALLOW_COPY_AND_ASSIGN(NavigatorImpl);
};
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
new file mode 100644
index 00000000000..37a0f243d6d
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -0,0 +1,480 @@
+// Copyright 2014 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/command_line.h"
+#include "base/guid.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/test/histogram_tester.h"
+#include "base/time/time.h"
+#include "content/browser/frame_host/navigation_controller_impl.h"
+#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigation_request.h"
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/frame_host/navigator.h"
+#include "content/browser/frame_host/navigator_impl.h"
+#include "content/browser/frame_host/render_frame_host_manager.h"
+#include "content/browser/loader/navigation_url_loader.h"
+#include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/browser/loader/navigation_url_loader_factory.h"
+#include "content/browser/site_instance_impl.h"
+#include "content/browser/streams/stream.h"
+#include "content/browser/streams/stream_registry.h"
+#include "content/common/navigation_params.h"
+#include "content/public/browser/stream_handle.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/common/url_utils.h"
+#include "content/test/test_render_frame_host.h"
+#include "content/test/test_web_contents.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/redirect_info.h"
+#include "ui/base/page_transition_types.h"
+#include "url/url_constants.h"
+
+namespace content {
+
+namespace {
+
+class TestNavigationURLLoader
+ : public NavigationURLLoader,
+ public base::SupportsWeakPtr<TestNavigationURLLoader> {
+ public:
+ TestNavigationURLLoader(const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ NavigationURLLoaderDelegate* delegate)
+ : common_params_(common_params),
+ request_info_(request_info.Pass()),
+ delegate_(delegate),
+ redirect_count_(0) {
+ }
+
+ // NavigationURLLoader implementation.
+ void FollowRedirect() override { redirect_count_++; }
+
+ const CommonNavigationParams& common_params() const { return common_params_; }
+ NavigationRequestInfo* request_info() const { return request_info_.get(); }
+
+ void CallOnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response) {
+ delegate_->OnRequestRedirected(redirect_info, response);
+ }
+
+ void CallOnResponseStarted(
+ const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body) {
+ delegate_->OnResponseStarted(response, body.Pass());
+ }
+
+ int redirect_count() { return redirect_count_; }
+
+ private:
+ CommonNavigationParams common_params_;
+ scoped_ptr<NavigationRequestInfo> request_info_;
+ NavigationURLLoaderDelegate* delegate_;
+ int redirect_count_;
+};
+
+class TestNavigationURLLoaderFactory : public NavigationURLLoaderFactory {
+ public:
+ // NavigationURLLoaderFactory implementation.
+ scoped_ptr<NavigationURLLoader> CreateLoader(
+ BrowserContext* browser_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body,
+ NavigationURLLoaderDelegate* delegate) override {
+ return scoped_ptr<NavigationURLLoader>(new TestNavigationURLLoader(
+ common_params, request_info.Pass(), delegate));
+ }
+};
+
+} // namespace
+
+class NavigatorTest : public RenderViewHostImplTestHarness {
+ public:
+ NavigatorTest() : stream_registry_(new StreamRegistry) {}
+
+ void SetUp() override {
+ RenderViewHostImplTestHarness::SetUp();
+ loader_factory_.reset(new TestNavigationURLLoaderFactory);
+ NavigationURLLoader::SetFactoryForTesting(loader_factory_.get());
+ }
+
+ void TearDown() override {
+ NavigationURLLoader::SetFactoryForTesting(nullptr);
+ loader_factory_.reset();
+ RenderViewHostImplTestHarness::TearDown();
+ }
+
+ NavigationRequest* GetNavigationRequestForFrameTreeNode(
+ FrameTreeNode* frame_tree_node) const {
+ NavigatorImpl* navigator =
+ static_cast<NavigatorImpl*>(frame_tree_node->navigator());
+ return navigator->navigation_request_map_.get(
+ frame_tree_node->frame_tree_node_id());
+ }
+
+ TestNavigationURLLoader* GetLoaderForNavigationRequest(
+ NavigationRequest* request) const {
+ return static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
+ }
+
+ void EnableBrowserSideNavigation() {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBrowserSideNavigation);
+ }
+
+ void SendRequestNavigation(FrameTreeNode* node,
+ const GURL& url) {
+ SendRequestNavigationWithParameters(
+ node, url, Referrer(), ui::PAGE_TRANSITION_LINK,
+ NavigationController::NO_RELOAD);
+ }
+
+ void SendRequestNavigationWithParameters(
+ FrameTreeNode* node,
+ const GURL& url,
+ const Referrer& referrer,
+ ui::PageTransition transition_type,
+ NavigationController::ReloadType reload_type) {
+ scoped_ptr<NavigationEntryImpl> entry(
+ NavigationEntryImpl::FromNavigationEntry(
+ NavigationController::CreateNavigationEntry(
+ url,
+ referrer,
+ transition_type,
+ false,
+ std::string(),
+ controller().GetBrowserContext())));
+ static_cast<NavigatorImpl*>(node->navigator())->RequestNavigation(
+ node, *entry, reload_type, base::TimeTicks::Now());
+ }
+
+ scoped_ptr<StreamHandle> MakeEmptyStream() {
+ GURL url(std::string(url::kBlobScheme) + "://" + base::GenerateGUID());
+ scoped_refptr<Stream> stream(new Stream(stream_registry_.get(), NULL, url));
+ stream->Finalize();
+ return stream->CreateHandle();
+ }
+
+ private:
+ scoped_ptr<StreamRegistry> stream_registry_;
+ scoped_ptr<TestNavigationURLLoaderFactory> loader_factory_;
+};
+
+// PlzNavigate: Test that a proper NavigationRequest is created by
+// BeginNavigation.
+// Note that all PlzNavigate methods on the browser side require the use of the
+// flag kEnableBrowserSideNavigation.
+TEST_F(NavigatorTest, BrowserSideNavigationBeginNavigation) {
+ const GURL kUrl1("http://www.google.com/");
+ const GURL kUrl2("http://www.chromium.org/");
+ const GURL kUrl3("http://www.gmail.com/");
+
+ contents()->NavigateAndCommit(kUrl1);
+
+ EnableBrowserSideNavigation();
+
+ // Add a subframe.
+ FrameTreeNode* root = contents()->GetFrameTree()->root();
+ TestRenderFrameHost* subframe_rfh = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->AddFrame(
+ root, root->current_frame_host()->GetProcess()->GetID(), 14,
+ "Child"));
+ EXPECT_TRUE(subframe_rfh);
+
+ FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
+ SendRequestNavigation(subframe_rfh->frame_tree_node(), kUrl2);
+ // There is no previous renderer in the subframe, so BeginNavigation is
+ // handled already.
+ NavigationRequest* subframe_request =
+ GetNavigationRequestForFrameTreeNode(subframe_node);
+ TestNavigationURLLoader* subframe_loader =
+ GetLoaderForNavigationRequest(subframe_request);
+ ASSERT_TRUE(subframe_request);
+ EXPECT_EQ(kUrl2, subframe_request->common_params().url);
+ EXPECT_EQ(kUrl2, subframe_loader->common_params().url);
+ // First party for cookies url should be that of the main frame.
+ EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies);
+ EXPECT_FALSE(subframe_loader->request_info()->is_main_frame);
+ EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame);
+
+ SendRequestNavigation(root, kUrl3);
+ // Simulate a BeginNavigation IPC on the main frame.
+ contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl3);
+ NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(root);
+ TestNavigationURLLoader* main_loader =
+ GetLoaderForNavigationRequest(main_request);
+ ASSERT_TRUE(main_request);
+ EXPECT_EQ(kUrl3, main_request->common_params().url);
+ EXPECT_EQ(kUrl3, main_loader->common_params().url);
+ EXPECT_EQ(kUrl3, main_loader->request_info()->first_party_for_cookies);
+ EXPECT_TRUE(main_loader->request_info()->is_main_frame);
+ EXPECT_FALSE(main_loader->request_info()->parent_is_main_frame);
+}
+
+// PlzNavigate: Test that RequestNavigation creates a NavigationRequest and that
+// RenderFrameHost is not modified when the navigation commits.
+TEST_F(NavigatorTest, BrowserSideNavigationRequestNavigationNoLiveRenderer) {
+ const GURL kUrl("http://www.google.com/");
+
+ EnableBrowserSideNavigation();
+ EXPECT_FALSE(main_test_rfh()->render_view_host()->IsRenderViewLive());
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+ SendRequestNavigation(node, kUrl);
+ NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
+ // A NavigationRequest should have been generated.
+ EXPECT_TRUE(main_request != NULL);
+ RenderFrameHostImpl* rfh = main_test_rfh();
+
+ // Now return the response without any redirects. This will cause the
+ // navigation to commit at the same URL.
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
+ response, MakeEmptyStream());
+ main_request = GetNavigationRequestForFrameTreeNode(node);
+
+ // The main RFH should not have been changed, and the renderer should have
+ // been initialized.
+ EXPECT_EQ(rfh, main_test_rfh());
+ EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
+ EXPECT_TRUE(main_test_rfh()->render_view_host()->IsRenderViewLive());
+}
+
+// PlzNavigate: Test that commiting an HTTP 204 or HTTP 205 response cancels the
+// navigation.
+TEST_F(NavigatorTest, BrowserSideNavigationNoContent) {
+ const GURL kUrl1("http://www.chromium.org/");
+ const GURL kUrl2("http://www.google.com/");
+
+ // Load a URL.
+ contents()->NavigateAndCommit(kUrl1);
+ RenderFrameHostImpl* rfh = main_test_rfh();
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh->rfh_state());
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+
+ EnableBrowserSideNavigation();
+
+ // Navigate to a different site.
+ SendRequestNavigation(node, kUrl2);
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl2);
+ NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(main_request);
+
+ // Commit an HTTP 204 response.
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+ const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0";
+ response->head.headers = new net::HttpResponseHeaders(
+ std::string(kNoContentHeaders, arraysize(kNoContentHeaders)));
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
+ response, MakeEmptyStream());
+
+ // There should be no pending RenderFrameHost; the navigation was aborted.
+ EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
+ EXPECT_FALSE(node->render_manager()->pending_frame_host());
+
+ // Now, repeat the test with 205 Reset Content.
+
+ // Navigate to a different site again.
+ SendRequestNavigation(node, kUrl2);
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl2);
+ main_request = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(main_request);
+
+ // Commit an HTTP 205 response.
+ response = new ResourceResponse;
+ const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0";
+ response->head.headers = new net::HttpResponseHeaders(
+ std::string(kResetContentHeaders, arraysize(kResetContentHeaders)));
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
+ response, MakeEmptyStream());
+
+ // There should be no pending RenderFrameHost; the navigation was aborted.
+ EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node));
+ EXPECT_FALSE(node->render_manager()->pending_frame_host());
+}
+
+// PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
+// site navigation.
+TEST_F(NavigatorTest, BrowserSideNavigationCrossSiteNavigation) {
+ const GURL kUrl1("http://www.chromium.org/");
+ const GURL kUrl2("http://www.google.com/");
+
+ contents()->NavigateAndCommit(kUrl1);
+ RenderFrameHostImpl* rfh = main_test_rfh();
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh->rfh_state());
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+
+ EnableBrowserSideNavigation();
+
+ // Navigate to a different site.
+ SendRequestNavigation(node, kUrl2);
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl2);
+ NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(main_request);
+
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
+ response, MakeEmptyStream());
+ RenderFrameHostImpl* pending_rfh =
+ node->render_manager()->pending_frame_host();
+ ASSERT_TRUE(pending_rfh);
+ EXPECT_NE(pending_rfh, rfh);
+ EXPECT_TRUE(pending_rfh->IsRenderFrameLive());
+ EXPECT_TRUE(pending_rfh->render_view_host()->IsRenderViewLive());
+}
+
+// PlzNavigate: Test that redirects are followed.
+TEST_F(NavigatorTest, BrowserSideNavigationRedirectCrossSite) {
+ const GURL kUrl1("http://www.chromium.org/");
+ const GURL kUrl2("http://www.google.com/");
+
+ contents()->NavigateAndCommit(kUrl1);
+ RenderFrameHostImpl* rfh = main_test_rfh();
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh->rfh_state());
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+
+ EnableBrowserSideNavigation();
+
+ // Navigate to a URL on the same site.
+ SendRequestNavigation(node, kUrl1);
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl1);
+ NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(main_request);
+
+ // It then redirects to another site.
+ net::RedirectInfo redirect_info;
+ redirect_info.status_code = 302;
+ redirect_info.new_method = "GET";
+ redirect_info.new_url = kUrl2;
+ redirect_info.new_first_party_for_cookies = kUrl2;
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+ GetLoaderForNavigationRequest(main_request)->CallOnRequestRedirected(
+ redirect_info, response);
+
+ // The redirect should have been followed.
+ EXPECT_EQ(1, GetLoaderForNavigationRequest(main_request)->redirect_count());
+
+ // Then it commits.
+ response = new ResourceResponse;
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
+ response, MakeEmptyStream());
+ RenderFrameHostImpl* pending_rfh =
+ node->render_manager()->pending_frame_host();
+ ASSERT_TRUE(pending_rfh);
+ EXPECT_NE(pending_rfh, rfh);
+ EXPECT_TRUE(pending_rfh->IsRenderFrameLive());
+ EXPECT_TRUE(pending_rfh->render_view_host()->IsRenderViewLive());
+}
+
+// PlzNavigate: Test that a navigation is cancelled if another request has been
+// issued in the meantime.
+TEST_F(NavigatorTest, BrowserSideNavigationReplacePendingNavigation) {
+ const GURL kUrl0("http://www.wikipedia.org/");
+ const GURL kUrl0_site = SiteInstance::GetSiteForURL(browser_context(), kUrl0);
+ const GURL kUrl1("http://www.chromium.org/");
+ const GURL kUrl2("http://www.google.com/");
+ const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2);
+
+ // Initialization.
+ contents()->NavigateAndCommit(kUrl0);
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+ EnableBrowserSideNavigation();
+ EXPECT_EQ(kUrl0_site, main_test_rfh()->GetSiteInstance()->GetSiteURL());
+
+ // Request navigation to the 1st URL.
+ SendRequestNavigation(node, kUrl1);
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl1);
+ NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(request1);
+ EXPECT_EQ(kUrl1, request1->common_params().url);
+ base::WeakPtr<TestNavigationURLLoader> loader1 =
+ GetLoaderForNavigationRequest(request1)->AsWeakPtr();
+
+ // Request navigation to the 2nd URL; the NavigationRequest must have been
+ // replaced by a new one with a different URL.
+ SendRequestNavigation(node, kUrl2);
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl2);
+ NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(request2);
+ EXPECT_EQ(kUrl2, request2->common_params().url);
+
+ // Confirm that the first loader got destroyed.
+ EXPECT_FALSE(loader1);
+
+ // Confirm that the commit corresponds to the new request.
+ scoped_refptr<ResourceResponse> response(new ResourceResponse);
+ GetLoaderForNavigationRequest(request2)->CallOnResponseStarted(
+ response, MakeEmptyStream());
+ RenderFrameHostImpl* pending_rfh =
+ node->render_manager()->pending_frame_host();
+ ASSERT_TRUE(pending_rfh);
+ EXPECT_EQ(kUrl2_site, pending_rfh->GetSiteInstance()->GetSiteURL());
+}
+
+// PlzNavigate: Tests that the navigation histograms are correctly tracked both
+// when PlzNavigate is enabled and disabled, and also ignores in-tab renderer
+// initiated navigation for the non-enabled case.
+// Note: the related histogram, Navigation.TimeToURLJobStart, cannot be tracked
+// by this test as the IO thread is not running.
+TEST_F(NavigatorTest, BrowserSideNavigationHistogramTest) {
+ const GURL kUrl0("http://www.google.com/");
+ const GURL kUrl1("http://www.chromium.org/");
+ base::HistogramTester histo_tester;
+
+ // Performs a "normal" non-PlzNavigate navigation
+ contents()->NavigateAndCommit(kUrl0);
+ histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 1);
+
+ // Performs an in-tab renderer initiated navigation
+ int32 new_page_id = 1 + contents()->GetMaxPageIDForSiteInstance(
+ main_test_rfh()->GetSiteInstance());
+ main_test_rfh()->SendNavigate(new_page_id, kUrl0);
+ histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 1);
+
+ // Performs a PlzNavigate navigation
+ EnableBrowserSideNavigation();
+ contents()->NavigateAndCommit(kUrl1);
+ histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 2);
+}
+
+// PlzNavigate: Test that a reload navigation is properly signaled to the
+// renderer when the navigation can commit.
+TEST_F(NavigatorTest, BrowserSideNavigationReload) {
+ const GURL kUrl("http://www.google.com/");
+ contents()->NavigateAndCommit(kUrl);
+
+ EnableBrowserSideNavigation();
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node();
+ SendRequestNavigationWithParameters(
+ node, kUrl, Referrer(), ui::PAGE_TRANSITION_LINK,
+ NavigationController::RELOAD);
+ contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl);
+ // A NavigationRequest should have been generated.
+ NavigationRequest* main_request =
+ GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(main_request != NULL);
+ EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD,
+ main_request->common_params().navigation_type);
+ int page_id = contents()->GetMaxPageIDForSiteInstance(
+ main_test_rfh()->GetSiteInstance()) + 1;
+ main_test_rfh()->SendNavigate(page_id, kUrl);
+
+ // Now do a shift+reload.
+ SendRequestNavigationWithParameters(
+ node, kUrl, Referrer(), ui::PAGE_TRANSITION_LINK,
+ NavigationController::RELOAD_IGNORING_CACHE);
+ contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl);
+ // A NavigationRequest should have been generated.
+ main_request = GetNavigationRequestForFrameTreeNode(node);
+ ASSERT_TRUE(main_request != NULL);
+ EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
+ main_request->common_params().navigation_type);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/popup_menu_helper_mac.h b/chromium/content/browser/frame_host/popup_menu_helper_mac.h
new file mode 100644
index 00000000000..e92aa10340f
--- /dev/null
+++ b/chromium/content/browser/frame_host/popup_menu_helper_mac.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2012 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 CONTENT_BROWSER_FRAME_HOST_POPUP_MENU_HELPER_MAC_H_
+#define CONTENT_BROWSER_FRAME_HOST_POPUP_MENU_HELPER_MAC_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "ui/gfx/rect.h"
+
+#ifdef __OBJC__
+@class WebMenuRunner;
+#else
+class WebMenuRunner;
+#endif
+
+namespace content {
+
+class RenderFrameHost;
+class RenderFrameHostImpl;
+class RenderWidgetHostViewMac;
+struct MenuItem;
+
+class PopupMenuHelper : public NotificationObserver {
+ public:
+ // Creates a PopupMenuHelper that will notify |render_frame_host| when a user
+ // selects or cancels the popup.
+ explicit PopupMenuHelper(RenderFrameHost* render_frame_host);
+ void Hide();
+
+ // Shows the popup menu and notifies the RenderFrameHost of the selection/
+ // cancellation. This call is blocking.
+ void ShowPopupMenu(const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection);
+
+ // Immediately return from ShowPopupMenu.
+ CONTENT_EXPORT static void DontShowPopupMenuForTesting();
+
+ protected:
+ virtual RenderWidgetHostViewMac* GetRenderWidgetHostView() const;
+
+ // NotificationObserver implementation:
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
+
+ NotificationRegistrar notification_registrar_;
+ RenderFrameHostImpl* render_frame_host_;
+ WebMenuRunner* menu_runner_;
+ bool popup_was_hidden_;
+
+ DISALLOW_COPY_AND_ASSIGN(PopupMenuHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_FRAME_HOST_POPUP_MENU_HELPER_MAC_H_
diff --git a/chromium/content/browser/frame_host/popup_menu_helper_mac.mm b/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
new file mode 100644
index 00000000000..eac8f7c3b7a
--- /dev/null
+++ b/chromium/content/browser/frame_host/popup_menu_helper_mac.mm
@@ -0,0 +1,128 @@
+// Copyright (c) 2012 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.
+
+#import <Carbon/Carbon.h>
+
+#include "content/browser/frame_host/popup_menu_helper_mac.h"
+
+#include "base/mac/scoped_nsobject.h"
+#import "base/mac/scoped_sending_event.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_mac.h"
+#include "content/browser/renderer_host/webmenurunner_mac.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/notification_types.h"
+#import "ui/base/cocoa/base_view.h"
+
+namespace content {
+
+namespace {
+
+bool g_allow_showing_popup_menus = true;
+
+} // namespace
+
+PopupMenuHelper::PopupMenuHelper(RenderFrameHost* render_frame_host)
+ : render_frame_host_(static_cast<RenderFrameHostImpl*>(render_frame_host)),
+ menu_runner_(nil),
+ popup_was_hidden_(false) {
+ notification_registrar_.Add(
+ this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
+ Source<RenderWidgetHost>(render_frame_host->GetRenderViewHost()));
+}
+
+void PopupMenuHelper::ShowPopupMenu(
+ const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection) {
+ // Only single selection list boxes show a popup on Mac.
+ DCHECK(!allow_multiple_selection);
+
+ if (!g_allow_showing_popup_menus)
+ return;
+
+ // Retain the Cocoa view for the duration of the pop-up so that it can't be
+ // dealloced if my Destroy() method is called while the pop-up's up (which
+ // would in turn delete me, causing a crash once the -runMenuInView
+ // call returns. That's what was happening in <http://crbug.com/33250>).
+ RenderWidgetHostViewMac* rwhvm =
+ static_cast<RenderWidgetHostViewMac*>(GetRenderWidgetHostView());
+ base::scoped_nsobject<RenderWidgetHostViewCocoa> cocoa_view(
+ [rwhvm->cocoa_view() retain]);
+
+ // Display the menu.
+ menu_runner_ = [[WebMenuRunner alloc] initWithItems:items
+ fontSize:item_font_size
+ rightAligned:right_aligned];
+
+ {
+ // Make sure events can be pumped while the menu is up.
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+
+ // One of the events that could be pumped is |window.close()|.
+ // User-initiated event-tracking loops protect against this by
+ // setting flags in -[CrApplication sendEvent:], but since
+ // web-content menus are initiated by IPC message the setup has to
+ // be done manually.
+ base::mac::ScopedSendingEvent sending_event_scoper;
+
+ // Now run a SYNCHRONOUS NESTED EVENT LOOP until the pop-up is finished.
+ [menu_runner_ runMenuInView:cocoa_view
+ withBounds:[cocoa_view flipRectToNSRect:bounds]
+ initialIndex:selected_item];
+ }
+
+ if (!render_frame_host_) {
+ // Bad news, the RenderFrameHost got deleted while we were off running the
+ // menu. Nothing to do.
+ [menu_runner_ release];
+ menu_runner_ = nil;
+ return;
+ }
+
+ if (!popup_was_hidden_) {
+ if ([menu_runner_ menuItemWasChosen]) {
+ render_frame_host_->DidSelectPopupMenuItem(
+ [menu_runner_ indexOfSelectedItem]);
+ } else {
+ render_frame_host_->DidCancelPopupMenu();
+ }
+ }
+ [menu_runner_ release];
+ menu_runner_ = nil;
+}
+
+void PopupMenuHelper::Hide() {
+ if (menu_runner_)
+ [menu_runner_ hide];
+ popup_was_hidden_ = true;
+}
+
+// static
+void PopupMenuHelper::DontShowPopupMenuForTesting() {
+ g_allow_showing_popup_menus = false;
+}
+
+RenderWidgetHostViewMac* PopupMenuHelper::GetRenderWidgetHostView() const {
+ return static_cast<RenderWidgetHostViewMac*>(
+ render_frame_host_->GetRenderViewHost()->GetView());
+}
+
+void PopupMenuHelper::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED);
+ DCHECK_EQ(Source<RenderWidgetHost>(source).ptr(),
+ render_frame_host_->GetRenderViewHost());
+ render_frame_host_ = NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.cc b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
index 8e424ead131..a83715dece8 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -4,8 +4,10 @@
#include <stddef.h>
+#include "base/callback.h"
#include "base/strings/string16.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "ui/gfx/native_widget_types.h"
#include "url/gurl.h"
namespace content {
@@ -20,6 +22,10 @@ const GURL& RenderFrameHostDelegate::GetMainFrameLastCommittedURL() const {
return GURL::EmptyGURL();
}
+bool RenderFrameHostDelegate::WillHandleDeferAfterResponseStarted() {
+ return false;
+}
+
bool RenderFrameHostDelegate::AddMessageToConsole(
int32 level, const base::string16& message, int32 line_no,
const base::string16& source_id) {
@@ -30,4 +36,43 @@ WebContents* RenderFrameHostDelegate::GetAsWebContents() {
return NULL;
}
+void RenderFrameHostDelegate::RequestMediaAccessPermission(
+ const MediaStreamRequest& request,
+ const MediaResponseCallback& callback) {
+ LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: "
+ << "Not supported.";
+ callback.Run(MediaStreamDevices(),
+ MEDIA_DEVICE_NOT_SUPPORTED,
+ scoped_ptr<MediaStreamUI>());
+}
+
+bool RenderFrameHostDelegate::CheckMediaAccessPermission(
+ const GURL& security_origin,
+ MediaStreamType type) {
+ LOG(ERROR) << "RenderFrameHostDelegate::CheckMediaAccessPermission: "
+ << "Not supported.";
+ return false;
+}
+
+AccessibilityMode RenderFrameHostDelegate::GetAccessibilityMode() const {
+ return AccessibilityModeOff;
+}
+
+RenderFrameHost* RenderFrameHostDelegate::GetGuestByInstanceID(
+ int browser_plugin_instance_id) {
+ return NULL;
+}
+
+GeolocationServiceContext*
+RenderFrameHostDelegate::GetGeolocationServiceContext() {
+ return NULL;
+}
+
+#if defined(OS_WIN)
+gfx::NativeViewAccessible
+ RenderFrameHostDelegate::GetParentNativeViewAccessible() {
+ return NULL;
+}
+#endif // defined(OS_WIN)
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
index b4db5d4c9c9..6c22d94abf2 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -5,10 +5,19 @@
#ifndef CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_
#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_DELEGATE_H_
+#include <vector>
+
#include "base/basictypes.h"
#include "base/i18n/rtl.h"
#include "content/common/content_export.h"
+#include "content/common/frame_message_enums.h"
#include "content/public/common/javascript_message_type.h"
+#include "content/public/common/media_stream_request.h"
+#include "net/http/http_response_headers.h"
+
+#if defined(OS_WIN)
+#include "ui/gfx/native_widget_types.h"
+#endif
class GURL;
@@ -17,9 +26,12 @@ class Message;
}
namespace content {
+class GeolocationServiceContext;
class RenderFrameHost;
class WebContents;
+struct AXEventNotificationDetails;
struct ContextMenuParams;
+struct TransitionLayerData;
// An interface implemented by an object interested in knowing about the state
// of the RenderFrameHost.
@@ -55,6 +67,14 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// The RenderFrameHost has been swapped out.
virtual void SwappedOut(RenderFrameHost* render_frame_host) {}
+ // Notification that the navigation on the main frame is blocked waiting
+ // for transition to occur.
+ virtual void DidDeferAfterResponseStarted(
+ const TransitionLayerData& transition_data) {}
+
+ // Used to query whether the navigation transition will be handled.
+ virtual bool WillHandleDeferAfterResponseStarted();
+
// Notification that a worker process has crashed.
virtual void WorkerCrashed(RenderFrameHost* render_frame_host) {}
@@ -104,6 +124,38 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// not a WebContents, returns NULL.
virtual WebContents* GetAsWebContents();
+ // The render frame has requested access to media devices listed in
+ // |request|, and the client should grant or deny that permission by
+ // calling |callback|.
+ virtual void RequestMediaAccessPermission(
+ const MediaStreamRequest& request,
+ const MediaResponseCallback& callback);
+
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual bool CheckMediaAccessPermission(const GURL& security_origin,
+ MediaStreamType type);
+
+ // Get the accessibility mode for the WebContents that owns this frame.
+ virtual AccessibilityMode GetAccessibilityMode() const;
+
+ // Invoked when an accessibility event is received from the renderer.
+ virtual void AccessibilityEventReceived(
+ const std::vector<AXEventNotificationDetails>& details) {}
+
+ // Find a guest RenderFrameHost by its browser plugin instance id.
+ virtual RenderFrameHost* GetGuestByInstanceID(
+ int browser_plugin_instance_id);
+
+ // Gets the GeolocationServiceContext associated with this delegate.
+ virtual GeolocationServiceContext* GetGeolocationServiceContext();
+
+#if defined(OS_WIN)
+ // Returns the frame's parent's NativeViewAccessible.
+ virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
+#endif
+
protected:
virtual ~RenderFrameHostDelegate() {}
};
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.cc b/chromium/content/browser/frame_host/render_frame_host_impl.cc
index 397fd915ea4..b7941077c5e 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -5,43 +5,76 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
+#include "base/metrics/histogram.h"
#include "base/metrics/user_metrics_action.h"
+#include "base/time/time.h"
+#include "content/browser/accessibility/accessibility_mode_helper.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/cross_site_transferring_request.h"
+#include "content/browser/frame_host/frame_accessibility.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
+#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/transition_request_manager.h"
+#include "content/common/accessibility_messages.h"
#include "content/common/desktop_notification_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/inter_process_time_ticks_converter.h"
+#include "content/common/navigation_params.h"
+#include "content/common/platform_notification_messages.h"
+#include "content/common/push_messaging_messages.h"
+#include "content/common/render_frame_setup.mojom.h"
#include "content/common/swapped_out_messages.h"
+#include "content/public/browser/ax_event_notification_details.h"
+#include "content/public/browser/browser_accessibility_state.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/desktop_notification_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/stream_handle.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
+#include "ui/accessibility/ax_tree.h"
#include "url/gurl.h"
+#if defined(OS_MACOSX)
+#include "content/browser/frame_host/popup_menu_helper_mac.h"
+#endif
+
using base::TimeDelta;
namespace content {
namespace {
+// The next value to use for the accessibility reset token.
+int g_next_accessibility_reset_token = 1;
+
// The (process id, routing id) pair that identifies one RenderFrame.
typedef std::pair<int32, int32> RenderFrameHostID;
typedef base::hash_map<RenderFrameHostID, RenderFrameHostImpl*>
@@ -57,9 +90,9 @@ class DesktopNotificationDelegateImpl : public DesktopNotificationDelegate {
render_frame_id_(render_frame_host->GetRoutingID()),
notification_id_(notification_id) {}
- virtual ~DesktopNotificationDelegateImpl() {}
+ ~DesktopNotificationDelegateImpl() override {}
- virtual void NotificationDisplayed() OVERRIDE {
+ void NotificationDisplayed() override {
RenderFrameHost* rfh =
RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!rfh)
@@ -69,18 +102,7 @@ class DesktopNotificationDelegateImpl : public DesktopNotificationDelegate {
rfh->GetRoutingID(), notification_id_));
}
- virtual void NotificationError() OVERRIDE {
- RenderFrameHost* rfh =
- RenderFrameHost::FromID(render_process_id_, render_frame_id_);
- if (!rfh)
- return;
-
- rfh->Send(new DesktopNotificationMsg_PostError(
- rfh->GetRoutingID(), notification_id_));
- delete this;
- }
-
- virtual void NotificationClosed(bool by_user) OVERRIDE {
+ void NotificationClosed(bool by_user) override {
RenderFrameHost* rfh =
RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!rfh)
@@ -90,10 +112,9 @@ class DesktopNotificationDelegateImpl : public DesktopNotificationDelegate {
rfh->GetRoutingID(), notification_id_, by_user));
static_cast<RenderFrameHostImpl*>(rfh)->NotificationClosed(
notification_id_);
- delete this;
}
- virtual void NotificationClick() OVERRIDE {
+ void NotificationClick() override {
RenderFrameHost* rfh =
RenderFrameHost::FromID(render_process_id_, render_frame_id_);
if (!rfh)
@@ -125,14 +146,20 @@ base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
} // namespace
+// static
+bool RenderFrameHostImpl::IsRFHStateActive(RenderFrameHostImplState rfh_state) {
+ return rfh_state == STATE_DEFAULT;
+}
+
+// static
RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
int render_frame_id) {
return RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
}
// static
-RenderFrameHostImpl* RenderFrameHostImpl::FromID(
- int process_id, int routing_id) {
+RenderFrameHostImpl* RenderFrameHostImpl::FromID(int process_id,
+ int routing_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
RoutingIDFrameMap::iterator it = frames->find(
@@ -140,13 +167,12 @@ RenderFrameHostImpl* RenderFrameHostImpl::FromID(
return it == frames->end() ? NULL : it->second;
}
-RenderFrameHostImpl::RenderFrameHostImpl(
- RenderViewHostImpl* render_view_host,
- RenderFrameHostDelegate* delegate,
- FrameTree* frame_tree,
- FrameTreeNode* frame_tree_node,
- int routing_id,
- bool is_swapped_out)
+RenderFrameHostImpl::RenderFrameHostImpl(RenderViewHostImpl* render_view_host,
+ RenderFrameHostDelegate* delegate,
+ FrameTree* frame_tree,
+ FrameTreeNode* frame_tree_node,
+ int routing_id,
+ bool is_swapped_out)
: render_view_host_(render_view_host),
delegate_(delegate),
cross_process_frame_connector_(NULL),
@@ -154,22 +180,47 @@ RenderFrameHostImpl::RenderFrameHostImpl(
frame_tree_(frame_tree),
frame_tree_node_(frame_tree_node),
routing_id_(routing_id),
- is_swapped_out_(is_swapped_out),
+ render_frame_created_(false),
+ navigations_suspended_(false),
+ is_waiting_for_beforeunload_ack_(false),
+ unload_ack_is_for_cross_site_transition_(false),
+ accessibility_reset_token_(0),
+ accessibility_reset_count_(0),
+ no_create_browser_accessibility_manager_for_testing_(false),
weak_ptr_factory_(this) {
frame_tree_->RegisterRenderFrameHost(this);
GetProcess()->AddRoute(routing_id_, this);
g_routing_id_frame_map.Get().insert(std::make_pair(
RenderFrameHostID(GetProcess()->GetID(), routing_id_),
this));
+
+ if (is_swapped_out) {
+ rfh_state_ = STATE_SWAPPED_OUT;
+ } else {
+ rfh_state_ = STATE_DEFAULT;
+ GetSiteInstance()->increment_active_frame_count();
+ }
+
+ SetUpMojoIfNeeded();
+ swapout_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
+ &RenderFrameHostImpl::OnSwappedOut, weak_ptr_factory_.GetWeakPtr())));
}
RenderFrameHostImpl::~RenderFrameHostImpl() {
GetProcess()->RemoveRoute(routing_id_);
g_routing_id_frame_map.Get().erase(
RenderFrameHostID(GetProcess()->GetID(), routing_id_));
+
if (delegate_)
delegate_->RenderFrameDeleted(this);
+ FrameAccessibility::GetInstance()->OnRenderFrameHostDestroyed(this);
+
+ // If this was swapped out, it already decremented the active frame count of
+ // the SiteInstance it belongs to.
+ if (IsRFHStateActive(rfh_state_))
+ GetSiteInstance()->decrement_active_frame_count();
+
// Notify the FrameTree that this RFH is going away, allowing it to shut down
// the corresponding RenderViewHost if it is no longer needed.
frame_tree_->UnregisterRenderFrameHost(this);
@@ -179,7 +230,7 @@ int RenderFrameHostImpl::GetRoutingID() {
return routing_id_;
}
-SiteInstance* RenderFrameHostImpl::GetSiteInstance() {
+SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
return render_view_host_->GetSiteInstance();
}
@@ -237,17 +288,31 @@ void RenderFrameHostImpl::ExecuteJavaScript(
javascript_callbacks_.insert(std::make_pair(key, callback));
}
+void RenderFrameHostImpl::ExecuteJavaScriptForTests(
+ const base::string16& javascript) {
+ Send(new FrameMsg_JavaScriptExecuteRequestForTests(routing_id_,
+ javascript,
+ 0, false));
+}
+
RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
return render_view_host_;
}
+ServiceRegistry* RenderFrameHostImpl::GetServiceRegistry() {
+ return service_registry_.get();
+}
+
bool RenderFrameHostImpl::Send(IPC::Message* message) {
if (IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart) {
return render_view_host_->input_router()->SendInput(
make_scoped_ptr(message));
}
- if (render_view_host_->IsSwappedOut()) {
+ // Route IPCs through the RenderFrameProxyHost when in swapped out state.
+ // Note: For subframes in --site-per-process mode, we don't use swapped out
+ // RenderFrameHosts.
+ if (frame_tree_node_->IsMainFrame() && is_swapped_out()) {
DCHECK(render_frame_proxy_host_);
return render_frame_proxy_host_->Send(message);
}
@@ -256,12 +321,9 @@ bool RenderFrameHostImpl::Send(IPC::Message* message) {
}
bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
- // Filter out most IPC messages if this renderer is swapped out.
+ // Filter out most IPC messages if this frame is swapped out.
// We still want to handle certain ACKs to keep our state consistent.
- // TODO(nasko): Only check RenderViewHost state, as this object's own state
- // isn't yet properly updated. Transition this check once the swapped out
- // state is correct in RenderFrameHost itself.
- if (render_view_host_->IsSwappedOut()) {
+ if (is_swapped_out()) {
if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
// If this is a synchronous message and we decided not to handle it,
// we must send an error reply, or else the renderer will be stuck
@@ -294,12 +356,10 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnDidStartProvisionalLoadForFrame)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailProvisionalLoadWithError,
OnDidFailProvisionalLoadWithError)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidRedirectProvisionalLoad,
- OnDidRedirectProvisionalLoad)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidFailLoadWithError,
OnDidFailLoadWithError)
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_DidCommitProvisionalLoad,
- OnNavigate(msg))
+ OnDidCommitProvisionalLoad(msg))
IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_DocumentOnLoadCompleted,
OnDocumentOnLoadCompleted)
@@ -315,21 +375,225 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(FrameHostMsg_DidAccessInitialDocument,
OnDidAccessInitialDocument)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidDisownOpener, OnDidDisownOpener)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidAssignPageId, OnDidAssignPageId)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateTitle, OnUpdateTitle)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateEncoding, OnUpdateEncoding)
- IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_RequestPermission,
- OnRequestDesktopNotificationPermission)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_BeginNavigation,
+ OnBeginNavigation)
+ IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_RequestPermission,
+ OnRequestPlatformNotificationPermission)
IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Show,
OnShowDesktopNotification)
IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_Cancel,
OnCancelDesktopNotification)
IPC_MESSAGE_HANDLER(FrameHostMsg_TextSurroundingSelectionResponse,
OnTextSurroundingSelectionResponse)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_LocationChanges,
+ OnAccessibilityLocationChanges)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_FindInPageResult,
+ OnAccessibilityFindInPageResult)
+ IPC_MESSAGE_HANDLER(PushMessagingHostMsg_RequestPermission,
+ OnRequestPushPermission)
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_HidePopup, OnHidePopup)
+#endif
IPC_END_MESSAGE_MAP()
+ // No further actions here, since we may have been deleted.
return handled;
}
+void RenderFrameHostImpl::AccessibilitySetFocus(int object_id) {
+ Send(new AccessibilityMsg_SetFocus(routing_id_, object_id));
+}
+
+void RenderFrameHostImpl::AccessibilityDoDefaultAction(int object_id) {
+ Send(new AccessibilityMsg_DoDefaultAction(routing_id_, object_id));
+}
+
+void RenderFrameHostImpl::AccessibilityShowMenu(
+ const gfx::Point& global_point) {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view)
+ view->AccessibilityShowMenu(global_point);
+}
+
+void RenderFrameHostImpl::AccessibilityScrollToMakeVisible(
+ int acc_obj_id, const gfx::Rect& subfocus) {
+ Send(new AccessibilityMsg_ScrollToMakeVisible(
+ routing_id_, acc_obj_id, subfocus));
+}
+
+void RenderFrameHostImpl::AccessibilityScrollToPoint(
+ int acc_obj_id, const gfx::Point& point) {
+ Send(new AccessibilityMsg_ScrollToPoint(
+ routing_id_, acc_obj_id, point));
+}
+
+void RenderFrameHostImpl::AccessibilitySetTextSelection(
+ int object_id, int start_offset, int end_offset) {
+ Send(new AccessibilityMsg_SetTextSelection(
+ routing_id_, object_id, start_offset, end_offset));
+}
+
+void RenderFrameHostImpl::AccessibilitySetValue(
+ int object_id, const base::string16& value) {
+ Send(new AccessibilityMsg_SetValue(routing_id_, object_id, value));
+}
+
+bool RenderFrameHostImpl::AccessibilityViewHasFocus() const {
+ RenderWidgetHostView* view = render_view_host_->GetView();
+ if (view)
+ return view->HasFocus();
+ return false;
+}
+
+gfx::Rect RenderFrameHostImpl::AccessibilityGetViewBounds() const {
+ RenderWidgetHostView* view = render_view_host_->GetView();
+ if (view)
+ return view->GetViewBounds();
+ return gfx::Rect();
+}
+
+gfx::Point RenderFrameHostImpl::AccessibilityOriginInScreen(
+ const gfx::Rect& bounds) const {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view)
+ return view->AccessibilityOriginInScreen(bounds);
+ return gfx::Point();
+}
+
+void RenderFrameHostImpl::AccessibilityHitTest(const gfx::Point& point) {
+ Send(new AccessibilityMsg_HitTest(routing_id_, point));
+}
+
+void RenderFrameHostImpl::AccessibilitySetAccessibilityFocus(int acc_obj_id) {
+ Send(new AccessibilityMsg_SetAccessibilityFocus(routing_id_, acc_obj_id));
+}
+
+void RenderFrameHostImpl::AccessibilityFatalError() {
+ browser_accessibility_manager_.reset(NULL);
+ if (accessibility_reset_token_)
+ return;
+
+ accessibility_reset_count_++;
+ if (accessibility_reset_count_ >= kMaxAccessibilityResets) {
+ Send(new AccessibilityMsg_FatalError(routing_id_));
+ } else {
+ accessibility_reset_token_ = g_next_accessibility_reset_token++;
+ UMA_HISTOGRAM_COUNTS("Accessibility.FrameResetCount", 1);
+ Send(new AccessibilityMsg_Reset(routing_id_, accessibility_reset_token_));
+ }
+}
+
+gfx::AcceleratedWidget
+ RenderFrameHostImpl::AccessibilityGetAcceleratedWidget() {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view)
+ return view->AccessibilityGetAcceleratedWidget();
+ return gfx::kNullAcceleratedWidget;
+}
+
+gfx::NativeViewAccessible
+ RenderFrameHostImpl::AccessibilityGetNativeViewAccessible() {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view)
+ return view->AccessibilityGetNativeViewAccessible();
+ return NULL;
+}
+
+BrowserAccessibilityManager* RenderFrameHostImpl::AccessibilityGetChildFrame(
+ int accessibility_node_id) {
+ RenderFrameHostImpl* child_frame =
+ FrameAccessibility::GetInstance()->GetChild(this, accessibility_node_id);
+ if (!child_frame)
+ return NULL;
+
+ // Return NULL if this isn't an out-of-process iframe. Same-process iframes
+ // are already part of the accessibility tree.
+ if (child_frame->GetProcess()->GetID() == GetProcess()->GetID())
+ return NULL;
+
+ // As a sanity check, make sure the frame we're going to return belongs
+ // to the same BrowserContext.
+ if (GetSiteInstance()->GetBrowserContext() !=
+ child_frame->GetSiteInstance()->GetBrowserContext()) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ return child_frame->GetOrCreateBrowserAccessibilityManager();
+}
+
+BrowserAccessibility* RenderFrameHostImpl::AccessibilityGetParentFrame() {
+ RenderFrameHostImpl* parent_frame = NULL;
+ int parent_node_id = 0;
+ if (!FrameAccessibility::GetInstance()->GetParent(
+ this, &parent_frame, &parent_node_id)) {
+ return NULL;
+ }
+
+ // As a sanity check, make sure the frame we're going to return belongs
+ // to the same BrowserContext.
+ if (GetSiteInstance()->GetBrowserContext() !=
+ parent_frame->GetSiteInstance()->GetBrowserContext()) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ BrowserAccessibilityManager* manager =
+ parent_frame->browser_accessibility_manager();
+ if (!manager)
+ return NULL;
+
+ return manager->GetFromID(parent_node_id);
+}
+
+bool RenderFrameHostImpl::CreateRenderFrame(int parent_routing_id,
+ int proxy_routing_id) {
+ TRACE_EVENT0("navigation", "RenderFrameHostImpl::CreateRenderFrame");
+ DCHECK(!IsRenderFrameLive()) << "Creating frame twice";
+
+ // The process may (if we're sharing a process with another host that already
+ // initialized it) or may not (we have our own process or the old process
+ // crashed) have been initialized. Calling Init multiple times will be
+ // ignored, so this is safe.
+ if (!GetProcess()->Init())
+ return false;
+
+ DCHECK(GetProcess()->HasConnection());
+
+ Send(new FrameMsg_NewFrame(routing_id_, parent_routing_id, proxy_routing_id));
+
+ // The renderer now has a RenderFrame for this RenderFrameHost. Note that
+ // this path is only used for out-of-process iframes. Main frame RenderFrames
+ // are created with their RenderView, and same-site iframes are created at the
+ // time of OnCreateChildFrame.
+ set_render_frame_created(true);
+
+ return true;
+}
+
+bool RenderFrameHostImpl::IsRenderFrameLive() {
+ // RenderFrames are created for main frames at the same time as RenderViews,
+ // so we rely on IsRenderViewLive. For subframes, we keep track of each
+ // RenderFrame individually with render_frame_created_.
+ bool is_live = !GetParent() ?
+ render_view_host_->IsRenderViewLive() :
+ GetProcess()->HasConnection() && render_frame_created_;
+
+ // Sanity check: the RenderView should always be live if the RenderFrame is.
+ DCHECK(!is_live || render_view_host_->IsRenderViewLive());
+
+ return is_live;
+}
+
void RenderFrameHostImpl::Init() {
GetProcess()->ResumeRequestsForView(routing_id_);
}
@@ -354,8 +618,22 @@ void RenderFrameHostImpl::OnAddMessageToConsole(
void RenderFrameHostImpl::OnCreateChildFrame(int new_routing_id,
const std::string& frame_name) {
+ // It is possible that while a new RenderFrameHost was committed, the
+ // RenderFrame corresponding to this host sent an IPC message to create a
+ // frame and it is delivered after this host is swapped out.
+ // Ignore such messages, as we know this RenderFrameHost is going away.
+ if (rfh_state_ != RenderFrameHostImpl::STATE_DEFAULT)
+ return;
+
RenderFrameHostImpl* new_frame = frame_tree_->AddFrame(
- frame_tree_node_, new_routing_id, frame_name);
+ frame_tree_node_, GetProcess()->GetID(), new_routing_id, frame_name);
+ if (!new_frame)
+ return;
+
+ // We know that the RenderFrame has been created in this case, immediately
+ // after the CreateChildFrame IPC was sent.
+ new_frame->set_render_frame_created(true);
+
if (delegate_)
delegate_->RenderFrameCreated(new_frame);
}
@@ -373,6 +651,8 @@ void RenderFrameHostImpl::OnOpenURL(
GURL validated_url(params.url);
GetProcess()->FilterURL(false, &validated_url);
+ TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnOpenURL",
+ "url", validated_url.possibly_invalid_spec());
frame_tree_node_->navigator()->RequestOpenURL(
this, validated_url, params.referrer, params.disposition,
params.should_replace_current_entry, params.user_gesture);
@@ -385,10 +665,10 @@ void RenderFrameHostImpl::OnDocumentOnLoadCompleted() {
}
void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame(
- int parent_routing_id,
- const GURL& url) {
+ const GURL& url,
+ bool is_transition_navigation) {
frame_tree_node_->navigator()->DidStartProvisionalLoad(
- this, parent_routing_id, url);
+ this, url, is_transition_navigation);
}
void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
@@ -407,14 +687,6 @@ void RenderFrameHostImpl::OnDidFailLoadWithError(
this, validated_url, error_code, error_description);
}
-void RenderFrameHostImpl::OnDidRedirectProvisionalLoad(
- int32 page_id,
- const GURL& source_url,
- const GURL& target_url) {
- frame_tree_node_->navigator()->DidRedirectProvisionalLoad(
- this, page_id, source_url, target_url);
-}
-
// Called when the renderer navigates. For every frame loaded, we'll get this
// notification containing parameters identifying the navigation.
//
@@ -423,7 +695,7 @@ void RenderFrameHostImpl::OnDidRedirectProvisionalLoad(
// level frame. If the user explicitly requests a subframe navigation, we will
// get a new page_id because we need to create a new navigation entry for that
// action.
-void RenderFrameHostImpl::OnNavigate(const IPC::Message& msg) {
+void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
// Read the parameters out of the IPC message directly to avoid making another
// copy when we filter the URLs.
PickleIterator iter(msg);
@@ -431,18 +703,20 @@ void RenderFrameHostImpl::OnNavigate(const IPC::Message& msg) {
if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::
Read(&msg, &iter, &validated_params))
return;
+ TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnDidCommitProvisionalLoad",
+ "url", validated_params.url.possibly_invalid_spec());
// If we're waiting for a cross-site beforeunload ack from this renderer and
// we receive a Navigate message from the main frame, then the renderer was
- // navigating already and sent it before hearing the ViewMsg_Stop message.
+ // navigating already and sent it before hearing the FrameMsg_Stop message.
// We do not want to cancel the pending navigation in this case, since the
// old page will soon be stopped. Instead, treat this as a beforeunload ack
// to allow the pending navigation to continue.
- if (render_view_host_->is_waiting_for_beforeunload_ack_ &&
- render_view_host_->unload_ack_is_for_cross_site_transition_ &&
- PageTransitionIsMainFrame(validated_params.transition)) {
- OnBeforeUnloadACK(true, send_before_unload_start_time_,
- base::TimeTicks::Now());
+ if (is_waiting_for_beforeunload_ack_ &&
+ unload_ack_is_for_cross_site_transition_ &&
+ ui::PageTransitionIsMainFrame(validated_params.transition)) {
+ base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
+ OnBeforeUnloadACK(true, approx_renderer_start_time, base::TimeTicks::Now());
return;
}
@@ -451,7 +725,7 @@ void RenderFrameHostImpl::OnNavigate(const IPC::Message& msg) {
// unload request. It will either respond to the unload request soon or our
// timer will expire. Either way, we should ignore this message, because we
// have already committed to closing this renderer.
- if (render_view_host_->IsWaitingForUnloadACK())
+ if (IsWaitingForUnloadACK())
return;
RenderProcessHost* process = GetProcess();
@@ -490,6 +764,7 @@ void RenderFrameHostImpl::OnNavigate(const IPC::Message& msg) {
return;
}
+ accessibility_reset_count_ = 0;
frame_tree_node()->navigator()->DidNavigate(this, validated_params);
}
@@ -506,7 +781,7 @@ void RenderFrameHostImpl::OnCrossSiteResponse(
scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
bool should_replace_current_entry) {
frame_tree_node_->render_manager()->OnCrossSiteResponse(
this, global_request_id, cross_site_transferring_request.Pass(),
@@ -514,84 +789,124 @@ void RenderFrameHostImpl::OnCrossSiteResponse(
should_replace_current_entry);
}
-void RenderFrameHostImpl::SwapOut(RenderFrameProxyHost* proxy) {
- // TODO(creis): Move swapped out state to RFH. Until then, only update it
- // when swapping out the main frame.
- if (!GetParent()) {
- // If this RenderViewHost is not in the default state, it must have already
- // gone through this, therefore just return.
- if (render_view_host_->rvh_state_ != RenderViewHostImpl::STATE_DEFAULT)
- return;
+void RenderFrameHostImpl::OnDeferredAfterResponseStarted(
+ const GlobalRequestID& global_request_id,
+ const TransitionLayerData& transition_data) {
+ frame_tree_node_->render_manager()->OnDeferredAfterResponseStarted(
+ global_request_id, this);
+
+ if (GetParent() || !delegate_->WillHandleDeferAfterResponseStarted())
+ frame_tree_node_->render_manager()->ResumeResponseDeferredAtStart();
+ else
+ delegate_->DidDeferAfterResponseStarted(transition_data);
+}
- render_view_host_->SetState(
- RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK);
- render_view_host_->unload_event_monitor_timeout_->Start(
- base::TimeDelta::FromMilliseconds(
- RenderViewHostImpl::kUnloadTimeoutMS));
+void RenderFrameHostImpl::SwapOut(RenderFrameProxyHost* proxy) {
+ // The end of this event is in OnSwapOutACK when the RenderFrame has completed
+ // the operation and sends back an IPC message.
+ // The trace event may not end properly if the ACK times out. We expect this
+ // to be fixed when RenderViewHostImpl::OnSwapOut moves to RenderFrameHost.
+ TRACE_EVENT_ASYNC_BEGIN0("navigation", "RenderFrameHostImpl::SwapOut", this);
+
+ // If this RenderFrameHost is not in the default state, it must have already
+ // gone through this, therefore just return.
+ if (rfh_state_ != RenderFrameHostImpl::STATE_DEFAULT) {
+ NOTREACHED() << "RFH should be in default state when calling SwapOut.";
+ return;
}
- set_render_frame_proxy_host(proxy);
+ SetState(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT);
+ swapout_event_monitor_timeout_->Start(
+ base::TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS));
+
+ // There may be no proxy if there are no active views in the process.
+ int proxy_routing_id = MSG_ROUTING_NONE;
+ if (proxy) {
+ set_render_frame_proxy_host(proxy);
+ proxy_routing_id = proxy->GetRoutingID();
+ }
- if (render_view_host_->IsRenderViewLive())
- Send(new FrameMsg_SwapOut(routing_id_, proxy->GetRoutingID()));
+ if (IsRenderFrameLive())
+ Send(new FrameMsg_SwapOut(routing_id_, proxy_routing_id));
if (!GetParent())
delegate_->SwappedOut(this);
-
- // Allow the navigation to proceed.
- frame_tree_node_->render_manager()->SwappedOut(this);
}
void RenderFrameHostImpl::OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time) {
- // TODO(creis): Support properly beforeunload on subframes. For now just
- // pretend that the handler ran and allowed the navigation to proceed.
- if (GetParent()) {
- render_view_host_->is_waiting_for_beforeunload_ack_ = false;
- frame_tree_node_->render_manager()->OnBeforeUnloadACK(
- render_view_host_->unload_ack_is_for_cross_site_transition_, proceed,
- renderer_before_unload_end_time);
- return;
- }
-
+ TRACE_EVENT_ASYNC_END0(
+ "navigation", "RenderFrameHostImpl::BeforeUnload", this);
+ DCHECK(!GetParent());
render_view_host_->decrement_in_flight_event_count();
render_view_host_->StopHangMonitorTimeout();
// If this renderer navigated while the beforeunload request was in flight, we
- // may have cleared this state in OnNavigate, in which case we can ignore
- // this message.
+ // may have cleared this state in OnDidCommitProvisionalLoad, in which case we
+ // can ignore this message.
// However renderer might also be swapped out but we still want to proceed
// with navigation, otherwise it would block future navigations. This can
// happen when pending cross-site navigation is canceled by a second one just
- // before OnNavigate while current RVH is waiting for commit but second
- // navigation is started from the beginning.
- if (!render_view_host_->is_waiting_for_beforeunload_ack_) {
+ // before OnDidCommitProvisionalLoad while current RVH is waiting for commit
+ // but second navigation is started from the beginning.
+ if (!is_waiting_for_beforeunload_ack_) {
return;
}
+ DCHECK(!send_before_unload_start_time_.is_null());
- render_view_host_->is_waiting_for_beforeunload_ack_ = false;
-
- base::TimeTicks before_unload_end_time;
- if (!send_before_unload_start_time_.is_null() &&
- !renderer_before_unload_start_time.is_null() &&
+ // Sets a default value for before_unload_end_time so that the browser
+ // survives a hacked renderer.
+ base::TimeTicks before_unload_end_time = renderer_before_unload_end_time;
+ if (!renderer_before_unload_start_time.is_null() &&
!renderer_before_unload_end_time.is_null()) {
// When passing TimeTicks across process boundaries, we need to compensate
// for any skew between the processes. Here we are converting the
// renderer's notion of before_unload_end_time to TimeTicks in the browser
// process. See comments in inter_process_time_ticks_converter.h for more.
+ base::TimeTicks receive_before_unload_ack_time = base::TimeTicks::Now();
InterProcessTimeTicksConverter converter(
LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
- LocalTimeTicks::FromTimeTicks(base::TimeTicks::Now()),
+ LocalTimeTicks::FromTimeTicks(receive_before_unload_ack_time),
RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
LocalTimeTicks browser_before_unload_end_time =
converter.ToLocalTimeTicks(
RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
+
+ // Collect UMA on the inter-process skew.
+ bool is_skew_additive = false;
+ if (converter.IsSkewAdditiveForMetrics()) {
+ is_skew_additive = true;
+ base::TimeDelta skew = converter.GetSkewForMetrics();
+ if (skew >= base::TimeDelta()) {
+ UMA_HISTOGRAM_TIMES(
+ "InterProcessTimeTicks.BrowserBehind_RendererToBrowser", skew);
+ } else {
+ UMA_HISTOGRAM_TIMES(
+ "InterProcessTimeTicks.BrowserAhead_RendererToBrowser", -skew);
+ }
+ }
+ UMA_HISTOGRAM_BOOLEAN(
+ "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
+ is_skew_additive);
+
+ base::TimeDelta on_before_unload_overhead_time =
+ (receive_before_unload_ack_time - send_before_unload_start_time_) -
+ (renderer_before_unload_end_time - renderer_before_unload_start_time);
+ UMA_HISTOGRAM_TIMES("Navigation.OnBeforeUnloadOverheadTime",
+ on_before_unload_overhead_time);
+
+ frame_tree_node_->navigator()->LogBeforeUnloadTime(
+ renderer_before_unload_start_time, renderer_before_unload_end_time);
}
+ // Resets beforeunload waiting state.
+ is_waiting_for_beforeunload_ack_ = false;
+ send_before_unload_start_time_ = base::TimeTicks();
+
frame_tree_node_->render_manager()->OnBeforeUnloadACK(
- render_view_host_->unload_ack_is_for_cross_site_transition_, proceed,
+ unload_ack_is_for_cross_site_transition_, proceed,
before_unload_end_time);
// If canceled, notify the delegate to cancel its pending navigation entry.
@@ -599,17 +914,30 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
render_view_host_->GetDelegate()->DidCancelLoading();
}
+bool RenderFrameHostImpl::IsWaitingForUnloadACK() const {
+ return render_view_host_->is_waiting_for_close_ack_ ||
+ rfh_state_ == STATE_PENDING_SWAP_OUT;
+}
+
void RenderFrameHostImpl::OnSwapOutACK() {
- OnSwappedOut(false);
+ OnSwappedOut();
}
-void RenderFrameHostImpl::OnSwappedOut(bool timed_out) {
- // For now, we only need to update the RVH state machine for top-level swaps.
- // Subframe swaps (in --site-per-process) can just continue via RFHM.
- if (!GetParent())
- render_view_host_->OnSwappedOut(timed_out);
- else
- frame_tree_node_->render_manager()->SwappedOut(this);
+void RenderFrameHostImpl::OnSwappedOut() {
+ // Ignore spurious swap out ack.
+ if (rfh_state_ != STATE_PENDING_SWAP_OUT)
+ return;
+
+ TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::SwapOut", this);
+ swapout_event_monitor_timeout_->Stop();
+
+ if (frame_tree_node_->render_manager()->DeleteFromPendingList(this)) {
+ // We are now deleted.
+ return;
+ }
+
+ // If this RFH wasn't pending deletion, then it is now swapped out.
+ SetState(RenderFrameHostImpl::STATE_SWAPPED_OUT);
}
void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
@@ -666,38 +994,54 @@ void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {
- // While a JS before unload dialog is showing, tabs in the same process
+ // While a JS beforeunload dialog is showing, tabs in the same process
// shouldn't process input events.
GetProcess()->SetIgnoreInputEvents(true);
render_view_host_->StopHangMonitorTimeout();
delegate_->RunBeforeUnloadConfirm(this, message, is_reload, reply_msg);
}
-void RenderFrameHostImpl::OnRequestDesktopNotificationPermission(
- const GURL& source_origin, int callback_context) {
- base::Closure done_callback = base::Bind(
- &RenderFrameHostImpl::DesktopNotificationPermissionRequestDone,
- weak_ptr_factory_.GetWeakPtr(), callback_context);
- GetContentClient()->browser()->RequestDesktopNotificationPermission(
- source_origin, this, done_callback);
+void RenderFrameHostImpl::OnRequestPlatformNotificationPermission(
+ const GURL& origin, int request_id) {
+ base::Callback<void(bool)> done_callback = base::Bind(
+ &RenderFrameHostImpl::PlatformNotificationPermissionRequestDone,
+ weak_ptr_factory_.GetWeakPtr(),
+ request_id);
+
+ if (!delegate()->GetAsWebContents())
+ return;
+
+ // TODO(peter): plumb user_gesture and bridge_id.
+ GetContentClient()->browser()->RequestPermission(
+ content::PERMISSION_NOTIFICATIONS,
+ delegate()->GetAsWebContents(),
+ routing_id_,
+ origin,
+ true, // user_gesture,
+ done_callback);
}
void RenderFrameHostImpl::OnShowDesktopNotification(
int notification_id,
const ShowDesktopNotificationHostMsgParams& params) {
+ scoped_ptr<DesktopNotificationDelegateImpl> delegate(
+ new DesktopNotificationDelegateImpl(this, notification_id));
+
base::Closure cancel_callback;
GetContentClient()->browser()->ShowDesktopNotification(
- params, this,
- new DesktopNotificationDelegateImpl(this, notification_id),
+ params,
+ GetSiteInstance()->GetBrowserContext(),
+ GetProcess()->GetID(),
+ delegate.Pass(),
&cancel_callback);
+
cancel_notification_callbacks_[notification_id] = cancel_callback;
}
void RenderFrameHostImpl::OnCancelDesktopNotification(int notification_id) {
- if (!cancel_notification_callbacks_.count(notification_id)) {
- NOTREACHED();
+ if (!cancel_notification_callbacks_.count(notification_id))
return;
- }
+
cancel_notification_callbacks_[notification_id].Run();
cancel_notification_callbacks_.erase(notification_id);
}
@@ -720,8 +1064,13 @@ void RenderFrameHostImpl::OnDidDisownOpener() {
delegate_->DidDisownOpener(this);
}
+void RenderFrameHostImpl::OnDidAssignPageId(int32 page_id) {
+ // Update the RVH's current page ID so that future IPCs from the renderer
+ // correspond to the new page.
+ render_view_host_->page_id_ = page_id;
+}
+
void RenderFrameHostImpl::OnUpdateTitle(
- int32 page_id,
const base::string16& title,
blink::WebTextDirection title_direction) {
// This message is only sent for top-level frames. TODO(avi): when frame tree
@@ -731,7 +1080,7 @@ void RenderFrameHostImpl::OnUpdateTitle(
return;
}
- delegate_->UpdateTitle(this, page_id, title,
+ delegate_->UpdateTitle(this, render_view_host_->page_id_, title,
WebTextDirectionToChromeTextDirection(
title_direction));
}
@@ -742,8 +1091,221 @@ void RenderFrameHostImpl::OnUpdateEncoding(const std::string& encoding_name) {
delegate_->UpdateEncoding(this, encoding_name);
}
-void RenderFrameHostImpl::SetPendingShutdown(const base::Closure& on_swap_out) {
- render_view_host_->SetPendingShutdown(on_swap_out);
+void RenderFrameHostImpl::OnBeginNavigation(
+ const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ frame_tree_node()->navigator()->OnBeginNavigation(
+ frame_tree_node(), params, common_params);
+}
+
+void RenderFrameHostImpl::OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params,
+ int reset_token) {
+ // Don't process this IPC if either we're waiting on a reset and this
+ // IPC doesn't have the matching token ID, or if we're not waiting on a
+ // reset but this message includes a reset token.
+ if (accessibility_reset_token_ != reset_token) {
+ Send(new AccessibilityMsg_Events_ACK(routing_id_));
+ return;
+ }
+ accessibility_reset_token_ = 0;
+
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+
+ AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if ((accessibility_mode != AccessibilityModeOff) && view &&
+ RenderFrameHostImpl::IsRFHStateActive(rfh_state())) {
+ if (accessibility_mode & AccessibilityModeFlagPlatform) {
+ GetOrCreateBrowserAccessibilityManager();
+ if (browser_accessibility_manager_)
+ browser_accessibility_manager_->OnAccessibilityEvents(params);
+ }
+
+ if (browser_accessibility_manager_) {
+ // Get the frame routing ids from out-of-process iframes and
+ // browser plugin instance ids from guests and update the mappings in
+ // FrameAccessibility.
+ for (size_t i = 0; i < params.size(); ++i) {
+ const AccessibilityHostMsg_EventParams& param = params[i];
+ UpdateCrossProcessIframeAccessibility(
+ param.node_to_frame_routing_id_map);
+ UpdateGuestFrameAccessibility(
+ param.node_to_browser_plugin_instance_id_map);
+ }
+ }
+
+ // Send the updates to the automation extension API.
+ std::vector<AXEventNotificationDetails> details;
+ details.reserve(params.size());
+ for (size_t i = 0; i < params.size(); ++i) {
+ const AccessibilityHostMsg_EventParams& param = params[i];
+ AXEventNotificationDetails detail(param.update.node_id_to_clear,
+ param.update.nodes,
+ param.event_type,
+ param.id,
+ GetProcess()->GetID(),
+ routing_id_);
+ details.push_back(detail);
+ }
+
+ delegate_->AccessibilityEventReceived(details);
+ }
+
+ // Always send an ACK or the renderer can be in a bad state.
+ Send(new AccessibilityMsg_Events_ACK(routing_id_));
+
+ // The rest of this code is just for testing; bail out if we're not
+ // in that mode.
+ if (accessibility_testing_callback_.is_null())
+ return;
+
+ for (size_t i = 0; i < params.size(); i++) {
+ const AccessibilityHostMsg_EventParams& param = params[i];
+ if (static_cast<int>(param.event_type) < 0)
+ continue;
+
+ if (!ax_tree_for_testing_) {
+ if (browser_accessibility_manager_) {
+ ax_tree_for_testing_.reset(new ui::AXTree(
+ browser_accessibility_manager_->SnapshotAXTreeForTesting()));
+ } else {
+ ax_tree_for_testing_.reset(new ui::AXTree());
+ CHECK(ax_tree_for_testing_->Unserialize(param.update))
+ << ax_tree_for_testing_->error();
+ }
+ } else {
+ CHECK(ax_tree_for_testing_->Unserialize(param.update))
+ << ax_tree_for_testing_->error();
+ }
+ accessibility_testing_callback_.Run(param.event_type, param.id);
+ }
+}
+
+void RenderFrameHostImpl::OnAccessibilityLocationChanges(
+ const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
+ if (accessibility_reset_token_)
+ return;
+
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view && RenderFrameHostImpl::IsRFHStateActive(rfh_state())) {
+ AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode & AccessibilityModeFlagPlatform) {
+ BrowserAccessibilityManager* manager =
+ GetOrCreateBrowserAccessibilityManager();
+ if (manager)
+ manager->OnLocationChanges(params);
+ }
+ // TODO(aboxhall): send location change events to web contents observers too
+ }
+}
+
+void RenderFrameHostImpl::OnAccessibilityFindInPageResult(
+ const AccessibilityHostMsg_FindInPageResultParams& params) {
+ AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode & AccessibilityModeFlagPlatform) {
+ BrowserAccessibilityManager* manager =
+ GetOrCreateBrowserAccessibilityManager();
+ if (manager) {
+ manager->OnFindInPageResult(
+ params.request_id, params.match_index, params.start_id,
+ params.start_offset, params.end_id, params.end_offset);
+ }
+ }
+}
+
+void RenderFrameHostImpl::OnRequestPushPermission(int request_id,
+ bool user_gesture) {
+ if (!delegate()->GetAsWebContents())
+ return;
+
+ GetContentClient()->browser()->RequestPermission(
+ PERMISSION_PUSH_MESSAGING,
+ delegate()->GetAsWebContents(),
+ routing_id_,
+ GetLastCommittedURL().GetOrigin(),
+ user_gesture,
+ base::Bind(&RenderFrameHostImpl::PushPermissionRequestDone,
+ weak_ptr_factory_.GetWeakPtr(),
+ request_id));
+}
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+void RenderFrameHostImpl::OnShowPopup(
+ const FrameHostMsg_ShowPopup_Params& params) {
+ RenderViewHostDelegateView* view =
+ render_view_host_->delegate_->GetDelegateView();
+ if (view) {
+ view->ShowPopupMenu(this,
+ params.bounds,
+ params.item_height,
+ params.item_font_size,
+ params.selected_item,
+ params.popup_items,
+ params.right_aligned,
+ params.allow_multiple_selection);
+ }
+}
+
+void RenderFrameHostImpl::OnHidePopup() {
+ RenderViewHostDelegateView* view =
+ render_view_host_->delegate_->GetDelegateView();
+ if (view)
+ view->HidePopupMenu();
+}
+#endif
+
+void RenderFrameHostImpl::RegisterMojoServices() {
+ GeolocationServiceContext* geolocation_service_context =
+ delegate_ ? delegate_->GetGeolocationServiceContext() : NULL;
+ if (geolocation_service_context) {
+ // TODO(creis): Bind process ID here so that GeolocationServiceImpl
+ // can perform permissions checks once site isolation is complete.
+ // crbug.com/426384
+ GetServiceRegistry()->AddService<GeolocationService>(
+ base::Bind(&GeolocationServiceContext::CreateService,
+ base::Unretained(geolocation_service_context),
+ base::Bind(&RenderFrameHostImpl::DidUseGeolocationPermission,
+ base::Unretained(this))));
+ }
+}
+
+void RenderFrameHostImpl::SetState(RenderFrameHostImplState rfh_state) {
+ // Only main frames should be swapped out and retained inside a proxy host.
+ if (rfh_state == STATE_SWAPPED_OUT)
+ CHECK(!GetParent());
+
+ // We update the number of RenderFrameHosts in a SiteInstance when the swapped
+ // out status of a RenderFrameHost gets flipped to/from active.
+ if (!IsRFHStateActive(rfh_state_) && IsRFHStateActive(rfh_state))
+ GetSiteInstance()->increment_active_frame_count();
+ else if (IsRFHStateActive(rfh_state_) && !IsRFHStateActive(rfh_state))
+ GetSiteInstance()->decrement_active_frame_count();
+
+ // The active and swapped out state of the RVH is determined by its main
+ // frame, since subframes should have their own widgets.
+ if (frame_tree_node_->IsMainFrame()) {
+ render_view_host_->set_is_active(IsRFHStateActive(rfh_state));
+ render_view_host_->set_is_swapped_out(rfh_state == STATE_SWAPPED_OUT);
+ }
+
+ // Whenever we change the RFH state to and from active or swapped out state,
+ // we should not be waiting for beforeunload or close acks. We clear them
+ // here to be safe, since they can cause navigations to be ignored in
+ // OnDidCommitProvisionalLoad.
+ // TODO(creis): Move is_waiting_for_beforeunload_ack_ into the state machine.
+ if (rfh_state == STATE_DEFAULT ||
+ rfh_state == STATE_SWAPPED_OUT ||
+ rfh_state_ == STATE_DEFAULT ||
+ rfh_state_ == STATE_SWAPPED_OUT) {
+ is_waiting_for_beforeunload_ack_ = false;
+ send_before_unload_start_time_ = base::TimeTicks();
+ render_view_host_->is_waiting_for_close_ack_ = false;
+ }
+ rfh_state_ = rfh_state;
}
bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
@@ -756,13 +1318,13 @@ bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
}
void RenderFrameHostImpl::Navigate(const FrameMsg_Navigate_Params& params) {
- TRACE_EVENT0("frame_host", "RenderFrameHostImpl::Navigate");
+ TRACE_EVENT0("navigation", "RenderFrameHostImpl::Navigate");
// Browser plugin guests are not allowed to navigate outside web-safe schemes,
// so do not grant them the ability to request additional URLs.
if (!GetProcess()->IsIsolatedGuest()) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
- GetProcess()->GetID(), params.url);
- if (params.url.SchemeIs(url::kDataScheme) &&
+ GetProcess()->GetID(), params.common_params.url);
+ if (params.common_params.url.SchemeIs(url::kDataScheme) &&
params.base_url_for_data_url.SchemeIs(url::kFileScheme)) {
// If 'data:' is used, and we have a 'file:' base url, grant access to
// local files.
@@ -773,18 +1335,17 @@ void RenderFrameHostImpl::Navigate(const FrameMsg_Navigate_Params& params) {
// Only send the message if we aren't suspended at the start of a cross-site
// request.
- if (render_view_host_->navigations_suspended_) {
+ if (navigations_suspended_) {
// Shouldn't be possible to have a second navigation while suspended, since
// navigations will only be suspended during a cross-site request. If a
// second navigation occurs, RenderFrameHostManager will cancel this pending
// RFH and create a new pending RFH.
- DCHECK(!render_view_host_->suspended_nav_params_.get());
- render_view_host_->suspended_nav_params_.reset(
- new FrameMsg_Navigate_Params(params));
+ DCHECK(!suspended_nav_params_.get());
+ suspended_nav_params_.reset(new FrameMsg_Navigate_Params(params));
} else {
// Get back to a clean state, in case we start a new navigation without
- // completing a RVH swap or unload handler.
- render_view_host_->SetState(RenderViewHostImpl::STATE_DEFAULT);
+ // completing a RFH swap or unload handler.
+ SetState(RenderFrameHostImpl::STATE_DEFAULT);
Send(new FrameMsg_Navigate(routing_id_, params));
}
@@ -800,53 +1361,60 @@ void RenderFrameHostImpl::Navigate(const FrameMsg_Navigate_Params& params) {
//
// Blink doesn't send throb notifications for JavaScript URLs, so we
// don't want to either.
- if (!params.url.SchemeIs(url::kJavaScriptScheme))
+ if (!params.common_params.url.SchemeIs(url::kJavaScriptScheme))
delegate_->DidStartLoading(this, true);
}
void RenderFrameHostImpl::NavigateToURL(const GURL& url) {
FrameMsg_Navigate_Params params;
+ params.common_params.url = url;
+ params.common_params.transition = ui::PAGE_TRANSITION_LINK;
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.commit_params.browser_navigation_start = base::TimeTicks::Now();
params.page_id = -1;
params.pending_history_list_offset = -1;
params.current_history_list_offset = -1;
params.current_history_list_length = 0;
- params.url = url;
- params.transition = PAGE_TRANSITION_LINK;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
Navigate(params);
}
+void RenderFrameHostImpl::OpenURL(const FrameHostMsg_OpenURL_Params& params) {
+ OnOpenURL(params);
+}
+
+void RenderFrameHostImpl::Stop() {
+ Send(new FrameMsg_Stop(routing_id_));
+}
+
void RenderFrameHostImpl::DispatchBeforeUnload(bool for_cross_site_transition) {
- // TODO(creis): Support subframes.
- if (!render_view_host_->IsRenderViewLive() || GetParent()) {
+ // TODO(creis): Support beforeunload on subframes. For now just pretend that
+ // the handler ran and allowed the navigation to proceed.
+ if (GetParent() || !IsRenderFrameLive()) {
// We don't have a live renderer, so just skip running beforeunload.
- render_view_host_->is_waiting_for_beforeunload_ack_ = true;
- render_view_host_->unload_ack_is_for_cross_site_transition_ =
- for_cross_site_transition;
- base::TimeTicks now = base::TimeTicks::Now();
- OnBeforeUnloadACK(true, now, now);
+ frame_tree_node_->render_manager()->OnBeforeUnloadACK(
+ for_cross_site_transition, true, base::TimeTicks::Now());
return;
}
+ TRACE_EVENT_ASYNC_BEGIN0(
+ "navigation", "RenderFrameHostImpl::BeforeUnload", this);
// This may be called more than once (if the user clicks the tab close button
// several times, or if she clicks the tab close button then the browser close
// button), and we only send the message once.
- if (render_view_host_->is_waiting_for_beforeunload_ack_) {
+ if (is_waiting_for_beforeunload_ack_) {
// Some of our close messages could be for the tab, others for cross-site
// transitions. We always want to think it's for closing the tab if any
// of the messages were, since otherwise it might be impossible to close
// (if there was a cross-site "close" request pending when the user clicked
// the close button). We want to keep the "for cross site" flag only if
// both the old and the new ones are also for cross site.
- render_view_host_->unload_ack_is_for_cross_site_transition_ =
- render_view_host_->unload_ack_is_for_cross_site_transition_ &&
- for_cross_site_transition;
+ unload_ack_is_for_cross_site_transition_ =
+ unload_ack_is_for_cross_site_transition_ && for_cross_site_transition;
} else {
// Start the hang monitor in case the renderer hangs in the beforeunload
// handler.
- render_view_host_->is_waiting_for_beforeunload_ack_ = true;
- render_view_host_->unload_ack_is_for_cross_site_transition_ =
- for_cross_site_transition;
+ is_waiting_for_beforeunload_ack_ = true;
+ unload_ack_is_for_cross_site_transition_ = for_cross_site_transition;
// Increment the in-flight event count, to ensure that input events won't
// cancel the timeout timer.
render_view_host_->increment_in_flight_event_count();
@@ -857,9 +1425,13 @@ void RenderFrameHostImpl::DispatchBeforeUnload(bool for_cross_site_transition) {
}
}
+void RenderFrameHostImpl::DisownOpener() {
+ Send(new FrameMsg_DisownOpener(GetRoutingID()));
+}
+
void RenderFrameHostImpl::ExtendSelectionAndDelete(size_t before,
size_t after) {
- Send(new FrameMsg_ExtendSelectionAndDelete(routing_id_, before, after));
+ Send(new InputMsg_ExtendSelectionAndDelete(routing_id_, before, after));
}
void RenderFrameHostImpl::JavaScriptDialogClosed(
@@ -868,8 +1440,7 @@ void RenderFrameHostImpl::JavaScriptDialogClosed(
const base::string16& user_input,
bool dialog_was_suppressed) {
GetProcess()->SetIgnoreInputEvents(false);
- bool is_waiting = render_view_host_->is_waiting_for_beforeunload_ack() ||
- render_view_host_->IsWaitingForUnloadACK();
+ bool is_waiting = is_waiting_for_beforeunload_ack_ || IsWaitingForUnloadACK();
// If we are executing as part of (before)unload event handling, we don't
// want to use the regular hung_renderer_delay_ms_ if the user has agreed to
@@ -892,20 +1463,249 @@ void RenderFrameHostImpl::JavaScriptDialogClosed(
// This must be done after sending the reply since RenderView can't close
// correctly while waiting for a response.
if (is_waiting && dialog_was_suppressed)
- render_view_host_->delegate_->RendererUnresponsive(
- render_view_host_,
- render_view_host_->is_waiting_for_beforeunload_ack(),
- render_view_host_->IsWaitingForUnloadACK());
+ render_view_host_->delegate_->RendererUnresponsive(render_view_host_);
}
void RenderFrameHostImpl::NotificationClosed(int notification_id) {
cancel_notification_callbacks_.erase(notification_id);
}
-void RenderFrameHostImpl::DesktopNotificationPermissionRequestDone(
- int callback_context) {
- Send(new DesktopNotificationMsg_PermissionRequestDone(
- routing_id_, callback_context));
+// PlzNavigate
+void RenderFrameHostImpl::CommitNavigation(
+ ResourceResponse* response,
+ scoped_ptr<StreamHandle> body,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params) {
+ // TODO(clamy): Check if we have to add security checks for the browser plugin
+ // guests.
+
+ Send(new FrameMsg_CommitNavigation(
+ routing_id_, response->head, body->GetURL(),
+ common_params, commit_params));
+ // TODO(clamy): Check if we should start the throbber for non javascript urls
+ // here.
+
+ // TODO(clamy): Release the stream handle once the renderer has finished
+ // reading it.
+ stream_handle_ = body.Pass();
+}
+
+void RenderFrameHostImpl::SetUpMojoIfNeeded() {
+ if (service_registry_.get())
+ return;
+
+ service_registry_.reset(new ServiceRegistryImpl());
+ if (!GetProcess()->GetServiceRegistry())
+ return;
+
+ RegisterMojoServices();
+ RenderFrameSetupPtr setup;
+ GetProcess()->GetServiceRegistry()->ConnectToRemoteService(&setup);
+ mojo::ServiceProviderPtr service_provider;
+ setup->GetServiceProviderForFrame(routing_id_,
+ mojo::GetProxy(&service_provider));
+ service_registry_->BindRemoteServiceProvider(
+ service_provider.PassMessagePipe());
+
+#if defined(OS_ANDROID)
+ service_registry_android_.reset(
+ new ServiceRegistryAndroid(service_registry_.get()));
+#endif
+}
+
+void RenderFrameHostImpl::InvalidateMojoConnection() {
+#if defined(OS_ANDROID)
+ // The Android-specific service registry has a reference to
+ // |service_registry_| and thus must be torn down first.
+ service_registry_android_.reset();
+#endif
+
+ service_registry_.reset();
+}
+
+void RenderFrameHostImpl::PlatformNotificationPermissionRequestDone(
+ int request_id,
+ bool granted) {
+ blink::WebNotificationPermission permission =
+ granted ? blink::WebNotificationPermissionAllowed
+ : blink::WebNotificationPermissionDenied;
+
+ Send(new PlatformNotificationMsg_PermissionRequestComplete(
+ routing_id_, request_id, permission));
+}
+
+void RenderFrameHostImpl::PushPermissionRequestDone(int request_id,
+ bool allowed) {
+ Send(new PushMessagingMsg_RequestPermissionResponse(routing_id_, request_id));
+}
+
+void RenderFrameHostImpl::UpdateCrossProcessIframeAccessibility(
+ const std::map<int32, int>& node_to_frame_routing_id_map) {
+ for (const auto& iter : node_to_frame_routing_id_map) {
+ // This is the id of the accessibility node that has a child frame.
+ int32 node_id = iter.first;
+ // The routing id from either a RenderFrame or a RenderFrameProxy.
+ int frame_routing_id = iter.second;
+
+ FrameTree* frame_tree = frame_tree_node()->frame_tree();
+ FrameTreeNode* child_frame_tree_node = frame_tree->FindByRoutingID(
+ GetProcess()->GetID(), frame_routing_id);
+ if (child_frame_tree_node) {
+ FrameAccessibility::GetInstance()->AddChildFrame(
+ this, node_id, child_frame_tree_node->frame_tree_node_id());
+ }
+ }
+}
+
+void RenderFrameHostImpl::UpdateGuestFrameAccessibility(
+ const std::map<int32, int>& node_to_browser_plugin_instance_id_map) {
+ for (const auto& iter : node_to_browser_plugin_instance_id_map) {
+ // This is the id of the accessibility node that hosts a plugin.
+ int32 node_id = iter.first;
+ // The id of the browser plugin.
+ int browser_plugin_instance_id = iter.second;
+ FrameAccessibility::GetInstance()->AddGuestWebContents(
+ this, node_id, browser_plugin_instance_id);
+ }
+}
+
+void RenderFrameHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
+ Send(new FrameMsg_SetAccessibilityMode(routing_id_, mode));
+}
+
+void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
+ const base::Callback<void(ui::AXEvent, int)>& callback) {
+ accessibility_testing_callback_ = callback;
+}
+
+const ui::AXTree* RenderFrameHostImpl::GetAXTreeForTesting() {
+ return ax_tree_for_testing_.get();
+}
+
+BrowserAccessibilityManager*
+ RenderFrameHostImpl::GetOrCreateBrowserAccessibilityManager() {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view &&
+ !browser_accessibility_manager_ &&
+ !no_create_browser_accessibility_manager_for_testing_) {
+ browser_accessibility_manager_.reset(
+ view->CreateBrowserAccessibilityManager(this));
+ if (browser_accessibility_manager_)
+ UMA_HISTOGRAM_COUNTS("Accessibility.FrameEnabledCount", 1);
+ else
+ UMA_HISTOGRAM_COUNTS("Accessibility.FrameDidNotEnableCount", 1);
+ }
+ return browser_accessibility_manager_.get();
+}
+
+void RenderFrameHostImpl::ActivateFindInPageResultForAccessibility(
+ int request_id) {
+ AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode & AccessibilityModeFlagPlatform) {
+ BrowserAccessibilityManager* manager =
+ GetOrCreateBrowserAccessibilityManager();
+ if (manager)
+ manager->ActivateFindInPageResult(request_id);
+ }
+}
+
+#if defined(OS_WIN)
+
+void RenderFrameHostImpl::SetParentNativeViewAccessible(
+ gfx::NativeViewAccessible accessible_parent) {
+ RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
+ render_view_host_->GetView());
+ if (view)
+ view->SetParentNativeViewAccessible(accessible_parent);
+}
+
+gfx::NativeViewAccessible
+RenderFrameHostImpl::GetParentNativeViewAccessible() const {
+ return delegate_->GetParentNativeViewAccessible();
+}
+
+#elif defined(OS_MACOSX)
+
+void RenderFrameHostImpl::DidSelectPopupMenuItem(int selected_index) {
+ Send(new FrameMsg_SelectPopupMenuItem(routing_id_, selected_index));
+}
+
+void RenderFrameHostImpl::DidCancelPopupMenu() {
+ Send(new FrameMsg_SelectPopupMenuItem(routing_id_, -1));
+}
+
+#elif defined(OS_ANDROID)
+
+void RenderFrameHostImpl::DidSelectPopupMenuItems(
+ const std::vector<int>& selected_indices) {
+ Send(new FrameMsg_SelectPopupMenuItems(routing_id_, false, selected_indices));
+}
+
+void RenderFrameHostImpl::DidCancelPopupMenu() {
+ Send(new FrameMsg_SelectPopupMenuItems(
+ routing_id_, true, std::vector<int>()));
+}
+
+#endif
+
+void RenderFrameHostImpl::ClearPendingTransitionRequestData() {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &TransitionRequestManager::ClearPendingTransitionRequestData,
+ base::Unretained(TransitionRequestManager::GetInstance()),
+ GetProcess()->GetID(),
+ routing_id_));
+}
+
+void RenderFrameHostImpl::SetNavigationsSuspended(
+ bool suspend,
+ const base::TimeTicks& proceed_time) {
+ // This should only be called to toggle the state.
+ DCHECK(navigations_suspended_ != suspend);
+
+ navigations_suspended_ = suspend;
+ if (navigations_suspended_) {
+ TRACE_EVENT_ASYNC_BEGIN0("navigation",
+ "RenderFrameHostImpl navigation suspended", this);
+ } else {
+ TRACE_EVENT_ASYNC_END0("navigation",
+ "RenderFrameHostImpl navigation suspended", this);
+ }
+
+ if (!suspend && suspended_nav_params_) {
+ // There's navigation message params waiting to be sent. Now that we're not
+ // suspended anymore, resume navigation by sending them. If we were swapped
+ // out, we should also stop filtering out the IPC messages now.
+ SetState(RenderFrameHostImpl::STATE_DEFAULT);
+
+ DCHECK(!proceed_time.is_null());
+ suspended_nav_params_->commit_params.browser_navigation_start =
+ proceed_time;
+ Send(new FrameMsg_Navigate(routing_id_, *suspended_nav_params_));
+ suspended_nav_params_.reset();
+ }
+}
+
+void RenderFrameHostImpl::CancelSuspendedNavigations() {
+ // Clear any state if a pending navigation is canceled or preempted.
+ if (suspended_nav_params_)
+ suspended_nav_params_.reset();
+
+ TRACE_EVENT_ASYNC_END0("navigation",
+ "RenderFrameHostImpl navigation suspended", this);
+ navigations_suspended_ = false;
+}
+
+void RenderFrameHostImpl::DidUseGeolocationPermission() {
+ RenderFrameHost* top_frame = frame_tree_node()->frame_tree()->GetMainFrame();
+ GetContentClient()->browser()->RegisterPermissionUsage(
+ PERMISSION_GEOLOCATION,
+ delegate_->GetAsWebContents(),
+ GetLastCommittedURL().GetOrigin(),
+ top_frame->GetLastCommittedURL().GetOrigin());
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.h b/chromium/content/browser/frame_host/render_frame_host_impl.h
index 854a14fb39e..b1c470312f4 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -10,19 +10,37 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/site_instance_impl.h"
+#include "content/common/accessibility_mode_enums.h"
#include "content/common/content_export.h"
+#include "content/common/mojo/service_registry_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/javascript_message_type.h"
-#include "content/public/common/page_transition_types.h"
+#include "net/http/http_response_headers.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/page_transition_types.h"
+
+#if defined(OS_ANDROID)
+#include "content/browser/mojo/service_registry_android.h"
+#endif
class GURL;
+struct AccessibilityHostMsg_EventParams;
+struct AccessibilityHostMsg_FindInPageResultParams;
+struct AccessibilityHostMsg_LocationChangeParams;
struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
struct FrameHostMsg_OpenURL_Params;
+struct FrameHostMsg_BeginNavigation_Params;
struct FrameMsg_Navigate_Params;
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+struct FrameHostMsg_ShowPopup_Params;
+#endif
namespace base {
class FilePath;
@@ -40,40 +58,118 @@ class RenderFrameProxyHost;
class RenderProcessHost;
class RenderViewHostImpl;
class RenderWidgetHostImpl;
+class StreamHandle;
+class TimeoutMonitor;
+struct CommitNavigationParams;
+struct CommonNavigationParams;
struct ContextMenuParams;
struct GlobalRequestID;
struct Referrer;
+struct ResourceResponse;
struct ShowDesktopNotificationHostMsgParams;
+struct TransitionLayerData;
-class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
+class CONTENT_EXPORT RenderFrameHostImpl
+ : public RenderFrameHost,
+ public BrowserAccessibilityDelegate {
public:
+ // Keeps track of the state of the RenderFrameHostImpl, particularly with
+ // respect to swap out.
+ enum RenderFrameHostImplState {
+ // The standard state for a RFH handling the communication with an active
+ // RenderFrame.
+ STATE_DEFAULT = 0,
+ // The RFH has not received the SwapOutACK yet, but the new page has
+ // committed in a different RFH. Upon reception of the SwapOutACK, the RFH
+ // will either enter STATE_SWAPPED_OUT (if it is a main frame and there are
+ // other active frames in its SiteInstance) or it will be deleted.
+ STATE_PENDING_SWAP_OUT,
+ // The RFH is swapped out and stored inside a RenderFrameProxyHost, being
+ // used as a placeholder to allow cross-process communication. Only main
+ // frames can enter this state.
+ STATE_SWAPPED_OUT,
+ };
+ // Helper function to determine whether the RFH state should contribute to the
+ // number of active frames of a SiteInstance or not.
+ static bool IsRFHStateActive(RenderFrameHostImplState rfh_state);
+
+ // An accessibility reset is only allowed to prevent very rare corner cases
+ // or race conditions where the browser and renderer get out of sync. If
+ // this happens more than this many times, kill the renderer.
+ static const int kMaxAccessibilityResets = 5;
+
static RenderFrameHostImpl* FromID(int process_id, int routing_id);
- virtual ~RenderFrameHostImpl();
+ ~RenderFrameHostImpl() override;
// RenderFrameHost
- virtual int GetRoutingID() OVERRIDE;
- virtual SiteInstance* GetSiteInstance() OVERRIDE;
- virtual RenderProcessHost* GetProcess() OVERRIDE;
- virtual RenderFrameHost* GetParent() OVERRIDE;
- virtual const std::string& GetFrameName() OVERRIDE;
- virtual bool IsCrossProcessSubframe() OVERRIDE;
- virtual GURL GetLastCommittedURL() OVERRIDE;
- virtual gfx::NativeView GetNativeView() OVERRIDE;
- virtual void ExecuteJavaScript(
- const base::string16& javascript) OVERRIDE;
- virtual void ExecuteJavaScript(
- const base::string16& javascript,
- const JavaScriptResultCallback& callback) OVERRIDE;
- virtual RenderViewHost* GetRenderViewHost() OVERRIDE;
+ int GetRoutingID() override;
+ SiteInstanceImpl* GetSiteInstance() override;
+ RenderProcessHost* GetProcess() override;
+ RenderFrameHost* GetParent() override;
+ const std::string& GetFrameName() override;
+ bool IsCrossProcessSubframe() override;
+ GURL GetLastCommittedURL() override;
+ gfx::NativeView GetNativeView() override;
+ void ExecuteJavaScript(const base::string16& javascript) override;
+ void ExecuteJavaScript(const base::string16& javascript,
+ const JavaScriptResultCallback& callback) override;
+ void ExecuteJavaScriptForTests(const base::string16& javascript) override;
+ RenderViewHost* GetRenderViewHost() override;
+ ServiceRegistry* GetServiceRegistry() override;
+ void ActivateFindInPageResultForAccessibility(int request_id) override;
// IPC::Sender
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
+ // BrowserAccessibilityDelegate
+ void AccessibilitySetFocus(int acc_obj_id) override;
+ void AccessibilityDoDefaultAction(int acc_obj_id) override;
+ void AccessibilityShowMenu(const gfx::Point& global_point) override;
+ void AccessibilityScrollToMakeVisible(int acc_obj_id,
+ const gfx::Rect& subfocus) override;
+ void AccessibilityScrollToPoint(int acc_obj_id,
+ const gfx::Point& point) override;
+ void AccessibilitySetTextSelection(int acc_obj_id,
+ int start_offset,
+ int end_offset) override;
+ void AccessibilitySetValue(int acc_obj_id, const base::string16& value)
+ override;
+ bool AccessibilityViewHasFocus() const override;
+ gfx::Rect AccessibilityGetViewBounds() const override;
+ gfx::Point AccessibilityOriginInScreen(
+ const gfx::Rect& bounds) const override;
+ void AccessibilityHitTest(const gfx::Point& point) override;
+ void AccessibilitySetAccessibilityFocus(int acc_obj_id) override;
+ void AccessibilityFatalError() override;
+ gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
+ gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
+ BrowserAccessibilityManager* AccessibilityGetChildFrame(
+ int accessibility_node_id) override;
+ BrowserAccessibility* AccessibilityGetParentFrame() override;
+
+ // Creates a RenderFrame in the renderer process. Only called for
+ // cross-process subframe navigations in --site-per-process.
+ bool CreateRenderFrame(int parent_routing_id, int proxy_routing_id);
+
+ // Returns whether the RenderFrame in the renderer process has been created
+ // and still has a connection. This is valid for all frames.
+ bool IsRenderFrameLive();
+
+ // Tracks whether the RenderFrame for this RenderFrameHost has been created in
+ // the renderer process. This is currently only used for subframes.
+ // TODO(creis): Use this for main frames as well when RVH goes away.
+ void set_render_frame_created(bool created) {
+ render_frame_created_ = created;
+ }
+ // Called for renderer-created windows to resume requests from this frame,
+ // after they are blocked in RenderWidgetHelper::CreateNewWindow.
void Init();
+
int routing_id() const { return routing_id_; }
void OnCreateChildFrame(int new_routing_id,
const std::string& frame_name);
@@ -115,26 +211,41 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
bool should_replace_current_entry);
+ // Called on the current RenderFrameHost when the network response is first
+ // receieved.
+ void OnDeferredAfterResponseStarted(
+ const GlobalRequestID& global_request_id,
+ const TransitionLayerData& transition_data);
+
// Tells the renderer that this RenderFrame is being swapped out for one in a
- // different renderer process. It should run its unload handler, move to
- // a blank document and create a RenderFrameProxy to replace the RenderFrame.
- // The renderer should preserve the Proxy object until it exits, in case we
- // come back. The renderer can exit if it has no other active RenderFrames,
- // but not until WasSwappedOut is called (when it is no longer visible).
+ // different renderer process. It should run its unload handler and move to
+ // a blank document. If |proxy| is not null, it should also create a
+ // RenderFrameProxy to replace the RenderFrame. The renderer should preserve
+ // the RenderFrameProxy object until it exits, in case we come back. The
+ // renderer can exit if it has no other active RenderFrames, but not until
+ // WasSwappedOut is called.
void SwapOut(RenderFrameProxyHost* proxy);
- void OnSwappedOut(bool timed_out);
- bool is_swapped_out() { return is_swapped_out_; }
- void set_swapped_out(bool is_swapped_out) {
- is_swapped_out_ = is_swapped_out;
+ bool is_waiting_for_beforeunload_ack() const {
+ return is_waiting_for_beforeunload_ack_;
}
- // Sets the RVH for |this| as pending shutdown. |on_swap_out| will be called
- // when the SwapOutACK is received.
- void SetPendingShutdown(const base::Closure& on_swap_out);
+ // Whether the RFH is waiting for an unload ACK from the renderer.
+ bool IsWaitingForUnloadACK() const;
+
+ // Called when either the SwapOut request has been acknowledged or has timed
+ // out.
+ void OnSwappedOut();
+
+ // Whether this RenderFrameHost has been swapped out, such that the frame is
+ // now rendered by a RenderFrameHost in a different process.
+ bool is_swapped_out() const { return rfh_state_ == STATE_SWAPPED_OUT; }
+
+ // The current state of this RFH.
+ RenderFrameHostImplState rfh_state() const { return rfh_state_; }
// Sends the given navigation message. Use this rather than sending it
// yourself since this does the internal bookkeeping described below. This
@@ -148,11 +259,47 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
// Load the specified URL; this is a shortcut for Navigate().
void NavigateToURL(const GURL& url);
+ // Treat this prospective navigation as thought it originated from the
+ // frame. Used, e.g., for a navigation request that originated from
+ // a RemoteFrame.
+ void OpenURL(const FrameHostMsg_OpenURL_Params& params);
+
+ // Stop the load in progress.
+ void Stop();
+
+ // Returns whether navigation messages are currently suspended for this
+ // RenderFrameHost. Only true during a cross-site navigation, while waiting
+ // for the onbeforeunload handler.
+ bool are_navigations_suspended() const { return navigations_suspended_; }
+
+ // Suspends (or unsuspends) any navigation messages from being sent from this
+ // RenderFrameHost. This is called when a pending RenderFrameHost is created
+ // for a cross-site navigation, because we must suspend any navigations until
+ // we hear back from the old renderer's onbeforeunload handler. Note that it
+ // is important that only one navigation event happen after calling this
+ // method with |suspend| equal to true. If |suspend| is false and there is a
+ // suspended_nav_message_, this will send the message. This function should
+ // only be called to toggle the state; callers should check
+ // are_navigations_suspended() first. If |suspend| is false, the time that the
+ // user decided the navigation should proceed should be passed as
+ // |proceed_time|.
+ void SetNavigationsSuspended(bool suspend,
+ const base::TimeTicks& proceed_time);
+
+ // Clears any suspended navigation state after a cross-site navigation is
+ // canceled or suspended. This is important if we later return to this
+ // RenderFrameHost.
+ void CancelSuspendedNavigations();
+
// Runs the beforeunload handler for this frame. |for_cross_site_transition|
// indicates whether this call is for the current frame during a cross-process
// navigation. False means we're closing the entire tab.
void DispatchBeforeUnload(bool for_cross_site_transition);
+ // Set the frame's opener to null in the renderer process in response to an
+ // action in another renderer process.
+ void DisownOpener();
+
// Deletes the current selection plus the specified number of characters
// before and after the selection or caret.
void ExtendSelectionAndDelete(size_t before, size_t after);
@@ -167,6 +314,67 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
// Called when an HTML5 notification is closed.
void NotificationClosed(int notification_id);
+ // Clears any outstanding transition request. This is called when we hear the
+ // response or commit.
+ void ClearPendingTransitionRequestData();
+
+ // Send a message to the renderer process to change the accessibility mode.
+ void SetAccessibilityMode(AccessibilityMode AccessibilityMode);
+
+ // Turn on accessibility testing. The given callback will be run
+ // every time an accessibility notification is received from the
+ // renderer process, and the accessibility tree it sent can be
+ // retrieved using GetAXTreeForTesting().
+ void SetAccessibilityCallbackForTesting(
+ const base::Callback<void(ui::AXEvent, int)>& callback);
+
+ // Returns a snapshot of the accessibility tree received from the
+ // renderer as of the last time an accessibility notification was
+ // received.
+ const ui::AXTree* GetAXTreeForTesting();
+
+ // Access the BrowserAccessibilityManager if it already exists.
+ BrowserAccessibilityManager* browser_accessibility_manager() const {
+ return browser_accessibility_manager_.get();
+ }
+
+ // If accessibility is enabled, get the BrowserAccessibilityManager for
+ // this frame, or create one if it doesn't exist yet, otherwise return
+ // NULL.
+ BrowserAccessibilityManager* GetOrCreateBrowserAccessibilityManager();
+
+ void set_no_create_browser_accessibility_manager_for_testing(bool flag) {
+ no_create_browser_accessibility_manager_for_testing_ = flag;
+ }
+
+#if defined(OS_WIN)
+ void SetParentNativeViewAccessible(
+ gfx::NativeViewAccessible accessible_parent);
+ gfx::NativeViewAccessible GetParentNativeViewAccessible() const;
+#elif defined(OS_MACOSX)
+ // Select popup menu related methods (for external popup menus).
+ void DidSelectPopupMenuItem(int selected_index);
+ void DidCancelPopupMenu();
+#elif defined(OS_ANDROID)
+ void DidSelectPopupMenuItems(const std::vector<int>& selected_indices);
+ void DidCancelPopupMenu();
+#endif
+
+ // PlzNavigate: Indicates that a navigation is ready to commit and can be
+ // handled by this RenderFrame.
+ void CommitNavigation(ResourceResponse* response,
+ scoped_ptr<StreamHandle> body,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params);
+
+ // Sets up the Mojo connection between this instance and its associated render
+ // frame if it has not yet been set up.
+ void SetUpMojoIfNeeded();
+
+ // Tears down the browser-side state relating to the Mojo connection between
+ // this instance and its associated render frame.
+ void InvalidateMojoConnection();
+
protected:
friend class RenderFrameHostFactory;
@@ -184,6 +392,8 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
friend class TestRenderFrameHost;
friend class TestRenderViewHost;
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe);
+
// IPC Message handlers.
void OnAddMessageToConsole(int32 level,
const base::string16& message,
@@ -193,18 +403,15 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
void OnFrameFocused();
void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
void OnDocumentOnLoadCompleted();
- void OnDidStartProvisionalLoadForFrame(int parent_routing_id,
- const GURL& url);
+ void OnDidStartProvisionalLoadForFrame(const GURL& url,
+ bool is_transition_navigation);
void OnDidFailProvisionalLoadWithError(
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params);
void OnDidFailLoadWithError(
const GURL& url,
int error_code,
const base::string16& error_description);
- void OnDidRedirectProvisionalLoad(int32 page_id,
- const GURL& source_url,
- const GURL& target_url);
- void OnNavigate(const IPC::Message& msg);
+ void OnDidCommitProvisionalLoad(const IPC::Message& msg);
void OnBeforeUnloadACK(
bool proceed,
const base::TimeTicks& renderer_before_unload_start_time,
@@ -221,8 +428,8 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
const base::string16& message,
bool is_reload,
IPC::Message* reply_msg);
- void OnRequestDesktopNotificationPermission(const GURL& origin,
- int callback_id);
+ void OnRequestPlatformNotificationPermission(const GURL& origin,
+ int request_id);
void OnShowDesktopNotification(
int notification_id,
const ShowDesktopNotificationHostMsgParams& params);
@@ -232,17 +439,56 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
size_t end_offset);
void OnDidAccessInitialDocument();
void OnDidDisownOpener();
- void OnUpdateTitle(int32 page_id,
- const base::string16& title,
+ void OnDidAssignPageId(int32 page_id);
+ void OnUpdateTitle(const base::string16& title,
blink::WebTextDirection title_direction);
void OnUpdateEncoding(const std::string& encoding);
+ void OnBeginNavigation(const FrameHostMsg_BeginNavigation_Params& params,
+ const CommonNavigationParams& common_params);
+ void OnAccessibilityEvents(
+ const std::vector<AccessibilityHostMsg_EventParams>& params,
+ int reset_token);
+ void OnAccessibilityLocationChanges(
+ const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
+ void OnAccessibilityFindInPageResult(
+ const AccessibilityHostMsg_FindInPageResultParams& params);
+ void OnRequestPushPermission(int request_id, bool user_gesture);
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params);
+ void OnHidePopup();
+#endif
+
+ // Registers Mojo services that this frame host makes available.
+ void RegisterMojoServices();
+
+ // Updates the state of this RenderFrameHost and clears any waiting state
+ // that is no longer relevant.
+ void SetState(RenderFrameHostImplState rfh_state);
// Returns whether the given URL is allowed to commit in the current process.
// This is a more conservative check than RenderProcessHost::FilterURL, since
// it will be used to kill processes that commit unauthorized URLs.
bool CanCommitURL(const GURL& url);
- void DesktopNotificationPermissionRequestDone(int callback_context);
+ void PlatformNotificationPermissionRequestDone(int request_id, bool granted);
+
+ void PushPermissionRequestDone(int request_id, bool allowed);
+
+ // Update the the singleton FrameAccessibility instance with a map
+ // from accessibility node id to the frame routing id of a cross-process
+ // iframe.
+ void UpdateCrossProcessIframeAccessibility(
+ const std::map<int32, int>& node_to_frame_routing_id_map);
+
+ // Update the the singleton FrameAccessibility instance with a map
+ // from accessibility node id to the browser plugin instance id of a
+ // guest WebContents.
+ void UpdateGuestFrameAccessibility(
+ const std::map<int32, int>& node_to_browser_plugin_instance_id_map);
+
+ // Informs the content client that geolocation permissions were used.
+ void DidUseGeolocationPermission();
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each
@@ -288,11 +534,82 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
std::map<int, base::Closure> cancel_notification_callbacks_;
int routing_id_;
- bool is_swapped_out_;
+
+ // The current state of this RenderFrameHost.
+ RenderFrameHostImplState rfh_state_;
+
+ // Tracks whether the RenderFrame for this RenderFrameHost has been created in
+ // the renderer process. Currently only used for subframes.
+ // TODO(creis): Use this for main frames as well when RVH goes away.
+ bool render_frame_created_;
+
+ // Whether we should buffer outgoing Navigate messages rather than sending
+ // them. This will be true when a RenderFrameHost is created for a cross-site
+ // request, until we hear back from the onbeforeunload handler of the old
+ // RenderFrameHost.
+ bool navigations_suspended_;
+
+ // We only buffer the params for a suspended navigation while this RFH is the
+ // pending RenderFrameHost of a RenderFrameHostManager. There will only ever
+ // be one suspended navigation, because RenderFrameHostManager will destroy
+ // the pending RenderFrameHost and create a new one if a second navigation
+ // occurs.
+ scoped_ptr<FrameMsg_Navigate_Params> suspended_nav_params_;
// When the last BeforeUnload message was sent.
base::TimeTicks send_before_unload_start_time_;
+ // Set to true when there is a pending FrameMsg_ShouldClose message. This
+ // ensures we don't spam the renderer with multiple beforeunload requests.
+ // When either this value or IsWaitingForUnloadACK is true, the value of
+ // unload_ack_is_for_cross_site_transition_ indicates whether this is for a
+ // cross-site transition or a tab close attempt.
+ // TODO(clamy): Remove this boolean and add one more state to the state
+ // machine.
+ bool is_waiting_for_beforeunload_ack_;
+
+ // Valid only when is_waiting_for_beforeunload_ack_ or
+ // IsWaitingForUnloadACK is true. This tells us if the unload request
+ // is for closing the entire tab ( = false), or only this RenderFrameHost in
+ // the case of a cross-site transition ( = true).
+ bool unload_ack_is_for_cross_site_transition_;
+
+ // Used to swap out or shut down this RFH when the unload event is taking too
+ // long to execute, depending on the number of active frames in the
+ // SiteInstance.
+ scoped_ptr<TimeoutMonitor> swapout_event_monitor_timeout_;
+
+ scoped_ptr<ServiceRegistryImpl> service_registry_;
+
+#if defined(OS_ANDROID)
+ scoped_ptr<ServiceRegistryAndroid> service_registry_android_;
+#endif
+
+ // The object managing the accessibility tree for this frame.
+ scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_;
+
+ // This is nonzero if we sent an accessibility reset to the renderer and
+ // we're waiting for an IPC containing this reset token (sequentially
+ // assigned) and a complete replacement accessibility tree.
+ int accessibility_reset_token_;
+
+ // A count of the number of times we needed to reset accessibility, so
+ // we don't keep trying to reset forever.
+ int accessibility_reset_count_;
+
+ // Callback when an event is received, for testing.
+ base::Callback<void(ui::AXEvent, int)> accessibility_testing_callback_;
+ // The most recently received accessibility tree - for testing only.
+ scoped_ptr<ui::AXTree> ax_tree_for_testing_;
+ // Flag to not create a BrowserAccessibilityManager, for testing. If one
+ // already exists it will still be used.
+ bool no_create_browser_accessibility_manager_for_testing_;
+
+ // PlzNavigate: Owns the stream used in navigations to store the body of the
+ // response once it has started.
+ scoped_ptr<StreamHandle> stream_handle_;
+
+ // NOTE: This must be the last member.
base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameHostImpl);
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc
index fc36df203e8..49b9495e32d 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -27,6 +27,7 @@
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
+#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_service.h"
@@ -36,29 +37,12 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/referrer.h"
#include "content/public/common/url_constants.h"
namespace content {
-RenderFrameHostManager::PendingNavigationParams::PendingNavigationParams(
- const GlobalRequestID& global_request_id,
- scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
- const std::vector<GURL>& transfer_url_chain,
- Referrer referrer,
- PageTransition page_transition,
- int render_frame_id,
- bool should_replace_current_entry)
- : global_request_id(global_request_id),
- cross_site_transferring_request(cross_site_transferring_request.Pass()),
- transfer_url_chain(transfer_url_chain),
- referrer(referrer),
- page_transition(page_transition),
- render_frame_id(render_frame_id),
- should_replace_current_entry(should_replace_current_entry) {
-}
-
-RenderFrameHostManager::PendingNavigationParams::~PendingNavigationParams() {}
-
+// static
bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) {
node->render_manager()->pending_delete_hosts_.clear();
return true;
@@ -152,9 +136,10 @@ RenderFrameProxyHost* RenderFrameHostManager::GetProxyToParent() {
return iter->second;
}
-void RenderFrameHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) {
+void RenderFrameHostManager::SetPendingWebUI(const GURL& url,
+ int bindings) {
pending_web_ui_.reset(
- delegate_->CreateWebUIForRenderManager(entry.GetURL()));
+ delegate_->CreateWebUIForRenderManager(url));
pending_and_current_web_ui_.reset();
// If we have assigned (zero or more) bindings to this NavigationEntry in the
@@ -162,8 +147,8 @@ void RenderFrameHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) {
// before. If so, note it and don't give it any bindings, to avoid a
// potential privilege escalation.
if (pending_web_ui_.get() &&
- entry.bindings() != NavigationEntryImpl::kInvalidBindings &&
- pending_web_ui_->GetBindings() != entry.bindings()) {
+ bindings != NavigationEntryImpl::kInvalidBindings &&
+ pending_web_ui_->GetBindings() != bindings) {
RecordAction(
base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
pending_web_ui_.reset();
@@ -172,9 +157,17 @@ void RenderFrameHostManager::SetPendingWebUI(const NavigationEntryImpl& entry) {
RenderFrameHostImpl* RenderFrameHostManager::Navigate(
const NavigationEntryImpl& entry) {
- TRACE_EVENT0("browser", "RenderFrameHostManager:Navigate");
+ TRACE_EVENT1("navigation", "RenderFrameHostManager:Navigate",
+ "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
// Create a pending RenderFrameHost to use for the navigation.
- RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(entry);
+ RenderFrameHostImpl* dest_render_frame_host = UpdateStateForNavigate(
+ entry.GetURL(),
+ entry.site_instance(),
+ entry.GetTransitionType(),
+ entry.restore_type() != NavigationEntryImpl::RESTORE_NONE,
+ entry.IsViewSourceMode(),
+ entry.transferred_global_request_id(),
+ entry.bindings());
if (!dest_render_frame_host)
return NULL; // We weren't able to create a pending render frame host.
@@ -182,7 +175,7 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
// that we don't show a sad tab while the dest_render_frame_host fetches
// its first page. (Bug 1145340)
if (dest_render_frame_host != render_frame_host_ &&
- !render_frame_host_->render_view_host()->IsRenderViewLive()) {
+ !render_frame_host_->IsRenderFrameLive()) {
// Note: we don't call InitRenderView here because we are navigating away
// soon anyway, and we don't have the NavigationEntry for this host.
delegate_->CreateRenderViewForRenderManager(
@@ -192,7 +185,16 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
// If the renderer crashed, then try to create a new one to satisfy this
// navigation request.
- if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) {
+ if (!dest_render_frame_host->IsRenderFrameLive()) {
+ // Instruct the destination render frame host to set up a Mojo connection
+ // with the new render frame if necessary. Note that this call needs to
+ // occur before initializing the RenderView; the flow of creating the
+ // RenderView can cause browser-side code to execute that expects the this
+ // RFH's ServiceRegistry to be initialized (e.g., if the site is a WebUI
+ // site that is handled via Mojo, then Mojo WebUI code in //chrome will
+ // add a service to this RFH's ServiceRegistry).
+ dest_render_frame_host->SetUpMojoIfNeeded();
+
// Recreate the opener chain.
int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
dest_render_frame_host->GetSiteInstance());
@@ -208,35 +210,34 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
if (dest_render_frame_host != render_frame_host_ &&
dest_render_frame_host->render_view_host()->GetView()) {
dest_render_frame_host->render_view_host()->GetView()->Hide();
- } else if (frame_tree_node_->IsMainFrame()) {
- // This is our primary renderer, notify here as we won't be calling
- // CommitPending (which does the notify). We only do this for top-level
- // frames.
+ } else {
+ // Notify here as we won't be calling CommitPending (which does the
+ // notify).
delegate_->NotifySwappedFromRenderManager(
- NULL, render_frame_host_->render_view_host());
+ NULL, render_frame_host_.get(), frame_tree_node_->IsMainFrame());
}
}
// If entry includes the request ID of a request that is being transferred,
// the destination render frame will take ownership, so release ownership of
// the request.
- if (pending_nav_params_ &&
- pending_nav_params_->global_request_id ==
+ if (cross_site_transferring_request_.get() &&
+ cross_site_transferring_request_->request_id() ==
entry.transferred_global_request_id()) {
- pending_nav_params_->cross_site_transferring_request->ReleaseRequest();
+ cross_site_transferring_request_->ReleaseRequest();
}
return dest_render_frame_host;
}
void RenderFrameHostManager::Stop() {
- render_frame_host_->render_view_host()->Stop();
+ render_frame_host_->Stop();
// If we are cross-navigating, we should stop the pending renderers. This
// will lead to a DidFailProvisionalLoad, which will properly destroy them.
if (cross_navigation_pending_) {
- pending_render_frame_host_->render_view_host()->Send(new ViewMsg_Stop(
- pending_render_frame_host_->render_view_host()->GetRoutingID()));
+ pending_render_frame_host_->Send(new FrameMsg_Stop(
+ pending_render_frame_host_->GetRoutingID()));
}
}
@@ -247,34 +248,35 @@ void RenderFrameHostManager::SetIsLoading(bool is_loading) {
}
bool RenderFrameHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
- if (!cross_navigation_pending_)
+ // If we're waiting for a close ACK, then the tab should close whether there's
+ // a navigation in progress or not. Unfortunately, we also need to check for
+ // cases that we arrive here with no navigation in progress, since there are
+ // some tab closure paths that don't set is_waiting_for_close_ack to true.
+ // TODO(creis): Clean this up in http://crbug.com/418266.
+ if (!cross_navigation_pending_ ||
+ render_frame_host_->render_view_host()->is_waiting_for_close_ack())
return true;
// We should always have a pending RFH when there's a cross-process navigation
// in progress. Sanity check this for http://crbug.com/276333.
CHECK(pending_render_frame_host_);
- // If the tab becomes unresponsive during {before}unload while doing a
+ // Unload handlers run in the background, so we should never get an
+ // unresponsiveness warning for them.
+ CHECK(!render_frame_host_->IsWaitingForUnloadACK());
+
+ // If the tab becomes unresponsive during beforeunload while doing a
// cross-site navigation, proceed with the navigation. (This assumes that
// the pending RenderFrameHost is still responsive.)
- if (render_frame_host_->render_view_host()->IsWaitingForUnloadACK()) {
- // The request has been started and paused while we're waiting for the
- // unload handler to finish. We'll pretend that it did. The pending
- // renderer will then be swapped in as part of the usual DidNavigate logic.
- // (If the unload handler later finishes, this call will be ignored because
- // the pending_nav_params_ state will already be cleaned up.)
- current_host()->OnSwappedOut(true);
- } else if (render_frame_host_->render_view_host()->
- is_waiting_for_beforeunload_ack()) {
+ if (render_frame_host_->is_waiting_for_beforeunload_ack()) {
// Haven't gotten around to starting the request, because we're still
// waiting for the beforeunload handler to finish. We'll pretend that it
// did finish, to let the navigation proceed. Note that there's a danger
// that the beforeunload handler will later finish and possibly return
// false (meaning the navigation should not proceed), but we'll ignore it
// in this case because it took too long.
- if (pending_render_frame_host_->render_view_host()->
- are_navigations_suspended()) {
- pending_render_frame_host_->render_view_host()->SetNavigationsSuspended(
+ if (pending_render_frame_host_->are_navigations_suspended()) {
+ pending_render_frame_host_->SetNavigationsSuspended(
false, base::TimeTicks::Now());
}
}
@@ -297,10 +299,9 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
// already made by ShouldCloseTabOnUnresponsiveRenderer. In that case, it
// is ok to do nothing here.
if (pending_render_frame_host_ &&
- pending_render_frame_host_->render_view_host()->
- are_navigations_suspended()) {
- pending_render_frame_host_->render_view_host()->
- SetNavigationsSuspended(false, proceed_time);
+ pending_render_frame_host_->are_navigations_suspended()) {
+ pending_render_frame_host_->SetNavigationsSuspended(false,
+ proceed_time);
}
} else {
// Current page says to cancel.
@@ -334,87 +335,86 @@ void RenderFrameHostManager::OnCrossSiteResponse(
scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
bool should_replace_current_entry) {
- // This should be called either when the pending RFH is ready to commit or
- // when we realize that the current RFH's request requires a transfer.
+ // We should only get here for transfer navigations. Most cross-process
+ // navigations can just continue and wait to run the unload handler (by
+ // swapping out) when the new navigation commits.
+ CHECK(cross_site_transferring_request.get());
+
+ // A transfer should only have come from our pending or current RFH.
+ // TODO(creis): We need to handle the case that the pending RFH has changed
+ // in the mean time, while this was being posted from the IO thread. We
+ // should probably cancel the request in that case.
DCHECK(pending_render_frame_host == pending_render_frame_host_ ||
pending_render_frame_host == render_frame_host_);
- // TODO(creis): Eventually we will want to check all navigation responses
- // here, but currently we pass information for a transfer if
- // ShouldSwapProcessesForRedirect returned true in the network stack.
- // In that case, we should set up a transfer after the unload handler runs.
- // If |cross_site_transferring_request| is NULL, we will just run the unload
- // handler and resume.
- pending_nav_params_.reset(new PendingNavigationParams(
- global_request_id, cross_site_transferring_request.Pass(),
- transfer_url_chain, referrer, page_transition,
- pending_render_frame_host->GetRoutingID(),
- should_replace_current_entry));
-
- // Run the unload handler of the current page.
- SwapOutOldPage();
+ // Store the transferring request so that we can release it if the transfer
+ // navigation matches.
+ cross_site_transferring_request_ = cross_site_transferring_request.Pass();
+
+ // Sanity check that the params are for the correct frame and process.
+ // These should match the RenderFrameHost that made the request.
+ // If it started as a cross-process navigation via OpenURL, this is the
+ // pending one. If it wasn't cross-process until the transfer, this is the
+ // current one.
+ int render_frame_id = pending_render_frame_host_ ?
+ pending_render_frame_host_->GetRoutingID() :
+ render_frame_host_->GetRoutingID();
+ DCHECK_EQ(render_frame_id, pending_render_frame_host->GetRoutingID());
+ int process_id = pending_render_frame_host_ ?
+ pending_render_frame_host_->GetProcess()->GetID() :
+ render_frame_host_->GetProcess()->GetID();
+ DCHECK_EQ(process_id, global_request_id.child_id);
+
+ // Treat the last URL in the chain as the destination and the remainder as
+ // the redirect chain.
+ CHECK(transfer_url_chain.size());
+ GURL transfer_url = transfer_url_chain.back();
+ std::vector<GURL> rest_of_chain = transfer_url_chain;
+ rest_of_chain.pop_back();
+
+ // We don't know whether the original request had |user_action| set to true.
+ // However, since we force the navigation to be in the current tab, it
+ // doesn't matter.
+ pending_render_frame_host->frame_tree_node()->navigator()->RequestTransferURL(
+ pending_render_frame_host,
+ transfer_url,
+ rest_of_chain,
+ referrer,
+ page_transition,
+ CURRENT_TAB,
+ global_request_id,
+ should_replace_current_entry,
+ true);
+
+ // The transferring request was only needed during the RequestTransferURL
+ // call, so it is safe to clear at this point.
+ cross_site_transferring_request_.reset();
}
-void RenderFrameHostManager::SwappedOut(
- RenderFrameHostImpl* render_frame_host) {
- // Make sure this is from our current RFH, and that we have a pending
- // navigation from OnCrossSiteResponse. (There may be no pending navigation
- // for data URLs that don't make network requests, for example.) If not,
- // just return early and ignore.
- if (render_frame_host != render_frame_host_ || !pending_nav_params_.get()) {
- pending_nav_params_.reset();
- return;
- }
+void RenderFrameHostManager::OnDeferredAfterResponseStarted(
+ const GlobalRequestID& global_request_id,
+ RenderFrameHostImpl* pending_render_frame_host) {
+ DCHECK(!response_started_id_.get());
- // Now that the unload handler has run, we need to either initiate the
- // pending transfer (if there is one) or resume the paused response (if not).
- // TODO(creis): The blank swapped out page is visible during this time, but
- // we can shorten this by delivering the response directly, rather than
- // forcing an identical request to be made.
- if (pending_nav_params_->cross_site_transferring_request) {
- // Sanity check that the params are for the correct frame and process.
- // These should match the RenderFrameHost that made the request.
- // If it started as a cross-process navigation via OpenURL, this is the
- // pending one. If it wasn't cross-process until the transfer, this is the
- // current one.
- int render_frame_id = pending_render_frame_host_ ?
- pending_render_frame_host_->GetRoutingID() :
- render_frame_host_->GetRoutingID();
- DCHECK_EQ(render_frame_id, pending_nav_params_->render_frame_id);
- int process_id = pending_render_frame_host_ ?
- pending_render_frame_host_->GetProcess()->GetID() :
- render_frame_host_->GetProcess()->GetID();
- DCHECK_EQ(process_id, pending_nav_params_->global_request_id.child_id);
-
- // Treat the last URL in the chain as the destination and the remainder as
- // the redirect chain.
- CHECK(pending_nav_params_->transfer_url_chain.size());
- GURL transfer_url = pending_nav_params_->transfer_url_chain.back();
- pending_nav_params_->transfer_url_chain.pop_back();
-
- // We don't know whether the original request had |user_action| set to true.
- // However, since we force the navigation to be in the current tab, it
- // doesn't matter.
- render_frame_host->frame_tree_node()->navigator()->RequestTransferURL(
- render_frame_host,
- transfer_url,
- pending_nav_params_->transfer_url_chain,
- pending_nav_params_->referrer,
- pending_nav_params_->page_transition,
- CURRENT_TAB,
- pending_nav_params_->global_request_id,
- pending_nav_params_->should_replace_current_entry,
- true);
- } else if (pending_render_frame_host_) {
- RenderProcessHostImpl* pending_process =
- static_cast<RenderProcessHostImpl*>(
- pending_render_frame_host_->GetProcess());
- pending_process->ResumeDeferredNavigation(
- pending_nav_params_->global_request_id);
- }
- pending_nav_params_.reset();
+ response_started_id_.reset(new GlobalRequestID(global_request_id));
+}
+
+void RenderFrameHostManager::ResumeResponseDeferredAtStart() {
+ DCHECK(response_started_id_.get());
+
+ RenderProcessHostImpl* process =
+ static_cast<RenderProcessHostImpl*>(render_frame_host_->GetProcess());
+ process->ResumeResponseDeferredAtStart(*response_started_id_);
+
+ render_frame_host_->ClearPendingTransitionRequestData();
+
+ response_started_id_.reset();
+}
+
+void RenderFrameHostManager::ClearNavigationTransitionData() {
+ render_frame_host_->ClearPendingTransitionRequestData();
}
void RenderFrameHostManager::DidNavigateFrame(
@@ -433,17 +433,6 @@ void RenderFrameHostManager::DidNavigateFrame(
if (render_frame_host == pending_render_frame_host_) {
// The pending cross-site navigation completed, so show the renderer.
- // If it committed without sending network requests (e.g., data URLs),
- // then we still need to swap out the old RFH first and run its unload
- // handler, only if it hasn't happened yet. OK for that to happen in the
- // background.
- if (pending_render_frame_host_->render_view_host()->
- HasPendingCrossSiteRequest() &&
- pending_render_frame_host_->render_view_host()->rvh_state() ==
- RenderViewHostImpl::STATE_DEFAULT) {
- SwapOutOldPage();
- }
-
CommitPending();
cross_navigation_pending_ = false;
} else if (render_frame_host == render_frame_host_) {
@@ -457,15 +446,24 @@ void RenderFrameHostManager::DidNavigateFrame(
}
}
-// TODO(creis): Take in RenderFrameHost instead, since frames can have openers.
-void RenderFrameHostManager::DidDisownOpener(RenderViewHost* render_view_host) {
- // Notify all swapped out hosts, including the pending RVH.
+void RenderFrameHostManager::DidDisownOpener(
+ RenderFrameHost* render_frame_host) {
+ // Notify all RenderFrameHosts but the one that notified us. This is necessary
+ // in case a process swap has occurred while the message was in flight.
for (RenderFrameProxyHostMap::iterator iter = proxy_hosts_.begin();
iter != proxy_hosts_.end();
++iter) {
DCHECK_NE(iter->second->GetSiteInstance(),
current_frame_host()->GetSiteInstance());
- iter->second->GetRenderViewHost()->DisownOpener();
+ iter->second->DisownOpener();
+ }
+
+ if (render_frame_host_.get() != render_frame_host)
+ render_frame_host_->DisownOpener();
+
+ if (pending_render_frame_host_ &&
+ pending_render_frame_host_.get() != render_frame_host) {
+ pending_render_frame_host_->DisownOpener();
}
}
@@ -490,64 +488,144 @@ void RenderFrameHostManager::RendererProcessClosing(
}
}
-void RenderFrameHostManager::SwapOutOldPage() {
- // Should only see this while we have a pending renderer or transfer.
- CHECK(cross_navigation_pending_ || pending_nav_params_.get());
+void RenderFrameHostManager::SwapOutOldFrame(
+ scoped_ptr<RenderFrameHostImpl> old_render_frame_host) {
+ TRACE_EVENT1("navigation", "RenderFrameHostManager::SwapOutOldFrame",
+ "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
// Tell the renderer to suppress any further modal dialogs so that we can swap
// it out. This must be done before canceling any current dialog, in case
// there is a loop creating additional dialogs.
// TODO(creis): Handle modal dialogs in subframe processes.
- render_frame_host_->render_view_host()->SuppressDialogsUntilSwapOut();
+ old_render_frame_host->render_view_host()->SuppressDialogsUntilSwapOut();
// Now close any modal dialogs that would prevent us from swapping out. This
// must be done separately from SwapOut, so that the PageGroupLoadDeferrer is
// no longer on the stack when we send the SwapOut message.
delegate_->CancelModalDialogsForRenderManager();
- // Create the RenderFrameProxyHost that will replace the
- // RenderFrameHost which is swapping out. If one exists, ensure it is deleted
- // from the map and not leaked.
- RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(
- render_frame_host_->GetSiteInstance()->GetId());
- if (iter != proxy_hosts_.end()) {
- delete iter->second;
- proxy_hosts_.erase(iter);
+ // If the old RFH is not live, just return as there is no further work to do.
+ // It will be deleted and there will be no proxy created.
+ int32 old_site_instance_id =
+ old_render_frame_host->GetSiteInstance()->GetId();
+ if (!old_render_frame_host->IsRenderFrameLive()) {
+ ShutdownRenderFrameProxyHostsInSiteInstance(old_site_instance_id);
+ return;
+ }
+
+ // If there are no active frames besides this one, we can delete the old
+ // RenderFrameHost once it runs its unload handler, without replacing it with
+ // a proxy.
+ size_t active_frame_count =
+ old_render_frame_host->GetSiteInstance()->active_frame_count();
+ if (active_frame_count <= 1) {
+ // Tell the old RenderFrameHost to swap out, with no proxy to replace it.
+ old_render_frame_host->SwapOut(NULL);
+ MoveToPendingDeleteHosts(old_render_frame_host.Pass());
+
+ // Also clear out any proxies from this SiteInstance, in case this was the
+ // last one keeping other proxies alive.
+ ShutdownRenderFrameProxyHostsInSiteInstance(old_site_instance_id);
+
+ return;
}
+ // Otherwise there are active views and we need a proxy for the old RFH.
+ // (There should not be one yet.)
+ CHECK(!GetRenderFrameProxyHost(old_render_frame_host->GetSiteInstance()));
RenderFrameProxyHost* proxy = new RenderFrameProxyHost(
- render_frame_host_->GetSiteInstance(), frame_tree_node_);
- proxy_hosts_[render_frame_host_->GetSiteInstance()->GetId()] = proxy;
-
- // Tell the old frame it is being swapped out. This will fire the unload
- // handler in the background (without firing the beforeunload handler a second
- // time). When the navigation completes, we will send a message to the
- // ResourceDispatcherHost, allowing the pending RVH's response to resume.
- render_frame_host_->SwapOut(proxy);
-
- // ResourceDispatcherHost has told us to run the onunload handler, which
- // means it is not a download or unsafe page, and we are going to perform the
- // navigation. Thus, we no longer need to remember that the RenderFrameHost
- // is part of a pending cross-site request.
- if (pending_render_frame_host_) {
- pending_render_frame_host_->render_view_host()->
- SetHasPendingCrossSiteRequest(false);
+ old_render_frame_host->GetSiteInstance(), frame_tree_node_);
+ CHECK(proxy_hosts_.insert(std::make_pair(old_site_instance_id, proxy)).second)
+ << "Inserting a duplicate item.";
+
+ // Tell the old RenderFrameHost to swap out and be replaced by the proxy.
+ old_render_frame_host->SwapOut(proxy);
+
+ bool is_main_frame = frame_tree_node_->IsMainFrame();
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
+ !is_main_frame) {
+ // In --site-per-process, subframes delete their RFH rather than storing it
+ // in the proxy. Schedule it for deletion once the SwapOutACK comes in.
+ // TODO(creis): This will be the default when we remove swappedout://.
+ MoveToPendingDeleteHosts(old_render_frame_host.Pass());
+ } else {
+ // We shouldn't get here for subframes, since we only swap subframes when
+ // --site-per-process is used.
+ DCHECK(is_main_frame);
+
+ // The old RenderFrameHost will stay alive inside the proxy so that existing
+ // JavaScript window references to it stay valid.
+ proxy->TakeFrameHostOwnership(old_render_frame_host.Pass());
}
}
-void RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance(
- int32 site_instance_id,
- RenderFrameHostImpl* rfh) {
- RFHPendingDeleteMap::iterator iter =
- pending_delete_hosts_.find(site_instance_id);
- if (iter != pending_delete_hosts_.end() && iter->second.get() == rfh)
- pending_delete_hosts_.erase(site_instance_id);
+void RenderFrameHostManager::MoveToPendingDeleteHosts(
+ scoped_ptr<RenderFrameHostImpl> render_frame_host) {
+ // |render_frame_host| will be deleted when its SwapOut ACK is received, or
+ // when the timer times out, or when the RFHM itself is deleted (whichever
+ // comes first).
+ pending_delete_hosts_.push_back(
+ linked_ptr<RenderFrameHostImpl>(render_frame_host.release()));
+}
+
+bool RenderFrameHostManager::IsPendingDeletion(
+ RenderFrameHostImpl* render_frame_host) {
+ for (const auto& rfh : pending_delete_hosts_) {
+ if (rfh == render_frame_host)
+ return true;
+ }
+ return false;
+}
+
+bool RenderFrameHostManager::DeleteFromPendingList(
+ RenderFrameHostImpl* render_frame_host) {
+ for (RFHPendingDeleteList::iterator iter = pending_delete_hosts_.begin();
+ iter != pending_delete_hosts_.end();
+ iter++) {
+ if (*iter == render_frame_host) {
+ pending_delete_hosts_.erase(iter);
+ return true;
+ }
+ }
+ return false;
}
void RenderFrameHostManager::ResetProxyHosts() {
STLDeleteValues(&proxy_hosts_);
}
+// PlzNavigate
+RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
+ const GURL& url,
+ ui::PageTransition transition) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ // TODO(clamy): When we handle renderer initiated navigations, make sure not
+ // to use a different process for subframes if --site-per-process is not
+ // enabled.
+
+ // Pick the right RenderFrameHost to commit the navigation.
+ // TODO(clamy): Replace the default values by the right ones.
+ RenderFrameHostImpl* render_frame_host = UpdateStateForNavigate(
+ url, NULL, transition, false, false, GlobalRequestID(),
+ NavigationEntryImpl::kInvalidBindings);
+
+ // If the renderer that needs to navigate is not live (it was just created or
+ // it crashed), initialize it.
+ if (!render_frame_host->render_view_host()->IsRenderViewLive()) {
+ // Recreate the opener chain.
+ int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
+ render_frame_host->GetSiteInstance());
+ if (!InitRenderView(render_frame_host->render_view_host(),
+ opener_route_id,
+ MSG_ROUTING_NONE,
+ frame_tree_node_->IsMainFrame())) {
+ return NULL;
+ }
+ }
+ return render_frame_host;
+}
+
void RenderFrameHostManager::Observe(
int type,
const NotificationSource& source,
@@ -564,6 +642,7 @@ void RenderFrameHostManager::Observe(
}
}
+// static
bool RenderFrameHostManager::ClearProxiesInSiteInstance(
int32 site_instance_id,
FrameTreeNode* node) {
@@ -571,26 +650,15 @@ bool RenderFrameHostManager::ClearProxiesInSiteInstance(
node->render_manager()->proxy_hosts_.find(site_instance_id);
if (iter != node->render_manager()->proxy_hosts_.end()) {
RenderFrameProxyHost* proxy = iter->second;
- // If the RVH is pending swap out, it needs to switch state to
- // pending shutdown. Otherwise it is deleted.
- if (proxy->GetRenderViewHost()->rvh_state() ==
- RenderViewHostImpl::STATE_PENDING_SWAP_OUT) {
+ // Delete the proxy. If it is for a main frame (and thus the RFH is stored
+ // in the proxy) and it was still pending swap out, move the RFH to the
+ // pending deletion list first.
+ if (node->IsMainFrame() &&
+ proxy->render_frame_host()->rfh_state() ==
+ RenderFrameHostImpl::STATE_PENDING_SWAP_OUT) {
scoped_ptr<RenderFrameHostImpl> swapped_out_rfh =
proxy->PassFrameHostOwnership();
-
- swapped_out_rfh->SetPendingShutdown(base::Bind(
- &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance,
- node->render_manager()->weak_factory_.GetWeakPtr(),
- site_instance_id,
- swapped_out_rfh.get()));
- RFHPendingDeleteMap::iterator pending_delete_iter =
- node->render_manager()->pending_delete_hosts_.find(site_instance_id);
- if (pending_delete_iter ==
- node->render_manager()->pending_delete_hosts_.end() ||
- pending_delete_iter->second.get() != swapped_out_rfh) {
- node->render_manager()->pending_delete_hosts_[site_instance_id] =
- linked_ptr<RenderFrameHostImpl>(swapped_out_rfh.release());
- }
+ node->render_manager()->MoveToPendingDeleteHosts(swapped_out_rfh.Pass());
}
delete proxy;
node->render_manager()->proxy_hosts_.erase(site_instance_id);
@@ -610,62 +678,55 @@ bool RenderFrameHostManager::ShouldTransitionCrossSite() {
}
bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
- const NavigationEntry* current_entry,
- const NavigationEntryImpl* new_entry) const {
- DCHECK(new_entry);
-
+ const GURL& current_effective_url,
+ bool current_is_view_source_mode,
+ SiteInstance* new_site_instance,
+ const GURL& new_effective_url,
+ bool new_is_view_source_mode) const {
// If new_entry already has a SiteInstance, assume it is correct. We only
// need to force a swap if it is in a different BrowsingInstance.
- if (new_entry->site_instance()) {
- return !new_entry->site_instance()->IsRelatedSiteInstance(
+ if (new_site_instance) {
+ return !new_site_instance->IsRelatedSiteInstance(
render_frame_host_->GetSiteInstance());
}
// Check for reasons to swap processes even if we are in a process model that
// doesn't usually swap (e.g., process-per-tab). Any time we return true,
// the new_entry will be rendered in a new SiteInstance AND BrowsingInstance.
-
- // We use the effective URL here, since that's what is used in the
- // SiteInstance's site and when we later call IsSameWebSite. If there is no
- // current_entry, check the current SiteInstance's site, which might already
- // be committed to a Web UI URL (such as the NTP).
BrowserContext* browser_context =
delegate_->GetControllerForRenderManager().GetBrowserContext();
- const GURL& current_url = (current_entry) ?
- SiteInstanceImpl::GetEffectiveURL(browser_context,
- current_entry->GetURL()) :
- render_frame_host_->GetSiteInstance()->GetSiteURL();
- const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
- new_entry->GetURL());
// Don't force a new BrowsingInstance for debug URLs that are handled in the
// renderer process, like javascript: or chrome://crash.
- if (IsRendererDebugURL(new_url))
+ if (IsRendererDebugURL(new_effective_url))
return false;
// For security, we should transition between processes when one is a Web UI
// page and one isn't.
- if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
- browser_context, current_url)) {
+ if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ render_frame_host_->GetProcess()->GetID()) ||
+ WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
+ browser_context, current_effective_url)) {
// If so, force a swap if destination is not an acceptable URL for Web UI.
// Here, data URLs are never allowed.
if (!WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
- browser_context, new_url)) {
+ browser_context, new_effective_url)) {
return true;
}
} else {
// Force a swap if it's a Web UI URL.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
- browser_context, new_url)) {
+ browser_context, new_effective_url)) {
return true;
}
}
- // Check with the content client as well. Important to pass current_url here,
- // which uses the SiteInstance's site if there is no current_entry.
+ // Check with the content client as well. Important to pass
+ // current_effective_url here, which uses the SiteInstance's site if there is
+ // no current_entry.
if (GetContentClient()->browser()->ShouldSwapBrowsingInstancesForNavigation(
render_frame_host_->GetSiteInstance(),
- current_url, new_url)) {
+ current_effective_url, new_effective_url)) {
return true;
}
@@ -673,8 +734,7 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
// without screwing up the session history sometimes (when navigating between
// "view-source:http://foo.com/" and "http://foo.com/", Blink doesn't treat
// it as a new navigation). So require a BrowsingInstance switch.
- if (current_entry &&
- current_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
+ if (current_is_view_source_mode != new_is_view_source_mode)
return true;
return false;
@@ -682,34 +742,90 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
bool RenderFrameHostManager::ShouldReuseWebUI(
const NavigationEntry* current_entry,
- const NavigationEntryImpl* new_entry) const {
+ const GURL& new_url) const {
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
return current_entry && web_ui_.get() &&
(WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
controller.GetBrowserContext(), current_entry->GetURL()) ==
WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
- controller.GetBrowserContext(), new_entry->GetURL()));
+ controller.GetBrowserContext(), new_url));
+}
+
+SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
+ const GURL& dest_url,
+ SiteInstance* dest_instance,
+ ui::PageTransition dest_transition,
+ bool dest_is_restore,
+ bool dest_is_view_source_mode) {
+ SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
+ SiteInstance* new_instance = current_instance;
+
+ // We do not currently swap processes for navigations in webview tag guests.
+ if (current_instance->GetSiteURL().SchemeIs(kGuestScheme))
+ return current_instance;
+
+ // Determine if we need a new BrowsingInstance for this entry. If true, this
+ // implies that it will get a new SiteInstance (and likely process), and that
+ // other tabs in the current BrowsingInstance will be unable to script it.
+ // This is used for cases that require a process swap even in the
+ // process-per-tab model, such as WebUI pages.
+ // TODO(clamy): Remove the dependency on the current entry.
+ const NavigationEntry* current_entry =
+ delegate_->GetLastCommittedNavigationEntryForRenderManager();
+ BrowserContext* browser_context =
+ delegate_->GetControllerForRenderManager().GetBrowserContext();
+ const GURL& current_effective_url = current_entry ?
+ SiteInstanceImpl::GetEffectiveURL(browser_context,
+ current_entry->GetURL()) :
+ render_frame_host_->GetSiteInstance()->GetSiteURL();
+ bool current_is_view_source_mode = current_entry ?
+ current_entry->IsViewSourceMode() : dest_is_view_source_mode;
+ bool force_swap = ShouldSwapBrowsingInstancesForNavigation(
+ current_effective_url,
+ current_is_view_source_mode,
+ dest_instance,
+ SiteInstanceImpl::GetEffectiveURL(browser_context, dest_url),
+ dest_is_view_source_mode);
+ if (ShouldTransitionCrossSite() || force_swap) {
+ new_instance = GetSiteInstanceForURL(
+ dest_url,
+ dest_instance,
+ dest_transition,
+ dest_is_restore,
+ dest_is_view_source_mode,
+ current_instance,
+ force_swap);
+ }
+
+ // If force_swap is true, we must use a different SiteInstance. If we didn't,
+ // we would have two RenderFrameHosts in the same SiteInstance and the same
+ // frame, resulting in page_id conflicts for their NavigationEntries.
+ if (force_swap)
+ CHECK_NE(new_instance, current_instance);
+ return new_instance;
}
-SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
- const NavigationEntryImpl& entry,
+SiteInstance* RenderFrameHostManager::GetSiteInstanceForURL(
+ const GURL& dest_url,
+ SiteInstance* dest_instance,
+ ui::PageTransition dest_transition,
+ bool dest_is_restore,
+ bool dest_is_view_source_mode,
SiteInstance* current_instance,
bool force_browsing_instance_swap) {
- // Determine which SiteInstance to use for navigating to |entry|.
- const GURL& dest_url = entry.GetURL();
NavigationControllerImpl& controller =
delegate_->GetControllerForRenderManager();
BrowserContext* browser_context = controller.GetBrowserContext();
// If the entry has an instance already we should use it.
- if (entry.site_instance()) {
+ if (dest_instance) {
// If we are forcing a swap, this should be in a different BrowsingInstance.
if (force_browsing_instance_swap) {
- CHECK(!entry.site_instance()->IsRelatedSiteInstance(
+ CHECK(!dest_instance->IsRelatedSiteInstance(
render_frame_host_->GetSiteInstance()));
}
- return entry.site_instance();
+ return dest_instance;
}
// If a swap is required, we need to force the SiteInstance AND
@@ -728,8 +844,8 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
// RenderViews in response to a link click.
//
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) &&
- PageTransitionCoreTypeIs(entry.GetTransitionType(),
- PAGE_TRANSITION_GENERATED)) {
+ ui::PageTransitionCoreTypeIs(
+ dest_transition, ui::PAGE_TRANSITION_GENERATED)) {
return current_instance;
}
@@ -771,7 +887,7 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
// TODO(nasko): This is the same condition as later in the function. This
// should be taken into account when refactoring this method as part of
// http://crbug.com/123007.
- if (entry.IsViewSourceMode())
+ if (dest_is_view_source_mode)
return SiteInstance::CreateForURL(browser_context, dest_url);
// If we are navigating from a blank SiteInstance to a WebUI, make sure we
@@ -789,8 +905,16 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
// In the case of session restore, as it loads all the pages immediately
// we need to set the site first, otherwise after a restore none of the
// pages would share renderers in process-per-site.
- if (entry.restore_type() != NavigationEntryImpl::RESTORE_NONE)
+ //
+ // The embedder can request some urls never to be assigned to SiteInstance
+ // through the ShouldAssignSiteForURL() content client method, so that
+ // renderers created for particular chrome urls (e.g. the chrome-native://
+ // scheme) can be reused for subsequent navigations in the same WebContents.
+ // See http://crbug.com/386542.
+ if (dest_is_restore &&
+ GetContentClient()->browser()->ShouldAssignSiteForURL(dest_url)) {
current_site_instance->SetSite(dest_url);
+ }
return current_site_instance;
}
@@ -811,18 +935,6 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
// compare against the last non-interstitial entry.
current_entry = controller.GetEntryAtOffset(-1);
}
- // If there is no last non-interstitial entry (and current_instance already
- // has a site), then we must have been opened from another tab. We want
- // to compare against the URL of the page that opened us, but we can't
- // get to it directly. The best we can do is check against the site of
- // the SiteInstance. This will be correct when we intercept links and
- // script-based navigations, but for now, it could place some pages in a
- // new process unnecessarily. We should only hit this case if a page tries
- // to open a new tab to an interstitial-inducing URL, and then navigates
- // the page to a different same-site URL. (This seems very unlikely in
- // practice.)
- const GURL& current_url = (current_entry) ? current_entry->GetURL() :
- current_instance->GetSiteURL();
// View-source URLs must use a new SiteInstance and BrowsingInstance.
// We don't need a swap when going from view-source to a debug URL like
@@ -830,7 +942,7 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
// TODO(creis): Refactor this method so this duplicated code isn't needed.
// See http://crbug.com/123007.
if (current_entry &&
- current_entry->IsViewSourceMode() != entry.IsViewSourceMode() &&
+ current_entry->IsViewSourceMode() != dest_is_view_source_mode &&
!IsRendererDebugURL(dest_url)) {
return SiteInstance::CreateForURL(browser_context, dest_url);
}
@@ -838,6 +950,8 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
// Use the current SiteInstance for same site navigations, as long as the
// process type is correct. (The URL may have been installed as an app since
// the last time we visited it.)
+ const GURL& current_url =
+ GetCurrentURLForSiteInstance(current_instance, current_entry);
if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
!current_site_instance->HasWrongProcessForURL(dest_url)) {
return current_instance;
@@ -851,6 +965,63 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForEntry(
return current_instance->GetRelatedSiteInstance(dest_url);
}
+const GURL& RenderFrameHostManager::GetCurrentURLForSiteInstance(
+ SiteInstance* current_instance, NavigationEntry* current_entry) {
+ // If this is a subframe that is potentially out of process from its parent,
+ // don't consider using current_entry's url for SiteInstance selection, since
+ // current_entry's url is for the main frame and may be in a different site
+ // than this frame.
+ // TODO(creis): Remove this when we can check the FrameNavigationEntry's url.
+ // See http://crbug.com/369654
+ if (!frame_tree_node_->IsMainFrame() &&
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
+ return frame_tree_node_->current_url();
+
+ // If there is no last non-interstitial entry (and current_instance already
+ // has a site), then we must have been opened from another tab. We want
+ // to compare against the URL of the page that opened us, but we can't
+ // get to it directly. The best we can do is check against the site of
+ // the SiteInstance. This will be correct when we intercept links and
+ // script-based navigations, but for now, it could place some pages in a
+ // new process unnecessarily. We should only hit this case if a page tries
+ // to open a new tab to an interstitial-inducing URL, and then navigates
+ // the page to a different same-site URL. (This seems very unlikely in
+ // practice.)
+ if (current_entry)
+ return current_entry->GetURL();
+ return current_instance->GetSiteURL();
+}
+
+void RenderFrameHostManager::CreateRenderFrameHostForNewSiteInstance(
+ SiteInstance* old_instance,
+ SiteInstance* new_instance,
+ bool is_main_frame) {
+ // Ensure that we have created RFHs for the new RFH's opener chain if
+ // we are staying in the same BrowsingInstance. This allows the new RFH
+ // to send cross-process script calls to its opener(s).
+ int opener_route_id = MSG_ROUTING_NONE;
+ if (new_instance->IsRelatedSiteInstance(old_instance)) {
+ opener_route_id =
+ delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
+ // Ensure that the frame tree has RenderFrameProxyHosts for the new
+ // SiteInstance in all nodes except the current one.
+ frame_tree_node_->frame_tree()->CreateProxiesForSiteInstance(
+ frame_tree_node_, new_instance);
+ }
+ }
+
+ // Create a non-swapped-out RFH with the given opener.
+ int route_id = CreateRenderFrame(
+ new_instance, opener_route_id, false, is_main_frame,
+ delegate_->IsHidden());
+ if (route_id == MSG_ROUTING_NONE) {
+ pending_render_frame_host_.reset();
+ return;
+ }
+}
+
scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
SiteInstance* site_instance,
int view_routing_id,
@@ -864,20 +1035,12 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
FrameTree* frame_tree = frame_tree_node_->frame_tree();
RenderViewHostImpl* render_view_host = NULL;
if (frame_tree_node_->IsMainFrame()) {
- render_view_host = frame_tree->CreateRenderViewHostForMainFrame(
+ render_view_host = frame_tree->CreateRenderViewHost(
site_instance, view_routing_id, frame_routing_id, swapped_out, hidden);
} else {
- render_view_host = frame_tree->GetRenderViewHostForSubFrame(site_instance);
-
- // If we haven't found a RVH for a subframe RFH, it's because we currently
- // do not create top-level RFHs for pending subframe navigations. Create
- // the RVH here for now.
- // TODO(creis): Mirror the frame tree so this check isn't necessary.
- if (!render_view_host) {
- render_view_host = frame_tree->CreateRenderViewHostForMainFrame(
- site_instance, view_routing_id, frame_routing_id, swapped_out,
- hidden);
- }
+ render_view_host = frame_tree->GetRenderViewHost(site_instance);
+
+ CHECK(render_view_host);
}
// TODO(creis): Pass hidden to RFH.
@@ -891,14 +1054,20 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
return render_frame_host.Pass();
}
-int RenderFrameHostManager::CreateRenderFrame(
- SiteInstance* instance,
- int opener_route_id,
- bool swapped_out,
- bool hidden) {
+int RenderFrameHostManager::CreateRenderFrame(SiteInstance* instance,
+ int opener_route_id,
+ bool swapped_out,
+ bool for_main_frame_navigation,
+ bool hidden) {
CHECK(instance);
DCHECK(!swapped_out || hidden); // Swapped out views should always be hidden.
+ // TODO(nasko): Remove the following CHECK once cross-site navigation no
+ // longer relies on swapped out RFH for the top-level frame.
+ if (!frame_tree_node_->IsMainFrame()) {
+ CHECK(!swapped_out);
+ }
+
scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
RenderFrameHostImpl* frame_to_announce = NULL;
int routing_id = MSG_ROUTING_NONE;
@@ -909,10 +1078,10 @@ int RenderFrameHostManager::CreateRenderFrame(
// Check if we've already created an RFH for this SiteInstance. If so, try
// to re-use the existing one, which has already been initialized. We'll
- // remove it from the list of swapped out hosts if it commits.
+ // remove it from the list of proxy hosts below if it will be active.
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
- if (proxy) {
+ if (proxy && proxy->render_frame_host()) {
routing_id = proxy->GetRenderViewHost()->GetRoutingID();
// Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
// Prevent the process from exiting while we're trying to use it.
@@ -953,16 +1122,24 @@ int RenderFrameHostManager::CreateRenderFrame(
proxy = new RenderFrameProxyHost(
new_render_frame_host->GetSiteInstance(), frame_tree_node_);
proxy_hosts_[instance->GetId()] = proxy;
- proxy->TakeFrameHostOwnership(new_render_frame_host.Pass());
proxy_routing_id = proxy->GetRoutingID();
+ if (frame_tree_node_->IsMainFrame())
+ proxy->TakeFrameHostOwnership(new_render_frame_host.Pass());
}
- bool success = InitRenderView(
- render_view_host, opener_route_id, proxy_routing_id,
- frame_tree_node_->IsMainFrame());
- if (success && frame_tree_node_->IsMainFrame()) {
- // Don't show the main frame's view until we get a DidNavigate from it.
- render_view_host->GetView()->Hide();
+ bool success = InitRenderView(render_view_host,
+ opener_route_id,
+ proxy_routing_id,
+ for_main_frame_navigation);
+ if (success) {
+ if (frame_tree_node_->IsMainFrame()) {
+ // Don't show the main frame's view until we get a DidNavigate from it.
+ render_view_host->GetView()->Hide();
+ } else if (!swapped_out) {
+ // Init the RFH, so a RenderFrame is created in the renderer.
+ DCHECK(new_render_frame_host.get());
+ success = InitRenderFrame(new_render_frame_host.get());
+ }
} else if (!swapped_out && pending_render_frame_host_) {
CancelPending();
}
@@ -981,10 +1158,27 @@ int RenderFrameHostManager::CreateRenderFrame(
return routing_id;
}
-bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host,
- int opener_route_id,
- int proxy_routing_id,
- bool for_main_frame) {
+int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
+ // A RenderFrameProxyHost should never be created in the same SiteInstance as
+ // the current RFH.
+ CHECK(instance);
+ CHECK_NE(instance, render_frame_host_->GetSiteInstance());
+
+ RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
+ if (proxy)
+ return proxy->GetRoutingID();
+
+ proxy = new RenderFrameProxyHost(instance, frame_tree_node_);
+ proxy_hosts_[instance->GetId()] = proxy;
+ proxy->InitRenderFrameProxy();
+ return proxy->GetRoutingID();
+}
+
+bool RenderFrameHostManager::InitRenderView(
+ RenderViewHostImpl* render_view_host,
+ int opener_route_id,
+ int proxy_routing_id,
+ bool for_main_frame_navigation) {
// We may have initialized this RenderViewHost for another RenderFrameHost.
if (render_view_host->IsRenderViewLive())
return true;
@@ -997,32 +1191,70 @@ bool RenderFrameHostManager::InitRenderView(RenderViewHost* render_view_host,
} else {
// Ensure that we don't create an unprivileged RenderView in a WebUI-enabled
// process unless it's swapped out.
- RenderViewHostImpl* rvh_impl =
- static_cast<RenderViewHostImpl*>(render_view_host);
- if (!rvh_impl->IsSwappedOut()) {
+ if (render_view_host->is_active()) {
CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
render_view_host->GetProcess()->GetID()));
}
}
- return delegate_->CreateRenderViewForRenderManager(
- render_view_host, opener_route_id, proxy_routing_id, for_main_frame);
+ return delegate_->CreateRenderViewForRenderManager(render_view_host,
+ opener_route_id,
+ proxy_routing_id,
+ for_main_frame_navigation);
+}
+
+bool RenderFrameHostManager::InitRenderFrame(
+ RenderFrameHostImpl* render_frame_host) {
+ if (render_frame_host->IsRenderFrameLive())
+ return true;
+
+ int parent_routing_id = MSG_ROUTING_NONE;
+ int proxy_routing_id = MSG_ROUTING_NONE;
+ if (frame_tree_node_->parent()) {
+ parent_routing_id = frame_tree_node_->parent()->render_manager()->
+ GetRoutingIdForSiteInstance(render_frame_host->GetSiteInstance());
+ CHECK_NE(parent_routing_id, MSG_ROUTING_NONE);
+ }
+ // Check whether there is an existing proxy for this frame in this
+ // SiteInstance. If there is, the new RenderFrame needs to be able to find
+ // the proxy it is replacing, so that it can fully initialize itself.
+ // NOTE: This is the only time that a RenderFrameProxyHost can be in the same
+ // SiteInstance as its RenderFrameHost. This is only the case until the
+ // RenderFrameHost commits, at which point it will replace and delete the
+ // RenderFrameProxyHost.
+ RenderFrameProxyHost* existing_proxy =
+ GetRenderFrameProxyHost(render_frame_host->GetSiteInstance());
+ if (existing_proxy) {
+ proxy_routing_id = existing_proxy->GetRoutingID();
+ CHECK_NE(proxy_routing_id, MSG_ROUTING_NONE);
+ }
+ return delegate_->CreateRenderFrameForRenderManager(render_frame_host,
+ parent_routing_id,
+ proxy_routing_id);
+}
+
+int RenderFrameHostManager::GetRoutingIdForSiteInstance(
+ SiteInstance* site_instance) {
+ if (render_frame_host_->GetSiteInstance() == site_instance)
+ return render_frame_host_->GetRoutingID();
+
+ RenderFrameProxyHostMap::iterator iter =
+ proxy_hosts_.find(site_instance->GetId());
+ if (iter != proxy_hosts_.end())
+ return iter->second->GetRoutingID();
+
+ return MSG_ROUTING_NONE;
}
void RenderFrameHostManager::CommitPending() {
+ TRACE_EVENT1("navigation", "RenderFrameHostManager::CommitPending",
+ "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
// First check whether we're going to want to focus the location bar after
// this commit. We do this now because the navigation hasn't formally
// committed yet, so if we've already cleared |pending_web_ui_| the call chain
// this triggers won't be able to figure out what's going on.
bool will_focus_location_bar = delegate_->FocusLocationBarByDefault();
- // We expect SwapOutOldPage to have canceled any modal dialogs and told the
- // renderer to suppress any further dialogs until it is swapped out. However,
- // crash reports indicate that it's still possible for modal dialogs to exist
- // at this point, which poses a risk if we delete their RenderViewHost below.
- // Cancel them again to be safe. http://crbug.com/324320.
- delegate_->CancelModalDialogsForRenderManager();
-
// Next commit the Web UI, if any. Either replace |web_ui_| with
// |pending_web_ui_|, or clear |web_ui_| if there is no pending WebUI, or
// leave |web_ui_| as is if reusing it.
@@ -1051,8 +1283,6 @@ void RenderFrameHostManager::CommitPending() {
render_frame_host_->render_view_host()->GetView() &&
render_frame_host_->render_view_host()->GetView()->HasFocus();
- // TODO(creis): As long as show/hide are on RVH, we don't want to do them for
- // subframe navigations or they'll interfere with the top-level page.
bool is_main_frame = frame_tree_node_->IsMainFrame();
// Swap in the pending frame and make it active. Also ensure the FrameTree
@@ -1065,33 +1295,27 @@ void RenderFrameHostManager::CommitPending() {
// The process will no longer try to exit, so we can decrement the count.
render_frame_host_->GetProcess()->RemovePendingView();
- // If the view is gone, then this RenderViewHost died while it was hidden.
- // We ignored the RenderProcessGone call at the time, so we should send it now
- // to make sure the sad tab shows up, etc.
- if (!render_frame_host_->render_view_host()->GetView()) {
+ // Show the new view (or a sad tab) if necessary.
+ bool new_rfh_has_view = !!render_frame_host_->render_view_host()->GetView();
+ if (!delegate_->IsHidden() && new_rfh_has_view) {
+ // In most cases, we need to show the new view.
+ render_frame_host_->render_view_host()->GetView()->Show();
+ }
+ if (!new_rfh_has_view) {
+ // If the view is gone, then this RenderViewHost died while it was hidden.
+ // We ignored the RenderProcessGone call at the time, so we should send it
+ // now to make sure the sad tab shows up, etc.
+ DCHECK(!render_frame_host_->IsRenderFrameLive());
+ DCHECK(!render_frame_host_->render_view_host()->IsRenderViewLive());
delegate_->RenderProcessGoneFromRenderManager(
render_frame_host_->render_view_host());
- } else if (!delegate_->IsHidden()) {
- render_frame_host_->render_view_host()->GetView()->Show();
}
- // If the old view is live and top-level, hide it now that the new one is
- // visible.
- int32 old_site_instance_id =
- old_render_frame_host->GetSiteInstance()->GetId();
- if (old_render_frame_host->render_view_host()->GetView()) {
- if (is_main_frame) {
- old_render_frame_host->render_view_host()->GetView()->Hide();
- old_render_frame_host->render_view_host()->WasSwappedOut(base::Bind(
- &RenderFrameHostManager::ClearPendingShutdownRFHForSiteInstance,
- weak_factory_.GetWeakPtr(),
- old_site_instance_id,
- old_render_frame_host.get()));
- } else {
- // TODO(creis): We'll need to set this back to false if we navigate back.
- old_render_frame_host->set_swapped_out(true);
- }
- }
+ // For top-level frames, also hide the old RenderViewHost's view.
+ // TODO(creis): As long as show/hide are on RVH, we don't want to hide on
+ // subframe navigations or we will interfere with the top-level frame.
+ if (is_main_frame && old_render_frame_host->render_view_host()->GetView())
+ old_render_frame_host->render_view_host()->GetView()->Hide();
// Make sure the size is up to date. (Fix for bug 1079768.)
delegate_->UpdateRenderViewSizeForRenderManager();
@@ -1105,82 +1329,47 @@ void RenderFrameHostManager::CommitPending() {
// Notify that we've swapped RenderFrameHosts. We do this before shutting down
// the RFH so that we can clean up RendererResources related to the RFH first.
- // TODO(creis): Only do this on top-level RFHs for now, and later update it to
- // pass the RFHs.
- if (is_main_frame) {
- delegate_->NotifySwappedFromRenderManager(
- old_render_frame_host->render_view_host(),
- render_frame_host_->render_view_host());
- }
-
- // If the old RFH is not live, just return as there is no work to do.
- if (!old_render_frame_host->render_view_host()->IsRenderViewLive()) {
- return;
- }
+ delegate_->NotifySwappedFromRenderManager(
+ old_render_frame_host.get(), render_frame_host_.get(), is_main_frame);
+
+ // Swap out the old frame now that the new one is visible.
+ // This will swap it out and then put it on the proxy list (if there are other
+ // active views in its SiteInstance) or schedule it for deletion when the swap
+ // out ack arrives (or immediately if the process isn't live).
+ // In the --site-per-process case, old subframe RHFs are not kept alive inside
+ // the proxy.
+ SwapOutOldFrame(old_render_frame_host.Pass());
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
+ !is_main_frame) {
+ // If this is a subframe, it should have a CrossProcessFrameConnector
+ // created already. Use it to link the new RFH's view to the proxy that
+ // belongs to the parent frame's SiteInstance.
+ // Note: We do this after swapping out the old RFH because that may create
+ // the proxy we're looking for.
+ RenderFrameProxyHost* proxy_to_parent = GetProxyToParent();
+ if (proxy_to_parent) {
+ proxy_to_parent->SetChildRWHView(
+ render_frame_host_->render_view_host()->GetView());
+ }
- // If the old RFH is live, we are swapping it out and should keep track of
- // it in case we navigate back to it, or it is waiting for the unload event
- // to execute in the background.
- // TODO(creis): Swap out the subframe in --site-per-process.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
- DCHECK(old_render_frame_host->is_swapped_out() ||
- !RenderViewHostImpl::IsRVHStateActive(
- old_render_frame_host->render_view_host()->rvh_state()));
-
- // If the RenderViewHost backing the RenderFrameHost is pending shutdown,
- // the RenderFrameHost should be put in the map of RenderFrameHosts pending
- // shutdown. Otherwise, it is stored in the map of proxy hosts.
- if (old_render_frame_host->render_view_host()->rvh_state() ==
- RenderViewHostImpl::STATE_PENDING_SHUTDOWN) {
- // The proxy for this RenderFrameHost is created when sending the
- // SwapOut message, so check if it already exists and delete it.
+ // Since the new RenderFrameHost is now committed, there must be no proxies
+ // for its SiteInstance. Delete any existing ones.
RenderFrameProxyHostMap::iterator iter =
- proxy_hosts_.find(old_site_instance_id);
+ proxy_hosts_.find(render_frame_host_->GetSiteInstance()->GetId());
if (iter != proxy_hosts_.end()) {
delete iter->second;
proxy_hosts_.erase(iter);
}
- RFHPendingDeleteMap::iterator pending_delete_iter =
- pending_delete_hosts_.find(old_site_instance_id);
- if (pending_delete_iter == pending_delete_hosts_.end() ||
- pending_delete_iter->second.get() != old_render_frame_host) {
- pending_delete_hosts_[old_site_instance_id] =
- linked_ptr<RenderFrameHostImpl>(old_render_frame_host.release());
- }
- } else {
- // Capture the active view count on the old RFH SiteInstance, since the
- // ownership will be passed into the proxy and the pointer will be invalid.
- int active_view_count =
- static_cast<SiteInstanceImpl*>(old_render_frame_host->GetSiteInstance())
- ->active_view_count();
-
- RenderFrameProxyHostMap::iterator iter =
- proxy_hosts_.find(old_site_instance_id);
- CHECK(iter != proxy_hosts_.end());
- iter->second->TakeFrameHostOwnership(old_render_frame_host.Pass());
-
- // If there are no active views in this SiteInstance, it means that
- // this RFH was the last active one in the SiteInstance. Now that we
- // know that all RFHs are swapped out, we can delete all the RFHs and RVHs
- // in this SiteInstance.
- if (!active_view_count) {
- ShutdownRenderFrameHostsInSiteInstance(old_site_instance_id);
- } else {
- // If this is a subframe, it should have a CrossProcessFrameConnector
- // created already and we just need to link it to the proper view in the
- // new process.
- if (!is_main_frame) {
- RenderFrameProxyHost* proxy = GetProxyToParent();
- if (proxy) {
- proxy->SetChildRWHView(
- render_frame_host_->render_view_host()->GetView());
- }
- }
- }
}
+
+ // After all is done, there must never be a proxy in the list which has the
+ // same SiteInstance as the current RenderFrameHost.
+ CHECK(proxy_hosts_.find(render_frame_host_->GetSiteInstance()->GetId()) ==
+ proxy_hosts_.end());
}
-void RenderFrameHostManager::ShutdownRenderFrameHostsInSiteInstance(
+void RenderFrameHostManager::ShutdownRenderFrameProxyHostsInSiteInstance(
int32 site_instance_id) {
// First remove any swapped out RFH for this SiteInstance from our own list.
ClearProxiesInSiteInstance(site_instance_id, frame_tree_node_);
@@ -1209,7 +1398,13 @@ void RenderFrameHostManager::ShutdownRenderFrameHostsInSiteInstance(
}
RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
- const NavigationEntryImpl& entry) {
+ const GURL& url,
+ SiteInstance* instance,
+ ui::PageTransition transition,
+ bool is_restore,
+ bool is_view_source_mode,
+ const GlobalRequestID& transferred_request_id,
+ int bindings) {
// If we are currently navigating cross-process, we want to get back to normal
// and then navigate as usual.
if (cross_navigation_pending_) {
@@ -1218,34 +1413,21 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
cross_navigation_pending_ = false;
}
- // render_frame_host_'s SiteInstance and new_instance will not be deleted
- // before the end of this method, so we don't have to worry about their ref
- // counts dropping to zero.
SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
- SiteInstance* new_instance = current_instance;
+ scoped_refptr<SiteInstance> new_instance = GetSiteInstanceForNavigation(
+ url, instance, transition, is_restore, is_view_source_mode);
- // We do not currently swap processes for navigations in webview tag guests.
- bool is_guest_scheme = current_instance->GetSiteURL().SchemeIs(kGuestScheme);
-
- // Determine if we need a new BrowsingInstance for this entry. If true, this
- // implies that it will get a new SiteInstance (and likely process), and that
- // other tabs in the current BrowsingInstance will be unable to script it.
- // This is used for cases that require a process swap even in the
- // process-per-tab model, such as WebUI pages.
const NavigationEntry* current_entry =
delegate_->GetLastCommittedNavigationEntryForRenderManager();
- bool force_swap = !is_guest_scheme &&
- ShouldSwapBrowsingInstancesForNavigation(current_entry, &entry);
- if (!is_guest_scheme && (ShouldTransitionCrossSite() || force_swap))
- new_instance = GetSiteInstanceForEntry(entry, current_instance, force_swap);
- // If force_swap is true, we must use a different SiteInstance. If we didn't,
- // we would have two RenderFrameHosts in the same SiteInstance and the same
- // frame, resulting in page_id conflicts for their NavigationEntries.
- if (force_swap)
- CHECK_NE(new_instance, current_instance);
+ if (new_instance.get() != current_instance) {
+ TRACE_EVENT_INSTANT2(
+ "navigation",
+ "RenderFrameHostManager::UpdateStateForNavigate:New SiteInstance",
+ TRACE_EVENT_SCOPE_THREAD,
+ "current_instance id", current_instance->GetId(),
+ "new_instance id", new_instance->GetId());
- if (new_instance != current_instance) {
// New SiteInstance: create a pending RFH to navigate.
DCHECK(!cross_navigation_pending_);
@@ -1255,26 +1437,15 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
// It must also happen after the above conditional call to CancelPending(),
// otherwise CancelPending may clear the pending_web_ui_ and the page will
// not have its bindings set appropriately.
- SetPendingWebUI(entry);
-
- // Ensure that we have created RFHs for the new RFH's opener chain if
- // we are staying in the same BrowsingInstance. This allows the pending RFH
- // to send cross-process script calls to its opener(s).
- int opener_route_id = MSG_ROUTING_NONE;
- if (new_instance->IsRelatedSiteInstance(current_instance)) {
- opener_route_id =
- delegate_->CreateOpenerRenderViewsForRenderManager(new_instance);
- }
-
- // Create a non-swapped-out pending RFH with the given opener and navigate
- // it.
- int route_id = CreateRenderFrame(new_instance, opener_route_id, false,
- delegate_->IsHidden());
- if (route_id == MSG_ROUTING_NONE)
+ SetPendingWebUI(url, bindings);
+ CreateRenderFrameHostForNewSiteInstance(
+ current_instance, new_instance.get(), frame_tree_node_->IsMainFrame());
+ if (!pending_render_frame_host_.get()) {
return NULL;
+ }
// Check if our current RFH is live before we set up a transition.
- if (!render_frame_host_->render_view_host()->IsRenderViewLive()) {
+ if (!render_frame_host_->IsRenderFrameLive()) {
if (!cross_navigation_pending_) {
// The current RFH is not live. There's no reason to sit around with a
// sad tab or a newly created RFH while we wait for the pending RFH to
@@ -1290,61 +1461,65 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
}
// Otherwise, it's safe to treat this as a pending cross-site transition.
+ // We now have a pending RFH.
+ DCHECK(!cross_navigation_pending_);
+ cross_navigation_pending_ = true;
+
+ // PlzNavigate: There is no notion of transfer navigations, and the old
+ // renderer before unload handler has already run at that point, so return
+ // here.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ return pending_render_frame_host_.get();
+ }
+
// We need to wait until the beforeunload handler has run, unless we are
// transferring an existing request (in which case it has already run).
// Suspend the new render view (i.e., don't let it send the cross-site
// Navigate message) until we hear back from the old renderer's
// beforeunload handler. If the handler returns false, we'll have to
// cancel the request.
- DCHECK(!pending_render_frame_host_->render_view_host()->
- are_navigations_suspended());
- bool is_transfer =
- entry.transferred_global_request_id() != GlobalRequestID();
+ //
+ DCHECK(!pending_render_frame_host_->are_navigations_suspended());
+ bool is_transfer = transferred_request_id != GlobalRequestID();
if (is_transfer) {
// We don't need to stop the old renderer or run beforeunload/unload
// handlers, because those have already been done.
- DCHECK(pending_nav_params_->global_request_id ==
- entry.transferred_global_request_id());
+ DCHECK(cross_site_transferring_request_->request_id() ==
+ transferred_request_id);
} else {
// Also make sure the old render view stops, in case a load is in
// progress. (We don't want to do this for transfers, since it will
// interrupt the transfer with an unexpected DidStopLoading.)
- render_frame_host_->render_view_host()->Send(new ViewMsg_Stop(
- render_frame_host_->render_view_host()->GetRoutingID()));
-
- pending_render_frame_host_->render_view_host()->SetNavigationsSuspended(
- true, base::TimeTicks());
-
- // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
- // request, so that ResourceDispatcherHost will know to tell us to run the
- // old page's unload handler before it sends the response.
- // TODO(creis): This needs to be on the RFH.
- pending_render_frame_host_->render_view_host()->
- SetHasPendingCrossSiteRequest(true);
- }
-
- // We now have a pending RFH.
- DCHECK(!cross_navigation_pending_);
- cross_navigation_pending_ = true;
-
- // Unless we are transferring an existing request, we should now
- // tell the old render view to run its beforeunload handler, since it
- // doesn't otherwise know that the cross-site request is happening. This
- // will trigger a call to OnBeforeUnloadACK with the reply.
- if (!is_transfer)
+ render_frame_host_->Send(new FrameMsg_Stop(
+ render_frame_host_->GetRoutingID()));
+ pending_render_frame_host_->SetNavigationsSuspended(true,
+ base::TimeTicks());
+ // Unless we are transferring an existing request, we should now tell the
+ // old render view to run its beforeunload handler, since it doesn't
+ // otherwise know that the cross-site request is happening. This will
+ // trigger a call to OnBeforeUnloadACK with the reply.
render_frame_host_->DispatchBeforeUnload(true);
+ }
return pending_render_frame_host_.get();
}
// Otherwise the same SiteInstance can be used. Navigate render_frame_host_.
DCHECK(!cross_navigation_pending_);
- if (ShouldReuseWebUI(current_entry, &entry)) {
+
+ // It's possible to swap out the current RFH and then decide to navigate in it
+ // anyway (e.g., a cross-process navigation that redirects back to the
+ // original site). In that case, we have a proxy for the current RFH but
+ // haven't deleted it yet. The new navigation will swap it back in, so we can
+ // delete the proxy.
+ DeleteRenderFrameProxyHost(new_instance.get());
+
+ if (ShouldReuseWebUI(current_entry, url)) {
pending_web_ui_.reset();
pending_and_current_web_ui_ = web_ui_->AsWeakPtr();
} else {
- SetPendingWebUI(entry);
-
+ SetPendingWebUI(url, bindings);
// Make sure the new RenderViewHost has the right bindings.
if (pending_web_ui() &&
!render_frame_host_->GetProcess()->IsIsolatedGuest()) {
@@ -1353,15 +1528,14 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
}
}
- if (pending_web_ui() &&
- render_frame_host_->render_view_host()->IsRenderViewLive()) {
+ if (pending_web_ui() && render_frame_host_->IsRenderFrameLive()) {
pending_web_ui()->GetController()->RenderViewReused(
render_frame_host_->render_view_host());
}
// The renderer can exit view source mode when any error or cancellation
// happen. We must overwrite to recover the mode.
- if (entry.IsViewSourceMode()) {
+ if (is_view_source_mode) {
render_frame_host_->render_view_host()->Send(
new ViewMsg_EnableViewSourceMode(
render_frame_host_->render_view_host()->GetRoutingID()));
@@ -1371,6 +1545,8 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
}
void RenderFrameHostManager::CancelPending() {
+ TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
+ "FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
scoped_ptr<RenderFrameHostImpl> pending_render_frame_host =
pending_render_frame_host_.Pass();
@@ -1383,17 +1559,18 @@ void RenderFrameHostManager::CancelPending() {
// If the SiteInstance for the pending RFH is being used by others, don't
// delete the RFH, just swap it out and it can be reused at a later point.
- SiteInstanceImpl* site_instance = static_cast<SiteInstanceImpl*>(
- pending_render_frame_host->GetSiteInstance());
- if (site_instance->active_view_count() > 1) {
+ SiteInstanceImpl* site_instance =
+ pending_render_frame_host->GetSiteInstance();
+ if (site_instance->active_frame_count() > 1) {
// Any currently suspended navigations are no longer needed.
- pending_render_frame_host->render_view_host()->CancelSuspendedNavigations();
+ pending_render_frame_host->CancelSuspendedNavigations();
RenderFrameProxyHost* proxy =
new RenderFrameProxyHost(site_instance, frame_tree_node_);
proxy_hosts_[site_instance->GetId()] = proxy;
pending_render_frame_host->SwapOut(proxy);
- proxy->TakeFrameHostOwnership(pending_render_frame_host.Pass());
+ if (frame_tree_node_->IsMainFrame())
+ proxy->TakeFrameHostOwnership(pending_render_frame_host.Pass());
} else {
// We won't be coming back, so delete this one.
pending_render_frame_host.reset();
@@ -1416,11 +1593,11 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::SetRenderFrameHost(
// count top-level ones. This makes the value easier for consumers to
// interpret.
if (render_frame_host_) {
- static_cast<SiteInstanceImpl*>(render_frame_host_->GetSiteInstance())->
+ render_frame_host_->GetSiteInstance()->
IncrementRelatedActiveContentsCount();
}
if (old_render_frame_host) {
- static_cast<SiteInstanceImpl*>(old_render_frame_host->GetSiteInstance())->
+ old_render_frame_host->GetSiteInstance()->
DecrementRelatedActiveContentsCount();
}
}
@@ -1434,6 +1611,10 @@ bool RenderFrameHostManager::IsRVHOnSwappedOutList(
rvh->GetSiteInstance());
if (!proxy)
return false;
+ // If there is a proxy without RFH, it is for a subframe in the SiteInstance
+ // of |rvh|. Subframes should be ignored in this case.
+ if (!proxy->render_frame_host())
+ return false;
return IsOnSwappedOutList(proxy->render_frame_host());
}
@@ -1468,4 +1649,13 @@ RenderFrameProxyHost* RenderFrameHostManager::GetRenderFrameProxyHost(
return NULL;
}
+void RenderFrameHostManager::DeleteRenderFrameProxyHost(
+ SiteInstance* instance) {
+ RenderFrameProxyHostMap::iterator iter = proxy_hosts_.find(instance->GetId());
+ if (iter != proxy_hosts_.end()) {
+ delete iter->second;
+ proxy_hosts_.erase(iter);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.h b/chromium/content/browser/frame_host/render_frame_host_manager.h
index 35abab1668d..7394628bcbf 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_
#define CONTENT_BROWSER_FRAME_HOST_RENDER_FRAME_HOST_MANAGER_H_
+#include <list>
+
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -16,7 +18,9 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
+struct FrameMsg_Navigate_Params;
namespace content {
class BrowserContext;
@@ -27,7 +31,9 @@ class FrameTreeNode;
class NavigationControllerImpl;
class NavigationEntry;
class NavigationEntryImpl;
+class RenderFrameHost;
class RenderFrameHostDelegate;
+class RenderFrameHost;
class RenderFrameHostImpl;
class RenderFrameHostManagerTest;
class RenderFrameProxyHost;
@@ -38,8 +44,53 @@ class RenderWidgetHostView;
class TestWebContents;
class WebUIImpl;
-// Manages RenderFrameHosts for a FrameTreeNode. This class acts as a state
-// machine to make cross-process navigations in a frame possible.
+// Manages RenderFrameHosts for a FrameTreeNode. It maintains a
+// current_frame_host() which is the content currently visible to the user. When
+// a frame is told to navigate to a different web site (as determined by
+// SiteInstance), it will replace its current RenderFrameHost with a new
+// RenderFrameHost dedicated to the new SiteInstance, possibly in a new process.
+//
+// Cross-process navigation works like this:
+//
+// - RFHM::Navigate determines whether the destination is cross-site, and if so,
+// it creates a pending_render_frame_host_.
+//
+// - The pending RFH is created in the "navigations suspended" state, meaning no
+// navigation messages are sent to its renderer until the beforeunload handler
+// has a chance to run in the current RFH.
+//
+// - The current RFH runs its beforeunload handler. If it returns false, we
+// cancel all the pending logic. Otherwise we allow the pending RFH to send
+// the navigation request to its renderer.
+//
+// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
+// main resource load from the pending RFH. It creates a
+// CrossSiteResourceHandler to check whether a process transfer is needed when
+// the request is ready to commit.
+//
+// - When RDH receives a response, the BufferedResourceHandler determines
+// whether it is a navigation type that doesn't commit (e.g. download, 204 or
+// error page). If so, it sends a message to the new renderer causing it to
+// cancel the request, and the request (e.g. the download) proceeds. In this
+// case, the pending RFH will never become the current RFH, but it remains
+// until the next DidNavigate event for this WebContentsImpl.
+//
+// - After RDH receives a response and determines that it is safe and not a
+// download, the CrossSiteResourceHandler checks whether a transfer for a
+// redirect is needed. If so, it pauses the network response and starts an
+// identical navigation in a new pending RFH. When the identical request is
+// later received by RDH, the response is transferred and unpaused.
+//
+// - Otherwise, the network response commits in the pending RFH's renderer,
+// which sends a DidCommitProvisionalLoad message back to the browser process.
+//
+// - RFHM::CommitPending makes visible the new RFH, and initiates the unload
+// handler in the old RFH. The unload handler will complete in the background.
+//
+// - RenderFrameHostManager may keep the previous RFH alive as a
+// RenderFrameProxyHost, to be used (for example) if the user goes back. The
+// process only stays live if another tab is using it, but if so, the existing
+// frame relationships will be maintained.
class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
public:
// Functions implemented by our owner that we need.
@@ -51,20 +102,29 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
// There is additional complexity that some of the functions we need in
// WebContentsImpl are inherited and non-virtual. These are named with
// "RenderManager" so that the duplicate implementation of them will be clear.
+ //
+ // Functions and parameters whose description are prefixed by PlzNavigate are
+ // part of a navigation refactoring project, currently behind the
+ // enable-browser-side-navigation flag. The idea is to move the logic behind
+ // driving navigations from the renderer to the browser.
class CONTENT_EXPORT Delegate {
public:
// Initializes the given renderer if necessary and creates the view ID
// corresponding to this view host. If this method is not called and the
// process is not shared, then the WebContentsImpl will act as though the
// renderer is not running (i.e., it will render "sad tab"). This method is
- // automatically called from LoadURL. |for_main_frame| indicates whether
- // this RenderViewHost is used to render a top-level frame, so the
+ // automatically called from LoadURL. |for_main_frame_navigation| indicates
+ // whether this RenderViewHost is used to render a top-level frame, so the
// appropriate RenderWidgetHostView type is used.
virtual bool CreateRenderViewForRenderManager(
RenderViewHost* render_view_host,
int opener_route_id,
int proxy_routing_id,
- bool for_main_frame) = 0;
+ bool for_main_frame_navigation) = 0;
+ virtual bool CreateRenderFrameForRenderManager(
+ RenderFrameHost* render_frame_host,
+ int parent_routing_id,
+ int proxy_routing_id) = 0;
virtual void BeforeUnloadFiredFromRenderManager(
bool proceed, const base::TimeTicks& proceed_time,
bool* proceed_to_fire_unload) = 0;
@@ -72,8 +132,9 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
RenderViewHost* render_view_host) = 0;
virtual void UpdateRenderViewSizeForRenderManager() = 0;
virtual void CancelModalDialogsForRenderManager() = 0;
- virtual void NotifySwappedFromRenderManager(
- RenderViewHost* old_host, RenderViewHost* new_host) = 0;
+ virtual void NotifySwappedFromRenderManager(RenderFrameHost* old_host,
+ RenderFrameHost* new_host,
+ bool is_main_frame) = 0;
virtual NavigationControllerImpl&
GetControllerForRenderManager() = 0;
@@ -102,9 +163,6 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
// Focuses the location bar.
virtual void SetFocusToLocationBar(bool select_all) = 0;
- // Creates a view and sets the size for the specified RVH.
- virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) = 0;
-
// Returns true if views created for this delegate should be created in a
// hidden state.
virtual bool IsHidden() = 0;
@@ -130,7 +188,7 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
RenderViewHostDelegate* render_view_delegate,
RenderWidgetHostDelegate* render_widget_delegate,
Delegate* delegate);
- virtual ~RenderFrameHostManager();
+ ~RenderFrameHostManager() override;
// For arguments, see WebContentsImpl constructor.
void Init(BrowserContext* browser_context,
@@ -174,8 +232,8 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
}
// Sets the pending Web UI for the pending navigation, ensuring that the
- // bindings are appropriate for the given NavigationEntry.
- void SetPendingWebUI(const NavigationEntryImpl& entry);
+ // bindings are appropriate compared to |bindings|.
+ void SetPendingWebUI(const GURL& url, int bindings);
// Called when we want to instruct the renderer to navigate to the given
// navigation entry. It may create a new RenderFrameHost or re-use an existing
@@ -217,28 +275,41 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
bool should_replace_current_entry);
- // The RenderFrameHost has been swapped out, so we should resume the pending
- // network response and allow the pending RenderFrameHost to commit.
- void SwappedOut(RenderFrameHostImpl* render_frame_host);
+ // Received a response from CrossSiteResourceHandler. If the navigation
+ // specifies a transition, this is called and the navigation will not resume
+ // until ResumeResponseDeferredAtStart.
+ void OnDeferredAfterResponseStarted(
+ const GlobalRequestID& global_request_id,
+ RenderFrameHostImpl* pending_render_frame_host);
+
+ // Resume navigation paused after receiving response headers.
+ void ResumeResponseDeferredAtStart();
+
+ // Clear navigation transition data.
+ void ClearNavigationTransitionData();
// Called when a renderer's frame navigates.
void DidNavigateFrame(RenderFrameHostImpl* render_frame_host);
// Called when a renderer sets its opener to null.
- void DidDisownOpener(RenderViewHost* render_view_host);
+ void DidDisownOpener(RenderFrameHost* render_frame_host);
// Helper method to create and initialize a RenderFrameHost. If |swapped_out|
// is true, it will be initially placed on the swapped out hosts list.
- // Otherwise, it will be used for a pending cross-site navigation.
// Returns the routing id of the *view* associated with the frame.
int CreateRenderFrame(SiteInstance* instance,
int opener_route_id,
bool swapped_out,
+ bool for_main_frame_navigation,
bool hidden);
+ // Helper method to create and initialize a RenderFrameProxyHost and return
+ // its routing id.
+ int CreateRenderFrameProxy(SiteInstance* instance);
+
// Sets the passed passed interstitial as the currently showing interstitial.
// |interstitial_page| should be non NULL (use the remove_interstitial_page
// method to unset the interstitial) and no interstitial page should be set
@@ -259,9 +330,9 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
InterstitialPageImpl* interstitial_page() const { return interstitial_page_; }
// NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
// Returns whether the given RenderFrameHost (or its associated
// RenderViewHost) is on the list of swapped out RenderFrameHosts.
@@ -275,67 +346,33 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
RenderFrameProxyHost* GetRenderFrameProxyHost(
SiteInstance* instance) const;
- // Runs the unload handler in the current page, when we know that a pending
- // cross-process navigation is going to commit. We may initiate a transfer
- // to a new process after this completes or times out.
- void SwapOutOldPage();
+ // Returns whether |render_frame_host| is on the pending deletion list.
+ bool IsPendingDeletion(RenderFrameHostImpl* render_frame_host);
- // Deletes a RenderFrameHost that was pending shutdown.
- void ClearPendingShutdownRFHForSiteInstance(int32 site_instance_id,
- RenderFrameHostImpl* rfh);
+ // If |render_frame_host| is on the pending deletion list, this deletes it.
+ // Returns whether it was deleted.
+ bool DeleteFromPendingList(RenderFrameHostImpl* render_frame_host);
// Deletes any proxy hosts associated with this node. Used during destruction
// of WebContentsImpl.
void ResetProxyHosts();
+ // Returns the routing id for a RenderFrameHost or RenderFrameHostProxy
+ // that has the given SiteInstance and is associated with this
+ // RenderFrameHostManager. Returns MSG_ROUTING_NONE if none is found.
+ int GetRoutingIdForSiteInstance(SiteInstance* site_instance);
+
+ // PlzNavigate: Called when a navigation is ready to commit, to select the
+ // renderer that will commit it.
+ RenderFrameHostImpl* GetFrameHostForNavigation(const GURL& url,
+ ui::PageTransition transition);
+
private:
friend class RenderFrameHostManagerTest;
friend class TestWebContents;
- // Tracks information about a navigation while a cross-process transition is
- // in progress, in case we need to transfer it to a new RenderFrameHost.
- // When a request is being transferred, deleting the PendingNavigationParams,
- // and thus |cross_site_transferring_request|, will cancel the request being
- // transferred, unless its ReleaseRequest method has been called.
- struct PendingNavigationParams {
- PendingNavigationParams(
- const GlobalRequestID& global_request_id,
- scoped_ptr<CrossSiteTransferringRequest>
- cross_site_transferring_request,
- const std::vector<GURL>& transfer_url,
- Referrer referrer,
- PageTransition page_transition,
- int render_frame_id,
- bool should_replace_current_entry);
- ~PendingNavigationParams();
-
- // The child ID and request ID for the pending navigation. Present whether
- // |request_transfer| is NULL or not.
- GlobalRequestID global_request_id;
-
- // If a pending request needs to be transferred to another process, this
- // owns the request until it's transferred to the new process, so it will be
- // cleaned up if the navigation is cancelled. Otherwise, this is NULL.
- scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request;
-
- // If |request_transfer| is non-NULL, the values below are all set.
-
- // The first entry is the original request URL, and the last entry is the
- // destination URL to request in the new process.
- std::vector<GURL> transfer_url_chain;
-
- // This is the referrer to use for the request in the new process.
- Referrer referrer;
-
- // This is the transition type for the original navigation.
- PageTransition page_transition;
-
- // This is the frame routing ID to use in RequestTransferURL.
- int render_frame_id;
-
- // This is whether the navigation should replace the current history entry.
- bool should_replace_current_entry;
- };
+ FRIEND_TEST_ALL_PREFIXES(CrossProcessFrameTreeBrowserTest,
+ CreateCrossProcessSubframeProxies);
// Used with FrameTree::ForEach to erase RenderFrameProxyHosts from a
// FrameTreeNode's RenderFrameHostManager.
@@ -347,31 +384,67 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
// switch. Can be overridden in unit tests.
bool ShouldTransitionCrossSite();
- // Returns true if for the navigation from |current_entry| to |new_entry|,
- // a new SiteInstance and BrowsingInstance should be created (even if we are
- // in a process model that doesn't usually swap). This forces a process swap
- // and severs script connections with existing tabs. Cases where this can
- // happen include transitions between WebUI and regular web pages.
- // Either of the entries may be NULL.
+ // Returns true if for the navigation from |current_effective_url| to
+ // |new_effective_url|, a new SiteInstance and BrowsingInstance should be
+ // created (even if we are in a process model that doesn't usually swap).
+ // This forces a process swap and severs script connections with existing
+ // tabs. Cases where this can happen include transitions between WebUI and
+ // regular web pages. |new_site_instance| may be null.
+ // If there is no current NavigationEntry, then |current_is_view_source_mode|
+ // should be the same as |new_is_view_source_mode|.
+ //
+ // We use the effective URL here, since that's what is used in the
+ // SiteInstance's site and when we later call IsSameWebSite. If there is no
+ // current NavigationEntry, check the current SiteInstance's site, which might
+ // already be committed to a Web UI URL (such as the NTP).
bool ShouldSwapBrowsingInstancesForNavigation(
- const NavigationEntry* current_entry,
- const NavigationEntryImpl* new_entry) const;
+ const GURL& current_effective_url,
+ bool current_is_view_source_mode,
+ SiteInstance* new_site_instance,
+ const GURL& new_effective_url,
+ bool new_is_view_source_mode) const;
// Returns true if it is safe to reuse the current WebUI when navigating from
- // |current_entry| to |new_entry|.
+ // |current_entry| to |new_url|.
bool ShouldReuseWebUI(
const NavigationEntry* current_entry,
- const NavigationEntryImpl* new_entry) const;
+ const GURL& new_url) const;
+
+ // Returns the SiteInstance to use for the navigation.
+ SiteInstance* GetSiteInstanceForNavigation(
+ const GURL& dest_url,
+ SiteInstance* dest_instance,
+ ui::PageTransition dest_transition,
+ bool dest_is_restore,
+ bool dest_is_view_source_mode);
- // Returns an appropriate SiteInstance object for the given NavigationEntry,
+ // Returns an appropriate SiteInstance object for the given |dest_url|,
// possibly reusing the current SiteInstance. If --process-per-tab is used,
// this is only called when ShouldSwapBrowsingInstancesForNavigation returns
- // true.
- SiteInstance* GetSiteInstanceForEntry(
- const NavigationEntryImpl& entry,
+ // true. |dest_instance| will be used if it is not null.
+ // This is a helper function for GetSiteInstanceForNavigation.
+ SiteInstance* GetSiteInstanceForURL(
+ const GURL& dest_url,
+ SiteInstance* dest_instance,
+ ui::PageTransition dest_transition,
+ bool dest_is_restore,
+ bool dest_is_view_source_mode,
SiteInstance* current_instance,
bool force_browsing_instance_swap);
+ // Determines the appropriate url to use as the current url for SiteInstance
+ // selection.
+ const GURL& GetCurrentURLForSiteInstance(
+ SiteInstance* current_instance,
+ NavigationEntry* current_entry);
+
+ // Creates a new RenderFrameHostImpl for the |new_instance| while respecting
+ // the opener route if needed and stores it in pending_render_frame_host_.
+ void CreateRenderFrameHostForNewSiteInstance(
+ SiteInstance* old_instance,
+ SiteInstance* new_instance,
+ bool is_main_frame);
+
// Creates a RenderFrameHost and corresponding RenderViewHost if necessary.
scoped_ptr<RenderFrameHostImpl> CreateRenderFrameHost(SiteInstance* instance,
int view_routing_id,
@@ -386,20 +459,34 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
// initialized for another RenderFrameHost.
// TODO(creis): opener_route_id is currently for the RenderViewHost but should
// be for the RenderFrame, since frames can have openers.
- bool InitRenderView(RenderViewHost* render_view_host,
+ bool InitRenderView(RenderViewHostImpl* render_view_host,
int opener_route_id,
int proxy_routing_id,
- bool for_main_frame);
+ bool for_main_frame_navigation);
+
+ // Initialization for RenderFrameHost uses the same sequence as InitRenderView
+ // above.
+ bool InitRenderFrame(RenderFrameHostImpl* render_frame_host);
// Sets the pending RenderFrameHost/WebUI to be the active one. Note that this
// doesn't require the pending render_frame_host_ pointer to be non-NULL,
// since there could be Web UI switching as well. Call this for every commit.
void CommitPending();
- // Shutdown all RenderFrameHosts in a SiteInstance. This is called to shutdown
- // frames when all the frames in a SiteInstance are confirmed to be swapped
- // out.
- void ShutdownRenderFrameHostsInSiteInstance(int32 site_instance_id);
+ // Runs the unload handler in the old RenderFrameHost, after the new
+ // RenderFrameHost has committed. |old_render_frame_host| will either be
+ // deleted or put on the pending delete list during this call.
+ void SwapOutOldFrame(scoped_ptr<RenderFrameHostImpl> old_render_frame_host);
+
+ // Holds |render_frame_host| until it can be deleted when its swap out ACK
+ // arrives.
+ void MoveToPendingDeleteHosts(
+ scoped_ptr<RenderFrameHostImpl> render_frame_host);
+
+ // Shutdown all RenderFrameProxyHosts in a SiteInstance. This is called to
+ // shutdown frames when all the frames in a SiteInstance are confirmed to be
+ // swapped out.
+ void ShutdownRenderFrameProxyHostsInSiteInstance(int32 site_instance_id);
// Helper method to terminate the pending RenderViewHost.
void CancelPending();
@@ -410,12 +497,22 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
scoped_ptr<RenderFrameHostImpl> render_frame_host);
RenderFrameHostImpl* UpdateStateForNavigate(
- const NavigationEntryImpl& entry);
+ const GURL& url,
+ SiteInstance* instance,
+ ui::PageTransition transition,
+ bool is_restore,
+ bool is_view_source_mode,
+ const GlobalRequestID& transferred_request_id,
+ int bindings);
// Called when a renderer process is starting to close. We should not
// schedule new navigations in its swapped out RenderFrameHosts after this.
void RendererProcessClosing(RenderProcessHost* render_process_host);
+ // Helper method to delete a RenderFrameProxyHost from the list, if one exists
+ // for the given |instance|.
+ void DeleteRenderFrameProxyHost(SiteInstance* instance);
+
// For use in creating RenderFrameHosts.
FrameTreeNode* frame_tree_node_;
@@ -453,8 +550,14 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
// associated with the navigation.
scoped_ptr<RenderFrameHostImpl> pending_render_frame_host_;
- // Tracks information about any current pending cross-process navigation.
- scoped_ptr<PendingNavigationParams> pending_nav_params_;
+ // If a pending request needs to be transferred to another process, this
+ // owns the request until it's transferred to the new process, so it will be
+ // cleaned up if the navigation is cancelled. Otherwise, this is NULL.
+ scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request_;
+
+ // Tracks information about any navigation paused after receiving response
+ // headers.
+ scoped_ptr<GlobalRequestID> response_started_id_;
// If either of these is non-NULL, the pending navigation is to a chrome:
// page. The scoped_ptr is used if pending_web_ui_ != web_ui_, the WeakPtr is
@@ -467,10 +570,11 @@ class CONTENT_EXPORT RenderFrameHostManager : public NotificationObserver {
typedef base::hash_map<int32, RenderFrameProxyHost*> RenderFrameProxyHostMap;
RenderFrameProxyHostMap proxy_hosts_;
- // A map of RenderFrameHosts pending shutdown.
- typedef base::hash_map<int32, linked_ptr<RenderFrameHostImpl> >
- RFHPendingDeleteMap;
- RFHPendingDeleteMap pending_delete_hosts_;
+ // A list of RenderFrameHosts waiting to shut down after swapping out. We use
+ // a linked list since we expect frequent deletes and no indexed access, and
+ // because sets don't appear to support linked_ptrs.
+ typedef std::list<linked_ptr<RenderFrameHostImpl> > RFHPendingDeleteList;
+ RFHPendingDeleteList pending_delete_hosts_;
// The intersitial page currently shown if any, not own by this class
// (the InterstitialPage is self-owned, it deletes itself when hidden).
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index ad2689ea138..fcfbd2c585c 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -7,7 +7,6 @@
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
-#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -253,7 +252,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
}
// Test for crbug.com/24447. Following a cross-site link with just
-// target=_blank should not create a new SiteInstance.
+// target=_blank should not create a new SiteInstance, unless we
+// are running in --site-per-process mode.
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
DontSwapProcessWithOnlyTargetBlank) {
StartServer();
@@ -288,10 +288,14 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ("/files/title2.html",
new_shell->web_contents()->GetLastCommittedURL().path());
- // Should have the same SiteInstance.
+ // Should have the same SiteInstance unless we're in site-per-process mode.
scoped_refptr<SiteInstance> blank_site_instance(
new_shell->web_contents()->GetSiteInstance());
- EXPECT_EQ(orig_site_instance, blank_site_instance);
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess))
+ EXPECT_EQ(orig_site_instance, blank_site_instance);
+ else
+ EXPECT_NE(orig_site_instance, blank_site_instance);
}
// Test for crbug.com/24447. Following a cross-site link with rel=noreferrer
@@ -329,10 +333,14 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
EXPECT_EQ("/files/title2.html",
shell()->web_contents()->GetLastCommittedURL().path());
- // Should have the same SiteInstance.
+ // Should have the same SiteInstance unless we're in site-per-process mode.
scoped_refptr<SiteInstance> noref_site_instance(
shell()->web_contents()->GetSiteInstance());
- EXPECT_EQ(orig_site_instance, noref_site_instance);
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess))
+ EXPECT_EQ(orig_site_instance, noref_site_instance);
+ else
+ EXPECT_NE(orig_site_instance, noref_site_instance);
}
// Test for crbug.com/116192. Targeted links should still work after the
@@ -398,7 +406,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// If it navigates away to another process, the original window should
// still be able to close it (using a cross-process close message).
NavigateToURL(new_shell, cross_site_url);
- EXPECT_EQ(new_site_instance,
+ EXPECT_EQ(new_site_instance.get(),
new_shell->web_contents()->GetSiteInstance());
WebContentsDestroyedWatcher close_watcher(new_shell->web_contents());
EXPECT_TRUE(ExecuteScriptAndExtractBool(
@@ -411,9 +419,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Test that setting the opener to null in a window affects cross-process
// navigations, including those to existing entries. http://crbug.com/156669.
-// Flaky on windows: http://crbug.com/291249
-// This test also crashes under ThreadSanitizer, http://crbug.com/356758.
-#if defined(OS_WIN) || defined(THREAD_SANITIZER)
+// This test crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(THREAD_SANITIZER)
#define MAYBE_DisownOpener DISABLED_DisownOpener
#else
#define MAYBE_DisownOpener DisownOpener
@@ -443,6 +450,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
&success));
EXPECT_TRUE(success);
Shell* new_shell = new_shell_observer.GetShell();
+ EXPECT_TRUE(new_shell->web_contents()->HasOpener());
// Wait for the navigation in the new tab to finish, if it hasn't.
WaitForLoadStop(new_shell->web_contents());
@@ -459,10 +467,12 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
scoped_refptr<SiteInstance> new_site_instance(
new_shell->web_contents()->GetSiteInstance());
EXPECT_NE(orig_site_instance, new_site_instance);
+ EXPECT_TRUE(new_shell->web_contents()->HasOpener());
// Now disown the opener.
EXPECT_TRUE(ExecuteScript(new_shell->web_contents(),
"window.opener = null;"));
+ EXPECT_FALSE(new_shell->web_contents()->HasOpener());
// Go back and ensure the opener is still null.
{
@@ -476,6 +486,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
"window.domAutomationController.send(window.opener == null);",
&success));
EXPECT_TRUE(success);
+ EXPECT_FALSE(new_shell->web_contents()->HasOpener());
// Now navigate forward again (creating a new process) and check opener.
NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
@@ -485,6 +496,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
"window.domAutomationController.send(window.opener == null);",
&success));
EXPECT_TRUE(success);
+ EXPECT_FALSE(new_shell->web_contents()->HasOpener());
}
// Test that subframes can disown their openers. http://crbug.com/225528.
@@ -569,7 +581,7 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
WaitForLoadStop(new_contents);
EXPECT_EQ("/files/title2.html", new_contents->GetLastCommittedURL().path());
NavigateToURL(new_shell2, test_server()->GetURL("files/post_message.html"));
- EXPECT_EQ(orig_site_instance, new_contents->GetSiteInstance());
+ EXPECT_EQ(orig_site_instance.get(), new_contents->GetSiteInstance());
RenderFrameHostManager* new_manager =
static_cast<WebContentsImpl*>(new_contents)->GetRenderManagerForTesting();
@@ -1142,7 +1154,7 @@ class RenderViewHostDestructionObserver : public WebContentsObserver {
public:
explicit RenderViewHostDestructionObserver(WebContents* web_contents)
: WebContentsObserver(web_contents) {}
- virtual ~RenderViewHostDestructionObserver() {}
+ ~RenderViewHostDestructionObserver() override {}
void EnsureRVHGetsDestructed(RenderViewHost* rvh) {
watched_render_view_hosts_.insert(rvh);
}
@@ -1152,7 +1164,7 @@ class RenderViewHostDestructionObserver : public WebContentsObserver {
private:
// WebContentsObserver implementation:
- virtual void RenderViewDeleted(RenderViewHost* rvh) OVERRIDE {
+ void RenderViewDeleted(RenderViewHost* rvh) override {
watched_render_view_hosts_.erase(rvh);
}
@@ -1268,7 +1280,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
new_shell->web_contents()->GetLastCommittedURL().path());
// Should have the same SiteInstance.
- EXPECT_EQ(orig_site_instance, new_shell->web_contents()->GetSiteInstance());
+ EXPECT_EQ(orig_site_instance.get(),
+ new_shell->web_contents()->GetSiteInstance());
// 2. Send the second tab to a different process.
NavigateToURL(new_shell, GetCrossSiteURL("files/title1.html"));
@@ -1283,7 +1296,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
WaitForLoadStop(shell()->web_contents());
EXPECT_EQ(GetCrossSiteURL("files/title1.html"),
shell()->web_contents()->GetLastCommittedURL());
- EXPECT_EQ(new_site_instance, shell()->web_contents()->GetSiteInstance());
+ EXPECT_EQ(new_site_instance.get(),
+ shell()->web_contents()->GetSiteInstance());
}
// Ensure that renderer-side debug URLs do not cause a process swap, since they
@@ -1351,10 +1365,18 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
crash_observer2.Wait();
}
+// The test fails with Android ASAN with changes in v8 that seem unrelated.
+// See http://crbug.com/428329.
+#if defined(OS_ANDROID) && defined(THREAD_SANITIZER)
+#define MAYBE_ClearPendingWebUIOnCommit DISABLED_ClearPendingWebUIOnCommit
+#else
+#define MAYBE_ClearPendingWebUIOnCommit ClearPendingWebUIOnCommit
+#endif
// Ensure that pending_and_current_web_ui_ is cleared when a URL commits.
// Otherwise it might get picked up by InitRenderView when granting bindings
// to other RenderViewHosts. See http://crbug.com/330811.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClearPendingWebUIOnCommit) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ MAYBE_ClearPendingWebUIOnCommit) {
// Visit a WebUI page with bindings.
GURL webui_url(GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost)));
@@ -1379,7 +1401,7 @@ class RFHMProcessPerTabTest : public RenderFrameHostManagerTest {
public:
RFHMProcessPerTabTest() {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kProcessPerTab);
}
};
@@ -1462,4 +1484,27 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, WebUIGetsBindings) {
new_web_contents->GetRenderViewHost()->GetEnabledBindings());
}
+// crbug.com/424526
+// The test loads a WebUI page in rocess-per-tab mode, then navigates to a blank
+// page and then to a regular page. The bug reproduces if blank page is visited
+// in between WebUI and regular page.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ ForceSwapAfterWebUIBindings) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(switches::kProcessPerTab);
+ ASSERT_TRUE(test_server()->Start());
+
+ const GURL web_ui_url(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ NavigateToURL(shell(), web_ui_url);
+ EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ shell()->web_contents()->GetRenderProcessHost()->GetID()));
+
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ GURL regular_page_url(test_server()->GetURL("files/title2.html"));
+ NavigateToURL(shell(), regular_page_url);
+ EXPECT_FALSE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ shell()->web_contents()->GetRenderProcessHost()->GetID()));
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
index a5100dfbe4b..11c3c8a2704 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -2,13 +2,17 @@
// 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/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/histogram_tester.h"
+#include "base/time/time.h"
#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
+#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/frame_messages.h"
@@ -23,17 +27,20 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/bindings_policy.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/javascript_message_type.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_notification_tracker.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
+#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
+#include "net/base/load_flags.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/page_transition_types.h"
namespace content {
namespace {
@@ -44,32 +51,32 @@ class RenderFrameHostManagerTestWebUIControllerFactory
RenderFrameHostManagerTestWebUIControllerFactory()
: should_create_webui_(false) {
}
- virtual ~RenderFrameHostManagerTestWebUIControllerFactory() {}
+ ~RenderFrameHostManagerTestWebUIControllerFactory() override {}
void set_should_create_webui(bool should_create_webui) {
should_create_webui_ = should_create_webui;
}
// WebUIFactory implementation.
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const OVERRIDE {
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override {
if (!(should_create_webui_ && HasWebUIScheme(url)))
return NULL;
return new WebUIController(web_ui);
}
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override {
return WebUI::kNoWebUI;
}
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return HasWebUIScheme(url);
}
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return HasWebUIScheme(url);
}
@@ -82,11 +89,11 @@ class RenderFrameHostManagerTestWebUIControllerFactory
class BeforeUnloadFiredWebContentsDelegate : public WebContentsDelegate {
public:
BeforeUnloadFiredWebContentsDelegate() {}
- virtual ~BeforeUnloadFiredWebContentsDelegate() {}
+ ~BeforeUnloadFiredWebContentsDelegate() override {}
- virtual void BeforeUnloadFired(WebContents* web_contents,
- bool proceed,
- bool* proceed_to_fire_unload) OVERRIDE {
+ void BeforeUnloadFired(WebContents* web_contents,
+ bool proceed,
+ bool* proceed_to_fire_unload) override {
*proceed_to_fire_unload = proceed;
}
@@ -94,6 +101,23 @@ class BeforeUnloadFiredWebContentsDelegate : public WebContentsDelegate {
DISALLOW_COPY_AND_ASSIGN(BeforeUnloadFiredWebContentsDelegate);
};
+class CloseWebContentsDelegate : public WebContentsDelegate {
+ public:
+ CloseWebContentsDelegate() : close_called_(false) {}
+ ~CloseWebContentsDelegate() override {}
+
+ void CloseContents(WebContents* web_contents) override {
+ close_called_ = true;
+ }
+
+ bool is_closed() { return close_called_; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CloseWebContentsDelegate);
+
+ bool close_called_;
+};
+
// This observer keeps track of the last deleted RenderViewHost to avoid
// accessing it and causing use-after-free condition.
class RenderViewHostDeletedObserver : public WebContentsObserver {
@@ -105,7 +129,7 @@ class RenderViewHostDeletedObserver : public WebContentsObserver {
deleted_(false) {
}
- virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE {
+ void RenderViewDeleted(RenderViewHost* render_view_host) override {
if (render_view_host->GetProcess()->GetID() == process_id_ &&
render_view_host->GetRoutingID() == routing_id_) {
deleted_ = true;
@@ -124,6 +148,29 @@ class RenderViewHostDeletedObserver : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(RenderViewHostDeletedObserver);
};
+// This observer keeps track of the last created RenderFrameHost to allow tests
+// to ensure that no RenderFrameHost objects are created when not expected.
+class RenderFrameHostCreatedObserver : public WebContentsObserver {
+ public:
+ RenderFrameHostCreatedObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ created_(false) {
+ }
+
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
+ created_ = true;
+ }
+
+ bool created() {
+ return created_;
+ }
+
+ private:
+ bool created_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderFrameHostCreatedObserver);
+};
+
// This observer keeps track of the last deleted RenderFrameHost to avoid
// accessing it and causing use-after-free condition.
class RenderFrameHostDeletedObserver : public WebContentsObserver {
@@ -135,7 +182,7 @@ class RenderFrameHostDeletedObserver : public WebContentsObserver {
deleted_(false) {
}
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE {
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
if (render_frame_host->GetProcess()->GetID() == process_id_ &&
render_frame_host->GetRoutingID() == routing_id_) {
deleted_ = true;
@@ -154,7 +201,6 @@ class RenderFrameHostDeletedObserver : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(RenderFrameHostDeletedObserver);
};
-
// This observer is used to check whether IPC messages are being filtered for
// swapped out RenderFrameHost objects. It observes the plugin crash and favicon
// update events, which the FilterMessagesWhileSwappedOut test simulates being
@@ -167,13 +213,12 @@ class PluginFaviconMessageObserver : public WebContentsObserver {
plugin_crashed_(false),
favicon_received_(false) { }
- virtual void PluginCrashed(const base::FilePath& plugin_path,
- base::ProcessId plugin_pid) OVERRIDE {
+ void PluginCrashed(const base::FilePath& plugin_path,
+ base::ProcessId plugin_pid) override {
plugin_crashed_ = true;
}
- virtual void DidUpdateFaviconURL(
- const std::vector<FaviconURL>& candidates) OVERRIDE {
+ void DidUpdateFaviconURL(const std::vector<FaviconURL>& candidates) override {
favicon_received_ = true;
}
@@ -202,7 +247,7 @@ class FrameLifetimeConsistencyChecker : public WebContentsObserver {
RenderFrameCreated(web_contents->GetMainFrame());
}
- virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE {
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
std::pair<int, int> routing_pair =
std::make_pair(render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID());
@@ -218,7 +263,7 @@ class FrameLifetimeConsistencyChecker : public WebContentsObserver {
}
}
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE {
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override {
std::pair<int, int> routing_pair =
std::make_pair(render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID());
@@ -252,13 +297,13 @@ class FrameLifetimeConsistencyChecker : public WebContentsObserver {
class RenderFrameHostManagerTest
: public RenderViewHostImplTestHarness {
public:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
WebUIControllerFactory::RegisterFactory(&factory_);
lifetime_checker_.reset(new FrameLifetimeConsistencyChecker(contents()));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
lifetime_checker_.reset();
RenderViewHostImplTestHarness::TearDown();
WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
@@ -268,99 +313,114 @@ class RenderFrameHostManagerTest
factory_.set_should_create_webui(should_create_webui);
}
- void StartCrossSiteTransition(TestWebContents* contents) {
- std::vector<GURL> url_chain;
- contents->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
- EXPECT_TRUE(contents->cross_navigation_pending());
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
- contents->GetRenderViewHost());
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK,
- rvh->rvh_state());
- }
-
void NavigateActiveAndCommit(const GURL& url) {
- // Note: we navigate the active RenderViewHost because previous navigations
+ // Note: we navigate the active RenderFrameHost because previous navigations
// won't have committed yet, so NavigateAndCommit does the wrong thing
// for us.
- controller().LoadURL(url, Referrer(), PAGE_TRANSITION_LINK, std::string());
- TestRenderViewHost* old_rvh = test_rvh();
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ TestRenderFrameHost* old_rfh = contents()->GetMainFrame();
+ TestRenderFrameHost* active_rfh = contents()->GetPendingMainFrame()
+ ? contents()->GetPendingMainFrame()
+ : old_rfh;
// Simulate the BeforeUnload_ACK that is received from the current renderer
// for a cross-site navigation.
- if (old_rvh != active_rvh()) {
- old_rvh->SendBeforeUnloadACK(true);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, old_rvh->rvh_state());
+ if (old_rfh != active_rfh) {
+ old_rfh->SendBeforeUnloadACK(true);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, old_rfh->rfh_state());
}
// Commit the navigation with a new page ID.
int32 max_page_id = contents()->GetMaxPageIDForSiteInstance(
- active_rvh()->GetSiteInstance());
-
- // Simulate the response coming from the pending renderer.
- if (old_rvh != active_rvh())
- StartCrossSiteTransition(contents());
-
- // Simulate the SwapOut_ACK that fires if you commit a cross-site
- // navigation.
- if (old_rvh != active_rvh()) {
- old_rvh->OnSwappedOut(false);
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_COMMIT,
- old_rvh->rvh_state());
- }
+ active_rfh->GetSiteInstance());
// Use an observer to avoid accessing a deleted renderer later on when the
// state is being checked.
- RenderViewHostDeletedObserver rvh_observer(old_rvh);
- active_test_rvh()->SendNavigate(max_page_id + 1, url);
+ RenderFrameHostDeletedObserver rfh_observer(old_rfh);
+ RenderViewHostDeletedObserver rvh_observer(old_rfh->GetRenderViewHost());
+ active_rfh->SendNavigate(max_page_id + 1, url);
+
+ // Make sure that we start to run the unload handler at the time of commit.
+ bool expecting_rfh_shutdown = false;
+ if (old_rfh != active_rfh && !rfh_observer.deleted()) {
+ EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT,
+ old_rfh->rfh_state());
+ if (!old_rfh->GetSiteInstance()->active_frame_count()) {
+ expecting_rfh_shutdown = true;
+ EXPECT_TRUE(
+ old_rfh->frame_tree_node()->render_manager()->IsPendingDeletion(
+ old_rfh));
+ }
+ }
- if (old_rvh != active_rvh() && !rvh_observer.deleted())
- EXPECT_TRUE(old_rvh->IsSwappedOut());
+ // Simulate the swap out ACK coming from the pending renderer. This should
+ // either shut down the old RFH or leave it in a swapped out state.
+ if (old_rfh != active_rfh) {
+ old_rfh->OnSwappedOut();
+ if (expecting_rfh_shutdown) {
+ EXPECT_TRUE(rfh_observer.deleted());
+ EXPECT_TRUE(rvh_observer.deleted());
+ } else {
+ EXPECT_EQ(RenderFrameHostImpl::STATE_SWAPPED_OUT,
+ old_rfh->rfh_state());
+ }
+ }
+ EXPECT_EQ(active_rfh, contents()->GetMainFrame());
+ EXPECT_EQ(NULL, contents()->GetPendingMainFrame());
}
bool ShouldSwapProcesses(RenderFrameHostManager* manager,
const NavigationEntryImpl* current_entry,
const NavigationEntryImpl* new_entry) const {
- return manager->ShouldSwapBrowsingInstancesForNavigation(current_entry,
- new_entry);
+ CHECK(new_entry);
+ BrowserContext* browser_context =
+ manager->delegate_->GetControllerForRenderManager().GetBrowserContext();
+ const GURL& current_effective_url = current_entry ?
+ SiteInstanceImpl::GetEffectiveURL(browser_context,
+ current_entry->GetURL()) :
+ manager->render_frame_host_->GetSiteInstance()->GetSiteURL();
+ bool current_is_view_source_mode = current_entry ?
+ current_entry->IsViewSourceMode() : new_entry->IsViewSourceMode();
+ return manager->ShouldSwapBrowsingInstancesForNavigation(
+ current_effective_url,
+ current_is_view_source_mode,
+ new_entry->site_instance(),
+ SiteInstanceImpl::GetEffectiveURL(browser_context, new_entry->GetURL()),
+ new_entry->IsViewSourceMode());
}
- // Creates a test RenderViewHost that's swapped out.
- TestRenderViewHost* CreateSwappedOutRenderViewHost() {
+ // Creates a test RenderFrameHost that's swapped out.
+ TestRenderFrameHost* CreateSwappedOutRenderFrameHost() {
const GURL kChromeURL("chrome://foo");
const GURL kDestUrl("http://www.google.com/");
// Navigate our first tab to a chrome url and then to the destination.
NavigateActiveAndCommit(kChromeURL);
- TestRenderViewHost* ntp_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetRenderManagerForTesting()->current_host());
+ TestRenderFrameHost* ntp_rfh = contents()->GetMainFrame();
// Navigate to a cross-site URL.
contents()->GetController().LoadURL(
- kDestUrl, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ kDestUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
EXPECT_TRUE(contents()->cross_navigation_pending());
- // Manually increase the number of active views in the
- // SiteInstance that ntp_rvh belongs to, to prevent it from being
+ // Manually increase the number of active frames in the
+ // SiteInstance that ntp_rfh belongs to, to prevent it from being
// destroyed when it gets swapped out.
- static_cast<SiteInstanceImpl*>(ntp_rvh->GetSiteInstance())->
- increment_active_view_count();
+ ntp_rfh->GetSiteInstance()->increment_active_frame_count();
- TestRenderViewHost* dest_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetRenderManagerForTesting()->pending_render_view_host());
- CHECK(dest_rvh);
- EXPECT_NE(ntp_rvh, dest_rvh);
+ TestRenderFrameHost* dest_rfh = contents()->GetPendingMainFrame();
+ CHECK(dest_rfh);
+ EXPECT_NE(ntp_rfh, dest_rfh);
// BeforeUnload finishes.
- ntp_rvh->SendBeforeUnloadACK(true);
+ ntp_rfh->SendBeforeUnloadACK(true);
- dest_rvh->SendNavigate(101, kDestUrl);
- ntp_rvh->OnSwappedOut(false);
+ dest_rfh->SendNavigate(101, kDestUrl);
+ ntp_rfh->OnSwappedOut();
- EXPECT_TRUE(ntp_rvh->IsSwappedOut());
- return ntp_rvh;
+ EXPECT_TRUE(ntp_rfh->is_swapped_out());
+ return ntp_rfh;
}
private:
@@ -383,54 +443,53 @@ TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) {
EXPECT_TRUE(active_rvh()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
NavigateActiveAndCommit(kDestUrl);
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
+
// Make a second tab.
scoped_ptr<TestWebContents> contents2(
TestWebContents::Create(browser_context(), NULL));
// Load the two URLs in the second tab. Note that the first navigation creates
- // a RVH that's not pending (since there is no cross-site transition), so
+ // a RFH that's not pending (since there is no cross-site transition), so
// we use the committed one.
contents2->GetController().LoadURL(
- kChromeUrl, Referrer(), PAGE_TRANSITION_LINK, std::string());
- TestRenderViewHost* ntp_rvh2 = static_cast<TestRenderViewHost*>(
- contents2->GetRenderManagerForTesting()->current_host());
+ kChromeUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ TestRenderFrameHost* ntp_rfh2 = contents2->GetMainFrame();
EXPECT_FALSE(contents2->cross_navigation_pending());
- ntp_rvh2->SendNavigate(100, kChromeUrl);
+ ntp_rfh2->SendNavigate(100, kChromeUrl);
// The second one is the opposite, creating a cross-site transition and
// requiring a beforeunload ack.
contents2->GetController().LoadURL(
- kDestUrl, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ kDestUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
EXPECT_TRUE(contents2->cross_navigation_pending());
- TestRenderViewHost* dest_rvh2 = static_cast<TestRenderViewHost*>(
- contents2->GetRenderManagerForTesting()->pending_render_view_host());
- ASSERT_TRUE(dest_rvh2);
+ TestRenderFrameHost* dest_rfh2 = contents2->GetPendingMainFrame();
+ ASSERT_TRUE(dest_rfh2);
- ntp_rvh2->SendBeforeUnloadACK(true);
- StartCrossSiteTransition(contents2.get());
- dest_rvh2->SendNavigate(101, kDestUrl);
+ ntp_rfh2->SendBeforeUnloadACK(true);
+ dest_rfh2->SendNavigate(101, kDestUrl);
- // The two RVH's should be different in every way.
- EXPECT_NE(active_rvh()->GetProcess(), dest_rvh2->GetProcess());
- EXPECT_NE(active_rvh()->GetSiteInstance(), dest_rvh2->GetSiteInstance());
- EXPECT_FALSE(active_rvh()->GetSiteInstance()->IsRelatedSiteInstance(
- dest_rvh2->GetSiteInstance()));
+ // The two RFH's should be different in every way.
+ EXPECT_NE(contents()->GetMainFrame()->GetProcess(), dest_rfh2->GetProcess());
+ EXPECT_NE(contents()->GetMainFrame()->GetSiteInstance(),
+ dest_rfh2->GetSiteInstance());
+ EXPECT_FALSE(dest_rfh2->GetSiteInstance()->IsRelatedSiteInstance(
+ contents()->GetMainFrame()->GetSiteInstance()));
// Navigate both to the new tab page, and verify that they share a
// RenderProcessHost (not a SiteInstance).
NavigateActiveAndCommit(kChromeUrl);
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
contents2->GetController().LoadURL(
- kChromeUrl, Referrer(), PAGE_TRANSITION_LINK, std::string());
- dest_rvh2->SendBeforeUnloadACK(true);
- StartCrossSiteTransition(contents2.get());
- static_cast<TestRenderViewHost*>(contents2->GetRenderManagerForTesting()->
- pending_render_view_host())->SendNavigate(102, kChromeUrl);
-
- EXPECT_NE(active_rvh()->GetSiteInstance(),
- contents2->GetRenderViewHost()->GetSiteInstance());
- EXPECT_EQ(active_rvh()->GetSiteInstance()->GetProcess(),
- contents2->GetRenderViewHost()->GetSiteInstance()->GetProcess());
+ kChromeUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ dest_rfh2->SendBeforeUnloadACK(true);
+ contents2->GetPendingMainFrame()->SendNavigate(102, kChromeUrl);
+
+ EXPECT_NE(contents()->GetMainFrame()->GetSiteInstance(),
+ contents2->GetMainFrame()->GetSiteInstance());
+ EXPECT_EQ(contents()->GetMainFrame()->GetSiteInstance()->GetProcess(),
+ contents2->GetMainFrame()->GetSiteInstance()->GetProcess());
}
// Ensure that the browser ignores most IPC messages that arrive from a
@@ -445,74 +504,72 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
// Navigate our first tab to a chrome url and then to the destination.
NavigateActiveAndCommit(kChromeURL);
- TestRenderViewHost* ntp_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetRenderManagerForTesting()->current_host());
+ TestRenderFrameHost* ntp_rfh = contents()->GetMainFrame();
// Send an update favicon message and make sure it works.
const base::string16 ntp_title = base::ASCIIToUTF16("NTP Title");
{
PluginFaviconMessageObserver observer(contents());
- EXPECT_TRUE(ntp_rvh->OnMessageReceived(
+ EXPECT_TRUE(ntp_rfh->GetRenderViewHost()->OnMessageReceived(
ViewHostMsg_UpdateFaviconURL(
- rvh()->GetRoutingID(), icons)));
+ ntp_rfh->GetRenderViewHost()->GetRoutingID(), icons)));
EXPECT_TRUE(observer.favicon_received());
}
- // Create one more view in the same SiteInstance where ntp_rvh
+ // Create one more frame in the same SiteInstance where ntp_rfh
// exists so that it doesn't get deleted on navigation to another
// site.
- static_cast<SiteInstanceImpl*>(ntp_rvh->GetSiteInstance())->
- increment_active_view_count();
+ ntp_rfh->GetSiteInstance()->increment_active_frame_count();
// Navigate to a cross-site URL.
NavigateActiveAndCommit(kDestUrl);
- TestRenderViewHost* dest_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetRenderViewHost());
- ASSERT_TRUE(dest_rvh);
- EXPECT_NE(ntp_rvh, dest_rvh);
+ TestRenderFrameHost* dest_rfh = contents()->GetMainFrame();
+ ASSERT_TRUE(dest_rfh);
+ EXPECT_NE(ntp_rfh, dest_rfh);
// The new RVH should be able to update its favicon.
const base::string16 dest_title = base::ASCIIToUTF16("Google");
{
PluginFaviconMessageObserver observer(contents());
EXPECT_TRUE(
- dest_rvh->OnMessageReceived(
- ViewHostMsg_UpdateFaviconURL(rvh()->GetRoutingID(), icons)));
+ dest_rfh->GetRenderViewHost()->OnMessageReceived(
+ ViewHostMsg_UpdateFaviconURL(
+ dest_rfh->GetRenderViewHost()->GetRoutingID(), icons)));
EXPECT_TRUE(observer.favicon_received());
}
// The old renderer, being slow, now updates the favicon. It should be
// filtered out and not take effect.
- EXPECT_TRUE(ntp_rvh->IsSwappedOut());
+ EXPECT_TRUE(ntp_rfh->is_swapped_out());
{
PluginFaviconMessageObserver observer(contents());
EXPECT_TRUE(
- ntp_rvh->OnMessageReceived(
- ViewHostMsg_UpdateFaviconURL(rvh()->GetRoutingID(), icons)));
+ ntp_rfh->GetRenderViewHost()->OnMessageReceived(
+ ViewHostMsg_UpdateFaviconURL(
+ dest_rfh->GetRenderViewHost()->GetRoutingID(), icons)));
EXPECT_FALSE(observer.favicon_received());
}
+#if defined(ENABLE_PLUGINS)
// The same logic should apply to RenderFrameHosts as well and routing through
// swapped out RFH shouldn't be allowed. Use a PluginCrashObserver to check
// if the IPC message is allowed through or not.
{
PluginFaviconMessageObserver observer(contents());
- // TODO(nasko): Check that the RFH is in swapped out when the state moves
- // from RVH to RFH.
- EXPECT_TRUE(ntp_rvh->main_render_frame_host()->OnMessageReceived(
+ EXPECT_TRUE(ntp_rfh->OnMessageReceived(
FrameHostMsg_PluginCrashed(
- main_rfh()->GetRoutingID(), base::FilePath(), 0)));
+ ntp_rfh->GetRoutingID(), base::FilePath(), 0)));
EXPECT_FALSE(observer.plugin_crashed());
}
+#endif
// We cannot filter out synchronous IPC messages, because the renderer would
// be left waiting for a reply. We pick RunBeforeUnloadConfirm as an example
// that can run easily within a unit test, and that needs to receive a reply
// without showing an actual dialog.
MockRenderProcessHost* ntp_process_host =
- static_cast<MockRenderProcessHost*>(ntp_rvh->GetProcess());
+ static_cast<MockRenderProcessHost*>(ntp_rfh->GetProcess());
ntp_process_host->sink().ClearMessages();
- RenderFrameHost* ntp_rfh = ntp_rvh->GetMainFrame();
const base::string16 msg = base::ASCIIToUTF16("Message");
bool result = false;
base::string16 unused;
@@ -533,28 +590,71 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
EXPECT_TRUE(ntp_process_host->sink().GetUniqueMessageMatching(IPC_REPLY_ID));
}
+// Ensure that frames aren't added to the frame tree, if the message is coming
+// from a process different than the parent frame's current RenderFrameHost
+// process. Otherwise it is possible to have collisions of routing ids, as they
+// are scoped per process. See https://crbug.com/415059.
+TEST_F(RenderFrameHostManagerTest, DropCreateChildFrameWhileSwappedOut) {
+ const GURL kUrl1("http://foo.com");
+ const GURL kUrl2("http://www.google.com/");
+
+ // Navigate to the first site.
+ NavigateActiveAndCommit(kUrl1);
+ TestRenderFrameHost* initial_rfh = contents()->GetMainFrame();
+ {
+ RenderFrameHostCreatedObserver observer(contents());
+ initial_rfh->OnCreateChildFrame(
+ initial_rfh->GetProcess()->GetNextRoutingID(), std::string());
+ EXPECT_TRUE(observer.created());
+ }
+
+ // Create one more frame in the same SiteInstance where initial_rfh
+ // exists so that initial_rfh doesn't get deleted on navigation to another
+ // site.
+ initial_rfh->GetSiteInstance()->increment_active_frame_count();
+
+ // Navigate to a cross-site URL.
+ NavigateActiveAndCommit(kUrl2);
+ EXPECT_TRUE(initial_rfh->is_swapped_out());
+
+ TestRenderFrameHost* dest_rfh = contents()->GetMainFrame();
+ ASSERT_TRUE(dest_rfh);
+ EXPECT_NE(initial_rfh, dest_rfh);
+
+ {
+ // Since the old RFH is now swapped out, it shouldn't process any messages
+ // to create child frames.
+ RenderFrameHostCreatedObserver observer(contents());
+ initial_rfh->OnCreateChildFrame(
+ initial_rfh->GetProcess()->GetNextRoutingID(), std::string());
+ EXPECT_FALSE(observer.created());
+ }
+}
+
TEST_F(RenderFrameHostManagerTest, WhiteListSwapCompositorFrame) {
- TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
+ TestRenderFrameHost* swapped_out_rfh = CreateSwappedOutRenderFrameHost();
TestRenderWidgetHostView* swapped_out_rwhv =
- static_cast<TestRenderWidgetHostView*>(swapped_out_rvh->GetView());
+ static_cast<TestRenderWidgetHostView*>(
+ swapped_out_rfh->GetRenderViewHost()->GetView());
EXPECT_FALSE(swapped_out_rwhv->did_swap_compositor_frame());
MockRenderProcessHost* process_host =
- static_cast<MockRenderProcessHost*>(swapped_out_rvh->GetProcess());
+ static_cast<MockRenderProcessHost*>(swapped_out_rfh->GetProcess());
process_host->sink().ClearMessages();
cc::CompositorFrame frame;
- ViewHostMsg_SwapCompositorFrame msg(rvh()->GetRoutingID(), 0, frame);
+ ViewHostMsg_SwapCompositorFrame msg(
+ rvh()->GetRoutingID(), 0, frame, std::vector<IPC::Message>());
- EXPECT_TRUE(swapped_out_rvh->OnMessageReceived(msg));
+ EXPECT_TRUE(swapped_out_rfh->render_view_host()->OnMessageReceived(msg));
EXPECT_TRUE(swapped_out_rwhv->did_swap_compositor_frame());
}
// Test if RenderViewHost::GetRenderWidgetHosts() only returns active
// widgets.
TEST_F(RenderFrameHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
- TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
- EXPECT_TRUE(swapped_out_rvh->IsSwappedOut());
+ TestRenderFrameHost* swapped_out_rfh = CreateSwappedOutRenderFrameHost();
+ EXPECT_TRUE(swapped_out_rfh->is_swapped_out());
scoped_ptr<RenderWidgetHostIterator> widgets(
RenderWidgetHost::GetRenderWidgetHosts());
@@ -564,8 +664,7 @@ TEST_F(RenderFrameHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
RenderWidgetHost* widget = widgets->GetNextHost();
EXPECT_FALSE(widgets->GetNextHost());
RenderViewHost* rvh = RenderViewHost::From(widget);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT,
- static_cast<RenderViewHostImpl*>(rvh)->rvh_state());
+ EXPECT_TRUE(static_cast<RenderViewHostImpl*>(rvh)->is_active());
}
// Test if RenderViewHost::GetRenderWidgetHosts() returns a subset of
@@ -575,8 +674,8 @@ TEST_F(RenderFrameHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
// including swapped out ones.
TEST_F(RenderFrameHostManagerTest,
GetRenderWidgetHostsWithinGetAllRenderWidgetHosts) {
- TestRenderViewHost* swapped_out_rvh = CreateSwappedOutRenderViewHost();
- EXPECT_TRUE(swapped_out_rvh->IsSwappedOut());
+ TestRenderFrameHost* swapped_out_rfh = CreateSwappedOutRenderFrameHost();
+ EXPECT_TRUE(swapped_out_rfh->is_swapped_out());
scoped_ptr<RenderWidgetHostIterator> widgets(
RenderWidgetHost::GetRenderWidgetHosts());
@@ -595,19 +694,18 @@ TEST_F(RenderFrameHostManagerTest,
}
}
-// Test if SiteInstanceImpl::active_view_count() is correctly updated
-// as views in a SiteInstance get swapped out and in.
-TEST_F(RenderFrameHostManagerTest, ActiveViewCountWhileSwappingInandOut) {
+// Test if SiteInstanceImpl::active_frame_count() is correctly updated
+// as frames in a SiteInstance get swapped out and in.
+TEST_F(RenderFrameHostManagerTest, ActiveFrameCountWhileSwappingInAndOut) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
// Navigate to an initial URL.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
+ TestRenderFrameHost* rfh1 = main_test_rfh();
- SiteInstanceImpl* instance1 =
- static_cast<SiteInstanceImpl*>(rvh1->GetSiteInstance());
- EXPECT_EQ(instance1->active_view_count(), 1U);
+ SiteInstanceImpl* instance1 = rfh1->GetSiteInstance();
+ EXPECT_EQ(instance1->active_frame_count(), 1U);
// Create 2 new tabs and simulate them being the opener chain for the main
// tab. They should be in the same SiteInstance.
@@ -619,26 +717,25 @@ TEST_F(RenderFrameHostManagerTest, ActiveViewCountWhileSwappingInandOut) {
TestWebContents::Create(browser_context(), instance1));
opener1->SetOpener(opener2.get());
- EXPECT_EQ(instance1->active_view_count(), 3U);
+ EXPECT_EQ(instance1->active_frame_count(), 3U);
// Navigate to a cross-site URL (different SiteInstance but same
// BrowsingInstance).
contents()->NavigateAndCommit(kUrl2);
- TestRenderViewHost* rvh2 = test_rvh();
- SiteInstanceImpl* instance2 =
- static_cast<SiteInstanceImpl*>(rvh2->GetSiteInstance());
+ TestRenderFrameHost* rfh2 = main_test_rfh();
+ SiteInstanceImpl* instance2 = rfh2->GetSiteInstance();
// rvh2 is on chromium.org which is different from google.com on
// which other tabs are.
- EXPECT_EQ(instance2->active_view_count(), 1U);
+ EXPECT_EQ(instance2->active_frame_count(), 1U);
// There are two active views on google.com now.
- EXPECT_EQ(instance1->active_view_count(), 2U);
+ EXPECT_EQ(instance1->active_frame_count(), 2U);
// Navigate to the original origin (google.com).
contents()->NavigateAndCommit(kUrl1);
- EXPECT_EQ(instance1->active_view_count(), 3U);
+ EXPECT_EQ(instance1->active_frame_count(), 3U);
}
// This deletes a WebContents when the given RVH is deleted. This is
@@ -654,8 +751,7 @@ class RenderViewHostDestroyer : public WebContentsObserver {
render_view_host_(render_view_host),
web_contents_(web_contents) {}
- virtual void RenderViewDeleted(
- RenderViewHost* render_view_host) OVERRIDE {
+ void RenderViewDeleted(RenderViewHost* render_view_host) override {
if (render_view_host == render_view_host_)
delete web_contents_;
}
@@ -679,20 +775,20 @@ TEST_F(RenderFrameHostManagerTest,
// Navigate our first tab to a chrome url and then to the destination.
NavigateActiveAndCommit(kChromeURL);
- TestRenderViewHost* ntp_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetRenderManagerForTesting()->current_host());
+ TestRenderFrameHost* ntp_rfh = contents()->GetMainFrame();
// Create one more tab and navigate to kUrl1. web_contents is not
// wrapped as scoped_ptr since it intentionally deleted by destroyer
// below as part of this test.
TestWebContents* web_contents =
- TestWebContents::Create(browser_context(), ntp_rvh->GetSiteInstance());
+ TestWebContents::Create(browser_context(), ntp_rfh->GetSiteInstance());
web_contents->NavigateAndCommit(kUrl1);
- RenderViewHostDestroyer destroyer(ntp_rvh, web_contents);
+ RenderViewHostDestroyer destroyer(ntp_rfh->GetRenderViewHost(),
+ web_contents);
// This causes the first tab to navigate to kUrl2, which destroys
- // the ntp_rvh in ShutdownRenderViewHostsInSiteInstance(). When
- // ntp_rvh is destroyed, it also destroys the RVHs in web_contents
+ // the ntp_rfh in ShutdownRenderViewHostsInSiteInstance(). When
+ // ntp_rfh is destroyed, it also destroys the RVHs in web_contents
// too. This can test whether
// SiteInstanceImpl::ShutdownRenderViewHostsInSiteInstance() can
// touch any object freed in this way or not while iterating through
@@ -718,16 +814,17 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
// Navigate.
controller().LoadURL(
- kUrl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Simulate response from RenderFrame for DispatchBeforeUnload.
base::TimeTicks now = base::TimeTicks::Now();
- main_test_rfh()->OnMessageReceived(FrameHostMsg_BeforeUnload_ACK(
- main_test_rfh()->GetRoutingID(), true, now, now));
- ASSERT_TRUE(pending_rvh()); // New pending RenderViewHost will be created.
- RenderViewHost* last_rvh = pending_rvh();
- int32 new_id = contents()->GetMaxPageIDForSiteInstance(
- active_rvh()->GetSiteInstance()) + 1;
- pending_test_rvh()->SendNavigate(new_id, kUrl);
+ contents()->GetMainFrame()->OnMessageReceived(FrameHostMsg_BeforeUnload_ACK(
+ contents()->GetMainFrame()->GetRoutingID(), true, now, now));
+ ASSERT_TRUE(contents()->GetPendingMainFrame())
+ << "Expected new pending RenderFrameHost to be created.";
+ RenderFrameHost* last_rfh = contents()->GetPendingMainFrame();
+ int32 new_id =
+ contents()->GetMaxPageIDForSiteInstance(last_rfh->GetSiteInstance()) + 1;
+ contents()->GetPendingMainFrame()->SendNavigate(new_id, kUrl);
EXPECT_EQ(controller().GetLastCommittedEntryIndex(), 1);
ASSERT_TRUE(controller().GetLastCommittedEntry());
EXPECT_TRUE(kUrl == controller().GetLastCommittedEntry()->GetURL());
@@ -740,11 +837,12 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
process()->sink().ClearMessages();
// Navigate, again.
controller().LoadURL(
- kUrl, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// The same RenderViewHost should be reused.
- EXPECT_FALSE(pending_rvh());
- EXPECT_TRUE(last_rvh == rvh());
- test_rvh()->SendNavigate(new_id, kUrl); // The same page_id returned.
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
+ EXPECT_TRUE(last_rfh == contents()->GetMainFrame());
+ // Navigate using the returned page_id.
+ contents()->GetMainFrame()->SendNavigate(new_id, kUrl);
EXPECT_EQ(controller().GetLastCommittedEntryIndex(), 1);
EXPECT_FALSE(controller().GetPendingEntry());
// New message should be sent out to make sure to enter view-source mode.
@@ -788,13 +886,13 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
Source<WebContents>(web_contents.get()));
RenderFrameHostManager* manager = web_contents->GetRenderManagerForTesting();
- RenderFrameHostImpl* host;
+ RenderFrameHostImpl* host = NULL;
// 1) The first navigation. --------------------------
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(),
- base::string16() /* title */, PAGE_TRANSITION_TYPED,
+ base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
host = manager->Navigate(entry1);
@@ -807,16 +905,15 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// Commit to SiteInstance should be delayed until RenderView commit.
EXPECT_TRUE(host == manager->current_frame_host());
ASSERT_TRUE(host);
- EXPECT_FALSE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
- static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->SetSite(kUrl1);
+ EXPECT_FALSE(host->GetSiteInstance()->HasSite());
+ host->GetSiteInstance()->SetSite(kUrl1);
// 2) Navigate to next site. -------------------------
const GURL kUrl2("http://www.google.com/foo");
NavigationEntryImpl entry2(
NULL /* instance */, -1 /* page_id */, kUrl2,
Referrer(kUrl1, blink::WebReferrerPolicyDefault),
- base::string16() /* title */, PAGE_TRANSITION_LINK,
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
host = manager->Navigate(entry2);
@@ -828,15 +925,14 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
manager->DidNavigateFrame(host);
EXPECT_TRUE(host == manager->current_frame_host());
ASSERT_TRUE(host);
- EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
+ EXPECT_TRUE(host->GetSiteInstance()->HasSite());
// 3) Cross-site navigate to next site. --------------
const GURL kUrl3("http://webkit.org/");
NavigationEntryImpl entry3(
NULL /* instance */, -1 /* page_id */, kUrl3,
Referrer(kUrl2, blink::WebReferrerPolicyDefault),
- base::string16() /* title */, PAGE_TRANSITION_LINK,
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
false /* is_renderer_init */);
host = manager->Navigate(entry3);
@@ -850,8 +946,7 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
manager->DidNavigateFrame(manager->pending_frame_host());
EXPECT_TRUE(host == manager->current_frame_host());
ASSERT_TRUE(host);
- EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
+ EXPECT_TRUE(host->GetSiteInstance()->HasSite());
// Check the pending RenderFrameHost has been committed.
EXPECT_FALSE(manager->pending_frame_host());
@@ -860,194 +955,6 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
}
-// Tests the Navigate function. In this unit test we verify that the Navigate
-// function can handle a new navigation event before the previous navigation
-// has been committed. This is also a regression test for
-// http://crbug.com/104600.
-TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyReNavigation) {
- TestNotificationTracker notifications;
-
- SiteInstance* instance = SiteInstance::Create(browser_context());
-
- scoped_ptr<TestWebContents> web_contents(
- TestWebContents::Create(browser_context(), instance));
- notifications.ListenFor(NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- Source<WebContents>(web_contents.get()));
-
- RenderFrameHostManager* manager = web_contents->GetRenderManagerForTesting();
-
- // 1) The first navigation. --------------------------
- const GURL kUrl1("http://www.google.com/");
- NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
- Referrer(), base::string16() /* title */,
- PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
- RenderFrameHostImpl* host = manager->Navigate(entry1);
-
- // The RenderFrameHost created in Init will be reused.
- EXPECT_TRUE(host == manager->current_frame_host());
- EXPECT_FALSE(manager->pending_frame_host());
-
- // We should observe a notification.
- EXPECT_TRUE(
- notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
- notifications.Reset();
-
- // Commit.
- manager->DidNavigateFrame(host);
-
- // Commit to SiteInstance should be delayed until RenderView commit.
- EXPECT_TRUE(host == manager->current_frame_host());
- ASSERT_TRUE(host);
- EXPECT_FALSE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
- static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->SetSite(kUrl1);
-
- // 2) Cross-site navigate to next site. -------------------------
- const GURL kUrl2("http://www.example.com");
- NavigationEntryImpl entry2(
- NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(),
- base::string16() /* title */, PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
- RenderFrameHostImpl* host2 = manager->Navigate(entry2);
- int host2_process_id = host2->GetProcess()->GetID();
-
- // A new RenderFrameHost should be created.
- EXPECT_TRUE(manager->pending_frame_host());
- ASSERT_EQ(host2, manager->pending_frame_host());
- EXPECT_NE(host2, host);
-
- // Check that the navigation is still suspended because the old RVH
- // is not swapped out, yet.
- EXPECT_TRUE(host2->render_view_host()->are_navigations_suspended());
- MockRenderProcessHost* test_process_host2 =
- static_cast<MockRenderProcessHost*>(host2->GetProcess());
- test_process_host2->sink().ClearMessages();
- host2->render_view_host()->NavigateToURL(kUrl2);
- EXPECT_FALSE(test_process_host2->sink().GetUniqueMessageMatching(
- FrameMsg_Navigate::ID));
-
- // Allow closing the current Render View (precondition for swapping out
- // the RVH): Simulate response from RenderFrame for FrameMsg_BeforeUnload sent
- // by DispatchBeforeUnload.
- TestRenderViewHost* test_host =
- static_cast<TestRenderViewHost*>(host->render_view_host());
- MockRenderProcessHost* test_process_host =
- static_cast<MockRenderProcessHost*>(test_host->GetProcess());
- EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
- FrameMsg_BeforeUnload::ID));
- test_host->SendBeforeUnloadACK(true);
-
- // CrossSiteResourceHandler::StartCrossSiteTransition triggers a
- // call of RenderFrameHostManager::SwapOutOldPage before
- // RenderFrameHostManager::DidNavigateFrame is called.
- // The RVH is swapped out after receiving the unload ack.
- manager->SwapOutOldPage();
- EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
- FrameMsg_SwapOut::ID));
- test_host->OnSwappedOut(false);
-
- EXPECT_EQ(host, manager->current_frame_host());
- EXPECT_FALSE(manager->current_frame_host()->is_swapped_out());
- EXPECT_EQ(host2, manager->pending_frame_host());
- // There should be still no navigation messages being sent.
- EXPECT_FALSE(test_process_host2->sink().GetUniqueMessageMatching(
- FrameMsg_Navigate::ID));
-
- // 3) Cross-site navigate to next site before 2) has committed. --------------
- const GURL kUrl3("http://webkit.org/");
- NavigationEntryImpl entry3(NULL /* instance */, -1 /* page_id */, kUrl3,
- Referrer(), base::string16() /* title */,
- PAGE_TRANSITION_TYPED,
- false /* is_renderer_init */);
- test_process_host->sink().ClearMessages();
- RenderFrameHostImpl* host3 = manager->Navigate(entry3);
-
- // A new RenderFrameHost should be created. host2 is now deleted.
- EXPECT_TRUE(manager->pending_frame_host());
- ASSERT_EQ(host3, manager->pending_frame_host());
- EXPECT_NE(host3, host);
- EXPECT_NE(host3->GetProcess()->GetID(), host2_process_id);
-
- // Navigations in the new RVH should be suspended.
- EXPECT_TRUE(static_cast<RenderViewHostImpl*>(
- host3->render_view_host())->are_navigations_suspended());
- EXPECT_EQ(host, manager->current_frame_host());
- EXPECT_FALSE(manager->current_frame_host()->is_swapped_out());
-
- // Simulate a response to the second beforeunload request.
- EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
- FrameMsg_BeforeUnload::ID));
- test_host->SendBeforeUnloadACK(true);
-
- // CrossSiteResourceHandler::StartCrossSiteTransition triggers a
- // call of RenderFrameHostManager::SwapOutOldPage before
- // RenderFrameHostManager::DidNavigateFrame is called. Since the previous
- // navigation has already caused the renderer to start swapping out, there
- // will be no more SwapOut messages being sent.
- manager->SwapOutOldPage();
- EXPECT_FALSE(test_process_host->sink().GetUniqueMessageMatching(
- FrameMsg_SwapOut::ID));
- test_host->OnSwappedOut(false);
-
- // Commit.
- manager->DidNavigateFrame(host3);
- EXPECT_TRUE(host3 == manager->current_frame_host());
- ASSERT_TRUE(host3);
- EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host3->GetSiteInstance())->
- HasSite());
- // Check the pending RenderFrameHost has been committed.
- EXPECT_FALSE(manager->pending_frame_host());
-
- // We should observe a notification.
- EXPECT_TRUE(
- notifications.Check1AndReset(NOTIFICATION_RENDER_VIEW_HOST_CHANGED));
-}
-
-// Test that navigation is not blocked when we make new navigation before
-// previous one has been committed. This is also a regression test for
-// http://crbug.com/104600.
-TEST_F(RenderFrameHostManagerTest, NewCrossNavigationBetweenSwapOutAndCommit) {
- const GURL kUrl1("http://www.google.com/");
- const GURL kUrl2("http://www.chromium.org/");
- const GURL kUrl3("http://www.youtube.com/");
-
- contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
-
- // Keep active_view_count nonzero so that no swapped out views in
- // this SiteInstance get forcefully deleted.
- static_cast<SiteInstanceImpl*>(rvh1->GetSiteInstance())->
- increment_active_view_count();
-
- // Navigate but don't commit.
- contents()->GetController().LoadURL(
- kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
- EXPECT_TRUE(rvh1->is_waiting_for_beforeunload_ack());
- contents()->ProceedWithCrossSiteNavigation();
- EXPECT_FALSE(rvh1->is_waiting_for_beforeunload_ack());
- StartCrossSiteTransition(contents());
- EXPECT_TRUE(rvh1->IsWaitingForUnloadACK());
-
- rvh1->OnSwappedOut(false);
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_COMMIT, rvh1->rvh_state());
-
- TestRenderViewHost* rvh2 = pending_test_rvh();
- EXPECT_TRUE(rvh2);
- static_cast<SiteInstanceImpl*>(rvh2->GetSiteInstance())->
- increment_active_view_count();
-
- contents()->GetController().LoadURL(
- kUrl3, Referrer(), PAGE_TRANSITION_LINK, std::string());
- // Pending rvh2 is already deleted.
- contents()->ProceedWithCrossSiteNavigation();
-
- TestRenderViewHost* rvh3 = pending_test_rvh();
- EXPECT_TRUE(rvh3);
- // Navigation should be already unblocked by rvh1.
- EXPECT_FALSE(rvh3->are_navigations_suspended());
-}
-
// Tests WebUI creation.
TEST_F(RenderFrameHostManagerTest, WebUI) {
set_should_create_webui(true);
@@ -1062,7 +969,7 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
const GURL kUrl("chrome://foo");
NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl,
Referrer(), base::string16() /* title */,
- PAGE_TRANSITION_TYPED,
+ ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderFrameHostImpl* host = manager->Navigate(entry);
@@ -1077,8 +984,7 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
// as the navigation starts, rather than lazily after it commits, so we don't
// try to re-use the SiteInstance/process for non Web UI things that may
// get loaded in between.
- EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
+ EXPECT_TRUE(host->GetSiteInstance()->HasSite());
EXPECT_EQ(kUrl, host->GetSiteInstance()->GetSiteURL());
// The Web UI is committed immediately because the RenderViewHost has not been
@@ -1106,12 +1012,14 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
// Test the case that new RVH is considered live.
manager1->current_host()->CreateRenderView(
base::string16(), -1, MSG_ROUTING_NONE, -1, false);
+ EXPECT_TRUE(manager1->current_host()->IsRenderViewLive());
+ EXPECT_TRUE(manager1->current_frame_host()->IsRenderFrameLive());
// Navigate to a WebUI page.
const GURL kUrl1("chrome://foo");
NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
Referrer(), base::string16() /* title */,
- PAGE_TRANSITION_TYPED,
+ ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderFrameHostImpl* host1 = manager1->Navigate(entry1);
@@ -1142,7 +1050,7 @@ TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
const GURL kUrl2("chrome://foo/bar");
NavigationEntryImpl entry2(NULL /* instance */, -1 /* page_id */, kUrl2,
Referrer(), base::string16() /* title */,
- PAGE_TRANSITION_LINK,
+ ui::PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
RenderFrameHostImpl* host2 = manager2->Navigate(entry2);
@@ -1162,42 +1070,46 @@ TEST_F(RenderFrameHostManagerTest, PageDoesBackAndReload) {
const GURL kUrl2("http://www.evil-site.com/");
// Navigate to a safe site, then an evil site.
- // This will switch RenderViewHosts. We cannot assert that the first and
- // second RVHs are different, though, because the first one may be promptly
+ // This will switch RenderFrameHosts. We cannot assert that the first and
+ // second RFHs are different, though, because the first one may be promptly
// deleted.
contents()->NavigateAndCommit(kUrl1);
contents()->NavigateAndCommit(kUrl2);
- RenderViewHost* evil_rvh = contents()->GetRenderViewHost();
+ TestRenderFrameHost* evil_rfh = contents()->GetMainFrame();
// Now let's simulate the evil page calling history.back().
contents()->OnGoToEntryAtOffset(-1);
- // We should have a new pending RVH.
- // Note that in this case, the navigation has not committed, so evil_rvh will
+ // We should have a new pending RFH.
+ // Note that in this case, the navigation has not committed, so evil_rfh will
// not be deleted yet.
- EXPECT_NE(evil_rvh, contents()->GetRenderManagerForTesting()->
- pending_render_view_host());
+ EXPECT_NE(evil_rfh, contents()->GetPendingMainFrame());
+ EXPECT_NE(evil_rfh->GetRenderViewHost(),
+ contents()->GetPendingMainFrame()->GetRenderViewHost());
- // Before that RVH has committed, the evil page reloads itself.
+ // Before that RFH has committed, the evil page reloads itself.
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.url = kUrl2;
- params.transition = PAGE_TRANSITION_CLIENT_REDIRECT;
+ params.transition = ui::PAGE_TRANSITION_CLIENT_REDIRECT;
params.should_update_history = false;
params.gesture = NavigationGestureAuto;
params.was_within_same_page = false;
params.is_post = false;
params.page_state = PageState::CreateFromURL(kUrl2);
- RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(evil_rvh);
- RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(
- rvh->GetProcess()->GetID(), rvh->main_frame_routing_id());
- contents()->GetFrameTree()->root()->navigator()->DidNavigate(rfh, params);
+ contents()->GetFrameTree()->root()->navigator()->DidNavigate(evil_rfh,
+ params);
- // That should have cancelled the pending RVH, and the evil RVH should be the
+ // That should have cancelled the pending RFH, and the evil RFH should be the
// current one.
EXPECT_TRUE(contents()->GetRenderManagerForTesting()->
pending_render_view_host() == NULL);
- EXPECT_EQ(evil_rvh, contents()->GetRenderManagerForTesting()->current_host());
+ EXPECT_TRUE(contents()->GetRenderManagerForTesting()->pending_frame_host() ==
+ NULL);
+ EXPECT_EQ(evil_rfh,
+ contents()->GetRenderManagerForTesting()->current_frame_host());
+ EXPECT_EQ(evil_rfh->GetRenderViewHost(),
+ contents()->GetRenderManagerForTesting()->current_host());
// Also we should not have a pending navigation entry.
EXPECT_TRUE(contents()->GetController().GetPendingEntry() == NULL);
@@ -1214,50 +1126,47 @@ TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
// Navigate to two pages.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
+ TestRenderFrameHost* rfh1 = main_test_rfh();
- // Keep active_view_count nonzero so that no swapped out views in
+ // Keep active_frame_count nonzero so that no swapped out frames in
// this SiteInstance get forcefully deleted.
- static_cast<SiteInstanceImpl*>(rvh1->GetSiteInstance())->
- increment_active_view_count();
+ rfh1->GetSiteInstance()->increment_active_frame_count();
contents()->NavigateAndCommit(kUrl2);
- TestRenderViewHost* rvh2 = test_rvh();
- static_cast<SiteInstanceImpl*>(rvh2->GetSiteInstance())->
- increment_active_view_count();
+ TestRenderFrameHost* rfh2 = main_test_rfh();
+ rfh2->GetSiteInstance()->increment_active_frame_count();
// Now go back, but suppose the SwapOut_ACK isn't received. This shouldn't
// happen, but we have seen it when going back quickly across many entries
// (http://crbug.com/93427).
contents()->GetController().GoBack();
- EXPECT_TRUE(rvh2->is_waiting_for_beforeunload_ack());
+ EXPECT_TRUE(rfh2->is_waiting_for_beforeunload_ack());
contents()->ProceedWithCrossSiteNavigation();
- EXPECT_FALSE(rvh2->is_waiting_for_beforeunload_ack());
- StartCrossSiteTransition(contents());
- EXPECT_TRUE(rvh2->IsWaitingForUnloadACK());
+ EXPECT_FALSE(rfh2->is_waiting_for_beforeunload_ack());
// The back navigation commits.
const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry();
- rvh1->SendNavigate(entry1->GetPageID(), entry1->GetURL());
- EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SWAP_OUT, rvh2->rvh_state());
+ rfh1->SendNavigate(entry1->GetPageID(), entry1->GetURL());
+ EXPECT_TRUE(rfh2->IsWaitingForUnloadACK());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh2->rfh_state());
// We should be able to navigate forward.
contents()->GetController().GoForward();
contents()->ProceedWithCrossSiteNavigation();
- StartCrossSiteTransition(contents());
const NavigationEntry* entry2 = contents()->GetController().GetPendingEntry();
- rvh2->SendNavigate(entry2->GetPageID(), entry2->GetURL());
- EXPECT_EQ(rvh2, rvh());
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
- EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SWAP_OUT, rvh1->rvh_state());
- rvh1->OnSwappedOut(false);
- EXPECT_TRUE(rvh1->IsSwappedOut());
+ rfh2->SendNavigate(entry2->GetPageID(), entry2->GetURL());
+ EXPECT_EQ(rfh2, main_test_rfh());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
+ rfh1->OnSwappedOut();
+ EXPECT_TRUE(rfh1->is_swapped_out());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_SWAPPED_OUT, rfh1->rfh_state());
}
-// Test that we create swapped out RVHs for the opener chain when navigating an
+// Test that we create swapped out RFHs for the opener chain when navigating an
// opened tab cross-process. This allows us to support certain cross-process
// JavaScript calls (http://crbug.com/99202).
-TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRVHs) {
+TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRFHs) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
const GURL kChromeUrl("chrome://foo");
@@ -1265,18 +1174,19 @@ TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRVHs) {
// Navigate to an initial URL.
contents()->NavigateAndCommit(kUrl1);
RenderFrameHostManager* manager = contents()->GetRenderManagerForTesting();
+ TestRenderFrameHost* rfh1 = main_test_rfh();
TestRenderViewHost* rvh1 = test_rvh();
// Create 2 new tabs and simulate them being the opener chain for the main
// tab. They should be in the same SiteInstance.
scoped_ptr<TestWebContents> opener1(
- TestWebContents::Create(browser_context(), rvh1->GetSiteInstance()));
+ TestWebContents::Create(browser_context(), rfh1->GetSiteInstance()));
RenderFrameHostManager* opener1_manager =
opener1->GetRenderManagerForTesting();
contents()->SetOpener(opener1.get());
scoped_ptr<TestWebContents> opener2(
- TestWebContents::Create(browser_context(), rvh1->GetSiteInstance()));
+ TestWebContents::Create(browser_context(), rfh1->GetSiteInstance()));
RenderFrameHostManager* opener2_manager =
opener2->GetRenderManagerForTesting();
opener1->SetOpener(opener2.get());
@@ -1284,41 +1194,183 @@ TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRVHs) {
// Navigate to a cross-site URL (different SiteInstance but same
// BrowsingInstance).
contents()->NavigateAndCommit(kUrl2);
+ TestRenderFrameHost* rfh2 = main_test_rfh();
TestRenderViewHost* rvh2 = test_rvh();
- EXPECT_NE(rvh1->GetSiteInstance(), rvh2->GetSiteInstance());
- EXPECT_TRUE(rvh1->GetSiteInstance()->IsRelatedSiteInstance(
- rvh2->GetSiteInstance()));
+ EXPECT_NE(rfh1->GetSiteInstance(), rfh2->GetSiteInstance());
+ EXPECT_TRUE(rfh1->GetSiteInstance()->IsRelatedSiteInstance(
+ rfh2->GetSiteInstance()));
// Ensure rvh1 is placed on swapped out list of the current tab.
+ EXPECT_TRUE(manager->IsOnSwappedOutList(rfh1));
EXPECT_TRUE(manager->IsRVHOnSwappedOutList(rvh1));
+ EXPECT_EQ(rfh1,
+ manager->GetRenderFrameProxyHost(rfh1->GetSiteInstance())
+ ->render_frame_host());
EXPECT_EQ(rvh1,
manager->GetSwappedOutRenderViewHost(rvh1->GetSiteInstance()));
- // Ensure a swapped out RVH is created in the first opener tab.
+ // Ensure a swapped out RFH and RFH is created in the first opener tab.
+ RenderFrameProxyHost* opener1_proxy =
+ opener1_manager->GetRenderFrameProxyHost(rfh2->GetSiteInstance());
+ RenderFrameHostImpl* opener1_rfh = opener1_proxy->render_frame_host();
TestRenderViewHost* opener1_rvh = static_cast<TestRenderViewHost*>(
opener1_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
+ EXPECT_TRUE(opener1_manager->IsOnSwappedOutList(opener1_rfh));
EXPECT_TRUE(opener1_manager->IsRVHOnSwappedOutList(opener1_rvh));
- EXPECT_TRUE(opener1_rvh->IsSwappedOut());
+ EXPECT_TRUE(opener1_rfh->is_swapped_out());
+ EXPECT_FALSE(opener1_rvh->is_active());
- // Ensure a swapped out RVH is created in the second opener tab.
+ // Ensure a swapped out RFH and RVH is created in the second opener tab.
+ RenderFrameProxyHost* opener2_proxy =
+ opener2_manager->GetRenderFrameProxyHost(rfh2->GetSiteInstance());
+ RenderFrameHostImpl* opener2_rfh = opener2_proxy->render_frame_host();
TestRenderViewHost* opener2_rvh = static_cast<TestRenderViewHost*>(
opener2_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
+ EXPECT_TRUE(opener2_manager->IsOnSwappedOutList(opener2_rfh));
EXPECT_TRUE(opener2_manager->IsRVHOnSwappedOutList(opener2_rvh));
- EXPECT_TRUE(opener2_rvh->IsSwappedOut());
+ EXPECT_TRUE(opener2_rfh->is_swapped_out());
+ EXPECT_FALSE(opener2_rvh->is_active());
// Navigate to a cross-BrowsingInstance URL.
contents()->NavigateAndCommit(kChromeUrl);
- TestRenderViewHost* rvh3 = test_rvh();
- EXPECT_NE(rvh1->GetSiteInstance(), rvh3->GetSiteInstance());
- EXPECT_FALSE(rvh1->GetSiteInstance()->IsRelatedSiteInstance(
- rvh3->GetSiteInstance()));
+ TestRenderFrameHost* rfh3 = main_test_rfh();
+ EXPECT_NE(rfh1->GetSiteInstance(), rfh3->GetSiteInstance());
+ EXPECT_FALSE(rfh1->GetSiteInstance()->IsRelatedSiteInstance(
+ rfh3->GetSiteInstance()));
// No scripting is allowed across BrowsingInstances, so we should not create
// swapped out RVHs for the opener chain in this case.
+ EXPECT_FALSE(opener1_manager->GetRenderFrameProxyHost(
+ rfh3->GetSiteInstance()));
EXPECT_FALSE(opener1_manager->GetSwappedOutRenderViewHost(
- rvh3->GetSiteInstance()));
+ rfh3->GetSiteInstance()));
+ EXPECT_FALSE(opener2_manager->GetRenderFrameProxyHost(
+ rfh3->GetSiteInstance()));
EXPECT_FALSE(opener2_manager->GetSwappedOutRenderViewHost(
- rvh3->GetSiteInstance()));
+ rfh3->GetSiteInstance()));
+}
+
+// Test that a page can disown the opener of the WebContents.
+TEST_F(RenderFrameHostManagerTest, DisownOpener) {
+ const GURL kUrl1("http://www.google.com/");
+ const GURL kUrl2("http://www.chromium.org/");
+
+ // Navigate to an initial URL.
+ contents()->NavigateAndCommit(kUrl1);
+ TestRenderFrameHost* rfh1 = main_test_rfh();
+
+ // Create a new tab and simulate having it be the opener for the main tab.
+ scoped_ptr<TestWebContents> opener1(
+ TestWebContents::Create(browser_context(), rfh1->GetSiteInstance()));
+ contents()->SetOpener(opener1.get());
+ EXPECT_TRUE(contents()->HasOpener());
+
+ // Navigate to a cross-site URL (different SiteInstance but same
+ // BrowsingInstance).
+ contents()->NavigateAndCommit(kUrl2);
+ TestRenderFrameHost* rfh2 = main_test_rfh();
+ EXPECT_NE(rfh1->GetSiteInstance(), rfh2->GetSiteInstance());
+
+ // Disown the opener from rfh2.
+ rfh2->DidDisownOpener();
+
+ // Ensure the opener is cleared.
+ EXPECT_FALSE(contents()->HasOpener());
+}
+
+// Test that a page can disown a same-site opener of the WebContents.
+TEST_F(RenderFrameHostManagerTest, DisownSameSiteOpener) {
+ const GURL kUrl1("http://www.google.com/");
+
+ // Navigate to an initial URL.
+ contents()->NavigateAndCommit(kUrl1);
+ TestRenderFrameHost* rfh1 = main_test_rfh();
+
+ // Create a new tab and simulate having it be the opener for the main tab.
+ scoped_ptr<TestWebContents> opener1(
+ TestWebContents::Create(browser_context(), rfh1->GetSiteInstance()));
+ contents()->SetOpener(opener1.get());
+ EXPECT_TRUE(contents()->HasOpener());
+
+ // Disown the opener from rfh1.
+ rfh1->DidDisownOpener();
+
+ // Ensure the opener is cleared even if it is in the same process.
+ EXPECT_FALSE(contents()->HasOpener());
+}
+
+// Test that a page can disown the opener just as a cross-process navigation is
+// in progress.
+TEST_F(RenderFrameHostManagerTest, DisownOpenerDuringNavigation) {
+ const GURL kUrl1("http://www.google.com/");
+ const GURL kUrl2("http://www.chromium.org/");
+
+ // Navigate to an initial URL.
+ contents()->NavigateAndCommit(kUrl1);
+ TestRenderFrameHost* rfh1 = main_test_rfh();
+
+ // Create a new tab and simulate having it be the opener for the main tab.
+ scoped_ptr<TestWebContents> opener1(
+ TestWebContents::Create(browser_context(), rfh1->GetSiteInstance()));
+ contents()->SetOpener(opener1.get());
+ EXPECT_TRUE(contents()->HasOpener());
+
+ // Navigate to a cross-site URL (different SiteInstance but same
+ // BrowsingInstance).
+ contents()->NavigateAndCommit(kUrl2);
+ TestRenderFrameHost* rfh2 = main_test_rfh();
+ EXPECT_NE(rfh1->GetSiteInstance(), rfh2->GetSiteInstance());
+
+ // Start a back navigation so that rfh1 becomes the pending RFH.
+ contents()->GetController().GoBack();
+ contents()->ProceedWithCrossSiteNavigation();
+
+ // Disown the opener from rfh2.
+ rfh2->DidDisownOpener();
+
+ // Ensure the opener is cleared.
+ EXPECT_FALSE(contents()->HasOpener());
+
+ // The back navigation commits.
+ const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry();
+ rfh1->SendNavigate(entry1->GetPageID(), entry1->GetURL());
+
+ // Ensure the opener is still cleared.
+ EXPECT_FALSE(contents()->HasOpener());
+}
+
+// Test that a page can disown the opener just after a cross-process navigation
+// commits.
+TEST_F(RenderFrameHostManagerTest, DisownOpenerAfterNavigation) {
+ const GURL kUrl1("http://www.google.com/");
+ const GURL kUrl2("http://www.chromium.org/");
+
+ // Navigate to an initial URL.
+ contents()->NavigateAndCommit(kUrl1);
+ TestRenderFrameHost* rfh1 = main_test_rfh();
+
+ // Create a new tab and simulate having it be the opener for the main tab.
+ scoped_ptr<TestWebContents> opener1(
+ TestWebContents::Create(browser_context(), rfh1->GetSiteInstance()));
+ contents()->SetOpener(opener1.get());
+ EXPECT_TRUE(contents()->HasOpener());
+
+ // Navigate to a cross-site URL (different SiteInstance but same
+ // BrowsingInstance).
+ contents()->NavigateAndCommit(kUrl2);
+ TestRenderFrameHost* rfh2 = main_test_rfh();
+ EXPECT_NE(rfh1->GetSiteInstance(), rfh2->GetSiteInstance());
+
+ // Commit a back navigation before the DidDisownOpener message arrives.
+ // rfh1 will be kept alive because of the opener tab.
+ contents()->GetController().GoBack();
+ contents()->ProceedWithCrossSiteNavigation();
+ const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry();
+ rfh1->SendNavigate(entry1->GetPageID(), entry1->GetURL());
+
+ // Disown the opener from rfh2.
+ rfh2->DidDisownOpener();
+ EXPECT_FALSE(contents()->HasOpener());
}
// Test that we clean up swapped out RenderViewHosts when a process hosting
@@ -1341,6 +1393,8 @@ TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) {
// Make sure the new opener RVH is considered live.
opener1_manager->current_host()->CreateRenderView(
base::string16(), -1, MSG_ROUTING_NONE, -1, false);
+ EXPECT_TRUE(opener1_manager->current_host()->IsRenderViewLive());
+ EXPECT_TRUE(opener1_manager->current_frame_host()->IsRenderFrameLive());
// Use a cross-process navigation in the opener to swap out the old RVH.
EXPECT_FALSE(opener1_manager->GetSwappedOutRenderViewHost(
@@ -1403,11 +1457,16 @@ TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) {
EXPECT_TRUE(rvh1->GetSiteInstance()->IsRelatedSiteInstance(
rvh2->GetSiteInstance()));
- // Ensure a swapped out RVH is created in the first opener tab.
+ // Ensure a swapped out RFH and RVH is created in the first opener tab.
+ RenderFrameProxyHost* opener1_proxy =
+ opener1_manager->GetRenderFrameProxyHost(rvh2->GetSiteInstance());
+ RenderFrameHostImpl* opener1_rfh = opener1_proxy->render_frame_host();
TestRenderViewHost* opener1_rvh = static_cast<TestRenderViewHost*>(
opener1_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
+ EXPECT_TRUE(opener1_manager->IsOnSwappedOutList(opener1_rfh));
EXPECT_TRUE(opener1_manager->IsRVHOnSwappedOutList(opener1_rvh));
- EXPECT_TRUE(opener1_rvh->IsSwappedOut());
+ EXPECT_TRUE(opener1_rfh->is_swapped_out());
+ EXPECT_FALSE(opener1_rvh->is_active());
// Ensure the new RVH has WebUI bindings.
EXPECT_TRUE(rvh2->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
@@ -1425,13 +1484,13 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
RenderFrameHostManager* manager = web_contents->GetRenderManagerForTesting();
- RenderFrameHostImpl* host;
+ RenderFrameHostImpl* host = NULL;
// 1) The first navigation. --------------------------
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(
NULL /* instance */, -1 /* page_id */, kUrl1, Referrer(),
- base::string16() /* title */, PAGE_TRANSITION_TYPED,
+ base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
host = manager->Navigate(entry1);
@@ -1445,8 +1504,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
// Commit to SiteInstance should be delayed until RenderView commit.
EXPECT_EQ(host, manager->current_frame_host());
ASSERT_TRUE(host);
- EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
+ EXPECT_TRUE(host->GetSiteInstance()->HasSite());
// 2) Navigate to a different domain. -------------------------
// Guests stay in the same process on navigation.
@@ -1454,7 +1512,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
NavigationEntryImpl entry2(
NULL /* instance */, -1 /* page_id */, kUrl2,
Referrer(kUrl1, blink::WebReferrerPolicyDefault),
- base::string16() /* title */, PAGE_TRANSITION_LINK,
+ base::string16() /* title */, ui::PAGE_TRANSITION_LINK,
true /* is_renderer_init */);
host = manager->Navigate(entry2);
@@ -1466,8 +1524,7 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
manager->DidNavigateFrame(host);
EXPECT_EQ(host, manager->current_frame_host());
ASSERT_TRUE(host);
- EXPECT_EQ(static_cast<SiteInstanceImpl*>(host->GetSiteInstance()),
- instance);
+ EXPECT_EQ(host->GetSiteInstance(), instance);
}
// Test that we cancel a pending RVH if we close the tab while it's pending.
@@ -1490,7 +1547,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
const GURL kUrl1("http://www.google.com/");
NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1,
Referrer(), base::string16() /* title */,
- PAGE_TRANSITION_TYPED,
+ ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderFrameHostImpl* host = manager->Navigate(entry1);
@@ -1508,15 +1565,14 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
// Commit to SiteInstance should be delayed until RenderFrame commits.
EXPECT_EQ(host, manager->current_frame_host());
- EXPECT_FALSE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
- HasSite());
- static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->SetSite(kUrl1);
+ EXPECT_FALSE(host->GetSiteInstance()->HasSite());
+ host->GetSiteInstance()->SetSite(kUrl1);
// 2) Cross-site navigate to next site. -------------------------
const GURL kUrl2("http://www.example.com");
NavigationEntryImpl entry2(
NULL /* instance */, -1 /* page_id */, kUrl2, Referrer(),
- base::string16() /* title */, PAGE_TRANSITION_TYPED,
+ base::string16() /* title */, ui::PAGE_TRANSITION_TYPED,
false /* is_renderer_init */);
RenderFrameHostImpl* host2 = manager->Navigate(entry2);
@@ -1539,214 +1595,118 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
EXPECT_EQ(host, manager->current_frame_host());
}
-// Tests that the RenderViewHost is properly deleted when the SwapOutACK is
-// received before the new page commits.
-TEST_F(RenderFrameHostManagerTest,
- SwapOutACKBeforeNewPageCommitsLeadsToDeletion) {
+TEST_F(RenderFrameHostManagerTest, CloseWithPendingWhileUnresponsive) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
- // Navigate to the first page.
- contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
- RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
-
- // Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
- base::TimeTicks now = base::TimeTicks::Now();
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
- EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* rvh2 =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
-
- // Simulate rvh2's response, which leads to an unload request being sent to
- // rvh1.
- std::vector<GURL> url_chain;
- url_chain.push_back(GURL());
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
- EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK,
- rvh1->rvh_state());
-
- // Simulate the swap out ack.
- rvh1->OnSwappedOut(false);
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_COMMIT, rvh1->rvh_state());
-
- // The new page commits.
- contents()->TestDidNavigate(rvh2, 1, kUrl2, PAGE_TRANSITION_TYPED);
- EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(rvh2, rvh());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
-
- // rvh1 should have been deleted.
- EXPECT_TRUE(rvh_deleted_observer.deleted());
- rvh1 = NULL;
-}
-
-// Tests that the RenderViewHost is properly swapped out when the SwapOutACK is
-// received before the new page commits.
-TEST_F(RenderFrameHostManagerTest,
- SwapOutACKBeforeNewPageCommitsLeadsToSwapOut) {
- const GURL kUrl1("http://www.google.com/");
- const GURL kUrl2("http://www.chromium.org/");
+ CloseWebContentsDelegate close_delegate;
+ contents()->SetDelegate(&close_delegate);
// Navigate to the first page.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
- RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
+ TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
- // Increment the number of active views in SiteInstanceImpl so that rvh2 is
- // not deleted on swap out.
- static_cast<SiteInstanceImpl*>(
- rvh1->GetSiteInstance())->increment_active_view_count();
+ // Start to close the tab, but assume it's unresponsive.
+ rfh1->render_view_host()->ClosePage();
+ EXPECT_TRUE(rfh1->render_view_host()->is_waiting_for_close_ack());
- // Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
- base::TimeTicks now = base::TimeTicks::Now();
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
- EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* rvh2 =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
-
- // Simulate rvh2's response, which leads to an unload request being sent to
- // rvh1.
- std::vector<GURL> url_chain;
- url_chain.push_back(GURL());
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
+ // Start a navigation to a new site.
+ controller().LoadURL(
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK,
- rvh1->rvh_state());
- // Simulate the swap out ack.
- rvh1->OnSwappedOut(false);
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_COMMIT, rvh1->rvh_state());
-
- // The new page commits.
- contents()->TestDidNavigate(rvh2, 1, kUrl2, PAGE_TRANSITION_TYPED);
- EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(rvh2, rvh());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
-
- // rvh1 should be swapped out.
- EXPECT_FALSE(rvh_deleted_observer.deleted());
- EXPECT_TRUE(rvh1->IsSwappedOut());
+ // Simulate the unresponsiveness timer. The tab should close.
+ contents()->RendererUnresponsive(rfh1->render_view_host());
+ EXPECT_TRUE(close_delegate.is_closed());
}
-// Tests that the RenderViewHost is properly deleted when the new
-// page commits before the swap out ack is received.
-TEST_F(RenderFrameHostManagerTest,
- NewPageCommitsBeforeSwapOutACKLeadsToDeletion) {
+// Tests that the RenderFrameHost is properly deleted when the SwapOutACK is
+// received. (SwapOut and the corresponding ACK always occur after commit.)
+// Also tests that an early SwapOutACK is properly ignored.
+TEST_F(RenderFrameHostManagerTest, DeleteFrameAfterSwapOutACK) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
// Navigate to the first page.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
- RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
+ TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
+ RenderFrameHostDeletedObserver rfh_deleted_observer(rfh1);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
// Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ controller().LoadURL(
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
base::TimeTicks now = base::TimeTicks::Now();
- main_test_rfh()->OnMessageReceived(
+ contents()->GetMainFrame()->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* rvh2 =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
-
- // Simulate rvh2's response, which leads to an unload request being sent to
- // rvh1.
- std::vector<GURL> url_chain;
- url_chain.push_back(GURL());
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
+
+ // Simulate the swap out ack, unexpectedly early (before commit). It should
+ // have no effect.
+ rfh1->OnSwappedOut();
EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK,
- rvh1->rvh_state());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
// The new page commits.
- contents()->TestDidNavigate(rvh2, 1, kUrl2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(rfh2, 1, kUrl2, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(rvh2, rvh());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
- EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SHUTDOWN, rvh1->rvh_state());
+ EXPECT_EQ(rfh2, contents()->GetMainFrame());
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
+ EXPECT_TRUE(
+ rfh1->frame_tree_node()->render_manager()->IsPendingDeletion(rfh1));
// Simulate the swap out ack.
- rvh1->OnSwappedOut(false);
+ rfh1->OnSwappedOut();
- // rvh1 should have been deleted.
- EXPECT_TRUE(rvh_deleted_observer.deleted());
- rvh1 = NULL;
+ // rfh1 should have been deleted.
+ EXPECT_TRUE(rfh_deleted_observer.deleted());
+ rfh1 = NULL;
}
-// Tests that the RenderViewHost is properly swapped out when the new page
-// commits before the swap out ack is received.
-TEST_F(RenderFrameHostManagerTest,
- NewPageCommitsBeforeSwapOutACKLeadsToSwapOut) {
+// Tests that the RenderFrameHost is properly swapped out when the SwapOut ACK
+// is received. (SwapOut and the corresponding ACK always occur after commit.)
+TEST_F(RenderFrameHostManagerTest, SwapOutFrameAfterSwapOutACK) {
const GURL kUrl1("http://www.google.com/");
const GURL kUrl2("http://www.chromium.org/");
// Navigate to the first page.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
- RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
+ TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
+ RenderFrameHostDeletedObserver rfh_deleted_observer(rfh1);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
- // Increment the number of active views in SiteInstanceImpl so that rvh1 is
+ // Increment the number of active frames in SiteInstanceImpl so that rfh1 is
// not deleted on swap out.
- static_cast<SiteInstanceImpl*>(
- rvh1->GetSiteInstance())->increment_active_view_count();
+ rfh1->GetSiteInstance()->increment_active_frame_count();
// Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ controller().LoadURL(
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
base::TimeTicks now = base::TimeTicks::Now();
- main_test_rfh()->OnMessageReceived(
+ contents()->GetMainFrame()->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* rvh2 =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
-
- // Simulate rvh2's response, which leads to an unload request being sent to
- // rvh1.
- std::vector<GURL> url_chain;
- url_chain.push_back(GURL());
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
- EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK,
- rvh1->rvh_state());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// The new page commits.
- contents()->TestDidNavigate(rvh2, 1, kUrl2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(rfh2, 1, kUrl2, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(rvh2, rvh());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
- EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SWAP_OUT, rvh1->rvh_state());
+ EXPECT_EQ(rfh2, contents()->GetMainFrame());
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
// Simulate the swap out ack.
- rvh1->OnSwappedOut(false);
+ rfh1->OnSwappedOut();
- // rvh1 should be swapped out.
- EXPECT_FALSE(rvh_deleted_observer.deleted());
- EXPECT_TRUE(rvh1->IsSwappedOut());
+ // rfh1 should be swapped out.
+ EXPECT_FALSE(rfh_deleted_observer.deleted());
+ EXPECT_TRUE(rfh1->is_swapped_out());
}
// Test that the RenderViewHost is properly swapped out if a navigation in the
@@ -1760,38 +1720,37 @@ TEST_F(RenderFrameHostManagerTest,
// Navigate to the first page.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
- RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
+ TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
+ RenderFrameHostDeletedObserver rfh_deleted_observer(rfh1);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
- // Increment the number of active views in SiteInstanceImpl so that rvh1 is
+ // Increment the number of active frames in SiteInstanceImpl so that rfh1 is
// not deleted on swap out.
- static_cast<SiteInstanceImpl*>(
- rvh1->GetSiteInstance())->increment_active_view_count();
+ rfh1->GetSiteInstance()->increment_active_frame_count();
// Navigate to new site, simulating onbeforeunload approval.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ controller().LoadURL(
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
base::TimeTicks now = base::TimeTicks::Now();
- main_test_rfh()->OnMessageReceived(
+ rfh1->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* rvh2 =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// The new page commits.
- contents()->TestDidNavigate(rvh2, 1, kUrl2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(rfh2, 1, kUrl2, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(rvh2, rvh());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
- EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SWAP_OUT, rvh1->rvh_state());
+ EXPECT_EQ(rfh2, contents()->GetMainFrame());
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
// Simulate the swap out ack.
- rvh1->OnSwappedOut(false);
+ rfh1->OnSwappedOut();
- // rvh1 should be swapped out.
- EXPECT_FALSE(rvh_deleted_observer.deleted());
- EXPECT_TRUE(rvh1->IsSwappedOut());
+ // rfh1 should be swapped out.
+ EXPECT_FALSE(rfh_deleted_observer.deleted());
+ EXPECT_TRUE(rfh1->is_swapped_out());
}
// Test that a RenderFrameHost is properly deleted or swapped out when a
@@ -1805,42 +1764,43 @@ TEST_F(RenderFrameHostManagerTest,
// Navigate to the first page.
contents()->NavigateAndCommit(kUrl1);
- TestRenderViewHost* rvh1 = test_rvh();
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
+ TestRenderFrameHost* rfh1 = main_test_rfh();
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
// Navigate to a new site, starting a cross-site navigation.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ controller().LoadURL(
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
{
pending_rfh = contents()->GetFrameTree()->root()->render_manager()
->pending_frame_host();
- RenderFrameHostDeletedObserver rvh_deleted_observer(pending_rfh);
+ RenderFrameHostDeletedObserver rfh_deleted_observer(pending_rfh);
// Cancel the navigation by simulating a declined beforeunload dialog.
- main_test_rfh()->OnMessageReceived(
+ contents()->GetMainFrame()->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, false, now, now));
EXPECT_FALSE(contents()->cross_navigation_pending());
// Since the pending RFH is the only one for the new SiteInstance, it should
// be deleted.
- EXPECT_TRUE(rvh_deleted_observer.deleted());
+ EXPECT_TRUE(rfh_deleted_observer.deleted());
}
// Start another cross-site navigation.
- controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ controller().LoadURL(
+ kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
{
pending_rfh = contents()->GetFrameTree()->root()->render_manager()
->pending_frame_host();
- RenderFrameHostDeletedObserver rvh_deleted_observer(pending_rfh);
+ RenderFrameHostDeletedObserver rfh_deleted_observer(pending_rfh);
- // Increment the number of active views in the new SiteInstance, which will
+ // Increment the number of active frames in the new SiteInstance, which will
// cause the pending RFH to be swapped out instead of deleted.
- static_cast<SiteInstanceImpl*>(
- pending_rfh->GetSiteInstance())->increment_active_view_count();
+ pending_rfh->GetSiteInstance()->increment_active_frame_count();
- main_test_rfh()->OnMessageReceived(
+ contents()->GetMainFrame()->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, false, now, now));
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_FALSE(rvh_deleted_observer.deleted());
+ EXPECT_FALSE(rfh_deleted_observer.deleted());
}
}
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.h b/chromium/content/browser/frame_host/render_frame_message_filter.h
index 25f7fbd57ad..0de54b10e83 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -21,10 +21,10 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
RenderFrameMessageFilter(int render_process_id,
RenderWidgetHelper* render_widget_helper);
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~RenderFrameMessageFilter();
+ ~RenderFrameMessageFilter() override;
void OnCreateChildFrame(int parent_routing_id,
const std::string& frame_name,
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.cc b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
index 2c84798fa2c..3db9edf613d 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -4,23 +4,52 @@
#include "content/browser/frame_host/render_frame_proxy_host.h"
+#include "base/lazy_instance.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
+#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/frame_messages.h"
+#include "content/public/browser/browser_thread.h"
#include "ipc/ipc_message.h"
namespace content {
+namespace {
+
+// The (process id, routing id) pair that identifies one RenderFrameProxy.
+typedef std::pair<int32, int32> RenderFrameProxyHostID;
+typedef base::hash_map<RenderFrameProxyHostID, RenderFrameProxyHost*>
+ RoutingIDFrameProxyMap;
+base::LazyInstance<RoutingIDFrameProxyMap> g_routing_id_frame_proxy_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+}
+
+// static
+RenderFrameProxyHost* RenderFrameProxyHost::FromID(int process_id,
+ int routing_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RoutingIDFrameProxyMap* frames = g_routing_id_frame_proxy_map.Pointer();
+ RoutingIDFrameProxyMap::iterator it = frames->find(
+ RenderFrameProxyHostID(process_id, routing_id));
+ return it == frames->end() ? NULL : it->second;
+}
+
RenderFrameProxyHost::RenderFrameProxyHost(SiteInstance* site_instance,
FrameTreeNode* frame_tree_node)
: routing_id_(site_instance->GetProcess()->GetNextRoutingID()),
site_instance_(site_instance),
frame_tree_node_(frame_tree_node) {
GetProcess()->AddRoute(routing_id_, this);
+ CHECK(g_routing_id_frame_proxy_map.Get().insert(
+ std::make_pair(
+ RenderFrameProxyHostID(GetProcess()->GetID(), routing_id_),
+ this)).second);
if (!frame_tree_node_->IsMainFrame() &&
frame_tree_node_->parent()
@@ -39,10 +68,18 @@ RenderFrameProxyHost::RenderFrameProxyHost(SiteInstance* site_instance,
}
RenderFrameProxyHost::~RenderFrameProxyHost() {
- if (GetProcess()->HasConnection())
- Send(new FrameMsg_DeleteProxy(routing_id_));
+ if (GetProcess()->HasConnection()) {
+ // TODO(nasko): For now, don't send this IPC for top-level frames, as
+ // the top-level RenderFrame will delete the RenderFrameProxy.
+ // This can be removed once we don't have a swapped out state on
+ // RenderFrame. See https://crbug.com/357747
+ if (!frame_tree_node_->IsMainFrame())
+ Send(new FrameMsg_DeleteProxy(routing_id_));
+ }
GetProcess()->RemoveRoute(routing_id_);
+ g_routing_id_frame_proxy_map.Get().erase(
+ RenderFrameProxyHostID(GetProcess()->GetID(), routing_id_));
}
void RenderFrameProxyHost::SetChildRWHView(RenderWidgetHostView* view) {
@@ -51,9 +88,14 @@ void RenderFrameProxyHost::SetChildRWHView(RenderWidgetHostView* view) {
}
RenderViewHostImpl* RenderFrameProxyHost::GetRenderViewHost() {
- if (render_frame_host_.get())
- return render_frame_host_->render_view_host();
- return NULL;
+ return frame_tree_node_->frame_tree()->GetRenderViewHost(
+ site_instance_.get());
+}
+
+void RenderFrameProxyHost::TakeFrameHostOwnership(
+ scoped_ptr<RenderFrameHostImpl> render_frame_host) {
+ render_frame_host_ = render_frame_host.Pass();
+ render_frame_host_->set_render_frame_proxy_host(this);
}
scoped_ptr<RenderFrameHostImpl> RenderFrameProxyHost::PassFrameHostOwnership() {
@@ -65,7 +107,11 @@ bool RenderFrameProxyHost::Send(IPC::Message *msg) {
// TODO(nasko): For now, RenderFrameHost uses this object to send IPC messages
// while swapped out. This can be removed once we don't have a swapped out
// state on RenderFrameHosts. See https://crbug.com/357747.
- msg->set_routing_id(routing_id_);
+
+ // Don't reset the routing ID for control messages. See
+ // https://crbug.com/423538
+ if (msg->routing_id() != MSG_ROUTING_CONTROL)
+ msg->set_routing_id(routing_id_);
return GetProcess()->Send(msg);
}
@@ -79,7 +125,48 @@ bool RenderFrameProxyHost::OnMessageReceived(const IPC::Message& msg) {
if (render_frame_host_.get())
return render_frame_host_->OnMessageReceived(msg);
- return false;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RenderFrameProxyHost, msg)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool RenderFrameProxyHost::InitRenderFrameProxy() {
+ // The process may (if we're sharing a process with another host that already
+ // initialized it) or may not (we have our own process or the old process
+ // crashed) have been initialized. Calling Init multiple times will be
+ // ignored, so this is safe.
+ if (!site_instance_->GetProcess()->Init())
+ return false;
+
+ DCHECK(GetProcess()->HasConnection());
+
+ int parent_routing_id = MSG_ROUTING_NONE;
+ if (frame_tree_node_->parent()) {
+ parent_routing_id = frame_tree_node_->parent()
+ ->render_manager()
+ ->GetRoutingIdForSiteInstance(site_instance_.get());
+ CHECK_NE(parent_routing_id, MSG_ROUTING_NONE);
+ }
+
+ Send(new FrameMsg_NewFrameProxy(routing_id_,
+ parent_routing_id,
+ frame_tree_node_->frame_tree()
+ ->GetRenderViewHost(site_instance_.get())
+ ->GetRoutingID()));
+
+ return true;
+}
+
+void RenderFrameProxyHost::DisownOpener() {
+ Send(new FrameMsg_DisownOpener(GetRoutingID()));
+}
+
+void RenderFrameProxyHost::OnOpenURL(
+ const FrameHostMsg_OpenURL_Params& params) {
+ frame_tree_node_->current_frame_host()->OpenURL(params);
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.h b/chromium/content/browser/frame_host/render_frame_proxy_host.h
index 218bcc411df..ed3235ca98b 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.h
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.h
@@ -55,14 +55,20 @@ class RenderFrameProxyHost
: public IPC::Listener,
public IPC::Sender {
public:
+ static RenderFrameProxyHost* FromID(int process_id, int routing_id);
+
RenderFrameProxyHost(SiteInstance* site_instance,
FrameTreeNode* frame_tree_node);
- virtual ~RenderFrameProxyHost();
+ ~RenderFrameProxyHost() override;
RenderProcessHost* GetProcess() {
return site_instance_->GetProcess();
}
+ // Initializes the object and creates the RenderFrameProxy in the process
+ // for the SiteInstance.
+ bool InitRenderFrameProxy();
+
int GetRoutingID() {
return routing_id_;
}
@@ -71,6 +77,8 @@ class RenderFrameProxyHost
return site_instance_.get();
}
+ FrameTreeNode* frame_tree_node() const { return frame_tree_node_; };
+
void SetChildRWHView(RenderWidgetHostView* view);
// TODO(nasko): The following methods should be removed once we don't have a
@@ -81,22 +89,27 @@ class RenderFrameProxyHost
RenderViewHostImpl* GetRenderViewHost();
void TakeFrameHostOwnership(
- scoped_ptr<RenderFrameHostImpl> render_frame_host) {
- render_frame_host_ = render_frame_host.Pass();
- }
+ scoped_ptr<RenderFrameHostImpl> render_frame_host);
scoped_ptr<RenderFrameHostImpl> PassFrameHostOwnership();
// IPC::Sender
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
CrossProcessFrameConnector* cross_process_frame_connector() {
return cross_process_frame_connector_.get();
}
+ // Set the frame's opener to null in the renderer process in response to an
+ // action in another renderer process.
+ void DisownOpener();
+
private:
+ // IPC Message handlers.
+ void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
+
// This RenderFrameProxyHost's routing id.
int routing_id_;
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
index d9e32c92c8b..ab1bff89c81 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -4,6 +4,7 @@
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
@@ -70,6 +71,10 @@ gfx::Rect RenderWidgetHostViewChildFrame::GetViewBounds() const {
return rect;
}
+gfx::Vector2dF RenderWidgetHostViewChildFrame::GetLastScrollOffset() const {
+ return last_scroll_offset_;
+}
+
gfx::NativeView RenderWidgetHostViewChildFrame::GetNativeView() const {
NOTREACHED();
return NULL;
@@ -86,7 +91,7 @@ RenderWidgetHostViewChildFrame::GetNativeViewAccessible() {
return NULL;
}
-void RenderWidgetHostViewChildFrame::SetBackgroundOpaque(bool opaque) {
+void RenderWidgetHostViewChildFrame::SetBackgroundColor(SkColor color) {
}
gfx::Size RenderWidgetHostViewChildFrame::GetPhysicalBackingSize() const {
@@ -111,7 +116,7 @@ void RenderWidgetHostViewChildFrame::ImeCancelComposition() {
NOTREACHED();
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
void RenderWidgetHostViewChildFrame::ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
@@ -122,7 +127,7 @@ void RenderWidgetHostViewChildFrame::ImeCompositionRangeChanged(
void RenderWidgetHostViewChildFrame::WasShown() {
if (!host_->is_hidden())
return;
- host_->WasShown();
+ host_->WasShown(ui::LatencyInfo());
}
void RenderWidgetHostViewChildFrame::WasHidden() {
@@ -145,8 +150,12 @@ void RenderWidgetHostViewChildFrame::SetIsLoading(bool is_loading) {
NOTREACHED();
}
-void RenderWidgetHostViewChildFrame::TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) {
+void RenderWidgetHostViewChildFrame::TextInputTypeChanged(
+ ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
+ NOTREACHED();
}
void RenderWidgetHostViewChildFrame::RenderProcessGone(
@@ -183,11 +192,6 @@ void RenderWidgetHostViewChildFrame::SelectionBoundsChanged(
}
#if defined(OS_ANDROID)
-void RenderWidgetHostViewChildFrame::ShowDisambiguationPopup(
- const gfx::Rect& target_rect,
- const SkBitmap& zoomed_bitmap) {
-}
-
void RenderWidgetHostViewChildFrame::LockCompositingSurface() {
}
@@ -195,28 +199,10 @@ void RenderWidgetHostViewChildFrame::UnlockCompositingSurface() {
}
#endif
-void RenderWidgetHostViewChildFrame::ScrollOffsetChanged() {
-}
-
-void RenderWidgetHostViewChildFrame::AcceleratedSurfaceInitialized(int host_id,
- int route_id) {
-}
-
-void RenderWidgetHostViewChildFrame::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) {
- if (frame_connector_)
- frame_connector_->ChildFrameBuffersSwapped(params, gpu_host_id);
-}
-
-void RenderWidgetHostViewChildFrame::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) {
-}
-
void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame(
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
+ last_scroll_offset_ = frame->metadata.root_scroll_offset;
if (frame_connector_) {
frame_connector_->ChildFrameCompositorFrameSwapped(
output_surface_id,
@@ -253,9 +239,6 @@ void RenderWidgetHostViewChildFrame::UnlockMouse() {
void RenderWidgetHostViewChildFrame::SetActive(bool active) {
}
-void RenderWidgetHostViewChildFrame::SetTakesFocusOnlyOnMouseDown(bool flag) {
-}
-
void RenderWidgetHostViewChildFrame::SetWindowVisibility(bool visible) {
}
@@ -288,8 +271,8 @@ bool RenderWidgetHostViewChildFrame::PostProcessEventForPluginIme(
void RenderWidgetHostViewChildFrame::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& /* dst_size */,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) {
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) {
callback.Run(false, SkBitmap());
}
@@ -305,20 +288,13 @@ bool RenderWidgetHostViewChildFrame::CanCopyToVideoFrame() const {
return false;
}
-void RenderWidgetHostViewChildFrame::AcceleratedSurfaceSuspend() {
- NOTREACHED();
-}
-
-void RenderWidgetHostViewChildFrame::AcceleratedSurfaceRelease() {
-}
-
bool RenderWidgetHostViewChildFrame::HasAcceleratedSurface(
const gfx::Size& desired_size) {
return false;
}
gfx::GLSurfaceHandle RenderWidgetHostViewChildFrame::GetCompositingSurface() {
- return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::TEXTURE_TRANSPORT);
+ return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
}
#if defined(OS_WIN)
@@ -332,8 +308,15 @@ gfx::NativeViewId RenderWidgetHostViewChildFrame::GetParentForWindowlessPlugin()
}
#endif // defined(OS_WIN)
-SkBitmap::Config RenderWidgetHostViewChildFrame::PreferredReadbackFormat() {
- return SkBitmap::kARGB_8888_Config;
+SkColorType RenderWidgetHostViewChildFrame::PreferredReadbackFormat() {
+ return kN32_SkColorType;
+}
+
+BrowserAccessibilityManager*
+RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) {
+ return BrowserAccessibilityManager::Create(
+ BrowserAccessibilityManager::GetEmptyDocument(), delegate);
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
index e288248aa45..b2895f9f7df 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -11,8 +11,6 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
-struct ViewHostMsg_TextInputState_Params;
-
namespace content {
class CrossProcessFrameConnector;
class RenderWidgetHost;
@@ -30,7 +28,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
: public RenderWidgetHostViewBase {
public:
explicit RenderWidgetHostViewChildFrame(RenderWidgetHost* widget);
- virtual ~RenderWidgetHostViewChildFrame();
+ ~RenderWidgetHostViewChildFrame() override;
void set_cross_process_frame_connector(
CrossProcessFrameConnector* frame_connector) {
@@ -38,125 +36,114 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
}
// RenderWidgetHostView implementation.
- virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
- virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void SetBounds(const gfx::Rect& rect) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual bool HasFocus() const OVERRIDE;
- virtual bool IsSurfaceAvailableForCopy() const OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsShowing() OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual void SetBackgroundOpaque(bool opaque) OVERRIDE;
- virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE;
+ void InitAsChild(gfx::NativeView parent_view) override;
+ RenderWidgetHost* GetRenderWidgetHost() const override;
+ void SetSize(const gfx::Size& size) override;
+ void SetBounds(const gfx::Rect& rect) override;
+ void Focus() override;
+ bool HasFocus() const override;
+ bool IsSurfaceAvailableForCopy() const override;
+ void Show() override;
+ void Hide() override;
+ bool IsShowing() override;
+ gfx::Rect GetViewBounds() const override;
+ gfx::Vector2dF GetLastScrollOffset() const override;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeViewId GetNativeViewId() const override;
+ gfx::NativeViewAccessible GetNativeViewAccessible() override;
+ void SetBackgroundColor(SkColor color) override;
+ gfx::Size GetPhysicalBackingSize() const override;
// RenderWidgetHostViewBase implementation.
- virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
- const gfx::Rect& pos) OVERRIDE;
- virtual void InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) OVERRIDE;
- virtual void WasShown() OVERRIDE;
- virtual void WasHidden() OVERRIDE;
- virtual void MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) OVERRIDE;
- virtual void Blur() OVERRIDE;
- virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
- virtual void SetIsLoading(bool is_loading) OVERRIDE;
- virtual void TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) OVERRIDE;
- virtual void ImeCancelComposition() OVERRIDE;
-#if defined(OS_MACOSX) || defined(USE_AURA)
- virtual void ImeCompositionRangeChanged(
+ void InitAsPopup(RenderWidgetHostView* parent_host_view,
+ const gfx::Rect& pos) override;
+ void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
+ void WasShown() override;
+ void WasHidden() override;
+ void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
+ void Blur() override;
+ void UpdateCursor(const WebCursor& cursor) override;
+ void SetIsLoading(bool is_loading) override;
+ void TextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) override;
+ void ImeCancelComposition() override;
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
+ void ImeCompositionRangeChanged(
const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
+ const std::vector<gfx::Rect>& character_bounds) override;
#endif
- virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const base::string16& text,
- size_t offset,
- const gfx::Range& range) OVERRIDE;
- virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
- virtual void ScrollOffsetChanged() OVERRIDE;
- virtual void CopyFromCompositingSurface(
+ void RenderProcessGone(base::TerminationStatus status,
+ int error_code) override;
+ void Destroy() override;
+ void SetTooltipText(const base::string16& tooltip_text) override;
+ void SelectionChanged(const base::string16& text,
+ size_t offset,
+ const gfx::Range& range) override;
+ void SelectionBoundsChanged(
+ const ViewHostMsg_SelectionBounds_Params& params) override;
+ void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) OVERRIDE;
- virtual void CopyFromCompositingSurfaceToVideoFrame(
+ const SkColorType color_type) override;
+ void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool CanCopyToVideoFrame() const OVERRIDE;
- virtual void AcceleratedSurfaceInitialized(int host_id,
- int route_id) OVERRIDE;
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfaceSuspend() OVERRIDE;
- virtual void AcceleratedSurfaceRelease() OVERRIDE;
- virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void OnSwapCompositorFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
- virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
- virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
- virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
+ const base::Callback<void(bool)>& callback) override;
+ bool CanCopyToVideoFrame() const override;
+ bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
+ void OnSwapCompositorFrame(uint32 output_surface_id,
+ scoped_ptr<cc::CompositorFrame> frame) override;
+ void GetScreenInfo(blink::WebScreenInfo* results) override;
+ gfx::Rect GetBoundsInRootWindow() override;
+ gfx::GLSurfaceHandle GetCompositingSurface() override;
#if defined(USE_AURA)
- virtual void ProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) OVERRIDE;
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) override;
#endif // defined(USE_AURA)
- virtual bool LockMouse() OVERRIDE;
- virtual void UnlockMouse() OVERRIDE;
+ bool LockMouse() override;
+ void UnlockMouse() override;
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
- virtual void SetActive(bool active) OVERRIDE;
- virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE;
- virtual void SetWindowVisibility(bool visible) OVERRIDE;
- virtual void WindowFrameChanged() OVERRIDE;
- virtual void ShowDefinitionForSelection() OVERRIDE;
- virtual bool SupportsSpeech() const OVERRIDE;
- virtual void SpeakSelection() OVERRIDE;
- virtual bool IsSpeaking() const OVERRIDE;
- virtual void StopSpeaking() OVERRIDE;
+ void SetActive(bool active) override;
+ void SetWindowVisibility(bool visible) override;
+ void WindowFrameChanged() override;
+ void ShowDefinitionForSelection() override;
+ bool SupportsSpeech() const override;
+ void SpeakSelection() override;
+ bool IsSpeaking() const override;
+ void StopSpeaking() override;
// RenderWidgetHostViewBase implementation.
- virtual bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) OVERRIDE;
+ bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) override;
#endif // defined(OS_MACOSX)
-#if defined(OS_ANDROID)
// RenderWidgetHostViewBase implementation.
- virtual void ShowDisambiguationPopup(
- const gfx::Rect& target_rect,
- const SkBitmap& zoomed_bitmap) OVERRIDE;
- virtual void LockCompositingSurface() OVERRIDE;
- virtual void UnlockCompositingSurface() OVERRIDE;
+#if defined(OS_ANDROID)
+ virtual void LockCompositingSurface() override;
+ virtual void UnlockCompositingSurface() override;
#endif // defined(OS_ANDROID)
#if defined(OS_WIN)
virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) OVERRIDE;
- virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE;
+ gfx::NativeViewAccessible accessible_parent) override;
+ virtual gfx::NativeViewId GetParentForWindowlessPlugin() const override;
#endif
+ BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) override;
- virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
+ SkColorType PreferredReadbackFormat() override;
protected:
friend class RenderWidgetHostView;
+ // The last scroll offset of the view.
+ gfx::Vector2dF last_scroll_offset_;
+
// Members will become private when RenderWidgetHostViewGuest is removed.
// The model object.
RenderWidgetHostImpl* host_;
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
index 95b4eb36391..7d731ff90fd 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -20,14 +20,14 @@ namespace {
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
};
class RenderWidgetHostViewChildFrameTest : public testing::Test {
public:
RenderWidgetHostViewChildFrameTest() {}
- virtual void SetUp() {
+ void SetUp() override {
browser_context_.reset(new TestBrowserContext);
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
@@ -36,7 +36,7 @@ class RenderWidgetHostViewChildFrameTest : public testing::Test {
view_ = new RenderWidgetHostViewChildFrame(widget_host_);
}
- virtual void TearDown() {
+ void TearDown() override {
if (view_)
view_->Destroy();
delete widget_host_;
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
index 8a02c69f5ea..708f8bf0364 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -12,7 +12,6 @@
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/gpu_messages.h"
-#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/input/web_touch_event_traits.h"
#include "content/common/view_messages.h"
#include "content/common/webplugin_geometry.h"
@@ -47,7 +46,7 @@ blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
RenderWidgetHost* widget_host,
BrowserPluginGuest* guest,
- RenderWidgetHostViewBase* platform_view)
+ base::WeakPtr<RenderWidgetHostViewBase> platform_view)
: RenderWidgetHostViewChildFrame(widget_host),
// |guest| is NULL during test.
guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()),
@@ -64,6 +63,19 @@ RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
#endif // defined(USE_AURA)
}
+bool RenderWidgetHostViewGuest::OnMessageReceivedFromEmbedder(
+ const IPC::Message& message,
+ RenderWidgetHostImpl* embedder) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(RenderWidgetHostViewGuest, message,
+ embedder)
+ IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_HandleInputEvent,
+ OnHandleInputEvent)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
void RenderWidgetHostViewGuest::WasShown() {
// If the WebContents associated with us showed an interstitial page in the
// beginning, the teardown path might call WasShown() while |host_| is in
@@ -74,7 +86,13 @@ void RenderWidgetHostViewGuest::WasShown() {
// |guest_| is NULL during test.
if ((guest_ && guest_->is_in_destruction()) || !host_->is_hidden())
return;
- host_->WasShown();
+ // Make sure the size of this view matches the size of the WebContentsView.
+ // The two sizes may fall out of sync if we switch RenderWidgetHostViews,
+ // resize, and then switch page, as is the case with interstitial pages.
+ // NOTE: |guest_| is NULL in unit tests.
+ if (guest_)
+ SetSize(guest_->web_contents()->GetViewBounds().size());
+ host_->WasShown(ui::LatencyInfo());
}
void RenderWidgetHostViewGuest::WasHidden() {
@@ -93,6 +111,20 @@ void RenderWidgetHostViewGuest::SetBounds(const gfx::Rect& rect) {
SetSize(rect.size());
}
+void RenderWidgetHostViewGuest::Focus() {
+ // InterstitialPageImpl focuses views directly, so we place focus logic here.
+ // InterstitialPages are not WebContents, and so BrowserPluginGuest does not
+ // have direct access to the interstitial page's RenderWidgetHost.
+ if (guest_)
+ guest_->SetFocus(host_, true);
+}
+
+bool RenderWidgetHostViewGuest::HasFocus() const {
+ if (!guest_)
+ return false;
+ return guest_->focused();
+}
+
#if defined(USE_AURA)
void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch, InputEventAckState ack_result) {
@@ -109,8 +141,11 @@ void RenderWidgetHostViewGuest::ProcessAckedTouchEvent(
INPUT_EVENT_ACK_STATE_CONSUMED) ? ui::ER_HANDLED : ui::ER_UNHANDLED;
for (ScopedVector<ui::TouchEvent>::iterator iter = events.begin(),
end = events.end(); iter != end; ++iter) {
+ if (!gesture_recognizer_->ProcessTouchEventPreDispatch(*(*iter), this))
+ continue;
+
scoped_ptr<ui::GestureRecognizer::Gestures> gestures;
- gestures.reset(gesture_recognizer_->ProcessTouchEventForGesture(
+ gestures.reset(gesture_recognizer_->ProcessTouchEventPostDispatch(
*(*iter), result, this));
ProcessGestures(gestures.get());
}
@@ -125,10 +160,8 @@ gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
gfx::Rect embedder_bounds;
if (rwhv)
embedder_bounds = rwhv->GetViewBounds();
- gfx::Rect shifted_rect = guest_->ToGuestRect(embedder_bounds);
- shifted_rect.set_width(size_.width());
- shifted_rect.set_height(size_.height());
- return shifted_rect;
+ return gfx::Rect(
+ guest_->GetScreenCoordinates(embedder_bounds.origin()), size_);
}
void RenderWidgetHostViewGuest::RenderProcessGone(
@@ -144,7 +177,8 @@ void RenderWidgetHostViewGuest::Destroy() {
// The RenderWidgetHost's destruction led here, so don't call it.
DestroyGuestView();
- platform_view_->Destroy();
+ if (platform_view_) // The platform view might have been destroyed already.
+ platform_view_->Destroy();
}
gfx::Size RenderWidgetHostViewGuest::GetPhysicalBackingSize() const {
@@ -157,29 +191,8 @@ base::string16 RenderWidgetHostViewGuest::GetSelectedText() const {
void RenderWidgetHostViewGuest::SetTooltipText(
const base::string16& tooltip_text) {
- platform_view_->SetTooltipText(tooltip_text);
-}
-
-void RenderWidgetHostViewGuest::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) {
- if (!guest_)
- return;
-
- FrameMsg_BuffersSwapped_Params guest_params;
- guest_params.size = params.size;
- guest_params.mailbox = params.mailbox;
- guest_params.gpu_route_id = params.route_id;
- guest_params.gpu_host_id = gpu_host_id;
- guest_->SendMessageToEmbedder(
- new BrowserPluginMsg_BuffersSwapped(guest_->instance_id(),
- guest_params));
-}
-
-void RenderWidgetHostViewGuest::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) {
- NOTREACHED();
+ if (guest_)
+ guest_->SetTooltipText(tooltip_text);
}
void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
@@ -188,39 +201,11 @@ void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
if (!guest_)
return;
- if (!guest_->attached()) {
- // If the guest doesn't have an embedder then there's nothing to give the
- // the frame to.
- return;
- }
- base::SharedMemoryHandle software_frame_handle =
- base::SharedMemory::NULLHandle();
- if (frame->software_frame_data) {
- cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
- scoped_ptr<cc::SharedBitmap> bitmap =
- HostSharedBitmapManager::current()->GetSharedBitmapFromId(
- frame_data->size, frame_data->bitmap_id);
- if (!bitmap)
- return;
-
- RenderWidgetHostView* embedder_rwhv =
- guest_->GetEmbedderRenderWidgetHostView();
- base::ProcessHandle embedder_pid =
- embedder_rwhv->GetRenderWidgetHost()->GetProcess()->GetHandle();
-
- bitmap->memory()->ShareToProcess(embedder_pid, &software_frame_handle);
- }
-
- FrameMsg_CompositorFrameSwapped_Params guest_params;
- frame->AssignTo(&guest_params.frame);
- guest_params.output_surface_id = output_surface_id;
- guest_params.producing_route_id = host_->GetRoutingID();
- guest_params.producing_host_id = host_->GetProcess()->GetID();
- guest_params.shared_memory_handle = software_frame_handle;
-
- guest_->SendMessageToEmbedder(
- new BrowserPluginMsg_CompositorFrameSwapped(guest_->instance_id(),
- guest_params));
+ last_scroll_offset_ = frame->metadata.root_scroll_offset;
+ guest_->SwapCompositorFrame(output_surface_id,
+ host_->GetProcess()->GetID(),
+ host_->GetRoutingID(),
+ frame.Pass());
}
bool RenderWidgetHostViewGuest::OnMessageReceived(const IPC::Message& msg) {
@@ -280,15 +265,27 @@ void RenderWidgetHostViewGuest::MovePluginWindows(
}
void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
- platform_view_->UpdateCursor(cursor);
+ // InterstitialPages are not WebContents so we cannot intercept
+ // ViewHostMsg_SetCursor for interstitial pages in BrowserPluginGuest.
+ // All guest RenderViewHosts have RenderWidgetHostViewGuests however,
+ // and so we will always hit this code path.
+ if (!guest_)
+ return;
+ guest_->SendMessageToEmbedder(
+ new BrowserPluginMsg_SetCursor(guest_->browser_plugin_instance_id(),
+ cursor));
+
}
void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
platform_view_->SetIsLoading(is_loading);
}
-void RenderWidgetHostViewGuest::TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) {
+void RenderWidgetHostViewGuest::TextInputTypeChanged(
+ ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
if (!guest_)
return;
@@ -296,7 +293,7 @@ void RenderWidgetHostViewGuest::TextInputStateChanged(
if (!rwhv)
return;
// Forward the information to embedding RWHV.
- rwhv->TextInputStateChanged(params);
+ rwhv->TextInputTypeChanged(type, input_mode, can_compose_inline, flags);
}
void RenderWidgetHostViewGuest::ImeCancelComposition() {
@@ -322,8 +319,9 @@ void RenderWidgetHostViewGuest::ImeCompositionRangeChanged(
return;
std::vector<gfx::Rect> guest_character_bounds;
for (size_t i = 0; i < character_bounds.size(); ++i) {
- gfx::Rect guest_rect = guest_->ToGuestRect(character_bounds[i]);
- guest_character_bounds.push_back(guest_rect);
+ guest_character_bounds.push_back(gfx::Rect(
+ guest_->GetScreenCoordinates(character_bounds[i].origin()),
+ character_bounds[i].size()));
}
// Forward the information to embedding RWHV.
rwhv->ImeCompositionRangeChanged(range, guest_character_bounds);
@@ -345,22 +343,24 @@ void RenderWidgetHostViewGuest::SelectionBoundsChanged(
if (!rwhv)
return;
ViewHostMsg_SelectionBounds_Params guest_params(params);
- guest_params.anchor_rect = guest_->ToGuestRect(params.anchor_rect);
- guest_params.focus_rect = guest_->ToGuestRect(params.focus_rect);
+ guest_params.anchor_rect.set_origin(
+ guest_->GetScreenCoordinates(params.anchor_rect.origin()));
+ guest_params.focus_rect.set_origin(
+ guest_->GetScreenCoordinates(params.focus_rect.origin()));
rwhv->SelectionBoundsChanged(guest_params);
}
-void RenderWidgetHostViewGuest::CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) {
- CHECK(guest_);
- guest_->CopyFromCompositingSurface(src_subrect, dst_size, callback);
-}
-
-void RenderWidgetHostViewGuest::SetBackgroundOpaque(bool opaque) {
- platform_view_->SetBackgroundOpaque(opaque);
+void RenderWidgetHostViewGuest::SetBackgroundColor(SkColor color) {
+ // Content embedders can toggle opaque backgrounds through this API.
+ // We plumb the value here so that BrowserPlugin updates its compositing
+ // state in response to this change. We also want to preserve this flag
+ // after recovering from a crash so we let BrowserPluginGuest store it.
+ if (!guest_)
+ return;
+ RenderWidgetHostViewBase::SetBackgroundColor(color);
+ bool opaque = GetBackgroundOpaque();
+ host_->SetBackgroundOpaque(opaque);
+ guest_->SetContentsOpaque(opaque);
}
bool RenderWidgetHostViewGuest::LockMouse() {
@@ -384,10 +384,6 @@ void RenderWidgetHostViewGuest::SetActive(bool active) {
platform_view_->SetActive(active);
}
-void RenderWidgetHostViewGuest::SetTakesFocusOnlyOnMouseDown(bool flag) {
- platform_view_->SetTakesFocusOnlyOnMouseDown(flag);
-}
-
void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
platform_view_->SetWindowVisibility(visible);
}
@@ -413,7 +409,7 @@ void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
// Vertical offset from guest's top to embedder's bottom edge.
embedder_bounds.bottom() - guest_bounds.y());
- RenderWidgetHostViewMacDictionaryHelper helper(platform_view_);
+ RenderWidgetHostViewMacDictionaryHelper helper(platform_view_.get());
helper.SetTargetView(rwhv);
helper.set_offset(guest_offset);
helper.ShowDefinitionForSelection();
@@ -442,12 +438,14 @@ bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
#endif // defined(OS_MACOSX)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
void RenderWidgetHostViewGuest::ShowDisambiguationPopup(
- const gfx::Rect& target_rect,
+ const gfx::Rect& rect_pixels,
const SkBitmap& zoomed_bitmap) {
}
+#endif // defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
+#if defined(OS_ANDROID)
void RenderWidgetHostViewGuest::LockCompositingSurface() {
}
@@ -544,8 +542,8 @@ void RenderWidgetHostViewGuest::ProcessGestures(
}
}
-SkBitmap::Config RenderWidgetHostViewGuest::PreferredReadbackFormat() {
- return SkBitmap::kARGB_8888_Config;
+SkColorType RenderWidgetHostViewGuest::PreferredReadbackFormat() {
+ return kN32_SkColorType;
}
RenderWidgetHostViewBase*
@@ -554,4 +552,43 @@ RenderWidgetHostViewGuest::GetGuestRenderWidgetHostView() const {
guest_->GetEmbedderRenderWidgetHostView());
}
+void RenderWidgetHostViewGuest::OnHandleInputEvent(
+ RenderWidgetHostImpl* embedder,
+ int browser_plugin_instance_id,
+ const gfx::Rect& guest_window_rect,
+ const blink::WebInputEvent* event) {
+ if (blink::WebInputEvent::isMouseEventType(event->type)) {
+ host_->ForwardMouseEvent(
+ *static_cast<const blink::WebMouseEvent*>(event));
+ return;
+ }
+
+ if (event->type == blink::WebInputEvent::MouseWheel) {
+ host_->ForwardWheelEvent(
+ *static_cast<const blink::WebMouseWheelEvent*>(event));
+ return;
+ }
+
+ if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
+ if (!embedder->GetLastKeyboardEvent())
+ return;
+ NativeWebKeyboardEvent keyboard_event(*embedder->GetLastKeyboardEvent());
+ host_->ForwardKeyboardEvent(keyboard_event);
+ return;
+ }
+
+ if (blink::WebInputEvent::isTouchEventType(event->type)) {
+ host_->ForwardTouchEventWithLatencyInfo(
+ *static_cast<const blink::WebTouchEvent*>(event),
+ ui::LatencyInfo());
+ return;
+ }
+
+ if (blink::WebInputEvent::isGestureEventType(event->type)) {
+ host_->ForwardGestureEvent(
+ *static_cast<const blink::WebGestureEvent*>(event));
+ return;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest.h b/chromium/content/browser/frame_host/render_widget_host_view_guest.h
index 6132b4e8655..2ebd4e66845 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest.h
@@ -18,12 +18,10 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
-struct ViewHostMsg_TextInputState_Params;
-
namespace content {
+class BrowserPluginGuest;
class RenderWidgetHost;
class RenderWidgetHostImpl;
-class BrowserPluginGuest;
struct NativeWebKeyboardEvent;
// See comments in render_widget_host_view.h about this class and its members.
@@ -41,112 +39,107 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
public ui::GestureConsumer,
public ui::GestureEventHelper {
public:
- RenderWidgetHostViewGuest(RenderWidgetHost* widget,
- BrowserPluginGuest* guest,
- RenderWidgetHostViewBase* platform_view);
- virtual ~RenderWidgetHostViewGuest();
+ RenderWidgetHostViewGuest(
+ RenderWidgetHost* widget,
+ BrowserPluginGuest* guest,
+ base::WeakPtr<RenderWidgetHostViewBase> platform_view);
+ ~RenderWidgetHostViewGuest() override;
+
+ bool OnMessageReceivedFromEmbedder(const IPC::Message& message,
+ RenderWidgetHostImpl* embedder);
// RenderWidgetHostView implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void SetBounds(const gfx::Rect& rect) OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual void SetBackgroundOpaque(bool opaque) OVERRIDE;
- virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE;
- virtual base::string16 GetSelectedText() const OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void InitAsChild(gfx::NativeView parent_view) override;
+ void SetSize(const gfx::Size& size) override;
+ void SetBounds(const gfx::Rect& rect) override;
+ void Focus() override;
+ bool HasFocus() const override;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeViewId GetNativeViewId() const override;
+ gfx::NativeViewAccessible GetNativeViewAccessible() override;
+ gfx::Rect GetViewBounds() const override;
+ void SetBackgroundColor(SkColor color) override;
+ gfx::Size GetPhysicalBackingSize() const override;
+ base::string16 GetSelectedText() const override;
// RenderWidgetHostViewBase implementation.
- virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
- const gfx::Rect& pos) OVERRIDE;
- virtual void InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) OVERRIDE;
- virtual void WasShown() OVERRIDE;
- virtual void WasHidden() OVERRIDE;
- virtual void MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) OVERRIDE;
- virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
- virtual void SetIsLoading(bool is_loading) OVERRIDE;
- virtual void TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) OVERRIDE;
- virtual void ImeCancelComposition() OVERRIDE;
+ void InitAsPopup(RenderWidgetHostView* parent_host_view,
+ const gfx::Rect& pos) override;
+ void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
+ void WasShown() override;
+ void WasHidden() override;
+ void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
+ void UpdateCursor(const WebCursor& cursor) override;
+ void SetIsLoading(bool is_loading) override;
+ void TextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) override;
+ void ImeCancelComposition() override;
#if defined(OS_MACOSX) || defined(USE_AURA)
- virtual void ImeCompositionRangeChanged(
+ void ImeCompositionRangeChanged(
const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
+ const std::vector<gfx::Rect>& character_bounds) override;
#endif
- virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const base::string16& text,
- size_t offset,
- const gfx::Range& range) OVERRIDE;
- virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
- virtual void CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) OVERRIDE;
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void OnSwapCompositorFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
+ void RenderProcessGone(base::TerminationStatus status,
+ int error_code) override;
+ void Destroy() override;
+ void SetTooltipText(const base::string16& tooltip_text) override;
+ void SelectionChanged(const base::string16& text,
+ size_t offset,
+ const gfx::Range& range) override;
+ void SelectionBoundsChanged(
+ const ViewHostMsg_SelectionBounds_Params& params) override;
+ void OnSwapCompositorFrame(uint32 output_surface_id,
+ scoped_ptr<cc::CompositorFrame> frame) override;
#if defined(USE_AURA)
- virtual void ProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) OVERRIDE;
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) override;
#endif
- virtual bool LockMouse() OVERRIDE;
- virtual void UnlockMouse() OVERRIDE;
- virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
+ bool LockMouse() override;
+ void UnlockMouse() override;
+ void GetScreenInfo(blink::WebScreenInfo* results) override;
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
- virtual void SetActive(bool active) OVERRIDE;
- virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE;
- virtual void SetWindowVisibility(bool visible) OVERRIDE;
- virtual void WindowFrameChanged() OVERRIDE;
- virtual void ShowDefinitionForSelection() OVERRIDE;
- virtual bool SupportsSpeech() const OVERRIDE;
- virtual void SpeakSelection() OVERRIDE;
- virtual bool IsSpeaking() const OVERRIDE;
- virtual void StopSpeaking() OVERRIDE;
+ void SetActive(bool active) override;
+ void SetWindowVisibility(bool visible) override;
+ void WindowFrameChanged() override;
+ void ShowDefinitionForSelection() override;
+ bool SupportsSpeech() const override;
+ void SpeakSelection() override;
+ bool IsSpeaking() const override;
+ void StopSpeaking() override;
// RenderWidgetHostViewBase implementation.
- virtual bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) OVERRIDE;
+ bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) override;
#endif // defined(OS_MACOSX)
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
// RenderWidgetHostViewBase implementation.
- virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
- const SkBitmap& zoomed_bitmap) OVERRIDE;
- virtual void LockCompositingSurface() OVERRIDE;
- virtual void UnlockCompositingSurface() OVERRIDE;
+ void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap) override;
+#endif // defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
+
+#if defined(OS_ANDROID)
+ virtual void LockCompositingSurface() override;
+ virtual void UnlockCompositingSurface() override;
#endif // defined(OS_ANDROID)
#if defined(OS_WIN)
virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) OVERRIDE;
- virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE;
+ gfx::NativeViewAccessible accessible_parent) override;
+ virtual gfx::NativeViewId GetParentForWindowlessPlugin() const override;
#endif
// Overridden from ui::GestureEventHelper.
- virtual bool CanDispatchToConsumer(ui::GestureConsumer* consumer) OVERRIDE;
- virtual void DispatchGestureEvent(ui::GestureEvent* event) OVERRIDE;
- virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
+ bool CanDispatchToConsumer(ui::GestureConsumer* consumer) override;
+ void DispatchGestureEvent(ui::GestureEvent* event) override;
+ void DispatchCancelTouchEvent(ui::TouchEvent* event) override;
- virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
+ SkColorType PreferredReadbackFormat() override;
protected:
friend class RenderWidgetHostView;
@@ -163,6 +156,11 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
RenderWidgetHostViewBase* GetGuestRenderWidgetHostView() const;
+ void OnHandleInputEvent(RenderWidgetHostImpl* embedder,
+ int browser_plugin_instance_id,
+ const gfx::Rect& guest_window_rect,
+ const blink::WebInputEvent* event);
+
// BrowserPluginGuest and RenderWidgetHostViewGuest's lifetimes are not tied
// to one another, therefore we access |guest_| through WeakPtr.
base::WeakPtr<BrowserPluginGuest> guest_;
@@ -170,7 +168,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
// The platform view for this RenderWidgetHostView.
// RenderWidgetHostViewGuest mostly only cares about stuff related to
// compositing, the rest are directly forwared to this |platform_view_|.
- RenderWidgetHostViewBase* platform_view_;
+ base::WeakPtr<RenderWidgetHostViewBase> platform_view_;
#if defined(USE_AURA)
scoped_ptr<ui::GestureRecognizer> gesture_recognizer_;
#endif
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index 172be978f61..968dc8abc07 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -20,24 +20,25 @@ namespace {
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
};
class RenderWidgetHostViewGuestTest : public testing::Test {
public:
RenderWidgetHostViewGuestTest() {}
- virtual void SetUp() {
+ void SetUp() override {
browser_context_.reset(new TestBrowserContext);
MockRenderProcessHost* process_host =
new MockRenderProcessHost(browser_context_.get());
widget_host_ = new RenderWidgetHostImpl(
&delegate_, process_host, MSG_ROUTING_NONE, false);
view_ = new RenderWidgetHostViewGuest(
- widget_host_, NULL, new TestRenderWidgetHostView(widget_host_));
+ widget_host_, NULL,
+ (new TestRenderWidgetHostView(widget_host_))->GetWeakPtr());
}
- virtual void TearDown() {
+ void TearDown() override {
if (view_)
view_->Destroy();
delete widget_host_;
diff --git a/chromium/content/browser/gamepad/canonical_axis_index_list.h b/chromium/content/browser/gamepad/canonical_axis_index_list.h
deleted file mode 100644
index 58b85a6e189..00000000000
--- a/chromium/content/browser/gamepad/canonical_axis_index_list.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 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 intentionally does not have header guards, it's included
-// inside a macro to generate enum values.
-
-// This file defines the canonical axes mapping order for gamepad-like devices.
-
-// TODO(SaurabhK): Consolidate with CanonicalAxisIndex enum in
-// gamepad_standard_mappings.h, crbug.com/351558.
-CANONICAL_AXIS_INDEX(AXIS_LEFT_STICK_X, 0)
-CANONICAL_AXIS_INDEX(AXIS_LEFT_STICK_Y, 1)
-CANONICAL_AXIS_INDEX(AXIS_RIGHT_STICK_X, 2)
-CANONICAL_AXIS_INDEX(AXIS_RIGHT_STICK_Y, 3)
-CANONICAL_AXIS_INDEX(NUM_CANONICAL_AXES, 4)
diff --git a/chromium/content/browser/gamepad/canonical_button_index_list.h b/chromium/content/browser/gamepad/canonical_button_index_list.h
deleted file mode 100644
index 153ce0ea3dd..00000000000
--- a/chromium/content/browser/gamepad/canonical_button_index_list.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 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 intentionally does not have header guards, it's included
-// inside a macro to generate enum values.
-// This defines the canonical button mapping order for gamepad-like devices.
-
-// TODO(SaurabhK): Consolidate with CanonicalButtonIndex enum in
-// gamepad_standard_mappings.h, crbug.com/351558.
-CANONICAL_BUTTON_INDEX(BUTTON_PRIMARY, 0)
-CANONICAL_BUTTON_INDEX(BUTTON_SECONDARY, 1)
-CANONICAL_BUTTON_INDEX(BUTTON_TERTIARY, 2)
-CANONICAL_BUTTON_INDEX(BUTTON_QUATERNARY, 3)
-CANONICAL_BUTTON_INDEX(BUTTON_LEFT_SHOULDER, 4)
-CANONICAL_BUTTON_INDEX(BUTTON_RIGHT_SHOULDER, 5)
-CANONICAL_BUTTON_INDEX(BUTTON_LEFT_TRIGGER, 6)
-CANONICAL_BUTTON_INDEX(BUTTON_RIGHT_TRIGGER, 7)
-CANONICAL_BUTTON_INDEX(BUTTON_BACK_SELECT, 8)
-CANONICAL_BUTTON_INDEX(BUTTON_START, 9)
-CANONICAL_BUTTON_INDEX(BUTTON_LEFT_THUMBSTICK, 10)
-CANONICAL_BUTTON_INDEX(BUTTON_RIGHT_THUMBSTICK, 11)
-CANONICAL_BUTTON_INDEX(BUTTON_DPAD_UP, 12)
-CANONICAL_BUTTON_INDEX(BUTTON_DPAD_DOWN, 13)
-CANONICAL_BUTTON_INDEX(BUTTON_DPAD_LEFT, 14)
-CANONICAL_BUTTON_INDEX(BUTTON_DPAD_RIGHT, 15)
-CANONICAL_BUTTON_INDEX(BUTTON_META, 16)
-CANONICAL_BUTTON_INDEX(NUM_CANONICAL_BUTTONS, 17) \ No newline at end of file
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
index f3cf7cc7055..9cb4cd11ed7 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher.h
@@ -47,7 +47,7 @@ class GamepadDataFetcherEmpty : public GamepadDataFetcher {
GamepadDataFetcherEmpty();
virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) OVERRIDE;
+ bool devices_changed_hint) override;
private:
DISALLOW_COPY_AND_ASSIGN(GamepadDataFetcherEmpty);
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h
index bbbdc1f2c05..989a467a291 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_android.h
@@ -23,10 +23,10 @@ class GamepadPlatformDataFetcherAndroid : public GamepadDataFetcher {
GamepadPlatformDataFetcherAndroid();
virtual ~GamepadPlatformDataFetcherAndroid();
- virtual void PauseHint(bool paused) OVERRIDE;
+ virtual void PauseHint(bool paused) override;
virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) OVERRIDE;
+ bool devices_changed_hint) override;
// Registers the JNI methods for GamepadsReader.
static bool RegisterGamepadPlatformDataFetcherAndroid(JNIEnv* env);
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
index a211bb67df1..e99a5e15904 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
@@ -20,6 +20,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/udev_linux.h"
+#include "device/udev_linux/scoped_udev.h"
namespace {
@@ -126,9 +127,7 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
// hardware, get the parent device that is also in the "input" subsystem.
// This function should just walk up the tree one level.
dev = udev_device_get_parent_with_subsystem_devtype(
- dev,
- kInputSubsystem,
- NULL);
+ dev, kInputSubsystem, NULL);
if (!dev) {
// Unable to get device information, don't use this device.
device_fd = -1;
@@ -156,10 +155,8 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
// as good as the information that the device bus has, walk up further
// to the subsystem/device type "usb"/"usb_device" and if this device
// has the same vendor/product id, prefer the description from that.
- struct udev_device *usb_dev = udev_device_get_parent_with_subsystem_devtype(
- dev,
- kUsbSubsystem,
- kUsbDeviceType);
+ struct udev_device* usb_dev = udev_device_get_parent_with_subsystem_devtype(
+ dev, kUsbSubsystem, kUsbDeviceType);
if (usb_dev) {
const char* usb_vendor_id =
udev_device_get_sysattr_value(usb_dev, "idVendor");
@@ -181,11 +178,11 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
// Append the vendor and product information then convert the utf-8
// id string to WebUChar.
- std::string id = name_string + base::StringPrintf(
- " (%sVendor: %s Product: %s)",
- mapper ? "STANDARD GAMEPAD " : "",
- vendor_id,
- product_id);
+ std::string id =
+ name_string + base::StringPrintf(" (%sVendor: %s Product: %s)",
+ mapper ? "STANDARD GAMEPAD " : "",
+ vendor_id,
+ product_id);
base::TruncateUTF8ToByteSize(id, WebGamepad::idLengthCap - 1, &id);
base::string16 tmp16 = base::UTF8ToUTF16(id);
memset(pad.id, 0, sizeof(pad.id));
@@ -193,8 +190,8 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
if (mapper) {
std::string mapping = "standard";
- base::TruncateUTF8ToByteSize(mapping, WebGamepad::mappingLengthCap - 1,
- &mapping);
+ base::TruncateUTF8ToByteSize(
+ mapping, WebGamepad::mappingLengthCap - 1, &mapping);
tmp16 = base::UTF8ToUTF16(mapping);
memset(pad.mapping, 0, sizeof(pad.mapping));
tmp16.copy(pad.mapping, arraysize(pad.mapping) - 1);
@@ -207,31 +204,30 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) {
}
void GamepadPlatformDataFetcherLinux::EnumerateDevices() {
- udev_enumerate* enumerate = udev_enumerate_new(udev_->udev_handle());
+ device::ScopedUdevEnumeratePtr enumerate(
+ udev_enumerate_new(udev_->udev_handle()));
if (!enumerate)
return;
- int ret = udev_enumerate_add_match_subsystem(enumerate, kInputSubsystem);
+ int ret =
+ udev_enumerate_add_match_subsystem(enumerate.get(), kInputSubsystem);
if (ret != 0)
return;
- ret = udev_enumerate_scan_devices(enumerate);
+ ret = udev_enumerate_scan_devices(enumerate.get());
if (ret != 0)
return;
- udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
- for (udev_list_entry* dev_list_entry = devices;
- dev_list_entry != NULL;
+ udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate.get());
+ for (udev_list_entry* dev_list_entry = devices; dev_list_entry != NULL;
dev_list_entry = udev_list_entry_get_next(dev_list_entry)) {
// Get the filename of the /sys entry for the device and create a
// udev_device object (dev) representing it
const char* path = udev_list_entry_get_name(dev_list_entry);
- udev_device* dev = udev_device_new_from_syspath(udev_->udev_handle(), path);
+ device::ScopedUdevDevicePtr dev(
+ udev_device_new_from_syspath(udev_->udev_handle(), path));
if (!dev)
continue;
- RefreshDevice(dev);
- udev_device_unref(dev);
+ RefreshDevice(dev.get());
}
- // Free the enumerator object
- udev_enumerate_unref(enumerate);
}
void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) {
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
index f95e52fc0b2..dab9497fef0 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
@@ -25,11 +25,11 @@ class UdevLinux;
class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher {
public:
GamepadPlatformDataFetcherLinux();
- virtual ~GamepadPlatformDataFetcherLinux();
+ ~GamepadPlatformDataFetcherLinux() override;
// GamepadDataFetcher implementation.
- virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) OVERRIDE;
+ void GetGamepadData(blink::WebGamepads* pads,
+ bool devices_changed_hint) override;
private:
void RefreshDevice(udev_device* dev);
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
index 54e65392864..77c024e9369 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h
@@ -31,10 +31,10 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
public XboxDataFetcher::Delegate {
public:
GamepadPlatformDataFetcherMac();
- virtual ~GamepadPlatformDataFetcherMac();
- virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) OVERRIDE;
- virtual void PauseHint(bool paused) OVERRIDE;
+ ~GamepadPlatformDataFetcherMac() override;
+ void GetGamepadData(blink::WebGamepads* pads,
+ bool devices_changed_hint) override;
+ void PauseHint(bool paused) override;
private:
bool enabled_;
@@ -63,10 +63,10 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher,
void DeviceRemove(IOHIDDeviceRef device);
void ValueChanged(IOHIDValueRef value);
- virtual void XboxDeviceAdd(XboxController* device) OVERRIDE;
- virtual void XboxDeviceRemove(XboxController* device) OVERRIDE;
- virtual void XboxValueChanged(XboxController* device,
- const XboxController::Data& data) OVERRIDE;
+ void XboxDeviceAdd(XboxController* device) override;
+ void XboxDeviceRemove(XboxController* device) override;
+ void XboxValueChanged(XboxController* device,
+ const XboxController::Data& data) override;
void RegisterForNotifications();
void UnregisterFromNotifications();
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
index 28082a9d529..d5cf220702c 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
@@ -34,8 +34,8 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
GamepadPlatformDataFetcherWin();
virtual ~GamepadPlatformDataFetcherWin();
virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) OVERRIDE;
- virtual void PauseHint(bool paused) OVERRIDE;
+ bool devices_changed_hint) override;
+ virtual void PauseHint(bool paused) override;
private:
// XInput-specific implementation for GetGamepadData.
diff --git a/chromium/content/browser/gamepad/gamepad_provider.cc b/chromium/content/browser/gamepad/gamepad_provider.cc
index 16976d96538..caa4cc82c66 100644
--- a/chromium/content/browser/gamepad/gamepad_provider.cc
+++ b/chromium/content/browser/gamepad/gamepad_provider.cc
@@ -175,8 +175,7 @@ bool GamepadProvider::PadState::Match(const WebGamepad& pad) const {
}
void GamepadProvider::PadState::SetPad(const WebGamepad& pad) {
- DCHECK(pad.connected);
- connected_ = true;
+ connected_ = pad.connected;
axes_length_ = pad.axesLength;
buttons_length_ = pad.buttonsLength;
memcpy(id_, pad.id, arraysize(id_));
@@ -230,8 +229,6 @@ void GamepadProvider::DoPoll() {
hwbuf->sequence.WriteEnd();
}
- CheckForUserGesture();
-
if (ever_had_user_gesture_) {
for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
WebGamepad& pad = hwbuf->buffer.items[i];
@@ -249,6 +246,8 @@ void GamepadProvider::DoPoll() {
}
}
+ CheckForUserGesture();
+
// Schedule our next interval of polling.
ScheduleDoPoll();
}
@@ -308,7 +307,9 @@ void GamepadProvider::CheckForUserGesture() {
if (user_gesture_observers_.empty() && ever_had_user_gesture_)
return;
- if (GamepadsHaveUserGesture(SharedMemoryAsHardwareBuffer()->buffer)) {
+ bool had_gesture_before = ever_had_user_gesture_;
+ const WebGamepads& pads = SharedMemoryAsHardwareBuffer()->buffer;
+ if (GamepadsHaveUserGesture(pads)) {
ever_had_user_gesture_ = true;
for (size_t i = 0; i < user_gesture_observers_.size(); i++) {
user_gesture_observers_[i].message_loop->PostTask(FROM_HERE,
@@ -316,6 +317,12 @@ void GamepadProvider::CheckForUserGesture() {
}
user_gesture_observers_.clear();
}
+ if (!had_gesture_before && ever_had_user_gesture_) {
+ // Initialize pad_states_ for the first time.
+ for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
+ pad_states_.get()[i].SetPad(pads.items[i]);
+ }
+ }
}
} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_provider.h b/chromium/content/browser/gamepad/gamepad_provider.h
index 86a4b17baf3..a81061a21f5 100644
--- a/chromium/content/browser/gamepad/gamepad_provider.h
+++ b/chromium/content/browser/gamepad/gamepad_provider.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT GamepadProvider :
// Manually specifies the data fetcher. Used for testing.
explicit GamepadProvider(scoped_ptr<GamepadDataFetcher> fetcher);
- virtual ~GamepadProvider();
+ ~GamepadProvider() override;
// Returns the shared memory handle of the gamepad data duplicated into the
// given process.
@@ -56,7 +56,7 @@ class CONTENT_EXPORT GamepadProvider :
void RegisterForUserGesture(const base::Closure& closure);
// base::SystemMonitor::DevicesChangedObserver implementation.
- virtual void OnDevicesChanged(base::SystemMonitor::DeviceType type) OVERRIDE;
+ void OnDevicesChanged(base::SystemMonitor::DeviceType type) override;
private:
void Initialize(scoped_ptr<GamepadDataFetcher> fetcher);
diff --git a/chromium/content/browser/gamepad/gamepad_provider_unittest.cc b/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
index adfef0c5bf3..e4f6571da27 100644
--- a/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
+++ b/chromium/content/browser/gamepad/gamepad_provider_unittest.cc
@@ -131,26 +131,16 @@ TEST_F(GamepadProviderTest, UserGesture) {
GamepadProvider* provider = CreateProvider(no_button_data);
provider->Resume();
- // Register for a user gesture and make sure the provider reads it twice
- // see below for why).
provider->RegisterForUserGesture(listener.GetClosure());
- mock_data_fetcher_->WaitForDataRead();
- mock_data_fetcher_->WaitForDataRead();
+ mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
// It should not have issued our callback.
message_loop().RunUntilIdle();
EXPECT_FALSE(listener.has_user_gesture());
// Set a button down and wait for it to be read twice.
- //
- // We wait for two reads before calling RunAllPending because the provider
- // will read the data on the background thread (setting the event) and *then*
- // will issue the callback on our thread. Waiting for it to read twice
- // ensures that it was able to issue callbacks for the first read (if it
- // issued one) before we try to check for it.
mock_data_fetcher_->SetTestData(button_down_data);
- mock_data_fetcher_->WaitForDataRead();
- mock_data_fetcher_->WaitForDataRead();
+ mock_data_fetcher_->WaitForDataReadAndCallbacksIssued();
// It should have issued our callback.
message_loop().RunUntilIdle();
diff --git a/chromium/content/browser/gamepad/gamepad_service.cc b/chromium/content/browser/gamepad/gamepad_service.cc
index a2a83b316fa..67930f6118d 100644
--- a/chromium/content/browser/gamepad/gamepad_service.cc
+++ b/chromium/content/browser/gamepad/gamepad_service.cc
@@ -15,24 +15,40 @@
namespace content {
+namespace {
+GamepadService* g_gamepad_service = 0;
+}
+
GamepadService::GamepadService()
: num_active_consumers_(0),
gesture_callback_pending_(false) {
+ SetInstance(this);
}
GamepadService::GamepadService(scoped_ptr<GamepadDataFetcher> fetcher)
: provider_(new GamepadProvider(fetcher.Pass())),
num_active_consumers_(0),
gesture_callback_pending_(false) {
+ SetInstance(this);
thread_checker_.DetachFromThread();
}
GamepadService::~GamepadService() {
+ SetInstance(NULL);
+}
+
+void GamepadService::SetInstance(GamepadService* instance) {
+ // Unit tests can create multiple instances but only one should exist at any
+ // given time so g_gamepad_service should only go from NULL to non-NULL and
+ // vica versa.
+ CHECK(!!instance != !!g_gamepad_service);
+ g_gamepad_service = instance;
}
GamepadService* GamepadService::GetInstance() {
- return Singleton<GamepadService,
- LeakySingletonTraits<GamepadService> >::get();
+ if (!g_gamepad_service)
+ g_gamepad_service = new GamepadService;
+ return g_gamepad_service;
}
void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
@@ -46,6 +62,7 @@ void GamepadService::ConsumerBecameActive(GamepadConsumer* consumer) {
insert_result.first->is_active = true;
if (!insert_result.first->did_observe_user_gesture &&
!gesture_callback_pending_) {
+ gesture_callback_pending_ = true;
provider_->RegisterForUserGesture(
base::Bind(&GamepadService::OnUserGesture,
base::Unretained(this)));
diff --git a/chromium/content/browser/gamepad/gamepad_service.h b/chromium/content/browser/gamepad/gamepad_service.h
index 60081884228..726558936af 100644
--- a/chromium/content/browser/gamepad/gamepad_service.h
+++ b/chromium/content/browser/gamepad/gamepad_service.h
@@ -82,6 +82,7 @@ class CONTENT_EXPORT GamepadService {
private:
friend struct DefaultSingletonTraits<GamepadService>;
friend class GamepadServiceTestConstructor;
+ friend class GamepadServiceTest;
GamepadService();
@@ -91,6 +92,8 @@ class CONTENT_EXPORT GamepadService {
virtual ~GamepadService();
+ static void SetInstance(GamepadService*);
+
void OnUserGesture();
struct ConsumerInfo {
diff --git a/chromium/content/browser/gamepad/gamepad_service_unittest.cc b/chromium/content/browser/gamepad/gamepad_service_unittest.cc
new file mode 100644
index 00000000000..acfa6a37acc
--- /dev/null
+++ b/chromium/content/browser/gamepad/gamepad_service_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2014 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/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "content/browser/gamepad/gamepad_consumer.h"
+#include "content/browser/gamepad/gamepad_service.h"
+#include "content/browser/gamepad/gamepad_test_helpers.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+static const int kNumberOfGamepads = blink::WebGamepads::itemsLengthCap;
+}
+
+using blink::WebGamepads;
+
+class ConnectionListener : public GamepadConsumer {
+ public:
+ ConnectionListener() {
+ ClearCounters();
+ }
+
+ void OnGamepadConnected(unsigned index,
+ const blink::WebGamepad& gamepad) override {
+ connected_counter_++;
+ }
+ void OnGamepadDisconnected(unsigned index,
+ const blink::WebGamepad& gamepad) override {
+ disconnected_counter_++;
+ }
+
+ void ClearCounters() {
+ connected_counter_ = 0;
+ disconnected_counter_ = 0;
+ }
+
+ int connected_counter() const { return connected_counter_; }
+ int disconnected_counter() const { return disconnected_counter_; }
+
+ private:
+ int connected_counter_;
+ int disconnected_counter_;
+};
+
+class GamepadServiceTest : public testing::Test {
+ protected:
+ GamepadServiceTest();
+ ~GamepadServiceTest() override;
+
+ void SetPadsConnected(bool connected);
+ void WaitForData();
+
+ int GetConnectedCounter() const {
+ return connection_listener_->connected_counter();
+ }
+ int GetDisconnectedCounter() const {
+ return connection_listener_->disconnected_counter();
+ }
+
+ void SetUp() override;
+
+ private:
+ MockGamepadDataFetcher* fetcher_;
+ GamepadService* service_;
+ scoped_ptr<ConnectionListener> connection_listener_;
+ TestBrowserThreadBundle browser_thread_;
+ WebGamepads test_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(GamepadServiceTest);
+};
+
+GamepadServiceTest::GamepadServiceTest()
+ : browser_thread_(TestBrowserThreadBundle::IO_MAINLOOP) {
+ memset(&test_data_, 0, sizeof(test_data_));
+
+ // Set it so that we have user gesture.
+ test_data_.items[0].buttonsLength = 1;
+ test_data_.items[0].buttons[0].value = 1.f;
+ test_data_.items[0].buttons[0].pressed = true;
+}
+
+GamepadServiceTest::~GamepadServiceTest() {
+ delete service_;
+}
+
+void GamepadServiceTest::SetUp() {
+ fetcher_ = new MockGamepadDataFetcher(test_data_);
+ service_ = new GamepadService(scoped_ptr<GamepadDataFetcher>(fetcher_));
+ connection_listener_.reset((new ConnectionListener));
+ service_->ConsumerBecameActive(connection_listener_.get());
+}
+
+void GamepadServiceTest::SetPadsConnected(bool connected) {
+ for (int i = 0; i < kNumberOfGamepads; ++i) {
+ test_data_.items[i].connected = connected;
+ }
+ fetcher_->SetTestData(test_data_);
+}
+
+void GamepadServiceTest::WaitForData() {
+ connection_listener_->ClearCounters();
+ fetcher_->WaitForDataReadAndCallbacksIssued();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(GamepadServiceTest, ConnectionsTest) {
+ WaitForData();
+ EXPECT_EQ(0, GetConnectedCounter());
+ EXPECT_EQ(0, GetDisconnectedCounter());
+
+ SetPadsConnected(true);
+ WaitForData();
+ EXPECT_EQ(kNumberOfGamepads, GetConnectedCounter());
+ EXPECT_EQ(0, GetDisconnectedCounter());
+
+ SetPadsConnected(false);
+ WaitForData();
+ EXPECT_EQ(0, GetConnectedCounter());
+ EXPECT_EQ(kNumberOfGamepads, GetDisconnectedCounter());
+
+ WaitForData();
+ EXPECT_EQ(0, GetConnectedCounter());
+ EXPECT_EQ(0, GetDisconnectedCounter());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings.cc
index 60ae0725fb8..687d4ce154d 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings.cc
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings.cc
@@ -30,6 +30,10 @@ blink::WebGamepadButton ButtonFromButtonAndAxis(
return blink::WebGamepadButton(button.pressed, value);
}
+blink::WebGamepadButton NullButton() {
+ return blink::WebGamepadButton(false, 0.0);
+}
+
void DpadFromAxis(blink::WebGamepad* mapped, float dir) {
bool up = false;
bool right = false;
@@ -47,14 +51,14 @@ void DpadFromAxis(blink::WebGamepad* mapped, float dir) {
left = dir >= .4f && dir <= 1.f;
}
- mapped->buttons[kButtonDpadUp].pressed = up;
- mapped->buttons[kButtonDpadUp].value = up ? 1.f : 0.f;
- mapped->buttons[kButtonDpadRight].pressed = right;
- mapped->buttons[kButtonDpadRight].value = right ? 1.f : 0.f;
- mapped->buttons[kButtonDpadDown].pressed = down;
- mapped->buttons[kButtonDpadDown].value = down ? 1.f : 0.f;
- mapped->buttons[kButtonDpadLeft].pressed = left;
- mapped->buttons[kButtonDpadLeft].value = left ? 1.f : 0.f;
+ mapped->buttons[BUTTON_INDEX_DPAD_UP].pressed = up;
+ mapped->buttons[BUTTON_INDEX_DPAD_UP].value = up ? 1.f : 0.f;
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT].pressed = right;
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT].value = right ? 1.f : 0.f;
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN].pressed = down;
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN].value = down ? 1.f : 0.f;
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT].pressed = left;
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT].value = left ? 1.f : 0.f;
}
} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings.h b/chromium/content/browser/gamepad/gamepad_standard_mappings.h
index e436f0c7497..d4908eff442 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings.h
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings.h
@@ -24,33 +24,39 @@ GamepadStandardMappingFunction GetGamepadStandardMappingFunction(
// general, err towards leaving it *unmapped* so that content can handle
// appropriately.
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
+// GENERATED_JAVA_PREFIX_TO_STRIP: BUTTON_INDEX_
enum CanonicalButtonIndex {
- kButtonPrimary,
- kButtonSecondary,
- kButtonTertiary,
- kButtonQuaternary,
- kButtonLeftShoulder,
- kButtonRightShoulder,
- kButtonLeftTrigger,
- kButtonRightTrigger,
- kButtonBackSelect,
- kButtonStart,
- kButtonLeftThumbstick,
- kButtonRightThumbstick,
- kButtonDpadUp,
- kButtonDpadDown,
- kButtonDpadLeft,
- kButtonDpadRight,
- kButtonMeta,
- kNumButtons
+ BUTTON_INDEX_PRIMARY,
+ BUTTON_INDEX_SECONDARY,
+ BUTTON_INDEX_TERTIARY,
+ BUTTON_INDEX_QUATERNARY,
+ BUTTON_INDEX_LEFT_SHOULDER,
+ BUTTON_INDEX_RIGHT_SHOULDER,
+ BUTTON_INDEX_LEFT_TRIGGER,
+ BUTTON_INDEX_RIGHT_TRIGGER,
+ BUTTON_INDEX_BACK_SELECT,
+ BUTTON_INDEX_START,
+ BUTTON_INDEX_LEFT_THUMBSTICK,
+ BUTTON_INDEX_RIGHT_THUMBSTICK,
+ BUTTON_INDEX_DPAD_UP,
+ BUTTON_INDEX_DPAD_DOWN,
+ BUTTON_INDEX_DPAD_LEFT,
+ BUTTON_INDEX_DPAD_RIGHT,
+ BUTTON_INDEX_META,
+ BUTTON_INDEX_COUNT
};
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
+// GENERATED_JAVA_PREFIX_TO_STRIP: AXIS_INDEX_
enum CanonicalAxisIndex {
- kAxisLeftStickX,
- kAxisLeftStickY,
- kAxisRightStickX,
- kAxisRightStickY,
- kNumAxes
+ AXIS_INDEX_LEFT_STICK_X,
+ AXIS_INDEX_LEFT_STICK_Y,
+ AXIS_INDEX_RIGHT_STICK_X,
+ AXIS_INDEX_RIGHT_STICK_Y,
+ AXIS_INDEX_COUNT
};
// Matches XInput's trigger deadzone
@@ -62,6 +68,7 @@ blink::WebGamepadButton AxisNegativeAsButton(float input);
blink::WebGamepadButton AxisPositiveAsButton(float input);
blink::WebGamepadButton ButtonFromButtonAndAxis(
blink::WebGamepadButton button, float axis);
+blink::WebGamepadButton NullButton();
void DpadFromAxis(blink::WebGamepad* mapped, float dir);
} // namespace content
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
index 86c3afde8a1..a0852420c6a 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings_linux.cc
@@ -8,188 +8,206 @@ namespace content {
namespace {
-void MapperXInputStyleGamepad(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperXInputStyleGamepad(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
- mapped->buttons[kButtonBackSelect] = input.buttons[6];
- mapped->buttons[kButtonStart] = input.buttons[7];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[9];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[10];
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[kButtonMeta] = input.buttons[8];
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[4];
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[8];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperLakeviewResearch(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperLakeviewResearch(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[0];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
- mapped->buttons[kButtonRightShoulder] = input.buttons[7];
- mapped->buttons[kButtonLeftTrigger] = input.buttons[4];
- mapped->buttons[kButtonRightTrigger] = input.buttons[5];
- mapped->buttons[kButtonBackSelect] = input.buttons[9];
- mapped->buttons[kButtonStart] = input.buttons[8];
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[5]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[4]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[4]);
- mapped->buttonsLength = kNumButtons - 1; // no Meta on this device
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[4]);
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; // no Meta on this device
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperPlaystationSixAxis(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperPlaystationSixAxis(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[14];
- mapped->buttons[kButtonSecondary] = input.buttons[13];
- mapped->buttons[kButtonTertiary] = input.buttons[15];
- mapped->buttons[kButtonQuaternary] = input.buttons[12];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[10];
- mapped->buttons[kButtonRightShoulder] = input.buttons[11];
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[12]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[13]);
- mapped->buttons[kButtonBackSelect] = input.buttons[0];
- mapped->buttons[kButtonStart] = input.buttons[3];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[1];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[2];
- mapped->buttons[kButtonDpadUp] = AxisToButton(input.axes[8]);
- mapped->buttons[kButtonDpadDown] = AxisToButton(input.axes[10]);
- mapped->buttons[kButtonDpadLeft] = input.buttons[7];
- mapped->buttons[kButtonDpadRight] = AxisToButton(input.axes[9]);
- mapped->buttons[kButtonMeta] = input.buttons[16];
-
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[15];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[12];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[12]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[13]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisToButton(input.axes[8]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisToButton(input.axes[10]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = AxisToButton(input.axes[9]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[16];
+
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperDualshock4(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperDualshock4(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
enum Dualshock4Buttons {
- kTouchpadButton = kNumButtons,
- kNumDualshock4Buttons
+ DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
+ DUALSHOCK_BUTTON_COUNT
};
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[1];
- mapped->buttons[kButtonSecondary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[0];
- mapped->buttons[kButtonQuaternary] = input.buttons[3];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[4];
- mapped->buttons[kButtonRightShoulder] = input.buttons[5];
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[3]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[4]);
- mapped->buttons[kButtonBackSelect] = input.buttons[8];
- mapped->buttons[kButtonStart] = input.buttons[9];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[10];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[11];
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[kButtonMeta] = input.buttons[12];
- mapped->buttons[kTouchpadButton] = input.buttons[13];
- mapped->axes[kAxisRightStickY] = input.axes[5];
-
- mapped->buttonsLength = kNumDualshock4Buttons;
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons[DUALSHOCK_BUTTON_TOUCHPAD] = input.buttons[13];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+
+ mapped->buttonsLength = DUALSHOCK_BUTTON_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperXGEAR(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[2];
- mapped->buttons[kButtonSecondary] = input.buttons[1];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[0];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
- mapped->buttons[kButtonRightShoulder] = input.buttons[7];
- mapped->buttons[kButtonLeftTrigger] = input.buttons[4];
- mapped->buttons[kButtonRightTrigger] = input.buttons[5];
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[5]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[4]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[4]);
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[2];
- mapped->buttonsLength = kNumButtons - 1; // no Meta on this device
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[4]);
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[2];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; // no Meta on this device
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-
-void MapperDragonRiseGeneric(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperDragonRiseGeneric(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[5]);
- mapped->axes[kAxisLeftStickX] = input.axes[0];
- mapped->axes[kAxisLeftStickY] = input.axes[1];
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[4];
- mapped->buttonsLength = kNumButtons - 1; // no Meta on this device
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[5]);
+ mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; // no Meta on this device
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperOnLiveWireless(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperOnLiveWireless(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
- mapped->buttons[kButtonBackSelect] = input.buttons[6];
- mapped->buttons[kButtonStart] = input.buttons[7];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[9];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[10];
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[7]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[7]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[6]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[6]);
- mapped->buttons[kButtonMeta] = input.buttons[8];
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[4];
-
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[8];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
+void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
+ mapped->buttons[BUTTON_INDEX_START] = NullButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[7]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[6]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[6];
+
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
+}
struct MappingData {
const char* const vendor_id;
const char* const product_id;
GamepadStandardMappingFunction function;
} AvailableMappings[] = {
- // http://www.linux-usb.org/usb.ids
- { "0079", "0006", MapperDragonRiseGeneric }, // DragonRise Generic USB
- { "045e", "028e", MapperXInputStyleGamepad }, // Xbox 360 Controller
- { "045e", "028f", MapperXInputStyleGamepad }, // Xbox 360 Wireless Controller
- { "046d", "c21d", MapperXInputStyleGamepad }, // Logitech F310
- { "046d", "c21e", MapperXInputStyleGamepad }, // Logitech F510
- { "046d", "c21f", MapperXInputStyleGamepad }, // Logitech F710
- { "054c", "0268", MapperPlaystationSixAxis }, // Playstation SIXAXIS
- { "054c", "05c4", MapperDualshock4 }, // Playstation Dualshock 4
- { "0925", "0005", MapperLakeviewResearch }, // SmartJoy PLUS Adapter
- { "0925", "8866", MapperLakeviewResearch }, // WiseGroup MP-8866
- { "0e8f", "0003", MapperXGEAR }, // XFXforce XGEAR PS2 Controller
- { "2378", "1008", MapperOnLiveWireless }, // OnLive Controller (Bluetooth)
- { "2378", "100a", MapperOnLiveWireless }, // OnLive Controller (Wired)
+ // http://www.linux-usb.org/usb.ids
+ {"0079", "0006", MapperDragonRiseGeneric}, // DragonRise Generic USB
+ {"045e", "028e", MapperXInputStyleGamepad}, // Xbox 360 Controller
+ {"045e",
+ "028f",
+ MapperXInputStyleGamepad}, // Xbox 360 Wireless Controller
+ {"046d", "c21d", MapperXInputStyleGamepad}, // Logitech F310
+ {"046d", "c21e", MapperXInputStyleGamepad}, // Logitech F510
+ {"046d", "c21f", MapperXInputStyleGamepad}, // Logitech F710
+ {"054c", "0268", MapperPlaystationSixAxis}, // Playstation SIXAXIS
+ {"054c", "05c4", MapperDualshock4}, // Playstation Dualshock 4
+ {"0925", "0005", MapperLakeviewResearch}, // SmartJoy PLUS Adapter
+ {"0925", "8866", MapperLakeviewResearch}, // WiseGroup MP-8866
+ {"0e8f", "0003", MapperXGEAR}, // XFXforce XGEAR PS2 Controller
+ {"2378", "1008", MapperOnLiveWireless}, // OnLive Controller (Bluetooth)
+ {"2378", "100a", MapperOnLiveWireless}, // OnLive Controller (Wired)
+ {"18d1", "2c40", MapperADT1}, // ADT-1 Controller
};
} // namespace
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm b/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
index 5481f0e9921..ebb08eda640 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings_mac.mm
@@ -8,221 +8,233 @@ namespace content {
namespace {
-void MapperXbox360Gamepad(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperXbox360Gamepad(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
- mapped->buttons[kButtonBackSelect] = input.buttons[9];
- mapped->buttons[kButtonStart] = input.buttons[8];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[6];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[7];
- mapped->buttons[kButtonDpadUp] = input.buttons[11];
- mapped->buttons[kButtonDpadDown] = input.buttons[12];
- mapped->buttons[kButtonDpadLeft] = input.buttons[13];
- mapped->buttons[kButtonDpadRight] = input.buttons[14];
- mapped->buttons[kButtonMeta] = input.buttons[10];
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[4];
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[12];
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[10];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperPlaystationSixAxis(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperPlaystationSixAxis(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[14];
- mapped->buttons[kButtonSecondary] = input.buttons[13];
- mapped->buttons[kButtonTertiary] = input.buttons[15];
- mapped->buttons[kButtonQuaternary] = input.buttons[12];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[10];
- mapped->buttons[kButtonRightShoulder] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[15];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[12];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[11];
- mapped->buttons[kButtonLeftTrigger] = ButtonFromButtonAndAxis(
- input.buttons[8], input.axes[14]);
- mapped->buttons[kButtonRightTrigger] = ButtonFromButtonAndAxis(
- input.buttons[9], input.axes[15]);
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] =
+ ButtonFromButtonAndAxis(input.buttons[8], input.axes[14]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] =
+ ButtonFromButtonAndAxis(input.buttons[9], input.axes[15]);
- mapped->buttons[kButtonBackSelect] = input.buttons[0];
- mapped->buttons[kButtonStart] = input.buttons[3];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[1];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[2];
// The SixAxis Dpad is pressure sensative
- mapped->buttons[kButtonDpadUp] = ButtonFromButtonAndAxis(
- input.buttons[4], input.axes[10]);
- mapped->buttons[kButtonDpadDown] = ButtonFromButtonAndAxis(
- input.buttons[6], input.axes[12]);
- mapped->buttons[kButtonDpadLeft] = ButtonFromButtonAndAxis(
- input.buttons[7], input.axes[13]);
- mapped->buttons[kButtonDpadRight] = ButtonFromButtonAndAxis(
- input.buttons[5], input.axes[11]);
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] =
+ ButtonFromButtonAndAxis(input.buttons[4], input.axes[10]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] =
+ ButtonFromButtonAndAxis(input.buttons[6], input.axes[12]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] =
+ ButtonFromButtonAndAxis(input.buttons[7], input.axes[13]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ ButtonFromButtonAndAxis(input.buttons[5], input.axes[11]);
- mapped->buttons[kButtonMeta] = input.buttons[16];
- mapped->axes[kAxisRightStickY] = input.axes[5];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[16];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperDualshock4(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperDualshock4(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
enum Dualshock4Buttons {
- kTouchpadButton = kNumButtons,
- kNumDualshock4Buttons
+ DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
+ DUALSHOCK_BUTTON_COUNT
};
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[1];
- mapped->buttons[kButtonSecondary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[0];
- mapped->buttons[kButtonQuaternary] = input.buttons[3];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[4];
- mapped->buttons[kButtonRightShoulder] = input.buttons[5];
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[3]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[4]);
- mapped->buttons[kButtonBackSelect] = input.buttons[8];
- mapped->buttons[kButtonStart] = input.buttons[9];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[10];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[11];
- mapped->buttons[kButtonMeta] = input.buttons[12];
- mapped->buttons[kTouchpadButton] = input.buttons[13];
- mapped->axes[kAxisRightStickY] = input.axes[5];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons[DUALSHOCK_BUTTON_TOUCHPAD] = input.buttons[13];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = kNumDualshock4Buttons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = DUALSHOCK_BUTTON_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperDirectInputStyle(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperDirectInputStyle(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[1];
- mapped->buttons[kButtonSecondary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[0];
- mapped->axes[kAxisRightStickY] = input.axes[5];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = kNumButtons - 1; /* no meta */
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperMacallyIShock(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperMacallyIShock(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
enum IShockButtons {
- kButtonC = kNumButtons,
- kButtonD,
- kButtonE,
- kNumIShockButtons
+ ISHOCK_BUTTON_C = BUTTON_INDEX_COUNT,
+ ISHOCK_BUTTON_D,
+ ISHOCK_BUTTON_E,
+ ISHOCK_BUTTON_COUNT,
};
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[6];
- mapped->buttons[kButtonSecondary] = input.buttons[5];
- mapped->buttons[kButtonTertiary] = input.buttons[7];
- mapped->buttons[kButtonQuaternary] = input.buttons[4];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[14];
- mapped->buttons[kButtonRightShoulder] = input.buttons[12];
- mapped->buttons[kButtonLeftTrigger] = input.buttons[15];
- mapped->buttons[kButtonRightTrigger] = input.buttons[13];
- mapped->buttons[kButtonBackSelect] = input.buttons[9];
- mapped->buttons[kButtonStart] = input.buttons[10];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[16];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[17];
- mapped->buttons[kButtonDpadUp] = input.buttons[0];
- mapped->buttons[kButtonDpadDown] = input.buttons[1];
- mapped->buttons[kButtonDpadLeft] = input.buttons[2];
- mapped->buttons[kButtonDpadRight] = input.buttons[3];
- mapped->buttons[kButtonMeta] = input.buttons[11];
- mapped->buttons[kButtonC] = input.buttons[8];
- mapped->buttons[kButtonD] = input.buttons[18];
- mapped->buttons[kButtonE] = input.buttons[19];
- mapped->axes[kAxisLeftStickX] = input.axes[0];
- mapped->axes[kAxisLeftStickY] = input.axes[1];
- mapped->axes[kAxisRightStickX] = -input.axes[5];
- mapped->axes[kAxisRightStickY] = input.axes[6];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[12];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[15];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[16];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[17];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[11];
+ mapped->buttons[ISHOCK_BUTTON_C] = input.buttons[8];
+ mapped->buttons[ISHOCK_BUTTON_D] = input.buttons[18];
+ mapped->buttons[ISHOCK_BUTTON_E] = input.buttons[19];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = -input.axes[5];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[6];
- mapped->buttonsLength = kNumIShockButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = ISHOCK_BUTTON_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperXGEAR(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperXGEAR(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[0];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
- mapped->buttons[kButtonRightShoulder] = input.buttons[7];
- mapped->buttons[kButtonLeftTrigger] = input.buttons[4];
- mapped->buttons[kButtonRightTrigger] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
DpadFromAxis(mapped, input.axes[9]);
- mapped->axes[kAxisRightStickX] = input.axes[5];
- mapped->axes[kAxisRightStickY] = input.axes[2];
- mapped->buttonsLength = kNumButtons - 1; /* no meta */
- mapped->axesLength = kNumAxes;
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[5];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[2];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperSmartJoyPLUS(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperSmartJoyPLUS(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[0];
- mapped->buttons[kButtonStart] = input.buttons[8];
- mapped->buttons[kButtonBackSelect] = input.buttons[9];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
- mapped->buttons[kButtonRightShoulder] = input.buttons[7];
- mapped->buttons[kButtonLeftTrigger] = input.buttons[4];
- mapped->buttons[kButtonRightTrigger] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[5];
DpadFromAxis(mapped, input.axes[9]);
- mapped->axes[kAxisRightStickY] = input.axes[5];
- mapped->buttonsLength = kNumButtons - 1; /* no meta */
- mapped->axesLength = kNumAxes;
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperDragonRiseGeneric(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperDragonRiseGeneric(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
DpadFromAxis(mapped, input.axes[9]);
- mapped->axes[kAxisLeftStickX] = input.axes[0];
- mapped->axes[kAxisLeftStickY] = input.axes[1];
- mapped->axes[kAxisRightStickX] = input.axes[2];
- mapped->axes[kAxisRightStickY] = input.axes[5];
- mapped->buttonsLength = kNumButtons - 1; /* no meta */
- mapped->axesLength = kNumAxes;
+ mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[2];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1; /* no meta */
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperOnLiveWireless(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperOnLiveWireless(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[0];
- mapped->buttons[kButtonSecondary] = input.buttons[1];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[4];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
- mapped->buttons[kButtonRightShoulder] = input.buttons[7];
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
- mapped->buttons[kButtonBackSelect] = input.buttons[10];
- mapped->buttons[kButtonStart] = input.buttons[11];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[13];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[14];
- mapped->buttons[kButtonMeta] = input.buttons[12];
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[4];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
+}
+
+void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
+ mapped->buttons[BUTTON_INDEX_START] = NullButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ DpadFromAxis(mapped, input.axes[9]);
+
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
struct MappingData {
@@ -230,21 +242,22 @@ struct MappingData {
const char* const product_id;
GamepadStandardMappingFunction function;
} AvailableMappings[] = {
- // http://www.linux-usb.org/usb.ids
- { "0079", "0006", MapperDragonRiseGeneric }, // DragonRise Generic USB
- { "045e", "028e", MapperXbox360Gamepad }, // Xbox 360 Controller
- { "045e", "028f", MapperXbox360Gamepad }, // Xbox 360 Wireless Controller
- { "046d", "c216", MapperDirectInputStyle }, // Logitech F310, D mode
- { "046d", "c218", MapperDirectInputStyle }, // Logitech F510, D mode
- { "046d", "c219", MapperDirectInputStyle }, // Logitech F710, D mode
- { "054c", "0268", MapperPlaystationSixAxis }, // Playstation SIXAXIS
- { "054c", "05c4", MapperDualshock4 }, // Playstation Dualshock 4
- { "0925", "0005", MapperSmartJoyPLUS }, // SmartJoy PLUS Adapter
- { "0e8f", "0003", MapperXGEAR }, // XFXforce XGEAR PS2 Controller
- { "2222", "0060", MapperDirectInputStyle }, // Macally iShockX, analog mode
- { "2222", "4010", MapperMacallyIShock }, // Macally iShock
- { "2378", "1008", MapperOnLiveWireless }, // OnLive Controller (Bluetooth)
- { "2378", "100a", MapperOnLiveWireless }, // OnLive Controller (Wired)
+ // http://www.linux-usb.org/usb.ids
+ {"0079", "0006", MapperDragonRiseGeneric}, // DragonRise Generic USB
+ {"045e", "028e", MapperXbox360Gamepad}, // Xbox 360 Controller
+ {"045e", "028f", MapperXbox360Gamepad}, // Xbox 360 Wireless Controller
+ {"046d", "c216", MapperDirectInputStyle}, // Logitech F310, D mode
+ {"046d", "c218", MapperDirectInputStyle}, // Logitech F510, D mode
+ {"046d", "c219", MapperDirectInputStyle}, // Logitech F710, D mode
+ {"054c", "0268", MapperPlaystationSixAxis}, // Playstation SIXAXIS
+ {"054c", "05c4", MapperDualshock4}, // Playstation Dualshock 4
+ {"0925", "0005", MapperSmartJoyPLUS}, // SmartJoy PLUS Adapter
+ {"0e8f", "0003", MapperXGEAR}, // XFXforce XGEAR PS2 Controller
+ {"2222", "0060", MapperDirectInputStyle}, // Macally iShockX, analog mode
+ {"2222", "4010", MapperMacallyIShock}, // Macally iShock
+ {"2378", "1008", MapperOnLiveWireless}, // OnLive Controller (Bluetooth)
+ {"2378", "100a", MapperOnLiveWireless}, // OnLive Controller (Wired)
+ {"18d1", "2c40", MapperADT1}, // ADT-1 Controller
};
} // namespace
diff --git a/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc b/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
index 39ce9fcefab..93c18517453 100644
--- a/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
+++ b/chromium/content/browser/gamepad/gamepad_standard_mappings_win.cc
@@ -8,97 +8,116 @@ namespace content {
namespace {
-void MapperLogitechDualAction(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperLogitechDualAction(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[1];
- mapped->buttons[kButtonSecondary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[0];
- mapped->axes[kAxisRightStickY] = input.axes[5];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void Mapper2Axes8Keys(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void Mapper2Axes8Keys(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[2];
- mapped->buttons[kButtonSecondary] = input.buttons[1];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[0];
- mapped->buttons[kButtonDpadUp] = AxisNegativeAsButton(input.axes[1]);
- mapped->buttons[kButtonDpadDown] = AxisPositiveAsButton(input.axes[1]);
- mapped->buttons[kButtonDpadLeft] = AxisNegativeAsButton(input.axes[0]);
- mapped->buttons[kButtonDpadRight] = AxisPositiveAsButton(input.axes[0]);
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[1]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[1]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[0]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[0]);
// Missing buttons
- mapped->buttons[kButtonLeftTrigger] = blink::WebGamepadButton();
- mapped->buttons[kButtonRightTrigger] = blink::WebGamepadButton();
- mapped->buttons[kButtonLeftThumbstick] = blink::WebGamepadButton();
- mapped->buttons[kButtonRightThumbstick] = blink::WebGamepadButton();
- mapped->buttons[kButtonMeta] = blink::WebGamepadButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = blink::WebGamepadButton();
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = blink::WebGamepadButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = blink::WebGamepadButton();
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = blink::WebGamepadButton();
+ mapped->buttons[BUTTON_INDEX_META] = blink::WebGamepadButton();
- mapped->buttonsLength = kNumButtons - 1;
+ mapped->buttonsLength = BUTTON_INDEX_COUNT - 1;
mapped->axesLength = 0;
}
-void MapperDualshock4(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperDualshock4(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
enum Dualshock4Buttons {
- kTouchpadButton = kNumButtons,
- kNumDualshock4Buttons
+ DUALSHOCK_BUTTON_TOUCHPAD = BUTTON_INDEX_COUNT,
+ DUALSHOCK_BUTTON_COUNT
};
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[1];
- mapped->buttons[kButtonSecondary] = input.buttons[2];
- mapped->buttons[kButtonTertiary] = input.buttons[0];
- mapped->buttons[kButtonQuaternary] = input.buttons[3];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[4];
- mapped->buttons[kButtonRightShoulder] = input.buttons[5];
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[3]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[4]);
- mapped->buttons[kButtonBackSelect] = input.buttons[8];
- mapped->buttons[kButtonStart] = input.buttons[9];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[10];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[11];
- mapped->buttons[kButtonMeta] = input.buttons[12];
- mapped->buttons[kTouchpadButton] = input.buttons[13];
- mapped->axes[kAxisRightStickY] = input.axes[5];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[3]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons[DUALSHOCK_BUTTON_TOUCHPAD] = input.buttons[13];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = kNumDualshock4Buttons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = DUALSHOCK_BUTTON_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
-void MapperOnLiveWireless(
- const blink::WebGamepad& input,
- blink::WebGamepad* mapped) {
+void MapperOnLiveWireless(const blink::WebGamepad& input,
+ blink::WebGamepad* mapped) {
*mapped = input;
- mapped->buttons[kButtonPrimary] = input.buttons[0];
- mapped->buttons[kButtonSecondary] = input.buttons[1];
- mapped->buttons[kButtonTertiary] = input.buttons[3];
- mapped->buttons[kButtonQuaternary] = input.buttons[4];
- mapped->buttons[kButtonLeftShoulder] = input.buttons[6];
- mapped->buttons[kButtonRightShoulder] = input.buttons[7];
- mapped->buttons[kButtonLeftTrigger] = AxisToButton(input.axes[2]);
- mapped->buttons[kButtonRightTrigger] = AxisToButton(input.axes[5]);
- mapped->buttons[kButtonBackSelect] = input.buttons[10];
- mapped->buttons[kButtonStart] = input.buttons[11];
- mapped->buttons[kButtonLeftThumbstick] = input.buttons[13];
- mapped->buttons[kButtonRightThumbstick] = input.buttons[14];
- mapped->buttons[kButtonMeta] = input.buttons[12];
- mapped->axes[kAxisRightStickX] = input.axes[3];
- mapped->axes[kAxisRightStickY] = input.axes[4];
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
DpadFromAxis(mapped, input.axes[9]);
- mapped->buttonsLength = kNumButtons;
- mapped->axesLength = kNumAxes;
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
+}
+
+void MapperADT1(const blink::WebGamepad& input, blink::WebGamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = AxisToButton(input.axes[3]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = NullButton();
+ mapped->buttons[BUTTON_INDEX_START] = NullButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[13];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[14];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ DpadFromAxis(mapped, input.axes[9]);
+
+ mapped->buttonsLength = BUTTON_INDEX_COUNT;
+ mapped->axesLength = AXIS_INDEX_COUNT;
}
struct MappingData {
@@ -106,12 +125,13 @@ struct MappingData {
const char* const product_id;
GamepadStandardMappingFunction function;
} AvailableMappings[] = {
- // http://www.linux-usb.org/usb.ids
- { "046d", "c216", MapperLogitechDualAction }, // Logitech DualAction
- { "0079", "0011", Mapper2Axes8Keys }, // 2Axes 8Keys Game Pad
- { "054c", "05c4", MapperDualshock4 }, // Playstation Dualshock 4
- { "2378", "1008", MapperOnLiveWireless }, // OnLive Controller (Bluetooth)
- { "2378", "100a", MapperOnLiveWireless }, // OnLive Controller (Wired)
+ // http://www.linux-usb.org/usb.ids
+ {"046d", "c216", MapperLogitechDualAction}, // Logitech DualAction
+ {"0079", "0011", Mapper2Axes8Keys}, // 2Axes 8Keys Game Pad
+ {"054c", "05c4", MapperDualshock4}, // Playstation Dualshock 4
+ {"2378", "1008", MapperOnLiveWireless}, // OnLive Controller (Bluetooth)
+ {"2378", "100a", MapperOnLiveWireless}, // OnLive Controller (Wired)
+ {"18d1", "2c40", MapperADT1}, // ADT-1 Controller
};
} // namespace
diff --git a/chromium/content/browser/gamepad/gamepad_test_helpers.cc b/chromium/content/browser/gamepad/gamepad_test_helpers.cc
index 8837c8e59c3..fc79dcb5ee6 100644
--- a/chromium/content/browser/gamepad/gamepad_test_helpers.cc
+++ b/chromium/content/browser/gamepad/gamepad_test_helpers.cc
@@ -30,6 +30,15 @@ void MockGamepadDataFetcher::WaitForDataRead() {
return read_data_.Wait();
}
+void MockGamepadDataFetcher::WaitForDataReadAndCallbacksIssued() {
+ // The provider will read the data on the background thread (setting the
+ // event) and *then* will issue the callback on the client thread. Waiting for
+ // it to read twice is a simple way to ensure that it was able to issue
+ // callbacks for the first read (if it issued one).
+ WaitForDataRead();
+ WaitForDataRead();
+}
+
void MockGamepadDataFetcher::SetTestData(const blink::WebGamepads& new_data) {
base::AutoLock lock(lock_);
test_data_ = new_data;
diff --git a/chromium/content/browser/gamepad/gamepad_test_helpers.h b/chromium/content/browser/gamepad/gamepad_test_helpers.h
index 2aad5753b27..dbaa9664912 100644
--- a/chromium/content/browser/gamepad/gamepad_test_helpers.h
+++ b/chromium/content/browser/gamepad/gamepad_test_helpers.h
@@ -23,16 +23,21 @@ class MockGamepadDataFetcher : public GamepadDataFetcher {
// returned when the provider queries us.
explicit MockGamepadDataFetcher(const blink::WebGamepads& test_data);
- virtual ~MockGamepadDataFetcher();
+ ~MockGamepadDataFetcher() override;
// GamepadDataFetcher.
- virtual void GetGamepadData(blink::WebGamepads* pads,
- bool devices_changed_hint) OVERRIDE;
+ void GetGamepadData(blink::WebGamepads* pads,
+ bool devices_changed_hint) override;
// Blocks the current thread until the GamepadProvider reads from this
// fetcher on the background thread.
void WaitForDataRead();
+ // Blocks the current thread until the GamepadProvider reads from this
+ // fetcher on the background thread and issued all callbacks related to the
+ // read on the client's thread.
+ void WaitForDataReadAndCallbacksIssued();
+
// Updates the test data.
void SetTestData(const blink::WebGamepads& new_data);
@@ -64,7 +69,7 @@ class GamepadTestHelper {
class GamepadServiceTestConstructor : public GamepadTestHelper {
public:
explicit GamepadServiceTestConstructor(const blink::WebGamepads& test_data);
- virtual ~GamepadServiceTestConstructor();
+ ~GamepadServiceTestConstructor() override;
GamepadService* gamepad_service() { return gamepad_service_; }
MockGamepadDataFetcher* data_fetcher() { return data_fetcher_; }
diff --git a/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h b/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h
index e5a6edd507b..16908c11646 100644
--- a/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h
+++ b/chromium/content/browser/gamepad/raw_input_data_fetcher_win.h
@@ -59,7 +59,7 @@ class RawInputDataFetcher
~RawInputDataFetcher();
// DestructionObserver overrides.
- virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
+ virtual void WillDestroyCurrentMessageLoop() override;
bool Available() { return rawinput_available_; }
void StartMonitor();
diff --git a/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h b/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h
index 99a68f209bd..d88ad968233 100644
--- a/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h
+++ b/chromium/content/browser/gamepad/xbox_data_fetcher_mac.h
@@ -163,9 +163,9 @@ class XboxDataFetcher : public XboxController::Delegate {
void AddController(XboxController* controller);
void RemoveController(XboxController* controller);
void RemoveControllerByLocationID(uint32 id);
- virtual void XboxControllerGotData(XboxController* controller,
- const XboxController::Data& data) OVERRIDE;
- virtual void XboxControllerError(XboxController* controller) OVERRIDE;
+ void XboxControllerGotData(XboxController* controller,
+ const XboxController::Data& data) override;
+ void XboxControllerError(XboxController* controller) override;
Delegate* delegate_;
diff --git a/chromium/content/browser/geofencing/OWNERS b/chromium/content/browser/geofencing/OWNERS
new file mode 100644
index 00000000000..1b10b3436d9
--- /dev/null
+++ b/chromium/content/browser/geofencing/OWNERS
@@ -0,0 +1 @@
+mek@chromium.org
diff --git a/chromium/content/browser/geofencing/geofencing_dispatcher_host.cc b/chromium/content/browser/geofencing/geofencing_dispatcher_host.cc
new file mode 100644
index 00000000000..5cae1136bc9
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_dispatcher_host.cc
@@ -0,0 +1,111 @@
+// Copyright 2014 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 "content/browser/geofencing/geofencing_dispatcher_host.h"
+
+#include "content/browser/geofencing/geofencing_manager.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/common/geofencing_messages.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+
+namespace content {
+
+static const int kMaxRegionIdLength = 200;
+
+GeofencingDispatcherHost::GeofencingDispatcherHost(
+ GeofencingManager* geofencing_manager)
+ : BrowserMessageFilter(GeofencingMsgStart),
+ manager_(geofencing_manager),
+ weak_factory_(this) {
+}
+
+GeofencingDispatcherHost::~GeofencingDispatcherHost() {
+}
+
+bool GeofencingDispatcherHost::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GeofencingDispatcherHost, message)
+ IPC_MESSAGE_HANDLER(GeofencingHostMsg_RegisterRegion, OnRegisterRegion)
+ IPC_MESSAGE_HANDLER(GeofencingHostMsg_UnregisterRegion, OnUnregisterRegion)
+ IPC_MESSAGE_HANDLER(GeofencingHostMsg_GetRegisteredRegions,
+ OnGetRegisteredRegions)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void GeofencingDispatcherHost::OnRegisterRegion(
+ int thread_id,
+ int request_id,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ int64 service_worker_registration_id) {
+ // Sanity check on region_id
+ if (region_id.length() > kMaxRegionIdLength) {
+ Send(new GeofencingMsg_RegisterRegionComplete(
+ thread_id, request_id, GeofencingStatus::GEOFENCING_STATUS_ERROR));
+ return;
+ }
+
+ manager_->RegisterRegion(
+ service_worker_registration_id,
+ region_id,
+ region,
+ base::Bind(&GeofencingDispatcherHost::RegisterRegionCompleted,
+ weak_factory_.GetWeakPtr(),
+ thread_id,
+ request_id));
+}
+
+void GeofencingDispatcherHost::OnUnregisterRegion(
+ int thread_id,
+ int request_id,
+ const std::string& region_id,
+ int64 service_worker_registration_id) {
+ // Sanity check on region_id
+ if (region_id.length() > kMaxRegionIdLength) {
+ Send(new GeofencingMsg_UnregisterRegionComplete(
+ thread_id, request_id, GeofencingStatus::GEOFENCING_STATUS_ERROR));
+ return;
+ }
+
+ manager_->UnregisterRegion(
+ service_worker_registration_id,
+ region_id,
+ base::Bind(&GeofencingDispatcherHost::UnregisterRegionCompleted,
+ weak_factory_.GetWeakPtr(),
+ thread_id,
+ request_id));
+}
+
+void GeofencingDispatcherHost::OnGetRegisteredRegions(
+ int thread_id,
+ int request_id,
+ int64 service_worker_registration_id) {
+ GeofencingRegistrations result;
+
+ GeofencingStatus status =
+ manager_->GetRegisteredRegions(service_worker_registration_id, &result);
+ Send(new GeofencingMsg_GetRegisteredRegionsComplete(
+ thread_id, request_id, status, result));
+}
+
+void GeofencingDispatcherHost::RegisterRegionCompleted(
+ int thread_id,
+ int request_id,
+ GeofencingStatus status) {
+ Send(new GeofencingMsg_RegisterRegionComplete(thread_id, request_id, status));
+}
+
+void GeofencingDispatcherHost::UnregisterRegionCompleted(
+ int thread_id,
+ int request_id,
+ GeofencingStatus status) {
+ Send(new GeofencingMsg_UnregisterRegionComplete(
+ thread_id, request_id, status));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geofencing/geofencing_dispatcher_host.h b/chromium/content/browser/geofencing/geofencing_dispatcher_host.h
new file mode 100644
index 00000000000..40ed3a8487b
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_dispatcher_host.h
@@ -0,0 +1,58 @@
+// Copyright 2014 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 CONTENT_BROWSER_GEOFENCING_GEOFENCING_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_GEOFENCING_GEOFENCING_DISPATCHER_HOST_H_
+
+#include "content/common/geofencing_status.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace blink {
+struct WebCircularGeofencingRegion;
+}
+
+namespace content {
+
+class GeofencingManager;
+class ServiceWorkerContextWrapper;
+
+class GeofencingDispatcherHost : public BrowserMessageFilter {
+ public:
+ explicit GeofencingDispatcherHost(GeofencingManager* geofencing_manager);
+
+ private:
+ ~GeofencingDispatcherHost() override;
+
+ // BrowserMessageFilter implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnRegisterRegion(int thread_id,
+ int request_id,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ int64 service_worker_registration_id);
+ void OnUnregisterRegion(int thread_id,
+ int request_id,
+ const std::string& region_id,
+ int64 service_worker_registration_id);
+ void OnGetRegisteredRegions(int thread_id,
+ int request_id,
+ int64 service_worker_registration_id);
+
+ void RegisterRegionCompleted(int thread_id,
+ int request_id,
+ GeofencingStatus result);
+ void UnregisterRegionCompleted(int thread_id,
+ int request_id,
+ GeofencingStatus result);
+
+ scoped_refptr<GeofencingManager> manager_;
+ base::WeakPtrFactory<GeofencingDispatcherHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeofencingDispatcherHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOFENCING_GEOFENCING_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/geofencing/geofencing_manager.cc b/chromium/content/browser/geofencing/geofencing_manager.cc
new file mode 100644
index 00000000000..6899c73067a
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_manager.cc
@@ -0,0 +1,371 @@
+// Copyright 2014 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 "content/browser/geofencing/geofencing_manager.h"
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "content/browser/geofencing/geofencing_service.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+#include "third_party/WebKit/public/platform/WebGeofencingEventType.h"
+#include "url/gurl.h"
+
+namespace content {
+
+struct GeofencingManager::Registration {
+ Registration(int64 service_worker_registration_id,
+ const GURL& service_worker_origin,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback,
+ int64 geofencing_registration_id);
+ int64 service_worker_registration_id;
+ GURL service_worker_origin;
+ std::string region_id;
+ blink::WebCircularGeofencingRegion region;
+
+ // Registration ID as returned by the |GeofencingService|.
+ int64 geofencing_registration_id;
+
+ // Callback to call when registration is completed. This field is reset when
+ // registration is complete.
+ StatusCallback registration_callback;
+
+ // Returns true if registration has been completed, and thus should be
+ // included in calls to GetRegisteredRegions.
+ bool is_active() const { return registration_callback.is_null(); }
+};
+
+GeofencingManager::Registration::Registration(
+ int64 service_worker_registration_id,
+ const GURL& service_worker_origin,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const GeofencingManager::StatusCallback& callback,
+ int64 geofencing_registration_id)
+ : service_worker_registration_id(service_worker_registration_id),
+ service_worker_origin(service_worker_origin),
+ region_id(region_id),
+ region(region),
+ geofencing_registration_id(geofencing_registration_id),
+ registration_callback(callback) {
+}
+
+GeofencingManager::GeofencingManager(
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
+ : service_(nullptr), service_worker_context_(service_worker_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+GeofencingManager::~GeofencingManager() {
+}
+
+void GeofencingManager::Init() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GeofencingManager::InitOnIO, this));
+}
+
+void GeofencingManager::Shutdown() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GeofencingManager::ShutdownOnIO, this));
+}
+
+void GeofencingManager::InitOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ service_ = GeofencingServiceImpl::GetInstance();
+}
+
+void GeofencingManager::ShutdownOnIO() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Clean up all registrations with the |GeofencingService|.
+ // TODO(mek): This will need to change to support geofence registrations that
+ // outlive the browser, although removing the references to this
+ // |GeofencingManager| from the |GeofencingService| will still be needed.
+ for (const auto& registration : registrations_by_id_) {
+ service_->UnregisterRegion(registration.first);
+ }
+}
+
+void GeofencingManager::RegisterRegion(
+ int64 service_worker_registration_id,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // TODO(mek): Validate region_id and region.
+
+ // Look up service worker. In unit tests |service_worker_context_| might not
+ // be set.
+ GURL service_worker_origin;
+ if (service_worker_context_.get()) {
+ ServiceWorkerRegistration* service_worker_registration =
+ service_worker_context_->context()->GetLiveRegistration(
+ service_worker_registration_id);
+ if (!service_worker_registration) {
+ callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER);
+ return;
+ }
+
+ service_worker_origin = service_worker_registration->pattern().GetOrigin();
+ }
+
+ if (!service_->IsServiceAvailable()) {
+ callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
+ return;
+ }
+
+ if (FindRegistration(service_worker_registration_id, region_id)) {
+ // Already registered, return an error.
+ // TODO(mek): Use a more specific error code.
+ callback.Run(GEOFENCING_STATUS_ERROR);
+ return;
+ }
+
+ AddRegistration(service_worker_registration_id,
+ service_worker_origin,
+ region_id,
+ region,
+ callback,
+ service_->RegisterRegion(region, this));
+}
+
+void GeofencingManager::UnregisterRegion(int64 service_worker_registration_id,
+ const std::string& region_id,
+ const StatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // TODO(mek): Validate region_id.
+
+ // Look up service worker. In unit tests |service_worker_context_| might not
+ // be set.
+ if (service_worker_context_.get()) {
+ ServiceWorkerRegistration* service_worker_registration =
+ service_worker_context_->context()->GetLiveRegistration(
+ service_worker_registration_id);
+ if (!service_worker_registration) {
+ callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER);
+ return;
+ }
+ }
+
+ if (!service_->IsServiceAvailable()) {
+ callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
+ return;
+ }
+
+ Registration* registration =
+ FindRegistration(service_worker_registration_id, region_id);
+ if (!registration) {
+ // Not registered, return an error.
+ callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED);
+ return;
+ }
+
+ if (!registration->is_active()) {
+ // Started registration, but not completed yet, error.
+ callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED);
+ return;
+ }
+
+ service_->UnregisterRegion(registration->geofencing_registration_id);
+ ClearRegistration(registration);
+ callback.Run(GEOFENCING_STATUS_OK);
+}
+
+GeofencingStatus GeofencingManager::GetRegisteredRegions(
+ int64 service_worker_registration_id,
+ std::map<std::string, blink::WebCircularGeofencingRegion>* result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ CHECK(result);
+
+ // Look up service worker. In unit tests |service_worker_context_| might not
+ // be set.
+ if (service_worker_context_.get()) {
+ ServiceWorkerRegistration* service_worker_registration =
+ service_worker_context_->context()->GetLiveRegistration(
+ service_worker_registration_id);
+ if (!service_worker_registration) {
+ return GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER;
+ }
+ }
+
+ if (!service_->IsServiceAvailable()) {
+ return GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE;
+ }
+
+ // Populate result, filtering out inactive registrations.
+ result->clear();
+ ServiceWorkerRegistrationsMap::iterator registrations =
+ registrations_.find(service_worker_registration_id);
+ if (registrations == registrations_.end())
+ return GEOFENCING_STATUS_OK;
+ for (const auto& registration : registrations->second) {
+ if (registration.second.is_active())
+ (*result)[registration.first] = registration.second.region;
+ }
+ return GEOFENCING_STATUS_OK;
+}
+
+void GeofencingManager::RegistrationFinished(int64 geofencing_registration_id,
+ GeofencingStatus status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ Registration* registration = FindRegistrationById(geofencing_registration_id);
+ DCHECK(registration);
+ DCHECK(!registration->is_active());
+ registration->registration_callback.Run(status);
+ registration->registration_callback.Reset();
+
+ // If the registration wasn't succesful, remove it from our storage.
+ if (status != GEOFENCING_STATUS_OK)
+ ClearRegistration(registration);
+}
+
+void GeofencingManager::RegionEntered(int64 geofencing_registration_id) {
+ DispatchGeofencingEvent(blink::WebGeofencingEventTypeEnter,
+ geofencing_registration_id);
+}
+
+void GeofencingManager::RegionExited(int64 geofencing_registration_id) {
+ DispatchGeofencingEvent(blink::WebGeofencingEventTypeLeave,
+ geofencing_registration_id);
+}
+
+GeofencingManager::Registration* GeofencingManager::FindRegistration(
+ int64 service_worker_registration_id,
+ const std::string& region_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ServiceWorkerRegistrationsMap::iterator registrations_iterator =
+ registrations_.find(service_worker_registration_id);
+ if (registrations_iterator == registrations_.end())
+ return nullptr;
+ RegionIdRegistrationMap::iterator registration =
+ registrations_iterator->second.find(region_id);
+ if (registration == registrations_iterator->second.end())
+ return nullptr;
+ return &registration->second;
+}
+
+GeofencingManager::Registration* GeofencingManager::FindRegistrationById(
+ int64 geofencing_registration_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ RegistrationIdRegistrationMap::iterator registration_iterator =
+ registrations_by_id_.find(geofencing_registration_id);
+ if (registration_iterator == registrations_by_id_.end())
+ return nullptr;
+ return &registration_iterator->second->second;
+}
+
+GeofencingManager::Registration& GeofencingManager::AddRegistration(
+ int64 service_worker_registration_id,
+ const GURL& service_worker_origin,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback,
+ int64 geofencing_registration_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!FindRegistration(service_worker_registration_id, region_id));
+ RegionIdRegistrationMap::iterator registration =
+ registrations_[service_worker_registration_id]
+ .insert(std::make_pair(region_id,
+ Registration(service_worker_registration_id,
+ service_worker_origin,
+ region_id,
+ region,
+ callback,
+ geofencing_registration_id)))
+ .first;
+ registrations_by_id_[geofencing_registration_id] = registration;
+ return registration->second;
+}
+
+void GeofencingManager::ClearRegistration(Registration* registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ registrations_by_id_.erase(registration->geofencing_registration_id);
+ ServiceWorkerRegistrationsMap::iterator registrations_iterator =
+ registrations_.find(registration->service_worker_registration_id);
+ DCHECK(registrations_iterator != registrations_.end());
+ registrations_iterator->second.erase(registration->region_id);
+ if (registrations_iterator->second.empty())
+ registrations_.erase(registrations_iterator);
+}
+
+void GeofencingManager::DispatchGeofencingEvent(
+ blink::WebGeofencingEventType event_type,
+ int64 geofencing_registration_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ Registration* registration = FindRegistrationById(geofencing_registration_id);
+ if (!registration ||
+ registration->service_worker_registration_id ==
+ kInvalidServiceWorkerRegistrationId) {
+ // TODO(mek): Log/track these failures.
+ return;
+ }
+
+ service_worker_context_->context()->storage()->FindRegistrationForId(
+ registration->service_worker_registration_id,
+ registration->service_worker_origin,
+ base::Bind(&GeofencingManager::DeliverGeofencingEvent,
+ this,
+ event_type,
+ geofencing_registration_id));
+}
+
+void GeofencingManager::DeliverGeofencingEvent(
+ blink::WebGeofencingEventType event_type,
+ int64 geofencing_registration_id,
+ ServiceWorkerStatusCode service_worker_status,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ Registration* registration = FindRegistrationById(geofencing_registration_id);
+ if (!registration) {
+ // Geofence got unregistered in the meantime, no longer need to deliver
+ // event.
+ return;
+ }
+
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ // TODO(mek): SW no longer exists, somehow handle this.
+ return;
+ }
+
+ ServiceWorkerVersion* active_version =
+ service_worker_registration->active_version();
+ if (!active_version) {
+ // TODO(mek): No active version, potentially because one is still being
+ // installed. Handle this somehow.
+ return;
+ }
+
+ // Hold on to the service worker registration in the callback to keep it alive
+ // until the callback dies. Otherwise the registration could be released when
+ // this method returns - before the event is delivered to the service worker.
+ base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback =
+ base::Bind(&GeofencingManager::DeliverGeofencingEventEnd,
+ this,
+ service_worker_registration);
+ active_version->DispatchGeofencingEvent(dispatch_event_callback,
+ event_type,
+ registration->region_id,
+ registration->region);
+}
+
+void GeofencingManager::DeliverGeofencingEventEnd(
+ const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
+ ServiceWorkerStatusCode service_worker_status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // TODO(mek): log/check result.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geofencing/geofencing_manager.h b/chromium/content/browser/geofencing/geofencing_manager.h
new file mode 100644
index 00000000000..29c52e4830b
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_manager.h
@@ -0,0 +1,179 @@
+// Copyright 2014 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 CONTENT_BROWSER_GEOFENCING_GEOFENCING_MANAGER_H_
+#define CONTENT_BROWSER_GEOFENCING_GEOFENCING_MANAGER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/geofencing/geofencing_registration_delegate.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/common/content_export.h"
+#include "content/common/geofencing_status.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+
+template <typename T>
+struct DefaultSingletonTraits;
+class GURL;
+
+namespace blink {
+struct WebCircularGeofencingRegion;
+};
+
+namespace content {
+
+class GeofencingService;
+class ServiceWorkerContextWrapper;
+class ServiceWorkerRegistration;
+
+// This is the main API to the geofencing subsystem. There is one instance of
+// this class per storage partition.
+// This class is responsible for keeping track of which geofences are currently
+// registered by websites/workers, persisting this list of registrations and
+// registering them with the global |GeofencingService|.
+// This class is created on the UI thread, but all its methods should only be
+// called from the IO thread.
+// TODO(mek): Implement some kind of persistence of registrations.
+// TODO(mek): Unregister a geofence when the ServiceWorkerRegistration it
+// belongs to goes away.
+class CONTENT_EXPORT GeofencingManager
+ : NON_EXPORTED_BASE(public GeofencingRegistrationDelegate),
+ public base::RefCountedThreadSafe<GeofencingManager> {
+ public:
+ typedef base::Callback<void(GeofencingStatus)> StatusCallback;
+
+ explicit GeofencingManager(
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
+
+ // Init and Shutdown are for use on the UI thread when the storagepartition is
+ // being setup and torn down.
+ void Init();
+ void Shutdown();
+
+ // Initiates registration of a new geofence. StatusCallback is called when
+ // registration has completed or failed (which could possibly be before
+ // RegisterRegion returns.
+ // Attempting to register a region with the same ID as an already registered
+ // (or in progress of being registered) region will fail.
+ // TODO(mek): Behavior when using an already used ID might need to be revised
+ // depending on what the actual spec ends up saying about this.
+ void RegisterRegion(int64 service_worker_registration_id,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback);
+
+ // Unregister a region that was previously registered by a call to
+ // RegisterRegion. Any attempt to unregister a region that has not been
+ // registered, or for which the registration is still in progress
+ // (RegisterRegion hasn't called its callback yet) will fail.
+ // TODO(mek): Maybe better behavior would be to allow unregistering still
+ // in-progress registrations.
+ void UnregisterRegion(int64 service_worker_registration_id,
+ const std::string& region_id,
+ const StatusCallback& callback);
+
+ // Returns all currently registered regions. In case of failure (no geofencing
+ // provider available for example) return an error status, while leaving
+ // |regions| untouched.
+ // This only returns regions for which the callback passed to RegisterRegion
+ // has been called already (so it doesn't include still in progress
+ // registrations).
+ GeofencingStatus GetRegisteredRegions(
+ int64 service_worker_registration_id,
+ std::map<std::string, blink::WebCircularGeofencingRegion>* result);
+
+ void SetServiceForTesting(GeofencingService* service) {
+ service_ = service;
+ }
+
+ protected:
+ friend class base::RefCountedThreadSafe<GeofencingManager>;
+ ~GeofencingManager() override;
+
+ private:
+ // Internal bookkeeping associated with each registered geofence.
+ struct Registration;
+
+ void InitOnIO();
+ void ShutdownOnIO();
+
+ // GeofencingRegistrationDelegate implementation.
+ void RegistrationFinished(int64 geofencing_registration_id,
+ GeofencingStatus status) override;
+ void RegionEntered(int64 geofencing_registration_id) override;
+ void RegionExited(int64 geofencing_registration_id) override;
+
+ // Looks up a particular geofence registration. Returns nullptr if no
+ // registration with the given IDs exists.
+ Registration* FindRegistration(int64 service_worker_registration_id,
+ const std::string& region_id);
+
+ // Looks up a particular geofence registration. Returns nullptr if no
+ // registration with the given ID exists.
+ Registration* FindRegistrationById(int64 geofencing_registration_id);
+
+ // Registers a new registration, returning a reference to the newly inserted
+ // object. Assumes no registration with the same IDs currently exists.
+ Registration& AddRegistration(
+ int64 service_worker_registration_id,
+ const GURL& service_worker_origin,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback,
+ int64 geofencing_registration_id);
+
+ // Clears a registration.
+ void ClearRegistration(Registration* registration);
+
+ // Starts dispatching a particular geofencing |event_type| for the geofence
+ // registration with the given ID. This first looks up the Service Worker
+ // Registration the geofence is associated with, and then attempts to deliver
+ // the event to that service worker.
+ void DispatchGeofencingEvent(blink::WebGeofencingEventType event_type,
+ int64 geofencing_registration_id);
+
+ // Delivers an event to the specified service worker for the given geofence.
+ // If the geofence registration id is no longer valid, this method does
+ // nothing. This assumes the |service_worker_registration| is the service
+ // worker the geofence registration is associated with.
+ void DeliverGeofencingEvent(blink::WebGeofencingEventType event_type,
+ int64 geofencing_registration_id,
+ ServiceWorkerStatusCode service_worker_status,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration);
+
+ // Called when delivery of a geofence event to a service worker has finished
+ // (or failed to finish).
+ void DeliverGeofencingEventEnd(const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration,
+ ServiceWorkerStatusCode service_worker_status);
+
+ // Map of all registered regions for a particular service worker registration.
+ typedef std::map<std::string, Registration> RegionIdRegistrationMap;
+ // Map of service worker registration id to the regions registered by that
+ // service worker.
+ typedef std::map<int64, RegionIdRegistrationMap>
+ ServiceWorkerRegistrationsMap;
+ ServiceWorkerRegistrationsMap registrations_;
+
+ // Map of all registered regions by geofencing_registration_id.
+ typedef std::map<int64, RegionIdRegistrationMap::iterator>
+ RegistrationIdRegistrationMap;
+ RegistrationIdRegistrationMap registrations_by_id_;
+
+ GeofencingService* service_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeofencingManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOFENCING_GEOFENCING_MANAGER_H_
diff --git a/chromium/content/browser/geofencing/geofencing_manager_unittest.cc b/chromium/content/browser/geofencing/geofencing_manager_unittest.cc
new file mode 100644
index 00000000000..cf64b9faa04
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_manager_unittest.cc
@@ -0,0 +1,414 @@
+// Copyright 2014 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/callback.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/geofencing/geofencing_manager.h"
+#include "content/browser/geofencing/geofencing_service.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+
+using blink::WebCircularGeofencingRegion;
+typedef std::map<std::string, WebCircularGeofencingRegion> RegionMap;
+
+namespace {
+
+static const char* kTestRegionId = "region-id";
+static const int64 kTestServiceWorkerRegistrationId = 123;
+static const int64 kTestServiceWorkerRegistrationId2 = 456;
+static const int64 kTestGeofencingRegistrationId = 42;
+static const int64 kTestGeofencingRegistrationId2 = 43;
+
+bool RegionsMatch(const WebCircularGeofencingRegion& expected,
+ const WebCircularGeofencingRegion& arg) {
+ return testing::Matches(expected.latitude)(arg.latitude) &&
+ testing::Matches(expected.longitude)(arg.longitude) &&
+ testing::Matches(expected.radius)(arg.radius);
+}
+}
+
+namespace content {
+
+class TestGeofencingService : public GeofencingService {
+ public:
+ MOCK_METHOD0(IsServiceAvailable, bool());
+ MOCK_METHOD2(RegisterRegion,
+ int64(const WebCircularGeofencingRegion& region,
+ GeofencingRegistrationDelegate* delegate));
+ MOCK_METHOD1(UnregisterRegion, void(int64 geofencing_registration_id));
+};
+
+ACTION_P(SaveDelegate, delegate) {
+ *delegate = arg1;
+}
+
+ACTION_P(QuitRunner, runner) {
+ runner->Quit();
+}
+
+MATCHER_P(WebCircularGeofencingRegionEq, expected, "") {
+ return RegionsMatch(expected, arg);
+}
+
+class StatusCatcher {
+ public:
+ StatusCatcher() : was_called_(false), runner_(new MessageLoopRunner()) {}
+
+ void Done(GeofencingStatus status) {
+ CHECK(!was_called_);
+ result_ = status;
+ was_called_ = true;
+ runner_->Quit();
+ }
+
+ GeofencingStatus Wait() {
+ runner_->Run();
+ CHECK(was_called_);
+ return result_;
+ }
+
+ private:
+ bool was_called_;
+ GeofencingStatus result_;
+ scoped_refptr<MessageLoopRunner> runner_;
+};
+
+class GeofencingManagerTest : public testing::Test {
+ public:
+ GeofencingManagerTest() : service_(nullptr) {
+ test_region_.latitude = 37.421999;
+ test_region_.longitude = -122.084015;
+ test_region_.radius = 100;
+ expected_regions_[kTestRegionId] = test_region_;
+ }
+
+ void SetUp() override {
+ service_ = new TestGeofencingService();
+ ON_CALL(*service_, IsServiceAvailable())
+ .WillByDefault(testing::Return(false));
+ manager_ = new GeofencingManager(nullptr /* ServiceWorkerContextWrapper */);
+ manager_->SetServiceForTesting(service_);
+ }
+
+ void TearDown() override {
+ manager_ = nullptr;
+ delete service_;
+ service_ = nullptr;
+ }
+
+ void SetHasProviderForTests() {
+ ON_CALL(*service_, IsServiceAvailable())
+ .WillByDefault(testing::Return(true));
+ }
+
+ GeofencingStatus RegisterRegionSync(
+ int64 service_worker_registration_id,
+ const std::string& id,
+ const WebCircularGeofencingRegion& region) {
+ StatusCatcher result;
+ manager_->RegisterRegion(
+ service_worker_registration_id,
+ id,
+ region,
+ base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
+ return result.Wait();
+ }
+
+ GeofencingStatus RegisterRegionSyncWithServiceResult(
+ int64 service_worker_registration_id,
+ const std::string& id,
+ const WebCircularGeofencingRegion& region,
+ GeofencingStatus service_status,
+ int64 geofencing_registration_id) {
+ StatusCatcher result;
+ GeofencingRegistrationDelegate* delegate = 0;
+ EXPECT_CALL(
+ *service_,
+ RegisterRegion(WebCircularGeofencingRegionEq(region), testing::_))
+ .WillOnce(testing::DoAll(SaveDelegate(&delegate),
+ testing::Return(geofencing_registration_id)));
+ manager_->RegisterRegion(
+ service_worker_registration_id,
+ id,
+ region,
+ base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
+ CHECK(delegate);
+ delegate->RegistrationFinished(geofencing_registration_id, service_status);
+ return result.Wait();
+ }
+
+ GeofencingStatus UnregisterRegionSync(int64 service_worker_registration_id,
+ const std::string& id,
+ bool should_call_service,
+ int64 geofencing_registration_id = 0) {
+ StatusCatcher result;
+ if (should_call_service) {
+ EXPECT_CALL(*service_, UnregisterRegion(geofencing_registration_id));
+ }
+ manager_->UnregisterRegion(
+ service_worker_registration_id,
+ id,
+ base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
+ return result.Wait();
+ }
+
+ void VerifyRegions(int64 service_worker_registration_id,
+ const RegionMap& expected_regions) {
+ RegionMap regions;
+ EXPECT_EQ(GEOFENCING_STATUS_OK,
+ manager_->GetRegisteredRegions(service_worker_registration_id,
+ &regions));
+ EXPECT_EQ(expected_regions.size(), regions.size());
+ for (RegionMap::const_iterator it = expected_regions.begin();
+ it != expected_regions.end();
+ ++it) {
+ EXPECT_THAT(regions[it->first],
+ WebCircularGeofencingRegionEq(it->second));
+ }
+ }
+
+ protected:
+ TestBrowserThreadBundle threads_;
+ TestGeofencingService* service_;
+ scoped_refptr<GeofencingManager> manager_;
+
+ WebCircularGeofencingRegion test_region_;
+ RegionMap expected_regions_;
+};
+
+TEST_F(GeofencingManagerTest, RegisterRegion_NoService) {
+ EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
+ RegisterRegionSync(
+ kTestServiceWorkerRegistrationId, kTestRegionId, test_region_));
+}
+
+TEST_F(GeofencingManagerTest, UnregisterRegion_NoService) {
+ EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
+ UnregisterRegionSync(
+ kTestServiceWorkerRegistrationId, kTestRegionId, false));
+}
+
+TEST_F(GeofencingManagerTest, GetRegisteredRegions_NoService) {
+ RegionMap regions;
+ EXPECT_EQ(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
+ manager_->GetRegisteredRegions(kTestServiceWorkerRegistrationId,
+ &regions));
+ EXPECT_TRUE(regions.empty());
+}
+
+TEST_F(GeofencingManagerTest, RegisterRegion_FailsInService) {
+ SetHasProviderForTests();
+ EXPECT_EQ(
+ GEOFENCING_STATUS_ERROR,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_ERROR,
+ -1));
+}
+
+TEST_F(GeofencingManagerTest, RegisterRegion_SucceedsInService) {
+ SetHasProviderForTests();
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId));
+ VerifyRegions(kTestServiceWorkerRegistrationId, expected_regions_);
+}
+
+TEST_F(GeofencingManagerTest, RegisterRegion_AlreadyRegistered) {
+ SetHasProviderForTests();
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId));
+ VerifyRegions(kTestServiceWorkerRegistrationId, expected_regions_);
+
+ WebCircularGeofencingRegion region2;
+ region2.latitude = 43.2;
+ region2.longitude = 1.45;
+ region2.radius = 8.5;
+ EXPECT_EQ(GEOFENCING_STATUS_ERROR,
+ RegisterRegionSync(
+ kTestServiceWorkerRegistrationId, kTestRegionId, region2));
+ VerifyRegions(kTestServiceWorkerRegistrationId, expected_regions_);
+}
+
+TEST_F(GeofencingManagerTest, UnregisterRegion_NotRegistered) {
+ SetHasProviderForTests();
+ EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED,
+ UnregisterRegionSync(
+ kTestServiceWorkerRegistrationId, kTestRegionId, false));
+}
+
+TEST_F(GeofencingManagerTest, UnregisterRegion_Success) {
+ SetHasProviderForTests();
+
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId));
+
+ EXPECT_EQ(GEOFENCING_STATUS_OK,
+ UnregisterRegionSync(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ true,
+ kTestGeofencingRegistrationId));
+ VerifyRegions(kTestServiceWorkerRegistrationId, RegionMap());
+}
+
+TEST_F(GeofencingManagerTest, GetRegisteredRegions_RegistrationInProgress) {
+ SetHasProviderForTests();
+ StatusCatcher result;
+ GeofencingRegistrationDelegate* delegate = nullptr;
+
+ EXPECT_CALL(
+ *service_,
+ RegisterRegion(WebCircularGeofencingRegionEq(test_region_), testing::_))
+ .WillOnce(testing::DoAll(SaveDelegate(&delegate),
+ testing::Return(kTestGeofencingRegistrationId)));
+ manager_->RegisterRegion(
+ kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
+
+ // At this point the manager should have tried registering the region with
+ // the service, resulting in |delegate| being set. Until the callback is
+ // called the registration is not complete though.
+ EXPECT_NE(delegate, nullptr);
+ VerifyRegions(kTestServiceWorkerRegistrationId, RegionMap());
+
+ // Now call the callback, and verify the registration completed succesfully.
+ delegate->RegistrationFinished(kTestGeofencingRegistrationId,
+ GEOFENCING_STATUS_OK);
+ EXPECT_EQ(GEOFENCING_STATUS_OK, result.Wait());
+ VerifyRegions(kTestServiceWorkerRegistrationId, expected_regions_);
+}
+
+TEST_F(GeofencingManagerTest, UnregisterRegion_RegistrationInProgress) {
+ SetHasProviderForTests();
+ StatusCatcher result;
+ GeofencingRegistrationDelegate* delegate = nullptr;
+
+ EXPECT_CALL(
+ *service_,
+ RegisterRegion(WebCircularGeofencingRegionEq(test_region_), testing::_))
+ .WillOnce(testing::DoAll(SaveDelegate(&delegate),
+ testing::Return(kTestGeofencingRegistrationId)));
+ manager_->RegisterRegion(
+ kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ base::Bind(&StatusCatcher::Done, base::Unretained(&result)));
+
+ // At this point the manager should have tried registering the region with
+ // the service, resulting in |delegate| being set. Until the callback is
+ // called the registration is not complete though.
+ EXPECT_NE(delegate, nullptr);
+
+ EXPECT_EQ(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED,
+ UnregisterRegionSync(
+ kTestServiceWorkerRegistrationId, kTestRegionId, false));
+}
+
+TEST_F(GeofencingManagerTest, GetRegisteredRegions_NoRegions) {
+ SetHasProviderForTests();
+ VerifyRegions(kTestServiceWorkerRegistrationId, RegionMap());
+}
+
+TEST_F(GeofencingManagerTest, RegisterRegion_SeparateServiceWorkers) {
+ SetHasProviderForTests();
+
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId));
+
+ VerifyRegions(kTestServiceWorkerRegistrationId, expected_regions_);
+ VerifyRegions(kTestServiceWorkerRegistrationId2, RegionMap());
+
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId2,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId2));
+
+ VerifyRegions(kTestServiceWorkerRegistrationId, expected_regions_);
+ VerifyRegions(kTestServiceWorkerRegistrationId2, expected_regions_);
+}
+
+TEST_F(GeofencingManagerTest, UnregisterRegion_SeparateServiceWorkers) {
+ SetHasProviderForTests();
+
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId));
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId2,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId2));
+
+ EXPECT_EQ(GEOFENCING_STATUS_OK,
+ UnregisterRegionSync(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ true,
+ kTestGeofencingRegistrationId));
+
+ VerifyRegions(kTestServiceWorkerRegistrationId, RegionMap());
+ VerifyRegions(kTestServiceWorkerRegistrationId2, expected_regions_);
+
+ EXPECT_EQ(GEOFENCING_STATUS_OK,
+ UnregisterRegionSync(kTestServiceWorkerRegistrationId2,
+ kTestRegionId,
+ true,
+ kTestGeofencingRegistrationId2));
+
+ VerifyRegions(kTestServiceWorkerRegistrationId, RegionMap());
+ VerifyRegions(kTestServiceWorkerRegistrationId2, RegionMap());
+}
+
+TEST_F(GeofencingManagerTest, ShutdownCleansRegistrations) {
+ SetHasProviderForTests();
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner());
+ EXPECT_EQ(
+ GEOFENCING_STATUS_OK,
+ RegisterRegionSyncWithServiceResult(kTestServiceWorkerRegistrationId,
+ kTestRegionId,
+ test_region_,
+ GEOFENCING_STATUS_OK,
+ kTestGeofencingRegistrationId));
+
+ EXPECT_CALL(*service_, UnregisterRegion(kTestGeofencingRegistrationId))
+ .WillOnce(QuitRunner(runner));
+ manager_->Shutdown();
+ runner->Run();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geofencing/geofencing_provider.h b/chromium/content/browser/geofencing/geofencing_provider.h
new file mode 100644
index 00000000000..dec96b5270b
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_provider.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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 CONTENT_BROWSER_GEOFENCING_GEOFENCING_PROVIDER_H_
+#define CONTENT_BROWSER_GEOFENCING_GEOFENCING_PROVIDER_H_
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "content/common/geofencing_status.h"
+
+namespace blink {
+struct WebCircularGeofencingRegion;
+};
+
+namespace content {
+
+class GeofencingProvider {
+ public:
+ typedef base::Callback<void(GeofencingStatus)> StatusCallback;
+
+ virtual ~GeofencingProvider() {}
+
+ // Called by |GeofencingService| to register a new fence. GeofencingService is
+ // responsible for handling things like duplicate regions, so platform
+ // specific implementations shouldn't have to worry about things like that.
+ // Also GeofencingService should be making sure the total number of geofences
+ // that is registered with the platform specific provider does not exceed the
+ // number of regions supported by the platform, although that isn't
+ // implemented yet.
+ // Implementations of RegisterRegion must asynchronously call the |callback|
+ // to indicate success or failure.
+ virtual void RegisterRegion(int64 geofencing_registration_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback) = 0;
+
+ // Called by |GeofencingService| to unregister an existing registration. Will
+ // only be called once for each registration.
+ virtual void UnregisterRegion(int64 geofencing_registration_id) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOFENCING_GEOFENCING_PROVIDER_H_
diff --git a/chromium/content/browser/geofencing/geofencing_registration_delegate.h b/chromium/content/browser/geofencing/geofencing_registration_delegate.h
new file mode 100644
index 00000000000..ead0ec8eed0
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_registration_delegate.h
@@ -0,0 +1,31 @@
+// Copyright 2014 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 CONTENT_BROWSER_GEOFENCING_GEOFENCING_REGISTRATION_DELEGATE_H_
+#define CONTENT_BROWSER_GEOFENCING_GEOFENCING_REGISTRATION_DELEGATE_H_
+
+#include "base/basictypes.h"
+#include "content/common/geofencing_status.h"
+
+namespace content {
+
+// |GeofencingService| has an instance of this class associated with each
+// geofence registration, and uses it to inform about events related to the
+// registration, such as the geofence finishing being registered.
+// These methods will always be called on the IO thread.
+// TODO(mek): Add methods for geofence enter/leave events.
+class GeofencingRegistrationDelegate {
+ public:
+ virtual void RegistrationFinished(int64 geofencing_registration_id,
+ GeofencingStatus status) = 0;
+ virtual void RegionEntered(int64 geofencing_registration_id) = 0;
+ virtual void RegionExited(int64 geofencing_registration_id) = 0;
+
+ protected:
+ virtual ~GeofencingRegistrationDelegate() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOFENCING_GEOFENCING_REGISTRATION_DELEGATE_H_
diff --git a/chromium/content/browser/geofencing/geofencing_service.cc b/chromium/content/browser/geofencing/geofencing_service.cc
new file mode 100644
index 00000000000..11df9529e4d
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_service.cc
@@ -0,0 +1,199 @@
+// Copyright 2014 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 "content/browser/geofencing/geofencing_service.h"
+
+#include "base/memory/singleton.h"
+#include "base/message_loop/message_loop.h"
+#include "content/browser/geofencing/geofencing_provider.h"
+#include "content/browser/geofencing/geofencing_registration_delegate.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+
+namespace content {
+
+namespace {
+
+void RunSoon(const base::Closure& callback) {
+ if (!callback.is_null())
+ base::MessageLoop::current()->PostTask(FROM_HERE, callback);
+}
+
+} // namespace
+
+struct GeofencingServiceImpl::Registration {
+ Registration();
+ Registration(const blink::WebCircularGeofencingRegion& region,
+ int64 geofencing_registration_id,
+ GeofencingRegistrationDelegate* delegate);
+
+ blink::WebCircularGeofencingRegion region;
+ int64 geofencing_registration_id;
+ GeofencingRegistrationDelegate* delegate;
+
+ enum RegistrationState {
+ // In progress of being registered with provider.
+ STATE_REGISTERING,
+ // Currently registered with provider.
+ STATE_REGISTERED,
+ // In progress of being registered with provider, but should be unregistered
+ // and deleted.
+ STATE_SHOULD_UNREGISTER_AND_DELETE,
+ // Not currently registered with provider, but still an active registration.
+ STATE_UNREGISTERED
+ };
+ RegistrationState state;
+};
+
+GeofencingServiceImpl::Registration::Registration()
+ : geofencing_registration_id(-1),
+ delegate(nullptr),
+ state(STATE_UNREGISTERED) {
+}
+
+GeofencingServiceImpl::Registration::Registration(
+ const blink::WebCircularGeofencingRegion& region,
+ int64 geofencing_registration_id,
+ GeofencingRegistrationDelegate* delegate)
+ : region(region),
+ geofencing_registration_id(geofencing_registration_id),
+ delegate(delegate),
+ state(STATE_REGISTERING) {
+}
+
+GeofencingServiceImpl::GeofencingServiceImpl() : next_registration_id_(0) {
+}
+
+GeofencingServiceImpl::~GeofencingServiceImpl() {
+}
+
+GeofencingServiceImpl* GeofencingServiceImpl::GetInstance() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return Singleton<GeofencingServiceImpl>::get();
+}
+
+bool GeofencingServiceImpl::IsServiceAvailable() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return EnsureProvider();
+}
+
+int64 GeofencingServiceImpl::RegisterRegion(
+ const blink::WebCircularGeofencingRegion& region,
+ GeofencingRegistrationDelegate* delegate) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ int64 geofencing_registration_id = GetNextId();
+ registrations_[geofencing_registration_id] =
+ Registration(region, geofencing_registration_id, delegate);
+
+ if (!EnsureProvider()) {
+ RunSoon(
+ base::Bind(&GeofencingServiceImpl::NotifyRegistrationFinished,
+ base::Unretained(this),
+ geofencing_registration_id,
+ GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE));
+ return geofencing_registration_id;
+ }
+
+ provider_->RegisterRegion(
+ geofencing_registration_id,
+ region,
+ base::Bind(&GeofencingServiceImpl::NotifyRegistrationFinished,
+ base::Unretained(this),
+ geofencing_registration_id));
+ return geofencing_registration_id;
+}
+
+void GeofencingServiceImpl::UnregisterRegion(int64 geofencing_registration_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ RegistrationsMap::iterator registration_iterator =
+ registrations_.find(geofencing_registration_id);
+ DCHECK(registration_iterator != registrations_.end());
+
+ if (!EnsureProvider())
+ return;
+
+ switch (registration_iterator->second.state) {
+ case Registration::STATE_REGISTERED:
+ provider_->UnregisterRegion(geofencing_registration_id);
+ // fallthru
+ case Registration::STATE_UNREGISTERED:
+ registrations_.erase(registration_iterator);
+ break;
+ case Registration::STATE_REGISTERING:
+ // Update state, NotifyRegistrationFinished will take care of actually
+ // unregistering.
+ registration_iterator->second.state =
+ Registration::STATE_SHOULD_UNREGISTER_AND_DELETE;
+ break;
+ case Registration::STATE_SHOULD_UNREGISTER_AND_DELETE:
+ // Should not happen.
+ NOTREACHED();
+ break;
+ }
+}
+
+void GeofencingServiceImpl::SetProviderForTesting(
+ scoped_ptr<GeofencingProvider> provider) {
+ DCHECK(!provider_.get());
+ provider_ = provider.Pass();
+}
+
+int GeofencingServiceImpl::RegistrationCountForTesting() {
+ return registrations_.size();
+}
+
+bool GeofencingServiceImpl::EnsureProvider() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!provider_) {
+ // TODO(mek): Create platform specific provider.
+ return false;
+ }
+ return true;
+}
+
+int64 GeofencingServiceImpl::GetNextId() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ return next_registration_id_++;
+}
+
+void GeofencingServiceImpl::NotifyRegistrationFinished(
+ int64 geofencing_registration_id,
+ GeofencingStatus status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ RegistrationsMap::iterator registration_iterator =
+ registrations_.find(geofencing_registration_id);
+ DCHECK(registration_iterator != registrations_.end());
+ DCHECK(registration_iterator->second.state ==
+ Registration::STATE_REGISTERING ||
+ registration_iterator->second.state ==
+ Registration::STATE_SHOULD_UNREGISTER_AND_DELETE);
+
+ if (registration_iterator->second.state ==
+ Registration::STATE_SHOULD_UNREGISTER_AND_DELETE) {
+ // Don't call delegate, but unregister with provider if registration was
+ // succesfull.
+ if (status == GEOFENCING_STATUS_OK) {
+ provider_->UnregisterRegion(geofencing_registration_id);
+ }
+ registrations_.erase(registration_iterator);
+ return;
+ }
+
+ // Normal case, mark as registered and call delegate.
+ registration_iterator->second.state = Registration::STATE_REGISTERED;
+ registration_iterator->second.delegate->RegistrationFinished(
+ geofencing_registration_id, status);
+
+ if (status != GEOFENCING_STATUS_OK) {
+ // Registration failed, remove from our book-keeping.
+ registrations_.erase(registration_iterator);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geofencing/geofencing_service.h b/chromium/content/browser/geofencing/geofencing_service.h
new file mode 100644
index 00000000000..dc3d832ffdf
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_service.h
@@ -0,0 +1,105 @@
+// Copyright 2014 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 CONTENT_BROWSER_GEOFENCING_GEOFENCING_SERVICE_H_
+#define CONTENT_BROWSER_GEOFENCING_GEOFENCING_SERVICE_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/common/geofencing_status.h"
+
+template <typename T>
+struct DefaultSingletonTraits;
+
+namespace blink {
+struct WebCircularGeofencingRegion;
+};
+
+namespace content {
+
+class GeofencingProvider;
+class GeofencingRegistrationDelegate;
+
+// This interface exists primarily to facilitate testing of classes that depend
+// on GeofencingService. It defines the interface exposed by
+// |GeofencingService|.
+class GeofencingService {
+ public:
+ virtual ~GeofencingService() {}
+
+ // Returns if a geofencing service is available.
+ virtual bool IsServiceAvailable() = 0;
+
+ // Register a region. This returns a unique registration ID, and
+ // asynchronously calls the |delegate|s RegistrationFinished method to
+ // inform the delegate of the result of the attempt to register the region.
+ // This does not transfer ownership of the |delegate|. Callers have to ensure
+ // that the delegate remains valid as long as the region is registered.
+ virtual int64 RegisterRegion(const blink::WebCircularGeofencingRegion& region,
+ GeofencingRegistrationDelegate* delegate) = 0;
+
+ // Unregister a region. This is assumed to always succeed. It is safe to call
+ // this even if a registration is still in progress.
+ virtual void UnregisterRegion(int64 geofencing_registration_id) = 0;
+};
+
+// This class combines all the geofence registrations from the various per
+// storage partition |GeofencingManager| instances, and registers a subset
+// of those fences with an underlying platform specific |GeofencingProvider|.
+// TODO(mek): Limit the number of geofences that are registered with the
+// underlying GeofencingProvider.
+class CONTENT_EXPORT GeofencingServiceImpl
+ : NON_EXPORTED_BASE(public GeofencingService) {
+ public:
+ // Gets a pointer to the singleton instance of the geofencing service. This
+ // must only be called on the IO thread so that the GeofencingService is
+ // always instantiated on the same thread. Ownership is NOT returned.
+ static GeofencingServiceImpl* GetInstance();
+
+ // GeofencingServiceInterface implementation.
+ bool IsServiceAvailable() override;
+ int64 RegisterRegion(
+ const blink::WebCircularGeofencingRegion& region,
+ GeofencingRegistrationDelegate* delegate) override;
+ void UnregisterRegion(int64 geofencing_registration_id) override;
+
+ protected:
+ friend class GeofencingServiceTest;
+ friend struct DefaultSingletonTraits<GeofencingServiceImpl>;
+ GeofencingServiceImpl();
+ ~GeofencingServiceImpl() override;
+
+ void SetProviderForTesting(scoped_ptr<GeofencingProvider> provider);
+ int RegistrationCountForTesting();
+
+ private:
+ struct Registration;
+ typedef std::map<int64, Registration> RegistrationsMap;
+
+ // This method checks if a |GeofencingProvider| exists, creates a new one if
+ // not, and finally returns false if it can't create a provider for the
+ // current platform.
+ bool EnsureProvider();
+
+ // Returns a new unique ID to use for the next geofence registration.
+ int64 GetNextId();
+
+ // Notifies the correct delegate that registration has completed for a
+ // specific geofence registration.
+ void NotifyRegistrationFinished(int64 geofencing_registration_id,
+ GeofencingStatus status);
+
+ int64 next_registration_id_;
+ RegistrationsMap registrations_;
+ scoped_ptr<GeofencingProvider> provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeofencingServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOFENCING_GEOFENCING_SERVICE_H_
diff --git a/chromium/content/browser/geofencing/geofencing_service_unittest.cc b/chromium/content/browser/geofencing/geofencing_service_unittest.cc
new file mode 100644
index 00000000000..7fbe0355c8a
--- /dev/null
+++ b/chromium/content/browser/geofencing/geofencing_service_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright 2014 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 "content/browser/geofencing/geofencing_provider.h"
+#include "content/browser/geofencing/geofencing_registration_delegate.h"
+#include "content/browser/geofencing/geofencing_service.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+
+using blink::WebCircularGeofencingRegion;
+
+namespace {
+
+bool RegionsMatch(const WebCircularGeofencingRegion& expected,
+ const WebCircularGeofencingRegion& arg) {
+ return testing::Matches(expected.latitude)(arg.latitude) &&
+ testing::Matches(expected.longitude)(arg.longitude) &&
+ testing::Matches(expected.radius)(arg.radius);
+}
+
+} // namespace
+
+namespace content {
+
+class MockGeofencingRegistrationDelegate
+ : public GeofencingRegistrationDelegate {
+ public:
+ MOCK_METHOD2(RegistrationFinished,
+ void(int64 geofencing_registration_id, GeofencingStatus status));
+ MOCK_METHOD1(RegionEntered, void(int64 geofencing_registration_id));
+ MOCK_METHOD1(RegionExited, void(int64 geofencing_registration_id));
+};
+
+class MockGeofencingProvider : public GeofencingProvider {
+ public:
+ MOCK_METHOD3(RegisterRegion,
+ void(int64 geofencing_registration_id,
+ const blink::WebCircularGeofencingRegion& region,
+ const StatusCallback& callback));
+ MOCK_METHOD1(UnregisterRegion, void(int64 geofencing_registration_id));
+};
+
+ACTION_P(QuitRunner, runner) {
+ runner->Quit();
+}
+
+ACTION_P(SaveRegistrationId, geofencing_registration_id) {
+ *geofencing_registration_id = arg0;
+}
+
+ACTION_P(SaveStatusCallback, callback) {
+ *callback = arg2;
+}
+
+MATCHER_P(WebCircularGeofencingRegionEq, expected, "") {
+ return RegionsMatch(expected, arg);
+}
+
+class GeofencingServiceTest : public testing::Test {
+ public:
+ GeofencingServiceTest() : service_(nullptr) {
+ test_region_.latitude = 37.421999;
+ test_region_.longitude = -122.084015;
+ test_region_.radius = 100;
+ }
+
+ void SetUp() override { service_ = new GeofencingServiceImpl(); }
+
+ void TearDown() override { delete service_; }
+
+ void SetProviderForTests() {
+ provider_ = new MockGeofencingProvider();
+ service_->SetProviderForTesting(make_scoped_ptr(provider_));
+ }
+
+ int RegistrationCount() { return service_->RegistrationCountForTesting(); }
+
+ int64 RegisterRegionSync(const WebCircularGeofencingRegion& region,
+ GeofencingStatus provider_status) {
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner());
+
+ // The registration ID that is passed to the provider.
+ int64 provider_registration_id = -1;
+ // The callback that is passed to the provider.
+ GeofencingProvider::StatusCallback callback;
+
+ EXPECT_CALL(
+ *provider_,
+ RegisterRegion(
+ testing::_, WebCircularGeofencingRegionEq(region), testing::_))
+ .WillOnce(testing::DoAll(SaveRegistrationId(&provider_registration_id),
+ SaveStatusCallback(&callback)));
+
+ int64 geofencing_registration_id =
+ service_->RegisterRegion(region, &delegate_);
+
+ // Service should have synchronously called the provider.
+ CHECK(!callback.is_null());
+ CHECK(provider_registration_id == geofencing_registration_id);
+
+ // Finish up registration by calling the callback and waiting for the
+ // delegate to be called.
+ EXPECT_CALL(
+ delegate_,
+ RegistrationFinished(geofencing_registration_id, provider_status))
+ .WillOnce(QuitRunner(runner));
+ callback.Run(provider_status);
+ runner->Run();
+ return geofencing_registration_id;
+ }
+
+ protected:
+ TestBrowserThreadBundle threads_;
+ GeofencingServiceImpl* service_;
+ MockGeofencingProvider* provider_;
+ MockGeofencingRegistrationDelegate delegate_;
+
+ WebCircularGeofencingRegion test_region_;
+};
+
+TEST_F(GeofencingServiceTest, RegisterRegion_NoProvider) {
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner());
+ int64 geofencing_registration_id =
+ service_->RegisterRegion(test_region_, &delegate_);
+ EXPECT_CALL(delegate_,
+ RegistrationFinished(
+ geofencing_registration_id,
+ GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE))
+ .WillOnce(QuitRunner(runner));
+ runner->Run();
+ EXPECT_EQ(0, RegistrationCount());
+}
+
+TEST_F(GeofencingServiceTest, RegisterRegion_FailsInProvider) {
+ SetProviderForTests();
+ RegisterRegionSync(test_region_, GEOFENCING_STATUS_ERROR);
+ EXPECT_EQ(0, RegistrationCount());
+}
+
+TEST_F(GeofencingServiceTest, RegisterRegion_SucceedsInProvider) {
+ SetProviderForTests();
+ RegisterRegionSync(test_region_, GEOFENCING_STATUS_OK);
+ EXPECT_EQ(1, RegistrationCount());
+}
+
+TEST_F(GeofencingServiceTest, UnregisterRegion_AfterRegistration) {
+ SetProviderForTests();
+ int geofencing_registration_id =
+ RegisterRegionSync(test_region_, GEOFENCING_STATUS_OK);
+ EXPECT_EQ(1, RegistrationCount());
+
+ EXPECT_CALL(*provider_, UnregisterRegion(geofencing_registration_id));
+ service_->UnregisterRegion(geofencing_registration_id);
+ EXPECT_EQ(0, RegistrationCount());
+}
+
+TEST_F(GeofencingServiceTest, UnregisterRegion_DuringSuccesfullRegistration) {
+ SetProviderForTests();
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner());
+
+ // The callback that is passed to the provider.
+ GeofencingProvider::StatusCallback callback;
+
+ EXPECT_CALL(
+ *provider_,
+ RegisterRegion(
+ testing::_, WebCircularGeofencingRegionEq(test_region_), testing::_))
+ .WillOnce(SaveStatusCallback(&callback));
+
+ int64 geofencing_registration_id =
+ service_->RegisterRegion(test_region_, &delegate_);
+
+ // Service should have synchronously called the provider.
+ CHECK(!callback.is_null());
+
+ // Call unregister before registration is finished.
+ service_->UnregisterRegion(geofencing_registration_id);
+
+ // Finish up registration by calling the callback and waiting for the
+ // provider to be called. The delegate should not be called in this case.
+ EXPECT_CALL(delegate_, RegistrationFinished(testing::_, testing::_)).Times(0);
+ EXPECT_CALL(*provider_, UnregisterRegion(geofencing_registration_id))
+ .WillOnce(QuitRunner(runner));
+ callback.Run(GEOFENCING_STATUS_OK);
+ runner->Run();
+ EXPECT_EQ(0, RegistrationCount());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/OWNERS b/chromium/content/browser/geolocation/OWNERS
index df10cf46d57..df3450ea5a7 100644
--- a/chromium/content/browser/geolocation/OWNERS
+++ b/chromium/content/browser/geolocation/OWNERS
@@ -1,3 +1,2 @@
-bulach@chromium.org
mvanouwerkerk@chromium.org
timvolodine@chromium.org
diff --git a/chromium/content/browser/geolocation/empty_wifi_data_provider.cc b/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
index d24213155d5..2a1f7680d89 100644
--- a/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
+++ b/chromium/content/browser/geolocation/empty_wifi_data_provider.cc
@@ -4,6 +4,8 @@
#include "content/browser/geolocation/empty_wifi_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
+
namespace content {
EmptyWifiDataProvider::EmptyWifiDataProvider() {
@@ -19,7 +21,7 @@ bool EmptyWifiDataProvider::GetData(WifiData* data) {
}
// static
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
return new EmptyWifiDataProvider();
}
diff --git a/chromium/content/browser/geolocation/empty_wifi_data_provider.h b/chromium/content/browser/geolocation/empty_wifi_data_provider.h
index a02ed2bc9b7..4397e19b547 100644
--- a/chromium/content/browser/geolocation/empty_wifi_data_provider.h
+++ b/chromium/content/browser/geolocation/empty_wifi_data_provider.h
@@ -9,16 +9,16 @@
namespace content {
-// An implementation of WifiDataProviderImplBase that does not provide any
+// An implementation of WifiDataProvider that does not provide any
// data. Used on platforms where a real implementation is not available.
-class EmptyWifiDataProvider : public WifiDataProviderImplBase {
+class EmptyWifiDataProvider : public WifiDataProvider {
public:
EmptyWifiDataProvider();
- // WifiDataProviderImplBase implementation
- virtual void StartDataProvider() OVERRIDE { }
- virtual void StopDataProvider() OVERRIDE { }
- virtual bool GetData(WifiData* data) OVERRIDE;
+ // WifiDataProvider implementation
+ virtual void StartDataProvider() override { }
+ virtual void StopDataProvider() override { }
+ virtual bool GetData(WifiData* data) override;
private:
virtual ~EmptyWifiDataProvider();
diff --git a/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc b/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
index ad1f2fcc444..9dfec900ea2 100644
--- a/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
+++ b/chromium/content/browser/geolocation/geolocation_dispatcher_host.cc
@@ -7,72 +7,24 @@
#include <utility>
#include "base/bind.h"
-#include "base/metrics/histogram.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/geolocation/geolocation_provider_impl.h"
#include "content/browser/renderer_host/render_message_filter.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/common/geoposition.h"
#include "content/common/geolocation_messages.h"
namespace content {
-namespace {
-
-// Geoposition error codes for reporting in UMA.
-enum GeopositionErrorCode {
- // NOTE: Do not renumber these as that would confuse interpretation of
- // previously logged data. When making changes, also update the enum list
- // in tools/metrics/histograms/histograms.xml to keep it in sync.
-
- // There was no error.
- GEOPOSITION_ERROR_CODE_NONE = 0,
-
- // User denied use of geolocation.
- GEOPOSITION_ERROR_CODE_PERMISSION_DENIED = 1,
-
- // Geoposition could not be determined.
- GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE = 2,
-
- // Timeout.
- GEOPOSITION_ERROR_CODE_TIMEOUT = 3,
-
- // NOTE: Add entries only immediately above this line.
- GEOPOSITION_ERROR_CODE_COUNT = 4
-};
-
-void RecordGeopositionErrorCode(Geoposition::ErrorCode error_code) {
- GeopositionErrorCode code = GEOPOSITION_ERROR_CODE_NONE;
- switch (error_code) {
- case Geoposition::ERROR_CODE_NONE:
- code = GEOPOSITION_ERROR_CODE_NONE;
- break;
- case Geoposition::ERROR_CODE_PERMISSION_DENIED:
- code = GEOPOSITION_ERROR_CODE_PERMISSION_DENIED;
- break;
- case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
- code = GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE;
- break;
- case Geoposition::ERROR_CODE_TIMEOUT:
- code = GEOPOSITION_ERROR_CODE_TIMEOUT;
- break;
- }
- UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
- code,
- GEOPOSITION_ERROR_CODE_COUNT);
-}
-
-} // namespace
GeolocationDispatcherHost::PendingPermission::PendingPermission(
int render_frame_id,
int render_process_id,
- int bridge_id)
+ int bridge_id,
+ const GURL& origin)
: render_frame_id(render_frame_id),
render_process_id(render_process_id),
- bridge_id(bridge_id) {
+ bridge_id(bridge_id),
+ origin(origin) {
}
GeolocationDispatcherHost::PendingPermission::~PendingPermission() {
@@ -81,7 +33,6 @@ GeolocationDispatcherHost::PendingPermission::~PendingPermission() {
GeolocationDispatcherHost::GeolocationDispatcherHost(
WebContents* web_contents)
: WebContentsObserver(web_contents),
- paused_(false),
weak_factory_(this) {
// This is initialized by WebContentsImpl. Do not add any non-trivial
// initialization here, defer to OnStartUpdating which is triggered whenever
@@ -93,15 +44,17 @@ GeolocationDispatcherHost::~GeolocationDispatcherHost() {
void GeolocationDispatcherHost::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
- OnStopUpdating(render_frame_host);
+ CancelPermissionRequestsForFrame(render_frame_host);
}
-void GeolocationDispatcherHost::RenderViewHostChanged(
- RenderViewHost* old_host,
- RenderViewHost* new_host) {
- updating_frames_.clear();
- paused_ = false;
- geolocation_subscription_.reset();
+void GeolocationDispatcherHost::DidNavigateAnyFrame(
+ RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) {
+ if (details.is_in_page)
+ return;
+
+ CancelPermissionRequestsForFrame(render_frame_host);
}
bool GeolocationDispatcherHost::OnMessageReceived(
@@ -111,118 +64,34 @@ bool GeolocationDispatcherHost::OnMessageReceived(
render_frame_host)
IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission,
OnRequestPermission)
- IPC_MESSAGE_HANDLER(GeolocationHostMsg_CancelPermissionRequest,
- OnCancelPermissionRequest)
- IPC_MESSAGE_HANDLER(GeolocationHostMsg_StartUpdating, OnStartUpdating)
- IPC_MESSAGE_HANDLER(GeolocationHostMsg_StopUpdating, OnStopUpdating)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void GeolocationDispatcherHost::OnLocationUpdate(
- const Geoposition& geoposition) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- RecordGeopositionErrorCode(geoposition.error_code);
- if (paused_)
- return;
-
- for (std::map<RenderFrameHost*, bool>::iterator i = updating_frames_.begin();
- i != updating_frames_.end(); ++i) {
- i->first->Send(new GeolocationMsg_PositionUpdated(
- i->first->GetRoutingID(), geoposition));
- }
-}
-
void GeolocationDispatcherHost::OnRequestPermission(
RenderFrameHost* render_frame_host,
int bridge_id,
- const GURL& requesting_frame,
+ const GURL& requesting_origin,
bool user_gesture) {
int render_process_id = render_frame_host->GetProcess()->GetID();
int render_frame_id = render_frame_host->GetRoutingID();
PendingPermission pending_permission(
- render_frame_id, render_process_id, bridge_id);
+ render_frame_id, render_process_id, bridge_id, requesting_origin);
pending_permissions_.push_back(pending_permission);
- GetContentClient()->browser()->RequestGeolocationPermission(
+ GetContentClient()->browser()->RequestPermission(
+ content::PERMISSION_GEOLOCATION,
web_contents(),
bridge_id,
- requesting_frame,
+ requesting_origin,
user_gesture,
base::Bind(&GeolocationDispatcherHost::SendGeolocationPermissionResponse,
weak_factory_.GetWeakPtr(),
- render_process_id, render_frame_id, bridge_id),
- &pending_permissions_.back().cancel);
-}
-
-void GeolocationDispatcherHost::OnCancelPermissionRequest(
- RenderFrameHost* render_frame_host,
- int bridge_id,
- const GURL& requesting_frame) {
- int render_process_id = render_frame_host->GetProcess()->GetID();
- int render_frame_id = render_frame_host->GetRoutingID();
- for (size_t i = 0; i < pending_permissions_.size(); ++i) {
- if (pending_permissions_[i].render_process_id == render_process_id &&
- pending_permissions_[i].render_frame_id == render_frame_id &&
- pending_permissions_[i].bridge_id == bridge_id) {
- if (!pending_permissions_[i].cancel.is_null())
- pending_permissions_[i].cancel.Run();
- pending_permissions_.erase(pending_permissions_.begin() + i);
- return;
- }
- }
-}
-
-void GeolocationDispatcherHost::OnStartUpdating(
- RenderFrameHost* render_frame_host,
- const GURL& requesting_frame,
- bool enable_high_accuracy) {
- // StartUpdating() can be invoked as a result of high-accuracy mode
- // being enabled / disabled. No need to record the dispatcher again.
- UMA_HISTOGRAM_BOOLEAN(
- "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
- enable_high_accuracy);
-
- updating_frames_[render_frame_host] = enable_high_accuracy;
- RefreshGeolocationOptions();
-}
-
-void GeolocationDispatcherHost::OnStopUpdating(
- RenderFrameHost* render_frame_host) {
- updating_frames_.erase(render_frame_host);
- RefreshGeolocationOptions();
-}
-
-void GeolocationDispatcherHost::PauseOrResume(bool should_pause) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- paused_ = should_pause;
- RefreshGeolocationOptions();
-}
-
-void GeolocationDispatcherHost::RefreshGeolocationOptions() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (updating_frames_.empty() || paused_) {
- geolocation_subscription_.reset();
- return;
- }
-
- bool high_accuracy = false;
- for (std::map<RenderFrameHost*, bool>::iterator i =
- updating_frames_.begin(); i != updating_frames_.end(); ++i) {
- if (i->second) {
- high_accuracy = true;
- break;
- }
- }
- geolocation_subscription_ = GeolocationProvider::GetInstance()->
- AddLocationUpdateCallback(
- base::Bind(&GeolocationDispatcherHost::OnLocationUpdate,
- base::Unretained(this)),
- high_accuracy);
+ render_process_id,
+ render_frame_id,
+ bridge_id));
}
void GeolocationDispatcherHost::SendGeolocationPermissionResponse(
@@ -254,4 +123,22 @@ void GeolocationDispatcherHost::SendGeolocationPermissionResponse(
NOTREACHED();
}
+void GeolocationDispatcherHost::CancelPermissionRequestsForFrame(
+ RenderFrameHost* render_frame_host) {
+ int render_process_id = render_frame_host->GetProcess()->GetID();
+ int render_frame_id = render_frame_host->GetRoutingID();
+
+ for (size_t i = 0; i < pending_permissions_.size(); ++i) {
+ if (pending_permissions_[i].render_process_id == render_process_id &&
+ pending_permissions_[i].render_frame_id == render_frame_id) {
+ GetContentClient()->browser()->CancelPermissionRequest(
+ content::PERMISSION_GEOLOCATION,
+ web_contents(),
+ pending_permissions_[i].bridge_id,
+ pending_permissions_[i].origin);
+ pending_permissions_.erase(pending_permissions_.begin() + i);
+ }
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_dispatcher_host.h b/chromium/content/browser/geolocation/geolocation_dispatcher_host.h
index e8bda4026d6..6359de10cce 100644
--- a/chromium/content/browser/geolocation/geolocation_dispatcher_host.h
+++ b/chromium/content/browser/geolocation/geolocation_dispatcher_host.h
@@ -10,77 +10,62 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
-#include "content/browser/geolocation/geolocation_provider_impl.h"
#include "content/public/browser/web_contents_observer.h"
class GURL;
namespace content {
-// GeolocationDispatcherHost is an observer for Geolocation messages.
-// It's the complement of GeolocationDispatcher (owned by RenderView).
+// GeolocationDispatcherHost is an observer for Geolocation permissions-related
+// messages. In this role, it's the complement of GeolocationDispatcher (owned
+// by RenderFrame).
+// TODO(blundell): Eliminate this class in favor of having
+// Mojo handle permissions for geolocation once there is resolution on how
+// that will work. crbug.com/420498
class GeolocationDispatcherHost : public WebContentsObserver {
public:
explicit GeolocationDispatcherHost(WebContents* web_contents);
- virtual ~GeolocationDispatcherHost();
-
- // Pause or resumes geolocation. Resuming when nothing is paused is a no-op.
- // If the web contents is paused while not currently using geolocation but
- // then goes on to do so before being resumed, then it will not get
- // geolocation updates until it is resumed.
- void PauseOrResume(bool should_pause);
+ ~GeolocationDispatcherHost() override;
private:
// WebContentsObserver
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void RenderViewHostChanged(RenderViewHost* old_host,
- RenderViewHost* new_host) OVERRIDE;
- virtual bool OnMessageReceived(
- const IPC::Message& msg, RenderFrameHost* render_frame_host) OVERRIDE;
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+ void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override;
+ bool OnMessageReceived(const IPC::Message& msg,
+ RenderFrameHost* render_frame_host) override;
// Message handlers:
+ // TODO(mlamouri): |requesting_origin| should be a security origin to
+ // guarantee that a proper origin is passed.
void OnRequestPermission(RenderFrameHost* render_frame_host,
int bridge_id,
- const GURL& requesting_frame,
+ const GURL& requesting_origin,
bool user_gesture);
- void OnCancelPermissionRequest(RenderFrameHost* render_frame_host,
- int bridge_id,
- const GURL& requesting_frame);
- void OnStartUpdating(RenderFrameHost* render_frame_host,
- const GURL& requesting_frame,
- bool enable_high_accuracy);
- void OnStopUpdating(RenderFrameHost* render_frame_host);
-
- // Updates the geolocation provider with the currently required update
- // options.
- void RefreshGeolocationOptions();
-
- void OnLocationUpdate(const Geoposition& position);
void SendGeolocationPermissionResponse(int render_process_id,
int render_frame_id,
int bridge_id,
bool allowed);
- // A map from the RenderFrameHosts that have requested geolocation updates to
- // the type of accuracy they requested (true = high accuracy).
- std::map<RenderFrameHost*, bool> updating_frames_;
- bool paused_;
+ // Clear pending permissions associated with a given frame and request the
+ // browser to cancel the permission requests.
+ void CancelPermissionRequestsForFrame(RenderFrameHost* render_frame_host);
struct PendingPermission {
PendingPermission(int render_frame_id,
int render_process_id,
- int bridge_id);
+ int bridge_id,
+ const GURL& origin);
~PendingPermission();
int render_frame_id;
int render_process_id;
int bridge_id;
- base::Closure cancel;
+ GURL origin;
};
std::vector<PendingPermission> pending_permissions_;
- scoped_ptr<GeolocationProvider::Subscription> geolocation_subscription_;
-
base::WeakPtrFactory<GeolocationDispatcherHost> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GeolocationDispatcherHost);
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl.h b/chromium/content/browser/geolocation/geolocation_provider_impl.h
index e3b8762ed44..b3c128649bb 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.h
@@ -26,18 +26,18 @@ class CONTENT_EXPORT GeolocationProviderImpl
public base::Thread {
public:
// GeolocationProvider implementation:
- virtual scoped_ptr<GeolocationProvider::Subscription>
- AddLocationUpdateCallback(const LocationUpdateCallback& callback,
- bool use_high_accuracy) OVERRIDE;
- virtual void UserDidOptIntoLocationServices() OVERRIDE;
- virtual void OverrideLocationForTesting(const Geoposition& position) OVERRIDE;
+ scoped_ptr<GeolocationProvider::Subscription> AddLocationUpdateCallback(
+ const LocationUpdateCallback& callback,
+ bool use_high_accuracy) override;
+ void UserDidOptIntoLocationServices() override;
+ void OverrideLocationForTesting(const Geoposition& position) override;
// Callback from the LocationArbitrator. Public for testing.
void OnLocationUpdate(const Geoposition& position);
// Gets a pointer to the singleton instance of the location relayer, which
// is in turn bound to the browser's global context objects. This must only be
- // called on the IO thread so that the GeolocationProviderImpl is always
+ // called on the UI thread so that the GeolocationProviderImpl is always
// instantiated on the same thread. Ownership is NOT returned.
static GeolocationProviderImpl* GetInstance();
@@ -48,7 +48,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
protected:
friend struct DefaultSingletonTraits<GeolocationProviderImpl>;
GeolocationProviderImpl();
- virtual ~GeolocationProviderImpl();
+ ~GeolocationProviderImpl() override;
// Useful for injecting mock geolocation arbitrator in tests.
virtual LocationArbitrator* CreateArbitrator();
@@ -75,8 +75,8 @@ class CONTENT_EXPORT GeolocationProviderImpl
void NotifyClients(const Geoposition& position);
// Thread
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void CleanUp() override;
base::CallbackList<void(const Geoposition&)> high_accuracy_callbacks_;
base::CallbackList<void(const Geoposition&)> low_accuracy_callbacks_;
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc b/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc
new file mode 100644
index 00000000000..f201f48e842
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright 2014 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/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
+#include "content/browser/geolocation/geolocation_provider_impl.h"
+#include "content/browser/geolocation/mock_location_arbitrator.h"
+#include "content/public/browser/access_token_store.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::MakeMatcher;
+using testing::Matcher;
+using testing::MatcherInterface;
+using testing::MatchResultListener;
+
+namespace content {
+
+class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
+ public:
+ LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
+ ~LocationProviderForTestArbitrator() override {}
+
+ // Only valid for use on the geolocation thread.
+ MockLocationArbitrator* mock_arbitrator() const {
+ return mock_arbitrator_;
+ }
+
+ protected:
+ // GeolocationProviderImpl implementation:
+ LocationArbitrator* CreateArbitrator() override;
+
+ private:
+ MockLocationArbitrator* mock_arbitrator_;
+};
+
+LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
+ DCHECK(mock_arbitrator_ == NULL);
+ mock_arbitrator_ = new MockLocationArbitrator;
+ return mock_arbitrator_;
+}
+
+class GeolocationObserver {
+ public:
+ virtual ~GeolocationObserver() {}
+ virtual void OnLocationUpdate(const Geoposition& position) = 0;
+};
+
+class MockGeolocationObserver : public GeolocationObserver {
+ public:
+ MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
+};
+
+class AsyncMockGeolocationObserver : public MockGeolocationObserver {
+ public:
+ void OnLocationUpdate(const Geoposition& position) override {
+ MockGeolocationObserver::OnLocationUpdate(position);
+ base::MessageLoop::current()->Quit();
+ }
+};
+
+class MockGeolocationCallbackWrapper {
+ public:
+ MOCK_METHOD1(Callback, void(const Geoposition& position));
+};
+
+class GeopositionEqMatcher
+ : public MatcherInterface<const Geoposition&> {
+ public:
+ explicit GeopositionEqMatcher(const Geoposition& expected)
+ : expected_(expected) {}
+
+ virtual bool MatchAndExplain(const Geoposition& actual,
+ MatchResultListener* listener) const override {
+ return actual.latitude == expected_.latitude &&
+ actual.longitude == expected_.longitude &&
+ actual.altitude == expected_.altitude &&
+ actual.accuracy == expected_.accuracy &&
+ actual.altitude_accuracy == expected_.altitude_accuracy &&
+ actual.heading == expected_.heading &&
+ actual.speed == expected_.speed &&
+ actual.timestamp == expected_.timestamp &&
+ actual.error_code == expected_.error_code &&
+ actual.error_message == expected_.error_message;
+ }
+
+ virtual void DescribeTo(::std::ostream* os) const override {
+ *os << "which matches the expected position";
+ }
+
+ virtual void DescribeNegationTo(::std::ostream* os) const override {
+ *os << "which does not match the expected position";
+ }
+
+ private:
+ Geoposition expected_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
+};
+
+Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
+ return MakeMatcher(new GeopositionEqMatcher(expected));
+}
+
+class GeolocationProviderTest : public testing::Test {
+ protected:
+ GeolocationProviderTest()
+ : message_loop_(),
+ ui_thread_(BrowserThread::UI, &message_loop_),
+ provider_(new LocationProviderForTestArbitrator) {
+ }
+
+ ~GeolocationProviderTest() override {}
+
+ LocationProviderForTestArbitrator* provider() { return provider_.get(); }
+
+ // Called on test thread.
+ bool ProvidersStarted();
+ void SendMockLocation(const Geoposition& position);
+
+ private:
+ // Called on provider thread.
+ void GetProvidersStarted(bool* started);
+
+ base::MessageLoop message_loop_;
+ TestBrowserThread ui_thread_;
+ scoped_ptr<LocationProviderForTestArbitrator> provider_;
+};
+
+
+bool GeolocationProviderTest::ProvidersStarted() {
+ DCHECK(provider_->IsRunning());
+ DCHECK(base::MessageLoop::current() == &message_loop_);
+ bool started;
+ provider_->message_loop_proxy()->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GeolocationProviderTest::GetProvidersStarted,
+ base::Unretained(this),
+ &started),
+ base::MessageLoop::QuitClosure());
+ message_loop_.Run();
+ return started;
+}
+
+void GeolocationProviderTest::GetProvidersStarted(bool* started) {
+ DCHECK(base::MessageLoop::current() == provider_->message_loop());
+ *started = provider_->mock_arbitrator()->providers_started();
+}
+
+void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
+ DCHECK(provider_->IsRunning());
+ DCHECK(base::MessageLoop::current() == &message_loop_);
+ provider_->message_loop()
+ ->PostTask(FROM_HERE,
+ base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
+ base::Unretained(provider_.get()),
+ position));
+}
+
+// Regression test for http://crbug.com/59377
+TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
+ EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing());
+ provider()->UserDidOptIntoLocationServices();
+ EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing());
+}
+
+void DummyFunction(const Geoposition& position) {
+}
+
+TEST_F(GeolocationProviderTest, StartStop) {
+ EXPECT_FALSE(provider()->IsRunning());
+ GeolocationProviderImpl::LocationUpdateCallback callback =
+ base::Bind(&DummyFunction);
+ scoped_ptr<content::GeolocationProvider::Subscription> subscription =
+ provider()->AddLocationUpdateCallback(callback, false);
+ EXPECT_TRUE(provider()->IsRunning());
+ EXPECT_TRUE(ProvidersStarted());
+
+ subscription.reset();
+
+ EXPECT_FALSE(ProvidersStarted());
+ EXPECT_TRUE(provider()->IsRunning());
+}
+
+TEST_F(GeolocationProviderTest, StalePositionNotSent) {
+ Geoposition first_position;
+ first_position.latitude = 12;
+ first_position.longitude = 34;
+ first_position.accuracy = 56;
+ first_position.timestamp = base::Time::Now();
+
+ AsyncMockGeolocationObserver first_observer;
+ GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind(
+ &MockGeolocationObserver::OnLocationUpdate,
+ base::Unretained(&first_observer));
+ EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
+ scoped_ptr<content::GeolocationProvider::Subscription> subscription =
+ provider()->AddLocationUpdateCallback(first_callback, false);
+ SendMockLocation(first_position);
+ base::MessageLoop::current()->Run();
+
+ subscription.reset();
+
+ Geoposition second_position;
+ second_position.latitude = 13;
+ second_position.longitude = 34;
+ second_position.accuracy = 56;
+ second_position.timestamp = base::Time::Now();
+
+ AsyncMockGeolocationObserver second_observer;
+
+ // After adding a second observer, check that no unexpected position update
+ // is sent.
+ EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
+ GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind(
+ &MockGeolocationObserver::OnLocationUpdate,
+ base::Unretained(&second_observer));
+ scoped_ptr<content::GeolocationProvider::Subscription> subscription2 =
+ provider()->AddLocationUpdateCallback(second_callback, false);
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // The second observer should receive the new position now.
+ EXPECT_CALL(second_observer,
+ OnLocationUpdate(GeopositionEq(second_position)));
+ SendMockLocation(second_position);
+ base::MessageLoop::current()->Run();
+
+ subscription2.reset();
+ EXPECT_FALSE(ProvidersStarted());
+}
+
+TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
+ Geoposition position;
+ position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
+ provider()->OverrideLocationForTesting(position);
+ // Adding an observer when the location is overridden should synchronously
+ // update the observer with our overridden position.
+ MockGeolocationObserver mock_observer;
+ EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
+ GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind(
+ &MockGeolocationObserver::OnLocationUpdate,
+ base::Unretained(&mock_observer));
+ scoped_ptr<content::GeolocationProvider::Subscription> subscription =
+ provider()->AddLocationUpdateCallback(callback, false);
+ subscription.reset();
+ // Wait for the providers to be stopped now that all clients are gone.
+ EXPECT_FALSE(ProvidersStarted());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_provider_unittest.cc b/chromium/content/browser/geolocation/geolocation_provider_unittest.cc
deleted file mode 100644
index 95fa1b69145..00000000000
--- a/chromium/content/browser/geolocation/geolocation_provider_unittest.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright (c) 2012 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/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string16.h"
-#include "base/time/time.h"
-#include "content/browser/geolocation/geolocation_provider_impl.h"
-#include "content/browser/geolocation/mock_location_arbitrator.h"
-#include "content/public/browser/access_token_store.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::MakeMatcher;
-using testing::Matcher;
-using testing::MatcherInterface;
-using testing::MatchResultListener;
-
-namespace content {
-
-class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
- public:
- LocationProviderForTestArbitrator() : mock_arbitrator_(NULL) {}
- virtual ~LocationProviderForTestArbitrator() {}
-
- // Only valid for use on the geolocation thread.
- MockLocationArbitrator* mock_arbitrator() const {
- return mock_arbitrator_;
- }
-
- protected:
- // GeolocationProviderImpl implementation:
- virtual LocationArbitrator* CreateArbitrator() OVERRIDE;
-
- private:
- MockLocationArbitrator* mock_arbitrator_;
-};
-
-LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
- DCHECK(mock_arbitrator_ == NULL);
- mock_arbitrator_ = new MockLocationArbitrator;
- return mock_arbitrator_;
-}
-
-class GeolocationObserver {
- public:
- virtual ~GeolocationObserver() {}
- virtual void OnLocationUpdate(const Geoposition& position) = 0;
-};
-
-class MockGeolocationObserver : public GeolocationObserver {
- public:
- MOCK_METHOD1(OnLocationUpdate, void(const Geoposition& position));
-};
-
-class AsyncMockGeolocationObserver : public MockGeolocationObserver {
- public:
- virtual void OnLocationUpdate(const Geoposition& position) OVERRIDE {
- MockGeolocationObserver::OnLocationUpdate(position);
- base::MessageLoop::current()->Quit();
- }
-};
-
-class MockGeolocationCallbackWrapper {
- public:
- MOCK_METHOD1(Callback, void(const Geoposition& position));
-};
-
-class GeopositionEqMatcher
- : public MatcherInterface<const Geoposition&> {
- public:
- explicit GeopositionEqMatcher(const Geoposition& expected)
- : expected_(expected) {}
-
- virtual bool MatchAndExplain(const Geoposition& actual,
- MatchResultListener* listener) const OVERRIDE {
- return actual.latitude == expected_.latitude &&
- actual.longitude == expected_.longitude &&
- actual.altitude == expected_.altitude &&
- actual.accuracy == expected_.accuracy &&
- actual.altitude_accuracy == expected_.altitude_accuracy &&
- actual.heading == expected_.heading &&
- actual.speed == expected_.speed &&
- actual.timestamp == expected_.timestamp &&
- actual.error_code == expected_.error_code &&
- actual.error_message == expected_.error_message;
- }
-
- virtual void DescribeTo(::std::ostream* os) const OVERRIDE {
- *os << "which matches the expected position";
- }
-
- virtual void DescribeNegationTo(::std::ostream* os) const OVERRIDE {
- *os << "which does not match the expected position";
- }
-
- private:
- Geoposition expected_;
-
- DISALLOW_COPY_AND_ASSIGN(GeopositionEqMatcher);
-};
-
-Matcher<const Geoposition&> GeopositionEq(const Geoposition& expected) {
- return MakeMatcher(new GeopositionEqMatcher(expected));
-}
-
-class GeolocationProviderTest : public testing::Test {
- protected:
- GeolocationProviderTest()
- : message_loop_(),
- ui_thread_(BrowserThread::UI, &message_loop_),
- provider_(new LocationProviderForTestArbitrator) {
- }
-
- virtual ~GeolocationProviderTest() {}
-
- LocationProviderForTestArbitrator* provider() { return provider_.get(); }
-
- // Called on test thread.
- bool ProvidersStarted();
- void SendMockLocation(const Geoposition& position);
-
- private:
- // Called on provider thread.
- void GetProvidersStarted(bool* started);
-
- base::MessageLoop message_loop_;
- TestBrowserThread ui_thread_;
- scoped_ptr<LocationProviderForTestArbitrator> provider_;
-};
-
-
-bool GeolocationProviderTest::ProvidersStarted() {
- DCHECK(provider_->IsRunning());
- DCHECK(base::MessageLoop::current() == &message_loop_);
- bool started;
- provider_->message_loop_proxy()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&GeolocationProviderTest::GetProvidersStarted,
- base::Unretained(this),
- &started),
- base::MessageLoop::QuitClosure());
- message_loop_.Run();
- return started;
-}
-
-void GeolocationProviderTest::GetProvidersStarted(bool* started) {
- DCHECK(base::MessageLoop::current() == provider_->message_loop());
- *started = provider_->mock_arbitrator()->providers_started();
-}
-
-void GeolocationProviderTest::SendMockLocation(const Geoposition& position) {
- DCHECK(provider_->IsRunning());
- DCHECK(base::MessageLoop::current() == &message_loop_);
- provider_->message_loop()
- ->PostTask(FROM_HERE,
- base::Bind(&GeolocationProviderImpl::OnLocationUpdate,
- base::Unretained(provider_.get()),
- position));
-}
-
-// Regression test for http://crbug.com/59377
-TEST_F(GeolocationProviderTest, OnPermissionGrantedWithoutObservers) {
- EXPECT_FALSE(provider()->user_did_opt_into_location_services_for_testing());
- provider()->UserDidOptIntoLocationServices();
- EXPECT_TRUE(provider()->user_did_opt_into_location_services_for_testing());
-}
-
-void DummyFunction(const Geoposition& position) {
-}
-
-TEST_F(GeolocationProviderTest, StartStop) {
- EXPECT_FALSE(provider()->IsRunning());
- GeolocationProviderImpl::LocationUpdateCallback callback =
- base::Bind(&DummyFunction);
- scoped_ptr<content::GeolocationProvider::Subscription> subscription =
- provider()->AddLocationUpdateCallback(callback, false);
- EXPECT_TRUE(provider()->IsRunning());
- EXPECT_TRUE(ProvidersStarted());
-
- subscription.reset();
-
- EXPECT_FALSE(ProvidersStarted());
- EXPECT_TRUE(provider()->IsRunning());
-}
-
-TEST_F(GeolocationProviderTest, StalePositionNotSent) {
- Geoposition first_position;
- first_position.latitude = 12;
- first_position.longitude = 34;
- first_position.accuracy = 56;
- first_position.timestamp = base::Time::Now();
-
- AsyncMockGeolocationObserver first_observer;
- GeolocationProviderImpl::LocationUpdateCallback first_callback = base::Bind(
- &MockGeolocationObserver::OnLocationUpdate,
- base::Unretained(&first_observer));
- EXPECT_CALL(first_observer, OnLocationUpdate(GeopositionEq(first_position)));
- scoped_ptr<content::GeolocationProvider::Subscription> subscription =
- provider()->AddLocationUpdateCallback(first_callback, false);
- SendMockLocation(first_position);
- base::MessageLoop::current()->Run();
-
- subscription.reset();
-
- Geoposition second_position;
- second_position.latitude = 13;
- second_position.longitude = 34;
- second_position.accuracy = 56;
- second_position.timestamp = base::Time::Now();
-
- AsyncMockGeolocationObserver second_observer;
-
- // After adding a second observer, check that no unexpected position update
- // is sent.
- EXPECT_CALL(second_observer, OnLocationUpdate(testing::_)).Times(0);
- GeolocationProviderImpl::LocationUpdateCallback second_callback = base::Bind(
- &MockGeolocationObserver::OnLocationUpdate,
- base::Unretained(&second_observer));
- scoped_ptr<content::GeolocationProvider::Subscription> subscription2 =
- provider()->AddLocationUpdateCallback(second_callback, false);
- base::MessageLoop::current()->RunUntilIdle();
-
- // The second observer should receive the new position now.
- EXPECT_CALL(second_observer,
- OnLocationUpdate(GeopositionEq(second_position)));
- SendMockLocation(second_position);
- base::MessageLoop::current()->Run();
-
- subscription2.reset();
- EXPECT_FALSE(ProvidersStarted());
-}
-
-TEST_F(GeolocationProviderTest, OverrideLocationForTesting) {
- Geoposition position;
- position.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
- provider()->OverrideLocationForTesting(position);
- // Adding an observer when the location is overridden should synchronously
- // update the observer with our overridden position.
- MockGeolocationObserver mock_observer;
- EXPECT_CALL(mock_observer, OnLocationUpdate(GeopositionEq(position)));
- GeolocationProviderImpl::LocationUpdateCallback callback = base::Bind(
- &MockGeolocationObserver::OnLocationUpdate,
- base::Unretained(&mock_observer));
- scoped_ptr<content::GeolocationProvider::Subscription> subscription =
- provider()->AddLocationUpdateCallback(callback, false);
- subscription.reset();
- // Wait for the providers to be stopped now that all clients are gone.
- EXPECT_FALSE(ProvidersStarted());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_service_context.cc b/chromium/content/browser/geolocation/geolocation_service_context.cc
new file mode 100644
index 00000000000..fc6b4aa07cd
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_context.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 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 "content/browser/geolocation/geolocation_service_context.h"
+
+namespace content {
+
+GeolocationServiceContext::GeolocationServiceContext() : paused_(false) {
+}
+
+GeolocationServiceContext::~GeolocationServiceContext() {
+}
+
+void GeolocationServiceContext::CreateService(
+ const base::Closure& update_callback,
+ mojo::InterfaceRequest<GeolocationService> request) {
+ GeolocationServiceImpl* service =
+ new GeolocationServiceImpl(this, update_callback);
+ services_.push_back(service);
+ mojo::WeakBindToRequest(service, &request);
+ if (geoposition_override_)
+ service->SetOverride(*geoposition_override_.get());
+ else
+ service->StartListeningForUpdates();
+}
+
+void GeolocationServiceContext::ServiceHadConnectionError(
+ GeolocationServiceImpl* service) {
+ auto it = std::find(services_.begin(), services_.end(), service);
+ DCHECK(it != services_.end());
+ services_.erase(it);
+}
+
+void GeolocationServiceContext::PauseUpdates() {
+ paused_ = true;
+ for (auto* service : services_) {
+ service->PauseUpdates();
+ }
+}
+
+void GeolocationServiceContext::ResumeUpdates() {
+ paused_ = false;
+ for (auto* service : services_) {
+ service->ResumeUpdates();
+ }
+}
+
+void GeolocationServiceContext::SetOverride(
+ scoped_ptr<Geoposition> geoposition) {
+ geoposition_override_.swap(geoposition);
+ for (auto* service : services_) {
+ service->SetOverride(*geoposition_override_.get());
+ }
+}
+
+void GeolocationServiceContext::ClearOverride() {
+ for (auto* service : services_) {
+ service->ClearOverride();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_service_context.h b/chromium/content/browser/geolocation/geolocation_service_context.h
new file mode 100644
index 00000000000..453c8b0dce2
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_context.h
@@ -0,0 +1,58 @@
+// Copyright 2014 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 CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_CONTEXT_H_
+#define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_CONTEXT_H_
+
+#include "base/memory/scoped_vector.h"
+#include "content/browser/geolocation/geolocation_service_impl.h"
+
+namespace content {
+
+// Provides information to a set of GeolocationServiceImpl instances that are
+// associated with a given context. Notably, allows pausing and resuming
+// geolocation on these instances.
+class GeolocationServiceContext {
+ public:
+ GeolocationServiceContext();
+ virtual ~GeolocationServiceContext();
+
+ // Creates a GeolocationServiceImpl that is weakly bound to |request|.
+ // |update_callback| will be called when services send
+ // location updates to their clients.
+ void CreateService(const base::Closure& update_callback,
+ mojo::InterfaceRequest<GeolocationService> request);
+
+ // Called when a service has a connection error. After this call, it is no
+ // longer safe to access |service|.
+ void ServiceHadConnectionError(GeolocationServiceImpl* service);
+
+ // Pauses and resumes geolocation. Resuming when nothing is paused is a
+ // no-op. If a service is added while geolocation is paused, that service
+ // will not get geolocation updates until geolocation is resumed.
+ void PauseUpdates();
+ void ResumeUpdates();
+
+ // Returns whether geolocation updates are currently paused.
+ bool paused() { return paused_; }
+
+ // Enables geolocation override. This method can be used to trigger possible
+ // location-specific behavior in a particular context.
+ void SetOverride(scoped_ptr<Geoposition> geoposition);
+
+ // Disables geolocation override.
+ void ClearOverride();
+
+ private:
+ ScopedVector<GeolocationServiceImpl> services_;
+ bool paused_;
+
+ scoped_ptr<Geoposition> geoposition_override_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_CONTEXT_H_
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.cc b/chromium/content/browser/geolocation/geolocation_service_impl.cc
new file mode 100644
index 00000000000..4c855f27046
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.cc
@@ -0,0 +1,155 @@
+// Copyright 2014 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 "content/browser/geolocation/geolocation_service_impl.h"
+
+#include "base/bind.h"
+#include "base/metrics/histogram.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
+#include "content/public/common/mojo_geoposition.mojom.h"
+
+namespace content {
+
+namespace {
+
+// Geoposition error codes for reporting in UMA.
+enum GeopositionErrorCode {
+ // NOTE: Do not renumber these as that would confuse interpretation of
+ // previously logged data. When making changes, also update the enum list
+ // in tools/metrics/histograms/histograms.xml to keep it in sync.
+
+ // There was no error.
+ GEOPOSITION_ERROR_CODE_NONE = 0,
+
+ // User denied use of geolocation.
+ GEOPOSITION_ERROR_CODE_PERMISSION_DENIED = 1,
+
+ // Geoposition could not be determined.
+ GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE = 2,
+
+ // Timeout.
+ GEOPOSITION_ERROR_CODE_TIMEOUT = 3,
+
+ // NOTE: Add entries only immediately above this line.
+ GEOPOSITION_ERROR_CODE_COUNT = 4
+};
+
+void RecordGeopositionErrorCode(Geoposition::ErrorCode error_code) {
+ GeopositionErrorCode code = GEOPOSITION_ERROR_CODE_NONE;
+ switch (error_code) {
+ case Geoposition::ERROR_CODE_NONE:
+ code = GEOPOSITION_ERROR_CODE_NONE;
+ break;
+ case Geoposition::ERROR_CODE_PERMISSION_DENIED:
+ code = GEOPOSITION_ERROR_CODE_PERMISSION_DENIED;
+ break;
+ case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
+ code = GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE;
+ break;
+ case Geoposition::ERROR_CODE_TIMEOUT:
+ code = GEOPOSITION_ERROR_CODE_TIMEOUT;
+ break;
+ }
+ UMA_HISTOGRAM_ENUMERATION("Geolocation.LocationUpdate.ErrorCode",
+ code,
+ GEOPOSITION_ERROR_CODE_COUNT);
+}
+
+} // namespace
+
+GeolocationServiceImpl::GeolocationServiceImpl(
+ GeolocationServiceContext* context,
+ const base::Closure& update_callback)
+ : context_(context),
+ update_callback_(update_callback),
+ high_accuracy_(false) {
+ DCHECK(context_);
+}
+
+GeolocationServiceImpl::~GeolocationServiceImpl() {
+}
+
+void GeolocationServiceImpl::PauseUpdates() {
+ geolocation_subscription_.reset();
+}
+
+void GeolocationServiceImpl::ResumeUpdates() {
+ if (position_override_.Validate()) {
+ OnLocationUpdate(position_override_);
+ return;
+ }
+
+ StartListeningForUpdates();
+}
+
+void GeolocationServiceImpl::StartListeningForUpdates() {
+ geolocation_subscription_ =
+ GeolocationProvider::GetInstance()->AddLocationUpdateCallback(
+ base::Bind(&GeolocationServiceImpl::OnLocationUpdate,
+ base::Unretained(this)),
+ high_accuracy_);
+}
+
+void GeolocationServiceImpl::SetHighAccuracy(bool high_accuracy) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Geolocation.GeolocationDispatcherHostImpl.EnableHighAccuracy",
+ high_accuracy);
+ high_accuracy_ = high_accuracy;
+
+ if (position_override_.Validate()) {
+ OnLocationUpdate(position_override_);
+ return;
+ }
+
+ StartListeningForUpdates();
+}
+
+void GeolocationServiceImpl::SetOverride(const Geoposition& position) {
+ position_override_ = position;
+ if (!position_override_.Validate()) {
+ ResumeUpdates();
+ }
+
+ geolocation_subscription_.reset();
+
+ OnLocationUpdate(position_override_);
+}
+
+void GeolocationServiceImpl::ClearOverride() {
+ position_override_ = Geoposition();
+ StartListeningForUpdates();
+}
+
+void GeolocationServiceImpl::OnConnectionError() {
+ context_->ServiceHadConnectionError(this);
+
+ // The above call deleted this instance, so the only safe thing to do is
+ // return.
+}
+
+void GeolocationServiceImpl::OnLocationUpdate(const Geoposition& position) {
+ RecordGeopositionErrorCode(position.error_code);
+ DCHECK(context_);
+
+ if (context_->paused())
+ return;
+
+ MojoGeopositionPtr geoposition(MojoGeoposition::New());
+ geoposition->valid = position.Validate();
+ geoposition->latitude = position.latitude;
+ geoposition->longitude = position.longitude;
+ geoposition->altitude = position.altitude;
+ geoposition->accuracy = position.accuracy;
+ geoposition->altitude_accuracy = position.altitude_accuracy;
+ geoposition->heading = position.heading;
+ geoposition->speed = position.speed;
+ geoposition->timestamp = position.timestamp.ToDoubleT();
+ geoposition->error_code = MojoGeoposition::ErrorCode(position.error_code);
+ geoposition->error_message = position.error_message;
+
+ update_callback_.Run();
+ client()->OnLocationUpdate(geoposition.Pass());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.h b/chromium/content/browser/geolocation/geolocation_service_impl.h
new file mode 100644
index 00000000000..172e4e196c8
--- /dev/null
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.h
@@ -0,0 +1,64 @@
+// Copyright 2014 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/memory/scoped_ptr.h"
+#include "content/browser/geolocation/geolocation_provider_impl.h"
+#include "content/common/geolocation_service.mojom.h"
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
+
+namespace content {
+
+class GeolocationProvider;
+class GeolocationServiceContext;
+
+// Implements the GeolocationService Mojo interface.
+class GeolocationServiceImpl : public mojo::InterfaceImpl<GeolocationService> {
+ public:
+ // |context| must outlive this object. |update_callback| will be
+ // called when location updates are sent.
+ GeolocationServiceImpl(GeolocationServiceContext* context,
+ const base::Closure& update_callback);
+ ~GeolocationServiceImpl() override;
+
+ // Starts listening for updates.
+ void StartListeningForUpdates();
+
+ // Pauses and resumes sending updates to the client of this instance.
+ void PauseUpdates();
+ void ResumeUpdates();
+
+ // Enables and disables geolocation override.
+ void SetOverride(const Geoposition& position);
+ void ClearOverride();
+
+ private:
+ // GeolocationService:
+ void SetHighAccuracy(bool high_accuracy) override;
+
+ // mojo::InterfaceImpl:
+ void OnConnectionError() override;
+
+ void OnLocationUpdate(const Geoposition& position);
+
+ // Owns this object.
+ GeolocationServiceContext* context_;
+ scoped_ptr<GeolocationProvider::Subscription> geolocation_subscription_;
+ base::Closure update_callback_;
+
+ // Valid iff SetOverride() has been called and ClearOverride() has not
+ // subsequently been called.
+ Geoposition position_override_;
+
+ // Whether this instance is currently observing location updates with high
+ // accuracy.
+ bool high_accuracy_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.cc b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
index b8ed8c49bf5..ef20a0ce468 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
@@ -28,9 +28,9 @@ const int64 LocationArbitratorImpl::kFixStaleTimeoutMilliseconds =
LocationArbitratorImpl::LocationArbitratorImpl(
const LocationUpdateCallback& callback)
- : callback_(callback),
- provider_callback_(
- base::Bind(&LocationArbitratorImpl::LocationUpdateAvailable,
+ : arbitrator_update_callback_(callback),
+ provider_update_callback_(
+ base::Bind(&LocationArbitratorImpl::OnLocationUpdate,
base::Unretained(this))),
position_provider_(NULL),
is_permission_granted_(false),
@@ -116,15 +116,14 @@ void LocationArbitratorImpl::RegisterProvider(
LocationProvider* provider) {
if (!provider)
return;
- provider->SetUpdateCallback(provider_callback_);
+ provider->SetUpdateCallback(provider_update_callback_);
if (is_permission_granted_)
provider->OnPermissionGranted();
providers_.push_back(provider);
}
-void LocationArbitratorImpl::LocationUpdateAvailable(
- const LocationProvider* provider,
- const Geoposition& new_position) {
+void LocationArbitratorImpl::OnLocationUpdate(const LocationProvider* provider,
+ const Geoposition& new_position) {
DCHECK(new_position.Validate() ||
new_position.error_code != Geoposition::ERROR_CODE_NONE);
if (!IsNewPositionBetter(position_, new_position,
@@ -132,7 +131,7 @@ void LocationArbitratorImpl::LocationUpdateAvailable(
return;
position_provider_ = provider;
position_ = new_position;
- callback_.Run(position_);
+ arbitrator_update_callback_.Run(position_);
}
AccessTokenStore* LocationArbitratorImpl::NewAccessTokenStore() {
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.h b/chromium/content/browser/geolocation/location_arbitrator_impl.h
index da20e7b1889..3ef7d5dfc6e 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.h
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.h
@@ -37,15 +37,15 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
typedef base::Callback<void(const Geoposition&)> LocationUpdateCallback;
explicit LocationArbitratorImpl(const LocationUpdateCallback& callback);
- virtual ~LocationArbitratorImpl();
+ ~LocationArbitratorImpl() override;
static GURL DefaultNetworkProviderURL();
// LocationArbitrator
- virtual void StartProviders(bool use_high_accuracy) OVERRIDE;
- virtual void StopProviders() OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
- virtual bool HasPermissionBeenGranted() const OVERRIDE;
+ void StartProviders(bool use_high_accuracy) override;
+ void StopProviders() override;
+ void OnPermissionGranted() override;
+ bool HasPermissionBeenGranted() const override;
protected:
AccessTokenStore* GetAccessTokenStore();
@@ -70,9 +70,9 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
net::URLRequestContextGetter* context_getter);
void DoStartProviders();
- // The providers call this function when a new position is available.
- void LocationUpdateAvailable(const LocationProvider* provider,
- const Geoposition& new_position);
+ // Gets called when a provider has a new position.
+ void OnLocationUpdate(const LocationProvider* provider,
+ const Geoposition& new_position);
// Returns true if |new_position| is an improvement over |old_position|.
// Set |from_same_provider| to true if both the positions came from the same
@@ -82,8 +82,8 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
bool from_same_provider) const;
scoped_refptr<AccessTokenStore> access_token_store_;
- LocationUpdateCallback callback_;
- LocationProvider::LocationProviderUpdateCallback provider_callback_;
+ LocationUpdateCallback arbitrator_update_callback_;
+ LocationProvider::LocationProviderUpdateCallback provider_update_callback_;
ScopedVector<LocationProvider> providers_;
bool use_high_accuracy_;
// The provider which supplied the current |position_|
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
index 81df7a4326f..bd5eb6e9d07 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
@@ -73,23 +73,21 @@ class TestingLocationArbitrator : public LocationArbitratorImpl {
access_token_store_(access_token_store) {
}
- virtual base::Time GetTimeNow() const OVERRIDE {
- return GetTimeNowForTest();
- }
+ base::Time GetTimeNow() const override { return GetTimeNowForTest(); }
- virtual AccessTokenStore* NewAccessTokenStore() OVERRIDE {
+ AccessTokenStore* NewAccessTokenStore() override {
return access_token_store_.get();
}
- virtual LocationProvider* NewNetworkLocationProvider(
+ LocationProvider* NewNetworkLocationProvider(
AccessTokenStore* access_token_store,
net::URLRequestContextGetter* context,
const GURL& url,
- const base::string16& access_token) OVERRIDE {
+ const base::string16& access_token) override {
return new MockLocationProvider(&cell_);
}
- virtual LocationProvider* NewSystemLocationProvider() OVERRIDE {
+ LocationProvider* NewSystemLocationProvider() override {
return new MockLocationProvider(&gps_);
}
@@ -107,7 +105,7 @@ class TestingLocationArbitrator : public LocationArbitratorImpl {
class GeolocationLocationArbitratorTest : public testing::Test {
protected:
// testing::Test
- virtual void SetUp() {
+ void SetUp() override {
access_token_store_ = new NiceMock<FakeAccessTokenStore>;
observer_.reset(new MockLocationObserver);
LocationArbitratorImpl::LocationUpdateCallback callback =
@@ -118,8 +116,7 @@ class GeolocationLocationArbitratorTest : public testing::Test {
}
// testing::Test
- virtual void TearDown() {
- }
+ void TearDown() override {}
void CheckLastPositionInfo(double latitude,
double longitude,
diff --git a/chromium/content/browser/geolocation/location_provider_android.h b/chromium/content/browser/geolocation/location_provider_android.h
index b4f5886ceba..e24f67cb980 100644
--- a/chromium/content/browser/geolocation/location_provider_android.h
+++ b/chromium/content/browser/geolocation/location_provider_android.h
@@ -23,11 +23,11 @@ class LocationProviderAndroid : public LocationProviderBase {
void NotifyNewGeoposition(const Geoposition& position);
// LocationProvider.
- virtual bool StartProvider(bool high_accuracy) OVERRIDE;
- virtual void StopProvider() OVERRIDE;
- virtual void GetPosition(Geoposition* position) OVERRIDE;
- virtual void RequestRefresh() OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
+ virtual bool StartProvider(bool high_accuracy) override;
+ virtual void StopProvider() override;
+ virtual void GetPosition(Geoposition* position) override;
+ virtual void RequestRefresh() override;
+ virtual void OnPermissionGranted() override;
private:
Geoposition last_position_;
diff --git a/chromium/content/browser/geolocation/location_provider_base.h b/chromium/content/browser/geolocation/location_provider_base.h
index 36d900bd747..1e3f4430da0 100644
--- a/chromium/content/browser/geolocation/location_provider_base.h
+++ b/chromium/content/browser/geolocation/location_provider_base.h
@@ -14,15 +14,15 @@ class CONTENT_EXPORT LocationProviderBase
: NON_EXPORTED_BASE(public LocationProvider) {
public:
LocationProviderBase();
- virtual ~LocationProviderBase();
+ ~LocationProviderBase() override;
protected:
void NotifyCallback(const Geoposition& position);
// Overridden from LocationProvider:
- virtual void SetUpdateCallback(
- const LocationProviderUpdateCallback& callback) OVERRIDE;
- virtual void RequestRefresh() OVERRIDE;
+ void SetUpdateCallback(
+ const LocationProviderUpdateCallback& callback) override;
+ void RequestRefresh() override;
private:
LocationProviderUpdateCallback callback_;
diff --git a/chromium/content/browser/geolocation/mock_location_arbitrator.h b/chromium/content/browser/geolocation/mock_location_arbitrator.h
index f096b12f720..620bcc88662 100644
--- a/chromium/content/browser/geolocation/mock_location_arbitrator.h
+++ b/chromium/content/browser/geolocation/mock_location_arbitrator.h
@@ -20,11 +20,10 @@ class MockLocationArbitrator : public LocationArbitrator {
bool providers_started() const { return providers_started_; }
// LocationArbitrator:
- virtual void StartProviders(bool use_high_accuracy)
- OVERRIDE;
- virtual void StopProviders() OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
- virtual bool HasPermissionBeenGranted() const OVERRIDE;
+ void StartProviders(bool use_high_accuracy) override;
+ void StopProviders() override;
+ void OnPermissionGranted() override;
+ bool HasPermissionBeenGranted() const override;
private:
bool permission_granted_;
diff --git a/chromium/content/browser/geolocation/mock_location_provider.cc b/chromium/content/browser/geolocation/mock_location_provider.cc
index 22980b1de73..2953ba1be17 100644
--- a/chromium/content/browser/geolocation/mock_location_provider.cc
+++ b/chromium/content/browser/geolocation/mock_location_provider.cc
@@ -86,7 +86,7 @@ class AutoMockLocationProvider : public MockLocationProvider {
position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE;
}
}
- virtual bool StartProvider(bool high_accuracy) OVERRIDE {
+ bool StartProvider(bool high_accuracy) override {
MockLocationProvider::StartProvider(high_accuracy);
if (!requires_permission_to_start_) {
UpdateListenersIfNeeded();
@@ -94,7 +94,7 @@ class AutoMockLocationProvider : public MockLocationProvider {
return true;
}
- virtual void OnPermissionGranted() OVERRIDE {
+ void OnPermissionGranted() override {
MockLocationProvider::OnPermissionGranted();
if (requires_permission_to_start_) {
UpdateListenersIfNeeded();
diff --git a/chromium/content/browser/geolocation/mock_location_provider.h b/chromium/content/browser/geolocation/mock_location_provider.h
index dd7471fb237..882a447330d 100644
--- a/chromium/content/browser/geolocation/mock_location_provider.h
+++ b/chromium/content/browser/geolocation/mock_location_provider.h
@@ -20,16 +20,16 @@ class MockLocationProvider : public LocationProviderBase {
// Will update |*self_ref| to point to |this| on construction, and to NULL
// on destruction.
explicit MockLocationProvider(MockLocationProvider** self_ref);
- virtual ~MockLocationProvider();
+ ~MockLocationProvider() override;
// Updates listeners with the new position.
void HandlePositionChanged(const Geoposition& position);
// LocationProvider implementation.
- virtual bool StartProvider(bool high_accuracy) OVERRIDE;
- virtual void StopProvider() OVERRIDE;
- virtual void GetPosition(Geoposition* position) OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
+ bool StartProvider(bool high_accuracy) override;
+ void StopProvider() override;
+ void GetPosition(Geoposition* position) override;
+ void OnPermissionGranted() override;
Geoposition position_;
enum State { STOPPED, LOW_ACCURACY, HIGH_ACCURACY } state_;
diff --git a/chromium/content/browser/geolocation/network_location_provider.cc b/chromium/content/browser/geolocation/network_location_provider.cc
index 2a9d7c8a3b8..13a6504d006 100644
--- a/chromium/content/browser/geolocation/network_location_provider.cc
+++ b/chromium/content/browser/geolocation/network_location_provider.cc
@@ -108,9 +108,9 @@ NetworkLocationProvider::NetworkLocationProvider(
const GURL& url,
const base::string16& access_token)
: access_token_store_(access_token_store),
- wifi_data_provider_(NULL),
+ wifi_data_provider_manager_(NULL),
wifi_data_update_callback_(
- base::Bind(&NetworkLocationProvider::WifiDataUpdateAvailable,
+ base::Bind(&NetworkLocationProvider::OnWifiDataUpdate,
base::Unretained(this))),
is_wifi_data_complete_(false),
access_token_(access_token),
@@ -120,10 +120,11 @@ NetworkLocationProvider::NetworkLocationProvider(
// Create the position cache.
position_cache_.reset(new PositionCache());
- NetworkLocationRequest::LocationResponseCallback callback =
- base::Bind(&NetworkLocationProvider::LocationResponseAvailable,
- base::Unretained(this));
- request_.reset(new NetworkLocationRequest(url_context_getter, url, callback));
+ request_.reset(new NetworkLocationRequest(
+ url_context_getter,
+ url,
+ base::Bind(&NetworkLocationProvider::OnLocationResponse,
+ base::Unretained(this))));
}
NetworkLocationProvider::~NetworkLocationProvider() {
@@ -153,14 +154,13 @@ void NetworkLocationProvider::OnPermissionGranted() {
}
}
-void NetworkLocationProvider::WifiDataUpdateAvailable(
- WifiDataProvider* provider) {
- DCHECK(provider == wifi_data_provider_);
- is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
+void NetworkLocationProvider::OnWifiDataUpdate() {
+ DCHECK(wifi_data_provider_manager_);
+ is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_);
OnWifiDataUpdated();
}
-void NetworkLocationProvider::LocationResponseAvailable(
+void NetworkLocationProvider::OnLocationResponse(
const Geoposition& position,
bool server_error,
const base::string16& access_token,
@@ -186,7 +186,7 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) {
DCHECK(CalledOnValidThread());
if (IsStarted())
return true;
- DCHECK(wifi_data_provider_ == NULL);
+ DCHECK(wifi_data_provider_manager_ == NULL);
if (!request_->url().is_valid()) {
LOG(WARNING) << "StartProvider() : Failed, Bad URL: "
<< request_->url().possibly_invalid_spec();
@@ -196,7 +196,8 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) {
// Registers a callback with the data provider. The first call to Register
// will create a singleton data provider and it will be deleted when the last
// callback is removed with Unregister.
- wifi_data_provider_ = WifiDataProvider::Register(&wifi_data_update_callback_);
+ wifi_data_provider_manager_ =
+ WifiDataProviderManager::Register(&wifi_data_update_callback_);
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@@ -204,7 +205,7 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) {
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromSeconds(kDataCompleteWaitSeconds));
// Get the wifi data.
- is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
+ is_wifi_data_complete_ = wifi_data_provider_manager_->GetData(&wifi_data_);
if (is_wifi_data_complete_)
OnWifiDataUpdated();
return true;
@@ -221,9 +222,9 @@ void NetworkLocationProvider::OnWifiDataUpdated() {
void NetworkLocationProvider::StopProvider() {
DCHECK(CalledOnValidThread());
if (IsStarted()) {
- wifi_data_provider_->Unregister(&wifi_data_update_callback_);
+ wifi_data_provider_manager_->Unregister(&wifi_data_update_callback_);
}
- wifi_data_provider_ = NULL;
+ wifi_data_provider_manager_ = NULL;
weak_factory_.InvalidateWeakPtrs();
}
@@ -269,7 +270,7 @@ void NetworkLocationProvider::RequestPosition() {
}
bool NetworkLocationProvider::IsStarted() const {
- return wifi_data_provider_ != NULL;
+ return wifi_data_provider_manager_ != NULL;
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/network_location_provider.h b/chromium/content/browser/geolocation/network_location_provider.h
index 710fd3f4fa6..e3588c64272 100644
--- a/chromium/content/browser/geolocation/network_location_provider.h
+++ b/chromium/content/browser/geolocation/network_location_provider.h
@@ -17,7 +17,7 @@
#include "base/threading/thread.h"
#include "content/browser/geolocation/location_provider_base.h"
#include "content/browser/geolocation/network_location_request.h"
-#include "content/browser/geolocation/wifi_data_provider.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
#include "content/common/content_export.h"
#include "content/public/common/geoposition.h"
@@ -69,38 +69,38 @@ class NetworkLocationProvider
net::URLRequestContextGetter* context,
const GURL& url,
const base::string16& access_token);
- virtual ~NetworkLocationProvider();
+ ~NetworkLocationProvider() override;
// LocationProvider implementation
- virtual bool StartProvider(bool high_accuracy) OVERRIDE;
- virtual void StopProvider() OVERRIDE;
- virtual void GetPosition(Geoposition *position) OVERRIDE;
- virtual void RequestRefresh() OVERRIDE;
- virtual void OnPermissionGranted() OVERRIDE;
+ bool StartProvider(bool high_accuracy) override;
+ void StopProvider() override;
+ void GetPosition(Geoposition* position) override;
+ void RequestRefresh() override;
+ void OnPermissionGranted() override;
private:
// Satisfies a position request from cache or network.
void RequestPosition();
- // Called from a callback when new wifi data is available.
- void WifiDataUpdateAvailable(WifiDataProvider* provider);
+ // Gets called when new wifi data is available.
+ void OnWifiDataUpdate();
- // Internal helper used by WifiDataUpdateAvailable.
+ // Internal helper used by OnWifiDataUpdate.
void OnWifiDataUpdated();
bool IsStarted() const;
- void LocationResponseAvailable(const Geoposition& position,
- bool server_error,
- const base::string16& access_token,
- const WifiData& wifi_data);
+ void OnLocationResponse(const Geoposition& position,
+ bool server_error,
+ const base::string16& access_token,
+ const WifiData& wifi_data);
scoped_refptr<AccessTokenStore> access_token_store_;
// The wifi data provider, acquired via global factories.
- WifiDataProvider* wifi_data_provider_;
+ WifiDataProviderManager* wifi_data_provider_manager_;
- WifiDataProvider::WifiDataUpdateCallback wifi_data_update_callback_;
+ WifiDataProviderManager::WifiDataUpdateCallback wifi_data_update_callback_;
// The wifi data and a flag to indicate if the data set is complete.
WifiData wifi_data_;
diff --git a/chromium/content/browser/geolocation/network_location_provider_unittest.cc b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
index c574b7a7b96..b8ef6cabb52 100644
--- a/chromium/content/browser/geolocation/network_location_provider_unittest.cc
+++ b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
@@ -13,6 +13,7 @@
#include "content/browser/geolocation/fake_access_token_store.h"
#include "content/browser/geolocation/location_arbitrator_impl.h"
#include "content/browser/geolocation/network_location_provider.h"
+#include "content/browser/geolocation/wifi_data_provider.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,8 +36,8 @@ class MessageLoopQuitListener {
CHECK(client_message_loop_);
}
- void LocationUpdateAvailable(const LocationProvider* provider,
- const Geoposition& position) {
+ void OnLocationUpdate(const LocationProvider* provider,
+ const Geoposition& position) {
EXPECT_EQ(client_message_loop_, base::MessageLoop::current());
updated_provider_ = provider;
client_message_loop_->Quit();
@@ -46,38 +47,30 @@ class MessageLoopQuitListener {
const LocationProvider* updated_provider_;
};
-// A mock implementation of WifiDataProviderImplBase for testing. Adapted from
+// A mock implementation of WifiDataProvider for testing. Adapted from
// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation_test.cc
-class MockWifiDataProviderImpl : public WifiDataProviderImplBase {
+class MockWifiDataProvider : public WifiDataProvider {
public:
- // Factory method for use with WifiDataProvider::SetFactory.
- static WifiDataProviderImplBase* GetInstance() {
+ // Factory method for use with WifiDataProvider::SetFactoryForTesting.
+ static WifiDataProvider* GetInstance() {
CHECK(instance_);
return instance_;
}
- static MockWifiDataProviderImpl* CreateInstance() {
+ static MockWifiDataProvider* CreateInstance() {
CHECK(!instance_);
- instance_ = new MockWifiDataProviderImpl;
+ instance_ = new MockWifiDataProvider;
return instance_;
}
- MockWifiDataProviderImpl()
- : start_calls_(0),
- stop_calls_(0),
- got_data_(true) {
- }
+ MockWifiDataProvider() : start_calls_(0), stop_calls_(0), got_data_(true) {}
- // WifiDataProviderImplBase implementation.
- virtual void StartDataProvider() OVERRIDE {
- ++start_calls_;
- }
+ // WifiDataProvider implementation.
+ void StartDataProvider() override { ++start_calls_; }
- virtual void StopDataProvider() OVERRIDE {
- ++stop_calls_;
- }
+ void StopDataProvider() override { ++stop_calls_; }
- virtual bool GetData(WifiData* data_out) OVERRIDE {
+ bool GetData(WifiData* data_out) override {
CHECK(data_out);
*data_out = data_;
return got_data_;
@@ -96,33 +89,32 @@ class MockWifiDataProviderImpl : public WifiDataProviderImplBase {
int stop_calls_;
private:
- virtual ~MockWifiDataProviderImpl() {
+ ~MockWifiDataProvider() override {
CHECK(this == instance_);
instance_ = NULL;
}
- static MockWifiDataProviderImpl* instance_;
+ static MockWifiDataProvider* instance_;
WifiData data_;
bool got_data_;
- DISALLOW_COPY_AND_ASSIGN(MockWifiDataProviderImpl);
+ DISALLOW_COPY_AND_ASSIGN(MockWifiDataProvider);
};
-MockWifiDataProviderImpl* MockWifiDataProviderImpl::instance_ = NULL;
+MockWifiDataProvider* MockWifiDataProvider::instance_ = NULL;
// Main test fixture
class GeolocationNetworkProviderTest : public testing::Test {
public:
- virtual void SetUp() {
+ void SetUp() override {
test_server_url_ = GURL(kTestServerUrl);
access_token_store_ = new FakeAccessTokenStore;
- wifi_data_provider_ =
- MockWifiDataProviderImpl::CreateInstance();
+ wifi_data_provider_ = MockWifiDataProvider::CreateInstance();
}
- virtual void TearDown() {
- WifiDataProvider::ResetFactory();
+ void TearDown() override {
+ WifiDataProviderManager::ResetFactoryForTesting();
}
LocationProvider* CreateProvider(bool set_permission_granted) {
@@ -140,7 +132,8 @@ class GeolocationNetworkProviderTest : public testing::Test {
GeolocationNetworkProviderTest() {
// TODO(joth): Really these should be in SetUp, not here, but they take no
// effect on Mac OS Release builds if done there. I kid not. Figure out why.
- WifiDataProvider::SetFactory(MockWifiDataProviderImpl::GetInstance);
+ WifiDataProviderManager::SetFactoryForTesting(
+ MockWifiDataProvider::GetInstance);
}
// Returns the current url fetcher (if any) and advances the id ready for the
@@ -321,7 +314,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
base::MessageLoop main_message_loop_;
scoped_refptr<FakeAccessTokenStore> access_token_store_;
net::TestURLFetcherFactory url_fetcher_factory_;
- scoped_refptr<MockWifiDataProviderImpl> wifi_data_provider_;
+ scoped_refptr<MockWifiDataProvider> wifi_data_provider_;
};
TEST_F(GeolocationNetworkProviderTest, CreateDestroy) {
@@ -473,9 +466,8 @@ TEST_F(GeolocationNetworkProviderTest, NoRequestOnStartupUntilWifiData) {
scoped_ptr<LocationProvider> provider(CreateProvider(true));
EXPECT_TRUE(provider->StartProvider(false));
- provider->SetUpdateCallback(
- base::Bind(&MessageLoopQuitListener::LocationUpdateAvailable,
- base::Unretained(&listener)));
+ provider->SetUpdateCallback(base::Bind(
+ &MessageLoopQuitListener::OnLocationUpdate, base::Unretained(&listener)));
main_message_loop_.RunUntilIdle();
EXPECT_FALSE(get_url_fetcher_and_advance_id())
diff --git a/chromium/content/browser/geolocation/network_location_request.cc b/chromium/content/browser/geolocation/network_location_request.cc
index 8fb6e6a9076..84ba5b05edc 100644
--- a/chromium/content/browser/geolocation/network_location_request.cc
+++ b/chromium/content/browser/geolocation/network_location_request.cc
@@ -103,9 +103,7 @@ NetworkLocationRequest::NetworkLocationRequest(
net::URLRequestContextGetter* context,
const GURL& url,
LocationResponseCallback callback)
- : url_context_(context),
- callback_(callback),
- url_(url) {
+ : url_context_(context), location_response_callback_(callback), url_(url) {
}
NetworkLocationRequest::~NetworkLocationRequest() {
@@ -122,7 +120,7 @@ bool NetworkLocationRequest::MakeRequest(const base::string16& access_token,
url_fetcher_.reset();
}
wifi_data_ = wifi_data;
- timestamp_ = timestamp;
+ wifi_data_timestamp_ = timestamp;
GURL request_url = FormRequestURL(url_);
url_fetcher_.reset(net::URLFetcher::Create(
@@ -136,7 +134,7 @@ bool NetworkLocationRequest::MakeRequest(const base::string16& access_token,
net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA);
- start_time_ = base::TimeTicks::Now();
+ request_start_time_ = base::TimeTicks::Now();
url_fetcher_->Start();
return true;
}
@@ -156,7 +154,7 @@ void NetworkLocationRequest::OnURLFetchComplete(
GetLocationFromResponse(status.is_success(),
response_code,
data,
- timestamp_,
+ wifi_data_timestamp_,
source->GetURL(),
&position,
&access_token);
@@ -165,7 +163,8 @@ void NetworkLocationRequest::OnURLFetchComplete(
url_fetcher_.reset();
if (!server_error) {
- const base::TimeDelta request_time = base::TimeTicks::Now() - start_time_;
+ const base::TimeDelta request_time =
+ base::TimeTicks::Now() - request_start_time_;
UMA_HISTOGRAM_CUSTOM_TIMES(
"Net.Wifi.LbsLatency",
@@ -176,7 +175,8 @@ void NetworkLocationRequest::OnURLFetchComplete(
}
DVLOG(1) << "NetworkLocationRequest::OnURLFetchComplete() : run callback.";
- callback_.Run(position, server_error, access_token, wifi_data_);
+ location_response_callback_.Run(
+ position, server_error, access_token, wifi_data_);
}
// Local functions.
@@ -409,7 +409,8 @@ bool ParseServerResponse(const std::string& response_body,
static_cast<const base::DictionaryValue*>(location_value);
// latitude and longitude fields are always required.
- double latitude, longitude;
+ double latitude = 0;
+ double longitude = 0;
if (!GetAsDouble(*location_object, kLatitudeString, &latitude) ||
!GetAsDouble(*location_object, kLongitudeString, &longitude)) {
VLOG(1) << "ParseServerResponse() : location lacks lat and/or long.";
diff --git a/chromium/content/browser/geolocation/network_location_request.h b/chromium/content/browser/geolocation/network_location_request.h
index 6fea08b8bd5..f0734e00c25 100644
--- a/chromium/content/browser/geolocation/network_location_request.h
+++ b/chromium/content/browser/geolocation/network_location_request.h
@@ -41,7 +41,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
NetworkLocationRequest(net::URLRequestContextGetter* context,
const GURL& url,
LocationResponseCallback callback);
- virtual ~NetworkLocationRequest();
+ ~NetworkLocationRequest() override;
// Makes a new request. Returns true if the new request was successfully
// started. In all cases, any currently pending request will be canceled.
@@ -54,20 +54,20 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
private:
// net::URLFetcherDelegate
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+ void OnURLFetchComplete(const net::URLFetcher* source) override;
scoped_refptr<net::URLRequestContextGetter> url_context_;
- LocationResponseCallback callback_;
+ LocationResponseCallback location_response_callback_;
const GURL url_;
scoped_ptr<net::URLFetcher> url_fetcher_;
// Keep a copy of the data sent in the request, so we can refer back to it
// when the response arrives.
WifiData wifi_data_;
- base::Time timestamp_; // Timestamp of the above data, not of the request.
+ base::Time wifi_data_timestamp_;
// The start time for the request.
- base::TimeTicks start_time_;
+ base::TimeTicks request_start_time_;
DISALLOW_COPY_AND_ASSIGN(NetworkLocationRequest);
};
diff --git a/chromium/content/browser/geolocation/wifi_data_provider.cc b/chromium/content/browser/geolocation/wifi_data_provider.cc
index 85595f927ab..cd739e7fb7c 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider.cc
@@ -6,142 +6,48 @@
namespace content {
-// static
-WifiDataProvider* WifiDataProvider::instance_ = NULL;
-
-// static
-WifiDataProvider::ImplFactoryFunction WifiDataProvider::factory_function_ =
- DefaultFactoryFunction;
-
-// static
-void WifiDataProvider::SetFactory(ImplFactoryFunction factory_function_in) {
- factory_function_ = factory_function_in;
-}
-
-// static
-void WifiDataProvider::ResetFactory() {
- factory_function_ = DefaultFactoryFunction;
-}
-
-// static
-WifiDataProvider* WifiDataProvider::Register(WifiDataUpdateCallback* callback) {
- bool need_to_start_data_provider = false;
- if (!instance_) {
- instance_ = new WifiDataProvider();
- need_to_start_data_provider = true;
- }
- DCHECK(instance_);
- instance_->AddCallback(callback);
- // Start the provider after adding the callback, to avoid any race in
- // it running early.
- if (need_to_start_data_provider)
- instance_->StartDataProvider();
- return instance_;
-}
-
-// static
-bool WifiDataProvider::Unregister(WifiDataUpdateCallback* callback) {
- DCHECK(instance_);
- DCHECK(instance_->has_callbacks());
- if (!instance_->RemoveCallback(callback)) {
- return false;
- }
- if (!instance_->has_callbacks()) {
- // Must stop the data provider (and any implementation threads) before
- // destroying to avoid any race conditions in access to the provider in
- // the destructor chain.
- instance_->StopDataProvider();
- delete instance_;
- instance_ = NULL;
- }
- return true;
-}
-
-WifiDataProviderImplBase::WifiDataProviderImplBase()
- : container_(NULL),
- client_loop_(base::MessageLoop::current()) {
+WifiDataProvider::WifiDataProvider()
+ : client_loop_(base::MessageLoop::current()) {
DCHECK(client_loop_);
}
-WifiDataProviderImplBase::~WifiDataProviderImplBase() {
-}
-
-void WifiDataProviderImplBase::SetContainer(WifiDataProvider* container) {
- container_ = container;
+WifiDataProvider::~WifiDataProvider() {
}
-void WifiDataProviderImplBase::AddCallback(WifiDataUpdateCallback* callback) {
+void WifiDataProvider::AddCallback(WifiDataUpdateCallback* callback) {
callbacks_.insert(callback);
}
-bool WifiDataProviderImplBase::RemoveCallback(
- WifiDataUpdateCallback* callback) {
+bool WifiDataProvider::RemoveCallback(WifiDataUpdateCallback* callback) {
return callbacks_.erase(callback) == 1;
}
-bool WifiDataProviderImplBase::has_callbacks() const {
+bool WifiDataProvider::has_callbacks() const {
return !callbacks_.empty();
}
-void WifiDataProviderImplBase::RunCallbacks() {
- client_loop_->PostTask(FROM_HERE, base::Bind(
- &WifiDataProviderImplBase::DoRunCallbacks,
- this));
+void WifiDataProvider::RunCallbacks() {
+ client_loop_->PostTask(FROM_HERE,
+ base::Bind(&WifiDataProvider::DoRunCallbacks, this));
}
-bool WifiDataProviderImplBase::CalledOnClientThread() const {
+bool WifiDataProvider::CalledOnClientThread() const {
return base::MessageLoop::current() == this->client_loop_;
}
-base::MessageLoop* WifiDataProviderImplBase::client_loop() const {
+base::MessageLoop* WifiDataProvider::client_loop() const {
return client_loop_;
}
-void WifiDataProviderImplBase::DoRunCallbacks() {
- // It's possible that all the callbacks (and the container) went away
- // whilst this task was pending. This is fine; the loop will be a no-op.
+void WifiDataProvider::DoRunCallbacks() {
+ // It's possible that all the callbacks went away whilst this task was
+ // pending. This is fine; the loop will be a no-op.
CallbackSet::const_iterator iter = callbacks_.begin();
while (iter != callbacks_.end()) {
WifiDataUpdateCallback* callback = *iter;
++iter; // Advance iter before running, in case callback unregisters.
- callback->Run(container_);
+ callback->Run();
}
}
-WifiDataProvider::WifiDataProvider() {
- DCHECK(factory_function_);
- impl_ = (*factory_function_)();
- DCHECK(impl_.get());
- impl_->SetContainer(this);
-}
-
-WifiDataProvider::~WifiDataProvider() {
- DCHECK(impl_.get());
- impl_->SetContainer(NULL);
-}
-
-bool WifiDataProvider::GetData(WifiData* data) {
- return impl_->GetData(data);
-}
-
-void WifiDataProvider::AddCallback(WifiDataUpdateCallback* callback) {
- impl_->AddCallback(callback);
-}
-
-bool WifiDataProvider::RemoveCallback(WifiDataUpdateCallback* callback) {
- return impl_->RemoveCallback(callback);
-}
-
-bool WifiDataProvider::has_callbacks() const {
- return impl_->has_callbacks();
-}
-
-void WifiDataProvider::StartDataProvider() {
- impl_->StartDataProvider();
-}
-
-void WifiDataProvider::StopDataProvider() {
- impl_->StopDataProvider();
-}
-
} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider.h b/chromium/content/browser/geolocation/wifi_data_provider.h
index bfb06ec5444..98d22963e9f 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider.h
@@ -2,19 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// A wifi data provider provides wifi data from the device that is used by a
-// NetworkLocationProvider to obtain a position fix. We use a singleton
-// instance of the wifi data provider, which is used by multiple
-// NetworkLocationProvider objects.
-//
-// This file provides WifiDataProvider, which provides static methods to
-// access the singleton instance. The singleton instance uses a private
-// implementation to abstract across platforms and also to allow mock providers
-// to be used for testing.
-//
-// This file also provides WifiDataProviderImplBase, a base class which
-// provides common functionality for the private implementations.
-
#ifndef CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_H_
@@ -32,16 +19,10 @@
namespace content {
-class WifiDataProvider;
-
-// See class WifiDataProvider for the public client API.
-// WifiDataProvider uses containment to hide platform-specific implementation
-// details from common code. This class provides common functionality for these
-// contained implementation classes. This is a modified pimpl pattern.
-class CONTENT_EXPORT WifiDataProviderImplBase
- : public base::RefCountedThreadSafe<WifiDataProviderImplBase> {
+class CONTENT_EXPORT WifiDataProvider
+ : public base::RefCountedThreadSafe<WifiDataProvider> {
public:
- WifiDataProviderImplBase();
+ WifiDataProvider();
// Tells the provider to start looking for data. Callbacks will start
// receiving notifications after this call.
@@ -56,11 +37,7 @@ class CONTENT_EXPORT WifiDataProviderImplBase
// obtain.
virtual bool GetData(WifiData* data) = 0;
- // Sets the container of this class, which is of type WifiDataProvider.
- // This is required to pass as a parameter when calling a callback.
- void SetContainer(WifiDataProvider* container);
-
- typedef base::Callback<void(WifiDataProvider*)> WifiDataUpdateCallback;
+ typedef base::Closure WifiDataUpdateCallback;
void AddCallback(WifiDataUpdateCallback* callback);
@@ -69,8 +46,8 @@ class CONTENT_EXPORT WifiDataProviderImplBase
bool has_callbacks() const;
protected:
- friend class base::RefCountedThreadSafe<WifiDataProviderImplBase>;
- virtual ~WifiDataProviderImplBase();
+ friend class base::RefCountedThreadSafe<WifiDataProvider>;
+ virtual ~WifiDataProvider();
typedef std::set<WifiDataUpdateCallback*> CallbackSet;
@@ -85,75 +62,12 @@ class CONTENT_EXPORT WifiDataProviderImplBase
private:
void DoRunCallbacks();
- WifiDataProvider* container_;
-
// Reference to the client's message loop. All callbacks should happen in this
// context.
base::MessageLoop* client_loop_;
CallbackSet callbacks_;
- DISALLOW_COPY_AND_ASSIGN(WifiDataProviderImplBase);
-};
-
-// A wifi data provider
-//
-// We use a singleton instance of this class which is shared by multiple network
-// location providers. These location providers access the instance through the
-// Register and Unregister methods.
-class CONTENT_EXPORT WifiDataProvider {
- public:
- // Sets the factory function which will be used by Register to create the
- // implementation used by the singleton instance. This factory approach is
- // used both to abstract accross platform-specific implementations and to
- // inject mock implementations for testing.
- typedef WifiDataProviderImplBase* (*ImplFactoryFunction)(void);
- static void SetFactory(ImplFactoryFunction factory_function_in);
-
- // Resets the factory function to the default.
- static void ResetFactory();
-
- typedef base::Callback<void(WifiDataProvider*)> WifiDataUpdateCallback;
-
- // Registers a callback, which will be run whenever new data is available.
- // Instantiates the singleton if necessary, and always returns it.
- static WifiDataProvider* Register(WifiDataUpdateCallback* callback);
-
- // Removes a callback. If this is the last callback, deletes the singleton
- // instance. Return value indicates success.
- static bool Unregister(WifiDataUpdateCallback* callback);
-
- // Provides whatever data the provider has, which may be nothing. Return
- // value indicates whether this is all the data the provider could ever
- // obtain.
- bool GetData(WifiData* data);
-
- private:
- // Private constructor and destructor, callers access singleton through
- // Register and Unregister.
- WifiDataProvider();
- virtual ~WifiDataProvider();
-
- void AddCallback(WifiDataUpdateCallback* callback);
- bool RemoveCallback(WifiDataUpdateCallback* callback);
- bool has_callbacks() const;
-
- void StartDataProvider();
- void StopDataProvider();
-
- static WifiDataProviderImplBase* DefaultFactoryFunction();
-
- // The singleton-like instance of this class. (Not 'true' singleton, as it
- // may go through multiple create/destroy/create cycles per process instance,
- // e.g. when under test).
- static WifiDataProvider* instance_;
-
- // The factory function used to create the singleton instance.
- static ImplFactoryFunction factory_function_;
-
- // The internal implementation.
- scoped_refptr<WifiDataProviderImplBase> impl_;
-
DISALLOW_COPY_AND_ASSIGN(WifiDataProvider);
};
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
index 49edb23e85c..2b5c218c24b 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/network/geolocation_handler.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
#include "content/public/browser/browser_thread.h"
namespace content {
@@ -166,7 +167,7 @@ bool WifiDataProviderChromeOs::GetAccessPointData(
}
// static
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
return new WifiDataProviderChromeOs();
}
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
index 895d06eaf31..db56ea7da09 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
@@ -11,15 +11,14 @@
namespace content {
-class CONTENT_EXPORT WifiDataProviderChromeOs
- : public WifiDataProviderImplBase {
+class CONTENT_EXPORT WifiDataProviderChromeOs : public WifiDataProvider {
public:
WifiDataProviderChromeOs();
- // WifiDataProviderImplBase
- virtual void StartDataProvider() OVERRIDE;
- virtual void StopDataProvider() OVERRIDE;
- virtual bool GetData(WifiData* data) OVERRIDE;
+ // WifiDataProvider
+ virtual void StartDataProvider() override;
+ virtual void StopDataProvider() override;
+ virtual bool GetData(WifiData* data) override;
private:
friend class GeolocationChromeOsWifiDataProviderTest;
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
index f282f31e510..eb0442194cb 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -19,8 +19,8 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test {
GeolocationChromeOsWifiDataProviderTest() {
}
- virtual void SetUp() OVERRIDE {
- chromeos::DBusThreadManager::InitializeWithStub();
+ virtual void SetUp() override {
+ chromeos::DBusThreadManager::Initialize();
chromeos::NetworkHandler::Initialize();
manager_client_ =
chromeos::DBusThreadManager::Get()->GetShillManagerClient();
@@ -29,7 +29,7 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test {
message_loop_.RunUntilIdle();
}
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
provider_ = NULL;
chromeos::NetworkHandler::Shutdown();
chromeos::DBusThreadManager::Shutdown();
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common.h b/chromium/content/browser/geolocation/wifi_data_provider_common.h
index befdb692114..771dd41efc8 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common.h
@@ -25,7 +25,7 @@ base::string16 MacAddressAsString16(const uint8 mac_as_int[6]);
// do polling behavior is taken care of by this base class, and all the platform
// need do is provide the underlying WLAN access API and polling policy.
// Also designed this way for ease of testing the cross-platform behavior.
-class CONTENT_EXPORT WifiDataProviderCommon : public WifiDataProviderImplBase {
+class CONTENT_EXPORT WifiDataProviderCommon : public WifiDataProvider {
public:
// Interface to abstract the low level data OS library call, and to allow
// mocking (hence public).
@@ -38,13 +38,13 @@ class CONTENT_EXPORT WifiDataProviderCommon : public WifiDataProviderImplBase {
WifiDataProviderCommon();
- // WifiDataProviderImplBase implementation
- virtual void StartDataProvider() OVERRIDE;
- virtual void StopDataProvider() OVERRIDE;
- virtual bool GetData(WifiData* data) OVERRIDE;
+ // WifiDataProvider implementation
+ void StartDataProvider() override;
+ void StopDataProvider() override;
+ bool GetData(WifiData* data) override;
protected:
- virtual ~WifiDataProviderCommon();
+ ~WifiDataProviderCommon() override;
// Returns ownership.
virtual WlanApiInterface* NewWlanApi() = 0;
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
index 9c55dfd3335..53d44bcc770 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "content/browser/geolocation/wifi_data_provider_common.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -62,18 +63,18 @@ class MessageLoopQuitter {
public:
explicit MessageLoopQuitter(base::MessageLoop* message_loop)
: message_loop_to_quit_(message_loop),
- callback_(base::Bind(&MessageLoopQuitter::WifiDataUpdateAvailable,
+ callback_(base::Bind(&MessageLoopQuitter::OnWifiDataUpdate,
base::Unretained(this))) {
CHECK(message_loop_to_quit_ != NULL);
}
- void WifiDataUpdateAvailable(WifiDataProvider* provider) {
+ void OnWifiDataUpdate() {
// Provider should call back on client's thread.
EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
message_loop_to_quit_->QuitNow();
}
base::MessageLoop* message_loop_to_quit_;
- WifiDataProvider::WifiDataUpdateCallback callback_;
+ WifiDataProviderManager::WifiDataUpdateCallback callback_;
};
class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
@@ -83,11 +84,11 @@ class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
new_polling_policy_(new MockPollingPolicy) {}
// WifiDataProviderCommon
- virtual WlanApiInterface* NewWlanApi() OVERRIDE {
+ WlanApiInterface* NewWlanApi() override {
CHECK(new_wlan_api_ != NULL);
return new_wlan_api_.release();
}
- virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE {
+ WifiPollingPolicy* NewPollingPolicy() override {
CHECK(new_polling_policy_ != NULL);
return new_polling_policy_.release();
}
@@ -96,12 +97,12 @@ class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
scoped_ptr<MockPollingPolicy> new_polling_policy_;
private:
- virtual ~WifiDataProviderCommonWithMock() {}
+ ~WifiDataProviderCommonWithMock() override {}
DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommonWithMock);
};
-WifiDataProviderImplBase* CreateWifiDataProviderCommonWithMock() {
+WifiDataProvider* CreateWifiDataProviderCommonWithMock() {
return new WifiDataProviderCommonWithMock;
}
@@ -112,13 +113,13 @@ class GeolocationWifiDataProviderCommonTest : public testing::Test {
: loop_quitter_(&main_message_loop_) {
}
- virtual void SetUp() {
+ void SetUp() override {
provider_ = new WifiDataProviderCommonWithMock;
wlan_api_ = provider_->new_wlan_api_.get();
polling_policy_ = provider_->new_polling_policy_.get();
provider_->AddCallback(&loop_quitter_.callback_);
}
- virtual void TearDown() {
+ void TearDown() override {
provider_->RemoveCallback(&loop_quitter_.callback_);
provider_->StopDataProvider();
provider_ = NULL;
@@ -181,7 +182,12 @@ TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi){
main_message_loop_.Run();
}
-TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
+#if defined(OS_MACOSX)
+#define MAYBE_DoAnEmptyScan DISABLED_DoAnEmptyScan
+#else
+#define MAYBE_DoAnEmptyScan DoAnEmptyScan
+#endif
+TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoAnEmptyScan) {
EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
.Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, PollingInterval())
@@ -194,7 +200,12 @@ TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
EXPECT_EQ(0, static_cast<int>(data.access_point_data.size()));
}
-TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
+#if defined(OS_MACOSX)
+#define MAYBE_DoScanWithResults DISABLED_DoScanWithResults
+#else
+#define MAYBE_DoScanWithResults DoScanWithResults
+#endif
+TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoScanWithResults) {
EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
.Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, PollingInterval())
@@ -218,11 +229,12 @@ TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
TEST_F(GeolocationWifiDataProviderCommonTest, RegisterUnregister) {
MessageLoopQuitter loop_quitter(&main_message_loop_);
- WifiDataProvider::SetFactory(CreateWifiDataProviderCommonWithMock);
- WifiDataProvider::Register(&loop_quitter.callback_);
+ WifiDataProviderManager::SetFactoryForTesting(
+ CreateWifiDataProviderCommonWithMock);
+ WifiDataProviderManager::Register(&loop_quitter.callback_);
main_message_loop_.Run();
- WifiDataProvider::Unregister(&loop_quitter.callback_);
- WifiDataProvider::ResetFactory();
+ WifiDataProviderManager::Unregister(&loop_quitter.callback_);
+ WifiDataProviderManager::ResetFactoryForTesting();
}
} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm b/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
index 81930e08f36..7e783f42942 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
+++ b/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
@@ -55,7 +55,7 @@ class CoreWlanApi : public WifiDataProviderCommon::WlanApiInterface {
bool Init();
// WlanApiInterface
- virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) OVERRIDE;
+ bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;
private:
base::scoped_nsobject<NSBundle> bundle_;
@@ -168,7 +168,7 @@ bool CoreWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
[supported_interfaces count] - interface_error_count,
1,
5,
- 5);
+ 6);
// Return true even if some interfaces failed to scan, so long as at least
// one interface did not fail.
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_linux.cc b/chromium/content/browser/geolocation/wifi_data_provider_linux.cc
index 5838c048e35..1909abfe141 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_linux.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_linux.cc
@@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
@@ -39,7 +40,7 @@ enum { NM_DEVICE_TYPE_WIFI = 2 };
class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface {
public:
NetworkManagerWlanApi();
- virtual ~NetworkManagerWlanApi();
+ ~NetworkManagerWlanApi() override;
// Must be called before any other interface method. Will return false if the
// NetworkManager session cannot be created (e.g. not present on this distro),
@@ -53,7 +54,7 @@ class NetworkManagerWlanApi : public WifiDataProviderCommon::WlanApiInterface {
//
// This function makes blocking D-Bus calls, but it's totally fine as
// the code runs in "Geolocation" thread, not the browser's UI thread.
- virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) OVERRIDE;
+ bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;
private:
// Enumerates the list of available network adapter devices known to
@@ -344,7 +345,7 @@ scoped_ptr<dbus::Response> NetworkManagerWlanApi::GetAccessPointProperty(
} // namespace
// static
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
+WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
return new WifiDataProviderLinux();
}
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_linux.h b/chromium/content/browser/geolocation/wifi_data_provider_linux.h
index 40f6f14e75f..48584257da1 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_linux.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_linux.h
@@ -22,11 +22,11 @@ class CONTENT_EXPORT WifiDataProviderLinux : public WifiDataProviderCommon {
private:
friend class GeolocationWifiDataProviderLinuxTest;
- virtual ~WifiDataProviderLinux();
+ ~WifiDataProviderLinux() override;
// WifiDataProviderCommon
- virtual WlanApiInterface* NewWlanApi() OVERRIDE;
- virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE;
+ WlanApiInterface* NewWlanApi() override;
+ WifiPollingPolicy* NewPollingPolicy() override;
// For testing.
WlanApiInterface* NewWlanApiForTesting(dbus::Bus* bus);
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
index 498b230643c..5a4b546a082 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
@@ -24,7 +24,7 @@ using ::testing::Unused;
namespace content {
class GeolocationWifiDataProviderLinuxTest : public testing::Test {
- virtual void SetUp() {
+ void SetUp() override {
// Create a mock bus.
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_mac.cc b/chromium/content/browser/geolocation/wifi_data_provider_mac.cc
index 6a87801c893..da541872583 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_mac.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_mac.cc
@@ -15,6 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/geolocation/osx_wifi.h"
#include "content/browser/geolocation/wifi_data_provider_common.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
namespace content {
namespace {
@@ -29,7 +30,7 @@ const int kNoWifiPollingIntervalMilliseconds = 20 * 1000; // 20s
class Apple80211Api : public WifiDataProviderCommon::WlanApiInterface {
public:
Apple80211Api();
- virtual ~Apple80211Api();
+ ~Apple80211Api() override;
// Must be called before any other interface method. Will return false if the
// Apple80211 framework cannot be initialized (e.g. running on post-10.5 OSX),
@@ -37,7 +38,7 @@ class Apple80211Api : public WifiDataProviderCommon::WlanApiInterface {
bool Init();
// WlanApiInterface
- virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) OVERRIDE;
+ bool GetAccessPointData(WifiData::AccessPointDataSet* data) override;
private:
// Handle, context and function pointers for Apple80211 library.
@@ -159,21 +160,21 @@ bool Apple80211Api::GetAccessPointData(WifiData::AccessPointDataSet* data) {
} // namespace
// static
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
- return new MacWifiDataProvider();
+WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+ return new WifiDataProviderMac();
}
-MacWifiDataProvider::MacWifiDataProvider() {
+WifiDataProviderMac::WifiDataProviderMac() {
}
-MacWifiDataProvider::~MacWifiDataProvider() {
+WifiDataProviderMac::~WifiDataProviderMac() {
}
-MacWifiDataProvider::WlanApiInterface* MacWifiDataProvider::NewWlanApi() {
+WifiDataProviderMac::WlanApiInterface* WifiDataProviderMac::NewWlanApi() {
// Try and find a API binding that works: first try the officially supported
// CoreWLAN API, and if this fails (e.g. on OSX 10.5) fall back to the reverse
// engineered Apple80211 API.
- MacWifiDataProvider::WlanApiInterface* core_wlan_api = NewCoreWlanApi();
+ WifiDataProviderMac::WlanApiInterface* core_wlan_api = NewCoreWlanApi();
if (core_wlan_api)
return core_wlan_api;
@@ -181,11 +182,11 @@ MacWifiDataProvider::WlanApiInterface* MacWifiDataProvider::NewWlanApi() {
if (wlan_api->Init())
return wlan_api.release();
- DVLOG(1) << "MacWifiDataProvider : failed to initialize any wlan api";
+ DVLOG(1) << "WifiDataProviderMac : failed to initialize any wlan api";
return NULL;
}
-WifiPollingPolicy* MacWifiDataProvider::NewPollingPolicy() {
+WifiPollingPolicy* WifiDataProviderMac::NewPollingPolicy() {
return new GenericWifiPollingPolicy<kDefaultPollingInterval,
kNoChangePollingInterval,
kTwoNoChangePollingInterval,
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_mac.h b/chromium/content/browser/geolocation/wifi_data_provider_mac.h
index ebb0030df2f..c1bd7985cdc 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_mac.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_mac.h
@@ -12,18 +12,18 @@ namespace content {
// Implementation of the wifi data provider for Mac OSX. Uses different API
// bindings depending on APIs detected available at runtime in order to access
// wifi scan data: Apple80211.h on OSX 10.5, CoreWLAN framework on OSX 10.6.
-class MacWifiDataProvider : public WifiDataProviderCommon {
+class WifiDataProviderMac : public WifiDataProviderCommon {
public:
- MacWifiDataProvider();
+ WifiDataProviderMac();
private:
- virtual ~MacWifiDataProvider();
+ ~WifiDataProviderMac() override;
// WifiDataProviderCommon
- virtual WlanApiInterface* NewWlanApi() OVERRIDE;
- virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE;
+ WlanApiInterface* NewWlanApi() override;
+ WifiPollingPolicy* NewPollingPolicy() override;
- DISALLOW_COPY_AND_ASSIGN(MacWifiDataProvider);
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProviderMac);
};
// Creates and returns a new API binding for the CoreWLAN API, or NULL if the
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_manager.cc b/chromium/content/browser/geolocation/wifi_data_provider_manager.cc
new file mode 100644
index 00000000000..cf53657e53a
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_data_provider_manager.cc
@@ -0,0 +1,98 @@
+// Copyright 2014 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 "content/browser/geolocation/wifi_data_provider_manager.h"
+
+#include "content/browser/geolocation/wifi_data_provider.h"
+
+namespace content {
+
+// static
+WifiDataProviderManager* WifiDataProviderManager::instance_ = NULL;
+
+// static
+WifiDataProviderManager::ImplFactoryFunction
+ WifiDataProviderManager::factory_function_ = DefaultFactoryFunction;
+
+// static
+void WifiDataProviderManager::SetFactoryForTesting(
+ ImplFactoryFunction factory_function_in) {
+ factory_function_ = factory_function_in;
+}
+
+// static
+void WifiDataProviderManager::ResetFactoryForTesting() {
+ factory_function_ = DefaultFactoryFunction;
+}
+
+// static
+WifiDataProviderManager* WifiDataProviderManager::Register(
+ WifiDataUpdateCallback* callback) {
+ bool need_to_start_data_provider = false;
+ if (!instance_) {
+ instance_ = new WifiDataProviderManager();
+ need_to_start_data_provider = true;
+ }
+ DCHECK(instance_);
+ instance_->AddCallback(callback);
+ // Start the provider after adding the callback, to avoid any race in
+ // it running early.
+ if (need_to_start_data_provider)
+ instance_->StartDataProvider();
+ return instance_;
+}
+
+// static
+bool WifiDataProviderManager::Unregister(WifiDataUpdateCallback* callback) {
+ DCHECK(instance_);
+ DCHECK(instance_->has_callbacks());
+ if (!instance_->RemoveCallback(callback)) {
+ return false;
+ }
+ if (!instance_->has_callbacks()) {
+ // Must stop the data provider (and any implementation threads) before
+ // destroying to avoid any race conditions in access to the provider in
+ // the destructor chain.
+ instance_->StopDataProvider();
+ delete instance_;
+ instance_ = NULL;
+ }
+ return true;
+}
+
+WifiDataProviderManager::WifiDataProviderManager() {
+ DCHECK(factory_function_);
+ impl_ = (*factory_function_)();
+ DCHECK(impl_.get());
+}
+
+WifiDataProviderManager::~WifiDataProviderManager() {
+ DCHECK(impl_.get());
+}
+
+bool WifiDataProviderManager::GetData(WifiData* data) {
+ return impl_->GetData(data);
+}
+
+void WifiDataProviderManager::AddCallback(WifiDataUpdateCallback* callback) {
+ impl_->AddCallback(callback);
+}
+
+bool WifiDataProviderManager::RemoveCallback(WifiDataUpdateCallback* callback) {
+ return impl_->RemoveCallback(callback);
+}
+
+bool WifiDataProviderManager::has_callbacks() const {
+ return impl_->has_callbacks();
+}
+
+void WifiDataProviderManager::StartDataProvider() {
+ impl_->StartDataProvider();
+}
+
+void WifiDataProviderManager::StopDataProvider() {
+ impl_->StopDataProvider();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_manager.h b/chromium/content/browser/geolocation/wifi_data_provider_manager.h
new file mode 100644
index 00000000000..966c03a5ced
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_data_provider_manager.h
@@ -0,0 +1,98 @@
+// Copyright 2014 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.
+
+// A wifi data provider provides wifi data from the device that is used by a
+// NetworkLocationProvider to obtain a position fix. We use a singleton
+// instance of the wifi data provider manager, which is used by multiple
+// NetworkLocationProvider objects.
+//
+// This file provides WifiDataProviderManager, which provides static methods to
+// access the singleton instance. The singleton instance uses a private
+// implementation of WifiDataProvider to abstract across platforms and also to
+// allow mock providers to be used for testing.
+
+#ifndef CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_MANAGER_H_
+#define CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_MANAGER_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_util.h"
+#include "content/browser/geolocation/wifi_data.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class WifiDataProvider;
+
+// A manager for wifi data providers.
+//
+// We use a singleton instance of this class which is shared by multiple network
+// location providers. These location providers access the instance through the
+// Register and Unregister methods.
+class CONTENT_EXPORT WifiDataProviderManager {
+ public:
+ typedef WifiDataProvider* (*ImplFactoryFunction)(void);
+
+ // Sets the factory function which will be used by Register to create the
+ // implementation used by the singleton instance. This factory approach is
+ // used both to abstract accross platform-specific implementations and to
+ // inject mock implementations for testing.
+ static void SetFactoryForTesting(ImplFactoryFunction factory_function_in);
+
+ // Resets the factory function to the default.
+ static void ResetFactoryForTesting();
+
+ typedef base::Closure WifiDataUpdateCallback;
+
+ // Registers a callback, which will be run whenever new data is available.
+ // Instantiates the singleton if necessary, and always returns it.
+ static WifiDataProviderManager* Register(WifiDataUpdateCallback* callback);
+
+ // Removes a callback. If this is the last callback, deletes the singleton
+ // instance. Return value indicates success.
+ static bool Unregister(WifiDataUpdateCallback* callback);
+
+ // Provides whatever data the provider has, which may be nothing. Return
+ // value indicates whether this is all the data the provider could ever
+ // obtain.
+ bool GetData(WifiData* data);
+
+ private:
+ // Private constructor and destructor, callers access singleton through
+ // Register and Unregister.
+ WifiDataProviderManager();
+ ~WifiDataProviderManager();
+
+ void AddCallback(WifiDataUpdateCallback* callback);
+ bool RemoveCallback(WifiDataUpdateCallback* callback);
+ bool has_callbacks() const;
+
+ void StartDataProvider();
+ void StopDataProvider();
+
+ static WifiDataProvider* DefaultFactoryFunction();
+
+ // The singleton-like instance of this class. (Not 'true' singleton, as it
+ // may go through multiple create/destroy/create cycles per process instance,
+ // e.g. when under test).
+ static WifiDataProviderManager* instance_;
+
+ // The factory function used to create the singleton instance.
+ static ImplFactoryFunction factory_function_;
+
+ // The internal implementation.
+ scoped_refptr<WifiDataProvider> impl_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProviderManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GEOLOCATION_WIFI_DATA_PROVIDER_MANAGER_H_
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_unittest_win.cc b/chromium/content/browser/geolocation/wifi_data_provider_unittest_win.cc
deleted file mode 100644
index c74f42c5739..00000000000
--- a/chromium/content/browser/geolocation/wifi_data_provider_unittest_win.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Most logic for the platform wifi provider is now factored into
-// WifiDataProviderCommon and covered by it's unit tests.
-
-#include "content/browser/geolocation/wifi_data_provider_win.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-TEST(GeolocationWin32WifiDataProviderTest, CreateDestroy) {
- // WifiDataProviderCommon requires the client to have a message loop.
- base::MessageLoop dummy_loop;
- scoped_refptr<Win32WifiDataProvider> instance(new Win32WifiDataProvider);
- instance = NULL;
- SUCCEED();
- // Can't actually call start provider on the Win32WifiDataProvider without
- // it accessing hardware and so risking making the test flaky.
-}
-
-} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win.cc b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
index 9345144438d..66c07c01848 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
@@ -32,6 +32,7 @@
#include "base/win/windows_version.h"
#include "content/browser/geolocation/wifi_data_provider_common.h"
#include "content/browser/geolocation/wifi_data_provider_common_win.h"
+#include "content/browser/geolocation/wifi_data_provider_manager.h"
// Taken from ndis.h for WinCE.
#define NDIS_STATUS_INVALID_LENGTH ((NDIS_STATUS)0xC0010014L)
@@ -43,7 +44,7 @@ namespace {
const int kInitialBufferSize = 2 << 12; // Good for about 50 APs.
const int kMaximumBufferSize = 2 << 20; // 2MB
-// Length for generic string buffers passed to Win32 APIs.
+// Length for generic string buffers passed to Windows APIs.
const int kStringLength = 512;
// The time periods, in milliseconds, between successive polls of the wifi data.
@@ -147,7 +148,7 @@ bool GetNetworkData(const WLAN_BSS_ENTRY& bss_entry,
bool UndefineDosDevice(const base::string16& device_name);
bool DefineDosDeviceIfNotExists(const base::string16& device_name);
HANDLE GetFileHandle(const base::string16& device_name);
-// Makes the OID query and returns a Win32 error code.
+// Makes the OID query and returns a Windows API error code.
int PerformQuery(HANDLE adapter_handle,
BYTE* buffer,
DWORD buffer_size,
@@ -159,17 +160,17 @@ bool ResizeBuffer(int requested_size,
bool GetSystemDirectory(base::string16* path);
} // namespace
-WifiDataProviderImplBase* WifiDataProvider::DefaultFactoryFunction() {
- return new Win32WifiDataProvider();
+WifiDataProvider* WifiDataProviderManager::DefaultFactoryFunction() {
+ return new WifiDataProviderWin();
}
-Win32WifiDataProvider::Win32WifiDataProvider() {
+WifiDataProviderWin::WifiDataProviderWin() {
}
-Win32WifiDataProvider::~Win32WifiDataProvider() {
+WifiDataProviderWin::~WifiDataProviderWin() {
}
-WifiDataProviderCommon::WlanApiInterface* Win32WifiDataProvider::NewWlanApi() {
+WifiDataProviderCommon::WlanApiInterface* WifiDataProviderWin::NewWlanApi() {
// Use the WLAN interface if we're on Vista and if it's available. Otherwise,
// use NDIS.
WlanApiInterface* api = WindowsWlanApi::Create();
@@ -179,7 +180,7 @@ WifiDataProviderCommon::WlanApiInterface* Win32WifiDataProvider::NewWlanApi() {
return WindowsNdisApi::Create();
}
-WifiPollingPolicy* Win32WifiDataProvider::NewPollingPolicy() {
+WifiPollingPolicy* WifiDataProviderWin::NewPollingPolicy() {
return new GenericWifiPollingPolicy<kDefaultPollingInterval,
kNoChangePollingInterval,
kTwoNoChangePollingInterval,
@@ -244,7 +245,7 @@ void WindowsWlanApi::LogWlanInterfaceCount(int count) {
count,
1,
5,
- 5);
+ 6);
}
bool WindowsWlanApi::GetAccessPointData(
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win.h b/chromium/content/browser/geolocation/wifi_data_provider_win.h
index c39bd580a79..d67798d5711 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win.h
@@ -10,18 +10,18 @@
namespace content {
-class CONTENT_EXPORT Win32WifiDataProvider : public WifiDataProviderCommon {
+class CONTENT_EXPORT WifiDataProviderWin : public WifiDataProviderCommon {
public:
- Win32WifiDataProvider();
+ WifiDataProviderWin();
private:
- virtual ~Win32WifiDataProvider();
+ virtual ~WifiDataProviderWin();
// WifiDataProviderCommon
virtual WlanApiInterface* NewWlanApi();
virtual WifiPollingPolicy* NewPollingPolicy();
- DISALLOW_COPY_AND_ASSIGN(Win32WifiDataProvider);
+ DISALLOW_COPY_AND_ASSIGN(WifiDataProviderWin);
};
} // namespace content
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc
new file mode 100644
index 00000000000..cb3c21ce3ec
--- /dev/null
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+// Most logic for the platform wifi provider is now factored into
+// WifiDataProviderCommon and covered by it's unit tests.
+
+#include "content/browser/geolocation/wifi_data_provider_win.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+TEST(GeolocationWifiDataProviderWinTest, CreateDestroy) {
+ // WifiDataProviderCommon requires the client to have a message loop.
+ base::MessageLoop dummy_loop;
+ scoped_refptr<WifiDataProviderWin> instance(new WifiDataProviderWin);
+ instance = NULL;
+ SUCCEED();
+ // Can't actually call start provider on the WifiDataProviderWin without
+ // it accessing hardware and so risking making the test flaky.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/OWNERS b/chromium/content/browser/gpu/OWNERS
index b66635ae032..954a4d9b72b 100644
--- a/chromium/content/browser/gpu/OWNERS
+++ b/chromium/content/browser/gpu/OWNERS
@@ -1,3 +1,4 @@
+jbauman@chromium.org
kbr@chromium.org
piman@chromium.org
zmo@chromium.org
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
index e2d1654e154..032c597c664 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -8,11 +8,13 @@
#include "base/debug/trace_event.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_restrictions.h"
+#include "base/tracked_objects.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_memory_buffer_factory_host_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/child_process_host_impl.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager.h"
@@ -26,8 +28,10 @@ namespace content {
BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
struct BrowserGpuChannelHostFactory::CreateRequest {
- CreateRequest()
- : event(true, false), gpu_host_id(0), route_id(MSG_ROUTING_NONE),
+ CreateRequest(int32 route_id)
+ : event(true, false),
+ gpu_host_id(0),
+ route_id(route_id),
result(CREATE_COMMAND_BUFFER_FAILED) {}
~CreateRequest() {}
base::WaitableEvent event;
@@ -129,6 +133,7 @@ void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
host->EstablishGpuChannel(
gpu_client_id_,
true,
+ true,
base::Bind(
&BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO,
this));
@@ -170,6 +175,13 @@ void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() {
void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
DCHECK(main_loop_->BelongsToCurrentThread());
{
+ // Since the current task synchronously waits for establishing a GPU
+ // channel, it shouldn't be tallied because its execution time has nothing
+ // to do with its efficiency. Using task stopwatch to exclude the waiting
+ // time from the current task run time.
+ tracked_objects::TaskStopwatch stopwatch;
+ stopwatch.Start();
+
// We're blocking the UI thread, which is generally undesirable.
// In this case we need to wait for this before we can show any UI
// /anyway/, so it won't cause additional jank.
@@ -178,6 +190,8 @@ void BrowserGpuChannelHostFactory::EstablishRequest::Wait() {
"BrowserGpuChannelHostFactory::EstablishGpuChannelSync");
base::ThreadRestrictions::ScopedAllowWait allow_wait;
event_.Wait();
+
+ stopwatch.Stop();
}
FinishOnMain();
}
@@ -209,13 +223,15 @@ void BrowserGpuChannelHostFactory::Terminate() {
BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory()
: gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
shutdown_event_(new base::WaitableEvent(true, false)),
- gpu_host_id_(0),
- next_create_gpu_memory_buffer_request_id_(0) {
+ gpu_memory_buffer_factory_host_(new GpuMemoryBufferFactoryHostImpl),
+ gpu_memory_buffer_manager_(
+ new BrowserGpuMemoryBufferManager(gpu_client_id_)),
+ gpu_host_id_(0) {
}
BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() {
DCHECK(IsMainThread());
- if (pending_request_)
+ if (pending_request_.get())
pending_request_->Cancel();
for (size_t n = 0; n < established_callbacks_.size(); n++)
established_callbacks_[n].Run();
@@ -277,8 +293,7 @@ CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
int32 surface_id,
const GPUCreateCommandBufferConfig& init_params,
int32 route_id) {
- CreateRequest request;
- request.route_id = route_id;
+ CreateRequest request(route_id);
GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
&BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO,
base::Unretained(this),
@@ -296,77 +311,11 @@ CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
return request.result;
}
-void BrowserGpuChannelHostFactory::CreateImageOnIO(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
- if (!host) {
- ImageCreatedOnIO(callback, gfx::Size());
- return;
- }
-
- host->CreateImage(
- window,
- gpu_client_id_,
- image_id,
- base::Bind(&BrowserGpuChannelHostFactory::ImageCreatedOnIO, callback));
-}
-
-// static
-void BrowserGpuChannelHostFactory::ImageCreatedOnIO(
- const CreateImageCallback& callback, const gfx::Size size) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::OnImageCreated,
- callback, size));
-}
-
-// static
-void BrowserGpuChannelHostFactory::OnImageCreated(
- const CreateImageCallback& callback, const gfx::Size size) {
- callback.Run(size);
-}
-
-void BrowserGpuChannelHostFactory::CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
- &BrowserGpuChannelHostFactory::CreateImageOnIO,
- base::Unretained(this),
- window,
- image_id,
- callback));
-}
-
-void BrowserGpuChannelHostFactory::DeleteImageOnIO(
- int32 image_id, int32 sync_point) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
- if (!host) {
- return;
- }
-
- host->DeleteImage(gpu_client_id_, image_id, sync_point);
-}
-
-void BrowserGpuChannelHostFactory::DeleteImage(
- int32 image_id, int32 sync_point) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- GetIOLoopProxy()->PostTask(FROM_HERE, base::Bind(
- &BrowserGpuChannelHostFactory::DeleteImageOnIO,
- base::Unretained(this),
- image_id,
- sync_point));
-}
-
GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
CauseForGpuLaunch cause_for_gpu_launch) {
EstablishGpuChannel(cause_for_gpu_launch, base::Closure());
- if (pending_request_)
+ if (pending_request_.get())
pending_request_->Wait();
return gpu_channel_.get();
@@ -376,19 +325,19 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannel(
CauseForGpuLaunch cause_for_gpu_launch,
const base::Closure& callback) {
if (gpu_channel_.get() && gpu_channel_->IsLost()) {
- DCHECK(!pending_request_);
+ DCHECK(!pending_request_.get());
// Recreate the channel if it has been lost.
gpu_channel_ = NULL;
}
- if (!gpu_channel_ && !pending_request_) {
+ if (!gpu_channel_.get() && !pending_request_.get()) {
// We should only get here if the context was lost.
pending_request_ = EstablishRequest::Create(
cause_for_gpu_launch, gpu_client_id_, gpu_host_id_);
}
if (!callback.is_null()) {
- if (gpu_channel_)
+ if (gpu_channel_.get())
callback.Run();
else
established_callbacks_.push_back(callback);
@@ -396,25 +345,28 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannel(
}
GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
- if (gpu_channel_ && !gpu_channel_->IsLost())
- return gpu_channel_;
+ if (gpu_channel_.get() && !gpu_channel_->IsLost())
+ return gpu_channel_.get();
return NULL;
}
void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
DCHECK(IsMainThread());
- DCHECK(pending_request_);
+ DCHECK(pending_request_.get());
if (pending_request_->channel_handle().name.empty()) {
- DCHECK(!gpu_channel_);
+ DCHECK(!gpu_channel_.get());
} else {
GetContentClient()->SetGpuInfo(pending_request_->gpu_info());
- gpu_channel_ = GpuChannelHost::Create(this,
- pending_request_->gpu_info(),
- pending_request_->channel_handle(),
- shutdown_event_.get());
+ gpu_channel_ =
+ GpuChannelHost::Create(this,
+ pending_request_->gpu_info(),
+ pending_request_->channel_handle(),
+ shutdown_event_.get(),
+ BrowserGpuMemoryBufferManager::current());
}
gpu_host_id_ = pending_request_->gpu_host_id();
+ gpu_memory_buffer_factory_host_->set_gpu_host_id(gpu_host_id_);
pending_request_ = NULL;
for (size_t n = 0; n < established_callbacks_.size(); n++)
@@ -423,20 +375,6 @@ void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
established_callbacks_.clear();
}
-scoped_ptr<gfx::GpuMemoryBuffer>
-BrowserGpuChannelHostFactory::AllocateGpuMemoryBuffer(size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage) {
- if (!GpuMemoryBufferImpl::IsFormatValid(internalformat) ||
- !GpuMemoryBufferImpl::IsUsageValid(usage))
- return scoped_ptr<gfx::GpuMemoryBuffer>();
-
- return GpuMemoryBufferImpl::Create(gfx::Size(width, height),
- internalformat,
- usage).PassAs<gfx::GpuMemoryBuffer>();
-}
-
// static
void BrowserGpuChannelHostFactory::AddFilterOnIO(
int host_id,
@@ -471,90 +409,4 @@ void BrowserGpuChannelHostFactory::SetHandlerForControlMessages(
filter));
}
-void BrowserGpuChannelHostFactory::CreateGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
- const CreateGpuMemoryBufferCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- uint32 request_id = next_create_gpu_memory_buffer_request_id_++;
- create_gpu_memory_buffer_requests_[request_id] = callback;
- GetIOLoopProxy()->PostTask(
- FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::CreateGpuMemoryBufferOnIO,
- base::Unretained(this),
- handle,
- size,
- internalformat,
- usage,
- request_id));
-}
-
-void BrowserGpuChannelHostFactory::DestroyGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- int32 sync_point) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- GetIOLoopProxy()->PostTask(
- FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO,
- base::Unretained(this),
- handle,
- sync_point));
-}
-
-void BrowserGpuChannelHostFactory::CreateGpuMemoryBufferOnIO(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
- uint32 request_id) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
- if (!host) {
- GpuMemoryBufferCreatedOnIO(request_id, gfx::GpuMemoryBufferHandle());
- return;
- }
-
- host->CreateGpuMemoryBuffer(
- handle,
- size,
- internalformat,
- usage,
- base::Bind(&BrowserGpuChannelHostFactory::GpuMemoryBufferCreatedOnIO,
- base::Unretained(this),
- request_id));
-}
-
-void BrowserGpuChannelHostFactory::GpuMemoryBufferCreatedOnIO(
- uint32 request_id,
- const gfx::GpuMemoryBufferHandle& handle) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated,
- base::Unretained(this),
- request_id,
- handle));
-}
-
-void BrowserGpuChannelHostFactory::OnGpuMemoryBufferCreated(
- uint32 request_id,
- const gfx::GpuMemoryBufferHandle& handle) {
- CreateGpuMemoryBufferCallbackMap::iterator iter =
- create_gpu_memory_buffer_requests_.find(request_id);
- DCHECK(iter != create_gpu_memory_buffer_requests_.end());
- iter->second.Run(handle);
- create_gpu_memory_buffer_requests_.erase(iter);
-}
-
-void BrowserGpuChannelHostFactory::DestroyGpuMemoryBufferOnIO(
- const gfx::GpuMemoryBufferHandle& handle,
- int32 sync_point) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
- if (!host)
- return;
-
- host->DestroyGpuMemoryBuffer(handle, sync_point);
-}
-
} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
index dc85f67ff45..4bc0b413153 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -10,49 +10,28 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
#include "ipc/message_filter.h"
namespace content {
+class BrowserGpuMemoryBufferManager;
+class GpuMemoryBufferFactoryHostImpl;
class CONTENT_EXPORT BrowserGpuChannelHostFactory
- : public GpuChannelHostFactory,
- public GpuMemoryBufferFactoryHost {
+ : public GpuChannelHostFactory {
public:
static void Initialize(bool establish_gpu_channel);
static void Terminate();
static BrowserGpuChannelHostFactory* instance() { return instance_; }
// GpuChannelHostFactory implementation.
- virtual bool IsMainThread() OVERRIDE;
- virtual base::MessageLoop* GetMainLoop() OVERRIDE;
- virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE;
- virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(
- size_t size) OVERRIDE;
- virtual CreateCommandBufferResult CreateViewCommandBuffer(
+ bool IsMainThread() override;
+ base::MessageLoop* GetMainLoop() override;
+ scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() override;
+ scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) override;
+ CreateCommandBufferResult CreateViewCommandBuffer(
int32 surface_id,
const GPUCreateCommandBufferConfig& init_params,
- int32 route_id) OVERRIDE;
- virtual void CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback) OVERRIDE;
- virtual void DeleteImage(int32 image_idu, int32 sync_point) OVERRIDE;
- virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
- size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage) OVERRIDE;
-
- // GpuMemoryBufferFactoryHost implementation.
- virtual void CreateGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
- const CreateGpuMemoryBufferCallback& callback) OVERRIDE;
- virtual void DestroyGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
- int32 sync_point) OVERRIDE;
+ int32 route_id) override;
// Specify a task runner and callback to be used for a set of messages. The
// callback will be set up on the current GpuProcessHost, identified by
@@ -78,7 +57,7 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
class EstablishRequest;
BrowserGpuChannelHostFactory();
- virtual ~BrowserGpuChannelHostFactory();
+ ~BrowserGpuChannelHostFactory() override;
void GpuChannelEstablished();
void CreateViewCommandBufferOnIO(
@@ -87,44 +66,18 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
const GPUCreateCommandBufferConfig& init_params);
static void CommandBufferCreatedOnIO(CreateRequest* request,
CreateCommandBufferResult result);
- void CreateImageOnIO(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback);
- static void ImageCreatedOnIO(
- const CreateImageCallback& callback, const gfx::Size size);
- static void OnImageCreated(
- const CreateImageCallback& callback, const gfx::Size size);
- void DeleteImageOnIO(int32 image_id, int32 sync_point);
static void AddFilterOnIO(int gpu_host_id,
scoped_refptr<IPC::MessageFilter> filter);
- void CreateGpuMemoryBufferOnIO(const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
- uint32 request_id);
- void GpuMemoryBufferCreatedOnIO(
- uint32 request_id,
- const gfx::GpuMemoryBufferHandle& handle);
- void OnGpuMemoryBufferCreated(
- uint32 request_id,
- const gfx::GpuMemoryBufferHandle& handle);
- void DestroyGpuMemoryBufferOnIO(const gfx::GpuMemoryBufferHandle& handle,
- int32 sync_point);
-
const int gpu_client_id_;
scoped_ptr<base::WaitableEvent> shutdown_event_;
scoped_refptr<GpuChannelHost> gpu_channel_;
+ scoped_ptr<GpuMemoryBufferFactoryHostImpl> gpu_memory_buffer_factory_host_;
+ scoped_ptr<BrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
int gpu_host_id_;
scoped_refptr<EstablishRequest> pending_request_;
std::vector<base::Closure> established_callbacks_;
- uint32 next_create_gpu_memory_buffer_request_id_;
- typedef std::map<uint32, CreateGpuMemoryBufferCallback>
- CreateGpuMemoryBufferCallbackMap;
- CreateGpuMemoryBufferCallbackMap create_gpu_memory_buffer_requests_;
-
static BrowserGpuChannelHostFactory* instance_;
DISALLOW_COPY_AND_ASSIGN(BrowserGpuChannelHostFactory);
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
new file mode 100644
index 00000000000..b5bcebc05ea
--- /dev/null
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -0,0 +1,250 @@
+// Copyright 2014 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 "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_restrictions.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+namespace {
+
+BrowserGpuMemoryBufferManager* g_gpu_memory_buffer_manager = nullptr;
+
+// Global atomic to generate gpu memory buffer unique IDs.
+base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id;
+
+} // namespace
+
+struct BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferRequest {
+ AllocateGpuMemoryBufferRequest(const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id)
+ : event(true, false),
+ size(size),
+ format(format),
+ usage(usage),
+ client_id(client_id) {}
+ ~AllocateGpuMemoryBufferRequest() {}
+ base::WaitableEvent event;
+ gfx::Size size;
+ gfx::GpuMemoryBuffer::Format format;
+ gfx::GpuMemoryBuffer::Usage usage;
+ int client_id;
+ scoped_ptr<gfx::GpuMemoryBuffer> result;
+};
+
+BrowserGpuMemoryBufferManager::BrowserGpuMemoryBufferManager(int gpu_client_id)
+ : gpu_client_id_(gpu_client_id) {
+ DCHECK(!g_gpu_memory_buffer_manager);
+ g_gpu_memory_buffer_manager = this;
+}
+
+BrowserGpuMemoryBufferManager::~BrowserGpuMemoryBufferManager() {
+ g_gpu_memory_buffer_manager = nullptr;
+}
+
+// static
+BrowserGpuMemoryBufferManager* BrowserGpuMemoryBufferManager::current() {
+ return g_gpu_memory_buffer_manager;
+}
+
+scoped_ptr<gfx::GpuMemoryBuffer>
+BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage) {
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ AllocateGpuMemoryBufferRequest request(size, format, usage, gpu_client_id_);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO,
+ base::Unretained(&request)));
+
+ // We're blocking the UI thread, which is generally undesirable.
+ TRACE_EVENT0("browser",
+ "BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer");
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
+ request.event.Wait();
+ return request.result.Pass();
+}
+
+void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ base::ProcessHandle child_process_handle,
+ int child_client_id,
+ const AllocationCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ gfx::GpuMemoryBufferId new_id = g_next_gpu_memory_buffer_id.GetNext();
+
+ BufferMap& buffers = clients_[child_client_id];
+ DCHECK(buffers.find(new_id) == buffers.end());
+
+ // Note: Handling of cases where the child process is removed before the
+ // allocation completes is less subtle if we set the buffer type to
+ // EMPTY_BUFFER here and verify that this has not changed when allocation
+ // completes.
+ buffers[new_id] = gfx::EMPTY_BUFFER;
+
+ GpuMemoryBufferImpl::AllocateForChildProcess(
+ new_id,
+ size,
+ format,
+ usage,
+ child_process_handle,
+ child_client_id,
+ base::Bind(&BrowserGpuMemoryBufferManager::
+ GpuMemoryBufferAllocatedForChildProcess,
+ base::Unretained(this),
+ child_process_handle,
+ child_client_id,
+ callback));
+}
+
+gfx::GpuMemoryBuffer*
+BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
+ ClientBuffer buffer) {
+ return GpuMemoryBufferImpl::FromClientBuffer(buffer);
+}
+
+void BrowserGpuMemoryBufferManager::SetDestructionSyncPoint(
+ gfx::GpuMemoryBuffer* buffer,
+ uint32 sync_point) {
+ static_cast<GpuMemoryBufferImpl*>(buffer)
+ ->set_destruction_sync_point(sync_point);
+}
+
+void BrowserGpuMemoryBufferManager::ChildProcessDeletedGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process_handle,
+ int child_client_id,
+ uint32 sync_point) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(clients_.find(child_client_id) != clients_.end());
+
+ BufferMap& buffers = clients_[child_client_id];
+
+ BufferMap::iterator buffer_it = buffers.find(id);
+ if (buffer_it == buffers.end()) {
+ LOG(ERROR) << "Invalid GpuMemoryBuffer ID for child process.";
+ return;
+ }
+
+ // This can happen if a child process managed to trigger a call to this while
+ // a buffer is in the process of being allocated.
+ if (buffer_it->second == gfx::EMPTY_BUFFER) {
+ LOG(ERROR) << "Invalid GpuMemoryBuffer type.";
+ return;
+ }
+
+ GpuMemoryBufferImpl::DeletedByChildProcess(
+ buffer_it->second, id, child_process_handle, child_client_id, sync_point);
+
+ buffers.erase(buffer_it);
+}
+
+void BrowserGpuMemoryBufferManager::ProcessRemoved(
+ base::ProcessHandle process_handle,
+ int client_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ ClientMap::iterator client_it = clients_.find(client_id);
+ if (client_it == clients_.end())
+ return;
+
+ for (auto &buffer_it : client_it->second) {
+ // This might happen if buffer is currenlty in the process of being
+ // allocated. The buffer will in that case be cleaned up when allocation
+ // completes.
+ if (buffer_it.second == gfx::EMPTY_BUFFER)
+ continue;
+
+ GpuMemoryBufferImpl::DeletedByChildProcess(buffer_it.second,
+ buffer_it.first,
+ process_handle,
+ client_id,
+ 0);
+ }
+
+ clients_.erase(client_it);
+}
+
+void BrowserGpuMemoryBufferManager::GpuMemoryBufferAllocatedForChildProcess(
+ base::ProcessHandle child_process_handle,
+ int child_client_id,
+ const AllocationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ ClientMap::iterator client_it = clients_.find(child_client_id);
+
+ // This can happen if the child process is removed while the buffer is being
+ // allocated.
+ if (client_it == clients_.end()) {
+ if (!handle.is_null()) {
+ GpuMemoryBufferImpl::DeletedByChildProcess(handle.type,
+ handle.id,
+ child_process_handle,
+ child_client_id,
+ 0);
+ }
+ callback.Run(gfx::GpuMemoryBufferHandle());
+ return;
+ }
+
+ BufferMap& buffers = client_it->second;
+
+ BufferMap::iterator buffer_it = buffers.find(handle.id);
+ DCHECK(buffer_it != buffers.end());
+ DCHECK_EQ(buffer_it->second, gfx::EMPTY_BUFFER);
+
+ if (handle.is_null()) {
+ buffers.erase(buffer_it);
+ callback.Run(gfx::GpuMemoryBufferHandle());
+ return;
+ }
+
+ // Store the type for this buffer so it can be cleaned up if the child
+ // process is removed.
+ buffer_it->second = handle.type;
+
+ callback.Run(handle);
+}
+
+// static
+void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferOnIO(
+ AllocateGpuMemoryBufferRequest* request) {
+ GpuMemoryBufferImpl::Create(
+ g_next_gpu_memory_buffer_id.GetNext(),
+ request->size,
+ request->format,
+ request->usage,
+ request->client_id,
+ base::Bind(&BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO,
+ base::Unretained(request)));
+}
+
+// static
+void BrowserGpuMemoryBufferManager::GpuMemoryBufferCreatedOnIO(
+ AllocateGpuMemoryBufferRequest* request,
+ scoped_ptr<GpuMemoryBufferImpl> buffer) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ request->result = buffer.Pass();
+ request->event.Signal();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
new file mode 100644
index 00000000000..84ad9e5c0f4
--- /dev/null
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
@@ -0,0 +1,77 @@
+// Copyright 2014 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 CONTENT_BROWSER_GPU_BROWSER_GPU_MEMORY_BUFFER_MANAGER_H_
+#define CONTENT_BROWSER_GPU_BROWSER_GPU_MEMORY_BUFFER_MANAGER_H_
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+
+namespace content {
+class GpuMemoryBufferImpl;
+
+class CONTENT_EXPORT BrowserGpuMemoryBufferManager
+ : public gpu::GpuMemoryBufferManager {
+ public:
+ typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)>
+ AllocationCallback;
+
+ explicit BrowserGpuMemoryBufferManager(int gpu_client_id);
+ ~BrowserGpuMemoryBufferManager() override;
+
+ static BrowserGpuMemoryBufferManager* current();
+
+ // Overridden from gpu::GpuMemoryBufferManager:
+ scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage) override;
+ gfx::GpuMemoryBuffer* GpuMemoryBufferFromClientBuffer(
+ ClientBuffer buffer) override;
+ void SetDestructionSyncPoint(gfx::GpuMemoryBuffer* buffer,
+ uint32 sync_point) override;
+
+ void AllocateGpuMemoryBufferForChildProcess(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ base::ProcessHandle child_process_handle,
+ int child_client_id,
+ const AllocationCallback& callback);
+ void ChildProcessDeletedGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process_handle,
+ int child_client_id,
+ uint32 sync_point);
+ void ProcessRemoved(base::ProcessHandle process_handle, int client_id);
+
+ private:
+ struct AllocateGpuMemoryBufferRequest;
+
+ void GpuMemoryBufferAllocatedForChildProcess(
+ base::ProcessHandle child_process_handle,
+ int child_client_id,
+ const AllocationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle);
+
+ static void AllocateGpuMemoryBufferOnIO(
+ AllocateGpuMemoryBufferRequest* request);
+ static void GpuMemoryBufferCreatedOnIO(
+ AllocateGpuMemoryBufferRequest* request,
+ scoped_ptr<GpuMemoryBufferImpl> buffer);
+
+ int gpu_client_id_;
+
+ typedef base::hash_map<gfx::GpuMemoryBufferId, gfx::GpuMemoryBufferType>
+ BufferMap;
+ typedef base::hash_map<int, BufferMap> ClientMap;
+ ClientMap clients_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserGpuMemoryBufferManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GPU_BROWSER_GPU_MEMORY_BUFFER_MANAGER_H_
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index 83ab50cbb29..77cf2bc5a83 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
+#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
@@ -19,17 +20,6 @@ namespace {
static bool IsGpuRasterizationBlacklisted() {
GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
- bool field_trial_enabled =
- (base::FieldTrialList::FindFullName(
- "GpuRasterizationExpandedDeviceWhitelist") == "Enabled");
-
- if (field_trial_enabled) {
- return manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION) &&
- manager->IsFeatureBlacklisted(
- gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION_FIELD_TRIAL);
- }
-
return manager->IsFeatureBlacklisted(
gpu::GPU_FEATURE_TYPE_GPU_RASTERIZATION);
}
@@ -38,6 +28,10 @@ const char* kGpuCompositingFeatureName = "gpu_compositing";
const char* kWebGLFeatureName = "webgl";
const char* kRasterizationFeatureName = "rasterization";
const char* kThreadedRasterizationFeatureName = "threaded_rasterization";
+const char* kMultipleRasterThreadsFeatureName = "multiple_raster_threads";
+
+const int kMinRasterThreads = 1;
+const int kMaxRasterThreads = 64;
struct GpuFeatureInfo {
std::string name;
@@ -48,7 +42,8 @@ struct GpuFeatureInfo {
};
const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
const GpuFeatureInfo kGpuFeatureInfo[] = {
@@ -66,7 +61,7 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
{
kGpuCompositingFeatureName,
manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING),
- false,
+ command_line.HasSwitch(switches::kDisableGpuCompositing),
"Gpu compositing has been disabled, either via about:flags or"
" command line. The browser will fall back to software compositing"
" and hardware acceleration will be unavailable.",
@@ -152,8 +147,14 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
"Threaded rasterization has not been enabled or"
" is not supported by the current system.",
false
- }
-
+ },
+ {
+ kMultipleRasterThreadsFeatureName,
+ false,
+ NumberOfRendererRasterThreads() == 1,
+ "Raster is using a single thread.",
+ false
+ },
};
DCHECK(index < arraysize(kGpuFeatureInfo));
*eof = (index == arraysize(kGpuFeatureInfo) - 1);
@@ -163,7 +164,8 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
} // namespace
bool IsPinchVirtualViewportEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
// Command line switches take precedence over platform default.
if (command_line.HasSwitch(cc::switches::kDisablePinchVirtualViewport))
@@ -171,25 +173,7 @@ bool IsPinchVirtualViewportEnabled() {
if (command_line.HasSwitch(cc::switches::kEnablePinchVirtualViewport))
return true;
-#if defined(OS_CHROMEOS)
- return true;
-#else
- return false;
-#endif
-}
-
-bool IsThreadedCompositingEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- // Command line switches take precedence over blacklist.
- if (command_line.HasSwitch(switches::kDisableThreadedCompositing))
- return false;
- if (command_line.HasSwitch(switches::kEnableThreadedCompositing))
- return true;
-
-#if defined(USE_AURA) || defined(OS_MACOSX)
- // We always want threaded compositing on Aura and Mac (the fallback is a
- // threaded software compositor).
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
return true;
#else
return false;
@@ -197,48 +181,66 @@ bool IsThreadedCompositingEnabled() {
}
bool IsDelegatedRendererEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
bool enabled = false;
-#if defined(USE_AURA)
- // Enable on Aura.
+#if defined(USE_AURA) || defined(OS_MACOSX)
+ // Enable on Aura and Mac.
enabled = true;
#endif
// Flags override.
enabled |= command_line.HasSwitch(switches::kEnableDelegatedRenderer);
enabled &= !command_line.HasSwitch(switches::kDisableDelegatedRenderer);
-
- // Needs compositing, and thread.
- if (enabled && !IsThreadedCompositingEnabled()) {
- enabled = false;
- LOG(ERROR) << "Disabling delegated-rendering because it needs "
- << "force-compositing-mode and threaded-compositing.";
- }
-
return enabled;
}
bool IsImplSidePaintingEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kDisableImplSidePainting))
- return false;
- else if (command_line.HasSwitch(switches::kEnableImplSidePainting))
- return true;
- else if (command_line.HasSwitch(
- switches::kEnableBleedingEdgeRenderingFastPaths))
+ if (command_line.HasSwitch(switches::kEnableImplSidePainting))
return true;
+ else if (command_line.HasSwitch(switches::kDisableImplSidePainting))
+ return false;
-#if defined(OS_MACOSX) || defined(OS_WIN)
- return false;
-#else
- return IsThreadedCompositingEnabled();
-#endif
+ return true;
+}
+
+int NumberOfRendererRasterThreads() {
+ int num_raster_threads = 1;
+
+ int force_num_raster_threads = ForceNumberOfRendererRasterThreads();
+ if (force_num_raster_threads)
+ num_raster_threads = force_num_raster_threads;
+
+ return num_raster_threads;
+}
+
+int ForceNumberOfRendererRasterThreads() {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ if (!command_line.HasSwitch(switches::kNumRasterThreads))
+ return 0;
+ std::string string_value =
+ command_line.GetSwitchValueASCII(switches::kNumRasterThreads);
+ int force_num_raster_threads = 0;
+ if (base::StringToInt(string_value, &force_num_raster_threads) &&
+ force_num_raster_threads >= kMinRasterThreads &&
+ force_num_raster_threads <= kMaxRasterThreads) {
+ return force_num_raster_threads;
+ } else {
+ LOG(WARNING) << "Failed to parse switch " <<
+ switches::kNumRasterThreads << ": " << string_value;
+ return 0;
+ }
}
bool IsGpuRasterizationEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (!IsImplSidePaintingEnabled())
return false;
@@ -256,7 +258,8 @@ bool IsGpuRasterizationEnabled() {
}
bool IsForceGpuRasterizationEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (!IsImplSidePaintingEnabled())
return false;
@@ -264,6 +267,13 @@ bool IsForceGpuRasterizationEnabled() {
return command_line.HasSwitch(switches::kForceGpuRasterization);
}
+bool UseSurfacesEnabled() {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+
+ return command_line.HasSwitch(switches::kUseSurfaces);
+}
+
base::Value* GetFeatureStatus() {
GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance();
std::string gpu_access_blocked_reason;
@@ -287,9 +297,9 @@ base::Value* GetFeatureStatus() {
} else if (gpu_feature_info.blocked ||
gpu_access_blocked) {
status = "unavailable";
- if (gpu_feature_info.fallback_to_software) {
+ if (gpu_feature_info.fallback_to_software)
status += "_software";
- } else
+ else
status += "_off";
} else {
status = "enabled";
@@ -300,13 +310,14 @@ base::Value* GetFeatureStatus() {
if (IsForceGpuRasterizationEnabled())
status += "_force";
}
- if (gpu_feature_info.name == kThreadedRasterizationFeatureName)
+ if (gpu_feature_info.name == kMultipleRasterThreadsFeatureName) {
+ if (ForceNumberOfRendererRasterThreads() > 0)
+ status += "_force";
+ }
+ if (gpu_feature_info.name == kThreadedRasterizationFeatureName ||
+ gpu_feature_info.name == kMultipleRasterThreadsFeatureName)
status += "_on";
}
- if (gpu_feature_info.name == kGpuCompositingFeatureName) {
- if (IsThreadedCompositingEnabled())
- status += "_threaded";
- }
if (gpu_feature_info.name == kWebGLFeatureName &&
(gpu_feature_info.blocked || gpu_access_blocked) &&
manager->ShouldUseSwiftShader()) {
diff --git a/chromium/content/browser/gpu/compositor_util.h b/chromium/content/browser/gpu/compositor_util.h
index 72a3ac0d42d..b26bb94968a 100644
--- a/chromium/content/browser/gpu/compositor_util.h
+++ b/chromium/content/browser/gpu/compositor_util.h
@@ -17,9 +17,6 @@ namespace content {
// flags, or platform default).
CONTENT_EXPORT bool IsPinchVirtualViewportEnabled();
-// Returns true if the threaded compositor is on (via flags or field trial).
-CONTENT_EXPORT bool IsThreadedCompositingEnabled();
-
// Returns true if delegated-renderer is on (via flags, or platform default).
CONTENT_EXPORT bool IsDelegatedRendererEnabled();
@@ -33,6 +30,16 @@ CONTENT_EXPORT bool IsGpuRasterizationEnabled();
// Returns true if force-gpu-rasterization is on (via flags) for the renderer.
CONTENT_EXPORT bool IsForceGpuRasterizationEnabled();
+// Returns the number of raster threads to use for compositing.
+CONTENT_EXPORT int NumberOfRendererRasterThreads();
+
+// Returns the number of raster threads to use for compositing that are forced
+// by the command line.
+CONTENT_EXPORT int ForceNumberOfRendererRasterThreads();
+
+// Returns true if using cc Surfaces is allowed.
+CONTENT_EXPORT bool UseSurfacesEnabled();
+
CONTENT_EXPORT base::Value* GetFeatureStatus();
CONTENT_EXPORT base::Value* GetProblems();
CONTENT_EXPORT base::Value* GetDriverBugWorkarounds();
diff --git a/chromium/content/browser/gpu/compositor_util_browsertest.cc b/chromium/content/browser/gpu/compositor_util_browsertest.cc
index 1f3b9f3f576..550d7773c0a 100644
--- a/chromium/content/browser/gpu/compositor_util_browsertest.cc
+++ b/chromium/content/browser/gpu/compositor_util_browsertest.cc
@@ -15,37 +15,19 @@ namespace content {
typedef ContentBrowserTest CompositorUtilTest;
-// Test that threaded compositing and FCM are in the expected mode on the bots
-// for all platforms.
+// Test that compositing is in the expected mode on the bots for all platforms.
IN_PROC_BROWSER_TEST_F(CompositorUtilTest, CompositingModeAsExpected) {
enum CompositingMode {
- DISABLED,
- ENABLED,
- THREADED, // Implies FCM
- DELEGATED, // Implies threaded
- } expected_mode = DISABLED;
-#if defined(USE_AURA)
- expected_mode = DELEGATED;
-#elif defined(OS_ANDROID)
+ DIRECT,
+ DELEGATED,
+ } expected_mode = DIRECT;
+#if defined(USE_AURA) || defined(OS_ANDROID)
expected_mode = DELEGATED;
#elif defined(OS_MACOSX)
- expected_mode = THREADED;
- // Lion and SnowLeopard have compositing blacklisted when using the Apple
- // software renderer, so results will vary depending if this test is being
- // run in a VM versus actual hardware.
- // http://crbug.com/230931
- if (base::mac::IsOSLionOrEarlier())
- return;
-#elif defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_VISTA)
- expected_mode = THREADED;
+ expected_mode = DELEGATED;
#endif
- EXPECT_EQ(expected_mode == THREADED ||
- expected_mode == DELEGATED,
- IsThreadedCompositingEnabled());
- EXPECT_EQ(expected_mode == DELEGATED,
- IsDelegatedRendererEnabled());
+ EXPECT_EQ(expected_mode == DELEGATED, IsDelegatedRendererEnabled());
}
}
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 93d15c71108..3e24bb5be2d 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -55,6 +55,11 @@ void GpuDataManagerImpl::RequestCompleteGpuInfoIfNeeded() {
private_->RequestCompleteGpuInfoIfNeeded();
}
+bool GpuDataManagerImpl::IsEssentialGpuInfoAvailable() const {
+ base::AutoLock auto_lock(lock_);
+ return private_->IsEssentialGpuInfoAvailable();
+}
+
bool GpuDataManagerImpl::IsCompleteGpuInfoAvailable() const {
base::AutoLock auto_lock(lock_);
return private_->IsCompleteGpuInfoAvailable();
@@ -76,6 +81,11 @@ void GpuDataManagerImpl::RegisterSwiftShaderPath(
private_->RegisterSwiftShaderPath(path);
}
+bool GpuDataManagerImpl::ShouldUseWarp() const {
+ base::AutoLock auto_lock(lock_);
+ return private_->ShouldUseWarp();
+}
+
void GpuDataManagerImpl::AddObserver(
GpuDataManagerObserver* observer) {
base::AutoLock auto_lock(lock_);
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.h b/chromium/content/browser/gpu/gpu_data_manager_impl.h
index 5a783e46c75..981ad7a85b6 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -23,7 +23,6 @@
#include "gpu/config/gpu_info.h"
class GURL;
-struct WebPreferences;
namespace base {
class CommandLine;
@@ -32,6 +31,7 @@ class CommandLine;
namespace content {
class GpuDataManagerImplPrivate;
+struct WebPreferences;
class CONTENT_EXPORT GpuDataManagerImpl
: public NON_EXPORTED_BASE(GpuDataManager) {
@@ -58,31 +58,32 @@ class CONTENT_EXPORT GpuDataManagerImpl
static GpuDataManagerImpl* GetInstance();
// GpuDataManager implementation.
- virtual void InitializeForTesting(
- const std::string& gpu_blacklist_json,
- const gpu::GPUInfo& gpu_info) OVERRIDE;
- virtual bool IsFeatureBlacklisted(int feature) const OVERRIDE;
- virtual gpu::GPUInfo GetGPUInfo() const OVERRIDE;
- virtual void GetGpuProcessHandles(
- const GetGpuProcessHandlesCallback& callback) const OVERRIDE;
- virtual bool GpuAccessAllowed(std::string* reason) const OVERRIDE;
- virtual void RequestCompleteGpuInfoIfNeeded() OVERRIDE;
- virtual bool IsCompleteGpuInfoAvailable() const OVERRIDE;
- virtual void RequestVideoMemoryUsageStatsUpdate() const OVERRIDE;
- virtual bool ShouldUseSwiftShader() const OVERRIDE;
- virtual void RegisterSwiftShaderPath(const base::FilePath& path) OVERRIDE;
- virtual void AddObserver(GpuDataManagerObserver* observer) OVERRIDE;
- virtual void RemoveObserver(GpuDataManagerObserver* observer) OVERRIDE;
- virtual void UnblockDomainFrom3DAPIs(const GURL& url) OVERRIDE;
- virtual void DisableGpuWatchdog() OVERRIDE;
- virtual void SetGLStrings(const std::string& gl_vendor,
- const std::string& gl_renderer,
- const std::string& gl_version) OVERRIDE;
- virtual void GetGLStrings(std::string* gl_vendor,
- std::string* gl_renderer,
- std::string* gl_version) OVERRIDE;
- virtual void DisableHardwareAcceleration() OVERRIDE;
- virtual bool CanUseGpuBrowserCompositor() const OVERRIDE;
+ void InitializeForTesting(const std::string& gpu_blacklist_json,
+ const gpu::GPUInfo& gpu_info) override;
+ bool IsFeatureBlacklisted(int feature) const override;
+ gpu::GPUInfo GetGPUInfo() const override;
+ void GetGpuProcessHandles(
+ const GetGpuProcessHandlesCallback& callback) const override;
+ bool GpuAccessAllowed(std::string* reason) const override;
+ void RequestCompleteGpuInfoIfNeeded() override;
+ bool IsEssentialGpuInfoAvailable() const override;
+ bool IsCompleteGpuInfoAvailable() const override;
+ void RequestVideoMemoryUsageStatsUpdate() const override;
+ bool ShouldUseSwiftShader() const override;
+ void RegisterSwiftShaderPath(const base::FilePath& path) override;
+ bool ShouldUseWarp() const override;
+ void AddObserver(GpuDataManagerObserver* observer) override;
+ void RemoveObserver(GpuDataManagerObserver* observer) override;
+ void UnblockDomainFrom3DAPIs(const GURL& url) override;
+ void DisableGpuWatchdog() override;
+ void SetGLStrings(const std::string& gl_vendor,
+ const std::string& gl_renderer,
+ const std::string& gl_version) override;
+ void GetGLStrings(std::string* gl_vendor,
+ std::string* gl_renderer,
+ std::string* gl_version) override;
+ void DisableHardwareAcceleration() override;
+ bool CanUseGpuBrowserCompositor() const override;
// This collects preliminary GPU info, load GpuBlacklist, and compute the
// preliminary blacklisted features; it should only be called at browser
@@ -205,7 +206,7 @@ class CONTENT_EXPORT GpuDataManagerImpl
};
GpuDataManagerImpl();
- virtual ~GpuDataManagerImpl();
+ ~GpuDataManagerImpl() override;
mutable base::Lock lock_;
scoped_ptr<GpuDataManagerImplPrivate> private_;
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
index 2c5b91e0142..f71a62c8652 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -23,6 +23,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/web_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_control_list_jsons.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
@@ -33,7 +34,6 @@
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gpu_switching_manager.h"
-#include "webkit/common/webpreferences.h"
#if defined(OS_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
@@ -113,7 +113,8 @@ void UpdateStats(const gpu::GPUInfo& gpu_info,
return;
}
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
bool disabled = false;
// Use entry 0 to capture the total number of times that data
@@ -138,9 +139,9 @@ void UpdateStats(const gpu::GPUInfo& gpu_info,
std::vector<uint32> flag_disabled_entries;
disabled = true;
blacklist->GetDecisionEntries(&flag_disabled_entries, disabled);
- for (size_t i = 0; i < flag_disabled_entries.size(); ++i) {
+ for (uint32 disabled_entry : flag_disabled_entries) {
UMA_HISTOGRAM_ENUMERATION("GPU.BlacklistTestResultsPerDisabledEntry",
- flag_disabled_entries[i], max_entry_id + 1);
+ disabled_entry, max_entry_id + 1);
}
const gpu::GpuFeatureType kGpuFeatures[] = {
@@ -225,7 +226,7 @@ void DisplayReconfigCallback(CGDirectDisplayID display,
bool gpu_changed = false;
if (flags & kCGDisplayAddFlag) {
uint32 vendor_id, device_id;
- if (gpu::CollectGpuID(&vendor_id, &device_id) == gpu::kGpuIDSuccess) {
+ if (gpu::CollectGpuID(&vendor_id, &device_id) == gpu::kCollectInfoSuccess) {
gpu_changed = manager->UpdateActiveGpu(vendor_id, device_id);
}
}
@@ -235,81 +236,6 @@ void DisplayReconfigCallback(CGDirectDisplayID display,
}
#endif // OS_MACOSX
-#if defined(OS_ANDROID)
-void ApplyAndroidWorkarounds(const gpu::GPUInfo& gpu_info,
- CommandLine* command_line,
- std::set<int>* workarounds) {
- std::string vendor(StringToLowerASCII(gpu_info.gl_vendor));
- std::string renderer(StringToLowerASCII(gpu_info.gl_renderer));
- std::string version(StringToLowerASCII(gpu_info.gl_version));
-
- bool is_img =
- gpu_info.gl_vendor.find("Imagination") != std::string::npos;
-
- gfx::DeviceDisplayInfo info;
- int default_tile_size = 256;
-
- // TODO(epenner): Now that this is somewhat generic, maybe we can
- // unify this for all platforms (http://crbug.com/159524)
-
- bool real_size_supported = true;
- int display_width = info.GetPhysicalDisplayWidth();
- int display_height = info.GetPhysicalDisplayHeight();
- if (display_width == 0 || display_height == 0) {
- real_size_supported = false;
- display_width = info.GetDisplayWidth();
- display_height = info.GetDisplayHeight();
- }
-
- int portrait_width = std::min(display_width, display_height);
- int landscape_width = std::max(display_width, display_height);
-
- if (real_size_supported) {
- // Maximum HD dimensions should be 768x1280
- // Maximum FHD dimensions should be 1200x1920
- if (portrait_width > 768 || landscape_width > 1280)
- default_tile_size = 384;
- if (portrait_width > 1200 || landscape_width > 1920)
- default_tile_size = 512;
-
- // Adjust for some resolutions that barely straddle an extra
- // tile when in portrait mode. This helps worst case scroll/raster
- // by not needing a full extra tile for each row.
- if (default_tile_size == 256 && portrait_width == 768)
- default_tile_size += 32;
- if (default_tile_size == 384 && portrait_width == 1200)
- default_tile_size += 32;
- } else {
- // We don't know the exact resolution due to screen controls etc.
- // So this just estimates the values above using tile counts.
- int numTiles = (display_width * display_height) / (256 * 256);
- if (numTiles > 16)
- default_tile_size = 384;
- if (numTiles >= 40)
- default_tile_size = 512;
- }
-
- // IMG: Fast async texture uploads only work with non-power-of-two,
- // but still multiple-of-eight sizes.
- // http://crbug.com/168099
- if (is_img)
- default_tile_size -= 8;
-
- // Set the command line if it isn't already set and we changed
- // the default tile size.
- if (default_tile_size != 256 &&
- !command_line->HasSwitch(switches::kDefaultTileWidth) &&
- !command_line->HasSwitch(switches::kDefaultTileHeight)) {
- std::stringstream size;
- size << default_tile_size;
- command_line->AppendSwitchASCII(
- switches::kDefaultTileWidth, size.str());
- command_line->AppendSwitchASCII(
- switches::kDefaultTileHeight, size.str());
- }
-}
-#endif // OS_ANDROID
-
// Block all domains' use of 3D APIs for this many milliseconds if
// approaching a threshold where system stability might be compromised.
const int64 kBlockAllDomainsMs = 10000;
@@ -340,12 +266,12 @@ void GpuDataManagerImplPrivate::InitializeForTesting(
bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
#if defined(OS_CHROMEOS)
if (feature == gpu::GPU_FEATURE_TYPE_PANEL_FITTING &&
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisablePanelFitting)) {
return true;
}
#endif // OS_CHROMEOS
- if (use_swiftshader_) {
+ if (use_swiftshader_ || ShouldUseWarp()) {
// Skia's software rendering is probably more efficient than going through
// software emulation of the GPU, so use that.
if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
@@ -361,7 +287,7 @@ bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
}
size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
- if (use_swiftshader_)
+ if (use_swiftshader_ || ShouldUseWarp())
return 1;
return blacklisted_features_.size();
}
@@ -385,7 +311,7 @@ void GpuDataManagerImplPrivate::GetGpuProcessHandles(
bool GpuDataManagerImplPrivate::GpuAccessAllowed(
std::string* reason) const {
- if (use_swiftshader_)
+ if (use_swiftshader_ || ShouldUseWarp())
return true;
if (!gpu_process_accessible_) {
@@ -398,7 +324,7 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(
if (card_blacklisted_) {
if (reason) {
*reason = "GPU access is disabled ";
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableGpu))
*reason += "through commandline switch --disable-gpu.";
else
@@ -437,7 +363,7 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(
}
void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
- if (complete_gpu_info_already_requested_ || gpu_info_.finalized)
+ if (complete_gpu_info_already_requested_ || IsCompleteGpuInfoAvailable())
return;
complete_gpu_info_already_requested_ = true;
@@ -451,8 +377,20 @@ void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
new GpuMsg_CollectGraphicsInfo());
}
+bool GpuDataManagerImplPrivate::IsEssentialGpuInfoAvailable() const {
+ if (gpu_info_.basic_info_state == gpu::kCollectInfoNone ||
+ gpu_info_.context_info_state == gpu::kCollectInfoNone) {
+ return false;
+ }
+ return true;
+}
+
bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
- return gpu_info_.finalized;
+#if defined(OS_WIN)
+ if (gpu_info_.dx_diagnostics_info_state == gpu::kCollectInfoNone)
+ return false;
+#endif
+ return IsEssentialGpuInfoAvailable();
}
void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
@@ -472,6 +410,11 @@ void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
EnableSwiftShaderIfNecessary();
}
+bool GpuDataManagerImplPrivate::ShouldUseWarp() const {
+ return use_warp_ ||
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseWarp);
+}
+
void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
GpuDataManagerImpl::UnlockedSession session(owner_);
observer_list_->AddObserver(observer);
@@ -552,7 +495,8 @@ void GpuDataManagerImplPrivate::Initialize() {
return;
}
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
return;
@@ -576,9 +520,13 @@ void GpuDataManagerImplPrivate::Initialize() {
gpu::CollectBasicGraphicsInfo(&gpu_info);
}
#if defined(ARCH_CPU_X86_FAMILY)
- if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id)
- gpu_info.finalized = true;
-#endif
+ if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id) {
+ gpu_info.context_info_state = gpu::kCollectInfoNonFatalFailure;
+#if defined(OS_WIN)
+ gpu_info.dx_diagnostics_info_state = gpu::kCollectInfoNonFatalFailure;
+#endif // OS_WIN
+ }
+#endif // ARCH_CPU_X86_FAMILY
std::string gpu_blacklist_string;
std::string gpu_driver_bug_list_string;
@@ -610,7 +558,7 @@ void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
}
gpu::GpuDriverBugList::AppendWorkaroundsFromCommandLine(
- &gpu_driver_bugs_, *CommandLine::ForCurrentProcess());
+ &gpu_driver_bugs_, *base::CommandLine::ForCurrentProcess());
// We have to update GpuFeatureType before notify all the observers.
NotifyGpuInfoUpdate();
@@ -618,12 +566,12 @@ void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
// No further update of gpu_info if falling back to SwiftShader.
- if (use_swiftshader_)
+ if (use_swiftshader_ || ShouldUseWarp())
return;
gpu::MergeGPUInfo(&gpu_info_, gpu_info);
- complete_gpu_info_already_requested_ =
- complete_gpu_info_already_requested_ || gpu_info_.finalized;
+ if (IsCompleteGpuInfoAvailable())
+ complete_gpu_info_already_requested_ = true;
UpdateGpuInfoHelper();
}
@@ -636,7 +584,7 @@ void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
}
void GpuDataManagerImplPrivate::AppendRendererCommandLine(
- CommandLine* command_line) const {
+ base::CommandLine* command_line) const {
DCHECK(command_line);
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
@@ -655,13 +603,14 @@ void GpuDataManagerImplPrivate::AppendRendererCommandLine(
}
void GpuDataManagerImplPrivate::AppendGpuCommandLine(
- CommandLine* command_line) const {
+ base::CommandLine* command_line) const {
DCHECK(command_line);
std::string use_gl =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kUseGL);
base::FilePath swiftshader_path =
- CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kSwiftShaderPath);
if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
command_line->AppendSwitch(switches::kDisableD3D11);
@@ -717,10 +666,13 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
gpu_info_.driver_vendor);
command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
gpu_info_.driver_version);
+
+ if (ShouldUseWarp())
+ command_line->AppendSwitch(switches::kUseWarp);
}
void GpuDataManagerImplPrivate::AppendPluginCommandLine(
- CommandLine* command_line) const {
+ base::CommandLine* command_line) const {
DCHECK(command_line);
#if defined(OS_MACOSX)
@@ -767,7 +719,7 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
#endif
if (!IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE) &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableAcceleratedVideoDecode)) {
prefs->pepper_accelerated_video_decode_enabled = true;
}
@@ -779,6 +731,7 @@ void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i)
blacklisted_features_.insert(i);
+ EnableWarpIfNecessary();
EnableSwiftShaderIfNecessary();
NotifyGpuInfoUpdate();
}
@@ -832,6 +785,7 @@ void GpuDataManagerImplPrivate::ProcessCrashed(
return;
}
{
+ gpu_info_.process_crash_count = GpuProcessHost::gpu_crash_count();
GpuDataManagerImpl::UnlockedSession session(owner_);
observer_list_->Notify(
&GpuDataManagerObserver::OnGpuProcessCrashed, exit_code);
@@ -852,7 +806,13 @@ base::ListValue* GpuDataManagerImplPrivate::GetLogMessages() const {
void GpuDataManagerImplPrivate::HandleGpuSwitch() {
GpuDataManagerImpl::UnlockedSession session(owner_);
- observer_list_->Notify(&GpuDataManagerObserver::OnGpuSwitching);
+ // Notify observers in the browser process.
+ ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
+ // Pass the notification to the GPU process to notify observers there.
+ GpuProcessHost::SendOnIO(
+ GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
+ new GpuMsg_GpuSwitched);
}
bool GpuDataManagerImplPrivate::UpdateActiveGpu(
@@ -884,6 +844,11 @@ bool GpuDataManagerImplPrivate::UpdateActiveGpu(
}
bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuCompositing))
+ return false;
+ if (ShouldUseWarp())
+ return true;
if (ShouldUseSwiftShader())
return false;
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING))
@@ -930,6 +895,7 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
: complete_gpu_info_already_requested_(false),
observer_list_(new GpuDataManagerObserverList),
use_swiftshader_(false),
+ use_warp_(false),
card_blacklisted_(false),
update_histograms_(true),
window_count_(0),
@@ -939,7 +905,8 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
gpu_process_accessible_(true),
finalized_(false) {
DCHECK(owner_);
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableGpu))
DisableHardwareAcceleration();
@@ -965,7 +932,7 @@ void GpuDataManagerImplPrivate::InitializeImpl(
const std::string& gpu_driver_bug_list_json,
const gpu::GPUInfo& gpu_info) {
const bool log_gpu_control_list_decisions =
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kLogGpuControlListDecisions);
if (!gpu_blacklist_json.empty()) {
@@ -989,11 +956,6 @@ void GpuDataManagerImplPrivate::InitializeImpl(
UpdateGpuInfo(gpu_info);
UpdateGpuSwitchingManager(gpu_info);
UpdatePreliminaryBlacklistedFeatures();
-
-#if defined(OS_ANDROID)
- ApplyAndroidWorkarounds(
- gpu_info, CommandLine::ForCurrentProcess(), &gpu_driver_bugs_);
-#endif // OS_ANDROID
}
void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
@@ -1007,6 +969,7 @@ void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL);
}
+ EnableWarpIfNecessary();
EnableSwiftShaderIfNecessary();
}
@@ -1032,15 +995,34 @@ void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
}
void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
+ if (ShouldUseWarp())
+ return;
+
if (!GpuAccessAllowed(NULL) ||
blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) {
if (!swiftshader_path_.empty() &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableSoftwareRasterizer))
use_swiftshader_ = true;
}
}
+void GpuDataManagerImplPrivate::EnableWarpIfNecessary() {
+#if defined(OS_WIN)
+ if (use_warp_)
+ return;
+ // We should only use WARP if we are unable to use the regular GPU for
+ // compositing, and if we in Metro mode.
+ use_warp_ =
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kViewerConnect) &&
+ !CanUseGpuBrowserCompositor();
+#endif
+}
+
+void GpuDataManagerImplPrivate::ForceWarpModeForTesting() {
+ use_warp_ = true;
+}
+
std::string GpuDataManagerImplPrivate::GetDomainFromURL(
const GURL& url) const {
// For the moment, we just use the host, or its IP address, as the
@@ -1148,7 +1130,10 @@ void GpuDataManagerImplPrivate::Notify3DAPIBlocked(const GURL& url,
void GpuDataManagerImplPrivate::OnGpuProcessInitFailure() {
gpu_process_accessible_ = false;
- gpu_info_.finalized = true;
+ gpu_info_.context_info_state = gpu::kCollectInfoFatalFailure;
+#if defined(OS_WIN)
+ gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoFatalFailure;
+#endif
complete_gpu_info_already_requested_ = true;
// Some observers might be waiting.
NotifyGpuInfoUpdate();
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
index 8e5514fad31..b3466c14ca5 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -38,10 +38,12 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
const GpuDataManager::GetGpuProcessHandlesCallback& callback) const;
bool GpuAccessAllowed(std::string* reason) const;
void RequestCompleteGpuInfoIfNeeded();
+ bool IsEssentialGpuInfoAvailable() const;
bool IsCompleteGpuInfoAvailable() const;
void RequestVideoMemoryUsageStatsUpdate() const;
bool ShouldUseSwiftShader() const;
void RegisterSwiftShaderPath(const base::FilePath& path);
+ bool ShouldUseWarp() const;
void AddObserver(GpuDataManagerObserver* observer);
void RemoveObserver(GpuDataManagerObserver* observer);
void UnblockDomainFrom3DAPIs(const GURL& url);
@@ -127,6 +129,8 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
SwiftShaderRendering2);
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
+ WarpEnabledOverridesSwiftShader);
+ FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
GpuInfoUpdate);
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
NoGpuInfoUpdateWithSwiftShader);
@@ -201,6 +205,13 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// Try to switch to SwiftShader rendering, if possible and necessary.
void EnableSwiftShaderIfNecessary();
+ // Try to switch to WARP rendering if the GPU hardware is not supported or
+ // absent, and if we are trying to run in Windows Metro mode.
+ void EnableWarpIfNecessary();
+
+ // Use only for testing, forces |use_warp_| to true.
+ void ForceWarpModeForTesting();
+
// Helper to extract the domain from a given URL.
std::string GetDomainFromURL(const GURL& url) const;
@@ -231,6 +242,8 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
bool use_swiftshader_;
+ bool use_warp_;
+
base::FilePath swiftshader_path_;
// Current card force-blacklisted due to GPU crashes, or disabled through
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
index 8955ce1f88d..8bcb01052e7 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -14,6 +14,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
#define LONG_STRING_CONST(...) #__VA_ARGS__
namespace content {
@@ -25,19 +29,17 @@ class TestObserver : public GpuDataManagerObserver {
: gpu_info_updated_(false),
video_memory_usage_stats_updated_(false) {
}
- virtual ~TestObserver() { }
+ ~TestObserver() override {}
bool gpu_info_updated() const { return gpu_info_updated_; }
bool video_memory_usage_stats_updated() const {
return video_memory_usage_stats_updated_;
}
- virtual void OnGpuInfoUpdate() OVERRIDE {
- gpu_info_updated_ = true;
- }
+ void OnGpuInfoUpdate() override { gpu_info_updated_ = true; }
- virtual void OnVideoMemoryUsageStatsUpdate(
- const GPUVideoMemoryUsageStats& stats) OVERRIDE {
+ void OnVideoMemoryUsageStatsUpdate(
+ const GPUVideoMemoryUsageStats& stats) override {
video_memory_usage_stats_updated_ = true;
}
@@ -69,7 +71,7 @@ class GpuDataManagerImplPrivateTest : public testing::Test {
public:
GpuDataManagerImplPrivateTest() { }
- virtual ~GpuDataManagerImplPrivateTest() { }
+ ~GpuDataManagerImplPrivateTest() override {}
protected:
// scoped_ptr doesn't work with GpuDataManagerImpl because its
@@ -115,11 +117,9 @@ class GpuDataManagerImplPrivateTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(ScopedGpuDataManagerImplPrivate);
};
- virtual void SetUp() {
- }
+ void SetUp() override {}
- virtual void TearDown() {
- }
+ void TearDown() override {}
base::Time JustBeforeExpiration(const GpuDataManagerImplPrivate* manager);
base::Time JustAfterExpiration(const GpuDataManagerImplPrivate* manager);
@@ -158,10 +158,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuSideBlacklisting) {
},
{
"id": 2,
- "gl_renderer": {
- "op": "contains",
- "value": "GeForce"
- },
+ "gl_renderer": ".*GeForce.*",
"features": [
"accelerated_2d_canvas"
]
@@ -205,10 +202,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) {
"id": 1,
"exceptions": [
{
- "gl_renderer": {
- "op": "contains",
- "value": "GeForce"
- }
+ "gl_renderer": ".*GeForce.*"
}
],
"features": [
@@ -290,6 +284,22 @@ TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) {
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
}
+TEST_F(GpuDataManagerImplPrivateTest, WarpEnabledOverridesSwiftShader) {
+ // If WARP fallback is enabled on Windows 8 it should not allow SwiftShader
+ // to be enabled.
+#if defined(OS_WIN)
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ ScopedGpuDataManagerImplPrivate manager;
+ manager->ForceWarpModeForTesting();
+ const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
+ manager->RegisterSwiftShaderPath(test_path);
+ manager->DisableHardwareAcceleration();
+ EXPECT_TRUE(manager->ShouldUseWarp());
+ EXPECT_FALSE(manager->ShouldUseSwiftShader());
+ }
+#endif
+}
+
TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) {
ScopedGpuDataManagerImpl manager;
@@ -601,7 +611,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) {
ScopedGpuDataManagerImplPrivate manager;
manager->gpu_driver_bugs_.insert(5);
- CommandLine command_line(0, NULL);
+ base::CommandLine command_line(0, NULL);
manager->AppendGpuCommandLine(&command_line);
EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
@@ -615,7 +625,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) {
manager->gpu_driver_bugs_.insert(5);
manager->gpu_driver_bugs_.insert(7);
- CommandLine command_line(0, NULL);
+ base::CommandLine command_line(0, NULL);
manager->AppendGpuCommandLine(&command_line);
EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index 997911656e7..4eb492696c5 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -4,11 +4,16 @@
#include "content/browser/gpu/gpu_internals_ui.h"
+#if defined(OS_LINUX) && defined(USE_X11)
+#include <X11/Xlib.h>
+#endif
+
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/environment.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
@@ -16,6 +21,7 @@
#include "base/values.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/browser/web_contents.h"
@@ -27,13 +33,18 @@
#include "content/public/common/url_constants.h"
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_info.h"
-#include "grit/content_resources.h"
#include "third_party/angle/src/common/version.h"
+#include "ui/gl/gpu_switching_manager.h"
#if defined(OS_WIN)
#include "ui/base/win/shell.h"
#endif
+#if defined(OS_LINUX) && defined(USE_X11)
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_atom_cache.h"
+#endif
+
namespace content {
namespace {
@@ -127,6 +138,10 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
ui::win::IsAeroGlassEnabled() ? "Aero Glass" : "none";
basic_info->Append(
NewDescriptionValuePair("Desktop compositing", compositor));
+ if (GpuDataManagerImpl::GetInstance()->ShouldUseWarp()) {
+ basic_info->Append(NewDescriptionValuePair("Using WARP",
+ new base::FundamentalValue(true)));
+ }
#endif
basic_info->Append(
@@ -157,6 +172,30 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
gpu_info.gl_ws_version));
basic_info->Append(NewDescriptionValuePair("Window system binding extensions",
gpu_info.gl_ws_extensions));
+#if defined(OS_LINUX) && defined(USE_X11)
+ basic_info->Append(NewDescriptionValuePair("Window manager",
+ ui::GuessWindowManagerName()));
+ {
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ std::string value;
+ const char kXDGCurrentDesktop[] = "XDG_CURRENT_DESKTOP";
+ if (env->GetVar(kXDGCurrentDesktop, &value))
+ basic_info->Append(NewDescriptionValuePair(kXDGCurrentDesktop, value));
+ const char kGDMSession[] = "GDMSESSION";
+ if (env->GetVar(kGDMSession, &value))
+ basic_info->Append(NewDescriptionValuePair(kGDMSession, value));
+ const char* kAtomsToCache[] = {
+ "_NET_WM_CM_S0",
+ NULL
+ };
+ ui::X11AtomCache atom_cache(gfx::GetXDisplay(), kAtomsToCache);
+ std::string compositing_manager = XGetSelectionOwner(
+ gfx::GetXDisplay(),
+ atom_cache.GetAtom("_NET_WM_CM_S0")) != None ? "Yes" : "No";
+ basic_info->Append(
+ NewDescriptionValuePair("Compositing manager", compositing_manager));
+ }
+#endif
std::string direct_rendering = gpu_info.direct_rendering ? "Yes" : "No";
basic_info->Append(
NewDescriptionValuePair("Direct rendering", direct_rendering));
@@ -166,6 +205,10 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
basic_info->Append(NewDescriptionValuePair(
"Reset notification strategy", reset_strategy));
+ basic_info->Append(NewDescriptionValuePair(
+ "GPU process crash count",
+ new base::FundamentalValue(gpu_info.process_crash_count)));
+
base::DictionaryValue* info = new base::DictionaryValue();
info->Set("basic_info", basic_info);
@@ -197,17 +240,20 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
class GpuMessageHandler
: public WebUIMessageHandler,
public base::SupportsWeakPtr<GpuMessageHandler>,
- public GpuDataManagerObserver {
+ public GpuDataManagerObserver,
+ public ui::GpuSwitchingObserver {
public:
GpuMessageHandler();
- virtual ~GpuMessageHandler();
+ ~GpuMessageHandler() override;
// WebUIMessageHandler implementation.
- virtual void RegisterMessages() OVERRIDE;
+ void RegisterMessages() override;
// GpuDataManagerObserver implementation.
- virtual void OnGpuInfoUpdate() OVERRIDE;
- virtual void OnGpuSwitching() OVERRIDE;
+ void OnGpuInfoUpdate() override;
+
+ // ui::GpuSwitchingObserver implementation.
+ void OnGpuSwitched() override;
// Messages
void OnBrowserBridgeInitialized(const base::ListValue* list);
@@ -236,6 +282,7 @@ GpuMessageHandler::GpuMessageHandler()
}
GpuMessageHandler::~GpuMessageHandler() {
+ ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
}
@@ -303,8 +350,10 @@ void GpuMessageHandler::OnBrowserBridgeInitialized(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Watch for changes in GPUInfo
- if (!observing_)
+ if (!observing_) {
GpuDataManagerImpl::GetInstance()->AddObserver(this);
+ ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
+ }
observing_ = true;
// Tell GpuDataManager it should have full GpuInfo. If the
@@ -324,7 +373,7 @@ base::Value* GpuMessageHandler::OnRequestClientInfo(
dict->SetString("version", GetContentClient()->GetProduct());
dict->SetString("command_line",
- CommandLine::ForCurrentProcess()->GetCommandLineString());
+ base::CommandLine::ForCurrentProcess()->GetCommandLineString());
dict->SetString("operating_system",
base::SysInfo::OperatingSystemName() + " " +
base::SysInfo::OperatingSystemVersion());
@@ -361,7 +410,7 @@ void GpuMessageHandler::OnGpuInfoUpdate() {
*(gpu_info_val.get()));
}
-void GpuMessageHandler::OnGpuSwitching() {
+void GpuMessageHandler::OnGpuSwitched() {
GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded();
}
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index cbe45393419..dd78ba6017d 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -25,7 +25,7 @@ const content::CauseForGpuLaunch kInitCause =
class ContextTestBase : public content::ContentBrowserTest {
public:
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
if (!content::BrowserGpuChannelHostFactory::CanUseForTesting())
return;
@@ -47,12 +47,12 @@ class ContextTestBase : public content::ContentBrowserTest {
WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
NULL));
CHECK(context_.get());
- context_->makeContextCurrent();
+ context_->InitializeOnCurrentThread();
context_support_ = context_->GetContextSupport();
ContentBrowserTest::SetUpOnMainThread();
}
- virtual void TearDownOnMainThread() OVERRIDE {
+ void TearDownOnMainThread() override {
// Must delete the context first.
context_.reset(NULL);
ContentBrowserTest::TearDownOnMainThread();
@@ -73,7 +73,7 @@ namespace content {
class BrowserGpuChannelHostFactoryTest : public ContentBrowserTest {
public:
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
if (!BrowserGpuChannelHostFactory::CanUseForTesting())
return;
@@ -161,7 +161,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
kInitCause,
base::Bind(&BrowserGpuChannelHostFactoryTest::Signal, &event));
EXPECT_TRUE(event);
- EXPECT_EQ(gpu_channel, GetGpuChannel());
+ EXPECT_EQ(gpu_channel.get(), GetGpuChannel());
}
// Fails since UI Compositor establishes a GpuChannel.
diff --git a/chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.cc b/chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.cc
new file mode 100644
index 00000000000..e57bd0c728c
--- /dev/null
+++ b/chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.cc
@@ -0,0 +1,94 @@
+// Copyright (c) 2014 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 "content/browser/gpu/gpu_memory_buffer_factory_host_impl.h"
+
+#include "base/bind.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+namespace content {
+
+GpuMemoryBufferFactoryHostImpl::GpuMemoryBufferFactoryHostImpl()
+ : gpu_host_id_(0), next_create_gpu_memory_buffer_request_id_(0) {
+}
+
+GpuMemoryBufferFactoryHostImpl::~GpuMemoryBufferFactoryHostImpl() {
+}
+
+void GpuMemoryBufferFactoryHostImpl::CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id,
+ const CreateGpuMemoryBufferCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
+ if (!host) {
+ callback.Run(gfx::GpuMemoryBufferHandle());
+ return;
+ }
+
+ uint32 request_id = next_create_gpu_memory_buffer_request_id_++;
+ create_gpu_memory_buffer_requests_[request_id] = callback;
+
+ host->CreateGpuMemoryBuffer(
+ type,
+ id,
+ size,
+ format,
+ usage,
+ client_id,
+ base::Bind(&GpuMemoryBufferFactoryHostImpl::OnGpuMemoryBufferCreated,
+ base::Unretained(this),
+ request_id));
+}
+
+void GpuMemoryBufferFactoryHostImpl::DestroyGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
+ int32 sync_point) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GpuMemoryBufferFactoryHostImpl::DestroyGpuMemoryBufferOnIO,
+ base::Unretained(this),
+ type,
+ id,
+ client_id,
+ sync_point));
+}
+
+void GpuMemoryBufferFactoryHostImpl::DestroyGpuMemoryBufferOnIO(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
+ int32 sync_point) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
+ if (!host)
+ return;
+
+ host->DestroyGpuMemoryBuffer(type, id, client_id, sync_point);
+}
+
+void GpuMemoryBufferFactoryHostImpl::OnGpuMemoryBufferCreated(
+ uint32 request_id,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ CreateGpuMemoryBufferCallbackMap::iterator iter =
+ create_gpu_memory_buffer_requests_.find(request_id);
+ DCHECK(iter != create_gpu_memory_buffer_requests_.end());
+ iter->second.Run(handle);
+ create_gpu_memory_buffer_requests_.erase(iter);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.h b/chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.h
new file mode 100644
index 00000000000..6cdf6b726d5
--- /dev/null
+++ b/chromium/content/browser/gpu/gpu_memory_buffer_factory_host_impl.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2014 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 CONTENT_BROWSER_GPU_GPU_MEMORY_BUFFER_FACTORY_HOST_IMPL_H_
+#define CONTENT_BROWSER_GPU_GPU_MEMORY_BUFFER_FACTORY_HOST_IMPL_H_
+
+#include <map>
+
+#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
+
+namespace content {
+
+class CONTENT_EXPORT GpuMemoryBufferFactoryHostImpl
+ : public GpuMemoryBufferFactoryHost {
+ public:
+ GpuMemoryBufferFactoryHostImpl();
+ ~GpuMemoryBufferFactoryHostImpl() override;
+
+ // Overridden from GpuMemoryBufferFactoryHost:
+ void CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id,
+ const CreateGpuMemoryBufferCallback& callback) override;
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
+ int32 sync_point) override;
+
+ void set_gpu_host_id(int gpu_host_id) { gpu_host_id_ = gpu_host_id; }
+
+ private:
+ void DestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
+ int32 sync_point);
+ void OnGpuMemoryBufferCreated(uint32 request_id,
+ const gfx::GpuMemoryBufferHandle& handle);
+
+ int gpu_host_id_;
+ uint32 next_create_gpu_memory_buffer_request_id_;
+ typedef std::map<uint32, CreateGpuMemoryBufferCallback>
+ CreateGpuMemoryBufferCallbackMap;
+ CreateGpuMemoryBufferCallbackMap create_gpu_memory_buffer_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryHostImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_GPU_GPU_MEMORY_BUFFER_FACTORY_HOST_IMPL_H_
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index 9176b6d891c..be7db476b0b 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -17,11 +17,12 @@
#include "base/sha1.h"
#include "base/threading/thread.h"
#include "content/browser/browser_child_process_host_impl.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/shader_disk_cache.h"
-#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_resize_helper.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
@@ -39,10 +40,10 @@
#include "ipc/ipc_switches.h"
#include "ipc/message_filter.h"
#include "media/base/media_switches.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/events/latency_info.h"
#include "ui/gl/gl_switches.h"
-
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#include "content/common/sandbox_win.h"
@@ -51,7 +52,7 @@
#endif
#if defined(USE_OZONE)
-#include "ui/ozone/ozone_switches.h"
+#include "ui/ozone/public/ozone_switches.h"
#endif
#if defined(USE_X11) && !defined(OS_CHROMEOS)
@@ -62,9 +63,59 @@ namespace content {
bool GpuProcessHost::gpu_enabled_ = true;
bool GpuProcessHost::hardware_gpu_enabled_ = true;
+int GpuProcessHost::gpu_crash_count_ = 0;
+int GpuProcessHost::gpu_recent_crash_count_ = 0;
+bool GpuProcessHost::crashed_before_ = false;
+int GpuProcessHost::swiftshader_crash_count_ = 0;
namespace {
+// Command-line switches to propagate to the GPU process.
+static const char* const kSwitchNames[] = {
+ switches::kDisableAcceleratedVideoDecode,
+ switches::kDisableBreakpad,
+ switches::kDisableGpuSandbox,
+ switches::kDisableGpuWatchdog,
+ switches::kDisableLogging,
+ switches::kDisableSeccompFilterSandbox,
+#if defined(ENABLE_WEBRTC)
+ switches::kDisableWebRtcHWEncoding,
+ switches::kEnableWebRtcHWVp8Encoding,
+#endif
+ switches::kEnableLogging,
+ switches::kEnableShareGroupAsyncTextureUpload,
+#if defined(OS_CHROMEOS)
+ switches::kDisableVaapiAcceleratedVideoEncode,
+#endif
+ switches::kGpuStartupDialog,
+ switches::kGpuSandboxAllowSysVShm,
+ switches::kGpuSandboxFailuresFatal,
+ switches::kGpuSandboxStartEarly,
+ switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
+ switches::kLoggingLevel,
+ switches::kLowEndDeviceMode,
+ switches::kNoSandbox,
+ switches::kTestGLLib,
+ switches::kTraceStartup,
+ switches::kTraceToConsole,
+ switches::kV,
+ switches::kVModule,
+#if defined(OS_MACOSX)
+ switches::kDisableRemoteCoreAnimation,
+ switches::kEnableSandboxLogging,
+#endif
+#if defined(USE_AURA)
+ switches::kUIPrioritizeInGpuProcess,
+#endif
+#if defined(USE_OZONE)
+ switches::kOzonePlatform,
+ switches::kOzoneUseSurfaceless,
+#endif
+#if defined(USE_X11) && !defined(OS_CHROMEOS)
+ switches::kX11Display,
+#endif
+};
+
enum GPUProcessLifetimeEvent {
LAUNCHED,
DIED_FIRST_TIME,
@@ -94,7 +145,7 @@ void SendGpuProcessMessage(GpuProcessHost::GpuProcessKind kind,
class GpuSandboxedProcessLauncherDelegate
: public SandboxedProcessLauncherDelegate {
public:
- GpuSandboxedProcessLauncherDelegate(CommandLine* cmd_line,
+ GpuSandboxedProcessLauncherDelegate(base::CommandLine* cmd_line,
ChildProcessHost* host)
#if defined(OS_WIN)
: cmd_line_(cmd_line) {}
@@ -102,10 +153,10 @@ class GpuSandboxedProcessLauncherDelegate
: ipc_fd_(host->TakeClientFileDescriptor()) {}
#endif
- virtual ~GpuSandboxedProcessLauncherDelegate() {}
+ ~GpuSandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
- virtual bool ShouldSandbox() OVERRIDE {
+ virtual bool ShouldSandbox() override {
bool sandbox = !cmd_line_->HasSwitch(switches::kDisableGpuSandbox);
if(! sandbox) {
DVLOG(1) << "GPU sandbox is disabled";
@@ -114,7 +165,7 @@ class GpuSandboxedProcessLauncherDelegate
}
virtual void PreSandbox(bool* disable_default_policy,
- base::FilePath* exposed_dir) OVERRIDE {
+ base::FilePath* exposed_dir) override {
*disable_default_policy = true;
}
@@ -199,16 +250,14 @@ class GpuSandboxedProcessLauncherDelegate
}
#elif defined(OS_POSIX)
- virtual int GetIpcFd() OVERRIDE {
- return ipc_fd_;
- }
+ base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); }
#endif // OS_WIN
private:
#if defined(OS_WIN)
- CommandLine* cmd_line_;
+ base::CommandLine* cmd_line_;
#elif defined(OS_POSIX)
- int ipc_fd_;
+ base::ScopedFD ipc_fd_;
#endif // OS_WIN
};
@@ -218,8 +267,10 @@ class GpuSandboxedProcessLauncherDelegate
bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
// The Gpu process is invalid if it's not using SwiftShader, the card is
// blacklisted, and we can kill it and start over.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU) ||
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kInProcessGPU) ||
(host->valid_ &&
(host->swiftshader_rendering_ ||
!GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()))) {
@@ -325,9 +376,12 @@ GpuProcessHost::GpuProcessHost(int host_id, GpuProcessKind kind)
kind_(kind),
process_launched_(false),
initialized_(false),
+ gpu_crash_recorded_(false),
uma_memory_stats_received_(false) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess) ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kInProcessGPU)) {
in_process_ = true;
}
@@ -355,67 +409,7 @@ GpuProcessHost::~GpuProcessHost() {
SendOutstandingReplies();
- // Maximum number of times the gpu process is allowed to crash in a session.
- // Once this limit is reached, any request to launch the gpu process will
- // fail.
- const int kGpuMaxCrashCount = 3;
-
- // Number of times the gpu process has crashed in the current browser session.
- static int gpu_crash_count = 0;
- static int gpu_recent_crash_count = 0;
- static base::Time last_gpu_crash_time;
- static bool crashed_before = false;
- static int swiftshader_crash_count = 0;
-
- bool disable_crash_limit = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGpuProcessCrashLimit);
-
- // Ending only acts as a failure if the GPU process was actually started and
- // was intended for actual rendering (and not just checking caps or other
- // options).
- if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
- if (swiftshader_rendering_) {
- UMA_HISTOGRAM_ENUMERATION("GPU.SwiftShaderLifetimeEvents",
- DIED_FIRST_TIME + swiftshader_crash_count,
- GPU_PROCESS_LIFETIME_EVENT_MAX);
-
- if (++swiftshader_crash_count >= kGpuMaxCrashCount &&
- !disable_crash_limit) {
- // SwiftShader is too unstable to use. Disable it for current session.
- gpu_enabled_ = false;
- }
- } else {
- ++gpu_crash_count;
- UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
- std::min(DIED_FIRST_TIME + gpu_crash_count,
- GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
- GPU_PROCESS_LIFETIME_EVENT_MAX);
-
- // Allow about 1 GPU crash per hour to be removed from the crash count,
- // so very occasional crashes won't eventually add up and prevent the
- // GPU process from launching.
- ++gpu_recent_crash_count;
- base::Time current_time = base::Time::Now();
- if (crashed_before) {
- int hours_different = (current_time - last_gpu_crash_time).InHours();
- gpu_recent_crash_count =
- std::max(0, gpu_recent_crash_count - hours_different);
- }
-
- crashed_before = true;
- last_gpu_crash_time = current_time;
-
- if ((gpu_recent_crash_count >= kGpuMaxCrashCount && !disable_crash_limit)
- || !initialized_) {
-#if !defined(OS_CHROMEOS)
- // The gpu process is too unstable to use. Disable it for current
- // session.
- hardware_gpu_enabled_ = false;
- GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration();
-#endif
- }
- }
- }
+ RecordProcessCrash();
// In case we never started, clean up.
while (!queued_messages_.empty()) {
@@ -508,7 +502,7 @@ bool GpuProcessHost::Init() {
if (in_process_) {
DCHECK(g_gpu_main_thread_factory);
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(switches::kDisableGpuWatchdog);
GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
@@ -516,7 +510,12 @@ bool GpuProcessHost::Init() {
gpu_data_manager->AppendGpuCommandLine(command_line);
in_process_gpu_thread_.reset(g_gpu_main_thread_factory(channel_id));
- in_process_gpu_thread_->Start();
+ base::Thread::Options options;
+#if defined(OS_WIN)
+ // WGL needs to create its own window and pump messages on it.
+ options.message_loop_type = base::MessageLoop::TYPE_UI;
+#endif
+ in_process_gpu_thread_->StartWithOptions(options);
OnProcessLaunched(); // Fake a callback that the process is ready.
} else if (!LaunchGpuProcess(channel_id)) {
@@ -565,7 +564,6 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated)
IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyCommandBuffer, OnDestroyCommandBuffer)
- IPC_MESSAGE_HANDLER(GpuHostMsg_ImageCreated, OnImageCreated)
IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryBufferCreated,
OnGpuMemoryBufferCreated)
IPC_MESSAGE_HANDLER(GpuHostMsg_DidCreateOffscreenContext,
@@ -576,8 +574,8 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryUmaStats,
OnGpuMemoryUmaStatsReceived)
#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
- OnAcceleratedSurfaceBuffersSwapped)
+ IPC_MESSAGE_HANDLER_GENERIC(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
+ OnAcceleratedSurfaceBuffersSwapped(message))
#endif
IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyChannel,
OnDestroyChannel)
@@ -602,6 +600,7 @@ void GpuProcessHost::OnChannelConnected(int32 peer_pid) {
void GpuProcessHost::EstablishGpuChannel(
int client_id,
bool share_context,
+ bool allow_future_sync_points,
const EstablishChannelCallback& callback) {
DCHECK(CalledOnValidThread());
TRACE_EVENT0("gpu", "GpuProcessHost::EstablishGpuChannel");
@@ -613,14 +612,15 @@ void GpuProcessHost::EstablishGpuChannel(
return;
}
- if (Send(new GpuMsg_EstablishChannel(client_id, share_context))) {
+ if (Send(new GpuMsg_EstablishChannel(
+ client_id, share_context, allow_future_sync_points))) {
channel_requests_.push(callback);
} else {
DVLOG(1) << "Failed to send GpuMsg_EstablishChannel.";
callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
}
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
CreateChannelCache(client_id);
}
@@ -650,57 +650,41 @@ void GpuProcessHost::CreateViewCommandBuffer(
}
}
-void GpuProcessHost::CreateImage(gfx::PluginWindowHandle window,
- int client_id,
- int image_id,
- const CreateImageCallback& callback) {
- TRACE_EVENT0("gpu", "GpuProcessHost::CreateImage");
-
- DCHECK(CalledOnValidThread());
-
- if (Send(new GpuMsg_CreateImage(window, client_id, image_id))) {
- create_image_requests_.push(callback);
- } else {
- callback.Run(gfx::Size());
- }
-}
-
-void GpuProcessHost::DeleteImage(int client_id,
- int image_id,
- int sync_point) {
- TRACE_EVENT0("gpu", "GpuProcessHost::DeleteImage");
-
- DCHECK(CalledOnValidThread());
-
- Send(new GpuMsg_DeleteImage(client_id, image_id, sync_point));
-}
-
void GpuProcessHost::CreateGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id,
const CreateGpuMemoryBufferCallback& callback) {
TRACE_EVENT0("gpu", "GpuProcessHost::CreateGpuMemoryBuffer");
DCHECK(CalledOnValidThread());
- if (Send(new GpuMsg_CreateGpuMemoryBuffer(
- handle, size, internalformat, usage))) {
+ GpuMsg_CreateGpuMemoryBuffer_Params params;
+ params.type = type;
+ params.id = id;
+ params.size = size;
+ params.format = format;
+ params.usage = usage;
+ params.client_id = client_id;
+ if (Send(new GpuMsg_CreateGpuMemoryBuffer(params))) {
create_gpu_memory_buffer_requests_.push(callback);
} else {
callback.Run(gfx::GpuMemoryBufferHandle());
}
}
-void GpuProcessHost::DestroyGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- int sync_point) {
+void GpuProcessHost::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
+ int sync_point) {
TRACE_EVENT0("gpu", "GpuProcessHost::DestroyGpuMemoryBuffer");
DCHECK(CalledOnValidThread());
- Send(new GpuMsg_DestroyGpuMemoryBuffer(handle, sync_point));
+ Send(new GpuMsg_DestroyGpuMemoryBuffer(type, id, client_id, sync_point));
}
void GpuProcessHost::OnInitialized(bool result, const gpu::GPUInfo& gpu_info) {
@@ -765,17 +749,6 @@ void GpuProcessHost::OnDestroyCommandBuffer(int32 surface_id) {
}
}
-void GpuProcessHost::OnImageCreated(const gfx::Size size) {
- TRACE_EVENT0("gpu", "GpuProcessHost::OnImageCreated");
-
- if (create_image_requests_.empty())
- return;
-
- CreateImageCallback callback = create_image_requests_.front();
- create_image_requests_.pop();
- callback.Run(size);
-}
-
void GpuProcessHost::OnGpuMemoryBufferCreated(
const gfx::GpuMemoryBufferHandle& handle) {
TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryBufferCreated");
@@ -843,67 +816,10 @@ void GpuProcessHost::OnGpuMemoryUmaStatsReceived(
#if defined(OS_MACOSX)
void GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
- TRACE_EVENT0("gpu", "GpuProcessHost::OnAcceleratedSurfaceBuffersSwapped");
-
- if (!ui::LatencyInfo::Verify(params.latency_info,
- "GpuHostMsg_AcceleratedSurfaceBuffersSwapped"))
- return;
-
- gfx::AcceleratedWidget native_widget =
- GpuSurfaceTracker::Get()->AcquireNativeWidget(params.surface_id);
- if (native_widget) {
- RenderWidgetHelper::OnNativeSurfaceBuffersSwappedOnIOThread(this, params);
- return;
- }
-
- gfx::GLSurfaceHandle surface_handle =
- GpuSurfaceTracker::Get()->GetSurfaceHandle(params.surface_id);
- // Compositor window is always gfx::kNullPluginWindow.
- // TODO(jbates) http://crbug.com/105344 This will be removed when there are no
- // plugin windows.
- if (surface_handle.handle != gfx::kNullPluginWindow ||
- surface_handle.transport_type == gfx::TEXTURE_TRANSPORT) {
- RouteOnUIThread(GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
- return;
- }
-
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.sync_point = 0;
-
- int render_process_id = 0;
- int render_widget_id = 0;
- if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface(
- params.surface_id, &render_process_id, &render_widget_id)) {
- Send(new AcceleratedSurfaceMsg_BufferPresented(params.route_id,
- ack_params));
- return;
- }
- RenderWidgetHelper* helper =
- RenderWidgetHelper::FromProcessHostID(render_process_id);
- if (!helper) {
- Send(new AcceleratedSurfaceMsg_BufferPresented(params.route_id,
- ack_params));
- return;
- }
-
- // Pass the SwapBuffers on to the RenderWidgetHelper to wake up the UI thread
- // if the browser is waiting for a new frame. Otherwise the RenderWidgetHelper
- // will forward to the RenderWidgetHostView via RenderProcessHostImpl and
- // RenderWidgetHostImpl.
- ViewHostMsg_CompositorSurfaceBuffersSwapped_Params view_params;
- view_params.surface_id = params.surface_id;
- view_params.surface_handle = params.surface_handle;
- view_params.route_id = params.route_id;
- view_params.size = params.size;
- view_params.scale_factor = params.scale_factor;
- view_params.gpu_process_host_id = host_id_;
- view_params.latency_info = params.latency_info;
- helper->DidReceiveBackingStoreMsg(ViewHostMsg_CompositorSurfaceBuffersSwapped(
- render_widget_id,
- view_params));
+ const IPC::Message& message) {
+ RenderWidgetResizeHelper::Get()->PostGpuProcessMsg(host_id_, message);
}
-#endif // OS_MACOSX
+#endif
void GpuProcessHost::OnProcessLaunched() {
UMA_HISTOGRAM_TIMES("GPU.GPUProcessLaunchTime",
@@ -912,6 +828,7 @@ void GpuProcessHost::OnProcessLaunched() {
void GpuProcessHost::OnProcessCrashed(int exit_code) {
SendOutstandingReplies();
+ RecordProcessCrash();
GpuDataManagerImpl::GetInstance()->ProcessCrashed(
process_->GetTerminationStatus(true /* known_dead */, NULL));
}
@@ -947,9 +864,10 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
return false;
}
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
- CommandLine::StringType gpu_launcher =
+ base::CommandLine::StringType gpu_launcher =
browser_command_line.GetSwitchValueNative(switches::kGpuLauncher);
#if defined(OS_LINUX)
@@ -963,50 +881,15 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
if (exe_path.empty())
return false;
- CommandLine* cmd_line = new CommandLine(exe_path);
+ base::CommandLine* cmd_line = new base::CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
cmd_line->AppendSwitch(switches::kDisableGpuSandbox);
- // Propagate relevant command line switches.
- static const char* const kSwitchNames[] = {
- switches::kDisableAcceleratedVideoDecode,
- switches::kDisableBreakpad,
- switches::kDisableGpuSandbox,
- switches::kDisableGpuWatchdog,
- switches::kDisableLogging,
- switches::kDisableSeccompFilterSandbox,
-#if defined(ENABLE_WEBRTC)
- switches::kDisableWebRtcHWEncoding,
-#endif
- switches::kEnableLogging,
- switches::kEnableShareGroupAsyncTextureUpload,
- switches::kGpuStartupDialog,
- switches::kGpuSandboxAllowSysVShm,
- switches::kGpuSandboxFailuresFatal,
- switches::kGpuSandboxStartAfterInitialization,
- switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
- switches::kLoggingLevel,
- switches::kNoSandbox,
- switches::kTestGLLib,
- switches::kTraceStartup,
- switches::kV,
- switches::kVModule,
-#if defined(OS_MACOSX)
- switches::kEnableSandboxLogging,
-#endif
-#if defined(USE_AURA)
- switches::kUIPrioritizeInGpuProcess,
-#endif
-#if defined(USE_OZONE)
- switches::kOzonePlatform,
-#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
- switches::kX11Display,
-#endif
- };
+ // If you want a browser command-line switch passed to the GPU process
+ // you need to add it to |kSwitchNames| at the beginning of this file.
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
arraysize(kSwitchNames));
cmd_line->CopySwitchesFrom(
@@ -1058,6 +941,13 @@ void GpuProcessHost::SendOutstandingReplies() {
create_command_buffer_requests_.pop();
callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
}
+
+ while (!create_gpu_memory_buffer_requests_.empty()) {
+ CreateGpuMemoryBufferCallback callback =
+ create_gpu_memory_buffer_requests_.front();
+ create_gpu_memory_buffer_requests_.pop();
+ callback.Run(gfx::GpuMemoryBufferHandle());
+ }
}
void GpuProcessHost::BlockLiveOffscreenContexts() {
@@ -1069,6 +959,72 @@ void GpuProcessHost::BlockLiveOffscreenContexts() {
}
}
+void GpuProcessHost::RecordProcessCrash() {
+ // Skip if a GPU process crash was already counted.
+ if (gpu_crash_recorded_)
+ return;
+
+ // Maximum number of times the GPU process is allowed to crash in a session.
+ // Once this limit is reached, any request to launch the GPU process will
+ // fail.
+ const int kGpuMaxCrashCount = 3;
+
+ // Last time the GPU process crashed.
+ static base::Time last_gpu_crash_time;
+
+ bool disable_crash_limit = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuProcessCrashLimit);
+
+ // Ending only acts as a failure if the GPU process was actually started and
+ // was intended for actual rendering (and not just checking caps or other
+ // options).
+ if (process_launched_ && kind_ == GPU_PROCESS_KIND_SANDBOXED) {
+ gpu_crash_recorded_ = true;
+ if (swiftshader_rendering_) {
+ UMA_HISTOGRAM_ENUMERATION("GPU.SwiftShaderLifetimeEvents",
+ DIED_FIRST_TIME + swiftshader_crash_count_,
+ GPU_PROCESS_LIFETIME_EVENT_MAX);
+
+ if (++swiftshader_crash_count_ >= kGpuMaxCrashCount &&
+ !disable_crash_limit) {
+ // SwiftShader is too unstable to use. Disable it for current session.
+ gpu_enabled_ = false;
+ }
+ } else {
+ ++gpu_crash_count_;
+ UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents",
+ std::min(DIED_FIRST_TIME + gpu_crash_count_,
+ GPU_PROCESS_LIFETIME_EVENT_MAX - 1),
+ GPU_PROCESS_LIFETIME_EVENT_MAX);
+
+ // Allow about 1 GPU crash per hour to be removed from the crash count,
+ // so very occasional crashes won't eventually add up and prevent the
+ // GPU process from launching.
+ ++gpu_recent_crash_count_;
+ base::Time current_time = base::Time::Now();
+ if (crashed_before_) {
+ int hours_different = (current_time - last_gpu_crash_time).InHours();
+ gpu_recent_crash_count_ =
+ std::max(0, gpu_recent_crash_count_ - hours_different);
+ }
+
+ crashed_before_ = true;
+ last_gpu_crash_time = current_time;
+
+ if ((gpu_recent_crash_count_ >= kGpuMaxCrashCount &&
+ !disable_crash_limit) ||
+ !initialized_) {
+#if !defined(OS_CHROMEOS)
+ // The GPU process is too unstable to use. Disable it for current
+ // session.
+ hardware_gpu_enabled_ = false;
+ GpuDataManagerImpl::GetInstance()->DisableHardwareAcceleration();
+#endif
+ }
+ }
+ }
+}
+
std::string GpuProcessHost::GetShaderPrefixKey() {
if (shader_prefix_key_.empty()) {
gpu::GPUInfo info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index cf789465248..2952d3869ef 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -26,18 +26,12 @@
#include "gpu/config/gpu_info.h"
#include "ipc/ipc_sender.h"
#include "ipc/message_filter.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
#include "url/gurl.h"
struct GPUCreateCommandBufferConfig;
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
-struct GpuHostMsg_AcceleratedSurfaceRelease_Params;
-
-namespace gfx {
-struct GpuMemoryBufferHandle;
-}
namespace IPC {
struct ChannelHandle;
@@ -67,12 +61,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
typedef base::Callback<void(CreateCommandBufferResult)>
CreateCommandBufferCallback;
- typedef base::Callback<void(const gfx::Size)> CreateImageCallback;
-
typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)>
CreateGpuMemoryBufferCallback;
static bool gpu_enabled() { return gpu_enabled_; }
+ static int gpu_crash_count() { return gpu_crash_count_; }
// Creates a new GpuProcessHost or gets an existing one, resulting in the
// launching of a GPU process if required. Returns null on failure. It
@@ -102,7 +95,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
int host_id() const { return host_id_; }
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// Adds a message filter to the GpuProcessHost's channel.
void AddFilter(IPC::MessageFilter* filter);
@@ -112,6 +105,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// and GPUInfo, we call the callback.
void EstablishGpuChannel(int client_id,
bool share_context,
+ bool allow_future_sync_points,
const EstablishChannelCallback& callback);
// Tells the GPU process to create a new command buffer that draws into the
@@ -124,22 +118,19 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
int route_id,
const CreateCommandBufferCallback& callback);
- // Tells the GPU process to create a new image using the given window.
- void CreateImage(
- gfx::PluginWindowHandle window,
- int client_id,
- int image_id,
- const CreateImageCallback& callback);
-
- // Tells the GPU process to delete image.
- void DeleteImage(int client_id, int image_id, int sync_point);
-
- void CreateGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
+ // Tells the GPU process to create a new GPU memory buffer.
+ void CreateGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id,
const CreateGpuMemoryBufferCallback& callback);
- void DestroyGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
+
+ // Tells the GPU process to destroy GPU memory buffer.
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
int sync_point);
// What kind of GPU process, e.g. sandboxed or unsandboxed.
@@ -157,7 +148,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
static bool ValidateHost(GpuProcessHost* host);
GpuProcessHost(int host_id, GpuProcessKind kind);
- virtual ~GpuProcessHost();
+ ~GpuProcessHost() override;
bool Init();
@@ -165,17 +156,16 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void RouteOnUIThread(const IPC::Message& message);
// BrowserChildProcessHostDelegate implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnProcessLaunched() OVERRIDE;
- virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnProcessLaunched() override;
+ void OnProcessCrashed(int exit_code) override;
// Message handlers.
void OnInitialized(bool result, const gpu::GPUInfo& gpu_info);
void OnChannelEstablished(const IPC::ChannelHandle& channel_handle);
void OnCommandBufferCreated(CreateCommandBufferResult result);
void OnDestroyCommandBuffer(int32 surface_id);
- void OnImageCreated(const gfx::Size size);
void OnGpuMemoryBufferCreated(const gfx::GpuMemoryBufferHandle& handle);
void OnDidCreateOffscreenContext(const GURL& url);
void OnDidLoseContext(bool offscreen,
@@ -184,8 +174,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void OnDidDestroyOffscreenContext(const GURL& url);
void OnGpuMemoryUmaStatsReceived(const GPUMemoryUmaStats& stats);
#if defined(OS_MACOSX)
- void OnAcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
+ void OnAcceleratedSurfaceBuffersSwapped(const IPC::Message& message);
#endif
void CreateChannelCache(int32 client_id);
@@ -199,6 +188,9 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void BlockLiveOffscreenContexts();
+ // Update GPU crash counters. Disable GPU if crash limit is reached.
+ void RecordProcessCrash();
+
std::string GetShaderPrefixKey();
// The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
@@ -211,9 +203,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// The pending create command buffer requests we need to reply to.
std::queue<CreateCommandBufferCallback> create_command_buffer_requests_;
- // The pending create image requests we need to reply to.
- std::queue<CreateImageCallback> create_image_requests_;
-
// The pending create gpu memory buffer requests we need to reply to.
std::queue<CreateGpuMemoryBufferCallback> create_gpu_memory_buffer_requests_;
@@ -241,6 +230,9 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Time Init started. Used to log total GPU process startup time to UMA.
base::TimeTicks init_start_time_;
+ // Whether this host recorded a GPU crash or not.
+ bool gpu_crash_recorded_;
+
// Master switch for enabling/disabling GPU acceleration for the current
// browser session. It does not change the acceleration settings for
// existing tabs, just the future ones.
@@ -248,6 +240,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
static bool hardware_gpu_enabled_;
+ static int gpu_crash_count_;
+ static int gpu_recent_crash_count_;
+ static bool crashed_before_;
+ static int swiftshader_crash_count_;
+
scoped_ptr<BrowserChildProcessHostImpl> process_;
// Track the URLs of the pages which have live offscreen contexts,
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc b/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
index a6a6805d176..8c4450628e7 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
@@ -11,18 +11,24 @@
#include "base/id_map.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/public/browser/browser_thread.h"
+#if defined(OS_MACOSX)
+#include "content/browser/compositor/browser_compositor_ca_layer_tree_mac.h"
+#endif
+
#if defined(USE_OZONE)
-#include "ui/ozone/ozone_platform.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
+#include "ui/ozone/public/ozone_platform.h"
#endif
namespace content {
@@ -198,24 +204,14 @@ bool GpuProcessHostUIShim::OnControlMessageReceived(
IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message)
IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage,
OnLogMessage)
-
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceInitialized,
OnAcceleratedSurfaceInitialized)
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
OnAcceleratedSurfaceBuffersSwapped)
- IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfacePostSubBuffer,
- OnAcceleratedSurfacePostSubBuffer)
- IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSuspend,
- OnAcceleratedSurfaceSuspend)
IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected,
OnGraphicsInfoCollected)
- IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceRelease,
- OnAcceleratedSurfaceRelease)
IPC_MESSAGE_HANDLER(GpuHostMsg_VideoMemoryUsageStats,
OnVideoMemoryUsageStatsReceived);
- IPC_MESSAGE_HANDLER(GpuHostMsg_UpdateVSyncParameters,
- OnUpdateVSyncParameters)
- IPC_MESSAGE_HANDLER(GpuHostMsg_FrameDrawn, OnFrameDrawn)
IPC_MESSAGE_UNHANDLED_ERROR()
IPC_END_MESSAGE_MAP()
@@ -223,23 +219,6 @@ bool GpuProcessHostUIShim::OnControlMessageReceived(
return true;
}
-void GpuProcessHostUIShim::OnUpdateVSyncParameters(int surface_id,
- base::TimeTicks timebase,
- base::TimeDelta interval) {
-
- int render_process_id = 0;
- int render_widget_id = 0;
- if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface(
- surface_id, &render_process_id, &render_widget_id)) {
- return;
- }
- RenderWidgetHost* rwh =
- RenderWidgetHost::FromID(render_process_id, render_widget_id);
- if (!rwh)
- return;
- RenderWidgetHostImpl::From(rwh)->UpdateVSyncParameters(timebase, interval);
-}
-
void GpuProcessHostUIShim::OnLogMessage(
int level,
const std::string& header,
@@ -263,104 +242,38 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceInitialized(int32 surface_id,
GetRenderWidgetHostViewFromSurfaceID(surface_id);
if (!view)
return;
- view->AcceleratedSurfaceInitialized(host_id_, route_id);
+ view->AcceleratedSurfaceInitialized(route_id);
}
void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
+#if defined(OS_MACOSX)
TRACE_EVENT0("renderer",
"GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped");
if (!ui::LatencyInfo::Verify(params.latency_info,
- "GpuHostMsg_AcceleratedSurfaceBuffersSwapped"))
+ "GpuHostMsg_AcceleratedSurfaceBuffersSwapped")) {
return;
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.mailbox = params.mailbox;
- ack_params.sync_point = 0;
- ScopedSendOnIOThread delayed_send(
- host_id_,
- new AcceleratedSurfaceMsg_BufferPresented(params.route_id,
- ack_params));
-
- RenderWidgetHostViewBase* view = GetRenderWidgetHostViewFromSurfaceID(
- params.surface_id);
- if (!view)
- return;
-
- delayed_send.Cancel();
-
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params view_params = params;
-
- RenderWidgetHostImpl* impl =
- RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
- for (size_t i = 0; i < view_params.latency_info.size(); i++)
- impl->AddLatencyInfoComponentIds(&view_params.latency_info[i]);
-
- // View must send ACK message after next composite.
- view->AcceleratedSurfaceBuffersSwapped(view_params, host_id_);
- view->DidReceiveRendererFrame();
-}
-
-void GpuProcessHostUIShim::OnFrameDrawn(
- const std::vector<ui::LatencyInfo>& latency_info) {
- if (!ui::LatencyInfo::Verify(latency_info,
- "GpuProcessHostUIShim::OnFrameDrawn"))
- return;
- RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
-}
+ }
-void GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params) {
- TRACE_EVENT0("renderer",
- "GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer");
- if (!ui::LatencyInfo::Verify(params.latency_info,
- "GpuHostMsg_AcceleratedSurfacePostSubBuffer"))
- return;
+ // On Mac with delegated rendering, accelerated surfaces are not necessarily
+ // associated with a RenderWidgetHostViewBase.
AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.mailbox = params.mailbox;
- ack_params.sync_point = 0;
- ScopedSendOnIOThread delayed_send(
- host_id_,
- new AcceleratedSurfaceMsg_BufferPresented(params.route_id,
- ack_params));
-
- RenderWidgetHostViewBase* view =
- GetRenderWidgetHostViewFromSurfaceID(params.surface_id);
- if (!view)
- return;
-
- delayed_send.Cancel();
-
- GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params view_params = params;
-
- RenderWidgetHostImpl* impl =
- RenderWidgetHostImpl::From(view->GetRenderWidgetHost());
- for (size_t i = 0; i < view_params.latency_info.size(); i++)
- impl->AddLatencyInfoComponentIds(&view_params.latency_info[i]);
-
- // View must send ACK message after next composite.
- view->AcceleratedSurfacePostSubBuffer(view_params, host_id_);
- view->DidReceiveRendererFrame();
-}
-
-void GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend(int32 surface_id) {
- TRACE_EVENT0("renderer",
- "GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend");
-
- RenderWidgetHostViewBase* view =
- GetRenderWidgetHostViewFromSurfaceID(surface_id);
- if (!view)
- return;
-
- view->AcceleratedSurfaceSuspend();
-}
-
-void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease(
- const GpuHostMsg_AcceleratedSurfaceRelease_Params& params) {
- RenderWidgetHostViewBase* view = GetRenderWidgetHostViewFromSurfaceID(
- params.surface_id);
- if (!view)
- return;
- view->AcceleratedSurfaceRelease();
+ DCHECK(IsDelegatedRendererEnabled());
+ gfx::AcceleratedWidget native_widget =
+ content::GpuSurfaceTracker::Get()->AcquireNativeWidget(params.surface_id);
+ BrowserCompositorCALayerTreeMacGotAcceleratedFrame(
+ native_widget,
+ params.surface_handle,
+ params.surface_id,
+ params.latency_info,
+ params.size,
+ params.scale_factor,
+ &ack_params.disable_throttling,
+ &ack_params.renderer_id);
+ Send(new AcceleratedSurfaceMsg_BufferPresented(params.route_id, ack_params));
+#else
+ NOTREACHED();
+#endif
}
void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived(
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
index 2fe19789bfe..e47dc9049f7 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
@@ -25,8 +25,6 @@
#include "ipc/ipc_sender.h"
struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
-struct GpuHostMsg_AcceleratedSurfaceRelease_Params;
namespace ui {
struct LatencyInfo;
@@ -66,13 +64,13 @@ class GpuProcessHostUIShim : public IPC::Listener,
CONTENT_EXPORT static GpuProcessHostUIShim* GetOneInstance();
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// IPC::Listener implementation.
// The GpuProcessHost causes this to be called on the UI thread to
// dispatch the incoming messages from the GPU process, which are
// actually received on the IO thread.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
CONTENT_EXPORT void SimulateRemoveAllContext();
CONTENT_EXPORT void SimulateCrash();
@@ -80,7 +78,7 @@ class GpuProcessHostUIShim : public IPC::Listener,
private:
explicit GpuProcessHostUIShim(int host_id);
- virtual ~GpuProcessHostUIShim();
+ ~GpuProcessHostUIShim() override;
// Message handlers.
bool OnControlMessageReceived(const IPC::Message& message);
@@ -93,17 +91,8 @@ class GpuProcessHostUIShim : public IPC::Listener,
void OnAcceleratedSurfaceInitialized(int32 surface_id, int32 route_id);
void OnAcceleratedSurfaceBuffersSwapped(
const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
- void OnAcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params);
- void OnAcceleratedSurfaceSuspend(int32 surface_id);
- void OnAcceleratedSurfaceRelease(
- const GpuHostMsg_AcceleratedSurfaceRelease_Params& params);
void OnVideoMemoryUsageStatsReceived(
const GPUVideoMemoryUsageStats& video_memory_usage_stats);
- void OnUpdateVSyncParameters(int surface_id,
- base::TimeTicks timebase,
- base::TimeDelta interval);
- void OnFrameDrawn(const std::vector<ui::LatencyInfo>& latency_info);
// The serial number of the GpuProcessHost / GpuProcessHostUIShim pair.
int host_id_;
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.h b/chromium/content/browser/gpu/gpu_surface_tracker.h
index de9d666dbe8..03d182fd14c 100644
--- a/chromium/content/browser/gpu/gpu_surface_tracker.h
+++ b/chromium/content/browser/gpu/gpu_surface_tracker.h
@@ -51,7 +51,7 @@ class GpuSurfaceTracker : public GpuSurfaceLookup {
// GpuSurfaceLookup implementation:
// Returns the native widget associated with a given surface_id.
- virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) OVERRIDE;
+ gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override;
// Gets the global instance of the surface tracker.
static GpuSurfaceTracker* Get() { return GetInstance(); }
@@ -124,7 +124,7 @@ class GpuSurfaceTracker : public GpuSurfaceLookup {
friend struct DefaultSingletonTraits<GpuSurfaceTracker>;
GpuSurfaceTracker();
- virtual ~GpuSurfaceTracker();
+ ~GpuSurfaceTracker() override;
base::Lock lock_;
SurfaceMap surface_map_;
diff --git a/chromium/content/browser/gpu/shader_disk_cache.cc b/chromium/content/browser/gpu/shader_disk_cache.cc
index c987cefc9a0..a50e3c38b98 100644
--- a/chromium/content/browser/gpu/shader_disk_cache.cc
+++ b/chromium/content/browser/gpu/shader_disk_cache.cc
@@ -4,6 +4,7 @@
#include "content/browser/gpu/shader_disk_cache.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/threading/thread_checker.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/browser/browser_thread.h"
@@ -23,6 +24,9 @@ void EntryCloser(disk_cache::Entry* entry) {
entry->Close();
}
+void FreeDiskCacheIterator(scoped_ptr<disk_cache::Backend::Iterator> iterator) {
+}
+
} // namespace
// ShaderDiskCacheEntry handles the work of caching/updating the cached
@@ -95,7 +99,7 @@ class ShaderDiskReadHelper
base::WeakPtr<ShaderDiskCache> cache_;
OpType op_type_;
- void* iter_;
+ scoped_ptr<disk_cache::Backend::Iterator> iter_;
scoped_refptr<net::IOBufferWithSize> buf_;
int host_id_;
disk_cache::Entry* entry_;
@@ -243,7 +247,6 @@ ShaderDiskReadHelper::ShaderDiskReadHelper(
int host_id)
: cache_(cache),
op_type_(OPEN_NEXT),
- iter_(NULL),
buf_(NULL),
host_id_(host_id),
entry_(NULL) {
@@ -257,6 +260,11 @@ void ShaderDiskReadHelper::LoadCache() {
}
void ShaderDiskReadHelper::OnOpComplete(int rv) {
+ // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "422516 ShaderDiskReadHelper::OnOpComplete"));
+
DCHECK(CalledOnValidThread());
if (!cache_.get())
return;
@@ -291,16 +299,17 @@ int ShaderDiskReadHelper::OpenNextEntry() {
DCHECK(CalledOnValidThread());
// Called through OnOpComplete, so we know |cache_| is valid.
op_type_ = OPEN_NEXT_COMPLETE;
- return cache_->backend()->OpenNextEntry(
- &iter_,
- &entry_,
- base::Bind(&ShaderDiskReadHelper::OnOpComplete, this));
+ if (!iter_)
+ iter_ = cache_->backend()->CreateIterator();
+ return iter_->OpenNextEntry(
+ &entry_, base::Bind(&ShaderDiskReadHelper::OnOpComplete, this));
}
int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) {
DCHECK(CalledOnValidThread());
// Called through OnOpComplete, so we know |cache_| is valid.
if (rv == net::ERR_FAILED) {
+ iter_.reset();
op_type_ = ITERATION_FINISHED;
return net::OK;
}
@@ -339,16 +348,21 @@ int ShaderDiskReadHelper::ReadComplete(int rv) {
int ShaderDiskReadHelper::IterationComplete(int rv) {
DCHECK(CalledOnValidThread());
// Called through OnOpComplete, so we know |cache_| is valid.
- cache_->backend()->EndEnumeration(&iter_);
- iter_ = NULL;
+ iter_.reset();
op_type_ = TERMINATE;
return net::OK;
}
ShaderDiskReadHelper::~ShaderDiskReadHelper() {
- if (entry_)
+ if (entry_) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&EntryCloser, entry_));
+ }
+ if (iter_) {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&FreeDiskCacheIterator,
+ base::Passed(&iter_)));
+ }
}
ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache,
@@ -545,7 +559,7 @@ void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) {
new ShaderDiskCacheEntry(AsWeakPtr(), key, shader);
shim->Cache();
- entry_map_[shim] = shim;
+ entry_map_[shim.get()] = shim;
}
int ShaderDiskCache::Clear(
diff --git a/chromium/content/browser/gpu/shader_disk_cache_unittest.cc b/chromium/content/browser/gpu/shader_disk_cache_unittest.cc
index 9c7061b62bb..15894ef6713 100644
--- a/chromium/content/browser/gpu/shader_disk_cache_unittest.cc
+++ b/chromium/content/browser/gpu/shader_disk_cache_unittest.cc
@@ -25,7 +25,7 @@ class ShaderDiskCacheTest : public testing::Test {
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
}
- virtual ~ShaderDiskCacheTest() {}
+ ~ShaderDiskCacheTest() override {}
const base::FilePath& cache_path() { return temp_dir_.path(); }
@@ -36,7 +36,7 @@ class ShaderDiskCacheTest : public testing::Test {
}
private:
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
ShaderCacheFactory::GetInstance()->RemoveCacheInfo(kDefaultClientId);
}
diff --git a/chromium/content/browser/gpu/test_support_gpu.gypi b/chromium/content/browser/gpu/test_support_gpu.gypi
index 9dcedc0cda9..98133776e5c 100644
--- a/chromium/content/browser/gpu/test_support_gpu.gypi
+++ b/chromium/content/browser/gpu/test_support_gpu.gypi
@@ -26,9 +26,9 @@
'<(DEPTH)/third_party/wtl/include',
],
'sources': [
+ '<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/content/content_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.rc',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.rc',
],
'conditions': [
['win_use_allocator_shim==1', {
diff --git a/chromium/content/browser/histogram_internals_request_job.cc b/chromium/content/browser/histogram_internals_request_job.cc
index aaa7a43eb26..e29dfca5e42 100644
--- a/chromium/content/browser/histogram_internals_request_job.cc
+++ b/chromium/content/browser/histogram_internals_request_job.cc
@@ -6,6 +6,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
+#include "base/profiler/scoped_tracker.h"
#include "content/browser/histogram_synchronizer.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
@@ -47,8 +48,8 @@ void AboutHistogram(std::string* data, const std::string& path) {
data->append("</head><body>");
// Display any stats for which we sent off requests the last time.
- data->append("<p>Stats as of last page load;");
- data->append("reload to get stats as of this page load.</p>\n");
+ data->append("<p>Stats accumulated from browser startup to previous ");
+ data->append("page load; reload to get stats as of this page load.</p>\n");
data->append("<table width=\"100%\">\n");
base::StatisticsRecorder::WriteHTMLGraph(unescaped_query, data);
@@ -59,6 +60,11 @@ int HistogramInternalsRequestJob::GetData(
std::string* charset,
std::string* data,
const net::CompletionCallback& callback) const {
+ // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "422489 HistogramInternalsRequestJob::GetData"));
+
mime_type->assign("text/html");
charset->assign("UTF8");
diff --git a/chromium/content/browser/histogram_internals_request_job.h b/chromium/content/browser/histogram_internals_request_job.h
index 4be774be87c..6304198477d 100644
--- a/chromium/content/browser/histogram_internals_request_job.h
+++ b/chromium/content/browser/histogram_internals_request_job.h
@@ -17,13 +17,13 @@ class HistogramInternalsRequestJob : public net::URLRequestSimpleJob {
HistogramInternalsRequestJob(net::URLRequest* request,
net::NetworkDelegate* network_delegate);
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* data,
- const net::CompletionCallback& callback) const OVERRIDE;
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const override;
private:
- virtual ~HistogramInternalsRequestJob() {}
+ ~HistogramInternalsRequestJob() override {}
// The string to select histograms which have |path_| as a substring.
std::string path_;
diff --git a/chromium/content/browser/histogram_message_filter.cc b/chromium/content/browser/histogram_message_filter.cc
index 8a58fff55f6..8eb7c7231ba 100644
--- a/chromium/content/browser/histogram_message_filter.cc
+++ b/chromium/content/browser/histogram_message_filter.cc
@@ -45,7 +45,7 @@ void HistogramMessageFilter::OnGetBrowserHistogram(
// Security: Only allow access to browser histograms when running in the
// context of a test.
bool using_stats_collection_controller =
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kStatsCollectionController);
if (!using_stats_collection_controller) {
LOG(ERROR) << "Attempt at reading browser histogram without specifying "
diff --git a/chromium/content/browser/histogram_message_filter.h b/chromium/content/browser/histogram_message_filter.h
index 67867061687..25fa6767b91 100644
--- a/chromium/content/browser/histogram_message_filter.h
+++ b/chromium/content/browser/histogram_message_filter.h
@@ -19,10 +19,10 @@ class HistogramMessageFilter : public BrowserMessageFilter {
HistogramMessageFilter();
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~HistogramMessageFilter();
+ ~HistogramMessageFilter() override;
// Message handlers.
void OnChildHistogramData(int sequence_number,
diff --git a/chromium/content/browser/histogram_synchronizer.h b/chromium/content/browser/histogram_synchronizer.h
index 9ff69d5cfeb..b7d75e03d45 100644
--- a/chromium/content/browser/histogram_synchronizer.h
+++ b/chromium/content/browser/histogram_synchronizer.h
@@ -80,7 +80,7 @@ class HistogramSynchronizer : public HistogramSubscriber {
class RequestContext;
HistogramSynchronizer();
- virtual ~HistogramSynchronizer();
+ ~HistogramSynchronizer() override;
// Establish a new sequence number, and use it to notify all processes
// (renderers, plugins, GPU, etc) of the need to supply, to the browser,
@@ -95,16 +95,16 @@ class HistogramSynchronizer : public HistogramSubscriber {
// Update the number of pending processes for the given |sequence_number|.
// This is called on UI thread.
- virtual void OnPendingProcesses(int sequence_number,
- int pending_processes,
- bool end) OVERRIDE;
+ void OnPendingProcesses(int sequence_number,
+ int pending_processes,
+ bool end) override;
// Send histogram_data back to caller and also record that we are waiting
// for one less histogram data from child process for the given sequence
// number. This method is accessible on UI thread.
- virtual void OnHistogramDataCollected(
+ void OnHistogramDataCollected(
int sequence_number,
- const std::vector<std::string>& pickled_histograms) OVERRIDE;
+ const std::vector<std::string>& pickled_histograms) override;
// Set the callback_thread_ and callback_ members. If these members already
// had values, then as a side effect, post the old callback_ to the old
diff --git a/chromium/content/browser/host_zoom_map_impl.cc b/chromium/content/browser/host_zoom_map_impl.cc
index 1b5f7a2f7d7..81f8182924d 100644
--- a/chromium/content/browser/host_zoom_map_impl.cc
+++ b/chromium/content/browser/host_zoom_map_impl.cc
@@ -21,14 +21,15 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/page_zoom.h"
+#include "content/public/common/url_constants.h"
#include "net/base/net_util.h"
-static const char* kHostZoomMapKeyName = "content_host_zoom_map";
-
namespace content {
namespace {
+const char kHostZoomMapKeyName[] = "content_host_zoom_map";
+
std::string GetHostFromProcessView(int render_process_id, int render_view_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RenderViewHost* render_view_host =
@@ -43,12 +44,23 @@ std::string GetHostFromProcessView(int render_process_id, int render_view_id) {
if (!entry)
return std::string();
- return net::GetHostOrSpecFromURL(entry->GetURL());
+ return net::GetHostOrSpecFromURL(HostZoomMap::GetURLFromEntry(entry));
}
} // namespace
-HostZoomMap* HostZoomMap::GetForBrowserContext(BrowserContext* context) {
+GURL HostZoomMap::GetURLFromEntry(const NavigationEntry* entry) {
+ switch (entry->GetPageType()) {
+ case PAGE_TYPE_ERROR:
+ return GURL(kUnreachableWebDataURL);
+ // TODO(wjmaclean): In future, give interstitial pages special treatment as
+ // well.
+ default:
+ return entry->GetURL();
+ }
+}
+
+HostZoomMap* HostZoomMap::GetDefaultForBrowserContext(BrowserContext* context) {
HostZoomMapImpl* rv = static_cast<HostZoomMapImpl*>(
context->GetUserData(kHostZoomMapKeyName));
if (!rv) {
@@ -61,19 +73,29 @@ HostZoomMap* HostZoomMap::GetForBrowserContext(BrowserContext* context) {
// Helper function for setting/getting zoom levels for WebContents without
// having to import HostZoomMapImpl everywhere.
double HostZoomMap::GetZoomLevel(const WebContents* web_contents) {
- HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
- HostZoomMap::GetForBrowserContext(web_contents->GetBrowserContext()));
+ HostZoomMapImpl* host_zoom_map =
+ static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
+ web_contents->GetBrowserContext()));
return host_zoom_map->GetZoomLevelForWebContents(
*static_cast<const WebContentsImpl*>(web_contents));
}
void HostZoomMap::SetZoomLevel(const WebContents* web_contents, double level) {
- HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
- HostZoomMap::GetForBrowserContext(web_contents->GetBrowserContext()));
+ HostZoomMapImpl* host_zoom_map =
+ static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
+ web_contents->GetBrowserContext()));
host_zoom_map->SetZoomLevelForWebContents(
*static_cast<const WebContentsImpl*>(web_contents), level);
}
+void HostZoomMap::SendErrorPageZoomLevelRefresh(
+ const WebContents* web_contents) {
+ HostZoomMapImpl* host_zoom_map =
+ static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
+ web_contents->GetBrowserContext()));
+ host_zoom_map->SendErrorPageZoomLevelRefresh();
+}
+
HostZoomMapImpl::HostZoomMapImpl()
: default_zoom_level_(0.0) {
registrar_.Add(
@@ -251,7 +273,7 @@ double HostZoomMapImpl::GetZoomLevelForWebContents(
// It is possible for a WebContent's zoom level to be queried before
// a navigation has occurred.
if (entry)
- url = entry->GetURL();
+ url = GetURLFromEntry(entry);
return GetZoomLevelForHostAndScheme(url.scheme(),
net::GetHostOrSpecFromURL(url));
}
@@ -275,7 +297,7 @@ void HostZoomMapImpl::SetZoomLevelForWebContents(
if (!entry)
return;
- GURL url = entry->GetURL();
+ GURL url = GetURLFromEntry(entry);
SetZoomLevelForHost(net::GetHostOrSpecFromURL(url), level);
}
}
@@ -374,7 +396,7 @@ void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
RenderProcessHost* render_process_host = i.GetCurrentValue();
- if (HostZoomMap::GetForBrowserContext(
+ if (HostZoomMap::GetDefaultForBrowserContext(
render_process_host->GetBrowserContext()) == this) {
render_process_host->Send(
new ViewMsg_SetZoomLevelForCurrentURL(scheme, host, level));
@@ -382,6 +404,14 @@ void HostZoomMapImpl::SendZoomLevelChange(const std::string& scheme,
}
}
+void HostZoomMapImpl::SendErrorPageZoomLevelRefresh() {
+ GURL error_url(kUnreachableWebDataURL);
+ std::string host = net::GetHostOrSpecFromURL(error_url);
+ double error_page_zoom_level = GetZoomLevelForHost(host);
+
+ SendZoomLevelChange(std::string(), host, error_page_zoom_level);
+}
+
HostZoomMapImpl::~HostZoomMapImpl() {
}
diff --git a/chromium/content/browser/host_zoom_map_impl.h b/chromium/content/browser/host_zoom_map_impl.h
index 821fa0e4923..78d643d750a 100644
--- a/chromium/content/browser/host_zoom_map_impl.h
+++ b/chromium/content/browser/host_zoom_map_impl.h
@@ -28,36 +28,32 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
public base::SupportsUserData::Data {
public:
HostZoomMapImpl();
- virtual ~HostZoomMapImpl();
+ ~HostZoomMapImpl() override;
// HostZoomMap implementation:
- virtual void CopyFrom(HostZoomMap* copy) OVERRIDE;
- virtual double GetZoomLevelForHostAndScheme(
- const std::string& scheme,
- const std::string& host) const OVERRIDE;
+ void CopyFrom(HostZoomMap* copy) override;
+ double GetZoomLevelForHostAndScheme(const std::string& scheme,
+ const std::string& host) const override;
// TODO(wjmaclean) Should we use a GURL here? crbug.com/384486
- virtual bool HasZoomLevel(const std::string& scheme,
- const std::string& host) const OVERRIDE;
- virtual ZoomLevelVector GetAllZoomLevels() const OVERRIDE;
- virtual void SetZoomLevelForHost(
- const std::string& host,
- double level) OVERRIDE;
- virtual void SetZoomLevelForHostAndScheme(
- const std::string& scheme,
- const std::string& host,
- double level) OVERRIDE;
- virtual bool UsesTemporaryZoomLevel(int render_process_id,
- int render_view_id) const OVERRIDE;
- virtual void SetTemporaryZoomLevel(int render_process_id,
- int render_view_id,
- double level) OVERRIDE;
-
- virtual void ClearTemporaryZoomLevel(int render_process_id,
- int render_view_id) OVERRIDE;
- virtual double GetDefaultZoomLevel() const OVERRIDE;
- virtual void SetDefaultZoomLevel(double level) OVERRIDE;
- virtual scoped_ptr<Subscription> AddZoomLevelChangedCallback(
- const ZoomLevelChangedCallback& callback) OVERRIDE;
+ bool HasZoomLevel(const std::string& scheme,
+ const std::string& host) const override;
+ ZoomLevelVector GetAllZoomLevels() const override;
+ void SetZoomLevelForHost(const std::string& host, double level) override;
+ void SetZoomLevelForHostAndScheme(const std::string& scheme,
+ const std::string& host,
+ double level) override;
+ bool UsesTemporaryZoomLevel(int render_process_id,
+ int render_view_id) const override;
+ void SetTemporaryZoomLevel(int render_process_id,
+ int render_view_id,
+ double level) override;
+
+ void ClearTemporaryZoomLevel(int render_process_id,
+ int render_view_id) override;
+ double GetDefaultZoomLevel() const override;
+ void SetDefaultZoomLevel(double level) override;
+ scoped_ptr<Subscription> AddZoomLevelChangedCallback(
+ const ZoomLevelChangedCallback& callback) override;
// Returns the current zoom level for the specified WebContents. This may
// be a temporary zoom level, depending on UsesTemporaryZoomLevel().
@@ -86,9 +82,11 @@ class CONTENT_EXPORT HostZoomMapImpl : public NON_EXPORTED_BASE(HostZoomMap),
int render_view_id) const;
// NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
+
+ void SendErrorPageZoomLevelRefresh();
private:
typedef std::map<std::string, double> HostZoomLevels;
diff --git a/chromium/content/browser/indexed_db/OWNERS b/chromium/content/browser/indexed_db/OWNERS
index d68c26c9187..6d435ba10c4 100644
--- a/chromium/content/browser/indexed_db/OWNERS
+++ b/chromium/content/browser/indexed_db/OWNERS
@@ -1,5 +1,4 @@
dgrogan@chromium.org
michaeln@chromium.org
jsbell@chromium.org
-ericu@chromium.org
cmumford@chromium.org
diff --git a/chromium/content/browser/indexed_db/indexed_db.h b/chromium/content/browser/indexed_db/indexed_db.h
index 3714d40af33..fc46e6d64ca 100644
--- a/chromium/content/browser/indexed_db/indexed_db.h
+++ b/chromium/content/browser/indexed_db/indexed_db.h
@@ -9,19 +9,6 @@ namespace content {
namespace indexed_db {
-enum TransactionMode {
- TRANSACTION_READ_ONLY = 0,
- TRANSACTION_READ_WRITE = 1,
- TRANSACTION_VERSION_CHANGE = 2
-};
-
-enum CursorDirection {
- CURSOR_NEXT = 0,
- CURSOR_NEXT_NO_DUPLICATE = 1,
- CURSOR_PREV = 2,
- CURSOR_PREV_NO_DUPLICATE = 3,
-};
-
enum CursorType {
CURSOR_KEY_AND_VALUE = 0,
CURSOR_KEY_ONLY
diff --git a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc
index b65b24725af..7bda0bbb3ec 100644
--- a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.cc
@@ -118,7 +118,7 @@ void IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe(
blob_key));
}
-webkit_blob::ShareableFileReference::FinalReleaseCallback
+storage::ShareableFileReference::FinalReleaseCallback
IndexedDBActiveBlobRegistry::GetFinalReleaseCallback(int64 database_id,
int64 blob_key) {
return base::Bind(
diff --git a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.h b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.h
index 92380e13260..b0ebe27fd7c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.h
+++ b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry.h
@@ -12,7 +12,7 @@
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
-#include "webkit/common/blob/shareable_file_reference.h"
+#include "storage/common/blob/shareable_file_reference.h"
namespace content {
@@ -31,8 +31,9 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
// Use DatabaseMetaDataKey::AllBlobsKey for "the whole database".
bool MarkDeletedCheckIfUsed(int64 database_id, int64 blob_key);
- webkit_blob::ShareableFileReference::FinalReleaseCallback
- GetFinalReleaseCallback(int64 database_id, int64 blob_key);
+ storage::ShareableFileReference::FinalReleaseCallback GetFinalReleaseCallback(
+ int64 database_id,
+ int64 blob_key);
// This closure holds a raw pointer to the IndexedDBActiveBlobRegistry,
// and may not be called after it is deleted.
base::Closure GetAddBlobRefCallback(int64 database_id, int64 blob_key);
@@ -42,6 +43,13 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
void ForceShutdown();
private:
+ // Maps blob_key -> IsDeleted; if the record's absent, it's not in active use
+ // and we don't care if it's deleted.
+ typedef std::map<int64, bool> SingleDBMap;
+ // Maps DB ID -> SingleDBMap
+ typedef std::map<int64, SingleDBMap> AllDBsMap;
+ typedef std::set<int64> DeletedDBSet;
+
void AddBlobRef(int64 database_id, int64 blob_key);
void ReleaseBlobRef(int64 database_id, int64 blob_key);
static void ReleaseBlobRefThreadSafe(
@@ -51,13 +59,6 @@ class CONTENT_EXPORT IndexedDBActiveBlobRegistry {
int64 blob_key,
const base::FilePath& unused);
- // Maps blob_key -> IsDeleted; if the record's absent, it's not in active use
- // and we don't care if it's deleted.
- typedef std::map<int64, bool> SingleDBMap;
- // Maps DB ID -> SingleDBMap
- typedef std::map<int64, SingleDBMap> AllDBsMap;
- typedef std::set<int64> DeletedDBSet;
-
AllDBsMap use_tracker_;
DeletedDBSet deleted_dbs_;
// As long as we've got blobs registered in use_tracker_,
diff --git a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc
index c8f84758f80..aa412cf0908 100644
--- a/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_active_blob_registry_unittest.cc
@@ -7,20 +7,20 @@
#include "base/test/test_simple_task_runner.h"
#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
+#include "content/browser/indexed_db/mock_indexed_db_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
-class MockIDBFactory : public IndexedDBFactory {
+class RegistryTestMockFactory : public MockIndexedDBFactory {
public:
- MockIDBFactory() : IndexedDBFactory(NULL), duplicate_calls_(false) {}
+ RegistryTestMockFactory() : duplicate_calls_(false) {}
- virtual void ReportOutstandingBlobs(const GURL& origin_url,
- bool blobs_outstanding) OVERRIDE {
+ void ReportOutstandingBlobs(const GURL& origin_url,
+ bool blobs_outstanding) override {
if (blobs_outstanding) {
if (origins_.count(origin_url)) {
duplicate_calls_ = true;
@@ -39,32 +39,34 @@ class MockIDBFactory : public IndexedDBFactory {
bool CheckNoOriginsInUse() const {
return !duplicate_calls_ && !origins_.size();
}
+
bool CheckSingleOriginInUse(const GURL& origin) const {
return !duplicate_calls_ && origins_.size() == 1 && origins_.count(origin);
}
- protected:
- virtual ~MockIDBFactory() {}
-
private:
+ ~RegistryTestMockFactory() override {}
+
std::set<GURL> origins_;
bool duplicate_calls_;
- DISALLOW_COPY_AND_ASSIGN(MockIDBFactory);
+ DISALLOW_COPY_AND_ASSIGN(RegistryTestMockFactory);
};
class MockIDBBackingStore : public IndexedDBFakeBackingStore {
public:
- MockIDBBackingStore(IndexedDBFactory* factory, base::TaskRunner* task_runner)
+ typedef std::pair<int64, int64> KeyPair;
+ typedef std::set<KeyPair> KeyPairSet;
+
+ MockIDBBackingStore(IndexedDBFactory* factory,
+ base::SequencedTaskRunner* task_runner)
: IndexedDBFakeBackingStore(factory, task_runner),
duplicate_calls_(false) {}
- virtual void ReportBlobUnused(int64 database_id, int64 blob_key) OVERRIDE {
+ void ReportBlobUnused(int64 database_id, int64 blob_key) override {
unused_blobs_.insert(std::make_pair(database_id, blob_key));
}
- typedef std::pair<int64, int64> KeyPair;
- typedef std::set<KeyPair> KeyPairSet;
bool CheckUnusedBlobsEmpty() const {
return !duplicate_calls_ && !unused_blobs_.size();
}
@@ -76,7 +78,7 @@ class MockIDBBackingStore : public IndexedDBFakeBackingStore {
const KeyPairSet& unused_blobs() const { return unused_blobs_; }
protected:
- virtual ~MockIDBBackingStore() {}
+ ~MockIDBBackingStore() override {}
private:
KeyPairSet unused_blobs_;
@@ -88,28 +90,29 @@ class MockIDBBackingStore : public IndexedDBFakeBackingStore {
// Base class for our test fixtures.
class IndexedDBActiveBlobRegistryTest : public testing::Test {
public:
+ typedef storage::ShareableFileReference::FinalReleaseCallback
+ ReleaseCallback;
+
+ static const int64 kDatabaseId0 = 7;
+ static const int64 kDatabaseId1 = 12;
+ static const int64 kBlobKey0 = 77;
+ static const int64 kBlobKey1 = 14;
+
IndexedDBActiveBlobRegistryTest()
: task_runner_(new base::TestSimpleTaskRunner),
- factory_(new MockIDBFactory),
- backing_store_(new MockIDBBackingStore(factory_, task_runner_)),
+ factory_(new RegistryTestMockFactory),
+ backing_store_(
+ new MockIDBBackingStore(factory_.get(), task_runner_.get())),
registry_(new IndexedDBActiveBlobRegistry(backing_store_.get())) {}
void RunUntilIdle() { task_runner_->RunUntilIdle(); }
- MockIDBFactory* factory() const { return factory_.get(); }
+ RegistryTestMockFactory* factory() const { return factory_.get(); }
MockIDBBackingStore* backing_store() const { return backing_store_.get(); }
IndexedDBActiveBlobRegistry* registry() const { return registry_.get(); }
- static const int64 kDatabaseId0 = 7;
- static const int64 kDatabaseId1 = 12;
- static const int64 kBlobKey0 = 77;
- static const int64 kBlobKey1 = 14;
-
- typedef webkit_blob::ShareableFileReference::FinalReleaseCallback
- ReleaseCallback;
-
private:
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- scoped_refptr<MockIDBFactory> factory_;
+ scoped_refptr<RegistryTestMockFactory> factory_;
scoped_refptr<MockIDBBackingStore> backing_store_;
scoped_ptr<IndexedDBActiveBlobRegistry> registry_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
index 0a83a914f84..781eadcdab8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -4,8 +4,8 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
@@ -24,6 +24,7 @@
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
+#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "content/common/indexed_db/indexed_db_key.h"
@@ -31,18 +32,18 @@
#include "content/common/indexed_db/indexed_db_key_range.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/fileapi/file_stream_writer.h"
+#include "storage/browser/fileapi/file_writer_delegate.h"
+#include "storage/browser/fileapi/local_file_stream_writer.h"
+#include "storage/common/database/database_identifier.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
#include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
#include "third_party/leveldatabase/env_chromium.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/fileapi/file_stream_writer.h"
-#include "webkit/browser/fileapi/file_writer_delegate.h"
-#include "webkit/browser/fileapi/local_file_stream_writer.h"
-#include "webkit/common/database/database_identifier.h"
using base::FilePath;
using base::StringPiece;
-using fileapi::FileWriterDelegate;
+using storage::FileWriterDelegate;
namespace content {
@@ -77,18 +78,18 @@ bool MakeIDBBlobDirectory(const FilePath& pathBase,
}
static std::string ComputeOriginIdentifier(const GURL& origin_url) {
- return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
+ return storage::GetIdentifierFromOrigin(origin_url) + "@1";
}
static base::FilePath ComputeFileName(const GURL& origin_url) {
return base::FilePath()
- .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
+ .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
.AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
}
static base::FilePath ComputeBlobPath(const GURL& origin_url) {
return base::FilePath()
- .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
+ .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
.AddExtension(FILE_PATH_LITERAL(".indexeddb.blob"));
}
@@ -347,7 +348,7 @@ WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
// TODO(ericu): Move this down into the member section of this file. I'm
// leaving it here for this CL as it's easier to see the diffs in place.
-WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
+WARN_UNUSED_RESULT leveldb::Status IndexedDBBackingStore::SetUpMetadata() {
const uint32 latest_known_data_version =
blink::kSerializedScriptValueVersion;
const std::string schema_version_key = SchemaVersionKey::Encode();
@@ -363,7 +364,7 @@ WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
if (!s.ok()) {
INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return s;
}
if (!found) {
// Initialize new backing store.
@@ -375,7 +376,7 @@ WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
// leftover from a partially-purged previous generation of data.
if (!base::DeleteFile(blob_path_, true)) {
INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return IOErrorStatus();
}
} else {
// Upgrade old backing store.
@@ -396,11 +397,11 @@ WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
s = GetInt(transaction.get(), it->Key(), &database_id, &found);
if (!s.ok()) {
INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return s;
}
if (!found) {
INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return InternalInconsistencyStatus();
}
std::string int_version_key = DatabaseMetaDataKey::Encode(
database_id, DatabaseMetaDataKey::USER_INT_VERSION);
@@ -419,14 +420,14 @@ WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
db_schema_version = 3;
if (!base::DeleteFile(blob_path_, true)) {
INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return IOErrorStatus();
}
}
}
if (!s.ok()) {
INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return s;
}
// All new values will be written using this serialization version.
@@ -434,11 +435,11 @@ WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
s = GetInt(transaction.get(), data_version_key, &db_data_version, &found);
if (!s.ok()) {
INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return s;
}
if (!found) {
INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
+ return InternalInconsistencyStatus();
}
if (db_data_version < latest_known_data_version) {
db_data_version = latest_known_data_version;
@@ -449,11 +450,9 @@ WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
DCHECK_EQ(db_data_version, latest_known_data_version);
s = transaction->Commit();
- if (!s.ok()) {
+ if (!s.ok())
INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
- return false;
- }
- return true;
+ return s;
}
template <typename DBOrTransaction>
@@ -487,14 +486,13 @@ WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId(
class DefaultLevelDBFactory : public LevelDBFactory {
public:
DefaultLevelDBFactory() {}
- virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full) OVERRIDE {
+ leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full) override {
return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
}
- virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
- OVERRIDE {
+ leveldb::Status DestroyLevelDB(const base::FilePath& file_name) override {
return LevelDBDatabase::Destroy(file_name);
}
@@ -564,7 +562,7 @@ static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key,
bool found = false;
leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found);
if (!s.ok()) {
- INTERNAL_READ_ERROR_UNTESTED(READ_BLOB_JOURNAL);
+ INTERNAL_READ_ERROR(READ_BLOB_JOURNAL);
return s;
}
journal->clear();
@@ -572,7 +570,7 @@ static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key,
return leveldb::Status::OK();
StringPiece slice(data);
if (!DecodeBlobJournal(&slice, journal)) {
- INTERNAL_READ_ERROR_UNTESTED(DECODE_BLOB_JOURNAL);
+ INTERNAL_CONSISTENCY_ERROR_UNTESTED(DECODE_BLOB_JOURNAL);
s = InternalInconsistencyStatus();
}
return s;
@@ -654,16 +652,14 @@ static leveldb::Status MergeDatabaseIntoLiveBlobJournal(
static std::string EncodeBlobData(
const std::vector<IndexedDBBlobInfo*>& blob_info) {
std::string ret;
- std::vector<IndexedDBBlobInfo*>::const_iterator iter;
- for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
- const IndexedDBBlobInfo& info = **iter;
- EncodeBool(info.is_file(), &ret);
- EncodeVarInt(info.key(), &ret);
- EncodeStringWithLength(info.type(), &ret);
- if (info.is_file())
- EncodeStringWithLength(info.file_name(), &ret);
+ for (const auto* info : blob_info) {
+ EncodeBool(info->is_file(), &ret);
+ EncodeVarInt(info->key(), &ret);
+ EncodeStringWithLength(info->type(), &ret);
+ if (info->is_file())
+ EncodeStringWithLength(info->file_name(), &ret);
else
- EncodeVarInt(info.size(), &ret);
+ EncodeVarInt(info->size(), &ret);
}
return ret;
}
@@ -709,7 +705,7 @@ IndexedDBBackingStore::IndexedDBBackingStore(
net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator,
- base::TaskRunner* task_runner)
+ base::SequencedTaskRunner* task_runner)
: indexed_db_factory_(indexed_db_factory),
origin_url_(origin_url),
blob_path_(blob_path),
@@ -725,12 +721,8 @@ IndexedDBBackingStore::~IndexedDBBackingStore() {
if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- std::set<int>::const_iterator iter;
- for (iter = child_process_ids_granted_.begin();
- iter != child_process_ids_granted_.end();
- ++iter) {
- policy->RevokeAllPermissionsForFile(*iter, blob_path_);
- }
+ for (const auto& pid : child_process_ids_granted_)
+ policy->RevokeAllPermissionsForFile(pid, blob_path_);
}
STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
incognito_blob_map_.end());
@@ -781,8 +773,9 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
bool* disk_full,
- base::TaskRunner* task_runner,
- bool clean_journal) {
+ base::SequencedTaskRunner* task_runner,
+ bool clean_journal,
+ leveldb::Status* status) {
*data_loss = blink::WebIDBDataLossNone;
DefaultLevelDBFactory leveldb_factory;
return IndexedDBBackingStore::Open(indexed_db_factory,
@@ -794,7 +787,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
disk_full,
&leveldb_factory,
task_runner,
- clean_journal);
+ clean_journal,
+ status);
}
static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
@@ -864,7 +858,7 @@ leveldb::Status IndexedDBBackingStore::DestroyBackingStore(
bool IndexedDBBackingStore::ReadCorruptionInfo(const base::FilePath& path_base,
const GURL& origin_url,
- std::string& message) {
+ std::string* message) {
const base::FilePath info_path =
path_base.Append(ComputeCorruptionFileName(origin_url));
@@ -891,7 +885,7 @@ bool IndexedDBBackingStore::ReadCorruptionInfo(const base::FilePath& path_base,
if (val && val->GetType() == base::Value::TYPE_DICTIONARY) {
base::DictionaryValue* dict_val =
static_cast<base::DictionaryValue*>(val.get());
- success = dict_val->GetString("message", &message);
+ success = dict_val->GetString("message", message);
}
}
file.Close();
@@ -934,14 +928,17 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
std::string* data_loss_message,
bool* is_disk_full,
LevelDBFactory* leveldb_factory,
- base::TaskRunner* task_runner,
- bool clean_journal) {
+ base::SequencedTaskRunner* task_runner,
+ bool clean_journal,
+ leveldb::Status* status) {
IDB_TRACE("IndexedDBBackingStore::Open");
DCHECK(!path_base.empty());
*data_loss = blink::WebIDBDataLossNone;
*data_loss_message = "";
*is_disk_full = false;
+ *status = leveldb::Status::OK();
+
scoped_ptr<LevelDBComparator> comparator(new Comparator());
if (!base::IsStringASCII(path_base.AsUTF8Unsafe())) {
@@ -949,8 +946,10 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
origin_url);
}
if (!base::CreateDirectory(path_base)) {
- LOG(ERROR) << "Unable to create IndexedDB database path "
- << path_base.AsUTF8Unsafe();
+ *status =
+ leveldb::Status::IOError("Unable to create IndexedDB database path");
+ LOG(ERROR) << status->ToString() << ": \"" << path_base.AsUTF8Unsafe()
+ << "\"";
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
origin_url);
return scoped_refptr<IndexedDBBackingStore>();
@@ -962,29 +961,30 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
path_base.Append(ComputeBlobPath(origin_url));
if (IsPathTooLong(file_path)) {
+ *status = leveldb::Status::IOError("File path too long");
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
origin_url);
return scoped_refptr<IndexedDBBackingStore>();
}
scoped_ptr<LevelDBDatabase> db;
- leveldb::Status status = leveldb_factory->OpenLevelDB(
+ *status = leveldb_factory->OpenLevelDB(
file_path, comparator.get(), &db, is_disk_full);
- DCHECK(!db == !status.ok());
- if (!status.ok()) {
- if (leveldb_env::IndicatesDiskFull(status)) {
+ DCHECK(!db == !status->ok());
+ if (!status->ok()) {
+ if (leveldb_env::IndicatesDiskFull(*status)) {
*is_disk_full = true;
- } else if (leveldb_env::IsCorruption(status)) {
+ } else if (leveldb_env::IsCorruption(*status)) {
*data_loss = blink::WebIDBDataLossTotal;
- *data_loss_message = leveldb_env::GetCorruptionMessage(status);
+ *data_loss_message = leveldb_env::GetCorruptionMessage(*status);
}
}
bool is_schema_known = false;
if (db) {
std::string corruption_message;
- if (ReadCorruptionInfo(path_base, origin_url, corruption_message)) {
+ if (ReadCorruptionInfo(path_base, origin_url, &corruption_message)) {
LOG(ERROR) << "IndexedDB recovering from a corrupted (and deleted) "
"database.";
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
@@ -1013,21 +1013,21 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
}
}
- DCHECK(status.ok() || !is_schema_known || leveldb_env::IsIOError(status) ||
- leveldb_env::IsCorruption(status));
+ DCHECK(status->ok() || !is_schema_known || leveldb_env::IsIOError(*status) ||
+ leveldb_env::IsCorruption(*status));
if (db) {
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url);
- } else if (leveldb_env::IsIOError(status)) {
+ } else if (leveldb_env::IsIOError(*status)) {
LOG(ERROR) << "Unable to open backing store, not trying to recover - "
- << status.ToString();
+ << status->ToString();
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, origin_url);
return scoped_refptr<IndexedDBBackingStore>();
} else {
- DCHECK(!is_schema_known || leveldb_env::IsCorruption(status));
+ DCHECK(!is_schema_known || leveldb_env::IsCorruption(*status));
LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
- status = leveldb_factory->DestroyLevelDB(file_path);
- if (!status.ok()) {
+ *status = leveldb_factory->DestroyLevelDB(file_path);
+ if (!status->ok()) {
LOG(ERROR) << "IndexedDB backing store cleanup failed";
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
origin_url);
@@ -1060,9 +1060,10 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
request_context,
db.Pass(),
comparator.Pass(),
- task_runner);
+ task_runner,
+ status);
- if (clean_journal && backing_store &&
+ if (clean_journal && backing_store.get() &&
!backing_store->CleanUpBlobJournal(LiveBlobJournalKey::Encode()).ok()) {
HistogramOpenStatus(
INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR, origin_url);
@@ -1074,17 +1075,19 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
const GURL& origin_url,
- base::TaskRunner* task_runner) {
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status) {
DefaultLevelDBFactory leveldb_factory;
return IndexedDBBackingStore::OpenInMemory(
- origin_url, &leveldb_factory, task_runner);
+ origin_url, &leveldb_factory, task_runner, status);
}
// static
scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
const GURL& origin_url,
LevelDBFactory* leveldb_factory,
- base::TaskRunner* task_runner) {
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status) {
IDB_TRACE("IndexedDBBackingStore::OpenInMemory");
scoped_ptr<LevelDBComparator> comparator(new Comparator());
@@ -1104,7 +1107,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
NULL /* request_context */,
db.Pass(),
comparator.Pass(),
- task_runner);
+ task_runner,
+ status);
}
// static
@@ -1115,7 +1119,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator,
- base::TaskRunner* task_runner) {
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status) {
// TODO(jsbell): Handle comparator name changes.
scoped_refptr<IndexedDBBackingStore> backing_store(
new IndexedDBBackingStore(indexed_db_factory,
@@ -1125,7 +1130,8 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
db.Pass(),
comparator.Pass(),
task_runner));
- if (!backing_store->SetUpMetadata())
+ *status = backing_store->SetUpMetadata();
+ if (!status->ok())
return scoped_refptr<IndexedDBBackingStore>();
return backing_store;
@@ -1154,6 +1160,7 @@ std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames(
for (*s = it->Seek(start_key);
s->ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
*s = it->Next()) {
+ // Decode database name (in iterator key).
StringPiece slice(it->Key());
DatabaseNameKey database_name_key;
if (!DatabaseNameKey::Decode(&slice, &database_name_key) ||
@@ -1161,11 +1168,35 @@ std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames(
INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
continue;
}
- found_names.push_back(database_name_key.database_name());
+
+ // Decode database id (in iterator value).
+ int64 database_id = 0;
+ StringPiece valueSlice(it->Value());
+ if (!DecodeInt(&valueSlice, &database_id) || !valueSlice.empty()) {
+ INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
+ continue;
+ }
+
+ // Look up version by id.
+ bool found = false;
+ int64 database_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
+ *s = GetVarInt(db_.get(),
+ DatabaseMetaDataKey::Encode(
+ database_id, DatabaseMetaDataKey::USER_INT_VERSION),
+ &database_version,
+ &found);
+ if (!s->ok() || !found) {
+ INTERNAL_READ_ERROR_UNTESTED(GET_DATABASE_NAMES);
+ continue;
+ }
+
+ // Ignore stale metadata from failed initial opens.
+ if (database_version != IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
+ found_names.push_back(database_name_key.database_name());
}
if (!s->ok())
- INTERNAL_READ_ERROR_UNTESTED(GET_DATABASE_NAMES);
+ INTERNAL_READ_ERROR(GET_DATABASE_NAMES);
return found_names;
}
@@ -1276,6 +1307,7 @@ leveldb::Status IndexedDBBackingStore::CreateIDBDatabaseMetaData(
const base::string16& version,
int64 int_version,
int64* row_id) {
+ // TODO(jsbell): Don't persist metadata if open fails. http://crbug.com/395472
scoped_refptr<LevelDBTransaction> transaction =
IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
@@ -1861,8 +1893,8 @@ leveldb::Status IndexedDBBackingStore::PutRecord(
int64 database_id,
int64 object_store_id,
const IndexedDBKey& key,
- IndexedDBValue& value,
- ScopedVector<webkit_blob::BlobDataHandle>* handles,
+ IndexedDBValue* value,
+ ScopedVector<storage::BlobDataHandle>* handles,
RecordIdentifier* record_identifier) {
IDB_TRACE("IndexedDBBackingStore::PutRecord");
if (!KeyPrefix::ValidIds(database_id, object_store_id))
@@ -1881,13 +1913,13 @@ leveldb::Status IndexedDBBackingStore::PutRecord(
std::string v;
EncodeVarInt(version, &v);
- v.append(value.bits);
+ v.append(value->bits);
leveldb_transaction->Put(object_store_data_key, &v);
s = transaction->PutBlobInfoIfNeeded(database_id,
object_store_id,
object_store_data_key,
- &value.blob_info,
+ &value->blob_info,
handles);
if (!s.ok())
return s;
@@ -1961,7 +1993,7 @@ leveldb::Status IndexedDBBackingStore::DeleteRange(
database_id,
object_store_id,
key_range,
- indexed_db::CURSOR_NEXT,
+ blink::WebIDBCursorDirectionNext,
&s);
if (!s.ok())
return s;
@@ -1973,7 +2005,7 @@ leveldb::Status IndexedDBBackingStore::DeleteRange(
database_id,
object_store_id,
key_range,
- indexed_db::CURSOR_PREV,
+ blink::WebIDBCursorDirectionPrev,
&s);
if (!s.ok())
@@ -2161,25 +2193,24 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
ChainedBlobWriterImpl(
int64 database_id,
IndexedDBBackingStore* backing_store,
- WriteDescriptorVec& blobs,
+ WriteDescriptorVec* blobs,
scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
: waiting_for_callback_(false),
database_id_(database_id),
backing_store_(backing_store),
callback_(callback),
aborted_(false) {
- blobs_.swap(blobs);
+ blobs_.swap(*blobs);
iter_ = blobs_.begin();
backing_store->task_runner()->PostTask(
FROM_HERE, base::Bind(&ChainedBlobWriterImpl::WriteNextFile, this));
}
- virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE {
+ void set_delegate(scoped_ptr<FileWriterDelegate> delegate) override {
delegate_.reset(delegate.release());
}
- virtual void ReportWriteCompletion(bool succeeded,
- int64 bytes_written) OVERRIDE {
+ void ReportWriteCompletion(bool succeeded, int64 bytes_written) override {
DCHECK(waiting_for_callback_);
DCHECK(!succeeded || bytes_written >= 0);
waiting_for_callback_ = false;
@@ -2200,7 +2231,7 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
}
}
- virtual void Abort() OVERRIDE {
+ void Abort() override {
if (!waiting_for_callback_)
return;
self_ref_ = this;
@@ -2208,13 +2239,13 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
}
private:
- virtual ~ChainedBlobWriterImpl() {}
+ ~ChainedBlobWriterImpl() override {}
void WriteNextFile() {
DCHECK(!waiting_for_callback_);
DCHECK(!aborted_);
if (iter_ == blobs_.end()) {
- DCHECK(!self_ref_);
+ DCHECK(!self_ref_.get());
callback_->Run(true);
return;
} else {
@@ -2240,11 +2271,11 @@ class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
};
class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
- public base::RefCounted<LocalWriteClosure> {
+ public base::RefCountedThreadSafe<LocalWriteClosure> {
public:
LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
chained_blob_writer,
- base::TaskRunner* task_runner)
+ base::SequencedTaskRunner* task_runner)
: chained_blob_writer_(chained_blob_writer),
task_runner_(task_runner),
bytes_written_(0) {}
@@ -2264,19 +2295,23 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
}
task_runner_->PostTask(
FROM_HERE,
- base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner,
- this,
- write_status == FileWriterDelegate::SUCCESS_COMPLETED));
+ base::Bind(&IndexedDBBackingStore::Transaction::ChainedBlobWriter::
+ ReportWriteCompletion,
+ chained_blob_writer_,
+ write_status == FileWriterDelegate::SUCCESS_COMPLETED,
+ bytes_written_));
}
void writeBlobToFileOnIOThread(const FilePath& file_path,
const GURL& blob_url,
net::URLRequestContext* request_context) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- scoped_ptr<fileapi::FileStreamWriter> writer(
- fileapi::FileStreamWriter::CreateForLocalFile(
- task_runner_, file_path, 0,
- fileapi::FileStreamWriter::CREATE_NEW_FILE));
+ scoped_ptr<storage::FileStreamWriter> writer(
+ storage::FileStreamWriter::CreateForLocalFile(
+ task_runner_.get(),
+ file_path,
+ 0,
+ storage::FileStreamWriter::CREATE_NEW_FILE));
scoped_ptr<FileWriterDelegate> delegate(
new FileWriterDelegate(writer.Pass(),
FileWriterDelegate::FLUSH_ON_COMPLETION));
@@ -2291,16 +2326,21 @@ class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
}
private:
- virtual ~LocalWriteClosure() {}
- friend class base::RefCounted<LocalWriteClosure>;
-
- void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
+ virtual ~LocalWriteClosure() {
+ // Make sure the last reference to a ChainedBlobWriter is released (and
+ // deleted) on the IDB thread since it owns a transaction which has thread
+ // affinity.
+ IndexedDBBackingStore::Transaction::ChainedBlobWriter* raw_tmp =
+ chained_blob_writer_.get();
+ raw_tmp->AddRef();
+ chained_blob_writer_ = NULL;
+ task_runner_->ReleaseSoon(FROM_HERE, raw_tmp);
}
+ friend class base::RefCountedThreadSafe<LocalWriteClosure>;
- IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
- base::TaskRunner* task_runner_;
+ scoped_refptr<IndexedDBBackingStore::Transaction::ChainedBlobWriter>
+ chained_blob_writer_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
int64 bytes_written_;
DISALLOW_COPY_AND_ASSIGN(LocalWriteClosure);
@@ -2348,7 +2388,7 @@ bool IndexedDBBackingStore::WriteBlobFile(
} else {
DCHECK(descriptor.url().is_valid());
scoped_refptr<LocalWriteClosure> write_closure(
- new LocalWriteClosure(chained_blob_writer, task_runner_));
+ new LocalWriteClosure(chained_blob_writer, task_runner_.get()));
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
@@ -2582,11 +2622,9 @@ leveldb::Status IndexedDBBackingStore::CleanUpBlobJournal(
return s;
if (!journal.size())
return leveldb::Status::OK();
- BlobJournalType::iterator journal_iter;
- for (journal_iter = journal.begin(); journal_iter != journal.end();
- ++journal_iter) {
- int64 database_id = journal_iter->first;
- int64 blob_key = journal_iter->second;
+ for (const auto& entry : journal) {
+ int64 database_id = entry.first;
+ int64 blob_key = entry.second;
DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
if (!RemoveBlobDirectory(database_id))
@@ -2630,34 +2668,33 @@ leveldb::Status IndexedDBBackingStore::Transaction::GetBlobInfoForRecord(
NOTREACHED();
return InternalInconsistencyStatus();
}
- scoped_ptr<LevelDBIterator> it = transaction()->CreateIterator();
std::string encoded_key = blob_entry_key.Encode();
- leveldb::Status s = it->Seek(encoded_key);
+ bool found;
+ std::string encoded_value;
+ leveldb::Status s = transaction()->Get(encoded_key, &encoded_value, &found);
if (!s.ok())
return s;
- if (it->IsValid() && CompareKeys(it->Key(), encoded_key) == 0) {
- if (!DecodeBlobData(it->Value().as_string(), &value->blob_info)) {
+ if (found) {
+ if (!DecodeBlobData(encoded_value, &value->blob_info)) {
INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD);
return InternalInconsistencyStatus();
}
- std::vector<IndexedDBBlobInfo>::iterator iter;
- for (iter = value->blob_info.begin(); iter != value->blob_info.end();
- ++iter) {
- iter->set_file_path(
- backing_store_->GetBlobFileName(database_id, iter->key()));
- iter->set_mark_used_callback(
+ for (auto& entry : value->blob_info) {
+ entry.set_file_path(
+ backing_store_->GetBlobFileName(database_id, entry.key()));
+ entry.set_mark_used_callback(
backing_store_->active_blob_registry()->GetAddBlobRefCallback(
- database_id, iter->key()));
- iter->set_release_callback(
+ database_id, entry.key()));
+ entry.set_release_callback(
backing_store_->active_blob_registry()->GetFinalReleaseCallback(
- database_id, iter->key()));
- if (iter->is_file()) {
+ database_id, entry.key()));
+ if (entry.is_file()) {
base::File::Info info;
- if (base::GetFileInfo(iter->file_path(), &info)) {
+ if (base::GetFileInfo(entry.file_path(), &info)) {
// This should always work, but it isn't fatal if it doesn't; it just
// means a potential slow synchronous call from the renderer later.
- iter->set_last_modified(info.last_modified);
- iter->set_size(info.size);
+ entry.set_last_modified(info.last_modified);
+ entry.set_size(info.size);
}
}
}
@@ -2797,21 +2834,21 @@ leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord(
static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction,
const std::string& target,
std::string* found_key,
- leveldb::Status& s) {
+ leveldb::Status* s) {
scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
- s = it->Seek(target);
- if (!s.ok())
+ *s = it->Seek(target);
+ if (!s->ok())
return false;
if (!it->IsValid()) {
- s = it->SeekToLast();
- if (!s.ok() || !it->IsValid())
+ *s = it->SeekToLast();
+ if (!s->ok() || !it->IsValid())
return false;
}
while (CompareIndexKeys(it->Key(), target) > 0) {
- s = it->Prev();
- if (!s.ok() || !it->IsValid())
+ *s = it->Prev();
+ if (!s->ok() || !it->IsValid())
return false;
}
@@ -2819,8 +2856,8 @@ static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction,
*found_key = it->Key().as_string();
// There can be several index keys that compare equal. We want the last one.
- s = it->Next();
- } while (s.ok() && it->IsValid() && !CompareIndexKeys(it->Key(), target));
+ *s = it->Next();
+ } while (s->ok() && it->IsValid() && !CompareIndexKeys(it->Key(), target));
return true;
}
@@ -3010,7 +3047,7 @@ IndexedDBBackingStore::Cursor::Cursor(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
const CursorOptions& cursor_options)
- : backing_store_(backing_store),
+ : backing_store_(backing_store.get()),
transaction_(transaction),
database_id_(database_id),
cursor_options_(cursor_options) {
@@ -3049,19 +3086,20 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
// TODO(alecflett): avoid a copy here?
IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey();
- bool first_iteration = true;
-
// When iterating with PrevNoDuplicate, spec requires that the
// value we yield for each key is the first duplicate in forwards
// order.
IndexedDBKey last_duplicate_key;
bool forward = cursor_options_.forward;
+ bool first_iteration_forward = forward;
+ bool flipped = false;
for (;;) {
if (next_state == SEEK) {
// TODO(jsbell): Optimize seeking for reverse cursors as well.
- if (first_iteration && key && forward) {
+ if (first_iteration_forward && key) {
+ first_iteration_forward = false;
std::string leveldb_key;
if (primary_key) {
leveldb_key = EncodeKey(*key, *primary_key);
@@ -3069,7 +3107,6 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
leveldb_key = EncodeKey(*key);
}
*s = iterator_->Seek(leveldb_key);
- first_iteration = false;
} else if (forward) {
*s = iterator_->Next();
} else {
@@ -3086,6 +3123,7 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
// We need to walk forward because we hit the end of
// the data.
forward = true;
+ flipped = true;
continue;
}
@@ -3097,6 +3135,7 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
// We need to walk forward because now we're beyond the
// bounds defined by the cursor.
forward = true;
+ flipped = true;
continue;
}
@@ -3116,7 +3155,7 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
if (primary_key && current_key_->Equals(*key) &&
this->primary_key().IsLessThan(*primary_key))
continue;
- if (current_key_->IsLessThan(*key))
+ if (!flipped && current_key_->IsLessThan(*key))
continue;
} else {
if (primary_key && key->Equals(*current_key_) &&
@@ -3145,6 +3184,7 @@ bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
// between key ranges.
if (!last_duplicate_key.Equals(*current_key_)) {
forward = true;
+ flipped = true;
continue;
}
@@ -3210,24 +3250,22 @@ class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
database_id,
cursor_options) {}
- virtual Cursor* Clone() OVERRIDE {
- return new ObjectStoreKeyCursorImpl(this);
- }
+ Cursor* Clone() override { return new ObjectStoreKeyCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual IndexedDBValue* value() OVERRIDE {
+ IndexedDBValue* value() override {
NOTREACHED();
return NULL;
}
- virtual bool LoadCurrentRow() OVERRIDE;
+ bool LoadCurrentRow() override;
protected:
- virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key) override {
return ObjectStoreDataKey::Encode(
cursor_options_.database_id, cursor_options_.object_store_id, key);
}
- virtual std::string EncodeKey(const IndexedDBKey& key,
- const IndexedDBKey& primary_key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) override {
NOTREACHED();
return std::string();
}
@@ -3276,19 +3314,19 @@ class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
database_id,
cursor_options) {}
- virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
+ Cursor* Clone() override { return new ObjectStoreCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
- virtual bool LoadCurrentRow() OVERRIDE;
+ IndexedDBValue* value() override { return &current_value_; }
+ bool LoadCurrentRow() override;
protected:
- virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key) override {
return ObjectStoreDataKey::Encode(
cursor_options_.database_id, cursor_options_.object_store_id, key);
}
- virtual std::string EncodeKey(const IndexedDBKey& key,
- const IndexedDBKey& primary_key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) override {
NOTREACHED();
return std::string();
}
@@ -3346,32 +3384,30 @@ class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
database_id,
cursor_options) {}
- virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
+ Cursor* Clone() override { return new IndexKeyCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual IndexedDBValue* value() OVERRIDE {
+ IndexedDBValue* value() override {
NOTREACHED();
return NULL;
}
- virtual const IndexedDBKey& primary_key() const OVERRIDE {
- return *primary_key_;
- }
- virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
- const OVERRIDE {
+ const IndexedDBKey& primary_key() const override { return *primary_key_; }
+ const IndexedDBBackingStore::RecordIdentifier& record_identifier()
+ const override {
NOTREACHED();
return record_identifier_;
}
- virtual bool LoadCurrentRow() OVERRIDE;
+ bool LoadCurrentRow() override;
protected:
- virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key) override {
return IndexDataKey::Encode(cursor_options_.database_id,
cursor_options_.object_store_id,
cursor_options_.index_id,
key);
}
- virtual std::string EncodeKey(const IndexedDBKey& key,
- const IndexedDBKey& primary_key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) override {
return IndexDataKey::Encode(cursor_options_.database_id,
cursor_options_.object_store_id,
cursor_options_.index_id,
@@ -3461,29 +3497,27 @@ class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
database_id,
cursor_options) {}
- virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
+ Cursor* Clone() override { return new IndexCursorImpl(this); }
// IndexedDBBackingStore::Cursor
- virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
- virtual const IndexedDBKey& primary_key() const OVERRIDE {
- return *primary_key_;
- }
- virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
- const OVERRIDE {
+ IndexedDBValue* value() override { return &current_value_; }
+ const IndexedDBKey& primary_key() const override { return *primary_key_; }
+ const IndexedDBBackingStore::RecordIdentifier& record_identifier()
+ const override {
NOTREACHED();
return record_identifier_;
}
- virtual bool LoadCurrentRow() OVERRIDE;
+ bool LoadCurrentRow() override;
protected:
- virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key) override {
return IndexDataKey::Encode(cursor_options_.database_id,
cursor_options_.object_store_id,
cursor_options_.index_id,
key);
}
- virtual std::string EncodeKey(const IndexedDBKey& key,
- const IndexedDBKey& primary_key) OVERRIDE {
+ std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) override {
return IndexDataKey::Encode(cursor_options_.database_id,
cursor_options_.object_store_id,
cursor_options_.index_id,
@@ -3573,7 +3607,7 @@ bool ObjectStoreCursorOptions(
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
cursor_options->database_id = database_id;
cursor_options->object_store_id = object_store_id;
@@ -3581,10 +3615,11 @@ bool ObjectStoreCursorOptions(
bool lower_bound = range.lower().IsValid();
bool upper_bound = range.upper().IsValid();
cursor_options->forward =
- (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
- direction == indexed_db::CURSOR_NEXT);
- cursor_options->unique = (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
- direction == indexed_db::CURSOR_PREV_NO_DUPLICATE);
+ (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
+ direction == blink::WebIDBCursorDirectionNext);
+ cursor_options->unique =
+ (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
+ direction == blink::WebIDBCursorDirectionPrevNoDuplicate);
if (!lower_bound) {
cursor_options->low_key =
@@ -3610,7 +3645,7 @@ bool ObjectStoreCursorOptions(
if (!FindGreatestKeyLessThanOrEqual(transaction,
cursor_options->high_key,
&cursor_options->high_key,
- s))
+ &s))
return false;
cursor_options->high_open = false;
}
@@ -3624,7 +3659,7 @@ bool ObjectStoreCursorOptions(
std::string found_high_key;
// TODO(cmumford): Handle this error (crbug.com/363397)
if (!FindGreatestKeyLessThanOrEqual(
- transaction, cursor_options->high_key, &found_high_key, s))
+ transaction, cursor_options->high_key, &found_high_key, &s))
return false;
// If the target key should not be included, but we end up with a smaller
@@ -3646,7 +3681,7 @@ bool IndexCursorOptions(
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
DCHECK(transaction);
if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
@@ -3659,10 +3694,11 @@ bool IndexCursorOptions(
bool lower_bound = range.lower().IsValid();
bool upper_bound = range.upper().IsValid();
cursor_options->forward =
- (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
- direction == indexed_db::CURSOR_NEXT);
- cursor_options->unique = (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
- direction == indexed_db::CURSOR_PREV_NO_DUPLICATE);
+ (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
+ direction == blink::WebIDBCursorDirectionNext);
+ cursor_options->unique =
+ (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
+ direction == blink::WebIDBCursorDirectionPrevNoDuplicate);
if (!lower_bound) {
cursor_options->low_key =
@@ -3685,7 +3721,7 @@ bool IndexCursorOptions(
if (!FindGreatestKeyLessThanOrEqual(transaction,
cursor_options->high_key,
&cursor_options->high_key,
- s))
+ &s))
return false;
cursor_options->high_open = false;
}
@@ -3698,7 +3734,7 @@ bool IndexCursorOptions(
// Seek to the *last* key in the set of non-unique keys
// TODO(cmumford): Handle this error (crbug.com/363397)
if (!FindGreatestKeyLessThanOrEqual(
- transaction, cursor_options->high_key, &found_high_key, s))
+ transaction, cursor_options->high_key, &found_high_key, &s))
return false;
// If the target key should not be included, but we end up with a smaller
@@ -3719,7 +3755,7 @@ IndexedDBBackingStore::OpenObjectStoreCursor(
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
leveldb::Status* s) {
IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor");
*s = leveldb::Status::OK();
@@ -3737,7 +3773,7 @@ IndexedDBBackingStore::OpenObjectStoreCursor(
if (!cursor->FirstSeek(s))
return scoped_ptr<IndexedDBBackingStore::Cursor>();
- return cursor.PassAs<IndexedDBBackingStore::Cursor>();
+ return cursor.Pass();
}
scoped_ptr<IndexedDBBackingStore::Cursor>
@@ -3746,7 +3782,7 @@ IndexedDBBackingStore::OpenObjectStoreKeyCursor(
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
leveldb::Status* s) {
IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
*s = leveldb::Status::OK();
@@ -3764,7 +3800,7 @@ IndexedDBBackingStore::OpenObjectStoreKeyCursor(
if (!cursor->FirstSeek(s))
return scoped_ptr<IndexedDBBackingStore::Cursor>();
- return cursor.PassAs<IndexedDBBackingStore::Cursor>();
+ return cursor.Pass();
}
scoped_ptr<IndexedDBBackingStore::Cursor>
@@ -3774,7 +3810,7 @@ IndexedDBBackingStore::OpenIndexKeyCursor(
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
leveldb::Status* s) {
IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
*s = leveldb::Status::OK();
@@ -3793,7 +3829,7 @@ IndexedDBBackingStore::OpenIndexKeyCursor(
if (!cursor->FirstSeek(s))
return scoped_ptr<IndexedDBBackingStore::Cursor>();
- return cursor.PassAs<IndexedDBBackingStore::Cursor>();
+ return cursor.Pass();
}
scoped_ptr<IndexedDBBackingStore::Cursor>
@@ -3803,7 +3839,7 @@ IndexedDBBackingStore::OpenIndexCursor(
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
leveldb::Status* s) {
IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
LevelDBTransaction* leveldb_transaction = transaction->transaction();
@@ -3821,7 +3857,7 @@ IndexedDBBackingStore::OpenIndexCursor(
if (!cursor->FirstSeek(s))
return scoped_ptr<IndexedDBBackingStore::Cursor>();
- return cursor.PassAs<IndexedDBBackingStore::Cursor>();
+ return cursor.Pass();
}
IndexedDBBackingStore::Transaction::Transaction(
@@ -3844,11 +3880,8 @@ void IndexedDBBackingStore::Transaction::Begin() {
// If incognito, this snapshots blobs just as the above transaction_
// constructor snapshots the leveldb.
- BlobChangeMap::const_iterator iter;
- for (iter = backing_store_->incognito_blob_map_.begin();
- iter != backing_store_->incognito_blob_map_.end();
- ++iter)
- incognito_blob_map_[iter->first] = iter->second->Clone().release();
+ for (const auto& iter : backing_store_->incognito_blob_map_)
+ incognito_blob_map_[iter.first] = iter.second->Clone().release();
}
static GURL getURLFromUUID(const string& uuid) {
@@ -3861,21 +3894,17 @@ leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
if (backing_store_->is_incognito())
return leveldb::Status::OK();
- BlobChangeMap::iterator iter = blob_change_map_.begin();
new_blob_entries->clear();
new_files_to_write->clear();
- if (iter != blob_change_map_.end()) {
+ if (!blob_change_map_.empty()) {
// Create LevelDBTransaction for the name generator seed and add-journal.
scoped_refptr<LevelDBTransaction> pre_transaction =
IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
backing_store_->db_.get());
BlobJournalType journal;
- for (; iter != blob_change_map_.end(); ++iter) {
- std::vector<IndexedDBBlobInfo>::iterator info_iter;
+ for (auto& iter : blob_change_map_) {
std::vector<IndexedDBBlobInfo*> new_blob_keys;
- for (info_iter = iter->second->mutable_blob_info().begin();
- info_iter != iter->second->mutable_blob_info().end();
- ++info_iter) {
+ for (auto& entry : iter.second->mutable_blob_info()) {
int64 next_blob_key = -1;
bool result = GetBlobKeyGeneratorCurrentNumber(
pre_transaction.get(), database_id_, &next_blob_key);
@@ -3884,27 +3913,27 @@ leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
BlobJournalEntryType journal_entry =
std::make_pair(database_id_, next_blob_key);
journal.push_back(journal_entry);
- if (info_iter->is_file()) {
+ if (entry.is_file()) {
new_files_to_write->push_back(
- WriteDescriptor(info_iter->file_path(),
+ WriteDescriptor(entry.file_path(),
next_blob_key,
- info_iter->size(),
- info_iter->last_modified()));
+ entry.size(),
+ entry.last_modified()));
} else {
new_files_to_write->push_back(
- WriteDescriptor(getURLFromUUID(info_iter->uuid()),
+ WriteDescriptor(getURLFromUUID(entry.uuid()),
next_blob_key,
- info_iter->size()));
+ entry.size()));
}
- info_iter->set_key(next_blob_key);
- new_blob_keys.push_back(&*info_iter);
+ entry.set_key(next_blob_key);
+ new_blob_keys.push_back(&entry);
result = UpdateBlobKeyGeneratorCurrentNumber(
pre_transaction.get(), database_id_, next_blob_key + 1);
if (!result)
return InternalInconsistencyStatus();
}
BlobEntryKey blob_entry_key;
- StringPiece key_piece(iter->second->key());
+ StringPiece key_piece(iter.second->key());
if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
NOTREACHED();
return InternalInconsistencyStatus();
@@ -3924,40 +3953,35 @@ bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
if (backing_store_->is_incognito())
return true;
- BlobChangeMap::const_iterator iter = blob_change_map_.begin();
// Look up all old files to remove as part of the transaction, store their
// names in blobs_to_remove_, and remove their old blob data entries.
- if (iter != blob_change_map_.end()) {
- scoped_ptr<LevelDBIterator> db_iter = transaction_->CreateIterator();
- for (; iter != blob_change_map_.end(); ++iter) {
- BlobEntryKey blob_entry_key;
- StringPiece key_piece(iter->second->key());
- if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
- NOTREACHED();
- INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
+ for (const auto& iter : blob_change_map_) {
+ BlobEntryKey blob_entry_key;
+ StringPiece key_piece(iter.second->key());
+ if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
+ NOTREACHED();
+ INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
+ transaction_ = NULL;
+ return false;
+ }
+ if (database_id_ < 0)
+ database_id_ = blob_entry_key.database_id();
+ else
+ DCHECK_EQ(database_id_, blob_entry_key.database_id());
+ std::string blob_entry_key_bytes = blob_entry_key.Encode();
+ bool found;
+ std::string blob_entry_value_bytes;
+ leveldb::Status s = transaction_->Get(
+ blob_entry_key_bytes, &blob_entry_value_bytes, &found);
+ if (s.ok() && found) {
+ std::vector<IndexedDBBlobInfo> blob_info;
+ if (!DecodeBlobData(blob_entry_value_bytes, &blob_info)) {
+ INTERNAL_READ_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
transaction_ = NULL;
return false;
}
- if (database_id_ < 0)
- database_id_ = blob_entry_key.database_id();
- else
- DCHECK_EQ(database_id_, blob_entry_key.database_id());
- std::string blob_entry_key_bytes = blob_entry_key.Encode();
- db_iter->Seek(blob_entry_key_bytes);
- if (db_iter->IsValid() &&
- !CompareKeys(db_iter->Key(), blob_entry_key_bytes)) {
- std::vector<IndexedDBBlobInfo> blob_info;
- if (!DecodeBlobData(db_iter->Value().as_string(), &blob_info)) {
- INTERNAL_READ_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
- transaction_ = NULL;
- return false;
- }
- std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
- for (blob_info_iter = blob_info.begin();
- blob_info_iter != blob_info.end();
- ++blob_info_iter)
- blobs_to_remove_.push_back(
- std::make_pair(database_id_, blob_info_iter->key()));
+ for (const auto& blob : blob_info) {
+ blobs_to_remove_.push_back(std::make_pair(database_id_, blob.key()));
transaction_->Remove(blob_entry_key_bytes);
}
}
@@ -3968,14 +3992,12 @@ bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
leveldb::Status IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
IndexedDBActiveBlobRegistry* registry =
backing_store_->active_blob_registry();
- BlobJournalType::iterator iter;
BlobJournalType primary_journal, live_blob_journal;
- for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
- ++iter) {
- if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
- live_blob_journal.push_back(*iter);
+ for (const auto& iter : blobs_to_remove_) {
+ if (registry->MarkDeletedCheckIfUsed(iter.first, iter.second))
+ live_blob_journal.push_back(iter);
else
- primary_journal.push_back(*iter);
+ primary_journal.push_back(iter);
}
UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
leveldb::Status s =
@@ -3990,14 +4012,14 @@ leveldb::Status IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
scoped_refptr<BlobWriteCallback> callback) {
IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseOne");
- DCHECK(transaction_);
+ DCHECK(transaction_.get());
DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
leveldb::Status s;
s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
if (!s.ok()) {
- INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
+ INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
transaction_ = NULL;
return s;
}
@@ -4022,7 +4044,7 @@ leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
if (new_files_to_write.size()) {
// This kicks off the writes of the new blobs, if any.
// This call will zero out new_blob_entries and new_files_to_write.
- WriteNewBlobs(new_blob_entries, new_files_to_write, callback);
+ WriteNewBlobs(&new_blob_entries, &new_files_to_write, callback);
// Remove the add journal, if any; once the blobs are written, and we
// commit, this will do the cleanup.
ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
@@ -4050,22 +4072,20 @@ leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) {
BlobChangeMap& target_map = backing_store_->incognito_blob_map_;
- BlobChangeMap::iterator iter;
- for (iter = blob_change_map_.begin(); iter != blob_change_map_.end();
- ++iter) {
- BlobChangeMap::iterator target_record = target_map.find(iter->first);
+ for (auto& iter : blob_change_map_) {
+ BlobChangeMap::iterator target_record = target_map.find(iter.first);
if (target_record != target_map.end()) {
delete target_record->second;
target_map.erase(target_record);
}
- if (iter->second) {
- target_map[iter->first] = iter->second;
- iter->second = NULL;
+ if (iter.second) {
+ target_map[iter.first] = iter.second;
+ iter.second = NULL;
}
}
}
if (!s.ok())
- INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
+ INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
else if (blobs_to_remove_.size())
s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
@@ -4079,14 +4099,14 @@ class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
scoped_refptr<BlobWriteCallback> callback)
: transaction_(transaction), callback_(callback) {}
- virtual void Run(bool succeeded) OVERRIDE {
+ void Run(bool succeeded) override {
callback_->Run(succeeded);
if (succeeded) // Else it's already been deleted during rollback.
transaction_->chained_blob_writer_ = NULL;
}
private:
- virtual ~BlobWriteCallbackWrapper() {}
+ ~BlobWriteCallbackWrapper() override {}
friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>;
IndexedDBBackingStore::Transaction* transaction_;
@@ -4096,22 +4116,19 @@ class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
};
void IndexedDBBackingStore::Transaction::WriteNewBlobs(
- BlobEntryKeyValuePairVec& new_blob_entries,
- WriteDescriptorVec& new_files_to_write,
+ BlobEntryKeyValuePairVec* new_blob_entries,
+ WriteDescriptorVec* new_files_to_write,
scoped_refptr<BlobWriteCallback> callback) {
- DCHECK_GT(new_files_to_write.size(), 0UL);
+ DCHECK_GT(new_files_to_write->size(), 0UL);
DCHECK_GT(database_id_, 0);
- BlobEntryKeyValuePairVec::iterator blob_entry_iter;
- for (blob_entry_iter = new_blob_entries.begin();
- blob_entry_iter != new_blob_entries.end();
- ++blob_entry_iter) {
+ for (auto& blob_entry_iter : *new_blob_entries) {
// Add the new blob-table entry for each blob to the main transaction, or
// remove any entry that may exist if there's no new one.
- if (!blob_entry_iter->second.size())
- transaction_->Remove(blob_entry_iter->first.Encode());
+ if (!blob_entry_iter.second.size())
+ transaction_->Remove(blob_entry_iter.first.Encode());
else
- transaction_->Put(blob_entry_iter->first.Encode(),
- &blob_entry_iter->second);
+ transaction_->Put(blob_entry_iter.first.Encode(),
+ &blob_entry_iter.second);
}
// Creating the writer will start it going asynchronously.
chained_blob_writer_ =
@@ -4123,11 +4140,12 @@ void IndexedDBBackingStore::Transaction::WriteNewBlobs(
void IndexedDBBackingStore::Transaction::Rollback() {
IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
- DCHECK(transaction_.get());
- if (chained_blob_writer_) {
+ if (chained_blob_writer_.get()) {
chained_blob_writer_->Abort();
chained_blob_writer_ = NULL;
}
+ if (transaction_.get() == NULL)
+ return;
transaction_->Rollback();
transaction_ = NULL;
}
@@ -4149,7 +4167,7 @@ void IndexedDBBackingStore::BlobChangeRecord::SetBlobInfo(
}
void IndexedDBBackingStore::BlobChangeRecord::SetHandles(
- ScopedVector<webkit_blob::BlobDataHandle>* handles) {
+ ScopedVector<storage::BlobDataHandle>* handles) {
handles_.clear();
if (handles)
handles_.swap(*handles);
@@ -4161,9 +4179,8 @@ IndexedDBBackingStore::BlobChangeRecord::Clone() const {
new BlobChangeRecord(key_, object_store_id_));
record->blob_info_ = blob_info_;
- ScopedVector<webkit_blob::BlobDataHandle>::const_iterator iter;
- for (iter = handles_.begin(); iter != handles_.end(); ++iter)
- record->handles_.push_back(new webkit_blob::BlobDataHandle(**iter));
+ for (const auto* handle : handles_)
+ record->handles_.push_back(new storage::BlobDataHandle(*handle));
return record.Pass();
}
@@ -4172,7 +4189,7 @@ leveldb::Status IndexedDBBackingStore::Transaction::PutBlobInfoIfNeeded(
int64 object_store_id,
const std::string& object_store_data_key,
std::vector<IndexedDBBlobInfo>* blob_info,
- ScopedVector<webkit_blob::BlobDataHandle>* handles) {
+ ScopedVector<storage::BlobDataHandle>* handles) {
if (!blob_info || blob_info->empty()) {
blob_change_map_.erase(object_store_data_key);
incognito_blob_map_.erase(object_store_data_key);
@@ -4207,7 +4224,7 @@ void IndexedDBBackingStore::Transaction::PutBlobInfo(
int64 object_store_id,
const std::string& object_store_data_key,
std::vector<IndexedDBBlobInfo>* blob_info,
- ScopedVector<webkit_blob::BlobDataHandle>* handles) {
+ ScopedVector<storage::BlobDataHandle>* handles) {
DCHECK_GT(object_store_data_key.size(), 0UL);
if (database_id_ < 0)
database_id_ = database_id;
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
index 59e381f2fef..a15b2372a6b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -29,15 +29,15 @@
#include "content/common/indexed_db/indexed_db_key.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_data_handle.h"
namespace base {
-class TaskRunner;
+class SequencedTaskRunner;
}
-namespace fileapi {
+namespace storage {
class FileWriterDelegate;
}
@@ -50,33 +50,255 @@ namespace content {
class IndexedDBFactory;
class LevelDBComparator;
class LevelDBDatabase;
+class LevelDBFactory;
struct IndexedDBValue;
-class LevelDBFactory {
- public:
- virtual ~LevelDBFactory() {}
- virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full) = 0;
- virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) = 0;
-};
-
class CONTENT_EXPORT IndexedDBBackingStore
: public base::RefCounted<IndexedDBBackingStore> {
public:
- class CONTENT_EXPORT Transaction;
-
class CONTENT_EXPORT Comparator : public LevelDBComparator {
public:
- virtual int Compare(const base::StringPiece& a,
- const base::StringPiece& b) const OVERRIDE;
- virtual const char* Name() const OVERRIDE;
+ int Compare(const base::StringPiece& a,
+ const base::StringPiece& b) const override;
+ const char* Name() const override;
+ };
+
+ class CONTENT_EXPORT RecordIdentifier {
+ public:
+ RecordIdentifier(const std::string& primary_key, int64 version);
+ RecordIdentifier();
+ ~RecordIdentifier();
+
+ const std::string& primary_key() const { return primary_key_; }
+ int64 version() const { return version_; }
+ void Reset(const std::string& primary_key, int64 version) {
+ primary_key_ = primary_key;
+ version_ = version;
+ }
+
+ private:
+ // TODO(jsbell): Make it more clear that this is the *encoded* version of
+ // the key.
+ std::string primary_key_;
+ int64 version_;
+ DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
+ };
+
+ class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
+ public:
+ virtual void Run(bool succeeded) = 0;
+
+ protected:
+ friend class base::RefCounted<BlobWriteCallback>;
+ virtual ~BlobWriteCallback() {}
+ };
+
+ class BlobChangeRecord {
+ public:
+ BlobChangeRecord(const std::string& key, int64 object_store_id);
+ ~BlobChangeRecord();
+
+ const std::string& key() const { return key_; }
+ int64 object_store_id() const { return object_store_id_; }
+ void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info);
+ std::vector<IndexedDBBlobInfo>& mutable_blob_info() { return blob_info_; }
+ const std::vector<IndexedDBBlobInfo>& blob_info() const {
+ return blob_info_;
+ }
+ void SetHandles(ScopedVector<storage::BlobDataHandle>* handles);
+ scoped_ptr<BlobChangeRecord> Clone() const;
+
+ private:
+ std::string key_;
+ int64 object_store_id_;
+ std::vector<IndexedDBBlobInfo> blob_info_;
+ ScopedVector<storage::BlobDataHandle> handles_;
+ DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord);
+ };
+ typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
+
+ class CONTENT_EXPORT Transaction {
+ public:
+ explicit Transaction(IndexedDBBackingStore* backing_store);
+ virtual ~Transaction();
+
+ virtual void Begin();
+ // The callback will be called eventually on success or failure, or
+ // immediately if phase one is complete due to lack of any blobs to write.
+ virtual leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>);
+ virtual leveldb::Status CommitPhaseTwo();
+ virtual void Rollback();
+ void Reset() {
+ backing_store_ = NULL;
+ transaction_ = NULL;
+ }
+ leveldb::Status PutBlobInfoIfNeeded(
+ int64 database_id,
+ int64 object_store_id,
+ const std::string& object_store_data_key,
+ std::vector<IndexedDBBlobInfo>*,
+ ScopedVector<storage::BlobDataHandle>* handles);
+ void PutBlobInfo(int64 database_id,
+ int64 object_store_id,
+ const std::string& object_store_data_key,
+ std::vector<IndexedDBBlobInfo>*,
+ ScopedVector<storage::BlobDataHandle>* handles);
+
+ LevelDBTransaction* transaction() { return transaction_.get(); }
+
+ leveldb::Status GetBlobInfoForRecord(
+ int64 database_id,
+ const std::string& object_store_data_key,
+ IndexedDBValue* value);
+
+ // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
+ // under that key.
+ typedef std::vector<std::pair<BlobEntryKey, std::string> >
+ BlobEntryKeyValuePairVec;
+
+ class WriteDescriptor {
+ public:
+ WriteDescriptor(const GURL& url, int64_t key, int64_t size);
+ WriteDescriptor(const base::FilePath& path,
+ int64_t key,
+ int64_t size,
+ base::Time last_modified);
+
+ bool is_file() const { return is_file_; }
+ const GURL& url() const {
+ DCHECK(!is_file_);
+ return url_;
+ }
+ const base::FilePath& file_path() const {
+ DCHECK(is_file_);
+ return file_path_;
+ }
+ int64_t key() const { return key_; }
+ int64_t size() const { return size_; }
+ base::Time last_modified() const { return last_modified_; }
+
+ private:
+ bool is_file_;
+ GURL url_;
+ base::FilePath file_path_;
+ int64_t key_;
+ int64_t size_;
+ base::Time last_modified_;
+ };
+
+ class ChainedBlobWriter
+ : public base::RefCountedThreadSafe<ChainedBlobWriter> {
+ public:
+ virtual void set_delegate(
+ scoped_ptr<storage::FileWriterDelegate> delegate) = 0;
+
+ // TODO(ericu): Add a reason in the event of failure.
+ virtual void ReportWriteCompletion(bool succeeded,
+ int64 bytes_written) = 0;
+
+ virtual void Abort() = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<ChainedBlobWriter>;
+ virtual ~ChainedBlobWriter() {}
+ };
+
+ class ChainedBlobWriterImpl;
+
+ typedef std::vector<WriteDescriptor> WriteDescriptorVec;
+
+ private:
+ class BlobWriteCallbackWrapper;
+
+ leveldb::Status HandleBlobPreTransaction(
+ BlobEntryKeyValuePairVec* new_blob_entries,
+ WriteDescriptorVec* new_files_to_write);
+ // Returns true on success, false on failure.
+ bool CollectBlobFilesToRemove();
+ // The callback will be called eventually on success or failure.
+ void WriteNewBlobs(BlobEntryKeyValuePairVec* new_blob_entries,
+ WriteDescriptorVec* new_files_to_write,
+ scoped_refptr<BlobWriteCallback> callback);
+ leveldb::Status SortBlobsToRemove();
+
+ IndexedDBBackingStore* backing_store_;
+ scoped_refptr<LevelDBTransaction> transaction_;
+ BlobChangeMap blob_change_map_;
+ BlobChangeMap incognito_blob_map_;
+ int64 database_id_;
+ BlobJournalType blobs_to_remove_;
+ scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
+ };
+
+ class Cursor {
+ public:
+ enum IteratorState { READY = 0, SEEK };
+
+ virtual ~Cursor();
+
+ struct CursorOptions {
+ CursorOptions();
+ ~CursorOptions();
+ int64 database_id;
+ int64 object_store_id;
+ int64 index_id;
+ std::string low_key;
+ bool low_open;
+ std::string high_key;
+ bool high_open;
+ bool forward;
+ bool unique;
+ };
+
+ const IndexedDBKey& key() const { return *current_key_; }
+ bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
+ bool Continue(const IndexedDBKey* key,
+ IteratorState state,
+ leveldb::Status* s) {
+ return Continue(key, NULL, state, s);
+ }
+ bool Continue(const IndexedDBKey* key,
+ const IndexedDBKey* primary_key,
+ IteratorState state,
+ leveldb::Status*);
+ bool Advance(uint32 count, leveldb::Status*);
+ bool FirstSeek(leveldb::Status*);
+
+ virtual Cursor* Clone() = 0;
+ virtual const IndexedDBKey& primary_key() const;
+ virtual IndexedDBValue* value() = 0;
+ virtual const RecordIdentifier& record_identifier() const;
+ virtual bool LoadCurrentRow() = 0;
+
+ protected:
+ Cursor(scoped_refptr<IndexedDBBackingStore> backing_store,
+ Transaction* transaction,
+ int64 database_id,
+ const CursorOptions& cursor_options);
+ explicit Cursor(const IndexedDBBackingStore::Cursor* other);
+
+ virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
+ virtual std::string EncodeKey(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key) = 0;
+
+ bool IsPastBounds() const;
+ bool HaveEnteredRange() const;
+
+ IndexedDBBackingStore* backing_store_;
+ Transaction* transaction_;
+ int64 database_id_;
+ const CursorOptions cursor_options_;
+ scoped_ptr<LevelDBIterator> iterator_;
+ scoped_ptr<IndexedDBKey> current_key_;
+ IndexedDBBackingStore::RecordIdentifier record_identifier_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Cursor);
};
const GURL& origin_url() const { return origin_url_; }
IndexedDBFactory* factory() const { return indexed_db_factory_; }
- base::TaskRunner* task_runner() const { return task_runner_; }
+ base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
return &close_timer_;
}
@@ -92,8 +314,9 @@ class CONTENT_EXPORT IndexedDBBackingStore
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
bool* disk_full,
- base::TaskRunner* task_runner,
- bool clean_journal);
+ base::SequencedTaskRunner* task_runner,
+ bool clean_journal,
+ leveldb::Status* status);
static scoped_refptr<IndexedDBBackingStore> Open(
IndexedDBFactory* indexed_db_factory,
const GURL& origin_url,
@@ -103,15 +326,18 @@ class CONTENT_EXPORT IndexedDBBackingStore
std::string* data_loss_message,
bool* disk_full,
LevelDBFactory* leveldb_factory,
- base::TaskRunner* task_runner,
- bool clean_journal);
+ base::SequencedTaskRunner* task_runner,
+ bool clean_journal,
+ leveldb::Status* status);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
const GURL& origin_url,
- base::TaskRunner* task_runner);
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status);
static scoped_refptr<IndexedDBBackingStore> OpenInMemory(
const GURL& origin_url,
LevelDBFactory* leveldb_factory,
- base::TaskRunner* task_runner);
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status);
void GrantChildProcessPermissions(int child_process_id);
@@ -154,36 +380,6 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64 database_id,
int64 object_store_id) WARN_UNUSED_RESULT;
- class CONTENT_EXPORT RecordIdentifier {
- public:
- RecordIdentifier(const std::string& primary_key, int64 version);
- RecordIdentifier();
- ~RecordIdentifier();
-
- const std::string& primary_key() const { return primary_key_; }
- int64 version() const { return version_; }
- void Reset(const std::string& primary_key, int64 version) {
- primary_key_ = primary_key;
- version_ = version;
- }
-
- private:
- // TODO(jsbell): Make it more clear that this is the *encoded* version of
- // the key.
- std::string primary_key_;
- int64 version_;
- DISALLOW_COPY_AND_ASSIGN(RecordIdentifier);
- };
-
- class BlobWriteCallback : public base::RefCounted<BlobWriteCallback> {
- public:
- virtual void Run(bool succeeded) = 0;
-
- protected:
- virtual ~BlobWriteCallback() {}
- friend class base::RefCounted<BlobWriteCallback>;
- };
-
virtual leveldb::Status GetRecord(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
@@ -195,8 +391,8 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64 database_id,
int64 object_store_id,
const IndexedDBKey& key,
- IndexedDBValue& value,
- ScopedVector<webkit_blob::BlobDataHandle>* handles,
+ IndexedDBValue* value,
+ ScopedVector<storage::BlobDataHandle>* handles,
RecordIdentifier* record) WARN_UNUSED_RESULT;
virtual leveldb::Status ClearObjectStore(
IndexedDBBackingStore::Transaction* transaction,
@@ -273,88 +469,19 @@ class CONTENT_EXPORT IndexedDBBackingStore
base::FilePath GetBlobFileName(int64 database_id, int64 key);
- class Cursor {
- public:
- virtual ~Cursor();
-
- enum IteratorState {
- READY = 0,
- SEEK
- };
-
- struct CursorOptions {
- CursorOptions();
- ~CursorOptions();
- int64 database_id;
- int64 object_store_id;
- int64 index_id;
- std::string low_key;
- bool low_open;
- std::string high_key;
- bool high_open;
- bool forward;
- bool unique;
- };
-
- const IndexedDBKey& key() const { return *current_key_; }
- bool Continue(leveldb::Status* s) { return Continue(NULL, NULL, SEEK, s); }
- bool Continue(const IndexedDBKey* key,
- IteratorState state,
- leveldb::Status* s) {
- return Continue(key, NULL, state, s);
- }
- bool Continue(const IndexedDBKey* key,
- const IndexedDBKey* primary_key,
- IteratorState state,
- leveldb::Status*);
- bool Advance(uint32 count, leveldb::Status*);
- bool FirstSeek(leveldb::Status*);
-
- virtual Cursor* Clone() = 0;
- virtual const IndexedDBKey& primary_key() const;
- virtual IndexedDBValue* value() = 0;
- virtual const RecordIdentifier& record_identifier() const;
- virtual bool LoadCurrentRow() = 0;
-
- protected:
- Cursor(scoped_refptr<IndexedDBBackingStore> backing_store,
- Transaction* transaction,
- int64 database_id,
- const CursorOptions& cursor_options);
- explicit Cursor(const IndexedDBBackingStore::Cursor* other);
-
- virtual std::string EncodeKey(const IndexedDBKey& key) = 0;
- virtual std::string EncodeKey(const IndexedDBKey& key,
- const IndexedDBKey& primary_key) = 0;
-
- bool IsPastBounds() const;
- bool HaveEnteredRange() const;
-
- IndexedDBBackingStore* backing_store_;
- Transaction* transaction_;
- int64 database_id_;
- const CursorOptions cursor_options_;
- scoped_ptr<LevelDBIterator> iterator_;
- scoped_ptr<IndexedDBKey> current_key_;
- IndexedDBBackingStore::RecordIdentifier record_identifier_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Cursor);
- };
-
virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status*);
virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
IndexedDBBackingStore::Transaction* transaction,
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status*);
virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
IndexedDBBackingStore::Transaction* transaction,
@@ -362,7 +489,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status*);
virtual scoped_ptr<Cursor> OpenIndexCursor(
IndexedDBBackingStore::Transaction* transaction,
@@ -370,157 +497,24 @@ class CONTENT_EXPORT IndexedDBBackingStore
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status*);
- class BlobChangeRecord {
- public:
- BlobChangeRecord(const std::string& key, int64 object_store_id);
- ~BlobChangeRecord();
- const std::string& key() const { return key_; }
- int64 object_store_id() const { return object_store_id_; }
- void SetBlobInfo(std::vector<IndexedDBBlobInfo>* blob_info);
- std::vector<IndexedDBBlobInfo>& mutable_blob_info() { return blob_info_; }
- const std::vector<IndexedDBBlobInfo>& blob_info() const {
- return blob_info_;
- }
- void SetHandles(ScopedVector<webkit_blob::BlobDataHandle>* handles);
- scoped_ptr<BlobChangeRecord> Clone() const;
-
- private:
- std::string key_;
- int64 object_store_id_;
- std::vector<IndexedDBBlobInfo> blob_info_;
- ScopedVector<webkit_blob::BlobDataHandle> handles_;
- DISALLOW_COPY_AND_ASSIGN(BlobChangeRecord);
- };
- typedef std::map<std::string, BlobChangeRecord*> BlobChangeMap;
-
- class Transaction {
- public:
- explicit Transaction(IndexedDBBackingStore* backing_store);
- virtual ~Transaction();
- virtual void Begin();
- // The callback will be called eventually on success or failure, or
- // immediately if phase one is complete due to lack of any blobs to write.
- virtual leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>);
- virtual leveldb::Status CommitPhaseTwo();
- virtual void Rollback();
- void Reset() {
- backing_store_ = NULL;
- transaction_ = NULL;
- }
- leveldb::Status PutBlobInfoIfNeeded(
- int64 database_id,
- int64 object_store_id,
- const std::string& object_store_data_key,
- std::vector<IndexedDBBlobInfo>*,
- ScopedVector<webkit_blob::BlobDataHandle>* handles);
- void PutBlobInfo(int64 database_id,
- int64 object_store_id,
- const std::string& object_store_data_key,
- std::vector<IndexedDBBlobInfo>*,
- ScopedVector<webkit_blob::BlobDataHandle>* handles);
-
- LevelDBTransaction* transaction() { return transaction_; }
-
- leveldb::Status GetBlobInfoForRecord(
- int64 database_id,
- const std::string& object_store_data_key,
- IndexedDBValue* value);
-
- // This holds a BlobEntryKey and the encoded IndexedDBBlobInfo vector stored
- // under that key.
- typedef std::vector<std::pair<BlobEntryKey, std::string> >
- BlobEntryKeyValuePairVec;
-
- class WriteDescriptor {
- public:
- WriteDescriptor(const GURL& url, int64_t key, int64_t size);
- WriteDescriptor(const base::FilePath& path,
- int64_t key,
- int64_t size,
- base::Time last_modified);
-
- bool is_file() const { return is_file_; }
- const GURL& url() const {
- DCHECK(!is_file_);
- return url_;
- }
- const base::FilePath& file_path() const {
- DCHECK(is_file_);
- return file_path_;
- }
- int64_t key() const { return key_; }
- int64_t size() const { return size_; }
- base::Time last_modified() const { return last_modified_; }
-
- private:
- bool is_file_;
- GURL url_;
- base::FilePath file_path_;
- int64_t key_;
- int64_t size_;
- base::Time last_modified_;
- };
-
- class ChainedBlobWriter : public base::RefCounted<ChainedBlobWriter> {
- public:
- virtual void set_delegate(
- scoped_ptr<fileapi::FileWriterDelegate> delegate) = 0;
-
- // TODO(ericu): Add a reason in the event of failure.
- virtual void ReportWriteCompletion(bool succeeded,
- int64 bytes_written) = 0;
-
- virtual void Abort() = 0;
-
- protected:
- virtual ~ChainedBlobWriter() {}
- friend class base::RefCounted<ChainedBlobWriter>;
- };
-
- class ChainedBlobWriterImpl;
-
- typedef std::vector<WriteDescriptor> WriteDescriptorVec;
-
- private:
- class BlobWriteCallbackWrapper;
-
- leveldb::Status HandleBlobPreTransaction(
- BlobEntryKeyValuePairVec* new_blob_entries,
- WriteDescriptorVec* new_files_to_write);
- // Returns true on success, false on failure.
- bool CollectBlobFilesToRemove();
- // The callback will be called eventually on success or failure.
- void WriteNewBlobs(BlobEntryKeyValuePairVec& new_blob_entries,
- WriteDescriptorVec& new_files_to_write,
- scoped_refptr<BlobWriteCallback> callback);
- leveldb::Status SortBlobsToRemove();
-
- IndexedDBBackingStore* backing_store_;
- scoped_refptr<LevelDBTransaction> transaction_;
- BlobChangeMap blob_change_map_;
- BlobChangeMap incognito_blob_map_;
- int64 database_id_;
- BlobJournalType blobs_to_remove_;
- scoped_refptr<ChainedBlobWriter> chained_blob_writer_;
- };
-
protected:
+ friend class base::RefCounted<IndexedDBBackingStore>;
+
IndexedDBBackingStore(IndexedDBFactory* indexed_db_factory,
const GURL& origin_url,
const base::FilePath& blob_path,
net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator,
- base::TaskRunner* task_runner);
+ base::SequencedTaskRunner* task_runner);
virtual ~IndexedDBBackingStore();
- friend class base::RefCounted<IndexedDBBackingStore>;
bool is_incognito() const { return !indexed_db_factory_; }
- bool SetUpMetadata();
+ leveldb::Status SetUpMetadata();
virtual bool WriteBlobFile(
int64 database_id,
@@ -538,11 +532,12 @@ class CONTENT_EXPORT IndexedDBBackingStore
net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator,
- base::TaskRunner* task_runner);
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status);
static bool ReadCorruptionInfo(const base::FilePath& path_base,
const GURL& origin_url,
- std::string& message);
+ std::string* message);
leveldb::Status FindKeyInIndex(
IndexedDBBackingStore::Transaction* transaction,
@@ -572,7 +567,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
const std::string origin_identifier_;
net::URLRequestContext* request_context_;
- base::TaskRunner* task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
std::set<int> child_process_ids_granted_;
BlobChangeMap incognito_blob_map_;
base::OneShotTimer<IndexedDBBackingStore> journal_cleaning_timer_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index 76d6d5fa526..da9bcda9386 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -5,23 +5,26 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/sequenced_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_value.h"
+#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
#include "content/public/test/mock_special_storage_policy.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/quota/special_storage_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/quota/special_storage_policy.h"
using base::ASCIIToUTF16;
@@ -31,24 +34,23 @@ namespace {
class Comparator : public LevelDBComparator {
public:
- virtual int Compare(const base::StringPiece& a,
- const base::StringPiece& b) const OVERRIDE {
+ int Compare(const base::StringPiece& a,
+ const base::StringPiece& b) const override {
return content::Compare(a, b, false /*index_keys*/);
}
- virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
+ const char* Name() const override { return "idb_cmp1"; }
};
class DefaultLevelDBFactory : public LevelDBFactory {
public:
DefaultLevelDBFactory() {}
- virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full) OVERRIDE {
+ leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full) override {
return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
}
- virtual leveldb::Status DestroyLevelDB(
- const base::FilePath& file_name) OVERRIDE {
+ leveldb::Status DestroyLevelDB(const base::FilePath& file_name) override {
return LevelDBDatabase::Destroy(file_name);
}
@@ -64,23 +66,26 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
const base::FilePath& path_base,
net::URLRequestContext* request_context,
LevelDBFactory* leveldb_factory,
- base::TaskRunner* task_runner) {
+ base::SequencedTaskRunner* task_runner,
+ leveldb::Status* status) {
DCHECK(!path_base.empty());
scoped_ptr<LevelDBComparator> comparator(new Comparator());
- if (!base::CreateDirectory(path_base))
+ if (!base::CreateDirectory(path_base)) {
+ *status = leveldb::Status::IOError("Unable to create base dir");
return scoped_refptr<TestableIndexedDBBackingStore>();
+ }
const base::FilePath file_path = path_base.AppendASCII("test_db_path");
const base::FilePath blob_path = path_base.AppendASCII("test_blob_path");
scoped_ptr<LevelDBDatabase> db;
bool is_disk_full = false;
- leveldb::Status status = leveldb_factory->OpenLevelDB(
+ *status = leveldb_factory->OpenLevelDB(
file_path, comparator.get(), &db, &is_disk_full);
- if (!db || !status.ok())
+ if (!db || !status->ok())
return scoped_refptr<TestableIndexedDBBackingStore>();
scoped_refptr<TestableIndexedDBBackingStore> backing_store(
@@ -92,7 +97,8 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
comparator.Pass(),
task_runner));
- if (!backing_store->SetUpMetadata())
+ *status = backing_store->SetUpMetadata();
+ if (!status->ok())
return scoped_refptr<TestableIndexedDBBackingStore>();
return backing_store;
@@ -107,12 +113,12 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
void ClearRemovals() { removals_.clear(); }
protected:
- virtual ~TestableIndexedDBBackingStore() {}
+ ~TestableIndexedDBBackingStore() override {}
- virtual bool WriteBlobFile(
+ bool WriteBlobFile(
int64 database_id,
const Transaction::WriteDescriptor& descriptor,
- Transaction::ChainedBlobWriter* chained_blob_writer) OVERRIDE {
+ Transaction::ChainedBlobWriter* chained_blob_writer) override {
if (KeyPrefix::IsValidDatabaseId(database_id_)) {
if (database_id_ != database_id) {
return false;
@@ -130,7 +136,7 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
return true;
}
- virtual bool RemoveBlobFile(int64 database_id, int64 key) OVERRIDE {
+ bool RemoveBlobFile(int64 database_id, int64 key) override {
if (database_id_ != database_id ||
!KeyPrefix::IsValidDatabaseId(database_id)) {
return false;
@@ -140,7 +146,7 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
}
// Timers don't play nicely with unit tests.
- virtual void StartJournalCleaningTimer() OVERRIDE {
+ void StartJournalCleaningTimer() override {
CleanPrimaryJournalIgnoreReturn();
}
@@ -151,7 +157,7 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
net::URLRequestContext* request_context,
scoped_ptr<LevelDBDatabase> db,
scoped_ptr<LevelDBComparator> comparator,
- base::TaskRunner* task_runner)
+ base::SequencedTaskRunner* task_runner)
: IndexedDBBackingStore(indexed_db_factory,
origin_url,
blob_path,
@@ -168,10 +174,10 @@ class TestableIndexedDBBackingStore : public IndexedDBBackingStore {
DISALLOW_COPY_AND_ASSIGN(TestableIndexedDBBackingStore);
};
-class TestIDBFactory : public IndexedDBFactory {
+class TestIDBFactory : public IndexedDBFactoryImpl {
public:
explicit TestIDBFactory(IndexedDBContextImpl* idb_context)
- : IndexedDBFactory(idb_context) {}
+ : IndexedDBFactoryImpl(idb_context) {}
scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest(
const GURL& origin,
@@ -179,36 +185,40 @@ class TestIDBFactory : public IndexedDBFactory {
blink::WebIDBDataLoss data_loss;
std::string data_loss_reason;
bool disk_full;
+ leveldb::Status status;
scoped_refptr<IndexedDBBackingStore> backing_store =
OpenBackingStore(origin,
context()->data_path(),
url_request_context,
&data_loss,
&data_loss_reason,
- &disk_full);
+ &disk_full,
+ &status);
scoped_refptr<TestableIndexedDBBackingStore> testable_store =
static_cast<TestableIndexedDBBackingStore*>(backing_store.get());
return testable_store;
}
protected:
- virtual ~TestIDBFactory() {}
+ ~TestIDBFactory() override {}
- virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
+ scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
const GURL& origin_url,
const base::FilePath& data_directory,
net::URLRequestContext* request_context,
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
bool* disk_full,
- bool first_time) OVERRIDE {
+ bool first_time,
+ leveldb::Status* status) override {
DefaultLevelDBFactory leveldb_factory;
return TestableIndexedDBBackingStore::Open(this,
origin_url,
data_directory,
request_context,
&leveldb_factory,
- context()->TaskRunner());
+ context()->TaskRunner(),
+ status);
}
private:
@@ -218,15 +228,17 @@ class TestIDBFactory : public IndexedDBFactory {
class IndexedDBBackingStoreTest : public testing::Test {
public:
IndexedDBBackingStoreTest() {}
- virtual void SetUp() {
+ void SetUp() override {
const GURL origin("http://localhost:81");
task_runner_ = new base::TestSimpleTaskRunner();
special_storage_policy_ = new MockSpecialStoragePolicy();
special_storage_policy_->SetAllUnlimited(true);
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- idb_context_ = new IndexedDBContextImpl(
- temp_dir_.path(), special_storage_policy_, NULL, task_runner_);
- idb_factory_ = new TestIDBFactory(idb_context_);
+ idb_context_ = new IndexedDBContextImpl(temp_dir_.path(),
+ special_storage_policy_.get(),
+ NULL,
+ task_runner_.get());
+ idb_factory_ = new TestIDBFactory(idb_context_.get());
backing_store_ =
idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
@@ -318,6 +330,9 @@ class IndexedDBBackingStoreTest : public testing::Test {
}
protected:
+ // Must be initialized before url_request_context_
+ content::TestBrowserThreadBundle thread_bundle_;
+
base::ScopedTempDir temp_dir_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
@@ -343,7 +358,7 @@ class IndexedDBBackingStoreTest : public testing::Test {
class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
public:
TestCallback() : called(false), succeeded(false) {}
- virtual void Run(bool succeeded_in) OVERRIDE {
+ void Run(bool succeeded_in) override {
called = true;
succeeded = succeeded_in;
}
@@ -351,7 +366,7 @@ class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
bool succeeded;
protected:
- virtual ~TestCallback() {}
+ ~TestCallback() override {}
private:
DISALLOW_COPY_AND_ASSIGN(TestCallback);
@@ -359,12 +374,12 @@ class TestCallback : public IndexedDBBackingStore::BlobWriteCallback {
TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
{
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store_->PutRecord(
- &transaction1, 1, 1, m_key1, m_value1, &handles, &record);
+ &transaction1, 1, 1, m_key1, &m_value1, &handles, &record);
EXPECT_TRUE(s.ok());
scoped_refptr<TestCallback> callback(new TestCallback());
EXPECT_TRUE(transaction1.CommitPhaseOne(callback).ok());
@@ -374,7 +389,7 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
}
{
- IndexedDBBackingStore::Transaction transaction2(backing_store_);
+ IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
EXPECT_TRUE(
@@ -391,15 +406,15 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistency) {
TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
{
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
1,
m_key3,
- m_value3,
+ &m_value3,
&handles,
&record).ok());
scoped_refptr<TestCallback> callback(new TestCallback());
@@ -412,7 +427,7 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
}
{
- IndexedDBBackingStore::Transaction transaction2(backing_store_);
+ IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
EXPECT_TRUE(
@@ -429,7 +444,7 @@ TEST_F(IndexedDBBackingStoreTest, PutGetConsistencyWithBlobs) {
}
{
- IndexedDBBackingStore::Transaction transaction3(backing_store_);
+ IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
transaction3.Begin();
IndexedDBValue result_value;
EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
@@ -476,36 +491,36 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key0,
- value0,
+ &value0,
&handles,
&record).ok());
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key1,
- value1,
+ &value1,
&handles,
&record).ok());
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key2,
- value2,
+ &value2,
&handles,
&record).ok());
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key3,
- value3,
+ &value3,
&handles,
&record).ok());
scoped_refptr<TestCallback> callback(new TestCallback());
@@ -517,7 +532,7 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRange) {
}
{
- IndexedDBBackingStore::Transaction transaction2(backing_store_);
+ IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
EXPECT_TRUE(
@@ -566,36 +581,36 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
IndexedDBValue value1 = IndexedDBValue("value1", blob_info1);
IndexedDBValue value2 = IndexedDBValue("value2", blob_info2);
IndexedDBValue value3 = IndexedDBValue("value3", blob_info3);
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key0,
- value0,
+ &value0,
&handles,
&record).ok());
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key1,
- value1,
+ &value1,
&handles,
&record).ok());
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key2,
- value2,
+ &value2,
&handles,
&record).ok());
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
i + 1,
key3,
- value3,
+ &value3,
&handles,
&record).ok());
scoped_refptr<TestCallback> callback(new TestCallback());
@@ -607,7 +622,7 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
}
{
- IndexedDBBackingStore::Transaction transaction2(backing_store_);
+ IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
EXPECT_TRUE(
@@ -625,15 +640,15 @@ TEST_F(IndexedDBBackingStoreTest, DeleteRangeEmptyRange) {
TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
{
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
EXPECT_TRUE(backing_store_->PutRecord(&transaction1,
1,
1,
m_key3,
- m_value3,
+ &m_value3,
&handles,
&record).ok());
scoped_refptr<TestCallback> callback(new TestCallback());
@@ -647,7 +662,7 @@ TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
IndexedDBValue read_result_value;
{
- IndexedDBBackingStore::Transaction transaction2(backing_store_);
+ IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
EXPECT_TRUE(
backing_store_->GetRecord(
@@ -667,7 +682,7 @@ TEST_F(IndexedDBBackingStoreTest, LiveBlobJournal) {
}
{
- IndexedDBBackingStore::Transaction transaction3(backing_store_);
+ IndexedDBBackingStore::Transaction transaction3(backing_store_.get());
transaction3.Begin();
EXPECT_TRUE(backing_store_->DeleteRange(&transaction3,
1,
@@ -704,15 +719,15 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
std::string index_key_raw;
EncodeIDBKey(index_key, &index_key_raw);
{
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store_->PutRecord(&transaction1,
high_database_id,
high_object_store_id,
m_key1,
- m_value1,
+ &m_value1,
&handles,
&record);
EXPECT_TRUE(s.ok());
@@ -743,7 +758,7 @@ TEST_F(IndexedDBBackingStoreTest, HighIds) {
}
{
- IndexedDBBackingStore::Transaction transaction2(backing_store_);
+ IndexedDBBackingStore::Transaction transaction2(backing_store_.get());
transaction2.Begin();
IndexedDBValue result_value;
leveldb::Status s = backing_store_->GetRecord(&transaction2,
@@ -792,32 +807,32 @@ TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
IndexedDBValue result_value;
- IndexedDBBackingStore::Transaction transaction1(backing_store_);
+ IndexedDBBackingStore::Transaction transaction1(backing_store_.get());
transaction1.Begin();
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
IndexedDBBackingStore::RecordIdentifier record;
leveldb::Status s = backing_store_->PutRecord(&transaction1,
database_id,
KeyPrefix::kInvalidId,
m_key1,
- m_value1,
+ &m_value1,
&handles,
&record);
EXPECT_FALSE(s.ok());
s = backing_store_->PutRecord(
- &transaction1, database_id, 0, m_key1, m_value1, &handles, &record);
+ &transaction1, database_id, 0, m_key1, &m_value1, &handles, &record);
EXPECT_FALSE(s.ok());
s = backing_store_->PutRecord(&transaction1,
KeyPrefix::kInvalidId,
object_store_id,
m_key1,
- m_value1,
+ &m_value1,
&handles,
&record);
EXPECT_FALSE(s.ok());
s = backing_store_->PutRecord(
- &transaction1, 0, object_store_id, m_key1, m_value1, &handles, &record);
+ &transaction1, 0, object_store_id, m_key1, &m_value1, &handles, &record);
EXPECT_FALSE(s.ok());
s = backing_store_->GetRecord(
@@ -895,7 +910,7 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
EXPECT_TRUE(s.ok());
EXPECT_GT(database_id, 0);
- IndexedDBBackingStore::Transaction transaction(backing_store_);
+ IndexedDBBackingStore::Transaction transaction(backing_store_.get());
transaction.Begin();
s = backing_store_->CreateObjectStore(&transaction,
@@ -957,6 +972,35 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
}
}
+TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) {
+ const base::string16 string_version(ASCIIToUTF16("string_version"));
+
+ const base::string16 db1_name(ASCIIToUTF16("db1"));
+ const int64 db1_version = 1LL;
+ int64 db1_id;
+
+ // Database records with DEFAULT_INT_VERSION represent stale data,
+ // and should not be enumerated.
+ const base::string16 db2_name(ASCIIToUTF16("db2"));
+ const int64 db2_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
+ int64 db2_id;
+
+ leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
+ db1_name, string_version, db1_version, &db1_id);
+ EXPECT_TRUE(s.ok());
+ EXPECT_GT(db1_id, 0LL);
+
+ s = backing_store_->CreateIDBDatabaseMetaData(
+ db2_name, string_version, db2_version, &db2_id);
+ EXPECT_TRUE(s.ok());
+ EXPECT_GT(db2_id, db1_id);
+
+ std::vector<base::string16> names = backing_store_->GetDatabaseNames(&s);
+ EXPECT_TRUE(s.ok());
+ EXPECT_EQ(names.size(), 1ULL);
+ EXPECT_EQ(names[0], db1_name);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_blob_info.cc b/chromium/content/browser/indexed_db/indexed_db_blob_info.cc
index 2c7d9ec019c..e4b1a3a1f12 100644
--- a/chromium/content/browser/indexed_db/indexed_db_blob_info.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_blob_info.cc
@@ -14,8 +14,6 @@ IndexedDBBlobInfo::IndexedDBBlobInfo()
: is_file_(false), size_(-1), key_(DatabaseMetaDataKey::kInvalidBlobKey) {
}
-IndexedDBBlobInfo::~IndexedDBBlobInfo() {}
-
IndexedDBBlobInfo::IndexedDBBlobInfo(const std::string& uuid,
const base::string16& type,
int64 size)
@@ -51,6 +49,8 @@ IndexedDBBlobInfo::IndexedDBBlobInfo(int64 key,
: is_file_(true), type_(type), size_(-1), file_name_(file_name), key_(key) {
}
+IndexedDBBlobInfo::~IndexedDBBlobInfo() {}
+
void IndexedDBBlobInfo::set_size(int64 size) {
DCHECK_EQ(-1, size_);
size_ = size;
diff --git a/chromium/content/browser/indexed_db/indexed_db_blob_info.h b/chromium/content/browser/indexed_db/indexed_db_blob_info.h
index a2ac99149fc..5001b4bb765 100644
--- a/chromium/content/browser/indexed_db/indexed_db_blob_info.h
+++ b/chromium/content/browser/indexed_db/indexed_db_blob_info.h
@@ -11,16 +11,14 @@
#include "base/files/file_path.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "webkit/common/blob/shareable_file_reference.h"
+#include "storage/common/blob/shareable_file_reference.h"
namespace content {
class CONTENT_EXPORT IndexedDBBlobInfo {
public:
- typedef webkit_blob::ShareableFileReference::FinalReleaseCallback
- ReleaseCallback;
+ typedef storage::ShareableFileReference::FinalReleaseCallback ReleaseCallback;
IndexedDBBlobInfo();
- ~IndexedDBBlobInfo();
// These two are used for Blobs.
IndexedDBBlobInfo(const std::string& uuid,
const base::string16& type,
@@ -35,6 +33,8 @@ class CONTENT_EXPORT IndexedDBBlobInfo {
const base::string16& type,
const base::string16& file_name);
+ ~IndexedDBBlobInfo();
+
bool is_file() const { return is_file_; }
const std::string& uuid() const { return uuid_; }
const base::string16& type() const { return type_; }
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index ddbfb44bbac..871d9f50f2f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -4,10 +4,10 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
@@ -34,12 +34,12 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/browser/quota/quota_manager.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/browser/quota/quota_manager.h"
using base::ASCIIToUTF16;
-using quota::QuotaManager;
-using webkit_database::DatabaseUtil;
+using storage::QuotaManager;
+using storage::DatabaseUtil;
namespace content {
@@ -49,13 +49,13 @@ class IndexedDBBrowserTest : public ContentBrowserTest {
public:
IndexedDBBrowserTest() : disk_usage_(-1) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
GetTestClassFactory()->Reset();
IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(GetIDBClassFactory);
ContentBrowserTest::SetUp();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
IndexedDBClassFactory::SetIndexedDBClassFactoryGetter(NULL);
ContentBrowserTest::TearDown();
}
@@ -125,7 +125,7 @@ class IndexedDBBrowserTest : public ContentBrowserTest {
return;
}
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- qm->SetTemporaryGlobalOverrideQuota(bytes, quota::QuotaCallback());
+ qm->SetTemporaryGlobalOverrideQuota(bytes, storage::QuotaCallback());
// Don't return until the quota has been set.
scoped_refptr<base::ThreadTestHelper> helper(new base::ThreadTestHelper(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)));
@@ -246,7 +246,7 @@ class IndexedDBBrowserTestWithLowQuota : public IndexedDBBrowserTest {
public:
IndexedDBBrowserTestWithLowQuota() {}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
const int kInitialQuotaKilobytes = 5000;
SetQuota(kInitialQuotaKilobytes);
}
@@ -263,7 +263,7 @@ class IndexedDBBrowserTestWithGCExposed : public IndexedDBBrowserTest {
public:
IndexedDBBrowserTestWithGCExposed() {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
}
@@ -297,7 +297,7 @@ static void CopyLevelDBToProfile(Shell* shell,
class IndexedDBBrowserTestWithPreexistingLevelDB : public IndexedDBBrowserTest {
public:
IndexedDBBrowserTestWithPreexistingLevelDB() {}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
scoped_refptr<IndexedDBContextImpl> context = GetContext();
context->TaskRunner()->PostTask(
FROM_HERE,
@@ -317,9 +317,7 @@ class IndexedDBBrowserTestWithPreexistingLevelDB : public IndexedDBBrowserTest {
class IndexedDBBrowserTestWithVersion0Schema : public
IndexedDBBrowserTestWithPreexistingLevelDB {
- virtual std::string EnclosingLevelDBDir() OVERRIDE {
- return "migration_from_0";
- }
+ std::string EnclosingLevelDBDir() override { return "migration_from_0"; }
};
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion0Schema, MigrationTest) {
@@ -328,9 +326,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion0Schema, MigrationTest) {
class IndexedDBBrowserTestWithVersion123456Schema : public
IndexedDBBrowserTestWithPreexistingLevelDB {
- virtual std::string EnclosingLevelDBDir() OVERRIDE {
- return "schema_version_123456";
- }
+ std::string EnclosingLevelDBDir() override { return "schema_version_123456"; }
};
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion123456Schema,
@@ -344,9 +340,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion123456Schema,
class IndexedDBBrowserTestWithVersion987654SSVData : public
IndexedDBBrowserTestWithPreexistingLevelDB {
- virtual std::string EnclosingLevelDBDir() OVERRIDE {
- return "ssv_version_987654";
- }
+ std::string EnclosingLevelDBDir() override { return "ssv_version_987654"; }
};
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion987654SSVData,
@@ -360,9 +354,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithVersion987654SSVData,
class IndexedDBBrowserTestWithCorruptLevelDB : public
IndexedDBBrowserTestWithPreexistingLevelDB {
- virtual std::string EnclosingLevelDBDir() OVERRIDE {
- return "corrupt_leveldb";
- }
+ std::string EnclosingLevelDBDir() override { return "corrupt_leveldb"; }
};
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithCorruptLevelDB,
@@ -376,9 +368,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithCorruptLevelDB,
class IndexedDBBrowserTestWithMissingSSTFile : public
IndexedDBBrowserTestWithPreexistingLevelDB {
- virtual std::string EnclosingLevelDBDir() OVERRIDE {
- return "missing_sst";
- }
+ std::string EnclosingLevelDBDir() override { return "missing_sst"; }
};
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithMissingSSTFile,
@@ -504,7 +494,7 @@ static scoped_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
scoped_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_OK);
- return http_response.PassAs<net::test_server::HttpResponse>();
+ return http_response.Pass();
} else if (request_path == "fail" && !request_query.empty()) {
FailClass failure_class = FAIL_CLASS_NOTHING;
FailMethod failure_method = FAIL_METHOD_NOTHING;
@@ -548,9 +538,16 @@ static scoped_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
failure_method = FAIL_METHOD_GET;
else if (fail_method == "Commit")
failure_method = FAIL_METHOD_COMMIT;
- else {
+ else
NOTREACHED() << "Unknown method: \"" << fail_method << "\"";
- }
+ } else if (fail_class == "LevelDBIterator") {
+ failure_class = FAIL_CLASS_LEVELDB_ITERATOR;
+ if (fail_method == "Seek")
+ failure_method = FAIL_METHOD_SEEK;
+ else
+ NOTREACHED() << "Unknown method: \"" << fail_method << "\"";
+ } else {
+ NOTREACHED() << "Unknown class: \"" << fail_class << "\"";
}
DCHECK_GE(instance_num, 1);
@@ -561,7 +558,7 @@ static scoped_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
scoped_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_OK);
- return http_response.PassAs<net::test_server::HttpResponse>();
+ return http_response.Pass();
}
// A request for a test resource
@@ -574,7 +571,7 @@ static scoped_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
if (!base::ReadFileToString(resourcePath, &file_contents))
return scoped_ptr<net::test_server::HttpResponse>();
http_response->set_content(file_contents);
- return http_response.PassAs<net::test_server::HttpResponse>();
+ return http_response.Pass();
}
} // namespace
@@ -590,7 +587,7 @@ IN_PROC_BROWSER_TEST_P(IndexedDBBrowserCorruptionTest,
const GURL& origin_url = embedded_test_server()->base_url();
embedded_test_server()->RegisterRequestHandler(
base::Bind(&CorruptDBRequestHandler,
- base::ConstRef(GetContext()),
+ base::Unretained(GetContext()),
origin_url,
s_corrupt_db_test_prefix,
this));
@@ -605,13 +602,15 @@ IN_PROC_BROWSER_TEST_P(IndexedDBBrowserCorruptionTest,
INSTANTIATE_TEST_CASE_P(IndexedDBBrowserCorruptionTestInstantiation,
IndexedDBBrowserCorruptionTest,
- ::testing::Values("get",
+ ::testing::Values("failGetBlobJournal",
+ "get",
+ "failWebkitGetDatabaseNames",
"iterate",
+ "failTransactionCommit",
"clearObjectStore"));
-// Crashes flakily on various platforms. crbug.com/375856
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest,
- DISABLED_DeleteCompactsBackingStore) {
+ DeleteCompactsBackingStore) {
const GURL test_url = GetTestUrl("indexeddb", "delete_compact.html");
SimpleTest(GURL(test_url.spec() + "#fill"));
int64 after_filling = RequestDiskUsage();
@@ -632,7 +631,7 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest,
const int kTestFillBytes = 1024 * 1024 * 5; // 5MB
EXPECT_GT(after_filling, kTestFillBytes);
- const int kTestCompactBytes = 1024 * 1024 * 1; // 1MB
+ const int kTestCompactBytes = 1024 * 10; // 10kB
EXPECT_LT(after_deleting, kTestCompactBytes);
}
@@ -661,7 +660,11 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest,
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, PRE_VersionChangeCrashResilience) {
NavigateAndWaitForTitle(shell(), "version_change_crash.html", "#part2",
"pass - part2 - crash me");
- NavigateToURL(shell(), GURL(kChromeUIBrowserCrashHost));
+ // If we actually crash here then googletest will not run the next step
+ // (VersionChangeCrashResilience) as an optimization. googletest's
+ // ASSERT_DEATH/EXIT fails to work properly (on Windows) due to how we
+ // implement the PRE_* test mechanism.
+ exit(0);
}
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, VersionChangeCrashResilience) {
@@ -710,19 +713,13 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, ForceCloseEventTest) {
class IndexedDBBrowserTestSingleProcess : public IndexedDBBrowserTest {
public:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kSingleProcess);
}
};
-// Crashing on Android due to kSingleProcess flag: http://crbug.com/342525
-#if defined(OS_ANDROID)
-#define MAYBE_RenderThreadShutdownTest DISABLED_RenderThreadShutdownTest
-#else
-#define MAYBE_RenderThreadShutdownTest RenderThreadShutdownTest
-#endif
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestSingleProcess,
- MAYBE_RenderThreadShutdownTest) {
+ RenderThreadShutdownTest) {
SimpleTest(GetTestUrl("indexeddb", "shutdown_with_requests.html"));
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 74a76fdce53..a5aafddd557 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/guid.h"
+#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/browser/child_process_security_policy_impl.h"
@@ -21,12 +22,12 @@
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/common/indexed_db/indexed_db_constants.h"
#include "content/common/indexed_db/indexed_db_messages.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/common/blob/blob_data.h"
-#include "webkit/common/blob/shareable_file_reference.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/common/blob/blob_data.h"
+#include "storage/common/blob/shareable_file_reference.h"
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace content {
@@ -46,7 +47,9 @@ IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
host_transaction_id_(kNoTransaction),
ipc_database_id_(kNoDatabase),
ipc_database_callbacks_id_(kNoDatabaseCallbacks),
- data_loss_(blink::WebIDBDataLossNone) {}
+ data_loss_(blink::WebIDBDataLossNone),
+ sent_blocked_(false) {
+}
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32 ipc_thread_id,
@@ -59,7 +62,9 @@ IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
host_transaction_id_(kNoTransaction),
ipc_database_id_(kNoDatabase),
ipc_database_callbacks_id_(kNoDatabaseCallbacks),
- data_loss_(blink::WebIDBDataLossNone) {}
+ data_loss_(blink::WebIDBDataLossNone),
+ sent_blocked_(false) {
+}
IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
int32 ipc_thread_id,
@@ -75,7 +80,9 @@ IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
origin_url_(origin_url),
ipc_database_id_(kNoDatabase),
ipc_database_callbacks_id_(ipc_database_callbacks_id),
- data_loss_(blink::WebIDBDataLossNone) {}
+ data_loss_(blink::WebIDBDataLossNone),
+ sent_blocked_(false) {
+}
IndexedDBCallbacks::~IndexedDBCallbacks() {}
@@ -85,6 +92,13 @@ void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
dispatcher_host_ = NULL;
+
+ if (!connection_open_start_time_.is_null()) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "WebCore.IndexedDB.OpenTime.Error",
+ base::TimeTicks::Now() - connection_open_start_time_);
+ connection_open_start_time_ = base::TimeTicks();
+ }
}
void IndexedDBCallbacks::OnSuccess(const std::vector<base::string16>& value) {
@@ -114,8 +128,19 @@ void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
kNoDatabaseCallbacks == ipc_database_callbacks_id_);
DCHECK_EQ(kNoDatabase, ipc_database_id_);
+ if (sent_blocked_)
+ return;
+
+ sent_blocked_ = true;
dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
ipc_thread_id_, ipc_callbacks_id_, existing_version));
+
+ if (!connection_open_start_time_.is_null()) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "WebCore.IndexedDB.OpenTime.Blocked",
+ base::TimeTicks::Now() - connection_open_start_time_);
+ connection_open_start_time_ = base::TimeTicks();
+ }
}
void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss,
@@ -152,6 +177,13 @@ void IndexedDBCallbacks::OnUpgradeNeeded(
params.data_loss = data_loss_;
params.data_loss_message = data_loss_message_;
dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
+
+ if (!connection_open_start_time_.is_null()) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "WebCore.IndexedDB.OpenTime.UpgradeNeeded",
+ base::TimeTicks::Now() - connection_open_start_time_);
+ connection_open_start_time_ = base::TimeTicks();
+ }
}
void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
@@ -179,19 +211,26 @@ void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
ipc_object_id,
IndexedDBDispatcherHost::ConvertMetadata(metadata)));
dispatcher_host_ = NULL;
+
+ if (!connection_open_start_time_.is_null()) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "WebCore.IndexedDB.OpenTime.Success",
+ base::TimeTicks::Now() - connection_open_start_time_);
+ connection_open_start_time_ = base::TimeTicks();
+ }
}
static std::string CreateBlobData(
const IndexedDBBlobInfo& blob_info,
scoped_refptr<IndexedDBDispatcherHost> dispatcher_host,
- webkit_blob::BlobStorageContext* blob_storage_context,
+ storage::BlobStorageContext* blob_storage_context,
base::TaskRunner* task_runner) {
std::string uuid = blob_info.uuid();
if (!uuid.empty()) {
// We're sending back a live blob, not a reference into our backing store.
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle(
blob_storage_context->GetBlobDataFromUUID(uuid));
- dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle);
+ dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass());
return uuid;
}
scoped_refptr<ShareableFileReference> shareable_file =
@@ -206,13 +245,13 @@ static std::string CreateBlobData(
}
uuid = base::GenerateGUID();
- scoped_refptr<webkit_blob::BlobData> blob_data =
- new webkit_blob::BlobData(uuid);
+ scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid);
+ blob_data->set_content_type(base::UTF16ToUTF8(blob_info.type()));
blob_data->AppendFile(
blob_info.file_path(), 0, blob_info.size(), blob_info.last_modified());
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle(
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle(
blob_storage_context->AddFinishedBlob(blob_data.get()));
- dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle);
+ dispatcher_host->HoldBlobDataHandle(uuid, blob_data_handle.Pass());
return uuid;
}
@@ -268,22 +307,20 @@ static void BlobLookupForCursorPrefetch(
static void FillInBlobData(
const std::vector<IndexedDBBlobInfo>& blob_info,
std::vector<IndexedDBMsg_BlobOrFileInfo>* blob_or_file_info) {
- for (std::vector<IndexedDBBlobInfo>::const_iterator iter = blob_info.begin();
- iter != blob_info.end();
- ++iter) {
- if (iter->is_file()) {
+ for (const auto& iter : blob_info) {
+ if (iter.is_file()) {
IndexedDBMsg_BlobOrFileInfo info;
info.is_file = true;
- info.mime_type = iter->type();
- info.file_name = iter->file_name();
- info.file_path = iter->file_path().AsUTF16Unsafe();
- info.size = iter->size();
- info.last_modified = iter->last_modified().ToDoubleT();
+ info.mime_type = iter.type();
+ info.file_name = iter.file_name();
+ info.file_path = iter.file_path().AsUTF16Unsafe();
+ info.size = iter.size();
+ info.last_modified = iter.last_modified().ToDoubleT();
blob_or_file_info->push_back(info);
} else {
IndexedDBMsg_BlobOrFileInfo info;
- info.mime_type = iter->type();
- info.size = iter->size();
+ info.mime_type = iter.type();
+ info.size = iter.size();
blob_or_file_info->push_back(info);
}
}
@@ -292,10 +329,9 @@ static void FillInBlobData(
void IndexedDBCallbacks::RegisterBlobsAndSend(
const std::vector<IndexedDBBlobInfo>& blob_info,
const base::Closure& callback) {
- std::vector<IndexedDBBlobInfo>::const_iterator iter;
- for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
- if (!iter->mark_used_callback().is_null())
- iter->mark_used_callback().Run();
+ for (const auto& iter : blob_info) {
+ if (!iter.mark_used_callback().is_null())
+ iter.mark_used_callback().Run();
}
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback);
@@ -394,9 +430,9 @@ void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
void IndexedDBCallbacks::OnSuccessWithPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- std::vector<IndexedDBValue>& values) {
+ std::vector<IndexedDBValue>* values) {
DCHECK_EQ(keys.size(), primary_keys.size());
- DCHECK_EQ(keys.size(), values.size());
+ DCHECK_EQ(keys.size(), values->size());
DCHECK(dispatcher_host_.get());
@@ -422,36 +458,32 @@ void IndexedDBCallbacks::OnSuccessWithPrefetch(
params->keys = msgKeys;
params->primary_keys = msgPrimaryKeys;
std::vector<std::string>& values_bits = params->values;
- values_bits.resize(values.size());
+ values_bits.resize(values->size());
std::vector<std::vector<IndexedDBMsg_BlobOrFileInfo> >& values_blob_infos =
params->blob_or_file_infos;
- values_blob_infos.resize(values.size());
+ values_blob_infos.resize(values->size());
bool found_blob_info = false;
- std::vector<IndexedDBValue>::iterator iter = values.begin();
- for (size_t i = 0; iter != values.end(); ++iter, ++i) {
+ std::vector<IndexedDBValue>::iterator iter = values->begin();
+ for (size_t i = 0; iter != values->end(); ++iter, ++i) {
values_bits[i].swap(iter->bits);
if (iter->blob_info.size()) {
found_blob_info = true;
FillInBlobData(iter->blob_info, &values_blob_infos[i]);
- std::vector<IndexedDBBlobInfo>::const_iterator blob_iter;
- for (blob_iter = iter->blob_info.begin();
- blob_iter != iter->blob_info.end();
- ++blob_iter) {
- if (!blob_iter->mark_used_callback().is_null())
- blob_iter->mark_used_callback().Run();
+ for (const auto& blob_iter : iter->blob_info) {
+ if (!blob_iter.mark_used_callback().is_null())
+ blob_iter.mark_used_callback().Run();
}
}
}
if (found_blob_info) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(BlobLookupForCursorPrefetch,
- base::Owned(params.release()),
- dispatcher_host_,
- values));
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(BlobLookupForCursorPrefetch,
+ base::Owned(params.release()),
+ dispatcher_host_,
+ *values));
} else {
dispatcher_host_->Send(
new IndexedDBMsg_CallbacksSuccessCursorPrefetch(*params.get()));
@@ -570,4 +602,9 @@ void IndexedDBCallbacks::OnSuccess() {
dispatcher_host_ = NULL;
}
+void IndexedDBCallbacks::SetConnectionOpenStartTime(
+ const base::TimeTicks& start_time) {
+ connection_open_start_time_ = start_time;
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.h b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
index 8041fb8beae..4b8a2177a8c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.h
@@ -83,7 +83,7 @@ class CONTENT_EXPORT IndexedDBCallbacks
virtual void OnSuccessWithPrefetch(
const std::vector<IndexedDBKey>& keys,
const std::vector<IndexedDBKey>& primary_keys,
- std::vector<IndexedDBValue>& values);
+ std::vector<IndexedDBValue>* values);
// IndexedDBDatabase::Get (with key injection)
virtual void OnSuccess(IndexedDBValue* value,
@@ -106,6 +106,8 @@ class CONTENT_EXPORT IndexedDBCallbacks
blink::WebIDBDataLoss data_loss() const { return data_loss_; }
+ void SetConnectionOpenStartTime(const base::TimeTicks& start_time);
+
protected:
virtual ~IndexedDBCallbacks();
@@ -133,6 +135,9 @@ class CONTENT_EXPORT IndexedDBCallbacks
blink::WebIDBDataLoss data_loss_;
std::string data_loss_message_;
+ // The "blocked" event should be sent at most once per request.
+ bool sent_blocked_;
+ base::TimeTicks connection_open_start_time_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBCallbacks);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_class_factory.cc b/chromium/content/browser/indexed_db/indexed_db_class_factory.cc
index a2a133689dd..78769db3092 100644
--- a/chromium/content/browser/indexed_db/indexed_db_class_factory.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_class_factory.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "content/browser/indexed_db/indexed_db_class_factory.h"
+#include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
namespace content {
@@ -27,4 +28,9 @@ LevelDBTransaction* IndexedDBClassFactory::CreateLevelDBTransaction(
return new LevelDBTransaction(db);
}
+content::LevelDBIteratorImpl* IndexedDBClassFactory::CreateIteratorImpl(
+ scoped_ptr<leveldb::Iterator> iterator) {
+ return new LevelDBIteratorImpl(iterator.Pass());
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_class_factory.h b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
index eb3c6566463..03b03597f67 100644
--- a/chromium/content/browser/indexed_db/indexed_db_class_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_class_factory.h
@@ -6,10 +6,16 @@
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_CLASS_FACTORY_H_
#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
+namespace leveldb {
+class Iterator;
+} // namespace leveldb
+
namespace content {
+class LevelDBIteratorImpl;
class LevelDBDatabase;
class LevelDBTransaction;
@@ -23,6 +29,8 @@ class CONTENT_EXPORT IndexedDBClassFactory {
static void SetIndexedDBClassFactoryGetter(GetterCallback* cb);
+ virtual LevelDBIteratorImpl* CreateIteratorImpl(
+ scoped_ptr<leveldb::Iterator> iterator);
virtual LevelDBTransaction* CreateLevelDBTransaction(LevelDBDatabase* db);
protected:
diff --git a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
index 49d04362d89..27f72f2b4b5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -11,6 +11,8 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
+#include "content/browser/indexed_db/leveldb/mock_leveldb_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/env_chromium.h"
@@ -20,6 +22,9 @@ using content::LevelDBComparator;
using content::LevelDBDatabase;
using content::LevelDBFactory;
using content::LevelDBSnapshot;
+using testing::_;
+using testing::Exactly;
+using testing::Invoke;
namespace base {
class TaskRunner;
@@ -43,10 +48,10 @@ class BustedLevelDBDatabase : public LevelDBDatabase {
const LevelDBComparator* /*comparator*/) {
return scoped_ptr<LevelDBDatabase>(new BustedLevelDBDatabase);
}
- virtual leveldb::Status Get(const base::StringPiece& key,
- std::string* value,
- bool* found,
- const LevelDBSnapshot* = 0) OVERRIDE {
+ leveldb::Status Get(const base::StringPiece& key,
+ std::string* value,
+ bool* found,
+ const LevelDBSnapshot* = 0) override {
return leveldb::Status::IOError("It's busted!");
}
@@ -54,30 +59,25 @@ class BustedLevelDBDatabase : public LevelDBDatabase {
DISALLOW_COPY_AND_ASSIGN(BustedLevelDBDatabase);
};
-class MockLevelDBFactory : public LevelDBFactory {
+class BustedLevelDBFactory : public LevelDBFactory {
public:
- MockLevelDBFactory() : destroy_called_(false) {}
- virtual leveldb::Status OpenLevelDB(
- const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full = 0) OVERRIDE {
- *db = BustedLevelDBDatabase::Open(file_name, comparator);
- return leveldb::Status::OK();
+ leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full = 0) override {
+ if (open_error_.ok())
+ *db = BustedLevelDBDatabase::Open(file_name, comparator);
+ return open_error_;
}
- virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
- OVERRIDE {
- EXPECT_FALSE(destroy_called_);
- destroy_called_ = true;
+ leveldb::Status DestroyLevelDB(const base::FilePath& file_name) override {
return leveldb::Status::IOError("error");
}
- virtual ~MockLevelDBFactory() { EXPECT_TRUE(destroy_called_); }
-
- private:
- bool destroy_called_;
+ void SetOpenError(const leveldb::Status& open_error) {
+ open_error_ = open_error;
+ }
private:
- DISALLOW_COPY_AND_ASSIGN(MockLevelDBFactory);
+ leveldb::Status open_error_;
};
TEST(IndexedDBIOErrorTest, CleanUpTest) {
@@ -87,13 +87,22 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
ASSERT_TRUE(temp_directory.CreateUniqueTempDir());
const base::FilePath path = temp_directory.path();
net::URLRequestContext* request_context = NULL;
- MockLevelDBFactory mock_leveldb_factory;
- blink::WebIDBDataLoss data_loss =
- blink::WebIDBDataLossNone;
+
+ BustedLevelDBFactory busted_factory;
+ content::MockLevelDBFactory mock_leveldb_factory;
+ ON_CALL(mock_leveldb_factory, OpenLevelDB(_, _, _, _)).WillByDefault(
+ Invoke(&busted_factory, &BustedLevelDBFactory::OpenLevelDB));
+ ON_CALL(mock_leveldb_factory, DestroyLevelDB(_)).WillByDefault(
+ Invoke(&busted_factory, &BustedLevelDBFactory::DestroyLevelDB));
+
+ EXPECT_CALL(mock_leveldb_factory, OpenLevelDB(_, _, _, _)).Times(Exactly(1));
+ EXPECT_CALL(mock_leveldb_factory, DestroyLevelDB(_)).Times(Exactly(1));
+ blink::WebIDBDataLoss data_loss = blink::WebIDBDataLossNone;
std::string data_loss_message;
bool disk_full = false;
- base::TaskRunner* task_runner = NULL;
+ base::SequencedTaskRunner* task_runner = NULL;
bool clean_journal = false;
+ leveldb::Status s;
scoped_refptr<IndexedDBBackingStore> backing_store =
IndexedDBBackingStore::Open(factory,
origin,
@@ -104,44 +113,10 @@ TEST(IndexedDBIOErrorTest, CleanUpTest) {
&disk_full,
&mock_leveldb_factory,
task_runner,
- clean_journal);
+ clean_journal,
+ &s);
}
-// TODO(dgrogan): Remove expect_destroy if we end up not using it again. It is
-// currently set to false in all 4 calls below.
-template <class T>
-class MockErrorLevelDBFactory : public LevelDBFactory {
- public:
- MockErrorLevelDBFactory(T error, bool expect_destroy)
- : error_(error),
- expect_destroy_(expect_destroy),
- destroy_called_(false) {}
- virtual leveldb::Status OpenLevelDB(
- const base::FilePath& file_name,
- const LevelDBComparator* comparator,
- scoped_ptr<LevelDBDatabase>* db,
- bool* is_disk_full = 0) OVERRIDE {
- return MakeIOError(
- "some filename", "some message", leveldb_env::kNewLogger, error_);
- }
- virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
- OVERRIDE {
- EXPECT_FALSE(destroy_called_);
- destroy_called_ = true;
- return leveldb::Status::IOError("error");
- }
- virtual ~MockErrorLevelDBFactory() {
- EXPECT_EQ(expect_destroy_, destroy_called_);
- }
-
- private:
- T error_;
- bool expect_destroy_;
- bool destroy_called_;
-
- DISALLOW_COPY_AND_ASSIGN(MockErrorLevelDBFactory);
-};
-
TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
content::IndexedDBFactory* factory = NULL;
const GURL origin("http://localhost:81");
@@ -153,10 +128,22 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
blink::WebIDBDataLossNone;
std::string data_loss_reason;
bool disk_full = false;
- base::TaskRunner* task_runner = NULL;
+ base::SequencedTaskRunner* task_runner = NULL;
bool clean_journal = false;
+ leveldb::Status s;
+
+ BustedLevelDBFactory busted_factory;
+ content::MockLevelDBFactory mock_leveldb_factory;
+ ON_CALL(mock_leveldb_factory, OpenLevelDB(_, _, _, _)).WillByDefault(
+ Invoke(&busted_factory, &BustedLevelDBFactory::OpenLevelDB));
+ ON_CALL(mock_leveldb_factory, DestroyLevelDB(_)).WillByDefault(
+ Invoke(&busted_factory, &BustedLevelDBFactory::DestroyLevelDB));
- MockErrorLevelDBFactory<int> mock_leveldb_factory(ENOSPC, false);
+ EXPECT_CALL(mock_leveldb_factory, OpenLevelDB(_, _, _, _)).Times(Exactly(4));
+ EXPECT_CALL(mock_leveldb_factory, DestroyLevelDB(_)).Times(Exactly(0));
+
+ busted_factory.SetOpenError(MakeIOError(
+ "some filename", "some message", leveldb_env::kNewLogger, ENOSPC));
scoped_refptr<IndexedDBBackingStore> backing_store =
IndexedDBBackingStore::Open(factory,
origin,
@@ -167,10 +154,14 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
&disk_full,
&mock_leveldb_factory,
task_runner,
- clean_journal);
-
- MockErrorLevelDBFactory<base::File::Error> mock_leveldb_factory2(
- base::File::FILE_ERROR_NO_MEMORY, false);
+ clean_journal,
+ &s);
+ ASSERT_TRUE(s.IsIOError());
+
+ busted_factory.SetOpenError(MakeIOError("some filename",
+ "some message",
+ leveldb_env::kNewLogger,
+ base::File::FILE_ERROR_NO_MEMORY));
scoped_refptr<IndexedDBBackingStore> backing_store2 =
IndexedDBBackingStore::Open(factory,
origin,
@@ -179,11 +170,14 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
&data_loss,
&data_loss_reason,
&disk_full,
- &mock_leveldb_factory2,
+ &mock_leveldb_factory,
task_runner,
- clean_journal);
+ clean_journal,
+ &s);
+ ASSERT_TRUE(s.IsIOError());
- MockErrorLevelDBFactory<int> mock_leveldb_factory3(EIO, false);
+ busted_factory.SetOpenError(MakeIOError(
+ "some filename", "some message", leveldb_env::kNewLogger, EIO));
scoped_refptr<IndexedDBBackingStore> backing_store3 =
IndexedDBBackingStore::Open(factory,
origin,
@@ -192,12 +186,16 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
&data_loss,
&data_loss_reason,
&disk_full,
- &mock_leveldb_factory3,
+ &mock_leveldb_factory,
task_runner,
- clean_journal);
-
- MockErrorLevelDBFactory<base::File::Error> mock_leveldb_factory4(
- base::File::FILE_ERROR_FAILED, false);
+ clean_journal,
+ &s);
+ ASSERT_TRUE(s.IsIOError());
+
+ busted_factory.SetOpenError(MakeIOError("some filename",
+ "some message",
+ leveldb_env::kNewLogger,
+ base::File::FILE_ERROR_FAILED));
scoped_refptr<IndexedDBBackingStore> backing_store4 =
IndexedDBBackingStore::Open(factory,
origin,
@@ -206,9 +204,11 @@ TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) {
&data_loss,
&data_loss_reason,
&disk_full,
- &mock_leveldb_factory4,
+ &mock_leveldb_factory,
task_runner,
- clean_journal);
+ clean_journal,
+ &s);
+ ASSERT_TRUE(s.IsIOError());
}
} // namespace
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.cc b/chromium/content/browser/indexed_db/indexed_db_connection.cc
index 0669e14c0d0..3ed927937e8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.cc
@@ -14,7 +14,7 @@ IndexedDBConnection::IndexedDBConnection(
IndexedDBConnection::~IndexedDBConnection() {}
void IndexedDBConnection::Close() {
- if (!callbacks_)
+ if (!callbacks_.get())
return;
database_->Close(this, false /* forced */);
database_ = NULL;
@@ -22,7 +22,7 @@ void IndexedDBConnection::Close() {
}
void IndexedDBConnection::ForceClose() {
- if (!callbacks_)
+ if (!callbacks_.get())
return;
database_->Close(this, true /* forced */);
database_ = NULL;
@@ -30,6 +30,12 @@ void IndexedDBConnection::ForceClose() {
callbacks_ = NULL;
}
+void IndexedDBConnection::VersionChangeIgnored() {
+ if (!database_.get())
+ return;
+ database_->VersionChangeIgnored();
+}
+
bool IndexedDBConnection::IsConnected() {
return database_.get() != NULL;
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_connection.h b/chromium/content/browser/indexed_db/indexed_db_connection.h
index 95d1f2e86d3..096323d7cd0 100644
--- a/chromium/content/browser/indexed_db/indexed_db_connection.h
+++ b/chromium/content/browser/indexed_db/indexed_db_connection.h
@@ -24,8 +24,10 @@ class CONTENT_EXPORT IndexedDBConnection {
virtual void Close();
virtual bool IsConnected();
- IndexedDBDatabase* database() { return database_; }
- IndexedDBDatabaseCallbacks* callbacks() { return callbacks_; }
+ void VersionChangeIgnored();
+
+ IndexedDBDatabase* database() const { return database_.get(); }
+ IndexedDBDatabaseCallbacks* callbacks() const { return callbacks_.get(); }
private:
// NULL in some unit tests, and after the connection is closed.
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
index c2bd0afa62c..b54d59a46ff 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -9,8 +9,8 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
@@ -23,22 +23,22 @@
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
-#include "content/browser/indexed_db/indexed_db_factory.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/indexed_db_quota_client.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/indexed_db_info.h"
#include "content/public/common/content_switches.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "storage/common/database/database_identifier.h"
#include "ui/base/text/bytes_formatting.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/browser/quota/special_storage_policy.h"
-#include "webkit/common/database/database_identifier.h"
using base::DictionaryValue;
using base::ListValue;
-using webkit_database::DatabaseUtil;
+using storage::DatabaseUtil;
namespace content {
const base::FilePath::CharType IndexedDBContextImpl::kIndexedDBDirectory[] =
@@ -68,7 +68,7 @@ void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path,
file_path.RemoveExtension().Extension() == kIndexedDBExtension) {
std::string origin_id = file_path.BaseName().RemoveExtension()
.RemoveExtension().MaybeAsASCII();
- origins->push_back(webkit_database::GetOriginFromIdentifier(origin_id));
+ origins->push_back(storage::GetOriginFromIdentifier(origin_id));
if (file_paths)
file_paths->push_back(file_path);
}
@@ -78,7 +78,7 @@ void GetAllOriginsAndPaths(const base::FilePath& indexeddb_path,
// This will be called after the IndexedDBContext is destroyed.
void ClearSessionOnlyOrigins(
const base::FilePath& indexeddb_path,
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) {
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy) {
// TODO(jsbell): DCHECK that this is running on an IndexedDB thread,
// if a global handle to it is ever available.
std::vector<GURL> origins;
@@ -102,8 +102,8 @@ void ClearSessionOnlyOrigins(
IndexedDBContextImpl::IndexedDBContextImpl(
const base::FilePath& data_path,
- quota::SpecialStoragePolicy* special_storage_policy,
- quota::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy,
+ storage::QuotaManagerProxy* quota_manager_proxy,
base::SequencedTaskRunner* task_runner)
: force_keep_session_state_(false),
special_storage_policy_(special_storage_policy),
@@ -119,36 +119,26 @@ IndexedDBContextImpl::IndexedDBContextImpl(
IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (!factory_) {
+ if (!factory_.get()) {
// Prime our cache of origins with existing databases so we can
// detect when dbs are newly created.
GetOriginSet();
- factory_ = new IndexedDBFactory(this);
+ factory_ = new IndexedDBFactoryImpl(this);
}
- return factory_;
+ return factory_.get();
}
std::vector<GURL> IndexedDBContextImpl::GetAllOrigins() {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- std::vector<GURL> origins;
std::set<GURL>* origins_set = GetOriginSet();
- for (std::set<GURL>::const_iterator iter = origins_set->begin();
- iter != origins_set->end();
- ++iter) {
- origins.push_back(*iter);
- }
- return origins;
+ return std::vector<GURL>(origins_set->begin(), origins_set->end());
}
std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
std::vector<GURL> origins = GetAllOrigins();
std::vector<IndexedDBInfo> result;
- for (std::vector<GURL>::const_iterator iter = origins.begin();
- iter != origins.end();
- ++iter) {
- const GURL& origin_url = *iter;
-
+ for (const auto& origin_url : origins) {
base::FilePath idb_directory = GetFilePath(origin_url);
size_t connection_count = GetConnectionCount(origin_url);
result.push_back(IndexedDBInfo(origin_url,
@@ -171,24 +161,21 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
std::sort(origins.begin(), origins.end(), HostNameComparator);
scoped_ptr<base::ListValue> list(new base::ListValue());
- for (std::vector<GURL>::const_iterator iter = origins.begin();
- iter != origins.end();
- ++iter) {
- const GURL& origin_url = *iter;
-
+ for (const auto& origin_url : origins) {
scoped_ptr<base::DictionaryValue> info(new base::DictionaryValue());
info->SetString("url", origin_url.spec());
info->SetString("size", ui::FormatBytes(GetOriginDiskUsage(origin_url)));
info->SetDouble("last_modified",
GetOriginLastModified(origin_url).ToJsTime());
- info->SetString("path", GetFilePath(origin_url).value());
+ if (!is_incognito())
+ info->SetString("path", GetFilePath(origin_url).value());
info->SetDouble("connection_count", GetConnectionCount(origin_url));
// This ends up being O(n^2) since we iterate over all open databases
// to extract just those in the origin, and we're iterating over all
// origins in the outer loop.
- if (factory_) {
+ if (factory_.get()) {
std::pair<IndexedDBFactory::OriginDBMapIterator,
IndexedDBFactory::OriginDBMapIterator> range =
factory_->GetOpenDatabasesForOrigin(origin_url);
@@ -213,11 +200,7 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
scoped_ptr<base::ListValue> transaction_list(new base::ListValue());
std::vector<const IndexedDBTransaction*> transactions =
db->transaction_coordinator().GetTransactions();
- for (std::vector<const IndexedDBTransaction*>::iterator trans_it =
- transactions.begin();
- trans_it != transactions.end();
- ++trans_it) {
- const IndexedDBTransaction* transaction = *trans_it;
+ for (const auto* transaction : transactions) {
scoped_ptr<base::DictionaryValue> transaction_info(
new base::DictionaryValue());
@@ -263,12 +246,9 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
"tasks_completed", transaction->diagnostics().tasks_completed);
scoped_ptr<base::ListValue> scope(new base::ListValue());
- for (std::set<int64>::const_iterator scope_it =
- transaction->scope().begin();
- scope_it != transaction->scope().end();
- ++scope_it) {
+ for (const auto& id : transaction->scope()) {
IndexedDBDatabaseMetadata::ObjectStoreMap::const_iterator it =
- db->metadata().object_stores.find(*scope_it);
+ db->metadata().object_stores.find(id);
if (it != db->metadata().object_stores.end())
scope->AppendString(it->second.name);
}
@@ -345,7 +325,7 @@ void IndexedDBContextImpl::ForceClose(const GURL origin_url,
if (data_path_.empty() || !IsInOriginSet(origin_url))
return;
- if (factory_)
+ if (factory_.get())
factory_->ForceClose(origin_url);
DCHECK_EQ(0UL, GetConnectionCount(origin_url));
}
@@ -355,14 +335,14 @@ size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) {
if (data_path_.empty() || !IsInOriginSet(origin_url))
return 0;
- if (!factory_)
+ if (!factory_.get())
return 0;
return factory_->GetConnectionCount(origin_url);
}
base::FilePath IndexedDBContextImpl::GetFilePath(const GURL& origin_url) const {
- std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url);
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
return GetIndexedDBFilePath(origin_id);
}
@@ -373,7 +353,7 @@ base::FilePath IndexedDBContextImpl::GetFilePathForTesting(
void IndexedDBContextImpl::SetTaskRunnerForTesting(
base::SequencedTaskRunner* task_runner) {
- DCHECK(!task_runner_);
+ DCHECK(!task_runner_.get());
task_runner_ = task_runner;
}
@@ -382,9 +362,9 @@ void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url,
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
if (quota_manager_proxy()) {
quota_manager_proxy()->NotifyStorageAccessed(
- quota::QuotaClient::kIndexedDatabase,
+ storage::QuotaClient::kIndexedDatabase,
origin_url,
- quota::kStorageTypeTemporary);
+ storage::kStorageTypeTemporary);
}
if (AddToOriginSet(origin_url)) {
// A newly created db, notify the quota system.
@@ -400,16 +380,16 @@ void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url,
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
if (quota_manager_proxy()) {
quota_manager_proxy()->NotifyStorageAccessed(
- quota::QuotaClient::kIndexedDatabase,
+ storage::QuotaClient::kIndexedDatabase,
origin_url,
- quota::kStorageTypeTemporary);
+ storage::kStorageTypeTemporary);
}
- if (factory_ && factory_->GetConnectionCount(origin_url) == 0)
+ if (factory_.get() && factory_->GetConnectionCount(origin_url) == 0)
QueryDiskAndUpdateQuotaUsage(origin_url);
}
void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) {
- DCHECK(!factory_ || factory_->GetConnectionCount(origin_url) > 0);
+ DCHECK(!factory_.get() || factory_->GetConnectionCount(origin_url) > 0);
QueryDiskAndUpdateQuotaUsage(origin_url);
QueryAvailableQuota(origin_url);
}
@@ -435,12 +415,12 @@ bool IndexedDBContextImpl::IsOverQuota(const GURL& origin_url) {
return WouldBeOverQuota(origin_url, kOneAdditionalByte);
}
-quota::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() {
- return quota_manager_proxy_;
+storage::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() {
+ return quota_manager_proxy_.get();
}
IndexedDBContextImpl::~IndexedDBContextImpl() {
- if (factory_) {
+ if (factory_.get()) {
TaskRunner()->PostTask(
FROM_HERE, base::Bind(&IndexedDBFactory::ContextDestroyed, factory_));
factory_ = NULL;
@@ -453,7 +433,7 @@ IndexedDBContextImpl::~IndexedDBContextImpl() {
return;
bool has_session_only_databases =
- special_storage_policy_ &&
+ special_storage_policy_.get() &&
special_storage_policy_->HasSessionOnlyOrigins();
// Clearing only session-only databases, and there are none.
@@ -496,22 +476,23 @@ void IndexedDBContextImpl::QueryDiskAndUpdateQuotaUsage(
// quota_manager_proxy() is NULL in unit tests.
if (quota_manager_proxy()) {
quota_manager_proxy()->NotifyStorageModified(
- quota::QuotaClient::kIndexedDatabase,
+ storage::QuotaClient::kIndexedDatabase,
origin_url,
- quota::kStorageTypeTemporary,
+ storage::kStorageTypeTemporary,
difference);
}
}
}
void IndexedDBContextImpl::GotUsageAndQuota(const GURL& origin_url,
- quota::QuotaStatusCode status,
+ storage::QuotaStatusCode status,
int64 usage,
int64 quota) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(status == quota::kQuotaStatusOk || status == quota::kQuotaErrorAbort)
+ DCHECK(status == storage::kQuotaStatusOk ||
+ status == storage::kQuotaErrorAbort)
<< "status was " << status;
- if (status == quota::kQuotaErrorAbort) {
+ if (status == storage::kQuotaErrorAbort) {
// We seem to no longer care to wait around for the answer.
return;
}
@@ -547,20 +528,15 @@ void IndexedDBContextImpl::QueryAvailableQuota(const GURL& origin_url) {
return;
quota_manager_proxy()->quota_manager()->GetUsageAndQuota(
origin_url,
- quota::kStorageTypeTemporary,
+ storage::kStorageTypeTemporary,
base::Bind(&IndexedDBContextImpl::GotUsageAndQuota, this, origin_url));
}
std::set<GURL>* IndexedDBContextImpl::GetOriginSet() {
if (!origin_set_) {
- origin_set_.reset(new std::set<GURL>);
std::vector<GURL> origins;
GetAllOriginsAndPaths(data_path_, &origins, NULL);
- for (std::vector<GURL>::const_iterator iter = origins.begin();
- iter != origins.end();
- ++iter) {
- origin_set_->insert(*iter);
- }
+ origin_set_.reset(new std::set<GURL>(origins.begin(), origins.end()));
}
return origin_set_.get();
}
@@ -571,8 +547,8 @@ void IndexedDBContextImpl::ResetCaches() {
space_available_map_.clear();
}
-base::TaskRunner* IndexedDBContextImpl::TaskRunner() const {
- return task_runner_;
+base::SequencedTaskRunner* IndexedDBContextImpl::TaskRunner() const {
+ return task_runner_.get();
}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.h b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
index b3ec9850fdd..8fff76c7a30 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -17,8 +17,8 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/public/browser/indexed_db_context.h"
+#include "storage/common/quota/quota_types.h"
#include "url/gurl.h"
-#include "webkit/common/quota/quota_types.h"
class GURL;
@@ -28,7 +28,7 @@ class FilePath;
class SequencedTaskRunner;
}
-namespace quota {
+namespace storage {
class QuotaManagerProxy;
class SpecialStoragePolicy;
}
@@ -40,29 +40,36 @@ class IndexedDBConnection;
class CONTENT_EXPORT IndexedDBContextImpl
: NON_EXPORTED_BASE(public IndexedDBContext) {
public:
+ // Recorded in histograms, so append only.
+ enum ForceCloseReason {
+ FORCE_CLOSE_DELETE_ORIGIN = 0,
+ FORCE_CLOSE_BACKING_STORE_FAILURE,
+ FORCE_CLOSE_INTERNALS_PAGE,
+ FORCE_CLOSE_REASON_MAX
+ };
+
+ // The indexed db directory.
+ static const base::FilePath::CharType kIndexedDBDirectory[];
+
// If |data_path| is empty, nothing will be saved to disk.
IndexedDBContextImpl(const base::FilePath& data_path,
- quota::SpecialStoragePolicy* special_storage_policy,
- quota::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy,
+ storage::QuotaManagerProxy* quota_manager_proxy,
base::SequencedTaskRunner* task_runner);
IndexedDBFactory* GetIDBFactory();
- // The indexed db directory.
- static const base::FilePath::CharType kIndexedDBDirectory[];
-
// Disables the exit-time deletion of session-only data.
void SetForceKeepSessionState() { force_keep_session_state_ = true; }
// IndexedDBContext implementation:
- virtual base::TaskRunner* TaskRunner() const OVERRIDE;
- virtual std::vector<IndexedDBInfo> GetAllOriginsInfo() OVERRIDE;
- virtual int64 GetOriginDiskUsage(const GURL& origin_url) OVERRIDE;
- virtual void DeleteForOrigin(const GURL& origin_url) OVERRIDE;
- virtual base::FilePath GetFilePathForTesting(
- const std::string& origin_id) const OVERRIDE;
- virtual void SetTaskRunnerForTesting(base::SequencedTaskRunner* task_runner)
- OVERRIDE;
+ base::SequencedTaskRunner* TaskRunner() const override;
+ std::vector<IndexedDBInfo> GetAllOriginsInfo() override;
+ int64 GetOriginDiskUsage(const GURL& origin_url) override;
+ void DeleteForOrigin(const GURL& origin_url) override;
+ base::FilePath GetFilePathForTesting(
+ const std::string& origin_id) const override;
+ void SetTaskRunnerForTesting(base::SequencedTaskRunner* task_runner) override;
// Methods called by IndexedDBDispatcherHost for quota support.
void ConnectionOpened(const GURL& origin_url, IndexedDBConnection* db);
@@ -72,20 +79,12 @@ class CONTENT_EXPORT IndexedDBContextImpl
bool WouldBeOverQuota(const GURL& origin_url, int64 additional_bytes);
bool IsOverQuota(const GURL& origin_url);
- quota::QuotaManagerProxy* quota_manager_proxy();
+ storage::QuotaManagerProxy* quota_manager_proxy();
std::vector<GURL> GetAllOrigins();
base::Time GetOriginLastModified(const GURL& origin_url);
base::ListValue* GetAllOriginsDetails();
- // Recorded in histograms, so append only.
- enum ForceCloseReason {
- FORCE_CLOSE_DELETE_ORIGIN = 0,
- FORCE_CLOSE_BACKING_STORE_FAILURE,
- FORCE_CLOSE_INTERNALS_PAGE,
- FORCE_CLOSE_REASON_MAX
- };
-
// ForceClose takes a value rather than a reference since it may release the
// owning object.
void ForceClose(const GURL origin_url, ForceCloseReason reason);
@@ -103,8 +102,10 @@ class CONTENT_EXPORT IndexedDBContextImpl
data_path_ = data_path;
}
+ bool is_incognito() const { return data_path_.empty(); }
+
protected:
- virtual ~IndexedDBContextImpl();
+ ~IndexedDBContextImpl() override;
private:
FRIEND_TEST_ALL_PREFIXES(IndexedDBTest, ClearLocalState);
@@ -121,7 +122,7 @@ class CONTENT_EXPORT IndexedDBContextImpl
void EnsureDiskUsageCacheInitialized(const GURL& origin_url);
void QueryDiskAndUpdateQuotaUsage(const GURL& origin_url);
void GotUsageAndQuota(const GURL& origin_url,
- quota::QuotaStatusCode,
+ storage::QuotaStatusCode,
int64 usage,
int64 quota);
void GotUpdatedQuota(const GURL& origin_url, int64 usage, int64 quota);
@@ -142,9 +143,9 @@ class CONTENT_EXPORT IndexedDBContextImpl
base::FilePath data_path_;
// If true, nothing (not even session-only data) should be deleted on exit.
bool force_keep_session_state_;
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
- scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
- base::SequencedTaskRunner* task_runner_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
scoped_ptr<std::set<GURL> > origin_set_;
OriginToSizeMap origin_size_map_;
OriginToSizeMap space_available_map_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.cc b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
index 7715a998a75..4fc3c0ea44e 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.cc
@@ -19,7 +19,7 @@ namespace content {
IndexedDBCursor::IndexedDBCursor(
scoped_ptr<IndexedDBBackingStore::Cursor> cursor,
indexed_db::CursorType cursor_type,
- IndexedDBDatabase::TaskType task_type,
+ blink::WebIDBTaskType task_type,
IndexedDBTransaction* transaction)
: task_type_(task_type),
cursor_type_(cursor_type),
@@ -170,7 +170,7 @@ void IndexedDBCursor::CursorPrefetchIterationOperation(
}
callbacks->OnSuccessWithPrefetch(
- found_keys, found_primary_keys, found_values);
+ found_keys, found_primary_keys, &found_values);
}
leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches,
diff --git a/chromium/content/browser/indexed_db/indexed_db_cursor.h b/chromium/content/browser/indexed_db/indexed_db_cursor.h
index 7c1491aff7f..a0f42000b0c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_cursor.h
+++ b/chromium/content/browser/indexed_db/indexed_db_cursor.h
@@ -13,6 +13,7 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
namespace content {
@@ -23,7 +24,7 @@ class CONTENT_EXPORT IndexedDBCursor
public:
IndexedDBCursor(scoped_ptr<IndexedDBBackingStore::Cursor> cursor,
indexed_db::CursorType cursor_type,
- IndexedDBDatabase::TaskType task_type,
+ blink::WebIDBTaskType task_type,
IndexedDBTransaction* transaction);
void Advance(uint32 count, scoped_refptr<IndexedDBCallbacks> callbacks);
@@ -59,7 +60,7 @@ class CONTENT_EXPORT IndexedDBCursor
~IndexedDBCursor();
- IndexedDBDatabase::TaskType task_type_;
+ blink::WebIDBTaskType task_type_;
indexed_db::CursorType cursor_type_;
const scoped_refptr<IndexedDBTransaction> transaction_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index cc0738b6d8e..905cf061f3a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -26,9 +26,9 @@
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/common/indexed_db/indexed_db_key_path.h"
#include "content/common/indexed_db/indexed_db_key_range.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
#include "third_party/leveldatabase/env_chromium.h"
-#include "webkit/browser/blob/blob_data_handle.h"
using base::ASCIIToUTF16;
using base::Int64ToString16;
@@ -123,6 +123,7 @@ IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
kInvalidId),
identifier_(unique_identifier),
factory_(factory) {
+ DCHECK(factory != NULL);
}
void IndexedDBDatabase::AddObjectStore(
@@ -271,7 +272,7 @@ void IndexedDBDatabase::CreateObjectStore(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
+ DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
if (ContainsKey(metadata_.object_stores, object_store_id)) {
DLOG(ERROR) << "Invalid object_store_id";
@@ -320,7 +321,7 @@ void IndexedDBDatabase::DeleteObjectStore(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
+ DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
if (!ValidateObjectStoreId(object_store_id))
return;
@@ -342,7 +343,7 @@ void IndexedDBDatabase::CreateIndex(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
+ DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
if (!ValidateObjectStoreIdAndNewIndexId(object_store_id, index_id))
return;
@@ -394,7 +395,7 @@ void IndexedDBDatabase::DeleteIndex(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
+ DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
if (!ValidateObjectStoreIdAndIndexId(object_store_id, index_id))
return;
@@ -459,8 +460,15 @@ void IndexedDBDatabase::Commit(int64 transaction_id) {
// been dispatched to the frontend, so it will find out about that
// asynchronously.
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
- if (transaction)
- transaction->Commit();
+ if (transaction) {
+ scoped_refptr<IndexedDBFactory> factory = factory_;
+ leveldb::Status s = transaction->Commit();
+ if (s.IsCorruption()) {
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error committing transaction.");
+ factory->HandleBackingStoreCorruption(identifier_.first, error);
+ }
+ }
}
void IndexedDBDatabase::Abort(int64 transaction_id) {
@@ -535,7 +543,7 @@ void IndexedDBDatabase::GetOperation(
id(),
object_store_id,
*key_range,
- indexed_db::CURSOR_NEXT,
+ blink::WebIDBCursorDirectionNext,
&s);
} else if (cursor_type == indexed_db::CURSOR_KEY_ONLY) {
// Index Value Retrieval Operation
@@ -545,7 +553,7 @@ void IndexedDBDatabase::GetOperation(
object_store_id,
index_id,
*key_range,
- indexed_db::CURSOR_NEXT,
+ blink::WebIDBCursorDirectionNext,
&s);
} else {
// Index Referenced Value Retrieval Operation
@@ -555,7 +563,7 @@ void IndexedDBDatabase::GetOperation(
object_store_id,
index_id,
*key_range,
- indexed_db::CURSOR_NEXT,
+ blink::WebIDBCursorDirectionNext,
&s);
}
@@ -710,9 +718,9 @@ struct IndexedDBDatabase::PutOperationParams {
PutOperationParams() {}
int64 object_store_id;
IndexedDBValue value;
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
scoped_ptr<IndexedDBKey> key;
- IndexedDBDatabase::PutMode put_mode;
+ blink::WebIDBPutMode put_mode;
scoped_refptr<IndexedDBCallbacks> callbacks;
std::vector<IndexKeys> index_keys;
@@ -723,16 +731,16 @@ struct IndexedDBDatabase::PutOperationParams {
void IndexedDBDatabase::Put(int64 transaction_id,
int64 object_store_id,
IndexedDBValue* value,
- ScopedVector<webkit_blob::BlobDataHandle>* handles,
+ ScopedVector<storage::BlobDataHandle>* handles,
scoped_ptr<IndexedDBKey> key,
- PutMode put_mode,
+ blink::WebIDBPutMode put_mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
const std::vector<IndexKeys>& index_keys) {
IDB_TRACE1("IndexedDBDatabase::Put", "txn.id", transaction_id);
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
+ DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
if (!ValidateObjectStoreId(object_store_id))
return;
@@ -754,7 +762,7 @@ void IndexedDBDatabase::Put(int64 transaction_id,
void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
IndexedDBTransaction* transaction) {
IDB_TRACE1("IndexedDBDatabase::PutOperation", "txn.id", transaction->id());
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
+ DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
bool key_was_generated = false;
DCHECK(metadata_.object_stores.find(params->object_store_id) !=
@@ -764,7 +772,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
DCHECK(object_store.auto_increment || params->key->IsValid());
scoped_ptr<IndexedDBKey> key;
- if (params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
+ if (params->put_mode != blink::WebIDBPutModeCursorUpdate &&
object_store.auto_increment && !params->key->IsValid()) {
scoped_ptr<IndexedDBKey> auto_inc_key = GenerateKey(
backing_store_.get(), transaction, id(), params->object_store_id);
@@ -783,7 +791,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
DCHECK(key->IsValid());
IndexedDBBackingStore::RecordIdentifier record_identifier;
- if (params->put_mode == IndexedDBDatabase::ADD_ONLY) {
+ if (params->put_mode == blink::WebIDBPutModeAddOnly) {
bool found = false;
leveldb::Status s = backing_store_->KeyExistsInObjectStore(
transaction->BackingStoreTransaction(),
@@ -841,7 +849,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
id(),
params->object_store_id,
*key,
- params->value,
+ &params->value,
&params->handles,
&record_identifier);
if (!s.ok()) {
@@ -865,7 +873,7 @@ void IndexedDBDatabase::PutOperation(scoped_ptr<PutOperationParams> params,
}
if (object_store.auto_increment &&
- params->put_mode != IndexedDBDatabase::CURSOR_UPDATE &&
+ params->put_mode != blink::WebIDBPutModeCursorUpdate &&
key->type() == WebIDBKeyTypeNumber) {
leveldb::Status s = UpdateKeyGenerator(backing_store_.get(),
transaction,
@@ -895,7 +903,7 @@ void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
+ DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
// TODO(alecflett): This method could be asynchronous, but we need to
// evaluate if it's worth the extra complexity.
@@ -932,7 +940,7 @@ void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
const IndexedDBObjectStoreMetadata& object_store_metadata =
metadata_.object_stores[object_store_id];
bool backing_store_success = MakeIndexWriters(transaction,
- backing_store_,
+ backing_store_.get(),
id(),
object_store_metadata,
*primary_key,
@@ -956,7 +964,7 @@ void IndexedDBDatabase::SetIndexKeys(int64 transaction_id,
for (size_t i = 0; i < index_writers.size(); ++i) {
IndexWriter* index_writer = index_writers[i];
index_writer->WriteIndexKeys(record_identifier,
- backing_store_,
+ backing_store_.get(),
transaction->BackingStoreTransaction(),
id(),
object_store_id);
@@ -970,10 +978,10 @@ void IndexedDBDatabase::SetIndexesReady(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_EQ(transaction->mode(), indexed_db::TRANSACTION_VERSION_CHANGE);
+ DCHECK_EQ(transaction->mode(), blink::WebIDBTransactionModeVersionChange);
transaction->ScheduleTask(
- IndexedDBDatabase::PREEMPTIVE_TASK,
+ blink::WebIDBTaskTypePreemptive,
base::Bind(&IndexedDBDatabase::SetIndexesReadyOperation,
this,
index_ids.size()));
@@ -994,9 +1002,9 @@ struct IndexedDBDatabase::OpenCursorOperationParams {
int64 object_store_id;
int64 index_id;
scoped_ptr<IndexedDBKeyRange> key_range;
- indexed_db::CursorDirection direction;
+ blink::WebIDBCursorDirection direction;
indexed_db::CursorType cursor_type;
- IndexedDBDatabase::TaskType task_type;
+ blink::WebIDBTaskType task_type;
scoped_refptr<IndexedDBCallbacks> callbacks;
private:
@@ -1008,9 +1016,9 @@ void IndexedDBDatabase::OpenCursor(
int64 object_store_id,
int64 index_id,
scoped_ptr<IndexedDBKeyRange> key_range,
- indexed_db::CursorDirection direction,
+ blink::WebIDBCursorDirection direction,
bool key_only,
- TaskType task_type,
+ blink::WebIDBTaskType task_type,
scoped_refptr<IndexedDBCallbacks> callbacks) {
IDB_TRACE1("IndexedDBDatabase::OpenCursor", "txn.id", transaction_id);
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
@@ -1043,14 +1051,14 @@ void IndexedDBDatabase::OpenCursorOperation(
// until the indexing is complete. This can't happen any earlier
// because we don't want to switch to early mode in case multiple
// indexes are being created in a row, with Put()'s in between.
- if (params->task_type == IndexedDBDatabase::PREEMPTIVE_TASK)
+ if (params->task_type == blink::WebIDBTaskTypePreemptive)
transaction->AddPreemptiveEvent();
leveldb::Status s;
scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor;
if (params->index_id == IndexedDBIndexMetadata::kInvalidId) {
if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
- DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
+ DCHECK_EQ(params->task_type, blink::WebIDBTaskTypeNormal);
backing_store_cursor = backing_store_->OpenObjectStoreKeyCursor(
transaction->BackingStoreTransaction(),
id(),
@@ -1068,7 +1076,7 @@ void IndexedDBDatabase::OpenCursorOperation(
&s);
}
} else {
- DCHECK_EQ(params->task_type, IndexedDBDatabase::NORMAL_TASK);
+ DCHECK_EQ(params->task_type, blink::WebIDBTaskTypeNormal);
if (params->cursor_type == indexed_db::CURSOR_KEY_ONLY) {
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
transaction->BackingStoreTransaction(),
@@ -1153,7 +1161,7 @@ void IndexedDBDatabase::CountOperation(
id(),
object_store_id,
*key_range,
- indexed_db::CURSOR_NEXT,
+ blink::WebIDBCursorDirectionNext,
&s);
} else {
backing_store_cursor = backing_store_->OpenIndexKeyCursor(
@@ -1162,7 +1170,7 @@ void IndexedDBDatabase::CountOperation(
object_store_id,
index_id,
*key_range,
- indexed_db::CURSOR_NEXT,
+ blink::WebIDBCursorDirectionNext,
&s);
}
if (!s.ok()) {
@@ -1197,7 +1205,7 @@ void IndexedDBDatabase::DeleteRange(
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
+ DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
if (!ValidateObjectStoreId(object_store_id))
return;
@@ -1243,7 +1251,7 @@ void IndexedDBDatabase::Clear(int64 transaction_id,
IndexedDBTransaction* transaction = GetTransaction(transaction_id);
if (!transaction)
return;
- DCHECK_NE(transaction->mode(), indexed_db::TRANSACTION_READ_ONLY);
+ DCHECK_NE(transaction->mode(), blink::WebIDBTransactionModeReadOnly);
if (!ValidateObjectStoreId(object_store_id))
return;
@@ -1347,7 +1355,7 @@ void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
DCHECK_EQ(transactions_[transaction->id()], transaction);
transactions_.erase(transaction->id());
- if (transaction->mode() == indexed_db::TRANSACTION_VERSION_CHANGE) {
+ if (transaction->mode() == blink::WebIDBTransactionModeVersionChange) {
if (pending_second_half_open_) {
if (committed) {
DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
@@ -1371,11 +1379,14 @@ void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
}
}
-void IndexedDBDatabase::TransactionCommitFailed() {
- // Factory may be null in unit tests.
- if (!factory_)
- return;
- factory_->HandleBackingStoreFailure(backing_store_->origin_url());
+void IndexedDBDatabase::TransactionCommitFailed(const leveldb::Status& status) {
+ if (status.IsCorruption()) {
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Error committing transaction");
+ factory_->HandleBackingStoreCorruption(backing_store_->origin_url(), error);
+ } else {
+ factory_->HandleBackingStoreFailure(backing_store_->origin_url());
+ }
}
size_t IndexedDBDatabase::ConnectionCount() const {
@@ -1448,7 +1459,7 @@ void IndexedDBDatabase::CreateTransaction(
int64 transaction_id,
IndexedDBConnection* connection,
const std::vector<int64>& object_store_ids,
- uint16 mode) {
+ blink::WebIDBTransactionMode mode) {
IDB_TRACE1("IndexedDBDatabase::CreateTransaction", "txn.id", transaction_id);
DCHECK(connections_.count(connection));
DCHECK(transactions_.find(transaction_id) == transactions_.end());
@@ -1461,9 +1472,9 @@ void IndexedDBDatabase::CreateTransaction(
transaction_id,
connection->callbacks(),
std::set<int64>(object_store_ids.begin(), object_store_ids.end()),
- static_cast<indexed_db::TransactionMode>(mode),
+ mode,
this,
- new IndexedDBBackingStore::Transaction(backing_store_)));
+ new IndexedDBBackingStore::Transaction(backing_store_.get())));
}
void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
@@ -1478,7 +1489,7 @@ bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
void IndexedDBDatabase::OpenConnection(
const IndexedDBPendingConnection& connection) {
- DCHECK(backing_store_);
+ DCHECK(backing_store_.get());
// TODO(jsbell): Should have a priority queue so that higher version
// requests are processed first. http://crbug.com/225850
@@ -1575,25 +1586,20 @@ void IndexedDBDatabase::RunVersionChangeTransaction(
scoped_ptr<IndexedDBConnection> connection,
int64 transaction_id,
int64 requested_version) {
-
- DCHECK(callbacks);
+ DCHECK(callbacks.get());
DCHECK(connections_.count(connection.get()));
if (ConnectionCount() > 1) {
DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss());
// Front end ensures the event is not fired at connections that have
// close_pending set.
- for (ConnectionSet::const_iterator it = connections_.begin();
- it != connections_.end();
- ++it) {
- if (*it != connection.get()) {
- (*it)->callbacks()->OnVersionChange(metadata_.int_version,
- requested_version);
+ for (const auto* iter : connections_) {
+ if (iter != connection.get()) {
+ iter->callbacks()->OnVersionChange(metadata_.int_version,
+ requested_version);
}
}
- // TODO(jsbell): Remove the call to OnBlocked and instead wait
- // until the frontend tells us that all the "versionchange" events
- // have been delivered. http://crbug.com/100123
- callbacks->OnBlocked(metadata_.int_version);
+ // OnBlocked will be fired at the request when one of the other
+ // connections acks that the OnVersionChange was ignored.
DCHECK(!pending_run_version_change_transaction_call_);
pending_run_version_change_transaction_call_.reset(new PendingUpgradeCall(
@@ -1614,7 +1620,7 @@ void IndexedDBDatabase::RunVersionChangeTransactionFinal(
CreateTransaction(transaction_id,
connection.get(),
object_store_ids,
- indexed_db::TRANSACTION_VERSION_CHANGE);
+ blink::WebIDBTransactionModeVersionChange);
transactions_[transaction_id]->ScheduleTask(
base::Bind(&IndexedDBDatabase::VersionChangeOperation,
@@ -1629,18 +1635,15 @@ void IndexedDBDatabase::DeleteDatabase(
scoped_refptr<IndexedDBCallbacks> callbacks) {
if (IsDeleteDatabaseBlocked()) {
- for (ConnectionSet::const_iterator it = connections_.begin();
- it != connections_.end();
- ++it) {
+ for (const auto* connection : connections_) {
// Front end ensures the event is not fired at connections that have
// close_pending set.
- (*it)->callbacks()->OnVersionChange(
+ connection->callbacks()->OnVersionChange(
metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
}
- // TODO(jsbell): Only fire OnBlocked if there are open
- // connections after the VersionChangeEvents are received, not
- // just set up to fire. http://crbug.com/100123
- callbacks->OnBlocked(metadata_.int_version);
+ // OnBlocked will be fired at the request when one of the other
+ // connections acks that the OnVersionChange was ignored.
+
pending_delete_calls_.push_back(new PendingDeleteCall(callbacks));
return;
}
@@ -1654,11 +1657,17 @@ bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
void IndexedDBDatabase::DeleteDatabaseFinal(
scoped_refptr<IndexedDBCallbacks> callbacks) {
DCHECK(!IsDeleteDatabaseBlocked());
- DCHECK(backing_store_);
- if (!backing_store_->DeleteDatabase(metadata_.name).ok()) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error deleting database."));
+ DCHECK(backing_store_.get());
+ leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name);
+ if (!s.ok()) {
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error deleting database.");
+ callbacks->OnError(error);
+ if (s.IsCorruption()) {
+ GURL origin_url = backing_store_->origin_url();
+ backing_store_ = NULL;
+ factory_->HandleBackingStoreCorruption(origin_url, error);
+ }
return;
}
int64 old_version = metadata_.int_version;
@@ -1667,8 +1676,7 @@ void IndexedDBDatabase::DeleteDatabaseFinal(
metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
metadata_.object_stores.clear();
callbacks->OnSuccess(old_version);
- if (factory_)
- factory_->DatabaseDeleted(identifier_);
+ factory_->DatabaseDeleted(identifier_);
}
void IndexedDBDatabase::ForceClose() {
@@ -1682,6 +1690,16 @@ void IndexedDBDatabase::ForceClose() {
DCHECK(connections_.empty());
}
+void IndexedDBDatabase::VersionChangeIgnored() {
+ if (pending_run_version_change_transaction_call_)
+ pending_run_version_change_transaction_call_->callbacks()->OnBlocked(
+ metadata_.int_version);
+
+ for (const auto& pending_delete_call : pending_delete_calls_)
+ pending_delete_call->callbacks()->OnBlocked(metadata_.int_version);
+}
+
+
void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
DCHECK(connections_.count(connection));
DCHECK(connection->IsConnected());
@@ -1694,12 +1712,9 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
// complete, but can occur on process termination or forced close.
{
TransactionMap transactions(transactions_);
- for (TransactionMap::const_iterator it = transactions.begin(),
- end = transactions.end();
- it != end;
- ++it) {
- if (it->second->connection() == connection->callbacks())
- it->second->Abort(
+ for (const auto& it : transactions) {
+ if (it.second->connection() == connection->callbacks())
+ it.second->Abort(
IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Connection is closing."));
}
@@ -1724,12 +1739,7 @@ void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
const GURL origin_url = backing_store_->origin_url();
backing_store_ = NULL;
- // factory_ should only be null in unit tests.
- // TODO(jsbell): DCHECK(factory_ || !in_unit_tests) - somehow.
- if (factory_) {
- factory_->ReleaseDatabase(identifier_, forced);
- factory_ = NULL;
- }
+ factory_->ReleaseDatabase(identifier_, forced);
}
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.h b/chromium/content/browser/indexed_db/indexed_db_database.h
index 63a438a4bb6..bcde7190c50 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -20,6 +20,7 @@
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "content/browser/indexed_db/list_set.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
#include "url/gurl.h"
namespace content {
@@ -37,17 +38,6 @@ struct IndexedDBValue;
class CONTENT_EXPORT IndexedDBDatabase
: NON_EXPORTED_BASE(public base::RefCounted<IndexedDBDatabase>) {
public:
- enum TaskType {
- NORMAL_TASK = 0,
- PREEMPTIVE_TASK
- };
-
- enum PutMode {
- ADD_OR_UPDATE,
- ADD_ONLY,
- CURSOR_UPDATE
- };
-
// An index and corresponding set of keys
typedef std::pair<int64, std::vector<IndexedDBKey> > IndexKeys;
@@ -91,10 +81,15 @@ class CONTENT_EXPORT IndexedDBDatabase
void CreateTransaction(int64 transaction_id,
IndexedDBConnection* connection,
const std::vector<int64>& object_store_ids,
- uint16 mode);
+ blink::WebIDBTransactionMode mode);
void Close(IndexedDBConnection* connection, bool forced);
void ForceClose();
+ // Ack that one of the connections notified with a "versionchange" event did
+ // not promptly close. Therefore a "blocked" event should be fired at the
+ // pending connection.
+ void VersionChangeIgnored();
+
void Commit(int64 transaction_id);
void Abort(int64 transaction_id);
void Abort(int64 transaction_id, const IndexedDBDatabaseError& error);
@@ -119,7 +114,7 @@ class CONTENT_EXPORT IndexedDBDatabase
void TransactionFinished(IndexedDBTransaction* transaction, bool committed);
// Called by transactions to report failure committing to the backing store.
- void TransactionCommitFailed();
+ void TransactionCommitFailed(const leveldb::Status& status);
void Get(int64 transaction_id,
int64 object_store_id,
@@ -130,9 +125,9 @@ class CONTENT_EXPORT IndexedDBDatabase
void Put(int64 transaction_id,
int64 object_store_id,
IndexedDBValue* value,
- ScopedVector<webkit_blob::BlobDataHandle>* handles,
+ ScopedVector<storage::BlobDataHandle>* handles,
scoped_ptr<IndexedDBKey> key,
- PutMode mode,
+ blink::WebIDBPutMode mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
const std::vector<IndexKeys>& index_keys);
void SetIndexKeys(int64 transaction_id,
@@ -146,9 +141,9 @@ class CONTENT_EXPORT IndexedDBDatabase
int64 object_store_id,
int64 index_id,
scoped_ptr<IndexedDBKeyRange> key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
bool key_only,
- TaskType task_type,
+ blink::WebIDBTaskType task_type,
scoped_refptr<IndexedDBCallbacks> callbacks);
void Count(int64 transaction_id,
int64 object_store_id,
@@ -229,6 +224,15 @@ class CONTENT_EXPORT IndexedDBDatabase
private:
friend class base::RefCounted<IndexedDBDatabase>;
+ class PendingDeleteCall;
+ class PendingSuccessCall;
+ class PendingUpgradeCall;
+
+ typedef std::map<int64, IndexedDBTransaction*> TransactionMap;
+ typedef std::list<IndexedDBPendingConnection> PendingOpenCallList;
+ typedef std::list<PendingDeleteCall*> PendingDeleteCallList;
+ typedef list_set<IndexedDBConnection*> ConnectionSet;
+
IndexedDBDatabase(const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
@@ -273,22 +277,12 @@ class CONTENT_EXPORT IndexedDBDatabase
IndexedDBTransactionCoordinator transaction_coordinator_;
- typedef std::map<int64, IndexedDBTransaction*> TransactionMap;
TransactionMap transactions_;
-
- typedef std::list<IndexedDBPendingConnection> PendingOpenCallList;
PendingOpenCallList pending_open_calls_;
-
- class PendingUpgradeCall;
scoped_ptr<PendingUpgradeCall> pending_run_version_change_transaction_call_;
- class PendingSuccessCall;
scoped_ptr<PendingSuccessCall> pending_second_half_open_;
-
- class PendingDeleteCall;
- typedef std::list<PendingDeleteCall*> PendingDeleteCallList;
PendingDeleteCallList pending_delete_calls_;
- typedef list_set<IndexedDBConnection*> ConnectionSet;
ConnectionSet connections_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabase);
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
index dcaf8233657..865086a9b27 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -16,12 +16,12 @@
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_cursor.h"
-#include "content/browser/indexed_db/indexed_db_factory.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
+#include "content/browser/indexed_db/mock_indexed_db_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::ASCIIToUTF16;
@@ -37,12 +37,12 @@ TEST(IndexedDBDatabaseTest, BackingStoreRetention) {
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef());
- IndexedDBFactory* factory = 0;
+ scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
leveldb::Status s;
scoped_refptr<IndexedDBDatabase> db =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
- backing_store,
- factory,
+ backing_store.get(),
+ factory.get(),
IndexedDBDatabase::Identifier(),
&s);
ASSERT_TRUE(s.ok());
@@ -56,12 +56,12 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef()); // local
- IndexedDBFactory* factory = 0;
+ scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
leveldb::Status s;
scoped_refptr<IndexedDBDatabase> db =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
- backing_store,
- factory,
+ backing_store.get(),
+ factory.get(),
IndexedDBDatabase::Identifier(),
&s);
ASSERT_TRUE(s.ok());
@@ -114,12 +114,12 @@ TEST(IndexedDBDatabaseTest, ForcedClose) {
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef());
- IndexedDBFactory* factory = 0;
+ scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
leveldb::Status s;
scoped_refptr<IndexedDBDatabase> database =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
- backing_store,
- factory,
+ backing_store.get(),
+ factory.get(),
IndexedDBDatabase::Identifier(),
&s);
ASSERT_TRUE(s.ok());
@@ -136,14 +136,14 @@ TEST(IndexedDBDatabaseTest, ForcedClose) {
upgrade_transaction_id,
IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
database->OpenConnection(connection);
- EXPECT_EQ(database, request->connection()->database());
+ EXPECT_EQ(database.get(), request->connection()->database());
const int64 transaction_id = 123;
const std::vector<int64> scope;
database->CreateTransaction(transaction_id,
request->connection(),
scope,
- indexed_db::TRANSACTION_READ_ONLY);
+ blink::WebIDBTransactionModeReadOnly);
request->connection()->ForceClose();
@@ -158,16 +158,14 @@ class MockDeleteCallbacks : public IndexedDBCallbacks {
blocked_called_(false),
success_called_(false) {}
- virtual void OnBlocked(int64 existing_version) OVERRIDE {
- blocked_called_ = true;
- }
- virtual void OnSuccess(int64 result) OVERRIDE { success_called_ = true; }
+ void OnBlocked(int64 existing_version) override { blocked_called_ = true; }
+ void OnSuccess(int64 result) override { success_called_ = true; }
bool blocked_called() const { return blocked_called_; }
bool success_called() const { return success_called_; }
private:
- virtual ~MockDeleteCallbacks() {}
+ ~MockDeleteCallbacks() override {}
bool blocked_called_;
bool success_called_;
@@ -180,12 +178,12 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
new IndexedDBFakeBackingStore();
EXPECT_TRUE(backing_store->HasOneRef()); // local
- IndexedDBFactory* factory = 0;
+ scoped_refptr<MockIndexedDBFactory> factory = new MockIndexedDBFactory();
leveldb::Status s;
scoped_refptr<IndexedDBDatabase> db =
IndexedDBDatabase::Create(ASCIIToUTF16("db"),
- backing_store,
- factory,
+ backing_store.get(),
+ factory.get(),
IndexedDBDatabase::Identifier(),
&s);
ASSERT_TRUE(s.ok());
@@ -208,7 +206,10 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
scoped_refptr<MockDeleteCallbacks> request2(new MockDeleteCallbacks());
db->DeleteDatabase(request2);
+ EXPECT_FALSE(request2->blocked_called());
+ db->VersionChangeIgnored();
EXPECT_TRUE(request2->blocked_called());
+
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
db->Close(request1->connection(), true /* forced */);
@@ -223,14 +224,16 @@ void DummyOperation(IndexedDBTransaction* transaction) {
class IndexedDBDatabaseOperationTest : public testing::Test {
public:
- IndexedDBDatabaseOperationTest() : commit_success_(leveldb::Status::OK()) {}
+ IndexedDBDatabaseOperationTest()
+ : commit_success_(leveldb::Status::OK()),
+ factory_(new MockIndexedDBFactory()) {}
- virtual void SetUp() {
+ void SetUp() override {
backing_store_ = new IndexedDBFakeBackingStore();
leveldb::Status s;
db_ = IndexedDBDatabase::Create(ASCIIToUTF16("db"),
- backing_store_,
- NULL /*factory*/,
+ backing_store_.get(),
+ factory_.get(),
IndexedDBDatabase::Identifier(),
&s);
ASSERT_TRUE(s.ok());
@@ -251,10 +254,10 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
transaction_id,
callbacks_,
std::set<int64>() /*scope*/,
- indexed_db::TRANSACTION_VERSION_CHANGE,
- db_,
+ blink::WebIDBTransactionModeVersionChange,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success_));
- db_->TransactionCreated(transaction_);
+ db_->TransactionCreated(transaction_.get());
// Add a dummy task which takes the place of the VersionChangeOperation
// which kicks off the upgrade. This ensures that the transaction has
@@ -275,6 +278,7 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
private:
base::MessageLoop message_loop_;
+ scoped_refptr<MockIndexedDBFactory> factory_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabaseOperationTest);
};
@@ -386,7 +390,7 @@ TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
// Put is asynchronous
IndexedDBValue value("value1", std::vector<IndexedDBBlobInfo>());
- ScopedVector<webkit_blob::BlobDataHandle> handles;
+ ScopedVector<storage::BlobDataHandle> handles;
scoped_ptr<IndexedDBKey> key(new IndexedDBKey("key"));
std::vector<IndexedDBDatabase::IndexKeys> index_keys;
scoped_refptr<MockIndexedDBCallbacks> request(
@@ -396,7 +400,7 @@ TEST_F(IndexedDBDatabaseOperationTest, CreatePutDelete) {
&value,
&handles,
key.Pass(),
- IndexedDBDatabase::ADD_ONLY,
+ blink::WebIDBPutModeAddOnly,
request,
index_keys);
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
index 47265d5c986..3584f03e83a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -26,13 +26,13 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/common/database/database_identifier.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/common/database/database_identifier.h"
-using webkit_database::DatabaseUtil;
+using storage::DatabaseUtil;
using blink::WebIDBKey;
namespace content {
@@ -50,7 +50,7 @@ IndexedDBDispatcherHost::IndexedDBDispatcherHost(
database_dispatcher_host_(new DatabaseDispatcherHost(this)),
cursor_dispatcher_host_(new CursorDispatcherHost(this)),
ipc_process_id_(ipc_process_id) {
- DCHECK(indexed_db_context_);
+ DCHECK(indexed_db_context_.get());
}
IndexedDBDispatcherHost::IndexedDBDispatcherHost(
@@ -65,7 +65,7 @@ IndexedDBDispatcherHost::IndexedDBDispatcherHost(
database_dispatcher_host_(new DatabaseDispatcherHost(this)),
cursor_dispatcher_host_(new CursorDispatcherHost(this)),
ipc_process_id_(ipc_process_id) {
- DCHECK(indexed_db_context_);
+ DCHECK(indexed_db_context_.get());
}
IndexedDBDispatcherHost::~IndexedDBDispatcherHost() {
@@ -211,7 +211,7 @@ uint32 IndexedDBDispatcherHost::TransactionIdToProcessId(
void IndexedDBDispatcherHost::HoldBlobDataHandle(
const std::string& uuid,
- scoped_ptr<webkit_blob::BlobDataHandle>& blob_data_handle) {
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
DCHECK(!ContainsKey(blob_data_handle_map_, uuid));
blob_data_handle_map_[uuid] = blob_data_handle.release();
}
@@ -240,12 +240,9 @@ IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) {
metadata.int_version = web_metadata.int_version;
metadata.max_object_store_id = web_metadata.max_object_store_id;
- for (content::IndexedDBDatabaseMetadata::ObjectStoreMap::const_iterator iter =
- web_metadata.object_stores.begin();
- iter != web_metadata.object_stores.end();
- ++iter) {
+ for (const auto& iter : web_metadata.object_stores) {
const content::IndexedDBObjectStoreMetadata& web_store_metadata =
- iter->second;
+ iter.second;
::IndexedDBObjectStoreMetadata idb_store_metadata;
idb_store_metadata.id = web_store_metadata.id;
idb_store_metadata.name = web_store_metadata.name;
@@ -253,12 +250,9 @@ IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(int32 ipc_cursor_id) {
idb_store_metadata.autoIncrement = web_store_metadata.auto_increment;
idb_store_metadata.max_index_id = web_store_metadata.max_index_id;
- for (content::IndexedDBObjectStoreMetadata::IndexMap::const_iterator
- index_iter = web_store_metadata.indexes.begin();
- index_iter != web_store_metadata.indexes.end();
- ++index_iter) {
+ for (const auto& index_iter : web_store_metadata.indexes) {
const content::IndexedDBIndexMetadata& web_index_metadata =
- index_iter->second;
+ index_iter.second;
::IndexedDBIndexMetadata idb_index_metadata;
idb_index_metadata.id = web_index_metadata.id;
idb_index_metadata.name = web_index_metadata.name;
@@ -278,7 +272,7 @@ void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames(
base::FilePath indexed_db_path = indexed_db_context_->data_path();
GURL origin_url =
- webkit_database::GetOriginFromIdentifier(params.database_identifier);
+ storage::GetOriginFromIdentifier(params.database_identifier);
Context()->GetIDBFactory()->GetDatabaseNames(
new IndexedDBCallbacks(
@@ -291,10 +285,11 @@ void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames(
void IndexedDBDispatcherHost::OnIDBFactoryOpen(
const IndexedDBHostMsg_FactoryOpen_Params& params) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ base::TimeTicks begin_time = base::TimeTicks::Now();
base::FilePath indexed_db_path = indexed_db_context_->data_path();
GURL origin_url =
- webkit_database::GetOriginFromIdentifier(params.database_identifier);
+ storage::GetOriginFromIdentifier(params.database_identifier);
int64 host_transaction_id = HostTransactionId(params.transaction_id);
@@ -307,6 +302,7 @@ void IndexedDBDispatcherHost::OnIDBFactoryOpen(
params.ipc_database_callbacks_id,
host_transaction_id,
origin_url);
+ callbacks->SetConnectionOpenStartTime(begin_time);
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks =
new IndexedDBDatabaseCallbacks(
this, params.ipc_thread_id, params.ipc_database_callbacks_id);
@@ -324,7 +320,7 @@ void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
GURL origin_url =
- webkit_database::GetOriginFromIdentifier(params.database_identifier);
+ storage::GetOriginFromIdentifier(params.database_identifier);
base::FilePath indexed_db_path = indexed_db_context_->data_path();
DCHECK(request_context_);
Context()->GetIDBFactory()->DeleteDatabase(
@@ -340,16 +336,15 @@ void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
// to the IndexedDBDispatcherHost.
void IndexedDBDispatcherHost::OnPutHelper(
const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<webkit_blob::BlobDataHandle*> handles) {
+ std::vector<storage::BlobDataHandle*> handles) {
database_dispatcher_host_->OnPut(params, handles);
}
void IndexedDBDispatcherHost::OnAckReceivedBlobs(
const std::vector<std::string>& uuids) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
- std::vector<std::string>::const_iterator iter;
- for (iter = uuids.begin(); iter != uuids.end(); ++iter)
- DropBlobDataHandle(*iter);
+ for (const auto& uuid : uuids)
+ DropBlobDataHandle(uuid);
}
void IndexedDBDispatcherHost::FinishTransaction(int64 host_transaction_id,
@@ -447,13 +442,11 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
}
DCHECK(transaction_database_map_.empty());
- for (WebIDBObjectIDToURLMap::iterator iter = database_url_map_.begin();
- iter != database_url_map_.end();
- iter++) {
- IndexedDBConnection* connection = map_.Lookup(iter->first);
+ for (const auto& iter : database_url_map_) {
+ IndexedDBConnection* connection = map_.Lookup(iter.first);
if (connection && connection->IsConnected()) {
connection->Close();
- parent_->Context()->ConnectionClosed(iter->second, connection);
+ parent_->Context()->ConnectionClosed(iter.second, connection);
}
}
}
@@ -475,6 +468,8 @@ bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseCreateTransaction,
OnCreateTransaction)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseClose, OnClose)
+ IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseVersionChangeIgnored,
+ OnVersionChangeIgnored)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseDestroyed, OnDestroyed)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabaseGet, OnGet)
IPC_MESSAGE_HANDLER(IndexedDBHostMsg_DatabasePut, OnPutWrapper)
@@ -568,6 +563,17 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
connection->Close();
}
+void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnVersionChangeIgnored(
+ int32 ipc_database_id) {
+ DCHECK(
+ parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ IndexedDBConnection* connection =
+ parent_->GetOrTerminateProcess(&map_, ipc_database_id);
+ if (!connection || !connection->IsConnected())
+ return;
+ connection->VersionChangeIgnored();
+}
+
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed(
int32 ipc_object_id) {
DCHECK(
@@ -603,7 +609,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPutWrapper(
const IndexedDBHostMsg_DatabasePut_Params& params) {
- std::vector<webkit_blob::BlobDataHandle*> handles;
+ std::vector<storage::BlobDataHandle*> handles;
for (size_t i = 0; i < params.blob_or_file_info.size(); ++i) {
const IndexedDBMsg_BlobOrFileInfo& info = params.blob_or_file_info[i];
handles.push_back(parent_->blob_storage_context_->context()
@@ -618,12 +624,11 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPutWrapper(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<webkit_blob::BlobDataHandle*> handles) {
-
+ std::vector<storage::BlobDataHandle*> handles) {
DCHECK(
parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
- ScopedVector<webkit_blob::BlobDataHandle> scoped_handles;
+ ScopedVector<storage::BlobDataHandle> scoped_handles;
scoped_handles.swap(handles);
IndexedDBConnection* connection =
@@ -664,15 +669,14 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
IndexedDBValue value;
value.bits = params.value;
value.blob_info.swap(blob_info);
- connection->database()->Put(
- host_transaction_id,
- params.object_store_id,
- &value,
- &scoped_handles,
- make_scoped_ptr(new IndexedDBKey(params.key)),
- static_cast<IndexedDBDatabase::PutMode>(params.put_mode),
- callbacks,
- params.index_keys);
+ connection->database()->Put(host_transaction_id,
+ params.object_store_id,
+ &value,
+ &scoped_handles,
+ make_scoped_ptr(new IndexedDBKey(params.key)),
+ params.put_mode,
+ callbacks,
+ params.index_keys);
TransactionIDToSizeMap* map =
&parent_->database_dispatcher_host_->transaction_size_map_;
// Size can't be big enough to overflow because it represents the
@@ -729,9 +733,9 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor(
params.object_store_id,
params.index_id,
make_scoped_ptr(new IndexedDBKeyRange(params.key_range)),
- static_cast<indexed_db::CursorDirection>(params.direction),
+ params.direction,
params.key_only,
- static_cast<IndexedDBDatabase::TaskType>(params.task_type),
+ params.task_type,
callbacks);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
index abbdab99234..667ec7cc2e8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -15,8 +15,8 @@
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/public/browser/browser_message_filter.h"
#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_data_handle.h"
struct IndexedDBDatabaseMetadata;
struct IndexedDBHostMsg_DatabaseCount_Params;
@@ -58,18 +58,18 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
const content::IndexedDBDatabaseMetadata& metadata);
// BrowserMessageFilter implementation.
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelClosing() override;
+ void OnDestruct() const override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
void FinishTransaction(int64 host_transaction_id, bool committed);
// A shortcut for accessing our context.
- IndexedDBContextImpl* Context() { return indexed_db_context_; }
- webkit_blob::BlobStorageContext* blob_storage_context() const {
+ IndexedDBContextImpl* Context() { return indexed_db_context_.get(); }
+ storage::BlobStorageContext* blob_storage_context() const {
return blob_storage_context_->context();
}
@@ -94,9 +94,8 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
static uint32 TransactionIdToRendererTransactionId(int64 host_transaction_id);
static uint32 TransactionIdToProcessId(int64 host_transaction_id);
- void HoldBlobDataHandle(
- const std::string& uuid,
- scoped_ptr<webkit_blob::BlobDataHandle>& blob_data_handle);
+ void HoldBlobDataHandle(const std::string& uuid,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle);
void DropBlobDataHandle(const std::string& uuid);
private:
@@ -104,30 +103,19 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
friend class BrowserThread;
friend class base::DeleteHelper<IndexedDBDispatcherHost>;
- virtual ~IndexedDBDispatcherHost();
-
- // Message processing. Most of the work is delegated to the dispatcher hosts
- // below.
- void OnIDBFactoryGetDatabaseNames(
- const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& p);
- void OnIDBFactoryOpen(const IndexedDBHostMsg_FactoryOpen_Params& p);
-
- void OnIDBFactoryDeleteDatabase(
- const IndexedDBHostMsg_FactoryDeleteDatabase_Params& p);
-
- void OnAckReceivedBlobs(const std::vector<std::string>& uuids);
- void OnPutHelper(const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<webkit_blob::BlobDataHandle*> handles);
-
- void ResetDispatcherHosts();
+ // Used in nested classes.
+ typedef std::map<std::string, storage::BlobDataHandle*> BlobDataHandleMap;
+ typedef std::map<int64, int64> TransactionIDToDatabaseIDMap;
+ typedef std::map<int64, uint64> TransactionIDToSizeMap;
+ typedef std::map<int64, GURL> TransactionIDToURLMap;
+ typedef std::map<int32, GURL> WebIDBObjectIDToURLMap;
// IDMap for RefCounted types
template <typename RefCountedType>
class RefIDMap {
- private:
+ public:
typedef int32 KeyType;
- public:
RefIDMap() {}
~RefIDMap() {}
@@ -154,24 +142,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
DISALLOW_COPY_AND_ASSIGN(RefIDMap);
};
- // Helper templates.
- template <class ReturnType>
- ReturnType* GetOrTerminateProcess(IDMap<ReturnType, IDMapOwnPointer>* map,
- int32 ipc_return_object_id);
- template <class ReturnType>
- ReturnType* GetOrTerminateProcess(RefIDMap<ReturnType>* map,
- int32 ipc_return_object_id);
-
- template <typename MapType>
- void DestroyObject(MapType* map, int32 ipc_object_id);
-
- // Used in nested classes.
- typedef std::map<int32, GURL> WebIDBObjectIDToURLMap;
-
- typedef std::map<int64, GURL> TransactionIDToURLMap;
- typedef std::map<int64, uint64> TransactionIDToSizeMap;
- typedef std::map<int64, int64> TransactionIDToDatabaseIDMap;
-
class DatabaseDispatcherHost {
public:
explicit DatabaseDispatcherHost(IndexedDBDispatcherHost* parent);
@@ -188,6 +158,7 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
void OnCreateTransaction(
const IndexedDBHostMsg_DatabaseCreateTransaction_Params&);
void OnClose(int32 ipc_database_id);
+ void OnVersionChangeIgnored(int32 ipc_database_id);
void OnDestroyed(int32 ipc_database_id);
void OnGet(const IndexedDBHostMsg_DatabaseGet_Params& params);
@@ -195,7 +166,7 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
// before posting to the IDB TaskRunner for the rest of the job.
void OnPutWrapper(const IndexedDBHostMsg_DatabasePut_Params& params);
void OnPut(const IndexedDBHostMsg_DatabasePut_Params& params,
- std::vector<webkit_blob::BlobDataHandle*> handles);
+ std::vector<storage::BlobDataHandle*> handles);
void OnSetIndexKeys(
const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params);
void OnSetIndexesReady(int32 ipc_database_id,
@@ -263,6 +234,34 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
DISALLOW_COPY_AND_ASSIGN(CursorDispatcherHost);
};
+ ~IndexedDBDispatcherHost() override;
+
+ // Helper templates.
+ template <class ReturnType>
+ ReturnType* GetOrTerminateProcess(IDMap<ReturnType, IDMapOwnPointer>* map,
+ int32 ipc_return_object_id);
+ template <class ReturnType>
+ ReturnType* GetOrTerminateProcess(RefIDMap<ReturnType>* map,
+ int32 ipc_return_object_id);
+
+ template <typename MapType>
+ void DestroyObject(MapType* map, int32 ipc_object_id);
+
+ // Message processing. Most of the work is delegated to the dispatcher hosts
+ // below.
+ void OnIDBFactoryGetDatabaseNames(
+ const IndexedDBHostMsg_FactoryGetDatabaseNames_Params& p);
+ void OnIDBFactoryOpen(const IndexedDBHostMsg_FactoryOpen_Params& p);
+
+ void OnIDBFactoryDeleteDatabase(
+ const IndexedDBHostMsg_FactoryDeleteDatabase_Params& p);
+
+ void OnAckReceivedBlobs(const std::vector<std::string>& uuids);
+ void OnPutHelper(const IndexedDBHostMsg_DatabasePut_Params& params,
+ std::vector<storage::BlobDataHandle*> handles);
+
+ void ResetDispatcherHosts();
+
// The getter holds the context until OnChannelConnected() can be called from
// the IO thread, which will extract the net::URLRequestContext from it.
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
@@ -270,7 +269,6 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
- typedef std::map<std::string, webkit_blob::BlobDataHandle*> BlobDataHandleMap;
BlobDataHandleMap blob_data_handle_map_;
// Only access on IndexedDB thread.
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.cc b/chromium/content/browser/indexed_db/indexed_db_factory.cc
deleted file mode 100644
index 3f08d06c9bd..00000000000
--- a/chromium/content/browser/indexed_db/indexed_db_factory.cc
+++ /dev/null
@@ -1,479 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/indexed_db/indexed_db_factory.h"
-
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "content/browser/indexed_db/indexed_db_backing_store.h"
-#include "content/browser/indexed_db/indexed_db_context_impl.h"
-#include "content/browser/indexed_db/indexed_db_database_error.h"
-#include "content/browser/indexed_db/indexed_db_tracing.h"
-#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
-#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
-#include "third_party/leveldatabase/env_chromium.h"
-#include "webkit/common/database/database_identifier.h"
-
-using base::ASCIIToUTF16;
-
-namespace content {
-
-const int64 kBackingStoreGracePeriodMs = 2000;
-
-IndexedDBFactory::IndexedDBFactory(IndexedDBContextImpl* context)
- : context_(context) {}
-
-IndexedDBFactory::~IndexedDBFactory() {}
-
-void IndexedDBFactory::RemoveDatabaseFromMaps(
- const IndexedDBDatabase::Identifier& identifier) {
- IndexedDBDatabaseMap::iterator it = database_map_.find(identifier);
- DCHECK(it != database_map_.end());
- IndexedDBDatabase* database = it->second;
- database_map_.erase(it);
-
- std::pair<OriginDBMap::iterator, OriginDBMap::iterator> range =
- origin_dbs_.equal_range(database->identifier().first);
- DCHECK(range.first != range.second);
- for (OriginDBMap::iterator it2 = range.first; it2 != range.second; ++it2) {
- if (it2->second == database) {
- origin_dbs_.erase(it2);
- break;
- }
- }
-}
-
-void IndexedDBFactory::ReleaseDatabase(
- const IndexedDBDatabase::Identifier& identifier,
- bool forcedClose) {
-
- DCHECK(!database_map_.find(identifier)->second->backing_store());
-
- RemoveDatabaseFromMaps(identifier);
-
- // No grace period on a forced-close, as the initiator is
- // assuming the backing store will be released once all
- // connections are closed.
- ReleaseBackingStore(identifier.first, forcedClose);
-}
-
-void IndexedDBFactory::ReleaseBackingStore(const GURL& origin_url,
- bool immediate) {
- if (immediate) {
- IndexedDBBackingStoreMap::iterator it =
- backing_stores_with_active_blobs_.find(origin_url);
- if (it != backing_stores_with_active_blobs_.end()) {
- it->second->active_blob_registry()->ForceShutdown();
- backing_stores_with_active_blobs_.erase(it);
- }
- }
-
- // Only close if this is the last reference.
- if (!HasLastBackingStoreReference(origin_url))
- return;
-
- // If this factory does hold the last reference to the backing store, it can
- // be closed - but unless requested to close it immediately, keep it around
- // for a short period so that a re-open is fast.
- if (immediate) {
- CloseBackingStore(origin_url);
- return;
- }
-
- // Start a timer to close the backing store, unless something else opens it
- // in the mean time.
- DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning());
- backing_store_map_[origin_url]->close_timer()->Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
- base::Bind(&IndexedDBFactory::MaybeCloseBackingStore, this, origin_url));
-}
-
-void IndexedDBFactory::MaybeCloseBackingStore(const GURL& origin_url) {
- // Another reference may have opened since the maybe-close was posted, so it
- // is necessary to check again.
- if (HasLastBackingStoreReference(origin_url))
- CloseBackingStore(origin_url);
-}
-
-void IndexedDBFactory::CloseBackingStore(const GURL& origin_url) {
- IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
- DCHECK(it != backing_store_map_.end());
- // Stop the timer (if it's running) - this may happen if the timer was started
- // and then a forced close occurs.
- it->second->close_timer()->Stop();
- backing_store_map_.erase(it);
-}
-
-bool IndexedDBFactory::HasLastBackingStoreReference(const GURL& origin_url)
- const {
- IndexedDBBackingStore* ptr;
- {
- // Scope so that the implicit scoped_refptr<> is freed.
- IndexedDBBackingStoreMap::const_iterator it =
- backing_store_map_.find(origin_url);
- DCHECK(it != backing_store_map_.end());
- ptr = it->second.get();
- }
- return ptr->HasOneRef();
-}
-
-void IndexedDBFactory::ForceClose(const GURL& origin_url) {
- std::pair<OriginDBMapIterator, OriginDBMapIterator> range =
- GetOpenDatabasesForOrigin(origin_url);
-
- while (range.first != range.second) {
- IndexedDBDatabase* db = range.first->second;
- ++range.first;
- db->ForceClose();
- }
-
- if (backing_store_map_.find(origin_url) != backing_store_map_.end())
- ReleaseBackingStore(origin_url, true /* immediate */);
-}
-
-void IndexedDBFactory::ContextDestroyed() {
- // Timers on backing stores hold a reference to this factory. When the
- // context (which nominally owns this factory) is destroyed during thread
- // termination the timers must be stopped so that this factory and the
- // stores can be disposed of.
- for (IndexedDBBackingStoreMap::iterator it = backing_store_map_.begin();
- it != backing_store_map_.end();
- ++it)
- it->second->close_timer()->Stop();
- backing_store_map_.clear();
- backing_stores_with_active_blobs_.clear();
- context_ = NULL;
-}
-
-void IndexedDBFactory::ReportOutstandingBlobs(const GURL& origin_url,
- bool blobs_outstanding) {
- if (!context_)
- return;
- if (blobs_outstanding) {
- DCHECK(!backing_stores_with_active_blobs_.count(origin_url));
- IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
- if (it != backing_store_map_.end())
- backing_stores_with_active_blobs_.insert(*it);
- else
- DCHECK(false);
- } else {
- IndexedDBBackingStoreMap::iterator it =
- backing_stores_with_active_blobs_.find(origin_url);
- if (it != backing_stores_with_active_blobs_.end()) {
- backing_stores_with_active_blobs_.erase(it);
- ReleaseBackingStore(origin_url, false /* immediate */);
- }
- }
-}
-
-void IndexedDBFactory::GetDatabaseNames(
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context) {
- IDB_TRACE("IndexedDBFactory::GetDatabaseNames");
- // TODO(dgrogan): Plumb data_loss back to script eventually?
- blink::WebIDBDataLoss data_loss;
- std::string data_loss_message;
- bool disk_full;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_url,
- data_directory,
- request_context,
- &data_loss,
- &data_loss_message,
- &disk_full);
- if (!backing_store) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- "Internal error opening backing store for "
- "indexedDB.webkitGetDatabaseNames."));
- return;
- }
-
- leveldb::Status s;
- std::vector<base::string16> names = backing_store->GetDatabaseNames(&s);
- if (!s.ok()) {
- // TODO(cmumford): Handle this error
- DLOG(ERROR) << "Internal error getting database names";
- }
- callbacks->OnSuccess(names);
- backing_store = NULL;
- ReleaseBackingStore(origin_url, false /* immediate */);
-}
-
-void IndexedDBFactory::DeleteDatabase(
- const base::string16& name,
- net::URLRequestContext* request_context,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const GURL& origin_url,
- const base::FilePath& data_directory) {
- IDB_TRACE("IndexedDBFactory::DeleteDatabase");
- IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
- IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
- if (it != database_map_.end()) {
- // If there are any connections to the database, directly delete the
- // database.
- it->second->DeleteDatabase(callbacks);
- return;
- }
-
- // TODO(dgrogan): Plumb data_loss back to script eventually?
- blink::WebIDBDataLoss data_loss;
- std::string data_loss_message;
- bool disk_full = false;
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_url,
- data_directory,
- request_context,
- &data_loss,
- &data_loss_message,
- &disk_full);
- if (!backing_store) {
- callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error opening backing store "
- "for indexedDB.deleteDatabase.")));
- return;
- }
-
- leveldb::Status s;
- scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create(
- name, backing_store, this, unique_identifier, &s);
- if (!database) {
- IndexedDBDatabaseError error(
- blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error creating database backend for "
- "indexedDB.deleteDatabase."));
- callbacks->OnError(error);
- if (leveldb_env::IsCorruption(s))
- HandleBackingStoreCorruption(origin_url, error);
- return;
- }
-
- database_map_[unique_identifier] = database;
- origin_dbs_.insert(std::make_pair(origin_url, database));
- database->DeleteDatabase(callbacks);
- RemoveDatabaseFromMaps(unique_identifier);
- database = NULL;
- backing_store = NULL;
- ReleaseBackingStore(origin_url, false /* immediate */);
-}
-
-void IndexedDBFactory::DatabaseDeleted(
- const IndexedDBDatabase::Identifier& identifier) {
- // NULL after ContextDestroyed() called, and in some unit tests.
- if (!context_)
- return;
- context_->DatabaseDeleted(identifier.first);
-}
-
-void IndexedDBFactory::HandleBackingStoreFailure(const GURL& origin_url) {
- // NULL after ContextDestroyed() called, and in some unit tests.
- if (!context_)
- return;
- context_->ForceClose(origin_url,
- IndexedDBContextImpl::FORCE_CLOSE_BACKING_STORE_FAILURE);
-}
-
-void IndexedDBFactory::HandleBackingStoreCorruption(
- const GURL& origin_url,
- const IndexedDBDatabaseError& error) {
- // Make a copy of origin_url as this is likely a reference to a member of a
- // backing store which this function will be deleting.
- GURL saved_origin_url(origin_url);
- DCHECK(context_);
- base::FilePath path_base = context_->data_path();
- IndexedDBBackingStore::RecordCorruptionInfo(
- path_base, saved_origin_url, base::UTF16ToUTF8(error.message()));
- HandleBackingStoreFailure(saved_origin_url);
- // Note: DestroyBackingStore only deletes LevelDB files, leaving all others,
- // so our corruption info file will remain.
- leveldb::Status s =
- IndexedDBBackingStore::DestroyBackingStore(path_base, saved_origin_url);
- if (!s.ok())
- DLOG(ERROR) << "Unable to delete backing store: " << s.ToString();
-}
-
-bool IndexedDBFactory::IsDatabaseOpen(const GURL& origin_url,
- const base::string16& name) const {
- return !!database_map_.count(IndexedDBDatabase::Identifier(origin_url, name));
-}
-
-bool IndexedDBFactory::IsBackingStoreOpen(const GURL& origin_url) const {
- return backing_store_map_.find(origin_url) != backing_store_map_.end();
-}
-
-bool IndexedDBFactory::IsBackingStorePendingClose(const GURL& origin_url)
- const {
- IndexedDBBackingStoreMap::const_iterator it =
- backing_store_map_.find(origin_url);
- if (it == backing_store_map_.end())
- return false;
- return it->second->close_timer()->IsRunning();
-}
-
-scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStoreHelper(
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context,
- blink::WebIDBDataLoss* data_loss,
- std::string* data_loss_message,
- bool* disk_full,
- bool first_time) {
- return IndexedDBBackingStore::Open(this,
- origin_url,
- data_directory,
- request_context,
- data_loss,
- data_loss_message,
- disk_full,
- context_->TaskRunner(),
- first_time);
-}
-
-scoped_refptr<IndexedDBBackingStore> IndexedDBFactory::OpenBackingStore(
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context,
- blink::WebIDBDataLoss* data_loss,
- std::string* data_loss_message,
- bool* disk_full) {
- const bool open_in_memory = data_directory.empty();
-
- IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url);
- if (it2 != backing_store_map_.end()) {
- it2->second->close_timer()->Stop();
- return it2->second;
- }
-
- scoped_refptr<IndexedDBBackingStore> backing_store;
- bool first_time = false;
- if (open_in_memory) {
- backing_store =
- IndexedDBBackingStore::OpenInMemory(origin_url, context_->TaskRunner());
- } else {
- first_time = !backends_opened_since_boot_.count(origin_url);
-
- backing_store = OpenBackingStoreHelper(origin_url,
- data_directory,
- request_context,
- data_loss,
- data_loss_message,
- disk_full,
- first_time);
- }
-
- if (backing_store.get()) {
- if (first_time)
- backends_opened_since_boot_.insert(origin_url);
- backing_store_map_[origin_url] = backing_store;
- // If an in-memory database, bind lifetime to this factory instance.
- if (open_in_memory)
- session_only_backing_stores_.insert(backing_store);
-
- // All backing stores associated with this factory should be of the same
- // type.
- DCHECK_NE(session_only_backing_stores_.empty(), open_in_memory);
-
- return backing_store;
- }
-
- return 0;
-}
-
-void IndexedDBFactory::Open(const base::string16& name,
- const IndexedDBPendingConnection& connection,
- net::URLRequestContext* request_context,
- const GURL& origin_url,
- const base::FilePath& data_directory) {
- IDB_TRACE("IndexedDBFactory::Open");
- scoped_refptr<IndexedDBDatabase> database;
- IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
- IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
- blink::WebIDBDataLoss data_loss =
- blink::WebIDBDataLossNone;
- std::string data_loss_message;
- bool disk_full = false;
- bool was_open = (it != database_map_.end());
- if (!was_open) {
- scoped_refptr<IndexedDBBackingStore> backing_store =
- OpenBackingStore(origin_url,
- data_directory,
- request_context,
- &data_loss,
- &data_loss_message,
- &disk_full);
- if (!backing_store) {
- if (disk_full) {
- connection.callbacks->OnError(
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
- ASCIIToUTF16(
- "Encountered full disk while opening "
- "backing store for indexedDB.open.")));
- return;
- }
- connection.callbacks->OnError(IndexedDBDatabaseError(
- blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error opening backing store for indexedDB.open.")));
- return;
- }
-
- leveldb::Status s;
- database = IndexedDBDatabase::Create(
- name, backing_store, this, unique_identifier, &s);
- if (!database) {
- DLOG(ERROR) << "Unable to create the database";
- IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
- ASCIIToUTF16(
- "Internal error creating "
- "database backend for "
- "indexedDB.open."));
- connection.callbacks->OnError(error);
- if (leveldb_env::IsCorruption(s)) {
- backing_store = NULL; // Closes the LevelDB so that it can be deleted
- HandleBackingStoreCorruption(origin_url, error);
- }
- return;
- }
- } else {
- database = it->second;
- }
-
- if (data_loss != blink::WebIDBDataLossNone)
- connection.callbacks->OnDataLoss(data_loss, data_loss_message);
-
- database->OpenConnection(connection);
-
- if (!was_open && database->ConnectionCount() > 0) {
- database_map_[unique_identifier] = database;
- origin_dbs_.insert(std::make_pair(origin_url, database));
- }
-}
-
-std::pair<IndexedDBFactory::OriginDBMapIterator,
- IndexedDBFactory::OriginDBMapIterator>
-IndexedDBFactory::GetOpenDatabasesForOrigin(const GURL& origin_url) const {
- return origin_dbs_.equal_range(origin_url);
-}
-
-size_t IndexedDBFactory::GetConnectionCount(const GURL& origin_url) const {
- size_t count(0);
-
- std::pair<OriginDBMapIterator, OriginDBMapIterator> range =
- GetOpenDatabasesForOrigin(origin_url);
- for (OriginDBMapIterator it = range.first; it != range.second; ++it)
- count += it->second->ConnectionCount();
-
- return count;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory.h b/chromium/content/browser/indexed_db/indexed_db_factory.h
index c2177de7e56..935ba56c550 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory.h
+++ b/chromium/content/browser/indexed_db/indexed_db_factory.h
@@ -27,7 +27,6 @@ class URLRequestContext;
namespace content {
class IndexedDBBackingStore;
-class IndexedDBContextImpl;
struct IndexedDBPendingConnection;
class CONTENT_EXPORT IndexedDBFactory
@@ -35,53 +34,54 @@ class CONTENT_EXPORT IndexedDBFactory
public:
typedef std::multimap<GURL, IndexedDBDatabase*> OriginDBMap;
typedef OriginDBMap::const_iterator OriginDBMapIterator;
+ typedef std::pair<OriginDBMapIterator, OriginDBMapIterator> OriginDBs;
+
+ virtual void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
+ bool forcedClose) = 0;
+
+ virtual void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context) = 0;
+ virtual void Open(const base::string16& name,
+ const IndexedDBPendingConnection& connection,
+ net::URLRequestContext* request_context,
+ const GURL& origin_url,
+ const base::FilePath& data_directory) = 0;
+
+ virtual void DeleteDatabase(const base::string16& name,
+ net::URLRequestContext* request_context,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory) = 0;
+
+ virtual void HandleBackingStoreFailure(const GURL& origin_url) = 0;
+ virtual void HandleBackingStoreCorruption(
+ const GURL& origin_url,
+ const IndexedDBDatabaseError& error) = 0;
- explicit IndexedDBFactory(IndexedDBContextImpl* context);
-
- void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
- bool forcedClose);
-
- void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
- const GURL& origin_url,
- const base::FilePath& data_directory,
- net::URLRequestContext* request_context);
- void Open(const base::string16& name,
- const IndexedDBPendingConnection& connection,
- net::URLRequestContext* request_context,
- const GURL& origin_url,
- const base::FilePath& data_directory);
-
- void DeleteDatabase(const base::string16& name,
- net::URLRequestContext* request_context,
- scoped_refptr<IndexedDBCallbacks> callbacks,
- const GURL& origin_url,
- const base::FilePath& data_directory);
-
- void HandleBackingStoreFailure(const GURL& origin_url);
- void HandleBackingStoreCorruption(const GURL& origin_url,
- const IndexedDBDatabaseError& error);
-
- std::pair<OriginDBMapIterator, OriginDBMapIterator> GetOpenDatabasesForOrigin(
- const GURL& origin_url) const;
+ virtual OriginDBs GetOpenDatabasesForOrigin(const GURL& origin_url) const = 0;
- void ForceClose(const GURL& origin_url);
+ virtual void ForceClose(const GURL& origin_url) = 0;
// Called by the IndexedDBContext destructor so the factory can do cleanup.
- void ContextDestroyed();
+ virtual void ContextDestroyed() = 0;
// Called by the IndexedDBActiveBlobRegistry.
virtual void ReportOutstandingBlobs(const GURL& origin_url,
- bool blobs_outstanding);
+ bool blobs_outstanding) = 0;
// Called by an IndexedDBDatabase when it is actually deleted.
- void DatabaseDeleted(const IndexedDBDatabase::Identifier& identifier);
+ virtual void DatabaseDeleted(
+ const IndexedDBDatabase::Identifier& identifier) = 0;
- size_t GetConnectionCount(const GURL& origin_url) const;
+ virtual size_t GetConnectionCount(const GURL& origin_url) const = 0;
protected:
friend class base::RefCountedThreadSafe<IndexedDBFactory>;
- virtual ~IndexedDBFactory();
+ IndexedDBFactory() {}
+ virtual ~IndexedDBFactory() {}
virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
const GURL& origin_url,
@@ -89,7 +89,8 @@ class CONTENT_EXPORT IndexedDBFactory
net::URLRequestContext* request_context,
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_reason,
- bool* disk_full);
+ bool* disk_full,
+ leveldb::Status* status) = 0;
virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
const GURL& origin_url,
@@ -98,54 +99,10 @@ class CONTENT_EXPORT IndexedDBFactory
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
bool* disk_full,
- bool first_time);
-
- void ReleaseBackingStore(const GURL& origin_url, bool immediate);
- void CloseBackingStore(const GURL& origin_url);
- IndexedDBContextImpl* context() const { return context_; }
+ bool first_time,
+ leveldb::Status* status) = 0;
private:
- FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
- BackingStoreReleasedOnForcedClose);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
- BackingStoreReleaseDelayedOnClose);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, DatabaseFailedOpen);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
- DeleteDatabaseClosesBackingStore);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
- ForceCloseReleasesBackingStore);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
- GetDatabaseNamesClosesBackingStore);
- FRIEND_TEST_ALL_PREFIXES(IndexedDBTest,
- ForceCloseOpenDatabasesOnCommitFailure);
-
- // Called internally after a database is closed, with some delay. If this
- // factory has the last reference, it will be released.
- void MaybeCloseBackingStore(const GURL& origin_url);
- bool HasLastBackingStoreReference(const GURL& origin_url) const;
-
- // Testing helpers, so unit tests don't need to grovel through internal state.
- bool IsDatabaseOpen(const GURL& origin_url,
- const base::string16& name) const;
- bool IsBackingStoreOpen(const GURL& origin_url) const;
- bool IsBackingStorePendingClose(const GURL& origin_url) const;
- void RemoveDatabaseFromMaps(const IndexedDBDatabase::Identifier& identifier);
-
- IndexedDBContextImpl* context_;
-
- typedef std::map<IndexedDBDatabase::Identifier,
- IndexedDBDatabase*> IndexedDBDatabaseMap;
- IndexedDBDatabaseMap database_map_;
- OriginDBMap origin_dbs_;
-
- typedef std::map<GURL, scoped_refptr<IndexedDBBackingStore> >
- IndexedDBBackingStoreMap;
- IndexedDBBackingStoreMap backing_store_map_;
-
- std::set<scoped_refptr<IndexedDBBackingStore> > session_only_backing_stores_;
- IndexedDBBackingStoreMap backing_stores_with_active_blobs_;
- std::set<GURL> backends_opened_since_boot_;
-
DISALLOW_COPY_AND_ASSIGN(IndexedDBFactory);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
new file mode 100644
index 00000000000..9a62b78fb4c
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -0,0 +1,503 @@
+// Copyright (c) 2013 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 "content/browser/indexed_db/indexed_db_factory_impl.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "content/browser/indexed_db/indexed_db_backing_store.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_database_error.h"
+#include "content/browser/indexed_db/indexed_db_tracing.h"
+#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
+#include "storage/common/database/database_identifier.h"
+#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
+#include "third_party/leveldatabase/env_chromium.h"
+
+using base::ASCIIToUTF16;
+
+namespace content {
+
+const int64 kBackingStoreGracePeriodMs = 2000;
+
+IndexedDBFactoryImpl::IndexedDBFactoryImpl(IndexedDBContextImpl* context)
+ : context_(context) {
+}
+
+IndexedDBFactoryImpl::~IndexedDBFactoryImpl() {
+}
+
+void IndexedDBFactoryImpl::RemoveDatabaseFromMaps(
+ const IndexedDBDatabase::Identifier& identifier) {
+ IndexedDBDatabaseMap::iterator it = database_map_.find(identifier);
+ DCHECK(it != database_map_.end());
+ IndexedDBDatabase* database = it->second;
+ database_map_.erase(it);
+
+ std::pair<OriginDBMap::iterator, OriginDBMap::iterator> range =
+ origin_dbs_.equal_range(database->identifier().first);
+ DCHECK(range.first != range.second);
+ for (OriginDBMap::iterator it2 = range.first; it2 != range.second; ++it2) {
+ if (it2->second == database) {
+ origin_dbs_.erase(it2);
+ break;
+ }
+ }
+}
+
+void IndexedDBFactoryImpl::ReleaseDatabase(
+ const IndexedDBDatabase::Identifier& identifier,
+ bool forcedClose) {
+ DCHECK(!database_map_.find(identifier)->second->backing_store());
+
+ RemoveDatabaseFromMaps(identifier);
+
+ // No grace period on a forced-close, as the initiator is
+ // assuming the backing store will be released once all
+ // connections are closed.
+ ReleaseBackingStore(identifier.first, forcedClose);
+}
+
+void IndexedDBFactoryImpl::ReleaseBackingStore(const GURL& origin_url,
+ bool immediate) {
+ if (immediate) {
+ IndexedDBBackingStoreMap::iterator it =
+ backing_stores_with_active_blobs_.find(origin_url);
+ if (it != backing_stores_with_active_blobs_.end()) {
+ it->second->active_blob_registry()->ForceShutdown();
+ backing_stores_with_active_blobs_.erase(it);
+ }
+ }
+
+ // Only close if this is the last reference.
+ if (!HasLastBackingStoreReference(origin_url))
+ return;
+
+ // If this factory does hold the last reference to the backing store, it can
+ // be closed - but unless requested to close it immediately, keep it around
+ // for a short period so that a re-open is fast.
+ if (immediate) {
+ CloseBackingStore(origin_url);
+ return;
+ }
+
+ // Start a timer to close the backing store, unless something else opens it
+ // in the mean time.
+ DCHECK(!backing_store_map_[origin_url]->close_timer()->IsRunning());
+ backing_store_map_[origin_url]->close_timer()->Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kBackingStoreGracePeriodMs),
+ base::Bind(
+ &IndexedDBFactoryImpl::MaybeCloseBackingStore, this, origin_url));
+}
+
+void IndexedDBFactoryImpl::MaybeCloseBackingStore(const GURL& origin_url) {
+ // Another reference may have opened since the maybe-close was posted, so it
+ // is necessary to check again.
+ if (HasLastBackingStoreReference(origin_url))
+ CloseBackingStore(origin_url);
+}
+
+void IndexedDBFactoryImpl::CloseBackingStore(const GURL& origin_url) {
+ IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
+ DCHECK(it != backing_store_map_.end());
+ // Stop the timer (if it's running) - this may happen if the timer was started
+ // and then a forced close occurs.
+ it->second->close_timer()->Stop();
+ backing_store_map_.erase(it);
+}
+
+bool IndexedDBFactoryImpl::HasLastBackingStoreReference(
+ const GURL& origin_url) const {
+ IndexedDBBackingStore* ptr;
+ {
+ // Scope so that the implicit scoped_refptr<> is freed.
+ IndexedDBBackingStoreMap::const_iterator it =
+ backing_store_map_.find(origin_url);
+ DCHECK(it != backing_store_map_.end());
+ ptr = it->second.get();
+ }
+ return ptr->HasOneRef();
+}
+
+void IndexedDBFactoryImpl::ForceClose(const GURL& origin_url) {
+ OriginDBs range = GetOpenDatabasesForOrigin(origin_url);
+
+ while (range.first != range.second) {
+ IndexedDBDatabase* db = range.first->second;
+ ++range.first;
+ db->ForceClose();
+ }
+
+ if (backing_store_map_.find(origin_url) != backing_store_map_.end())
+ ReleaseBackingStore(origin_url, true /* immediate */);
+}
+
+void IndexedDBFactoryImpl::ContextDestroyed() {
+ // Timers on backing stores hold a reference to this factory. When the
+ // context (which nominally owns this factory) is destroyed during thread
+ // termination the timers must be stopped so that this factory and the
+ // stores can be disposed of.
+ for (const auto& it : backing_store_map_)
+ it.second->close_timer()->Stop();
+ backing_store_map_.clear();
+ backing_stores_with_active_blobs_.clear();
+ context_ = NULL;
+}
+
+void IndexedDBFactoryImpl::ReportOutstandingBlobs(const GURL& origin_url,
+ bool blobs_outstanding) {
+ if (!context_)
+ return;
+ if (blobs_outstanding) {
+ DCHECK(!backing_stores_with_active_blobs_.count(origin_url));
+ IndexedDBBackingStoreMap::iterator it = backing_store_map_.find(origin_url);
+ if (it != backing_store_map_.end())
+ backing_stores_with_active_blobs_.insert(*it);
+ else
+ DCHECK(false);
+ } else {
+ IndexedDBBackingStoreMap::iterator it =
+ backing_stores_with_active_blobs_.find(origin_url);
+ if (it != backing_stores_with_active_blobs_.end()) {
+ backing_stores_with_active_blobs_.erase(it);
+ ReleaseBackingStore(origin_url, false /* immediate */);
+ }
+ }
+}
+
+void IndexedDBFactoryImpl::GetDatabaseNames(
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context) {
+ IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames");
+ // TODO(dgrogan): Plumb data_loss back to script eventually?
+ blink::WebIDBDataLoss data_loss;
+ std::string data_loss_message;
+ bool disk_full;
+ leveldb::Status s;
+ // TODO(cmumford): Handle this error
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin_url,
+ data_directory,
+ request_context,
+ &data_loss,
+ &data_loss_message,
+ &disk_full,
+ &s);
+ if (!backing_store.get()) {
+ callbacks->OnError(
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error opening backing store for "
+ "indexedDB.webkitGetDatabaseNames."));
+ return;
+ }
+
+ std::vector<base::string16> names = backing_store->GetDatabaseNames(&s);
+ if (!s.ok()) {
+ DLOG(ERROR) << "Internal error getting database names";
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ "Internal error opening backing store for "
+ "indexedDB.webkitGetDatabaseNames.");
+ callbacks->OnError(error);
+ backing_store = NULL;
+ if (s.IsCorruption())
+ HandleBackingStoreCorruption(origin_url, error);
+ return;
+ }
+ callbacks->OnSuccess(names);
+ backing_store = NULL;
+ ReleaseBackingStore(origin_url, false /* immediate */);
+}
+
+void IndexedDBFactoryImpl::DeleteDatabase(
+ const base::string16& name,
+ net::URLRequestContext* request_context,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory) {
+ IDB_TRACE("IndexedDBFactoryImpl::DeleteDatabase");
+ IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
+ IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
+ if (it != database_map_.end()) {
+ // If there are any connections to the database, directly delete the
+ // database.
+ it->second->DeleteDatabase(callbacks);
+ return;
+ }
+
+ // TODO(dgrogan): Plumb data_loss back to script eventually?
+ blink::WebIDBDataLoss data_loss;
+ std::string data_loss_message;
+ bool disk_full = false;
+ leveldb::Status s;
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin_url,
+ data_directory,
+ request_context,
+ &data_loss,
+ &data_loss_message,
+ &disk_full,
+ &s);
+ if (!backing_store.get()) {
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16(
+ "Internal error opening backing store "
+ "for indexedDB.deleteDatabase."));
+ callbacks->OnError(error);
+ if (s.IsCorruption()) {
+ HandleBackingStoreCorruption(origin_url, error);
+ }
+ return;
+ }
+
+ scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create(
+ name, backing_store.get(), this, unique_identifier, &s);
+ if (!database.get()) {
+ IndexedDBDatabaseError error(
+ blink::WebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16(
+ "Internal error creating database backend for "
+ "indexedDB.deleteDatabase."));
+ callbacks->OnError(error);
+ if (leveldb_env::IsCorruption(s)) {
+ backing_store = NULL;
+ HandleBackingStoreCorruption(origin_url, error);
+ }
+ return;
+ }
+
+ database_map_[unique_identifier] = database.get();
+ origin_dbs_.insert(std::make_pair(origin_url, database.get()));
+ database->DeleteDatabase(callbacks);
+ RemoveDatabaseFromMaps(unique_identifier);
+ database = NULL;
+ backing_store = NULL;
+ ReleaseBackingStore(origin_url, false /* immediate */);
+}
+
+void IndexedDBFactoryImpl::DatabaseDeleted(
+ const IndexedDBDatabase::Identifier& identifier) {
+ // NULL after ContextDestroyed() called, and in some unit tests.
+ if (!context_)
+ return;
+ context_->DatabaseDeleted(identifier.first);
+}
+
+void IndexedDBFactoryImpl::HandleBackingStoreFailure(const GURL& origin_url) {
+ // NULL after ContextDestroyed() called, and in some unit tests.
+ if (!context_)
+ return;
+ context_->ForceClose(origin_url,
+ IndexedDBContextImpl::FORCE_CLOSE_BACKING_STORE_FAILURE);
+}
+
+void IndexedDBFactoryImpl::HandleBackingStoreCorruption(
+ const GURL& origin_url,
+ const IndexedDBDatabaseError& error) {
+ // Make a copy of origin_url as this is likely a reference to a member of a
+ // backing store which this function will be deleting.
+ GURL saved_origin_url(origin_url);
+ DCHECK(context_);
+ base::FilePath path_base = context_->data_path();
+ IndexedDBBackingStore::RecordCorruptionInfo(
+ path_base, saved_origin_url, base::UTF16ToUTF8(error.message()));
+ HandleBackingStoreFailure(saved_origin_url);
+ // Note: DestroyBackingStore only deletes LevelDB files, leaving all others,
+ // so our corruption info file will remain.
+ leveldb::Status s =
+ IndexedDBBackingStore::DestroyBackingStore(path_base, saved_origin_url);
+ if (!s.ok())
+ DLOG(ERROR) << "Unable to delete backing store: " << s.ToString();
+}
+
+bool IndexedDBFactoryImpl::IsDatabaseOpen(const GURL& origin_url,
+ const base::string16& name) const {
+ return !!database_map_.count(IndexedDBDatabase::Identifier(origin_url, name));
+}
+
+bool IndexedDBFactoryImpl::IsBackingStoreOpen(const GURL& origin_url) const {
+ return backing_store_map_.find(origin_url) != backing_store_map_.end();
+}
+
+bool IndexedDBFactoryImpl::IsBackingStorePendingClose(
+ const GURL& origin_url) const {
+ IndexedDBBackingStoreMap::const_iterator it =
+ backing_store_map_.find(origin_url);
+ if (it == backing_store_map_.end())
+ return false;
+ return it->second->close_timer()->IsRunning();
+}
+
+scoped_refptr<IndexedDBBackingStore>
+IndexedDBFactoryImpl::OpenBackingStoreHelper(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* disk_full,
+ bool first_time,
+ leveldb::Status* status) {
+ return IndexedDBBackingStore::Open(this,
+ origin_url,
+ data_directory,
+ request_context,
+ data_loss,
+ data_loss_message,
+ disk_full,
+ context_->TaskRunner(),
+ first_time,
+ status);
+}
+
+scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* disk_full,
+ leveldb::Status* status) {
+ const bool open_in_memory = data_directory.empty();
+
+ IndexedDBBackingStoreMap::iterator it2 = backing_store_map_.find(origin_url);
+ if (it2 != backing_store_map_.end()) {
+ it2->second->close_timer()->Stop();
+ return it2->second;
+ }
+
+ scoped_refptr<IndexedDBBackingStore> backing_store;
+ bool first_time = false;
+ if (open_in_memory) {
+ backing_store = IndexedDBBackingStore::OpenInMemory(
+ origin_url, context_->TaskRunner(), status);
+ } else {
+ first_time = !backends_opened_since_boot_.count(origin_url);
+
+ backing_store = OpenBackingStoreHelper(origin_url,
+ data_directory,
+ request_context,
+ data_loss,
+ data_loss_message,
+ disk_full,
+ first_time,
+ status);
+ }
+
+ if (backing_store.get()) {
+ if (first_time)
+ backends_opened_since_boot_.insert(origin_url);
+ backing_store_map_[origin_url] = backing_store;
+ // If an in-memory database, bind lifetime to this factory instance.
+ if (open_in_memory)
+ session_only_backing_stores_.insert(backing_store);
+
+ // All backing stores associated with this factory should be of the same
+ // type.
+ DCHECK_NE(session_only_backing_stores_.empty(), open_in_memory);
+
+ return backing_store;
+ }
+
+ return 0;
+}
+
+void IndexedDBFactoryImpl::Open(const base::string16& name,
+ const IndexedDBPendingConnection& connection,
+ net::URLRequestContext* request_context,
+ const GURL& origin_url,
+ const base::FilePath& data_directory) {
+ IDB_TRACE("IndexedDBFactoryImpl::Open");
+ scoped_refptr<IndexedDBDatabase> database;
+ IndexedDBDatabase::Identifier unique_identifier(origin_url, name);
+ IndexedDBDatabaseMap::iterator it = database_map_.find(unique_identifier);
+ blink::WebIDBDataLoss data_loss =
+ blink::WebIDBDataLossNone;
+ std::string data_loss_message;
+ bool disk_full = false;
+ bool was_open = (it != database_map_.end());
+ if (!was_open) {
+ leveldb::Status s;
+ scoped_refptr<IndexedDBBackingStore> backing_store =
+ OpenBackingStore(origin_url,
+ data_directory,
+ request_context,
+ &data_loss,
+ &data_loss_message,
+ &disk_full,
+ &s);
+ if (!backing_store.get()) {
+ if (disk_full) {
+ connection.callbacks->OnError(
+ IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError,
+ ASCIIToUTF16(
+ "Encountered full disk while opening "
+ "backing store for indexedDB.open.")));
+ return;
+ }
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16(
+ "Internal error opening backing store"
+ " for indexedDB.open."));
+ connection.callbacks->OnError(error);
+ if (s.IsCorruption()) {
+ HandleBackingStoreCorruption(origin_url, error);
+ }
+ return;
+ }
+
+ database = IndexedDBDatabase::Create(
+ name, backing_store.get(), this, unique_identifier, &s);
+ if (!database.get()) {
+ DLOG(ERROR) << "Unable to create the database";
+ IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
+ ASCIIToUTF16(
+ "Internal error creating "
+ "database backend for "
+ "indexedDB.open."));
+ connection.callbacks->OnError(error);
+ if (leveldb_env::IsCorruption(s)) {
+ backing_store = NULL; // Closes the LevelDB so that it can be deleted
+ HandleBackingStoreCorruption(origin_url, error);
+ }
+ return;
+ }
+ } else {
+ database = it->second;
+ }
+
+ if (data_loss != blink::WebIDBDataLossNone)
+ connection.callbacks->OnDataLoss(data_loss, data_loss_message);
+
+ database->OpenConnection(connection);
+
+ if (!was_open && database->ConnectionCount() > 0) {
+ database_map_[unique_identifier] = database.get();
+ origin_dbs_.insert(std::make_pair(origin_url, database.get()));
+ }
+}
+
+std::pair<IndexedDBFactoryImpl::OriginDBMapIterator,
+ IndexedDBFactoryImpl::OriginDBMapIterator>
+IndexedDBFactoryImpl::GetOpenDatabasesForOrigin(const GURL& origin_url) const {
+ return origin_dbs_.equal_range(origin_url);
+}
+
+size_t IndexedDBFactoryImpl::GetConnectionCount(const GURL& origin_url) const {
+ size_t count(0);
+
+ OriginDBs range = GetOpenDatabasesForOrigin(origin_url);
+ for (OriginDBMapIterator it = range.first; it != range.second; ++it)
+ count += it->second->ConnectionCount();
+
+ return count;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.h b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
new file mode 100644
index 00000000000..da9d2a9a45b
--- /dev/null
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -0,0 +1,136 @@
+// Copyright (c) 2014 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 CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_
+#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "content/browser/indexed_db/indexed_db_factory.h"
+
+namespace content {
+
+class IndexedDBContextImpl;
+
+class CONTENT_EXPORT IndexedDBFactoryImpl : public IndexedDBFactory {
+ public:
+ explicit IndexedDBFactoryImpl(IndexedDBContextImpl* context);
+
+ // content::IndexedDBFactory overrides:
+ void ReleaseDatabase(const IndexedDBDatabase::Identifier& identifier,
+ bool forcedClose) override;
+
+ void GetDatabaseNames(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context) override;
+ void Open(const base::string16& name,
+ const IndexedDBPendingConnection& connection,
+ net::URLRequestContext* request_context,
+ const GURL& origin_url,
+ const base::FilePath& data_directory) override;
+
+ void DeleteDatabase(const base::string16& name,
+ net::URLRequestContext* request_context,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory) override;
+
+ void HandleBackingStoreFailure(const GURL& origin_url) override;
+ void HandleBackingStoreCorruption(
+ const GURL& origin_url,
+ const IndexedDBDatabaseError& error) override;
+
+ OriginDBs GetOpenDatabasesForOrigin(const GURL& origin_url) const override;
+
+ void ForceClose(const GURL& origin_url) override;
+
+ // Called by the IndexedDBContext destructor so the factory can do cleanup.
+ void ContextDestroyed() override;
+
+ // Called by the IndexedDBActiveBlobRegistry.
+ void ReportOutstandingBlobs(const GURL& origin_url,
+ bool blobs_outstanding) override;
+
+ // Called by an IndexedDBDatabase when it is actually deleted.
+ void DatabaseDeleted(
+ const IndexedDBDatabase::Identifier& identifier) override;
+
+ size_t GetConnectionCount(const GURL& origin_url) const override;
+
+ protected:
+ ~IndexedDBFactoryImpl() override;
+
+ scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_reason,
+ bool* disk_full,
+ leveldb::Status* s) override;
+
+ scoped_refptr<IndexedDBBackingStore> OpenBackingStoreHelper(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* disk_full,
+ bool first_time,
+ leveldb::Status* s) override;
+
+ void ReleaseBackingStore(const GURL& origin_url, bool immediate);
+ void CloseBackingStore(const GURL& origin_url);
+ IndexedDBContextImpl* context() const { return context_; }
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ BackingStoreReleasedOnForcedClose);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ BackingStoreReleaseDelayedOnClose);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest, DatabaseFailedOpen);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ DeleteDatabaseClosesBackingStore);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ ForceCloseReleasesBackingStore);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBFactoryTest,
+ GetDatabaseNamesClosesBackingStore);
+ FRIEND_TEST_ALL_PREFIXES(IndexedDBTest,
+ ForceCloseOpenDatabasesOnCommitFailure);
+
+ typedef std::map<IndexedDBDatabase::Identifier, IndexedDBDatabase*>
+ IndexedDBDatabaseMap;
+ typedef std::map<GURL, scoped_refptr<IndexedDBBackingStore> >
+ IndexedDBBackingStoreMap;
+
+ // Called internally after a database is closed, with some delay. If this
+ // factory has the last reference, it will be released.
+ void MaybeCloseBackingStore(const GURL& origin_url);
+ bool HasLastBackingStoreReference(const GURL& origin_url) const;
+
+ // Testing helpers, so unit tests don't need to grovel through internal state.
+ bool IsDatabaseOpen(const GURL& origin_url, const base::string16& name) const;
+ bool IsBackingStoreOpen(const GURL& origin_url) const;
+ bool IsBackingStorePendingClose(const GURL& origin_url) const;
+ void RemoveDatabaseFromMaps(const IndexedDBDatabase::Identifier& identifier);
+
+ IndexedDBContextImpl* context_;
+
+ IndexedDBDatabaseMap database_map_;
+ OriginDBMap origin_dbs_;
+ IndexedDBBackingStoreMap backing_store_map_;
+
+ std::set<scoped_refptr<IndexedDBBackingStore> > session_only_backing_stores_;
+ IndexedDBBackingStoreMap backing_stores_with_active_blobs_;
+ std::set<GURL> backends_opened_since_boot_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_FACTORY_IMPL_H_
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 975f9bcbcd3..70f8ae64ad5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -2,9 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/indexed_db/indexed_db_factory.h"
-
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
@@ -12,13 +10,14 @@
#include "base/test/test_simple_task_runner.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
+#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseException.h"
#include "third_party/WebKit/public/platform/WebIDBTypes.h"
#include "url/gurl.h"
-#include "webkit/common/database/database_identifier.h"
using base::ASCIIToUTF16;
@@ -26,10 +25,10 @@ namespace content {
namespace {
-class MockIDBFactory : public IndexedDBFactory {
+class MockIDBFactory : public IndexedDBFactoryImpl {
public:
explicit MockIDBFactory(IndexedDBContextImpl* context)
- : IndexedDBFactory(context) {}
+ : IndexedDBFactoryImpl(context) {}
scoped_refptr<IndexedDBBackingStore> TestOpenBackingStore(
const GURL& origin,
const base::FilePath& data_directory) {
@@ -37,13 +36,15 @@ class MockIDBFactory : public IndexedDBFactory {
blink::WebIDBDataLossNone;
std::string data_loss_message;
bool disk_full;
+ leveldb::Status s;
scoped_refptr<IndexedDBBackingStore> backing_store =
OpenBackingStore(origin,
data_directory,
NULL /* request_context */,
&data_loss,
&data_loss_message,
- &disk_full);
+ &disk_full,
+ &s);
EXPECT_EQ(blink::WebIDBDataLossNone, data_loss);
return backing_store;
}
@@ -58,7 +59,7 @@ class MockIDBFactory : public IndexedDBFactory {
}
private:
- virtual ~MockIDBFactory() {}
+ ~MockIDBFactory() override {}
DISALLOW_COPY_AND_ASSIGN(MockIDBFactory);
};
@@ -108,8 +109,8 @@ TEST_F(IndexedDBFactoryTest, BackingStoreLifetime) {
scoped_refptr<IndexedDBBackingStore> disk_store3 =
factory()->TestOpenBackingStore(origin2, temp_directory.path());
- factory()->TestCloseBackingStore(disk_store1);
- factory()->TestCloseBackingStore(disk_store3);
+ factory()->TestCloseBackingStore(disk_store1.get());
+ factory()->TestCloseBackingStore(disk_store3.get());
EXPECT_FALSE(disk_store1->HasOneRef());
EXPECT_FALSE(disk_store2->HasOneRef());
@@ -161,8 +162,8 @@ TEST_F(IndexedDBFactoryTest, MemoryBackingStoreLifetime) {
scoped_refptr<IndexedDBBackingStore> mem_store3 =
factory()->TestOpenBackingStore(origin2, base::FilePath());
- factory()->TestCloseBackingStore(mem_store1);
- factory()->TestCloseBackingStore(mem_store3);
+ factory()->TestCloseBackingStore(mem_store1.get());
+ factory()->TestCloseBackingStore(mem_store3.get());
EXPECT_FALSE(mem_store1->HasOneRef());
EXPECT_FALSE(mem_store2->HasOneRef());
@@ -189,29 +190,31 @@ TEST_F(IndexedDBFactoryTest, RejectLongOrigins) {
GURL too_long_origin("http://" + origin + ":81/");
scoped_refptr<IndexedDBBackingStore> diskStore1 =
factory()->TestOpenBackingStore(too_long_origin, base_path);
- EXPECT_FALSE(diskStore1);
+ EXPECT_FALSE(diskStore1.get());
GURL ok_origin("http://someorigin.com:82/");
scoped_refptr<IndexedDBBackingStore> diskStore2 =
factory()->TestOpenBackingStore(ok_origin, base_path);
- EXPECT_TRUE(diskStore2);
+ EXPECT_TRUE(diskStore2.get());
}
-class DiskFullFactory : public IndexedDBFactory {
+class DiskFullFactory : public IndexedDBFactoryImpl {
public:
explicit DiskFullFactory(IndexedDBContextImpl* context)
- : IndexedDBFactory(context) {}
+ : IndexedDBFactoryImpl(context) {}
private:
- virtual ~DiskFullFactory() {}
- virtual scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
+ ~DiskFullFactory() override {}
+ scoped_refptr<IndexedDBBackingStore> OpenBackingStore(
const GURL& origin_url,
const base::FilePath& data_directory,
net::URLRequestContext* request_context,
blink::WebIDBDataLoss* data_loss,
std::string* data_loss_message,
- bool* disk_full) OVERRIDE {
+ bool* disk_full,
+ leveldb::Status* s) override {
*disk_full = true;
+ *s = leveldb::Status::IOError("Disk is full");
return scoped_refptr<IndexedDBBackingStore>();
}
@@ -222,14 +225,14 @@ class LookingForQuotaErrorMockCallbacks : public IndexedDBCallbacks {
public:
LookingForQuotaErrorMockCallbacks()
: IndexedDBCallbacks(NULL, 0, 0), error_called_(false) {}
- virtual void OnError(const IndexedDBDatabaseError& error) OVERRIDE {
+ void OnError(const IndexedDBDatabaseError& error) override {
error_called_ = true;
EXPECT_EQ(blink::WebIDBDatabaseExceptionQuotaError, error.code());
}
bool error_called() const { return error_called_; }
private:
- virtual ~LookingForQuotaErrorMockCallbacks() {}
+ ~LookingForQuotaErrorMockCallbacks() override {}
bool error_called_;
DISALLOW_COPY_AND_ASSIGN(LookingForQuotaErrorMockCallbacks);
@@ -431,21 +434,21 @@ class UpgradeNeededCallbacks : public MockIndexedDBCallbacks {
public:
UpgradeNeededCallbacks() {}
- virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) OVERRIDE {
+ void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
+ const IndexedDBDatabaseMetadata& metadata) override {
EXPECT_TRUE(connection_.get());
EXPECT_FALSE(connection.get());
}
- virtual void OnUpgradeNeeded(
+ void OnUpgradeNeeded(
int64 old_version,
scoped_ptr<IndexedDBConnection> connection,
- const content::IndexedDBDatabaseMetadata& metadata) OVERRIDE {
+ const content::IndexedDBDatabaseMetadata& metadata) override {
connection_ = connection.Pass();
}
protected:
- virtual ~UpgradeNeededCallbacks() {}
+ ~UpgradeNeededCallbacks() override {}
private:
DISALLOW_COPY_AND_ASSIGN(UpgradeNeededCallbacks);
@@ -455,13 +458,13 @@ class ErrorCallbacks : public MockIndexedDBCallbacks {
public:
ErrorCallbacks() : MockIndexedDBCallbacks(false), saw_error_(false) {}
- virtual void OnError(const IndexedDBDatabaseError& error) OVERRIDE {
+ void OnError(const IndexedDBDatabaseError& error) override {
saw_error_= true;
}
bool saw_error() const { return saw_error_; }
private:
- virtual ~ErrorCallbacks() {}
+ ~ErrorCallbacks() override {}
bool saw_error_;
DISALLOW_COPY_AND_ASSIGN(ErrorCallbacks);
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index 461c0808c60..49040ae9478 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -20,7 +20,7 @@ IndexedDBFakeBackingStore::IndexedDBFakeBackingStore()
}
IndexedDBFakeBackingStore::IndexedDBFakeBackingStore(
IndexedDBFactory* factory,
- base::TaskRunner* task_runner)
+ base::SequencedTaskRunner* task_runner)
: IndexedDBBackingStore(factory,
GURL("http://localhost:81"),
base::FilePath(),
@@ -82,8 +82,8 @@ leveldb::Status IndexedDBFakeBackingStore::PutRecord(
int64 database_id,
int64 object_store_id,
const IndexedDBKey& key,
- IndexedDBValue& value,
- ScopedVector<webkit_blob::BlobDataHandle>* handles,
+ IndexedDBValue* value,
+ ScopedVector<storage::BlobDataHandle>* handles,
RecordIdentifier* record) {
return leveldb::Status::OK();
}
@@ -163,7 +163,7 @@ IndexedDBFakeBackingStore::OpenObjectStoreKeyCursor(
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status* s) {
return scoped_ptr<IndexedDBBackingStore::Cursor>();
}
@@ -173,7 +173,7 @@ IndexedDBFakeBackingStore::OpenObjectStoreCursor(
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status* s) {
return scoped_ptr<IndexedDBBackingStore::Cursor>();
}
@@ -184,7 +184,7 @@ IndexedDBFakeBackingStore::OpenIndexKeyCursor(
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status* s) {
return scoped_ptr<IndexedDBBackingStore::Cursor>();
}
@@ -195,7 +195,7 @@ IndexedDBFakeBackingStore::OpenIndexCursor(
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
+ blink::WebIDBCursorDirection,
leveldb::Status* s) {
return scoped_ptr<IndexedDBBackingStore::Cursor>();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
index fef28af3bd9..9a4fd0927a6 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -10,7 +10,7 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
namespace base {
-class TaskRunner;
+class SequencedTaskRunner;
}
namespace content {
@@ -21,126 +21,118 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
public:
IndexedDBFakeBackingStore();
IndexedDBFakeBackingStore(IndexedDBFactory* factory,
- base::TaskRunner* task_runner);
- virtual std::vector<base::string16> GetDatabaseNames(leveldb::Status* s)
- OVERRIDE;
- virtual leveldb::Status GetIDBDatabaseMetaData(const base::string16& name,
- IndexedDBDatabaseMetadata*,
- bool* found) OVERRIDE;
- virtual leveldb::Status CreateIDBDatabaseMetaData(
- const base::string16& name,
- const base::string16& version,
- int64 int_version,
- int64* row_id) OVERRIDE;
- virtual bool UpdateIDBDatabaseIntVersion(Transaction*,
- int64 row_id,
- int64 version) OVERRIDE;
- virtual leveldb::Status DeleteDatabase(const base::string16& name) OVERRIDE;
-
- virtual leveldb::Status CreateObjectStore(Transaction*,
- int64 database_id,
- int64 object_store_id,
- const base::string16& name,
- const IndexedDBKeyPath&,
- bool auto_increment) OVERRIDE;
-
- virtual leveldb::Status DeleteObjectStore(Transaction* transaction,
- int64 database_id,
- int64 object_store_id) OVERRIDE;
-
- virtual leveldb::Status PutRecord(
- IndexedDBBackingStore::Transaction* transaction,
- int64 database_id,
- int64 object_store_id,
- const IndexedDBKey& key,
- IndexedDBValue& value,
- ScopedVector<webkit_blob::BlobDataHandle>* handles,
- RecordIdentifier* record) OVERRIDE;
-
- virtual leveldb::Status ClearObjectStore(Transaction*,
- int64 database_id,
- int64 object_store_id) OVERRIDE;
- virtual leveldb::Status DeleteRecord(Transaction*,
- int64 database_id,
- int64 object_store_id,
- const RecordIdentifier&) OVERRIDE;
- virtual leveldb::Status GetKeyGeneratorCurrentNumber(Transaction*,
- int64 database_id,
- int64 object_store_id,
- int64* current_number)
- OVERRIDE;
- virtual leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
+ base::SequencedTaskRunner* task_runner);
+ std::vector<base::string16> GetDatabaseNames(leveldb::Status* s) override;
+ leveldb::Status GetIDBDatabaseMetaData(const base::string16& name,
+ IndexedDBDatabaseMetadata*,
+ bool* found) override;
+ leveldb::Status CreateIDBDatabaseMetaData(const base::string16& name,
+ const base::string16& version,
+ int64 int_version,
+ int64* row_id) override;
+ bool UpdateIDBDatabaseIntVersion(Transaction*,
+ int64 row_id,
+ int64 version) override;
+ leveldb::Status DeleteDatabase(const base::string16& name) override;
+
+ leveldb::Status CreateObjectStore(Transaction*,
+ int64 database_id,
+ int64 object_store_id,
+ const base::string16& name,
+ const IndexedDBKeyPath&,
+ bool auto_increment) override;
+
+ leveldb::Status DeleteObjectStore(Transaction* transaction,
+ int64 database_id,
+ int64 object_store_id) override;
+
+ leveldb::Status PutRecord(IndexedDBBackingStore::Transaction* transaction,
+ int64 database_id,
+ int64 object_store_id,
+ const IndexedDBKey& key,
+ IndexedDBValue* value,
+ ScopedVector<storage::BlobDataHandle>* handles,
+ RecordIdentifier* record) override;
+
+ leveldb::Status ClearObjectStore(Transaction*,
+ int64 database_id,
+ int64 object_store_id) override;
+ leveldb::Status DeleteRecord(Transaction*,
+ int64 database_id,
+ int64 object_store_id,
+ const RecordIdentifier&) override;
+ leveldb::Status GetKeyGeneratorCurrentNumber(Transaction*,
+ int64 database_id,
+ int64 object_store_id,
+ int64* current_number) override;
+ leveldb::Status MaybeUpdateKeyGeneratorCurrentNumber(
Transaction*,
int64 database_id,
int64 object_store_id,
int64 new_number,
- bool check_current) OVERRIDE;
- virtual leveldb::Status KeyExistsInObjectStore(
+ bool check_current) override;
+ leveldb::Status KeyExistsInObjectStore(
Transaction*,
int64 database_id,
int64 object_store_id,
const IndexedDBKey&,
RecordIdentifier* found_record_identifier,
- bool* found) OVERRIDE;
-
- virtual leveldb::Status CreateIndex(Transaction*,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- const base::string16& name,
- const IndexedDBKeyPath&,
- bool is_unique,
- bool is_multi_entry) OVERRIDE;
- virtual leveldb::Status DeleteIndex(Transaction*,
- int64 database_id,
- int64 object_store_id,
- int64 index_id) OVERRIDE;
- virtual leveldb::Status PutIndexDataForRecord(Transaction*,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- const IndexedDBKey&,
- const RecordIdentifier&)
- OVERRIDE;
- virtual void ReportBlobUnused(int64 database_id, int64 blob_key) OVERRIDE;
- virtual scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
+ bool* found) override;
+
+ leveldb::Status CreateIndex(Transaction*,
+ int64 database_id,
+ int64 object_store_id,
+ int64 index_id,
+ const base::string16& name,
+ const IndexedDBKeyPath&,
+ bool is_unique,
+ bool is_multi_entry) override;
+ leveldb::Status DeleteIndex(Transaction*,
+ int64 database_id,
+ int64 object_store_id,
+ int64 index_id) override;
+ leveldb::Status PutIndexDataForRecord(Transaction*,
+ int64 database_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKey&,
+ const RecordIdentifier&) override;
+ void ReportBlobUnused(int64 database_id, int64 blob_key) override;
+ scoped_ptr<Cursor> OpenObjectStoreKeyCursor(
Transaction* transaction,
int64 database_id,
int64 object_store_id,
const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
- leveldb::Status*) OVERRIDE;
- virtual scoped_ptr<Cursor> OpenObjectStoreCursor(
- Transaction* transaction,
- int64 database_id,
- int64 object_store_id,
- const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
- leveldb::Status*) OVERRIDE;
- virtual scoped_ptr<Cursor> OpenIndexKeyCursor(
- Transaction* transaction,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
- leveldb::Status*) OVERRIDE;
- virtual scoped_ptr<Cursor> OpenIndexCursor(Transaction* transaction,
- int64 database_id,
- int64 object_store_id,
- int64 index_id,
- const IndexedDBKeyRange& key_range,
- indexed_db::CursorDirection,
- leveldb::Status*) OVERRIDE;
+ blink::WebIDBCursorDirection,
+ leveldb::Status*) override;
+ scoped_ptr<Cursor> OpenObjectStoreCursor(Transaction* transaction,
+ int64 database_id,
+ int64 object_store_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection,
+ leveldb::Status*) override;
+ scoped_ptr<Cursor> OpenIndexKeyCursor(Transaction* transaction,
+ int64 database_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection,
+ leveldb::Status*) override;
+ scoped_ptr<Cursor> OpenIndexCursor(Transaction* transaction,
+ int64 database_id,
+ int64 object_store_id,
+ int64 index_id,
+ const IndexedDBKeyRange& key_range,
+ blink::WebIDBCursorDirection,
+ leveldb::Status*) override;
class FakeTransaction : public IndexedDBBackingStore::Transaction {
public:
explicit FakeTransaction(leveldb::Status phase_two_result);
- virtual void Begin() OVERRIDE;
- virtual leveldb::Status CommitPhaseOne(
- scoped_refptr<BlobWriteCallback>) OVERRIDE;
- virtual leveldb::Status CommitPhaseTwo() OVERRIDE;
- virtual void Rollback() OVERRIDE;
+ void Begin() override;
+ leveldb::Status CommitPhaseOne(scoped_refptr<BlobWriteCallback>) override;
+ leveldb::Status CommitPhaseTwo() override;
+ void Rollback() override;
private:
leveldb::Status result_;
@@ -150,8 +142,9 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
protected:
friend class base::RefCounted<IndexedDBFakeBackingStore>;
- virtual ~IndexedDBFakeBackingStore();
+ ~IndexedDBFakeBackingStore() override;
+ private:
DISALLOW_COPY_AND_ASSIGN(IndexedDBFakeBackingStore);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
index 0f5a25419ab..c9de8a3acb8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_index_writer.cc
@@ -131,16 +131,13 @@ bool MakeIndexWriters(
bool* completed) {
*completed = false;
- for (std::vector<IndexedDBDatabase::IndexKeys>::const_iterator it =
- index_keys.begin();
- it != index_keys.end();
- ++it) {
+ for (const auto& it : index_keys) {
IndexedDBObjectStoreMetadata::IndexMap::const_iterator found =
- object_store.indexes.find(it->first);
+ object_store.indexes.find(it.first);
if (found == object_store.indexes.end())
continue;
const IndexedDBIndexMetadata& index = found->second;
- IndexedDBDatabase::IndexKeys keys = *it;
+ IndexedDBDatabase::IndexKeys keys = it;
// If the object_store is using auto_increment, then any indexes with an
// identical key_path need to also use the primary (generated) key as a key.
diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
index 5e181f43c89..472e1b9abcf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -11,6 +11,7 @@
#include "base/threading/platform_thread.h"
#include "base/values.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
@@ -20,10 +21,9 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
-#include "grit/content_resources.h"
+#include "storage/common/database/database_identifier.h"
#include "third_party/zlib/google/zip.h"
#include "ui/base/text/bytes_formatting.h"
-#include "webkit/common/database/database_identifier.h"
namespace content {
@@ -44,7 +44,6 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui)
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost);
- source->SetUseJsonJSFormatV2();
source->SetJsonPath("strings.js");
source->AddResourcePath("indexeddb_internals.js",
IDR_INDEXED_DB_INTERNALS_JS);
@@ -87,15 +86,19 @@ void IndexedDBInternalsUI::GetAllOriginsOnIndexedDBThread(
const base::FilePath& context_path) {
DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
- scoped_ptr<base::ListValue> info_list(static_cast<IndexedDBContextImpl*>(
- context.get())->GetAllOriginsDetails());
+ IndexedDBContextImpl* context_impl =
+ static_cast<IndexedDBContextImpl*>(context.get());
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&IndexedDBInternalsUI::OnOriginsReady,
- base::Unretained(this),
- base::Passed(&info_list),
- context_path));
+ scoped_ptr<base::ListValue> info_list(context_impl->GetAllOriginsDetails());
+ bool is_incognito = context_impl->is_incognito();
+
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&IndexedDBInternalsUI::OnOriginsReady,
+ base::Unretained(this),
+ base::Passed(&info_list),
+ is_incognito ? base::FilePath() : context_path));
}
void IndexedDBInternalsUI::OnOriginsReady(scoped_ptr<base::ListValue> origins,
@@ -148,7 +151,7 @@ bool IndexedDBInternalsUI::GetOriginContext(
base::Bind(&FindContext, path, &result_partition, context);
BrowserContext::ForEachStoragePartition(browser_context, cb);
- if (!result_partition || !(*context))
+ if (!result_partition || !(context->get()))
return false;
return true;
@@ -163,7 +166,7 @@ void IndexedDBInternalsUI::DownloadOriginData(const base::ListValue* args) {
if (!GetOriginData(args, &partition_path, &origin_url, &context))
return;
- DCHECK(context);
+ DCHECK(context.get());
context->TaskRunner()->PostTask(
FROM_HERE,
base::Bind(&IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread,
@@ -213,7 +216,7 @@ void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
// has completed.
base::FilePath temp_path = temp_dir.Take();
- std::string origin_id = webkit_database::GetIdentifierFromOrigin(origin_url);
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
base::FilePath zip_path =
temp_path.AppendASCII(origin_id).AddExtension(FILE_PATH_LITERAL("zip"));
@@ -301,12 +304,12 @@ void IndexedDBInternalsUI::OnDownloadDataReady(
class FileDeleter : public DownloadItem::Observer {
public:
explicit FileDeleter(const base::FilePath& temp_dir) : temp_dir_(temp_dir) {}
- virtual ~FileDeleter();
+ ~FileDeleter() override;
- virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE;
- virtual void OnDownloadOpened(DownloadItem* item) OVERRIDE {}
- virtual void OnDownloadRemoved(DownloadItem* item) OVERRIDE {}
- virtual void OnDownloadDestroyed(DownloadItem* item) OVERRIDE {}
+ void OnDownloadUpdated(DownloadItem* download) override;
+ void OnDownloadOpened(DownloadItem* item) override {}
+ void OnDownloadRemoved(DownloadItem* item) override {}
+ void OnDownloadDestroyed(DownloadItem* item) override {}
private:
const base::FilePath temp_dir_;
@@ -332,7 +335,7 @@ void FileDeleter::OnDownloadUpdated(DownloadItem* item) {
FileDeleter::~FileDeleter() {
base::ScopedTempDir path;
- bool will_delete ALLOW_UNUSED = path.Set(temp_dir_);
+ bool will_delete = path.Set(temp_dir_);
DCHECK(will_delete);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.h b/chromium/content/browser/indexed_db/indexed_db_internals_ui.h
index f51df01db09..157978f433b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.h
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.h
@@ -27,7 +27,7 @@ class StoragePartition;
class IndexedDBInternalsUI : public WebUIController {
public:
explicit IndexedDBInternalsUI(WebUI* web_ui);
- virtual ~IndexedDBInternalsUI();
+ ~IndexedDBInternalsUI() override;
private:
void GetAllOrigins(const base::ListValue* args);
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index d0064267c93..f8a3a1e51bd 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -54,7 +54,7 @@
// <0, 0, 0, 100, database id>
// => Existence implies the database id is in the free list
// [DatabaseFreeListKey]
-// <0, 0, 0, 201, origin, database name> => Database id [DatabaseNameKey]
+// <0, 0, 0, 201, origin, database name> => Database id (int) [DatabaseNameKey]
//
//
// Database metadata: [DatabaseMetaDataKey]
@@ -160,6 +160,9 @@
// The sequence number is obsolete; it was used to allow two entries with the
// same user (index) key in non-unique indexes prior to the inclusion of the
// primary key in the data.
+//
+// Note: In order to be compatible with LevelDB's Bloom filter each bit of the
+// encoded key needs to used and "not ignored" by the comparator.
using base::StringPiece;
using blink::WebIDBKeyType;
@@ -377,10 +380,9 @@ void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
}
void EncodeBlobJournal(const BlobJournalType& journal, std::string* into) {
- BlobJournalType::const_iterator iter;
- for (iter = journal.begin(); iter != journal.end(); ++iter) {
- EncodeVarInt(iter->first, into);
- EncodeVarInt(iter->second, into);
+ for (const auto& iter : journal) {
+ EncodeVarInt(iter.first, into);
+ EncodeVarInt(iter.second, into);
}
}
@@ -1436,7 +1438,7 @@ std::string DatabaseMetaDataKey::Encode(int64 database_id,
}
ObjectStoreMetaDataKey::ObjectStoreMetaDataKey()
- : object_store_id_(-1), meta_data_type_(-1) {}
+ : object_store_id_(-1), meta_data_type_(0xFF) {}
bool ObjectStoreMetaDataKey::Decode(StringPiece* slice,
ObjectStoreMetaDataKey* result) {
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
index 85bc091b56b..de16b55f07b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -90,19 +90,6 @@ CONTENT_EXPORT int Compare(const base::StringPiece& a,
class KeyPrefix {
public:
- KeyPrefix();
- explicit KeyPrefix(int64 database_id);
- KeyPrefix(int64 database_id, int64 object_store_id);
- KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id);
- static KeyPrefix CreateWithSpecialIndex(int64 database_id,
- int64 object_store_id,
- int64 index_id);
-
- static bool Decode(base::StringPiece* slice, KeyPrefix* result);
- std::string Encode() const;
- static std::string EncodeEmpty();
- int Compare(const KeyPrefix& other) const;
-
// These are serialized to disk; any new items must be appended, and none can
// be deleted.
enum Type {
@@ -138,6 +125,21 @@ class KeyPrefix {
static const int64 kMaxIndexId =
(1ULL << kMaxIndexIdBits) - 1; // max signed int32
+ static const int64 kInvalidId = -1;
+
+ KeyPrefix();
+ explicit KeyPrefix(int64 database_id);
+ KeyPrefix(int64 database_id, int64 object_store_id);
+ KeyPrefix(int64 database_id, int64 object_store_id, int64 index_id);
+ static KeyPrefix CreateWithSpecialIndex(int64 database_id,
+ int64 object_store_id,
+ int64 index_id);
+
+ static bool Decode(base::StringPiece* slice, KeyPrefix* result);
+ std::string Encode() const;
+ static std::string EncodeEmpty();
+ int Compare(const KeyPrefix& other) const;
+
CONTENT_EXPORT static bool IsValidDatabaseId(int64 database_id);
static bool IsValidObjectStoreId(int64 index_id);
static bool IsValidIndexId(int64 index_id);
@@ -158,17 +160,16 @@ class KeyPrefix {
int64 object_store_id_;
int64 index_id_;
- static const int64 kInvalidId = -1;
-
private:
- static std::string EncodeInternal(int64 database_id,
- int64 object_store_id,
- int64 index_id);
// Special constructor for CreateWithSpecialIndex()
KeyPrefix(enum Type,
int64 database_id,
int64 object_store_id,
int64 index_id);
+
+ static std::string EncodeInternal(int64 database_id,
+ int64 object_store_id,
+ int64 index_id);
};
class SchemaVersionKey {
@@ -378,6 +379,11 @@ class IndexNamesKey {
class ObjectStoreDataKey {
public:
+ static const int64 kSpecialIndexNumber;
+
+ ObjectStoreDataKey();
+ ~ObjectStoreDataKey();
+
static bool Decode(base::StringPiece* slice, ObjectStoreDataKey* result);
CONTENT_EXPORT static std::string Encode(int64 database_id,
int64 object_store_id,
@@ -386,10 +392,6 @@ class ObjectStoreDataKey {
int64 object_store_id,
const IndexedDBKey& user_key);
scoped_ptr<IndexedDBKey> user_key() const;
- static const int64 kSpecialIndexNumber;
- ObjectStoreDataKey();
- ~ObjectStoreDataKey();
-
private:
std::string encoded_user_key_;
};
@@ -408,9 +410,9 @@ class ExistsEntryKey {
const IndexedDBKey& user_key);
scoped_ptr<IndexedDBKey> user_key() const;
+ private:
static const int64 kSpecialIndexNumber;
- private:
std::string encoded_user_key_;
DISALLOW_COPY_AND_ASSIGN(ExistsEntryKey);
};
@@ -433,9 +435,9 @@ class BlobEntryKey {
int64 database_id() const { return database_id_; }
int64 object_store_id() const { return object_store_id_; }
+ private:
static const int64 kSpecialIndexNumber;
- private:
static std::string Encode(int64 database_id,
int64 object_store_id,
const std::string& encoded_user_key);
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
index 0bd647cff3a..5f9edf1a811 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -726,15 +726,13 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeBlobJournal) {
journals.push_back(journal);
}
- std::vector<BlobJournalType>::const_iterator journal_iter;
- for (journal_iter = journals.begin(); journal_iter != journals.end();
- ++journal_iter) {
+ for (const auto& journal_iter : journals) {
std::string encoding;
- EncodeBlobJournal(*journal_iter, &encoding);
+ EncodeBlobJournal(journal_iter, &encoding);
StringPiece slice(encoding);
BlobJournalType journal_out;
EXPECT_TRUE(DecodeBlobJournal(&slice, &journal_out));
- EXPECT_EQ(*journal_iter, journal_out);
+ EXPECT_EQ(journal_iter, journal_out);
}
journals.clear();
@@ -751,10 +749,9 @@ TEST(IndexedDBLevelDBCodingTest, EncodeDecodeBlobJournal) {
journals.push_back(journal);
}
- for (journal_iter = journals.begin(); journal_iter != journals.end();
- ++journal_iter) {
+ for (const auto& journal_iter : journals) {
std::string encoding;
- EncodeBlobJournal(*journal_iter, &encoding);
+ EncodeBlobJournal(journal_iter, &encoding);
StringPiece slice(encoding);
BlobJournalType journal_out;
EXPECT_FALSE(DecodeBlobJournal(&slice, &journal_out));
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.h b/chromium/content/browser/indexed_db/indexed_db_metadata.h
index 68df82ed842..a597616c55f 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.h
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata.h
@@ -14,6 +14,8 @@
namespace content {
struct IndexedDBIndexMetadata {
+ static const int64 kInvalidId = -1;
+
IndexedDBIndexMetadata() {}
IndexedDBIndexMetadata(const base::string16& name,
int64 id,
@@ -30,11 +32,13 @@ struct IndexedDBIndexMetadata {
IndexedDBKeyPath key_path;
bool unique;
bool multi_entry;
-
- static const int64 kInvalidId = -1;
};
struct CONTENT_EXPORT IndexedDBObjectStoreMetadata {
+ typedef std::map<int64, IndexedDBIndexMetadata> IndexMap;
+
+ static const int64 kInvalidId = -1;
+
IndexedDBObjectStoreMetadata();
IndexedDBObjectStoreMetadata(const base::string16& name,
int64 id,
@@ -48,9 +52,6 @@ struct CONTENT_EXPORT IndexedDBObjectStoreMetadata {
bool auto_increment;
int64 max_index_id;
- static const int64 kInvalidId = -1;
-
- typedef std::map<int64, IndexedDBIndexMetadata> IndexMap;
IndexMap indexes;
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
index 5e0cea898e0..d8af36c5566 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
@@ -10,19 +10,19 @@
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/net_util.h"
-#include "webkit/browser/database/database_util.h"
+#include "storage/browser/database/database_util.h"
-using quota::QuotaClient;
-using webkit_database::DatabaseUtil;
+using storage::QuotaClient;
+using storage::DatabaseUtil;
namespace content {
namespace {
-quota::QuotaStatusCode DeleteOriginDataOnIndexedDBThread(
+storage::QuotaStatusCode DeleteOriginDataOnIndexedDBThread(
IndexedDBContextImpl* context,
const GURL& origin) {
context->DeleteForOrigin(origin);
- return quota::kQuotaStatusOk;
+ return storage::kQuotaStatusOk;
}
int64 GetOriginUsageOnIndexedDBThread(IndexedDBContextImpl* context,
@@ -49,11 +49,9 @@ void GetOriginsForHostOnIndexedDBThread(IndexedDBContextImpl* context,
std::set<GURL>* origins_to_return) {
DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
std::vector<GURL> all_origins = context->GetAllOrigins();
- for (std::vector<GURL>::const_iterator iter = all_origins.begin();
- iter != all_origins.end();
- ++iter) {
- if (host == net::GetHostOrSpecFromURL(*iter))
- origins_to_return->insert(*iter);
+ for (const auto& origin_url : all_origins) {
+ if (host == net::GetHostOrSpecFromURL(origin_url))
+ origins_to_return->insert(origin_url);
}
}
@@ -72,13 +70,13 @@ QuotaClient::ID IndexedDBQuotaClient::id() const { return kIndexedDatabase; }
void IndexedDBQuotaClient::OnQuotaManagerDestroyed() { delete this; }
void IndexedDBQuotaClient::GetOriginUsage(const GURL& origin_url,
- quota::StorageType type,
+ storage::StorageType type,
const GetUsageCallback& callback) {
DCHECK(!callback.is_null());
- DCHECK(indexed_db_context_);
+ DCHECK(indexed_db_context_.get());
// IndexedDB is in the temp namespace for now.
- if (type != quota::kStorageTypeTemporary) {
+ if (type != storage::kStorageTypeTemporary) {
callback.Run(0);
return;
}
@@ -98,13 +96,13 @@ void IndexedDBQuotaClient::GetOriginUsage(const GURL& origin_url,
}
void IndexedDBQuotaClient::GetOriginsForType(
- quota::StorageType type,
+ storage::StorageType type,
const GetOriginsCallback& callback) {
DCHECK(!callback.is_null());
- DCHECK(indexed_db_context_);
+ DCHECK(indexed_db_context_.get());
// All databases are in the temp namespace for now.
- if (type != quota::kStorageTypeTemporary) {
+ if (type != storage::kStorageTypeTemporary) {
callback.Run(std::set<GURL>());
return;
}
@@ -125,14 +123,14 @@ void IndexedDBQuotaClient::GetOriginsForType(
}
void IndexedDBQuotaClient::GetOriginsForHost(
- quota::StorageType type,
+ storage::StorageType type,
const std::string& host,
const GetOriginsCallback& callback) {
DCHECK(!callback.is_null());
- DCHECK(indexed_db_context_);
+ DCHECK(indexed_db_context_.get());
// All databases are in the temp namespace for now.
- if (type != quota::kStorageTypeTemporary) {
+ if (type != storage::kStorageTypeTemporary) {
callback.Run(std::set<GURL>());
return;
}
@@ -154,16 +152,16 @@ void IndexedDBQuotaClient::GetOriginsForHost(
}
void IndexedDBQuotaClient::DeleteOriginData(const GURL& origin,
- quota::StorageType type,
+ storage::StorageType type,
const DeletionCallback& callback) {
- if (type != quota::kStorageTypeTemporary) {
- callback.Run(quota::kQuotaErrorNotSupported);
+ if (type != storage::kStorageTypeTemporary) {
+ callback.Run(storage::kQuotaErrorNotSupported);
return;
}
// No task runner means unit test; no cleanup necessary.
if (!indexed_db_context_->TaskRunner()) {
- callback.Run(quota::kQuotaStatusOk);
+ callback.Run(storage::kQuotaStatusOk);
return;
}
@@ -175,8 +173,8 @@ void IndexedDBQuotaClient::DeleteOriginData(const GURL& origin,
callback);
}
-bool IndexedDBQuotaClient::DoesSupport(quota::StorageType type) const {
- return type == quota::kStorageTypeTemporary;
+bool IndexedDBQuotaClient::DoesSupport(storage::StorageType type) const {
+ return type == storage::kStorageTypeTemporary;
}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client.h b/chromium/content/browser/indexed_db/indexed_db_quota_client.h
index 6f4c50ef690..7894a653f26 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.h
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.h
@@ -12,9 +12,9 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "content/common/content_export.h"
-#include "webkit/browser/quota/quota_client.h"
-#include "webkit/browser/quota/quota_task.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_task.h"
+#include "storage/common/quota/quota_types.h"
namespace content {
class IndexedDBContextImpl;
@@ -22,32 +22,31 @@ class IndexedDBContextImpl;
// A QuotaClient implementation to integrate IndexedDB
// with the quota management system. This interface is used
// on the IO thread by the quota manager.
-class IndexedDBQuotaClient : public quota::QuotaClient,
- public quota::QuotaTaskObserver {
+class IndexedDBQuotaClient : public storage::QuotaClient,
+ public storage::QuotaTaskObserver {
public:
CONTENT_EXPORT explicit IndexedDBQuotaClient(
IndexedDBContextImpl* indexed_db_context);
- CONTENT_EXPORT virtual ~IndexedDBQuotaClient();
+ CONTENT_EXPORT ~IndexedDBQuotaClient() override;
// QuotaClient method overrides
- virtual ID id() const OVERRIDE;
- virtual void OnQuotaManagerDestroyed() OVERRIDE;
- CONTENT_EXPORT virtual void GetOriginUsage(const GURL& origin_url,
- quota::StorageType type,
- const GetUsageCallback& callback)
- OVERRIDE;
- CONTENT_EXPORT virtual void GetOriginsForType(
- quota::StorageType type,
- const GetOriginsCallback& callback) OVERRIDE;
- CONTENT_EXPORT virtual void GetOriginsForHost(
- quota::StorageType type,
+ ID id() const override;
+ void OnQuotaManagerDestroyed() override;
+ CONTENT_EXPORT void GetOriginUsage(const GURL& origin_url,
+ storage::StorageType type,
+ const GetUsageCallback& callback) override;
+ CONTENT_EXPORT void GetOriginsForType(
+ storage::StorageType type,
+ const GetOriginsCallback& callback) override;
+ CONTENT_EXPORT void GetOriginsForHost(
+ storage::StorageType type,
const std::string& host,
- const GetOriginsCallback& callback) OVERRIDE;
- CONTENT_EXPORT virtual void DeleteOriginData(const GURL& origin,
- quota::StorageType type,
- const DeletionCallback& callback)
- OVERRIDE;
- virtual bool DoesSupport(quota::StorageType type) const OVERRIDE;
+ const GetOriginsCallback& callback) override;
+ CONTENT_EXPORT void DeleteOriginData(
+ const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) override;
+ bool DoesSupport(storage::StorageType type) const override;
private:
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index 54ce775d6e2..f0befd24666 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -5,8 +5,8 @@
#include <map>
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/test/test_simple_task_runner.h"
@@ -18,12 +18,12 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/database/database_identifier.h"
// Declared to shorten the line lengths.
-static const quota::StorageType kTemp = quota::kStorageTypeTemporary;
-static const quota::StorageType kPerm = quota::kStorageTypePersistent;
+static const storage::StorageType kTemp = storage::kStorageTypeTemporary;
+static const storage::StorageType kPerm = storage::kStorageTypePersistent;
namespace content {
@@ -43,19 +43,18 @@ class IndexedDBQuotaClientTest : public testing::Test {
weak_factory_(this) {
browser_context_.reset(new TestBrowserContext());
- scoped_refptr<quota::QuotaManager> quota_manager =
- new MockQuotaManager(
- false /*in_memory*/,
- browser_context_->GetPath(),
- base::MessageLoop::current()->message_loop_proxy(),
- base::MessageLoop::current()->message_loop_proxy(),
- browser_context_->GetSpecialStoragePolicy());
+ scoped_refptr<storage::QuotaManager> quota_manager =
+ new MockQuotaManager(false /*in_memory*/,
+ browser_context_->GetPath(),
+ base::MessageLoop::current()->message_loop_proxy(),
+ base::MessageLoop::current()->message_loop_proxy(),
+ browser_context_->GetSpecialStoragePolicy());
idb_context_ =
new IndexedDBContextImpl(browser_context_->GetPath(),
browser_context_->GetSpecialStoragePolicy(),
quota_manager->proxy(),
- task_runner_);
+ task_runner_.get());
base::MessageLoop::current()->RunUntilIdle();
setup_temp_dir();
}
@@ -70,16 +69,16 @@ class IndexedDBQuotaClientTest : public testing::Test {
idb_context()->set_data_path_for_testing(indexeddb_dir);
}
- virtual ~IndexedDBQuotaClientTest() {
+ ~IndexedDBQuotaClientTest() override {
FlushIndexedDBTaskRunner();
idb_context_ = NULL;
browser_context_.reset();
base::MessageLoop::current()->RunUntilIdle();
}
- int64 GetOriginUsage(quota::QuotaClient* client,
+ int64 GetOriginUsage(storage::QuotaClient* client,
const GURL& origin,
- quota::StorageType type) {
+ storage::StorageType type) {
usage_ = -1;
client->GetOriginUsage(
origin,
@@ -92,8 +91,8 @@ class IndexedDBQuotaClientTest : public testing::Test {
return usage_;
}
- const std::set<GURL>& GetOriginsForType(quota::QuotaClient* client,
- quota::StorageType type) {
+ const std::set<GURL>& GetOriginsForType(storage::QuotaClient* client,
+ storage::StorageType type) {
origins_.clear();
client->GetOriginsForType(
type,
@@ -104,8 +103,8 @@ class IndexedDBQuotaClientTest : public testing::Test {
return origins_;
}
- const std::set<GURL>& GetOriginsForHost(quota::QuotaClient* client,
- quota::StorageType type,
+ const std::set<GURL>& GetOriginsForHost(storage::QuotaClient* client,
+ storage::StorageType type,
const std::string& host) {
origins_.clear();
client->GetOriginsForHost(
@@ -118,9 +117,9 @@ class IndexedDBQuotaClientTest : public testing::Test {
return origins_;
}
- quota::QuotaStatusCode DeleteOrigin(quota::QuotaClient* client,
- const GURL& origin_url) {
- delete_status_ = quota::kQuotaStatusUnknown;
+ storage::QuotaStatusCode DeleteOrigin(storage::QuotaClient* client,
+ const GURL& origin_url) {
+ delete_status_ = storage::kQuotaStatusUnknown;
client->DeleteOriginData(
origin_url,
kTemp,
@@ -131,7 +130,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
return delete_status_;
}
- IndexedDBContextImpl* idb_context() { return idb_context_; }
+ IndexedDBContextImpl* idb_context() { return idb_context_.get(); }
void SetFileSizeTo(const base::FilePath& path, int size) {
std::string junk(size, 'a');
@@ -140,7 +139,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
void AddFakeIndexedDB(const GURL& origin, int size) {
base::FilePath file_path_origin = idb_context()->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(origin));
+ storage::GetIdentifierFromOrigin(origin));
if (!base::CreateDirectory(file_path_origin)) {
LOG(ERROR) << "failed to base::CreateDirectory "
<< file_path_origin.value();
@@ -157,7 +156,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
origins_ = origins;
}
- void OnDeleteOriginComplete(quota::QuotaStatusCode code) {
+ void OnDeleteOriginComplete(storage::QuotaStatusCode code) {
delete_status_ = code;
}
@@ -168,7 +167,7 @@ class IndexedDBQuotaClientTest : public testing::Test {
scoped_refptr<IndexedDBContextImpl> idb_context_;
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestBrowserContext> browser_context_;
- quota::QuotaStatusCode delete_status_;
+ storage::QuotaStatusCode delete_status_;
base::WeakPtrFactory<IndexedDBQuotaClientTest> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBQuotaClientTest);
@@ -237,8 +236,8 @@ TEST_F(IndexedDBQuotaClientTest, DeleteOrigin) {
EXPECT_EQ(1000, GetOriginUsage(&client, kOriginA, kTemp));
EXPECT_EQ(50, GetOriginUsage(&client, kOriginB, kTemp));
- quota::QuotaStatusCode delete_status = DeleteOrigin(&client, kOriginA);
- EXPECT_EQ(quota::kQuotaStatusOk, delete_status);
+ storage::QuotaStatusCode delete_status = DeleteOrigin(&client, kOriginA);
+ EXPECT_EQ(storage::kQuotaStatusOk, delete_status);
EXPECT_EQ(0, GetOriginUsage(&client, kOriginA, kTemp));
EXPECT_EQ(50, GetOriginUsage(&client, kOriginB, kTemp));
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.cc b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
index 4de6784ae8c..6609e02499b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.cc
@@ -54,7 +54,7 @@ IndexedDBTransaction::IndexedDBTransaction(
int64 id,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
const std::set<int64>& object_store_ids,
- indexed_db::TransactionMode mode,
+ blink::WebIDBTransactionMode mode,
IndexedDBDatabase* database,
IndexedDBBackingStore::Transaction* backing_store_transaction)
: id_(id),
@@ -86,7 +86,7 @@ IndexedDBTransaction::~IndexedDBTransaction() {
DCHECK(abort_task_stack_.empty());
}
-void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
+void IndexedDBTransaction::ScheduleTask(blink::WebIDBTaskType type,
Operation task) {
DCHECK_NE(state_, COMMITTING);
if (state_ == FINISHED)
@@ -94,7 +94,7 @@ void IndexedDBTransaction::ScheduleTask(IndexedDBDatabase::TaskType type,
timeout_timer_.Stop();
used_ = true;
- if (type == IndexedDBDatabase::NORMAL_TASK) {
+ if (type == blink::WebIDBTaskTypeNormal) {
task_queue_.push(task);
++diagnostics_.tasks_scheduled;
} else {
@@ -212,12 +212,12 @@ class BlobWriteCallbackImpl : public IndexedDBBackingStore::BlobWriteCallback {
explicit BlobWriteCallbackImpl(
scoped_refptr<IndexedDBTransaction> transaction)
: transaction_(transaction) {}
- virtual void Run(bool succeeded) OVERRIDE {
+ void Run(bool succeeded) override {
transaction_->BlobWriteComplete(succeeded);
}
protected:
- virtual ~BlobWriteCallbackImpl() {}
+ ~BlobWriteCallbackImpl() override {}
private:
scoped_refptr<IndexedDBTransaction> transaction_;
@@ -235,14 +235,16 @@ void IndexedDBTransaction::BlobWriteComplete(bool success) {
"Failed to write blobs."));
}
-void IndexedDBTransaction::Commit() {
+leveldb::Status IndexedDBTransaction::Commit() {
IDB_TRACE1("IndexedDBTransaction::Commit", "txn.id", id());
+ timeout_timer_.Stop();
+
// In multiprocess ports, front-end may have requested a commit but
// an abort has already been initiated asynchronously by the
// back-end.
if (state_ == FINISHED)
- return;
+ return leveldb::Status::OK();
DCHECK_NE(state_, COMMITTING);
DCHECK(!used_ || state_ == STARTED);
@@ -252,27 +254,31 @@ void IndexedDBTransaction::Commit() {
// create_index which are considered synchronous by the front-end
// but are processed asynchronously.
if (HasPendingTasks())
- return;
+ return leveldb::Status::OK();
state_ = COMMITTING;
+ leveldb::Status s;
if (!used_) {
- CommitPhaseTwo();
+ s = CommitPhaseTwo();
} else {
scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback(
new BlobWriteCallbackImpl(this));
// CommitPhaseOne will call the callback synchronously if there are no blobs
// to write.
- if (!transaction_->CommitPhaseOne(callback).ok())
+ s = transaction_->CommitPhaseOne(callback);
+ if (!s.ok())
Abort(IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionDataError,
"Error processing blob journal."));
}
+
+ return s;
}
-void IndexedDBTransaction::CommitPhaseTwo() {
+leveldb::Status IndexedDBTransaction::CommitPhaseTwo() {
// Abort may have been called just as the blob write completed.
if (state_ == FINISHED)
- return;
+ return leveldb::Status::OK();
DCHECK_EQ(state_, COMMITTING);
@@ -281,11 +287,16 @@ void IndexedDBTransaction::CommitPhaseTwo() {
// alive while executing this method.
scoped_refptr<IndexedDBTransaction> protect(this);
- timeout_timer_.Stop();
-
state_ = FINISHED;
- bool committed = !used_ || transaction_->CommitPhaseTwo().ok();
+ leveldb::Status s;
+ bool committed;
+ if (!used_) {
+ committed = true;
+ } else {
+ s = transaction_->CommitPhaseTwo();
+ committed = s.ok();
+ }
// Backing store resources (held via cursors) must be released
// before script callbacks are fired, as the script callbacks may
@@ -312,10 +323,11 @@ void IndexedDBTransaction::CommitPhaseTwo() {
IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
"Internal error committing transaction."));
database_->TransactionFinished(this, false);
- database_->TransactionCommitFailed();
+ database_->TransactionCommitFailed(s);
}
database_ = NULL;
+ return s;
}
void IndexedDBTransaction::ProcessTaskQueue() {
@@ -370,7 +382,7 @@ void IndexedDBTransaction::ProcessTaskQueue() {
// Otherwise, start a timer in case the front-end gets wedged and
// never requests further activity. Read-only transactions don't
// block other transactions, so don't time those out.
- if (mode_ != indexed_db::TRANSACTION_READ_ONLY) {
+ if (mode_ != blink::WebIDBTransactionModeReadOnly) {
timeout_timer_.Start(
FROM_HERE,
base::TimeDelta::FromSeconds(kInactivityTimeoutPeriodSeconds),
@@ -385,10 +397,8 @@ void IndexedDBTransaction::Timeout() {
}
void IndexedDBTransaction::CloseOpenCursors() {
- for (std::set<IndexedDBCursor*>::iterator i = open_cursors_.begin();
- i != open_cursors_.end();
- ++i)
- (*i)->Close();
+ for (auto* cursor : open_cursors_)
+ cursor->Close();
open_cursors_.clear();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction.h b/chromium/content/browser/indexed_db/indexed_db_transaction.h
index e30422f15ab..bd0e543035c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction.h
@@ -17,6 +17,7 @@
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_database.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
namespace content {
@@ -29,28 +30,36 @@ class CONTENT_EXPORT IndexedDBTransaction
public:
typedef base::Callback<void(IndexedDBTransaction*)> Operation;
+ enum State {
+ CREATED, // Created, but not yet started by coordinator.
+ STARTED, // Started by the coordinator.
+ COMMITTING, // In the process of committing, possibly waiting for blobs
+ // to be written.
+ FINISHED, // Either aborted or committed.
+ };
+
IndexedDBTransaction(
int64 id,
scoped_refptr<IndexedDBDatabaseCallbacks> callbacks,
const std::set<int64>& object_store_ids,
- indexed_db::TransactionMode,
+ blink::WebIDBTransactionMode,
IndexedDBDatabase* db,
IndexedDBBackingStore::Transaction* backing_store_transaction);
virtual void Abort();
- void Commit();
+ leveldb::Status Commit();
void Abort(const IndexedDBDatabaseError& error);
// Called by the transaction coordinator when this transaction is unblocked.
void Start();
- indexed_db::TransactionMode mode() const { return mode_; }
+ blink::WebIDBTransactionMode mode() const { return mode_; }
const std::set<int64>& scope() const { return object_store_ids_; }
void ScheduleTask(Operation task) {
- ScheduleTask(IndexedDBDatabase::NORMAL_TASK, task);
+ ScheduleTask(blink::WebIDBTaskTypeNormal, task);
}
- void ScheduleTask(IndexedDBDatabase::TaskType, Operation task);
+ void ScheduleTask(blink::WebIDBTaskType, Operation task);
void ScheduleAbortTask(Operation abort_task);
void RegisterOpenCursor(IndexedDBCursor* cursor);
void UnregisterOpenCursor(IndexedDBCursor* cursor);
@@ -64,16 +73,8 @@ class CONTENT_EXPORT IndexedDBTransaction
}
int64 id() const { return id_; }
- IndexedDBDatabase* database() const { return database_; }
- IndexedDBDatabaseCallbacks* connection() const { return callbacks_; }
-
- enum State {
- CREATED, // Created, but not yet started by coordinator.
- STARTED, // Started by the coordinator.
- COMMITTING, // In the process of committing, possibly waiting for blobs
- // to be written.
- FINISHED, // Either aborted or committed.
- };
+ IndexedDBDatabase* database() const { return database_.get(); }
+ IndexedDBDatabaseCallbacks* connection() const { return callbacks_.get(); }
State state() const { return state_; }
bool IsTimeoutTimerRunning() const { return timeout_timer_.IsRunning(); }
@@ -108,12 +109,12 @@ class CONTENT_EXPORT IndexedDBTransaction
void BlobWriteComplete(bool success);
void ProcessTaskQueue();
void CloseOpenCursors();
- void CommitPhaseTwo();
+ leveldb::Status CommitPhaseTwo();
void Timeout();
const int64 id_;
const std::set<int64> object_store_ids_;
- const indexed_db::TransactionMode mode_;
+ const blink::WebIDBTransactionMode mode_;
bool used_;
State state_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
index a1eaad41ecd..ca7f3838b88 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.cc
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "content/browser/indexed_db/indexed_db_transaction.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
namespace content {
@@ -44,7 +45,7 @@ bool IndexedDBTransactionCoordinator::IsRunningVersionChangeTransaction()
const {
return !started_transactions_.empty() &&
(*started_transactions_.begin())->mode() ==
- indexed_db::TRANSACTION_VERSION_CHANGE;
+ blink::WebIDBTransactionModeVersionChange;
}
#ifndef NDEBUG
@@ -66,16 +67,10 @@ std::vector<const IndexedDBTransaction*>
IndexedDBTransactionCoordinator::GetTransactions() const {
std::vector<const IndexedDBTransaction*> result;
- for (TransactionSet::const_iterator it = started_transactions_.begin();
- it != started_transactions_.end();
- ++it) {
- result.push_back(*it);
- }
- for (TransactionSet::const_iterator it = queued_transactions_.begin();
- it != queued_transactions_.end();
- ++it) {
- result.push_back(*it);
- }
+ for (const auto& transaction : started_transactions_)
+ result.push_back(transaction.get());
+ for (const auto& transaction : queued_transactions_)
+ result.push_back(transaction.get());
return result;
}
@@ -93,11 +88,8 @@ void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() {
// data. ("Version change" transactions are exclusive, but handled by the
// connection sequencing in IndexedDBDatabase.)
std::set<int64> locked_scope;
- for (TransactionSet::const_iterator it = started_transactions_.begin();
- it != started_transactions_.end();
- ++it) {
- IndexedDBTransaction* transaction = *it;
- if (transaction->mode() == indexed_db::TRANSACTION_READ_WRITE) {
+ for (const auto& transaction : started_transactions_) {
+ if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) {
// Started read/write transactions have exclusive access to the object
// stores within their scopes.
locked_scope.insert(transaction->scope().begin(),
@@ -109,14 +101,14 @@ void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() {
while (it != queued_transactions_.end()) {
scoped_refptr<IndexedDBTransaction> transaction = *it;
++it;
- if (CanStartTransaction(transaction, locked_scope)) {
+ if (CanStartTransaction(transaction.get(), locked_scope)) {
DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
queued_transactions_.erase(transaction);
started_transactions_.insert(transaction);
transaction->Start();
DCHECK_EQ(IndexedDBTransaction::STARTED, transaction->state());
}
- if (transaction->mode() == indexed_db::TRANSACTION_READ_WRITE) {
+ if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) {
// Either the transaction started, so it has exclusive access to the
// stores in its scope, or per the spec the transaction which was
// created first must get access first, so the stores are also locked.
@@ -147,16 +139,16 @@ bool IndexedDBTransactionCoordinator::CanStartTransaction(
const std::set<int64>& locked_scope) const {
DCHECK(queued_transactions_.count(transaction));
switch (transaction->mode()) {
- case indexed_db::TRANSACTION_VERSION_CHANGE:
+ case blink::WebIDBTransactionModeVersionChange:
DCHECK_EQ(1u, queued_transactions_.size());
DCHECK(started_transactions_.empty());
DCHECK(locked_scope.empty());
return true;
- case indexed_db::TRANSACTION_READ_ONLY:
+ case blink::WebIDBTransactionModeReadOnly:
return true;
- case indexed_db::TRANSACTION_READ_WRITE:
+ case blink::WebIDBTransactionModeReadWrite:
return !DoSetsIntersect(transaction->scope(), locked_scope);
}
NOTREACHED();
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
index 98db0b39de0..890541dfd24 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_coordinator.h
@@ -37,6 +37,8 @@ class IndexedDBTransactionCoordinator {
std::vector<const IndexedDBTransaction*> GetTransactions() const;
private:
+ typedef list_set<scoped_refptr<IndexedDBTransaction> > TransactionSet;
+
void ProcessQueuedTransactions();
bool CanStartTransaction(IndexedDBTransaction* const transaction,
const std::set<int64>& locked_scope) const;
@@ -44,7 +46,6 @@ class IndexedDBTransactionCoordinator {
// Transactions in different states are grouped below.
// list_set is used to provide stable ordering; required by spec
// for the queue, convenience for diagnostics for the rest.
- typedef list_set<scoped_refptr<IndexedDBTransaction> > TransactionSet;
TransactionSet queued_transactions_;
TransactionSet started_transactions_;
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
index c6a1244d4dc..e033dd79e64 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -10,6 +10,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/indexed_db/indexed_db_fake_backing_store.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
+#include "content/browser/indexed_db/mock_indexed_db_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -31,7 +32,7 @@ class AbortObserver {
class IndexedDBTransactionTest : public testing::Test {
public:
- IndexedDBTransactionTest() {
+ IndexedDBTransactionTest() : factory_(new MockIndexedDBFactory()) {
backing_store_ = new IndexedDBFakeBackingStore();
CreateDB();
}
@@ -40,11 +41,10 @@ class IndexedDBTransactionTest : public testing::Test {
// DB is created here instead of the constructor to workaround a
// "peculiarity of C++". More info at
// https://code.google.com/p/googletest/wiki/FAQ#My_compiler_complains_that_a_constructor_(or_destructor)_cannot
- IndexedDBFactory* factory = NULL;
leveldb::Status s;
db_ = IndexedDBDatabase::Create(base::ASCIIToUTF16("db"),
- backing_store_,
- factory,
+ backing_store_.get(),
+ factory_.get(),
IndexedDBDatabase::Identifier(),
&s);
ASSERT_TRUE(s.ok());
@@ -64,12 +64,14 @@ class IndexedDBTransactionTest : public testing::Test {
private:
base::MessageLoop message_loop_;
+ scoped_refptr<MockIndexedDBFactory> factory_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBTransactionTest);
};
-class IndexedDBTransactionTestMode : public IndexedDBTransactionTest,
- public testing::WithParamInterface<indexed_db::TransactionMode> {
+class IndexedDBTransactionTestMode
+ : public IndexedDBTransactionTest,
+ public testing::WithParamInterface<blink::WebIDBTransactionMode> {
public:
IndexedDBTransactionTestMode() {}
private:
@@ -84,10 +86,10 @@ TEST_F(IndexedDBTransactionTest, Timeout) {
id,
new MockIndexedDBDatabaseCallbacks(),
scope,
- indexed_db::TRANSACTION_READ_WRITE,
- db_,
+ blink::WebIDBTransactionModeReadWrite,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
- db_->TransactionCreated(transaction);
+ db_->TransactionCreated(transaction.get());
// No conflicting transactions, so coordinator will start it immediately:
EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
@@ -128,10 +130,10 @@ TEST_F(IndexedDBTransactionTest, NoTimeoutReadOnly) {
id,
new MockIndexedDBDatabaseCallbacks(),
scope,
- indexed_db::TRANSACTION_READ_ONLY,
- db_,
+ blink::WebIDBTransactionModeReadOnly,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
- db_->TransactionCreated(transaction);
+ db_->TransactionCreated(transaction.get());
// No conflicting transactions, so coordinator will start it immediately:
EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
@@ -161,7 +163,7 @@ TEST_P(IndexedDBTransactionTestMode, ScheduleNormalTask) {
new MockIndexedDBDatabaseCallbacks(),
scope,
GetParam(),
- db_,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
EXPECT_FALSE(transaction->HasPendingTasks());
@@ -171,7 +173,7 @@ TEST_P(IndexedDBTransactionTestMode, ScheduleNormalTask) {
EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
- db_->TransactionCreated(transaction);
+ db_->TransactionCreated(transaction.get());
EXPECT_FALSE(transaction->HasPendingTasks());
EXPECT_TRUE(transaction->IsTaskQueueEmpty());
@@ -179,7 +181,7 @@ TEST_P(IndexedDBTransactionTestMode, ScheduleNormalTask) {
EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
transaction->ScheduleTask(
- IndexedDBDatabase::NORMAL_TASK,
+ blink::WebIDBTaskTypeNormal,
base::Bind(&IndexedDBTransactionTest::DummyOperation,
base::Unretained(this)));
@@ -222,8 +224,8 @@ TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) {
id,
new MockIndexedDBDatabaseCallbacks(),
scope,
- indexed_db::TRANSACTION_VERSION_CHANGE,
- db_,
+ blink::WebIDBTransactionModeVersionChange,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_failure));
EXPECT_FALSE(transaction->HasPendingTasks());
@@ -233,7 +235,7 @@ TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) {
EXPECT_EQ(0, transaction->diagnostics().tasks_scheduled);
EXPECT_EQ(0, transaction->diagnostics().tasks_completed);
- db_->TransactionCreated(transaction);
+ db_->TransactionCreated(transaction.get());
EXPECT_FALSE(transaction->HasPendingTasks());
EXPECT_TRUE(transaction->IsTaskQueueEmpty());
@@ -241,7 +243,7 @@ TEST_F(IndexedDBTransactionTest, SchedulePreemptiveTask) {
EXPECT_TRUE(transaction->preemptive_task_queue_.empty());
transaction->ScheduleTask(
- IndexedDBDatabase::PREEMPTIVE_TASK,
+ blink::WebIDBTaskTypePreemptive,
base::Bind(&IndexedDBTransactionTest::DummyOperation,
base::Unretained(this)));
transaction->AddPreemptiveEvent();
@@ -284,9 +286,9 @@ TEST_P(IndexedDBTransactionTestMode, AbortTasks) {
new MockIndexedDBDatabaseCallbacks(),
scope,
GetParam(),
- db_,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_failure));
- db_->TransactionCreated(transaction);
+ db_->TransactionCreated(transaction.get());
AbortObserver observer;
transaction->ScheduleTask(
@@ -314,16 +316,16 @@ TEST_P(IndexedDBTransactionTestMode, AbortPreemptive) {
new MockIndexedDBDatabaseCallbacks(),
scope,
GetParam(),
- db_,
+ db_.get(),
new IndexedDBFakeBackingStore::FakeTransaction(commit_success));
- db_->TransactionCreated(transaction);
+ db_->TransactionCreated(transaction.get());
// No conflicting transactions, so coordinator will start it immediately:
EXPECT_EQ(IndexedDBTransaction::STARTED, transaction->state());
EXPECT_FALSE(transaction->IsTimeoutTimerRunning());
transaction->ScheduleTask(
- IndexedDBDatabase::PREEMPTIVE_TASK,
+ blink::WebIDBTaskTypePreemptive,
base::Bind(&IndexedDBTransactionTest::DummyOperation,
base::Unretained(this)));
EXPECT_EQ(0, transaction->pending_preemptive_events_);
@@ -356,11 +358,9 @@ TEST_P(IndexedDBTransactionTestMode, AbortPreemptive) {
transaction->diagnostics().tasks_scheduled);
}
-static const indexed_db::TransactionMode kTestModes[] = {
- indexed_db::TRANSACTION_READ_ONLY,
- indexed_db::TRANSACTION_READ_WRITE,
- indexed_db::TRANSACTION_VERSION_CHANGE
-};
+static const blink::WebIDBTransactionMode kTestModes[] = {
+ blink::WebIDBTransactionModeReadOnly, blink::WebIDBTransactionModeReadWrite,
+ blink::WebIDBTransactionModeVersionChange};
INSTANTIATE_TEST_CASE_P(IndexedDBTransactions,
IndexedDBTransactionTestMode,
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index 6fa627b1632..ddb1fdc66bd 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -2,23 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/indexed_db/indexed_db_connection.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_context.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/special_storage_policy.h"
+#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/special_storage_policy.h"
-#include "webkit/common/database/database_identifier.h"
namespace content {
@@ -61,13 +62,16 @@ TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) {
// Create the scope which will ensure we run the destructor of the context
// which should trigger the clean up.
{
- scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+ scoped_refptr<IndexedDBContextImpl> idb_context =
+ new IndexedDBContextImpl(temp_dir.path(),
+ special_storage_policy_.get(),
+ NULL,
+ task_runner_.get());
normal_path = idb_context->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(kNormalOrigin));
+ storage::GetIdentifierFromOrigin(kNormalOrigin));
session_only_path = idb_context->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin));
+ storage::GetIdentifierFromOrigin(kSessionOnlyOrigin));
ASSERT_TRUE(base::CreateDirectory(normal_path));
ASSERT_TRUE(base::CreateDirectory(session_only_path));
FlushIndexedDBTaskRunner();
@@ -92,16 +96,19 @@ TEST_F(IndexedDBTest, SetForceKeepSessionState) {
{
// Create some indexedDB paths.
// With the levelDB backend, these are directories.
- scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+ scoped_refptr<IndexedDBContextImpl> idb_context =
+ new IndexedDBContextImpl(temp_dir.path(),
+ special_storage_policy_.get(),
+ NULL,
+ task_runner_.get());
// Save session state. This should bypass the destruction-time deletion.
idb_context->SetForceKeepSessionState();
normal_path = idb_context->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(kNormalOrigin));
+ storage::GetIdentifierFromOrigin(kNormalOrigin));
session_only_path = idb_context->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(kSessionOnlyOrigin));
+ storage::GetIdentifierFromOrigin(kSessionOnlyOrigin));
ASSERT_TRUE(base::CreateDirectory(normal_path));
ASSERT_TRUE(base::CreateDirectory(session_only_path));
message_loop_.RunUntilIdle();
@@ -123,10 +130,10 @@ class ForceCloseDBCallbacks : public IndexedDBCallbacks {
idb_context_(idb_context),
origin_url_(origin_url) {}
- virtual void OnSuccess() OVERRIDE {}
- virtual void OnSuccess(const std::vector<base::string16>&) OVERRIDE {}
- virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) OVERRIDE {
+ void OnSuccess() override {}
+ void OnSuccess(const std::vector<base::string16>&) override {}
+ void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
+ const IndexedDBDatabaseMetadata& metadata) override {
connection_ = connection.Pass();
idb_context_->ConnectionOpened(origin_url_, connection_.get());
}
@@ -134,7 +141,7 @@ class ForceCloseDBCallbacks : public IndexedDBCallbacks {
IndexedDBConnection* connection() { return connection_.get(); }
protected:
- virtual ~ForceCloseDBCallbacks() {}
+ ~ForceCloseDBCallbacks() override {}
private:
scoped_refptr<IndexedDBContextImpl> idb_context_;
@@ -160,8 +167,11 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
const GURL kTestOrigin("http://test/");
- scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+ scoped_refptr<IndexedDBContextImpl> idb_context =
+ new IndexedDBContextImpl(temp_dir.path(),
+ special_storage_policy_.get(),
+ NULL,
+ task_runner_.get());
scoped_refptr<ForceCloseDBCallbacks> open_callbacks =
new ForceCloseDBCallbacks(idb_context, kTestOrigin);
@@ -172,7 +182,7 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
IndexedDBFactory* factory = idb_context->GetIDBFactory();
test_path = idb_context->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(kTestOrigin));
+ storage::GetIdentifierFromOrigin(kTestOrigin));
IndexedDBPendingConnection open_connection(open_callbacks,
open_db_callbacks,
@@ -219,10 +229,10 @@ TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) {
const GURL kTestOrigin("http://test/");
scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+ temp_dir.path(), special_storage_policy_.get(), NULL, task_runner_.get());
base::FilePath test_path = idb_context->GetFilePathForTesting(
- webkit_database::GetIdentifierFromOrigin(kTestOrigin));
+ storage::GetIdentifierFromOrigin(kTestOrigin));
ASSERT_TRUE(base::CreateDirectory(test_path));
scoped_ptr<LevelDBLock> lock =
@@ -245,9 +255,10 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
scoped_refptr<IndexedDBContextImpl> context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_, NULL, task_runner_);
+ temp_dir.path(), special_storage_policy_.get(), NULL, task_runner_.get());
- scoped_refptr<IndexedDBFactory> factory = context->GetIDBFactory();
+ scoped_refptr<IndexedDBFactoryImpl> factory =
+ static_cast<IndexedDBFactoryImpl*>(context->GetIDBFactory());
scoped_refptr<MockIndexedDBCallbacks> callbacks(new MockIndexedDBCallbacks());
scoped_refptr<MockIndexedDBDatabaseCallbacks> db_callbacks(
@@ -273,7 +284,8 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
EXPECT_TRUE(factory->IsBackingStoreOpen(kTestOrigin));
// Simulate the write failure.
- callbacks->connection()->database()->TransactionCommitFailed();
+ leveldb::Status status = leveldb::Status::IOError("Simulated failure");
+ callbacks->connection()->database()->TransactionCommitFailed(status);
EXPECT_TRUE(db_callbacks->forced_close_called());
EXPECT_FALSE(factory->IsBackingStoreOpen(kTestOrigin));
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 16f4fc79c61..5f48cbef60e 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -16,14 +16,16 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
-#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
+#include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h"
#include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/env_idb.h"
#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/env.h"
+#include "third_party/leveldatabase/src/include/leveldb/filter_policy.h"
#include "third_party/leveldatabase/src/include/leveldb/slice.h"
using base::StringPiece;
@@ -89,14 +91,18 @@ LevelDBDatabase::~LevelDBDatabase() {
env_.reset();
}
-static leveldb::Status OpenDB(leveldb::Comparator* comparator,
- leveldb::Env* env,
- const base::FilePath& path,
- leveldb::DB** db) {
+static leveldb::Status OpenDB(
+ leveldb::Comparator* comparator,
+ leveldb::Env* env,
+ const base::FilePath& path,
+ leveldb::DB** db,
+ scoped_ptr<const leveldb::FilterPolicy>* filter_policy) {
+ filter_policy->reset(leveldb::NewBloomFilterPolicy(10));
leveldb::Options options;
options.comparator = comparator;
options.create_if_missing = true;
options.paranoid_checks = true;
+ options.filter_policy = filter_policy->get();
options.compression = leveldb::kSnappyCompression;
// For info about the troubles we've run into with this parameter, see:
@@ -105,7 +111,9 @@ static leveldb::Status OpenDB(leveldb::Comparator* comparator,
options.env = env;
// ChromiumEnv assumes UTF8, converts back to FilePath before using.
- return leveldb::DB::Open(options, path.AsUTF8Unsafe(), db);
+ leveldb::Status s = leveldb::DB::Open(options, path.AsUTF8Unsafe(), db);
+
+ return s;
}
leveldb::Status LevelDBDatabase::Destroy(const base::FilePath& file_name) {
@@ -120,7 +128,8 @@ class LockImpl : public LevelDBLock {
public:
explicit LockImpl(leveldb::Env* env, leveldb::FileLock* lock)
: env_(env), lock_(lock) {}
- virtual ~LockImpl() { env_->UnlockFile(lock_); }
+ ~LockImpl() override { env_->UnlockFile(lock_); }
+
private:
leveldb::Env* env_;
leveldb::FileLock* lock_;
@@ -263,12 +272,18 @@ leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
const LevelDBComparator* comparator,
scoped_ptr<LevelDBDatabase>* result,
bool* is_disk_full) {
+ base::TimeTicks begin_time = base::TimeTicks::Now();
+
scoped_ptr<ComparatorAdapter> comparator_adapter(
new ComparatorAdapter(comparator));
leveldb::DB* db;
- const leveldb::Status s =
- OpenDB(comparator_adapter.get(), leveldb::IDBEnv(), file_name, &db);
+ scoped_ptr<const leveldb::FilterPolicy> filter_policy;
+ const leveldb::Status s = OpenDB(comparator_adapter.get(),
+ leveldb::IDBEnv(),
+ file_name,
+ &db,
+ &filter_policy);
if (!s.ok()) {
HistogramLevelDBError("WebCore.IndexedDB.LevelDBOpenErrors", s);
@@ -283,12 +298,16 @@ leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
return s;
}
+ UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.LevelDB.OpenTime",
+ base::TimeTicks::Now() - begin_time);
+
CheckFreeSpace("Success", file_name);
(*result).reset(new LevelDBDatabase);
(*result)->db_ = make_scoped_ptr(db);
(*result)->comparator_adapter_ = comparator_adapter.Pass();
(*result)->comparator_ = comparator;
+ (*result)->filter_policy_ = filter_policy.Pass();
return s;
}
@@ -300,8 +319,12 @@ scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
scoped_ptr<leveldb::Env> in_memory_env(leveldb::NewMemEnv(leveldb::IDBEnv()));
leveldb::DB* db;
- const leveldb::Status s = OpenDB(
- comparator_adapter.get(), in_memory_env.get(), base::FilePath(), &db);
+ scoped_ptr<const leveldb::FilterPolicy> filter_policy;
+ const leveldb::Status s = OpenDB(comparator_adapter.get(),
+ in_memory_env.get(),
+ base::FilePath(),
+ &db,
+ &filter_policy);
if (!s.ok()) {
LOG(ERROR) << "Failed to open in-memory LevelDB database: " << s.ToString();
@@ -313,12 +336,15 @@ scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
result->db_ = make_scoped_ptr(db);
result->comparator_adapter_ = comparator_adapter.Pass();
result->comparator_ = comparator;
+ result->filter_policy_ = filter_policy.Pass();
return result.Pass();
}
leveldb::Status LevelDBDatabase::Put(const StringPiece& key,
std::string* value) {
+ base::TimeTicks begin_time = base::TimeTicks::Now();
+
leveldb::WriteOptions write_options;
write_options.sync = kSyncWrites;
@@ -326,6 +352,9 @@ leveldb::Status LevelDBDatabase::Put(const StringPiece& key,
db_->Put(write_options, MakeSlice(key), MakeSlice(*value));
if (!s.ok())
LOG(ERROR) << "LevelDB put failed: " << s.ToString();
+ else
+ UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.PutTime",
+ base::TimeTicks::Now() - begin_time);
return s;
}
@@ -362,6 +391,7 @@ leveldb::Status LevelDBDatabase::Get(const StringPiece& key,
}
leveldb::Status LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) {
+ base::TimeTicks begin_time = base::TimeTicks::Now();
leveldb::WriteOptions write_options;
write_options.sync = kSyncWrites;
@@ -370,81 +400,13 @@ leveldb::Status LevelDBDatabase::Write(const LevelDBWriteBatch& write_batch) {
if (!s.ok()) {
HistogramLevelDBError("WebCore.IndexedDB.LevelDBWriteErrors", s);
LOG(ERROR) << "LevelDB write failed: " << s.ToString();
+ } else {
+ UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.WriteTime",
+ base::TimeTicks::Now() - begin_time);
}
return s;
}
-namespace {
-class IteratorImpl : public LevelDBIterator {
- public:
- virtual ~IteratorImpl() {}
-
- virtual bool IsValid() const OVERRIDE;
- virtual leveldb::Status SeekToLast() OVERRIDE;
- virtual leveldb::Status Seek(const StringPiece& target) OVERRIDE;
- virtual leveldb::Status Next() OVERRIDE;
- virtual leveldb::Status Prev() OVERRIDE;
- virtual StringPiece Key() const OVERRIDE;
- virtual StringPiece Value() const OVERRIDE;
-
- private:
- friend class content::LevelDBDatabase;
- explicit IteratorImpl(scoped_ptr<leveldb::Iterator> iterator);
- void CheckStatus();
-
- scoped_ptr<leveldb::Iterator> iterator_;
-
- DISALLOW_COPY_AND_ASSIGN(IteratorImpl);
-};
-} // namespace
-
-IteratorImpl::IteratorImpl(scoped_ptr<leveldb::Iterator> it)
- : iterator_(it.Pass()) {}
-
-void IteratorImpl::CheckStatus() {
- const leveldb::Status& s = iterator_->status();
- if (!s.ok())
- LOG(ERROR) << "LevelDB iterator error: " << s.ToString();
-}
-
-bool IteratorImpl::IsValid() const { return iterator_->Valid(); }
-
-leveldb::Status IteratorImpl::SeekToLast() {
- iterator_->SeekToLast();
- CheckStatus();
- return iterator_->status();
-}
-
-leveldb::Status IteratorImpl::Seek(const StringPiece& target) {
- iterator_->Seek(MakeSlice(target));
- CheckStatus();
- return iterator_->status();
-}
-
-leveldb::Status IteratorImpl::Next() {
- DCHECK(IsValid());
- iterator_->Next();
- CheckStatus();
- return iterator_->status();
-}
-
-leveldb::Status IteratorImpl::Prev() {
- DCHECK(IsValid());
- iterator_->Prev();
- CheckStatus();
- return iterator_->status();
-}
-
-StringPiece IteratorImpl::Key() const {
- DCHECK(IsValid());
- return MakeStringPiece(iterator_->key());
-}
-
-StringPiece IteratorImpl::Value() const {
- DCHECK(IsValid());
- return MakeStringPiece(iterator_->value());
-}
-
scoped_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator(
const LevelDBSnapshot* snapshot) {
leveldb::ReadOptions read_options;
@@ -453,7 +415,8 @@ scoped_ptr<LevelDBIterator> LevelDBDatabase::CreateIterator(
read_options.snapshot = snapshot ? snapshot->snapshot_ : 0;
scoped_ptr<leveldb::Iterator> i(db_->NewIterator(read_options));
- return scoped_ptr<LevelDBIterator>(new IteratorImpl(i.Pass()));
+ return scoped_ptr<LevelDBIterator>(
+ IndexedDBClassFactory::Get()->CreateIteratorImpl(i.Pass()));
}
const LevelDBComparator* LevelDBDatabase::Comparator() const {
@@ -464,6 +427,8 @@ void LevelDBDatabase::Compact(const base::StringPiece& start,
const base::StringPiece& stop) {
const leveldb::Slice start_slice = MakeSlice(start);
const leveldb::Slice stop_slice = MakeSlice(stop);
+ // NULL batch means just wait for earlier writes to be done
+ db_->Write(leveldb::WriteOptions(), NULL);
db_->CompactRange(&start_slice, &stop_slice);
}
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index f6bf7bed5bf..ddc6aa5c100 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -18,6 +18,7 @@
namespace leveldb {
class Comparator;
class DB;
+class FilterPolicy;
class Env;
class Snapshot;
}
@@ -58,15 +59,14 @@ class CONTENT_EXPORT LevelDBDatabase {
public:
explicit ComparatorAdapter(const LevelDBComparator* comparator);
- virtual int Compare(const leveldb::Slice& a,
- const leveldb::Slice& b) const OVERRIDE;
+ int Compare(const leveldb::Slice& a,
+ const leveldb::Slice& b) const override;
- virtual const char* Name() const OVERRIDE;
+ const char* Name() const override;
- virtual void FindShortestSeparator(std::string* start,
- const leveldb::Slice& limit) const
- OVERRIDE;
- virtual void FindShortSuccessor(std::string* key) const OVERRIDE;
+ void FindShortestSeparator(std::string* start,
+ const leveldb::Slice& limit) const override;
+ void FindShortSuccessor(std::string* key) const override;
private:
const LevelDBComparator* comparator_;
@@ -104,6 +104,7 @@ class CONTENT_EXPORT LevelDBDatabase {
scoped_ptr<leveldb::Env> env_;
scoped_ptr<leveldb::Comparator> comparator_adapter_;
scoped_ptr<leveldb::DB> db_;
+ scoped_ptr<const leveldb::FilterPolicy> filter_policy_;
const LevelDBComparator* comparator_;
};
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_factory.h b/chromium/content/browser/indexed_db/leveldb/leveldb_factory.h
new file mode 100644
index 00000000000..31974ee9098
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_factory.h
@@ -0,0 +1,33 @@
+// Copyright 2014 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 CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_FACTORY_H_
+#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_FACTORY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/status.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace content {
+
+class LevelDBComparator;
+class LevelDBDatabase;
+
+class CONTENT_EXPORT LevelDBFactory {
+ public:
+ virtual ~LevelDBFactory() {}
+ virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full) = 0;
+ virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_FACTORY_H_
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator.h b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator.h
index 1069a8b0a3c..d5efa4bf519 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator.h
@@ -6,11 +6,12 @@
#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ITERATOR_H_
#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
namespace content {
-class LevelDBIterator {
+class CONTENT_EXPORT LevelDBIterator {
public:
virtual ~LevelDBIterator() {}
virtual bool IsValid() const = 0;
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc
new file mode 100644
index 00000000000..46c99f4b60b
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 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/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h"
+
+static leveldb::Slice MakeSlice(const base::StringPiece& s) {
+ return leveldb::Slice(s.begin(), s.size());
+}
+
+static base::StringPiece MakeStringPiece(const leveldb::Slice& s) {
+ return base::StringPiece(s.data(), s.size());
+}
+
+namespace content {
+
+LevelDBIteratorImpl::~LevelDBIteratorImpl() {
+}
+
+LevelDBIteratorImpl::LevelDBIteratorImpl(scoped_ptr<leveldb::Iterator> it)
+ : iterator_(it.Pass()) {
+}
+
+void LevelDBIteratorImpl::CheckStatus() {
+ const leveldb::Status& s = iterator_->status();
+ if (!s.ok())
+ LOG(ERROR) << "LevelDB iterator error: " << s.ToString();
+}
+
+bool LevelDBIteratorImpl::IsValid() const {
+ return iterator_->Valid();
+}
+
+leveldb::Status LevelDBIteratorImpl::SeekToLast() {
+ iterator_->SeekToLast();
+ CheckStatus();
+ return iterator_->status();
+}
+
+leveldb::Status LevelDBIteratorImpl::Seek(const base::StringPiece& target) {
+ iterator_->Seek(MakeSlice(target));
+ CheckStatus();
+ return iterator_->status();
+}
+
+leveldb::Status LevelDBIteratorImpl::Next() {
+ DCHECK(IsValid());
+ iterator_->Next();
+ CheckStatus();
+ return iterator_->status();
+}
+
+leveldb::Status LevelDBIteratorImpl::Prev() {
+ DCHECK(IsValid());
+ iterator_->Prev();
+ CheckStatus();
+ return iterator_->status();
+}
+
+base::StringPiece LevelDBIteratorImpl::Key() const {
+ DCHECK(IsValid());
+ return MakeStringPiece(iterator_->key());
+}
+
+base::StringPiece LevelDBIteratorImpl::Value() const {
+ DCHECK(IsValid());
+ return MakeStringPiece(iterator_->value());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h
new file mode 100644
index 00000000000..72b92e0f93b
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_iterator_impl.h
@@ -0,0 +1,42 @@
+// Copyright 2014 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 CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ITERATOR_IMPL_H_
+#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ITERATOR_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
+#include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
+
+namespace content {
+
+class CONTENT_EXPORT LevelDBIteratorImpl : public content::LevelDBIterator {
+ public:
+ ~LevelDBIteratorImpl() override;
+ bool IsValid() const override;
+ leveldb::Status SeekToLast() override;
+ leveldb::Status Seek(const base::StringPiece& target) override;
+ leveldb::Status Next() override;
+ leveldb::Status Prev() override;
+ base::StringPiece Key() const override;
+ base::StringPiece Value() const override;
+
+ protected:
+ explicit LevelDBIteratorImpl(scoped_ptr<leveldb::Iterator> iterator);
+
+ private:
+ void CheckStatus();
+
+ friend class IndexedDBClassFactory;
+ friend class MockBrowserTestIndexedDBClassFactory;
+
+ scoped_ptr<leveldb::Iterator> iterator_;
+
+ DISALLOW_COPY_AND_ASSIGN(LevelDBIteratorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_LEVELDB_ITERATOR_IMPL_H_
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
index e20d404c3c5..a9e71093322 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.cc
@@ -5,6 +5,8 @@
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/time/time.h"
#include "content/browser/indexed_db/leveldb/leveldb_database.h"
#include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -25,9 +27,8 @@ LevelDBTransaction::Record::Record() : deleted(false) {}
LevelDBTransaction::Record::~Record() {}
void LevelDBTransaction::Clear() {
- for (DataType::iterator it = data_.begin(); it != data_.end(); ++it) {
- delete it->second;
- }
+ for (const auto& it : data_)
+ delete it.second;
data_.clear();
}
@@ -93,20 +94,22 @@ leveldb::Status LevelDBTransaction::Commit() {
return leveldb::Status::OK();
}
+ base::TimeTicks begin_time = base::TimeTicks::Now();
scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create();
- for (DataType::iterator iterator = data_.begin(); iterator != data_.end();
- ++iterator) {
- if (!iterator->second->deleted)
- write_batch->Put(iterator->first, iterator->second->value);
+ for (const auto& iterator : data_) {
+ if (!iterator.second->deleted)
+ write_batch->Put(iterator.first, iterator.second->value);
else
- write_batch->Remove(iterator->first);
+ write_batch->Remove(iterator.first);
}
leveldb::Status s = db_->Write(*write_batch);
if (s.ok()) {
Clear();
finished_ = true;
+ UMA_HISTOGRAM_TIMES("WebCore.IndexedDB.LevelDB.Transaction.CommitTime",
+ base::TimeTicks::Now() - begin_time);
}
return s;
}
@@ -118,7 +121,7 @@ void LevelDBTransaction::Rollback() {
}
scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() {
- return TransactionIterator::Create(this).PassAs<LevelDBIterator>();
+ return TransactionIterator::Create(this);
}
scoped_ptr<LevelDBTransaction::DataIterator>
@@ -439,12 +442,8 @@ void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) {
}
void LevelDBTransaction::NotifyIterators() {
- for (std::set<TransactionIterator*>::iterator i = iterators_.begin();
- i != iterators_.end();
- ++i) {
- TransactionIterator* transaction_iterator = *i;
+ for (auto* transaction_iterator : iterators_)
transaction_iterator->DataChanged();
- }
}
scoped_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create(
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
index f6b5a95e121..28d76569374 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_transaction.h
@@ -24,7 +24,6 @@ class LevelDBWriteBatch;
class CONTENT_EXPORT LevelDBTransaction
: public base::RefCounted<LevelDBTransaction> {
public:
-
void Put(const base::StringPiece& key, std::string* value);
void Remove(const base::StringPiece& key);
virtual leveldb::Status Get(const base::StringPiece& key,
@@ -72,15 +71,15 @@ class CONTENT_EXPORT LevelDBTransaction
class DataIterator : public LevelDBIterator {
public:
static scoped_ptr<DataIterator> Create(LevelDBTransaction* transaction);
- virtual ~DataIterator();
-
- virtual bool IsValid() const OVERRIDE;
- virtual leveldb::Status SeekToLast() OVERRIDE;
- virtual leveldb::Status Seek(const base::StringPiece& slice) OVERRIDE;
- virtual leveldb::Status Next() OVERRIDE;
- virtual leveldb::Status Prev() OVERRIDE;
- virtual base::StringPiece Key() const OVERRIDE;
- virtual base::StringPiece Value() const OVERRIDE;
+ ~DataIterator() override;
+
+ bool IsValid() const override;
+ leveldb::Status SeekToLast() override;
+ leveldb::Status Seek(const base::StringPiece& slice) override;
+ leveldb::Status Next() override;
+ leveldb::Status Prev() override;
+ base::StringPiece Key() const override;
+ base::StringPiece Value() const override;
bool IsDeleted() const;
private:
@@ -93,20 +92,22 @@ class CONTENT_EXPORT LevelDBTransaction
class TransactionIterator : public LevelDBIterator {
public:
- virtual ~TransactionIterator();
+ ~TransactionIterator() override;
static scoped_ptr<TransactionIterator> Create(
scoped_refptr<LevelDBTransaction> transaction);
- virtual bool IsValid() const OVERRIDE;
- virtual leveldb::Status SeekToLast() OVERRIDE;
- virtual leveldb::Status Seek(const base::StringPiece& target) OVERRIDE;
- virtual leveldb::Status Next() OVERRIDE;
- virtual leveldb::Status Prev() OVERRIDE;
- virtual base::StringPiece Key() const OVERRIDE;
- virtual base::StringPiece Value() const OVERRIDE;
+ bool IsValid() const override;
+ leveldb::Status SeekToLast() override;
+ leveldb::Status Seek(const base::StringPiece& target) override;
+ leveldb::Status Next() override;
+ leveldb::Status Prev() override;
+ base::StringPiece Key() const override;
+ base::StringPiece Value() const override;
void DataChanged();
private:
+ enum Direction { FORWARD, REVERSE };
+
explicit TransactionIterator(scoped_refptr<LevelDBTransaction> transaction);
void HandleConflictsAndDeletes();
void SetCurrentIteratorToSmallestKey();
@@ -121,10 +122,6 @@ class CONTENT_EXPORT LevelDBTransaction
scoped_ptr<LevelDBIterator> db_iterator_;
LevelDBIterator* current_;
- enum Direction {
- FORWARD,
- REVERSE
- };
Direction direction_;
mutable bool data_changed_;
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
index 83fdd59b878..7c649872a2d 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_unittest.cc
@@ -25,12 +25,12 @@ namespace {
class SimpleComparator : public LevelDBComparator {
public:
- virtual int Compare(const base::StringPiece& a,
- const base::StringPiece& b) const OVERRIDE {
+ int Compare(const base::StringPiece& a,
+ const base::StringPiece& b) const override {
size_t len = std::min(a.size(), b.size());
return memcmp(a.begin(), b.begin(), len);
}
- virtual const char* Name() const OVERRIDE { return "temp_comparator"; }
+ const char* Name() const override { return "temp_comparator"; }
};
} // namespace
@@ -51,7 +51,7 @@ TEST(LevelDBDatabaseTest, CorruptionTest) {
put_value = value;
leveldb::Status status = leveldb->Put(key, &put_value);
EXPECT_TRUE(status.ok());
- leveldb.Pass();
+ leveldb.reset();
EXPECT_FALSE(leveldb);
LevelDBDatabase::Open(temp_directory.path(), &comparator, &leveldb);
@@ -61,7 +61,7 @@ TEST(LevelDBDatabaseTest, CorruptionTest) {
EXPECT_TRUE(status.ok());
EXPECT_TRUE(found);
EXPECT_EQ(value, got_value);
- leveldb.Pass();
+ leveldb.reset();
EXPECT_FALSE(leveldb);
base::FilePath file_path = temp_directory.path().AppendASCII("CURRENT");
diff --git a/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.cc b/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.cc
new file mode 100644
index 00000000000..61ff10b85b2
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.cc
@@ -0,0 +1,14 @@
+// Copyright 2014 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 "content/browser/indexed_db/leveldb/mock_leveldb_factory.h"
+
+namespace content {
+
+MockLevelDBFactory::MockLevelDBFactory() {
+}
+
+MockLevelDBFactory::~MockLevelDBFactory() {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h b/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h
new file mode 100644
index 00000000000..dacb86081d0
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb/mock_leveldb_factory.h
@@ -0,0 +1,29 @@
+// Copyright 2014 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 CONTENT_BROWSER_INDEXED_DB_LEVELDB_MOCK_LEVELDB_FACTORY_H_
+#define CONTENT_BROWSER_INDEXED_DB_LEVELDB_MOCK_LEVELDB_FACTORY_H_
+
+#include "base/files/file_path.h"
+#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace content {
+
+class MockLevelDBFactory : public LevelDBFactory {
+ public:
+ MockLevelDBFactory();
+ ~MockLevelDBFactory();
+ MOCK_METHOD4(OpenLevelDB,
+ leveldb::Status(const base::FilePath& file_name,
+ const LevelDBComparator* comparator,
+ scoped_ptr<LevelDBDatabase>* db,
+ bool* is_disk_full));
+ MOCK_METHOD1(DestroyLevelDB,
+ leveldb::Status(const base::FilePath& file_name));
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_LEVELDB_MOCK_LEVELDB_FACTORY_H_
diff --git a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
index 0014070b3a2..a683f3759fb 100644
--- a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
+++ b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc
@@ -5,6 +5,7 @@
#include <string>
#include "base/logging.h"
+#include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h"
#include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
#include "content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
@@ -51,9 +52,9 @@ class LevelDBTestTansaction : public LevelDBTransaction {
DCHECK_GT(fail_on_call_num, 0);
}
- virtual leveldb::Status Get(const base::StringPiece& key,
- std::string* value,
- bool* found) OVERRIDE {
+ leveldb::Status Get(const base::StringPiece& key,
+ std::string* value,
+ bool* found) override {
if (fail_method_ != FAIL_METHOD_GET ||
++current_call_num_ != fail_on_call_num_)
return LevelDBTransaction::Get(key, value, found);
@@ -62,7 +63,7 @@ class LevelDBTestTansaction : public LevelDBTransaction {
return leveldb::Status::Corruption("Corrupted for the test");
}
- virtual leveldb::Status Commit() OVERRIDE {
+ leveldb::Status Commit() override {
if (fail_method_ != FAIL_METHOD_COMMIT ||
++current_call_num_ != fail_on_call_num_)
return LevelDBTransaction::Commit();
@@ -71,7 +72,7 @@ class LevelDBTestTansaction : public LevelDBTransaction {
}
private:
- virtual ~LevelDBTestTansaction() {}
+ ~LevelDBTestTansaction() override {}
FailMethod fail_method_;
int fail_on_call_num_;
@@ -85,22 +86,22 @@ class LevelDBTraceTansaction : public LevelDBTransaction {
commit_tracer_(s_class_name, "Commit", tx_num),
get_tracer_(s_class_name, "Get", tx_num) {}
- virtual leveldb::Status Get(const base::StringPiece& key,
- std::string* value,
- bool* found) OVERRIDE {
+ leveldb::Status Get(const base::StringPiece& key,
+ std::string* value,
+ bool* found) override {
get_tracer_.log_call();
return LevelDBTransaction::Get(key, value, found);
}
- virtual leveldb::Status Commit() OVERRIDE {
+ leveldb::Status Commit() override {
commit_tracer_.log_call();
return LevelDBTransaction::Commit();
}
private:
- virtual ~LevelDBTraceTansaction() {}
+ static const std::string s_class_name;
- const static std::string s_class_name;
+ ~LevelDBTraceTansaction() override {}
FunctionTracer commit_tracer_;
FunctionTracer get_tracer_;
@@ -108,6 +109,86 @@ class LevelDBTraceTansaction : public LevelDBTransaction {
const std::string LevelDBTraceTansaction::s_class_name = "LevelDBTransaction";
+class LevelDBTraceIteratorImpl : public LevelDBIteratorImpl {
+ public:
+ LevelDBTraceIteratorImpl(scoped_ptr<leveldb::Iterator> iterator, int inst_num)
+ : LevelDBIteratorImpl(iterator.Pass()),
+ is_valid_tracer_(s_class_name, "IsValid", inst_num),
+ seek_to_last_tracer_(s_class_name, "SeekToLast", inst_num),
+ seek_tracer_(s_class_name, "Seek", inst_num),
+ next_tracer_(s_class_name, "Next", inst_num),
+ prev_tracer_(s_class_name, "Prev", inst_num),
+ key_tracer_(s_class_name, "Key", inst_num),
+ value_tracer_(s_class_name, "Value", inst_num) {}
+ ~LevelDBTraceIteratorImpl() override {}
+
+ private:
+ static const std::string s_class_name;
+
+ bool IsValid() const override {
+ is_valid_tracer_.log_call();
+ return LevelDBIteratorImpl::IsValid();
+ }
+ leveldb::Status SeekToLast() override {
+ seek_to_last_tracer_.log_call();
+ return LevelDBIteratorImpl::SeekToLast();
+ }
+ leveldb::Status Seek(const base::StringPiece& target) override {
+ seek_tracer_.log_call();
+ return LevelDBIteratorImpl::Seek(target);
+ }
+ leveldb::Status Next() override {
+ next_tracer_.log_call();
+ return LevelDBIteratorImpl::Next();
+ }
+ leveldb::Status Prev() override {
+ prev_tracer_.log_call();
+ return LevelDBIteratorImpl::Prev();
+ }
+ base::StringPiece Key() const override {
+ key_tracer_.log_call();
+ return LevelDBIteratorImpl::Key();
+ }
+ base::StringPiece Value() const override {
+ value_tracer_.log_call();
+ return LevelDBIteratorImpl::Value();
+ }
+
+ mutable FunctionTracer is_valid_tracer_;
+ mutable FunctionTracer seek_to_last_tracer_;
+ mutable FunctionTracer seek_tracer_;
+ mutable FunctionTracer next_tracer_;
+ mutable FunctionTracer prev_tracer_;
+ mutable FunctionTracer key_tracer_;
+ mutable FunctionTracer value_tracer_;
+};
+
+const std::string LevelDBTraceIteratorImpl::s_class_name = "LevelDBIterator";
+
+class LevelDBTestIteratorImpl : public content::LevelDBIteratorImpl {
+ public:
+ LevelDBTestIteratorImpl(scoped_ptr<leveldb::Iterator> iterator,
+ FailMethod fail_method,
+ int fail_on_call_num)
+ : LevelDBIteratorImpl(iterator.Pass()),
+ fail_method_(fail_method),
+ fail_on_call_num_(fail_on_call_num),
+ current_call_num_(0) {}
+ ~LevelDBTestIteratorImpl() override {}
+
+ private:
+ leveldb::Status Seek(const base::StringPiece& target) override {
+ if (fail_method_ != FAIL_METHOD_SEEK ||
+ ++current_call_num_ != fail_on_call_num_)
+ return LevelDBIteratorImpl::Seek(target);
+ return leveldb::Status::Corruption("Corrupted for test");
+ }
+
+ FailMethod fail_method_;
+ int fail_on_call_num_;
+ int current_call_num_;
+};
+
MockBrowserTestIndexedDBClassFactory::MockBrowserTestIndexedDBClassFactory()
: failure_class_(FAIL_CLASS_NOTHING),
failure_method_(FAIL_METHOD_NOTHING),
@@ -139,6 +220,27 @@ MockBrowserTestIndexedDBClassFactory::CreateLevelDBTransaction(
}
}
+LevelDBIteratorImpl* MockBrowserTestIndexedDBClassFactory::CreateIteratorImpl(
+ scoped_ptr<leveldb::Iterator> iterator) {
+ instance_count_[FAIL_CLASS_LEVELDB_ITERATOR] =
+ instance_count_[FAIL_CLASS_LEVELDB_ITERATOR] + 1;
+ if (only_trace_calls_) {
+ return new LevelDBTraceIteratorImpl(
+ iterator.Pass(), instance_count_[FAIL_CLASS_LEVELDB_ITERATOR]);
+ } else {
+ if (failure_class_ == FAIL_CLASS_LEVELDB_ITERATOR &&
+ instance_count_[FAIL_CLASS_LEVELDB_ITERATOR] ==
+ fail_on_instance_num_[FAIL_CLASS_LEVELDB_ITERATOR]) {
+ return new LevelDBTestIteratorImpl(
+ iterator.Pass(),
+ failure_method_,
+ fail_on_call_num_[FAIL_CLASS_LEVELDB_ITERATOR]);
+ } else {
+ return new LevelDBIteratorImpl(iterator.Pass());
+ }
+ }
+}
+
void MockBrowserTestIndexedDBClassFactory::FailOperation(
FailClass failure_class,
FailMethod failure_method,
diff --git a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
index b30f150cb4a..9e40b60a90a 100644
--- a/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
+++ b/chromium/content/browser/indexed_db/mock_browsertest_indexed_db_class_factory.h
@@ -16,6 +16,7 @@ class LevelDBDatabase;
enum FailClass {
FAIL_CLASS_NOTHING,
+ FAIL_CLASS_LEVELDB_ITERATOR,
FAIL_CLASS_LEVELDB_TRANSACTION,
};
@@ -23,14 +24,16 @@ enum FailMethod {
FAIL_METHOD_NOTHING,
FAIL_METHOD_COMMIT,
FAIL_METHOD_GET,
+ FAIL_METHOD_SEEK,
};
class MockBrowserTestIndexedDBClassFactory : public IndexedDBClassFactory {
public:
MockBrowserTestIndexedDBClassFactory();
- virtual ~MockBrowserTestIndexedDBClassFactory();
- virtual LevelDBTransaction* CreateLevelDBTransaction(
- LevelDBDatabase* db) OVERRIDE;
+ ~MockBrowserTestIndexedDBClassFactory() override;
+ LevelDBTransaction* CreateLevelDBTransaction(LevelDBDatabase* db) override;
+ LevelDBIteratorImpl* CreateIteratorImpl(
+ scoped_ptr<leveldb::Iterator> iterator) override;
void FailOperation(FailClass failure_class,
FailMethod failure_method,
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
index fecfd1abb29..24743fe0b32 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_callbacks.h
@@ -17,16 +17,16 @@ class MockIndexedDBCallbacks : public IndexedDBCallbacks {
MockIndexedDBCallbacks();
explicit MockIndexedDBCallbacks(bool expect_connection);
- virtual void OnSuccess() OVERRIDE;
- virtual void OnSuccess(int64 result) OVERRIDE;
- virtual void OnSuccess(const std::vector<base::string16>& result) OVERRIDE;
- virtual void OnSuccess(const IndexedDBKey& key) OVERRIDE;
- virtual void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
- const IndexedDBDatabaseMetadata& metadata) OVERRIDE;
+ void OnSuccess() override;
+ void OnSuccess(int64 result) override;
+ void OnSuccess(const std::vector<base::string16>& result) override;
+ void OnSuccess(const IndexedDBKey& key) override;
+ void OnSuccess(scoped_ptr<IndexedDBConnection> connection,
+ const IndexedDBDatabaseMetadata& metadata) override;
IndexedDBConnection* connection() { return connection_.get(); }
protected:
- virtual ~MockIndexedDBCallbacks();
+ ~MockIndexedDBCallbacks() override;
scoped_ptr<IndexedDBConnection> connection_;
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
index 7252a9fde0a..31a29645a25 100644
--- a/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_database_callbacks.h
@@ -14,17 +14,17 @@ class MockIndexedDBDatabaseCallbacks : public IndexedDBDatabaseCallbacks {
public:
MockIndexedDBDatabaseCallbacks();
- virtual void OnVersionChange(int64 old_version, int64 new_version) OVERRIDE {}
- virtual void OnForcedClose() OVERRIDE;
- virtual void OnAbort(int64 transaction_id,
- const IndexedDBDatabaseError& error) OVERRIDE;
- virtual void OnComplete(int64 transaction_id) OVERRIDE {}
+ void OnVersionChange(int64 old_version, int64 new_version) override {}
+ void OnForcedClose() override;
+ void OnAbort(int64 transaction_id,
+ const IndexedDBDatabaseError& error) override;
+ void OnComplete(int64 transaction_id) override {}
bool abort_called() const { return abort_called_; }
bool forced_close_called() const { return forced_close_called_; }
private:
- virtual ~MockIndexedDBDatabaseCallbacks() {}
+ ~MockIndexedDBDatabaseCallbacks() override {}
bool abort_called_;
bool forced_close_called_;
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc b/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc
new file mode 100644
index 00000000000..1c95226f6e4
--- /dev/null
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.cc
@@ -0,0 +1,20 @@
+// Copyright 2014 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 "content/browser/indexed_db/mock_indexed_db_factory.h"
+
+namespace content {
+
+MockIndexedDBFactory::MockIndexedDBFactory() {
+}
+
+MockIndexedDBFactory::~MockIndexedDBFactory() {
+}
+
+IndexedDBFactory::OriginDBs MockIndexedDBFactory::GetOpenDatabasesForOrigin(
+ const GURL& origin_url) const {
+ return OriginDBs();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/indexed_db/mock_indexed_db_factory.h b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
new file mode 100644
index 00000000000..6860cfa7da8
--- /dev/null
+++ b/chromium/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -0,0 +1,85 @@
+// Copyright 2014 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 CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_FACTORY_H_
+#define CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_FACTORY_H_
+
+#include <string>
+
+#include "content/browser/indexed_db/indexed_db_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace content {
+
+class MockIndexedDBFactory : public IndexedDBFactory {
+ public:
+ MockIndexedDBFactory();
+ MOCK_METHOD2(ReleaseDatabase,
+ void(const IndexedDBDatabase::Identifier& identifier,
+ bool forcedClose));
+ MOCK_METHOD4(GetDatabaseNames,
+ void(scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context));
+ MOCK_METHOD5(Open,
+ void(const base::string16& name,
+ const IndexedDBPendingConnection& connection,
+ net::URLRequestContext* request_context,
+ const GURL& origin_url,
+ const base::FilePath& data_directory));
+ MOCK_METHOD5(DeleteDatabase,
+ void(const base::string16& name,
+ net::URLRequestContext* request_context,
+ scoped_refptr<IndexedDBCallbacks> callbacks,
+ const GURL& origin_url,
+ const base::FilePath& data_directory));
+ MOCK_METHOD1(HandleBackingStoreFailure, void(const GURL& origin_url));
+ MOCK_METHOD2(HandleBackingStoreCorruption,
+ void(const GURL& origin_url,
+ const IndexedDBDatabaseError& error));
+ // The Android NDK implements a subset of STL, and the gtest templates can't
+ // deal with std::pair's. This means we can't use GoogleMock for this method
+ virtual OriginDBs GetOpenDatabasesForOrigin(
+ const GURL& origin_url) const override;
+ MOCK_METHOD1(ForceClose, void(const GURL& origin_url));
+ MOCK_METHOD0(ContextDestroyed, void());
+ MOCK_METHOD1(DatabaseDeleted,
+ void(const IndexedDBDatabase::Identifier& identifier));
+ MOCK_CONST_METHOD1(GetConnectionCount, size_t(const GURL& origin_url));
+
+ MOCK_METHOD2(ReportOutstandingBlobs,
+ void(const GURL& origin_url, bool blobs_outstanding));
+
+ protected:
+ virtual ~MockIndexedDBFactory();
+
+ MOCK_METHOD7(OpenBackingStore,
+ scoped_refptr<IndexedDBBackingStore>(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_reason,
+ bool* disk_full,
+ leveldb::Status* s));
+
+ MOCK_METHOD8(OpenBackingStoreHelper,
+ scoped_refptr<IndexedDBBackingStore>(
+ const GURL& origin_url,
+ const base::FilePath& data_directory,
+ net::URLRequestContext* request_context,
+ blink::WebIDBDataLoss* data_loss,
+ std::string* data_loss_message,
+ bool* disk_full,
+ bool first_time,
+ leveldb::Status* s));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockIndexedDBFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_INDEXED_DB_MOCK_INDEXED_DB_FACTORY_H_
diff --git a/chromium/content/browser/loader/OWNERS b/chromium/content/browser/loader/OWNERS
index 1e9e8232811..747dc150159 100644
--- a/chromium/content/browser/loader/OWNERS
+++ b/chromium/content/browser/loader/OWNERS
@@ -1,2 +1 @@
-davidben@chromium.org
mmenke@chromium.org \ No newline at end of file
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index 69e831bd298..5125bec8607 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -14,6 +14,7 @@
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
#include "content/browser/devtools/devtools_netlog_observer.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_buffer.h"
@@ -29,6 +30,7 @@
#include "net/base/load_flags.h"
#include "net/base/net_log.h"
#include "net/base/net_util.h"
+#include "net/url_request/redirect_info.h"
using base::TimeTicks;
@@ -41,7 +43,7 @@ static int kMaxAllocationSize = 1024 * 32;
void GetNumericArg(const std::string& name, int* result) {
const std::string& value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
if (!value.empty())
base::StringToInt(value, result);
}
@@ -71,7 +73,7 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
backing_(backing) {
}
private:
- virtual ~DependentIOBuffer() {}
+ ~DependentIOBuffer() override {}
scoped_refptr<ResourceBuffer> backing_;
};
@@ -112,6 +114,13 @@ void AsyncResourceHandler::OnFollowRedirect(int request_id) {
return;
}
+ if (!redirect_start_time_.is_null()) {
+ UMA_HISTOGRAM_TIMES("Net.AsyncResourceHandler_RedirectHopTime",
+ TimeTicks::Now() - redirect_start_time_);
+ // Reset start time.
+ redirect_start_time_ = TimeTicks();
+ }
+
ResumeIfDeferred();
}
@@ -134,19 +143,22 @@ bool AsyncResourceHandler::OnUploadProgress(uint64 position,
new ResourceMsg_UploadProgress(GetRequestID(), position, size));
}
-bool AsyncResourceHandler::OnRequestRedirected(const GURL& new_url,
- ResourceResponse* response,
- bool* defer) {
+bool AsyncResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) {
const ResourceRequestInfoImpl* info = GetRequestInfo();
if (!info->filter())
return false;
+ redirect_start_time_ = TimeTicks::Now();
+
*defer = did_defer_ = true;
OnDefer();
if (rdh_->delegate()) {
rdh_->delegate()->OnRequestRedirected(
- new_url, request(), info->GetContext(), response);
+ redirect_info.new_url, request(), info->GetContext(), response);
}
DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
@@ -159,8 +171,7 @@ bool AsyncResourceHandler::OnRequestRedirected(const GURL& new_url,
// and hopefully those will eventually all be owned by the browser. It's
// possible this is still needed while renderer-owned ones exist.
return info->filter()->Send(new ResourceMsg_ReceivedRedirect(
- GetRequestID(), new_url, request()->first_party_for_cookies(),
- response->head));
+ GetRequestID(), redirect_info, response->head));
}
bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
@@ -185,7 +196,7 @@ bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
HostZoomMap* host_zoom_map =
GetHostZoomMapForResourceContext(info->GetContext());
- if (info->GetResourceType() == ResourceType::MAIN_FRAME && host_zoom_map) {
+ if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME && host_zoom_map) {
const GURL& request_url = request()->url();
info->filter()->Send(new ViewMsg_SetZoomLevelForLoadingURL(
info->GetRouteID(),
diff --git a/chromium/content/browser/loader/async_resource_handler.h b/chromium/content/browser/loader/async_resource_handler.h
index b0821191e0d..e2954f4975a 100644
--- a/chromium/content/browser/loader/async_resource_handler.h
+++ b/chromium/content/browser/loader/async_resource_handler.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
#include "content/browser/loader/resource_handler.h"
#include "content/browser/loader/resource_message_delegate.h"
#include "url/gurl.h"
@@ -30,27 +31,26 @@ class AsyncResourceHandler : public ResourceHandler,
public:
AsyncResourceHandler(net::URLRequest* request,
ResourceDispatcherHostImpl* rdh);
- virtual ~AsyncResourceHandler();
+ ~AsyncResourceHandler() override;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// ResourceHandler implementation:
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
- virtual bool OnRequestRedirected(const GURL& new_url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
+ void OnDataDownloaded(int bytes_downloaded) override;
private:
// IPC message handlers:
@@ -78,6 +78,8 @@ class AsyncResourceHandler : public ResourceHandler,
int64_t reported_transfer_size_;
+ base::TimeTicks redirect_start_time_;
+
DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler);
};
diff --git a/chromium/content/browser/loader/buffered_resource_handler.cc b/chromium/content/browser/loader/buffered_resource_handler.cc
index 8fb8c5d4484..f96b5506d8c 100644
--- a/chromium/content/browser/loader/buffered_resource_handler.cc
+++ b/chromium/content/browser/loader/buffered_resource_handler.cc
@@ -16,7 +16,6 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/loader/stream_resource_handler.h"
-#include "content/browser/plugin_service_impl.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_save_info.h"
@@ -32,6 +31,10 @@
#include "net/http/http_content_disposition.h"
#include "net/http/http_response_headers.h"
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_service_impl.h"
+#endif
+
namespace content {
namespace {
@@ -70,7 +73,7 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
}
private:
- virtual ~DependentIOBuffer() {}
+ ~DependentIOBuffer() override {}
scoped_refptr<net::IOBuffer> buf_;
};
@@ -348,7 +351,7 @@ bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
request(),
true, // is_content_initiated
must_download,
- content::DownloadItem::kInvalidId,
+ DownloadItem::kInvalidId,
scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()),
DownloadUrlParameters::OnStartedCallback()));
return UseAlternateNextHandler(handler.Pass(), std::string());
diff --git a/chromium/content/browser/loader/buffered_resource_handler.h b/chromium/content/browser/loader/buffered_resource_handler.h
index 0b6d6989097..8735359e21e 100644
--- a/chromium/content/browser/loader/buffered_resource_handler.h
+++ b/chromium/content/browser/loader/buffered_resource_handler.h
@@ -28,26 +28,25 @@ class BufferedResourceHandler
BufferedResourceHandler(scoped_ptr<ResourceHandler> next_handler,
ResourceDispatcherHostImpl* host,
net::URLRequest* request);
- virtual ~BufferedResourceHandler();
+ ~BufferedResourceHandler() override;
private:
// ResourceHandler implementation:
- virtual void SetController(ResourceController* controller) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
+ void SetController(ResourceController* controller) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
// ResourceController implementation:
- virtual void Resume() OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual void CancelAndIgnore() OVERRIDE;
- virtual void CancelWithError(int error_code) OVERRIDE;
+ void Resume() override;
+ void Cancel() override;
+ void CancelAndIgnore() override;
+ void CancelWithError(int error_code) override;
bool ProcessResponse(bool* defer);
diff --git a/chromium/content/browser/loader/certificate_resource_handler.cc b/chromium/content/browser/loader/certificate_resource_handler.cc
index 9b3a607eb46..eb1976bef05 100644
--- a/chromium/content/browser/loader/certificate_resource_handler.cc
+++ b/chromium/content/browser/loader/certificate_resource_handler.cc
@@ -12,6 +12,7 @@
#include "net/base/mime_sniffer.h"
#include "net/base/mime_util.h"
#include "net/http/http_response_headers.h"
+#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
@@ -34,10 +35,10 @@ bool CertificateResourceHandler::OnUploadProgress(uint64 position,
return true;
}
-bool CertificateResourceHandler::OnRequestRedirected(const GURL& url,
- ResourceResponse* resp,
- bool* defer) {
- url_ = url;
+bool CertificateResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* resp,
+ bool* defer) {
return true;
}
diff --git a/chromium/content/browser/loader/certificate_resource_handler.h b/chromium/content/browser/loader/certificate_resource_handler.h
index 9c67860eb7e..e8ce4ba4be3 100644
--- a/chromium/content/browser/loader/certificate_resource_handler.h
+++ b/chromium/content/browser/loader/certificate_resource_handler.h
@@ -14,7 +14,6 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/loader/resource_handler.h"
#include "net/base/mime_util.h"
-#include "url/gurl.h"
namespace net {
class IOBuffer;
@@ -32,40 +31,39 @@ namespace content {
class CertificateResourceHandler : public ResourceHandler {
public:
explicit CertificateResourceHandler(net::URLRequest* request);
- virtual ~CertificateResourceHandler();
+ ~CertificateResourceHandler() override;
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
// Not needed, as this event handler ought to be the final resource.
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* resp,
- bool* defer) OVERRIDE;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* resp,
+ bool* defer) override;
// Check if this indeed an X509 cert.
- virtual bool OnResponseStarted(ResourceResponse* resp,
- bool* defer) OVERRIDE;
+ bool OnResponseStarted(ResourceResponse* resp, bool* defer) override;
// Pass-through implementation.
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnWillStart(const GURL& url, bool* defer) override;
// Pass-through implementation.
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
// Create a new buffer to store received data.
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
// A read was completed, maybe allocate a new buffer for further data.
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
// Done downloading the certificate.
- virtual void OnResponseCompleted(const net::URLRequestStatus& urs,
- const std::string& sec_info,
- bool* defer) OVERRIDE;
+ void OnResponseCompleted(const net::URLRequestStatus& urs,
+ const std::string& sec_info,
+ bool* defer) override;
// N/A to cert downloading.
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ void OnDataDownloaded(int bytes_downloaded) override;
private:
typedef std::vector<std::pair<scoped_refptr<net::IOBuffer>,
@@ -73,7 +71,6 @@ class CertificateResourceHandler : public ResourceHandler {
void AssembleResource();
- GURL url_;
size_t content_length_;
ContentVector buffer_;
scoped_refptr<net::IOBuffer> read_buffer_;
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.cc b/chromium/content/browser/loader/cross_site_resource_handler.cc
index 8fa7238c357..2ec5ee56934 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler.cc
@@ -11,11 +11,12 @@
#include "base/logging.h"
#include "content/browser/appcache/appcache_interceptor.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/cross_site_request_manager.h"
#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/site_instance_impl.h"
+#include "content/browser/transition_request_manager.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
@@ -39,14 +40,12 @@ struct CrossSiteResponseParams {
CrossSiteResponseParams(
int render_frame_id,
const GlobalRequestID& global_request_id,
- bool is_transfer,
const std::vector<GURL>& transfer_url_chain,
const Referrer& referrer,
- PageTransition page_transition,
+ ui::PageTransition page_transition,
bool should_replace_current_entry)
: render_frame_id(render_frame_id),
global_request_id(global_request_id),
- is_transfer(is_transfer),
transfer_url_chain(transfer_url_chain),
referrer(referrer),
page_transition(page_transition),
@@ -55,19 +54,15 @@ struct CrossSiteResponseParams {
int render_frame_id;
GlobalRequestID global_request_id;
- bool is_transfer;
std::vector<GURL> transfer_url_chain;
Referrer referrer;
- PageTransition page_transition;
+ ui::PageTransition page_transition;
bool should_replace_current_entry;
};
void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
- scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request;
- if (params.is_transfer) {
- cross_site_transferring_request.reset(new CrossSiteTransferringRequest(
- params.global_request_id));
- }
+ scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request(
+ new CrossSiteTransferringRequest(params.global_request_id));
RenderFrameHostImpl* rfh =
RenderFrameHostImpl::FromID(params.global_request_id.child_id,
@@ -84,12 +79,29 @@ void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
}
}
+void OnDeferredAfterResponseStartedHelper(
+ const GlobalRequestID& global_request_id,
+ int render_frame_id,
+ const TransitionLayerData& transition_data) {
+ RenderFrameHostImpl* rfh =
+ RenderFrameHostImpl::FromID(global_request_id.child_id, render_frame_id);
+ if (rfh)
+ rfh->OnDeferredAfterResponseStarted(global_request_id, transition_data);
+}
+
+// Returns whether a transfer is needed by doing a check on the UI thread.
bool CheckNavigationPolicyOnUI(GURL url, int process_id, int render_frame_id) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess));
RenderFrameHostImpl* rfh =
RenderFrameHostImpl::FromID(process_id, render_frame_id);
if (!rfh)
return false;
+ // A transfer is not needed if the current SiteInstance doesn't yet have a
+ // site. This is the case for tests that use NavigateToURL.
+ if (!rfh->GetSiteInstance()->HasSite())
+ return false;
+
// TODO(nasko): This check is very simplistic and is used temporarily only
// for --site-per-process. It should be updated to match the check performed
// by RenderFrameHostManager::UpdateStateForNavigate.
@@ -117,54 +129,63 @@ CrossSiteResourceHandler::~CrossSiteResourceHandler() {
}
bool CrossSiteResourceHandler::OnRequestRedirected(
- const GURL& new_url,
+ const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) {
- // Top-level requests change their cookie first-party URL on redirects, while
- // subframes retain the parent's value.
- if (GetRequestInfo()->GetResourceType() == ResourceType::MAIN_FRAME)
- request()->set_first_party_for_cookies(new_url);
-
// We should not have started the transition before being redirected.
DCHECK(!in_cross_site_transition_);
- return next_handler_->OnRequestRedirected(new_url, response, defer);
+ return next_handler_->OnRequestRedirected(redirect_info, response, defer);
}
bool CrossSiteResourceHandler::OnResponseStarted(
ResourceResponse* response,
bool* defer) {
+ response_ = response;
+ has_started_response_ = true;
+
+ // Store this handler on the ExtraRequestInfo, so that RDH can call our
+ // ResumeResponse method when we are ready to resume.
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+ info->set_cross_site_handler(this);
+
+ TransitionLayerData transition_data;
+ bool is_navigation_transition =
+ TransitionRequestManager::GetInstance()->GetPendingTransitionRequest(
+ info->GetChildID(), info->GetRenderFrameID(), request()->url(),
+ &transition_data);
+
+ if (is_navigation_transition) {
+ if (response_.get())
+ transition_data.response_headers = response_->head.headers;
+ transition_data.request_url = request()->url();
+
+ return OnNavigationTransitionResponseStarted(response, defer,
+ transition_data);
+ } else {
+ return OnNormalResponseStarted(response, defer);
+ }
+}
+
+bool CrossSiteResourceHandler::OnNormalResponseStarted(
+ ResourceResponse* response,
+ bool* defer) {
// At this point, we know that the response is safe to send back to the
// renderer: it is not a download, and it has passed the SSL and safe
// browsing checks.
// We should not have already started the transition before now.
DCHECK(!in_cross_site_transition_);
- has_started_response_ = true;
ResourceRequestInfoImpl* info = GetRequestInfo();
- // We will need to swap processes if either (1) a redirect that requires a
- // transfer occurred before we got here, or (2) a pending cross-site request
- // was already in progress. Note that a swap may no longer be needed if we
- // transferred back into the original process due to a redirect.
+ // We only need to pause the response if a transfer to a different process is
+ // required. Other cross-process navigations can proceed immediately, since
+ // we run the unload handler at commit time.
+ // Note that a process swap may no longer be necessary if we transferred back
+ // into the original process due to a redirect.
bool should_transfer =
GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
info->GetContext(), request()->original_url(), request()->url());
- // When the --site-per-process flag is passed, we transfer processes for
- // cross-site navigations. This is skipped if a transfer is already required
- // or for WebUI processes for now, since pages like the NTP host multiple
- // cross-site WebUI iframes.
- if (!should_transfer &&
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
- info->GetChildID())) {
- return DeferForNavigationPolicyCheck(info, response, defer);
- }
-
- bool swap_needed = should_transfer ||
- CrossSiteRequestManager::GetInstance()->
- HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID());
-
// If this is a download, just pass the response through without doing a
// cross-site check. The renderer will see it is a download and abort the
// request.
@@ -180,26 +201,72 @@ bool CrossSiteResourceHandler::OnResponseStarted(
//
// TODO(davidben): Unify IsDownload() and is_stream(). Several places need to
// check for both and remembering about streams is error-prone.
- if (!swap_needed || info->IsDownload() || info->is_stream() ||
+ if (info->IsDownload() || info->is_stream() ||
(response->head.headers.get() &&
response->head.headers->response_code() == 204)) {
return next_handler_->OnResponseStarted(response, defer);
}
- // Now that we know a swap is needed and we have something to commit, we
- // pause to let the UI thread run the unload handler of the previous page
- // and set up a transfer if needed.
- StartCrossSiteTransition(response, should_transfer);
+ // When the --site-per-process flag is passed, we transfer processes for
+ // cross-site navigations. This is skipped if a transfer is already required
+ // or for WebUI processes for now, since pages like the NTP host multiple
+ // cross-site WebUI iframes.
+ if (!should_transfer &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess) &&
+ !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
+ info->GetChildID())) {
+ return DeferForNavigationPolicyCheck(info, response, defer);
+ }
- // Defer loading until after the onunload event handler has run.
+ if (!should_transfer)
+ return next_handler_->OnResponseStarted(response, defer);
+
+ // Now that we know a transfer is needed and we have something to commit, we
+ // pause to let the UI thread set up the transfer.
+ StartCrossSiteTransition(response);
+
+ // Defer loading until after the new renderer process has issued a
+ // corresponding request.
*defer = true;
OnDidDefer();
return true;
}
+bool CrossSiteResourceHandler::OnNavigationTransitionResponseStarted(
+ ResourceResponse* response,
+ bool* defer,
+ const TransitionLayerData& transition_data) {
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+
+ GlobalRequestID global_id(info->GetChildID(), info->GetRequestID());
+ int render_frame_id = info->GetRenderFrameID();
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &OnDeferredAfterResponseStartedHelper,
+ global_id,
+ render_frame_id,
+ transition_data));
+
+ *defer = true;
+ OnDidDefer();
+ return true;
+}
+
+void CrossSiteResourceHandler::ResumeResponseDeferredAtStart(int request_id) {
+ bool defer = false;
+ if (!OnNormalResponseStarted(response_.get(), &defer)) {
+ controller()->Cancel();
+ } else if (!defer) {
+ ResumeIfDeferred();
+ }
+}
+
void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) {
if (is_transfer) {
- StartCrossSiteTransition(response_, is_transfer);
+ StartCrossSiteTransition(response_.get());
} else {
ResumeResponse();
}
@@ -215,23 +282,9 @@ void CrossSiteResourceHandler::OnResponseCompleted(
const std::string& security_info,
bool* defer) {
if (!in_cross_site_transition_) {
- ResourceRequestInfoImpl* info = GetRequestInfo();
- // If we've already completed the transition, or we're canceling the
- // request, or an error occurred with no cross-process navigation in
- // progress, then we should just pass this through.
- if (has_started_response_ ||
- status.status() != net::URLRequestStatus::FAILED ||
- !CrossSiteRequestManager::GetInstance()->HasPendingCrossSiteRequest(
- info->GetChildID(), info->GetRouteID())) {
- next_handler_->OnResponseCompleted(status, security_info, defer);
- return;
- }
-
- // An error occurred. We should wait now for the cross-process transition,
- // so that the error message (e.g., 404) can be displayed to the user.
- // Also continue with the logic below to remember that we completed
- // during the cross-site transition.
- StartCrossSiteTransition(NULL, false);
+ // If we're not transferring, then we should pass this through.
+ next_handler_->OnResponseCompleted(status, security_info, defer);
+ return;
}
// We have to buffer the call until after the transition completes.
@@ -248,13 +301,15 @@ void CrossSiteResourceHandler::OnResponseCompleted(
// We can now send the response to the new renderer, which will cause
// WebContentsImpl to swap in the new renderer and destroy the old one.
void CrossSiteResourceHandler::ResumeResponse() {
+ TRACE_EVENT_ASYNC_END0(
+ "navigation", "CrossSiteResourceHandler transition", this);
DCHECK(request());
in_cross_site_transition_ = false;
ResourceRequestInfoImpl* info = GetRequestInfo();
if (has_started_response_) {
// Send OnResponseStarted to the new renderer.
- DCHECK(response_);
+ DCHECK(response_.get());
bool defer = false;
if (!next_handler_->OnResponseStarted(response_.get(), &defer)) {
controller()->Cancel();
@@ -286,11 +341,11 @@ void CrossSiteResourceHandler::SetLeakRequestsForTesting(
leak_requests_for_testing_ = leak_requests_for_testing;
}
-// Prepare to render the cross-site response in a new RenderFrameHost, by
-// telling the old RenderFrameHost to run its onunload handler.
+// Prepare to transfer the response to a new RenderFrameHost.
void CrossSiteResourceHandler::StartCrossSiteTransition(
- ResourceResponse* response,
- bool should_transfer) {
+ ResourceResponse* response) {
+ TRACE_EVENT_ASYNC_BEGIN0(
+ "navigation", "CrossSiteResourceHandler transition", this);
in_cross_site_transition_ = true;
response_ = response;
@@ -310,14 +365,13 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
std::vector<GURL> transfer_url_chain;
Referrer referrer;
int render_frame_id = info->GetRenderFrameID();
- if (should_transfer) {
- transfer_url_chain = request()->url_chain();
- referrer = Referrer(GURL(request()->referrer()), info->GetReferrerPolicy());
+ transfer_url_chain = request()->url_chain();
+ referrer = Referrer(GURL(request()->referrer()), info->GetReferrerPolicy());
+
+ AppCacheInterceptor::PrepareForCrossSiteTransfer(
+ request(), global_id.child_id);
+ ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id);
- AppCacheInterceptor::PrepareForCrossSiteTransfer(
- request(), global_id.child_id);
- ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id);
- }
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -325,7 +379,6 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
&OnCrossSiteResponseHelper,
CrossSiteResponseParams(render_frame_id,
global_id,
- should_transfer,
transfer_url_chain,
referrer,
info->GetPageTransition(),
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.h b/chromium/content/browser/loader/cross_site_resource_handler.h
index 257af02c01b..f0410462996 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_resource_handler.h
@@ -17,28 +17,28 @@ class URLRequest;
namespace content {
-// Ensures that cross-site responses are delayed until the onunload handler of
-// the previous page is allowed to run. This handler wraps an
-// AsyncEventHandler, and it sits inside SafeBrowsing and Buffered event
-// handlers. This is important, so that it can intercept OnResponseStarted
-// after we determine that a response is safe and not a download.
+struct TransitionLayerData;
+
+// Ensures that responses are delayed for navigations that must be transferred
+// to a different process. This handler wraps an AsyncEventHandler, and it sits
+// inside SafeBrowsing and Buffered event handlers. This is important, so that
+// it can intercept OnResponseStarted after we determine that a response is safe
+// and not a download.
class CrossSiteResourceHandler : public LayeredResourceHandler {
public:
CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request);
- virtual ~CrossSiteResourceHandler();
+ ~CrossSiteResourceHandler() override;
// ResourceHandler implementation:
- virtual bool OnRequestRedirected(const GURL& new_url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read,
- bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
// We can now send the response to the new renderer, which will cause
// WebContentsImpl to swap in the new renderer and destroy the old one.
@@ -49,11 +49,18 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
CONTENT_EXPORT static void SetLeakRequestsForTesting(
bool leak_requests_for_testing);
+ // Navigations are deferred at OnResponseStarted to parse out any navigation
+ // transition link headers, and give the navigation transition (if it exists)
+ // a chance to run.
+ void ResumeResponseDeferredAtStart(int request_id);
+
+ // Returns whether the handler is deferred.
+ bool did_defer_for_testing() const { return did_defer_; }
+
private:
- // Prepare to render the cross-site response in a new RenderViewHost, by
- // telling the old RenderViewHost to run its onunload handler.
- void StartCrossSiteTransition(ResourceResponse* response,
- bool should_transfer);
+ // Prepare to transfer the cross-site response to a new RenderFrameHost, by
+ // asking it to issue an identical request (on the UI thread).
+ void StartCrossSiteTransition(ResourceResponse* response);
// Defer the navigation to the UI thread to check whether transfer is required
// or not. Currently only used in --site-per-process.
@@ -61,6 +68,14 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
ResourceResponse* response,
bool* defer);
+ bool OnNavigationTransitionResponseStarted(
+ ResourceResponse* response,
+ bool* defer,
+ const TransitionLayerData& transition_data);
+
+ bool OnNormalResponseStarted(ResourceResponse* response,
+ bool* defer);
+
void ResumeOrTransfer(bool is_transfer);
void ResumeIfDeferred();
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index b8ef55d4fff..ab7e240b1ee 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -9,6 +9,7 @@
#include "content/browser/loader/resource_request_info_impl.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
#include "net/url_request/url_request_status.h"
namespace {
@@ -69,8 +70,12 @@ void DetachableResourceHandler::Detach() {
// Resume if necessary. The request may have been deferred, say, waiting on a
// full buffer in AsyncResourceHandler. Now that it has been detached, resume
// and drain it.
- if (is_deferred_)
+ if (is_deferred_) {
+ // The nested ResourceHandler may have logged that it's blocking the
+ // request. Log it as no longer doing so, to avoid a DCHECK on resume.
+ request()->LogUnblocked();
Resume();
+ }
}
void DetachableResourceHandler::SetController(ResourceController* controller) {
@@ -89,15 +94,17 @@ bool DetachableResourceHandler::OnUploadProgress(uint64 position, uint64 size) {
return next_handler_->OnUploadProgress(position, size);
}
-bool DetachableResourceHandler::OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) {
+bool DetachableResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) {
DCHECK(!is_deferred_);
if (!next_handler_)
return true;
- bool ret = next_handler_->OnRequestRedirected(url, response, &is_deferred_);
+ bool ret = next_handler_->OnRequestRedirected(
+ redirect_info, response, &is_deferred_);
*defer = is_deferred_;
return ret;
}
@@ -144,7 +151,7 @@ bool DetachableResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int min_size) {
if (!next_handler_) {
DCHECK_EQ(-1, min_size);
- if (!read_buffer_)
+ if (!read_buffer_.get())
read_buffer_ = new net::IOBuffer(kReadBufSize);
*buf = read_buffer_;
*buf_size = kReadBufSize;
diff --git a/chromium/content/browser/loader/detachable_resource_handler.h b/chromium/content/browser/loader/detachable_resource_handler.h
index 9a685701a9d..64d23ef2628 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.h
+++ b/chromium/content/browser/loader/detachable_resource_handler.h
@@ -37,7 +37,7 @@ class DetachableResourceHandler : public ResourceHandler,
DetachableResourceHandler(net::URLRequest* request,
base::TimeDelta cancel_delay,
scoped_ptr<ResourceHandler> next_handler);
- virtual ~DetachableResourceHandler();
+ ~DetachableResourceHandler() override;
bool is_detached() const { return next_handler_ == NULL; }
void Detach();
@@ -47,29 +47,28 @@ class DetachableResourceHandler : public ResourceHandler,
}
// ResourceHandler implementation:
- virtual void SetController(ResourceController* controller) OVERRIDE;
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ void SetController(ResourceController* controller) override;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
+ void OnDataDownloaded(int bytes_downloaded) override;
// ResourceController implementation:
- virtual void Resume() OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual void CancelAndIgnore() OVERRIDE;
- virtual void CancelWithError(int error_code) OVERRIDE;
+ void Resume() override;
+ void Cancel() override;
+ void CancelAndIgnore() override;
+ void CancelWithError(int error_code) override;
private:
scoped_ptr<ResourceHandler> next_handler_;
diff --git a/chromium/content/browser/loader/layered_resource_handler.cc b/chromium/content/browser/loader/layered_resource_handler.cc
index 1c65820f610..fa15b0de40f 100644
--- a/chromium/content/browser/loader/layered_resource_handler.cc
+++ b/chromium/content/browser/loader/layered_resource_handler.cc
@@ -35,11 +35,12 @@ bool LayeredResourceHandler::OnUploadProgress(uint64 position,
return next_handler_->OnUploadProgress(position, size);
}
-bool LayeredResourceHandler::OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) {
+bool LayeredResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) {
DCHECK(next_handler_.get());
- return next_handler_->OnRequestRedirected(url, response, defer);
+ return next_handler_->OnRequestRedirected(redirect_info, response, defer);
}
bool LayeredResourceHandler::OnResponseStarted(ResourceResponse* response,
diff --git a/chromium/content/browser/loader/layered_resource_handler.h b/chromium/content/browser/loader/layered_resource_handler.h
index dc6de2314dc..0c098f9a8d7 100644
--- a/chromium/content/browser/loader/layered_resource_handler.h
+++ b/chromium/content/browser/loader/layered_resource_handler.h
@@ -21,27 +21,25 @@ class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
public:
LayeredResourceHandler(net::URLRequest* request,
scoped_ptr<ResourceHandler> next_handler);
- virtual ~LayeredResourceHandler();
+ ~LayeredResourceHandler() override;
// ResourceHandler implementation:
- virtual void SetController(ResourceController* controller) OVERRIDE;
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read,
- bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ void SetController(ResourceController* controller) override;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
+ void OnDataDownloaded(int bytes_downloaded) override;
scoped_ptr<ResourceHandler> next_handler_;
};
diff --git a/chromium/content/browser/loader/navigation_resource_handler.cc b/chromium/content/browser/loader/navigation_resource_handler.cc
new file mode 100644
index 00000000000..393b295776e
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_resource_handler.cc
@@ -0,0 +1,149 @@
+// Copyright 2014 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 "content/browser/loader/navigation_resource_handler.h"
+
+#include "base/logging.h"
+#include "content/browser/devtools/devtools_netlog_observer.h"
+#include "content/browser/loader/navigation_url_loader_impl_core.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/resource_context_impl.h"
+#include "content/browser/streams/stream.h"
+#include "content/browser/streams/stream_context.h"
+#include "content/public/browser/resource_controller.h"
+#include "content/public/browser/stream_handle.h"
+#include "content/public/common/resource_response.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+NavigationResourceHandler::NavigationResourceHandler(
+ net::URLRequest* request,
+ NavigationURLLoaderImplCore* core)
+ : ResourceHandler(request),
+ core_(core) {
+ core_->set_resource_handler(this);
+}
+
+NavigationResourceHandler::~NavigationResourceHandler() {
+ if (core_) {
+ core_->NotifyRequestFailed(net::ERR_ABORTED);
+ DetachFromCore();
+ }
+}
+
+void NavigationResourceHandler::Cancel() {
+ controller()->Cancel();
+ core_ = nullptr;
+}
+
+void NavigationResourceHandler::FollowRedirect() {
+ controller()->Resume();
+}
+
+void NavigationResourceHandler::SetController(ResourceController* controller) {
+ writer_.set_controller(controller);
+ ResourceHandler::SetController(controller);
+}
+
+bool NavigationResourceHandler::OnUploadProgress(uint64 position, uint64 size) {
+ return true;
+}
+
+bool NavigationResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) {
+ DCHECK(core_);
+
+ // TODO(davidben): Perform a CSP check here, and anything else that would have
+ // been done renderer-side.
+ DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
+ core_->NotifyRequestRedirected(redirect_info, response);
+ *defer = true;
+ return true;
+}
+
+bool NavigationResourceHandler::OnResponseStarted(ResourceResponse* response,
+ bool* defer) {
+ DCHECK(core_);
+
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+
+ // If the BufferedResourceHandler intercepted this request and converted it
+ // into a download, it will still call OnResponseStarted and immediately
+ // cancel. Ignore the call; OnReadCompleted will happen shortly.
+ //
+ // TODO(davidben): Move the dispatch out of BufferedResourceHandler. Perhaps
+ // all the way to the UI thread. Downloads, user certificates, etc., should be
+ // dispatched at the navigation layer.
+ if (info->IsDownload() || info->is_stream())
+ return true;
+
+ StreamContext* stream_context =
+ GetStreamContextForResourceContext(info->GetContext());
+ writer_.InitializeStream(stream_context->registry(),
+ request()->url().GetOrigin());
+
+ // Detach from the loader; at this point, the request is now owned by the
+ // StreamHandle.
+ DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
+ core_->NotifyResponseStarted(response, writer_.stream()->CreateHandle());
+ DetachFromCore();
+ return true;
+}
+
+bool NavigationResourceHandler::OnWillStart(const GURL& url, bool* defer) {
+ return true;
+}
+
+bool NavigationResourceHandler::OnBeforeNetworkStart(const GURL& url,
+ bool* defer) {
+ return true;
+}
+
+bool NavigationResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
+ writer_.OnWillRead(buf, buf_size, min_size);
+ return true;
+}
+
+bool NavigationResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
+ writer_.OnReadCompleted(bytes_read, defer);
+ return true;
+}
+
+void NavigationResourceHandler::OnResponseCompleted(
+ const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) {
+ // If the request has already committed, close the stream and leave it as-is.
+ //
+ // TODO(davidben): The net error code should be passed through StreamWriter
+ // down to the stream's consumer. See https://crbug.com/426162.
+ if (writer_.stream()) {
+ writer_.Finalize();
+ return;
+ }
+
+ if (core_) {
+ DCHECK_NE(net::OK, status.error());
+ core_->NotifyRequestFailed(status.error());
+ DetachFromCore();
+ }
+}
+
+void NavigationResourceHandler::OnDataDownloaded(int bytes_downloaded) {
+ NOTREACHED();
+}
+
+void NavigationResourceHandler::DetachFromCore() {
+ DCHECK(core_);
+ core_->set_resource_handler(nullptr);
+ core_ = nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/navigation_resource_handler.h b/chromium/content/browser/loader/navigation_resource_handler.h
new file mode 100644
index 00000000000..59090260de9
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_resource_handler.h
@@ -0,0 +1,60 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_HANDLER_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_RESOURCE_HANDLER_H_
+
+#include "base/macros.h"
+#include "content/browser/loader/resource_handler.h"
+#include "content/browser/loader/stream_writer.h"
+
+namespace content {
+
+class NavigationURLLoaderImplCore;
+
+// PlzNavigate: The leaf ResourceHandler used with NavigationURLLoaderImplCore.
+class NavigationResourceHandler : public ResourceHandler {
+ public:
+ NavigationResourceHandler(net::URLRequest* request,
+ NavigationURLLoaderImplCore* core);
+ ~NavigationResourceHandler() override;
+
+ // Called by the loader the cancel the request.
+ void Cancel();
+
+ // Called to the loader to resume a paused redirect.
+ void FollowRedirect();
+
+ // ResourceHandler implementation.
+ void SetController(ResourceController* controller) override;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
+ void OnDataDownloaded(int bytes_downloaded) override;
+
+ private:
+ // Clears |core_| and its reference to the resource handler. After calling
+ // this, the lifetime of the request is no longer tied to |core_|.
+ void DetachFromCore();
+
+ NavigationURLLoaderImplCore* core_;
+ StreamWriter writer_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationResourceHandler);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_CERTIFICATE_RESOURCE_HANDLER_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader.cc b/chromium/content/browser/loader/navigation_url_loader.cc
new file mode 100644
index 00000000000..e0e1e9e7735
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 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 "content/browser/loader/navigation_url_loader.h"
+
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_url_loader_factory.h"
+#include "content/browser/loader/navigation_url_loader_impl.h"
+
+namespace content {
+
+static NavigationURLLoaderFactory* g_factory = nullptr;
+
+scoped_ptr<NavigationURLLoader> NavigationURLLoader::Create(
+ BrowserContext* browser_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body,
+ NavigationURLLoaderDelegate* delegate) {
+ if (g_factory) {
+ return g_factory->CreateLoader(browser_context, frame_tree_node_id,
+ common_params, request_info.Pass(),
+ request_body, delegate);
+ }
+ return scoped_ptr<NavigationURLLoader>(new NavigationURLLoaderImpl(
+ browser_context, frame_tree_node_id, common_params, request_info.Pass(),
+ request_body, delegate));
+}
+
+void NavigationURLLoader::SetFactoryForTesting(
+ NavigationURLLoaderFactory* factory) {
+ g_factory = factory;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
new file mode 100644
index 00000000000..7713e736610
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -0,0 +1,62 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
+
+#include "base/basictypes.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class BrowserContext;
+class NavigationURLLoaderDelegate;
+class NavigationURLLoaderFactory;
+class ResourceRequestBody;
+struct CommonNavigationParams;
+struct NavigationRequestInfo;
+
+// PlzNavigate: The navigation logic's UI thread entry point into the resource
+// loading stack. It exposes an interface to control the request prior to
+// receiving the response. If the NavigationURLLoader is destroyed before
+// OnResponseStarted is called, the request is aborted.
+class CONTENT_EXPORT NavigationURLLoader {
+ public:
+ // Creates a NavigationURLLoader. The caller is responsible for ensuring that
+ // |delegate| outlives the loader. |request_body| must not be accessed on the
+ // UI thread after this point.
+ //
+ // TODO(davidben): When navigation is disentangled from the loader, the
+ // request parameters should not come in as a navigation-specific
+ // structure. Information like has_user_gesture and
+ // should_replace_current_entry shouldn't be needed at this layer.
+ static scoped_ptr<NavigationURLLoader> Create(
+ BrowserContext* browser_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body,
+ NavigationURLLoaderDelegate* delegate);
+
+ // For testing purposes; sets the factory for use in testing.
+ static void SetFactoryForTesting(NavigationURLLoaderFactory* factory);
+
+ virtual ~NavigationURLLoader() {}
+
+ // Called in response to OnRequestRedirected to continue processing the
+ // request.
+ virtual void FollowRedirect() = 0;
+
+ protected:
+ NavigationURLLoader() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NavigationURLLoader);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_delegate.h b/chromium/content/browser/loader/navigation_url_loader_delegate.h
new file mode 100644
index 00000000000..199f48a2a98
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_delegate.h
@@ -0,0 +1,52 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_DELEGATE_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_DELEGATE_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+
+namespace net {
+struct RedirectInfo;
+}
+
+namespace content {
+
+class StreamHandle;
+struct ResourceResponse;
+
+// PlzNavigate: The delegate interface to NavigationURLLoader.
+class CONTENT_EXPORT NavigationURLLoaderDelegate {
+ public:
+ // Called when the request is redirected. Call FollowRedirect to continue
+ // processing the request.
+ virtual void OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response) = 0;
+
+ // Called when the request receives its response. No further calls will be
+ // made to the delegate. The response body is returned as a stream in
+ // |body_stream|.
+ virtual void OnResponseStarted(
+ const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body_stream) = 0;
+
+ // Called if the request fails before receving a response. |net_error| is a
+ // network error code for the failure.
+ virtual void OnRequestFailed(int net_error) = 0;
+
+ protected:
+ NavigationURLLoaderDelegate() {}
+ virtual ~NavigationURLLoaderDelegate() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderDelegate);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_DELEGATE_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_factory.h b/chromium/content/browser/loader/navigation_url_loader_factory.h
new file mode 100644
index 00000000000..ddb4fe1dc3d
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_factory.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_FACTORY_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/loader/navigation_url_loader.h"
+
+namespace content {
+
+// NavigationURLLoader::Create uses the currently registered factory to create
+// the loader. This is intended for testing.
+class NavigationURLLoaderFactory {
+ public:
+ virtual scoped_ptr<NavigationURLLoader> CreateLoader(
+ BrowserContext* browser_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body,
+ NavigationURLLoaderDelegate* delegate) = 0;
+
+ protected:
+ NavigationURLLoaderFactory() {}
+ virtual ~NavigationURLLoaderFactory() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_FACTORY_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
new file mode 100644
index 00000000000..b6dbed08685
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -0,0 +1,76 @@
+// Copyright 2014 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 "content/browser/loader/navigation_url_loader_impl.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/browser/loader/navigation_url_loader_impl_core.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/stream_handle.h"
+
+namespace content {
+
+NavigationURLLoaderImpl::NavigationURLLoaderImpl(
+ BrowserContext* browser_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body,
+ NavigationURLLoaderDelegate* delegate)
+ : delegate_(delegate),
+ weak_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ core_ = new NavigationURLLoaderImplCore(weak_factory_.GetWeakPtr());
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImplCore::Start, base::Unretained(core_),
+ browser_context->GetResourceContext(), frame_tree_node_id,
+ common_params, base::Passed(&request_info),
+ make_scoped_refptr(request_body)));
+}
+
+NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, core_);
+ core_ = nullptr;
+}
+
+void NavigationURLLoaderImpl::FollowRedirect() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImplCore::FollowRedirect,
+ base::Unretained(core_)));
+}
+
+void NavigationURLLoaderImpl::NotifyRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ delegate_->OnRequestRedirected(redirect_info, response);
+}
+
+void NavigationURLLoaderImpl::NotifyResponseStarted(
+ const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ delegate_->OnResponseStarted(response, body.Pass());
+}
+
+void NavigationURLLoaderImpl::NotifyRequestFailed(int net_error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ delegate_->OnRequestFailed(net_error);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
new file mode 100644
index 00000000000..ecfd2382e8e
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -0,0 +1,66 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/loader/navigation_url_loader.h"
+
+namespace net {
+struct RedirectInfo;
+}
+
+namespace content {
+
+class NavigationURLLoaderImplCore;
+class StreamHandle;
+struct ResourceResponse;
+
+class NavigationURLLoaderImpl : public NavigationURLLoader {
+ public:
+ // The caller is responsible for ensuring that |delegate| outlives the loader.
+ NavigationURLLoaderImpl(BrowserContext* browser_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body,
+ NavigationURLLoaderDelegate* delegate);
+ ~NavigationURLLoaderImpl() override;
+
+ // Called in response to OnRequestRedirected to continue processing the
+ // request.
+ void FollowRedirect() override;
+
+ private:
+ friend class NavigationURLLoaderImplCore;
+
+ // Notifies the delegate of a redirect.
+ void NotifyRequestRedirected(const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response);
+
+ // Notifies the delegate that the response has started.
+ void NotifyResponseStarted(const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body);
+
+ // Notifies the delegate the request failed to return a response.
+ void NotifyRequestFailed(int net_error);
+
+ NavigationURLLoaderDelegate* delegate_;
+
+ // |core_| is deleted on the IO thread in a subsequent task when the
+ // NavigationURLLoaderImpl goes out of scope.
+ NavigationURLLoaderImplCore* core_;
+
+ base::WeakPtrFactory<NavigationURLLoaderImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
new file mode 100644
index 00000000000..48845e8aa0c
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
@@ -0,0 +1,104 @@
+// Copyright 2014 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 "content/browser/loader/navigation_url_loader_impl_core.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_resource_handler.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/common/navigation_params.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/stream_handle.h"
+#include "content/public/common/resource_response.h"
+#include "net/base/net_errors.h"
+#include "net/url_request/redirect_info.h"
+
+namespace content {
+
+NavigationURLLoaderImplCore::NavigationURLLoaderImplCore(
+ const base::WeakPtr<NavigationURLLoaderImpl>& loader)
+ : loader_(loader),
+ resource_handler_(nullptr) {
+ // This object is created on the UI thread but otherwise is accessed and
+ // deleted on the IO thread.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+NavigationURLLoaderImplCore::~NavigationURLLoaderImplCore() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (resource_handler_)
+ resource_handler_->Cancel();
+}
+
+void NavigationURLLoaderImplCore::Start(
+ ResourceContext* resource_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ResourceDispatcherHostImpl::Get()->BeginNavigationRequest(
+ resource_context, frame_tree_node_id,
+ common_params, *request_info, request_body,
+ this);
+}
+
+void NavigationURLLoaderImplCore::FollowRedirect() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (resource_handler_)
+ resource_handler_->FollowRedirect();
+}
+
+
+void NavigationURLLoaderImplCore::NotifyRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Make a copy of the ResourceResponse before it is passed to another thread.
+ //
+ // TODO(davidben): This copy could be avoided if ResourceResponse weren't
+ // reference counted and the loader stack passed unique ownership of the
+ // response. https://crbug.com/416050
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImpl::NotifyRequestRedirected, loader_,
+ redirect_info, response->DeepCopy()));
+}
+
+void NavigationURLLoaderImplCore::NotifyResponseStarted(
+ ResourceResponse* response,
+ scoped_ptr<StreamHandle> body) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // If, by the time the task reaches the UI thread, |loader_| has already been
+ // destroyed, NotifyResponseStarted will not run. |body| will be destructed
+ // and the request released at that point.
+
+ // Make a copy of the ResourceResponse before it is passed to another thread.
+ //
+ // TODO(davidben): This copy could be avoided if ResourceResponse weren't
+ // reference counted and the loader stack passed unique ownership of the
+ // response. https://crbug.com/416050
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImpl::NotifyResponseStarted, loader_,
+ response->DeepCopy(), base::Passed(&body)));
+}
+
+void NavigationURLLoaderImplCore::NotifyRequestFailed(int net_error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImpl::NotifyRequestFailed, loader_,
+ net_error));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.h b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
new file mode 100644
index 00000000000..f31d3ccbdc3
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
@@ -0,0 +1,75 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
+#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
+
+#include "base/basictypes.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/loader/navigation_url_loader_impl.h"
+
+namespace net {
+class URLRequest;
+struct RedirectInfo;
+}
+
+namespace content {
+
+class FrameTreeNode;
+class NavigationResourceHandler;
+class ResourceContext;
+class ResourceHandler;
+class ResourceRequestBody;
+class StreamHandle;
+struct ResourceResponse;
+
+// The IO-thread counterpart to the NavigationURLLoaderImpl. It lives on the IO
+// thread and is owned by the UI-thread NavigationURLLoaderImpl.
+// NavigationURLLoaderImplCore interacts with the ResourceDispatcherHost stack
+// and forwards signals back to the loader on the UI thread.
+class NavigationURLLoaderImplCore {
+ public:
+ // Creates a new NavigationURLLoaderImplCore that forwards signals back to
+ // |loader| on the UI thread.
+ explicit NavigationURLLoaderImplCore(
+ const base::WeakPtr<NavigationURLLoaderImpl>& loader);
+ ~NavigationURLLoaderImplCore();
+
+ // Starts the request.
+ void Start(ResourceContext* resource_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ scoped_ptr<NavigationRequestInfo> request_info,
+ ResourceRequestBody* request_body);
+
+ // Follows the current pending redirect.
+ void FollowRedirect();
+
+ void set_resource_handler(NavigationResourceHandler* resource_handler) {
+ resource_handler_ = resource_handler;
+ }
+
+ // Notifies |loader_| on the UI thread that the request was redirected.
+ void NotifyRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response);
+
+ // Notifies |loader_| on the UI thread that the response started.
+ void NotifyResponseStarted(ResourceResponse* response,
+ scoped_ptr<StreamHandle> body);
+
+ // Notifies |loader_| on the UI thread that the request failed.
+ void NotifyRequestFailed(int net_error);
+
+ private:
+ base::WeakPtr<NavigationURLLoaderImpl> loader_;
+ NavigationResourceHandler* resource_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationURLLoaderImplCore);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
new file mode 100644
index 00000000000..e81cad218be
--- /dev/null
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -0,0 +1,389 @@
+// Copyright 2014 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/command_line.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/run_loop.h"
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/loader/navigation_url_loader_delegate.h"
+#include "content/browser/loader/navigation_url_loader_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/streams/stream.h"
+#include "content/browser/streams/stream_context.h"
+#include "content/browser/streams/stream_registry.h"
+#include "content/browser/streams/stream_url_request_job.h"
+#include "content/common/navigation_params.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/stream_handle.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/resource_response.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class StreamProtocolHandler
+ : public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ StreamProtocolHandler(StreamRegistry* registry) : registry_(registry) {}
+
+ // net::URLRequestJobFactory::ProtocolHandler implementation.
+ net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ scoped_refptr<Stream> stream = registry_->GetStream(request->url());
+ if (stream.get())
+ return new StreamURLRequestJob(request, network_delegate, stream);
+ return nullptr;
+ }
+
+ private:
+ StreamRegistry* registry_;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamProtocolHandler);
+};
+
+class TestNavigationURLLoaderDelegate : public NavigationURLLoaderDelegate {
+ public:
+ TestNavigationURLLoaderDelegate()
+ : net_error_(0) {
+ }
+
+ const net::RedirectInfo& redirect_info() const { return redirect_info_; }
+ ResourceResponse* redirect_response() const {
+ return redirect_response_.get();
+ }
+ ResourceResponse* response() const { return response_.get(); }
+ StreamHandle* body() const { return body_.get(); }
+ int net_error() const { return net_error_; }
+
+ void WaitForRequestRedirected() {
+ request_redirected_.reset(new base::RunLoop);
+ request_redirected_->Run();
+ request_redirected_.reset();
+ }
+
+ void WaitForResponseStarted() {
+ response_started_.reset(new base::RunLoop);
+ response_started_->Run();
+ response_started_.reset();
+ }
+
+ void WaitForRequestFailed() {
+ request_failed_.reset(new base::RunLoop);
+ request_failed_->Run();
+ request_failed_.reset();
+ }
+
+ void ReleaseBody() {
+ body_.reset();
+ }
+
+ // NavigationURLLoaderDelegate implementation.
+ void OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ const scoped_refptr<ResourceResponse>& response) override {
+ redirect_info_ = redirect_info;
+ redirect_response_ = response;
+ ASSERT_TRUE(request_redirected_);
+ request_redirected_->Quit();
+ }
+
+ void OnResponseStarted(const scoped_refptr<ResourceResponse>& response,
+ scoped_ptr<StreamHandle> body) override {
+ response_ = response;
+ body_ = body.Pass();
+ ASSERT_TRUE(response_started_);
+ response_started_->Quit();
+ }
+
+ void OnRequestFailed(int net_error) override {
+ net_error_ = net_error;
+ ASSERT_TRUE(request_failed_);
+ request_failed_->Quit();
+ }
+
+ private:
+ net::RedirectInfo redirect_info_;
+ scoped_refptr<ResourceResponse> redirect_response_;
+ scoped_refptr<ResourceResponse> response_;
+ scoped_ptr<StreamHandle> body_;
+ int net_error_;
+
+ scoped_ptr<base::RunLoop> request_redirected_;
+ scoped_ptr<base::RunLoop> response_started_;
+ scoped_ptr<base::RunLoop> request_failed_;
+};
+
+class RequestBlockingResourceDispatcherHostDelegate
+ : public ResourceDispatcherHostDelegate {
+ public:
+ // ResourceDispatcherHostDelegate implementation:
+ bool ShouldBeginRequest(const std::string& method,
+ const GURL& url,
+ ResourceType resource_type,
+ ResourceContext* resource_context) override {
+ return false;
+ }
+};
+
+} // namespace
+
+class NavigationURLLoaderTest : public testing::Test {
+ public:
+ NavigationURLLoaderTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ browser_context_(new TestBrowserContext) {
+ BrowserContext::EnsureResourceContextInitialized(browser_context_.get());
+ base::RunLoop().RunUntilIdle();
+ net::URLRequestContext* request_context =
+ browser_context_->GetResourceContext()->GetRequestContext();
+ // Attach URLRequestTestJob and make streams work.
+ job_factory_.SetProtocolHandler(
+ "test", net::URLRequestTestJob::CreateProtocolHandler());
+ job_factory_.SetProtocolHandler(
+ "blob", new StreamProtocolHandler(
+ StreamContext::GetFor(browser_context_.get())->registry()));
+ request_context->set_job_factory(&job_factory_);
+
+ // NavigationURLLoader is only used for browser-side navigations.
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBrowserSideNavigation);
+ }
+
+ scoped_ptr<NavigationURLLoader> MakeTestLoader(
+ const GURL& url,
+ NavigationURLLoaderDelegate* delegate) {
+ FrameHostMsg_BeginNavigation_Params begin_params;
+ CommonNavigationParams common_params;
+ begin_params.method = "GET";
+ common_params.url = url;
+ scoped_ptr<NavigationRequestInfo> request_info(
+ new NavigationRequestInfo(begin_params));
+ request_info->first_party_for_cookies = url;
+ request_info->is_main_frame = true;
+
+ return NavigationURLLoader::Create(
+ browser_context_.get(), 0,
+ common_params, request_info.Pass(), nullptr, delegate);
+ }
+
+ // Helper function for fetching the body of a URL to a string.
+ std::string FetchURL(const GURL& url) {
+ net::TestDelegate delegate;
+ net::URLRequestContext* request_context =
+ browser_context_->GetResourceContext()->GetRequestContext();
+ scoped_ptr<net::URLRequest> request(request_context->CreateRequest(
+ url, net::DEFAULT_PRIORITY, &delegate, nullptr));
+ request->Start();
+ base::RunLoop().Run();
+
+ EXPECT_TRUE(request->status().is_success());
+ EXPECT_EQ(200, request->response_headers()->response_code());
+ return delegate.data_received();
+ }
+
+ protected:
+ TestBrowserThreadBundle thread_bundle_;
+ net::URLRequestJobFactoryImpl job_factory_;
+ scoped_ptr<TestBrowserContext> browser_context_;
+ ResourceDispatcherHostImpl host_;
+};
+
+// Tests that a basic request works.
+TEST_F(NavigationURLLoaderTest, Basic) {
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_1(), &delegate);
+
+ // Wait for the response to come back.
+ delegate.WaitForResponseStarted();
+
+ // Check the response is correct.
+ EXPECT_EQ("text/html", delegate.response()->head.mime_type);
+ EXPECT_EQ(200, delegate.response()->head.headers->response_code());
+
+ // Check the body is correct.
+ EXPECT_EQ(net::URLRequestTestJob::test_data_1(),
+ FetchURL(delegate.body()->GetURL()));
+}
+
+// Tests that request failures are propagated correctly.
+TEST_F(NavigationURLLoaderTest, RequestFailed) {
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(GURL("bogus:bogus"), &delegate);
+
+ // Wait for the request to fail as expected.
+ delegate.WaitForRequestFailed();
+ EXPECT_EQ(net::ERR_UNKNOWN_URL_SCHEME, delegate.net_error());
+}
+
+// Test that redirects are sent to the delegate.
+TEST_F(NavigationURLLoaderTest, RequestRedirected) {
+ // Fake a top-level request. Choose a URL which redirects so the request can
+ // be paused before the response comes in.
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
+ &delegate);
+
+ // Wait for the request to redirect.
+ delegate.WaitForRequestRedirected();
+ EXPECT_EQ(net::URLRequestTestJob::test_url_2(),
+ delegate.redirect_info().new_url);
+ EXPECT_EQ("GET", delegate.redirect_info().new_method);
+ EXPECT_EQ(net::URLRequestTestJob::test_url_2(),
+ delegate.redirect_info().new_first_party_for_cookies);
+ EXPECT_EQ(302, delegate.redirect_response()->head.headers->response_code());
+
+ // Wait for the response to complete.
+ loader->FollowRedirect();
+ delegate.WaitForResponseStarted();
+
+ // Check the response is correct.
+ EXPECT_EQ("text/html", delegate.response()->head.mime_type);
+ EXPECT_EQ(200, delegate.response()->head.headers->response_code());
+
+ // Release the body and check it is correct.
+ EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
+ EXPECT_EQ(net::URLRequestTestJob::test_data_2(),
+ FetchURL(delegate.body()->GetURL()));
+}
+
+// Tests that the destroying the loader cancels the request.
+TEST_F(NavigationURLLoaderTest, CancelOnDestruct) {
+ // Fake a top-level request. Choose a URL which redirects so the request can
+ // be paused before the response comes in.
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
+ &delegate);
+
+ // Wait for the request to redirect.
+ delegate.WaitForRequestRedirected();
+
+ // Destroy the loader and verify that URLRequestTestJob no longer has anything
+ // paused.
+ loader.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
+}
+
+// Test that the delegate is not called if OnResponseStarted and destroying the
+// loader race.
+TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
+ &delegate);
+
+ // Wait for the request to redirect.
+ delegate.WaitForRequestRedirected();
+
+ // In the same event loop iteration, follow the redirect (allowing the
+ // response to go through) and destroy the loader.
+ loader->FollowRedirect();
+ loader.reset();
+
+ // Verify the URLRequestTestJob no longer has anything paused and that no
+ // response body was received.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
+ EXPECT_FALSE(delegate.body());
+}
+
+// Tests that the loader may be canceled by context.
+TEST_F(NavigationURLLoaderTest, CancelByContext) {
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
+ &delegate);
+
+ // Wait for the request to redirect.
+ delegate.WaitForRequestRedirected();
+
+ // Cancel all requests.
+ host_.CancelRequestsForContext(browser_context_->GetResourceContext());
+
+ // Wait for the request to now be aborted.
+ delegate.WaitForRequestFailed();
+ EXPECT_EQ(net::ERR_ABORTED, delegate.net_error());
+}
+
+// Tests that, if the request is blocked by the ResourceDispatcherHostDelegate,
+// the caller is informed appropriately.
+TEST_F(NavigationURLLoaderTest, RequestBlocked) {
+ RequestBlockingResourceDispatcherHostDelegate rdh_delegate;
+ host_.SetDelegate(&rdh_delegate);
+
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_1(), &delegate);
+
+ // Wait for the request to fail as expected.
+ delegate.WaitForRequestFailed();
+ EXPECT_EQ(net::ERR_ABORTED, delegate.net_error());
+
+ host_.SetDelegate(nullptr);
+}
+
+// Tests that ownership leaves the loader once the response is received.
+TEST_F(NavigationURLLoaderTest, LoaderDetached) {
+ // Fake a top-level request to a URL whose body does not load immediately.
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_2(), &delegate);
+
+ // Wait for the response to come back.
+ delegate.WaitForResponseStarted();
+
+ // Check the response is correct.
+ EXPECT_EQ("text/html", delegate.response()->head.mime_type);
+ EXPECT_EQ(200, delegate.response()->head.headers->response_code());
+
+ // Destroy the loader.
+ loader.reset();
+ base::RunLoop().RunUntilIdle();
+
+ // Check the body can still be fetched through the StreamHandle.
+ EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
+ EXPECT_EQ(net::URLRequestTestJob::test_data_2(),
+ FetchURL(delegate.body()->GetURL()));
+}
+
+// Tests that the request is owned by the body StreamHandle.
+TEST_F(NavigationURLLoaderTest, OwnedByHandle) {
+ // Fake a top-level request to a URL whose body does not load immediately.
+ TestNavigationURLLoaderDelegate delegate;
+ scoped_ptr<NavigationURLLoader> loader =
+ MakeTestLoader(net::URLRequestTestJob::test_url_2(), &delegate);
+
+ // Wait for the response to come back.
+ delegate.WaitForResponseStarted();
+
+ // Release the body.
+ delegate.ReleaseBody();
+ base::RunLoop().RunUntilIdle();
+
+ // Verify that URLRequestTestJob no longer has anything paused.
+ EXPECT_FALSE(net::URLRequestTestJob::ProcessOnePendingMessage());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/power_save_block_resource_throttle.h b/chromium/content/browser/loader/power_save_block_resource_throttle.h
index 2a4f9b39c5a..a09293faf3b 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.h
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.h
@@ -19,12 +19,12 @@ class PowerSaveBlocker;
class PowerSaveBlockResourceThrottle : public ResourceThrottle {
public:
PowerSaveBlockResourceThrottle();
- virtual ~PowerSaveBlockResourceThrottle();
+ ~PowerSaveBlockResourceThrottle() override;
// ResourceThrottle overrides:
- virtual void WillStartRequest(bool* defer) OVERRIDE;
- virtual void WillProcessResponse(bool* defer) OVERRIDE;
- virtual const char* GetNameForLogging() const OVERRIDE;
+ void WillStartRequest(bool* defer) override;
+ void WillProcessResponse(bool* defer) override;
+ const char* GetNameForLogging() const override;
private:
void ActivatePowerSaveBlocker();
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
index caf36cddf39..00e63928076 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -15,9 +15,9 @@
#include "net/base/io_buffer.h"
#include "net/base/mime_sniffer.h"
#include "net/base/net_errors.h"
-#include "webkit/common/blob/shareable_file_reference.h"
+#include "storage/common/blob/shareable_file_reference.h"
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace {
@@ -38,7 +38,7 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
backing_(backing) {
}
private:
- virtual ~DependentIOBuffer() {}
+ ~DependentIOBuffer() override {}
scoped_refptr<net::IOBuffer> backing_;
};
@@ -121,7 +121,7 @@ class RedirectToFileResourceHandler::Writer {
// We create a ShareableFileReference that's deletable for the temp file
// created as a result of the download.
- scoped_refptr<webkit_blob::ShareableFileReference> deletable_file_;
+ scoped_refptr<storage::ShareableFileReference> deletable_file_;
DISALLOW_COPY_AND_ASSIGN(Writer);
};
@@ -157,11 +157,8 @@ void RedirectToFileResourceHandler::
bool RedirectToFileResourceHandler::OnResponseStarted(
ResourceResponse* response,
bool* defer) {
- if (response->head.error_code == net::OK ||
- response->head.error_code == net::ERR_IO_PENDING) {
- DCHECK(writer_);
- response->head.download_file_path = writer_->path();
- }
+ DCHECK(writer_);
+ response->head.download_file_path = writer_->path();
return next_handler_->OnResponseStarted(response, defer);
}
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
index 07763f5c16a..1778921e370 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
@@ -25,7 +25,7 @@ class FileStream;
class GrowableIOBuffer;
}
-namespace webkit_blob {
+namespace storage {
class ShareableFileReference;
}
@@ -46,7 +46,7 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
// |next_handler|.
RedirectToFileResourceHandler(scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request);
- virtual ~RedirectToFileResourceHandler();
+ ~RedirectToFileResourceHandler() override;
// Replace the CreateTemporaryFileStream implementation with a mocked one for
// testing purposes. The function should create a net::FileStream and a
@@ -56,22 +56,20 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
const CreateTemporaryFileStreamFunction& create_temporary_file_stream);
// LayeredResourceHandler implementation:
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
private:
- void DidCreateTemporaryFile(
- base::File::Error error_code,
- scoped_ptr<net::FileStream> file_stream,
- webkit_blob::ShareableFileReference* deletable_file);
+ void DidCreateTemporaryFile(base::File::Error error_code,
+ scoped_ptr<net::FileStream> file_stream,
+ storage::ShareableFileReference* deletable_file);
// Called by RedirectToFileResourceHandler::Writer.
void DidWriteToFile(int result);
@@ -94,7 +92,7 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
int write_cursor_;
// Helper writer object which maintains references to the net::FileStream and
- // webkit_blob::ShareableFileReference. This is maintained separately so that,
+ // storage::ShareableFileReference. This is maintained separately so that,
// on Windows, the temporary file isn't deleted until after it is closed.
class Writer;
Writer* writer_;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index 0858bd67e03..8673c07b086 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -18,12 +19,12 @@
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
#include "content/shell/browser/shell_network_delegate.h"
-#include "content/test/net/url_request_failed_job.h"
-#include "content/test/net/url_request_mock_http_job.h"
#include "net/base/net_errors.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/url_request/url_request_failed_job.h"
+#include "net/test/url_request/url_request_mock_http_job.h"
using base::ASCIIToUTF16;
@@ -35,25 +36,28 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
ResourceDispatcherHostBrowserTest() : got_downloads_(false) {}
protected:
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
base::FilePath path = GetTestFilePath("", "");
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestMockHTTPJob::AddUrlHandler, path));
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &net::URLRequestMockHTTPJob::AddUrlHandler,
+ path,
+ make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestFailedJob::AddUrlHandler));
+ base::Bind(&net::URLRequestFailedJob::AddUrlHandler));
}
- virtual void OnDownloadCreated(
- DownloadManager* manager,
- DownloadItem* item) OVERRIDE {
+ void OnDownloadCreated(DownloadManager* manager,
+ DownloadItem* item) override {
if (!got_downloads_)
got_downloads_ = !!manager->InProgressCount();
}
GURL GetMockURL(const std::string& file) {
- return URLRequestMockHTTPJob::GetMockUrl(
+ return net::URLRequestMockHTTPJob::GetMockUrl(
base::FilePath().AppendASCII(file));
}
@@ -219,9 +223,10 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
ASSERT_FALSE(got_downloads());
}
+// Flaky everywhere. http://crbug.com/130404
// Tests that onunload is run for cross-site requests. (Bug 1114994)
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossSiteOnunloadCookie) {
+ DISABLED_CrossSiteOnunloadCookie) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url = embedded_test_server()->GetURL("/onunload_cookie.html");
@@ -266,7 +271,7 @@ scoped_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
scoped_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_NO_CONTENT);
- return http_response.PassAs<net::test_server::HttpResponse>();
+ return http_response.Pass();
}
} // namespace
@@ -333,12 +338,12 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
CheckTitleTest(url, "Title Of Awesomeness");
}
+// Flaky everywhere. http://crbug.com/130404
// Tests that a cross-site navigation to an error page (resulting in the link
// doctor page) still runs the onunload handler and can support navigations
// away from the link doctor page. (Bug 1235537)
-// Flaky: http://crbug.com/100823
IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
- CrossSiteNavigationErrorPage) {
+ DISABLED_CrossSiteNavigationErrorPage) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url(embedded_test_server()->GetURL("/onunload_cookie.html"));
@@ -348,7 +353,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// TODO(creis): If this causes crashes or hangs, it might be for the same
// reason as ErrorPageTest::DNSError. See bug 1199491 and
// http://crbug.com/22877.
- GURL failed_url = URLRequestFailedJob::GetMockHttpUrl(
+ GURL failed_url = net::URLRequestFailedJob::GetMockHttpUrl(
net::ERR_NAME_NOT_RESOLVED);
NavigateToURL(shell(), failed_url);
@@ -393,7 +398,7 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
// TODO(creis): If this causes crashes or hangs, it might be for the same
// reason as ErrorPageTest::DNSError. See bug 1199491 and
// http://crbug.com/22877.
- GURL failed_url = URLRequestFailedJob::GetMockHttpUrl(
+ GURL failed_url = net::URLRequestFailedJob::GetMockHttpUrl(
net::ERR_NAME_NOT_RESOLVED);
NavigateToURL(shell(), failed_url);
@@ -445,7 +450,7 @@ scoped_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
http_response->set_code(net::HTTP_FOUND);
http_response->AddCustomHeader(
"Location", request.relative_url.substr(request_path.length()));
- return http_response.PassAs<net::test_server::HttpResponse>();
+ return http_response.Pass();
}
} // namespace
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 0e5abc6653c..26ecf1d8dbb 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -27,15 +27,18 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/cert_store_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/cross_site_request_manager.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/download/save_file_resource_handler.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/browser/frame_host/navigation_request_info.h"
+#include "content/browser/frame_host/navigator.h"
#include "content/browser/loader/async_resource_handler.h"
#include "content/browser/loader/buffered_resource_handler.h"
#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/detachable_resource_handler.h"
+#include "content/browser/loader/navigation_resource_handler.h"
+#include "content/browser/loader/navigation_url_loader_impl_core.h"
#include "content/browser/loader/power_save_block_resource_throttle.h"
#include "content/browser/loader/redirect_to_file_resource_handler.h"
#include "content/browser/loader/resource_message_filter.h"
@@ -44,7 +47,6 @@
#include "content/browser/loader/sync_resource_handler.h"
#include "content/browser/loader/throttling_resource_handler.h"
#include "content/browser/loader/upload_data_stream_builder.h"
-#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/resource_context_impl.h"
@@ -52,10 +54,10 @@
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/streams/stream_registry.h"
-#include "content/browser/worker_host/worker_service_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/appcache_interfaces.h"
+#include "content/common/navigation_params.h"
#include "content/common/resource_messages.h"
-#include "content/common/resource_request_body.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -67,6 +69,7 @@
#include "content/public/browser/resource_request_details.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/browser/stream_handle.h"
+#include "content/public/browser/stream_info.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
@@ -87,20 +90,23 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "storage/browser/fileapi/file_permission_policy.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/common/blob/blob_data.h"
+#include "storage/common/blob/shareable_file_reference.h"
#include "url/url_constants.h"
-#include "webkit/common/blob/blob_data.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/blob/blob_url_request_job_factory.h"
-#include "webkit/browser/fileapi/file_permission_policy.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/common/blob/shareable_file_reference.h"
+
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_service_impl.h"
+#endif
using base::Time;
using base::TimeDelta;
using base::TimeTicks;
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
// ----------------------------------------------------------------------------
@@ -137,10 +143,64 @@ const double kMaxRequestsPerProcessRatio = 0.45;
// same resource (see bugs 46104 and 31014).
const int kDefaultDetachableCancelDelayMs = 30000;
-bool IsDetachableResourceType(ResourceType::Type type) {
+enum SHA1HistogramTypes {
+ // SHA-1 is not present in the certificate chain.
+ SHA1_NOT_PRESENT = 0,
+ // SHA-1 is present in the certificate chain, and the leaf expires on or
+ // after January 1, 2017.
+ SHA1_EXPIRES_AFTER_JANUARY_2017 = 1,
+ // SHA-1 is present in the certificate chain, and the leaf expires on or
+ // after June 1, 2016.
+ SHA1_EXPIRES_AFTER_JUNE_2016 = 2,
+ // SHA-1 is present in the certificate chain, and the leaf expires on or
+ // after January 1, 2016.
+ SHA1_EXPIRES_AFTER_JANUARY_2016 = 3,
+ // SHA-1 is present in the certificate chain, but the leaf expires before
+ // January 1, 2016
+ SHA1_PRESENT = 4,
+ // Always keep this at the end.
+ SHA1_HISTOGRAM_TYPES_MAX,
+};
+
+void RecordCertificateHistograms(const net::SSLInfo& ssl_info,
+ ResourceType resource_type) {
+ // The internal representation of the dates for UI treatment of SHA-1.
+ // See http://crbug.com/401365 for details
+ static const int64_t kJanuary2017 = INT64_C(13127702400000000);
+ static const int64_t kJune2016 = INT64_C(13109213000000000);
+ static const int64_t kJanuary2016 = INT64_C(13096080000000000);
+
+ SHA1HistogramTypes sha1_histogram = SHA1_NOT_PRESENT;
+ if (ssl_info.cert_status & net::CERT_STATUS_SHA1_SIGNATURE_PRESENT) {
+ DCHECK(ssl_info.cert.get());
+ if (ssl_info.cert->valid_expiry() >=
+ base::Time::FromInternalValue(kJanuary2017)) {
+ sha1_histogram = SHA1_EXPIRES_AFTER_JANUARY_2017;
+ } else if (ssl_info.cert->valid_expiry() >=
+ base::Time::FromInternalValue(kJune2016)) {
+ sha1_histogram = SHA1_EXPIRES_AFTER_JUNE_2016;
+ } else if (ssl_info.cert->valid_expiry() >=
+ base::Time::FromInternalValue(kJanuary2016)) {
+ sha1_histogram = SHA1_EXPIRES_AFTER_JANUARY_2016;
+ } else {
+ sha1_histogram = SHA1_PRESENT;
+ }
+ }
+ if (resource_type == RESOURCE_TYPE_MAIN_FRAME) {
+ UMA_HISTOGRAM_ENUMERATION("Net.Certificate.SHA1.MainFrame",
+ sha1_histogram,
+ SHA1_HISTOGRAM_TYPES_MAX);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Net.Certificate.SHA1.Subresource",
+ sha1_histogram,
+ SHA1_HISTOGRAM_TYPES_MAX);
+ }
+}
+
+bool IsDetachableResourceType(ResourceType type) {
switch (type) {
- case ResourceType::PREFETCH:
- case ResourceType::PING:
+ case RESOURCE_TYPE_PREFETCH:
+ case RESOURCE_TYPE_PING:
return true;
default:
return false;
@@ -172,7 +232,8 @@ void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
void SetReferrerForRequest(net::URLRequest* request, const Referrer& referrer) {
if (!referrer.url.is_valid() ||
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoReferrers)) {
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kNoReferrers)) {
request->SetReferrer(std::string());
} else {
request->SetReferrer(referrer.url.spec());
@@ -201,7 +262,7 @@ void SetReferrerForRequest(net::URLRequest* request, const Referrer& referrer) {
bool ShouldServiceRequest(int process_type,
int child_id,
const ResourceHostMsg_Request& request_data,
- fileapi::FileSystemContext* file_system_context) {
+ storage::FileSystemContext* file_system_context) {
if (process_type == PROCESS_TYPE_PLUGIN)
return true;
@@ -228,7 +289,7 @@ bool ShouldServiceRequest(int process_type,
return false;
}
if (iter->type() == ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM) {
- fileapi::FileSystemURL url =
+ storage::FileSystemURL url =
file_system_context->CrackURL(iter->filesystem_url());
if (!policy->CanReadFileSystemFile(child_id, url)) {
NOTREACHED() << "Denied unauthorized upload of "
@@ -248,16 +309,6 @@ void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
child_id, path);
}
-#if defined(OS_WIN)
-#pragma warning(disable: 4748)
-#pragma optimize("", off)
-#endif
-
-#if defined(OS_WIN)
-#pragma optimize("", on)
-#pragma warning(default: 4748)
-#endif
-
DownloadInterruptReason CallbackAndReturn(
const DownloadUrlParameters::OnStartedCallback& started_cb,
DownloadInterruptReason interrupt_reason) {
@@ -310,11 +361,49 @@ bool IsValidatedSCT(
return sct_status.status == net::ct::SCT_STATUS_OK;
}
-webkit_blob::BlobStorageContext* GetBlobStorageContext(
- ResourceMessageFilter* filter) {
- if (!filter->blob_storage_context())
+storage::BlobStorageContext* GetBlobStorageContext(
+ ChromeBlobStorageContext* blob_storage_context) {
+ if (!blob_storage_context)
return NULL;
- return filter->blob_storage_context()->context();
+ return blob_storage_context->context();
+}
+
+void AttachRequestBodyBlobDataHandles(
+ ResourceRequestBody* body,
+ storage::BlobStorageContext* blob_context) {
+ DCHECK(blob_context);
+ for (size_t i = 0; i < body->elements()->size(); ++i) {
+ const ResourceRequestBody::Element& element = (*body->elements())[i];
+ if (element.type() != ResourceRequestBody::Element::TYPE_BLOB)
+ continue;
+ scoped_ptr<storage::BlobDataHandle> handle =
+ blob_context->GetBlobDataFromUUID(element.blob_uuid());
+ DCHECK(handle);
+ if (!handle)
+ continue;
+ // Ensure the blob and any attached shareable files survive until
+ // upload completion. The |body| takes ownership of |handle|.
+ const void* key = handle.get();
+ body->SetUserData(key, handle.release());
+ }
+}
+
+// PlzNavigate
+// This method is called in the UI thread to send the timestamp of a resource
+// request to the respective Navigator (for an UMA histogram).
+void LogResourceRequestTimeOnUI(
+ base::TimeTicks timestamp,
+ int render_process_id,
+ int render_frame_id,
+ const GURL& url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ RenderFrameHostImpl* host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ if (host != NULL) {
+ DCHECK(host->frame_tree_node()->IsMainFrame());
+ host->frame_tree_node()->navigator()->LogResourceRequestTime(
+ timestamp, url);
+ }
}
} // namespace
@@ -387,6 +476,17 @@ void ResourceDispatcherHostImpl::RemoveResourceContext(
active_resource_contexts_.erase(context);
}
+void ResourceDispatcherHostImpl::ResumeResponseDeferredAtStart(
+ const GlobalRequestID& id) {
+ ResourceLoader* loader = GetLoader(id);
+ if (loader) {
+ // The response we were meant to resume could have already been canceled.
+ ResourceRequestInfoImpl* info = loader->GetRequestInfo();
+ if (info->cross_site_handler())
+ info->cross_site_handler()->ResumeResponseDeferredAtStart(id.request_id);
+ }
+}
+
void ResourceDispatcherHostImpl::CancelRequestsForContext(
ResourceContext* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -398,7 +498,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
// the requests to cancel first, and then we start cancelling. We assert at
// the end that there are no more to cancel since the context is about to go
// away.
- typedef std::vector<linked_ptr<ResourceLoader> > LoaderList;
+ typedef std::vector<linked_ptr<ResourceLoader>> LoaderList;
LoaderList loaders_to_cancel;
for (LoaderMap::iterator i = pending_loaders_.begin();
@@ -444,15 +544,16 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
for (LoaderList::iterator i = loaders_to_cancel.begin();
i != loaders_to_cancel.end(); ++i) {
// There is no strict requirement that this be the case, but currently
- // downloads, streams, detachable requests, and transferred requests are the
- // only requests that aren't cancelled when the associated processes go
- // away. It may be OK for this invariant to change in the future, but if
- // this assertion fires without the invariant changing, then it's indicative
- // of a leak.
+ // downloads, streams, detachable requests, transferred requests, and
+ // browser-owned requests are the only requests that aren't cancelled when
+ // the associated processes go away. It may be OK for this invariant to
+ // change in the future, but if this assertion fires without the invariant
+ // changing, then it's indicative of a leak.
DCHECK((*i)->GetRequestInfo()->IsDownload() ||
(*i)->GetRequestInfo()->is_stream() ||
((*i)->GetRequestInfo()->detachable_handler() &&
(*i)->GetRequestInfo()->detachable_handler()->is_detached()) ||
+ (*i)->GetRequestInfo()->GetProcessType() == PROCESS_TYPE_BROWSER ||
(*i)->is_transferring());
}
#endif
@@ -517,6 +618,15 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
}
request->SetLoadFlags(request->load_flags() | extra_load_flags);
+ // We treat a download as a main frame load, and thus update the policy URL on
+ // redirects.
+ //
+ // TODO(davidben): Is this correct? If this came from a
+ // ViewHostMsg_DownloadUrl in a frame, should it have first-party URL set
+ // appropriately?
+ request->set_first_party_url_policy(
+ net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
+
// Check if the renderer is permitted to request the requested URL.
if (!ChildProcessSecurityPolicyImpl::GetInstance()->
CanRequestURL(child_id, url)) {
@@ -543,7 +653,7 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
if (request->url().SchemeIs(url::kBlobScheme)) {
ChromeBlobStorageContext* blob_context =
GetChromeBlobStorageContextForResourceContext(context);
- webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle(
+ storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
request.get(),
blob_context->context()->GetBlobDataFromPublicURL(request->url()));
}
@@ -631,23 +741,19 @@ ResourceDispatcherHostImpl::MaybeInterceptAsStream(net::URLRequest* request,
origin));
info->set_is_stream(true);
- delegate_->OnStreamCreated(
- request,
- handler->stream()->CreateHandle(
- request->url(),
- mime_type,
- response->head.headers));
- return handler.PassAs<ResourceHandler>();
-}
-
-void ResourceDispatcherHostImpl::ClearSSLClientAuthHandlerForRequest(
- net::URLRequest* request) {
- ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
- if (info) {
- ResourceLoader* loader = GetLoader(info->GetGlobalRequestID());
- if (loader)
- loader->ClearSSLClientAuthHandler();
+ scoped_ptr<StreamInfo> stream_info(new StreamInfo);
+ stream_info->handle = handler->stream()->CreateHandle();
+ stream_info->original_url = request->url();
+ stream_info->mime_type = mime_type;
+ // Make a copy of the response headers so it is safe to pass across threads;
+ // the old handler (AsyncResourceHandler) may modify it in parallel via the
+ // ResourceDispatcherHostDelegate.
+ if (response->head.headers.get()) {
+ stream_info->response_headers =
+ new net::HttpResponseHeaders(response->head.headers->raw_headers());
}
+ delegate_->OnStreamCreated(request, stream_info.Pass());
+ return handler.Pass();
}
ResourceDispatcherHostLoginDelegate*
@@ -667,7 +773,7 @@ bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
- if (!ResourceType::IsFrame(info->GetResourceType()))
+ if (!IsResourceTypeFrame(info->GetResourceType()))
return false;
const net::URLRequestJobFactory* job_factory =
@@ -713,7 +819,7 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
if (loader->request()->was_fetched_via_proxy() &&
loader->request()->was_fetched_via_spdy() &&
- loader->request()->url().SchemeIs("http")) {
+ loader->request()->url().SchemeIs(url::kHttpScheme)) {
scheduler_->OnReceivedSpdyProxiedHttpResponse(
info->GetChildID(), info->GetRouteID());
}
@@ -737,7 +843,7 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
ResourceRequestInfo* info = loader->GetRequestInfo();
// Record final result of all resource loads.
- if (info->GetResourceType() == ResourceType::MAIN_FRAME) {
+ if (info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME) {
// This enumeration has "3" appended to its name to distinguish it from
// older versions.
UMA_HISTOGRAM_SPARSE_SLOWLY(
@@ -758,7 +864,7 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
"Net.CertificateTransparency.MainFrameValidSCTCount", num_valid_scts);
}
} else {
- if (info->GetResourceType() == ResourceType::IMAGE) {
+ if (info->GetResourceType() == RESOURCE_TYPE_IMAGE) {
UMA_HISTOGRAM_SPARSE_SLOWLY(
"Net.ErrorCodesForImages",
-loader->request()->status().error());
@@ -769,6 +875,11 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
-loader->request()->status().error());
}
+ if (loader->request()->url().SchemeIsSecure()) {
+ RecordCertificateHistograms(loader->request()->ssl_info(),
+ info->GetResourceType());
+ }
+
if (delegate_)
delegate_->RequestComplete(loader->request());
@@ -856,6 +967,19 @@ void ResourceDispatcherHostImpl::OnRequestResource(
int routing_id,
int request_id,
const ResourceHostMsg_Request& request_data) {
+ // When logging time-to-network only care about main frame and non-transfer
+ // navigations.
+ if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME &&
+ request_data.transferred_request_request_id == -1) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&LogResourceRequestTimeOnUI,
+ TimeTicks::Now(),
+ filter_->child_id(),
+ request_data.render_frame_id,
+ request_data.url));
+ }
BeginRequest(request_id, request_data, NULL, routing_id);
}
@@ -890,10 +1014,13 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
GlobalRequestID new_request_id(child_id, request_id);
// Clear out data that depends on |info| before updating it.
+ // We always need to move the memory stats to the new process. In contrast,
+ // stats.num_requests is only tracked for some requests (those that require
+ // file descriptors for their shared memory buffer).
IncrementOutstandingRequestsMemory(-1, *info);
- OustandingRequestsStats empty_stats = { 0, 0 };
- OustandingRequestsStats old_stats = GetOutstandingRequestsStats(*info);
- UpdateOutstandingRequestsStats(*info, empty_stats);
+ bool should_update_count = info->counted_as_in_flight_request();
+ if (should_update_count)
+ IncrementOutstandingRequestsCount(-1, info);
pending_loaders_.erase(old_request_id);
// ResourceHandlers should always get state related to the request from the
@@ -906,8 +1033,9 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
// Update maps that used the old IDs, if necessary. Some transfers in tests
// do not actually use a different ID, so not all maps need to be updated.
pending_loaders_[new_request_id] = loader;
- UpdateOutstandingRequestsStats(*info, old_stats);
IncrementOutstandingRequestsMemory(1, *info);
+ if (should_update_count)
+ IncrementOutstandingRequestsCount(1, info);
if (old_routing_id != new_routing_id) {
if (blocked_loaders_map_.find(old_routing_id) !=
blocked_loaders_map_.end()) {
@@ -999,9 +1127,7 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
// Allow the observer to block/handle the request.
- if (delegate_ && !delegate_->ShouldBeginRequest(child_id,
- route_id,
- request_data.method,
+ if (delegate_ && !delegate_->ShouldBeginRequest(request_data.method,
request_data.url,
request_data.resource_type,
resource_context)) {
@@ -1034,6 +1160,13 @@ void ResourceDispatcherHostImpl::BeginRequest(
new_request->set_first_party_for_cookies(
request_data.first_party_for_cookies);
+ // If the request is a MAIN_FRAME request, the first-party URL gets updated on
+ // redirects.
+ if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) {
+ new_request->set_first_party_url_policy(
+ net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
+ }
+
const Referrer referrer(request_data.referrer, request_data.referrer_policy);
SetReferrerForRequest(new_request.get(), referrer);
@@ -1043,18 +1176,31 @@ void ResourceDispatcherHostImpl::BeginRequest(
new_request->SetLoadFlags(load_flags);
+ storage::BlobStorageContext* blob_context =
+ GetBlobStorageContext(filter_->blob_storage_context());
// Resolve elements from request_body and prepare upload data.
if (request_data.request_body.get()) {
+ // |blob_context| could be null when the request is from the plugins because
+ // ResourceMessageFilters created in PluginProcessHost don't have the blob
+ // context.
+ if (blob_context) {
+ // Attaches the BlobDataHandles to request_body not to free the blobs and
+ // any attached shareable files until upload completion. These data will
+ // be used in UploadDataStream and ServiceWorkerURLRequestJob.
+ AttachRequestBodyBlobDataHandles(
+ request_data.request_body.get(),
+ blob_context);
+ }
new_request->set_upload(UploadDataStreamBuilder::Build(
request_data.request_body.get(),
- GetBlobStorageContext(filter_),
+ blob_context,
filter_->file_system_context(),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
.get()));
}
bool allow_download = request_data.allow_download &&
- ResourceType::IsFrame(request_data.resource_type);
+ IsResourceTypeFrame(request_data.resource_type);
// Make extra info and read footer (contains request ID).
ResourceRequestInfoImpl* extra_info =
@@ -1075,6 +1221,8 @@ void ResourceDispatcherHostImpl::BeginRequest(
false, // is stream
allow_download,
request_data.has_user_gesture,
+ request_data.enable_load_timing,
+ request_data.enable_upload_progress,
request_data.referrer_policy,
request_data.visiblity_state,
resource_context,
@@ -1086,20 +1234,29 @@ void ResourceDispatcherHostImpl::BeginRequest(
if (new_request->url().SchemeIs(url::kBlobScheme)) {
// Hang on to a reference to ensure the blob is not released prior
// to the job being started.
- webkit_blob::BlobProtocolHandler::SetRequestedBlobDataHandle(
+ storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
new_request.get(),
- filter_->blob_storage_context()->context()->
- GetBlobDataFromPublicURL(new_request->url()));
+ filter_->blob_storage_context()->context()->GetBlobDataFromPublicURL(
+ new_request->url()));
}
- // Initialize the service worker handler for the request.
+ // Initialize the service worker handler for the request. We don't use
+ // ServiceWorker for synchronous loads to avoid renderer deadlocks. We
+ // don't use ServiceWorker for favicons to avoid cache tainting.
+ bool is_favicon_load = request_data.resource_type == RESOURCE_TYPE_FAVICON;
ServiceWorkerRequestHandler::InitializeHandler(
new_request.get(),
filter_->service_worker_context(),
- GetBlobStorageContext(filter_),
+ blob_context,
child_id,
request_data.service_worker_provider_id,
- request_data.resource_type);
+ request_data.skip_service_worker || is_sync_load || is_favicon_load,
+ request_data.fetch_request_mode,
+ request_data.fetch_credentials_mode,
+ request_data.resource_type,
+ request_data.fetch_request_context_type,
+ request_data.fetch_frame_type,
+ request_data.request_body);
// Have the appcache associate its extra info with the request.
AppCacheInterceptor::SetExtraRequestInfo(
@@ -1153,20 +1310,41 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
handler.Pass()));
}
- // Install a CrossSiteResourceHandler for all main frame requests. This will
- // let us check whether a transfer is required and pause for the unload
- // handler either if so or if a cross-process navigation is already under way.
- bool is_swappable_navigation =
- request_data.resource_type == ResourceType::MAIN_FRAME;
- // If we are using --site-per-process, install it for subframes as well.
- if (!is_swappable_navigation &&
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
- is_swappable_navigation =
- request_data.resource_type == ResourceType::SUB_FRAME;
+ // PlzNavigate: If using --enable-browser-side-navigation, the
+ // CrossSiteResourceHandler is not needed. This codepath is not used for the
+ // actual navigation request, but only the subsequent blob URL load. This does
+ // not require request transfers.
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation)) {
+ // Install a CrossSiteResourceHandler for all main frame requests. This will
+ // check whether a transfer is required and, if so, pause for the UI thread
+ // to drive the transfer.
+ bool is_swappable_navigation =
+ request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME;
+ // If we are using --site-per-process, install it for subframes as well.
+ if (!is_swappable_navigation &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess)) {
+ is_swappable_navigation =
+ request_data.resource_type == RESOURCE_TYPE_SUB_FRAME;
+ }
+ if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER)
+ handler.reset(new CrossSiteResourceHandler(handler.Pass(), request));
}
- if (is_swappable_navigation && process_type == PROCESS_TYPE_RENDERER)
- handler.reset(new CrossSiteResourceHandler(handler.Pass(), request));
+ return AddStandardHandlers(request, request_data.resource_type,
+ resource_context, filter_->appcache_service(),
+ child_id, route_id, handler.Pass());
+}
+
+scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
+ net::URLRequest* request,
+ ResourceType resource_type,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ int child_id,
+ int route_id,
+ scoped_ptr<ResourceHandler> handler) {
// Insert a buffered event handler before the actual one.
handler.reset(
new BufferedResourceHandler(handler.Pass(), this, request));
@@ -1175,10 +1353,8 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
if (delegate_) {
delegate_->RequestBeginning(request,
resource_context,
- filter_->appcache_service(),
- request_data.resource_type,
- child_id,
- route_id,
+ appcache_service,
+ resource_type,
&throttles);
}
@@ -1208,7 +1384,7 @@ void ResourceDispatcherHostImpl::RegisterDownloadedTempFile(
int child_id, int request_id, const base::FilePath& file_path) {
scoped_refptr<ShareableFileReference> reference =
ShareableFileReference::Get(file_path);
- DCHECK(reference);
+ DCHECK(reference.get());
registered_temp_files_[child_id][request_id] = reference;
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
@@ -1288,13 +1464,15 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
false, // is_main_frame
false, // parent_is_main_frame
-1, // parent_render_frame_id
- ResourceType::SUB_RESOURCE,
- PAGE_TRANSITION_LINK,
+ RESOURCE_TYPE_SUB_RESOURCE,
+ ui::PAGE_TRANSITION_LINK,
false, // should_replace_current_entry
download, // is_download
false, // is_stream
download, // allow_download
false, // has_user_gesture
+ false, // enable_load_timing
+ false, // enable_upload_progress
blink::WebReferrerPolicyDefault,
blink::WebPageVisibilityStateVisible,
context,
@@ -1302,10 +1480,11 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
true); // is_async
}
-void ResourceDispatcherHostImpl::OnRenderViewHostCreated(
- int child_id,
- int route_id) {
- scheduler_->OnClientCreated(child_id, route_id);
+void ResourceDispatcherHostImpl::OnRenderViewHostCreated(int child_id,
+ int route_id,
+ bool is_visible,
+ bool is_audible) {
+ scheduler_->OnClientCreated(child_id, route_id, is_visible, is_audible);
}
void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(
@@ -1315,6 +1494,31 @@ void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(
CancelRequestsForRoute(child_id, route_id);
}
+void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
+ int route_id,
+ bool is_loading) {
+ scheduler_->OnLoadingStateChanged(child_id, route_id, !is_loading);
+}
+
+void ResourceDispatcherHostImpl::OnRenderViewHostWasHidden(
+ int child_id,
+ int route_id) {
+ scheduler_->OnVisibilityChanged(child_id, route_id, false);
+}
+
+void ResourceDispatcherHostImpl::OnRenderViewHostWasShown(
+ int child_id,
+ int route_id) {
+ scheduler_->OnVisibilityChanged(child_id, route_id, true);
+}
+
+void ResourceDispatcherHostImpl::OnAudioRenderHostStreamStateChanged(
+ int child_id,
+ int route_id,
+ bool is_playing) {
+ scheduler_->OnAudibilityChanged(child_id, route_id, is_playing);
+}
+
// This function is only used for saving feature.
void ResourceDispatcherHostImpl::BeginSaveFile(
const GURL& url,
@@ -1388,12 +1592,9 @@ void ResourceDispatcherHostImpl::CancelTransferringNavigation(
void ResourceDispatcherHostImpl::ResumeDeferredNavigation(
const GlobalRequestID& id) {
ResourceLoader* loader = GetLoader(id);
- if (loader) {
- // The response we were meant to resume could have already been canceled.
- ResourceRequestInfoImpl* info = loader->GetRequestInfo();
- if (info->cross_site_handler())
- info->cross_site_handler()->ResumeResponse();
- }
+ // The response we were meant to resume could have already been canceled.
+ if (loader)
+ loader->CompleteTransfer();
}
// The object died, so cancel and detach all requests associated with it except
@@ -1564,23 +1765,28 @@ ResourceDispatcherHostImpl::IncrementOutstandingRequestsMemory(
ResourceDispatcherHostImpl::OustandingRequestsStats
ResourceDispatcherHostImpl::IncrementOutstandingRequestsCount(
int count,
- const ResourceRequestInfoImpl& info) {
+ ResourceRequestInfoImpl* info) {
DCHECK_EQ(1, abs(count));
num_in_flight_requests_ += count;
- OustandingRequestsStats stats = GetOutstandingRequestsStats(info);
+ // Keep track of whether this request is counting toward the number of
+ // in-flight requests for this process, in case we need to transfer it to
+ // another process. This should be a toggle.
+ DCHECK_NE(info->counted_as_in_flight_request(), count > 0);
+ info->set_counted_as_in_flight_request(count > 0);
+
+ OustandingRequestsStats stats = GetOutstandingRequestsStats(*info);
stats.num_requests += count;
DCHECK_GE(stats.num_requests, 0);
- UpdateOutstandingRequestsStats(info, stats);
+ UpdateOutstandingRequestsStats(*info, stats);
return stats;
}
bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest(
- const net::URLRequest* request_) {
- const ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(request_);
- OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, *info);
+ net::URLRequest* request) {
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
+ OustandingRequestsStats stats = IncrementOutstandingRequestsCount(1, info);
if (stats.num_requests > max_num_in_flight_requests_per_process_)
return false;
@@ -1591,10 +1797,175 @@ bool ResourceDispatcherHostImpl::HasSufficientResourcesForRequest(
}
void ResourceDispatcherHostImpl::FinishedWithResourcesForRequest(
- const net::URLRequest* request_) {
- const ResourceRequestInfoImpl* info =
- ResourceRequestInfoImpl::ForRequest(request_);
- IncrementOutstandingRequestsCount(-1, *info);
+ net::URLRequest* request) {
+ ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
+ IncrementOutstandingRequestsCount(-1, info);
+}
+
+void ResourceDispatcherHostImpl::BeginNavigationRequest(
+ ResourceContext* resource_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& params,
+ const NavigationRequestInfo& info,
+ scoped_refptr<ResourceRequestBody> request_body,
+ NavigationURLLoaderImplCore* loader) {
+ // PlzNavigate: BeginNavigationRequest currently should only be used for the
+ // browser-side navigations project.
+ CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+
+ ResourceType resource_type = info.is_main_frame ?
+ RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME;
+
+ if (is_shutdown_ ||
+ // TODO(davidben): Check ShouldServiceRequest here. This is important; it
+ // needs to be checked relative to the child that /requested/ the
+ // navigation. It's where file upload checks, etc., come in.
+ (delegate_ && !delegate_->ShouldBeginRequest(
+ info.navigation_params.method,
+ params.url,
+ resource_type,
+ resource_context))) {
+ loader->NotifyRequestFailed(net::ERR_ABORTED);
+ return;
+ }
+
+ // Save the URL on the stack to help catch URLRequests which outlive their
+ // URLRequestContexts. See https://crbug.com/90971
+ char url_buf[128];
+ base::strlcpy(url_buf, params.url.spec().c_str(), arraysize(url_buf));
+ base::debug::Alias(url_buf);
+ CHECK(ContainsKey(active_resource_contexts_, resource_context));
+
+ const net::URLRequestContext* request_context =
+ resource_context->GetRequestContext();
+
+ int load_flags = info.navigation_params.load_flags;
+ load_flags |= net::LOAD_VERIFY_EV_CERT;
+ if (info.is_main_frame) {
+ load_flags |= net::LOAD_MAIN_FRAME;
+ } else {
+ load_flags |= net::LOAD_SUB_FRAME;
+ }
+ // Add a flag to selectively bypass the data reduction proxy if the resource
+ // type is not an image.
+ load_flags |= net::LOAD_BYPASS_DATA_REDUCTION_PROXY;
+
+ // TODO(davidben): BuildLoadFlagsForRequest includes logic for
+ // CanSendCookiesForOrigin and CanReadRawCookies. Is this needed here?
+
+ // Sync loads should have maximum priority and should be the only
+ // requests that have the ignore limits flag set.
+ DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
+
+ // TODO(davidben): OverrideCookieStoreForRenderProcess handling for
+ // prerender. There may not be a renderer process yet, so we need to use the
+ // ResourceContext or something.
+ scoped_ptr<net::URLRequest> new_request;
+ new_request = request_context->CreateRequest(params.url, net::HIGHEST,
+ nullptr, nullptr);
+
+ new_request->set_method(info.navigation_params.method);
+ new_request->set_first_party_for_cookies(
+ info.first_party_for_cookies);
+ if (info.is_main_frame) {
+ new_request->set_first_party_url_policy(
+ net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
+ }
+
+ SetReferrerForRequest(new_request.get(), params.referrer);
+
+ net::HttpRequestHeaders headers;
+ headers.AddHeadersFromString(info.navigation_params.headers);
+ new_request->SetExtraRequestHeaders(headers);
+
+ new_request->SetLoadFlags(load_flags);
+
+ // Resolve elements from request_body and prepare upload data.
+ if (info.navigation_params.request_body.get()) {
+ storage::BlobStorageContext* blob_context = GetBlobStorageContext(
+ GetChromeBlobStorageContextForResourceContext(resource_context));
+ AttachRequestBodyBlobDataHandles(
+ info.navigation_params.request_body.get(),
+ blob_context);
+ // TODO(davidben): The FileSystemContext is null here. In the case where
+ // another renderer requested this navigation, this should be the same
+ // FileSystemContext passed into ShouldServiceRequest.
+ new_request->set_upload(UploadDataStreamBuilder::Build(
+ info.navigation_params.request_body.get(),
+ blob_context,
+ nullptr, // file_system_context
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
+ .get()));
+ }
+
+ request_id_--;
+
+ // Make extra info and read footer (contains request ID).
+ //
+ // TODO(davidben): Associate the request with the FrameTreeNode and/or tab so
+ // that IO thread -> UI thread hops will work.
+ ResourceRequestInfoImpl* extra_info =
+ new ResourceRequestInfoImpl(
+ PROCESS_TYPE_BROWSER,
+ -1, // child_id
+ -1, // route_id
+ -1, // request_data.origin_pid,
+ request_id_,
+ -1, // request_data.render_frame_id,
+ info.is_main_frame,
+ info.parent_is_main_frame,
+ -1, // request_data.parent_render_frame_id,
+ resource_type,
+ params.transition,
+ // should_replace_current_entry. This was only maintained at layer for
+ // request transfers and isn't needed for browser-side navigations.
+ false,
+ false, // is download
+ false, // is stream
+ params.allow_download,
+ info.navigation_params.has_user_gesture,
+ true, // enable_load_timing
+ false, // enable_upload_progress
+ params.referrer.policy,
+ // TODO(davidben): This is only used for prerenders. Replace
+ // is_showing with something for that. Or maybe it just comes from the
+ // same mechanism as the cookie one.
+ blink::WebPageVisibilityStateVisible,
+ resource_context,
+ base::WeakPtr<ResourceMessageFilter>(), // filter
+ true);
+ // Request takes ownership.
+ extra_info->AssociateWithRequest(new_request.get());
+
+ if (new_request->url().SchemeIs(url::kBlobScheme)) {
+ // Hang on to a reference to ensure the blob is not released prior
+ // to the job being started.
+ ChromeBlobStorageContext* blob_context =
+ GetChromeBlobStorageContextForResourceContext(resource_context);
+ storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
+ new_request.get(),
+ blob_context->context()->GetBlobDataFromPublicURL(new_request->url()));
+ }
+
+ // TODO(davidben): Attach ServiceWorkerRequestHandler.
+
+ // TODO(davidben): Attach AppCacheInterceptor.
+
+ scoped_ptr<ResourceHandler> handler(new NavigationResourceHandler(
+ new_request.get(), loader));
+
+ // TODO(davidben): Pass in the appropriate appcache_service. Also fix the
+ // dependency on child_id/route_id. Those are used by the ResourceScheduler;
+ // currently it's a no-op.
+ handler = AddStandardHandlers(new_request.get(), resource_type,
+ resource_context,
+ nullptr, // appcache_service
+ -1, // child_id
+ -1, // route_id
+ handler.Pass());
+
+ BeginRequestInternal(new_request.Pass(), handler.Pass());
}
// static
@@ -1925,15 +2296,15 @@ int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest(
// keep-alive connection created to load a sub-frame or a sub-resource could
// be reused to load a main frame.
load_flags |= net::LOAD_VERIFY_EV_CERT;
- if (request_data.resource_type == ResourceType::MAIN_FRAME) {
+ if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) {
load_flags |= net::LOAD_MAIN_FRAME;
- } else if (request_data.resource_type == ResourceType::SUB_FRAME) {
+ } else if (request_data.resource_type == RESOURCE_TYPE_SUB_FRAME) {
load_flags |= net::LOAD_SUB_FRAME;
- } else if (request_data.resource_type == ResourceType::PREFETCH) {
+ } else if (request_data.resource_type == RESOURCE_TYPE_PREFETCH) {
load_flags |= (net::LOAD_PREFETCH | net::LOAD_DO_NOT_PROMPT_FOR_LOGIN);
- } else if (request_data.resource_type == ResourceType::FAVICON) {
+ } else if (request_data.resource_type == RESOURCE_TYPE_FAVICON) {
load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN;
- } else if (request_data.resource_type == ResourceType::IMAGE) {
+ } else if (request_data.resource_type == RESOURCE_TYPE_IMAGE) {
// Prevent third-party image content from prompting for login, as this
// is often a scam to extract credentials for another domain from the user.
// Only block image loads, as the attack applies largely to the "src"
@@ -1969,6 +2340,11 @@ int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest(
load_flags &= ~net::LOAD_REPORT_RAW_HEADERS;
}
+ // Add a flag to selectively bypass the data reduction proxy if the resource
+ // type is not an image.
+ if (request_data.resource_type != RESOURCE_TYPE_IMAGE)
+ load_flags |= net::LOAD_BYPASS_DATA_REDUCTION_PROXY;
+
return load_flags;
}
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 3cc7b4fd1ec..a96af553b4a 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -30,16 +30,17 @@
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_scheduler.h"
#include "content/common/content_export.h"
+#include "content/common/resource_request_body.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_dispatcher_host.h"
+#include "content/public/common/resource_type.h"
#include "ipc/ipc_message.h"
#include "net/cookies/canonical_cookie.h"
#include "net/url_request/url_request.h"
-#include "webkit/common/resource_type.h"
class ResourceHandler;
struct ResourceHostMsg_Request;
@@ -48,11 +49,13 @@ namespace net {
class URLRequestJobFactory;
}
-namespace webkit_blob {
+namespace storage {
class ShareableFileReference;
}
namespace content {
+class AppCacheService;
+class NavigationURLLoaderImplCore;
class ResourceContext;
class ResourceDispatcherHostDelegate;
class ResourceMessageDelegate;
@@ -60,7 +63,9 @@ class ResourceMessageFilter;
class ResourceRequestInfoImpl;
class SaveFileManager;
class WebContentsImpl;
+struct CommonNavigationParams;
struct DownloadSaveInfo;
+struct NavigationRequestInfo;
struct Referrer;
class CONTENT_EXPORT ResourceDispatcherHostImpl
@@ -68,16 +73,16 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
public ResourceLoaderDelegate {
public:
ResourceDispatcherHostImpl();
- virtual ~ResourceDispatcherHostImpl();
+ ~ResourceDispatcherHostImpl() override;
// Returns the current ResourceDispatcherHostImpl. May return NULL if it
// hasn't been created yet.
static ResourceDispatcherHostImpl* Get();
// ResourceDispatcherHost implementation:
- virtual void SetDelegate(ResourceDispatcherHostDelegate* delegate) OVERRIDE;
- virtual void SetAllowCrossOriginAuthPrompt(bool value) OVERRIDE;
- virtual DownloadInterruptReason BeginDownload(
+ void SetDelegate(ResourceDispatcherHostDelegate* delegate) override;
+ void SetAllowCrossOriginAuthPrompt(bool value) override;
+ DownloadInterruptReason BeginDownload(
scoped_ptr<net::URLRequest> request,
const Referrer& referrer,
bool is_content_initiated,
@@ -87,11 +92,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool prefer_cache,
scoped_ptr<DownloadSaveInfo> save_info,
uint32 download_id,
- const DownloadStartedCallback& started_callback) OVERRIDE;
- virtual void ClearLoginDelegateForRequest(net::URLRequest* request) OVERRIDE;
- virtual void BlockRequestsForRoute(int child_id, int route_id) OVERRIDE;
- virtual void ResumeBlockedRequestsForRoute(
- int child_id, int route_id) OVERRIDE;
+ const DownloadStartedCallback& started_callback) override;
+ void ClearLoginDelegateForRequest(net::URLRequest* request) override;
+ void BlockRequestsForRoute(int child_id, int route_id) override;
+ void ResumeBlockedRequestsForRoute(int child_id, int route_id) override;
// Puts the resource dispatcher host in an inactive state (unable to begin
// new requests). Cancels all pending requests.
@@ -103,6 +107,9 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Notify the ResourceDispatcherHostImpl of a resource context destruction.
void RemoveResourceContext(ResourceContext* context);
+ // Resumes a request that deferred at response start.
+ void ResumeResponseDeferredAtStart(const GlobalRequestID& id);
+
// Force cancels any pending requests for the given |context|. This is
// necessary to ensure that before |context| goes away, all requests
// for it are dead.
@@ -159,11 +166,30 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
}
// Called when a RenderViewHost is created.
- void OnRenderViewHostCreated(int child_id, int route_id);
+ void OnRenderViewHostCreated(int child_id,
+ int route_id,
+ bool is_visible,
+ bool is_audible);
// Called when a RenderViewHost is deleted.
void OnRenderViewHostDeleted(int child_id, int route_id);
+ // Called when a RenderViewHost starts or stops loading.
+ void OnRenderViewHostSetIsLoading(int child_id,
+ int route_id,
+ bool is_loading);
+
+ // Called when a RenderViewHost is hidden.
+ void OnRenderViewHostWasHidden(int child_id, int route_id);
+
+ // Called when a RenderViewHost is shown.
+ void OnRenderViewHostWasShown(int child_id, int route_id);
+
+ // Called when an AudioRenderHost starts or stops playing.
+ void OnAudioRenderHostStreamStateChanged(int child_id,
+ int route_id,
+ bool is_playing);
+
// Force cancels any pending requests for the given process.
void CancelRequestsForProcess(int child_id);
@@ -211,27 +237,34 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Must be called after the ResourceRequestInfo has been created
// and associated with the request. If |payload| is set to a non-empty value,
- // the value will be sent to the old resource handler instead of cancelling
+ // the value will be sent to the old resource handler instead of canceling
// it, except on HTTP errors.
scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
net::URLRequest* request,
ResourceResponse* response,
std::string* payload);
- void ClearSSLClientAuthHandlerForRequest(net::URLRequest* request);
-
ResourceScheduler* scheduler() { return scheduler_.get(); }
// Called by a ResourceHandler when it's ready to start reading data and
// sending it to the renderer. Returns true if there are enough file
// descriptors available for the shared memory buffer. If false is returned,
// the request should cancel.
- bool HasSufficientResourcesForRequest(const net::URLRequest* request_);
+ bool HasSufficientResourcesForRequest(net::URLRequest* request);
// Called by a ResourceHandler after it has finished its request and is done
// using its shared memory buffer. Frees up that file descriptor to be used
// elsewhere.
- void FinishedWithResourcesForRequest(const net::URLRequest* request_);
+ void FinishedWithResourcesForRequest(net::URLRequest* request);
+
+ // PlzNavigate: Begins a request for NavigationURLLoader. |loader| is the
+ // loader to attach to the leaf resource handler.
+ void BeginNavigationRequest(ResourceContext* resource_context,
+ int64 frame_tree_node_id,
+ const CommonNavigationParams& common_params,
+ const NavigationRequestInfo& info,
+ scoped_refptr<ResourceRequestBody> request_body,
+ NavigationURLLoaderImplCore* loader);
private:
friend class ResourceDispatcherHostTest;
@@ -256,16 +289,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
friend class ResourceMessageDelegate;
// ResourceLoaderDelegate implementation:
- virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
+ ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
ResourceLoader* loader,
- net::AuthChallengeInfo* auth_info) OVERRIDE;
- virtual bool HandleExternalProtocol(ResourceLoader* loader,
- const GURL& url) OVERRIDE;
- virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE;
- virtual void DidReceiveRedirect(ResourceLoader* loader,
- const GURL& new_url) OVERRIDE;
- virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE;
- virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE;
+ net::AuthChallengeInfo* auth_info) override;
+ bool HandleExternalProtocol(ResourceLoader* loader, const GURL& url) override;
+ void DidStartRequest(ResourceLoader* loader) override;
+ void DidReceiveRedirect(ResourceLoader* loader, const GURL& new_url) override;
+ void DidReceiveResponse(ResourceLoader* loader) override;
+ void DidFinishLoading(ResourceLoader* loader) override;
// An init helper that runs on the IO thread.
void OnInit();
@@ -304,12 +335,12 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int count,
const ResourceRequestInfoImpl& info);
- // Called every time an in flight request is issued or finished. |count|
- // indicates whether the request is issuing or finishing. |count| must be 1
- // or -1.
+ // Called when an in flight request allocates or releases a shared memory
+ // buffer. |count| indicates whether the request is issuing or finishing.
+ // |count| must be 1 or -1.
OustandingRequestsStats IncrementOutstandingRequestsCount(
int count,
- const ResourceRequestInfoImpl& info);
+ ResourceRequestInfoImpl* info);
// Estimate how much heap space |request| will consume to run.
static int CalculateApproximateMemoryCost(net::URLRequest* request);
@@ -372,6 +403,18 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int child_id,
ResourceContext* resource_context);
+ // Wraps |handler| in the standard resource handlers for normal resource
+ // loading and navigation requests. This adds BufferedResourceHandler and
+ // ResourceThrottles.
+ scoped_ptr<ResourceHandler> AddStandardHandlers(
+ net::URLRequest* request,
+ ResourceType resource_type,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ int child_id,
+ int route_id,
+ scoped_ptr<ResourceHandler> handler);
+
void OnDataDownloadedACK(int request_id);
void OnUploadProgressACK(int request_id);
void OnCancelRequest(int request_id);
@@ -423,7 +466,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Collection of temp files downloaded for child processes via
// the download_to_file mechanism. We avoid deleting them until
// the client no longer needs them.
- typedef std::map<int, scoped_refptr<webkit_blob::ShareableFileReference> >
+ typedef std::map<int, scoped_refptr<storage::ShareableFileReference> >
DeletableFilesMap; // key is request id
typedef std::map<int, DeletableFilesMap>
RegisteredTempFiles; // key is child process id
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index a815032ac6f..d18facde88a 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -6,8 +6,8 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
@@ -23,7 +23,7 @@
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/worker_host/worker_service_impl.h"
+#include "content/common/appcache_interfaces.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
@@ -37,10 +37,10 @@
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
+#include "net/base/elements_upload_data_stream.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
-#include "net/base/upload_data_stream.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -49,14 +49,13 @@
#include "net/url_request/url_request_simple_job.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/common/blob/shareable_file_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/common/blob/shareable_file_reference.h"
// TODO(eroman): Write unit tests for SafeBrowsing that exercise
// SafeBrowsingResourceHandler.
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace content {
@@ -126,10 +125,9 @@ static int RequestIDForMessage(const IPC::Message& msg) {
return request_id;
}
-static ResourceHostMsg_Request CreateResourceRequest(
- const char* method,
- ResourceType::Type type,
- const GURL& url) {
+static ResourceHostMsg_Request CreateResourceRequest(const char* method,
+ ResourceType type,
+ const GURL& url) {
ResourceHostMsg_Request request;
request.method = std::string(method);
request.url = url;
@@ -139,12 +137,12 @@ static ResourceHostMsg_Request CreateResourceRequest(
request.origin_pid = 0;
request.resource_type = type;
request.request_context = 0;
- request.appcache_host_id = appcache::kAppCacheNoHostId;
+ request.appcache_host_id = kAppCacheNoHostId;
request.download_to_file = false;
request.is_main_frame = true;
request.parent_is_main_frame = false;
request.parent_render_frame_id = -1;
- request.transition_type = PAGE_TRANSITION_LINK;
+ request.transition_type = ui::PAGE_TRANSITION_LINK;
request.allow_download = true;
return request;
}
@@ -225,7 +223,7 @@ class TestFilter : public ResourceMessageFilter {
int received_after_canceled() const { return received_after_canceled_; }
// ResourceMessageFilter override
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
// No messages should be received when the process has been canceled.
if (canceled_)
received_after_canceled_++;
@@ -237,7 +235,7 @@ class TestFilter : public ResourceMessageFilter {
ResourceContext* resource_context() { return resource_context_; }
protected:
- virtual ~TestFilter() {}
+ ~TestFilter() override {}
private:
void GetContexts(const ResourceHostMsg_Request& request,
@@ -267,12 +265,10 @@ class ForwardingFilter : public TestFilter {
}
// TestFilter override
- virtual bool Send(IPC::Message* msg) OVERRIDE {
- return dest_->Send(msg);
- }
+ bool Send(IPC::Message* msg) override { return dest_->Send(msg); }
private:
- virtual ~ForwardingFilter() {}
+ ~ForwardingFilter() override {}
IPC::Sender* dest_;
@@ -280,7 +276,7 @@ class ForwardingFilter : public TestFilter {
};
// This class is a variation on URLRequestTestJob that will call
-// URLRequest::OnBeforeNetworkStart before starting.
+// URLRequest::WillStartUsingNetwork before starting.
class URLRequestTestDelayedNetworkJob : public net::URLRequestTestJob {
public:
URLRequestTestDelayedNetworkJob(net::URLRequest* request,
@@ -288,7 +284,7 @@ class URLRequestTestDelayedNetworkJob : public net::URLRequestTestJob {
: net::URLRequestTestJob(request, network_delegate) {}
// Only start if not deferred for network start.
- virtual void Start() OVERRIDE {
+ void Start() override {
bool defer = false;
NotifyBeforeNetworkStart(&defer);
if (defer)
@@ -296,12 +292,10 @@ class URLRequestTestDelayedNetworkJob : public net::URLRequestTestJob {
net::URLRequestTestJob::Start();
}
- virtual void ResumeNetworkStart() OVERRIDE {
- net::URLRequestTestJob::StartAsync();
- }
+ void ResumeNetworkStart() override { net::URLRequestTestJob::StartAsync(); }
private:
- virtual ~URLRequestTestDelayedNetworkJob() {}
+ ~URLRequestTestDelayedNetworkJob() override {}
DISALLOW_COPY_AND_ASSIGN(URLRequestTestDelayedNetworkJob);
};
@@ -335,7 +329,7 @@ class URLRequestTestDelayedStartJob : public net::URLRequestTestJob {
}
// Do nothing until you're told to.
- virtual void Start() OVERRIDE {}
+ void Start() override {}
// Finish starting a URL request whose job is an instance of
// URLRequestTestDelayedStartJob. It is illegal to call this routine
@@ -366,7 +360,7 @@ class URLRequestTestDelayedStartJob : public net::URLRequestTestJob {
}
protected:
- virtual ~URLRequestTestDelayedStartJob() {
+ ~URLRequestTestDelayedStartJob() override {
for (URLRequestTestDelayedStartJob** job = &list_head_; *job;
job = &(*job)->next_) {
if (*job == this) {
@@ -413,10 +407,10 @@ class URLRequestTestDelayedCompletionJob : public net::URLRequestTestJob {
auto_advance) {}
protected:
- virtual ~URLRequestTestDelayedCompletionJob() {}
+ ~URLRequestTestDelayedCompletionJob() override {}
private:
- virtual bool NextReadAsync() OVERRIDE { return true; }
+ bool NextReadAsync() override { return true; }
};
class URLRequestBigJob : public net::URLRequestSimpleJob {
@@ -426,10 +420,10 @@ class URLRequestBigJob : public net::URLRequestSimpleJob {
: net::URLRequestSimpleJob(request, network_delegate) {
}
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* data,
- const net::CompletionCallback& callback) const OVERRIDE {
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const override {
*mime_type = "text/plain";
*charset = "UTF-8";
@@ -446,7 +440,7 @@ class URLRequestBigJob : public net::URLRequestSimpleJob {
}
private:
- virtual ~URLRequestBigJob() {}
+ ~URLRequestBigJob() override {}
// big-job:substring,N
static bool ParseURL(const GURL& url, std::string* text, int* count) {
@@ -493,20 +487,29 @@ class TestURLRequestJobFactory : public net::URLRequestJobFactory {
network_start_notification_ = notification;
}
- virtual net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
+ net::URLRequestJob* MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE;
+ net::NetworkDelegate* network_delegate) const override;
- virtual bool IsHandledProtocol(const std::string& scheme) const OVERRIDE {
+ net::URLRequestJob* MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const override;
+
+ net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override;
+
+ bool IsHandledProtocol(const std::string& scheme) const override {
return supported_schemes_.count(scheme) > 0;
}
- virtual bool IsHandledURL(const GURL& url) const OVERRIDE {
+ bool IsHandledURL(const GURL& url) const override {
return supported_schemes_.count(url.scheme()) > 0;
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
@@ -528,9 +531,7 @@ class TestUserData : public base::SupportsUserData::Data {
: was_deleted_(was_deleted) {
}
- virtual ~TestUserData() {
- *was_deleted_ = true;
- }
+ ~TestUserData() override { *was_deleted_ = true; }
private:
bool* was_deleted_;
@@ -539,9 +540,9 @@ class TestUserData : public base::SupportsUserData::Data {
class TransfersAllNavigationsContentBrowserClient
: public TestContentBrowserClient {
public:
- virtual bool ShouldSwapProcessesForRedirect(ResourceContext* resource_context,
- const GURL& current_url,
- const GURL& new_url) OVERRIDE {
+ bool ShouldSwapProcessesForRedirect(ResourceContext* resource_context,
+ const GURL& current_url,
+ const GURL& new_url) override {
return true;
}
};
@@ -568,13 +569,13 @@ class GenericResourceThrottle : public ResourceThrottle {
error_code_for_cancellation_(code) {
}
- virtual ~GenericResourceThrottle() {
+ ~GenericResourceThrottle() override {
if (active_throttle_ == this)
active_throttle_ = NULL;
}
// ResourceThrottle implementation:
- virtual void WillStartRequest(bool* defer) OVERRIDE {
+ void WillStartRequest(bool* defer) override {
ASSERT_EQ(NULL, active_throttle_);
if (flags_ & DEFER_STARTING_REQUEST) {
active_throttle_ = this;
@@ -590,7 +591,7 @@ class GenericResourceThrottle : public ResourceThrottle {
}
}
- virtual void WillProcessResponse(bool* defer) OVERRIDE {
+ void WillProcessResponse(bool* defer) override {
ASSERT_EQ(NULL, active_throttle_);
if (flags_ & DEFER_PROCESSING_RESPONSE) {
active_throttle_ = this;
@@ -598,7 +599,7 @@ class GenericResourceThrottle : public ResourceThrottle {
}
}
- virtual void OnBeforeNetworkStart(bool* defer) OVERRIDE {
+ void WillStartUsingNetwork(bool* defer) override {
ASSERT_EQ(NULL, active_throttle_);
if (flags_ & DEFER_NETWORK_START) {
@@ -607,7 +608,7 @@ class GenericResourceThrottle : public ResourceThrottle {
}
}
- virtual const char* GetNameForLogging() const OVERRIDE {
+ const char* GetNameForLogging() const override {
return "GenericResourceThrottle";
}
@@ -659,14 +660,11 @@ class TestResourceDispatcherHostDelegate
// ResourceDispatcherHostDelegate implementation:
- virtual void RequestBeginning(
- net::URLRequest* request,
- ResourceContext* resource_context,
- appcache::AppCacheService* appcache_service,
- ResourceType::Type resource_type,
- int child_id,
- int route_id,
- ScopedVector<ResourceThrottle>* throttles) OVERRIDE {
+ void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles) override {
if (user_data_) {
const void* key = user_data_.get();
request->SetUserData(key, user_data_.release());
@@ -733,7 +731,7 @@ class ResourceDispatcherHostTest : public testing::Test,
}
// IPC::Sender implementation
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
accum_.AddMessage(*msg);
if (send_data_received_acks_ &&
@@ -755,12 +753,12 @@ class ResourceDispatcherHostTest : public testing::Test,
friend class TestURLRequestJobFactory;
// testing::Test
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ChildProcessSecurityPolicyImpl::GetInstance()->Add(0);
HandleScheme("test");
}
- virtual void TearDown() {
+ void TearDown() override {
EXPECT_TRUE(URLRequestTestDelayedStartJob::DelayedStartQueueEmpty());
URLRequestTestDelayedStartJob::ClearQueue();
@@ -778,8 +776,6 @@ class ResourceDispatcherHostTest : public testing::Test,
ResourceDispatcherHostImpl::Get()->CancelRequestsForContext(
browser_context_->GetResourceContext());
- WorkerServiceImpl::GetInstance()->PerformTeardownForTesting();
-
browser_context_.reset();
base::RunLoop().RunUntilIdle();
}
@@ -801,9 +797,10 @@ class ResourceDispatcherHostTest : public testing::Test,
// Generates a request using the given filter and resource type.
void MakeTestRequestWithResourceType(ResourceMessageFilter* filter,
- int render_view_id, int request_id,
+ int render_view_id,
+ int request_id,
const GURL& url,
- ResourceType::Type type);
+ ResourceType type);
void CancelRequest(int request_id);
void RendererCancelRequest(int request_id) {
@@ -895,7 +892,7 @@ void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
int request_id,
const GURL& url) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
- url, ResourceType::SUB_RESOURCE);
+ url, RESOURCE_TYPE_SUB_RESOURCE);
}
void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
@@ -903,7 +900,7 @@ void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
int render_view_id,
int request_id,
const GURL& url,
- ResourceType::Type type) {
+ ResourceType type) {
ResourceHostMsg_Request request =
CreateResourceRequest("GET", type, url);
ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
@@ -1042,7 +1039,7 @@ TEST_F(ResourceDispatcherHostTest, TestMany) {
MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
MakeTestRequestWithResourceType(filter_.get(), 0, 4,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
MakeTestRequest(0, 5, net::URLRequestTestJob::test_url_redirect_to_url_2());
// Finish the redirection
@@ -1076,7 +1073,7 @@ TEST_F(ResourceDispatcherHostTest, Cancel) {
MakeTestRequestWithResourceType(filter_.get(), 0, 4,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
CancelRequest(2);
@@ -1127,7 +1124,7 @@ TEST_F(ResourceDispatcherHostTest, Cancel) {
TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_2(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
GlobalRequestID global_request_id(filter_->child_id(), 1);
ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
host_.GetURLRequest(global_request_id));
@@ -1169,14 +1166,14 @@ TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
// test_url_1's data is available synchronously, so use 2 and 3.
ResourceHostMsg_Request request_prefetch = CreateResourceRequest(
- "GET", ResourceType::PREFETCH, net::URLRequestTestJob::test_url_2());
+ "GET", RESOURCE_TYPE_PREFETCH, net::URLRequestTestJob::test_url_2());
ResourceHostMsg_Request request_ping = CreateResourceRequest(
- "GET", ResourceType::PING, net::URLRequestTestJob::test_url_3());
+ "GET", RESOURCE_TYPE_PING, net::URLRequestTestJob::test_url_3());
ResourceHostMsg_RequestResource msg_prefetch(0, 1, request_prefetch);
- host_.OnMessageReceived(msg_prefetch, filter_);
+ host_.OnMessageReceived(msg_prefetch, filter_.get());
ResourceHostMsg_RequestResource msg_ping(0, 2, request_ping);
- host_.OnMessageReceived(msg_ping, filter_);
+ host_.OnMessageReceived(msg_ping, filter_.get());
// Remove the filter before processing the requests by simulating channel
// closure.
@@ -1220,11 +1217,11 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
// resources should continue to load, even when redirected.
TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
ResourceHostMsg_Request request = CreateResourceRequest(
- "GET", ResourceType::PREFETCH,
+ "GET", RESOURCE_TYPE_PREFETCH,
net::URLRequestTestJob::test_url_redirect_to_url_2());
ResourceHostMsg_RequestResource msg(0, 1, request);
- host_.OnMessageReceived(msg, filter_);
+ host_.OnMessageReceived(msg, filter_.get());
// Remove the filter before processing the request by simulating channel
// closure.
@@ -1300,7 +1297,7 @@ TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
// Cancel request must come from the renderer for a detachable resource to
// detach.
RendererCancelRequest(1);
@@ -1370,7 +1367,7 @@ TEST_F(ResourceDispatcherHostTest, PausedStartError) {
EXPECT_EQ(0, host_.pending_requests());
}
-// Test the OnBeforeNetworkStart throttle.
+// Test the WillStartUsingNetwork throttle.
TEST_F(ResourceDispatcherHostTest, ThrottleNetworkStart) {
// Arrange to have requests deferred before processing response headers.
TestResourceDispatcherHostDelegate delegate;
@@ -1466,11 +1463,11 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
// request 1 goes to the test delegate
ResourceHostMsg_Request request = CreateResourceRequest(
- "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
+ "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
MakeTestRequestWithResourceType(test_filter.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
// request 2 goes to us
MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
@@ -1478,12 +1475,12 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
// request 3 goes to the test delegate
MakeTestRequestWithResourceType(test_filter.get(), 0, 3,
net::URLRequestTestJob::test_url_3(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
// request 4 goes to us
MakeTestRequestWithResourceType(filter_.get(), 0, 4,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
// Make sure all requests have finished stage one. test_url_1 will have
@@ -1540,7 +1537,7 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
GlobalRequestID global_request_id(filter_->child_id(), 1);
ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(
host_.GetURLRequest(global_request_id));
@@ -1651,7 +1648,7 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
// Blocked detachable resources should not delay cancellation.
MakeTestRequestWithResourceType(filter_.get(), 1, 5,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1685,19 +1682,19 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(second_filter.get(), 0, 2,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 0, 3,
net::URLRequestTestJob::test_url_3(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(second_filter.get(), 0, 4,
net::URLRequestTestJob::test_url_1(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(second_filter.get(), 0, 5,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
// Simulate process death.
host_.CancelRequestsForProcess(second_filter->child_id());
@@ -1733,28 +1730,28 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 1, 2,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 0, 3,
net::URLRequestTestJob::test_url_3(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(second_filter.get(), 1, 4,
net::URLRequestTestJob::test_url_1(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 2, 5,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 2, 6,
net::URLRequestTestJob::test_url_3(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 0, 7,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
MakeTestRequestWithResourceType(second_filter.get(), 1, 8,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
host_.CancelRequestsForProcess(filter_->child_id());
host_.CancelRequestsForProcess(second_filter->child_id());
@@ -1766,15 +1763,17 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
// Test the private helper method "CalculateApproximateMemoryCost()".
TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
net::URLRequestContext context;
- net::URLRequest req(
- GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL, &context);
- EXPECT_EQ(4427,
- ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
+ scoped_ptr<net::URLRequest> req(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL, NULL));
+ EXPECT_EQ(
+ 4427,
+ ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req.get()));
// Add 9 bytes of referrer.
- req.SetReferrer("123456789");
- EXPECT_EQ(4436,
- ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
+ req->SetReferrer("123456789");
+ EXPECT_EQ(
+ 4436,
+ ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req.get()));
// Add 33 bytes of upload content.
std::string upload_content;
@@ -1782,12 +1781,13 @@ TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
std::fill(upload_content.begin(), upload_content.end(), 'x');
scoped_ptr<net::UploadElementReader> reader(new net::UploadBytesElementReader(
upload_content.data(), upload_content.size()));
- req.set_upload(make_scoped_ptr(
- net::UploadDataStream::CreateWithReader(reader.Pass(), 0)));
+ req->set_upload(
+ net::ElementsUploadDataStream::CreateWithReader(reader.Pass(), 0));
// Since the upload throttling is disabled, this has no effect on the cost.
- EXPECT_EQ(4436,
- ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(&req));
+ EXPECT_EQ(
+ 4436,
+ ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(req.get()));
}
// Test that too much memory for outstanding requests for a particular
@@ -1815,25 +1815,25 @@ TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
for (size_t i = 0; i < kMaxRequests; ++i) {
MakeTestRequestWithResourceType(filter_.get(), 0, i + 1,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
}
// Issue two more requests for our process -- these should fail immediately.
MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequests + 1,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequests + 2,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
// Issue two requests for the second process -- these should succeed since
// it is just process 0 that is saturated.
MakeTestRequestWithResourceType(second_filter.get(), 0, kMaxRequests + 3,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
MakeTestRequestWithResourceType(second_filter.get(), 0, kMaxRequests + 4,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1884,25 +1884,25 @@ TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
for (size_t i = 0; i < kMaxRequestsPerProcess; ++i) {
MakeTestRequestWithResourceType(filter_.get(), 0, i + 1,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
}
// Issue another request for our process -- this should fail immediately.
MakeTestRequestWithResourceType(filter_.get(), 0, kMaxRequestsPerProcess + 1,
net::URLRequestTestJob::test_url_2(),
- ResourceType::SUB_RESOURCE);
+ RESOURCE_TYPE_SUB_RESOURCE);
// Issue a request for the second process -- this should succeed, because it
// is just process 0 that is saturated.
MakeTestRequestWithResourceType(
second_filter.get(), 0, kMaxRequestsPerProcess + 2,
- net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE);
+ net::URLRequestTestJob::test_url_2(), RESOURCE_TYPE_SUB_RESOURCE);
// Issue a request for the third process -- this should fail, because the
// global limit has been reached.
MakeTestRequestWithResourceType(
third_filter.get(), 0, kMaxRequestsPerProcess + 3,
- net::URLRequestTestJob::test_url_2(), ResourceType::SUB_RESOURCE);
+ net::URLRequestTestJob::test_url_2(), RESOURCE_TYPE_SUB_RESOURCE);
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -2046,7 +2046,7 @@ TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
// Only MAIN_FRAMEs can trigger a download.
MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("http:bla"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Flush all pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -2092,7 +2092,7 @@ TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Return some data so that the request is identified as a download
// and the proper resource handlers are created.
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
@@ -2127,7 +2127,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Return some data so that the request is identified as a download
// and the proper resource handlers are created.
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
@@ -2158,7 +2158,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
net::URLRequestTestJob::test_url_4(),
- ResourceType::PREFETCH); // detachable type
+ RESOURCE_TYPE_PREFETCH); // detachable type
// Simulate a cancel coming from the renderer.
RendererCancelRequest(request_id);
@@ -2194,7 +2194,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
GlobalRequestID global_request_id(filter_->child_id(), request_id);
@@ -2243,7 +2243,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Now that we're blocked on the redirect, update the response and unblock by
// telling the AsyncResourceHandler to follow the redirect.
@@ -2269,7 +2269,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
int new_request_id = 2;
ResourceHostMsg_Request request =
- CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
GURL("http://other.com/blech"));
request.transferred_request_child_id = filter_->child_id();
request.transferred_request_request_id = request_id;
@@ -2288,6 +2288,88 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
CheckSuccessfulRequest(msgs[1], kResponseBody);
}
+// Test transferring two navigations with text/html, to ensure the resource
+// accounting works.
+TEST_F(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
+ // This test expects the cross site request to be leaked, so it can transfer
+ // the request directly.
+ CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
+
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ // Configure initial request.
+ const std::string kResponseBody = "hello world";
+ SetResponse("HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n\n",
+ kResponseBody);
+
+ HandleScheme("http");
+
+ // Temporarily replace ContentBrowserClient with one that will trigger the
+ // transfer navigation code paths.
+ TransfersAllNavigationsContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ // Make the first request.
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("http://example.com/blah"),
+ RESOURCE_TYPE_MAIN_FRAME);
+
+ // Make a second request from the same process.
+ int second_request_id = 2;
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id,
+ second_request_id,
+ GURL("http://example.com/foo"),
+ RESOURCE_TYPE_MAIN_FRAME);
+
+ // Flush all the pending requests to get the response through the
+ // BufferedResourceHandler.
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
+
+ // Restore, now that we've set up a transfer.
+ SetBrowserClientForTesting(old_client);
+
+ // This second filter is used to emulate a second process.
+ scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
+
+ // Transfer the first request.
+ int new_render_view_id = 1;
+ int new_request_id = 5;
+ ResourceHostMsg_Request request =
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
+ GURL("http://example.com/blah"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_id;
+
+ ResourceHostMsg_RequestResource transfer_request_msg(
+ new_render_view_id, new_request_id, request);
+ host_.OnMessageReceived(transfer_request_msg, second_filter.get());
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Transfer the second request.
+ int new_second_request_id = 6;
+ ResourceHostMsg_Request second_request =
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
+ GURL("http://example.com/foo"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = second_request_id;
+
+ ResourceHostMsg_RequestResource second_transfer_request_msg(
+ new_render_view_id, new_second_request_id, second_request);
+ host_.OnMessageReceived(second_transfer_request_msg, second_filter.get());
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Check generated messages.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(2U, msgs.size());
+ CheckSuccessfulRequest(msgs[0], kResponseBody);
+}
+
// Test transferred navigations with text/plain, which causes
// BufferedResourceHandler to buffer the response to sniff the content
// before the transfer occurs.
@@ -2314,7 +2396,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Now that we're blocked on the redirect, update the response and unblock by
// telling the AsyncResourceHandler to follow the redirect. Use a text/plain
@@ -2342,7 +2424,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
int new_request_id = 2;
ResourceHostMsg_Request request =
- CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
GURL("http://other.com/blech"));
request.transferred_request_child_id = filter_->child_id();
request.transferred_request_request_id = request_id;
@@ -2390,7 +2472,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
first_child_id = first_filter->child_id();
ResourceHostMsg_Request first_request =
- CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
GURL("http://example.com/blah"));
ResourceHostMsg_RequestResource first_request_msg(
@@ -2426,7 +2508,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
int new_request_id = 2;
ResourceHostMsg_Request request =
- CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
GURL("http://other.com/blech"));
request.transferred_request_child_id = first_child_id;
request.transferred_request_request_id = request_id;
@@ -2470,7 +2552,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Now that we're blocked on the redirect, simulate hitting another redirect.
SetResponse("HTTP/1.1 302 Found\n"
@@ -2505,7 +2587,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
int new_request_id = 2;
ResourceHostMsg_Request request =
- CreateResourceRequest("GET", ResourceType::MAIN_FRAME,
+ CreateResourceRequest("GET", RESOURCE_TYPE_MAIN_FRAME,
GURL("http://other.com/blech"));
request.transferred_request_child_id = filter_->child_id();
request.transferred_request_request_id = request_id;
@@ -2523,7 +2605,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
EXPECT_EQ(second_filter->child_id(), info->GetChildID());
EXPECT_EQ(new_render_view_id, info->GetRouteID());
EXPECT_EQ(new_request_id, info->GetRequestID());
- EXPECT_EQ(second_filter, info->filter());
+ EXPECT_EQ(second_filter.get(), info->filter());
// Let request complete.
base::MessageLoop::current()->RunUntilIdle();
@@ -2543,7 +2625,7 @@ TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
HandleScheme("http");
MakeTestRequestWithResourceType(filter_.get(), 0, 1, GURL("foo://bar"),
- ResourceType::MAIN_FRAME);
+ RESOURCE_TYPE_MAIN_FRAME);
// Flush all pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -2605,7 +2687,7 @@ TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
GURL("http://example.com/blah"),
- ResourceType::PREFETCH);
+ RESOURCE_TYPE_PREFETCH);
// Get a bit of data before cancelling.
EXPECT_TRUE(net::URLRequestTestJob::ProcessOnePendingMessage());
@@ -2764,7 +2846,7 @@ TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
// The child releases from the request.
ResourceHostMsg_ReleaseDownloadedFile release_msg(kRequestID);
- host_.OnMessageReceived(release_msg, filter_);
+ host_.OnMessageReceived(release_msg, filter_.get());
// Still readable because there is another reference to the file. (The child
// may take additional blob references.)
@@ -2819,10 +2901,10 @@ TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
// Make a request which downloads to file.
ResourceHostMsg_Request request = CreateResourceRequest(
- "GET", ResourceType::SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
+ "GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
request.download_to_file = true;
ResourceHostMsg_RequestResource request_msg(0, 1, request);
- host_.OnMessageReceived(request_msg, filter_);
+ host_.OnMessageReceived(request_msg, filter_.get());
// Running the message loop until idle does not work because
// RedirectToFileResourceHandler posts things to base::WorkerPool. Instead,
@@ -2877,7 +2959,7 @@ TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
// RunUntilIdle doesn't work because base::WorkerPool is involved.
ShareableFileReleaseWaiter waiter(response_head.download_file_path);
ResourceHostMsg_ReleaseDownloadedFile release_msg(1);
- host_.OnMessageReceived(release_msg, filter_);
+ host_.OnMessageReceived(release_msg, filter_.get());
waiter.Wait();
// The release callback runs before the delete is scheduled, so pump the
// message loop for the delete itself. (This relies on the delete happening on
@@ -2927,4 +3009,17 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
}
}
+net::URLRequestJob* TestURLRequestJobFactory::MaybeInterceptRedirect(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const GURL& location) const {
+ return nullptr;
+}
+
+net::URLRequestJob* TestURLRequestJobFactory::MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_handler.h b/chromium/content/browser/loader/resource_handler.h
index a9d8a38aaa9..306a672616c 100644
--- a/chromium/content/browser/loader/resource_handler.h
+++ b/chromium/content/browser/loader/resource_handler.h
@@ -25,6 +25,7 @@ namespace net {
class IOBuffer;
class URLRequest;
class URLRequestStatus;
+struct RedirectInfo;
} // namespace net
namespace content {
@@ -51,7 +52,7 @@ class CONTENT_EXPORT ResourceHandler
// false. Set |*defer| to true to defer the redirect. The redirect may be
// followed later on via ResourceDispatcherHost::FollowDeferredRedirect. If
// the handler returns false, then the request is cancelled.
- virtual bool OnRequestRedirected(const GURL& url,
+ virtual bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) = 0;
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index 0becbf42a3d..eae75eb4be5 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -14,6 +14,7 @@
#include "content/browser/loader/detachable_resource_handler.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/service_worker/service_worker_request_handler.h"
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "content/browser/ssl/ssl_manager.h"
#include "content/common/ssl_status_serialization.h"
@@ -29,6 +30,7 @@
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/ssl/client_cert_store.h"
+#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_status.h"
using base::TimeDelta;
@@ -37,9 +39,9 @@ using base::TimeTicks;
namespace content {
namespace {
-void PopulateResourceResponse(net::URLRequest* request,
+void PopulateResourceResponse(ResourceRequestInfoImpl* info,
+ net::URLRequest* request,
ResourceResponse* response) {
- response->head.error_code = request->status().error();
response->head.request_time = request->request_time();
response->head.response_time = request->response_time();
response->head.headers = request->response_headers();
@@ -53,13 +55,24 @@ void PopulateResourceResponse(net::URLRequest* request,
response_info.npn_negotiated_protocol;
response->head.connection_info = response_info.connection_info;
response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
+ response->head.proxy_server = response_info.proxy_server;
response->head.socket_address = request->GetSocketAddress();
+ if (ServiceWorkerRequestHandler* handler =
+ ServiceWorkerRequestHandler::GetHandler(request)) {
+ handler->GetExtraResponseInfo(
+ &response->head.was_fetched_via_service_worker,
+ &response->head.was_fallback_required_by_service_worker,
+ &response->head.original_url_via_service_worker,
+ &response->head.response_type_via_service_worker,
+ &response->head.service_worker_fetch_start,
+ &response->head.service_worker_fetch_ready,
+ &response->head.service_worker_fetch_end);
+ }
AppCacheInterceptor::GetExtraResponseInfo(
request,
&response->head.appcache_id,
&response->head.appcache_manifest_url);
- // TODO(mmenke): Figure out if LOAD_ENABLE_LOAD_TIMING is safe to remove.
- if (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
+ if (info->is_load_timing_enabled())
request->GetLoadTimingInfo(&response->head.load_timing);
}
@@ -83,8 +96,7 @@ ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
ResourceLoader::~ResourceLoader() {
if (login_delegate_.get())
login_delegate_->OnRequestCancelled();
- if (ssl_client_auth_handler_.get())
- ssl_client_auth_handler_->OnRequestCancelled();
+ ssl_client_auth_handler_.reset();
// Run ResourceHandler destructor before we tear-down the rest of our state
// as the ResourceHandler may want to inspect the URLRequest and other state.
@@ -148,7 +160,8 @@ void ResourceLoader::ReportUploadProgress() {
bool too_much_time_passed = time_since_last > kOneSecond;
if (is_finished || enough_new_progress || too_much_time_passed) {
- if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
+ ResourceRequestInfoImpl* info = GetRequestInfo();
+ if (info->is_upload_progress_enabled()) {
handler_->OnUploadProgress(progress.position(), progress.size());
waiting_for_upload_progress_ack_ = true;
}
@@ -158,7 +171,7 @@ void ResourceLoader::ReportUploadProgress() {
}
void ResourceLoader::MarkAsTransferring() {
- CHECK(ResourceType::IsFrame(GetRequestInfo()->GetResourceType()))
+ CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
<< "Can only transfer for navigations";
is_transferring_ = true;
}
@@ -183,16 +196,12 @@ void ResourceLoader::ClearLoginDelegate() {
login_delegate_ = NULL;
}
-void ResourceLoader::ClearSSLClientAuthHandler() {
- ssl_client_auth_handler_ = NULL;
-}
-
void ResourceLoader::OnUploadProgressACK() {
waiting_for_upload_progress_ack_ = false;
}
void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
- const GURL& new_url,
+ const net::RedirectInfo& redirect_info,
bool* defer) {
DCHECK_EQ(request_.get(), unused);
@@ -203,27 +212,27 @@ void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
if (info->GetProcessType() != PROCESS_TYPE_PLUGIN &&
!ChildProcessSecurityPolicyImpl::GetInstance()->
- CanRequestURL(info->GetChildID(), new_url)) {
+ CanRequestURL(info->GetChildID(), redirect_info.new_url)) {
VLOG(1) << "Denied unauthorized request for "
- << new_url.possibly_invalid_spec();
+ << redirect_info.new_url.possibly_invalid_spec();
// Tell the renderer that this request was disallowed.
Cancel();
return;
}
- delegate_->DidReceiveRedirect(this, new_url);
+ delegate_->DidReceiveRedirect(this, redirect_info.new_url);
- if (delegate_->HandleExternalProtocol(this, new_url)) {
+ if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) {
// The request is complete so we can remove it.
CancelAndIgnore();
return;
}
scoped_refptr<ResourceResponse> response(new ResourceResponse());
- PopulateResourceResponse(request_.get(), response.get());
+ PopulateResourceResponse(info, request_.get(), response.get());
- if (!handler_->OnRequestRedirected(new_url, response.get(), defer)) {
+ if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) {
Cancel();
} else if (*defer) {
deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed.
@@ -259,12 +268,14 @@ void ResourceLoader::OnCertificateRequested(
return;
}
- DCHECK(!ssl_client_auth_handler_.get())
+ DCHECK(!ssl_client_auth_handler_)
<< "OnCertificateRequested called with ssl_client_auth_handler pending";
- ssl_client_auth_handler_ = new SSLClientAuthHandler(
+ ssl_client_auth_handler_.reset(new SSLClientAuthHandler(
GetRequestInfo()->GetContext()->CreateClientCertStore(),
request_.get(),
- cert_info);
+ cert_info,
+ base::Bind(&ResourceLoader::ContinueWithCertificate,
+ weak_ptr_factory_.GetWeakPtr())));
ssl_client_auth_handler_->SelectCertificate();
}
@@ -280,7 +291,6 @@ void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
SSLManager::OnSSLCertificateError(
weak_ptr_factory_.GetWeakPtr(),
- info->GetGlobalRequestID(),
info->GetResourceType(),
request_->url(),
render_process_id,
@@ -375,8 +385,7 @@ void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
}
}
-void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
- int error,
+void ResourceLoader::CancelSSLRequest(int error,
const net::SSLInfo* ssl_info) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -393,7 +402,7 @@ void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
}
}
-void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
+void ResourceLoader::ContinueSSLRequest() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
@@ -483,10 +492,7 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
login_delegate_->OnRequestCancelled();
login_delegate_ = NULL;
}
- if (ssl_client_auth_handler_.get()) {
- ssl_client_auth_handler_->OnRequestCancelled();
- ssl_client_auth_handler_ = NULL;
- }
+ ssl_client_auth_handler_.reset();
request_->CancelWithError(error);
@@ -510,7 +516,7 @@ void ResourceLoader::StoreSignedCertificateTimestamps(
for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
sct_list.begin(); iter != sct_list.end(); ++iter) {
- const int sct_id(sct_store->Store(iter->sct, process_id));
+ const int sct_id(sct_store->Store(iter->sct.get(), process_id));
sct_ids->push_back(
SignedCertificateTimestampIDAndStatus(sct_id, iter->status));
}
@@ -520,7 +526,7 @@ void ResourceLoader::CompleteResponseStarted() {
ResourceRequestInfoImpl* info = GetRequestInfo();
scoped_refptr<ResourceResponse> response(new ResourceResponse());
- PopulateResourceResponse(request_.get(), response.get());
+ PopulateResourceResponse(info, request_.get(), response.get());
if (request_->ssl_info().cert.get()) {
int cert_id = CertStore::GetInstance()->StoreCert(
@@ -606,7 +612,7 @@ void ResourceLoader::ReadMore(int* bytes_read) {
return;
}
- DCHECK(buf);
+ DCHECK(buf.get());
DCHECK(buf_size > 0);
request_->Read(buf.get(), buf_size, bytes_read);
@@ -672,7 +678,7 @@ void ResourceLoader::CallDidFinishLoading() {
void ResourceLoader::RecordHistograms() {
ResourceRequestInfoImpl* info = GetRequestInfo();
- if (info->GetResourceType() == ResourceType::PREFETCH) {
+ if (info->GetResourceType() == RESOURCE_TYPE_PREFETCH) {
PrefetchStatus status = STATUS_UNDEFINED;
TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
@@ -702,4 +708,9 @@ void ResourceLoader::RecordHistograms() {
}
}
+void ResourceLoader::ContinueWithCertificate(net::X509Certificate* cert) {
+ ssl_client_auth_handler_.reset();
+ request_->ContinueWithCertificate(cert);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index d06f58ca617..d740ec03b06 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -15,6 +15,10 @@
#include "content/public/common/signed_certificate_timestamp_id_and_status.h"
#include "net/url_request/url_request.h"
+namespace net {
+class X509Certificate;
+}
+
namespace content {
class ResourceDispatcherHostLoginDelegate;
class ResourceLoaderDelegate;
@@ -31,7 +35,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
ResourceLoader(scoped_ptr<net::URLRequest> request,
scoped_ptr<ResourceHandler> handler,
ResourceLoaderDelegate* delegate);
- virtual ~ResourceLoader();
+ ~ResourceLoader() override;
void StartRequest();
void CancelRequest(bool from_renderer);
@@ -46,7 +50,6 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
ResourceRequestInfoImpl* GetRequestInfo();
void ClearLoginDelegate();
- void ClearSSLClientAuthHandler();
// IPC message handlers:
void OnUploadProgressACK();
@@ -56,33 +59,29 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
FRIEND_TEST_ALL_PREFIXES(ResourceLoaderTest, ClientCertStoreNull);
// net::URLRequest::Delegate implementation:
- virtual void OnReceivedRedirect(net::URLRequest* request,
- const GURL& new_url,
- bool* defer) OVERRIDE;
- virtual void OnAuthRequired(net::URLRequest* request,
- net::AuthChallengeInfo* info) OVERRIDE;
- virtual void OnCertificateRequested(net::URLRequest* request,
- net::SSLCertRequestInfo* info) OVERRIDE;
- virtual void OnSSLCertificateError(net::URLRequest* request,
- const net::SSLInfo& info,
- bool fatal) OVERRIDE;
- virtual void OnBeforeNetworkStart(net::URLRequest* request,
- bool* defer) OVERRIDE;
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
- virtual void OnReadCompleted(net::URLRequest* request,
- int bytes_read) OVERRIDE;
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer) override;
+ void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* info) override;
+ void OnCertificateRequested(net::URLRequest* request,
+ net::SSLCertRequestInfo* info) override;
+ void OnSSLCertificateError(net::URLRequest* request,
+ const net::SSLInfo& info,
+ bool fatal) override;
+ void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override;
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
// SSLErrorHandler::Delegate implementation:
- virtual void CancelSSLRequest(const GlobalRequestID& id,
- int error,
- const net::SSLInfo* ssl_info) OVERRIDE;
- virtual void ContinueSSLRequest(const GlobalRequestID& id) OVERRIDE;
+ void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override;
+ void ContinueSSLRequest() override;
// ResourceController implementation:
- virtual void Resume() OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual void CancelAndIgnore() OVERRIDE;
- virtual void CancelWithError(int error_code) OVERRIDE;
+ void Resume() override;
+ void Cancel() override;
+ void CancelAndIgnore() override;
+ void CancelWithError(int error_code) override;
void StartRequestInternal();
void CancelRequestInternal(int error, bool from_renderer);
@@ -103,6 +102,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void ResponseCompleted();
void CallDidFinishLoading();
void RecordHistograms();
+ void ContinueWithCertificate(net::X509Certificate* cert);
bool is_deferred() const { return deferred_stage_ != DEFERRED_NONE; }
@@ -133,7 +133,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
ResourceLoaderDelegate* delegate_;
scoped_refptr<ResourceDispatcherHostLoginDelegate> login_delegate_;
- scoped_refptr<SSLClientAuthHandler> ssl_client_auth_handler_;
+ scoped_ptr<SSLClientAuthHandler> ssl_client_auth_handler_;
uint64 last_upload_position_;
bool waiting_for_upload_progress_ack_;
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index d2fdd99b3ba..635f566f7dd 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -4,8 +4,8 @@
#include "content/browser/loader/resource_loader.h"
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
@@ -27,10 +27,10 @@
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "storage/common/blob/shareable_file_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace content {
namespace {
@@ -44,7 +44,7 @@ class ClientCertStoreStub : public net::ClientCertStore {
: response_(certs),
request_count_(0) {}
- virtual ~ClientCertStoreStub() {}
+ ~ClientCertStoreStub() override {}
// Returns |cert_authorities| field of the certificate request passed in the
// most recent call to GetClientCerts().
@@ -62,9 +62,9 @@ class ClientCertStoreStub : public net::ClientCertStore {
}
// net::ClientCertStore:
- virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
- net::CertificateList* selected_certs,
- const base::Closure& callback) OVERRIDE {
+ void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
+ net::CertificateList* selected_certs,
+ const base::Closure& callback) override {
++request_count_;
requested_authorities_ = cert_request_info.cert_authorities;
*selected_certs = response_;
@@ -127,39 +127,38 @@ class ResourceHandlerStub : public ResourceHandler {
}
// ResourceHandler implementation:
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
+ bool OnUploadProgress(uint64 position, uint64 size) override {
NOTREACHED();
return true;
}
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) OVERRIDE {
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override {
NOTREACHED();
return true;
}
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE {
- EXPECT_FALSE(response_);
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
+ EXPECT_FALSE(response_.get());
response_ = response;
return true;
}
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE {
+ bool OnWillStart(const GURL& url, bool* defer) override {
EXPECT_TRUE(start_url_.is_empty());
start_url_ = url;
*defer = defer_request_on_will_start_;
return true;
}
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE {
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
return true;
}
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE {
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override {
EXPECT_TRUE(expect_reads_);
EXPECT_FALSE(received_on_will_read_);
EXPECT_FALSE(received_eof_);
@@ -171,7 +170,7 @@ class ResourceHandlerStub : public ResourceHandler {
return true;
}
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE {
+ bool OnReadCompleted(int bytes_read, bool* defer) override {
EXPECT_TRUE(received_on_will_read_);
EXPECT_TRUE(expect_reads_);
EXPECT_FALSE(received_response_completed_);
@@ -190,9 +189,9 @@ class ResourceHandlerStub : public ResourceHandler {
return !cancel_on_read_completed_;
}
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE {
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override {
EXPECT_FALSE(received_response_completed_);
if (status.is_success() && expect_reads_)
EXPECT_TRUE(received_eof_);
@@ -201,7 +200,7 @@ class ResourceHandlerStub : public ResourceHandler {
status_ = status;
}
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE {
+ void OnDataDownloaded(int bytes_downloaded) override {
EXPECT_FALSE(expect_reads_);
total_bytes_downloaded_ += bytes_downloaded;
}
@@ -229,12 +228,11 @@ class SelectCertificateBrowserClient : public TestContentBrowserClient {
public:
SelectCertificateBrowserClient() : call_count_(0) {}
- virtual void SelectClientCertificate(
+ void SelectClientCertificate(
int render_process_id,
int render_view_id,
- const net::HttpNetworkSession* network_session,
net::SSLCertRequestInfo* cert_request_info,
- const base::Callback<void(net::X509Certificate*)>& callback) OVERRIDE {
+ const base::Callback<void(net::X509Certificate*)>& callback) override {
++call_count_;
passed_certs_ = cert_request_info->client_certs;
}
@@ -257,7 +255,7 @@ class ResourceContextStub : public MockResourceContext {
explicit ResourceContextStub(net::URLRequestContext* test_request_context)
: MockResourceContext(test_request_context) {}
- virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore() OVERRIDE {
+ scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
return dummy_cert_store_.Pass();
}
@@ -305,21 +303,22 @@ class ResourceLoaderTest : public testing::Test,
virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
scoped_ptr<ResourceHandlerStub> leaf_handler,
net::URLRequest* request) {
- return leaf_handler.PassAs<ResourceHandler>();
+ return leaf_handler.Pass();
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
const int kRenderProcessId = 1;
const int kRenderViewId = 2;
scoped_ptr<net::URLRequest> request(
- new net::URLRequest(test_url(),
- net::DEFAULT_PRIORITY,
- NULL,
- resource_context_.GetRequestContext()));
+ resource_context_.GetRequestContext()->CreateRequest(
+ test_url(),
+ net::DEFAULT_PRIORITY,
+ NULL /* delegate */,
+ NULL /* cookie_store */));
raw_ptr_to_request_ = request.get();
ResourceRequestInfo::AllocateForTesting(request.get(),
- ResourceType::MAIN_FRAME,
+ RESOURCE_TYPE_MAIN_FRAME,
&resource_context_,
kRenderProcessId,
kRenderViewId,
@@ -335,20 +334,20 @@ class ResourceLoaderTest : public testing::Test,
}
// ResourceLoaderDelegate:
- virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
+ ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
ResourceLoader* loader,
- net::AuthChallengeInfo* auth_info) OVERRIDE {
+ net::AuthChallengeInfo* auth_info) override {
return NULL;
}
- virtual bool HandleExternalProtocol(ResourceLoader* loader,
- const GURL& url) OVERRIDE {
+ bool HandleExternalProtocol(ResourceLoader* loader,
+ const GURL& url) override {
return false;
}
- virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {}
- virtual void DidReceiveRedirect(ResourceLoader* loader,
- const GURL& new_url) OVERRIDE {}
- virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {}
- virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {}
+ void DidStartRequest(ResourceLoader* loader) override {}
+ void DidReceiveRedirect(ResourceLoader* loader,
+ const GURL& new_url) override {}
+ void DidReceiveResponse(ResourceLoader* loader) override {}
+ void DidFinishLoading(ResourceLoader* loader) override {}
content::TestBrowserThreadBundle thread_bundle_;
@@ -377,8 +376,7 @@ TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
// Ownership of the |test_store| is about to be turned over to ResourceLoader.
// We need to keep raw pointer copies to access these objects later.
ClientCertStoreStub* raw_ptr_to_store = test_store.get();
- resource_context_.SetClientCertStore(
- test_store.PassAs<net::ClientCertStore>());
+ resource_context_.SetClientCertStore(test_store.Pass());
// Prepare a dummy certificate request.
scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
@@ -498,9 +496,9 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
loader_.reset();
}
- virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
+ scoped_ptr<ResourceHandler> WrapResourceHandler(
scoped_ptr<ResourceHandlerStub> leaf_handler,
- net::URLRequest* request) OVERRIDE {
+ net::URLRequest* request) override {
leaf_handler->set_expect_reads(false);
// Make a temporary file.
@@ -523,14 +521,13 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
// Inject them into the handler.
scoped_ptr<RedirectToFileResourceHandler> handler(
- new RedirectToFileResourceHandler(
- leaf_handler.PassAs<ResourceHandler>(), request));
+ new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
redirect_to_file_resource_handler_ = handler.get();
handler->SetCreateTemporaryFileStreamFunctionForTesting(
base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
base::Unretained(this),
- base::Passed(file_stream.PassAs<net::FileStream>())));
- return handler.PassAs<ResourceHandler>();
+ base::Passed(&file_stream)));
+ return handler.Pass();
}
private:
diff --git a/chromium/content/browser/loader/resource_message_filter.cc b/chromium/content/browser/loader/resource_message_filter.cc
index 137029cf644..9ffa29f5716 100644
--- a/chromium/content/browser/loader/resource_message_filter.cc
+++ b/chromium/content/browser/loader/resource_message_filter.cc
@@ -10,7 +10,7 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/resource_context.h"
-#include "webkit/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_context.h"
namespace content {
@@ -19,7 +19,7 @@ ResourceMessageFilter::ResourceMessageFilter(
int process_type,
ChromeAppCacheService* appcache_service,
ChromeBlobStorageContext* blob_storage_context,
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
ServiceWorkerContextWrapper* service_worker_context,
const GetContextsCallback& get_contexts_callback)
: BrowserMessageFilter(ResourceMsgStart),
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 90af00e7e73..3b52a7773c0 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -10,13 +10,13 @@
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
-#include "webkit/common/resource_type.h"
+#include "content/public/common/resource_type.h"
struct ResourceHostMsg_Request;
-namespace fileapi {
+namespace storage {
class FileSystemContext;
-} // namespace fileapi
+} // namespace storage
namespace net {
class URLRequestContext;
@@ -42,26 +42,24 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
// |appcache_service|, |blob_storage_context|, |file_system_context| may be
// NULL in unittests or for requests from the (NPAPI) plugin process.
- ResourceMessageFilter(
- int child_id,
- int process_type,
- ChromeAppCacheService* appcache_service,
- ChromeBlobStorageContext* blob_storage_context,
- fileapi::FileSystemContext* file_system_context,
- ServiceWorkerContextWrapper* service_worker_context,
- const GetContextsCallback& get_contexts_callback);
+ ResourceMessageFilter(int child_id,
+ int process_type,
+ ChromeAppCacheService* appcache_service,
+ ChromeBlobStorageContext* blob_storage_context,
+ storage::FileSystemContext* file_system_context,
+ ServiceWorkerContextWrapper* service_worker_context,
+ const GetContextsCallback& get_contexts_callback);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
void GetContexts(const ResourceHostMsg_Request& request,
ResourceContext** resource_context,
net::URLRequestContext** request_context);
// Returns the net::URLRequestContext for the given request.
- net::URLRequestContext* GetURLRequestContext(
- ResourceType::Type request_type);
+ net::URLRequestContext* GetURLRequestContext(ResourceType request_type);
ChromeAppCacheService* appcache_service() const {
return appcache_service_.get();
@@ -71,7 +69,7 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
return blob_storage_context_.get();
}
- fileapi::FileSystemContext* file_system_context() const {
+ storage::FileSystemContext* file_system_context() const {
return file_system_context_.get();
}
@@ -86,7 +84,7 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
protected:
// Protected destructor so that we can be overriden in tests.
- virtual ~ResourceMessageFilter();
+ ~ResourceMessageFilter() override;
private:
// The ID of the child process.
@@ -96,7 +94,7 @@ class CONTENT_EXPORT ResourceMessageFilter : public BrowserMessageFilter {
scoped_refptr<ChromeAppCacheService> appcache_service_;
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
GetContextsCallback get_contexts_callback_;
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 03d925ee786..8cae9a5c93b 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -6,9 +6,9 @@
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/worker_host/worker_service_impl.h"
#include "content/common/net/url_request_user_data.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/common/process_type.h"
#include "net/url_request/url_request.h"
namespace content {
@@ -23,14 +23,13 @@ const ResourceRequestInfo* ResourceRequestInfo::ForRequest(
}
// static
-void ResourceRequestInfo::AllocateForTesting(
- net::URLRequest* request,
- ResourceType::Type resource_type,
- ResourceContext* context,
- int render_process_id,
- int render_view_id,
- int render_frame_id,
- bool is_async) {
+void ResourceRequestInfo::AllocateForTesting(net::URLRequest* request,
+ ResourceType resource_type,
+ ResourceContext* context,
+ int render_process_id,
+ int render_view_id,
+ int render_frame_id,
+ bool is_async) {
ResourceRequestInfoImpl* info =
new ResourceRequestInfoImpl(
PROCESS_TYPE_RENDERER, // process_type
@@ -39,16 +38,18 @@ void ResourceRequestInfo::AllocateForTesting(
0, // origin_pid
0, // request_id
render_frame_id, // render_frame_id
- resource_type == ResourceType::MAIN_FRAME, // is_main_frame
+ resource_type == RESOURCE_TYPE_MAIN_FRAME, // is_main_frame
false, // parent_is_main_frame
0, // parent_render_frame_id
resource_type, // resource_type
- PAGE_TRANSITION_LINK, // transition_type
+ ui::PAGE_TRANSITION_LINK, // transition_type
false, // should_replace_current_entry
false, // is_download
false, // is_stream
true, // allow_download
false, // has_user_gesture
+ false, // enable load timing
+ false, // enable upload progress
blink::WebReferrerPolicyDefault, // referrer_policy
blink::WebPageVisibilityStateVisible, // visibility_state
context, // context
@@ -96,13 +97,15 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
bool is_main_frame,
bool parent_is_main_frame,
int parent_render_frame_id,
- ResourceType::Type resource_type,
- PageTransition transition_type,
+ ResourceType resource_type,
+ ui::PageTransition transition_type,
bool should_replace_current_entry,
bool is_download,
bool is_stream,
bool allow_download,
bool has_user_gesture,
+ bool enable_load_timing,
+ bool enable_upload_progress,
blink::WebReferrerPolicy referrer_policy,
blink::WebPageVisibilityState visibility_state,
ResourceContext* context,
@@ -124,7 +127,10 @@ ResourceRequestInfoImpl::ResourceRequestInfoImpl(
is_stream_(is_stream),
allow_download_(allow_download),
has_user_gesture_(has_user_gesture),
+ enable_load_timing_(enable_load_timing),
+ enable_upload_progress_(enable_upload_progress),
was_ignored_by_handler_(false),
+ counted_as_in_flight_request_(false),
resource_type_(resource_type),
transition_type_(transition_type),
memory_cost_(0),
@@ -174,7 +180,7 @@ int ResourceRequestInfoImpl::GetParentRenderFrameID() const {
return parent_render_frame_id_;
}
-ResourceType::Type ResourceRequestInfoImpl::GetResourceType() const {
+ResourceType ResourceRequestInfoImpl::GetResourceType() const {
return resource_type_;
}
@@ -191,7 +197,7 @@ ResourceRequestInfoImpl::GetVisibilityState() const {
return visibility_state_;
}
-PageTransition ResourceRequestInfoImpl::GetPageTransition() const {
+ui::PageTransition ResourceRequestInfoImpl::GetPageTransition() const {
return transition_type_;
}
@@ -206,18 +212,7 @@ bool ResourceRequestInfoImpl::WasIgnoredByHandler() const {
bool ResourceRequestInfoImpl::GetAssociatedRenderFrame(
int* render_process_id,
int* render_frame_id) const {
- // If the request is from the worker process, find a content that owns the
- // worker.
- if (process_type_ == PROCESS_TYPE_WORKER) {
- // Need to display some related UI for this network request - pick an
- // arbitrary parent to do so.
- if (!WorkerServiceImpl::GetInstance()->GetRendererForWorker(
- child_id_, render_process_id, render_frame_id)) {
- *render_process_id = -1;
- *render_frame_id = -1;
- return false;
- }
- } else if (process_type_ == PROCESS_TYPE_PLUGIN) {
+ if (process_type_ == PROCESS_TYPE_PLUGIN) {
*render_process_id = origin_pid_;
*render_frame_id = render_frame_id_;
} else {
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 82c81c0985e..6b75fcdae87 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -15,8 +15,8 @@
#include "base/supports_user_data.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/resource_type.h"
#include "net/base/load_states.h"
-#include "webkit/common/resource_type.h"
namespace content {
class CrossSiteResourceHandler;
@@ -49,42 +49,43 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_main_frame,
bool parent_is_main_frame,
int parent_render_frame_id,
- ResourceType::Type resource_type,
- PageTransition transition_type,
+ ResourceType resource_type,
+ ui::PageTransition transition_type,
bool should_replace_current_entry,
bool is_download,
bool is_stream,
bool allow_download,
bool has_user_gesture,
+ bool enable_load_timing,
+ bool enable_upload_progress,
blink::WebReferrerPolicy referrer_policy,
blink::WebPageVisibilityState visibility_state,
ResourceContext* context,
base::WeakPtr<ResourceMessageFilter> filter,
bool is_async);
- virtual ~ResourceRequestInfoImpl();
+ ~ResourceRequestInfoImpl() override;
// ResourceRequestInfo implementation:
- virtual ResourceContext* GetContext() const OVERRIDE;
- virtual int GetChildID() const OVERRIDE;
- virtual int GetRouteID() const OVERRIDE;
- virtual int GetOriginPID() const OVERRIDE;
- virtual int GetRequestID() const OVERRIDE;
- virtual int GetRenderFrameID() const OVERRIDE;
- virtual bool IsMainFrame() const OVERRIDE;
- virtual bool ParentIsMainFrame() const OVERRIDE;
- virtual int GetParentRenderFrameID() const OVERRIDE;
- virtual ResourceType::Type GetResourceType() const OVERRIDE;
- virtual int GetProcessType() const OVERRIDE;
- virtual blink::WebReferrerPolicy GetReferrerPolicy() const OVERRIDE;
- virtual blink::WebPageVisibilityState GetVisibilityState() const OVERRIDE;
- virtual PageTransition GetPageTransition() const OVERRIDE;
- virtual bool HasUserGesture() const OVERRIDE;
- virtual bool WasIgnoredByHandler() const OVERRIDE;
- virtual bool GetAssociatedRenderFrame(int* render_process_id,
- int* render_frame_id) const OVERRIDE;
- virtual bool IsAsync() const OVERRIDE;
- virtual bool IsDownload() const OVERRIDE;
-
+ ResourceContext* GetContext() const override;
+ int GetChildID() const override;
+ int GetRouteID() const override;
+ int GetOriginPID() const override;
+ int GetRequestID() const override;
+ int GetRenderFrameID() const override;
+ bool IsMainFrame() const override;
+ bool ParentIsMainFrame() const override;
+ int GetParentRenderFrameID() const override;
+ ResourceType GetResourceType() const override;
+ int GetProcessType() const override;
+ blink::WebReferrerPolicy GetReferrerPolicy() const override;
+ blink::WebPageVisibilityState GetVisibilityState() const override;
+ ui::PageTransition GetPageTransition() const override;
+ bool HasUserGesture() const override;
+ bool WasIgnoredByHandler() const override;
+ bool GetAssociatedRenderFrame(int* render_process_id,
+ int* render_frame_id) const override;
+ bool IsAsync() const override;
+ bool IsDownload() const override;
CONTENT_EXPORT void AssociateWithRequest(net::URLRequest* request);
@@ -147,11 +148,25 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
was_ignored_by_handler_ = value;
}
+ // Whether this request has been counted towards the number of in flight
+ // requests, which is only true for requests that require a file descriptor
+ // for their shared memory buffer.
+ bool counted_as_in_flight_request() const {
+ return counted_as_in_flight_request_;
+ }
+ void set_counted_as_in_flight_request(bool was_counted) {
+ counted_as_in_flight_request_ = was_counted;
+ }
+
// The approximate in-memory size (bytes) that we credited this request
// as consuming in |outstanding_requests_memory_cost_map_|.
int memory_cost() const { return memory_cost_; }
void set_memory_cost(int cost) { memory_cost_ = cost; }
+ bool is_load_timing_enabled() const { return enable_load_timing_; }
+
+ bool is_upload_progress_enabled() const { return enable_upload_progress_; }
+
private:
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
DeletedFilterDetached);
@@ -175,9 +190,12 @@ class ResourceRequestInfoImpl : public ResourceRequestInfo,
bool is_stream_;
bool allow_download_;
bool has_user_gesture_;
+ bool enable_load_timing_;
+ bool enable_upload_progress_;
bool was_ignored_by_handler_;
- ResourceType::Type resource_type_;
- PageTransition transition_type_;
+ bool counted_as_in_flight_request_;
+ ResourceType resource_type_;
+ ui::PageTransition transition_type_;
int memory_cost_;
blink::WebReferrerPolicy referrer_policy_;
blink::WebPageVisibilityState visibility_state_;
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index a826580cdcd..82d96ab5162 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -6,7 +6,10 @@
#include "content/browser/loader/resource_scheduler.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
#include "base/stl_util.h"
+#include "base/time/time.h"
#include "content/common/resource_messages.h"
#include "content/browser/loader/resource_message_delegate.h"
#include "content/public/browser/resource_controller.h"
@@ -22,9 +25,28 @@
namespace content {
+namespace {
+
+void PostHistogram(const char* base_name,
+ const char* suffix,
+ base::TimeDelta time) {
+ std::string histogram_name =
+ base::StringPrintf("ResourceScheduler.%s.%s", base_name, suffix);
+ base::HistogramBase* histogram_counter = base::Histogram::FactoryTimeGet(
+ histogram_name,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(5),
+ 50,
+ base::Histogram::kUmaTargetedHistogramFlag);
+ histogram_counter->AddTime(time);
+}
+
+} // namespace
+
+static const size_t kCoalescedTimerPeriod = 5000;
static const size_t kMaxNumDelayableRequestsPerClient = 10;
static const size_t kMaxNumDelayableRequestsPerHost = 6;
-
+static const size_t kMaxNumThrottledRequestsPerClient = 1;
struct ResourceScheduler::RequestPriorityParams {
RequestPriorityParams()
@@ -121,28 +143,51 @@ class ResourceScheduler::ScheduledResourceRequest
const RequestPriorityParams& priority)
: ResourceMessageDelegate(request),
client_id_(client_id),
+ client_state_on_creation_(scheduler->GetClientState(client_id_)),
request_(request),
ready_(false),
deferred_(false),
+ classification_(NORMAL_REQUEST),
scheduler_(scheduler),
priority_(priority),
- fifo_ordering_(0),
- accounted_as_delayable_request_(false) {
+ fifo_ordering_(0) {
TRACE_EVENT_ASYNC_BEGIN1("net", "URLRequest", request_,
"url", request->url().spec());
}
- virtual ~ScheduledResourceRequest() {
- scheduler_->RemoveRequest(this);
- }
+ ~ScheduledResourceRequest() override { scheduler_->RemoveRequest(this); }
void Start() {
TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request_, "Queued");
ready_ = true;
- if (deferred_ && request_->status().is_success()) {
+ if (!request_->status().is_success())
+ return;
+ base::TimeTicks time = base::TimeTicks::Now();
+ ClientState current_state = scheduler_->GetClientState(client_id_);
+ // Note: the client state isn't perfectly accurate since it won't capture
+ // tabs which have switched between active and background multiple times.
+ // Ex: A tab with the following transitions Active -> Background -> Active
+ // will be recorded as Active.
+ const char* client_state = "Other";
+ if (current_state == client_state_on_creation_ && current_state == ACTIVE) {
+ client_state = "Active";
+ } else if (current_state == client_state_on_creation_ &&
+ current_state == BACKGROUND) {
+ client_state = "Background";
+ }
+
+ base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0);
+ if (deferred_) {
deferred_ = false;
controller()->Resume();
+ time_was_deferred = time - time_deferred_;
}
+ PostHistogram("RequestTimeDeferred", client_state, time_was_deferred);
+ PostHistogram(
+ "RequestTimeThrottled", client_state, time - request_->creation_time());
+ // TODO(aiolos): Remove one of the above histograms after gaining an
+ // understanding of the difference between them and which one is more
+ // interesting.
}
void set_request_priority_params(const RequestPriorityParams& priority) {
@@ -158,16 +203,16 @@ class ResourceScheduler::ScheduledResourceRequest
void set_fifo_ordering(uint32 fifo_ordering) {
fifo_ordering_ = fifo_ordering;
}
- bool accounted_as_delayable_request() const {
- return accounted_as_delayable_request_;
+ RequestClassification classification() const {
+ return classification_;
}
- void set_accounted_as_delayable_request(bool accounted) {
- accounted_as_delayable_request_ = accounted;
+ void set_classification(RequestClassification classification) {
+ classification_ = classification;
}
private:
// ResourceMessageDelegate interface:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ScheduledResourceRequest, message)
IPC_MESSAGE_HANDLER(ResourceHostMsg_DidChangePriority, DidChangePriority)
@@ -177,28 +222,28 @@ class ResourceScheduler::ScheduledResourceRequest
}
// ResourceThrottle interface:
- virtual void WillStartRequest(bool* defer) OVERRIDE {
+ void WillStartRequest(bool* defer) override {
deferred_ = *defer = !ready_;
+ time_deferred_ = base::TimeTicks::Now();
}
- virtual const char* GetNameForLogging() const OVERRIDE {
- return "ResourceScheduler";
- }
+ const char* GetNameForLogging() const override { return "ResourceScheduler"; }
void DidChangePriority(int request_id, net::RequestPriority new_priority,
int intra_priority_value) {
scheduler_->ReprioritizeRequest(this, new_priority, intra_priority_value);
}
- ClientId client_id_;
+ const ClientId client_id_;
+ const ResourceScheduler::ClientState client_state_on_creation_;
net::URLRequest* request_;
bool ready_;
bool deferred_;
+ RequestClassification classification_;
ResourceScheduler* scheduler_;
RequestPriorityParams priority_;
uint32 fifo_ordering_;
- // True if the request is delayable in |in_flight_requests_|.
- bool accounted_as_delayable_request_;
+ base::TimeTicks time_deferred_;
DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest);
};
@@ -229,20 +274,38 @@ void ResourceScheduler::RequestQueue::Insert(
// Each client represents a tab.
class ResourceScheduler::Client {
public:
- Client()
- : has_body_(false),
+ explicit Client(ResourceScheduler* scheduler,
+ bool is_visible,
+ bool is_audible)
+ : is_audible_(is_audible),
+ is_visible_(is_visible),
+ is_loaded_(false),
+ is_paused_(false),
+ has_body_(false),
using_spdy_proxy_(false),
- total_delayable_count_(0) {}
- ~Client() {}
+ in_flight_delayable_count_(0),
+ total_layout_blocking_count_(0),
+ throttle_state_(ResourceScheduler::THROTTLED) {
+ scheduler_ = scheduler;
+ }
+
+ ~Client() {
+ // Update to default state and pause to ensure the scheduler has a
+ // correct count of relevant types of clients.
+ is_visible_ = false;
+ is_audible_ = false;
+ is_paused_ = true;
+ UpdateThrottleState();
+ }
void ScheduleRequest(
net::URLRequest* url_request,
ScheduledResourceRequest* request) {
- if (ShouldStartRequest(request) == START_REQUEST) {
+ if (ShouldStartRequest(request) == START_REQUEST)
StartRequest(request);
- } else {
+ else
pending_requests_.Insert(request);
- }
+ SetRequestClassification(request, ClassifyRequest(request));
}
void RemoveRequest(ScheduledResourceRequest* request) {
@@ -262,14 +325,83 @@ class ResourceScheduler::Client {
for (RequestSet::iterator it = in_flight_requests_.begin();
it != in_flight_requests_.end(); ++it) {
unowned_requests.insert(*it);
- (*it)->set_accounted_as_delayable_request(false);
+ (*it)->set_classification(NORMAL_REQUEST);
}
ClearInFlightRequests();
return unowned_requests;
}
+ bool is_active() const { return is_visible_ || is_audible_; }
+
+ bool is_loaded() const { return is_loaded_; }
+
+ bool is_visible() const { return is_visible_; }
+
+ void OnAudibilityChanged(bool is_audible) {
+ if (is_audible == is_audible_) {
+ return;
+ }
+ is_audible_ = is_audible;
+ UpdateThrottleState();
+ }
+
+ void OnVisibilityChanged(bool is_visible) {
+ if (is_visible == is_visible_) {
+ return;
+ }
+ is_visible_ = is_visible;
+ UpdateThrottleState();
+ }
+
+ void OnLoadingStateChanged(bool is_loaded) {
+ if (is_loaded == is_loaded_) {
+ return;
+ }
+ is_loaded_ = is_loaded;
+ UpdateThrottleState();
+ }
+
+ void SetPaused() {
+ is_paused_ = true;
+ UpdateThrottleState();
+ }
+
+ void UpdateThrottleState() {
+ ClientThrottleState old_throttle_state = throttle_state_;
+ if (!scheduler_->should_throttle()) {
+ SetThrottleState(UNTHROTTLED);
+ } else if (is_active() && !is_loaded_) {
+ SetThrottleState(ACTIVE_AND_LOADING);
+ } else if (is_active()) {
+ SetThrottleState(UNTHROTTLED);
+ } else if (is_paused_) {
+ SetThrottleState(PAUSED);
+ } else if (!scheduler_->active_clients_loaded()) {
+ SetThrottleState(THROTTLED);
+ } else if (is_loaded_ && scheduler_->should_coalesce()) {
+ SetThrottleState(COALESCED);
+ } else if (!is_active()) {
+ SetThrottleState(UNTHROTTLED);
+ }
+
+ if (throttle_state_ == old_throttle_state) {
+ return;
+ }
+ if (throttle_state_ == ACTIVE_AND_LOADING) {
+ scheduler_->IncrementActiveClientsLoading();
+ } else if (old_throttle_state == ACTIVE_AND_LOADING) {
+ scheduler_->DecrementActiveClientsLoading();
+ }
+ if (throttle_state_ == COALESCED) {
+ scheduler_->IncrementCoalescedClients();
+ } else if (old_throttle_state == COALESCED) {
+ scheduler_->DecrementCoalescedClients();
+ }
+ }
+
void OnNavigate() {
has_body_ = false;
+ is_loaded_ = false;
}
void OnWillInsertBody() {
@@ -293,7 +425,7 @@ class ResourceScheduler::Client {
DCHECK(ContainsKey(in_flight_requests_, request));
// The priority and SPDY support may have changed, so update the
// delayable count.
- SetRequestDelayable(request, IsDelayableRequest(request));
+ SetRequestClassification(request, ClassifyRequest(request));
// Request has already started.
return;
}
@@ -307,53 +439,140 @@ class ResourceScheduler::Client {
}
}
+ // Called on Client creation, when a Client changes user observability,
+ // possibly when all observable Clients have finished loading, and
+ // possibly when this Client has finished loading.
+ // State changes:
+ // Client became observable.
+ // any state -> UNTHROTTLED
+ // Client is unobservable, but all observable clients finished loading.
+ // THROTTLED -> UNTHROTTLED
+ // Non-observable client finished loading.
+ // THROTTLED || UNTHROTTLED -> COALESCED
+ // Non-observable client, an observable client starts loading.
+ // COALESCED -> THROTTLED
+ // A COALESCED client will transition into UNTHROTTLED when the network is
+ // woken up by a heartbeat and then transition back into COALESCED.
+ void SetThrottleState(ResourceScheduler::ClientThrottleState throttle_state) {
+ if (throttle_state == throttle_state_) {
+ return;
+ }
+ throttle_state_ = throttle_state;
+ if (throttle_state_ != PAUSED) {
+ is_paused_ = false;
+ }
+ LoadAnyStartablePendingRequests();
+ // TODO(aiolos): Stop any started but not inflght requests when
+ // switching to stricter throttle state?
+ }
+
+ ResourceScheduler::ClientThrottleState throttle_state() const {
+ return throttle_state_;
+ }
+
+ void LoadCoalescedRequests() {
+ if (throttle_state_ != COALESCED) {
+ return;
+ }
+ if (scheduler_->active_clients_loaded()) {
+ SetThrottleState(UNTHROTTLED);
+ } else {
+ SetThrottleState(THROTTLED);
+ }
+ LoadAnyStartablePendingRequests();
+ SetThrottleState(COALESCED);
+ }
+
private:
enum ShouldStartReqResult {
- DO_NOT_START_REQUEST_AND_STOP_SEARCHING = -2,
- DO_NOT_START_REQUEST_AND_KEEP_SEARCHING = -1,
- START_REQUEST = 1,
+ DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
+ DO_NOT_START_REQUEST_AND_KEEP_SEARCHING,
+ START_REQUEST,
};
void InsertInFlightRequest(ScheduledResourceRequest* request) {
in_flight_requests_.insert(request);
- if (IsDelayableRequest(request))
- SetRequestDelayable(request, true);
+ SetRequestClassification(request, ClassifyRequest(request));
}
void EraseInFlightRequest(ScheduledResourceRequest* request) {
size_t erased = in_flight_requests_.erase(request);
DCHECK_EQ(1u, erased);
- SetRequestDelayable(request, false);
- DCHECK_LE(total_delayable_count_, in_flight_requests_.size());
+ // Clear any special state that we were tracking for this request.
+ SetRequestClassification(request, NORMAL_REQUEST);
}
void ClearInFlightRequests() {
in_flight_requests_.clear();
- total_delayable_count_ = 0;
+ in_flight_delayable_count_ = 0;
+ total_layout_blocking_count_ = 0;
+ }
+
+ size_t CountRequestsWithClassification(
+ const RequestClassification classification, const bool include_pending) {
+ size_t classification_request_count = 0;
+ for (RequestSet::const_iterator it = in_flight_requests_.begin();
+ it != in_flight_requests_.end(); ++it) {
+ if ((*it)->classification() == classification)
+ classification_request_count++;
+ }
+ if (include_pending) {
+ for (RequestQueue::NetQueue::const_iterator
+ it = pending_requests_.GetNextHighestIterator();
+ it != pending_requests_.End(); ++it) {
+ if ((*it)->classification() == classification)
+ classification_request_count++;
+ }
+ }
+ return classification_request_count;
}
- bool IsDelayableRequest(ScheduledResourceRequest* request) {
+ void SetRequestClassification(ScheduledResourceRequest* request,
+ RequestClassification classification) {
+ RequestClassification old_classification = request->classification();
+ if (old_classification == classification)
+ return;
+
+ if (old_classification == IN_FLIGHT_DELAYABLE_REQUEST)
+ in_flight_delayable_count_--;
+ if (old_classification == LAYOUT_BLOCKING_REQUEST)
+ total_layout_blocking_count_--;
+
+ if (classification == IN_FLIGHT_DELAYABLE_REQUEST)
+ in_flight_delayable_count_++;
+ if (classification == LAYOUT_BLOCKING_REQUEST)
+ total_layout_blocking_count_++;
+
+ request->set_classification(classification);
+ DCHECK_EQ(
+ CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
+ in_flight_delayable_count_);
+ DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
+ total_layout_blocking_count_);
+ }
+
+ RequestClassification ClassifyRequest(ScheduledResourceRequest* request) {
+ // If a request is already marked as layout-blocking make sure to keep the
+ // classification across redirects unless the priority was lowered.
+ if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
+ request->url_request()->priority() > net::LOW) {
+ return LAYOUT_BLOCKING_REQUEST;
+ }
+
+ if (!has_body_ && request->url_request()->priority() > net::LOW)
+ return LAYOUT_BLOCKING_REQUEST;
+
if (request->url_request()->priority() < net::LOW) {
net::HostPortPair host_port_pair =
net::HostPortPair::FromURL(request->url_request()->url());
net::HttpServerProperties& http_server_properties =
*request->url_request()->context()->http_server_properties();
- if (!http_server_properties.SupportsSpdy(host_port_pair)) {
- return true;
+ if (!http_server_properties.SupportsSpdy(host_port_pair) &&
+ ContainsKey(in_flight_requests_, request)) {
+ return IN_FLIGHT_DELAYABLE_REQUEST;
}
}
- return false;
- }
-
- void SetRequestDelayable(ScheduledResourceRequest* request,
- bool delayable) {
- if (request->accounted_as_delayable_request() == delayable)
- return;
- if (delayable)
- total_delayable_count_++;
- else
- total_delayable_count_--;
- request->set_accounted_as_delayable_request(delayable);
+ return NORMAL_REQUEST;
}
bool ShouldKeepSearching(
@@ -379,46 +598,77 @@ class ResourceScheduler::Client {
// ShouldStartRequest is the main scheduling algorithm.
//
- // Requests are categorized into two categories:
+ // Requests are evaluated on five attributes:
//
- // 1. Immediately issued requests, which are:
- //
- // * Higher priority requests (>= net::LOW).
+ // 1. Non-delayable requests:
// * Synchronous requests.
- // * Requests to SPDY-capable origin servers.
// * Non-HTTP[S] requests.
//
- // 2. The remainder are delayable requests, which follow these rules:
+ // 2. Requests to SPDY-capable origin servers.
//
- // * If no high priority requests are in flight, start loading low priority
- // requests.
- // * Once the renderer has a <body>, start loading delayable requests.
+ // 3. High-priority requests:
+ // * Higher priority requests (>= net::LOW).
+ //
+ // 4. Layout-blocking requests:
+ // * High-priority requests (> net::LOW) initiated before the renderer has
+ // a <body>.
+ //
+ // 5. Low priority requests
+ //
+ // The following rules are followed:
+ //
+ // ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules:
+ // * Non-delayable, High-priority and SPDY capable requests are issued
+ // immediately.
+ // * Low priority requests are delayable.
+ // * Allow one delayable request to load at a time while layout-blocking
+ // requests are loading or the body tag has not yet been parsed.
+ // * If no high priority or layout-blocking requests are in flight, start
+ // loading delayable requests.
// * Never exceed 10 delayable requests in flight per client.
// * Never exceed 6 delayable requests for a given host.
- // * Prior to <body>, allow one delayable request to load at a time.
+ //
+ // THROTTLED Clients follow these rules:
+ // * Non-delayable and SPDY-capable requests are issued immediately.
+ // * At most one non-SPDY request will be issued per THROTTLED Client
+ // * If no high priority requests are in flight, start loading low priority
+ // requests.
+ //
+ // COALESCED Clients never load requests, with the following exceptions:
+ // * Non-delayable requests are issued imediately.
+ // * On a (currently 5 second) heart beat, they load all requests as an
+ // UNTHROTTLED Client, and then return to the COALESCED state.
+ // * When an active Client makes a request, they are THROTTLED until the
+ // active Client finishes loading.
ShouldStartReqResult ShouldStartRequest(
ScheduledResourceRequest* request) const {
const net::URLRequest& url_request = *request->url_request();
+ // Syncronous requests could block the entire render, which could impact
+ // user-observable Clients.
+ if (!ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) {
+ return START_REQUEST;
+ }
+
// TODO(simonjam): This may end up causing disk contention. We should
// experiment with throttling if that happens.
+ // TODO(aiolos): We probably want to Coalesce these as well to avoid
+ // waking the disk.
if (!url_request.url().SchemeIsHTTPOrHTTPS()) {
return START_REQUEST;
}
- if (using_spdy_proxy_ && url_request.url().SchemeIs("http")) {
- return START_REQUEST;
+ if (throttle_state_ == COALESCED) {
+ return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
- net::HttpServerProperties& http_server_properties =
- *url_request.context()->http_server_properties();
-
- if (url_request.priority() >= net::LOW ||
- !ResourceRequestInfo::ForRequest(&url_request)->IsAsync()) {
+ if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme)) {
return START_REQUEST;
}
net::HostPortPair host_port_pair =
net::HostPortPair::FromURL(url_request.url());
+ net::HttpServerProperties& http_server_properties =
+ *url_request.context()->http_server_properties();
// TODO(willchan): We should really improve this algorithm as described in
// crbug.com/164101. Also, theoretically we should not count a SPDY request
@@ -427,8 +677,18 @@ class ResourceScheduler::Client {
return START_REQUEST;
}
- size_t num_delayable_requests_in_flight = total_delayable_count_;
- if (num_delayable_requests_in_flight >= kMaxNumDelayableRequestsPerClient) {
+ if (throttle_state_ == THROTTLED &&
+ in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) {
+ // There may still be SPDY-capable requests that should be issued.
+ return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
+ }
+
+ // High-priority and layout-blocking requests.
+ if (url_request.priority() >= net::LOW) {
+ return START_REQUEST;
+ }
+
+ if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) {
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
@@ -439,9 +699,10 @@ class ResourceScheduler::Client {
}
bool have_immediate_requests_in_flight =
- in_flight_requests_.size() > num_delayable_requests_in_flight;
- if (have_immediate_requests_in_flight && !has_body_ &&
- num_delayable_requests_in_flight != 0) {
+ in_flight_requests_.size() > in_flight_delayable_count_;
+ if (have_immediate_requests_in_flight &&
+ (!has_body_ || total_layout_blocking_count_ != 0) &&
+ in_flight_delayable_count_ != 0) {
return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
}
@@ -485,15 +746,37 @@ class ResourceScheduler::Client {
}
}
+ bool is_audible_;
+ bool is_visible_;
+ bool is_loaded_;
+ bool is_paused_;
bool has_body_;
bool using_spdy_proxy_;
RequestQueue pending_requests_;
RequestSet in_flight_requests_;
+ ResourceScheduler* scheduler_;
// The number of delayable in-flight requests.
- size_t total_delayable_count_;
+ size_t in_flight_delayable_count_;
+ // The number of layout-blocking in-flight requests.
+ size_t total_layout_blocking_count_;
+ ResourceScheduler::ClientThrottleState throttle_state_;
};
-ResourceScheduler::ResourceScheduler() {
+ResourceScheduler::ResourceScheduler()
+ : should_coalesce_(false),
+ should_throttle_(false),
+ active_clients_loading_(0),
+ coalesced_clients_(0),
+ coalescing_timer_(new base::Timer(true /* retain_user_task */,
+ true /* is_repeating */)) {
+ std::string throttling_trial_group =
+ base::FieldTrialList::FindFullName("RequestThrottlingAndCoalescing");
+ if (throttling_trial_group == "Throttle") {
+ should_throttle_ = true;
+ } else if (throttling_trial_group == "Coalesce") {
+ should_coalesce_ = true;
+ should_throttle_ = true;
+ }
}
ResourceScheduler::~ResourceScheduler() {
@@ -501,15 +784,31 @@ ResourceScheduler::~ResourceScheduler() {
DCHECK(client_map_.empty());
}
+void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle,
+ bool should_coalesce) {
+ should_coalesce_ = should_coalesce;
+ should_throttle_ = should_throttle;
+ OnLoadingActiveClientsStateChangedForAllClients();
+}
+
+ResourceScheduler::ClientThrottleState
+ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
+ Client* client = GetClient(child_id, route_id);
+ DCHECK(client);
+ return client->throttle_state();
+}
+
scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
int child_id,
int route_id,
net::URLRequest* url_request) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
- scoped_ptr<ScheduledResourceRequest> request(
- new ScheduledResourceRequest(client_id, url_request, this,
- RequestPriorityParams(url_request->priority(), 0)));
+ scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest(
+ client_id,
+ url_request,
+ this,
+ RequestPriorityParams(url_request->priority(), 0)));
ClientMap::iterator it = client_map_.find(client_id);
if (it == client_map_.end()) {
@@ -519,12 +818,12 @@ scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
// 3. The tab is closed while a RequestResource IPC is in flight.
unowned_requests_.insert(request.get());
request->Start();
- return request.PassAs<ResourceThrottle>();
+ return request.Pass();
}
Client* client = it->second;
client->ScheduleRequest(url_request, request.get());
- return request.PassAs<ResourceThrottle>();
+ return request.Pass();
}
void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) {
@@ -543,12 +842,20 @@ void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) {
client->RemoveRequest(request);
}
-void ResourceScheduler::OnClientCreated(int child_id, int route_id) {
+void ResourceScheduler::OnClientCreated(int child_id,
+ int route_id,
+ bool is_visible,
+ bool is_audible) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
DCHECK(!ContainsKey(client_map_, client_id));
- client_map_[client_id] = new Client;
+ Client* client = new Client(this, is_visible, is_audible);
+ client_map_[client_id] = client;
+
+ // TODO(aiolos): set Client visibility/audibility when signals are added
+ // this will UNTHROTTLE Clients as needed
+ client->UpdateThrottleState();
}
void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
@@ -560,7 +867,6 @@ void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
return;
Client* client = it->second;
-
// FYI, ResourceDispatcherHost cancels all of the requests after this function
// is called. It should end up canceling all of the requests except for a
// cross-renderer navigation.
@@ -574,6 +880,31 @@ void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
client_map_.erase(it);
}
+void ResourceScheduler::OnLoadingStateChanged(int child_id,
+ int route_id,
+ bool is_loaded) {
+ Client* client = GetClient(child_id, route_id);
+ DCHECK(client);
+ client->OnLoadingStateChanged(is_loaded);
+}
+
+void ResourceScheduler::OnVisibilityChanged(int child_id,
+ int route_id,
+ bool is_visible) {
+ Client* client = GetClient(child_id, route_id);
+ DCHECK(client);
+ client->OnVisibilityChanged(is_visible);
+}
+
+void ResourceScheduler::OnAudibilityChanged(int child_id,
+ int route_id,
+ bool is_audible) {
+ Client* client = GetClient(child_id, route_id);
+ // We might get this call after the client has been deleted.
+ if (client)
+ client->OnAudibilityChanged(is_audible);
+}
+
void ResourceScheduler::OnNavigate(int child_id, int route_id) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
@@ -617,6 +948,116 @@ void ResourceScheduler::OnReceivedSpdyProxiedHttpResponse(
client->OnReceivedSpdyProxiedHttpResponse();
}
+bool ResourceScheduler::IsClientVisibleForTesting(int child_id, int route_id) {
+ Client* client = GetClient(child_id, route_id);
+ DCHECK(client);
+ return client->is_visible();
+}
+
+ResourceScheduler::Client* ResourceScheduler::GetClient(int child_id,
+ int route_id) {
+ ClientId client_id = MakeClientId(child_id, route_id);
+ ClientMap::iterator client_it = client_map_.find(client_id);
+ if (client_it == client_map_.end()) {
+ return NULL;
+ }
+ return client_it->second;
+}
+
+void ResourceScheduler::DecrementActiveClientsLoading() {
+ DCHECK_NE(0u, active_clients_loading_);
+ --active_clients_loading_;
+ DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
+ if (active_clients_loading_ == 0) {
+ OnLoadingActiveClientsStateChangedForAllClients();
+ }
+}
+
+void ResourceScheduler::IncrementActiveClientsLoading() {
+ ++active_clients_loading_;
+ DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
+ if (active_clients_loading_ == 1) {
+ OnLoadingActiveClientsStateChangedForAllClients();
+ }
+}
+
+void ResourceScheduler::OnLoadingActiveClientsStateChangedForAllClients() {
+ ClientMap::iterator client_it = client_map_.begin();
+ while (client_it != client_map_.end()) {
+ Client* client = client_it->second;
+ client->UpdateThrottleState();
+ ++client_it;
+ }
+}
+
+size_t ResourceScheduler::CountActiveClientsLoading() const {
+ size_t active_and_loading = 0;
+ ClientMap::const_iterator client_it = client_map_.begin();
+ while (client_it != client_map_.end()) {
+ Client* client = client_it->second;
+ if (client->throttle_state() == ACTIVE_AND_LOADING) {
+ ++active_and_loading;
+ }
+ ++client_it;
+ }
+ return active_and_loading;
+}
+
+void ResourceScheduler::IncrementCoalescedClients() {
+ ++coalesced_clients_;
+ DCHECK(should_coalesce_);
+ DCHECK_EQ(coalesced_clients_, CountCoalescedClients());
+ if (coalesced_clients_ == 1) {
+ coalescing_timer_->Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kCoalescedTimerPeriod),
+ base::Bind(&ResourceScheduler::LoadCoalescedRequests,
+ base::Unretained(this)));
+ }
+}
+
+void ResourceScheduler::DecrementCoalescedClients() {
+ DCHECK(should_coalesce_);
+ DCHECK_NE(0U, coalesced_clients_);
+ --coalesced_clients_;
+ DCHECK_EQ(coalesced_clients_, CountCoalescedClients());
+ if (coalesced_clients_ == 0) {
+ coalescing_timer_->Stop();
+ }
+}
+
+size_t ResourceScheduler::CountCoalescedClients() const {
+ DCHECK(should_coalesce_);
+ size_t coalesced_clients = 0;
+ ClientMap::const_iterator client_it = client_map_.begin();
+ while (client_it != client_map_.end()) {
+ Client* client = client_it->second;
+ if (client->throttle_state() == COALESCED) {
+ ++coalesced_clients;
+ }
+ ++client_it;
+ }
+ return coalesced_clients_;
+}
+
+void ResourceScheduler::LoadCoalescedRequests() {
+ DCHECK(should_coalesce_);
+ ClientMap::iterator client_it = client_map_.begin();
+ while (client_it != client_map_.end()) {
+ Client* client = client_it->second;
+ client->LoadCoalescedRequests();
+ ++client_it;
+ }
+}
+
+ResourceScheduler::ClientState ResourceScheduler::GetClientState(
+ ClientId client_id) const {
+ ClientMap::const_iterator client_it = client_map_.find(client_id);
+ if (client_it == client_map_.end())
+ return UNKNOWN;
+ return client_it->second->is_active() ? ACTIVE : BACKGROUND;
+}
+
void ResourceScheduler::ReprioritizeRequest(ScheduledResourceRequest* request,
net::RequestPriority new_priority,
int new_intra_priority_value) {
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index 0e918f10c6d..2b8d7373b4f 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -12,6 +12,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
+#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "net/base/priority_queue.h"
#include "net/base/request_priority.h"
@@ -52,9 +53,55 @@ class ResourceThrottle;
// the URLRequest.
class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
public:
+ enum ClientThrottleState {
+ // TODO(aiolos): Add logic to ShouldStartRequest for PAUSED Clients to only
+ // issue synchronous requests.
+ // TODO(aiolos): Add max number of THROTTLED Clients, and logic to set
+ // subsquent Clients to PAUSED instead. Also add logic to unpause a Client
+ // when a background Client becomes COALESCED (ie, finishes loading.)
+ // TODO(aiolos): Add tests for the above mentioned logic.
+
+ // Currently being deleted client.
+ // This state currently follows the same logic for loading requests as
+ // UNTHROTTLED/ACTIVE_AND_LOADING Clients. See above TODO's.
+ PAUSED,
+ // Loaded background client, all observable clients loaded.
+ COALESCED,
+ // Background client, an observable client is loading.
+ THROTTLED,
+ // Observable (active) loaded client or
+ // Loading background client, all observable clients loaded.
+ // Note that clients which would be COALESCED are UNTHROTTLED until
+ // coalescing is turned on.
+ UNTHROTTLED,
+ // Observable (active) loading client.
+ ACTIVE_AND_LOADING,
+ };
+
+ enum RequestClassification {
+ NORMAL_REQUEST,
+ // Low priority in-flight requests
+ IN_FLIGHT_DELAYABLE_REQUEST,
+ // High-priority requests received before the renderer has a <body>
+ LAYOUT_BLOCKING_REQUEST,
+ };
+
ResourceScheduler();
~ResourceScheduler();
+ // Use a mock timer when testing.
+ void set_timer_for_testing(scoped_ptr<base::Timer> timer) {
+ coalescing_timer_.reset(timer.release());
+ }
+
+ // TODO(aiolos): Remove when throttling and coalescing have landed
+ void SetThrottleOptionsForTesting(bool should_throttle, bool should_coalesce);
+
+ bool should_coalesce() const { return should_coalesce_; }
+ bool should_throttle() const { return should_throttle_; }
+
+ ClientThrottleState GetClientStateForTesting(int child_id, int route_id);
+
// Requests that this ResourceScheduler schedule, and eventually loads, the
// specified |url_request|. Caller should delete the returned ResourceThrottle
// when the load completes or is canceled.
@@ -64,11 +111,23 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Signals from the UI thread, posted as tasks on the IO thread:
// Called when a renderer is created.
- void OnClientCreated(int child_id, int route_id);
+ void OnClientCreated(int child_id,
+ int route_id,
+ bool is_visible,
+ bool is_audible);
// Called when a renderer is destroyed.
void OnClientDeleted(int child_id, int route_id);
+ // Called when a renderer stops or restarts loading.
+ void OnLoadingStateChanged(int child_id, int route_id, bool is_loaded);
+
+ // Called when a Client is shown or hidden.
+ void OnVisibilityChanged(int child_id, int route_id, bool is_visible);
+
+ // Called when a Client starts or stops playing audio.
+ void OnAudibilityChanged(int child_id, int route_id, bool is_audible);
+
// Signals from IPC messages directly from the renderers:
// Called when a client navigates to a new main document.
@@ -78,13 +137,29 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// resource loads won't interfere with first paint.
void OnWillInsertBody(int child_id, int route_id);
- // Signals from the IO thread
+ // Signals from the IO thread:
// Called when we received a response to a http request that was served
// from a proxy using SPDY.
void OnReceivedSpdyProxiedHttpResponse(int child_id, int route_id);
+ // Client functions:
+
+ // Called to check if all user observable tabs have completed loading.
+ bool active_clients_loaded() const { return active_clients_loading_ == 0; }
+
+ bool IsClientVisibleForTesting(int child_id, int route_id);
+
private:
+ enum ClientState {
+ // Observable client.
+ ACTIVE,
+ // Non-observable client.
+ BACKGROUND,
+ // No client found.
+ UNKNOWN,
+ };
+
class RequestQueue;
class ScheduledResourceRequest;
struct RequestPriorityParams;
@@ -101,6 +176,31 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Called when a ScheduledResourceRequest is destroyed.
void RemoveRequest(ScheduledResourceRequest* request);
+ // These calls may update the ThrottleState of all clients, and have the
+ // potential to be re-entrant.
+ // Called when a Client newly becomes active loading.
+ void IncrementActiveClientsLoading();
+ // Called when an active and loading Client either completes loading or
+ // becomes inactive.
+ void DecrementActiveClientsLoading();
+
+ void OnLoadingActiveClientsStateChangedForAllClients();
+
+ size_t CountActiveClientsLoading() const;
+
+ // Called when a Client becomes coalesced.
+ void IncrementCoalescedClients();
+ // Called when a client stops being coalesced.
+ void DecrementCoalescedClients();
+
+ void LoadCoalescedRequests();
+
+ size_t CountCoalescedClients() const;
+
+ // Returns UNKNOWN if the corresponding client is not found, else returns
+ // whether the client is ACTIVE (user-observable) or BACKGROUND.
+ ClientState GetClientState(ClientId client_id) const;
+
// Update the queue position for |request|, possibly causing it to start
// loading.
//
@@ -114,7 +214,16 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Returns the client ID for the given |child_id| and |route_id| combo.
ClientId MakeClientId(int child_id, int route_id);
+ // Returns the client for the given |child_id| and |route_id| combo.
+ Client* GetClient(int child_id, int route_id);
+
+ bool should_coalesce_;
+ bool should_throttle_;
ClientMap client_map_;
+ size_t active_clients_loading_;
+ size_t coalesced_clients_;
+ // This is a repeating timer to initiate requests on COALESCED Clients.
+ scoped_ptr<base::Timer> coalescing_timer_;
RequestSet unowned_requests_;
};
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.cc b/chromium/content/browser/loader/resource_scheduler_filter.cc
index 4c825dab987..b9f240d4fc1 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.cc
+++ b/chromium/content/browser/loader/resource_scheduler_filter.cc
@@ -8,7 +8,7 @@
#include "content/browser/loader/resource_scheduler.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
namespace content {
namespace {
@@ -43,9 +43,17 @@ bool ResourceSchedulerFilter::OnMessageReceived(const IPC::Message& message) {
&message, &iter, &params)) {
break;
}
- if (PageTransitionIsMainFrame(params.transition) &&
+ if (ui::PageTransitionIsMainFrame(params.transition) &&
!params.was_within_same_page) {
- scheduler->OnNavigate(child_id_, message.routing_id());
+ // We need to track the RenderViewHost routing_id because of downstream
+ // dependencies (crbug.com/392171 DownloadRequestHandle,
+ // SaveFileManager, ResourceDispatcherHostImpl, MediaStreamUIProxy,
+ // SpeechRecognitionDispatcherHost and possibly others). They look up
+ // the view based on the ID stored in the resource requests.
+ // Once those dependencies are unwound or moved to RenderFrameHost
+ // (crbug.com/304341) we can move the client to be based on the
+ // routing_id of the RenderFrameHost.
+ scheduler->OnNavigate(child_id_, params.render_view_routing_id);
}
break;
}
diff --git a/chromium/content/browser/loader/resource_scheduler_filter.h b/chromium/content/browser/loader/resource_scheduler_filter.h
index 9f4c5f3a7ed..0a6c23ab9f3 100644
--- a/chromium/content/browser/loader/resource_scheduler_filter.h
+++ b/chromium/content/browser/loader/resource_scheduler_filter.h
@@ -19,10 +19,10 @@ class ResourceSchedulerFilter : public BrowserMessageFilter {
explicit ResourceSchedulerFilter(int child_id);
// BrowserMessageFilter methods:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~ResourceSchedulerFilter();
+ ~ResourceSchedulerFilter() override;
int child_id_;
};
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index f4cb0e0f091..2d1b0fe34bd 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -6,7 +6,10 @@
#include "base/memory/scoped_vector.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "base/timer/mock_timer.h"
+#include "base/timer/timer.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
@@ -16,13 +19,18 @@
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_throttle.h"
#include "content/public/common/process_type.h"
+#include "content/public/common/resource_type.h"
+#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host_factory.h"
+#include "content/test/test_web_contents.h"
#include "net/base/host_port_pair.h"
#include "net/base/request_priority.h"
#include "net/http/http_server_properties_impl.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/resource_type.h"
+#include "ui/events/latency_info.h"
namespace content {
@@ -32,6 +40,12 @@ class TestRequestFactory;
const int kChildId = 30;
const int kRouteId = 75;
+const int kChildId2 = 43;
+const int kRouteId2 = 67;
+const int kBackgroundChildId = 35;
+const int kBackgroundRouteId = 43;
+const int kBackgroundChildId2 = 54;
+const int kBackgroundRouteId2 = 82;
class TestRequest : public ResourceController {
public:
@@ -42,6 +56,7 @@ class TestRequest : public ResourceController {
url_request_(url_request.Pass()) {
throttle_->set_controller_for_testing(this);
}
+ ~TestRequest() override {}
bool started() const { return started_; }
@@ -51,14 +66,18 @@ class TestRequest : public ResourceController {
started_ = !deferred;
}
+ void Cancel() override {
+ // Alert the scheduler that the request can be deleted.
+ throttle_.reset(0);
+ }
+
const net::URLRequest* url_request() const { return url_request_.get(); }
protected:
// ResourceController interface:
- virtual void Cancel() OVERRIDE {}
- virtual void CancelAndIgnore() OVERRIDE {}
- virtual void CancelWithError(int error_code) OVERRIDE {}
- virtual void Resume() OVERRIDE { started_ = true; }
+ void CancelAndIgnore() override {}
+ void CancelWithError(int error_code) override {}
+ void Resume() override { started_ = true; }
private:
bool started_;
@@ -70,15 +89,14 @@ class CancelingTestRequest : public TestRequest {
public:
CancelingTestRequest(scoped_ptr<ResourceThrottle> throttle,
scoped_ptr<net::URLRequest> url_request)
- : TestRequest(throttle.Pass(), url_request.Pass()) {
- }
+ : TestRequest(throttle.Pass(), url_request.Pass()) {}
void set_request_to_cancel(scoped_ptr<TestRequest> request_to_cancel) {
request_to_cancel_ = request_to_cancel.Pass();
}
private:
- virtual void Resume() OVERRIDE {
+ void Resume() override {
TestRequest::Resume();
request_to_cancel_.reset();
}
@@ -88,10 +106,8 @@ class CancelingTestRequest : public TestRequest {
class FakeResourceContext : public ResourceContext {
private:
- virtual net::HostResolver* GetHostResolver() OVERRIDE { return NULL; }
- virtual net::URLRequestContext* GetRequestContext() OVERRIDE { return NULL; }
- virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { return false; }
- virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { return false; }
+ net::HostResolver* GetHostResolver() override { return NULL; }
+ net::URLRequestContext* GetRequestContext() override { return NULL; }
};
class FakeResourceMessageFilter : public ResourceMessageFilter {
@@ -109,7 +125,7 @@ class FakeResourceMessageFilter : public ResourceMessageFilter {
}
private:
- virtual ~FakeResourceMessageFilter() {}
+ ~FakeResourceMessageFilter() override {}
void GetContexts(const ResourceHostMsg_Request& request,
ResourceContext** resource_context,
@@ -126,67 +142,121 @@ class ResourceSchedulerTest : public testing::Test {
ResourceSchedulerTest()
: next_request_id_(0),
ui_thread_(BrowserThread::UI, &message_loop_),
- io_thread_(BrowserThread::IO, &message_loop_) {
- scheduler_.OnClientCreated(kChildId, kRouteId);
+ io_thread_(BrowserThread::IO, &message_loop_),
+ mock_timer_(new base::MockTimer(true, true)) {
+ scheduler_.set_timer_for_testing(scoped_ptr<base::Timer>(mock_timer_));
+
+ // TODO(aiolos): Remove when throttling and coalescing have both landed.
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+
+ scheduler_.OnClientCreated(kChildId, kRouteId, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId, kBackgroundRouteId, false, false);
context_.set_http_server_properties(http_server_properties_.GetWeakPtr());
}
- virtual ~ResourceSchedulerTest() {
+ ~ResourceSchedulerTest() override {
scheduler_.OnClientDeleted(kChildId, kRouteId);
+ scheduler_.OnClientDeleted(kBackgroundChildId, kBackgroundRouteId);
}
- scoped_ptr<net::URLRequest> NewURLRequestWithRoute(
+ scoped_ptr<net::URLRequest> NewURLRequestWithChildAndRoute(
const char* url,
net::RequestPriority priority,
- int route_id) {
+ int child_id,
+ int route_id,
+ bool is_async) {
scoped_ptr<net::URLRequest> url_request(
context_.CreateRequest(GURL(url), priority, NULL, NULL));
ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl(
- PROCESS_TYPE_RENDERER, // process_type
- kChildId, // child_id
- route_id, // route_id
- 0, // origin_pid
- ++next_request_id_, // request_id
- MSG_ROUTING_NONE, // render_frame_id
- false, // is_main_frame
- false, // parent_is_main_frame
- 0, // parent_render_frame_id
- ResourceType::SUB_RESOURCE, // resource_type
- PAGE_TRANSITION_LINK, // transition_type
- false, // should_replace_current_entry
- false, // is_download
- false, // is_stream
- true, // allow_download
- false, // has_user_gesture
- blink::WebReferrerPolicyDefault, // referrer_policy
- blink::WebPageVisibilityStateVisible, // visibility_state
- NULL, // context
+ PROCESS_TYPE_RENDERER, // process_type
+ child_id, // child_id
+ route_id, // route_id
+ 0, // origin_pid
+ ++next_request_id_, // request_id
+ MSG_ROUTING_NONE, // render_frame_id
+ false, // is_main_frame
+ false, // parent_is_main_frame
+ 0, // parent_render_frame_id
+ RESOURCE_TYPE_SUB_RESOURCE, // resource_type
+ ui::PAGE_TRANSITION_LINK, // transition_type
+ false, // should_replace_current_entry
+ false, // is_download
+ false, // is_stream
+ true, // allow_download
+ false, // has_user_gesture
+ false, // enable_load_timing
+ false, // enable_upload_progress
+ blink::WebReferrerPolicyDefault, // referrer_policy
+ blink::WebPageVisibilityStateVisible, // visibility_state
+ NULL, // context
base::WeakPtr<ResourceMessageFilter>(), // filter
- true); // is_async
+ is_async); // is_async
info->AssociateWithRequest(url_request.get());
return url_request.Pass();
}
scoped_ptr<net::URLRequest> NewURLRequest(const char* url,
net::RequestPriority priority) {
- return NewURLRequestWithRoute(url, priority, kRouteId);
+ return NewURLRequestWithChildAndRoute(
+ url, priority, kChildId, kRouteId, true);
}
TestRequest* NewRequestWithRoute(const char* url,
net::RequestPriority priority,
int route_id) {
- scoped_ptr<net::URLRequest> url_request(
- NewURLRequestWithRoute(url, priority, route_id));
- scoped_ptr<ResourceThrottle> throttle(scheduler_.ScheduleRequest(
- kChildId, route_id, url_request.get()));
+ return NewRequestWithChildAndRoute(url, priority, route_id, kChildId);
+ }
+
+ TestRequest* NewRequestWithChildAndRoute(const char* url,
+ net::RequestPriority priority,
+ int child_id,
+ int route_id) {
+ return GetNewTestRequest(url, priority, child_id, route_id, true);
+ }
+
+ TestRequest* NewRequest(const char* url, net::RequestPriority priority) {
+ return NewRequestWithChildAndRoute(url, priority, kChildId, kRouteId);
+ }
+
+ TestRequest* NewBackgroundRequest(const char* url,
+ net::RequestPriority priority) {
+ return NewRequestWithChildAndRoute(
+ url, priority, kBackgroundChildId, kBackgroundRouteId);
+ }
+
+ TestRequest* NewSyncRequest(const char* url, net::RequestPriority priority) {
+ return NewSyncRequestWithChildAndRoute(url, priority, kChildId, kRouteId);
+ }
+
+ TestRequest* NewBackgroundSyncRequest(const char* url,
+ net::RequestPriority priority) {
+ return NewSyncRequestWithChildAndRoute(
+ url, priority, kBackgroundChildId, kBackgroundRouteId);
+ }
+
+ TestRequest* NewSyncRequestWithChildAndRoute(const char* url,
+ net::RequestPriority priority,
+ int child_id,
+ int route_id) {
+ return GetNewTestRequest(url, priority, child_id, route_id, false);
+ }
+
+ TestRequest* GetNewTestRequest(const char* url,
+ net::RequestPriority priority,
+ int child_id,
+ int route_id,
+ bool is_async) {
+ scoped_ptr<net::URLRequest> url_request(NewURLRequestWithChildAndRoute(
+ url, priority, child_id, route_id, is_async));
+ scoped_ptr<ResourceThrottle> throttle(
+ scheduler_.ScheduleRequest(child_id, route_id, url_request.get()));
TestRequest* request = new TestRequest(throttle.Pass(), url_request.Pass());
request->Start();
return request;
}
- TestRequest* NewRequest(const char* url, net::RequestPriority priority) {
- return NewRequestWithRoute(url, priority, kRouteId);
- }
void ChangeRequestPriority(TestRequest* request,
net::RequestPriority new_priority,
@@ -201,12 +271,18 @@ class ResourceSchedulerTest : public testing::Test {
rdh_.OnMessageReceived(msg, filter.get());
}
+ void FireCoalescingTimer() {
+ EXPECT_TRUE(mock_timer_->IsRunning());
+ mock_timer_->Fire();
+ }
+
int next_request_id_;
base::MessageLoopForIO message_loop_;
BrowserThreadImpl ui_thread_;
BrowserThreadImpl io_thread_;
ResourceDispatcherHostImpl rdh_;
ResourceScheduler scheduler_;
+ base::MockTimer* mock_timer_;
net::HttpServerPropertiesImpl http_server_properties_;
net::TestURLRequestContext context_;
};
@@ -234,16 +310,42 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) {
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
+ high.reset();
scheduler_.OnWillInsertBody(kChildId, kRouteId);
EXPECT_TRUE(low2->started());
}
+TEST_F(ResourceSchedulerTest, OneLowLoadsUntilCriticalComplete) {
+ scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ EXPECT_TRUE(high->started());
+ EXPECT_TRUE(low->started());
+ EXPECT_FALSE(low2->started());
+ scheduler_.OnWillInsertBody(kChildId, kRouteId);
+ EXPECT_FALSE(low2->started());
+ high.reset();
+ EXPECT_TRUE(low2->started());
+}
+
+TEST_F(ResourceSchedulerTest, LowDoesNotBlockCriticalComplete) {
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOW));
+ scoped_ptr<TestRequest> lowest(NewRequest("http://host/lowest", net::LOWEST));
+ scoped_ptr<TestRequest> lowest2(
+ NewRequest("http://host/lowest", net::LOWEST));
+ EXPECT_TRUE(low->started());
+ EXPECT_TRUE(lowest->started());
+ EXPECT_FALSE(lowest2->started());
+ scheduler_.OnWillInsertBody(kChildId, kRouteId);
+ EXPECT_TRUE(lowest2->started());
+}
+
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
http_server_properties_.SetSupportsSpdy(
net::HostPortPair("spdyhost", 443), true);
scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
scoped_ptr<TestRequest> low_spdy(
- NewRequest("https://spdyhost/high", net::LOWEST));
+ NewRequest("https://spdyhost/low", net::LOWEST));
scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
@@ -251,6 +353,7 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
scheduler_.OnWillInsertBody(kChildId, kRouteId);
+ high.reset();
EXPECT_TRUE(low2->started());
}
@@ -293,8 +396,8 @@ TEST_F(ResourceSchedulerTest, CancelOtherRequestsWhileResuming) {
scoped_ptr<net::URLRequest> url_request(
NewURLRequest("http://host/low2", net::LOWEST));
- scoped_ptr<ResourceThrottle> throttle(scheduler_.ScheduleRequest(
- kChildId, kRouteId, url_request.get()));
+ scoped_ptr<ResourceThrottle> throttle(
+ scheduler_.ScheduleRequest(kChildId, kRouteId, url_request.get()));
scoped_ptr<CancelingTestRequest> low2(new CancelingTestRequest(
throttle.Pass(), url_request.Pass()));
low2->Start();
@@ -391,6 +494,8 @@ TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) {
}
scheduler_.OnWillInsertBody(kChildId, kRouteId);
+ high.reset();
+
EXPECT_TRUE(request->started());
EXPECT_FALSE(idle->started());
}
@@ -420,6 +525,8 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
}
scheduler_.OnWillInsertBody(kChildId, kRouteId);
+ high.reset();
+
EXPECT_FALSE(request->started());
EXPECT_TRUE(idle->started());
}
@@ -427,7 +534,7 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
// Dummies to enforce scheduling.
scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/high", net::LOWEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST));
scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
@@ -457,7 +564,7 @@ TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
// Dummies to enforce scheduling.
scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/high", net::LOWEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
ScopedVector<TestRequest> lows;
@@ -473,19 +580,52 @@ TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
EXPECT_FALSE(request->started());
scheduler_.OnWillInsertBody(kChildId, kRouteId);
+ high.reset();
EXPECT_TRUE(request->started());
}
TEST_F(ResourceSchedulerTest, NonHTTPSchedulesImmediately) {
// Dummies to enforce scheduling.
scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/high", net::LOWEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
scoped_ptr<TestRequest> request(
NewRequest("chrome-extension://req", net::LOWEST));
EXPECT_TRUE(request->started());
}
+TEST_F(ResourceSchedulerTest, ActiveLoadingSyncSchedulesImmediately) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewSyncRequest("http://host/req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, UnthrottledSyncSchedulesImmediately) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewBackgroundSyncRequest("http://host/req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+}
+
TEST_F(ResourceSchedulerTest, SpdyProxySchedulesImmediately) {
scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
@@ -531,6 +671,1543 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
EXPECT_TRUE(low2->started());
}
+TEST_F(ResourceSchedulerTest, ThrottledClientCreation) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_TRUE(scheduler_.should_throttle());
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, ActiveClientThrottleUpdateOnLoadingChange) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+}
+
+TEST_F(ResourceSchedulerTest, CoalesceBackgroundClientOnLoadCompletion) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+}
+
+TEST_F(ResourceSchedulerTest, UnthrottleBackgroundClientOnLoadingStarted) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, false);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+}
+
+TEST_F(ResourceSchedulerTest, OneRequestPerThrottledClient) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+
+ EXPECT_TRUE(high->started());
+ EXPECT_FALSE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, UnthrottleNewlyVisibleClient) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+ EXPECT_FALSE(request->started());
+
+ scheduler_.OnVisibilityChanged(kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, UnthrottleNewlyAudibleClient) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+ EXPECT_FALSE(request->started());
+
+ scheduler_.OnAudibilityChanged(kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(request->started());
+}
+
+TEST_F(ResourceSchedulerTest, VisibleClientStillUnthrottledOnAudabilityChange) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, false);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+}
+
+TEST_F(ResourceSchedulerTest, AudibleClientStillUnthrottledOnVisabilityChange) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+}
+
+TEST_F(ResourceSchedulerTest, ThrottledClientStartsNextHighestPriorityRequest) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+ // Lower priority request started first to test request prioritizaton.
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/high", net::IDLE));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+
+ EXPECT_FALSE(low->started());
+ EXPECT_FALSE(high->started());
+
+ // request->CancelRequest();
+ request->Cancel();
+ EXPECT_TRUE(high->started());
+ EXPECT_FALSE(low->started());
+}
+
+TEST_F(ResourceSchedulerTest, ThrottledSpdyProxySchedulesImmediately) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+
+ EXPECT_FALSE(request->started());
+
+ scheduler_.OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
+ kBackgroundRouteId);
+ EXPECT_TRUE(request->started());
+
+ scoped_ptr<TestRequest> after(
+ NewBackgroundRequest("http://host/after", net::IDLE));
+ EXPECT_TRUE(after->started());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedClientIssuesNoRequests) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+
+ EXPECT_FALSE(high->started());
+ EXPECT_FALSE(request->started());
+
+ scheduler_.OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
+ kBackgroundRouteId);
+ EXPECT_FALSE(high->started());
+
+ scoped_ptr<TestRequest> after(
+ NewBackgroundRequest("http://host/after", net::HIGHEST));
+ EXPECT_FALSE(after->started());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedSpdyProxyWaits) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("http://host/req", net::IDLE));
+
+ EXPECT_FALSE(request->started());
+
+ scheduler_.OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
+ kBackgroundRouteId);
+ EXPECT_FALSE(request->started());
+
+ scoped_ptr<TestRequest> after(
+ NewBackgroundRequest("http://host/after", net::IDLE));
+ EXPECT_FALSE(after->started());
+}
+
+TEST_F(ResourceSchedulerTest, ThrottledNonHTTPSchedulesImmediately) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("chrome-extension://req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(low->started());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedNonHTTPSchedulesImmediately) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewBackgroundRequest("chrome-extension://req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(low->started());
+}
+
+TEST_F(ResourceSchedulerTest, ThrottledSyncSchedulesImmediately) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewBackgroundSyncRequest("http://host/req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(low->started());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedSyncSchedulesImmediately) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ // Dummies to enforce scheduling.
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ scoped_ptr<TestRequest> request(
+ NewBackgroundSyncRequest("http://host/req", net::LOWEST));
+ EXPECT_TRUE(request->started());
+ EXPECT_FALSE(low->started());
+ EXPECT_FALSE(high->started());
+}
+
+TEST_F(ResourceSchedulerTest, AllBackgroundClientsUnthrottle) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+}
+
+TEST_F(ResourceSchedulerTest,
+ UnloadedClientVisibilityChangedCorrectlyUnthrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, false, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+
+ // 1 visible, 3 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 2 visible, 2 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible, 3 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest,
+ UnloadedClientAudibilityChangedCorrectlyUnthrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, false, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+
+ // 1 audible, 3 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 2 audible, 2 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 audible, 3 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest,
+ LoadedClientVisibilityChangedCorrectlyUnthrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, false, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ // 1 visible, 3 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 2 visible, 2 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible, 3 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest,
+ LoadedClientAudibilityChangedCorrectlyUnthrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, false, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+ // 1 audible, 3 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 2 audible, 2 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 audible, 3 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, UnloadedClientBecomesHiddenCorrectlyUnthrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+
+ // 2 visible, 2 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible, 3 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 0 visible, 4 hidden
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible, 3 hidden
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, UnloadedClientBecomesSilentCorrectlyUnthrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, false, true);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ // 2 audible, 2 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 audible, 3 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 0 audible, 4 hidden
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, false);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 audible, 3 hidden
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, LoadedClientBecomesHiddenCorrectlyThrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ // 2 visible, 2 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible, 3 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 0 visible, 4 hidden
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible, 3 hidden
+ scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, LoadedClientBecomesSilentCorrectlyThrottles) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, false, true);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, true);
+ // 2 audible, 2 hidden
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 audible, 3 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 0 audible, 4 hidden
+ scheduler_.OnAudibilityChanged(kChildId, kRouteId, false);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 audible, 3 hidden
+ scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, HiddenLoadedChangesCorrectlyStayThrottled) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+
+ // 1 visible and 2 hidden loading, 1 visible loaded
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible and 1 hidden loading, 1 visible and 1 hidden loaded
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible loading, 1 visible and 2 hidden loaded
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible and 1 hidden loading, 1 visible and 1 hidden loaded
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, PartialVisibleClientLoadedDoesNotUnthrottle) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+
+ // 2 visible loading, 1 hidden loading, 1 hidden loaded
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 2 visible loading, 1 hidden loading, 1 hidden loaded
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, FullVisibleLoadedCorrectlyUnthrottle) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+
+ // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ EXPECT_TRUE(high->started());
+ EXPECT_FALSE(low->started());
+
+ // 2 visible loaded, 1 hidden loading, 1 hidden loaded
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ // kBackgroundClientId unthrottling should unthrottle it's request.
+ EXPECT_TRUE(low->started());
+
+ // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest,
+ ActiveAndLoadingClientDeletedCorrectlyUnthrottle) {
+ // TODO(aiolos): remove when throttling and coalescing have both landed
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ false /* should_coalesce */);
+ scheduler_.OnClientCreated(kChildId2, kRouteId2, true, false);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+
+ // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId2, kRouteId2));
+
+ // 1 visible loaded, 1 hidden loading, 1 hidden loaded
+ scheduler_.OnClientDeleted(kChildId2, kRouteId2);
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false);
+ EXPECT_FALSE(scheduler_.active_clients_loaded());
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedClientCreationStartsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+}
+
+TEST_F(ResourceSchedulerTest, ActiveLoadingClientLoadedAndHiddenStartsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+}
+
+TEST_F(ResourceSchedulerTest, ActiveLoadingClientHiddenAndLoadedStartsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::THROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ scheduler_.OnVisibilityChanged(kChildId, kRouteId, false);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kChildId, kRouteId));
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedClientBecomesAudibleStopsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnAudibilityChanged(kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+}
+
+TEST_F(ResourceSchedulerTest, LastCoalescedClientDeletionStopsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnClientDeleted(kBackgroundChildId, kBackgroundRouteId);
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ // To avoid errors on test tear down.
+ scheduler_.OnClientCreated(
+ kBackgroundChildId, kBackgroundRouteId, false, false);
+}
+
+TEST_F(ResourceSchedulerTest, LastCoalescedClientStartsLoadingStopsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, false);
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, false);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ // This is needed to avoid errors on test tear down.
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest, LastCoalescedClientBecomesVisibleStopsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnClientCreated(
+ kBackgroundChildId2, kBackgroundRouteId2, false, false);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId2,
+ kBackgroundRouteId2));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnVisibilityChanged(kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnVisibilityChanged(
+ kBackgroundChildId2, kBackgroundRouteId2, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ // To avoid errors on test tear down.
+ scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
+}
+
+TEST_F(ResourceSchedulerTest,
+ CoalescedClientBecomesLoadingAndVisibleStopsTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ EXPECT_FALSE(mock_timer_->IsRunning());
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(mock_timer_->IsRunning());
+
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, false);
+ EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+
+ scheduler_.OnVisibilityChanged(kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_FALSE(mock_timer_->IsRunning());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedRequestsIssueOnTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+ EXPECT_FALSE(high->started());
+ EXPECT_FALSE(low->started());
+
+ FireCoalescingTimer();
+
+ EXPECT_TRUE(high->started());
+ EXPECT_TRUE(low->started());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedRequestsUnthrottleCorrectlyOnTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> high2(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> high3(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> high4(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+ scoped_ptr<TestRequest> low2(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+ scoped_ptr<TestRequest> low3(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+ scoped_ptr<TestRequest> low4(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ http_server_properties_.SetSupportsSpdy(net::HostPortPair("spdyhost", 443),
+ true);
+ scoped_ptr<TestRequest> low_spdy(
+ NewBackgroundRequest("https://spdyhost/low", net::LOW));
+ scoped_ptr<TestRequest> sync_request(
+ NewBackgroundSyncRequest("http://host/req", net::LOW));
+ scoped_ptr<TestRequest> non_http_request(
+ NewBackgroundRequest("chrome-extension://req", net::LOW));
+
+ // Sync requests should issue immediately.
+ EXPECT_TRUE(sync_request->started());
+ // Non-http(s) requests should issue immediately.
+ EXPECT_TRUE(non_http_request->started());
+ // Nothing else should issue without a timer fire.
+ EXPECT_FALSE(high->started());
+ EXPECT_FALSE(high2->started());
+ EXPECT_FALSE(high3->started());
+ EXPECT_FALSE(high4->started());
+ EXPECT_FALSE(low->started());
+ EXPECT_FALSE(low2->started());
+ EXPECT_FALSE(low3->started());
+ EXPECT_FALSE(low4->started());
+ EXPECT_FALSE(low_spdy->started());
+
+ FireCoalescingTimer();
+
+ // All high priority requests should issue.
+ EXPECT_TRUE(high->started());
+ EXPECT_TRUE(high2->started());
+ EXPECT_TRUE(high3->started());
+ EXPECT_TRUE(high4->started());
+ // There should only be one net::LOWEST priority request issued with
+ // non-delayable requests in flight.
+ EXPECT_TRUE(low->started());
+ EXPECT_FALSE(low2->started());
+ EXPECT_FALSE(low3->started());
+ EXPECT_FALSE(low4->started());
+ // Spdy-Enable requests should issue regardless of priority.
+ EXPECT_TRUE(low_spdy->started());
+}
+
+TEST_F(ResourceSchedulerTest, CoalescedRequestsWaitForNextTimer) {
+ scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */,
+ true /* should_coalesce */);
+ scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true);
+ scheduler_.OnLoadingStateChanged(
+ kBackgroundChildId, kBackgroundRouteId, true);
+
+ EXPECT_EQ(ResourceScheduler::COALESCED,
+ scheduler_.GetClientStateForTesting(kBackgroundChildId,
+ kBackgroundRouteId));
+ EXPECT_TRUE(scheduler_.active_clients_loaded());
+
+ scoped_ptr<TestRequest> high(
+ NewBackgroundRequest("http://host/high", net::HIGHEST));
+ EXPECT_FALSE(high->started());
+
+ FireCoalescingTimer();
+
+ scoped_ptr<TestRequest> high2(
+ NewBackgroundRequest("http://host/high2", net::HIGHEST));
+ scoped_ptr<TestRequest> low(
+ NewBackgroundRequest("http://host/low", net::LOWEST));
+
+ EXPECT_TRUE(high->started());
+ EXPECT_FALSE(high2->started());
+ EXPECT_FALSE(low->started());
+
+ FireCoalescingTimer();
+
+ EXPECT_TRUE(high->started());
+ EXPECT_TRUE(high2->started());
+ EXPECT_TRUE(low->started());
+}
+
+TEST_F(ResourceSchedulerTest, GetVisualSignalFromRenderViewHost) {
+ scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory;
+ scoped_ptr<TestRenderViewHostFactory> render_view_host_factory;
+ scoped_ptr<TestBrowserContext> browser_context;
+ scoped_ptr<TestWebContents> web_contents_1;
+ scoped_ptr<TestWebContents> web_contents_2;
+ render_process_host_factory.reset(new MockRenderProcessHostFactory());
+ render_view_host_factory.reset(
+ new TestRenderViewHostFactory(render_process_host_factory.get()));
+
+ browser_context.reset(new TestBrowserContext());
+ scoped_refptr<SiteInstance> site_instance_1 =
+ SiteInstance::Create(browser_context.get());
+ scoped_refptr<SiteInstance> site_instance_2 =
+ SiteInstance::Create(browser_context.get());
+ SiteInstanceImpl::set_render_process_host_factory(
+ render_process_host_factory.get());
+
+ web_contents_1.reset(
+ TestWebContents::Create(browser_context.get(), site_instance_1.get()));
+ web_contents_2.reset(
+ TestWebContents::Create(browser_context.get(), site_instance_2.get()));
+ base::RunLoop().RunUntilIdle();
+
+ RenderViewHostImpl* rvh1 = web_contents_1->GetRenderViewHost();
+ RenderViewHostImpl* rvh2 = web_contents_2->GetRenderViewHost();
+ ResourceScheduler* scheduler = ResourceDispatcherHostImpl::Get()->scheduler();
+
+ // Check initial visibility is set correctly.
+ EXPECT_EQ(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
+ rvh1->GetRoutingID()),
+ !rvh1->is_hidden());
+ EXPECT_EQ(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
+ rvh1->GetRoutingID()),
+ !rvh2->is_hidden());
+
+ // 1 visible, 1 hidden
+ rvh1->WasShown(ui::LatencyInfo());
+ rvh2->WasHidden();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
+ rvh1->GetRoutingID()));
+ EXPECT_FALSE(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
+ rvh2->GetRoutingID()));
+
+ // Flip the visibility and check again.
+ rvh1->WasHidden();
+ rvh2->WasShown(ui::LatencyInfo());
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
+ rvh1->GetRoutingID()));
+ EXPECT_TRUE(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
+ rvh2->GetRoutingID()));
+ // Clean up.
+ web_contents_1.reset();
+ web_contents_2.reset();
+ base::RunLoop().RunUntilIdle();
+
+ browser_context.reset();
+ render_process_host_factory.reset();
+}
+
} // unnamed namespace
} // namespace content
diff --git a/chromium/content/browser/loader/stream_resource_handler.cc b/chromium/content/browser/loader/stream_resource_handler.cc
index 46713fc67fa..08827e19feb 100644
--- a/chromium/content/browser/loader/stream_resource_handler.cc
+++ b/chromium/content/browser/loader/stream_resource_handler.cc
@@ -4,31 +4,23 @@
#include "content/browser/loader/stream_resource_handler.h"
-#include "base/guid.h"
#include "base/logging.h"
-#include "content/browser/streams/stream.h"
-#include "content/browser/streams/stream_registry.h"
-#include "content/public/browser/resource_controller.h"
-#include "net/base/io_buffer.h"
-#include "net/url_request/url_request_status.h"
-#include "url/url_constants.h"
namespace content {
StreamResourceHandler::StreamResourceHandler(net::URLRequest* request,
StreamRegistry* registry,
const GURL& origin)
- : ResourceHandler(request),
- read_buffer_(NULL) {
- // TODO(tyoshino): Find a way to share this with the blob URL creation in
- // WebKit.
- GURL url(std::string(url::kBlobScheme) + ":" + origin.spec() +
- base::GenerateGUID());
- stream_ = new Stream(registry, this, url);
+ : ResourceHandler(request) {
+ writer_.InitializeStream(registry, origin);
}
StreamResourceHandler::~StreamResourceHandler() {
- stream_->RemoveWriteObserver(this);
+}
+
+void StreamResourceHandler::SetController(ResourceController* controller) {
+ writer_.set_controller(controller);
+ ResourceHandler::SetController(controller);
}
bool StreamResourceHandler::OnUploadProgress(uint64 position,
@@ -36,9 +28,10 @@ bool StreamResourceHandler::OnUploadProgress(uint64 position,
return true;
}
-bool StreamResourceHandler::OnRequestRedirected(const GURL& url,
- ResourceResponse* resp,
- bool* defer) {
+bool StreamResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* resp,
+ bool* defer) {
return true;
}
@@ -58,33 +51,12 @@ bool StreamResourceHandler::OnBeforeNetworkStart(const GURL& url, bool* defer) {
bool StreamResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) {
- static const int kReadBufSize = 32768;
-
- DCHECK(buf && buf_size);
- if (!read_buffer_.get())
- read_buffer_ = new net::IOBuffer(kReadBufSize);
- *buf = read_buffer_.get();
- *buf_size = kReadBufSize;
-
+ writer_.OnWillRead(buf, buf_size, min_size);
return true;
}
bool StreamResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
- if (!bytes_read)
- return true;
-
- // We have more data to read.
- DCHECK(read_buffer_.get());
-
- // Release the ownership of the buffer, and store a reference
- // to it. A new one will be allocated in OnWillRead().
- scoped_refptr<net::IOBuffer> buffer;
- read_buffer_.swap(buffer);
- stream_->AddData(buffer, bytes_read);
-
- if (!stream_->can_add_data())
- *defer = true;
-
+ writer_.OnReadCompleted(bytes_read, defer);
return true;
}
@@ -92,19 +64,11 @@ void StreamResourceHandler::OnResponseCompleted(
const net::URLRequestStatus& status,
const std::string& sec_info,
bool* defer) {
- stream_->Finalize();
+ writer_.Finalize();
}
void StreamResourceHandler::OnDataDownloaded(int bytes_downloaded) {
NOTREACHED();
}
-void StreamResourceHandler::OnSpaceAvailable(Stream* stream) {
- controller()->Resume();
-}
-
-void StreamResourceHandler::OnClose(Stream* stream) {
- controller()->Cancel();
-}
-
} // namespace content
diff --git a/chromium/content/browser/loader/stream_resource_handler.h b/chromium/content/browser/loader/stream_resource_handler.h
index 3b8bc217890..4ec226e21e1 100644
--- a/chromium/content/browser/loader/stream_resource_handler.h
+++ b/chromium/content/browser/loader/stream_resource_handler.h
@@ -8,8 +8,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "content/browser/loader/resource_handler.h"
-#include "content/browser/streams/stream_write_observer.h"
-#include "url/gurl.h"
+#include "content/browser/loader/stream_writer.h"
namespace net {
class URLRequest;
@@ -20,8 +19,7 @@ namespace content {
class StreamRegistry;
// Redirect this resource to a stream.
-class StreamResourceHandler : public StreamWriteObserver,
- public ResourceHandler {
+class StreamResourceHandler : public ResourceHandler {
public:
// |origin| will be used to construct the URL for the Stream. See
// WebCore::BlobURL and and WebCore::SecurityOrigin in Blink to understand
@@ -29,44 +27,42 @@ class StreamResourceHandler : public StreamWriteObserver,
StreamResourceHandler(net::URLRequest* request,
StreamRegistry* registry,
const GURL& origin);
- virtual ~StreamResourceHandler();
+ ~StreamResourceHandler() override;
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
+ void SetController(ResourceController* controller) override;
+
+ bool OnUploadProgress(uint64 position, uint64 size) override;
// Not needed, as this event handler ought to be the final resource.
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* resp,
- bool* defer) OVERRIDE;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* resp,
+ bool* defer) override;
- virtual bool OnResponseStarted(ResourceResponse* resp,
- bool* defer) OVERRIDE;
+ bool OnResponseStarted(ResourceResponse* resp, bool* defer) override;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnWillStart(const GURL& url, bool* defer) override;
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
// Create a new buffer to store received data.
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
// A read was completed, forward the data to the Stream.
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& sec_info,
- bool* defer) OVERRIDE;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& sec_info,
+ bool* defer) override;
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ void OnDataDownloaded(int bytes_downloaded) override;
- Stream* stream() { return stream_.get(); }
+ Stream* stream() { return writer_.stream(); }
private:
- virtual void OnSpaceAvailable(Stream* stream) OVERRIDE;
- virtual void OnClose(Stream* stream) OVERRIDE;
+ StreamWriter writer_;
- scoped_refptr<Stream> stream_;
- scoped_refptr<net::IOBuffer> read_buffer_;
DISALLOW_COPY_AND_ASSIGN(StreamResourceHandler);
};
diff --git a/chromium/content/browser/loader/stream_writer.cc b/chromium/content/browser/loader/stream_writer.cc
new file mode 100644
index 00000000000..99b5ee1d3b0
--- /dev/null
+++ b/chromium/content/browser/loader/stream_writer.cc
@@ -0,0 +1,82 @@
+// Copyright 2014 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 "content/browser/loader/stream_writer.h"
+
+#include "base/guid.h"
+#include "content/browser/streams/stream.h"
+#include "content/browser/streams/stream_registry.h"
+#include "content/public/browser/resource_controller.h"
+#include "net/base/io_buffer.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
+
+namespace content {
+
+StreamWriter::StreamWriter() : controller_(nullptr) {
+}
+
+StreamWriter::~StreamWriter() {
+ if (stream_.get())
+ Finalize();
+}
+
+void StreamWriter::InitializeStream(StreamRegistry* registry,
+ const GURL& origin) {
+ DCHECK(!stream_.get());
+
+ // TODO(tyoshino): Find a way to share this with the blob URL creation in
+ // WebKit.
+ GURL url(std::string(url::kBlobScheme) + ":" + origin.spec() +
+ base::GenerateGUID());
+ stream_ = new Stream(registry, this, url);
+}
+
+void StreamWriter::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) {
+ static const int kReadBufSize = 32768;
+
+ DCHECK(buf);
+ DCHECK(buf_size);
+ DCHECK_LE(min_size, kReadBufSize);
+ if (!read_buffer_.get())
+ read_buffer_ = new net::IOBuffer(kReadBufSize);
+ *buf = read_buffer_.get();
+ *buf_size = kReadBufSize;
+}
+
+void StreamWriter::OnReadCompleted(int bytes_read, bool* defer) {
+ if (!bytes_read)
+ return;
+
+ // We have more data to read.
+ DCHECK(read_buffer_.get());
+
+ // Release the ownership of the buffer, and store a reference
+ // to it. A new one will be allocated in OnWillRead().
+ scoped_refptr<net::IOBuffer> buffer;
+ read_buffer_.swap(buffer);
+ stream_->AddData(buffer, bytes_read);
+
+ if (!stream_->can_add_data())
+ *defer = true;
+}
+
+void StreamWriter::Finalize() {
+ DCHECK(stream_.get());
+ stream_->Finalize();
+ stream_->RemoveWriteObserver(this);
+ stream_ = nullptr;
+}
+
+void StreamWriter::OnSpaceAvailable(Stream* stream) {
+ controller_->Resume();
+}
+
+void StreamWriter::OnClose(Stream* stream) {
+ controller_->Cancel();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/loader/stream_writer.h b/chromium/content/browser/loader/stream_writer.h
new file mode 100644
index 00000000000..a611e26dde6
--- /dev/null
+++ b/chromium/content/browser/loader/stream_writer.h
@@ -0,0 +1,83 @@
+// Copyright 2014 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 CONTENT_BROWSER_LOADER_STREAM_WRITER_H_
+#define CONTENT_BROWSER_LOADER_STREAM_WRITER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/browser/streams/stream_write_observer.h"
+
+class GURL;
+
+namespace net {
+class IOBuffer;
+}
+
+namespace content {
+
+class ResourceController;
+class Stream;
+class StreamRegistry;
+
+// StreamWriter is a helper class for ResourceHandlers which route their output
+// into a Stream. It manages an internal buffer and handles back-pressure from
+// the Stream's reader.
+class StreamWriter : public StreamWriteObserver {
+ public:
+ // Creates a new StreamWriter without an initialized Stream or controller. The
+ // controller must be set before the writer is used.
+ StreamWriter();
+ ~StreamWriter() override;
+
+ Stream* stream() { return stream_.get(); }
+
+ void set_controller(ResourceController* controller) {
+ controller_ = controller;
+ }
+
+ // Initializes the writer with a new Stream in |registry|. |origin| will be
+ // used to construct the URL for the Stream. See WebCore::BlobURL and and
+ // WebCore::SecurityOrigin in Blink to understand how origin check is done on
+ // resource loading.
+ void InitializeStream(StreamRegistry* registry,
+ const GURL& origin);
+
+ // Prepares a buffer to read data from the request. This call will be followed
+ // by either OnReadCompleted (on successful read or EOF) or destruction. The
+ // buffer may not be recycled until OnReadCompleted is called. If |min_size|
+ // is not -1, it is the minimum size of the returned buffer.
+ //
+ // OnWillRead may be called before the stream is initialized. This is to
+ // support BufferedResourceHandler which reads the initial chunk of data
+ // early.
+ void OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size);
+
+ // A read was completed, forward the data to the Stream. If |*defer| is set to
+ // true, the implementation must not continue to process the request until
+ // Resume is called on |controller_|.
+ //
+ // InitializeStream must have been called before calling OnReadCompleted.
+ void OnReadCompleted(int bytes_read, bool* defer);
+
+ // Called when there is no more data to read to the stream.
+ void Finalize();
+
+ private:
+ // StreamWriteObserver implementation.
+ void OnSpaceAvailable(Stream* stream) override;
+ void OnClose(Stream* stream) override;
+
+ ResourceController* controller_;
+ scoped_refptr<Stream> stream_;
+ scoped_refptr<net::IOBuffer> read_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamWriter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LOADER_STREAM_WRITER_H_
diff --git a/chromium/content/browser/loader/sync_resource_handler.cc b/chromium/content/browser/loader/sync_resource_handler.cc
index 090b9391056..1da8887daa9 100644
--- a/chromium/content/browser/loader/sync_resource_handler.cc
+++ b/chromium/content/browser/loader/sync_resource_handler.cc
@@ -14,6 +14,7 @@
#include "content/public/browser/resource_request_info.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
+#include "net/url_request/redirect_info.h"
namespace content {
@@ -45,23 +46,24 @@ bool SyncResourceHandler::OnUploadProgress(uint64 position, uint64 size) {
}
bool SyncResourceHandler::OnRequestRedirected(
- const GURL& new_url,
+ const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) {
if (rdh_->delegate()) {
rdh_->delegate()->OnRequestRedirected(
- new_url, request(), GetRequestInfo()->GetContext(), response);
+ redirect_info.new_url, request(), GetRequestInfo()->GetContext(),
+ response);
}
DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
// TODO(darin): It would be much better if this could live in WebCore, but
// doing so requires API changes at all levels. Similar code exists in
// WebCore/platform/network/cf/ResourceHandleCFNet.cpp :-(
- if (new_url.GetOrigin() != result_.final_url.GetOrigin()) {
+ if (redirect_info.new_url.GetOrigin() != result_.final_url.GetOrigin()) {
LOG(ERROR) << "Cross origin redirect denied";
return false;
}
- result_.final_url = new_url;
+ result_.final_url = redirect_info.new_url;
total_transfer_size_ += request()->GetTotalReceivedBytes();
return true;
diff --git a/chromium/content/browser/loader/sync_resource_handler.h b/chromium/content/browser/loader/sync_resource_handler.h
index 693b48f3b37..09713e2e504 100644
--- a/chromium/content/browser/loader/sync_resource_handler.h
+++ b/chromium/content/browser/loader/sync_resource_handler.h
@@ -31,24 +31,23 @@ class SyncResourceHandler : public ResourceHandler {
SyncResourceHandler(net::URLRequest* request,
IPC::Message* result_message,
ResourceDispatcherHostImpl* resource_dispatcher_host);
- virtual ~SyncResourceHandler();
+ ~SyncResourceHandler() override;
- virtual bool OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
- virtual bool OnRequestRedirected(const GURL& new_url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
- int* buf_size,
- int min_size) OVERRIDE;
- virtual bool OnReadCompleted(int bytes_read, bool* defer) OVERRIDE;
- virtual void OnResponseCompleted(const net::URLRequestStatus& status,
- const std::string& security_info,
- bool* defer) OVERRIDE;
- virtual void OnDataDownloaded(int bytes_downloaded) OVERRIDE;
+ bool OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
+ bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size,
+ int min_size) override;
+ bool OnReadCompleted(int bytes_read, bool* defer) override;
+ void OnResponseCompleted(const net::URLRequestStatus& status,
+ const std::string& security_info,
+ bool* defer) override;
+ void OnDataDownloaded(int bytes_downloaded) override;
private:
enum { kReadBufSize = 3840 };
diff --git a/chromium/content/browser/loader/temporary_file_stream.cc b/chromium/content/browser/loader/temporary_file_stream.cc
index 0569d490100..e904d88e107 100644
--- a/chromium/content/browser/loader/temporary_file_stream.cc
+++ b/chromium/content/browser/loader/temporary_file_stream.cc
@@ -10,9 +10,9 @@
#include "base/memory/ref_counted.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/file_stream.h"
-#include "webkit/common/blob/shareable_file_reference.h"
+#include "storage/common/blob/shareable_file_reference.h"
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace content {
@@ -43,7 +43,7 @@ void DidCreateTemporaryFile(
scoped_ptr<net::FileStream> file_stream(
new net::FileStream(file_proxy->TakeFile(), task_runner));
- callback.Run(error_code, file_stream.Pass(), deletable_file);
+ callback.Run(error_code, file_stream.Pass(), deletable_file.get());
}
} // namespace
diff --git a/chromium/content/browser/loader/temporary_file_stream.h b/chromium/content/browser/loader/temporary_file_stream.h
index 1cb4bc25be8..280359636d8 100644
--- a/chromium/content/browser/loader/temporary_file_stream.h
+++ b/chromium/content/browser/loader/temporary_file_stream.h
@@ -14,7 +14,7 @@ namespace net {
class FileStream;
}
-namespace webkit_blob {
+namespace storage {
class ShareableFileReference;
}
@@ -22,20 +22,20 @@ namespace content {
typedef base::Callback<void(base::File::Error,
scoped_ptr<net::FileStream>,
- webkit_blob::ShareableFileReference*)>
+ storage::ShareableFileReference*)>
CreateTemporaryFileStreamCallback;
// Creates a temporary file and asynchronously calls |callback| with a
-// net::FileStream and webkit_blob::ShareableFileReference. The file is deleted
-// when the webkit_blob::ShareableFileReference is deleted. Note it is the
-// consumer's responsibility to ensure the webkit_blob::ShareableFileReference
+// net::FileStream and storage::ShareableFileReference. The file is deleted
+// when the storage::ShareableFileReference is deleted. Note it is the
+// consumer's responsibility to ensure the storage::ShareableFileReference
// stays in scope until net::FileStream has finished closing the file. On error,
// |callback| is called with an error in the first parameter.
//
// This function may only be called on the IO thread.
//
// TODO(davidben): Juggling the net::FileStream and
-// webkit_blob::ShareableFileReference lifetimes is a nuisance. The two should
+// storage::ShareableFileReference lifetimes is a nuisance. The two should
// be tied together so the consumer need not deal with it.
CONTENT_EXPORT void CreateTemporaryFileStream(
const CreateTemporaryFileStreamCallback& callback);
diff --git a/chromium/content/browser/loader/temporary_file_stream_unittest.cc b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
index 1903d446b76..854a5ddf5ab 100644
--- a/chromium/content/browser/loader/temporary_file_stream_unittest.cc
+++ b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
@@ -10,18 +10,18 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
+#include "storage/common/blob/shareable_file_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/blob/shareable_file_reference.h"
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace content {
diff --git a/chromium/content/browser/loader/throttling_resource_handler.cc b/chromium/content/browser/loader/throttling_resource_handler.cc
index a302f1da797..1f17d336b6d 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler.cc
@@ -31,22 +31,23 @@ ThrottlingResourceHandler::ThrottlingResourceHandler(
ThrottlingResourceHandler::~ThrottlingResourceHandler() {
}
-bool ThrottlingResourceHandler::OnRequestRedirected(const GURL& new_url,
- ResourceResponse* response,
- bool* defer) {
+bool ThrottlingResourceHandler::OnRequestRedirected(
+ const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) {
DCHECK(!cancelled_by_resource_throttle_);
*defer = false;
while (next_index_ < throttles_.size()) {
int index = next_index_;
- throttles_[index]->WillRedirectRequest(new_url, defer);
+ throttles_[index]->WillRedirectRequest(redirect_info.new_url, defer);
next_index_++;
if (cancelled_by_resource_throttle_)
return false;
if (*defer) {
OnRequestDefered(index);
deferred_stage_ = DEFERRED_REDIRECT;
- deferred_url_ = new_url;
+ deferred_redirect_ = redirect_info;
deferred_response_ = response;
return true; // Do not cancel.
}
@@ -54,7 +55,7 @@ bool ThrottlingResourceHandler::OnRequestRedirected(const GURL& new_url,
next_index_ = 0; // Reset for next time.
- return next_handler_->OnRequestRedirected(new_url, response, defer);
+ return next_handler_->OnRequestRedirected(redirect_info, response, defer);
}
bool ThrottlingResourceHandler::OnWillStart(const GURL& url, bool* defer) {
@@ -87,7 +88,7 @@ bool ThrottlingResourceHandler::OnBeforeNetworkStart(const GURL& url,
*defer = false;
while (next_index_ < throttles_.size()) {
int index = next_index_;
- throttles_[index]->OnBeforeNetworkStart(defer);
+ throttles_[index]->WillStartUsingNetwork(defer);
next_index_++;
if (cancelled_by_resource_throttle_)
return false;
@@ -199,13 +200,13 @@ void ThrottlingResourceHandler::ResumeNetworkStart() {
void ThrottlingResourceHandler::ResumeRedirect() {
DCHECK(!cancelled_by_resource_throttle_);
- GURL new_url = deferred_url_;
- deferred_url_ = GURL();
+ net::RedirectInfo redirect_info = deferred_redirect_;
+ deferred_redirect_ = net::RedirectInfo();
scoped_refptr<ResourceResponse> response;
deferred_response_.swap(response);
bool defer = false;
- if (!OnRequestRedirected(new_url, response.get(), &defer)) {
+ if (!OnRequestRedirected(redirect_info, response.get(), &defer)) {
controller()->Cancel();
} else if (!defer) {
controller()->Resume();
diff --git a/chromium/content/browser/loader/throttling_resource_handler.h b/chromium/content/browser/loader/throttling_resource_handler.h
index fd284dbba2c..0d1287d644e 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.h
+++ b/chromium/content/browser/loader/throttling_resource_handler.h
@@ -9,6 +9,7 @@
#include "base/memory/scoped_vector.h"
#include "content/browser/loader/layered_resource_handler.h"
#include "content/public/browser/resource_controller.h"
+#include "net/url_request/redirect_info.h"
#include "url/gurl.h"
namespace net {
@@ -28,22 +29,21 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
ThrottlingResourceHandler(scoped_ptr<ResourceHandler> next_handler,
net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles);
- virtual ~ThrottlingResourceHandler();
+ ~ThrottlingResourceHandler() override;
// LayeredResourceHandler overrides:
- virtual bool OnRequestRedirected(const GURL& url,
- ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnResponseStarted(ResourceResponse* response,
- bool* defer) OVERRIDE;
- virtual bool OnWillStart(const GURL& url, bool* defer) OVERRIDE;
- virtual bool OnBeforeNetworkStart(const GURL& url, bool* defer) OVERRIDE;
+ bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
+ ResourceResponse* response,
+ bool* defer) override;
+ bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL& url, bool* defer) override;
+ bool OnBeforeNetworkStart(const GURL& url, bool* defer) override;
// ResourceController implementation:
- virtual void Cancel() OVERRIDE;
- virtual void CancelAndIgnore() OVERRIDE;
- virtual void CancelWithError(int error_code) OVERRIDE;
- virtual void Resume() OVERRIDE;
+ void Cancel() override;
+ void CancelAndIgnore() override;
+ void CancelWithError(int error_code) override;
+ void Resume() override;
private:
void ResumeStart();
@@ -68,6 +68,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
size_t next_index_;
GURL deferred_url_;
+ net::RedirectInfo deferred_redirect_;
scoped_refptr<ResourceResponse> deferred_response_;
bool cancelled_by_resource_throttle_;
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index 2db9fdf0fef..376e221d2a6 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -7,15 +7,15 @@
#include "base/logging.h"
#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
#include "content/common/resource_request_body.h"
+#include "net/base/elements_upload_data_stream.h"
#include "net/base/upload_bytes_element_reader.h"
-#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
-using webkit_blob::BlobData;
-using webkit_blob::BlobDataHandle;
-using webkit_blob::BlobStorageContext;
+using storage::BlobData;
+using storage::BlobDataHandle;
+using storage::BlobStorageContext;
namespace content {
namespace {
@@ -30,7 +30,7 @@ class BytesElementReader : public net::UploadBytesElementReader {
DCHECK_EQ(ResourceRequestBody::Element::TYPE_BYTES, element.type());
}
- virtual ~BytesElementReader() {}
+ ~BytesElementReader() override {}
private:
scoped_refptr<ResourceRequestBody> resource_request_body_;
@@ -55,7 +55,7 @@ class FileElementReader : public net::UploadFileElementReader {
DCHECK_EQ(ResourceRequestBody::Element::TYPE_FILE, element.type());
}
- virtual ~FileElementReader() {}
+ ~FileElementReader() override {}
private:
scoped_refptr<ResourceRequestBody> resource_request_body_;
@@ -64,12 +64,11 @@ class FileElementReader : public net::UploadFileElementReader {
};
void ResolveBlobReference(
- ResourceRequestBody* body,
- webkit_blob::BlobStorageContext* blob_context,
+ storage::BlobStorageContext* blob_context,
const ResourceRequestBody::Element& element,
std::vector<const ResourceRequestBody::Element*>* resolved_elements) {
DCHECK(blob_context);
- scoped_ptr<webkit_blob::BlobDataHandle> handle =
+ scoped_ptr<storage::BlobDataHandle> handle =
blob_context->GetBlobDataFromUUID(element.blob_uuid());
DCHECK(handle);
if (!handle)
@@ -85,11 +84,6 @@ void ResolveBlobReference(
DCHECK_NE(BlobData::Item::TYPE_BLOB, item.type());
resolved_elements->push_back(&item);
}
-
- // Ensure the blob and any attached shareable files survive until
- // upload completion. The |body| takes ownership of |handle|.
- const void* key = handle.get();
- body->SetUserData(key, handle.release());
}
} // namespace
@@ -97,14 +91,14 @@ void ResolveBlobReference(
scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
ResourceRequestBody* body,
BlobStorageContext* blob_context,
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
base::TaskRunner* file_task_runner) {
// Resolve all blob elements.
std::vector<const ResourceRequestBody::Element*> resolved_elements;
for (size_t i = 0; i < body->elements()->size(); ++i) {
const ResourceRequestBody::Element& element = (*body->elements())[i];
if (element.type() == ResourceRequestBody::Element::TYPE_BLOB)
- ResolveBlobReference(body, blob_context, element, &resolved_elements);
+ ResolveBlobReference(blob_context, element, &resolved_elements);
else
resolved_elements.push_back(&element);
}
@@ -121,6 +115,9 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
new FileElementReader(body, file_task_runner, element));
break;
case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
+ // If |body| contains any filesystem URLs, the caller should have
+ // supplied a FileSystemContext.
+ DCHECK(file_system_context);
element_readers.push_back(
new content::UploadFileSystemFileElementReader(
file_system_context,
@@ -140,7 +137,8 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
}
return make_scoped_ptr(
- new net::UploadDataStream(element_readers.Pass(), body->identifier()));
+ new net::ElementsUploadDataStream(element_readers.Pass(),
+ body->identifier()));
}
} // namespace content
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.h b/chromium/content/browser/loader/upload_data_stream_builder.h
index 60b6f337c22..228aade7979 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.h
+++ b/chromium/content/browser/loader/upload_data_stream_builder.h
@@ -12,7 +12,7 @@ namespace base {
class TaskRunner;
}
-namespace fileapi {
+namespace storage {
class FileSystemContext;
}
@@ -20,7 +20,7 @@ namespace net {
class UploadDataStream;
}
-namespace webkit_blob {
+namespace storage {
class BlobStorageContext;
}
@@ -32,18 +32,18 @@ class CONTENT_EXPORT UploadDataStreamBuilder {
public:
// Creates a new UploadDataStream from this request body.
//
- // This also resolves any blob references using the given |blob_context|
- // and binds those blob references to the ResourceRequestBody ensuring that
- // the blob data remains valid for the lifetime of the ResourceRequestBody
- // object.
+ // If |body| contains any blob references, the caller is responsible for
+ // making sure them outlive the returned value of UploadDataStream. We do this
+ // by binding the BlobDataHandles of them to ResourceRequestBody in
+ // ResourceDispatcherHostImpl::BeginRequest().
//
// |file_system_context| is used to create a FileStreamReader for files with
// filesystem URLs. |file_task_runner| is used to perform file operations
// when the data gets uploaded.
static scoped_ptr<net::UploadDataStream> Build(
ResourceRequestBody* body,
- webkit_blob::BlobStorageContext* blob_context,
- fileapi::FileSystemContext* file_system_context,
+ storage::BlobStorageContext* blob_context,
+ storage::FileSystemContext* file_system_context,
base::TaskRunner* file_task_runner);
};
diff --git a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
index 67a57e3d9ab..dfd22b25317 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -6,8 +6,8 @@
#include <algorithm>
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
@@ -16,13 +16,13 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-using webkit_blob::BlobData;
-using webkit_blob::BlobDataHandle;
-using webkit_blob::BlobStorageContext;
+using storage::BlobData;
+using storage::BlobDataHandle;
+using storage::BlobStorageContext;
namespace content {
namespace {
@@ -76,15 +76,17 @@ TEST(UploadDataStreamBuilderTest, CreateUploadDataStreamWithoutBlob) {
request_body.get(), NULL, NULL, base::MessageLoopProxy::current().get()));
EXPECT_EQ(kIdentifier, upload->identifier());
- ASSERT_EQ(request_body->elements()->size(), upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(request_body->elements()->size(),
+ upload->GetElementReaders()->size());
const net::UploadBytesElementReader* r1 =
- upload->element_readers()[0]->AsBytesReader();
+ (*upload->GetElementReaders())[0]->AsBytesReader();
ASSERT_TRUE(r1);
EXPECT_EQ(kData, std::string(r1->bytes(), r1->length()));
const net::UploadFileElementReader* r2 =
- upload->element_readers()[1]->AsFileReader();
+ (*upload->GetElementReaders())[1]->AsFileReader();
ASSERT_TRUE(r2);
EXPECT_EQ(kFilePath, r2->path().value());
EXPECT_EQ(kFileOffset, r2->range_offset());
@@ -105,7 +107,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
const std::string blob_id0("id-0");
scoped_refptr<BlobData> blob_data(new BlobData(blob_id0));
scoped_ptr<BlobDataHandle> handle1 =
- blob_storage_context.AddFinishedBlob(blob_data);
+ blob_storage_context.AddFinishedBlob(blob_data.get());
const std::string blob_id1("id-1");
blob_data = new BlobData(blob_id1);
@@ -113,7 +115,7 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
blob_data->AppendFile(
base::FilePath(FILE_PATH_LITERAL("BlobFile.txt")), 0, 20, time1);
scoped_ptr<BlobDataHandle> handle2 =
- blob_storage_context.AddFinishedBlob(blob_data);
+ blob_storage_context.AddFinishedBlob(blob_data.get());
// Setup upload data elements for comparison.
ResourceRequestBody::Element blob_element1, blob_element2;
@@ -150,11 +152,12 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
NULL,
base::MessageLoopProxy::current().get()));
- ASSERT_EQ(2U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(2U, upload->GetElementReaders()->size());
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[0], upload_element1));
+ *(*upload->GetElementReaders())[0], upload_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[1], upload_element2));
+ *(*upload->GetElementReaders())[1], upload_element2));
// Test having only one blob reference that refers to empty blob data.
request_body = new ResourceRequestBody();
@@ -165,7 +168,8 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
&blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
- ASSERT_EQ(0U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(0U, upload->GetElementReaders()->size());
// Test having only one blob reference.
request_body = new ResourceRequestBody();
@@ -176,11 +180,12 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
&blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
- ASSERT_EQ(2U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(2U, upload->GetElementReaders()->size());
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[0], blob_element1));
+ *(*upload->GetElementReaders())[0], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[1], blob_element2));
+ *(*upload->GetElementReaders())[1], blob_element2));
// Test having one blob reference at the beginning.
request_body = new ResourceRequestBody();
@@ -199,15 +204,16 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
&blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
- ASSERT_EQ(4U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(4U, upload->GetElementReaders()->size());
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[0], blob_element1));
+ *(*upload->GetElementReaders())[0], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[1], blob_element2));
+ *(*upload->GetElementReaders())[1], blob_element2));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[2], upload_element1));
+ *(*upload->GetElementReaders())[2], upload_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[3], upload_element2));
+ *(*upload->GetElementReaders())[3], upload_element2));
// Test having one blob reference at the end.
request_body = new ResourceRequestBody();
@@ -226,15 +232,16 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
&blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
- ASSERT_EQ(4U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(4U, upload->GetElementReaders()->size());
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[0], upload_element1));
+ *(*upload->GetElementReaders())[0], upload_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[1], upload_element2));
+ *(*upload->GetElementReaders())[1], upload_element2));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[2], blob_element1));
+ *(*upload->GetElementReaders())[2], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[3], blob_element2));
+ *(*upload->GetElementReaders())[3], blob_element2));
// Test having one blob reference in the middle.
request_body = new ResourceRequestBody();
@@ -253,15 +260,16 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
&blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
- ASSERT_EQ(4U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(4U, upload->GetElementReaders()->size());
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[0], upload_element1));
+ *(*upload->GetElementReaders())[0], upload_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[1], blob_element1));
+ *(*upload->GetElementReaders())[1], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[2], blob_element2));
+ *(*upload->GetElementReaders())[2], blob_element2));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[3], upload_element2));
+ *(*upload->GetElementReaders())[3], upload_element2));
// Test having multiple blob references.
request_body = new ResourceRequestBody();
@@ -282,23 +290,24 @@ TEST(UploadDataStreamBuilderTest, ResolveBlobAndCreateUploadDataStream) {
&blob_storage_context,
NULL,
base::MessageLoopProxy::current().get());
- ASSERT_EQ(8U, upload->element_readers().size());
+ ASSERT_TRUE(upload->GetElementReaders());
+ ASSERT_EQ(8U, upload->GetElementReaders()->size());
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[0], blob_element1));
+ *(*upload->GetElementReaders())[0], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[1], blob_element2));
+ *(*upload->GetElementReaders())[1], blob_element2));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[2], upload_element1));
+ *(*upload->GetElementReaders())[2], upload_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[3], blob_element1));
+ *(*upload->GetElementReaders())[3], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[4], blob_element2));
+ *(*upload->GetElementReaders())[4], blob_element2));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[5], blob_element1));
+ *(*upload->GetElementReaders())[5], blob_element1));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[6], blob_element2));
+ *(*upload->GetElementReaders())[6], blob_element2));
EXPECT_TRUE(AreElementsEqual(
- *upload->element_readers()[7], upload_element2));
+ *(*upload->GetElementReaders())[7], upload_element2));
}
// Clean up for ASAN.
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/mach_broker_mac.h b/chromium/content/browser/mach_broker_mac.h
index dede40068eb..9088ca70265 100644
--- a/chromium/content/browser/mach_broker_mac.h
+++ b/chromium/content/browser/mach_broker_mac.h
@@ -44,10 +44,6 @@ class CONTENT_EXPORT MachBroker : public base::ProcessMetrics::PortProvider,
// and false if otherwise.
static bool ChildSendTaskPortToParent();
- // Returns the Mach port name to use when sending or receiving messages.
- // Does the Right Thing in the browser and in child processes.
- static std::string GetMachPortName();
-
// Returns the global MachBroker.
static MachBroker* GetInstance();
@@ -68,25 +64,25 @@ class CONTENT_EXPORT MachBroker : public base::ProcessMetrics::PortProvider,
void AddPlaceholderForPid(base::ProcessHandle pid);
// Implement |ProcessMetrics::PortProvider|.
- virtual mach_port_t TaskForPid(base::ProcessHandle process) const OVERRIDE;
+ mach_port_t TaskForPid(base::ProcessHandle process) const override;
// Implement |BrowserChildProcessObserver|.
- virtual void BrowserChildProcessHostDisconnected(
- const ChildProcessData& data) OVERRIDE;
- virtual void BrowserChildProcessCrashed(
- const ChildProcessData& data) OVERRIDE;
+ void BrowserChildProcessHostDisconnected(
+ const ChildProcessData& data) override;
+ void BrowserChildProcessCrashed(const ChildProcessData& data) override;
// Implement |NotificationObserver|.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
+
private:
friend class MachBrokerTest;
friend class MachListenerThreadDelegate;
friend struct DefaultSingletonTraits<MachBroker>;
MachBroker();
- virtual ~MachBroker();
+ ~MachBroker() override;
// Updates the mapping for |pid| to include the given |mach_info|. Does
// nothing if PlaceholderForPid() has not already been called for the given
@@ -97,6 +93,9 @@ class CONTENT_EXPORT MachBroker : public base::ProcessMetrics::PortProvider,
// Removes all mappings belonging to |pid| from the broker.
void InvalidatePid(base::ProcessHandle pid);
+ // Returns the Mach port name to use when sending or receiving messages.
+ // Does the Right Thing in the browser and in child processes.
+ static std::string GetMachPortName();
// Callback used to register notifications on the UI thread.
void RegisterNotifications();
diff --git a/chromium/content/browser/mach_broker_mac.mm b/chromium/content/browser/mach_broker_mac.mm
index 1c9e6e55bd8..f2e5f985c32 100644
--- a/chromium/content/browser/mach_broker_mac.mm
+++ b/chromium/content/browser/mach_broker_mac.mm
@@ -85,7 +85,7 @@ class MachListenerThreadDelegate : public base::PlatformThread::Delegate {
}
// Implement |PlatformThread::Delegate|.
- virtual void ThreadMain() OVERRIDE {
+ void ThreadMain() override {
MachBroker_ParentRecvMsg msg;
bzero(&msg, sizeof(msg));
msg.header.msgh_size = sizeof(msg);
@@ -132,7 +132,6 @@ class MachListenerThreadDelegate : public base::PlatformThread::Delegate {
DISALLOW_COPY_AND_ASSIGN(MachListenerThreadDelegate);
};
-// static
bool MachBroker::ChildSendTaskPortToParent() {
// Look up the named MachBroker port that's been registered with the
// bootstrap server.
@@ -168,17 +167,6 @@ bool MachBroker::ChildSendTaskPortToParent() {
return true;
}
-// static
-std::string MachBroker::GetMachPortName() {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- const bool is_child = command_line->HasSwitch(switches::kProcessType);
-
- // In non-browser (child) processes, use the parent's pid.
- const pid_t pid = is_child ? getppid() : getpid();
- return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
-}
-
-// static
MachBroker* MachBroker::GetInstance() {
return Singleton<MachBroker, LeakySingletonTraits<MachBroker> >::get();
}
@@ -286,6 +274,17 @@ void MachBroker::InvalidatePid(base::ProcessHandle pid) {
mach_map_.erase(it);
}
+// static
+std::string MachBroker::GetMachPortName() {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ const bool is_child = command_line->HasSwitch(switches::kProcessType);
+
+ // In non-browser (child) processes, use the parent's pid.
+ const pid_t pid = is_child ? getppid() : getpid();
+ return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
+}
+
void MachBroker::RegisterNotifications() {
registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CLOSED,
NotificationService::AllBrowserContextsAndSources());
diff --git a/chromium/content/browser/manifest/OWNERS b/chromium/content/browser/manifest/OWNERS
new file mode 100644
index 00000000000..2d282460822
--- /dev/null
+++ b/chromium/content/browser/manifest/OWNERS
@@ -0,0 +1 @@
+mlamouri@chromium.org
diff --git a/chromium/content/browser/manifest/manifest_browsertest.cc b/chromium/content/browser/manifest/manifest_browsertest.cc
new file mode 100644
index 00000000000..8eaca0a9445
--- /dev/null
+++ b/chromium/content/browser/manifest/manifest_browsertest.cc
@@ -0,0 +1,202 @@
+// Copyright 2014 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/command_line.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/manifest.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace content {
+
+class ManifestBrowserTest : public ContentBrowserTest {
+ protected:
+ ManifestBrowserTest() {}
+ ~ManifestBrowserTest() override {}
+
+ void GetManifestAndWait() {
+ shell()->web_contents()->GetManifest(
+ base::Bind(&ManifestBrowserTest::OnGetManifest,
+ base::Unretained(this)));
+
+ message_loop_runner_ = new MessageLoopRunner();
+ message_loop_runner_->Run();
+ }
+
+ void OnGetManifest(const Manifest& manifest) {
+ manifest_ = manifest;
+ message_loop_runner_->Quit();
+ }
+
+ const Manifest& manifest() const {
+ return manifest_;
+ }
+
+ private:
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+ Manifest manifest_;
+
+ DISALLOW_COPY_AND_ASSIGN(ManifestBrowserTest);
+};
+
+// If a page has no manifest, requesting a manifest should return the empty
+// manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, NoManifest) {
+ GURL test_url = GetTestUrl("manifest", "no-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+}
+
+// If a page manifest points to a 404 URL, requesting the manifest should return
+// the empty manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, 404Manifest) {
+ GURL test_url = GetTestUrl("manifest", "404-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+}
+
+// If a page has an empty manifest, requesting the manifest should return the
+// empty manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, EmptyManifest) {
+ GURL test_url = GetTestUrl("manifest", "empty-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+}
+
+// If a page's manifest can't be parsed correctly, requesting the manifest
+// should return an empty manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, ParseErrorManifest) {
+ GURL test_url = GetTestUrl("manifest", "parse-error-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+}
+
+// If a page has a manifest that can be fetched and parsed, requesting the
+// manifest should return a properly filled manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DummyManifest) {
+ GURL test_url = GetTestUrl("manifest", "dummy-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ GetManifestAndWait();
+ EXPECT_FALSE(manifest().IsEmpty());
+}
+
+// If a page changes manifest during its life-time, requesting the manifest
+// should return the current manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DynamicManifest) {
+ GURL test_url = GetTestUrl("manifest", "dynamic-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ {
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+ }
+
+ {
+ std::string manifest_url =
+ GetTestUrl("manifest", "dummy-manifest.json").spec();
+ ASSERT_TRUE(content::ExecuteScript(
+ shell()->web_contents(), "setManifestTo('" + manifest_url + "')"));
+
+ GetManifestAndWait();
+ EXPECT_FALSE(manifest().IsEmpty());
+ }
+
+ {
+ std::string manifest_url =
+ GetTestUrl("manifest", "empty-manifest.json").spec();
+ ASSERT_TRUE(content::ExecuteScript(
+ shell()->web_contents(), "setManifestTo('" + manifest_url + "')"));
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+ }
+}
+
+// If a page's manifest lives in a different origin, it should follow the CORS
+// rules and requesting the manifest should return an empty manifest (unless the
+// response contains CORS headers).
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, CORSManifest) {
+ scoped_ptr<net::test_server::EmbeddedTestServer> cors_embedded_test_server(
+ new net::test_server::EmbeddedTestServer);
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(cors_embedded_test_server->InitializeAndWaitUntilReady());
+ ASSERT_NE(embedded_test_server()->port(), cors_embedded_test_server->port());
+
+ GURL test_url =
+ embedded_test_server()->GetURL("/manifest/dynamic-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ std::string manifest_url =
+ cors_embedded_test_server->GetURL("/manifest/dummy-manifest.json").spec();
+ ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
+ "setManifestTo('" + manifest_url + "')"));
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+}
+
+// If a page's manifest is in an unsecure origin while the page is in a secure
+// origin, requesting the manifest should return the empty manifest.
+IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, MixedContentManifest) {
+ scoped_ptr<net::SpawnedTestServer> https_server(new net::SpawnedTestServer(
+ net::SpawnedTestServer::TYPE_HTTPS,
+ net::BaseTestServer::SSLOptions(net::BaseTestServer::SSLOptions::CERT_OK),
+ base::FilePath(FILE_PATH_LITERAL("content/test/data"))));
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ ASSERT_TRUE(https_server->Start());
+
+ GURL test_url =
+ embedded_test_server()->GetURL("/manifest/dynamic-manifest.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+
+ std::string manifest_url =
+ https_server->GetURL("/manifest/dummy-manifest.json").spec();
+ ASSERT_TRUE(content::ExecuteScript(shell()->web_contents(),
+ "setManifestTo('" + manifest_url + "')"));
+
+ GetManifestAndWait();
+ EXPECT_TRUE(manifest().IsEmpty());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/manifest/manifest_manager_host.cc b/chromium/content/browser/manifest/manifest_manager_host.cc
new file mode 100644
index 00000000000..50b3ecade66
--- /dev/null
+++ b/chromium/content/browser/manifest/manifest_manager_host.cc
@@ -0,0 +1,138 @@
+// Copyright 2014 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 "content/browser/manifest/manifest_manager_host.h"
+
+#include "content/common/manifest_manager_messages.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/manifest.h"
+#include "content/public/common/result_codes.h"
+
+namespace content {
+
+namespace {
+
+void KillRenderer(RenderFrameHost* render_frame_host) {
+ base::ProcessHandle process_handle =
+ render_frame_host->GetProcess()->GetHandle();
+ if (process_handle == base::kNullProcessHandle)
+ return;
+ base::KillProcess(process_handle, RESULT_CODE_KILLED_BAD_MESSAGE, false);
+}
+
+} // anonymous namespace
+
+ManifestManagerHost::ManifestManagerHost(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {
+}
+
+ManifestManagerHost::~ManifestManagerHost() {
+}
+
+ManifestManagerHost::CallbackMap* ManifestManagerHost::GetCallbackMapForFrame(
+ RenderFrameHost* render_frame_host) {
+ FrameCallbackMap::iterator it = pending_callbacks_.find(render_frame_host);
+ return it != pending_callbacks_.end() ? it->second : 0;
+}
+
+void ManifestManagerHost::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
+ if (!callbacks)
+ return;
+
+ // Before deleting the callbacks, make sure they are called with a failure
+ // state. Do this in a block so the iterator is destroyed before |callbacks|.
+ {
+ CallbackMap::const_iterator it(callbacks);
+ for (; !it.IsAtEnd(); it.Advance())
+ it.GetCurrentValue()->Run(Manifest());
+ }
+
+ delete callbacks;
+ pending_callbacks_.erase(render_frame_host);
+}
+
+void ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host,
+ const GetManifestCallback& callback) {
+ CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
+ if (!callbacks) {
+ callbacks = new CallbackMap();
+ pending_callbacks_[render_frame_host] = callbacks;
+ }
+
+ int request_id = callbacks->Add(new GetManifestCallback(callback));
+
+ render_frame_host->Send(new ManifestManagerMsg_RequestManifest(
+ render_frame_host->GetRoutingID(), request_id));
+}
+
+bool ManifestManagerHost::OnMessageReceived(
+ const IPC::Message& message, RenderFrameHost* render_frame_host) {
+ bool handled = true;
+
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ManifestManagerHost, message,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse,
+ OnRequestManifestResponse)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void ManifestManagerHost::OnRequestManifestResponse(
+ RenderFrameHost* render_frame_host,
+ int request_id,
+ const Manifest& insecure_manifest) {
+ CallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host);
+ if (!callbacks) {
+ DVLOG(1) << "Unexpected RequestManifestResponse to from renderer. "
+ "Killing renderer.";
+ KillRenderer(render_frame_host);
+ return;
+ }
+
+ GetManifestCallback* callback = callbacks->Lookup(request_id);
+ if (!callback) {
+ DVLOG(1) << "Received a request_id (" << request_id << ") from renderer "
+ "with no associated callback. Killing renderer.";
+ KillRenderer(render_frame_host);
+ return;
+ }
+
+ // When receiving a Manifest, the browser process can't trust that it is
+ // coming from a known and secure source. It must be processed accordingly.
+ Manifest manifest = insecure_manifest;
+ manifest.name = base::NullableString16(
+ manifest.name.string().substr(0, Manifest::kMaxIPCStringLength),
+ manifest.name.is_null());
+ manifest.short_name = base::NullableString16(
+ manifest.short_name.string().substr(0, Manifest::kMaxIPCStringLength),
+ manifest.short_name.is_null());
+ if (!manifest.start_url.is_valid())
+ manifest.start_url = GURL();
+ for (size_t i = 0; i < manifest.icons.size(); ++i) {
+ if (!manifest.icons[i].src.is_valid())
+ manifest.icons[i].src = GURL();
+ manifest.icons[i].type = base::NullableString16(
+ manifest.icons[i].type.string().substr(0,
+ Manifest::kMaxIPCStringLength),
+ manifest.icons[i].type.is_null());
+ }
+ manifest.gcm_sender_id = base::NullableString16(
+ manifest.gcm_sender_id.string().substr(
+ 0, Manifest::kMaxIPCStringLength),
+ manifest.gcm_sender_id.is_null());
+
+ callback->Run(manifest);
+ callbacks->Remove(request_id);
+ if (callbacks->IsEmpty()) {
+ delete callbacks;
+ pending_callbacks_.erase(render_frame_host);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/manifest/manifest_manager_host.h b/chromium/content/browser/manifest/manifest_manager_host.h
new file mode 100644
index 00000000000..aea980f0ba6
--- /dev/null
+++ b/chromium/content/browser/manifest/manifest_manager_host.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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 CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_HOST_H_
+#define CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_HOST_H_
+
+#include "base/callback_forward.h"
+#include "base/id_map.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+
+class RenderFrameHost;
+class WebContents;
+struct Manifest;
+
+// ManifestManagerHost is a helper class that allows callers to get the Manifest
+// associated with a frame. It handles the IPC messaging with the child process.
+// TODO(mlamouri): keep a cached version and a dirty bit here.
+class ManifestManagerHost : public WebContentsObserver {
+ public:
+ explicit ManifestManagerHost(WebContents* web_contents);
+ ~ManifestManagerHost() override;
+
+ typedef base::Callback<void(const Manifest&)> GetManifestCallback;
+
+ // Calls the given callback with the manifest associated with the
+ // given RenderFrameHost. If the frame has no manifest or if getting it failed
+ // the callback will have an empty manifest.
+ void GetManifest(RenderFrameHost*, const GetManifestCallback&);
+
+ // WebContentsObserver
+ bool OnMessageReceived(const IPC::Message&, RenderFrameHost*) override;
+ void RenderFrameDeleted(RenderFrameHost*) override;
+
+ private:
+ typedef IDMap<GetManifestCallback, IDMapOwnPointer> CallbackMap;
+ typedef base::hash_map<RenderFrameHost*, CallbackMap*> FrameCallbackMap;
+
+ void OnRequestManifestResponse(
+ RenderFrameHost*, int request_id, const Manifest&);
+
+ // Returns the CallbackMap associated with the given RenderFrameHost, or null.
+ CallbackMap* GetCallbackMapForFrame(RenderFrameHost*);
+
+ FrameCallbackMap pending_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(ManifestManagerHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_HOST_H_
diff --git a/chromium/content/browser/media/OWNERS b/chromium/content/browser/media/OWNERS
index b1afdbbadb8..2e3d17b05b9 100644
--- a/chromium/content/browser/media/OWNERS
+++ b/chromium/content/browser/media/OWNERS
@@ -1,12 +1,9 @@
-acolwell@chromium.org
dalecurtis@chromium.org
ddorwin@chromium.org
perkj@chromium.org
scherkus@chromium.org
-shadi@chromium.org
tommi@chromium.org
vrk@chromium.org
-wjia@chromium.org
xhwang@chromium.org
xians@chromium.org
@@ -14,3 +11,8 @@ per-file cast_*=hclam@chromium.org
per-file cast_*=hubbe@chromium.org
per-file cast_*=mikhal@chromium.org
per-file cast_*=pwestin@google.com
+
+per-file midi_*=toyoshim@chromium.org
+
+# For changes related to the tab media indicators.
+per-file audio_stream_monitor*=miu@chromium.org
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.cc b/chromium/content/browser/media/android/browser_demuxer_android.cc
index 197895261d7..a0cf7f7d738 100644
--- a/chromium/content/browser/media/android/browser_demuxer_android.cc
+++ b/chromium/content/browser/media/android/browser_demuxer_android.cc
@@ -21,12 +21,12 @@ class BrowserDemuxerAndroid::Internal : public media::DemuxerAndroid {
}
// media::DemuxerAndroid implementation.
- virtual void Initialize(media::DemuxerAndroidClient* client) OVERRIDE {
+ virtual void Initialize(media::DemuxerAndroidClient* client) override {
DCHECK(!ClientIDExists()) << demuxer_client_id_;
demuxer_->AddDemuxerClient(demuxer_client_id_, client);
}
- virtual void RequestDemuxerData(media::DemuxerStream::Type type) OVERRIDE {
+ virtual void RequestDemuxerData(media::DemuxerStream::Type type) override {
DCHECK(ClientIDExists()) << demuxer_client_id_;
demuxer_->Send(new MediaPlayerMsg_ReadFromDemuxer(
demuxer_client_id_, type));
@@ -34,7 +34,7 @@ class BrowserDemuxerAndroid::Internal : public media::DemuxerAndroid {
virtual void RequestDemuxerSeek(
const base::TimeDelta& time_to_seek,
- bool is_browser_seek) OVERRIDE {
+ bool is_browser_seek) override {
DCHECK(ClientIDExists()) << demuxer_client_id_;
demuxer_->Send(new MediaPlayerMsg_DemuxerSeekRequest(
demuxer_client_id_, time_to_seek, is_browser_seek));
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.h b/chromium/content/browser/media/android/browser_demuxer_android.h
index 4ab7c8d84c2..1e7f799e68a 100644
--- a/chromium/content/browser/media/android/browser_demuxer_android.h
+++ b/chromium/content/browser/media/android/browser_demuxer_android.h
@@ -22,8 +22,8 @@ class CONTENT_EXPORT BrowserDemuxerAndroid : public BrowserMessageFilter {
// BrowserMessageFilter overrides.
virtual void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ BrowserThread::ID* thread) override;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
// Returns an uninitialized demuxer implementation associated with
// |demuxer_client_id|, which can be used to communicate with the real demuxer
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.cc b/chromium/content/browser/media/android/browser_media_player_manager.cc
index 5df9016f7b7..b8016b471f4 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -26,6 +26,7 @@
#include "content/public/common/content_switches.h"
#include "media/base/android/media_player_bridge.h"
#include "media/base/android/media_source_player.h"
+#include "media/base/android/media_url_interceptor.h"
#include "media/base/media_switches.h"
using media::MediaPlayerAndroid;
@@ -40,6 +41,7 @@ namespace content {
const int kMediaPlayerThreshold = 1;
static BrowserMediaPlayerManager::Factory g_factory = NULL;
+static media::MediaUrlInterceptor* media_url_interceptor_ = NULL;
// static
void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
@@ -47,6 +49,12 @@ void BrowserMediaPlayerManager::RegisterFactory(Factory factory) {
}
// static
+void BrowserMediaPlayerManager::RegisterMediaUrlInterceptor(
+ media::MediaUrlInterceptor* media_url_interceptor) {
+ media_url_interceptor_ = media_url_interceptor;
+}
+
+// static
BrowserMediaPlayerManager* BrowserMediaPlayerManager::Create(
RenderFrameHost* rfh) {
if (g_factory)
@@ -75,9 +83,8 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
manager,
base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesReleased,
- weak_ptr_factory_.GetWeakPtr()),
- media_player_params.frame_url);
+ media_player_params.frame_url,
+ media_player_params.allow_credentials);
BrowserMediaPlayerManager* browser_media_player_manager =
static_cast<BrowserMediaPlayerManager*>(manager);
ContentViewCoreImpl* content_view_core_impl =
@@ -103,8 +110,6 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
manager,
base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesRequested,
weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&BrowserMediaPlayerManager::OnMediaResourcesReleased,
- weak_ptr_factory_.GetWeakPtr()),
demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
media_player_params.frame_url);
}
@@ -164,15 +169,12 @@ void BrowserMediaPlayerManager::FullscreenPlayerSeek(int msec) {
}
void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableOverlayFullscreenVideoSubtitle)) {
- if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
- delegate->ToggleFullscreenModeForTab(web_contents_, false);
- if (RenderWidgetHostViewAndroid* view_android =
- static_cast<RenderWidgetHostViewAndroid*>(
- web_contents_->GetRenderWidgetHostView())) {
- view_android->SetOverlayVideoMode(false);
- }
+ if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
+ delegate->ToggleFullscreenModeForTab(web_contents_, false);
+ if (RenderWidgetHostViewAndroid* view_android =
+ static_cast<RenderWidgetHostViewAndroid*>(
+ web_contents_->GetRenderWidgetHostView())) {
+ view_android->SetOverlayVideoMode(false);
}
Send(
@@ -188,10 +190,12 @@ void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
player->SetVideoSurface(gfx::ScopedJavaSurface());
}
-void BrowserMediaPlayerManager::OnTimeUpdate(int player_id,
- base::TimeDelta current_time) {
- Send(
- new MediaPlayerMsg_MediaTimeUpdate(RoutingID(), player_id, current_time));
+void BrowserMediaPlayerManager::OnTimeUpdate(
+ int player_id,
+ base::TimeDelta current_timestamp,
+ base::TimeTicks current_time_ticks) {
+ Send(new MediaPlayerMsg_MediaTimeUpdate(
+ RoutingID(), player_id, current_timestamp, current_time_ticks));
}
void BrowserMediaPlayerManager::SetVideoSurface(
@@ -206,17 +210,11 @@ void BrowserMediaPlayerManager::SetVideoSurface(
return;
Send(new MediaPlayerMsg_DidEnterFullscreen(RoutingID(), player->player_id()));
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableOverlayFullscreenVideoSubtitle)) {
- return;
- }
if (RenderWidgetHostViewAndroid* view_android =
static_cast<RenderWidgetHostViewAndroid*>(
web_contents_->GetRenderWidgetHostView())) {
view_android->SetOverlayVideoMode(true);
}
- if (WebContentsDelegate* delegate = web_contents_->GetDelegate())
- delegate->ToggleFullscreenModeForTab(web_contents_, true);
}
void BrowserMediaPlayerManager::OnMediaMetadataChanged(
@@ -254,8 +252,13 @@ void BrowserMediaPlayerManager::OnSeekRequest(
Send(new MediaPlayerMsg_SeekRequest(RoutingID(), player_id, time_to_seek));
}
-void BrowserMediaPlayerManager::PauseVideo() {
- Send(new MediaPlayerMsg_PauseVideo(RoutingID()));
+void BrowserMediaPlayerManager::ReleaseAllMediaPlayers() {
+ for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
+ it != players_.end(); ++it) {
+ if ((*it)->player_id() == fullscreen_player_id_)
+ fullscreen_player_is_released_ = true;
+ (*it)->Release();
+ }
}
void BrowserMediaPlayerManager::OnSeekComplete(
@@ -284,7 +287,7 @@ BrowserMediaPlayerManager::GetMediaResourceGetter() {
RenderProcessHost* host = web_contents()->GetRenderProcessHost();
BrowserContext* context = host->GetBrowserContext();
StoragePartition* partition = host->GetStoragePartition();
- fileapi::FileSystemContext* file_system_context =
+ storage::FileSystemContext* file_system_context =
partition ? partition->GetFileSystemContext() : NULL;
// Eventually this needs to be fixed to pass the correct frame rather
// than just using the main frame.
@@ -297,6 +300,11 @@ BrowserMediaPlayerManager::GetMediaResourceGetter() {
return media_resource_getter_.get();
}
+media::MediaUrlInterceptor*
+BrowserMediaPlayerManager::GetMediaUrlInterceptor() {
+ return media_url_interceptor_;
+}
+
MediaPlayerAndroid* BrowserMediaPlayerManager::GetFullscreenPlayer() {
return GetPlayer(fullscreen_player_id_);
}
@@ -435,11 +443,12 @@ void BrowserMediaPlayerManager::OnInitialize(
RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
web_contents()->GetRenderProcessHost());
- MediaPlayerAndroid* player = CreateMediaPlayer(
- media_player_params,
+ MediaPlayerAndroid* player =
+ CreateMediaPlayer(media_player_params,
- host->GetBrowserContext()->IsOffTheRecord(), this,
- host->browser_demuxer_android());
+ host->GetBrowserContext()->IsOffTheRecord(),
+ this,
+ host->browser_demuxer_android().get());
if (!player)
return;
@@ -487,7 +496,7 @@ void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
void BrowserMediaPlayerManager::OnReleaseResources(int player_id) {
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
- player->Release();
+ ReleasePlayer(player);
if (player_id == fullscreen_player_id_)
fullscreen_player_is_released_ = true;
}
@@ -498,6 +507,15 @@ void BrowserMediaPlayerManager::OnDestroyPlayer(int player_id) {
fullscreen_player_id_ = -1;
}
+void BrowserMediaPlayerManager::OnRequestRemotePlayback(int /* player_id */) {
+ // Does nothing if we don't have a remote player
+}
+
+void BrowserMediaPlayerManager::OnRequestRemotePlaybackControl(
+ int /* player_id */) {
+ // Does nothing if we don't have a remote player
+}
+
void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
DCHECK(!GetPlayer(player->player_id()));
players_.push_back(player);
@@ -506,8 +524,8 @@ void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
it != players_.end(); ++it) {
- MediaPlayerAndroid* player = *it;
- if (player->player_id() == player_id) {
+ if ((*it)->player_id() == player_id) {
+ ReleaseMediaResources(player_id);
players_.erase(it);
break;
}
@@ -521,6 +539,7 @@ scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
it != players_.end(); ++it) {
if ((*it)->player_id() == player_id) {
previous_player = *it;
+ ReleaseMediaResources(player_id);
players_.weak_erase(it);
players_.push_back(player);
break;
@@ -539,7 +558,7 @@ bool BrowserMediaPlayerManager::Send(IPC::Message* msg) {
void BrowserMediaPlayerManager::ReleaseFullscreenPlayer(
MediaPlayerAndroid* player) {
- player->Release();
+ ReleasePlayer(player);
}
void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
@@ -563,21 +582,23 @@ void BrowserMediaPlayerManager::OnMediaResourcesRequested(int player_id) {
for (it = players_.begin(); it != players_.end(); ++it) {
if ((*it)->IsPlayerReady() && !(*it)->IsPlaying() &&
fullscreen_player_id_ != (*it)->player_id()) {
- (*it)->Release();
+ ReleasePlayer(*it);
Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(),
(*it)->player_id()));
}
}
}
-void BrowserMediaPlayerManager::OnMediaResourcesReleased(int player_id) {
+void BrowserMediaPlayerManager::ReleaseMediaResources(int player_id) {
#if defined(VIDEO_HOLE)
- MediaPlayerAndroid* player = GetPlayer(player_id);
- if (player && player->IsSurfaceInUse())
- return;
if (external_video_surface_container_)
external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
#endif // defined(VIDEO_HOLE)
}
+void BrowserMediaPlayerManager::ReleasePlayer(MediaPlayerAndroid* player) {
+ player->Release();
+ ReleaseMediaResources(player->player_id());
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.h b/chromium/content/browser/media/android/browser_media_player_manager.h
index 4c533885bf6..36506cd8241 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -16,6 +16,7 @@
#include "ipc/ipc_message.h"
#include "media/base/android/media_player_android.h"
#include "media/base/android/media_player_manager.h"
+#include "media/base/android/media_url_interceptor.h"
#include "ui/gfx/rect_f.h"
#include "url/gurl.h"
@@ -44,6 +45,10 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
typedef BrowserMediaPlayerManager* (*Factory)(RenderFrameHost*);
static void RegisterFactory(Factory factory);
+ // Permits embedders to handle custom urls.
+ static void RegisterMediaUrlInterceptor(
+ media::MediaUrlInterceptor* media_url_interceptor);
+
// Returns a new instance using the registered factory if available.
static BrowserMediaPlayerManager* Create(RenderFrameHost* rfh);
@@ -62,33 +67,36 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// Any actual seek started by renderer will be handled by browser in OnSeek().
void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
- // Pauses all video players manages by this class.
- void PauseVideo();
+ // Stops and releases every media managed by this class.
+ void ReleaseAllMediaPlayers();
// media::MediaPlayerManager overrides.
virtual void OnTimeUpdate(
- int player_id, base::TimeDelta current_time) OVERRIDE;
+ int player_id,
+ base::TimeDelta current_timestamp,
+ base::TimeTicks current_time_ticks) override;
virtual void OnMediaMetadataChanged(
int player_id,
base::TimeDelta duration,
int width,
int height,
- bool success) OVERRIDE;
- virtual void OnPlaybackComplete(int player_id) OVERRIDE;
- virtual void OnMediaInterrupted(int player_id) OVERRIDE;
- virtual void OnBufferingUpdate(int player_id, int percentage) OVERRIDE;
+ bool success) override;
+ virtual void OnPlaybackComplete(int player_id) override;
+ virtual void OnMediaInterrupted(int player_id) override;
+ virtual void OnBufferingUpdate(int player_id, int percentage) override;
virtual void OnSeekComplete(
int player_id,
- const base::TimeDelta& current_time) OVERRIDE;
- virtual void OnError(int player_id, int error) OVERRIDE;
+ const base::TimeDelta& current_time) override;
+ virtual void OnError(int player_id, int error) override;
virtual void OnVideoSizeChanged(
- int player_id, int width, int height) OVERRIDE;
- virtual media::MediaResourceGetter* GetMediaResourceGetter() OVERRIDE;
- virtual media::MediaPlayerAndroid* GetFullscreenPlayer() OVERRIDE;
- virtual media::MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE;
- virtual void RequestFullScreen(int player_id) OVERRIDE;
+ int player_id, int width, int height) override;
+ virtual media::MediaResourceGetter* GetMediaResourceGetter() override;
+ virtual media::MediaUrlInterceptor* GetMediaUrlInterceptor() override;
+ virtual media::MediaPlayerAndroid* GetFullscreenPlayer() override;
+ virtual media::MediaPlayerAndroid* GetPlayer(int player_id) override;
+ virtual void RequestFullScreen(int player_id) override;
#if defined(VIDEO_HOLE)
- virtual bool ShouldUseVideoOverlayForEmbeddedEncryptedVideo() OVERRIDE;
+ virtual bool ShouldUseVideoOverlayForEmbeddedEncryptedVideo() override;
void AttachExternalVideoSurface(int player_id, jobject surface);
void DetachExternalVideoSurface(int player_id);
@@ -107,6 +115,8 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
virtual void OnSetPoster(int player_id, const GURL& poster);
virtual void OnReleaseResources(int player_id);
virtual void OnDestroyPlayer(int player_id);
+ virtual void OnRequestRemotePlayback(int player_id);
+ virtual void OnRequestRemotePlaybackControl(int player_id);
virtual void ReleaseFullscreenPlayer(media::MediaPlayerAndroid* player);
#if defined(VIDEO_HOLE)
void OnNotifyExternalSurface(
@@ -152,9 +162,11 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// constrained by hardware and memory limits.
virtual void OnMediaResourcesRequested(int player_id);
- // Similar to the above call, MediaPlayerAndroid must call this method when
- // releasing all the decoding resources.
- virtual void OnMediaResourcesReleased(int player_id);
+ // Called when a player releases all decoding resources.
+ void ReleaseMediaResources(int player_id);
+
+ // Releases the player. However, don't remove it from |players_|.
+ void ReleasePlayer(media::MediaPlayerAndroid* player);
#if defined(VIDEO_HOLE)
void OnRequestExternalSurface(int player_id, const gfx::RectF& rect);
diff --git a/chromium/content/browser/media/android/media_resource_getter_impl.cc b/chromium/content/browser/media/android/media_resource_getter_impl.cc
index bcf293d9252..686e01c331c 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -12,19 +12,24 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/browser/resource_context_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "jni/MediaResourceGetter_jni.h"
+#include "media/base/android/media_url_interceptor.h"
+#include "net/base/auth.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
+#include "net/http/http_auth.h"
+#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "url/gurl.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
using base::android::ConvertUTF8ToJavaString;
using base::android::ScopedJavaLocalRef;
@@ -40,15 +45,27 @@ static void ReturnResultOnUIThread(
static void RequestPlatformPathFromBlobURL(
const GURL& url,
- BrowserContext* browser_context,
+ ResourceContext* resource_context,
const base::Callback<void(const std::string&)>& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ChromeBlobStorageContext* context =
- ChromeBlobStorageContext::GetFor(browser_context);
- scoped_ptr<webkit_blob::BlobDataHandle> handle =
- context->context()->GetBlobDataFromPublicURL(url);
- const std::vector<webkit_blob::BlobData::Item> items =
- handle->data()->items();
+ ChromeBlobStorageContext* blob_storage_context =
+ GetChromeBlobStorageContextForResourceContext(resource_context);
+
+ scoped_ptr<storage::BlobDataHandle> handle =
+ blob_storage_context->context()->GetBlobDataFromPublicURL(url);
+ if (!handle) {
+ // There are plenty of cases where handle can be empty. The most trivial is
+ // when JS has aready revoked the given blob URL via URL.revokeObjectURL
+ ReturnResultOnUIThread(callback, std::string());
+ return;
+ }
+ storage::BlobData* data = handle->data();
+ if (!data) {
+ ReturnResultOnUIThread(callback, std::string());
+ NOTREACHED();
+ return;
+ }
+ const std::vector<storage::BlobData::Item> items = data->items();
// TODO(qinmin): handle the case when the blob data is not a single file.
DLOG_IF(WARNING, items.size() != 1u)
@@ -59,7 +76,7 @@ static void RequestPlatformPathFromBlobURL(
static void RequestPlaformPathFromFileSystemURL(
const GURL& url,
int render_process_id,
- scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
const base::Callback<void(const std::string&)>& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::FilePath platform_path;
@@ -75,7 +92,21 @@ static void RequestPlaformPathFromFileSystemURL(
ReturnResultOnUIThread(callback, std::string());
}
-// Get the metadata from a media URL. When finished, a task is posted to the UI
+// Posts a task to the UI thread to run the callback function.
+static void PostMediaMetadataCallbackTask(
+ const media::MediaResourceGetter::ExtractMediaMetadataCB& callback,
+ JNIEnv* env, ScopedJavaLocalRef<jobject>& j_metadata) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, base::TimeDelta::FromMilliseconds(
+ Java_MediaMetadata_getDurationInMilliseconds(
+ env, j_metadata.obj())),
+ Java_MediaMetadata_getWidth(env, j_metadata.obj()),
+ Java_MediaMetadata_getHeight(env, j_metadata.obj()),
+ Java_MediaMetadata_isSuccess(env, j_metadata.obj())));
+}
+
+// Gets the metadata from a media URL. When finished, a task is posted to the UI
// thread to run the callback function.
static void GetMediaMetadata(
const std::string& url, const std::string& cookies,
@@ -94,40 +125,52 @@ static void GetMediaMetadata(
j_url_string.obj(),
j_cookies.obj(),
j_user_agent.obj());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(callback, base::TimeDelta::FromMilliseconds(
- Java_MediaMetadata_getDurationInMilliseconds(
- env, j_metadata.obj())),
- Java_MediaMetadata_getWidth(env, j_metadata.obj()),
- Java_MediaMetadata_getHeight(env, j_metadata.obj()),
- Java_MediaMetadata_isSuccess(env, j_metadata.obj())));
+
+ PostMediaMetadataCallbackTask(callback, env, j_metadata);
+}
+
+// Gets the metadata from a file descriptor. When finished, a task is posted to
+// the UI thread to run the callback function.
+static void GetMediaMetadataFromFd(
+ const int fd, const int64 offset, const int64 size,
+ const media::MediaResourceGetter::ExtractMediaMetadataCB& callback) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> j_metadata =
+ Java_MediaResourceGetter_extractMediaMetadataFromFd(
+ env, fd, offset, size);
+
+ PostMediaMetadataCallbackTask(callback, env, j_metadata);
}
-// The task object that retrieves cookie on the IO thread.
+// The task object that retrieves media resources on the IO thread.
// TODO(qinmin): refactor this class to make the code reusable by others as
// there are lots of duplicated functionalities elsewhere.
-class CookieGetterTask
- : public base::RefCountedThreadSafe<CookieGetterTask> {
+// http://crbug.com/395762.
+class MediaResourceGetterTask
+ : public base::RefCountedThreadSafe<MediaResourceGetterTask> {
public:
- CookieGetterTask(BrowserContext* browser_context,
- int render_process_id, int render_frame_id);
+ MediaResourceGetterTask(BrowserContext* browser_context,
+ int render_process_id, int render_frame_id);
- // Called by CookieGetterImpl to start getting cookies for a URL.
+ // Called by MediaResourceGetterImpl to start getting auth credentials.
+ net::AuthCredentials RequestAuthCredentials(const GURL& url) const;
+
+ // Called by MediaResourceGetterImpl to start getting cookies for a URL.
void RequestCookies(
const GURL& url, const GURL& first_party_for_cookies,
const media::MediaResourceGetter::GetCookieCB& callback);
private:
- friend class base::RefCountedThreadSafe<CookieGetterTask>;
- virtual ~CookieGetterTask();
+ friend class base::RefCountedThreadSafe<MediaResourceGetterTask>;
+ virtual ~MediaResourceGetterTask();
void CheckPolicyForCookies(
const GURL& url, const GURL& first_party_for_cookies,
const media::MediaResourceGetter::GetCookieCB& callback,
const net::CookieList& cookie_list);
- // Context getter used to get the CookieStore.
+ // Context getter used to get the CookieStore and auth cache.
net::URLRequestContextGetter* context_getter_;
// Resource context for checking cookie policies.
@@ -139,10 +182,10 @@ class CookieGetterTask
// Render frame id, used to check tab specific cookie policy.
int render_frame_id_;
- DISALLOW_COPY_AND_ASSIGN(CookieGetterTask);
+ DISALLOW_COPY_AND_ASSIGN(MediaResourceGetterTask);
};
-CookieGetterTask::CookieGetterTask(
+MediaResourceGetterTask::MediaResourceGetterTask(
BrowserContext* browser_context, int render_process_id, int render_frame_id)
: context_getter_(browser_context->GetRequestContext()),
resource_context_(browser_context->GetResourceContext()),
@@ -150,9 +193,32 @@ CookieGetterTask::CookieGetterTask(
render_frame_id_(render_frame_id) {
}
-CookieGetterTask::~CookieGetterTask() {}
+MediaResourceGetterTask::~MediaResourceGetterTask() {}
-void CookieGetterTask::RequestCookies(
+net::AuthCredentials MediaResourceGetterTask::RequestAuthCredentials(
+ const GURL& url) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ net::HttpTransactionFactory* factory =
+ context_getter_->GetURLRequestContext()->http_transaction_factory();
+ if (!factory)
+ return net::AuthCredentials();
+
+ net::HttpAuthCache* auth_cache =
+ factory->GetSession()->http_auth_cache();
+ if (!auth_cache)
+ return net::AuthCredentials();
+
+ net::HttpAuthCache::Entry* entry =
+ auth_cache->LookupByPath(url.GetOrigin(), url.path());
+
+ // TODO(qinmin): handle other auth schemes. See http://crbug.com/395219.
+ if (entry && entry->scheme() == net::HttpAuth::AUTH_SCHEME_BASIC)
+ return entry->credentials();
+ else
+ return net::AuthCredentials();
+}
+
+void MediaResourceGetterTask::RequestCookies(
const GURL& url, const GURL& first_party_for_cookies,
const media::MediaResourceGetter::GetCookieCB& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -173,14 +239,14 @@ void CookieGetterTask::RequestCookies(
net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
if (cookie_monster) {
cookie_monster->GetAllCookiesForURLAsync(url, base::Bind(
- &CookieGetterTask::CheckPolicyForCookies, this,
+ &MediaResourceGetterTask::CheckPolicyForCookies, this,
url, first_party_for_cookies, callback));
} else {
callback.Run(std::string());
}
}
-void CookieGetterTask::CheckPolicyForCookies(
+void MediaResourceGetterTask::CheckPolicyForCookies(
const GURL& url, const GURL& first_party_for_cookies,
const media::MediaResourceGetter::GetCookieCB& callback,
const net::CookieList& cookie_list) {
@@ -190,8 +256,9 @@ void CookieGetterTask::CheckPolicyForCookies(
resource_context_, render_process_id_, render_frame_id_)) {
net::CookieStore* cookie_store =
context_getter_->GetURLRequestContext()->cookie_store();
- cookie_store->GetCookiesWithOptionsAsync(
- url, net::CookieOptions(), callback);
+ net::CookieOptions options;
+ options.set_include_httponly();
+ cookie_store->GetCookiesWithOptionsAsync(url, options, callback);
} else {
callback.Run(std::string());
}
@@ -199,22 +266,37 @@ void CookieGetterTask::CheckPolicyForCookies(
MediaResourceGetterImpl::MediaResourceGetterImpl(
BrowserContext* browser_context,
- fileapi::FileSystemContext* file_system_context,
+ storage::FileSystemContext* file_system_context,
int render_process_id,
int render_frame_id)
: browser_context_(browser_context),
file_system_context_(file_system_context),
render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
- weak_factory_(this) {}
+ weak_factory_(this) {
+}
MediaResourceGetterImpl::~MediaResourceGetterImpl() {}
+void MediaResourceGetterImpl::GetAuthCredentials(
+ const GURL& url, const GetAuthCredentialsCB& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ scoped_refptr<MediaResourceGetterTask> task = new MediaResourceGetterTask(
+ browser_context_, 0, 0);
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&MediaResourceGetterTask::RequestAuthCredentials, task, url),
+ base::Bind(&MediaResourceGetterImpl::GetAuthCredentialsCallback,
+ weak_factory_.GetWeakPtr(), callback));
+}
+
void MediaResourceGetterImpl::GetCookies(
const GURL& url, const GURL& first_party_for_cookies,
const GetCookieCB& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_refptr<CookieGetterTask> task = new CookieGetterTask(
+ scoped_refptr<MediaResourceGetterTask> task = new MediaResourceGetterTask(
browser_context_, render_process_id_, render_frame_id_);
GetCookieCB cb = base::Bind(&MediaResourceGetterImpl::GetCookiesCallback,
@@ -223,11 +305,18 @@ void MediaResourceGetterImpl::GetCookies(
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&CookieGetterTask::RequestCookies,
+ base::Bind(&MediaResourceGetterTask::RequestCookies,
task, url, first_party_for_cookies,
base::Bind(&ReturnResultOnUIThread, cb)));
}
+void MediaResourceGetterImpl::GetAuthCredentialsCallback(
+ const GetAuthCredentialsCB& callback,
+ const net::AuthCredentials& credentials) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ callback.Run(credentials.username(), credentials.password());
+}
+
void MediaResourceGetterImpl::GetCookiesCallback(
const GetCookieCB& callback, const std::string& cookies) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -248,11 +337,12 @@ void MediaResourceGetterImpl::GetPlatformPathFromURL(
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(&RequestPlatformPathFromBlobURL, url, browser_context_, cb));
+ base::Bind(&RequestPlatformPathFromBlobURL, url,
+ browser_context_->GetResourceContext(), cb));
return;
}
- scoped_refptr<fileapi::FileSystemContext> context(file_system_context_);
+ scoped_refptr<storage::FileSystemContext> context(file_system_context_);
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
@@ -276,6 +366,16 @@ void MediaResourceGetterImpl::ExtractMediaMetadata(
base::Bind(&GetMediaMetadata, url, cookies, user_agent, callback));
}
+void MediaResourceGetterImpl::ExtractMediaMetadata(
+ const int fd, const int64 offset, const int64 size,
+ const ExtractMediaMetadataCB& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
+ pool->PostWorkerTask(
+ FROM_HERE,
+ base::Bind(&GetMediaMetadataFromFd, fd, offset, size, callback));
+}
+
// static
bool MediaResourceGetterImpl::RegisterMediaResourceGetter(JNIEnv* env) {
return RegisterNativesImpl(env);
diff --git a/chromium/content/browser/media/android/media_resource_getter_impl.h b/chromium/content/browser/media/android/media_resource_getter_impl.h
index c1ed4b97b36..4f0d2e81af8 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.h
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.h
@@ -12,9 +12,11 @@
#include "base/memory/weak_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "media/base/android/media_resource_getter.h"
+#include "media/base/android/media_url_interceptor.h"
+#include "net/base/auth.h"
#include "net/cookies/canonical_cookie.h"
-namespace fileapi {
+namespace storage {
class FileSystemContext;
}
@@ -35,26 +37,42 @@ class MediaResourceGetterImpl : public media::MediaResourceGetter {
// |render_process_id| are passed to retrieve the CookieStore.
// |file_system_context| are used to get the platform path.
MediaResourceGetterImpl(BrowserContext* browser_context,
- fileapi::FileSystemContext* file_system_context,
- int render_process_id, int render_frame_id);
+ storage::FileSystemContext* file_system_context,
+ int render_process_id,
+ int render_frame_id);
virtual ~MediaResourceGetterImpl();
// media::MediaResourceGetter implementation.
// Must be called on the UI thread.
- virtual void GetCookies(const GURL& url,
- const GURL& first_party_for_cookies,
- const GetCookieCB& callback) OVERRIDE;
+ virtual void GetAuthCredentials(
+ const GURL& url,
+ const GetAuthCredentialsCB& callback) override;
+ virtual void GetCookies(
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ const GetCookieCB& callback) override;
virtual void GetPlatformPathFromURL(
const GURL& url,
- const GetPlatformPathCB& callback) OVERRIDE;
+ const GetPlatformPathCB& callback) override;
virtual void ExtractMediaMetadata(
- const std::string& url, const std::string& cookies,
+ const std::string& url,
+ const std::string& cookies,
const std::string& user_agent,
- const ExtractMediaMetadataCB& callback) OVERRIDE;
+ const ExtractMediaMetadataCB& callback) override;
+ virtual void ExtractMediaMetadata(
+ const int fd,
+ const int64 offset,
+ const int64 size,
+ const ExtractMediaMetadataCB& callback) override;
static bool RegisterMediaResourceGetter(JNIEnv* env);
private:
+ // Called when GetAuthCredentials() finishes.
+ void GetAuthCredentialsCallback(
+ const GetAuthCredentialsCB& callback,
+ const net::AuthCredentials& credentials);
+
// Called when GetCookies() finishes.
void GetCookiesCallback(
const GetCookieCB& callback, const std::string& cookies);
@@ -67,7 +85,7 @@ class MediaResourceGetterImpl : public media::MediaResourceGetter {
BrowserContext* browser_context_;
// FileSystemContext to be used on FILE thread.
- fileapi::FileSystemContext* file_system_context_;
+ storage::FileSystemContext* file_system_context_;
// Render process id, used to check whether the process can access cookies.
int render_process_id_;
diff --git a/chromium/content/browser/media/audio_stream_monitor.cc b/chromium/content/browser/media/audio_stream_monitor.cc
new file mode 100644
index 00000000000..1d2f76f7f2c
--- /dev/null
+++ b/chromium/content/browser/media/audio_stream_monitor.cc
@@ -0,0 +1,162 @@
+// Copyright 2014 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 "content/browser/media/audio_stream_monitor.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/invalidate_type.h"
+#include "content/public/browser/render_frame_host.h"
+
+namespace content {
+
+namespace {
+
+AudioStreamMonitor* AudioStreamMonitorFromRenderFrame(int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ WebContentsImpl* const web_contents =
+ static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(
+ RenderFrameHost::FromID(render_process_id, render_frame_id)));
+ return web_contents ? web_contents->audio_stream_monitor() : NULL;
+}
+
+} // namespace
+
+AudioStreamMonitor::AudioStreamMonitor(WebContents* contents)
+ : web_contents_(contents),
+ clock_(&default_tick_clock_),
+ was_recently_audible_(false) {
+ DCHECK(web_contents_);
+}
+
+AudioStreamMonitor::~AudioStreamMonitor() {}
+
+bool AudioStreamMonitor::WasRecentlyAudible() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return was_recently_audible_;
+}
+
+// static
+void AudioStreamMonitor::StartMonitoringStream(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const ReadPowerAndClipCallback& read_power_callback) {
+ if (!monitoring_available())
+ return;
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&StartMonitoringHelper,
+ render_process_id,
+ render_frame_id,
+ stream_id,
+ read_power_callback));
+}
+
+// static
+void AudioStreamMonitor::StopMonitoringStream(int render_process_id,
+ int render_frame_id,
+ int stream_id) {
+ if (!monitoring_available())
+ return;
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&StopMonitoringHelper,
+ render_process_id,
+ render_frame_id,
+ stream_id));
+}
+
+// static
+void AudioStreamMonitor::StartMonitoringHelper(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const ReadPowerAndClipCallback& read_power_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ AudioStreamMonitor* const monitor =
+ AudioStreamMonitorFromRenderFrame(render_process_id, render_frame_id);
+ if (monitor) {
+ monitor->StartMonitoringStreamOnUIThread(
+ render_process_id, stream_id, read_power_callback);
+ }
+}
+
+// static
+void AudioStreamMonitor::StopMonitoringHelper(int render_process_id,
+ int render_frame_id,
+ int stream_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ AudioStreamMonitor* const monitor =
+ AudioStreamMonitorFromRenderFrame(render_process_id, render_frame_id);
+ if (monitor)
+ monitor->StopMonitoringStreamOnUIThread(render_process_id, stream_id);
+}
+
+void AudioStreamMonitor::StartMonitoringStreamOnUIThread(
+ int render_process_id,
+ int stream_id,
+ const ReadPowerAndClipCallback& read_power_callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!read_power_callback.is_null());
+ poll_callbacks_[StreamID(render_process_id, stream_id)] = read_power_callback;
+ if (!poll_timer_.IsRunning()) {
+ poll_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond,
+ base::Bind(&AudioStreamMonitor::Poll, base::Unretained(this)));
+ }
+}
+
+void AudioStreamMonitor::StopMonitoringStreamOnUIThread(int render_process_id,
+ int stream_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ poll_callbacks_.erase(StreamID(render_process_id, stream_id));
+ if (poll_callbacks_.empty())
+ poll_timer_.Stop();
+}
+
+void AudioStreamMonitor::Poll() {
+ for (StreamPollCallbackMap::const_iterator it = poll_callbacks_.begin();
+ it != poll_callbacks_.end();
+ ++it) {
+ // TODO(miu): A new UI for delivering specific power level and clipping
+ // information is still in the works. For now, we throw away all
+ // information except for "is it audible?"
+ const float power_dbfs = it->second.Run().first;
+ const float kSilenceThresholdDBFS = -72.24719896f;
+ if (power_dbfs >= kSilenceThresholdDBFS) {
+ last_blurt_time_ = clock_->NowTicks();
+ MaybeToggle();
+ break; // No need to poll remaining streams.
+ }
+ }
+}
+
+void AudioStreamMonitor::MaybeToggle() {
+ const bool indicator_was_on = was_recently_audible_;
+ const base::TimeTicks off_time =
+ last_blurt_time_ + base::TimeDelta::FromMilliseconds(kHoldOnMilliseconds);
+ const base::TimeTicks now = clock_->NowTicks();
+ const bool should_indicator_be_on = now < off_time;
+
+ if (should_indicator_be_on != indicator_was_on) {
+ was_recently_audible_ = should_indicator_be_on;
+ web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ }
+
+ if (!should_indicator_be_on) {
+ off_timer_.Stop();
+ } else if (!off_timer_.IsRunning()) {
+ off_timer_.Start(
+ FROM_HERE,
+ off_time - now,
+ base::Bind(&AudioStreamMonitor::MaybeToggle, base::Unretained(this)));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/audio_stream_monitor.h b/chromium/content/browser/media/audio_stream_monitor.h
new file mode 100644
index 00000000000..d1a32d5f857
--- /dev/null
+++ b/chromium/content/browser/media/audio_stream_monitor.h
@@ -0,0 +1,153 @@
+// Copyright 2014 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 CONTENT_BROWSER_MEDIA_AUDIO_STREAM_MONITOR_H_
+#define CONTENT_BROWSER_MEDIA_AUDIO_STREAM_MONITOR_H_
+
+#include <map>
+#include <utility>
+
+#include "base/callback_forward.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+#include "media/audio/audio_output_controller.h"
+
+namespace base {
+class TickClock;
+}
+
+namespace content {
+class WebContents;
+
+// Repeatedly polls audio streams for their power levels, and "debounces" the
+// information into a simple, binary "was recently audible" result for the audio
+// indicators in the tab UI. The debouncing logic is to: 1) Turn on immediately
+// when sound is audible; and 2) Hold on for X amount of time after sound has
+// gone silent, then turn off. Said another way, we don't want tab indicators
+// to turn on/off repeatedly and annoy the user. AudioStreamMonitor sends UI
+// update notifications only when needed, but may be queried at any time.
+//
+// Each WebContentsImpl owns an AudioStreamMonitor.
+class CONTENT_EXPORT AudioStreamMonitor {
+ public:
+ explicit AudioStreamMonitor(WebContents* contents);
+ ~AudioStreamMonitor();
+
+ // Indicates if audio stream monitoring is available. It's only available if
+ // AudioOutputController can and will monitor output power levels.
+ static bool monitoring_available() {
+ return media::AudioOutputController::will_monitor_audio_levels();
+ }
+
+ // Returns true if audio has recently been audible from the tab. This is
+ // usually called whenever the tab data model is refreshed; but there are
+ // other use cases as well (e.g., the OOM killer uses this to de-prioritize
+ // the killing of tabs making sounds).
+ bool WasRecentlyAudible() const;
+
+ // Starts or stops audio level monitoring respectively for the stream owned by
+ // the specified renderer. Safe to call from any thread.
+ //
+ // The callback returns the current power level (in dBFS units) and the clip
+ // status (true if any part of the audio signal has clipped since the last
+ // callback run). |stream_id| must be unique within a |render_process_id|.
+ typedef base::Callback<std::pair<float, bool>()> ReadPowerAndClipCallback;
+ static void StartMonitoringStream(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const ReadPowerAndClipCallback& read_power_callback);
+ static void StopMonitoringStream(int render_process_id,
+ int render_frame_id,
+ int stream_id);
+
+ void set_was_recently_audible_for_testing(bool value) {
+ was_recently_audible_ = value;
+ }
+
+ private:
+ friend class AudioStreamMonitorTest;
+
+ enum {
+ // Desired polling frequency. Note: If this is set too low, short-duration
+ // "blip" sounds won't be detected. http://crbug.com/339133#c4
+ kPowerMeasurementsPerSecond = 15,
+
+ // Amount of time to hold a tab indicator on after its last blurt.
+ kHoldOnMilliseconds = 2000
+ };
+
+ // Helper methods for starting and stopping monitoring which lookup the
+ // identified renderer and forward calls to the correct AudioStreamMonitor.
+ static void StartMonitoringHelper(
+ int render_process_id,
+ int render_frame_id,
+ int stream_id,
+ const ReadPowerAndClipCallback& read_power_callback);
+ static void StopMonitoringHelper(int render_process_id,
+ int render_frame_id,
+ int stream_id);
+
+ // Starts polling the stream for audio stream power levels using |callback|.
+ void StartMonitoringStreamOnUIThread(
+ int render_process_id,
+ int stream_id,
+ const ReadPowerAndClipCallback& callback);
+
+ // Stops polling the stream, discarding the internal copy of the |callback|
+ // provided in the call to StartMonitoringStream().
+ void StopMonitoringStreamOnUIThread(int render_process_id, int stream_id);
+
+ // Called by |poll_timer_| to sample the power levels from each of the streams
+ // playing in the tab.
+ void Poll();
+
+ // Compares last known indicator state with what it should be, and triggers UI
+ // updates through |web_contents_| if needed. When the indicator is turned
+ // on, |off_timer_| is started to re-invoke this method in the future.
+ void MaybeToggle();
+
+ // The WebContents instance instance to receive indicator toggle
+ // notifications. This pointer should be valid for the lifetime of
+ // AudioStreamMonitor.
+ WebContents* const web_contents_;
+
+ // Note: |clock_| is always |&default_tick_clock_|, except during unit
+ // testing.
+ base::DefaultTickClock default_tick_clock_;
+ base::TickClock* const clock_;
+
+ // Confirms single-threaded access in debug builds.
+ base::ThreadChecker thread_checker_;
+
+ // The callbacks to read power levels for each stream. Only playing (i.e.,
+ // not paused) streams will have an entry in this map.
+ typedef std::pair<int, int> StreamID;
+ typedef std::map<StreamID, ReadPowerAndClipCallback> StreamPollCallbackMap;
+ StreamPollCallbackMap poll_callbacks_;
+
+ // Records the last time at which sound was audible from any stream.
+ base::TimeTicks last_blurt_time_;
+
+ // Set to true if the last call to MaybeToggle() determined the indicator
+ // should be turned on.
+ bool was_recently_audible_;
+
+ // Calls Poll() at regular intervals while |poll_callbacks_| is non-empty.
+ base::RepeatingTimer<AudioStreamMonitor> poll_timer_;
+
+ // Started only when an indicator is toggled on, to turn it off again in the
+ // future.
+ base::OneShotTimer<AudioStreamMonitor> off_timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioStreamMonitor);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_AUDIO_STREAM_MONITOR_H_
diff --git a/chromium/content/browser/media/audio_stream_monitor_unittest.cc b/chromium/content/browser/media/audio_stream_monitor_unittest.cc
new file mode 100644
index 00000000000..2b36d877bcc
--- /dev/null
+++ b/chromium/content/browser/media/audio_stream_monitor_unittest.cc
@@ -0,0 +1,297 @@
+// Copyright 2014 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 "content/browser/media/audio_stream_monitor.h"
+
+#include <map>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/invalidate_type.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/test/test_renderer_host.h"
+#include "media/audio/audio_power_monitor.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::InvokeWithoutArgs;
+
+namespace content {
+
+namespace {
+
+const int kRenderProcessId = 1;
+const int kAnotherRenderProcessId = 2;
+const int kStreamId = 3;
+const int kAnotherStreamId = 6;
+
+// Used to confirm audio indicator state changes occur at the correct times.
+class MockWebContentsDelegate : public WebContentsDelegate {
+ public:
+ MOCK_METHOD2(NavigationStateChanged,
+ void(const WebContents* source, InvalidateTypes changed_flags));
+};
+
+} // namespace
+
+class AudioStreamMonitorTest : public RenderViewHostTestHarness {
+ public:
+ AudioStreamMonitorTest() {
+ // Start |clock_| at non-zero.
+ clock_.Advance(base::TimeDelta::FromSeconds(1000000));
+ }
+
+ void SetUp() override {
+ RenderViewHostTestHarness::SetUp();
+
+ WebContentsImpl* web_contents = reinterpret_cast<WebContentsImpl*>(
+ RenderViewHostTestHarness::web_contents());
+ web_contents->SetDelegate(&mock_web_contents_delegate_);
+ monitor_ = web_contents->audio_stream_monitor();
+ const_cast<base::TickClock*&>(monitor_->clock_) = &clock_;
+ }
+
+ base::TimeTicks GetTestClockTime() { return clock_.NowTicks(); }
+
+ void AdvanceClock(const base::TimeDelta& delta) { clock_.Advance(delta); }
+
+ AudioStreamMonitor::ReadPowerAndClipCallback CreatePollCallback(
+ int stream_id) {
+ return base::Bind(
+ &AudioStreamMonitorTest::ReadPower, base::Unretained(this), stream_id);
+ }
+
+ void SetStreamPower(int stream_id, float power) {
+ current_power_[stream_id] = power;
+ }
+
+ void SimulatePollTimerFired() { monitor_->Poll(); }
+
+ void SimulateOffTimerFired() { monitor_->MaybeToggle(); }
+
+ void ExpectIsPolling(int render_process_id, int stream_id, bool is_polling) {
+ const AudioStreamMonitor::StreamID key(render_process_id, stream_id);
+ EXPECT_EQ(
+ is_polling,
+ monitor_->poll_callbacks_.find(key) != monitor_->poll_callbacks_.end());
+ EXPECT_EQ(!monitor_->poll_callbacks_.empty(),
+ monitor_->poll_timer_.IsRunning());
+ }
+
+ void ExpectTabWasRecentlyAudible(bool was_audible,
+ const base::TimeTicks& last_blurt_time) {
+ EXPECT_EQ(was_audible, monitor_->was_recently_audible_);
+ EXPECT_EQ(last_blurt_time, monitor_->last_blurt_time_);
+ EXPECT_EQ(monitor_->was_recently_audible_,
+ monitor_->off_timer_.IsRunning());
+ }
+
+ void ExpectWebContentsWillBeNotifiedOnce(bool should_be_audible) {
+ EXPECT_CALL(
+ mock_web_contents_delegate_,
+ NavigationStateChanged(RenderViewHostTestHarness::web_contents(),
+ INVALIDATE_TYPE_TAB))
+ .WillOnce(InvokeWithoutArgs(
+ this,
+ should_be_audible
+ ? &AudioStreamMonitorTest::ExpectIsNotifyingForToggleOn
+ : &AudioStreamMonitorTest::ExpectIsNotifyingForToggleOff))
+ .RetiresOnSaturation();
+ }
+
+ static base::TimeDelta one_polling_interval() {
+ return base::TimeDelta::FromSeconds(1) /
+ AudioStreamMonitor::kPowerMeasurementsPerSecond;
+ }
+
+ static base::TimeDelta holding_period() {
+ return base::TimeDelta::FromMilliseconds(
+ AudioStreamMonitor::kHoldOnMilliseconds);
+ }
+
+ void StartMonitoring(
+ int render_process_id,
+ int stream_id,
+ const AudioStreamMonitor::ReadPowerAndClipCallback& callback) {
+ monitor_->StartMonitoringStreamOnUIThread(
+ render_process_id, stream_id, callback);
+ }
+
+ void StopMonitoring(int render_process_id, int stream_id) {
+ monitor_->StopMonitoringStreamOnUIThread(render_process_id, stream_id);
+ }
+
+ protected:
+ AudioStreamMonitor* monitor_;
+
+ private:
+ std::pair<float, bool> ReadPower(int stream_id) {
+ return std::make_pair(current_power_[stream_id], false);
+ }
+
+ void ExpectIsNotifyingForToggleOn() {
+ EXPECT_TRUE(monitor_->WasRecentlyAudible());
+ }
+
+ void ExpectIsNotifyingForToggleOff() {
+ EXPECT_FALSE(monitor_->WasRecentlyAudible());
+ }
+
+ MockWebContentsDelegate mock_web_contents_delegate_;
+ base::SimpleTestTickClock clock_;
+ std::map<int, float> current_power_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioStreamMonitorTest);
+};
+
+// Tests that AudioStreamMonitor is polling while it has a
+// ReadPowerAndClipCallback, and is not polling at other times.
+TEST_F(AudioStreamMonitorTest, PollsWhenProvidedACallback) {
+ EXPECT_FALSE(monitor_->WasRecentlyAudible());
+ ExpectIsPolling(kRenderProcessId, kStreamId, false);
+
+ StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId));
+ EXPECT_FALSE(monitor_->WasRecentlyAudible());
+ ExpectIsPolling(kRenderProcessId, kStreamId, true);
+
+ StopMonitoring(kRenderProcessId, kStreamId);
+ EXPECT_FALSE(monitor_->WasRecentlyAudible());
+ ExpectIsPolling(kRenderProcessId, kStreamId, false);
+}
+
+// Tests that AudioStreamMonitor debounces the power level readings it's taking,
+// which could be fluctuating rapidly between the audible versus silence
+// threshold. See comments in audio_stream_monitor.h for expected behavior.
+TEST_F(AudioStreamMonitorTest,
+ ImpulsesKeepIndicatorOnUntilHoldingPeriodHasPassed) {
+ StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId));
+
+ // Expect WebContents will get one call form AudioStreamMonitor to toggle the
+ // indicator on upon the very first poll.
+ ExpectWebContentsWillBeNotifiedOnce(true);
+
+ // Loop, each time testing a slightly longer period of polled silence. The
+ // indicator should remain on throughout.
+ int num_silence_polls = 0;
+ base::TimeTicks last_blurt_time;
+ do {
+ // Poll an audible signal, and expect tab indicator state is on.
+ SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power());
+ last_blurt_time = GetTestClockTime();
+ SimulatePollTimerFired();
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+ AdvanceClock(one_polling_interval());
+
+ // Poll a silent signal repeatedly, ensuring that the indicator is being
+ // held on during the holding period.
+ SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power());
+ for (int i = 0; i < num_silence_polls; ++i) {
+ SimulatePollTimerFired();
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+ // Note: Redundant off timer firings should not have any effect.
+ SimulateOffTimerFired();
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+ AdvanceClock(one_polling_interval());
+ }
+
+ ++num_silence_polls;
+ } while (GetTestClockTime() < last_blurt_time + holding_period());
+
+ // At this point, the clock has just advanced to beyond the holding period, so
+ // the next firing of the off timer should turn off the tab indicator. Also,
+ // make sure it stays off for several cycles thereafter.
+ ExpectWebContentsWillBeNotifiedOnce(false);
+ for (int i = 0; i < 10; ++i) {
+ SimulateOffTimerFired();
+ ExpectTabWasRecentlyAudible(false, last_blurt_time);
+ AdvanceClock(one_polling_interval());
+ }
+}
+
+// Tests that the AudioStreamMonitor correctly processes the blurts from two
+// different streams in the same tab.
+TEST_F(AudioStreamMonitorTest, HandlesMultipleStreamsBlurting) {
+ StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId));
+ StartMonitoring(
+ kRenderProcessId, kAnotherStreamId, CreatePollCallback(kAnotherStreamId));
+
+ base::TimeTicks last_blurt_time;
+ ExpectTabWasRecentlyAudible(false, last_blurt_time);
+
+ // Measure audible sound from the first stream and silence from the second.
+ // The indicator turns on (i.e., tab was recently audible).
+ ExpectWebContentsWillBeNotifiedOnce(true);
+ SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power());
+ SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power());
+ last_blurt_time = GetTestClockTime();
+ SimulatePollTimerFired();
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+
+ // Halfway through the holding period, the second stream joins in. The
+ // indicator stays on.
+ AdvanceClock(holding_period() / 2);
+ SimulateOffTimerFired();
+ SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power());
+ last_blurt_time = GetTestClockTime();
+ SimulatePollTimerFired(); // Restarts holding period.
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+
+ // Now, measure silence from both streams. After an entire holding period
+ // has passed (since the second stream joined in), the indicator should turn
+ // off.
+ ExpectWebContentsWillBeNotifiedOnce(false);
+ AdvanceClock(holding_period());
+ SimulateOffTimerFired();
+ SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power());
+ SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power());
+ SimulatePollTimerFired();
+ ExpectTabWasRecentlyAudible(false, last_blurt_time);
+
+ // Now, measure silence from the first stream and audible sound from the
+ // second. The indicator turns back on.
+ ExpectWebContentsWillBeNotifiedOnce(true);
+ SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power());
+ last_blurt_time = GetTestClockTime();
+ SimulatePollTimerFired();
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+
+ // From here onwards, both streams are silent. Halfway through the holding
+ // period, the indicator should not have changed.
+ SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power());
+ AdvanceClock(holding_period() / 2);
+ SimulatePollTimerFired();
+ SimulateOffTimerFired();
+ ExpectTabWasRecentlyAudible(true, last_blurt_time);
+
+ // Just past the holding period, the indicator should be turned off.
+ ExpectWebContentsWillBeNotifiedOnce(false);
+ AdvanceClock(holding_period() - (GetTestClockTime() - last_blurt_time));
+ SimulateOffTimerFired();
+ ExpectTabWasRecentlyAudible(false, last_blurt_time);
+
+ // Polling should not turn the indicator back while both streams are remaining
+ // silent.
+ for (int i = 0; i < 100; ++i) {
+ AdvanceClock(one_polling_interval());
+ SimulatePollTimerFired();
+ ExpectTabWasRecentlyAudible(false, last_blurt_time);
+ }
+}
+
+TEST_F(AudioStreamMonitorTest, MultipleRendererProcesses) {
+ StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId));
+ StartMonitoring(
+ kAnotherRenderProcessId, kStreamId, CreatePollCallback(kStreamId));
+ ExpectIsPolling(kRenderProcessId, kStreamId, true);
+ ExpectIsPolling(kAnotherRenderProcessId, kStreamId, true);
+ StopMonitoring(kAnotherRenderProcessId, kStreamId);
+ ExpectIsPolling(kRenderProcessId, kStreamId, true);
+ ExpectIsPolling(kAnotherRenderProcessId, kStreamId, false);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.cc b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
index b8051fa73d0..a75eb3c6476 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
@@ -4,161 +4,211 @@
#include "content/browser/media/capture/audio_mirroring_manager.h"
-#include "content/public/browser/browser_thread.h"
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/lazy_instance.h"
namespace content {
namespace {
-// Debug utility to make sure methods of AudioMirroringManager are not invoked
-// more than once in a single call stack. In release builds, this compiles to
-// nothing and gets completely optimized out.
-class ReentrancyGuard {
- public:
-#ifdef NDEBUG
- ReentrancyGuard() {}
- ~ReentrancyGuard() {}
-#else
- ReentrancyGuard() {
- DCHECK(!inside_a_method_);
- inside_a_method_ = true;
- }
- ~ReentrancyGuard() {
- inside_a_method_ = false;
- }
-
- static bool inside_a_method_; // Safe to be static, since AMM is a singleton.
-#endif
-};
-
-#ifndef NDEBUG
-bool ReentrancyGuard::inside_a_method_ = false;
-#endif
+base::LazyInstance<AudioMirroringManager>::Leaky g_audio_mirroring_manager =
+ LAZY_INSTANCE_INITIALIZER;
} // namespace
-AudioMirroringManager::AudioMirroringManager() {}
+// static
+AudioMirroringManager* AudioMirroringManager::GetInstance() {
+ return g_audio_mirroring_manager.Pointer();
+}
-AudioMirroringManager::~AudioMirroringManager() {
- DCHECK(diverters_.empty());
- DCHECK(sessions_.empty());
+AudioMirroringManager::AudioMirroringManager() {
+ // Only *after* construction, check that AudioMirroringManager is being
+ // invoked on the same single thread.
+ thread_checker_.DetachFromThread();
}
+AudioMirroringManager::~AudioMirroringManager() {}
+
void AudioMirroringManager::AddDiverter(
- int render_process_id, int render_view_id, Diverter* diverter) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ReentrancyGuard guard;
+ int render_process_id, int render_frame_id, Diverter* diverter) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(diverter);
- // DCHECK(diverter not already in diverters_ under any key)
+ // DCHECK(diverter not already in routes_)
#ifndef NDEBUG
- for (DiverterMap::const_iterator it = diverters_.begin();
- it != diverters_.end(); ++it) {
- DCHECK_NE(diverter, it->second);
+ for (StreamRoutes::const_iterator it = routes_.begin();
+ it != routes_.end(); ++it) {
+ DCHECK_NE(diverter, it->diverter);
}
#endif
-
- // Add the diverter to the set of active diverters.
- const Target target(render_process_id, render_view_id);
- diverters_.insert(std::make_pair(target, diverter));
-
- // If a mirroring session is active, start diverting the audio stream
- // immediately.
- SessionMap::iterator session_it = sessions_.find(target);
- if (session_it != sessions_.end()) {
- diverter->StartDiverting(
- session_it->second->AddInput(diverter->GetAudioParameters()));
- }
+ routes_.push_back(StreamRoutingState(
+ SourceFrameRef(render_process_id, render_frame_id),
+ diverter));
+
+ // Query existing destinations to see whether to immediately start diverting
+ // the stream.
+ std::set<SourceFrameRef> candidates;
+ candidates.insert(routes_.back().source_render_frame);
+ InitiateQueriesToFindNewDestination(NULL, candidates);
}
-void AudioMirroringManager::RemoveDiverter(
- int render_process_id, int render_view_id, Diverter* diverter) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ReentrancyGuard guard;
-
- // Stop diverting the audio stream if a mirroring session is active.
- const Target target(render_process_id, render_view_id);
- SessionMap::iterator session_it = sessions_.find(target);
- if (session_it != sessions_.end())
- diverter->StopDiverting();
-
- // Remove the diverter from the set of active diverters.
- for (DiverterMap::iterator it = diverters_.lower_bound(target);
- it != diverters_.end() && it->first == target; ++it) {
- if (it->second == diverter) {
- diverters_.erase(it);
- break;
+void AudioMirroringManager::RemoveDiverter(Diverter* diverter) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Find and remove the entry from the routing table. If the stream is being
+ // diverted, it is stopped.
+ for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ if (it->diverter == diverter) {
+ ChangeRoute(&(*it), NULL);
+ routes_.erase(it);
+ return;
}
}
+ NOTREACHED();
}
-void AudioMirroringManager::StartMirroring(
- int render_process_id, int render_view_id,
- MirroringDestination* destination) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ReentrancyGuard guard;
+void AudioMirroringManager::StartMirroring(MirroringDestination* destination) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(destination);
- // Insert an entry into the set of active mirroring sessions. If a mirroring
- // session is already active for |render_process_id| + |render_view_id|,
- // replace the entry.
- const Target target(render_process_id, render_view_id);
- SessionMap::iterator session_it = sessions_.find(target);
- MirroringDestination* old_destination;
- if (session_it == sessions_.end()) {
- old_destination = NULL;
- sessions_.insert(std::make_pair(target, destination));
-
- DVLOG(1) << "Start mirroring render_process_id:render_view_id="
- << render_process_id << ':' << render_view_id
- << " --> MirroringDestination@" << destination;
- } else {
- old_destination = session_it->second;
- session_it->second = destination;
-
- DVLOG(1) << "Switch mirroring of render_process_id:render_view_id="
- << render_process_id << ':' << render_view_id
- << " MirroringDestination@" << old_destination
- << " --> MirroringDestination@" << destination;
+ // Insert an entry into the set of active mirroring sessions, if this is a
+ // previously-unknown destination.
+ if (std::find(sessions_.begin(), sessions_.end(), destination) ==
+ sessions_.end()) {
+ sessions_.push_back(destination);
}
- // Divert audio streams coming from |target| to |destination|. If streams
- // were already diverted to the |old_destination|, remove them.
- for (DiverterMap::iterator it = diverters_.lower_bound(target);
- it != diverters_.end() && it->first == target; ++it) {
- Diverter* const diverter = it->second;
- if (old_destination)
- diverter->StopDiverting();
- diverter->StartDiverting(
- destination->AddInput(diverter->GetAudioParameters()));
+ // Query the MirroringDestination to see which of the audio streams should be
+ // diverted.
+ std::set<SourceFrameRef> candidates;
+ for (StreamRoutes::const_iterator it = routes_.begin(); it != routes_.end();
+ ++it) {
+ if (!it->destination || it->destination == destination)
+ candidates.insert(it->source_render_frame);
+ }
+ if (!candidates.empty()) {
+ destination->QueryForMatches(
+ candidates,
+ base::Bind(&AudioMirroringManager::UpdateRoutesToDestination,
+ base::Unretained(this),
+ destination,
+ false));
}
}
-void AudioMirroringManager::StopMirroring(
- int render_process_id, int render_view_id,
- MirroringDestination* destination) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ReentrancyGuard guard;
-
- // Stop mirroring if there is an active session *and* the destination
- // matches.
- const Target target(render_process_id, render_view_id);
- SessionMap::iterator session_it = sessions_.find(target);
- if (session_it == sessions_.end() || destination != session_it->second)
- return;
-
- DVLOG(1) << "Stop mirroring render_process_id:render_view_id="
- << render_process_id << ':' << render_view_id
- << " --> MirroringDestination@" << destination;
+void AudioMirroringManager::StopMirroring(MirroringDestination* destination) {
+ DCHECK(thread_checker_.CalledOnValidThread());
// Stop diverting each audio stream in the mirroring session being stopped.
- for (DiverterMap::iterator it = diverters_.lower_bound(target);
- it != diverters_.end() && it->first == target; ++it) {
- it->second->StopDiverting();
+ // Each stopped stream becomes a candidate to be diverted to another
+ // destination.
+ std::set<SourceFrameRef> redivert_candidates;
+ for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ if (it->destination == destination) {
+ ChangeRoute(&(*it), NULL);
+ redivert_candidates.insert(it->source_render_frame);
+ }
}
+ if (!redivert_candidates.empty())
+ InitiateQueriesToFindNewDestination(destination, redivert_candidates);
// Remove the entry from the set of active mirroring sessions.
- sessions_.erase(session_it);
+ const Destinations::iterator dest_it =
+ std::find(sessions_.begin(), sessions_.end(), destination);
+ if (dest_it == sessions_.end()) {
+ NOTREACHED();
+ return;
+ }
+ sessions_.erase(dest_it);
+}
+
+void AudioMirroringManager::InitiateQueriesToFindNewDestination(
+ MirroringDestination* old_destination,
+ const std::set<SourceFrameRef>& candidates) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ for (Destinations::const_iterator it = sessions_.begin();
+ it != sessions_.end(); ++it) {
+ if (*it != old_destination) {
+ (*it)->QueryForMatches(
+ candidates,
+ base::Bind(&AudioMirroringManager::UpdateRoutesToDestination,
+ base::Unretained(this),
+ *it,
+ true));
+ }
+ }
}
+void AudioMirroringManager::UpdateRoutesToDestination(
+ MirroringDestination* destination,
+ bool add_only,
+ const std::set<SourceFrameRef>& matches) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (std::find(sessions_.begin(), sessions_.end(), destination) ==
+ sessions_.end()) {
+ return; // Query result callback invoked after StopMirroring().
+ }
+
+ DVLOG(1) << (add_only ? "Add " : "Replace with ") << matches.size()
+ << " routes to MirroringDestination@" << destination;
+
+ // Start/stop diverting based on |matches|. Any stopped stream becomes a
+ // candidate to be diverted to another destination.
+ std::set<SourceFrameRef> redivert_candidates;
+ for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
+ if (matches.find(it->source_render_frame) != matches.end()) {
+ // Only change the route if the stream is not already being diverted.
+ if (!it->destination)
+ ChangeRoute(&(*it), destination);
+ } else if (!add_only) {
+ // Only stop diverting if the stream is currently routed to |destination|.
+ if (it->destination == destination) {
+ ChangeRoute(&(*it), NULL);
+ redivert_candidates.insert(it->source_render_frame);
+ }
+ }
+ }
+ if (!redivert_candidates.empty())
+ InitiateQueriesToFindNewDestination(destination, redivert_candidates);
+}
+
+// static
+void AudioMirroringManager::ChangeRoute(
+ StreamRoutingState* route, MirroringDestination* new_destination) {
+ if (route->destination == new_destination)
+ return; // No change.
+
+ if (route->destination) {
+ DVLOG(1) << "Stop diverting render_process_id:render_frame_id="
+ << route->source_render_frame.first << ':'
+ << route->source_render_frame.second
+ << " --> MirroringDestination@" << route->destination;
+ route->diverter->StopDiverting();
+ route->destination = NULL;
+ }
+
+ if (new_destination) {
+ DVLOG(1) << "Start diverting of render_process_id:render_frame_id="
+ << route->source_render_frame.first << ':'
+ << route->source_render_frame.second
+ << " --> MirroringDestination@" << new_destination;
+ route->diverter->StartDiverting(
+ new_destination->AddInput(route->diverter->GetAudioParameters()));
+ route->destination = new_destination;
+ }
+}
+
+AudioMirroringManager::StreamRoutingState::StreamRoutingState(
+ const SourceFrameRef& source_frame, Diverter* stream_diverter)
+ : source_render_frame(source_frame),
+ diverter(stream_diverter),
+ destination(NULL) {}
+
+AudioMirroringManager::StreamRoutingState::~StreamRoutingState() {}
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.h b/chromium/content/browser/media/capture/audio_mirroring_manager.h
index fe7db7ad52e..441c884ad92 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.h
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.h
@@ -5,32 +5,40 @@
// AudioMirroringManager is a singleton object that maintains a set of active
// audio mirroring destinations and auto-connects/disconnects audio streams
// to/from those destinations. It is meant to be used exclusively on the IO
-// BrowserThread.
+// thread.
//
// How it works:
//
// 1. AudioRendererHost gets a CreateStream message from the render process
// and, among other things, creates an AudioOutputController to control the
-// audio data flow between the render and browser processes.
-// 2. At some point, AudioRendererHost receives an "associate with render
-// view" message. Among other actions, it registers the
-// AudioOutputController with AudioMirroringManager (as a Diverter).
-// 3. A user request to mirror all the audio for a single RenderView is made.
-// A MirroringDestination is created, and StartMirroring() is called to
-// begin the mirroring session. This causes AudioMirroringManager to
-// instruct any matching Diverters to divert their audio data to the
-// MirroringDestination.
-//
-// #2 and #3 above may occur in any order, as it is the job of
-// AudioMirroringManager to realize when the players can be "matched up."
+// audio data flow between the render and browser processes. More
+// importantly, it registers the AudioOutputController with
+// AudioMirroringManager (as a Diverter).
+// 2. A user request to mirror all the audio for a WebContents is made. A
+// MirroringDestination is created, and StartMirroring() is called to begin
+// the mirroring session. The MirroringDestination is queried to determine
+// which of all the known Diverters will re-route their audio to it.
+// 3a. During a mirroring session, AudioMirroringManager may encounter new
+// Diverters, and will query all the MirroringDestinations to determine
+// which is a match, if any.
+// 3b. During a mirroring session, a call to StartMirroring() can be made to
+// request a "refresh" query on a MirroringDestination, and this will
+// result in AudioMirroringManager starting/stopping only those Diverters
+// that are not correctly routed to the destination.
+// 3c. When a mirroring session is stopped, the remaining destinations will be
+// queried to determine whether diverting should continue to a different
+// destination.
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_AUDIO_MIRRORING_MANAGER_H_
-#include <map>
+#include <set>
#include <utility>
+#include <vector>
#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "media/audio/audio_source_diverter.h"
@@ -45,10 +53,25 @@ class CONTENT_EXPORT AudioMirroringManager {
// Interface for diverting audio data to an alternative AudioOutputStream.
typedef media::AudioSourceDiverter Diverter;
+ // A SourceFrameRef is a RenderFrameHost identified by a <render_process_id,
+ // render_frame_id> pair.
+ typedef std::pair<int, int> SourceFrameRef;
+
// Interface to be implemented by audio mirroring destinations. See comments
// for StartMirroring() and StopMirroring() below.
class MirroringDestination {
public:
+ // Asynchronously query whether this MirroringDestination wants to consume
+ // audio sourced from each of the |candidates|. |results_callback| is run
+ // to indicate which of them (or none) should have audio routed to this
+ // MirroringDestination. |results_callback| must be run on the same thread
+ // as the one that called QueryForMatches().
+ typedef base::Callback<void(const std::set<SourceFrameRef>&)>
+ MatchesCallback;
+ virtual void QueryForMatches(
+ const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) = 0;
+
// Create a consumer of audio data in the format specified by |params|, and
// connect it as an input to mirroring. When Close() is called on the
// returned AudioOutputStream, the input is disconnected and the object
@@ -60,45 +83,78 @@ class CONTENT_EXPORT AudioMirroringManager {
virtual ~MirroringDestination() {}
};
+ // Note: Use GetInstance() for non-test code.
AudioMirroringManager();
-
virtual ~AudioMirroringManager();
- // Add/Remove a diverter for an audio stream with a known RenderView target
- // (represented by |render_process_id| + |render_view_id|). Multiple
- // diverters may be added for the same target. |diverter| must live until
- // after RemoveDiverter() is called.
- //
- // Re-entrancy warning: These methods should not be called by a Diverter
- // during a Start/StopDiverting() invocation.
- virtual void AddDiverter(int render_process_id, int render_view_id,
+ // Returns the global instance.
+ static AudioMirroringManager* GetInstance();
+
+ // Add/Remove a diverter for an audio stream with a known RenderFrame source
+ // (represented by |render_process_id| + |render_frame_id|). Multiple
+ // diverters may be added for the same source frame, but never the same
+ // diverter. |diverter| must live until after RemoveDiverter() is called.
+ virtual void AddDiverter(int render_process_id, int render_frame_id,
Diverter* diverter);
- virtual void RemoveDiverter(int render_process_id, int render_view_id,
- Diverter* diverter);
-
- // Start/stop mirroring all audio output streams associated with a RenderView
- // target (represented by |render_process_id| + |render_view_id|) to
- // |destination|. |destination| must live until after StopMirroring() is
- // called.
- virtual void StartMirroring(int render_process_id, int render_view_id,
- MirroringDestination* destination);
- virtual void StopMirroring(int render_process_id, int render_view_id,
- MirroringDestination* destination);
+ virtual void RemoveDiverter(Diverter* diverter);
+
+ // (Re-)Start/Stop mirroring to the given |destination|. |destination| must
+ // live until after StopMirroring() is called. A client may request a
+ // re-start by calling StartMirroring() again; and this will cause
+ // AudioMirroringManager to query |destination| and only re-route those
+ // diverters that are missing/new to the returned set of matches.
+ virtual void StartMirroring(MirroringDestination* destination);
+ virtual void StopMirroring(MirroringDestination* destination);
private:
- // A mirroring target is a RenderView identified by a
- // <render_process_id, render_view_id> pair.
- typedef std::pair<int, int> Target;
+ friend class AudioMirroringManagerTest;
+
+ struct StreamRoutingState {
+ // The source render frame associated with the audio stream.
+ SourceFrameRef source_render_frame;
+
+ // The diverter for re-routing the audio stream.
+ Diverter* diverter;
+
+ // If not NULL, the audio stream is currently being diverted to this
+ // destination.
+ MirroringDestination* destination;
+
+ StreamRoutingState(const SourceFrameRef& source_frame,
+ Diverter* stream_diverter);
+ ~StreamRoutingState();
+ };
+
+ typedef std::vector<StreamRoutingState> StreamRoutes;
+ typedef std::vector<MirroringDestination*> Destinations;
+
+ // Helper to find a destination other than |old_destination| for the given
+ // |candidates| to be diverted to.
+ void InitiateQueriesToFindNewDestination(
+ MirroringDestination* old_destination,
+ const std::set<SourceFrameRef>& candidates);
+
+ // MirroringDestination query callback. |matches| contains all RenderFrame
+ // sources that will be diverted to |destination|. If |add_only| is false,
+ // then any Diverters currently routed to |destination| but not found in
+ // |matches| will be stopped.
+ void UpdateRoutesToDestination(MirroringDestination* destination,
+ bool add_only,
+ const std::set<SourceFrameRef>& matches);
+
+ // Starts diverting audio to the |new_destination|, if not NULL. Otherwise,
+ // stops diverting audio.
+ static void ChangeRoute(StreamRoutingState* route,
+ MirroringDestination* new_destination);
- // Note: Objects in these maps are not owned.
- typedef std::multimap<Target, Diverter*> DiverterMap;
- typedef std::map<Target, MirroringDestination*> SessionMap;
+ // Routing table. Contains one entry for each Diverter.
+ StreamRoutes routes_;
- // Currently-active divertable audio streams.
- DiverterMap diverters_;
+ // All active mirroring sessions.
+ Destinations sessions_;
- // Currently-active mirroring sessions.
- SessionMap sessions_;
+ // Used to check that all AudioMirroringManager code runs on the same thread.
+ base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(AudioMirroringManager);
};
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
index cd197769aa5..6fece29c09f 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -5,6 +5,7 @@
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include <map>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -18,6 +19,7 @@
using media::AudioOutputStream;
using media::AudioParameters;
using testing::_;
+using testing::Invoke;
using testing::NotNull;
using testing::Ref;
using testing::Return;
@@ -37,14 +39,56 @@ class MockDiverter : public AudioMirroringManager::Diverter {
class MockMirroringDestination
: public AudioMirroringManager::MirroringDestination {
public:
+ typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
+
+ MockMirroringDestination(int render_process_id, int render_frame_id)
+ : render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id),
+ query_count_(0) {}
+
+ MOCK_METHOD2(QueryForMatches,
+ void(const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback));
MOCK_METHOD1(AddInput,
media::AudioOutputStream*(const media::AudioParameters& params));
+
+ void SimulateQuery(const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) {
+ ++query_count_;
+
+ std::set<SourceFrameRef> result;
+ if (candidates.find(SourceFrameRef(render_process_id_, render_frame_id_)) !=
+ candidates.end()) {
+ result.insert(SourceFrameRef(render_process_id_, render_frame_id_));
+ }
+ results_callback.Run(result);
+ }
+
+ media::AudioOutputStream* SimulateAddInput(
+ const media::AudioParameters& params) {
+ static AudioOutputStream* const kNonNullPointer =
+ reinterpret_cast<AudioOutputStream*>(0x11111110);
+ return kNonNullPointer;
+ }
+
+ int query_count() const {
+ return query_count_;
+ }
+
+ private:
+ const int render_process_id_;
+ const int render_frame_id_;
+ int query_count_;
};
} // namespace
class AudioMirroringManagerTest : public testing::Test {
public:
+ typedef AudioMirroringManager::Diverter Diverter;
+ typedef AudioMirroringManager::MirroringDestination MirroringDestination;
+ typedef AudioMirroringManager::StreamRoutes StreamRoutes;
+
AudioMirroringManagerTest()
: io_thread_(BrowserThread::IO, &message_loop_),
params_(AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
@@ -52,7 +96,7 @@ class AudioMirroringManagerTest : public testing::Test {
AudioParameters::kAudioCDSampleRate / 10) {}
MockDiverter* CreateStream(
- int render_process_id, int render_view_id, int expected_times_diverted) {
+ int render_process_id, int render_frame_id, int expected_times_diverted) {
MockDiverter* const diverter = new MockDiverter();
if (expected_times_diverted > 0) {
EXPECT_CALL(*diverter, GetAudioParameters())
@@ -64,41 +108,52 @@ class AudioMirroringManagerTest : public testing::Test {
.Times(expected_times_diverted);
}
- mirroring_manager_.AddDiverter(render_process_id, render_view_id, diverter);
+ mirroring_manager_.AddDiverter(
+ render_process_id, render_frame_id, diverter);
return diverter;
}
- void KillStream(
- int render_process_id, int render_view_id, MockDiverter* diverter) {
- mirroring_manager_.RemoveDiverter(
- render_process_id, render_view_id, diverter);
-
+ void KillStream(MockDiverter* diverter) {
+ mirroring_manager_.RemoveDiverter(diverter);
delete diverter;
}
- MockMirroringDestination* StartMirroringTo(
- int render_process_id, int render_view_id, int expected_inputs_added) {
- MockMirroringDestination* const dest = new MockMirroringDestination();
+ void StartMirroringTo(const scoped_ptr<MockMirroringDestination>& dest,
+ int expected_inputs_added) {
+ EXPECT_CALL(*dest, QueryForMatches(_, _))
+ .WillRepeatedly(Invoke(dest.get(),
+ &MockMirroringDestination::SimulateQuery));
if (expected_inputs_added > 0) {
- static AudioOutputStream* const kNonNullPointer =
- reinterpret_cast<AudioOutputStream*>(0x11111110);
EXPECT_CALL(*dest, AddInput(Ref(params_)))
.Times(expected_inputs_added)
- .WillRepeatedly(Return(kNonNullPointer));
+ .WillRepeatedly(Invoke(dest.get(),
+ &MockMirroringDestination::SimulateAddInput))
+ .RetiresOnSaturation();
}
- mirroring_manager_.StartMirroring(render_process_id, render_view_id, dest);
+ mirroring_manager_.StartMirroring(dest.get());
+ }
- return dest;
+ void StopMirroringTo(const scoped_ptr<MockMirroringDestination>& dest) {
+ mirroring_manager_.StopMirroring(dest.get());
}
- void StopMirroringTo(int render_process_id, int render_view_id,
- MockMirroringDestination* dest) {
- mirroring_manager_.StopMirroring(render_process_id, render_view_id, dest);
+ int CountStreamsDivertedTo(
+ const scoped_ptr<MockMirroringDestination>& dest) const {
+ int count = 0;
+ for (StreamRoutes::const_iterator it = mirroring_manager_.routes_.begin();
+ it != mirroring_manager_.routes_.end(); ++it) {
+ if (it->destination == dest.get())
+ ++count;
+ }
+ return count;
+ }
- delete dest;
-}
+ void ExpectNoLongerManagingAnything() const {
+ EXPECT_TRUE(mirroring_manager_.routes_.empty());
+ EXPECT_TRUE(mirroring_manager_.sessions_.empty());
+ }
private:
base::MessageLoopForIO message_loop_;
@@ -111,123 +166,389 @@ class AudioMirroringManagerTest : public testing::Test {
namespace {
const int kRenderProcessId = 123;
-const int kRenderViewId = 456;
+const int kRenderFrameId = 456;
const int kAnotherRenderProcessId = 789;
-const int kAnotherRenderViewId = 1234;
+const int kAnotherRenderFrameId = 1234;
const int kYetAnotherRenderProcessId = 4560;
-const int kYetAnotherRenderViewId = 7890;
+const int kYetAnotherRenderFrameId = 7890;
}
TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) {
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 0);
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(0, destination->query_count());
+
+ ExpectNoLongerManagingAnything();
}
TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
-
- MockMirroringDestination* const another_destination =
- StartMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 0);
- StopMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId,
- another_destination);
-}
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 0);
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(0, destination->query_count());
-TEST_F(AudioMirroringManagerTest, SwitchMirroringDestinationNoStreams) {
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
- MockMirroringDestination* const new_destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 0);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
- StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination);
+ const scoped_ptr<MockMirroringDestination> another_destination(
+ new MockMirroringDestination(kAnotherRenderProcessId,
+ kAnotherRenderFrameId));
+ StartMirroringTo(another_destination, 0);
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
+
+ StopMirroringTo(another_destination);
+ EXPECT_EQ(0, another_destination->query_count());
+
+ ExpectNoLongerManagingAnything();
}
+// Tests that a mirroring session starts after, and ends before, a stream that
+// will be diverted to it.
TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) {
- MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 1);
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
- KillStream(kRenderProcessId, kRenderViewId, stream);
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ ExpectNoLongerManagingAnything();
}
+// Tests that a mirroring session starts before, and ends after, a stream that
+// will be diverted to it.
TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinMirroringSession) {
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
- MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 1);
- KillStream(kRenderProcessId, kRenderViewId, stream);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(0, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ ExpectNoLongerManagingAnything();
}
-TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundTwoMirroringSessions) {
- MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 2);
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
- MockMirroringDestination* const new_destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
- StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination);
- KillStream(kRenderProcessId, kRenderViewId, stream);
+// Tests that a stream is diverted correctly as two mirroring sessions come and
+// go.
+TEST_F(AudioMirroringManagerTest, StreamLifetimeAcrossTwoMirroringSessions) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 2);
+
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ const scoped_ptr<MockMirroringDestination> second_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(second_destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, second_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(second_destination));
+
+ StopMirroringTo(second_destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, second_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(second_destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, second_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(second_destination));
+
+ ExpectNoLongerManagingAnything();
}
-TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinTwoMirroringSessions) {
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
- MockDiverter* const stream = CreateStream(kRenderProcessId, kRenderViewId, 2);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
- MockMirroringDestination* const new_destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
- KillStream(kRenderProcessId, kRenderViewId, stream);
- StopMirroringTo(kRenderProcessId, kRenderViewId, new_destination);
+// Tests that a stream does not flip-flop between two destinations that are a
+// match for it.
+TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_1) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 2);
+
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ const scoped_ptr<MockMirroringDestination> replacement_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(replacement_destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(replacement_destination));
+
+ StopMirroringTo(replacement_destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ ExpectNoLongerManagingAnything();
+}
+
+// Same as StreamDivertingStickyToOneDestination_1, with a different order of
+// operations that should have the same effects.
+TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_2) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 2);
+
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ const scoped_ptr<MockMirroringDestination> replacement_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(replacement_destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(replacement_destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ StopMirroringTo(replacement_destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ ExpectNoLongerManagingAnything();
+}
+
+// Same as StreamDivertingStickyToOneDestination_1, except that the stream is
+// killed before the first destination is stopped. Therefore, the second
+// destination should never see the stream.
+TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_3) {
+ MockDiverter* const stream =
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ const scoped_ptr<MockMirroringDestination> replacement_destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(replacement_destination, 0);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ KillStream(stream);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ StopMirroringTo(replacement_destination);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, replacement_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(replacement_destination));
+
+ ExpectNoLongerManagingAnything();
}
+// Tests that multiple streams are diverted/mixed to one destination.
TEST_F(AudioMirroringManagerTest, MultipleStreamsInOneMirroringSession) {
MockDiverter* const stream1 =
- CreateStream(kRenderProcessId, kRenderViewId, 1);
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 3);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 3);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
MockDiverter* const stream2 =
- CreateStream(kRenderProcessId, kRenderViewId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ EXPECT_EQ(2, destination->query_count());
+ EXPECT_EQ(2, CountStreamsDivertedTo(destination));
+
MockDiverter* const stream3 =
- CreateStream(kRenderProcessId, kRenderViewId, 1);
- KillStream(kRenderProcessId, kRenderViewId, stream2);
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
- KillStream(kRenderProcessId, kRenderViewId, stream3);
- KillStream(kRenderProcessId, kRenderViewId, stream1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(3, CountStreamsDivertedTo(destination));
+
+ KillStream(stream2);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(2, CountStreamsDivertedTo(destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ KillStream(stream3);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ KillStream(stream1);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+
+ ExpectNoLongerManagingAnything();
}
// A random interleaving of operations for three separate targets, each of which
// has one stream mirrored to one destination.
TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
MockDiverter* const stream =
- CreateStream(kRenderProcessId, kRenderViewId, 1);
- MockMirroringDestination* const destination =
- StartMirroringTo(kRenderProcessId, kRenderViewId, 1);
+ CreateStream(kRenderProcessId, kRenderFrameId, 1);
+
+ const scoped_ptr<MockMirroringDestination> destination(
+ new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
+ StartMirroringTo(destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+
+ const scoped_ptr<MockMirroringDestination> another_destination(
+ new MockMirroringDestination(kAnotherRenderProcessId,
+ kAnotherRenderFrameId));
+ StartMirroringTo(another_destination, 1);
+ EXPECT_EQ(1, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(0, another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
- MockMirroringDestination* const another_destination =
- StartMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId, 1);
MockDiverter* const another_stream =
- CreateStream(kAnotherRenderProcessId, kAnotherRenderViewId, 1);
-
- KillStream(kRenderProcessId, kRenderViewId, stream);
+ CreateStream(kAnotherRenderProcessId, kAnotherRenderFrameId, 1);
+ EXPECT_EQ(2, destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, another_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
+
+ KillStream(stream);
+ EXPECT_EQ(2, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(1, another_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
MockDiverter* const yet_another_stream =
- CreateStream(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 1);
- MockMirroringDestination* const yet_another_destination =
- StartMirroringTo(kYetAnotherRenderProcessId, kYetAnotherRenderViewId, 1);
-
- StopMirroringTo(kAnotherRenderProcessId, kAnotherRenderViewId,
- another_destination);
-
- StopMirroringTo(kYetAnotherRenderProcessId, kYetAnotherRenderViewId,
- yet_another_destination);
-
- StopMirroringTo(kRenderProcessId, kRenderViewId, destination);
-
- KillStream(kAnotherRenderProcessId, kAnotherRenderViewId, another_stream);
- KillStream(kYetAnotherRenderProcessId, kYetAnotherRenderViewId,
- yet_another_stream);
+ CreateStream(kYetAnotherRenderProcessId, kYetAnotherRenderFrameId, 1);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
+
+ const scoped_ptr<MockMirroringDestination> yet_another_destination(
+ new MockMirroringDestination(kYetAnotherRenderProcessId,
+ kYetAnotherRenderFrameId));
+ StartMirroringTo(yet_another_destination, 1);
+ EXPECT_EQ(3, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
+ EXPECT_EQ(1, yet_another_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(yet_another_destination));
+
+ StopMirroringTo(another_destination);
+ EXPECT_EQ(4, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
+ EXPECT_EQ(2, yet_another_destination->query_count());
+ EXPECT_EQ(1, CountStreamsDivertedTo(yet_another_destination));
+
+ StopMirroringTo(yet_another_destination);
+ EXPECT_EQ(5, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
+ EXPECT_EQ(2, yet_another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
+
+ StopMirroringTo(destination);
+ EXPECT_EQ(5, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
+ EXPECT_EQ(2, yet_another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
+
+ KillStream(another_stream);
+ EXPECT_EQ(5, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
+ EXPECT_EQ(2, yet_another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
+
+ KillStream(yet_another_stream);
+ EXPECT_EQ(5, destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(destination));
+ EXPECT_EQ(2, another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(another_destination));
+ EXPECT_EQ(2, yet_another_destination->query_count());
+ EXPECT_EQ(0, CountStreamsDivertedTo(yet_another_destination));
+
+ ExpectNoLongerManagingAnything();
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/content_video_capture_device_core.cc b/chromium/content/browser/media/capture/content_video_capture_device_core.cc
index 6878652de07..f0499a23c22 100644
--- a/chromium/content/browser/media/capture/content_video_capture_device_core.cc
+++ b/chromium/content/browser/media/capture/content_video_capture_device_core.cc
@@ -66,6 +66,7 @@ ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {}
bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
VideoCaptureOracle::Event event,
+ const gfx::Rect& damage_rect,
base::TimeTicks event_time,
scoped_refptr<media::VideoFrame>* storage,
CaptureFrameCallback* callback) {
@@ -74,11 +75,16 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
if (!client_)
return false; // Capture is stopped.
+ // Always round up the coded size to multiple of 16 pixels.
+ // See http://crbug.com/402151.
+ const gfx::Size visible_size = params_.requested_format.frame_size;
+ const gfx::Size coded_size((visible_size.width() + 15) & ~15,
+ (visible_size.height() + 15) & ~15);
+
scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer =
- client_->ReserveOutputBuffer(video_frame_format_,
- params_.requested_format.frame_size);
+ client_->ReserveOutputBuffer(video_frame_format_, coded_size);
const bool should_capture =
- oracle_->ObserveEventAndDecideCapture(event, event_time);
+ oracle_->ObserveEventAndDecideCapture(event, damage_rect, event_time);
const bool content_is_dirty =
(event == VideoCaptureOracle::kCompositorUpdate ||
event == VideoCaptureOracle::kSoftwarePaint);
@@ -88,14 +94,14 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
"paint"));
// Consider the various reasons not to initiate a capture.
- if (should_capture && !output_buffer) {
+ if (should_capture && !output_buffer.get()) {
TRACE_EVENT_INSTANT1("mirroring",
- "EncodeLimited",
+ "PipelineLimited",
TRACE_EVENT_SCOPE_THREAD,
"trigger",
event_name);
return false;
- } else if (!should_capture && output_buffer) {
+ } else if (!should_capture && output_buffer.get()) {
if (content_is_dirty) {
// This is a normal and acceptable way to drop a frame. We've hit our
// capture rate limit: for example, the content is animating at 60fps but
@@ -105,10 +111,10 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
"trigger", event_name);
}
return false;
- } else if (!should_capture && !output_buffer) {
+ } else if (!should_capture && !output_buffer.get()) {
// We decided not to capture, but we wouldn't have been able to if we wanted
// to because no output buffer was available.
- TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited",
+ TRACE_EVENT_INSTANT1("mirroring", "NearlyPipelineLimited",
TRACE_EVENT_SCOPE_THREAD,
"trigger", event_name);
return false;
@@ -122,9 +128,9 @@ bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
if (video_frame_format_ != media::VideoFrame::NATIVE_TEXTURE) {
*storage = media::VideoFrame::WrapExternalPackedMemory(
video_frame_format_,
- params_.requested_format.frame_size,
- gfx::Rect(params_.requested_format.frame_size),
- params_.requested_format.frame_size,
+ coded_size,
+ gfx::Rect(visible_size),
+ visible_size,
static_cast<uint8*>(output_buffer->data()),
output_buffer->size(),
base::SharedMemory::NULLHandle(),
@@ -149,7 +155,8 @@ void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) {
// If this is the first call to UpdateCaptureSize(), or the receiver supports
// variable resolution, then determine the capture size by treating the
// requested width and height as maxima.
- if (!capture_size_updated_ || params_.allow_resolution_change) {
+ if (!capture_size_updated_ || params_.resolution_change_policy ==
+ media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT) {
// The capture resolution should not exceed the source frame size.
// In other words it should downscale the image but not upscale it.
if (source_size.width() > params_.requested_format.frame_size.width() ||
@@ -192,7 +199,7 @@ void ThreadSafeCaptureOracle::DidCaptureFrame(
return; // Capture is stopped.
if (success) {
- if (oracle_->CompleteCapture(frame_number, timestamp)) {
+ if (oracle_->CompleteCapture(frame_number, &timestamp)) {
media::VideoCaptureFormat format = params_.requested_format;
format.frame_size = frame->coded_size();
client_->OnIncomingCapturedVideoFrame(buffer, format, frame, timestamp);
@@ -296,9 +303,13 @@ void ContentVideoCaptureDeviceCore::CaptureStarted(bool success) {
ContentVideoCaptureDeviceCore::ContentVideoCaptureDeviceCore(
scoped_ptr<VideoCaptureMachine> capture_machine)
: state_(kIdle),
- capture_machine_(capture_machine.Pass()) {}
+ capture_machine_(capture_machine.Pass()) {
+ DCHECK(capture_machine_.get());
+}
ContentVideoCaptureDeviceCore::~ContentVideoCaptureDeviceCore() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_NE(state_, kCapturing);
// If capture_machine is not NULL, then we need to return to the UI thread to
// safely stop the capture machine.
if (capture_machine_) {
@@ -333,7 +344,7 @@ void ContentVideoCaptureDeviceCore::Error(const std::string& reason) {
if (state_ == kIdle)
return;
- if (oracle_proxy_)
+ if (oracle_proxy_.get())
oracle_proxy_->ReportError(reason);
StopAndDeAllocate();
diff --git a/chromium/content/browser/media/capture/content_video_capture_device_core.h b/chromium/content/browser/media/capture/content_video_capture_device_core.h
index 3a7e6974ae7..c86bb6c883a 100644
--- a/chromium/content/browser/media/capture/content_video_capture_device_core.h
+++ b/chromium/content/browser/media/capture/content_video_capture_device_core.h
@@ -62,12 +62,13 @@ class ThreadSafeCaptureOracle
bool success)> CaptureFrameCallback;
bool ObserveEventAndDecideCapture(VideoCaptureOracle::Event event,
+ const gfx::Rect& damage_rect,
base::TimeTicks event_time,
scoped_refptr<media::VideoFrame>* storage,
CaptureFrameCallback* callback);
- base::TimeDelta capture_period() const {
- return oracle_->capture_period();
+ base::TimeDelta min_capture_period() const {
+ return oracle_->min_capture_period();
}
// Returns the current capture resolution.
@@ -118,12 +119,9 @@ class ThreadSafeCaptureOracle
// UI BrowserThread.
class VideoCaptureMachine {
public:
- VideoCaptureMachine() : started_(false) {}
+ VideoCaptureMachine() {}
virtual ~VideoCaptureMachine() {}
- // This should only be checked on the UI thread.
- bool started() const { return started_; }
-
// Starts capturing. Returns true if succeeded.
// Must be run on the UI BrowserThread.
virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
@@ -133,9 +131,6 @@ class VideoCaptureMachine {
// |callback| is invoked after the capturing has stopped.
virtual void Stop(const base::Closure& callback) = 0;
- protected:
- bool started_;
-
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureMachine);
};
@@ -144,7 +139,7 @@ class VideoCaptureMachine {
//
// Separating this from the "shell classes" WebContentsVideoCaptureDevice and
// DesktopCaptureDeviceAura allows safe destruction without needing to block any
-// threads (e.g., the IO BrowserThread), as well as code sharing.
+// threads, as well as code sharing.
//
// ContentVideoCaptureDeviceCore manages a simple state machine and the pipeline
// (see notes at top of this file). It times the start of successive captures
@@ -172,8 +167,8 @@ class CONTENT_EXPORT ContentVideoCaptureDeviceCore
void TransitionStateTo(State next_state);
- // Called on the IO thread in response to StartCaptureMachine().
- // |success| is true if capture machine succeeded to start.
+ // Called back in response to StartCaptureMachine(). |success| is true if
+ // capture machine succeeded to start.
void CaptureStarted(bool success);
// Stops capturing and notifies client_ of an error state.
@@ -192,7 +187,7 @@ class CONTENT_EXPORT ContentVideoCaptureDeviceCore
// Our thread-safe capture oracle which serves as the gateway to the video
// capture pipeline. Besides the VideoCaptureDevice itself, it is the only
- // component of the/ system with direct access to |client_|.
+ // component of the system with direct access to |client_|.
scoped_refptr<ThreadSafeCaptureOracle> oracle_proxy_;
DISALLOW_COPY_AND_ASSIGN(ContentVideoCaptureDeviceCore);
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index cf180c9db26..c77ee0cc4c3 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -7,16 +7,15 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
-#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread.h"
+#include "base/timer/timer.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/power_save_blocker.h"
#include "media/base/video_util.h"
#include "third_party/libyuv/include/libyuv/scale_argb.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h"
@@ -49,35 +48,24 @@ webrtc::DesktopRect ComputeLetterboxRect(
} // namespace
-class DesktopCaptureDevice::Core
- : public base::RefCountedThreadSafe<Core>,
- public webrtc::DesktopCapturer::Callback {
+class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
public:
- Core(scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<base::Thread> thread,
+ Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer,
DesktopMediaID::Type type);
+ ~Core() override;
// Implementation of VideoCaptureDevice methods.
void AllocateAndStart(const media::VideoCaptureParams& params,
scoped_ptr<Client> client);
- void StopAndDeAllocate();
void SetNotificationWindowId(gfx::NativeViewId window_id);
private:
- friend class base::RefCountedThreadSafe<Core>;
- virtual ~Core();
// webrtc::DesktopCapturer::Callback interface
- virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
- virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE;
-
- // Helper methods that run on the |task_runner_|. Posted from the
- // corresponding public methods.
- void DoAllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client);
- void DoStopAndDeAllocate();
+ webrtc::SharedMemory* CreateSharedMemory(size_t size) override;
+ void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
// Chooses new output properties based on the supplied source size and the
// properties requested to Allocate(), and dispatches OnFrameInfo[Changed]
@@ -94,13 +82,8 @@ class DesktopCaptureDevice::Core
// Captures a single frame.
void DoCapture();
- void DoSetNotificationWindowId(gfx::NativeViewId window_id);
-
// Task runner used for capturing operations.
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- // The thread on which the capturer is running.
- scoped_ptr<base::Thread> thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// The underlying DesktopCapturer instance used to capture frames.
scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_;
@@ -127,9 +110,8 @@ class DesktopCaptureDevice::Core
// and/or letterboxed.
webrtc::DesktopRect output_rect_;
- // True when we have delayed OnCaptureTimer() task posted on
- // |task_runner_|.
- bool capture_task_posted_;
+ // Timer used to capture the frame.
+ base::OneShotTimer<Core> capture_timer_;
// True when waiting for |desktop_capturer_| to capture current frame.
bool capture_in_progress_;
@@ -143,50 +125,64 @@ class DesktopCaptureDevice::Core
scoped_ptr<webrtc::BasicDesktopFrame> black_frame_;
+ // TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
+ // screen from sleeping for the drive-by web.
+ scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+
DISALLOW_COPY_AND_ASSIGN(Core);
};
DesktopCaptureDevice::Core::Core(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<base::Thread> thread,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
scoped_ptr<webrtc::DesktopCapturer> capturer,
DesktopMediaID::Type type)
: task_runner_(task_runner),
- thread_(thread.Pass()),
desktop_capturer_(capturer.Pass()),
- capture_task_posted_(false),
capture_in_progress_(false),
first_capture_returned_(false),
capturer_type_(type) {
- DCHECK(!task_runner_.get() || !thread_.get());
- if (thread_.get())
- task_runner_ = thread_->message_loop_proxy();
}
DesktopCaptureDevice::Core::~Core() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ client_.reset();
+ output_frame_.reset();
+ previous_frame_size_.set(0, 0);
+ desktop_capturer_.reset();
}
void DesktopCaptureDevice::Core::AllocateAndStart(
const media::VideoCaptureParams& params,
scoped_ptr<Client> client) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_GT(params.requested_format.frame_size.GetArea(), 0);
DCHECK_GT(params.requested_format.frame_rate, 0);
+ DCHECK(desktop_capturer_);
+ DCHECK(client.get());
+ DCHECK(!client_.get());
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &Core::DoAllocateAndStart, this, params, base::Passed(&client)));
-}
+ client_ = client.Pass();
+ requested_params_ = params;
-void DesktopCaptureDevice::Core::StopAndDeAllocate() {
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&Core::DoStopAndDeAllocate, this));
+ capture_format_ = requested_params_.requested_format;
+
+ // This capturer always outputs ARGB, non-interlaced.
+ capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
+
+ power_save_blocker_.reset(PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ "DesktopCaptureDevice is running").release());
+
+ desktop_capturer_->Start(this);
+
+ CaptureFrameAndScheduleNext();
}
void DesktopCaptureDevice::Core::SetNotificationWindowId(
gfx::NativeViewId window_id) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&Core::DoSetNotificationWindowId, this, window_id));
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(window_id);
+ desktop_capturer_->SetExcludedWindow(window_id);
}
webrtc::SharedMemory*
@@ -196,7 +192,7 @@ DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) {
void DesktopCaptureDevice::Core::OnCaptureCompleted(
webrtc::DesktopFrame* frame) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(capture_in_progress_);
if (!first_capture_returned_) {
@@ -224,10 +220,14 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
base::TimeDelta capture_time(
base::TimeDelta::FromMilliseconds(frame->capture_time_ms()));
- UMA_HISTOGRAM_TIMES(
- capturer_type_ == DesktopMediaID::TYPE_SCREEN ? kUmaScreenCaptureTime
- : kUmaWindowCaptureTime,
- capture_time);
+
+ // The two UMA_ blocks must be put in its own scope since it creates a static
+ // variable which expected constant histogram name.
+ if (capturer_type_ == DesktopMediaID::TYPE_SCREEN) {
+ UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
+ } else {
+ UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
+ }
scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
@@ -309,35 +309,6 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
output_data, output_bytes, capture_format_, 0, base::TimeTicks::Now());
}
-void DesktopCaptureDevice::Core::DoAllocateAndStart(
- const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(desktop_capturer_);
- DCHECK(client.get());
- DCHECK(!client_.get());
-
- client_ = client.Pass();
- requested_params_ = params;
-
- capture_format_ = requested_params_.requested_format;
-
- // This capturer always outputs ARGB, non-interlaced.
- capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
-
- desktop_capturer_->Start(this);
-
- CaptureFrameAndScheduleNext();
-}
-
-void DesktopCaptureDevice::Core::DoStopAndDeAllocate() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- client_.reset();
- output_frame_.reset();
- previous_frame_size_.set(0, 0);
- desktop_capturer_.reset();
-}
-
void DesktopCaptureDevice::Core::RefreshCaptureFormat(
const webrtc::DesktopSize& frame_size) {
if (previous_frame_size_.equals(frame_size))
@@ -348,7 +319,8 @@ void DesktopCaptureDevice::Core::RefreshCaptureFormat(
output_frame_.reset();
if (previous_frame_size_.is_empty() ||
- requested_params_.allow_resolution_change) {
+ requested_params_.resolution_change_policy ==
+ media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT) {
// If this is the first frame, or the receiver supports variable resolution
// then determine the output size by treating the requested width & height
// as maxima.
@@ -380,8 +352,7 @@ void DesktopCaptureDevice::Core::RefreshCaptureFormat(
}
void DesktopCaptureDevice::Core::OnCaptureTimer() {
- DCHECK(capture_task_posted_);
- capture_task_posted_ = false;
+ DCHECK(task_runner_->BelongsToCurrentThread());
if (!client_)
return;
@@ -390,8 +361,7 @@ void DesktopCaptureDevice::Core::OnCaptureTimer() {
}
void DesktopCaptureDevice::Core::CaptureFrameAndScheduleNext() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(!capture_task_posted_);
+ DCHECK(task_runner_->BelongsToCurrentThread());
base::TimeTicks started_time = base::TimeTicks::Now();
DoCapture();
@@ -403,14 +373,12 @@ void DesktopCaptureDevice::Core::CaptureFrameAndScheduleNext() {
base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
// Schedule a task for the next frame.
- capture_task_posted_ = true;
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&Core::OnCaptureTimer, this),
- capture_period - last_capture_duration);
+ capture_timer_.Start(FROM_HERE, capture_period - last_capture_duration,
+ this, &Core::OnCaptureTimer);
}
void DesktopCaptureDevice::Core::DoCapture() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!capture_in_progress_);
capture_in_progress_ = true;
@@ -421,18 +389,9 @@ void DesktopCaptureDevice::Core::DoCapture() {
DCHECK(!capture_in_progress_);
}
-void DesktopCaptureDevice::Core::DoSetNotificationWindowId(
- gfx::NativeViewId window_id) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(window_id);
- desktop_capturer_->SetExcludedWindow(window_id);
-}
-
// static
scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
const DesktopMediaID& source) {
- scoped_ptr<base::Thread> ui_thread;
-
webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault();
// Leave desktop effects enabled during WebRTC captures.
@@ -442,24 +401,11 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
switch (source.type) {
case DesktopMediaID::TYPE_SCREEN: {
- scoped_ptr<webrtc::ScreenCapturer> screen_capturer;
-
#if defined(OS_WIN)
- bool magnification_allowed =
- base::FieldTrialList::FindFullName("ScreenCaptureUseMagnification") ==
- "Enabled";
-
- if (magnification_allowed) {
- // The magnification capturer requires running on a dedicated UI thread.
- ui_thread.reset(new base::Thread("screenCaptureUIThread"));
- base::Thread::Options thread_options(base::MessageLoop::TYPE_UI, 0);
- ui_thread->StartWithOptions(thread_options);
-
- options.set_allow_use_magnification_api(true);
- }
+ options.set_allow_use_magnification_api(true);
#endif
-
- screen_capturer.reset(webrtc::ScreenCapturer::Create(options));
+ scoped_ptr<webrtc::ScreenCapturer> screen_capturer(
+ webrtc::ScreenCapturer::Create(options));
if (screen_capturer && screen_capturer->SelectScreen(source.id)) {
capturer.reset(new webrtc::DesktopAndCursorComposer(
screen_capturer.release(),
@@ -477,7 +423,7 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
capturer.reset(new webrtc::DesktopAndCursorComposer(
window_capturer.release(),
webrtc::MouseCursorMonitor::CreateForWindow(options, source.id)));
- IncrementDesktopCaptureCounter(WINDOW_CATPTURER_CREATED);
+ IncrementDesktopCaptureCounter(WINDOW_CAPTURER_CREATED);
}
break;
}
@@ -488,46 +434,54 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
}
scoped_ptr<media::VideoCaptureDevice> result;
- if (capturer) {
- scoped_refptr<base::SequencedTaskRunner> task_runner;
- if (!ui_thread.get()) {
- scoped_refptr<base::SequencedWorkerPool> blocking_pool =
- BrowserThread::GetBlockingPool();
- task_runner = blocking_pool->GetSequencedTaskRunner(
- blocking_pool->GetSequenceToken());
- }
- result.reset(new DesktopCaptureDevice(
- task_runner, ui_thread.Pass(), capturer.Pass(), source.type));
- }
+ if (capturer)
+ result.reset(new DesktopCaptureDevice(capturer.Pass(), source.type));
return result.Pass();
}
DesktopCaptureDevice::~DesktopCaptureDevice() {
- StopAndDeAllocate();
+ DCHECK(!core_);
}
void DesktopCaptureDevice::AllocateAndStart(
const media::VideoCaptureParams& params,
scoped_ptr<Client> client) {
- core_->AllocateAndStart(params, client.Pass());
+ thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&Core::AllocateAndStart, base::Unretained(core_.get()), params,
+ base::Passed(&client)));
}
void DesktopCaptureDevice::StopAndDeAllocate() {
- core_->StopAndDeAllocate();
+ if (core_) {
+ thread_.message_loop_proxy()->DeleteSoon(FROM_HERE, core_.release());
+ thread_.Stop();
+ }
}
void DesktopCaptureDevice::SetNotificationWindowId(
gfx::NativeViewId window_id) {
- core_->SetNotificationWindowId(window_id);
+ thread_.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&Core::SetNotificationWindowId, base::Unretained(core_.get()),
+ window_id));
}
DesktopCaptureDevice::DesktopCaptureDevice(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<base::Thread> thread,
scoped_ptr<webrtc::DesktopCapturer> capturer,
DesktopMediaID::Type type)
- : core_(new Core(task_runner, thread.Pass(), capturer.Pass(), type)) {
+ : thread_("desktopCaptureThread") {
+#if defined(OS_WIN)
+ // On Windows the thread must be a UI thread.
+ base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_UI;
+#else
+ base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT;
+#endif
+
+ thread_.StartWithOptions(base::Thread::Options(thread_type, 0));
+
+ core_.reset(new Core(thread_.message_loop_proxy(), capturer.Pass(), type));
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.h b/chromium/content/browser/media/capture/desktop_capture_device.h
index 9fb8ca419fa..a9c3f000b3c 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device.h
@@ -7,13 +7,14 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/public/browser/desktop_media_id.h"
#include "media/video/capture/video_capture_device.h"
#include "ui/gfx/native_widget_types.h"
namespace base {
-class SequencedTaskRunner;
+class SingleThreadTaskRunner;
class Thread;
} // namespace base
@@ -34,12 +35,12 @@ class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
static scoped_ptr<media::VideoCaptureDevice> Create(
const DesktopMediaID& source);
- virtual ~DesktopCaptureDevice();
+ ~DesktopCaptureDevice() override;
// VideoCaptureDevice interface.
- virtual void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) OVERRIDE;
- virtual void StopAndDeAllocate() OVERRIDE;
+ void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) override;
+ void StopAndDeAllocate() override;
// Set the platform-dependent window id for the notification window.
void SetNotificationWindowId(gfx::NativeViewId window_id);
@@ -48,13 +49,11 @@ class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
friend class DesktopCaptureDeviceTest;
class Core;
- // Either |task_runner| or |thread| should be non-NULL, but not both.
- DesktopCaptureDevice(scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<base::Thread> thread,
- scoped_ptr<webrtc::DesktopCapturer> desktop_capturer,
+ DesktopCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> desktop_capturer,
DesktopMediaID::Type type);
- scoped_refptr<Core> core_;
+ base::Thread thread_;
+ scoped_ptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDevice);
};
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
index 08aec1eba2e..6b6557f1844 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
@@ -14,7 +14,7 @@
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/common/gpu/client/gl_helper.h"
#include "content/public/browser/browser_thread.h"
-#include "media/base/bind_to_current_loop.h"
+#include "content/public/browser/power_save_blocker.h"
#include "media/base/video_util.h"
#include "media/video/capture/video_capture_types.h"
#include "skia/ext/image_operations.h"
@@ -47,7 +47,7 @@ void RenderCursorOnVideoFrame(
const scoped_refptr<media::VideoFrame>& target,
const SkBitmap& cursor_bitmap,
const gfx::Point& cursor_position) {
- DCHECK(target);
+ DCHECK(target.get());
DCHECK(!cursor_bitmap.isNull());
gfx::Rect rect = gfx::IntersectRects(
@@ -96,30 +96,29 @@ class DesktopVideoCaptureMachine
public base::SupportsWeakPtr<DesktopVideoCaptureMachine> {
public:
DesktopVideoCaptureMachine(const DesktopMediaID& source);
- virtual ~DesktopVideoCaptureMachine();
+ ~DesktopVideoCaptureMachine() override;
// VideoCaptureFrameSource overrides.
- virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params) OVERRIDE;
- virtual void Stop(const base::Closure& callback) OVERRIDE;
+ bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
+ const media::VideoCaptureParams& params) override;
+ void Stop(const base::Closure& callback) override;
// Implements aura::WindowObserver.
- virtual void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE;
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
- virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE;
- virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
- aura::Window* new_root) OVERRIDE;
+ void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
+ void OnWindowDestroyed(aura::Window* window) override;
+ void OnWindowAddedToRootWindow(aura::Window* window) override;
+ void OnWindowRemovingFromRootWindow(aura::Window* window,
+ aura::Window* new_root) override;
// Implements ui::CompositorObserver.
- virtual void OnCompositingDidCommit(ui::Compositor* compositor) OVERRIDE {}
- virtual void OnCompositingStarted(ui::Compositor* compositor,
- base::TimeTicks start_time) OVERRIDE {}
- virtual void OnCompositingEnded(ui::Compositor* compositor) OVERRIDE;
- virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE {}
- virtual void OnCompositingLockStateChanged(
- ui::Compositor* compositor) OVERRIDE {}
+ void OnCompositingDidCommit(ui::Compositor* compositor) override {}
+ void OnCompositingStarted(ui::Compositor* compositor,
+ base::TimeTicks start_time) override {}
+ void OnCompositingEnded(ui::Compositor* compositor) override;
+ void OnCompositingAborted(ui::Compositor* compositor) override {}
+ void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
private:
// Captures a frame.
@@ -175,6 +174,10 @@ class DesktopVideoCaptureMachine
gfx::Point cursor_hot_point_;
SkBitmap scaled_cursor_bitmap_;
+ // TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
+ // screen from sleeping for the drive-by web.
+ scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+
DISALLOW_COPY_AND_ASSIGN(DesktopVideoCaptureMachine);
};
@@ -214,17 +217,21 @@ bool DesktopVideoCaptureMachine::Start(
if (desktop_window_->GetHost())
desktop_window_->GetHost()->compositor()->AddObserver(this);
+ power_save_blocker_.reset(PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
+ "DesktopCaptureDevice is running").release());
+
// Starts timer.
- timer_.Start(FROM_HERE, oracle_proxy_->capture_period(),
+ timer_.Start(FROM_HERE, oracle_proxy_->min_capture_period(),
base::Bind(&DesktopVideoCaptureMachine::Capture, AsWeakPtr(),
false));
- started_ = true;
return true;
}
void DesktopVideoCaptureMachine::Stop(const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ power_save_blocker_.reset();
// Stop observing compositor and window events.
if (desktop_window_) {
@@ -237,17 +244,15 @@ void DesktopVideoCaptureMachine::Stop(const base::Closure& callback) {
// Stop timer.
timer_.Stop();
- started_ = false;
-
callback.Run();
}
void DesktopVideoCaptureMachine::UpdateCaptureSize() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (oracle_proxy_ && desktop_window_) {
- ui::Layer* layer = desktop_window_->layer();
- oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel(
- layer, layer->bounds().size()));
+ if (oracle_proxy_.get() && desktop_window_) {
+ ui::Layer* layer = desktop_window_->layer();
+ oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel(
+ layer, layer->bounds().size()));
}
ClearCursorState();
}
@@ -267,15 +272,13 @@ void DesktopVideoCaptureMachine::Capture(bool dirty) {
dirty ? VideoCaptureOracle::kCompositorUpdate
: VideoCaptureOracle::kTimerPoll;
if (oracle_proxy_->ObserveEventAndDecideCapture(
- event, start_time, &frame, &capture_frame_cb)) {
+ event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) {
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(
base::Bind(&DesktopVideoCaptureMachine::DidCopyOutput,
AsWeakPtr(), frame, start_time, capture_frame_cb));
- gfx::Rect window_rect =
- ui::ConvertRectToPixel(desktop_window_->layer(),
- gfx::Rect(desktop_window_->bounds().width(),
- desktop_window_->bounds().height()));
+ gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(),
+ desktop_window_->bounds().height());
request->set_area(window_rect);
desktop_window_->layer()->RequestCopyOfOutput(request.Pass());
}
@@ -296,14 +299,8 @@ void CopyOutputFinishedForVideo(
}
void RunSingleReleaseCallback(scoped_ptr<cc::SingleReleaseCallback> cb,
- const std::vector<uint32>& sync_points) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
- DCHECK(gl_helper);
- for (unsigned i = 0; i < sync_points.size(); i++)
- gl_helper->WaitSyncPoint(sync_points[i]);
- uint32 new_sync_point = gl_helper->InsertSyncPoint();
- cb->Run(new_sync_point, false);
+ uint32 sync_point) {
+ cb->Run(sync_point, false);
}
void DesktopVideoCaptureMachine::DidCopyOutput(
@@ -317,10 +314,14 @@ void DesktopVideoCaptureMachine::DidCopyOutput(
video_frame, start_time, capture_frame_cb, result.Pass());
base::TimeDelta capture_time = base::TimeTicks::Now() - start_time;
- UMA_HISTOGRAM_TIMES(
- window_id_.type == DesktopMediaID::TYPE_SCREEN ? kUmaScreenCaptureTime
- : kUmaWindowCaptureTime,
- capture_time);
+
+ // The two UMA_ blocks must be put in its own scope since it creates a static
+ // variable which expected constant histogram name.
+ if (window_id_.type == DesktopMediaID::TYPE_SCREEN) {
+ UMA_HISTOGRAM_TIMES(kUmaScreenCaptureTime, capture_time);
+ } else {
+ UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
+ }
if (first_call) {
first_call = false;
@@ -330,7 +331,7 @@ void DesktopVideoCaptureMachine::DidCopyOutput(
} else {
IncrementDesktopCaptureCounter(succeeded
? FIRST_WINDOW_CAPTURE_SUCCEEDED
- : FIRST_WINDOW_CAPTURE_SUCCEEDED);
+ : FIRST_WINDOW_CAPTURE_FAILED);
}
}
}
@@ -346,7 +347,7 @@ bool DesktopVideoCaptureMachine::ProcessCopyOutputResponse(
if (capture_params_.requested_format.pixel_format ==
media::PIXEL_FORMAT_TEXTURE) {
- DCHECK(!video_frame);
+ DCHECK(!video_frame.get());
cc::TextureMailbox texture_mailbox;
scoped_ptr<cc::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
@@ -357,8 +358,7 @@ bool DesktopVideoCaptureMachine::ProcessCopyOutputResponse(
make_scoped_ptr(new gpu::MailboxHolder(texture_mailbox.mailbox(),
texture_mailbox.target(),
texture_mailbox.sync_point())),
- media::BindToCurrentLoop(base::Bind(&RunSingleReleaseCallback,
- base::Passed(&release_callback))),
+ base::Bind(&RunSingleReleaseCallback, base::Passed(&release_callback)),
result->size(),
gfx::Rect(result->size()),
result->size(),
@@ -523,7 +523,7 @@ media::VideoCaptureDevice* DesktopCaptureDeviceAura::Create(
const DesktopMediaID& source) {
IncrementDesktopCaptureCounter(source.type == DesktopMediaID::TYPE_SCREEN
? SCREEN_CAPTURER_CREATED
- : WINDOW_CATPTURER_CREATED);
+ : WINDOW_CAPTURER_CREATED);
return new DesktopCaptureDeviceAura(source);
}
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.h b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
index 997b3ce3a00..8f3540a7fd6 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
@@ -27,12 +27,12 @@ class CONTENT_EXPORT DesktopCaptureDeviceAura
// Creates a VideoCaptureDevice for the Aura desktop.
static media::VideoCaptureDevice* Create(const DesktopMediaID& source);
- virtual ~DesktopCaptureDeviceAura();
+ ~DesktopCaptureDeviceAura() override;
// VideoCaptureDevice implementation.
- virtual void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) OVERRIDE;
- virtual void StopAndDeAllocate() OVERRIDE;
+ void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) override;
+ void StopAndDeAllocate() override;
private:
DesktopCaptureDeviceAura(const DesktopMediaID& source);
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
index 3cfccf0de54..81cbd15b20e 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -60,7 +60,7 @@ class DesktopCaptureDeviceAuraTest : public testing::Test {
virtual ~DesktopCaptureDeviceAuraTest() {}
protected:
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
// The ContextFactory must exist before any Compositors are created.
bool enable_pixel_output = false;
ui::ContextFactory* context_factory =
@@ -82,7 +82,7 @@ class DesktopCaptureDeviceAuraTest : public testing::Test {
desktop_window_->Show();
}
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
helper_->RunAllPendingInMessageLoop();
root_window()->RemoveChild(desktop_window_.get());
desktop_window_.reset();
@@ -115,9 +115,7 @@ TEST_F(DesktopCaptureDeviceAuraTest, StartAndStop) {
capture_params.requested_format.frame_size.SetSize(640, 480);
capture_params.requested_format.frame_rate = kFrameRate;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
- capture_device->AllocateAndStart(
- capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
+ capture_device->AllocateAndStart(capture_params, client.Pass());
capture_device->StopAndDeAllocate();
}
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h b/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
index 0994fcd3150..0058e9121ec 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
@@ -12,7 +12,7 @@ namespace content {
// DESKTOP_CAPTURE_COUNTER_BOUNDARY.
enum DesktopCaptureCounters {
SCREEN_CAPTURER_CREATED,
- WINDOW_CATPTURER_CREATED,
+ WINDOW_CAPTURER_CREATED,
FIRST_SCREEN_CAPTURE_SUCCEEDED,
FIRST_SCREEN_CAPTURE_FAILED,
FIRST_WINDOW_CAPTURE_SUCCEEDED,
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
index 0c1a360e292..0388043642f 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -4,13 +4,13 @@
#include "content/browser/media/capture/desktop_capture_device.h"
+#include <string>
+
#include "base/basictypes.h"
-#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "base/threading/thread.h"
#include "base/time/time.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
@@ -63,9 +63,10 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
class InvertedDesktopFrame : public webrtc::DesktopFrame {
public:
// Takes ownership of |frame|.
- InvertedDesktopFrame(webrtc::DesktopFrame* frame)
+ explicit InvertedDesktopFrame(webrtc::DesktopFrame* frame)
: webrtc::DesktopFrame(
- frame->size(), -frame->stride(),
+ frame->size(),
+ -frame->stride(),
frame->data() + (frame->size().height() - 1) * frame->stride(),
frame->shared_memory()),
original_frame_(frame) {
@@ -73,7 +74,7 @@ class InvertedDesktopFrame : public webrtc::DesktopFrame {
set_capture_time_ms(frame->capture_time_ms());
mutable_updated_region()->Swap(frame->mutable_updated_region());
}
- virtual ~InvertedDesktopFrame() {}
+ ~InvertedDesktopFrame() override {}
private:
scoped_ptr<webrtc::DesktopFrame> original_frame_;
@@ -89,18 +90,16 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
frame_index_(0),
generate_inverted_frames_(false) {
}
- virtual ~FakeScreenCapturer() {}
+ ~FakeScreenCapturer() override {}
void set_generate_inverted_frames(bool generate_inverted_frames) {
generate_inverted_frames_ = generate_inverted_frames;
}
// VideoFrameCapturer interface.
- virtual void Start(Callback* callback) OVERRIDE {
- callback_ = callback;
- }
+ void Start(Callback* callback) override { callback_ = callback; }
- virtual void Capture(const webrtc::DesktopRegion& region) OVERRIDE {
+ void Capture(const webrtc::DesktopRegion& region) override {
webrtc::DesktopSize size;
if (frame_index_ % 2 == 0) {
size = webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1);
@@ -115,17 +114,12 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
callback_->OnCaptureCompleted(frame);
}
- virtual void SetMouseShapeObserver(
- MouseShapeObserver* mouse_shape_observer) OVERRIDE {
- }
+ void SetMouseShapeObserver(
+ MouseShapeObserver* mouse_shape_observer) override {}
- virtual bool GetScreenList(ScreenList* screens) OVERRIDE {
- return false;
- }
+ bool GetScreenList(ScreenList* screens) override { return false; }
- virtual bool SelectScreen(webrtc::ScreenId id) OVERRIDE {
- return false;
- }
+ bool SelectScreen(webrtc::ScreenId id) override { return false; }
private:
Callback* callback_;
@@ -137,21 +131,12 @@ class FakeScreenCapturer : public webrtc::ScreenCapturer {
class DesktopCaptureDeviceTest : public testing::Test {
public:
- virtual void SetUp() OVERRIDE {
- worker_pool_ = new base::SequencedWorkerPool(3, "TestCaptureThread");
- }
-
void CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> capturer) {
- capture_device_.reset(new DesktopCaptureDevice(
- worker_pool_->GetSequencedTaskRunner(worker_pool_->GetSequenceToken()),
- thread_.Pass(),
- capturer.Pass(),
- DesktopMediaID::TYPE_SCREEN));
+ capture_device_.reset(
+ new DesktopCaptureDevice(capturer.Pass(), DesktopMediaID::TYPE_SCREEN));
}
protected:
- scoped_refptr<base::SequencedWorkerPool> worker_pool_;
- scoped_ptr<base::Thread> thread_;
scoped_ptr<DesktopCaptureDevice> capture_device_;
};
@@ -183,9 +168,7 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
capture_params.requested_format.frame_size.SetSize(640, 480);
capture_params.requested_format.frame_rate = kFrameRate;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
- capture_device_->AllocateAndStart(
- capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
+ capture_device_->AllocateAndStart(capture_params, client.Pass());
EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout()));
capture_device_->StopAndDeAllocate();
@@ -195,7 +178,6 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size);
- worker_pool_->FlushForTesting();
}
// Test that screen capturer behaves correctly if the source frame size changes
@@ -221,10 +203,8 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
kTestFrameHeight1);
capture_params.requested_format.frame_rate = kFrameRate;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
- capture_device_->AllocateAndStart(
- capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
+ capture_device_->AllocateAndStart(capture_params, client.Pass());
// Capture at least two frames, to ensure that the source frame size has
// changed while capturing.
@@ -240,7 +220,6 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size);
- worker_pool_->FlushForTesting();
}
// Test that screen capturer behaves correctly if the source frame size changes
@@ -264,10 +243,9 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
kTestFrameHeight2);
capture_params.requested_format.frame_rate = kFrameRate;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
capture_device_->AllocateAndStart(
- capture_params, client.PassAs<media::VideoCaptureDevice::Client>());
+ capture_params, client.Pass());
// Capture at least three frames, to ensure that the source frame size has
// changed at least twice while capturing.
@@ -283,7 +261,6 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
EXPECT_EQ(kTestFrameHeight1, format.frame_size.height());
EXPECT_EQ(kFrameRate, format.frame_rate);
EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format);
- worker_pool_->FlushForTesting();
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/video_capture_oracle.cc b/chromium/content/browser/media/capture/video_capture_oracle.cc
index c41e5e7e0b1..142bfe604c5 100644
--- a/chromium/content/browser/media/capture/video_capture_oracle.cc
+++ b/chromium/content/browser/media/capture/video_capture_oracle.cc
@@ -4,7 +4,11 @@
#include "content/browser/media/capture/video_capture_oracle.h"
+#include <algorithm>
+
#include "base/debug/trace_event.h"
+#include "base/format_macros.h"
+#include "base/strings/stringprintf.h"
namespace content {
@@ -21,75 +25,167 @@ namespace {
// further into the WebRTC encoding stack.
const int kNumRedundantCapturesOfStaticContent = 200;
+// These specify the minimum/maximum amount of recent event history to examine
+// to detect animated content. If the values are too low, there is a greater
+// risk of false-positive detections and low accuracy. If they are too high,
+// the the implementation will be slow to lock-in/out, and also will not react
+// well to mildly-variable frame rate content (e.g., 25 +/- 1 FPS).
+//
+// These values were established by experimenting with a wide variety of
+// scenarios, including 24/25/30 FPS videos, 60 FPS WebGL demos, and the
+// transitions between static and animated content.
+const int kMinObservationWindowMillis = 1000;
+const int kMaxObservationWindowMillis = 2000;
+
+// The maximum amount of time that can elapse before declaring two subsequent
+// events as "not animating." This is the same value found in
+// cc::FrameRateCounter.
+const int kNonAnimatingThresholdMillis = 250; // 4 FPS
+
+// The slowest that content can be animating in order for AnimatedContentSampler
+// to lock-in. This is the threshold at which the "smoothness" problem is no
+// longer relevant.
+const int kMaxLockInPeriodMicros = 83333; // 12 FPS
+
+// The amount of time over which to fully correct the drift of the rewritten
+// frame timestamps from the presentation event timestamps. The lower the
+// value, the higher the variance in frame timestamps.
+const int kDriftCorrectionMillis = 6000;
+
+// Given the amount of time between frames, compare to the expected amount of
+// time between frames at |frame_rate| and return the fractional difference.
+double FractionFromExpectedFrameRate(base::TimeDelta delta, int frame_rate) {
+ DCHECK_GT(frame_rate, 0);
+ const base::TimeDelta expected_delta =
+ base::TimeDelta::FromSeconds(1) / frame_rate;
+ return (delta - expected_delta).InMillisecondsF() /
+ expected_delta.InMillisecondsF();
+}
+
} // anonymous namespace
-VideoCaptureOracle::VideoCaptureOracle(base::TimeDelta capture_period,
+VideoCaptureOracle::VideoCaptureOracle(base::TimeDelta min_capture_period,
bool events_are_reliable)
- : capture_period_(capture_period),
- frame_number_(0),
- last_delivered_frame_number_(0),
- sampler_(capture_period_,
- events_are_reliable,
- kNumRedundantCapturesOfStaticContent) {}
+ : frame_number_(0),
+ last_delivered_frame_number_(-1),
+ smoothing_sampler_(min_capture_period,
+ events_are_reliable,
+ kNumRedundantCapturesOfStaticContent),
+ content_sampler_(min_capture_period) {
+}
+
+VideoCaptureOracle::~VideoCaptureOracle() {}
bool VideoCaptureOracle::ObserveEventAndDecideCapture(
Event event,
+ const gfx::Rect& damage_rect,
base::TimeTicks event_time) {
- // Record |event| and decide whether it's a good time to capture.
- const bool content_is_dirty = (event == kCompositorUpdate ||
- event == kSoftwarePaint);
+ DCHECK_GE(event, 0);
+ DCHECK_LT(event, kNumEvents);
+ if (event_time < last_event_time_[event]) {
+ LOG(WARNING) << "Event time is not monotonically non-decreasing. "
+ << "Deciding not to capture this frame.";
+ return false;
+ }
+ last_event_time_[event] = event_time;
+
bool should_sample;
- if (content_is_dirty) {
- frame_number_++;
- should_sample = sampler_.AddEventAndConsiderSampling(event_time);
- } else {
- should_sample = sampler_.IsOverdueForSamplingAt(event_time);
+ switch (event) {
+ case kCompositorUpdate:
+ case kSoftwarePaint:
+ smoothing_sampler_.ConsiderPresentationEvent(event_time);
+ content_sampler_.ConsiderPresentationEvent(damage_rect, event_time);
+ if (content_sampler_.HasProposal()) {
+ should_sample = content_sampler_.ShouldSample();
+ if (should_sample)
+ event_time = content_sampler_.frame_timestamp();
+ } else {
+ should_sample = smoothing_sampler_.ShouldSample();
+ }
+ break;
+ default:
+ should_sample = smoothing_sampler_.IsOverdueForSamplingAt(event_time);
+ break;
}
+
+ SetFrameTimestamp(frame_number_, event_time);
return should_sample;
}
int VideoCaptureOracle::RecordCapture() {
- sampler_.RecordSample();
- return frame_number_;
+ smoothing_sampler_.RecordSample();
+ content_sampler_.RecordSample(GetFrameTimestamp(frame_number_));
+ return frame_number_++;
}
bool VideoCaptureOracle::CompleteCapture(int frame_number,
- base::TimeTicks timestamp) {
- // Drop frame if previous frame number is higher or we're trying to deliver
- // a frame with the same timestamp.
- if (last_delivered_frame_number_ > frame_number ||
- last_delivered_frame_timestamp_ == timestamp) {
- LOG(ERROR) << "Frame with same timestamp or out of order delivery. "
- << "Dropping frame.";
+ base::TimeTicks* frame_timestamp) {
+ // Drop frame if previous frame number is higher.
+ if (last_delivered_frame_number_ > frame_number) {
+ LOG(WARNING) << "Out of order frame delivery detected. Dropping frame.";
return false;
}
+ last_delivered_frame_number_ = frame_number;
+
+ *frame_timestamp = GetFrameTimestamp(frame_number);
- if (last_delivered_frame_timestamp_ > timestamp) {
- // We should not get here unless time was adjusted backwards.
- LOG(ERROR) << "Frame with past timestamp (" << timestamp.ToInternalValue()
- << ") was delivered";
+ // If enabled, log a measurement of how this frame timestamp has incremented
+ // in relation to an ideal increment.
+ if (VLOG_IS_ON(2) && frame_number > 0) {
+ const base::TimeDelta delta =
+ *frame_timestamp - GetFrameTimestamp(frame_number - 1);
+ if (content_sampler_.HasProposal()) {
+ const double estimated_frame_rate =
+ 1000000.0 / content_sampler_.detected_period().InMicroseconds();
+ const int rounded_frame_rate =
+ static_cast<int>(estimated_frame_rate + 0.5);
+ VLOG(2) << base::StringPrintf(
+ "Captured #%d: delta=%" PRId64 " usec"
+ ", now locked into {%s}, %+0.1f%% slower than %d FPS",
+ frame_number,
+ delta.InMicroseconds(),
+ content_sampler_.detected_region().ToString().c_str(),
+ 100.0 * FractionFromExpectedFrameRate(delta, rounded_frame_rate),
+ rounded_frame_rate);
+ } else {
+ VLOG(2) << base::StringPrintf(
+ "Captured #%d: delta=%" PRId64 " usec"
+ ", d/30fps=%+0.1f%%, d/25fps=%+0.1f%%, d/24fps=%+0.1f%%",
+ frame_number,
+ delta.InMicroseconds(),
+ 100.0 * FractionFromExpectedFrameRate(delta, 30),
+ 100.0 * FractionFromExpectedFrameRate(delta, 25),
+ 100.0 * FractionFromExpectedFrameRate(delta, 24));
+ }
}
- last_delivered_frame_number_ = frame_number;
- last_delivered_frame_timestamp_ = timestamp;
+ return !frame_timestamp->is_null();
+}
- return true;
+base::TimeTicks VideoCaptureOracle::GetFrameTimestamp(int frame_number) const {
+ DCHECK_LE(frame_number, frame_number_);
+ DCHECK_LT(frame_number_ - frame_number, kMaxFrameTimestamps);
+ return frame_timestamps_[frame_number % kMaxFrameTimestamps];
}
-SmoothEventSampler::SmoothEventSampler(base::TimeDelta capture_period,
+void VideoCaptureOracle::SetFrameTimestamp(int frame_number,
+ base::TimeTicks timestamp) {
+ frame_timestamps_[frame_number % kMaxFrameTimestamps] = timestamp;
+}
+
+SmoothEventSampler::SmoothEventSampler(base::TimeDelta min_capture_period,
bool events_are_reliable,
int redundant_capture_goal)
: events_are_reliable_(events_are_reliable),
- capture_period_(capture_period),
+ min_capture_period_(min_capture_period),
redundant_capture_goal_(redundant_capture_goal),
- token_bucket_capacity_(capture_period + capture_period / 2),
+ token_bucket_capacity_(min_capture_period + min_capture_period / 2),
overdue_sample_count_(0),
token_bucket_(token_bucket_capacity_) {
- DCHECK_GT(capture_period_.InMicroseconds(), 0);
+ DCHECK_GT(min_capture_period_.InMicroseconds(), 0);
}
-bool SmoothEventSampler::AddEventAndConsiderSampling(
- base::TimeTicks event_time) {
+void SmoothEventSampler::ConsiderPresentationEvent(base::TimeTicks event_time) {
DCHECK(!event_time.is_null());
// Add tokens to the bucket based on advancement in time. Then, re-bound the
@@ -104,40 +200,31 @@ bool SmoothEventSampler::AddEventAndConsiderSampling(
if (token_bucket_ > token_bucket_capacity_)
token_bucket_ = token_bucket_capacity_;
}
- // Side note: If the system clock is reset, causing |current_event_| to be
- // greater than |event_time|, everything here will simply gracefully adjust.
- if (token_bucket_ < base::TimeDelta())
- token_bucket_ = base::TimeDelta();
TRACE_COUNTER1("mirroring",
"MirroringTokenBucketUsec",
std::max<int64>(0, token_bucket_.InMicroseconds()));
}
current_event_ = event_time;
+}
- // Return true if one capture period's worth of tokens are in the bucket.
- return token_bucket_ >= capture_period_;
+bool SmoothEventSampler::ShouldSample() const {
+ return token_bucket_ >= min_capture_period_;
}
void SmoothEventSampler::RecordSample() {
- token_bucket_ -= capture_period_;
+ token_bucket_ -= min_capture_period_;
+ if (token_bucket_ < base::TimeDelta())
+ token_bucket_ = base::TimeDelta();
TRACE_COUNTER1("mirroring",
"MirroringTokenBucketUsec",
std::max<int64>(0, token_bucket_.InMicroseconds()));
- bool was_paused = overdue_sample_count_ == redundant_capture_goal_;
if (HasUnrecordedEvent()) {
last_sample_ = current_event_;
overdue_sample_count_ = 0;
} else {
++overdue_sample_count_;
}
- bool is_paused = overdue_sample_count_ == redundant_capture_goal_;
-
- VLOG_IF(0, !was_paused && is_paused)
- << "Tab content unchanged for " << redundant_capture_goal_
- << " frames; capture will halt until content changes.";
- VLOG_IF(0, was_paused && !is_paused)
- << "Content changed; capture will resume.";
}
bool SmoothEventSampler::IsOverdueForSamplingAt(base::TimeTicks event_time)
@@ -159,14 +246,191 @@ bool SmoothEventSampler::IsOverdueForSamplingAt(base::TimeTicks event_time)
// If we're dirty but not yet old, then we've recently gotten updates, so we
// won't request a sample just yet.
base::TimeDelta dirty_interval = event_time - last_sample_;
- if (dirty_interval < capture_period_ * 4)
- return false;
- else
- return true;
+ return dirty_interval >=
+ base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis);
}
bool SmoothEventSampler::HasUnrecordedEvent() const {
return !current_event_.is_null() && current_event_ != last_sample_;
}
+AnimatedContentSampler::AnimatedContentSampler(
+ base::TimeDelta min_capture_period)
+ : min_capture_period_(min_capture_period) {}
+
+AnimatedContentSampler::~AnimatedContentSampler() {}
+
+void AnimatedContentSampler::ConsiderPresentationEvent(
+ const gfx::Rect& damage_rect, base::TimeTicks event_time) {
+ AddObservation(damage_rect, event_time);
+
+ if (AnalyzeObservations(event_time, &detected_region_, &detected_period_) &&
+ detected_period_ > base::TimeDelta() &&
+ detected_period_ <=
+ base::TimeDelta::FromMicroseconds(kMaxLockInPeriodMicros)) {
+ if (damage_rect == detected_region_)
+ UpdateFrameTimestamp(event_time);
+ else
+ frame_timestamp_ = base::TimeTicks();
+ } else {
+ detected_region_ = gfx::Rect();
+ detected_period_ = base::TimeDelta();
+ frame_timestamp_ = base::TimeTicks();
+ }
+}
+
+bool AnimatedContentSampler::HasProposal() const {
+ return detected_period_ > base::TimeDelta();
+}
+
+bool AnimatedContentSampler::ShouldSample() const {
+ return !frame_timestamp_.is_null();
+}
+
+void AnimatedContentSampler::RecordSample(base::TimeTicks frame_timestamp) {
+ recorded_frame_timestamp_ = frame_timestamp;
+ sequence_offset_ = base::TimeDelta();
+}
+
+void AnimatedContentSampler::AddObservation(const gfx::Rect& damage_rect,
+ base::TimeTicks event_time) {
+ if (damage_rect.IsEmpty())
+ return; // Useless observation.
+
+ // Add the observation to the FIFO queue.
+ if (!observations_.empty() && observations_.back().event_time > event_time)
+ return; // The implementation assumes chronological order.
+ observations_.push_back(Observation(damage_rect, event_time));
+
+ // Prune-out old observations.
+ const base::TimeDelta threshold =
+ base::TimeDelta::FromMilliseconds(kMaxObservationWindowMillis);
+ while ((event_time - observations_.front().event_time) > threshold)
+ observations_.pop_front();
+}
+
+gfx::Rect AnimatedContentSampler::ElectMajorityDamageRect() const {
+ // This is an derivative of the Boyer-Moore Majority Vote Algorithm where each
+ // pixel in a candidate gets one vote, as opposed to each candidate getting
+ // one vote.
+ const gfx::Rect* candidate = NULL;
+ int64 votes = 0;
+ for (ObservationFifo::const_iterator i = observations_.begin();
+ i != observations_.end(); ++i) {
+ DCHECK_GT(i->damage_rect.size().GetArea(), 0);
+ if (votes == 0) {
+ candidate = &(i->damage_rect);
+ votes = candidate->size().GetArea();
+ } else if (i->damage_rect == *candidate) {
+ votes += i->damage_rect.size().GetArea();
+ } else {
+ votes -= i->damage_rect.size().GetArea();
+ if (votes < 0) {
+ candidate = &(i->damage_rect);
+ votes = -votes;
+ }
+ }
+ }
+ return (votes > 0) ? *candidate : gfx::Rect();
+}
+
+bool AnimatedContentSampler::AnalyzeObservations(
+ base::TimeTicks event_time,
+ gfx::Rect* rect,
+ base::TimeDelta* period) const {
+ const gfx::Rect elected_rect = ElectMajorityDamageRect();
+ if (elected_rect.IsEmpty())
+ return false; // There is no regular animation present.
+
+ // Scan |observations_|, gathering metrics about the ones having a damage Rect
+ // equivalent to the |elected_rect|. Along the way, break early whenever the
+ // event times reveal a non-animating period.
+ int64 num_pixels_damaged_in_all = 0;
+ int64 num_pixels_damaged_in_chosen = 0;
+ base::TimeDelta sum_frame_durations;
+ size_t count_frame_durations = 0;
+ base::TimeTicks first_event_time;
+ base::TimeTicks last_event_time;
+ for (ObservationFifo::const_reverse_iterator i = observations_.rbegin();
+ i != observations_.rend(); ++i) {
+ const int area = i->damage_rect.size().GetArea();
+ num_pixels_damaged_in_all += area;
+ if (i->damage_rect != elected_rect)
+ continue;
+ num_pixels_damaged_in_chosen += area;
+ if (last_event_time.is_null()) {
+ last_event_time = i->event_time;
+ if ((event_time - last_event_time) >=
+ base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis)) {
+ return false; // Content animation has recently ended.
+ }
+ } else {
+ const base::TimeDelta frame_duration = first_event_time - i->event_time;
+ if (frame_duration >=
+ base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis)) {
+ break; // Content not animating before this point.
+ }
+ sum_frame_durations += frame_duration;
+ ++count_frame_durations;
+ }
+ first_event_time = i->event_time;
+ }
+
+ if ((last_event_time - first_event_time) <
+ base::TimeDelta::FromMilliseconds(kMinObservationWindowMillis)) {
+ return false; // Content has not animated for long enough for accuracy.
+ }
+ if (num_pixels_damaged_in_chosen <= (num_pixels_damaged_in_all * 2 / 3))
+ return false; // Animation is not damaging a supermajority of pixels.
+
+ *rect = elected_rect;
+ DCHECK_GT(count_frame_durations, 0u);
+ *period = sum_frame_durations / count_frame_durations;
+ return true;
+}
+
+void AnimatedContentSampler::UpdateFrameTimestamp(base::TimeTicks event_time) {
+ // This is how much time to advance from the last frame timestamp. Never
+ // advance by less than |min_capture_period_| because the downstream consumer
+ // cannot handle the higher frame rate. If |detected_period_| is less than
+ // |min_capture_period_|, excess frames should be dropped.
+ const base::TimeDelta advancement =
+ std::max(detected_period_, min_capture_period_);
+
+ // Compute the |timebase| upon which to determine the |frame_timestamp_|.
+ // Ideally, this would always equal the timestamp of the last recorded frame
+ // sampling. Determine how much drift from the ideal is present, then adjust
+ // the timebase by a small amount to spread out the entire correction over
+ // many frame timestamps.
+ //
+ // This accounts for two main sources of drift: 1) The clock drift of the
+ // system clock relative to the video hardware, which affects the event times;
+ // and 2) The small error introduced by this frame timestamp rewriting, as it
+ // is based on averaging over recent events.
+ base::TimeTicks timebase = event_time - sequence_offset_ - advancement;
+ if (!recorded_frame_timestamp_.is_null()) {
+ const base::TimeDelta drift = recorded_frame_timestamp_ - timebase;
+ const int64 correct_over_num_frames =
+ base::TimeDelta::FromMilliseconds(kDriftCorrectionMillis) /
+ detected_period_;
+ DCHECK_GT(correct_over_num_frames, 0);
+ timebase = recorded_frame_timestamp_ - (drift / correct_over_num_frames);
+ }
+
+ // Compute |frame_timestamp_|. Whenever |detected_period_| is less than
+ // |min_capture_period_|, some extra time is "borrowed" to be able to advance
+ // by the full |min_capture_period_|. Then, whenever the total amount of
+ // borrowed time reaches a full |min_capture_period_|, drop a frame. Note
+ // that when |detected_period_| is greater or equal to |min_capture_period_|,
+ // this logic is effectively disabled.
+ borrowed_time_ += advancement - detected_period_;
+ if (borrowed_time_ >= min_capture_period_) {
+ borrowed_time_ -= min_capture_period_;
+ frame_timestamp_ = base::TimeTicks();
+ } else {
+ sequence_offset_ += advancement;
+ frame_timestamp_ = timebase + sequence_offset_;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/video_capture_oracle.h b/chromium/content/browser/media/capture/video_capture_oracle.h
index 6242b6a29a8..32e7baff4da 100644
--- a/chromium/content/browser/media/capture/video_capture_oracle.h
+++ b/chromium/content/browser/media/capture/video_capture_oracle.h
@@ -5,26 +5,34 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_VIDEO_CAPTURE_ORACLE_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_VIDEO_CAPTURE_ORACLE_H_
+#include <deque>
+
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "ui/gfx/geometry/rect.h"
namespace content {
// Filters a sequence of events to achieve a target frequency.
class CONTENT_EXPORT SmoothEventSampler {
public:
- explicit SmoothEventSampler(base::TimeDelta capture_period,
- bool events_are_reliable,
- int redundant_capture_goal);
+ SmoothEventSampler(base::TimeDelta min_capture_period,
+ bool events_are_reliable,
+ int redundant_capture_goal);
+
+ base::TimeDelta min_capture_period() const { return min_capture_period_; }
+
+ // Add a new event to the event history, and consider whether it ought to be
+ // sampled. The event is not recorded as a sample until RecordSample() is
+ // called.
+ void ConsiderPresentationEvent(base::TimeTicks event_time);
- // Add a new event to the event history, and return whether it ought to be
- // sampled based on the desired |capture_period|. The event is not recorded as
- // a sample until RecordSample() is called.
- bool AddEventAndConsiderSampling(base::TimeTicks event_time);
+ // Returns true if the last event considered should be sampled.
+ bool ShouldSample() const;
- // Operates on the last event added by AddEventAndConsiderSampling(), marking
+ // Operates on the last event added by ConsiderPresentationEvent(), marking
// it as sampled. After this point we are current in the stream of events, as
// we have sampled the most recent event.
void RecordSample();
@@ -33,13 +41,13 @@ class CONTENT_EXPORT SmoothEventSampler {
// much time will have passed relative to the last event and/or sample.
bool IsOverdueForSamplingAt(base::TimeTicks event_time) const;
- // Returns true if AddEventAndConsiderSampling() has been called since the
- // last call to RecordSample().
+ // Returns true if ConsiderPresentationEvent() has been called since the last
+ // call to RecordSample().
bool HasUnrecordedEvent() const;
private:
const bool events_are_reliable_;
- const base::TimeDelta capture_period_;
+ const base::TimeDelta min_capture_period_;
const int redundant_capture_goal_;
const base::TimeDelta token_bucket_capacity_;
@@ -51,6 +59,115 @@ class CONTENT_EXPORT SmoothEventSampler {
DISALLOW_COPY_AND_ASSIGN(SmoothEventSampler);
};
+// Analyzes a sequence of events to detect the presence of constant frame rate
+// animated content. In the case where there are multiple regions of animated
+// content, AnimatedContentSampler will propose sampling the one having the
+// largest "smoothness" impact, according to human perception (e.g., a 24 FPS
+// video versus a 60 FPS busy spinner).
+//
+// In addition, AnimatedContentSampler will provide rewritten frame timestamps,
+// for downstream consumers, that are "truer" to the source content than to the
+// local presentation hardware.
+class CONTENT_EXPORT AnimatedContentSampler {
+ public:
+ explicit AnimatedContentSampler(base::TimeDelta min_capture_period);
+ ~AnimatedContentSampler();
+
+ // Examines the given presentation event metadata, along with recent history,
+ // to detect animated content, updating the state of this sampler.
+ // |damage_rect| is the region of a frame about to be drawn, while
+ // |event_time| refers to the frame's estimated presentation time.
+ void ConsiderPresentationEvent(const gfx::Rect& damage_rect,
+ base::TimeTicks event_time);
+
+ // Returns true if animated content has been detected and a decision has been
+ // made about whether to sample the last event.
+ bool HasProposal() const;
+
+ // Returns true if the last event considered should be sampled.
+ bool ShouldSample() const;
+
+ // Returns a frame timestamp to provide to consumers of the sampled frame.
+ // Only valid when should_sample() returns true.
+ base::TimeTicks frame_timestamp() const { return frame_timestamp_; }
+
+ // Accessors to currently-detected animating region/period, for logging.
+ const gfx::Rect& detected_region() const { return detected_region_; }
+ base::TimeDelta detected_period() const { return detected_period_; }
+
+ // Records that a frame with the given |frame_timestamp| was sampled. This
+ // method should be called when *any* sampling is taken, even if it was not
+ // proposed by AnimatedContentSampler.
+ void RecordSample(base::TimeTicks frame_timestamp);
+
+ private:
+ friend class AnimatedContentSamplerTest;
+
+ // Data structure for efficient online analysis of recent event history.
+ struct Observation {
+ gfx::Rect damage_rect;
+ base::TimeTicks event_time;
+
+ Observation(const gfx::Rect& d, base::TimeTicks e)
+ : damage_rect(d), event_time(e) {}
+ };
+ typedef std::deque<Observation> ObservationFifo;
+
+ // Adds an observation to |observations_|, and prunes-out the old ones.
+ void AddObservation(const gfx::Rect& damage_rect, base::TimeTicks event_time);
+
+ // Returns the damage Rect that is responsible for the majority of the pixel
+ // damage in recent event history, if there is such a Rect. If there isn't,
+ // this method could still return any Rect, so the caller must confirm the
+ // returned Rect really is responsible for the majority of pixel damage.
+ gfx::Rect ElectMajorityDamageRect() const;
+
+ // Analyzes the observations relative to the current |event_time| to detect
+ // stable animating content. If detected, returns true and sets the output
+ // arguments to the region of the animating content and its mean frame
+ // duration.
+ bool AnalyzeObservations(base::TimeTicks event_time,
+ gfx::Rect* rect,
+ base::TimeDelta* period) const;
+
+ // Called by ConsiderPresentationEvent() when the current event is part of a
+ // detected animation, to update |frame_timestamp_|.
+ void UpdateFrameTimestamp(base::TimeTicks event_time);
+
+ // The client expects frame timestamps to be at least this far apart.
+ const base::TimeDelta min_capture_period_;
+
+ // A recent history of observations in chronological order, maintained by
+ // AddObservation().
+ ObservationFifo observations_;
+
+ // The region of currently-detected animated content. If empty, that means
+ // "not detected."
+ gfx::Rect detected_region_;
+
+ // The mean frame duration of currently-detected animated content. If zero,
+ // that means "not detected."
+ base::TimeDelta detected_period_;
+
+ // The rewritten frame timestamp for the latest event.
+ base::TimeTicks frame_timestamp_;
+
+ // The frame timestamp provided in the last call to RecordSample(). This
+ // timestamp may or may not have been one proposed by AnimatedContentSampler.
+ base::TimeTicks recorded_frame_timestamp_;
+
+ // Accumulates all the time advancements since the last call to
+ // RecordSample(). When this is greater than zero, there have been one or
+ // more events proposed for sampling, but not yet recorded. This accounts for
+ // the cases where AnimatedContentSampler indicates a frame should be sampled,
+ // but the client chooses not to do so.
+ base::TimeDelta sequence_offset_;
+
+ // A token bucket that is used to decide which frames to drop whenever
+ // |detected_period_| is less than |min_capture_period_|.
+ base::TimeDelta borrowed_time_;
+};
+
// VideoCaptureOracle manages the producer-side throttling of captured frames
// from a video capture device. It is informed of every update by the device;
// this empowers it to look into the future and decide if a particular frame
@@ -61,43 +178,61 @@ class CONTENT_EXPORT VideoCaptureOracle {
kTimerPoll,
kCompositorUpdate,
kSoftwarePaint,
+ kNumEvents,
};
- VideoCaptureOracle(base::TimeDelta capture_period,
+ VideoCaptureOracle(base::TimeDelta min_capture_period,
bool events_are_reliable);
- virtual ~VideoCaptureOracle() {}
+ virtual ~VideoCaptureOracle();
- // Record an event of type |event|, and decide whether the caller should do a
- // frame capture immediately. Decisions of the oracle are final: the caller
- // must do what it is told.
- bool ObserveEventAndDecideCapture(Event event, base::TimeTicks event_time);
+ // Record a event of type |event|, and decide whether the caller should do a
+ // frame capture. |damage_rect| is the region of a frame about to be drawn,
+ // and may be an empty Rect, if this is not known. If the caller accepts the
+ // oracle's proposal, it should call RecordCapture() to indicate this.
+ bool ObserveEventAndDecideCapture(Event event,
+ const gfx::Rect& damage_rect,
+ base::TimeTicks event_time);
// Record the start of a capture. Returns a frame_number to be used with
// CompleteCapture().
int RecordCapture();
- // Record the completion of a capture. Returns true iff the captured frame
- // should be delivered.
- bool CompleteCapture(int frame_number, base::TimeTicks timestamp);
+ // Notify of the completion of a capture. Returns true iff the captured frame
+ // should be delivered. |frame_timestamp| is set to the timestamp that should
+ // be provided to the consumer of the frame.
+ bool CompleteCapture(int frame_number, base::TimeTicks* frame_timestamp);
- base::TimeDelta capture_period() const { return capture_period_; }
+ base::TimeDelta min_capture_period() const {
+ return smoothing_sampler_.min_capture_period();
+ }
private:
-
- // Time between frames.
- const base::TimeDelta capture_period_;
+ // Retrieve/Assign a frame timestamp by capture |frame_number|.
+ base::TimeTicks GetFrameTimestamp(int frame_number) const;
+ void SetFrameTimestamp(int frame_number, base::TimeTicks timestamp);
// Incremented every time a paint or update event occurs.
int frame_number_;
+ // Stores the last |event_time| from the last observation/decision. Used to
+ // sanity-check that event times are monotonically non-decreasing.
+ base::TimeTicks last_event_time_[kNumEvents];
+
// Stores the frame number from the last delivered frame.
int last_delivered_frame_number_;
- // Stores the timestamp of the last delivered frame.
- base::TimeTicks last_delivered_frame_timestamp_;
-
- // Tracks present/paint history.
- SmoothEventSampler sampler_;
+ // These track present/paint history and propose whether to sample each event
+ // for capture. |smoothing_sampler_| uses a "works for all" heuristic, while
+ // |content_sampler_| specifically detects animated content (e.g., video
+ // playback) and decides which events to sample to "lock into" that content.
+ SmoothEventSampler smoothing_sampler_;
+ AnimatedContentSampler content_sampler_;
+
+ // Recent history of frame timestamps proposed by VideoCaptureOracle. This is
+ // a ring-buffer, and should only be accessed by the Get/SetFrameTimestamp()
+ // methods.
+ enum { kMaxFrameTimestamps = 16 };
+ base::TimeTicks frame_timestamps_[kMaxFrameTimestamps];
};
} // namespace content
diff --git a/chromium/content/browser/media/capture/video_capture_oracle_unittest.cc b/chromium/content/browser/media/capture/video_capture_oracle_unittest.cc
index dff8e97de7f..1a4222ac4d5 100644
--- a/chromium/content/browser/media/capture/video_capture_oracle_unittest.cc
+++ b/chromium/content/browser/media/capture/video_capture_oracle_unittest.cc
@@ -4,17 +4,29 @@
#include "content/browser/media/capture/video_capture_oracle.h"
+#include <cstdlib>
+#include <utility>
+#include <vector>
+
+#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/rect.h"
namespace content {
namespace {
+bool AddEventAndConsiderSampling(SmoothEventSampler* sampler,
+ base::TimeTicks event_time) {
+ sampler->ConsiderPresentationEvent(event_time);
+ return sampler->ShouldSample();
+}
+
void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
SmoothEventSampler* sampler,
base::TimeTicks* t) {
- ASSERT_TRUE(sampler->AddEventAndConsiderSampling(*t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
ASSERT_TRUE(sampler->HasUnrecordedEvent());
sampler->RecordSample();
ASSERT_FALSE(sampler->HasUnrecordedEvent());
@@ -26,17 +38,15 @@ void SteadyStateSampleAndAdvance(base::TimeDelta vsync,
void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync,
SmoothEventSampler* sampler,
base::TimeTicks* t) {
- ASSERT_FALSE(sampler->AddEventAndConsiderSampling(*t));
+ ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t));
ASSERT_TRUE(sampler->HasUnrecordedEvent());
ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
*t += vsync;
ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t));
}
-void TimeTicksFromString(const char* string, base::TimeTicks* t) {
- base::Time time;
- ASSERT_TRUE(base::Time::FromString(string, &time));
- *t = base::TimeTicks::UnixEpoch() + (time - base::Time::UnixEpoch());
+base::TimeTicks InitialTestTimeTicks() {
+ return base::TimeTicks() + base::TimeDelta::FromSeconds(1);
}
void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
@@ -48,15 +58,15 @@ void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
// Consider the first event. We want to sample that.
ASSERT_FALSE(sampler->HasUnrecordedEvent());
- ASSERT_TRUE(sampler->AddEventAndConsiderSampling(*t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t));
ASSERT_TRUE(sampler->HasUnrecordedEvent());
sampler->RecordSample();
ASSERT_FALSE(sampler->HasUnrecordedEvent());
- // After more than one capture period has passed without considering an event,
- // we should repeatedly be overdue for sampling. However, once the redundant
- // capture goal is achieved, we should no longer be overdue for sampling.
- *t += capture_period * 4;
+ // After more than 250 ms has passed without considering an event, we should
+ // repeatedly be overdue for sampling. However, once the redundant capture
+ // goal is achieved, we should no longer be overdue for sampling.
+ *t += base::TimeDelta::FromMilliseconds(250);
for (int i = 0; i < redundant_capture_goal; i++) {
SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
ASSERT_FALSE(sampler->HasUnrecordedEvent());
@@ -69,6 +79,8 @@ void TestRedundantCaptureStrategy(base::TimeDelta capture_period,
<< "Should not be overdue once redundant capture goal achieved.";
}
+} // namespace
+
// 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains
// much more comprehensive before/after/edge-case scenarios than the others.
TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
@@ -77,8 +89,7 @@ TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60;
SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
&sampler, &t);
@@ -94,8 +105,8 @@ TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) {
// case we are adding events but not sampling them.
for (int i = 0; i < 20; i++) {
SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
- ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t));
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
ASSERT_TRUE(sampler.HasUnrecordedEvent());
t += vsync;
}
@@ -117,8 +128,7 @@ TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50;
SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
&sampler, &t);
@@ -136,10 +146,10 @@ TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) {
// Now pretend we're limited by backpressure in the pipeline. In this scenario
// case we are adding events but not sampling them.
- for (int i = 0; i < 12; i++) {
+ for (int i = 0; i < 20; i++) {
SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
- ASSERT_EQ(i >= 5, sampler.IsOverdueForSamplingAt(t));
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
t += vsync;
}
@@ -163,8 +173,7 @@ TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75;
SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
&sampler, &t);
@@ -186,8 +195,8 @@ TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) {
// case we are adding events but not sampling them.
for (int i = 0; i < 20; i++) {
SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
- ASSERT_EQ(i >= 8, sampler.IsOverdueForSamplingAt(t));
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
t += vsync;
}
@@ -213,8 +222,7 @@ TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30;
SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
&sampler, &t);
@@ -227,10 +235,10 @@ TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) {
// Now pretend we're limited by backpressure in the pipeline. In this scenario
// case we are adding events but not sampling them.
- for (int i = 0; i < 7; i++) {
+ for (int i = 0; i < 10; i++) {
SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
- ASSERT_EQ(i >= 3, sampler.IsOverdueForSamplingAt(t));
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
t += vsync;
}
@@ -249,8 +257,7 @@ TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24;
SmoothEventSampler sampler(capture_period, true, redundant_capture_goal);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
TestRedundantCaptureStrategy(capture_period, redundant_capture_goal,
&sampler, &t);
@@ -263,10 +270,10 @@ TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) {
// Now pretend we're limited by backpressure in the pipeline. In this scenario
// case we are adding events but not sampling them.
- for (int i = 0; i < 7; i++) {
+ for (int i = 0; i < 10; i++) {
SCOPED_TRACE(base::StringPrintf("Iteration %d", i));
- ASSERT_EQ(i >= 3, sampler.IsOverdueForSamplingAt(t));
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
t += vsync;
}
@@ -283,19 +290,18 @@ TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) {
const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1);
SmoothEventSampler sampler(capture_period, true, 1);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
sampler.RecordSample();
ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t))
<< "Sampled last event; should not be dirty.";
t += overdue_period;
// Now simulate 2 events with the same clock value.
- ASSERT_TRUE(sampler.AddEventAndConsiderSampling(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t));
sampler.RecordSample();
- ASSERT_FALSE(sampler.AddEventAndConsiderSampling(t))
+ ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t))
<< "Two events at same time -- expected second not to be sampled.";
ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period))
<< "Second event should dirty the capture state.";
@@ -308,18 +314,20 @@ TEST(SmoothEventSamplerTest, FallbackToPollingIfUpdatesUnreliable) {
SmoothEventSampler should_not_poll(timer_interval, true, 1);
SmoothEventSampler should_poll(timer_interval, false, 1);
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
// Do one round of the "happy case" where an event was received and
// RecordSample() was called by the client.
- ASSERT_TRUE(should_not_poll.AddEventAndConsiderSampling(t));
- ASSERT_TRUE(should_poll.AddEventAndConsiderSampling(t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&should_not_poll, t));
+ ASSERT_TRUE(AddEventAndConsiderSampling(&should_poll, t));
should_not_poll.RecordSample();
should_poll.RecordSample();
- // One time period ahead, neither sampler says we're overdue.
- for (int i = 0; i < 3; i++) {
+ // For the following time period, before 250 ms has elapsed, neither sampler
+ // says we're overdue.
+ const int non_overdue_intervals = static_cast<int>(
+ base::TimeDelta::FromMilliseconds(250) / timer_interval);
+ for (int i = 0; i < non_overdue_intervals; i++) {
t += timer_interval;
ASSERT_FALSE(should_not_poll.IsOverdueForSamplingAt(t))
<< "Sampled last event; should not be dirty.";
@@ -330,7 +338,7 @@ TEST(SmoothEventSamplerTest, FallbackToPollingIfUpdatesUnreliable) {
// Next time period ahead, both samplers say we're overdue. The non-polling
// sampler is returning true here because it has been configured to allow one
// redundant capture.
- t += timer_interval;
+ t += timer_interval; // Step past the 250 ms threshold.
ASSERT_TRUE(should_not_poll.IsOverdueForSamplingAt(t))
<< "Sampled last event; is dirty one time only to meet redundancy goal.";
ASSERT_TRUE(should_poll.IsOverdueForSamplingAt(t))
@@ -356,6 +364,8 @@ TEST(SmoothEventSamplerTest, FallbackToPollingIfUpdatesUnreliable) {
should_poll.RecordSample();
}
+namespace {
+
struct DataPoint {
bool should_capture;
double increment_ms;
@@ -364,19 +374,20 @@ struct DataPoint {
void ReplayCheckingSamplerDecisions(const DataPoint* data_points,
size_t num_data_points,
SmoothEventSampler* sampler) {
- base::TimeTicks t;
- TimeTicksFromString("Sat, 23 Mar 2013 1:21:08 GMT", &t);
+ base::TimeTicks t = InitialTestTimeTicks();
for (size_t i = 0; i < num_data_points; ++i) {
t += base::TimeDelta::FromMicroseconds(
static_cast<int64>(data_points[i].increment_ms * 1000));
ASSERT_EQ(data_points[i].should_capture,
- sampler->AddEventAndConsiderSampling(t))
+ AddEventAndConsiderSampling(sampler, t))
<< "at data_points[" << i << ']';
if (data_points[i].should_capture)
sampler->RecordSample();
}
}
+} // namespace
+
TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) {
// Actual capturing of timing data: Initial instability as a 24 FPS video was
// started from a still screen, then clearly followed by steady-state.
@@ -483,5 +494,768 @@ TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) {
ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler);
}
+class AnimatedContentSamplerTest : public ::testing::Test {
+ public:
+ AnimatedContentSamplerTest() {}
+ ~AnimatedContentSamplerTest() override {}
+
+ void SetUp() override {
+ const base::TimeDelta since_epoch =
+ InitialTestTimeTicks() - base::TimeTicks::UnixEpoch();
+ rand_seed_ = abs(static_cast<int>(since_epoch.InMicroseconds()));
+ sampler_.reset(new AnimatedContentSampler(GetMinCapturePeriod()));
+ }
+
+ protected:
+ // Overridden by subclass for parameterized tests.
+ virtual base::TimeDelta GetMinCapturePeriod() const {
+ return base::TimeDelta::FromSeconds(1) / 30;
+ }
+
+ AnimatedContentSampler* sampler() const {
+ return sampler_.get();
+ }
+
+ int GetRandomInRange(int begin, int end) {
+ const int len = end - begin;
+ const int rand_offset = (len == 0) ? 0 : (NextRandomInt() % (end - begin));
+ return begin + rand_offset;
+ }
+
+ gfx::Rect GetRandomDamageRect() {
+ return gfx::Rect(0, 0, GetRandomInRange(1, 100), GetRandomInRange(1, 100));
+ }
+
+ gfx::Rect GetContentDamageRect() {
+ // This must be distinct from anything GetRandomDamageRect() could return.
+ return gfx::Rect(0, 0, 1280, 720);
+ }
+
+ // Directly inject an observation. Only used to test
+ // ElectMajorityDamageRect().
+ void ObserveDamageRect(const gfx::Rect& damage_rect) {
+ sampler_->observations_.push_back(
+ AnimatedContentSampler::Observation(damage_rect, base::TimeTicks()));
+ }
+
+ gfx::Rect ElectMajorityDamageRect() const {
+ return sampler_->ElectMajorityDamageRect();
+ }
+
+ private:
+ // Note: Not using base::RandInt() because it is horribly slow on debug
+ // builds. The following is a very simple, deterministic LCG:
+ int NextRandomInt() {
+ rand_seed_ = (1103515245 * rand_seed_ + 12345) % (1 << 31);
+ return rand_seed_;
+ }
+
+ int rand_seed_;
+ scoped_ptr<AnimatedContentSampler> sampler_;
+};
+
+TEST_F(AnimatedContentSamplerTest, ElectsNoneFromZeroDamageRects) {
+ EXPECT_EQ(gfx::Rect(), ElectMajorityDamageRect());
+}
+
+TEST_F(AnimatedContentSamplerTest, ElectsMajorityFromOneDamageRect) {
+ const gfx::Rect the_one_rect(0, 0, 1, 1);
+ ObserveDamageRect(the_one_rect);
+ EXPECT_EQ(the_one_rect, ElectMajorityDamageRect());
+}
+
+TEST_F(AnimatedContentSamplerTest, ElectsNoneFromTwoDamageRectsOfSameArea) {
+ const gfx::Rect one_rect(0, 0, 1, 1);
+ const gfx::Rect another_rect(1, 1, 1, 1);
+ ObserveDamageRect(one_rect);
+ ObserveDamageRect(another_rect);
+ EXPECT_EQ(gfx::Rect(), ElectMajorityDamageRect());
+}
+
+TEST_F(AnimatedContentSamplerTest, ElectsLargerOfTwoDamageRects_1) {
+ const gfx::Rect one_rect(0, 0, 1, 1);
+ const gfx::Rect another_rect(0, 0, 2, 2);
+ ObserveDamageRect(one_rect);
+ ObserveDamageRect(another_rect);
+ EXPECT_EQ(another_rect, ElectMajorityDamageRect());
+}
+
+TEST_F(AnimatedContentSamplerTest, ElectsLargerOfTwoDamageRects_2) {
+ const gfx::Rect one_rect(0, 0, 2, 2);
+ const gfx::Rect another_rect(0, 0, 1, 1);
+ ObserveDamageRect(one_rect);
+ ObserveDamageRect(another_rect);
+ EXPECT_EQ(one_rect, ElectMajorityDamageRect());
+}
+
+TEST_F(AnimatedContentSamplerTest, ElectsSameAsMooreDemonstration) {
+ // A more complex sequence (from Moore's web site): Three different Rects with
+ // the same area, but occurring a different number of times. C should win the
+ // vote.
+ const gfx::Rect rect_a(0, 0, 1, 4);
+ const gfx::Rect rect_b(1, 1, 4, 1);
+ const gfx::Rect rect_c(2, 2, 2, 2);
+ for (int i = 0; i < 3; ++i)
+ ObserveDamageRect(rect_a);
+ for (int i = 0; i < 2; ++i)
+ ObserveDamageRect(rect_c);
+ for (int i = 0; i < 2; ++i)
+ ObserveDamageRect(rect_b);
+ for (int i = 0; i < 3; ++i)
+ ObserveDamageRect(rect_c);
+ ObserveDamageRect(rect_b);
+ for (int i = 0; i < 2; ++i)
+ ObserveDamageRect(rect_c);
+ EXPECT_EQ(rect_c, ElectMajorityDamageRect());
+}
+
+TEST_F(AnimatedContentSamplerTest, Elects24FpsVideoInsteadOf48FpsSpinner) {
+ // Scenario: 24 FPS 720x480 Video versus 48 FPS 96x96 "Busy Spinner"
+ const gfx::Rect video_rect(100, 100, 720, 480);
+ const gfx::Rect spinner_rect(360, 0, 96, 96);
+ for (int i = 0; i < 100; ++i) {
+ // |video_rect| occurs once for every two |spinner_rect|. Vary the order
+ // of events between the two:
+ ObserveDamageRect(video_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(video_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(video_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(spinner_rect);
+ ObserveDamageRect(video_rect);
+ ObserveDamageRect(spinner_rect);
+ }
+ EXPECT_EQ(video_rect, ElectMajorityDamageRect());
+}
+
+namespace {
+
+// A test scenario for AnimatedContentSamplerParameterizedTest.
+struct Scenario {
+ base::TimeDelta vsync_interval; // Reflects compositor's update rate.
+ base::TimeDelta min_capture_period; // Reflects maximum capture rate.
+ base::TimeDelta content_period; // Reflects content animation rate.
+
+ Scenario(base::TimeDelta v, base::TimeDelta m, base::TimeDelta c)
+ : vsync_interval(v), min_capture_period(m), content_period(c) {
+ CHECK(content_period >= vsync_interval)
+ << "Bad test params: Impossible to animate faster than the compositor.";
+ }
+};
+
+// Value printer for Scenario.
+::std::ostream& operator<<(::std::ostream& os, const Scenario& s) {
+ return os << "{ vsync_interval=" << s.vsync_interval.InMicroseconds()
+ << ", min_capture_period=" << s.min_capture_period.InMicroseconds()
+ << ", content_period=" << s.content_period.InMicroseconds()
+ << " }";
+}
+
+base::TimeDelta FpsAsPeriod(int frame_rate) {
+ return base::TimeDelta::FromSeconds(1) / frame_rate;
+}
+
} // namespace
+
+class AnimatedContentSamplerParameterizedTest
+ : public AnimatedContentSamplerTest,
+ public ::testing::WithParamInterface<Scenario> {
+ public:
+ AnimatedContentSamplerParameterizedTest()
+ : count_dropped_frames_(0), count_sampled_frames_(0) {}
+ virtual ~AnimatedContentSamplerParameterizedTest() {}
+
+ protected:
+ typedef std::pair<gfx::Rect, base::TimeTicks> Event;
+
+ base::TimeDelta GetMinCapturePeriod() const override {
+ return GetParam().min_capture_period;
+ }
+
+ // Generate a sequence of events from the compositor pipeline. The event
+ // times will all be at compositor vsync boundaries.
+ std::vector<Event> GenerateEventSequence(base::TimeTicks begin,
+ base::TimeTicks end,
+ bool include_content_frame_events,
+ bool include_random_events) {
+ DCHECK(GetParam().content_period >= GetParam().vsync_interval);
+ base::TimeTicks next_content_time = begin - GetParam().content_period;
+ std::vector<Event> events;
+ for (base::TimeTicks compositor_time = begin; compositor_time < end;
+ compositor_time += GetParam().vsync_interval) {
+ if (include_content_frame_events && next_content_time < compositor_time) {
+ events.push_back(Event(GetContentDamageRect(), compositor_time));
+ next_content_time += GetParam().content_period;
+ } else if (include_random_events && GetRandomInRange(0, 1) == 0) {
+ events.push_back(Event(GetRandomDamageRect(), compositor_time));
+ }
+ }
+
+ DCHECK(!events.empty());
+ return events;
+ }
+
+ // Feed |events| through the sampler, and detect whether the expected
+ // lock-in/out transition occurs. Also, track and measure the frame drop
+ // ratio and check it against the expected drop rate.
+ void RunEventSequence(const std::vector<Event> events,
+ bool was_detecting_before,
+ bool is_detecting_after,
+ bool simulate_pipeline_back_pressure) {
+ gfx::Rect first_detected_region;
+
+ EXPECT_EQ(was_detecting_before, sampler()->HasProposal());
+ bool has_detection_switched = false;
+ ResetFrameCounters();
+ for (std::vector<Event>::const_iterator i = events.begin();
+ i != events.end(); ++i) {
+ sampler()->ConsiderPresentationEvent(i->first, i->second);
+
+ // Detect when the sampler locks in/out, and that it stays that way for
+ // all further iterations of this loop.
+ if (!has_detection_switched &&
+ was_detecting_before != sampler()->HasProposal()) {
+ has_detection_switched = true;
+ }
+ ASSERT_EQ(
+ has_detection_switched ? is_detecting_after : was_detecting_before,
+ sampler()->HasProposal());
+
+ if (sampler()->HasProposal()) {
+ // Make sure the sampler doesn't flip-flop and keep proposing sampling
+ // based on locking into different regions.
+ if (first_detected_region.IsEmpty()) {
+ first_detected_region = sampler()->detected_region();
+ ASSERT_FALSE(first_detected_region.IsEmpty());
+ } else {
+ EXPECT_EQ(first_detected_region, sampler()->detected_region());
+ }
+
+ if (simulate_pipeline_back_pressure && GetRandomInRange(0, 2) == 0)
+ ClientCannotSampleFrame(*i);
+ else
+ ClientDoesWhatSamplerProposes(*i);
+ } else {
+ EXPECT_FALSE(sampler()->ShouldSample());
+ if (!simulate_pipeline_back_pressure || GetRandomInRange(0, 2) == 1)
+ sampler()->RecordSample(i->second);
+ }
+ }
+ EXPECT_EQ(is_detecting_after, sampler()->HasProposal());
+ ExpectFrameDropRatioIsCorrect();
+ }
+
+ void ResetFrameCounters() {
+ count_dropped_frames_ = 0;
+ count_sampled_frames_ = 0;
+ }
+
+ // Keep track what the sampler is proposing, and call RecordSample() if it
+ // proposes sampling |event|.
+ void ClientDoesWhatSamplerProposes(const Event& event) {
+ if (sampler()->ShouldSample()) {
+ EXPECT_EQ(GetContentDamageRect(), event.first);
+ sampler()->RecordSample(sampler()->frame_timestamp());
+ ++count_sampled_frames_;
+ } else if (event.first == GetContentDamageRect()) {
+ ++count_dropped_frames_;
+ }
+ }
+
+ // RecordSample() is not called, but for testing, keep track of what the
+ // sampler is proposing for |event|.
+ void ClientCannotSampleFrame(const Event& event) {
+ if (sampler()->ShouldSample()) {
+ EXPECT_EQ(GetContentDamageRect(), event.first);
+ ++count_sampled_frames_;
+ } else if (event.first == GetContentDamageRect()) {
+ ++count_dropped_frames_;
+ }
+ }
+
+ // Confirm the AnimatedContentSampler is not dropping more frames than
+ // expected, given current test parameters.
+ void ExpectFrameDropRatioIsCorrect() {
+ if (count_sampled_frames_ == 0) {
+ EXPECT_EQ(0, count_dropped_frames_);
+ return;
+ }
+ const double content_framerate =
+ 1000000.0 / GetParam().content_period.InMicroseconds();
+ const double capture_framerate =
+ 1000000.0 / GetParam().min_capture_period.InMicroseconds();
+ const double expected_drop_rate = std::max(
+ 0.0, (content_framerate - capture_framerate) / capture_framerate);
+ const double actual_drop_rate =
+ static_cast<double>(count_dropped_frames_) / count_sampled_frames_;
+ EXPECT_NEAR(expected_drop_rate, actual_drop_rate, 0.015);
+ }
+
+ private:
+ // These counters only include the frames with the desired content.
+ int count_dropped_frames_;
+ int count_sampled_frames_;
+};
+
+// Tests that the implementation locks in/out of frames containing stable
+// animated content, whether or not random events are also simultaneously
+// present.
+TEST_P(AnimatedContentSamplerParameterizedTest, DetectsAnimatedContent) {
+ // |begin| refers to the start of an event sequence in terms of the
+ // Compositor's clock.
+ base::TimeTicks begin = InitialTestTimeTicks();
+
+ // Provide random events and expect no lock-in.
+ base::TimeTicks end = begin + base::TimeDelta::FromSeconds(5);
+ RunEventSequence(GenerateEventSequence(begin, end, false, true),
+ false,
+ false,
+ false);
+ begin = end;
+
+ // Provide content frame events with some random events mixed-in, and expect
+ // the sampler to lock-in.
+ end = begin + base::TimeDelta::FromSeconds(5);
+ RunEventSequence(GenerateEventSequence(begin, end, true, true),
+ false,
+ true,
+ false);
+ begin = end;
+
+ // Continue providing content frame events without the random events mixed-in
+ // and expect the lock-in to hold.
+ end = begin + base::TimeDelta::FromSeconds(5);
+ RunEventSequence(GenerateEventSequence(begin, end, true, false),
+ true,
+ true,
+ false);
+ begin = end;
+
+ // Continue providing just content frame events and expect the lock-in to
+ // hold. Also simulate the capture pipeline experiencing back pressure.
+ end = begin + base::TimeDelta::FromSeconds(20);
+ RunEventSequence(GenerateEventSequence(begin, end, true, false),
+ true,
+ true,
+ true);
+ begin = end;
+
+ // Provide a half-second of random events only, and expect the lock-in to be
+ // broken.
+ end = begin + base::TimeDelta::FromMilliseconds(500);
+ RunEventSequence(GenerateEventSequence(begin, end, false, true),
+ true,
+ false,
+ false);
+ begin = end;
+
+ // Now, go back to providing content frame events, and expect the sampler to
+ // lock-in once again.
+ end = begin + base::TimeDelta::FromSeconds(5);
+ RunEventSequence(GenerateEventSequence(begin, end, true, false),
+ false,
+ true,
+ false);
+ begin = end;
+}
+
+// Tests that AnimatedContentSampler won't lock in to, nor flip-flop between,
+// two animations of the same pixel change rate. VideoCaptureOracle should
+// revert to using the SmoothEventSampler for these kinds of situations, as
+// there is no "right answer" as to which animation to lock into.
+TEST_P(AnimatedContentSamplerParameterizedTest,
+ DoesNotLockInToTwoCompetingAnimations) {
+ // Don't test when the event stream cannot indicate two separate content
+ // animations under the current test parameters.
+ if (GetParam().content_period < 2 * GetParam().vsync_interval)
+ return;
+
+ // Start the first animation and run for a bit, and expect the sampler to
+ // lock-in.
+ base::TimeTicks begin = InitialTestTimeTicks();
+ base::TimeTicks end = begin + base::TimeDelta::FromSeconds(5);
+ RunEventSequence(GenerateEventSequence(begin, end, true, false),
+ false,
+ true,
+ false);
+ begin = end;
+
+ // Now, keep the first animation and blend in an second animation of the same
+ // size and frame rate, but at a different position. This will should cause
+ // the sampler to enter an "undetected" state since it's unclear which
+ // animation should be locked into.
+ end = begin + base::TimeDelta::FromSeconds(20);
+ std::vector<Event> first_animation_events =
+ GenerateEventSequence(begin, end, true, false);
+ gfx::Rect second_animation_rect(
+ gfx::Point(0, GetContentDamageRect().height()),
+ GetContentDamageRect().size());
+ std::vector<Event> both_animations_events;
+ base::TimeDelta second_animation_offset = GetParam().vsync_interval;
+ for (std::vector<Event>::const_iterator i = first_animation_events.begin();
+ i != first_animation_events.end(); ++i) {
+ both_animations_events.push_back(*i);
+ both_animations_events.push_back(
+ Event(second_animation_rect, i->second + second_animation_offset));
+ }
+ RunEventSequence(both_animations_events, true, false, false);
+ begin = end;
+
+ // Now, run just the first animation, and expect the sampler to lock-in once
+ // again.
+ end = begin + base::TimeDelta::FromSeconds(5);
+ RunEventSequence(GenerateEventSequence(begin, end, true, false),
+ false,
+ true,
+ false);
+ begin = end;
+
+ // Now, blend in the second animation again, but it has half the frame rate of
+ // the first animation and damage Rects with twice the area. This will should
+ // cause the sampler to enter an "undetected" state again. This tests that
+ // pixel-weighting is being accounted for in the sampler's logic.
+ end = begin + base::TimeDelta::FromSeconds(20);
+ first_animation_events = GenerateEventSequence(begin, end, true, false);
+ second_animation_rect.set_width(second_animation_rect.width() * 2);
+ both_animations_events.clear();
+ bool include_second_animation_frame = true;
+ for (std::vector<Event>::const_iterator i = first_animation_events.begin();
+ i != first_animation_events.end(); ++i) {
+ both_animations_events.push_back(*i);
+ if (include_second_animation_frame) {
+ both_animations_events.push_back(
+ Event(second_animation_rect, i->second + second_animation_offset));
+ }
+ include_second_animation_frame = !include_second_animation_frame;
+ }
+ RunEventSequence(both_animations_events, true, false, false);
+ begin = end;
+}
+
+// Tests that the frame timestamps are smooth; meaning, that when run through a
+// simulated compositor, each frame is held displayed for the right number of
+// v-sync intervals.
+TEST_P(AnimatedContentSamplerParameterizedTest, FrameTimestampsAreSmooth) {
+ // Generate 30 seconds of animated content events, run the events through
+ // AnimatedContentSampler, and record all frame timestamps being proposed
+ // once lock-in is continuous.
+ base::TimeTicks begin = InitialTestTimeTicks();
+ std::vector<Event> events = GenerateEventSequence(
+ begin,
+ begin + base::TimeDelta::FromSeconds(20),
+ true,
+ false);
+ typedef std::vector<base::TimeTicks> Timestamps;
+ Timestamps frame_timestamps;
+ for (std::vector<Event>::const_iterator i = events.begin(); i != events.end();
+ ++i) {
+ sampler()->ConsiderPresentationEvent(i->first, i->second);
+ if (sampler()->HasProposal()) {
+ if (sampler()->ShouldSample()) {
+ frame_timestamps.push_back(sampler()->frame_timestamp());
+ sampler()->RecordSample(sampler()->frame_timestamp());
+ }
+ } else {
+ frame_timestamps.clear(); // Reset until continuous lock-in.
+ }
+ }
+ ASSERT_LE(2u, frame_timestamps.size());
+
+ // Iterate through the |frame_timestamps|, building a histogram counting the
+ // number of times each frame was displayed k times. For example, 10 frames
+ // of 30 Hz content on a 60 Hz v-sync interval should result in
+ // display_counts[2] == 10. Quit early if any one frame was obviously
+ // repeated too many times.
+ const int64 max_expected_repeats_per_frame = 1 +
+ std::max(GetParam().min_capture_period, GetParam().content_period) /
+ GetParam().vsync_interval;
+ std::vector<size_t> display_counts(max_expected_repeats_per_frame + 1, 0);
+ base::TimeTicks last_present_time = frame_timestamps.front();
+ for (Timestamps::const_iterator i = frame_timestamps.begin() + 1;
+ i != frame_timestamps.end(); ++i) {
+ const size_t num_vsync_intervals = static_cast<size_t>(
+ (*i - last_present_time) / GetParam().vsync_interval);
+ ASSERT_LT(0u, num_vsync_intervals);
+ ASSERT_GT(display_counts.size(), num_vsync_intervals); // Quit early.
+ ++display_counts[num_vsync_intervals];
+ last_present_time += num_vsync_intervals * GetParam().vsync_interval;
+ }
+
+ // Analyze the histogram for an expected result pattern. If the frame
+ // timestamps are smooth, there should only be one or two buckets with
+ // non-zero counts and they should be next to each other. Because the clock
+ // precision for the event_times provided to the sampler is very granular
+ // (i.e., the vsync_interval), it's okay if other buckets have a tiny "stray"
+ // count in this test.
+ size_t highest_count = 0;
+ size_t second_highest_count = 0;
+ for (size_t repeats = 1; repeats < display_counts.size(); ++repeats) {
+ DVLOG(1) << "display_counts[" << repeats << "] is "
+ << display_counts[repeats];
+ if (display_counts[repeats] >= highest_count) {
+ second_highest_count = highest_count;
+ highest_count = display_counts[repeats];
+ } else if (display_counts[repeats] > second_highest_count) {
+ second_highest_count = display_counts[repeats];
+ }
+ }
+ size_t stray_count_remaining =
+ (frame_timestamps.size() - 1) - (highest_count + second_highest_count);
+ // Expect no more than 0.75% of frames fall outside the two main buckets.
+ EXPECT_GT(frame_timestamps.size() * 75 / 10000, stray_count_remaining);
+ for (size_t repeats = 1; repeats < display_counts.size() - 1; ++repeats) {
+ if (display_counts[repeats] == highest_count) {
+ EXPECT_EQ(second_highest_count, display_counts[repeats + 1]);
+ ++repeats;
+ } else if (display_counts[repeats] == second_highest_count) {
+ EXPECT_EQ(highest_count, display_counts[repeats + 1]);
+ ++repeats;
+ } else {
+ EXPECT_GE(stray_count_remaining, display_counts[repeats]);
+ stray_count_remaining -= display_counts[repeats];
+ }
+ }
+}
+
+// Tests that frame timestamps are "lightly pushed" back towards the original
+// presentation event times, which tells us the AnimatedContentSampler can
+// account for sources of timestamp drift and correct the drift.
+TEST_P(AnimatedContentSamplerParameterizedTest,
+ FrameTimestampsConvergeTowardsEventTimes) {
+ const int max_drift_increment_millis = 3;
+
+ // Generate a full minute of events.
+ const base::TimeTicks begin = InitialTestTimeTicks();
+ const base::TimeTicks end = begin + base::TimeDelta::FromMinutes(1);
+ std::vector<Event> events = GenerateEventSequence(begin, end, true, false);
+
+ // Modify the event sequence so that 1-3 ms of additional drift is suddenly
+ // present every 100 events. This is meant to simulate that, external to
+ // AnimatedContentSampler, the video hardware vsync timebase is being
+ // refreshed and is showing severe drift from the system clock.
+ base::TimeDelta accumulated_drift;
+ for (size_t i = 1; i < events.size(); ++i) {
+ if (i % 100 == 0) {
+ accumulated_drift += base::TimeDelta::FromMilliseconds(
+ GetRandomInRange(1, max_drift_increment_millis + 1));
+ }
+ events[i].second += accumulated_drift;
+ }
+
+ // Run all the events through the sampler and track the last rewritten frame
+ // timestamp.
+ base::TimeTicks last_frame_timestamp;
+ for (std::vector<Event>::const_iterator i = events.begin(); i != events.end();
+ ++i) {
+ sampler()->ConsiderPresentationEvent(i->first, i->second);
+ if (sampler()->ShouldSample())
+ last_frame_timestamp = sampler()->frame_timestamp();
+ }
+
+ // If drift was accounted for, the |last_frame_timestamp| should be close to
+ // the last event's timestamp.
+ const base::TimeDelta total_error =
+ events.back().second - last_frame_timestamp;
+ const base::TimeDelta max_acceptable_error = GetParam().min_capture_period +
+ base::TimeDelta::FromMilliseconds(max_drift_increment_millis);
+ EXPECT_NEAR(0.0,
+ total_error.InMicroseconds(),
+ max_acceptable_error.InMicroseconds());
+}
+
+INSTANTIATE_TEST_CASE_P(
+ ,
+ AnimatedContentSamplerParameterizedTest,
+ ::testing::Values(
+ // Typical frame rate content: Compositor runs at 60 Hz, capture at 30
+ // Hz, and content video animates at 30, 25, or 24 Hz.
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(30)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(25)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(24)),
+
+ // High frame rate content that leverages the Compositor's
+ // capabilities, but capture is still at 30 Hz.
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(60)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(50)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(48)),
+
+ // High frame rate content that leverages the Compositor's
+ // capabilities, and capture is also a buttery 60 Hz.
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(60)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(50)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(48)),
+
+ // On some platforms, the Compositor runs at 50 Hz.
+ Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(30)),
+ Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(25)),
+ Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(24)),
+ Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(50)),
+ Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(48)),
+
+ // Stable, but non-standard content frame rates.
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(16)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(20)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(23)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(26)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(27)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(28)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(29)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(31)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(32)),
+ Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(33))));
+
+// Tests that VideoCaptureOracle filters out events whose timestamps are
+// decreasing.
+TEST(VideoCaptureOracleTest, EnforcesEventTimeMonotonicity) {
+ const base::TimeDelta min_capture_period =
+ base::TimeDelta::FromSeconds(1) / 30;
+ const gfx::Rect damage_rect(0, 0, 1280, 720);
+ const base::TimeDelta event_increment = min_capture_period * 2;
+
+ VideoCaptureOracle oracle(min_capture_period, true);
+
+ base::TimeTicks t = InitialTestTimeTicks();
+ for (int i = 0; i < 10; ++i) {
+ t += event_increment;
+ ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ damage_rect, t));
+ }
+
+ base::TimeTicks furthest_event_time = t;
+ for (int i = 0; i < 10; ++i) {
+ t -= event_increment;
+ ASSERT_FALSE(oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ damage_rect, t));
+ }
+
+ t = furthest_event_time;
+ for (int i = 0; i < 10; ++i) {
+ t += event_increment;
+ ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ damage_rect, t));
+ }
+}
+
+// Tests that VideoCaptureOracle is enforcing the requirement that captured
+// frames are delivered in order. Otherwise, downstream consumers could be
+// tripped-up by out-of-order frames or frame timestamps.
+TEST(VideoCaptureOracleTest, EnforcesFramesDeliveredInOrder) {
+ const base::TimeDelta min_capture_period =
+ base::TimeDelta::FromSeconds(1) / 30;
+ const gfx::Rect damage_rect(0, 0, 1280, 720);
+ const base::TimeDelta event_increment = min_capture_period * 2;
+
+ VideoCaptureOracle oracle(min_capture_period, true);
+
+ // Most basic scenario: Frames delivered one at a time, with no additional
+ // captures in-between deliveries.
+ base::TimeTicks t = InitialTestTimeTicks();
+ int last_frame_number;
+ base::TimeTicks ignored;
+ for (int i = 0; i < 10; ++i) {
+ t += event_increment;
+ ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ damage_rect, t));
+ last_frame_number = oracle.RecordCapture();
+ ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, &ignored));
+ }
+
+ // Basic pipelined scenario: More than one frame in-flight at delivery points.
+ for (int i = 0; i < 50; ++i) {
+ const int num_in_flight = 1 + i % 3;
+ for (int j = 0; j < num_in_flight; ++j) {
+ t += event_increment;
+ ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ damage_rect, t));
+ last_frame_number = oracle.RecordCapture();
+ }
+ for (int j = num_in_flight - 1; j >= 0; --j) {
+ ASSERT_TRUE(oracle.CompleteCapture(last_frame_number - j, &ignored));
+ }
+ }
+
+ // Pipelined scenario with out-of-order delivery attempts rejected.
+ for (int i = 0; i < 50; ++i) {
+ const int num_in_flight = 1 + i % 3;
+ for (int j = 0; j < num_in_flight; ++j) {
+ t += event_increment;
+ ASSERT_TRUE(oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ damage_rect, t));
+ last_frame_number = oracle.RecordCapture();
+ }
+ ASSERT_TRUE(oracle.CompleteCapture(last_frame_number, &ignored));
+ for (int j = 1; j < num_in_flight; ++j) {
+ ASSERT_FALSE(oracle.CompleteCapture(last_frame_number - j, &ignored));
+ }
+ }
+}
+
+// Tests that VideoCaptureOracle transitions between using its two samplers in a
+// way that does not introduce severe jank, pauses, etc.
+TEST(VideoCaptureOracleTest, TransitionsSmoothlyBetweenSamplers) {
+ const base::TimeDelta min_capture_period =
+ base::TimeDelta::FromSeconds(1) / 30;
+ const gfx::Rect animation_damage_rect(0, 0, 1280, 720);
+ const base::TimeDelta event_increment = min_capture_period * 2;
+
+ VideoCaptureOracle oracle(min_capture_period, true);
+
+ // Run sequences of animation events and non-animation events through the
+ // oracle. As the oracle transitions between each sampler, make sure the
+ // frame timestamps won't trip-up downstream consumers.
+ base::TimeTicks t = InitialTestTimeTicks();
+ base::TimeTicks last_frame_timestamp;
+ for (int i = 0; i < 1000; ++i) {
+ t += event_increment;
+
+ // For every 100 events, provide 50 that will cause the
+ // AnimatedContentSampler to lock-in, followed by 50 that will cause it to
+ // lock-out (i.e., the oracle will use the SmoothEventSampler instead).
+ const bool provide_animated_content_event =
+ (i % 100) >= 25 && (i % 100) < 75;
+
+ // Only the few events that trigger the lock-out transition should be
+ // dropped, because the AnimatedContentSampler doesn't yet realize the
+ // animation ended. Otherwise, the oracle should always decide to sample
+ // because one of its samplers says to.
+ const bool require_oracle_says_sample = (i % 100) < 75 || (i % 100) >= 78;
+ const bool oracle_says_sample = oracle.ObserveEventAndDecideCapture(
+ VideoCaptureOracle::kCompositorUpdate,
+ provide_animated_content_event ? animation_damage_rect : gfx::Rect(),
+ t);
+ if (require_oracle_says_sample)
+ ASSERT_TRUE(oracle_says_sample);
+ if (!oracle_says_sample)
+ continue;
+
+ const int frame_number = oracle.RecordCapture();
+
+ base::TimeTicks frame_timestamp;
+ ASSERT_TRUE(oracle.CompleteCapture(frame_number, &frame_timestamp));
+ ASSERT_FALSE(frame_timestamp.is_null());
+ if (!last_frame_timestamp.is_null()) {
+ const base::TimeDelta delta = frame_timestamp - last_frame_timestamp;
+ EXPECT_LE(event_increment.InMicroseconds(), delta.InMicroseconds());
+ // Right after the AnimatedContentSampler lock-out transition, there were
+ // a few frames dropped, so allow a gap in the timestamps. Otherwise, the
+ // delta between frame timestamps should never be more than 2X the
+ // |event_increment|.
+ const base::TimeDelta max_acceptable_delta = (i % 100) == 78 ?
+ event_increment * 5 : event_increment * 2;
+ EXPECT_GE(max_acceptable_delta.InMicroseconds(), delta.InMicroseconds());
+ }
+ last_frame_timestamp = frame_timestamp;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
index ad5a33f6923..605124dd308 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
@@ -15,8 +15,11 @@
#include "content/browser/media/capture/web_contents_capture_util.h"
#include "content/browser/media/capture/web_contents_tracker.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
#include "media/audio/virtual_audio_input_stream.h"
#include "media/audio/virtual_audio_output_stream.h"
+#include "media/base/bind_to_current_loop.h"
namespace content {
@@ -25,7 +28,7 @@ class WebContentsAudioInputStream::Impl
public AudioMirroringManager::MirroringDestination {
public:
// Takes ownership of |mixer_stream|. The rest outlive this instance.
- Impl(int render_process_id, int render_view_id,
+ Impl(int render_process_id, int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream);
@@ -52,6 +55,8 @@ class WebContentsAudioInputStream::Impl
private:
friend class base::RefCountedThreadSafe<WebContentsAudioInputStream::Impl>;
+ typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
+
enum State {
CONSTRUCTED,
OPENED,
@@ -59,31 +64,38 @@ class WebContentsAudioInputStream::Impl
CLOSED
};
- virtual ~Impl();
-
- // Returns true if the mirroring target has been permanently lost.
- bool IsTargetLost() const;
+ ~Impl() override;
// Notifies the consumer callback that the stream is now dead.
void ReportError();
- // Start/Stop mirroring by posting a call to AudioMirroringManager on the IO
- // BrowserThread.
+ // (Re-)Start/Stop mirroring by posting a call to AudioMirroringManager on the
+ // IO BrowserThread.
void StartMirroring();
void StopMirroring();
+ // Invoked on the UI thread to make sure WebContents muting is turned off for
+ // successful audio capture.
+ void UnmuteWebContentsAudio();
+
// AudioMirroringManager::MirroringDestination implementation
- virtual media::AudioOutputStream* AddInput(
- const media::AudioParameters& params) OVERRIDE;
+ void QueryForMatches(const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) override;
+ void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback);
+ media::AudioOutputStream* AddInput(
+ const media::AudioParameters& params) override;
// Callback which is run when |stream| is closed. Deletes |stream|.
void ReleaseInput(media::VirtualAudioOutputStream* stream);
// Called by WebContentsTracker when the target of the audio mirroring has
// changed.
- void OnTargetChanged(int render_process_id, int render_view_id);
+ void OnTargetChanged(RenderWidgetHost* target);
// Injected dependencies.
+ const int initial_render_process_id_;
+ const int initial_main_render_frame_id_;
AudioMirroringManager* const mirroring_manager_;
const scoped_refptr<WebContentsTracker> tracker_;
// The AudioInputStream implementation that handles the audio conversion and
@@ -92,9 +104,9 @@ class WebContentsAudioInputStream::Impl
State state_;
- // Current audio mirroring target.
- int target_render_process_id_;
- int target_render_view_id_;
+ // Set to true if |tracker_| reports a NULL target, which indicates the target
+ // is permanently lost.
+ bool is_target_lost_;
// Current callback used to consume the resulting mixed audio data.
AudioInputCallback* callback_;
@@ -105,14 +117,17 @@ class WebContentsAudioInputStream::Impl
};
WebContentsAudioInputStream::Impl::Impl(
- int render_process_id, int render_view_id,
+ int render_process_id, int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream)
- : mirroring_manager_(mirroring_manager),
- tracker_(tracker), mixer_stream_(mixer_stream), state_(CONSTRUCTED),
- target_render_process_id_(render_process_id),
- target_render_view_id_(render_view_id),
+ : initial_render_process_id_(render_process_id),
+ initial_main_render_frame_id_(main_render_frame_id),
+ mirroring_manager_(mirroring_manager),
+ tracker_(tracker),
+ mixer_stream_(mixer_stream),
+ state_(CONSTRUCTED),
+ is_target_lost_(false),
callback_(NULL) {
DCHECK(mirroring_manager_);
DCHECK(tracker_.get());
@@ -138,7 +153,7 @@ bool WebContentsAudioInputStream::Impl::Open() {
state_ = OPENED;
tracker_->Start(
- target_render_process_id_, target_render_view_id_,
+ initial_render_process_id_, initial_main_render_frame_id_,
base::Bind(&Impl::OnTargetChanged, this));
return true;
@@ -152,7 +167,7 @@ void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) {
return;
callback_ = callback;
- if (IsTargetLost()) {
+ if (is_target_lost_) {
ReportError();
callback_ = NULL;
return;
@@ -162,6 +177,14 @@ void WebContentsAudioInputStream::Impl::Start(AudioInputCallback* callback) {
mixer_stream_->Start(callback);
StartMirroring();
+
+ // WebContents audio muting is implemented as audio capture to nowhere.
+ // Unmuting will stop that audio capture, allowing AudioMirroringManager to
+ // divert audio capture to here.
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&Impl::UnmuteWebContentsAudio, this));
}
void WebContentsAudioInputStream::Impl::Stop() {
@@ -175,8 +198,7 @@ void WebContentsAudioInputStream::Impl::Stop() {
mixer_stream_->Stop();
callback_ = NULL;
- if (!IsTargetLost())
- StopMirroring();
+ StopMirroring();
}
void WebContentsAudioInputStream::Impl::Close() {
@@ -194,12 +216,6 @@ void WebContentsAudioInputStream::Impl::Close() {
state_ = CLOSED;
}
-bool WebContentsAudioInputStream::Impl::IsTargetLost() const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- return target_render_process_id_ <= 0 || target_render_view_id_ <= 0;
-}
-
void WebContentsAudioInputStream::Impl::ReportError() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -216,7 +232,6 @@ void WebContentsAudioInputStream::Impl::StartMirroring() {
FROM_HERE,
base::Bind(&AudioMirroringManager::StartMirroring,
base::Unretained(mirroring_manager_),
- target_render_process_id_, target_render_view_id_,
make_scoped_refptr(this)));
}
@@ -228,10 +243,52 @@ void WebContentsAudioInputStream::Impl::StopMirroring() {
FROM_HERE,
base::Bind(&AudioMirroringManager::StopMirroring,
base::Unretained(mirroring_manager_),
- target_render_process_id_, target_render_view_id_,
make_scoped_refptr(this)));
}
+void WebContentsAudioInputStream::Impl::UnmuteWebContentsAudio() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ WebContents* const contents = tracker_->web_contents();
+ if (contents)
+ contents->SetAudioMuted(false);
+}
+
+void WebContentsAudioInputStream::Impl::QueryForMatches(
+ const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&Impl::QueryForMatchesOnUIThread,
+ this,
+ candidates,
+ media::BindToCurrentLoop(results_callback)));
+}
+
+void WebContentsAudioInputStream::Impl::QueryForMatchesOnUIThread(
+ const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ std::set<SourceFrameRef> matches;
+ WebContents* const contents = tracker_->web_contents();
+ if (contents) {
+ // Add each ID to |matches| if it maps to a RenderFrameHost that maps to the
+ // currently-tracked WebContents.
+ for (std::set<SourceFrameRef>::const_iterator i = candidates.begin();
+ i != candidates.end(); ++i) {
+ WebContents* const contents_containing_frame =
+ WebContents::FromRenderFrameHost(
+ RenderFrameHost::FromID(i->first, i->second));
+ if (contents_containing_frame == contents)
+ matches.insert(*i);
+ }
+ }
+
+ results_callback.Run(matches);
+}
+
media::AudioOutputStream* WebContentsAudioInputStream::Impl::AddInput(
const media::AudioParameters& params) {
// Note: The closure created here holds a reference to "this," which will
@@ -248,27 +305,14 @@ void WebContentsAudioInputStream::Impl::ReleaseInput(
delete stream;
}
-void WebContentsAudioInputStream::Impl::OnTargetChanged(int render_process_id,
- int render_view_id) {
+void WebContentsAudioInputStream::Impl::OnTargetChanged(
+ RenderWidgetHost* target) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (target_render_process_id_ == render_process_id &&
- target_render_view_id_ == render_view_id) {
- return;
- }
-
- DVLOG(1) << "Target RenderView has changed from "
- << target_render_process_id_ << ':' << target_render_view_id_
- << " to " << render_process_id << ':' << render_view_id;
-
- if (state_ == MIRRORING)
- StopMirroring();
-
- target_render_process_id_ = render_process_id;
- target_render_view_id_ = render_view_id;
+ is_target_lost_ = !target;
if (state_ == MIRRORING) {
- if (IsTargetLost()) {
+ if (is_target_lost_) {
ReportError();
Stop();
} else {
@@ -284,27 +328,27 @@ WebContentsAudioInputStream* WebContentsAudioInputStream::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
AudioMirroringManager* audio_mirroring_manager) {
int render_process_id;
- int render_view_id;
+ int main_render_frame_id;
if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
- device_id, &render_process_id, &render_view_id)) {
+ device_id, &render_process_id, &main_render_frame_id)) {
return NULL;
}
return new WebContentsAudioInputStream(
- render_process_id, render_view_id,
+ render_process_id, main_render_frame_id,
audio_mirroring_manager,
- new WebContentsTracker(),
+ new WebContentsTracker(false),
new media::VirtualAudioInputStream(
params, worker_task_runner,
media::VirtualAudioInputStream::AfterCloseCallback()));
}
WebContentsAudioInputStream::WebContentsAudioInputStream(
- int render_process_id, int render_view_id,
+ int render_process_id, int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream)
- : impl_(new Impl(render_process_id, render_view_id,
+ : impl_(new Impl(render_process_id, main_render_frame_id,
mirroring_manager, tracker, mixer_stream)) {}
WebContentsAudioInputStream::~WebContentsAudioInputStream() {}
@@ -346,4 +390,8 @@ bool WebContentsAudioInputStream::GetAutomaticGainControl() {
return impl_->mixer_stream()->GetAutomaticGainControl();
}
+bool WebContentsAudioInputStream::IsMuted() {
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.h b/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
index c0a2c6afd7f..d66d27004b5 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.h
@@ -3,15 +3,12 @@
// found in the LICENSE file.
//
// An AudioInputStream which provides a loop-back of all audio output generated
-// by the RenderView associated with a WebContents instance. The single stream
-// of data is produced by format-converting and mixing all audio output from a
-// RenderView. In other words, WebContentsAudioInputStream provides tab-level
+// by the entire RenderFrame tree associated with a WebContents instance. The
+// single stream of data is produced by format-converting and mixing all audio
+// output streams. As the RenderFrameHost tree mutates (e.g., due to page
+// navigations, or crashes/reloads), the stream will continue without
+// interruption. In other words, WebContentsAudioInputStream provides tab-level
// audio mirroring.
-//
-// The implementation observes a WebContents instance (which represents a
-// browser tab) so that it can track the replacement of RenderViews due to
-// navigation, crash/reload, etc. events; and take appropriate actions to
-// provide a seamless, uninterrupted mirroring experience.
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_AUDIO_INPUT_STREAM_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_AUDIO_INPUT_STREAM_H_
@@ -40,15 +37,16 @@ class CONTENT_EXPORT WebContentsAudioInputStream
: NON_EXPORTED_BASE(public media::AudioInputStream) {
public:
// media::AudioInputStream implementation
- virtual bool Open() OVERRIDE;
- virtual void Start(AudioInputCallback* callback) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual double GetMaxVolume() OVERRIDE;
- virtual void SetVolume(double volume) OVERRIDE;
- virtual double GetVolume() OVERRIDE;
- virtual void SetAutomaticGainControl(bool enabled) OVERRIDE;
- virtual bool GetAutomaticGainControl() OVERRIDE;
+ bool Open() override;
+ void Start(AudioInputCallback* callback) override;
+ void Stop() override;
+ void Close() override;
+ double GetMaxVolume() override;
+ void SetVolume(double volume) override;
+ double GetVolume() override;
+ void SetAutomaticGainControl(bool enabled) override;
+ bool GetAutomaticGainControl() override;
+ bool IsMuted() override;
// Create a new audio mirroring session, or return NULL on error. |device_id|
// should be in the format accepted by
@@ -75,12 +73,12 @@ class CONTENT_EXPORT WebContentsAudioInputStream
class Impl;
WebContentsAudioInputStream(
- int render_process_id, int render_view_id,
+ int render_process_id, int main_render_frame_id,
AudioMirroringManager* mirroring_manager,
const scoped_refptr<WebContentsTracker>& tracker,
media::VirtualAudioInputStream* mixer_stream);
- virtual ~WebContentsAudioInputStream();
+ ~WebContentsAudioInputStream() override;
scoped_refptr<Impl> impl_;
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
index 72f6109029d..9772c9457ce 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
@@ -11,9 +11,10 @@
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
-#include "content/browser/browser_thread_impl.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/capture/web_contents_tracker.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/simple_sources.h"
#include "media/audio/virtual_audio_input_stream.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -40,9 +41,9 @@ namespace content {
namespace {
const int kRenderProcessId = 123;
-const int kRenderViewId = 456;
+const int kRenderFrameId = 456;
const int kAnotherRenderProcessId = 789;
-const int kAnotherRenderViewId = 1;
+const int kAnotherRenderFrameId = 1;
const AudioParameters& TestAudioParameters() {
static const AudioParameters params(
@@ -58,12 +59,8 @@ class MockAudioMirroringManager : public AudioMirroringManager {
MockAudioMirroringManager() : AudioMirroringManager() {}
virtual ~MockAudioMirroringManager() {}
- MOCK_METHOD3(StartMirroring,
- void(int render_process_id, int render_view_id,
- MirroringDestination* destination));
- MOCK_METHOD3(StopMirroring,
- void(int render_process_id, int render_view_id,
- MirroringDestination* destination));
+ MOCK_METHOD1(StartMirroring, void(MirroringDestination* destination));
+ MOCK_METHOD1(StopMirroring, void(MirroringDestination* destination));
private:
DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
@@ -71,10 +68,10 @@ class MockAudioMirroringManager : public AudioMirroringManager {
class MockWebContentsTracker : public WebContentsTracker {
public:
- MockWebContentsTracker() : WebContentsTracker() {}
+ MockWebContentsTracker() : WebContentsTracker(false) {}
MOCK_METHOD3(Start,
- void(int render_process_id, int render_view_id,
+ void(int render_process_id, int render_frame_id,
const ChangeCallback& callback));
MOCK_METHOD0(Stop, void());
@@ -177,23 +174,23 @@ class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
class WebContentsAudioInputStreamTest : public testing::Test {
public:
WebContentsAudioInputStreamTest()
- : audio_thread_("Audio thread"),
- io_thread_(BrowserThread::IO),
+ : thread_bundle_(new TestBrowserThreadBundle(
+ TestBrowserThreadBundle::REAL_IO_THREAD)),
+ audio_thread_("Audio thread"),
mock_mirroring_manager_(new MockAudioMirroringManager()),
mock_tracker_(new MockWebContentsTracker()),
mock_vais_(NULL),
wcais_(NULL),
destination_(NULL),
current_render_process_id_(kRenderProcessId),
- current_render_view_id_(kRenderViewId),
+ current_render_frame_id_(kRenderFrameId),
on_data_event_(false, false) {
audio_thread_.Start();
- io_thread_.Start();
}
- virtual ~WebContentsAudioInputStreamTest() {
+ ~WebContentsAudioInputStreamTest() override {
audio_thread_.Stop();
- io_thread_.Stop();
+ thread_bundle_.reset();
DCHECK(!mock_vais_);
DCHECK(!wcais_);
@@ -209,16 +206,19 @@ class WebContentsAudioInputStreamTest : public testing::Test {
EXPECT_CALL(*mock_vais_, Close()); // At Close() time.
ASSERT_EQ(kRenderProcessId, current_render_process_id_);
- ASSERT_EQ(kRenderViewId, current_render_view_id_);
- EXPECT_CALL(*mock_tracker_.get(), Start(kRenderProcessId, kRenderViewId, _))
+ ASSERT_EQ(kRenderFrameId, current_render_frame_id_);
+ EXPECT_CALL(*mock_tracker_.get(),
+ Start(kRenderProcessId, kRenderFrameId, _))
.WillOnce(DoAll(
SaveArg<2>(&change_callback_),
- WithArgs<0, 1>(Invoke(&change_callback_,
- &WebContentsTracker::ChangeCallback::Run))));
+ WithArgs<0, 1>(Invoke(this,
+ &WebContentsAudioInputStreamTest::
+ SimulateChangeCallback))));
+
EXPECT_CALL(*mock_tracker_.get(), Stop()); // At Close() time.
wcais_ = new WebContentsAudioInputStream(
- current_render_process_id_, current_render_view_id_,
+ current_render_process_id_, current_render_frame_id_,
mock_mirroring_manager_.get(),
mock_tracker_, mock_vais_);
wcais_->Open();
@@ -228,13 +228,11 @@ class WebContentsAudioInputStreamTest : public testing::Test {
EXPECT_CALL(*mock_vais_, Start(&mock_input_callback_));
EXPECT_CALL(*mock_vais_, Stop()); // At Stop() time.
- EXPECT_CALL(*mock_mirroring_manager_,
- StartMirroring(kRenderProcessId, kRenderViewId, NotNull()))
- .WillOnce(SaveArg<2>(&destination_))
+ EXPECT_CALL(*mock_mirroring_manager_, StartMirroring(NotNull()))
+ .WillOnce(SaveArg<0>(&destination_))
.RetiresOnSaturation();
// At Stop() time, or when the mirroring target changes:
- EXPECT_CALL(*mock_mirroring_manager_,
- StopMirroring(kRenderProcessId, kRenderViewId, NotNull()))
+ EXPECT_CALL(*mock_mirroring_manager_, StopMirroring(NotNull()))
.WillOnce(Assign(
&destination_,
static_cast<AudioMirroringManager::MirroringDestination*>(NULL)))
@@ -308,38 +306,24 @@ class WebContentsAudioInputStreamTest : public testing::Test {
const int next_render_process_id =
current_render_process_id_ == kRenderProcessId ?
kAnotherRenderProcessId : kRenderProcessId;
- const int next_render_view_id =
- current_render_view_id_ == kRenderViewId ?
- kAnotherRenderViewId : kRenderViewId;
-
- EXPECT_CALL(*mock_mirroring_manager_,
- StartMirroring(next_render_process_id, next_render_view_id,
- NotNull()))
- .WillOnce(SaveArg<2>(&destination_))
- .RetiresOnSaturation();
- // At Stop() time, or when the mirroring target changes:
- EXPECT_CALL(*mock_mirroring_manager_,
- StopMirroring(next_render_process_id, next_render_view_id,
- NotNull()))
- .WillOnce(Assign(
- &destination_,
- static_cast<AudioMirroringManager::MirroringDestination*>(NULL)))
+ const int next_render_frame_id =
+ current_render_frame_id_ == kRenderFrameId ?
+ kAnotherRenderFrameId : kRenderFrameId;
+
+ EXPECT_CALL(*mock_mirroring_manager_, StartMirroring(NotNull()))
+ .WillOnce(SaveArg<0>(&destination_))
.RetiresOnSaturation();
- // Simulate OnTargetChange() callback from WebContentsTracker.
- EXPECT_FALSE(change_callback_.is_null());
- change_callback_.Run(next_render_process_id, next_render_view_id);
+ SimulateChangeCallback(next_render_process_id, next_render_frame_id);
current_render_process_id_ = next_render_process_id;
- current_render_view_id_ = next_render_view_id;
+ current_render_frame_id_ = next_render_frame_id;
}
void LoseMirroringTarget() {
EXPECT_CALL(mock_input_callback_, OnError(_));
- // Simulate OnTargetChange() callback from WebContentsTracker.
- EXPECT_FALSE(change_callback_.is_null());
- change_callback_.Run(-1, -1);
+ SimulateChangeCallback(-1, -1);
}
void Stop() {
@@ -369,8 +353,19 @@ class WebContentsAudioInputStreamTest : public testing::Test {
}
private:
+ void SimulateChangeCallback(int render_process_id, int render_frame_id) {
+ ASSERT_FALSE(change_callback_.is_null());
+ if (render_process_id == -1 || render_frame_id == -1) {
+ change_callback_.Run(NULL);
+ } else {
+ // For our tests, any non-NULL value will suffice since it will not be
+ // dereferenced.
+ change_callback_.Run(reinterpret_cast<RenderWidgetHost*>(0xdeadbee5));
+ }
+ }
+
+ scoped_ptr<TestBrowserThreadBundle> thread_bundle_;
base::Thread audio_thread_;
- BrowserThreadImpl io_thread_;
scoped_ptr<MockAudioMirroringManager> mock_mirroring_manager_;
scoped_refptr<MockWebContentsTracker> mock_tracker_;
@@ -391,9 +386,9 @@ class WebContentsAudioInputStreamTest : public testing::Test {
// to simulate: 1) calls to AddInput(); and 2) diverting audio data.
AudioMirroringManager::MirroringDestination* destination_;
- // Current target RenderView. These get flipped in ChangedMirroringTarget().
+ // Current target RenderFrame. These get flipped in ChangedMirroringTarget().
int current_render_process_id_;
- int current_render_view_id_;
+ int current_render_frame_id_;
// Streams provided by calls to WebContentsAudioInputStream::AddInput(). Each
// is started with a simulated source of audio data.
diff --git a/chromium/content/browser/media/capture/web_contents_audio_muter.cc b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
new file mode 100644
index 00000000000..4d321927a4f
--- /dev/null
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -0,0 +1,152 @@
+// Copyright 2014 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 "content/browser/media/capture/web_contents_audio_muter.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "content/browser/media/capture/audio_mirroring_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_manager.h"
+#include "media/audio/fake_audio_consumer.h"
+#include "media/base/bind_to_current_loop.h"
+
+namespace content {
+
+namespace {
+
+// An AudioOutputStream that pumps audio data, but does nothing with it.
+// Pumping the audio data is necessary because video playback is synchronized to
+// the audio stream and will freeze otherwise.
+//
+// TODO(miu): media::FakeAudioOutputStream does pretty much the same thing as
+// this class, but requires construction/destruction via media::AudioManagerBase
+// on the audio thread. Once that's fixed, this class will no longer be needed.
+// http://crbug.com/416278
+class AudioDiscarder : public media::AudioOutputStream {
+ public:
+ explicit AudioDiscarder(const media::AudioParameters& params)
+ : consumer_(media::AudioManager::Get()->GetWorkerTaskRunner(), params) {}
+
+ // AudioOutputStream implementation.
+ bool Open() override { return true; }
+ void Start(AudioSourceCallback* callback) override {
+ consumer_.Start(base::Bind(&AudioDiscarder::FetchAudioData, callback));
+ }
+ void Stop() override { consumer_.Stop(); }
+ void SetVolume(double volume) override {}
+ void GetVolume(double* volume) override { *volume = 0; }
+ void Close() override { delete this; }
+
+ private:
+ ~AudioDiscarder() override {}
+
+ static void FetchAudioData(AudioSourceCallback* callback,
+ media::AudioBus* audio_bus) {
+ callback->OnMoreData(audio_bus, 0);
+ }
+
+ // Calls FetchAudioData() at regular intervals and discards the data.
+ media::FakeAudioConsumer consumer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AudioDiscarder);
+};
+
+} // namespace
+
+// A simple AudioMirroringManager::MirroringDestination implementation that
+// identifies the audio streams rendered by a WebContents and provides
+// AudioDiscarders to AudioMirroringManager.
+class WebContentsAudioMuter::MuteDestination
+ : public base::RefCountedThreadSafe<MuteDestination>,
+ public AudioMirroringManager::MirroringDestination {
+ public:
+ explicit MuteDestination(WebContents* web_contents)
+ : web_contents_(web_contents) {}
+
+ private:
+ friend class base::RefCountedThreadSafe<MuteDestination>;
+
+ typedef AudioMirroringManager::SourceFrameRef SourceFrameRef;
+
+ ~MuteDestination() override {}
+
+ void QueryForMatches(const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) override {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&MuteDestination::QueryForMatchesOnUIThread,
+ this,
+ candidates,
+ media::BindToCurrentLoop(results_callback)));
+ }
+
+ void QueryForMatchesOnUIThread(const std::set<SourceFrameRef>& candidates,
+ const MatchesCallback& results_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ std::set<SourceFrameRef> matches;
+ // Add each ID to |matches| if it maps to a RenderFrameHost that maps to the
+ // WebContents being muted.
+ for (std::set<SourceFrameRef>::const_iterator i = candidates.begin();
+ i != candidates.end(); ++i) {
+ WebContents* const contents_containing_frame =
+ WebContents::FromRenderFrameHost(
+ RenderFrameHost::FromID(i->first, i->second));
+ if (contents_containing_frame == web_contents_)
+ matches.insert(*i);
+ }
+ results_callback.Run(matches);
+ }
+
+ media::AudioOutputStream* AddInput(
+ const media::AudioParameters& params) override {
+ return new AudioDiscarder(params);
+ }
+
+ WebContents* const web_contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(MuteDestination);
+};
+
+WebContentsAudioMuter::WebContentsAudioMuter(WebContents* web_contents)
+ : destination_(new MuteDestination(web_contents)), is_muting_(false) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+WebContentsAudioMuter::~WebContentsAudioMuter() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ StopMuting();
+}
+
+void WebContentsAudioMuter::StartMuting() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (is_muting_)
+ return;
+ is_muting_ = true;
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&AudioMirroringManager::StartMirroring,
+ base::Unretained(AudioMirroringManager::GetInstance()),
+ destination_));
+}
+
+void WebContentsAudioMuter::StopMuting() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!is_muting_)
+ return;
+ is_muting_ = false;
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&AudioMirroringManager::StopMirroring,
+ base::Unretained(AudioMirroringManager::GetInstance()),
+ destination_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_audio_muter.h b/chromium/content/browser/media/capture/web_contents_audio_muter.h
new file mode 100644
index 00000000000..d9c5f2fcbb2
--- /dev/null
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.h
@@ -0,0 +1,43 @@
+// Copyright 2014 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 CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_AUDIO_MUTER_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_AUDIO_MUTER_H_
+
+#include "base/memory/ref_counted.h"
+
+namespace content {
+
+class WebContents;
+
+// Mutes all audio output from a WebContents. Internally, this is accomplished
+// by providing a MirroringDestination implementation, similar to that found in
+// WebContentsAudioInputStream for audio capture/mirroring. However, the
+// WebContentsAudioMuter::MuteDestination only pumps the audio data and discards
+// it.
+class WebContentsAudioMuter {
+ public:
+ explicit WebContentsAudioMuter(WebContents* web_contents);
+ ~WebContentsAudioMuter();
+
+ bool is_muting() const { return is_muting_; }
+
+ void StartMuting();
+ void StopMuting();
+
+ private:
+ // AudioMirroringManager::MirroringDestination implementation which is
+ // ref-counted so it remains alive as tasks referencing it are posted on both
+ // the UI and IO threads.
+ class MuteDestination;
+ const scoped_refptr<MuteDestination> destination_;
+
+ bool is_muting_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebContentsAudioMuter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_AUDIO_MUTER_H_
diff --git a/chromium/content/browser/media/capture/web_contents_capture_util.cc b/chromium/content/browser/media/capture/web_contents_capture_util.cc
index 57b636a8960..e1c5d52351f 100644
--- a/chromium/content/browser/media/capture/web_contents_capture_util.cc
+++ b/chromium/content/browser/media/capture/web_contents_capture_util.cc
@@ -9,40 +9,24 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-namespace {
-
-const char kVirtualDeviceScheme[] = "virtual-media-stream://";
-
-} // namespace
-
namespace content {
-std::string WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
- const std::string& device_id) {
- return kVirtualDeviceScheme + device_id;
-}
-
-std::string WebContentsCaptureUtil::StripWebContentsDeviceScheme(
- const std::string& device_id) {
- return (IsWebContentsDeviceId(device_id) ?
- device_id.substr(arraysize(kVirtualDeviceScheme) - 1) :
- device_id);
-}
-
bool WebContentsCaptureUtil::IsWebContentsDeviceId(
const std::string& device_id) {
- return StartsWithASCII(device_id, kVirtualDeviceScheme, true);
+ int ignored;
+ return ExtractTabCaptureTarget(device_id, &ignored, &ignored);
}
bool WebContentsCaptureUtil::ExtractTabCaptureTarget(
const std::string& device_id_param,
int* render_process_id,
- int* render_view_id) {
- if (!IsWebContentsDeviceId(device_id_param))
+ int* main_render_frame_id) {
+ static const char kDeviceScheme[] = "web-contents-media-stream://";
+ if (!StartsWithASCII(device_id_param, kDeviceScheme, true))
return false;
const std::string device_id = device_id_param.substr(
- arraysize(kVirtualDeviceScheme) - 1);
+ arraysize(kDeviceScheme) - 1);
const size_t sep_pos = device_id.find(':');
if (sep_pos == std::string::npos)
@@ -53,7 +37,7 @@ bool WebContentsCaptureUtil::ExtractTabCaptureTarget(
device_id.length() - sep_pos - 1);
return (base::StringToInt(component1, render_process_id) &&
- base::StringToInt(component2, render_view_id));
+ base::StringToInt(component2, main_render_frame_id));
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_capture_util.h b/chromium/content/browser/media/capture/web_contents_capture_util.h
index 5f43f423b8b..60a9113f23d 100644
--- a/chromium/content/browser/media/capture/web_contents_capture_util.h
+++ b/chromium/content/browser/media/capture/web_contents_capture_util.h
@@ -13,21 +13,14 @@ namespace content {
class CONTENT_EXPORT WebContentsCaptureUtil {
public:
- // Returns a new id after appending the device id scheme for virtual streams.
- static std::string AppendWebContentsDeviceScheme(
- const std::string& device_id_param);
-
- static std::string StripWebContentsDeviceScheme(
- const std::string& device_id_param);
-
// Check whether the device id indicates that this is a web contents stream.
static bool IsWebContentsDeviceId(const std::string& device_id);
- // Function to extract the target renderer id's from a tab media stream
+ // Function to extract the target render frame id's from a media stream
// request's device id.
static bool ExtractTabCaptureTarget(const std::string& device_id,
int* render_process_id,
- int* render_view_id);
+ int* main_render_frame_id);
};
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_tracker.cc b/chromium/content/browser/media/capture/web_contents_tracker.cc
index 07653310128..6810ac097aa 100644
--- a/chromium/content/browser/media/capture/web_contents_tracker.cc
+++ b/chromium/content/browser/media/capture/web_contents_tracker.cc
@@ -5,20 +5,24 @@
#include "content/browser/media/capture/web_contents_tracker.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
namespace content {
-WebContentsTracker::WebContentsTracker() {}
+WebContentsTracker::WebContentsTracker(bool track_fullscreen_rwh)
+ : track_fullscreen_rwh_(track_fullscreen_rwh),
+ last_target_(NULL) {}
WebContentsTracker::~WebContentsTracker() {
DCHECK(!web_contents()) << "BUG: Still observering!";
}
-void WebContentsTracker::Start(int render_process_id, int render_view_id,
+void WebContentsTracker::Start(int render_process_id, int main_render_frame_id,
const ChangeCallback& callback) {
DCHECK(!message_loop_.get() || message_loop_->BelongsToCurrentThread());
@@ -26,10 +30,14 @@ void WebContentsTracker::Start(int render_process_id, int render_view_id,
DCHECK(message_loop_.get());
callback_ = callback;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsTracker::LookUpAndObserveWebContents, this,
- render_process_id, render_view_id));
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ StartObservingWebContents(render_process_id, main_render_frame_id);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebContentsTracker::StartObservingWebContents, this,
+ render_process_id, main_render_frame_id));
+ }
}
void WebContentsTracker::Stop() {
@@ -37,66 +45,100 @@ void WebContentsTracker::Stop() {
callback_.Reset();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WebContentsTracker::Observe, this,
- static_cast<WebContents*>(NULL)));
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ WebContentsObserver::Observe(NULL);
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebContentsTracker::Observe, this,
+ static_cast<WebContents*>(NULL)));
+ }
}
-void WebContentsTracker::OnWebContentsChangeEvent() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+RenderWidgetHost* WebContentsTracker::GetTargetRenderWidgetHost() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
WebContents* const wc = web_contents();
- RenderViewHost* const rvh = wc ? wc->GetRenderViewHost() : NULL;
- RenderProcessHost* const rph = rvh ? rvh->GetProcess() : NULL;
-
- const int render_process_id = rph ? rph->GetID() : MSG_ROUTING_NONE;
- const int render_view_id = rvh ? rvh->GetRoutingID() : MSG_ROUTING_NONE;
+ if (!wc)
+ return NULL;
+
+ RenderWidgetHost* rwh = NULL;
+ if (track_fullscreen_rwh_) {
+ RenderWidgetHostView* const view = wc->GetFullscreenRenderWidgetHostView();
+ if (view)
+ rwh = view->GetRenderWidgetHost();
+ }
+ if (!rwh) {
+ RenderFrameHostImpl* const rfh =
+ static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
+ if (rfh)
+ rwh = rfh->GetRenderWidgetHost();
+ }
+
+ return rwh;
+}
- message_loop_->PostTask(FROM_HERE,
- base::Bind(&WebContentsTracker::MaybeDoCallback, this,
- render_process_id, render_view_id));
+void WebContentsTracker::OnPossibleTargetChange(bool force_callback_run) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderWidgetHost* const rwh = GetTargetRenderWidgetHost();
+ if (rwh == last_target_ && !force_callback_run)
+ return;
+ DVLOG(1) << "Will report target change from RenderWidgetHost@" << last_target_
+ << " to RenderWidgetHost@" << rwh;
+ last_target_ = rwh;
+
+ if (message_loop_->BelongsToCurrentThread()) {
+ MaybeDoCallback(rwh);
+ } else {
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebContentsTracker::MaybeDoCallback, this, rwh));
+ }
}
-void WebContentsTracker::MaybeDoCallback(int render_process_id,
- int render_view_id) {
+void WebContentsTracker::MaybeDoCallback(RenderWidgetHost* rwh) {
DCHECK(message_loop_->BelongsToCurrentThread());
if (!callback_.is_null())
- callback_.Run(render_process_id, render_view_id);
+ callback_.Run(rwh);
}
-void WebContentsTracker::LookUpAndObserveWebContents(int render_process_id,
- int render_view_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void WebContentsTracker::StartObservingWebContents(int render_process_id,
+ int main_render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderViewHost* const rvh =
- RenderViewHost::FromID(render_process_id, render_view_id);
- DVLOG_IF(1, !rvh) << "RenderViewHost::FromID("
- << render_process_id << ", " << render_view_id
- << ") returned NULL.";
- Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
+ Observe(WebContents::FromRenderFrameHost(RenderFrameHost::FromID(
+ render_process_id, main_render_frame_id)));
DVLOG_IF(1, !web_contents())
- << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL.";
+ << "Could not find WebContents associated with main RenderFrameHost "
+ << "referenced by render_process_id=" << render_process_id
+ << ", routing_id=" << main_render_frame_id;
+
+ OnPossibleTargetChange(true);
+}
- OnWebContentsChangeEvent();
+void WebContentsTracker::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ OnPossibleTargetChange(false);
}
-void WebContentsTracker::RenderViewReady() {
- OnWebContentsChangeEvent();
+void WebContentsTracker::RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) {
+ OnPossibleTargetChange(false);
}
-void WebContentsTracker::AboutToNavigateRenderView(RenderViewHost* rvh) {
- OnWebContentsChangeEvent();
+void WebContentsTracker::WebContentsDestroyed() {
+ Observe(NULL);
+ OnPossibleTargetChange(false);
}
-void WebContentsTracker::DidNavigateMainFrame(
- const LoadCommittedDetails& details, const FrameNavigateParams& params) {
- OnWebContentsChangeEvent();
+void WebContentsTracker::DidShowFullscreenWidget(int routing_id) {
+ OnPossibleTargetChange(false);
}
-void WebContentsTracker::WebContentsDestroyed() {
- OnWebContentsChangeEvent();
+void WebContentsTracker::DidDestroyFullscreenWidget(int routing_id) {
+ OnPossibleTargetChange(false);
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_tracker.h b/chromium/content/browser/media/capture/web_contents_tracker.h
index f8957f3f839..f124eaa47e8 100644
--- a/chromium/content/browser/media/capture/web_contents_tracker.h
+++ b/chromium/content/browser/media/capture/web_contents_tracker.h
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// Given a starting render_process_id and render_view_id, the WebContentsTracker
-// tracks RenderViewHost instance swapping during the lifetime of a WebContents
-// instance. This is used when mirroring tab video and audio so that user
-// navigations, crashes, etc., during a tab's lifetime allow the capturing code
-// to remain active on the current/latest RenderView.
+// Given a starting render_process_id and main_render_frame_id, the
+// WebContentsTracker tracks changes to the active RenderFrameHost tree during
+// the lifetime of a WebContents instance. This is used when mirroring tab
+// video and audio so that user navigations, crashes, iframes, etc., during a
+// tab's lifetime allow the capturing code to remain active on the
+// current/latest render frame tree.
//
// Threading issues: Start(), Stop() and the ChangeCallback are invoked on the
// same thread. This can be any thread, and the decision is locked-in by
@@ -26,58 +27,88 @@ class MessageLoopProxy;
namespace content {
+class RenderWidgetHost;
+
class CONTENT_EXPORT WebContentsTracker
: public base::RefCountedThreadSafe<WebContentsTracker>,
public WebContentsObserver {
public:
- WebContentsTracker();
-
- // Callback for whenever the target is swapped. The callback is also invoked
- // with both arguments set to MSG_ROUTING_NONE to indicate tracking will not
- // continue (i.e., the WebContents instance was not found or has been
- // destroyed).
- typedef base::Callback<void(int render_process_id, int render_view_id)>
- ChangeCallback;
-
- // Start tracking. The last-known |render_process_id| and |render_view_id|
- // are provided, and the given callback is invoked asynchronously one or more
- // times. The callback will be invoked on the same thread calling Start().
- virtual void Start(int render_process_id, int render_view_id,
+ // If |track_fullscreen_rwh| is true, the ChangeCallback will be run when a
+ // WebContents shows/destroys a fullscreen RenderWidgetHost view. If false,
+ // fullscreen events are ignored. Specify true for video tab capture and
+ // false for audio tab capture.
+ explicit WebContentsTracker(bool track_fullscreen_rwh);
+
+ // Callback to indicate a new RenderWidgetHost should be targeted for capture.
+ // This is also invoked with NULL to indicate tracking will not continue
+ // (i.e., the WebContents instance was not found or has been destroyed).
+ typedef base::Callback<void(RenderWidgetHost* rwh)> ChangeCallback;
+
+ // Start tracking. The last-known |render_process_id| and
+ // |main_render_frame_id| are provided, and |callback| will be run once to
+ // indicate the current capture target (this may occur during the invocation
+ // of Start(), or in the future). The callback will be invoked on the same
+ // thread calling Start().
+ virtual void Start(int render_process_id, int main_render_frame_id,
const ChangeCallback& callback);
// Stop tracking. Once this method returns, the callback is guaranteed not to
// be invoked again.
virtual void Stop();
+ // Current target. This must only be called on the UI BrowserThread.
+ RenderWidgetHost* GetTargetRenderWidgetHost() const;
+
protected:
friend class base::RefCountedThreadSafe<WebContentsTracker>;
- virtual ~WebContentsTracker();
+ ~WebContentsTracker() override;
private:
- // Reads the render_process_id/render_view_id from the current WebContents
- // instance and then invokes the callback.
- void OnWebContentsChangeEvent();
+ // Determine the target RenderWidgetHost and, if different from that last
+ // reported, runs the ChangeCallback on the appropriate thread. If
+ // |force_callback_run| is true, the ChangeCallback is run even if the
+ // RenderWidgetHost has not changed.
+ void OnPossibleTargetChange(bool force_callback_run);
- // Called on the thread that Start()/Stop() are called on, check whether the
- // callback is still valid and, if so, invoke it.
- void MaybeDoCallback(int render_process_id, int render_view_id);
+ // Called on the thread that Start()/Stop() are called on. Checks whether the
+ // callback is still valid and, if so, runs it.
+ void MaybeDoCallback(RenderWidgetHost* rwh);
// Look-up the current WebContents instance associated with the given
- // |render_process_id| and |render_view_id| and begin observing it.
- void LookUpAndObserveWebContents(int render_process_id,
- int render_view_id);
-
- // WebContentsObserver overrides to react to events of interest.
- virtual void RenderViewReady() OVERRIDE;
- virtual void AboutToNavigateRenderView(RenderViewHost* render_view_host)
- OVERRIDE;
- virtual void DidNavigateMainFrame(const LoadCommittedDetails& details,
- const FrameNavigateParams& params) OVERRIDE;
- virtual void WebContentsDestroyed() OVERRIDE;
-
+ // |render_process_id| and |main_render_frame_id| and begin observing it.
+ void StartObservingWebContents(int render_process_id,
+ int main_render_frame_id);
+
+ // WebContentsObserver overrides: According to web_contents_observer.h, these
+ // two method overrides are all that is necessary to track the set of active
+ // RenderFrameHosts.
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+ void RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) override;
+
+ // WebContentsObserver override to notify the client that the capture target
+ // has been permanently lost.
+ void WebContentsDestroyed() override;
+
+ // WebContentsObserver overrides to notify the client that the capture target
+ // may have changed due to a separate fullscreen widget shown/destroyed.
+ void DidShowFullscreenWidget(int routing_id) override;
+ void DidDestroyFullscreenWidget(int routing_id) override;
+
+ // If true, the client is interested in the showing/destruction of fullscreen
+ // RenderWidgetHosts.
+ const bool track_fullscreen_rwh_;
+
+ // MessageLoop corresponding to the thread that called Start().
scoped_refptr<base::MessageLoopProxy> message_loop_;
+
+ // Callback to run when the target RenderWidgetHost has changed.
ChangeCallback callback_;
+ // Pointer to the RenderWidgetHost provided in the last run of |callback_|.
+ // This is used to eliminate duplicate callback runs.
+ RenderWidgetHost* last_target_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsTracker);
};
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
index 8a8474c2782..4a931fc54b0 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -13,7 +13,7 @@
// video encoder -- is the performance bottleneck, and that the rate of
// frame capture should be throttled back.
//
-// 2. Capture: A bitmap is snapshotted/copied from the RenderView's backing
+// 2. Capture: A bitmap is snapshotted/copied from the RenderWidget's backing
// store. This is initiated on the UI BrowserThread, and often occurs
// asynchronously. Where supported, the GPU scales and color converts
// frames to our desired size, and the readback happens directly into the
@@ -65,21 +65,27 @@
#include "content/browser/media/capture/content_video_capture_device_core.h"
#include "content/browser/media/capture/video_capture_oracle.h"
#include "content/browser/media/capture/web_contents_capture_util.h"
+#include "content/browser/media/capture/web_contents_tracker.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
-#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents.h"
#include "media/base/video_util.h"
#include "media/video/capture/video_capture_types.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/screen.h"
namespace content {
@@ -136,11 +142,12 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
oracle_proxy_(oracle),
delivery_log_(delivery_log) {}
- virtual bool ShouldCaptureFrame(
+ bool ShouldCaptureFrame(
+ const gfx::Rect& damage_rect,
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback*
- deliver_frame_cb) OVERRIDE;
+ deliver_frame_cb) override;
private:
const VideoCaptureOracle::Event event_type_;
@@ -178,18 +185,21 @@ class ContentCaptureSubscription : public content::NotificationObserver {
const RenderWidgetHost& source,
const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
const CaptureCallback& capture_callback);
- virtual ~ContentCaptureSubscription();
+ ~ContentCaptureSubscription() override;
// content::NotificationObserver implementation.
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) override;
private:
void OnTimer();
+ // Maintain a weak reference to the RenderWidgetHost (via its routing ID),
+ // since the instance could be destroyed externally during the lifetime of
+ // |this|.
const int render_process_id_;
- const int render_view_id_;
+ const int render_widget_id_;
VideoFrameDeliveryLog delivery_log_;
FrameSubscriber paint_subscriber_;
@@ -214,24 +224,17 @@ void RenderVideoFrame(const SkBitmap& input,
const scoped_refptr<media::VideoFrame>& output,
const base::Callback<void(bool)>& done_cb);
-// Keeps track of the RenderView to be sourced, and executes copying of the
-// backing store on the UI BrowserThread.
-//
-// TODO(nick): It would be nice to merge this with WebContentsTracker, but its
-// implementation is currently asynchronous -- in our case, the "rvh changed"
-// notification would get posted back to the UI thread and processed later, and
-// this seems disadvantageous.
-class WebContentsCaptureMachine
- : public VideoCaptureMachine,
- public WebContentsObserver {
+// Renews capture subscriptions based on feedback from WebContentsTracker, and
+// also executes copying of the backing store on the UI BrowserThread.
+class WebContentsCaptureMachine : public VideoCaptureMachine {
public:
- WebContentsCaptureMachine(int render_process_id, int render_view_id);
- virtual ~WebContentsCaptureMachine();
+ WebContentsCaptureMachine(int render_process_id, int main_render_frame_id);
+ ~WebContentsCaptureMachine() override;
// VideoCaptureMachine overrides.
- virtual bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
- const media::VideoCaptureParams& params) OVERRIDE;
- virtual void Stop(const base::Closure& callback) OVERRIDE;
+ bool Start(const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
+ const media::VideoCaptureParams& params) override;
+ void Stop(const base::Closure& callback) override;
// Starts a copy from the backing store or the composited surface. Must be run
// on the UI BrowserThread. |deliver_frame_cb| will be run when the operation
@@ -243,40 +246,11 @@ class WebContentsCaptureMachine
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
deliver_frame_cb);
- // content::WebContentsObserver implementation.
- virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE {
- fullscreen_widget_id_ = routing_id;
- RenewFrameSubscription();
- }
-
- virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE {
- DCHECK_EQ(fullscreen_widget_id_, routing_id);
- fullscreen_widget_id_ = MSG_ROUTING_NONE;
- RenewFrameSubscription();
- }
-
- virtual void RenderViewReady() OVERRIDE {
- RenewFrameSubscription();
- }
-
- virtual void AboutToNavigateRenderView(RenderViewHost* rvh) OVERRIDE {
- RenewFrameSubscription();
- }
-
- virtual void DidNavigateMainFrame(
- const LoadCommittedDetails& details,
- const FrameNavigateParams& params) OVERRIDE {
- RenewFrameSubscription();
- }
-
- virtual void WebContentsDestroyed() OVERRIDE;
-
private:
- // Starts observing the web contents, returning false if lookup fails.
- bool StartObservingWebContents();
+ bool IsStarted() const;
- // Helper function to determine the view that we are currently tracking.
- RenderWidgetHost* GetTarget();
+ // Computes the preferred size of the target RenderWidget for optimal capture.
+ gfx::Size ComputeOptimalTargetSize() const;
// Response callback for RenderWidgetHost::CopyFromBackingStore().
void DidCopyFromBackingStore(
@@ -294,14 +268,16 @@ class WebContentsCaptureMachine
deliver_frame_cb,
bool success);
- // Remove the old subscription, and start a new one. This should be called
- // after any change to the WebContents that affects the RenderWidgetHost or
- // attached views.
- void RenewFrameSubscription();
+ // Remove the old subscription, and start a new one if |rwh| is not NULL.
+ void RenewFrameSubscription(RenderWidgetHost* rwh);
// Parameters saved in constructor.
const int initial_render_process_id_;
- const int initial_render_view_id_;
+ const int initial_main_render_frame_id_;
+
+ // Tracks events and calls back to RenewFrameSubscription() to maintain
+ // capture on the correct RenderWidgetHost.
+ const scoped_refptr<WebContentsTracker> tracker_;
// A dedicated worker thread on which SkBitmap->VideoFrame conversion will
// occur. Only used when this activity cannot be done on the GPU.
@@ -313,10 +289,6 @@ class WebContentsCaptureMachine
// Video capture parameters that this machine is started with.
media::VideoCaptureParams capture_params_;
- // Routing ID of any active fullscreen render widget or MSG_ROUTING_NONE
- // otherwise.
- int fullscreen_widget_id_;
-
// Last known RenderView size.
gfx::Size last_view_size_;
@@ -332,6 +304,7 @@ class WebContentsCaptureMachine
};
bool FrameSubscriber::ShouldCaptureFrame(
+ const gfx::Rect& damage_rect,
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* deliver_frame_cb) {
@@ -340,7 +313,7 @@ bool FrameSubscriber::ShouldCaptureFrame(
ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
bool oracle_decision = oracle_proxy_->ObserveEventAndDecideCapture(
- event_type_, present_time, storage, &capture_frame_cb);
+ event_type_, damage_rect, present_time, storage, &capture_frame_cb);
if (!capture_frame_cb.is_null())
*deliver_frame_cb = base::Bind(capture_frame_cb, *storage);
@@ -354,7 +327,7 @@ ContentCaptureSubscription::ContentCaptureSubscription(
const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
const CaptureCallback& capture_callback)
: render_process_id_(source.GetProcess()->GetID()),
- render_view_id_(source.GetRoutingID()),
+ render_widget_id_(source.GetRoutingID()),
delivery_log_(),
paint_subscriber_(VideoCaptureOracle::kSoftwarePaint, oracle_proxy,
&delivery_log_),
@@ -362,10 +335,9 @@ ContentCaptureSubscription::ContentCaptureSubscription(
&delivery_log_),
capture_callback_(capture_callback),
timer_(true, true) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
- source.GetView());
+ RenderWidgetHostView* const view = source.GetView();
// Subscribe to accelerated presents. These will be serviced directly by the
// oracle.
@@ -384,22 +356,25 @@ ContentCaptureSubscription::ContentCaptureSubscription(
Source<RenderWidgetHost>(&source));
// Subscribe to timer events. This instance will service these as well.
- timer_.Start(FROM_HERE, oracle_proxy->capture_period(),
+ timer_.Start(FROM_HERE, oracle_proxy->min_capture_period(),
base::Bind(&ContentCaptureSubscription::OnTimer,
base::Unretained(this)));
}
ContentCaptureSubscription::~ContentCaptureSubscription() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // If the BrowserThreads have been torn down, then the browser is in the final
+ // stages of exiting and it is dangerous to take any further action. We must
+ // return early. http://crbug.com/396413
+ if (!BrowserThread::IsMessageLoopValid(BrowserThread::UI))
+ return;
+
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (kAcceleratedSubscriberIsSupported) {
- RenderViewHost* source = RenderViewHost::FromID(render_process_id_,
- render_view_id_);
- if (source) {
- RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
- source->GetView());
- if (view)
- view->EndFrameSubscription();
- }
+ RenderWidgetHost* const source =
+ RenderWidgetHost::FromID(render_process_id_, render_widget_id_);
+ RenderWidgetHostView* const view = source ? source->GetView() : NULL;
+ if (view)
+ view->EndFrameSubscription();
}
}
@@ -407,7 +382,7 @@ void ContentCaptureSubscription::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, type);
RenderWidgetHostImpl* rwh =
@@ -433,7 +408,8 @@ void ContentCaptureSubscription::Observe(
scoped_refptr<media::VideoFrame> frame;
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
const base::TimeTicks start_time = base::TimeTicks::Now();
- if (paint_subscriber_.ShouldCaptureFrame(start_time,
+ if (paint_subscriber_.ShouldCaptureFrame(gfx::Rect(),
+ start_time,
&frame,
&deliver_frame_cb)) {
// This message happens just before paint. If we post a task to do the copy,
@@ -445,14 +421,15 @@ void ContentCaptureSubscription::Observe(
}
void ContentCaptureSubscription::OnTimer() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
TRACE_EVENT0("mirroring", "ContentCaptureSubscription::OnTimer");
scoped_refptr<media::VideoFrame> frame;
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
const base::TimeTicks start_time = base::TimeTicks::Now();
- if (timer_subscriber_.ShouldCaptureFrame(start_time,
+ if (timer_subscriber_.ShouldCaptureFrame(gfx::Rect(),
+ start_time,
&frame,
&deliver_frame_cb)) {
capture_callback_.Run(start_time, frame, deliver_frame_cb);
@@ -469,12 +446,12 @@ void RenderVideoFrame(const SkBitmap& input,
// Sanity-check the captured bitmap.
if (input.empty() ||
!input.readyToDraw() ||
- input.config() != SkBitmap::kARGB_8888_Config ||
+ input.colorType() != kN32_SkColorType ||
input.width() < 2 || input.height() < 2) {
DVLOG(1) << "input unacceptable (size="
<< input.getSize()
<< ", ready=" << input.readyToDraw()
- << ", config=" << input.config() << ')';
+ << ", colorType=" << input.colorType() << ')';
return;
}
@@ -558,24 +535,24 @@ void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
}
WebContentsCaptureMachine::WebContentsCaptureMachine(int render_process_id,
- int render_view_id)
+ int main_render_frame_id)
: initial_render_process_id_(render_process_id),
- initial_render_view_id_(render_view_id),
- fullscreen_widget_id_(MSG_ROUTING_NONE),
+ initial_main_render_frame_id_(main_render_frame_id),
+ tracker_(new WebContentsTracker(true)),
weak_ptr_factory_(this) {}
-WebContentsCaptureMachine::~WebContentsCaptureMachine() {
- BrowserThread::PostBlockingPoolTask(
- FROM_HERE,
- base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
- base::Bind(&base::DoNothing)));
+WebContentsCaptureMachine::~WebContentsCaptureMachine() {}
+
+bool WebContentsCaptureMachine::IsStarted() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return weak_ptr_factory_.HasWeakPtrs();
}
bool WebContentsCaptureMachine::Start(
const scoped_refptr<ThreadSafeCaptureOracle>& oracle_proxy,
const media::VideoCaptureParams& params) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(!started_);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!IsStarted());
DCHECK(oracle_proxy.get());
oracle_proxy_ = oracle_proxy;
@@ -588,36 +565,40 @@ bool WebContentsCaptureMachine::Start(
return false;
}
- if (!StartObservingWebContents()) {
- DVLOG(1) << "Failed to observe web contents.";
- render_thread_.reset();
- return false;
- }
+ // Note: Creation of the first WeakPtr in the following statement will cause
+ // IsStarted() to return true from now on.
+ tracker_->Start(initial_render_process_id_, initial_main_render_frame_id_,
+ base::Bind(&WebContentsCaptureMachine::RenewFrameSubscription,
+ weak_ptr_factory_.GetWeakPtr()));
- started_ = true;
return true;
}
void WebContentsCaptureMachine::Stop(const base::Closure& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- subscription_.reset();
- if (web_contents()) {
- web_contents()->DecrementCapturerCount();
- Observe(NULL);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!IsStarted()) {
+ callback.Run();
+ return;
}
- // Any callback that intend to use render_thread_ will not work after it is
- // passed.
+ // The following cancels any outstanding callbacks and causes IsStarted() to
+ // return false from here onward.
weak_ptr_factory_.InvalidateWeakPtrs();
+ // Note: RenewFrameSubscription() must be called before stopping |tracker_| so
+ // the web_contents() can be notified that the capturing is ending.
+ RenewFrameSubscription(NULL);
+ tracker_->Stop();
+
// The render thread cannot be stopped on the UI thread, so post a message
// to the thread pool used for blocking operations.
- BrowserThread::PostBlockingPoolTask(
- FROM_HERE,
- base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
- callback));
-
- started_ = false;
+ if (render_thread_.get()) {
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
+ callback));
+ }
}
void WebContentsCaptureMachine::Capture(
@@ -625,12 +606,12 @@ void WebContentsCaptureMachine::Capture(
const scoped_refptr<media::VideoFrame>& target,
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
deliver_frame_cb) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderWidgetHost* rwh = GetTarget();
+ RenderWidgetHost* rwh = tracker_->GetTargetRenderWidgetHost();
RenderWidgetHostViewBase* view =
rwh ? static_cast<RenderWidgetHostViewBase*>(rwh->GetView()) : NULL;
- if (!view || !rwh) {
+ if (!view) {
deliver_frame_cb.Run(base::TimeTicks(), false);
return;
}
@@ -667,63 +648,37 @@ void WebContentsCaptureMachine::Capture(
start_time,
target,
deliver_frame_cb),
- SkBitmap::kARGB_8888_Config);
- }
-}
-
-bool WebContentsCaptureMachine::StartObservingWebContents() {
- // Look-up the RenderViewHost and, from that, the WebContents that wraps it.
- // If successful, begin observing the WebContents instance.
- //
- // Why this can be unsuccessful: The request for mirroring originates in a
- // render process, and this request is based on the current RenderView
- // associated with a tab. However, by the time we get up-and-running here,
- // there have been multiple back-and-forth IPCs between processes, as well as
- // a bit of indirection across threads. It's easily possible that, in the
- // meantime, the original RenderView may have gone away.
- RenderViewHost* const rvh =
- RenderViewHost::FromID(initial_render_process_id_,
- initial_render_view_id_);
- DVLOG_IF(1, !rvh) << "RenderViewHost::FromID("
- << initial_render_process_id_ << ", "
- << initial_render_view_id_ << ") returned NULL.";
- Observe(rvh ? WebContents::FromRenderViewHost(rvh) : NULL);
-
- WebContentsImpl* contents = static_cast<WebContentsImpl*>(web_contents());
- if (contents) {
- contents->IncrementCapturerCount(oracle_proxy_->GetCaptureSize());
- fullscreen_widget_id_ = contents->GetFullscreenWidgetRoutingID();
- RenewFrameSubscription();
- return true;
+ kN32_SkColorType);
}
-
- DVLOG(1) << "WebContents::FromRenderViewHost(" << rvh << ") returned NULL.";
- return false;
}
-void WebContentsCaptureMachine::WebContentsDestroyed() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- subscription_.reset();
- web_contents()->DecrementCapturerCount();
- oracle_proxy_->ReportError("WebContentsDestroyed()");
-}
-
-RenderWidgetHost* WebContentsCaptureMachine::GetTarget() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!web_contents())
- return NULL;
-
- RenderWidgetHost* rwh = NULL;
- if (fullscreen_widget_id_ != MSG_ROUTING_NONE) {
- RenderProcessHost* process = web_contents()->GetRenderProcessHost();
- if (process)
- rwh = RenderWidgetHost::FromID(process->GetID(), fullscreen_widget_id_);
- } else {
- rwh = web_contents()->GetRenderViewHost();
+gfx::Size WebContentsCaptureMachine::ComputeOptimalTargetSize() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ gfx::Size optimal_size = oracle_proxy_->GetCaptureSize();
+
+ // If the ratio between physical and logical pixels is greater than 1:1,
+ // shrink |optimal_size| by that amount. Then, when external code resizes the
+ // render widget to the "preferred size," the widget will be physically
+ // rendered at the exact capture size, thereby eliminating unnecessary scaling
+ // operations in the graphics pipeline.
+ RenderWidgetHost* const rwh = tracker_->GetTargetRenderWidgetHost();
+ RenderWidgetHostView* const rwhv = rwh ? rwh->GetView() : NULL;
+ if (rwhv) {
+ const gfx::NativeView view = rwhv->GetNativeView();
+ gfx::Screen* const screen = gfx::Screen::GetScreenFor(view);
+ const gfx::Display display = screen->GetDisplayNearestWindow(view);
+ const float scale = display.device_scale_factor();
+ if (scale > 1.0f) {
+ const gfx::Size shrunk_size(
+ gfx::ToFlooredSize(gfx::ScaleSize(optimal_size, 1.0f / scale)));
+ if (shrunk_size.width() > 0 && shrunk_size.height() > 0)
+ optimal_size = shrunk_size;
+ }
}
- return rwh;
+ VLOG(1) << "Computed optimal target size: " << optimal_size.ToString();
+ return optimal_size;
}
void WebContentsCaptureMachine::DidCopyFromBackingStore(
@@ -733,7 +688,7 @@ void WebContentsCaptureMachine::DidCopyFromBackingStore(
deliver_frame_cb,
bool success,
const SkBitmap& bitmap) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::TimeTicks now = base::TimeTicks::Now();
DCHECK(render_thread_.get());
@@ -756,7 +711,7 @@ void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&
deliver_frame_cb,
bool success) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::TimeTicks now = base::TimeTicks::Now();
if (success) {
@@ -768,15 +723,31 @@ void WebContentsCaptureMachine::DidCopyFromCompositingSurfaceToVideoFrame(
deliver_frame_cb.Run(start_time, success);
}
-void WebContentsCaptureMachine::RenewFrameSubscription() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void WebContentsCaptureMachine::RenewFrameSubscription(RenderWidgetHost* rwh) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Always destroy the old subscription before creating a new one.
+ const bool had_subscription = !!subscription_;
subscription_.reset();
- RenderWidgetHost* rwh = GetTarget();
- if (!rwh || !rwh->GetView())
+ DVLOG(1) << "Renewing frame subscription to RWH@" << rwh
+ << ", had_subscription=" << had_subscription;
+
+ if (!rwh) {
+ if (had_subscription && tracker_->web_contents())
+ tracker_->web_contents()->DecrementCapturerCount();
+ if (IsStarted()) {
+ // Tracking of WebContents and/or its main frame has failed before Stop()
+ // was called, so report this as an error:
+ oracle_proxy_->ReportError("WebContents and/or main frame are gone.");
+ }
return;
+ }
+
+ if (!had_subscription && tracker_->web_contents()) {
+ tracker_->web_contents()->IncrementCapturerCount(
+ ComputeOptimalTargetSize());
+ }
subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_,
base::Bind(&WebContentsCaptureMachine::Capture,
@@ -786,9 +757,10 @@ void WebContentsCaptureMachine::RenewFrameSubscription() {
} // namespace
WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
- int render_process_id, int render_view_id)
+ int render_process_id, int main_render_frame_id)
: core_(new ContentVideoCaptureDeviceCore(scoped_ptr<VideoCaptureMachine>(
- new WebContentsCaptureMachine(render_process_id, render_view_id)))) {}
+ new WebContentsCaptureMachine(
+ render_process_id, main_render_frame_id)))) {}
WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
@@ -797,15 +769,16 @@ WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
// static
media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
const std::string& device_id) {
- // Parse device_id into render_process_id and render_view_id.
+ // Parse device_id into render_process_id and main_render_frame_id.
int render_process_id = -1;
- int render_view_id = -1;
+ int main_render_frame_id = -1;
if (!WebContentsCaptureUtil::ExtractTabCaptureTarget(
- device_id, &render_process_id, &render_view_id)) {
+ device_id, &render_process_id, &main_render_frame_id)) {
return NULL;
}
- return new WebContentsVideoCaptureDevice(render_process_id, render_view_id);
+ return new WebContentsVideoCaptureDevice(
+ render_process_id, main_render_frame_id);
}
void WebContentsVideoCaptureDevice::AllocateAndStart(
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.h b/chromium/content/browser/media/capture/web_contents_video_capture_device.h
index 16c7b09f8e1..d385a2b5302 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.h
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.h
@@ -16,36 +16,32 @@ namespace content {
class ContentVideoCaptureDeviceCore;
// A virtualized VideoCaptureDevice that mirrors the displayed contents of a
-// tab (accessed via its associated WebContents instance), producing a stream of
-// video frames.
+// WebContents (i.e., the composition of an entire render frame tree), producing
+// a stream of video frames.
//
-// An instance is created by providing a device_id. The device_id contains the
-// routing ID for a RenderViewHost, and from the RenderViewHost instance, a
-// reference to its associated WebContents instance is acquired. From then on,
-// WebContentsVideoCaptureDevice will capture from whatever render view is
-// currently associated with that WebContents instance. This allows the
-// underlying render view to be swapped out (e.g., due to navigation or
-// crashes/reloads), without any interruption in capturing.
+// An instance is created by providing a device_id. The device_id contains
+// information necessary for finding a WebContents instance. From then on,
+// WebContentsVideoCaptureDevice will capture from the RenderWidgetHost that
+// encompasses the currently active RenderFrameHost tree for that that
+// WebContents instance. As the RenderFrameHost tree mutates (e.g., due to page
+// navigations, or crashes/reloads), capture will continue without interruption.
class CONTENT_EXPORT WebContentsVideoCaptureDevice
: public media::VideoCaptureDevice {
public:
- // Construct from a |device_id| string of the form:
- // "virtual-media-stream://render_process_id:render_view_id", where
- // |render_process_id| and |render_view_id| are decimal integers.
- // |destroy_cb| is invoked on an outside thread once all outstanding objects
- // are completely destroyed -- this will be some time after the
- // WebContentsVideoCaptureDevice is itself deleted.
+ // Create a WebContentsVideoCaptureDevice instance from the given
+ // |device_id|. Returns NULL if |device_id| is invalid.
static media::VideoCaptureDevice* Create(const std::string& device_id);
- virtual ~WebContentsVideoCaptureDevice();
+ ~WebContentsVideoCaptureDevice() override;
// VideoCaptureDevice implementation.
- virtual void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) OVERRIDE;
- virtual void StopAndDeAllocate() OVERRIDE;
+ void AllocateAndStart(const media::VideoCaptureParams& params,
+ scoped_ptr<Client> client) override;
+ void StopAndDeAllocate() override;
private:
- WebContentsVideoCaptureDevice(int render_process_id, int render_view_id);
+ WebContentsVideoCaptureDevice(
+ int render_process_id, int main_render_frame_id);
const scoped_ptr<ContentVideoCaptureDeviceCore> core_;
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
index dc1bd5a54d9..09f84454f60 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -32,6 +32,8 @@
#include "skia/ext/platform_canvas.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
namespace content {
namespace {
@@ -39,6 +41,7 @@ namespace {
const int kTestWidth = 320;
const int kTestHeight = 240;
const int kTestFramesPerSecond = 20;
+const float kTestDeviceScaleFactor = 2.0f;
const SkColor kNothingYet = 0xdeadbeef;
const SkColor kNotInterested = ~kNothingYet;
@@ -160,21 +163,21 @@ class CaptureTestView : public TestRenderWidgetHostView {
: TestRenderWidgetHostView(rwh),
controller_(controller) {}
- virtual ~CaptureTestView() {}
+ ~CaptureTestView() override {}
// TestRenderWidgetHostView overrides.
- virtual gfx::Rect GetViewBounds() const OVERRIDE {
+ gfx::Rect GetViewBounds() const override {
return gfx::Rect(100, 100, 100 + kTestWidth, 100 + kTestHeight);
}
- virtual bool CanCopyToVideoFrame() const OVERRIDE {
+ bool CanCopyToVideoFrame() const override {
return controller_->CanCopyToVideoFrame();
}
- virtual void CopyFromCompositingSurfaceToVideoFrame(
+ void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) OVERRIDE {
+ const base::Callback<void(bool)>& callback) override {
SkColor c = ConvertRgbToYuv(controller_->GetSolidColor());
media::FillYUV(
target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));
@@ -182,22 +185,20 @@ class CaptureTestView : public TestRenderWidgetHostView {
controller_->SignalCopy();
}
- virtual void BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE {
+ void BeginFrameSubscription(
+ scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override {
subscriber_.reset(subscriber.release());
}
- virtual void EndFrameSubscription() OVERRIDE {
- subscriber_.reset();
- }
+ void EndFrameSubscription() override { subscriber_.reset(); }
// Simulate a compositor paint event for our subscriber.
void SimulateUpdate() {
const base::TimeTicks present_time = base::TimeTicks::Now();
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
scoped_refptr<media::VideoFrame> target;
- if (subscriber_ && subscriber_->ShouldCaptureFrame(present_time,
- &target, &callback)) {
+ if (subscriber_ && subscriber_->ShouldCaptureFrame(
+ gfx::Rect(), present_time, &target, &callback)) {
SkColor c = ConvertRgbToYuv(controller_->GetSolidColor());
media::FillYUV(
target.get(), SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));
@@ -245,11 +246,11 @@ class CaptureTestRenderViewHost : public TestRenderViewHost {
}
// TestRenderViewHost overrides.
- virtual void CopyFromBackingStore(
+ void CopyFromBackingStore(
const gfx::Rect& src_rect,
const gfx::Size& accelerated_dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config& bitmap_config) OVERRIDE {
+ const SkColorType color_type) override {
gfx::Size size = controller_->GetCopyResultSize();
SkColor color = controller_->GetSolidColor();
@@ -283,18 +284,16 @@ class CaptureTestRenderViewHostFactory : public RenderViewHostFactory {
RegisterFactory(this);
}
- virtual ~CaptureTestRenderViewHostFactory() {
- UnregisterFactory();
- }
+ ~CaptureTestRenderViewHostFactory() override { UnregisterFactory(); }
// RenderViewHostFactory implementation.
- virtual RenderViewHost* CreateRenderViewHost(
+ RenderViewHost* CreateRenderViewHost(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
RenderWidgetHostDelegate* widget_delegate,
int routing_id,
int main_frame_routing_id,
- bool swapped_out) OVERRIDE {
+ bool swapped_out) override {
return new CaptureTestRenderViewHost(instance, delegate, widget_delegate,
routing_id, main_frame_routing_id,
swapped_out, controller_);
@@ -315,11 +314,11 @@ class StubClient : public media::VideoCaptureDevice::Client {
error_callback_(error_callback) {
buffer_pool_ = new VideoCaptureBufferPool(2);
}
- virtual ~StubClient() {}
+ ~StubClient() override {}
- virtual scoped_refptr<media::VideoCaptureDevice::Client::Buffer>
- ReserveOutputBuffer(media::VideoFrame::Format format,
- const gfx::Size& dimensions) OVERRIDE {
+ scoped_refptr<media::VideoCaptureDevice::Client::Buffer> ReserveOutputBuffer(
+ media::VideoFrame::Format format,
+ const gfx::Size& dimensions) override {
CHECK_EQ(format, media::VideoFrame::I420);
const size_t frame_bytes =
media::VideoFrame::AllocationSize(media::VideoFrame::I420, dimensions);
@@ -335,20 +334,19 @@ class StubClient : public media::VideoCaptureDevice::Client {
new PoolBuffer(buffer_pool_, buffer_id, data, size));
}
- virtual void OnIncomingCapturedData(
- const uint8* data,
- int length,
- const media::VideoCaptureFormat& frame_format,
- int rotation,
- base::TimeTicks timestamp) OVERRIDE {
+ void OnIncomingCapturedData(const uint8* data,
+ int length,
+ const media::VideoCaptureFormat& frame_format,
+ int rotation,
+ base::TimeTicks timestamp) override {
FAIL();
}
- virtual void OnIncomingCapturedVideoFrame(
+ void OnIncomingCapturedVideoFrame(
const scoped_refptr<Buffer>& buffer,
const media::VideoCaptureFormat& buffer_format,
const scoped_refptr<media::VideoFrame>& frame,
- base::TimeTicks timestamp) OVERRIDE {
+ base::TimeTicks timestamp) override {
EXPECT_EQ(gfx::Size(kTestWidth, kTestHeight), buffer_format.frame_size);
EXPECT_EQ(media::PIXEL_FORMAT_I420, buffer_format.pixel_format);
EXPECT_EQ(media::VideoFrame::I420, frame->format());
@@ -361,9 +359,7 @@ class StubClient : public media::VideoCaptureDevice::Client {
color_callback_.Run((SkColorSetRGB(yuv[0], yuv[1], yuv[2])));
}
- virtual void OnError(const std::string& reason) OVERRIDE {
- error_callback_.Run();
- }
+ void OnError(const std::string& reason) override { error_callback_.Run(); }
private:
class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
@@ -375,7 +371,7 @@ class StubClient : public media::VideoCaptureDevice::Client {
: Buffer(buffer_id, data, size), pool_(pool) {}
private:
- virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); }
+ ~PoolBuffer() override { pool_->RelinquishProducerReservation(id()); }
const scoped_refptr<VideoCaptureBufferPool> pool_;
};
@@ -399,7 +395,7 @@ class StubClientObserver {
virtual ~StubClientObserver() {}
scoped_ptr<media::VideoCaptureDevice::Client> PassClient() {
- return client_.PassAs<media::VideoCaptureDevice::Client>();
+ return client_.Pass();
}
void QuitIfConditionMet(SkColor color) {
@@ -466,6 +462,44 @@ class StubClientObserver {
DISALLOW_COPY_AND_ASSIGN(StubClientObserver);
};
+// A dummy implementation of gfx::Screen, since WebContentsVideoCaptureDevice
+// needs access to a gfx::Display's device scale factor.
+class FakeScreen : public gfx::Screen {
+ public:
+ FakeScreen() : the_one_display_(0x1337, gfx::Rect(0, 0, 2560, 1440)) {
+ the_one_display_.set_device_scale_factor(kTestDeviceScaleFactor);
+ }
+ ~FakeScreen() override {}
+
+ // gfx::Screen implementation (only what's needed for testing).
+ gfx::Point GetCursorScreenPoint() override { return gfx::Point(); }
+ gfx::NativeWindow GetWindowUnderCursor() override { return NULL; }
+ gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override {
+ return NULL;
+ }
+ int GetNumDisplays() const override { return 1; }
+ std::vector<gfx::Display> GetAllDisplays() const override {
+ return std::vector<gfx::Display>(1, the_one_display_);
+ }
+ gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override {
+ return the_one_display_;
+ }
+ gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override {
+ return the_one_display_;
+ }
+ gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override {
+ return the_one_display_;
+ }
+ gfx::Display GetPrimaryDisplay() const override { return the_one_display_; }
+ void AddObserver(gfx::DisplayObserver* observer) override {}
+ void RemoveObserver(gfx::DisplayObserver* observer) override {}
+
+ private:
+ gfx::Display the_one_display_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeScreen);
+};
+
// Test harness that sets up a minimal environment with necessary stubs.
class WebContentsVideoCaptureDeviceTest : public testing::Test {
public:
@@ -476,7 +510,10 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
}
protected:
- virtual void SetUp() {
+ void SetUp() override {
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, &fake_screen_);
+ ASSERT_EQ(&fake_screen_, gfx::Screen::GetNativeScreen());
+
// TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be
// eliminated here, if only we could use RenderViewHostTestHarness. The
// catch is that we need our TestRenderViewHost to support a
@@ -499,22 +536,16 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
render_process_host_factory_.get());
web_contents_.reset(
TestWebContents::Create(browser_context_.get(), site_instance.get()));
-
- // This is actually a CaptureTestRenderViewHost.
- RenderWidgetHostImpl* rwh =
- RenderWidgetHostImpl::From(web_contents_->GetRenderViewHost());
-
- std::string device_id =
- WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
- base::StringPrintf("%d:%d", rwh->GetProcess()->GetID(),
- rwh->GetRoutingID()));
-
- device_.reset(WebContentsVideoCaptureDevice::Create(device_id));
+ RenderFrameHost* const main_frame = web_contents_->GetMainFrame();
+ device_.reset(WebContentsVideoCaptureDevice::Create(
+ base::StringPrintf("web-contents-media-stream://%d:%d",
+ main_frame->GetProcess()->GetID(),
+ main_frame->GetRoutingID())));
base::RunLoop().RunUntilIdle();
}
- virtual void TearDown() {
+ void TearDown() override {
// Tear down in opposite order of set-up.
// The device is destroyed asynchronously, and will notify the
@@ -536,10 +567,13 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
SiteInstanceImpl::set_render_process_host_factory(NULL);
render_view_host_factory_.reset();
render_process_host_factory_.reset();
+
+ gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, NULL);
}
// Accessors.
CaptureTestSourceController* source() { return &controller_; }
+ WebContents* web_contents() const { return web_contents_.get(); }
media::VideoCaptureDevice* device() { return device_.get(); }
void SimulateDrawEvent() {
@@ -564,6 +598,8 @@ class WebContentsVideoCaptureDeviceTest : public testing::Test {
}
private:
+ FakeScreen fake_screen_;
+
StubClientObserver client_observer_;
// The controller controls which pixel patterns to produce.
@@ -596,20 +632,23 @@ TEST_F(WebContentsVideoCaptureDeviceTest, InvalidInitialWebContentsError) {
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError());
device()->StopAndDeAllocate();
}
TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
+ const gfx::Size capture_preferred_size(
+ static_cast<int>(kTestWidth / kTestDeviceScaleFactor),
+ static_cast<int>(kTestHeight / kTestDeviceScaleFactor));
+ ASSERT_NE(capture_preferred_size, web_contents()->GetPreferredSize());
+
// We'll simulate the tab being closed after the capture pipeline is up and
// running.
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
// Do one capture to prove
source()->SetSolidColor(SK_ColorRED);
@@ -618,6 +657,10 @@ TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
base::RunLoop().RunUntilIdle();
+ // Check that the preferred size of the WebContents matches the one provided
+ // by WebContentsVideoCaptureDevice.
+ EXPECT_EQ(capture_preferred_size, web_contents()->GetPreferredSize());
+
// Post a task to close the tab. We should see an error reported to the
// consumer.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
@@ -633,7 +676,6 @@ TEST_F(WebContentsVideoCaptureDeviceTest,
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
// Make a point of not running the UI messageloop here.
@@ -655,7 +697,6 @@ TEST_F(WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
base::RunLoop().RunUntilIdle();
@@ -675,7 +716,6 @@ TEST_F(WebContentsVideoCaptureDeviceTest, DeviceRestart) {
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
base::RunLoop().RunUntilIdle();
source()->SetSolidColor(SK_ColorRED);
@@ -714,7 +754,6 @@ TEST_F(WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
for (int i = 0; i < 6; i++) {
@@ -765,7 +804,6 @@ TEST_F(WebContentsVideoCaptureDeviceTest, RejectsInvalidAllocateParams) {
capture_params.requested_format.frame_size.SetSize(1280, 720);
capture_params.requested_format.frame_rate = -2;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
@@ -787,7 +825,6 @@ TEST_F(WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- capture_params.allow_resolution_change = false;
// 1x1 is too small to process; we intend for this to result in an error.
source()->SetCopyResultSize(1, 1);
source()->SetSolidColor(SK_ColorRED);
diff --git a/chromium/content/browser/media/cdm/browser_cdm_manager.cc b/chromium/content/browser/media/cdm/browser_cdm_manager.cc
index a71bfafbd5f..d3d4630cb08 100644
--- a/chromium/content/browser/media/cdm/browser_cdm_manager.cc
+++ b/chromium/content/browser/media/cdm/browser_cdm_manager.cc
@@ -4,8 +4,12 @@
#include "content/browser/media/cdm/browser_cdm_manager.h"
+#include "base/bind.h"
#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/task_runner.h"
#include "content/common/media/cdm_messages.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -28,41 +32,121 @@ const size_t kMaxInitDataLength = 64 * 1024; // 64 KB
const size_t kMaxSessionResponseLength = 64 * 1024; // 64 KB
const size_t kMaxKeySystemLength = 256;
-// static
-BrowserCdmManager* BrowserCdmManager::Create(RenderFrameHost* rfh) {
- return new BrowserCdmManager(rfh);
+// The ID used in this class is a concatenation of |render_frame_id| and
+// |cdm_id|, i.e. (render_frame_id << 32) + cdm_id.
+
+static uint64 GetId(int render_frame_id, int cdm_id) {
+ return (static_cast<uint64>(render_frame_id) << 32) +
+ static_cast<uint64>(cdm_id);
+}
+
+static bool IdBelongsToFrame(uint64 id, int render_frame_id) {
+ return (id >> 32) == static_cast<uint64>(render_frame_id);
+}
+
+// Render process ID to BrowserCdmManager map.
+typedef std::map<int, BrowserCdmManager*> BrowserCdmManagerMap;
+base::LazyInstance<BrowserCdmManagerMap> g_browser_cdm_manager_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+BrowserCdmManager* BrowserCdmManager::FromProcess(int render_process_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!g_browser_cdm_manager_map.Get().count(render_process_id))
+ return NULL;
+
+ return g_browser_cdm_manager_map.Get()[render_process_id];
}
-BrowserCdmManager::BrowserCdmManager(RenderFrameHost* render_frame_host)
- : render_frame_host_(render_frame_host),
- web_contents_(WebContents::FromRenderFrameHost(render_frame_host)),
- weak_ptr_factory_(this) {
+BrowserCdmManager::BrowserCdmManager(
+ int render_process_id,
+ const scoped_refptr<base::TaskRunner>& task_runner)
+ : BrowserMessageFilter(CdmMsgStart),
+ render_process_id_(render_process_id),
+ task_runner_(task_runner) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!task_runner_.get()) {
+ task_runner_ =
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
+ }
+
+ // This may overwrite an existing entry of |render_process_id| if the
+ // previous process crashed and didn't cleanup its child frames. For example,
+ // see FrameTreeBrowserTest.FrameTreeAfterCrash test.
+ g_browser_cdm_manager_map.Get()[render_process_id] = this;
}
BrowserCdmManager::~BrowserCdmManager() {
- // During the tear down process, OnDestroyCdm() may or may not be called
- // (e.g. WebContents may be destroyed before the render process is killed). So
- // we cannot DCHECK(cdm_map_.empty()) here. Instead, all CDMs in |cdm_map_|
- // will be destroyed here because they are owned by BrowserCdmManager.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(g_browser_cdm_manager_map.Get().count(render_process_id_));
+
+ g_browser_cdm_manager_map.Get().erase(render_process_id_);
}
-BrowserCdm* BrowserCdmManager::GetCdm(int cdm_id) {
- return cdm_map_.get(cdm_id);
+// Makes sure BrowserCdmManager is always deleted on the Browser UI thread.
+void BrowserCdmManager::OnDestruct() const {
+ if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ delete this;
+ } else {
+ BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
+ }
}
-void BrowserCdmManager::OnSessionCreated(
- int cdm_id,
- uint32 session_id,
- const std::string& web_session_id) {
+base::TaskRunner* BrowserCdmManager::OverrideTaskRunnerForMessage(
+ const IPC::Message& message) {
+ // Only handles CDM messages.
+ if (IPC_MESSAGE_CLASS(message) != CdmMsgStart)
+ return NULL;
+
+ return task_runner_.get();
+}
+
+bool BrowserCdmManager::OnMessageReceived(const IPC::Message& msg) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BrowserCdmManager, msg)
+ IPC_MESSAGE_HANDLER(CdmHostMsg_InitializeCdm, OnInitializeCdm)
+ IPC_MESSAGE_HANDLER(CdmHostMsg_CreateSession, OnCreateSession)
+ IPC_MESSAGE_HANDLER(CdmHostMsg_UpdateSession, OnUpdateSession)
+ IPC_MESSAGE_HANDLER(CdmHostMsg_ReleaseSession, OnReleaseSession)
+ IPC_MESSAGE_HANDLER(CdmHostMsg_DestroyCdm, OnDestroyCdm)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+media::BrowserCdm* BrowserCdmManager::GetCdm(int render_frame_id, int cdm_id) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ return cdm_map_.get(GetId(render_frame_id, cdm_id));
+}
+
+void BrowserCdmManager::RenderFrameDeleted(int render_frame_id) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ std::vector<uint64> ids_to_remove;
+ for (CdmMap::iterator it = cdm_map_.begin(); it != cdm_map_.end(); ++it) {
+ if (IdBelongsToFrame(it->first, render_frame_id))
+ ids_to_remove.push_back(it->first);
+ }
+
+ for (size_t i = 0; i < ids_to_remove.size(); ++i)
+ RemoveCdm(ids_to_remove[i]);
+}
+
+void BrowserCdmManager::OnSessionCreated(int render_frame_id,
+ int cdm_id,
+ uint32 session_id,
+ const std::string& web_session_id) {
Send(new CdmMsg_SessionCreated(
- RoutingID(), cdm_id, session_id, web_session_id));
+ render_frame_id, cdm_id, session_id, web_session_id));
}
-void BrowserCdmManager::OnSessionMessage(
- int cdm_id,
- uint32 session_id,
- const std::vector<uint8>& message,
- const GURL& destination_url) {
+void BrowserCdmManager::OnSessionMessage(int render_frame_id,
+ int cdm_id,
+ uint32 session_id,
+ const std::vector<uint8>& message,
+ const GURL& destination_url) {
GURL verified_gurl = destination_url;
if (!verified_gurl.is_valid() && !verified_gurl.is_empty()) {
DLOG(WARNING) << "SessionMessage destination_url is invalid : "
@@ -71,28 +155,34 @@ void BrowserCdmManager::OnSessionMessage(
}
Send(new CdmMsg_SessionMessage(
- RoutingID(), cdm_id, session_id, message, verified_gurl));
+ render_frame_id, cdm_id, session_id, message, verified_gurl));
}
-void BrowserCdmManager::OnSessionReady(int cdm_id, uint32 session_id) {
- Send(new CdmMsg_SessionReady(RoutingID(), cdm_id, session_id));
+void BrowserCdmManager::OnSessionReady(int render_frame_id,
+ int cdm_id,
+ uint32 session_id) {
+ Send(new CdmMsg_SessionReady(render_frame_id, cdm_id, session_id));
}
-void BrowserCdmManager::OnSessionClosed(int cdm_id, uint32 session_id) {
- Send(new CdmMsg_SessionClosed(RoutingID(), cdm_id, session_id));
+void BrowserCdmManager::OnSessionClosed(int render_frame_id,
+ int cdm_id,
+ uint32 session_id) {
+ Send(new CdmMsg_SessionClosed(render_frame_id, cdm_id, session_id));
}
-void BrowserCdmManager::OnSessionError(int cdm_id,
+void BrowserCdmManager::OnSessionError(int render_frame_id,
+ int cdm_id,
uint32 session_id,
MediaKeys::KeyError error_code,
uint32 system_code) {
Send(new CdmMsg_SessionError(
- RoutingID(), cdm_id, session_id, error_code, system_code));
+ render_frame_id, cdm_id, session_id, error_code, system_code));
}
-void BrowserCdmManager::OnInitializeCdm(int cdm_id,
- const std::string& key_system,
- const GURL& security_origin) {
+void BrowserCdmManager::OnInitializeCdm(int render_frame_id,
+ int cdm_id,
+ const std::string& key_system,
+ const GURL& security_origin) {
if (key_system.size() > kMaxKeySystemLength) {
// This failure will be discovered and reported by OnCreateSession()
// as GetCdm() will return null.
@@ -100,10 +190,11 @@ void BrowserCdmManager::OnInitializeCdm(int cdm_id,
return;
}
- AddCdm(cdm_id, key_system, security_origin);
+ AddCdm(render_frame_id, cdm_id, key_system, security_origin);
}
void BrowserCdmManager::OnCreateSession(
+ int render_frame_id,
int cdm_id,
uint32 session_id,
CdmHostMsg_CreateSession_ContentType content_type,
@@ -111,7 +202,7 @@ void BrowserCdmManager::OnCreateSession(
if (init_data.size() > kMaxInitDataLength) {
LOG(WARNING) << "InitData for ID: " << cdm_id
<< " too long: " << init_data.size();
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
@@ -135,101 +226,112 @@ void BrowserCdmManager::OnCreateSession(
#if defined(OS_ANDROID)
if (CommandLine::ForCurrentProcess()
->HasSwitch(switches::kDisableInfobarForProtectedMediaIdentifier)) {
- CreateSessionIfPermitted(cdm_id, session_id, mime_type, init_data, true);
+ CreateSessionIfPermitted(
+ render_frame_id, cdm_id, session_id, mime_type, init_data, true);
return;
}
#endif
- BrowserCdm* cdm = GetCdm(cdm_id);
+ BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
if (!cdm) {
- DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
- std::map<int, GURL>::const_iterator iter =
- cdm_security_origin_map_.find(cdm_id);
+ std::map<uint64, GURL>::const_iterator iter =
+ cdm_security_origin_map_.find(GetId(render_frame_id, cdm_id));
if (iter == cdm_security_origin_map_.end()) {
NOTREACHED();
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
-
- base::Closure cancel_callback;
- GetContentClient()->browser()->RequestProtectedMediaIdentifierPermission(
- web_contents_,
- iter->second,
+ GURL security_origin = iter->second;
+
+ RenderFrameHost* rfh =
+ RenderFrameHost::FromID(render_process_id_, render_frame_id);
+ WebContents* web_contents = WebContents::FromRenderFrameHost(rfh);
+ DCHECK(web_contents);
+ GetContentClient()->browser()->RequestPermission(
+ content::PERMISSION_PROTECTED_MEDIA,
+ web_contents,
+ 0, // bridge id
+ security_origin,
+ // Only implemented for Android infobars which do not support
+ // user gestures.
+ true,
base::Bind(&BrowserCdmManager::CreateSessionIfPermitted,
- weak_ptr_factory_.GetWeakPtr(),
+ this,
+ render_frame_id,
cdm_id,
session_id,
mime_type,
- init_data),
- &cancel_callback);
- if (!cancel_callback.is_null())
- cdm_cancel_permision_map_[cdm_id] = cancel_callback;
+ init_data));
}
void BrowserCdmManager::OnUpdateSession(
+ int render_frame_id,
int cdm_id,
uint32 session_id,
const std::vector<uint8>& response) {
- BrowserCdm* cdm = GetCdm(cdm_id);
+ BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
if (!cdm) {
- DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
if (response.size() > kMaxSessionResponseLength) {
LOG(WARNING) << "Response for ID " << cdm_id
<< " is too long: " << response.size();
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
cdm->UpdateSession(session_id, &response[0], response.size());
}
-void BrowserCdmManager::OnReleaseSession(int cdm_id, uint32 session_id) {
- BrowserCdm* cdm = GetCdm(cdm_id);
+void BrowserCdmManager::OnReleaseSession(int render_frame_id,
+ int cdm_id,
+ uint32 session_id) {
+ BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
if (!cdm) {
- DLOG(WARNING) << "No CDM for ID " << cdm_id << " found";
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
cdm->ReleaseSession(session_id);
}
-void BrowserCdmManager::OnDestroyCdm(int cdm_id) {
- BrowserCdm* cdm = GetCdm(cdm_id);
- if (!cdm)
- return;
-
- CancelAllPendingSessionCreations(cdm_id);
- RemoveCdm(cdm_id);
+void BrowserCdmManager::OnDestroyCdm(int render_frame_id, int cdm_id) {
+ RemoveCdm(GetId(render_frame_id, cdm_id));
}
-void BrowserCdmManager::CancelAllPendingSessionCreations(int cdm_id) {
- if (cdm_cancel_permision_map_.count(cdm_id)) {
- cdm_cancel_permision_map_[cdm_id].Run();
- cdm_cancel_permision_map_.erase(cdm_id);
- }
+void BrowserCdmManager::SendSessionError(int render_frame_id,
+ int cdm_id,
+ uint32 session_id) {
+ OnSessionError(
+ render_frame_id, cdm_id, session_id, MediaKeys::kUnknownError, 0);
}
-void BrowserCdmManager::AddCdm(int cdm_id,
+#define BROWSER_CDM_MANAGER_CB(func) \
+ base::Bind(&BrowserCdmManager::func, this, render_frame_id, cdm_id)
+
+void BrowserCdmManager::AddCdm(int render_frame_id,
+ int cdm_id,
const std::string& key_system,
const GURL& security_origin) {
- DCHECK(!GetCdm(cdm_id));
- base::WeakPtr<BrowserCdmManager> weak_this = weak_ptr_factory_.GetWeakPtr();
- scoped_ptr<BrowserCdm> cdm(media::CreateBrowserCdm(
- key_system,
- base::Bind(&BrowserCdmManager::OnSessionCreated, weak_this, cdm_id),
- base::Bind(&BrowserCdmManager::OnSessionMessage, weak_this, cdm_id),
- base::Bind(&BrowserCdmManager::OnSessionReady, weak_this, cdm_id),
- base::Bind(&BrowserCdmManager::OnSessionClosed, weak_this, cdm_id),
- base::Bind(&BrowserCdmManager::OnSessionError, weak_this, cdm_id)));
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ DCHECK(!GetCdm(render_frame_id, cdm_id));
+
+ scoped_ptr<BrowserCdm> cdm(
+ media::CreateBrowserCdm(key_system,
+ BROWSER_CDM_MANAGER_CB(OnSessionCreated),
+ BROWSER_CDM_MANAGER_CB(OnSessionMessage),
+ BROWSER_CDM_MANAGER_CB(OnSessionReady),
+ BROWSER_CDM_MANAGER_CB(OnSessionClosed),
+ BROWSER_CDM_MANAGER_CB(OnSessionError)));
if (!cdm) {
// This failure will be discovered and reported by OnCreateSession()
@@ -238,44 +340,39 @@ void BrowserCdmManager::AddCdm(int cdm_id,
return;
}
- cdm_map_.add(cdm_id, cdm.Pass());
- cdm_security_origin_map_[cdm_id] = security_origin;
+ uint64 id = GetId(render_frame_id, cdm_id);
+ cdm_map_.add(id, cdm.Pass());
+ cdm_security_origin_map_[id] = security_origin;
}
-void BrowserCdmManager::RemoveCdm(int cdm_id) {
- // TODO(xhwang): Detach CDM from the player it's set to. In prefixed
- // EME implementation the current code is fine because we always destroy the
- // player before we destroy the DrmBridge. This will not always be the case
- // in unprefixed EME implementation.
- cdm_map_.erase(cdm_id);
- cdm_security_origin_map_.erase(cdm_id);
- cdm_cancel_permision_map_.erase(cdm_id);
-}
-
-int BrowserCdmManager::RoutingID() {
- return render_frame_host_->GetRoutingID();
-}
+void BrowserCdmManager::RemoveCdm(uint64 id) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
-bool BrowserCdmManager::Send(IPC::Message* msg) {
- return render_frame_host_->Send(msg);
+ cdm_map_.erase(id);
+ cdm_security_origin_map_.erase(id);
+ if (cdm_cancel_permission_map_.count(id)) {
+ cdm_cancel_permission_map_[id].Run();
+ cdm_cancel_permission_map_.erase(id);
+ }
}
void BrowserCdmManager::CreateSessionIfPermitted(
+ int render_frame_id,
int cdm_id,
uint32 session_id,
const std::string& content_type,
const std::vector<uint8>& init_data,
bool permitted) {
- cdm_cancel_permision_map_.erase(cdm_id);
+ cdm_cancel_permission_map_.erase(GetId(render_frame_id, cdm_id));
if (!permitted) {
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
- BrowserCdm* cdm = GetCdm(cdm_id);
+ BrowserCdm* cdm = GetCdm(render_frame_id, cdm_id);
if (!cdm) {
- DLOG(WARNING) << "No CDM for ID: " << cdm_id << " found";
- OnSessionError(cdm_id, session_id, MediaKeys::kUnknownError, 0);
+ DLOG(WARNING) << "No CDM found for: " << render_frame_id << ", " << cdm_id;
+ SendSessionError(render_frame_id, cdm_id, session_id);
return;
}
diff --git a/chromium/content/browser/media/cdm/browser_cdm_manager.h b/chromium/content/browser/media/cdm/browser_cdm_manager.h
index 85be4c182a5..27fb5c93e83 100644
--- a/chromium/content/browser/media/cdm/browser_cdm_manager.h
+++ b/chromium/content/browser/media/cdm/browser_cdm_manager.h
@@ -15,6 +15,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/common/media/cdm_messages_enums.h"
+#include "content/public/browser/browser_message_filter.h"
#include "ipc/ipc_message.h"
// TODO(xhwang): Drop this when KeyError is moved to a common header.
#include "media/base/media_keys.h"
@@ -26,99 +27,120 @@ class BrowserCdm;
namespace content {
-class RenderFrameHost;
-class WebContents;
-
// This class manages all CDM objects. It receives control operations from the
// the render process, and forwards them to corresponding CDM object. Callbacks
// from CDM objects are converted to IPCs and then sent to the render process.
-class CONTENT_EXPORT BrowserCdmManager {
+class CONTENT_EXPORT BrowserCdmManager : public BrowserMessageFilter {
public:
- // Creates a new BrowserCdmManager for |rfh|.
- static BrowserCdmManager* Create(RenderFrameHost* rfh);
-
- ~BrowserCdmManager();
-
- media::BrowserCdm* GetCdm(int cdm_id);
+ // Returns the BrowserCdmManager associated with the |render_process_id|.
+ // Returns NULL if no BrowserCdmManager is associated.
+ static BrowserCdmManager* FromProcess(int render_process_id);
+
+ // Constructs the BrowserCdmManager for |render_process_id| which runs on
+ // |task_runner|.
+ // If |task_runner| is not NULL, all CDM messages are posted to it. Otherwise,
+ // all messages are posted to the browser UI thread.
+ BrowserCdmManager(int render_process_id,
+ const scoped_refptr<base::TaskRunner>& task_runner);
+
+ // BrowserMessageFilter implementations.
+ virtual void OnDestruct() const override;
+ virtual base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
+
+ media::BrowserCdm* GetCdm(int render_frame_id, int cdm_id);
+
+ // Notifies that the render frame has been deleted so that all CDMs belongs
+ // to this render frame needs to be destroyed as well. This is needed because
+ // in some cases (e.g. fast termination of the renderer), the message to
+ // destroy the CDM will not be received.
+ void RenderFrameDeleted(int render_frame_id);
+
+ protected:
+ friend class base::RefCountedThreadSafe<BrowserCdmManager>;
+ friend class base::DeleteHelper<BrowserCdmManager>;
+ virtual ~BrowserCdmManager();
+ private:
// CDM callbacks.
- void OnSessionCreated(int cdm_id,
+ void OnSessionCreated(int render_frame_id,
+ int cdm_id,
uint32 session_id,
const std::string& web_session_id);
- void OnSessionMessage(int cdm_id,
+ void OnSessionMessage(int render_frame_id,
+ int cdm_id,
uint32 session_id,
const std::vector<uint8>& message,
const GURL& destination_url);
- void OnSessionReady(int cdm_id, uint32 session_id);
- void OnSessionClosed(int cdm_id, uint32 session_id);
- void OnSessionError(int cdm_id,
+ void OnSessionReady(int render_frame_id, int cdm_id, uint32 session_id);
+ void OnSessionClosed(int render_frame_id, int cdm_id, uint32 session_id);
+ void OnSessionError(int render_frame_id,
+ int cdm_id,
uint32 session_id,
media::MediaKeys::KeyError error_code,
uint32 system_code);
// Message handlers.
- void OnInitializeCdm(int cdm_id,
+ void OnInitializeCdm(int render_frame_id,
+ int cdm_id,
const std::string& key_system,
const GURL& frame_url);
- void OnCreateSession(int cdm_id,
+ void OnCreateSession(int render_frame_id,
+ int cdm_id,
uint32 session_id,
CdmHostMsg_CreateSession_ContentType content_type,
const std::vector<uint8>& init_data);
- void OnUpdateSession(int cdm_id,
+ void OnUpdateSession(int render_frame_id,
+ int cdm_id,
uint32 session_id,
const std::vector<uint8>& response);
- void OnReleaseSession(int cdm_id, uint32 session_id);
- void OnSetCdm(int player_id, int cdm_id);
- void OnDestroyCdm(int cdm_id);
-
- private:
- // Clients must use Create() or subclass constructor.
- explicit BrowserCdmManager(RenderFrameHost* render_frame_host);
+ void OnReleaseSession(int render_frame_id,
+ int cdm_id, uint32 session_id);
+ void OnDestroyCdm(int render_frame_id, int cdm_id);
- // Cancels all pending session creations associated with |cdm_id|.
- void CancelAllPendingSessionCreations(int cdm_id);
+ void SendSessionError(int render_frame_id, int cdm_id, uint32 session_id);
// Adds a new CDM identified by |cdm_id| for the given |key_system| and
// |security_origin|.
- void AddCdm(int cdm_id,
+ void AddCdm(int render_frame_id,
+ int cdm_id,
const std::string& key_system,
const GURL& security_origin);
// Removes the CDM with the specified id.
- void RemoveCdm(int cdm_id);
-
- int RoutingID();
-
- // Helper function to send messages to RenderFrameObserver.
- bool Send(IPC::Message* msg);
+ void RemoveCdm(uint64 id);
// If |permitted| is false, it does nothing but send
// |CdmMsg_SessionError| IPC message.
// The primary use case is infobar permission callback, i.e., when infobar
// can decide user's intention either from interacting with the actual info
// bar or from the saved preference.
- void CreateSessionIfPermitted(int cdm_id,
+ void CreateSessionIfPermitted(int render_frame_id,
+ int cdm_id,
uint32 session_id,
const std::string& content_type,
const std::vector<uint8>& init_data,
bool permitted);
- RenderFrameHost* const render_frame_host_;
+ const int render_process_id_;
- WebContents* const web_contents_;
+ // TaskRunner to dispatch all CDM messages to. If it's NULL, all messages are
+ // dispatched to the browser UI thread.
+ scoped_refptr<base::TaskRunner> task_runner_;
- // A map from CDM IDs to managed CDMs.
- typedef base::ScopedPtrHashMap<int, media::BrowserCdm> CdmMap;
- CdmMap cdm_map_;
+ // The key in the following maps is a combination of |render_frame_id| and
+ // |cdm_id|.
- // Map from CDM ID to CDM's security origin.
- std::map<int, GURL> cdm_security_origin_map_;
+ // Map of managed BrowserCdms.
+ typedef base::ScopedPtrHashMap<uint64, media::BrowserCdm> CdmMap;
+ CdmMap cdm_map_;
- // Map from CDM ID to a callback to cancel the permission request.
- std::map<int, base::Closure> cdm_cancel_permision_map_;
+ // Map of CDM's security origin.
+ std::map<uint64, GURL> cdm_security_origin_map_;
- // NOTE: Weak pointers must be invalidated before all other member variables.
- base::WeakPtrFactory<BrowserCdmManager> weak_ptr_factory_;
+ // Map of callbacks to cancel the permission request.
+ std::map<uint64, base::Closure> cdm_cancel_permission_map_;
DISALLOW_COPY_AND_ASSIGN(BrowserCdmManager);
};
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index 9c0dbac6351..3d561424107 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "content/browser/media/media_browsertest.h"
@@ -26,6 +25,8 @@ const char kWebMAudioVideo[] = "video/webm; codecs=\"vorbis, vp8\"";
const char kEmeKeyError[] = "KEYERROR";
const char kEmeNotSupportedError[] = "NOTSUPPORTEDERROR";
+const char kDefaultEmePlayer[] = "eme_player.html";
+
// The type of video src used to load media.
enum SrcType {
SRC,
@@ -52,7 +53,7 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
public testing::WithParamInterface<std::tr1::tuple<const char*, SrcType> > {
public:
// Can only be used in parameterized (*_P) tests.
- const char* CurrentKeySystem() {
+ const std::string CurrentKeySystem() {
return std::tr1::get<0>(GetParam());
}
@@ -61,14 +62,15 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
return std::tr1::get<1>(GetParam());
}
- void TestSimplePlayback(const char* encrypted_media, const char* media_type) {
+ void TestSimplePlayback(const std::string& encrypted_media,
+ const std::string& media_type) {
RunSimpleEncryptedMediaTest(
encrypted_media, media_type, CurrentKeySystem(), CurrentSourceType());
}
void TestFrameSizeChange() {
RunEncryptedMediaTest("encrypted_frame_size_change.html",
- "frame_size_change-av-enc-v.webm", kWebMAudioVideo,
+ "frame_size_change-av_enc-v.webm", kWebMAudioVideo,
CurrentKeySystem(), CurrentSourceType(), kEnded);
}
@@ -78,50 +80,56 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
return;
}
- std::vector<StringPair> query_params;
- query_params.push_back(std::make_pair("keysystem", CurrentKeySystem()));
- query_params.push_back(std::make_pair("runencrypted", "1"));
- RunMediaTestPage("mse_config_change.html", &query_params, kEnded, true);
+ base::StringPairs query_params;
+ query_params.push_back(std::make_pair("keySystem", CurrentKeySystem()));
+ query_params.push_back(std::make_pair("runEncrypted", "1"));
+ query_params.push_back(std::make_pair("usePrefixedEME", "1"));
+ RunMediaTestPage("mse_config_change.html", query_params, kEnded, true);
}
- void RunEncryptedMediaTest(const char* html_page,
- const char* media_file,
- const char* media_type,
- const char* key_system,
+ void RunEncryptedMediaTest(const std::string& html_page,
+ const std::string& media_file,
+ const std::string& media_type,
+ const std::string& key_system,
SrcType src_type,
- const char* expectation) {
+ const std::string& expectation) {
if (src_type == MSE && !IsMSESupported()) {
VLOG(0) << "Skipping test - MSE not supported.";
return;
}
- std::vector<StringPair> query_params;
- query_params.push_back(std::make_pair("mediafile", media_file));
- query_params.push_back(std::make_pair("mediatype", media_type));
- query_params.push_back(std::make_pair("keysystem", key_system));
+ base::StringPairs query_params;
+ query_params.push_back(std::make_pair("mediaFile", media_file));
+ query_params.push_back(std::make_pair("mediaType", media_type));
+ query_params.push_back(std::make_pair("keySystem", key_system));
if (src_type == MSE)
- query_params.push_back(std::make_pair("usemse", "1"));
- RunMediaTestPage(html_page, &query_params, expectation, true);
+ query_params.push_back(std::make_pair("useMSE", "1"));
+ query_params.push_back(std::make_pair("usePrefixedEME", "1"));
+ RunMediaTestPage(html_page, query_params, expectation, true);
}
- void RunSimpleEncryptedMediaTest(const char* media_file,
- const char* media_type,
- const char* key_system,
+ void RunSimpleEncryptedMediaTest(const std::string& media_file,
+ const std::string& media_type,
+ const std::string& key_system,
SrcType src_type) {
- RunEncryptedMediaTest("encrypted_media_player.html", media_file,
- media_type, key_system, src_type, kEnded);
+ RunEncryptedMediaTest(kDefaultEmePlayer,
+ media_file,
+ media_type,
+ key_system,
+ src_type,
+ kEnded);
}
protected:
// We want to fail quickly when a test fails because an error is encountered.
- virtual void AddWaitForTitles(content::TitleWatcher* title_watcher) OVERRIDE {
+ void AddWaitForTitles(content::TitleWatcher* title_watcher) override {
MediaBrowserTest::AddWaitForTitles(title_watcher);
title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEmeNotSupportedError));
title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEmeKeyError));
}
#if defined(OS_ANDROID)
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ virtual void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(
switches::kDisableGestureRequirementForMediaPlayback);
}
@@ -141,23 +149,23 @@ INSTANTIATE_TEST_CASE_P(MSE_ClearKey, EncryptedMediaTest,
Combine(Values(kClearKeyKeySystem), Values(MSE)));
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
- TestSimplePlayback("bear-a-enc_a.webm", kWebMAudioOnly);
+ TestSimplePlayback("bear-a_enc-a.webm", kWebMAudioOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioClearVideo_WebM) {
- TestSimplePlayback("bear-320x240-av-enc_a.webm", kWebMAudioVideo);
+ TestSimplePlayback("bear-320x240-av_enc-a.webm", kWebMAudioVideo);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM) {
- TestSimplePlayback("bear-320x240-av-enc_av.webm", kWebMAudioVideo);
+ TestSimplePlayback("bear-320x240-av_enc-av.webm", kWebMAudioVideo);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoOnly_WebM) {
- TestSimplePlayback("bear-320x240-v-enc_v.webm", kWebMVideoOnly);
+ TestSimplePlayback("bear-320x240-v_enc-v.webm", kWebMVideoOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
- TestSimplePlayback("bear-320x240-av-enc_v.webm", kWebMAudioVideo);
+ TestSimplePlayback("bear-320x240-av_enc-v.webm", kWebMAudioVideo);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
@@ -174,8 +182,11 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
}
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
- RunEncryptedMediaTest("encrypted_media_player.html", "bear-a-enc_a.webm",
- kWebMAudioOnly, "com.example.foo", MSE,
+ RunEncryptedMediaTest(kDefaultEmePlayer,
+ "bear-a_enc-a.webm",
+ kWebMAudioOnly,
+ "com.example.foo",
+ MSE,
kEmeNotSupportedError);
}
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index bdd77096bc3..46f7a49b618 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -4,13 +4,14 @@
#include "content/browser/media/media_browsertest.h"
-#include "base/strings/stringprintf.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#include "media/base/test_data_util.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
// TODO(wolenetz): Fix Media.YUV* tests on MSVS 2012 x64. crbug.com/180074
#if defined(OS_WIN) && defined(ARCH_CPU_X86_64) && _MSC_VER == 1700
@@ -26,39 +27,37 @@ const char MediaBrowserTest::kEnded[] = "ENDED";
const char MediaBrowserTest::kError[] = "ERROR";
const char MediaBrowserTest::kFailed[] = "FAILED";
-void MediaBrowserTest::RunMediaTestPage(
- const char* html_page, std::vector<StringPair>* query_params,
- const char* expected, bool http) {
+void MediaBrowserTest::RunMediaTestPage(const std::string& html_page,
+ const base::StringPairs& query_params,
+ const std::string& expected_title,
+ bool http) {
GURL gurl;
- std::string query = "";
- if (query_params != NULL && !query_params->empty()) {
- std::vector<StringPair>::const_iterator itr = query_params->begin();
- query = base::StringPrintf("%s=%s", itr->first, itr->second);
- ++itr;
- for (; itr != query_params->end(); ++itr) {
- query.append(base::StringPrintf("&%s=%s", itr->first, itr->second));
- }
- }
+ std::string query = media::GetURLQueryString(query_params);
+ scoped_ptr<net::SpawnedTestServer> http_test_server;
if (http) {
- ASSERT_TRUE(test_server()->Start());
- gurl = test_server()->GetURL(
- base::StringPrintf("files/media/%s?%s", html_page, query.c_str()));
+ http_test_server.reset(
+ new net::SpawnedTestServer(net::SpawnedTestServer::TYPE_HTTP,
+ net::SpawnedTestServer::kLocalhost,
+ media::GetTestDataPath()));
+ CHECK(http_test_server->Start());
+ gurl = http_test_server->GetURL("files/" + html_page + "?" + query);
} else {
- base::FilePath test_file_path = GetTestFilePath("media", html_page);
- gurl = GetFileUrlWithQuery(test_file_path, query);
+ gurl = content::GetFileUrlWithQuery(media::GetTestDataFilePath(html_page),
+ query);
}
- RunTest(gurl, expected);
+ std::string final_title = RunTest(gurl, expected_title);
+ EXPECT_EQ(expected_title, final_title);
}
-void MediaBrowserTest::RunTest(const GURL& gurl, const char* expected) {
- const base::string16 expected_title = base::ASCIIToUTF16(expected);
- DVLOG(1) << "Running test URL: " << gurl;
- TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+std::string MediaBrowserTest::RunTest(const GURL& gurl,
+ const std::string& expected_title) {
+ VLOG(0) << "Running test URL: " << gurl;
+ TitleWatcher title_watcher(shell()->web_contents(),
+ base::ASCIIToUTF16(expected_title));
AddWaitForTitles(&title_watcher);
NavigateToURL(shell(), gurl);
-
- base::string16 final_title = title_watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, final_title);
+ base::string16 result = title_watcher.WaitAndGetTitle();
+ return base::UTF16ToASCII(result);
}
void MediaBrowserTest::AddWaitForTitles(content::TitleWatcher* title_watcher) {
@@ -75,25 +74,39 @@ class MediaTest : public testing::WithParamInterface<bool>,
public MediaBrowserTest {
public:
// Play specified audio over http:// or file:// depending on |http| setting.
- void PlayAudio(const char* media_file, bool http) {
+ void PlayAudio(const std::string& media_file, bool http) {
PlayMedia("audio", media_file, http);
}
// Play specified video over http:// or file:// depending on |http| setting.
- void PlayVideo(const char* media_file, bool http) {
+ void PlayVideo(const std::string& media_file, bool http) {
PlayMedia("video", media_file, http);
}
// Run specified color format test with the expected result.
- void RunColorFormatTest(const char* media_file, const char* expected) {
- base::FilePath test_file_path = GetTestFilePath("media", "blackwhite.html");
+ void RunColorFormatTest(const std::string& media_file,
+ const std::string& expected) {
+ base::FilePath test_file_path =
+ media::GetTestDataFilePath("blackwhite.html");
RunTest(GetFileUrlWithQuery(test_file_path, media_file), expected);
}
- void PlayMedia(const char* tag, const char* media_file, bool http) {
- std::vector<StringPair> query_params;
+ void PlayMedia(const std::string& tag,
+ const std::string& media_file,
+ bool http) {
+ base::StringPairs query_params;
query_params.push_back(std::make_pair(tag, media_file));
- RunMediaTestPage("player.html", &query_params, kEnded, http);
+ RunMediaTestPage("player.html", query_params, kEnded, http);
+ }
+
+ void RunVideoSizeTest(const char* media_file, int width, int height) {
+ std::string expected;
+ expected += base::IntToString(width);
+ expected += " ";
+ expected += base::IntToString(height);
+ base::StringPairs query_params;
+ query_params.push_back(std::make_pair("video", media_file));
+ RunMediaTestPage("player.html", query_params, expected, false);
}
};
@@ -140,7 +153,23 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMovPcmS16be) {
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMovPcmS24be) {
PlayVideo("bear_pcm_s24be.mov", GetParam());
}
-#endif
+
+IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated0) {
+ RunVideoSizeTest("bear_rotate_0.mp4", 1280, 720);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated90) {
+ RunVideoSizeTest("bear_rotate_90.mp4", 720, 1280);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated180) {
+ RunVideoSizeTest("bear_rotate_180.mp4", 1280, 720);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaTest, VideoBearRotated270) {
+ RunVideoSizeTest("bear_rotate_270.mp4", 720, 1280);
+}
+#endif // defined(USE_PROPRIETARY_CODECS)
#if defined(OS_CHROMEOS)
#if defined(USE_PROPRIETARY_CODECS)
@@ -171,8 +200,9 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavGsmms) {
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearFlac) {
PlayAudio("bear.flac", GetParam());
}
-#endif
-#endif
+#endif // defined(USE_PROPRIETARY_CODECS)
+#endif // defined(OS_CHROMEOS)
+
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearWavAlaw) {
PlayAudio("bear_alaw.wav", GetParam());
@@ -209,19 +239,19 @@ INSTANTIATE_TEST_CASE_P(File, MediaTest, ::testing::Values(false));
INSTANTIATE_TEST_CASE_P(Http, MediaTest, ::testing::Values(true));
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv420pTheora)) {
- RunColorFormatTest("yuv420p.ogv", "ENDED");
+ RunColorFormatTest("yuv420p.ogv", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv422pTheora)) {
- RunColorFormatTest("yuv422p.ogv", "ENDED");
+ RunColorFormatTest("yuv422p.ogv", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv444pTheora)) {
- RunColorFormatTest("yuv444p.ogv", "ENDED");
+ RunColorFormatTest("yuv444p.ogv", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv420pVp8)) {
- RunColorFormatTest("yuv420p.webm", "ENDED");
+ RunColorFormatTest("yuv420p.webm", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv444pVp9)) {
@@ -230,24 +260,24 @@ IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv444pVp9)) {
#if defined(USE_PROPRIETARY_CODECS)
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv420pH264)) {
- RunColorFormatTest("yuv420p.mp4", "ENDED");
+ RunColorFormatTest("yuv420p.mp4", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuvj420pH264)) {
- RunColorFormatTest("yuvj420p.mp4", "ENDED");
+ RunColorFormatTest("yuvj420p.mp4", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv422pH264)) {
- RunColorFormatTest("yuv422p.mp4", "ENDED");
+ RunColorFormatTest("yuv422p.mp4", kEnded);
}
IN_PROC_BROWSER_TEST_F(MediaTest, MAYBE(Yuv444pH264)) {
- RunColorFormatTest("yuv444p.mp4", "ENDED");
+ RunColorFormatTest("yuv444p.mp4", kEnded);
}
#if defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(MediaTest, Yuv420pMpeg4) {
- RunColorFormatTest("yuv420p.avi", "ENDED");
+ RunColorFormatTest("yuv420p.avi", kEnded);
}
#endif // defined(OS_CHROMEOS)
#endif // defined(USE_PROPRIETARY_CODECS)
diff --git a/chromium/content/browser/media/media_browsertest.h b/chromium/content/browser/media/media_browsertest.h
index b242db30259..caf5d147c76 100644
--- a/chromium/content/browser/media/media_browsertest.h
+++ b/chromium/content/browser/media/media_browsertest.h
@@ -5,10 +5,10 @@
#ifndef CONTENT_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
#define CONTENT_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
-#include <utility>
-#include <vector>
+#include <string>
#include "content/public/test/content_browser_test.h"
+#include "media/base/test_data_util.h"
namespace content {
@@ -19,8 +19,6 @@ class TitleWatcher;
// the test http server.
class MediaBrowserTest : public ContentBrowserTest {
public:
- typedef std::pair<const char*, const char*> StringPair;
-
// Common test results.
static const char kEnded[];
static const char kError[];
@@ -30,17 +28,18 @@ class MediaBrowserTest : public ContentBrowserTest {
// If http is true, the test starts a local http test server to load the test
// page, otherwise a local file URL is loaded inside the content shell.
// It uses RunTest() to check for expected test output.
- void RunMediaTestPage(const char* html_page,
- std::vector<StringPair>* query_params,
- const char* expected, bool http);
+ void RunMediaTestPage(const std::string& html_page,
+ const base::StringPairs& query_params,
+ const std::string& expected,
+ bool http);
// Opens a URL and waits for the document title to match either one of the
- // default strings or the expected string.
- void RunTest(const GURL& gurl, const char* expected);
+ // default strings or the expected string. Returns the matching title value.
+ std::string RunTest(const GURL& gurl, const std::string& expected);
virtual void AddWaitForTitles(content::TitleWatcher* title_watcher);
};
-} // namespace content
+} // namespace content
#endif // CONTENT_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index cfcfd5ae2c5..e454de461ec 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -32,20 +32,11 @@ const char kOggVideoProbably[] = "probably";
const char kOggVideoMaybe[] = "maybe";
const char kTheoraProbably[] = "probably";
const char kOpusProbably[] = "probably";
-#if defined(USE_PROPRIETARY_CODECS)
-const char kTheoraAndPropProbably[] = "probably";
-const char kOpusAndPropProbably[] = "probably";
-#else
-const char kTheoraAndPropProbably[] = "";
-const char kOpusAndPropProbably[] = "";
-#endif // USE_PROPRIETARY_CODECS
#else
const char kOggVideoProbably[] = "";
const char kOggVideoMaybe[] = "";
const char kTheoraProbably[] = "";
const char kOpusProbably[] = "";
-const char kTheoraAndPropProbably[] = "maybe";
-const char kOpusAndPropProbably[] = "maybe";
#endif // !OS_ANDROID
namespace content {
@@ -54,9 +45,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
public:
MediaCanPlayTypeTest() : url_("about:blank") { }
- virtual void SetUpOnMainThread() OVERRIDE {
- NavigateToURL(shell(), url_);
- }
+ void SetUpOnMainThread() override { NavigateToURL(shell(), url_); }
std::string CanPlay(const std::string& type) {
std::string command("document.createElement('video').canPlayType(");
@@ -71,6 +60,177 @@ public:
return result;
}
+ void TestMPEGUnacceptableCombinations(std::string mime) {
+ // Codecs must be followed by valid hexadecimal number.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.unknown\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.unknown\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.unknown\"'"));
+
+ // Codecs must not end with a dot.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.\"'"));
+
+ // Codecs not belonging to MPEG container.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, vorbis\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, opus\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40.2\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.2\"'"));
+
+ // Codecs are case sensitive.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC1.4d401e\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC3.64001f\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"MP4A\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"MP4A.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC1, MP4\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC3, MP4\"'"));
+ EXPECT_EQ(kNot,
+ CanPlay("'" + mime + "; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+ EXPECT_EQ(kNot,
+ CanPlay("'" + mime + "; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+ // Unknown codecs.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc4\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1x\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3x\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4ax\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
+ }
+
+ void TestOGGUnacceptableCombinations(std::string mime) {
+ // Codecs not belonging to OGG container.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, vorbis\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, vorbis\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, opus\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, mp4a.40.2\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, 1\"'"));
+
+ // Codecs are case sensitive.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Theora, Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Theora, Vorbis\"'"));
+
+ // Unknown codecs.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"unknown\"'"));
+ }
+
+ void TestWEBMUnacceptableCombinations(std::string mime) {
+ // Codecs not belonging to WEBM container.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, opus\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, opus\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0, mp4a.40\"'"));
+
+ // Codecs are case sensitive.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP8, Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP8.0, Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP9, Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP9.0, Opus\"'"));
+
+ // Unknown codec.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"unknown\"'"));
+ }
+
+ void TestWAVUnacceptableCombinations(std::string mime) {
+ // Codecs not belonging to WAV container.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.2\"'"));
+
+ // Unknown codec.
+ EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"unknown\"'"));
+ }
+
private:
GURL url_;
DISALLOW_COPY_AND_ASSIGN(MediaCanPlayTypeTest);
@@ -80,60 +240,12 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_wav) {
EXPECT_EQ(kMaybe, CanPlay("'audio/wav'"));
EXPECT_EQ(kProbably, CanPlay("'audio/wav; codecs=\"1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"theora\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp9.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"opus\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"mp4a.40.5\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"opus, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"opus, theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vorbis, mp4a\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"unknown\"'"));
+ TestWAVUnacceptableCombinations("audio/wav");
EXPECT_EQ(kMaybe, CanPlay("'audio/x-wav'"));
EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"theora\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"vp9.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"opus\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"mp4a.40.5\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"1, mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"1, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"1, theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"opus, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"opus, theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"vorbis, mp4a\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-wav; codecs=\"unknown\"'"));
+ TestWAVUnacceptableCombinations("audio/x-wav");
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) {
@@ -164,41 +276,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) {
EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp8, vp9\"'"));
EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp8.0, vp9.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, avc3\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8.0, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8.0, mp4a.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9.0, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9.0, mp4a.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"1\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"mp4a.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP8\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP9\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"Vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP8, Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP9, Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, Opus\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"unknown\"'"));
+
+ TestWEBMUnacceptableCombinations("video/webm");
EXPECT_EQ(kMaybe, CanPlay("'audio/webm'"));
EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"vorbis\"'"));
@@ -219,19 +298,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) {
EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9, opus\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"1, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vorbis, mp4a\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"mp4a.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"unknown\"'"));
+ TestWEBMUnacceptableCombinations("audio/webm");
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
@@ -244,37 +311,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
EXPECT_EQ(kOggVideoProbably,
CanPlay("'video/ogg; codecs=\"opus, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3, mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1, vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3, vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1, avc3\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"mp4a.4.02\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3.64001F, mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc1.4D401E, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"avc3.64001F, vorbis\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"Theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"Theora, Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"Theora, Vorbis\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'video/ogg; codecs=\"unknown\"'"));
+ TestOGGUnacceptableCombinations("video/ogg");
EXPECT_EQ(kMaybe, CanPlay("'audio/ogg'"));
EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vorbis\"'"));
@@ -282,30 +319,10 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
EXPECT_EQ(kOpusProbably, CanPlay("'audio/ogg; codecs=\"vorbis, opus\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, vorbis\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"opus, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"vorbis, 1\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"mp4a.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"Theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"Theora, Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"Theora, Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"unknown\"'"));
+ TestOGGUnacceptableCombinations("audio/ogg");
EXPECT_EQ(kMaybe, CanPlay("'application/ogg'"));
EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vorbis\"'"));
@@ -318,39 +335,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
EXPECT_EQ(kOpusProbably,
CanPlay("'application/ogg; codecs=\"opus, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc3, mp4a\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1, vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc3, vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1, avc3\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot,
- CanPlay("'application/ogg; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
- EXPECT_EQ(kNot,
- CanPlay("'application/ogg; codecs=\"avc3.64001F, mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc1.4D401E, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"avc3.64001F, vorbis\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"Theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"Theora, Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"Theora, Opus\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'application/ogg; codecs=\"unknown\"'"));
+ TestOGGUnacceptableCombinations("application/ogg");
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
@@ -374,41 +359,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1.\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3.\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"AVC1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"AVC3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"MP4A\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc4\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1x\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3x\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"unknown\"'"));
+ TestMPEGUnacceptableCombinations("audio/mpeg");
// audio/mp3 does not allow any codecs parameter
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3'"));
@@ -422,41 +373,7 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1.\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc3.\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"AVC1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"AVC3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"MP4A\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc4\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1x\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc3x\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"unknown\"'"));
+ TestMPEGUnacceptableCombinations("audio/mp3");
// audio/x-mp3 does not allow any codecs parameter
EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3'"));
@@ -470,596 +387,212 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"AVC1\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"AVC3\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"MP4A\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc2\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc4\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc1x\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc3x\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"unknown\"'"));
+ TestMPEGUnacceptableCombinations("audio/x-mp3");
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
- // TODO(amogh.bihani): Change this expectation when bug 53193 is fixed.
- std::string PropAndVP9Probably = "";
-#if defined (OS_ANDROID)
- if (base::android::BuildInfo::GetInstance()->sdk_int() < 19)
- PropAndVP9Probably = "maybe";
- else
- PropAndVP9Probably = "probably";
-#else
-#if defined(USE_PROPRIETARY_CODECS)
- PropAndVP9Probably = "probably";
-#endif // USE_PROPRIETARY_CODECS
-#endif // OS_ANDROID
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'video/mp4; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'video/mp4; codecs=\"avc3.64001F, mp4a.40.5\"'"));
-
- // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
- // http://crbug.com/53193 ----------------------------------------------------
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.unknown\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, mp4a.40\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, mp4a.40\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42801E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42C01E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"vp8\"'"));
- EXPECT_EQ(PropAndVP9Probably, CanPlay("'video/mp4; codecs=\"vp9\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42E11E\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42F01E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"vorbis\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3, vorbis\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably,
- CanPlay("'video/mp4; codecs=\"avc1.4D401E, vorbis\"'"));
+ CanPlay("'video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably,
- CanPlay("'video/mp4; codecs=\"avc3.64001F, vorbis\"'"));
-
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/mp4; codecs=\"opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/mp4; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/mp4; codecs=\"vp9, opus\"'"));
-
- EXPECT_EQ(kTheoraAndPropProbably, CanPlay("'video/mp4; codecs=\"theora\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, mp4a\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, mp4a.40.2\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, avc1\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, avc3\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, avc1.4D401E\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/mp4; codecs=\"theora, avc3.64001F\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC1\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC3\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"MP4A\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC3, MP4\"'"));
+ CanPlay("'video/mp4; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
+
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, mp4a.40.2\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, mp4a.40.2\"'"));
EXPECT_EQ(kPropMaybe,
- CanPlay("'video/mp4; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+ CanPlay("'video/mp4; codecs=\"avc1.42E01E, mp4a.40\"'"));
EXPECT_EQ(kPropMaybe,
- CanPlay("'video/mp4; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+ CanPlay("'video/mp4; codecs=\"avc3.42E01E, mp4a.40\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc4\"'"));
+ TestMPEGUnacceptableCombinations("video/mp4");
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"mp4ax\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"unknown\"'"));
- // ---------------------------------------------------------------------------
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a.40\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a.40\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, avc3\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42E01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42E01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42801E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42C01E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1, avc3\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1.42E11E\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42F01E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.64001F\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably,
- CanPlay("'video/x-m4v; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+ CanPlay("'video/x-m4v; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably,
- CanPlay("'video/x-m4v; codecs=\"avc3.64001F, mp4a.40.5\"'"));
-
- // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
- // http://crbug.com/53193 ----------------------------------------------------
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"vp8\"'"));
- EXPECT_EQ(PropAndVP9Probably, CanPlay("'video/x-m4v; codecs=\"vp9\"'"));
+ CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"vorbis\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'video/x-m4v; codecs=\"avc1.4D401E, vorbis\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'video/x-m4v; codecs=\"avc3.64001F, vorbis\"'"));
-
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/x-m4v; codecs=\"opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"vp9, opus\"'"));
-
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, mp4a\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, mp4a.40.2\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, avc1\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, avc3\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, avc1.4D401E\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'video/x-m4v; codecs=\"theora, avc3.64001F\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC1\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC3\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"MP4A\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC3, MP4\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a.40.2\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a.40.2\"'"));
EXPECT_EQ(kPropMaybe,
- CanPlay("'video/x-m4v; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+ CanPlay("'video/x-m4v; codecs=\"avc1.42E01E, mp4a.40\"'"));
EXPECT_EQ(kPropMaybe,
- CanPlay("'video/x-m4v; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc4\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"mp4ax\"'"));
+ CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"unknown\"'"));
- // ---------------------------------------------------------------------------
+ TestMPEGUnacceptableCombinations("video/x-m4v");
EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"mp4a.40\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.2\"'"));
- // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
- // http://crbug.com/53193 ----------------------------------------------------
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3, mp4a\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3, mp4a.40\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3.64001F\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/mp4; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/mp4; codecs=\"avc3.64001F mp4a.40.2\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/mp4; codecs=\"mp4a, vorbis\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/mp4; codecs=\"mp4a.40.2, vorbis\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vorbis\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vp8\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vp8.0\"'"));
- EXPECT_EQ(PropAndVP9Probably, CanPlay("'audio/mp4; codecs=\"vp9\"'"));
- EXPECT_EQ(PropAndVP9Probably, CanPlay("'audio/mp4; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp4; codecs=\"opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'audio/mp4; codecs=\"mp4a, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'audio/mp4; codecs=\"vorbis, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp4; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp4; codecs=\"vp9, opus\"'"));
-
- EXPECT_EQ(kTheoraAndPropProbably, CanPlay("'audio/mp4; codecs=\"theora\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'audio/mp4; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'audio/mp4; codecs=\"theora, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1, vorbis\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC1\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC3\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"MP4A\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(kPropMaybe,
- CanPlay("'audio/mp4; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(kPropMaybe,
- CanPlay("'audio/mp4; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc4\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc1x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc3x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"unknown\"'"));
- // ---------------------------------------------------------------------------
+ TestMPEGUnacceptableCombinations("audio/mp4");
EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"mp4a.40\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.2\"'"));
- // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
- // http://crbug.com/53193 ----------------------------------------------------
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3, mp4a\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1, mp4a\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.unknown\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3.\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"avc3.64001F mp4a.40.2\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"mp4a, vorbis\"'"));
- EXPECT_EQ(kPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"mp4a.40.2, vorbis\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vorbis\"'"));
-
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vp8\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vp8.0\"'"));
- EXPECT_EQ(PropAndVP9Probably, CanPlay("'audio/x-m4a; codecs=\"vp9\"'"));
- EXPECT_EQ(PropAndVP9Probably, CanPlay("'audio/x-m4a; codecs=\"vp9.0\"'"));
-
- EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/x-m4a; codecs=\"opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"mp4a, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"vorbis, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(kOpusAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"vp9, opus\"'"));
-
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"theora\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(kTheoraAndPropProbably,
- CanPlay("'audio/x-m4a; codecs=\"theora, mp4a\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1, vorbis\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC1\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC3\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"MP4A\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(kPropMaybe,
- CanPlay("'audio/x-m4a; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(kPropMaybe,
- CanPlay("'audio/x-m4a; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc2\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc4\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc1x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc3x\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"unknown\"'"));
- // ---------------------------------------------------------------------------
+ TestMPEGUnacceptableCombinations("audio/x-m4a");
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
// HLS are supported only on Android IceCreamSandwich and above (API level 14)
- std::string HLSProbably = "";
- std::string HLSMaybe = "";
- std::string HLSAndVP9Probably = "";
+ std::string probablyCanPlayHLS = kNot;
+ std::string maybeCanPlayHLS = kNot;
#if defined(OS_ANDROID)
- int sdk = base::android::BuildInfo::GetInstance()->sdk_int();
- if (sdk > 13) {
- HLSProbably = "probably";
- HLSMaybe = "maybe";
- if (sdk < 19)
- HLSAndVP9Probably = "maybe";
- else
- HLSAndVP9Probably = "probably";
+ if (base::android::BuildInfo::GetInstance()->sdk_int() > 13) {
+ probablyCanPlayHLS = kProbably;
+ maybeCanPlayHLS = kMaybe;
}
#endif
- EXPECT_EQ(HLSMaybe, CanPlay("'application/x-mpegurl'"));
+ EXPECT_EQ(maybeCanPlayHLS, CanPlay("'application/x-mpegurl'"));
- EXPECT_EQ(HLSProbably,
+ EXPECT_EQ(maybeCanPlayHLS,
CanPlay("'application/x-mpegurl; codecs=\"avc1\"'"));
- EXPECT_EQ(HLSProbably,
+ EXPECT_EQ(maybeCanPlayHLS,
CanPlay("'application/x-mpegurl; codecs=\"avc3\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"mp4a\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a\"'"));
-
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(HLSProbably,
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a.40\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a.40\"'"));
+
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3.42801E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3.42C01E\"'"));
+
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42E11E\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42F01E\"'"));
+
+ EXPECT_EQ(probablyCanPlayHLS,
CanPlay("'application/x-mpegurl; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc3.64001F, mp4a.40.5\"'"));
-
- // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
- // http://crbug.com/53193 ----------------------------------------------------
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(HLSProbably, CanPlay("'application/x-mpegurl; codecs=\"avc1.\"'"));
- EXPECT_EQ(HLSProbably, CanPlay("'application/x-mpegurl; codecs=\"avc3.\"'"));
- EXPECT_EQ(HLSProbably, CanPlay("'application/x-mpegurl; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(HLSProbably, CanPlay("'application/x-mpegurl; codecs=\"vp8\"'"));
- EXPECT_EQ(HLSAndVP9Probably,
- CanPlay("'application/x-mpegurl; codecs=\"vp9\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"vorbis\"'"));
-
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.4D401E, vorbis\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/x-mpegurl; codecs=\"avc3.64001F, vorbis\"'"));
-
- EXPECT_EQ(HLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"opus\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"vp9, opus\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"theora\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"theora, mp4a\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"theora, mp4a.40.2\"'"));
-
- EXPECT_EQ(HLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"AVC1\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(HLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"AVC3\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(HLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"MP4A\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"avc2\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"avc4\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"avc1x\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"avc3x\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/x-mpegurl; codecs=\"unknown\"'"));
- // ---------------------------------------------------------------------------
-
- EXPECT_EQ(HLSMaybe, CanPlay("'application/vnd.apple.mpegurl'"));
-
- EXPECT_EQ(HLSProbably,
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
+
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a.40.2\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a.40.2\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E, mp4a.40\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E, mp4a.40\"'"));
+
+ TestMPEGUnacceptableCombinations("application/x-mpegurl");
+
+ EXPECT_EQ(maybeCanPlayHLS, CanPlay("'application/vnd.apple.mpegurl'"));
+
+ EXPECT_EQ(maybeCanPlayHLS,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1\"'"));
- EXPECT_EQ(HLSProbably,
+ EXPECT_EQ(maybeCanPlayHLS,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a\"'"));
-
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(HLSProbably,
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a.40\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a.40\"'"));
+
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42E01E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.42E01E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.42801E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.42C01E\"'"));
+
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42E11E\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(probablyCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42F01E\"'"));
+
+ EXPECT_EQ(probablyCanPlayHLS,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.2\"'"));
- // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
- // http://crbug.com/53193 ----------------------------------------------------
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.unknown\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.unknown\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.unknown\"'"));
-
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.\"'"));
-
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp8\"'"));
- EXPECT_EQ(HLSAndVP9Probably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp9\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"vorbis\"'"));
-
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.4D401E, vorbis\"'"));
- EXPECT_EQ(HLSProbably,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.64001F, vorbis\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"opus\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp9, opus\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora, mp4a\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora, mp4a.40.2\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC1\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC1.4d401e\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC3\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC3.64001f\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"MP4A\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"MP4A.40.2\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC1, MP4\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC3, MP4\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; "
- "codecs=\", AVC1.4D401E, MP4.40.2\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; "
- "codecs=\", AVC3.64001F, MP4.40.2\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc2\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc4\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1x\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3x\"'"));
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4ax\"'"));
-
- EXPECT_EQ(HLSMaybe,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"unknown\"'"));
- // ---------------------------------------------------------------------------
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a.40.2\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a.40.2\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; "
+ "codecs=\"avc1.42E01E, mp4a.40\"'"));
+ EXPECT_EQ(maybeCanPlayHLS,
+ CanPlay("'application/vnd.apple.mpegurl; "
+ "codecs=\"avc3.42E01E, mp4a.40\"'"));
+
+ TestMPEGUnacceptableCombinations("application/vnd.apple.mpegurl");
}
} // namespace content
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index 1d3f4b4c09d..4d600851783 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -38,7 +38,7 @@ std::string EffectsToString(int effects) {
};
std::string ret;
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) {
+ for (size_t i = 0; i < arraysize(flags); ++i) {
if (effects & flags[i].flag) {
if (!ret.empty())
ret += " | ";
@@ -68,16 +68,16 @@ class AudioLogImpl : public media::AudioLog {
AudioLogImpl(int owner_id,
media::AudioLogFactory::AudioComponent component,
content::MediaInternals* media_internals);
- virtual ~AudioLogImpl();
+ ~AudioLogImpl() override;
- virtual void OnCreated(int component_id,
- const media::AudioParameters& params,
- const std::string& device_id) OVERRIDE;
- virtual void OnStarted(int component_id) OVERRIDE;
- virtual void OnStopped(int component_id) OVERRIDE;
- virtual void OnClosed(int component_id) OVERRIDE;
- virtual void OnError(int component_id) OVERRIDE;
- virtual void OnSetVolume(int component_id, double volume) OVERRIDE;
+ void OnCreated(int component_id,
+ const media::AudioParameters& params,
+ const std::string& device_id) override;
+ void OnStarted(int component_id) override;
+ void OnStopped(int component_id) override;
+ void OnClosed(int component_id) override;
+ void OnError(int component_id) override;
+ void OnSetVolume(int component_id, double volume) override;
private:
void SendSingleStringUpdate(int component_id,
@@ -110,7 +110,6 @@ void AudioLogImpl::OnCreated(int component_id,
dict.SetString(kAudioLogStatusKey, "created");
dict.SetString("device_id", device_id);
- dict.SetInteger("input_channels", params.input_channels());
dict.SetInteger("frames_per_buffer", params.frames_per_buffer());
dict.SetInteger("sample_rate", params.sample_rate());
dict.SetInteger("channels", params.channels());
@@ -118,7 +117,7 @@ void AudioLogImpl::OnCreated(int component_id,
ChannelLayoutToString(params.channel_layout()));
dict.SetString("effects", EffectsToString(params.effects()));
- media_internals_->SendUpdateAndCache(
+ media_internals_->SendUpdateAndCacheAudioStreamKey(
FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
}
@@ -134,7 +133,7 @@ void AudioLogImpl::OnClosed(int component_id) {
base::DictionaryValue dict;
StoreComponentMetadata(component_id, &dict);
dict.SetString(kAudioLogStatusKey, "closed");
- media_internals_->SendUpdateAndPurgeCache(
+ media_internals_->SendUpdateAndPurgeAudioStreamCache(
FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
}
@@ -146,7 +145,7 @@ void AudioLogImpl::OnSetVolume(int component_id, double volume) {
base::DictionaryValue dict;
StoreComponentMetadata(component_id, &dict);
dict.SetDouble("volume", volume);
- media_internals_->SendUpdateAndCache(
+ media_internals_->SendUpdateAndCacheAudioStreamKey(
FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
}
@@ -160,7 +159,7 @@ void AudioLogImpl::SendSingleStringUpdate(int component_id,
base::DictionaryValue dict;
StoreComponentMetadata(component_id, &dict);
dict.SetString(key, value);
- media_internals_->SendUpdateAndCache(
+ media_internals_->SendUpdateAndCacheAudioStreamKey(
FormatCacheKey(component_id), kAudioLogUpdateFunction, &dict);
}
@@ -215,14 +214,54 @@ void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
NOTREACHED();
}
-void MediaInternals::SendEverything() {
- base::string16 everything_update;
+void MediaInternals::SendAudioStreamData() {
+ base::string16 audio_stream_update;
{
base::AutoLock auto_lock(lock_);
- everything_update = SerializeUpdate(
- "media.onReceiveEverything", &cached_data_);
+ audio_stream_update = SerializeUpdate(
+ "media.onReceiveAudioStreamData", &audio_streams_cached_data_);
}
- SendUpdate(everything_update);
+ SendUpdate(audio_stream_update);
+}
+
+void MediaInternals::SendVideoCaptureDeviceCapabilities() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ SendUpdate(SerializeUpdate("media.onReceiveVideoCaptureCapabilities",
+ &video_capture_capabilities_cached_data_));
+}
+
+void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
+ const media::VideoCaptureDeviceInfos& video_capture_device_infos) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ video_capture_capabilities_cached_data_.Clear();
+
+ for (const auto& video_capture_device_info : video_capture_device_infos) {
+ base::ListValue* format_list = new base::ListValue();
+ for (const auto& format : video_capture_device_info.supported_formats)
+ format_list->AppendString(format.ToString());
+
+ base::DictionaryValue* device_dict = new base::DictionaryValue();
+ device_dict->SetString("id", video_capture_device_info.name.id());
+ device_dict->SetString(
+ "name", video_capture_device_info.name.GetNameAndModel());
+ device_dict->Set("formats", format_list);
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ device_dict->SetString(
+ "captureApi",
+ video_capture_device_info.name.GetCaptureApiTypeString());
+#endif
+ video_capture_capabilities_cached_data_.Append(device_dict);
+ }
+
+ if (update_callbacks_.size() > 0)
+ SendVideoCaptureDeviceCapabilities();
+}
+
+scoped_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
+ AudioComponent component) {
+ base::AutoLock auto_lock(lock_);
+ return scoped_ptr<media::AudioLog>(new AudioLogImpl(
+ owner_ids_[component]++, component, this));
}
void MediaInternals::SendUpdate(const base::string16& update) {
@@ -239,30 +278,24 @@ void MediaInternals::SendUpdate(const base::string16& update) {
update_callbacks_[i].Run(update);
}
-scoped_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
- AudioComponent component) {
- base::AutoLock auto_lock(lock_);
- return scoped_ptr<media::AudioLog>(new AudioLogImpl(
- owner_ids_[component]++, component, this));
-}
-
-void MediaInternals::SendUpdateAndCache(const std::string& cache_key,
- const std::string& function,
- const base::DictionaryValue* value) {
+void MediaInternals::SendUpdateAndCacheAudioStreamKey(
+ const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value) {
SendUpdate(SerializeUpdate(function, value));
base::AutoLock auto_lock(lock_);
- if (!cached_data_.HasKey(cache_key)) {
- cached_data_.Set(cache_key, value->DeepCopy());
+ if (!audio_streams_cached_data_.HasKey(cache_key)) {
+ audio_streams_cached_data_.Set(cache_key, value->DeepCopy());
return;
}
base::DictionaryValue* existing_dict = NULL;
- CHECK(cached_data_.GetDictionary(cache_key, &existing_dict));
+ CHECK(audio_streams_cached_data_.GetDictionary(cache_key, &existing_dict));
existing_dict->MergeDictionary(value);
}
-void MediaInternals::SendUpdateAndPurgeCache(
+void MediaInternals::SendUpdateAndPurgeAudioStreamCache(
const std::string& cache_key,
const std::string& function,
const base::DictionaryValue* value) {
@@ -270,7 +303,7 @@ void MediaInternals::SendUpdateAndPurgeCache(
base::AutoLock auto_lock(lock_);
scoped_ptr<base::Value> out_value;
- CHECK(cached_data_.Remove(cache_key, &out_value));
+ CHECK(audio_streams_cached_data_.Remove(cache_key, &out_value));
}
} // namespace content
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index c0f144a5b8b..4c1b2ed2ed6 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -16,6 +16,7 @@
#include "base/values.h"
#include "content/common/content_export.h"
#include "media/audio/audio_logging.h"
+#include "media/video/capture/video_capture_device_info.h"
namespace media {
class AudioParameters;
@@ -28,27 +29,34 @@ namespace content {
class CONTENT_EXPORT MediaInternals
: NON_EXPORTED_BASE(public media::AudioLogFactory) {
public:
+ // Called with the update string.
+ typedef base::Callback<void(const base::string16&)> UpdateCallback;
+
static MediaInternals* GetInstance();
- virtual ~MediaInternals();
+ ~MediaInternals() override;
// Called when a MediaEvent occurs.
void OnMediaEvents(int render_process_id,
const std::vector<media::MediaLogEvent>& events);
- // Called with the update string.
- typedef base::Callback<void(const base::string16&)> UpdateCallback;
-
// Add/remove update callbacks (see above). Must be called on the IO thread.
void AddUpdateCallback(const UpdateCallback& callback);
void RemoveUpdateCallback(const UpdateCallback& callback);
- // Sends all cached data to each registered UpdateCallback.
- void SendEverything();
+ // Sends all audio cached data to each registered UpdateCallback.
+ void SendAudioStreamData();
+
+ // Sends all video capture capabilities cached data to each registered
+ // UpdateCallback.
+ void SendVideoCaptureDeviceCapabilities();
+
+ // Called to inform of the capabilities enumerated for video devices.
+ void UpdateVideoCaptureDeviceCapabilities(
+ const media::VideoCaptureDeviceInfos& video_capture_device_infos);
// AudioLogFactory implementation. Safe to call from any thread.
- virtual scoped_ptr<media::AudioLog> CreateAudioLog(
- AudioComponent component) OVERRIDE;
+ scoped_ptr<media::AudioLog> CreateAudioLog(AudioComponent component) override;
private:
friend class AudioLogImpl;
@@ -61,22 +69,24 @@ class CONTENT_EXPORT MediaInternals
// thread, but will forward to the IO thread.
void SendUpdate(const base::string16& update);
- // Caches |value| under |cache_key| so that future SendEverything() calls will
- // include the current data. Calls JavaScript |function|(|value|) for each
- // registered UpdateCallback. SendUpdateAndPurgeCache() is similar but purges
- // the cache entry after completion instead.
- void SendUpdateAndCache(const std::string& cache_key,
- const std::string& function,
- const base::DictionaryValue* value);
- void SendUpdateAndPurgeCache(const std::string& cache_key,
- const std::string& function,
- const base::DictionaryValue* value);
+ // Caches |value| under |cache_key| so that future SendAudioStreamData() calls
+ // will include the current data. Calls JavaScript |function|(|value|) for
+ // each registered UpdateCallback. SendUpdateAndPurgeCache() is similar but
+ // purges the cache entry after completion instead.
+ void SendUpdateAndCacheAudioStreamKey(const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value);
+ void SendUpdateAndPurgeAudioStreamCache(const std::string& cache_key,
+ const std::string& function,
+ const base::DictionaryValue* value);
+
// Must only be accessed on the IO thread.
std::vector<UpdateCallback> update_callbacks_;
+ base::ListValue video_capture_capabilities_cached_data_;
// All variables below must be accessed under |lock_|.
base::Lock lock_;
- base::DictionaryValue cached_data_;
+ base::DictionaryValue audio_streams_cached_data_;
int owner_ids_[AUDIO_COMPONENT_MAX];
DISALLOW_COPY_AND_ASSIGN(MediaInternals);
diff --git a/chromium/content/browser/media/media_internals_handler.h b/chromium/content/browser/media/media_internals_handler.h
index 265c1224d7e..d984a96d1a2 100644
--- a/chromium/content/browser/media/media_internals_handler.h
+++ b/chromium/content/browser/media/media_internals_handler.h
@@ -21,10 +21,10 @@ class MediaInternalsProxy;
class MediaInternalsMessageHandler : public WebUIMessageHandler {
public:
MediaInternalsMessageHandler();
- virtual ~MediaInternalsMessageHandler();
+ ~MediaInternalsMessageHandler() override;
// WebUIMessageHandler implementation.
- virtual void RegisterMessages() OVERRIDE;
+ void RegisterMessages() override;
// Javascript message handlers.
void OnGetEverything(const base::ListValue* list);
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index 49456ab498a..4193a834812 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -137,7 +137,8 @@ void MediaInternalsProxy::StopObservingMediaInternalsOnIOThread() {
void MediaInternalsProxy::GetEverythingOnIOThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- MediaInternals::GetInstance()->SendEverything();
+ MediaInternals::GetInstance()->SendAudioStreamData();
+ MediaInternals::GetInstance()->SendVideoCaptureDeviceCapabilities();
}
void MediaInternalsProxy::UpdateUIOnUIThread(const base::string16& update) {
diff --git a/chromium/content/browser/media/media_internals_proxy.h b/chromium/content/browser/media/media_internals_proxy.h
index b737b858a3e..c2672f09d45 100644
--- a/chromium/content/browser/media/media_internals_proxy.h
+++ b/chromium/content/browser/media/media_internals_proxy.h
@@ -35,9 +35,9 @@ class MediaInternalsProxy
MediaInternalsProxy();
// NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
// Register a Handler and start receiving callbacks from MediaInternals.
void Attach(MediaInternalsMessageHandler* handler);
@@ -52,12 +52,12 @@ class MediaInternalsProxy
void OnUpdate(const base::string16& update);
// net::NetLog::ThreadSafeObserver implementation. Callable from any thread:
- virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE;
+ void OnAddEntry(const net::NetLog::Entry& entry) override;
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
friend class base::DeleteHelper<MediaInternalsProxy>;
- virtual ~MediaInternalsProxy();
+ ~MediaInternalsProxy() override;
// Build a dictionary mapping constant names to values.
base::Value* GetConstants();
diff --git a/chromium/content/browser/media/media_internals_ui.cc b/chromium/content/browser/media/media_internals_ui.cc
index f185bdca23e..3a5ac605234 100644
--- a/chromium/content/browser/media/media_internals_ui.cc
+++ b/chromium/content/browser/media/media_internals_ui.cc
@@ -6,12 +6,12 @@
#include "base/command_line.h"
#include "content/browser/media/media_internals_handler.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
-#include "grit/content_resources.h"
namespace content {
namespace {
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index b9208c8dfd1..da8e2c51eb3 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -8,48 +8,36 @@
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_parameters.h"
#include "media/base/channel_layout.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/size.h"
namespace {
const int kTestComponentID = 0;
const char kTestDeviceID[] = "test-device-id";
-} // namespace
-
-namespace content {
-class MediaInternalsTest
- : public testing::TestWithParam<media::AudioLogFactory::AudioComponent> {
+// This class encapsulates a MediaInternals reference. It also has some useful
+// methods to receive a callback, deserialize its associated data and expect
+// integer/string values.
+class MediaInternalsTestBase {
public:
- MediaInternalsTest()
- : media_internals_(MediaInternals::GetInstance()),
- update_cb_(base::Bind(&MediaInternalsTest::UpdateCallbackImpl,
- base::Unretained(this))),
- test_params_(media::AudioParameters::AUDIO_PCM_LINEAR,
- media::CHANNEL_LAYOUT_MONO,
- 0,
- 48000,
- 16,
- 128,
- media::AudioParameters::ECHO_CANCELLER |
- media::AudioParameters::DUCKING),
- test_component_(GetParam()),
- audio_log_(media_internals_->CreateAudioLog(test_component_)) {
- media_internals_->AddUpdateCallback(update_cb_);
- }
-
- virtual ~MediaInternalsTest() {
- media_internals_->RemoveUpdateCallback(update_cb_);
+ MediaInternalsTestBase()
+ : media_internals_(content::MediaInternals::GetInstance()) {
}
+ virtual ~MediaInternalsTestBase() {}
protected:
// Extracts and deserializes the JSON update data; merges into |update_data_|.
void UpdateCallbackImpl(const base::string16& update) {
- // Each update string looks like "<JavaScript Function Name>({<JSON>});", to
- // use the JSON reader we need to strip out the JavaScript code.
+ // Each update string looks like "<JavaScript Function Name>({<JSON>});"
+ // or for video capabilities: "<JavaScript Function Name>([{<JSON>}]);".
+ // In the second case we will be able to extract the dictionary if it is the
+ // only member of the list.
+ // To use the JSON reader we need to strip out the JS function name and ().
std::string utf8_update = base::UTF16ToUTF8(update);
const std::string::size_type first_brace = utf8_update.find('{');
const std::string::size_type last_brace = utf8_update.rfind('}');
@@ -62,34 +50,191 @@ class MediaInternalsTest
update_data_.MergeDictionary(output_dict);
}
- void ExpectInt(const std::string& key, int expected_value) {
+ void ExpectInt(const std::string& key, int expected_value) const {
int actual_value = 0;
ASSERT_TRUE(update_data_.GetInteger(key, &actual_value));
EXPECT_EQ(expected_value, actual_value);
}
- void ExpectString(const std::string& key, const std::string& expected_value) {
+ void ExpectString(const std::string& key,
+ const std::string& expected_value) const {
std::string actual_value;
ASSERT_TRUE(update_data_.GetString(key, &actual_value));
EXPECT_EQ(expected_value, actual_value);
}
- void ExpectStatus(const std::string& expected_value) {
+ void ExpectStatus(const std::string& expected_value) const {
ExpectString("status", expected_value);
}
- TestBrowserThreadBundle thread_bundle_;
- MediaInternals* const media_internals_;
- MediaInternals::UpdateCallback update_cb_;
+ void ExpectListOfStrings(const std::string& key,
+ const base::ListValue& expected_list) const {
+ const base::ListValue* actual_list;
+ ASSERT_TRUE(update_data_.GetList(key, &actual_list));
+ const size_t expected_size = expected_list.GetSize();
+ const size_t actual_size = actual_list->GetSize();
+ ASSERT_EQ(expected_size, actual_size);
+ for (size_t i = 0; i < expected_size; ++i) {
+ std::string expected_value, actual_value;
+ ASSERT_TRUE(expected_list.GetString(i, &expected_value));
+ ASSERT_TRUE(actual_list->GetString(i, &actual_value));
+ EXPECT_EQ(expected_value, actual_value);
+ }
+ }
+
+ const content::TestBrowserThreadBundle thread_bundle_;
base::DictionaryValue update_data_;
+ content::MediaInternals* const media_internals_;
+};
+
+} // namespace
+
+namespace content {
+
+class MediaInternalsVideoCaptureDeviceTest : public testing::Test,
+ public MediaInternalsTestBase {
+ public:
+ MediaInternalsVideoCaptureDeviceTest()
+ : update_cb_(base::Bind(
+ &MediaInternalsVideoCaptureDeviceTest::UpdateCallbackImpl,
+ base::Unretained(this))) {
+ media_internals_->AddUpdateCallback(update_cb_);
+ }
+
+ ~MediaInternalsVideoCaptureDeviceTest() override {
+ media_internals_->RemoveUpdateCallback(update_cb_);
+ }
+
+ protected:
+ MediaInternals::UpdateCallback update_cb_;
+};
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+TEST_F(MediaInternalsVideoCaptureDeviceTest,
+ AllCaptureApiTypesHaveProperStringRepresentation) {
+ typedef media::VideoCaptureDevice::Name VideoCaptureDeviceName;
+ typedef std::map<VideoCaptureDeviceName::CaptureApiType, std::string>
+ CaptureApiTypeStringMap;
+ CaptureApiTypeStringMap m;
+#if defined(OS_WIN)
+ m[VideoCaptureDeviceName::MEDIA_FOUNDATION] = "Media Foundation";
+ m[VideoCaptureDeviceName::DIRECT_SHOW] = "Direct Show";
+ m[VideoCaptureDeviceName::DIRECT_SHOW_WDM_CROSSBAR] =
+ "Direct Show WDM Crossbar";
+#elif defined(OS_MACOSX)
+ m[VideoCaptureDeviceName::AVFOUNDATION] = "AV Foundation";
+ m[VideoCaptureDeviceName::QTKIT] = "QTKit";
+ m[VideoCaptureDeviceName::DECKLINK] = "DeckLink";
+#endif
+ EXPECT_EQ(media::VideoCaptureDevice::Name::API_TYPE_UNKNOWN, m.size());
+ for (CaptureApiTypeStringMap::iterator it = m.begin(); it != m.end(); ++it) {
+ const VideoCaptureDeviceName device_name("dummy", "dummy", it->first);
+ EXPECT_EQ(it->second, device_name.GetCaptureApiTypeString());
+ }
+}
+#endif
+
+TEST_F(MediaInternalsVideoCaptureDeviceTest,
+ VideoCaptureFormatStringIsInExpectedFormat) {
+ // Since media internals will send video capture capabilities to JavaScript in
+ // an expected format and there are no public methods for accessing the
+ // resolutions, frame rates or pixel formats, this test checks that the format
+ // has not changed. If the test fails because of the changed format, it should
+ // be updated at the same time as the media internals JS files.
+ const float kFrameRate = 30.0f;
+ const gfx::Size kFrameSize(1280, 720);
+ const media::VideoPixelFormat kPixelFormat = media::PIXEL_FORMAT_I420;
+ const media::VideoCaptureFormat capture_format(
+ kFrameSize, kFrameRate, kPixelFormat);
+ const std::string expected_string =
+ base::StringPrintf("resolution: %s, fps: %f, pixel format: %s",
+ kFrameSize.ToString().c_str(),
+ kFrameRate,
+ media::VideoCaptureFormat::PixelFormatToString(
+ kPixelFormat).c_str());
+ EXPECT_EQ(expected_string, capture_format.ToString());
+}
+
+TEST_F(MediaInternalsVideoCaptureDeviceTest,
+ NotifyVideoCaptureDeviceCapabilitiesEnumerated) {
+ const int kWidth = 1280;
+ const int kHeight = 720;
+ const float kFrameRate = 30.0f;
+ const media::VideoPixelFormat kPixelFormat = media::PIXEL_FORMAT_I420;
+ const media::VideoCaptureFormat format_hd({kWidth, kHeight},
+ kFrameRate, kPixelFormat);
+ media::VideoCaptureFormats formats{};
+ formats.push_back(format_hd);
+ const media::VideoCaptureDeviceInfo device_info(
+#if defined(OS_MACOSX)
+ media::VideoCaptureDevice::Name("dummy", "dummy",
+ media::VideoCaptureDevice::Name::QTKIT),
+#elif defined(OS_WIN)
+ media::VideoCaptureDevice::Name("dummy", "dummy",
+ media::VideoCaptureDevice::Name::DIRECT_SHOW),
+#elif defined(OS_LINUX) || defined(OS_CHROMEOS)
+ media::VideoCaptureDevice::Name("dummy", "/dev/dummy"),
+#else
+ media::VideoCaptureDevice::Name("dummy", "dummy"),
+#endif
+ formats);
+ media::VideoCaptureDeviceInfos device_infos{};
+ device_infos.push_back(device_info);
+
+ // When updating video capture capabilities, the update will serialize
+ // a JSON array of objects to string. So here, the |UpdateCallbackImpl| will
+ // deserialize the first object in the array. This means we have to have
+ // exactly one device_info in the |device_infos|.
+ media_internals_->UpdateVideoCaptureDeviceCapabilities(device_infos);
+
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+ ExpectString("id", "/dev/dummy");
+#else
+ ExpectString("id", "dummy");
+#endif
+ ExpectString("name", "dummy");
+ base::ListValue expected_list;
+ expected_list.AppendString(format_hd.ToString());
+ ExpectListOfStrings("formats", expected_list);
+#if defined(OS_MACOSX)
+ ExpectString("captureApi", "QTKit");
+#elif defined(OS_WIN)
+ ExpectString("captureApi", "Direct Show");
+#endif
+}
+
+class MediaInternalsAudioLogTest
+ : public MediaInternalsTestBase,
+ public testing::TestWithParam<media::AudioLogFactory::AudioComponent> {
+ public:
+ MediaInternalsAudioLogTest() :
+ update_cb_(base::Bind(&MediaInternalsAudioLogTest::UpdateCallbackImpl,
+ base::Unretained(this))),
+ test_params_(media::AudioParameters::AUDIO_PCM_LINEAR,
+ media::CHANNEL_LAYOUT_MONO,
+ 48000,
+ 16,
+ 128,
+ media::AudioParameters::ECHO_CANCELLER |
+ media::AudioParameters::DUCKING),
+ test_component_(GetParam()),
+ audio_log_(media_internals_->CreateAudioLog(test_component_)) {
+ media_internals_->AddUpdateCallback(update_cb_);
+ }
+
+ virtual ~MediaInternalsAudioLogTest() {
+ media_internals_->RemoveUpdateCallback(update_cb_);
+ }
+
+ protected:
+ MediaInternals::UpdateCallback update_cb_;
const media::AudioParameters test_params_;
const media::AudioLogFactory::AudioComponent test_component_;
scoped_ptr<media::AudioLog> audio_log_;
};
-TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
- audio_log_->OnCreated(
- kTestComponentID, test_params_, kTestDeviceID);
+TEST_P(MediaInternalsAudioLogTest, AudioLogCreateStartStopErrorClose) {
+ audio_log_->OnCreated(kTestComponentID, test_params_, kTestDeviceID);
base::RunLoop().RunUntilIdle();
ExpectString("channel_layout",
@@ -97,7 +242,6 @@ TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
ExpectInt("sample_rate", test_params_.sample_rate());
ExpectInt("frames_per_buffer", test_params_.frames_per_buffer());
ExpectInt("channels", test_params_.channels());
- ExpectInt("input_channels", test_params_.input_channels());
ExpectString("effects", "ECHO_CANCELLER | DUCKING");
ExpectString("device_id", kTestDeviceID);
ExpectInt("component_id", kTestComponentID);
@@ -128,9 +272,8 @@ TEST_P(MediaInternalsTest, AudioLogCreateStartStopErrorClose) {
ExpectStatus("closed");
}
-TEST_P(MediaInternalsTest, AudioLogCreateClose) {
- audio_log_->OnCreated(
- kTestComponentID, test_params_, kTestDeviceID);
+TEST_P(MediaInternalsAudioLogTest, AudioLogCreateClose) {
+ audio_log_->OnCreated(kTestComponentID, test_params_, kTestDeviceID);
base::RunLoop().RunUntilIdle();
ExpectStatus("created");
@@ -140,7 +283,7 @@ TEST_P(MediaInternalsTest, AudioLogCreateClose) {
}
INSTANTIATE_TEST_CASE_P(
- MediaInternalsTest, MediaInternalsTest, testing::Values(
+ MediaInternalsAudioLogTest, MediaInternalsAudioLogTest, testing::Values(
media::AudioLogFactory::AUDIO_INPUT_CONTROLLER,
media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER,
media::AudioLogFactory::AUDIO_OUTPUT_STREAM));
diff --git a/chromium/content/browser/media/media_source_browsertest.cc b/chromium/content/browser/media/media_source_browsertest.cc
index d5d86154637..684b37d6505 100644
--- a/chromium/content/browser/media/media_source_browsertest.cc
+++ b/chromium/content/browser/media/media_source_browsertest.cc
@@ -32,22 +32,24 @@ static bool IsMSESupported() {
class MediaSourceTest : public content::MediaBrowserTest {
public:
- void TestSimplePlayback(const char* media_file, const char* media_type,
- const char* expectation) {
+ void TestSimplePlayback(const std::string& media_file,
+ const std::string& media_type,
+ const std::string& expectation) {
if (!IsMSESupported()) {
VLOG(0) << "Skipping test - MSE not supported.";
return;
}
- std::vector<StringPair> query_params;
- query_params.push_back(std::make_pair("mediafile", media_file));
- query_params.push_back(std::make_pair("mediatype", media_type));
- RunMediaTestPage("media_source_player.html", &query_params, expectation,
+ base::StringPairs query_params;
+ query_params.push_back(std::make_pair("mediaFile", media_file));
+ query_params.push_back(std::make_pair("mediaType", media_type));
+ query_params.push_back(std::make_pair("usePrefixedEME", "1"));
+ RunMediaTestPage("media_source_player.html", query_params, expectation,
true);
}
#if defined(OS_ANDROID)
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ virtual void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(
switches::kDisableGestureRequirementForMediaPlayback);
}
@@ -84,7 +86,9 @@ IN_PROC_BROWSER_TEST_F(MediaSourceTest, ConfigChangeVideo) {
VLOG(0) << "Skipping test - MSE not supported.";
return;
}
- RunMediaTestPage("mse_config_change.html", NULL, kEnded, true);
+ base::StringPairs query_params;
+ query_params.push_back(std::make_pair("usePrefixedEME", "1"));
+ RunMediaTestPage("mse_config_change.html", query_params, kEnded, true);
}
} // namespace content
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index 0214eb52f68..7f9e2b65564 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -7,7 +7,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "content/browser/media/cdm/browser_cdm_manager.h"
-#include "content/common/media/cdm_messages.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message_macros.h"
@@ -36,64 +36,31 @@ void MediaWebContentsObserver::RenderFrameDeleted(
#if defined(OS_ANDROID)
media_player_managers_.erase(key);
#endif
- cdm_managers_.erase(key);
+ // TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager
+ // and BrowserCdmManager all run on browser UI thread. So this call is okay.
+ // In the future we need to support the case where MediaWebContentsObserver
+ // get notified on browser UI thread, but BrowserMediaPlayerManager and
+ // BrowserCdmManager run on a different thread.
+ BrowserCdmManager* browser_cdm_manager =
+ BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID());
+ if (browser_cdm_manager)
+ browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID());
}
+#if defined(OS_ANDROID)
+
bool MediaWebContentsObserver::OnMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
-#if defined(OS_ANDROID)
- // Handles MediaPlayer messages first because MediaPlayers messages are much
- // more frequent than CDM messages.
if (OnMediaPlayerMessageReceived(msg, render_frame_host))
return true;
if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host))
return true;
-#endif // defined(OS_ANDROID)
-
- if (OnCdmMessageReceived(msg, render_frame_host))
- return true;
return false;
}
-bool MediaWebContentsObserver::OnCdmMessageReceived(
- const IPC::Message& msg,
- RenderFrameHost* render_frame_host) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg)
- IPC_MESSAGE_FORWARD(CdmHostMsg_InitializeCdm,
- GetCdmManager(render_frame_host),
- BrowserCdmManager::OnInitializeCdm)
- IPC_MESSAGE_FORWARD(CdmHostMsg_CreateSession,
- GetCdmManager(render_frame_host),
- BrowserCdmManager::OnCreateSession)
- IPC_MESSAGE_FORWARD(CdmHostMsg_UpdateSession,
- GetCdmManager(render_frame_host),
- BrowserCdmManager::OnUpdateSession)
- IPC_MESSAGE_FORWARD(CdmHostMsg_ReleaseSession,
- GetCdmManager(render_frame_host),
- BrowserCdmManager::OnReleaseSession)
- IPC_MESSAGE_FORWARD(CdmHostMsg_DestroyCdm,
- GetCdmManager(render_frame_host),
- BrowserCdmManager::OnDestroyCdm)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-BrowserCdmManager* MediaWebContentsObserver::GetCdmManager(
- RenderFrameHost* render_frame_host) {
- uintptr_t key = reinterpret_cast<uintptr_t>(render_frame_host);
- if (!cdm_managers_.contains(key)) {
- cdm_managers_.set(
- key, make_scoped_ptr(BrowserCdmManager::Create(render_frame_host)));
- }
- return cdm_managers_.get(key);
-}
-
-#if defined(OS_ANDROID)
bool MediaWebContentsObserver::OnMediaPlayerMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
@@ -129,6 +96,13 @@ bool MediaWebContentsObserver::OnMediaPlayerMessageReceived(
IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_DestroyMediaPlayer,
GetMediaPlayerManager(render_frame_host),
BrowserMediaPlayerManager::OnDestroyPlayer)
+ IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_RequestRemotePlayback,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnRequestRemotePlayback)
+ IPC_MESSAGE_FORWARD(
+ MediaPlayerHostMsg_RequestRemotePlaybackControl,
+ GetMediaPlayerManager(render_frame_host),
+ BrowserMediaPlayerManager::OnRequestRemotePlaybackControl)
#if defined(VIDEO_HOLE)
IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_NotifyExternalSurface,
GetMediaPlayerManager(render_frame_host),
@@ -161,7 +135,16 @@ void MediaWebContentsObserver::OnSetCdm(RenderFrameHost* render_frame_host,
return;
}
- media::BrowserCdm* cdm = GetCdmManager(render_frame_host)->GetCdm(cdm_id);
+ // MediaPlayerAndroid runs on the same thread as BrowserCdmManager.
+ BrowserCdmManager* browser_cdm_manager =
+ BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID());
+ if (!browser_cdm_manager) {
+ NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id;
+ return;
+ }
+
+ media::BrowserCdm* cdm =
+ browser_cdm_manager->GetCdm(render_frame_host->GetRoutingID(), cdm_id);
if (!cdm) {
NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id;
return;
@@ -183,14 +166,6 @@ BrowserMediaPlayerManager* MediaWebContentsObserver::GetMediaPlayerManager(
return media_player_managers_.get(key);
}
-void MediaWebContentsObserver::PauseVideo() {
- for (MediaPlayerManagerMap::iterator iter = media_player_managers_.begin();
- iter != media_player_managers_.end(); ++iter) {
- BrowserMediaPlayerManager* manager = iter->second;
- manager->PauseVideo();
- }
-}
-
#if defined(VIDEO_HOLE)
void MediaWebContentsObserver::OnFrameInfoUpdated() {
for (MediaPlayerManagerMap::iterator iter = media_player_managers_.begin();
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 8ed89932057..d79e1ce930e 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -13,9 +13,7 @@
namespace content {
class BrowserCdmManager;
-#if defined(OS_ANDROID)
class BrowserMediaPlayerManager;
-#endif // defined(OS_ANDROID)
class RenderViewHost;
// This class manages all RenderFrame based media related managers at the
@@ -28,20 +26,12 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
virtual ~MediaWebContentsObserver();
// WebContentsObserver implementations.
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host) OVERRIDE;
-
- // Helper function to handle CDM IPC messages. Returns whether the |message|
- // is handled in the function.
- bool OnCdmMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host);
-
- // Gets the CDM manager associated with |render_frame_host|. Creates
- // a new one if it doesn't exist. The caller doesn't own the returned pointer.
- BrowserCdmManager* GetCdmManager(RenderFrameHost* render_frame_host);
+ virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
#if defined(OS_ANDROID)
+ virtual bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) override;
+
// Helper functions to handle media player IPC messages. Returns whether the
// |message| is handled in the function.
bool OnMediaPlayerMessageReceived(const IPC::Message& message,
@@ -56,27 +46,18 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
void OnSetCdm(RenderFrameHost* render_frame_host, int player_id, int cdm_id);
- // Pauses all media player.
- void PauseVideo();
-
#if defined(VIDEO_HOLE)
void OnFrameInfoUpdated();
#endif // defined(VIDEO_HOLE)
-#endif // defined(OS_ANDROID)
-
private:
- // Map from RenderFrameHost* to BrowserCdmManager.
- typedef base::ScopedPtrHashMap<uintptr_t, BrowserCdmManager> CdmManagerMap;
- CdmManagerMap cdm_managers_;
-
-#if defined(OS_ANDROID)
// Map from RenderFrameHost* to BrowserMediaPlayerManager.
typedef base::ScopedPtrHashMap<uintptr_t, BrowserMediaPlayerManager>
MediaPlayerManagerMap;
MediaPlayerManagerMap media_player_managers_;
#endif // defined(OS_ANDROID)
+ private:
DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserver);
};
diff --git a/chromium/content/browser/media/midi_dispatcher_host.cc b/chromium/content/browser/media/midi_dispatcher_host.cc
index 9b6faa1c585..944dae51d8d 100644
--- a/chromium/content/browser/media/midi_dispatcher_host.cc
+++ b/chromium/content/browser/media/midi_dispatcher_host.cc
@@ -11,6 +11,7 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/navigation_details.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -38,6 +39,21 @@ MidiDispatcherHost::MidiDispatcherHost(WebContents* web_contents)
MidiDispatcherHost::~MidiDispatcherHost() {
}
+void MidiDispatcherHost::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ CancelPermissionRequestsForFrame(render_frame_host);
+}
+
+void MidiDispatcherHost::DidNavigateAnyFrame(
+ RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) {
+ if (details.is_in_page)
+ return;
+
+ CancelPermissionRequestsForFrame(render_frame_host);
+}
+
bool MidiDispatcherHost::OnMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host) {
bool handled = true;
@@ -45,8 +61,6 @@ bool MidiDispatcherHost::OnMessageReceived(const IPC::Message& message,
render_frame_host)
IPC_MESSAGE_HANDLER(MidiHostMsg_RequestSysExPermission,
OnRequestSysExPermission)
- IPC_MESSAGE_HANDLER(MidiHostMsg_CancelSysExPermissionRequest,
- OnCancelSysExPermissionRequest)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -64,30 +78,33 @@ void MidiDispatcherHost::OnRequestSysExPermission(
render_process_id, render_frame_id, bridge_id);
pending_permissions_.push_back(pending_permission);
- GetContentClient()->browser()->RequestMidiSysExPermission(
+ GetContentClient()->browser()->RequestPermission(
+ PERMISSION_MIDI_SYSEX,
web_contents(),
bridge_id,
origin,
user_gesture,
base::Bind(&MidiDispatcherHost::WasSysExPermissionGranted,
weak_factory_.GetWeakPtr(),
- render_process_id, render_frame_id, bridge_id),
- &pending_permissions_.back().cancel);
+ render_process_id,
+ render_frame_id,
+ bridge_id));
}
-void MidiDispatcherHost::OnCancelSysExPermissionRequest(
- RenderFrameHost* render_frame_host,
- int bridge_id,
- const GURL& requesting_frame) {
+void MidiDispatcherHost::CancelPermissionRequestsForFrame(
+ RenderFrameHost* render_frame_host) {
int render_process_id = render_frame_host->GetProcess()->GetID();
int render_frame_id = render_frame_host->GetRoutingID();
for (size_t i = 0; i < pending_permissions_.size(); ++i) {
if (pending_permissions_[i].render_process_id == render_process_id &&
- pending_permissions_[i].render_frame_id == render_frame_id &&
- pending_permissions_[i].bridge_id == bridge_id) {
- if (!pending_permissions_[i].cancel.is_null())
- pending_permissions_[i].cancel.Run();
+ pending_permissions_[i].render_frame_id == render_frame_id) {
+ GetContentClient()->browser()->CancelPermissionRequest(
+ PERMISSION_MIDI_SYSEX,
+ web_contents(),
+ pending_permissions_[i].bridge_id,
+ render_frame_host->GetLastCommittedURL());
+
pending_permissions_.erase(pending_permissions_.begin() + i);
return;
}
diff --git a/chromium/content/browser/media/midi_dispatcher_host.h b/chromium/content/browser/media/midi_dispatcher_host.h
index 87b7b1df776..a487178851d 100644
--- a/chromium/content/browser/media/midi_dispatcher_host.h
+++ b/chromium/content/browser/media/midi_dispatcher_host.h
@@ -19,11 +19,15 @@ class BrowserContext;
class MidiDispatcherHost : public WebContentsObserver {
public:
explicit MidiDispatcherHost(WebContents* web_contents);
- virtual ~MidiDispatcherHost();
+ ~MidiDispatcherHost() override;
// WebContentsObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host) OVERRIDE;
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+ void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override;
+ bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) override;
private:
void OnRequestSysExPermission(RenderFrameHost* render_frame_host,
@@ -37,6 +41,7 @@ class MidiDispatcherHost : public WebContentsObserver {
int render_frame_id,
int bridge_id,
bool is_allowed);
+ void CancelPermissionRequestsForFrame(RenderFrameHost* render_frame_host);
struct PendingPermission {
PendingPermission(int render_process_id,
@@ -46,7 +51,6 @@ class MidiDispatcherHost : public WebContentsObserver {
int render_process_id;
int render_frame_id;
int bridge_id;
- base::Closure cancel;
};
std::vector<PendingPermission> pending_permissions_;
diff --git a/chromium/content/browser/media/midi_host.cc b/chromium/content/browser/media/midi_host.cc
index 950cf48e0a9..2fc01478575 100644
--- a/chromium/content/browser/media/midi_host.cc
+++ b/chromium/content/browser/media/midi_host.cc
@@ -52,13 +52,16 @@ MidiHost::MidiHost(int renderer_process_id, media::MidiManager* midi_manager)
: BrowserMessageFilter(MidiMsgStart),
renderer_process_id_(renderer_process_id),
has_sys_ex_permission_(false),
+ is_session_requested_(false),
midi_manager_(midi_manager),
sent_bytes_in_flight_(0),
bytes_sent_since_last_acknowledgement_(0) {
+ CHECK(midi_manager_);
}
MidiHost::~MidiHost() {
- if (midi_manager_)
+ // Close an open session, or abort opening a session.
+ if (is_session_requested_)
midi_manager_->EndSession(this);
}
@@ -72,23 +75,21 @@ bool MidiHost::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(MidiHost, message)
IPC_MESSAGE_HANDLER(MidiHostMsg_StartSession, OnStartSession)
IPC_MESSAGE_HANDLER(MidiHostMsg_SendData, OnSendData)
+ IPC_MESSAGE_HANDLER(MidiHostMsg_EndSession, OnEndSession)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void MidiHost::OnStartSession(int client_id) {
- if (midi_manager_)
- midi_manager_->StartSession(this, client_id);
+void MidiHost::OnStartSession() {
+ is_session_requested_ = true;
+ midi_manager_->StartSession(this);
}
void MidiHost::OnSendData(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
- if (!midi_manager_)
- return;
-
if (data.empty())
return;
@@ -117,25 +118,31 @@ void MidiHost::OnSendData(uint32 port,
midi_manager_->DispatchSendMidiData(this, port, data, timestamp);
}
-void MidiHost::CompleteStartSession(int client_id, media::MidiResult result) {
- MidiPortInfoList input_ports;
- MidiPortInfoList output_ports;
+void MidiHost::OnEndSession() {
+ is_session_requested_ = false;
+ midi_manager_->EndSession(this);
+}
+void MidiHost::CompleteStartSession(media::MidiResult result) {
+ DCHECK(is_session_requested_);
if (result == media::MIDI_OK) {
- input_ports = midi_manager_->input_ports();
- output_ports = midi_manager_->output_ports();
- received_messages_queues_.clear();
- received_messages_queues_.resize(input_ports.size());
// ChildSecurityPolicy is set just before OnStartSession by
// MidiDispatcherHost. So we can safely cache the policy.
has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()->
CanSendMidiSysExMessage(renderer_process_id_);
}
+ Send(new MidiMsg_SessionStarted(result));
+}
+
+void MidiHost::AddInputPort(const media::MidiPortInfo& info) {
+ base::AutoLock auto_lock(messages_queues_lock_);
+ // MidiMessageQueue is created later in ReceiveMidiData().
+ received_messages_queues_.push_back(nullptr);
+ Send(new MidiMsg_AddInputPort(info));
+}
- Send(new MidiMsg_SessionStarted(client_id,
- result,
- input_ports,
- output_ports));
+void MidiHost::AddOutputPort(const media::MidiPortInfo& info) {
+ Send(new MidiMsg_AddOutputPort(info));
}
void MidiHost::ReceiveMidiData(
@@ -145,11 +152,12 @@ void MidiHost::ReceiveMidiData(
double timestamp) {
TRACE_EVENT0("midi", "MidiHost::ReceiveMidiData");
+ base::AutoLock auto_lock(messages_queues_lock_);
if (received_messages_queues_.size() <= port)
return;
// Lazy initialization
- if (received_messages_queues_[port] == NULL)
+ if (received_messages_queues_[port] == nullptr)
received_messages_queues_[port] = new media::MidiMessageQueue(true);
received_messages_queues_[port]->Add(data, length);
diff --git a/chromium/content/browser/media/midi_host.h b/chromium/content/browser/media/midi_host.h
index 8be45d8218f..3a469bf93b9 100644
--- a/chromium/content/browser/media/midi_host.h
+++ b/chromium/content/browser/media/midi_host.h
@@ -11,6 +11,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
@@ -31,32 +32,35 @@ class CONTENT_EXPORT MidiHost
MidiHost(int renderer_process_id, media::MidiManager* midi_manager);
// BrowserMessageFilter implementation.
- virtual void OnDestruct() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// MidiManagerClient implementation.
- virtual void CompleteStartSession(int client_id,
- media::MidiResult result) OVERRIDE;
- virtual void ReceiveMidiData(uint32 port,
- const uint8* data,
- size_t length,
- double timestamp) OVERRIDE;
- virtual void AccumulateMidiBytesSent(size_t n) OVERRIDE;
+ void CompleteStartSession(media::MidiResult result) override;
+ void AddInputPort(const media::MidiPortInfo& info) override;
+ void AddOutputPort(const media::MidiPortInfo& info) override;
+ void ReceiveMidiData(uint32 port,
+ const uint8* data,
+ size_t length,
+ double timestamp) override;
+ void AccumulateMidiBytesSent(size_t n) override;
// Start session to access MIDI hardware.
- void OnStartSession(int client_id);
+ void OnStartSession();
// Data to be sent to a MIDI output port.
void OnSendData(uint32 port,
const std::vector<uint8>& data,
double timestamp);
+ void OnEndSession();
+
private:
FRIEND_TEST_ALL_PREFIXES(MidiHostTest, IsValidWebMIDIData);
friend class base::DeleteHelper<MidiHost>;
friend class BrowserThread;
- virtual ~MidiHost();
+ ~MidiHost() override;
// Returns true if |data| fulfills the requirements of MidiOutput.send API
// defined in the WebMIDI spec.
@@ -71,6 +75,9 @@ class CONTENT_EXPORT MidiHost
// messages.
bool has_sys_ex_permission_;
+ // Represents if a session is requested to start.
+ bool is_session_requested_;
+
// |midi_manager_| talks to the platform-specific MIDI APIs.
// It can be NULL if the platform (or our current implementation)
// does not support MIDI. If not supported then a call to
@@ -81,6 +88,9 @@ class CONTENT_EXPORT MidiHost
// Buffers where data sent from each MIDI input port is stored.
ScopedVector<media::MidiMessageQueue> received_messages_queues_;
+ // Protects access to |received_messages_queues_|;
+ base::Lock messages_queues_lock_;
+
// The number of bytes sent to the platform-specific MIDI sending
// system, but not yet completed.
size_t sent_bytes_in_flight_;
diff --git a/chromium/content/browser/media/webrtc_aecdump_browsertest.cc b/chromium/content/browser/media/webrtc_aecdump_browsertest.cc
new file mode 100644
index 00000000000..bdeed59bea7
--- /dev/null
+++ b/chromium/content/browser/media/webrtc_aecdump_browsertest.cc
@@ -0,0 +1,233 @@
+// Copyright (c) 2014 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/process/process_handle.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/webrtc_content_browsertest_base.h"
+#include "media/audio/audio_manager.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace {
+
+const int kExpectedConsumerId = 0;
+
+// Get the ID for the render process host when there should only be one.
+bool GetRenderProcessHostId(base::ProcessId* id) {
+ content::RenderProcessHost::iterator it(
+ content::RenderProcessHost::AllHostsIterator());
+ *id = base::GetProcId(it.GetCurrentValue()->GetHandle());
+ EXPECT_NE(base::kNullProcessId, *id);
+ if (*id == base::kNullProcessId)
+ return false;
+ it.Advance();
+ EXPECT_TRUE(it.IsAtEnd());
+ return it.IsAtEnd();
+}
+
+} // namespace
+
+namespace content {
+
+class WebRtcAecDumpBrowserTest : public WebRtcContentBrowserTest {
+ public:
+ WebRtcAecDumpBrowserTest() {}
+ ~WebRtcAecDumpBrowserTest() override {}
+};
+
+#if defined(OS_WIN)
+#define IntToStringType base::IntToString16
+#else
+#define IntToStringType base::IntToString
+#endif
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+// Timing out on ARM linux bot: http://crbug.com/238490
+#define MAYBE_CallWithAecDump DISABLED_CallWithAecDump
+#elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
+// Renderer crashes under Android ASAN: https://crbug.com/408496.
+#define MAYBE_CallWithAecDump DISABLED_CallWithAecDump
+#else
+#define MAYBE_CallWithAecDump CallWithAecDump
+#endif
+
+// This tests will make a complete PeerConnection-based call, verify that
+// video is playing for the call, and verify that a non-empty AEC dump file
+// exists. The AEC dump is enabled through webrtc-internals. The HTML and
+// Javascript is bypassed since it would trigger a file picker dialog. Instead,
+// the dialog callback FileSelected() is invoked directly. In fact, there's
+// never a webrtc-internals page opened at all since that's not needed.
+IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest, MAYBE_CallWithAecDump) {
+ if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+ LOG(INFO) << "Missing output devices: skipping test...";
+ return;
+ }
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ // We must navigate somewhere first so that the render process is created.
+ NavigateToURL(shell(), GURL(""));
+
+ base::FilePath dump_file;
+ ASSERT_TRUE(CreateTemporaryFile(&dump_file));
+ base::DeleteFile(dump_file, false);
+
+ // This fakes the behavior of another open tab with webrtc-internals, and
+ // enabling AEC dump in that tab.
+ WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL);
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+ DisableOpusIfOnAndroid();
+ ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
+
+ EXPECT_FALSE(base::PathExists(dump_file));
+
+ // Add file extensions that we expect to be added. The dump name will be
+ // <temporary path>.<render process id>.<consumer id>, for example
+ // "/tmp/.com.google.Chrome.Z6UC3P.12345.0".
+ base::ProcessId render_process_id = base::kNullProcessId;
+ EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
+ dump_file = dump_file.AddExtension(IntToStringType(render_process_id))
+ .AddExtension(IntToStringType(kExpectedConsumerId));
+
+ EXPECT_TRUE(base::PathExists(dump_file));
+ int64 file_size = 0;
+ EXPECT_TRUE(base::GetFileSize(dump_file, &file_size));
+ EXPECT_GT(file_size, 0);
+
+ base::DeleteFile(dump_file, false);
+}
+
+// TODO(grunell): Add test for multiple dumps when re-use of
+// MediaStreamAudioProcessor in AudioCapturer has been removed.
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+// Timing out on ARM linux bot: http://crbug.com/238490
+#define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled
+#elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
+// Renderer crashes under Android ASAN: https://crbug.com/408496.
+#define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled
+#else
+#define MAYBE_CallWithAecDumpEnabledThenDisabled CallWithAecDumpEnabledThenDisabled
+#endif
+
+// As above, but enable and disable dump before starting a call. The file should
+// be created, but should be empty.
+IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest,
+ MAYBE_CallWithAecDumpEnabledThenDisabled) {
+ if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+ LOG(INFO) << "Missing output devices: skipping test...";
+ return;
+ }
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ // We must navigate somewhere first so that the render process is created.
+ NavigateToURL(shell(), GURL(""));
+
+ base::FilePath dump_file;
+ ASSERT_TRUE(CreateTemporaryFile(&dump_file));
+ base::DeleteFile(dump_file, false);
+
+ // This fakes the behavior of another open tab with webrtc-internals, and
+ // enabling AEC dump in that tab, then disabling it.
+ WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL);
+ WebRTCInternals::GetInstance()->DisableAecDump();
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+ NavigateToURL(shell(), url);
+ DisableOpusIfOnAndroid();
+ ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
+
+ // Add file extensions that we expect to be added.
+ base::ProcessId render_process_id = base::kNullProcessId;
+ EXPECT_TRUE(GetRenderProcessHostId(&render_process_id));
+ dump_file = dump_file.AddExtension(IntToStringType(render_process_id))
+ .AddExtension(IntToStringType(kExpectedConsumerId));
+
+ EXPECT_FALSE(base::PathExists(dump_file));
+
+ base::DeleteFile(dump_file, false);
+}
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+// Timing out on ARM linux bot: http://crbug.com/238490
+#define MAYBE_TwoCallsWithAecDump DISABLED_TwoCallsWithAecDump
+#elif defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
+// Renderer crashes under Android ASAN: https://crbug.com/408496.
+#define MAYBE_TwoCallsWithAecDump DISABLED_TwoCallsWithAecDump
+#else
+#define MAYBE_TwoCallsWithAecDump TwoCallsWithAecDump
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebRtcAecDumpBrowserTest, MAYBE_TwoCallsWithAecDump) {
+ if (OnWinXp()) {
+ // http://crbug.com/425034.
+ LOG(INFO) << "Disabled on Win XP: skipping test...";
+ return;
+ }
+ if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+ LOG(INFO) << "Missing output devices: skipping test...";
+ return;
+ }
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ // We must navigate somewhere first so that the render process is created.
+ NavigateToURL(shell(), GURL(""));
+
+ // Create a second window.
+ Shell* shell2 = CreateBrowser();
+ NavigateToURL(shell2, GURL(""));
+
+ base::FilePath dump_file;
+ ASSERT_TRUE(CreateTemporaryFile(&dump_file));
+ base::DeleteFile(dump_file, false);
+
+ // This fakes the behavior of another open tab with webrtc-internals, and
+ // enabling AEC dump in that tab.
+ WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL);
+
+ GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
+
+ NavigateToURL(shell(), url);
+ NavigateToURL(shell2, url);
+ ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell2->web_contents(),
+ "call({video: true, audio: true});",
+ &result));
+ ASSERT_STREQ("OK", result.c_str());
+
+ EXPECT_FALSE(base::PathExists(dump_file));
+
+ RenderProcessHost::iterator it =
+ content::RenderProcessHost::AllHostsIterator();
+ for (; !it.IsAtEnd(); it.Advance()) {
+ base::ProcessId render_process_id =
+ base::GetProcId(it.GetCurrentValue()->GetHandle());
+ EXPECT_NE(base::kNullProcessId, render_process_id);
+
+ // Add file extensions that we expect to be added.
+ base::FilePath unique_dump_file =
+ dump_file.AddExtension(IntToStringType(render_process_id))
+ .AddExtension(IntToStringType(kExpectedConsumerId));
+
+ EXPECT_TRUE(base::PathExists(unique_dump_file));
+ int64 file_size = 0;
+ EXPECT_TRUE(base::GetFileSize(unique_dump_file, &file_size));
+ EXPECT_GT(file_size, 0);
+
+ base::DeleteFile(unique_dump_file, false);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/webrtc_browsertest.cc b/chromium/content/browser/media/webrtc_browsertest.cc
index f5bb216ead0..45c3623550a 100644
--- a/chromium/content/browser/media/webrtc_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_browsertest.cc
@@ -3,50 +3,47 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/strings/string_number_conversions.h"
+#include "base/files/file_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"
-#include "base/values.h"
-#include "content/browser/media/webrtc_internals.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
#include "content/test/webrtc_content_browsertest_base.h"
#include "media/audio/audio_manager.h"
#include "media/base/media_switches.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
+namespace {
#if defined (OS_ANDROID) || defined(THREAD_SANITIZER)
// Just do the bare minimum of audio checking on Android and under TSAN since
// it's a bit sensitive to device performance.
-static const char kUseLenientAudioChecking[] = "true";
+const char kUseLenientAudioChecking[] = "true";
#else
-static const char kUseLenientAudioChecking[] = "false";
+const char kUseLenientAudioChecking[] = "false";
#endif
-namespace content {
+} // namespace
-class WebRtcBrowserTest : public WebRtcContentBrowserTest,
- public testing::WithParamInterface<bool> {
- public:
- WebRtcBrowserTest() {}
- virtual ~WebRtcBrowserTest() {}
+namespace content {
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- WebRtcContentBrowserTest::SetUpCommandLine(command_line);
+#if defined(OS_ANDROID) && defined(ADDRESS_SANITIZER)
+// Renderer crashes under Android ASAN: https://crbug.com/408496.
+#define MAYBE_WebRtcBrowserTest DISABLED_WebRtcBrowserTest
+#elif defined(OS_ANDROID) && defined(__aarch64__)
+// Failures on ARM64 Android: http://crbug.com/408179.
+#define MAYBE_WebRtcBrowserTest DISABLED_WebRtcBrowserTest
+#else
+#define MAYBE_WebRtcBrowserTest WebRtcBrowserTest
+#endif
- bool enable_audio_track_processing = GetParam();
- if (!enable_audio_track_processing)
- command_line->AppendSwitch(switches::kDisableAudioTrackProcessing);
- }
+class MAYBE_WebRtcBrowserTest : public WebRtcContentBrowserTest {
+ public:
+ MAYBE_WebRtcBrowserTest() {}
+ ~MAYBE_WebRtcBrowserTest() override {}
// Convenience function since most peerconnection-call.html tests just load
// the page, kick off some javascript and wait for the title to change to OK.
@@ -73,65 +70,100 @@ class WebRtcBrowserTest : public WebRtcContentBrowserTest,
return;
}
- ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
+ ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeDeviceForMediaStream))
<< "Must run with fake devices since the test will explicitly look "
<< "for the fake device signal.";
MakeTypicalPeerConnectionCall(javascript);
}
-
- void DisableOpusIfOnAndroid() {
-#if defined(OS_ANDROID)
- // Always force iSAC 16K on Android for now (Opus is broken).
- EXPECT_EQ("isac-forced",
- ExecuteJavascriptAndReturnResult("forceIsac16KInSdp();"));
-#endif
- }
};
-static const bool kRunTestsWithFlag[] = { false, true };
-INSTANTIATE_TEST_CASE_P(WebRtcBrowserTests,
- WebRtcBrowserTest,
- testing::ValuesIn(kRunTestsWithFlag));
-
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux bot: http://crbug.com/238490
#define MAYBE_CanSetupDefaultVideoCall DISABLED_CanSetupDefaultVideoCall
+// Flaky on TSAN v2. http://crbug.com/408006
+#elif defined(THREAD_SANITIZER)
+#define MAYBE_CanSetupDefaultVideoCall DISABLED_CanSetupDefaultVideoCall
#else
#define MAYBE_CanSetupDefaultVideoCall CanSetupDefaultVideoCall
#endif
// These tests will make a complete PeerConnection-based call and verify that
// video is playing for the call.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupDefaultVideoCall) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanSetupDefaultVideoCall) {
MakeTypicalPeerConnectionCall(
"callAndExpectResolution({video: true}, 640, 480);");
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CanSetupVideoCallWith1To1AspecRatio) {
+// Flaky on TSAN v2. http://crbug.com/408006
+#if defined(THREAD_SANITIZER)
+#define MAYBE_CanSetupVideoCallWith1To1AspectRatio \
+ DISABLED_CanSetupVideoCallWith1To1AspectRatio
+#else
+#define MAYBE_CanSetupVideoCallWith1To1AspectRatio \
+ CanSetupVideoCallWith1To1AspectRatio
+#endif
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanSetupVideoCallWith1To1AspectRatio) {
const std::string javascript =
"callAndExpectResolution({video: {mandatory: {minWidth: 320,"
" maxWidth: 320, minHeight: 320, maxHeight: 320}}}, 320, 320);";
MakeTypicalPeerConnectionCall(javascript);
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
- CanSetupVideoCallWith16To9AspecRatio) {
+#if defined(OS_ANDROID) && defined(ARCH_CPU_ARM64)
+// Failing on ARM64 Android bot: http://crbug.com/408179
+#define MAYBE_CanSetupVideoCallWith16To9AspectRatio \
+ DISABLED_CanSetupVideoCallWith16To9AspectRatio
+// Flaky on TSAN v2. http://crbug.com/408006
+#elif defined(THREAD_SANITIZER)
+#define MAYBE_CanSetupVideoCallWith16To9AspectRatio \
+ DISABLED_CanSetupVideoCallWith16To9AspectRatio
+#else
+#define MAYBE_CanSetupVideoCallWith16To9AspectRatio \
+ CanSetupVideoCallWith16To9AspectRatio
+#endif
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanSetupVideoCallWith16To9AspectRatio) {
const std::string javascript =
"callAndExpectResolution({video: {mandatory: {minWidth: 640,"
" maxWidth: 640, minAspectRatio: 1.777}}}, 640, 360);";
MakeTypicalPeerConnectionCall(javascript);
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
- CanSetupVideoCallWith4To3AspecRatio) {
+// Flaky on TSAN v2. http://crbug.com/408006
+#if defined(THREAD_SANITIZER)
+#define MAYBE_CanSetupVideoCallWith4To3AspectRatio \
+ DISABLED_CanSetupVideoCallWith4To3AspectRatio
+#else
+#define MAYBE_CanSetupVideoCallWith4To3AspectRatio \
+ CanSetupVideoCallWith4To3AspectRatio
+#endif
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanSetupVideoCallWith4To3AspectRatio) {
const std::string javascript =
"callAndExpectResolution({video: {mandatory: {minWidth: 960,"
"maxAspectRatio: 1.333}}}, 960, 720);";
MakeTypicalPeerConnectionCall(javascript);
}
+// Flaky on TSAN v2. http://crbug.com/408006
+#if defined(THREAD_SANITIZER)
+#define MAYBE_CanSetupVideoCallAndDisableLocalVideo \
+ DISABLED_CanSetupVideoCallAndDisableLocalVideo
+#else
+#define MAYBE_CanSetupVideoCallAndDisableLocalVideo \
+ CanSetupVideoCallAndDisableLocalVideo
+#endif
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanSetupVideoCallAndDisableLocalVideo) {
+ const std::string javascript =
+ "callAndDisableLocalVideo({video: true});";
+ MakeTypicalPeerConnectionCall(javascript);
+}
+
#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux, see http://crbug.com/240376
#define MAYBE_CanSetupAudioAndVideoCall DISABLED_CanSetupAudioAndVideoCall
@@ -139,18 +171,20 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
#define MAYBE_CanSetupAudioAndVideoCall CanSetupAudioAndVideoCall
#endif
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupAudioAndVideoCall) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanSetupAudioAndVideoCall) {
MakeTypicalPeerConnectionCall("call({video: true, audio: true});");
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MANUAL_CanSetupCallAndSendDtmf) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MANUAL_CanSetupCallAndSendDtmf) {
MakeTypicalPeerConnectionCall("callAndSendDtmf(\'123,abc\');");
}
// TODO(phoglund): this test fails because the peer connection state will be
// stable in the second negotiation round rather than have-local-offer.
// http://crbug.com/293125.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
DISABLED_CanMakeEmptyCallThenAddStreamsAndRenegotiate) {
const char* kJavascript =
"callEmptyThenAddOneStreamAndRenegotiate({video: true, audio: true});";
@@ -163,37 +197,33 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
// The stream sent from pc3 to pc4 is the stream received on pc1.
// The stream sent from pc4 to pc3 is cloned from stream the stream received
// on pc2.
-// Flaky on win xp. http://crbug.com/304775
-#if defined(OS_WIN)
+#if defined(THREAD_SANITIZER)
+// Flaky on TSAN v2. http://crbug.com/373637
#define MAYBE_CanForwardRemoteStream DISABLED_CanForwardRemoteStream
#define MAYBE_CanForwardRemoteStream720p DISABLED_CanForwardRemoteStream720p
#else
#define MAYBE_CanForwardRemoteStream CanForwardRemoteStream
-// Flaky on TSAN v2. http://crbug.com/373637
-#if defined(THREAD_SANITIZER)
-#define MAYBE_CanForwardRemoteStream720p DISABLED_CanForwardRemoteStream720p
-#else
#define MAYBE_CanForwardRemoteStream720p CanForwardRemoteStream720p
#endif
-#endif
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanForwardRemoteStream) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, MAYBE_CanForwardRemoteStream) {
#if defined (OS_ANDROID)
// This test fails on Nexus 5 devices.
// TODO(henrika): see http://crbug.com/362437 and http://crbug.com/359389
// for details.
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableWebRtcHWDecoding);
#endif
MakeTypicalPeerConnectionCall(
"callAndForwardRemoteStream({video: true, audio: false});");
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanForwardRemoteStream720p) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CanForwardRemoteStream720p) {
#if defined (OS_ANDROID)
// This test fails on Nexus 5 devices.
// TODO(henrika): see http://crbug.com/362437 and http://crbug.com/359389
// for details.
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kDisableWebRtcHWDecoding);
#endif
const std::string javascript = GenerateGetUserMediaCall(
@@ -201,6 +231,11 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanForwardRemoteStream720p) {
MakeTypicalPeerConnectionCall(javascript);
}
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ NoCrashWhenConnectChromiumSinkToRemoteTrack) {
+ MakeTypicalPeerConnectionCall("ConnectChromiumSinkToRemoteAudioTrack();");
+}
+
// This test will make a complete PeerConnection-based call but remove the
// MSID and bundle attribute from the initial offer to verify that
// video is playing for the call even if the initiating client don't support
@@ -213,26 +248,27 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanForwardRemoteStream720p) {
#define MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle\
CanSetupAudioAndVideoCallWithoutMsidAndBundle
#endif
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
MAYBE_CanSetupAudioAndVideoCallWithoutMsidAndBundle) {
MakeTypicalPeerConnectionCall("callWithoutMsidAndBundle();");
}
// This test will modify the SDP offer to an unsupported codec, which should
// cause SetLocalDescription to fail.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateUnsupportedVideoCodec) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ NegotiateUnsupportedVideoCodec) {
MakeTypicalPeerConnectionCall("negotiateUnsupportedVideoCodec();");
}
// This test will modify the SDP offer to use no encryption, which should
// cause SetLocalDescription to fail.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateNonCryptoCall) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, NegotiateNonCryptoCall) {
MakeTypicalPeerConnectionCall("negotiateNonCryptoCall();");
}
// This test can negotiate an SDP offer that includes a b=AS:xx to control
// the bandwidth for audio and video
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateOfferWithBLine) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, NegotiateOfferWithBLine) {
MakeTypicalPeerConnectionCall("negotiateOfferWithBLine();");
}
@@ -245,18 +281,24 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, NegotiateOfferWithBLine) {
#define MAYBE_CanSetupLegacyCall CanSetupLegacyCall
#endif
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupLegacyCall) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, MAYBE_CanSetupLegacyCall) {
MakeTypicalPeerConnectionCall("callWithLegacySdp();");
}
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel.
// TODO(mallinath) - Remove this test after rtp based data channel is disabled.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallWithDataOnly) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, CallWithDataOnly) {
MakeTypicalPeerConnectionCall("callWithDataOnly();");
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallWithSctpDataOnly) {
+#if defined(MEMORY_SANITIZER)
+// Fails under MemorySanitizer: http://crbug.com/405951
+#define MAYBE_CallWithSctpDataOnly DISABLED_CallWithSctpDataOnly
+#else
+#define MAYBE_CallWithSctpDataOnly CallWithSctpDataOnly
+#endif
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, MAYBE_CallWithSctpDataOnly) {
MakeTypicalPeerConnectionCall("callWithSctpDataOnly();");
}
@@ -270,19 +312,21 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallWithSctpDataOnly) {
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel and audio and video tracks.
// TODO(mallinath) - Remove this test after rtp based data channel is disabled.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, DISABLED_CallWithDataAndMedia) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, MAYBE_CallWithDataAndMedia) {
MakeTypicalPeerConnectionCall("callWithDataAndMedia();");
}
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS) && \
+ defined(ARCH_CPU_ARM_FAMILY)) || defined(MEMORY_SANITIZER)
// Timing out on ARM linux bot: http://crbug.com/238490
+// Fails under MemorySanitizer: http://crbug.com/405951
#define MAYBE_CallWithSctpDataAndMedia DISABLED_CallWithSctpDataAndMedia
#else
#define MAYBE_CallWithSctpDataAndMedia CallWithSctpDataAndMedia
#endif
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
MAYBE_CallWithSctpDataAndMedia) {
MakeTypicalPeerConnectionCall("callWithSctpDataAndMedia();");
}
@@ -297,7 +341,8 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
// This test will make a PeerConnection-based call and test an unreliable text
// dataChannel and later add an audio and video track.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithDataAndLaterAddMedia) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CallWithDataAndLaterAddMedia) {
MakeTypicalPeerConnectionCall("callWithDataAndLaterAddMedia();");
}
@@ -311,7 +356,8 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithDataAndLaterAddMedia) {
// This test will make a PeerConnection-based call and send a new Video
// MediaStream that has been created based on a MediaStream created with
// getUserMedia.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithNewVideoMediaStream) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ MAYBE_CallWithNewVideoMediaStream) {
MakeTypicalPeerConnectionCall("callWithNewVideoMediaStream();");
}
@@ -321,33 +367,55 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithNewVideoMediaStream) {
// AudioTrack is added instead.
// TODO(phoglund): This test is manual since not all buildbots has an audio
// input.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MANUAL_CallAndModifyStream) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, MANUAL_CallAndModifyStream) {
MakeTypicalPeerConnectionCall(
"callWithNewVideoMediaStreamLaterSwitchToAudio();");
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, AddTwoMediaStreamsToOnePC) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, AddTwoMediaStreamsToOnePC) {
MakeTypicalPeerConnectionCall("addTwoMediaStreamsToOneConnection();");
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
"callAndEnsureAudioIsPlaying(%s, {audio:true, video:true});",
kUseLenientAudioChecking));
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
"callAndEnsureAudioIsPlaying(%s, {audio:true});",
kUseLenientAudioChecking));
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
- EstablishAudioVideoCallAndVerifyMutingWorks) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ EstablishAudioVideoCallAndVerifyRemoteMutingWorks) {
MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
- "callAndEnsureAudioTrackMutingWorks(%s);", kUseLenientAudioChecking));
+ "callAndEnsureRemoteAudioTrackMutingWorks(%s);",
+ kUseLenientAudioChecking));
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ EstablishAudioVideoCallAndVerifyLocalMutingWorks) {
+ MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
+ "callAndEnsureLocalAudioTrackMutingWorks(%s);",
+ kUseLenientAudioChecking));
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ EnsureLocalVideoMuteDoesntMuteAudio) {
+ MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
+ "callAndEnsureLocalVideoMutingDoesntMuteAudio(%s);",
+ kUseLenientAudioChecking));
+}
+
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+ EnsureRemoteVideoMuteDoesntMuteAudio) {
+ MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
+ "callAndEnsureRemoteVideoMutingDoesntMuteAudio(%s);",
+ kUseLenientAudioChecking));
}
// Flaky on TSAN v2: http://crbug.com/373637
@@ -358,110 +426,18 @@ IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
#define MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks\
EstablishAudioVideoCallAndVerifyUnmutingWorks
#endif
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
MAYBE_EstablishAudioVideoCallAndVerifyUnmutingWorks) {
MakeAudioDetectingPeerConnectionCall(base::StringPrintf(
"callAndEnsureAudioTrackUnmutingWorks(%s);", kUseLenientAudioChecking));
}
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallAndVerifyVideoMutingWorks) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, CallAndVerifyVideoMutingWorks) {
MakeTypicalPeerConnectionCall("callAndEnsureVideoTrackMutingWorks();");
}
-#if defined(OS_WIN)
-#define IntToStringType base::IntToString16
-#else
-#define IntToStringType base::IntToString
-#endif
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
-// Timing out on ARM linux bot: http://crbug.com/238490
-#define MAYBE_CallWithAecDump DISABLED_CallWithAecDump
-#else
-#define MAYBE_CallWithAecDump CallWithAecDump
-#endif
-
-// This tests will make a complete PeerConnection-based call, verify that
-// video is playing for the call, and verify that a non-empty AEC dump file
-// exists. The AEC dump is enabled through webrtc-internals. The HTML and
-// Javascript is bypassed since it would trigger a file picker dialog. Instead,
-// the dialog callback FileSelected() is invoked directly. In fact, there's
-// never a webrtc-internals page opened at all since that's not needed.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CallWithAecDump) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
-
- // We must navigate somewhere first so that the render process is created.
- NavigateToURL(shell(), GURL(""));
-
- base::FilePath dump_file;
- ASSERT_TRUE(CreateTemporaryFile(&dump_file));
-
- // This fakes the behavior of another open tab with webrtc-internals, and
- // enabling AEC dump in that tab.
- WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL);
-
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
- NavigateToURL(shell(), url);
- DisableOpusIfOnAndroid();
- ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
-
- // Get the ID for the render process host. There should only be one.
- RenderProcessHost::iterator it(
- content::RenderProcessHost::AllHostsIterator());
- int render_process_host_id = it.GetCurrentValue()->GetID();
- EXPECT_GE(render_process_host_id, 0);
-
- // Add file extensions that we expect to be added.
- static const int kExpectedConsumerId = 0;
- dump_file = dump_file.AddExtension(IntToStringType(render_process_host_id))
- .AddExtension(IntToStringType(kExpectedConsumerId));
-
- EXPECT_TRUE(base::PathExists(dump_file));
- int64 file_size = 0;
- EXPECT_TRUE(base::GetFileSize(dump_file, &file_size));
- EXPECT_GT(file_size, 0);
-
- base::DeleteFile(dump_file, false);
-}
-
-// TODO(grunell): Add test for multiple dumps when re-use of
-// MediaStreamAudioProcessor in AudioCapturer has been removed.
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
-// Timing out on ARM linux bot: http://crbug.com/238490
-#define MAYBE_CallWithAecDumpEnabledThenDisabled DISABLED_CallWithAecDumpEnabledThenDisabled
-#else
-#define MAYBE_CallWithAecDumpEnabledThenDisabled CallWithAecDumpEnabledThenDisabled
-#endif
-
-// As above, but enable and disable dump before starting a call. The file should
-// be created, but should be empty.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
- MAYBE_CallWithAecDumpEnabledThenDisabled) {
- ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
-
- // We must navigate somewhere first so that the render process is created.
- NavigateToURL(shell(), GURL(""));
-
- base::FilePath dump_file;
- ASSERT_TRUE(CreateTemporaryFile(&dump_file));
-
- // This fakes the behavior of another open tab with webrtc-internals, and
- // enabling AEC dump in that tab, then disabling it.
- WebRTCInternals::GetInstance()->FileSelected(dump_file, -1, NULL);
- WebRTCInternals::GetInstance()->DisableAecDump();
-
- GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
- NavigateToURL(shell(), url);
- DisableOpusIfOnAndroid();
- ExecuteJavascriptAndWaitForOk("call({video: true, audio: true});");
-
- EXPECT_TRUE(base::PathExists(dump_file));
- int64 file_size = 0;
- EXPECT_TRUE(base::GetFileSize(dump_file, &file_size));
- EXPECT_EQ(0, file_size);
-
- base::DeleteFile(dump_file, false);
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest, CreateOfferWithOfferOptions) {
+ MakeTypicalPeerConnectionCall("testCreateOfferOptions();");
}
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/media/webrtc_getusermedia_browsertest.cc
index c7e1b4214e5..8c8bf2dba09 100644
--- a/chromium/content/browser/media/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_getusermedia_browsertest.cc
@@ -75,32 +75,26 @@ std::string GenerateGetUserMediaWithOptionalSourceID(
namespace content {
-class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest,
- public testing::WithParamInterface<bool> {
+class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest {
public:
WebRtcGetUserMediaBrowserTest() : trace_log_(NULL) {}
- virtual ~WebRtcGetUserMediaBrowserTest() {}
-
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- WebRtcContentBrowserTest::SetUpCommandLine(command_line);
-
- bool enable_audio_track_processing = GetParam();
- if (!enable_audio_track_processing)
- command_line->AppendSwitch(switches::kDisableAudioTrackProcessing);
- }
+ ~WebRtcGetUserMediaBrowserTest() override {}
void StartTracing() {
CHECK(trace_log_ == NULL) << "Can only can start tracing once";
trace_log_ = base::debug::TraceLog::GetInstance();
+ base::debug::TraceOptions trace_options(base::debug::RECORD_UNTIL_FULL);
+ trace_options.enable_sampling = true;
trace_log_->SetEnabled(base::debug::CategoryFilter("video"),
base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceLog::ENABLE_SAMPLING);
+ trace_options);
// Check that we are indeed recording.
EXPECT_EQ(trace_log_->GetNumTracesRecorded(), 1);
}
void StopTracing() {
- CHECK(message_loop_runner_ == NULL) << "Calling StopTracing more than once";
+ CHECK(message_loop_runner_.get() == NULL)
+ << "Calling StopTracing more than once";
trace_log_->SetDisabled();
message_loop_runner_ = new MessageLoopRunner;
trace_log_->Flush(base::Bind(
@@ -132,15 +126,15 @@ class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest,
// Put getUserMedia to work and let it run for a couple of seconds.
DCHECK(time_to_sample_secs);
ExecuteJavascriptAndWaitForOk(
- base::StringPrintf("%s({video: true});",
+ base::StringPrintf("%s({video: true}, 'myStreamName');",
kGetUserMediaAndGetStreamUp));
// Now the stream is up and running, start collecting traces.
StartTracing();
- // Let the stream run for a while in javascript.
ExecuteJavascriptAndWaitForOk(
- base::StringPrintf("waitAndStopVideoTrack(%d);", time_to_sample_secs));
+ base::StringPrintf("waitAndStopVideoTrack(window['myStreamName'], %d);",
+ time_to_sample_secs));
// Wait until the page title changes to "OK". Do not sleep() here since that
// would stop both this code and the browser underneath.
@@ -177,6 +171,7 @@ class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest,
graph_name, "", "interarrival_time", interarrival_us, "us", true);
}
+ // Runs the JavaScript twoGetUserMedia with |constraints1| and |constraint2|.
void RunTwoGetTwoGetUserMediaWithDifferentContraints(
const std::string& constraints1,
const std::string& constraints2,
@@ -241,15 +236,10 @@ class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest,
scoped_refptr<MessageLoopRunner> message_loop_runner_;
};
-static const bool kRunTestsWithFlag[] = { false, true };
-INSTANTIATE_TEST_CASE_P(WebRtcGetUserMediaBrowserTests,
- WebRtcGetUserMediaBrowserTest,
- testing::ValuesIn(kRunTestsWithFlag));
-
// These tests will all make a getUserMedia call with different constraints and
// see that the success callback is called. If the error callback is called or
// none of the callbacks are called the tests will simply time out and fail.
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, GetVideoStreamAndStop) {
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetVideoStreamAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -259,7 +249,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, GetVideoStreamAndStop) {
base::StringPrintf("%s({video: true});", kGetUserMediaAndStop));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
RenderSameTrackMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -271,7 +261,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
kRenderSameTrackMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
RenderClonedMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -284,7 +274,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
kRenderClonedMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kRenderClonedTrackMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -296,7 +286,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
kRenderClonedTrackMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
kRenderDuplicatedMediastreamAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -308,7 +298,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
kRenderDuplicatedMediastreamAndStop));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
GetAudioAndVideoStreamAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -319,7 +309,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
"%s({video: true, audio: true});", kGetUserMediaAndStop));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
GetAudioAndVideoStreamAndClone) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -329,7 +319,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
ExecuteJavascriptAndWaitForOk("getUserMediaAndClone();");
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
RenderVideoTrackInMultipleTagsAndPause) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -341,7 +331,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithMandatorySourceID) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -366,7 +356,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
}
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithInvalidMandatorySourceID) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -399,7 +389,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
video_ids[0])));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithInvalidOptionalSourceID) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -432,7 +422,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
video_ids[0])));
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) {
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -442,7 +432,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest, TwoGetUserMediaAndStop) {
"twoGetUserMediaAndStop({video: true, audio: true});");
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
TwoGetUserMediaWithEqualConstraints) {
std::string constraints1 = "{video: true, audio: true}";
const std::string& constraints2 = constraints1;
@@ -452,7 +442,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
TwoGetUserMediaWithSecondVideoCropped) {
std::string constraints1 = "{video: true}";
std::string constraints2 = "{video: {mandatory: {maxHeight: 360}}}";
@@ -461,7 +451,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
TwoGetUserMediaWithFirstHdSecondVga) {
std::string constraints1 =
"{video: {mandatory: {minWidth:1280 , minHeight: 720}}}";
@@ -472,7 +462,26 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
expected_result);
}
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ TwoGetUserMediaAndVerifyFrameRate) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ std::string constraints1 =
+ "{video: {mandatory: {minWidth:640 , minHeight: 480, "
+ "minFrameRate : 15, maxFrameRate : 15}}}";
+ std::string constraints2 =
+ "{video: {mandatory: {maxWidth:320 , maxHeight: 240,"
+ "minFrameRate : 7, maxFrameRate : 7}}}";
+
+ std::string command = "twoGetUserMediaAndVerifyFrameRate(" +
+ constraints1 + ',' + constraints2 + ", 15, 7)";
+ ExecuteJavascriptAndWaitForOk(command);
+}
+
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
GetUserMediaWithTooHighVideoConstraintsValues) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -488,15 +497,45 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
large_value);
NavigateToURL(shell(), url);
- // TODO(perkj): A proper error code should be returned by gUM.
- EXPECT_EQ("TrackStartError", ExecuteJavascriptAndReturnResult(call));
+ EXPECT_EQ("ConstraintNotSatisfiedError",
+ ExecuteJavascriptAndReturnResult(call));
+}
+
+// This test makes two getUserMedia requests, one with impossible constraints
+// that should trigger an error, and one with valid constraints. The test
+// verifies getUserMedia can succeed after being given impossible constraints.
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
+ TwoGetUserMediaAndCheckCallbackAfterFailure) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+ NavigateToURL(shell(), url);
+
+ int large_value = 99999;
+ const std::string gum_with_impossible_constraints =
+ GenerateGetUserMediaCall(kGetUserMediaAndExpectFailure,
+ large_value,
+ large_value,
+ large_value,
+ large_value,
+ large_value,
+ large_value);
+ const std::string gum_with_vga_constraints =
+ GenerateGetUserMediaCall(kGetUserMediaAndAnalyseAndStop,
+ 640, 640, 480, 480, 10, 30);
+
+ ASSERT_EQ("ConstraintNotSatisfiedError",
+ ExecuteJavascriptAndReturnResult(gum_with_impossible_constraints));
+
+ ASSERT_EQ("w=640:h=480",
+ ExecuteJavascriptAndReturnResult(gum_with_vga_constraints));
}
// This test will make a simple getUserMedia page, verify that video is playing
// in a simple local <video>, and for a couple of seconds, collect some
// performance traces from VideoCaptureController colorspace conversion and
// potential resizing.
-IN_PROC_BROWSER_TEST_P(
+IN_PROC_BROWSER_TEST_F(
WebRtcGetUserMediaBrowserTest,
TraceVideoCaptureControllerPerformanceDuringGetUserMedia) {
RunGetUserMediaAndCollectMeasures(
@@ -506,7 +545,7 @@ IN_PROC_BROWSER_TEST_P(
}
// This test calls getUserMedia and checks for aspect ratio behavior.
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
TestGetUserMediaAspectRatio4To3) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -521,7 +560,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
}
// This test calls getUserMedia and checks for aspect ratio behavior.
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
TestGetUserMediaAspectRatio16To9) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
@@ -536,7 +575,7 @@ IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
}
// This test calls getUserMedia and checks for aspect ratio behavior.
-IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest,
TestGetUserMediaAspectRatio1To1) {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
diff --git a/chromium/content/browser/media/webrtc_identity_store.cc b/chromium/content/browser/media/webrtc_identity_store.cc
index 4a02b71efa0..419cb96ab7c 100644
--- a/chromium/content/browser/media/webrtc_identity_store.cc
+++ b/chromium/content/browser/media/webrtc_identity_store.cc
@@ -171,7 +171,7 @@ class WebRTCIdentityRequestHandle {
};
WebRTCIdentityStore::WebRTCIdentityStore(const base::FilePath& path,
- quota::SpecialStoragePolicy* policy)
+ storage::SpecialStoragePolicy* policy)
: validity_period_(base::TimeDelta::FromDays(30)),
task_runner_(base::WorkerPool::GetTaskRunner(true)),
backend_(new WebRTCIdentityStoreBackend(path, policy, validity_period_)) {
diff --git a/chromium/content/browser/media/webrtc_identity_store.h b/chromium/content/browser/media/webrtc_identity_store.h
index 3602b7028cd..6bf10fe61a2 100644
--- a/chromium/content/browser/media/webrtc_identity_store.h
+++ b/chromium/content/browser/media/webrtc_identity_store.h
@@ -19,9 +19,9 @@ class FilePath;
class TaskRunner;
} // namespace base
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
-} // namespace quota
+} // namespace storage
namespace content {
class WebRTCIdentityRequest;
@@ -43,7 +43,7 @@ class CONTENT_EXPORT WebRTCIdentityStore
// If |path| is empty, nothing will be saved to disk.
WebRTCIdentityStore(const base::FilePath& path,
- quota::SpecialStoragePolicy* policy);
+ storage::SpecialStoragePolicy* policy);
// Retrieve the cached DTLS private key and certificate, i.e. identity, for
// the |origin| and |identity_name| pair, or generate a new identity using
diff --git a/chromium/content/browser/media/webrtc_identity_store_backend.cc b/chromium/content/browser/media/webrtc_identity_store_backend.cc
index 57a0b04f058..f6ecbad5c20 100644
--- a/chromium/content/browser/media/webrtc_identity_store_backend.cc
+++ b/chromium/content/browser/media/webrtc_identity_store_backend.cc
@@ -4,8 +4,8 @@
#include "content/browser/media/webrtc_identity_store_backend.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string_util.h"
#include "content/public/browser/browser_thread.h"
@@ -13,12 +13,12 @@
#include "sql/error_delegate_util.h"
#include "sql/statement.h"
#include "sql/transaction.h"
+#include "storage/browser/quota/special_storage_policy.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/special_storage_policy.h"
namespace content {
-static const char* kWebRTCIdentityStoreDBName = "webrtc_identity_store";
+static const char kWebRTCIdentityStoreDBName[] = "webrtc_identity_store";
static const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] =
FILE_PATH_LITERAL("WebRTCIdentityStore");
@@ -112,7 +112,7 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
public:
SqlLiteStorage(base::TimeDelta validity_period,
const base::FilePath& path,
- quota::SpecialStoragePolicy* policy)
+ storage::SpecialStoragePolicy* policy)
: validity_period_(validity_period), special_storage_policy_(policy) {
if (!path.empty())
path_ = path.Append(kWebRTCIdentityStoreDirectory);
@@ -169,7 +169,7 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
base::TimeDelta validity_period_;
// The file path of the DB. Empty if temporary.
base::FilePath path_;
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
scoped_ptr<sql::Connection> db_;
// Batched DB operations pending to commit.
PendingOperationList pending_operations_;
@@ -179,11 +179,12 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
WebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
const base::FilePath& path,
- quota::SpecialStoragePolicy* policy,
+ storage::SpecialStoragePolicy* policy,
base::TimeDelta validity_period)
: validity_period_(validity_period),
state_(NOT_STARTED),
- sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) {}
+ sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) {
+}
bool WebRTCIdentityStoreBackend::FindIdentity(
const GURL& origin,
diff --git a/chromium/content/browser/media/webrtc_identity_store_backend.h b/chromium/content/browser/media/webrtc_identity_store_backend.h
index 92b68b62d67..81919746741 100644
--- a/chromium/content/browser/media/webrtc_identity_store_backend.h
+++ b/chromium/content/browser/media/webrtc_identity_store_backend.h
@@ -18,9 +18,9 @@ namespace base {
class FilePath;
} // namespace base
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
-} // namespace quota
+} // namespace storage
namespace content {
@@ -38,7 +38,7 @@ class WebRTCIdentityStoreBackend
// No data is saved on disk if |path| is empty. Identites older than
// |validity_period| will be removed lazily.
WebRTCIdentityStoreBackend(const base::FilePath& path,
- quota::SpecialStoragePolicy* policy,
+ storage::SpecialStoragePolicy* policy,
base::TimeDelta validity_period);
// Finds the identity with |origin|, |identity_name|, and |common_name| from
diff --git a/chromium/content/browser/media/webrtc_identity_store_unittest.cc b/chromium/content/browser/media/webrtc_identity_store_unittest.cc
index 586559f2c05..9078f1a19ac 100644
--- a/chromium/content/browser/media/webrtc_identity_store_unittest.cc
+++ b/chromium/content/browser/media/webrtc_identity_store_unittest.cc
@@ -17,11 +17,11 @@
namespace content {
-static const char* kFakeOrigin = "http://foo.com";
-static const char* kFakeIdentityName1 = "name1";
-static const char* kFakeIdentityName2 = "name2";
-static const char* kFakeCommonName1 = "cname1";
-static const char* kFakeCommonName2 = "cname2";
+static const char kFakeOrigin[] = "http://foo.com";
+static const char kFakeIdentityName1[] = "name1";
+static const char kFakeIdentityName2[] = "name2";
+static const char kFakeCommonName1[] = "cname1";
+static const char kFakeCommonName2[] = "cname2";
static void OnRequestCompleted(bool* completed,
std::string* out_cert,
@@ -49,9 +49,7 @@ class WebRTCIdentityStoreTest : public testing::Test {
webrtc_identity_store_->SetTaskRunnerForTesting(pool_owner_->pool());
}
- virtual ~WebRTCIdentityStoreTest() {
- pool_owner_->pool()->Shutdown();
- }
+ ~WebRTCIdentityStoreTest() override { pool_owner_->pool()->Shutdown(); }
void SetValidityPeriod(base::TimeDelta validity_period) {
webrtc_identity_store_->SetValidityPeriodForTesting(validity_period);
diff --git a/chromium/content/browser/media/webrtc_internals.cc b/chromium/content/browser/media/webrtc_internals.cc
index 892f0378d2e..56078a109ef 100644
--- a/chromium/content/browser/media/webrtc_internals.cc
+++ b/chromium/content/browser/media/webrtc_internals.cc
@@ -4,13 +4,14 @@
#include "content/browser/media/webrtc_internals.h"
-#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
#include "content/browser/media/webrtc_internals_ui_observer.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/power_save_blocker.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -20,6 +21,10 @@ using std::string;
namespace content {
namespace {
+
+static base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals =
+ LAZY_INSTANCE_INITIALIZER;
+
// Makes sure that |dict| has a ListValue under path "log".
static base::ListValue* EnsureLogList(base::DictionaryValue* dict) {
base::ListValue* log = NULL;
@@ -59,14 +64,14 @@ WebRTCInternals::~WebRTCInternals() {
}
WebRTCInternals* WebRTCInternals::GetInstance() {
- return Singleton<WebRTCInternals>::get();
+ return g_webrtc_internals.Pointer();
}
void WebRTCInternals::OnAddPeerConnection(int render_process_id,
ProcessId pid,
int lid,
const string& url,
- const string& servers,
+ const string& rtc_configuration,
const string& constraints) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -77,10 +82,11 @@ void WebRTCInternals::OnAddPeerConnection(int render_process_id,
dict->SetInteger("rid", render_process_id);
dict->SetInteger("pid", static_cast<int>(pid));
dict->SetInteger("lid", lid);
- dict->SetString("servers", servers);
+ dict->SetString("rtcConfiguration", rtc_configuration);
dict->SetString("constraints", constraints);
dict->SetString("url", url);
peer_connection_data_.Append(dict);
+ CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers())
SendUpdate("addPeerConnection", dict);
@@ -101,6 +107,7 @@ void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
continue;
peer_connection_data_.Remove(i, NULL);
+ CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers()) {
base::DictionaryValue id;
@@ -136,6 +143,9 @@ void WebRTCInternals::OnUpdatePeerConnection(
if (!log_entry)
return;
+ double epoch_time = base::Time::Now().ToJsTime();
+ string time = base::DoubleToString(epoch_time);
+ log_entry->SetString("time", time);
log_entry->SetString("type", type);
log_entry->SetString("value", value);
log->Append(log_entry);
@@ -144,8 +154,7 @@ void WebRTCInternals::OnUpdatePeerConnection(
base::DictionaryValue update;
update.SetInteger("pid", static_cast<int>(pid));
update.SetInteger("lid", lid);
- update.SetString("type", type);
- update.SetString("value", value);
+ update.MergeDictionary(log_entry);
SendUpdate("updatePeerConnection", &update);
}
@@ -260,6 +269,7 @@ void WebRTCInternals::ResetForTesting() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
observers_.Clear();
peer_connection_data_.Clear();
+ CreateOrReleasePowerSaveBlocker();
get_user_media_requests_.Clear();
aec_dump_enabled_ = false;
}
@@ -296,6 +306,8 @@ void WebRTCInternals::FileSelectionCanceled(void* params) {
}
void WebRTCInternals::OnRendererExit(int render_process_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
// Iterates from the end of the list to remove the PeerConnections created
// by the exitting renderer.
for (int i = peer_connection_data_.GetSize() - 1; i >= 0; --i) {
@@ -319,6 +331,7 @@ void WebRTCInternals::OnRendererExit(int render_process_id) {
peer_connection_data_.Remove(i, NULL);
}
}
+ CreateOrReleasePowerSaveBlocker();
bool found_any = false;
// Iterates from the end of the list to remove the getUserMedia requests
@@ -354,4 +367,20 @@ void WebRTCInternals::EnableAecDumpOnAllRenderProcessHosts() {
}
#endif
+void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ if (peer_connection_data_.empty() && power_save_blocker_) {
+ DVLOG(1) << ("Releasing the block on application suspension since no "
+ "PeerConnections are active anymore.");
+ power_save_blocker_.reset();
+ } else if (!peer_connection_data_.empty() && !power_save_blocker_) {
+ DVLOG(1) << ("Preventing the application from being suspended while one or "
+ "more PeerConnections are active.");
+ power_save_blocker_ = content::PowerSaveBlocker::Create(
+ content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ "WebRTC has active PeerConnections.").Pass();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_internals.h b/chromium/content/browser/media/webrtc_internals.h
index 7ff95b9bca9..db8693ab3eb 100644
--- a/chromium/content/browser/media/webrtc_internals.h
+++ b/chromium/content/browser/media/webrtc_internals.h
@@ -6,7 +6,8 @@
#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_
#include "base/gtest_prod_util.h"
-#include "base/memory/singleton.h"
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/values.h"
@@ -16,6 +17,8 @@
#include "ui/shell_dialogs/select_file_dialog.h"
namespace content {
+
+class PowerSaveBlocker;
class WebContents;
class WebRTCInternalsUIObserver;
@@ -34,13 +37,14 @@ class CONTENT_EXPORT WebRTCInternals : public NotificationObserver,
// render process terminates and we want to clean up.
// |pid| is the renderer process id, |lid| is the renderer local id used to
// identify a PeerConnection, |url| is the url of the tab owning the
- // PeerConnection, |servers| is the servers configuration, |constraints| is
- // the media constraints used to initialize the PeerConnection.
+ // PeerConnection, |rtc_configuration| is the serialized RTCConfiguration,
+ // |constraints| is the media constraints used to initialize the
+ // PeerConnection.
void OnAddPeerConnection(int render_process_id,
base::ProcessId pid,
int lid,
const std::string& url,
- const std::string& servers,
+ const std::string& rtc_configuration,
const std::string& constraints);
// This method is called when PeerConnection is destroyed.
@@ -98,28 +102,29 @@ class CONTENT_EXPORT WebRTCInternals : public NotificationObserver,
void ResetForTesting();
private:
- friend struct DefaultSingletonTraits<WebRTCInternals>;
- FRIEND_TEST_ALL_PREFIXES(WebRtcBrowserTest, CallWithAecDump);
- FRIEND_TEST_ALL_PREFIXES(WebRtcBrowserTest,
+ friend struct base::DefaultLazyInstanceTraits<WebRTCInternals>;
+ FRIEND_TEST_ALL_PREFIXES(WebRtcAecDumpBrowserTest, CallWithAecDump);
+ FRIEND_TEST_ALL_PREFIXES(WebRtcAecDumpBrowserTest,
CallWithAecDumpEnabledThenDisabled);
+ FRIEND_TEST_ALL_PREFIXES(WebRtcAecDumpBrowserTest, TwoCallsWithAecDump);
FRIEND_TEST_ALL_PREFIXES(WebRTCInternalsTest,
AecRecordingFileSelectionCanceled);
WebRTCInternals();
- virtual ~WebRTCInternals();
+ ~WebRTCInternals() override;
void SendUpdate(const std::string& command, base::Value* value);
// NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
// ui::SelectFileDialog::Listener implementation.
- virtual void FileSelected(const base::FilePath& path,
- int index,
- void* unused_params) OVERRIDE;
- virtual void FileSelectionCanceled(void* params) OVERRIDE;
+ void FileSelected(const base::FilePath& path,
+ int index,
+ void* unused_params) override;
+ void FileSelectionCanceled(void* params) override;
// Called when a renderer exits (including crashes).
void OnRendererExit(int render_process_id);
@@ -129,6 +134,11 @@ class CONTENT_EXPORT WebRTCInternals : public NotificationObserver,
void EnableAecDumpOnAllRenderProcessHosts();
#endif
+ // Called whenever an element is added to or removed from
+ // |peer_connection_data_| to impose/release a block on suspending the current
+ // application for power-saving.
+ void CreateOrReleasePowerSaveBlocker();
+
ObserverList<WebRTCInternalsUIObserver> observers_;
// |peer_connection_data_| is a list containing all the PeerConnection
@@ -142,8 +152,9 @@ class CONTENT_EXPORT WebRTCInternals : public NotificationObserver,
// "servers" and "constraints" -- server configuration and media constraints
// used to initialize the PeerConnection respectively.
// "log" -- a ListValue contains all the updates for the PeerConnection. Each
- // list item is a DictionaryValue containing "type" and "value", both of which
- // are strings.
+ // list item is a DictionaryValue containing "time", which is the number of
+ // milliseconds since epoch as a string, and "type" and "value", both of which
+ // are strings representing the event.
base::ListValue peer_connection_data_;
// A list of getUserMedia requests. Each item is a DictionaryValue that
@@ -163,6 +174,11 @@ class CONTENT_EXPORT WebRTCInternals : public NotificationObserver,
// AEC dump (diagnostic echo canceller recording) state.
bool aec_dump_enabled_;
base::FilePath aec_dump_file_path_;
+
+ // While |peer_connection_data_| is non-empty, hold an instance of
+ // PowerSaveBlocker. This prevents the application from being suspended while
+ // remoting.
+ scoped_ptr<PowerSaveBlocker> power_save_blocker_;
};
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_internals_browsertest.cc b/chromium/content/browser/media/webrtc_internals_browsertest.cc
index 7b352d66b24..e9f1e611407 100644
--- a/chromium/content/browser/media/webrtc_internals_browsertest.cc
+++ b/chromium/content/browser/media/webrtc_internals_browsertest.cc
@@ -149,15 +149,14 @@ static const int64 FAKE_TIME_STAMP = 3600000;
class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
public:
MAYBE_WebRtcInternalsBrowserTest() {}
- virtual ~MAYBE_WebRtcInternalsBrowserTest() {}
+ ~MAYBE_WebRtcInternalsBrowserTest() override {}
- virtual void SetUpOnMainThread() OVERRIDE {
- // We need fake devices in this test since we want to run on naked VMs. We
- // assume these switches are set by default in content_browsertests.
- ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeDeviceForMediaStream));
+ void SetUpOnMainThread() override {
+ // Assume this is set by the content test launcher.
ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseFakeUIForMediaStream));
+ ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream));
}
protected:
@@ -175,7 +174,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
void ExecuteAddPeerConnectionJs(const PeerConnectionEntry& pc) {
std::stringstream ss;
ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ << ", " <<
- "url:'u', servers:'s', constraints:'c'}";
+ "url:'u', rtcConfiguration:'s', constraints:'c'}";
ASSERT_TRUE(ExecuteJavascript("addPeerConnection(" + ss.str() + ");"));
}
@@ -232,7 +231,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
ASSERT_TRUE(ExecuteScriptAndExtractString(
shell()->web_contents(),
"window.domAutomationController.send("
- "JSON.stringify(userMediaRequests));",
+ "JSON.stringify(userMediaRequests));",
&json_requests));
scoped_ptr<base::Value> value_requests;
value_requests.reset(base::JSONReader::Read(json_requests));
@@ -259,6 +258,24 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
EXPECT_EQ(requests[i].audio_constraints, audio);
EXPECT_EQ(requests[i].video_constraints, video);
}
+
+ bool user_media_tab_existed = false;
+ ASSERT_TRUE(ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "window.domAutomationController.send("
+ "$('user-media-tab-id') != null);",
+ &user_media_tab_existed));
+ EXPECT_EQ(!requests.empty(), user_media_tab_existed);
+
+ if (user_media_tab_existed) {
+ int user_media_request_count = -1;
+ ASSERT_TRUE(ExecuteScriptAndExtractInt(
+ shell()->web_contents(),
+ "window.domAutomationController.send("
+ "$('user-media-tab-id').childNodes.length);",
+ &user_media_request_count));
+ ASSERT_EQ(requests.size(), static_cast<size_t>(user_media_request_count));
+ }
}
// Verifies that DOM for |pc| is correctly created with the right content.
diff --git a/chromium/content/browser/media/webrtc_internals_message_handler.h b/chromium/content/browser/media/webrtc_internals_message_handler.h
index 8c5f10ca401..b27e7f0abb6 100644
--- a/chromium/content/browser/media/webrtc_internals_message_handler.h
+++ b/chromium/content/browser/media/webrtc_internals_message_handler.h
@@ -21,14 +21,13 @@ class WebRTCInternalsMessageHandler : public WebUIMessageHandler,
public WebRTCInternalsUIObserver{
public:
WebRTCInternalsMessageHandler();
- virtual ~WebRTCInternalsMessageHandler();
+ ~WebRTCInternalsMessageHandler() override;
// WebUIMessageHandler implementation.
- virtual void RegisterMessages() OVERRIDE;
+ void RegisterMessages() override;
// WebRTCInternalsUIObserver override.
- virtual void OnUpdate(const std::string& command,
- const base::Value* args) OVERRIDE;
+ void OnUpdate(const std::string& command, const base::Value* args) override;
private:
// Javascript message handler.
diff --git a/chromium/content/browser/media/webrtc_internals_ui.cc b/chromium/content/browser/media/webrtc_internals_ui.cc
index 5c4adc591a9..67970305741 100644
--- a/chromium/content/browser/media/webrtc_internals_ui.cc
+++ b/chromium/content/browser/media/webrtc_internals_ui.cc
@@ -5,11 +5,11 @@
#include "content/browser/media/webrtc_internals_ui.h"
#include "content/browser/media/webrtc_internals_message_handler.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
-#include "grit/content_resources.h"
namespace content {
namespace {
diff --git a/chromium/content/browser/media/webrtc_internals_unittest.cc b/chromium/content/browser/media/webrtc_internals_unittest.cc
index e4b0531fa54..afe3587db5e 100644
--- a/chromium/content/browser/media/webrtc_internals_unittest.cc
+++ b/chromium/content/browser/media/webrtc_internals_unittest.cc
@@ -15,13 +15,12 @@ namespace content {
namespace {
static const std::string kContraints = "c";
-static const std::string kServers = "s";
+static const std::string kRtcConfiguration = "r";
static const std::string kUrl = "u";
class MockWebRTCInternalsProxy : public WebRTCInternalsUIObserver {
public:
- virtual void OnUpdate(const std::string& command,
- const base::Value* value) OVERRIDE {
+ void OnUpdate(const std::string& command, const base::Value* value) override {
command_ = command;
if (value)
value_.reset(value->DeepCopy());
@@ -99,7 +98,7 @@ TEST_F(WebRTCInternalsTest, AddRemoveObserver) {
WebRTCInternals::GetInstance()->AddObserver(observer.get());
WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
WebRTCInternals::GetInstance()->OnAddPeerConnection(
- 0, 3, 4, kUrl, kServers, kContraints);
+ 0, 3, 4, kUrl, kRtcConfiguration, kContraints);
EXPECT_EQ("", observer->command());
WebRTCInternals::GetInstance()->OnRemovePeerConnection(3, 4);
@@ -110,7 +109,7 @@ TEST_F(WebRTCInternalsTest, SendAddPeerConnectionUpdate) {
new MockWebRTCInternalsProxy());
WebRTCInternals::GetInstance()->AddObserver(observer.get());
WebRTCInternals::GetInstance()->OnAddPeerConnection(
- 0, 1, 2, kUrl, kServers, kContraints);
+ 0, 1, 2, kUrl, kRtcConfiguration, kContraints);
EXPECT_EQ("addPeerConnection", observer->command());
base::DictionaryValue* dict = NULL;
@@ -119,7 +118,7 @@ TEST_F(WebRTCInternalsTest, SendAddPeerConnectionUpdate) {
VerifyInt(dict, "pid", 1);
VerifyInt(dict, "lid", 2);
VerifyString(dict, "url", kUrl);
- VerifyString(dict, "servers", kServers);
+ VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
VerifyString(dict, "constraints", kContraints);
WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
@@ -131,7 +130,7 @@ TEST_F(WebRTCInternalsTest, SendRemovePeerConnectionUpdate) {
new MockWebRTCInternalsProxy());
WebRTCInternals::GetInstance()->AddObserver(observer.get());
WebRTCInternals::GetInstance()->OnAddPeerConnection(
- 0, 1, 2, kUrl, kServers, kContraints);
+ 0, 1, 2, kUrl, kRtcConfiguration, kContraints);
WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
EXPECT_EQ("removePeerConnection", observer->command());
@@ -149,7 +148,7 @@ TEST_F(WebRTCInternalsTest, SendUpdatePeerConnectionUpdate) {
new MockWebRTCInternalsProxy());
WebRTCInternals::GetInstance()->AddObserver(observer.get());
WebRTCInternals::GetInstance()->OnAddPeerConnection(
- 0, 1, 2, kUrl, kServers, kContraints);
+ 0, 1, 2, kUrl, kRtcConfiguration, kContraints);
const std::string update_type = "fakeType";
const std::string update_value = "fakeValue";
@@ -166,6 +165,10 @@ TEST_F(WebRTCInternalsTest, SendUpdatePeerConnectionUpdate) {
VerifyString(dict, "type", update_type);
VerifyString(dict, "value", update_value);
+ std::string time;
+ EXPECT_TRUE(dict->GetString("time", &time));
+ EXPECT_FALSE(time.empty());
+
WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
}
@@ -216,7 +219,7 @@ TEST_F(WebRTCInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
const std::string update_value = "fakeValue";
WebRTCInternals::GetInstance()->OnAddPeerConnection(
- rid, pid, lid, kUrl, kServers, kContraints);
+ rid, pid, lid, kUrl, kRtcConfiguration, kContraints);
WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
pid, lid, update_type, update_value);
@@ -238,7 +241,7 @@ TEST_F(WebRTCInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
VerifyInt(dict, "pid", pid);
VerifyInt(dict, "lid", lid);
VerifyString(dict, "url", kUrl);
- VerifyString(dict, "servers", kServers);
+ VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
VerifyString(dict, "constraints", kContraints);
base::ListValue* log = NULL;
@@ -248,6 +251,9 @@ TEST_F(WebRTCInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
EXPECT_TRUE((*log->begin())->GetAsDictionary(&dict));
VerifyString(dict, "type", update_type);
VerifyString(dict, "value", update_value);
+ std::string time;
+ EXPECT_TRUE(dict->GetString("time", &time));
+ EXPECT_FALSE(time.empty());
}
TEST_F(WebRTCInternalsTest, OnAddStats) {
@@ -255,7 +261,7 @@ TEST_F(WebRTCInternalsTest, OnAddStats) {
scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
WebRTCInternals::GetInstance()->AddObserver(observer.get());
WebRTCInternals::GetInstance()->OnAddPeerConnection(
- rid, pid, lid, kUrl, kServers, kContraints);
+ rid, pid, lid, kUrl, kRtcConfiguration, kContraints);
base::ListValue list;
list.AppendString("xxx");
diff --git a/chromium/content/browser/media/webrtc_webcam_browsertest.cc b/chromium/content/browser/media/webrtc_webcam_browsertest.cc
new file mode 100644
index 00000000000..1be6ee51045
--- /dev/null
+++ b/chromium/content/browser/media/webrtc_webcam_browsertest.cc
@@ -0,0 +1,102 @@
+// Copyright 2014 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/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "media/base/media_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace {
+
+const base::CommandLine::StringType FAKE_DEVICE_FLAG =
+#if defined(OS_WIN)
+ base::ASCIIToUTF16(switches::kUseFakeDeviceForMediaStream);
+#else
+ switches::kUseFakeDeviceForMediaStream;
+#endif
+
+bool IsUseFakeDeviceForMediaStream(const base::CommandLine::StringType& arg) {
+ return arg.find(FAKE_DEVICE_FLAG) != std::string::npos;
+}
+
+void RemoveFakeDeviceFromCommandLine(base::CommandLine* command_line) {
+ CommandLine::StringVector argv = command_line->argv();
+ argv.erase(std::remove_if(argv.begin(), argv.end(),
+ IsUseFakeDeviceForMediaStream),
+ argv.end());
+ command_line->InitFromArgv(argv);
+}
+
+} // namespace
+
+namespace content {
+
+// This class doesn't inherit from WebRtcContentBrowserTestBase like the others
+// since we want it to actually acquire the real webcam on the system (if there
+// is one).
+class WebRtcWebcamBrowserTest: public ContentBrowserTest {
+ public:
+ ~WebRtcWebcamBrowserTest() override {}
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ASSERT_TRUE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
+
+ // The content_browsertests run with this flag by default, and this test is
+ // the only current exception to that rule, so just remove the flag
+ // --use-fake-device-for-media-stream here. We could also have all tests
+ // involving media streams add this flag explicitly, but it will be really
+ // unintuitive for developers to write tests involving media stream and have
+ // them fail on what looks like random bots, so running with fake devices
+ // is really a reasonable default.
+ RemoveFakeDeviceFromCommandLine(command_line);
+ }
+
+ void SetUp() override {
+ EnablePixelOutput();
+ ContentBrowserTest::SetUp();
+ }
+};
+
+// The test is tagged as MANUAL since the webcam is a system-level resource; we
+// only want it to run on bots where we can ensure sequential execution. The
+// Android bots will run the test since they ignore MANUAL, but that's what we
+// want here since the bot runs tests sequentially on the device.
+IN_PROC_BROWSER_TEST_F(WebRtcWebcamBrowserTest,
+ MANUAL_CanAcquireVgaOnRealWebcam) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ GURL url(embedded_test_server()->GetURL(
+ "/media/getusermedia-real-webcam.html"));
+ NavigateToURL(shell(), url);
+
+ std::string result;
+ ASSERT_TRUE(ExecuteScriptAndExtractString(shell()->web_contents(),
+ "hasVideoInputDeviceOnSystem()",
+ &result));
+ if (result != "has-video-input-device") {
+ VLOG(0) << "No video device; skipping test...";
+ return;
+ }
+
+ // GetUserMedia should acquire VGA by default.
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ shell()->web_contents(),
+ "getUserMediaAndReturnVideoDimensions({video: true})",
+ &result));
+
+ if (result == "640x480" || result == "480x640") {
+ // Don't care if the device happens to be in landscape or portrait mode
+ // since we don't know how it is oriented in the lab :)
+ return;
+ }
+ FAIL() << "Expected resolution to be 640x480 or 480x640, got" << result;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/message_port_message_filter.h b/chromium/content/browser/message_port_message_filter.h
index 64d07d6c328..21bfbb24e17 100644
--- a/chromium/content/browser/message_port_message_filter.h
+++ b/chromium/content/browser/message_port_message_filter.h
@@ -22,9 +22,9 @@ class CONTENT_EXPORT MessagePortMessageFilter : public BrowserMessageFilter {
explicit MessagePortMessageFilter(const NextRoutingIDCallback& callback);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() const override;
int GetNextRoutingID();
@@ -36,7 +36,7 @@ class CONTENT_EXPORT MessagePortMessageFilter : public BrowserMessageFilter {
protected:
// This is protected, so we can define sub classes for testing.
- virtual ~MessagePortMessageFilter();
+ ~MessagePortMessageFilter() override;
private:
friend class BrowserThread;
diff --git a/chromium/content/browser/mime_registry_message_filter.h b/chromium/content/browser/mime_registry_message_filter.h
index 4237f508e74..c4b110e98a2 100644
--- a/chromium/content/browser/mime_registry_message_filter.h
+++ b/chromium/content/browser/mime_registry_message_filter.h
@@ -14,13 +14,12 @@ class MimeRegistryMessageFilter : public BrowserMessageFilter {
public:
MimeRegistryMessageFilter();
- virtual void OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~MimeRegistryMessageFilter();
+ ~MimeRegistryMessageFilter() override;
void OnGetMimeTypeFromExtension(const base::FilePath::StringType& ext,
std::string* mime_type);
diff --git a/chromium/content/browser/mojo/mojo_application_host.cc b/chromium/content/browser/mojo/mojo_application_host.cc
index 90187b9b92f..18219676a3e 100644
--- a/chromium/content/browser/mojo/mojo_application_host.cc
+++ b/chromium/content/browser/mojo/mojo_application_host.cc
@@ -7,7 +7,7 @@
#include "content/common/mojo/mojo_messages.h"
#include "content/public/browser/browser_thread.h"
#include "ipc/ipc_sender.h"
-#include "mojo/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
namespace content {
namespace {
@@ -24,13 +24,17 @@ base::PlatformFile PlatformFileFromScopedPlatformHandle(
} // namespace
MojoApplicationHost::MojoApplicationHost() : did_activate_(false) {
+#if defined(OS_ANDROID)
+ service_registry_android_.reset(
+ new ServiceRegistryAndroid(&service_registry_));
+#endif
}
MojoApplicationHost::~MojoApplicationHost() {
}
bool MojoApplicationHost::Init() {
- DCHECK(!child_service_provider_.get()) << "Already initialized!";
+ DCHECK(!client_handle_.is_valid()) << "Already initialized!";
mojo::embedder::PlatformChannelPair channel_pair;
@@ -43,12 +47,11 @@ bool MojoApplicationHost::Init() {
// Forward this to the client once we know its process handle.
client_handle_ = channel_pair.PassClientHandle();
- child_service_provider_.reset(
- BindToPipe(new ServiceProviderImpl(), message_pipe.Pass()));
+ service_registry_.BindRemoteServiceProvider(message_pipe.Pass());
return true;
}
-bool MojoApplicationHost::Activate(IPC::Sender* sender,
+void MojoApplicationHost::Activate(IPC::Sender* sender,
base::ProcessHandle process_handle) {
DCHECK(!did_activate_);
DCHECK(client_handle_.is_valid());
@@ -57,15 +60,10 @@ bool MojoApplicationHost::Activate(IPC::Sender* sender,
PlatformFileFromScopedPlatformHandle(client_handle_.Pass());
did_activate_ = sender->Send(new MojoMsg_Activate(
IPC::GetFileHandleForProcess(client_file, process_handle, true)));
- return did_activate_;
}
-void MojoApplicationHost::ServiceProviderImpl::ConnectToService(
- const mojo::String& service_url,
- const mojo::String& service_name,
- mojo::ScopedMessagePipeHandle handle,
- const mojo::String& requestor_url) {
- // TODO(darin): Provide something meaningful here.
+void MojoApplicationHost::WillDestroySoon() {
+ channel_init_.WillDestroySoon();
}
} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_application_host.h b/chromium/content/browser/mojo/mojo_application_host.h
index f5913269d72..1825b3eab55 100644
--- a/chromium/content/browser/mojo/mojo_application_host.h
+++ b/chromium/content/browser/mojo/mojo_application_host.h
@@ -5,10 +5,15 @@
#ifndef CONTENT_BROWSER_MOJO_MOJO_APPLICATION_HOST_H_
#define CONTENT_BROWSER_MOJO_MOJO_APPLICATION_HOST_H_
+#include "base/memory/scoped_ptr.h"
#include "base/process/process_handle.h"
-#include "mojo/embedder/channel_init.h"
-#include "mojo/embedder/scoped_platform_handle.h"
-#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+#include "content/common/mojo/service_registry_impl.h"
+#include "mojo/edk/embedder/channel_init.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+
+#if defined(OS_ANDROID)
+#include "content/browser/mojo/service_registry_android.h"
+#endif
namespace IPC {
class Sender;
@@ -19,49 +24,35 @@ namespace content {
// MojoApplicationHost represents the code needed on the browser side to setup
// a child process as a Mojo application via Chrome IPC. The child process
// should use MojoApplication to handle messages generated by an instance of
-// MojoApplicationHost. MojoApplicationHost makes the mojo::ShellClient
-// interface available so that child-provided services can be invoked.
+// MojoApplicationHost. MojoApplicationHost makes the ServiceRegistry interface
+// available so that child-provided services can be invoked.
class MojoApplicationHost {
public:
MojoApplicationHost();
virtual ~MojoApplicationHost();
// Two-phase initialization:
- // 1- Init makes the shell_client() available synchronously.
+ // 1- Init makes service_registry() available synchronously.
// 2- Activate establishes the actual connection to the peer process.
bool Init();
- bool Activate(IPC::Sender* sender, base::ProcessHandle process_handle);
+ void Activate(IPC::Sender* sender, base::ProcessHandle process_handle);
- bool did_activate() const { return did_activate_; }
+ void WillDestroySoon();
- mojo::ServiceProvider* service_provider() {
- DCHECK(child_service_provider_.get());
- return child_service_provider_->client();
- }
+ ServiceRegistry* service_registry() { return &service_registry_; }
private:
- class ServiceProviderImpl
- : public mojo::InterfaceImpl<mojo::ServiceProvider> {
- public:
- virtual void OnConnectionError() OVERRIDE {
- // TODO(darin): How should we handle this error?
- }
-
- // mojo::ServiceProvider methods:
- virtual void ConnectToService(
- const mojo::String& service_url,
- const mojo::String& service_name,
- mojo::ScopedMessagePipeHandle handle,
- const mojo::String& requestor_url) OVERRIDE;
- };
-
mojo::embedder::ChannelInit channel_init_;
mojo::embedder::ScopedPlatformHandle client_handle_;
- scoped_ptr<ServiceProviderImpl> child_service_provider_;
-
bool did_activate_;
+ ServiceRegistryImpl service_registry_;
+
+#if defined(OS_ANDROID)
+ scoped_ptr<ServiceRegistryAndroid> service_registry_android_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(MojoApplicationHost);
};
diff --git a/chromium/content/browser/mojo/service_registry_android.cc b/chromium/content/browser/mojo/service_registry_android.cc
new file mode 100644
index 00000000000..269c8be61f4
--- /dev/null
+++ b/chromium/content/browser/mojo/service_registry_android.cc
@@ -0,0 +1,97 @@
+// Copyright 2014 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 "content/browser/mojo/service_registry_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/callback.h"
+#include "content/common/mojo/service_registry_impl.h"
+#include "jni/ServiceRegistry_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ScopedJavaGlobalRef;
+
+namespace content {
+
+namespace {
+
+// Callback passed to the wrapped ServiceRegistry upon AddService(). The
+// ServiceRegistry will call it to create a registered Java service
+void CreateImplAndAttach(
+ const ScopedJavaGlobalRef<jobject>& j_scoped_service_registry,
+ const ScopedJavaGlobalRef<jobject>& j_scoped_manager,
+ const ScopedJavaGlobalRef<jobject>& j_scoped_factory,
+ mojo::ScopedMessagePipeHandle handle) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_ServiceRegistry_createImplAndAttach(env,
+ j_scoped_service_registry.obj(),
+ handle.release().value(),
+ j_scoped_manager.obj(),
+ j_scoped_factory.obj());
+}
+
+} // namespace
+
+// static
+bool ServiceRegistryAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+// Constructor and destructor call into Java.
+ServiceRegistryAndroid::ServiceRegistryAndroid(
+ ServiceRegistryImpl* service_registry)
+ : service_registry_(service_registry) {
+ JNIEnv* env = AttachCurrentThread();
+ obj_.Reset(
+ env,
+ Java_ServiceRegistry_create(env, reinterpret_cast<intptr_t>(this)).obj());
+}
+
+ServiceRegistryAndroid::~ServiceRegistryAndroid() {
+ Java_ServiceRegistry_destroy(AttachCurrentThread(), obj_.obj());
+}
+
+// Methods called from Java.
+void ServiceRegistryAndroid::AddService(JNIEnv* env,
+ jobject j_service_registry,
+ jobject j_manager,
+ jobject j_factory,
+ jstring j_name) {
+ std::string name(ConvertJavaStringToUTF8(env, j_name));
+
+ ScopedJavaGlobalRef<jobject> j_scoped_service_registry;
+ j_scoped_service_registry.Reset(env, j_service_registry);
+
+ ScopedJavaGlobalRef<jobject> j_scoped_manager;
+ j_scoped_manager.Reset(env, j_manager);
+
+ ScopedJavaGlobalRef<jobject> j_scoped_factory;
+ j_scoped_factory.Reset(env, j_factory);
+
+ service_registry_->AddService(name,
+ base::Bind(&CreateImplAndAttach,
+ j_scoped_service_registry,
+ j_scoped_manager,
+ j_scoped_factory));
+}
+
+void ServiceRegistryAndroid::RemoveService(JNIEnv* env,
+ jobject j_service_registry,
+ jstring j_name) {
+ std::string name(ConvertJavaStringToUTF8(env, j_name));
+ service_registry_->RemoveService(name);
+}
+
+void ServiceRegistryAndroid::ConnectToRemoteService(JNIEnv* env,
+ jobject j_service_registry,
+ jstring j_name,
+ jint j_handle) {
+ std::string name(ConvertJavaStringToUTF8(env, j_name));
+ mojo::ScopedMessagePipeHandle handle((mojo::MessagePipeHandle(j_handle)));
+ service_registry_->ConnectToRemoteService(name, handle.Pass());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/mojo/service_registry_android.h b/chromium/content/browser/mojo/service_registry_android.h
new file mode 100644
index 00000000000..0873531be25
--- /dev/null
+++ b/chromium/content/browser/mojo/service_registry_android.h
@@ -0,0 +1,53 @@
+// Copyright 2014 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 CONTENT_BROWSER_MOJO_SERVICE_REGISTRY_ANDROID_H_
+#define CONTENT_BROWSER_MOJO_SERVICE_REGISTRY_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class ServiceRegistryImpl;
+
+// Android wrapper over ServiceRegistryImpl, allowing the browser services in
+// Java to register with ServiceRegistry.java (and abstracting away the JNI
+// calls).
+class CONTENT_EXPORT ServiceRegistryAndroid {
+ public:
+ static bool Register(JNIEnv* env);
+
+ explicit ServiceRegistryAndroid(ServiceRegistryImpl* service_registry);
+ virtual ~ServiceRegistryAndroid();
+
+ // Methods called from Java.
+ void AddService(JNIEnv* env,
+ jobject j_service_registry,
+ jobject j_manager,
+ jobject j_factory,
+ jstring j_name);
+ void RemoveService(JNIEnv* env, jobject j_service_registry, jstring j_name);
+ void ConnectToRemoteService(JNIEnv* env,
+ jobject j_service_registry,
+ jstring j_name,
+ jint handle);
+
+ const base::android::ScopedJavaGlobalRef<jobject>& GetObjForTesting() {
+ return obj_;
+ }
+
+ private:
+ ServiceRegistryImpl* service_registry_;
+ base::android::ScopedJavaGlobalRef<jobject> obj_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceRegistryAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MOJO_SERVICE_REGISTRY_ANDROID_H_
diff --git a/chromium/content/browser/net/browser_online_state_observer.h b/chromium/content/browser/net/browser_online_state_observer.h
index fbb0db4bf71..13d9e3d303a 100644
--- a/chromium/content/browser/net/browser_online_state_observer.h
+++ b/chromium/content/browser/net/browser_online_state_observer.h
@@ -16,11 +16,11 @@ class BrowserOnlineStateObserver
: public net::NetworkChangeNotifier::ConnectionTypeObserver {
public:
BrowserOnlineStateObserver();
- virtual ~BrowserOnlineStateObserver();
+ ~BrowserOnlineStateObserver() override;
// ConnectionTypeObserver implementation.
- virtual void OnConnectionTypeChanged(
- net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
+ void OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) override;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserOnlineStateObserver);
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
index 967101f4dbb..1009d29c626 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -13,8 +13,8 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
@@ -38,9 +38,9 @@
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
+#include "storage/browser/quota/special_storage_policy.h"
#include "third_party/sqlite/sqlite3.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/special_storage_policy.h"
using base::Time;
@@ -76,7 +76,7 @@ class SQLitePersistentCookieStore::Backend
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
- quota::SpecialStoragePolicy* special_storage_policy,
+ storage::SpecialStoragePolicy* special_storage_policy,
CookieCryptoDelegate* crypto_delegate)
: path_(path),
num_pending_(0),
@@ -249,7 +249,7 @@ class SQLitePersistentCookieStore::Backend
bool restore_old_session_cookies_;
// Policy defining what data is deleted on shutdown.
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
// The cumulative time spent loading the cookies on the background runner.
// Incremented and reported from the background runner.
@@ -1205,7 +1205,7 @@ SQLitePersistentCookieStore::SQLitePersistentCookieStore(
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
- quota::SpecialStoragePolicy* special_storage_policy,
+ storage::SpecialStoragePolicy* special_storage_policy,
CookieCryptoDelegate* crypto_delegate)
: backend_(new Backend(path,
client_task_runner,
@@ -1259,15 +1259,15 @@ CookieStoreConfig::CookieStoreConfig()
}
CookieStoreConfig::CookieStoreConfig(
- const base::FilePath& path,
+ const base::FilePath& path,
SessionCookieMode session_cookie_mode,
- quota::SpecialStoragePolicy* storage_policy,
+ storage::SpecialStoragePolicy* storage_policy,
net::CookieMonsterDelegate* cookie_delegate)
- : path(path),
- session_cookie_mode(session_cookie_mode),
- storage_policy(storage_policy),
- cookie_delegate(cookie_delegate),
- crypto_delegate(NULL) {
+ : path(path),
+ session_cookie_mode(session_cookie_mode),
+ storage_policy(storage_policy),
+ cookie_delegate(cookie_delegate),
+ crypto_delegate(NULL) {
CHECK(!path.empty() || session_cookie_mode == EPHEMERAL_SESSION_COOKIES);
}
@@ -1279,19 +1279,19 @@ net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
if (config.path.empty()) {
// Empty path means in-memory store.
- cookie_monster = new net::CookieMonster(NULL, config.cookie_delegate);
+ cookie_monster = new net::CookieMonster(NULL, config.cookie_delegate.get());
} else {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
config.client_task_runner;
scoped_refptr<base::SequencedTaskRunner> background_task_runner =
config.background_task_runner;
- if (!client_task_runner) {
+ if (!client_task_runner.get()) {
client_task_runner =
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
}
- if (!background_task_runner) {
+ if (!background_task_runner.get()) {
background_task_runner =
BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
BrowserThread::GetBlockingPool()->GetSequenceToken());
@@ -1304,11 +1304,11 @@ net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
background_task_runner,
(config.session_cookie_mode ==
CookieStoreConfig::RESTORED_SESSION_COOKIES),
- config.storage_policy,
+ config.storage_policy.get(),
config.crypto_delegate);
cookie_monster =
- new net::CookieMonster(persistent_store, config.cookie_delegate);
+ new net::CookieMonster(persistent_store, config.cookie_delegate.get());
if ((config.session_cookie_mode ==
CookieStoreConfig::PERSISTANT_SESSION_COOKIES) ||
(config.session_cookie_mode ==
@@ -1317,16 +1317,7 @@ net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
}
}
- // In the case of Android WebView, the cookie store may be created
- // before the browser process fully initializes -- certainly before
- // the main loop ever runs. In this situation, the CommandLine singleton
- // will not have been set up. Android tests do not need file cookies
- // so always ignore them here.
- //
- // TODO(ajwong): Remove the InitializedForCurrentProcess() check
- // once http://crbug.com/331424 is resolved.
- if (CommandLine::InitializedForCurrentProcess() &&
- CommandLine::ForCurrentProcess()->HasSwitch(
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableFileCookies)) {
cookie_monster->SetEnableFileScheme(true);
}
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store.h b/chromium/content/browser/net/sqlite_persistent_cookie_store.h
index 5773de186a3..786b6b6725a 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store.h
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store.h
@@ -27,7 +27,7 @@ namespace net {
class CanonicalCookie;
}
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
}
@@ -50,21 +50,21 @@ class CONTENT_EXPORT SQLitePersistentCookieStore
const scoped_refptr<base::SequencedTaskRunner>& client_task_runner,
const scoped_refptr<base::SequencedTaskRunner>& background_task_runner,
bool restore_old_session_cookies,
- quota::SpecialStoragePolicy* special_storage_policy,
+ storage::SpecialStoragePolicy* special_storage_policy,
CookieCryptoDelegate* crypto_delegate);
// net::CookieMonster::PersistentCookieStore:
- virtual void Load(const LoadedCallback& loaded_callback) OVERRIDE;
- virtual void LoadCookiesForKey(const std::string& key,
- const LoadedCallback& callback) OVERRIDE;
- virtual void AddCookie(const net::CanonicalCookie& cc) OVERRIDE;
- virtual void UpdateCookieAccessTime(const net::CanonicalCookie& cc) OVERRIDE;
- virtual void DeleteCookie(const net::CanonicalCookie& cc) OVERRIDE;
- virtual void SetForceKeepSessionState() OVERRIDE;
- virtual void Flush(const base::Closure& callback) OVERRIDE;
+ void Load(const LoadedCallback& loaded_callback) override;
+ void LoadCookiesForKey(const std::string& key,
+ const LoadedCallback& callback) override;
+ void AddCookie(const net::CanonicalCookie& cc) override;
+ void UpdateCookieAccessTime(const net::CanonicalCookie& cc) override;
+ void DeleteCookie(const net::CanonicalCookie& cc) override;
+ void SetForceKeepSessionState() override;
+ void Flush(const base::Closure& callback) override;
protected:
- virtual ~SQLitePersistentCookieStore();
+ ~SQLitePersistentCookieStore() override;
private:
class Backend;
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
index 7092aa28efa..21f3c85d8f5 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store_perftest.cc
@@ -61,7 +61,7 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
pool_owner_->pool()->GetNamedSequenceToken("client"));
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
store_ = new SQLitePersistentCookieStore(
temp_dir_.path().Append(cookie_filename),
@@ -101,7 +101,7 @@ class SQLitePersistentCookieStorePerfTest : public testing::Test {
false, NULL, NULL);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
store_ = NULL;
pool_owner_->pool()->Shutdown();
}
diff --git a/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc b/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
index d6e30a6587e..47590d7274b 100644
--- a/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
@@ -40,10 +40,10 @@ const base::FilePath::CharType kCookieFilename[] = FILE_PATH_LITERAL("Cookies");
class CookieCryptor : public content::CookieCryptoDelegate {
public:
CookieCryptor();
- virtual bool EncryptString(const std::string& plaintext,
- std::string* ciphertext) OVERRIDE;
- virtual bool DecryptString(const std::string& ciphertext,
- std::string* plaintext) OVERRIDE;
+ bool EncryptString(const std::string& plaintext,
+ std::string* ciphertext) override;
+ bool DecryptString(const std::string& ciphertext,
+ std::string* plaintext) override;
private:
scoped_ptr<crypto::SymmetricKey> key_;
@@ -173,11 +173,9 @@ class SQLitePersistentCookieStoreTest : public testing::Test {
return contents;
}
- virtual void SetUp() OVERRIDE {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- }
+ void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
DestroyStore();
pool_owner_->pool()->Shutdown();
}
diff --git a/chromium/content/browser/net/view_blob_internals_job_factory.cc b/chromium/content/browser/net/view_blob_internals_job_factory.cc
index 984763d45c9..d15c59f84fd 100644
--- a/chromium/content/browser/net/view_blob_internals_job_factory.cc
+++ b/chromium/content/browser/net/view_blob_internals_job_factory.cc
@@ -7,7 +7,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "content/public/common/url_constants.h"
-#include "webkit/browser/blob/view_blob_internals_job.h"
+#include "storage/browser/blob/view_blob_internals_job.h"
namespace content {
@@ -21,8 +21,8 @@ bool ViewBlobInternalsJobFactory::IsSupportedURL(const GURL& url) {
net::URLRequestJob* ViewBlobInternalsJobFactory::CreateJobForRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- webkit_blob::BlobStorageContext* blob_storage_context) {
- return new webkit_blob::ViewBlobInternalsJob(
+ storage::BlobStorageContext* blob_storage_context) {
+ return new storage::ViewBlobInternalsJob(
request, network_delegate, blob_storage_context);
}
diff --git a/chromium/content/browser/net/view_blob_internals_job_factory.h b/chromium/content/browser/net/view_blob_internals_job_factory.h
index 4d4b60abf4c..cc8bd14242f 100644
--- a/chromium/content/browser/net/view_blob_internals_job_factory.h
+++ b/chromium/content/browser/net/view_blob_internals_job_factory.h
@@ -9,10 +9,11 @@ namespace net {
class NetworkDelegate;
class URLRequest;
class URLRequestJob;
-} // namespace net
-namespace webkit_blob {
+}
+
+namespace storage {
class BlobStorageContext;
-} // webkit_blob
+}
class GURL;
@@ -24,7 +25,7 @@ class ViewBlobInternalsJobFactory {
static net::URLRequestJob* CreateJobForRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
- webkit_blob::BlobStorageContext* blob_storage_context);
+ storage::BlobStorageContext* blob_storage_context);
};
} // namespace content
diff --git a/chromium/content/browser/net/view_http_cache_job_factory.cc b/chromium/content/browser/net/view_http_cache_job_factory.cc
index a0cce463d74..e80cac725e7 100644
--- a/chromium/content/browser/net/view_http_cache_job_factory.cc
+++ b/chromium/content/browser/net/view_http_cache_job_factory.cc
@@ -28,22 +28,21 @@ class ViewHttpCacheJob : public net::URLRequestJob {
net::NetworkDelegate* network_delegate)
: net::URLRequestJob(request, network_delegate),
core_(new Core),
- weak_factory_(this),
callback_(base::Bind(&ViewHttpCacheJob::OnStartCompleted,
- base::Unretained(this))) {
+ base::Unretained(this))),
+ weak_factory_(this) {
}
// net::URLRequestJob implementation.
- virtual void Start() OVERRIDE;
- virtual void Kill() OVERRIDE;
- virtual bool GetMimeType(std::string* mime_type) const OVERRIDE{
+ void Start() override;
+ void Kill() override;
+ bool GetMimeType(std::string* mime_type) const override {
return core_->GetMimeType(mime_type);
}
- virtual bool GetCharset(std::string* charset) OVERRIDE{
+ bool GetCharset(std::string* charset) override {
return core_->GetCharset(charset);
}
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size, int *bytes_read) OVERRIDE{
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override {
return core_->ReadRawData(buf, buf_size, bytes_read);
}
@@ -83,15 +82,16 @@ class ViewHttpCacheJob : public net::URLRequestJob {
DISALLOW_COPY_AND_ASSIGN(Core);
};
- virtual ~ViewHttpCacheJob() {}
+ ~ViewHttpCacheJob() override {}
void StartAsync();
void OnStartCompleted();
scoped_refptr<Core> core_;
- base::WeakPtrFactory<ViewHttpCacheJob> weak_factory_;
base::Closure callback_;
+ base::WeakPtrFactory<ViewHttpCacheJob> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ViewHttpCacheJob);
};
diff --git a/chromium/content/browser/net_info_browsertest.cc b/chromium/content/browser/net_info_browsertest.cc
new file mode 100644
index 00000000000..cea69620487
--- /dev/null
+++ b/chromium/content/browser/net_info_browsertest.cc
@@ -0,0 +1,80 @@
+// Copyright 2014 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/command_line.h"
+#include "base/run_loop.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/base/network_change_notifier.h"
+#include "net/base/network_change_notifier_factory.h"
+
+class NetInfoBrowserTest : public content::ContentBrowserTest {
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // TODO(jkarlin): Once NetInfo is enabled on all platforms remove this
+ // switch.
+ command_line->AppendSwitch(switches::kEnableNetworkInformation);
+ }
+
+#if defined(OS_CHROMEOS)
+ virtual void SetUp() override {
+ // ChromeOS's NetworkChangeNotifier isn't known to content and therefore
+ // doesn't get created in content_browsertests. Insert a mock
+ // NetworkChangeNotifier.
+ net::NetworkChangeNotifier::CreateMock();
+ content::ContentBrowserTest::SetUp();
+ }
+#endif
+
+ void SetUpOnMainThread() override {
+ net::NetworkChangeNotifier::SetTestNotificationsOnly(true);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ static void SetConnectionType(
+ net::NetworkChangeNotifier::ConnectionType type) {
+ net::NetworkChangeNotifier::NotifyObserversOfConnectionTypeChangeForTests(
+ type);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ std::string RunScriptExtractString(const std::string& script) {
+ std::string data;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractString(shell()->web_contents(), script, &data));
+ return data;
+ }
+
+ bool RunScriptExtractBool(const std::string& script) {
+ bool data;
+ EXPECT_TRUE(
+ ExecuteScriptAndExtractBool(shell()->web_contents(), script, &data));
+ return data;
+ }
+};
+
+// Make sure that type changes in the browser make their way to
+// navigator.connection.type.
+IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkChangePlumbsToNavigator) {
+ NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"));
+ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ EXPECT_EQ("wifi", RunScriptExtractString("getType()"));
+ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
+ EXPECT_EQ("ethernet", RunScriptExtractString("getType()"));
+}
+
+// Make sure that type changes in the browser make their way to
+// navigator.isOnline.
+IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, IsOnline) {
+ NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"));
+ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
+ EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
+ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE);
+ EXPECT_FALSE(RunScriptExtractBool("getOnLine()"));
+ SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
+}
diff --git a/chromium/content/browser/notification_service_impl.h b/chromium/content/browser/notification_service_impl.h
index c9dce92cb60..2df369a6d0f 100644
--- a/chromium/content/browser/notification_service_impl.h
+++ b/chromium/content/browser/notification_service_impl.h
@@ -23,12 +23,12 @@ class CONTENT_EXPORT NotificationServiceImpl : public NotificationService {
// Normally instantiated when the thread is created. Not all threads have
// a NotificationService. Only one instance should be created per thread.
NotificationServiceImpl();
- virtual ~NotificationServiceImpl();
+ ~NotificationServiceImpl() override;
// NotificationService:
- virtual void Notify(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Notify(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
private:
friend class NotificationRegistrar;
diff --git a/chromium/content/browser/notification_service_impl_unittest.cc b/chromium/content/browser/notification_service_impl_unittest.cc
index 1317e4a4e7e..1e71e64251d 100644
--- a/chromium/content/browser/notification_service_impl_unittest.cc
+++ b/chromium/content/browser/notification_service_impl_unittest.cc
@@ -22,9 +22,9 @@ class TestObserver : public NotificationObserver {
int notification_count() const { return notification_count_; }
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE {
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override {
++notification_count_;
}
diff --git a/chromium/content/browser/notifications/OWNERS b/chromium/content/browser/notifications/OWNERS
new file mode 100644
index 00000000000..2fca67fdfda
--- /dev/null
+++ b/chromium/content/browser/notifications/OWNERS
@@ -0,0 +1 @@
+peter@chromium.org \ No newline at end of file
diff --git a/chromium/content/browser/notifications/notification_message_filter.cc b/chromium/content/browser/notifications/notification_message_filter.cc
new file mode 100644
index 00000000000..fecd0730b77
--- /dev/null
+++ b/chromium/content/browser/notifications/notification_message_filter.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 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 "content/browser/notifications/notification_message_filter.h"
+
+#include "base/callback.h"
+#include "content/browser/notifications/page_notification_delegate.h"
+#include "content/common/platform_notification_messages.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/desktop_notification_delegate.h"
+#include "content/public/common/content_client.h"
+
+namespace content {
+
+NotificationMessageFilter::NotificationMessageFilter(
+ int process_id,
+ ResourceContext* resource_context,
+ BrowserContext* browser_context)
+ : BrowserMessageFilter(PlatformNotificationMsgStart),
+ process_id_(process_id),
+ resource_context_(resource_context),
+ browser_context_(browser_context) {}
+
+NotificationMessageFilter::~NotificationMessageFilter() {}
+
+void NotificationMessageFilter::DidCloseNotification(int notification_id) {
+ close_closures_.erase(notification_id);
+}
+
+bool NotificationMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(NotificationMessageFilter, message)
+ IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_CheckPermission,
+ OnCheckNotificationPermission)
+ IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_Show,
+ OnShowPlatformNotification)
+ IPC_MESSAGE_HANDLER(PlatformNotificationHostMsg_Close,
+ OnClosePlatformNotification)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void NotificationMessageFilter::OverrideThreadForMessage(
+ const IPC::Message& message, content::BrowserThread::ID* thread) {
+ if (message.type() == PlatformNotificationHostMsg_Show::ID ||
+ message.type() == PlatformNotificationHostMsg_Close::ID)
+ *thread = BrowserThread::UI;
+}
+
+void NotificationMessageFilter::OnCheckNotificationPermission(
+ const GURL& origin, blink::WebNotificationPermission* permission) {
+ *permission =
+ GetContentClient()->browser()->CheckDesktopNotificationPermission(
+ origin,
+ resource_context_,
+ process_id_);
+}
+
+void NotificationMessageFilter::OnShowPlatformNotification(
+ int notification_id, const ShowDesktopNotificationHostMsgParams& params) {
+ scoped_ptr<DesktopNotificationDelegate> delegate(
+ new PageNotificationDelegate(process_id_, notification_id));
+
+ base::Closure close_closure;
+ GetContentClient()->browser()->ShowDesktopNotification(params,
+ browser_context_,
+ process_id_,
+ delegate.Pass(),
+ &close_closure);
+
+ if (!close_closure.is_null())
+ close_closures_[notification_id] = close_closure;
+}
+
+void NotificationMessageFilter::OnClosePlatformNotification(
+ int notification_id) {
+ if (!close_closures_.count(notification_id))
+ return;
+
+ close_closures_[notification_id].Run();
+ close_closures_.erase(notification_id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/notifications/notification_message_filter.h b/chromium/content/browser/notifications/notification_message_filter.h
new file mode 100644
index 00000000000..0b5159b18b7
--- /dev/null
+++ b/chromium/content/browser/notifications/notification_message_filter.h
@@ -0,0 +1,58 @@
+// Copyright 2014 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 CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_MESSAGE_FILTER_H_
+
+#include <map>
+
+#include "base/callback_forward.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "third_party/WebKit/public/platform/WebNotificationPermission.h"
+
+class GURL;
+
+namespace content {
+
+class BrowserContext;
+class ResourceContext;
+struct ShowDesktopNotificationHostMsgParams;
+
+class NotificationMessageFilter : public BrowserMessageFilter {
+ public:
+ NotificationMessageFilter(
+ int process_id,
+ ResourceContext* resource_context,
+ BrowserContext* browser_context);
+
+ // To be called by the notification's delegate when it has closed, so that
+ // the close closure associated with that notification can be removed.
+ void DidCloseNotification(int notification_id);
+
+ // BrowserMessageFilter implementation. Called on the UI thread.
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OverrideThreadForMessage(
+ const IPC::Message& message, content::BrowserThread::ID* thread) override;
+
+ protected:
+ ~NotificationMessageFilter() override;
+
+ private:
+ void OnCheckNotificationPermission(
+ const GURL& origin, blink::WebNotificationPermission* permission);
+ void OnShowPlatformNotification(
+ int notification_id, const ShowDesktopNotificationHostMsgParams& params);
+ void OnClosePlatformNotification(int notification_id);
+
+ int process_id_;
+ ResourceContext* resource_context_;
+ BrowserContext* browser_context_;
+
+ // Map mapping notification ids to their associated close closures.
+ std::map<int, base::Closure> close_closures_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/notifications/page_notification_delegate.cc b/chromium/content/browser/notifications/page_notification_delegate.cc
new file mode 100644
index 00000000000..dacfffbfd22
--- /dev/null
+++ b/chromium/content/browser/notifications/page_notification_delegate.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 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 "content/browser/notifications/page_notification_delegate.h"
+
+#include "content/browser/notifications/notification_message_filter.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/common/platform_notification_messages.h"
+#include "content/public/browser/render_process_host.h"
+
+namespace content {
+
+PageNotificationDelegate::PageNotificationDelegate(int render_process_id,
+ int notification_id)
+ : render_process_id_(render_process_id),
+ notification_id_(notification_id) {}
+
+PageNotificationDelegate::~PageNotificationDelegate() {}
+
+void PageNotificationDelegate::NotificationDisplayed() {
+ RenderProcessHost* sender = RenderProcessHost::FromID(render_process_id_);
+ if (!sender)
+ return;
+
+ sender->Send(new PlatformNotificationMsg_DidShow(notification_id_));
+}
+
+// TODO(peter): Remove |by_user| since we're not using that anywhere.
+void PageNotificationDelegate::NotificationClosed(bool by_user) {
+ RenderProcessHost* sender = RenderProcessHost::FromID(render_process_id_);
+ if (!sender)
+ return;
+
+ sender->Send(new PlatformNotificationMsg_DidClose(notification_id_));
+ static_cast<RenderProcessHostImpl*>(sender)
+ ->notification_message_filter()->DidCloseNotification(notification_id_);
+}
+
+void PageNotificationDelegate::NotificationClick() {
+ RenderProcessHost* sender = RenderProcessHost::FromID(render_process_id_);
+ if (!sender)
+ return;
+
+ sender->Send(new PlatformNotificationMsg_DidClick(notification_id_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/notifications/page_notification_delegate.h b/chromium/content/browser/notifications/page_notification_delegate.h
new file mode 100644
index 00000000000..dd3422f2c4e
--- /dev/null
+++ b/chromium/content/browser/notifications/page_notification_delegate.h
@@ -0,0 +1,32 @@
+// Copyright 2014 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 CONTENT_BROWSER_NOTIFICATIONS_PAGE_NOTIFICATION_DELEGATE_H_
+#define CONTENT_BROWSER_NOTIFICATIONS_PAGE_NOTIFICATION_DELEGATE_H_
+
+#include "content/public/browser/desktop_notification_delegate.h"
+
+namespace content {
+
+// A delegate used by the notification service to report the results of platform
+// notification interactions to Web Notifications whose lifetime is tied to
+// that of the page displaying them.
+class PageNotificationDelegate : public DesktopNotificationDelegate {
+ public:
+ PageNotificationDelegate(int render_process_id, int notification_id);
+ ~PageNotificationDelegate() override;
+
+ // DesktopNotificationDelegate implementation.
+ void NotificationDisplayed() override;
+ void NotificationClosed(bool by_user) override;
+ void NotificationClick() override;
+
+ private:
+ int render_process_id_;
+ int notification_id_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_NOTIFICATIONS_PAGE_NOTIFICATION_DELEGATE_H_
diff --git a/chromium/content/browser/pepper_flash_settings_helper_impl.h b/chromium/content/browser/pepper_flash_settings_helper_impl.h
index 19584a8cec3..9a5887ba31f 100644
--- a/chromium/content/browser/pepper_flash_settings_helper_impl.h
+++ b/chromium/content/browser/pepper_flash_settings_helper_impl.h
@@ -19,20 +19,19 @@ class CONTENT_EXPORT PepperFlashSettingsHelperImpl
PepperFlashSettingsHelperImpl();
// PepperFlashSettingsHelper implementation.
- virtual void OpenChannelToBroker(
- const base::FilePath& path,
- const OpenChannelCallback& callback) OVERRIDE;
+ void OpenChannelToBroker(const base::FilePath& path,
+ const OpenChannelCallback& callback) override;
// PpapiPluginProcessHost::BrokerClient implementation.
- virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
- int* renderer_id) OVERRIDE;
- virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
- base::ProcessId plugin_pid,
- int plugin_child_id) OVERRIDE;
- virtual bool OffTheRecord() OVERRIDE;
+ void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
+ int* renderer_id) override;
+ void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
+ base::ProcessId plugin_pid,
+ int plugin_child_id) override;
+ bool OffTheRecord() override;
protected:
- virtual ~PepperFlashSettingsHelperImpl();
+ ~PepperFlashSettingsHelperImpl() override;
private:
OpenChannelCallback callback_;
diff --git a/chromium/content/browser/plugin_browsertest.cc b/chromium/content/browser/plugin_browsertest.cc
index 2e4053385ca..a5ca6da74ea 100644
--- a/chromium/content/browser/plugin_browsertest.cc
+++ b/chromium/content/browser/plugin_browsertest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -17,8 +17,8 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/common/shell_switches.h"
-#include "content/test/net/url_request_mock_http_job.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/url_request/url_request_mock_http_job.h"
#include "net/url_request/url_request.h"
#include "ui/gfx/rect.h"
@@ -39,7 +39,8 @@ namespace content {
namespace {
void SetUrlRequestMock(const base::FilePath& path) {
- URLRequestMockHTTPJob::AddUrlHandler(path);
+ net::URLRequestMockHTTPJob::AddUrlHandler(
+ path, content::BrowserThread::GetBlockingPool());
}
}
@@ -48,7 +49,7 @@ class PluginTest : public ContentBrowserTest {
protected:
PluginTest() {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
// Some NPAPI tests schedule garbage collection to force object tear-down.
command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose_gc");
@@ -75,7 +76,7 @@ class PluginTest : public ContentBrowserTest {
#endif
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
base::FilePath path = GetTestFilePath("", "");
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, base::Bind(&SetUrlRequestMock, path));
@@ -186,9 +187,9 @@ IN_PROC_BROWSER_TEST_F(PluginTest,
#endif
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE_GetURLRequest404Response) {
- GURL url(URLRequestMockHTTPJob::GetMockUrl(
- base::FilePath().AppendASCII("npapi").
- AppendASCII("plugin_url_request_404.html")));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath().AppendASCII("npapi").AppendASCII(
+ "plugin_url_request_404.html")));
LoadAndWait(url);
}
@@ -222,10 +223,12 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(ManyPlugins)) {
LoadAndWait(GetURL("many_plugins.html"));
}
+#if !defined(OS_MACOSX) // http://crbug.com/402164
// Test various calls to GetURL from a plugin.
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURL)) {
LoadAndWait(GetURL("geturl.html"));
}
+#endif
// Test various calls to GetURL for javascript URLs with
// non NULL targets from a plugin.
@@ -294,7 +297,8 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyPluginWindowRect)) {
// Tests that creating a new instance of a plugin while another one is handling
// a paint message doesn't cause deadlock.
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(CreateInstanceInPaint)) {
+// http://crbug.com/406184
+IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_CreateInstanceInPaint) {
LoadAndWait(GetURL("create_instance_in_paint.html"));
}
@@ -306,7 +310,8 @@ IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_AlertInWindowMessage) {
WaitForAppModalDialog(shell());
}
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(VerifyNPObjectLifetimeTest)) {
+// http://crbug.com/406184
+IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_VerifyNPObjectLifetimeTest) {
LoadAndWait(GetURL("npobject_lifetime_test.html"));
}
@@ -354,6 +359,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, PluginSingleRangeRequest) {
LoadAndWait(GetURL("plugin_single_range_request.html"));
}
+#if !defined(OS_WIN) // http://crbug.com/396373
// Test checking the privacy mode is on.
// If this flakes on Linux, use http://crbug.com/104380
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateEnabled)) {
@@ -361,24 +367,27 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PrivateEnabled)) {
url = GURL(url.spec() + "?private");
LoadAndWaitInWindow(CreateOffTheRecordBrowser(), url);
}
+#endif
-#if defined(OS_WIN) || defined(OS_MACOSX)
+// These used to run on Windows: http://crbug.com/396373
+#if defined(OS_MACOSX)
// Test a browser hang due to special case of multiple
// plugin instances indulged in sync calls across renderer.
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(MultipleInstancesSyncCalls)) {
LoadAndWait(GetURL("multiple_instances_sync_calls.html"));
}
-#endif
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(GetURLRequestFailWrite)) {
- GURL url(URLRequestMockHTTPJob::GetMockUrl(
- base::FilePath().AppendASCII("npapi").
- AppendASCII("plugin_url_request_fail_write.html")));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath().AppendASCII("npapi").AppendASCII(
+ "plugin_url_request_fail_write.html")));
LoadAndWait(url);
}
+#endif
#if defined(OS_WIN)
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(EnsureScriptingWorksInDestroy)) {
+// Flaky on Windows x86. http://crbug.com/388245
+IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_EnsureScriptingWorksInDestroy) {
LoadAndWait(GetURL("ensure_scripting_works_in_destroy.html"));
}
@@ -394,9 +403,9 @@ IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(NoHangIfInitCrashes)) {
// If this flakes on Mac, use http://crbug.com/111508
IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(PluginReferrerTest)) {
- GURL url(URLRequestMockHTTPJob::GetMockUrl(
- base::FilePath().AppendASCII("npapi").
- AppendASCII("plugin_url_request_referrer_test.html")));
+ GURL url(net::URLRequestMockHTTPJob::GetMockUrl(
+ base::FilePath().AppendASCII("npapi").AppendASCII(
+ "plugin_url_request_referrer_test.html")));
LoadAndWait(url);
}
@@ -437,7 +446,7 @@ IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_FlashSecurity) {
// TODO(port) Port the following tests to platforms that have the required
// plugins.
// Flaky: http://crbug.com/55915
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Quicktime)) {
+IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Quicktime) {
TestPlugin("quicktime.html");
}
@@ -476,7 +485,8 @@ IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Java) {
TestPlugin("Java.html");
}
-IN_PROC_BROWSER_TEST_F(PluginTest, MAYBE(Silverlight)) {
+// Flaky: http://crbug.com/55915
+IN_PROC_BROWSER_TEST_F(PluginTest, DISABLED_Silverlight) {
TestPlugin("silverlight.html");
}
#endif // defined(OS_WIN)
@@ -498,11 +508,10 @@ class TestResourceDispatcherHostDelegate
private:
// ResourceDispatcherHostDelegate implementation:
- virtual void OnResponseStarted(
- net::URLRequest* request,
- ResourceContext* resource_context,
- ResourceResponse* response,
- IPC::Sender* sender) OVERRIDE {
+ void OnResponseStarted(net::URLRequest* request,
+ ResourceContext* resource_context,
+ ResourceResponse* response,
+ IPC::Sender* sender) override {
// The URL below comes from plugin_geturl_test.cc.
if (!EndsWith(request->url().spec(),
"npapi/plugin_ref_target_page.html",
@@ -524,7 +533,7 @@ class TestResourceDispatcherHostDelegate
void GotCookie(bool found_cookie) {
found_cookie_ = found_cookie;
- if (runner_)
+ if (runner_.get())
runner_->QuitClosure().Run();
}
diff --git a/chromium/content/browser/plugin_content_origin_whitelist.cc b/chromium/content/browser/plugin_content_origin_whitelist.cc
new file mode 100644
index 00000000000..d10e703f117
--- /dev/null
+++ b/chromium/content/browser/plugin_content_origin_whitelist.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 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 "content/browser/plugin_content_origin_whitelist.h"
+
+#include "content/common/frame_messages.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace content {
+
+PluginContentOriginWhitelist::PluginContentOriginWhitelist(
+ WebContents* web_contents)
+ : WebContentsObserver(web_contents) {
+}
+
+PluginContentOriginWhitelist::~PluginContentOriginWhitelist() {
+}
+
+void PluginContentOriginWhitelist::RenderFrameCreated(
+ RenderFrameHost* render_frame_host) {
+ if (!whitelist_.empty()) {
+ Send(new FrameMsg_UpdatePluginContentOriginWhitelist(
+ render_frame_host->GetRoutingID(), whitelist_));
+ }
+}
+
+bool PluginContentOriginWhitelist::OnMessageReceived(
+ const IPC::Message& message,
+ RenderFrameHost* render_frame_host) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PluginContentOriginWhitelist, message)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_PluginContentOriginAllowed,
+ OnPluginContentOriginAllowed)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void PluginContentOriginWhitelist::DidNavigateMainFrame(
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) {
+ if (details.is_navigation_to_different_page()) {
+ // We expect RenderFrames to clear their replicated whitelist independently.
+ whitelist_.clear();
+ }
+}
+
+void PluginContentOriginWhitelist::OnPluginContentOriginAllowed(
+ const GURL& content_origin) {
+ whitelist_.insert(content_origin);
+
+ web_contents()->SendToAllFrames(
+ new FrameMsg_UpdatePluginContentOriginWhitelist(
+ MSG_ROUTING_NONE, whitelist_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/plugin_content_origin_whitelist.h b/chromium/content/browser/plugin_content_origin_whitelist.h
new file mode 100644
index 00000000000..25311d242eb
--- /dev/null
+++ b/chromium/content/browser/plugin_content_origin_whitelist.h
@@ -0,0 +1,51 @@
+// Copyright 2014 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 CONTENT_BROWSER_PLUGIN_CONTENT_ORIGIN_WHITELIST_H_
+#define CONTENT_BROWSER_PLUGIN_CONTENT_ORIGIN_WHITELIST_H_
+
+#include <set>
+
+#include "content/public/browser/web_contents_observer.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class WebContents;
+
+// This class manages the tab-wide list of temporarily whitelisted plugin
+// content origins that are exempt from power saving.
+//
+// RenderFrames report content origins that should be whitelisted via IPC.
+// This class aggregates those origins and broadcasts the total list to all
+// RenderFrames owned by the tab (WebContents). This class also sends these
+// origins to any newly created RenderFrames.
+//
+// Tab-wide whitelists are cleared by top-level navigation. RenderFrames that
+// persist across top level navigations are responsible for clearing their own
+// whitelists.
+class PluginContentOriginWhitelist : public WebContentsObserver {
+ public:
+ explicit PluginContentOriginWhitelist(WebContents* web_contents);
+ ~PluginContentOriginWhitelist() override;
+
+ private:
+ // WebContentsObserver implementation.
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
+ bool OnMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host) override;
+ void DidNavigateMainFrame(
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override;
+
+ void OnPluginContentOriginAllowed(const GURL& content_origin);
+
+ std::set<GURL> whitelist_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginContentOriginWhitelist);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PLUGIN_CONTENT_ORIGIN_WHITELIST_H_
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index a318e724d4b..f74b37831b5 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -122,32 +122,28 @@ class PluginDataRemoverImpl::Context
}
// PluginProcessHost::Client methods.
- virtual int ID() OVERRIDE {
+ int ID() override {
// Generate a unique identifier for this PluginProcessHostClient.
return ChildProcessHostImpl::GenerateChildProcessUniqueId();
}
- virtual bool OffTheRecord() OVERRIDE {
- return false;
- }
+ bool OffTheRecord() override { return false; }
- virtual ResourceContext* GetResourceContext() OVERRIDE {
- return resource_context_;
- }
+ ResourceContext* GetResourceContext() override { return resource_context_; }
- virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {}
+ void SetPluginInfo(const WebPluginInfo& info) override {}
- virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {}
+ void OnFoundPluginProcessHost(PluginProcessHost* host) override {}
- virtual void OnSentPluginChannelRequest() OVERRIDE {}
+ void OnSentPluginChannelRequest() override {}
- virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
+ void OnChannelOpened(const IPC::ChannelHandle& handle) override {
ConnectToChannel(handle, false);
// Balancing the AddRef call.
Release();
}
- virtual void OnError() OVERRIDE {
+ void OnError() override {
LOG(ERROR) << "Couldn't open plugin channel";
SignalDone();
// Balancing the AddRef call.
@@ -155,16 +151,15 @@ class PluginDataRemoverImpl::Context
}
// PpapiPluginProcessHost::BrokerClient implementation.
- virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
- int* renderer_id) OVERRIDE {
+ void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
+ int* renderer_id) override {
*renderer_handle = base::kNullProcessHandle;
*renderer_id = 0;
}
- virtual void OnPpapiChannelOpened(
- const IPC::ChannelHandle& channel_handle,
- base::ProcessId /* peer_pid */,
- int /* child_id */) OVERRIDE {
+ void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
+ base::ProcessId /* peer_pid */,
+ int /* child_id */) override {
if (!channel_handle.name.empty())
ConnectToChannel(channel_handle, true);
@@ -173,7 +168,7 @@ class PluginDataRemoverImpl::Context
}
// IPC::Listener methods.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
IPC_BEGIN_MESSAGE_MAP(Context, message)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ClearSiteDataResult,
OnClearSiteDataResult)
@@ -185,7 +180,7 @@ class PluginDataRemoverImpl::Context
return true;
}
- virtual void OnChannelError() OVERRIDE {
+ void OnChannelError() override {
if (is_removing_) {
NOTREACHED() << "Channel error";
SignalDone();
@@ -197,7 +192,7 @@ class PluginDataRemoverImpl::Context
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
friend class base::DeleteHelper<Context>;
- virtual ~Context() {}
+ ~Context() override {}
IPC::Message* CreatePpapiClearSiteDataMsg(uint64 max_age) {
base::FilePath profile_path =
diff --git a/chromium/content/browser/plugin_data_remover_impl.h b/chromium/content/browser/plugin_data_remover_impl.h
index 6f4be32538a..704ebaaa637 100644
--- a/chromium/content/browser/plugin_data_remover_impl.h
+++ b/chromium/content/browser/plugin_data_remover_impl.h
@@ -17,10 +17,10 @@ namespace content {
class CONTENT_EXPORT PluginDataRemoverImpl : public PluginDataRemover {
public:
explicit PluginDataRemoverImpl(BrowserContext* browser_context);
- virtual ~PluginDataRemoverImpl();
+ ~PluginDataRemoverImpl() override;
// PluginDataRemover implementation:
- virtual base::WaitableEvent* StartRemoving(base::Time begin_time) OVERRIDE;
+ base::WaitableEvent* StartRemoving(base::Time begin_time) override;
// The plug-in whose data should be removed (usually Flash) is specified via
// its MIME type. This method sets a different MIME type in order to call a
diff --git a/chromium/content/browser/plugin_data_remover_impl_browsertest.cc b/chromium/content/browser/plugin_data_remover_impl_browsertest.cc
index 3dfe49285ba..97adba91bd0 100644
--- a/chromium/content/browser/plugin_data_remover_impl_browsertest.cc
+++ b/chromium/content/browser/plugin_data_remover_impl_browsertest.cc
@@ -28,7 +28,7 @@ class PluginDataRemoverTest : public ContentBrowserTest {
base::MessageLoop::current()->Quit();
}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
#if defined(OS_MACOSX)
base::FilePath browser_directory;
PathService::Get(base::DIR_MODULE, &browser_directory);
diff --git a/chromium/content/browser/plugin_loader_posix.cc b/chromium/content/browser/plugin_loader_posix.cc
index 7b278811343..22bc2b614c2 100644
--- a/chromium/content/browser/plugin_loader_posix.cc
+++ b/chromium/content/browser/plugin_loader_posix.cc
@@ -110,9 +110,9 @@ void PluginLoaderPosix::GetPluginsToLoad() {
base::Bind(&PluginLoaderPosix::LoadPluginsInternal,
make_scoped_refptr(this)));
- HISTOGRAM_TIMES("PluginLoaderPosix.GetPluginList",
- (base::TimeTicks::Now() - start_time) *
- base::Time::kMicrosecondsPerMillisecond);
+ LOCAL_HISTOGRAM_TIMES("PluginLoaderPosix.GetPluginList",
+ (base::TimeTicks::Now() - start_time) *
+ base::Time::kMicrosecondsPerMillisecond);
}
void PluginLoaderPosix::LoadPluginsInternal() {
@@ -209,9 +209,9 @@ bool PluginLoaderPosix::MaybeRunPendingCallbacks() {
}
callbacks_.clear();
- HISTOGRAM_TIMES("PluginLoaderPosix.LoadDone",
- (base::TimeTicks::Now() - load_start_time_)
- * base::Time::kMicrosecondsPerMillisecond);
+ LOCAL_HISTOGRAM_TIMES("PluginLoaderPosix.LoadDone",
+ (base::TimeTicks::Now() - load_start_time_) *
+ base::Time::kMicrosecondsPerMillisecond);
load_start_time_ = base::TimeTicks();
return true;
diff --git a/chromium/content/browser/plugin_loader_posix.h b/chromium/content/browser/plugin_loader_posix.h
index 42c6437bde2..5b1580c17fa 100644
--- a/chromium/content/browser/plugin_loader_posix.h
+++ b/chromium/content/browser/plugin_loader_posix.h
@@ -55,14 +55,14 @@ class CONTENT_EXPORT PluginLoaderPosix
void GetPlugins(const PluginService::GetPluginsCallback& callback);
// UtilityProcessHostClient:
- virtual void OnProcessCrashed(int exit_code) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnProcessCrashed(int exit_code) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// IPC::Sender:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
private:
- virtual ~PluginLoaderPosix();
+ ~PluginLoaderPosix() override;
// Called on the FILE thread to get the list of plugin paths to probe.
void GetPluginsToLoad();
diff --git a/chromium/content/browser/plugin_loader_posix_unittest.cc b/chromium/content/browser/plugin_loader_posix_unittest.cc
index 542b2c6cbb4..59e30b1ddd3 100644
--- a/chromium/content/browser/plugin_loader_posix_unittest.cc
+++ b/chromium/content/browser/plugin_loader_posix_unittest.cc
@@ -77,9 +77,7 @@ class PluginLoaderPosixTest : public testing::Test {
plugin_loader_(new MockPluginLoaderPosix) {
}
- virtual void SetUp() OVERRIDE {
- PluginServiceImpl::GetInstance()->Init();
- }
+ void SetUp() override { PluginServiceImpl::GetInstance()->Init(); }
base::MessageLoop* message_loop() { return &message_loop_; }
MockPluginLoaderPosix* plugin_loader() { return plugin_loader_.get(); }
diff --git a/chromium/content/browser/plugin_process_host.cc b/chromium/content/browser/plugin_process_host.cc
index 6c65dbf3c92..dd969d3e6c7 100644
--- a/chromium/content/browser/plugin_process_host.cc
+++ b/chromium/content/browser/plugin_process_host.cc
@@ -16,12 +16,13 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/synchronization/lock.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
@@ -46,7 +47,6 @@
#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
-#include "content/common/plugin_carbon_interpose_constants_mac.h"
#include "ui/gfx/rect.h"
#endif
@@ -57,6 +57,24 @@
namespace content {
+namespace {
+
+base::LazyInstance<std::map<base::ProcessId, WebPluginInfo> >
+ g_process_webplugin_info = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::Lock>::Leaky
+ g_process_webplugin_info_lock = LAZY_INSTANCE_INITIALIZER;
+}
+
+bool PluginProcessHost::GetWebPluginInfoFromPluginPid(base::ProcessId pid,
+ WebPluginInfo* info) {
+ base::AutoLock lock(g_process_webplugin_info_lock.Get());
+ if (!g_process_webplugin_info.Get().count(pid))
+ return false;
+
+ *info = g_process_webplugin_info.Get()[pid];
+ return true;
+}
+
#if defined(OS_WIN)
void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
// The window is destroyed at this point, we just care about its parent, which
@@ -85,30 +103,29 @@ class PluginSandboxedProcessLauncherDelegate
#endif // OS_POSIX
{}
- virtual ~PluginSandboxedProcessLauncherDelegate() {}
+ ~PluginSandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
- virtual bool ShouldSandbox() OVERRIDE {
+ virtual bool ShouldSandbox() override {
return false;
}
#elif defined(OS_POSIX)
- virtual int GetIpcFd() OVERRIDE {
- return ipc_fd_;
- }
+ base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); }
#endif // OS_WIN
private:
#if defined(OS_POSIX)
- int ipc_fd_;
+ base::ScopedFD ipc_fd_;
#endif // OS_POSIX
DISALLOW_COPY_AND_ASSIGN(PluginSandboxedProcessLauncherDelegate);
};
PluginProcessHost::PluginProcessHost()
+ : pid_(base::kNullProcessId)
#if defined(OS_MACOSX)
- : plugin_cursor_visible_(true)
+ , plugin_cursor_visible_(true)
#endif
{
process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_PLUGIN, this));
@@ -145,6 +162,11 @@ PluginProcessHost::~PluginProcessHost() {
#endif
// Cancel all pending and sent requests.
CancelRequests();
+
+ {
+ base::AutoLock lock(g_process_webplugin_info_lock.Get());
+ g_process_webplugin_info.Get()[pid_] = info_;
+ }
}
bool PluginProcessHost::Send(IPC::Message* message) {
@@ -161,8 +183,9 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
// Build command line for plugin. When we have a plugin launcher, we can't
// allow "self" on linux and we need the real file path.
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
- CommandLine::StringType plugin_launcher =
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringType plugin_launcher =
browser_command_line.GetSwitchValueNative(switches::kPluginLauncher);
#if defined(OS_MACOSX)
@@ -181,7 +204,7 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
if (exe_path.empty())
return false;
- CommandLine* cmd_line = new CommandLine(exe_path);
+ base::CommandLine* cmd_line = new base::CommandLine(exe_path);
// Put the process type and plugin path first so they're easier to see
// in process listings using native process management tools.
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kPluginProcess);
@@ -225,25 +248,6 @@ bool PluginProcessHost::Init(const WebPluginInfo& info) {
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
-#if defined(OS_POSIX)
- base::EnvironmentMap env;
-#if defined(OS_MACOSX) && !defined(__LP64__)
- if (browser_command_line.HasSwitch(switches::kEnableCarbonInterposing)) {
- std::string interpose_list = GetContentClient()->GetCarbonInterposePath();
- if (!interpose_list.empty()) {
- // Add our interposing library for Carbon. This is stripped back out in
- // plugin_main.cc, so changes here should be reflected there.
- const char* existing_list = getenv(kDYLDInsertLibrariesKey);
- if (existing_list) {
- interpose_list.insert(0, ":");
- interpose_list.insert(0, existing_list);
- }
- }
- env[kDYLDInsertLibrariesKey] = interpose_list;
- }
-#endif
-#endif
-
process_->Launch(
new PluginSandboxedProcessLauncherDelegate(process_->GetHost()),
cmd_line);
@@ -284,8 +288,6 @@ bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
OnPluginWindowDestroyed)
#endif
#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSelectWindow,
- OnPluginSelectWindow)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginShowWindow,
OnPluginShowWindow)
IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginHideWindow,
@@ -305,6 +307,12 @@ void PluginProcessHost::OnChannelConnected(int32 peer_pid) {
}
pending_requests_.clear();
+
+ pid_ = peer_pid;
+ {
+ base::AutoLock lock(g_process_webplugin_info_lock.Get());
+ g_process_webplugin_info.Get()[pid_] = info_;
+ }
}
void PluginProcessHost::OnChannelError() {
diff --git a/chromium/content/browser/plugin_process_host.h b/chromium/content/browser/plugin_process_host.h
index 71c758039ba..1e8b67812ac 100644
--- a/chromium/content/browser/plugin_process_host.h
+++ b/chromium/content/browser/plugin_process_host.h
@@ -16,14 +16,15 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/process/process_handle.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/common/process_type.h"
+#include "content/public/common/resource_type.h"
#include "content/public/common/webplugininfo.h"
#include "ipc/ipc_channel_proxy.h"
#include "ui/gfx/native_widget_types.h"
-#include "webkit/common/resource_type.h"
struct ResourceHostMsg_Request;
@@ -74,10 +75,10 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
};
PluginProcessHost();
- virtual ~PluginProcessHost();
+ ~PluginProcessHost() override;
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// Initialize the new plugin process, returning true on success. This must
// be called before the object can be used.
@@ -86,9 +87,9 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
// Force the plugin process to shutdown (cleanly).
void ForceShutdown();
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
// Tells the plugin process to create a new channel for communication with a
// renderer. When the plugin process responds with the channel name,
@@ -120,6 +121,12 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
void AddWindow(HWND window);
#endif
+ // Given a pid of a plugin process, returns the plugin information in |info|
+ // if we know about that process. Otherwise returns false.
+ // This method can be called on any thread.
+ static bool GetWebPluginInfoFromPluginPid(base::ProcessId pid,
+ WebPluginInfo* info);
+
private:
// Sends a message to the plugin process to request creation of a new channel
// for the given mime type.
@@ -134,16 +141,14 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
#endif
#if defined(OS_MACOSX)
- void OnPluginSelectWindow(uint32 window_id, gfx::Rect window_rect,
- bool modal);
void OnPluginShowWindow(uint32 window_id, gfx::Rect window_rect,
bool modal);
void OnPluginHideWindow(uint32 window_id, gfx::Rect window_rect);
void OnPluginSetCursorVisibility(bool visible);
#endif
- virtual bool CanShutdown() OVERRIDE;
- virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+ bool CanShutdown() override;
+ void OnProcessCrashed(int exit_code) override;
void CancelRequests();
@@ -163,6 +168,9 @@ class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
// Information about the plugin.
WebPluginInfo info_;
+ // The pid of the plugin process.
+ int pid_;
+
#if defined(OS_WIN)
// Tracks plugin parent windows created on the UI thread.
std::set<HWND> plugin_parent_windows_set_;
diff --git a/chromium/content/browser/plugin_process_host_mac.cc b/chromium/content/browser/plugin_process_host_mac.cc
index 93503009f3d..f3ad53f217b 100644
--- a/chromium/content/browser/plugin_process_host_mac.cc
+++ b/chromium/content/browser/plugin_process_host_mac.cc
@@ -19,14 +19,6 @@
namespace content {
-void PluginProcessHost::OnPluginSelectWindow(uint32 window_id,
- gfx::Rect window_rect,
- bool modal) {
- plugin_visible_windows_set_.insert(window_id);
- if (modal)
- plugin_modal_windows_set_.insert(window_id);
-}
-
void PluginProcessHost::OnPluginShowWindow(uint32 window_id,
gfx::Rect window_rect,
bool modal) {
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index a2c3170baf5..49b66389dd3 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -11,7 +11,6 @@
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
-#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
@@ -157,15 +156,6 @@ PluginServiceImpl::PluginServiceImpl()
}
PluginServiceImpl::~PluginServiceImpl() {
-#if defined(OS_WIN)
- // Release the events since they're owned by RegKey, not WaitableEvent.
- hkcu_watcher_.StopWatching();
- hklm_watcher_.StopWatching();
- if (hkcu_event_)
- hkcu_event_->Release();
- if (hklm_event_)
- hklm_event_->Release();
-#endif
// Make sure no plugin channel requests have been leaked.
DCHECK(pending_plugin_clients_.empty());
}
@@ -178,7 +168,8 @@ void PluginServiceImpl::Init() {
RegisterPepperPlugins();
// Load any specified on the command line as well.
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
base::FilePath path =
command_line->GetSwitchValuePath(switches::kLoadPlugin);
if (!path.empty())
@@ -199,24 +190,18 @@ void PluginServiceImpl::StartWatchingPlugins() {
if (hkcu_key_.Create(HKEY_CURRENT_USER,
kRegistryMozillaPlugins,
KEY_NOTIFY) == ERROR_SUCCESS) {
- if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
- hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
- base::WaitableEventWatcher::EventCallback callback =
- base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
- base::Unretained(this));
- hkcu_watcher_.StartWatching(hkcu_event_.get(), callback);
- }
+ base::win::RegKey::ChangeCallback callback =
+ base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
+ base::Unretained(&hkcu_key_));
+ hkcu_key_.StartWatching(callback);
}
if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
kRegistryMozillaPlugins,
KEY_NOTIFY) == ERROR_SUCCESS) {
- if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
- hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
- base::WaitableEventWatcher::EventCallback callback =
- base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
- base::Unretained(this));
- hklm_watcher_.StartWatching(hklm_event_.get(), callback);
- }
+ base::win::RegKey::ChangeCallback callback =
+ base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
+ base::Unretained(&hklm_key_));
+ hklm_key_.StartWatching(callback);
}
#endif
#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
@@ -633,7 +618,7 @@ void PluginServiceImpl::GetPluginsOnIOThread(
// If we switch back to loading plugins in process, then we need to make
// sure g_thread_init() gets called since plugins may call glib at load.
- if (!plugin_loader_)
+ if (!plugin_loader_.get())
plugin_loader_ = new PluginLoaderPosix;
plugin_loader_->GetPlugins(
@@ -641,22 +626,16 @@ void PluginServiceImpl::GetPluginsOnIOThread(
}
#endif
-void PluginServiceImpl::OnWaitableEventSignaled(
- base::WaitableEvent* waitable_event) {
#if defined(OS_WIN)
- if (waitable_event == hkcu_event_) {
- hkcu_key_.StartWatching();
- } else {
- hklm_key_.StartWatching();
- }
+void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) {
+ key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged,
+ base::Unretained(this),
+ base::Unretained(key)));
PluginList::Singleton()->RefreshPlugins();
PurgePluginListCache(NULL, false);
-#else
- // This event should only get signaled on a Windows machine.
- NOTREACHED();
-#endif // defined(OS_WIN)
}
+#endif // defined(OS_WIN)
void PluginServiceImpl::RegisterPepperPlugins() {
ComputePepperPluginList(&ppapi_plugins_);
@@ -840,10 +819,15 @@ bool PluginServiceImpl::GetPluginInfoFromWindow(
if (!IsPluginWindow(window))
return false;
- GetPluginPropertyFromWindow(
- window, kPluginNameAtomProperty, plugin_name);
- GetPluginPropertyFromWindow(
- window, kPluginVersionAtomProperty, plugin_version);
+
+ DWORD process_id = 0;
+ GetWindowThreadProcessId(window, &process_id);
+ WebPluginInfo info;
+ if (!PluginProcessHost::GetWebPluginInfoFromPluginPid(process_id, &info))
+ return false;
+
+ *plugin_name = info.name;
+ *plugin_version = info.version;
return true;
}
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index 861889c7a36..8770974a973 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -8,6 +8,10 @@
#ifndef CONTENT_BROWSER_PLUGIN_SERVICE_IMPL_H_
#define CONTENT_BROWSER_PLUGIN_SERVICE_IMPL_H_
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
#include <map>
#include <set>
#include <vector>
@@ -65,58 +69,56 @@ class CONTENT_EXPORT PluginServiceImpl
static PluginServiceImpl* GetInstance();
// PluginService implementation:
- virtual void Init() OVERRIDE;
- virtual void StartWatchingPlugins() OVERRIDE;
- virtual bool GetPluginInfoArray(
- const GURL& url,
- const std::string& mime_type,
- bool allow_wildcard,
- std::vector<WebPluginInfo>* info,
- std::vector<std::string>* actual_mime_types) OVERRIDE;
- virtual bool GetPluginInfo(int render_process_id,
- int render_frame_id,
- ResourceContext* context,
- const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- bool allow_wildcard,
- bool* is_stale,
- WebPluginInfo* info,
- std::string* actual_mime_type) OVERRIDE;
- virtual bool GetPluginInfoByPath(const base::FilePath& plugin_path,
- WebPluginInfo* info) OVERRIDE;
- virtual base::string16 GetPluginDisplayNameByPath(
- const base::FilePath& path) OVERRIDE;
- virtual void GetPlugins(const GetPluginsCallback& callback) OVERRIDE;
- virtual PepperPluginInfo* GetRegisteredPpapiPluginInfo(
- const base::FilePath& plugin_path) OVERRIDE;
- virtual void SetFilter(PluginServiceFilter* filter) OVERRIDE;
- virtual PluginServiceFilter* GetFilter() OVERRIDE;
- virtual void ForcePluginShutdown(const base::FilePath& plugin_path) OVERRIDE;
- virtual bool IsPluginUnstable(const base::FilePath& plugin_path) OVERRIDE;
- virtual void RefreshPlugins() OVERRIDE;
- virtual void AddExtraPluginPath(const base::FilePath& path) OVERRIDE;
- virtual void RemoveExtraPluginPath(const base::FilePath& path) OVERRIDE;
- virtual void AddExtraPluginDir(const base::FilePath& path) OVERRIDE;
- virtual void RegisterInternalPlugin(
- const WebPluginInfo& info, bool add_at_beginning) OVERRIDE;
- virtual void UnregisterInternalPlugin(const base::FilePath& path) OVERRIDE;
- virtual void GetInternalPlugins(
- std::vector<WebPluginInfo>* plugins) OVERRIDE;
- virtual bool NPAPIPluginsSupported() OVERRIDE;
- virtual void DisablePluginsDiscoveryForTesting() OVERRIDE;
+ void Init() override;
+ void StartWatchingPlugins() override;
+ bool GetPluginInfoArray(const GURL& url,
+ const std::string& mime_type,
+ bool allow_wildcard,
+ std::vector<WebPluginInfo>* info,
+ std::vector<std::string>* actual_mime_types) override;
+ bool GetPluginInfo(int render_process_id,
+ int render_frame_id,
+ ResourceContext* context,
+ const GURL& url,
+ const GURL& page_url,
+ const std::string& mime_type,
+ bool allow_wildcard,
+ bool* is_stale,
+ WebPluginInfo* info,
+ std::string* actual_mime_type) override;
+ bool GetPluginInfoByPath(const base::FilePath& plugin_path,
+ WebPluginInfo* info) override;
+ base::string16 GetPluginDisplayNameByPath(
+ const base::FilePath& path) override;
+ void GetPlugins(const GetPluginsCallback& callback) override;
+ PepperPluginInfo* GetRegisteredPpapiPluginInfo(
+ const base::FilePath& plugin_path) override;
+ void SetFilter(PluginServiceFilter* filter) override;
+ PluginServiceFilter* GetFilter() override;
+ void ForcePluginShutdown(const base::FilePath& plugin_path) override;
+ bool IsPluginUnstable(const base::FilePath& plugin_path) override;
+ void RefreshPlugins() override;
+ void AddExtraPluginPath(const base::FilePath& path) override;
+ void RemoveExtraPluginPath(const base::FilePath& path) override;
+ void AddExtraPluginDir(const base::FilePath& path) override;
+ void RegisterInternalPlugin(const WebPluginInfo& info,
+ bool add_at_beginning) override;
+ void UnregisterInternalPlugin(const base::FilePath& path) override;
+ void GetInternalPlugins(std::vector<WebPluginInfo>* plugins) override;
+ bool NPAPIPluginsSupported() override;
+ void DisablePluginsDiscoveryForTesting() override;
#if defined(OS_MACOSX)
- virtual void AppActivated() OVERRIDE;
+ void AppActivated() override;
#elif defined(OS_WIN)
virtual bool GetPluginInfoFromWindow(HWND window,
base::string16* plugin_name,
- base::string16* plugin_version) OVERRIDE;
+ base::string16* plugin_version) override;
// Returns true iff the given HWND is a plugin.
bool IsPluginWindow(HWND window);
#endif
- virtual bool PpapiDevChannelSupported(BrowserContext* browser_context,
- const GURL& document_url) OVERRIDE;
+ bool PpapiDevChannelSupported(BrowserContext* browser_context,
+ const GURL& document_url) override;
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. This will start a process to host the
@@ -160,9 +162,11 @@ class CONTENT_EXPORT PluginServiceImpl
// Creates the PluginServiceImpl object, but doesn't actually build the plugin
// list yet. It's generated lazily.
PluginServiceImpl();
- virtual ~PluginServiceImpl();
+ ~PluginServiceImpl() override;
- void OnWaitableEventSignaled(base::WaitableEvent* waitable_event);
+#if defined(OS_WIN)
+ void OnKeyChanged(base::win::RegKey* key);
+#endif
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. Returns NULL if no process has been
@@ -220,10 +224,6 @@ class CONTENT_EXPORT PluginServiceImpl
// Registry keys for getting notifications when new plugins are installed.
base::win::RegKey hkcu_key_;
base::win::RegKey hklm_key_;
- scoped_ptr<base::WaitableEvent> hkcu_event_;
- scoped_ptr<base::WaitableEvent> hklm_event_;
- base::WaitableEventWatcher hkcu_watcher_;
- base::WaitableEventWatcher hklm_watcher_;
#endif
#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
diff --git a/chromium/content/browser/plugin_service_impl_browsertest.cc b/chromium/content/browser/plugin_service_impl_browsertest.cc
index 7a3271e6c78..b8a3dfb2248 100644
--- a/chromium/content/browser/plugin_service_impl_browsertest.cc
+++ b/chromium/content/browser/plugin_service_impl_browsertest.cc
@@ -42,21 +42,19 @@ class MockPluginProcessHostClient : public PluginProcessHost::Client,
expect_fail_(expect_fail) {
}
- virtual ~MockPluginProcessHostClient() {
+ ~MockPluginProcessHostClient() override {
if (channel_)
BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, channel_);
}
// PluginProcessHost::Client implementation.
- virtual int ID() OVERRIDE { return 42; }
- virtual bool OffTheRecord() OVERRIDE { return false; }
- virtual ResourceContext* GetResourceContext() OVERRIDE {
- return context_;
- }
- virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {}
- virtual void OnSentPluginChannelRequest() OVERRIDE {}
+ int ID() override { return 42; }
+ bool OffTheRecord() override { return false; }
+ ResourceContext* GetResourceContext() override { return context_; }
+ void OnFoundPluginProcessHost(PluginProcessHost* host) override {}
+ void OnSentPluginChannelRequest() override {}
- virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
+ void OnChannelOpened(const IPC::ChannelHandle& handle) override {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_TRUE(set_plugin_info_called_);
ASSERT_TRUE(!channel_);
@@ -64,36 +62,28 @@ class MockPluginProcessHostClient : public PluginProcessHost::Client,
ASSERT_TRUE(channel_->Connect());
}
- virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
+ void SetPluginInfo(const WebPluginInfo& info) override {
ASSERT_TRUE(info.mime_types.size());
ASSERT_EQ(kNPAPITestPluginMimeType, info.mime_types[0].mime_type);
set_plugin_info_called_ = true;
}
- virtual void OnError() OVERRIDE {
- Fail();
- }
+ void OnError() override { Fail(); }
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
Fail();
return false;
}
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
+ void OnChannelConnected(int32 peer_pid) override {
if (expect_fail_)
FAIL();
QuitMessageLoop();
}
- virtual void OnChannelError() OVERRIDE {
- Fail();
- }
+ void OnChannelError() override { Fail(); }
#if defined(OS_POSIX)
- virtual void OnChannelDenied() OVERRIDE {
- Fail();
- }
- virtual void OnChannelListenError() OVERRIDE {
- Fail();
- }
+ void OnChannelDenied() override { Fail(); }
+ void OnChannelListenError() override { Fail(); }
#endif
private:
@@ -119,17 +109,19 @@ class MockPluginServiceFilter : public content::PluginServiceFilter {
public:
MockPluginServiceFilter() {}
- virtual bool IsPluginAvailable(
- int render_process_id,
- int render_view_id,
- const void* context,
- const GURL& url,
- const GURL& policy_url,
- WebPluginInfo* plugin) OVERRIDE { return true; }
-
- virtual bool CanLoadPlugin(
- int render_process_id,
- const base::FilePath& path) OVERRIDE { return false; }
+ bool IsPluginAvailable(int render_process_id,
+ int render_view_id,
+ const void* context,
+ const GURL& url,
+ const GURL& policy_url,
+ WebPluginInfo* plugin) override {
+ return true;
+ }
+
+ bool CanLoadPlugin(int render_process_id,
+ const base::FilePath& path) override {
+ return false;
+ }
};
class PluginServiceTest : public ContentBrowserTest {
@@ -140,7 +132,7 @@ class PluginServiceTest : public ContentBrowserTest {
return shell()->web_contents()->GetBrowserContext()->GetResourceContext();
}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
#if defined(OS_MACOSX)
base::FilePath browser_directory;
PathService::Get(base::DIR_MODULE, &browser_directory);
@@ -193,7 +185,7 @@ class MockCanceledPluginServiceClient : public PluginProcessHost::Client {
// Client implementation.
MOCK_METHOD0(ID, int());
- virtual ResourceContext* GetResourceContext() OVERRIDE {
+ virtual ResourceContext* GetResourceContext() override {
get_resource_context_called_ = true;
return context_;
}
@@ -254,16 +246,16 @@ class MockCanceledBeforeSentPluginProcessHostClient
on_found_plugin_process_host_called_(false),
host_(NULL) {}
- virtual ~MockCanceledBeforeSentPluginProcessHostClient() {}
+ ~MockCanceledBeforeSentPluginProcessHostClient() override {}
// Client implementation.
- virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
+ void SetPluginInfo(const WebPluginInfo& info) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ASSERT_TRUE(info.mime_types.size());
ASSERT_EQ(kNPAPITestPluginMimeType, info.mime_types[0].mime_type);
set_plugin_info_called_ = true;
}
- virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
+ void OnFoundPluginProcessHost(PluginProcessHost* host) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
set_on_found_plugin_process_host_called();
set_host(host);
@@ -326,21 +318,21 @@ class MockCanceledAfterSentPluginProcessHostClient
ResourceContext* context)
: MockCanceledBeforeSentPluginProcessHostClient(context),
on_sent_plugin_channel_request_called_(false) {}
- virtual ~MockCanceledAfterSentPluginProcessHostClient() {}
+ ~MockCanceledAfterSentPluginProcessHostClient() override {}
// Client implementation.
- virtual int ID() OVERRIDE { return 42; }
- virtual bool OffTheRecord() OVERRIDE { return false; }
+ int ID() override { return 42; }
+ bool OffTheRecord() override { return false; }
// We override this guy again since we don't want to cancel yet.
- virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
+ void OnFoundPluginProcessHost(PluginProcessHost* host) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
set_on_found_plugin_process_host_called();
set_host(host);
}
- virtual void OnSentPluginChannelRequest() OVERRIDE {
+ void OnSentPluginChannelRequest() override {
on_sent_plugin_channel_request_called_ = true;
host()->CancelSentRequest(this);
BrowserThread::PostTask(
diff --git a/chromium/content/browser/power_monitor_message_broadcaster.cc b/chromium/content/browser/power_monitor_message_broadcaster.cc
index 23de161b05c..e862abbfe74 100644
--- a/chromium/content/browser/power_monitor_message_broadcaster.cc
+++ b/chromium/content/browser/power_monitor_message_broadcaster.cc
@@ -24,6 +24,13 @@ PowerMonitorMessageBroadcaster::~PowerMonitorMessageBroadcaster() {
power_monitor->RemoveObserver(this);
}
+void PowerMonitorMessageBroadcaster::Init() {
+ base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+ // Unit tests does not initialize the PowerMonitor.
+ if (power_monitor)
+ OnPowerStateChange(power_monitor->IsOnBatteryPower());
+}
+
void PowerMonitorMessageBroadcaster::OnPowerStateChange(bool on_battery_power) {
sender_->Send(new PowerMonitorMsg_PowerStateChange(on_battery_power));
}
diff --git a/chromium/content/browser/power_monitor_message_broadcaster.h b/chromium/content/browser/power_monitor_message_broadcaster.h
index 082ba670bbd..3221fadc690 100644
--- a/chromium/content/browser/power_monitor_message_broadcaster.h
+++ b/chromium/content/browser/power_monitor_message_broadcaster.h
@@ -21,12 +21,14 @@ class CONTENT_EXPORT PowerMonitorMessageBroadcaster
: public base::PowerObserver {
public:
explicit PowerMonitorMessageBroadcaster(IPC::Sender* sender);
- virtual ~PowerMonitorMessageBroadcaster();
+ ~PowerMonitorMessageBroadcaster() override;
// Implement PowerObserver.
- virtual void OnPowerStateChange(bool on_battery_power) OVERRIDE;
- virtual void OnSuspend() OVERRIDE;
- virtual void OnResume() OVERRIDE;
+ void OnPowerStateChange(bool on_battery_power) override;
+ void OnSuspend() override;
+ void OnResume() override;
+
+ void Init();
private:
IPC::Sender* sender_;
diff --git a/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc b/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc
index 515508266cf..32deb1ea09b 100644
--- a/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc
+++ b/chromium/content/browser/power_monitor_message_broadcaster_unittest.cc
@@ -17,9 +17,9 @@ class PowerMonitorMessageSender : public IPC::Sender {
suspends_(0),
resumes_(0) {
}
- virtual ~PowerMonitorMessageSender() {}
+ ~PowerMonitorMessageSender() override {}
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
switch (msg->type()) {
case PowerMonitorMsg_Suspend::ID:
suspends_++;
@@ -53,7 +53,7 @@ class PowerMonitorMessageBroadcasterTest : public testing::Test {
power_monitor_.reset(new base::PowerMonitor(
scoped_ptr<base::PowerMonitorSource>(power_monitor_source_)));
}
- virtual ~PowerMonitorMessageBroadcasterTest() {};
+ ~PowerMonitorMessageBroadcasterTest() override {}
base::PowerMonitorTestSource* source() { return power_monitor_source_; }
base::PowerMonitor* monitor() { return power_monitor_.get(); }
@@ -69,6 +69,10 @@ TEST_F(PowerMonitorMessageBroadcasterTest, PowerMessageBroadcast) {
PowerMonitorMessageSender sender;
PowerMonitorMessageBroadcaster broadcaster(&sender);
+ // Calling Init should invoke a power state change.
+ broadcaster.Init();
+ EXPECT_EQ(sender.power_state_changes(), 1);
+
// Sending resume when not suspended should have no effect.
source()->GenerateResumeEvent();
EXPECT_EQ(sender.resumes(), 0);
@@ -91,19 +95,19 @@ TEST_F(PowerMonitorMessageBroadcasterTest, PowerMessageBroadcast) {
// Pretend the device has gone on battery power
source()->GeneratePowerStateEvent(true);
- EXPECT_EQ(sender.power_state_changes(), 1);
+ EXPECT_EQ(sender.power_state_changes(), 2);
// Repeated indications the device is on battery power should be suppressed.
source()->GeneratePowerStateEvent(true);
- EXPECT_EQ(sender.power_state_changes(), 1);
+ EXPECT_EQ(sender.power_state_changes(), 2);
// Pretend the device has gone off battery power
source()->GeneratePowerStateEvent(false);
- EXPECT_EQ(sender.power_state_changes(), 2);
+ EXPECT_EQ(sender.power_state_changes(), 3);
// Repeated indications the device is off battery power should be suppressed.
source()->GeneratePowerStateEvent(false);
- EXPECT_EQ(sender.power_state_changes(), 2);
+ EXPECT_EQ(sender.power_state_changes(), 3);
}
} // namespace base
diff --git a/chromium/content/browser/power_profiler/power_data_provider.h b/chromium/content/browser/power_profiler/power_data_provider.h
index 85f67e7f5fb..897bc9b636c 100644
--- a/chromium/content/browser/power_profiler/power_data_provider.h
+++ b/chromium/content/browser/power_profiler/power_data_provider.h
@@ -21,6 +21,12 @@ typedef std::vector<PowerEvent> PowerEventVector;
// A class used to get power usage.
class PowerDataProvider {
public:
+ enum AccuracyLevel {
+ High,
+ Moderate,
+ Low
+ };
+
static scoped_ptr<PowerDataProvider> Create();
PowerDataProvider() {}
@@ -31,6 +37,9 @@ class PowerDataProvider {
// Returns sampling rate at which the provider can operate.
virtual base::TimeDelta GetSamplingRate() = 0;
+
+ // Returns accuracy level of the provider.
+ virtual AccuracyLevel GetAccuracyLevel() = 0;
};
} // namespace content
diff --git a/chromium/content/browser/power_profiler/power_data_provider_ia_win.h b/chromium/content/browser/power_profiler/power_data_provider_ia_win.h
index 2c7e489328d..427a5fa202a 100644
--- a/chromium/content/browser/power_profiler/power_data_provider_ia_win.h
+++ b/chromium/content/browser/power_profiler/power_data_provider_ia_win.h
@@ -18,8 +18,9 @@ class PowerDataProviderIA : public PowerDataProvider {
virtual ~PowerDataProviderIA();
bool Initialize();
- virtual PowerEventVector GetData() OVERRIDE;
- virtual base::TimeDelta GetSamplingRate() OVERRIDE;
+ virtual PowerEventVector GetData() override;
+ virtual base::TimeDelta GetSamplingRate() override;
+ virtual AccuracyLevel GetAccuracyLevel() override { return High; }
private:
CIntelPowerGadgetLib energy_lib_;
diff --git a/chromium/content/browser/power_profiler/power_profiler_service.cc b/chromium/content/browser/power_profiler/power_profiler_service.cc
index 026b42ab893..84ddb1bd15a 100644
--- a/chromium/content/browser/power_profiler/power_profiler_service.cc
+++ b/chromium/content/browser/power_profiler/power_profiler_service.cc
@@ -42,10 +42,23 @@ PowerProfilerService::PowerProfilerService(
PowerProfilerService::~PowerProfilerService() {
}
-bool PowerProfilerService::IsAvailable() {
+bool PowerProfilerService::IsAvailable() const {
return status_ != UNINITIALIZED;
}
+std::string PowerProfilerService::GetAccuracyLevel() const {
+ DCHECK(IsAvailable());
+ switch (data_provider_->GetAccuracyLevel()) {
+ case PowerDataProvider::High:
+ return "High";
+ case PowerDataProvider::Moderate:
+ return "Moderate";
+ case PowerDataProvider::Low:
+ return "Low";
+ }
+ return "";
+}
+
PowerProfilerService* PowerProfilerService::GetInstance() {
return Singleton<PowerProfilerService>::get();
}
diff --git a/chromium/content/browser/power_profiler/power_profiler_service.h b/chromium/content/browser/power_profiler/power_profiler_service.h
index 35f2f65cce3..4daae28f907 100644
--- a/chromium/content/browser/power_profiler/power_profiler_service.h
+++ b/chromium/content/browser/power_profiler/power_profiler_service.h
@@ -25,7 +25,8 @@ class CONTENT_EXPORT PowerProfilerService {
void AddObserver(PowerProfilerObserver* observer);
void RemoveObserver(PowerProfilerObserver* observer);
- bool IsAvailable();
+ bool IsAvailable() const;
+ std::string GetAccuracyLevel() const;
virtual ~PowerProfilerService();
diff --git a/chromium/content/browser/power_profiler/power_profiler_service_unittest.cc b/chromium/content/browser/power_profiler/power_profiler_service_unittest.cc
index f7f77dc82dd..3386b6f618c 100644
--- a/chromium/content/browser/power_profiler/power_profiler_service_unittest.cc
+++ b/chromium/content/browser/power_profiler/power_profiler_service_unittest.cc
@@ -19,9 +19,9 @@ const int kDefaultSamplePeriodMs = 50;
class TestPowerDataProvider : public PowerDataProvider {
public:
TestPowerDataProvider(int count) : num_events_to_send_(count) {}
- virtual ~TestPowerDataProvider() {}
+ ~TestPowerDataProvider() override {}
- virtual PowerEventVector GetData() OVERRIDE {
+ PowerEventVector GetData() override {
PowerEventVector events;
if (num_events_to_send_ == 0)
return events;
@@ -36,10 +36,12 @@ class TestPowerDataProvider : public PowerDataProvider {
return events;
}
- virtual base::TimeDelta GetSamplingRate() OVERRIDE {
+ base::TimeDelta GetSamplingRate() override {
return base::TimeDelta::FromMilliseconds(kDefaultSamplePeriodMs);
}
+ AccuracyLevel GetAccuracyLevel() override { return High; }
+
private:
int num_events_to_send_;
DISALLOW_COPY_AND_ASSIGN(TestPowerDataProvider);
@@ -50,9 +52,9 @@ class TestPowerProfilerObserver : public PowerProfilerObserver {
TestPowerProfilerObserver()
: valid_event_count_(0),
total_num_events_received_(0) {}
- virtual ~TestPowerProfilerObserver() {}
+ ~TestPowerProfilerObserver() override {}
- virtual void OnPowerEvent(const PowerEventVector& events) OVERRIDE {
+ void OnPowerEvent(const PowerEventVector& events) override {
if (IsValidEvent(events[0]))
++valid_event_count_;
@@ -109,7 +111,7 @@ class PowerProfilerServiceTest : public testing::Test {
protected:
PowerProfilerServiceTest() : ui_thread_(BrowserThread::UI, &message_loop_) {}
- virtual ~PowerProfilerServiceTest() {}
+ ~PowerProfilerServiceTest() override {}
void RegisterQuitClosure(base::Closure closure) {
observer_.set_quit_closure(closure);
diff --git a/chromium/content/browser/power_save_blocker_android.cc b/chromium/content/browser/power_save_blocker_android.cc
index 79da1a907ed..2f79ef99f27 100644
--- a/chromium/content/browser/power_save_blocker_android.cc
+++ b/chromium/content/browser/power_save_blocker_android.cc
@@ -62,7 +62,7 @@ PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
}
PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- if (delegate_) {
+ if (delegate_.get()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Delegate::RemoveBlock, delegate_));
diff --git a/chromium/content/browser/power_save_blocker_impl.h b/chromium/content/browser/power_save_blocker_impl.h
index 948aced4cb4..39ba8f24f8e 100644
--- a/chromium/content/browser/power_save_blocker_impl.h
+++ b/chromium/content/browser/power_save_blocker_impl.h
@@ -14,7 +14,7 @@ namespace content {
class PowerSaveBlockerImpl : public PowerSaveBlocker {
public:
PowerSaveBlockerImpl(PowerSaveBlockerType type, const std::string& reason);
- virtual ~PowerSaveBlockerImpl();
+ ~PowerSaveBlockerImpl() override;
#if defined(OS_ANDROID)
// In Android platform, the kPowerSaveBlockPreventDisplaySleep type of
diff --git a/chromium/content/browser/power_save_blocker_win.cc b/chromium/content/browser/power_save_blocker_win.cc
index 727600dff14..4cbecf4447a 100644
--- a/chromium/content/browser/power_save_blocker_win.cc
+++ b/chromium/content/browser/power_save_blocker_win.cc
@@ -49,7 +49,7 @@ HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type, const std::string& reason) {
if (!handle.IsValid())
return INVALID_HANDLE_VALUE;
- if (PowerSetRequestFn(handle, type))
+ if (PowerSetRequestFn(handle.Get(), type))
return handle.Take();
// Something went wrong.
@@ -76,7 +76,7 @@ void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) {
if (!PowerClearRequestFn)
return;
- BOOL success = PowerClearRequestFn(request_handle, type);
+ BOOL success = PowerClearRequestFn(request_handle.Get(), type);
DCHECK(success);
}
diff --git a/chromium/content/browser/power_save_blocker_x11.cc b/chromium/content/browser/power_save_blocker_x11.cc
index e5fb4e5f3df..f1d028c7f45 100644
--- a/chromium/content/browser/power_save_blocker_x11.cc
+++ b/chromium/content/browser/power_save_blocker_x11.cc
@@ -200,7 +200,7 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) {
// reason: The reason for the inhibit
// flags: Flags that spefify what should be inhibited
message_writer->AppendString(
- CommandLine::ForCurrentProcess()->GetProgram().value());
+ base::CommandLine::ForCurrentProcess()->GetProgram().value());
message_writer->AppendUint32(0); // should be toplevel_xid
message_writer->AppendString(reason_);
{
@@ -228,7 +228,7 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) {
// app_id: The application identifier
// reason: The reason for the inhibit
message_writer->AppendString(
- CommandLine::ForCurrentProcess()->GetProgram().value());
+ base::CommandLine::ForCurrentProcess()->GetProgram().value());
message_writer->AppendString(reason_);
break;
}
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index fc6a75ebed7..22b69ba76d2 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -48,10 +48,10 @@ class PpapiPluginSandboxedProcessLauncherDelegate
#endif // OS_POSIX
is_broker_(is_broker) {}
- virtual ~PpapiPluginSandboxedProcessLauncherDelegate() {}
+ ~PpapiPluginSandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
- virtual bool ShouldSandbox() OVERRIDE {
+ virtual bool ShouldSandbox() override {
return !is_broker_;
}
@@ -69,21 +69,20 @@ class PpapiPluginSandboxedProcessLauncherDelegate
}
#elif defined(OS_POSIX)
- virtual bool ShouldUseZygote() OVERRIDE {
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
- CommandLine::StringType plugin_launcher = browser_command_line
+ bool ShouldUseZygote() override {
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringType plugin_launcher = browser_command_line
.GetSwitchValueNative(switches::kPpapiPluginLauncher);
return !is_broker_ && plugin_launcher.empty() && info_.is_sandboxed;
}
- virtual int GetIpcFd() OVERRIDE {
- return ipc_fd_;
- }
+ base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); }
#endif // OS_WIN
private:
#if defined(OS_POSIX)
const PepperPluginInfo& info_;
- int ipc_fd_;
+ base::ScopedFD ipc_fd_;
#endif // OS_POSIX
bool is_broker_;
@@ -100,13 +99,13 @@ class PpapiPluginProcessHost::PluginNetworkObserver
net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
}
- virtual ~PluginNetworkObserver() {
+ ~PluginNetworkObserver() override {
net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
}
// IPAddressObserver implementation.
- virtual void OnIPAddressChanged() OVERRIDE {
+ void OnIPAddressChanged() override {
// TODO(brettw) bug 90246: This doesn't seem correct. The online/offline
// notification seems like it should be sufficient, but I don't see that
// when I unplug and replug my network cable. Sending this notification when
@@ -117,8 +116,8 @@ class PpapiPluginProcessHost::PluginNetworkObserver
}
// ConnectionTypeObserver implementation.
- virtual void OnConnectionTypeChanged(
- net::NetworkChangeNotifier::ConnectionType type) OVERRIDE {
+ void OnConnectionTypeChanged(
+ net::NetworkChangeNotifier::ConnectionType type) override {
process_host_->Send(new PpapiMsg_SetNetworkState(
type != net::NetworkChangeNotifier::CONNECTION_NONE));
}
@@ -288,8 +287,9 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
return false;
}
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
- CommandLine::StringType plugin_launcher =
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringType plugin_launcher =
browser_command_line.GetSwitchValueNative(switches::kPpapiPluginLauncher);
#if defined(OS_LINUX)
@@ -304,7 +304,7 @@ bool PpapiPluginProcessHost::Init(const PepperPluginInfo& info) {
return false;
}
- CommandLine* cmd_line = new CommandLine(exe_path);
+ base::CommandLine* cmd_line = new base::CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType,
is_broker_ ? switches::kPpapiBrokerProcess
: switches::kPpapiPluginProcess);
diff --git a/chromium/content/browser/ppapi_plugin_process_host.h b/chromium/content/browser/ppapi_plugin_process_host.h
index 594c12f6152..3f90d3025dc 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.h
+++ b/chromium/content/browser/ppapi_plugin_process_host.h
@@ -60,15 +60,15 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
virtual ResourceContext* GetResourceContext() = 0;
protected:
- virtual ~PluginClient() {}
+ ~PluginClient() override {}
};
class BrokerClient : public Client {
protected:
- virtual ~BrokerClient() {}
+ ~BrokerClient() override {}
};
- virtual ~PpapiPluginProcessHost();
+ ~PpapiPluginProcessHost() override;
static PpapiPluginProcessHost* CreatePluginHost(
const PepperPluginInfo& info,
@@ -96,7 +96,7 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
std::vector<PpapiPluginProcessHost*>* hosts);
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// Opens a new channel to the plugin. The client will be notified when the
// channel is ready or if there's an error.
@@ -126,12 +126,12 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
void RequestPluginChannel(Client* client);
- virtual void OnProcessLaunched() OVERRIDE;
+ void OnProcessLaunched() override;
- virtual void OnProcessCrashed(int exit_code) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ void OnProcessCrashed(int exit_code) override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
void CancelRequests();
diff --git a/chromium/content/browser/profiler_controller_impl.h b/chromium/content/browser/profiler_controller_impl.h
index 34c76ec56de..44e160c9a5d 100644
--- a/chromium/content/browser/profiler_controller_impl.h
+++ b/chromium/content/browser/profiler_controller_impl.h
@@ -25,7 +25,7 @@ class ProfilerControllerImpl : public ProfilerController {
// Normally instantiated when the child process is launched. Only one instance
// should be created per process.
ProfilerControllerImpl();
- virtual ~ProfilerControllerImpl();
+ ~ProfilerControllerImpl() override;
// Notify the |subscriber_| that it should expect at least |pending_processes|
// additional calls to OnProfilerDataCollected(). OnPendingProcess() may be
@@ -42,9 +42,9 @@ class ProfilerControllerImpl : public ProfilerController {
int process_type);
// ProfilerController implementation:
- virtual void Register(ProfilerSubscriber* subscriber) OVERRIDE;
- virtual void Unregister(const ProfilerSubscriber* subscriber) OVERRIDE;
- virtual void GetProfilerData(int sequence_number) OVERRIDE;
+ void Register(ProfilerSubscriber* subscriber) override;
+ void Unregister(const ProfilerSubscriber* subscriber) override;
+ void GetProfilerData(int sequence_number) override;
private:
friend struct DefaultSingletonTraits<ProfilerControllerImpl>;
diff --git a/chromium/content/browser/profiler_message_filter.h b/chromium/content/browser/profiler_message_filter.h
index 1575abcc6f2..df4ce53e061 100644
--- a/chromium/content/browser/profiler_message_filter.h
+++ b/chromium/content/browser/profiler_message_filter.h
@@ -21,13 +21,13 @@ class ProfilerMessageFilter : public BrowserMessageFilter {
explicit ProfilerMessageFilter(int process_type);
// BrowserMessageFilter implementation.
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+ void OnChannelConnected(int32 peer_pid) override;
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~ProfilerMessageFilter();
+ ~ProfilerMessageFilter() override;
private:
// Message handlers.
diff --git a/chromium/content/browser/push_messaging/OWNERS b/chromium/content/browser/push_messaging/OWNERS
new file mode 100644
index 00000000000..de1f744c561
--- /dev/null
+++ b/chromium/content/browser/push_messaging/OWNERS
@@ -0,0 +1,2 @@
+mvanouwerkerk@chromium.org
+
diff --git a/chromium/content/browser/push_messaging/push_messaging_message_filter.cc b/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
new file mode 100644
index 00000000000..ed9046f0565
--- /dev/null
+++ b/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
@@ -0,0 +1,183 @@
+// Copyright 2014 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 "content/browser/push_messaging/push_messaging_message_filter.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/metrics/histogram.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/common/push_messaging_messages.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/push_messaging_service.h"
+#include "third_party/WebKit/public/platform/WebPushPermissionStatus.h"
+
+namespace content {
+namespace {
+
+void RecordRegistrationStatus(PushRegistrationStatus status) {
+ UMA_HISTOGRAM_ENUMERATION("PushMessaging.RegistrationStatus",
+ status,
+ PUSH_REGISTRATION_STATUS_LAST + 1);
+}
+
+} // namespace
+
+PushMessagingMessageFilter::PushMessagingMessageFilter(
+ int render_process_id,
+ ServiceWorkerContextWrapper* service_worker_context)
+ : BrowserMessageFilter(PushMessagingMsgStart),
+ render_process_id_(render_process_id),
+ service_worker_context_(service_worker_context),
+ service_(NULL),
+ weak_factory_(this) {
+}
+
+PushMessagingMessageFilter::~PushMessagingMessageFilter() {}
+
+bool PushMessagingMessageFilter::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PushMessagingMessageFilter, message)
+ IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Register, OnRegister)
+ IPC_MESSAGE_HANDLER(PushMessagingHostMsg_PermissionStatus,
+ OnPermissionStatusRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PushMessagingMessageFilter::OnRegister(int render_frame_id,
+ int callbacks_id,
+ const std::string& sender_id,
+ bool user_gesture,
+ int service_worker_provider_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(mvanouwerkerk): Validate arguments?
+ ServiceWorkerProviderHost* service_worker_host =
+ service_worker_context_->context()->GetProviderHost(
+ render_process_id_, service_worker_provider_id);
+ if (!service_worker_host || !service_worker_host->active_version()) {
+ PushRegistrationStatus status =
+ PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER;
+ Send(new PushMessagingMsg_RegisterError(
+ render_frame_id,
+ callbacks_id,
+ status));
+ RecordRegistrationStatus(status);
+ return;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&PushMessagingMessageFilter::DoRegister,
+ weak_factory_.GetWeakPtr(),
+ render_frame_id,
+ callbacks_id,
+ sender_id,
+ user_gesture,
+ service_worker_host->active_version()->scope().GetOrigin(),
+ service_worker_host->active_version()->registration_id()));
+}
+
+void PushMessagingMessageFilter::OnPermissionStatusRequest(
+ int render_frame_id,
+ int service_worker_provider_id,
+ int permission_callback_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ServiceWorkerProviderHost* service_worker_host =
+ service_worker_context_->context()->GetProviderHost(
+ render_process_id_, service_worker_provider_id);
+
+ if (service_worker_host && service_worker_host->active_version()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&PushMessagingMessageFilter::DoPermissionStatusRequest,
+ weak_factory_.GetWeakPtr(),
+ service_worker_host->active_version()->scope().GetOrigin(),
+ render_frame_id,
+ permission_callback_id));
+ } else {
+ Send(new PushMessagingMsg_PermissionStatusFailure(
+ render_frame_id, permission_callback_id));
+ }
+}
+
+void PushMessagingMessageFilter::DoRegister(
+ int render_frame_id,
+ int callbacks_id,
+ const std::string& sender_id,
+ bool user_gesture,
+ const GURL& origin,
+ int64 service_worker_registration_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!service()) {
+ PushRegistrationStatus status =
+ PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE;
+ Send(new PushMessagingMsg_RegisterError(
+ render_frame_id,
+ callbacks_id,
+ status));
+ RecordRegistrationStatus(status);
+ return;
+ }
+ service()->Register(origin,
+ service_worker_registration_id,
+ sender_id,
+ render_process_id_,
+ render_frame_id,
+ user_gesture,
+ base::Bind(&PushMessagingMessageFilter::DidRegister,
+ weak_factory_.GetWeakPtr(),
+ render_frame_id,
+ callbacks_id));
+}
+
+void PushMessagingMessageFilter::DoPermissionStatusRequest(
+ const GURL& requesting_origin,
+ int render_frame_id,
+ int callback_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ blink::WebPushPermissionStatus permission_value =
+ service()->GetPermissionStatus(
+ requesting_origin, render_process_id_, render_frame_id);
+
+ Send(new PushMessagingMsg_PermissionStatusResult(
+ render_frame_id, callback_id, permission_value));
+}
+
+void PushMessagingMessageFilter::DidRegister(
+ int render_frame_id,
+ int callbacks_id,
+ const GURL& push_endpoint,
+ const std::string& push_registration_id,
+ PushRegistrationStatus status) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (status == PUSH_REGISTRATION_STATUS_SUCCESS) {
+ Send(new PushMessagingMsg_RegisterSuccess(
+ render_frame_id, callbacks_id, push_endpoint, push_registration_id));
+ } else {
+ Send(new PushMessagingMsg_RegisterError(
+ render_frame_id, callbacks_id, status));
+ }
+ RecordRegistrationStatus(status);
+}
+
+PushMessagingService* PushMessagingMessageFilter::service() {
+ if (!service_) {
+ RenderProcessHost* process_host =
+ RenderProcessHost::FromID(render_process_id_);
+ if (!process_host)
+ return NULL;
+ service_ = process_host->GetBrowserContext()->GetPushMessagingService();
+ }
+ return service_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/push_messaging/push_messaging_message_filter.h b/chromium/content/browser/push_messaging/push_messaging_message_filter.h
new file mode 100644
index 00000000000..4f9ebd9f994
--- /dev/null
+++ b/chromium/content/browser/push_messaging/push_messaging_message_filter.h
@@ -0,0 +1,76 @@
+// Copyright 2014 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 CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_MESSAGE_FILTER_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/common/push_messaging_status.h"
+#include "url/gurl.h"
+
+class GURL;
+
+namespace content {
+
+class PushMessagingService;
+class ServiceWorkerContextWrapper;
+
+class PushMessagingMessageFilter : public BrowserMessageFilter {
+ public:
+ PushMessagingMessageFilter(
+ int render_process_id,
+ ServiceWorkerContextWrapper* service_worker_context);
+
+ private:
+ ~PushMessagingMessageFilter() override;
+
+ // BrowserMessageFilter implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnRegister(int render_frame_id,
+ int callbacks_id,
+ const std::string& sender_id,
+ bool user_gesture,
+ int service_worker_provider_id);
+
+ void OnPermissionStatusRequest(int render_frame_id,
+ int service_worker_provider_id,
+ int permission_callback_id);
+
+ void DoRegister(int render_frame_id,
+ int callbacks_id,
+ const std::string& sender_id,
+ bool user_gesture,
+ const GURL& origin,
+ int64 service_worker_registration_id);
+
+ void DoPermissionStatusRequest(const GURL& requesting_origin,
+ int render_frame_id,
+ int callback_id);
+ void DidRegister(int render_frame_id,
+ int callbacks_id,
+ const GURL& push_endpoint,
+ const std::string& push_registration_id,
+ PushRegistrationStatus status);
+
+ PushMessagingService* service();
+
+ int render_process_id_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+
+ // Owned by the content embedder's browsing context.
+ PushMessagingService* service_;
+
+ base::WeakPtrFactory<PushMessagingMessageFilter> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PushMessagingMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
new file mode 100644
index 00000000000..fc5218a8a2d
--- /dev/null
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -0,0 +1,104 @@
+// Copyright 2014 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 "content/browser/push_messaging/push_messaging_router.h"
+
+#include "base/bind.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+
+namespace content {
+
+// static
+void PushMessagingRouter::DeliverMessage(
+ BrowserContext* browser_context,
+ const GURL& origin,
+ int64 service_worker_registration_id,
+ const std::string& data,
+ const DeliverMessageCallback& deliver_message_callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ StoragePartition* partition =
+ BrowserContext::GetStoragePartitionForSite(browser_context, origin);
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
+ static_cast<ServiceWorkerContextWrapper*>(
+ partition->GetServiceWorkerContext());
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&PushMessagingRouter::FindServiceWorkerRegistration,
+ origin,
+ service_worker_registration_id,
+ data,
+ deliver_message_callback,
+ service_worker_context));
+}
+
+// static
+void PushMessagingRouter::FindServiceWorkerRegistration(
+ const GURL& origin,
+ int64 service_worker_registration_id,
+ const std::string& data,
+ const DeliverMessageCallback& deliver_message_callback,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Try to acquire the registration from storage. If it's already live we'll
+ // receive it right away. If not, it will be revived from storage.
+ service_worker_context->context()->storage()->FindRegistrationForId(
+ service_worker_registration_id,
+ origin,
+ base::Bind(&PushMessagingRouter::FindServiceWorkerRegistrationCallback,
+ data,
+ deliver_message_callback));
+}
+
+// static
+void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
+ const std::string& data,
+ const DeliverMessageCallback& deliver_message_callback,
+ ServiceWorkerStatusCode service_worker_status,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (service_worker_status == SERVICE_WORKER_OK) {
+ // Hold on to the service worker registration in the callback to keep it
+ // alive until the callback dies. Otherwise the registration could be
+ // released when this method returns - before the event is delivered to the
+ // service worker.
+ base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback =
+ base::Bind(&PushMessagingRouter::DeliverMessageEnd,
+ deliver_message_callback,
+ service_worker_registration);
+ service_worker_registration->active_version()->DispatchPushEvent(
+ dispatch_event_callback, data);
+ } else {
+ // TODO(mvanouwerkerk): UMA logging.
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(deliver_message_callback,
+ PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER));
+ }
+}
+
+// static
+void PushMessagingRouter::DeliverMessageEnd(
+ const DeliverMessageCallback& deliver_message_callback,
+ const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
+ ServiceWorkerStatusCode service_worker_status) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // TODO(mvanouwerkerk): UMA logging.
+ PushDeliveryStatus delivery_status =
+ service_worker_status == SERVICE_WORKER_OK
+ ? PUSH_DELIVERY_STATUS_SUCCESS
+ : PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR;
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(deliver_message_callback, delivery_status));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.h b/chromium/content/browser/push_messaging/push_messaging_router.h
new file mode 100644
index 00000000000..d9f25cc3868
--- /dev/null
+++ b/chromium/content/browser/push_messaging/push_messaging_router.h
@@ -0,0 +1,68 @@
+// Copyright 2014 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 CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_ROUTER_H_
+#define CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_ROUTER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/public/common/push_messaging_status.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class BrowserContext;
+class ServiceWorkerContextWrapper;
+class ServiceWorkerRegistration;
+
+class PushMessagingRouter {
+ public:
+ typedef base::Callback<void(PushDeliveryStatus)>
+ DeliverMessageCallback;
+
+ // Delivers a push message with |data| to the Service Worker identified by
+ // |origin| and |service_worker_registration_id|. Must be called on the UI
+ // thread.
+ static void DeliverMessage(
+ BrowserContext* browser_context,
+ const GURL& origin,
+ int64 service_worker_registration_id,
+ const std::string& data,
+ const DeliverMessageCallback& deliver_message_callback);
+
+ private:
+ // Attempts to find a Service Worker registration so that a push event can be
+ // dispatched. Must be called on the IO thread.
+ static void FindServiceWorkerRegistration(
+ const GURL& origin,
+ int64 service_worker_registration_id,
+ const std::string& data,
+ const DeliverMessageCallback& deliver_message_callback,
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+
+ // If a registration was successfully retrieved, dispatches a push event with
+ // |data| on the Service Worker identified by |service_worker_registration|.
+ // Must be called on the IO thread.
+ static void FindServiceWorkerRegistrationCallback(
+ const std::string& data,
+ const DeliverMessageCallback& deliver_message_callback,
+ ServiceWorkerStatusCode service_worker_status,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration);
+
+ // Gets called asynchronously after the Service Worker has dispatched the push
+ // event. Must be called on the IO thread.
+ static void DeliverMessageEnd(
+ const DeliverMessageCallback& deliver_message_callback,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration,
+ ServiceWorkerStatusCode service_worker_status);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PushMessagingRouter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_PUSH_MESSAGING_PUSH_MESSAGING_ROUTER_H_
diff --git a/chromium/content/browser/push_messaging_message_filter.cc b/chromium/content/browser/push_messaging_message_filter.cc
deleted file mode 100644
index 451c11253f6..00000000000
--- a/chromium/content/browser/push_messaging_message_filter.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2014 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 "content/browser/push_messaging_message_filter.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/common/push_messaging_messages.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/push_messaging_service.h"
-
-namespace content {
-
-PushMessagingMessageFilter::PushMessagingMessageFilter(int render_process_id)
- : BrowserMessageFilter(PushMessagingMsgStart),
- render_process_id_(render_process_id),
- service_(NULL),
- weak_factory_(this) {}
-
-PushMessagingMessageFilter::~PushMessagingMessageFilter() {}
-
-bool PushMessagingMessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PushMessagingMessageFilter, message)
- IPC_MESSAGE_HANDLER(PushMessagingHostMsg_Register, OnRegister)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void PushMessagingMessageFilter::OnRegister(int routing_id,
- int callbacks_id,
- const std::string& sender_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // TODO(mvanouwerkerk): Validate arguments?
- // TODO(mvanouwerkerk): A WebContentsObserver could avoid this PostTask
- // by receiving the IPC on the UI thread.
- BrowserThread::PostTask(BrowserThread::UI,
- FROM_HERE,
- base::Bind(&PushMessagingMessageFilter::DoRegister,
- weak_factory_.GetWeakPtr(),
- routing_id,
- callbacks_id,
- sender_id));
-}
-
-void PushMessagingMessageFilter::DoRegister(int routing_id,
- int callbacks_id,
- const std::string& sender_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (!service()) {
- DidRegister(routing_id, callbacks_id, GURL(), "", false);
- return;
- }
- // TODO(mvanouwerkerk): Pass in a real app ID based on Service Worker ID.
- std::string app_id = "https://example.com 0";
- service_->Register(app_id,
- sender_id,
- base::Bind(&PushMessagingMessageFilter::DidRegister,
- weak_factory_.GetWeakPtr(),
- routing_id,
- callbacks_id));
-}
-
-void PushMessagingMessageFilter::DidRegister(int routing_id,
- int callbacks_id,
- const GURL& endpoint,
- const std::string& registration_id,
- bool success) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (success) {
- Send(new PushMessagingMsg_RegisterSuccess(routing_id,
- callbacks_id,
- endpoint,
- registration_id));
- } else {
- Send(new PushMessagingMsg_RegisterError(routing_id, callbacks_id));
- }
-}
-
-PushMessagingService* PushMessagingMessageFilter::service() {
- if (!service_) {
- RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
- RenderProcessHost::FromID(render_process_id_));
- if (!host)
- return NULL;
- service_ = host->GetBrowserContext()->GetPushMessagingService();
- }
- return service_;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/push_messaging_message_filter.h b/chromium/content/browser/push_messaging_message_filter.h
deleted file mode 100644
index abc02188873..00000000000
--- a/chromium/content/browser/push_messaging_message_filter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_PUSH_MESSAGING_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_PUSH_MESSAGING_MESSAGE_FILTER_H_
-
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class PushMessagingService;
-
-class PushMessagingMessageFilter : public BrowserMessageFilter {
- public:
- explicit PushMessagingMessageFilter(int render_process_id);
-
- private:
- virtual ~PushMessagingMessageFilter();
-
- // BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void OnRegister(int routing_id,
- int callbacks_id,
- const std::string& sender_id);
-
- void DoRegister(int routing_id,
- int callbacks_id,
- const std::string& sender_id);
-
- void DidRegister(int routing_id,
- int callbacks_id,
- const GURL& endpoint,
- const std::string& registration_id,
- bool success);
-
- PushMessagingService* service();
-
- int render_process_id_;
- PushMessagingService* service_; // Not owned.
-
- base::WeakPtrFactory<PushMessagingMessageFilter> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PushMessagingMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_PUSH_MESSAGING_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/quota/mock_quota_manager.cc b/chromium/content/browser/quota/mock_quota_manager.cc
index 0343f39d01f..4884d0d7dfe 100644
--- a/chromium/content/browser/quota/mock_quota_manager.cc
+++ b/chromium/content/browser/quota/mock_quota_manager.cc
@@ -10,7 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "url/gurl.h"
-using quota::kQuotaStatusOk;
+using storage::kQuotaStatusOk;
namespace content {
@@ -33,20 +33,23 @@ MockQuotaManager::StorageInfo::~StorageInfo() {}
MockQuotaManager::MockQuotaManager(
bool is_incognito,
const base::FilePath& profile_path,
- base::SingleThreadTaskRunner* io_thread,
- base::SequencedTaskRunner* db_thread,
- SpecialStoragePolicy* special_storage_policy)
- : QuotaManager(is_incognito, profile_path, io_thread, db_thread,
- special_storage_policy),
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
+ const scoped_refptr<base::SequencedTaskRunner>& db_thread,
+ const scoped_refptr<SpecialStoragePolicy>& special_storage_policy)
+ : QuotaManager(is_incognito,
+ profile_path,
+ io_thread,
+ db_thread,
+ special_storage_policy),
weak_factory_(this) {
}
void MockQuotaManager::GetUsageAndQuota(
const GURL& origin,
- quota::StorageType type,
+ storage::StorageType type,
const GetUsageAndQuotaCallback& callback) {
StorageInfo& info = usage_and_quota_map_[std::make_pair(origin, type)];
- callback.Run(quota::kQuotaStatusOk, info.usage, info.quota);
+ callback.Run(storage::kQuotaStatusOk, info.usage, info.quota);
}
void MockQuotaManager::SetQuota(const GURL& origin, StorageType type,
diff --git a/chromium/content/browser/quota/mock_quota_manager.h b/chromium/content/browser/quota/mock_quota_manager.h
index ded0b907904..a6bba10e985 100644
--- a/chromium/content/browser/quota/mock_quota_manager.h
+++ b/chromium/content/browser/quota/mock_quota_manager.h
@@ -11,19 +11,19 @@
#include <vector>
#include "base/memory/scoped_ptr.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_task.h"
+#include "storage/common/quota/quota_types.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/quota_client.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/quota_task.h"
-#include "webkit/common/quota/quota_types.h"
-
-using quota::GetOriginsCallback;
-using quota::QuotaClient;
-using quota::QuotaManager;
-using quota::QuotaStatusCode;
-using quota::SpecialStoragePolicy;
-using quota::StatusCallback;
-using quota::StorageType;
+
+using storage::GetOriginsCallback;
+using storage::QuotaClient;
+using storage::QuotaManager;
+using storage::QuotaStatusCode;
+using storage::SpecialStoragePolicy;
+using storage::StatusCallback;
+using storage::StorageType;
namespace content {
@@ -40,28 +40,27 @@ namespace content {
// origin data stored in the profile.
class MockQuotaManager : public QuotaManager {
public:
- MockQuotaManager(bool is_incognito,
- const base::FilePath& profile_path,
- base::SingleThreadTaskRunner* io_thread,
- base::SequencedTaskRunner* db_thread,
- SpecialStoragePolicy* special_storage_policy);
+ MockQuotaManager(
+ bool is_incognito,
+ const base::FilePath& profile_path,
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_thread,
+ const scoped_refptr<base::SequencedTaskRunner>& db_thread,
+ const scoped_refptr<SpecialStoragePolicy>& special_storage_policy);
// Overrides QuotaManager's implementation. The internal usage data is
// updated when MockQuotaManagerProxy::NotifyStorageModified() is
// called. The internal quota value can be updated by calling
// a helper method MockQuotaManagerProxy::SetQuota().
- virtual void GetUsageAndQuota(
- const GURL& origin,
- quota::StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE;
+ void GetUsageAndQuota(const GURL& origin,
+ storage::StorageType type,
+ const GetUsageAndQuotaCallback& callback) override;
// Overrides QuotaManager's implementation with a canned implementation that
// allows clients to set up the origin database that should be queried. This
// method will only search through the origins added explicitly via AddOrigin.
- virtual void GetOriginsModifiedSince(
- StorageType type,
- base::Time modified_since,
- const GetOriginsCallback& callback) OVERRIDE;
+ void GetOriginsModifiedSince(StorageType type,
+ base::Time modified_since,
+ const GetOriginsCallback& callback) override;
// Removes an origin from the canned list of origins, but doesn't touch
// anything on disk. The caller must provide |quota_client_mask| which
@@ -69,10 +68,10 @@ class MockQuotaManager : public QuotaManager {
// origin as a bitmask built from QuotaClient::IDs. Setting the mask to
// QuotaClient::kAllClientsMask will remove all clients from the origin,
// regardless of type.
- virtual void DeleteOriginData(const GURL& origin,
- StorageType type,
- int quota_client_mask,
- const StatusCallback& callback) OVERRIDE;
+ void DeleteOriginData(const GURL& origin,
+ StorageType type,
+ int quota_client_mask,
+ const StatusCallback& callback) override;
// Helper method for updating internal quota info.
void SetQuota(const GURL& origin, StorageType type, int64 quota);
@@ -96,7 +95,7 @@ class MockQuotaManager : public QuotaManager {
QuotaClient::ID quota_client) const;
protected:
- virtual ~MockQuotaManager();
+ ~MockQuotaManager() override;
private:
friend class MockQuotaManagerProxy;
diff --git a/chromium/content/browser/quota/mock_quota_manager_proxy.cc b/chromium/content/browser/quota/mock_quota_manager_proxy.cc
index ddeef6a7b39..2e26e32c0f3 100644
--- a/chromium/content/browser/quota/mock_quota_manager_proxy.cc
+++ b/chromium/content/browser/quota/mock_quota_manager_proxy.cc
@@ -8,7 +8,7 @@
#include "base/single_thread_task_runner.h"
#include "url/gurl.h"
-using quota::kStorageTypeUnknown;
+using storage::kStorageTypeUnknown;
namespace content {
diff --git a/chromium/content/browser/quota/mock_quota_manager_proxy.h b/chromium/content/browser/quota/mock_quota_manager_proxy.h
index 9e8835fb08a..0f52f6dcc8e 100644
--- a/chromium/content/browser/quota/mock_quota_manager_proxy.h
+++ b/chromium/content/browser/quota/mock_quota_manager_proxy.h
@@ -6,12 +6,12 @@
#define CONTENT_BROWSER_QUOTA_MOCK_QUOTA_MANAGER_PROXY_H_
#include "content/browser/quota/mock_quota_manager.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/quota/quota_types.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/quota_client.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/common/quota/quota_types.h"
-using quota::QuotaManagerProxy;
+using storage::QuotaManagerProxy;
namespace content {
@@ -23,39 +23,39 @@ class MockQuotaManagerProxy : public QuotaManagerProxy {
MockQuotaManagerProxy(MockQuotaManager* quota_manager,
base::SingleThreadTaskRunner* task_runner);
- virtual void RegisterClient(QuotaClient* client) OVERRIDE;
+ void RegisterClient(QuotaClient* client) override;
void SimulateQuotaManagerDestroyed();
// We don't mock them.
- virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
- virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
- virtual void SetUsageCacheEnabled(QuotaClient::ID client_id,
- const GURL& origin,
- StorageType type,
- bool enabled) OVERRIDE {}
- virtual void GetUsageAndQuota(
+ void NotifyOriginInUse(const GURL& origin) override {}
+ void NotifyOriginNoLongerInUse(const GURL& origin) override {}
+ void SetUsageCacheEnabled(QuotaClient::ID client_id,
+ const GURL& origin,
+ StorageType type,
+ bool enabled) override {}
+ void GetUsageAndQuota(
base::SequencedTaskRunner* original_task_runner,
const GURL& origin,
StorageType type,
- const QuotaManager::GetUsageAndQuotaCallback& callback) OVERRIDE {}
+ const QuotaManager::GetUsageAndQuotaCallback& callback) override {}
// Validates the |client_id| and updates the internal access count
// which can be accessed via notify_storage_accessed_count().
// The also records the |origin| and |type| in last_notified_origin_ and
// last_notified_type_.
- virtual void NotifyStorageAccessed(QuotaClient::ID client_id,
- const GURL& origin,
- StorageType type) OVERRIDE;
+ void NotifyStorageAccessed(QuotaClient::ID client_id,
+ const GURL& origin,
+ StorageType type) override;
// Records the |origin|, |type| and |delta| as last_notified_origin_,
// last_notified_type_ and last_notified_delta_ respecitvely.
// If non-null MockQuotaManager is given to the constructor this also
// updates the manager's internal usage information.
- virtual void NotifyStorageModified(QuotaClient::ID client_id,
- const GURL& origin,
- StorageType type,
- int64 delta) OVERRIDE;
+ void NotifyStorageModified(QuotaClient::ID client_id,
+ const GURL& origin,
+ StorageType type,
+ int64 delta) override;
int notify_storage_accessed_count() const { return storage_accessed_count_; }
int notify_storage_modified_count() const { return storage_modified_count_; }
@@ -64,7 +64,7 @@ class MockQuotaManagerProxy : public QuotaManagerProxy {
int64 last_notified_delta() const { return last_notified_delta_; }
protected:
- virtual ~MockQuotaManagerProxy();
+ ~MockQuotaManagerProxy() override;
private:
MockQuotaManager* mock_manager() const {
diff --git a/chromium/content/browser/quota/mock_quota_manager_unittest.cc b/chromium/content/browser/quota/mock_quota_manager_unittest.cc
index e1885c4ff28..706ca821972 100644
--- a/chromium/content/browser/quota/mock_quota_manager_unittest.cc
+++ b/chromium/content/browser/quota/mock_quota_manager_unittest.cc
@@ -5,7 +5,7 @@
#include <set>
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
@@ -15,9 +15,9 @@
#include "content/public/test/mock_storage_client.h"
#include "testing/gtest/include/gtest/gtest.h"
-using quota::kQuotaStatusOk;
-using quota::kStorageTypePersistent;
-using quota::kStorageTypeTemporary;
+using storage::kQuotaStatusOk;
+using storage::kStorageTypePersistent;
+using storage::kStorageTypeTemporary;
namespace content {
@@ -42,7 +42,7 @@ class MockQuotaManagerTest : public testing::Test {
weak_factory_(this) {
}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
policy_ = new MockSpecialStoragePolicy;
manager_ = new MockQuotaManager(false /* is_incognito */,
@@ -52,7 +52,7 @@ class MockQuotaManagerTest : public testing::Test {
policy_.get());
}
- virtual void TearDown() {
+ void TearDown() override {
// Make sure the quota manager cleans up correctly.
manager_ = NULL;
base::RunLoop().RunUntilIdle();
@@ -223,4 +223,4 @@ TEST_F(MockQuotaManagerTest, ModifiedOrigins) {
EXPECT_EQ(0UL, origins().count(kOrigin1));
EXPECT_EQ(1UL, origins().count(kOrigin2));
}
-} // Namespace content
+} // namespace content
diff --git a/chromium/content/browser/quota/quota_backend_impl_unittest.cc b/chromium/content/browser/quota/quota_backend_impl_unittest.cc
index 201fab09375..2cf9f175774 100644
--- a/chromium/content/browser/quota/quota_backend_impl_unittest.cc
+++ b/chromium/content/browser/quota/quota_backend_impl_unittest.cc
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/quota/quota_backend_impl.h"
+#include "storage/browser/fileapi/quota/quota_backend_impl.h"
#include <string>
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
+#include "storage/browser/fileapi/file_system_usage_cache.h"
+#include "storage/browser/fileapi/obfuscated_file_util.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
#include "third_party/leveldatabase/src/include/leveldb/env.h"
-#include "webkit/browser/fileapi/file_system_usage_cache.h"
-#include "webkit/browser/fileapi/obfuscated_file_util.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-using fileapi::FileSystemUsageCache;
-using fileapi::ObfuscatedFileUtil;
-using fileapi::QuotaBackendImpl;
-using fileapi::SandboxFileSystemBackendDelegate;
+using storage::FileSystemUsageCache;
+using storage::ObfuscatedFileUtil;
+using storage::QuotaBackendImpl;
+using storage::SandboxFileSystemBackendDelegate;
namespace content {
@@ -38,7 +38,7 @@ bool DidReserveQuota(bool accepted,
return accepted;
}
-class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
+class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
public:
MockQuotaManagerProxy()
: QuotaManagerProxy(NULL, NULL),
@@ -46,29 +46,27 @@ class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
usage_(0), quota_(0) {}
// We don't mock them.
- virtual void NotifyOriginInUse(const GURL& origin) OVERRIDE {}
- virtual void NotifyOriginNoLongerInUse(const GURL& origin) OVERRIDE {}
- virtual void SetUsageCacheEnabled(quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- bool enabled) OVERRIDE {}
-
- virtual void NotifyStorageModified(
- quota::QuotaClient::ID client_id,
- const GURL& origin,
- quota::StorageType type,
- int64 delta) OVERRIDE {
+ void NotifyOriginInUse(const GURL& origin) override {}
+ void NotifyOriginNoLongerInUse(const GURL& origin) override {}
+ void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ bool enabled) override {}
+
+ void NotifyStorageModified(storage::QuotaClient::ID client_id,
+ const GURL& origin,
+ storage::StorageType type,
+ int64 delta) override {
++storage_modified_count_;
usage_ += delta;
ASSERT_LE(usage_, quota_);
}
- virtual void GetUsageAndQuota(
- base::SequencedTaskRunner* original_task_runner,
- const GURL& origin,
- quota::StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE {
- callback.Run(quota::kQuotaStatusOk, usage_, quota_);
+ void GetUsageAndQuota(base::SequencedTaskRunner* original_task_runner,
+ const GURL& origin,
+ storage::StorageType type,
+ const GetUsageAndQuotaCallback& callback) override {
+ callback.Run(storage::kQuotaStatusOk, usage_, quota_);
}
int storage_modified_count() { return storage_modified_count_; }
@@ -77,7 +75,7 @@ class MockQuotaManagerProxy : public quota::QuotaManagerProxy {
void set_quota(int64 quota) { quota_ = quota; }
protected:
- virtual ~MockQuotaManagerProxy() {}
+ ~MockQuotaManagerProxy() override {}
private:
int storage_modified_count_;
@@ -95,7 +93,7 @@ class QuotaBackendImplTest : public testing::Test {
: file_system_usage_cache_(file_task_runner()),
quota_manager_proxy_(new MockQuotaManagerProxy) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
file_util_.reset(ObfuscatedFileUtil::CreateForTesting(
@@ -106,7 +104,7 @@ class QuotaBackendImplTest : public testing::Test {
quota_manager_proxy_.get()));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
backend_.reset();
quota_manager_proxy_ = NULL;
file_util_.reset();
@@ -115,7 +113,7 @@ class QuotaBackendImplTest : public testing::Test {
protected:
void InitializeForOriginAndType(const GURL& origin,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
ASSERT_TRUE(file_util_->InitOriginDatabase(origin, true /* create */));
ASSERT_TRUE(file_util_->origin_database_ != NULL);
@@ -135,7 +133,7 @@ class QuotaBackendImplTest : public testing::Test {
}
base::FilePath GetUsageCachePath(const GURL& origin,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
base::FilePath path;
base::File::Error error =
backend_->GetUsageCachePath(origin, type, &path);
@@ -157,7 +155,7 @@ class QuotaBackendImplTest : public testing::Test {
};
TEST_F(QuotaBackendImplTest, ReserveQuota_Basic) {
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
InitializeForOriginAndType(GURL(kOrigin), type);
quota_manager_proxy_->set_quota(10000);
@@ -183,7 +181,7 @@ TEST_F(QuotaBackendImplTest, ReserveQuota_Basic) {
}
TEST_F(QuotaBackendImplTest, ReserveQuota_NoSpace) {
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
InitializeForOriginAndType(GURL(kOrigin), type);
quota_manager_proxy_->set_quota(100);
@@ -201,7 +199,7 @@ TEST_F(QuotaBackendImplTest, ReserveQuota_NoSpace) {
}
TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) {
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
InitializeForOriginAndType(GURL(kOrigin), type);
quota_manager_proxy_->set_quota(10000);
@@ -219,7 +217,7 @@ TEST_F(QuotaBackendImplTest, ReserveQuota_Revert) {
}
TEST_F(QuotaBackendImplTest, ReleaseReservedQuota) {
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
InitializeForOriginAndType(GURL(kOrigin), type);
const int64 kInitialUsage = 2000;
quota_manager_proxy_->set_usage(kInitialUsage);
@@ -233,7 +231,7 @@ TEST_F(QuotaBackendImplTest, ReleaseReservedQuota) {
}
TEST_F(QuotaBackendImplTest, CommitQuotaUsage) {
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
InitializeForOriginAndType(GURL(kOrigin), type);
quota_manager_proxy_->set_quota(10000);
base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
@@ -256,7 +254,7 @@ TEST_F(QuotaBackendImplTest, CommitQuotaUsage) {
}
TEST_F(QuotaBackendImplTest, DirtyCount) {
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
InitializeForOriginAndType(GURL(kOrigin), type);
base::FilePath path = GetUsageCachePath(GURL(kOrigin), type);
diff --git a/chromium/content/browser/quota/quota_database_unittest.cc b/chromium/content/browser/quota/quota_database_unittest.cc
index 1415ed53f28..5b5b00e1454 100644
--- a/chromium/content/browser/quota/quota_database_unittest.cc
+++ b/chromium/content/browser/quota/quota_database_unittest.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "content/public/test/mock_special_storage_policy.h"
@@ -16,13 +16,13 @@
#include "sql/meta_table.h"
#include "sql/statement.h"
#include "sql/transaction.h"
+#include "storage/browser/quota/quota_database.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/quota_database.h"
-using quota::kStorageTypePersistent;
-using quota::kStorageTypeTemporary;
-using quota::QuotaDatabase;
+using storage::kStorageTypePersistent;
+using storage::kStorageTypeTemporary;
+using storage::QuotaDatabase;
namespace content {
namespace {
@@ -55,14 +55,14 @@ class QuotaDatabaseTest : public testing::Test {
QuotaTableEntry("c", kStorageTypePersistent, 3),
};
- CreateV2Database(kDbFile, entries, ARRAYSIZE_UNSAFE(entries));
+ CreateV2Database(kDbFile, entries, arraysize(entries));
QuotaDatabase db(kDbFile);
EXPECT_TRUE(db.LazyOpen(true));
EXPECT_TRUE(db.db_.get());
typedef EntryVerifier<QuotaTableEntry> Verifier;
- Verifier verifier(entries, entries + ARRAYSIZE_UNSAFE(entries));
+ Verifier verifier(entries, entries + arraysize(entries));
EXPECT_TRUE(db.DumpQuotaTable(
base::Bind(&Verifier::Run, base::Unretained(&verifier))));
EXPECT_TRUE(verifier.table.empty());
@@ -287,7 +287,7 @@ class QuotaDatabaseTest : public testing::Test {
GURL("http://a/"),
GURL("http://b/"),
GURL("http://c/") };
- std::set<GURL> origins(kOrigins, kOrigins + ARRAYSIZE_UNSAFE(kOrigins));
+ std::set<GURL> origins(kOrigins, kOrigins + arraysize(kOrigins));
EXPECT_TRUE(db.RegisterInitialOriginInfo(origins, kStorageTypeTemporary));
@@ -336,7 +336,7 @@ class QuotaDatabaseTest : public testing::Test {
QuotaTableEntry("http://gle/", kStorageTypePersistent, 3)
};
QuotaTableEntry* begin = kTableEntries;
- QuotaTableEntry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries);
+ QuotaTableEntry* end = kTableEntries + arraysize(kTableEntries);
QuotaDatabase db(kDbFile);
EXPECT_TRUE(db.LazyOpen(true));
@@ -359,7 +359,7 @@ class QuotaDatabaseTest : public testing::Test {
Entry(GURL("http://gle/"), kStorageTypeTemporary, 1, now, now),
};
Entry* begin = kTableEntries;
- Entry* end = kTableEntries + ARRAYSIZE_UNSAFE(kTableEntries);
+ Entry* end = kTableEntries + arraysize(kTableEntries);
QuotaDatabase db(kDbFile);
EXPECT_TRUE(db.LazyOpen(true));
@@ -467,8 +467,8 @@ class QuotaDatabaseTest : public testing::Test {
EXPECT_TRUE(QuotaDatabase::CreateSchema(
db.get(), meta_table.get(),
kCurrentVersion, kCompatibleVersion,
- kTables, ARRAYSIZE_UNSAFE(kTables),
- kIndexes, ARRAYSIZE_UNSAFE(kIndexes)));
+ kTables, arraysize(kTables),
+ kIndexes, arraysize(kIndexes)));
// V2 and V3 QuotaTable are compatible, so we can simply use
// AssignQuotaTable to poplulate v2 database here.
diff --git a/chromium/content/browser/quota/quota_manager_unittest.cc b/chromium/content/browser/quota/quota_manager_unittest.cc
index 5baa025e859..1337bc389f4 100644
--- a/chromium/content/browser/quota/quota_manager_unittest.cc
+++ b/chromium/content/browser/quota/quota_manager_unittest.cc
@@ -8,7 +8,7 @@
#include <vector>
#include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -19,29 +19,29 @@
#include "base/time/time.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/mock_storage_client.h"
+#include "storage/browser/quota/quota_database.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/quota_database.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
using base::MessageLoopProxy;
-using quota::kQuotaErrorAbort;
-using quota::kQuotaErrorInvalidModification;
-using quota::kQuotaErrorNotSupported;
-using quota::kQuotaStatusOk;
-using quota::kQuotaStatusUnknown;
-using quota::kStorageTypePersistent;
-using quota::kStorageTypeSyncable;
-using quota::kStorageTypeTemporary;
-using quota::kStorageTypeUnknown;
-using quota::QuotaClient;
-using quota::QuotaManager;
-using quota::QuotaStatusCode;
-using quota::StorageType;
-using quota::UsageAndQuota;
-using quota::UsageInfo;
-using quota::UsageInfoEntries;
+using storage::kQuotaErrorAbort;
+using storage::kQuotaErrorInvalidModification;
+using storage::kQuotaErrorNotSupported;
+using storage::kQuotaStatusOk;
+using storage::kQuotaStatusUnknown;
+using storage::kStorageTypePersistent;
+using storage::kStorageTypeSyncable;
+using storage::kStorageTypeTemporary;
+using storage::kStorageTypeUnknown;
+using storage::QuotaClient;
+using storage::QuotaManager;
+using storage::QuotaStatusCode;
+using storage::StorageType;
+using storage::UsageAndQuota;
+using storage::UsageInfo;
+using storage::UsageInfoEntries;
namespace content {
@@ -78,13 +78,13 @@ class QuotaManagerTest : public testing::Test {
weak_factory_(this) {
}
- virtual void SetUp() {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
mock_special_storage_policy_ = new MockSpecialStoragePolicy;
ResetQuotaManager(false /* is_incognito */);
}
- virtual void TearDown() {
+ void TearDown() override {
// Make sure the quota manager cleans up correctly.
quota_manager_ = NULL;
base::RunLoop().RunUntilIdle();
@@ -469,9 +469,9 @@ TEST_F(QuotaManagerTest, GetUsageInfo) {
{ "http://bar.com/", kPerm, 40 },
{ "http://example.com/", kPerm, 40 },
};
- RegisterClient(CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ RegisterClient(CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem));
- RegisterClient(CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ RegisterClient(CreateClient(kData2, arraysize(kData2),
QuotaClient::kDatabase));
GetUsageInfo();
@@ -500,7 +500,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Simple) {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com/", kPerm, 80 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
@@ -593,7 +593,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_MultiOrigins) {
{ "http://baz.com/", kTemp, 30 },
{ "http://foo.com/", kPerm, 40 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
// This time explicitly sets a temporary global quota.
@@ -636,9 +636,9 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) {
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
mock_special_storage_policy()->GrantQueryDiskSize(GURL("http://installed/"));
- RegisterClient(CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ RegisterClient(CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem));
- RegisterClient(CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ RegisterClient(CreateClient(kData2, arraysize(kData2),
QuotaClient::kDatabase));
const int64 kTempQuotaBase =
@@ -701,7 +701,7 @@ void QuotaManagerTest::GetUsage_WithModifyTestBody(const StorageType type) {
{ "http://foo.com/", type, 10 },
{ "http://foo.com:1/", type, 20 },
};
- MockStorageClient* client = CreateClient(data, ARRAYSIZE_UNSAFE(data),
+ MockStorageClient* client = CreateClient(data, arraysize(data),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -743,7 +743,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_WithAdditionalTasks) {
{ "http://bar.com/", kTemp, 13 },
{ "http://foo.com/", kPerm, 40 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
SetTemporaryGlobalQuota(100);
base::RunLoop().RunUntilIdle();
@@ -777,7 +777,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_NukeManager) {
{ "http://bar.com/", kTemp, 13 },
{ "http://foo.com/", kPerm, 40 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
SetTemporaryGlobalQuota(100);
base::RunLoop().RunUntilIdle();
@@ -804,7 +804,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Overbudget) {
{ "http://usage10/", kTemp, 10 },
{ "http://usage200/", kTemp, 200 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
SetTemporaryGlobalQuota(100);
base::RunLoop().RunUntilIdle();
@@ -837,7 +837,7 @@ TEST_F(QuotaManagerTest, GetTemporaryUsageAndQuota_Unlimited) {
{ "http://unlimited/", kTemp, 4000 },
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1065,7 +1065,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_MultiOrigins) {
{ "http://baz.com/", kPerm, 30 },
{ "http://foo.com/", kTemp, 40 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
SetPersistentHostQuota("foo.com", 100);
@@ -1087,7 +1087,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_WithAdditionalTasks) {
{ "http://bar.com/", kPerm, 13 },
{ "http://foo.com/", kTemp, 40 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
SetPersistentHostQuota("foo.com", 100);
@@ -1117,7 +1117,7 @@ TEST_F(QuotaManagerTest, GetPersistentUsageAndQuota_NukeManager) {
{ "http://bar.com/", kPerm, 13 },
{ "http://foo.com/", kTemp, 40 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
SetPersistentHostQuota("foo.com", 100);
@@ -1142,7 +1142,7 @@ TEST_F(QuotaManagerTest, GetUsage_Simple) {
{ "http://bar.com:1/", kPerm, 600000 },
{ "http://foo.com/", kTemp, 7000000 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
GetGlobalUsage(kPerm);
@@ -1175,7 +1175,7 @@ TEST_F(QuotaManagerTest, GetUsage_WithModification) {
{ "http://foo.com/", kTemp, 7000000 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1224,7 +1224,7 @@ TEST_F(QuotaManagerTest, GetUsage_WithDeleteOrigin) {
{ "http://foo.com/", kPerm, 300 },
{ "http://bar.com/", kTemp, 4000 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1279,9 +1279,9 @@ TEST_F(QuotaManagerTest, EvictOriginData) {
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -1298,10 +1298,10 @@ TEST_F(QuotaManagerTest, EvictOriginData) {
base::RunLoop().RunUntilIdle();
int64 predelete_host_pers = usage();
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData1); ++i)
+ for (size_t i = 0; i < arraysize(kData1); ++i)
quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown,
GURL(kData1[i].origin), kData1[i].type);
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData2); ++i)
+ for (size_t i = 0; i < arraysize(kData2); ++i)
quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown,
GURL(kData2[i].origin), kData2[i].type);
base::RunLoop().RunUntilIdle();
@@ -1341,7 +1341,7 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
{ "http://bar.com/", kTemp, 4000 },
};
static const int kNumberOfTemporaryOrigins = 3;
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1357,7 +1357,7 @@ TEST_F(QuotaManagerTest, EvictOriginDataWithDeletionError) {
base::RunLoop().RunUntilIdle();
int64 predelete_host_pers = usage();
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData); ++i)
+ for (size_t i = 0; i < arraysize(kData); ++i)
NotifyStorageAccessed(client, GURL(kData[i].origin), kData[i].type);
base::RunLoop().RunUntilIdle();
@@ -1427,7 +1427,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuotaForEviction) {
};
mock_special_storage_policy()->AddUnlimited(GURL("http://unlimited/"));
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1446,7 +1446,7 @@ TEST_F(QuotaManagerTest, DeleteHostDataSimple) {
static const MockOriginData kData[] = {
{ "http://foo.com/", kTemp, 1 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1509,9 +1509,9 @@ TEST_F(QuotaManagerTest, DeleteHostDataMultiple) {
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -1597,9 +1597,9 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
{ "https://foo.com/", kTemp, 80 },
{ "http://bar.com/", kTemp, 9 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -1624,10 +1624,10 @@ TEST_F(QuotaManagerTest, DeleteOriginDataMultiple) {
base::RunLoop().RunUntilIdle();
const int64 predelete_bar_pers = usage();
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData1); ++i)
+ for (size_t i = 0; i < arraysize(kData1); ++i)
quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown,
GURL(kData1[i].origin), kData1[i].type);
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData2); ++i)
+ for (size_t i = 0; i < arraysize(kData2); ++i)
quota_manager()->NotifyStorageAccessed(QuotaClient::kUnknown,
GURL(kData2[i].origin), kData2[i].type);
base::RunLoop().RunUntilIdle();
@@ -1681,7 +1681,7 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) {
{ "http://b.com/", kPerm, 300 },
{ "http://c.com/", kTemp, 4000 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1711,7 +1711,7 @@ TEST_F(QuotaManagerTest, GetCachedOrigins) {
GetCachedOrigins(kTemp, &origins);
EXPECT_EQ(3U, origins.size());
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData); ++i) {
+ for (size_t i = 0; i < arraysize(kData); ++i) {
if (kData[i].type == kTemp)
EXPECT_TRUE(origins.find(GURL(kData[i].origin)) != origins.end());
}
@@ -1725,7 +1725,7 @@ TEST_F(QuotaManagerTest, NotifyAndLRUOrigin) {
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1765,7 +1765,7 @@ TEST_F(QuotaManagerTest, GetLRUOriginWithOriginInUse) {
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1820,7 +1820,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
{ "http://b.com/", kPerm, 0 }, // persistent
{ "http://c.com/", kTemp, 0 },
};
- MockStorageClient* client = CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ MockStorageClient* client = CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem);
RegisterClient(client);
@@ -1842,7 +1842,7 @@ TEST_F(QuotaManagerTest, GetOriginsModifiedSince) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(4U, modified_origins().size());
EXPECT_EQ(modified_origins_type(), kTemp);
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kData); ++i) {
+ for (size_t i = 0; i < arraysize(kData); ++i) {
if (kData[i].type == kTemp)
EXPECT_EQ(1U, modified_origins().count(GURL(kData[i].origin)));
}
@@ -1879,8 +1879,7 @@ TEST_F(QuotaManagerTest, DumpQuotaTable) {
QuotaTableEntry("example2.com", kPerm, 20),
QuotaTableEntry("example3.com", kPerm, 300),
};
- std::set<QuotaTableEntry> entries
- (kEntries, kEntries + ARRAYSIZE_UNSAFE(kEntries));
+ std::set<QuotaTableEntry> entries(kEntries, kEntries + arraysize(kEntries));
typedef QuotaTableEntries::const_iterator iterator;
for (iterator itr(quota_entries().begin()), end(quota_entries().end());
@@ -1919,8 +1918,7 @@ TEST_F(QuotaManagerTest, DumpOriginInfoTable) {
make_pair(make_pair(GURL("http://example.com/"), kTemp), 1),
make_pair(make_pair(GURL("http://example.com/"), kPerm), 2),
};
- std::set<Entry> entries
- (kEntries, kEntries + ARRAYSIZE_UNSAFE(kEntries));
+ std::set<Entry> entries(kEntries, kEntries + arraysize(kEntries));
typedef OriginInfoTableEntries::const_iterator iterator;
for (iterator itr(origin_info_entries().begin()),
@@ -1961,13 +1959,13 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleOrigin) {
static const MockOriginData kData4[] = {
{ "http://foo.com/", kTemp, 8 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kAppcache);
- MockStorageClient* client3 = CreateClient(kData3, ARRAYSIZE_UNSAFE(kData3),
+ MockStorageClient* client3 = CreateClient(kData3, arraysize(kData3),
QuotaClient::kDatabase);
- MockStorageClient* client4 = CreateClient(kData4, ARRAYSIZE_UNSAFE(kData4),
+ MockStorageClient* client4 = CreateClient(kData4, arraysize(kData4),
QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -2017,13 +2015,13 @@ TEST_F(QuotaManagerTest, DeleteSpecificClientTypeSingleHost) {
static const MockOriginData kData4[] = {
{ "http://foo.com:4444/", kTemp, 8 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kAppcache);
- MockStorageClient* client3 = CreateClient(kData3, ARRAYSIZE_UNSAFE(kData3),
+ MockStorageClient* client3 = CreateClient(kData3, arraysize(kData3),
QuotaClient::kDatabase);
- MockStorageClient* client4 = CreateClient(kData4, ARRAYSIZE_UNSAFE(kData4),
+ MockStorageClient* client4 = CreateClient(kData4, arraysize(kData4),
QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -2072,13 +2070,13 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleOrigin) {
static const MockOriginData kData4[] = {
{ "http://foo.com/", kTemp, 8 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kAppcache);
- MockStorageClient* client3 = CreateClient(kData3, ARRAYSIZE_UNSAFE(kData3),
+ MockStorageClient* client3 = CreateClient(kData3, arraysize(kData3),
QuotaClient::kDatabase);
- MockStorageClient* client4 = CreateClient(kData4, ARRAYSIZE_UNSAFE(kData4),
+ MockStorageClient* client4 = CreateClient(kData4, arraysize(kData4),
QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -2117,13 +2115,13 @@ TEST_F(QuotaManagerTest, DeleteMultipleClientTypesSingleHost) {
static const MockOriginData kData4[] = {
{ "http://foo.com:4444/", kTemp, 8 },
};
- MockStorageClient* client1 = CreateClient(kData1, ARRAYSIZE_UNSAFE(kData1),
+ MockStorageClient* client1 = CreateClient(kData1, arraysize(kData1),
QuotaClient::kFileSystem);
- MockStorageClient* client2 = CreateClient(kData2, ARRAYSIZE_UNSAFE(kData2),
+ MockStorageClient* client2 = CreateClient(kData2, arraysize(kData2),
QuotaClient::kAppcache);
- MockStorageClient* client3 = CreateClient(kData3, ARRAYSIZE_UNSAFE(kData3),
+ MockStorageClient* client3 = CreateClient(kData3, arraysize(kData3),
QuotaClient::kDatabase);
- MockStorageClient* client4 = CreateClient(kData4, ARRAYSIZE_UNSAFE(kData4),
+ MockStorageClient* client4 = CreateClient(kData4, arraysize(kData4),
QuotaClient::kIndexedDatabase);
RegisterClient(client1);
RegisterClient(client2);
@@ -2156,7 +2154,7 @@ TEST_F(QuotaManagerTest, GetUsageAndQuota_Incognito) {
{ "http://foo.com/", kTemp, 10 },
{ "http://foo.com/", kPerm, 80 },
};
- RegisterClient(CreateClient(kData, ARRAYSIZE_UNSAFE(kData),
+ RegisterClient(CreateClient(kData, arraysize(kData),
QuotaClient::kFileSystem));
GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kPerm);
diff --git a/chromium/content/browser/quota/quota_reservation_manager_unittest.cc b/chromium/content/browser/quota/quota_reservation_manager_unittest.cc
index 84caddcd0ed..61de3d574e8 100644
--- a/chromium/content/browser/quota/quota_reservation_manager_unittest.cc
+++ b/chromium/content/browser/quota/quota_reservation_manager_unittest.cc
@@ -2,30 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/browser/fileapi/quota/quota_reservation_manager.h"
+#include "storage/browser/fileapi/quota/quota_reservation_manager.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "storage/browser/fileapi/quota/open_file_handle.h"
+#include "storage/browser/fileapi/quota/quota_reservation.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/quota/open_file_handle.h"
-#include "webkit/browser/fileapi/quota/quota_reservation.h"
-using fileapi::kFileSystemTypeTemporary;
-using fileapi::OpenFileHandle;
-using fileapi::QuotaReservation;
-using fileapi::QuotaReservationManager;
+using storage::kFileSystemTypeTemporary;
+using storage::OpenFileHandle;
+using storage::QuotaReservation;
+using storage::QuotaReservationManager;
namespace content {
namespace {
const char kOrigin[] = "http://example.com";
-const fileapi::FileSystemType kType = kFileSystemTypeTemporary;
+const storage::FileSystemType kType = kFileSystemTypeTemporary;
const int64 kInitialFileSize = 1;
typedef QuotaReservationManager::ReserveQuotaCallback ReserveQuotaCallback;
@@ -47,12 +47,12 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend {
FakeBackend()
: on_memory_usage_(kInitialFileSize),
on_disk_usage_(kInitialFileSize) {}
- virtual ~FakeBackend() {}
+ ~FakeBackend() override {}
- virtual void ReserveQuota(const GURL& origin,
- fileapi::FileSystemType type,
- int64 delta,
- const ReserveQuotaCallback& callback) OVERRIDE {
+ void ReserveQuota(const GURL& origin,
+ storage::FileSystemType type,
+ int64 delta,
+ const ReserveQuotaCallback& callback) override {
EXPECT_EQ(GURL(kOrigin), origin);
EXPECT_EQ(kType, type);
on_memory_usage_ += delta;
@@ -61,28 +61,28 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend {
base::Bind(base::IgnoreResult(callback), base::File::FILE_OK, delta));
}
- virtual void ReleaseReservedQuota(const GURL& origin,
- fileapi::FileSystemType type,
- int64 size) OVERRIDE {
+ void ReleaseReservedQuota(const GURL& origin,
+ storage::FileSystemType type,
+ int64 size) override {
EXPECT_LE(0, size);
EXPECT_EQ(GURL(kOrigin), origin);
EXPECT_EQ(kType, type);
on_memory_usage_ -= size;
}
- virtual void CommitQuotaUsage(const GURL& origin,
- fileapi::FileSystemType type,
- int64 delta) OVERRIDE {
+ void CommitQuotaUsage(const GURL& origin,
+ storage::FileSystemType type,
+ int64 delta) override {
EXPECT_EQ(GURL(kOrigin), origin);
EXPECT_EQ(kType, type);
on_disk_usage_ += delta;
on_memory_usage_ += delta;
}
- virtual void IncrementDirtyCount(const GURL& origin,
- fileapi::FileSystemType type) OVERRIDE {}
- virtual void DecrementDirtyCount(const GURL& origin,
- fileapi::FileSystemType type) OVERRIDE {}
+ void IncrementDirtyCount(const GURL& origin,
+ storage::FileSystemType type) override {}
+ void DecrementDirtyCount(const GURL& origin,
+ storage::FileSystemType type) override {}
int64 on_memory_usage() { return on_memory_usage_; }
int64 on_disk_usage() { return on_disk_usage_; }
@@ -180,9 +180,9 @@ void RefreshReservation(QuotaReservation* reservation, int64 size) {
class QuotaReservationManagerTest : public testing::Test {
public:
QuotaReservationManagerTest() {}
- virtual ~QuotaReservationManagerTest() {}
+ ~QuotaReservationManagerTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(work_dir_.CreateUniqueTempDir());
file_path_ = work_dir_.path().Append(FILE_PATH_LITERAL("hoge"));
SetFileSize(file_path_, kInitialFileSize);
@@ -191,9 +191,7 @@ class QuotaReservationManagerTest : public testing::Test {
reservation_manager_.reset(new QuotaReservationManager(backend.Pass()));
}
- virtual void TearDown() OVERRIDE {
- reservation_manager_.reset();
- }
+ void TearDown() override { reservation_manager_.reset(); }
FakeBackend* fake_backend() {
return static_cast<FakeBackend*>(reservation_manager_->backend_.get());
@@ -294,12 +292,12 @@ TEST_F(QuotaReservationManagerTest, MultipleWriter) {
TEST_F(QuotaReservationManagerTest, MultipleClient) {
scoped_refptr<QuotaReservation> reservation1 =
reservation_manager()->CreateReservation(GURL(kOrigin), kType);
- RefreshReservation(reservation1, 10);
+ RefreshReservation(reservation1.get(), 10);
int64 cached_reserved_quota1 = reservation1->remaining_quota();
scoped_refptr<QuotaReservation> reservation2 =
reservation_manager()->CreateReservation(GURL(kOrigin), kType);
- RefreshReservation(reservation2, 20);
+ RefreshReservation(reservation2.get(), 20);
int64 cached_reserved_quota2 = reservation2->remaining_quota();
scoped_ptr<FakeWriter> writer1(
diff --git a/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc b/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc
index a9d93f6bb9d..6c00c0f877f 100644
--- a/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc
+++ b/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -13,13 +13,13 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "content/public/test/mock_storage_client.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_temporary_storage_evictor.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/quota_temporary_storage_evictor.h"
-using quota::QuotaTemporaryStorageEvictor;
-using quota::StorageType;
-using quota::UsageAndQuota;
+using storage::QuotaTemporaryStorageEvictor;
+using storage::StorageType;
+using storage::UsageAndQuota;
namespace content {
@@ -27,7 +27,7 @@ class QuotaTemporaryStorageEvictorTest;
namespace {
-class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
+class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler {
public:
explicit MockQuotaEvictionHandler(QuotaTemporaryStorageEvictorTest *test)
: quota_(0),
@@ -35,35 +35,33 @@ class MockQuotaEvictionHandler : public quota::QuotaEvictionHandler {
error_on_evict_origin_data_(false),
error_on_get_usage_and_quota_(false) {}
- virtual void EvictOriginData(
- const GURL& origin,
- StorageType type,
- const EvictOriginDataCallback& callback) OVERRIDE {
+ void EvictOriginData(const GURL& origin,
+ StorageType type,
+ const EvictOriginDataCallback& callback) override {
if (error_on_evict_origin_data_) {
- callback.Run(quota::kQuotaErrorInvalidModification);
+ callback.Run(storage::kQuotaErrorInvalidModification);
return;
}
int64 origin_usage = EnsureOriginRemoved(origin);
if (origin_usage >= 0)
available_space_ += origin_usage;
- callback.Run(quota::kQuotaStatusOk);
+ callback.Run(storage::kQuotaStatusOk);
}
- virtual void GetUsageAndQuotaForEviction(
- const UsageAndQuotaCallback& callback) OVERRIDE {
+ void GetUsageAndQuotaForEviction(
+ const UsageAndQuotaCallback& callback) override {
if (error_on_get_usage_and_quota_) {
- callback.Run(quota::kQuotaErrorInvalidAccess, UsageAndQuota());
+ callback.Run(storage::kQuotaErrorInvalidAccess, UsageAndQuota());
return;
}
if (!task_for_get_usage_and_quota_.is_null())
task_for_get_usage_and_quota_.Run();
UsageAndQuota quota_and_usage(-1, GetUsage(), quota_, available_space_);
- callback.Run(quota::kQuotaStatusOk, quota_and_usage);
+ callback.Run(storage::kQuotaStatusOk, quota_and_usage);
}
- virtual void GetLRUOrigin(
- StorageType type,
- const GetLRUOriginCallback& callback) OVERRIDE {
+ void GetLRUOrigin(StorageType type,
+ const GetLRUOriginCallback& callback) override {
if (origin_order_.empty())
callback.Run(GURL());
else
@@ -143,7 +141,7 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test {
: num_get_usage_and_quota_for_eviction_(0),
weak_factory_(this) {}
- virtual void SetUp() {
+ void SetUp() override {
quota_eviction_handler_.reset(new MockQuotaEvictionHandler(this));
// Run multiple evictions in a single RunUntilIdle() when interval_ms == 0
@@ -151,7 +149,7 @@ class QuotaTemporaryStorageEvictorTest : public testing::Test {
quota_eviction_handler_.get(), 0));
}
- virtual void TearDown() {
+ void TearDown() override {
temporary_storage_evictor_.reset();
quota_eviction_handler_.reset();
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/quota/storage_monitor_unittest.cc b/chromium/content/browser/quota/storage_monitor_unittest.cc
index 5926e9ac1fd..78599de7472 100644
--- a/chromium/content/browser/quota/storage_monitor_unittest.cc
+++ b/chromium/content/browser/quota/storage_monitor_unittest.cc
@@ -11,26 +11,26 @@
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/mock_storage_client.h"
#include "net/base/net_util.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/storage_monitor.h"
+#include "storage/browser/quota/storage_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/browser/quota/storage_monitor.h"
-#include "webkit/browser/quota/storage_observer.h"
-
-using quota::HostStorageObservers;
-using quota::kQuotaErrorNotSupported;
-using quota::kQuotaStatusOk;
-using quota::kStorageTypePersistent;
-using quota::kStorageTypeTemporary;
-using quota::QuotaClient;
-using quota::QuotaManager;
-using quota::QuotaStatusCode;
-using quota::SpecialStoragePolicy;
-using quota::StorageMonitor;
-using quota::StorageObserver;
-using quota::StorageObserverList;
-using quota::StorageType;
-using quota::StorageTypeObservers;
+
+using storage::HostStorageObservers;
+using storage::kQuotaErrorNotSupported;
+using storage::kQuotaStatusOk;
+using storage::kStorageTypePersistent;
+using storage::kStorageTypeTemporary;
+using storage::QuotaClient;
+using storage::QuotaManager;
+using storage::QuotaStatusCode;
+using storage::SpecialStoragePolicy;
+using storage::StorageMonitor;
+using storage::StorageObserver;
+using storage::StorageObserverList;
+using storage::StorageType;
+using storage::StorageTypeObservers;
namespace content {
@@ -51,7 +51,7 @@ class MockObserver : public StorageObserver {
}
// StorageObserver implementation:
- virtual void OnStorageEvent(const StorageObserver::Event& event) OVERRIDE {
+ void OnStorageEvent(const StorageObserver::Event& event) override {
events_.push_back(event);
}
@@ -86,10 +86,10 @@ class UsageMockQuotaManager : public QuotaManager {
delayed_callback_.Run(callback_status_, callback_usage_, callback_quota_);
}
- virtual void GetUsageAndQuotaForWebApps(
+ void GetUsageAndQuotaForWebApps(
const GURL& origin,
StorageType type,
- const GetUsageAndQuotaCallback& callback) OVERRIDE {
+ const GetUsageAndQuotaCallback& callback) override {
if (initialized_)
callback.Run(callback_status_, callback_usage_, callback_quota_);
else
@@ -97,7 +97,7 @@ class UsageMockQuotaManager : public QuotaManager {
}
protected:
- virtual ~UsageMockQuotaManager() {}
+ ~UsageMockQuotaManager() override {}
private:
int64 callback_usage_;
@@ -164,12 +164,12 @@ class StorageMonitorTestBase : public testing::Test {
class StorageTestWithManagerBase : public StorageMonitorTestBase {
public:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
storage_policy_ = new MockSpecialStoragePolicy();
quota_manager_ = new UsageMockQuotaManager(storage_policy_.get());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// This ensures the quota manager is destroyed correctly.
quota_manager_ = NULL;
base::RunLoop().RunUntilIdle();
@@ -563,7 +563,7 @@ class StorageMonitorTest : public StorageTestWithManagerBase {
}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
StorageTestWithManagerBase::SetUp();
storage_monitor_ = quota_manager_->storage_monitor_.get();
@@ -645,7 +645,7 @@ TEST_F(StorageMonitorTest, RemoveObserverForFilter) {
class StorageMonitorIntegrationTest : public testing::Test {
public:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
storage_policy_ = new MockSpecialStoragePolicy();
quota_manager_ = new QuotaManager(
@@ -663,7 +663,7 @@ class StorageMonitorIntegrationTest : public testing::Test {
quota_manager_->proxy()->RegisterClient(client_);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// This ensures the quota manager is destroyed correctly.
quota_manager_ = NULL;
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/quota/usage_tracker_unittest.cc b/chromium/content/browser/quota/usage_tracker_unittest.cc
index 3cba8bd4791..786146ab7d5 100644
--- a/chromium/content/browser/quota/usage_tracker_unittest.cc
+++ b/chromium/content/browser/quota/usage_tracker_unittest.cc
@@ -6,16 +6,16 @@
#include "base/run_loop.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "net/base/net_util.h"
+#include "storage/browser/quota/usage_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/quota/usage_tracker.h"
-using quota::kQuotaStatusOk;
-using quota::kStorageTypeTemporary;
-using quota::QuotaClient;
-using quota::QuotaClientList;
-using quota::SpecialStoragePolicy;
-using quota::StorageType;
-using quota::UsageTracker;
+using storage::kQuotaStatusOk;
+using storage::kStorageTypeTemporary;
+using storage::QuotaClient;
+using storage::QuotaClientList;
+using storage::SpecialStoragePolicy;
+using storage::StorageType;
+using storage::UsageTracker;
namespace content {
@@ -45,25 +45,23 @@ void DidGetUsage(bool* done,
class MockQuotaClient : public QuotaClient {
public:
MockQuotaClient() {}
- virtual ~MockQuotaClient() {}
+ ~MockQuotaClient() override {}
- virtual ID id() const OVERRIDE {
- return kFileSystem;
- }
+ ID id() const override { return kFileSystem; }
- virtual void OnQuotaManagerDestroyed() OVERRIDE {}
+ void OnQuotaManagerDestroyed() override {}
- virtual void GetOriginUsage(const GURL& origin,
- StorageType type,
- const GetUsageCallback& callback) OVERRIDE {
+ void GetOriginUsage(const GURL& origin,
+ StorageType type,
+ const GetUsageCallback& callback) override {
EXPECT_EQ(kStorageTypeTemporary, type);
int64 usage = GetUsage(origin);
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, usage));
}
- virtual void GetOriginsForType(StorageType type,
- const GetOriginsCallback& callback) OVERRIDE {
+ void GetOriginsForType(StorageType type,
+ const GetOriginsCallback& callback) override {
EXPECT_EQ(kStorageTypeTemporary, type);
std::set<GURL> origins;
for (UsageMap::const_iterator itr = usage_map_.begin();
@@ -74,9 +72,9 @@ class MockQuotaClient : public QuotaClient {
base::Bind(callback, origins));
}
- virtual void GetOriginsForHost(StorageType type,
- const std::string& host,
- const GetOriginsCallback& callback) OVERRIDE {
+ void GetOriginsForHost(StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) override {
EXPECT_EQ(kStorageTypeTemporary, type);
std::set<GURL> origins;
for (UsageMap::const_iterator itr = usage_map_.begin();
@@ -88,17 +86,17 @@ class MockQuotaClient : public QuotaClient {
base::Bind(callback, origins));
}
- virtual void DeleteOriginData(const GURL& origin,
- StorageType type,
- const DeletionCallback& callback) OVERRIDE {
+ void DeleteOriginData(const GURL& origin,
+ StorageType type,
+ const DeletionCallback& callback) override {
EXPECT_EQ(kStorageTypeTemporary, type);
usage_map_.erase(origin);
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(callback, kQuotaStatusOk));
}
- virtual bool DoesSupport(quota::StorageType type) const OVERRIDE {
- return type == quota::kStorageTypeTemporary;
+ bool DoesSupport(storage::StorageType type) const override {
+ return type == storage::kStorageTypeTemporary;
}
int64 GetUsage(const GURL& origin) {
@@ -132,7 +130,7 @@ class UsageTrackerTest : public testing::Test {
storage_policy_.get(), NULL) {
}
- virtual ~UsageTrackerTest() {}
+ ~UsageTrackerTest() override {}
UsageTracker* usage_tracker() {
return &usage_tracker_;
diff --git a/chromium/content/browser/quota_dispatcher_host.cc b/chromium/content/browser/quota_dispatcher_host.cc
index fcee63396e5..2ea8a5ec9b5 100644
--- a/chromium/content/browser/quota_dispatcher_host.cc
+++ b/chromium/content/browser/quota_dispatcher_host.cc
@@ -10,13 +10,13 @@
#include "content/common/quota_messages.h"
#include "content/public/browser/quota_permission_context.h"
#include "net/base/net_util.h"
+#include "storage/browser/quota/quota_manager.h"
#include "url/gurl.h"
-#include "webkit/browser/quota/quota_manager.h"
-using quota::QuotaClient;
-using quota::QuotaManager;
-using quota::QuotaStatusCode;
-using quota::StorageType;
+using storage::QuotaClient;
+using storage::QuotaManager;
+using storage::QuotaStatusCode;
+using storage::StorageType;
namespace content {
@@ -44,7 +44,7 @@ class QuotaDispatcherHost::RequestDispatcher {
QuotaDispatcherHost* dispatcher_host() const {
return dispatcher_host_.get();
}
- quota::QuotaManager* quota_manager() const {
+ storage::QuotaManager* quota_manager() const {
return dispatcher_host_ ? dispatcher_host_->quota_manager_ : NULL;
}
QuotaPermissionContext* permission_context() const {
@@ -68,7 +68,7 @@ class QuotaDispatcherHost::QueryUsageAndQuotaDispatcher
int request_id)
: RequestDispatcher(dispatcher_host, request_id),
weak_factory_(this) {}
- virtual ~QueryUsageAndQuotaDispatcher() {}
+ ~QueryUsageAndQuotaDispatcher() override {}
void QueryStorageUsageAndQuota(const GURL& origin, StorageType type) {
quota_manager()->GetUsageAndQuotaForWebApps(
@@ -82,7 +82,7 @@ class QuotaDispatcherHost::QueryUsageAndQuotaDispatcher
QuotaStatusCode status, int64 usage, int64 quota) {
if (!dispatcher_host())
return;
- if (status != quota::kQuotaStatusOk) {
+ if (status != storage::kQuotaStatusOk) {
dispatcher_host()->Send(new QuotaMsg_DidFail(request_id(), status));
} else {
dispatcher_host()->Send(new QuotaMsg_DidQueryStorageUsageAndQuota(
@@ -112,15 +112,15 @@ class QuotaDispatcherHost::RequestQuotaDispatcher
// TODO(nhiroki): The backend should accept uint64 values.
requested_quota_ = base::saturated_cast<int64>(params_.requested_size);
}
- virtual ~RequestQuotaDispatcher() {}
+ ~RequestQuotaDispatcher() override {}
void Start() {
DCHECK(dispatcher_host());
- DCHECK(params_.storage_type == quota::kStorageTypeTemporary ||
- params_.storage_type == quota::kStorageTypePersistent ||
- params_.storage_type == quota::kStorageTypeSyncable);
- if (params_.storage_type == quota::kStorageTypePersistent) {
+ DCHECK(params_.storage_type == storage::kStorageTypeTemporary ||
+ params_.storage_type == storage::kStorageTypePersistent ||
+ params_.storage_type == storage::kStorageTypeSyncable);
+ if (params_.storage_type == storage::kStorageTypePersistent) {
quota_manager()->GetUsageAndQuotaForWebApps(
params_.origin_url, params_.storage_type,
base::Bind(&self_type::DidGetPersistentUsageAndQuota,
@@ -139,7 +139,7 @@ class QuotaDispatcherHost::RequestQuotaDispatcher
int64 quota) {
if (!dispatcher_host())
return;
- if (status != quota::kQuotaStatusOk) {
+ if (status != storage::kQuotaStatusOk) {
DidFinish(status, 0, 0);
return;
}
@@ -148,7 +148,7 @@ class QuotaDispatcherHost::RequestQuotaDispatcher
params_.storage_type) ||
requested_quota_ <= quota) {
// Seems like we can just let it go.
- DidFinish(quota::kQuotaStatusOk, usage, params_.requested_size);
+ DidFinish(storage::kQuotaStatusOk, usage, params_.requested_size);
return;
}
current_usage_ = usage;
@@ -174,7 +174,7 @@ class QuotaDispatcherHost::RequestQuotaDispatcher
return;
if (response != QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW) {
// User didn't allow the new quota. Just returning the current quota.
- DidFinish(quota::kQuotaStatusOk, current_usage_, current_quota_);
+ DidFinish(storage::kQuotaStatusOk, current_usage_, current_quota_);
return;
}
// Now we're allowed to set the new quota.
@@ -193,7 +193,7 @@ class QuotaDispatcherHost::RequestQuotaDispatcher
if (!dispatcher_host())
return;
DCHECK(dispatcher_host());
- if (status != quota::kQuotaStatusOk) {
+ if (status != storage::kQuotaStatusOk) {
dispatcher_host()->Send(new QuotaMsg_DidFail(request_id(), status));
} else {
dispatcher_host()->Send(new QuotaMsg_DidGrantStorageQuota(
@@ -245,11 +245,11 @@ void QuotaDispatcherHost::OnQueryStorageUsageAndQuota(
void QuotaDispatcherHost::OnRequestStorageQuota(
const StorageQuotaParams& params) {
- if (params.storage_type != quota::kStorageTypeTemporary &&
- params.storage_type != quota::kStorageTypePersistent) {
+ if (params.storage_type != storage::kStorageTypeTemporary &&
+ params.storage_type != storage::kStorageTypePersistent) {
// Unsupported storage types.
Send(new QuotaMsg_DidFail(params.request_id,
- quota::kQuotaErrorNotSupported));
+ storage::kQuotaErrorNotSupported));
return;
}
diff --git a/chromium/content/browser/quota_dispatcher_host.h b/chromium/content/browser/quota_dispatcher_host.h
index d241ab59c37..8a30f229f81 100644
--- a/chromium/content/browser/quota_dispatcher_host.h
+++ b/chromium/content/browser/quota_dispatcher_host.h
@@ -8,7 +8,7 @@
#include "base/basictypes.h"
#include "base/id_map.h"
#include "content/public/browser/browser_message_filter.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/common/quota/quota_types.h"
class GURL;
@@ -16,7 +16,7 @@ namespace IPC {
class Message;
}
-namespace quota {
+namespace storage {
class QuotaManager;
}
@@ -27,30 +27,29 @@ struct StorageQuotaParams;
class QuotaDispatcherHost : public BrowserMessageFilter {
public:
QuotaDispatcherHost(int process_id,
- quota::QuotaManager* quota_manager,
+ storage::QuotaManager* quota_manager,
QuotaPermissionContext* permission_context);
// BrowserMessageFilter:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~QuotaDispatcherHost();
+ ~QuotaDispatcherHost() override;
private:
class RequestDispatcher;
class QueryUsageAndQuotaDispatcher;
class RequestQuotaDispatcher;
- void OnQueryStorageUsageAndQuota(
- int request_id,
- const GURL& origin_url,
- quota::StorageType type);
+ void OnQueryStorageUsageAndQuota(int request_id,
+ const GURL& origin_url,
+ storage::StorageType type);
void OnRequestStorageQuota(const StorageQuotaParams& params);
// The ID of this process.
int process_id_;
- quota::QuotaManager* quota_manager_;
+ storage::QuotaManager* quota_manager_;
scoped_refptr<QuotaPermissionContext> permission_context_;
IDMap<RequestDispatcher, IDMapOwnPointer> outstanding_requests_;
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index 55a8ec5f01d..3afe25bd977 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -15,7 +15,7 @@ include_rules = [
]
specific_include_rules = {
- ".*_(unit|browser)test\.cc": [
+ ".*_(unit|browser)test\.(cc|mm)": [
"+content/browser/frame_host",
"+content/browser/web_contents",
"+content/public/browser/web_contents.h",
diff --git a/chromium/content/browser/renderer_host/OWNERS b/chromium/content/browser/renderer_host/OWNERS
index 9d25787925e..2e48dfae455 100644
--- a/chromium/content/browser/renderer_host/OWNERS
+++ b/chromium/content/browser/renderer_host/OWNERS
@@ -1,8 +1,11 @@
# for *aura*
-per-file *aura*=ben@chromium.org
+per-file *aura*=sadrul@chromium.org
+
+# Windows.
+per-file *win*=ananta@chromium.org
# for *mac*
-thakis@chromium.org
+asvitkine@chromium.org
# for GPU-related stuff in *mac*
kbr@chromium.org
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.h b/chromium/content/browser/renderer_host/clipboard_message_filter.h
index 3fcb94edc7a..792bfc5b774 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.h
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.h
@@ -21,12 +21,12 @@ class ClipboardMessageFilter : public BrowserMessageFilter {
public:
ClipboardMessageFilter();
- virtual void OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
private:
- virtual ~ClipboardMessageFilter();
+ ~ClipboardMessageFilter() override;
void OnWriteObjectsAsync(const ui::Clipboard::ObjectMap& objects);
void OnWriteObjectsSync(const ui::Clipboard::ObjectMap& objects,
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h
deleted file mode 100644
index 52a98989293..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_CONTEXT_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_CONTEXT_MAC_H_
-
-#import <AppKit/NSOpenGL.h>
-#include <OpenGL/OpenGL.h>
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/lazy_instance.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/public/browser/gpu_data_manager_observer.h"
-#include "ui/gl/scoped_cgl.h"
-
-namespace content {
-
-class CompositingIOSurfaceShaderPrograms;
-
-class CompositingIOSurfaceContext
- : public base::RefCounted<CompositingIOSurfaceContext>,
- public content::GpuDataManagerObserver {
- public:
- enum {
- // The number used to look up the context used for async readback and for
- // initializing the IOSurface.
- kOffscreenContextWindowNumber = -2,
- // The number used to look up the context used by CAOpenGLLayers.
- kCALayerContextWindowNumber = -3,
- };
-
- // Get or create a GL context for the specified window with the specified
- // surface ordering. Share these GL contexts as much as possible because
- // creating and destroying them can be expensive
- // http://crbug.com/180463
- static scoped_refptr<CompositingIOSurfaceContext> Get(int window_number);
-
- // Mark that all the GL contexts in the same sharegroup as this context as
- // invalid, so they shouldn't be returned anymore by Get, but rather, new
- // contexts should be created. This is called as a precaution when unexpected
- // GL errors occur.
- void PoisonContextAndSharegroup();
- bool HasBeenPoisoned() const { return poisoned_; }
-
- CompositingIOSurfaceShaderPrograms* shader_program_cache() const {
- return shader_program_cache_.get();
- }
- CGLContextObj cgl_context() const { return cgl_context_; }
- bool is_vsync_disabled() const { return is_vsync_disabled_; }
- int window_number() const { return window_number_; }
-
- // content::GpuDataManagerObserver implementation.
- virtual void OnGpuSwitching() OVERRIDE;
-
- private:
- friend class base::RefCounted<CompositingIOSurfaceContext>;
-
- CompositingIOSurfaceContext(
- int window_number,
- base::ScopedTypeRef<CGLContextObj> clg_context_strong,
- CGLContextObj clg_context,
- bool is_vsync_disabled_,
- scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache);
- virtual ~CompositingIOSurfaceContext();
-
- int window_number_;
- base::ScopedTypeRef<CGLContextObj> cgl_context_strong_;
- // Weak, backed by |cgl_context_strong_|.
- CGLContextObj cgl_context_;
-
- bool is_vsync_disabled_;
- scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache_;
- bool poisoned_;
-
- // The global map from window number and window ordering to
- // context data.
- typedef std::map<int, CompositingIOSurfaceContext*> WindowMap;
- static base::LazyInstance<WindowMap> window_map_;
- static WindowMap* window_map();
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_CONTEXT_MAC_H_
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm
deleted file mode 100644
index a66bf5022d3..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_context_mac.mm
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/renderer_host/compositing_iosurface_context_mac.h"
-
-#include <OpenGL/gl.h>
-#include <OpenGL/OpenGL.h>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/gl/gl_switches.h"
-#include "ui/gl/gpu_switching_manager.h"
-
-namespace content {
-
-// static
-scoped_refptr<CompositingIOSurfaceContext>
-CompositingIOSurfaceContext::Get(int window_number) {
- TRACE_EVENT0("browser", "CompositingIOSurfaceContext::Get");
-
- // Return the context for this window_number, if it exists.
- WindowMap::iterator found = window_map()->find(window_number);
- if (found != window_map()->end()) {
- DCHECK(!found->second->poisoned_);
- return found->second;
- }
-
- static bool is_vsync_disabled =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync);
-
- base::ScopedTypeRef<CGLContextObj> cgl_context_strong;
- CGLContextObj cgl_context = NULL;
- CGLError error = kCGLNoError;
-
- // Create the pixel format object for the context.
- std::vector<CGLPixelFormatAttribute> attribs;
- attribs.push_back(kCGLPFADepthSize);
- attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
- attribs.push_back(kCGLPFAAllowOfflineRenderers);
- attribs.push_back(static_cast<CGLPixelFormatAttribute>(1));
- }
- attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
- GLint number_virtual_screens = 0;
- base::ScopedTypeRef<CGLPixelFormatObj> pixel_format;
- error = CGLChoosePixelFormat(&attribs.front(),
- pixel_format.InitializeInto(),
- &number_virtual_screens);
- if (error != kCGLNoError) {
- LOG(ERROR) << "Failed to create pixel format object.";
- return NULL;
- }
-
- // Create all contexts in the same share group so that the textures don't
- // need to be recreated when transitioning contexts.
- CGLContextObj share_context = NULL;
- if (!window_map()->empty())
- share_context = window_map()->begin()->second->cgl_context();
- error = CGLCreateContext(
- pixel_format, share_context, cgl_context_strong.InitializeInto());
- if (error != kCGLNoError) {
- LOG(ERROR) << "Failed to create context object.";
- return NULL;
- }
- cgl_context = cgl_context_strong;
-
- // Note that VSync is ignored because CoreAnimation will automatically
- // rate limit draws.
-
- // Prepare the shader program cache. Precompile the shader programs
- // needed to draw the IO Surface for non-offscreen contexts.
- bool prepared = false;
- scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache;
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context);
- shader_program_cache.reset(new CompositingIOSurfaceShaderPrograms());
- if (window_number == kOffscreenContextWindowNumber) {
- prepared = true;
- } else {
- prepared = (
- shader_program_cache->UseBlitProgram() &&
- shader_program_cache->UseSolidWhiteProgram());
- }
- glUseProgram(0u);
- }
- if (!prepared) {
- LOG(ERROR) << "IOSurface failed to compile/link required shader programs.";
- return NULL;
- }
-
- return new CompositingIOSurfaceContext(
- window_number,
- cgl_context_strong,
- cgl_context,
- is_vsync_disabled,
- shader_program_cache.Pass());
-}
-
-void CompositingIOSurfaceContext::PoisonContextAndSharegroup() {
- if (poisoned_)
- return;
-
- for (WindowMap::iterator it = window_map()->begin();
- it != window_map()->end();
- ++it) {
- it->second->poisoned_ = true;
- }
- window_map()->clear();
-}
-
-CompositingIOSurfaceContext::CompositingIOSurfaceContext(
- int window_number,
- base::ScopedTypeRef<CGLContextObj> cgl_context_strong,
- CGLContextObj cgl_context,
- bool is_vsync_disabled,
- scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache)
- : window_number_(window_number),
- cgl_context_strong_(cgl_context_strong),
- cgl_context_(cgl_context),
- is_vsync_disabled_(is_vsync_disabled),
- shader_program_cache_(shader_program_cache.Pass()),
- poisoned_(false) {
- DCHECK(window_map()->find(window_number_) == window_map()->end());
- window_map()->insert(std::make_pair(window_number_, this));
-
- GpuDataManager::GetInstance()->AddObserver(this);
-}
-
-CompositingIOSurfaceContext::~CompositingIOSurfaceContext() {
- GpuDataManager::GetInstance()->RemoveObserver(this);
-
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context_);
- shader_program_cache_->Reset();
- }
- if (!poisoned_) {
- DCHECK(window_map()->find(window_number_) != window_map()->end());
- DCHECK(window_map()->find(window_number_)->second == this);
- window_map()->erase(window_number_);
- } else {
- WindowMap::const_iterator found = window_map()->find(window_number_);
- if (found != window_map()->end())
- DCHECK(found->second != this);
- }
-}
-
-void CompositingIOSurfaceContext::OnGpuSwitching() {
- // Recreate all browser-side GL contexts whenever the GPU switches. If this
- // is not done, performance will suffer.
- // http://crbug.com/361493
- PoisonContextAndSharegroup();
-}
-
-// static
-CompositingIOSurfaceContext::WindowMap*
- CompositingIOSurfaceContext::window_map() {
- return window_map_.Pointer();
-}
-
-// static
-base::LazyInstance<CompositingIOSurfaceContext::WindowMap>
- CompositingIOSurfaceContext::window_map_;
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.h
deleted file mode 100644
index 0449ae792c3..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2013 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 CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/ref_counted.h"
-#include "base/timer/timer.h"
-
-namespace content {
-class CompositingIOSurfaceMac;
-class CompositingIOSurfaceContext;
-class CompositingIOSurfaceLayerHelper;
-
-class CompositingIOSurfaceLayerClient {
- public:
- virtual void AcceleratedLayerDidDrawFrame(bool succeeded) = 0;
-};
-
-} // namespace content
-
-// The CoreAnimation layer for drawing accelerated content.
-@interface CompositingIOSurfaceLayer : CAOpenGLLayer {
- @private
- content::CompositingIOSurfaceLayerClient* client_;
- scoped_refptr<content::CompositingIOSurfaceMac> iosurface_;
- scoped_refptr<content::CompositingIOSurfaceContext> context_;
-
- // The browser places back-pressure on the GPU by not acknowledging swap
- // calls until they appear on the screen. This can lead to hangs if the
- // view is moved offscreen (among other things). Prevent hangs by always
- // acknowledging the frame after timeout of 1/6th of a second has passed.
- scoped_ptr<content::CompositingIOSurfaceLayerHelper> helper_;
- scoped_ptr<base::DelayTimer<content::CompositingIOSurfaceLayerHelper>> timer_;
-
- // Used to track when canDrawInCGLContext should return YES. This can be
- // in response to receiving a new compositor frame, or from any of the events
- // that cause setNeedsDisplay to be called on the layer.
- BOOL needs_display_;
-
- // This is set when a frame is received, and un-set when the frame is drawn.
- BOOL has_pending_frame_;
-
- // Incremented every time that this layer is asked to draw but does not have
- // new content to draw.
- uint64 did_not_draw_counter_;
-}
-
-- (content::CompositingIOSurfaceMac*)iosurface;
-- (content::CompositingIOSurfaceContext*)context;
-
-- (id)initWithIOSurface:(scoped_refptr<content::CompositingIOSurfaceMac>)
- iosurface
- withScaleFactor:(float)scale_factor
- withClient:(content::CompositingIOSurfaceLayerClient*)client;
-
-// Mark that the client is no longer valid and cannot be called back into.
-- (void)resetClient;
-
-// Called when a new frame is received.
-- (void)gotNewFrame;
-
-- (void)setNeedsDisplayAndDisplayAndAck;
-- (void)displayIfNeededAndAck;
-@end
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_LAYER_MAC_H_
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
deleted file mode 100644
index bda4c5fd9e4..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2013 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 "content/browser/renderer_host/compositing_iosurface_layer_mac.h"
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <OpenGL/gl.h>
-
-#include "base/mac/mac_util.h"
-#include "base/mac/sdk_forward_declarations.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_mac.h"
-#include "ui/base/cocoa/animation_utils.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gl/gpu_switching_manager.h"
-
-@interface CompositingIOSurfaceLayer(Private)
-- (void)ackPendingFrame:(bool)success;
-- (void)timerFired;
-@end
-
-namespace content {
-
-// The base::DelayTimer needs a C++ class to operate on, rather than Objective C
-// class. This helper class provides a bridge between the two.
-class CompositingIOSurfaceLayerHelper {
- public:
- CompositingIOSurfaceLayerHelper(CompositingIOSurfaceLayer* layer)
- : layer_(layer) {}
- void TimerFired() {
- [layer_ timerFired];
- }
- private:
- CompositingIOSurfaceLayer* layer_;
-};
-
-} // namespace content
-
-@implementation CompositingIOSurfaceLayer
-
-- (content::CompositingIOSurfaceMac*)iosurface {
- return iosurface_.get();
-}
-
-- (content::CompositingIOSurfaceContext*)context {
- return context_.get();
-}
-
-- (id)initWithIOSurface:(scoped_refptr<content::CompositingIOSurfaceMac>)
- iosurface
- withScaleFactor:(float)scale_factor
- withClient:(content::CompositingIOSurfaceLayerClient*)client {
- if (self = [super init]) {
- iosurface_ = iosurface;
- client_ = client;
- helper_.reset(new content::CompositingIOSurfaceLayerHelper(self));
- timer_.reset(new base::DelayTimer<content::CompositingIOSurfaceLayerHelper>(
- FROM_HERE,
- base::TimeDelta::FromSeconds(1) / 6,
- helper_.get(),
- &content::CompositingIOSurfaceLayerHelper::TimerFired));
-
- context_ = content::CompositingIOSurfaceContext::Get(
- content::CompositingIOSurfaceContext::kCALayerContextWindowNumber);
- DCHECK(context_);
- needs_display_ = NO;
- has_pending_frame_ = NO;
- did_not_draw_counter_ = 0;
-
- [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
- [self setAnchorPoint:CGPointMake(0, 0)];
- // Setting contents gravity is necessary to prevent the layer from being
- // scaled during dyanmic resizes (especially with devtools open).
- [self setContentsGravity:kCAGravityTopLeft];
- if ([self respondsToSelector:(@selector(setContentsScale:))]) {
- [self setContentsScale:scale_factor];
- }
- }
- return self;
-}
-
-- (void)resetClient {
- // Any acks that were waiting on this layer to draw will not occur, so ack
- // them now to prevent blocking the renderer.
- [self ackPendingFrame:true];
- client_ = NULL;
-}
-
-- (void)gotNewFrame {
- has_pending_frame_ = YES;
- timer_->Reset();
-
- // A trace value of 2 indicates that there is a pending swap ack. See
- // canDrawInCGLContext for other value meanings.
- TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, 2);
-
- if (context_ && context_->is_vsync_disabled()) {
- // If vsync is disabled, draw immediately and don't bother trying to use
- // the isAsynchronous property to ensure smooth animation.
- [self setNeedsDisplayAndDisplayAndAck];
- } else {
- needs_display_ = YES;
- if (![self isAsynchronous])
- [self setAsynchronous:YES];
- }
-}
-
-// Private methods:
-
-- (void)setNeedsDisplayAndDisplayAndAck {
- // Workaround for crbug.com/395827
- if ([self isAsynchronous])
- [self setAsynchronous:NO];
-
- [self setNeedsDisplay];
- [self displayIfNeededAndAck];
-}
-
-- (void)displayIfNeededAndAck {
- // Workaround for crbug.com/395827
- if ([self isAsynchronous])
- [self setAsynchronous:NO];
-
- [self displayIfNeeded];
-
- // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
- // rapidly (e.g, with vsync off). This is unacceptable because the failure
- // to ack a single frame will hang the renderer. Ensure that the renderer
- // not be blocked by lying and claiming that we drew the frame.
- [self ackPendingFrame:true];
-}
-
-- (void)ackPendingFrame:(bool)success {
- if (!has_pending_frame_)
- return;
-
- TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, 0);
- has_pending_frame_ = NO;
- if (client_)
- client_->AcceleratedLayerDidDrawFrame(success);
-}
-
-- (void)timerFired {
- if (has_pending_frame_)
- [self setNeedsDisplayAndDisplayAndAck];
-}
-
-// The remaining methods implement the CAOpenGLLayer interface.
-
-- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
- if (!context_)
- return [super copyCGLPixelFormatForDisplayMask:mask];
- return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context()));
-}
-
-- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
- if (!context_)
- return [super copyCGLContextForPixelFormat:pixelFormat];
- return CGLRetainContext(context_->cgl_context());
-}
-
-- (void)setNeedsDisplay {
- needs_display_ = YES;
- [super setNeedsDisplay];
-}
-
-- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
- pixelFormat:(CGLPixelFormatObj)pixelFormat
- forLayerTime:(CFTimeInterval)timeInterval
- displayTime:(const CVTimeStamp*)timeStamp {
- // Add an instantaneous blip to the PendingSwapAck state to indicate
- // that CoreAnimation asked if a frame is ready. A blip up to to 3 (usually
- // from 2, indicating that a swap ack is pending) indicates that we requested
- // a draw. A blip up to 1 (usually from 0, indicating there is no pending swap
- // ack) indicates that we did not request a draw. This would be more natural
- // to do with a tracing pseudo-thread
- // http://crbug.com/366300
- TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, needs_display_ ? 3 : 1);
- TRACE_COUNTER_ID1("browser", "PendingSwapAck", self,
- has_pending_frame_ ? 2 : 0);
-
- // If we return NO 30 times in a row, switch to being synchronous to avoid
- // burning CPU cycles on this callback.
- if (needs_display_) {
- did_not_draw_counter_ = 0;
- } else {
- did_not_draw_counter_ += 1;
- if (did_not_draw_counter_ > 30)
- [self setAsynchronous:NO];
- }
-
- return needs_display_;
-}
-
-- (void)drawInCGLContext:(CGLContextObj)glContext
- pixelFormat:(CGLPixelFormatObj)pixelFormat
- forLayerTime:(CFTimeInterval)timeInterval
- displayTime:(const CVTimeStamp*)timeStamp {
- TRACE_EVENT0("browser", "CompositingIOSurfaceLayer::drawInCGLContext");
-
- if (!iosurface_->HasIOSurface() || context_->cgl_context() != glContext) {
- glClearColor(1, 1, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT);
- return;
- }
-
- // The correct viewport to cover the layer will be set up by the caller.
- // Transform this into a window size for DrawIOSurface, where it will be
- // transformed back into this viewport.
- GLint viewport[4];
- glGetIntegerv(GL_VIEWPORT, viewport);
- gfx::Rect window_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
- float window_scale_factor = 1.f;
- if ([self respondsToSelector:(@selector(contentsScale))])
- window_scale_factor = [self contentsScale];
- window_rect = ToNearestRect(
- gfx::ScaleRect(window_rect, 1.f/window_scale_factor));
-
- bool draw_succeeded = iosurface_->DrawIOSurface(
- context_, window_rect, window_scale_factor);
-
- [self ackPendingFrame:draw_succeeded];
- needs_display_ = NO;
-
- [super drawInCGLContext:glContext
- pixelFormat:pixelFormat
- forLayerTime:timeInterval
- displayTime:timeStamp];
-}
-
-@end
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
deleted file mode 100644
index 08c3c74c286..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_mac.h
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
-
-#include <deque>
-#include <list>
-#include <vector>
-
-#import <Cocoa/Cocoa.h>
-#include <IOSurface/IOSurfaceAPI.h>
-#include <QuartzCore/QuartzCore.h>
-
-#include "base/callback.h"
-#include "base/lazy_instance.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "media/base/video_frame.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/size.h"
-
-class SkBitmap;
-
-namespace gfx {
-class Rect;
-}
-
-namespace content {
-
-class CompositingIOSurfaceContext;
-class CompositingIOSurfaceShaderPrograms;
-class CompositingIOSurfaceTransformer;
-class RenderWidgetHostViewFrameSubscriber;
-class RenderWidgetHostViewMac;
-
-// This class manages an OpenGL context and IOSurface for the accelerated
-// compositing code path. The GL context is attached to
-// RenderWidgetHostViewCocoa for blitting the IOSurface.
-class CompositingIOSurfaceMac
- : public base::RefCounted<CompositingIOSurfaceMac> {
- public:
- // Returns NULL if IOSurface or GL API calls fail.
- static scoped_refptr<CompositingIOSurfaceMac> Create();
-
- // Set IOSurface that will be drawn on the next NSView drawRect.
- bool SetIOSurfaceWithContextCurrent(
- scoped_refptr<CompositingIOSurfaceContext> current_context,
- IOSurfaceID io_surface_handle,
- const gfx::Size& size,
- float scale_factor) WARN_UNUSED_RESULT;
-
- // Get the CGL renderer ID currently associated with this context.
- int GetRendererID();
-
- // Blit the IOSurface to the rectangle specified by |window_rect| in DIPs,
- // with the origin in the lower left corner. If the window rect's size is
- // larger than the IOSurface, the remaining right and bottom edges will be
- // white. |window_scale_factor| is 1 in normal views, 2 in HiDPI views.
- bool DrawIOSurface(
- scoped_refptr<CompositingIOSurfaceContext> drawing_context,
- const gfx::Rect& window_rect,
- float window_scale_factor) WARN_UNUSED_RESULT;
-
- // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
- // into |out|. The copied region is specified with |src_pixel_subrect| and
- // the data is transformed so that it fits in |dst_pixel_size|.
- // |src_pixel_subrect| and |dst_pixel_size| are not in DIP but in pixel.
- // Caller must ensure that |out| is allocated to dimensions that match
- // dst_pixel_size, with no additional padding.
- // |callback| is invoked when the operation is completed or failed.
- // Do no call this method again before |callback| is invoked.
- void CopyTo(const gfx::Rect& src_pixel_subrect,
- const gfx::Size& dst_pixel_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback);
-
- // Transfer the contents of the surface to an already-allocated YV12
- // VideoFrame, and invoke a callback to indicate success or failure.
- void CopyToVideoFrame(
- const gfx::Rect& src_subrect,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback);
-
- // Unref the IOSurface and delete the associated GL texture. If the GPU
- // process is no longer referencing it, this will delete the IOSurface.
- void UnrefIOSurface();
-
- bool HasIOSurface() { return !!io_surface_.get(); }
-
- const gfx::Size& pixel_io_surface_size() const {
- return pixel_io_surface_size_;
- }
- // In cocoa view units / DIPs.
- const gfx::Size& dip_io_surface_size() const { return dip_io_surface_size_; }
- float scale_factor() const { return scale_factor_; }
-
- // Returns true if asynchronous readback is supported on this system.
- bool IsAsynchronousReadbackSupported();
-
- // Scan the list of started asynchronous copies and test if each one has
- // completed. If |block_until_finished| is true, then block until all
- // pending copies are finished.
- void CheckIfAllCopiesAreFinished(bool block_until_finished);
-
- // Returns true if the offscreen context used by this surface has been
- // poisoned.
- bool HasBeenPoisoned() const;
-
- private:
- friend class base::RefCounted<CompositingIOSurfaceMac>;
-
- // Vertex structure for use in glDraw calls.
- struct SurfaceVertex {
- SurfaceVertex() : x_(0.0f), y_(0.0f), tx_(0.0f), ty_(0.0f) { }
- void set(float x, float y, float tx, float ty) {
- x_ = x;
- y_ = y;
- tx_ = tx;
- ty_ = ty;
- }
- void set_position(float x, float y) {
- x_ = x;
- y_ = y;
- }
- void set_texcoord(float tx, float ty) {
- tx_ = tx;
- ty_ = ty;
- }
- float x_;
- float y_;
- float tx_;
- float ty_;
- };
-
- // Counter-clockwise verts starting from upper-left corner (0, 0).
- struct SurfaceQuad {
- void set_size(gfx::Size vertex_size, gfx::Size texcoord_size) {
- // Texture coordinates are flipped vertically so they can be drawn on
- // a projection with a flipped y-axis (origin is top left).
- float vw = static_cast<float>(vertex_size.width());
- float vh = static_cast<float>(vertex_size.height());
- float tw = static_cast<float>(texcoord_size.width());
- float th = static_cast<float>(texcoord_size.height());
- verts_[0].set(0.0f, 0.0f, 0.0f, th);
- verts_[1].set(0.0f, vh, 0.0f, 0.0f);
- verts_[2].set(vw, vh, tw, 0.0f);
- verts_[3].set(vw, 0.0f, tw, th);
- }
- void set_rect(float x1, float y1, float x2, float y2) {
- verts_[0].set_position(x1, y1);
- verts_[1].set_position(x1, y2);
- verts_[2].set_position(x2, y2);
- verts_[3].set_position(x2, y1);
- }
- void set_texcoord_rect(float tx1, float ty1, float tx2, float ty2) {
- // Texture coordinates are flipped vertically so they can be drawn on
- // a projection with a flipped y-axis (origin is top left).
- verts_[0].set_texcoord(tx1, ty2);
- verts_[1].set_texcoord(tx1, ty1);
- verts_[2].set_texcoord(tx2, ty1);
- verts_[3].set_texcoord(tx2, ty2);
- }
- SurfaceVertex verts_[4];
- };
-
- // Keeps track of states and buffers for readback of IOSurface.
- //
- // TODO(miu): Major code refactoring is badly needed! To be done in a
- // soon-upcoming change. For now, we blatantly violate the style guide with
- // respect to struct vs. class usage:
- struct CopyContext {
- explicit CopyContext(const scoped_refptr<CompositingIOSurfaceContext>& ctx);
- ~CopyContext();
-
- // Delete any references to owned OpenGL objects. This must be called
- // within the OpenGL context just before destruction.
- void ReleaseCachedGLObjects();
-
- // The following two methods assume |num_outputs| has been set, and are
- // being called within the OpenGL context.
- void PrepareReadbackFramebuffers();
- void PrepareForAsynchronousReadback();
-
- const scoped_ptr<CompositingIOSurfaceTransformer> transformer;
- GLenum output_readback_format;
- int num_outputs;
- GLuint output_textures[3]; // Not owned.
- // Note: For YUV, the |output_texture_sizes| widths are in terms of 4-byte
- // quads, not pixels.
- gfx::Size output_texture_sizes[3];
- GLuint frame_buffers[3];
- GLuint pixel_buffers[3];
- GLuint fence; // When non-zero, doing an asynchronous copy.
- int cycles_elapsed;
- base::Callback<bool(const void*, int)> map_buffer_callback;
- base::Callback<void(bool)> done_callback;
- };
-
- CompositingIOSurfaceMac(
- const scoped_refptr<CompositingIOSurfaceContext>& context);
- ~CompositingIOSurfaceMac();
-
- // If this IOSurface has moved to a different window, use that window's
- // GL context (if multiple visible windows are using the same GL context
- // then call to setView call can stall and prevent reaching 60fps).
- void SwitchToContextOnNewWindow(NSView* view,
- int window_number);
-
- // Returns true if IOSurface is ready to render. False otherwise.
- bool MapIOSurfaceToTextureWithContextCurrent(
- const scoped_refptr<CompositingIOSurfaceContext>& current_context,
- const gfx::Size pixel_size,
- float scale_factor,
- IOSurfaceID io_surface_handle) WARN_UNUSED_RESULT;
-
- void UnrefIOSurfaceWithContextCurrent();
-
- void DrawQuad(const SurfaceQuad& quad);
-
- // Copy current frame to |target| video frame. This method must be called
- // within a CGL context. Returns a callback that should be called outside
- // of the CGL context.
- // If |called_within_draw| is true this method is called within a drawing
- // operations. This allow certain optimizations.
- base::Closure CopyToVideoFrameWithinContext(
- const gfx::Rect& src_subrect,
- bool called_within_draw,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback);
-
- // Common GPU-readback copy path. Only one of |bitmap_output| or
- // |video_frame_output| may be specified: Either ARGB is written to
- // |bitmap_output| or letter-boxed YV12 is written to |video_frame_output|.
- base::Closure CopyToSelectedOutputWithinContext(
- const gfx::Rect& src_pixel_subrect,
- const gfx::Rect& dst_pixel_rect,
- bool called_within_draw,
- const SkBitmap* bitmap_output,
- const scoped_refptr<media::VideoFrame>& video_frame_output,
- const base::Callback<void(bool)>& done_callback);
-
- // TODO(hclam): These two methods should be static.
- void AsynchronousReadbackForCopy(
- const gfx::Rect& dst_pixel_rect,
- bool called_within_draw,
- CopyContext* copy_context,
- const SkBitmap* bitmap_output,
- const scoped_refptr<media::VideoFrame>& video_frame_output);
- bool SynchronousReadbackForCopy(
- const gfx::Rect& dst_pixel_rect,
- CopyContext* copy_context,
- const SkBitmap* bitmap_output,
- const scoped_refptr<media::VideoFrame>& video_frame_output);
-
- void CheckIfAllCopiesAreFinishedWithinContext(
- bool block_until_finished,
- std::vector<base::Closure>* done_callbacks);
-
- void FailAllCopies();
- void DestroyAllCopyContextsWithinContext();
-
- // Check for GL errors and store the result in error_. Only return new
- // errors
- GLenum GetAndSaveGLError();
-
- gfx::Rect IntersectWithIOSurface(const gfx::Rect& rect) const;
-
- // Offscreen context used for all operations other than drawing to the
- // screen. This is in the same share group as the contexts used for
- // drawing, and is the same for all IOSurfaces in all windows.
- scoped_refptr<CompositingIOSurfaceContext> offscreen_context_;
-
- // IOSurface data.
- IOSurfaceID io_surface_handle_;
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
-
- // The width and height of the io surface.
- gfx::Size pixel_io_surface_size_; // In pixels.
- gfx::Size dip_io_surface_size_; // In view / density independent pixels.
- float scale_factor_;
-
- // The "live" OpenGL texture referring to this IOSurfaceRef. Note
- // that per the CGLTexImageIOSurface2D API we do not need to
- // explicitly update this texture's contents once created. All we
- // need to do is ensure it is re-bound before attempting to draw
- // with it.
- GLuint texture_;
-
- // A pool of CopyContexts with OpenGL objects ready for re-use. Prefer to
- // pull one from the pool before creating a new CopyContext.
- std::vector<CopyContext*> copy_context_pool_;
-
- // CopyContexts being used for in-flight copy operations.
- std::deque<CopyContext*> copy_requests_;
-
- // Timer for finishing a copy operation.
- base::Timer finish_copy_timer_;
-
- // Error saved by GetAndSaveGLError
- GLint gl_error_;
-
- // Aggressive IOSurface eviction logic. When using CoreAnimation, IOSurfaces
- // are used only transiently to transfer from the GPU process to the browser
- // process. Once the IOSurface has been drawn to its CALayer, the CALayer
- // will not need updating again until its view is hidden and re-shown.
- // Aggressively evict surfaces when more than 8 (the number allowed by the
- // memory manager for fast tab switching) are allocated.
- enum {
- kMaximumUnevictedSurfaces = 8,
- };
- typedef std::list<CompositingIOSurfaceMac*> EvictionQueue;
- void EvictionMarkUpdated();
- void EvictionMarkEvicted();
- EvictionQueue::iterator eviction_queue_iterator_;
- bool eviction_has_been_drawn_since_updated_;
-
- static void EvictionScheduleDoEvict();
- static void EvictionDoEvict();
- static base::LazyInstance<EvictionQueue> eviction_queue_;
- static bool eviction_scheduled_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm b/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm
deleted file mode 100644
index 3fd28545d2f..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ /dev/null
@@ -1,970 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/compositing_iosurface_mac.h"
-
-#include <OpenGL/CGLIOSurface.h>
-#include <OpenGL/CGLRenderers.h>
-#include <OpenGL/OpenGL.h>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/platform_thread.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_transformer_mac.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_mac.h"
-#include "content/common/content_constants_internal.h"
-#include "gpu/config/gpu_driver_bug_workaround_type.h"
-#include "media/base/video_util.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-#include "ui/gfx/size_conversions.h"
-#include "ui/gl/gl_context.h"
-
-#ifdef NDEBUG
-#define CHECK_GL_ERROR()
-#define CHECK_AND_SAVE_GL_ERROR()
-#else
-#define CHECK_GL_ERROR() do { \
- GLenum gl_error = glGetError(); \
- LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
- } while (0)
-#define CHECK_AND_SAVE_GL_ERROR() do { \
- GLenum gl_error = GetAndSaveGLError(); \
- LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
- } while (0)
-#endif
-
-namespace content {
-namespace {
-
-// How many times to test if asynchronous copy has completed.
-// This value is chosen such that we allow at most 1 second to finish a copy.
-const int kFinishCopyRetryCycles = 100;
-
-// Time in milliseconds to allow asynchronous copy to finish.
-// This value is shorter than 16ms such that copy can complete within a vsync.
-const int kFinishCopyPollingPeriodMs = 10;
-
-bool HasAppleFenceExtension() {
- static bool initialized_has_fence = false;
- static bool has_fence = false;
-
- if (!initialized_has_fence) {
- has_fence =
- strstr(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)),
- "GL_APPLE_fence") != NULL;
- initialized_has_fence = true;
- }
- return has_fence;
-}
-
-bool HasPixelBufferObjectExtension() {
- static bool initialized_has_pbo = false;
- static bool has_pbo = false;
-
- if (!initialized_has_pbo) {
- has_pbo =
- strstr(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)),
- "GL_ARB_pixel_buffer_object") != NULL;
- initialized_has_pbo = true;
- }
- return has_pbo;
-}
-
-// Helper function to reverse the argument order. Also takes ownership of
-// |bitmap_output| for the life of the binding.
-void ReverseArgumentOrder(
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- scoped_ptr<SkBitmap> bitmap_output, bool success) {
- callback.Run(success, *bitmap_output);
-}
-
-// Called during an async GPU readback with a pointer to the pixel buffer. In
-// the snapshot path, we just memcpy the data into our output bitmap since the
-// width, height, and stride should all be equal.
-bool MapBufferToSkBitmap(const SkBitmap* output, const void* buf, int ignored) {
- TRACE_EVENT0("browser", "MapBufferToSkBitmap");
-
- if (buf) {
- SkAutoLockPixels output_lock(*output);
- memcpy(output->getPixels(), buf, output->getSize());
- }
- return buf != NULL;
-}
-
-// Copies tightly-packed scanlines from |buf| to |region_in_frame| in the given
-// |target| VideoFrame's |plane|. Assumption: |buf|'s width is
-// |region_in_frame.width()| and its stride is always in 4-byte alignment.
-//
-// TODO(miu): Refactor by moving this function into media/video_util.
-// http://crbug.com/219779
-bool MapBufferToVideoFrame(
- const scoped_refptr<media::VideoFrame>& target,
- const gfx::Rect& region_in_frame,
- const void* buf,
- int plane) {
- COMPILE_ASSERT(media::VideoFrame::kYPlane == 0, VideoFrame_kYPlane_mismatch);
- COMPILE_ASSERT(media::VideoFrame::kUPlane == 1, VideoFrame_kUPlane_mismatch);
- COMPILE_ASSERT(media::VideoFrame::kVPlane == 2, VideoFrame_kVPlane_mismatch);
-
- TRACE_EVENT1("browser", "MapBufferToVideoFrame", "plane", plane);
-
- // Apply black-out in the regions surrounding the view area (for
- // letterboxing/pillarboxing). Only do this once, since this is performed on
- // all planes in the VideoFrame here.
- if (plane == 0)
- media::LetterboxYUV(target.get(), region_in_frame);
-
- if (buf) {
- int packed_width = region_in_frame.width();
- int packed_height = region_in_frame.height();
- // For planes 1 and 2, the width and height are 1/2 size (rounded up).
- if (plane > 0) {
- packed_width = (packed_width + 1) / 2;
- packed_height = (packed_height + 1) / 2;
- }
- const uint8* src = reinterpret_cast<const uint8*>(buf);
- const int src_stride = (packed_width % 4 == 0 ?
- packed_width :
- (packed_width + 4 - (packed_width % 4)));
- const uint8* const src_end = src + packed_height * src_stride;
-
- // Calculate starting offset and stride into the destination buffer.
- const int dst_stride = target->stride(plane);
- uint8* dst = target->data(plane);
- if (plane == 0)
- dst += (region_in_frame.y() * dst_stride) + region_in_frame.x();
- else
- dst += (region_in_frame.y() / 2 * dst_stride) + (region_in_frame.x() / 2);
-
- // Copy each row, accounting for strides in the source and destination.
- for (; src < src_end; src += src_stride, dst += dst_stride)
- memcpy(dst, src, packed_width);
- }
- return buf != NULL;
-}
-
-} // namespace
-
-CompositingIOSurfaceMac::CopyContext::CopyContext(
- const scoped_refptr<CompositingIOSurfaceContext>& context)
- : transformer(new CompositingIOSurfaceTransformer(
- GL_TEXTURE_RECTANGLE_ARB, true, context->shader_program_cache())),
- output_readback_format(GL_BGRA),
- num_outputs(0),
- fence(0),
- cycles_elapsed(0) {
- memset(output_textures, 0, sizeof(output_textures));
- memset(frame_buffers, 0, sizeof(frame_buffers));
- memset(pixel_buffers, 0, sizeof(pixel_buffers));
-}
-
-CompositingIOSurfaceMac::CopyContext::~CopyContext() {
- DCHECK_EQ(frame_buffers[0], 0u) << "Failed to call ReleaseCachedGLObjects().";
-}
-
-void CompositingIOSurfaceMac::CopyContext::ReleaseCachedGLObjects() {
- // No outstanding callbacks should be pending.
- DCHECK(map_buffer_callback.is_null());
- DCHECK(done_callback.is_null());
-
- // For an asynchronous read-back, there are more objects to delete:
- if (fence) {
- glDeleteBuffers(arraysize(pixel_buffers), pixel_buffers); CHECK_GL_ERROR();
- memset(pixel_buffers, 0, sizeof(pixel_buffers));
- glDeleteFencesAPPLE(1, &fence); CHECK_GL_ERROR();
- fence = 0;
- }
-
- glDeleteFramebuffersEXT(arraysize(frame_buffers), frame_buffers);
- CHECK_GL_ERROR();
- memset(frame_buffers, 0, sizeof(frame_buffers));
-
- // Note: |output_textures| are owned by the transformer.
- if (transformer)
- transformer->ReleaseCachedGLObjects();
-}
-
-void CompositingIOSurfaceMac::CopyContext::PrepareReadbackFramebuffers() {
- for (int i = 0; i < num_outputs; ++i) {
- if (!frame_buffers[i]) {
- glGenFramebuffersEXT(1, &frame_buffers[i]); CHECK_GL_ERROR();
- }
- }
-}
-
-void CompositingIOSurfaceMac::CopyContext::PrepareForAsynchronousReadback() {
- PrepareReadbackFramebuffers();
- if (!fence) {
- glGenFencesAPPLE(1, &fence); CHECK_GL_ERROR();
- }
- for (int i = 0; i < num_outputs; ++i) {
- if (!pixel_buffers[i]) {
- glGenBuffersARB(1, &pixel_buffers[i]); CHECK_GL_ERROR();
- }
- }
-}
-
-
-// static
-scoped_refptr<CompositingIOSurfaceMac> CompositingIOSurfaceMac::Create() {
- scoped_refptr<CompositingIOSurfaceContext> offscreen_context =
- CompositingIOSurfaceContext::Get(
- CompositingIOSurfaceContext::kOffscreenContextWindowNumber);
- if (!offscreen_context) {
- LOG(ERROR) << "Failed to create context for offscreen operations";
- return NULL;
- }
-
- return new CompositingIOSurfaceMac(offscreen_context);
-}
-
-CompositingIOSurfaceMac::CompositingIOSurfaceMac(
- const scoped_refptr<CompositingIOSurfaceContext>& offscreen_context)
- : offscreen_context_(offscreen_context),
- io_surface_handle_(0),
- scale_factor_(1.f),
- texture_(0),
- finish_copy_timer_(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kFinishCopyPollingPeriodMs),
- base::Bind(&CompositingIOSurfaceMac::CheckIfAllCopiesAreFinished,
- base::Unretained(this),
- false),
- true),
- gl_error_(GL_NO_ERROR),
- eviction_queue_iterator_(eviction_queue_.Get().end()),
- eviction_has_been_drawn_since_updated_(false) {
- CHECK(offscreen_context_);
-}
-
-CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
- FailAllCopies();
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- offscreen_context_->cgl_context());
- DestroyAllCopyContextsWithinContext();
- UnrefIOSurfaceWithContextCurrent();
- }
- offscreen_context_ = NULL;
- DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
-}
-
-bool CompositingIOSurfaceMac::SetIOSurfaceWithContextCurrent(
- scoped_refptr<CompositingIOSurfaceContext> current_context,
- IOSurfaceID io_surface_handle,
- const gfx::Size& size,
- float scale_factor) {
- bool result = MapIOSurfaceToTextureWithContextCurrent(
- current_context, size, scale_factor, io_surface_handle);
- EvictionMarkUpdated();
- return result;
-}
-
-int CompositingIOSurfaceMac::GetRendererID() {
- GLint current_renderer_id = -1;
- if (CGLGetParameter(offscreen_context_->cgl_context(),
- kCGLCPCurrentRendererID,
- &current_renderer_id) == kCGLNoError)
- return current_renderer_id & kCGLRendererIDMatchingMask;
- return -1;
-}
-
-bool CompositingIOSurfaceMac::DrawIOSurface(
- scoped_refptr<CompositingIOSurfaceContext> drawing_context,
- const gfx::Rect& window_rect,
- float window_scale_factor) {
- DCHECK_EQ(CGLGetCurrentContext(), drawing_context->cgl_context());
-
- bool has_io_surface = HasIOSurface();
- TRACE_EVENT1("browser", "CompositingIOSurfaceMac::DrawIOSurface",
- "has_io_surface", has_io_surface);
-
- gfx::Rect pixel_window_rect =
- ToNearestRect(gfx::ScaleRect(window_rect, window_scale_factor));
- glViewport(
- pixel_window_rect.x(), pixel_window_rect.y(),
- pixel_window_rect.width(), pixel_window_rect.height());
-
- SurfaceQuad quad;
- quad.set_size(dip_io_surface_size_, pixel_io_surface_size_);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- // Note that the projection keeps things in view units, so the use of
- // window_rect / dip_io_surface_size_ (as opposed to the pixel_ variants)
- // below is correct.
- glOrtho(0, window_rect.width(), window_rect.height(), 0, -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
-
- if (has_io_surface) {
- drawing_context->shader_program_cache()->UseBlitProgram();
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
-
- DrawQuad(quad);
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_AND_SAVE_GL_ERROR();
-
- // Fill the resize gutters with white.
- if (window_rect.width() > dip_io_surface_size_.width() ||
- window_rect.height() > dip_io_surface_size_.height()) {
- drawing_context->shader_program_cache()->UseSolidWhiteProgram();
- SurfaceQuad filler_quad;
- if (window_rect.width() > dip_io_surface_size_.width()) {
- // Draw right-side gutter down to the bottom of the window.
- filler_quad.set_rect(dip_io_surface_size_.width(), 0.0f,
- window_rect.width(), window_rect.height());
- DrawQuad(filler_quad);
- }
- if (window_rect.height() > dip_io_surface_size_.height()) {
- // Draw bottom gutter to the width of the IOSurface.
- filler_quad.set_rect(
- 0.0f, dip_io_surface_size_.height(),
- dip_io_surface_size_.width(), window_rect.height());
- DrawQuad(filler_quad);
- }
- }
-
- // Workaround for issue 158469. Issue a dummy draw call with texture_ not
- // bound to blit_rgb_sampler_location_, in order to shake all references
- // to the IOSurface out of the driver.
- glBegin(GL_TRIANGLES);
- glEnd();
-
- glUseProgram(0); CHECK_AND_SAVE_GL_ERROR();
- } else {
- // Should match the clear color of RenderWidgetHostViewMac.
- glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- }
-
- bool workaround_needed =
- GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
- gpu::FORCE_GL_FINISH_AFTER_COMPOSITING);
- if (workaround_needed) {
- TRACE_EVENT0("gpu", "glFinish");
- glFinish();
- }
-
- // Check if any of the drawing calls result in an error.
- GetAndSaveGLError();
- bool result = true;
- if (gl_error_ != GL_NO_ERROR) {
- LOG(ERROR) << "GL error in DrawIOSurface: " << gl_error_;
- result = false;
- // If there was an error, clear the screen to a light grey to avoid
- // rendering artifacts. If we're in a really bad way, this too may
- // generate an error. Clear the GL error afterwards just in case.
- glClearColor(0.8, 0.8, 0.8, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
- glGetError();
- }
-
- eviction_has_been_drawn_since_updated_ = true;
- return result;
-}
-
-void CompositingIOSurfaceMac::CopyTo(
- const gfx::Rect& src_pixel_subrect,
- const gfx::Size& dst_pixel_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback) {
- scoped_ptr<SkBitmap> output(new SkBitmap());
- output->setConfig(SkBitmap::kARGB_8888_Config,
- dst_pixel_size.width(),
- dst_pixel_size.height(),
- 0,
- kOpaque_SkAlphaType);
-
- if (!output->allocPixels()) {
- DLOG(ERROR) << "Failed to allocate SkBitmap pixels!";
- callback.Run(false, *output);
- return;
- }
- DCHECK_EQ(output->rowBytesAsPixels(), dst_pixel_size.width())
- << "Stride is required to be equal to width for GPU readback.";
-
- base::Closure copy_done_callback;
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- offscreen_context_->cgl_context());
- copy_done_callback = CopyToSelectedOutputWithinContext(
- src_pixel_subrect, gfx::Rect(dst_pixel_size), false,
- output.get(), NULL,
- base::Bind(&ReverseArgumentOrder, callback, base::Passed(&output)));
- }
- if (!copy_done_callback.is_null())
- copy_done_callback.Run();
-}
-
-void CompositingIOSurfaceMac::CopyToVideoFrame(
- const gfx::Rect& src_pixel_subrect,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) {
- base::Closure copy_done_callback;
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- offscreen_context_->cgl_context());
- copy_done_callback = CopyToVideoFrameWithinContext(
- src_pixel_subrect, false, target, callback);
- }
- if (!copy_done_callback.is_null())
- copy_done_callback.Run();
-}
-
-base::Closure CompositingIOSurfaceMac::CopyToVideoFrameWithinContext(
- const gfx::Rect& src_pixel_subrect,
- bool called_within_draw,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) {
- gfx::Rect region_in_frame = media::ComputeLetterboxRegion(
- gfx::Rect(target->coded_size()), src_pixel_subrect.size());
- // Make coordinates and sizes even because we letterbox in YUV space right
- // now (see CopyRGBToVideoFrame). They need to be even for the UV samples to
- // line up correctly.
- region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
- region_in_frame.y() & ~1,
- region_in_frame.width() & ~1,
- region_in_frame.height() & ~1);
- DCHECK_LE(region_in_frame.right(), target->coded_size().width());
- DCHECK_LE(region_in_frame.bottom(), target->coded_size().height());
-
- return CopyToSelectedOutputWithinContext(
- src_pixel_subrect, region_in_frame, called_within_draw,
- NULL, target, callback);
-}
-
-bool CompositingIOSurfaceMac::MapIOSurfaceToTextureWithContextCurrent(
- const scoped_refptr<CompositingIOSurfaceContext>& current_context,
- const gfx::Size pixel_size,
- float scale_factor,
- IOSurfaceID io_surface_handle) {
- TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture");
-
- if (!io_surface_ || io_surface_handle != io_surface_handle_)
- UnrefIOSurfaceWithContextCurrent();
-
- pixel_io_surface_size_ = pixel_size;
- scale_factor_ = scale_factor;
- dip_io_surface_size_ = gfx::ToFlooredSize(
- gfx::ScaleSize(pixel_io_surface_size_, 1.0 / scale_factor_));
-
- // Early-out if the IOSurface has not changed. Note that because IOSurface
- // sizes are rounded, the same IOSurface may have two different sizes
- // associated with it.
- if (io_surface_ && io_surface_handle == io_surface_handle_)
- return true;
-
- io_surface_.reset(IOSurfaceLookup(io_surface_handle));
- // Can fail if IOSurface with that ID was already released by the gpu
- // process.
- if (!io_surface_) {
- UnrefIOSurfaceWithContextCurrent();
- return false;
- }
-
- io_surface_handle_ = io_surface_handle;
-
- // Actual IOSurface size is rounded up to reduce reallocations during window
- // resize. Get the actual size to properly map the texture.
- gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_),
- IOSurfaceGetHeight(io_surface_));
-
- glGenTextures(1, &texture_);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
- glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- CHECK_AND_SAVE_GL_ERROR();
- GLuint plane = 0;
- CGLError cgl_error = CGLTexImageIOSurface2D(
- current_context->cgl_context(),
- GL_TEXTURE_RECTANGLE_ARB,
- GL_RGBA,
- rounded_size.width(),
- rounded_size.height(),
- GL_BGRA,
- GL_UNSIGNED_INT_8_8_8_8_REV,
- io_surface_.get(),
- plane);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- if (cgl_error != kCGLNoError) {
- LOG(ERROR) << "CGLTexImageIOSurface2D: " << cgl_error;
- UnrefIOSurfaceWithContextCurrent();
- return false;
- }
- GetAndSaveGLError();
- if (gl_error_ != GL_NO_ERROR) {
- LOG(ERROR) << "GL error in MapIOSurfaceToTexture: " << gl_error_;
- UnrefIOSurfaceWithContextCurrent();
- return false;
- }
- return true;
-}
-
-void CompositingIOSurfaceMac::UnrefIOSurface() {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- offscreen_context_->cgl_context());
- UnrefIOSurfaceWithContextCurrent();
-}
-
-void CompositingIOSurfaceMac::DrawQuad(const SurfaceQuad& quad) {
- TRACE_EVENT0("gpu", "CompositingIOSurfaceMac::DrawQuad");
-
- glEnableClientState(GL_VERTEX_ARRAY); CHECK_AND_SAVE_GL_ERROR();
- glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_AND_SAVE_GL_ERROR();
-
- glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].x_);
- glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].tx_);
- glDrawArrays(GL_QUADS, 0, 4); CHECK_AND_SAVE_GL_ERROR();
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
-
-void CompositingIOSurfaceMac::UnrefIOSurfaceWithContextCurrent() {
- if (texture_) {
- glDeleteTextures(1, &texture_);
- texture_ = 0;
- }
- pixel_io_surface_size_ = gfx::Size();
- scale_factor_ = 1;
- dip_io_surface_size_ = gfx::Size();
- io_surface_.reset();
-
- // Forget the ID, because even if it is still around when we want to use it
- // again, OSX may have reused the same ID for a new tab and we don't want to
- // blit random tab contents.
- io_surface_handle_ = 0;
-
- EvictionMarkEvicted();
-}
-
-bool CompositingIOSurfaceMac::IsAsynchronousReadbackSupported() {
- if (!HasAppleFenceExtension() && HasPixelBufferObjectExtension())
- return false;
- if (GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
- gpu::DISABLE_ASYNC_READPIXELS)) {
- return false;
- }
- return true;
-}
-
-bool CompositingIOSurfaceMac::HasBeenPoisoned() const {
- return offscreen_context_->HasBeenPoisoned();
-}
-
-base::Closure CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext(
- const gfx::Rect& src_pixel_subrect,
- const gfx::Rect& dst_pixel_rect,
- bool called_within_draw,
- const SkBitmap* bitmap_output,
- const scoped_refptr<media::VideoFrame>& video_frame_output,
- const base::Callback<void(bool)>& done_callback) {
- DCHECK_NE(bitmap_output != NULL, video_frame_output.get() != NULL);
- DCHECK(!done_callback.is_null());
-
- // SWIZZLE_RGBA_FOR_ASYNC_READPIXELS workaround: Fall-back to synchronous
- // readback for SkBitmap output since the Blit shader program doesn't support
- // switchable output formats.
- const bool require_sync_copy_for_workaround = bitmap_output &&
- offscreen_context_->shader_program_cache()->rgb_to_yv12_output_format() ==
- GL_RGBA;
- const bool async_copy = !require_sync_copy_for_workaround &&
- IsAsynchronousReadbackSupported();
- TRACE_EVENT2(
- "browser", "CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext",
- "output", bitmap_output ? "SkBitmap (ARGB)" : "VideoFrame (YV12)",
- "async_readback", async_copy);
-
- const gfx::Rect src_rect = IntersectWithIOSurface(src_pixel_subrect);
- if (src_rect.IsEmpty() || dst_pixel_rect.IsEmpty())
- return base::Bind(done_callback, false);
-
- CopyContext* copy_context;
- if (copy_context_pool_.empty()) {
- // Limit the maximum number of simultaneous copies to two. Rationale:
- // Really, only one should ever be in-progress at a time, as we should
- // depend on the speed of the hardware to rate-limit the copying naturally.
- // In the asynchronous read-back case, the one currently in-flight copy is
- // highly likely to have finished by this point (i.e., it's just waiting for
- // us to make a glMapBuffer() call). Therefore, we allow a second copy to
- // be started here.
- if (copy_requests_.size() >= 2)
- return base::Bind(done_callback, false);
- copy_context = new CopyContext(offscreen_context_);
- } else {
- copy_context = copy_context_pool_.back();
- copy_context_pool_.pop_back();
- }
-
- if (!HasIOSurface())
- return base::Bind(done_callback, false);
-
- // Send transform commands to the GPU.
- copy_context->num_outputs = 0;
- if (bitmap_output) {
- if (copy_context->transformer->ResizeBilinear(
- texture_, src_rect, dst_pixel_rect.size(),
- &copy_context->output_textures[0])) {
- copy_context->output_readback_format = GL_BGRA;
- copy_context->num_outputs = 1;
- copy_context->output_texture_sizes[0] = dst_pixel_rect.size();
- }
- } else {
- if (copy_context->transformer->TransformRGBToYV12(
- texture_, src_rect, dst_pixel_rect.size(),
- &copy_context->output_textures[0],
- &copy_context->output_textures[1],
- &copy_context->output_textures[2],
- &copy_context->output_texture_sizes[0],
- &copy_context->output_texture_sizes[1])) {
- copy_context->output_readback_format =
- offscreen_context_->shader_program_cache()->
- rgb_to_yv12_output_format();
- copy_context->num_outputs = 3;
- copy_context->output_texture_sizes[2] =
- copy_context->output_texture_sizes[1];
- }
- }
- if (!copy_context->num_outputs)
- return base::Bind(done_callback, false);
-
- // In the asynchronous case, issue commands to the GPU and return a null
- // closure here. In the synchronous case, perform a blocking readback and
- // return a callback to be run outside the CGL context to indicate success.
- if (async_copy) {
- copy_context->done_callback = done_callback;
- AsynchronousReadbackForCopy(
- dst_pixel_rect, called_within_draw, copy_context, bitmap_output,
- video_frame_output);
- copy_requests_.push_back(copy_context);
- if (!finish_copy_timer_.IsRunning())
- finish_copy_timer_.Reset();
- return base::Closure();
- } else {
- const bool success = SynchronousReadbackForCopy(
- dst_pixel_rect, copy_context, bitmap_output, video_frame_output);
- return base::Bind(done_callback, success);
- }
-}
-
-void CompositingIOSurfaceMac::AsynchronousReadbackForCopy(
- const gfx::Rect& dst_pixel_rect,
- bool called_within_draw,
- CopyContext* copy_context,
- const SkBitmap* bitmap_output,
- const scoped_refptr<media::VideoFrame>& video_frame_output) {
- copy_context->PrepareForAsynchronousReadback();
-
- // Copy the textures to their corresponding PBO.
- for (int i = 0; i < copy_context->num_outputs; ++i) {
- TRACE_EVENT1(
- "browser", "CompositingIOSurfaceMac::AsynchronousReadbackForCopy",
- "plane", i);
-
- // Attach the output texture to the FBO.
- glBindFramebufferEXT(
- GL_READ_FRAMEBUFFER_EXT, copy_context->frame_buffers[i]);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_RECTANGLE_ARB, copy_context->output_textures[i], 0);
- DCHECK(glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT) ==
- GL_FRAMEBUFFER_COMPLETE_EXT);
-
- // Create a PBO and issue an asynchronous read-back.
- glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context->pixel_buffers[i]);
- CHECK_AND_SAVE_GL_ERROR();
- glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
- copy_context->output_texture_sizes[i].GetArea() * 4,
- NULL, GL_STREAM_READ_ARB);
- CHECK_AND_SAVE_GL_ERROR();
- glReadPixels(0, 0,
- copy_context->output_texture_sizes[i].width(),
- copy_context->output_texture_sizes[i].height(),
- copy_context->output_readback_format,
- GL_UNSIGNED_INT_8_8_8_8_REV, 0);
- CHECK_AND_SAVE_GL_ERROR();
- }
-
- glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_AND_SAVE_GL_ERROR();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_AND_SAVE_GL_ERROR();
-
- glSetFenceAPPLE(copy_context->fence); CHECK_GL_ERROR();
- copy_context->cycles_elapsed = 0;
-
- // When this asynchronous copy happens in a draw operaton there is no need
- // to explicitly flush because there will be a swap buffer and this flush
- // hurts performance.
- if (!called_within_draw) {
- glFlush(); CHECK_AND_SAVE_GL_ERROR();
- }
-
- copy_context->map_buffer_callback = bitmap_output ?
- base::Bind(&MapBufferToSkBitmap, bitmap_output) :
- base::Bind(&MapBufferToVideoFrame, video_frame_output, dst_pixel_rect);
-}
-
-void CompositingIOSurfaceMac::CheckIfAllCopiesAreFinished(
- bool block_until_finished) {
- if (copy_requests_.empty())
- return;
-
- std::vector<base::Closure> done_callbacks;
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- offscreen_context_->cgl_context());
- CheckIfAllCopiesAreFinishedWithinContext(
- block_until_finished, &done_callbacks);
- }
- for (size_t i = 0; i < done_callbacks.size(); ++i)
- done_callbacks[i].Run();
-}
-
-void CompositingIOSurfaceMac::CheckIfAllCopiesAreFinishedWithinContext(
- bool block_until_finished,
- std::vector<base::Closure>* done_callbacks) {
- while (!copy_requests_.empty()) {
- CopyContext* const copy_context = copy_requests_.front();
-
- if (copy_context->fence && !glTestFenceAPPLE(copy_context->fence)) {
- CHECK_AND_SAVE_GL_ERROR();
- // Doing a glFinishFenceAPPLE can cause transparent window flashes when
- // switching tabs, so only do it when required.
- if (block_until_finished) {
- glFinishFenceAPPLE(copy_context->fence);
- CHECK_AND_SAVE_GL_ERROR();
- } else if (copy_context->cycles_elapsed < kFinishCopyRetryCycles) {
- ++copy_context->cycles_elapsed;
- // This copy has not completed there is no need to test subsequent
- // requests.
- break;
- }
- }
- CHECK_AND_SAVE_GL_ERROR();
-
- bool success = true;
- for (int i = 0; success && i < copy_context->num_outputs; ++i) {
- TRACE_EVENT1(
- "browser",
- "CompositingIOSurfaceMac::CheckIfAllCopiesAreFinishedWithinContext",
- "plane", i);
-
- glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context->pixel_buffers[i]);
- CHECK_AND_SAVE_GL_ERROR();
-
- void* buf = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
- CHECK_AND_SAVE_GL_ERROR();
- success &= copy_context->map_buffer_callback.Run(buf, i);
- glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_AND_SAVE_GL_ERROR();
- }
- copy_context->map_buffer_callback.Reset();
- glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_AND_SAVE_GL_ERROR();
-
- copy_requests_.pop_front();
- done_callbacks->push_back(base::Bind(copy_context->done_callback, success));
- copy_context->done_callback.Reset();
- copy_context_pool_.push_back(copy_context);
- }
- if (copy_requests_.empty())
- finish_copy_timer_.Stop();
-
- CHECK(copy_requests_.empty() || !block_until_finished);
-}
-
-bool CompositingIOSurfaceMac::SynchronousReadbackForCopy(
- const gfx::Rect& dst_pixel_rect,
- CopyContext* copy_context,
- const SkBitmap* bitmap_output,
- const scoped_refptr<media::VideoFrame>& video_frame_output) {
- bool success = true;
- copy_context->PrepareReadbackFramebuffers();
- for (int i = 0; i < copy_context->num_outputs; ++i) {
- TRACE_EVENT1(
- "browser", "CompositingIOSurfaceMac::SynchronousReadbackForCopy",
- "plane", i);
-
- // Attach the output texture to the FBO.
- glBindFramebufferEXT(
- GL_READ_FRAMEBUFFER_EXT, copy_context->frame_buffers[i]);
- glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_RECTANGLE_ARB, copy_context->output_textures[i], 0);
- DCHECK(glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT) ==
- GL_FRAMEBUFFER_COMPLETE_EXT);
-
- // Blocking read-back of pixels from textures.
- void* buf;
- // When data must be transferred into a VideoFrame one scanline at a time,
- // it is necessary to allocate a separate buffer for glReadPixels() that can
- // be populated one-shot.
- //
- // TODO(miu): Don't keep allocating/deleting this buffer for every frame.
- // Keep it cached, allocated on first use.
- scoped_ptr<uint32[]> temp_readback_buffer;
- if (bitmap_output) {
- // The entire SkBitmap is populated, never a region within. So, read the
- // texture directly into the bitmap's pixel memory.
- buf = bitmap_output->getPixels();
- } else {
- // Optimization: If the VideoFrame is letterboxed (not pillarboxed), and
- // its stride is equal to the stride of the data being read back, then
- // readback directly into the VideoFrame's buffer to save a round of
- // memcpy'ing.
- //
- // TODO(miu): Move these calculations into VideoFrame (need a CalcOffset()
- // method). http://crbug.com/219779
- const int src_stride = copy_context->output_texture_sizes[i].width() * 4;
- const int dst_stride = video_frame_output->stride(i);
- if (src_stride == dst_stride && dst_pixel_rect.x() == 0) {
- const int y_offset = dst_pixel_rect.y() / (i == 0 ? 1 : 2);
- buf = video_frame_output->data(i) + y_offset * dst_stride;
- } else {
- // Create and readback into a temporary buffer because the data must be
- // transferred to VideoFrame's pixel memory one scanline at a time.
- temp_readback_buffer.reset(
- new uint32[copy_context->output_texture_sizes[i].GetArea()]);
- buf = temp_readback_buffer.get();
- }
- }
- glReadPixels(0, 0,
- copy_context->output_texture_sizes[i].width(),
- copy_context->output_texture_sizes[i].height(),
- copy_context->output_readback_format,
- GL_UNSIGNED_INT_8_8_8_8_REV, buf);
- CHECK_AND_SAVE_GL_ERROR();
- if (video_frame_output.get()) {
- if (!temp_readback_buffer) {
- // Apply letterbox black-out around view region.
- media::LetterboxYUV(video_frame_output.get(), dst_pixel_rect);
- } else {
- // Copy from temporary buffer and fully render the VideoFrame.
- success &= MapBufferToVideoFrame(video_frame_output, dst_pixel_rect,
- temp_readback_buffer.get(), i);
- }
- }
- }
-
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); CHECK_AND_SAVE_GL_ERROR();
- copy_context_pool_.push_back(copy_context);
- return success;
-}
-
-void CompositingIOSurfaceMac::FailAllCopies() {
- for (size_t i = 0; i < copy_requests_.size(); ++i) {
- copy_requests_[i]->map_buffer_callback.Reset();
-
- base::Callback<void(bool)>& done_callback =
- copy_requests_[i]->done_callback;
- if (!done_callback.is_null()) {
- done_callback.Run(false);
- done_callback.Reset();
- }
- }
-}
-
-void CompositingIOSurfaceMac::DestroyAllCopyContextsWithinContext() {
- // Move all in-flight copies, if any, back into the pool. Then, destroy all
- // the CopyContexts in the pool.
- copy_context_pool_.insert(copy_context_pool_.end(),
- copy_requests_.begin(), copy_requests_.end());
- copy_requests_.clear();
- while (!copy_context_pool_.empty()) {
- scoped_ptr<CopyContext> copy_context(copy_context_pool_.back());
- copy_context_pool_.pop_back();
- copy_context->ReleaseCachedGLObjects();
- }
-}
-
-gfx::Rect CompositingIOSurfaceMac::IntersectWithIOSurface(
- const gfx::Rect& rect) const {
- return gfx::IntersectRects(rect,
- gfx::ToEnclosingRect(gfx::Rect(pixel_io_surface_size_)));
-}
-
-GLenum CompositingIOSurfaceMac::GetAndSaveGLError() {
- GLenum gl_error = glGetError();
- if (gl_error_ == GL_NO_ERROR)
- gl_error_ = gl_error;
- return gl_error;
-}
-
-void CompositingIOSurfaceMac::EvictionMarkUpdated() {
- EvictionMarkEvicted();
- eviction_queue_.Get().push_back(this);
- eviction_queue_iterator_ = --eviction_queue_.Get().end();
- eviction_has_been_drawn_since_updated_ = false;
- EvictionScheduleDoEvict();
-}
-
-void CompositingIOSurfaceMac::EvictionMarkEvicted() {
- if (eviction_queue_iterator_ == eviction_queue_.Get().end())
- return;
- eviction_queue_.Get().erase(eviction_queue_iterator_);
- eviction_queue_iterator_ = eviction_queue_.Get().end();
- eviction_has_been_drawn_since_updated_ = false;
-}
-
-// static
-void CompositingIOSurfaceMac::EvictionScheduleDoEvict() {
- if (eviction_scheduled_)
- return;
- if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
- return;
-
- eviction_scheduled_ = true;
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&CompositingIOSurfaceMac::EvictionDoEvict));
-}
-
-// static
-void CompositingIOSurfaceMac::EvictionDoEvict() {
- eviction_scheduled_ = false;
- // Walk the list of allocated surfaces from least recently used to most
- // recently used.
- for (EvictionQueue::iterator it = eviction_queue_.Get().begin();
- it != eviction_queue_.Get().end();) {
- CompositingIOSurfaceMac* surface = *it;
- ++it;
-
- // If the number of IOSurfaces allocated is less than the threshold,
- // stop walking the list of surfaces.
- if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
- break;
-
- // Don't evict anything that has not yet been drawn.
- if (!surface->eviction_has_been_drawn_since_updated_)
- continue;
-
- // Don't evict anything with pending copy requests.
- if (!surface->copy_requests_.empty())
- continue;
-
- // Evict the surface.
- surface->UnrefIOSurface();
- }
-}
-
-// static
-base::LazyInstance<CompositingIOSurfaceMac::EvictionQueue>
- CompositingIOSurfaceMac::eviction_queue_;
-
-// static
-bool CompositingIOSurfaceMac::eviction_scheduled_ = false;
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc b/chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
deleted file mode 100644
index 753c180dbf5..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.cc
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
-
-#include <string>
-#include <OpenGL/gl.h>
-
-#include "base/basictypes.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "gpu/config/gpu_driver_bug_workaround_type.h"
-
-namespace content {
-
-namespace {
-
-// Convenience macro allowing GLSL programs to be specified inline, and to be
-// automatically converted into string form by the C preprocessor.
-#define GLSL_PROGRAM_AS_STRING(shader_code) #shader_code
-
-// As required by the spec, add the version directive to the beginning of each
-// program to activate the expected syntax and built-in features. GLSL version
-// 1.2 is the latest version supported by MacOS 10.6.
-const char kVersionDirective[] = "#version 120\n";
-
-// Allow switchable output swizzling from RGBToYV12 fragment shaders (needed for
-// workaround; see comments in CompositingIOSurfaceShaderPrograms ctor).
-const char kOutputSwizzleMacroNormal[] = "#define OUTPUT_PIXEL_ORDERING bgra\n";
-const char kOutputSwizzleMacroSwapRB[] = "#define OUTPUT_PIXEL_ORDERING rgba\n";
-
-// Only the bare-bones calculations here for speed.
-const char kvsBlit[] = GLSL_PROGRAM_AS_STRING(
- varying vec2 texture_coord;
- void main() {
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
- texture_coord = gl_MultiTexCoord0.xy;
- }
-);
-
-// Just samples the texture.
-const char kfsBlit[] = GLSL_PROGRAM_AS_STRING(
- uniform sampler2DRect texture_;
- varying vec2 texture_coord;
- void main() {
- gl_FragColor = vec4(texture2DRect(texture_, texture_coord).rgb, 1.0);
- }
-);
-
-
-// Only calculates position.
-const char kvsSolidWhite[] = GLSL_PROGRAM_AS_STRING(
- void main() {
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
- }
-);
-
-// Always white.
-const char kfsSolidWhite[] = GLSL_PROGRAM_AS_STRING(
- void main() {
- gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
- }
-);
-
-
-///////////////////////////////////////////////////////////////////////
-// RGB24 to YV12 in two passes; writing two 8888 targets each pass.
-//
-// YV12 is full-resolution luma and half-resolution blue/red chroma.
-//
-// (original)
-// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB
-// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB
-// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB
-// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB
-// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB
-// XRGB XRGB XRGB XRGB XRGB XRGB XRGB XRGB
-// |
-// | (y plane) (temporary)
-// | YYYY YYYY UUVV UUVV
-// +--> { YYYY YYYY + UUVV UUVV }
-// YYYY YYYY UUVV UUVV
-// First YYYY YYYY UUVV UUVV
-// pass YYYY YYYY UUVV UUVV
-// YYYY YYYY UUVV UUVV
-// |
-// | (u plane) (v plane)
-// Second | UUUU VVVV
-// pass +--> { UUUU + VVVV }
-// UUUU VVVV
-//
-///////////////////////////////////////////////////////////////////////
-
-// Phase one of RGB24->YV12 conversion: vsFetch4Pixels/fsConvertRGBtoY8UV44
-//
-// Writes four source pixels at a time to a full-size Y plane and a half-width
-// interleaved UV plane. After execution, the Y plane is complete but the UV
-// planes still need to be de-interleaved and vertically scaled.
-const char kRGBtoYV12_vsFetch4Pixels[] = GLSL_PROGRAM_AS_STRING(
- uniform float texel_scale_x_;
- varying vec2 texture_coord0;
- varying vec2 texture_coord1;
- varying vec2 texture_coord2;
- varying vec2 texture_coord3;
- void main() {
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
-
- vec2 texcoord_base = gl_MultiTexCoord0.xy;
- vec2 one_texel_x = vec2(texel_scale_x_, 0.0);
- texture_coord0 = texcoord_base - 1.5 * one_texel_x;
- texture_coord1 = texcoord_base - 0.5 * one_texel_x;
- texture_coord2 = texcoord_base + 0.5 * one_texel_x;
- texture_coord3 = texcoord_base + 1.5 * one_texel_x;
- }
-);
-
-const char kRGBtoYV12_fsConvertRGBtoY8UV44[] = GLSL_PROGRAM_AS_STRING(
- const vec3 rgb_to_y = vec3(0.257, 0.504, 0.098);
- const vec3 rgb_to_u = vec3(-0.148, -0.291, 0.439);
- const vec3 rgb_to_v = vec3(0.439, -0.368, -0.071);
- const float y_bias = 0.0625;
- const float uv_bias = 0.5;
- uniform sampler2DRect texture_;
- varying vec2 texture_coord0;
- varying vec2 texture_coord1;
- varying vec2 texture_coord2;
- varying vec2 texture_coord3;
- void main() {
- // Load the four texture samples.
- vec3 pixel0 = texture2DRect(texture_, texture_coord0).rgb;
- vec3 pixel1 = texture2DRect(texture_, texture_coord1).rgb;
- vec3 pixel2 = texture2DRect(texture_, texture_coord2).rgb;
- vec3 pixel3 = texture2DRect(texture_, texture_coord3).rgb;
-
- // RGB -> Y conversion (x4).
- vec4 yyyy = vec4(dot(pixel0, rgb_to_y),
- dot(pixel1, rgb_to_y),
- dot(pixel2, rgb_to_y),
- dot(pixel3, rgb_to_y)) + y_bias;
-
- // Average adjacent texture samples while converting RGB->UV. This is the
- // same as color converting then averaging, but slightly less math. These
- // values will be in the range [-0.439f, +0.439f] and still need to have
- // the bias term applied.
- vec3 blended_pixel0 = pixel0 + pixel1;
- vec3 blended_pixel1 = pixel2 + pixel3;
- vec2 uu = vec2(dot(blended_pixel0, rgb_to_u),
- dot(blended_pixel1, rgb_to_u)) / 2.0;
- vec2 vv = vec2(dot(blended_pixel0, rgb_to_v),
- dot(blended_pixel1, rgb_to_v)) / 2.0;
-
- gl_FragData[0] = yyyy.OUTPUT_PIXEL_ORDERING;
- gl_FragData[1] = vec4(uu, vv) + uv_bias;
- }
-);
-
-// Phase two of RGB24->YV12 conversion: vsFetch2Pixels/fsConvertUV44toU2V2
-//
-// Deals with UV only. Input is two UUVV quads. The pixels have already been
-// scaled horizontally prior to this point, and vertical scaling will now happen
-// via bilinear interpolation during texture sampling. Output is two color
-// planes U and V, packed four pixels to a "RGBA" quad.
-const char kRGBtoYV12_vsFetch2Pixels[] = GLSL_PROGRAM_AS_STRING(
- varying vec2 texture_coord0;
- varying vec2 texture_coord1;
- void main() {
- gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
-
- vec2 texcoord_base = gl_MultiTexCoord0.xy;
- texture_coord0 = texcoord_base - vec2(0.5, 0.0);
- texture_coord1 = texcoord_base + vec2(0.5, 0.0);
- }
-);
-
-const char kRGBtoYV12_fsConvertUV44toU2V2[] = GLSL_PROGRAM_AS_STRING(
- uniform sampler2DRect texture_;
- varying vec2 texture_coord0;
- varying vec2 texture_coord1;
- void main() {
- // We're just sampling two pixels and unswizzling them. There's no need
- // to do vertical scaling with math, since bilinear interpolation in the
- // sampler takes care of that.
- vec4 lo_uuvv = texture2DRect(texture_, texture_coord0);
- vec4 hi_uuvv = texture2DRect(texture_, texture_coord1);
- gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg).OUTPUT_PIXEL_ORDERING;
- gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba).OUTPUT_PIXEL_ORDERING;
- }
-);
-
-
-enum ShaderProgram {
- SHADER_PROGRAM_BLIT = 0,
- SHADER_PROGRAM_SOLID_WHITE,
- SHADER_PROGRAM_RGB_TO_YV12__1_OF_2,
- SHADER_PROGRAM_RGB_TO_YV12__2_OF_2,
- NUM_SHADER_PROGRAMS
-};
-
-// The code snippets that together make up an entire vertex shader program.
-const char* kVertexShaderSourceCodeMap[] = {
- // SHADER_PROGRAM_BLIT
- kvsBlit,
- // SHADER_PROGRAM_SOLID_WHITE
- kvsSolidWhite,
-
- // SHADER_PROGRAM_RGB_TO_YV12__1_OF_2
- kRGBtoYV12_vsFetch4Pixels,
- // SHADER_PROGRAM_RGB_TO_YV12__2_OF_2
- kRGBtoYV12_vsFetch2Pixels,
-};
-
-// The code snippets that together make up an entire fragment shader program.
-const char* kFragmentShaderSourceCodeMap[] = {
- // SHADER_PROGRAM_BLIT
- kfsBlit,
- // SHADER_PROGRAM_SOLID_WHITE
- kfsSolidWhite,
-
- // SHADER_PROGRAM_RGB_TO_YV12__1_OF_2
- kRGBtoYV12_fsConvertRGBtoY8UV44,
- // SHADER_PROGRAM_RGB_TO_YV12__2_OF_2
- kRGBtoYV12_fsConvertUV44toU2V2,
-};
-
-GLuint CompileShaderGLSL(ShaderProgram shader_program, GLenum shader_type,
- bool output_swap_rb) {
- TRACE_EVENT2("gpu", "CompileShaderGLSL",
- "program", shader_program,
- "type", shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment");
-
- DCHECK_GE(shader_program, 0);
- DCHECK_LT(shader_program, NUM_SHADER_PROGRAMS);
-
- const GLuint shader = glCreateShader(shader_type);
- DCHECK_NE(shader, 0u);
-
- // Select and compile the shader program source code.
- if (shader_type == GL_VERTEX_SHADER) {
- const GLchar* source_snippets[] = {
- kVersionDirective,
- kVertexShaderSourceCodeMap[shader_program],
- };
- glShaderSource(shader, arraysize(source_snippets), source_snippets, NULL);
- } else {
- DCHECK(shader_type == GL_FRAGMENT_SHADER);
- const GLchar* source_snippets[] = {
- kVersionDirective,
- output_swap_rb ? kOutputSwizzleMacroSwapRB : kOutputSwizzleMacroNormal,
- kFragmentShaderSourceCodeMap[shader_program],
- };
- glShaderSource(shader, arraysize(source_snippets), source_snippets, NULL);
- }
- glCompileShader(shader);
-
- // Check for successful compilation. On error in debug builds, pull the info
- // log and emit the compiler messages.
- GLint error;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &error);
- if (error != GL_TRUE) {
-#ifndef NDEBUG
- static const int kMaxInfoLogLength = 8192;
- scoped_ptr<char[]> buffer(new char[kMaxInfoLogLength]);
- GLsizei length_returned = 0;
- glGetShaderInfoLog(shader, kMaxInfoLogLength - 1, &length_returned,
- buffer.get());
- buffer[kMaxInfoLogLength - 1] = '\0';
- DLOG(ERROR) << "Failed to compile "
- << (shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment")
- << " shader for program " << shader_program << ":\n"
- << buffer.get()
- << (length_returned >= kMaxInfoLogLength ?
- "\n*** TRUNCATED! ***" : "");
-#endif
- glDeleteShader(shader);
- return 0;
- }
-
- // Success!
- return shader;
-}
-
-GLuint CompileAndLinkProgram(ShaderProgram which, bool output_swap_rb) {
- TRACE_EVENT1("gpu", "CompileAndLinkProgram", "program", which);
-
- // Compile and link a new shader program.
- const GLuint vertex_shader =
- CompileShaderGLSL(which, GL_VERTEX_SHADER, false);
- const GLuint fragment_shader =
- CompileShaderGLSL(which, GL_FRAGMENT_SHADER, output_swap_rb);
- const GLuint program = glCreateProgram();
- DCHECK_NE(program, 0u);
- glAttachShader(program, vertex_shader);
- glAttachShader(program, fragment_shader);
- glLinkProgram(program);
-
- // Flag shaders for deletion so that they will be deleted automatically when
- // the program is later deleted.
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
-
- // Check that the program successfully linked.
- GLint error = GL_FALSE;
- glGetProgramiv(program, GL_LINK_STATUS, &error);
- if (error != GL_TRUE) {
- glDeleteProgram(program);
- return 0;
- }
- return program;
-}
-
-} // namespace
-
-
-CompositingIOSurfaceShaderPrograms::CompositingIOSurfaceShaderPrograms()
- : rgb_to_yv12_output_format_(GL_BGRA) {
- COMPILE_ASSERT(kNumShaderPrograms == NUM_SHADER_PROGRAMS,
- header_constant_disagrees_with_enum);
- COMPILE_ASSERT(arraysize(kVertexShaderSourceCodeMap) == NUM_SHADER_PROGRAMS,
- vertex_shader_source_code_map_incorrect_size);
- COMPILE_ASSERT(arraysize(kFragmentShaderSourceCodeMap) == NUM_SHADER_PROGRAMS,
- fragment_shader_source_code_map_incorrect_size);
-
- memset(shader_programs_, 0, sizeof(shader_programs_));
- for (size_t i = 0; i < arraysize(texture_var_locations_); ++i)
- texture_var_locations_[i] = -1;
- for (size_t i = 0; i < arraysize(texel_scale_x_var_locations_); ++i)
- texel_scale_x_var_locations_[i] = -1;
-
- // Look for the swizzle_rgba_for_async_readpixels driver bug workaround and
- // modify rgb_to_yv12_output_format_ if necessary.
- // See: http://crbug.com/265115
- GpuDataManagerImpl* const manager = GpuDataManagerImpl::GetInstance();
- if (manager) {
- base::ListValue workarounds;
- manager->GetDriverBugWorkarounds(&workarounds);
- base::ListValue::const_iterator it = workarounds.Find(
- base::StringValue(gpu::GpuDriverBugWorkaroundTypeToString(
- gpu::SWIZZLE_RGBA_FOR_ASYNC_READPIXELS)));
- if (it != workarounds.end())
- rgb_to_yv12_output_format_ = GL_RGBA;
- }
- DVLOG(1) << "Using RGBToYV12 fragment shader output format: "
- << (rgb_to_yv12_output_format_ == GL_BGRA ? "BGRA" : "RGBA");
-}
-
-CompositingIOSurfaceShaderPrograms::~CompositingIOSurfaceShaderPrograms() {
-#ifndef NDEBUG
- for (size_t i = 0; i < arraysize(shader_programs_); ++i)
- DCHECK_EQ(shader_programs_[i], 0u) << "Failed to call Reset().";
-#endif
-}
-
-void CompositingIOSurfaceShaderPrograms::Reset() {
- for (size_t i = 0; i < arraysize(shader_programs_); ++i) {
- if (shader_programs_[i] != 0u) {
- glDeleteProgram(shader_programs_[i]);
- shader_programs_[i] = 0u;
- }
- }
- for (size_t i = 0; i < arraysize(texture_var_locations_); ++i)
- texture_var_locations_[i] = -1;
- for (size_t i = 0; i < arraysize(texel_scale_x_var_locations_); ++i)
- texel_scale_x_var_locations_[i] = -1;
-}
-
-bool CompositingIOSurfaceShaderPrograms::UseBlitProgram() {
- const GLuint program = GetShaderProgram(SHADER_PROGRAM_BLIT);
- if (program == 0u)
- return false;
- glUseProgram(program);
- BindUniformTextureVariable(SHADER_PROGRAM_BLIT, 0);
- return true;
-}
-
-bool CompositingIOSurfaceShaderPrograms::UseSolidWhiteProgram() {
- const GLuint program = GetShaderProgram(SHADER_PROGRAM_SOLID_WHITE);
- if (program == 0u)
- return false;
- glUseProgram(program);
- return true;
-}
-
-bool CompositingIOSurfaceShaderPrograms::UseRGBToYV12Program(
- int pass_number, float texel_scale_x) {
- const int which = SHADER_PROGRAM_RGB_TO_YV12__1_OF_2 + pass_number - 1;
- DCHECK_GE(which, SHADER_PROGRAM_RGB_TO_YV12__1_OF_2);
- DCHECK_LE(which, SHADER_PROGRAM_RGB_TO_YV12__2_OF_2);
-
- const GLuint program = GetShaderProgram(which);
- if (program == 0u)
- return false;
- glUseProgram(program);
- BindUniformTextureVariable(which, 0);
- if (which == SHADER_PROGRAM_RGB_TO_YV12__1_OF_2) {
- BindUniformTexelScaleXVariable(which, texel_scale_x);
- } else {
- // The second pass doesn't have a texel_scale_x uniform variable since it's
- // never supposed to be doing any scaling (i.e., outside of the usual
- // 2x2-->1x1 that's already built into the process).
- DCHECK_EQ(texel_scale_x, 1.0f);
- }
- return true;
-}
-
-void CompositingIOSurfaceShaderPrograms::SetOutputFormatForTesting(
- GLenum format) {
- rgb_to_yv12_output_format_ = format;
- Reset();
-}
-
-GLuint CompositingIOSurfaceShaderPrograms::GetShaderProgram(int which) {
- if (shader_programs_[which] == 0u) {
- shader_programs_[which] =
- CompileAndLinkProgram(static_cast<ShaderProgram>(which),
- rgb_to_yv12_output_format_ == GL_RGBA);
- DCHECK_NE(shader_programs_[which], 0u)
- << "Failed to create ShaderProgram " << which;
- }
- return shader_programs_[which];
-}
-
-void CompositingIOSurfaceShaderPrograms::BindUniformTextureVariable(
- int which, int texture_unit_offset) {
- if (texture_var_locations_[which] == -1) {
- texture_var_locations_[which] =
- glGetUniformLocation(GetShaderProgram(which), "texture_");
- DCHECK_NE(texture_var_locations_[which], -1)
- << "Failed to find location of uniform variable: texture_";
- }
- glUniform1i(texture_var_locations_[which], texture_unit_offset);
-}
-
-void CompositingIOSurfaceShaderPrograms::BindUniformTexelScaleXVariable(
- int which, float texel_scale_x) {
- if (texel_scale_x_var_locations_[which] == -1) {
- texel_scale_x_var_locations_[which] =
- glGetUniformLocation(GetShaderProgram(which), "texel_scale_x_");
- DCHECK_NE(texel_scale_x_var_locations_[which], -1)
- << "Failed to find location of uniform variable: texel_scale_x_";
- }
- glUniform1f(texel_scale_x_var_locations_[which], texel_scale_x);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
deleted file mode 100644
index de1987f2e03..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_SHADER_PROGRAMS_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_SHADER_PROGRAMS_MAC_H_
-
-#include <OpenGL/gl.h>
-
-#include "base/basictypes.h"
-#include "base/gtest_prod_util.h"
-
-namespace content {
-
-// Provides caching of the compile-and-link step for shader programs at runtime
-// since, once compiled and linked, the programs can be shared. Callers invoke
-// one of the UseXXX() methods to glUseProgram() the program and have its
-// uniform variables bound with the given parameters.
-//
-// Note: All public methods must be invoked within the the same GL context!
-class CompositingIOSurfaceShaderPrograms {
- public:
- CompositingIOSurfaceShaderPrograms();
- ~CompositingIOSurfaceShaderPrograms();
-
- // Reset the cache, deleting any references to currently-cached shader
- // programs. This must be called within an active OpenGL context just before
- // destruction.
- void Reset();
-
- // Begin using the "blit" program, which is set up to sample the texture at
- // GL_TEXTURE_0. Returns false on error.
- bool UseBlitProgram();
-
- // Begin using the program that just draws solid white very efficiently.
- // Returns false on error.
- bool UseSolidWhiteProgram();
-
- // Begin using one of the two RGB-to-YV12 color conversion programs, as
- // specified by |pass_number| 1 or 2. The programs will sample the texture at
- // GL_TEXTURE0, and account for scaling in the X direction by |texel_scale_x|.
- // Returns false on error.
- bool UseRGBToYV12Program(int pass_number, float texel_scale_x);
-
- // |format| argument to use for glReadPixels() when reading back textures
- // generated by the RGBToYV12 program.
- GLenum rgb_to_yv12_output_format() const {
- return rgb_to_yv12_output_format_;
- }
-
- protected:
- FRIEND_TEST_ALL_PREFIXES(CompositingIOSurfaceTransformerTest,
- TransformsRGBToYV12);
-
- // Side effect: Calls Reset(), deleting any cached programs.
- void SetOutputFormatForTesting(GLenum format);
-
- private:
- enum { kNumShaderPrograms = 4 };
-
- // Helper methods to cache uniform variable locations.
- GLuint GetShaderProgram(int which);
- void BindUniformTextureVariable(int which, int texture_unit_offset);
- void BindUniformTexelScaleXVariable(int which, float texel_scale_x);
-
- // Cached values for previously-compiled/linked shader programs, and the
- // locations of their uniform variables.
- GLuint shader_programs_[kNumShaderPrograms];
- GLint texture_var_locations_[kNumShaderPrograms];
- GLint texel_scale_x_var_locations_[kNumShaderPrograms];
-
- // Byte order of the quads generated by the RGBToYV12 shader program. Must
- // always be GL_BGRA (default) or GL_RGBA (workaround case).
- GLenum rgb_to_yv12_output_format_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositingIOSurfaceShaderPrograms);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_SHADER_PROGRAMS_MAC_H_
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc b/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
deleted file mode 100644
index 2e0401ff476..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/renderer_host/compositing_iosurface_transformer_mac.h"
-
-#include <algorithm>
-
-#include "base/basictypes.h"
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/size.h"
-
-namespace content {
-
-namespace {
-
-const GLenum kColorAttachments[] = {
- GL_COLOR_ATTACHMENT0_EXT,
- GL_COLOR_ATTACHMENT1_EXT
-};
-
-// Set viewport and model/projection matrices for drawing to a framebuffer of
-// size dst_size, with coordinates starting at (0, 0).
-void SetTransformationsForOffScreenRendering(const gfx::Size& dst_size) {
- glViewport(0, 0, dst_size.width(), dst_size.height());
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, dst_size.width(), 0, dst_size.height(), -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-}
-
-// Configure texture sampling parameters.
-void SetTextureParameters(GLenum target, GLint min_mag_filter, GLint wrap) {
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_mag_filter);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, min_mag_filter);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
-}
-
-// Draw the currently-bound texture. The src region is applied to the entire
-// destination framebuffer of the given size. Specify |flip_y| is the src
-// texture is upside-down relative to the destination.
-//
-// Assumption: The orthographic projection is set up as
-// (0,0)x(dst_width,dst_height).
-void DrawQuad(float src_x, float src_y, float src_width, float src_height,
- bool flip_y, float dst_width, float dst_height) {
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- float vertices[4][2] = {
- { 0.0f, dst_height },
- { 0.0f, 0.0f },
- { dst_width, 0.0f },
- { dst_width, dst_height }
- };
- glVertexPointer(arraysize(vertices[0]), GL_FLOAT, sizeof(vertices[0]),
- vertices);
-
- float tex_coords[4][2] = {
- { src_x, src_y + src_height },
- { src_x, src_y },
- { src_x + src_width, src_y },
- { src_x + src_width, src_y + src_height }
- };
- if (flip_y) {
- std::swap(tex_coords[0][1], tex_coords[1][1]);
- std::swap(tex_coords[2][1], tex_coords[3][1]);
- }
- glTexCoordPointer(arraysize(tex_coords[0]), GL_FLOAT, sizeof(tex_coords[0]),
- tex_coords);
-
- COMPILE_ASSERT(arraysize(vertices) == arraysize(tex_coords),
- same_number_of_points_in_both);
- glDrawArrays(GL_QUADS, 0, arraysize(vertices));
-
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
-
-} // namespace
-
-CompositingIOSurfaceTransformer::CompositingIOSurfaceTransformer(
- GLenum texture_target, bool src_texture_needs_y_flip,
- CompositingIOSurfaceShaderPrograms* shader_program_cache)
- : texture_target_(texture_target),
- src_texture_needs_y_flip_(src_texture_needs_y_flip),
- shader_program_cache_(shader_program_cache),
- frame_buffer_(0) {
- DCHECK(texture_target_ == GL_TEXTURE_RECTANGLE_ARB)
- << "Fragment shaders currently only support RECTANGLE textures.";
- DCHECK(shader_program_cache_);
-
- memset(textures_, 0, sizeof(textures_));
-
- // The RGB-to-YV12 transform requires that the driver/hardware supports
- // multiple draw buffers.
- GLint max_draw_buffers = 1;
- glGetIntegerv(GL_MAX_DRAW_BUFFERS, &max_draw_buffers);
- system_supports_multiple_draw_buffers_ = (max_draw_buffers >= 2);
-}
-
-CompositingIOSurfaceTransformer::~CompositingIOSurfaceTransformer() {
- for (int i = 0; i < NUM_CACHED_TEXTURES; ++i)
- DCHECK_EQ(textures_[i], 0u) << "Failed to call ReleaseCachedGLObjects().";
- DCHECK_EQ(frame_buffer_, 0u) << "Failed to call ReleaseCachedGLObjects().";
-}
-
-void CompositingIOSurfaceTransformer::ReleaseCachedGLObjects() {
- for (int i = 0; i < NUM_CACHED_TEXTURES; ++i) {
- if (textures_[i]) {
- glDeleteTextures(1, &textures_[i]);
- textures_[i] = 0;
- texture_sizes_[i] = gfx::Size();
- }
- }
- if (frame_buffer_) {
- glDeleteFramebuffersEXT(1, &frame_buffer_);
- frame_buffer_ = 0;
- }
-}
-
-bool CompositingIOSurfaceTransformer::ResizeBilinear(
- GLuint src_texture, const gfx::Rect& src_subrect, const gfx::Size& dst_size,
- GLuint* texture) {
- if (src_subrect.IsEmpty() || dst_size.IsEmpty())
- return false;
-
- glActiveTexture(GL_TEXTURE0);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
-
- PrepareTexture(RGBA_OUTPUT, dst_size);
- PrepareFramebuffer();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- texture_target_, textures_[RGBA_OUTPUT], 0);
- DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
- GL_FRAMEBUFFER_COMPLETE_EXT);
-
- glBindTexture(texture_target_, src_texture);
- SetTextureParameters(
- texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR,
- GL_CLAMP_TO_EDGE);
-
- const bool prepared = shader_program_cache_->UseBlitProgram();
- DCHECK(prepared);
- SetTransformationsForOffScreenRendering(dst_size);
- DrawQuad(src_subrect.x(), src_subrect.y(),
- src_subrect.width(), src_subrect.height(),
- src_texture_needs_y_flip_,
- dst_size.width(), dst_size.height());
- glUseProgram(0);
-
- glBindTexture(texture_target_, 0);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-
- *texture = textures_[RGBA_OUTPUT];
- return true;
-}
-
-bool CompositingIOSurfaceTransformer::TransformRGBToYV12(
- GLuint src_texture,
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- GLuint* texture_y,
- GLuint* texture_u,
- GLuint* texture_v,
- gfx::Size* packed_y_size,
- gfx::Size* packed_uv_size) {
- if (!system_supports_multiple_draw_buffers_)
- return false;
- if (src_subrect.IsEmpty() || dst_size.IsEmpty())
- return false;
-
- TRACE_EVENT0("gpu", "TransformRGBToYV12");
-
- glActiveTexture(GL_TEXTURE0);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_BLEND);
-
- // Resize output textures for each plane, and for the intermediate UUVV one
- // that becomes an input into pass #2. |packed_y_size| is the size of the Y
- // output texture, where its width is 1/4 the number of Y pixels because 4 Y
- // pixels are packed into a single quad. |packed_uv_size| is half the size of
- // Y in both dimensions, rounded up.
- *packed_y_size = gfx::Size((dst_size.width() + 3) / 4, dst_size.height());
- *packed_uv_size = gfx::Size((packed_y_size->width() + 1) / 2,
- (packed_y_size->height() + 1) / 2);
- PrepareTexture(Y_PLANE_OUTPUT, *packed_y_size);
- PrepareTexture(UUVV_INTERMEDIATE, *packed_y_size);
- PrepareTexture(U_PLANE_OUTPUT, *packed_uv_size);
- PrepareTexture(V_PLANE_OUTPUT, *packed_uv_size);
-
- /////////////////////////////////////////
- // Pass 1: RGB --(scaled)--> YYYY + UUVV
- PrepareFramebuffer();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frame_buffer_);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- texture_target_, textures_[Y_PLANE_OUTPUT], 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
- texture_target_, textures_[UUVV_INTERMEDIATE], 0);
- DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
- GL_FRAMEBUFFER_COMPLETE_EXT);
- glDrawBuffers(2, kColorAttachments);
-
- // Read from |src_texture|. Enable bilinear filtering only if scaling is
- // required. The filtering will take place entirely in the first pass.
- glBindTexture(texture_target_, src_texture);
- SetTextureParameters(
- texture_target_, src_subrect.size() == dst_size ? GL_NEAREST : GL_LINEAR,
- GL_CLAMP_TO_EDGE);
-
- // Use the first-pass shader program and draw the scene.
- const bool prepared_pass_1 = shader_program_cache_->UseRGBToYV12Program(
- 1,
- static_cast<float>(src_subrect.width()) / dst_size.width());
- DCHECK(prepared_pass_1);
- SetTransformationsForOffScreenRendering(*packed_y_size);
- DrawQuad(src_subrect.x(), src_subrect.y(),
- ((packed_y_size->width() * 4.0f) / dst_size.width()) *
- src_subrect.width(),
- src_subrect.height(),
- src_texture_needs_y_flip_,
- packed_y_size->width(), packed_y_size->height());
-
- /////////////////////////////////////////
- // Pass 2: UUVV -> UUUU + VVVV
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- texture_target_, textures_[U_PLANE_OUTPUT], 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
- texture_target_, textures_[V_PLANE_OUTPUT], 0);
- DCHECK(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) ==
- GL_FRAMEBUFFER_COMPLETE_EXT);
-
- // Read from the intermediate UUVV texture. The second pass uses bilinear
- // minification to achieve vertical scaling, so enable it always.
- glBindTexture(texture_target_, textures_[UUVV_INTERMEDIATE]);
- SetTextureParameters(texture_target_, GL_LINEAR, GL_CLAMP_TO_EDGE);
-
- // Use the second-pass shader program and draw the scene.
- const bool prepared_pass_2 =
- shader_program_cache_->UseRGBToYV12Program(2, 1.0f);
- DCHECK(prepared_pass_2);
- SetTransformationsForOffScreenRendering(*packed_uv_size);
- DrawQuad(0.0f, 0.0f,
- packed_uv_size->width() * 2.0f,
- packed_uv_size->height() * 2.0f,
- false,
- packed_uv_size->width(), packed_uv_size->height());
- glUseProgram(0);
-
- // Before leaving, put back to drawing to a single rendering output.
- glDrawBuffers(1, kColorAttachments);
-
- glBindTexture(texture_target_, 0);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-
- *texture_y = textures_[Y_PLANE_OUTPUT];
- *texture_u = textures_[U_PLANE_OUTPUT];
- *texture_v = textures_[V_PLANE_OUTPUT];
- return true;
-}
-
-void CompositingIOSurfaceTransformer::PrepareTexture(
- CachedTexture which, const gfx::Size& size) {
- DCHECK_GE(which, 0);
- DCHECK_LT(which, NUM_CACHED_TEXTURES);
- DCHECK(!size.IsEmpty());
-
- if (!textures_[which]) {
- glGenTextures(1, &textures_[which]);
- DCHECK_NE(textures_[which], 0u);
- texture_sizes_[which] = gfx::Size();
- }
-
- // Re-allocate the texture if its size has changed since last use.
- if (texture_sizes_[which] != size) {
- TRACE_EVENT2("gpu", "Resize Texture",
- "which", which,
- "new_size", size.ToString());
- glBindTexture(texture_target_, textures_[which]);
- glTexImage2D(texture_target_, 0, GL_RGBA, size.width(), size.height(), 0,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
- texture_sizes_[which] = size;
- }
-}
-
-void CompositingIOSurfaceTransformer::PrepareFramebuffer() {
- if (!frame_buffer_) {
- glGenFramebuffersEXT(1, &frame_buffer_);
- DCHECK_NE(frame_buffer_, 0u);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.h b/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.h
deleted file mode 100644
index 48900741944..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_TRANSFORMER_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_TRANSFORMER_MAC_H_
-
-#include <OpenGL/gl.h>
-
-#include "base/basictypes.h"
-#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
-#include "ui/gfx/size.h"
-
-namespace gfx {
-class Rect;
-} // namespace gfx
-
-namespace content {
-
-// Provides useful image filtering operations that are implemented efficiently
-// using OpenGL shader programs.
-//
-// Note: All methods assume to be called within an active OpenGL context.
-class CompositingIOSurfaceTransformer {
- public:
- // Construct a transformer that always uses the given parameters for texture
- // bindings. |texture_target| is one of the valid enums to use with
- // glBindTexture().
- // |src_texture_needs_y_flip| is true when the |src_texture| argument to any
- // of the methods below uses upside-down Y coordinates.
- // |shader_program_cache| is not owned by this instance.
- CompositingIOSurfaceTransformer(
- GLenum texture_target, bool src_texture_needs_y_flip,
- CompositingIOSurfaceShaderPrograms* shader_program_cache);
-
- ~CompositingIOSurfaceTransformer();
-
- // Delete any references to currently-cached OpenGL objects. This must be
- // called within the OpenGL context just before destruction.
- void ReleaseCachedGLObjects();
-
- // Resize using bilinear interpolation. Returns false on error. Otherwise,
- // the |texture| argument will point to the result. Ownership of the returned
- // |texture| remains with CompositingIOSurfaceTransformer (i.e., the caller
- // must not delete this texture). The |texture| remains valid until the next
- // call to ResizeBilinear() or ReleaseCachedGLObjects().
- //
- // If the src and dst sizes are identical, this becomes a simple copy into a
- // new texture.
- //
- // Note: This implementation is faulty in that minifications by more than 2X
- // will undergo aliasing.
- bool ResizeBilinear(GLuint src_texture, const gfx::Rect& src_subrect,
- const gfx::Size& dst_size, GLuint* texture);
-
- // Color format conversion from RGB to planar YV12 (also known as YUV420).
- //
- // YV12 is effectively a twelve bit per pixel format consisting of a full-
- // size y (luminance) plane and half-width, half-height u and v (blue and
- // red chrominance) planes. This method will return three off-screen
- // textures, one for each plane, via the output arguments |texture_y|,
- // |texture_u|, and |texture_v|. While the textures are in GL_RGBA format,
- // they should be interpreted as the appropriate single-byte, planar format
- // after reading the pixel data. The output arguments |packed_y_size| and
- // |packed_uv_size| follow from these special semantics: They represent the
- // size of their corresponding texture, if it was to be treated like RGBA
- // pixel data. That means their widths are in terms of "quads," where one
- // quad contains 4 Y (or U or V) pixels.
- //
- // Ownership of the returned textures remains with
- // CompositingIOSurfaceTransformer (i.e., the caller must not delete the
- // textures). The textures remain valid until the next call to
- // TransformRGBToYV12() or ReleaseCachedGLObjects().
- //
- // If |src_subrect|'s size does not match |dst_size|, the source will be
- // bilinearly interpolated during conversion.
- //
- // Returns true if successful, and the caller is responsible for deleting the
- // output textures.
- bool TransformRGBToYV12(
- GLuint src_texture, const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- GLuint* texture_y, GLuint* texture_u, GLuint* texture_v,
- gfx::Size* packed_y_size, gfx::Size* packed_uv_size);
-
- private:
- enum CachedTexture {
- RGBA_OUTPUT = 0,
- Y_PLANE_OUTPUT,
- UUVV_INTERMEDIATE,
- U_PLANE_OUTPUT,
- V_PLANE_OUTPUT,
- NUM_CACHED_TEXTURES
- };
-
- // If necessary, generate the texture and/or resize it to the given |size|.
- void PrepareTexture(CachedTexture which, const gfx::Size& size);
-
- // If necessary, generate a framebuffer object to be used as an intermediate
- // destination for drawing.
- void PrepareFramebuffer();
-
- // Target to bind all input and output textures to (which defines the type of
- // textures being created and read). Generally, this is
- // GL_TEXTURE_RECTANGLE_ARB.
- const GLenum texture_target_;
- const bool src_texture_needs_y_flip_;
- CompositingIOSurfaceShaderPrograms* const shader_program_cache_;
-
- // Cached OpenGL objects.
- GLuint textures_[NUM_CACHED_TEXTURES];
- gfx::Size texture_sizes_[NUM_CACHED_TEXTURES];
- GLuint frame_buffer_;
-
- // Auto-detected and set once in the constructor.
- bool system_supports_multiple_draw_buffers_;
-
- DISALLOW_COPY_AND_ASSIGN(CompositingIOSurfaceTransformer);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_TRANSFORMER_MAC_H_
diff --git a/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc b/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
deleted file mode 100644
index 07c59429184..00000000000
--- a/chromium/content/browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc
+++ /dev/null
@@ -1,533 +0,0 @@
-// Copyright (c) 2013 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 "content/browser/renderer_host/compositing_iosurface_transformer_mac.h"
-
-#include <OpenGL/CGLCurrent.h>
-#include <OpenGL/CGLRenderers.h>
-#include <OpenGL/CGLTypes.h>
-#include <OpenGL/OpenGL.h>
-#include <OpenGL/gl.h>
-#include <OpenGL/glu.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <sstream>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/compositing_iosurface_shader_programs_mac.h"
-#include "media/base/yuv_convert.h"
-#include "testing/gtest/include/gtest/gtest.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/SkRect.h"
-#include "ui/gfx/rect.h"
-
-namespace content {
-
-#define EXPECT_NO_GL_ERROR(stmt) \
- do { \
- stmt; \
- const GLenum error_code = glGetError(); \
- EXPECT_TRUE(GL_NO_ERROR == error_code) \
- << "for error code " << error_code \
- << ": " << gluErrorString(error_code); \
- } while(0)
-
-namespace {
-
-const GLenum kGLTextureTarget = GL_TEXTURE_RECTANGLE_ARB;
-
-enum RendererRestriction {
- RESTRICTION_NONE,
- RESTRICTION_SOFTWARE_ONLY,
- RESTRICTION_HARDWARE_ONLY
-};
-
-bool InitializeGLContext(CGLContextObj* context,
- RendererRestriction restriction) {
- std::vector<CGLPixelFormatAttribute> attribs;
- // Select off-screen renderers only.
- attribs.push_back(kCGLPFAOffScreen);
- // By default, the library will prefer hardware-accelerated renderers, but
- // falls back on the software ones if necessary. However, there are use cases
- // where we want to force a restriction (e.g., benchmarking performance).
- if (restriction == RESTRICTION_SOFTWARE_ONLY) {
- attribs.push_back(kCGLPFARendererID);
- attribs.push_back(static_cast<CGLPixelFormatAttribute>(
- kCGLRendererGenericFloatID));
- } else if (restriction == RESTRICTION_HARDWARE_ONLY) {
- attribs.push_back(kCGLPFAAccelerated);
- }
- attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
-
- CGLPixelFormatObj format;
- GLint num_pixel_formats = 0;
- bool success = true;
- if (CGLChoosePixelFormat(&attribs.front(), &format, &num_pixel_formats) !=
- kCGLNoError) {
- LOG(ERROR) << "Error choosing pixel format.";
- success = false;
- }
- if (success && num_pixel_formats <= 0) {
- LOG(ERROR) << "num_pixel_formats <= 0; actual value is "
- << num_pixel_formats;
- success = false;
- }
- if (success && CGLCreateContext(format, NULL, context) != kCGLNoError) {
- LOG(ERROR) << "Error creating context.";
- success = false;
- }
- CGLDestroyPixelFormat(format);
- return success;
-}
-
-// Returns a decent test pattern for testing all of: 1) orientation, 2) scaling,
-// 3) color space conversion (e.g., 4 pixels --> one U or V pixel), and 4)
-// texture alignment/processing. Example 32x32 bitmap:
-//
-// GGGGGGGGGGGGGGGGRRBBRRBBRRBBRRBB
-// GGGGGGGGGGGGGGGGRRBBRRBBRRBBRRBB
-// GGGGGGGGGGGGGGGGYYCCYYCCYYCCYYCC
-// GGGGGGGGGGGGGGGGYYCCYYCCYYCCYYCC
-// GGGGGGGGGGGGGGGGRRBBRRBBRRBBRRBB
-// GGGGGGGGGGGGGGGGRRBBRRBBRRBBRRBB
-// GGGGGGGGGGGGGGGGYYCCYYCCYYCCYYCC
-// GGGGGGGGGGGGGGGGYYCCYYCCYYCCYYCC
-// RRBBRRBBRRBBRRBBRRBBRRBBRRBBRRBB
-// RRBBRRBBRRBBRRBBRRBBRRBBRRBBRRBB
-// YYCCYYCCYYCCYYCCYYCCYYCCYYCCYYCC
-// YYCCYYCCYYCCYYCCYYCCYYCCYYCCYYCC
-// RRBBRRBBRRBBRRBBRRBBRRBBRRBBRRBB
-// RRBBRRBBRRBBRRBBRRBBRRBBRRBBRRBB
-// YYCCYYCCYYCCYYCCYYCCYYCCYYCCYYCC
-// YYCCYYCCYYCCYYCCYYCCYYCCYYCCYYCC
-//
-// Key: G = Gray, R = Red, B = Blue, Y = Yellow, C = Cyan
-SkBitmap GenerateTestPatternBitmap(const gfx::Size& size) {
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- CHECK(bitmap.allocPixels());
- SkAutoLockPixels lock_bitmap(bitmap);
- bitmap.eraseColor(SK_ColorGRAY);
- for (int y = 0; y < size.height(); ++y) {
- uint32_t* p = bitmap.getAddr32(0, y);
- for (int x = 0; x < size.width(); ++x, ++p) {
- if ((x < (size.width() / 2)) && (y < (size.height() / 2)))
- continue; // Leave upper-left quadrant gray.
- *p = SkColorSetARGB(255,
- x % 4 < 2 ? 255 : 0,
- y % 4 < 2 ? 255 : 0,
- x % 4 < 2 ? 0 : 255);
- }
- }
- return bitmap;
-}
-
-// Creates a new texture consisting of the given |bitmap|.
-GLuint CreateTextureWithImage(const SkBitmap& bitmap) {
- GLuint texture;
- EXPECT_NO_GL_ERROR(glGenTextures(1, &texture));
- EXPECT_NO_GL_ERROR(glBindTexture(kGLTextureTarget, texture));
- {
- SkAutoLockPixels lock_bitmap(bitmap);
- EXPECT_NO_GL_ERROR(glTexImage2D(
- kGLTextureTarget, 0, GL_RGBA, bitmap.width(), bitmap.height(), 0,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, bitmap.getPixels()));
- }
- glBindTexture(kGLTextureTarget, 0);
- return texture;
-}
-
-// Read back a texture from the GPU, returning the image data as an SkBitmap.
-SkBitmap ReadBackTexture(GLuint texture, const gfx::Size& size, GLenum format) {
- SkBitmap result;
- result.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- CHECK(result.allocPixels());
-
- GLuint frame_buffer;
- EXPECT_NO_GL_ERROR(glGenFramebuffersEXT(1, &frame_buffer));
- EXPECT_NO_GL_ERROR(
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, frame_buffer));
- EXPECT_NO_GL_ERROR(glFramebufferTexture2DEXT(
- GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, kGLTextureTarget,
- texture, 0));
- DCHECK(glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT) ==
- GL_FRAMEBUFFER_COMPLETE_EXT);
-
- {
- SkAutoLockPixels lock_result(result);
- EXPECT_NO_GL_ERROR(glReadPixels(
- 0, 0, size.width(), size.height(), format, GL_UNSIGNED_INT_8_8_8_8_REV,
- result.getPixels()));
- }
-
- EXPECT_NO_GL_ERROR(glDeleteFramebuffersEXT(1, &frame_buffer));
-
- return result;
-}
-
-// Returns the |src_rect| region of |src| scaled to |to_size| by drawing on a
-// Skia canvas, and using bilinear filtering (just like a GPU would).
-SkBitmap ScaleBitmapWithSkia(const SkBitmap& src,
- const gfx::Rect& src_rect,
- const gfx::Size& to_size) {
- SkBitmap cropped_src;
- if (src_rect == gfx::Rect(0, 0, src.width(), src.height())) {
- cropped_src = src;
- } else {
- CHECK(src.extractSubset(
- &cropped_src,
- SkIRect::MakeXYWH(src_rect.x(), src_rect.y(),
- src_rect.width(), src_rect.height())));
- }
-
- SkBitmap result;
- result.setConfig(cropped_src.config(), to_size.width(), to_size.height());
- CHECK(result.allocPixels());
-
- SkCanvas canvas(result);
- canvas.scale(static_cast<double>(result.width()) / cropped_src.width(),
- static_cast<double>(result.height()) / cropped_src.height());
- SkPaint paint;
- paint.setFilterLevel(SkPaint::kLow_FilterLevel); // Use bilinear filtering.
- canvas.drawBitmap(cropped_src, 0, 0, &paint);
-
- return result;
-}
-
-// The maximum value by which a pixel value may deviate from the expected value
-// before considering it "significantly different." This is meant to account
-// for the slight differences in filtering techniques used between the various
-// GPUs and software implementations.
-const int kDifferenceThreshold = 16;
-
-// Returns the number of pixels significantly different between |expected| and
-// |actual|.
-int ImageDifference(const SkBitmap& expected, const SkBitmap& actual) {
- SkAutoLockPixels lock_expected(expected);
- SkAutoLockPixels lock_actual(actual);
-
- // Sanity-check assumed image properties.
- DCHECK_EQ(expected.width(), actual.width());
- DCHECK_EQ(expected.height(), actual.height());
- DCHECK_EQ(SkBitmap::kARGB_8888_Config, expected.config());
- DCHECK_EQ(SkBitmap::kARGB_8888_Config, actual.config());
-
- // Compare both images.
- int num_pixels_different = 0;
- for (int y = 0; y < expected.height(); ++y) {
- const uint32_t* p = expected.getAddr32(0, y);
- const uint32_t* q = actual.getAddr32(0, y);
- for (int x = 0; x < expected.width(); ++x, ++p, ++q) {
- if (abs(static_cast<int>(SkColorGetR(*p)) -
- static_cast<int>(SkColorGetR(*q))) > kDifferenceThreshold ||
- abs(static_cast<int>(SkColorGetG(*p)) -
- static_cast<int>(SkColorGetG(*q))) > kDifferenceThreshold ||
- abs(static_cast<int>(SkColorGetB(*p)) -
- static_cast<int>(SkColorGetB(*q))) > kDifferenceThreshold) {
- ++num_pixels_different;
- }
- }
- }
-
- return num_pixels_different;
-}
-
-// Returns the number of pixels significantly different between |expected| and
-// |actual|. It is understood that |actual| contains 4-byte quads, and so we
-// may need to be ignoring a mod-4 number of pixels at the end of each of its
-// rows.
-int ImagePlaneDifference(const uint8* expected, const SkBitmap& actual,
- const gfx::Size& dst_size) {
- SkAutoLockPixels actual_lock(actual);
-
- int num_pixels_different = 0;
- for (int y = 0; y < dst_size.height(); ++y) {
- const uint8* p = expected + y * dst_size.width();
- const uint8* const p_end = p + dst_size.width();
- const uint8* q =
- reinterpret_cast<uint8*>(actual.getPixels()) + y * actual.rowBytes();
- for (; p < p_end; ++p, ++q) {
- if (abs(static_cast<int>(*p) - static_cast<int>(*q)) >
- kDifferenceThreshold) {
- ++num_pixels_different;
- }
- }
- }
-
- return num_pixels_different;
-}
-
-} // namespace
-
-// Note: All tests fixtures operate within an off-screen OpenGL context.
-class CompositingIOSurfaceTransformerTest : public testing::Test {
- public:
- CompositingIOSurfaceTransformerTest() {
- // TODO(miu): Try to use RESTRICTION_NONE to speed up the execution time of
- // unit tests, once it's established that the trybots and buildbots behave
- // well when using the GPU.
- CHECK(InitializeGLContext(&context_, RESTRICTION_SOFTWARE_ONLY));
- CGLSetCurrentContext(context_);
- shader_program_cache_.reset(new CompositingIOSurfaceShaderPrograms());
- transformer_.reset(new CompositingIOSurfaceTransformer(
- kGLTextureTarget, false, shader_program_cache_.get()));
- }
-
- virtual ~CompositingIOSurfaceTransformerTest() {
- transformer_->ReleaseCachedGLObjects();
- shader_program_cache_->Reset();
- CGLSetCurrentContext(NULL);
- CGLDestroyContext(context_);
- }
-
- protected:
- void RunResizeTest(const SkBitmap& src_bitmap, const gfx::Rect& src_rect,
- const gfx::Size& dst_size) {
- SCOPED_TRACE(::testing::Message()
- << "src_rect=(" << src_rect.x() << ',' << src_rect.y()
- << ")x[" << src_rect.width() << 'x' << src_rect.height()
- << "]; dst_size=[" << dst_size.width() << 'x'
- << dst_size.height() << ']');
-
- // Do the scale operation on the GPU.
- const GLuint original_texture = CreateTextureWithImage(src_bitmap);
- ASSERT_NE(0u, original_texture);
- GLuint scaled_texture = 0u;
- ASSERT_TRUE(transformer_->ResizeBilinear(
- original_texture, src_rect, dst_size, &scaled_texture));
- EXPECT_NE(0u, scaled_texture);
- CGLFlushDrawable(context_); // Account for some buggy driver impls.
- const SkBitmap result_bitmap =
- ReadBackTexture(scaled_texture, dst_size, GL_BGRA);
- EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
-
- // Compare the image read back to the version produced by a known-working
- // software implementation. Allow up to 2 lines of mismatch due to how
- // implementations disagree on resolving the processing of edges.
- const SkBitmap expected_bitmap =
- ScaleBitmapWithSkia(src_bitmap, src_rect, dst_size);
- EXPECT_GE(std::max(expected_bitmap.width(), expected_bitmap.height()) * 2,
- ImageDifference(expected_bitmap, result_bitmap));
- }
-
- void RunTransformRGBToYV12Test(
- const SkBitmap& src_bitmap, const gfx::Rect& src_rect,
- const gfx::Size& dst_size) {
- SCOPED_TRACE(::testing::Message()
- << "src_rect=(" << src_rect.x() << ',' << src_rect.y()
- << ")x[" << src_rect.width() << 'x' << src_rect.height()
- << "]; dst_size=[" << dst_size.width() << 'x'
- << dst_size.height() << ']');
-
- // Perform the RGB to YV12 conversion.
- const GLuint original_texture = CreateTextureWithImage(src_bitmap);
- ASSERT_NE(0u, original_texture);
- GLuint texture_y = 0u;
- GLuint texture_u = 0u;
- GLuint texture_v = 0u;
- gfx::Size packed_y_size;
- gfx::Size packed_uv_size;
- ASSERT_TRUE(transformer_->TransformRGBToYV12(
- original_texture, src_rect, dst_size,
- &texture_y, &texture_u, &texture_v, &packed_y_size, &packed_uv_size));
- EXPECT_NE(0u, texture_y);
- EXPECT_NE(0u, texture_u);
- EXPECT_NE(0u, texture_v);
- EXPECT_FALSE(packed_y_size.IsEmpty());
- EXPECT_FALSE(packed_uv_size.IsEmpty());
- EXPECT_NO_GL_ERROR(glDeleteTextures(1, &original_texture));
-
- // Read-back the texture for each plane.
- CGLFlushDrawable(context_); // Account for some buggy driver impls.
- const GLenum format = shader_program_cache_->rgb_to_yv12_output_format();
- const SkBitmap result_y_bitmap =
- ReadBackTexture(texture_y, packed_y_size, format);
- const SkBitmap result_u_bitmap =
- ReadBackTexture(texture_u, packed_uv_size, format);
- const SkBitmap result_v_bitmap =
- ReadBackTexture(texture_v, packed_uv_size, format);
-
- // Compare the Y, U, and V planes read-back to the version produced by a
- // known-working software implementation. Allow up to 2 lines of mismatch
- // due to how implementations disagree on resolving the processing of edges.
- const SkBitmap expected_bitmap =
- ScaleBitmapWithSkia(src_bitmap, src_rect, dst_size);
- const gfx::Size dst_uv_size(
- (dst_size.width() + 1) / 2, (dst_size.height() + 1) / 2);
- scoped_ptr<uint8[]> expected_y_plane(
- new uint8[dst_size.width() * dst_size.height()]);
- scoped_ptr<uint8[]> expected_u_plane(
- new uint8[dst_uv_size.width() * dst_uv_size.height()]);
- scoped_ptr<uint8[]> expected_v_plane(
- new uint8[dst_uv_size.width() * dst_uv_size.height()]);
- {
- SkAutoLockPixels src_bitmap_lock(expected_bitmap);
- media::ConvertRGB32ToYUV(
- reinterpret_cast<const uint8*>(expected_bitmap.getPixels()),
- expected_y_plane.get(), expected_u_plane.get(),
- expected_v_plane.get(),
- expected_bitmap.width(), expected_bitmap.height(),
- expected_bitmap.rowBytes(),
- dst_size.width(), (dst_size.width() + 1) / 2);
- }
- EXPECT_GE(
- std::max(expected_bitmap.width(), expected_bitmap.height()) * 2,
- ImagePlaneDifference(expected_y_plane.get(), result_y_bitmap, dst_size))
- << " for RGB --> Y Plane";
- EXPECT_GE(
- std::max(expected_bitmap.width(), expected_bitmap.height()),
- ImagePlaneDifference(expected_u_plane.get(), result_u_bitmap,
- dst_uv_size))
- << " for RGB --> U Plane";
- EXPECT_GE(
- std::max(expected_bitmap.width(), expected_bitmap.height()),
- ImagePlaneDifference(expected_v_plane.get(), result_v_bitmap,
- dst_uv_size))
- << " for RGB --> V Plane";
- }
-
- CompositingIOSurfaceShaderPrograms* shader_program_cache() const {
- return shader_program_cache_.get();
- }
-
- private:
- CGLContextObj context_;
- scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache_;
- scoped_ptr<CompositingIOSurfaceTransformer> transformer_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompositingIOSurfaceTransformerTest);
-};
-
-TEST_F(CompositingIOSurfaceTransformerTest, ShaderProgramsCompileAndLink) {
- // Attempt to use each program, binding its required uniform variables.
- EXPECT_NO_GL_ERROR(shader_program_cache()->UseBlitProgram());
- EXPECT_NO_GL_ERROR(shader_program_cache()->UseSolidWhiteProgram());
- EXPECT_NO_GL_ERROR(shader_program_cache()->UseRGBToYV12Program(1, 1.0f));
- EXPECT_NO_GL_ERROR(shader_program_cache()->UseRGBToYV12Program(2, 1.0f));
-
- EXPECT_NO_GL_ERROR(glUseProgram(0));
-}
-
-namespace {
-
-const struct TestParameters {
- int src_width;
- int src_height;
- int scaled_width;
- int scaled_height;
-} kTestParameters[] = {
- // Test 1:1 copies, but exposing varying pixel packing configurations.
- { 64, 64, 64, 64 },
- { 63, 63, 63, 63 },
- { 62, 62, 62, 62 },
- { 61, 61, 61, 61 },
- { 60, 60, 60, 60 },
- { 59, 59, 59, 59 },
- { 58, 58, 58, 58 },
- { 57, 57, 57, 57 },
- { 56, 56, 56, 56 },
-
- // Even-size, one or both dimensions upscaled.
- { 32, 32, 64, 32 }, { 32, 32, 32, 64 }, { 32, 32, 64, 64 },
- // Even-size, one or both dimensions downscaled by 2X.
- { 32, 32, 16, 32 }, { 32, 32, 32, 16 }, { 32, 32, 16, 16 },
- // Even-size, one or both dimensions downscaled by 1 pixel.
- { 32, 32, 31, 32 }, { 32, 32, 32, 31 }, { 32, 32, 31, 31 },
- // Even-size, one or both dimensions downscaled by 2 pixels.
- { 32, 32, 30, 32 }, { 32, 32, 32, 30 }, { 32, 32, 30, 30 },
- // Even-size, one or both dimensions downscaled by 3 pixels.
- { 32, 32, 29, 32 }, { 32, 32, 32, 29 }, { 32, 32, 29, 29 },
-
- // Odd-size, one or both dimensions upscaled.
- { 33, 33, 66, 33 }, { 33, 33, 33, 66 }, { 33, 33, 66, 66 },
- // Odd-size, one or both dimensions downscaled by 2X.
- { 33, 33, 16, 33 }, { 33, 33, 33, 16 }, { 33, 33, 16, 16 },
- // Odd-size, one or both dimensions downscaled by 1 pixel.
- { 33, 33, 32, 33 }, { 33, 33, 33, 32 }, { 33, 33, 32, 32 },
- // Odd-size, one or both dimensions downscaled by 2 pixels.
- { 33, 33, 31, 33 }, { 33, 33, 33, 31 }, { 33, 33, 31, 31 },
- // Odd-size, one or both dimensions downscaled by 3 pixels.
- { 33, 33, 30, 33 }, { 33, 33, 33, 30 }, { 33, 33, 30, 30 },
-};
-
-} // namespace
-
-TEST_F(CompositingIOSurfaceTransformerTest, ResizesTexturesCorrectly) {
- for (size_t i = 0; i < arraysize(kTestParameters); ++i) {
- SCOPED_TRACE(::testing::Message() << "kTestParameters[" << i << ']');
-
- const TestParameters& params = kTestParameters[i];
- const gfx::Size src_size(params.src_width, params.src_height);
- const gfx::Size dst_size(params.scaled_width, params.scaled_height);
- const SkBitmap src_bitmap = GenerateTestPatternBitmap(src_size);
-
- // Full texture resize test.
- RunResizeTest(src_bitmap, gfx::Rect(src_size), dst_size);
- // Subrect resize test: missing top row in source.
- RunResizeTest(src_bitmap,
- gfx::Rect(0, 1, params.src_width, params.src_height - 1),
- dst_size);
- // Subrect resize test: missing left column in source.
- RunResizeTest(src_bitmap,
- gfx::Rect(1, 0, params.src_width - 1, params.src_height),
- dst_size);
- // Subrect resize test: missing top+bottom rows, and left column in source.
- RunResizeTest(src_bitmap,
- gfx::Rect(1, 1, params.src_width - 1, params.src_height - 2),
- dst_size);
- // Subrect resize test: missing top row, and left+right columns in source.
- RunResizeTest(src_bitmap,
- gfx::Rect(1, 1, params.src_width - 2, params.src_height - 1),
- dst_size);
- }
-}
-
-TEST_F(CompositingIOSurfaceTransformerTest, TransformsRGBToYV12) {
- static const GLenum kOutputFormats[] = { GL_BGRA, GL_RGBA };
-
- for (size_t i = 0; i < arraysize(kOutputFormats); ++i) {
- SCOPED_TRACE(::testing::Message() << "kOutputFormats[" << i << ']');
-
- shader_program_cache()->SetOutputFormatForTesting(kOutputFormats[i]);
-
- for (size_t j = 0; j < arraysize(kTestParameters); ++j) {
- SCOPED_TRACE(::testing::Message() << "kTestParameters[" << j << ']');
-
- const TestParameters& params = kTestParameters[j];
- const gfx::Size src_size(params.src_width, params.src_height);
- const gfx::Size dst_size(params.scaled_width, params.scaled_height);
- const SkBitmap src_bitmap = GenerateTestPatternBitmap(src_size);
-
- // Full texture resize test.
- RunTransformRGBToYV12Test(src_bitmap, gfx::Rect(src_size), dst_size);
- // Subrect resize test: missing top row in source.
- RunTransformRGBToYV12Test(
- src_bitmap, gfx::Rect(0, 1, params.src_width, params.src_height - 1),
- dst_size);
- // Subrect resize test: missing left column in source.
- RunTransformRGBToYV12Test(
- src_bitmap, gfx::Rect(1, 0, params.src_width - 1, params.src_height),
- dst_size);
- // Subrect resize test: missing top+bottom rows, and left column in
- // source.
- RunTransformRGBToYV12Test(
- src_bitmap,
- gfx::Rect(1, 1, params.src_width - 1, params.src_height - 2),
- dst_size);
- // Subrect resize test: missing top row, and left+right columns in source.
- RunTransformRGBToYV12Test(
- src_bitmap,
- gfx::Rect(1, 1, params.src_width - 2, params.src_height - 1),
- dst_size);
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 47f037d17f4..5d8ecc8138c 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -10,10 +10,12 @@
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/bind.h"
+#include "base/cancelable_callback.h"
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
@@ -24,10 +26,13 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/context_provider.h"
#include "cc/output/output_surface.h"
+#include "cc/output/output_surface_client.h"
#include "cc/trees/layer_tree_host.h"
#include "content/browser/android/child_process_launcher_android.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gl_helper.h"
@@ -36,6 +41,7 @@
#include "content/common/gpu/gpu_process_launch_causes.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/public/browser/android/compositor_client.h"
+#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -43,11 +49,11 @@
#include "ui/base/android/window_android.h"
#include "ui/gfx/android/device_display_info.h"
#include "ui/gfx/frame_time.h"
-#include "ui/gl/android/surface_texture.h"
-#include "ui/gl/android/surface_texture_tracker.h"
#include "webkit/common/gpu/context_provider_in_process.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
+namespace content {
+
namespace {
const unsigned int kMaxSwapBuffers = 2U;
@@ -55,97 +61,75 @@ const unsigned int kMaxSwapBuffers = 2U;
// Used to override capabilities_.adjust_deadline_for_parent to false
class OutputSurfaceWithoutParent : public cc::OutputSurface {
public:
- OutputSurfaceWithoutParent(const scoped_refptr<
- content::ContextProviderCommandBuffer>& context_provider)
- : cc::OutputSurface(context_provider) {
+ OutputSurfaceWithoutParent(
+ const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
+ base::WeakPtr<CompositorImpl> compositor_impl)
+ : cc::OutputSurface(context_provider),
+ swap_buffers_completion_callback_(
+ base::Bind(&OutputSurfaceWithoutParent::OnSwapBuffersCompleted,
+ base::Unretained(this))) {
capabilities_.adjust_deadline_for_parent = false;
+ compositor_impl_ = compositor_impl;
+ main_thread_ = base::MessageLoopProxy::current();
}
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE {
- content::ContextProviderCommandBuffer* provider_command_buffer =
- static_cast<content::ContextProviderCommandBuffer*>(
- context_provider_.get());
- content::CommandBufferProxyImpl* command_buffer_proxy =
- provider_command_buffer->GetCommandBufferProxy();
- DCHECK(command_buffer_proxy);
- command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
+ virtual void SwapBuffers(cc::CompositorFrame* frame) override {
+ for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
+ frame->metadata.latency_info[i].AddLatencyNumber(
+ ui::INPUT_EVENT_BROWSER_SWAP_BUFFER_COMPONENT, 0, 0);
+ }
- OutputSurface::SwapBuffers(frame);
+ GetCommandBufferProxy()->SetLatencyInfo(frame->metadata.latency_info);
+ DCHECK(frame->gl_frame_data->sub_buffer_rect ==
+ gfx::Rect(frame->gl_frame_data->size));
+ context_provider_->ContextSupport()->Swap();
+ client_->DidSwapBuffers();
}
-};
-class SurfaceTextureTrackerImpl : public gfx::SurfaceTextureTracker {
- public:
- SurfaceTextureTrackerImpl() : next_surface_texture_id_(1) {
- thread_checker_.DetachFromThread();
- }
+ virtual bool BindToClient(cc::OutputSurfaceClient* client) override {
+ if (!OutputSurface::BindToClient(client))
+ return false;
+
+ GetCommandBufferProxy()->SetSwapBuffersCompletionCallback(
+ swap_buffers_completion_callback_.callback());
+
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&CompositorImpl::PopulateGpuCapabilities,
+ compositor_impl_,
+ context_provider_->ContextCapabilities().gpu));
- // Overridden from gfx::SurfaceTextureTracker:
- virtual scoped_refptr<gfx::SurfaceTexture> AcquireSurfaceTexture(
- int primary_id,
- int secondary_id) OVERRIDE {
- base::AutoLock lock(surface_textures_lock_);
- SurfaceTextureMapKey key(primary_id, secondary_id);
- SurfaceTextureMap::iterator it = surface_textures_.find(key);
- if (it == surface_textures_.end())
- return scoped_refptr<gfx::SurfaceTexture>();
- scoped_refptr<gfx::SurfaceTexture> surface_texture = it->second;
- surface_textures_.erase(it);
- return surface_texture;
+ return true;
}
- int AddSurfaceTexture(gfx::SurfaceTexture* surface_texture,
- int child_process_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- int surface_texture_id = next_surface_texture_id_++;
- if (next_surface_texture_id_ == INT_MAX)
- next_surface_texture_id_ = 1;
-
- base::AutoLock lock(surface_textures_lock_);
- SurfaceTextureMapKey key(surface_texture_id, child_process_id);
- DCHECK(surface_textures_.find(key) == surface_textures_.end());
- surface_textures_[key] = surface_texture;
- content::RegisterChildProcessSurfaceTexture(
- surface_texture_id,
- child_process_id,
- surface_texture->j_surface_texture().obj());
- return surface_texture_id;
+ private:
+ CommandBufferProxyImpl* GetCommandBufferProxy() {
+ ContextProviderCommandBuffer* provider_command_buffer =
+ static_cast<content::ContextProviderCommandBuffer*>(
+ context_provider_.get());
+ CommandBufferProxyImpl* command_buffer_proxy =
+ provider_command_buffer->GetCommandBufferProxy();
+ DCHECK(command_buffer_proxy);
+ return command_buffer_proxy;
}
- void RemoveAllSurfaceTextures(int child_process_id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::AutoLock lock(surface_textures_lock_);
- SurfaceTextureMap::iterator it = surface_textures_.begin();
- while (it != surface_textures_.end()) {
- if (it->first.second == child_process_id) {
- content::UnregisterChildProcessSurfaceTexture(it->first.first,
- it->first.second);
- surface_textures_.erase(it++);
- } else {
- ++it;
- }
- }
+ void OnSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ RenderWidgetHostImpl::CompositorFrameDrawn(latency_info);
+ OutputSurface::OnSwapBuffersComplete();
}
- private:
- typedef std::pair<int, int> SurfaceTextureMapKey;
- typedef base::hash_map<SurfaceTextureMapKey,
- scoped_refptr<gfx::SurfaceTexture> >
- SurfaceTextureMap;
- SurfaceTextureMap surface_textures_;
- mutable base::Lock surface_textures_lock_;
- int next_surface_texture_id_;
- base::ThreadChecker thread_checker_;
+ base::CancelableCallback<void(const std::vector<ui::LatencyInfo>&)>
+ swap_buffers_completion_callback_;
+
+ scoped_refptr<base::MessageLoopProxy> main_thread_;
+ base::WeakPtr<CompositorImpl> compositor_impl_;
};
-base::LazyInstance<SurfaceTextureTrackerImpl> g_surface_texture_tracker =
- LAZY_INSTANCE_INITIALIZER;
static bool g_initialized = false;
} // anonymous namespace
-namespace content {
-
// static
Compositor* Compositor::Create(CompositorClient* client,
gfx::NativeWindow root_window) {
@@ -155,9 +139,6 @@ Compositor* Compositor::Create(CompositorClient* client,
// static
void Compositor::Initialize() {
DCHECK(!CompositorImpl::IsInitialized());
- // SurfaceTextureTracker instance must be set before we create a GPU thread
- // that could be using it to initialize GLImage instances.
- gfx::SurfaceTextureTracker::InitInstance(g_surface_texture_tracker.Pointer());
g_initialized = true;
}
@@ -166,25 +147,6 @@ bool CompositorImpl::IsInitialized() {
return g_initialized;
}
-// static
-int CompositorImpl::CreateSurfaceTexture(int child_process_id) {
- // Note: this needs to be 0 as the surface texture implemenation will take
- // ownership of the texture and call glDeleteTextures when the GPU service
- // attaches the surface texture to a real texture id. glDeleteTextures
- // silently ignores 0.
- const int kDummyTextureId = 0;
- scoped_refptr<gfx::SurfaceTexture> surface_texture =
- gfx::SurfaceTexture::Create(kDummyTextureId);
- return g_surface_texture_tracker.Pointer()->AddSurfaceTexture(
- surface_texture.get(), child_process_id);
-}
-
-// static
-void CompositorImpl::DestroyAllSurfaceTextures(int child_process_id) {
- g_surface_texture_tracker.Pointer()->RemoveAllSurfaceTextures(
- child_process_id);
-}
-
CompositorImpl::CompositorImpl(CompositorClient* client,
gfx::NativeWindow root_window)
: root_layer_(cc::Layer::Create()),
@@ -281,10 +243,9 @@ void CompositorImpl::Composite(CompositingTrigger trigger) {
if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
CauseForGpuLaunch cause =
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
- factory->EstablishGpuChannel(
- cause,
- base::Bind(&CompositorImpl::OnGpuChannelEstablished,
- weak_factory_.GetWeakPtr()));
+ factory->EstablishGpuChannel(cause,
+ base::Bind(&CompositorImpl::ScheduleComposite,
+ weak_factory_.GetWeakPtr()));
return;
}
@@ -314,7 +275,6 @@ void CompositorImpl::Composite(CompositingTrigger trigger) {
// animation updates that will already be reflected in the current frame
// we are about to draw.
ignore_schedule_composite_ = true;
- client_->Layout();
const base::TimeTicks frame_time = gfx::FrameTime::Now();
if (needs_animate_) {
@@ -332,20 +292,20 @@ void CompositorImpl::Composite(CompositingTrigger trigger) {
root_window_->RequestVSyncUpdate();
}
-void CompositorImpl::OnGpuChannelEstablished() {
- ScheduleComposite();
-}
-
UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
return ui_resource_provider_;
}
+ui::SystemUIResourceManager& CompositorImpl::GetSystemUIResourceManager() {
+ return ui_resource_provider_.GetSystemUIResourceManager();
+}
+
void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) {
- if (subroot_layer_) {
+ if (subroot_layer_.get()) {
subroot_layer_->RemoveFromParent();
subroot_layer_ = NULL;
}
- if (root_layer) {
+ if (root_layer.get()) {
subroot_layer_ = root_layer;
root_layer_->AddChild(root_layer);
}
@@ -379,7 +339,7 @@ void CompositorImpl::SetSurface(jobject surface) {
// First, cleanup any existing surface references.
if (surface_id_)
- content::UnregisterViewSurface(surface_id_);
+ UnregisterViewSurface(surface_id_);
SetWindowSurface(NULL);
// Now, set the new surface if we have one.
@@ -394,12 +354,27 @@ void CompositorImpl::SetSurface(jobject surface) {
if (window) {
SetWindowSurface(window);
ANativeWindow_release(window);
- content::RegisterViewSurface(surface_id_, j_surface.obj());
+ RegisterViewSurface(surface_id_, j_surface.obj());
}
}
void CompositorImpl::SetVisible(bool visible) {
if (!visible) {
+ DCHECK(host_);
+ // Look for any layers that were attached to the root for readback
+ // and are waiting for Composite() to happen.
+ bool readback_pending = false;
+ for (size_t i = 0; i < root_layer_->children().size(); ++i) {
+ if (root_layer_->children()[i]->HasCopyRequest()) {
+ readback_pending = true;
+ break;
+ }
+ }
+ if (readback_pending) {
+ ignore_schedule_composite_ = true;
+ host_->Composite(base::TimeTicks::Now());
+ ignore_schedule_composite_ = false;
+ }
if (WillComposite())
CancelComposite();
ui_resource_provider_.SetLayerTreeHost(NULL);
@@ -407,7 +382,6 @@ void CompositorImpl::SetVisible(bool visible) {
} else if (!host_) {
DCHECK(!WillComposite());
needs_composite_ = false;
- needs_animate_ = false;
pending_swapbuffers_ = 0;
cc::LayerTreeSettings settings;
settings.refresh_rate = 60.0;
@@ -417,14 +391,21 @@ void CompositorImpl::SetVisible(bool visible) {
settings.top_controls_height = 0.f;
settings.highp_threshold_min = 2048;
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
settings.initial_debug_state.SetRecordRenderingStats(
command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
settings.initial_debug_state.show_fps_counter =
command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
+ // TODO(enne): Update this this compositor to use the scheduler.
+ settings.single_thread_proxy_scheduler = false;
host_ = cc::LayerTreeHost::CreateSingleThreaded(
- this, this, HostSharedBitmapManager::current(), settings);
+ this,
+ this,
+ HostSharedBitmapManager::current(),
+ BrowserGpuMemoryBufferManager::current(),
+ settings,
+ base::MessageLoopProxy::current());
host_->SetRootLayer(root_layer_);
host_->SetVisible(true);
@@ -472,7 +453,7 @@ CreateGpuProcessViewContext(
const scoped_refptr<GpuChannelHost>& gpu_channel_host,
const blink::WebGraphicsContext3D::Attributes attributes,
int surface_id) {
- DCHECK(gpu_channel_host);
+ DCHECK(gpu_channel_host.get());
GURL url("chrome://gpu/Compositor::createContext3D");
static const size_t kBytesPerPixel = 4;
@@ -500,14 +481,29 @@ CreateGpuProcessViewContext(
}
void CompositorImpl::Layout() {
- // TODO: If we get this callback from the SingleThreadProxy, we need
- // to stop calling it ourselves in CompositorImpl::Composite().
- NOTREACHED();
+ ignore_schedule_composite_ = true;
client_->Layout();
+ ignore_schedule_composite_ = false;
}
-scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
- bool fallback) {
+void CompositorImpl::RequestNewOutputSurface(bool fallback) {
+ BrowserGpuChannelHostFactory* factory =
+ BrowserGpuChannelHostFactory::instance();
+ if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) {
+ CauseForGpuLaunch cause =
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+ factory->EstablishGpuChannel(
+ cause,
+ base::Bind(&CompositorImpl::CreateOutputSurface,
+ weak_factory_.GetWeakPtr(),
+ fallback));
+ return;
+ }
+
+ CreateOutputSurface(fallback);
+}
+
+void CompositorImpl::CreateOutputSurface(bool fallback) {
blink::WebGraphicsContext3D::Attributes attrs;
attrs.shareResources = true;
attrs.noAutomaticFlushes = true;
@@ -520,23 +516,30 @@ scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface(
BrowserGpuChannelHostFactory* factory =
BrowserGpuChannelHostFactory::instance();
scoped_refptr<GpuChannelHost> gpu_channel_host = factory->GetGpuChannel();
- if (gpu_channel_host && !gpu_channel_host->IsLost()) {
+ if (gpu_channel_host.get() && !gpu_channel_host->IsLost()) {
context_provider = ContextProviderCommandBuffer::Create(
CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_),
"BrowserCompositor");
}
if (!context_provider.get()) {
LOG(ERROR) << "Failed to create 3D context for compositor.";
- return scoped_ptr<cc::OutputSurface>();
+ host_->SetOutputSurface(scoped_ptr<cc::OutputSurface>());
+ return;
}
- return scoped_ptr<cc::OutputSurface>(
- new OutputSurfaceWithoutParent(context_provider));
+ host_->SetOutputSurface(
+ scoped_ptr<cc::OutputSurface>(new OutputSurfaceWithoutParent(
+ context_provider, weak_factory_.GetWeakPtr())));
+}
+
+void CompositorImpl::PopulateGpuCapabilities(
+ gpu::Capabilities gpu_capabilities) {
+ ui_resource_provider_.SetSupportsETC1NonPowerOfTwo(
+ gpu_capabilities.texture_format_etc1_npot);
}
void CompositorImpl::OnLostResources() {
client_->DidLoseResources();
- ui_resource_provider_.UIResourcesAreInvalid();
}
void CompositorImpl::ScheduleComposite() {
@@ -552,7 +555,6 @@ void CompositorImpl::ScheduleComposite() {
}
void CompositorImpl::ScheduleAnimation() {
- DCHECK(!needs_animate_ || needs_composite_);
DCHECK(!needs_composite_ || WillComposite());
needs_animate_ = true;
@@ -582,6 +584,7 @@ void CompositorImpl::DidAbortSwapBuffers() {
// This really gets called only once from
// SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the
// context was lost.
+ ScheduleComposite();
client_->OnSwapBuffersCompleted(0);
}
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 4792d9058c7..402271b1084 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -8,17 +8,18 @@
#include "base/basictypes.h"
#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "cc/resources/ui_resource_client.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "content/browser/android/ui_resource_provider_impl.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/browser/android/compositor.h"
+#include "gpu/command_buffer/common/capabilities.h"
#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/base/android/system_ui_resource_manager.h"
#include "ui/base/android/window_android_compositor.h"
class SkBitmap;
@@ -48,56 +49,59 @@ class CONTENT_EXPORT CompositorImpl
static bool IsInitialized();
- // Creates a surface texture and returns a surface texture id. Returns -1 on
- // failure.
- static int CreateSurfaceTexture(int child_process_id);
-
- // Destroy all surface textures associated with |child_process_id|.
- static void DestroyAllSurfaceTextures(int child_process_id);
+ void PopulateGpuCapabilities(gpu::Capabilities gpu_capabilities);
private:
// Compositor implementation.
- virtual void SetRootLayer(scoped_refptr<cc::Layer> root) OVERRIDE;
- virtual void SetWindowSurface(ANativeWindow* window) OVERRIDE;
- virtual void SetSurface(jobject surface) OVERRIDE;
- virtual void SetVisible(bool visible) OVERRIDE;
- virtual void setDeviceScaleFactor(float factor) OVERRIDE;
- virtual void SetWindowBounds(const gfx::Size& size) OVERRIDE;
- virtual void SetHasTransparentBackground(bool flag) OVERRIDE;
- virtual void SetNeedsComposite() OVERRIDE;
- virtual UIResourceProvider& GetUIResourceProvider() OVERRIDE;
+ virtual void SetRootLayer(scoped_refptr<cc::Layer> root) override;
+ virtual void SetSurface(jobject surface) override;
+ virtual void SetVisible(bool visible) override;
+ virtual void setDeviceScaleFactor(float factor) override;
+ virtual void SetWindowBounds(const gfx::Size& size) override;
+ virtual void SetHasTransparentBackground(bool flag) override;
+ virtual void SetNeedsComposite() override;
+ virtual UIResourceProvider& GetUIResourceProvider() override;
// LayerTreeHostClient implementation.
- virtual void WillBeginMainFrame(int frame_id) OVERRIDE {}
- virtual void DidBeginMainFrame() OVERRIDE {}
- virtual void Animate(base::TimeTicks frame_begin_time) OVERRIDE {}
- virtual void Layout() OVERRIDE;
- virtual void ApplyScrollAndScale(const gfx::Vector2d& scroll_delta,
- float page_scale) OVERRIDE {}
- virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback)
- OVERRIDE;
- virtual void DidInitializeOutputSurface() OVERRIDE {}
- virtual void WillCommit() OVERRIDE {}
- virtual void DidCommit() OVERRIDE;
- virtual void DidCommitAndDrawFrame() OVERRIDE {}
- virtual void DidCompleteSwapBuffers() OVERRIDE;
+ virtual void WillBeginMainFrame(int frame_id) override {}
+ virtual void DidBeginMainFrame() override {}
+ virtual void BeginMainFrame(const cc::BeginFrameArgs& args) override {}
+ virtual void Layout() override;
+ virtual void ApplyViewportDeltas(
+ const gfx::Vector2d& inner_delta,
+ const gfx::Vector2d& outer_delta,
+ float page_scale,
+ float top_controls_delta) override {}
+ virtual void ApplyViewportDeltas(
+ const gfx::Vector2d& scroll_delta,
+ float page_scale,
+ float top_controls_delta) override {}
+ virtual void RequestNewOutputSurface(bool fallback) override;
+ virtual void DidInitializeOutputSurface() override {}
+ virtual void WillCommit() override {}
+ virtual void DidCommit() override;
+ virtual void DidCommitAndDrawFrame() override {}
+ virtual void DidCompleteSwapBuffers() override;
// LayerTreeHostSingleThreadClient implementation.
- virtual void ScheduleComposite() OVERRIDE;
- virtual void ScheduleAnimation() OVERRIDE;
- virtual void DidPostSwapBuffers() OVERRIDE;
- virtual void DidAbortSwapBuffers() OVERRIDE;
+ virtual void ScheduleComposite() override;
+ virtual void ScheduleAnimation() override;
+ virtual void DidPostSwapBuffers() override;
+ virtual void DidAbortSwapBuffers() override;
// ImageTransportFactoryAndroidObserver implementation.
- virtual void OnLostResources() OVERRIDE;
+ virtual void OnLostResources() override;
// WindowAndroidCompositor implementation.
- virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) OVERRIDE;
+ virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) override;
virtual void RequestCopyOfOutputOnRootLayer(
- scoped_ptr<cc::CopyOutputRequest> request) OVERRIDE;
+ scoped_ptr<cc::CopyOutputRequest> request) override;
virtual void OnVSync(base::TimeTicks frame_time,
- base::TimeDelta vsync_period) OVERRIDE;
- virtual void SetNeedsAnimate() OVERRIDE;
+ base::TimeDelta vsync_period) override;
+ virtual void SetNeedsAnimate() override;
+ virtual ui::SystemUIResourceManager& GetSystemUIResourceManager() override;
+
+ void SetWindowSurface(ANativeWindow* window);
enum CompositingTrigger {
DO_NOT_COMPOSITE,
@@ -106,6 +110,7 @@ class CONTENT_EXPORT CompositorImpl
};
void PostComposite(CompositingTrigger trigger);
void Composite(CompositingTrigger trigger);
+ void CreateOutputSurface(bool fallback);
bool WillCompositeThisFrame() const {
return current_composite_task_ &&
@@ -127,9 +132,6 @@ class CONTENT_EXPORT CompositorImpl
composite_on_vsync_trigger_ = DO_NOT_COMPOSITE;
will_composite_immediately_ = false;
}
- cc::UIResourceId GenerateUIResourceFromUIResourceBitmap(
- const cc::UIResourceBitmap& bitmap,
- bool is_transient);
void OnGpuChannelEstablished();
// root_layer_ is the persistent internal root layer, while subroot_layer_
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock_aura.cc b/chromium/content/browser/renderer_host/compositor_resize_lock_aura.cc
index 419b7b326b8..9d5b7d87274 100644
--- a/chromium/content/browser/renderer_host/compositor_resize_lock_aura.cc
+++ b/chromium/content/browser/renderer_host/compositor_resize_lock_aura.cc
@@ -19,8 +19,8 @@ CompositorResizeLock::CompositorResizeLock(
const base::TimeDelta& timeout)
: ResizeLock(new_size, defer_compositor_lock),
host_(host),
- weak_ptr_factory_(this),
- cancelled_(false) {
+ cancelled_(false),
+ weak_ptr_factory_(this) {
DCHECK(host_);
TRACE_EVENT_ASYNC_BEGIN2("ui", "CompositorResizeLock", this,
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h b/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h
index 1c2be391053..ad706904812 100644
--- a/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h
+++ b/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h
@@ -26,21 +26,22 @@ class CompositorResizeLock : public ResizeLock {
const gfx::Size new_size,
bool defer_compositor_lock,
const base::TimeDelta& timeout);
- virtual ~CompositorResizeLock();
+ ~CompositorResizeLock() override;
- virtual bool GrabDeferredLock() OVERRIDE;
- virtual void UnlockCompositor() OVERRIDE;
+ bool GrabDeferredLock() override;
+ void UnlockCompositor() override;
protected:
- virtual void LockCompositor() OVERRIDE;
+ void LockCompositor() override;
void CancelLock();
private:
aura::WindowTreeHost* host_;
scoped_refptr<ui::CompositorLock> compositor_lock_;
- base::WeakPtrFactory<CompositorResizeLock> weak_ptr_factory_;
bool cancelled_;
+ base::WeakPtrFactory<CompositorResizeLock> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CompositorResizeLock);
};
diff --git a/chromium/content/browser/renderer_host/database_message_filter.cc b/chromium/content/browser/renderer_host/database_message_filter.cc
index 7c7b9a36b1b..bb5bdd6946e 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.cc
+++ b/chromium/content/browser/renderer_host/database_message_filter.cc
@@ -13,22 +13,22 @@
#include "content/common/database_messages.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/result_codes.h"
+#include "storage/browser/database/database_util.h"
+#include "storage/browser/database/vfs_backend.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/database/database_identifier.h"
#include "third_party/sqlite/sqlite3.h"
-#include "webkit/browser/database/database_util.h"
-#include "webkit/browser/database/vfs_backend.h"
-#include "webkit/browser/quota/quota_manager.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/common/database/database_identifier.h"
#if defined(OS_POSIX)
#include "base/file_descriptor_posix.h"
#endif
-using quota::QuotaManager;
-using quota::QuotaStatusCode;
-using webkit_database::DatabaseTracker;
-using webkit_database::DatabaseUtil;
-using webkit_database::VfsBackend;
+using storage::QuotaManager;
+using storage::QuotaStatusCode;
+using storage::DatabaseTracker;
+using storage::DatabaseUtil;
+using storage::VfsBackend;
namespace content {
namespace {
@@ -39,7 +39,7 @@ const int kDelayDeleteRetryMs = 100;
} // namespace
DatabaseMessageFilter::DatabaseMessageFilter(
- webkit_database::DatabaseTracker* db_tracker)
+ storage::DatabaseTracker* db_tracker)
: BrowserMessageFilter(DatabaseMsgStart),
db_tracker_(db_tracker),
observer_added_(false) {
@@ -270,19 +270,19 @@ void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
}
quota_manager->GetUsageAndQuota(
- webkit_database::GetOriginFromIdentifier(origin_identifier),
- quota::kStorageTypeTemporary,
- base::Bind(&DatabaseMessageFilter::OnDatabaseGetUsageAndQuota,
- this, reply_msg));
+ storage::GetOriginFromIdentifier(origin_identifier),
+ storage::kStorageTypeTemporary,
+ base::Bind(
+ &DatabaseMessageFilter::OnDatabaseGetUsageAndQuota, this, reply_msg));
}
void DatabaseMessageFilter::OnDatabaseGetUsageAndQuota(
IPC::Message* reply_msg,
- quota::QuotaStatusCode status,
+ storage::QuotaStatusCode status,
int64 usage,
int64 quota) {
int64 available = 0;
- if ((status == quota::kQuotaStatusOk) && (usage < quota))
+ if ((status == storage::kQuotaStatusOk) && (usage < quota))
available = quota - usage;
DatabaseHostMsg_GetSpaceAvailable::WriteReplyParams(reply_msg, available);
Send(reply_msg);
diff --git a/chromium/content/browser/renderer_host/database_message_filter.h b/chromium/content/browser/renderer_host/database_message_filter.h
index aa99e03c4e0..dcac74ab2bc 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.h
+++ b/chromium/content/browser/renderer_host/database_message_filter.h
@@ -8,31 +8,29 @@
#include "base/containers/hash_tables.h"
#include "base/strings/string16.h"
#include "content/public/browser/browser_message_filter.h"
-#include "webkit/browser/database/database_tracker.h"
-#include "webkit/common/database/database_connections.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/browser/database/database_tracker.h"
+#include "storage/common/database/database_connections.h"
+#include "storage/common/quota/quota_types.h"
namespace content {
-class DatabaseMessageFilter
- : public BrowserMessageFilter,
- public webkit_database::DatabaseTracker::Observer {
+class DatabaseMessageFilter : public BrowserMessageFilter,
+ public storage::DatabaseTracker::Observer {
public:
- explicit DatabaseMessageFilter(webkit_database::DatabaseTracker* db_tracker);
+ explicit DatabaseMessageFilter(storage::DatabaseTracker* db_tracker);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
- webkit_database::DatabaseTracker* database_tracker() const {
+ storage::DatabaseTracker* database_tracker() const {
return db_tracker_.get();
}
private:
- virtual ~DatabaseMessageFilter();
+ ~DatabaseMessageFilter() override;
class PromptDelegate;
@@ -55,7 +53,7 @@ class DatabaseMessageFilter
void OnDatabaseGetSpaceAvailable(const std::string& origin_identifier,
IPC::Message* reply_msg);
void OnDatabaseGetUsageAndQuota(IPC::Message* reply_msg,
- quota::QuotaStatusCode status,
+ storage::QuotaStatusCode status,
int64 usage,
int64 quota);
@@ -73,12 +71,12 @@ class DatabaseMessageFilter
int error);
// DatabaseTracker::Observer callbacks (file thread)
- virtual void OnDatabaseSizeChanged(const std::string& origin_identifier,
- const base::string16& database_name,
- int64 database_size) OVERRIDE;
- virtual void OnDatabaseScheduledForDeletion(
+ void OnDatabaseSizeChanged(const std::string& origin_identifier,
+ const base::string16& database_name,
+ int64 database_size) override;
+ void OnDatabaseScheduledForDeletion(
const std::string& origin_identifier,
- const base::string16& database_name) OVERRIDE;
+ const base::string16& database_name) override;
void DatabaseDeleteFile(const base::string16& vfs_file_name,
bool sync_dir,
@@ -86,14 +84,14 @@ class DatabaseMessageFilter
int reschedule_count);
// The database tracker for the current browser context.
- scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
+ scoped_refptr<storage::DatabaseTracker> db_tracker_;
// True if and only if this instance was added as an observer
// to DatabaseTracker.
bool observer_added_;
// Keeps track of all DB connections opened by this renderer
- webkit_database::DatabaseConnections database_connections_;
+ storage::DatabaseConnections database_connections_;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/delegated_frame_evictor.h b/chromium/content/browser/renderer_host/delegated_frame_evictor.h
index 64df6f7bc8c..796b6c255f0 100644
--- a/chromium/content/browser/renderer_host/delegated_frame_evictor.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_evictor.h
@@ -20,7 +20,7 @@ class CONTENT_EXPORT DelegatedFrameEvictor : public RendererFrameManagerClient {
public:
// |client| must outlive |this|.
explicit DelegatedFrameEvictor(DelegatedFrameEvictorClient* client);
- virtual ~DelegatedFrameEvictor();
+ ~DelegatedFrameEvictor() override;
void SwappedFrame(bool visible);
void DiscardedFrame();
@@ -31,7 +31,7 @@ class CONTENT_EXPORT DelegatedFrameEvictor : public RendererFrameManagerClient {
private:
// RendererFrameManagerClient implementation.
- virtual void EvictCurrentFrame() OVERRIDE;
+ void EvictCurrentFrame() override;
DelegatedFrameEvictorClient* client_;
bool has_frame_;
diff --git a/chromium/content/browser/renderer_host/file_utilities_message_filter.cc b/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
index d819c6dcc9c..f0a1e4ab6ae 100644
--- a/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
+++ b/chromium/content/browser/renderer_host/file_utilities_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/renderer_host/file_utilities_message_filter.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/common/file_utilities_messages.h"
diff --git a/chromium/content/browser/renderer_host/file_utilities_message_filter.h b/chromium/content/browser/renderer_host/file_utilities_message_filter.h
index ecfbfe02ce9..54a5830a6d4 100644
--- a/chromium/content/browser/renderer_host/file_utilities_message_filter.h
+++ b/chromium/content/browser/renderer_host/file_utilities_message_filter.h
@@ -21,12 +21,12 @@ class FileUtilitiesMessageFilter : public BrowserMessageFilter {
explicit FileUtilitiesMessageFilter(int process_id);
// BrowserMessageFilter implementation.
- virtual void OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
private:
- virtual ~FileUtilitiesMessageFilter();
+ ~FileUtilitiesMessageFilter() override;
typedef void (*FileInfoWriteFunc)(IPC::Message* reply_msg,
const base::File::Info& file_info);
diff --git a/chromium/content/browser/renderer_host/font_utils_linux.cc b/chromium/content/browser/renderer_host/font_utils_linux.cc
new file mode 100644
index 00000000000..2ee84e1f403
--- /dev/null
+++ b/chromium/content/browser/renderer_host/font_utils_linux.cc
@@ -0,0 +1,260 @@
+// Copyright 2014 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 <fcntl.h>
+#include <fontconfig/fontconfig.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <string>
+
+#include "base/posix/eintr_wrapper.h"
+#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
+#include "third_party/npapi/bindings/npapi_extensions.h"
+
+namespace {
+
+// MSCharSetToFontconfig translates a Microsoft charset identifier to a
+// fontconfig language set by appending to |langset|.
+// Returns true if |langset| is Latin/Greek/Cyrillic.
+bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
+ // We have need to translate raw fdwCharSet values into terms that
+ // fontconfig can understand. (See the description of fdwCharSet in the MSDN
+ // documentation for CreateFont:
+ // http://msdn.microsoft.com/en-us/library/dd183499(VS.85).aspx )
+ //
+ // Although the argument is /called/ 'charset', the actual values conflate
+ // character sets (which are sets of Unicode code points) and character
+ // encodings (which are algorithms for turning a series of bits into a
+ // series of code points.) Sometimes the values will name a language,
+ // sometimes they'll name an encoding. In the latter case I'm assuming that
+ // they mean the set of code points in the domain of that encoding.
+ //
+ // fontconfig deals with ISO 639-1 language codes:
+ // http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
+ //
+ // So, for each of the documented fdwCharSet values I've had to take a
+ // guess at the set of ISO 639-1 languages intended.
+
+ bool is_lgc = false;
+ switch (fdwCharSet) {
+ case NPCharsetAnsi:
+ // These values I don't really know what to do with, so I'm going to map
+ // them to English also.
+ case NPCharsetDefault:
+ case NPCharsetMac:
+ case NPCharsetOEM:
+ case NPCharsetSymbol:
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("en"));
+ break;
+ case NPCharsetBaltic:
+ // The three baltic languages.
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("et"));
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lv"));
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lt"));
+ break;
+ case NPCharsetChineseBIG5:
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-tw"));
+ break;
+ case NPCharsetGB2312:
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-cn"));
+ break;
+ case NPCharsetEastEurope:
+ // A scattering of eastern European languages.
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl"));
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("cs"));
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("sk"));
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hu"));
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr"));
+ break;
+ case NPCharsetGreek:
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el"));
+ break;
+ case NPCharsetHangul:
+ case NPCharsetJohab:
+ // Korean
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko"));
+ break;
+ case NPCharsetRussian:
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru"));
+ break;
+ case NPCharsetShiftJIS:
+ // Japanese
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ja"));
+ break;
+ case NPCharsetTurkish:
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr"));
+ break;
+ case NPCharsetVietnamese:
+ is_lgc = true;
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi"));
+ break;
+ case NPCharsetArabic:
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ar"));
+ break;
+ case NPCharsetHebrew:
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("he"));
+ break;
+ case NPCharsetThai:
+ FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("th"));
+ break;
+ // default:
+ // Don't add any languages in that case that we don't recognise the
+ // constant.
+ }
+ return is_lgc;
+}
+
+} // namespace
+
+namespace content {
+
+int MatchFontFaceWithFallback(const std::string& face,
+ bool is_bold,
+ bool is_italic,
+ uint32 charset,
+ uint32 fallback_family) {
+ FcLangSet* langset = FcLangSetCreate();
+ bool is_lgc = MSCharSetToFontconfig(langset, charset);
+ FcPattern* pattern = FcPatternCreate();
+ FcPatternAddString(
+ pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(face.c_str()));
+
+ // TODO(thestig) Check if we can access Chrome's per-script font preference
+ // here and select better default fonts for non-LGC case.
+ std::string generic_font_name;
+ if (is_lgc) {
+ switch (fallback_family) {
+ case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF:
+ generic_font_name = "Times New Roman";
+ break;
+ case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF:
+ generic_font_name = "Arial";
+ break;
+ case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE:
+ generic_font_name = "Courier New";
+ break;
+ }
+ }
+ if (!generic_font_name.empty()) {
+ const FcChar8* fc_generic_font_name =
+ reinterpret_cast<const FcChar8*>(generic_font_name.c_str());
+ FcPatternAddString(pattern, FC_FAMILY, fc_generic_font_name);
+ }
+
+ if (is_bold)
+ FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
+ if (is_italic)
+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
+ FcPatternAddLangSet(pattern, FC_LANG, langset);
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
+ FcConfigSubstitute(NULL, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
+ int font_fd = -1;
+ int good_enough_index = -1;
+ bool good_enough_index_set = false;
+
+ if (font_set) {
+ for (int i = 0; i < font_set->nfont; ++i) {
+ FcPattern* current = font_set->fonts[i];
+
+ // Older versions of fontconfig have a bug where they cannot select
+ // only scalable fonts so we have to manually filter the results.
+ FcBool is_scalable;
+ if (FcPatternGetBool(current, FC_SCALABLE, 0, &is_scalable) !=
+ FcResultMatch ||
+ !is_scalable) {
+ continue;
+ }
+
+ FcChar8* c_filename;
+ if (FcPatternGetString(current, FC_FILE, 0, &c_filename) !=
+ FcResultMatch) {
+ continue;
+ }
+
+ // We only want to return sfnt (TrueType) based fonts. We don't have a
+ // very good way of detecting this so we'll filter based on the
+ // filename.
+ bool is_sfnt = false;
+ static const char kSFNTExtensions[][5] = {".ttf", ".otc", ".TTF", ".ttc",
+ ""};
+ const size_t filename_len = strlen(reinterpret_cast<char*>(c_filename));
+ for (unsigned j = 0;; j++) {
+ if (kSFNTExtensions[j][0] == 0) {
+ // None of the extensions matched.
+ break;
+ }
+ const size_t ext_len = strlen(kSFNTExtensions[j]);
+ if (filename_len > ext_len &&
+ memcmp(c_filename + filename_len - ext_len,
+ kSFNTExtensions[j],
+ ext_len) == 0) {
+ is_sfnt = true;
+ break;
+ }
+ }
+
+ if (!is_sfnt)
+ continue;
+
+ // This font is good enough to pass muster, but we might be able to do
+ // better with subsequent ones.
+ if (!good_enough_index_set) {
+ good_enough_index = i;
+ good_enough_index_set = true;
+ }
+
+ FcValue matrix;
+ bool have_matrix = FcPatternGet(current, FC_MATRIX, 0, &matrix) == 0;
+
+ if (is_italic && have_matrix) {
+ // we asked for an italic font, but fontconfig is giving us a
+ // non-italic font with a transformation matrix.
+ continue;
+ }
+
+ FcValue embolden;
+ const bool have_embolden =
+ FcPatternGet(current, FC_EMBOLDEN, 0, &embolden) == 0;
+
+ if (is_bold && have_embolden) {
+ // we asked for a bold font, but fontconfig gave us a non-bold font
+ // and asked us to apply fake bolding.
+ continue;
+ }
+
+ font_fd =
+ HANDLE_EINTR(open(reinterpret_cast<char*>(c_filename), O_RDONLY));
+ if (font_fd >= 0)
+ break;
+ }
+ }
+
+ if (font_fd == -1 && good_enough_index_set) {
+ // We didn't find a font that we liked, so we fallback to something
+ // acceptable.
+ FcPattern* current = font_set->fonts[good_enough_index];
+ FcChar8* c_filename;
+ FcPatternGetString(current, FC_FILE, 0, &c_filename);
+ font_fd = HANDLE_EINTR(open(reinterpret_cast<char*>(c_filename), O_RDONLY));
+ }
+
+ if (font_set)
+ FcFontSetDestroy(font_set);
+ FcPatternDestroy(pattern);
+
+ return font_fd;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/font_utils_linux.h b/chromium/content/browser/renderer_host/font_utils_linux.h
new file mode 100644
index 00000000000..669f816984c
--- /dev/null
+++ b/chromium/content/browser/renderer_host/font_utils_linux.h
@@ -0,0 +1,20 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
+#define CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
+
+#include <string>
+
+namespace content {
+
+int MatchFontFaceWithFallback(const std::string& face,
+ bool is_bold,
+ bool is_italic,
+ uint32 charset,
+ uint32 fallback_family);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_FONT_UTILS_LINUX_H_
diff --git a/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h b/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
index fefbf424e4d..e5dc8aefd7b 100644
--- a/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
+++ b/chromium/content/browser/renderer_host/gamepad_browser_message_filter.h
@@ -22,18 +22,16 @@ class GamepadBrowserMessageFilter :
GamepadBrowserMessageFilter();
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// GamepadConsumer implementation.
- virtual void OnGamepadConnected(
- unsigned index,
- const blink::WebGamepad& gamepad) OVERRIDE;
- virtual void OnGamepadDisconnected(
- unsigned index,
- const blink::WebGamepad& gamepad) OVERRIDE;
+ void OnGamepadConnected(unsigned index,
+ const blink::WebGamepad& gamepad) override;
+ void OnGamepadDisconnected(unsigned index,
+ const blink::WebGamepad& gamepad) override;
private:
- virtual ~GamepadBrowserMessageFilter();
+ ~GamepadBrowserMessageFilter() override;
void OnGamepadStartPolling(base::SharedMemoryHandle* renderer_handle);
void OnGamepadStopPolling();
diff --git a/chromium/content/browser/renderer_host/gpu_message_filter.cc b/chromium/content/browser/renderer_host/gpu_message_filter.cc
index 1cbfaf08174..d16310679e7 100644
--- a/chromium/content/browser/renderer_host/gpu_message_filter.cc
+++ b/chromium/content/browser/renderer_host/gpu_message_filter.cc
@@ -134,6 +134,7 @@ void GpuMessageFilter::OnEstablishGpuChannel(
host->EstablishGpuChannel(
render_process_id_,
share_contexts,
+ false,
base::Bind(&GpuMessageFilter::EstablishChannelCallback,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(&reply)));
diff --git a/chromium/content/browser/renderer_host/gpu_message_filter.h b/chromium/content/browser/renderer_host/gpu_message_filter.h
index 559415e70fe..57dfe9b45c3 100644
--- a/chromium/content/browser/renderer_host/gpu_message_filter.h
+++ b/chromium/content/browser/renderer_host/gpu_message_filter.h
@@ -37,7 +37,7 @@ class GpuMessageFilter : public BrowserMessageFilter {
RenderWidgetHelper* render_widget_helper);
// BrowserMessageFilter methods:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// This set of API is used to subscribe to frame presentation events.
// See RenderWidgetHostViewFrameSubscriber for more details.
@@ -52,7 +52,7 @@ class GpuMessageFilter : public BrowserMessageFilter {
struct CreateViewCommandBufferRequest;
struct FrameSubscription;
- virtual ~GpuMessageFilter();
+ ~GpuMessageFilter() override;
// Message handlers called on the browser IO thread:
void OnEstablishGpuChannel(CauseForGpuLaunch,
@@ -81,11 +81,11 @@ class GpuMessageFilter : public BrowserMessageFilter {
scoped_refptr<RenderWidgetHelper> render_widget_helper_;
- base::WeakPtrFactory<GpuMessageFilter> weak_ptr_factory_;
-
typedef std::vector<linked_ptr<FrameSubscription> > FrameSubscriptionList;
FrameSubscriptionList frame_subscription_list_;
+ base::WeakPtrFactory<GpuMessageFilter> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GpuMessageFilter);
};
diff --git a/chromium/content/browser/renderer_host/image_transport_factory_android.cc b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
index cf3ff8b1b7c..41e315608e0 100644
--- a/chromium/content/browser/renderer_host/image_transport_factory_android.cc
+++ b/chromium/content/browser/renderer_host/image_transport_factory_android.cc
@@ -24,7 +24,7 @@ class GLContextLostListener
: public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
public:
// WebGraphicsContextLostCallback implementation.
- virtual void onContextLost() OVERRIDE;
+ virtual void onContextLost() override;
private:
static void DidLoseContext();
};
@@ -38,8 +38,8 @@ class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid {
CmdBufferImageTransportFactory();
virtual ~CmdBufferImageTransportFactory();
- virtual GLHelper* GetGLHelper() OVERRIDE;
- virtual uint32 GetChannelID() OVERRIDE {
+ virtual GLHelper* GetGLHelper() override;
+ virtual uint32 GetChannelID() override {
return BrowserGpuChannelHostFactory::instance()->GetGpuChannelId();
}
@@ -55,7 +55,7 @@ CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
BrowserGpuChannelHostFactory::instance();
scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
- DCHECK(gpu_channel_host);
+ DCHECK(gpu_channel_host.get());
blink::WebGraphicsContext3D::Attributes attrs;
attrs.shareResources = true;
@@ -83,7 +83,7 @@ CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() {
limits,
NULL));
context_->setContextLostCallback(context_lost_listener_.get());
- if (context_->makeContextCurrent())
+ if (context_->InitializeOnCurrentThread())
context_->pushGroupMarkerEXT(
base::StringPrintf("CmdBufferImageTransportFactory-%p",
context_.get()).c_str());
@@ -104,6 +104,20 @@ GLHelper* CmdBufferImageTransportFactory::GetGLHelper() {
} // anonymous namespace
// static
+void ImageTransportFactoryAndroid::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactoryAndroid> test_factory) {
+ DCHECK(!g_factory);
+ g_factory = test_factory.release();
+}
+
+// static
+void ImageTransportFactoryAndroid::TerminateForUnitTests() {
+ DCHECK(g_factory);
+ delete g_factory;
+ g_factory = NULL;
+}
+
+// static
ImageTransportFactoryAndroid* ImageTransportFactoryAndroid::GetInstance() {
if (!g_factory)
g_factory = new CmdBufferImageTransportFactory();
diff --git a/chromium/content/browser/renderer_host/image_transport_factory_android.h b/chromium/content/browser/renderer_host/image_transport_factory_android.h
index 3be7a678e69..25623811406 100644
--- a/chromium/content/browser/renderer_host/image_transport_factory_android.h
+++ b/chromium/content/browser/renderer_host/image_transport_factory_android.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_RENDERER_HOST_IMAGE_TRANSPORT_FACTORY_ANDROID_H_
#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
namespace gfx {
@@ -28,10 +29,16 @@ class ImageTransportFactoryAndroidObserver {
virtual void OnLostResources() = 0;
};
-class ImageTransportFactoryAndroid {
+class CONTENT_EXPORT ImageTransportFactoryAndroid {
public:
virtual ~ImageTransportFactoryAndroid();
+ // Initializes the global transport factory for unit tests.
+ static void InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactoryAndroid> test_factory);
+ // Terminates the global transport factory for unit tests.
+ static void TerminateForUnitTests();
+
static ImageTransportFactoryAndroid* GetInstance();
virtual GLHelper* GetGLHelper() = 0;
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.cc b/chromium/content/browser/renderer_host/ime_adapter_android.cc
index afbc43400f7..b7d3748002d 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.cc
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.cc
@@ -11,6 +11,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -21,6 +22,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/common/frame_messages.h"
+#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/native_web_keyboard_event.h"
@@ -28,6 +30,7 @@
#include "jni/ImeAdapter_jni.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebTextInputType.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
@@ -86,6 +89,14 @@ bool RegisterImeAdapter(JNIEnv* env) {
ui::TEXT_INPUT_TYPE_TELEPHONE,
ui::TEXT_INPUT_TYPE_NUMBER,
ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE);
+ Java_ImeAdapter_initializeTextInputFlags(
+ env,
+ blink::WebTextInputFlagAutocompleteOn,
+ blink::WebTextInputFlagAutocompleteOff,
+ blink::WebTextInputFlagAutocorrectOn,
+ blink::WebTextInputFlagAutocorrectOff,
+ blink::WebTextInputFlagSpellcheckOn,
+ blink::WebTextInputFlagSpellcheckOff);
return true;
}
@@ -147,9 +158,10 @@ bool ImeAdapterAndroid::SendSyntheticKeyEvent(JNIEnv*,
int type,
long time_ms,
int key_code,
+ int modifiers,
int text) {
NativeWebKeyboardEvent event(static_cast<blink::WebInputEvent::Type>(type),
- 0 /* modifiers */, time_ms / 1000.0, key_code,
+ modifiers, time_ms / 1000.0, key_code,
text, false /* is_system_key */);
rwhva_->SendKeyEvent(event);
return true;
@@ -256,6 +268,36 @@ void ImeAdapterAndroid::FocusedNodeChanged(bool is_editable_node) {
}
}
+void ImeAdapterAndroid::SetCharacterBounds(
+ const std::vector<gfx::Rect>& character_bounds) {
+ JNIEnv* env = AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
+ if (obj.is_null())
+ return;
+
+ const size_t coordinates_array_size = character_bounds.size() * 4;
+ base::android::ScopedJavaLocalRef<jfloatArray> coordinates_dest_array(
+ env, env->NewFloatArray(coordinates_array_size));
+ if (coordinates_dest_array.is_null())
+ return;
+
+ scoped_ptr<jfloat[]> coordinates_array(new jfloat[coordinates_array_size]);
+ for (size_t i = 0; i < character_bounds.size(); ++i) {
+ const gfx::Rect& rect = character_bounds[i];
+ const size_t coordinates_array_index = i * 4;
+ coordinates_array[coordinates_array_index + 0] = rect.x();
+ coordinates_array[coordinates_array_index + 1] = rect.y();
+ coordinates_array[coordinates_array_index + 2] = rect.right();
+ coordinates_array[coordinates_array_index + 3] = rect.bottom();
+ }
+ // TODO(yukawa): Consider to move this to base/android/jni_array.h
+ env->SetFloatArrayRegion(coordinates_dest_array.obj(), 0,
+ coordinates_array_size, coordinates_array.get());
+ base::android::CheckException(env);
+ Java_ImeAdapter_setCharacterBounds(env, obj.obj(),
+ coordinates_dest_array.obj());
+}
+
void ImeAdapterAndroid::SetEditableSelectionOffsets(JNIEnv*, jobject,
int start, int end) {
RenderFrameHost* rfh = GetFocusedFrame();
@@ -276,7 +318,7 @@ void ImeAdapterAndroid::SetComposingRegion(JNIEnv*, jobject,
underlines.push_back(blink::WebCompositionUnderline(
0, end - start, SK_ColorBLACK, false, SK_ColorTRANSPARENT));
- rfh->Send(new FrameMsg_SetCompositionFromExistingText(
+ rfh->Send(new InputMsg_SetCompositionFromExistingText(
rfh->GetRoutingID(), start, end, underlines));
}
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.h b/chromium/content/browser/renderer_host/ime_adapter_android.h
index a23696da37d..50e9dbfa89d 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.h
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.h
@@ -7,7 +7,10 @@
#include <jni.h>
+#include <vector>
+
#include "base/android/jni_weak_ref.h"
+#include "ui/gfx/geometry/rect.h"
namespace content {
@@ -41,6 +44,7 @@ class ImeAdapterAndroid {
int event_type,
long timestamp_ms,
int native_key_code,
+ int modifiers,
int unicode_char);
void SetComposingText(JNIEnv*,
jobject obj,
@@ -63,6 +67,7 @@ class ImeAdapterAndroid {
// Called from native -> java
void CancelComposition();
void FocusedNodeChanged(bool is_editable_node);
+ void SetCharacterBounds(const std::vector<gfx::Rect>& rects);
private:
RenderWidgetHostImpl* GetRenderWidgetHostImpl();
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
index 0c49a847578..c4b6d9600ab 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -31,22 +31,22 @@ class GestureEventQueueTest : public testing::Test,
: acked_gesture_event_count_(0),
sent_gesture_event_count_(0) {}
- virtual ~GestureEventQueueTest() {}
+ ~GestureEventQueueTest() override {}
// testing::Test
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
queue_.reset(new GestureEventQueue(this, this, DefaultConfig()));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// Process all pending tasks to avoid leaks.
RunUntilIdle();
queue_.reset();
}
// GestureEventQueueClient
- virtual void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& event) OVERRIDE {
+ void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& event) override {
++sent_gesture_event_count_;
if (sync_ack_result_) {
scoped_ptr<InputEventAckState> ack_result = sync_ack_result_.Pass();
@@ -54,19 +54,19 @@ class GestureEventQueueTest : public testing::Test,
}
}
- virtual void OnGestureEventAck(
- const GestureEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
++acked_gesture_event_count_;
last_acked_event_ = event.event;
- if (sync_followup_event_)
- SimulateGestureEvent(*sync_followup_event_.Pass());
+ if (sync_followup_event_) {
+ auto sync_followup_event = sync_followup_event_.Pass();
+ SimulateGestureEvent(*sync_followup_event);
+ }
}
// TouchpadTapSuppressionControllerClient
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& event) OVERRIDE {
- }
+ void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& event) override {}
protected:
static GestureEventQueue::Config DefaultConfig() {
diff --git a/chromium/content/browser/renderer_host/input/gesture_text_selector.cc b/chromium/content/browser/renderer_host/input/gesture_text_selector.cc
new file mode 100644
index 00000000000..67c4fe7ebb0
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/gesture_text_selector.cc
@@ -0,0 +1,115 @@
+// Copyright 2014 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 "content/browser/renderer_host/input/gesture_text_selector.h"
+
+#include "ui/events/event_constants.h"
+#include "ui/events/gesture_detection/gesture_detector.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
+#include "ui/events/gesture_detection/motion_event.h"
+
+using ui::GestureDetector;
+using ui::MotionEvent;
+
+namespace content {
+namespace {
+scoped_ptr<GestureDetector> CreateGestureDetector(
+ ui::GestureListener* listener) {
+ GestureDetector::Config config =
+ ui::DefaultGestureProviderConfig().gesture_detector_config;
+
+ ui::DoubleTapListener* null_double_tap_listener = nullptr;
+
+ // Doubletap, showpress and longpress detection are not required, and
+ // should be explicitly disabled for efficiency.
+ scoped_ptr<ui::GestureDetector> detector(
+ new ui::GestureDetector(config, listener, null_double_tap_listener));
+ detector->set_longpress_enabled(false);
+ detector->set_showpress_enabled(false);
+
+ return detector.Pass();
+}
+
+} // namespace
+
+GestureTextSelector::GestureTextSelector(GestureTextSelectorClient* client)
+ : client_(client),
+ text_selection_triggered_(false),
+ secondary_button_pressed_(false),
+ anchor_x_(0.0f),
+ anchor_y_(0.0f) {
+ DCHECK(client);
+}
+
+GestureTextSelector::~GestureTextSelector() {
+}
+
+bool GestureTextSelector::OnTouchEvent(const MotionEvent& event) {
+ if (event.GetAction() == MotionEvent::ACTION_DOWN) {
+ // Only trigger selection on ACTION_DOWN to prevent partial touch or gesture
+ // sequences from being forwarded.
+ text_selection_triggered_ = ShouldStartTextSelection(event);
+ secondary_button_pressed_ =
+ event.GetButtonState() == MotionEvent::BUTTON_SECONDARY;
+ anchor_x_ = event.GetX();
+ anchor_y_ = event.GetY();
+ }
+
+ if (!text_selection_triggered_)
+ return false;
+
+ if (event.GetAction() == MotionEvent::ACTION_MOVE) {
+ secondary_button_pressed_ =
+ event.GetButtonState() == MotionEvent::BUTTON_SECONDARY;
+ if (!secondary_button_pressed_) {
+ anchor_x_ = event.GetX();
+ anchor_y_ = event.GetY();
+ }
+ }
+
+ if (!gesture_detector_)
+ gesture_detector_ = CreateGestureDetector(this);
+
+ gesture_detector_->OnTouchEvent(event);
+
+ // Always return true, even if |gesture_detector_| technically doesn't
+ // consume the event, to prevent a partial touch stream from being forwarded.
+ return true;
+}
+
+bool GestureTextSelector::OnSingleTapUp(const MotionEvent& e) {
+ DCHECK(text_selection_triggered_);
+ client_->LongPress(e.GetEventTime(), e.GetX(), e.GetY());
+ return true;
+}
+
+bool GestureTextSelector::OnScroll(const MotionEvent& e1,
+ const MotionEvent& e2,
+ float distance_x,
+ float distance_y) {
+ DCHECK(text_selection_triggered_);
+
+ // Return if Stylus button is not pressed.
+ if (!secondary_button_pressed_)
+ return true;
+
+ // TODO(changwan): check if we can show handles after the scroll finishes
+ // instead. Currently it is not possible as ShowSelectionHandles should
+ // be called before we change the selection.
+ client_->ShowSelectionHandlesAutomatically();
+ client_->SelectRange(anchor_x_, anchor_y_, e2.GetX(), e2.GetY());
+ return true;
+}
+
+// static
+bool GestureTextSelector::ShouldStartTextSelection(const MotionEvent& event) {
+ DCHECK_GT(event.GetPointerCount(), 0u);
+ // Currently we are supporting stylus-only cases.
+ const bool is_stylus = event.GetToolType(0) == MotionEvent::TOOL_TYPE_STYLUS;
+ const bool is_only_secondary_button_pressed =
+ event.GetButtonState() == MotionEvent::BUTTON_SECONDARY;
+ return is_stylus && is_only_secondary_button_pressed;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/gesture_text_selector.h b/chromium/content/browser/renderer_host/input/gesture_text_selector.h
new file mode 100644
index 00000000000..e494045b731
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/gesture_text_selector.h
@@ -0,0 +1,72 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_TEXT_SELECTOR_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_TEXT_SELECTOR_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "ui/events/gesture_detection/gesture_listeners.h"
+
+namespace ui {
+class GestureDetector;
+class MotionEvent;
+}
+
+namespace content {
+class GestureTextSelectorTest;
+
+// Interface with which GestureTextSelector can select, unselect, show
+// selection handles, or long press.
+class CONTENT_EXPORT GestureTextSelectorClient {
+ public:
+ virtual ~GestureTextSelectorClient() {}
+
+ virtual void ShowSelectionHandlesAutomatically() = 0;
+ virtual void SelectRange(float x1, float y1, float x2, float y2) = 0;
+ virtual void LongPress(base::TimeTicks time, float x, float y) = 0;
+};
+
+// A class to handle gesture-based text selection, such as when clicking first
+// button on stylus input. It also generates a synthetic long press gesture on
+// tap so that a word can be selected or the contextual menu can be shown.
+class CONTENT_EXPORT GestureTextSelector : public ui::SimpleGestureListener {
+ public:
+ explicit GestureTextSelector(GestureTextSelectorClient* client);
+ ~GestureTextSelector() override;
+
+ // This should be called before |event| is seen by the platform gesture
+ // detector or forwarded to web content.
+ bool OnTouchEvent(const ui::MotionEvent& event);
+
+ private:
+ friend class GestureTextSelectorTest;
+ FRIEND_TEST_ALL_PREFIXES(GestureTextSelectorTest,
+ ShouldStartTextSelection);
+
+ // SimpleGestureListener implementation.
+ bool OnSingleTapUp(const ui::MotionEvent& e) override;
+ bool OnScroll(const ui::MotionEvent& e1,
+ const ui::MotionEvent& e2,
+ float distance_x,
+ float distance_y) override;
+
+ static bool ShouldStartTextSelection(const ui::MotionEvent& event);
+
+ GestureTextSelectorClient* client_;
+ bool text_selection_triggered_;
+ bool secondary_button_pressed_;
+ float anchor_x_;
+ float anchor_y_;
+ scoped_ptr<ui::GestureDetector> gesture_detector_;
+
+ DISALLOW_COPY_AND_ASSIGN(GestureTextSelector);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_GESTURE_TEXT_SELECTOR_H_
diff --git a/chromium/content/browser/renderer_host/input/gesture_text_selector_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_text_selector_unittest.cc
new file mode 100644
index 00000000000..dfa2af1ee54
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/gesture_text_selector_unittest.cc
@@ -0,0 +1,223 @@
+// Copyright 2014 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 <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "content/browser/renderer_host/input/gesture_text_selector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/gesture_detection/motion_event.h"
+#include "ui/events/test/motion_event_test_utils.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+using ui::MotionEvent;
+using ui::test::MockMotionEvent;
+
+namespace content {
+
+class GestureTextSelectorTest : public testing::Test,
+ public GestureTextSelectorClient {
+ public:
+ GestureTextSelectorTest() {}
+ ~GestureTextSelectorTest() override {}
+
+ // Test implementation.
+ void SetUp() override {
+ selector_.reset(new GestureTextSelector(this));
+ event_log_.clear();
+ }
+
+ void TearDown() override {
+ selector_.reset();
+ event_log_.clear();
+ }
+
+ // GestureTextSelectorClient implementation.
+ void ShowSelectionHandlesAutomatically() override {
+ event_log_.push_back("Show");
+ }
+
+ void SelectRange(float x1, float y1, float x2, float y2) override {
+ std::stringstream ss;
+ ss << "SelectRange(" << x1 << ", " << y1 << ", " << x2 << ", " << y2 << ")";
+ event_log_.push_back(ss.str());
+ }
+
+ void LongPress(base::TimeTicks time, float x, float y) override {
+ event_log_.push_back("LongPress");
+ }
+
+ protected:
+ scoped_ptr<GestureTextSelector> selector_;
+ std::vector<std::string> event_log_;
+};
+
+TEST_F(GestureTextSelectorTest, ShouldStartTextSelection) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ { // Touched with a finger.
+ MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f);
+ e.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER);
+ e.set_button_state(0);
+ EXPECT_FALSE(selector_->ShouldStartTextSelection(e));
+ }
+
+ { // Touched with a stylus, but no button pressed.
+ MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f);
+ e.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ e.set_button_state(0);
+ EXPECT_FALSE(selector_->ShouldStartTextSelection(e));
+ }
+
+ { // Touched with a stylus, with first button (BUTTON_SECONDARY) pressed.
+ MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f);
+ e.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ e.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->ShouldStartTextSelection(e));
+ }
+
+ { // Touched with a stylus, with two buttons pressed.
+ MockMotionEvent e(MotionEvent::ACTION_DOWN, event_time, 50.0f, 50.0f);
+ e.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ e.set_button_state(
+ MotionEvent::BUTTON_SECONDARY | MotionEvent::BUTTON_TERTIARY);
+ EXPECT_FALSE(selector_->ShouldStartTextSelection(e));
+ }
+}
+
+TEST_F(GestureTextSelectorTest, FingerTouch) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ const float x = 50.0f;
+ const float y = 30.0f;
+ // 1. Touched with a finger: ignored
+ MockMotionEvent finger(MotionEvent::ACTION_DOWN, event_time, x, y);
+ finger.SetToolType(0, MotionEvent::TOOL_TYPE_FINGER);
+ EXPECT_FALSE(selector_->OnTouchEvent(finger));
+ // We do not consume finger events.
+ EXPECT_TRUE(event_log_.empty());
+}
+
+TEST_F(GestureTextSelectorTest, PenDragging) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ const float x1 = 50.0f;
+ const float y1 = 30.0f;
+ const float x2 = 100.0f;
+ const float y2 = 90.0f;
+ // 1. ACTION_DOWN with stylus + button
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ MockMotionEvent action_down(MotionEvent::ACTION_DOWN, event_time, x1, y1);
+ action_down.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_down.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_down));
+ EXPECT_TRUE(event_log_.empty());
+
+ // 2. ACTION_MOVE
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ MockMotionEvent action_move(MotionEvent::ACTION_MOVE, event_time, x2, y2);
+ action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_move.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_move));
+ ASSERT_EQ(2u, event_log_.size());
+ EXPECT_STREQ("Show", event_log_[0].c_str());
+ EXPECT_STREQ("SelectRange(50, 30, 100, 90)", event_log_[1].c_str());
+
+ // 3. ACTION_UP
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ MockMotionEvent action_up(MotionEvent::ACTION_UP, event_time, x2, y2);
+ action_up.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_up.set_button_state(0);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_up));
+ ASSERT_EQ(2u, event_log_.size()); // NO CHANGE
+}
+
+TEST_F(GestureTextSelectorTest, PenDraggingButtonNotPressed) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ float x = 50.0f;
+ float y = 30.0f;
+
+ // 1. ACTION_DOWN with stylus + button
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ MockMotionEvent action_down(MotionEvent::ACTION_DOWN, event_time, x, y);
+ action_down.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_down.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_down));
+ EXPECT_TRUE(event_log_.empty());
+
+ // 2. ACTION_MOVE
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ x += 20; // 70
+ y += 20; // 50
+ MockMotionEvent action_move(MotionEvent::ACTION_MOVE, event_time, x, y);
+ action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_move.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_move));
+ ASSERT_EQ(2u, event_log_.size());
+ EXPECT_STREQ("Show", event_log_[0].c_str());
+ EXPECT_STREQ("SelectRange(50, 30, 70, 50)", event_log_[1].c_str());
+
+ // 3. ACTION_MOVE with stylus + no button
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ x += 20; // 90
+ y += 20; // 70
+ action_move = MockMotionEvent(MotionEvent::ACTION_MOVE, event_time, x, y);
+ action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_move.set_button_state(0);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_move));
+ EXPECT_EQ(2u, event_log_.size()); // NO CHANGE
+
+ // 4. ACTION_MOVE with stylus + button pressed again
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ x += 20; // 110
+ y += 20; // 90
+ action_move = MockMotionEvent(MotionEvent::ACTION_MOVE, event_time, x, y);
+ action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_move.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_move));
+ EXPECT_EQ(4u, event_log_.size());
+ EXPECT_STREQ("SelectRange(90, 70, 110, 90)", event_log_.back().c_str());
+
+ // 5. ACTION_UP
+ event_time += base::TimeDelta::FromMilliseconds(10);
+ MockMotionEvent action_up(MotionEvent::ACTION_UP, event_time, x, y);
+ action_up.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_up.set_button_state(0);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_up));
+ EXPECT_EQ(4u, event_log_.size()); // NO CHANGE
+}
+
+TEST_F(GestureTextSelectorTest, TapTriggersLongPressSelection) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ const float x1 = 50.0f;
+ const float y1 = 30.0f;
+ const float x2 = 51.0f;
+ const float y2 = 31.0f;
+ // 1. ACTION_DOWN with stylus + button
+ event_time += base::TimeDelta::FromMilliseconds(1);
+ MockMotionEvent action_down(MotionEvent::ACTION_DOWN, event_time, x1, y1);
+ action_down.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_down.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_down));
+ EXPECT_TRUE(event_log_.empty());
+
+ // 2. ACTION_MOVE
+ event_time += base::TimeDelta::FromMilliseconds(1);
+ MockMotionEvent action_move(MotionEvent::ACTION_MOVE, event_time, x2, y2);
+ action_move.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_move.set_button_state(MotionEvent::BUTTON_SECONDARY);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_move));
+ EXPECT_TRUE(event_log_.empty());
+
+ // 3. ACTION_UP
+ event_time += base::TimeDelta::FromMilliseconds(1);
+ MockMotionEvent action_up(MotionEvent::ACTION_UP, event_time, x2, y2);
+ action_up.SetToolType(0, MotionEvent::TOOL_TYPE_STYLUS);
+ action_up.set_button_state(0);
+ EXPECT_TRUE(selector_->OnTouchEvent(action_up));
+ ASSERT_EQ(1u, event_log_.size());
+ EXPECT_STREQ("LongPress", event_log_.back().c_str());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router.h b/chromium/content/browser/renderer_host/input/input_router.h
index 1b30815c7ce..96b68c322fe 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -22,7 +22,7 @@ class InputRouterClient;
// received, it is free to customize when those events are dispatched.
class InputRouter : public IPC::Listener {
public:
- virtual ~InputRouter() {}
+ ~InputRouter() override {}
// Should be called only in response to |SetNeedsFlush| requests made via
// the |InputRouterClient|.
diff --git a/chromium/content/browser/renderer_host/input/input_router_config_helper.cc b/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
index 31b17cfab70..d78b6cb2a90 100644
--- a/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_config_helper.cc
@@ -9,8 +9,7 @@
#include "ui/events/gesture_detection/gesture_detector.h"
#if defined(USE_AURA)
-#include "ui/events/gestures/gesture_configuration.h"
-#include "ui/events/gestures/unified_gesture_detector_enabled.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
#elif defined(OS_ANDROID)
#include "ui/gfx/android/view_configuration.h"
#include "ui/gfx/screen.h"
@@ -20,30 +19,32 @@ namespace content {
namespace {
#if defined(USE_AURA)
-
+// TODO(jdduke): Consolidate router configuration paths using
+// ui::GestureConfiguration.
GestureEventQueue::Config GetGestureEventQueueConfig() {
GestureEventQueue::Config config;
-
+ ui::GestureConfiguration* gesture_config =
+ ui::GestureConfiguration::GetInstance();
config.debounce_interval = base::TimeDelta::FromMilliseconds(
- ui::GestureConfiguration::scroll_debounce_interval_in_ms());
+ gesture_config->scroll_debounce_interval_in_ms());
config.touchscreen_tap_suppression_config.enabled = true;
config.touchscreen_tap_suppression_config.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(
- ui::GestureConfiguration::fling_max_cancel_to_down_time_in_ms());
+ gesture_config->fling_max_cancel_to_down_time_in_ms());
config.touchscreen_tap_suppression_config.max_tap_gap_time =
- base::TimeDelta::FromMilliseconds(static_cast<int>(
- ui::GestureConfiguration::semi_long_press_time_in_seconds() * 1000));
+ base::TimeDelta::FromMilliseconds(
+ gesture_config->semi_long_press_time_in_ms());
config.touchpad_tap_suppression_config.enabled = true;
config.touchpad_tap_suppression_config.max_cancel_to_down_time =
base::TimeDelta::FromMilliseconds(
- ui::GestureConfiguration::fling_max_cancel_to_down_time_in_ms());
+ gesture_config->fling_max_cancel_to_down_time_in_ms());
config.touchpad_tap_suppression_config.max_tap_gap_time =
- base::TimeDelta::FromMilliseconds(static_cast<int>(
- ui::GestureConfiguration::fling_max_tap_gap_time_in_ms() * 1000));
+ base::TimeDelta::FromMilliseconds(
+ gesture_config->fling_max_tap_gap_time_in_ms());
return config;
}
@@ -52,10 +53,8 @@ TouchEventQueue::Config GetTouchEventQueueConfig() {
TouchEventQueue::Config config;
config.touchmove_slop_suppression_length_dips =
- ui::GestureConfiguration::max_touch_move_in_pixels_for_click();
-
- config.touchmove_slop_suppression_region_includes_boundary =
- ui::IsUnifiedGestureDetectorEnabled();
+ ui::GestureConfiguration::GetInstance()
+ ->max_touch_move_in_pixels_for_click();
return config;
}
@@ -114,7 +113,7 @@ TouchEventQueue::Config GetTouchEventQueueConfig() {
TouchEventQueue::TouchScrollingMode GetTouchScrollingMode() {
std::string modeString =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kTouchScrollingMode);
if (modeString == switches::kTouchScrollingModeAsyncTouchmove)
return TouchEventQueue::TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
index a509465a653..4848f6dc6f4 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -68,7 +68,7 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
client_(client),
ack_handler_(ack_handler),
routing_id_(routing_id),
- select_range_pending_(false),
+ select_message_pending_(false),
move_caret_pending_(false),
mouse_move_pending_(false),
mouse_wheel_pending_(false),
@@ -83,7 +83,9 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
UpdateTouchAckTimeoutEnabled();
}
-InputRouterImpl::~InputRouterImpl() {}
+InputRouterImpl::~InputRouterImpl() {
+ STLDeleteElements(&pending_select_messages_);
+}
void InputRouterImpl::Flush() {
flush_requested_ = true;
@@ -95,7 +97,8 @@ bool InputRouterImpl::SendInput(scoped_ptr<IPC::Message> message) {
switch (message->type()) {
// Check for types that require an ACK.
case InputMsg_SelectRange::ID:
- return SendSelectRange(message.Pass());
+ case InputMsg_MoveRangeSelectionExtent::ID:
+ return SendSelectMessage(message.Pass());
case InputMsg_MoveCaret::ID:
return SendMoveCaret(message.Pass());
case InputMsg_HandleInputEvent::ID:
@@ -150,8 +153,8 @@ void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) {
mouse_wheel_pending_ = true;
current_wheel_event_ = wheel_event;
- HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
- coalesced_mouse_wheel_events_.size());
+ LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
+ coalesced_mouse_wheel_events_.size());
FilterAndSendWebInputEvent(
wheel_event.event.event, wheel_event.event.latency, false);
@@ -164,7 +167,7 @@ void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
// renderer and we need to give something to the HandleKeyboardEvent
// handler.
key_queue_.push_back(key_event);
- HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
+ LOCAL_HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
gesture_event_queue_.FlingHasBeenHalted();
@@ -267,8 +270,10 @@ bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(InputRouterImpl, message)
IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll)
- IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
+ IPC_MESSAGE_HANDLER(InputHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
+ IPC_MESSAGE_HANDLER(InputHostMsg_SelectRange_ACK, OnSelectMessageAck)
+ IPC_MESSAGE_HANDLER(InputHostMsg_MoveRangeSelectionExtent_ACK,
+ OnSelectMessageAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
OnHasTouchEventHandlers)
IPC_MESSAGE_HANDLER(InputHostMsg_SetTouchAction,
@@ -298,14 +303,25 @@ void InputRouterImpl::OnGestureEventAck(
ack_handler_->OnGestureEventAck(event, ack_result);
}
-bool InputRouterImpl::SendSelectRange(scoped_ptr<IPC::Message> message) {
- DCHECK(message->type() == InputMsg_SelectRange::ID);
- if (select_range_pending_) {
- next_selection_range_ = message.Pass();
+bool InputRouterImpl::SendSelectMessage(
+ scoped_ptr<IPC::Message> message) {
+ DCHECK(message->type() == InputMsg_SelectRange::ID ||
+ message->type() == InputMsg_MoveRangeSelectionExtent::ID);
+
+ // TODO(jdduke): Factor out common logic between selection and caret-related
+ // IPC messages.
+ if (select_message_pending_) {
+ if (!pending_select_messages_.empty() &&
+ pending_select_messages_.back()->type() == message->type()) {
+ delete pending_select_messages_.back();
+ pending_select_messages_.pop_back();
+ }
+
+ pending_select_messages_.push_back(message.release());
return true;
}
- select_range_pending_ = true;
+ select_message_pending_ = true;
return Send(message.release());
}
@@ -353,8 +369,8 @@ void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
// cancelable (respect ACK disposition) or not.
bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event);
if (WebInputEvent::isTouchEventType(input_event.type)) {
- DCHECK(!ignores_ack ==
- static_cast<const blink::WebTouchEvent&>(input_event).cancelable);
+ DCHECK_NE(static_cast<int>(ignores_ack),
+ static_cast<const blink::WebTouchEvent&>(input_event).cancelable);
}
// If we don't care about the ack disposition, send the ack immediately.
@@ -487,10 +503,15 @@ void InputRouterImpl::OnMsgMoveCaretAck() {
SendMoveCaret(next_move_caret_.Pass());
}
-void InputRouterImpl::OnSelectRangeAck() {
- select_range_pending_ = false;
- if (next_selection_range_)
- SendSelectRange(next_selection_range_.Pass());
+void InputRouterImpl::OnSelectMessageAck() {
+ select_message_pending_ = false;
+ if (!pending_select_messages_.empty()) {
+ scoped_ptr<IPC::Message> next_message =
+ make_scoped_ptr(pending_select_messages_.front());
+ pending_select_messages_.pop_front();
+
+ SendSelectMessage(next_message.Pass());
+ }
}
void InputRouterImpl::OnHasTouchEventHandlers(bool has_handlers) {
@@ -679,7 +700,7 @@ bool InputRouterImpl::HasPendingEvents() const {
!key_queue_.empty() ||
mouse_move_pending_ ||
mouse_wheel_pending_ ||
- select_range_pending_ ||
+ select_message_pending_ ||
move_caret_pending_;
}
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
index e06113b3e58..2b00c12996f 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -33,7 +33,6 @@ namespace content {
class InputAckHandler;
class InputRouterClient;
class OverscrollController;
-class RenderWidgetHostImpl;
struct DidOverscrollParams;
// A default implementation for browser input event routing.
@@ -54,52 +53,49 @@ class CONTENT_EXPORT InputRouterImpl
InputAckHandler* ack_handler,
int routing_id,
const Config& config);
- virtual ~InputRouterImpl();
+ ~InputRouterImpl() override;
// InputRouter
- virtual void Flush() OVERRIDE;
- virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE;
- virtual void SendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
- virtual void SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE;
- virtual void SendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool is_keyboard_shortcut) OVERRIDE;
- virtual void SendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual void SendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE;
- virtual bool ShouldForwardTouchEvent() const OVERRIDE;
- virtual void OnViewUpdated(int view_flags) OVERRIDE;
- virtual bool HasPendingEvents() const OVERRIDE;
+ void Flush() override;
+ bool SendInput(scoped_ptr<IPC::Message> message) override;
+ void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override;
+ void SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) override;
+ void SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_keyboard_shortcut) override;
+ void SendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) override;
+ void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override;
+ const NativeWebKeyboardEvent* GetLastKeyboardEvent() const override;
+ bool ShouldForwardTouchEvent() const override;
+ void OnViewUpdated(int view_flags) override;
+ bool HasPendingEvents() const override;
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
friend class InputRouterImplTest;
// TouchpadTapSuppressionControllerClient
- virtual void SendMouseEventImmediately(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE;
+ void SendMouseEventImmediately(
+ const MouseEventWithLatencyInfo& mouse_event) override;
// TouchEventQueueClient
- virtual void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE;
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
+ void SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& touch_event) override;
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
// GetureEventFilterClient
- virtual void SendGestureEventImmediately(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE;
- virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
+ void SendGestureEventImmediately(
+ const GestureEventWithLatencyInfo& gesture_event) override;
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
bool SendMoveCaret(scoped_ptr<IPC::Message> message);
- bool SendSelectRange(scoped_ptr<IPC::Message> message);
+ bool SendSelectMessage(scoped_ptr<IPC::Message> message);
bool Send(IPC::Message* message);
// Filters and forwards |input_event| to the appropriate handler.
@@ -152,7 +148,7 @@ private:
void OnInputEventAck(const InputHostMsg_HandleInputEvent_ACK_Params& ack);
void OnDidOverscroll(const DidOverscrollParams& params);
void OnMsgMoveCaretAck();
- void OnSelectRangeAck();
+ void OnSelectMessageAck();
void OnHasTouchEventHandlers(bool has_handlers);
void OnSetTouchAction(TouchAction touch_action);
@@ -216,11 +212,13 @@ private:
InputAckHandler* ack_handler_;
int routing_id_;
- // (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK.
- bool select_range_pending_;
+ // (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK
+ // or MoveRangeSelectionExtent_ACK.
+ bool select_message_pending_;
- // (Similar to |next_mouse_move_|.) The next SelectRange to send, if any.
- scoped_ptr<IPC::Message> next_selection_range_;
+ // Queue of pending select messages to send after receving the next select
+ // message ack.
+ std::deque<IPC::Message*> pending_select_messages_;
// (Similar to |mouse_move_pending_|.) True while waiting for MoveCaret_ACK.
bool move_caret_pending_;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
index 0a8c89fd176..ad832642acf 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
@@ -28,26 +28,26 @@ namespace {
class NullInputAckHandler : public InputAckHandler {
public:
NullInputAckHandler() : ack_count_(0) {}
- virtual ~NullInputAckHandler() {}
+ ~NullInputAckHandler() override {}
// InputAckHandler
- virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) override {
++ack_count_;
}
- virtual void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
++ack_count_;
}
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
++ack_count_;
}
- virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
++ack_count_;
}
- virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE {
+ void OnUnexpectedEventAck(UnexpectedEventAckType type) override {
++ack_count_;
}
@@ -66,28 +66,28 @@ class NullInputAckHandler : public InputAckHandler {
class NullInputRouterClient : public InputRouterClient {
public:
NullInputRouterClient() {}
- virtual ~NullInputRouterClient() {}
+ ~NullInputRouterClient() override {}
// InputRouterClient
- virtual InputEventAckState FilterInputEvent(
+ InputEventAckState FilterInputEvent(
const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) OVERRIDE {
+ const ui::LatencyInfo& latency_info) override {
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
- virtual void IncrementInFlightEventCount() OVERRIDE {}
- virtual void DecrementInFlightEventCount() OVERRIDE {}
- virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE {}
- virtual void DidFlush() OVERRIDE {}
- virtual void SetNeedsFlush() OVERRIDE {}
- virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE {}
+ void IncrementInFlightEventCount() override {}
+ void DecrementInFlightEventCount() override {}
+ void OnHasTouchEventHandlers(bool has_handlers) override {}
+ void DidFlush() override {}
+ void SetNeedsFlush() override {}
+ void DidOverscroll(const DidOverscrollParams& params) override {}
};
class NullIPCSender : public IPC::Sender {
public:
NullIPCSender() : sent_count_(0) {}
- virtual ~NullIPCSender() {}
+ ~NullIPCSender() override {}
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
delete message;
++sent_count_;
return true;
@@ -197,11 +197,11 @@ class InputEventTimer {
class InputRouterImplPerfTest : public testing::Test {
public:
InputRouterImplPerfTest() : last_input_id_(0) {}
- virtual ~InputRouterImplPerfTest() {}
+ ~InputRouterImplPerfTest() override {}
protected:
// testing::Test
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
sender_.reset(new NullIPCSender());
client_.reset(new NullInputRouterClient());
ack_handler_.reset(new NullInputAckHandler());
@@ -212,7 +212,7 @@ class InputRouterImplPerfTest : public testing::Test {
InputRouterImpl::Config()));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
base::MessageLoop::current()->RunUntilIdle();
input_router_.reset();
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 1fa1a7d305a..ed922c9d8ac 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -142,16 +142,16 @@ float PinchScaleToWheelDelta(float scale) {
class InputRouterImplTest : public testing::Test {
public:
InputRouterImplTest() {}
- virtual ~InputRouterImplTest() {}
+ ~InputRouterImplTest() override {}
protected:
// testing::Test
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
browser_context_.reset(new TestBrowserContext());
process_.reset(new MockRenderProcessHost(browser_context_.get()));
client_.reset(new MockInputRouterClient());
ack_handler_.reset(new MockInputAckHandler());
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(switches::kValidateInputEventStream);
input_router_.reset(new InputRouterImpl(process_.get(),
client_.get(),
@@ -162,7 +162,7 @@ class InputRouterImplTest : public testing::Test {
ack_handler_->set_input_router(input_router());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// Process all pending tasks to avoid leaks.
base::MessageLoop::current()->RunUntilIdle();
@@ -284,7 +284,7 @@ class InputRouterImplTest : public testing::Test {
}
bool TouchEventTimeoutEnabled() const {
- return input_router()->touch_event_queue_.ack_timeout_enabled();
+ return input_router()->touch_event_queue_.IsAckTimeoutEnabled();
}
void Flush() const {
@@ -354,7 +354,7 @@ TEST_F(InputRouterImplTest, CoalescesRangeSelection) {
// Now ack the first message.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
input_router_->OnMessageReceived(*response);
}
@@ -367,7 +367,197 @@ TEST_F(InputRouterImplTest, CoalescesRangeSelection) {
// Acking the coalesced msg should not send any more msg.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_SelectRange_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest, CoalescesMoveRangeSelectionExtent) {
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(1, 2))));
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Send two more messages without acking.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(3, 4))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Now ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the two messages are coalesced into one message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(5, 6));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Acking the coalesced msg should not send any more msg.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest, InterleaveSelectRangeAndMoveRangeSelectionExtent) {
+ // Send first message: SelectRange.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2),
+ gfx::Point(3, 4));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Send second message: MoveRangeSelectionExtent.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Send third message: SelectRange.
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(7, 8), gfx::Point(9, 10))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Ack the messages and verify that they're not coalesced and that they're in
+ // correct order.
+
+ // Ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(5, 6));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the second message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(7, 8),
+ gfx::Point(9, 10));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the third message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+}
+
+TEST_F(InputRouterImplTest,
+ CoalescesInterleavedSelectRangeAndMoveRangeSelectionExtent) {
+ // Send interleaved SelectRange and MoveRangeSelectionExtent messages. They
+ // should be coalesced as shown by the arrows.
+ // > SelectRange
+ // MoveRangeSelectionExtent
+ // MoveRangeSelectionExtent
+ // > MoveRangeSelectionExtent
+ // SelectRange
+ // > SelectRange
+ // > MoveRangeSelectionExtent
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(1, 2), gfx::Point(3, 4))));
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(1, 2),
+ gfx::Point(3, 4));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(5, 6))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(7, 8))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(9, 10))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(11, 12), gfx::Point(13, 14))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_SelectRange(0, gfx::Point(15, 16), gfx::Point(17, 18))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ input_router_->SendInput(scoped_ptr<IPC::Message>(
+ new InputMsg_MoveRangeSelectionExtent(0, gfx::Point(19, 20))));
+ EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
+
+ // Ack the first message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the three MoveRangeSelectionExtent messages are coalesced into
+ // one message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(9, 10));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the second message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify that the two SelectRange messages are coalesced into one message.
+ ExpectIPCMessageWithArg2<InputMsg_SelectRange>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(15, 16),
+ gfx::Point(17, 18));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the third message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_SelectRange_ACK(0));
+ input_router_->OnMessageReceived(*response);
+ }
+
+ // Verify the fourth message.
+ ExpectIPCMessageWithArg1<InputMsg_MoveRangeSelectionExtent>(
+ process_->sink().GetMessageAt(0),
+ gfx::Point(19, 20));
+ EXPECT_EQ(1u, GetSentMessageCountAndResetSink());
+
+ // Ack the fourth message.
+ {
+ scoped_ptr<IPC::Message> response(
+ new InputHostMsg_MoveRangeSelectionExtent_ACK(0));
input_router_->OnMessageReceived(*response);
}
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
@@ -391,7 +581,7 @@ TEST_F(InputRouterImplTest, CoalescesCaretMove) {
// Now ack the first message.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_MoveCaret_ACK(0));
input_router_->OnMessageReceived(*response);
}
@@ -402,7 +592,7 @@ TEST_F(InputRouterImplTest, CoalescesCaretMove) {
// Acking the coalesced msg should not send any more msg.
{
- scoped_ptr<IPC::Message> response(new ViewHostMsg_MoveCaret_ACK(0));
+ scoped_ptr<IPC::Message> response(new InputHostMsg_MoveCaret_ACK(0));
input_router_->OnMessageReceived(*response);
}
EXPECT_EQ(0u, GetSentMessageCountAndResetSink());
@@ -619,8 +809,8 @@ TEST_F(InputRouterImplTest, TouchEventQueue) {
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
}
-// Tests that the touch-queue is emptied if a page stops listening for touch
-// events.
+// Tests that the touch-queue is emptied after a page stops listening for touch
+// events and the outstanding ack is received.
TEST_F(InputRouterImplTest, TouchEventQueueFlush) {
OnHasTouchEventHandlers(true);
EXPECT_TRUE(client_->has_touch_handler());
@@ -632,15 +822,23 @@ TEST_F(InputRouterImplTest, TouchEventQueueFlush) {
// Send a touch-press event.
PressTouchPoint(1, 1);
SendTouchEvent();
+ MoveTouchPoint(0, 2, 2);
+ MoveTouchPoint(0, 3, 3);
EXPECT_FALSE(TouchEventQueueEmpty());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- // The page stops listening for touch-events. The touch-event queue should now
- // be emptied, but none of the queued touch-events should be sent to the
- // renderer.
+ // The page stops listening for touch-events. Note that flushing is deferred
+ // until the outstanding ack is received.
OnHasTouchEventHandlers(false);
EXPECT_FALSE(client_->has_touch_handler());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_FALSE(TouchEventQueueEmpty());
+ EXPECT_TRUE(input_router_->ShouldForwardTouchEvent());
+
+ // After the ack, the touch-event queue should be empty, and none of the
+ // flushed touch-events should have been sent to the renderer.
+ SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
EXPECT_TRUE(TouchEventQueueEmpty());
EXPECT_FALSE(input_router_->ShouldForwardTouchEvent());
}
@@ -1097,53 +1295,40 @@ TEST_F(InputRouterImplTest,
// Start a touch sequence.
PressTouchPoint(1, 1);
SendTouchEvent();
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// TOUCH_ACTION_NONE should disable the timeout.
OnSetTouchAction(TOUCH_ACTION_NONE);
SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_FALSE(TouchEventTimeoutEnabled());
- // End the touch sequence.
- ReleaseTouchPoint(0);
+ MoveTouchPoint(0, 1, 1);
SendTouchEvent();
- SendInputEventACK(WebInputEvent::TouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_FALSE(TouchEventTimeoutEnabled());
- ack_handler_->GetAndResetAckCount();
- GetSentMessageCountAndResetSink();
-
- // Start another touch sequence. While this does restore the touch timeout
- // the timeout will not apply until the *next* touch sequence. This affords a
- // touch-action response from the renderer without racing against the timeout.
- PressTouchPoint(1, 1);
- SendTouchEvent();
- EXPECT_TRUE(TouchEventTimeoutEnabled());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
- // Delay the ack. The timeout should *not* fire.
+ // Delay the move ack. The timeout should not fire.
RunTasksAndWait(base::TimeDelta::FromMilliseconds(timeout_ms + 1));
EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
-
- // Finally send the ack. The touch sequence should not have been cancelled.
- SendInputEventACK(WebInputEvent::TouchStart,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(TouchEventTimeoutEnabled());
+ SendInputEventACK(WebInputEvent::TouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
- EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- // End the sequence.
+ // End the touch sequence.
ReleaseTouchPoint(0);
SendTouchEvent();
SendInputEventACK(WebInputEvent::TouchEnd, INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
- EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_FALSE(TouchEventTimeoutEnabled());
+ ack_handler_->GetAndResetAckCount();
+ GetSentMessageCountAndResetSink();
- // A new touch sequence should (finally) be subject to the timeout.
+ // Start another touch sequence. This should restore the touch timeout.
PressTouchPoint(1, 1);
SendTouchEvent();
EXPECT_TRUE(TouchEventTimeoutEnabled());
- EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
// Wait for the touch ack timeout to fire.
RunTasksAndWait(base::TimeDelta::FromMilliseconds(timeout_ms + 1));
diff --git a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
index 875964a8080..93f7ccadf4f 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_ack_handler.h
@@ -15,18 +15,18 @@ class InputRouter;
class MockInputAckHandler : public InputAckHandler {
public:
MockInputAckHandler();
- virtual ~MockInputAckHandler();
+ ~MockInputAckHandler() override;
// InputAckHandler
- virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
+ void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) override;
+ void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnUnexpectedEventAck(UnexpectedEventAckType type) override;
size_t GetAndResetAckCount();
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
index f0b31676ffd..a552ac0debf 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -17,18 +17,18 @@ class InputRouter;
class MockInputRouterClient : public InputRouterClient {
public:
MockInputRouterClient();
- virtual ~MockInputRouterClient();
+ ~MockInputRouterClient() override;
// InputRouterClient
- virtual InputEventAckState FilterInputEvent(
+ InputEventAckState FilterInputEvent(
const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) OVERRIDE;
- virtual void IncrementInFlightEventCount() OVERRIDE;
- virtual void DecrementInFlightEventCount() OVERRIDE;
- virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
- virtual void SetNeedsFlush() OVERRIDE;
- virtual void DidFlush() OVERRIDE;
- virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
+ const ui::LatencyInfo& latency_info) override;
+ void IncrementInFlightEventCount() override;
+ void DecrementInFlightEventCount() override;
+ void OnHasTouchEventHandlers(bool has_handlers) override;
+ void SetNeedsFlush() override;
+ void DidFlush() override;
+ void DidOverscroll(const DidOverscrollParams& params) override;
bool GetAndResetFilterEventCalled();
size_t GetAndResetDidFlushCount();
diff --git a/chromium/content/browser/renderer_host/input/motion_event_android.cc b/chromium/content/browser/renderer_host/input/motion_event_android.cc
index 7409955bc9c..fa21047d71b 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_android.cc
+++ b/chromium/content/browser/renderer_host/input/motion_event_android.cc
@@ -4,8 +4,12 @@
#include "content/browser/renderer_host/input/motion_event_android.h"
+#include <android/input.h>
+
#include "base/android/jni_android.h"
+#include "base/float_util.h"
#include "jni/MotionEvent_jni.h"
+#include "ui/events/event_constants.h"
using base::android::AttachCurrentThread;
using namespace JNI_MotionEvent;
@@ -13,26 +17,6 @@ using namespace JNI_MotionEvent;
namespace content {
namespace {
-int ToAndroidAction(MotionEventAndroid::Action action) {
- switch (action) {
- case MotionEventAndroid::ACTION_DOWN:
- return ACTION_DOWN;
- case MotionEventAndroid::ACTION_UP:
- return ACTION_UP;
- case MotionEventAndroid::ACTION_MOVE:
- return ACTION_MOVE;
- case MotionEventAndroid::ACTION_CANCEL:
- return ACTION_CANCEL;
- case MotionEventAndroid::ACTION_POINTER_DOWN:
- return ACTION_POINTER_DOWN;
- case MotionEventAndroid::ACTION_POINTER_UP:
- return ACTION_POINTER_UP;
- };
- NOTREACHED() << "Invalid Android MotionEvent type for gesture detection: "
- << action;
- return ACTION_CANCEL;
-}
-
MotionEventAndroid::Action FromAndroidAction(int android_action) {
switch (android_action) {
case ACTION_DOWN:
@@ -54,16 +38,98 @@ MotionEventAndroid::Action FromAndroidAction(int android_action) {
return MotionEventAndroid::ACTION_CANCEL;
}
-int64 ToAndroidTime(base::TimeTicks time) {
- return (time - base::TimeTicks()).InMilliseconds();
+MotionEventAndroid::ToolType FromAndroidToolType(int android_tool_type) {
+ switch (android_tool_type) {
+ case TOOL_TYPE_UNKNOWN:
+ return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
+ case TOOL_TYPE_FINGER:
+ return MotionEventAndroid::TOOL_TYPE_FINGER;
+ case TOOL_TYPE_STYLUS:
+ return MotionEventAndroid::TOOL_TYPE_STYLUS;
+ case TOOL_TYPE_MOUSE:
+ return MotionEventAndroid::TOOL_TYPE_MOUSE;
+ case TOOL_TYPE_ERASER:
+ return MotionEventAndroid::TOOL_TYPE_ERASER;
+ default:
+ NOTREACHED() << "Invalid Android MotionEvent tool type: "
+ << android_tool_type;
+ };
+ return MotionEventAndroid::TOOL_TYPE_UNKNOWN;
+}
+
+int FromAndroidButtonState(int button_state) {
+ int result = 0;
+ if ((button_state & BUTTON_BACK) != 0)
+ result |= MotionEventAndroid::BUTTON_BACK;
+ if ((button_state & BUTTON_FORWARD) != 0)
+ result |= MotionEventAndroid::BUTTON_FORWARD;
+ if ((button_state & BUTTON_PRIMARY) != 0)
+ result |= MotionEventAndroid::BUTTON_PRIMARY;
+ if ((button_state & BUTTON_SECONDARY) != 0)
+ result |= MotionEventAndroid::BUTTON_SECONDARY;
+ if ((button_state & BUTTON_TERTIARY) != 0)
+ result |= MotionEventAndroid::BUTTON_TERTIARY;
+ return result;
+}
+
+int FromAndroidMetaState(int meta_state) {
+ int flags = ui::EF_NONE;
+ if ((meta_state & AMETA_SHIFT_ON) != 0)
+ flags |= ui::EF_SHIFT_DOWN;
+ if ((meta_state & AMETA_CTRL_ON) != 0)
+ flags |= ui::EF_CONTROL_DOWN;
+ if ((meta_state & AMETA_ALT_ON) != 0)
+ flags |= ui::EF_ALT_DOWN;
+ if ((meta_state & AMETA_META_ON) != 0)
+ flags |= ui::EF_COMMAND_DOWN;
+ if ((meta_state & AMETA_CAPS_LOCK_ON) != 0)
+ flags |= ui::EF_CAPS_LOCK_DOWN;
+ return flags;
}
base::TimeTicks FromAndroidTime(int64 time_ms) {
return base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms);
}
+float ToValidFloat(float x) {
+ if (base::IsNaN(x))
+ return 0.f;
+
+ // Wildly large orientation values have been observed in the wild after device
+ // rotation. There's not much we can do in that case other than simply
+ // sanitize results beyond an absurd and arbitrary threshold.
+ if (std::abs(x) > 1e5f)
+ return 0.f;
+
+ return x;
+}
+
} // namespace
+MotionEventAndroid::Pointer::Pointer(jint id,
+ jfloat pos_x_pixels,
+ jfloat pos_y_pixels,
+ jfloat touch_major_pixels,
+ jfloat touch_minor_pixels,
+ jfloat orientation_rad,
+ jint tool_type)
+ : id(id),
+ pos_x_pixels(pos_x_pixels),
+ pos_y_pixels(pos_y_pixels),
+ touch_major_pixels(touch_major_pixels),
+ touch_minor_pixels(touch_minor_pixels),
+ orientation_rad(orientation_rad),
+ tool_type(tool_type) {
+}
+
+MotionEventAndroid::CachedPointer::CachedPointer()
+ : id(0),
+ touch_major(0),
+ touch_minor(0),
+ orientation(0),
+ tool_type(TOOL_TYPE_UNKNOWN) {
+}
+
MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
JNIEnv* env,
jobject event,
@@ -72,95 +138,34 @@ MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
jint pointer_count,
jint history_size,
jint action_index,
- jfloat pos_x_0_pixels,
- jfloat pos_y_0_pixels,
- jfloat pos_x_1_pixels,
- jfloat pos_y_1_pixels,
- jint pointer_id_0,
- jint pointer_id_1,
- jfloat touch_major_0_pixels,
- jfloat touch_major_1_pixels,
- jfloat raw_pos_x_pixels,
- jfloat raw_pos_y_pixels)
- : cached_time_(FromAndroidTime(time_ms)),
+ jint android_button_state,
+ jint meta_state,
+ jfloat raw_offset_x_pixels,
+ jfloat raw_offset_y_pixels,
+ const Pointer& pointer0,
+ const Pointer& pointer1)
+ : pix_to_dip_(pix_to_dip),
+ cached_time_(FromAndroidTime(time_ms)),
cached_action_(FromAndroidAction(android_action)),
cached_pointer_count_(pointer_count),
cached_history_size_(history_size),
cached_action_index_(action_index),
- pix_to_dip_(pix_to_dip),
- should_recycle_(false) {
+ cached_button_state_(FromAndroidButtonState(android_button_state)),
+ cached_flags_(FromAndroidMetaState(meta_state)),
+ cached_raw_position_offset_(ToDips(raw_offset_x_pixels),
+ ToDips(raw_offset_y_pixels)) {
DCHECK_GT(pointer_count, 0);
DCHECK_GE(history_size, 0);
event_.Reset(env, event);
- DCHECK(event_.obj());
-
- cached_positions_[0] = ToDips(gfx::PointF(pos_x_0_pixels, pos_y_0_pixels));
- cached_positions_[1] = ToDips(gfx::PointF(pos_x_1_pixels, pos_y_1_pixels));
- cached_pointer_ids_[0] = pointer_id_0;
- cached_pointer_ids_[1] = pointer_id_1;
- cached_touch_majors_[0] = ToDips(touch_major_0_pixels);
- cached_touch_majors_[1] = ToDips(touch_major_1_pixels);
- cached_raw_position_offset_ =
- ToDips(gfx::PointF(raw_pos_x_pixels, raw_pos_y_pixels)) -
- cached_positions_[0];
-}
+ if (cached_pointer_count_ > MAX_POINTERS_TO_CACHE || history_size > 0)
+ DCHECK(event_.obj());
-MotionEventAndroid::MotionEventAndroid(float pix_to_dip,
- JNIEnv* env,
- jobject event)
- : cached_time_(FromAndroidTime(Java_MotionEvent_getEventTime(env, event))),
- cached_action_(
- FromAndroidAction(Java_MotionEvent_getActionMasked(env, event))),
- cached_pointer_count_(Java_MotionEvent_getPointerCount(env, event)),
- cached_history_size_(Java_MotionEvent_getHistorySize(env, event)),
- cached_action_index_(Java_MotionEvent_getActionIndex(env, event)),
- pix_to_dip_(pix_to_dip),
- should_recycle_(true) {
- event_.Reset(env, event);
- DCHECK(event_.obj());
-
- for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
- if (i < cached_pointer_count_) {
- cached_positions_[i] =
- ToDips(gfx::PointF(Java_MotionEvent_getXF_I(env, event, i),
- Java_MotionEvent_getYF_I(env, event, i)));
- cached_pointer_ids_[i] = Java_MotionEvent_getPointerId(env, event, i);
- cached_touch_majors_[i] =
- ToDips(Java_MotionEvent_getTouchMajorF_I(env, event, i));
- } else {
- cached_pointer_ids_[i] = 0;
- cached_touch_majors_[i] = 0.f;
- }
- }
-
- cached_raw_position_offset_ =
- ToDips(gfx::PointF(Java_MotionEvent_getRawX(env, event),
- Java_MotionEvent_getRawY(env, event))) -
- cached_positions_[0];
-}
-
-MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& other)
- : event_(Obtain(other)),
- cached_time_(other.cached_time_),
- cached_action_(other.cached_action_),
- cached_pointer_count_(other.cached_pointer_count_),
- cached_history_size_(other.cached_history_size_),
- cached_action_index_(other.cached_action_index_),
- cached_raw_position_offset_(other.cached_raw_position_offset_),
- pix_to_dip_(other.pix_to_dip_),
- should_recycle_(true) {
- DCHECK(event_.obj());
- for (size_t i = 0; i < MAX_POINTERS_TO_CACHE; ++i) {
- cached_positions_[i] = other.cached_positions_[i];
- cached_pointer_ids_[i] = other.cached_pointer_ids_[i];
- cached_touch_majors_[i] = other.cached_touch_majors_[i];
- }
+ cached_pointers_[0] = FromAndroidPointer(pointer0);
+ cached_pointers_[1] = FromAndroidPointer(pointer1);
}
MotionEventAndroid::~MotionEventAndroid() {
- if (should_recycle_)
- Java_MotionEvent_recycle(AttachCurrentThread(), event_.obj());
}
int MotionEventAndroid::GetId() const {
@@ -182,7 +187,7 @@ size_t MotionEventAndroid::GetPointerCount() const {
int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
- return cached_pointer_ids_[pointer_index];
+ return cached_pointers_[pointer_index].id;
return Java_MotionEvent_getPointerId(
AttachCurrentThread(), event_.obj(), pointer_index);
}
@@ -190,7 +195,7 @@ int MotionEventAndroid::GetPointerId(size_t pointer_index) const {
float MotionEventAndroid::GetX(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
- return cached_positions_[pointer_index].x();
+ return cached_pointers_[pointer_index].position.x();
return ToDips(Java_MotionEvent_getXF_I(
AttachCurrentThread(), event_.obj(), pointer_index));
}
@@ -198,7 +203,7 @@ float MotionEventAndroid::GetX(size_t pointer_index) const {
float MotionEventAndroid::GetY(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
- return cached_positions_[pointer_index].y();
+ return cached_pointers_[pointer_index].position.y();
return ToDips(Java_MotionEvent_getYF_I(
AttachCurrentThread(), event_.obj(), pointer_index));
}
@@ -214,13 +219,34 @@ float MotionEventAndroid::GetRawY(size_t pointer_index) const {
float MotionEventAndroid::GetTouchMajor(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
if (pointer_index < MAX_POINTERS_TO_CACHE)
- return cached_touch_majors_[pointer_index];
+ return cached_pointers_[pointer_index].touch_major;
return ToDips(Java_MotionEvent_getTouchMajorF_I(
AttachCurrentThread(), event_.obj(), pointer_index));
}
+float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_pointers_[pointer_index].touch_minor;
+ return ToDips(Java_MotionEvent_getTouchMinorF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
+}
+
+float MotionEventAndroid::GetOrientation(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_pointers_[pointer_index].orientation;
+ return ToValidFloat(Java_MotionEvent_getOrientationF_I(
+ AttachCurrentThread(), event_.obj(), pointer_index));
+}
+
float MotionEventAndroid::GetPressure(size_t pointer_index) const {
DCHECK_LT(pointer_index, cached_pointer_count_);
+ // Note that this early return is a special case exercised only in testing, as
+ // caching the pressure values is not a worthwhile optimization (they're
+ // accessed at most once per event instance).
+ if (!event_.obj())
+ return 0.f;
return Java_MotionEvent_getPressureF_I(
AttachCurrentThread(), event_.obj(), pointer_index);
}
@@ -258,45 +284,38 @@ float MotionEventAndroid::GetHistoricalY(size_t pointer_index,
AttachCurrentThread(), event_.obj(), pointer_index, historical_index));
}
-scoped_ptr<ui::MotionEvent> MotionEventAndroid::Clone() const {
- return scoped_ptr<MotionEvent>(new MotionEventAndroid(*this));
-}
-
-scoped_ptr<ui::MotionEvent> MotionEventAndroid::Cancel() const {
- // The input coordinates to |MotionEventAndroid| are always in device pixels,
- // but the cached coordinates are in DIPs.
- const gfx::PointF position_pixels =
- gfx::ScalePoint(cached_positions_[0], 1.f / pix_to_dip_);
- return scoped_ptr<MotionEvent>(
- new MotionEventAndroid(pix_to_dip_,
- AttachCurrentThread(),
- Obtain(GetDownTime(),
- GetEventTime(),
- MotionEventAndroid::ACTION_CANCEL,
- position_pixels.x(),
- position_pixels.y()).obj()));
-}
-
-float MotionEventAndroid::GetTouchMinor(size_t pointer_index) const {
- return ToDips(Java_MotionEvent_getTouchMinorF_I(
+ui::MotionEvent::ToolType MotionEventAndroid::GetToolType(
+ size_t pointer_index) const {
+ DCHECK_LT(pointer_index, cached_pointer_count_);
+ if (pointer_index < MAX_POINTERS_TO_CACHE)
+ return cached_pointers_[pointer_index].tool_type;
+ return FromAndroidToolType(Java_MotionEvent_getToolType(
AttachCurrentThread(), event_.obj(), pointer_index));
}
-float MotionEventAndroid::GetOrientation() const {
- return Java_MotionEvent_getOrientationF(AttachCurrentThread(), event_.obj());
+int MotionEventAndroid::GetButtonState() const {
+ return cached_button_state_;
}
-base::TimeTicks MotionEventAndroid::GetDownTime() const {
- return FromAndroidTime(
- Java_MotionEvent_getDownTime(AttachCurrentThread(), event_.obj()));
+int MotionEventAndroid::GetFlags() const {
+ return cached_flags_;
}
float MotionEventAndroid::ToDips(float pixels) const {
return pixels * pix_to_dip_;
}
-gfx::PointF MotionEventAndroid::ToDips(const gfx::PointF& point_pixels) const {
- return gfx::ScalePoint(point_pixels, pix_to_dip_);
+MotionEventAndroid::CachedPointer MotionEventAndroid::FromAndroidPointer(
+ const Pointer& pointer) const {
+ CachedPointer result;
+ result.id = pointer.id;
+ result.position =
+ gfx::PointF(ToDips(pointer.pos_x_pixels), ToDips(pointer.pos_y_pixels));
+ result.touch_major = ToDips(pointer.touch_major_pixels);
+ result.touch_minor = ToDips(pointer.touch_minor_pixels);
+ result.orientation = ToValidFloat(pointer.orientation_rad);
+ result.tool_type = FromAndroidToolType(pointer.tool_type);
+ return result;
}
// static
@@ -304,27 +323,4 @@ bool MotionEventAndroid::RegisterMotionEventAndroid(JNIEnv* env) {
return JNI_MotionEvent::RegisterNativesImpl(env);
}
-// static
-base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
- const MotionEventAndroid& event) {
- return Java_MotionEvent_obtainAVME_AVME(AttachCurrentThread(),
- event.event_.obj());
-}
-
-// static
-base::android::ScopedJavaLocalRef<jobject> MotionEventAndroid::Obtain(
- base::TimeTicks down_time,
- base::TimeTicks event_time,
- Action action,
- float x_pixels,
- float y_pixels) {
- return Java_MotionEvent_obtainAVME_J_J_I_F_F_I(AttachCurrentThread(),
- ToAndroidTime(down_time),
- ToAndroidTime(event_time),
- ToAndroidAction(action),
- x_pixels,
- y_pixels,
- 0);
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/motion_event_android.h b/chromium/content/browser/renderer_host/input/motion_event_android.h
index 0362b0454e9..4af9f72e00b 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_android.h
+++ b/chromium/content/browser/renderer_host/input/motion_event_android.h
@@ -1,3 +1,4 @@
+
// Copyright 2014 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.
@@ -10,6 +11,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "content/common/content_export.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/gfx/geometry/point_f.h"
@@ -18,8 +20,25 @@ namespace content {
// Implementation of ui::MotionEvent wrapping a native Android MotionEvent.
// All *input* coordinates are in device pixels (as with Android MotionEvent),
// while all *output* coordinates are in DIPs (as with WebTouchEvent).
-class MotionEventAndroid : public ui::MotionEvent {
+class CONTENT_EXPORT MotionEventAndroid : public ui::MotionEvent {
public:
+ struct Pointer {
+ Pointer(jint id,
+ jfloat pos_x_pixels,
+ jfloat pos_y_pixels,
+ jfloat touch_major_pixels,
+ jfloat touch_minor_pixels,
+ jfloat orientation_rad,
+ jint tool_type);
+ jint id;
+ jfloat pos_x_pixels;
+ jfloat pos_y_pixels;
+ jfloat touch_major_pixels;
+ jfloat touch_minor_pixels;
+ jfloat orientation_rad;
+ jint tool_type;
+ };
+
// Forcing the caller to provide all cached values upon construction
// eliminates the need to perform a JNI call to retrieve values individually.
MotionEventAndroid(float pix_to_dip,
@@ -30,68 +49,49 @@ class MotionEventAndroid : public ui::MotionEvent {
jint pointer_count,
jint history_size,
jint action_index,
- jfloat pos_x_0_pixels,
- jfloat pos_y_0_pixels,
- jfloat pos_x_1_pixels,
- jfloat pos_y_1_pixels,
- jint pointer_id_0,
- jint pointer_id_1,
- jfloat touch_major_0_pixels,
- jfloat touch_major_1_pixels,
- jfloat raw_pos_x_pixels,
- jfloat raw_pos_y_pixels);
+ jint android_button_state,
+ jint meta_state,
+ jfloat raw_offset_x_pixels,
+ jfloat raw_offset_y_pixels,
+ const Pointer& pointer0,
+ const Pointer& pointer1);
virtual ~MotionEventAndroid();
// ui::MotionEvent methods.
- virtual int GetId() const OVERRIDE;
- virtual Action GetAction() const OVERRIDE;
- virtual int GetActionIndex() const OVERRIDE;
- virtual size_t GetPointerCount() const OVERRIDE;
- virtual int GetPointerId(size_t pointer_index) const OVERRIDE;
- virtual float GetX(size_t pointer_index) const OVERRIDE;
- virtual float GetY(size_t pointer_index) const OVERRIDE;
- virtual float GetRawX(size_t pointer_index) const OVERRIDE;
- virtual float GetRawY(size_t pointer_index) const OVERRIDE;
- virtual float GetTouchMajor(size_t pointer_index) const OVERRIDE;
- virtual float GetPressure(size_t pointer_index) const OVERRIDE;
- virtual base::TimeTicks GetEventTime() const OVERRIDE;
- virtual size_t GetHistorySize() const OVERRIDE;
+ virtual int GetId() const override;
+ virtual Action GetAction() const override;
+ virtual int GetActionIndex() const override;
+ virtual size_t GetPointerCount() const override;
+ virtual int GetPointerId(size_t pointer_index) const override;
+ virtual float GetX(size_t pointer_index) const override;
+ virtual float GetY(size_t pointer_index) const override;
+ virtual float GetRawX(size_t pointer_index) const override;
+ virtual float GetRawY(size_t pointer_index) const override;
+ virtual float GetTouchMajor(size_t pointer_index) const override;
+ virtual float GetTouchMinor(size_t pointer_index) const override;
+ virtual float GetOrientation(size_t pointer_index) const override;
+ virtual float GetPressure(size_t pointer_index) const override;
+ virtual base::TimeTicks GetEventTime() const override;
+ virtual size_t GetHistorySize() const override;
virtual base::TimeTicks GetHistoricalEventTime(
- size_t historical_index) const OVERRIDE;
+ size_t historical_index) const override;
virtual float GetHistoricalTouchMajor(size_t pointer_index,
- size_t historical_index) const OVERRIDE;
+ size_t historical_index) const override;
virtual float GetHistoricalX(size_t pointer_index,
- size_t historical_index) const OVERRIDE;
+ size_t historical_index) const override;
virtual float GetHistoricalY(size_t pointer_index,
- size_t historical_index) const OVERRIDE;
- virtual scoped_ptr<MotionEvent> Clone() const OVERRIDE;
- virtual scoped_ptr<MotionEvent> Cancel() const OVERRIDE;
-
- // Additional Android MotionEvent methods.
- float GetTouchMinor() const { return GetTouchMinor(0); }
- float GetTouchMinor(size_t pointer_index) const;
- float GetOrientation() const;
- base::TimeTicks GetDownTime() const;
+ size_t historical_index) const override;
+ virtual ToolType GetToolType(size_t pointer_index) const override;
+ virtual int GetButtonState() const override;
+ virtual int GetFlags() const override;
static bool RegisterMotionEventAndroid(JNIEnv* env);
- static base::android::ScopedJavaLocalRef<jobject> Obtain(
- const MotionEventAndroid& event);
- static base::android::ScopedJavaLocalRef<jobject> Obtain(
- base::TimeTicks down_time,
- base::TimeTicks event_time,
- Action action,
- float x_pixels,
- float y_pixels);
-
private:
- MotionEventAndroid();
- MotionEventAndroid(float pix_to_dip, JNIEnv* env, jobject event);
- MotionEventAndroid(const MotionEventAndroid&);
- MotionEventAndroid& operator=(const MotionEventAndroid&);
+ struct CachedPointer;
float ToDips(float pixels) const;
- gfx::PointF ToDips(const gfx::PointF& pixels) const;
+ CachedPointer FromAndroidPointer(const Pointer& pointer) const;
// Cache pointer coords, id's and major lengths for the most common
// touch-related scenarios, i.e., scrolling and pinching. This prevents
@@ -101,23 +101,29 @@ class MotionEventAndroid : public ui::MotionEvent {
// The Java reference to the underlying MotionEvent.
base::android::ScopedJavaGlobalRef<jobject> event_;
- base::TimeTicks cached_time_;
- Action cached_action_;
- size_t cached_pointer_count_;
- size_t cached_history_size_;
- int cached_action_index_;
- gfx::PointF cached_positions_[MAX_POINTERS_TO_CACHE];
- int cached_pointer_ids_[MAX_POINTERS_TO_CACHE];
- float cached_touch_majors_[MAX_POINTERS_TO_CACHE];
- gfx::Vector2dF cached_raw_position_offset_;
-
// Used to convert pixel coordinates from the Java-backed MotionEvent to
// DIP coordinates cached/returned by the MotionEventAndroid.
const float pix_to_dip_;
- // Whether |event_| should be recycled on destruction. This will only be true
- // for those events generated via |Obtain(...)|.
- bool should_recycle_;
+ const base::TimeTicks cached_time_;
+ const Action cached_action_;
+ const size_t cached_pointer_count_;
+ const size_t cached_history_size_;
+ const int cached_action_index_;
+ const int cached_button_state_;
+ const int cached_flags_;
+ const gfx::Vector2dF cached_raw_position_offset_;
+ struct CachedPointer {
+ CachedPointer();
+ int id;
+ gfx::PointF position;
+ float touch_major;
+ float touch_minor;
+ float orientation;
+ ToolType tool_type;
+ } cached_pointers_[MAX_POINTERS_TO_CACHE];
+
+ DISALLOW_COPY_AND_ASSIGN(MotionEventAndroid);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/motion_event_android_unittest.cc b/chromium/content/browser/renderer_host/input/motion_event_android_unittest.cc
new file mode 100644
index 00000000000..d7482d9aa7e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/motion_event_android_unittest.cc
@@ -0,0 +1,174 @@
+// Copyright 2014 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 <android/input.h>
+
+#include "base/android/jni_android.h"
+#include "base/float_util.h"
+#include "content/browser/renderer_host/input/motion_event_android.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/test/motion_event_test_utils.h"
+
+using ui::MotionEvent;
+
+namespace content {
+namespace {
+const float kPixToDip = 0.5f;
+
+int kAndroidActionDown = AMOTION_EVENT_ACTION_DOWN;
+
+int kAndroidAltKeyDown = AMETA_ALT_ON;
+
+// Corresponds to TOOL_TYPE_FINGER, see
+// developer.android.com/reference/android/view/MotionEvent.html
+// #TOOL_TYPE_FINGER.
+int kAndroidToolTypeFinger = 1;
+
+// Corresponds to BUTTON_PRIMARY, see
+// developer.android.com/reference/android/view/MotionEvent.html#BUTTON_PRIMARY.
+int kAndroidButtonPrimary = 1;
+
+} // namespace
+
+// Note that these tests avoid creating a Java instance of the MotionEvent, as
+// we're primarily testing caching behavior, and the code necessary to
+// construct a Java-backed MotionEvent itself adds unnecessary complexity.
+TEST(MotionEventAndroidTest, Constructor) {
+ int event_time_ms = 5;
+ base::TimeTicks event_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_time_ms);
+ MotionEventAndroid::Pointer p0(
+ 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger);
+ MotionEventAndroid::Pointer p1(
+ 2, -13.7f, 7.13f, 3.5f, 12.1f, -0.1f, kAndroidToolTypeFinger);
+ float raw_offset = -3.f;
+ int pointer_count = 2;
+ int history_size = 0;
+ int action_index = -1;
+ MotionEventAndroid event(kPixToDip,
+ base::android::AttachCurrentThread(),
+ nullptr,
+ event_time_ms,
+ kAndroidActionDown,
+ pointer_count,
+ history_size,
+ action_index,
+ kAndroidButtonPrimary,
+ kAndroidAltKeyDown,
+ raw_offset,
+ -raw_offset,
+ p0,
+ p1);
+
+ EXPECT_EQ(MotionEvent::ACTION_DOWN, event.GetAction());
+ EXPECT_EQ(event_time, event.GetEventTime());
+ EXPECT_EQ(p0.pos_x_pixels * kPixToDip, event.GetX(0));
+ EXPECT_EQ(p0.pos_y_pixels * kPixToDip, event.GetY(0));
+ EXPECT_EQ(p1.pos_x_pixels * kPixToDip, event.GetX(1));
+ EXPECT_EQ(p1.pos_y_pixels * kPixToDip, event.GetY(1));
+ EXPECT_FLOAT_EQ((p0.pos_x_pixels + raw_offset) * kPixToDip, event.GetRawX(0));
+ EXPECT_FLOAT_EQ((p0.pos_y_pixels - raw_offset) * kPixToDip, event.GetRawY(0));
+ EXPECT_FLOAT_EQ((p1.pos_x_pixels + raw_offset) * kPixToDip, event.GetRawX(1));
+ EXPECT_FLOAT_EQ((p1.pos_y_pixels - raw_offset) * kPixToDip, event.GetRawY(1));
+ EXPECT_EQ(p0.touch_major_pixels * kPixToDip, event.GetTouchMajor(0));
+ EXPECT_EQ(p1.touch_major_pixels * kPixToDip, event.GetTouchMajor(1));
+ EXPECT_EQ(p0.touch_minor_pixels * kPixToDip, event.GetTouchMinor(0));
+ EXPECT_EQ(p1.touch_minor_pixels * kPixToDip, event.GetTouchMinor(1));
+ EXPECT_EQ(p0.orientation_rad, event.GetOrientation(0));
+ EXPECT_EQ(p1.orientation_rad, event.GetOrientation(1));
+ EXPECT_EQ(p0.id, event.GetPointerId(0));
+ EXPECT_EQ(p1.id, event.GetPointerId(1));
+ EXPECT_EQ(MotionEvent::TOOL_TYPE_FINGER, event.GetToolType(0));
+ EXPECT_EQ(MotionEvent::TOOL_TYPE_FINGER, event.GetToolType(1));
+ EXPECT_EQ(MotionEvent::BUTTON_PRIMARY, event.GetButtonState());
+ EXPECT_EQ(ui::EF_ALT_DOWN, event.GetFlags());
+ EXPECT_EQ(static_cast<size_t>(pointer_count), event.GetPointerCount());
+ EXPECT_EQ(static_cast<size_t>(history_size), event.GetHistorySize());
+ EXPECT_EQ(action_index, event.GetActionIndex());
+}
+
+TEST(MotionEventAndroidTest, Clone) {
+ const int pointer_count = 1;
+ MotionEventAndroid::Pointer p0(
+ 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger);
+ MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0);
+ MotionEventAndroid event(kPixToDip,
+ base::android::AttachCurrentThread(),
+ nullptr,
+ 0,
+ kAndroidActionDown,
+ pointer_count,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ p0,
+ p1);
+
+ scoped_ptr<MotionEvent> clone = event.Clone();
+ EXPECT_EQ(ui::test::ToString(event), ui::test::ToString(*clone));
+}
+
+TEST(MotionEventAndroidTest, Cancel) {
+ const int event_time_ms = 5;
+ const int pointer_count = 1;
+ MotionEventAndroid::Pointer p0(
+ 1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, kAndroidToolTypeFinger);
+ MotionEventAndroid::Pointer p1(0, 0, 0, 0, 0, 0, 0);
+ MotionEventAndroid event(kPixToDip,
+ base::android::AttachCurrentThread(),
+ nullptr,
+ event_time_ms,
+ kAndroidActionDown,
+ pointer_count,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ p0,
+ p1);
+
+ scoped_ptr<MotionEvent> cancel_event = event.Cancel();
+ EXPECT_EQ(MotionEvent::ACTION_CANCEL, cancel_event->GetAction());
+ EXPECT_EQ(
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(event_time_ms),
+ cancel_event->GetEventTime());
+ EXPECT_EQ(p0.pos_x_pixels * kPixToDip, cancel_event->GetX(0));
+ EXPECT_EQ(p0.pos_y_pixels * kPixToDip, cancel_event->GetY(0));
+ EXPECT_EQ(static_cast<size_t>(pointer_count),
+ cancel_event->GetPointerCount());
+ EXPECT_EQ(0U, cancel_event->GetHistorySize());
+}
+
+TEST(MotionEventAndroidTest, InvalidOrientationsSanitized) {
+ int pointer_count = 2;
+ float orientation0 = 1e10f;
+ float orientation1 = std::numeric_limits<float>::quiet_NaN();
+ MotionEventAndroid::Pointer p0(0, 0, 0, 0, 0, orientation0, 0);
+ MotionEventAndroid::Pointer p1(1, 0, 0, 0, 0, orientation1, 0);
+ MotionEventAndroid event(kPixToDip,
+ base::android::AttachCurrentThread(),
+ nullptr,
+ 0,
+ kAndroidActionDown,
+ pointer_count,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ p0,
+ p1);
+
+ EXPECT_EQ(0.f, event.GetOrientation(0));
+ EXPECT_EQ(0.f, event.GetOrientation(1));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web.cc b/chromium/content/browser/renderer_host/input/motion_event_web.cc
index d1ff8a3c84f..77a40a4fe25 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web.cc
+++ b/chromium/content/browser/renderer_host/input/motion_event_web.cc
@@ -2,9 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// MSVC++ requires this to be set before any other includes to get M_PI.
+#define _USE_MATH_DEFINES
+
#include "content/browser/renderer_host/input/motion_event_web.h"
+#include <cmath>
+
#include "base/logging.h"
+#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/common/input/web_touch_event_traits.h"
using blink::WebInputEvent;
@@ -102,59 +108,58 @@ float MotionEventWeb::GetRawY(size_t pointer_index) const {
float MotionEventWeb::GetTouchMajor(size_t pointer_index) const {
DCHECK_LT(pointer_index, GetPointerCount());
- // TODO(jdduke): We should be a bit more careful about axes here.
return 2.f * std::max(event_.touches[pointer_index].radiusX,
event_.touches[pointer_index].radiusY);
}
-float MotionEventWeb::GetPressure(size_t pointer_index) const {
- return 0.f;
+float MotionEventWeb::GetTouchMinor(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, GetPointerCount());
+ return 2.f * std::min(event_.touches[pointer_index].radiusX,
+ event_.touches[pointer_index].radiusY);
}
-base::TimeTicks MotionEventWeb::GetEventTime() const {
- return base::TimeTicks() +
- base::TimeDelta::FromMicroseconds(event_.timeStampSeconds *
- base::Time::kMicrosecondsPerSecond);
-}
+float MotionEventWeb::GetOrientation(size_t pointer_index) const {
+ DCHECK_LT(pointer_index, GetPointerCount());
-size_t MotionEventWeb::GetHistorySize() const { return 0; }
+ float rotation_angle_rad = event_.touches[pointer_index].rotationAngle
+ * M_PI / 180.f;
+ DCHECK(0 <= rotation_angle_rad && rotation_angle_rad <= M_PI_2)
+ << "Unexpected touch rotation angle";
+
+ if (event_.touches[pointer_index].radiusX
+ > event_.touches[pointer_index].radiusY) {
+ // The case radiusX == radiusY is omitted from here on purpose: for circles,
+ // we want to pass the angle (which could be any value in such cases but
+ // always seem to be set to zero) unchanged.
+ rotation_angle_rad -= (float) M_PI_2;
+ }
-base::TimeTicks MotionEventWeb::GetHistoricalEventTime(
- size_t historical_index) const {
- NOTIMPLEMENTED();
- return base::TimeTicks();
+ return rotation_angle_rad;
}
-float MotionEventWeb::GetHistoricalTouchMajor(size_t pointer_index,
- size_t historical_index) const {
- NOTIMPLEMENTED();
+float MotionEventWeb::GetPressure(size_t pointer_index) const {
return 0.f;
}
-float MotionEventWeb::GetHistoricalX(size_t pointer_index,
- size_t historical_index) const {
- NOTIMPLEMENTED();
- return 0.f;
+base::TimeTicks MotionEventWeb::GetEventTime() const {
+ return base::TimeTicks() +
+ base::TimeDelta::FromMicroseconds(event_.timeStampSeconds *
+ base::Time::kMicrosecondsPerSecond);
}
-float MotionEventWeb::GetHistoricalY(size_t pointer_index,
- size_t historical_index) const {
- NOTIMPLEMENTED();
- return 0.f;
+ui::MotionEvent::ToolType MotionEventWeb::GetToolType(
+ size_t pointer_index) const {
+ // TODO(jdduke): Plumb tool type from the platform event, crbug.com/404128.
+ DCHECK_LT(pointer_index, GetPointerCount());
+ return TOOL_TYPE_UNKNOWN;
}
-scoped_ptr<ui::MotionEvent> MotionEventWeb::Clone() const {
- return scoped_ptr<MotionEvent>(new MotionEventWeb(event_));
+int MotionEventWeb::GetButtonState() const {
+ return 0;
}
-scoped_ptr<ui::MotionEvent> MotionEventWeb::Cancel() const {
- WebTouchEvent cancel_event(event_);
- WebTouchEventTraits::ResetTypeAndTouchStates(
- blink::WebInputEvent::TouchCancel,
- // TODO(rbyers): Shouldn't we use a fresh timestamp?
- event_.timeStampSeconds,
- &cancel_event);
- return scoped_ptr<MotionEvent>(new MotionEventWeb(cancel_event));
+int MotionEventWeb::GetFlags() const {
+ return WebEventModifiersToEventFlags(event_.modifiers);
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/motion_event_web.h b/chromium/content/browser/renderer_host/input/motion_event_web.h
index f4ae25890fe..f3d85abfc12 100644
--- a/chromium/content/browser/renderer_host/input/motion_event_web.h
+++ b/chromium/content/browser/renderer_host/input/motion_event_web.h
@@ -14,35 +14,26 @@ namespace content {
class MotionEventWeb : public ui::MotionEvent {
public:
explicit MotionEventWeb(const blink::WebTouchEvent& event);
- virtual ~MotionEventWeb();
+ ~MotionEventWeb() override;
// ui::MotionEvent
- virtual int GetId() const OVERRIDE;
- virtual Action GetAction() const OVERRIDE;
- virtual int GetActionIndex() const OVERRIDE;
- virtual size_t GetPointerCount() const OVERRIDE;
- virtual int GetPointerId(size_t pointer_index) const OVERRIDE;
- virtual float GetX(size_t pointer_index) const OVERRIDE;
- virtual float GetY(size_t pointer_index) const OVERRIDE;
- virtual float GetRawX(size_t pointer_index) const OVERRIDE;
- virtual float GetRawY(size_t pointer_index) const OVERRIDE;
- virtual float GetTouchMajor(size_t pointer_index) const OVERRIDE;
- virtual float GetPressure(size_t pointer_index) const OVERRIDE;
- virtual base::TimeTicks GetEventTime() const OVERRIDE;
- virtual size_t GetHistorySize() const OVERRIDE;
- virtual base::TimeTicks GetHistoricalEventTime(
- size_t historical_index) const OVERRIDE;
- virtual float GetHistoricalTouchMajor(
- size_t pointer_index,
- size_t historical_index) const OVERRIDE;
- virtual float GetHistoricalX(
- size_t pointer_index,
- size_t historical_index) const OVERRIDE;
- virtual float GetHistoricalY(
- size_t pointer_index,
- size_t historical_index) const OVERRIDE;
- virtual scoped_ptr<MotionEvent> Clone() const OVERRIDE;
- virtual scoped_ptr<MotionEvent> Cancel() const OVERRIDE;
+ int GetId() const override;
+ Action GetAction() const override;
+ int GetActionIndex() const override;
+ size_t GetPointerCount() const override;
+ int GetPointerId(size_t pointer_index) const override;
+ float GetX(size_t pointer_index) const override;
+ float GetY(size_t pointer_index) const override;
+ float GetRawX(size_t pointer_index) const override;
+ float GetRawY(size_t pointer_index) const override;
+ float GetTouchMajor(size_t pointer_index) const override;
+ float GetTouchMinor(size_t pointer_index) const override;
+ float GetOrientation(size_t pointer_index) const override;
+ float GetPressure(size_t pointer_index) const override;
+ base::TimeTicks GetEventTime() const override;
+ ToolType GetToolType(size_t pointer_index) const override;
+ int GetButtonState() const override;
+ int GetFlags() const override;
private:
blink::WebTouchEvent event_;
diff --git a/chromium/content/browser/renderer_host/input/selection_event_type.h b/chromium/content/browser/renderer_host/input/selection_event_type.h
new file mode 100644
index 00000000000..567259f0496
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/selection_event_type.h
@@ -0,0 +1,29 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_SELECTION_EVENT_TYPE_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_SELECTION_EVENT_TYPE_
+
+namespace content {
+
+// This file contains a list of events relating to selection and insertion, used
+// for notifying Java when the renderer selection has changed.
+//
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.input
+enum SelectionEventType {
+ SELECTION_SHOWN,
+ SELECTION_CLEARED,
+ SELECTION_DRAG_STARTED,
+ SELECTION_DRAG_STOPPED,
+ INSERTION_SHOWN,
+ INSERTION_MOVED,
+ INSERTION_TAPPED,
+ INSERTION_CLEARED,
+ INSERTION_DRAG_STARTED,
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_SELECTION_EVENT_TYPE_
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
index 8314d948ba7..6e5e20fb22a 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.cc
@@ -61,9 +61,10 @@ void SyntheticGestureController::OnDidFlushInput() {
return;
DCHECK(!pending_gesture_queue_.IsEmpty());
+ auto pending_gesture_result = pending_gesture_result_.Pass();
StopGesture(*pending_gesture_queue_.FrontGesture(),
pending_gesture_queue_.FrontCallback(),
- *pending_gesture_result_.Pass());
+ *pending_gesture_result);
pending_gesture_queue_.Pop();
if (!pending_gesture_queue_.IsEmpty())
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index b79e797aad2..8c08361e7d0 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -47,10 +47,10 @@ class MockSyntheticGesture : public SyntheticGesture {
step_count_(0) {
*finished_ = false;
}
- virtual ~MockSyntheticGesture() {}
+ ~MockSyntheticGesture() override {}
- virtual Result ForwardInputEvents(const base::TimeTicks& timestamp,
- SyntheticGestureTarget* target) OVERRIDE {
+ Result ForwardInputEvents(const base::TimeTicks& timestamp,
+ SyntheticGestureTarget* target) override {
step_count_++;
if (step_count_ == num_steps_) {
*finished_ = true;
@@ -75,22 +75,19 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget {
MockSyntheticGestureTarget()
: flush_requested_(false),
pointer_assumed_stopped_time_ms_(kPointerAssumedStoppedTimeMs) {}
- virtual ~MockSyntheticGestureTarget() {}
+ ~MockSyntheticGestureTarget() override {}
// SyntheticGestureTarget:
- virtual void DispatchInputEventToPlatform(
- const WebInputEvent& event) OVERRIDE {}
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {}
- virtual void SetNeedsFlush() OVERRIDE {
- flush_requested_ = true;
- }
+ void SetNeedsFlush() override { flush_requested_ = true; }
- virtual SyntheticGestureParams::GestureSourceType
- GetDefaultSyntheticGestureSourceType() const OVERRIDE {
+ SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const override {
return SyntheticGestureParams::TOUCH_INPUT;
}
- virtual base::TimeDelta PointerAssumedStoppedTime() const OVERRIDE {
+ base::TimeDelta PointerAssumedStoppedTime() const override {
return base::TimeDelta::FromMilliseconds(pointer_assumed_stopped_time_ms_);
}
@@ -98,11 +95,9 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget {
pointer_assumed_stopped_time_ms_ = time_ms;
}
- virtual float GetTouchSlopInDips() const OVERRIDE {
- return kTouchSlopInDips;
- }
+ float GetTouchSlopInDips() const override { return kTouchSlopInDips; }
- virtual float GetMinScalingSpanInDips() const OVERRIDE {
+ float GetMinScalingSpanInDips() const override {
return kMinScalingSpanInDips;
}
@@ -118,7 +113,7 @@ class MockSyntheticGestureTarget : public SyntheticGestureTarget {
class MockScrollGestureTarget : public MockSyntheticGestureTarget {
public:
MockScrollGestureTarget() : total_abs_scroll_distance_length_(0) {}
- virtual ~MockScrollGestureTarget() {}
+ ~MockScrollGestureTarget() override {}
gfx::Vector2dF start_to_end_distance() const {
return start_to_end_distance_;
@@ -135,10 +130,9 @@ class MockScrollGestureTarget : public MockSyntheticGestureTarget {
class MockScrollMouseTarget : public MockScrollGestureTarget {
public:
MockScrollMouseTarget() {}
- virtual ~MockScrollMouseTarget() {}
+ ~MockScrollMouseTarget() override {}
- virtual void DispatchInputEventToPlatform(
- const WebInputEvent& event) OVERRIDE {
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_EQ(event.type, WebInputEvent::MouseWheel);
const WebMouseWheelEvent& mouse_wheel_event =
static_cast<const WebMouseWheelEvent&>(event);
@@ -151,10 +145,9 @@ class MockScrollMouseTarget : public MockScrollGestureTarget {
class MockScrollTouchTarget : public MockScrollGestureTarget {
public:
MockScrollTouchTarget() : started_(false) {}
- virtual ~MockScrollTouchTarget() {}
+ ~MockScrollTouchTarget() override {}
- virtual void DispatchInputEventToPlatform(
- const WebInputEvent& event) OVERRIDE {
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
ASSERT_EQ(touch_event.touchesLength, 1U);
@@ -200,10 +193,9 @@ class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
last_pointer_distance_(0),
zoom_direction_(ZOOM_DIRECTION_UNKNOWN),
started_(false) {}
- virtual ~MockSyntheticPinchTouchTarget() {}
+ ~MockSyntheticPinchTouchTarget() override {}
- virtual void DispatchInputEventToPlatform(
- const WebInputEvent& event) OVERRIDE {
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
ASSERT_EQ(touch_event.touchesLength, 2U);
@@ -278,7 +270,7 @@ class MockSyntheticPinchTouchTarget : public MockSyntheticGestureTarget {
class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget {
public:
MockSyntheticTapGestureTarget() : state_(NOT_STARTED) {}
- virtual ~MockSyntheticTapGestureTarget() {}
+ ~MockSyntheticTapGestureTarget() override {}
bool GestureFinished() const { return state_ == FINISHED; }
gfx::PointF position() const { return position_; }
@@ -300,10 +292,9 @@ class MockSyntheticTapGestureTarget : public MockSyntheticGestureTarget {
class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget {
public:
MockSyntheticTapTouchTarget() {}
- virtual ~MockSyntheticTapTouchTarget() {}
+ ~MockSyntheticTapTouchTarget() override {}
- virtual void DispatchInputEventToPlatform(
- const WebInputEvent& event) OVERRIDE {
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type));
const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event);
ASSERT_EQ(touch_event.touchesLength, 1U);
@@ -333,10 +324,9 @@ class MockSyntheticTapTouchTarget : public MockSyntheticTapGestureTarget {
class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
public:
MockSyntheticTapMouseTarget() {}
- virtual ~MockSyntheticTapMouseTarget() {}
+ ~MockSyntheticTapMouseTarget() override {}
- virtual void DispatchInputEventToPlatform(
- const WebInputEvent& event) OVERRIDE {
+ void DispatchInputEventToPlatform(const WebInputEvent& event) override {
ASSERT_TRUE(WebInputEvent::isMouseEventType(event.type));
const WebMouseEvent& mouse_event = static_cast<const WebMouseEvent&>(event);
@@ -369,7 +359,7 @@ class MockSyntheticTapMouseTarget : public MockSyntheticTapGestureTarget {
class SyntheticGestureControllerTest : public testing::Test {
public:
SyntheticGestureControllerTest() {}
- virtual ~SyntheticGestureControllerTest() {}
+ ~SyntheticGestureControllerTest() override {}
protected:
template<typename MockGestureTarget>
@@ -379,14 +369,14 @@ class SyntheticGestureControllerTest : public testing::Test {
scoped_ptr<SyntheticGestureTarget>(target_)));
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
start_time_ = base::TimeTicks::Now();
time_ = start_time_;
num_success_ = 0;
num_failure_ = 0;
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
controller_.reset();
target_ = NULL;
time_ = base::TimeTicks();
@@ -430,10 +420,10 @@ class SyntheticGestureControllerTest : public testing::Test {
TEST_F(SyntheticGestureControllerTest, SingleGesture) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
- bool finished;
+ bool finished = false;
scoped_ptr<MockSyntheticGesture> gesture(
new MockSyntheticGesture(&finished, 3));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
EXPECT_TRUE(finished);
@@ -444,10 +434,10 @@ TEST_F(SyntheticGestureControllerTest, SingleGesture) {
TEST_F(SyntheticGestureControllerTest, GestureFailed) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
- bool finished;
+ bool finished = false;
scoped_ptr<MockSyntheticGesture> gesture(
new MockSyntheticGesture(&finished, 0));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
EXPECT_TRUE(finished);
@@ -458,14 +448,15 @@ TEST_F(SyntheticGestureControllerTest, GestureFailed) {
TEST_F(SyntheticGestureControllerTest, SuccessiveGestures) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
- bool finished_1, finished_2;
+ bool finished_1 = false;
scoped_ptr<MockSyntheticGesture> gesture_1(
new MockSyntheticGesture(&finished_1, 2));
+ bool finished_2 = false;
scoped_ptr<MockSyntheticGesture> gesture_2(
new MockSyntheticGesture(&finished_2, 4));
// Queue first gesture and wait for it to finish
- QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture_1.Pass());
FlushInputUntilComplete();
EXPECT_TRUE(finished_1);
@@ -473,7 +464,7 @@ TEST_F(SyntheticGestureControllerTest, SuccessiveGestures) {
EXPECT_EQ(0, num_failure_);
// Queue second gesture.
- QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture_2.Pass());
FlushInputUntilComplete();
EXPECT_TRUE(finished_2);
@@ -484,14 +475,15 @@ TEST_F(SyntheticGestureControllerTest, SuccessiveGestures) {
TEST_F(SyntheticGestureControllerTest, TwoGesturesInFlight) {
CreateControllerAndTarget<MockSyntheticGestureTarget>();
- bool finished_1, finished_2;
+ bool finished_1 = false;
scoped_ptr<MockSyntheticGesture> gesture_1(
new MockSyntheticGesture(&finished_1, 2));
+ bool finished_2 = false;
scoped_ptr<MockSyntheticGesture> gesture_2(
new MockSyntheticGesture(&finished_2, 4));
- QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>());
- QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture_1.Pass());
+ QueueSyntheticGesture(gesture_2.Pass());
FlushInputUntilComplete();
EXPECT_TRUE(finished_1);
@@ -510,8 +502,8 @@ TEST_F(SyntheticGestureControllerTest, GestureCompletedOnDidFlushInput) {
scoped_ptr<MockSyntheticGesture> gesture_2(
new MockSyntheticGesture(&finished_2, 4));
- QueueSyntheticGesture(gesture_1.PassAs<SyntheticGesture>());
- QueueSyntheticGesture(gesture_2.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture_1.Pass());
+ QueueSyntheticGesture(gesture_2.Pass());
while (target_->flush_requested()) {
target_->ClearFlushRequest();
@@ -561,16 +553,15 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchVertical) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
static_cast<MockScrollGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
- // TODO(dominikg): Remove adjustment when crbug.com/332418 is fixed.
EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
- scroll_target->start_to_end_distance() - gfx::Vector2dF(0, 0.001f));
+ scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchHorizontal) {
@@ -583,22 +574,15 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchHorizontal) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
static_cast<MockScrollGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
- // TODO(dominikg): Use vector comparison when crbug.com/332418 is fixed.
- //EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
- // scroll_target->start_to_end_distance());
- EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_).x(),
- scroll_target->start_to_end_distance().x());
- EXPECT_LT(AddTouchSlopToVector(params.distances[0], target_).y(),
- scroll_target->start_to_end_distance().y());
- EXPECT_GE(AddTouchSlopToVector(params.distances[0], target_).y(),
- scroll_target->start_to_end_distance().y() - 0.001f);
+ EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
+ scroll_target->start_to_end_distance());
}
void CheckIsWithinRangeSingle(float scroll_distance,
@@ -631,7 +615,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchDiagonal) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -658,7 +642,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchLongStop) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -686,7 +670,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchFling) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -708,7 +692,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchZeroDistance) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -728,7 +712,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseVertical) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -748,7 +732,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseHorizontal) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -768,7 +752,7 @@ TEST_F(SyntheticGestureControllerTest, SingleScrollGestureMouseDiagonal) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -789,7 +773,7 @@ TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouse) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -811,7 +795,7 @@ TEST_F(SyntheticGestureControllerTest, MultiScrollGestureMouseHorizontal) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -857,7 +841,7 @@ TEST_F(SyntheticGestureControllerTest, MultiScrollGestureTouch) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
@@ -881,21 +865,20 @@ TEST_F(SyntheticGestureControllerTest, MultiScrollGestureTouchVertical) {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockScrollGestureTarget* scroll_target =
static_cast<MockScrollGestureTarget*>(target_);
EXPECT_EQ(1, num_success_);
EXPECT_EQ(0, num_failure_);
- // TODO(dominikg): Remove adjustment when crbug.com/332418 is fixed.
EXPECT_FLOAT_EQ(
params.distances[0].Length() + params.distances[1].Length() +
target_->GetTouchSlopInDips(),
- scroll_target->total_abs_scroll_distance_length() - 0.001f);
+ scroll_target->total_abs_scroll_distance_length());
EXPECT_EQ(AddTouchSlopToVector(params.distances[0] + params.distances[1],
target_),
- scroll_target->start_to_end_distance() - gfx::Vector2dF(0, 0.001f));
+ scroll_target->start_to_end_distance());
}
TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) {
@@ -907,7 +890,7 @@ TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) {
params.anchor.SetPoint(54, 89);
scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticPinchTouchTarget* pinch_target =
@@ -928,7 +911,7 @@ TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomOut) {
params.anchor.SetPoint(-12, 93);
scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticPinchTouchTarget* pinch_target =
@@ -948,7 +931,7 @@ TEST_F(SyntheticGestureControllerTest, PinchGestureTouchNoScaling) {
params.scale_factor = 1.0f;
scoped_ptr<SyntheticPinchGesture> gesture(new SyntheticPinchGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticPinchTouchTarget* pinch_target =
@@ -969,7 +952,7 @@ TEST_F(SyntheticGestureControllerTest, TapGestureTouch) {
params.position.SetPoint(87, -124);
scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTapTouchTarget* tap_target =
@@ -992,7 +975,7 @@ TEST_F(SyntheticGestureControllerTest, TapGestureMouse) {
params.position.SetPoint(98, 123);
scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
- QueueSyntheticGesture(gesture.PassAs<SyntheticGesture>());
+ QueueSyntheticGesture(gesture.Pass());
FlushInputUntilComplete();
MockSyntheticTapMouseTarget* tap_target =
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
index dcf146ffb92..571fcbdb76f 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_android.h
@@ -25,21 +25,21 @@ class SyntheticGestureTargetAndroid : public SyntheticGestureTargetBase {
// SyntheticGestureTargetBase:
virtual void DispatchWebTouchEventToPlatform(
const blink::WebTouchEvent& web_touch,
- const ui::LatencyInfo& latency_info) OVERRIDE;
+ const ui::LatencyInfo& latency_info) override;
virtual void DispatchWebMouseWheelEventToPlatform(
const blink::WebMouseWheelEvent& web_wheel,
- const ui::LatencyInfo& latency_info) OVERRIDE;
+ const ui::LatencyInfo& latency_info) override;
virtual void DispatchWebMouseEventToPlatform(
const blink::WebMouseEvent& web_mouse,
- const ui::LatencyInfo& latency_info) OVERRIDE;
+ const ui::LatencyInfo& latency_info) override;
// SyntheticGestureTarget:
virtual SyntheticGestureParams::GestureSourceType
- GetDefaultSyntheticGestureSourceType() const OVERRIDE;
+ GetDefaultSyntheticGestureSourceType() const override;
- virtual float GetTouchSlopInDips() const OVERRIDE;
+ virtual float GetTouchSlopInDips() const override;
- virtual float GetMinScalingSpanInDips() const OVERRIDE;
+ virtual float GetMinScalingSpanInDips() const override;
private:
// Enum values below need to be kept in sync with TouchEventSynthesizer.java
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
index 0b4d9c8c97f..a7626d440d4 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -10,7 +10,7 @@
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event_processor.h"
-#include "ui/events/gestures/gesture_configuration.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
using blink::WebTouchEvent;
using blink::WebMouseWheelEvent;
@@ -135,11 +135,14 @@ SyntheticGestureTargetAura::GetDefaultSyntheticGestureSourceType() const {
float SyntheticGestureTargetAura::GetTouchSlopInDips() const {
// - 1 because Aura considers a pointer to be moving if it has moved at least
// 'max_touch_move_in_pixels_for_click' pixels.
- return ui::GestureConfiguration::max_touch_move_in_pixels_for_click() - 1;
+ return ui::GestureConfiguration::GetInstance()
+ ->max_touch_move_in_pixels_for_click() -
+ 1;
}
float SyntheticGestureTargetAura::GetMinScalingSpanInDips() const {
- return ui::GestureConfiguration::min_distance_for_pinch_scroll_in_pixels();
+ return ui::GestureConfiguration::GetInstance()
+ ->min_distance_for_pinch_scroll_in_pixels();
}
aura::Window* SyntheticGestureTargetAura::GetWindow() const {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
index f3634d61162..53f06720b8e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_aura.h
@@ -26,23 +26,23 @@ class SyntheticGestureTargetAura : public SyntheticGestureTargetBase {
explicit SyntheticGestureTargetAura(RenderWidgetHostImpl* host);
// SyntheticGestureTargetBase:
- virtual void DispatchWebTouchEventToPlatform(
+ void DispatchWebTouchEventToPlatform(
const blink::WebTouchEvent& web_touch,
- const ui::LatencyInfo& latency_info) OVERRIDE;
- virtual void DispatchWebMouseWheelEventToPlatform(
+ const ui::LatencyInfo& latency_info) override;
+ void DispatchWebMouseWheelEventToPlatform(
const blink::WebMouseWheelEvent& web_wheel,
- const ui::LatencyInfo& latency_info) OVERRIDE;
- virtual void DispatchWebMouseEventToPlatform(
+ const ui::LatencyInfo& latency_info) override;
+ void DispatchWebMouseEventToPlatform(
const blink::WebMouseEvent& web_mouse,
- const ui::LatencyInfo& latency_info) OVERRIDE;
+ const ui::LatencyInfo& latency_info) override;
// SyntheticGestureTarget:
- virtual SyntheticGestureParams::GestureSourceType
- GetDefaultSyntheticGestureSourceType() const OVERRIDE;
+ SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const override;
- virtual float GetTouchSlopInDips() const OVERRIDE;
+ float GetTouchSlopInDips() const override;
- virtual float GetMinScalingSpanInDips() const OVERRIDE;
+ float GetMinScalingSpanInDips() const override;
private:
aura::Window* GetWindow() const;
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
index a66a8d34cae..d48be113e62 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_target_base.h
@@ -25,7 +25,7 @@ class RenderWidgetHostImpl;
class SyntheticGestureTargetBase : public SyntheticGestureTarget {
public:
explicit SyntheticGestureTargetBase(RenderWidgetHostImpl* host);
- virtual ~SyntheticGestureTargetBase();
+ ~SyntheticGestureTargetBase() override;
virtual void DispatchWebTouchEventToPlatform(
const blink::WebTouchEvent& web_touch,
@@ -40,19 +40,18 @@ class SyntheticGestureTargetBase : public SyntheticGestureTarget {
const ui::LatencyInfo& latency_info);
// SyntheticGestureTarget:
- virtual void DispatchInputEventToPlatform(
- const blink::WebInputEvent& event) OVERRIDE;
+ void DispatchInputEventToPlatform(const blink::WebInputEvent& event) override;
- virtual void SetNeedsFlush() OVERRIDE;
+ void SetNeedsFlush() override;
- virtual SyntheticGestureParams::GestureSourceType
- GetDefaultSyntheticGestureSourceType() const OVERRIDE;
+ SyntheticGestureParams::GestureSourceType
+ GetDefaultSyntheticGestureSourceType() const override;
- virtual base::TimeDelta PointerAssumedStoppedTime() const OVERRIDE;
+ base::TimeDelta PointerAssumedStoppedTime() const override;
- virtual float GetTouchSlopInDips() const OVERRIDE;
+ float GetTouchSlopInDips() const override;
- virtual float GetMinScalingSpanInDips() const OVERRIDE;
+ float GetMinScalingSpanInDips() const override;
protected:
RenderWidgetHostImpl* render_widget_host() const { return host_; }
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h
index 76ee1da7b26..71e79ec6b2b 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_pinch_gesture.h
@@ -18,11 +18,11 @@ namespace content {
class CONTENT_EXPORT SyntheticPinchGesture : public SyntheticGesture {
public:
explicit SyntheticPinchGesture(const SyntheticPinchGestureParams& params);
- virtual ~SyntheticPinchGesture();
+ ~SyntheticPinchGesture() override;
- virtual SyntheticGesture::Result ForwardInputEvents(
+ SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
- SyntheticGestureTarget* target) OVERRIDE;
+ SyntheticGestureTarget* target) override;
private:
enum GestureState {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
index b6b281406c3..8800aca2969 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
@@ -99,15 +99,6 @@ void SyntheticSmoothScrollGesture::ForwardTouchInputEvents(
target->PointerAssumedStoppedTime()) {
event_timestamp = current_scroll_segment_stop_time_ +
target->PointerAssumedStoppedTime();
- // Send one last move event, but don't change the location. Without this
- // we'd still sometimes cause a fling on Android.
-
- // Required to suppress flings on Aura, see
- // |UpdateWebTouchPointFromUIEvent|, remove when crbug.com/332418
- // is fixed.
- touch_event_.touches[0].position.y += 0.001f;
-
- ForwardTouchEvent(target, event_timestamp);
ReleaseTouchPoint(target, event_timestamp);
state_ = DONE;
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h
index a4078550e0e..080e2dbaec1 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h
@@ -28,11 +28,11 @@ class CONTENT_EXPORT SyntheticSmoothScrollGesture : public SyntheticGesture {
public:
explicit SyntheticSmoothScrollGesture(
const SyntheticSmoothScrollGestureParams& params);
- virtual ~SyntheticSmoothScrollGesture();
+ ~SyntheticSmoothScrollGesture() override;
- virtual SyntheticGesture::Result ForwardInputEvents(
+ SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
- SyntheticGestureTarget* target) OVERRIDE;
+ SyntheticGestureTarget* target) override;
private:
enum GestureState {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
index e67d1984d98..a42b2dd17ed 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_tap_gesture.h
@@ -16,11 +16,11 @@ namespace content {
class CONTENT_EXPORT SyntheticTapGesture : public SyntheticGesture {
public:
explicit SyntheticTapGesture(const SyntheticTapGestureParams& params);
- virtual ~SyntheticTapGesture();
+ ~SyntheticTapGesture() override;
- virtual SyntheticGesture::Result ForwardInputEvents(
+ SyntheticGesture::Result ForwardInputEvents(
const base::TimeTicks& timestamp,
- SyntheticGestureTarget* target) OVERRIDE;
+ SyntheticGestureTarget* target) override;
private:
enum GestureState {
diff --git a/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc b/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
index 702dc6f10b8..0c2e94f07e0 100644
--- a/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/tap_suppression_controller_unittest.cc
@@ -39,7 +39,7 @@ class MockTapSuppressionController : public TapSuppressionController,
time_(),
timer_started_(false) {}
- virtual ~MockTapSuppressionController() {}
+ ~MockTapSuppressionController() override {}
void SendGestureFlingCancel() {
last_actions_ = NONE;
@@ -89,26 +89,20 @@ class MockTapSuppressionController : public TapSuppressionController,
int last_actions() { return last_actions_; }
protected:
- virtual base::TimeTicks Now() OVERRIDE {
- return time_;
- }
+ base::TimeTicks Now() override { return time_; }
- virtual void StartTapDownTimer(const base::TimeDelta& delay) OVERRIDE {
+ void StartTapDownTimer(const base::TimeDelta& delay) override {
timer_expiry_time_ = time_ + delay;
timer_started_ = true;
}
- virtual void StopTapDownTimer() OVERRIDE {
- timer_started_ = false;
- }
+ void StopTapDownTimer() override { timer_started_ = false; }
private:
// TapSuppressionControllerClient implementation
- virtual void DropStashedTapDown() OVERRIDE {
- last_actions_ |= TAP_DOWN_DROPPED;
- }
+ void DropStashedTapDown() override { last_actions_ |= TAP_DOWN_DROPPED; }
- virtual void ForwardStashedTapDown() OVERRIDE {
+ void ForwardStashedTapDown() override {
last_actions_ |= STASHED_TAP_DOWN_FORWARDED;
}
@@ -131,19 +125,16 @@ class TapSuppressionControllerTest : public testing::Test {
public:
TapSuppressionControllerTest() {
}
- virtual ~TapSuppressionControllerTest() {
- }
+ ~TapSuppressionControllerTest() override {}
protected:
// testing::Test
- virtual void SetUp() {
+ void SetUp() override {
tap_suppression_controller_.reset(
new MockTapSuppressionController(GetConfig()));
}
- virtual void TearDown() {
- tap_suppression_controller_.reset();
- }
+ void TearDown() override { tap_suppression_controller_.reset(); }
static TapSuppressionController::Config GetConfig() {
TapSuppressionController::Config config;
diff --git a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
index 9d9fb83785d..c9d0a2bef86 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -71,7 +71,7 @@ namespace content {
class TouchActionBrowserTest : public ContentBrowserTest {
public:
TouchActionBrowserTest() {}
- virtual ~TouchActionBrowserTest() {}
+ ~TouchActionBrowserTest() override {}
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(shell()->web_contents()->
@@ -97,7 +97,7 @@ class TouchActionBrowserTest : public ContentBrowserTest {
}
// ContentBrowserTest:
- virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
+ void SetUpCommandLine(CommandLine* cmd) override {
cmd->AppendSwitchASCII(switches::kTouchEvents,
switches::kTouchEventsEnabled);
// TODO(rbyers): Remove this switch once touch-action ships.
@@ -138,9 +138,9 @@ class TouchActionBrowserTest : public ContentBrowserTest {
scoped_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
GetWidgetHost()->QueueSyntheticGesture(
- gesture.PassAs<SyntheticGesture>(),
+ gesture.Pass(),
base::Bind(&TouchActionBrowserTest::OnSyntheticGestureCompleted,
- base::Unretained(this)));
+ base::Unretained(this)));
// Runs until we get the OnSyntheticGestureCompleted callback
runner_->Run();
@@ -192,16 +192,8 @@ IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, DISABLED_DefaultAuto) {
// Verify that touching a touch-action: none region disables scrolling and
// enables all touch events to be sent.
// Disabled on MacOS because it doesn't support touch input.
-// Flaky on OS_CHROMEOS http://crbug.com/376695.
-// Also flaky on Linux Tests (TSan v2) http://crbug.com/376668.
-#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
-#define MAYBE_TouchActionNone DISABLED_TouchActionNone
-#elif defined(THREAD_SANITIZER) && defined(OS_LINUX)
-#define MAYBE_TouchActionNone DISABLED_TouchActionNone
-#else
-#define MAYBE_TouchActionNone TouchActionNone
-#endif
-IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TouchActionNone) {
+// It's just flaky everywhere.
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, DISABLED_TouchActionNone) {
LoadURL();
bool scrolled = DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 45));
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index c7d5cc605a7..61ae63ef1ff 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -7,11 +7,11 @@
#include "content/browser/renderer_host/input/motion_event_web.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/common/input/web_touch_event_traits.h"
+#include "content/grit/content_resources.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "grit/content_resources.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
-#include "ui/events/gesture_detection/gesture_config_helper.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/screen.h"
@@ -47,14 +47,15 @@ TouchEmulator::TouchEmulator(TouchEmulatorClient* client)
: client_(client),
gesture_provider_(GetGestureProviderConfig(), this),
enabled_(false),
- allow_pinch_(false) {
+ emulated_stream_active_sequence_count_(0),
+ native_stream_active_sequence_count_(0) {
DCHECK(client_);
ResetState();
bool use_2x = gfx::Screen::GetNativeScreen()->
GetPrimaryDisplay().device_scale_factor() > 1.5f;
float cursor_scale_factor = use_2x ? 2.f : 1.f;
- InitCursorFromResource(&touch_cursor_,
+ cursor_size_ = InitCursorFromResource(&touch_cursor_,
cursor_scale_factor,
use_2x ? IDR_DEVTOOLS_TOUCH_CURSOR_ICON_2X :
IDR_DEVTOOLS_TOUCH_CURSOR_ICON);
@@ -85,18 +86,16 @@ void TouchEmulator::ResetState() {
last_mouse_move_timestamp_ = 0;
mouse_pressed_ = false;
shift_pressed_ = false;
- touch_active_ = false;
suppress_next_fling_cancel_ = false;
pinch_scale_ = 1.f;
pinch_gesture_active_ = false;
}
-void TouchEmulator::Enable(bool allow_pinch) {
+void TouchEmulator::Enable() {
if (!enabled_) {
enabled_ = true;
ResetState();
}
- allow_pinch_ = allow_pinch;
UpdateCursor();
}
@@ -109,7 +108,7 @@ void TouchEmulator::Disable() {
CancelTouch();
}
-void TouchEmulator::InitCursorFromResource(
+gfx::SizeF TouchEmulator::InitCursorFromResource(
WebCursor* cursor, float scale, int resource_id) {
gfx::Image& cursor_image =
content::GetContentClient()->GetNativeImageNamed(resource_id);
@@ -124,12 +123,18 @@ void TouchEmulator::InitCursorFromResource(
#endif
cursor->InitFromCursorInfo(cursor_info);
+ return gfx::ScaleSize(cursor_image.Size(), 1.f / scale);
}
bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
if (!enabled_)
return false;
+ if (mouse_event.button == WebMouseEvent::ButtonRight &&
+ mouse_event.type == WebInputEvent::MouseDown) {
+ client_->ShowContextMenuAtPoint(gfx::Point(mouse_event.x, mouse_event.y));
+ }
+
if (mouse_event.button != WebMouseEvent::ButtonLeft)
return true;
@@ -154,7 +159,7 @@ bool TouchEmulator::HandleMouseEvent(const WebMouseEvent& mouse_event) {
if (FillTouchEventAndPoint(mouse_event) &&
gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_))) {
- client_->ForwardTouchEvent(touch_event_);
+ ForwardTouchEventToClient();
}
// Do not pass mouse events to the renderer.
@@ -166,7 +171,7 @@ bool TouchEmulator::HandleMouseWheelEvent(const WebMouseWheelEvent& event) {
return false;
// Send mouse wheel for easy scrolling when there is no active touch.
- return touch_active_;
+ return emulated_stream_active_sequence_count_ > 0;
}
bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) {
@@ -192,11 +197,59 @@ bool TouchEmulator::HandleKeyboardEvent(const WebKeyboardEvent& event) {
return false;
}
-bool TouchEmulator::HandleTouchEventAck(InputEventAckState ack_result) {
- const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
- gesture_provider_.OnTouchEventAck(event_consumed);
- // TODO(dgozman): Disable emulation when real touch events are available.
- return true;
+bool TouchEmulator::HandleTouchEvent(const blink::WebTouchEvent& event) {
+ // Block native event when emulated touch stream is active.
+ if (emulated_stream_active_sequence_count_)
+ return true;
+
+ bool is_sequence_start = WebTouchEventTraits::IsTouchSequenceStart(event);
+ // Do not allow middle-sequence event to pass through, if start was blocked.
+ if (!native_stream_active_sequence_count_ && !is_sequence_start)
+ return true;
+
+ if (is_sequence_start)
+ native_stream_active_sequence_count_++;
+ return false;
+}
+
+void TouchEmulator::ForwardTouchEventToClient() {
+ const bool event_consumed = true;
+ // Block emulated event when emulated native stream is active.
+ if (native_stream_active_sequence_count_) {
+ gesture_provider_.OnTouchEventAck(event_consumed);
+ return;
+ }
+
+ bool is_sequence_start =
+ WebTouchEventTraits::IsTouchSequenceStart(touch_event_);
+ // Do not allow middle-sequence event to pass through, if start was blocked.
+ if (!emulated_stream_active_sequence_count_ && !is_sequence_start) {
+ gesture_provider_.OnTouchEventAck(event_consumed);
+ return;
+ }
+
+ if (is_sequence_start)
+ emulated_stream_active_sequence_count_++;
+ client_->ForwardEmulatedTouchEvent(touch_event_);
+}
+
+bool TouchEmulator::HandleTouchEventAck(
+ const blink::WebTouchEvent& event, InputEventAckState ack_result) {
+ bool is_sequence_end = WebTouchEventTraits::IsTouchSequenceEnd(event);
+ if (emulated_stream_active_sequence_count_) {
+ if (is_sequence_end)
+ emulated_stream_active_sequence_count_--;
+
+ const bool event_consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+ gesture_provider_.OnTouchEventAck(event_consumed);
+ return true;
+ }
+
+ // We may have not seen native touch sequence start (when created in the
+ // middle of a sequence), so don't decrement sequence count below zero.
+ if (is_sequence_end && native_stream_active_sequence_count_)
+ native_stream_active_sequence_count_--;
+ return false;
}
void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
@@ -266,16 +319,16 @@ void TouchEmulator::OnGestureEvent(const ui::GestureEventData& gesture) {
}
void TouchEmulator::CancelTouch() {
- if (!touch_active_)
+ if (!emulated_stream_active_sequence_count_)
return;
WebTouchEventTraits::ResetTypeAndTouchStates(
WebInputEvent::TouchCancel,
(base::TimeTicks::Now() - base::TimeTicks()).InSecondsF(),
&touch_event_);
- touch_active_ = false;
- if (gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_)))
- client_->ForwardTouchEvent(touch_event_);
+ if (gesture_provider_.GetCurrentDownEvent() &&
+ gesture_provider_.OnTouchEvent(MotionEventWeb(touch_event_)))
+ ForwardTouchEventToClient();
}
void TouchEmulator::UpdateCursor() {
@@ -351,14 +404,12 @@ bool TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
switch (mouse_event.type) {
case WebInputEvent::MouseDown:
eventType = WebInputEvent::TouchStart;
- touch_active_ = true;
break;
case WebInputEvent::MouseMove:
eventType = WebInputEvent::TouchMove;
break;
case WebInputEvent::MouseUp:
eventType = WebInputEvent::TouchEnd;
- touch_active_ = false;
break;
default:
eventType = WebInputEvent::Undefined;
@@ -371,7 +422,8 @@ bool TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
WebTouchPoint& point = touch_event_.touches[0];
point.id = 0;
- point.radiusX = point.radiusY = 1.f;
+ point.radiusX = 0.5f * cursor_size_.width();
+ point.radiusY = 0.5f * cursor_size_.height();
point.force = 1.f;
point.rotationAngle = 0.f;
point.position.x = mouse_event.x;
@@ -383,7 +435,7 @@ bool TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
}
bool TouchEmulator::InPinchGestureMode() const {
- return shift_pressed_ && allow_pinch_;
+ return shift_pressed_;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index af1e056db30..c364eb9fdca 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -10,6 +10,7 @@
#include "content/common/input/input_event_ack_state.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
+#include "ui/gfx/size_f.h"
namespace content {
@@ -17,29 +18,38 @@ namespace content {
class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
public:
explicit TouchEmulator(TouchEmulatorClient* client);
- virtual ~TouchEmulator();
+ ~TouchEmulator() override;
- void Enable(bool allow_pinch);
+ void Enable();
void Disable();
- // Returns |true| if the event was consumed.
+ // Note that TouchEmulator should always listen to touch events and their acks
+ // (even in disabled state) to track native stream presence.
+ bool enabled() const { return enabled_; }
+
+ // Returns |true| if the event was consumed. Consumed event should not
+ // propagate any further.
// TODO(dgozman): maybe pass latency info together with events.
bool HandleMouseEvent(const blink::WebMouseEvent& event);
bool HandleMouseWheelEvent(const blink::WebMouseWheelEvent& event);
bool HandleKeyboardEvent(const blink::WebKeyboardEvent& event);
+ bool HandleTouchEvent(const blink::WebTouchEvent& event);
// Returns |true| if the event ack was consumed. Consumed ack should not
// propagate any further.
- bool HandleTouchEventAck(InputEventAckState ack_result);
+ bool HandleTouchEventAck(const blink::WebTouchEvent& event,
+ InputEventAckState ack_result);
// Cancel any touches, for example, when focus is lost.
void CancelTouch();
private:
// ui::GestureProviderClient implementation.
- virtual void OnGestureEvent(const ui::GestureEventData& gesture) OVERRIDE;
+ void OnGestureEvent(const ui::GestureEventData& gesture) override;
- void InitCursorFromResource(WebCursor* cursor, float scale, int resource_id);
+ // Returns cursor size in DIP.
+ gfx::SizeF InitCursorFromResource(
+ WebCursor* cursor, float scale, int resource_id);
void ResetState();
void UpdateCursor();
bool UpdateShiftPressed(bool shift_pressed);
@@ -56,19 +66,21 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
void PinchEnd(const blink::WebGestureEvent& event);
void ScrollEnd(const blink::WebGestureEvent& event);
+ void ForwardTouchEventToClient();
+
TouchEmulatorClient* const client_;
ui::FilteredGestureProvider gesture_provider_;
// Disabled emulator does only process touch acks left from previous
// emulation. It does not intercept any events.
bool enabled_;
- bool allow_pinch_;
// While emulation is on, default cursor is touch. Pressing shift changes
// cursor to the pinch one.
WebCursor pointer_cursor_;
WebCursor touch_cursor_;
WebCursor pinch_cursor_;
+ gfx::SizeF cursor_size_;
// These are used to drop extra mouse move events coming too quickly, so
// we don't handle too much touches in gesture provider.
@@ -79,7 +91,8 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
bool shift_pressed_;
blink::WebTouchEvent touch_event_;
- bool touch_active_;
+ int emulated_stream_active_sequence_count_;
+ int native_stream_active_sequence_count_;
// Whether we should suppress next fling cancel. This may happen when we
// did not send fling start in pinch mode.
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_client.h b/chromium/content/browser/renderer_host/input/touch_emulator_client.h
index 92f382f5f9c..7f807368dcb 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_client.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_client.h
@@ -17,8 +17,9 @@ class CONTENT_EXPORT TouchEmulatorClient {
virtual ~TouchEmulatorClient() {}
virtual void ForwardGestureEvent(const blink::WebGestureEvent& event) = 0;
- virtual void ForwardTouchEvent(const blink::WebTouchEvent& event) = 0;
+ virtual void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) = 0;
virtual void SetCursor(const WebCursor& cursor) = 0;
+ virtual void ShowContextMenuAtPoint(const gfx::Point& point) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 8fdfd54cce2..80eb51ad28a 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -12,7 +12,6 @@
#include "content/browser/renderer_host/input/touch_emulator_client.h"
#include "content/common/input/web_input_event_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/gesture_detection/gesture_config_helper.h"
#if defined(USE_AURA)
#include "ui/aura/env.h"
@@ -35,6 +34,7 @@ class TouchEmulatorTest : public testing::Test,
TouchEmulatorTest()
: shift_pressed_(false),
mouse_pressed_(false),
+ ack_touches_synchronously_(true),
last_mouse_x_(-1),
last_mouse_y_(-1) {
last_event_time_seconds_ =
@@ -42,10 +42,10 @@ class TouchEmulatorTest : public testing::Test,
event_time_delta_seconds_ = 0.1;
}
- virtual ~TouchEmulatorTest() {}
+ ~TouchEmulatorTest() override {}
// testing::Test
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
#if defined(USE_AURA)
aura::Env::CreateInstance(true);
screen_.reset(aura::TestScreen::Create(gfx::Size()));
@@ -53,10 +53,10 @@ class TouchEmulatorTest : public testing::Test,
#endif
emulator_.reset(new TouchEmulator(this));
- emulator_->Enable(true /* allow_pinch */);
+ emulator_->Enable();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
emulator_->Disable();
EXPECT_EQ("", ExpectedEvents());
@@ -66,23 +66,26 @@ class TouchEmulatorTest : public testing::Test,
#endif
}
- virtual void ForwardGestureEvent(
- const blink::WebGestureEvent& event) OVERRIDE {
+ void ForwardGestureEvent(const blink::WebGestureEvent& event) override {
forwarded_events_.push_back(event.type);
}
- virtual void ForwardTouchEvent(
- const blink::WebTouchEvent& event) OVERRIDE {
+ void ForwardEmulatedTouchEvent(const blink::WebTouchEvent& event) override {
forwarded_events_.push_back(event.type);
EXPECT_EQ(1U, event.touchesLength);
EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
int expectedCancelable = event.type != WebInputEvent::TouchCancel;
EXPECT_EQ(expectedCancelable, event.cancelable);
- emulator()->HandleTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ if (ack_touches_synchronously_) {
+ emulator()->HandleTouchEventAck(
+ event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ }
}
- virtual void SetCursor(const WebCursor& cursor) OVERRIDE {}
+ void SetCursor(const WebCursor& cursor) override {}
+
+ void ShowContextMenuAtPoint(const gfx::Point& point) override {}
protected:
TouchEmulator* emulator() const {
@@ -181,6 +184,68 @@ class TouchEmulatorTest : public testing::Test,
mouse_pressed_ = false;
}
+ bool TouchStart(int x, int y, bool ack) {
+ return SendTouchEvent(
+ WebInputEvent::TouchStart, WebTouchPoint::StatePressed, x, y, ack);
+ }
+
+ bool TouchMove(int x, int y, bool ack) {
+ return SendTouchEvent(
+ WebInputEvent::TouchMove, WebTouchPoint::StateMoved, x, y, ack);
+ }
+
+ bool TouchEnd(int x, int y, bool ack) {
+ return SendTouchEvent(
+ WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, x, y, ack);
+ }
+
+ WebTouchEvent MakeTouchEvent(WebInputEvent::Type type,
+ WebTouchPoint::State state, int x, int y) {
+ WebTouchEvent event;
+ event.type = type;
+ event.timeStampSeconds = GetNextEventTimeSeconds();
+ event.touchesLength = 1;
+ event.touches[0].id = 0;
+ event.touches[0].state = state;
+ event.touches[0].position.x = x;
+ event.touches[0].position.y = y;
+ event.touches[0].screenPosition.x = x;
+ event.touches[0].screenPosition.y = y;
+ return event;
+ }
+
+ bool SendTouchEvent(WebInputEvent::Type type, WebTouchPoint::State state,
+ int x, int y, bool ack) {
+ WebTouchEvent event = MakeTouchEvent(type, state, x, y);
+ if (emulator()->HandleTouchEvent(event)) {
+ // Touch event is not forwarded.
+ return false;
+ }
+
+ if (ack) {
+ // Can't send ack if there are some pending acks.
+ DCHECK(!touch_events_to_ack_.size());
+
+ // Touch event is forwarded, ack should not be handled by emulator.
+ EXPECT_FALSE(emulator()->HandleTouchEventAck(
+ event, INPUT_EVENT_ACK_STATE_CONSUMED));
+ } else {
+ touch_events_to_ack_.push_back(event);
+ }
+ return true;
+ }
+
+ void AckOldestTouchEvent() {
+ DCHECK(touch_events_to_ack_.size());
+ WebTouchEvent event = touch_events_to_ack_[0];
+ touch_events_to_ack_.erase(touch_events_to_ack_.begin());
+ // Emulator should not handle ack from native stream.
+ EXPECT_FALSE(emulator()->HandleTouchEventAck(
+ event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS));
+ }
+
+ void DisableSynchronousTouchAck() { ack_touches_synchronously_ = false; }
+
private:
scoped_ptr<TouchEmulator> emulator_;
std::vector<WebInputEvent::Type> forwarded_events_;
@@ -191,8 +256,10 @@ class TouchEmulatorTest : public testing::Test,
double event_time_delta_seconds_;
bool shift_pressed_;
bool mouse_pressed_;
+ bool ack_touches_synchronously_;
int last_mouse_x_;
int last_mouse_y_;
+ std::vector<WebTouchEvent> touch_events_to_ack_;
base::MessageLoopForUI message_loop_;
};
@@ -263,6 +330,30 @@ TEST_F(TouchEmulatorTest, Pinch) {
EXPECT_EQ("TouchEnd GestureScrollEnd", ExpectedEvents());
}
+TEST_F(TouchEmulatorTest, CancelWithDelayedAck) {
+ DisableSynchronousTouchAck();
+
+ // Simulate a sequence that is interrupted by |CancelTouch()|.
+ MouseDown(100, 200);
+ EXPECT_EQ("TouchStart", ExpectedEvents());
+ MouseDrag(200, 200);
+ EXPECT_EQ("TouchMove", ExpectedEvents());
+ emulator()->CancelTouch();
+ EXPECT_EQ("TouchCancel", ExpectedEvents());
+ // The mouse up should have no effect as the sequence was already cancelled.
+ MouseUp(400, 200);
+ EXPECT_EQ("", ExpectedEvents());
+
+ // Simulate a sequence that fully completes before |CancelTouch()|.
+ MouseDown(100, 200);
+ EXPECT_EQ("TouchStart", ExpectedEvents());
+ MouseUp(100, 200);
+ EXPECT_EQ("TouchEnd", ExpectedEvents());
+ // |CancelTouch| should have no effect as the sequence was already terminated.
+ emulator()->CancelTouch();
+ EXPECT_EQ("", ExpectedEvents());
+}
+
TEST_F(TouchEmulatorTest, DisableAndReenable) {
MouseDown(100, 200);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
@@ -282,7 +373,7 @@ TEST_F(TouchEmulatorTest, DisableAndReenable) {
MouseMove(300, 300);
EXPECT_EQ("", ExpectedEvents());
- emulator()->Enable(true /* allow_pinch */);
+ emulator()->Enable();
MouseDown(300, 300);
EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
MouseDrag(300, 400);
@@ -342,8 +433,90 @@ TEST_F(TouchEmulatorTest, MouseWheel) {
emulator()->Disable();
EXPECT_EQ("TouchCancel GestureTapCancel", ExpectedEvents());
EXPECT_TRUE(SendMouseWheelEvent());
- emulator()->Enable(true /* allow_pinch */);
+ emulator()->Enable();
EXPECT_TRUE(SendMouseWheelEvent());
}
+TEST_F(TouchEmulatorTest, MultipleTouchStreams) {
+ // Native stream should be blocked while emulated is active.
+ MouseMove(100, 200);
+ EXPECT_EQ("", ExpectedEvents());
+ MouseDown(100, 200);
+ EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
+ EXPECT_FALSE(TouchStart(10, 10, true));
+ EXPECT_FALSE(TouchMove(20, 20, true));
+ MouseUp(200, 200);
+ EXPECT_EQ(
+ "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
+ " TouchEnd GestureScrollEnd",
+ ExpectedEvents());
+ EXPECT_FALSE(TouchEnd(20, 20, true));
+
+ // Emulated stream should be blocked while native is active.
+ EXPECT_TRUE(TouchStart(10, 10, true));
+ EXPECT_TRUE(TouchMove(20, 20, true));
+ MouseDown(300, 200);
+ EXPECT_EQ("", ExpectedEvents());
+ // Re-enabling in the middle of a touch sequence should not affect this.
+ emulator()->Disable();
+ emulator()->Enable();
+ MouseDrag(300, 300);
+ EXPECT_EQ("", ExpectedEvents());
+ MouseUp(300, 300);
+ EXPECT_EQ("", ExpectedEvents());
+ EXPECT_TRUE(TouchEnd(20, 20, true));
+ EXPECT_EQ("", ExpectedEvents());
+
+ // Late ack for TouchEnd should not mess things up.
+ EXPECT_TRUE(TouchStart(10, 10, false));
+ EXPECT_TRUE(TouchMove(20, 20, false));
+ emulator()->Disable();
+ EXPECT_TRUE(TouchEnd(20, 20, false));
+ EXPECT_TRUE(TouchStart(30, 30, false));
+ AckOldestTouchEvent(); // TouchStart.
+ emulator()->Enable();
+ AckOldestTouchEvent(); // TouchMove.
+ AckOldestTouchEvent(); // TouchEnd.
+ MouseDown(300, 200);
+ EXPECT_EQ("", ExpectedEvents());
+ MouseDrag(300, 300);
+ EXPECT_EQ("", ExpectedEvents());
+ MouseUp(300, 300);
+ EXPECT_EQ("", ExpectedEvents());
+ AckOldestTouchEvent(); // TouchStart.
+ MouseDown(300, 200);
+ EXPECT_EQ("", ExpectedEvents());
+ EXPECT_TRUE(TouchMove(30, 40, true));
+ EXPECT_TRUE(TouchEnd(30, 40, true));
+ MouseUp(300, 200);
+ EXPECT_EQ("", ExpectedEvents());
+
+ // Emulation should be back to normal.
+ MouseDown(100, 200);
+ EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
+ MouseUp(200, 200);
+ EXPECT_EQ(
+ "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
+ " TouchEnd GestureScrollEnd",
+ ExpectedEvents());
+}
+
+TEST_F(TouchEmulatorTest, MultipleTouchStreamsLateEnable) {
+ // Enabling in the middle of native touch sequence should be handled.
+ // Send artificial late TouchEnd ack, like it is the first thing emulator
+ // does see.
+ WebTouchEvent event = MakeTouchEvent(
+ WebInputEvent::TouchEnd, WebTouchPoint::StateReleased, 10, 10);
+ EXPECT_FALSE(emulator()->HandleTouchEventAck(
+ event, INPUT_EVENT_ACK_STATE_CONSUMED));
+
+ MouseDown(100, 200);
+ EXPECT_EQ("TouchStart GestureTapDown", ExpectedEvents());
+ MouseUp(200, 200);
+ EXPECT_EQ(
+ "TouchMove GestureTapCancel GestureScrollBegin GestureScrollUpdate"
+ " TouchEnd GestureScrollEnd",
+ ExpectedEvents());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.cc b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
index bbac01c3ebf..fa109dedddf 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
@@ -69,15 +69,28 @@ class TouchEventQueue::TouchTimeoutHandler {
timeout_delay_(timeout_delay),
pending_ack_state_(PENDING_ACK_NONE),
timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
- base::Unretained(this))) {
+ base::Unretained(this))),
+ enabled_(true),
+ enabled_for_current_sequence_(false) {
DCHECK(timeout_delay != base::TimeDelta());
}
~TouchTimeoutHandler() {}
- void Start(const TouchEventWithLatencyInfo& event) {
+ void StartIfNecessary(const TouchEventWithLatencyInfo& event) {
DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
- DCHECK(ShouldTouchTriggerTimeout(event.event));
+ if (!enabled_)
+ return;
+
+ if (!ShouldTouchTriggerTimeout(event.event))
+ return;
+
+ if (WebTouchEventTraits::IsTouchSequenceStart(event.event))
+ enabled_for_current_sequence_ = true;
+
+ if (!enabled_for_current_sequence_)
+ return;
+
timeout_event_ = event;
timeout_monitor_.Restart(timeout_delay_);
}
@@ -85,6 +98,8 @@ class TouchEventQueue::TouchTimeoutHandler {
bool ConfirmTouchEvent(InputEventAckState ack_result) {
switch (pending_ack_state_) {
case PENDING_ACK_NONE:
+ if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
+ enabled_for_current_sequence_ = false;
timeout_monitor_.Stop();
return false;
case PENDING_ACK_ORIGINAL_EVENT:
@@ -95,7 +110,8 @@ class TouchEventQueue::TouchTimeoutHandler {
touch_queue_->SendTouchEventImmediately(cancel_event);
} else {
SetPendingAckState(PENDING_ACK_NONE);
- touch_queue_->UpdateTouchAckStates(timeout_event_.event, ack_result);
+ touch_queue_->UpdateTouchConsumerStates(timeout_event_.event,
+ ack_result);
}
return true;
case PENDING_ACK_CANCEL_EVENT:
@@ -109,19 +125,29 @@ class TouchEventQueue::TouchTimeoutHandler {
return HasTimeoutEvent();
}
- bool IsTimeoutTimerRunning() const {
- return timeout_monitor_.IsRunning();
- }
+ void SetEnabled(bool enabled) {
+ if (enabled_ == enabled)
+ return;
- void Reset() {
- pending_ack_state_ = PENDING_ACK_NONE;
- timeout_monitor_.Stop();
- }
+ enabled_ = enabled;
- void set_timeout_delay(base::TimeDelta timeout_delay) {
- timeout_delay_ = timeout_delay;
+ if (enabled_)
+ return;
+
+ enabled_for_current_sequence_ = false;
+ // Only reset the |timeout_handler_| if the timer is running and has not
+ // yet timed out. This ensures that an already timed out sequence is
+ // properly flushed by the handler.
+ if (IsTimeoutTimerRunning()) {
+ pending_ack_state_ = PENDING_ACK_NONE;
+ timeout_monitor_.Stop();
+ }
}
+ bool IsTimeoutTimerRunning() const { return timeout_monitor_.IsRunning(); }
+
+ bool enabled() const { return enabled_; }
+
private:
enum PendingAckState {
PENDING_ACK_NONE,
@@ -184,6 +210,9 @@ class TouchEventQueue::TouchTimeoutHandler {
// Provides timeout-based callback behavior.
TimeoutMonitor timeout_monitor_;
+
+ bool enabled_;
+ bool enabled_for_current_sequence_;
};
// Provides touchmove slop suppression for a single touch that remains within
@@ -193,9 +222,14 @@ class TouchEventQueue::TouchTimeoutHandler {
class TouchEventQueue::TouchMoveSlopSuppressor {
public:
TouchMoveSlopSuppressor(double slop_suppression_length_dips)
- : slop_suppression_length_dips_squared_(slop_suppression_length_dips *
- slop_suppression_length_dips),
- suppressing_touchmoves_(false) {}
+ : slop_suppression_length_dips_squared_(0),
+ suppressing_touchmoves_(false) {
+ if (slop_suppression_length_dips) {
+ slop_suppression_length_dips += kSlopEpsilon;
+ slop_suppression_length_dips_squared_ =
+ slop_suppression_length_dips * slop_suppression_length_dips;
+ }
+ }
bool FilterEvent(const WebTouchEvent& event) {
if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
@@ -248,15 +282,9 @@ class TouchEventQueue::TouchMoveSlopSuppressor {
// the Client receives the event with their original timestamp.
class CoalescedWebTouchEvent {
public:
- // Events for which |async| is true will not be ack'ed to the client after the
- // corresponding ack is received following dispatch.
- CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, bool async)
- : coalesced_event_(event) {
- if (async)
- coalesced_event_.event.cancelable = false;
- else
- events_to_ack_.push_back(event);
-
+ CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event,
+ bool suppress_client_ack)
+ : coalesced_event_(event), suppress_client_ack_(suppress_client_ack) {
TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventQueue::QueueEvent", this);
}
@@ -268,42 +296,48 @@ class CoalescedWebTouchEvent {
// the event was coalesced.
bool CoalesceEventIfPossible(
const TouchEventWithLatencyInfo& event_with_latency) {
- if (!WillDispatchAckToClient())
+ if (suppress_client_ack_)
return false;
if (!coalesced_event_.CanCoalesceWith(event_with_latency))
return false;
+ // Addition of the first event to |uncoaleseced_events_to_ack_| is deferred
+ // until the first coalesced event, optimizing the (common) case where the
+ // event is not coalesced at all.
+ if (uncoaleseced_events_to_ack_.empty())
+ uncoaleseced_events_to_ack_.push_back(coalesced_event_);
+
TRACE_EVENT_INSTANT0(
"input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD);
coalesced_event_.CoalesceWith(event_with_latency);
- events_to_ack_.push_back(event_with_latency);
+ uncoaleseced_events_to_ack_.push_back(event_with_latency);
+ DCHECK_GE(uncoaleseced_events_to_ack_.size(), 2U);
return true;
}
- void UpdateLatencyInfoForAck(const ui::LatencyInfo& renderer_latency_info) {
- if (!WillDispatchAckToClient())
- return;
-
- for (WebTouchEventWithLatencyList::iterator iter = events_to_ack_.begin(),
- end = events_to_ack_.end();
- iter != end;
- ++iter) {
- iter->latency.AddNewLatencyFrom(renderer_latency_info);
- }
- }
-
void DispatchAckToClient(InputEventAckState ack_result,
+ const ui::LatencyInfo* optional_latency_info,
TouchEventQueueClient* client) {
DCHECK(client);
- if (!WillDispatchAckToClient())
+ if (suppress_client_ack_)
return;
- for (WebTouchEventWithLatencyList::const_iterator
- iter = events_to_ack_.begin(),
- end = events_to_ack_.end();
+ if (uncoaleseced_events_to_ack_.empty()) {
+ if (optional_latency_info)
+ coalesced_event_.latency.AddNewLatencyFrom(*optional_latency_info);
+ client->OnTouchEventAck(coalesced_event_, ack_result);
+ return;
+ }
+
+ DCHECK_GE(uncoaleseced_events_to_ack_.size(), 2U);
+ for (WebTouchEventWithLatencyList::iterator
+ iter = uncoaleseced_events_to_ack_.begin(),
+ end = uncoaleseced_events_to_ack_.end();
iter != end;
++iter) {
+ if (optional_latency_info)
+ iter->latency.AddNewLatencyFrom(*optional_latency_info);
client->OnTouchEventAck(*iter, ack_result);
}
}
@@ -313,22 +347,22 @@ class CoalescedWebTouchEvent {
}
private:
- bool WillDispatchAckToClient() const { return !events_to_ack_.empty(); }
-
// This is the event that is forwarded to the renderer.
TouchEventWithLatencyInfo coalesced_event_;
// This is the list of the original events that were coalesced, each requiring
// future ack dispatch to the client.
+ // Note that this will be empty if no coalescing has occurred.
typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
- WebTouchEventWithLatencyList events_to_ack_;
+ WebTouchEventWithLatencyList uncoaleseced_events_to_ack_;
+
+ bool suppress_client_ack_;
DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
};
TouchEventQueue::Config::Config()
: touchmove_slop_suppression_length_dips(0),
- touchmove_slop_suppression_region_includes_boundary(true),
touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT),
touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)),
touch_ack_timeout_supported(false) {
@@ -339,19 +373,16 @@ TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
: client_(client),
dispatching_touch_ack_(NULL),
dispatching_touch_(false),
- touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT),
- ack_timeout_enabled_(config.touch_ack_timeout_supported),
+ has_handlers_(true),
+ drop_remaining_touches_in_sequence_(false),
touchmove_slop_suppressor_(new TouchMoveSlopSuppressor(
- config.touchmove_slop_suppression_length_dips +
- (config.touchmove_slop_suppression_region_includes_boundary
- ? kSlopEpsilon
- : -kSlopEpsilon))),
+ config.touchmove_slop_suppression_length_dips)),
send_touch_events_async_(false),
needs_async_touchmove_for_outer_slop_region_(false),
last_sent_touch_timestamp_sec_(0),
touch_scrolling_mode_(config.touch_scrolling_mode) {
DCHECK(client);
- if (ack_timeout_enabled_) {
+ if (config.touch_ack_timeout_supported) {
timeout_handler_.reset(
new TouchTimeoutHandler(this, config.touch_ack_timeout_delay));
}
@@ -411,11 +442,6 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
if (touch_queue_.empty())
return;
- if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED &&
- touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT) {
- touch_filtering_state_ = FORWARD_ALL_TOUCHES;
- }
-
PopTouchEventToClient(ack_result, latency_info);
TryForwardNextEventToRenderer();
}
@@ -446,19 +472,8 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
DCHECK(!empty());
DCHECK(!dispatching_touch_);
- DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES);
TouchEventWithLatencyInfo touch = touch_queue_.front()->coalesced_event();
- if (WebTouchEventTraits::IsTouchSequenceStart(touch.event)) {
- touch_filtering_state_ =
- ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT
- : FORWARD_ALL_TOUCHES;
- touch_ack_states_.clear();
- send_touch_events_async_ = false;
- touch_sequence_start_position_ =
- gfx::PointF(touch.event.touches[0].position);
- }
-
if (send_touch_events_async_ &&
touch.event.type == WebInputEvent::TouchMove) {
// Throttling touchmove's in a continuous touchmove stream while scrolling
@@ -503,7 +518,8 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
if (pending_async_touchmove_->CanCoalesceWith(touch)) {
pending_async_touchmove_->CoalesceWith(touch);
pending_async_touchmove_->event.cancelable = !send_touch_events_async_;
- touch = *pending_async_touchmove_.Pass();
+ touch = *pending_async_touchmove_;
+ pending_async_touchmove_.reset();
} else {
scoped_ptr<TouchEventWithLatencyInfo> async_move =
pending_async_touchmove_.Pass();
@@ -524,47 +540,43 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
// the touch timeout should not be started.
base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
SendTouchEventImmediately(touch);
- if (dispatching_touch_ &&
- touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT &&
- ShouldTouchTriggerTimeout(touch.event)) {
- DCHECK(timeout_handler_);
- timeout_handler_->Start(touch);
- }
+ if (dispatching_touch_ && timeout_handler_)
+ timeout_handler_->StartIfNecessary(touch);
}
void TouchEventQueue::OnGestureScrollEvent(
const GestureEventWithLatencyInfo& gesture_event) {
- if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin)
- return;
-
- if (touch_filtering_state_ != DROP_ALL_TOUCHES &&
- touch_filtering_state_ != DROP_TOUCHES_IN_SEQUENCE) {
- DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves())
- << "The renderer should be offered a touchmove before scrolling begins";
- }
-
- if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) {
- if (touch_filtering_state_ != DROP_ALL_TOUCHES &&
- touch_filtering_state_ != DROP_TOUCHES_IN_SEQUENCE) {
+ if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) {
+ if (!touch_consumer_states_.is_empty() &&
+ !drop_remaining_touches_in_sequence_) {
+ DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves())
+ << "A touch handler should be offered a touchmove before scrolling.";
+ }
+ if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE &&
+ !drop_remaining_touches_in_sequence_ &&
+ touch_consumer_states_.is_empty()) {
// If no touch points have a consumer, prevent all subsequent touch events
// received during the scroll from reaching the renderer. This ensures
// that the first touchstart the renderer sees in any given sequence can
// always be preventDefault'ed (cancelable == true).
// TODO(jdduke): Revisit if touchstarts during scroll are made cancelable.
- if (touch_ack_states_.empty() ||
- AllTouchAckStatesHaveState(
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)) {
- touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
- return;
- }
+ drop_remaining_touches_in_sequence_ = true;
+ }
+
+ if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) {
+ needs_async_touchmove_for_outer_slop_region_ = true;
+ pending_async_touchmove_.reset();
}
- pending_async_touchmove_.reset();
- send_touch_events_async_ = true;
- needs_async_touchmove_for_outer_slop_region_ = true;
return;
}
+ if (gesture_event.event.type != blink::WebInputEvent::GestureScrollUpdate)
+ return;
+
+ if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE)
+ send_touch_events_async_ = true;
+
if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL)
return;
@@ -575,10 +587,10 @@ void TouchEventQueue::OnGestureScrollEvent(
if (!dispatching_touch_ack_)
return;
- if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE)
+ if (drop_remaining_touches_in_sequence_)
return;
- touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
+ drop_remaining_touches_in_sequence_ = true;
// Fake a TouchCancel to cancel the touch points of the touch event
// that is currently being acked.
@@ -614,27 +626,7 @@ void TouchEventQueue::OnGestureEventAck(
void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
DCHECK(!dispatching_touch_ack_);
DCHECK(!dispatching_touch_);
-
- if (has_handlers) {
- if (touch_filtering_state_ == DROP_ALL_TOUCHES) {
- // If no touch handler was previously registered, ensure that we don't
- // send a partial touch sequence to the renderer.
- DCHECK(touch_queue_.empty());
- touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
- }
- } else {
- // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch
- // state tracking and/or touch-action filtering (e.g., if the touch handler
- // was removed mid-sequence), crbug.com/375940.
- touch_filtering_state_ = DROP_ALL_TOUCHES;
- pending_async_touchmove_.reset();
- if (timeout_handler_)
- timeout_handler_->Reset();
- if (!touch_queue_.empty())
- ProcessTouchAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, LatencyInfo());
- // As there is no touch handler, ack'ing the event should flush the queue.
- DCHECK(touch_queue_.empty());
- }
+ has_handlers_ = has_handlers;
}
bool TouchEventQueue::IsPendingAckTouchStart() const {
@@ -648,25 +640,12 @@ bool TouchEventQueue::IsPendingAckTouchStart() const {
}
void TouchEventQueue::SetAckTimeoutEnabled(bool enabled) {
- // The timeout handler is valid only if explicitly supported in the config.
- if (!timeout_handler_)
- return;
-
- if (ack_timeout_enabled_ == enabled)
- return;
-
- ack_timeout_enabled_ = enabled;
-
- if (enabled)
- return;
+ if (timeout_handler_)
+ timeout_handler_->SetEnabled(enabled);
+}
- if (touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT)
- touch_filtering_state_ = FORWARD_ALL_TOUCHES;
- // Only reset the |timeout_handler_| if the timer is running and has not yet
- // timed out. This ensures that an already timed out sequence is properly
- // flushed by the handler.
- if (timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning())
- timeout_handler_->Reset();
+bool TouchEventQueue::IsAckTimeoutEnabled() const {
+ return timeout_handler_ && timeout_handler_->enabled();
}
bool TouchEventQueue::HasPendingAsyncTouchMoveForTesting() const {
@@ -686,36 +665,34 @@ void TouchEventQueue::FlushQueue() {
DCHECK(!dispatching_touch_ack_);
DCHECK(!dispatching_touch_);
pending_async_touchmove_.reset();
- if (touch_filtering_state_ != DROP_ALL_TOUCHES)
- touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
+ drop_remaining_touches_in_sequence_ = true;
while (!touch_queue_.empty())
PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
}
void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) {
- AckTouchEventToClient(ack_result, PopTouchEvent());
+ AckTouchEventToClient(ack_result, PopTouchEvent(), NULL);
}
void TouchEventQueue::PopTouchEventToClient(
InputEventAckState ack_result,
const LatencyInfo& renderer_latency_info) {
- scoped_ptr<CoalescedWebTouchEvent> acked_event = PopTouchEvent();
- acked_event->UpdateLatencyInfoForAck(renderer_latency_info);
- AckTouchEventToClient(ack_result, acked_event.Pass());
+ AckTouchEventToClient(ack_result, PopTouchEvent(), &renderer_latency_info);
}
void TouchEventQueue::AckTouchEventToClient(
InputEventAckState ack_result,
- scoped_ptr<CoalescedWebTouchEvent> acked_event) {
+ scoped_ptr<CoalescedWebTouchEvent> acked_event,
+ const ui::LatencyInfo* optional_latency_info) {
DCHECK(acked_event);
DCHECK(!dispatching_touch_ack_);
- UpdateTouchAckStates(acked_event->coalesced_event().event, ack_result);
+ UpdateTouchConsumerStates(acked_event->coalesced_event().event, ack_result);
// Note that acking the touch-event may result in multiple gestures being sent
// to the renderer, or touch-events being queued.
base::AutoReset<const CoalescedWebTouchEvent*> dispatching_touch_ack(
&dispatching_touch_ack_, acked_event.get());
- acked_event->DispatchAckToClient(ack_result, client_);
+ acked_event->DispatchAckToClient(ack_result, optional_latency_info, client_);
}
scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() {
@@ -748,19 +725,25 @@ TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
if (touchmove_slop_suppressor_->FilterEvent(event))
return ACK_WITH_NOT_CONSUMED;
- if (touch_filtering_state_ == DROP_ALL_TOUCHES)
- return ACK_WITH_NO_CONSUMER_EXISTS;
+ if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
+ touch_consumer_states_.clear();
+ send_touch_events_async_ = false;
+ pending_async_touchmove_.reset();
+ touch_sequence_start_position_ = gfx::PointF(event.touches[0].position);
+ drop_remaining_touches_in_sequence_ = false;
+ if (!has_handlers_) {
+ drop_remaining_touches_in_sequence_ = true;
+ return ACK_WITH_NO_CONSUMER_EXISTS;
+ }
+ }
- if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE &&
+ if (drop_remaining_touches_in_sequence_ &&
event.type != WebInputEvent::TouchCancel) {
- if (WebTouchEventTraits::IsTouchSequenceStart(event))
- return FORWARD_TO_RENDERER;
return ACK_WITH_NO_CONSUMER_EXISTS;
}
- // Touch press events should always be forwarded to the renderer.
if (event.type == WebInputEvent::TouchStart)
- return FORWARD_TO_RENDERER;
+ return has_handlers_ ? FORWARD_TO_RENDERER : ACK_WITH_NO_CONSUMER_EXISTS;
for (unsigned int i = 0; i < event.touchesLength; ++i) {
const WebTouchPoint& point = event.touches[i];
@@ -768,22 +751,15 @@ TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
if (point.state == WebTouchPoint::StateStationary)
continue;
- if (touch_ack_states_.count(point.id) > 0) {
- if (touch_ack_states_.find(point.id)->second !=
- INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
- return FORWARD_TO_RENDERER;
- } else {
- // If the ACK status of a point is unknown, then the event should be
- // forwarded to the renderer.
+ if (touch_consumer_states_.has_bit(point.id))
return FORWARD_TO_RENDERER;
- }
}
return ACK_WITH_NO_CONSUMER_EXISTS;
}
-void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event,
- InputEventAckState ack_result) {
+void TouchEventQueue::UpdateTouchConsumerStates(const WebTouchEvent& event,
+ InputEventAckState ack_result) {
// Update the ACK status for each touch point in the ACKed event.
if (event.type == WebInputEvent::TouchEnd ||
event.type == WebInputEvent::TouchCancel) {
@@ -792,31 +768,19 @@ void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event,
const WebTouchPoint& point = event.touches[i];
if (point.state == WebTouchPoint::StateReleased ||
point.state == WebTouchPoint::StateCancelled)
- touch_ack_states_.erase(point.id);
+ touch_consumer_states_.clear_bit(point.id);
}
} else if (event.type == WebInputEvent::TouchStart) {
for (unsigned i = 0; i < event.touchesLength; ++i) {
const WebTouchPoint& point = event.touches[i];
- if (point.state == WebTouchPoint::StatePressed)
- touch_ack_states_[point.id] = ack_result;
+ if (point.state == WebTouchPoint::StatePressed) {
+ if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
+ touch_consumer_states_.mark_bit(point.id);
+ else
+ touch_consumer_states_.clear_bit(point.id);
+ }
}
}
}
-bool TouchEventQueue::AllTouchAckStatesHaveState(
- InputEventAckState ack_state) const {
- if (touch_ack_states_.empty())
- return false;
-
- for (TouchPointAckStates::const_iterator iter = touch_ack_states_.begin(),
- end = touch_ack_states_.end();
- iter != end;
- ++iter) {
- if (iter->second != ack_state)
- return false;
- }
-
- return true;
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue.h b/chromium/content/browser/renderer_host/input/touch_event_queue.h
index ecb8fe83b40..3bdab903750 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.h
@@ -14,6 +14,7 @@
#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/gesture_detection/bitset_32.h"
#include "ui/gfx/geometry/point_f.h"
namespace content {
@@ -62,11 +63,6 @@ class CONTENT_EXPORT TouchEventQueue {
// Defaults to 0 (disabled).
double touchmove_slop_suppression_length_dips;
- // Whether the touchmove slop suppression region is boundary inclusive.
- // Defaults to true.
- // TODO(jdduke): Remove when unified GR enabled, crbug.com/332418.
- bool touchmove_slop_suppression_region_includes_boundary;
-
// Determines the type of touch scrolling.
// Defaults to TouchEventQueue:::TOUCH_SCROLLING_MODE_DEFAULT.
TouchEventQueue::TouchScrollingMode touch_scrolling_mode;
@@ -119,6 +115,10 @@ class CONTENT_EXPORT TouchEventQueue {
// it will take effect only for the following touch sequence.
void SetAckTimeoutEnabled(bool enabled);
+ bool IsAckTimeoutEnabled() const;
+
+ bool IsForwardingTouches();
+
bool empty() const WARN_UNUSED_RESULT {
return touch_queue_.empty();
}
@@ -127,13 +127,7 @@ class CONTENT_EXPORT TouchEventQueue {
return touch_queue_.size();
}
- bool ack_timeout_enabled() const {
- return ack_timeout_enabled_;
- }
-
- bool has_handlers() const {
- return touch_filtering_state_ != DROP_ALL_TOUCHES;
- }
+ bool has_handlers() const { return has_handlers_; }
private:
class TouchTimeoutHandler;
@@ -165,9 +159,11 @@ class CONTENT_EXPORT TouchEventQueue {
void PopTouchEventToClient(InputEventAckState ack_result,
const ui::LatencyInfo& renderer_latency_info);
- // Ack all coalesced events in |acked_event| to the client with |ack_result|.
+ // Ack all coalesced events in |acked_event| to the client with |ack_result|,
+ // updating the acked events with |optional_latency_info| if it exists.
void AckTouchEventToClient(InputEventAckState ack_result,
- scoped_ptr<CoalescedWebTouchEvent> acked_event);
+ scoped_ptr<CoalescedWebTouchEvent> acked_event,
+ const ui::LatencyInfo* optional_latency_info);
// Safely pop the head of the queue.
scoped_ptr<CoalescedWebTouchEvent> PopTouchEvent();
@@ -184,10 +180,8 @@ class CONTENT_EXPORT TouchEventQueue {
// has no touch handler.
PreFilterResult FilterBeforeForwarding(const blink::WebTouchEvent& event);
void ForwardToRenderer(const TouchEventWithLatencyInfo& event);
- void UpdateTouchAckStates(const blink::WebTouchEvent& event,
- InputEventAckState ack_result);
- bool AllTouchAckStatesHaveState(InputEventAckState ack_state) const;
-
+ void UpdateTouchConsumerStates(const blink::WebTouchEvent& event,
+ InputEventAckState ack_result);
// Handles touch event forwarding and ack'ed event dispatch.
TouchEventQueueClient* client_;
@@ -195,9 +189,11 @@ class CONTENT_EXPORT TouchEventQueue {
typedef std::deque<CoalescedWebTouchEvent*> TouchQueue;
TouchQueue touch_queue_;
- // Maintain the ACK status for each touch point.
- typedef std::map<int, InputEventAckState> TouchPointAckStates;
- TouchPointAckStates touch_ack_states_;
+ // Maps whether each active pointer has a consumer (i.e., a touch point has a
+ // valid consumer iff |touch_consumer_states[pointer.id]| is true.).
+ // TODO(jdduke): Consider simply tracking whether *any* touchstart had a
+ // consumer, crbug.com/416497.
+ ui::BitSet32 touch_consumer_states_;
// Position of the first touch in the most recent sequence forwarded to the
// client.
@@ -212,18 +208,18 @@ class CONTENT_EXPORT TouchEventQueue {
// ack after forwarding a touch event to the client.
bool dispatching_touch_;
- enum TouchFilteringState {
- FORWARD_ALL_TOUCHES, // Don't filter at all - the default.
- FORWARD_TOUCHES_UNTIL_TIMEOUT, // Don't filter unless we get an ACK timeout.
- DROP_TOUCHES_IN_SEQUENCE, // Filter all events until a new touch
- // sequence is received.
- DROP_ALL_TOUCHES, // Filter all events, e.g., no touch handler.
- TOUCH_FILTERING_STATE_DEFAULT = FORWARD_ALL_TOUCHES,
- };
- TouchFilteringState touch_filtering_state_;
+ // Whether the renderer has at least one touch handler.
+ bool has_handlers_;
+
+ // Whether to allow any remaining touches for the current sequence. Note that
+ // this is a stricter condition than an empty |touch_consumer_states_|, as it
+ // also prevents forwarding of touchstart events for new pointers in the
+ // current sequence. This is only used when the event is synthetically
+ // cancelled after a touch timeout, or after a scroll event when the
+ // mode is TOUCH_SCROLLING_MODE_TOUCHCANCEL.
+ bool drop_remaining_touches_in_sequence_;
// Optional handler for timed-out touch event acks.
- bool ack_timeout_enabled_;
scoped_ptr<TouchTimeoutHandler> timeout_handler_;
// Suppression of TouchMove's within a slop region when a sequence has not yet
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
index 06a3a9f40f3..fcd5ce8d07b 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
@@ -35,30 +35,28 @@ class TouchEventQueueTest : public testing::Test,
acked_event_count_(0),
last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN),
slop_length_dips_(0),
- slop_includes_boundary_(true),
touch_scrolling_mode_(TouchEventQueue::TOUCH_SCROLLING_MODE_DEFAULT) {}
- virtual ~TouchEventQueueTest() {}
+ ~TouchEventQueueTest() override {}
// testing::Test
- virtual void SetUp() OVERRIDE { ResetQueueWithConfig(CreateConfig()); }
+ void SetUp() override { ResetQueueWithConfig(CreateConfig()); }
- virtual void TearDown() OVERRIDE {
- queue_.reset();
- }
+ void TearDown() override { queue_.reset(); }
// TouchEventQueueClient
- virtual void SendTouchEventImmediately(
- const TouchEventWithLatencyInfo& event) OVERRIDE {
+ void SendTouchEventImmediately(
+ const TouchEventWithLatencyInfo& event) override {
++sent_event_count_;
last_sent_event_ = event.event;
- if (sync_ack_result_)
- SendTouchEventAck(*sync_ack_result_.Pass());
+ if (sync_ack_result_) {
+ auto sync_ack_result = sync_ack_result_.Pass();
+ SendTouchEventAck(*sync_ack_result);
+ }
}
- virtual void OnTouchEventAck(
- const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
++acked_event_count_;
last_acked_event_ = event.event;
last_acked_event_state_ = ack_result;
@@ -81,8 +79,6 @@ class TouchEventQueueTest : public testing::Test,
TouchEventQueue::Config config;
config.touch_scrolling_mode = touch_scrolling_mode_;
config.touchmove_slop_suppression_length_dips = slop_length_dips_;
- config.touchmove_slop_suppression_region_includes_boundary =
- slop_includes_boundary_;
return config;
}
@@ -91,10 +87,8 @@ class TouchEventQueueTest : public testing::Test,
ResetQueueWithConfig(CreateConfig());
}
- void SetUpForTouchMoveSlopTesting(double slop_length_dips,
- bool slop_includes_boundary) {
+ void SetUpForTouchMoveSlopTesting(double slop_length_dips) {
slop_length_dips_ = slop_length_dips;
- slop_includes_boundary_ = slop_includes_boundary;
ResetQueueWithConfig(CreateConfig());
}
@@ -175,6 +169,10 @@ class TouchEventQueueTest : public testing::Test,
touch_event_.timeStampSeconds += seconds;
}
+ void ResetTouchEvent() {
+ touch_event_ = SyntheticWebTouchEvent();
+ }
+
size_t GetAndResetAckedEventCount() {
size_t count = acked_event_count_;
acked_event_count_ = 0;
@@ -197,8 +195,6 @@ class TouchEventQueueTest : public testing::Test,
void SetAckTimeoutDisabled() { queue_->SetAckTimeoutEnabled(false); }
- bool IsTimeoutEnabled() const { return queue_->ack_timeout_enabled(); }
-
bool IsTimeoutRunning() const { return queue_->IsTimeoutRunningForTesting(); }
bool HasPendingAsyncTouchMove() const {
@@ -253,7 +249,6 @@ class TouchEventQueueTest : public testing::Test,
scoped_ptr<WebGestureEvent> followup_gesture_event_;
scoped_ptr<InputEventAckState> sync_ack_result_;
double slop_length_dips_;
- bool slop_includes_boundary_;
TouchEventQueue::TouchScrollingMode touch_scrolling_mode_;
base::MessageLoopForUI message_loop_;
};
@@ -287,9 +282,55 @@ TEST_F(TouchEventQueueTest, Basic) {
EXPECT_TRUE(acked_event().cancelable);
}
-// Tests that the touch-queue is emptied if a page stops listening for touch
-// events.
-TEST_F(TouchEventQueueTest, QueueFlushedWhenHandlersRemoved) {
+// Tests that touch-events with multiple points are queued properly.
+TEST_F(TouchEventQueueTest, BasicMultiTouch) {
+ const size_t kPointerCount = 10;
+ for (float i = 0; i < kPointerCount; ++i)
+ PressTouchPoint(i, i);
+
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(kPointerCount, queued_event_count());
+
+ for (int i = 0; i < static_cast<int>(kPointerCount); ++i)
+ MoveTouchPoint(i, 1.f + i, 2.f + i);
+
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ // All moves should coalesce.
+ EXPECT_EQ(kPointerCount + 1, queued_event_count());
+
+ for (int i = 0; i < static_cast<int>(kPointerCount); ++i)
+ ReleaseTouchPoint(kPointerCount - 1 - i);
+
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(kPointerCount * 2 + 1, queued_event_count());
+
+ // Ack all presses.
+ for (size_t i = 0; i < kPointerCount; ++i)
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ EXPECT_EQ(kPointerCount, GetAndResetAckedEventCount());
+ EXPECT_EQ(kPointerCount, GetAndResetSentEventCount());
+
+ // Ack the coalesced move.
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(kPointerCount, GetAndResetAckedEventCount());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Ack all releases.
+ for (size_t i = 0; i < kPointerCount; ++i)
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ EXPECT_EQ(kPointerCount, GetAndResetAckedEventCount());
+ EXPECT_EQ(kPointerCount - 1, GetAndResetSentEventCount());
+}
+
+// Tests that the touch-queue continues delivering events for an active pointer
+// after all handlers are removed, but acks new pointers immediately as having
+// no consumer.
+TEST_F(TouchEventQueueTest, NoNewTouchesForwardedAfterHandlersRemoved) {
OnHasTouchEventHandlers(true);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(0U, GetAndResetSentEventCount());
@@ -297,32 +338,51 @@ TEST_F(TouchEventQueueTest, QueueFlushedWhenHandlersRemoved) {
// Send a touch-press event.
PressTouchPoint(1, 1);
EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
- ReleaseTouchPoint(0);
-
- // Events will be queued until the first sent event is ack'ed.
- for (int i = 5; i < 15; ++i) {
- PressTouchPoint(1, 1);
- MoveTouchPoint(0, i, i);
- ReleaseTouchPoint(0);
- }
- EXPECT_EQ(32U, queued_event_count());
- EXPECT_EQ(0U, GetAndResetSentEventCount());
+ // Signal that all touch handlers have been removed.
+ OnHasTouchEventHandlers(false);
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(1U, queued_event_count());
- // Receive an ACK for the first touch-event. One of the queued touch-event
- // should be forwarded.
+ // Process the ack for the sent touch, ensuring that it is honored (despite
+ // the touch handler having been removed).
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(31U, queued_event_count());
- EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state());
- // Flush the queue. The touch-event queue should now be emptied, but none of
- // the queued touch-events should be sent to the renderer.
- OnHasTouchEventHandlers(false);
+ // Try forwarding a new pointer. It should be rejected immediately.
+ PressTouchPoint(2, 2);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state());
+
+ // Further events for the pointer without a handler should not be forwarded.
+ MoveTouchPoint(1, 3, 3);
+ ReleaseTouchPoint(1);
+ EXPECT_EQ(2U, GetAndResetAckedEventCount());
EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, acked_event_state());
+
+ // Events for the first pointer, that had a handler, should be forwarded, even
+ // if the renderer reports that no handlers exist.
+ MoveTouchPoint(0, 4, 4);
+ ReleaseTouchPoint(0);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state());
+
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(0U, GetAndResetSentEventCount());
- EXPECT_EQ(31U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, acked_event_state());
}
// Tests that addition of a touch handler during a touch sequence will not cause
@@ -366,14 +426,23 @@ TEST_F(TouchEventQueueTest, ActiveSequenceDroppedWhenHandlersRemoved) {
EXPECT_EQ(0U, GetAndResetAckedEventCount());
EXPECT_EQ(0U, GetAndResetSentEventCount());
- // Touch handle deregistration should flush the queue.
+ // Unregister all touch handlers.
OnHasTouchEventHandlers(false);
- EXPECT_EQ(2U, GetAndResetAckedEventCount());
- EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, queued_event_count());
- // The ack should be ignored as the touch queue is now empty.
- SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ // Repeated registration/unregstration of handlers should have no effect as
+ // we're still awaiting the ack arrival.
+ OnHasTouchEventHandlers(true);
EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+ OnHasTouchEventHandlers(false);
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, queued_event_count());
+
+ // The ack should be flush the queue.
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+ EXPECT_EQ(2U, GetAndResetAckedEventCount());
EXPECT_EQ(0U, queued_event_count());
// Events should be dropped while there is no touch handler.
@@ -397,6 +466,34 @@ TEST_F(TouchEventQueueTest, ActiveSequenceDroppedWhenHandlersRemoved) {
EXPECT_EQ(1U, GetAndResetSentEventCount());
}
+// Tests that removal/addition of a touch handler without any intervening
+// touch activity has no affect on touch forwarding.
+TEST_F(TouchEventQueueTest,
+ ActiveSequenceUnaffectedByRepeatedHandlerRemovalAndAddition) {
+ // Send a touch-press event.
+ PressTouchPoint(1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+
+ // Simulate the case where the touchstart handler removes itself, and adds a
+ // touchmove handler.
+ OnHasTouchEventHandlers(false);
+ OnHasTouchEventHandlers(true);
+
+ // Queue a touch-move event.
+ MoveTouchPoint(0, 5, 5);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // The ack should trigger forwarding of the touchmove, as if no touch
+ // handler registration changes have occurred.
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, queued_event_count());
+}
+
// Tests that touch-events are coalesced properly in the queue.
TEST_F(TouchEventQueueTest, Coalesce) {
// Send a touch-press event.
@@ -405,7 +502,7 @@ TEST_F(TouchEventQueueTest, Coalesce) {
// Send a few touch-move events, followed by a touch-release event. All the
// touch-move events should be coalesced into a single event.
- for (int i = 5; i < 15; ++i)
+ for (float i = 5; i < 15; ++i)
MoveTouchPoint(0, i, i);
EXPECT_EQ(0U, GetAndResetSentEventCount());
@@ -445,7 +542,7 @@ TEST_F(TouchEventQueueTest, SentTouchEventDoesNotCoalesce) {
// Send a few touch-move events, followed by a touch-release event. All the
// touch-move events should be coalesced into a single event.
- for (int i = 5; i < 15; ++i)
+ for (float i = 5; i < 15; ++i)
MoveTouchPoint(0, i, i);
EXPECT_EQ(0U, GetAndResetSentEventCount());
@@ -498,33 +595,23 @@ TEST_F(TouchEventQueueTest, MultiTouch) {
EXPECT_EQ(WebTouchPoint::StateMoved, event.touches[1].state);
}
-// Tests that if a touch-event queue is destroyed in response to a touch-event
-// in the renderer, then there is no crash when the ACK for that touch-event
-// comes back.
-TEST_F(TouchEventQueueTest, AckAfterQueueFlushed) {
- // Send some touch-events to the renderer.
+// Tests that the touch-event queue is robust to redundant acks.
+TEST_F(TouchEventQueueTest, SpuriousAcksIgnored) {
+ // Trigger a spurious ack.
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
+
+ // Send and ack a touch press.
PressTouchPoint(1, 1);
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, queued_event_count());
-
- MoveTouchPoint(0, 10, 10);
- EXPECT_EQ(0U, GetAndResetSentEventCount());
- EXPECT_EQ(2U, queued_event_count());
-
- // Receive an ACK for the press. This should cause the queued touch-move to
- // be sent to the renderer.
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- EXPECT_EQ(1U, queued_event_count());
-
- OnHasTouchEventHandlers(false);
- EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(0U, queued_event_count());
- // Now receive an ACK for the move.
+ // Trigger a spurious ack.
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_EQ(0U, GetAndResetSentEventCount());
- EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetAckedEventCount());
}
// Tests that touch-move events are not sent to the renderer if the preceding
@@ -717,10 +804,10 @@ TEST_F(TouchEventQueueTest, AckWithFollowupEvents) {
// Create a touch event that will be queued synchronously by a touch ack.
// Note, this will be triggered by all subsequent touch acks.
WebTouchEvent followup_event;
- followup_event.type = WebInputEvent::TouchStart;
+ followup_event.type = WebInputEvent::TouchMove;
followup_event.touchesLength = 1;
- followup_event.touches[0].id = 1;
- followup_event.touches[0].state = WebTouchPoint::StatePressed;
+ followup_event.touches[0].id = 0;
+ followup_event.touches[0].state = WebTouchPoint::StateMoved;
SetFollowupEvent(followup_event);
// Receive an ACK for the press. This should cause the followup touch-move to
@@ -859,13 +946,16 @@ TEST_F(TouchEventQueueTest, TouchCancelOnScroll) {
EXPECT_EQ(1U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
+ MoveTouchPoint(0, 30, 15);
+ EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
// Queue another TouchStart.
PressTouchPoint(20, 20);
- EXPECT_EQ(2U, queued_event_count());
+ EXPECT_EQ(3U, queued_event_count());
EXPECT_EQ(0U, GetAndResetSentEventCount());
EXPECT_EQ(WebInputEvent::TouchStart, latest_event().type);
- // GestureScrollBegin inserts a synthetic TouchCancel before the TouchStart.
WebGestureEvent followup_scroll;
followup_scroll.type = WebInputEvent::GestureScrollBegin;
SetFollowupEvent(followup_scroll);
@@ -873,6 +963,16 @@ TEST_F(TouchEventQueueTest, TouchCancelOnScroll) {
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(2U, queued_event_count());
+ EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type);
+
+ // GestureScrollUpdate inserts a synthetic TouchCancel before the TouchStart.
+ followup_scroll.type = WebInputEvent::GestureScrollUpdate;
+ SetFollowupEvent(followup_scroll);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, queued_event_count());
EXPECT_EQ(WebInputEvent::TouchCancel, sent_event().type);
EXPECT_FALSE(sent_event().cancelable);
EXPECT_EQ(WebInputEvent::TouchStart, latest_event().type);
@@ -1146,14 +1246,12 @@ TEST_F(TouchEventQueueTest, NoTouchTimeoutIfDisabledAfterTouchStart) {
// Send the ack immediately. The timeout should not have fired.
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(IsTimeoutRunning());
- EXPECT_TRUE(IsTimeoutEnabled());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
// Now explicitly disable the timeout.
SetAckTimeoutDisabled();
EXPECT_FALSE(IsTimeoutRunning());
- EXPECT_FALSE(IsTimeoutEnabled());
// A TouchMove should not start or trigger the timeout.
MoveTouchPoint(0, 5, 5);
@@ -1174,19 +1272,6 @@ TEST_F(TouchEventQueueTest, NoTouchTimeoutIfAckIsSynchronous) {
EXPECT_FALSE(IsTimeoutRunning());
}
-// Tests that the timeout is disabled if the touch handler disappears.
-TEST_F(TouchEventQueueTest, NoTouchTimeoutIfTouchHandlerRemoved) {
- SetUpForTimeoutTesting(DefaultTouchTimeoutDelay());
-
- // Queue a TouchStart.
- PressTouchPoint(0, 1);
- ASSERT_TRUE(IsTimeoutRunning());
-
- // Unload the touch handler.
- OnHasTouchEventHandlers(false);
- EXPECT_FALSE(IsTimeoutRunning());
-}
-
// Tests that the timeout does not fire if explicitly disabled while an event
// is in-flight.
TEST_F(TouchEventQueueTest, NoTouchTimeoutIfDisabledWhileTimerIsActive) {
@@ -1356,10 +1441,9 @@ TEST_F(TouchEventQueueTest, NoCancelOnTouchTimeoutWithoutConsumer) {
// Tests that TouchMove's are dropped if within the boundary-inclusive slop
// suppression region for an unconsumed TouchStart.
TEST_F(TouchEventQueueTest, TouchMoveSuppressionIncludingSlopBoundary) {
- const double kSlopLengthDips = 10.;
- const double kHalfSlopLengthDips = kSlopLengthDips / 2;
- const bool slop_includes_boundary = true;
- SetUpForTouchMoveSlopTesting(kSlopLengthDips, slop_includes_boundary);
+ const float kSlopLengthDips = 10;
+ const float kHalfSlopLengthDips = kSlopLengthDips / 2;
+ SetUpForTouchMoveSlopTesting(kSlopLengthDips);
// Queue a TouchStart.
PressTouchPoint(0, 0);
@@ -1400,10 +1484,10 @@ TEST_F(TouchEventQueueTest, TouchMoveSuppressionIncludingSlopBoundary) {
// As soon as a TouchMove exceeds the (Euclidean) distance, no more
// TouchMove's should be suppressed.
- const double kFortyFiveDegreeSlopLengthXY =
- kSlopLengthDips * std::sqrt(2.) / 2.;
- MoveTouchPoint(0, kFortyFiveDegreeSlopLengthXY + .2,
- kFortyFiveDegreeSlopLengthXY + .2);
+ const float kFortyFiveDegreeSlopLengthXY =
+ kSlopLengthDips * std::sqrt(2.f) / 2;
+ MoveTouchPoint(0, kFortyFiveDegreeSlopLengthXY + .2f,
+ kFortyFiveDegreeSlopLengthXY + .2f);
EXPECT_EQ(1U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
@@ -1428,7 +1512,7 @@ TEST_F(TouchEventQueueTest, TouchMoveSuppressionIncludingSlopBoundary) {
ASSERT_EQ(0U, queued_event_count());
// The slop region is boundary-inclusive.
- MoveTouchPoint(0, kSlopLengthDips - 1., 0);
+ MoveTouchPoint(0, kSlopLengthDips - 1, 0);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(0U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
@@ -1439,67 +1523,38 @@ TEST_F(TouchEventQueueTest, TouchMoveSuppressionIncludingSlopBoundary) {
EXPECT_EQ(1U, GetAndResetAckedEventCount());
}
-// Tests that TouchMove's are dropped if within the boundary-exclusive slop
-// suppression region for an unconsumed TouchStart.
-TEST_F(TouchEventQueueTest, TouchMoveSuppressionExcludingSlopBoundary) {
- const double kSlopLengthDips = 10.;
- const double kHalfSlopLengthDips = kSlopLengthDips / 2;
- const bool slop_includes_boundary = false;
- SetUpForTouchMoveSlopTesting(kSlopLengthDips, slop_includes_boundary);
+// Tests that TouchMove's are not dropped within the slop suppression region if
+// the touchstart was consumed.
+TEST_F(TouchEventQueueTest, NoTouchMoveSuppressionAfterTouchConsumed) {
+ const float kSlopLengthDips = 10;
+ const float kHalfSlopLengthDips = kSlopLengthDips / 2;
+ SetUpForTouchMoveSlopTesting(kSlopLengthDips);
// Queue a TouchStart.
PressTouchPoint(0, 0);
- SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
ASSERT_EQ(1U, GetAndResetSentEventCount());
ASSERT_EQ(1U, GetAndResetAckedEventCount());
- // TouchMove's within the region should be suppressed.
+ // TouchMove's within the region should not be suppressed, as a touch was
+ // consumed.
MoveTouchPoint(0, 0, kHalfSlopLengthDips);
- EXPECT_EQ(0U, queued_event_count());
- EXPECT_EQ(0U, GetAndResetSentEventCount());
- EXPECT_EQ(1U, GetAndResetAckedEventCount());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, acked_event_state());
-
- MoveTouchPoint(0, kSlopLengthDips - 0.2f, 0);
- EXPECT_EQ(0U, queued_event_count());
- EXPECT_EQ(0U, GetAndResetSentEventCount());
- EXPECT_EQ(1U, GetAndResetAckedEventCount());
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, acked_event_state());
-
- // As soon as a TouchMove reaches the (Euclidean) slop distance, no more
- // TouchMove's should be suppressed.
- MoveTouchPoint(0, kSlopLengthDips, 0);
- EXPECT_EQ(1U, queued_event_count());
- EXPECT_EQ(1U, GetAndResetSentEventCount());
- EXPECT_EQ(0U, GetAndResetAckedEventCount());
- SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, GetAndResetAckedEventCount());
-
- MoveTouchPoint(0, kHalfSlopLengthDips, 0);
EXPECT_EQ(1U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
- SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, GetAndResetAckedEventCount());
}
-// Tests that TouchMove's are not dropped within the slop suppression region if
-// the touchstart was consumed.
-TEST_F(TouchEventQueueTest, NoTouchMoveSuppressionAfterTouchConsumed) {
- const double kSlopLengthDips = 10.;
- const double kHalfSlopLengthDips = kSlopLengthDips / 2;
- const bool slop_includes_boundary = true;
- SetUpForTouchMoveSlopTesting(kSlopLengthDips, slop_includes_boundary);
-
+// Tests that even very small TouchMove's are not suppressed when suppression is
+// disabled.
+TEST_F(TouchEventQueueTest, NoTouchMoveSuppressionIfDisabled) {
// Queue a TouchStart.
PressTouchPoint(0, 0);
- SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
ASSERT_EQ(1U, GetAndResetSentEventCount());
ASSERT_EQ(1U, GetAndResetAckedEventCount());
- // TouchMove's within the region should not be suppressed, as a touch was
- // consumed.
- MoveTouchPoint(0, 0, kHalfSlopLengthDips);
+ // Small TouchMove's should not be suppressed.
+ MoveTouchPoint(0, 0.001f, 0.001f);
EXPECT_EQ(1U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
@@ -1510,9 +1565,7 @@ TEST_F(TouchEventQueueTest, NoTouchMoveSuppressionAfterTouchConsumed) {
TEST_F(TouchEventQueueTest, TouchMoveSuppressionWithDIPScaling) {
const float kSlopLengthPixels = 7.f;
const float kDPIScale = 3.f;
- const bool slop_includes_boundary = true;
- SetUpForTouchMoveSlopTesting(kSlopLengthPixels / kDPIScale,
- slop_includes_boundary);
+ SetUpForTouchMoveSlopTesting(kSlopLengthPixels / kDPIScale);
// Queue a TouchStart.
PressTouchPoint(0, 0);
@@ -1550,10 +1603,9 @@ TEST_F(TouchEventQueueTest, TouchMoveSuppressionWithDIPScaling) {
// Tests that TouchMove's are not dropped if a secondary pointer is present
// during any movement.
TEST_F(TouchEventQueueTest, NoTouchMoveSuppressionAfterMultiTouch) {
- const double kSlopLengthDips = 10.;
- const double kHalfSlopLengthDips = kSlopLengthDips / 2;
- const bool slop_includes_boundary = true;
- SetUpForTouchMoveSlopTesting(kSlopLengthDips, slop_includes_boundary);
+ const float kSlopLengthDips = 10;
+ const float kHalfSlopLengthDips = kSlopLengthDips / 2;
+ SetUpForTouchMoveSlopTesting(kSlopLengthDips);
// Queue a TouchStart.
PressTouchPoint(0, 0);
@@ -1717,8 +1769,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- // Now send the first touch move and associated GestureScrollBegin,
- // but don't ACK the gesture event yet.
+ // Now send the first touch move and associated GestureScrollBegin.
MoveTouchPoint(0, 0, 5);
WebGestureEvent followup_scroll;
followup_scroll.type = WebInputEvent::GestureScrollBegin;
@@ -1726,9 +1777,21 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ SendGestureEventAck(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Send the second touch move and associated GestureScrollUpdate, but don't
+ // ACK the gesture event yet.
+ MoveTouchPoint(0, 0, 50);
+ followup_scroll.type = WebInputEvent::GestureScrollUpdate;
+ SetFollowupEvent(followup_scroll);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
// Now queue a second touchmove and verify it's not (yet) dispatched.
- MoveTouchPoint(0, 0, 10);
+ MoveTouchPoint(0, 0, 100);
+ SetFollowupEvent(followup_scroll);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(HasPendingAsyncTouchMove());
EXPECT_EQ(0U, queued_event_count());
@@ -1737,6 +1800,8 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
// Queuing the final touchend should flush the pending, async touchmove.
ReleaseTouchPoint(0);
+ followup_scroll.type = WebInputEvent::GestureScrollEnd;
+ SetFollowupEvent(followup_scroll);
EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type);
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_FALSE(sent_event().cancelable);
@@ -1758,10 +1823,12 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
EXPECT_EQ(0U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
- // Now mark the scroll as not consumed (which would cause future
- // touchmoves in the active sequence to be sent if there was one).
- SendGestureEventAck(WebInputEvent::GestureScrollBegin,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ // Now mark the scrolls as not consumed (which would cause future touchmoves
+ // in the active sequence to be sent if there was one).
+ SendGestureEventAck(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendGestureEventAck(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
// Start a new touch sequence and verify that throttling has been reset.
// Touch moves after the start of scrolling will again be throttled.
@@ -1770,10 +1837,20 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetAndResetAckedEventCount());
MoveTouchPoint(0, 0, 5);
+ followup_scroll.type = WebInputEvent::GestureScrollBegin;
+ SetFollowupEvent(followup_scroll);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ MoveTouchPoint(0, 0, 5);
+ followup_scroll.type = WebInputEvent::GestureScrollUpdate;
SetFollowupEvent(followup_scroll);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
MoveTouchPoint(0, 0, 10);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_TRUE(HasPendingAsyncTouchMove());
@@ -1993,6 +2070,8 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithTouchCancelAfterAck) {
EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(0U, queued_event_count());
+ SendGestureEvent(WebInputEvent::GestureScrollUpdate);
+
// The async touchmove should be ack'ed immediately, but not forwarded.
// However, because the ack triggers a touchcancel, both the pending touch and
// the queued touchcancel should be flushed.
@@ -2010,7 +2089,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithTouchCancelAfterAck) {
EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(1U, GetAndResetSentEventCount());
- // The ack for the asnc touchmove should not reach the client, as it has
+ // The ack for the async touchmove should not reach the client, as it has
// already been ack'ed.
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(sent_event().cancelable);
@@ -2026,4 +2105,124 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithTouchCancelAfterAck) {
EXPECT_EQ(0U, GetAndResetSentEventCount());
}
+// Ensure that the async touch is fully reset if the touch sequence restarts
+// without properly terminating.
+TEST_F(TouchEventQueueTest, AsyncTouchWithHardTouchStartReset) {
+ SetTouchScrollingMode(TouchEventQueue::TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE);
+
+ PressTouchPoint(0, 0);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Trigger async touchmove dispatch.
+ MoveTouchPoint(0, 1, 1);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ WebGestureEvent followup_scroll;
+ followup_scroll.type = WebInputEvent::GestureScrollBegin;
+ SetFollowupEvent(followup_scroll);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+ SendGestureEvent(WebInputEvent::GestureScrollUpdate);
+
+ // The async touchmove should be immediately ack'ed but delivery is deferred.
+ MoveTouchPoint(0, 2, 2);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
+
+ // The queue should be robust to hard touch restarts with a new touch
+ // sequence. In this case, the deferred async touch should not be flushed
+ // by the new touch sequence.
+ SendGestureEvent(WebInputEvent::GestureScrollEnd);
+ ResetTouchEvent();
+
+ PressTouchPoint(0, 0);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(WebInputEvent::TouchStart, sent_event().type);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+}
+
+TEST_F(TouchEventQueueTest, TouchAbsorptionWithConsumedFirstMove) {
+ SetTouchScrollingMode(TouchEventQueue::TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE);
+
+ // Queue a TouchStart.
+ PressTouchPoint(0, 1);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ MoveTouchPoint(0, 20, 5);
+ SendGestureEvent(blink::WebInputEvent::GestureScrollBegin);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+
+ // Even if the first touchmove event was consumed, subsequent unconsumed
+ // touchmove events should trigger scrolling.
+ MoveTouchPoint(0, 60, 5);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ MoveTouchPoint(0, 20, 5);
+ WebGestureEvent followup_scroll;
+ followup_scroll.type = WebInputEvent::GestureScrollUpdate;
+ SetFollowupEvent(followup_scroll);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendGestureEventAck(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Touch move event is throttled.
+ MoveTouchPoint(0, 60, 5);
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+}
+
+TEST_F(TouchEventQueueTest, UnseenTouchPointerIdsNotForwarded) {
+ SyntheticWebTouchEvent event;
+ event.PressPoint(0, 0);
+ SendTouchEvent(event);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Give the touchmove a previously unseen pointer id; it should not be sent.
+ int press_id = event.touches[0].id;
+ event.MovePoint(0, 1, 1);
+ event.touches[0].id = 7;
+ SendTouchEvent(event);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Give the touchmove a valid id; it should be sent.
+ event.touches[0].id = press_id;
+ SendTouchEvent(event);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Do the same for release.
+ event.ReleasePoint(0);
+ event.touches[0].id = 11;
+ SendTouchEvent(event);
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+
+ // Give the touchmove a valid id; it should be sent.
+ event.touches[0].id = press_id;
+ SendTouchEvent(event);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_handle.cc b/chromium/content/browser/renderer_host/input/touch_handle.cc
new file mode 100644
index 00000000000..acfe3bd70f8
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_handle.cc
@@ -0,0 +1,267 @@
+// Copyright 2014 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 "content/browser/renderer_host/input/touch_handle.h"
+
+#include <cmath>
+
+namespace content {
+
+namespace {
+
+// Maximum duration of a fade sequence.
+const double kFadeDurationMs = 200;
+
+// Maximum amount of travel for a fade sequence. This avoids handle "ghosting"
+// when the handle is moving rapidly while the fade is active.
+const double kFadeDistanceSquared = 20.f * 20.f;
+
+// Avoid using an empty touch rect, as it may fail the intersection test event
+// if it lies within the other rect's bounds.
+const float kMinTouchMajorForHitTesting = 1.f;
+
+// The maximum touch size to use when computing whether a touch point is
+// targetting a touch handle. This is necessary for devices that misreport
+// touch radii, preventing inappropriately largely touch sizes from completely
+// breaking handle dragging behavior.
+const float kMaxTouchMajorForHitTesting = 36.f;
+
+} // namespace
+
+// Responsible for rendering a selection or insertion handle for text editing.
+TouchHandle::TouchHandle(TouchHandleClient* client,
+ TouchHandleOrientation orientation)
+ : drawable_(client->CreateDrawable()),
+ client_(client),
+ orientation_(orientation),
+ deferred_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
+ alpha_(0.f),
+ animate_deferred_fade_(false),
+ enabled_(true),
+ is_visible_(false),
+ is_dragging_(false),
+ is_drag_within_tap_region_(false) {
+ DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
+ drawable_->SetEnabled(enabled_);
+ drawable_->SetOrientation(orientation_);
+ drawable_->SetAlpha(alpha_);
+ drawable_->SetVisible(is_visible_);
+ drawable_->SetFocus(position_);
+}
+
+TouchHandle::~TouchHandle() {
+}
+
+void TouchHandle::SetEnabled(bool enabled) {
+ if (enabled_ == enabled)
+ return;
+ if (!enabled) {
+ EndDrag();
+ EndFade();
+ }
+ enabled_ = enabled;
+ drawable_->SetEnabled(enabled);
+}
+
+void TouchHandle::SetVisible(bool visible, AnimationStyle animation_style) {
+ DCHECK(enabled_);
+ if (is_visible_ == visible)
+ return;
+
+ is_visible_ = visible;
+
+ // Handle repositioning may have been deferred while previously invisible.
+ if (visible)
+ drawable_->SetFocus(position_);
+
+ bool animate = animation_style != ANIMATION_NONE;
+ if (is_dragging_) {
+ animate_deferred_fade_ = animate;
+ return;
+ }
+
+ if (animate)
+ BeginFade();
+ else
+ EndFade();
+}
+
+void TouchHandle::SetPosition(const gfx::PointF& position) {
+ DCHECK(enabled_);
+ if (position_ == position)
+ return;
+ position_ = position;
+ // Suppress repositioning a handle while invisible or fading out to prevent it
+ // from "ghosting" outside the visible bounds. The position will be pushed to
+ // the drawable when the handle regains visibility (see |SetVisible()|).
+ if (is_visible_)
+ drawable_->SetFocus(position_);
+}
+
+void TouchHandle::SetOrientation(TouchHandleOrientation orientation) {
+ DCHECK(enabled_);
+ DCHECK_NE(orientation, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
+ if (is_dragging_) {
+ deferred_orientation_ = orientation;
+ return;
+ }
+ DCHECK_EQ(deferred_orientation_, TOUCH_HANDLE_ORIENTATION_UNDEFINED);
+ if (orientation_ == orientation)
+ return;
+
+ orientation_ = orientation;
+ drawable_->SetOrientation(orientation);
+}
+
+bool TouchHandle::WillHandleTouchEvent(const ui::MotionEvent& event) {
+ if (!enabled_)
+ return false;
+
+ if (!is_dragging_ && event.GetAction() != ui::MotionEvent::ACTION_DOWN)
+ return false;
+
+ switch (event.GetAction()) {
+ case ui::MotionEvent::ACTION_DOWN: {
+ if (!is_visible_)
+ return false;
+ const float touch_size = std::max(
+ kMinTouchMajorForHitTesting,
+ std::min(kMaxTouchMajorForHitTesting, event.GetTouchMajor()));
+ const gfx::RectF touch_rect(event.GetX() - touch_size * .5f,
+ event.GetY() - touch_size * .5f,
+ touch_size,
+ touch_size);
+ if (!drawable_->IntersectsWith(touch_rect))
+ return false;
+ touch_down_position_ = gfx::PointF(event.GetX(), event.GetY());
+ touch_to_focus_offset_ = position_ - touch_down_position_;
+ touch_down_time_ = event.GetEventTime();
+ BeginDrag();
+ } break;
+
+ case ui::MotionEvent::ACTION_MOVE: {
+ gfx::PointF touch_move_position(event.GetX(), event.GetY());
+ if (is_drag_within_tap_region_) {
+ const float tap_slop = client_->GetTapSlop();
+ is_drag_within_tap_region_ =
+ (touch_move_position - touch_down_position_).LengthSquared() <
+ tap_slop * tap_slop;
+ }
+
+ // Note that we signal drag update even if we're inside the tap region,
+ // as there are cases where characters are narrower than the slop length.
+ client_->OnHandleDragUpdate(*this,
+ touch_move_position + touch_to_focus_offset_);
+ } break;
+
+ case ui::MotionEvent::ACTION_UP: {
+ if (is_drag_within_tap_region_ &&
+ (event.GetEventTime() - touch_down_time_) <
+ client_->GetTapTimeout()) {
+ client_->OnHandleTapped(*this);
+ }
+
+ EndDrag();
+ } break;
+
+ case ui::MotionEvent::ACTION_CANCEL:
+ EndDrag();
+ break;
+
+ default:
+ break;
+ };
+ return true;
+}
+
+bool TouchHandle::Animate(base::TimeTicks frame_time) {
+ if (fade_end_time_ == base::TimeTicks())
+ return false;
+
+ DCHECK(enabled_);
+
+ float time_u =
+ 1.f - (fade_end_time_ - frame_time).InMillisecondsF() / kFadeDurationMs;
+ float position_u =
+ (position_ - fade_start_position_).LengthSquared() / kFadeDistanceSquared;
+ float u = std::max(time_u, position_u);
+ SetAlpha(is_visible_ ? u : 1.f - u);
+
+ if (u >= 1.f) {
+ EndFade();
+ return false;
+ }
+
+ return true;
+}
+
+void TouchHandle::BeginDrag() {
+ DCHECK(enabled_);
+ if (is_dragging_)
+ return;
+ EndFade();
+ is_dragging_ = true;
+ is_drag_within_tap_region_ = true;
+ client_->OnHandleDragBegin(*this);
+}
+
+void TouchHandle::EndDrag() {
+ DCHECK(enabled_);
+ if (!is_dragging_)
+ return;
+
+ is_dragging_ = false;
+ is_drag_within_tap_region_ = false;
+ client_->OnHandleDragEnd(*this);
+
+ if (deferred_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED) {
+ TouchHandleOrientation deferred_orientation = deferred_orientation_;
+ deferred_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED;
+ SetOrientation(deferred_orientation);
+ }
+
+ if (animate_deferred_fade_) {
+ BeginFade();
+ } else {
+ // As drawable visibility assignment is deferred while dragging, push the
+ // change by forcing fade completion.
+ EndFade();
+ }
+}
+
+void TouchHandle::BeginFade() {
+ DCHECK(enabled_);
+ DCHECK(!is_dragging_);
+ animate_deferred_fade_ = false;
+ const float target_alpha = is_visible_ ? 1.f : 0.f;
+ if (target_alpha == alpha_) {
+ EndFade();
+ return;
+ }
+
+ drawable_->SetVisible(true);
+ fade_end_time_ = base::TimeTicks::Now() +
+ base::TimeDelta::FromMillisecondsD(
+ kFadeDurationMs * std::abs(target_alpha - alpha_));
+ fade_start_position_ = position_;
+ client_->SetNeedsAnimate();
+}
+
+void TouchHandle::EndFade() {
+ DCHECK(enabled_);
+ animate_deferred_fade_ = false;
+ fade_end_time_ = base::TimeTicks();
+ SetAlpha(is_visible_ ? 1.f : 0.f);
+ drawable_->SetVisible(is_visible_);
+}
+
+void TouchHandle::SetAlpha(float alpha) {
+ alpha = std::max(0.f, std::min(1.f, alpha));
+ if (alpha_ == alpha)
+ return;
+ alpha_ = alpha;
+ drawable_->SetAlpha(alpha);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_handle.h b/chromium/content/browser/renderer_host/input/touch_handle.h
new file mode 100644
index 00000000000..7859febef23
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_handle.h
@@ -0,0 +1,135 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_HANDLE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_HANDLE_H_
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "ui/events/gesture_detection/motion_event.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace content {
+
+class TouchHandle;
+
+enum TouchHandleOrientation {
+ TOUCH_HANDLE_LEFT,
+ TOUCH_HANDLE_CENTER,
+ TOUCH_HANDLE_RIGHT,
+ TOUCH_HANDLE_ORIENTATION_UNDEFINED,
+};
+
+// Interface through which |TouchHandle| delegates rendering-specific duties.
+class CONTENT_EXPORT TouchHandleDrawable {
+ public:
+ virtual ~TouchHandleDrawable() {}
+ virtual void SetEnabled(bool enabled) = 0;
+ virtual void SetOrientation(TouchHandleOrientation orientation) = 0;
+ virtual void SetAlpha(float alpha) = 0;
+ virtual void SetFocus(const gfx::PointF& position) = 0;
+ virtual void SetVisible(bool visible) = 0;
+ virtual bool IntersectsWith(const gfx::RectF& rect) const = 0;
+};
+
+// Interface through which |TouchHandle| communicates handle manipulation and
+// requests concrete drawable instances.
+class CONTENT_EXPORT TouchHandleClient {
+ public:
+ virtual ~TouchHandleClient() {}
+ virtual void OnHandleDragBegin(const TouchHandle& handle) = 0;
+ virtual void OnHandleDragUpdate(const TouchHandle& handle,
+ const gfx::PointF& new_position) = 0;
+ virtual void OnHandleDragEnd(const TouchHandle& handle) = 0;
+ virtual void OnHandleTapped(const TouchHandle& handle) = 0;
+ virtual void SetNeedsAnimate() = 0;
+ virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() = 0;
+ virtual base::TimeDelta GetTapTimeout() const = 0;
+ virtual float GetTapSlop() const = 0;
+};
+
+// Responsible for displaying a selection or insertion handle for text
+// interaction.
+class CONTENT_EXPORT TouchHandle {
+ public:
+ // The drawable will be enabled but invisible until otherwise specified.
+ TouchHandle(TouchHandleClient* client, TouchHandleOrientation orientation);
+ ~TouchHandle();
+
+ // Sets whether the handle is active, allowing resource cleanup if necessary.
+ // If false, active animations or touch drag sequences will be cancelled.
+ // While disabled, manipulation is *explicitly not supported*, and may lead to
+ // undesirable and/or unstable side-effects. The handle can be safely
+ // re-enabled to allow continued operation.
+ void SetEnabled(bool enabled);
+
+ enum AnimationStyle { ANIMATION_NONE, ANIMATION_SMOOTH };
+ // Update the handle visibility, fading in/out according to |animation_style|.
+ // If an animation is in-progress, it will be overriden appropriately.
+ void SetVisible(bool visible, AnimationStyle animation_style);
+
+ // Update the handle placement to |position|.
+ // Note: If a fade out animation is active or the handle is invisible, the
+ // handle position will not be updated until the handle regains visibility.
+ void SetPosition(const gfx::PointF& position);
+
+ // Update the handle visuals to |orientation|.
+ // Note: If the handle is being dragged, the orientation change will be
+ // deferred until the drag has ceased.
+ void SetOrientation(TouchHandleOrientation orientation);
+
+ // Allows touch-dragging of the handle. Returns true if the event was
+ // consumed, in which case the caller should cease further handling.
+ bool WillHandleTouchEvent(const ui::MotionEvent& event);
+
+ // Ticks an active animation, as requested to the client by |SetNeedsAnimate|.
+ // Returns true if an animation is active and requires further ticking.
+ bool Animate(base::TimeTicks frame_time);
+
+ bool is_dragging() const { return is_dragging_; }
+ const gfx::PointF& position() const { return position_; }
+ TouchHandleOrientation orientation() const { return orientation_; }
+
+ private:
+ void BeginDrag();
+ void EndDrag();
+ void BeginFade();
+ void EndFade();
+ void SetAlpha(float alpha);
+
+ scoped_ptr<TouchHandleDrawable> drawable_;
+
+ TouchHandleClient* const client_;
+
+ gfx::PointF position_;
+ TouchHandleOrientation orientation_;
+ TouchHandleOrientation deferred_orientation_;
+
+ gfx::PointF touch_down_position_;
+ gfx::Vector2dF touch_to_focus_offset_;
+ base::TimeTicks touch_down_time_;
+
+ // Note that when a fade animation is active, |is_visible_| and |position_|
+ // may not reflect the actual visibilty and position of the drawable. This
+ // discrepancy is resolved either upon fade completion or cancellation.
+ base::TimeTicks fade_end_time_;
+ gfx::PointF fade_start_position_;
+ float alpha_;
+ bool animate_deferred_fade_;
+
+ bool enabled_;
+ bool is_visible_;
+ bool is_dragging_;
+ bool is_drag_within_tap_region_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHandle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_HANDLE_H_
diff --git a/chromium/content/browser/renderer_host/input/touch_handle_unittest.cc b/chromium/content/browser/renderer_host/input/touch_handle_unittest.cc
new file mode 100644
index 00000000000..a3459e6c585
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_handle_unittest.cc
@@ -0,0 +1,491 @@
+// Copyright 2014 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 "content/browser/renderer_host/input/touch_handle.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/test/motion_event_test_utils.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+using ui::test::MockMotionEvent;
+
+namespace content {
+namespace {
+
+const int kDefaultTapTimeoutMs = 200;
+const float kDefaultTapSlop = 10.f;
+const float kDefaultDrawableSize = 10.f;
+
+struct MockDrawableData {
+ MockDrawableData()
+ : orientation(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
+ alpha(0.f),
+ enabled(false),
+ visible(false),
+ rect(0, 0, kDefaultDrawableSize, kDefaultDrawableSize) {}
+ TouchHandleOrientation orientation;
+ float alpha;
+ bool enabled;
+ bool visible;
+ gfx::RectF rect;
+};
+
+class MockTouchHandleDrawable : public TouchHandleDrawable {
+ public:
+ explicit MockTouchHandleDrawable(MockDrawableData* data) : data_(data) {}
+ ~MockTouchHandleDrawable() override {}
+
+ void SetEnabled(bool enabled) override { data_->enabled = enabled; }
+
+ void SetOrientation(TouchHandleOrientation orientation) override {
+ data_->orientation = orientation;
+ }
+
+ void SetAlpha(float alpha) override { data_->alpha = alpha; }
+
+ void SetFocus(const gfx::PointF& position) override {
+ // Anchor focus to the top left of the rect (regardless of orientation).
+ data_->rect.set_origin(position);
+ }
+
+ void SetVisible(bool visible) override { data_->visible = visible; }
+
+ bool IntersectsWith(const gfx::RectF& rect) const override {
+ return data_->rect.Intersects(rect);
+ }
+
+ private:
+ MockDrawableData* data_;
+};
+
+} // namespace
+
+class TouchHandleTest : public testing::Test, public TouchHandleClient {
+ public:
+ TouchHandleTest()
+ : dragging_(false),
+ dragged_(false),
+ tapped_(false),
+ needs_animate_(false) {}
+
+ ~TouchHandleTest() override {}
+
+ // TouchHandleClient implementation.
+ void OnHandleDragBegin(const TouchHandle& handle) override {
+ dragging_ = true;
+ }
+
+ void OnHandleDragUpdate(const TouchHandle& handle,
+ const gfx::PointF& new_position) override {
+ dragged_ = true;
+ drag_position_ = new_position;
+ }
+
+ void OnHandleDragEnd(const TouchHandle& handle) override {
+ dragging_ = false;
+ }
+
+ void OnHandleTapped(const TouchHandle& handle) override { tapped_ = true; }
+
+ void SetNeedsAnimate() override { needs_animate_ = true; }
+
+ scoped_ptr<TouchHandleDrawable> CreateDrawable() override {
+ return scoped_ptr<TouchHandleDrawable>(
+ new MockTouchHandleDrawable(&drawable_data_));
+ }
+
+ base::TimeDelta GetTapTimeout() const override {
+ return base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs);
+ }
+
+ float GetTapSlop() const override { return kDefaultTapSlop; }
+
+ void Animate(TouchHandle& handle) {
+ needs_animate_ = false;
+ base::TimeTicks now = base::TimeTicks::Now();
+ while (handle.Animate(now))
+ now += base::TimeDelta::FromMilliseconds(16);
+ }
+
+ bool GetAndResetHandleDragged() {
+ bool dragged = dragged_;
+ dragged_ = false;
+ return dragged;
+ }
+
+ bool GetAndResetHandleTapped() {
+ bool tapped = tapped_;
+ tapped_ = false;
+ return tapped;
+ }
+
+ bool GetAndResetNeedsAnimate() {
+ bool needs_animate = needs_animate_;
+ needs_animate_ = false;
+ return needs_animate;
+ }
+
+ bool IsDragging() const { return dragging_; }
+ const gfx::PointF& DragPosition() const { return drag_position_; }
+ bool NeedsAnimate() const { return needs_animate_; }
+
+ const MockDrawableData& drawable() { return drawable_data_; }
+
+ private:
+ gfx::PointF drag_position_;
+ bool dragging_;
+ bool dragged_;
+ bool tapped_;
+ bool needs_animate_;
+
+ MockDrawableData drawable_data_;
+};
+
+TEST_F(TouchHandleTest, Visibility) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ EXPECT_FALSE(drawable().visible);
+
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_EQ(1.f, drawable().alpha);
+
+ handle.SetVisible(false, TouchHandle::ANIMATION_NONE);
+ EXPECT_FALSE(drawable().visible);
+
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_EQ(1.f, drawable().alpha);
+}
+
+TEST_F(TouchHandleTest, VisibilityAnimation) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ ASSERT_FALSE(NeedsAnimate());
+ ASSERT_FALSE(drawable().visible);
+ ASSERT_EQ(0.f, drawable().alpha);
+
+ handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_TRUE(NeedsAnimate());
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_EQ(0.f, drawable().alpha);
+
+ Animate(handle);
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_EQ(1.f, drawable().alpha);
+
+ ASSERT_FALSE(NeedsAnimate());
+ handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_TRUE(NeedsAnimate());
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_EQ(1.f, drawable().alpha);
+
+ Animate(handle);
+ EXPECT_FALSE(drawable().visible);
+ EXPECT_EQ(0.f, drawable().alpha);
+
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+ EXPECT_EQ(1.f, drawable().alpha);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+ handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_EQ(1.f, drawable().alpha);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+ handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_EQ(1.f, drawable().alpha);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+}
+
+TEST_F(TouchHandleTest, Orientation) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
+
+ handle.SetOrientation(TOUCH_HANDLE_LEFT);
+ EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
+
+ handle.SetOrientation(TOUCH_HANDLE_RIGHT);
+ EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
+
+ handle.SetOrientation(TOUCH_HANDLE_CENTER);
+ EXPECT_EQ(TOUCH_HANDLE_CENTER, drawable().orientation);
+}
+
+TEST_F(TouchHandleTest, Position) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+
+ gfx::PointF position;
+ EXPECT_EQ(gfx::PointF(), drawable().rect.origin());
+
+ position = gfx::PointF(7.3f, -3.7f);
+ handle.SetPosition(position);
+ EXPECT_EQ(position, drawable().rect.origin());
+
+ position = gfx::PointF(-7.3f, 3.7f);
+ handle.SetPosition(position);
+ EXPECT_EQ(position, drawable().rect.origin());
+}
+
+TEST_F(TouchHandleTest, PositionNotUpdatedWhileFadingOrInvisible) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+ ASSERT_TRUE(drawable().visible);
+ ASSERT_FALSE(NeedsAnimate());
+
+ gfx::PointF old_position(7.3f, -3.7f);
+ handle.SetPosition(old_position);
+ ASSERT_EQ(old_position, drawable().rect.origin());
+
+ handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
+ ASSERT_TRUE(NeedsAnimate());
+
+ gfx::PointF new_position(3.7f, -3.7f);
+ handle.SetPosition(new_position);
+ EXPECT_EQ(old_position, drawable().rect.origin());
+ EXPECT_TRUE(NeedsAnimate());
+
+ // While the handle is fading, the new position should not take affect.
+ base::TimeTicks now = base::TimeTicks::Now();
+ while (handle.Animate(now)) {
+ EXPECT_EQ(old_position, drawable().rect.origin());
+ now += base::TimeDelta::FromMilliseconds(16);
+ }
+
+ // Even after the animation terminates, the new position will not be pushed.
+ EXPECT_EQ(old_position, drawable().rect.origin());
+
+ // As soon as the handle becomes visible, the new position will be pushed.
+ handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_EQ(new_position, drawable().rect.origin());
+}
+
+TEST_F(TouchHandleTest, Enabled) {
+ // A newly created handle defaults to enabled.
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ EXPECT_TRUE(drawable().enabled);
+
+ handle.SetVisible(true, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+ EXPECT_EQ(0.f, drawable().alpha);
+ handle.SetEnabled(false);
+ EXPECT_FALSE(drawable().enabled);
+
+ // Dragging should not be allowed while the handle is disabled.
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ const float kOffset = kDefaultDrawableSize / 2.f;
+ MockMotionEvent event(
+ MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+
+ // Disabling mid-animation should cancel the animation.
+ handle.SetEnabled(true);
+ handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+ handle.SetEnabled(false);
+ EXPECT_FALSE(drawable().enabled);
+ EXPECT_FALSE(drawable().visible);
+ EXPECT_FALSE(handle.Animate(base::TimeTicks::Now()));
+
+ // Disabling mid-drag should cancel the drag.
+ handle.SetEnabled(true);
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+ handle.SetEnabled(false);
+ EXPECT_FALSE(IsDragging());
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+}
+
+TEST_F(TouchHandleTest, Drag) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ const float kOffset = kDefaultDrawableSize / 2.f;
+
+ // The handle must be visible to trigger drag.
+ MockMotionEvent event(
+ MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(IsDragging());
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+
+ // ACTION_DOWN must fall within the drawable region to trigger drag.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 50, 50);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(IsDragging());
+
+ // Only ACTION_DOWN will trigger drag.
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_MOVE, event_time, kOffset, kOffset);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(IsDragging());
+
+ // Start the drag.
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_MOVE, event_time, kOffset + 10, kOffset + 15);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetHandleDragged());
+ EXPECT_TRUE(IsDragging());
+ EXPECT_EQ(gfx::PointF(10, 15), DragPosition());
+
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_MOVE, event_time, kOffset - 10, kOffset - 15);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetHandleDragged());
+ EXPECT_TRUE(IsDragging());
+ EXPECT_EQ(gfx::PointF(-10, -15), DragPosition());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetHandleDragged());
+ EXPECT_FALSE(IsDragging());
+
+ // Non-ACTION_DOWN events after the drag has terminated should not be handled.
+ event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+}
+
+TEST_F(TouchHandleTest, DragDefersOrientationChange) {
+ TouchHandle handle(this, TOUCH_HANDLE_RIGHT);
+ ASSERT_EQ(drawable().orientation, TOUCH_HANDLE_RIGHT);
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+
+ // Orientation changes will be deferred until the drag ends.
+ handle.SetOrientation(TOUCH_HANDLE_LEFT);
+ EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetHandleDragged());
+ EXPECT_TRUE(IsDragging());
+ EXPECT_EQ(TOUCH_HANDLE_RIGHT, drawable().orientation);
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetHandleDragged());
+ EXPECT_FALSE(IsDragging());
+ EXPECT_EQ(TOUCH_HANDLE_LEFT, drawable().orientation);
+}
+
+TEST_F(TouchHandleTest, DragDefersFade) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+
+ // Fade will be deferred until the drag ends.
+ handle.SetVisible(false, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_FALSE(NeedsAnimate());
+ EXPECT_TRUE(drawable().visible);
+ EXPECT_EQ(1.f, drawable().alpha);
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(NeedsAnimate());
+ EXPECT_TRUE(drawable().visible);
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(IsDragging());
+ EXPECT_TRUE(NeedsAnimate());
+
+ Animate(handle);
+ EXPECT_FALSE(drawable().visible);
+ EXPECT_EQ(0.f, drawable().alpha);
+}
+
+TEST_F(TouchHandleTest, DragTargettingUsesTouchSize) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ const float kTouchSize = 24.f;
+ const float kOffset = kDefaultDrawableSize + kTouchSize / 2.001f;
+
+ MockMotionEvent event(
+ MockMotionEvent::ACTION_DOWN, event_time, kOffset, kOffset);
+ event.SetTouchMajor(0.f);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(IsDragging());
+
+ event.SetTouchMajor(kTouchSize / 2.f);
+ EXPECT_FALSE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(IsDragging());
+
+ event.SetTouchMajor(kTouchSize);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+
+ event.SetTouchMajor(kTouchSize * 2.f);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+
+ // Ensure a touch size of 0 can still register a hit.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN,
+ event_time,
+ kDefaultDrawableSize / 2.f,
+ kDefaultDrawableSize / 2.f);
+ event.SetTouchMajor(0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(IsDragging());
+}
+
+TEST_F(TouchHandleTest, Tap) {
+ TouchHandle handle(this, TOUCH_HANDLE_CENTER);
+ handle.SetVisible(true, TouchHandle::ANIMATION_NONE);
+
+ base::TimeTicks event_time = base::TimeTicks::Now();
+
+ // ACTION_CANCEL shouldn't trigger a tap.
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ event_time += base::TimeDelta::FromMilliseconds(50);
+ event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetHandleTapped());
+
+ // Long press shouldn't trigger a tap.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ event_time += 2 * GetTapTimeout();
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetHandleTapped());
+
+ // Only a brief tap within the slop region should trigger a tap.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ event_time += GetTapTimeout() / 2;
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_MOVE, event_time, kDefaultTapSlop / 2.f, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_UP, event_time, kDefaultTapSlop / 2.f, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetHandleTapped());
+
+ // Moving beyond the slop region shouldn't trigger a tap.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ event_time += GetTapTimeout() / 2;
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_MOVE, event_time, kDefaultTapSlop * 2.f, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ event = MockMotionEvent(
+ MockMotionEvent::ACTION_UP, event_time, kDefaultTapSlop * 2.f, 0);
+ EXPECT_TRUE(handle.WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetHandleTapped());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
index 758f3ec6a29..3a9f2fd734e 100644
--- a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -97,7 +97,7 @@ class InputEventMessageFilter : public BrowserMessageFilter {
InputEventAckState last_ack_state() const { return state_; }
protected:
- virtual ~InputEventMessageFilter() {}
+ ~InputEventMessageFilter() override {}
private:
void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) {
@@ -108,7 +108,7 @@ class InputEventMessageFilter : public BrowserMessageFilter {
}
// BrowserMessageFilter:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
InputHostMsg_HandleInputEvent_ACK::Param params;
InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
@@ -131,7 +131,7 @@ class InputEventMessageFilter : public BrowserMessageFilter {
class TouchInputBrowserTest : public ContentBrowserTest {
public:
TouchInputBrowserTest() {}
- virtual ~TouchInputBrowserTest() {}
+ ~TouchInputBrowserTest() override {}
RenderWidgetHostImpl* GetWidgetHost() {
return RenderWidgetHostImpl::From(shell()->web_contents()->
@@ -156,10 +156,10 @@ class TouchInputBrowserTest : public ContentBrowserTest {
GiveItSomeTime();
filter_ = new InputEventMessageFilter();
- host->GetProcess()->AddFilter(filter_);
+ host->GetProcess()->AddFilter(filter_.get());
}
- virtual void SetUpCommandLine(CommandLine* cmd) OVERRIDE {
+ void SetUpCommandLine(CommandLine* cmd) override {
cmd->AppendSwitchASCII(switches::kTouchEvents,
switches::kTouchEventsEnabled);
}
@@ -183,14 +183,8 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
filter()->WaitForAck(WebInputEvent::TouchStart);
- if (content::IsThreadedCompositingEnabled()) {
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- filter()->last_ack_state());
- } else {
- // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once
- // WebViewImpl::hasTouchEventHandlersAt() is implemented.
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
- }
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ filter()->last_ack_state());
// If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent
// touch-points don't need to be dispatched until the touch point is released.
@@ -247,14 +241,8 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
touch.PressPoint(25, 25);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
filter()->WaitForAck(WebInputEvent::TouchStart);
- if (content::IsThreadedCompositingEnabled()) {
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- filter()->last_ack_state());
- } else {
- // http://crbug.com/326232: This should be NO_CONSUMER_EXISTS once
- // WebViewImpl::hasTouchEventHandlersAt() is implemented.
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
- }
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ filter()->last_ack_state());
touch.PressPoint(25, 125);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller.cc
new file mode 100644
index 00000000000..4c8807d0fcc
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller.cc
@@ -0,0 +1,423 @@
+// Copyright 2014 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 "content/browser/renderer_host/input/touch_selection_controller.h"
+
+#include "base/auto_reset.h"
+#include "base/logging.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+namespace {
+
+TouchHandleOrientation ToTouchHandleOrientation(cc::SelectionBoundType type) {
+ switch (type) {
+ case cc::SELECTION_BOUND_LEFT:
+ return TOUCH_HANDLE_LEFT;
+ case cc::SELECTION_BOUND_RIGHT:
+ return TOUCH_HANDLE_RIGHT;
+ case cc::SELECTION_BOUND_CENTER:
+ return TOUCH_HANDLE_CENTER;
+ case cc::SELECTION_BOUND_EMPTY:
+ return TOUCH_HANDLE_ORIENTATION_UNDEFINED;
+ }
+ NOTREACHED() << "Invalid selection bound type: " << type;
+ return TOUCH_HANDLE_ORIENTATION_UNDEFINED;
+}
+
+} // namespace
+
+TouchSelectionController::TouchSelectionController(
+ TouchSelectionControllerClient* client,
+ base::TimeDelta tap_timeout,
+ float tap_slop)
+ : client_(client),
+ tap_timeout_(tap_timeout),
+ tap_slop_(tap_slop),
+ response_pending_input_event_(INPUT_EVENT_TYPE_NONE),
+ start_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
+ end_orientation_(TOUCH_HANDLE_ORIENTATION_UNDEFINED),
+ is_insertion_active_(false),
+ activate_insertion_automatically_(false),
+ is_selection_active_(false),
+ activate_selection_automatically_(false),
+ selection_empty_(false),
+ selection_editable_(false),
+ temporarily_hidden_(false) {
+ DCHECK(client_);
+ HideAndDisallowShowingAutomatically();
+}
+
+TouchSelectionController::~TouchSelectionController() {
+}
+
+void TouchSelectionController::OnSelectionBoundsChanged(
+ const cc::ViewportSelectionBound& start,
+ const cc::ViewportSelectionBound& end) {
+ if (!activate_selection_automatically_ &&
+ !activate_insertion_automatically_) {
+ DCHECK_EQ(INPUT_EVENT_TYPE_NONE, response_pending_input_event_);
+ return;
+ }
+
+ if (start == start_ && end_ == end)
+ return;
+
+ start_ = start;
+ end_ = end;
+ start_orientation_ = ToTouchHandleOrientation(start_.type);
+ end_orientation_ = ToTouchHandleOrientation(end_.type);
+
+ // Ensure that |response_pending_input_event_| is cleared after the method
+ // completes, while also making its current value available for the duration
+ // of the call.
+ InputEventType causal_input_event = response_pending_input_event_;
+ response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
+ base::AutoReset<InputEventType> auto_reset_response_pending_input_event(
+ &response_pending_input_event_, causal_input_event);
+
+ const bool is_selection_dragging =
+ is_selection_active_ && (start_selection_handle_->is_dragging() ||
+ end_selection_handle_->is_dragging());
+
+ // It's possible that the bounds temporarily overlap while a selection handle
+ // is being dragged, incorrectly reporting a CENTER orientation.
+ // TODO(jdduke): This safeguard is racy, as it's possible the delayed response
+ // from handle positioning occurs *after* the handle dragging has ceased.
+ // Instead, prevent selection -> insertion transitions without an intervening
+ // action or selection clearing of some sort, crbug.com/392696.
+ if (is_selection_dragging) {
+ if (start_orientation_ == TOUCH_HANDLE_CENTER)
+ start_orientation_ = start_selection_handle_->orientation();
+ if (end_orientation_ == TOUCH_HANDLE_CENTER)
+ end_orientation_ = end_selection_handle_->orientation();
+ }
+
+ if (GetStartPosition() != GetEndPosition() ||
+ (is_selection_dragging &&
+ start_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED &&
+ end_orientation_ != TOUCH_HANDLE_ORIENTATION_UNDEFINED)) {
+ OnSelectionChanged();
+ return;
+ }
+
+ if (start_orientation_ == TOUCH_HANDLE_CENTER && selection_editable_) {
+ OnInsertionChanged();
+ return;
+ }
+
+ HideAndDisallowShowingAutomatically();
+}
+
+bool TouchSelectionController::WillHandleTouchEvent(
+ const ui::MotionEvent& event) {
+ if (is_insertion_active_) {
+ DCHECK(insertion_handle_);
+ return insertion_handle_->WillHandleTouchEvent(event);
+ }
+
+ if (is_selection_active_) {
+ DCHECK(start_selection_handle_);
+ DCHECK(end_selection_handle_);
+ if (start_selection_handle_->is_dragging())
+ return start_selection_handle_->WillHandleTouchEvent(event);
+
+ if (end_selection_handle_->is_dragging())
+ return end_selection_handle_->WillHandleTouchEvent(event);
+
+ const gfx::PointF event_pos(event.GetX(), event.GetY());
+ if ((event_pos - GetStartPosition()).LengthSquared() <=
+ (event_pos - GetEndPosition()).LengthSquared())
+ return start_selection_handle_->WillHandleTouchEvent(event);
+ else
+ return end_selection_handle_->WillHandleTouchEvent(event);
+ }
+
+ return false;
+}
+
+void TouchSelectionController::OnLongPressEvent() {
+ response_pending_input_event_ = LONG_PRESS;
+ ShowSelectionHandlesAutomatically();
+ ShowInsertionHandleAutomatically();
+ ResetCachedValuesIfInactive();
+}
+
+void TouchSelectionController::OnTapEvent() {
+ response_pending_input_event_ = TAP;
+ ShowInsertionHandleAutomatically();
+ if (selection_empty_)
+ DeactivateInsertion();
+ ResetCachedValuesIfInactive();
+}
+
+void TouchSelectionController::HideAndDisallowShowingAutomatically() {
+ response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
+ DeactivateInsertion();
+ DeactivateSelection();
+ activate_insertion_automatically_ = false;
+ activate_selection_automatically_ = false;
+}
+
+void TouchSelectionController::SetTemporarilyHidden(bool hidden) {
+ if (temporarily_hidden_ == hidden)
+ return;
+ temporarily_hidden_ = hidden;
+
+ TouchHandle::AnimationStyle animation_style = GetAnimationStyle(true);
+ if (is_selection_active_) {
+ start_selection_handle_->SetVisible(GetStartVisible(), animation_style);
+ end_selection_handle_->SetVisible(GetEndVisible(), animation_style);
+ }
+ if (is_insertion_active_)
+ insertion_handle_->SetVisible(GetStartVisible(), animation_style);
+}
+
+void TouchSelectionController::OnSelectionEditable(bool editable) {
+ if (selection_editable_ == editable)
+ return;
+ selection_editable_ = editable;
+ ResetCachedValuesIfInactive();
+ if (!selection_editable_)
+ DeactivateInsertion();
+}
+
+void TouchSelectionController::OnSelectionEmpty(bool empty) {
+ if (selection_empty_ == empty)
+ return;
+ selection_empty_ = empty;
+ ResetCachedValuesIfInactive();
+}
+
+bool TouchSelectionController::Animate(base::TimeTicks frame_time) {
+ if (is_insertion_active_)
+ return insertion_handle_->Animate(frame_time);
+
+ if (is_selection_active_) {
+ bool needs_animate = start_selection_handle_->Animate(frame_time);
+ needs_animate |= end_selection_handle_->Animate(frame_time);
+ return needs_animate;
+ }
+
+ return false;
+}
+
+void TouchSelectionController::OnHandleDragBegin(const TouchHandle& handle) {
+ if (&handle == insertion_handle_.get()) {
+ client_->OnSelectionEvent(INSERTION_DRAG_STARTED, handle.position());
+ return;
+ }
+
+ gfx::PointF base, extent;
+ if (&handle == start_selection_handle_.get()) {
+ base = end_selection_handle_->position() + GetEndLineOffset();
+ extent = start_selection_handle_->position() + GetStartLineOffset();
+ } else {
+ base = start_selection_handle_->position() + GetStartLineOffset();
+ extent = end_selection_handle_->position() + GetEndLineOffset();
+ }
+
+ // When moving the handle we want to move only the extent point. Before doing
+ // so we must make sure that the base point is set correctly.
+ client_->SelectBetweenCoordinates(base, extent);
+
+ client_->OnSelectionEvent(SELECTION_DRAG_STARTED, handle.position());
+}
+
+void TouchSelectionController::OnHandleDragUpdate(const TouchHandle& handle,
+ const gfx::PointF& position) {
+ // As the position corresponds to the bottom left point of the selection
+ // bound, offset it by half the corresponding line height.
+ gfx::Vector2dF line_offset = &handle == end_selection_handle_.get()
+ ? GetStartLineOffset()
+ : GetEndLineOffset();
+ gfx::PointF line_position = position + line_offset;
+ if (&handle == insertion_handle_.get()) {
+ client_->MoveCaret(line_position);
+ } else {
+ client_->MoveRangeSelectionExtent(line_position);
+ }
+}
+
+void TouchSelectionController::OnHandleDragEnd(const TouchHandle& handle) {
+ if (&handle != insertion_handle_.get())
+ client_->OnSelectionEvent(SELECTION_DRAG_STOPPED, handle.position());
+}
+
+void TouchSelectionController::OnHandleTapped(const TouchHandle& handle) {
+ if (insertion_handle_ && &handle == insertion_handle_.get())
+ client_->OnSelectionEvent(INSERTION_TAPPED, handle.position());
+}
+
+void TouchSelectionController::SetNeedsAnimate() {
+ client_->SetNeedsAnimate();
+}
+
+scoped_ptr<TouchHandleDrawable> TouchSelectionController::CreateDrawable() {
+ return client_->CreateDrawable();
+}
+
+base::TimeDelta TouchSelectionController::GetTapTimeout() const {
+ return tap_timeout_;
+}
+
+float TouchSelectionController::GetTapSlop() const {
+ return tap_slop_;
+}
+
+void TouchSelectionController::ShowInsertionHandleAutomatically() {
+ if (activate_insertion_automatically_)
+ return;
+ activate_insertion_automatically_ = true;
+ ResetCachedValuesIfInactive();
+}
+
+void TouchSelectionController::ShowSelectionHandlesAutomatically() {
+ if (activate_selection_automatically_)
+ return;
+ activate_selection_automatically_ = true;
+ ResetCachedValuesIfInactive();
+}
+
+void TouchSelectionController::OnInsertionChanged() {
+ DeactivateSelection();
+
+ if (response_pending_input_event_ == TAP && selection_empty_) {
+ HideAndDisallowShowingAutomatically();
+ return;
+ }
+
+ if (!activate_insertion_automatically_)
+ return;
+
+ const bool was_active = is_insertion_active_;
+ const gfx::PointF position = GetStartPosition();
+ if (!is_insertion_active_)
+ ActivateInsertion();
+ else
+ client_->OnSelectionEvent(INSERTION_MOVED, position);
+
+ insertion_handle_->SetVisible(GetStartVisible(),
+ GetAnimationStyle(was_active));
+ insertion_handle_->SetPosition(position);
+}
+
+void TouchSelectionController::OnSelectionChanged() {
+ DeactivateInsertion();
+
+ if (!activate_selection_automatically_)
+ return;
+
+ const bool was_active = is_selection_active_;
+ ActivateSelection();
+
+ const TouchHandle::AnimationStyle animation = GetAnimationStyle(was_active);
+ start_selection_handle_->SetVisible(GetStartVisible(), animation);
+ end_selection_handle_->SetVisible(GetEndVisible(), animation);
+
+ start_selection_handle_->SetPosition(GetStartPosition());
+ end_selection_handle_->SetPosition(GetEndPosition());
+}
+
+void TouchSelectionController::ActivateInsertion() {
+ DCHECK(!is_selection_active_);
+
+ if (!insertion_handle_)
+ insertion_handle_.reset(new TouchHandle(this, TOUCH_HANDLE_CENTER));
+
+ if (!is_insertion_active_) {
+ is_insertion_active_ = true;
+ insertion_handle_->SetEnabled(true);
+ client_->OnSelectionEvent(INSERTION_SHOWN, GetStartPosition());
+ }
+}
+
+void TouchSelectionController::DeactivateInsertion() {
+ if (!is_insertion_active_)
+ return;
+ DCHECK(insertion_handle_);
+ is_insertion_active_ = false;
+ insertion_handle_->SetEnabled(false);
+ client_->OnSelectionEvent(INSERTION_CLEARED, gfx::PointF());
+}
+
+void TouchSelectionController::ActivateSelection() {
+ DCHECK(!is_insertion_active_);
+
+ if (!start_selection_handle_) {
+ start_selection_handle_.reset(new TouchHandle(this, start_orientation_));
+ } else {
+ start_selection_handle_->SetEnabled(true);
+ start_selection_handle_->SetOrientation(start_orientation_);
+ }
+
+ if (!end_selection_handle_) {
+ end_selection_handle_.reset(new TouchHandle(this, end_orientation_));
+ } else {
+ end_selection_handle_->SetEnabled(true);
+ end_selection_handle_->SetOrientation(end_orientation_);
+ }
+
+ // As a long press received while a selection is already active may trigger
+ // an entirely new selection, notify the client but avoid sending an
+ // intervening SELECTION_CLEARED update to avoid unnecessary state changes.
+ if (!is_selection_active_ || response_pending_input_event_ == LONG_PRESS) {
+ is_selection_active_ = true;
+ response_pending_input_event_ = INPUT_EVENT_TYPE_NONE;
+ client_->OnSelectionEvent(SELECTION_SHOWN, GetStartPosition());
+ }
+}
+
+void TouchSelectionController::DeactivateSelection() {
+ if (!is_selection_active_)
+ return;
+ DCHECK(start_selection_handle_);
+ DCHECK(end_selection_handle_);
+ start_selection_handle_->SetEnabled(false);
+ end_selection_handle_->SetEnabled(false);
+ is_selection_active_ = false;
+ client_->OnSelectionEvent(SELECTION_CLEARED, gfx::PointF());
+}
+
+void TouchSelectionController::ResetCachedValuesIfInactive() {
+ if (is_selection_active_ || is_insertion_active_)
+ return;
+ start_ = cc::ViewportSelectionBound();
+ end_ = cc::ViewportSelectionBound();
+ start_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED;
+ end_orientation_ = TOUCH_HANDLE_ORIENTATION_UNDEFINED;
+}
+
+const gfx::PointF& TouchSelectionController::GetStartPosition() const {
+ return start_.edge_bottom;
+}
+
+const gfx::PointF& TouchSelectionController::GetEndPosition() const {
+ return end_.edge_bottom;
+}
+
+gfx::Vector2dF TouchSelectionController::GetStartLineOffset() const {
+ return gfx::ScaleVector2d(start_.edge_top - start_.edge_bottom, 0.5f);
+}
+
+gfx::Vector2dF TouchSelectionController::GetEndLineOffset() const {
+ return gfx::ScaleVector2d(end_.edge_top - end_.edge_bottom, 0.5f);
+}
+
+bool TouchSelectionController::GetStartVisible() const {
+ return start_.visible && !temporarily_hidden_;
+}
+
+bool TouchSelectionController::GetEndVisible() const {
+ return end_.visible && !temporarily_hidden_;
+}
+
+TouchHandle::AnimationStyle TouchSelectionController::GetAnimationStyle(
+ bool was_active) const {
+ return was_active && client_->SupportsAnimation()
+ ? TouchHandle::ANIMATION_SMOOTH
+ : TouchHandle::ANIMATION_NONE;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller.h b/chromium/content/browser/renderer_host/input/touch_selection_controller.h
new file mode 100644
index 00000000000..abe4ed46fac
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller.h
@@ -0,0 +1,150 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_SELECTION_CONTROLLER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_SELECTION_CONTROLLER_H_
+
+#include "cc/output/viewport_selection_bound.h"
+#include "content/browser/renderer_host/input/selection_event_type.h"
+#include "content/browser/renderer_host/input/touch_handle.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect_f.h"
+
+namespace blink {
+class WebInputEvent;
+}
+
+namespace ui {
+class MotionEvent;
+}
+
+namespace content {
+
+// Interface through which |TouchSelectionController| issues selection-related
+// commands, notifications and requests.
+class CONTENT_EXPORT TouchSelectionControllerClient {
+ public:
+ virtual ~TouchSelectionControllerClient() {}
+
+ virtual bool SupportsAnimation() const = 0;
+ virtual void SetNeedsAnimate() = 0;
+ virtual void MoveCaret(const gfx::PointF& position) = 0;
+ virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) = 0;
+ virtual void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) = 0;
+ virtual void OnSelectionEvent(SelectionEventType event,
+ const gfx::PointF& position) = 0;
+ virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() = 0;
+};
+
+// Controller for manipulating text selection via touch input.
+class CONTENT_EXPORT TouchSelectionController : public TouchHandleClient {
+ public:
+ TouchSelectionController(TouchSelectionControllerClient* client,
+ base::TimeDelta tap_timeout,
+ float tap_slop);
+ ~TouchSelectionController() override;
+
+ // To be called when the selection bounds have changed.
+ // Note that such updates will trigger handle updates only if preceded
+ // by an appropriate call to allow automatic showing.
+ void OnSelectionBoundsChanged(const cc::ViewportSelectionBound& start,
+ const cc::ViewportSelectionBound& end);
+
+ // Allows touch-dragging of the handle.
+ // Returns true iff the event was consumed, in which case the caller should
+ // cease further handling of the event.
+ bool WillHandleTouchEvent(const ui::MotionEvent& event);
+
+ // To be called before forwarding a tap event. This allows automatically
+ // showing the insertion handle from subsequent bounds changes.
+ void OnTapEvent();
+
+ // To be called before forwarding a longpress event. This allows automatically
+ // showing the selection or insertion handles from subsequent bounds changes.
+ void OnLongPressEvent();
+
+ // Hide the handles and suppress bounds updates until the next explicit
+ // showing allowance.
+ void HideAndDisallowShowingAutomatically();
+
+ // Override the handle visibility according to |hidden|.
+ void SetTemporarilyHidden(bool hidden);
+
+ // To be called when the editability of the focused region changes.
+ void OnSelectionEditable(bool editable);
+
+ // To be called when the contents of the focused region changes.
+ void OnSelectionEmpty(bool empty);
+
+ // Ticks an active animation, as requested to the client by |SetNeedsAnimate|.
+ // Returns true if an animation is active and requires further ticking.
+ bool Animate(base::TimeTicks animate_time);
+
+ private:
+ enum InputEventType { TAP, LONG_PRESS, INPUT_EVENT_TYPE_NONE };
+
+ // TouchHandleClient implementation.
+ void OnHandleDragBegin(const TouchHandle& handle) override;
+ void OnHandleDragUpdate(const TouchHandle& handle,
+ const gfx::PointF& new_position) override;
+ void OnHandleDragEnd(const TouchHandle& handle) override;
+ void OnHandleTapped(const TouchHandle& handle) override;
+ void SetNeedsAnimate() override;
+ scoped_ptr<TouchHandleDrawable> CreateDrawable() override;
+ base::TimeDelta GetTapTimeout() const override;
+ float GetTapSlop() const override;
+
+ void ShowInsertionHandleAutomatically();
+ void ShowSelectionHandlesAutomatically();
+
+ void OnInsertionChanged();
+ void OnSelectionChanged();
+
+ void ActivateInsertion();
+ void DeactivateInsertion();
+ void ActivateSelection();
+ void DeactivateSelection();
+ void ResetCachedValuesIfInactive();
+
+ const gfx::PointF& GetStartPosition() const;
+ const gfx::PointF& GetEndPosition() const;
+ gfx::Vector2dF GetStartLineOffset() const;
+ gfx::Vector2dF GetEndLineOffset() const;
+ bool GetStartVisible() const;
+ bool GetEndVisible() const;
+ TouchHandle::AnimationStyle GetAnimationStyle(bool was_active) const;
+
+ TouchSelectionControllerClient* const client_;
+ const base::TimeDelta tap_timeout_;
+ const float tap_slop_;
+
+ InputEventType response_pending_input_event_;
+
+ cc::ViewportSelectionBound start_;
+ cc::ViewportSelectionBound end_;
+ TouchHandleOrientation start_orientation_;
+ TouchHandleOrientation end_orientation_;
+
+ scoped_ptr<TouchHandle> insertion_handle_;
+ bool is_insertion_active_;
+ bool activate_insertion_automatically_;
+
+ scoped_ptr<TouchHandle> start_selection_handle_;
+ scoped_ptr<TouchHandle> end_selection_handle_;
+ bool is_selection_active_;
+ bool activate_selection_automatically_;
+
+ bool selection_empty_;
+ bool selection_editable_;
+
+ bool temporarily_hidden_;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchSelectionController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_SELECTION_CONTROLLER_H_
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_unittest.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_unittest.cc
new file mode 100644
index 00000000000..de7d620ff97
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_unittest.cc
@@ -0,0 +1,810 @@
+// Copyright 2014 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 "content/browser/renderer_host/input/touch_selection_controller.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/test/motion_event_test_utils.h"
+
+using ui::test::MockMotionEvent;
+
+namespace content {
+namespace {
+
+const int kDefaultTapTimeoutMs = 200;
+const float kDefaulTapSlop = 10.f;
+
+class MockTouchHandleDrawable : public TouchHandleDrawable {
+ public:
+ explicit MockTouchHandleDrawable(bool* contains_point)
+ : intersects_rect_(contains_point) {}
+ ~MockTouchHandleDrawable() override {}
+ void SetEnabled(bool enabled) override {}
+ void SetOrientation(TouchHandleOrientation orientation) override {}
+ void SetAlpha(float alpha) override {}
+ void SetFocus(const gfx::PointF& position) override {}
+ void SetVisible(bool visible) override {}
+ bool IntersectsWith(const gfx::RectF& rect) const override {
+ return *intersects_rect_;
+ }
+
+ private:
+ bool* intersects_rect_;
+};
+
+} // namespace
+
+class TouchSelectionControllerTest : public testing::Test,
+ public TouchSelectionControllerClient {
+ public:
+ TouchSelectionControllerTest()
+ : last_event_(SELECTION_CLEARED),
+ caret_moved_(false),
+ selection_moved_(false),
+ selection_points_swapped_(false),
+ needs_animate_(false),
+ animation_enabled_(true),
+ dragging_enabled_(false) {}
+
+ ~TouchSelectionControllerTest() override {}
+
+ // testing::Test implementation.
+ void SetUp() override {
+ controller_.reset(new TouchSelectionController(
+ this,
+ base::TimeDelta::FromMilliseconds(kDefaultTapTimeoutMs),
+ kDefaulTapSlop));
+ }
+
+ void TearDown() override { controller_.reset(); }
+
+ // TouchSelectionControllerClient implementation.
+
+ bool SupportsAnimation() const override { return animation_enabled_; }
+
+ void SetNeedsAnimate() override { needs_animate_ = true; }
+
+ void MoveCaret(const gfx::PointF& position) override {
+ caret_moved_ = true;
+ caret_position_ = position;
+ }
+
+ void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) override {
+ if (base == selection_end_ && extent == selection_start_)
+ selection_points_swapped_ = true;
+
+ selection_start_ = base;
+ selection_end_ = extent;
+ }
+
+ virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) override {
+ selection_moved_ = true;
+ selection_end_ = extent;
+ }
+
+ void OnSelectionEvent(SelectionEventType event,
+ const gfx::PointF& end_position) override {
+ last_event_ = event;
+ last_event_start_ = end_position;
+ }
+
+ scoped_ptr<TouchHandleDrawable> CreateDrawable() override {
+ return scoped_ptr<TouchHandleDrawable>(
+ new MockTouchHandleDrawable(&dragging_enabled_));
+ }
+
+ void SetAnimationEnabled(bool enabled) { animation_enabled_ = enabled; }
+ void SetDraggingEnabled(bool enabled) { dragging_enabled_ = enabled; }
+
+ void ClearSelection() {
+ controller_->OnSelectionBoundsChanged(cc::ViewportSelectionBound(),
+ cc::ViewportSelectionBound());
+ }
+
+ void ClearInsertion() { ClearSelection(); }
+
+ void ChangeInsertion(const gfx::RectF& rect, bool visible) {
+ cc::ViewportSelectionBound bound;
+ bound.type = cc::SELECTION_BOUND_CENTER;
+ bound.edge_top = rect.origin();
+ bound.edge_bottom = rect.bottom_left();
+ bound.visible = visible;
+ controller_->OnSelectionBoundsChanged(bound, bound);
+ }
+
+ void ChangeSelection(const gfx::RectF& start_rect,
+ bool start_visible,
+ const gfx::RectF& end_rect,
+ bool end_visible) {
+ cc::ViewportSelectionBound start_bound, end_bound;
+ start_bound.type = cc::SELECTION_BOUND_LEFT;
+ end_bound.type = cc::SELECTION_BOUND_RIGHT;
+ start_bound.edge_top = start_rect.origin();
+ start_bound.edge_bottom = start_rect.bottom_left();
+ end_bound.edge_top = end_rect.origin();
+ end_bound.edge_bottom = end_rect.bottom_left();
+ start_bound.visible = start_visible;
+ end_bound.visible = end_visible;
+ controller_->OnSelectionBoundsChanged(start_bound, end_bound);
+ }
+
+ void Animate() {
+ base::TimeTicks now = base::TimeTicks::Now();
+ while (needs_animate_) {
+ needs_animate_ = controller_->Animate(now);
+ now += base::TimeDelta::FromMilliseconds(16);
+ }
+ }
+
+ bool GetAndResetNeedsAnimate() {
+ bool needs_animate = needs_animate_;
+ Animate();
+ return needs_animate;
+ }
+
+ bool GetAndResetCaretMoved() {
+ bool moved = caret_moved_;
+ caret_moved_ = false;
+ return moved;
+ }
+
+ bool GetAndResetSelectionMoved() {
+ bool moved = selection_moved_;
+ selection_moved_ = false;
+ return moved;
+ }
+
+ bool GetAndResetSelectionPointsSwapped() {
+ bool swapped = selection_points_swapped_;
+ selection_points_swapped_ = false;
+ return swapped;
+ }
+
+ const gfx::PointF& GetLastCaretPosition() const { return caret_position_; }
+ const gfx::PointF& GetLastSelectionStart() const { return selection_start_; }
+ const gfx::PointF& GetLastSelectionEnd() const { return selection_end_; }
+ SelectionEventType GetLastEventType() const { return last_event_; }
+ const gfx::PointF& GetLastEventAnchor() const { return last_event_start_; }
+
+ TouchSelectionController& controller() { return *controller_; }
+
+ private:
+ gfx::PointF last_event_start_;
+ gfx::PointF caret_position_;
+ gfx::PointF selection_start_;
+ gfx::PointF selection_end_;
+ SelectionEventType last_event_;
+ bool caret_moved_;
+ bool selection_moved_;
+ bool selection_points_swapped_;
+ bool needs_animate_;
+ bool animation_enabled_;
+ bool dragging_enabled_;
+ scoped_ptr<TouchSelectionController> controller_;
+};
+
+TEST_F(TouchSelectionControllerTest, InsertionBasic) {
+ gfx::RectF insertion_rect(5, 5, 0, 10);
+ bool visible = true;
+
+ // Insertion events are ignored until automatic showing is enabled.
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+ controller().OnTapEvent();
+
+ // Insertion events are ignored until the selection region is marked editable.
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+
+ insertion_rect.Offset(1, 0);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+
+ insertion_rect.Offset(0, 1);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+
+ ClearInsertion();
+ EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionClearedWhenNoLongerEditable) {
+ gfx::RectF insertion_rect(5, 5, 0, 10);
+ bool visible = true;
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+
+ controller().OnSelectionEditable(false);
+ EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionStaysHiddenIfEmptyRegionTapped) {
+ gfx::RectF insertion_rect(5, 5, 0, 10);
+ bool visible = true;
+ controller().OnSelectionEditable(true);
+
+ // Taps should be ignored if they're in an empty editable region.
+ controller().OnTapEvent();
+ controller().OnSelectionEmpty(true);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+
+ // Once the region becomes editable, taps should show the insertion handle.
+ controller().OnTapEvent();
+ controller().OnSelectionEmpty(false);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+
+ // Reset the selection.
+ controller().HideAndDisallowShowingAutomatically();
+ EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
+
+ // Long-pressing should show the handle even if the editable region is empty.
+ insertion_rect.Offset(2, -2);
+ controller().OnLongPressEvent();
+ controller().OnSelectionEmpty(true);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+
+ // Single Tap on an empty edit field should clear insertion handle.
+ controller().OnTapEvent();
+ EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionAppearsAfterTapFollowingTyping) {
+ gfx::RectF insertion_rect(5, 5, 0, 10);
+ bool visible = true;
+
+ // Simulate the user tapping an empty text field.
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+ controller().OnSelectionEmpty(true);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+
+ // Simulate the cursor moving while a user is typing.
+ insertion_rect.Offset(10, 0);
+ controller().OnSelectionEmpty(false);
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+
+ // If the user taps the *same* position as the cursor at the end of the text
+ // entry, the handle should appear.
+ controller().OnTapEvent();
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(insertion_rect.bottom_left(), GetLastEventAnchor());
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionToSelectionTransition) {
+ controller().OnLongPressEvent();
+ controller().OnSelectionEditable(true);
+
+ gfx::RectF start_rect(5, 5, 0, 10);
+ gfx::RectF end_rect(50, 5, 0, 10);
+ bool visible = true;
+
+ ChangeInsertion(start_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ ChangeInsertion(end_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
+
+ controller().HideAndDisallowShowingAutomatically();
+ EXPECT_EQ(INSERTION_CLEARED, GetLastEventType());
+
+ controller().OnTapEvent();
+ ChangeInsertion(end_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(end_rect.bottom_left(), GetLastEventAnchor());
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionDragged) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+
+ // The touch sequence should not be handled if insertion is not active.
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event));
+
+ float line_height = 10.f;
+ gfx::RectF start_rect(10, 0, 0, line_height);
+ bool visible = true;
+ ChangeInsertion(start_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ // The touch sequence should be handled only if the drawable reports a hit.
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event));
+ SetDraggingEnabled(true);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetCaretMoved());
+
+ // The MoveCaret() result should reflect the movement.
+ // The reported position is offset from the center of |start_rect|.
+ gfx::PointF start_offset = start_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetCaretMoved());
+ EXPECT_EQ(start_offset + gfx::Vector2dF(0, 5), GetLastCaretPosition());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 5, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetCaretMoved());
+ EXPECT_EQ(start_offset + gfx::Vector2dF(5, 5), GetLastCaretPosition());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 10, 10);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetCaretMoved());
+ EXPECT_EQ(start_offset + gfx::Vector2dF(10, 10), GetLastCaretPosition());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetCaretMoved());
+
+ // Once the drag is complete, no more touch events should be consumed until
+ // the next ACTION_DOWN.
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event));
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionTapped) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+ SetDraggingEnabled(true);
+
+ gfx::RectF start_rect(10, 0, 0, 10);
+ bool visible = true;
+ ChangeInsertion(start_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ //TODO(AKV): this test case has to be modified once crbug.com/394093 is fixed.
+ EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
+
+ // Reset the insertion.
+ ClearInsertion();
+ controller().OnTapEvent();
+ ChangeInsertion(start_rect, visible);
+ ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
+
+ // No tap should be signalled if the time between DOWN and UP was too long.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP,
+ event_time + base::TimeDelta::FromSeconds(1),
+ 0,
+ 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
+
+ // Reset the insertion.
+ ClearInsertion();
+ controller().OnTapEvent();
+ ChangeInsertion(start_rect, visible);
+ ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
+
+ // No tap should be signalled if the drag was too long.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 100, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 100, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
+
+ // Reset the insertion.
+ ClearInsertion();
+ controller().OnTapEvent();
+ ChangeInsertion(start_rect, visible);
+ ASSERT_EQ(INSERTION_SHOWN, GetLastEventType());
+
+ // No tap should be signalled if the touch sequence is cancelled.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ event = MockMotionEvent(MockMotionEvent::ACTION_CANCEL, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
+}
+
+TEST_F(TouchSelectionControllerTest, InsertionNotResetByRepeatedTapOrPress) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+ SetDraggingEnabled(true);
+
+ gfx::RectF anchor_rect(10, 0, 0, 10);
+ bool visible = true;
+ ChangeInsertion(anchor_rect, visible);
+ EXPECT_EQ(INSERTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
+
+ // Tapping again shouldn't reset the active insertion point.
+ controller().OnTapEvent();
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
+ EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
+
+ anchor_rect.Offset(5, 15);
+ ChangeInsertion(anchor_rect, visible);
+ EXPECT_EQ(INSERTION_MOVED, GetLastEventType());
+ EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
+
+ // Pressing shouldn't reset the active insertion point.
+ controller().OnLongPressEvent();
+ controller().OnSelectionEmpty(true);
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(INSERTION_TAPPED, GetLastEventType());
+ EXPECT_EQ(anchor_rect.bottom_left(), GetLastEventAnchor());
+}
+
+TEST_F(TouchSelectionControllerTest, SelectionBasic) {
+ gfx::RectF start_rect(5, 5, 0, 10);
+ gfx::RectF end_rect(50, 5, 0, 10);
+ bool visible = true;
+
+ // Selection events are ignored until automatic showing is enabled.
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+
+ controller().OnLongPressEvent();
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ start_rect.Offset(1, 0);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ // Selection movement does not currently trigger a separate event.
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+
+ ClearSelection();
+ EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+}
+
+TEST_F(TouchSelectionControllerTest, SelectionRepeatedLongPress) {
+ gfx::RectF start_rect(5, 5, 0, 10);
+ gfx::RectF end_rect(50, 5, 0, 10);
+ bool visible = true;
+
+ controller().OnLongPressEvent();
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ // A long press triggering a new selection should re-send the SELECTION_SHOWN
+ // event notification.
+ start_rect.Offset(10, 10);
+ controller().OnLongPressEvent();
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+}
+
+TEST_F(TouchSelectionControllerTest, SelectionDragged) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnLongPressEvent();
+
+ // The touch sequence should not be handled if selection is not active.
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time, 0, 0);
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event));
+
+ float line_height = 10.f;
+ gfx::RectF start_rect(0, 0, 0, line_height);
+ gfx::RectF end_rect(50, 0, 0, line_height);
+ bool visible = true;
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ // The touch sequence should be handled only if the drawable reports a hit.
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event));
+ SetDraggingEnabled(true);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ // The SelectBetweenCoordinates() result should reflect the movement. Note
+ // that the start coordinate will always reflect the "fixed" handle's
+ // position, in this case the position from |end_rect|.
+ // Note that the reported position is offset from the center of the
+ // input rects (i.e., the middle of the corresponding text line).
+ gfx::PointF fixed_offset = end_rect.CenterPoint();
+ gfx::PointF start_offset = start_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_EQ(fixed_offset, GetLastSelectionStart());
+ EXPECT_EQ(start_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 5, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_EQ(fixed_offset, GetLastSelectionStart());
+ EXPECT_EQ(start_offset + gfx::Vector2dF(5, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_EQ(fixed_offset, GetLastSelectionStart());
+ EXPECT_EQ(start_offset + gfx::Vector2dF(10, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ // Once the drag is complete, no more touch events should be consumed until
+ // the next ACTION_DOWN.
+ EXPECT_FALSE(controller().WillHandleTouchEvent(event));
+}
+
+TEST_F(TouchSelectionControllerTest, SelectionDraggedWithOverlap) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnLongPressEvent();
+
+ float line_height = 10.f;
+ gfx::RectF start_rect(0, 0, 0, line_height);
+ gfx::RectF end_rect(50, 0, 0, line_height);
+ bool visible = true;
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ // The ACTION_DOWN should lock to the closest handle.
+ gfx::PointF end_offset = end_rect.CenterPoint();
+ gfx::PointF fixed_offset = start_rect.CenterPoint();
+ float touch_down_x = (end_offset.x() + fixed_offset.x()) / 2 + 1.f;
+ MockMotionEvent event(
+ MockMotionEvent::ACTION_DOWN, event_time, touch_down_x, 0);
+ SetDraggingEnabled(true);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ // Even though the ACTION_MOVE is over the start handle, it should continue
+ // targetting the end handle that consumed the ACTION_DOWN.
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_EQ(fixed_offset, GetLastSelectionStart());
+ EXPECT_EQ(end_offset - gfx::Vector2dF(touch_down_x, 0),
+ GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 0, 0);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+}
+
+TEST_F(TouchSelectionControllerTest, SelectionDraggedToSwitchBaseAndExtent) {
+ base::TimeTicks event_time = base::TimeTicks::Now();
+ controller().OnLongPressEvent();
+
+ float line_height = 10.f;
+ gfx::RectF start_rect(50, line_height, 0, line_height);
+ gfx::RectF end_rect(100, line_height, 0, line_height);
+ bool visible = true;
+ ChangeSelection(start_rect, visible, end_rect, visible);
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ SetDraggingEnabled(true);
+
+ // Move the extent, not triggering a swap of points.
+ MockMotionEvent event(MockMotionEvent::ACTION_DOWN, event_time,
+ end_rect.x(), end_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+
+ gfx::PointF base_offset = start_rect.CenterPoint();
+ gfx::PointF extent_offset = end_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ end_rect.x(), end_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ end_rect += gfx::Vector2dF(0, 5);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Move the base, triggering a swap of points.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
+ start_rect.x(), start_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
+
+ base_offset = end_rect.CenterPoint();
+ extent_offset = start_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ start_rect.x(), start_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ start_rect += gfx::Vector2dF(0, 5);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Move the same point again, not triggering a swap of points.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
+ start_rect.x(), start_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+
+ base_offset = end_rect.CenterPoint();
+ extent_offset = start_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ start_rect.x(), start_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+
+ start_rect += gfx::Vector2dF(0, 5);
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Move the base, triggering a swap of points.
+ event = MockMotionEvent(MockMotionEvent::ACTION_DOWN, event_time,
+ end_rect.x(), end_rect.bottom());
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+ EXPECT_TRUE(GetAndResetSelectionPointsSwapped());
+
+ base_offset = start_rect.CenterPoint();
+ extent_offset = end_rect.CenterPoint();
+ event = MockMotionEvent(MockMotionEvent::ACTION_MOVE, event_time,
+ end_rect.x(), end_rect.bottom() + 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STARTED, GetLastEventType());
+ EXPECT_TRUE(GetAndResetSelectionMoved());
+ EXPECT_FALSE(GetAndResetSelectionPointsSwapped());
+ EXPECT_EQ(base_offset, GetLastSelectionStart());
+ EXPECT_EQ(extent_offset + gfx::Vector2dF(0, 5), GetLastSelectionEnd());
+
+ event = MockMotionEvent(MockMotionEvent::ACTION_UP, event_time, 10, 5);
+ EXPECT_TRUE(controller().WillHandleTouchEvent(event));
+ EXPECT_EQ(SELECTION_DRAG_STOPPED, GetLastEventType());
+ EXPECT_FALSE(GetAndResetSelectionMoved());
+}
+
+TEST_F(TouchSelectionControllerTest, Animation) {
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+
+ gfx::RectF insertion_rect(5, 5, 0, 10);
+
+ bool visible = true;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+
+ visible = false;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+
+ visible = true;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+
+ // If the handles are explicity hidden, no animation should be triggered.
+ controller().HideAndDisallowShowingAutomatically();
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+
+ // If the client doesn't support animation, no animation should be triggered.
+ SetAnimationEnabled(false);
+ controller().OnTapEvent();
+ visible = true;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+}
+
+TEST_F(TouchSelectionControllerTest, TemporarilyHidden) {
+ controller().OnTapEvent();
+ controller().OnSelectionEditable(true);
+
+ gfx::RectF insertion_rect(5, 5, 0, 10);
+
+ bool visible = true;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+
+ controller().SetTemporarilyHidden(true);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+
+ visible = false;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+
+ visible = true;
+ ChangeInsertion(insertion_rect, visible);
+ EXPECT_FALSE(GetAndResetNeedsAnimate());
+
+ controller().SetTemporarilyHidden(false);
+ EXPECT_TRUE(GetAndResetNeedsAnimate());
+}
+
+TEST_F(TouchSelectionControllerTest, SelectionClearOnTap) {
+ gfx::RectF start_rect(5, 5, 0, 10);
+ gfx::RectF end_rect(50, 5, 0, 10);
+ bool visible = true;
+
+ controller().OnLongPressEvent();
+ ChangeSelection(start_rect, visible, end_rect, visible);
+
+ // Selection should not be cleared if the selection bounds have not changed.
+ controller().OnTapEvent();
+ EXPECT_EQ(SELECTION_SHOWN, GetLastEventType());
+ EXPECT_EQ(start_rect.bottom_left(), GetLastEventAnchor());
+
+ controller().OnTapEvent();
+ ClearSelection();
+ EXPECT_EQ(SELECTION_CLEARED, GetLastEventType());
+ EXPECT_EQ(gfx::PointF(), GetLastEventAnchor());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
index da74dfd6538..64e5d472e6f 100644
--- a/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchpad_tap_suppression_controller.h
@@ -30,7 +30,7 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
TouchpadTapSuppressionController(
TouchpadTapSuppressionControllerClient* client,
const TapSuppressionController::Config& config);
- virtual ~TouchpadTapSuppressionController();
+ ~TouchpadTapSuppressionController() override;
// Should be called on arrival of GestureFlingCancel events.
void GestureFlingCancel();
@@ -52,8 +52,8 @@ class TouchpadTapSuppressionController : public TapSuppressionControllerClient {
friend class MockRenderWidgetHost;
// TapSuppressionControllerClient implementation.
- virtual void DropStashedTapDown() OVERRIDE;
- virtual void ForwardStashedTapDown() OVERRIDE;
+ void DropStashedTapDown() override;
+ void ForwardStashedTapDown() override;
TouchpadTapSuppressionControllerClient* client_;
MouseEventWithLatencyInfo stashed_mouse_down_;
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
index 706e9d8610e..35ff274356f 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h
@@ -22,7 +22,7 @@ class TouchscreenTapSuppressionController
TouchscreenTapSuppressionController(
GestureEventQueue* geq,
const TapSuppressionController::Config& config);
- virtual ~TouchscreenTapSuppressionController();
+ ~TouchscreenTapSuppressionController() override;
// Should be called on arrival of GestureFlingCancel events.
void GestureFlingCancel();
@@ -37,8 +37,8 @@ class TouchscreenTapSuppressionController
private:
// TapSuppressionControllerClient implementation.
- virtual void DropStashedTapDown() OVERRIDE;
- virtual void ForwardStashedTapDown() OVERRIDE;
+ void DropStashedTapDown() override;
+ void ForwardStashedTapDown() override;
GestureEventQueue* gesture_event_queue_;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc
index 19e8fc61771..73c9174bfe4 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_win.cc
@@ -160,7 +160,9 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(HWND hwnd,
// NOTE: There doesn't seem to be a way to query the mouse button state in
// this case.
- if (LOWORD(lparam) > 1)
+ // Bit 30 of lParam represents the "previous key state". If set, the key was
+ // already down, therefore this is an auto-repeat.
+ if (lparam & 0x40000000)
result.modifiers |= WebInputEvent::IsAutoRepeat;
result.modifiers |= GetLocationModifier(wparam, lparam);
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util.cc b/chromium/content/browser/renderer_host/input/web_input_event_util.cc
index 524cf001431..81fc359e63c 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util.cc
@@ -2,10 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// MSVC++ requires this to be set before any other includes to get M_PI.
+#define _USE_MATH_DEFINES
+
#include "content/browser/renderer_host/input/web_input_event_util.h"
+#include <cmath>
+
#include "base/strings/string_util.h"
#include "content/common/input/web_touch_event_traits.h"
+#include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
#include "ui/events/gesture_detection/motion_event.h"
@@ -188,7 +194,42 @@ WebTouchPoint CreateWebTouchPoint(const MotionEvent& event,
touch.position.y = event.GetY(pointer_index);
touch.screenPosition.x = event.GetRawX(pointer_index);
touch.screenPosition.y = event.GetRawY(pointer_index);
- touch.radiusX = touch.radiusY = event.GetTouchMajor(pointer_index) * 0.5f;
+
+ // A note on touch ellipse specifications:
+ //
+ // Android MotionEvent provides the major and minor axes of the touch ellipse,
+ // as well as the orientation of the major axis clockwise from vertical, in
+ // radians. See:
+ // http://developer.android.com/reference/android/view/MotionEvent.html
+ //
+ // The proposed extension to W3C Touch Events specifies the touch ellipse
+ // using two radii along x- & y-axes and a positive acute rotation angle in
+ // degrees. See:
+ // http://dvcs.w3.org/hg/webevents/raw-file/default/touchevents.html
+
+ float major_radius = event.GetTouchMajor(pointer_index) / 2.f;
+ float minor_radius = event.GetTouchMinor(pointer_index) / 2.f;
+ float orientation_deg = event.GetOrientation(pointer_index) * 180.f / M_PI;
+ DCHECK_GE(major_radius, 0);
+ DCHECK_GE(minor_radius, 0);
+ DCHECK_GE(major_radius, minor_radius);
+ // Allow a small bound tolerance to account for floating point conversion.
+ DCHECK_GT(orientation_deg, -90.01f);
+ DCHECK_LT(orientation_deg, 90.01f);
+ if (orientation_deg >= 0) {
+ // The case orientation_deg == 0 is handled here on purpose: although the
+ // 'else' block is equivalent in this case, we want to pass the 0 value
+ // unchanged (and 0 is the default value for many devices that don't
+ // report elliptical touches).
+ touch.radiusX = minor_radius;
+ touch.radiusY = major_radius;
+ touch.rotationAngle = orientation_deg;
+ } else {
+ touch.radiusX = major_radius;
+ touch.radiusY = minor_radius;
+ touch.rotationAngle = orientation_deg + 90;
+ }
+
touch.force = event.GetPressure(pointer_index);
return touch;
@@ -215,6 +256,10 @@ void UpdateWindowsKeyCodeAndKeyIdentifier(blink::WebKeyboardEvent* event,
blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
const ui::MotionEvent& event) {
+ COMPILE_ASSERT(static_cast<int>(MotionEvent::MAX_TOUCH_POINT_COUNT) ==
+ static_cast<int>(blink::WebTouchEvent::touchesLengthCap),
+ inconsistent_maximum_number_of_active_touch_points);
+
blink::WebTouchEvent result;
WebTouchEventTraits::ResetType(
@@ -222,6 +267,7 @@ blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
(event.GetEventTime() - base::TimeTicks()).InSecondsF(),
&result);
+ result.modifiers = EventFlagsToWebEventModifiers(event.GetFlags());
result.touchesLength =
std::min(event.GetPointerCount(),
static_cast<size_t>(WebTouchEvent::touchesLengthCap));
@@ -236,6 +282,7 @@ blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
WebGestureEvent CreateWebGestureEventFromGestureEventData(
const ui::GestureEventData& data) {
WebGestureEvent gesture;
+ gesture.modifiers = EventFlagsToWebEventModifiers(data.flags);
gesture.x = data.x;
gesture.y = data.y;
gesture.globalX = data.raw_x;
@@ -332,4 +379,60 @@ WebGestureEvent CreateWebGestureEventFromGestureEventData(
return gesture;
}
+int EventFlagsToWebEventModifiers(int flags) {
+ int modifiers = 0;
+
+ if (flags & ui::EF_SHIFT_DOWN)
+ modifiers |= blink::WebInputEvent::ShiftKey;
+ if (flags & ui::EF_CONTROL_DOWN)
+ modifiers |= blink::WebInputEvent::ControlKey;
+ if (flags & ui::EF_ALT_DOWN)
+ modifiers |= blink::WebInputEvent::AltKey;
+ if (flags & ui::EF_COMMAND_DOWN)
+ modifiers |= blink::WebInputEvent::MetaKey;
+
+ if (flags & ui::EF_LEFT_MOUSE_BUTTON)
+ modifiers |= blink::WebInputEvent::LeftButtonDown;
+ if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
+ modifiers |= blink::WebInputEvent::MiddleButtonDown;
+ if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
+ modifiers |= blink::WebInputEvent::RightButtonDown;
+ if (flags & ui::EF_CAPS_LOCK_DOWN)
+ modifiers |= blink::WebInputEvent::CapsLockOn;
+ if (flags & ui::EF_IS_REPEAT)
+ modifiers |= blink::WebInputEvent::IsAutoRepeat;
+ if (flags & ui::EF_NUMPAD_KEY)
+ modifiers |= blink::WebInputEvent::IsKeyPad;
+
+ return modifiers;
+}
+
+int WebEventModifiersToEventFlags(int modifiers) {
+ int flags = 0;
+
+ if (modifiers & blink::WebInputEvent::ShiftKey)
+ flags |= ui::EF_SHIFT_DOWN;
+ if (modifiers & blink::WebInputEvent::ControlKey)
+ flags |= ui::EF_CONTROL_DOWN;
+ if (modifiers & blink::WebInputEvent::AltKey)
+ flags |= ui::EF_ALT_DOWN;
+ if (modifiers & blink::WebInputEvent::MetaKey)
+ flags |= ui::EF_COMMAND_DOWN;
+
+ if (modifiers & blink::WebInputEvent::LeftButtonDown)
+ flags |= ui::EF_LEFT_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::MiddleButtonDown)
+ flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::RightButtonDown)
+ flags |= ui::EF_RIGHT_MOUSE_BUTTON;
+ if (modifiers & blink::WebInputEvent::CapsLockOn)
+ flags |= ui::EF_CAPS_LOCK_DOWN;
+ if (modifiers & blink::WebInputEvent::IsAutoRepeat)
+ flags |= ui::EF_IS_REPEAT;
+ if (modifiers & blink::WebInputEvent::IsKeyPad)
+ flags |= ui::EF_NUMPAD_KEY;
+
+ return flags;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util.h b/chromium/content/browser/renderer_host/input/web_input_event_util.h
index 4143a1cbce4..1cadd7d0050 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util.h
@@ -32,6 +32,10 @@ CONTENT_EXPORT blink::WebTouchEvent CreateWebTouchEventFromMotionEvent(
CONTENT_EXPORT blink::WebGestureEvent CreateWebGestureEventFromGestureEventData(
const ui::GestureEventData& data);
+int EventFlagsToWebEventModifiers(int flags);
+
+int WebEventModifiersToEventFlags(int modifiers);
+
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_H_
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
new file mode 100644
index 00000000000..1d29a070c17
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 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.
+
+// Needed on Windows to get |M_PI| from <cmath>.
+#ifdef _WIN32
+#define _USE_MATH_DEFINES
+#endif
+
+#include <cmath>
+
+#include "content/browser/renderer_host/input/web_input_event_util.h"
+#include "content/common/input/web_input_event_traits.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/gesture_detection/motion_event_generic.h"
+
+using blink::WebInputEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+using ui::MotionEvent;
+using ui::MotionEventGeneric;
+
+namespace content {
+
+TEST(WebInputEventUtilTest, MotionEventConversion) {
+ ui::PointerProperties pointer(5, 10, 40);
+ pointer.id = 15;
+ pointer.raw_x = 20;
+ pointer.raw_y = 25;
+ pointer.pressure = 30;
+ pointer.touch_minor = 35;
+ pointer.orientation = static_cast<float>(-M_PI / 2);
+ MotionEventGeneric event(
+ MotionEvent::ACTION_DOWN, base::TimeTicks::Now(), pointer);
+ event.set_flags(ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
+
+ WebTouchEvent expected_event;
+ expected_event.type = WebInputEvent::TouchStart;
+ expected_event.touchesLength = 1;
+ expected_event.timeStampSeconds =
+ (event.GetEventTime() - base::TimeTicks()).InSecondsF();
+ expected_event.modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
+ WebTouchPoint expected_pointer;
+ expected_pointer.id = pointer.id;
+ expected_pointer.state = WebTouchPoint::StatePressed;
+ expected_pointer.position = blink::WebFloatPoint(pointer.x, pointer.y);
+ expected_pointer.screenPosition =
+ blink::WebFloatPoint(pointer.raw_x, pointer.raw_y);
+ expected_pointer.radiusX = pointer.touch_major / 2.f;
+ expected_pointer.radiusY = pointer.touch_minor / 2.f;
+ expected_pointer.rotationAngle = 0.f;
+ expected_pointer.force = pointer.pressure;
+ expected_event.touches[0] = expected_pointer;
+
+ WebTouchEvent actual_event = CreateWebTouchEventFromMotionEvent(event);
+ EXPECT_EQ(WebInputEventTraits::ToString(expected_event),
+ WebInputEventTraits::ToString(actual_event));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/DEPS b/chromium/content/browser/renderer_host/java/DEPS
deleted file mode 100644
index 05512435883..00000000000
--- a/chromium/content/browser/renderer_host/java/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+content/child", # For java bridge bindings
- "+third_party/WebKit/public/web/WebBindings.h", # For java bridge bindings
-]
diff --git a/chromium/content/browser/renderer_host/java/gin_java_bound_object.cc b/chromium/content/browser/renderer_host/java/gin_java_bound_object.cc
deleted file mode 100644
index 70abba842c9..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_bound_object.cc
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/java/gin_java_bound_object.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/renderer_host/java/jni_helper.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-namespace {
-
-const char kJavaLangClass[] = "java/lang/Class";
-const char kJavaLangObject[] = "java/lang/Object";
-const char kJavaLangReflectMethod[] = "java/lang/reflect/Method";
-const char kGetClass[] = "getClass";
-const char kGetMethods[] = "getMethods";
-const char kIsAnnotationPresent[] = "isAnnotationPresent";
-const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
-const char kReturningJavaLangReflectMethodArray[] =
- "()[Ljava/lang/reflect/Method;";
-const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z";
-
-} // namespace
-
-
-// static
-GinJavaBoundObject* GinJavaBoundObject::CreateNamed(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz) {
- return new GinJavaBoundObject(ref, safe_annotation_clazz);
-}
-
-// static
-GinJavaBoundObject* GinJavaBoundObject::CreateTransient(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz,
- RenderFrameHost* holder) {
- std::set<RenderFrameHost*> holders;
- holders.insert(holder);
- return new GinJavaBoundObject(ref, safe_annotation_clazz, holders);
-}
-
-GinJavaBoundObject::GinJavaBoundObject(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz)
- : ref_(ref),
- names_count_(1),
- object_get_class_method_id_(NULL),
- are_methods_set_up_(false),
- safe_annotation_clazz_(safe_annotation_clazz) {
-}
-
-GinJavaBoundObject::GinJavaBoundObject(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz,
- const std::set<RenderFrameHost*> holders)
- : ref_(ref),
- names_count_(0),
- holders_(holders),
- object_get_class_method_id_(NULL),
- are_methods_set_up_(false),
- safe_annotation_clazz_(safe_annotation_clazz) {
-}
-
-GinJavaBoundObject::~GinJavaBoundObject() {
-}
-
-std::set<std::string> GinJavaBoundObject::GetMethodNames() {
- EnsureMethodsAreSetUp();
- std::set<std::string> result;
- for (JavaMethodMap::const_iterator it = methods_.begin();
- it != methods_.end();
- ++it) {
- result.insert(it->first);
- }
- return result;
-}
-
-bool GinJavaBoundObject::HasMethod(const std::string& method_name) {
- EnsureMethodsAreSetUp();
- return methods_.find(method_name) != methods_.end();
-}
-
-const JavaMethod* GinJavaBoundObject::FindMethod(
- const std::string& method_name,
- size_t num_parameters) {
- EnsureMethodsAreSetUp();
-
- // Get all methods with the correct name.
- std::pair<JavaMethodMap::const_iterator, JavaMethodMap::const_iterator>
- iters = methods_.equal_range(method_name);
- if (iters.first == iters.second) {
- return NULL;
- }
-
- // LIVECONNECT_COMPLIANCE: We just take the first method with the correct
- // number of arguments, while the spec proposes using cost-based algorithm:
- // https://jdk6.java.net/plugin2/liveconnect/#OVERLOADED_METHODS
- for (JavaMethodMap::const_iterator iter = iters.first; iter != iters.second;
- ++iter) {
- if (iter->second->num_parameters() == num_parameters) {
- return iter->second.get();
- }
- }
-
- return NULL;
-}
-
-bool GinJavaBoundObject::IsObjectGetClassMethod(const JavaMethod* method) {
- EnsureMethodsAreSetUp();
- // As java.lang.Object.getClass is declared to be final, it is sufficient to
- // compare methodIDs.
- return method->id() == object_get_class_method_id_;
-}
-
-const base::android::JavaRef<jclass>&
-GinJavaBoundObject::GetSafeAnnotationClass() {
- return safe_annotation_clazz_;
-}
-
-base::android::ScopedJavaLocalRef<jclass> GinJavaBoundObject::GetLocalClassRef(
- JNIEnv* env) {
- if (!object_get_class_method_id_) {
- object_get_class_method_id_ = GetMethodIDFromClassName(
- env, kJavaLangObject, kGetClass, kReturningJavaLangClass);
- }
- ScopedJavaLocalRef<jobject> obj = GetLocalRef(env);
- if (obj.obj()) {
- return base::android::ScopedJavaLocalRef<jclass>(
- env,
- static_cast<jclass>(
- env->CallObjectMethod(obj.obj(), object_get_class_method_id_)));
- } else {
- return base::android::ScopedJavaLocalRef<jclass>();
- }
-}
-
-void GinJavaBoundObject::EnsureMethodsAreSetUp() {
- if (are_methods_set_up_)
- return;
- are_methods_set_up_ = true;
-
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jclass> clazz = GetLocalClassRef(env);
- if (clazz.is_null()) {
- return;
- }
-
- ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>(
- env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangClass,
- kGetMethods,
- kReturningJavaLangReflectMethodArray))));
-
- size_t num_methods = env->GetArrayLength(methods.obj());
- // Java objects always have public methods.
- DCHECK(num_methods);
-
- for (size_t i = 0; i < num_methods; ++i) {
- ScopedJavaLocalRef<jobject> java_method(
- env,
- env->GetObjectArrayElement(methods.obj(), i));
-
- if (!safe_annotation_clazz_.is_null()) {
- jboolean safe = env->CallBooleanMethod(java_method.obj(),
- GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kIsAnnotationPresent,
- kTakesJavaLangClassReturningBoolean),
- safe_annotation_clazz_.obj());
-
- if (!safe)
- continue;
- }
-
- JavaMethod* method = new JavaMethod(java_method);
- methods_.insert(std::make_pair(method->name(), method));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/gin_java_bound_object.h b/chromium/content/browser/renderer_host/java/gin_java_bound_object.h
deleted file mode 100644
index 610b0c42899..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_bound_object.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BOUND_OBJECT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BOUND_OBJECT_H_
-
-#include <map>
-#include <set>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/id_map.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/values.h"
-#include "content/browser/renderer_host/java/java_method.h"
-
-namespace content {
-
-class RenderFrameHost;
-
-class GinJavaBoundObject
- : public base::RefCountedThreadSafe<GinJavaBoundObject> {
- public:
- // Using scoped_refptr<> as a value type is somewhat not IDMap had been
- // designed for (it returns T* from lookups, so we have to de-ref it), but on
- // the other hand, this allows us to manage lifetime of GinJavaBoundObject
- // automatically.
- typedef IDMap<scoped_refptr<GinJavaBoundObject>, IDMapOwnPointer> ObjectMap;
- typedef ObjectMap::KeyType ObjectID;
-
- static GinJavaBoundObject* CreateNamed(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz);
- static GinJavaBoundObject* CreateTransient(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz,
- RenderFrameHost* holder);
-
- JavaObjectWeakGlobalRef& GetWeakRef() { return ref_; }
- base::android::ScopedJavaLocalRef<jobject> GetLocalRef(JNIEnv* env) {
- return ref_.get(env);
- }
-
- bool IsNamed() { return names_count_ > 0; }
- void AddName() { ++names_count_; }
- void RemoveName() { --names_count_; }
-
- bool HasHolders() { return !holders_.empty(); }
- void AddHolder(RenderFrameHost* holder) { holders_.insert(holder); }
- void RemoveHolder(RenderFrameHost* holder) { holders_.erase(holder); }
-
- // The following methods are called on the background thread.
- std::set<std::string> GetMethodNames();
- bool HasMethod(const std::string& method_name);
- const JavaMethod* FindMethod(const std::string& method_name,
- size_t num_parameters);
- bool IsObjectGetClassMethod(const JavaMethod* method);
- const base::android::JavaRef<jclass>& GetSafeAnnotationClass();
- base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(JNIEnv* env);
-
- private:
- friend class base::RefCountedThreadSafe<GinJavaBoundObject>;
-
- GinJavaBoundObject(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz);
- GinJavaBoundObject(
- const JavaObjectWeakGlobalRef& ref,
- const base::android::JavaRef<jclass>& safe_annotation_clazz,
- const std::set<RenderFrameHost*> holders);
- ~GinJavaBoundObject();
-
- // The following methods are called on the background thread.
- void EnsureMethodsAreSetUp();
-
- JavaObjectWeakGlobalRef ref_;
-
- // An object must be kept in retained_object_set_ either if it has
- // names or if it has a non-empty holders set.
- int names_count_;
- std::set<RenderFrameHost*> holders_;
-
- // The following fields are accessed on the background thread.
- typedef std::multimap<std::string, linked_ptr<JavaMethod> > JavaMethodMap;
- JavaMethodMap methods_;
- jmethodID object_get_class_method_id_;
- bool are_methods_set_up_;
- base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BOUND_OBJECT_H_
diff --git a/chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.cc b/chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.cc
deleted file mode 100644
index 92b1ccc2fc1..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/java/gin_java_bound_object_delegate.h"
-
-namespace content {
-
-GinJavaBoundObjectDelegate::GinJavaBoundObjectDelegate(
- scoped_refptr<GinJavaBoundObject> object)
- : object_(object) {
-}
-
-GinJavaBoundObjectDelegate::~GinJavaBoundObjectDelegate() {
-}
-
-base::android::ScopedJavaLocalRef<jobject>
-GinJavaBoundObjectDelegate::GetLocalRef(JNIEnv* env) {
- return object_->GetLocalRef(env);
-}
-
-base::android::ScopedJavaLocalRef<jclass>
-GinJavaBoundObjectDelegate::GetLocalClassRef(JNIEnv* env) {
- return object_->GetLocalClassRef(env);
-}
-
-const JavaMethod* GinJavaBoundObjectDelegate::FindMethod(
- const std::string& method_name,
- size_t num_parameters) {
- return object_->FindMethod(method_name, num_parameters);
-}
-
-bool GinJavaBoundObjectDelegate::IsObjectGetClassMethod(
- const JavaMethod* method) {
- return object_->IsObjectGetClassMethod(method);
-}
-
-const base::android::JavaRef<jclass>&
-GinJavaBoundObjectDelegate::GetSafeAnnotationClass() {
- return object_->GetSafeAnnotationClass();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.h b/chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.h
deleted file mode 100644
index 9852d91e733..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_bound_object_delegate.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BOUND_OBJECT_DELEGATE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BOUND_OBJECT_DELEGATE_H_
-
-#include "base/memory/ref_counted.h"
-#include "content/browser/renderer_host/java/gin_java_bound_object.h"
-#include "content/browser/renderer_host/java/gin_java_method_invocation_helper.h"
-
-namespace content {
-
-class GinJavaBoundObjectDelegate
- : public GinJavaMethodInvocationHelper::ObjectDelegate {
- public:
- GinJavaBoundObjectDelegate(scoped_refptr<GinJavaBoundObject> object);
- virtual ~GinJavaBoundObjectDelegate();
-
- virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
- JNIEnv* env) OVERRIDE;
- virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
- JNIEnv* env) OVERRIDE;
- virtual const JavaMethod* FindMethod(const std::string& method_name,
- size_t num_parameters) OVERRIDE;
- virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE;
- virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass()
- OVERRIDE;
-
- private:
- scoped_refptr<GinJavaBoundObject> object_;
-
- DISALLOW_COPY_AND_ASSIGN(GinJavaBoundObjectDelegate);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_BOUND_OBJECT_DELEGATE_H_
diff --git a/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc b/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc
deleted file mode 100644
index d3fb1386544..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.cc
+++ /dev/null
@@ -1,341 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/java/gin_java_method_invocation_helper.h"
-
-#include <unistd.h>
-
-#include "base/android/event_log.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/float_util.h"
-#include "content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h"
-#include "content/browser/renderer_host/java/java_method.h"
-#include "content/browser/renderer_host/java/jni_helper.h"
-#include "content/common/android/gin_java_bridge_value.h"
-#include "content/public/browser/browser_thread.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-
-namespace {
-
-const char kObjectIsGone[] = "Java object is gone";
-const char kMethodNotFound[] = "Method not found";
-const char kAccessToObjectGetClassIsBlocked[] =
- "Access to java.lang.Object.getClass is blocked";
-const char kJavaExceptionRaised[] =
- "Java exception has been raised during method invocation";
-
-// See frameworks/base/core/java/android/webkit/EventLogTags.logtags
-const int kObjectGetClassInvocationAttemptLogTag = 70151;
-
-} // namespace
-
-GinJavaMethodInvocationHelper::GinJavaMethodInvocationHelper(
- scoped_ptr<ObjectDelegate> object,
- const std::string& method_name,
- const base::ListValue& arguments)
- : object_(object.Pass()),
- method_name_(method_name),
- arguments_(arguments.DeepCopy()) {
-}
-
-GinJavaMethodInvocationHelper::~GinJavaMethodInvocationHelper() {}
-
-void GinJavaMethodInvocationHelper::Init(DispatcherDelegate* dispatcher) {
- // Build on the UI thread a map of object_id -> WeakRef for Java objects from
- // |arguments_|. Then we can use this map on the background thread without
- // accessing |dispatcher|.
- BuildObjectRefsFromListValue(dispatcher, arguments_.get());
-}
-
-// As V8ValueConverter has finite recursion depth when serializing
-// JavaScript values, we don't bother about having a recursion threshold here.
-void GinJavaMethodInvocationHelper::BuildObjectRefsFromListValue(
- DispatcherDelegate* dispatcher,
- const base::Value* list_value) {
- DCHECK(list_value->IsType(base::Value::TYPE_LIST));
- const base::ListValue* list;
- list_value->GetAsList(&list);
- for (base::ListValue::const_iterator iter = list->begin();
- iter != list->end();
- ++iter) {
- if (AppendObjectRef(dispatcher, *iter))
- continue;
- if ((*iter)->IsType(base::Value::TYPE_LIST)) {
- BuildObjectRefsFromListValue(dispatcher, *iter);
- } else if ((*iter)->IsType(base::Value::TYPE_DICTIONARY)) {
- BuildObjectRefsFromDictionaryValue(dispatcher, *iter);
- }
- }
-}
-
-void GinJavaMethodInvocationHelper::BuildObjectRefsFromDictionaryValue(
- DispatcherDelegate* dispatcher,
- const base::Value* dict_value) {
- DCHECK(dict_value->IsType(base::Value::TYPE_DICTIONARY));
- const base::DictionaryValue* dict;
- dict_value->GetAsDictionary(&dict);
- for (base::DictionaryValue::Iterator iter(*dict);
- !iter.IsAtEnd();
- iter.Advance()) {
- if (AppendObjectRef(dispatcher, &iter.value()))
- continue;
- if (iter.value().IsType(base::Value::TYPE_LIST)) {
- BuildObjectRefsFromListValue(dispatcher, &iter.value());
- } else if (iter.value().IsType(base::Value::TYPE_DICTIONARY)) {
- BuildObjectRefsFromDictionaryValue(dispatcher, &iter.value());
- }
- }
-}
-
-bool GinJavaMethodInvocationHelper::AppendObjectRef(
- DispatcherDelegate* dispatcher,
- const base::Value* raw_value) {
- if (!GinJavaBridgeValue::ContainsGinJavaBridgeValue(raw_value))
- return false;
- scoped_ptr<const GinJavaBridgeValue> value(
- GinJavaBridgeValue::FromValue(raw_value));
- if (!value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID))
- return false;
- GinJavaBoundObject::ObjectID object_id;
- if (value->GetAsObjectID(&object_id)) {
- ObjectRefs::iterator iter = object_refs_.find(object_id);
- if (iter == object_refs_.end()) {
- JavaObjectWeakGlobalRef object_ref(
- dispatcher->GetObjectWeakRef(object_id));
- if (!object_ref.is_empty()) {
- object_refs_.insert(std::make_pair(object_id, object_ref));
- }
- }
- }
- return true;
-}
-
-void GinJavaMethodInvocationHelper::Invoke() {
- JNIEnv* env = AttachCurrentThread();
- const JavaMethod* method =
- object_->FindMethod(method_name_, arguments_->GetSize());
- if (!method) {
- SetInvocationFailure(kMethodNotFound);
- return;
- }
-
- if (object_->IsObjectGetClassMethod(method)) {
- base::android::EventLogWriteInt(kObjectGetClassInvocationAttemptLogTag,
- getuid());
- SetInvocationFailure(kAccessToObjectGetClassIsBlocked);
- return;
- }
-
- ScopedJavaLocalRef<jobject> obj;
- ScopedJavaLocalRef<jclass> cls;
- if (method->is_static()) {
- cls = object_->GetLocalClassRef(env);
- } else {
- obj = object_->GetLocalRef(env);
- }
- if (obj.is_null() && cls.is_null()) {
- SetInvocationFailure(kObjectIsGone);
- return;
- }
-
- std::vector<jvalue> parameters(method->num_parameters());
- for (size_t i = 0; i < method->num_parameters(); ++i) {
- const base::Value* argument;
- arguments_->Get(i, &argument);
- parameters[i] = CoerceJavaScriptValueToJavaValue(
- env, argument, method->parameter_type(i), true, object_refs_);
- }
- if (method->is_static()) {
- InvokeMethod(
- NULL, cls.obj(), method->return_type(), method->id(), &parameters[0]);
- } else {
- InvokeMethod(
- obj.obj(), NULL, method->return_type(), method->id(), &parameters[0]);
- }
-
- // Now that we're done with the jvalue, release any local references created
- // by CoerceJavaScriptValueToJavaValue().
- for (size_t i = 0; i < method->num_parameters(); ++i) {
- ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
- }
-}
-
-void GinJavaMethodInvocationHelper::SetInvocationFailure(
- const char* error_message) {
- holds_primitive_result_ = true;
- primitive_result_.reset(new base::ListValue());
- error_message_ = error_message;
-}
-
-void GinJavaMethodInvocationHelper::SetPrimitiveResult(
- const base::ListValue& result_wrapper) {
- holds_primitive_result_ = true;
- primitive_result_.reset(result_wrapper.DeepCopy());
-}
-
-void GinJavaMethodInvocationHelper::SetObjectResult(
- const base::android::JavaRef<jobject>& object,
- const base::android::JavaRef<jclass>& safe_annotation_clazz) {
- holds_primitive_result_ = false;
- object_result_.Reset(object);
- safe_annotation_clazz_.Reset(safe_annotation_clazz);
-}
-
-bool GinJavaMethodInvocationHelper::HoldsPrimitiveResult() {
- return holds_primitive_result_;
-}
-
-const base::ListValue& GinJavaMethodInvocationHelper::GetPrimitiveResult() {
- return *primitive_result_.get();
-}
-
-const base::android::JavaRef<jobject>&
-GinJavaMethodInvocationHelper::GetObjectResult() {
- return object_result_;
-}
-
-const base::android::JavaRef<jclass>&
-GinJavaMethodInvocationHelper::GetSafeAnnotationClass() {
- return safe_annotation_clazz_;
-}
-
-const std::string& GinJavaMethodInvocationHelper::GetErrorMessage() {
- return error_message_;
-}
-
-void GinJavaMethodInvocationHelper::InvokeMethod(jobject object,
- jclass clazz,
- const JavaType& return_type,
- jmethodID id,
- jvalue* parameters) {
- DCHECK(object || clazz);
- JNIEnv* env = AttachCurrentThread();
- base::ListValue result_wrapper;
- switch (return_type.type) {
- case JavaType::TypeBoolean:
- result_wrapper.AppendBoolean(
- object ? env->CallBooleanMethodA(object, id, parameters)
- : env->CallStaticBooleanMethodA(clazz, id, parameters));
- break;
- case JavaType::TypeByte:
- result_wrapper.AppendInteger(
- object ? env->CallByteMethodA(object, id, parameters)
- : env->CallStaticByteMethodA(clazz, id, parameters));
- break;
- case JavaType::TypeChar:
- result_wrapper.AppendInteger(
- object ? env->CallCharMethodA(object, id, parameters)
- : env->CallStaticCharMethodA(clazz, id, parameters));
- break;
- case JavaType::TypeShort:
- result_wrapper.AppendInteger(
- object ? env->CallShortMethodA(object, id, parameters)
- : env->CallStaticShortMethodA(clazz, id, parameters));
- break;
- case JavaType::TypeInt:
- result_wrapper.AppendInteger(
- object ? env->CallIntMethodA(object, id, parameters)
- : env->CallStaticIntMethodA(clazz, id, parameters));
- break;
- case JavaType::TypeLong:
- result_wrapper.AppendDouble(
- object ? env->CallLongMethodA(object, id, parameters)
- : env->CallStaticLongMethodA(clazz, id, parameters));
- break;
- case JavaType::TypeFloat: {
- float result = object
- ? env->CallFloatMethodA(object, id, parameters)
- : env->CallStaticFloatMethodA(clazz, id, parameters);
- if (base::IsFinite(result)) {
- result_wrapper.AppendDouble(result);
- } else {
- result_wrapper.Append(
- GinJavaBridgeValue::CreateNonFiniteValue(result).release());
- }
- break;
- }
- case JavaType::TypeDouble: {
- double result = object
- ? env->CallDoubleMethodA(object, id, parameters)
- : env->CallStaticDoubleMethodA(clazz, id, parameters);
- if (base::IsFinite(result)) {
- result_wrapper.AppendDouble(result);
- } else {
- result_wrapper.Append(
- GinJavaBridgeValue::CreateNonFiniteValue(result).release());
- }
- break;
- }
- case JavaType::TypeVoid:
- if (object)
- env->CallVoidMethodA(object, id, parameters);
- else
- env->CallStaticVoidMethodA(clazz, id, parameters);
- result_wrapper.Append(
- GinJavaBridgeValue::CreateUndefinedValue().release());
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that
- // return arrays. Spec requires calling the method and converting the
- // result to a JavaScript array.
- result_wrapper.Append(
- GinJavaBridgeValue::CreateUndefinedValue().release());
- break;
- case JavaType::TypeString: {
- jstring java_string = static_cast<jstring>(
- object ? env->CallObjectMethodA(object, id, parameters)
- : env->CallStaticObjectMethodA(clazz, id, parameters));
- // If an exception was raised, we must clear it before calling most JNI
- // methods. ScopedJavaLocalRef is liable to make such calls, so we test
- // first.
- if (base::android::ClearException(env)) {
- SetInvocationFailure(kJavaExceptionRaised);
- return;
- }
- ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
- if (!scoped_java_string.obj()) {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined.
- // Spec requires returning a null string.
- result_wrapper.Append(
- GinJavaBridgeValue::CreateUndefinedValue().release());
- break;
- }
- result_wrapper.AppendString(
- base::android::ConvertJavaStringToUTF8(scoped_java_string));
- break;
- }
- case JavaType::TypeObject: {
- // If an exception was raised, we must clear it before calling most JNI
- // methods. ScopedJavaLocalRef is liable to make such calls, so we test
- // first.
- jobject java_object =
- object ? env->CallObjectMethodA(object, id, parameters)
- : env->CallStaticObjectMethodA(clazz, id, parameters);
- if (base::android::ClearException(env)) {
- SetInvocationFailure(kJavaExceptionRaised);
- return;
- }
- ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
- if (!scoped_java_object.obj()) {
- result_wrapper.Append(base::Value::CreateNullValue());
- break;
- }
- SetObjectResult(scoped_java_object, object_->GetSafeAnnotationClass());
- return;
- }
- }
- // This is for all cases except JavaType::TypeObject.
- if (!base::android::ClearException(env)) {
- SetPrimitiveResult(result_wrapper);
- } else {
- SetInvocationFailure(kJavaExceptionRaised);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.h b/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.h
deleted file mode 100644
index 89805ca0696..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_METHOD_INVOCATION_HELPER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_METHOD_INVOCATION_HELPER_H_
-
-#include <map>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/memory/ref_counted.h"
-#include "base/values.h"
-#include "content/browser/renderer_host/java/gin_java_bound_object.h"
-#include "content/browser/renderer_host/java/java_type.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class JavaMethod;
-
-// Instances of this class are created and initialized on the UI thread, do
-// their work on the background thread, and then again examined on the UI
-// thread. They don't work on both threads simultaneously, though.
-class CONTENT_EXPORT GinJavaMethodInvocationHelper
- : public base::RefCountedThreadSafe<GinJavaMethodInvocationHelper> {
- public:
- // DispatcherDelegate is used on the UI thread
- class DispatcherDelegate {
- public:
- DispatcherDelegate() {}
- virtual ~DispatcherDelegate() {}
- virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
- GinJavaBoundObject::ObjectID object_id) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DispatcherDelegate);
- };
-
- // ObjectDelegate is used in the background thread
- class ObjectDelegate {
- public:
- ObjectDelegate() {}
- virtual ~ObjectDelegate() {}
- virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
- JNIEnv* env) = 0;
- virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
- JNIEnv* env) = 0;
- virtual const JavaMethod* FindMethod(const std::string& method_name,
- size_t num_parameters) = 0;
- virtual bool IsObjectGetClassMethod(const JavaMethod* method) = 0;
- virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass() = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ObjectDelegate);
- };
-
- GinJavaMethodInvocationHelper(scoped_ptr<ObjectDelegate> object,
- const std::string& method_name,
- const base::ListValue& arguments);
- void Init(DispatcherDelegate* dispatcher);
-
- // Called on the background thread
- void Invoke();
-
- // Called on the UI thread
- bool HoldsPrimitiveResult();
- const base::ListValue& GetPrimitiveResult();
- const base::android::JavaRef<jobject>& GetObjectResult();
- const base::android::JavaRef<jclass>& GetSafeAnnotationClass();
- const std::string& GetErrorMessage();
-
- private:
- friend class base::RefCountedThreadSafe<GinJavaMethodInvocationHelper>;
- ~GinJavaMethodInvocationHelper();
-
- // Called on the UI thread
- void BuildObjectRefsFromListValue(DispatcherDelegate* dispatcher,
- const base::Value* list_value);
- void BuildObjectRefsFromDictionaryValue(DispatcherDelegate* dispatcher,
- const base::Value* dict_value);
-
- bool AppendObjectRef(DispatcherDelegate* dispatcher,
- const base::Value* raw_value);
-
- // Called on the background thread.
- void InvokeMethod(jobject object,
- jclass clazz,
- const JavaType& return_type,
- jmethodID id,
- jvalue* parameters);
- void SetInvocationFailure(const char* error_message);
- void SetPrimitiveResult(const base::ListValue& result_wrapper);
- void SetObjectResult(
- const base::android::JavaRef<jobject>& object,
- const base::android::JavaRef<jclass>& safe_annotation_clazz);
-
- typedef std::map<GinJavaBoundObject::ObjectID,
- JavaObjectWeakGlobalRef> ObjectRefs;
-
- scoped_ptr<ObjectDelegate> object_;
- const std::string method_name_;
- scoped_ptr<base::ListValue> arguments_;
- ObjectRefs object_refs_;
- bool holds_primitive_result_;
- scoped_ptr<base::ListValue> primitive_result_;
- std::string error_message_;
- base::android::ScopedJavaGlobalRef<jobject> object_result_;
- base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
-
- DISALLOW_COPY_AND_ASSIGN(GinJavaMethodInvocationHelper);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_METHOD_INVOCATION_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc b/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc
deleted file mode 100644
index d7634410dee..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/java/gin_java_method_invocation_helper.h"
-
-#include "base/android/jni_android.h"
-#include "content/common/android/gin_java_bridge_value.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-class NullObjectDelegate
- : public GinJavaMethodInvocationHelper::ObjectDelegate {
- public:
- NullObjectDelegate() {}
-
- virtual ~NullObjectDelegate() {}
-
- virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
- JNIEnv* env) OVERRIDE {
- return base::android::ScopedJavaLocalRef<jobject>();
- }
-
- virtual base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(
- JNIEnv* env) OVERRIDE {
- return base::android::ScopedJavaLocalRef<jclass>();
- }
-
- virtual const JavaMethod* FindMethod(const std::string& method_name,
- size_t num_parameters) OVERRIDE {
- return NULL;
- }
-
- virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE {
- return false;
- }
-
- virtual const base::android::JavaRef<jclass>& GetSafeAnnotationClass()
- OVERRIDE {
- return safe_annotation_class_;
- }
-
- private:
- base::android::ScopedJavaLocalRef<jclass> safe_annotation_class_;
-
- DISALLOW_COPY_AND_ASSIGN(NullObjectDelegate);
-};
-
-class NullDispatcherDelegate
- : public GinJavaMethodInvocationHelper::DispatcherDelegate {
- public:
- NullDispatcherDelegate() {}
-
- virtual ~NullDispatcherDelegate() {}
-
- virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
- GinJavaBoundObject::ObjectID object_id) OVERRIDE {
- return JavaObjectWeakGlobalRef();
- }
-
- DISALLOW_COPY_AND_ASSIGN(NullDispatcherDelegate);
-};
-
-} // namespace
-
-class GinJavaMethodInvocationHelperTest : public testing::Test {
-};
-
-namespace {
-
-class CountingDispatcherDelegate
- : public GinJavaMethodInvocationHelper::DispatcherDelegate {
- public:
- CountingDispatcherDelegate() {}
-
- virtual ~CountingDispatcherDelegate() {}
-
- virtual JavaObjectWeakGlobalRef GetObjectWeakRef(
- GinJavaBoundObject::ObjectID object_id) OVERRIDE {
- counters_[object_id]++;
- return JavaObjectWeakGlobalRef();
- }
-
- void AssertInvocationsCount(GinJavaBoundObject::ObjectID begin_object_id,
- GinJavaBoundObject::ObjectID end_object_id) {
- EXPECT_EQ(end_object_id - begin_object_id,
- static_cast<int>(counters_.size()));
- for (GinJavaBoundObject::ObjectID i = begin_object_id;
- i < end_object_id; ++i) {
- EXPECT_LT(0, counters_[i]) << "ObjectID: " << i;
- }
- }
-
- private:
- typedef std::map<GinJavaBoundObject::ObjectID, int> Counters;
- Counters counters_;
-
- DISALLOW_COPY_AND_ASSIGN(CountingDispatcherDelegate);
-};
-
-} // namespace
-
-TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsNoObjects) {
- base::ListValue no_objects;
- for (int i = 0; i < 10; ++i) {
- no_objects.AppendInteger(i);
- }
-
- scoped_refptr<GinJavaMethodInvocationHelper> helper =
- new GinJavaMethodInvocationHelper(
- scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
- new NullObjectDelegate()),
- "foo",
- no_objects);
- CountingDispatcherDelegate counter;
- helper->Init(&counter);
- counter.AssertInvocationsCount(0, 0);
-}
-
-TEST_F(GinJavaMethodInvocationHelperTest, RetrievalOfObjectsHaveObjects) {
- base::ListValue objects;
- objects.AppendInteger(100);
- objects.Append(GinJavaBridgeValue::CreateObjectIDValue(1).release());
- base::ListValue* sub_list = new base::ListValue();
- sub_list->AppendInteger(200);
- sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(2).release());
- objects.Append(sub_list);
- base::DictionaryValue* sub_dict = new base::DictionaryValue();
- sub_dict->SetInteger("1", 300);
- sub_dict->Set("2", GinJavaBridgeValue::CreateObjectIDValue(3).release());
- objects.Append(sub_dict);
- base::ListValue* sub_list_with_dict = new base::ListValue();
- base::DictionaryValue* sub_sub_dict = new base::DictionaryValue();
- sub_sub_dict->Set("1", GinJavaBridgeValue::CreateObjectIDValue(4).release());
- sub_list_with_dict->Append(sub_sub_dict);
- objects.Append(sub_list_with_dict);
- base::DictionaryValue* sub_dict_with_list = new base::DictionaryValue();
- base::ListValue* sub_sub_list = new base::ListValue();
- sub_sub_list->Append(GinJavaBridgeValue::CreateObjectIDValue(5).release());
- sub_dict_with_list->Set("1", sub_sub_list);
- objects.Append(sub_dict_with_list);
-
- scoped_refptr<GinJavaMethodInvocationHelper> helper =
- new GinJavaMethodInvocationHelper(
- scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
- new NullObjectDelegate()),
- "foo",
- objects);
- CountingDispatcherDelegate counter;
- helper->Init(&counter);
- counter.AssertInvocationsCount(1, 6);
-}
-
-TEST_F(GinJavaMethodInvocationHelperTest, HandleObjectIsGone) {
- base::ListValue no_objects;
- scoped_refptr<GinJavaMethodInvocationHelper> helper =
- new GinJavaMethodInvocationHelper(
- scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
- new NullObjectDelegate()),
- "foo",
- no_objects);
- NullDispatcherDelegate dispatcher;
- helper->Init(&dispatcher);
- EXPECT_TRUE(helper->GetErrorMessage().empty());
- helper->Invoke();
- EXPECT_TRUE(helper->HoldsPrimitiveResult());
- EXPECT_TRUE(helper->GetPrimitiveResult().empty());
- EXPECT_FALSE(helper->GetErrorMessage().empty());
-}
-
-namespace {
-
-class MethodNotFoundObjectDelegate : public NullObjectDelegate {
- public:
- MethodNotFoundObjectDelegate() : find_method_called_(false) {}
-
- virtual ~MethodNotFoundObjectDelegate() {}
-
- virtual base::android::ScopedJavaLocalRef<jobject> GetLocalRef(
- JNIEnv* env) OVERRIDE {
- return base::android::ScopedJavaLocalRef<jobject>(
- env, static_cast<jobject>(env->FindClass("java/lang/String")));
- }
-
- virtual const JavaMethod* FindMethod(const std::string& method_name,
- size_t num_parameters) OVERRIDE {
- find_method_called_ = true;
- return NULL;
- }
-
- bool find_method_called() const { return find_method_called_; }
-
- protected:
- bool find_method_called_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MethodNotFoundObjectDelegate);
-};
-
-} // namespace
-
-TEST_F(GinJavaMethodInvocationHelperTest, HandleMethodNotFound) {
- base::ListValue no_objects;
- MethodNotFoundObjectDelegate* object_delegate =
- new MethodNotFoundObjectDelegate();
- scoped_refptr<GinJavaMethodInvocationHelper> helper =
- new GinJavaMethodInvocationHelper(
- scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
- object_delegate),
- "foo",
- no_objects);
- NullDispatcherDelegate dispatcher;
- helper->Init(&dispatcher);
- EXPECT_FALSE(object_delegate->find_method_called());
- EXPECT_TRUE(helper->GetErrorMessage().empty());
- helper->Invoke();
- EXPECT_TRUE(object_delegate->find_method_called());
- EXPECT_TRUE(helper->HoldsPrimitiveResult());
- EXPECT_TRUE(helper->GetPrimitiveResult().empty());
- EXPECT_FALSE(helper->GetErrorMessage().empty());
-}
-
-namespace {
-
-class GetClassObjectDelegate : public MethodNotFoundObjectDelegate {
- public:
- GetClassObjectDelegate() : get_class_called_(false) {}
-
- virtual ~GetClassObjectDelegate() {}
-
- virtual const JavaMethod* FindMethod(const std::string& method_name,
- size_t num_parameters) OVERRIDE {
- find_method_called_ = true;
- return kFakeGetClass;
- }
-
- virtual bool IsObjectGetClassMethod(const JavaMethod* method) OVERRIDE {
- get_class_called_ = true;
- return kFakeGetClass == method;
- }
-
- bool get_class_called() const { return get_class_called_; }
-
- private:
- static const JavaMethod* kFakeGetClass;
- bool get_class_called_;
-
- DISALLOW_COPY_AND_ASSIGN(GetClassObjectDelegate);
-};
-
-// We don't expect GinJavaMethodInvocationHelper to actually invoke the
-// method, since the point of the test is to verify whether calls to
-// 'getClass' get blocked.
-const JavaMethod* GetClassObjectDelegate::kFakeGetClass =
- (JavaMethod*)0xdeadbeef;
-
-} // namespace
-
-TEST_F(GinJavaMethodInvocationHelperTest, HandleGetClassInvocation) {
- base::ListValue no_objects;
- GetClassObjectDelegate* object_delegate =
- new GetClassObjectDelegate();
- scoped_refptr<GinJavaMethodInvocationHelper> helper =
- new GinJavaMethodInvocationHelper(
- scoped_ptr<GinJavaMethodInvocationHelper::ObjectDelegate>(
- object_delegate),
- "foo",
- no_objects);
- NullDispatcherDelegate dispatcher;
- helper->Init(&dispatcher);
- EXPECT_FALSE(object_delegate->find_method_called());
- EXPECT_FALSE(object_delegate->get_class_called());
- EXPECT_TRUE(helper->GetErrorMessage().empty());
- helper->Invoke();
- EXPECT_TRUE(object_delegate->find_method_called());
- EXPECT_TRUE(object_delegate->get_class_called());
- EXPECT_TRUE(helper->HoldsPrimitiveResult());
- EXPECT_TRUE(helper->GetPrimitiveResult().empty());
- EXPECT_FALSE(helper->GetErrorMessage().empty());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc b/chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc
deleted file mode 100644
index 8f7c29f16eb..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h"
-
-#include <unistd.h>
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/common/android/gin_java_bridge_value.h"
-
-using base::android::ConvertUTF8ToJavaString;
-
-namespace content {
-
-namespace {
-
-const char kJavaLangString[] = "java/lang/String";
-const char kUndefined[] = "undefined";
-
-double RoundDoubleTowardsZero(const double& x) {
- if (std::isnan(x)) {
- return 0.0;
- }
- return x > 0.0 ? floor(x) : ceil(x);
-}
-
-// Rounds to jlong using Java's type conversion rules.
-jlong RoundDoubleToLong(const double& x) {
- double intermediate = RoundDoubleTowardsZero(x);
- // The int64 limits can not be converted exactly to double values, so we
- // compare to custom constants. kint64max is 2^63 - 1, but the spacing
- // between double values in the the range 2^62 to 2^63 is 2^10. The cast is
- // required to silence a spurious gcc warning for integer overflow.
- const int64 kLimit = (GG_INT64_C(1) << 63) - static_cast<uint64>(1 << 10);
- DCHECK(kLimit > 0);
- const double kLargestDoubleLessThanInt64Max = kLimit;
- const double kSmallestDoubleGreaterThanInt64Min = -kLimit;
- if (intermediate > kLargestDoubleLessThanInt64Max) {
- return kint64max;
- }
- if (intermediate < kSmallestDoubleGreaterThanInt64Min) {
- return kint64min;
- }
- return static_cast<jlong>(intermediate);
-}
-
-// Rounds to jint using Java's type conversion rules.
-jint RoundDoubleToInt(const double& x) {
- double intermediate = RoundDoubleTowardsZero(x);
- // The int32 limits cast exactly to double values.
- intermediate = std::min(intermediate, static_cast<double>(kint32max));
- intermediate = std::max(intermediate, static_cast<double>(kint32min));
- return static_cast<jint>(intermediate);
-}
-
-jvalue CoerceJavaScriptIntegerToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
-
- // For conversion to numeric types, we need to replicate Java's type
- // conversion rules. This requires that for integer values, we simply discard
- // all but the lowest n buts, where n is the number of bits in the target
- // type.
- jvalue result;
- int int_value;
- value->GetAsInteger(&int_value);
- switch (target_type.type) {
- case JavaType::TypeByte:
- result.b = static_cast<jbyte>(int_value);
- break;
- case JavaType::TypeChar:
- result.c = static_cast<jchar>(int_value);
- break;
- case JavaType::TypeShort:
- result.s = static_cast<jshort>(int_value);
- break;
- case JavaType::TypeInt:
- result.i = int_value;
- break;
- case JavaType::TypeLong:
- result.j = int_value;
- break;
- case JavaType::TypeFloat:
- result.f = int_value;
- break;
- case JavaType::TypeDouble:
- result.d = int_value;
- break;
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
- // requires handling object equivalents of primitive types.
- result.l = NULL;
- break;
- case JavaType::TypeString:
- result.l = coerce_to_string
- ? ConvertUTF8ToJavaString(
- env, base::Int64ToString(int_value)).Release()
- : NULL;
- break;
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires converting to false for 0 or NaN, true otherwise.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceJavaScriptDoubleToJavaValue(JNIEnv* env,
- double double_value,
- const JavaType& target_type,
- bool coerce_to_string) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
- // For conversion to numeric types, we need to replicate Java's type
- // conversion rules.
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeByte:
- result.b = static_cast<jbyte>(RoundDoubleToInt(double_value));
- break;
- case JavaType::TypeChar:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert double to 0.
- // Spec requires converting doubles similarly to how we convert doubles to
- // other numeric types.
- result.c = 0;
- break;
- case JavaType::TypeShort:
- result.s = static_cast<jshort>(RoundDoubleToInt(double_value));
- break;
- case JavaType::TypeInt:
- result.i = RoundDoubleToInt(double_value);
- break;
- case JavaType::TypeLong:
- result.j = RoundDoubleToLong(double_value);
- break;
- case JavaType::TypeFloat:
- result.f = static_cast<jfloat>(double_value);
- break;
- case JavaType::TypeDouble:
- result.d = double_value;
- break;
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
- // requires handling object equivalents of primitive types.
- result.l = NULL;
- break;
- case JavaType::TypeString:
- result.l =
- coerce_to_string
- ? ConvertUTF8ToJavaString(
- env, base::StringPrintf("%.6lg", double_value)).Release()
- : NULL;
- break;
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires converting to false for 0 or NaN, true otherwise.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceJavaScriptBooleanToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_BOOLEAN_VALUES.
- bool boolean_value;
- value->GetAsBoolean(&boolean_value);
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeBoolean:
- result.z = boolean_value ? JNI_TRUE : JNI_FALSE;
- break;
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires handling java.lang.Boolean and java.lang.Object.
- result.l = NULL;
- break;
- case JavaType::TypeString:
- result.l = coerce_to_string
- ? ConvertUTF8ToJavaString(
- env, boolean_value ? "true" : "false").Release()
- : NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeChar:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble: {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires converting to 0 or 1.
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceJavaScriptStringToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_STRING_VALUES.
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeString: {
- std::string string_result;
- value->GetAsString(&string_result);
- result.l = ConvertUTF8ToJavaString(env, string_result).Release();
- break;
- }
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires handling java.lang.Object.
- result.l = NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble: {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires using valueOf() method of corresponding object type.
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeChar:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires using java.lang.Short.decode().
- result.c = 0;
- break;
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires converting the empty string to false, otherwise true.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-// Note that this only handles primitive types and strings.
-jobject CreateJavaArray(JNIEnv* env, const JavaType& type, jsize length) {
- switch (type.type) {
- case JavaType::TypeBoolean:
- return env->NewBooleanArray(length);
- case JavaType::TypeByte:
- return env->NewByteArray(length);
- case JavaType::TypeChar:
- return env->NewCharArray(length);
- case JavaType::TypeShort:
- return env->NewShortArray(length);
- case JavaType::TypeInt:
- return env->NewIntArray(length);
- case JavaType::TypeLong:
- return env->NewLongArray(length);
- case JavaType::TypeFloat:
- return env->NewFloatArray(length);
- case JavaType::TypeDouble:
- return env->NewDoubleArray(length);
- case JavaType::TypeString: {
- base::android::ScopedJavaLocalRef<jclass> clazz(
- base::android::GetClass(env, kJavaLangString));
- return env->NewObjectArray(length, clazz.obj(), NULL);
- }
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- case JavaType::TypeArray:
- case JavaType::TypeObject:
- // Not handled.
- NOTREACHED();
- }
- return NULL;
-}
-
-// Sets the specified element of the supplied array to the value of the
-// supplied jvalue. Requires that the type of the array matches that of the
-// jvalue. Handles only primitive types and strings. Note that in the case of a
-// string, the array takes a new reference to the string object.
-void SetArrayElement(JNIEnv* env,
- jobject array,
- const JavaType& type,
- jsize index,
- const jvalue& value) {
- switch (type.type) {
- case JavaType::TypeBoolean:
- env->SetBooleanArrayRegion(static_cast<jbooleanArray>(array), index, 1,
- &value.z);
- break;
- case JavaType::TypeByte:
- env->SetByteArrayRegion(static_cast<jbyteArray>(array), index, 1,
- &value.b);
- break;
- case JavaType::TypeChar:
- env->SetCharArrayRegion(static_cast<jcharArray>(array), index, 1,
- &value.c);
- break;
- case JavaType::TypeShort:
- env->SetShortArrayRegion(static_cast<jshortArray>(array), index, 1,
- &value.s);
- break;
- case JavaType::TypeInt:
- env->SetIntArrayRegion(static_cast<jintArray>(array), index, 1,
- &value.i);
- break;
- case JavaType::TypeLong:
- env->SetLongArrayRegion(static_cast<jlongArray>(array), index, 1,
- &value.j);
- break;
- case JavaType::TypeFloat:
- env->SetFloatArrayRegion(static_cast<jfloatArray>(array), index, 1,
- &value.f);
- break;
- case JavaType::TypeDouble:
- env->SetDoubleArrayRegion(static_cast<jdoubleArray>(array), index, 1,
- &value.d);
- break;
- case JavaType::TypeString:
- env->SetObjectArrayElement(static_cast<jobjectArray>(array), index,
- value.l);
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- case JavaType::TypeArray:
- case JavaType::TypeObject:
- // Not handled.
- NOTREACHED();
- }
- base::android::CheckException(env);
-}
-
-jvalue CoerceJavaScriptNullOrUndefinedToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string) {
- bool is_undefined = false;
- scoped_ptr<const GinJavaBridgeValue> gin_value;
- if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) {
- gin_value = GinJavaBridgeValue::FromValue(value);
- if (gin_value->IsType(GinJavaBridgeValue::TYPE_UNDEFINED)) {
- is_undefined = true;
- }
- }
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeObject:
- result.l = NULL;
- break;
- case JavaType::TypeString:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert undefined to
- // "undefined". Spec requires converting undefined to NULL.
- result.l = (coerce_to_string && is_undefined)
- ? ConvertUTF8ToJavaString(env, kUndefined).Release()
- : NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeChar:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble: {
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeBoolean:
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jobject CoerceJavaScriptListToArray(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- const ObjectRefs& object_refs) {
- DCHECK_EQ(JavaType::TypeArray, target_type.type);
- const JavaType& target_inner_type = *target_type.inner_type.get();
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
- // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
- if (target_inner_type.type == JavaType::TypeArray) {
- return NULL;
- }
-
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
- // arrays. Spec requires handling object arrays.
- if (target_inner_type.type == JavaType::TypeObject) {
- return NULL;
- }
-
- const base::ListValue* list_value;
- value->GetAsList(&list_value);
- // Create the Java array.
- jsize length = static_cast<jsize>(list_value->GetSize());
- jobject result = CreateJavaArray(env, target_inner_type, length);
- if (!result) {
- return NULL;
- }
- scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
- for (jsize i = 0; i < length; ++i) {
- const base::Value* value_element = null_value.get();
- list_value->Get(i, &value_element);
- jvalue element = CoerceJavaScriptValueToJavaValue(
- env, value_element, target_inner_type, false, object_refs);
- SetArrayElement(env, result, target_inner_type, i, element);
- // CoerceJavaScriptValueToJavaValue() creates new local references to
- // strings, objects and arrays. Of these, only strings can occur here.
- // SetArrayElement() causes the array to take its own reference to the
- // string, so we can now release the local reference.
- DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
- DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
- ReleaseJavaValueIfRequired(env, &element, target_inner_type);
- }
-
- return result;
-}
-
-jobject CoerceJavaScriptDictionaryToArray(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- const ObjectRefs& object_refs) {
- DCHECK_EQ(JavaType::TypeArray, target_type.type);
-
- const JavaType& target_inner_type = *target_type.inner_type.get();
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
- // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
- if (target_inner_type.type == JavaType::TypeArray) {
- return NULL;
- }
-
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
- // arrays. Spec requires handling object arrays.
- if (target_inner_type.type == JavaType::TypeObject) {
- return NULL;
- }
-
- const base::DictionaryValue* dictionary_value;
- value->GetAsDictionary(&dictionary_value);
- const base::Value* length_value;
- // If the object does not have a length property, return null.
- if (!dictionary_value->Get("length", &length_value)) {
- return NULL;
- }
-
- // If the length property does not have numeric type, or is outside the valid
- // range for a Java array length, return null.
- jsize length = -1;
- if (length_value->IsType(base::Value::TYPE_INTEGER)) {
- int int_length;
- length_value->GetAsInteger(&int_length);
- if (int_length >= 0 && int_length <= kint32max) {
- length = static_cast<jsize>(int_length);
- }
- } else if (length_value->IsType(base::Value::TYPE_DOUBLE)) {
- double double_length;
- length_value->GetAsDouble(&double_length);
- if (double_length >= 0.0 && double_length <= kint32max) {
- length = static_cast<jsize>(double_length);
- }
- }
- if (length == -1) {
- return NULL;
- }
-
- jobject result = CreateJavaArray(env, target_inner_type, length);
- if (!result) {
- return NULL;
- }
- scoped_ptr<base::Value> null_value(base::Value::CreateNullValue());
- for (jsize i = 0; i < length; ++i) {
- const std::string key(base::IntToString(i));
- const base::Value* value_element = null_value.get();
- if (dictionary_value->HasKey(key)) {
- dictionary_value->Get(key, &value_element);
- }
- jvalue element = CoerceJavaScriptValueToJavaValue(
- env, value_element, target_inner_type, false, object_refs);
- SetArrayElement(env, result, target_inner_type, i, element);
- // CoerceJavaScriptValueToJavaValue() creates new local references to
- // strings, objects and arrays. Of these, only strings can occur here.
- // SetArrayElement() causes the array to take its own reference to the
- // string, so we can now release the local reference.
- DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
- DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
- ReleaseJavaValueIfRequired(env, &element, target_inner_type);
- }
-
- return result;
-}
-
-jvalue CoerceJavaScriptObjectToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string,
- const ObjectRefs& object_refs) {
- // This covers both JavaScript objects (including arrays) and Java objects.
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_OTHER_OBJECTS,
- // http://jdk6.java.net/plugin2/liveconnect/#JS_ARRAY_VALUES and
- // http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_OBJECTS
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeObject: {
- if (GinJavaBridgeValue::ContainsGinJavaBridgeValue(value)) {
- scoped_ptr<const GinJavaBridgeValue> gin_value(
- GinJavaBridgeValue::FromValue(value));
- DCHECK(gin_value);
- DCHECK(gin_value->IsType(GinJavaBridgeValue::TYPE_OBJECT_ID));
- base::android::ScopedJavaLocalRef<jobject> obj;
- GinJavaBoundObject::ObjectID object_id;
- if (gin_value->GetAsObjectID(&object_id)) {
- ObjectRefs::const_iterator iter = object_refs.find(object_id);
- if (iter != object_refs.end()) {
- obj.Reset(iter->second.get(env));
- }
- }
- result.l = obj.Release();
- } else {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to pass null. Spec
- // requires converting if the target type is
- // netscape.javascript.JSObject, otherwise raising a JavaScript
- // exception.
- result.l = NULL;
- }
- break;
- }
- case JavaType::TypeString:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to
- // "undefined". Spec requires calling toString() on the Java object.
- result.l = coerce_to_string
- ? ConvertUTF8ToJavaString(env, kUndefined).Release()
- : NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble:
- case JavaType::TypeChar: {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires raising a JavaScript exception.
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires raising a JavaScript exception.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- if (value->IsType(base::Value::TYPE_DICTIONARY)) {
- result.l = CoerceJavaScriptDictionaryToArray(
- env, value, target_type, object_refs);
- } else if (value->IsType(base::Value::TYPE_LIST)) {
- result.l =
- CoerceJavaScriptListToArray(env, value, target_type, object_refs);
- } else {
- result.l = NULL;
- }
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceGinJavaBridgeValueToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string,
- const ObjectRefs& object_refs) {
- DCHECK(GinJavaBridgeValue::ContainsGinJavaBridgeValue(value));
- scoped_ptr<const GinJavaBridgeValue> gin_value(
- GinJavaBridgeValue::FromValue(value));
- switch (gin_value->GetType()) {
- case GinJavaBridgeValue::TYPE_UNDEFINED:
- return CoerceJavaScriptNullOrUndefinedToJavaValue(
- env, value, target_type, coerce_to_string);
- case GinJavaBridgeValue::TYPE_NONFINITE: {
- float float_value;
- gin_value->GetAsNonFinite(&float_value);
- return CoerceJavaScriptDoubleToJavaValue(
- env, float_value, target_type, coerce_to_string);
- }
- case GinJavaBridgeValue::TYPE_OBJECT_ID:
- return CoerceJavaScriptObjectToJavaValue(
- env, value, target_type, coerce_to_string, object_refs);
- default:
- NOTREACHED();
- }
- return jvalue();
-}
-
-} // namespace
-
-
-void ReleaseJavaValueIfRequired(JNIEnv* env,
- jvalue* value,
- const JavaType& type) {
- if (type.type == JavaType::TypeString || type.type == JavaType::TypeObject ||
- type.type == JavaType::TypeArray) {
- env->DeleteLocalRef(value->l);
- value->l = NULL;
- }
-}
-
-jvalue CoerceJavaScriptValueToJavaValue(JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string,
- const ObjectRefs& object_refs) {
- // Note that in all these conversions, the relevant field of the jvalue must
- // always be explicitly set, as jvalue does not initialize its fields.
-
- switch (value->GetType()) {
- case base::Value::TYPE_INTEGER:
- return CoerceJavaScriptIntegerToJavaValue(
- env, value, target_type, coerce_to_string);
- case base::Value::TYPE_DOUBLE: {
- double double_value;
- value->GetAsDouble(&double_value);
- return CoerceJavaScriptDoubleToJavaValue(
- env, double_value, target_type, coerce_to_string);
- }
- case base::Value::TYPE_BOOLEAN:
- return CoerceJavaScriptBooleanToJavaValue(
- env, value, target_type, coerce_to_string);
- case base::Value::TYPE_STRING:
- return CoerceJavaScriptStringToJavaValue(env, value, target_type);
- case base::Value::TYPE_DICTIONARY:
- case base::Value::TYPE_LIST:
- return CoerceJavaScriptObjectToJavaValue(
- env, value, target_type, coerce_to_string, object_refs);
- case base::Value::TYPE_NULL:
- return CoerceJavaScriptNullOrUndefinedToJavaValue(
- env, value, target_type, coerce_to_string);
- case base::Value::TYPE_BINARY:
- return CoerceGinJavaBridgeValueToJavaValue(
- env, value, target_type, coerce_to_string, object_refs);
- }
- NOTREACHED();
- return jvalue();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h b/chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h
deleted file mode 100644
index 1df7345ecc6..00000000000
--- a/chromium/content/browser/renderer_host/java/gin_java_script_to_java_types_coercion.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_SCRIPT_TO_JAVA_TYPES_COERCION_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_SCRIPT_TO_JAVA_TYPES_COERCION_H_
-
-#include <map>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/values.h"
-#include "content/browser/renderer_host/java/gin_java_bound_object.h"
-#include "content/browser/renderer_host/java/java_type.h"
-
-namespace content {
-
-typedef std::map<GinJavaBoundObject::ObjectID, JavaObjectWeakGlobalRef>
- ObjectRefs;
-
-jvalue CoerceJavaScriptValueToJavaValue(
- JNIEnv* env,
- const base::Value* value,
- const JavaType& target_type,
- bool coerce_to_string,
- const ObjectRefs& object_refs);
-
-void ReleaseJavaValueIfRequired(JNIEnv* env,
- jvalue* value,
- const JavaType& type);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_GIN_JAVA_SCRIPT_TO_JAVA_TYPES_COERCION_H_
diff --git a/chromium/content/browser/renderer_host/java/java_bound_object.cc b/chromium/content/browser/renderer_host/java/java_bound_object.cc
deleted file mode 100644
index f812c429683..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bound_object.cc
+++ /dev/null
@@ -1,1040 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/java/java_bound_object.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/memory/singleton.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
-#include "content/browser/renderer_host/java/java_type.h"
-#include "content/browser/renderer_host/java/jni_helper.h"
-#include "content/public/browser/browser_thread.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-using base::StringPrintf;
-using base::android::AttachCurrentThread;
-using base::android::ConvertUTF8ToJavaString;
-using base::android::GetClass;
-using base::android::JavaRef;
-using base::android::ScopedJavaGlobalRef;
-using base::android::ScopedJavaLocalRef;
-using blink::WebBindings;
-
-// The conversion between JavaScript and Java types is based on the Live
-// Connect 2 spec. See
-// http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS.
-
-// Note that in some cases, we differ from from the spec in order to maintain
-// existing behavior. These areas are marked LIVECONNECT_COMPLIANCE. We may
-// revisit this decision in the future.
-
-namespace content {
-namespace {
-
-const char kJavaLangClass[] = "java/lang/Class";
-const char kJavaLangObject[] = "java/lang/Object";
-const char kJavaLangReflectMethod[] = "java/lang/reflect/Method";
-const char kJavaLangSecurityExceptionClass[] = "java/lang/SecurityException";
-const char kGetClass[] = "getClass";
-const char kGetMethods[] = "getMethods";
-const char kIsAnnotationPresent[] = "isAnnotationPresent";
-const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
-const char kReturningJavaLangReflectMethodArray[] =
- "()[Ljava/lang/reflect/Method;";
-const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z";
-// This is an exception message, so no need to localize.
-const char kAccessToObjectGetClassIsBlocked[] =
- "Access to java.lang.Object.getClass is blocked";
-
-// Our special NPObject type. We extend an NPObject with a pointer to a
-// JavaBoundObject. We also add static methods for each of the NPObject
-// callbacks, which are registered by our NPClass. These methods simply
-// delegate to the private implementation methods of JavaBoundObject.
-struct JavaNPObject : public NPObject {
- JavaBoundObject* bound_object;
-
- static const NPClass kNPClass;
-
- static NPObject* Allocate(NPP npp, NPClass* np_class);
- static void Deallocate(NPObject* np_object);
- static bool HasMethod(NPObject* np_object, NPIdentifier np_identifier);
- static bool Invoke(NPObject* np_object, NPIdentifier np_identifier,
- const NPVariant *args, uint32_t arg_count,
- NPVariant *result);
- static bool HasProperty(NPObject* np_object, NPIdentifier np_identifier);
- static bool GetProperty(NPObject* np_object, NPIdentifier np_identifier,
- NPVariant *result);
- static bool Enumerate(NPObject* object, NPIdentifier** values,
- uint32_t* count);
-};
-
-const NPClass JavaNPObject::kNPClass = {
- NP_CLASS_STRUCT_VERSION,
- JavaNPObject::Allocate,
- JavaNPObject::Deallocate,
- NULL, // NPInvalidate
- JavaNPObject::HasMethod,
- JavaNPObject::Invoke,
- NULL, // NPInvokeDefault
- JavaNPObject::HasProperty,
- JavaNPObject::GetProperty,
- NULL, // NPSetProperty,
- NULL, // NPRemoveProperty
- JavaNPObject::Enumerate,
- NULL,
-};
-
-NPObject* JavaNPObject::Allocate(NPP npp, NPClass* np_class) {
- JavaNPObject* obj = new JavaNPObject();
- return obj;
-}
-
-void JavaNPObject::Deallocate(NPObject* np_object) {
- JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(np_object);
- delete obj->bound_object;
- delete obj;
-}
-
-bool JavaNPObject::HasMethod(NPObject* np_object, NPIdentifier np_identifier) {
- std::string name(WebBindings::utf8FromIdentifier(np_identifier));
- JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(np_object);
- return obj->bound_object->HasMethod(name);
-}
-
-bool JavaNPObject::Invoke(NPObject* np_object, NPIdentifier np_identifier,
- const NPVariant* args, uint32_t arg_count,
- NPVariant* result) {
- std::string name(WebBindings::utf8FromIdentifier(np_identifier));
- JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(np_object);
- return obj->bound_object->Invoke(name, args, arg_count, result);
-}
-
-bool JavaNPObject::HasProperty(NPObject* np_object,
- NPIdentifier np_identifier) {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return false to indicate
- // that the property is not present. Spec requires supporting this correctly.
- return false;
-}
-
-bool JavaNPObject::GetProperty(NPObject* np_object,
- NPIdentifier np_identifier,
- NPVariant* result) {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return false to indicate
- // that the property is undefined. Spec requires supporting this correctly.
- return false;
-}
-
-bool JavaNPObject::Enumerate(NPObject* np_object, NPIdentifier** values,
- uint32_t* count) {
- JavaNPObject* obj = reinterpret_cast<JavaNPObject*>(np_object);
- if (!obj->bound_object->CanEnumerateMethods()) return false;
- std::vector<std::string> method_names = obj->bound_object->GetMethodNames();
- *count = base::saturated_cast<uint32_t>(method_names.size());
- *values = static_cast<NPIdentifier*>(calloc(*count, sizeof(NPIdentifier)));
- for (uint32_t i = 0; i < *count; ++i) {
- (*values)[i] = WebBindings::getStringIdentifier(method_names[i].c_str());
- }
- return true;
-}
-
-// Calls a Java method through JNI. If the Java method raises an uncaught
-// exception, it is cleared and this method returns false. Otherwise, this
-// method returns true and the Java method's return value is provided as an
-// NPVariant. Note that this method does not do any type coercion. The Java
-// return value is simply converted to the corresponding NPAPI type.
-bool CallJNIMethod(
- jobject object,
- jclass clazz,
- const JavaType& return_type,
- jmethodID id,
- jvalue* parameters,
- NPVariant* result,
- const JavaRef<jclass>& safe_annotation_clazz,
- const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager,
- bool can_enumerate_methods) {
- DCHECK(object || clazz);
- JNIEnv* env = AttachCurrentThread();
- switch (return_type.type) {
- case JavaType::TypeBoolean:
- BOOLEAN_TO_NPVARIANT(
- object ? env->CallBooleanMethodA(object, id, parameters)
- : env->CallStaticBooleanMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeByte:
- INT32_TO_NPVARIANT(
- object ? env->CallByteMethodA(object, id, parameters)
- : env->CallStaticByteMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeChar:
- INT32_TO_NPVARIANT(
- object ? env->CallCharMethodA(object, id, parameters)
- : env->CallStaticCharMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeShort:
- INT32_TO_NPVARIANT(
- object ? env->CallShortMethodA(object, id, parameters)
- : env->CallStaticShortMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeInt:
- INT32_TO_NPVARIANT(object
- ? env->CallIntMethodA(object, id, parameters)
- : env->CallStaticIntMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeLong:
- DOUBLE_TO_NPVARIANT(
- object ? env->CallLongMethodA(object, id, parameters)
- : env->CallStaticLongMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeFloat:
- DOUBLE_TO_NPVARIANT(
- object ? env->CallFloatMethodA(object, id, parameters)
- : env->CallStaticFloatMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeDouble:
- DOUBLE_TO_NPVARIANT(
- object ? env->CallDoubleMethodA(object, id, parameters)
- : env->CallStaticDoubleMethodA(clazz, id, parameters),
- *result);
- break;
- case JavaType::TypeVoid:
- if (object)
- env->CallVoidMethodA(object, id, parameters);
- else
- env->CallStaticVoidMethodA(clazz, id, parameters);
- VOID_TO_NPVARIANT(*result);
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to not call methods that
- // return arrays. Spec requires calling the method and converting the
- // result to a JavaScript array.
- VOID_TO_NPVARIANT(*result);
- break;
- case JavaType::TypeString: {
- jstring java_string = static_cast<jstring>(
- object ? env->CallObjectMethodA(object, id, parameters)
- : env->CallStaticObjectMethodA(clazz, id, parameters));
- // If an exception was raised, we must clear it before calling most JNI
- // methods. ScopedJavaLocalRef is liable to make such calls, so we test
- // first.
- if (base::android::ClearException(env)) {
- return false;
- }
- ScopedJavaLocalRef<jstring> scoped_java_string(env, java_string);
- if (!scoped_java_string.obj()) {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return undefined.
- // Spec requires returning a null string.
- VOID_TO_NPVARIANT(*result);
- break;
- }
- std::string str =
- base::android::ConvertJavaStringToUTF8(scoped_java_string);
- size_t length = str.length();
- // This pointer is freed in _NPN_ReleaseVariantValue in
- // third_party/WebKit/Source/WebCore/bindings/v8/npruntime.cpp.
- char* buffer = static_cast<char*>(malloc(length));
- str.copy(buffer, length, 0);
- STRINGN_TO_NPVARIANT(buffer, length, *result);
- break;
- }
- case JavaType::TypeObject: {
- // If an exception was raised, we must clear it before calling most JNI
- // methods. ScopedJavaLocalRef is liable to make such calls, so we test
- // first.
- jobject java_object =
- object ? env->CallObjectMethodA(object, id, parameters)
- : env->CallStaticObjectMethodA(clazz, id, parameters);
- if (base::android::ClearException(env)) {
- return false;
- }
- ScopedJavaLocalRef<jobject> scoped_java_object(env, java_object);
- if (!scoped_java_object.obj()) {
- NULL_TO_NPVARIANT(*result);
- break;
- }
- OBJECT_TO_NPVARIANT(JavaBoundObject::Create(scoped_java_object,
- safe_annotation_clazz,
- manager,
- can_enumerate_methods),
- *result);
- break;
- }
- }
- return !base::android::ClearException(env);
-}
-
-double RoundDoubleTowardsZero(const double& x) {
- if (std::isnan(x)) {
- return 0.0;
- }
- return x > 0.0 ? floor(x) : ceil(x);
-}
-
-// Rounds to jlong using Java's type conversion rules.
-jlong RoundDoubleToLong(const double& x) {
- double intermediate = RoundDoubleTowardsZero(x);
- // The int64 limits can not be converted exactly to double values, so we
- // compare to custom constants. kint64max is 2^63 - 1, but the spacing
- // between double values in the the range 2^62 to 2^63 is 2^10. The cast is
- // required to silence a spurious gcc warning for integer overflow.
- const int64 limit = (GG_INT64_C(1) << 63) - static_cast<uint64>(1 << 10);
- DCHECK(limit > 0);
- const double kLargestDoubleLessThanInt64Max = limit;
- const double kSmallestDoubleGreaterThanInt64Min = -limit;
- if (intermediate > kLargestDoubleLessThanInt64Max) {
- return kint64max;
- }
- if (intermediate < kSmallestDoubleGreaterThanInt64Min) {
- return kint64min;
- }
- return static_cast<jlong>(intermediate);
-}
-
-// Rounds to jint using Java's type conversion rules.
-jint RoundDoubleToInt(const double& x) {
- double intermediate = RoundDoubleTowardsZero(x);
- // The int32 limits cast exactly to double values.
- intermediate = std::min(intermediate, static_cast<double>(kint32max));
- intermediate = std::max(intermediate, static_cast<double>(kint32min));
- return static_cast<jint>(intermediate);
-}
-
-jvalue CoerceJavaScriptNumberToJavaValue(const NPVariant& variant,
- const JavaType& target_type,
- bool coerce_to_string) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_NUMBER_VALUES.
-
- // For conversion to numeric types, we need to replicate Java's type
- // conversion rules. This requires that for integer values, we simply discard
- // all but the lowest n buts, where n is the number of bits in the target
- // type. For double values, the logic is more involved.
- jvalue result;
- DCHECK(variant.type == NPVariantType_Int32 ||
- variant.type == NPVariantType_Double);
- bool is_double = variant.type == NPVariantType_Double;
- switch (target_type.type) {
- case JavaType::TypeByte:
- result.b = is_double ?
- static_cast<jbyte>(RoundDoubleToInt(NPVARIANT_TO_DOUBLE(variant))) :
- static_cast<jbyte>(NPVARIANT_TO_INT32(variant));
- break;
- case JavaType::TypeChar:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert double to 0.
- // Spec requires converting doubles similarly to how we convert doubles to
- // other numeric types.
- result.c = is_double ? 0 :
- static_cast<jchar>(NPVARIANT_TO_INT32(variant));
- break;
- case JavaType::TypeShort:
- result.s = is_double ?
- static_cast<jshort>(RoundDoubleToInt(NPVARIANT_TO_DOUBLE(variant))) :
- static_cast<jshort>(NPVARIANT_TO_INT32(variant));
- break;
- case JavaType::TypeInt:
- result.i = is_double ? RoundDoubleToInt(NPVARIANT_TO_DOUBLE(variant)) :
- NPVARIANT_TO_INT32(variant);
- break;
- case JavaType::TypeLong:
- result.j = is_double ? RoundDoubleToLong(NPVARIANT_TO_DOUBLE(variant)) :
- NPVARIANT_TO_INT32(variant);
- break;
- case JavaType::TypeFloat:
- result.f = is_double ? static_cast<jfloat>(NPVARIANT_TO_DOUBLE(variant)) :
- NPVARIANT_TO_INT32(variant);
- break;
- case JavaType::TypeDouble:
- result.d = is_double ? NPVARIANT_TO_DOUBLE(variant) :
- NPVARIANT_TO_INT32(variant);
- break;
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
- // requires handling object equivalents of primitive types.
- result.l = NULL;
- break;
- case JavaType::TypeString:
- result.l = coerce_to_string ?
- ConvertUTF8ToJavaString(
- AttachCurrentThread(),
- is_double ?
- base::StringPrintf("%.6lg", NPVARIANT_TO_DOUBLE(variant)) :
- base::Int64ToString(NPVARIANT_TO_INT32(variant))).Release() :
- NULL;
- break;
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires converting to false for 0 or NaN, true otherwise.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to null. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceJavaScriptBooleanToJavaValue(const NPVariant& variant,
- const JavaType& target_type,
- bool coerce_to_string) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_BOOLEAN_VALUES.
- DCHECK_EQ(NPVariantType_Bool, variant.type);
- bool boolean_value = NPVARIANT_TO_BOOLEAN(variant);
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeBoolean:
- result.z = boolean_value ? JNI_TRUE : JNI_FALSE;
- break;
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires handling java.lang.Boolean and java.lang.Object.
- result.l = NULL;
- break;
- case JavaType::TypeString:
- result.l = coerce_to_string ?
- ConvertUTF8ToJavaString(AttachCurrentThread(),
- boolean_value ? "true" : "false").Release() :
- NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeChar:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble: {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires converting to 0 or 1.
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceJavaScriptStringToJavaValue(const NPVariant& variant,
- const JavaType& target_type) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_STRING_VALUES.
- DCHECK_EQ(NPVariantType_String, variant.type);
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeString:
- result.l = ConvertUTF8ToJavaString(
- AttachCurrentThread(),
- base::StringPiece(NPVARIANT_TO_STRING(variant).UTF8Characters,
- NPVARIANT_TO_STRING(variant).UTF8Length)).Release();
- break;
- case JavaType::TypeObject:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires handling java.lang.Object.
- result.l = NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble: {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires using valueOf() method of corresponding object type.
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeChar:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires using java.lang.Short.decode().
- result.c = 0;
- break;
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires converting the empty string to false, otherwise true.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-// Note that this only handles primitive types and strings.
-jobject CreateJavaArray(const JavaType& type, jsize length) {
- JNIEnv* env = AttachCurrentThread();
- switch (type.type) {
- case JavaType::TypeBoolean:
- return env->NewBooleanArray(length);
- case JavaType::TypeByte:
- return env->NewByteArray(length);
- case JavaType::TypeChar:
- return env->NewCharArray(length);
- case JavaType::TypeShort:
- return env->NewShortArray(length);
- case JavaType::TypeInt:
- return env->NewIntArray(length);
- case JavaType::TypeLong:
- return env->NewLongArray(length);
- case JavaType::TypeFloat:
- return env->NewFloatArray(length);
- case JavaType::TypeDouble:
- return env->NewDoubleArray(length);
- case JavaType::TypeString: {
- ScopedJavaLocalRef<jclass> clazz(GetClass(env, "java/lang/String"));
- return env->NewObjectArray(length, clazz.obj(), NULL);
- }
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- case JavaType::TypeArray:
- case JavaType::TypeObject:
- // Not handled.
- NOTREACHED();
- }
- return NULL;
-}
-
-// Sets the specified element of the supplied array to the value of the
-// supplied jvalue. Requires that the type of the array matches that of the
-// jvalue. Handles only primitive types and strings. Note that in the case of a
-// string, the array takes a new reference to the string object.
-void SetArrayElement(jobject array,
- const JavaType& type,
- jsize index,
- const jvalue& value) {
- JNIEnv* env = AttachCurrentThread();
- switch (type.type) {
- case JavaType::TypeBoolean:
- env->SetBooleanArrayRegion(static_cast<jbooleanArray>(array), index, 1,
- &value.z);
- break;
- case JavaType::TypeByte:
- env->SetByteArrayRegion(static_cast<jbyteArray>(array), index, 1,
- &value.b);
- break;
- case JavaType::TypeChar:
- env->SetCharArrayRegion(static_cast<jcharArray>(array), index, 1,
- &value.c);
- break;
- case JavaType::TypeShort:
- env->SetShortArrayRegion(static_cast<jshortArray>(array), index, 1,
- &value.s);
- break;
- case JavaType::TypeInt:
- env->SetIntArrayRegion(static_cast<jintArray>(array), index, 1,
- &value.i);
- break;
- case JavaType::TypeLong:
- env->SetLongArrayRegion(static_cast<jlongArray>(array), index, 1,
- &value.j);
- break;
- case JavaType::TypeFloat:
- env->SetFloatArrayRegion(static_cast<jfloatArray>(array), index, 1,
- &value.f);
- break;
- case JavaType::TypeDouble:
- env->SetDoubleArrayRegion(static_cast<jdoubleArray>(array), index, 1,
- &value.d);
- break;
- case JavaType::TypeString:
- env->SetObjectArrayElement(static_cast<jobjectArray>(array), index,
- value.l);
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- case JavaType::TypeArray:
- case JavaType::TypeObject:
- // Not handled.
- NOTREACHED();
- }
- base::android::CheckException(env);
-}
-
-void ReleaseJavaValueIfRequired(JNIEnv* env,
- jvalue* value,
- const JavaType& type) {
- if (type.type == JavaType::TypeString ||
- type.type == JavaType::TypeObject ||
- type.type == JavaType::TypeArray) {
- env->DeleteLocalRef(value->l);
- value->l = NULL;
- }
-}
-
-jvalue CoerceJavaScriptValueToJavaValue(const NPVariant& variant,
- const JavaType& target_type,
- bool coerce_to_string);
-
-// Returns a new local reference to a Java array.
-jobject CoerceJavaScriptObjectToArray(const NPVariant& variant,
- const JavaType& target_type) {
- DCHECK_EQ(JavaType::TypeArray, target_type.type);
- NPObject* object = NPVARIANT_TO_OBJECT(variant);
- DCHECK_NE(&JavaNPObject::kNPClass, object->_class);
-
- const JavaType& target_inner_type = *target_type.inner_type.get();
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for
- // multi-dimensional arrays. Spec requires handling multi-demensional arrays.
- if (target_inner_type.type == JavaType::TypeArray) {
- return NULL;
- }
-
- // LIVECONNECT_COMPLIANCE: Existing behavior is to return null for object
- // arrays. Spec requires handling object arrays.
- if (target_inner_type.type == JavaType::TypeObject) {
- return NULL;
- }
-
- // If the object does not have a length property, return null.
- NPVariant length_variant;
- if (!WebBindings::getProperty(0, object,
- WebBindings::getStringIdentifier("length"),
- &length_variant)) {
- WebBindings::releaseVariantValue(&length_variant);
- return NULL;
- }
-
- // If the length property does not have numeric type, or is outside the valid
- // range for a Java array length, return null.
- jsize length = -1;
- if (NPVARIANT_IS_INT32(length_variant)
- && NPVARIANT_TO_INT32(length_variant) >= 0) {
- length = NPVARIANT_TO_INT32(length_variant);
- } else if (NPVARIANT_IS_DOUBLE(length_variant)
- && NPVARIANT_TO_DOUBLE(length_variant) >= 0.0
- && NPVARIANT_TO_DOUBLE(length_variant) <= kint32max) {
- length = static_cast<jsize>(NPVARIANT_TO_DOUBLE(length_variant));
- }
- WebBindings::releaseVariantValue(&length_variant);
- if (length == -1) {
- return NULL;
- }
-
- // Create the Java array.
- // TODO(steveblock): Handle failure to create the array.
- jobject result = CreateJavaArray(target_inner_type, length);
- NPVariant value_variant;
- JNIEnv* env = AttachCurrentThread();
- for (jsize i = 0; i < length; ++i) {
- // It seems that getProperty() will set the variant to type void on failure,
- // but this doesn't seem to be documented, so do it explicitly here for
- // safety.
- VOID_TO_NPVARIANT(value_variant);
- // If this fails, for example due to a missing element, we simply treat the
- // value as JavaScript undefined.
- WebBindings::getProperty(0, object, WebBindings::getIntIdentifier(i),
- &value_variant);
- jvalue element = CoerceJavaScriptValueToJavaValue(value_variant,
- target_inner_type,
- false);
- SetArrayElement(result, target_inner_type, i, element);
- // CoerceJavaScriptValueToJavaValue() creates new local references to
- // strings, objects and arrays. Of these, only strings can occur here.
- // SetArrayElement() causes the array to take its own reference to the
- // string, so we can now release the local reference.
- DCHECK_NE(JavaType::TypeObject, target_inner_type.type);
- DCHECK_NE(JavaType::TypeArray, target_inner_type.type);
- ReleaseJavaValueIfRequired(env, &element, target_inner_type);
- WebBindings::releaseVariantValue(&value_variant);
- }
-
- return result;
-}
-
-jvalue CoerceJavaScriptObjectToJavaValue(const NPVariant& variant,
- const JavaType& target_type,
- bool coerce_to_string) {
- // This covers both JavaScript objects (including arrays) and Java objects.
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_OTHER_OBJECTS,
- // http://jdk6.java.net/plugin2/liveconnect/#JS_ARRAY_VALUES and
- // http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_OBJECTS
- DCHECK_EQ(NPVariantType_Object, variant.type);
-
- NPObject* object = NPVARIANT_TO_OBJECT(variant);
- bool is_java_object = &JavaNPObject::kNPClass == object->_class;
-
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeObject:
- if (is_java_object) {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to pass all Java
- // objects. Spec requires passing only Java objects which are
- // assignment-compatibile.
- result.l = AttachCurrentThread()->NewLocalRef(
- JavaBoundObject::GetJavaObject(object).obj());
- } else {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to pass null. Spec
- // requires converting if the target type is
- // netscape.javascript.JSObject, otherwise raising a JavaScript
- // exception.
- result.l = NULL;
- }
- break;
- case JavaType::TypeString:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to
- // "undefined". Spec requires calling toString() on the Java object.
- result.l = coerce_to_string ?
- ConvertUTF8ToJavaString(AttachCurrentThread(), "undefined").
- Release() :
- NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble:
- case JavaType::TypeChar: {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to 0. Spec
- // requires raising a JavaScript exception.
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeBoolean:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to false. Spec
- // requires raising a JavaScript exception.
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- if (is_java_object) {
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- } else {
- result.l = CoerceJavaScriptObjectToArray(variant, target_type);
- }
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-jvalue CoerceJavaScriptNullOrUndefinedToJavaValue(const NPVariant& variant,
- const JavaType& target_type,
- bool coerce_to_string) {
- // See http://jdk6.java.net/plugin2/liveconnect/#JS_NULL.
- DCHECK(variant.type == NPVariantType_Null ||
- variant.type == NPVariantType_Void);
- jvalue result;
- switch (target_type.type) {
- case JavaType::TypeObject:
- result.l = NULL;
- break;
- case JavaType::TypeString:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert undefined to
- // "undefined". Spec requires converting undefined to NULL.
- result.l = (coerce_to_string && variant.type == NPVariantType_Void) ?
- ConvertUTF8ToJavaString(AttachCurrentThread(), "undefined").
- Release() :
- NULL;
- break;
- case JavaType::TypeByte:
- case JavaType::TypeChar:
- case JavaType::TypeShort:
- case JavaType::TypeInt:
- case JavaType::TypeLong:
- case JavaType::TypeFloat:
- case JavaType::TypeDouble: {
- jvalue null_value = {0};
- result = null_value;
- break;
- }
- case JavaType::TypeBoolean:
- result.z = JNI_FALSE;
- break;
- case JavaType::TypeArray:
- // LIVECONNECT_COMPLIANCE: Existing behavior is to convert to NULL. Spec
- // requires raising a JavaScript exception.
- result.l = NULL;
- break;
- case JavaType::TypeVoid:
- // Conversion to void must never happen.
- NOTREACHED();
- break;
- }
- return result;
-}
-
-// coerce_to_string means that we should try to coerce all JavaScript values to
-// strings when required, rather than simply converting to NULL. This is used
-// to maintain current behaviour, which differs slightly depending upon whether
-// or not the coercion in question is for an array element.
-//
-// Note that the jvalue returned by this method may contain a new local
-// reference to an object (string, object or array). This must be released by
-// the caller.
-jvalue CoerceJavaScriptValueToJavaValue(const NPVariant& variant,
- const JavaType& target_type,
- bool coerce_to_string) {
- // Note that in all these conversions, the relevant field of the jvalue must
- // always be explicitly set, as jvalue does not initialize its fields.
-
- switch (variant.type) {
- case NPVariantType_Int32:
- case NPVariantType_Double:
- return CoerceJavaScriptNumberToJavaValue(variant, target_type,
- coerce_to_string);
- case NPVariantType_Bool:
- return CoerceJavaScriptBooleanToJavaValue(variant, target_type,
- coerce_to_string);
- case NPVariantType_String:
- return CoerceJavaScriptStringToJavaValue(variant, target_type);
- case NPVariantType_Object:
- return CoerceJavaScriptObjectToJavaValue(variant, target_type,
- coerce_to_string);
- case NPVariantType_Null:
- case NPVariantType_Void:
- return CoerceJavaScriptNullOrUndefinedToJavaValue(variant, target_type,
- coerce_to_string);
- }
- NOTREACHED();
- return jvalue();
-}
-
-} // namespace
-
-NPObject* JavaBoundObject::Create(
- const JavaRef<jobject>& object,
- const JavaRef<jclass>& safe_annotation_clazz,
- const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager,
- bool can_enumerate_methods) {
- // The first argument (a plugin's instance handle) is passed through to the
- // allocate function directly, and we don't use it, so it's ok to be 0.
- // The object is created with a ref count of one.
- NPObject* np_object = WebBindings::createObject(0, const_cast<NPClass*>(
- &JavaNPObject::kNPClass));
- // The NPObject takes ownership of the JavaBoundObject.
- reinterpret_cast<JavaNPObject*>(np_object)->bound_object =
- new JavaBoundObject(
- object, safe_annotation_clazz, manager, can_enumerate_methods);
- return np_object;
-}
-
-JavaBoundObject::JavaBoundObject(
- const JavaRef<jobject>& object,
- const JavaRef<jclass>& safe_annotation_clazz,
- const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager,
- bool can_enumerate_methods)
- : java_object_(AttachCurrentThread(), object.obj()),
- manager_(manager),
- are_methods_set_up_(false),
- object_get_class_method_id_(NULL),
- can_enumerate_methods_(can_enumerate_methods),
- safe_annotation_clazz_(safe_annotation_clazz) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&JavaBridgeDispatcherHostManager::JavaBoundObjectCreated,
- manager_,
- base::android::ScopedJavaGlobalRef<jobject>(object)));
- // Other than informing the JavaBridgeDispatcherHostManager that a java bound
- // object has been created (above), we don't do anything else with our Java
- // object when first created. We do it all lazily when a method is first
- // invoked.
-}
-
-JavaBoundObject::~JavaBoundObject() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&JavaBridgeDispatcherHostManager::JavaBoundObjectDestroyed,
- manager_,
- base::android::ScopedJavaGlobalRef<jobject>(
- java_object_.get(AttachCurrentThread()))));
-}
-
-ScopedJavaLocalRef<jobject> JavaBoundObject::GetJavaObject(NPObject* object) {
- DCHECK_EQ(&JavaNPObject::kNPClass, object->_class);
- JavaBoundObject* jbo = reinterpret_cast<JavaNPObject*>(object)->bound_object;
- return jbo->java_object_.get(AttachCurrentThread());
-}
-
-std::vector<std::string> JavaBoundObject::GetMethodNames() const {
- EnsureMethodsAreSetUp();
- std::vector<std::string> result;
- for (JavaMethodMap::const_iterator it = methods_.begin();
- it != methods_.end();
- it = methods_.upper_bound(it->first)) {
- result.push_back(it->first);
- }
- return result;
-}
-
-bool JavaBoundObject::HasMethod(const std::string& name) const {
- EnsureMethodsAreSetUp();
- return methods_.find(name) != methods_.end();
-}
-
-bool JavaBoundObject::Invoke(const std::string& name, const NPVariant* args,
- size_t arg_count, NPVariant* result) {
- EnsureMethodsAreSetUp();
-
- // Get all methods with the correct name.
- std::pair<JavaMethodMap::const_iterator, JavaMethodMap::const_iterator>
- iters = methods_.equal_range(name);
- if (iters.first == iters.second) {
- return false;
- }
-
- // Take the first method with the correct number of arguments.
- JavaMethod* method = NULL;
- for (JavaMethodMap::const_iterator iter = iters.first; iter != iters.second;
- ++iter) {
- if (iter->second->num_parameters() == arg_count) {
- method = iter->second.get();
- break;
- }
- }
- if (!method) {
- return false;
- }
-
- // Block access to java.lang.Object.getClass.
- // As it is declared to be final, it is sufficient to compare methodIDs.
- if (method->id() == object_get_class_method_id_) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&JavaBoundObject::ThrowSecurityException,
- kAccessToObjectGetClassIsBlocked));
- return false;
- }
-
- // Coerce
- std::vector<jvalue> parameters(arg_count);
- for (size_t i = 0; i < arg_count; ++i) {
- parameters[i] = CoerceJavaScriptValueToJavaValue(args[i],
- method->parameter_type(i),
- true);
- }
-
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jobject> obj;
- ScopedJavaLocalRef<jclass> cls;
- bool ok = false;
- if (method->is_static()) {
- cls = GetLocalClassRef(env);
- } else {
- obj = java_object_.get(env);
- }
- if (!obj.is_null() || !cls.is_null()) {
- // Call
- ok = CallJNIMethod(obj.obj(), cls.obj(), method->return_type(),
- method->id(), &parameters[0], result,
- safe_annotation_clazz_,
- manager_,
- can_enumerate_methods_);
- }
-
- // Now that we're done with the jvalue, release any local references created
- // by CoerceJavaScriptValueToJavaValue().
- for (size_t i = 0; i < arg_count; ++i) {
- ReleaseJavaValueIfRequired(env, &parameters[i], method->parameter_type(i));
- }
-
- return ok;
-}
-
-ScopedJavaLocalRef<jclass> JavaBoundObject::GetLocalClassRef(
- JNIEnv* env) const {
- if (!object_get_class_method_id_) {
- object_get_class_method_id_ = GetMethodIDFromClassName(
- env, kJavaLangObject, kGetClass, kReturningJavaLangClass);
- }
-
- ScopedJavaLocalRef<jobject> obj = java_object_.get(env);
- if (!obj.is_null()) {
- return ScopedJavaLocalRef<jclass>(env, static_cast<jclass>(
- env->CallObjectMethod(obj.obj(), object_get_class_method_id_)));
- } else {
- return ScopedJavaLocalRef<jclass>();
- }
-}
-
-void JavaBoundObject::EnsureMethodsAreSetUp() const {
- if (are_methods_set_up_)
- return;
- are_methods_set_up_ = true;
-
- JNIEnv* env = AttachCurrentThread();
-
- ScopedJavaLocalRef<jclass> clazz = GetLocalClassRef(env);
- if (clazz.is_null()) {
- return;
- }
-
- ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>(
- env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangClass,
- kGetMethods,
- kReturningJavaLangReflectMethodArray))));
-
- size_t num_methods = env->GetArrayLength(methods.obj());
- // Java objects always have public methods.
- DCHECK(num_methods);
-
- for (size_t i = 0; i < num_methods; ++i) {
- ScopedJavaLocalRef<jobject> java_method(
- env,
- env->GetObjectArrayElement(methods.obj(), i));
-
- if (!safe_annotation_clazz_.is_null()) {
- jboolean safe = env->CallBooleanMethod(java_method.obj(),
- GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kIsAnnotationPresent,
- kTakesJavaLangClassReturningBoolean),
- safe_annotation_clazz_.obj());
-
- if (!safe)
- continue;
- }
-
- JavaMethod* method = new JavaMethod(java_method);
- methods_.insert(std::make_pair(method->name(), method));
- }
-}
-
-// static
-void JavaBoundObject::ThrowSecurityException(const char* message) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- JNIEnv* env = AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jclass> clazz(
- env, env->FindClass(kJavaLangSecurityExceptionClass));
- env->ThrowNew(clazz.obj(), message);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_bound_object.h b/chromium/content/browser/renderer_host/java/java_bound_object.h
deleted file mode 100644
index f29aed6df1b..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bound_object.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BOUND_OBJECT_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BOUND_OBJECT_H_
-
-#include <jni.h>
-#include <map>
-#include <string>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/renderer_host/java/java_method.h"
-#include "third_party/npapi/bindings/npruntime.h"
-
-namespace content {
-
-class JavaBridgeDispatcherHostManager;
-
-// Wrapper around a Java object.
-//
-// Represents a Java object for use in the Java bridge. Holds a global ref to
-// the Java object and provides the ability to invoke methods on it.
-// Interrogation of the Java object for its methods is done lazily. This class
-// is not generally threadsafe. However, it does allow for instances to be
-// created and destroyed on different threads.
-class JavaBoundObject {
- public:
- // Takes a Java object and creates a JavaBoundObject around it. If
- // |safe_annotation_clazz| annotation is non-null, the method is exposed
- // to JavaScript. Returns an NPObject with a ref count of one which owns the
- // JavaBoundObject.
- // See also comment below for |manager_|.
- static NPObject* Create(
- const base::android::JavaRef<jobject>& object,
- const base::android::JavaRef<jclass>& safe_annotation_clazz,
- const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager,
- bool can_enumerate_methods);
-
- virtual ~JavaBoundObject();
-
- // Gets a local ref to the underlying JavaObject from a JavaBoundObject
- // wrapped as an NPObject. May return null if the underlying object has
- // been garbage collected.
- static base::android::ScopedJavaLocalRef<jobject> GetJavaObject(
- NPObject* object);
-
- // Methods to implement the NPObject callbacks.
- bool CanEnumerateMethods() const { return can_enumerate_methods_; }
- std::vector<std::string> GetMethodNames() const;
- bool HasMethod(const std::string& name) const;
- bool Invoke(const std::string& name, const NPVariant* args, size_t arg_count,
- NPVariant* result);
-
- private:
- JavaBoundObject(
- const base::android::JavaRef<jobject>& object,
- const base::android::JavaRef<jclass>& safe_annotation_clazz,
- const base::WeakPtr<JavaBridgeDispatcherHostManager>& manager,
- bool can_enumerate_methods);
-
- void EnsureMethodsAreSetUp() const;
- base::android::ScopedJavaLocalRef<jclass> GetLocalClassRef(JNIEnv* env) const;
-
- static void ThrowSecurityException(const char* message);
-
- // The weak ref to the underlying Java object that this JavaBoundObject
- // instance represents.
- JavaObjectWeakGlobalRef java_object_;
-
- // Keep a pointer back to the JavaBridgeDispatcherHostManager so that we
- // can notify it when this JavaBoundObject is destroyed. JavaBoundObjects
- // may outlive the manager so keep a WeakPtr. Note the WeakPtr may only be
- // dereferenced on the UI thread.
- base::WeakPtr<JavaBridgeDispatcherHostManager> manager_;
-
- // Map of public methods, from method name to Method instance. Multiple
- // entries will be present for overloaded methods. Note that we can't use
- // scoped_ptr in STL containers as we can't copy it.
- typedef std::multimap<std::string, linked_ptr<JavaMethod> > JavaMethodMap;
- mutable JavaMethodMap methods_;
- mutable bool are_methods_set_up_;
- mutable jmethodID object_get_class_method_id_;
- const bool can_enumerate_methods_;
-
- base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(JavaBoundObject);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BOUND_OBJECT_H_
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_channel_host.cc b/chromium/content/browser/renderer_host/java/java_bridge_channel_host.cc
deleted file mode 100644
index 8f53b9d99a8..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bridge_channel_host.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2011 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 "content/browser/renderer_host/java/java_bridge_channel_host.h"
-
-#include "base/atomicops.h"
-#include "base/lazy_instance.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "content/common/java_bridge_messages.h"
-
-using base::WaitableEvent;
-
-namespace content {
-namespace {
-struct WaitableEventLazyInstanceTraits
- : public base::DefaultLazyInstanceTraits<WaitableEvent> {
- static WaitableEvent* New(void* instance) {
- // Use placement new to initialize our instance in our preallocated space.
- // The parenthesis is very important here to force POD type initialization.
- return new (instance) WaitableEvent(false, false);
- }
-};
-base::LazyInstance<WaitableEvent, WaitableEventLazyInstanceTraits> dummy_event =
- LAZY_INSTANCE_INITIALIZER;
-
-base::subtle::AtomicWord g_last_id = 0;
-}
-
-JavaBridgeChannelHost::~JavaBridgeChannelHost() {
-#if defined(OS_POSIX)
- if (channel_handle_.socket.fd > 0) {
- close(channel_handle_.socket.fd);
- }
-#endif
-}
-
-JavaBridgeChannelHost* JavaBridgeChannelHost::GetJavaBridgeChannelHost(
- int renderer_id,
- base::MessageLoopProxy* ipc_message_loop) {
- std::string channel_name(base::StringPrintf("r%d.javabridge", renderer_id));
- // There's no need for a shutdown event here. If the browser is terminated
- // while the JavaBridgeChannelHost is blocked on a synchronous IPC call, the
- // renderer's shutdown event will cause the underlying channel to shut down,
- // thus terminating the IPC call.
- return static_cast<JavaBridgeChannelHost*>(NPChannelBase::GetChannel(
- channel_name,
- IPC::Channel::MODE_SERVER,
- ClassFactory,
- ipc_message_loop,
- true,
- dummy_event.Pointer()));
-}
-
-int JavaBridgeChannelHost::ThreadsafeGenerateRouteID() {
- return base::subtle::NoBarrier_AtomicIncrement(&g_last_id, 1);
-}
-
-int JavaBridgeChannelHost::GenerateRouteID() {
- return ThreadsafeGenerateRouteID();
-}
-
-bool JavaBridgeChannelHost::Init(base::MessageLoopProxy* ipc_message_loop,
- bool create_pipe_now,
- WaitableEvent* shutdown_event) {
- if (!NPChannelBase::Init(ipc_message_loop, create_pipe_now, shutdown_event)) {
- return false;
- }
-
- // Finish populating our ChannelHandle.
-#if defined(OS_POSIX)
- // We take control of the FD for all session between this host and
- // the corresponding renderers. We keep it open until this object
- // is deleted.
- channel_handle_.socket.fd = channel_->TakeClientFileDescriptor();
-#endif
-
- return true;
-}
-
-bool JavaBridgeChannelHost::OnControlMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(JavaBridgeChannelHost, message)
- IPC_MESSAGE_HANDLER(JavaBridgeMsg_GenerateRouteID, OnGenerateRouteID)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void JavaBridgeChannelHost::OnGenerateRouteID(int* route_id) {
- *route_id = GenerateRouteID();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_channel_host.h b/chromium/content/browser/renderer_host/java/java_bridge_channel_host.h
deleted file mode 100644
index 3f3f1468e9b..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bridge_channel_host.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_CHANNEL_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_CHANNEL_HOST_H_
-
-#include "content/child/npapi/np_channel_base.h"
-
-namespace content {
-
-class JavaBridgeChannelHost : public NPChannelBase {
- public:
- static JavaBridgeChannelHost* GetJavaBridgeChannelHost(
- int renderer_id,
- base::MessageLoopProxy* ipc_message_loop);
-
- // A threadsafe function to generate a unique route ID. Used by the
- // JavaBridgeDispatcherHost on the UI thread and this class on the Java
- // Bridge's background thread.
- static int ThreadsafeGenerateRouteID();
-
- // NPChannelBase implementation:
- virtual int GenerateRouteID() OVERRIDE;
-
- // NPChannelBase override:
- virtual bool Init(base::MessageLoopProxy* ipc_message_loop,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) OVERRIDE;
-
- protected:
- // NPChannelBase override:
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
-
- private:
- JavaBridgeChannelHost() {}
- friend class base::RefCountedThreadSafe<JavaBridgeChannelHost>;
- virtual ~JavaBridgeChannelHost();
-
- static NPChannelBase* ClassFactory() {
- return new JavaBridgeChannelHost();
- }
-
- // Message handlers
- void OnGenerateRouteID(int* route_id);
-
- DISALLOW_COPY_AND_ASSIGN(JavaBridgeChannelHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_CHANNEL_HOST_H_
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
deleted file mode 100644
index 922b03a55e8..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/java/java_bridge_dispatcher_host.h"
-
-#include "base/android/java_handler_thread.h"
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "content/browser/renderer_host/java/java_bridge_channel_host.h"
-#include "content/child/child_process.h"
-#include "content/child/npapi/npobject_stub.h"
-#include "content/child/npapi/npobject_util.h" // For CreateNPVariantParam()
-#include "content/common/java_bridge_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-#if !defined(OS_ANDROID)
-#error "JavaBridge only supports OS_ANDROID"
-#endif
-
-namespace content {
-
-namespace {
-// The JavaBridge needs to use a Java thread so the callback
-// will happen on a thread with a prepared Looper.
-class JavaBridgeThread : public base::android::JavaHandlerThread {
- public:
- JavaBridgeThread() : base::android::JavaHandlerThread("JavaBridge") {
- Start();
- }
- virtual ~JavaBridgeThread() {
- Stop();
- }
-};
-
-void CleanUpStubs(const std::vector<base::WeakPtr<NPObjectStub> > & stubs) {
- for (size_t i = 0; i < stubs.size(); ++i) {
- if (stubs[i]) {
- stubs[i]->DeleteSoon();
- }
- }
-}
-
-base::LazyInstance<JavaBridgeThread> g_background_thread =
- LAZY_INSTANCE_INITIALIZER;
-} // namespace
-
-JavaBridgeDispatcherHost::JavaBridgeDispatcherHost(
- RenderFrameHost* render_frame_host)
- : render_frame_host_(render_frame_host) {
-}
-
-JavaBridgeDispatcherHost::~JavaBridgeDispatcherHost() {
- g_background_thread.Get().message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&CleanUpStubs, stubs_));
-}
-
-void JavaBridgeDispatcherHost::AddNamedObject(const base::string16& name,
- NPObject* object) {
- NPVariant_Param variant_param;
- CreateNPVariantParam(object, &variant_param);
-
- Send(new JavaBridgeMsg_AddNamedObject(
- render_frame_host_->GetRoutingID(), name, variant_param));
-}
-
-void JavaBridgeDispatcherHost::RemoveNamedObject(const base::string16& name) {
- // On receipt of this message, the JavaBridgeDispatcher will drop its
- // reference to the corresponding proxy object. When the last reference is
- // removed, the proxy object will delete its NPObjectProxy, which will cause
- // the NPObjectStub to be deleted, which will drop its reference to the
- // original NPObject.
- Send(new JavaBridgeMsg_RemoveNamedObject(
- render_frame_host_->GetRoutingID(), name));
-}
-
-void JavaBridgeDispatcherHost::RenderFrameDeleted() {
- render_frame_host_ = NULL;
-}
-
-void JavaBridgeDispatcherHost::OnGetChannelHandle(IPC::Message* reply_msg) {
- g_background_thread.Get().message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&JavaBridgeDispatcherHost::GetChannelHandle, this, reply_msg));
-}
-
-void JavaBridgeDispatcherHost::Send(IPC::Message* msg) {
- if (render_frame_host_) {
- render_frame_host_->Send(msg);
- return;
- }
-
- delete msg;
-}
-
-void JavaBridgeDispatcherHost::GetChannelHandle(IPC::Message* reply_msg) {
- // The channel creates the channel handle based on the renderer ID we passed
- // to GetJavaBridgeChannelHost() and, on POSIX, the file descriptor used by
- // the underlying channel.
- JavaBridgeHostMsg_GetChannelHandle::WriteReplyParams(
- reply_msg,
- channel_->channel_handle());
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&JavaBridgeDispatcherHost::Send, this, reply_msg));
-}
-
-void JavaBridgeDispatcherHost::CreateNPVariantParam(NPObject* object,
- NPVariant_Param* param) {
- // The JavaBridgeChannelHost needs to be created on the background thread, as
- // that is where Java objects will live, and CreateNPVariantParam() needs the
- // channel to create the NPObjectStub. To avoid blocking here until the
- // channel is ready, create the NPVariant_Param by hand, then post a message
- // to the background thread to set up the channel and create the corresponding
- // NPObjectStub. Post that message before doing any IPC, to make sure that
- // the channel and object proxies are ready before responses are received
- // from the renderer.
-
- // Create an NPVariantParam suitable for serialization over IPC from our
- // NPVariant. See CreateNPVariantParam() in npobject_utils.
- param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID;
- int route_id = JavaBridgeChannelHost::ThreadsafeGenerateRouteID();
- param->npobject_routing_id = route_id;
-
- blink::WebBindings::retainObject(object);
- g_background_thread.Get().message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&JavaBridgeDispatcherHost::CreateObjectStub, this, object,
- render_frame_host_->GetProcess()->GetID(), route_id));
-}
-
-void JavaBridgeDispatcherHost::CreateObjectStub(NPObject* object,
- int render_process_id,
- int route_id) {
- DCHECK_EQ(g_background_thread.Get().message_loop(),
- base::MessageLoop::current());
- if (!channel_.get()) {
- channel_ = JavaBridgeChannelHost::GetJavaBridgeChannelHost(
- render_process_id,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
- }
-
- // In a typical scenario, the lifetime of each NPObjectStub is governed by
- // that of the NPObjectProxy in the renderer, via the channel. However,
- // we cannot guaranteed that the renderer always terminates cleanly
- // (crashes / sometimes just unavoidable). We keep a weak reference to
- // it now and schedule a delete on it when this host is getting deleted.
-
- // Pass 0 for the containing window, as it's only used by plugins to pump the
- // window message queue when a method on a renderer-side object causes a
- // dialog to be displayed, and the Java Bridge does not need this
- // functionality. The page URL is also not required.
- stubs_.push_back((new NPObjectStub(
- object, channel_.get(), route_id, 0, GURL()))->AsWeakPtr());
-
- // The NPObjectStub takes a reference to the NPObject. Release the ref added
- // in CreateNPVariantParam().
- blink::WebBindings::releaseObject(object);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h
deleted file mode 100644
index a656f07afb0..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_DISPATCHER_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_DISPATCHER_HOST_H_
-
-#include <vector>
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "content/child/npapi/npobject_stub.h"
-
-class RouteIDGenerator;
-struct NPObject;
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-class NPChannelBase;
-class RenderFrameHost;
-struct NPVariant_Param;
-
-// This class handles injecting Java objects into a single RenderFrame. The Java
-// object itself lives in the browser process on a background thread, while a
-// proxy object is created in the renderer. An instance of this class exists
-// for each RenderViewHost.
-class JavaBridgeDispatcherHost
- : public base::RefCountedThreadSafe<JavaBridgeDispatcherHost> {
- public:
- // We hold a weak pointer to the RenderFrameHost. It must outlive this object.
- explicit JavaBridgeDispatcherHost(RenderFrameHost* render_frame_host);
-
- // Injects |object| into the main frame of the corresponding RenderView. A
- // proxy object is created in the renderer and when the main frame's window
- // object is next cleared, this proxy object is bound to the window object
- // using |name|. The proxy object remains bound until the next time the
- // window object is cleared after a call to RemoveNamedObject() or
- // AddNamedObject() with the same name. The proxy object proxies calls back
- // to |object|, which is manipulated on the background thread. This class
- // holds a reference to |object| for the time that the proxy object is bound
- // to the window object.
- void AddNamedObject(const base::string16& name, NPObject* object);
- void RemoveNamedObject(const base::string16& name);
-
- // Since this object is ref-counted, it might outlive render_frame_host.
- void RenderFrameDeleted();
-
- void OnGetChannelHandle(IPC::Message* reply_msg);
- void Send(IPC::Message* msg);
-
- private:
- friend class base::RefCountedThreadSafe<JavaBridgeDispatcherHost>;
- virtual ~JavaBridgeDispatcherHost();
-
- void GetChannelHandle(IPC::Message* reply_msg);
- void CreateNPVariantParam(NPObject* object, NPVariant_Param* param);
- void CreateObjectStub(NPObject* object, int render_process_id, int route_id);
-
- scoped_refptr<NPChannelBase> channel_;
- RenderFrameHost* render_frame_host_;
- std::vector<base::WeakPtr<NPObjectStub> > stubs_;
-
- DISALLOW_COPY_AND_ASSIGN(JavaBridgeDispatcherHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
deleted file mode 100644
index 635a1d13c2c..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/renderer_host/java/java_bound_object.h"
-#include "content/browser/renderer_host/java/java_bridge_dispatcher_host.h"
-#include "content/common/android/hash_set.h"
-#include "content/common/java_bridge_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_frame_host.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-namespace content {
-
-JavaBridgeDispatcherHostManager::JavaBridgeDispatcherHostManager(
- WebContents* web_contents,
- jobject retained_object_set)
- : WebContentsObserver(web_contents),
- retained_object_set_(base::android::AttachCurrentThread(),
- retained_object_set),
- allow_object_contents_inspection_(true) {
- DCHECK(retained_object_set);
-}
-
-JavaBridgeDispatcherHostManager::~JavaBridgeDispatcherHostManager() {
- for (ObjectMap::iterator iter = objects_.begin(); iter != objects_.end();
- ++iter) {
- blink::WebBindings::releaseObject(iter->second);
- }
- DCHECK_EQ(0U, instances_.size());
-}
-
-void JavaBridgeDispatcherHostManager::AddNamedObject(const base::string16& name,
- NPObject* object) {
- // Record this object in a map so that we can add it into RenderViewHosts
- // created later. The JavaBridgeDispatcherHost instances will take a
- // reference to the object, but we take one too, because this method can be
- // called before there are any such instances.
- blink::WebBindings::retainObject(object);
- objects_[name] = object;
-
- for (InstanceMap::iterator iter = instances_.begin();
- iter != instances_.end(); ++iter) {
- iter->second->AddNamedObject(name, object);
- }
-}
-
-void JavaBridgeDispatcherHostManager::RemoveNamedObject(
- const base::string16& name) {
- ObjectMap::iterator iter = objects_.find(name);
- if (iter == objects_.end()) {
- return;
- }
-
- blink::WebBindings::releaseObject(iter->second);
- objects_.erase(iter);
-
- for (InstanceMap::iterator iter = instances_.begin();
- iter != instances_.end(); ++iter) {
- iter->second->RemoveNamedObject(name);
- }
-}
-
-void JavaBridgeDispatcherHostManager::RenderFrameCreated(
- RenderFrameHost* render_frame_host) {
- // Creates a JavaBridgeDispatcherHost for the specified RenderViewHost and
- // adds all currently registered named objects to the new instance.
- scoped_refptr<JavaBridgeDispatcherHost> instance =
- new JavaBridgeDispatcherHost(render_frame_host);
-
- for (ObjectMap::const_iterator iter = objects_.begin();
- iter != objects_.end(); ++iter) {
- instance->AddNamedObject(iter->first, iter->second);
- }
-
- instances_[render_frame_host] = instance;
-}
-
-void JavaBridgeDispatcherHostManager::RenderFrameDeleted(
- RenderFrameHost* render_frame_host) {
- if (!instances_.count(render_frame_host)) // Needed for tests.
- return;
- instances_[render_frame_host]->RenderFrameDeleted();
- instances_.erase(render_frame_host);
-}
-
-void JavaBridgeDispatcherHostManager::DocumentAvailableInMainFrame() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Called when the window object has been cleared in the main frame.
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jobject> retained_object_set =
- retained_object_set_.get(env);
- if (!retained_object_set.is_null()) {
- JNI_Java_HashSet_clear(env, retained_object_set);
-
- // We also need to add back the named objects we have so far as they
- // should survive navigations.
- ObjectMap::iterator it = objects_.begin();
- for (; it != objects_.end(); ++it) {
- JNI_Java_HashSet_add(env, retained_object_set,
- JavaBoundObject::GetJavaObject(it->second));
- }
- }
-}
-
-bool JavaBridgeDispatcherHostManager::OnMessageReceived(
- const IPC::Message& message,
- RenderFrameHost* render_frame_host) {
- DCHECK(render_frame_host);
- if (!instances_.count(render_frame_host))
- return false;
- scoped_refptr<JavaBridgeDispatcherHost> instance =
- instances_[render_frame_host];
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcherHostManager, message)
- IPC_MESSAGE_FORWARD_DELAY_REPLY(
- JavaBridgeHostMsg_GetChannelHandle,
- instance.get(),
- JavaBridgeDispatcherHost::OnGetChannelHandle)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void JavaBridgeDispatcherHostManager::JavaBoundObjectCreated(
- const base::android::JavaRef<jobject>& object) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jobject> retained_object_set =
- retained_object_set_.get(env);
- if (!retained_object_set.is_null()) {
- JNI_Java_HashSet_add(env, retained_object_set, object);
- }
-}
-
-void JavaBridgeDispatcherHostManager::JavaBoundObjectDestroyed(
- const base::android::JavaRef<jobject>& object) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jobject> retained_object_set =
- retained_object_set_.get(env);
- if (!retained_object_set.is_null()) {
- JNI_Java_HashSet_remove(env, retained_object_set, object);
- }
-}
-
-void JavaBridgeDispatcherHostManager::SetAllowObjectContentsInspection(
- bool allow) {
- allow_object_contents_inspection_ = allow;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h b/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
deleted file mode 100644
index 8d03576be57..00000000000
--- a/chromium/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_DISPATCHER_HOST_MANAGER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_DISPATCHER_HOST_MANAGER_H_
-
-#include <map>
-
-#include "base/android/jni_weak_ref.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/strings/string16.h"
-#include "content/public/browser/web_contents_observer.h"
-
-struct NPObject;
-
-namespace content {
-class JavaBridgeDispatcherHost;
-class RenderFrameHost;
-
-// This class handles injecting Java objects into all of the RenderFrames
-// associated with a WebContents. It manages a set of JavaBridgeDispatcherHost
-// objects, one per RenderFrameHost.
-class JavaBridgeDispatcherHostManager
- : public WebContentsObserver,
- public base::SupportsWeakPtr<JavaBridgeDispatcherHostManager> {
- public:
- JavaBridgeDispatcherHostManager(WebContents* web_contents,
- jobject retained_object_set);
- virtual ~JavaBridgeDispatcherHostManager();
-
- // These methods add or remove the object to each JavaBridgeDispatcherHost.
- // Each one holds a reference to the NPObject while the object is bound to
- // the corresponding RenderFrame. See JavaBridgeDispatcherHost for details.
- void AddNamedObject(const base::string16& name, NPObject* object);
- void RemoveNamedObject(const base::string16& name);
-
- // WebContentsObserver overrides
- virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void DocumentAvailableInMainFrame() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message,
- RenderFrameHost* render_frame_host) OVERRIDE;
-
- void JavaBoundObjectCreated(const base::android::JavaRef<jobject>& object);
- void JavaBoundObjectDestroyed(const base::android::JavaRef<jobject>& object);
-
- bool GetAllowObjectContentsInspection() const {
- return allow_object_contents_inspection_;
- }
- void SetAllowObjectContentsInspection(bool allow);
-
- private:
- typedef std::map<RenderFrameHost*, scoped_refptr<JavaBridgeDispatcherHost> >
- InstanceMap;
- InstanceMap instances_;
- typedef std::map<base::string16, NPObject*> ObjectMap;
- ObjectMap objects_;
- // Every time a JavaBoundObject backed by a real Java object is
- // created/destroyed, we insert/remove a strong ref to that Java object into
- // this set so that it doesn't get garbage collected while it's still
- // potentially in use. Although the set is managed native side, it's owned
- // and defined in Java so that pushing refs into it does not create new GC
- // roots that would prevent ContentViewCore from being garbage collected.
- JavaObjectWeakGlobalRef retained_object_set_;
- bool allow_object_contents_inspection_;
-
- DISALLOW_COPY_AND_ASSIGN(JavaBridgeDispatcherHostManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_BRIDGE_DISPATCHER_HOST_MANAGER_H_
diff --git a/chromium/content/browser/renderer_host/java/java_method.cc b/chromium/content/browser/renderer_host/java/java_method.cc
deleted file mode 100644
index 03bdb2d7e06..00000000000
--- a/chromium/content/browser/renderer_host/java/java_method.cc
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/java/java_method.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/lazy_instance.h"
-#include "base/memory/singleton.h"
-#include "base/strings/string_util.h" // For ReplaceSubstringsAfterOffset
-#include "content/browser/renderer_host/java/jni_helper.h"
-
-using base::android::AttachCurrentThread;
-using base::android::ConvertJavaStringToUTF8;
-using base::android::GetClass;
-using base::android::MethodID;
-using base::android::ScopedJavaGlobalRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace content {
-namespace {
-
-const char kGetName[] = "getName";
-const char kGetDeclaringClass[] = "getDeclaringClass";
-const char kGetModifiers[] = "getModifiers";
-const char kGetParameterTypes[] = "getParameterTypes";
-const char kGetReturnType[] = "getReturnType";
-const char kIntegerReturningBoolean[] = "(I)Z";
-const char kIsStatic[] = "isStatic";
-const char kJavaLangClass[] = "java/lang/Class";
-const char kJavaLangReflectMethod[] = "java/lang/reflect/Method";
-const char kJavaLangReflectModifier[] = "java/lang/reflect/Modifier";
-const char kReturningInteger[] = "()I";
-const char kReturningJavaLangClass[] = "()Ljava/lang/Class;";
-const char kReturningJavaLangClassArray[] = "()[Ljava/lang/Class;";
-const char kReturningJavaLangString[] = "()Ljava/lang/String;";
-
-struct ModifierClassTraits :
- public base::internal::LeakyLazyInstanceTraits<ScopedJavaGlobalRef<
- jclass> > {
- static ScopedJavaGlobalRef<jclass>* New(void* instance) {
- JNIEnv* env = AttachCurrentThread();
- // Use placement new to initialize our instance in our preallocated space.
- return new (instance) ScopedJavaGlobalRef<jclass>(
- GetClass(env, kJavaLangReflectModifier));
- }
-};
-
-base::LazyInstance<ScopedJavaGlobalRef<jclass>, ModifierClassTraits>
- g_java_lang_reflect_modifier_class = LAZY_INSTANCE_INITIALIZER;
-
-std::string BinaryNameToJNIName(const std::string& binary_name,
- JavaType* type) {
- DCHECK(type);
- *type = JavaType::CreateFromBinaryName(binary_name);
- switch (type->type) {
- case JavaType::TypeBoolean:
- return "Z";
- case JavaType::TypeByte:
- return "B";
- case JavaType::TypeChar:
- return "C";
- case JavaType::TypeShort:
- return "S";
- case JavaType::TypeInt:
- return "I";
- case JavaType::TypeLong:
- return "J";
- case JavaType::TypeFloat:
- return "F";
- case JavaType::TypeDouble:
- return "D";
- case JavaType::TypeVoid:
- return "V";
- case JavaType::TypeArray: {
- // For array types, the binary name uses the JNI name encodings.
- std::string jni_name = binary_name;
- ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/");
- return jni_name;
- }
- case JavaType::TypeString:
- case JavaType::TypeObject:
- std::string jni_name = "L" + binary_name + ";";
- ReplaceSubstringsAfterOffset(&jni_name, 0, ".", "/");
- return jni_name;
- }
- NOTREACHED();
- return std::string();
-}
-
-} // namespace
-
-JavaMethod::JavaMethod(const base::android::JavaRef<jobject>& method)
- : java_method_(method),
- have_calculated_num_parameters_(false),
- id_(NULL) {
- JNIEnv* env = AttachCurrentThread();
- // On construction, we do nothing except get the name. Everything else is
- // done lazily.
- ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
- env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kGetName,
- kReturningJavaLangString))));
- name_ = ConvertJavaStringToUTF8(name);
-}
-
-JavaMethod::~JavaMethod() {
-}
-
-size_t JavaMethod::num_parameters() const {
- EnsureNumParametersIsSetUp();
- return num_parameters_;
-}
-
-bool JavaMethod::is_static() const {
- EnsureTypesAndIDAreSetUp();
- return is_static_;
-}
-
-const JavaType& JavaMethod::parameter_type(size_t index) const {
- EnsureTypesAndIDAreSetUp();
- return parameter_types_[index];
-}
-
-const JavaType& JavaMethod::return_type() const {
- EnsureTypesAndIDAreSetUp();
- return return_type_;
-}
-
-jmethodID JavaMethod::id() const {
- EnsureTypesAndIDAreSetUp();
- return id_;
-}
-
-void JavaMethod::EnsureNumParametersIsSetUp() const {
- if (have_calculated_num_parameters_) {
- return;
- }
- have_calculated_num_parameters_ = true;
-
- // The number of parameters will be used frequently when determining
- // whether to call this method. We don't get the ID etc until actually
- // required.
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jarray> parameters(env, static_cast<jarray>(
- env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kGetParameterTypes,
- kReturningJavaLangClassArray))));
- num_parameters_ = env->GetArrayLength(parameters.obj());
-}
-
-void JavaMethod::EnsureTypesAndIDAreSetUp() const {
- if (id_) {
- return;
- }
-
- // Get the parameters
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobjectArray> parameters(env, static_cast<jobjectArray>(
- env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kGetParameterTypes,
- kReturningJavaLangClassArray))));
- // Usually, this will already have been called.
- EnsureNumParametersIsSetUp();
- DCHECK_EQ(num_parameters_,
- static_cast<size_t>(env->GetArrayLength(parameters.obj())));
-
- // Java gives us the argument type using an extended version of the 'binary
- // name'. See
- // http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Class.html#getName().
- // If we build the signature now, there's no need to store the binary name
- // of the arguments. We just store the simple type.
- std::string signature("(");
-
- // Form the signature and record the parameter types.
- parameter_types_.resize(num_parameters_);
- for (size_t i = 0; i < num_parameters_; ++i) {
- ScopedJavaLocalRef<jobject> parameter(env, env->GetObjectArrayElement(
- parameters.obj(), i));
- ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
- env->CallObjectMethod(parameter.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangClass,
- kGetName,
- kReturningJavaLangString))));
- std::string name_utf8 = ConvertJavaStringToUTF8(name);
- signature += BinaryNameToJNIName(name_utf8, &parameter_types_[i]);
- }
- signature += ")";
-
- // Get the return type
- ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>(
- env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kGetReturnType,
- kReturningJavaLangClass))));
- ScopedJavaLocalRef<jstring> name(env, static_cast<jstring>(
- env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangClass,
- kGetName,
- kReturningJavaLangString))));
- signature += BinaryNameToJNIName(ConvertJavaStringToUTF8(name),
- &return_type_);
-
- // Determine whether the method is static.
- jint modifiers = env->CallIntMethod(
- java_method_.obj(), GetMethodIDFromClassName(env,
- kJavaLangReflectMethod,
- kGetModifiers,
- kReturningInteger));
- is_static_ = env->CallStaticBooleanMethod(
- g_java_lang_reflect_modifier_class.Get().obj(),
- MethodID::Get<MethodID::TYPE_STATIC>(
- env, g_java_lang_reflect_modifier_class.Get().obj(), kIsStatic,
- kIntegerReturningBoolean),
- modifiers);
-
- // Get the ID for this method.
- ScopedJavaLocalRef<jclass> declaring_class(env, static_cast<jclass>(
- env->CallObjectMethod(java_method_.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangReflectMethod,
- kGetDeclaringClass,
- kReturningJavaLangClass))));
- id_ = is_static_ ?
- MethodID::Get<MethodID::TYPE_STATIC>(
- env, declaring_class.obj(), name_.c_str(), signature.c_str()) :
- MethodID::Get<MethodID::TYPE_INSTANCE>(
- env, declaring_class.obj(), name_.c_str(), signature.c_str());
- java_method_.Reset();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_method.h b/chromium/content/browser/renderer_host/java/java_method.h
deleted file mode 100644
index 1d59bacc5a0..00000000000
--- a/chromium/content/browser/renderer_host/java/java_method.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2011 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_METHOD_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_METHOD_H_
-
-#include <jni.h>
-#include <string>
-#include <vector>
-
-#include "base/android/scoped_java_ref.h"
-#include "content/browser/renderer_host/java/java_type.h"
-
-namespace content {
-
-// Wrapper around java.lang.reflect.Method. This class must be used on a single
-// thread only.
-class JavaMethod {
- public:
- explicit JavaMethod(const base::android::JavaRef<jobject>& method);
- ~JavaMethod();
-
- const std::string& name() const { return name_; }
- size_t num_parameters() const;
- bool is_static() const;
- const JavaType& parameter_type(size_t index) const;
- const JavaType& return_type() const;
- jmethodID id() const;
-
- private:
- void EnsureNumParametersIsSetUp() const;
- void EnsureTypesAndIDAreSetUp() const;
-
- std::string name_;
- mutable base::android::ScopedJavaGlobalRef<jobject> java_method_;
- mutable bool have_calculated_num_parameters_;
- mutable size_t num_parameters_;
- mutable std::vector<JavaType> parameter_types_;
- mutable JavaType return_type_;
- mutable bool is_static_;
- mutable jmethodID id_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(JavaMethod);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_METHOD_H_
diff --git a/chromium/content/browser/renderer_host/java/java_type.cc b/chromium/content/browser/renderer_host/java/java_type.cc
deleted file mode 100644
index b590e7733c0..00000000000
--- a/chromium/content/browser/renderer_host/java/java_type.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/java/java_type.h"
-
-#include "base/logging.h"
-
-namespace content {
-namespace {
-
-JavaType JavaTypeFromJNIName(const std::string& jni_name) {
- JavaType result;
- DCHECK(!jni_name.empty());
- switch (jni_name[0]) {
- case 'Z':
- result.type = JavaType::TypeBoolean;
- break;
- case 'B':
- result.type = JavaType::TypeByte;
- break;
- case 'C':
- result.type = JavaType::TypeChar;
- break;
- case 'S':
- result.type = JavaType::TypeShort;
- break;
- case 'I':
- result.type = JavaType::TypeInt;
- break;
- case 'J':
- result.type = JavaType::TypeLong;
- break;
- case 'F':
- result.type = JavaType::TypeFloat;
- break;
- case 'D':
- result.type = JavaType::TypeDouble;
- break;
- case '[':
- result.type = JavaType::TypeArray;
- // LIVECONNECT_COMPLIANCE: We don't support multi-dimensional arrays, so
- // there's no need to populate the inner types.
- break;
- case 'L':
- result.type = jni_name == "Ljava.lang.String;" ?
- JavaType::TypeString :
- JavaType::TypeObject;
- break;
- default:
- // Includes void (V).
- NOTREACHED();
- }
- return result;
-}
-
-} // namespace
-
-JavaType::JavaType() {
-}
-
-JavaType::JavaType(const JavaType& other) {
- *this = other;
-}
-
-JavaType::~JavaType() {
-}
-
-JavaType& JavaType::operator=(const JavaType& other) {
- type = other.type;
- if (other.inner_type) {
- DCHECK_EQ(JavaType::TypeArray, type);
- inner_type.reset(new JavaType(*other.inner_type));
- } else {
- inner_type.reset();
- }
- return *this;
-}
-
-JavaType JavaType::CreateFromBinaryName(const std::string& binary_name) {
- JavaType result;
- DCHECK(!binary_name.empty());
- if (binary_name == "boolean") {
- result.type = JavaType::TypeBoolean;
- } else if (binary_name == "byte") {
- result.type = JavaType::TypeByte;
- } else if (binary_name == "char") {
- result.type = JavaType::TypeChar;
- } else if (binary_name == "short") {
- result.type = JavaType::TypeShort;
- } else if (binary_name == "int") {
- result.type = JavaType::TypeInt;
- } else if (binary_name == "long") {
- result.type = JavaType::TypeLong;
- } else if (binary_name == "float") {
- result.type = JavaType::TypeFloat;
- } else if (binary_name == "double") {
- result.type = JavaType::TypeDouble;
- } else if (binary_name == "void") {
- result.type = JavaType::TypeVoid;
- } else if (binary_name[0] == '[') {
- result.type = JavaType::TypeArray;
- // The inner type of an array is represented in JNI format.
- result.inner_type.reset(new JavaType(JavaTypeFromJNIName(
- binary_name.substr(1))));
- } else if (binary_name == "java.lang.String") {
- result.type = JavaType::TypeString;
- } else {
- result.type = JavaType::TypeObject;
- }
- return result;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/java/java_type.h b/chromium/content/browser/renderer_host/java/java_type.h
deleted file mode 100644
index fe7845eeaa6..00000000000
--- a/chromium/content/browser/renderer_host/java/java_type.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_TYPE_H_
-#define CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_TYPE_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-
-namespace content {
-
-// The type of a Java value. A light-weight enum-like structure intended for
-// use by value and in STL containers.
-struct JavaType {
- JavaType();
- JavaType(const JavaType& other);
- ~JavaType();
- JavaType& operator=(const JavaType& other);
-
- // Java's reflection API represents types as a string using an extended
- // 'binary name'.
- static JavaType CreateFromBinaryName(const std::string& binary_name);
-
- enum Type {
- TypeBoolean,
- TypeByte,
- TypeChar,
- TypeShort,
- TypeInt,
- TypeLong,
- TypeFloat,
- TypeDouble,
- // This is only used as a return type, so we should never convert from
- // JavaScript with this type.
- TypeVoid,
- TypeArray,
- // We special-case strings, as they get special handling when coercing.
- TypeString,
- TypeObject,
- };
-
- Type type;
- scoped_ptr<JavaType> inner_type; // Used for TypeArray only.
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_JAVA_JAVA_TYPE_H_
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 86799c9bc99..25333b365c2 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -7,8 +7,9 @@
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/win/windows_version.h"
-#include "content/browser/accessibility/browser_accessibility_manager_win.h"
-#include "content/browser/accessibility/browser_accessibility_win.h"
+#include "content/browser/renderer_host/legacy_render_widget_host_win_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/common/content_switches.h"
#include "ui/base/touch/touch_enabled.h"
@@ -20,38 +21,44 @@
namespace content {
+namespace {
+
// A custom MSAA object id used to determine if a screen reader or some
// other client is listening on MSAA events - if so, we enable full web
// accessibility support.
const int kIdScreenReaderHoneyPot = 1;
+} // namespace
+
LegacyRenderWidgetHostHWND::~LegacyRenderWidgetHostHWND() {
- ::DestroyWindow(hwnd());
+ if (::IsWindow(hwnd()))
+ ::DestroyWindow(hwnd());
}
// static
-scoped_ptr<LegacyRenderWidgetHostHWND> LegacyRenderWidgetHostHWND::Create(
- HWND parent) {
- // content_unittests passes in the desktop window as the parent. We allow
- // the LegacyRenderWidgetHostHWND instance to be created in this case for
- // these tests to pass.
+LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create(
+ HWND parent,
+ LegacyRenderWidgetHostHWNDDelegate* delegate) {
if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableLegacyIntermediateWindow) ||
- (!GetWindowEventTarget(parent) && parent != ::GetDesktopWindow()))
- return scoped_ptr<LegacyRenderWidgetHostHWND>();
-
- scoped_ptr<LegacyRenderWidgetHostHWND> legacy_window_instance;
- legacy_window_instance.reset(new LegacyRenderWidgetHostHWND(parent));
- // If we failed to create the child, or if the switch to disable the legacy
- // window is passed in, then return NULL.
- if (!::IsWindow(legacy_window_instance->hwnd()))
- return scoped_ptr<LegacyRenderWidgetHostHWND>();
+ switches::kDisableLegacyIntermediateWindow)) {
+ return nullptr;
+ }
+ LegacyRenderWidgetHostHWND* legacy_window_instance =
+ new LegacyRenderWidgetHostHWND(parent, delegate);
+ // If we failed to create the child, return NULL.
+ if (!::IsWindow(legacy_window_instance->hwnd())) {
+ delete legacy_window_instance;
+ return nullptr;
+ }
legacy_window_instance->Init();
- return legacy_window_instance.Pass();
+ return legacy_window_instance;
}
void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) {
+ if (!::IsWindow(hwnd()))
+ return;
+
::SetParent(hwnd(), parent);
// If the new parent is the desktop Window, then we disable the child window
// to ensure that it does not receive any input events. It should not because
@@ -64,35 +71,38 @@ void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) {
}
HWND LegacyRenderWidgetHostHWND::GetParent() {
- return ::GetParent(hwnd());
-}
+ if (!::IsWindow(hwnd()))
+ return NULL;
-void LegacyRenderWidgetHostHWND::OnManagerDeleted() {
- manager_ = NULL;
+ return ::GetParent(hwnd());
}
void LegacyRenderWidgetHostHWND::Show() {
- ::ShowWindow(hwnd(), SW_SHOW);
+ if (::IsWindow(hwnd()))
+ ::ShowWindow(hwnd(), SW_SHOW);
}
void LegacyRenderWidgetHostHWND::Hide() {
- ::ShowWindow(hwnd(), SW_HIDE);
+ if (::IsWindow(hwnd()))
+ ::ShowWindow(hwnd(), SW_HIDE);
}
void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
+ if (!::IsWindow(hwnd()))
+ return;
+
gfx::Rect bounds_in_pixel = gfx::win::DIPToScreenRect(bounds);
::SetWindowPos(hwnd(), NULL, bounds_in_pixel.x(), bounds_in_pixel.y(),
- bounds_in_pixel.width(), bounds_in_pixel.height(), 0);
-}
-
-void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
- if (manager_)
- manager_->OnAccessibleHwndDeleted();
+ bounds_in_pixel.width(), bounds_in_pixel.height(),
+ SWP_NOREDRAW);
}
-LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND(HWND parent)
- : manager_(NULL),
- mouse_tracking_enabled_(false) {
+LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND(
+ HWND parent,
+ LegacyRenderWidgetHostHWNDDelegate* delegate)
+ : mouse_tracking_enabled_(false),
+ delegate_(delegate) {
+ DCHECK(delegate_);
RECT rect = {0};
Base::Create(parent, rect, L"Chrome Legacy Window",
WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
@@ -101,8 +111,9 @@ LegacyRenderWidgetHostHWND::LegacyRenderWidgetHostHWND(HWND parent)
bool LegacyRenderWidgetHostHWND::Init() {
if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
- ui::AreTouchEventsEnabled())
+ ui::AreTouchEventsEnabled()) {
RegisterTouchWindow(hwnd(), TWF_WANTPALM);
+ }
HRESULT hr = ::CreateStdAccessibleObject(
hwnd(), OBJID_WINDOW, IID_IAccessible,
@@ -146,13 +157,16 @@ LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
return static_cast<LRESULT>(0L);
}
- if (OBJID_CLIENT != obj_id || !manager_)
+ if (OBJID_CLIENT != obj_id)
+ return static_cast<LRESULT>(0L);
+
+ base::win::ScopedComPtr<IAccessible> native_accessible(
+ delegate_->GetNativeViewAccessible());
+ if (!native_accessible)
return static_cast<LRESULT>(0L);
- base::win::ScopedComPtr<IAccessible> root(
- manager_->GetRoot()->ToBrowserAccessibilityWin());
return LresultFromObject(IID_IAccessible, w_param,
- static_cast<IAccessible*>(root.Detach()));
+ static_cast<IAccessible*>(native_accessible.Detach()));
}
// We send keyboard/mouse/touch messages to the parent window via SendMessage.
@@ -167,11 +181,14 @@ LRESULT LegacyRenderWidgetHostHWND::OnKeyboardRange(UINT message,
WPARAM w_param,
LPARAM l_param,
BOOL& handled) {
+ LRESULT ret = 0;
if (GetWindowEventTarget(GetParent())) {
- return GetWindowEventTarget(GetParent())->HandleKeyboardMessage(
- message, w_param, l_param);
+ bool msg_handled = false;
+ ret = GetWindowEventTarget(GetParent())->HandleKeyboardMessage(
+ message, w_param, l_param, &msg_handled);
+ handled = msg_handled;
}
- return 0;
+ return ret;
}
LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
@@ -200,28 +217,45 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
::MapWindowPoints(hwnd(), GetParent(), &mouse_coords, 1);
l_param = MAKELPARAM(mouse_coords.x, mouse_coords.y);
}
+
+ LRESULT ret = 0;
+
if (GetWindowEventTarget(GetParent())) {
- return GetWindowEventTarget(GetParent())->HandleMouseMessage(
- message, w_param, l_param);
+ bool msg_handled = false;
+ ret = GetWindowEventTarget(GetParent())->HandleMouseMessage(
+ message, w_param, l_param, &msg_handled);
+ handled = msg_handled;
+ // If the parent did not handle non client mouse messages, we call
+ // DefWindowProc on the message with the parent window handle. This
+ // ensures that WM_SYSCOMMAND is generated for the parent and we are
+ // out of the picture.
+ if (!handled &&
+ (message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) {
+ ret = ::DefWindowProc(GetParent(), message, w_param, l_param);
+ handled = TRUE;
+ }
}
- return 0;
+ return ret;
}
LRESULT LegacyRenderWidgetHostHWND::OnMouseLeave(UINT message,
WPARAM w_param,
LPARAM l_param) {
mouse_tracking_enabled_ = false;
+ LRESULT ret = 0;
if ((::GetCapture() != GetParent()) && GetWindowEventTarget(GetParent())) {
// We should send a WM_MOUSELEAVE to the parent window only if the mouse
// has moved outside the bounds of the parent.
POINT cursor_pos;
::GetCursorPos(&cursor_pos);
if (::WindowFromPoint(cursor_pos) != GetParent()) {
- return GetWindowEventTarget(GetParent())->HandleMouseMessage(
- message, w_param, l_param);
+ bool msg_handled = false;
+ ret = GetWindowEventTarget(GetParent())->HandleMouseMessage(
+ message, w_param, l_param, &msg_handled);
+ SetMsgHandled(msg_handled);
}
}
- return 0;
+ return ret;
}
LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message,
@@ -254,29 +288,37 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseActivate(UINT message,
LRESULT LegacyRenderWidgetHostHWND::OnTouch(UINT message,
WPARAM w_param,
LPARAM l_param) {
+ LRESULT ret = 0;
if (GetWindowEventTarget(GetParent())) {
- return GetWindowEventTarget(GetParent())->HandleTouchMessage(
- message, w_param, l_param);
+ bool msg_handled = false;
+ ret = GetWindowEventTarget(GetParent())->HandleTouchMessage(
+ message, w_param, l_param, &msg_handled);
+ SetMsgHandled(msg_handled);
}
- return 0;
+ return ret;
}
LRESULT LegacyRenderWidgetHostHWND::OnScroll(UINT message,
WPARAM w_param,
LPARAM l_param) {
+ LRESULT ret = 0;
if (GetWindowEventTarget(GetParent())) {
- return GetWindowEventTarget(GetParent())->HandleScrollMessage(
- message, w_param, l_param);
+ bool msg_handled = false;
+ ret = GetWindowEventTarget(GetParent())->HandleScrollMessage(
+ message, w_param, l_param, &msg_handled);
+ SetMsgHandled(msg_handled);
}
- return 0;
+ return ret;
}
LRESULT LegacyRenderWidgetHostHWND::OnNCHitTest(UINT message,
WPARAM w_param,
LPARAM l_param) {
if (GetWindowEventTarget(GetParent())) {
+ bool msg_handled = false;
LRESULT hit_test = GetWindowEventTarget(
- GetParent())->HandleNcHitTestMessage(message, w_param, l_param);
+ GetParent())->HandleNcHitTestMessage(message, w_param, l_param,
+ &msg_handled);
// If the parent returns HTNOWHERE which can happen for popup windows, etc
// we return HTCLIENT.
if (hit_test == HTNOWHERE)
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
index 814c200c275..3222e05c1d4 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.h
@@ -11,9 +11,9 @@
#include <oleacc.h>
#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_comptr.h"
#include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
namespace ui {
@@ -21,8 +21,6 @@ class WindowEventTarget;
}
namespace content {
-class BrowserAccessibilityManagerWin;
-
// Reasons for the existence of this class outlined below:-
// 1. Some screen readers expect every tab / every unique web content container
// to be in its own HWND with class name Chrome_RenderWidgetHostHWND.
@@ -40,12 +38,11 @@ class BrowserAccessibilityManagerWin;
// fail.
// We should look to get rid of this code when all of the above are fixed.
+class LegacyRenderWidgetHostHWNDDelegate;
+
// This class implements a child HWND with the same size as the content area,
-// that delegates its accessibility implementation to the root of the
-// BrowserAccessibilityManager tree. This HWND is hooked up as the parent of
-// the root object in the BrowserAccessibilityManager tree, so when any
-// accessibility client calls ::WindowFromAccessibleObject, they get this
-// HWND instead of the DesktopWindowTreeHostWin.
+// and delegates its accessibility implementation to the
+// gfx::NativeViewAccessible provided by the owner class.
class CONTENT_EXPORT LegacyRenderWidgetHostHWND
: public ATL::CWindowImpl<LegacyRenderWidgetHostHWND,
NON_EXPORTED_BASE(ATL::CWindow),
@@ -57,12 +54,14 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
NON_EXPORTED_BASE(ATL::CWindow),
ATL::CWinTraits<WS_CHILD> > Base;
- ~LegacyRenderWidgetHostHWND();
+ virtual ~LegacyRenderWidgetHostHWND();
// Creates and returns an instance of the LegacyRenderWidgetHostHWND class on
// successful creation of a child window parented to the parent window passed
// in.
- static scoped_ptr<LegacyRenderWidgetHostHWND> Create(HWND parent);
+ static LegacyRenderWidgetHostHWND* Create(
+ HWND parent,
+ LegacyRenderWidgetHostHWNDDelegate* delegate);
BEGIN_MSG_MAP_EX(LegacyRenderWidgetHostHWND)
MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
@@ -84,6 +83,8 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
MESSAGE_HANDLER_EX(WM_SIZE, OnSize)
END_MSG_MAP()
+ // May be deleted at any time by Windows! Other classes should never store
+ // this value.
HWND hwnd() { return m_hWnd; }
// Called when the child window is to be reparented to a new window.
@@ -93,13 +94,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
IAccessible* window_accessible() { return window_accessible_; }
- void set_browser_accessibility_manager(
- content::BrowserAccessibilityManagerWin* manager) {
- manager_ = manager;
- }
-
- void OnManagerDeleted();
-
// Functions to show and hide the window.
void Show();
void Hide();
@@ -107,11 +101,9 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
// Resizes the window to the bounds passed in.
void SetBounds(const gfx::Rect& bounds);
- protected:
- virtual void OnFinalMessage(HWND hwnd) OVERRIDE;
-
private:
- LegacyRenderWidgetHostHWND(HWND parent);
+ LegacyRenderWidgetHostHWND(HWND parent,
+ LegacyRenderWidgetHostHWNDDelegate* delegate);
bool Init();
@@ -136,7 +128,8 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
LRESULT OnNCCalcSize(UINT message, WPARAM w_param, LPARAM l_param);
LRESULT OnSize(UINT message, WPARAM w_param, LPARAM l_param);
- content::BrowserAccessibilityManagerWin* manager_;
+ LegacyRenderWidgetHostHWNDDelegate* delegate_;
+
base::win::ScopedComPtr<IAccessible> window_accessible_;
// Set to true if we turned on mouse tracking.
@@ -148,4 +141,3 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_H_
-
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win_delegate.h b/chromium/content/browser/renderer_host/legacy_render_widget_host_win_delegate.h
new file mode 100644
index 00000000000..a94d81e0939
--- /dev/null
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win_delegate.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2014 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 CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_DELEGATE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_DELEGATE_H_
+
+#include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace content {
+
+// A delegate interface for LegacyRenderWidgetHostHWND to query the
+// native view accessible from the owner class.
+class CONTENT_EXPORT LegacyRenderWidgetHostHWNDDelegate {
+ public:
+ // Get the native view accessible for the web contents.
+ // Once initialized, this should always return a valid object, but the
+ // object may change as the user navigates.
+ virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0;
+};
+
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_LEGACY_RENDER_WIDGET_HOST_WIN_DELEGATE_H_
diff --git a/chromium/content/browser/renderer_host/media/DEPS b/chromium/content/browser/renderer_host/media/DEPS
index c3a5b96fc44..21fd0fd9d57 100644
--- a/chromium/content/browser/renderer_host/media/DEPS
+++ b/chromium/content/browser/renderer_host/media/DEPS
@@ -1,3 +1,11 @@
include_rules = [
"+media",
]
+
+specific_include_rules = {
+ # TODO(miu): Need to relocate MediaStreamManager/DispatcherHost/UIProxy and
+ # friends to somewhere more appropriate. Perhaps content/browser/media?
+ "media_stream_ui_proxy(_unittest)?\.cc": [
+ "+content/browser/frame_host",
+ ],
+}
diff --git a/chromium/content/browser/renderer_host/media/OWNERS b/chromium/content/browser/renderer_host/media/OWNERS
index d32059427a5..0db86f8db0f 100644
--- a/chromium/content/browser/renderer_host/media/OWNERS
+++ b/chromium/content/browser/renderer_host/media/OWNERS
@@ -1,9 +1,7 @@
-acolwell@chromium.org
dalecurtis@chromium.org
ddorwin@chromium.org
perkj@chromium.org
scherkus@chromium.org
-shadi@chromium.org
tommi@chromium.org
vrk@chromium.org
wjia@chromium.org
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
index 17b4d7d251d..e360eb0eef2 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -14,6 +14,10 @@
#include "media/base/channel_layout.h"
#include "media/base/scoped_histogram_timer.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/audio/cras_audio_handler.h"
+#endif
+
namespace content {
const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
@@ -28,6 +32,9 @@ AudioInputDeviceManager::AudioInputDeviceManager(
: listener_(NULL),
next_capture_session_id_(kFirstSessionId),
use_fake_device_(false),
+#if defined(OS_CHROMEOS)
+ keyboard_mic_streams_count_(0),
+#endif
audio_manager_(audio_manager) {
}
@@ -49,7 +56,7 @@ void AudioInputDeviceManager::Register(
const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!listener_);
- DCHECK(!device_task_runner_);
+ DCHECK(!device_task_runner_.get());
listener_ = listener;
device_task_runner_ = device_task_runner;
}
@@ -109,6 +116,43 @@ bool AudioInputDeviceManager::ShouldUseFakeDevice() const {
return use_fake_device_;
}
+#if defined(OS_CHROMEOS)
+void AudioInputDeviceManager::RegisterKeyboardMicStream(
+ const base::Closure& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ++keyboard_mic_streams_count_;
+ if (keyboard_mic_streams_count_ == 1) {
+ BrowserThread::PostTaskAndReply(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
+ this,
+ true),
+ callback);
+ } else {
+ callback.Run();
+ }
+}
+
+void AudioInputDeviceManager::UnregisterKeyboardMicStream() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ --keyboard_mic_streams_count_;
+ DCHECK_GE(keyboard_mic_streams_count_, 0);
+ if (keyboard_mic_streams_count_ == 0) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
+ this,
+ false));
+ }
+}
+#endif
+
void AudioInputDeviceManager::EnumerateOnDeviceThread(
MediaStreamType stream_type) {
SCOPED_UMA_HISTOGRAM_TIMER(
@@ -250,4 +294,13 @@ void AudioInputDeviceManager::GetFakeDeviceNames(
kFakeDeviceId2));
}
+#if defined(OS_CHROMEOS)
+void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
+ bool active) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active);
+}
+#endif
+
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
index e8d44cb807a..a2d4ca4f92c 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -45,24 +45,35 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
const StreamDeviceInfo* GetOpenedDeviceInfoById(int session_id);
// MediaStreamProvider implementation, called on IO thread.
- virtual void Register(MediaStreamProviderListener* listener,
- const scoped_refptr<base::SingleThreadTaskRunner>&
- device_task_runner) OVERRIDE;
- virtual void Unregister() OVERRIDE;
- virtual void EnumerateDevices(MediaStreamType stream_type) OVERRIDE;
- virtual int Open(const StreamDeviceInfo& device) OVERRIDE;
- virtual void Close(int session_id) OVERRIDE;
+ void Register(MediaStreamProviderListener* listener,
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ device_task_runner) override;
+ void Unregister() override;
+ void EnumerateDevices(MediaStreamType stream_type) override;
+ int Open(const StreamDeviceInfo& device) override;
+ void Close(int session_id) override;
void UseFakeDevice();
bool ShouldUseFakeDevice() const;
+#if defined(OS_CHROMEOS)
+ // Registers and unregisters that a stream using keyboard mic has been opened
+ // or closed. Keeps count of how many such streams are open and activates and
+ // inactivates the keyboard mic accordingly. The (in)activation is done on the
+ // UI thread and for the register case a callback must therefor be provided
+ // which is called when activated.
+ // Called on the IO thread.
+ void RegisterKeyboardMicStream(const base::Closure& callback);
+ void UnregisterKeyboardMicStream();
+#endif
+
private:
// Used by the unittests to get a list of fake devices.
friend class MediaStreamDispatcherHostTest;
void GetFakeDeviceNames(media::AudioDeviceNames* device_names);
typedef std::vector<StreamDeviceInfo> StreamDeviceList;
- virtual ~AudioInputDeviceManager();
+ ~AudioInputDeviceManager() override;
// Enumerates audio input devices on media stream device thread.
void EnumerateOnDeviceThread(MediaStreamType stream_type);
@@ -87,12 +98,22 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// device is found, it will return devices_.end().
StreamDeviceList::iterator GetDevice(int session_id);
+#if defined(OS_CHROMEOS)
+ // Calls Cras audio handler and sets keyboard mic active status.
+ void SetKeyboardMicStreamActiveOnUIThread(bool active);
+#endif
+
// Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int next_capture_session_id_;
bool use_fake_device_;
StreamDeviceList devices_;
+#if defined(OS_CHROMEOS)
+ // Keeps count of how many streams are using keyboard mic.
+ int keyboard_mic_streams_count_;
+#endif
+
media::AudioManager* const audio_manager_; // Weak.
// The message loop of media stream device thread that this object runs on.
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index c2963eefd36..f6a5fb2fade 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -55,7 +55,7 @@ class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
MAYBE_AudioInputDeviceManagerTest() {}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
// The test must run on Browser::IO.
message_loop_.reset(new base::MessageLoopForIO);
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -84,7 +84,7 @@ class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
message_loop_->RunUntilIdle();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
manager_->Unregister();
io_thread_.reset();
}
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 2dcc56d0918..7b421ba6d55 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -19,6 +19,20 @@
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_bus.h"
+namespace {
+
+void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
+ std::ostringstream oss;
+ oss << "[stream_id=" << stream_id << "] ";
+ if (add_prefix)
+ oss << "AIRH::";
+ oss << msg;
+ content::MediaStreamManager::SendMessageToNativeLog(oss.str());
+ DVLOG(1) << oss.str();
+}
+
+} // namespace
+
namespace content {
struct AudioInputRendererHost::AudioEntry {
@@ -42,12 +56,16 @@ struct AudioInputRendererHost::AudioEntry {
// Set to true after we called Close() for the controller.
bool pending_close;
+
+ // If this entry's layout has a keyboard mic channel.
+ bool has_keyboard_mic_;
};
AudioInputRendererHost::AudioEntry::AudioEntry()
: stream_id(0),
shared_memory_segment_count(0),
- pending_close(false) {
+ pending_close(false),
+ has_keyboard_mic_(false) {
}
AudioInputRendererHost::AudioEntry::~AudioEntry() {}
@@ -133,8 +151,10 @@ void AudioInputRendererHost::DoCompleteCreation(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntry* entry = LookupByController(controller);
- if (!entry)
+ if (!entry) {
+ NOTREACHED() << "AudioInputController is invalid.";
return;
+ }
if (!PeerHandle()) {
NOTREACHED() << "Renderer process handle is invalid.";
@@ -162,22 +182,21 @@ void AudioInputRendererHost::DoCompleteCreation(
AudioInputSyncWriter* writer =
static_cast<AudioInputSyncWriter*>(entry->writer.get());
-#if defined(OS_WIN)
- base::SyncSocket::Handle foreign_socket_handle;
-#else
- base::FileDescriptor foreign_socket_handle;
-#endif
+ base::SyncSocket::TransitDescriptor socket_transit_descriptor;
// If we failed to prepare the sync socket for the renderer then we fail
// the construction of audio input stream.
- if (!writer->PrepareForeignSocketHandle(PeerHandle(),
- &foreign_socket_handle)) {
+ if (!writer->PrepareForeignSocket(PeerHandle(), &socket_transit_descriptor)) {
DeleteEntryOnError(entry, SYNC_SOCKET_ERROR);
return;
}
- Send(new AudioInputMsg_NotifyStreamCreated(entry->stream_id,
- foreign_memory_handle, foreign_socket_handle,
+ LogMessage(entry->stream_id,
+ "DoCompleteCreation: IPC channel and stream are now open",
+ true);
+
+ Send(new AudioInputMsg_NotifyStreamCreated(
+ entry->stream_id, foreign_memory_handle, socket_transit_descriptor,
entry->shared_memory.requested_size(),
entry->shared_memory_segment_count));
}
@@ -187,29 +206,39 @@ void AudioInputRendererHost::DoSendRecordingMessage(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(henrika): See crbug.com/115262 for details on why this method
// should be implemented.
+ AudioEntry* entry = LookupByController(controller);
+ if (!entry) {
+ NOTREACHED() << "AudioInputController is invalid.";
+ return;
+ }
+ LogMessage(
+ entry->stream_id, "DoSendRecordingMessage: stream is now started", true);
}
void AudioInputRendererHost::DoHandleError(
media::AudioInputController* controller,
media::AudioInputController::ErrorCode error_code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Log all errors even it is ignored later.
- MediaStreamManager::SendMessageToNativeLog(
- base::StringPrintf("AudioInputController error: %d", error_code));
+ AudioEntry* entry = LookupByController(controller);
+ if (!entry) {
+ NOTREACHED() << "AudioInputController is invalid.";
+ return;
+ }
// This is a fix for crbug.com/357501. The error can be triggered when closing
// the lid on Macs, which causes more problems than it fixes.
// Also, in crbug.com/357569, the goal is to remove usage of the error since
// it was added to solve a crash on Windows that no longer can be reproduced.
if (error_code == media::AudioInputController::NO_DATA_ERROR) {
- DVLOG(1) << "AudioInputRendererHost@" << this << "::DoHandleError: "
- << "NO_DATA_ERROR ignored.";
+ // TODO(henrika): it might be possible to do something other than just
+ // logging when we detect many NO_DATA_ERROR calls for a stream.
+ LogMessage(entry->stream_id, "AIC::DoCheckForNoData: NO_DATA_ERROR", false);
return;
}
- AudioEntry* entry = LookupByController(controller);
- if (!entry)
- return;
+ std::ostringstream oss;
+ oss << "AIC reports error_code=" << error_code;
+ LogMessage(entry->stream_id, oss.str(), false);
audio_log_->OnError(entry->stream_id);
DeleteEntryOnError(entry, AUDIO_INPUT_CONTROLLER_ERROR);
@@ -219,15 +248,13 @@ void AudioInputRendererHost::DoLog(media::AudioInputController* controller,
const std::string& message) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
AudioEntry* entry = LookupByController(controller);
- if (!entry)
+ if (!entry) {
+ NOTREACHED() << "AudioInputController is invalid.";
return;
+ }
// Add stream ID and current audio level reported by AIC to native log.
- std::string log_string =
- base::StringPrintf("[stream_id=%d] ", entry->stream_id);
- log_string += message;
- MediaStreamManager::SendMessageToNativeLog(log_string);
- DVLOG(1) << log_string;
+ LogMessage(entry->stream_id, message, false);
}
bool AudioInputRendererHost::OnMessageReceived(const IPC::Message& message) {
@@ -250,15 +277,42 @@ void AudioInputRendererHost::OnCreateStream(
const AudioInputHostMsg_CreateStream_Config& config) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "AudioInputRendererHost@" << this
- << "::OnCreateStream(stream_id=" << stream_id
- << ", render_view_id=" << render_view_id
- << ", session_id=" << session_id << ")";
+#if defined(OS_CHROMEOS)
+ if (config.params.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
+ media_stream_manager_->audio_input_device_manager()
+ ->RegisterKeyboardMicStream(
+ base::Bind(&AudioInputRendererHost::DoCreateStream,
+ this,
+ stream_id,
+ render_view_id,
+ session_id,
+ config));
+ } else {
+ DoCreateStream(stream_id, render_view_id, session_id, config);
+ }
+#else
+ DoCreateStream(stream_id, render_view_id, session_id, config);
+#endif
+}
+
+void AudioInputRendererHost::DoCreateStream(
+ int stream_id,
+ int render_view_id,
+ int session_id,
+ const AudioInputHostMsg_CreateStream_Config& config) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ std::ostringstream oss;
+ oss << "[stream_id=" << stream_id << "] "
+ << "AIRH::OnCreateStream(render_view_id=" << render_view_id
+ << ", session_id=" << session_id << ")";
DCHECK_GT(render_view_id, 0);
// media::AudioParameters is validated in the deserializer.
if (LookupById(stream_id) != NULL) {
SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS);
+ MaybeUnregisterKeyboardMicStream(config);
return;
}
@@ -267,7 +321,7 @@ void AudioInputRendererHost::OnCreateStream(
ShouldUseFakeDevice()) {
audio_params.Reset(
media::AudioParameters::AUDIO_FAKE,
- config.params.channel_layout(), config.params.channels(), 0,
+ config.params.channel_layout(), config.params.channels(),
config.params.sample_rate(), config.params.bits_per_sample(),
config.params.frames_per_buffer());
}
@@ -282,11 +336,13 @@ void AudioInputRendererHost::OnCreateStream(
SendErrorMessage(stream_id, PERMISSION_DENIED);
DLOG(WARNING) << "No permission has been granted to input stream with "
<< "session_id=" << session_id;
+ MaybeUnregisterKeyboardMicStream(config);
return;
}
device_id = info->device.id;
device_name = info->device.name;
+ oss << ": device_name=" << device_name;
}
// Create a new AudioEntry structure.
@@ -305,6 +361,7 @@ void AudioInputRendererHost::OnCreateStream(
!entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) {
// If creation of shared memory failed then send an error message.
SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED);
+ MaybeUnregisterKeyboardMicStream(config);
return;
}
@@ -313,6 +370,7 @@ void AudioInputRendererHost::OnCreateStream(
if (!writer->Init()) {
SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED);
+ MaybeUnregisterKeyboardMicStream(config);
return;
}
@@ -331,40 +389,45 @@ void AudioInputRendererHost::OnCreateStream(
entry->writer.get(),
user_input_monitor_);
} else {
- // TODO(henrika): replace CreateLowLatency() with Create() as soon
- // as satish has ensured that Speech Input also uses the default low-
- // latency path. See crbug.com/112472 for details.
- entry->controller =
- media::AudioInputController::CreateLowLatency(audio_manager_,
- this,
- audio_params,
- device_id,
- entry->writer.get(),
- user_input_monitor_);
+ DCHECK_EQ(config.params.format(),
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY);
+ entry->controller = media::AudioInputController::CreateLowLatency(
+ audio_manager_,
+ this,
+ audio_params,
+ device_id,
+ entry->writer.get(),
+ user_input_monitor_,
+ config.automatic_gain_control);
+ oss << ", AGC=" << config.automatic_gain_control;
}
if (!entry->controller.get()) {
SendErrorMessage(stream_id, STREAM_CREATE_ERROR);
+ MaybeUnregisterKeyboardMicStream(config);
return;
}
- // Set the initial AGC state for the audio input stream. Note that, the AGC
- // is only supported in AUDIO_PCM_LOW_LATENCY mode.
- if (config.params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY)
- entry->controller->SetAutomaticGainControl(config.automatic_gain_control);
+#if defined(OS_CHROMEOS)
+ if (config.params.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
+ entry->has_keyboard_mic_ = true;
+ }
+#endif
+
+ MediaStreamManager::SendMessageToNativeLog(oss.str());
+ DVLOG(1) << oss.str();
// Since the controller was created successfully, create an entry and add it
// to the map.
entry->stream_id = stream_id;
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
-
- MediaStreamManager::SendMessageToNativeLog(
- "Audio input stream created successfully. Device name: " + device_name);
audio_log_->OnCreated(stream_id, audio_params, device_id);
}
void AudioInputRendererHost::OnRecordStream(int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ LogMessage(stream_id, "OnRecordStream", true);
AudioEntry* entry = LookupById(stream_id);
if (!entry) {
@@ -378,6 +441,7 @@ void AudioInputRendererHost::OnRecordStream(int stream_id) {
void AudioInputRendererHost::OnCloseStream(int stream_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ LogMessage(stream_id, "OnCloseStream", true);
AudioEntry* entry = LookupById(stream_id);
@@ -400,8 +464,10 @@ void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) {
void AudioInputRendererHost::SendErrorMessage(
int stream_id, ErrorCode error_code) {
- MediaStreamManager::SendMessageToNativeLog(
- base::StringPrintf("AudioInputRendererHost error: %d", error_code));
+ std::string err_msg =
+ base::StringPrintf("SendErrorMessage(error_code=%d)", error_code);
+ LogMessage(stream_id, err_msg, true);
+
Send(new AudioInputMsg_NotifyStreamStateChanged(
stream_id, media::AudioInputIPCDelegate::kError));
}
@@ -419,6 +485,7 @@ void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!entry->pending_close) {
+ LogMessage(entry->stream_id, "CloseAndDeleteStream", true);
entry->controller->Close(base::Bind(&AudioInputRendererHost::DeleteEntry,
this, entry));
entry->pending_close = true;
@@ -428,6 +495,14 @@ void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true);
+
+#if defined(OS_CHROMEOS)
+ if (entry->has_keyboard_mic_) {
+ media_stream_manager_->audio_input_device_manager()
+ ->UnregisterKeyboardMicStream();
+ }
+#endif
// Delete the entry when this method goes out of scope.
scoped_ptr<AudioEntry> entry_deleter(entry);
@@ -470,4 +545,15 @@ AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
return NULL;
}
+void AudioInputRendererHost::MaybeUnregisterKeyboardMicStream(
+ const AudioInputHostMsg_CreateStream_Config& config) {
+#if defined(OS_CHROMEOS)
+ if (config.params.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
+ media_stream_manager_->audio_input_device_manager()
+ ->UnregisterKeyboardMicStream();
+ }
+#endif
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
index 7bd6692eabb..b847bf6d4dc 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -107,19 +107,19 @@ class CONTENT_EXPORT AudioInputRendererHost
media::UserInputMonitor* user_input_monitor);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// AudioInputController::EventHandler implementation.
- virtual void OnCreated(media::AudioInputController* controller) OVERRIDE;
- virtual void OnRecording(media::AudioInputController* controller) OVERRIDE;
- virtual void OnError(media::AudioInputController* controller,
- media::AudioInputController::ErrorCode error_code) OVERRIDE;
- virtual void OnData(media::AudioInputController* controller,
- const media::AudioBus* data) OVERRIDE;
- virtual void OnLog(media::AudioInputController* controller,
- const std::string& message) OVERRIDE;
+ void OnCreated(media::AudioInputController* controller) override;
+ void OnRecording(media::AudioInputController* controller) override;
+ void OnError(media::AudioInputController* controller,
+ media::AudioInputController::ErrorCode error_code) override;
+ void OnData(media::AudioInputController* controller,
+ const media::AudioBus* data) override;
+ void OnLog(media::AudioInputController* controller,
+ const std::string& message) override;
private:
// TODO(henrika): extend test suite (compare AudioRenderHost)
@@ -130,18 +130,26 @@ class CONTENT_EXPORT AudioInputRendererHost
struct AudioEntry;
typedef std::map<int, AudioEntry*> AudioEntryMap;
- virtual ~AudioInputRendererHost();
+ ~AudioInputRendererHost() override;
// Methods called on IO thread ----------------------------------------------
// Audio related IPC message handlers.
+ // For ChromeOS: Checks if the stream should contain keyboard mic, if so
+ // registers to AudioInputDeviceManager. Then calls DoCreateStream.
+ // For non-ChromeOS: Just calls DoCreateStream.
+ void OnCreateStream(int stream_id,
+ int render_view_id,
+ int session_id,
+ const AudioInputHostMsg_CreateStream_Config& config);
+
// Creates an audio input stream with the specified format whose data is
// consumed by an entity in the render view referenced by |render_view_id|.
// |session_id| is used to find out which device to be used for the stream.
// Upon success/failure, the peer is notified via the
// NotifyStreamCreated message.
- void OnCreateStream(int stream_id,
+ void DoCreateStream(int stream_id,
int render_view_id,
int session_id,
const AudioInputHostMsg_CreateStream_Config& config);
@@ -196,6 +204,11 @@ class CONTENT_EXPORT AudioInputRendererHost
// event is received.
AudioEntry* LookupByController(media::AudioInputController* controller);
+ // If ChromeOS and |config|'s layout has keyboard mic, unregister in
+ // AudioInputDeviceManager.
+ void MaybeUnregisterKeyboardMicStream(
+ const AudioInputHostMsg_CreateStream_Config& config);
+
// Used to create an AudioInputController.
media::AudioManager* audio_manager_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
index 117fbe8fedb..987fd232054 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc
@@ -60,18 +60,20 @@ void AudioInputSyncWriter::Write(const media::AudioBus* data,
if (last_write_time_.is_null()) {
// This is the first time Write is called.
base::TimeDelta interval = base::Time::Now() - creation_time_;
- oss << "Audio input data received for the first time: delay = "
- << interval.InMilliseconds() << "ms.";
+ oss << "AISW::Write: audio input data received for the first time: delay "
+ "= " << interval.InMilliseconds() << "ms";
} else {
base::TimeDelta interval = base::Time::Now() - last_write_time_;
if (interval > kLogDelayThreadhold) {
- oss << "Audio input data delay unexpectedly long: delay = "
- << interval.InMilliseconds() << "ms.";
+ oss << "AISW::Write: audio input data delay unexpectedly long: delay = "
+ << interval.InMilliseconds() << "ms";
}
}
- if (!oss.str().empty())
+ if (!oss.str().empty()) {
MediaStreamManager::SendMessageToNativeLog(oss.str());
+ DVLOG(1) << oss.str();
+ }
last_write_time_ = base::Time::Now();
#endif
@@ -105,27 +107,11 @@ bool AudioInputSyncWriter::Init() {
foreign_socket_.get());
}
-#if defined(OS_WIN)
-
-bool AudioInputSyncWriter::PrepareForeignSocketHandle(
+bool AudioInputSyncWriter::PrepareForeignSocket(
base::ProcessHandle process_handle,
- base::SyncSocket::Handle* foreign_handle) {
- ::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(),
- process_handle, foreign_handle,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
- return (*foreign_handle != 0);
+ base::SyncSocket::TransitDescriptor* descriptor) {
+ return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor);
}
-#else
-
-bool AudioInputSyncWriter::PrepareForeignSocketHandle(
- base::ProcessHandle process_handle,
- base::FileDescriptor* foreign_handle) {
- foreign_handle->fd = foreign_socket_->handle();
- foreign_handle->auto_close = false;
- return (foreign_handle->fd != -1);
-}
-
-#endif
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
index 424d7907f11..1ace401441f 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer.h
@@ -32,22 +32,18 @@ class AudioInputSyncWriter : public media::AudioInputController::SyncWriter {
int shared_memory_segment_count,
const media::AudioParameters& params);
- virtual ~AudioInputSyncWriter();
+ ~AudioInputSyncWriter() override;
// media::AudioInputController::SyncWriter implementation.
- virtual void UpdateRecordedBytes(uint32 bytes) OVERRIDE;
- virtual void Write(const media::AudioBus* data,
- double volume,
- bool key_pressed) OVERRIDE;
- virtual void Close() OVERRIDE;
+ void UpdateRecordedBytes(uint32 bytes) override;
+ void Write(const media::AudioBus* data,
+ double volume,
+ bool key_pressed) override;
+ void Close() override;
bool Init();
- bool PrepareForeignSocketHandle(base::ProcessHandle process_handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle* foreign_handle);
-#else
- base::FileDescriptor* foreign_handle);
-#endif
+ bool PrepareForeignSocket(base::ProcessHandle process_handle,
+ base::SyncSocket::TransitDescriptor* descriptor);
private:
base::SharedMemory* shared_memory_;
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
index 7b07fd99c3b..43555fcdb19 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -6,10 +6,13 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
#include "base/process/process.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
@@ -39,7 +42,7 @@ class AudioRendererHost::AudioEntry
const std::string& output_device_id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<media::AudioOutputController::SyncReader> reader);
- virtual ~AudioEntry();
+ ~AudioEntry() override;
int stream_id() const {
return stream_id_;
@@ -66,12 +69,11 @@ class AudioRendererHost::AudioEntry
private:
// media::AudioOutputController::EventHandler implementation.
- virtual void OnCreated() OVERRIDE;
- virtual void OnPlaying() OVERRIDE;
- virtual void OnPaused() OVERRIDE;
- virtual void OnError() OVERRIDE;
- virtual void OnDeviceChange(int new_buffer_size, int new_sample_rate)
- OVERRIDE;
+ void OnCreated() override;
+ void OnPlaying() override;
+ void OnPaused() override;
+ void OnError() override;
+ void OnDeviceChange(int new_buffer_size, int new_sample_rate) override;
AudioRendererHost* const host_;
const int stream_id_;
@@ -238,24 +240,17 @@ void AudioRendererHost::DoCompleteCreation(int stream_id) {
AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader());
-#if defined(OS_WIN)
- base::SyncSocket::Handle foreign_socket_handle;
-#else
- base::FileDescriptor foreign_socket_handle;
-#endif
+ base::SyncSocket::TransitDescriptor socket_descriptor;
// If we failed to prepare the sync socket for the renderer then we fail
// the construction of audio stream.
- if (!reader->PrepareForeignSocketHandle(PeerHandle(),
- &foreign_socket_handle)) {
+ if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) {
ReportErrorAndClose(entry->stream_id());
return;
}
Send(new AudioMsg_NotifyStreamCreated(
- entry->stream_id(),
- foreign_memory_handle,
- foreign_socket_handle,
+ entry->stream_id(), foreign_memory_handle, socket_descriptor,
entry->shared_memory()->requested_size()));
}
@@ -272,30 +267,18 @@ void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
is_playing ? media::AudioOutputIPCDelegate::kPlaying
: media::AudioOutputIPCDelegate::kPaused));
- MediaObserver* const media_observer =
- GetContentClient()->browser()->GetMediaObserver();
- if (media_observer) {
- if (is_playing) {
- media_observer->OnAudioStreamPlaying(
- render_process_id_,
- entry->render_frame_id(),
- entry->stream_id(),
- base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
- entry->controller()));
- if (!entry->playing()) {
- entry->set_playing(true);
- base::AtomicRefCountInc(&num_playing_streams_);
- }
- } else {
- media_observer->OnAudioStreamStopped(render_process_id_,
- entry->render_frame_id(),
- entry->stream_id());
- if (entry->playing()) {
- entry->set_playing(false);
- base::AtomicRefCountDec(&num_playing_streams_);
- }
- }
+ if (is_playing) {
+ AudioStreamMonitor::StartMonitoringStream(
+ render_process_id_,
+ entry->render_frame_id(),
+ entry->stream_id(),
+ base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
+ entry->controller()));
+ } else {
+ AudioStreamMonitor::StopMonitoringStream(
+ render_process_id_, entry->render_frame_id(), entry->stream_id());
}
+ UpdateNumPlayingStreams(entry, is_playing);
}
RenderViewHost::AudioOutputControllerList
@@ -303,8 +286,9 @@ AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
RenderViewHost::AudioOutputControllerList controllers;
- AudioEntryMap::const_iterator it = audio_entries_.begin();
- for (; it != audio_entries_.end(); ++it) {
+ for (AudioEntryMap::const_iterator it = audio_entries_.begin();
+ it != audio_entries_.end();
+ ++it) {
AudioEntry* entry = it->second;
if (entry->render_view_id() == render_view_id)
controllers.push_back(entry->controller());
@@ -357,8 +341,6 @@ void AudioRendererHost::OnCreateStream(
output_device_id = info->device.matched_output_device_id;
// Create the shared memory and share with the renderer process.
- // For synchronized I/O (if input_channels > 0) then we allocate
- // extra memory after the output data for the input data.
uint32 shared_memory_size = AudioBus::CalculateMemorySize(params);
scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
@@ -378,18 +360,17 @@ void AudioRendererHost::OnCreateStream(
if (media_observer)
media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
- scoped_ptr<AudioEntry> entry(new AudioEntry(
- this,
- stream_id,
- render_view_id,
- render_frame_id,
- params,
- output_device_id,
- shared_memory.Pass(),
- reader.PassAs<media::AudioOutputController::SyncReader>()));
+ scoped_ptr<AudioEntry> entry(new AudioEntry(this,
+ stream_id,
+ render_view_id,
+ render_frame_id,
+ params,
+ output_device_id,
+ shared_memory.Pass(),
+ reader.Pass()));
if (mirroring_manager_) {
mirroring_manager_->AddDiverter(
- render_process_id_, entry->render_view_id(), entry->controller());
+ render_process_id_, entry->render_frame_id(), entry->controller());
}
audio_entries_.insert(std::make_pair(stream_id, entry.release()));
audio_log_->OnCreated(stream_id, params, output_device_id);
@@ -454,10 +435,8 @@ void AudioRendererHost::OnCloseStream(int stream_id) {
audio_entries_.erase(i);
media::AudioOutputController* const controller = entry->controller();
- if (mirroring_manager_) {
- mirroring_manager_->RemoveDiverter(
- render_process_id_, entry->render_view_id(), controller);
- }
+ if (mirroring_manager_)
+ mirroring_manager_->RemoveDiverter(controller);
controller->Close(
base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
audio_log_->OnClosed(stream_id);
@@ -465,17 +444,9 @@ void AudioRendererHost::OnCloseStream(int stream_id) {
void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // At this point, make the final "say" in audio playback state.
- MediaObserver* const media_observer =
- GetContentClient()->browser()->GetMediaObserver();
- if (media_observer) {
- media_observer->OnAudioStreamStopped(render_process_id_,
- entry->render_frame_id(),
- entry->stream_id());
- if (entry->playing())
- base::AtomicRefCountDec(&num_playing_streams_);
- }
+ AudioStreamMonitor::StopMonitoringStream(
+ render_process_id_, entry->render_frame_id(), entry->stream_id());
+ UpdateNumPlayingStreams(entry.get(), false);
}
void AudioRendererHost::ReportErrorAndClose(int stream_id) {
@@ -500,8 +471,44 @@ AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
return i != audio_entries_.end() ? i->second : NULL;
}
+void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry,
+ bool is_playing) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (entry->playing() == is_playing)
+ return;
+
+ bool should_alert_resource_scheduler;
+ if (is_playing) {
+ should_alert_resource_scheduler =
+ !RenderViewHasActiveAudio(entry->render_view_id());
+ entry->set_playing(true);
+ base::AtomicRefCountInc(&num_playing_streams_);
+ } else {
+ entry->set_playing(false);
+ should_alert_resource_scheduler =
+ !RenderViewHasActiveAudio(entry->render_view_id());
+ base::AtomicRefCountDec(&num_playing_streams_);
+ }
+
+ if (should_alert_resource_scheduler && ResourceDispatcherHostImpl::Get()) {
+ ResourceDispatcherHostImpl::Get()->OnAudioRenderHostStreamStateChanged(
+ render_process_id_, entry->render_view_id(), is_playing);
+ }
+}
+
bool AudioRendererHost::HasActiveAudio() {
return !base::AtomicRefCountIsZero(&num_playing_streams_);
}
+bool AudioRendererHost::RenderViewHasActiveAudio(int render_view_id) const {
+ for (AudioEntryMap::const_iterator it = audio_entries_.begin();
+ it != audio_entries_.end();
+ ++it) {
+ AudioEntry* entry = it->second;
+ if (entry->render_view_id() == render_view_id && entry->playing())
+ return true;
+ }
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
index 38317ef8094..11bc13f3900 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
@@ -81,14 +81,18 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
const RenderViewHost::GetAudioOutputControllersCallback& callback) const;
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Returns true if any streams managed by this host are actively playing. Can
// be called from any thread.
bool HasActiveAudio();
+ // Returns true if any streams managed by the RenderView identified by
+ // |render_view_id| are actively playing. Can be called from any thread.
+ bool RenderViewHasActiveAudio(int render_view_id) const;
+
private:
friend class AudioRendererHostTest;
friend class BrowserThread;
@@ -101,7 +105,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
class AudioEntry;
typedef std::map<int, AudioEntry*> AudioEntryMap;
- virtual ~AudioRendererHost();
+ ~AudioRendererHost() override;
// Methods called on IO thread ----------------------------------------------
@@ -157,6 +161,10 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
// Returns NULL if not found.
AudioEntry* LookupById(int stream_id);
+ // A helper method to update the number of playing streams and alert the
+ // ResourceScheduler when the renderer starts or stops playing an audiostream.
+ void UpdateNumPlayingStreams(AudioEntry* entry, bool is_playing);
+
// ID of the RenderProcessHost that owns this instance.
const int render_process_id_;
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 343c9890810..8c03eaca66b 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
@@ -43,12 +43,9 @@ class MockAudioMirroringManager : public AudioMirroringManager {
MOCK_METHOD3(AddDiverter,
void(int render_process_id,
- int render_view_id,
- Diverter* diverter));
- MOCK_METHOD3(RemoveDiverter,
- void(int render_process_id,
- int render_view_id,
+ int render_frame_id,
Diverter* diverter));
+ MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter));
private:
DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
@@ -101,14 +98,9 @@ class MockAudioRendererHost : public AudioRendererHost {
return true;
}
- void OnNotifyStreamCreated(int stream_id,
- base::SharedMemoryHandle handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle socket_handle,
-#else
- base::FileDescriptor socket_descriptor,
-#endif
- uint32 length) {
+ void OnNotifyStreamCreated(
+ int stream_id, base::SharedMemoryHandle handle,
+ base::SyncSocket::TransitDescriptor socket_descriptor, uint32 length) {
// Maps the shared memory.
shared_memory_.reset(new base::SharedMemory(handle, false));
CHECK(shared_memory_->Map(length));
@@ -116,12 +108,8 @@ class MockAudioRendererHost : public AudioRendererHost {
shared_memory_length_ = length;
// Create the SyncSocket using the handle.
- base::SyncSocket::Handle sync_socket_handle;
-#if defined(OS_WIN)
- sync_socket_handle = socket_handle;
-#else
- sync_socket_handle = socket_descriptor.fd;
-#endif
+ base::SyncSocket::Handle sync_socket_handle =
+ base::SyncSocket::UnwrapHandle(socket_descriptor);
sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
// And then delegate the call to the mock method.
@@ -157,7 +145,7 @@ class AudioRendererHostTest : public testing::Test {
public:
AudioRendererHostTest() {
audio_manager_.reset(media::AudioManager::CreateForTesting());
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
host_ = new MockAudioRendererHost(audio_manager_.get(),
@@ -169,7 +157,7 @@ class AudioRendererHostTest : public testing::Test {
host_->set_peer_pid_for_testing(base::GetCurrentProcId());
}
- virtual ~AudioRendererHostTest() {
+ ~AudioRendererHostTest() override {
// Simulate closing the IPC channel and give the audio thread time to close
// the underlying streams.
host_->OnChannelClosing();
@@ -185,7 +173,7 @@ class AudioRendererHostTest : public testing::Test {
EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
EXPECT_CALL(mirroring_manager_,
- AddDiverter(kRenderProcessId, kRenderViewId, NotNull()))
+ AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
.RetiresOnSaturation();
// Send a create stream message to the audio output stream and wait until
@@ -199,7 +187,6 @@ class AudioRendererHostTest : public testing::Test {
params = media::AudioParameters(
media::AudioParameters::AUDIO_FAKE,
media::CHANNEL_LAYOUT_STEREO,
- 2,
media::AudioParameters::kAudioCDSampleRate, 16,
media::AudioParameters::kAudioCDSampleRate / 10,
media::AudioParameters::NO_EFFECTS);
@@ -216,8 +203,7 @@ class AudioRendererHostTest : public testing::Test {
// At some point in the future, a corresponding RemoveDiverter() call must
// be made.
- EXPECT_CALL(mirroring_manager_,
- RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull()))
+ EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
.RetiresOnSaturation();
SyncWithAudioThread();
}
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
index 3daacca566e..e6657ef74ca 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -9,12 +9,31 @@
#include "base/command_line.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/histogram.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/common/content_switches.h"
-#include "media/audio/audio_buffers_state.h"
#include "media/audio/audio_parameters.h"
using media::AudioBus;
+namespace {
+
+// Used to log if any audio glitches have been detected during an audio session.
+// Elements in this enum should not be added, deleted or rearranged.
+enum AudioGlitchResult {
+ AUDIO_RENDERER_NO_AUDIO_GLITCHES = 0,
+ AUDIO_RENDERER_AUDIO_GLITCHES = 1,
+ AUDIO_RENDERER_AUDIO_GLITCHES_MAX = AUDIO_RENDERER_AUDIO_GLITCHES
+};
+
+void LogAudioGlitchResult(AudioGlitchResult result) {
+ UMA_HISTOGRAM_ENUMERATION("Media.AudioRendererAudioGlitches",
+ result,
+ AUDIO_RENDERER_AUDIO_GLITCHES_MAX + 1);
+}
+
+} // namespace
+
namespace content {
AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
@@ -47,6 +66,18 @@ AudioSyncReader::~AudioSyncReader() {
100.0 * renderer_missed_callback_count_ / renderer_callback_count_;
UMA_HISTOGRAM_PERCENTAGE(
"Media.AudioRendererMissedDeadline", percentage_missed);
+
+ // Add more detailed information regarding detected audio glitches where
+ // a non-zero value of |renderer_missed_callback_count_| is added to the
+ // AUDIO_RENDERER_AUDIO_GLITCHES bin.
+ renderer_missed_callback_count_ > 0 ?
+ LogAudioGlitchResult(AUDIO_RENDERER_AUDIO_GLITCHES) :
+ LogAudioGlitchResult(AUDIO_RENDERER_NO_AUDIO_GLITCHES);
+ std::string log_string =
+ base::StringPrintf("ASR: number of detected audio glitches=%d",
+ static_cast<int>(renderer_missed_callback_count_));
+ MediaStreamManager::SendMessageToNativeLog(log_string);
+ DVLOG(1) << log_string;
}
// media::AudioOutputController::SyncReader implementations.
@@ -83,24 +114,11 @@ bool AudioSyncReader::Init() {
foreign_socket_.get());
}
-#if defined(OS_WIN)
-bool AudioSyncReader::PrepareForeignSocketHandle(
+bool AudioSyncReader::PrepareForeignSocket(
base::ProcessHandle process_handle,
- base::SyncSocket::Handle* foreign_handle) {
- ::DuplicateHandle(GetCurrentProcess(), foreign_socket_->handle(),
- process_handle, foreign_handle,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
- return (*foreign_handle != 0);
+ base::SyncSocket::TransitDescriptor* descriptor) {
+ return foreign_socket_->PrepareTransitDescriptor(process_handle, descriptor);
}
-#else
-bool AudioSyncReader::PrepareForeignSocketHandle(
- base::ProcessHandle process_handle,
- base::FileDescriptor* foreign_handle) {
- foreign_handle->fd = foreign_socket_->handle();
- foreign_handle->auto_close = false;
- return (foreign_handle->fd != -1);
-}
-#endif
bool AudioSyncReader::WaitUntilDataIsReady() {
base::TimeDelta timeout = maximum_wait_time_;
@@ -125,10 +143,11 @@ bool AudioSyncReader::WaitUntilDataIsReady() {
while (timeout.InMicroseconds() > 0) {
bytes_received = socket_->ReceiveWithTimeout(
&renderer_buffer_index, sizeof(renderer_buffer_index), timeout);
- if (!bytes_received)
+ if (bytes_received != sizeof(renderer_buffer_index)) {
+ bytes_received = 0;
break;
+ }
- DCHECK_EQ(bytes_received, sizeof(renderer_buffer_index));
if (renderer_buffer_index == buffer_index_)
break;
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.h b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
index d596d1b4c0e..16af1921894 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.h
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
@@ -31,20 +31,16 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
AudioSyncReader(base::SharedMemory* shared_memory,
const media::AudioParameters& params);
- virtual ~AudioSyncReader();
+ ~AudioSyncReader() override;
// media::AudioOutputController::SyncReader implementations.
- virtual void UpdatePendingBytes(uint32 bytes) OVERRIDE;
- virtual void Read(media::AudioBus* dest) OVERRIDE;
- virtual void Close() OVERRIDE;
+ void UpdatePendingBytes(uint32 bytes) override;
+ void Read(media::AudioBus* dest) override;
+ void Close() override;
bool Init();
- bool PrepareForeignSocketHandle(base::ProcessHandle process_handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle* foreign_handle);
-#else
- base::FileDescriptor* foreign_handle);
-#endif
+ bool PrepareForeignSocket(base::ProcessHandle process_handle,
+ base::SyncSocket::TransitDescriptor* descriptor);
private:
// Blocks until data is ready for reading or a timeout expires. Returns false
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter.cc b/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
deleted file mode 100644
index db0d175e754..00000000000
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2013 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 "content/browser/renderer_host/media/device_request_message_filter.h"
-
-#include "content/browser/browser_main_loop.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/media/media_stream_messages.h"
-#include "content/public/browser/resource_context.h"
-
-namespace content {
-
-DeviceRequestMessageFilter::DeviceRequestMessageFilter(
- ResourceContext* resource_context,
- MediaStreamManager* media_stream_manager,
- int render_process_id)
- : BrowserMessageFilter(MediaStreamMsgStart),
- resource_context_(resource_context),
- media_stream_manager_(media_stream_manager),
- render_process_id_(render_process_id) {
- DCHECK(resource_context);
- DCHECK(media_stream_manager);
-}
-
-DeviceRequestMessageFilter::~DeviceRequestMessageFilter() {
- // CHECK rather than DCHECK to make sure this never happens in the
- // wild. We want to be sure due to http://crbug.com/341211
- CHECK(requests_.empty());
-}
-
-struct DeviceRequestMessageFilter::DeviceRequest {
- DeviceRequest(int request_id,
- const GURL& origin,
- const std::string& audio_devices_label,
- const std::string& video_devices_label)
- : request_id(request_id),
- origin(origin),
- has_audio_returned(false),
- has_video_returned(false),
- audio_devices_label(audio_devices_label),
- video_devices_label(video_devices_label) {}
-
- int request_id;
- GURL origin;
- bool has_audio_returned;
- bool has_video_returned;
- std::string audio_devices_label;
- std::string video_devices_label;
- StreamDeviceInfoArray audio_devices;
- StreamDeviceInfoArray video_devices;
-};
-
-void DeviceRequestMessageFilter::DevicesEnumerated(
- int render_view_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& new_devices) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Look up the DeviceRequest by id.
- DeviceRequestList::iterator request_it = requests_.begin();
- for (; request_it != requests_.end(); ++request_it) {
- if (label == request_it->audio_devices_label ||
- label == request_it->video_devices_label) {
- break;
- }
- }
- DCHECK(request_it != requests_.end());
-
- StreamDeviceInfoArray* audio_devices = &request_it->audio_devices;
- StreamDeviceInfoArray* video_devices = &request_it->video_devices;
-
- // Store hmac'd device ids instead of raw device ids.
- if (label == request_it->audio_devices_label) {
- request_it->has_audio_returned = true;
- DCHECK(audio_devices->empty());
- *audio_devices = new_devices;
- } else {
- DCHECK(label == request_it->video_devices_label);
- request_it->has_video_returned = true;
- DCHECK(video_devices->empty());
- *video_devices = new_devices;
- }
-
- if (!request_it->has_audio_returned || !request_it->has_video_returned) {
- // Wait for the rest of the devices to complete.
- return;
- }
-
- // Both audio and video devices are ready for copying.
- StreamDeviceInfoArray all_devices = *audio_devices;
- all_devices.insert(
- all_devices.end(), video_devices->begin(), video_devices->end());
-
- Send(new MediaStreamMsg_GetSourcesACK(request_it->request_id, all_devices));
-
- media_stream_manager_->CancelRequest(request_it->audio_devices_label);
- media_stream_manager_->CancelRequest(request_it->video_devices_label);
- requests_.erase(request_it);
-}
-
-bool DeviceRequestMessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(DeviceRequestMessageFilter, message)
- IPC_MESSAGE_HANDLER(MediaStreamHostMsg_GetSources, OnGetSources)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void DeviceRequestMessageFilter::OnChannelClosing() {
- // Since the IPC channel is gone, cancel outstanding device requests.
- for (DeviceRequestList::iterator request_it = requests_.begin();
- request_it != requests_.end(); ++request_it) {
- media_stream_manager_->CancelRequest(request_it->audio_devices_label);
- media_stream_manager_->CancelRequest(request_it->video_devices_label);
- }
- requests_.clear();
-}
-
-void DeviceRequestMessageFilter::OnGetSources(int request_id,
- const GURL& security_origin) {
- if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
- render_process_id_, security_origin)) {
- LOG(ERROR) << "Disallowed URL in DRMF::OnGetSources: " << security_origin;
- return;
- }
-
- // Make request to get audio devices.
- const std::string& audio_label = media_stream_manager_->EnumerateDevices(
- this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
- MEDIA_DEVICE_AUDIO_CAPTURE, security_origin,
- resource_context_->AllowMicAccess(security_origin));
- DCHECK(!audio_label.empty());
-
- // Make request for video devices.
- const std::string& video_label = media_stream_manager_->EnumerateDevices(
- this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
- MEDIA_DEVICE_VIDEO_CAPTURE, security_origin,
- resource_context_->AllowCameraAccess(security_origin));
- DCHECK(!video_label.empty());
-
- requests_.push_back(DeviceRequest(
- request_id, security_origin, audio_label, video_label));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter.h b/chromium/content/browser/renderer_host/media/device_request_message_filter.h
deleted file mode 100644
index 2ec54ccfc37..00000000000
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2013 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 CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
-
-#include <map>
-#include <string>
-
-#include "base/synchronization/lock.h"
-#include "content/browser/renderer_host/media/media_stream_requester.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace content {
-
-class MediaStreamManager;
-class ResourceContext;
-
-// DeviceRequestMessageFilter used to delegate requests from the
-// MediaStreamCenter.
-class CONTENT_EXPORT DeviceRequestMessageFilter : public BrowserMessageFilter,
- public MediaStreamRequester {
- public:
- DeviceRequestMessageFilter(ResourceContext* resource_context,
- MediaStreamManager* media_stream_manager,
- int render_process_id);
-
- // MediaStreamRequester implementation.
- // TODO(vrk): Replace MediaStreamRequester interface with a single callback so
- // we don't have to override all these callbacks we don't care about.
- // (crbug.com/249476)
- virtual void StreamGenerated(
- int render_view_id, int page_request_id, const std::string& label,
- const StreamDeviceInfoArray& audio_devices,
- const StreamDeviceInfoArray& video_devices) OVERRIDE {}
- virtual void StreamGenerationFailed(
- int render_view_id,
- int page_request_id,
- content::MediaStreamRequestResult result) OVERRIDE {}
- virtual void DeviceStopped(int render_view_id,
- const std::string& label,
- const StreamDeviceInfo& device) OVERRIDE {}
- virtual void DeviceOpened(int render_view_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfo& video_device) OVERRIDE {}
- // DevicesEnumerated() is the only callback we're interested in.
- virtual void DevicesEnumerated(int render_view_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices) OVERRIDE;
-
- // BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
-
- protected:
- virtual ~DeviceRequestMessageFilter();
-
- private:
- void OnGetSources(int request_id, const GURL& security_origin);
-
- // Owned by ProfileIOData which is guaranteed to outlive DRMF.
- ResourceContext* resource_context_;
- MediaStreamManager* media_stream_manager_;
-
- struct DeviceRequest;
- typedef std::vector<DeviceRequest> DeviceRequestList;
- // List of all requests.
- DeviceRequestList requests_;
-
- int render_process_id_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceRequestMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_DEVICE_REQUEST_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
deleted file mode 100644
index 6d6a9e34dad..00000000000
--- a/chromium/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 2013 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/strings/string_number_conversions.h"
-#include "content/browser/renderer_host/media/device_request_message_filter.h"
-#include "content/browser/renderer_host/media/media_stream_manager.h"
-#include "content/common/media/media_stream_messages.h"
-#include "content/public/test/mock_resource_context.h"
-#include "content/public/test/test_browser_thread.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::Invoke;
-
-namespace content {
-
-static const std::string kAudioLabel = "audio_label";
-static const std::string kVideoLabel = "video_label";
-
-class MockMediaStreamManager : public MediaStreamManager {
- public:
- MockMediaStreamManager() {}
-
- virtual ~MockMediaStreamManager() {}
-
- MOCK_METHOD8(EnumerateDevices,
- std::string(MediaStreamRequester* requester,
- int render_process_id,
- int render_view_id,
- const ResourceContext::SaltCallback& rc,
- int page_request_id,
- MediaStreamType type,
- const GURL& security_origin,
- bool have_permission));
-
- std::string DoEnumerateDevices(MediaStreamRequester* requester,
- int render_process_id,
- int render_view_id,
- const ResourceContext::SaltCallback& rc,
- int page_request_id,
- MediaStreamType type,
- const GURL& security_origin,
- bool have_permission) {
- if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
- return kAudioLabel;
- } else {
- return kVideoLabel;
- }
- }
-};
-
-class MockDeviceRequestMessageFilter : public DeviceRequestMessageFilter {
- public:
- MockDeviceRequestMessageFilter(MockResourceContext* context,
- MockMediaStreamManager* manager)
- : DeviceRequestMessageFilter(context, manager, 0), received_id_(-1) {}
- StreamDeviceInfoArray requested_devices() { return requested_devices_; }
- int received_id() { return received_id_; }
-
- private:
- virtual ~MockDeviceRequestMessageFilter() {}
-
- // Override the Send() method to intercept the message that we're sending to
- // the renderer.
- virtual bool Send(IPC::Message* reply_msg) OVERRIDE {
- CHECK(reply_msg);
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MockDeviceRequestMessageFilter, *reply_msg)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK, SaveDevices)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- EXPECT_TRUE(handled);
-
- delete reply_msg;
- return true;
- }
-
- void SaveDevices(int request_id, const StreamDeviceInfoArray& devices) {
- received_id_ = request_id;
- requested_devices_ = devices;
- }
-
- int received_id_;
- StreamDeviceInfoArray requested_devices_;
-};
-
-class DeviceRequestMessageFilterTest : public testing::Test {
- public:
- DeviceRequestMessageFilterTest() : next_device_id_(0) {}
-
- void RunTest(int number_audio_devices, int number_video_devices) {
- AddAudioDevices(number_audio_devices);
- AddVideoDevices(number_video_devices);
- GURL origin("https://test.com");
- EXPECT_CALL(*media_stream_manager_,
- EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE,
- _, _))
- .Times(1);
- EXPECT_CALL(*media_stream_manager_,
- EnumerateDevices(_, _, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE,
- _, _))
- .Times(1);
- // Send message to get devices. Should trigger 2 EnumerateDevice() requests.
- const int kRequestId = 123;
- SendGetSourcesMessage(kRequestId, origin);
-
- // Run audio callback. Because there's still an outstanding video request,
- // this should not populate |message|.
- FireAudioDeviceCallback();
- EXPECT_EQ(0u, host_->requested_devices().size());
-
- // After the video device callback is fired, |message| should be populated.
- FireVideoDeviceCallback();
- EXPECT_EQ(static_cast<size_t>(number_audio_devices + number_video_devices),
- host_->requested_devices().size());
-
- EXPECT_EQ(kRequestId, host_->received_id());
- }
-
- protected:
- virtual ~DeviceRequestMessageFilterTest() {}
-
- virtual void SetUp() OVERRIDE {
- message_loop_.reset(new base::MessageLoopForIO);
- io_thread_.reset(
- new TestBrowserThread(BrowserThread::IO, message_loop_.get()));
-
- media_stream_manager_.reset(new MockMediaStreamManager());
- ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _, _, _))
- .WillByDefault(Invoke(media_stream_manager_.get(),
- &MockMediaStreamManager::DoEnumerateDevices));
-
- resource_context_.reset(new MockResourceContext(NULL));
- host_ = new MockDeviceRequestMessageFilter(resource_context_.get(),
- media_stream_manager_.get());
- }
-
- scoped_refptr<MockDeviceRequestMessageFilter> host_;
- scoped_ptr<MockMediaStreamManager> media_stream_manager_;
- scoped_ptr<MockResourceContext> resource_context_;
- StreamDeviceInfoArray physical_audio_devices_;
- StreamDeviceInfoArray physical_video_devices_;
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<TestBrowserThread> io_thread_;
-
- private:
- void AddAudioDevices(int number_of_devices) {
- for (int i = 0; i < number_of_devices; i++) {
- physical_audio_devices_.push_back(
- StreamDeviceInfo(
- MEDIA_DEVICE_AUDIO_CAPTURE,
- "/dev/audio/" + base::IntToString(next_device_id_),
- "Audio Device" + base::IntToString(next_device_id_)));
- next_device_id_++;
- }
- }
-
- void AddVideoDevices(int number_of_devices) {
- for (int i = 0; i < number_of_devices; i++) {
- physical_video_devices_.push_back(
- StreamDeviceInfo(
- MEDIA_DEVICE_VIDEO_CAPTURE,
- "/dev/video/" + base::IntToString(next_device_id_),
- "Video Device" + base::IntToString(next_device_id_)));
- next_device_id_++;
- }
- }
-
- void SendGetSourcesMessage(int request_id, const GURL& origin) {
- host_->OnMessageReceived(MediaStreamHostMsg_GetSources(request_id, origin));
- }
-
- void FireAudioDeviceCallback() {
- host_->DevicesEnumerated(-1, -1, kAudioLabel, physical_audio_devices_);
- }
-
- void FireVideoDeviceCallback() {
- host_->DevicesEnumerated(-1, -1, kVideoLabel, physical_video_devices_);
- }
-
- int next_device_id_;
-};
-
-TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AudioAndVideoDevices) {
- // Runs through test with 1 audio and 1 video device.
- RunTest(1, 1);
-}
-
-TEST_F(DeviceRequestMessageFilterTest,
- TestGetSources_MultipleAudioAndVideoDevices) {
- // Runs through test with 3 audio devices and 2 video devices.
- RunTest(3, 2);
-}
-
-TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoVideoDevices) {
- // Runs through test with 4 audio devices and 0 video devices.
- RunTest(4, 0);
-}
-
-TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoAudioDevices) {
- // Runs through test with 0 audio devices and 3 video devices.
- RunTest(0, 3);
-}
-
-TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoDevices) {
- // Runs through test with no devices.
- RunTest(0, 0);
-}
-
-}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_capture_devices_impl.h b/chromium/content/browser/renderer_host/media/media_capture_devices_impl.h
index 078f659608b..77174cc6205 100644
--- a/chromium/content/browser/renderer_host/media/media_capture_devices_impl.h
+++ b/chromium/content/browser/renderer_host/media/media_capture_devices_impl.h
@@ -15,8 +15,8 @@ class MediaCaptureDevicesImpl : public MediaCaptureDevices {
static MediaCaptureDevicesImpl* GetInstance();
// Overriden from MediaCaptureDevices
- virtual const MediaStreamDevices& GetAudioCaptureDevices() OVERRIDE;
- virtual const MediaStreamDevices& GetVideoCaptureDevices() OVERRIDE;
+ const MediaStreamDevices& GetAudioCaptureDevices() override;
+ const MediaStreamDevices& GetVideoCaptureDevices() override;
// Called by MediaStreamManager to notify the change of media capture
// devices, these 2 methods are called in IO thread.
@@ -26,7 +26,7 @@ class MediaCaptureDevicesImpl : public MediaCaptureDevices {
private:
friend struct DefaultSingletonTraits<MediaCaptureDevicesImpl>;
MediaCaptureDevicesImpl();
- virtual ~MediaCaptureDevicesImpl();
+ ~MediaCaptureDevicesImpl() override;
void UpdateAudioDevicesOnUIThread(const content::MediaStreamDevices& devices);
void UpdateVideoDevicesOnUIThread(const content::MediaStreamDevices& devices);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index 91fad34fe5c..2b0a385f8f9 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -16,17 +16,15 @@ namespace content {
MediaStreamDispatcherHost::MediaStreamDispatcherHost(
int render_process_id,
const ResourceContext::SaltCallback& salt_callback,
- MediaStreamManager* media_stream_manager,
- ResourceContext* resource_context)
+ MediaStreamManager* media_stream_manager)
: BrowserMessageFilter(MediaStreamMsgStart),
render_process_id_(render_process_id),
salt_callback_(salt_callback),
- media_stream_manager_(media_stream_manager),
- resource_context_(resource_context) {
+ media_stream_manager_(media_stream_manager) {
}
void MediaStreamDispatcherHost::StreamGenerated(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
@@ -36,12 +34,11 @@ void MediaStreamDispatcherHost::StreamGenerated(
<< ", {label = " << label << "})";
Send(new MediaStreamMsg_StreamGenerated(
- render_view_id, page_request_id, label, audio_devices,
- video_devices));
+ render_frame_id, page_request_id, label, audio_devices, video_devices));
}
void MediaStreamDispatcherHost::StreamGenerationFailed(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
content::MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -50,12 +47,12 @@ void MediaStreamDispatcherHost::StreamGenerationFailed(
<< ", { result= " << result << "})";
- Send(new MediaStreamMsg_StreamGenerationFailed(render_view_id,
+ Send(new MediaStreamMsg_StreamGenerationFailed(render_frame_id,
page_request_id,
result));
}
-void MediaStreamDispatcherHost::DeviceStopped(int render_view_id,
+void MediaStreamDispatcherHost::DeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -64,11 +61,11 @@ void MediaStreamDispatcherHost::DeviceStopped(int render_view_id,
<< "{type = " << device.device.type << "}, "
<< "{device_id = " << device.device.id << "})";
- Send(new MediaStreamMsg_DeviceStopped(render_view_id, label, device));
+ Send(new MediaStreamMsg_DeviceStopped(render_frame_id, label, device));
}
void MediaStreamDispatcherHost::DevicesEnumerated(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& devices) {
@@ -76,12 +73,12 @@ void MediaStreamDispatcherHost::DevicesEnumerated(
DVLOG(1) << "MediaStreamDispatcherHost::DevicesEnumerated("
<< ", {page_request_id = " << page_request_id << "})";
- Send(new MediaStreamMsg_DevicesEnumerated(render_view_id, page_request_id,
+ Send(new MediaStreamMsg_DevicesEnumerated(render_frame_id, page_request_id,
devices));
}
void MediaStreamDispatcherHost::DeviceOpened(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& video_device) {
@@ -90,7 +87,7 @@ void MediaStreamDispatcherHost::DeviceOpened(
<< ", {page_request_id = " << page_request_id << "})";
Send(new MediaStreamMsg_DeviceOpened(
- render_view_id, page_request_id, label, video_device));
+ render_frame_id, page_request_id, label, video_device));
}
bool MediaStreamDispatcherHost::OnMessageReceived(const IPC::Message& message) {
@@ -125,13 +122,13 @@ MediaStreamDispatcherHost::~MediaStreamDispatcherHost() {
}
void MediaStreamDispatcherHost::OnGenerateStream(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const StreamOptions& components,
const GURL& security_origin,
bool user_gesture) {
DVLOG(1) << "MediaStreamDispatcherHost::OnGenerateStream("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< page_request_id << ", ["
<< " audio:" << components.audio_requested
<< " video:" << components.video_requested
@@ -143,37 +140,36 @@ void MediaStreamDispatcherHost::OnGenerateStream(
return;
media_stream_manager_->GenerateStream(
- this, render_process_id_, render_view_id, salt_callback_,
+ this, render_process_id_, render_frame_id, salt_callback_,
page_request_id, components, security_origin, user_gesture);
}
-void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id,
+void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_frame_id,
int page_request_id) {
DVLOG(1) << "MediaStreamDispatcherHost::OnCancelGenerateStream("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< page_request_id << ")";
- media_stream_manager_->CancelRequest(render_process_id_, render_view_id,
+ media_stream_manager_->CancelRequest(render_process_id_, render_frame_id,
page_request_id);
}
void MediaStreamDispatcherHost::OnStopStreamDevice(
- int render_view_id,
+ int render_frame_id,
const std::string& device_id) {
DVLOG(1) << "MediaStreamDispatcherHost::OnStopStreamDevice("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< device_id << ")";
- media_stream_manager_->StopStreamDevice(render_process_id_, render_view_id,
+ media_stream_manager_->StopStreamDevice(render_process_id_, render_frame_id,
device_id);
}
void MediaStreamDispatcherHost::OnEnumerateDevices(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
MediaStreamType type,
- const GURL& security_origin,
- bool hide_labels_if_no_access) {
+ const GURL& security_origin) {
DVLOG(1) << "MediaStreamDispatcherHost::OnEnumerateDevices("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< page_request_id << ", "
<< type << ", "
<< security_origin.spec() << ")";
@@ -181,41 +177,29 @@ void MediaStreamDispatcherHost::OnEnumerateDevices(
if (!IsURLAllowed(security_origin))
return;
- DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- type == MEDIA_DEVICE_VIDEO_CAPTURE ||
- type == MEDIA_DEVICE_AUDIO_OUTPUT);
- bool have_permission = true;
- if (hide_labels_if_no_access) {
- bool audio_type = type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- type == MEDIA_DEVICE_AUDIO_OUTPUT;
- have_permission = audio_type ?
- resource_context_->AllowMicAccess(security_origin) :
- resource_context_->AllowCameraAccess(security_origin);
- }
-
media_stream_manager_->EnumerateDevices(
- this, render_process_id_, render_view_id, salt_callback_,
- page_request_id, type, security_origin, have_permission);
+ this, render_process_id_, render_frame_id, salt_callback_,
+ page_request_id, type, security_origin);
}
void MediaStreamDispatcherHost::OnCancelEnumerateDevices(
- int render_view_id,
+ int render_frame_id,
int page_request_id) {
DVLOG(1) << "MediaStreamDispatcherHost::OnCancelEnumerateDevices("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< page_request_id << ")";
- media_stream_manager_->CancelRequest(render_process_id_, render_view_id,
+ media_stream_manager_->CancelRequest(render_process_id_, render_frame_id,
page_request_id);
}
void MediaStreamDispatcherHost::OnOpenDevice(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
const GURL& security_origin) {
DVLOG(1) << "MediaStreamDispatcherHost::OnOpenDevice("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< page_request_id << ", device_id: "
<< device_id.c_str() << ", type: "
<< type << ", "
@@ -225,15 +209,15 @@ void MediaStreamDispatcherHost::OnOpenDevice(
return;
media_stream_manager_->OpenDevice(
- this, render_process_id_, render_view_id, salt_callback_,
+ this, render_process_id_, render_frame_id, salt_callback_,
page_request_id, device_id, type, security_origin);
}
void MediaStreamDispatcherHost::OnCloseDevice(
- int render_view_id,
+ int render_frame_id,
const std::string& label) {
DVLOG(1) << "MediaStreamDispatcherHost::OnCloseDevice("
- << render_view_id << ", "
+ << render_frame_id << ", "
<< label << ")";
media_stream_manager_->CancelRequest(label);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index b599c39c951..f35ae26e992 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -22,79 +22,76 @@ class MediaStreamManager;
class ResourceContext;
// MediaStreamDispatcherHost is a delegate for Media Stream API messages used by
-// MediaStreamImpl. It's the complement of MediaStreamDispatcher
-// (owned by RenderView).
+// MediaStreamImpl. There is one MediaStreamDispatcherHost per
+// RenderProcessHost, the former owned by the latter.
class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
public MediaStreamRequester {
public:
MediaStreamDispatcherHost(
int render_process_id,
const ResourceContext::SaltCallback& salt_callback,
- MediaStreamManager* media_stream_manager,
- ResourceContext* resource_context);
+ MediaStreamManager* media_stream_manager);
// MediaStreamRequester implementation.
- virtual void StreamGenerated(
- int render_view_id,
+ void StreamGenerated(int render_frame_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& audio_devices,
+ const StreamDeviceInfoArray& video_devices) override;
+ void StreamGenerationFailed(
+ int render_frame_id,
int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& audio_devices,
- const StreamDeviceInfoArray& video_devices) OVERRIDE;
- virtual void StreamGenerationFailed(
- int render_view_id,
- int page_request_id,
- content::MediaStreamRequestResult result) OVERRIDE;
- virtual void DeviceStopped(int render_view_id,
- const std::string& label,
- const StreamDeviceInfo& device) OVERRIDE;
- virtual void DevicesEnumerated(int render_view_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfoArray& devices) OVERRIDE;
- virtual void DeviceOpened(int render_view_id,
- int page_request_id,
- const std::string& label,
- const StreamDeviceInfo& video_device) OVERRIDE;
+ content::MediaStreamRequestResult result) override;
+ void DeviceStopped(int render_frame_id,
+ const std::string& label,
+ const StreamDeviceInfo& device) override;
+ void DevicesEnumerated(int render_frame_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& devices) override;
+ void DeviceOpened(int render_frame_id,
+ int page_request_id,
+ const std::string& label,
+ const StreamDeviceInfo& video_device) override;
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelClosing() override;
protected:
- virtual ~MediaStreamDispatcherHost();
+ ~MediaStreamDispatcherHost() override;
private:
friend class MockMediaStreamDispatcherHost;
- void OnGenerateStream(int render_view_id,
+ void OnGenerateStream(int render_frame_id,
int page_request_id,
const StreamOptions& components,
const GURL& security_origin,
bool user_gesture);
- void OnCancelGenerateStream(int render_view_id,
+ void OnCancelGenerateStream(int render_frame_id,
int page_request_id);
- void OnStopStreamDevice(int render_view_id,
+ void OnStopStreamDevice(int render_frame_id,
const std::string& device_id);
- void OnEnumerateDevices(int render_view_id,
+ void OnEnumerateDevices(int render_frame_id,
int page_request_id,
MediaStreamType type,
- const GURL& security_origin,
- bool hide_labels_if_no_access);
+ const GURL& security_origin);
- void OnCancelEnumerateDevices(int render_view_id,
+ void OnCancelEnumerateDevices(int render_frame_id,
int page_request_id);
- void OnOpenDevice(int render_view_id,
+ void OnOpenDevice(int render_frame_id,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
const GURL& security_origin);
- void OnCloseDevice(int render_view_id,
+ void OnCloseDevice(int render_frame_id,
const std::string& label);
- void StoreRequest(int render_view_id,
+ void StoreRequest(int render_frame_id,
int page_request_id,
const std::string& label);
@@ -104,9 +101,6 @@ class CONTENT_EXPORT MediaStreamDispatcherHost : public BrowserMessageFilter,
ResourceContext::SaltCallback salt_callback_;
MediaStreamManager* media_stream_manager_;
- // Owned by ProfileIOData which is guaranteed to outlive MSDH.
- ResourceContext* const resource_context_;
-
DISALLOW_COPY_AND_ASSIGN(MediaStreamDispatcherHost);
};
diff --git a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index a7edd38fc25..9b3d22f2661 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -33,6 +33,10 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/audio/cras_audio_handler.h"
+#endif
+
using ::testing::_;
using ::testing::DeleteArg;
using ::testing::DoAll;
@@ -52,10 +56,8 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
MockMediaStreamDispatcherHost(
const ResourceContext::SaltCallback salt_callback,
const scoped_refptr<base::MessageLoopProxy>& message_loop,
- MediaStreamManager* manager,
- ResourceContext* resource_context)
- : MediaStreamDispatcherHost(kProcessId, salt_callback, manager,
- resource_context),
+ MediaStreamManager* manager)
+ : MediaStreamDispatcherHost(kProcessId, salt_callback, manager),
message_loop_(message_loop),
current_ipc_(NULL) {}
@@ -70,22 +72,22 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id));
// Accessor to private functions.
- void OnGenerateStream(int render_view_id,
+ void OnGenerateStream(int render_frame_id,
int page_request_id,
const StreamOptions& components,
const GURL& security_origin,
const base::Closure& quit_closure) {
quit_closures_.push(quit_closure);
MediaStreamDispatcherHost::OnGenerateStream(
- render_view_id, page_request_id, components, security_origin, false);
+ render_frame_id, page_request_id, components, security_origin, false);
}
- void OnStopStreamDevice(int render_view_id,
+ void OnStopStreamDevice(int render_frame_id,
const std::string& device_id) {
- MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id, device_id);
+ MediaStreamDispatcherHost::OnStopStreamDevice(render_frame_id, device_id);
}
- void OnOpenDevice(int render_view_id,
+ void OnOpenDevice(int render_frame_id,
int page_request_id,
const std::string& device_id,
MediaStreamType type,
@@ -93,19 +95,17 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
const base::Closure& quit_closure) {
quit_closures_.push(quit_closure);
MediaStreamDispatcherHost::OnOpenDevice(
- render_view_id, page_request_id, device_id, type, security_origin);
+ render_frame_id, page_request_id, device_id, type, security_origin);
}
- void OnEnumerateDevices(int render_view_id,
+ void OnEnumerateDevices(int render_frame_id,
int page_request_id,
MediaStreamType type,
const GURL& security_origin,
- bool hide_labels_if_no_access,
const base::Closure& quit_closure) {
quit_closures_.push(quit_closure);
MediaStreamDispatcherHost::OnEnumerateDevices(
- render_view_id, page_request_id, type, security_origin,
- hide_labels_if_no_access);
+ render_frame_id, page_request_id, type, security_origin);
}
std::string label_;
@@ -120,7 +120,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
// This method is used to dispatch IPC messages to the renderer. We intercept
// these messages here and dispatch to our mock methods to verify the
// conversation between this object and the renderer.
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ virtual bool Send(IPC::Message* message) override {
CHECK(message);
current_ipc_ = message;
@@ -225,7 +225,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
audio_manager_.reset(
new media::MockAudioManager(base::MessageLoopProxy::current()));
// Make sure we use fake devices to avoid long delays.
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
// Create our own MediaStreamManager.
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
@@ -234,29 +234,38 @@ class MediaStreamDispatcherHostTest : public testing::Test {
media_stream_manager_->video_capture_manager()
->video_capture_device_factory());
DCHECK(video_capture_device_factory_);
+#if defined(OS_WIN)
+ // Override the Video Capture Thread that MediaStreamManager constructs.
+ media_stream_manager_->video_capture_manager()->set_device_task_runner(
+ base::MessageLoopProxy::current());
+#endif
MockResourceContext* mock_resource_context =
static_cast<MockResourceContext*>(
browser_context_.GetResourceContext());
- mock_resource_context->set_mic_access(true);
- mock_resource_context->set_camera_access(true);
host_ = new MockMediaStreamDispatcherHost(
mock_resource_context->GetMediaDeviceIDSalt(),
base::MessageLoopProxy::current(),
- media_stream_manager_.get(),
- mock_resource_context);
+ media_stream_manager_.get());
// Use the fake content client and browser.
content_client_.reset(new TestContentClient());
SetContentClient(content_client_.get());
old_browser_client_ = SetBrowserClientForTesting(host_.get());
+
+#if defined(OS_CHROMEOS)
+ chromeos::CrasAudioHandler::InitializeForTesting();
+#endif
}
- virtual ~MediaStreamDispatcherHostTest() {
+ ~MediaStreamDispatcherHostTest() override {
+#if defined(OS_CHROMEOS)
+ chromeos::CrasAudioHandler::Shutdown();
+#endif
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
video_capture_device_factory_->GetDeviceNames(&physical_video_devices_);
ASSERT_GT(physical_video_devices_.size(), 0u);
@@ -265,21 +274,19 @@ class MediaStreamDispatcherHostTest : public testing::Test {
ASSERT_GT(physical_audio_devices_.size(), 0u);
}
- virtual void TearDown() OVERRIDE {
- host_->OnChannelClosing();
- }
+ void TearDown() override { host_->OnChannelClosing(); }
protected:
virtual void SetupFakeUI(bool expect_started) {
- scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
+ stream_ui_ = new MockMediaStreamUIProxy();
if (expect_started) {
- EXPECT_CALL(*stream_ui, OnStarted(_, _));
+ EXPECT_CALL(*stream_ui_, OnStarted(_, _));
}
media_stream_manager_->UseFakeUI(
- stream_ui.PassAs<FakeMediaStreamUIProxy>());
+ scoped_ptr<FakeMediaStreamUIProxy>(stream_ui_));
}
- void GenerateStreamAndWaitForResult(int render_view_id,
+ void GenerateStreamAndWaitForResult(int render_frame_id,
int page_request_id,
const StreamOptions& options) {
base::RunLoop run_loop;
@@ -289,10 +296,11 @@ class MediaStreamDispatcherHostTest : public testing::Test {
int expected_video_array_size =
(options.video_requested &&
physical_video_devices_.size() > 0) ? 1 : 0;
- EXPECT_CALL(*host_.get(), OnStreamGenerated(render_view_id, page_request_id,
+ EXPECT_CALL(*host_.get(), OnStreamGenerated(render_frame_id,
+ page_request_id,
expected_audio_array_size,
expected_video_array_size));
- host_->OnGenerateStream(render_view_id, page_request_id, options, origin_,
+ host_->OnGenerateStream(render_frame_id, page_request_id, options, origin_,
run_loop.QuitClosure());
run_loop.Run();
EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_));
@@ -302,25 +310,25 @@ class MediaStreamDispatcherHostTest : public testing::Test {
}
void GenerateStreamAndWaitForFailure(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const StreamOptions& options,
MediaStreamRequestResult expected_result) {
base::RunLoop run_loop;
EXPECT_CALL(*host_.get(),
- OnStreamGenerationFailed(render_view_id,
+ OnStreamGenerationFailed(render_frame_id,
page_request_id,
expected_result));
- host_->OnGenerateStream(render_view_id, page_request_id, options, origin_,
- run_loop.QuitClosure());
+ host_->OnGenerateStream(render_frame_id, page_request_id, options,
+ origin_, run_loop.QuitClosure());
run_loop.Run();
}
- void OpenVideoDeviceAndWaitForResult(int render_view_id,
+ void OpenVideoDeviceAndWaitForResult(int render_frame_id,
int page_request_id,
const std::string& device_id) {
base::RunLoop run_loop;
- host_->OnOpenDevice(render_view_id, page_request_id, device_id,
+ host_->OnOpenDevice(render_frame_id, page_request_id, device_id,
MEDIA_DEVICE_VIDEO_CAPTURE, origin_,
run_loop.QuitClosure());
run_loop.Run();
@@ -328,13 +336,12 @@ class MediaStreamDispatcherHostTest : public testing::Test {
EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_));
}
- void EnumerateDevicesAndWaitForResult(int render_view_id,
+ void EnumerateDevicesAndWaitForResult(int render_frame_id,
int page_request_id,
- MediaStreamType type,
- bool hide_labels_if_no_access) {
+ MediaStreamType type) {
base::RunLoop run_loop;
- host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_,
- hide_labels_if_no_access, run_loop.QuitClosure());
+ host_->OnEnumerateDevices(render_frame_id, page_request_id, type, origin_,
+ run_loop.QuitClosure());
run_loop.Run();
ASSERT_FALSE(host_->enumerated_devices_.empty());
EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_));
@@ -420,6 +427,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
scoped_refptr<MockMediaStreamDispatcherHost> host_;
scoped_ptr<media::AudioManager> audio_manager_;
scoped_ptr<MediaStreamManager> media_stream_manager_;
+ MockMediaStreamUIProxy* stream_ui_;
ContentBrowserClient* old_browser_client_;
scoped_ptr<ContentClient> content_client_;
content::TestBrowserThreadBundle thread_bundle_;
@@ -450,6 +458,9 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) {
EXPECT_EQ(host_->video_devices_.size(), 0u);
}
+// This test simulates a shutdown scenario: we don't setup a fake UI proxy for
+// MediaStreamManager, so it will create an ordinary one which will not find
+// a RenderFrameHostDelegate. This normally should only be the case at shutdown.
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) {
StreamOptions options(false, false);
@@ -457,7 +468,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) {
kRenderId,
kPageRequestId,
options,
- MEDIA_DEVICE_INVALID_STATE);
+ MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN);
}
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) {
@@ -470,8 +481,8 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) {
EXPECT_EQ(host_->video_devices_.size(), 1u);
}
-// This test generates two streams with video only using the same render view
-// id. The same capture device with the same device and session id is expected
+// This test generates two streams with video only using the same render frame
+// id. The same capture device with the same device and session id is expected
// to be used.
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) {
StreamOptions options(false, true);
@@ -530,7 +541,7 @@ TEST_F(MediaStreamDispatcherHostTest,
// This test generates two streams with video only using two separate render
-// view ids. The same device id but different session ids are expected.
+// frame ids. The same device id but different session ids are expected.
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
StreamOptions options(false, true);
@@ -545,7 +556,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
const std::string device_id1 = host_->video_devices_.front().device.id;
const int session_id1 = host_->video_devices_.front().session_id;
- // Generate second stream from another render view.
+ // Generate second stream from another render frame.
SetupFakeUI(true);
GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options);
@@ -850,7 +861,7 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
EXPECT_CALL(*stream_ui, OnStarted(_, _))
.WillOnce(SaveArg<0>(&close_callback));
- media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
+ media_stream_manager_->UseFakeUI(stream_ui.Pass());
GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
@@ -884,53 +895,33 @@ TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
}
TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) {
+ SetupFakeUI(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_AUDIO_CAPTURE, true);
+ MEDIA_DEVICE_AUDIO_CAPTURE);
EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
}
TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) {
+ SetupFakeUI(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_VIDEO_CAPTURE, true);
+ MEDIA_DEVICE_VIDEO_CAPTURE);
EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
}
-TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevicesNoAccessHideLabels) {
- MockResourceContext* mock_resource_context =
- static_cast<MockResourceContext*>(browser_context_.GetResourceContext());
- mock_resource_context->set_mic_access(false);
+TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevicesNoAccess) {
+ SetupFakeUI(false);
+ stream_ui_->SetMicAccess(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_AUDIO_CAPTURE, true);
+ MEDIA_DEVICE_AUDIO_CAPTURE);
EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_));
}
-TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevicesNoAccessHideLabels) {
- MockResourceContext* mock_resource_context =
- static_cast<MockResourceContext*>(browser_context_.GetResourceContext());
- mock_resource_context->set_camera_access(false);
+TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevicesNoAccess) {
+ SetupFakeUI(false);
+ stream_ui_->SetCameraAccess(false);
EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_VIDEO_CAPTURE, true);
+ MEDIA_DEVICE_VIDEO_CAPTURE);
EXPECT_TRUE(DoesNotContainLabels(host_->enumerated_devices_));
}
-TEST_F(MediaStreamDispatcherHostTest,
- EnumerateAudioDevicesNoAccessNoHideLabels) {
- MockResourceContext* mock_resource_context =
- static_cast<MockResourceContext*>(browser_context_.GetResourceContext());
- mock_resource_context->set_mic_access(false);
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_AUDIO_CAPTURE, false);
- EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
-}
-
-TEST_F(MediaStreamDispatcherHostTest,
- EnumerateVideoDevicesNoAccessNoHideLabels) {
- MockResourceContext* mock_resource_context =
- static_cast<MockResourceContext*>(browser_context_.GetResourceContext());
- mock_resource_context->set_camera_access(false);
- EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId,
- MEDIA_DEVICE_VIDEO_CAPTURE, false);
- EXPECT_TRUE(DoesContainLabels(host_->enumerated_devices_));
-}
-
}; // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.cc b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
index 2b337cafa78..0124f21297f 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -19,7 +19,6 @@
#include "content/browser/browser_main_loop.h"
#include "content/browser/media/capture/web_contents_capture_util.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/device_request_message_filter.h"
#include "content/browser/renderer_host/media/media_capture_devices_impl.h"
#include "content/browser/renderer_host/media/media_stream_requester.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
@@ -31,6 +30,7 @@
#include "content/public/browser/media_observer.h"
#include "content/public/browser/media_request_state.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/media_stream_request.h"
#include "media/audio/audio_manager_base.h"
@@ -44,6 +44,10 @@
#include "base/win/scoped_com_initializer.h"
#endif
+#if defined(OS_CHROMEOS)
+#include "chromeos/audio/cras_audio_handler.h"
+#endif
+
namespace content {
// Forward declaration of DeviceMonitorMac and its only useable method.
@@ -118,6 +122,18 @@ void ParseStreamType(const StreamOptions& options,
}
}
+// Turns off available audio effects (removes the flag) if the options
+// explicitly turn them off.
+void FilterAudioEffects(const StreamOptions& options, int* effects) {
+ DCHECK(effects);
+ // TODO(ajm): Should we also handle ECHO_CANCELLER here?
+ std::string value;
+ if (options.GetFirstAudioConstraintByName(
+ kMediaStreamAudioDucking, &value, NULL) && value == "false") {
+ *effects &= ~media::AudioParameters::DUCKING;
+ }
+}
+
// Private helper method for SendMessageToNativeLog() that obtains the global
// MediaStreamManager instance on the UI thread before sending |message| to the
// webrtcLoggingPrivate API.
@@ -183,20 +199,18 @@ class MediaStreamManager::DeviceRequest {
public:
DeviceRequest(MediaStreamRequester* requester,
int requesting_process_id,
- int requesting_view_id,
+ int requesting_frame_id,
int page_request_id,
const GURL& security_origin,
- bool have_permission,
bool user_gesture,
MediaStreamRequestType request_type,
const StreamOptions& options,
const ResourceContext::SaltCallback& salt_callback)
: requester(requester),
requesting_process_id(requesting_process_id),
- requesting_view_id(requesting_view_id),
+ requesting_frame_id(requesting_frame_id),
page_request_id(page_request_id),
security_origin(security_origin),
- have_permission(have_permission),
user_gesture(user_gesture),
request_type(request_type),
options(options),
@@ -230,7 +244,7 @@ class MediaStreamManager::DeviceRequest {
const std::string& requested_video_device_id) {
DCHECK(!ui_request_);
ui_request_.reset(new MediaStreamRequest(requesting_process_id,
- requesting_view_id,
+ requesting_frame_id,
page_request_id,
security_origin,
user_gesture,
@@ -243,12 +257,12 @@ class MediaStreamManager::DeviceRequest {
// Creates a tab capture specific MediaStreamRequest object that is used by
// this request when UI is asked for permission and device selection.
- void CreateTabCatureUIRequest(int target_render_process_id,
- int target_render_view_id,
- const std::string& tab_capture_id) {
+ void CreateTabCaptureUIRequest(int target_render_process_id,
+ int target_render_frame_id,
+ const std::string& tab_capture_id) {
DCHECK(!ui_request_);
ui_request_.reset(new MediaStreamRequest(target_render_process_id,
- target_render_view_id,
+ target_render_frame_id,
page_request_id,
security_origin,
user_gesture,
@@ -283,17 +297,10 @@ class MediaStreamManager::DeviceRequest {
if (!ui_request_)
return;
- // If we appended a device_id scheme, we want to remove it when notifying
- // observers which may be in different modules since this scheme is only
- // used internally within the content module.
- std::string device_id =
- WebContentsCaptureUtil::StripWebContentsDeviceScheme(
- ui_request_->tab_capture_device_id);
-
media_observer->OnMediaRequestStateChanged(
- ui_request_->render_process_id, ui_request_->render_view_id,
+ ui_request_->render_process_id, ui_request_->render_frame_id,
ui_request_->page_request_id, ui_request_->security_origin,
- MediaStreamDevice(stream_type, device_id, device_id), new_state);
+ stream_type, new_state);
}
MediaRequestState state(MediaStreamType stream_type) const {
@@ -309,21 +316,17 @@ class MediaStreamManager::DeviceRequest {
// specifies the target renderer from which audio and video is captured.
const int requesting_process_id;
- // The render view id that requested this stream to be generated and that
+ // The render frame id that requested this stream to be generated and that
// will receive a handle to the MediaStream. This may be different from
- // MediaStreamRequest::render_view_id which in the tab capture case
+ // MediaStreamRequest::render_frame_id which in the tab capture case
// specifies the target renderer from which audio and video is captured.
- const int requesting_view_id;
+ const int requesting_frame_id;
- // An ID the render view provided to identify this request.
+ // An ID the render frame provided to identify this request.
const int page_request_id;
const GURL security_origin;
- // This is used when enumerating devices; if we don't have device access
- // permission, we remove the device label.
- bool have_permission;
-
const bool user_gesture;
const MediaStreamRequestType request_type;
@@ -357,13 +360,25 @@ MediaStreamManager::EnumerationCache::~EnumerationCache() {
MediaStreamManager::MediaStreamManager()
: audio_manager_(NULL),
+#if defined(OS_WIN)
+ video_capture_thread_("VideoCaptureThread"),
+#endif
monitoring_started_(false),
+#if defined(OS_CHROMEOS)
+ has_checked_keyboard_mic_(false),
+#endif
io_loop_(NULL),
use_fake_ui_(false) {}
MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
: audio_manager_(audio_manager),
+#if defined(OS_WIN)
+ video_capture_thread_("VideoCaptureThread"),
+#endif
monitoring_started_(false),
+#if defined(OS_CHROMEOS)
+ has_checked_keyboard_mic_(false),
+#endif
io_loop_(NULL),
use_fake_ui_(false) {
DCHECK(audio_manager_);
@@ -391,7 +406,7 @@ MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
MediaStreamManager::~MediaStreamManager() {
DVLOG(1) << "~MediaStreamManager";
DCHECK(requests_.empty());
- DCHECK(!device_task_runner_);
+ DCHECK(!device_task_runner_.get());
base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
// The PowerMonitor instance owned by BrowserMainLoops always outlives the
@@ -414,7 +429,7 @@ AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
std::string MediaStreamManager::MakeMediaAccessRequest(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const StreamOptions& options,
const GURL& security_origin,
@@ -425,10 +440,9 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
// suggests that this is the wrong design. Can this be refactored?
DeviceRequest* request = new DeviceRequest(NULL,
render_process_id,
- render_view_id,
+ render_frame_id,
page_request_id,
security_origin,
- true,
false, // user gesture
MEDIA_DEVICE_ACCESS,
options,
@@ -451,7 +465,7 @@ std::string MediaStreamManager::MakeMediaAccessRequest(
void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const ResourceContext::SaltCallback& sc,
int page_request_id,
const StreamOptions& options,
@@ -466,10 +480,9 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
DeviceRequest* request = new DeviceRequest(requester,
render_process_id,
- render_view_id,
+ render_frame_id,
page_request_id,
security_origin,
- true,
user_gesture,
MEDIA_GENERATE_STREAM,
options,
@@ -489,13 +502,13 @@ void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
}
void MediaStreamManager::CancelRequest(int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id) {
for (DeviceRequests::const_iterator request_it = requests_.begin();
request_it != requests_.end(); ++request_it) {
const DeviceRequest* request = request_it->second;
if (request->requesting_process_id == render_process_id &&
- request->requesting_view_id == render_view_id &&
+ request->requesting_frame_id == render_frame_id &&
request->page_request_id == page_request_id) {
CancelRequest(request_it->first);
return;
@@ -557,19 +570,19 @@ void MediaStreamManager::CancelAllRequests(int render_process_id) {
}
void MediaStreamManager::StopStreamDevice(int render_process_id,
- int render_view_id,
+ int render_frame_id,
const std::string& device_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} "
+ DVLOG(1) << "StopStreamDevice({render_frame_id = " << render_frame_id << "} "
<< ", {device_id = " << device_id << "})";
- // Find the first request for this |render_process_id| and |render_view_id|
+ // Find the first request for this |render_process_id| and |render_frame_id|
// of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and
// stop it.
for (DeviceRequests::iterator request_it = requests_.begin();
- request_it != requests_.end(); ++request_it) {
+ request_it != requests_.end(); ++request_it) {
DeviceRequest* request = request_it->second;
if (request->requesting_process_id != render_process_id ||
- request->requesting_view_id != render_view_id ||
+ request->requesting_frame_id != render_frame_id ||
request->request_type != MEDIA_GENERATE_STREAM) {
continue;
}
@@ -648,12 +661,11 @@ void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
std::string MediaStreamManager::EnumerateDevices(
MediaStreamRequester* requester,
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const ResourceContext::SaltCallback& sc,
int page_request_id,
MediaStreamType type,
- const GURL& security_origin,
- bool have_permission) {
+ const GURL& security_origin) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(requester);
DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
@@ -662,10 +674,9 @@ std::string MediaStreamManager::EnumerateDevices(
DeviceRequest* request = new DeviceRequest(requester,
render_process_id,
- render_view_id,
+ render_frame_id,
page_request_id,
security_origin,
- have_permission,
false, // user gesture
MEDIA_ENUMERATE_DEVICES,
StreamOptions(),
@@ -733,8 +744,7 @@ void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
DVLOG(1) << "Enumerate Devices ({label = " << label << "})";
}
-void MediaStreamManager::EnumerateAudioOutputDevices(
- const std::string& label) {
+void MediaStreamManager::EnumerateAudioOutputDevices(const std::string& label) {
DCHECK(device_task_runner_->BelongsToCurrentThread());
scoped_ptr<media::AudioDeviceNames> device_names(
@@ -786,7 +796,7 @@ void MediaStreamManager::AudioOutputDevicesEnumerated(
void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const ResourceContext::SaltCallback& sc,
int page_request_id,
const std::string& device_id,
@@ -810,10 +820,9 @@ void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
}
DeviceRequest* request = new DeviceRequest(requester,
render_process_id,
- render_view_id,
+ render_frame_id,
page_request_id,
security_origin,
- true,
false, // user gesture
MEDIA_OPEN_DEVICE,
options,
@@ -910,7 +919,7 @@ void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
session_ids.push_back(device_it->session_id);
if (it->second->requester) {
it->second->requester->DeviceStopped(
- it->second->requesting_view_id,
+ it->second->requesting_frame_id,
it->first,
*device_it);
}
@@ -1081,7 +1090,7 @@ void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
// Start enumeration for devices of all requested device types.
const MediaStreamType streams[] = { request->audio_type(),
request->video_type() };
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(streams); ++i) {
+ for (size_t i = 0; i < arraysize(streams); ++i) {
if (streams[i] == MEDIA_NO_SERVICE)
continue;
request->SetState(streams[i], MEDIA_REQUEST_STATE_REQUESTED);
@@ -1220,6 +1229,10 @@ void MediaStreamManager::SetupRequest(const std::string& label) {
return;
}
+#if defined(OS_CHROMEOS)
+ EnsureKeyboardMicChecked();
+#endif
+
if (!is_web_contents_capture && !is_screen_capture) {
if (EnumerationRequired(&audio_enumeration_cache_, audio_type) ||
EnumerationRequired(&video_enumeration_cache_, video_type)) {
@@ -1295,17 +1308,10 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
// Customize options for a WebContents based capture.
int target_render_process_id = 0;
- int target_render_view_id = 0;
-
- // TODO(justinlin): Can't plumb audio mirroring using stream type right
- // now, so plumbing by device_id. Will revisit once it's refactored.
- // http://crbug.com/163100
- std::string tab_capture_device_id =
- WebContentsCaptureUtil::AppendWebContentsDeviceScheme(capture_device_id);
+ int target_render_frame_id = 0;
bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
- tab_capture_device_id, &target_render_process_id,
- &target_render_view_id);
+ capture_device_id, &target_render_process_id, &target_render_frame_id);
if (!has_valid_device_id ||
(request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
request->audio_type() != MEDIA_NO_SERVICE) ||
@@ -1314,15 +1320,15 @@ bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
return false;
}
- request->CreateTabCatureUIRequest(target_render_process_id,
- target_render_view_id,
- tab_capture_device_id);
+ request->CreateTabCaptureUIRequest(target_render_process_id,
+ target_render_frame_id,
+ capture_device_id);
DVLOG(3) << "SetupTabCaptureRequest "
- << ", {tab_capture_device_id = " << tab_capture_device_id << "}"
+ << ", {capture_device_id = " << capture_device_id << "}"
<< ", {target_render_process_id = " << target_render_process_id
<< "}"
- << ", {target_render_view_id = " << target_render_view_id << "}";
+ << ", {target_render_frame_id = " << target_render_frame_id << "}";
return true;
}
@@ -1394,15 +1400,19 @@ bool MediaStreamManager::FindExistingRequestedDeviceInfo(
it != requests_.end() ; ++it) {
const DeviceRequest* request = it->second;
if (request->requesting_process_id == new_request.requesting_process_id &&
- request->requesting_view_id == new_request.requesting_view_id &&
+ request->requesting_frame_id == new_request.requesting_frame_id &&
request->request_type == new_request.request_type) {
for (StreamDeviceInfoArray::const_iterator device_it =
request->devices.begin();
device_it != request->devices.end(); ++device_it) {
if (device_it->device.id == source_id &&
device_it->device.type == new_device_info.type) {
- *existing_device_info = *device_it;
- *existing_request_state = request->state(device_it->device.type);
+ *existing_device_info = *device_it;
+ // Make sure that the audio |effects| reflect what the request
+ // is set to and not what the capabilities are.
+ FilterAudioEffects(request->options,
+ &existing_device_info->device.input.effects);
+ *existing_request_state = request->state(device_it->device.type);
return true;
}
}
@@ -1431,7 +1441,7 @@ void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
}
request->requester->StreamGenerated(
- request->requesting_view_id,
+ request->requesting_frame_id,
request->page_request_id,
label, audio_devices, video_devices);
}
@@ -1442,7 +1452,7 @@ void MediaStreamManager::FinalizeRequestFailed(
content::MediaStreamRequestResult result) {
if (request->requester)
request->requester->StreamGenerationFailed(
- request->requesting_view_id,
+ request->requesting_frame_id,
request->page_request_id,
result);
@@ -1457,7 +1467,7 @@ void MediaStreamManager::FinalizeRequestFailed(
void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
DeviceRequest* request) {
const StreamDeviceInfoArray& requested_devices = request->devices;
- request->requester->DeviceOpened(request->requesting_view_id,
+ request->requester->DeviceOpened(request->requesting_frame_id,
request->page_request_id,
label, requested_devices.front());
}
@@ -1466,6 +1476,11 @@ void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
DeviceRequest* request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES);
+ DCHECK(((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) &&
+ request->video_type() == MEDIA_NO_SERVICE) ||
+ (request->audio_type() == MEDIA_NO_SERVICE &&
+ request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE));
if (request->security_origin.is_valid()) {
for (StreamDeviceInfoArray::iterator it = request->devices.begin();
@@ -1476,11 +1491,48 @@ void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
request->devices.clear();
}
- if (!request->have_permission)
+ if (use_fake_ui_) {
+ if (!fake_ui_)
+ fake_ui_.reset(new FakeMediaStreamUIProxy());
+ request->ui_proxy = fake_ui_.Pass();
+ } else {
+ request->ui_proxy = MediaStreamUIProxy::Create();
+ }
+
+ // Output label permissions are based on input permission.
+ MediaStreamType type =
+ request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT
+ ? MEDIA_DEVICE_AUDIO_CAPTURE
+ : MEDIA_DEVICE_VIDEO_CAPTURE;
+
+ request->ui_proxy->CheckAccess(
+ request->security_origin,
+ type,
+ request->requesting_process_id,
+ request->requesting_frame_id,
+ base::Bind(&MediaStreamManager::HandleCheckMediaAccessResponse,
+ base::Unretained(this),
+ label));
+}
+
+void MediaStreamManager::HandleCheckMediaAccessResponse(
+ const std::string& label,
+ bool have_access) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ DeviceRequest* request = FindRequest(label);
+ if (!request) {
+ // This can happen if the request was cancelled.
+ DVLOG(1) << "The request with label " << label << " does not exist.";
+ return;
+ }
+
+ if (!have_access)
ClearDeviceLabels(&request->devices);
request->requester->DevicesEnumerated(
- request->requesting_view_id,
+ request->requesting_frame_id,
request->page_request_id,
label,
request->devices);
@@ -1528,7 +1580,7 @@ void MediaStreamManager::FinalizeMediaAccessRequest(
void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (device_task_runner_)
+ if (device_task_runner_.get())
return;
device_task_runner_ = audio_manager_->GetWorkerTaskRunner();
@@ -1549,7 +1601,16 @@ void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
video_capture_manager_ =
new VideoCaptureManager(media::VideoCaptureDeviceFactory::CreateFactory(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)));
+#if defined(OS_WIN)
+ // Use an STA Video Capture Thread to try to avoid crashes on enumeration of
+ // buggy third party Direct Show modules, http://crbug.com/428958.
+ video_capture_thread_.init_com_with_mta(false);
+ CHECK(video_capture_thread_.Start());
+ video_capture_manager_->Register(this,
+ video_capture_thread_.message_loop_proxy());
+#else
video_capture_manager_->Register(this, device_task_runner_);
+#endif
}
void MediaStreamManager::Opened(MediaStreamType stream_type,
@@ -1583,6 +1644,14 @@ void MediaStreamManager::Opened(MediaStreamType stream_type,
audio_input_device_manager_->GetOpenedDeviceInfoById(
device_it->session_id);
device_it->device.input = info->device.input;
+
+ // Since the audio input device manager will set the input
+ // parameters to the default settings (including supported effects),
+ // we need to adjust those settings here according to what the
+ // request asks for.
+ FilterAudioEffects(request->options,
+ &device_it->device.input.effects);
+
device_it->device.matched_output = info->device.matched_output;
}
}
@@ -1817,8 +1886,6 @@ void MediaStreamManager::HandleAccessRequestResponse(
StreamDeviceInfo device_info;
device_info.device = *device_it;
- // TODO(justinlin): Nicer way to do this?
- // Re-append the device's id since we lost it when posting request to UI.
if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
device_info.device.id = request->UIRequest()->tab_capture_device_id;
@@ -1847,7 +1914,7 @@ void MediaStreamManager::HandleAccessRequestResponse(
}
// If this is request for a new MediaStream, a device is only opened once
- // per render view. This is so that the permission to use a device can be
+ // per render frame. This is so that the permission to use a device can be
// revoked by a single call to StopStreamDevice regardless of how many
// MediaStreams it is being used in.
if (request->request_type == MEDIA_GENERATE_STREAM) {
@@ -1900,7 +1967,7 @@ void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
if (request->requester) {
for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
device_it != request->devices.end(); ++device_it) {
- request->requester->DeviceStopped(request->requesting_view_id,
+ request->requester->DeviceStopped(request->requesting_frame_id,
label,
*device_it);
}
@@ -1919,7 +1986,7 @@ void MediaStreamManager::WillDestroyCurrentMessageLoop() {
DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
DCHECK_EQ(base::MessageLoop::current(), io_loop_);
DCHECK(requests_.empty());
- if (device_task_runner_) {
+ if (device_task_runner_.get()) {
StopMonitoring();
video_capture_manager_->Unregister();
@@ -2038,4 +2105,36 @@ void MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
}
}
+#if defined(OS_CHROMEOS)
+void MediaStreamManager::EnsureKeyboardMicChecked() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!has_checked_keyboard_mic_) {
+ has_checked_keyboard_mic_ = true;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&MediaStreamManager::CheckKeyboardMicOnUIThread,
+ base::Unretained(this)));
+ }
+}
+
+void MediaStreamManager::CheckKeyboardMicOnUIThread() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // We will post this on the device thread before the media media access
+ // request is posted on the UI thread, so setting the keyboard mic info will
+ // be done before any stream is created.
+ if (chromeos::CrasAudioHandler::Get()->HasKeyboardMic()) {
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaStreamManager::SetKeyboardMicOnDeviceThread,
+ base::Unretained(this)));
+ }
+}
+
+void MediaStreamManager::SetKeyboardMicOnDeviceThread() {
+ DCHECK(device_task_runner_->BelongsToCurrentThread());
+ audio_manager_->SetHasKeyboardMic();
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.h b/chromium/content/browser/renderer_host/media/media_stream_manager.h
index 1de659c3937..9499e32f257 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -37,6 +37,7 @@
#include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_observer.h"
#include "base/system_monitor/system_monitor.h"
+#include "base/threading/thread.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
@@ -50,6 +51,7 @@ class AudioManager;
namespace content {
class AudioInputDeviceManager;
+class BrowserContext;
class FakeMediaStreamUIProxy;
class MediaStreamDeviceSettings;
class MediaStreamRequester;
@@ -71,7 +73,7 @@ class CONTENT_EXPORT MediaStreamManager
MediaRequestResponseCallback;
explicit MediaStreamManager(media::AudioManager* audio_manager);
- virtual ~MediaStreamManager();
+ ~MediaStreamManager() override;
// Used to access VideoCaptureManager.
VideoCaptureManager* video_capture_manager();
@@ -81,13 +83,13 @@ class CONTENT_EXPORT MediaStreamManager
// Creates a new media access request which is identified by a unique string
// that's returned to the caller. This will trigger the infobar and ask users
- // for access to the device. |render_process_id| and |render_view_id| refer
- // to the view where the infobar will appear to the user. |callback| is
+ // for access to the device. |render_process_id| and |render_frame_id| are
+ // used to determine where the infobar will appear to the user. |callback| is
// used to send the selected device to the clients. An empty list of device
// will be returned if the users deny the access.
std::string MakeMediaAccessRequest(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const StreamOptions& options,
const GURL& security_origin,
@@ -95,11 +97,11 @@ class CONTENT_EXPORT MediaStreamManager
// GenerateStream opens new media devices according to |components|. It
// creates a new request which is identified by a unique string that's
- // returned to the caller. |render_process_id| and |render_view_id| refer to
- // the view where the infobar will appear to the user.
+ // returned to the caller. |render_process_id| and |render_frame_id| are used
+ // to determine where the infobar will appear to the user.
void GenerateStream(MediaStreamRequester* requester,
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const ResourceContext::SaltCallback& sc,
int page_request_id,
const StreamOptions& components,
@@ -107,7 +109,7 @@ class CONTENT_EXPORT MediaStreamManager
bool user_gesture);
void CancelRequest(int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id);
// Cancel an open request identified by |label|.
@@ -116,10 +118,10 @@ class CONTENT_EXPORT MediaStreamManager
// Cancel all requests for the given |render_process_id|.
void CancelAllRequests(int render_process_id);
- // Closes the stream device for a certain render view. The stream must have
+ // Closes the stream device for a certain render frame. The stream must have
// been opened by a call to GenerateStream.
void StopStreamDevice(int render_process_id,
- int render_view_id,
+ int render_frame_id,
const std::string& device_id);
// Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE
@@ -129,22 +131,20 @@ class CONTENT_EXPORT MediaStreamManager
// and video devices and also start monitoring device changes, such as
// plug/unplug. The new device lists will be delivered via media observer to
// MediaCaptureDevicesDispatcher.
- // If |have_permission| is false, we remove the device label from the result.
virtual std::string EnumerateDevices(MediaStreamRequester* requester,
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const ResourceContext::SaltCallback& sc,
int page_request_id,
MediaStreamType type,
- const GURL& security_origin,
- bool have_permission);
+ const GURL& security_origin);
// Open a device identified by |device_id|. |type| must be either
// MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
// The request is identified using string returned to the caller.
void OpenDevice(MediaStreamRequester* requester,
int render_process_id,
- int render_view_id,
+ int render_frame_id,
const ResourceContext::SaltCallback& sc,
int page_request_id,
const std::string& device_id,
@@ -166,18 +166,14 @@ class CONTENT_EXPORT MediaStreamManager
void EnsureDeviceMonitorStarted();
// Implements MediaStreamProviderListener.
- virtual void Opened(MediaStreamType stream_type,
- int capture_session_id) OVERRIDE;
- virtual void Closed(MediaStreamType stream_type,
- int capture_session_id) OVERRIDE;
- virtual void DevicesEnumerated(MediaStreamType stream_type,
- const StreamDeviceInfoArray& devices) OVERRIDE;
- virtual void Aborted(MediaStreamType stream_type,
- int capture_session_id) OVERRIDE;
+ void Opened(MediaStreamType stream_type, int capture_session_id) override;
+ void Closed(MediaStreamType stream_type, int capture_session_id) override;
+ void DevicesEnumerated(MediaStreamType stream_type,
+ const StreamDeviceInfoArray& devices) override;
+ void Aborted(MediaStreamType stream_type, int capture_session_id) override;
// Implements base::SystemMonitor::DevicesChangedObserver.
- virtual void OnDevicesChanged(
- base::SystemMonitor::DeviceType device_type) OVERRIDE;
+ void OnDevicesChanged(base::SystemMonitor::DeviceType device_type) override;
// Called by the tests to specify a fake UI that should be used for next
// generated stream (or when using --use-fake-ui-for-media-stream).
@@ -196,7 +192,7 @@ class CONTENT_EXPORT MediaStreamManager
// But for some tests which use TestBrowserThreadBundle, we need to call
// WillDestroyCurrentMessageLoop explicitly because the notification happens
// too late. (see http://crbug.com/247525#c14).
- virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
+ void WillDestroyCurrentMessageLoop() override;
// Sends log messages to the render process hosts whose corresponding render
// processes are making device requests, to be used by the
@@ -209,8 +205,8 @@ class CONTENT_EXPORT MediaStreamManager
static void SendMessageToNativeLog(const std::string& message);
// base::PowerObserver overrides.
- virtual void OnSuspend() OVERRIDE;
- virtual void OnResume() OVERRIDE;
+ void OnSuspend() override;
+ void OnResume() override;
protected:
// Used for testing.
@@ -301,7 +297,7 @@ class CONTENT_EXPORT MediaStreamManager
// needed.
void PostRequestToUI(const std::string& label, DeviceRequest* request);
// Returns true if a device with |device_id| has already been requested with
- // a render procecss_id and render_view_id and type equal to the the values
+ // a render procecss_id and render_frame_id and type equal to the the values
// in |request|. If it has been requested, |device_info| contain information
// about the device.
bool FindExistingRequestedDeviceInfo(
@@ -322,6 +318,8 @@ class CONTENT_EXPORT MediaStreamManager
const MediaStreamDevices& devices);
void FinalizeEnumerateDevices(const std::string& label,
DeviceRequest* request);
+ void HandleCheckMediaAccessResponse(const std::string& label,
+ bool have_access);
// This method is called when an audio or video device is plugged in or
// removed. It make sure all MediaStreams that use a removed device is
@@ -362,6 +360,20 @@ class CONTENT_EXPORT MediaStreamManager
StreamDeviceInfoArray devices,
gfx::NativeViewId window_id);
+#if defined(OS_CHROMEOS)
+ // Ensures that we have checked for presence of a keyboard mic. This is only
+ // done once. This function should be called before posting a request on the
+ // UI thread.
+ void EnsureKeyboardMicChecked();
+
+ // Checks if the system has a keyboard mic, and if so, inform the audio
+ // manager via SetKeyboardMicOnDeviceThread().
+ void CheckKeyboardMicOnUIThread();
+
+ // Tells the audio mananger that the system supports a keyboard mic.
+ void SetKeyboardMicOnDeviceThread();
+#endif
+
// Task runner shared by VideoCaptureManager and AudioInputDeviceManager and
// used for enumerating audio output devices.
// Note: Enumeration tasks may take seconds to complete so must never be run
@@ -371,10 +383,21 @@ class CONTENT_EXPORT MediaStreamManager
media::AudioManager* const audio_manager_; // not owned
scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
scoped_refptr<VideoCaptureManager> video_capture_manager_;
+#if defined(OS_WIN)
+ base::Thread video_capture_thread_;
+#endif
// Indicator of device monitoring state.
bool monitoring_started_;
+#if defined(OS_CHROMEOS)
+ // Flag that's set when we have checked if the system has a keyboard mic. We
+ // only need to check it once, and not when constructing since that will
+ // affect startup time.
+ // Must be accessed on the IO thread;
+ bool has_checked_keyboard_mic_;
+#endif
+
// Stores most recently enumerated device lists. The cache is cleared when
// monitoring is stopped or there is no request for that type of device.
EnumerationCache audio_enumeration_cache_;
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index e01b945b815..51ab0a52bfb 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -55,10 +55,10 @@ typedef media::FakeAudioManager AudioManagerPlatform;
class MockAudioManager : public AudioManagerPlatform {
public:
MockAudioManager() : AudioManagerPlatform(&fake_audio_log_factory_) {}
- virtual ~MockAudioManager() {}
+ ~MockAudioManager() override {}
- virtual void GetAudioInputDeviceNames(
- media::AudioDeviceNames* device_names) OVERRIDE {
+ void GetAudioInputDeviceNames(
+ media::AudioDeviceNames* device_names) override {
DCHECK(device_names->empty());
if (HasAudioInputDevices()) {
AudioManagerBase::GetAudioInputDeviceNames(device_names);
@@ -79,7 +79,7 @@ class MediaStreamManagerTest : public ::testing::Test {
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
message_loop_(base::MessageLoopProxy::current()) {
// Create our own MediaStreamManager. Use fake devices to run on the bots.
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kUseFakeDeviceForMediaStream);
audio_manager_.reset(new MockAudioManager());
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
@@ -99,7 +99,7 @@ class MediaStreamManagerTest : public ::testing::Test {
protected:
std::string MakeMediaAccessRequest(int index) {
const int render_process_id = 1;
- const int render_view_id = 1;
+ const int render_frame_id = 1;
const int page_request_id = 1;
const GURL security_origin;
MediaStreamManager::MediaRequestResponseCallback callback =
@@ -107,7 +107,7 @@ class MediaStreamManagerTest : public ::testing::Test {
base::Unretained(this), index);
StreamOptions options(true, true);
return media_stream_manager_->MakeMediaAccessRequest(render_process_id,
- render_view_id,
+ render_frame_id,
page_request_id,
options,
security_origin,
@@ -146,7 +146,7 @@ TEST_F(MediaStreamManagerTest, MakeMultipleRequests) {
// Second request.
int render_process_id = 2;
- int render_view_id = 2;
+ int render_frame_id = 2;
int page_request_id = 2;
GURL security_origin;
StreamOptions options(true, true);
@@ -155,7 +155,7 @@ TEST_F(MediaStreamManagerTest, MakeMultipleRequests) {
base::Unretained(this), 1);
std::string label2 = media_stream_manager_->MakeMediaAccessRequest(
render_process_id,
- render_view_id,
+ render_frame_id,
page_request_id,
options,
security_origin,
diff --git a/chromium/content/browser/renderer_host/media/media_stream_requester.h b/chromium/content/browser/renderer_host/media/media_stream_requester.h
index 337effade97..c36f166670f 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_requester.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_requester.h
@@ -18,29 +18,29 @@ namespace content {
class CONTENT_EXPORT MediaStreamRequester {
public:
// Called as a reply of a successful call to GenerateStream.
- virtual void StreamGenerated(int render_view_id,
+ virtual void StreamGenerated(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices) = 0;
// Called if GenerateStream failed.
virtual void StreamGenerationFailed(
- int render_view_id,
+ int render_frame_id,
int page_request_id,
content::MediaStreamRequestResult result) = 0;
// Called if a device has been stopped by a user from UI or the device
- // has become unavailable. |render_view_id| is the render view that requested
- // the device and |label| is the label of the request|.
- virtual void DeviceStopped(int render_view_id,
+ // has become unavailable. |render_frame_id| is the render frame that
+ // requested the device and |label| is the label of the request.
+ virtual void DeviceStopped(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device) = 0;
// Called as a reply of a successful call to EnumerateDevices.
- virtual void DevicesEnumerated(int render_view_id,
+ virtual void DevicesEnumerated(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& devices) = 0;
// Called as a reply of a successful call to OpenDevice.
- virtual void DeviceOpened(int render_view_id,
+ virtual void DeviceOpened(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& device_info) = 0;
diff --git a/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc b/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
index 9bae1f72839..328d60e28ac 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
@@ -49,13 +49,16 @@ bool MediaStreamTrackMetricsHost::OnMessageReceived(
void MediaStreamTrackMetricsHost::OnAddTrack(uint64 id,
bool is_audio,
bool is_remote) {
- DCHECK(tracks_.find(id) == tracks_.end());
+ if (tracks_.find(id) != tracks_.end())
+ return;
+
TrackInfo info = {is_audio, is_remote, base::TimeTicks::Now()};
tracks_[id] = info;
}
void MediaStreamTrackMetricsHost::OnRemoveTrack(uint64 id) {
- DCHECK(tracks_.find(id) != tracks_.end());
+ if (tracks_.find(id) == tracks_.end())
+ return;
TrackInfo& info = tracks_[id];
ReportDuration(info);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.h b/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.h
index 081b0d51137..35235dba611 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_track_metrics_host.h
@@ -31,10 +31,10 @@ class MediaStreamTrackMetricsHost
explicit MediaStreamTrackMetricsHost();
protected:
- virtual ~MediaStreamTrackMetricsHost();
+ ~MediaStreamTrackMetricsHost() override;
// BrowserMessageFilter override.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
void OnAddTrack(uint64 id, bool is_audio, bool is_remote);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
index 048b078c2bf..990471f94bc 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
@@ -30,7 +30,7 @@ class MediaStreamDeviceUIControllerTest
const std::string&, const StreamDeviceInfoArray&));
MOCK_METHOD1(SettingsError, void(const std::string&));
MOCK_METHOD1(StopStreamFromUI, void(const std::string&));
- void GetAvailableDevices(MediaStreamDevices* devices) OVERRIDE {
+ void GetAvailableDevices(MediaStreamDevices* devices) override {
devices->push_back(MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE,
"mic",
"mic_id",
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 1c924241aa3..d6d827540a6 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -5,8 +5,8 @@
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "base/command_line.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "media/video/capture/fake_video_capture_device.h"
@@ -16,10 +16,14 @@ namespace content {
class MediaStreamUIProxy::Core {
public:
explicit Core(const base::WeakPtr<MediaStreamUIProxy>& proxy,
- RenderViewHostDelegate* test_render_delegate);
+ RenderFrameHostDelegate* test_render_delegate);
~Core();
void RequestAccess(const MediaStreamRequest& request);
+ bool CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int process_id,
+ int frame_id);
void OnStarted(gfx::NativeViewId* window_id);
private:
@@ -27,11 +31,13 @@ class MediaStreamUIProxy::Core {
content::MediaStreamRequestResult result,
scoped_ptr<MediaStreamUI> stream_ui);
void ProcessStopRequestFromUI();
+ RenderFrameHostDelegate* GetRenderFrameHostDelegate(int render_process_id,
+ int render_frame_id);
base::WeakPtr<MediaStreamUIProxy> proxy_;
scoped_ptr<MediaStreamUI> ui_;
- RenderViewHostDelegate* const test_render_delegate_;
+ RenderFrameHostDelegate* const test_render_delegate_;
// WeakPtr<> is used to RequestMediaAccessPermission() because there is no way
// cancel media requests.
@@ -41,7 +47,7 @@ class MediaStreamUIProxy::Core {
};
MediaStreamUIProxy::Core::Core(const base::WeakPtr<MediaStreamUIProxy>& proxy,
- RenderViewHostDelegate* test_render_delegate)
+ RenderFrameHostDelegate* test_render_delegate)
: proxy_(proxy),
test_render_delegate_(test_render_delegate),
weak_factory_(this) {
@@ -55,24 +61,15 @@ void MediaStreamUIProxy::Core::RequestAccess(
const MediaStreamRequest& request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderViewHostDelegate* render_delegate;
-
- if (test_render_delegate_) {
- render_delegate = test_render_delegate_;
- } else {
- RenderViewHostImpl* host = RenderViewHostImpl::FromID(
- request.render_process_id, request.render_view_id);
-
- // Tab may have gone away.
- if (!host || !host->GetDelegate()) {
- ProcessAccessRequestResponse(
- MediaStreamDevices(),
- MEDIA_DEVICE_INVALID_STATE,
- scoped_ptr<MediaStreamUI>());
- return;
- }
+ RenderFrameHostDelegate* render_delegate = GetRenderFrameHostDelegate(
+ request.render_process_id, request.render_frame_id);
- render_delegate = host->GetDelegate();
+ // Tab may have gone away, or has no delegate from which to request access.
+ if (!render_delegate) {
+ ProcessAccessRequestResponse(MediaStreamDevices(),
+ MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
+ scoped_ptr<MediaStreamUI>());
+ return;
}
render_delegate->RequestMediaAccessPermission(
@@ -80,6 +77,20 @@ void MediaStreamUIProxy::Core::RequestAccess(
weak_factory_.GetWeakPtr()));
}
+bool MediaStreamUIProxy::Core::CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderFrameHostDelegate* render_delegate =
+ GetRenderFrameHostDelegate(render_process_id, render_frame_id);
+ if (!render_delegate)
+ return false;
+
+ return render_delegate->CheckMediaAccessPermission(security_origin, type);
+}
+
void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId* window_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (ui_) {
@@ -109,6 +120,16 @@ void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
base::Bind(&MediaStreamUIProxy::ProcessStopRequestFromUI, proxy_));
}
+RenderFrameHostDelegate* MediaStreamUIProxy::Core::GetRenderFrameHostDelegate(
+ int render_process_id,
+ int render_frame_id) {
+ if (test_render_delegate_)
+ return test_render_delegate_;
+ RenderFrameHostImpl* host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ return host ? host->delegate() : NULL;
+}
+
// static
scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() {
return scoped_ptr<MediaStreamUIProxy>(new MediaStreamUIProxy(NULL));
@@ -116,13 +137,13 @@ scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() {
// static
scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::CreateForTests(
- RenderViewHostDelegate* render_delegate) {
+ RenderFrameHostDelegate* render_delegate) {
return scoped_ptr<MediaStreamUIProxy>(
new MediaStreamUIProxy(render_delegate));
}
MediaStreamUIProxy::MediaStreamUIProxy(
- RenderViewHostDelegate* test_render_delegate)
+ RenderFrameHostDelegate* test_render_delegate)
: weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
core_.reset(new Core(weak_factory_.GetWeakPtr(), test_render_delegate));
@@ -130,7 +151,6 @@ MediaStreamUIProxy::MediaStreamUIProxy(
MediaStreamUIProxy::~MediaStreamUIProxy() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, core_.release());
}
void MediaStreamUIProxy::RequestAccess(
@@ -144,6 +164,28 @@ void MediaStreamUIProxy::RequestAccess(
base::Bind(&Core::RequestAccess, base::Unretained(core_.get()), request));
}
+void MediaStreamUIProxy::CheckAccess(
+ const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&Core::CheckAccess,
+ base::Unretained(core_.get()),
+ security_origin,
+ type,
+ render_process_id,
+ render_frame_id),
+ base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback,
const WindowIdCallback& window_id_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -163,13 +205,6 @@ void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback,
base::Owned(window_id)));
}
-void MediaStreamUIProxy::OnWindowId(const WindowIdCallback& window_id_callback,
- gfx::NativeViewId* window_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!window_id_callback.is_null())
- window_id_callback.Run(*window_id);
-}
-
void MediaStreamUIProxy::ProcessAccessRequestResponse(
const MediaStreamDevices& devices,
content::MediaStreamRequestResult result) {
@@ -190,8 +225,25 @@ void MediaStreamUIProxy::ProcessStopRequestFromUI() {
cb.Run();
}
+void MediaStreamUIProxy::OnWindowId(const WindowIdCallback& window_id_callback,
+ gfx::NativeViewId* window_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!window_id_callback.is_null())
+ window_id_callback.Run(*window_id);
+}
+
+void MediaStreamUIProxy::OnCheckedAccess(
+ const base::Callback<void(bool)>& callback,
+ bool have_access) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!callback.is_null())
+ callback.Run(have_access);
+}
+
FakeMediaStreamUIProxy::FakeMediaStreamUIProxy()
- : MediaStreamUIProxy(NULL) {
+ : MediaStreamUIProxy(NULL),
+ mic_access_(true),
+ camera_access_(true) {
}
FakeMediaStreamUIProxy::~FakeMediaStreamUIProxy() {}
@@ -201,6 +253,14 @@ void FakeMediaStreamUIProxy::SetAvailableDevices(
devices_ = devices;
}
+void FakeMediaStreamUIProxy::SetMicAccess(bool access) {
+ mic_access_ = access;
+}
+
+void FakeMediaStreamUIProxy::SetCameraAccess(bool access) {
+ camera_access_ = access;
+}
+
void FakeMediaStreamUIProxy::RequestAccess(
const MediaStreamRequest& request,
const ResponseCallback& response_callback) {
@@ -245,7 +305,7 @@ void FakeMediaStreamUIProxy::RequestAccess(
}
}
- // Fail the request if a device exist for the requested type.
+ // Fail the request if a device doesn't exist for the requested type.
if ((request.audio_type != MEDIA_NO_SERVICE && !accepted_audio) ||
(request.video_type != MEDIA_NO_SERVICE && !accepted_video)) {
devices_to_use.clear();
@@ -261,6 +321,33 @@ void FakeMediaStreamUIProxy::RequestAccess(
MEDIA_DEVICE_OK));
}
+void FakeMediaStreamUIProxy::CheckAccess(
+ const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+
+ bool have_access = false;
+ if (CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kUseFakeUIForMediaStream) != "deny") {
+ have_access =
+ type == MEDIA_DEVICE_AUDIO_CAPTURE ? mic_access_ : camera_access_;
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&MediaStreamUIProxy::OnCheckedAccess,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ have_access));
+ return;
+}
+
void FakeMediaStreamUIProxy::OnStarted(
const base::Closure& stop_callback,
const WindowIdCallback& window_id_callback) {}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h
index 01be16676cd..23fc592e62b 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h
@@ -9,15 +9,16 @@
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/common/media_stream_request.h"
namespace content {
-class RenderViewHostDelegate;
+class RenderFrameHostDelegate;
// MediaStreamUIProxy proxies calls to media stream UI between IO thread and UI
// thread. One instance of this class is create per MediaStream object. It must
-// be create, used and destroyed on IO thread.
+// be created, used and destroyed on IO thread.
class CONTENT_EXPORT MediaStreamUIProxy {
public:
typedef base::Callback<
@@ -29,7 +30,7 @@ class CONTENT_EXPORT MediaStreamUIProxy {
static scoped_ptr<MediaStreamUIProxy> Create();
static scoped_ptr<MediaStreamUIProxy> CreateForTests(
- RenderViewHostDelegate* render_delegate);
+ RenderFrameHostDelegate* render_delegate);
virtual ~MediaStreamUIProxy();
@@ -40,6 +41,16 @@ class CONTENT_EXPORT MediaStreamUIProxy {
virtual void RequestAccess(const MediaStreamRequest& request,
const ResponseCallback& response_callback);
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user, it checks any stored settings such as policy
+ // or extension permissions. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual void CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback);
+
// Notifies the UI that the MediaStream has been started. Must be called after
// access has been approved using RequestAccess(). |stop_callback| is be
// called on the IO thread after the user has requests the stream to be
@@ -48,10 +59,10 @@ class CONTENT_EXPORT MediaStreamUIProxy {
virtual void OnStarted(const base::Closure& stop_callback,
const WindowIdCallback& window_id_callback);
- void SetRenderViewHostDelegateForTests(RenderViewHostDelegate* delegate);
+ void SetRenderFrameHostDelegateForTests(RenderFrameHostDelegate* delegate);
protected:
- MediaStreamUIProxy(RenderViewHostDelegate* test_render_delegate);
+ explicit MediaStreamUIProxy(RenderFrameHostDelegate* test_render_delegate);
private:
class Core;
@@ -64,8 +75,10 @@ class CONTENT_EXPORT MediaStreamUIProxy {
void ProcessStopRequestFromUI();
void OnWindowId(const WindowIdCallback& window_id_callback,
gfx::NativeViewId* window_id);
+ void OnCheckedAccess(const base::Callback<void(bool)>& callback,
+ bool have_access);
- scoped_ptr<Core> core_;
+ scoped_ptr<Core, content::BrowserThread::DeleteOnUIThread> core_;
ResponseCallback response_callback_;
base::Closure stop_callback_;
@@ -77,20 +90,31 @@ class CONTENT_EXPORT MediaStreamUIProxy {
class CONTENT_EXPORT FakeMediaStreamUIProxy : public MediaStreamUIProxy {
public:
explicit FakeMediaStreamUIProxy();
- virtual ~FakeMediaStreamUIProxy();
+ ~FakeMediaStreamUIProxy() override;
void SetAvailableDevices(const MediaStreamDevices& devices);
+ void SetMicAccess(bool access);
+ void SetCameraAccess(bool access);
// MediaStreamUIProxy overrides.
- virtual void RequestAccess(
- const MediaStreamRequest& request,
- const ResponseCallback& response_callback) OVERRIDE;
- virtual void OnStarted(const base::Closure& stop_callback,
- const WindowIdCallback& window_id_callback) OVERRIDE;
+ void RequestAccess(const MediaStreamRequest& request,
+ const ResponseCallback& response_callback) override;
+ void CheckAccess(const GURL& security_origin,
+ MediaStreamType type,
+ int render_process_id,
+ int render_frame_id,
+ const base::Callback<void(bool)>& callback) override;
+ void OnStarted(const base::Closure& stop_callback,
+ const WindowIdCallback& window_id_callback) override;
private:
+ // This is used for RequestAccess().
MediaStreamDevices devices_;
+ // These are used for CheckAccess().
+ bool mic_access_;
+ bool camera_access_;
+
DISALLOW_COPY_AND_ASSIGN(FakeMediaStreamUIProxy);
};
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 4529b4999d9..4eb7546e651 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -5,7 +5,7 @@
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
#include "base/message_loop/message_loop.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -19,22 +19,14 @@ using testing::SaveArg;
namespace content {
namespace {
-class MockRenderViewHostDelegate : public RenderViewHostDelegate {
+class MockRenderFrameHostDelegate : public RenderFrameHostDelegate {
public:
MOCK_METHOD2(RequestMediaAccessPermission,
void(const MediaStreamRequest& request,
const MediaResponseCallback& callback));
-
- // Stubs for pure virtual methods we don't care about.
- virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE {
- NOTREACHED();
- return gfx::Rect();
- }
- virtual RendererPreferences GetRendererPrefs(
- BrowserContext* browser_context) const OVERRIDE {
- NOTREACHED();
- return RendererPreferences();
- }
+ MOCK_METHOD2(CheckMediaAccessPermission,
+ bool(const GURL& security_origin,
+ MediaStreamType type));
};
class MockResponseCallback {
@@ -42,6 +34,7 @@ class MockResponseCallback {
MOCK_METHOD2(OnAccessRequestResponse,
void(const MediaStreamDevices& devices,
content::MediaStreamRequestResult result));
+ MOCK_METHOD1(OnCheckResponse, void(bool have_access));
};
class MockMediaStreamUI : public MediaStreamUI {
@@ -66,7 +59,7 @@ class MediaStreamUIProxyTest : public testing::Test {
proxy_ = MediaStreamUIProxy::CreateForTests(&delegate_);
}
- virtual ~MediaStreamUIProxyTest() {
+ ~MediaStreamUIProxyTest() override {
proxy_.reset();
message_loop_.RunUntilIdle();
}
@@ -76,7 +69,7 @@ class MediaStreamUIProxyTest : public testing::Test {
TestBrowserThread ui_thread_;
TestBrowserThread io_thread_;
- MockRenderViewHostDelegate delegate_;
+ MockRenderFrameHostDelegate delegate_;
MockResponseCallback response_callback_;
scoped_ptr<MediaStreamUIProxy> proxy_;
};
@@ -84,7 +77,7 @@ class MediaStreamUIProxyTest : public testing::Test {
MATCHER_P(SameRequest, expected, "") {
return
expected.render_process_id == arg.render_process_id &&
- expected.render_view_id == arg.render_view_id &&
+ expected.render_frame_id == arg.render_frame_id &&
expected.tab_capture_device_id == arg.tab_capture_device_id &&
expected.security_origin == arg.security_origin &&
expected.request_type == arg.request_type &&
@@ -140,7 +133,7 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic"));
scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(0));
- callback.Run(devices, MEDIA_DEVICE_OK, ui.PassAs<MediaStreamUI>());
+ callback.Run(devices, MEDIA_DEVICE_OK, ui.Pass());
MediaStreamDevices response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
@@ -199,7 +192,7 @@ TEST_F(MediaStreamUIProxyTest, StopFromUI) {
scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_))
.WillOnce(testing::DoAll(SaveArg<0>(&stop_callback), Return(0)));
- callback.Run(devices, MEDIA_DEVICE_OK, ui.PassAs<MediaStreamUI>());
+ callback.Run(devices, MEDIA_DEVICE_OK, ui.Pass());
MediaStreamDevices response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
@@ -244,8 +237,7 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(kWindowId));
- callback.Run(
- MediaStreamDevices(), MEDIA_DEVICE_OK, ui.PassAs<MediaStreamUI>());
+ callback.Run(MediaStreamDevices(), MEDIA_DEVICE_OK, ui.Pass());
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _));
MockStopStreamHandler handler;
@@ -258,4 +250,16 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
message_loop_.RunUntilIdle();
}
+TEST_F(MediaStreamUIProxyTest, CheckAccess) {
+ proxy_->CheckAccess(GURL("http://origin/"),
+ MEDIA_DEVICE_AUDIO_CAPTURE,
+ 0,
+ 0,
+ base::Bind(&MockResponseCallback::OnCheckResponse,
+ base::Unretained(&response_callback_)));
+ EXPECT_CALL(delegate_, CheckMediaAccessPermission(_, _));
+ EXPECT_CALL(response_callback_, OnCheckResponse(_));
+ message_loop_.RunUntilIdle();
+}
+
} // content
diff --git a/chromium/content/browser/renderer_host/media/mock_media_observer.h b/chromium/content/browser/renderer_host/media/mock_media_observer.h
index 04678c9235a..ae4e7e61f28 100644
--- a/chromium/content/browser/renderer_host/media/mock_media_observer.h
+++ b/chromium/content/browser/renderer_host/media/mock_media_observer.h
@@ -21,9 +21,9 @@ class MockMediaObserver : public MediaObserver {
virtual ~MockMediaObserver();
MOCK_METHOD6(OnMediaRequestStateChanged,
- void(int render_process_id, int render_view_id,
+ void(int render_process_id, int render_frame_id,
int page_request_id, const GURL& security_origin,
- const MediaStreamDevice& device,
+ MediaStreamType stream_type,
const MediaRequestState state));
};
diff --git a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
index a5e0ba3fb0a..cae185d6598 100644
--- a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
+++ b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -3,14 +3,17 @@
// found in the LICENSE file.
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
+#include "base/power_monitor/power_monitor.h"
#include "content/browser/media/webrtc_internals.h"
#include "content/common/media/peer_connection_tracker_messages.h"
+#include "content/public/browser/render_process_host.h"
namespace content {
PeerConnectionTrackerHost::PeerConnectionTrackerHost(int render_process_id)
: BrowserMessageFilter(PeerConnectionTrackerMsgStart),
- render_process_id_(render_process_id) {}
+ render_process_id_(render_process_id) {
+}
bool PeerConnectionTrackerHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
@@ -38,6 +41,27 @@ void PeerConnectionTrackerHost::OverrideThreadForMessage(
PeerConnectionTrackerHost::~PeerConnectionTrackerHost() {
}
+void PeerConnectionTrackerHost::OnChannelConnected(int32 peer_pid) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Add PowerMonitor when connected to channel rather than in constructor due
+ // to thread safety concerns. Observers of PowerMonitor must be added and
+ // removed on the same thread. BrowserMessageFilter is created on the UI
+ // thread but can be destructed on the UI or IO thread because they are
+ // referenced by RenderProcessHostImpl on the UI thread and ChannelProxy on
+ // the IO thread. Using OnChannelConnected and OnChannelClosing guarantees
+ // execution on the IO thread.
+ base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+ if (power_monitor)
+ power_monitor->AddObserver(this);
+}
+
+void PeerConnectionTrackerHost::OnChannelClosing() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+ if (power_monitor)
+ power_monitor->RemoveObserver(this);
+}
+
void PeerConnectionTrackerHost::OnAddPeerConnection(
const PeerConnectionInfo& info) {
WebRTCInternals::GetInstance()->OnAddPeerConnection(
@@ -45,7 +69,7 @@ void PeerConnectionTrackerHost::OnAddPeerConnection(
peer_pid(),
info.lid,
info.url,
- info.servers,
+ info.rtc_configuration,
info.constraints);
}
@@ -82,4 +106,17 @@ void PeerConnectionTrackerHost::OnGetUserMedia(
video_constraints);
}
+void PeerConnectionTrackerHost::OnSuspend() {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&PeerConnectionTrackerHost::SendOnSuspendOnUIThread, this));
+}
+
+void PeerConnectionTrackerHost::SendOnSuspendOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id_);
+ if (host)
+ host->Send(new PeerConnectionTracker_OnSuspend());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.h b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.h
index 6a411e8ba00..0d7b506a047 100644
--- a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.h
+++ b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_PEER_CONNECTION_TRACKER_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_PEER_CONNECTION_TRACKER_HOST_H_
+#include "base/power_monitor/power_observer.h"
#include "content/public/browser/browser_message_filter.h"
struct PeerConnectionInfo;
@@ -16,19 +17,26 @@ class ListValue;
namespace content {
// This class is the host for PeerConnectionTracker in the browser process
-// managed by RenderProcessHostImpl. It passes IPC messages between
-// WebRTCInternals and PeerConnectionTracker.
-class PeerConnectionTrackerHost : public BrowserMessageFilter {
+// managed by RenderProcessHostImpl. It receives PeerConnection events from
+// PeerConnectionTracker as IPC messages that it forwards to WebRTCInternals.
+// It also forwards browser process events to PeerConnectionTracker via IPC.
+class PeerConnectionTrackerHost : public BrowserMessageFilter,
+ public base::PowerObserver {
public:
PeerConnectionTrackerHost(int render_process_id);
// content::BrowserMessageFilter override.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OverrideThreadForMessage(const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelClosing() override;
+
+ // base::PowerObserver override.
+ void OnSuspend() override;
protected:
- virtual ~PeerConnectionTrackerHost();
+ ~PeerConnectionTrackerHost() override;
private:
// Handlers for peer connection messages coming from the renderer.
@@ -42,6 +50,7 @@ class PeerConnectionTrackerHost : public BrowserMessageFilter {
bool video,
const std::string& audio_constraints,
const std::string& video_constraints);
+ void SendOnSuspendOnUIThread();
int render_process_id_;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index 92523756eff..f583a94adaa 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
@@ -19,6 +19,7 @@ const int VideoCaptureBufferPool::kInvalidId = -1;
VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
: count_(count),
next_buffer_id_(0) {
+ DCHECK_GT(count, 0);
}
VideoCaptureBufferPool::~VideoCaptureBufferPool() {
@@ -168,4 +169,3 @@ VideoCaptureBufferPool::Buffer* VideoCaptureBufferPool::GetBuffer(
}
} // namespace content
-
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.cc b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
index 4775a77c061..c0b462bce26 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -12,8 +12,10 @@
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/common/gpu/client/gl_helper.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/video_frame.h"
@@ -21,6 +23,12 @@
#include "media/base/yuv_convert.h"
#include "third_party/libyuv/include/libyuv.h"
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/image_transport_factory_android.h"
+#else
+#include "content/browser/compositor/image_transport_factory.h"
+#endif
+
using media::VideoCaptureFormat;
namespace content {
@@ -34,9 +42,6 @@ static const int kInfiniteRatio = 99999;
name, \
(height) ? ((width) * 100) / (height) : kInfiniteRatio);
-// The number of buffers that VideoCaptureBufferPool should allocate.
-const int kNoOfBuffers = 3;
-
class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
public:
PoolBuffer(const scoped_refptr<VideoCaptureBufferPool>& pool,
@@ -44,15 +49,45 @@ class PoolBuffer : public media::VideoCaptureDevice::Client::Buffer {
void* data,
size_t size)
: Buffer(buffer_id, data, size), pool_(pool) {
- DCHECK(pool_);
+ DCHECK(pool_.get());
}
private:
- virtual ~PoolBuffer() { pool_->RelinquishProducerReservation(id()); }
+ ~PoolBuffer() override { pool_->RelinquishProducerReservation(id()); }
const scoped_refptr<VideoCaptureBufferPool> pool_;
};
+class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
+ public:
+ explicit SyncPointClientImpl(GLHelper* gl_helper) : gl_helper_(gl_helper) {}
+ ~SyncPointClientImpl() override {}
+ uint32 InsertSyncPoint() override { return gl_helper_->InsertSyncPoint(); }
+ void WaitSyncPoint(uint32 sync_point) override {
+ gl_helper_->WaitSyncPoint(sync_point);
+ }
+
+ private:
+ GLHelper* gl_helper_;
+};
+
+void ReturnVideoFrame(const scoped_refptr<media::VideoFrame>& video_frame,
+ uint32 sync_point) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+#if defined(OS_ANDROID)
+ GLHelper* gl_helper =
+ ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
+#else
+ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+#endif
+ DCHECK(gl_helper);
+ // UpdateReleaseSyncPoint() creates a new sync_point using |gl_helper|, so
+ // wait the given |sync_point| using |gl_helper|.
+ gl_helper->WaitSyncPoint(sync_point);
+ SyncPointClientImpl client(gl_helper);
+ video_frame->UpdateReleaseSyncPoint(&client);
+}
+
} // anonymous namespace
struct VideoCaptureController::ControllerClient {
@@ -66,7 +101,8 @@ struct VideoCaptureController::ControllerClient {
render_process_handle(render_process),
session_id(session_id),
parameters(params),
- session_closed(false) {}
+ session_closed(false),
+ paused(false) {}
~ControllerClient() {}
@@ -98,6 +134,10 @@ struct VideoCaptureController::ControllerClient {
// implicitly), we could avoid tracking this state here in the Controller, and
// simplify the code in both places.
bool session_closed;
+
+ // Indicates whether the client is paused, if true, VideoCaptureController
+ // stops updating its buffer.
+ bool paused;
};
// Receives events from the VideoCaptureDevice and posts them to a
@@ -114,24 +154,23 @@ class VideoCaptureController::VideoCaptureDeviceClient
explicit VideoCaptureDeviceClient(
const base::WeakPtr<VideoCaptureController>& controller,
const scoped_refptr<VideoCaptureBufferPool>& buffer_pool);
- virtual ~VideoCaptureDeviceClient();
+ ~VideoCaptureDeviceClient() override;
// VideoCaptureDevice::Client implementation.
- virtual scoped_refptr<Buffer> ReserveOutputBuffer(
- media::VideoFrame::Format format,
- const gfx::Size& size) OVERRIDE;
- virtual void OnIncomingCapturedData(const uint8* data,
- int length,
- const VideoCaptureFormat& frame_format,
- int rotation,
- base::TimeTicks timestamp) OVERRIDE;
- virtual void OnIncomingCapturedVideoFrame(
+ scoped_refptr<Buffer> ReserveOutputBuffer(media::VideoFrame::Format format,
+ const gfx::Size& size) override;
+ void OnIncomingCapturedData(const uint8* data,
+ int length,
+ const VideoCaptureFormat& frame_format,
+ int rotation,
+ base::TimeTicks timestamp) override;
+ void OnIncomingCapturedVideoFrame(
const scoped_refptr<Buffer>& buffer,
const VideoCaptureFormat& buffer_format,
const scoped_refptr<media::VideoFrame>& frame,
- base::TimeTicks timestamp) OVERRIDE;
- virtual void OnError(const std::string& reason) OVERRIDE;
- virtual void OnLog(const std::string& message) OVERRIDE;
+ base::TimeTicks timestamp) override;
+ void OnError(const std::string& reason) override;
+ void OnLog(const std::string& message) override;
private:
scoped_refptr<Buffer> DoReserveOutputBuffer(media::VideoFrame::Format format,
@@ -142,20 +181,19 @@ class VideoCaptureController::VideoCaptureDeviceClient
// The pool of shared-memory buffers used for capturing.
const scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
-
- bool first_frame_;
};
-VideoCaptureController::VideoCaptureController()
- : buffer_pool_(new VideoCaptureBufferPool(kNoOfBuffers)),
+VideoCaptureController::VideoCaptureController(int max_buffers)
+ : buffer_pool_(new VideoCaptureBufferPool(max_buffers)),
state_(VIDEO_CAPTURE_STATE_STARTED),
+ has_received_frames_(false),
weak_ptr_factory_(this) {
}
VideoCaptureController::VideoCaptureDeviceClient::VideoCaptureDeviceClient(
const base::WeakPtr<VideoCaptureController>& controller,
const scoped_refptr<VideoCaptureBufferPool>& buffer_pool)
- : controller_(controller), buffer_pool_(buffer_pool), first_frame_(true) {}
+ : controller_(controller), buffer_pool_(buffer_pool) {}
VideoCaptureController::VideoCaptureDeviceClient::~VideoCaptureDeviceClient() {}
@@ -233,6 +271,22 @@ int VideoCaptureController::RemoveClient(
return session_id;
}
+void VideoCaptureController::PauseOrResumeClient(
+ const VideoCaptureControllerID& id,
+ VideoCaptureControllerEventHandler* event_handler,
+ bool pause) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(1) << "VideoCaptureController::PauseOrResumeClient, id "
+ << id.device_id << ", " << pause;
+
+ ControllerClient* client = FindClient(id, event_handler, controller_clients_);
+ if (!client)
+ return;
+
+ DCHECK(client->paused != pause);
+ client->paused = pause;
+}
+
void VideoCaptureController::StopSession(int session_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id;
@@ -249,7 +303,7 @@ void VideoCaptureController::ReturnBuffer(
const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
int buffer_id,
- const std::vector<uint32>& sync_points) {
+ uint32 sync_point) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ControllerClient* client = FindClient(id, event_handler, controller_clients_);
@@ -264,13 +318,12 @@ void VideoCaptureController::ReturnBuffer(
}
scoped_refptr<media::VideoFrame> frame = iter->second;
client->active_buffers.erase(iter);
-
- if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) {
- for (size_t i = 0; i < sync_points.size(); i++)
- frame->AppendReleaseSyncPoint(sync_points[i]);
- }
-
buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
+
+ if (sync_point)
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&ReturnVideoFrame, frame, sync_point));
}
const media::VideoCaptureFormat&
@@ -330,7 +383,7 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData(
scoped_refptr<Buffer> buffer =
DoReserveOutputBuffer(media::VideoFrame::I420, dimensions);
- if (!buffer)
+ if (!buffer.get())
return;
uint8* yplane = NULL;
bool flip = false;
@@ -429,7 +482,7 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData(
base::SharedMemory::NULLHandle(),
base::TimeDelta(),
base::Closure());
- DCHECK(frame);
+ DCHECK(frame.get());
VideoCaptureFormat format(
dimensions, frame_format.frame_rate, media::PIXEL_FORMAT_I420);
@@ -443,22 +496,6 @@ void VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedData(
format,
frame,
timestamp));
-
- if (first_frame_) {
- UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width",
- frame_format.frame_size.width());
- UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height",
- frame_format.frame_size.height());
- UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio",
- frame_format.frame_size.width(),
- frame_format.frame_size.height());
- UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate",
- frame_format.frame_rate);
- UMA_HISTOGRAM_ENUMERATION("Media.VideoCapture.PixelFormat",
- frame_format.pixel_format,
- media::PIXEL_FORMAT_MAX);
- first_frame_ = false;
- }
}
void
@@ -481,8 +518,13 @@ VideoCaptureController::VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
void VideoCaptureController::VideoCaptureDeviceClient::OnError(
const std::string& reason) {
- MediaStreamManager::SendMessageToNativeLog(
- "Error on video capture: " + reason);
+ const std::string log_message = base::StringPrintf(
+ "Error on video capture: %s, OS message: %s",
+ reason.c_str(),
+ logging::SystemErrorCodeToString(
+ logging::GetLastSystemErrorCode()).c_str());
+ DLOG(ERROR) << log_message;
+ MediaStreamManager::SendMessageToNativeLog(log_message);
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoErrorOnIOThread, controller_));
@@ -548,7 +590,7 @@ void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
for (ControllerClients::iterator client_it = controller_clients_.begin();
client_it != controller_clients_.end(); ++client_it) {
ControllerClient* client = *client_it;
- if (client->session_closed)
+ if (client->session_closed || client->paused)
continue;
if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) {
@@ -569,7 +611,8 @@ void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
}
client->event_handler->OnBufferReady(
- client->controller_id, buffer->id(), buffer_format, timestamp);
+ client->controller_id, buffer->id(), buffer_format,
+ frame->visible_rect(), timestamp);
}
bool inserted =
@@ -580,6 +623,19 @@ void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
}
}
+ if (!has_received_frames_) {
+ UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Width",
+ buffer_format.frame_size.width());
+ UMA_HISTOGRAM_COUNTS("Media.VideoCapture.Height",
+ buffer_format.frame_size.height());
+ UMA_HISTOGRAM_ASPECT_RATIO("Media.VideoCapture.AspectRatio",
+ buffer_format.frame_size.width(),
+ buffer_format.frame_size.height());
+ UMA_HISTOGRAM_COUNTS("Media.VideoCapture.FrameRate",
+ buffer_format.frame_rate);
+ has_received_frames_ = true;
+ }
+
buffer_pool_->HoldForConsumers(buffer->id(), count);
}
@@ -642,9 +698,19 @@ VideoCaptureController::FindClient(
return NULL;
}
-int VideoCaptureController::GetClientCount() {
+int VideoCaptureController::GetClientCount() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return controller_clients_.size();
}
+int VideoCaptureController::GetActiveClientCount() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int active_client_count = 0;
+ for (ControllerClient* client : controller_clients_) {
+ if (!client->paused)
+ ++active_client_count;
+ }
+ return active_client_count;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller.h b/chromium/content/browser/renderer_host/media/video_capture_controller.h
index 9b8287002ec..720213ecf26 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -66,7 +66,12 @@ class VideoCaptureBufferPool;
class CONTENT_EXPORT VideoCaptureController {
public:
- VideoCaptureController();
+ // |max_buffers| is the maximum number of video frame buffers in-flight at any
+ // one time. This value should be based on the logical capacity of the
+ // capture pipeline, and not on hardware performance. For example, tab
+ // capture requires more buffers than webcam capture because the pipeline is
+ // longer (it includes read-backs pending in the GPU pipeline).
+ explicit VideoCaptureController(int max_buffers);
virtual ~VideoCaptureController();
base::WeakPtr<VideoCaptureController> GetWeakPtr();
@@ -91,7 +96,15 @@ class CONTENT_EXPORT VideoCaptureController {
int RemoveClient(const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler);
- int GetClientCount();
+ // Pause or resume the video capture for specified client.
+ void PauseOrResumeClient(const VideoCaptureControllerID& id,
+ VideoCaptureControllerEventHandler* event_handler,
+ bool pause);
+
+ int GetClientCount() const;
+
+ // Return the number of clients that aren't paused.
+ int GetActiveClientCount() const;
// API called directly by VideoCaptureManager in case the device is
// prematurely closed.
@@ -105,10 +118,12 @@ class CONTENT_EXPORT VideoCaptureController {
void ReturnBuffer(const VideoCaptureControllerID& id,
VideoCaptureControllerEventHandler* event_handler,
int buffer_id,
- const std::vector<uint32>& sync_points);
+ uint32 sync_point);
const media::VideoCaptureFormat& GetVideoCaptureFormat() const;
+ bool has_received_frames() const { return has_received_frames_; }
+
private:
class VideoCaptureDeviceClient;
@@ -146,6 +161,9 @@ class CONTENT_EXPORT VideoCaptureController {
// state which stops the flow of data to clients.
VideoCaptureState state_;
+ // True if the controller has received a video frame from the device.
+ bool has_received_frames_;
+
media::VideoCaptureFormat video_capture_format_;
base::WeakPtrFactory<VideoCaptureController> weak_ptr_factory_;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
index 3e709476a12..2bddf694606 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -9,6 +9,10 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
+namespace gfx {
+class Rect;
+} // namespace gfx
+
namespace gpu {
struct MailboxHolder;
} // namespace gpu
@@ -51,6 +55,7 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler {
virtual void OnBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) = 0;
// A texture mailbox buffer has been filled with data.
diff --git a/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
index f650397de7b..87cb033b1fa 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -16,6 +16,7 @@
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/common/gpu/client/gl_helper.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
@@ -24,6 +25,12 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/test/no_transport_image_transport_factory_android.h"
+#else
+#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
+#endif
+
using ::testing::InSequence;
using ::testing::Mock;
@@ -46,22 +53,23 @@ class MockVideoCaptureControllerEventHandler
MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
MOCK_METHOD1(DoError, void(const VideoCaptureControllerID&));
- virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {
+ virtual void OnError(const VideoCaptureControllerID& id) override {
DoError(id);
}
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) OVERRIDE {
+ int length, int buffer_id) override {
DoBufferCreated(id);
}
virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
- int buffer_id) OVERRIDE {
+ int buffer_id) override {
DoBufferDestroyed(id);
}
virtual void OnBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE {
+ const gfx::Rect& visible_rect,
+ base::TimeTicks timestamp) override {
DoBufferReady(id);
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -70,17 +78,14 @@ class MockVideoCaptureControllerEventHandler
id,
this,
buffer_id,
- std::vector<uint32>()));
+ 0));
}
virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
const gpu::MailboxHolder& mailbox_holder,
const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE {
+ base::TimeTicks timestamp) override {
DoMailboxBufferReady(id);
- // Use a very different syncpoint value when returning a new syncpoint.
- std::vector<uint32> release_sync_points;
- release_sync_points.push_back(~mailbox_holder.sync_point);
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureController::ReturnBuffer,
@@ -88,9 +93,9 @@ class MockVideoCaptureControllerEventHandler
id,
this,
buffer_id,
- release_sync_points));
+ mailbox_holder.sync_point));
}
- virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
+ virtual void OnEnded(const VideoCaptureControllerID& id) override {
DoEnded(id);
// OnEnded() must respond by (eventually) unregistering the client.
base::MessageLoop::current()->PostTask(FROM_HERE,
@@ -105,13 +110,13 @@ class MockVideoCaptureControllerEventHandler
class VideoCaptureControllerTest : public testing::Test {
public:
VideoCaptureControllerTest() {}
- virtual ~VideoCaptureControllerTest() {}
+ ~VideoCaptureControllerTest() override {}
protected:
static const int kPoolSize = 3;
- virtual void SetUp() OVERRIDE {
- controller_.reset(new VideoCaptureController());
+ void SetUp() override {
+ controller_.reset(new VideoCaptureController(kPoolSize));
device_ = controller_->NewDeviceClient().Pass();
client_a_.reset(new MockVideoCaptureControllerEventHandler(
controller_.get()));
@@ -119,9 +124,7 @@ class VideoCaptureControllerTest : public testing::Test {
controller_.get()));
}
- virtual void TearDown() OVERRIDE {
- base::RunLoop().RunUntilIdle();
- }
+ void TearDown() override { base::RunLoop().RunUntilIdle(); }
scoped_refptr<media::VideoFrame> WrapI420Buffer(
const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
@@ -263,17 +266,25 @@ TEST_F(VideoCaptureControllerTest, AddAndRemoveClients) {
<< "Client count should return to zero after all clients are gone.";
}
-static void CacheSyncPoint(std::vector<uint32>* called_release_sync_points,
- const std::vector<uint32>& release_sync_points) {
- DCHECK(called_release_sync_points->empty());
- called_release_sync_points->assign(release_sync_points.begin(),
- release_sync_points.end());
+static void CacheSyncPoint(uint32* called_release_sync_point,
+ uint32 release_sync_point) {
+ *called_release_sync_point = release_sync_point;
}
// This test will connect and disconnect several clients while simulating an
// active capture device being started and generating frames. It runs on one
// thread and is intended to behave deterministically.
TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
+// VideoCaptureController::ReturnBuffer() uses ImageTransportFactory.
+#if defined(OS_ANDROID)
+ ImageTransportFactoryAndroid::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactoryAndroid>(
+ new NoTransportImageTransportFactoryAndroid));
+#else
+ ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactory>(new NoTransportImageTransportFactory));
+#endif
+
media::VideoCaptureParams session_100;
session_100.requested_format = media::VideoCaptureFormat(
gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
@@ -320,7 +331,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer;
buffer =
device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
memset(buffer->data(), buffer_no++, buffer->size());
{
InSequence s;
@@ -355,7 +366,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// delay. This shouldn't affect anything.
buffer =
device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
memset(buffer->data(), buffer_no++, buffer->size());
device_->OnIncomingCapturedVideoFrame(
buffer,
@@ -386,7 +397,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
for (int i = 0; i < kPoolSize; i++) {
buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
capture_resolution);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
memset(buffer->data(), buffer_no++, buffer->size());
device_->OnIncomingCapturedVideoFrame(
buffer,
@@ -399,7 +410,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
}
// ReserveOutputBuffer ought to fail now, because the pool is depleted.
ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
- capture_resolution));
+ capture_resolution).get());
// The new client needs to be told of 3 buffers; the old clients only 2.
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
@@ -426,7 +437,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Queue up another buffer.
buffer =
device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
memset(buffer->data(), buffer_no++, buffer->size());
device_->OnIncomingCapturedVideoFrame(
buffer,
@@ -444,7 +455,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
EXPECT_CALL(*client_a_, DoEnded(client_a_route_2)).Times(1);
controller_->StopSession(200);
}
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
memset(buffer->data(), buffer_no++, buffer->size());
device_->OnIncomingCapturedVideoFrame(
buffer,
@@ -473,7 +484,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
for (int i = 0; i < shm_buffers; ++i) {
buffer = device_->ReserveOutputBuffer(media::VideoFrame::I420,
capture_resolution);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
device_->OnIncomingCapturedVideoFrame(
buffer,
media::VideoCaptureFormat(capture_resolution,
@@ -484,42 +495,55 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
buffer = NULL;
}
std::vector<uint32> mailbox_syncpoints(mailbox_buffers);
- std::vector<std::vector<uint32> > release_syncpoint_vectors(mailbox_buffers);
+ std::vector<uint32> release_syncpoints(mailbox_buffers);
+#if defined(OS_ANDROID)
+ GLHelper* gl_helper =
+ ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
+#else
+ GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
+#endif
for (int i = 0; i < mailbox_buffers; ++i) {
buffer = device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
gfx::Size(0, 0));
- ASSERT_TRUE(buffer);
- mailbox_syncpoints[i] = i;
+ ASSERT_TRUE(buffer.get());
+ mailbox_syncpoints[i] = gl_helper->InsertSyncPoint();
device_->OnIncomingCapturedVideoFrame(
buffer,
media::VideoCaptureFormat(capture_resolution,
device_format.frame_rate,
media::PIXEL_FORMAT_TEXTURE),
- WrapMailboxBuffer(
- buffer,
- make_scoped_ptr(new gpu::MailboxHolder(
- gpu::Mailbox(), 0, mailbox_syncpoints[i])),
- base::Bind(&CacheSyncPoint, &release_syncpoint_vectors[i]),
- capture_resolution),
+ WrapMailboxBuffer(buffer,
+ make_scoped_ptr(new gpu::MailboxHolder(
+ gpu::Mailbox(), 0, mailbox_syncpoints[i])),
+ base::Bind(&CacheSyncPoint, &release_syncpoints[i]),
+ capture_resolution),
base::TimeTicks());
buffer = NULL;
}
// ReserveOutputBuffers ought to fail now regardless of buffer format, because
// the pool is depleted.
ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::I420,
- capture_resolution));
+ capture_resolution).get());
ASSERT_FALSE(device_->ReserveOutputBuffer(media::VideoFrame::NATIVE_TEXTURE,
- gfx::Size(0, 0)));
+ gfx::Size(0, 0)).get());
EXPECT_CALL(*client_b_, DoBufferReady(client_b_route_2)).Times(shm_buffers);
EXPECT_CALL(*client_b_, DoMailboxBufferReady(client_b_route_2))
.Times(mailbox_buffers);
base::RunLoop().RunUntilIdle();
for (size_t i = 0; i < mailbox_syncpoints.size(); ++i) {
- // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady()
- ASSERT_EQ(1u, release_syncpoint_vectors[i].size());
- ASSERT_EQ(mailbox_syncpoints[i], ~release_syncpoint_vectors[i][0]);
+ // A new release sync point must be inserted when the video frame is
+ // returned to the Browser process.
+ // See: MockVideoCaptureControllerEventHandler::OnMailboxBufferReady() and
+ // VideoCaptureController::ReturnBuffer()
+ ASSERT_NE(mailbox_syncpoints[i], release_syncpoints[i]);
}
Mock::VerifyAndClearExpectations(client_b_.get());
+
+#if defined(OS_ANDROID)
+ ImageTransportFactoryAndroid::TerminateForUnitTests();
+#else
+ ImageTransportFactory::Terminate();
+#endif
}
// Exercises the OnError() codepath of VideoCaptureController, and tests the
@@ -553,7 +577,7 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
device_->ReserveOutputBuffer(media::VideoFrame::I420, capture_resolution);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
device_->OnIncomingCapturedVideoFrame(
buffer,
@@ -592,7 +616,7 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
const gfx::Size dims(320, 240);
scoped_refptr<media::VideoCaptureDevice::Client::Buffer> buffer =
device_->ReserveOutputBuffer(media::VideoFrame::I420, dims);
- ASSERT_TRUE(buffer);
+ ASSERT_TRUE(buffer.get());
device_->OnError("Test error");
device_->OnIncomingCapturedVideoFrame(
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.cc b/chromium/content/browser/renderer_host/media/video_capture_host.cc
index a7fdf9d76e1..cc340e3dd80 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -77,6 +77,7 @@ void VideoCaptureHost::OnBufferReady(
const VideoCaptureControllerID& controller_id,
int buffer_id,
const media::VideoCaptureFormat& frame_format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) {
BrowserThread::PostTask(
BrowserThread::IO,
@@ -86,6 +87,7 @@ void VideoCaptureHost::OnBufferReady(
controller_id,
buffer_id,
frame_format,
+ visible_rect,
timestamp));
}
@@ -143,6 +145,7 @@ void VideoCaptureHost::DoSendFilledBufferOnIOThread(
const VideoCaptureControllerID& controller_id,
int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -150,7 +153,7 @@ void VideoCaptureHost::DoSendFilledBufferOnIOThread(
return;
Send(new VideoCaptureMsg_BufferReady(
- controller_id.device_id, buffer_id, format, timestamp));
+ controller_id.device_id, buffer_id, format, visible_rect, timestamp));
}
void VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread(
@@ -199,6 +202,7 @@ bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(VideoCaptureHost, message)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture)
+ IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Resume, OnResumeCapture)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats,
@@ -218,9 +222,11 @@ void VideoCaptureHost::OnStartCapture(int device_id,
DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
<< " session_id=" << session_id
<< ", device_id=" << device_id
- << ", format=" << params.requested_format.frame_size.ToString()
+ << ", format=" << params.requested_format.ToString()
<< "@" << params.requested_format.frame_rate
- << " (" << (params.allow_resolution_change ? "variable" : "constant")
+ << " (" << (params.resolution_change_policy ==
+ media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT ?
+ "variable" : "constant")
<< ")";
VideoCaptureControllerID controller_id(device_id);
if (entries_.find(controller_id) != entries_.end()) {
@@ -290,14 +296,39 @@ void VideoCaptureHost::OnStopCapture(int device_id) {
void VideoCaptureHost::OnPauseCapture(int device_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
- // Not used.
- Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
+
+ VideoCaptureControllerID controller_id(device_id);
+ EntryMap::iterator it = entries_.find(controller_id);
+ if (it == entries_.end())
+ return;
+
+ if (it->second) {
+ media_stream_manager_->video_capture_manager()->PauseCaptureForClient(
+ it->second.get(), controller_id, this);
+ }
}
-void VideoCaptureHost::OnReceiveEmptyBuffer(
+void VideoCaptureHost::OnResumeCapture(
int device_id,
- int buffer_id,
- const std::vector<uint32>& sync_points) {
+ media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(1) << "VideoCaptureHost::OnResumeCapture, device_id " << device_id;
+
+ VideoCaptureControllerID controller_id(device_id);
+ EntryMap::iterator it = entries_.find(controller_id);
+ if (it == entries_.end())
+ return;
+
+ if (it->second) {
+ media_stream_manager_->video_capture_manager()->ResumeCaptureForClient(
+ session_id, params, it->second.get(), controller_id, this);
+ }
+}
+
+void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id,
+ int buffer_id,
+ uint32 sync_point) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
VideoCaptureControllerID controller_id(device_id);
@@ -305,7 +336,7 @@ void VideoCaptureHost::OnReceiveEmptyBuffer(
if (it != entries_.end()) {
const base::WeakPtr<VideoCaptureController>& controller = it->second;
if (controller)
- controller->ReturnBuffer(controller_id, this, buffer_id, sync_points);
+ controller->ReturnBuffer(controller_id, this, buffer_id, sync_point);
}
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index caecb1ae228..1fd9813760e 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -71,28 +71,29 @@ class CONTENT_EXPORT VideoCaptureHost
explicit VideoCaptureHost(MediaStreamManager* media_stream_manager);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// VideoCaptureControllerEventHandler implementation.
- virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE;
- virtual void OnBufferCreated(const VideoCaptureControllerID& id,
- base::SharedMemoryHandle handle,
- int length,
- int buffer_id) OVERRIDE;
- virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
- int buffer_id) OVERRIDE;
- virtual void OnBufferReady(const VideoCaptureControllerID& id,
- int buffer_id,
- const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE;
- virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
- int buffer_id,
- const gpu::MailboxHolder& mailbox_holder,
- const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE;
- virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE;
+ void OnError(const VideoCaptureControllerID& id) override;
+ void OnBufferCreated(const VideoCaptureControllerID& id,
+ base::SharedMemoryHandle handle,
+ int length,
+ int buffer_id) override;
+ void OnBufferDestroyed(const VideoCaptureControllerID& id,
+ int buffer_id) override;
+ void OnBufferReady(const VideoCaptureControllerID& id,
+ int buffer_id,
+ const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
+ base::TimeTicks timestamp) override;
+ void OnMailboxBufferReady(const VideoCaptureControllerID& id,
+ int buffer_id,
+ const gpu::MailboxHolder& mailbox_holder,
+ const media::VideoCaptureFormat& format,
+ base::TimeTicks timestamp) override;
+ void OnEnded(const VideoCaptureControllerID& id) override;
private:
friend class BrowserThread;
@@ -100,7 +101,7 @@ class CONTENT_EXPORT VideoCaptureHost
friend class MockVideoCaptureHost;
friend class VideoCaptureHostTest;
- virtual ~VideoCaptureHost();
+ ~VideoCaptureHost() override;
// IPC message: Start capture on the VideoCaptureDevice referenced by
// |session_id|. |device_id| is an id created by VideoCaptureMessageFilter
@@ -122,11 +123,13 @@ class CONTENT_EXPORT VideoCaptureHost
// IPC message: Pause capture on device referenced by |device_id|.
void OnPauseCapture(int device_id);
+ void OnResumeCapture(int device_id,
+ media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& params);
+
// IPC message: Receive an empty buffer from renderer. Send it to device
// referenced by |device_id|.
- void OnReceiveEmptyBuffer(int device_id,
- int buffer_id,
- const std::vector<uint32>& sync_points);
+ void OnReceiveEmptyBuffer(int device_id, int buffer_id, uint32 sync_point);
// IPC message: Get supported formats referenced by |capture_session_id|.
// |device_id| is needed for message back-routing purposes.
@@ -157,6 +160,7 @@ class CONTENT_EXPORT VideoCaptureHost
const VideoCaptureControllerID& controller_id,
int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp);
// Sends a filled texture mailbox buffer to the VideoCaptureMessageFilter.
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
index 6088081bf7b..6787a385e6e 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
@@ -34,6 +34,10 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/audio/cras_audio_handler.h"
+#endif
+
using ::testing::_;
using ::testing::AtLeast;
using ::testing::AnyNumber;
@@ -86,23 +90,23 @@ class MockMediaStreamRequester : public MediaStreamRequester {
// MediaStreamRequester implementation.
MOCK_METHOD5(StreamGenerated,
- void(int render_view_id,
+ void(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_devices,
const StreamDeviceInfoArray& video_devices));
MOCK_METHOD3(StreamGenerationFailed,
- void(int render_view_id,
+ void(int render_frame_id,
int page_request_id,
content::MediaStreamRequestResult result));
- MOCK_METHOD3(DeviceStopped, void(int render_view_id,
+ MOCK_METHOD3(DeviceStopped, void(int render_frame_id,
const std::string& label,
const StreamDeviceInfo& device));
- MOCK_METHOD4(DevicesEnumerated, void(int render_view_id,
+ MOCK_METHOD4(DevicesEnumerated, void(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfoArray& devices));
- MOCK_METHOD4(DeviceOpened, void(int render_view_id,
+ MOCK_METHOD4(DeviceOpened, void(int render_frame_id,
int page_request_id,
const std::string& label,
const StreamDeviceInfo& device_info));
@@ -126,10 +130,11 @@ class MockVideoCaptureHost : public VideoCaptureHost {
int buffer_id));
MOCK_METHOD2(OnBufferFreed,
void(int device_id, int buffer_id));
- MOCK_METHOD4(OnBufferFilled,
+ MOCK_METHOD5(OnBufferFilled,
void(int device_id,
int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp));
MOCK_METHOD5(OnMailboxBufferFilled,
void(int device_id,
@@ -152,7 +157,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
void ReturnReceivedDibs(int device_id) {
int handle = GetReceivedDib();
while (handle) {
- this->OnReceiveEmptyBuffer(device_id, handle, std::vector<uint32>());
+ this->OnReceiveEmptyBuffer(device_id, handle, 0);
handle = GetReceivedDib();
}
}
@@ -177,7 +182,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
// This method is used to dispatch IPC messages to the renderer. We intercept
// these messages here and dispatch to our mock methods to verify the
// conversation between this object and the renderer.
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ virtual bool Send(IPC::Message* message) override {
CHECK(message);
// In this method we dispatch the messages to the according handlers as if
@@ -222,6 +227,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
void OnBufferFilledDispatch(int device_id,
int buffer_id,
const media::VideoCaptureFormat& frame_format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) {
base::SharedMemory* dib = filled_dib_[buffer_id];
ASSERT_TRUE(dib != NULL);
@@ -238,10 +244,9 @@ class MockVideoCaptureHost : public VideoCaptureHost {
dumper_.NewVideoFrame(dib->memory());
}
- OnBufferFilled(device_id, buffer_id, frame_format, timestamp);
+ OnBufferFilled(device_id, buffer_id, frame_format, visible_rect, timestamp);
if (return_buffers_) {
- VideoCaptureHost::OnReceiveEmptyBuffer(
- device_id, buffer_id, std::vector<uint32>());
+ VideoCaptureHost::OnReceiveEmptyBuffer(device_id, buffer_id, 0);
}
}
@@ -253,8 +258,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
OnMailboxBufferFilled(
device_id, buffer_id, mailbox_holder, format, timestamp);
if (return_buffers_) {
- VideoCaptureHost::OnReceiveEmptyBuffer(
- device_id, buffer_id, std::vector<uint32>());
+ VideoCaptureHost::OnReceiveEmptyBuffer(device_id, buffer_id, 0);
}
}
@@ -283,8 +287,13 @@ class VideoCaptureHostTest : public testing::Test {
message_loop_(base::MessageLoopProxy::current()),
opened_session_id_(kInvalidMediaCaptureSessionId) {}
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
SetBrowserClientForTesting(&browser_client_);
+
+#if defined(OS_CHROMEOS)
+ chromeos::CrasAudioHandler::InitializeForTesting();
+#endif
+
// Create our own MediaStreamManager.
audio_manager_.reset(media::AudioManager::CreateForTesting());
#ifndef TEST_REAL_CAPTURE_DEVICE
@@ -301,7 +310,7 @@ class VideoCaptureHostTest : public testing::Test {
OpenSession();
}
- virtual void TearDown() OVERRIDE {
+ virtual void TearDown() override {
// Verifies and removes the expectations on host_ and
// returns true iff successful.
Mock::VerifyAndClearExpectations(host_.get());
@@ -315,11 +324,15 @@ class VideoCaptureHostTest : public testing::Test {
// Release the reference to the mock object. The object will be destructed
// on the current message loop.
host_ = NULL;
+
+#if defined(OS_CHROMEOS)
+ chromeos::CrasAudioHandler::Shutdown();
+#endif
}
void OpenSession() {
const int render_process_id = 1;
- const int render_view_id = 1;
+ const int render_frame_id = 1;
const int page_request_id = 1;
const GURL security_origin("http://test.com");
@@ -332,13 +345,12 @@ class VideoCaptureHostTest : public testing::Test {
std::string label = media_stream_manager_->EnumerateDevices(
&stream_requester_,
render_process_id,
- render_view_id,
+ render_frame_id,
browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
page_request_id,
MEDIA_DEVICE_VIDEO_CAPTURE,
- security_origin,
- true);
- EXPECT_CALL(stream_requester_, DevicesEnumerated(render_view_id,
+ security_origin);
+ EXPECT_CALL(stream_requester_, DevicesEnumerated(render_frame_id,
page_request_id,
label,
_))
@@ -359,13 +371,13 @@ class VideoCaptureHostTest : public testing::Test {
media_stream_manager_->OpenDevice(
&stream_requester_,
render_process_id,
- render_view_id,
+ render_frame_id,
browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(),
page_request_id,
devices[0].device.id,
MEDIA_DEVICE_VIDEO_CAPTURE,
security_origin);
- EXPECT_CALL(stream_requester_, DeviceOpened(render_view_id,
+ EXPECT_CALL(stream_requester_, DeviceOpened(render_frame_id,
page_request_id,
_,
_))
@@ -390,13 +402,14 @@ class VideoCaptureHostTest : public testing::Test {
protected:
void StartCapture() {
- EXPECT_CALL(*host_, OnNewBufferCreated(kDeviceId, _, _, _))
- .Times(AnyNumber()).WillRepeatedly(Return());
+ EXPECT_CALL(*host_.get(), OnNewBufferCreated(kDeviceId, _, _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return());
base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
- .Times(AnyNumber()).WillOnce(ExitMessageLoop(
- message_loop_, run_loop.QuitClosure()));
+ EXPECT_CALL(*host_.get(), OnBufferFilled(kDeviceId, _, _, _, _))
+ .Times(AnyNumber())
+ .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
media::VideoCaptureParams params;
params.requested_format = media::VideoCaptureFormat(
@@ -410,7 +423,8 @@ class VideoCaptureHostTest : public testing::Test {
// asynchronous start operations to complete.
InSequence s;
base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED));
media::VideoCaptureParams params;
params.requested_format = media::VideoCaptureFormat(
gfx::Size(352, 288), 30, media::PIXEL_FORMAT_I420);
@@ -426,7 +440,7 @@ class VideoCaptureHostTest : public testing::Test {
.Times(AnyNumber()).WillRepeatedly(Return());
base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
+ EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _, _))
.Times(AnyNumber())
.WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
@@ -441,7 +455,8 @@ class VideoCaptureHostTest : public testing::Test {
void StopCapture() {
base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
.WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()));
host_->OnStopCapture(kDeviceId);
@@ -457,9 +472,9 @@ class VideoCaptureHostTest : public testing::Test {
void NotifyPacketReady() {
base::RunLoop run_loop;
- EXPECT_CALL(*host_, OnBufferFilled(kDeviceId, _, _, _))
- .Times(AnyNumber()).WillOnce(ExitMessageLoop(
- message_loop_, run_loop.QuitClosure()))
+ EXPECT_CALL(*host_.get(), OnBufferFilled(kDeviceId, _, _, _, _))
+ .Times(AnyNumber())
+ .WillOnce(ExitMessageLoop(message_loop_, run_loop.QuitClosure()))
.RetiresOnSaturation();
run_loop.Run();
}
@@ -470,8 +485,8 @@ class VideoCaptureHostTest : public testing::Test {
void SimulateError() {
// Expect a change state to error state sent through IPC.
- EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR))
- .Times(1);
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ERROR)).Times(1);
VideoCaptureControllerID id(kDeviceId);
host_->OnError(id);
// Wait for the error callback.
@@ -499,8 +514,8 @@ TEST_F(VideoCaptureHostTest, CloseSessionWithoutStopping) {
// When the session is closed via the stream without stopping capture, the
// ENDED event is sent.
- EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ENDED))
- .Times(1);
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_ENDED)).Times(1);
CloseSession();
base::RunLoop().RunUntilIdle();
}
@@ -524,8 +539,8 @@ TEST_F(VideoCaptureHostTest, StartCaptureErrorStop) {
}
TEST_F(VideoCaptureHostTest, StartCaptureError) {
- EXPECT_CALL(*host_, OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED))
- .Times(0);
+ EXPECT_CALL(*host_.get(),
+ OnStateChanged(kDeviceId, VIDEO_CAPTURE_STATE_STOPPED)).Times(0);
StartCapture();
NotifyPacketReady();
SimulateError();
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.cc b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
index 3e9e0bfa864..617a8696dee 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -14,6 +14,7 @@
#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/browser/media/capture/web_contents_video_capture_device.h"
+#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
#include "content/public/browser/browser_thread.h"
@@ -70,6 +71,29 @@ void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) {
}
}
+// The maximum number of buffers in the capture pipeline. See
+// VideoCaptureController ctor comments for more details.
+const int kMaxNumberOfBuffers = 3;
+const int kMaxNumberOfBuffersForTabCapture = 5;
+
+// Used for logging capture events.
+// Elements in this enum should not be deleted or rearranged; the only
+// permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT.
+enum VideoCaptureEvent {
+ VIDEO_CAPTURE_START_CAPTURE = 0,
+ VIDEO_CAPTURE_STOP_CAPTURE_OK = 1,
+ VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR = 2,
+ VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE = 3,
+ VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4,
+ NUM_VIDEO_CAPTURE_EVENT
+};
+
+void LogVideoCaptureEvent(VideoCaptureEvent event) {
+ UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event",
+ event,
+ NUM_VIDEO_CAPTURE_EVENT);
+}
+
} // namespace
namespace content {
@@ -84,15 +108,6 @@ VideoCaptureManager::DeviceEntry::DeviceEntry(
VideoCaptureManager::DeviceEntry::~DeviceEntry() {}
-VideoCaptureManager::DeviceInfo::DeviceInfo() {}
-
-VideoCaptureManager::DeviceInfo::DeviceInfo(
- const media::VideoCaptureDevice::Name& name,
- const media::VideoCaptureFormats& supported_formats)
- : name(name),
- supported_formats(supported_formats) {}
-
-VideoCaptureManager::DeviceInfo::~DeviceInfo() {}
VideoCaptureManager::VideoCaptureManager(
scoped_ptr<media::VideoCaptureDeviceFactory> factory)
@@ -215,7 +230,8 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread(
// We look up the device id from the renderer in our local enumeration
// since the renderer does not have all the information that might be
// held in the browser-side VideoCaptureDevice::Name structure.
- DeviceInfo* found = FindDeviceInfoById(entry->id, devices_info_cache_);
+ media::VideoCaptureDeviceInfo* found =
+ FindDeviceInfoById(entry->id, devices_info_cache_);
if (found) {
video_capture_device =
video_capture_device_factory_->Create(found->name);
@@ -242,6 +258,8 @@ void VideoCaptureManager::DoStartDeviceOnDeviceThread(
notification_window_ids_.end()) {
static_cast<DesktopCaptureDevice*>(video_capture_device.get())
->SetNotificationWindowId(notification_window_ids_[session_id]);
+ VLOG(2) << "Screen capture notification window passed for session "
+ << session_id;
}
}
#endif // defined(ENABLE_SCREEN_CAPTURE)
@@ -282,8 +300,10 @@ void VideoCaptureManager::StartCaptureForClient(
DCHECK(entry->video_capture_controller);
+ LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE);
+
// First client starts the device.
- if (entry->video_capture_controller->GetClientCount() == 0) {
+ if (entry->video_capture_controller->GetActiveClientCount() == 0) {
DVLOG(1) << "VideoCaptureManager starting device (type = "
<< entry->stream_type << ", id = " << entry->id << ")";
@@ -317,7 +337,18 @@ void VideoCaptureManager::StopCaptureForClient(
NOTREACHED();
return;
}
- if (aborted_due_to_error) {
+ if (!aborted_due_to_error) {
+ if (controller->has_received_frames()) {
+ LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK);
+ } else if (entry->stream_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
+ LogVideoCaptureEvent(
+ VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE);
+ } else {
+ LogVideoCaptureEvent(
+ VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB);
+ }
+ } else {
+ LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR);
SessionMap::iterator it;
for (it = sessions_.begin(); it != sessions_.end(); ++it) {
if (it->second.type == entry->stream_type &&
@@ -338,6 +369,71 @@ void VideoCaptureManager::StopCaptureForClient(
DestroyDeviceEntryIfNoClients(entry);
}
+void VideoCaptureManager::PauseCaptureForClient(
+ VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(controller);
+ DCHECK(client_handler);
+ DeviceEntry* entry = GetDeviceEntryForController(controller);
+ if (!entry) {
+ NOTREACHED();
+ return;
+ }
+
+ // We only pause the MEDIA_DEVICE_VIDEO_CAPTURE entry to release camera to
+ // system.
+ if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
+ return;
+
+ controller->PauseOrResumeClient(client_id, client_handler, true);
+ if (controller->GetActiveClientCount() != 0)
+ return;
+
+ // There is no more client, release the camera.
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
+ base::Unretained(entry)));
+}
+
+void VideoCaptureManager::ResumeCaptureForClient(
+ media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& params,
+ VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(controller);
+ DCHECK(client_handler);
+
+ DeviceEntry* entry = GetDeviceEntryForController(controller);
+ if (!entry) {
+ NOTREACHED();
+ return;
+ }
+
+ // We only pause/resume the MEDIA_DEVICE_VIDEO_CAPTURE entry.
+ if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
+ return;
+
+ controller->PauseOrResumeClient(client_id, client_handler, false);
+ if (controller->GetActiveClientCount() != 1)
+ return;
+
+ // This is first active client, allocate the camera.
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &VideoCaptureManager::DoStartDeviceOnDeviceThread,
+ this,
+ session_id,
+ entry,
+ params,
+ base::Passed(entry->video_capture_controller->NewDeviceClient())));
+}
+
bool VideoCaptureManager::GetDeviceSupportedFormats(
media::VideoCaptureSessionId capture_session_id,
media::VideoCaptureFormats* supported_formats) {
@@ -350,7 +446,7 @@ bool VideoCaptureManager::GetDeviceSupportedFormats(
DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name;
// Return all available formats of the device, regardless its started state.
- DeviceInfo* existing_device =
+ media::VideoCaptureDeviceInfo* existing_device =
FindDeviceInfoById(it->second.id, devices_info_cache_);
if (existing_device)
*supported_formats = existing_device->supported_formats;
@@ -383,8 +479,11 @@ void VideoCaptureManager::SetDesktopCaptureWindowId(
media::VideoCaptureSessionId session_id,
gfx::NativeViewId window_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id;
+
SessionMap::iterator session_it = sessions_.find(session_id);
if (session_it == sessions_.end()) {
+ VLOG(2) << "Session not found, will save the notification window.";
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(
@@ -397,13 +496,16 @@ void VideoCaptureManager::SetDesktopCaptureWindowId(
DeviceEntry* const existing_device =
GetDeviceEntryForMediaStreamDevice(session_it->second);
- if (!existing_device)
+ if (!existing_device) {
+ VLOG(2) << "Failed to find an existing device.";
return;
+ }
DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type);
DesktopMediaID id = DesktopMediaID::Parse(existing_device->id);
if (id.type == DesktopMediaID::TYPE_NONE ||
id.type == DesktopMediaID::TYPE_AURA_WINDOW) {
+ VLOG(2) << "Video capture device type mismatch.";
return;
}
@@ -449,7 +551,7 @@ void VideoCaptureManager::OnClosed(
void VideoCaptureManager::OnDevicesInfoEnumerated(
MediaStreamType stream_type,
base::ElapsedTimer* timer,
- const DeviceInfos& new_devices_info_cache) {
+ const media::VideoCaptureDeviceInfos& new_devices_info_cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_TIMES(
"Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime",
@@ -460,13 +562,15 @@ void VideoCaptureManager::OnDevicesInfoEnumerated(
}
devices_info_cache_ = new_devices_info_cache;
+ MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities(
+ devices_info_cache_);
+
// Walk the |devices_info_cache_| and transform from VCD::Name to
// StreamDeviceInfo for return purposes.
StreamDeviceInfoArray devices;
- for (DeviceInfos::const_iterator it = devices_info_cache_.begin();
- it != devices_info_cache_.end(); ++it) {
+ for (const auto& it : devices_info_cache_) {
devices.push_back(StreamDeviceInfo(
- stream_type, it->name.GetNameAndModel(), it->name.id()));
+ stream_type, it.name.GetNameAndModel(), it.name.id()));
}
listener_->DevicesEnumerated(stream_type, devices);
}
@@ -476,23 +580,21 @@ bool VideoCaptureManager::IsOnDeviceThread() const {
}
void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
- base::Callback<void(const DeviceInfos&)> on_devices_enumerated_callback,
+ base::Callback<void(const media::VideoCaptureDeviceInfos&)>
+ on_devices_enumerated_callback,
MediaStreamType stream_type,
- const DeviceInfos& old_device_info_cache,
+ const media::VideoCaptureDeviceInfos& old_device_info_cache,
scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot) {
DCHECK(IsOnDeviceThread());
// Construct |new_devices_info_cache| with the cached devices that are still
// present in the system, and remove their names from |names_snapshot|, so we
// keep there the truly new devices.
- DeviceInfos new_devices_info_cache;
- for (DeviceInfos::const_iterator it_device_info =
- old_device_info_cache.begin();
- it_device_info != old_device_info_cache.end(); ++it_device_info) {
+ media::VideoCaptureDeviceInfos new_devices_info_cache;
+ for (const auto& device_info : old_device_info_cache) {
for (media::VideoCaptureDevice::Names::iterator it =
- names_snapshot->begin();
- it != names_snapshot->end(); ++it) {
- if (it_device_info->name.id() == it->id()) {
- new_devices_info_cache.push_back(*it_device_info);
+ names_snapshot->begin(); it != names_snapshot->end(); ++it) {
+ if (device_info.name.id() == it->id()) {
+ new_devices_info_cache.push_back(device_info);
names_snapshot->erase(it);
break;
}
@@ -500,13 +602,10 @@ void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
}
// Get the supported capture formats for the new devices in |names_snapshot|.
- for (media::VideoCaptureDevice::Names::const_iterator it =
- names_snapshot->begin();
- it != names_snapshot->end(); ++it) {
- media::VideoCaptureFormats supported_formats;
- DeviceInfo device_info(*it, media::VideoCaptureFormats());
+ for (const auto& it : *names_snapshot) {
+ media::VideoCaptureDeviceInfo device_info(it, media::VideoCaptureFormats());
video_capture_device_factory_->GetDeviceSupportedFormats(
- *it, &(device_info.supported_formats));
+ it, &(device_info.supported_formats));
ConsolidateCaptureFormats(&device_info.supported_formats);
new_devices_info_cache.push_back(device_info);
}
@@ -582,8 +681,10 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
return existing_device;
}
+ const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ?
+ kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers;
scoped_ptr<VideoCaptureController> video_capture_controller(
- new VideoCaptureController());
+ new VideoCaptureController(max_buffers));
DeviceEntry* new_device = new DeviceEntry(device_info.type,
device_info.id,
video_capture_controller.Pass());
@@ -591,13 +692,12 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
return new_device;
}
-VideoCaptureManager::DeviceInfo* VideoCaptureManager::FindDeviceInfoById(
+media::VideoCaptureDeviceInfo* VideoCaptureManager::FindDeviceInfoById(
const std::string& id,
- DeviceInfos& device_vector) {
- for (DeviceInfos::iterator it = device_vector.begin();
- it != device_vector.end(); ++it) {
- if (it->name.id() == id)
- return &(*it);
+ media::VideoCaptureDeviceInfos& device_vector) {
+ for (auto& it : device_vector) {
+ if (it.name.id() == id)
+ return &(it);
}
return NULL;
}
@@ -611,6 +711,7 @@ void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
DesktopCaptureDevice* device =
static_cast<DesktopCaptureDevice*>(entry->video_capture_device.get());
device->SetNotificationWindowId(window_id);
+ VLOG(2) << "Screen capture notification window passed on device thread.";
#endif
}
@@ -621,6 +722,8 @@ void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread(
DCHECK(notification_window_ids_.find(session_id) ==
notification_window_ids_.end());
notification_window_ids_[session_id] = window_id;
+ VLOG(2) << "Screen capture notification window saved for session "
+ << session_id << " on device thread.";
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager.h b/chromium/content/browser/renderer_host/media/video_capture_manager.h
index 7f69d56a904..544fb86472f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -27,6 +27,7 @@
#include "content/common/media/media_stream_options.h"
#include "media/video/capture/video_capture_device.h"
#include "media/video/capture/video_capture_device_factory.h"
+#include "media/video/capture/video_capture_device_info.h"
#include "media/video/capture/video_capture_types.h"
namespace content {
@@ -44,17 +45,17 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
scoped_ptr<media::VideoCaptureDeviceFactory> factory);
// Implements MediaStreamProvider.
- virtual void Register(MediaStreamProviderListener* listener,
- const scoped_refptr<base::SingleThreadTaskRunner>&
- device_task_runner) OVERRIDE;
+ void Register(MediaStreamProviderListener* listener,
+ const scoped_refptr<base::SingleThreadTaskRunner>&
+ device_task_runner) override;
- virtual void Unregister() OVERRIDE;
+ void Unregister() override;
- virtual void EnumerateDevices(MediaStreamType stream_type) OVERRIDE;
+ void EnumerateDevices(MediaStreamType stream_type) override;
- virtual int Open(const StreamDeviceInfo& device) OVERRIDE;
+ int Open(const StreamDeviceInfo& device) override;
- virtual void Close(int capture_session_id) OVERRIDE;
+ void Close(int capture_session_id) override;
// Called by VideoCaptureHost to locate a capture device for |capture_params|,
// adding the Host as a client of the device's controller if successful. The
@@ -84,6 +85,28 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
VideoCaptureControllerEventHandler* client_handler,
bool aborted_due_to_error);
+ // Called by VideoCaptureHost to pause to update video buffer specified by
+ // |client_id| and |client_handler|. If all clients of |controller| are
+ // paused, the corresponding device will be closed.
+ void PauseCaptureForClient(
+ VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler);
+
+ // Called by VideoCaptureHost to resume to update video buffer specified by
+ // |client_id| and |client_handler|. The |session_id| and |params| should be
+ // same as those used in StartCaptureForClient().
+ // If this is first active client of |controller|, device will be allocated
+ // and it will take a little time to resume.
+ // Allocating device could failed if other app holds the camera, the error
+ // will be notified through VideoCaptureControllerEventHandler::OnError().
+ void ResumeCaptureForClient(
+ media::VideoCaptureSessionId session_id,
+ const media::VideoCaptureParams& params,
+ VideoCaptureController* controller,
+ VideoCaptureControllerID client_id,
+ VideoCaptureControllerEventHandler* client_handler);
+
// Retrieves all capture supported formats for a particular device. Returns
// false if the |capture_session_id| is not found. The supported formats are
// cached during device(s) enumeration, and depending on the underlying
@@ -108,23 +131,17 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
return video_capture_device_factory_.get();
}
+#if defined(OS_WIN)
+ void set_device_task_runner(
+ const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
+ device_task_runner_ = device_task_runner;
+ }
+#endif
+
private:
- virtual ~VideoCaptureManager();
+ ~VideoCaptureManager() override;
struct DeviceEntry;
- // This data structure is a convenient wrap of a devices' name and associated
- // video capture supported formats.
- struct DeviceInfo {
- DeviceInfo();
- DeviceInfo(const media::VideoCaptureDevice::Name& name,
- const media::VideoCaptureFormats& supported_formats);
- ~DeviceInfo();
-
- media::VideoCaptureDevice::Name name;
- media::VideoCaptureFormats supported_formats;
- };
- typedef std::vector<DeviceInfo> DeviceInfos;
-
// Checks to see if |entry| has no clients left on its controller. If so,
// remove it from the list of devices, and delete it asynchronously. |entry|
// may be freed by this function.
@@ -135,9 +152,10 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
media::VideoCaptureSessionId capture_session_id);
void OnClosed(MediaStreamType type,
media::VideoCaptureSessionId capture_session_id);
- void OnDevicesInfoEnumerated(MediaStreamType stream_type,
- base::ElapsedTimer* timer,
- const DeviceInfos& new_devices_info_cache);
+ void OnDevicesInfoEnumerated(
+ MediaStreamType stream_type,
+ base::ElapsedTimer* timer,
+ const media::VideoCaptureDeviceInfos& new_devices_info_cache);
// Finds a DeviceEntry by its device ID and type, if it is already opened.
DeviceEntry* GetDeviceEntryForMediaStreamDevice(
@@ -158,9 +176,10 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// devices in the system |names_snapshot|. Retrieves the supported formats of
// the new devices and sends the new cache to OnDevicesInfoEnumerated().
void ConsolidateDevicesInfoOnDeviceThread(
- base::Callback<void(const DeviceInfos&)> on_devices_enumerated_callback,
+ base::Callback<void(const media::VideoCaptureDeviceInfos&)>
+ on_devices_enumerated_callback,
MediaStreamType stream_type,
- const DeviceInfos& old_device_info_cache,
+ const media::VideoCaptureDeviceInfos& old_device_info_cache,
scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot);
// Creates and Starts a new VideoCaptureDevice, storing the result in
@@ -176,8 +195,9 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// |entry->video_capture_device|.
void DoStopDeviceOnDeviceThread(DeviceEntry* entry);
- DeviceInfo* FindDeviceInfoById(const std::string& id,
- DeviceInfos& device_vector);
+ media::VideoCaptureDeviceInfo* FindDeviceInfoById(
+ const std::string& id,
+ media::VideoCaptureDeviceInfos& device_vector);
void SetDesktopCaptureWindowIdOnDeviceThread(DeviceEntry* entry,
gfx::NativeViewId window_id);
@@ -238,7 +258,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// this list in OnDevicesInfoEnumerated(). GetDeviceSupportedFormats() will
// use this list if the device is not started, otherwise it will retrieve the
// active device capture format from the VideoCaptureController associated.
- DeviceInfos devices_info_cache_;
+ media::VideoCaptureDeviceInfos devices_info_cache_;
// Accessed on the device thread only.
std::map<media::VideoCaptureSessionId, gfx::NativeViewId>
diff --git a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 8599924b052..e42601ae44b 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -48,19 +48,20 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
virtual void OnBufferCreated(const VideoCaptureControllerID& id,
base::SharedMemoryHandle handle,
- int length, int buffer_id) OVERRIDE {}
+ int length, int buffer_id) override {}
virtual void OnBufferDestroyed(const VideoCaptureControllerID& id,
- int buffer_id) OVERRIDE {}
+ int buffer_id) override {}
virtual void OnBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE {}
+ const gfx::Rect& visible_rect,
+ base::TimeTicks timestamp) override {}
virtual void OnMailboxBufferReady(const VideoCaptureControllerID& id,
int buffer_id,
const gpu::MailboxHolder& mailbox_holder,
const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE {}
- virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {}
+ base::TimeTicks timestamp) override {}
+ virtual void OnEnded(const VideoCaptureControllerID& id) override {}
void OnGotControllerCallback(VideoCaptureControllerID) {}
};
@@ -69,10 +70,10 @@ class MockFrameObserver : public VideoCaptureControllerEventHandler {
class VideoCaptureManagerTest : public testing::Test {
public:
VideoCaptureManagerTest() : next_client_id_(1) {}
- virtual ~VideoCaptureManagerTest() {}
+ ~VideoCaptureManagerTest() override {}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
listener_.reset(new MockMediaStreamProviderListener());
message_loop_.reset(new base::MessageLoopForIO);
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
@@ -88,7 +89,7 @@ class VideoCaptureManagerTest : public testing::Test {
frame_observer_.reset(new MockFrameObserver());
}
- virtual void TearDown() OVERRIDE {}
+ void TearDown() override {}
void OnGotControllerCallback(
VideoCaptureControllerID id,
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
index 7bc8233b9cd..1cc1f6bcf18 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host.h
@@ -30,10 +30,10 @@ class CONTENT_EXPORT WebRTCIdentityServiceHost : public BrowserMessageFilter {
scoped_refptr<WebRTCIdentityStore> identity_store);
protected:
- virtual ~WebRTCIdentityServiceHost();
+ ~WebRTCIdentityServiceHost() override;
// content::BrowserMessageFilter override.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
// |sequence_number| is the same as in the OnRequestIdentity call.
diff --git a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
index a785a22b993..4a9c5d2db38 100644
--- a/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc
@@ -29,11 +29,10 @@ class MockWebRTCIdentityStore : public WebRTCIdentityStore {
public:
MockWebRTCIdentityStore() : WebRTCIdentityStore(base::FilePath(), NULL) {}
- virtual base::Closure RequestIdentity(
- const GURL& origin,
- const std::string& identity_name,
- const std::string& common_name,
- const CompletionCallback& callback) OVERRIDE {
+ base::Closure RequestIdentity(const GURL& origin,
+ const std::string& identity_name,
+ const std::string& common_name,
+ const CompletionCallback& callback) override {
EXPECT_TRUE(callback_.is_null());
callback_ = callback;
@@ -51,7 +50,7 @@ class MockWebRTCIdentityStore : public WebRTCIdentityStore {
}
private:
- virtual ~MockWebRTCIdentityStore() {}
+ ~MockWebRTCIdentityStore() override {}
void OnCancel() { callback_.Reset(); }
@@ -67,13 +66,13 @@ class WebRTCIdentityServiceHostForTest : public WebRTCIdentityServiceHost {
policy->Add(FAKE_RENDERER_ID);
}
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
messages_.push_back(*message);
delete message;
return true;
}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
return WebRTCIdentityServiceHost::OnMessageReceived(message);
}
@@ -84,7 +83,7 @@ class WebRTCIdentityServiceHostForTest : public WebRTCIdentityServiceHost {
void ClearMessages() { messages_.clear(); }
private:
- virtual ~WebRTCIdentityServiceHostForTest() {
+ ~WebRTCIdentityServiceHostForTest() override {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
policy->Remove(FAKE_RENDERER_ID);
diff --git a/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h b/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h
index 7255ab915e6..d30e3a78fb1 100644
--- a/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h
+++ b/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h
@@ -15,9 +15,10 @@ class MemoryBenchmarkMessageFilter : public BrowserMessageFilter {
public:
MemoryBenchmarkMessageFilter();
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
private:
- virtual ~MemoryBenchmarkMessageFilter();
+ ~MemoryBenchmarkMessageFilter() override;
void OnHeapProfilerDump(const std::string& reason);
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
index 646b358ac8d..502b30d9981 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event.cc
@@ -17,7 +17,7 @@ int GetModifiersFromNativeWebKeyboardEvent(
modifiers |= ui::EF_CONTROL_DOWN;
if (event.modifiers & NativeWebKeyboardEvent::AltKey)
modifiers |= ui::EF_ALT_DOWN;
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
if (event.modifiers & NativeWebKeyboardEvent::MetaKey)
modifiers |= ui::EF_COMMAND_DOWN;
#endif
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index 3a6e7576563..86dc692fea2 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -15,7 +15,7 @@ using blink::WebInputEvent;
namespace {
bool IsScrollEndEffectEnabled() {
- return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kScrollEndEffect) == "1";
}
@@ -212,20 +212,18 @@ bool OverscrollController::ProcessEventForOverscroll(
static_cast<const blink::WebMouseWheelEvent&>(event);
if (!wheel.hasPreciseScrollingDeltas)
break;
-
- ProcessOverscroll(wheel.deltaX * wheel.accelerationRatioX,
- wheel.deltaY * wheel.accelerationRatioY,
- wheel.type);
- event_processed = true;
+ event_processed =
+ ProcessOverscroll(wheel.deltaX * wheel.accelerationRatioX,
+ wheel.deltaY * wheel.accelerationRatioY,
+ wheel.type);
break;
}
case blink::WebInputEvent::GestureScrollUpdate: {
const blink::WebGestureEvent& gesture =
static_cast<const blink::WebGestureEvent&>(event);
- ProcessOverscroll(gesture.data.scrollUpdate.deltaX,
- gesture.data.scrollUpdate.deltaY,
- gesture.type);
- event_processed = true;
+ event_processed = ProcessOverscroll(gesture.data.scrollUpdate.deltaX,
+ gesture.data.scrollUpdate.deltaY,
+ gesture.type);
break;
}
case blink::WebInputEvent::GestureFlingStart: {
@@ -263,7 +261,7 @@ bool OverscrollController::ProcessEventForOverscroll(
return event_processed;
}
-void OverscrollController::ProcessOverscroll(float delta_x,
+bool OverscrollController::ProcessOverscroll(float delta_x,
float delta_y,
blink::WebInputEvent::Type type) {
if (scroll_state_ != STATE_CONTENT_SCROLLING)
@@ -279,7 +277,7 @@ void OverscrollController::ProcessOverscroll(float delta_x,
if (fabs(overscroll_delta_x_) <= horiz_threshold &&
fabs(overscroll_delta_y_) <= vert_threshold) {
SetOverscrollMode(OVERSCROLL_NONE);
- return;
+ return true;
}
// Compute the current overscroll direction. If the direction is different
@@ -306,7 +304,7 @@ void OverscrollController::ProcessOverscroll(float delta_x,
SetOverscrollMode(OVERSCROLL_NONE);
if (overscroll_mode_ == OVERSCROLL_NONE)
- return;
+ return false;
// Tell the delegate about the overscroll update so that it can update
// the display accordingly (e.g. show history preview etc.).
@@ -332,8 +330,9 @@ void OverscrollController::ProcessOverscroll(float delta_x,
} else {
delegate_delta_y = 0.f;
}
- delegate_->OnOverscrollUpdate(delegate_delta_x, delegate_delta_y);
+ return delegate_->OnOverscrollUpdate(delegate_delta_x, delegate_delta_y);
}
+ return false;
}
void OverscrollController::CompleteAction() {
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index 5577ce97f3d..a6287efd3bd 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -91,8 +91,9 @@ class OverscrollController {
// Processes horizontal overscroll. This can update both the overscroll mode
// and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_|
- // and |overscroll_delta_y_|).
- void ProcessOverscroll(float delta_x,
+ // and |overscroll_delta_y_|). Returns true if overscroll was handled by the
+ // delegate.
+ bool ProcessOverscroll(float delta_x,
float delta_y,
blink::WebInputEvent::Type event_type);
diff --git a/chromium/content/browser/renderer_host/overscroll_controller_delegate.h b/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
index 59295ce4127..54b5da18857 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller_delegate.h
@@ -23,8 +23,9 @@ class OverscrollControllerDelegate {
// events will only be processed if the visible bounds are non-empty.
virtual gfx::Rect GetVisibleBounds() const = 0;
- // This is called for each update in the overscroll amount.
- virtual void OnOverscrollUpdate(float delta_x, float delta_y) = 0;
+ // This is called for each update in the overscroll amount. Returns true if
+ // the delegate consumed the event.
+ virtual bool OnOverscrollUpdate(float delta_x, float delta_y) = 0;
// This is called when the overscroll completes.
virtual void OnOverscrollComplete(OverscrollMode overscroll_mode) = 0;
diff --git a/chromium/content/browser/renderer_host/p2p/OWNERS b/chromium/content/browser/renderer_host/p2p/OWNERS
index f12c2d60e83..49f36fb7949 100644
--- a/chromium/content/browser/renderer_host/p2p/OWNERS
+++ b/chromium/content/browser/renderer_host/p2p/OWNERS
@@ -1,3 +1,3 @@
hclam@chromium.org
-mallinath@chromium.org
sergeyu@chromium.org
+juberti@chromium.org
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index bb8c1fb9610..8bab6aff976 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -269,7 +269,7 @@ void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection(
void P2PSocketDispatcherHost::OnSend(int socket_id,
const net::IPEndPoint& socket_address,
const std::vector<char>& data,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 packet_id) {
P2PSocketHost* socket = LookupSocket(socket_id);
if (!socket) {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
index 21376bdd320..18b18df2272 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -22,7 +22,7 @@ namespace net {
class URLRequestContextGetter;
}
-namespace talk_base {
+namespace rtc {
struct PacketOptions;
}
@@ -39,12 +39,12 @@ class P2PSocketDispatcherHost
net::URLRequestContextGetter* url_context);
// content::BrowserMessageFilter overrides.
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// net::NetworkChangeNotifier::IPAddressObserver interface.
- virtual void OnIPAddressChanged() OVERRIDE;
+ void OnIPAddressChanged() override;
// Starts the RTP packet header dumping. Must be called on the IO thread.
void StartRtpDump(
@@ -56,7 +56,7 @@ class P2PSocketDispatcherHost
void StopRtpDumpOnUIThread(bool incoming, bool outgoing);
protected:
- virtual ~P2PSocketDispatcherHost();
+ ~P2PSocketDispatcherHost() override;
private:
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
@@ -84,7 +84,7 @@ class P2PSocketDispatcherHost
void OnSend(int socket_id,
const net::IPEndPoint& socket_address,
const std::vector<char>& data,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 packet_id);
void OnSetOption(int socket_id, P2PSocketOption option, int value);
void OnDestroySocket(int socket_id);
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.cc b/chromium/content/browser/renderer_host/p2p/socket_host.cc
index 007ab77a200..8f6e71f3c71 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/p2p/socket_host.h"
+#include "base/metrics/histogram.h"
#include "base/sys_byteorder.h"
#include "content/browser/renderer_host/p2p/socket_host_tcp.h"
#include "content/browser/renderer_host/p2p/socket_host_tcp_server.h"
@@ -11,20 +12,22 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/hmac.h"
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
-#include "third_party/libjingle/source/talk/base/byteorder.h"
-#include "third_party/libjingle/source/talk/base/messagedigest.h"
-#include "third_party/libjingle/source/talk/p2p/base/stun.h"
+#include "third_party/webrtc/base/asyncpacketsocket.h"
+#include "third_party/webrtc/base/byteorder.h"
+#include "third_party/webrtc/base/messagedigest.h"
+#include "third_party/webrtc/p2p/base/stun.h"
namespace {
const uint32 kStunMagicCookie = 0x2112A442;
-const int kMinRtpHdrLen = 12;
-const int kRtpExtnHdrLen = 4;
-const int kDtlsRecordHeaderLen = 13;
-const int kTurnChannelHdrLen = 4;
-const int kAbsSendTimeExtnLen = 3;
-const int kOneByteHdrLen = 1;
+const size_t kMinRtpHeaderLength = 12;
+const size_t kMinRtcpHeaderLength = 8;
+const size_t kRtpExtensionHeaderLength = 4;
+const size_t kDtlsRecordHeaderLength = 13;
+const size_t kTurnChannelHeaderLength = 4;
+const size_t kAbsSendTimeExtensionLength = 3;
+const size_t kOneByteHeaderLength = 1;
+const size_t kMaxRtpPacketLength = 2048;
// Fake auth tag written by the render process if external authentication is
// enabled. HMAC in packet will be compared against this value before updating
@@ -33,37 +36,50 @@ static const unsigned char kFakeAuthTag[10] = {
0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd
};
-bool IsTurnChannelData(const char* data) {
- return ((*data & 0xC0) == 0x40);
+bool IsTurnChannelData(const char* data, size_t length) {
+ return length >= kTurnChannelHeaderLength && ((*data & 0xC0) == 0x40);
}
-bool IsDtlsPacket(const char* data, int len) {
+bool IsDtlsPacket(const char* data, size_t length) {
const uint8* u = reinterpret_cast<const uint8*>(data);
- return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
+ return (length >= kDtlsRecordHeaderLength && (u[0] > 19 && u[0] < 64));
}
-bool IsRtcpPacket(const char* data) {
+bool IsRtcpPacket(const char* data, size_t length) {
+ if (length < kMinRtcpHeaderLength) {
+ return false;
+ }
+
int type = (static_cast<uint8>(data[1]) & 0x7F);
return (type >= 64 && type < 96);
}
-bool IsTurnSendIndicationPacket(const char* data) {
- uint16 type = talk_base::GetBE16(data);
+bool IsTurnSendIndicationPacket(const char* data, size_t length) {
+ if (length < content::P2PSocketHost::kStunHeaderSize) {
+ return false;
+ }
+
+ uint16 type = rtc::GetBE16(data);
return (type == cricket::TURN_SEND_INDICATION);
}
-bool IsRtpPacket(const char* data, int len) {
- return ((*data & 0xC0) == 0x80);
+bool IsRtpPacket(const char* data, size_t length) {
+ return (length >= kMinRtpHeaderLength) && ((*data & 0xC0) == 0x80);
}
// Verifies rtp header and message length.
-bool ValidateRtpHeader(const char* rtp, int length, size_t* header_length) {
- if (header_length)
+bool ValidateRtpHeader(const char* rtp, size_t length, size_t* header_length) {
+ if (header_length) {
*header_length = 0;
+ }
+
+ if (length < kMinRtpHeaderLength) {
+ return false;
+ }
- int cc_count = rtp[0] & 0x0F;
- int rtp_hdr_len_without_extn = kMinRtpHdrLen + 4 * cc_count;
- if (rtp_hdr_len_without_extn > length) {
+ size_t cc_count = rtp[0] & 0x0F;
+ size_t header_length_without_extension = kMinRtpHeaderLength + 4 * cc_count;
+ if (header_length_without_extension > length) {
return false;
}
@@ -71,29 +87,40 @@ bool ValidateRtpHeader(const char* rtp, int length, size_t* header_length) {
// length is verified above.
if (!(rtp[0] & 0x10)) {
if (header_length)
- *header_length = rtp_hdr_len_without_extn;
+ *header_length = header_length_without_extension;
return true;
}
- rtp += rtp_hdr_len_without_extn;
+ rtp += header_length_without_extension;
+
+ if (header_length_without_extension + kRtpExtensionHeaderLength > length) {
+ return false;
+ }
// Getting extension profile length.
// Length is in 32 bit words.
- uint16 extn_length = talk_base::GetBE16(rtp + 2) * 4;
+ uint16 extension_length_in_32bits = rtc::GetBE16(rtp + 2);
+ size_t extension_length = extension_length_in_32bits * 4;
+
+ size_t rtp_header_length = extension_length +
+ header_length_without_extension +
+ kRtpExtensionHeaderLength;
// Verify input length against total header size.
- if (rtp_hdr_len_without_extn + kRtpExtnHdrLen + extn_length > length) {
+ if (rtp_header_length > length) {
return false;
}
- if (header_length)
- *header_length = rtp_hdr_len_without_extn + kRtpExtnHdrLen + extn_length;
+ if (header_length) {
+ *header_length = rtp_header_length;
+ }
return true;
}
-void UpdateAbsSendTimeExtnValue(char* extn_data, int len,
- uint32 abs_send_time) {
+void UpdateAbsSendTimeExtensionValue(char* extension_data,
+ size_t length,
+ uint32 abs_send_time) {
// Absolute send time in RTP streams.
//
// The absolute send time is signaled to the receiver in-band using the
@@ -109,7 +136,11 @@ void UpdateAbsSendTimeExtnValue(char* extn_data, int len,
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ID | len=2 | absolute send time |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- DCHECK_EQ(len, kAbsSendTimeExtnLen);
+ if (length != kAbsSendTimeExtensionLength) {
+ NOTREACHED();
+ return;
+ }
+
// Now() has resolution ~1-15ms, using HighResNow(). But it is warned not to
// use it unless necessary, as it is expensive than Now().
uint32 now_second = abs_send_time;
@@ -121,24 +152,29 @@ void UpdateAbsSendTimeExtnValue(char* extn_data, int len,
((now_us << 18) / base::Time::kMicrosecondsPerSecond) & 0x00FFFFFF;
}
// TODO(mallinath) - Add SetBE24 to byteorder.h in libjingle.
- extn_data[0] = static_cast<uint8>(now_second >> 16);
- extn_data[1] = static_cast<uint8>(now_second >> 8);
- extn_data[2] = static_cast<uint8>(now_second);
+ extension_data[0] = static_cast<uint8>(now_second >> 16);
+ extension_data[1] = static_cast<uint8>(now_second >> 8);
+ extension_data[2] = static_cast<uint8>(now_second);
}
-// Assumes |len| is actual packet length + tag length. Updates HMAC at end of
+// Assumes |length| is actual packet length + tag length. Updates HMAC at end of
// the RTP packet.
-void UpdateRtpAuthTag(char* rtp, int len,
- const talk_base::PacketOptions& options) {
+void UpdateRtpAuthTag(char* rtp,
+ size_t length,
+ const rtc::PacketOptions& options) {
// If there is no key, return.
- if (options.packet_time_params.srtp_auth_key.empty())
+ if (options.packet_time_params.srtp_auth_key.empty()) {
return;
+ }
size_t tag_length = options.packet_time_params.srtp_auth_tag_len;
- char* auth_tag = rtp + (len - tag_length);
- // We should have a fake HMAC value @ auth_tag.
- DCHECK_EQ(0, memcmp(auth_tag, kFakeAuthTag, tag_length));
+ // ROC (rollover counter) is at the beginning of the auth tag.
+ const size_t kRocLength = 4;
+ if (tag_length < kRocLength || tag_length > length) {
+ NOTREACHED();
+ return;
+ }
crypto::HMAC hmac(crypto::HMAC::SHA1);
if (!hmac.Init(reinterpret_cast<const unsigned char*>(
@@ -148,15 +184,20 @@ void UpdateRtpAuthTag(char* rtp, int len,
return;
}
- if (hmac.DigestLength() < tag_length) {
+ if (tag_length > hmac.DigestLength()) {
NOTREACHED();
return;
}
+ char* auth_tag = rtp + (length - tag_length);
+
+ // We should have a fake HMAC value @ auth_tag.
+ DCHECK_EQ(0, memcmp(auth_tag, kFakeAuthTag, tag_length));
+
// Copy ROC after end of rtp packet.
- memcpy(auth_tag, &options.packet_time_params.srtp_packet_index, 4);
+ memcpy(auth_tag, &options.packet_time_params.srtp_packet_index, kRocLength);
// Authentication of a RTP packet will have RTP packet + ROC size.
- int auth_required_length = len - tag_length + 4;
+ int auth_required_length = length - tag_length + kRocLength;
unsigned char output[64];
if (!hmac.Sign(base::StringPiece(rtp, auth_required_length),
@@ -175,8 +216,9 @@ namespace content {
namespace packet_processing_helpers {
-bool ApplyPacketOptions(char* data, int length,
- const talk_base::PacketOptions& options,
+bool ApplyPacketOptions(char* data,
+ size_t length,
+ const rtc::PacketOptions& options,
uint32 abs_send_time) {
DCHECK(data != NULL);
DCHECK(length > 0);
@@ -188,13 +230,13 @@ bool ApplyPacketOptions(char* data, int length,
}
DCHECK(!IsDtlsPacket(data, length));
- DCHECK(!IsRtcpPacket(data));
+ DCHECK(!IsRtcpPacket(data, length));
// If there is a srtp auth key present then packet must be a RTP packet.
// RTP packet may have been wrapped in a TURN Channel Data or
// TURN send indication.
- int rtp_start_pos;
- int rtp_length;
+ size_t rtp_start_pos;
+ size_t rtp_length;
if (!GetRtpPacketStartPositionAndLength(
data, length, &rtp_start_pos, &rtp_length)) {
// This method should never return false.
@@ -208,9 +250,11 @@ bool ApplyPacketOptions(char* data, int length,
// then we should parse the rtp packet to update the timestamp. Otherwise
// just calculate HMAC and update packet with it.
if (options.packet_time_params.rtp_sendtime_extension_id != -1) {
- UpdateRtpAbsSendTimeExtn(
- start, rtp_length,
- options.packet_time_params.rtp_sendtime_extension_id, abs_send_time);
+ UpdateRtpAbsSendTimeExtension(
+ start,
+ rtp_length,
+ options.packet_time_params.rtp_sendtime_extension_id,
+ abs_send_time);
}
UpdateRtpAuthTag(start, rtp_length, options);
@@ -218,11 +262,16 @@ bool ApplyPacketOptions(char* data, int length,
}
bool GetRtpPacketStartPositionAndLength(const char* packet,
- int length,
- int* rtp_start_pos,
- int* rtp_packet_length) {
- int rtp_begin, rtp_length;
- if (IsTurnChannelData(packet)) {
+ size_t length,
+ size_t* rtp_start_pos,
+ size_t* rtp_packet_length) {
+ if (length < kMinRtpHeaderLength || length > kMaxRtpPacketLength) {
+ return false;
+ }
+
+ size_t rtp_begin;
+ size_t rtp_length = 0;
+ if (IsTurnChannelData(packet, length)) {
// Turn Channel Message header format.
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -233,32 +282,23 @@ bool GetRtpPacketStartPositionAndLength(const char* packet,
// / Application Data /
// / /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- if (length < kTurnChannelHdrLen) {
- return false;
- }
-
- rtp_begin = kTurnChannelHdrLen;
- rtp_length = talk_base::GetBE16(&packet[2]);
- if (length < rtp_length + kTurnChannelHdrLen) {
- return false;
- }
- } else if (IsTurnSendIndicationPacket(packet)) {
- if (length <= P2PSocketHost::kStunHeaderSize) {
- // Message must be greater than 20 bytes, if it's carrying any payload.
+ rtp_begin = kTurnChannelHeaderLength;
+ rtp_length = rtc::GetBE16(&packet[2]);
+ if (length < rtp_length + kTurnChannelHeaderLength) {
return false;
}
+ } else if (IsTurnSendIndicationPacket(packet, length)) {
// Validate STUN message length.
- int stun_msg_len = talk_base::GetBE16(&packet[2]);
- if (stun_msg_len + P2PSocketHost::kStunHeaderSize != length) {
+ const size_t stun_message_length = rtc::GetBE16(&packet[2]);
+ if (stun_message_length + P2PSocketHost::kStunHeaderSize != length) {
return false;
}
// First skip mandatory stun header which is of 20 bytes.
rtp_begin = P2PSocketHost::kStunHeaderSize;
// Loop through STUN attributes until we find STUN DATA attribute.
- const char* start = packet + rtp_begin;
bool data_attr_present = false;
- while ((packet + rtp_begin) - start < stun_msg_len) {
+ while (rtp_begin < length) {
// Keep reading STUN attributes until we hit DATA attribute.
// Attribute will be a TLV structure.
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -273,17 +313,26 @@ bool GetRtpPacketStartPositionAndLength(const char* packet,
// padding so that its value contains a multiple of 4 bytes. The
// padding bits are ignored, and may be any value.
uint16 attr_type, attr_length;
+ const int kAttrHeaderLength = sizeof(attr_type) + sizeof(attr_length);
+
+ if (length < rtp_begin + kAttrHeaderLength) {
+ return false;
+ }
+
// Getting attribute type and length.
- attr_type = talk_base::GetBE16(&packet[rtp_begin]);
- attr_length = talk_base::GetBE16(
+ attr_type = rtc::GetBE16(&packet[rtp_begin]);
+ attr_length = rtc::GetBE16(
&packet[rtp_begin + sizeof(attr_type)]);
+
+ rtp_begin += kAttrHeaderLength; // Skip STUN_DATA_ATTR header.
+
// Checking for bogus attribute length.
- if (length < attr_length + rtp_begin) {
+ if (length < rtp_begin + attr_length) {
return false;
}
if (attr_type != cricket::STUN_ATTR_DATA) {
- rtp_begin += sizeof(attr_type) + sizeof(attr_length) + attr_length;
+ rtp_begin += attr_length;
if ((attr_length % 4) != 0) {
rtp_begin += (4 - (attr_length % 4));
}
@@ -291,12 +340,8 @@ bool GetRtpPacketStartPositionAndLength(const char* packet,
}
data_attr_present = true;
- rtp_begin += 4; // Skip STUN_DATA_ATTR header.
rtp_length = attr_length;
- // One final check of length before exiting.
- if (length < rtp_length + rtp_begin) {
- return false;
- }
+
// We found STUN_DATA_ATTR. We can skip parsing rest of the packet.
break;
}
@@ -314,8 +359,7 @@ bool GetRtpPacketStartPositionAndLength(const char* packet,
}
// Making sure we have a valid RTP packet at the end.
- if (!(rtp_length < kMinRtpHdrLen) &&
- IsRtpPacket(packet + rtp_begin, rtp_length) &&
+ if (IsRtpPacket(packet + rtp_begin, rtp_length) &&
ValidateRtpHeader(packet + rtp_begin, rtp_length, NULL)) {
*rtp_start_pos = rtp_begin;
*rtp_packet_length = rtp_length;
@@ -326,8 +370,10 @@ bool GetRtpPacketStartPositionAndLength(const char* packet,
// ValidateRtpHeader must be called before this method to make sure, we have
// a sane rtp packet.
-bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
- int extension_id, uint32 abs_send_time) {
+bool UpdateRtpAbsSendTimeExtension(char* rtp,
+ size_t length,
+ int extension_id,
+ uint32 abs_send_time) {
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -346,17 +392,18 @@ bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
return true;
}
- int cc_count = rtp[0] & 0x0F;
- int rtp_hdr_len_without_extn = kMinRtpHdrLen + 4 * cc_count;
+ size_t cc_count = rtp[0] & 0x0F;
+ size_t header_length_without_extension = kMinRtpHeaderLength + 4 * cc_count;
- rtp += rtp_hdr_len_without_extn;
+ rtp += header_length_without_extension;
// Getting extension profile ID and length.
- uint16 profile_id = talk_base::GetBE16(rtp);
+ uint16 profile_id = rtc::GetBE16(rtp);
// Length is in 32 bit words.
- uint16 extn_length = talk_base::GetBE16(rtp + 2) * 4;
+ uint16 extension_length_in_32bits = rtc::GetBE16(rtp + 2);
+ size_t extension_length = extension_length_in_32bits * 4;
- rtp += kRtpExtnHdrLen; // Moving past extn header.
+ rtp += kRtpExtensionHeaderLength; // Moving past extension header.
bool found = false;
// WebRTC is using one byte header extension.
@@ -365,7 +412,7 @@ bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
// 0
// 0 1 2 3 4 5 6 7
// +-+-+-+-+-+-+-+-+
- // | ID | len |
+ // | ID |length |
// +-+-+-+-+-+-+-+-+
// 0 1 2 3
@@ -379,20 +426,26 @@ bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | data |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- char* extn_start = rtp;
- while (rtp - extn_start < extn_length) {
+ const char* extension_start = rtp;
+ const char* extension_end = extension_start + extension_length;
+
+ while (rtp < extension_end) {
const int id = (*rtp & 0xF0) >> 4;
- const int len = (*rtp & 0x0F) + 1;
+ const size_t length = (*rtp & 0x0F) + 1;
+ if (rtp + kOneByteHeaderLength + length > extension_end) {
+ return false;
+ }
// The 4-bit length is the number minus one of data bytes of this header
// extension element following the one-byte header.
if (id == extension_id) {
- UpdateAbsSendTimeExtnValue(rtp + kOneByteHdrLen, len, abs_send_time);
+ UpdateAbsSendTimeExtensionValue(
+ rtp + kOneByteHeaderLength, length, abs_send_time);
found = true;
break;
}
- rtp += kOneByteHdrLen + len;
+ rtp += kOneByteHeaderLength + length;
// Counting padding bytes.
- while ((*rtp == 0) && (rtp - extn_start < extn_length)) {
+ while ((rtp < extension_end) && (*rtp == 0)) {
++rtp;
}
}
@@ -402,32 +455,61 @@ bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
} // packet_processing_helpers
-P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender, int socket_id)
+P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender,
+ int socket_id,
+ ProtocolType protocol_type)
: message_sender_(message_sender),
id_(socket_id),
state_(STATE_UNINITIALIZED),
dump_incoming_rtp_packet_(false),
dump_outgoing_rtp_packet_(false),
- weak_ptr_factory_(this) {
+ weak_ptr_factory_(this),
+ protocol_type_(protocol_type),
+ send_packets_delayed_total_(0),
+ send_packets_total_(0),
+ send_bytes_delayed_max_(0),
+ send_bytes_delayed_cur_(0) {
}
-P2PSocketHost::~P2PSocketHost() { }
+P2PSocketHost::~P2PSocketHost() {
+ if (protocol_type_ == P2PSocketHost::UDP) {
+ UMA_HISTOGRAM_COUNTS_10000("WebRTC.SystemMaxConsecutiveBytesDelayed_UDP",
+ send_bytes_delayed_max_);
+ } else {
+ UMA_HISTOGRAM_COUNTS_10000("WebRTC.SystemMaxConsecutiveBytesDelayed_TCP",
+ send_bytes_delayed_max_);
+ }
+
+ if (send_packets_total_ > 0) {
+ int delay_rate = (send_packets_delayed_total_ * 100) / send_packets_total_;
+ if (protocol_type_ == P2PSocketHost::UDP) {
+ UMA_HISTOGRAM_PERCENTAGE("WebRTC.SystemPercentPacketsDelayed_UDP",
+ delay_rate);
+ } else {
+ UMA_HISTOGRAM_PERCENTAGE("WebRTC.SystemPercentPacketsDelayed_TCP",
+ delay_rate);
+ }
+ }
+}
// Verifies that the packet |data| has a valid STUN header.
// static
bool P2PSocketHost::GetStunPacketType(
const char* data, int data_size, StunMessageType* type) {
- if (data_size < kStunHeaderSize)
+ if (data_size < kStunHeaderSize) {
return false;
+ }
uint32 cookie = base::NetToHost32(*reinterpret_cast<const uint32*>(data + 4));
- if (cookie != kStunMagicCookie)
+ if (cookie != kStunMagicCookie) {
return false;
+ }
uint16 length = base::NetToHost16(*reinterpret_cast<const uint16*>(data + 2));
- if (length != data_size - kStunHeaderSize)
+ if (length != data_size - kStunHeaderSize) {
return false;
+ }
int message_type = base::NetToHost16(*reinterpret_cast<const uint16*>(data));
@@ -501,11 +583,13 @@ void P2PSocketHost::StartRtpDump(
DCHECK(!packet_callback.is_null());
DCHECK(incoming || outgoing);
- if (incoming)
+ if (incoming) {
dump_incoming_rtp_packet_ = true;
+ }
- if (outgoing)
+ if (outgoing) {
dump_outgoing_rtp_packet_ = true;
+ }
packet_dump_callback_ = packet_callback;
}
@@ -514,27 +598,32 @@ void P2PSocketHost::StopRtpDump(bool incoming, bool outgoing) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(incoming || outgoing);
- if (incoming)
+ if (incoming) {
dump_incoming_rtp_packet_ = false;
+ }
- if (outgoing)
+ if (outgoing) {
dump_outgoing_rtp_packet_ = false;
+ }
- if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_)
+ if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_) {
packet_dump_callback_.Reset();
+ }
}
void P2PSocketHost::DumpRtpPacket(const char* packet,
size_t length,
bool incoming) {
- if (IsDtlsPacket(packet, length) || IsRtcpPacket(packet))
+ if (IsDtlsPacket(packet, length) || IsRtcpPacket(packet, length)) {
return;
+ }
- int rtp_packet_pos = 0;
- int rtp_packet_length = length;
+ size_t rtp_packet_pos = 0;
+ size_t rtp_packet_length = length;
if (!packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- packet, length, &rtp_packet_pos, &rtp_packet_length))
+ packet, length, &rtp_packet_pos, &rtp_packet_length)) {
return;
+ }
packet += rtp_packet_pos;
@@ -582,4 +671,24 @@ void P2PSocketHost::DumpRtpPacketOnIOThread(scoped_ptr<uint8[]> packet_header,
incoming));
}
+void P2PSocketHost::IncrementDelayedPackets() {
+ send_packets_delayed_total_++;
+}
+
+void P2PSocketHost::IncrementTotalSentPackets() {
+ send_packets_total_++;
+}
+
+void P2PSocketHost::IncrementDelayedBytes(uint32 size) {
+ send_bytes_delayed_cur_ += size;
+ if (send_bytes_delayed_cur_ > send_bytes_delayed_max_) {
+ send_bytes_delayed_max_ = send_bytes_delayed_cur_;
+ }
+}
+
+void P2PSocketHost::DecrementDelayedBytes(uint32 size) {
+ send_bytes_delayed_cur_ -= size;
+ DCHECK_GE(send_bytes_delayed_cur_, 0);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index bfcbbd229f1..390c115efb6 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -20,7 +20,7 @@ namespace net {
class URLRequestContextGetter;
}
-namespace talk_base {
+namespace rtc {
struct PacketOptions;
}
@@ -33,20 +33,24 @@ namespace packet_processing_helpers {
// called. It will try to do, 1. update absolute send time extension header
// if present with current time and 2. update HMAC in RTP packet.
// If abs_send_time is 0, ApplyPacketOption will get current time from system.
-CONTENT_EXPORT bool ApplyPacketOptions(char* data, int length,
- const talk_base::PacketOptions& options,
+CONTENT_EXPORT bool ApplyPacketOptions(char* data,
+ size_t length,
+ const rtc::PacketOptions& options,
uint32 abs_send_time);
// Helper method which finds RTP ofset and length if the packet is encapsulated
// in a TURN Channel Message or TURN Send Indication message.
-CONTENT_EXPORT bool GetRtpPacketStartPositionAndLength(const char* data,
- int length,
- int* rtp_start_pos,
- int* rtp_packet_length);
+CONTENT_EXPORT bool GetRtpPacketStartPositionAndLength(
+ const char* data,
+ size_t length,
+ size_t* rtp_start_pos,
+ size_t* rtp_packet_length);
+
// Helper method which updates absoulute send time extension if present.
-CONTENT_EXPORT bool UpdateRtpAbsSendTimeExtn(char* rtp, int length,
- int extension_id,
- uint32 abs_send_time);
+CONTENT_EXPORT bool UpdateRtpAbsSendTimeExtension(char* rtp,
+ size_t length,
+ int extension_id,
+ uint32 abs_send_time);
} // packet_processing_helpers
@@ -70,7 +74,7 @@ class CONTENT_EXPORT P2PSocketHost {
// Sends |data| on the socket to |to|.
virtual void Send(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 packet_id) = 0;
virtual P2PSocketHost* AcceptIncomingTcpConnection(
@@ -87,6 +91,9 @@ class CONTENT_EXPORT P2PSocketHost {
protected:
friend class P2PSocketHostTcpTestBase;
+ // This should match suffix IPProtocolType defined in histograms.xml.
+ enum ProtocolType { UDP = 0x1, TCP = 0x2 };
+
// TODO(mallinath) - Remove this below enum and use one defined in
// libjingle/souce/talk/p2p/base/stun.h
enum StunMessageType {
@@ -121,7 +128,9 @@ class CONTENT_EXPORT P2PSocketHost {
STATE_ERROR,
};
- P2PSocketHost(IPC::Sender* message_sender, int socket_id);
+ P2PSocketHost(IPC::Sender* message_sender,
+ int socket_id,
+ ProtocolType protocol_type);
// Verifies that the packet |data| has a valid STUN header. In case
// of success stores type of the message in |type|.
@@ -138,6 +147,12 @@ class CONTENT_EXPORT P2PSocketHost {
size_t packet_length,
bool incoming);
+ // Used by subclasses to track the metrics of delayed bytes and packets.
+ void IncrementDelayedPackets();
+ void IncrementTotalSentPackets();
+ void IncrementDelayedBytes(uint32 size);
+ void DecrementDelayedBytes(uint32 size);
+
IPC::Sender* message_sender_;
int id_;
State state_;
@@ -147,6 +162,19 @@ class CONTENT_EXPORT P2PSocketHost {
base::WeakPtrFactory<P2PSocketHost> weak_ptr_factory_;
+ ProtocolType protocol_type_;
+
+ private:
+ // Track total delayed packets for calculating how many packets are
+ // delayed by system at the end of call.
+ uint32 send_packets_delayed_total_;
+ uint32 send_packets_total_;
+
+ // Track the maximum of consecutive delayed bytes caused by system's
+ // EWOULDBLOCK.
+ int32 send_bytes_delayed_max_;
+ int32 send_bytes_delayed_cur_;
+
DISALLOW_COPY_AND_ASSIGN(P2PSocketHost);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
index 978f6269f5d..79f7b14b0b8 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -18,7 +18,7 @@
#include "net/socket/tcp_client_socket.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
+#include "third_party/webrtc/base/asyncpacketsocket.h"
namespace {
@@ -49,7 +49,7 @@ P2PSocketHostTcpBase::P2PSocketHostTcpBase(
int socket_id,
P2PSocketType type,
net::URLRequestContextGetter* url_context)
- : P2PSocketHost(message_sender, socket_id),
+ : P2PSocketHost(message_sender, socket_id, P2PSocketHost::TCP),
write_pending_(false),
connected_(false),
type_(type),
@@ -83,8 +83,18 @@ bool P2PSocketHostTcpBase::Init(const net::IPEndPoint& local_address,
remote_address_ = remote_address;
state_ = STATE_CONNECTING;
- net::HostPortPair dest_host_port_pair =
- net::HostPortPair::FromIPEndPoint(remote_address.ip_address);
+ net::HostPortPair dest_host_port_pair;
+ // If there is no resolved address, let's try with domain name, assuming
+ // socket layer will do the DNS resolve.
+ if (remote_address.ip_address.address().empty()) {
+ DCHECK(!remote_address.hostname.empty());
+ dest_host_port_pair = net::HostPortPair(remote_address.hostname,
+ remote_address.ip_address.port());
+ } else {
+ dest_host_port_pair = net::HostPortPair::FromIPEndPoint(
+ remote_address.ip_address);
+ }
+
// TODO(mallinath) - We are ignoring local_address altogether. We should
// find a way to inject this into ProxyResolvingClientSocket. This could be
// a problem on multi-homed host.
@@ -175,8 +185,15 @@ void P2PSocketHostTcpBase::StartTls() {
// Default ssl config.
const net::SSLConfig ssl_config;
- net::HostPortPair dest_host_port_pair =
+ net::HostPortPair dest_host_port_pair;
+
+ // Calling net::HostPortPair::FromIPEndPoint will crash if the IP address is
+ // empty.
+ if (!remote_address_.ip_address.address().empty()) {
net::HostPortPair::FromIPEndPoint(remote_address_.ip_address);
+ } else {
+ dest_host_port_pair.set_port(remote_address_.ip_address.port());
+ }
if (!remote_address_.hostname.empty())
dest_host_port_pair.set_host(remote_address_.hostname);
@@ -217,29 +234,48 @@ void P2PSocketHostTcpBase::OnOpen() {
<< kSendSocketBufferSize;
}
- DoSendSocketCreateMsg();
+ if (!DoSendSocketCreateMsg())
+ return;
+
+ DCHECK_EQ(state_, STATE_OPEN);
DoRead();
}
-void P2PSocketHostTcpBase::DoSendSocketCreateMsg() {
+bool P2PSocketHostTcpBase::DoSendSocketCreateMsg() {
DCHECK(socket_.get());
- net::IPEndPoint address;
- int result = socket_->GetLocalAddress(&address);
+ net::IPEndPoint local_address;
+ int result = socket_->GetLocalAddress(&local_address);
if (result < 0) {
LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get local"
<< " address: " << result;
OnError();
- return;
+ return false;
}
- VLOG(1) << "Local address: " << address.ToString();
+ VLOG(1) << "Local address: " << local_address.ToString();
+
+ net::IPEndPoint remote_address;
+ result = socket_->GetPeerAddress(&remote_address);
+ if (result < 0) {
+ LOG(ERROR) << "P2PSocketHostTcpBase::OnConnected: unable to get peer"
+ << " address: " << result;
+ OnError();
+ return false;
+ }
+ VLOG(1) << "Remote address: " << remote_address.ToString();
+ if (remote_address_.ip_address.address().empty()) {
+ // Save |remote_address| if address is empty.
+ remote_address_.ip_address = remote_address;
+ }
// If we are not doing TLS, we are ready to send data now.
// In case of TLS SignalConnect will be sent only after TLS handshake is
// successfull. So no buffering will be done at socket handlers if any
// packets sent before that by the application.
- message_sender_->Send(new P2PMsg_OnSocketCreated(id_, address));
+ message_sender_->Send(new P2PMsg_OnSocketCreated(
+ id_, local_address, remote_address));
+ return true;
}
void P2PSocketHostTcpBase::DoRead() {
@@ -298,7 +334,7 @@ void P2PSocketHostTcpBase::OnPacket(const std::vector<char>& data) {
// but may be honored in the future.
void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 packet_id) {
if (!socket_) {
// The Send message may be sent after the an OnError message was
@@ -329,8 +365,11 @@ void P2PSocketHostTcpBase::Send(const net::IPEndPoint& to,
void P2PSocketHostTcpBase::WriteOrQueue(
scoped_refptr<net::DrainableIOBuffer>& buffer) {
+ IncrementTotalSentPackets();
if (write_buffer_.get()) {
write_queue_.push(buffer);
+ IncrementDelayedPackets();
+ IncrementDelayedBytes(buffer->size());
return;
}
@@ -368,6 +407,8 @@ void P2PSocketHostTcpBase::HandleWriteResult(int result) {
} else {
write_buffer_ = write_queue_.front();
write_queue_.pop();
+ // Update how many bytes are still waiting to be sent.
+ DecrementDelayedBytes(write_buffer_->size());
}
}
} else if (result == net::ERR_IO_PENDING) {
@@ -458,7 +499,7 @@ int P2PSocketHostTcp::ProcessInput(char* input, int input_len) {
void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options) {
+ const rtc::PacketOptions& options) {
int size = kPacketHeaderSize + data.size();
scoped_refptr<net::DrainableIOBuffer> buffer =
new net::DrainableIOBuffer(new net::IOBuffer(size), size);
@@ -511,7 +552,7 @@ int P2PSocketHostStunTcp::ProcessInput(char* input, int input_len) {
void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options) {
+ const rtc::PacketOptions& options) {
// Each packet is expected to have header (STUN/TURN ChannelData), where
// header contains message type and and length of message.
if (data.size() < kPacketHeaderSize + kPacketLengthOffset) {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
index f5ff8633b06..4c2bb313f93 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.h
@@ -32,28 +32,29 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
int socket_id,
P2PSocketType type,
net::URLRequestContextGetter* url_context);
- virtual ~P2PSocketHostTcpBase();
+ ~P2PSocketHostTcpBase() override;
bool InitAccepted(const net::IPEndPoint& remote_address,
net::StreamSocket* socket);
// P2PSocketHost overrides.
- virtual bool Init(const net::IPEndPoint& local_address,
- const P2PHostAndIPEndPoint& remote_address) OVERRIDE;
- virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const talk_base::PacketOptions& options,
- uint64 packet_id) OVERRIDE;
- virtual P2PSocketHost* AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address, int id) OVERRIDE;
- virtual bool SetOption(P2PSocketOption option, int value) OVERRIDE;
+ bool Init(const net::IPEndPoint& local_address,
+ const P2PHostAndIPEndPoint& remote_address) override;
+ void Send(const net::IPEndPoint& to,
+ const std::vector<char>& data,
+ const rtc::PacketOptions& options,
+ uint64 packet_id) override;
+ P2PSocketHost* AcceptIncomingTcpConnection(
+ const net::IPEndPoint& remote_address,
+ int id) override;
+ bool SetOption(P2PSocketOption option, int value) override;
protected:
// Derived classes will provide the implementation.
virtual int ProcessInput(char* input, int input_len) = 0;
virtual void DoSend(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options) = 0;
+ const rtc::PacketOptions& options) = 0;
void WriteOrQueue(scoped_refptr<net::DrainableIOBuffer>& buffer);
void OnPacket(const std::vector<char>& data);
@@ -80,7 +81,7 @@ class CONTENT_EXPORT P2PSocketHostTcpBase : public P2PSocketHost {
// Helper method to send socket create message and start read.
void OnOpen();
- void DoSendSocketCreateMsg();
+ bool DoSendSocketCreateMsg();
P2PHostAndIPEndPoint remote_address_;
@@ -104,13 +105,14 @@ class CONTENT_EXPORT P2PSocketHostTcp : public P2PSocketHostTcpBase {
int socket_id,
P2PSocketType type,
net::URLRequestContextGetter* url_context);
- virtual ~P2PSocketHostTcp();
+ ~P2PSocketHostTcp() override;
protected:
- virtual int ProcessInput(char* input, int input_len) OVERRIDE;
- virtual void DoSend(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const talk_base::PacketOptions& options) OVERRIDE;
+ int ProcessInput(char* input, int input_len) override;
+ void DoSend(const net::IPEndPoint& to,
+ const std::vector<char>& data,
+ const rtc::PacketOptions& options) override;
+
private:
DISALLOW_COPY_AND_ASSIGN(P2PSocketHostTcp);
};
@@ -126,13 +128,14 @@ class CONTENT_EXPORT P2PSocketHostStunTcp : public P2PSocketHostTcpBase {
P2PSocketType type,
net::URLRequestContextGetter* url_context);
- virtual ~P2PSocketHostStunTcp();
+ ~P2PSocketHostStunTcp() override;
protected:
- virtual int ProcessInput(char* input, int input_len) OVERRIDE;
- virtual void DoSend(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const talk_base::PacketOptions& options) OVERRIDE;
+ int ProcessInput(char* input, int input_len) override;
+ void DoSend(const net::IPEndPoint& to,
+ const std::vector<char>& data,
+ const rtc::PacketOptions& options) override;
+
private:
int GetExpectedPacketSize(const char* data, int len, int* pad_bytes);
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
index 2418de9e87c..0976b22ad2b 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
@@ -23,7 +23,7 @@ namespace content {
P2PSocketHostTcpServer::P2PSocketHostTcpServer(IPC::Sender* message_sender,
int socket_id,
P2PSocketType client_type)
- : P2PSocketHost(message_sender, socket_id),
+ : P2PSocketHost(message_sender, socket_id, P2PSocketHost::TCP),
client_type_(client_type),
socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
accept_callback_(base::Bind(&P2PSocketHostTcpServer::OnAccepted,
@@ -61,7 +61,10 @@ bool P2PSocketHostTcpServer::Init(const net::IPEndPoint& local_address,
VLOG(1) << "Local address: " << local_address_.ToString();
state_ = STATE_OPEN;
- message_sender_->Send(new P2PMsg_OnSocketCreated(id_, local_address_));
+ // NOTE: Remote address can be empty as socket is just listening
+ // in this state.
+ message_sender_->Send(new P2PMsg_OnSocketCreated(
+ id_, local_address_, remote_address.ip_address));
DoAccept();
return true;
}
@@ -116,7 +119,7 @@ void P2PSocketHostTcpServer::OnAccepted(int result) {
void P2PSocketHostTcpServer::Send(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 packet_id) {
NOTREACHED();
OnError();
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
index e050b00fa06..df2053224fa 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.h
@@ -31,19 +31,19 @@ class CONTENT_EXPORT P2PSocketHostTcpServer : public P2PSocketHost {
P2PSocketHostTcpServer(IPC::Sender* message_sender,
int socket_id,
P2PSocketType client_type);
- virtual ~P2PSocketHostTcpServer();
+ ~P2PSocketHostTcpServer() override;
// P2PSocketHost overrides.
- virtual bool Init(const net::IPEndPoint& local_address,
- const P2PHostAndIPEndPoint& remote_address) OVERRIDE;
- virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const talk_base::PacketOptions& options,
- uint64 packet_id) OVERRIDE;
- virtual P2PSocketHost* AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address, int id) OVERRIDE;
- virtual bool SetOption(P2PSocketOption option, int value) OVERRIDE;
-
+ bool Init(const net::IPEndPoint& local_address,
+ const P2PHostAndIPEndPoint& remote_address) override;
+ void Send(const net::IPEndPoint& to,
+ const std::vector<char>& data,
+ const rtc::PacketOptions& options,
+ uint64 packet_id) override;
+ P2PSocketHost* AcceptIncomingTcpConnection(
+ const net::IPEndPoint& remote_address,
+ int id) override;
+ bool SetOption(P2PSocketOption option, int value) override;
private:
friend class P2PSocketHostTcpServerTest;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
index 270fad90cb1..64b420b8b8b 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc
@@ -26,7 +26,7 @@ class FakeServerSocket : public net::ServerSocket {
accept_socket_(NULL) {
}
- virtual ~FakeServerSocket() {}
+ ~FakeServerSocket() override {}
bool listening() { return listening_; }
@@ -47,19 +47,19 @@ class FakeServerSocket : public net::ServerSocket {
}
}
- virtual int Listen(const net::IPEndPoint& address, int backlog) OVERRIDE {
+ int Listen(const net::IPEndPoint& address, int backlog) override {
local_address_ = address;
listening_ = true;
return net::OK;
}
- virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE {
+ int GetLocalAddress(net::IPEndPoint* address) const override {
*address = local_address_;
return net::OK;
}
- virtual int Accept(scoped_ptr<net::StreamSocket>* socket,
- const net::CompletionCallback& callback) OVERRIDE {
+ int Accept(scoped_ptr<net::StreamSocket>* socket,
+ const net::CompletionCallback& callback) override {
DCHECK(socket);
if (!incoming_sockets_.empty()) {
socket->reset(incoming_sockets_.front());
@@ -89,7 +89,7 @@ namespace content {
class P2PSocketHostTcpServerTest : public testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
socket_ = new FakeServerSocket();
socket_host_.reset(
new P2PSocketHostTcpServer(&sender_, 0, P2P_SOCKET_TCP_CLIENT));
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 24b77c3adbe..cd5a9093aa7 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -25,7 +25,7 @@ class P2PSocketHostTcpTestBase : public testing::Test {
: socket_type_(type) {
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
EXPECT_CALL(sender_, Send(
MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
@@ -89,7 +89,7 @@ TEST_F(P2PSocketHostTcpTest, SendStunNoAuth) {
.Times(3)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
socket_host_->Send(dest_.ip_address, packet1, options, 0);
@@ -121,7 +121,7 @@ TEST_F(P2PSocketHostTcpTest, ReceiveStun) {
.Times(3)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
socket_host_->Send(dest_.ip_address, packet1, options, 0);
@@ -168,7 +168,7 @@ TEST_F(P2PSocketHostTcpTest, SendDataNoAuth) {
MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet;
CreateRandomPacket(&packet);
socket_host_->Send(dest_.ip_address, packet, options, 0);
@@ -194,7 +194,7 @@ TEST_F(P2PSocketHostTcpTest, SendAfterStunRequest) {
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
socket_->AppendInputData(&received_data[0], received_data.size());
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
// Now we should be able to send any data to |dest_|.
std::vector<char> packet;
CreateRandomPacket(&packet);
@@ -218,7 +218,7 @@ TEST_F(P2PSocketHostTcpTest, AsyncWrites) {
.Times(2)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
@@ -254,7 +254,7 @@ TEST_F(P2PSocketHostTcpTest, SendDataWithPacketOptions) {
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
socket_->AppendInputData(&received_data[0], received_data.size());
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
options.packet_time_params.rtp_sendtime_extension_id = 3;
// Now we should be able to send any data to |dest_|.
std::vector<char> packet;
@@ -278,7 +278,7 @@ TEST_F(P2PSocketHostStunTcpTest, SendStunNoAuth) {
.Times(3)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
socket_host_->Send(dest_.ip_address, packet1, options, 0);
@@ -307,7 +307,7 @@ TEST_F(P2PSocketHostStunTcpTest, ReceiveStun) {
.Times(3)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
socket_host_->Send(dest_.ip_address, packet1, options, 0);
@@ -351,7 +351,7 @@ TEST_F(P2PSocketHostStunTcpTest, SendDataNoAuth) {
MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet;
CreateRandomPacket(&packet);
socket_host_->Send(dest_.ip_address, packet, options, 0);
@@ -370,7 +370,7 @@ TEST_F(P2PSocketHostStunTcpTest, AsyncWrites) {
.Times(2)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
socket_host_->Send(dest_.ip_address, packet1, options, 0);
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
index b27b55b9982..acab45ff25f 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
@@ -31,7 +31,7 @@ class MockIPCSender : public IPC::Sender {
class FakeSocket : public net::StreamSocket {
public:
FakeSocket(std::string* written_data);
- virtual ~FakeSocket();
+ ~FakeSocket() override;
void set_async_write(bool async_write) { async_write_ = async_write; }
void AppendInputData(const char* data, int data_size);
@@ -41,26 +41,28 @@ class FakeSocket : public net::StreamSocket {
void SetLocalAddress(const net::IPEndPoint& local_address);
// net::Socket implementation.
- virtual int Read(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback) OVERRIDE;
- virtual int Write(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback) OVERRIDE;
- virtual int SetReceiveBufferSize(int32 size) OVERRIDE;
- virtual int SetSendBufferSize(int32 size) OVERRIDE;
- virtual int Connect(const net::CompletionCallback& callback) OVERRIDE;
- virtual void Disconnect() OVERRIDE;
- virtual bool IsConnected() const OVERRIDE;
- virtual bool IsConnectedAndIdle() const OVERRIDE;
- virtual int GetPeerAddress(net::IPEndPoint* address) const OVERRIDE;
- virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE;
- virtual const net::BoundNetLog& NetLog() const OVERRIDE;
- virtual void SetSubresourceSpeculation() OVERRIDE;
- virtual void SetOmniboxSpeculation() OVERRIDE;
- virtual bool WasEverUsed() const OVERRIDE;
- virtual bool UsingTCPFastOpen() const OVERRIDE;
- virtual bool WasNpnNegotiated() const OVERRIDE;
- virtual net::NextProto GetNegotiatedProtocol() const OVERRIDE;
- virtual bool GetSSLInfo(net::SSLInfo* ssl_info) OVERRIDE;
+ int Read(net::IOBuffer* buf,
+ int buf_len,
+ const net::CompletionCallback& callback) override;
+ int Write(net::IOBuffer* buf,
+ int buf_len,
+ const net::CompletionCallback& callback) override;
+ int SetReceiveBufferSize(int32 size) override;
+ int SetSendBufferSize(int32 size) override;
+ int Connect(const net::CompletionCallback& callback) override;
+ void Disconnect() override;
+ bool IsConnected() const override;
+ bool IsConnectedAndIdle() const override;
+ int GetPeerAddress(net::IPEndPoint* address) const override;
+ int GetLocalAddress(net::IPEndPoint* address) const override;
+ const net::BoundNetLog& NetLog() const override;
+ void SetSubresourceSpeculation() override;
+ void SetOmniboxSpeculation() override;
+ bool WasEverUsed() const override;
+ bool UsingTCPFastOpen() const override;
+ bool WasNpnNegotiated() const override;
+ net::NextProto GetNegotiatedProtocol() const override;
+ bool GetSSLInfo(net::SSLInfo* ssl_info) override;
private:
void DoAsyncWrite(scoped_refptr<net::IOBuffer> buf, int buf_len,
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
index 50a4dd0ac83..0ef92eb8a6f 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
-#include "third_party/libjingle/source/talk/base/ratelimiter.h"
-#include "third_party/libjingle/source/talk/base/timing.h"
+#include "third_party/webrtc/base/ratelimiter.h"
+#include "third_party/webrtc/base/timing.h"
namespace content {
@@ -16,19 +16,19 @@ const int kMaxIceMessageBandwidth = 256 * 1024;
P2PMessageThrottler::P2PMessageThrottler()
- : timing_(new talk_base::Timing()),
- rate_limiter_(new talk_base::RateLimiter(kMaxIceMessageBandwidth, 1.0)) {
+ : timing_(new rtc::Timing()),
+ rate_limiter_(new rtc::RateLimiter(kMaxIceMessageBandwidth, 1.0)) {
}
P2PMessageThrottler::~P2PMessageThrottler() {
}
-void P2PMessageThrottler::SetTiming(scoped_ptr<talk_base::Timing> timing) {
+void P2PMessageThrottler::SetTiming(scoped_ptr<rtc::Timing> timing) {
timing_ = timing.Pass();
}
void P2PMessageThrottler::SetSendIceBandwidth(int bandwidth_kbps) {
- rate_limiter_.reset(new talk_base::RateLimiter(bandwidth_kbps, 1.0));
+ rate_limiter_.reset(new rtc::RateLimiter(bandwidth_kbps, 1.0));
}
bool P2PMessageThrottler::DropNextPacket(size_t packet_len) {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
index 166d30054f5..a28a5885621 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_throttler.h
@@ -8,7 +8,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
-namespace talk_base {
+namespace rtc {
class RateLimiter;
class Timing;
}
@@ -24,13 +24,13 @@ class CONTENT_EXPORT P2PMessageThrottler {
P2PMessageThrottler();
virtual ~P2PMessageThrottler();
- void SetTiming(scoped_ptr<talk_base::Timing> timing);
+ void SetTiming(scoped_ptr<rtc::Timing> timing);
bool DropNextPacket(size_t packet_len);
void SetSendIceBandwidth(int bandwith_kbps);
private:
- scoped_ptr<talk_base::Timing> timing_;
- scoped_ptr<talk_base::RateLimiter> rate_limiter_;
+ scoped_ptr<rtc::Timing> timing_;
+ scoped_ptr<rtc::RateLimiter> rate_limiter_;
DISALLOW_COPY_AND_ASSIGN(P2PMessageThrottler);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
index 5dad882629f..29883179715 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -6,7 +6,10 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "content/browser/renderer_host/p2p/socket_host_throttler.h"
#include "content/common/p2p_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -15,7 +18,7 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
+#include "third_party/webrtc/base/asyncpacketsocket.h"
namespace {
@@ -52,7 +55,7 @@ namespace content {
P2PSocketHostUdp::PendingPacket::PendingPacket(
const net::IPEndPoint& to,
const std::vector<char>& content,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 id)
: to(to),
data(new net::IOBuffer(content.size())),
@@ -68,7 +71,7 @@ P2PSocketHostUdp::PendingPacket::~PendingPacket() {
P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender,
int socket_id,
P2PMessageThrottler* throttler)
- : P2PSocketHost(message_sender, socket_id),
+ : P2PSocketHost(message_sender, socket_id, P2PSocketHost::UDP),
socket_(
new net::UDPServerSocket(GetContentClient()->browser()->GetNetLog(),
net::NetLog::Source())),
@@ -84,6 +87,21 @@ P2PSocketHostUdp::~P2PSocketHostUdp() {
}
}
+void P2PSocketHostUdp::SetSendBufferSize() {
+ unsigned int send_buffer_size = 0;
+
+ base::StringToUint(
+ base::FieldTrialList::FindFullName("WebRTC-SystemUDPSendSocketSize"),
+ &send_buffer_size);
+
+ if (send_buffer_size > 0) {
+ if (!SetOption(P2P_SOCKET_OPT_SNDBUF, send_buffer_size)) {
+ LOG(WARNING) << "Failed to set socket send buffer size to "
+ << send_buffer_size;
+ }
+ }
+}
+
bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
const P2PHostAndIPEndPoint& remote_address) {
DCHECK_EQ(state_, STATE_UNINITIALIZED);
@@ -113,7 +131,11 @@ bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
state_ = STATE_OPEN;
- message_sender_->Send(new P2PMsg_OnSocketCreated(id_, address));
+ SetSendBufferSize();
+
+ // NOTE: Remote address will be same as what renderer provided.
+ message_sender_->Send(new P2PMsg_OnSocketCreated(
+ id_, address, remote_address.ip_address));
recv_buffer_ = new net::IOBuffer(kReadBufferSize);
DoRead();
@@ -184,7 +206,7 @@ void P2PSocketHostUdp::HandleReadResult(int result) {
void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
const std::vector<char>& data,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 packet_id) {
if (!socket_) {
// The Send message may be sent after the an OnError message was
@@ -209,8 +231,12 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
}
}
+ IncrementTotalSentPackets();
+
if (send_pending_) {
send_queue_.push_back(PendingPacket(to, data, options, packet_id));
+ IncrementDelayedBytes(data.size());
+ IncrementDelayedPackets();
} else {
// TODO(mallinath: Remove unnecessary memcpy in this case.
PendingPacket packet(to, data, options, packet_id);
@@ -239,52 +265,64 @@ void P2PSocketHostUdp::DoSend(const PendingPacket& packet) {
last_dscp_ = net::DSCP_NO_CHANGE;
}
}
+
+ uint64 tick_received = base::TimeTicks::Now().ToInternalValue();
+
packet_processing_helpers::ApplyPacketOptions(
packet.data->data(), packet.size, packet.packet_options, 0);
- int result = socket_->SendTo(
- packet.data.get(),
- packet.size,
- packet.to,
- base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id));
+ int result = socket_->SendTo(packet.data.get(),
+ packet.size,
+ packet.to,
+ base::Bind(&P2PSocketHostUdp::OnSend,
+ base::Unretained(this),
+ packet.id,
+ tick_received));
// sendto() may return an error, e.g. if we've received an ICMP Destination
// Unreachable message. When this happens try sending the same packet again,
// and just drop it if it fails again.
if (IsTransientError(result)) {
- result = socket_->SendTo(
- packet.data.get(),
- packet.size,
- packet.to,
- base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this),
- packet.id));
+ result = socket_->SendTo(packet.data.get(),
+ packet.size,
+ packet.to,
+ base::Bind(&P2PSocketHostUdp::OnSend,
+ base::Unretained(this),
+ packet.id,
+ tick_received));
}
if (result == net::ERR_IO_PENDING) {
send_pending_ = true;
} else {
- HandleSendResult(packet.id, result);
+ HandleSendResult(packet.id, tick_received, result);
}
if (dump_outgoing_rtp_packet_)
DumpRtpPacket(packet.data->data(), packet.size, false);
}
-void P2PSocketHostUdp::OnSend(uint64 packet_id, int result) {
+void P2PSocketHostUdp::OnSend(uint64 packet_id,
+ uint64 tick_received,
+ int result) {
DCHECK(send_pending_);
DCHECK_NE(result, net::ERR_IO_PENDING);
send_pending_ = false;
- HandleSendResult(packet_id, result);
+ HandleSendResult(packet_id, tick_received, result);
// Send next packets if we have them waiting in the buffer.
while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
- DoSend(send_queue_.front());
+ PendingPacket packet = send_queue_.front();
+ DoSend(packet);
send_queue_.pop_front();
+ DecrementDelayedBytes(packet.size);
}
}
-void P2PSocketHostUdp::HandleSendResult(uint64 packet_id, int result) {
+void P2PSocketHostUdp::HandleSendResult(uint64 packet_id,
+ uint64 tick_received,
+ int result) {
TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
"result", result);
if (result < 0) {
@@ -296,6 +334,14 @@ void P2PSocketHostUdp::HandleSendResult(uint64 packet_id, int result) {
VLOG(0) << "sendto() has failed twice returning a "
" transient error. Dropping the packet.";
}
+
+ // UMA to track the histograms from 1ms to 1 sec for how long a packet spends
+ // in the browser process.
+ UMA_HISTOGRAM_TIMES(
+ "WebRTC.SystemSendPacketDuration_UDP" /* name */,
+ base::TimeTicks::Now() -
+ base::TimeTicks::FromInternalValue(tick_received) /* sample */);
+
message_sender_->Send(new P2PMsg_OnSendComplete(id_));
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
index b22795c059d..f0b04a65496 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -18,7 +18,7 @@
#include "content/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
#include "net/udp/udp_server_socket.h"
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
+#include "third_party/webrtc/base/asyncpacketsocket.h"
namespace content {
@@ -29,18 +29,19 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
P2PSocketHostUdp(IPC::Sender* message_sender,
int socket_id,
P2PMessageThrottler* throttler);
- virtual ~P2PSocketHostUdp();
+ ~P2PSocketHostUdp() override;
// P2PSocketHost overrides.
- virtual bool Init(const net::IPEndPoint& local_address,
- const P2PHostAndIPEndPoint& remote_address) OVERRIDE;
- virtual void Send(const net::IPEndPoint& to,
- const std::vector<char>& data,
- const talk_base::PacketOptions& options,
- uint64 packet_id) OVERRIDE;
- virtual P2PSocketHost* AcceptIncomingTcpConnection(
- const net::IPEndPoint& remote_address, int id) OVERRIDE;
- virtual bool SetOption(P2PSocketOption option, int value) OVERRIDE;
+ bool Init(const net::IPEndPoint& local_address,
+ const P2PHostAndIPEndPoint& remote_address) override;
+ void Send(const net::IPEndPoint& to,
+ const std::vector<char>& data,
+ const rtc::PacketOptions& options,
+ uint64 packet_id) override;
+ P2PSocketHost* AcceptIncomingTcpConnection(
+ const net::IPEndPoint& remote_address,
+ int id) override;
+ bool SetOption(P2PSocketOption option, int value) override;
private:
friend class P2PSocketHostUdpTest;
@@ -50,25 +51,27 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
struct PendingPacket {
PendingPacket(const net::IPEndPoint& to,
const std::vector<char>& content,
- const talk_base::PacketOptions& options,
+ const rtc::PacketOptions& options,
uint64 id);
~PendingPacket();
net::IPEndPoint to;
scoped_refptr<net::IOBuffer> data;
int size;
- talk_base::PacketOptions packet_options;
+ rtc::PacketOptions packet_options;
uint64 id;
};
void OnError();
+ void SetSendBufferSize();
+
void DoRead();
void OnRecv(int result);
void HandleReadResult(int result);
void DoSend(const PendingPacket& packet);
- void OnSend(uint64 packet_id, int result);
- void HandleSendResult(uint64 packet_id, int result);
+ void OnSend(uint64 packet_id, uint64 tick_received, int result);
+ void HandleSendResult(uint64 packet_id, uint64 tick_received, int result);
scoped_ptr<net::DatagramServerSocket> socket_;
scoped_refptr<net::IOBuffer> recv_buffer_;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
index 6235cb07d9f..5d67a24fc33 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc
@@ -17,7 +17,7 @@
#include "net/udp/datagram_server_socket.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle/source/talk/base/timing.h"
+#include "third_party/webrtc/base/timing.h"
using ::testing::_;
using ::testing::DeleteArg;
@@ -26,10 +26,10 @@ using ::testing::Return;
namespace {
-class FakeTiming : public talk_base::Timing {
+class FakeTiming : public rtc::Timing {
public:
FakeTiming() : now_(0.0) {}
- virtual double TimerNow() OVERRIDE { return now_; }
+ double TimerNow() override { return now_; }
void set_now(double now) { now_ = now; }
private:
@@ -46,27 +46,27 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
: sent_packets_(sent_packets) {
}
- virtual void Close() OVERRIDE {
- }
+ void Close() override {}
- virtual int GetPeerAddress(net::IPEndPoint* address) const OVERRIDE {
+ int GetPeerAddress(net::IPEndPoint* address) const override {
NOTREACHED();
return net::ERR_SOCKET_NOT_CONNECTED;
}
- virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE {
+ int GetLocalAddress(net::IPEndPoint* address) const override {
*address = address_;
return 0;
}
- virtual int Listen(const net::IPEndPoint& address) OVERRIDE {
+ int Listen(const net::IPEndPoint& address) override {
address_ = address;
return 0;
}
- virtual int RecvFrom(net::IOBuffer* buf, int buf_len,
- net::IPEndPoint* address,
- const net::CompletionCallback& callback) OVERRIDE {
+ int RecvFrom(net::IOBuffer* buf,
+ int buf_len,
+ net::IPEndPoint* address,
+ const net::CompletionCallback& callback) override {
CHECK(recv_callback_.is_null());
if (incoming_packets_.size() > 0) {
scoped_refptr<net::IOBuffer> buffer(buf);
@@ -85,22 +85,19 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
}
}
- virtual int SendTo(net::IOBuffer* buf, int buf_len,
- const net::IPEndPoint& address,
- const net::CompletionCallback& callback) OVERRIDE {
+ int SendTo(net::IOBuffer* buf,
+ int buf_len,
+ const net::IPEndPoint& address,
+ const net::CompletionCallback& callback) override {
scoped_refptr<net::IOBuffer> buffer(buf);
std::vector<char> data_vector(buffer->data(), buffer->data() + buf_len);
sent_packets_->push_back(UDPPacket(address, data_vector));
return buf_len;
}
- virtual int SetReceiveBufferSize(int32 size) OVERRIDE {
- return net::OK;
- }
+ int SetReceiveBufferSize(int32 size) override { return net::OK; }
- virtual int SetSendBufferSize(int32 size) OVERRIDE {
- return net::OK;
- }
+ int SetSendBufferSize(int32 size) override { return net::OK; }
void ReceivePacket(const net::IPEndPoint& address, std::vector<char> data) {
if (!recv_callback_.is_null()) {
@@ -116,53 +113,43 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
}
}
- virtual const net::BoundNetLog& NetLog() const OVERRIDE {
- return net_log_;
- }
+ const net::BoundNetLog& NetLog() const override { return net_log_; }
- virtual void AllowAddressReuse() OVERRIDE {
- NOTIMPLEMENTED();
- }
+ void AllowAddressReuse() override { NOTIMPLEMENTED(); }
- virtual void AllowBroadcast() OVERRIDE {
- NOTIMPLEMENTED();
- }
+ void AllowBroadcast() override { NOTIMPLEMENTED(); }
- virtual int JoinGroup(
- const net::IPAddressNumber& group_address) const OVERRIDE {
+ int JoinGroup(const net::IPAddressNumber& group_address) const override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- virtual int LeaveGroup(
- const net::IPAddressNumber& group_address) const OVERRIDE {
+ int LeaveGroup(const net::IPAddressNumber& group_address) const override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- virtual int SetMulticastInterface(uint32 interface_index) OVERRIDE {
+ int SetMulticastInterface(uint32 interface_index) override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- virtual int SetMulticastTimeToLive(int time_to_live) OVERRIDE {
+ int SetMulticastTimeToLive(int time_to_live) override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- virtual int SetMulticastLoopbackMode(bool loopback) OVERRIDE {
+ int SetMulticastLoopbackMode(bool loopback) override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- virtual int SetDiffServCodePoint(net::DiffServCodePoint dscp) OVERRIDE {
+ int SetDiffServCodePoint(net::DiffServCodePoint dscp) override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- virtual void DetachFromThread() OVERRIDE {
- NOTIMPLEMENTED();
- }
+ void DetachFromThread() override { NOTIMPLEMENTED(); }
private:
net::IPEndPoint address_;
@@ -182,7 +169,7 @@ namespace content {
class P2PSocketHostUdpTest : public testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
EXPECT_CALL(sender_, Send(
MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
@@ -197,7 +184,7 @@ class P2PSocketHostUdpTest : public testing::Test {
dest1_ = ParseAddress(kTestIpAddress1, kTestPort1);
dest2_ = ParseAddress(kTestIpAddress2, kTestPort2);
- scoped_ptr<talk_base::Timing> timing(new FakeTiming());
+ scoped_ptr<rtc::Timing> timing(new FakeTiming());
throttler_.SetTiming(timing.Pass());
}
@@ -221,7 +208,7 @@ TEST_F(P2PSocketHostUdpTest, SendStunNoAuth) {
.Times(3)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
socket_host_->Send(dest1_, packet1, options, 0);
@@ -247,7 +234,7 @@ TEST_F(P2PSocketHostUdpTest, SendDataNoAuth) {
MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet;
CreateRandomPacket(&packet);
socket_host_->Send(dest1_, packet, options, 0);
@@ -271,7 +258,7 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) {
MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet;
CreateRandomPacket(&packet);
socket_host_->Send(dest1_, packet, options, 0);
@@ -296,7 +283,7 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) {
MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
.WillOnce(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet;
CreateRandomPacket(&packet);
socket_host_->Send(dest1_, packet, options, 0);
@@ -317,7 +304,7 @@ TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) {
socket_->ReceivePacket(dest1_, request_packet);
// Should fail when trying to send the same packet to |dest2_|.
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet;
CreateRandomPacket(&packet);
EXPECT_CALL(sender_, Send(
@@ -334,7 +321,7 @@ TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimit) {
.Times(2)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
throttler_.SetSendIceBandwidth(packet1.size() * 2);
@@ -363,7 +350,7 @@ TEST_F(P2PSocketHostUdpTest, ThrottleAfterLimitAfterReceive) {
.Times(4)
.WillRepeatedly(DoAll(DeleteArg<0>(), Return(true)));
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> packet1;
CreateStunRequest(&packet1);
throttler_.SetSendIceBandwidth(packet1.size());
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc
index 1404ced5bc6..7e9393fd96c 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc
@@ -152,152 +152,158 @@ namespace content {
// This test verifies parsing of all invalid raw packets.
TEST(P2PSocketHostTest, TestInvalidRawRtpMessages) {
- int start_pos = INT_MAX, rtp_length = INT_MAX;
+ size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kRtpMsgWithInvalidLength),
sizeof(kRtpMsgWithInvalidLength),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kRtpMsgWithInvalidExtnLength),
sizeof(kRtpMsgWithInvalidExtnLength),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
}
// Verify invalid TURN send indication messages. Messages are proper STUN
// messages with incorrect values in attributes.
TEST(P2PSocketHostTest, TestInvalidTurnSendIndicationMessages) {
// Initializing out params to very large value.
- int start_pos = INT_MAX, rtp_length = INT_MAX;
+ size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnSendIndicationMsgWithNoAttributes),
sizeof(kTurnSendIndicationMsgWithNoAttributes),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnSendIndicationMsgWithInvalidLength),
sizeof(kTurnSendIndicationMsgWithInvalidLength),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnSendIndicatinMsgWithNoDataAttribute),
sizeof(kTurnSendIndicatinMsgWithNoDataAttribute),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
}
// This test verifies incorrectly formed TURN channel messages.
TEST(P2PSocketHostTest, TestInvalidTurnChannelMessages) {
- int start_pos = INT_MAX, rtp_length = INT_MAX;
+ size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnChannelMsgNoRtpPacket),
sizeof(kTurnChannelMsgNoRtpPacket),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnChannelMsgWithZeroLength),
sizeof(kTurnChannelMsgWithZeroLength),
&start_pos, &rtp_length));
- EXPECT_EQ(INT_MAX, start_pos);
- EXPECT_EQ(INT_MAX, rtp_length);
+ EXPECT_EQ(SIZE_MAX, start_pos);
+ EXPECT_EQ(SIZE_MAX, rtp_length);
}
// This test verifies parsing of a valid RTP packet which has 2byte header
// extension instead of a 1 byte header extension.
TEST(P2PSocketHostTest, TestValid2ByteExtnHdrRtpMessage) {
- int start_pos = INT_MAX, rtp_length = INT_MAX;
+ size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kRtpMsgWith2ByteExtnHeader),
sizeof(kRtpMsgWith2ByteExtnHeader),
&start_pos, &rtp_length));
- EXPECT_EQ(20, rtp_length);
- EXPECT_EQ(0, start_pos);
+ EXPECT_EQ(20U, rtp_length);
+ EXPECT_EQ(0U, start_pos);
}
// This test verifies parsing of a valid RTP packet which has 1 byte header
// AbsSendTime extension in it.
TEST(P2PSocketHostTest, TestValidRtpPacketWithAbsSendTimeExtension) {
- int start_pos = INT_MAX, rtp_length = INT_MAX;
+ size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kRtpMsgWithAbsSendTimeExtension),
sizeof(kRtpMsgWithAbsSendTimeExtension),
&start_pos, &rtp_length));
- EXPECT_EQ(24, rtp_length);
- EXPECT_EQ(0, start_pos);
+ EXPECT_EQ(24U, rtp_length);
+ EXPECT_EQ(0U, start_pos);
}
// This test verifies parsing of a valid TURN Send Indication messages.
TEST(P2PSocketHostTest, TestValidTurnSendIndicationMessages) {
- int start_pos = INT_MAX, rtp_length = INT_MAX;
+ size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnSendIndicationMsgWithoutRtpExtension),
sizeof(kTurnSendIndicationMsgWithoutRtpExtension),
&start_pos, &rtp_length));
- EXPECT_EQ(12, rtp_length);
- EXPECT_EQ(32, start_pos);
+ EXPECT_EQ(12U, rtp_length);
+ EXPECT_EQ(32U, start_pos);
- start_pos = INT_MAX, rtp_length = INT_MAX;
+ start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnSendIndicationMsgWithAbsSendTimeExtension),
sizeof(kTurnSendIndicationMsgWithAbsSendTimeExtension),
&start_pos, &rtp_length));
- EXPECT_EQ(24, rtp_length);
- EXPECT_EQ(32, start_pos);
+ EXPECT_EQ(24U, rtp_length);
+ EXPECT_EQ(32U, start_pos);
}
// This test verifies parsing of valid TURN Channel Messages.
TEST(P2PSocketHostTest, TestValidTurnChannelMessages) {
- int start_pos = -1, rtp_length = -1;
+ size_t start_pos = 0, rtp_length = 0;
EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnChannelMsgWithRtpPacket),
sizeof(kTurnChannelMsgWithRtpPacket), &start_pos, &rtp_length));
- EXPECT_EQ(12, rtp_length);
- EXPECT_EQ(4, start_pos);
+ EXPECT_EQ(12U, rtp_length);
+ EXPECT_EQ(4U, start_pos);
- start_pos = -1, rtp_length = -1;
+ start_pos = 0, rtp_length = 0;
EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
reinterpret_cast<char*>(kTurnChannelMsgWithAbsSendTimeExtension),
sizeof(kTurnChannelMsgWithAbsSendTimeExtension),
&start_pos, &rtp_length));
- EXPECT_EQ(20, rtp_length);
- EXPECT_EQ(4, start_pos);
+ EXPECT_EQ(20U, rtp_length);
+ EXPECT_EQ(4U, start_pos);
}
// Verify handling of a 2 byte extension header RTP messsage. Currently we don't
// handle this kind of message.
TEST(P2PSocketHostTest, TestUpdateAbsSendTimeExtensionIn2ByteHeaderExtn) {
- EXPECT_FALSE(packet_processing_helpers::UpdateRtpAbsSendTimeExtn(
- reinterpret_cast<char*>(kRtpMsgWith2ByteExtnHeader),
- sizeof(kRtpMsgWith2ByteExtnHeader), 3, 0));
+ EXPECT_FALSE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
+ reinterpret_cast<char*>(kRtpMsgWith2ByteExtnHeader),
+ sizeof(kRtpMsgWith2ByteExtnHeader),
+ 3,
+ 0));
}
// Verify finding an extension ID in the TURN send indication message.
TEST(P2PSocketHostTest, TestUpdateAbsSendTimeExtensionInTurnSendIndication) {
- EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtn(
+ EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
reinterpret_cast<char*>(kTurnSendIndicationMsgWithoutRtpExtension),
- sizeof(kTurnSendIndicationMsgWithoutRtpExtension), 3, 0));
+ sizeof(kTurnSendIndicationMsgWithoutRtpExtension),
+ 3,
+ 0));
- EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtn(
+ EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
reinterpret_cast<char*>(kTurnSendIndicationMsgWithAbsSendTimeExtension),
- sizeof(kTurnSendIndicationMsgWithAbsSendTimeExtension), 3, 0));
+ sizeof(kTurnSendIndicationMsgWithAbsSendTimeExtension),
+ 3,
+ 0));
}
// Test without any packet options variables set. This method should return
// without HMAC value in the packet.
TEST(P2PSocketHostTest, TestApplyPacketOptionsWithDefaultValues) {
unsigned char fake_tag[4] = { 0xba, 0xdd, 0xba, 0xdd };
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
std::vector<char> rtp_packet;
rtp_packet.resize(sizeof(kRtpMsgWithAbsSendTimeExtension) + 4); // tag length
memcpy(&rtp_packet[0], kRtpMsgWithAbsSendTimeExtension,
@@ -317,7 +323,7 @@ TEST(P2PSocketHostTest, TestApplyPacketOptionsWithDefaultValues) {
// Veirfy HMAC is updated when packet option parameters are set.
TEST(P2PSocketHostTest, TestApplyPacketOptionsWithAuthParams) {
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
options.packet_time_params.srtp_auth_key.resize(20);
options.packet_time_params.srtp_auth_key.assign(
kTestKey, kTestKey + sizeof(kTestKey));
@@ -341,14 +347,16 @@ TEST(P2PSocketHostTest, TestApplyPacketOptionsWithAuthParams) {
// Verify finding an extension ID in a raw rtp message.
TEST(P2PSocketHostTest, TestUpdateAbsSendTimeExtensionInRtpPacket) {
- EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtn(
+ EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
reinterpret_cast<char*>(kRtpMsgWithAbsSendTimeExtension),
- sizeof(kRtpMsgWithAbsSendTimeExtension), 3, 0));
+ sizeof(kRtpMsgWithAbsSendTimeExtension),
+ 3,
+ 0));
}
// Verify we update both AbsSendTime extension header and HMAC.
TEST(P2PSocketHostTest, TestApplyPacketOptionsWithAuthParamsAndAbsSendTime) {
- talk_base::PacketOptions options;
+ rtc::PacketOptions options;
options.packet_time_params.srtp_auth_key.resize(20);
options.packet_time_params.srtp_auth_key.assign(
kTestKey, kTestKey + sizeof(kTestKey));
diff --git a/chromium/content/browser/renderer_host/pepper/OWNERS b/chromium/content/browser/renderer_host/pepper/OWNERS
index 4523b30354e..d107f297fa7 100644
--- a/chromium/content/browser/renderer_host/pepper/OWNERS
+++ b/chromium/content/browser/renderer_host/pepper/OWNERS
@@ -2,4 +2,3 @@ bbudge@chromium.org
dmichael@chromium.org
raymes@chromium.org
teravest@chromium.org
-yzshen@chromium.org
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
index 403b129a469..130245e6022 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc
@@ -37,7 +37,7 @@ BrowserPpapiHost* BrowserPpapiHost::CreateExternalPluginProcess(
scoped_refptr<PepperMessageFilter> pepper_message_filter(
new PepperMessageFilter());
channel->AddFilter(pepper_message_filter->GetFilter());
- channel->AddFilter(browser_ppapi_host->message_filter());
+ channel->AddFilter(browser_ppapi_host->message_filter().get());
channel->AddFilter((new TraceMessageFilter())->GetFilter());
return browser_ppapi_host;
diff --git a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
index 16fec3d2907..bd0c61d7c59 100644
--- a/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
+++ b/chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.h
@@ -22,6 +22,10 @@
#include "ipc/message_filter.h"
#include "ppapi/host/ppapi_host.h"
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
namespace content {
class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
@@ -38,23 +42,22 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
const base::FilePath& profile_data_directory,
bool in_process,
bool external_plugin);
- virtual ~BrowserPpapiHostImpl();
+ ~BrowserPpapiHostImpl() override;
// BrowserPpapiHost.
- virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE;
- virtual base::ProcessHandle GetPluginProcessHandle() const OVERRIDE;
- virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE;
- virtual bool GetRenderFrameIDsForInstance(PP_Instance instance,
- int* render_process_id,
- int* render_frame_id) const
- OVERRIDE;
- virtual const std::string& GetPluginName() OVERRIDE;
- virtual const base::FilePath& GetPluginPath() OVERRIDE;
- virtual const base::FilePath& GetProfileDataDirectory() OVERRIDE;
- virtual GURL GetDocumentURLForInstance(PP_Instance instance) OVERRIDE;
- virtual GURL GetPluginURLForInstance(PP_Instance instance) OVERRIDE;
- virtual void SetOnKeepaliveCallback(
- const BrowserPpapiHost::OnKeepaliveCallback& callback) OVERRIDE;
+ ppapi::host::PpapiHost* GetPpapiHost() override;
+ base::ProcessHandle GetPluginProcessHandle() const override;
+ bool IsValidInstance(PP_Instance instance) const override;
+ bool GetRenderFrameIDsForInstance(PP_Instance instance,
+ int* render_process_id,
+ int* render_frame_id) const override;
+ const std::string& GetPluginName() override;
+ const base::FilePath& GetPluginPath() override;
+ const base::FilePath& GetProfileDataDirectory() override;
+ GURL GetDocumentURLForInstance(PP_Instance instance) override;
+ GURL GetPluginURLForInstance(PP_Instance instance) override;
+ void SetOnKeepaliveCallback(
+ const BrowserPpapiHost::OnKeepaliveCallback& callback) override;
void set_plugin_process_handle(base::ProcessHandle handle) {
plugin_process_handle_ = handle;
@@ -89,12 +92,12 @@ class CONTENT_EXPORT BrowserPpapiHostImpl : public BrowserPpapiHost {
BrowserPpapiHostImpl* browser_ppapi_host_impl);
// IPC::MessageFilter.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
void OnHostDestroyed();
private:
- virtual ~HostMessageFilter();
+ ~HostMessageFilter() override;
void OnKeepalive();
void OnHostMsgLogInterfaceUsage(int hash) const;
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
index e1ce0320b6e..9a88cfc460a 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.cc
@@ -18,6 +18,7 @@
#include "content/browser/renderer_host/pepper/pepper_printing_host.h"
#include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font_host.h"
#include "content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h"
#include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"
#include "ppapi/host/message_filter_host.h"
@@ -29,6 +30,7 @@
using ppapi::host::MessageFilterHost;
using ppapi::host::ResourceHost;
using ppapi::host::ResourceMessageFilter;
+using ppapi::proxy::SerializedTrueTypeFontDesc;
using ppapi::UnpackMessage;
namespace content {
@@ -140,6 +142,20 @@ scoped_ptr<ResourceHost> ContentBrowserPepperHostFactory::CreateResourceHost(
params.pp_resource(),
manager.Pass()));
}
+ case PpapiHostMsg_TrueTypeFont_Create::ID: {
+ SerializedTrueTypeFontDesc desc;
+ if (!UnpackMessage<PpapiHostMsg_TrueTypeFont_Create>(message, &desc)) {
+ NOTREACHED();
+ return scoped_ptr<ResourceHost>();
+ }
+ // Check that the family name is valid UTF-8 before passing it to the
+ // host OS.
+ if (!base::IsStringUTF8(desc.family))
+ return scoped_ptr<ResourceHost>();
+
+ return scoped_ptr<ResourceHost>(new PepperTrueTypeFontHost(
+ host_, instance, params.pp_resource(), desc));
+ }
case PpapiHostMsg_TrueTypeFontSingleton_Create::ID: {
return scoped_ptr<ResourceHost>(new PepperTrueTypeFontListHost(
host_, instance, params.pp_resource()));
@@ -242,7 +258,7 @@ ContentBrowserPepperHostFactory::CreateNewTCPSocket(
scoped_refptr<ResourceMessageFilter> tcp_socket(
new PepperTCPSocketMessageFilter(this, host_, instance, version));
- if (!tcp_socket)
+ if (!tcp_socket.get())
return scoped_ptr<ResourceHost>();
return scoped_ptr<ResourceHost>(new MessageFilterHost(
diff --git a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
index 04267a32e8a..84161f3392d 100644
--- a/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
+++ b/chromium/content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h
@@ -26,13 +26,13 @@ class ContentBrowserPepperHostFactory : public ppapi::host::HostFactory {
// Non-owning pointer to the filter must outlive this class.
explicit ContentBrowserPepperHostFactory(BrowserPpapiHostImpl* host);
- virtual ~ContentBrowserPepperHostFactory();
+ ~ContentBrowserPepperHostFactory() override;
- virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
ppapi::host::PpapiHost* host,
const ppapi::proxy::ResourceMessageCallParams& params,
PP_Instance instance,
- const IPC::Message& message) OVERRIDE;
+ const IPC::Message& message) override;
// Creates ResourceHost for already accepted TCP |socket|. In the case of
// failure returns wrapped NULL.
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc
index 40c13dfee01..e2c909c9ae5 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.cc
@@ -23,14 +23,14 @@ class FontMessageFilter : public ppapi::host::ResourceMessageFilter {
FontMessageFilter();
// ppapi::host::ResourceMessageFilter implementation.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
private:
- virtual ~FontMessageFilter();
+ ~FontMessageFilter() override;
// Message handler.
int32_t OnHostMsgGetFontFamilies(ppapi::host::HostMessageContext* context);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h b/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h
index c002e634c91..643be703b9d 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_browser_font_singleton_host.h
@@ -17,7 +17,7 @@ class PepperBrowserFontSingletonHost : public ppapi::host::ResourceHost {
PepperBrowserFontSingletonHost(BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperBrowserFontSingletonHost();
+ ~PepperBrowserFontSingletonHost() override;
private:
DISALLOW_COPY_AND_ASSIGN(PepperBrowserFontSingletonHost);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
index a6b61981ac5..d4913da4ce8 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.cc
@@ -97,8 +97,8 @@ int32_t PepperExternalFileRefBackend::GetAbsolutePath(
return PP_OK_COMPLETIONPENDING;
}
-fileapi::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
- return fileapi::FileSystemURL();
+storage::FileSystemURL PepperExternalFileRefBackend::GetFileSystemURL() const {
+ return storage::FileSystemURL();
}
base::FilePath PepperExternalFileRefBackend::GetExternalFilePath() const {
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
index 4d2980ae421..f3c3c947d57 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_external_file_ref_backend.h
@@ -25,29 +25,28 @@ class PepperExternalFileRefBackend : public PepperFileRefBackend {
PepperExternalFileRefBackend(ppapi::host::PpapiHost* host,
int render_process_id,
const base::FilePath& path);
- virtual ~PepperExternalFileRefBackend();
+ ~PepperExternalFileRefBackend() override;
// PepperFileRefBackend overrides.
- virtual int32_t MakeDirectory(ppapi::host::ReplyMessageContext context,
- int32_t make_directory_flags) OVERRIDE;
- virtual int32_t Touch(ppapi::host::ReplyMessageContext context,
- PP_Time last_accessed_time,
- PP_Time last_modified_time) OVERRIDE;
- virtual int32_t Delete(ppapi::host::ReplyMessageContext context) OVERRIDE;
- virtual int32_t Rename(ppapi::host::ReplyMessageContext context,
- PepperFileRefHost* new_file_ref) OVERRIDE;
- virtual int32_t Query(ppapi::host::ReplyMessageContext context) OVERRIDE;
- virtual int32_t ReadDirectoryEntries(ppapi::host::ReplyMessageContext context)
- OVERRIDE;
- virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context)
- OVERRIDE;
- virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
- virtual base::FilePath GetExternalFilePath() const OVERRIDE;
+ int32_t MakeDirectory(ppapi::host::ReplyMessageContext context,
+ int32_t make_directory_flags) override;
+ int32_t Touch(ppapi::host::ReplyMessageContext context,
+ PP_Time last_accessed_time,
+ PP_Time last_modified_time) override;
+ int32_t Delete(ppapi::host::ReplyMessageContext context) override;
+ int32_t Rename(ppapi::host::ReplyMessageContext context,
+ PepperFileRefHost* new_file_ref) override;
+ int32_t Query(ppapi::host::ReplyMessageContext context) override;
+ int32_t ReadDirectoryEntries(
+ ppapi::host::ReplyMessageContext context) override;
+ int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context) override;
+ storage::FileSystemURL GetFileSystemURL() const override;
+ base::FilePath GetExternalFilePath() const override;
- virtual int32_t CanRead() const OVERRIDE;
- virtual int32_t CanWrite() const OVERRIDE;
- virtual int32_t CanCreate() const OVERRIDE;
- virtual int32_t CanReadWrite() const OVERRIDE;
+ int32_t CanRead() const override;
+ int32_t CanWrite() const override;
+ int32_t CanCreate() const override;
+ int32_t CanReadWrite() const override;
private:
// Generic reply callback.
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
index e350138f8a7..31850f85171 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -28,11 +28,11 @@
#include "ppapi/shared_impl/file_system_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
#include "ppapi/shared_impl/time_conversion.h"
-#include "webkit/browser/fileapi/file_observers.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/task_runner_bound_observer_list.h"
-#include "webkit/common/fileapi/file_system_util.h"
+#include "storage/browser/fileapi/file_observers.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/task_runner_bound_observer_list.h"
+#include "storage/common/fileapi/file_system_util.h"
namespace content {
@@ -87,7 +87,7 @@ void DidCloseFile(const base::Closure& on_close_callback) {
}
void DidOpenFile(base::WeakPtr<PepperFileIOHost> file_host,
- fileapi::FileSystemOperation::OpenFileCallback callback,
+ storage::FileSystemOperation::OpenFileCallback callback,
base::File file,
const base::Closure& on_close_callback) {
if (file_host) {
@@ -109,7 +109,8 @@ PepperFileIOHost::PepperFileIOHost(BrowserPpapiHostImpl* host,
: ResourceHost(host->GetPpapiHost(), instance, resource),
browser_ppapi_host_(host),
render_process_host_(NULL),
- file_(BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)),
+ file_(BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
+ .get()),
open_flags_(0),
file_system_type_(PP_FILESYSTEMTYPE_INVALID),
max_written_offset_(0),
@@ -186,13 +187,13 @@ int32_t PepperFileIOHost::OnHostMsgOpen(
// Not all external file systems are fully supported yet.
// Whitelist the supported ones.
- if (file_system_url_.mount_type() == fileapi::kFileSystemTypeExternal) {
+ if (file_system_url_.mount_type() == storage::kFileSystemTypeExternal) {
switch (file_system_url_.type()) {
- case fileapi::kFileSystemTypeNativeMedia:
- case fileapi::kFileSystemTypeDeviceMedia:
- case fileapi::kFileSystemTypePicasa:
- case fileapi::kFileSystemTypeItunes:
- case fileapi::kFileSystemTypeIphoto:
+ case storage::kFileSystemTypeNativeMedia:
+ case storage::kFileSystemTypeDeviceMedia:
+ case storage::kFileSystemTypePicasa:
+ case storage::kFileSystemTypeItunes:
+ case storage::kFileSystemTypeIphoto:
break;
default:
return PP_ERROR_NOACCESS;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
index abef036c95b..36f7dba09a4 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
@@ -12,7 +12,6 @@
#include "base/files/file.h"
#include "base/files/file_proxy.h"
#include "base/memory/weak_ptr.h"
-#include "base/platform_file.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_platform_file.h"
@@ -21,8 +20,8 @@
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/shared_impl/file_io_state_manager.h"
+#include "storage/browser/fileapi/file_system_context.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
namespace ppapi {
struct FileGrowth;
@@ -39,18 +38,18 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
PepperFileIOHost(BrowserPpapiHostImpl* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperFileIOHost();
+ ~PepperFileIOHost() override;
// ppapi::host::ResourceHost override.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
struct UIThreadStuff {
UIThreadStuff();
~UIThreadStuff();
base::ProcessId resolved_render_process_id;
- scoped_refptr<fileapi::FileSystemContext> file_system_context;
+ scoped_refptr<storage::FileSystemContext> file_system_context;
};
private:
@@ -127,8 +126,8 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
base::WeakPtr<PepperFileSystemBrowserHost> file_system_host_;
// Valid only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
- fileapi::FileSystemURL file_system_url_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
+ storage::FileSystemURL file_system_url_;
base::Closure on_close_callback_;
int64_t max_written_offset_;
bool check_quota_;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
index a8d362d36e8..6a1d9affe23 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.cc
@@ -17,7 +17,7 @@
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/file_ref_util.h"
-#include "webkit/browser/fileapi/file_permission_policy.h"
+#include "storage/browser/fileapi/file_permission_policy.h"
using ppapi::host::ResourceHost;
@@ -109,10 +109,10 @@ PP_FileSystemType PepperFileRefHost::GetFileSystemType() const {
return fs_type_;
}
-fileapi::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
+storage::FileSystemURL PepperFileRefHost::GetFileSystemURL() const {
if (backend_)
return backend_->GetFileSystemURL();
- return fileapi::FileSystemURL();
+ return storage::FileSystemURL();
}
base::FilePath PepperFileRefHost::GetExternalFilePath() const {
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
index d850504d175..5f6d11eb119 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_ref_host.h
@@ -15,7 +15,7 @@
#include "ppapi/c/pp_time.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
-#include "webkit/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/file_system_url.h"
namespace content {
class PepperFileRefHost;
@@ -40,7 +40,7 @@ class PepperFileRefBackend {
virtual int32_t ReadDirectoryEntries(
ppapi::host::ReplyMessageContext context) = 0;
virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context) = 0;
- virtual fileapi::FileSystemURL GetFileSystemURL() const = 0;
+ virtual storage::FileSystemURL GetFileSystemURL() const = 0;
virtual base::FilePath GetExternalFilePath() const = 0;
// Returns an error from the pp_errors.h enum.
@@ -65,17 +65,17 @@ class CONTENT_EXPORT PepperFileRefHost
PP_Resource resource,
const base::FilePath& external_path);
- virtual ~PepperFileRefHost();
+ ~PepperFileRefHost() override;
// ResourceHost overrides.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
- virtual bool IsFileRefHost() OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
+ bool IsFileRefHost() override;
// Required to support Rename().
PP_FileSystemType GetFileSystemType() const;
- fileapi::FileSystemURL GetFileSystemURL() const;
+ storage::FileSystemURL GetFileSystemURL() const;
// Required to support FileIO.
base::FilePath GetExternalFilePath() const;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index 5eec4105002..d5f1da50f86 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "content/browser/renderer_host/pepper/pepper_file_io_host.h"
#include "content/browser/renderer_host/pepper/quota_reservation.h"
+#include "content/common/pepper_file_util.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
@@ -21,11 +22,11 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/file_system_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
-#include "webkit/common/fileapi/file_system_util.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/isolated_context.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/fileapi/file_system_util.h"
+#include "storage/common/quota/quota_types.h"
namespace content {
@@ -34,7 +35,7 @@ namespace {
// This is the minimum amount of quota we reserve per file system.
const int64_t kMinimumQuotaReservationSize = 1024 * 1024; // 1 MB
-scoped_refptr<fileapi::FileSystemContext> GetFileSystemContextFromRenderId(
+scoped_refptr<storage::FileSystemContext> GetFileSystemContextFromRenderId(
int render_process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
@@ -117,7 +118,7 @@ bool PepperFileSystemBrowserHost::IsFileSystemHost() { return true; }
void PepperFileSystemBrowserHost::OpenQuotaFile(
PepperFileIOHost* file_io_host,
- const fileapi::FileSystemURL& url,
+ const storage::FileSystemURL& url,
const OpenQuotaFileCallback& callback) {
int32_t id = file_io_host->pp_resource();
std::pair<FileMap::iterator, bool> insert_result =
@@ -162,9 +163,9 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
return PP_ERROR_INPROGRESS;
called_open_ = true;
- fileapi::FileSystemType file_system_type =
- ppapi::PepperFileSystemTypeToFileSystemType(type_);
- if (file_system_type == fileapi::kFileSystemTypeUnknown)
+ storage::FileSystemType file_system_type =
+ PepperFileSystemTypeToFileSystemType(type_);
+ if (file_system_type == storage::kFileSystemTypeUnknown)
return PP_ERROR_FAILED;
int render_process_id = 0;
@@ -187,7 +188,7 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgOpen(
void PepperFileSystemBrowserHost::OpenExistingFileSystem(
const base::Closure& callback,
- scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
if (file_system_context.get()) {
opened_ = true;
} else {
@@ -206,8 +207,8 @@ void PepperFileSystemBrowserHost::OpenExistingFileSystem(
void PepperFileSystemBrowserHost::OpenFileSystem(
ppapi::host::ReplyMessageContext reply_context,
- fileapi::FileSystemType file_system_type,
- scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ storage::FileSystemType file_system_type,
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
if (!file_system_context.get()) {
OpenFileSystemComplete(
reply_context, GURL(), std::string(), base::File::FILE_ERROR_FAILED);
@@ -221,7 +222,7 @@ void PepperFileSystemBrowserHost::OpenFileSystem(
file_system_context_->OpenFileSystem(
origin,
file_system_type,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(&PepperFileSystemBrowserHost::OpenFileSystemComplete,
weak_factory_.GetWeakPtr(),
reply_context));
@@ -253,14 +254,14 @@ void PepperFileSystemBrowserHost::OpenIsolatedFileSystem(
ppapi::host::ReplyMessageContext reply_context,
const std::string& fsid,
PP_IsolatedFileSystemType_Private type,
- scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
if (!file_system_context.get()) {
SendReplyForIsolatedFileSystem(reply_context, fsid, PP_ERROR_FAILED);
return;
}
SetFileSystemContext(file_system_context);
- root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
+ root_url_ = GURL(storage::GetIsolatedFileSystemRootURIString(
browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()).GetOrigin(),
fsid,
ppapi::IsolatedFileSystemTypeToRootName(type)));
@@ -287,7 +288,7 @@ void PepperFileSystemBrowserHost::OpenIsolatedFileSystem(
void PepperFileSystemBrowserHost::OpenPluginPrivateFileSystem(
ppapi::host::ReplyMessageContext reply_context,
const std::string& fsid,
- scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
GURL origin =
browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()).GetOrigin();
if (!origin.is_valid()) {
@@ -303,10 +304,10 @@ void PepperFileSystemBrowserHost::OpenPluginPrivateFileSystem(
file_system_context->OpenPluginPrivateFileSystem(
origin,
- fileapi::kFileSystemTypePluginPrivate,
+ storage::kFileSystemTypePluginPrivate,
fsid,
plugin_id,
- fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
+ storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
base::Bind(
&PepperFileSystemBrowserHost::OpenPluginPrivateFileSystemComplete,
weak_factory_.GetWeakPtr(),
@@ -334,18 +335,18 @@ int32_t PepperFileSystemBrowserHost::OnHostMsgInitIsolatedFileSystem(
called_open_ = true;
// Do a sanity check.
- if (!fileapi::ValidateIsolatedFileSystemId(fsid))
+ if (!storage::ValidateIsolatedFileSystemId(fsid))
return PP_ERROR_BADARGUMENT;
int render_process_id = 0;
int unused;
if (!browser_ppapi_host_->GetRenderFrameIDsForInstance(
pp_instance(), &render_process_id, &unused)) {
- fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+ storage::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
return PP_ERROR_FAILED;
}
- root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
+ root_url_ = GURL(storage::GetIsolatedFileSystemRootURIString(
browser_ppapi_host_->GetDocumentURLForInstance(pp_instance()).GetOrigin(),
fsid,
ppapi::IsolatedFileSystemTypeToRootName(type)));
@@ -400,14 +401,14 @@ void PepperFileSystemBrowserHost::SendReplyForIsolatedFileSystem(
const std::string& fsid,
int32_t error) {
if (error != PP_OK)
- fileapi::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+ storage::IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
reply_context.params.set_result(error);
host()->SendReply(reply_context,
PpapiPluginMsg_FileSystem_InitIsolatedFileSystemReply());
}
void PepperFileSystemBrowserHost::SetFileSystemContext(
- scoped_refptr<fileapi::FileSystemContext> file_system_context) {
+ scoped_refptr<storage::FileSystemContext> file_system_context) {
file_system_context_ = file_system_context;
if (type_ != PP_FILESYSTEMTYPE_EXTERNAL || root_url_.is_valid()) {
file_system_operation_runner_ =
@@ -421,15 +422,15 @@ bool PepperFileSystemBrowserHost::ShouldCreateQuotaReservation() const {
return false;
// For file system types with quota, some origins have unlimited storage.
- quota::QuotaManagerProxy* quota_manager_proxy =
+ storage::QuotaManagerProxy* quota_manager_proxy =
file_system_context_->quota_manager_proxy();
CHECK(quota_manager_proxy);
CHECK(quota_manager_proxy->quota_manager());
- fileapi::FileSystemType file_system_type =
- ppapi::PepperFileSystemTypeToFileSystemType(type_);
+ storage::FileSystemType file_system_type =
+ PepperFileSystemTypeToFileSystemType(type_);
return !quota_manager_proxy->quota_manager()->IsStorageUnlimited(
root_url_.GetOrigin(),
- fileapi::FileSystemTypeToQuotaStorageType(file_system_type));
+ storage::FileSystemTypeToQuotaStorageType(file_system_type));
}
void PepperFileSystemBrowserHost::CreateQuotaReservation(
@@ -441,7 +442,7 @@ void PepperFileSystemBrowserHost::CreateQuotaReservation(
base::Bind(&QuotaReservation::Create,
file_system_context_,
root_url_.GetOrigin(),
- ppapi::PepperFileSystemTypeToFileSystemType(type_)),
+ PepperFileSystemTypeToFileSystemType(type_)),
base::Bind(&PepperFileSystemBrowserHost::GotQuotaReservation,
weak_factory_.GetWeakPtr(),
callback));
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
index f6f75fb9aa5..669adde14c7 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host.h
@@ -19,8 +19,8 @@
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/shared_impl/file_growth.h"
+#include "storage/browser/fileapi/file_system_context.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
namespace content {
@@ -37,7 +37,7 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost
PP_Instance instance,
PP_Resource resource,
PP_FileSystemType type);
- virtual ~PepperFileSystemBrowserHost();
+ ~PepperFileSystemBrowserHost() override;
// Opens the PepperFileSystemBrowserHost to use an existing file system at the
// given |root_url|. The file system at |root_url| must already be opened and
@@ -46,30 +46,30 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost
void OpenExisting(const GURL& root_url, const base::Closure& callback);
// ppapi::host::ResourceHost overrides.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
- virtual bool IsFileSystemHost() OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
+ bool IsFileSystemHost() override;
// Supports FileRefs direct access on the host side.
PP_FileSystemType GetType() const { return type_; }
bool IsOpened() const { return opened_; }
GURL GetRootUrl() const { return root_url_; }
- scoped_refptr<fileapi::FileSystemContext> GetFileSystemContext() const {
+ scoped_refptr<storage::FileSystemContext> GetFileSystemContext() const {
return file_system_context_;
}
// Supports FileIOs direct access on the host side.
// Non-NULL only for PP_FILESYSTEMTYPE_LOCAL{PERSISTENT,TEMPORARY}.
- fileapi::FileSystemOperationRunner* GetFileSystemOperationRunner() const {
+ storage::FileSystemOperationRunner* GetFileSystemOperationRunner() const {
return file_system_operation_runner_.get();
}
- bool ChecksQuota() const { return quota_reservation_ != NULL; }
+ bool ChecksQuota() const { return quota_reservation_.get() != NULL; }
// Opens a file for writing with quota checks. Returns the file size in the
// callback.
typedef base::Callback<void(int64_t)> OpenQuotaFileCallback;
void OpenQuotaFile(PepperFileIOHost* file_io_host,
- const fileapi::FileSystemURL& url,
+ const storage::FileSystemURL& url,
const OpenQuotaFileCallback& callback);
// Closes the file. This must be called after OpenQuotaFile and before the
// PepperFileIOHost is destroyed.
@@ -81,11 +81,11 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost
void OpenExistingFileSystem(
const base::Closure& callback,
- scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ scoped_refptr<storage::FileSystemContext> file_system_context);
void OpenFileSystem(
ppapi::host::ReplyMessageContext reply_context,
- fileapi::FileSystemType file_system_type,
- scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ storage::FileSystemType file_system_type,
+ scoped_refptr<storage::FileSystemContext> file_system_context);
void OpenFileSystemComplete(ppapi::host::ReplyMessageContext reply_context,
const GURL& root,
const std::string& name,
@@ -94,11 +94,11 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost
ppapi::host::ReplyMessageContext reply_context,
const std::string& fsid,
PP_IsolatedFileSystemType_Private type,
- scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ scoped_refptr<storage::FileSystemContext> file_system_context);
void OpenPluginPrivateFileSystem(
ppapi::host::ReplyMessageContext reply_context,
const std::string& fsid,
- scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ scoped_refptr<storage::FileSystemContext> file_system_context);
void OpenPluginPrivateFileSystemComplete(
ppapi::host::ReplyMessageContext reply_context,
const std::string& fsid,
@@ -122,7 +122,7 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost
int32_t error);
void SetFileSystemContext(
- scoped_refptr<fileapi::FileSystemContext> file_system_context);
+ scoped_refptr<storage::FileSystemContext> file_system_context);
bool ShouldCreateQuotaReservation() const;
void CreateQuotaReservation(const base::Closure& callback);
@@ -147,9 +147,9 @@ class CONTENT_EXPORT PepperFileSystemBrowserHost
bool called_open_; // whether open has been called.
bool opened_; // whether open succeeded.
GURL root_url_;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
- scoped_ptr<fileapi::FileSystemOperationRunner> file_system_operation_runner_;
+ scoped_ptr<storage::FileSystemOperationRunner> file_system_operation_runner_;
// Used only for file systems with quota.
// When a PepperFileIOHost calls OpenQuotaFile, we add the id and a non-owning
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc
index 8aa144cf426..ccc9c610d21 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc
@@ -19,9 +19,9 @@ class PepperFileSystemBrowserHostTest : public testing::Test,
public BrowserPpapiHostTest {
public:
PepperFileSystemBrowserHostTest() {}
- virtual ~PepperFileSystemBrowserHostTest() {}
+ ~PepperFileSystemBrowserHostTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
PP_Instance pp_instance = 12345;
PP_Resource pp_resource = 67890;
host_.reset(new PepperFileSystemBrowserHost(GetBrowserPpapiHost(),
@@ -30,7 +30,7 @@ class PepperFileSystemBrowserHostTest : public testing::Test,
PP_FILESYSTEMTYPE_ISOLATED));
}
- virtual void TearDown() OVERRIDE { host_.reset(); }
+ void TearDown() override { host_.reset(); }
protected:
std::string GeneratePluginId(const std::string& mime_type) {
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
index d4413b20c9c..5452bafc09c 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
@@ -5,9 +5,9 @@
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
#include "base/bind.h"
-#include "base/file_util.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/threading/sequenced_worker_pool.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h
index ab21076262b..301f97e9632 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h
@@ -43,14 +43,14 @@ class PepperFlashFileMessageFilter : public ppapi::host::ResourceMessageFilter {
typedef base::Callback<bool(int, const base::FilePath&)>
CheckPermissionsCallback;
- virtual ~PepperFlashFileMessageFilter();
+ ~PepperFlashFileMessageFilter() override;
// ppapi::host::ResourceMessageFilter overrides.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
int32_t OnOpenFile(ppapi::host::HostMessageContext* context,
const ppapi::PepperFilePath& path,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
index c9f2c18fbc6..8d6ee7346fa 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host.h
@@ -37,19 +37,17 @@ class CONTENT_EXPORT PepperGamepadHost :
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperGamepadHost();
+ ~PepperGamepadHost() override;
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// GamepadConsumer implementation.
- virtual void OnGamepadConnected(
- unsigned index,
- const blink::WebGamepad& gamepad) OVERRIDE {}
- virtual void OnGamepadDisconnected(
- unsigned index,
- const blink::WebGamepad& gamepad) OVERRIDE {}
+ void OnGamepadConnected(unsigned index,
+ const blink::WebGamepad& gamepad) override {}
+ void OnGamepadDisconnected(unsigned index,
+ const blink::WebGamepad& gamepad) override {}
private:
int32_t OnRequestMemory(ppapi::host::HostMessageContext* context);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
index f86c944a46d..b5787e170b5 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc
@@ -26,7 +26,7 @@ class PepperGamepadHostTest : public testing::Test,
public BrowserPpapiHostTest {
public:
PepperGamepadHostTest() {}
- virtual ~PepperGamepadHostTest() {}
+ ~PepperGamepadHostTest() override {}
void ConstructService(const blink::WebGamepads& test_data) {
service_.reset(new GamepadServiceTestConstructor(test_data));
@@ -140,29 +140,19 @@ TEST_F(PepperGamepadHostTest, WaitForReply) {
gamepad_host.OnResourceMessageReceived(
PpapiHostMsg_Gamepad_RequestMemory(), &context));
- // Wait for the gamepad background thread to read twice to make sure we
- // don't get a message yet (see below for why).
MockGamepadDataFetcher* fetcher = service_->data_fetcher();
- fetcher->WaitForDataRead();
- fetcher->WaitForDataRead();
+ fetcher->WaitForDataReadAndCallbacksIssued();
// It should not have sent the callback message.
service_->message_loop().RunUntilIdle();
EXPECT_EQ(0u, sink().message_count());
// Set a button down and wait for it to be read twice.
- //
- // We wait for two reads before calling RunAllPending because the provider
- // will read the data on the background thread (setting the event) and *then*
- // will issue the callback on our thread. Waiting for it to read twice
- // ensures that it was able to issue callbacks for the first read (if it
- // issued one) before we try to check for it.
blink::WebGamepads button_down_data = default_data;
button_down_data.items[0].buttons[0].value = 1.f;
button_down_data.items[0].buttons[0].pressed = true;
fetcher->SetTestData(button_down_data);
- fetcher->WaitForDataRead();
- fetcher->WaitForDataRead();
+ fetcher->WaitForDataReadAndCallbacksIssued();
// It should have sent a callback.
service_->message_loop().RunUntilIdle();
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
index 8fb404df4e3..a5321845b8a 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.h
@@ -43,17 +43,17 @@ class CONTENT_EXPORT PepperHostResolverMessageFilter
bool private_api);
protected:
- virtual ~PepperHostResolverMessageFilter();
+ ~PepperHostResolverMessageFilter() override;
private:
typedef std::vector<PP_NetAddress_Private> NetAddressList;
// ppapi::host::ResourceMessageFilter overrides.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
int32_t OnMsgResolve(const ppapi::host::HostMessageContext* context,
const ppapi::HostPortPair& host_port,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
index bc7f2b6a119..ddab7c00822 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/file_util_proxy.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
@@ -33,10 +33,10 @@
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_file_ref_api.h"
#include "ppapi/thunk/ppb_file_system_api.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/file_system_url.h"
-#include "webkit/common/fileapi/file_system_util.h"
+#include "storage/browser/fileapi/file_system_operation.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/file_system_url.h"
+#include "storage/common/fileapi/file_system_util.h"
using ppapi::host::PpapiHost;
using ppapi::host::ResourceHost;
@@ -59,11 +59,11 @@ PepperInternalFileRefBackend::PepperInternalFileRefBackend(
PepperInternalFileRefBackend::~PepperInternalFileRefBackend() {}
-fileapi::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
+storage::FileSystemURL PepperInternalFileRefBackend::GetFileSystemURL() const {
if (!fs_url_.is_valid() && fs_host_.get() && fs_host_->IsOpened()) {
GURL fs_path =
fs_host_->GetRootUrl().Resolve(net::EscapePath(path_.substr(1)));
- scoped_refptr<fileapi::FileSystemContext> fs_context =
+ scoped_refptr<storage::FileSystemContext> fs_context =
GetFileSystemContext();
if (fs_context.get())
fs_url_ = fs_context->CrackURL(fs_path);
@@ -75,7 +75,7 @@ base::FilePath PepperInternalFileRefBackend::GetExternalFilePath() const {
return base::FilePath();
}
-scoped_refptr<fileapi::FileSystemContext>
+scoped_refptr<storage::FileSystemContext>
PepperInternalFileRefBackend::GetFileSystemContext() const {
if (!fs_host_.get())
return NULL;
@@ -146,7 +146,7 @@ int32_t PepperInternalFileRefBackend::Rename(
if (!GetFileSystemURL().is_valid())
return PP_ERROR_FAILED;
- fileapi::FileSystemURL new_url = new_file_ref->GetFileSystemURL();
+ storage::FileSystemURL new_url = new_file_ref->GetFileSystemURL();
if (!new_url.is_valid())
return PP_ERROR_FAILED;
if (!new_url.IsInSameFileSystem(GetFileSystemURL()))
@@ -155,7 +155,7 @@ int32_t PepperInternalFileRefBackend::Rename(
GetFileSystemContext()->operation_runner()->Move(
GetFileSystemURL(),
new_url,
- fileapi::FileSystemOperation::OPTION_NONE,
+ storage::FileSystemOperation::OPTION_NONE,
base::Bind(&PepperInternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(),
reply_context,
@@ -197,8 +197,8 @@ int32_t PepperInternalFileRefBackend::ReadDirectoryEntries(
if (!GetFileSystemURL().is_valid())
return PP_ERROR_FAILED;
- fileapi::FileSystemOperation::FileEntryList* accumulated_file_list =
- new fileapi::FileSystemOperation::FileEntryList;
+ storage::FileSystemOperation::FileEntryList* accumulated_file_list =
+ new storage::FileSystemOperation::FileEntryList;
GetFileSystemContext()->operation_runner()->ReadDirectory(
GetFileSystemURL(),
base::Bind(&PepperInternalFileRefBackend::ReadDirectoryComplete,
@@ -210,9 +210,9 @@ int32_t PepperInternalFileRefBackend::ReadDirectoryEntries(
void PepperInternalFileRefBackend::ReadDirectoryComplete(
ppapi::host::ReplyMessageContext context,
- fileapi::FileSystemOperation::FileEntryList* accumulated_file_list,
+ storage::FileSystemOperation::FileEntryList* accumulated_file_list,
base::File::Error error,
- const fileapi::FileSystemOperation::FileEntryList& file_list,
+ const storage::FileSystemOperation::FileEntryList& file_list,
bool has_more) {
accumulated_file_list->insert(
accumulated_file_list->end(), file_list.begin(), file_list.end());
@@ -228,7 +228,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
if (dir_path.empty() || dir_path[dir_path.size() - 1] != '/')
dir_path += '/';
- for (fileapi::FileSystemOperation::FileEntryList::const_iterator it =
+ for (storage::FileSystemOperation::FileEntryList::const_iterator it =
accumulated_file_list->begin();
it != accumulated_file_list->end();
++it) {
@@ -241,7 +241,7 @@ void PepperInternalFileRefBackend::ReadDirectoryComplete(
info.file_system_type = fs_type_;
info.file_system_plugin_resource = fs_host_->pp_resource();
std::string path =
- dir_path + fileapi::FilePathToString(base::FilePath(it->name));
+ dir_path + storage::FilePathToString(base::FilePath(it->name));
info.internal_path = path;
info.display_name = ppapi::GetNameForInternalFilePath(path);
infos.push_back(info);
@@ -261,7 +261,7 @@ int32_t PepperInternalFileRefBackend::GetAbsolutePath(
}
int32_t PepperInternalFileRefBackend::CanRead() const {
- fileapi::FileSystemURL url = GetFileSystemURL();
+ storage::FileSystemURL url = GetFileSystemURL();
if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
return PP_ERROR_FAILED;
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadFileSystemFile(
@@ -272,7 +272,7 @@ int32_t PepperInternalFileRefBackend::CanRead() const {
}
int32_t PepperInternalFileRefBackend::CanWrite() const {
- fileapi::FileSystemURL url = GetFileSystemURL();
+ storage::FileSystemURL url = GetFileSystemURL();
if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
return PP_ERROR_FAILED;
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanWriteFileSystemFile(
@@ -283,7 +283,7 @@ int32_t PepperInternalFileRefBackend::CanWrite() const {
}
int32_t PepperInternalFileRefBackend::CanCreate() const {
- fileapi::FileSystemURL url = GetFileSystemURL();
+ storage::FileSystemURL url = GetFileSystemURL();
if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
return PP_ERROR_FAILED;
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanCreateFileSystemFile(
@@ -294,7 +294,7 @@ int32_t PepperInternalFileRefBackend::CanCreate() const {
}
int32_t PepperInternalFileRefBackend::CanReadWrite() const {
- fileapi::FileSystemURL url = GetFileSystemURL();
+ storage::FileSystemURL url = GetFileSystemURL();
if (!FileSystemURLIsValid(GetFileSystemContext().get(), url))
return PP_ERROR_FAILED;
ChildProcessSecurityPolicyImpl* policy =
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
index 4214de01785..e210763c810 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.h
@@ -12,9 +12,9 @@
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_time.h"
#include "ppapi/host/ppapi_host.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/file_system_operation.h"
-#include "webkit/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/file_system_operation.h"
+#include "storage/browser/fileapi/file_system_url.h"
namespace content {
@@ -28,29 +28,28 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
int render_process_id,
base::WeakPtr<PepperFileSystemBrowserHost> fs_host,
const std::string& path);
- virtual ~PepperInternalFileRefBackend();
+ ~PepperInternalFileRefBackend() override;
// PepperFileRefBackend overrides.
- virtual int32_t MakeDirectory(ppapi::host::ReplyMessageContext context,
- int32_t make_directory_flags) OVERRIDE;
- virtual int32_t Touch(ppapi::host::ReplyMessageContext context,
- PP_Time last_accessed_time,
- PP_Time last_modified_time) OVERRIDE;
- virtual int32_t Delete(ppapi::host::ReplyMessageContext context) OVERRIDE;
- virtual int32_t Rename(ppapi::host::ReplyMessageContext context,
- PepperFileRefHost* new_file_ref) OVERRIDE;
- virtual int32_t Query(ppapi::host::ReplyMessageContext context) OVERRIDE;
- virtual int32_t ReadDirectoryEntries(ppapi::host::ReplyMessageContext context)
- OVERRIDE;
- virtual int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context)
- OVERRIDE;
- virtual fileapi::FileSystemURL GetFileSystemURL() const OVERRIDE;
- virtual base::FilePath GetExternalFilePath() const OVERRIDE;
-
- virtual int32_t CanRead() const OVERRIDE;
- virtual int32_t CanWrite() const OVERRIDE;
- virtual int32_t CanCreate() const OVERRIDE;
- virtual int32_t CanReadWrite() const OVERRIDE;
+ int32_t MakeDirectory(ppapi::host::ReplyMessageContext context,
+ int32_t make_directory_flags) override;
+ int32_t Touch(ppapi::host::ReplyMessageContext context,
+ PP_Time last_accessed_time,
+ PP_Time last_modified_time) override;
+ int32_t Delete(ppapi::host::ReplyMessageContext context) override;
+ int32_t Rename(ppapi::host::ReplyMessageContext context,
+ PepperFileRefHost* new_file_ref) override;
+ int32_t Query(ppapi::host::ReplyMessageContext context) override;
+ int32_t ReadDirectoryEntries(
+ ppapi::host::ReplyMessageContext context) override;
+ int32_t GetAbsolutePath(ppapi::host::ReplyMessageContext context) override;
+ storage::FileSystemURL GetFileSystemURL() const override;
+ base::FilePath GetExternalFilePath() const override;
+
+ int32_t CanRead() const override;
+ int32_t CanWrite() const override;
+ int32_t CanCreate() const override;
+ int32_t CanReadWrite() const override;
private:
// Generic reply callback.
@@ -64,12 +63,12 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
const base::File::Info& file_info);
void ReadDirectoryComplete(
ppapi::host::ReplyMessageContext context,
- fileapi::FileSystemOperation::FileEntryList* accumulated_file_list,
+ storage::FileSystemOperation::FileEntryList* accumulated_file_list,
base::File::Error error,
- const fileapi::FileSystemOperation::FileEntryList& file_list,
+ const storage::FileSystemOperation::FileEntryList& file_list,
bool has_more);
- scoped_refptr<fileapi::FileSystemContext> GetFileSystemContext() const;
+ scoped_refptr<storage::FileSystemContext> GetFileSystemContext() const;
ppapi::host::PpapiHost* host_;
int render_process_id_;
@@ -77,7 +76,7 @@ class PepperInternalFileRefBackend : public PepperFileRefBackend {
PP_FileSystemType fs_type_;
std::string path_;
- mutable fileapi::FileSystemURL fs_url_;
+ mutable storage::FileSystemURL fs_url_;
base::WeakPtrFactory<PepperInternalFileRefBackend> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
index 68dac47fc8d..02a89adf016 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_message_filter.h
@@ -24,10 +24,10 @@ class PepperMessageFilter : public BrowserMessageFilter {
PepperMessageFilter();
// BrowserMessageFilter methods.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~PepperMessageFilter();
+ ~PepperMessageFilter() override;
private:
void OnX509CertificateParseDER(const std::vector<char>& der,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
index 12241c5c5b4..71974219a19 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.h
@@ -26,10 +26,10 @@ class CONTENT_EXPORT PepperNetworkMonitorHost
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperNetworkMonitorHost();
+ ~PepperNetworkMonitorHost() override;
// net::NetworkChangeNotifier::IPAddressObserver interface.
- virtual void OnIPAddressChanged() OVERRIDE;
+ void OnIPAddressChanged() override;
private:
void OnPermissionCheckResult(bool can_use_network_monitor);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 4b3d817b66e..b80d1c6f9c3 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -11,6 +11,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/socket_permission_request.h"
+#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/proxy/proxy_info.h"
#include "net/url_request/url_request_context.h"
@@ -145,9 +146,11 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() {
request.reply_context,
base::Owned(proxy_info));
int result = proxy_service_->ResolveProxy(request.url,
+ net::LOAD_NORMAL,
proxy_info,
callback,
&pending_request,
+ NULL,
net::BoundNetLog());
pending_requests_.push(pending_request);
// If it was handled synchronously, we must run the callback now;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
index 28f52b66273..eddbc89a1bd 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperNetworkProxyHost();
+ ~PepperNetworkProxyHost() override;
private:
// We retrieve the appropriate URLRequestContextGetter and whether this API
@@ -55,9 +55,9 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
void DidGetUIThreadData(const UIThreadData&);
// ResourceHost implementation.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
int32_t OnMsgGetProxyForURL(ppapi::host::HostMessageContext* context,
const std::string& url);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
index de5f5fec949..1343f9a12f6 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
@@ -5,6 +5,8 @@
#include "content/browser/renderer_host/pepper/pepper_print_settings_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
#include "ppapi/c/pp_errors.h"
#include "printing/printing_context.h"
#include "printing/units.h"
@@ -13,7 +15,7 @@ namespace content {
namespace {
-#if defined(ENABLE_FULL_PRINTING)
+#if defined(ENABLE_PRINT_PREVIEW)
// Print units conversion functions.
int32_t DeviceUnitsInPoints(int32_t device_units,
int32_t device_units_per_inch) {
@@ -42,12 +44,23 @@ PP_Rect PrintAreaToPPPrintArea(const gfx::Rect& print_area,
return result;
}
+class PrintingContextDelegate : public printing::PrintingContext::Delegate {
+ public:
+ // PrintingContext::Delegate methods.
+ gfx::NativeView GetParentView() override { return NULL; }
+ std::string GetAppLocale() override {
+ return GetContentClient()->browser()->GetApplicationLocale();
+ }
+};
+
PepperPrintSettingsManager::Result ComputeDefaultPrintSettings() {
// This function should run on the UI thread because |PrintingContext| methods
// call into platform APIs.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ PrintingContextDelegate delegate;
scoped_ptr<printing::PrintingContext> context(
- printing::PrintingContext::Create(std::string()));
+ printing::PrintingContext::Create(&delegate));
if (!context.get() ||
context->UseDefaultSettings() != printing::PrintingContext::OK) {
return PepperPrintSettingsManager::Result(PP_PrintSettings_Dev(),
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.h b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.h
index 48a8e9f100e..9199e72655b 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_print_settings_manager.h
@@ -32,11 +32,11 @@ class CONTENT_EXPORT PepperPrintSettingsManagerImpl
: public PepperPrintSettingsManager {
public:
PepperPrintSettingsManagerImpl() {}
- virtual ~PepperPrintSettingsManagerImpl() {}
+ ~PepperPrintSettingsManagerImpl() override {}
// PepperPrintSettingsManager implementation.
- virtual void GetDefaultPrintSettings(
- PepperPrintSettingsManager::Callback callback) OVERRIDE;
+ void GetDefaultPrintSettings(
+ PepperPrintSettingsManager::Callback callback) override;
private:
DISALLOW_COPY_AND_ASSIGN(PepperPrintSettingsManagerImpl);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_printing_host.h b/chromium/content/browser/renderer_host/pepper/pepper_printing_host.h
index ec956292b2d..fb2536d9945 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_printing_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_printing_host.h
@@ -22,12 +22,12 @@ class CONTENT_EXPORT PepperPrintingHost : public ppapi::host::ResourceHost {
PP_Instance instance,
PP_Resource resource,
scoped_ptr<PepperPrintSettingsManager> print_settings_manager);
- virtual ~PepperPrintingHost();
+ ~PepperPrintingHost() override;
// ppapi::host::ResourceHost implementation.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
private:
int32_t OnGetDefaultPrintSettings(ppapi::host::HostMessageContext* context);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc b/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc
index d9780425d20..36b006c8075 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_printing_host_unittest.cc
@@ -21,11 +21,11 @@ namespace {
class MockPepperPrintSettingsManager : public PepperPrintSettingsManager {
public:
MockPepperPrintSettingsManager(const PP_PrintSettings_Dev& settings);
- virtual ~MockPepperPrintSettingsManager() {}
+ ~MockPepperPrintSettingsManager() override {}
// PepperPrintSettingsManager implementation.
- virtual void GetDefaultPrintSettings(
- PepperPrintSettingsManager::Callback callback) OVERRIDE;
+ void GetDefaultPrintSettings(
+ PepperPrintSettingsManager::Callback callback) override;
private:
PP_PrintSettings_Dev settings_;
@@ -47,7 +47,7 @@ class PepperPrintingHostTest : public testing::Test,
public:
PepperPrintingHostTest() {}
- virtual ~PepperPrintingHostTest() {}
+ ~PepperPrintingHostTest() override {}
DISALLOW_COPY_AND_ASSIGN(PepperPrintingHostTest);
};
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
index 5683ab9ed0c..109da1f2856 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_renderer_connection.h
@@ -36,10 +36,10 @@ class PepperRendererConnection : public BrowserMessageFilter {
explicit PepperRendererConnection(int render_process_id);
// BrowserMessageFilter overrides.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
private:
- virtual ~PepperRendererConnection();
+ ~PepperRendererConnection() override;
// Returns the host for the child process for the given |child_process_id|.
// If |child_process_id| is 0, returns the host owned by this
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
index ab516283d58..3bb92bf8b48 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.cc
@@ -77,7 +77,7 @@ bool CanOpenWithPepperFlags(int pp_open_flags,
bool CanOpenFileSystemURLWithPepperFlags(int pp_open_flags,
int child_id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
return CanOpenFileWithPepperFlags(
&ChildProcessSecurityPolicyImpl::CanReadFileSystemFile,
&ChildProcessSecurityPolicyImpl::CanWriteFileSystemFile,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
index d0a39831324..790b4cfe997 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_security_helper.h
@@ -7,7 +7,7 @@
#include "base/files/file_path.h"
#include "content/common/content_export.h"
-#include "webkit/browser/fileapi/file_system_url.h"
+#include "storage/browser/fileapi/file_system_url.h"
namespace content {
@@ -22,7 +22,7 @@ CONTENT_EXPORT bool CanOpenWithPepperFlags(int pp_open_flags,
CONTENT_EXPORT bool CanOpenFileSystemURLWithPepperFlags(
int pp_open_flags,
int child_id,
- const fileapi::FileSystemURL& url);
+ const storage::FileSystemURL& url);
} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
index 43262fc8c1a..b1bc22fe627 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
@@ -41,7 +41,7 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
static size_t GetNumInstances();
protected:
- virtual ~PepperTCPServerSocketMessageFilter();
+ ~PepperTCPServerSocketMessageFilter() override;
private:
enum State {
@@ -53,11 +53,11 @@ class CONTENT_EXPORT PepperTCPServerSocketMessageFilter
};
// ppapi::host::ResourceMessageFilter overrides.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
int32_t OnMsgListen(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& addr,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
index 5c4e066b360..7c9250f4899 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -63,14 +63,14 @@ class CONTENT_EXPORT PepperTCPSocketMessageFilter
static size_t GetNumInstances();
private:
- virtual ~PepperTCPSocketMessageFilter();
+ ~PepperTCPSocketMessageFilter() override;
// ppapi::host::ResourceMessageFilter overrides.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
int32_t OnMsgBind(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& net_addr);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h
new file mode 100644
index 00000000000..f26b9bd9b79
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font.h
@@ -0,0 +1,55 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "ppapi/proxy/serialized_structs.h"
+
+namespace content {
+
+class PepperTrueTypeFont
+ : public base::RefCountedThreadSafe<PepperTrueTypeFont> {
+ public:
+ // Factory method to create a font for the current host.
+ static PepperTrueTypeFont* Create();
+
+ // Initializes the font. Updates the descriptor with the actual font's
+ // characteristics. The exact font will depend on the host platform's font
+ // matching and fallback algorithm. On failure, returns NULL and leaves desc
+ // unchanged.
+ // NOTE: This method may perform long blocking file IO.
+ virtual int32_t Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) = 0;
+
+ // Retrieves an array of TrueType table tags contained in this font. Returns
+ // the number of tags on success, a Pepper error code on failure. 'tags' are
+ // written only on success.
+ // NOTE: This method may perform long blocking file IO. It may be called even
+ // though the call to Initialize failed. Implementors must check validity.
+ virtual int32_t GetTableTags(std::vector<uint32_t>* tags) = 0;
+
+ // Gets a TrueType font table corresponding to the given tag. The 'offset' and
+ // 'max_data_length' parameters determine what part of the table is returned.
+ // Returns the data size in bytes on success, a Pepper error code on failure.
+ // 'data' is written only on success.
+ // NOTE: This method may perform long blocking file IO. It may be called even
+ // though the call to Initialize failed. Implementors must check validity.
+ virtual int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<PepperTrueTypeFont>;
+ virtual ~PepperTrueTypeFont() {};
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc
new file mode 100644
index 00000000000..d259aae2526
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_android.cc
@@ -0,0 +1,16 @@
+// Copyright 2014 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/logging.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+
+namespace content {
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ NOTIMPLEMENTED(); // Not implemented on Android.
+ return NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
new file mode 100644
index 00000000000..060a0e68b40
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.cc
@@ -0,0 +1,159 @@
+// Copyright 2014 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 "content/browser/renderer_host/pepper/pepper_truetype_font_host.h"
+
+#include "base/bind.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+using ppapi::host::HostMessageContext;
+using ppapi::host::ReplyMessageContext;
+using ppapi::proxy::SerializedTrueTypeFontDesc;
+
+namespace content {
+
+PepperTrueTypeFontHost::PepperTrueTypeFontHost(
+ BrowserPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const SerializedTrueTypeFontDesc& desc)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ initialize_completed_(false),
+ weak_factory_(this) {
+ font_ = PepperTrueTypeFont::Create();
+ // Initialize the font on a blocking pool thread. This must complete before
+ // using |font_|.
+ base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
+ task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
+ SerializedTrueTypeFontDesc* actual_desc =
+ new SerializedTrueTypeFontDesc(desc);
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PepperTrueTypeFont::Initialize, font_, actual_desc),
+ base::Bind(&PepperTrueTypeFontHost::OnInitializeComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(actual_desc)));
+}
+
+PepperTrueTypeFontHost::~PepperTrueTypeFontHost() {
+ if (font_.get()) {
+ // Release the font on the task runner in case the implementation requires
+ // long blocking operations.
+ font_->AddRef();
+ PepperTrueTypeFont* raw_font = font_.get();
+ font_ = NULL;
+ task_runner_->ReleaseSoon(FROM_HERE, raw_font);
+ }
+}
+
+int32_t PepperTrueTypeFontHost::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ HostMessageContext* context) {
+ if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV))
+ return PP_ERROR_FAILED;
+
+ PPAPI_BEGIN_MESSAGE_MAP(PepperTrueTypeFontHost, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TrueTypeFont_GetTableTags,
+ OnHostMsgGetTableTags)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TrueTypeFont_GetTable,
+ OnHostMsgGetTable)
+ PPAPI_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperTrueTypeFontHost::OnHostMsgGetTableTags(
+ HostMessageContext* context) {
+ if (!font_.get())
+ return PP_ERROR_FAILED;
+
+ // Get font data on a thread that allows slow blocking operations.
+ std::vector<uint32_t>* tags = new std::vector<uint32_t>();
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PepperTrueTypeFont::GetTableTags, font_, tags),
+ base::Bind(&PepperTrueTypeFontHost::OnGetTableTagsComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(tags),
+ context->MakeReplyMessageContext()));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+int32_t PepperTrueTypeFontHost::OnHostMsgGetTable(HostMessageContext* context,
+ uint32_t table,
+ int32_t offset,
+ int32_t max_data_length) {
+ if (!font_.get())
+ return PP_ERROR_FAILED;
+ if (offset < 0 || max_data_length < 0)
+ return PP_ERROR_BADARGUMENT;
+
+ // Get font data on a thread that allows slow blocking operations.
+ std::string* data = new std::string();
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&PepperTrueTypeFont::GetTable,
+ font_,
+ table,
+ offset,
+ max_data_length,
+ data),
+ base::Bind(&PepperTrueTypeFontHost::OnGetTableComplete,
+ weak_factory_.GetWeakPtr(),
+ base::Owned(data),
+ context->MakeReplyMessageContext()));
+
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperTrueTypeFontHost::OnInitializeComplete(
+ SerializedTrueTypeFontDesc* desc,
+ int32_t result) {
+ DCHECK(!initialize_completed_);
+ initialize_completed_ = true;
+ // Release the font if there was an error, so future calls will fail.
+ if (result != PP_OK)
+ font_ = NULL;
+ host()->SendUnsolicitedReply(
+ pp_resource(), PpapiPluginMsg_TrueTypeFont_CreateReply(*desc, result));
+}
+
+void PepperTrueTypeFontHost::OnGetTableTagsComplete(
+ std::vector<uint32_t>* tags,
+ ReplyMessageContext reply_context,
+ int32_t result) {
+ DCHECK(initialize_completed_);
+ // It's possible that Initialize failed and that |font_| is NULL. Check that
+ // the font implementation doesn't return PP_OK in that case.
+ DCHECK(font_.get() || result != PP_OK);
+ reply_context.params.set_result(result);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_TrueTypeFont_GetTableTagsReply(*tags));
+}
+
+void PepperTrueTypeFontHost::OnGetTableComplete(
+ std::string* data,
+ ReplyMessageContext reply_context,
+ int32_t result) {
+ DCHECK(initialize_completed_);
+ // It's possible that Initialize failed and that |font_| is NULL. Check that
+ // the font implementation doesn't return PP_OK in that case.
+ DCHECK(font_.get() || result != PP_OK);
+ reply_context.params.set_result(result);
+ host()->SendReply(reply_context,
+ PpapiPluginMsg_TrueTypeFont_GetTableReply(*data));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h
new file mode 100644
index 00000000000..b449547010a
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_host.h
@@ -0,0 +1,69 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+#include "content/common/content_export.h"
+#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/resource_host.h"
+
+namespace content {
+
+class BrowserPpapiHost;
+
+class CONTENT_EXPORT PepperTrueTypeFontHost : public ppapi::host::ResourceHost {
+ public:
+ PepperTrueTypeFontHost(BrowserPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource,
+ const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
+
+ ~PepperTrueTypeFontHost() override;
+
+ int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) override;
+
+ private:
+ int32_t OnHostMsgGetTableTags(ppapi::host::HostMessageContext* context);
+ int32_t OnHostMsgGetTable(ppapi::host::HostMessageContext* context,
+ uint32_t table,
+ int32_t offset,
+ int32_t max_data_length);
+
+ void OnInitializeComplete(ppapi::proxy::SerializedTrueTypeFontDesc* desc,
+ int32_t result);
+ void OnGetTableTagsComplete(std::vector<uint32_t>* tags,
+ ppapi::host::ReplyMessageContext reply_context,
+ int32_t result);
+ void OnGetTableComplete(std::string* data,
+ ppapi::host::ReplyMessageContext reply_context,
+ int32_t result);
+
+ // We use a SequencedTaskRunner to run potentially slow font operations and
+ // ensure that Initialize completes before we make any calls to get font data.
+ // Even though we allow multiple pending GetTableTags and GetTable calls, this
+ // implies that they run serially.
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ scoped_refptr<PepperTrueTypeFont> font_;
+ bool initialize_completed_;
+
+ base::WeakPtrFactory<PepperTrueTypeFontHost> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontHost);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
new file mode 100644
index 00000000000..ebfacb87b30
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_linux.cc
@@ -0,0 +1,156 @@
+// Copyright 2014 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/compiler_specific.h"
+#include "base/files/scoped_file.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/sys_byteorder.h"
+#include "content/browser/renderer_host/font_utils_linux.h"
+#include "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+#include "content/public/common/child_process_sandbox_support_linux.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace content {
+
+namespace {
+
+class PepperTrueTypeFontLinux : public PepperTrueTypeFont {
+ public:
+ PepperTrueTypeFontLinux();
+
+ // PepperTrueTypeFont implementation.
+ int32_t Initialize(ppapi::proxy::SerializedTrueTypeFontDesc* desc) override;
+ int32_t GetTableTags(std::vector<uint32_t>* tags) override;
+ int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) override;
+
+ private:
+ ~PepperTrueTypeFontLinux() override;
+
+ base::ScopedFD fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontLinux);
+};
+
+PepperTrueTypeFontLinux::PepperTrueTypeFontLinux() {
+}
+
+PepperTrueTypeFontLinux::~PepperTrueTypeFontLinux() {
+}
+
+int32_t PepperTrueTypeFontLinux::Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+ // If no face is provided, convert family to the platform defaults. These
+ // names should be mapped by FontConfig to an appropriate default font.
+ if (desc->family.empty()) {
+ switch (desc->generic_family) {
+ case PP_TRUETYPEFONTFAMILY_SERIF:
+ desc->family = "serif";
+ break;
+ case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+ desc->family = "sans-serif";
+ break;
+ case PP_TRUETYPEFONTFAMILY_CURSIVE:
+ desc->family = "cursive";
+ break;
+ case PP_TRUETYPEFONTFAMILY_FANTASY:
+ desc->family = "fantasy";
+ break;
+ case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+ desc->family = "monospace";
+ break;
+ }
+ }
+
+ fd_.reset(
+ MatchFontFaceWithFallback(desc->family,
+ desc->weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
+ desc->style & PP_TRUETYPEFONTSTYLE_ITALIC,
+ desc->charset,
+ PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT));
+ // TODO(bbudge) Modify content API to return results of font matching and
+ // fallback, so we can update |desc| to reflect that.
+ return fd_.is_valid() ? PP_OK : PP_ERROR_FAILED;
+}
+
+int32_t PepperTrueTypeFontLinux::GetTableTags(std::vector<uint32_t>* tags) {
+ if (!fd_.is_valid())
+ return PP_ERROR_FAILED;
+ // Get the 2 byte numTables field at an offset of 4 in the font.
+ uint8_t num_tables_buf[2];
+ size_t output_length = sizeof(num_tables_buf);
+ if (!GetFontTable(fd_.get(),
+ 0 /* tag */,
+ 4 /* offset */,
+ reinterpret_cast<uint8_t*>(&num_tables_buf),
+ &output_length))
+ return PP_ERROR_FAILED;
+ DCHECK(output_length == sizeof(num_tables_buf));
+ // Font data is stored in big-endian order.
+ uint16_t num_tables = (num_tables_buf[0] << 8) | num_tables_buf[1];
+
+ // The font has a header, followed by n table entries in its directory.
+ static const size_t kFontHeaderSize = 12;
+ static const size_t kTableEntrySize = 16;
+ output_length = num_tables * kTableEntrySize;
+ scoped_ptr<uint8_t[]> table_entries(new uint8_t[output_length]);
+ // Get the table directory entries, which follow the font header.
+ if (!GetFontTable(fd_.get(),
+ 0 /* tag */,
+ kFontHeaderSize /* offset */,
+ table_entries.get(),
+ &output_length))
+ return PP_ERROR_FAILED;
+ DCHECK(output_length == num_tables * kTableEntrySize);
+
+ tags->resize(num_tables);
+ for (uint16_t i = 0; i < num_tables; i++) {
+ uint8_t* entry = table_entries.get() + i * kTableEntrySize;
+ uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
+ static_cast<uint32_t>(entry[1]) << 16 |
+ static_cast<uint32_t>(entry[2]) << 8 |
+ static_cast<uint32_t>(entry[3]);
+ (*tags)[i] = tag;
+ }
+
+ return num_tables;
+}
+
+int32_t PepperTrueTypeFontLinux::GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ if (!fd_.is_valid())
+ return PP_ERROR_FAILED;
+ // Get the size of the font data first.
+ size_t table_size = 0;
+ // Tags are byte swapped on Linux.
+ table_tag = base::ByteSwap(table_tag);
+ if (!GetFontTable(fd_.get(), table_tag, offset, NULL, &table_size))
+ return PP_ERROR_FAILED;
+ // Only retrieve as much as the caller requested.
+ table_size = std::min(table_size, static_cast<size_t>(max_data_length));
+ data->resize(table_size);
+ if (!GetFontTable(fd_.get(),
+ table_tag,
+ offset,
+ reinterpret_cast<uint8_t*>(&(*data)[0]),
+ &table_size))
+ return PP_ERROR_FAILED;
+
+ return base::checked_cast<int32_t>(table_size);
+}
+
+} // namespace
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ return new PepperTrueTypeFontLinux();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
index 7479046cfe7..3730724aa25 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.cc
@@ -27,14 +27,14 @@ class FontMessageFilter : public ppapi::host::ResourceMessageFilter {
FontMessageFilter();
// ppapi::host::ResourceMessageFilter implementation.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
private:
- virtual ~FontMessageFilter();
+ ~FontMessageFilter() override;
// Message handlers.
int32_t OnHostMsgGetFontFamilies(ppapi::host::HostMessageContext* context);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
index 69a471bb33e..19999ca1f59 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_host.h
@@ -17,7 +17,7 @@ class PepperTrueTypeFontListHost : public ppapi::host::ResourceHost {
PepperTrueTypeFontListHost(BrowserPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperTrueTypeFontListHost();
+ ~PepperTrueTypeFontListHost() override;
private:
DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontListHost);
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
index 8e275904081..158d8ea9de1 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_list_win.cc
@@ -63,7 +63,7 @@ void GetFontFamilies_SlowBlocking(FontFamilyList* font_families) {
memset(&logfont, 0, sizeof(logfont));
logfont.lfCharSet = DEFAULT_CHARSET;
base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
- ::EnumFontFamiliesExW(hdc,
+ ::EnumFontFamiliesExW(hdc.Get(),
&logfont,
(FONTENUMPROCW) & EnumFontFamiliesProc,
(LPARAM)font_families,
@@ -78,7 +78,7 @@ void GetFontsInFamily_SlowBlocking(const std::string& family,
base::string16 family16 = base::UTF8ToUTF16(family);
memcpy(&logfont.lfFaceName, &family16[0], sizeof(logfont.lfFaceName));
base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
- ::EnumFontFamiliesExW(hdc,
+ ::EnumFontFamiliesExW(hdc.Get(),
&logfont,
(FONTENUMPROCW) & EnumFontsInFamilyProc,
(LPARAM)fonts_in_family,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm
new file mode 100644
index 00000000000..1e52e172bbf
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_mac.mm
@@ -0,0 +1,412 @@
+// Copyright 2014 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 "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+
+#import <ApplicationServices/ApplicationServices.h>
+
+#include <stdio.h>
+
+#include "base/compiler_specific.h"
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace content {
+
+namespace {
+
+static bool FindFloat(CFDictionaryRef dict, CFStringRef name, float* value) {
+ CFNumberRef num;
+ return CFDictionaryGetValueIfPresent(
+ dict, name, reinterpret_cast<const void**>(&num)) &&
+ CFNumberIsFloatType(num) &&
+ CFNumberGetValue(num, kCFNumberFloatType, value);
+}
+
+float GetMacWeight(PP_TrueTypeFontWeight_Dev weight) {
+ // Map values from NORMAL (400) to HEAVY (900) to the range [0 .. 1], and
+ // values below NORMAL to the range [-0.6 .. 0]. NORMAL should map to 0.
+ float normal = PP_TRUETYPEFONTWEIGHT_NORMAL;
+ float heavy = PP_TRUETYPEFONTWEIGHT_HEAVY;
+ return (weight - normal) / (heavy - normal);
+}
+
+PP_TrueTypeFontWeight_Dev GetPepperWeight(float weight) {
+ // Perform the inverse mapping of GetMacWeight.
+ return static_cast<PP_TrueTypeFontWeight_Dev>(
+ weight * (PP_TRUETYPEFONTWEIGHT_HEAVY - PP_TRUETYPEFONTWEIGHT_NORMAL) +
+ PP_TRUETYPEFONTWEIGHT_NORMAL);
+}
+
+float GetMacWidth(PP_TrueTypeFontWidth_Dev width) {
+ // Map values from NORMAL (4) to ULTRA_EXPANDED (8) to the range [0 .. 1],
+ // and values below NORMAL to the range [-1 .. 0]. Normal should map to 0.
+ float normal = PP_TRUETYPEFONTWIDTH_NORMAL;
+ float ultra_expanded = PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED;
+ return (width - normal) / (ultra_expanded - normal);
+}
+
+PP_TrueTypeFontWidth_Dev GetPepperWidth(float width) {
+ // Perform the inverse mapping of GetMacWeight.
+ return static_cast<PP_TrueTypeFontWidth_Dev>(
+ width *
+ (PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED - PP_TRUETYPEFONTWIDTH_NORMAL) +
+ PP_TRUETYPEFONTWIDTH_NORMAL);
+}
+
+#define MAKE_TABLE_TAG(a, b, c, d) ((a) << 24) + ((b) << 16) + ((c) << 8) + (d)
+
+// TrueType font header and table entry structs. See
+// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
+struct FontHeader {
+ int32_t font_type;
+ uint16_t num_tables;
+ uint16_t search_range;
+ uint16_t entry_selector;
+ uint16_t range_shift;
+};
+static_assert(sizeof(FontHeader) == 12, "FontHeader wrong size");
+
+struct FontDirectoryEntry {
+ uint32_t tag;
+ uint32_t checksum;
+ uint32_t offset;
+ uint32_t logical_length;
+};
+static_assert(sizeof(FontDirectoryEntry) == 16,
+ "FontDirectoryEntry wrong size");
+
+uint32_t CalculateChecksum(char* table, int32_t table_length) {
+ uint32_t sum = 0;
+ uint32_t* current = reinterpret_cast<uint32_t*>(table);
+ uint32_t length = (table_length + 3) / 4;
+ // Raw font data is big-endian.
+ while (length-- > 0)
+ sum += base::NetToHost32(*current++);
+ return sum;
+}
+
+class PepperTrueTypeFontMac : public PepperTrueTypeFont {
+ public:
+ PepperTrueTypeFontMac();
+
+ // PepperTrueTypeFont implementation.
+ int32_t Initialize(ppapi::proxy::SerializedTrueTypeFontDesc* desc) override;
+ int32_t GetTableTags(std::vector<uint32_t>* tags) override;
+ int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) override;
+
+ private:
+ ~PepperTrueTypeFontMac() override;
+
+ virtual int32_t GetEntireFont(int32_t offset,
+ int32_t max_data_length,
+ std::string* data);
+
+ base::ScopedCFTypeRef<CTFontRef> font_ref_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontMac);
+};
+
+PepperTrueTypeFontMac::PepperTrueTypeFontMac() {
+}
+
+PepperTrueTypeFontMac::~PepperTrueTypeFontMac() {
+}
+
+int32_t PepperTrueTypeFontMac::Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+ // Create the font in a nested scope, so we can use the same variable names
+ // when we get the actual font characteristics.
+ {
+ // Create attributes and traits dictionaries.
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> attributes_ref(
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> traits_ref(
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ if (!attributes_ref || !traits_ref)
+ return PP_ERROR_FAILED;
+
+ CFDictionaryAddValue(attributes_ref, kCTFontTraitsAttribute, traits_ref);
+
+ // Use symbolic traits to specify traits when possible.
+ CTFontSymbolicTraits symbolic_traits = 0;
+ if (desc->style & PP_TRUETYPEFONTSTYLE_ITALIC)
+ symbolic_traits |= kCTFontItalicTrait;
+ if (desc->weight == PP_TRUETYPEFONTWEIGHT_BOLD)
+ symbolic_traits |= kCTFontBoldTrait;
+ if (desc->width == PP_TRUETYPEFONTWIDTH_CONDENSED)
+ symbolic_traits |= kCTFontCondensedTrait;
+ else if (desc->width == PP_TRUETYPEFONTWIDTH_EXPANDED)
+ symbolic_traits |= kCTFontExpandedTrait;
+
+ base::ScopedCFTypeRef<CFNumberRef> symbolic_traits_ref(CFNumberCreate(
+ kCFAllocatorDefault, kCFNumberSInt32Type, &symbolic_traits));
+ if (!symbolic_traits_ref)
+ return PP_ERROR_FAILED;
+ CFDictionaryAddValue(traits_ref, kCTFontSymbolicTrait, symbolic_traits_ref);
+
+ // Font family matching doesn't work using family classes in symbolic
+ // traits. Instead, map generic_family to font families that are always
+ // available.
+ std::string family(desc->family);
+ if (family.empty()) {
+ switch (desc->generic_family) {
+ case PP_TRUETYPEFONTFAMILY_SERIF:
+ family = "Times";
+ break;
+ case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+ family = "Helvetica";
+ break;
+ case PP_TRUETYPEFONTFAMILY_CURSIVE:
+ family = "Apple Chancery";
+ break;
+ case PP_TRUETYPEFONTFAMILY_FANTASY:
+ family = "Papyrus";
+ break;
+ case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+ family = "Courier";
+ break;
+ }
+ }
+
+ base::ScopedCFTypeRef<CFStringRef> name_ref(
+ base::SysUTF8ToCFStringRef(family));
+ if (name_ref)
+ CFDictionaryAddValue(
+ attributes_ref, kCTFontFamilyNameAttribute, name_ref);
+
+ if (desc->weight != PP_TRUETYPEFONTWEIGHT_NORMAL &&
+ desc->weight != PP_TRUETYPEFONTWEIGHT_BOLD) {
+ float weight = GetMacWeight(desc->weight);
+ base::ScopedCFTypeRef<CFNumberRef> weight_trait_ref(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &weight));
+ if (weight_trait_ref)
+ CFDictionaryAddValue(traits_ref, kCTFontWeightTrait, weight_trait_ref);
+ }
+
+ if (desc->width != PP_TRUETYPEFONTWIDTH_NORMAL &&
+ desc->width != PP_TRUETYPEFONTWIDTH_CONDENSED &&
+ desc->width != PP_TRUETYPEFONTWIDTH_EXPANDED) {
+ float width = GetMacWidth(desc->width);
+ base::ScopedCFTypeRef<CFNumberRef> width_trait_ref(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &width));
+ if (width_trait_ref)
+ CFDictionaryAddValue(traits_ref, kCTFontWidthTrait, width_trait_ref);
+ }
+
+ base::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
+ CTFontDescriptorCreateWithAttributes(attributes_ref));
+
+ if (desc_ref)
+ font_ref_.reset(CTFontCreateWithFontDescriptor(desc_ref, 0, NULL));
+
+ if (!font_ref_.get())
+ return PP_ERROR_FAILED;
+ }
+
+ // Now query to get the actual font characteristics.
+ base::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
+ CTFontCopyFontDescriptor(font_ref_));
+
+ base::ScopedCFTypeRef<CFStringRef> family_name_ref(
+ base::mac::CFCast<CFStringRef>(
+ CTFontDescriptorCopyAttribute(desc_ref, kCTFontFamilyNameAttribute)));
+ desc->family = base::SysCFStringRefToUTF8(family_name_ref);
+
+ base::ScopedCFTypeRef<CFDictionaryRef> traits_ref(
+ base::mac::CFCast<CFDictionaryRef>(
+ CTFontDescriptorCopyAttribute(desc_ref, kCTFontTraitsAttribute)));
+
+ desc->style = PP_TRUETYPEFONTSTYLE_NORMAL;
+ CTFontSymbolicTraits symbolic_traits(CTFontGetSymbolicTraits(font_ref_));
+ if (symbolic_traits & kCTFontItalicTrait)
+ desc->style = static_cast<PP_TrueTypeFontStyle_Dev>(
+ desc->style | PP_TRUETYPEFONTSTYLE_ITALIC);
+ if (symbolic_traits & kCTFontBoldTrait) {
+ desc->weight = PP_TRUETYPEFONTWEIGHT_BOLD;
+ } else {
+ float weight;
+ if (FindFloat(traits_ref, kCTFontWeightTrait, &weight))
+ desc->weight = GetPepperWeight(weight);
+ }
+ if (symbolic_traits & kCTFontCondensedTrait) {
+ desc->width = PP_TRUETYPEFONTWIDTH_CONDENSED;
+ } else if (symbolic_traits & kCTFontExpandedTrait) {
+ desc->width = PP_TRUETYPEFONTWIDTH_EXPANDED;
+ } else {
+ float width;
+ if (FindFloat(traits_ref, kCTFontWidthTrait, &width))
+ desc->width = GetPepperWidth(width);
+ }
+
+ // Character set isn't supported on Mac.
+ desc->charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
+ return PP_OK;
+}
+
+int32_t PepperTrueTypeFontMac::GetTableTags(std::vector<uint32_t>* tags) {
+ if (!font_ref_.get())
+ return PP_ERROR_FAILED;
+ base::ScopedCFTypeRef<CFArrayRef> tag_array(
+ CTFontCopyAvailableTables(font_ref_, kCTFontTableOptionNoOptions));
+ if (!tag_array)
+ return PP_ERROR_FAILED;
+
+ // Items returned by CTFontCopyAvailableTables are not boxed. Whose bright
+ // idea was this?
+ CFIndex length = CFArrayGetCount(tag_array);
+ tags->resize(length);
+ for (CFIndex i = 0; i < length; ++i) {
+ (*tags)[i] =
+ reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(tag_array, i));
+ }
+ return length;
+}
+
+int32_t PepperTrueTypeFontMac::GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ if (!font_ref_.get())
+ return PP_ERROR_FAILED;
+
+ if (!table_tag)
+ return GetEntireFont(offset, max_data_length, data);
+
+ base::ScopedCFTypeRef<CFDataRef> table_ref(
+ CTFontCopyTable(font_ref_,
+ static_cast<CTFontTableTag>(table_tag),
+ kCTFontTableOptionNoOptions));
+ if (!table_ref)
+ return PP_ERROR_FAILED;
+
+ CFIndex table_size = CFDataGetLength(table_ref);
+ CFIndex safe_offset =
+ std::min(base::checked_cast<CFIndex>(offset), table_size);
+ CFIndex safe_length = std::min(table_size - safe_offset,
+ base::checked_cast<CFIndex>(max_data_length));
+ data->resize(safe_length);
+ CFDataGetBytes(table_ref,
+ CFRangeMake(safe_offset, safe_length),
+ reinterpret_cast<UInt8*>(&(*data)[0]));
+
+ return safe_length;
+}
+
+int32_t PepperTrueTypeFontMac::GetEntireFont(int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ // Reconstruct the font header, table directory, and tables.
+ std::vector<uint32_t> table_tags;
+ int32_t table_count = GetTableTags(&table_tags);
+ if (table_count < 0)
+ return table_count; // PPAPI error code.
+
+ // Allocate enough room for the header and the table directory entries.
+ std::string font(
+ sizeof(FontHeader) + sizeof(FontDirectoryEntry) * table_count, 0);
+ // Map the OS X font type value to a TrueType scalar type.
+ base::ScopedCFTypeRef<CFNumberRef> font_type_ref(
+ base::mac::CFCast<CFNumberRef>(
+ CTFontCopyAttribute(font_ref_, kCTFontFormatAttribute)));
+ int32_t font_type;
+ CFNumberGetValue(font_type_ref, kCFNumberSInt32Type, &font_type);
+ switch (font_type) {
+ case kCTFontFormatOpenTypePostScript:
+ font_type = MAKE_TABLE_TAG('O', 'T', 'T', 'O');
+ break;
+ case kCTFontFormatTrueType:
+ case kCTFontFormatBitmap:
+ font_type = MAKE_TABLE_TAG('t', 'r', 'u', 'e');
+ break;
+ case kCTFontFormatPostScript:
+ font_type = MAKE_TABLE_TAG('t', 'y', 'p', '1');
+ break;
+ case kCTFontFormatOpenTypeTrueType:
+ case kCTFontFormatUnrecognized:
+ default:
+ font_type = MAKE_TABLE_TAG(0, 1, 0, 0);
+ break;
+ }
+
+ // Calculate the rest of the header values.
+ uint16_t num_tables = base::checked_cast<uint16_t>(table_count);
+ uint16_t entry_selector = 0;
+ uint16_t search_range = 1;
+ while (search_range < (num_tables >> 1)) {
+ entry_selector++;
+ search_range <<= 1;
+ }
+ search_range <<= 4;
+ uint16_t range_shift = (num_tables << 4) - search_range;
+
+ // Write the header, with values in big-endian order.
+ FontHeader* font_header = reinterpret_cast<FontHeader*>(&font[0]);
+ font_header->font_type = base::HostToNet32(font_type);
+ font_header->num_tables = base::HostToNet16(num_tables);
+ font_header->search_range = base::HostToNet16(search_range);
+ font_header->entry_selector = base::HostToNet16(entry_selector);
+ font_header->range_shift = base::HostToNet16(range_shift);
+
+ for (int32_t i = 0; i < table_count; i++) {
+ // Get the table data.
+ std::string table;
+ int32_t table_size =
+ GetTable(table_tags[i], 0, std::numeric_limits<int32_t>::max(), &table);
+ if (table_size < 0)
+ return table_size; // PPAPI error code.
+
+ // Append it to the font data so far, and zero pad so tables stay aligned.
+ size_t table_offset = font.size();
+ font.append(table);
+ size_t padding = font.size() & 0x3;
+ font.append(padding, 0);
+
+ // Fill in the directory entry for this table.
+ FontDirectoryEntry* entry = reinterpret_cast<FontDirectoryEntry*>(
+ &font[0] + sizeof(FontHeader) + i * sizeof(FontDirectoryEntry));
+ entry->tag = base::HostToNet32(table_tags[i]);
+ entry->checksum =
+ base::HostToNet32(CalculateChecksum(&font[table_offset], table_size));
+ entry->offset = base::HostToNet32(table_offset);
+ entry->logical_length = base::HostToNet32(table_size);
+ // TODO(bbudge) set the 'head' table checksumAdjustment.
+ }
+
+ // Extract a substring if the caller specified an offset or max data length.
+ int32_t font_size = base::checked_cast<int32_t>(font.size());
+ int32_t safe_offset = std::min(offset, font_size);
+ int32_t safe_length = std::min(font_size - safe_offset, max_data_length);
+ if (safe_offset || safe_length != font_size)
+ font = font.substr(safe_offset, safe_length);
+
+ data->clear();
+ data->swap(font);
+ return safe_length;
+}
+
+} // namespace
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ return new PepperTrueTypeFontMac();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc
new file mode 100644
index 00000000000..6eb36a1e358
--- /dev/null
+++ b/chromium/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc
@@ -0,0 +1,237 @@
+// Copyright 2014 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 "content/browser/renderer_host/pepper/pepper_truetype_font.h"
+
+#include <windows.h>
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "base/win/scoped_gdi_object.h"
+#include "base/win/scoped_hdc.h"
+#include "base/win/scoped_select_object.h"
+#include "ppapi/c/dev/ppb_truetype_font_dev.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace content {
+
+namespace {
+
+class PepperTrueTypeFontWin : public PepperTrueTypeFont {
+ public:
+ PepperTrueTypeFontWin();
+
+ // PepperTrueTypeFont implementation.
+ virtual int32_t Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) override;
+ virtual int32_t GetTableTags(std::vector<uint32_t>* tags) override;
+ virtual int32_t GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) override;
+
+ private:
+ virtual ~PepperTrueTypeFontWin();
+
+ DWORD GetFontData(HDC hdc,
+ DWORD table,
+ DWORD offset,
+ LPVOID buffer,
+ DWORD length);
+
+ base::win::ScopedHFONT font_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
+};
+
+PepperTrueTypeFontWin::PepperTrueTypeFontWin() {
+}
+
+PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
+}
+
+int32_t PepperTrueTypeFontWin::Initialize(
+ ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
+ DWORD pitch_and_family = DEFAULT_PITCH;
+ switch (desc->generic_family) {
+ case PP_TRUETYPEFONTFAMILY_SERIF:
+ pitch_and_family |= FF_ROMAN;
+ break;
+ case PP_TRUETYPEFONTFAMILY_SANSSERIF:
+ pitch_and_family |= FF_SWISS;
+ break;
+ case PP_TRUETYPEFONTFAMILY_CURSIVE:
+ pitch_and_family |= FF_SCRIPT;
+ break;
+ case PP_TRUETYPEFONTFAMILY_FANTASY:
+ pitch_and_family |= FF_DECORATIVE;
+ break;
+ case PP_TRUETYPEFONTFAMILY_MONOSPACE:
+ pitch_and_family |= FF_MODERN;
+ break;
+ }
+ // TODO(bbudge) support widths (extended, condensed).
+
+ font_.Set(CreateFont(0 /* height */,
+ 0 /* width */,
+ 0 /* escapement */,
+ 0 /* orientation */,
+ desc->weight, // our weight enum matches Windows.
+ (desc->style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
+ 0 /* underline */,
+ 0 /* strikeout */,
+ desc->charset, // our charset enum matches Windows.
+ OUT_OUTLINE_PRECIS, // truetype and other outline fonts
+ CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,
+ pitch_and_family,
+ base::UTF8ToUTF16(desc->family).c_str()));
+ if (!font_.Get())
+ return PP_ERROR_FAILED;
+
+ LOGFONT font_desc;
+ if (!::GetObject(font_.Get(), sizeof(LOGFONT), &font_desc))
+ return PP_ERROR_FAILED;
+
+ switch (font_desc.lfPitchAndFamily & 0xF0) { // Top 4 bits are family.
+ case FF_ROMAN:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
+ break;
+ case FF_SWISS:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
+ break;
+ case FF_SCRIPT:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
+ break;
+ case FF_DECORATIVE:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
+ break;
+ case FF_MODERN:
+ desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
+ break;
+ }
+
+ desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC
+ : PP_TRUETYPEFONTSTYLE_NORMAL;
+ desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight);
+ desc->width = PP_TRUETYPEFONTWIDTH_NORMAL;
+ desc->charset = static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
+
+ // To get the face name, select the font and query for the name. GetObject
+ // doesn't fill in the name field of the LOGFONT structure.
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ if (hdc.IsValid()) {
+ base::win::ScopedSelectObject select_object(hdc.Get(), font_.Get());
+ WCHAR name[LF_FACESIZE];
+ GetTextFace(hdc.Get(), LF_FACESIZE, name);
+ desc->family = base::UTF16ToUTF8(name);
+ }
+
+ return PP_OK;
+}
+
+int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
+ if (!font_.Get())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ if (!hdc.IsValid())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedSelectObject select_object(hdc.Get(), font_.Get());
+
+ // Get the whole font header.
+ static const DWORD kFontHeaderSize = 12;
+ uint8_t header_buf[kFontHeaderSize];
+ if (GetFontData(hdc.Get(), 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
+ return PP_ERROR_FAILED;
+
+ // The numTables follows a 4 byte scalerType tag. Font data is stored in
+ // big-endian order.
+ DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
+
+ // The size in bytes of an entry in the table directory.
+ static const DWORD kDirectoryEntrySize = 16;
+ DWORD directory_size = num_tables * kDirectoryEntrySize;
+ scoped_ptr<uint8_t[]> directory(new uint8_t[directory_size]);
+ // Get the table directory entries after the font header.
+ if (GetFontData(hdc.Get(), 0 /* tag */, kFontHeaderSize, directory.get(),
+ directory_size) ==
+ GDI_ERROR)
+ return PP_ERROR_FAILED;
+
+ tags->resize(num_tables);
+ for (DWORD i = 0; i < num_tables; i++) {
+ const uint8_t* entry = directory.get() + i * kDirectoryEntrySize;
+ uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
+ static_cast<uint32_t>(entry[1]) << 16 |
+ static_cast<uint32_t>(entry[2]) << 8 |
+ static_cast<uint32_t>(entry[3]);
+ (*tags)[i] = tag;
+ }
+
+ return num_tables;
+}
+
+int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
+ int32_t offset,
+ int32_t max_data_length,
+ std::string* data) {
+ if (!font_.Get())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
+ if (!hdc.IsValid())
+ return PP_ERROR_FAILED;
+
+ base::win::ScopedSelectObject select_object(hdc.Get(), font_.Get());
+
+ // Tags are byte swapped on Windows.
+ table_tag = base::ByteSwap(table_tag);
+ // Get the size of the font table first.
+ DWORD table_size = GetFontData(hdc.Get(), table_tag, 0, NULL, 0);
+ if (table_size == GDI_ERROR)
+ return PP_ERROR_FAILED;
+
+ DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
+ DWORD safe_length =
+ std::min(table_size - safe_offset, static_cast<DWORD>(max_data_length));
+ data->resize(safe_length);
+ if (safe_length == 0) {
+ table_size = 0;
+ } else {
+ table_size = GetFontData(hdc.Get(),
+ table_tag,
+ safe_offset,
+ reinterpret_cast<uint8_t*>(&(*data)[0]),
+ safe_length);
+ if (table_size == GDI_ERROR)
+ return PP_ERROR_FAILED;
+ }
+ return static_cast<int32_t>(table_size);
+}
+
+DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
+ DWORD table,
+ DWORD offset,
+ void* buffer,
+ DWORD length) {
+ // If this is a zero byte read, return a successful result.
+ if (buffer && !length)
+ return 0;
+
+ return ::GetFontData(hdc, table, offset, buffer, length);
+}
+
+} // namespace
+
+// static
+PepperTrueTypeFont* PepperTrueTypeFont::Create() {
+ return new PepperTrueTypeFontWin();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index a4ed3dca46e..26c0e44ee34 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -23,6 +23,7 @@
#include "ppapi/host/error_conversion.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/udp_socket_resource_base.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
@@ -46,6 +47,8 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
: allow_address_reuse_(false),
allow_broadcast_(false),
closed_(false),
+ remaining_recv_slots_(
+ ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots),
external_plugin_(host->external_plugin()),
private_api_(private_api),
render_process_id_(0),
@@ -74,8 +77,8 @@ PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
switch (message.type()) {
case PpapiHostMsg_UDPSocket_SetOption::ID:
- case PpapiHostMsg_UDPSocket_RecvFrom::ID:
case PpapiHostMsg_UDPSocket_Close::ID:
+ case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID:
return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
case PpapiHostMsg_UDPSocket_Bind::ID:
case PpapiHostMsg_UDPSocket_SendTo::ID:
@@ -91,12 +94,12 @@ int32_t PepperUDPSocketMessageFilter::OnResourceMessageReceived(
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SetOption,
OnMsgSetOption)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_Bind, OnMsgBind)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_RecvFrom,
- OnMsgRecvFrom)
PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SendTo,
OnMsgSendTo)
PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_UDPSocket_Close,
OnMsgClose)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+ PpapiHostMsg_UDPSocket_RecvSlotAvailable, OnMsgRecvSlotAvailable)
PPAPI_END_MESSAGE_MAP()
return PP_ERROR_FAILED;
}
@@ -188,45 +191,6 @@ int32_t PepperUDPSocketMessageFilter::OnMsgBind(
return PP_OK_COMPLETIONPENDING;
}
-int32_t PepperUDPSocketMessageFilter::OnMsgRecvFrom(
- const ppapi::host::HostMessageContext* context,
- int32_t num_bytes) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(context);
- DCHECK(socket_.get());
-
- if (closed_ || !socket_.get())
- return PP_ERROR_FAILED;
-
- if (recvfrom_buffer_.get())
- return PP_ERROR_INPROGRESS;
-
- if (num_bytes <= 0 ||
- num_bytes > ppapi::proxy::UDPSocketResourceBase::kMaxReadSize) {
- // |num_bytes| value is checked on the plugin side.
- NOTREACHED();
- return PP_ERROR_BADARGUMENT;
- }
-
- recvfrom_buffer_ = new net::IOBuffer(num_bytes);
-
- // Use base::Unretained(this), so that the lifespan of this object doesn't
- // have to last until the callback is called.
- // It is safe to do so because |socket_| is owned by this object. If this
- // object gets destroyed (and so does |socket_|), the callback won't be
- // called.
- int net_result = socket_->RecvFrom(
- recvfrom_buffer_.get(),
- num_bytes,
- &recvfrom_address_,
- base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
- base::Unretained(this),
- context->MakeReplyMessageContext()));
- if (net_result != net::ERR_IO_PENDING)
- OnRecvFromCompleted(context->MakeReplyMessageContext(), net_result);
- return PP_OK_COMPLETIONPENDING;
-}
-
int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
const ppapi::host::HostMessageContext* context,
const std::string& data,
@@ -262,6 +226,23 @@ int32_t PepperUDPSocketMessageFilter::OnMsgClose(
return PP_OK;
}
+int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable(
+ const ppapi::host::HostMessageContext* context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (remaining_recv_slots_ <
+ ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots) {
+ remaining_recv_slots_++;
+ }
+
+ if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
+ DCHECK_EQ(1u, remaining_recv_slots_);
+ DoRecvFrom();
+ }
+
+ return PP_OK;
+}
+
void PepperUDPSocketMessageFilter::DoBind(
const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& addr) {
@@ -312,6 +293,33 @@ void PepperUDPSocketMessageFilter::DoBind(
allow_broadcast_ = false;
socket_.swap(socket);
SendBindReply(context, PP_OK, net_address);
+
+ DoRecvFrom();
+}
+
+void PepperUDPSocketMessageFilter::DoRecvFrom() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!closed_);
+ DCHECK(socket_.get());
+ DCHECK(!recvfrom_buffer_.get());
+ DCHECK_GT(remaining_recv_slots_, 0u);
+
+ recvfrom_buffer_ = new net::IOBuffer(
+ ppapi::proxy::UDPSocketResourceBase::kMaxReadSize);
+
+ // Use base::Unretained(this), so that the lifespan of this object doesn't
+ // have to last until the callback is called.
+ // It is safe to do so because |socket_| is owned by this object. If this
+ // object gets destroyed (and so does |socket_|), the callback won't be
+ // called.
+ int net_result = socket_->RecvFrom(
+ recvfrom_buffer_.get(),
+ ppapi::proxy::UDPSocketResourceBase::kMaxReadSize,
+ &recvfrom_address_,
+ base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
+ base::Unretained(this)));
+ if (net_result != net::ERR_IO_PENDING)
+ OnRecvFromCompleted(net_result);
}
void PepperUDPSocketMessageFilter::DoSendTo(
@@ -371,9 +379,7 @@ void PepperUDPSocketMessageFilter::Close() {
closed_ = true;
}
-void PepperUDPSocketMessageFilter::OnRecvFromCompleted(
- const ppapi::host::ReplyMessageContext& context,
- int net_result) {
+void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(recvfrom_buffer_.get());
@@ -389,13 +395,19 @@ void PepperUDPSocketMessageFilter::OnRecvFromCompleted(
}
if (pp_result >= 0) {
- SendRecvFromReply(
- context, PP_OK, std::string(recvfrom_buffer_->data(), pp_result), addr);
+ SendRecvFromResult(PP_OK, std::string(recvfrom_buffer_->data(), pp_result),
+ addr);
} else {
- SendRecvFromError(context, pp_result);
+ SendRecvFromError(pp_result);
}
recvfrom_buffer_ = NULL;
+
+ DCHECK_GT(remaining_recv_slots_, 0u);
+ remaining_recv_slots_--;
+
+ if (remaining_recv_slots_ > 0 && !closed_ && socket_.get())
+ DoRecvFrom();
}
void PepperUDPSocketMessageFilter::OnSendToCompleted(
@@ -421,14 +433,15 @@ void PepperUDPSocketMessageFilter::SendBindReply(
SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr));
}
-void PepperUDPSocketMessageFilter::SendRecvFromReply(
- const ppapi::host::ReplyMessageContext& context,
+void PepperUDPSocketMessageFilter::SendRecvFromResult(
int32_t result,
const std::string& data,
const PP_NetAddress_Private& addr) {
- ppapi::host::ReplyMessageContext reply_context(context);
- reply_context.params.set_result(result);
- SendReply(reply_context, PpapiPluginMsg_UDPSocket_RecvFromReply(data, addr));
+ if (resource_host()) {
+ resource_host()->host()->SendUnsolicitedReply(
+ resource_host()->pp_resource(),
+ PpapiPluginMsg_UDPSocket_PushRecvResult(result, data, addr));
+ }
}
void PepperUDPSocketMessageFilter::SendSendToReply(
@@ -447,12 +460,9 @@ void PepperUDPSocketMessageFilter::SendBindError(
}
void PepperUDPSocketMessageFilter::SendRecvFromError(
- const ppapi::host::ReplyMessageContext& context,
int32_t result) {
- SendRecvFromReply(context,
- result,
- std::string(),
- NetAddressPrivateImpl::kInvalidNetAddress);
+ SendRecvFromResult(result, std::string(),
+ NetAddressPrivateImpl::kInvalidNetAddress);
}
void PepperUDPSocketMessageFilter::SendSendToError(
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
index 8ca7f0800bc..1aa2c36cad4 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
@@ -53,55 +53,53 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
static size_t GetNumInstances();
protected:
- virtual ~PepperUDPSocketMessageFilter();
+ ~PepperUDPSocketMessageFilter() override;
private:
// ppapi::host::ResourceMessageFilter overrides.
- virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
- virtual int32_t OnResourceMessageReceived(
+ scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
int32_t OnMsgSetOption(const ppapi::host::HostMessageContext* context,
PP_UDPSocket_Option name,
const ppapi::SocketOptionData& value);
int32_t OnMsgBind(const ppapi::host::HostMessageContext* context,
const PP_NetAddress_Private& addr);
- int32_t OnMsgRecvFrom(const ppapi::host::HostMessageContext* context,
- int32_t num_bytes);
int32_t OnMsgSendTo(const ppapi::host::HostMessageContext* context,
const std::string& data,
const PP_NetAddress_Private& addr);
int32_t OnMsgClose(const ppapi::host::HostMessageContext* context);
+ int32_t OnMsgRecvSlotAvailable(
+ const ppapi::host::HostMessageContext* context);
void DoBind(const ppapi::host::ReplyMessageContext& context,
const PP_NetAddress_Private& addr);
+ void DoRecvFrom();
void DoSendTo(const ppapi::host::ReplyMessageContext& context,
const std::string& data,
const PP_NetAddress_Private& addr);
void Close();
- void OnRecvFromCompleted(const ppapi::host::ReplyMessageContext& context,
- int net_result);
+ void OnRecvFromCompleted(int net_result);
void OnSendToCompleted(const ppapi::host::ReplyMessageContext& context,
int net_result);
void SendBindReply(const ppapi::host::ReplyMessageContext& context,
int32_t result,
const PP_NetAddress_Private& addr);
- void SendRecvFromReply(const ppapi::host::ReplyMessageContext& context,
- int32_t result,
- const std::string& data,
- const PP_NetAddress_Private& addr);
+ void SendRecvFromResult(int32_t result,
+ const std::string& data,
+ const PP_NetAddress_Private& addr);
void SendSendToReply(const ppapi::host::ReplyMessageContext& context,
int32_t result,
int32_t bytes_written);
void SendBindError(const ppapi::host::ReplyMessageContext& context,
int32_t result);
- void SendRecvFromError(const ppapi::host::ReplyMessageContext& context,
- int32_t result);
+ void SendRecvFromError(int32_t result);
void SendSendToError(const ppapi::host::ReplyMessageContext& context,
int32_t result);
@@ -116,6 +114,8 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
net::IPEndPoint recvfrom_address_;
+ size_t remaining_recv_slots_;
+
bool external_plugin_;
bool private_api_;
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
index 85a404cac36..5343cbd153f 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
@@ -7,26 +7,26 @@
#include "base/bind.h"
#include "base/callback.h"
#include "content/public/browser/browser_thread.h"
-#include "webkit/browser/fileapi/file_system_operation_runner.h"
-#include "webkit/browser/fileapi/quota/open_file_handle.h"
-#include "webkit/browser/fileapi/quota/quota_reservation.h"
-#include "webkit/common/fileapi/file_system_util.h"
+#include "storage/browser/fileapi/file_system_operation_runner.h"
+#include "storage/browser/fileapi/quota/open_file_handle.h"
+#include "storage/browser/fileapi/quota/quota_reservation.h"
+#include "storage/common/fileapi/file_system_util.h"
namespace content {
// static
scoped_refptr<QuotaReservation> QuotaReservation::Create(
- scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
const GURL& origin_url,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
return scoped_refptr<QuotaReservation>(
new QuotaReservation(file_system_context, origin_url, type));
}
QuotaReservation::QuotaReservation(
- scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
const GURL& origin_url,
- fileapi::FileSystemType file_system_type)
+ storage::FileSystemType file_system_type)
: file_system_context_(file_system_context) {
quota_reservation_ =
file_system_context->CreateQuotaReservationOnFileTaskRunner(
@@ -35,10 +35,11 @@ QuotaReservation::QuotaReservation(
// For unit testing only.
QuotaReservation::QuotaReservation(
- scoped_refptr<fileapi::QuotaReservation> quota_reservation,
+ scoped_refptr<storage::QuotaReservation> quota_reservation,
const GURL& /* origin_url */,
- fileapi::FileSystemType /* file_system_type */)
- : quota_reservation_(quota_reservation) {}
+ storage::FileSystemType /* file_system_type */)
+ : quota_reservation_(quota_reservation) {
+}
QuotaReservation::~QuotaReservation() {
// We should have no open files at this point.
@@ -48,9 +49,9 @@ QuotaReservation::~QuotaReservation() {
}
int64_t QuotaReservation::OpenFile(int32_t id,
- const fileapi::FileSystemURL& url) {
+ const storage::FileSystemURL& url) {
base::FilePath platform_file_path;
- if (file_system_context_) {
+ if (file_system_context_.get()) {
base::File::Error error =
file_system_context_->operation_runner()->SyncGetPlatformPath(
url, &platform_file_path);
@@ -63,7 +64,7 @@ int64_t QuotaReservation::OpenFile(int32_t id,
platform_file_path = url.path();
}
- scoped_ptr<fileapi::OpenFileHandle> file_handle =
+ scoped_ptr<storage::OpenFileHandle> file_handle =
quota_reservation_->GetOpenFileHandle(platform_file_path);
std::pair<FileMap::iterator, bool> insert_result =
files_.insert(std::make_pair(id, file_handle.get()));
@@ -116,7 +117,7 @@ void QuotaReservation::GotReservedQuota(const ReserveQuotaCallback& callback,
for (FileMap::iterator it = files_.begin(); it != files_.end(); ++it)
file_sizes[it->first] = it->second->GetMaxWrittenOffset();
- if (file_system_context_) {
+ if (file_system_context_.get()) {
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -129,8 +130,9 @@ void QuotaReservation::GotReservedQuota(const ReserveQuotaCallback& callback,
}
void QuotaReservation::DeleteOnCorrectThread() const {
- if (file_system_context_ && !file_system_context_->default_file_task_runner()
- ->RunsTasksOnCurrentThread()) {
+ if (file_system_context_.get() &&
+ !file_system_context_->default_file_task_runner()
+ ->RunsTasksOnCurrentThread()) {
file_system_context_->default_file_task_runner()->DeleteSoon(FROM_HERE,
this);
} else {
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.h b/chromium/content/browser/renderer_host/pepper/quota_reservation.h
index 33490918f93..7ea637c2b8f 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation.h
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.h
@@ -12,10 +12,10 @@
#include "content/common/content_export.h"
#include "ppapi/c/pp_stdint.h" // For int64_t on Windows.
#include "ppapi/shared_impl/file_growth.h"
+#include "storage/browser/fileapi/file_system_context.h"
#include "url/gurl.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-namespace fileapi {
+namespace storage {
class FileSystemURL;
class OpenFileHandle;
class QuotaReservation;
@@ -36,12 +36,12 @@ class CONTENT_EXPORT QuotaReservation
public:
// Static method to facilitate construction on the file task runner.
static scoped_refptr<QuotaReservation> Create(
- scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
const GURL& origin_url,
- fileapi::FileSystemType file_system_type);
+ storage::FileSystemType file_system_type);
// Opens a file with the given id and path and returns its current size.
- int64_t OpenFile(int32_t id, const fileapi::FileSystemURL& url);
+ int64_t OpenFile(int32_t id, const storage::FileSystemURL& url);
// Closes the file opened by OpenFile with the given id.
void CloseFile(int32_t id, const ppapi::FileGrowth& file_growth);
// Refreshes the quota reservation to a new amount. A map that associates file
@@ -65,15 +65,15 @@ class CONTENT_EXPORT QuotaReservation
friend class QuotaReservationTest;
QuotaReservation(
- scoped_refptr<fileapi::FileSystemContext> file_system_context,
+ scoped_refptr<storage::FileSystemContext> file_system_context,
const GURL& origin_url,
- fileapi::FileSystemType file_system_type);
+ storage::FileSystemType file_system_type);
// For unit testing only. A QuotaReservation intended for unit testing will
// have file_system_context_ == NULL.
- QuotaReservation(scoped_refptr<fileapi::QuotaReservation> quota_reservation,
+ QuotaReservation(scoped_refptr<storage::QuotaReservation> quota_reservation,
const GURL& origin_url,
- fileapi::FileSystemType file_system_type);
+ storage::FileSystemType file_system_type);
~QuotaReservation();
@@ -82,9 +82,9 @@ class CONTENT_EXPORT QuotaReservation
void DeleteOnCorrectThread() const;
- scoped_refptr<fileapi::FileSystemContext> file_system_context_;
- scoped_refptr<fileapi::QuotaReservation> quota_reservation_;
- typedef std::map<int32_t, fileapi::OpenFileHandle*> FileMap;
+ scoped_refptr<storage::FileSystemContext> file_system_context_;
+ scoped_refptr<storage::QuotaReservation> quota_reservation_;
+ typedef std::map<int32_t, storage::OpenFileHandle*> FileMap;
FileMap files_;
DISALLOW_COPY_AND_ASSIGN(QuotaReservation);
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
index e949074efb8..6eb6f13b4d1 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
@@ -6,22 +6,22 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "storage/browser/fileapi/quota/quota_reservation.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/fileapi/quota/quota_reservation.h"
-using fileapi::QuotaReservationManager;
+using storage::QuotaReservationManager;
namespace content {
namespace {
const char kOrigin[] = "http://example.com";
-const fileapi::FileSystemType kType = fileapi::kFileSystemTypeTemporary;
+const storage::FileSystemType kType = storage::kFileSystemTypeTemporary;
const base::FilePath::StringType file1_name = FILE_PATH_LITERAL("file1");
const base::FilePath::StringType file2_name = FILE_PATH_LITERAL("file2");
@@ -33,30 +33,30 @@ const int kFile3ID = 3;
class FakeBackend : public QuotaReservationManager::QuotaBackend {
public:
FakeBackend() {}
- virtual ~FakeBackend() {}
+ ~FakeBackend() override {}
- virtual void ReserveQuota(
+ void ReserveQuota(
const GURL& origin,
- fileapi::FileSystemType type,
+ storage::FileSystemType type,
int64 delta,
- const QuotaReservationManager::ReserveQuotaCallback& callback) OVERRIDE {
+ const QuotaReservationManager::ReserveQuotaCallback& callback) override {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(callback), base::File::FILE_OK, delta));
}
- virtual void ReleaseReservedQuota(const GURL& origin,
- fileapi::FileSystemType type,
- int64 size) OVERRIDE {}
+ void ReleaseReservedQuota(const GURL& origin,
+ storage::FileSystemType type,
+ int64 size) override {}
- virtual void CommitQuotaUsage(const GURL& origin,
- fileapi::FileSystemType type,
- int64 delta) OVERRIDE {}
+ void CommitQuotaUsage(const GURL& origin,
+ storage::FileSystemType type,
+ int64 delta) override {}
- virtual void IncrementDirtyCount(const GURL& origin,
- fileapi::FileSystemType type) OVERRIDE {}
- virtual void DecrementDirtyCount(const GURL& origin,
- fileapi::FileSystemType type) OVERRIDE {}
+ void IncrementDirtyCount(const GURL& origin,
+ storage::FileSystemType type) override {}
+ void DecrementDirtyCount(const GURL& origin,
+ storage::FileSystemType type) override {}
private:
DISALLOW_COPY_AND_ASSIGN(FakeBackend);
@@ -67,16 +67,16 @@ class FakeBackend : public QuotaReservationManager::QuotaBackend {
class QuotaReservationTest : public testing::Test {
public:
QuotaReservationTest() {}
- virtual ~QuotaReservationTest() {}
+ ~QuotaReservationTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(work_dir_.CreateUniqueTempDir());
reservation_manager_.reset(new QuotaReservationManager(
scoped_ptr<QuotaReservationManager::QuotaBackend>(new FakeBackend)));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
reservation_manager_.reset();
base::RunLoop().RunUntilIdle();
}
@@ -85,16 +85,16 @@ class QuotaReservationTest : public testing::Test {
return work_dir_.path().Append(file_name);
}
- fileapi::FileSystemURL MakeFileSystemURL(
+ storage::FileSystemURL MakeFileSystemURL(
const base::FilePath::StringType& file_name) {
- return fileapi::FileSystemURL::CreateForTest(
+ return storage::FileSystemURL::CreateForTest(
GURL(kOrigin), kType, MakeFilePath(file_name));
}
scoped_refptr<QuotaReservation> CreateQuotaReservation(
- scoped_refptr<fileapi::QuotaReservation> reservation,
+ scoped_refptr<storage::QuotaReservation> reservation,
const GURL& origin,
- fileapi::FileSystemType type) {
+ storage::FileSystemType type) {
// Sets reservation_ as a side effect.
return scoped_refptr<QuotaReservation>(
new QuotaReservation(reservation, origin, type));
@@ -114,7 +114,7 @@ class QuotaReservationTest : public testing::Test {
private:
base::MessageLoop message_loop_;
base::ScopedTempDir work_dir_;
- scoped_ptr<fileapi::QuotaReservationManager> reservation_manager_;
+ scoped_ptr<storage::QuotaReservationManager> reservation_manager_;
DISALLOW_COPY_AND_ASSIGN(QuotaReservationTest);
};
@@ -148,9 +148,9 @@ void ReserveQuota(scoped_refptr<QuotaReservation> quota_reservation,
// 2) Open a file, grow it, close it, and reserve quota with correct sizes.
TEST_F(QuotaReservationTest, ReserveQuota) {
GURL origin(kOrigin);
- fileapi::FileSystemType type = kType;
+ storage::FileSystemType type = kType;
- scoped_refptr<fileapi::QuotaReservation> reservation(
+ scoped_refptr<storage::QuotaReservation> reservation(
reservation_manager()->CreateReservation(origin, type));
scoped_refptr<QuotaReservation> test =
CreateQuotaReservation(reservation, origin, type);
@@ -189,9 +189,9 @@ TEST_F(QuotaReservationTest, ReserveQuota) {
// 1) We can open and close multiple files.
TEST_F(QuotaReservationTest, MultipleFiles) {
GURL origin(kOrigin);
- fileapi::FileSystemType type = kType;
+ storage::FileSystemType type = kType;
- scoped_refptr<fileapi::QuotaReservation> reservation(
+ scoped_refptr<storage::QuotaReservation> reservation(
reservation_manager()->CreateReservation(origin, type));
scoped_refptr<QuotaReservation> test =
CreateQuotaReservation(reservation, origin, type);
diff --git a/chromium/content/browser/renderer_host/popup_menu_helper_mac.h b/chromium/content/browser/renderer_host/popup_menu_helper_mac.h
deleted file mode 100644
index 8a6f3176c7e..00000000000
--- a/chromium/content/browser/renderer_host/popup_menu_helper_mac.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_POPUP_MENU_HELPER_MAC_H_
-#define CONTENT_BROWSER_RENDERER_HOST_POPUP_MENU_HELPER_MAC_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "ui/gfx/rect.h"
-
-#ifdef __OBJC__
-@class WebMenuRunner;
-#else
-class WebMenuRunner;
-#endif
-
-namespace content {
-class RenderViewHost;
-class RenderViewHostImpl;
-class RenderWidgetHostViewMac;
-struct MenuItem;
-
-class PopupMenuHelper : public NotificationObserver {
- public:
- // Creates a PopupMenuHelper that will notify |render_view_host| when a user
- // selects or cancels the popup.
- explicit PopupMenuHelper(RenderViewHost* render_view_host);
- void Hide();
-
- // Shows the popup menu and notifies the RenderViewHost of the selection/
- // cancel.
- // This call is blocking.
- void ShowPopupMenu(const gfx::Rect& bounds,
- int item_height,
- double item_font_size,
- int selected_item,
- const std::vector<MenuItem>& items,
- bool right_aligned,
- bool allow_multiple_selection);
-
- // Immediately return from ShowPopupMenu.
- CONTENT_EXPORT static void DontShowPopupMenuForTesting();
-
- protected:
- virtual RenderWidgetHostViewMac* GetRenderWidgetHostView() const;
-
- // NotificationObserver implementation:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
-
- NotificationRegistrar notification_registrar_;
- RenderViewHostImpl* render_view_host_;
- WebMenuRunner* menu_runner_;
- bool popup_was_hidden_;
-
- DISALLOW_COPY_AND_ASSIGN(PopupMenuHelper);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_POPUP_MENU_HELPER_MAC_H_
diff --git a/chromium/content/browser/renderer_host/popup_menu_helper_mac.mm b/chromium/content/browser/renderer_host/popup_menu_helper_mac.mm
deleted file mode 100644
index 1fb28bae96b..00000000000
--- a/chromium/content/browser/renderer_host/popup_menu_helper_mac.mm
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2012 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.
-
-#import <Carbon/Carbon.h>
-
-#include "content/browser/renderer_host/popup_menu_helper_mac.h"
-
-#include "base/mac/scoped_nsobject.h"
-#import "base/mac/scoped_sending_event.h"
-#include "base/message_loop/message_loop.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/render_widget_host_view_mac.h"
-#include "content/browser/renderer_host/webmenurunner_mac.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
-#import "ui/base/cocoa/base_view.h"
-
-namespace content {
-
-namespace {
-
-bool g_allow_showing_popup_menus = true;
-
-} // namespace
-
-PopupMenuHelper::PopupMenuHelper(RenderViewHost* render_view_host)
- : render_view_host_(static_cast<RenderViewHostImpl*>(render_view_host)),
- menu_runner_(nil),
- popup_was_hidden_(false) {
- notification_registrar_.Add(
- this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
- Source<RenderWidgetHost>(render_view_host));
-}
-
-void PopupMenuHelper::ShowPopupMenu(
- const gfx::Rect& bounds,
- int item_height,
- double item_font_size,
- int selected_item,
- const std::vector<MenuItem>& items,
- bool right_aligned,
- bool allow_multiple_selection) {
- // Only single selection list boxes show a popup on Mac.
- DCHECK(!allow_multiple_selection);
-
- if (!g_allow_showing_popup_menus)
- return;
-
- // Retain the Cocoa view for the duration of the pop-up so that it can't be
- // dealloced if my Destroy() method is called while the pop-up's up (which
- // would in turn delete me, causing a crash once the -runMenuInView
- // call returns. That's what was happening in <http://crbug.com/33250>).
- RenderWidgetHostViewMac* rwhvm =
- static_cast<RenderWidgetHostViewMac*>(GetRenderWidgetHostView());
- base::scoped_nsobject<RenderWidgetHostViewCocoa> cocoa_view(
- [rwhvm->cocoa_view() retain]);
-
- // Display the menu.
- menu_runner_ = [[WebMenuRunner alloc] initWithItems:items
- fontSize:item_font_size
- rightAligned:right_aligned];
-
- {
- // Make sure events can be pumped while the menu is up.
- base::MessageLoop::ScopedNestableTaskAllower allow(
- base::MessageLoop::current());
-
- // One of the events that could be pumped is |window.close()|.
- // User-initiated event-tracking loops protect against this by
- // setting flags in -[CrApplication sendEvent:], but since
- // web-content menus are initiated by IPC message the setup has to
- // be done manually.
- base::mac::ScopedSendingEvent sending_event_scoper;
-
- // Now run a SYNCHRONOUS NESTED EVENT LOOP until the pop-up is finished.
- [menu_runner_ runMenuInView:cocoa_view
- withBounds:[cocoa_view flipRectToNSRect:bounds]
- initialIndex:selected_item];
- }
-
- if (!render_view_host_) {
- // Bad news, the RenderViewHost got deleted while we were off running the
- // menu. Nothing to do.
- [menu_runner_ release];
- menu_runner_ = nil;
- return;
- }
-
- if (!popup_was_hidden_) {
- if ([menu_runner_ menuItemWasChosen]) {
- render_view_host_->DidSelectPopupMenuItem(
- [menu_runner_ indexOfSelectedItem]);
- } else {
- render_view_host_->DidCancelPopupMenu();
- }
- }
- [menu_runner_ release];
- menu_runner_ = nil;
-}
-
-void PopupMenuHelper::Hide() {
- if (menu_runner_)
- [menu_runner_ hide];
- popup_was_hidden_ = true;
-}
-
-// static
-void PopupMenuHelper::DontShowPopupMenuForTesting() {
- g_allow_showing_popup_menus = false;
-}
-
-RenderWidgetHostViewMac* PopupMenuHelper::GetRenderWidgetHostView() const {
- return static_cast<RenderWidgetHostViewMac*>(render_view_host_->GetView());
-}
-
-void PopupMenuHelper::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK(type == NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED);
- DCHECK(Source<RenderWidgetHost>(source).ptr() == render_view_host_);
- render_view_host_ = NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index cb1617089fc..0474e081bc7 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
+#include "base/numerics/safe_math.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
@@ -19,21 +20,25 @@
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/plugin_process_host.h"
-#include "content/browser/plugin_service_impl.h"
-#include "content/browser/ppapi_plugin_process_host.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_helper.h"
+#include "content/browser/renderer_host/render_widget_resize_helper.h"
+#include "content/browser/transition_request_manager.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/child_process_messages.h"
+#include "content/common/content_constants_internal.h"
#include "content/common/cookie_data.h"
#include "content/common/desktop_notification_messages.h"
#include "content/common/frame_messages.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "content/common/host_discardable_shared_memory_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/media/media_param_traits.h"
#include "content/common/view_messages.h"
@@ -87,6 +92,11 @@
#include "media/base/android/webaudio_media_codec_bridge.h"
#endif
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_service_impl.h"
+#include "content/browser/ppapi_plugin_process_host.h"
+#endif
+
using net::CookieStore;
namespace content {
@@ -96,10 +106,6 @@ namespace {
const int kPluginsRefreshThresholdInSeconds = 3;
#endif
-// When two CPU usage queries arrive within this interval, we sample the CPU
-// usage only once and send it as a response for both queries.
-static const int64 kCPUUsageSampleIntervalMs = 900;
-
const uint32 kFilteredMessageClasses[] = {
ChildProcessMsgStart,
DesktopNotificationMsgStart,
@@ -143,6 +149,7 @@ class RenderMessageCompletionCallback {
IPC::Message* reply_msg_;
};
+#if defined(ENABLE_PLUGINS)
class OpenChannelToPpapiPluginCallback
: public RenderMessageCompletionCallback,
public PpapiPluginProcessHost::PluginClient {
@@ -154,27 +161,23 @@ class OpenChannelToPpapiPluginCallback
context_(context) {
}
- virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
- int* renderer_id) OVERRIDE {
+ void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
+ int* renderer_id) override {
*renderer_handle = filter()->PeerHandle();
*renderer_id = filter()->render_process_id();
}
- virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
- base::ProcessId plugin_pid,
- int plugin_child_id) OVERRIDE {
+ void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
+ base::ProcessId plugin_pid,
+ int plugin_child_id) override {
ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(
reply_msg(), channel_handle, plugin_pid, plugin_child_id);
SendReplyAndDeleteThis();
}
- virtual bool OffTheRecord() OVERRIDE {
- return filter()->OffTheRecord();
- }
+ bool OffTheRecord() override { return filter()->OffTheRecord(); }
- virtual ResourceContext* GetResourceContext() OVERRIDE {
- return context_;
- }
+ ResourceContext* GetResourceContext() override { return context_; }
private:
ResourceContext* context_;
@@ -189,31 +192,30 @@ class OpenChannelToPpapiBrokerCallback
routing_id_(routing_id) {
}
- virtual ~OpenChannelToPpapiBrokerCallback() {}
+ ~OpenChannelToPpapiBrokerCallback() override {}
- virtual void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
- int* renderer_id) OVERRIDE {
+ void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
+ int* renderer_id) override {
*renderer_handle = filter_->PeerHandle();
*renderer_id = filter_->render_process_id();
}
- virtual void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
- base::ProcessId plugin_pid,
- int /* plugin_child_id */) OVERRIDE {
+ void OnPpapiChannelOpened(const IPC::ChannelHandle& channel_handle,
+ base::ProcessId plugin_pid,
+ int /* plugin_child_id */) override {
filter_->Send(new ViewMsg_PpapiBrokerChannelCreated(routing_id_,
plugin_pid,
channel_handle));
delete this;
}
- virtual bool OffTheRecord() OVERRIDE {
- return filter_->OffTheRecord();
- }
+ bool OffTheRecord() override { return filter_->OffTheRecord(); }
private:
scoped_refptr<RenderMessageFilter> filter_;
int routing_id_;
};
+#endif // defined(ENABLE_PLUGINS)
} // namespace
@@ -230,15 +232,11 @@ class RenderMessageFilter::OpenChannelToNpapiPluginCallback
sent_plugin_channel_request_(false) {
}
- virtual int ID() OVERRIDE {
- return filter()->render_process_id();
- }
+ int ID() override { return filter()->render_process_id(); }
- virtual ResourceContext* GetResourceContext() OVERRIDE {
- return context_;
- }
+ ResourceContext* GetResourceContext() override { return context_; }
- virtual bool OffTheRecord() OVERRIDE {
+ bool OffTheRecord() override {
if (filter()->OffTheRecord())
return true;
if (GetContentClient()->browser()->AllowSaveLocalState(context_))
@@ -252,26 +250,22 @@ class RenderMessageFilter::OpenChannelToNpapiPluginCallback
return false;
}
- virtual void SetPluginInfo(const WebPluginInfo& info) OVERRIDE {
- info_ = info;
- }
+ void SetPluginInfo(const WebPluginInfo& info) override { info_ = info; }
- virtual void OnFoundPluginProcessHost(PluginProcessHost* host) OVERRIDE {
+ void OnFoundPluginProcessHost(PluginProcessHost* host) override {
DCHECK(host);
host_ = host;
}
- virtual void OnSentPluginChannelRequest() OVERRIDE {
+ void OnSentPluginChannelRequest() override {
sent_plugin_channel_request_ = true;
}
- virtual void OnChannelOpened(const IPC::ChannelHandle& handle) OVERRIDE {
+ void OnChannelOpened(const IPC::ChannelHandle& handle) override {
WriteReplyAndDeleteThis(handle);
}
- virtual void OnError() OVERRIDE {
- WriteReplyAndDeleteThis(IPC::ChannelHandle());
- }
+ void OnError() override { WriteReplyAndDeleteThis(IPC::ChannelHandle()); }
PluginProcessHost* host() const {
return host_;
@@ -319,12 +313,12 @@ RenderMessageFilter::RenderMessageFilter(
incognito_(browser_context->IsOffTheRecord()),
dom_storage_context_(dom_storage_context),
render_process_id_(render_process_id),
- cpu_usage_(0),
audio_manager_(audio_manager),
media_internals_(media_internals) {
DCHECK(request_context_.get());
- render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
+ if (render_widget_helper)
+ render_widget_helper_->Init(render_process_id_, resource_dispatcher_host_);
}
RenderMessageFilter::~RenderMessageFilter() {
@@ -332,6 +326,11 @@ RenderMessageFilter::~RenderMessageFilter() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(plugin_host_clients_.empty());
HostSharedBitmapManager::current()->ProcessRemoved(PeerHandle());
+ BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
+ BrowserGpuMemoryBufferManager::current();
+ if (gpu_memory_buffer_manager)
+ gpu_memory_buffer_manager->ProcessRemoved(PeerHandle(), render_process_id_);
+ HostDiscardableSharedMemoryManager::current()->ProcessRemoved(PeerHandle());
}
void RenderMessageFilter::OnChannelClosing() {
@@ -354,18 +353,6 @@ void RenderMessageFilter::OnChannelClosing() {
plugin_host_clients_.clear();
}
-void RenderMessageFilter::OnChannelConnected(int32 peer_id) {
- base::ProcessHandle handle = PeerHandle();
-#if defined(OS_MACOSX)
- process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
- NULL));
-#else
- process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
-#endif
- cpu_usage_ = process_metrics_->GetCPUUsage(); // Initialize CPU usage counters
- cpu_usage_sample_time_ = base::TimeTicks::Now();
-}
-
bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderMessageFilter, message)
@@ -389,6 +376,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LoadFont, OnLoadFont)
#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SaveImageFromDataURL,
+ OnSaveImageFromDataURL)
#if defined(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
@@ -403,20 +392,32 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
OnOpenChannelToPpapiBroker)
#endif
+#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
- render_widget_helper_->DidReceiveBackingStoreMsg(message))
+ RenderWidgetResizeHelper::Get()->PostRendererProcessMsg(
+ render_process_id_, message))
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
- render_widget_helper_->DidReceiveBackingStoreMsg(message))
+ RenderWidgetResizeHelper::Get()->PostRendererProcessMsg(
+ render_process_id_, message))
+#endif
IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission,
OnCheckNotificationPermission)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateSharedBitmap, OnAllocateSharedBitmap)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(
+ ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ OnAllocateGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedGpuMemoryBuffer,
+ OnDeletedGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
OnAllocatedSharedBitmap)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedSharedBitmap,
OnDeletedSharedBitmap)
+ IPC_MESSAGE_HANDLER(
+ ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory,
+ OnAllocateLockedDiscardableSharedMemory)
#if defined(OS_POSIX) && !defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewHostMsg_AllocTransportDIB, OnAllocTransportDIB)
IPC_MESSAGE_HANDLER(ViewHostMsg_FreeTransportDIB, OnFreeTransportDIB)
@@ -424,7 +425,6 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DidGenerateCacheableMetadata,
OnCacheableMetadataAvailable)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_Keygen, OnKeygen)
- IPC_MESSAGE_HANDLER(ViewHostMsg_GetCPUUsage, OnGetCPUUsage)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetAudioHardwareConfig,
OnGetAudioHardwareConfig)
#if defined(OS_WIN)
@@ -437,6 +437,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ViewHostMsg_RunWebAudioMediaCodec, OnWebAudioMediaCodec)
#endif
+ IPC_MESSAGE_HANDLER(FrameHostMsg_AddNavigationTransitionData,
+ OnAddNavigationTransitionData)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -504,6 +506,7 @@ void RenderMessageFilter::OnCreateWindow(
*route_id = MSG_ROUTING_NONE;
*main_frame_route_id = MSG_ROUTING_NONE;
*surface_id = 0;
+ *cloned_session_storage_namespace_id = 0;
return;
}
@@ -546,7 +549,7 @@ void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes,
PeerHandle()));
#else
scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
- PeerHandle(), content::BrowserChildProcessHost::GetPortProvider()));
+ PeerHandle(), BrowserChildProcessHost::GetPortProvider()));
#endif
if (!metrics->GetMemoryBytes(private_bytes, shared_bytes)) {
*private_bytes = 0;
@@ -822,16 +825,6 @@ void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
*route_id = render_widget_helper_->GetNextRoutingID();
}
-void RenderMessageFilter::OnGetCPUUsage(int* cpu_usage) {
- base::TimeTicks now = base::TimeTicks::Now();
- int64 since_last_sample_ms = (now - cpu_usage_sample_time_).InMilliseconds();
- if (since_last_sample_ms > kCPUUsageSampleIntervalMs) {
- cpu_usage_sample_time_ = now;
- cpu_usage_ = static_cast<int>(process_metrics_->GetCPUUsage());
- }
- *cpu_usage = cpu_usage_;
-}
-
void RenderMessageFilter::OnGetAudioHardwareConfig(
media::AudioParameters* input_params,
media::AudioParameters* output_params) {
@@ -851,11 +844,11 @@ void RenderMessageFilter::OnGetMonitorColorProfile(std::vector<char>* profile) {
}
#endif
-void RenderMessageFilter::OnDownloadUrl(int render_view_id,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& suggested_name,
- const bool use_prompt) {
+void RenderMessageFilter::DownloadUrl(int render_view_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name,
+ const bool use_prompt) const {
scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
save_info->suggested_name = suggested_name;
save_info->prompt_for_save_location = use_prompt;
@@ -867,6 +860,7 @@ void RenderMessageFilter::OnDownloadUrl(int render_view_id,
// default cookie store.
// TODO(tburkard): retrieve the appropriate special cookie store, if this
// is ever to be used for downloads as well.
+
scoped_ptr<net::URLRequest> request(
resource_context_->GetRequestContext()->CreateRequest(
url, net::DEFAULT_PRIORITY, NULL, NULL));
@@ -880,10 +874,30 @@ void RenderMessageFilter::OnDownloadUrl(int render_view_id,
render_view_id,
false,
save_info.Pass(),
- content::DownloadItem::kInvalidId,
+ DownloadItem::kInvalidId,
ResourceDispatcherHostImpl::DownloadStartedCallback());
}
+void RenderMessageFilter::OnDownloadUrl(int render_view_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name) {
+ DownloadUrl(render_view_id, url, referrer, suggested_name, false);
+}
+
+void RenderMessageFilter::OnSaveImageFromDataURL(int render_view_id,
+ const std::string& url_str) {
+ // Please refer to RenderViewImpl::saveImageFromDataURL().
+ if (url_str.length() >= kMaxLengthOfDataURLString)
+ return;
+
+ GURL data_url(url_str);
+ if (!data_url.SchemeIs(url::kDataScheme))
+ return;
+
+ DownloadUrl(render_view_id, data_url, Referrer(), base::string16(), true);
+}
+
void RenderMessageFilter::OnCheckNotificationPermission(
const GURL& source_origin, int* result) {
#if defined(ENABLE_NOTIFICATIONS)
@@ -939,6 +953,14 @@ void RenderMessageFilter::OnDeletedSharedBitmap(const cc::SharedBitmapId& id) {
HostSharedBitmapManager::current()->ChildDeletedSharedBitmap(id);
}
+void RenderMessageFilter::OnAllocateLockedDiscardableSharedMemory(
+ uint32 size,
+ base::SharedMemoryHandle* handle) {
+ HostDiscardableSharedMemoryManager::current()
+ ->AllocateLockedDiscardableSharedMemoryForChild(
+ PeerHandle(), size, handle);
+}
+
net::CookieStore* RenderMessageFilter::GetCookieStoreForURL(
const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -977,24 +999,10 @@ void RenderMessageFilter::OnFreeTransportDIB(
}
#endif
-bool RenderMessageFilter::CheckPreparsedJsCachingEnabled() const {
- static bool checked = false;
- static bool result = false;
- if (!checked) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
- checked = true;
- }
- return result;
-}
-
void RenderMessageFilter::OnCacheableMetadataAvailable(
const GURL& url,
double expected_response_time,
const std::vector<char>& data) {
- if (!CheckPreparsedJsCachingEnabled())
- return;
-
net::HttpCache* cache = request_context_->GetURLRequestContext()->
http_transaction_factory()->GetCache();
DCHECK(cache);
@@ -1220,4 +1228,61 @@ void RenderMessageFilter::OnWebAudioMediaCodec(
}
#endif
+void RenderMessageFilter::OnAddNavigationTransitionData(
+ FrameHostMsg_AddNavigationTransitionData_Params params) {
+ if (params.elements.size() > TransitionRequestManager::kMaxNumOfElements)
+ return;
+ TransitionRequestManager::GetInstance()->AddPendingTransitionRequestData(
+ render_process_id_,
+ params.render_frame_id,
+ params.allowed_destination_host_pattern,
+ params.selector,
+ params.markup,
+ params.elements);
+}
+
+void RenderMessageFilter::OnAllocateGpuMemoryBuffer(
+ uint32 width,
+ uint32 height,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ IPC::Message* reply) {
+ DCHECK(BrowserGpuMemoryBufferManager::current());
+
+ base::CheckedNumeric<int> size = width;
+ size *= height;
+ if (!size.IsValid()) {
+ GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
+ return;
+ }
+
+ BrowserGpuMemoryBufferManager::current()
+ ->AllocateGpuMemoryBufferForChildProcess(
+ gfx::Size(width, height),
+ format,
+ usage,
+ PeerHandle(),
+ render_process_id_,
+ base::Bind(
+ &RenderMessageFilter::GpuMemoryBufferAllocated, this, reply));
+}
+
+void RenderMessageFilter::GpuMemoryBufferAllocated(
+ IPC::Message* reply,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply,
+ handle);
+ Send(reply);
+}
+
+void RenderMessageFilter::OnDeletedGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ uint32 sync_point) {
+ DCHECK(BrowserGpuMemoryBufferManager::current());
+
+ BrowserGpuMemoryBufferManager::current()->ChildProcessDeletedGpuMemoryBuffer(
+ id, PeerHandle(), render_process_id_, sync_point);
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index 95a80acbf0c..9d836262035 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -20,7 +20,6 @@
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "cc/resources/shared_bitmap_manager.h"
-#include "content/common/pepper_renderer_instance_data.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/common/three_d_api_types.h"
#include "ipc/message_filter.h"
@@ -28,10 +27,14 @@
#include "media/base/channel_layout.h"
#include "net/cookies/canonical_cookie.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/surface/transport_dib.h"
#if defined(OS_MACOSX)
+#include <IOSurface/IOSurfaceAPI.h>
+#include "base/mac/scoped_cftyperef.h"
#include "content/common/mac/font_loader.h"
#endif
@@ -39,7 +42,12 @@
#include "base/threading/worker_pool.h"
#endif
+#if defined(ENABLE_PLUGINS)
+#include "content/common/pepper_renderer_instance_data.h"
+#endif
+
struct FontDescriptor;
+struct FrameHostMsg_AddNavigationTransitionData_Params;
struct ViewHostMsg_CreateWindow_Params;
namespace blink {
@@ -52,6 +60,10 @@ class SharedMemory;
class TaskRunner;
}
+namespace gfx {
+struct GpuMemoryBufferHandle;
+}
+
namespace media {
class AudioManager;
struct MediaLogEvent;
@@ -77,7 +89,7 @@ struct WebPluginInfo;
// This class filters out incoming IPC messages for the renderer process on the
// IPC thread.
-class RenderMessageFilter : public BrowserMessageFilter {
+class CONTENT_EXPORT RenderMessageFilter : public BrowserMessageFilter {
public:
// Create the filter.
RenderMessageFilter(int render_process_id,
@@ -90,14 +102,13 @@ class RenderMessageFilter : public BrowserMessageFilter {
DOMStorageContextWrapper* dom_storage_context);
// IPC::MessageFilter methods:
- virtual void OnChannelClosing() OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+ void OnChannelClosing() override;
// BrowserMessageFilter methods:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnDestruct() const override;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& message) override;
bool OffTheRecord() const;
@@ -108,14 +119,22 @@ class RenderMessageFilter : public BrowserMessageFilter {
// Only call on the IO thread.
net::CookieStore* GetCookieStoreForURL(const GURL& url);
+ protected:
+ ~RenderMessageFilter() override;
+
+ // This method will be overridden by TestSaveImageFromDataURL class for test.
+ virtual void DownloadUrl(int render_view_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name,
+ const bool use_prompt) const;
+
private:
friend class BrowserThread;
friend class base::DeleteHelper<RenderMessageFilter>;
class OpenChannelToNpapiPluginCallback;
- virtual ~RenderMessageFilter();
-
void OnGetProcessMemorySizes(size_t* private_bytes, size_t* shared_bytes);
void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params,
int* route_id,
@@ -158,6 +177,7 @@ class RenderMessageFilter : public BrowserMessageFilter {
const base::string16& characters);
#endif
+#if defined(ENABLE_PLUGINS)
void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
void GetPluginsCallback(IPC::Message* reply_msg,
const std::vector<WebPluginInfo>& plugins);
@@ -185,17 +205,16 @@ class RenderMessageFilter : public BrowserMessageFilter {
bool is_external);
void OnOpenChannelToPpapiBroker(int routing_id,
const base::FilePath& path);
+#endif // defined(ENABLE_PLUGINS)
void OnGenerateRoutingID(int* route_id);
void OnDownloadUrl(int render_view_id,
const GURL& url,
const Referrer& referrer,
- const base::string16& suggested_name,
- const bool use_prompt);
+ const base::string16& suggested_name);
+ void OnSaveImageFromDataURL(int render_view_id, const std::string& url_str);
void OnCheckNotificationPermission(const GURL& source_origin,
int* permission_level);
- void OnGetCPUUsage(int* cpu_usage);
-
void OnGetAudioHardwareConfig(media::AudioParameters* input_params,
media::AudioParameters* output_params);
@@ -221,6 +240,11 @@ class RenderMessageFilter : public BrowserMessageFilter {
void OnDeletedSharedBitmap(const cc::SharedBitmapId& id);
void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
+ // Browser side discardable shared memory allocation.
+ void OnAllocateLockedDiscardableSharedMemory(
+ uint32 size,
+ base::SharedMemoryHandle* handle);
+
// Browser side transport DIB allocation
void OnAllocTransportDIB(uint32 size,
bool cache_in_browser,
@@ -270,6 +294,19 @@ class RenderMessageFilter : public BrowserMessageFilter {
uint32_t data_size);
#endif
+ void OnAddNavigationTransitionData(
+ FrameHostMsg_AddNavigationTransitionData_Params params);
+
+ void OnAllocateGpuMemoryBuffer(uint32 width,
+ uint32 height,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ IPC::Message* reply);
+ void GpuMemoryBufferAllocated(IPC::Message* reply,
+ const gfx::GpuMemoryBufferHandle& handle);
+ void OnDeletedGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
+ uint32 sync_point);
+
// Cached resource request dispatcher host and plugin service, guaranteed to
// be non-null if Init succeeds. We do not own the objects, they are managed
// by the BrowserProcess, which has a wider scope than we do.
@@ -298,13 +335,6 @@ class RenderMessageFilter : public BrowserMessageFilter {
std::set<OpenChannelToNpapiPluginCallback*> plugin_host_clients_;
- // Records the last time we sampled CPU usage of the renderer process.
- base::TimeTicks cpu_usage_sample_time_;
- // Records the last sampled CPU usage in percents.
- int cpu_usage_;
- // Used for sampling CPU usage of the renderer process.
- scoped_ptr<base::ProcessMetrics> process_metrics_;
-
media::AudioManager* audio_manager_;
MediaInternals* media_internals_;
diff --git a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
index b77f20fa44b..f2856bfdc86 100644
--- a/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -2,18 +2,24 @@
// 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 "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/child_process_messages.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
namespace content {
namespace {
@@ -36,13 +42,12 @@ class RenderProcessHostTest : public ContentBrowserTest,
protected:
// RenderProcessHostObserver:
- virtual void RenderProcessExited(RenderProcessHost* host,
- base::ProcessHandle handle,
- base::TerminationStatus status,
- int exit_code) OVERRIDE {
+ void RenderProcessExited(RenderProcessHost* host,
+ base::TerminationStatus status,
+ int exit_code) override {
++process_exits_;
}
- virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE {
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override {
++host_destructions_;
}
@@ -115,15 +120,14 @@ class ShellCloser : public RenderProcessHostObserver {
protected:
// RenderProcessHostObserver:
- virtual void RenderProcessExited(RenderProcessHost* host,
- base::ProcessHandle handle,
- base::TerminationStatus status,
- int exit_code) OVERRIDE {
+ void RenderProcessExited(RenderProcessHost* host,
+ base::TerminationStatus status,
+ int exit_code) override {
logging_string_->append("ShellCloser::RenderProcessExited ");
shell_->Close();
}
- virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE {
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override {
logging_string_->append("ShellCloser::RenderProcessHostDestroyed ");
}
@@ -140,14 +144,13 @@ class ObserverLogger : public RenderProcessHostObserver {
protected:
// RenderProcessHostObserver:
- virtual void RenderProcessExited(RenderProcessHost* host,
- base::ProcessHandle handle,
- base::TerminationStatus status,
- int exit_code) OVERRIDE {
+ void RenderProcessExited(RenderProcessHost* host,
+ base::TerminationStatus status,
+ int exit_code) override {
logging_string_->append("ObserverLogger::RenderProcessExited ");
}
- virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE {
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override {
logging_string_->append("ObserverLogger::RenderProcessHostDestroyed ");
host_destroyed_ = true;
}
@@ -192,5 +195,42 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
}
}
+#if defined(OS_WIN)
+// Provides functionality to test renderer processes with the Win32K lockdown
+// process mitigation.
+class Win32KLockdownRendererProcessHostTest : public RenderProcessHostTest {
+ public:
+ Win32KLockdownRendererProcessHostTest() {}
+
+ virtual ~Win32KLockdownRendererProcessHostTest() {}
+
+ protected:
+ virtual void SetUp() override {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ command_line->AppendSwitch(switches::kEnableWin32kRendererLockDown);
+ RenderProcessHostTest::SetUp();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Win32KLockdownRendererProcessHostTest);
+};
+
+// Tests whether navigation requests with the Win32K lockdown mitigation set
+// work correctly.
+IN_PROC_BROWSER_TEST_F(Win32KLockdownRendererProcessHostTest,
+ RendererWin32KLockdownNavigationTest) {
+ if (base::win::GetVersion() < base::win::VERSION_WIN8)
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
+ NavigateToURL(shell(), test_url);
+
+ EXPECT_EQ(1, RenderProcessHostCount());
+ EXPECT_EQ(0, process_exits_);
+}
+#endif
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.cc b/chromium/content/browser/renderer_host/render_process_host_impl.cc
index 2eafd8c9c47..c582a6e97a6 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -11,10 +11,6 @@
#include <limits>
#include <vector>
-#if defined(OS_POSIX)
-#include <utility> // for pair<>
-#endif
-
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -26,8 +22,7 @@
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/numerics/safe_math.h"
-#include "base/path_service.h"
+#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -40,12 +35,12 @@
#include "cc/base/switches.h"
#include "content/browser/appcache/appcache_dispatcher_host.h"
#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/browser/battery_status/battery_status_message_filter.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_main.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browser_plugin/browser_plugin_message_filter.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/device_sensors/device_light_message_filter.h"
#include "content/browser/device_sensors/device_motion_message_filter.h"
#include "content/browser/device_sensors/device_orientation_message_filter.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
@@ -54,6 +49,7 @@
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/fileapi/fileapi_message_filter.h"
#include "content/browser/frame_host/render_frame_message_filter.h"
+#include "content/browser/geofencing/geofencing_dispatcher_host.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -69,9 +65,9 @@
#include "content/browser/message_port_message_filter.h"
#include "content/browser/mime_registry_message_filter.h"
#include "content/browser/mojo/mojo_application_host.h"
-#include "content/browser/plugin_service_impl.h"
+#include "content/browser/notifications/notification_message_filter.h"
#include "content/browser/profiler_message_filter.h"
-#include "content/browser/push_messaging_message_filter.h"
+#include "content/browser/push_messaging/push_messaging_message_filter.h"
#include "content/browser/quota_dispatcher_host.h"
#include "content/browser/renderer_host/clipboard_message_filter.h"
#include "content/browser/renderer_host/database_message_filter.h"
@@ -80,12 +76,10 @@
#include "content/browser/renderer_host/gpu_message_filter.h"
#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
-#include "content/browser/renderer_host/media/device_request_message_filter.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
-#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
#include "content/browser/renderer_host/render_message_filter.h"
@@ -93,26 +87,22 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
#include "content/browser/renderer_host/text_input_client_message_filter.h"
#include "content/browser/renderer_host/websocket_dispatcher_host.h"
#include "content/browser/resolve_proxy_msg_helper.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/shared_worker/shared_worker_message_filter.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/browser/speech/speech_recognition_dispatcher_host.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/streams/stream_context.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/vibration/vibration_message_filter.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
-#include "content/browser/worker_host/worker_message_filter.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/child_process_messages.h"
#include "content/common/content_switches_internal.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/mojo/mojo_messages.h"
#include "content/common/resource_messages.h"
@@ -132,63 +122,66 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
+#include "content/public/common/resource_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "content/public/common/url_constants.h"
+#include "device/battery/battery_monitor_impl.h"
+#include "gpu/command_buffer/client/gpu_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_logging.h"
#include "ipc/ipc_switches.h"
+#include "ipc/mojo/ipc_channel_mojo.h"
+#include "ipc/mojo/ipc_channel_mojo_host.h"
#include "media/base/media_switches.h"
-#include "mojo/common/common_type_converters.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_switches.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
+#include "ui/gl/gpu_switching_manager.h"
#include "ui/native_theme/native_theme_switches.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
-#include "webkit/common/resource_type.h"
#if defined(OS_ANDROID)
#include "content/browser/media/android/browser_demuxer_android.h"
-#include "content/browser/renderer_host/compositor_impl_android.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
+#include "content/browser/screen_orientation/screen_orientation_message_filter_android.h"
#endif
#if defined(OS_WIN)
-#include "base/strings/string_number_conversions.h"
#include "base/win/scoped_com_initializer.h"
#include "content/common/font_cache_dispatcher_win.h"
#include "content/common/sandbox_win.h"
#include "ui/gfx/win/dpi.h"
#endif
-#if defined(OS_MACOSX)
-#include "content/public/common/sandbox_type_mac.h"
+#if defined(ENABLE_BROWSER_CDMS)
+#include "content/browser/media/cdm/browser_cdm_manager.h"
+#endif
+
+#if defined(ENABLE_PLUGINS)
+#include "content/browser/plugin_service_impl.h"
#endif
#if defined(ENABLE_WEBRTC)
#include "content/browser/media/webrtc_internals.h"
#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
+#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "content/common/media/aec_dump_messages.h"
#include "content/common/media/media_stream_messages.h"
#endif
extern bool g_exited_main_message_loop;
-static const char* kSiteProcessMapKeyName = "content_site_process_map";
-
namespace content {
namespace {
+const char kSiteProcessMapKeyName[] = "content_site_process_map";
+
void CacheShaderInfo(int32 id, base::FilePath path) {
ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path);
}
@@ -200,11 +193,11 @@ void RemoveShaderInfo(int32 id) {
net::URLRequestContext* GetRequestContext(
scoped_refptr<net::URLRequestContextGetter> request_context,
scoped_refptr<net::URLRequestContextGetter> media_request_context,
- ResourceType::Type resource_type) {
- // If the request has resource type of ResourceType::MEDIA, we use a request
+ ResourceType resource_type) {
+ // If the request has resource type of RESOURCE_TYPE_MEDIA, we use a request
// context specific to media for handling it because these resources have
// specific needs for caching.
- if (resource_type == ResourceType::MEDIA)
+ if (resource_type == RESOURCE_TYPE_MEDIA)
return media_request_context->GetURLRequestContext();
return request_context->GetURLRequestContext();
}
@@ -306,15 +299,15 @@ SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
// NOTE: changes to this class need to be reviewed by the security team.
class RendererSandboxedProcessLauncherDelegate
- : public content::SandboxedProcessLauncherDelegate {
+ : public SandboxedProcessLauncherDelegate {
public:
- RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel)
+ explicit RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel)
#if defined(OS_POSIX)
- : ipc_fd_(channel->TakeClientFileDescriptor())
+ : ipc_fd_(channel->TakeClientFileDescriptor())
#endif // OS_POSIX
{}
- virtual ~RendererSandboxedProcessLauncherDelegate() {}
+ ~RendererSandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
@@ -324,51 +317,28 @@ class RendererSandboxedProcessLauncherDelegate
}
#elif defined(OS_POSIX)
- virtual bool ShouldUseZygote() OVERRIDE {
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
- CommandLine::StringType renderer_prefix =
+ bool ShouldUseZygote() override {
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+ base::CommandLine::StringType renderer_prefix =
browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
return renderer_prefix.empty();
}
- virtual int GetIpcFd() OVERRIDE {
- return ipc_fd_;
- }
-#if defined(OS_MACOSX)
- virtual SandboxType GetSandboxType() OVERRIDE {
- return SANDBOX_TYPE_RENDERER;
- }
-#endif
+ base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); }
#endif // OS_WIN
private:
#if defined(OS_POSIX)
- int ipc_fd_;
+ base::ScopedFD ipc_fd_;
#endif // OS_POSIX
};
-#if defined(OS_MACOSX)
-void AddBooleanValue(CFMutableDictionaryRef dictionary,
- const CFStringRef key,
- bool value) {
- CFDictionaryAddValue(
- dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse);
-}
-
-void AddIntegerValue(CFMutableDictionaryRef dictionary,
- const CFStringRef key,
- int32 value) {
- base::ScopedCFTypeRef<CFNumberRef> number(
- CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
- CFDictionaryAddValue(dictionary, key, number.get());
-}
-#endif
-
const char kSessionStorageHolderKey[] = "kSessionStorageHolderKey";
class SessionStorageHolder : public base::SupportsUserData::Data {
public:
SessionStorageHolder() {}
- virtual ~SessionStorageHolder() {}
+ ~SessionStorageHolder() override {}
void Hold(const SessionStorageNamespaceMap& sessions, int view_route_id) {
session_storage_namespaces_awaiting_close_[view_route_id] = sessions;
@@ -404,15 +374,22 @@ size_t RenderProcessHost::GetMaxRendererProcessCount() {
if (g_max_renderer_count_override)
return g_max_renderer_count_override;
- // Defines the maximum number of renderer processes according to the
- // amount of installed memory as reported by the OS. The calculation
- // assumes that you want the renderers to use half of the installed
- // RAM and assuming that each WebContents uses ~40MB.
- // If you modify this assumption, you need to adjust the
- // ThirtyFourTabs test to match the expected number of processes.
+#if defined(OS_ANDROID)
+ // On Android we don't maintain a limit of renderer process hosts - we are
+ // happy with keeping a lot of these, as long as the number of live renderer
+ // processes remains reasonable, and on Android the OS takes care of that.
+ return std::numeric_limits<size_t>::max();
+#endif
+
+ // On other platforms, we calculate the maximum number of renderer process
+ // hosts according to the amount of installed memory as reported by the OS.
+ // The calculation assumes that you want the renderers to use half of the
+ // installed RAM and assuming that each WebContents uses ~40MB. If you modify
+ // this assumption, you need to adjust the ThirtyFourTabs test to match the
+ // expected number of processes.
//
- // With the given amounts of installed memory below on a 32-bit CPU,
- // the maximum renderer count will roughly be as follows:
+ // With the given amounts of installed memory below on a 32-bit CPU, the
+ // maximum renderer count will roughly be as follows:
//
// 128 MB -> 3
// 512 MB -> 6
@@ -456,7 +433,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
is_self_deleted_(false),
#endif
pending_views_(0),
- mojo_activation_required_(false),
+ mojo_application_host_(new MojoApplicationHost),
visible_widgets_(0),
backgrounded_(true),
is_initialized_(false),
@@ -483,7 +460,7 @@ RenderProcessHostImpl::RenderProcessHostImpl(
mark_child_process_activity_time();
if (!GetBrowserContext()->IsOffTheRecord() &&
- !CommandLine::ForCurrentProcess()->HasSwitch(
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&CacheShaderInfo, GetID(),
@@ -539,7 +516,7 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
if (gpu_observer_registered_) {
- GpuDataManagerImpl::GetInstance()->RemoveObserver(this);
+ ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
gpu_observer_registered_ = false;
}
@@ -552,15 +529,11 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
UnregisterHost(GetID());
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&RemoveShaderInfo, GetID()));
}
-
-#if defined(OS_ANDROID)
- CompositorImpl::DestroyAllSurfaceTextures(GetID());
-#endif
}
void RenderProcessHostImpl::EnableSendQueue() {
@@ -573,11 +546,12 @@ bool RenderProcessHostImpl::Init() {
if (channel_)
return true;
- CommandLine::StringType renderer_prefix;
+ base::CommandLine::StringType renderer_prefix;
#if defined(OS_POSIX)
// A command prefix is something prepended to the command line of the spawned
// process. It is supported only on POSIX systems.
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
renderer_prefix =
browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
#endif // defined(OS_POSIX)
@@ -598,20 +572,16 @@ bool RenderProcessHostImpl::Init() {
// Setup the IPC channel.
const std::string channel_id =
IPC::Channel::GenerateVerifiedChannelID(std::string());
- channel_ = IPC::ChannelProxy::Create(
- channel_id,
- IPC::Channel::MODE_SERVER,
- this,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get());
+ channel_ = CreateChannelProxy(channel_id);
// Setup the Mojo channel.
- mojo_application_host_.reset(new MojoApplicationHost());
mojo_application_host_->Init();
// Call the embedder first so that their IPC filters have priority.
GetContentClient()->browser()->RenderProcessWillLaunch(this);
CreateMessageFilters();
+ RegisterMojoServices();
if (run_renderer_in_process()) {
DCHECK(g_renderer_main_thread_factory);
@@ -640,7 +610,7 @@ bool RenderProcessHostImpl::Init() {
} else {
// Build command line for renderer. We call AppendRendererCommandLine()
// first so the process type argument will appear first.
- CommandLine* cmd_line = new CommandLine(renderer_path);
+ base::CommandLine* cmd_line = new base::CommandLine(renderer_path);
if (!renderer_prefix.empty())
cmd_line->PrependWrapper(renderer_prefix);
AppendRendererCommandLine(cmd_line);
@@ -660,25 +630,43 @@ bool RenderProcessHostImpl::Init() {
if (!gpu_observer_registered_) {
gpu_observer_registered_ = true;
- GpuDataManagerImpl::GetInstance()->AddObserver(this);
+ ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
}
+ power_monitor_broadcaster_.Init();
+
is_initialized_ = true;
+ init_time_ = base::TimeTicks::Now();
return true;
}
-void RenderProcessHostImpl::MaybeActivateMojo() {
- // TODO(darin): Following security review, we can unconditionally initialize
- // Mojo in all renderers. We will then be able to directly call Activate()
- // from OnProcessLaunched.
- if (!mojo_activation_required_)
- return; // Waiting on someone to require Mojo.
+bool RenderProcessHostImpl::ShouldUseMojoChannel() const {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ return command_line.HasSwitch(switches::kEnableRendererMojoChannel) ||
+ IPC::ChannelMojo::ShouldBeUsed();
+}
+
+scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
+ const std::string& channel_id) {
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
+ if (ShouldUseMojoChannel()) {
+ VLOG(1) << "Mojo Channel is enabled on host";
+ if (!channel_mojo_host_) {
+ channel_mojo_host_.reset(new IPC::ChannelMojoHost(
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
+ }
- if (!GetHandle())
- return; // Waiting on renderer startup.
+ return IPC::ChannelProxy::Create(
+ IPC::ChannelMojo::CreateServerFactory(
+ channel_mojo_host_->channel_delegate(), channel_id),
+ this,
+ runner.get());
+ }
- if (!mojo_application_host_->did_activate())
- mojo_application_host_->Activate(this, GetHandle());
+ return IPC::ChannelProxy::Create(
+ channel_id, IPC::Channel::MODE_SERVER, this, runner.get());
}
void RenderProcessHostImpl::CreateMessageFilters() {
@@ -736,17 +724,17 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new AudioInputRendererHost(
audio_manager,
media_stream_manager,
- BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
+ AudioMirroringManager::GetInstance(),
BrowserMainLoop::GetInstance()->user_input_monitor()));
// The AudioRendererHost needs to be available for lookup, so it's
// stashed in a member variable.
audio_renderer_host_ = new AudioRendererHost(
GetID(),
audio_manager,
- BrowserMainLoop::GetInstance()->audio_mirroring_manager(),
+ AudioMirroringManager::GetInstance(),
media_internals,
media_stream_manager);
- AddFilter(audio_renderer_host_);
+ AddFilter(audio_renderer_host_.get());
AddFilter(
new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager()));
AddFilter(new VideoCaptureHost(media_stream_manager));
@@ -773,10 +761,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new MediaStreamDispatcherHost(
GetID(),
browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
- media_stream_manager,
- resource_context));
- AddFilter(new DeviceRequestMessageFilter(
- resource_context, media_stream_manager, GetID()));
+ media_stream_manager));
AddFilter(new MediaStreamTrackMetricsHost());
#endif
#if defined(ENABLE_PLUGINS)
@@ -804,23 +789,17 @@ void RenderProcessHostImpl::CreateMessageFilters() {
channel_->AddFilter(new FontCacheDispatcher());
#elif defined(OS_ANDROID)
browser_demuxer_android_ = new BrowserDemuxerAndroid();
- AddFilter(browser_demuxer_android_);
+ AddFilter(browser_demuxer_android_.get());
+#endif
+#if defined(ENABLE_BROWSER_CDMS)
+ browser_cdm_manager_ = new BrowserCdmManager(GetID(), NULL);
+ AddFilter(browser_cdm_manager_.get());
#endif
-
- SocketStreamDispatcherHost::GetRequestContextCallback
- request_context_callback(
- base::Bind(&GetRequestContext, request_context,
- media_request_context));
-
- SocketStreamDispatcherHost* socket_stream_dispatcher_host =
- new SocketStreamDispatcherHost(
- GetID(), request_context_callback, resource_context);
- AddFilter(socket_stream_dispatcher_host);
WebSocketDispatcherHost::GetRequestContextCallback
websocket_request_context_callback(
base::Bind(&GetRequestContext, request_context,
- media_request_context, ResourceType::SUB_RESOURCE));
+ media_request_context, RESOURCE_TYPE_SUB_RESOURCE));
AddFilter(
new WebSocketDispatcherHost(GetID(), websocket_request_context_callback));
@@ -828,51 +807,34 @@ void RenderProcessHostImpl::CreateMessageFilters() {
message_port_message_filter_ = new MessagePortMessageFilter(
base::Bind(&RenderWidgetHelper::GetNextRoutingID,
base::Unretained(widget_helper_.get())));
- AddFilter(message_port_message_filter_);
+ AddFilter(message_port_message_filter_.get());
scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
- new ServiceWorkerDispatcherHost(GetID(), message_port_message_filter_);
+ new ServiceWorkerDispatcherHost(
+ GetID(), message_port_message_filter_.get(), resource_context);
service_worker_filter->Init(
storage_partition_impl_->GetServiceWorkerContext());
- AddFilter(service_worker_filter);
+ AddFilter(service_worker_filter.get());
- // If "--enable-embedded-shared-worker" is set, we use
- // SharedWorkerMessageFilter in stead of WorkerMessageFilter.
- if (WorkerService::EmbeddedSharedWorkerEnabled()) {
- AddFilter(new SharedWorkerMessageFilter(
- GetID(),
- resource_context,
- WorkerStoragePartition(
- storage_partition_impl_->GetURLRequestContext(),
- storage_partition_impl_->GetMediaURLRequestContext(),
- storage_partition_impl_->GetAppCacheService(),
- storage_partition_impl_->GetQuotaManager(),
- storage_partition_impl_->GetFileSystemContext(),
- storage_partition_impl_->GetDatabaseTracker(),
- storage_partition_impl_->GetIndexedDBContext(),
- storage_partition_impl_->GetServiceWorkerContext()),
- message_port_message_filter_));
- } else {
- AddFilter(new WorkerMessageFilter(
- GetID(),
- resource_context,
- WorkerStoragePartition(
- storage_partition_impl_->GetURLRequestContext(),
- storage_partition_impl_->GetMediaURLRequestContext(),
- storage_partition_impl_->GetAppCacheService(),
- storage_partition_impl_->GetQuotaManager(),
- storage_partition_impl_->GetFileSystemContext(),
- storage_partition_impl_->GetDatabaseTracker(),
- storage_partition_impl_->GetIndexedDBContext(),
- storage_partition_impl_->GetServiceWorkerContext()),
- message_port_message_filter_));
- }
+ AddFilter(new SharedWorkerMessageFilter(
+ GetID(),
+ resource_context,
+ WorkerStoragePartition(
+ storage_partition_impl_->GetURLRequestContext(),
+ storage_partition_impl_->GetMediaURLRequestContext(),
+ storage_partition_impl_->GetAppCacheService(),
+ storage_partition_impl_->GetQuotaManager(),
+ storage_partition_impl_->GetFileSystemContext(),
+ storage_partition_impl_->GetDatabaseTracker(),
+ storage_partition_impl_->GetIndexedDBContext(),
+ storage_partition_impl_->GetServiceWorkerContext()),
+ message_port_message_filter_.get()));
#if defined(ENABLE_WEBRTC)
p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost(
resource_context,
browser_context->GetRequestContextForRenderProcess(GetID()));
- AddFilter(p2p_socket_dispatcher_host_);
+ AddFilter(p2p_socket_dispatcher_host_.get());
#endif
AddFilter(new TraceMessageFilter());
@@ -882,38 +844,72 @@ void RenderProcessHostImpl::CreateMessageFilters() {
GetID(),
storage_partition_impl_->GetQuotaManager(),
GetContentClient()->browser()->CreateQuotaPermissionContext()));
+
+ notification_message_filter_ = new NotificationMessageFilter(
+ GetID(),
+ resource_context,
+ browser_context);
+ AddFilter(notification_message_filter_.get());
+
AddFilter(new GamepadBrowserMessageFilter());
+ AddFilter(new DeviceLightMessageFilter());
AddFilter(new DeviceMotionMessageFilter());
AddFilter(new DeviceOrientationMessageFilter());
AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
AddFilter(new HistogramMessageFilter());
#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
- if (CommandLine::ForCurrentProcess()->HasSwitch(
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableMemoryBenchmarking))
AddFilter(new MemoryBenchmarkMessageFilter());
#endif
AddFilter(new VibrationMessageFilter());
- AddFilter(new PushMessagingMessageFilter(GetID()));
- AddFilter(new BatteryStatusMessageFilter());
+ AddFilter(new PushMessagingMessageFilter(
+ GetID(), storage_partition_impl_->GetServiceWorkerContext()));
+#if defined(OS_ANDROID)
+ AddFilter(new ScreenOrientationMessageFilterAndroid());
+#endif
+ AddFilter(new GeofencingDispatcherHost(
+ storage_partition_impl_->GetGeofencingManager()));
+}
+
+void RenderProcessHostImpl::RegisterMojoServices() {
+ mojo_application_host_->service_registry()->AddService(
+ base::Bind(&device::BatteryMonitorImpl::Create));
}
int RenderProcessHostImpl::GetNextRoutingID() {
return widget_helper_->GetNextRoutingID();
}
-
void RenderProcessHostImpl::ResumeDeferredNavigation(
const GlobalRequestID& request_id) {
widget_helper_->ResumeDeferredNavigation(request_id);
}
+void RenderProcessHostImpl::ResumeResponseDeferredAtStart(
+ const GlobalRequestID& request_id) {
+ widget_helper_->ResumeResponseDeferredAtStart(request_id);
+}
+
void RenderProcessHostImpl::NotifyTimezoneChange() {
Send(new ViewMsg_TimezoneChange());
}
+ServiceRegistry* RenderProcessHostImpl::GetServiceRegistry() {
+ DCHECK(mojo_application_host_);
+ return mojo_application_host_->service_registry();
+}
+
+const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics()
+ const {
+ return init_time_;
+}
+
void RenderProcessHostImpl::AddRoute(
int32 routing_id,
IPC::Listener* listener) {
+ CHECK(!listeners_.Lookup(routing_id))
+ << "Found Routing ID Conflict: " << routing_id;
listeners_.AddWithID(listener, routing_id);
}
@@ -923,8 +919,8 @@ void RenderProcessHostImpl::RemoveRoute(int32 routing_id) {
#if defined(OS_WIN)
// Dump the handle table if handle auditing is enabled.
- const CommandLine& browser_command_line =
- *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kAuditHandles) ||
browser_command_line.HasSwitch(switches::kAuditAllHandles)) {
DumpHandles();
@@ -948,21 +944,8 @@ void RenderProcessHostImpl::RemoveObserver(
observers_.RemoveObserver(observer);
}
-bool RenderProcessHostImpl::WaitForBackingStoreMsg(
- int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
- // The post task to this thread with the process id could be in queue, and we
- // don't want to dispatch a message before then since it will need the handle.
- if (child_process_launcher_.get() && child_process_launcher_->IsStarting())
- return false;
-
- return widget_helper_->WaitForBackingStoreMsg(render_widget_id,
- max_delay, msg);
-}
-
void RenderProcessHostImpl::ReceivedBadMessage() {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC))
return;
@@ -1010,23 +993,24 @@ StoragePartition* RenderProcessHostImpl::GetStoragePartition() const {
return storage_partition_impl_;
}
-static void AppendCompositorCommandLineFlags(CommandLine* command_line) {
+static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
if (IsPinchVirtualViewportEnabled())
command_line->AppendSwitch(cc::switches::kEnablePinchVirtualViewport);
- if (IsThreadedCompositingEnabled())
- command_line->AppendSwitch(switches::kEnableThreadedCompositing);
-
if (IsDelegatedRendererEnabled())
command_line->AppendSwitch(switches::kEnableDelegatedRenderer);
- if (IsImplSidePaintingEnabled())
+ if (IsImplSidePaintingEnabled()) {
command_line->AppendSwitch(switches::kEnableImplSidePainting);
+ command_line->AppendSwitchASCII(
+ switches::kNumRasterThreads,
+ base::IntToString(NumberOfRendererRasterThreads()));
+ }
- if (content::IsGpuRasterizationEnabled())
+ if (IsGpuRasterizationEnabled())
command_line->AppendSwitch(switches::kEnableGpuRasterization);
- if (content::IsForceGpuRasterizationEnabled())
+ if (IsForceGpuRasterizationEnabled())
command_line->AppendSwitch(switches::kForceGpuRasterization);
// Appending disable-gpu-feature switches due to software rendering list.
@@ -1036,13 +1020,14 @@ static void AppendCompositorCommandLineFlags(CommandLine* command_line) {
}
void RenderProcessHostImpl::AppendRendererCommandLine(
- CommandLine* command_line) const {
+ base::CommandLine* command_line) const {
// Pass the process type first, so it shows first in process listings.
command_line->AppendSwitchASCII(switches::kProcessType,
switches::kRendererProcess);
// Now send any options from our own command line we want to propagate.
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
// Pass on the browser locale.
@@ -1063,7 +1048,7 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
GetContentClient()->browser()->AppendExtraCommandLineSwitches(
command_line, GetID());
- if (content::IsPinchToZoomEnabled())
+ if (IsPinchToZoomEnabled())
command_line->AppendSwitch(switches::kEnablePinch);
#if defined(OS_WIN)
@@ -1075,8 +1060,8 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
}
void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
- const CommandLine& browser_cmd,
- CommandLine* renderer_cmd) const {
+ const base::CommandLine& browser_cmd,
+ base::CommandLine* renderer_cmd) const {
// Propagate the following switches to the renderer command line (along
// with any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = {
@@ -1090,18 +1075,16 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDefaultTileWidth,
switches::kDefaultTileHeight,
switches::kDisable3DAPIs,
- switches::kDisableAcceleratedFixedRootBackground,
- switches::kDisableAcceleratedOverflowScroll,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableApplicationCache,
+ switches::kDisableBlinkScheduler,
switches::kDisableBreakpad,
- switches::kDisableCompositingForFixedPosition,
+ switches::kDisablePreferCompositingToLCDText,
switches::kDisableCompositingForTransition,
switches::kDisableDatabases,
- switches::kDisableDesktopNotifications,
switches::kDisableDirectNPAPIRequests,
+ switches::kDisableDisplayList2dCanvas,
switches::kDisableDistanceFieldText,
- switches::kDisableFastTextAutosizing,
switches::kDisableFileSystem,
switches::kDisableGpuCompositing,
switches::kDisableGpuVsync,
@@ -1112,62 +1095,64 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableLocalStorage,
switches::kDisableLogging,
switches::kDisableMediaSource,
+ switches::kDisableOneCopy,
switches::kDisableOverlayScrollbar,
switches::kDisablePinch,
switches::kDisablePrefixedEncryptedMedia,
- switches::kDisableRepaintAfterLayout,
switches::kDisableSeccompFilterSandbox,
switches::kDisableSessionStorage,
switches::kDisableSharedWorkers,
+ switches::kDisableSVG1DOM,
+ switches::kDisableThreadedCompositing,
+ switches::kDisableThreadedScrolling,
switches::kDisableTouchAdjustment,
switches::kDisableTouchDragDrop,
switches::kDisableTouchEditing,
- switches::kDisableZeroCopy,
+ switches::kDisableV8IdleNotificationAfterCommit,
switches::kDomAutomationController,
- switches::kEnableAcceleratedFixedRootBackground,
- switches::kEnableAcceleratedOverflowScroll,
+ switches::kEnableAcceleratedJpegDecoding,
switches::kEnableBeginFrameScheduling,
switches::kEnableBleedingEdgeRenderingFastPaths,
- switches::kEnableCompositingForFixedPosition,
+ switches::kEnableBrowserSideNavigation,
+ switches::kEnablePreferCompositingToLCDText,
switches::kEnableCompositingForTransition,
+ switches::kEnableCredentialManagerAPI,
switches::kEnableDeferredImageDecoding,
+ switches::kEnableDisplayList2dCanvas,
switches::kEnableDistanceFieldText,
switches::kEnableEncryptedMedia,
switches::kEnableExperimentalCanvasFeatures,
switches::kEnableExperimentalWebPlatformFeatures,
- switches::kEnableFastTextAutosizing,
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
switches::kEnableGPUServiceLogging,
- switches::kEnableHighDpiCompositingForFixedPosition,
+ switches::kEnableLinkDisambiguationPopup,
switches::kEnableLowResTiling,
switches::kEnableInbandTextTracks,
switches::kEnableLCDText,
switches::kEnableLayerSquashing,
switches::kEnableLogging,
switches::kEnableMemoryBenchmarking,
+ switches::kEnableNetworkInformation,
switches::kEnableOneCopy,
switches::kEnableOverlayFullscreenVideo,
switches::kEnableOverlayScrollbar,
switches::kEnableOverscrollNotifications,
switches::kEnablePinch,
switches::kEnablePreciseMemoryInfo,
- switches::kEnablePreparsedJsCaching,
- switches::kEnableRepaintAfterLayout,
+ switches::kEnableRendererMojoChannel,
switches::kEnableSeccompFilterSandbox,
- switches::kEnableServiceWorker,
switches::kEnableSkiaBenchmarking,
- switches::kEnableSpeechSynthesis,
+ switches::kEnableSmoothScrolling,
switches::kEnableStatsTable,
switches::kEnableStrictSiteIsolation,
- switches::kEnableTargetedStyleRecalc,
+ switches::kEnableThreadedCompositing,
switches::kEnableTouchDragDrop,
switches::kEnableTouchEditing,
+ switches::kEnableV8IdleNotificationAfterCommit,
switches::kEnableViewport,
switches::kEnableViewportMeta,
- switches::kMainFrameResizesAreOrientationChanges,
switches::kEnableVtune,
- switches::kEnableWebAnimationsSVG,
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
switches::kEnableWebMIDI,
@@ -1178,18 +1163,19 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kIPCConnectionTimeout,
switches::kJavaScriptFlags,
switches::kLoggingLevel,
+ switches::kMainFrameResizesAreOrientationChanges,
switches::kMaxUntiledLayerWidth,
switches::kMaxUntiledLayerHeight,
switches::kMemoryMetrics,
switches::kNoReferrers,
switches::kNoSandbox,
- switches::kNumRasterThreads,
switches::kPpapiInProcess,
switches::kProfilerTiming,
switches::kReduceSecurityForTesting,
switches::kRegisterPepperPlugins,
switches::kRendererAssertTest,
switches::kRendererStartupDialog,
+ switches::kRootLayerScrolls,
switches::kShowPaintRects,
switches::kSitePerProcess,
switches::kStatsCollectionController,
@@ -1208,9 +1194,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kCompositeToMailbox,
cc::switches::kDisableCompositedAntialiasing,
- cc::switches::kDisableCompositorTouchHitTesting,
cc::switches::kDisableMainFrameBeforeActivation,
- cc::switches::kDisableMainFrameBeforeDraw,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnableGpuBenchmarking,
cc::switches::kEnableMainFrameBeforeActivation,
@@ -1233,31 +1217,38 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
cc::switches::kTopControlsShowThreshold,
#if defined(ENABLE_PLUGINS)
switches::kEnablePepperTesting,
+ switches::kEnablePluginPowerSaver,
#endif
#if defined(ENABLE_WEBRTC)
switches::kDisableAudioTrackProcessing,
- switches::kDisableDeviceEnumeration,
switches::kDisableWebRtcHWDecoding,
switches::kDisableWebRtcHWEncoding,
switches::kEnableWebRtcHWVp8Encoding,
+ switches::kEnableWebRtcHWH264Encoding,
#endif
+ switches::kLowEndDeviceMode,
#if defined(OS_ANDROID)
switches::kDisableGestureRequirementForMediaPlayback,
- switches::kDisableLowEndDeviceMode,
switches::kDisableWebRTC,
- switches::kEnableLowEndDeviceMode,
switches::kEnableSpeechRecognition,
switches::kMediaDrmEnableNonCompositing,
switches::kNetworkCountryIso,
switches::kDisableWebAudio,
+ switches::kRendererWaitForJavaDebugger,
#endif
#if defined(OS_MACOSX)
// Allow this to be set when invoking the browser and relayed along.
switches::kEnableSandboxLogging,
#endif
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ switches::kEnableThreadedEventHandlingMac,
+#endif
#if defined(OS_WIN)
switches::kDisableDirectWrite,
- switches::kEnableHighResolutionTime,
+ switches::kEnableWin32kRendererLockDown,
+#endif
+#if defined(OS_CHROMEOS)
+ switches::kDisableVaapiAcceleratedVideoEncode,
#endif
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
@@ -1282,16 +1273,26 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
if (IsImplSidePaintingEnabled() &&
!browser_cmd.HasSwitch(switches::kEnableDeferredImageDecoding))
renderer_cmd->AppendSwitch(switches::kEnableDeferredImageDecoding);
+
+ // Add kWaitForDebugger to let renderer process wait for a debugger.
+ if (browser_cmd.HasSwitch(switches::kWaitForDebuggerChildren)) {
+ // Look to pass-on the kWaitForDebugger flag.
+ std::string value =
+ browser_cmd.GetSwitchValueASCII(switches::kWaitForDebuggerChildren);
+ if (value.empty() || value == switches::kRendererProcess) {
+ renderer_cmd->AppendSwitch(switches::kWaitForDebugger);
+ }
+ }
}
base::ProcessHandle RenderProcessHostImpl::GetHandle() const {
if (run_renderer_in_process())
- return base::Process::Current().handle();
+ return base::GetCurrentProcessHandle();
if (!child_process_launcher_.get() || child_process_launcher_->IsStarting())
return base::kNullProcessHandle;
- return child_process_launcher_->GetHandle();
+ return child_process_launcher_->GetProcess().Handle();
}
bool RenderProcessHostImpl::FastShutdownIfPossible() {
@@ -1376,9 +1377,6 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
OnUserMetricsRecordAction)
IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(
- ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
- OnAllocateGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK)
#if defined(ENABLE_WEBRTC)
IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer,
@@ -1404,13 +1402,6 @@ bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
reply->set_reply_error();
Send(reply);
}
-
- // If this is a SwapBuffers, we need to ack it if we're not going to handle
- // it so that the GPU process doesn't get stuck in unscheduled state.
- IPC_BEGIN_MESSAGE_MAP(RenderProcessHostImpl, msg)
- IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
- OnCompositorSurfaceBuffersSwappedNoHost)
- IPC_END_MESSAGE_MAP()
return true;
}
return listener->OnMessageReceived(msg);
@@ -1585,7 +1576,7 @@ RenderProcessHostImpl::StartRtpDump(
bool incoming,
bool outgoing,
const WebRtcRtpPacketCallback& packet_callback) {
- if (!p2p_socket_dispatcher_host_)
+ if (!p2p_socket_dispatcher_host_.get())
return WebRtcStopRtpDumpCallback();
BrowserThread::PostTask(BrowserThread::IO,
@@ -1736,7 +1727,7 @@ bool RenderProcessHost::run_renderer_in_process() {
void RenderProcessHost::SetRunRendererInProcess(bool value) {
g_run_renderer_in_process_ = value;
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (value) {
if (!command_line->HasSwitch(switches::kLang)) {
// Modify the current process' command line to include the browser locale,
@@ -1773,7 +1764,8 @@ bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
// from the same site to share, if we knew what the given process was
// dedicated to. Allowing no sharing is simpler for now.) This may cause
// resource exhaustion issues if too many sites are open at once.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
command_line.HasSwitch(switches::kSitePerProcess))
return false;
@@ -1830,7 +1822,8 @@ bool RenderProcessHost::ShouldUseProcessPerSite(
// the case if the --process-per-site switch is specified, or in
// process-per-site-instance for particular sites (e.g., WebUI).
// Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kProcessPerSite))
return true;
@@ -1915,6 +1908,11 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead) {
base::TERMINATION_STATUS_NORMAL_TERMINATION;
RendererClosedDetails details(GetHandle(), status, exit_code);
+ mojo_application_host_->WillDestroySoon();
+
+ child_process_launcher_.reset();
+ channel_.reset();
+
within_process_died_observer_ = true;
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_CLOSED,
@@ -1922,11 +1920,9 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead) {
Details<RendererClosedDetails>(&details));
FOR_EACH_OBSERVER(RenderProcessHostObserver,
observers_,
- RenderProcessExited(this, GetHandle(), status, exit_code));
+ RenderProcessExited(this, status, exit_code));
within_process_died_observer_ = false;
- child_process_launcher_.reset();
- channel_.reset();
gpu_message_filter_ = NULL;
message_port_message_filter_ = NULL;
RemoveUserData(kSessionStorageHolderKey);
@@ -1940,7 +1936,7 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead) {
iter.Advance();
}
- mojo_application_host_.reset();
+ mojo_application_host_.reset(new MojoApplicationHost);
// It's possible that one of the calls out to the observers might have caused
// this object to be no longer needed.
@@ -2026,6 +2022,8 @@ void RenderProcessHostImpl::OnShutdownRequest() {
Source<RenderProcessHost>(this),
NotificationService::NoDetails());
+ mojo_application_host_->WillDestroySoon();
+
Send(new ChildProcessMsg_Shutdown());
}
@@ -2082,11 +2080,7 @@ void RenderProcessHostImpl::OnProcessLaunched() {
return;
if (child_process_launcher_) {
- if (!child_process_launcher_->GetHandle()) {
- OnChannelError();
- return;
- }
-
+ DCHECK(child_process_launcher_->GetProcess().IsValid());
SetBackgrounded(backgrounded_);
}
@@ -2105,7 +2099,10 @@ void RenderProcessHostImpl::OnProcessLaunched() {
// Allow Mojo to be setup before the renderer sees any Chrome IPC messages.
// This way, Mojo can be safely used from the renderer in response to any
// Chrome IPC message.
- MaybeActivateMojo();
+ mojo_application_host_->Activate(this, GetHandle());
+
+ if (channel_mojo_host_)
+ channel_mojo_host_->OnClientLaunched(GetHandle());
while (!queued_messages_.empty()) {
Send(queued_messages_.front());
@@ -2140,21 +2137,7 @@ void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) {
MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size);
}
-void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost(
- const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
- TRACE_EVENT0("renderer_host",
- "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost");
- if (!ui::LatencyInfo::Verify(params.latency_info,
- "ViewHostMsg_CompositorSurfaceBuffersSwapped"))
- return;
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.sync_point = 0;
- RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
- params.gpu_process_host_id,
- ack_params);
-}
-
-void RenderProcessHostImpl::OnGpuSwitching() {
+void RenderProcessHostImpl::OnGpuSwitched() {
// We are updating all widgets including swapped out ones.
scoped_ptr<RenderWidgetHostIterator> widgets(
RenderWidgetHostImpl::GetAllRenderWidgetHosts());
@@ -2167,7 +2150,7 @@ void RenderProcessHostImpl::OnGpuSwitching() {
continue;
RenderViewHost* rvh = RenderViewHost::From(widget);
- rvh->UpdateWebkitPreferences(rvh->GetWebkitPreferences());
+ rvh->OnWebkitPreferencesChanged();
}
}
@@ -2222,7 +2205,7 @@ void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file,
int id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::FilePath unique_file =
- file.AddExtension(IntToStringType(GetID()))
+ file.AddExtension(IntToStringType(base::GetProcId(GetHandle())))
.AddExtension(IntToStringType(id));
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
@@ -2260,118 +2243,4 @@ void RenderProcessHostImpl::DecrementWorkerRefCount() {
Cleanup();
}
-void RenderProcessHostImpl::ConnectTo(
- const base::StringPiece& service_name,
- mojo::ScopedMessagePipeHandle handle) {
- mojo_activation_required_ = true;
- MaybeActivateMojo();
-
- mojo_application_host_->service_provider()->ConnectToService(
- mojo::String::From(service_name),
- std::string(),
- handle.Pass(),
- mojo::String());
-}
-
-void RenderProcessHostImpl::OnAllocateGpuMemoryBuffer(uint32 width,
- uint32 height,
- uint32 internalformat,
- uint32 usage,
- IPC::Message* reply) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!GpuMemoryBufferImpl::IsFormatValid(internalformat) ||
- !GpuMemoryBufferImpl::IsUsageValid(usage)) {
- GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
- return;
- }
- base::CheckedNumeric<int> size = width;
- size *= height;
- if (!size.IsValid()) {
- GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
- return;
- }
-
-#if defined(OS_MACOSX)
- // TODO(reveman): This should be moved to
- // GpuMemoryBufferImpl::AllocateForChildProcess and
- // GpuMemoryBufferImplIOSurface. crbug.com/325045, crbug.com/323304
- if (GpuMemoryBufferImplIOSurface::IsConfigurationSupported(internalformat,
- usage)) {
- base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
- properties.reset(
- CFDictionaryCreateMutable(kCFAllocatorDefault,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- AddIntegerValue(properties, kIOSurfaceWidth, width);
- AddIntegerValue(properties, kIOSurfaceHeight, height);
- AddIntegerValue(properties,
- kIOSurfaceBytesPerElement,
- GpuMemoryBufferImpl::BytesPerPixel(internalformat));
- AddIntegerValue(
- properties,
- kIOSurfacePixelFormat,
- GpuMemoryBufferImplIOSurface::PixelFormat(internalformat));
- // TODO(reveman): Remove this when using a mach_port_t to transfer
- // IOSurface to renderer process. crbug.com/323304
- AddBooleanValue(
- properties, kIOSurfaceIsGlobal, true);
-
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceCreate(properties));
- if (io_surface) {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::IO_SURFACE_BUFFER;
- handle.io_surface_id = IOSurfaceGetID(io_surface);
-
- // TODO(reveman): This makes the assumption that the renderer will
- // grab a reference to the surface before sending another message.
- // crbug.com/325045
- last_io_surface_ = io_surface;
- GpuMemoryBufferAllocated(reply, handle);
- return;
- }
- }
-#endif
-
-#if defined(OS_ANDROID)
- // TODO(reveman): This should be moved to
- // GpuMemoryBufferImpl::AllocateForChildProcess and
- // GpuMemoryBufferImplSurfaceTexture when adding support for out-of-process
- // GPU service. crbug.com/368716
- if (GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(
- internalformat, usage)) {
- // Each surface texture is associated with a render process id. This allows
- // the GPU service and Java Binder IPC to verify that a renderer is not
- // trying to use a surface texture it doesn't own.
- int surface_texture_id = CompositorImpl::CreateSurfaceTexture(GetID());
- if (surface_texture_id != -1) {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SURFACE_TEXTURE_BUFFER;
- handle.surface_texture_id =
- gfx::SurfaceTextureId(surface_texture_id, GetID());
- GpuMemoryBufferAllocated(reply, handle);
- return;
- }
- }
-#endif
-
- GpuMemoryBufferImpl::AllocateForChildProcess(
- gfx::Size(width, height),
- internalformat,
- usage,
- GetHandle(),
- base::Bind(&RenderProcessHostImpl::GpuMemoryBufferAllocated,
- weak_factory_.GetWeakPtr(),
- reply));
-}
-
-void RenderProcessHostImpl::GpuMemoryBufferAllocated(
- IPC::Message* reply,
- const gfx::GpuMemoryBufferHandle& handle) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply,
- handle);
- Send(reply);
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.h b/chromium/content/browser/renderer_host/render_process_host_impl.h
index 2728626246e..b3bdf3bea7f 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_IMPL_H_
-#define CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_IMPL_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_PROCESS_HOST_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_PROCESS_HOST_IMPL_H_
#include <map>
#include <queue>
@@ -12,23 +12,17 @@
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/process/process.h"
-#include "base/timer/timer.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/power_monitor_message_broadcaster.h"
#include "content/common/content_export.h"
-#include "content/public/browser/gpu_data_manager_observer.h"
+#include "content/common/mojo/service_registry_impl.h"
#include "content/public/browser/render_process_host.h"
#include "ipc/ipc_channel_proxy.h"
#include "ipc/ipc_platform_file.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
-
-#if defined(OS_MACOSX)
-#include <IOSurface/IOSurfaceAPI.h>
-#include "base/mac/scoped_cftyperef.h"
-#endif
-
-struct ViewHostMsg_CompositorSurfaceBuffersSwapped_Params;
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gl/gpu_switching_observer.h"
namespace base {
class CommandLine;
@@ -37,21 +31,25 @@ class MessageLoop;
namespace gfx {
class Size;
-struct GpuMemoryBufferHandle;
+}
+
+namespace IPC {
+class ChannelMojoHost;
}
namespace content {
class AudioRendererHost;
+class BrowserCdmManager;
class BrowserDemuxerAndroid;
class GpuMessageFilter;
class MessagePortMessageFilter;
class MojoApplicationHost;
+class NotificationMessageFilter;
#if defined(ENABLE_WEBRTC)
class P2PSocketDispatcherHost;
#endif
class PeerConnectionTrackerHost;
class RendererMainThread;
-class RenderProcessHostMojoImpl;
class RenderWidgetHelper;
class RenderWidgetHost;
class RenderWidgetHostImpl;
@@ -84,77 +82,74 @@ typedef base::Thread* (*RendererMainThreadFactoryFunction)(
class CONTENT_EXPORT RenderProcessHostImpl
: public RenderProcessHost,
public ChildProcessLauncher::Client,
- public GpuDataManagerObserver {
+ public ui::GpuSwitchingObserver {
public:
RenderProcessHostImpl(BrowserContext* browser_context,
StoragePartitionImpl* storage_partition_impl,
bool is_isolated_guest);
- virtual ~RenderProcessHostImpl();
+ ~RenderProcessHostImpl() override;
// RenderProcessHost implementation (public portion).
- virtual void EnableSendQueue() OVERRIDE;
- virtual bool Init() OVERRIDE;
- virtual int GetNextRoutingID() OVERRIDE;
- virtual void AddRoute(int32 routing_id, IPC::Listener* listener) OVERRIDE;
- virtual void RemoveRoute(int32 routing_id) OVERRIDE;
- virtual void AddObserver(RenderProcessHostObserver* observer) OVERRIDE;
- virtual void RemoveObserver(RenderProcessHostObserver* observer) OVERRIDE;
- virtual bool WaitForBackingStoreMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) OVERRIDE;
- virtual void ReceivedBadMessage() OVERRIDE;
- virtual void WidgetRestored() OVERRIDE;
- virtual void WidgetHidden() OVERRIDE;
- virtual int VisibleWidgetCount() const OVERRIDE;
- virtual bool IsIsolatedGuest() const OVERRIDE;
- virtual StoragePartition* GetStoragePartition() const OVERRIDE;
- virtual bool FastShutdownIfPossible() OVERRIDE;
- virtual void DumpHandles() OVERRIDE;
- virtual base::ProcessHandle GetHandle() const OVERRIDE;
- virtual BrowserContext* GetBrowserContext() const OVERRIDE;
- virtual bool InSameStoragePartition(
- StoragePartition* partition) const OVERRIDE;
- virtual int GetID() const OVERRIDE;
- virtual bool HasConnection() const OVERRIDE;
- virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE;
- virtual bool IgnoreInputEvents() const OVERRIDE;
- virtual void Cleanup() OVERRIDE;
- virtual void AddPendingView() OVERRIDE;
- virtual void RemovePendingView() OVERRIDE;
- virtual void SetSuddenTerminationAllowed(bool enabled) OVERRIDE;
- virtual bool SuddenTerminationAllowed() const OVERRIDE;
- virtual IPC::ChannelProxy* GetChannel() OVERRIDE;
- virtual void AddFilter(BrowserMessageFilter* filter) OVERRIDE;
- virtual bool FastShutdownForPageCount(size_t count) OVERRIDE;
- virtual bool FastShutdownStarted() const OVERRIDE;
- virtual base::TimeDelta GetChildProcessIdleTime() const OVERRIDE;
- virtual void ResumeRequestsForView(int route_id) OVERRIDE;
- virtual void FilterURL(bool empty_allowed, GURL* url) OVERRIDE;
+ void EnableSendQueue() override;
+ bool Init() override;
+ int GetNextRoutingID() override;
+ void AddRoute(int32 routing_id, IPC::Listener* listener) override;
+ void RemoveRoute(int32 routing_id) override;
+ void AddObserver(RenderProcessHostObserver* observer) override;
+ void RemoveObserver(RenderProcessHostObserver* observer) override;
+ void ReceivedBadMessage() override;
+ void WidgetRestored() override;
+ void WidgetHidden() override;
+ int VisibleWidgetCount() const override;
+ bool IsIsolatedGuest() const override;
+ StoragePartition* GetStoragePartition() const override;
+ bool FastShutdownIfPossible() override;
+ void DumpHandles() override;
+ base::ProcessHandle GetHandle() const override;
+ BrowserContext* GetBrowserContext() const override;
+ bool InSameStoragePartition(StoragePartition* partition) const override;
+ int GetID() const override;
+ bool HasConnection() const override;
+ void SetIgnoreInputEvents(bool ignore_input_events) override;
+ bool IgnoreInputEvents() const override;
+ void Cleanup() override;
+ void AddPendingView() override;
+ void RemovePendingView() override;
+ void SetSuddenTerminationAllowed(bool enabled) override;
+ bool SuddenTerminationAllowed() const override;
+ IPC::ChannelProxy* GetChannel() override;
+ void AddFilter(BrowserMessageFilter* filter) override;
+ bool FastShutdownForPageCount(size_t count) override;
+ bool FastShutdownStarted() const override;
+ base::TimeDelta GetChildProcessIdleTime() const override;
+ void ResumeRequestsForView(int route_id) override;
+ void FilterURL(bool empty_allowed, GURL* url) override;
#if defined(ENABLE_WEBRTC)
- virtual void EnableAecDump(const base::FilePath& file) OVERRIDE;
- virtual void DisableAecDump() OVERRIDE;
- virtual void SetWebRtcLogMessageCallback(
- base::Callback<void(const std::string&)> callback) OVERRIDE;
- virtual WebRtcStopRtpDumpCallback StartRtpDump(
+ void EnableAecDump(const base::FilePath& file) override;
+ void DisableAecDump() override;
+ void SetWebRtcLogMessageCallback(
+ base::Callback<void(const std::string&)> callback) override;
+ WebRtcStopRtpDumpCallback StartRtpDump(
bool incoming,
bool outgoing,
- const WebRtcRtpPacketCallback& packet_callback) OVERRIDE;
+ const WebRtcRtpPacketCallback& packet_callback) override;
#endif
- virtual void ResumeDeferredNavigation(const GlobalRequestID& request_id)
- OVERRIDE;
- virtual void NotifyTimezoneChange() OVERRIDE;
+ void ResumeDeferredNavigation(const GlobalRequestID& request_id) override;
+ void NotifyTimezoneChange() override;
+ ServiceRegistry* GetServiceRegistry() override;
+ const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
// IPC::Sender via RenderProcessHost.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// IPC::Listener via RenderProcessHost.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
- virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
+ void OnBadMessageReceived(const IPC::Message& message) override;
// ChildProcessLauncher::Client implementation.
- virtual void OnProcessLaunched() OVERRIDE;
+ void OnProcessLaunched() override;
scoped_refptr<AudioRendererHost> audio_renderer_host() const;
@@ -236,8 +231,18 @@ class CONTENT_EXPORT RenderProcessHostImpl
}
#endif
+#if defined(ENABLE_BROWSER_CDMS)
+ const scoped_refptr<BrowserCdmManager>& browser_cdm_manager() {
+ return browser_cdm_manager_;
+ }
+#endif
+
MessagePortMessageFilter* message_port_message_filter() const {
- return message_port_message_filter_;
+ return message_port_message_filter_.get();
+ }
+
+ NotificationMessageFilter* notification_message_filter() const {
+ return notification_message_filter_.get();
}
void set_is_isolated_guest_for_testing(bool is_isolated_guest) {
@@ -250,24 +255,19 @@ class CONTENT_EXPORT RenderProcessHostImpl
void IncrementWorkerRefCount();
void DecrementWorkerRefCount();
- // Establish a connection to a renderer-provided service. See
- // content/common/mojo/mojo_service_names.h for a list of services.
- void ConnectTo(const base::StringPiece& service_name,
- mojo::ScopedMessagePipeHandle handle);
-
- template <typename Interface>
- void ConnectTo(const base::StringPiece& service_name,
- mojo::InterfacePtr<Interface>* ptr) {
- mojo::MessagePipe pipe;
- ptr->Bind(pipe.handle0.Pass());
- ConnectTo(service_name, pipe.handle1.Pass());
- }
+ // Call this function to resume the navigation when it was deferred
+ // immediately after receiving response headers.
+ void ResumeResponseDeferredAtStart(const GlobalRequestID& request_id);
protected:
// A proxy for our IPC::Channel that lives on the IO thread (see
// browser_process.h)
scoped_ptr<IPC::ChannelProxy> channel_;
+ // A host object ChannelMojo needs. The lifetime is bound to
+ // the RenderProcessHostImpl, not the channel.
+ scoped_ptr<IPC::ChannelMojoHost> channel_mojo_host_;
+
// True if fast shutdown has been performed on this RPH.
bool fast_shutdown_started_;
@@ -287,11 +287,16 @@ class CONTENT_EXPORT RenderProcessHostImpl
private:
friend class VisitRelayingRenderProcessHost;
- void MaybeActivateMojo();
+ bool ShouldUseMojoChannel() const;
+ scoped_ptr<IPC::ChannelProxy> CreateChannelProxy(
+ const std::string& channel_id);
// Creates and adds the IO thread message filters.
void CreateMessageFilters();
+ // Registers Mojo services to be exposed to the renderer.
+ void RegisterMojoServices();
+
// Control message handlers.
void OnShutdownRequest();
void OnDumpHandlesDone();
@@ -300,10 +305,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
void OnSavedPageAsMHTML(int job_id, int64 mhtml_file_size);
void OnCloseACK(int old_route_id);
- // CompositorSurfaceBuffersSwapped handler when there's no RWH.
- void OnCompositorSurfaceBuffersSwappedNoHost(
- const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params);
-
// Generates a command line to be used to spawn a renderer and appends the
// results to |*command_line|.
void AppendRendererCommandLine(base::CommandLine* command_line) const;
@@ -321,7 +322,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Handle termination of our process.
void ProcessDied(bool already_dead);
- virtual void OnGpuSwitching() OVERRIDE;
+ // GpuSwitchingObserver implementation.
+ void OnGpuSwitched() override;
#if defined(ENABLE_WEBRTC)
void OnRegisterAecDumpConsumer(int id);
@@ -335,17 +337,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void SendDisableAecDumpToRenderer();
#endif
- // GpuMemoryBuffer allocation handler.
- void OnAllocateGpuMemoryBuffer(uint32 width,
- uint32 height,
- uint32 internalformat,
- uint32 usage,
- IPC::Message* reply);
- void GpuMemoryBufferAllocated(IPC::Message* reply,
- const gfx::GpuMemoryBufferHandle& handle);
-
scoped_ptr<MojoApplicationHost> mojo_application_host_;
- bool mojo_activation_required_;
// The registered IPC listener objects. When this list is empty, we should
// delete ourselves.
@@ -374,6 +366,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// The filter for MessagePort messages coming from the renderer.
scoped_refptr<MessagePortMessageFilter> message_port_message_filter_;
+ // The filter for Web Notification messages coming from the renderer. Holds a
+ // closure per notification that must be freed when the notification closes.
+ scoped_refptr<NotificationMessageFilter> notification_message_filter_;
+
// Used in single-process mode.
scoped_ptr<base::Thread> in_process_renderer_;
@@ -381,6 +377,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
// also reset that in the case of process termination.
bool is_initialized_;
+ // PlzNavigate
+ // Stores the time at which the first call to Init happened.
+ base::TimeTicks init_time_;
+
// Used to launch and terminate the process without blocking the UI thread.
scoped_ptr<ChildProcessLauncher> child_process_launcher_;
@@ -445,6 +445,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
scoped_refptr<BrowserDemuxerAndroid> browser_demuxer_android_;
#endif
+#if defined(ENABLE_BROWSER_CDMS)
+ scoped_refptr<BrowserCdmManager> browser_cdm_manager_;
+#endif
+
#if defined(ENABLE_WEBRTC)
base::Callback<void(const std::string&)> webrtc_log_message_callback_;
@@ -463,13 +467,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
-#if defined(OS_MACOSX)
- base::ScopedCFTypeRef<IOSurfaceRef> last_io_surface_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_IMPL_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_PROCESS_HOST_IMPL_H_
diff --git a/chromium/content/browser/renderer_host/render_process_host_unittest.cc b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
index 474a72bd166..e25c53c7307 100644
--- a/chromium/content/browser/renderer_host/render_process_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_unittest.cc
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <limits>
+
+#include "base/command_line.h"
+#include "content/public/common/content_constants.h"
+#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/test/test_render_view_host.h"
@@ -26,4 +31,60 @@ TEST_F(RenderProcessHostUnitTest, GuestsAreNotSuitableHosts) {
RenderProcessHost::GetExistingProcessHost(browser_context(), test_url));
}
+#if !defined(OS_ANDROID)
+TEST_F(RenderProcessHostUnitTest, RendererProcessLimit) {
+ // This test shouldn't run with --site-per-process or
+ // --enable-strict-site-isolation modes, since they don't allow renderer
+ // process reuse, which this test explicitly exercises.
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kSitePerProcess) ||
+ command_line.HasSwitch(switches::kEnableStrictSiteIsolation))
+ return;
+
+ // Disable any overrides.
+ RenderProcessHostImpl::SetMaxRendererProcessCount(0);
+
+ // Verify that the limit is between 1 and kMaxRendererProcessCount.
+ EXPECT_GT(RenderProcessHostImpl::GetMaxRendererProcessCount(), 0u);
+ EXPECT_LE(RenderProcessHostImpl::GetMaxRendererProcessCount(),
+ kMaxRendererProcessCount);
+
+ // Add dummy process hosts to saturate the limit.
+ ASSERT_NE(0u, kMaxRendererProcessCount);
+ ScopedVector<MockRenderProcessHost> hosts;
+ for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
+ hosts.push_back(new MockRenderProcessHost(browser_context()));
+ }
+
+ // Verify that the renderer sharing will happen.
+ GURL test_url("http://foo.com");
+ EXPECT_TRUE(RenderProcessHostImpl::ShouldTryToUseExistingProcessHost(
+ browser_context(), test_url));
+}
+#endif
+
+#if defined(OS_ANDROID)
+TEST_F(RenderProcessHostUnitTest, NoRendererProcessLimitOnAndroid) {
+ // Disable any overrides.
+ RenderProcessHostImpl::SetMaxRendererProcessCount(0);
+
+ // Verify that by default the limit on Android returns max size_t.
+ EXPECT_EQ(std::numeric_limits<size_t>::max(),
+ RenderProcessHostImpl::GetMaxRendererProcessCount());
+
+ // Add a few dummy process hosts.
+ ASSERT_NE(0u, kMaxRendererProcessCount);
+ ScopedVector<MockRenderProcessHost> hosts;
+ for (size_t i = 0; i < kMaxRendererProcessCount; ++i) {
+ hosts.push_back(new MockRenderProcessHost(browser_context()));
+ }
+
+ // Verify that the renderer sharing still won't happen.
+ GURL test_url("http://foo.com");
+ EXPECT_FALSE(RenderProcessHostImpl::ShouldTryToUseExistingProcessHost(
+ browser_context(), test_url));
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
index 6015c04306e..2fdaf0aa833 100644
--- a/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -34,11 +34,10 @@ class RenderViewHostTestWebContentsObserver : public WebContentsObserver {
explicit RenderViewHostTestWebContentsObserver(WebContents* web_contents)
: WebContentsObserver(web_contents),
navigation_count_(0) {}
- virtual ~RenderViewHostTestWebContentsObserver() {}
+ ~RenderViewHostTestWebContentsObserver() override {}
- virtual void DidNavigateMainFrame(
- const LoadCommittedDetails& details,
- const FrameNavigateParams& params) OVERRIDE {
+ void DidNavigateMainFrame(const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override {
observed_socket_address_ = params.socket_address;
base_url_ = params.base_url;
++navigation_count_;
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.cc b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
index 88e590b097f..41a110e3f5c 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.cc
@@ -4,8 +4,8 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/public/common/web_preferences.h"
#include "url/gurl.h"
-#include "webkit/common/webpreferences.h"
namespace content {
@@ -22,7 +22,7 @@ WebContents* RenderViewHostDelegate::GetAsWebContents() {
return NULL;
}
-WebPreferences RenderViewHostDelegate::GetWebkitPrefs() {
+WebPreferences RenderViewHostDelegate::ComputeWebkitPrefs() {
return WebPreferences();
}
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate.h b/chromium/content/browser/renderer_host/render_view_host_delegate.h
index fd8aeae8625..b7074f5704b 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate.h
@@ -13,8 +13,6 @@
#include "base/strings/string16.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/common/content_export.h"
-#include "content/public/common/media_stream_request.h"
-#include "content/public/common/page_transition_types.h"
#include "net/base/load_states.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "ui/base/window_open_disposition.h"
@@ -24,7 +22,6 @@ class SkBitmap;
struct ViewHostMsg_CreateWindow_Params;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
struct ViewMsg_PostMessage_Params;
-struct WebPreferences;
namespace base {
class ListValue;
@@ -53,12 +50,12 @@ class SessionStorageNamespace;
class SiteInstance;
class WebContents;
class WebContentsImpl;
-struct AXEventNotificationDetails;
struct FileChooserParams;
struct GlobalRequestID;
struct NativeWebKeyboardEvent;
struct Referrer;
struct RendererPreferences;
+struct WebPreferences;
//
// RenderViewHostDelegate
@@ -112,8 +109,8 @@ class CONTENT_EXPORT RenderViewHostDelegate {
int32 page_id,
const PageState& state) {}
- // The destination URL has changed should be updated
- virtual void UpdateTargetURL(int32 page_id, const GURL& url) {}
+ // The destination URL has changed should be updated.
+ virtual void UpdateTargetURL(const GURL& url) {}
// The page is trying to close the RenderView's representation in the client.
virtual void Close(RenderViewHost* render_view_host) {}
@@ -141,9 +138,9 @@ class CONTENT_EXPORT RenderViewHostDelegate {
virtual RendererPreferences GetRendererPrefs(
BrowserContext* browser_context) const = 0;
- // Returns a WebPreferences object that will be used by the renderer
+ // Computes a WebPreferences object that will be used by the renderer
// associated with the owning render view host.
- virtual WebPreferences GetWebkitPrefs();
+ virtual WebPreferences ComputeWebkitPrefs();
// Notification the user has made a gesture while focus was on the
// page. This is used to avoid uninitiated user downloads (aka carpet
@@ -158,9 +155,7 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// 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,
- bool is_during_before_unload,
- bool is_during_unload) {}
+ virtual void RendererUnresponsive(RenderViewHost* render_view_host) {}
// Notification that a previously unresponsive renderer has become
// responsive again. The delegate can use this notification to end the
@@ -266,13 +261,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// Show the newly created full screen widget. Similar to above.
virtual void ShowCreatedFullscreenWidget(int route_id) {}
- // The render view has requested access to media devices listed in
- // |request|, and the client should grant or deny that permission by
- // calling |callback|.
- virtual void RequestMediaAccessPermission(
- const MediaStreamRequest& request,
- const MediaResponseCallback& callback) {}
-
// Returns the SessionStorageNamespace the render view should use. Might
// create the SessionStorageNamespace on the fly.
virtual SessionStorageNamespace* GetSessionStorageNamespace(
@@ -292,10 +280,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
// created by the RenderViewHost.
virtual FrameTree* GetFrameTree();
- // Invoked when an accessibility event is received from the renderer.
- virtual void AccessibilityEventReceived(
- const std::vector<AXEventNotificationDetails>& details) {}
-
protected:
virtual ~RenderViewHostDelegate() {}
};
diff --git a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
index fb2babdc87f..53366ecb3ef 100644
--- a/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
+++ b/chromium/content/browser/renderer_host/render_view_host_delegate_view.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "content/common/content_export.h"
#include "content/common/drag_event_source_info.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
@@ -20,6 +21,11 @@ class Rect;
class Vector2d;
}
+namespace ui {
+class GestureEvent;
+class MouseEvent;
+}
+
namespace content {
class RenderFrameHost;
struct ContextMenuParams;
@@ -36,20 +42,6 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
const ContextMenuParams& params) {}
- // Shows a popup menu with the specified items.
- // This method should call RenderViewHost::DidSelectPopupMenuItem[s]() or
- // RenderViewHost::DidCancelPopupMenu() based on the user action.
- virtual void ShowPopupMenu(const gfx::Rect& bounds,
- int item_height,
- double item_font_size,
- int selected_item,
- const std::vector<MenuItem>& items,
- bool right_aligned,
- bool allow_multiple_selection) {};
-
- // Hides a popup menu opened by ShowPopupMenu().
- virtual void HidePopupMenu() {};
-
// The user started dragging content of the specified type within the
// RenderView. Contextual information about the dragged content is supplied
// by DropData. If the delegate's view cannot start the drag for /any/
@@ -73,6 +65,39 @@ class CONTENT_EXPORT RenderViewHostDelegateView {
// retrieved by doing a Shift-Tab.
virtual void TakeFocus(bool reverse) {}
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ // Shows a popup menu with the specified items.
+ // This method should call RenderFrameHost::DidSelectPopupMenuItem[s]() or
+ // RenderFrameHost::DidCancelPopupMenu() based on the user action.
+ virtual void ShowPopupMenu(RenderFrameHost* render_frame_host,
+ const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection) {};
+
+ // Hides a popup menu opened by ShowPopupMenu().
+ virtual void HidePopupMenu() {};
+#endif
+
+#if defined(TOOLKIT_VIEWS) || defined(USE_AURA)
+ // Shows a Link Disambiguation Popup. |target_rect| is the area the user
+ // touched that resulted in ambiguity, in DIPs in the host's coordinate
+ // system, |zoomed_bitmap| is an enlarged image of that |target_rect|, and
+ // |callback| is for forwarding on to the original scale web content.
+ virtual void ShowDisambiguationPopup(
+ const gfx::Rect& target_rect,
+ const SkBitmap& zoomed_bitmap,
+ const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
+ const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {}
+
+ // Hides the Link Disambiguation Popup, if it was showing, otherwise does
+ // nothing.
+ virtual void HideDisambiguationPopup() {}
+#endif
+
protected:
virtual ~RenderViewHostDelegateView() {}
};
diff --git a/chromium/content/browser/renderer_host/render_view_host_factory.cc b/chromium/content/browser/renderer_host/render_view_host_factory.cc
index 5cffd134b8e..0b2edf21f0d 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -26,8 +26,14 @@ RenderViewHost* RenderViewHostFactory::Create(
routing_id, main_frame_routing_id,
swapped_out);
}
- return new RenderViewHostImpl(instance, delegate, widget_delegate, routing_id,
- main_frame_routing_id, swapped_out, hidden);
+ return new RenderViewHostImpl(instance,
+ delegate,
+ widget_delegate,
+ routing_id,
+ main_frame_routing_id,
+ swapped_out,
+ hidden,
+ true /* has_initialized_audio_host */);
}
// static
diff --git a/chromium/content/browser/renderer_host/render_view_host_impl.cc b/chromium/content/browser/renderer_host/render_view_host_impl.cc
index e14b364cadf..01a5e1bb5d8 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -15,6 +15,7 @@
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -23,9 +24,7 @@
#include "base/time/time.h"
#include "base/values.h"
#include "cc/base/switches.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/cross_site_request_manager.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/gpu/compositor_util.h"
@@ -35,24 +34,20 @@
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/common/accessibility_messages.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_switches_internal.h"
#include "content/common/drag_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/inter_process_time_ticks_converter.h"
-#include "content/common/mojo/mojo_service_names.h"
#include "content/common/speech_recognition_messages.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
-#include "content/common/web_ui_setup.mojom.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
@@ -71,27 +66,26 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/drop_data.h"
+#include "content/public/common/file_chooser_file_info.h"
+#include "content/public/common/file_chooser_params.h"
#include "content/public/common/result_codes.h"
+#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "net/base/filename_util.h"
#include "net/base/net_util.h"
#include "net/base/network_change_notifier.h"
#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/fileapi/isolated_context.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/accessibility/ax_tree.h"
#include "ui/base/touch/touch_device.h"
#include "ui/base/touch/touch_enabled.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/native_theme/native_theme_switches.h"
-#include "ui/shell_dialogs/selected_file_info.h"
#include "url/url_constants.h"
-#include "webkit/browser/fileapi/isolated_context.h"
-#if defined(OS_MACOSX)
-#include "content/browser/renderer_host/popup_menu_helper_mac.h"
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
#include "base/win/win_util.h"
#endif
@@ -137,22 +131,12 @@ void DismissVirtualKeyboardTask() {
} // namespace
// static
-const int RenderViewHostImpl::kUnloadTimeoutMS = 1000;
+const int64 RenderViewHostImpl::kUnloadTimeoutMS = 1000;
///////////////////////////////////////////////////////////////////////////////
// RenderViewHost, public:
// static
-bool RenderViewHostImpl::IsRVHStateActive(RenderViewHostImplState rvh_state) {
- if (rvh_state == STATE_DEFAULT ||
- rvh_state == STATE_WAITING_FOR_UNLOAD_ACK ||
- rvh_state == STATE_WAITING_FOR_COMMIT ||
- rvh_state == STATE_WAITING_FOR_CLOSE)
- return true;
- return false;
-}
-
-// static
RenderViewHost* RenderViewHost::FromID(int render_process_id,
int render_view_id) {
return RenderViewHostImpl::FromID(render_process_id, render_view_id);
@@ -184,7 +168,8 @@ RenderViewHostImpl::RenderViewHostImpl(
int routing_id,
int main_frame_routing_id,
bool swapped_out,
- bool hidden)
+ bool hidden,
+ bool has_initialized_audio_host)
: RenderWidgetHostImpl(widget_delegate,
instance->GetProcess(),
routing_id,
@@ -194,43 +179,46 @@ RenderViewHostImpl::RenderViewHostImpl(
instance_(static_cast<SiteInstanceImpl*>(instance)),
waiting_for_drag_context_response_(false),
enabled_bindings_(0),
- navigations_suspended_(false),
+ page_id_(-1),
+ is_active_(!swapped_out),
+ is_swapped_out_(swapped_out),
main_frame_routing_id_(main_frame_routing_id),
run_modal_reply_msg_(NULL),
run_modal_opener_id_(MSG_ROUTING_NONE),
- is_waiting_for_beforeunload_ack_(false),
- unload_ack_is_for_cross_site_transition_(false),
+ is_waiting_for_close_ack_(false),
sudden_termination_allowed_(false),
render_view_termination_status_(base::TERMINATION_STATUS_STILL_RUNNING),
virtual_keyboard_requested_(false),
- weak_factory_(this),
- is_focused_element_editable_(false) {
+ is_focused_element_editable_(false),
+ updating_web_preferences_(false),
+ weak_factory_(this) {
DCHECK(instance_.get());
CHECK(delegate_); // http://crbug.com/82827
GetProcess()->EnableSendQueue();
- if (swapped_out) {
- rvh_state_ = STATE_SWAPPED_OUT;
- } else {
- rvh_state_ = STATE_DEFAULT;
- instance_->increment_active_view_count();
- }
-
if (ResourceDispatcherHostImpl::Get()) {
+ bool has_active_audio = false;
+ if (has_initialized_audio_host) {
+ scoped_refptr<AudioRendererHost> arh =
+ static_cast<RenderProcessHostImpl*>(GetProcess())
+ ->audio_renderer_host();
+ if (arh.get())
+ has_active_audio = arh->RenderViewHasActiveAudio(GetRoutingID());
+ }
BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
+ BrowserThread::IO,
+ FROM_HERE,
base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID()));
+ GetProcess()->GetID(),
+ GetRoutingID(),
+ !is_hidden(),
+ has_active_audio));
}
-
#if defined(ENABLE_BROWSER_CDMS)
media_web_contents_observer_.reset(new MediaWebContentsObserver(this));
#endif
-
- unload_event_monitor_timeout_.reset(new TimeoutMonitor(base::Bind(
- &RenderViewHostImpl::OnSwappedOut, weak_factory_.GetWeakPtr(), true)));
}
RenderViewHostImpl::~RenderViewHostImpl() {
@@ -243,22 +231,13 @@ RenderViewHostImpl::~RenderViewHostImpl() {
}
delegate_->RenderViewDeleted(this);
-
- // Be sure to clean up any leftover state from cross-site requests.
- CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
- GetProcess()->GetID(), GetRoutingID(), false);
-
- // If this was swapped out, it already decremented the active view
- // count of the SiteInstance it belongs to.
- if (IsRVHStateActive(rvh_state_))
- instance_->decrement_active_view_count();
}
RenderViewHostDelegate* RenderViewHostImpl::GetDelegate() const {
return delegate_;
}
-SiteInstance* RenderViewHostImpl::GetSiteInstance() const {
+SiteInstanceImpl* RenderViewHostImpl::GetSiteInstance() const {
return instance_.get();
}
@@ -268,7 +247,8 @@ bool RenderViewHostImpl::CreateRenderView(
int proxy_route_id,
int32 max_page_id,
bool window_was_created_with_opener) {
- TRACE_EVENT0("renderer_host", "RenderViewHostImpl::CreateRenderView");
+ TRACE_EVENT0("renderer_host,navigation",
+ "RenderViewHostImpl::CreateRenderView");
DCHECK(!IsRenderViewLive()) << "Creating view twice";
// The process may (if we're sharing a process with another host that already
@@ -294,23 +274,22 @@ bool RenderViewHostImpl::CreateRenderView(
ViewMsg_New_Params params;
params.renderer_preferences =
delegate_->GetRendererPrefs(GetProcess()->GetBrowserContext());
- params.web_preferences = delegate_->GetWebkitPrefs();
+ params.web_preferences = GetWebkitPreferences();
params.view_id = GetRoutingID();
params.main_frame_routing_id = main_frame_routing_id_;
params.surface_id = surface_id();
params.session_storage_namespace_id =
- delegate_->GetSessionStorageNamespace(instance_)->id();
+ delegate_->GetSessionStorageNamespace(instance_.get())->id();
params.frame_name = frame_name;
// Ensure the RenderView sets its opener correctly.
params.opener_route_id = opener_route_id;
- params.swapped_out = !IsRVHStateActive(rvh_state_);
+ params.swapped_out = !is_active_;
params.proxy_routing_id = proxy_route_id;
params.hidden = is_hidden();
params.never_visible = delegate_->IsNeverVisible();
params.window_was_created_with_opener = window_was_created_with_opener;
params.next_page_id = next_page_id;
GetWebScreenInfo(&params.screen_info);
- params.accessibility_mode = accessibility_mode();
Send(new ViewMsg_New(params));
@@ -335,11 +314,12 @@ void RenderViewHostImpl::SyncRendererPrefs() {
GetProcess()->GetBrowserContext())));
}
-WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
+WebPreferences RenderViewHostImpl::ComputeWebkitPrefs(const GURL& url) {
TRACE_EVENT0("browser", "RenderViewHostImpl::GetWebkitPrefs");
WebPreferences prefs;
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
prefs.javascript_enabled =
!command_line.HasSwitch(switches::kDisableJavaScript);
@@ -387,8 +367,6 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
GpuProcessHost::gpu_enabled() &&
!command_line.HasSwitch(switches::kDisableFlashStage3d);
- prefs.site_specific_quirks_enabled =
- !command_line.HasSwitch(switches::kDisableSiteSpecificQuirks);
prefs.allow_file_access_from_file_urls =
command_line.HasSwitch(switches::kAllowFileAccessFromFiles);
@@ -403,13 +381,15 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
!command_line.HasSwitch(switches::kDisableAccelerated2dCanvas);
prefs.antialiased_2d_canvas_disabled =
command_line.HasSwitch(switches::kDisable2dCanvasAntialiasing);
+ prefs.antialiased_clips_2d_canvas_enabled =
+ command_line.HasSwitch(switches::kEnable2dCanvasClipAntialiasing);
prefs.accelerated_2d_canvas_msaa_sample_count =
atoi(command_line.GetSwitchValueASCII(
switches::kAcceleratedCanvas2dMSAASampleCount).c_str());
- prefs.deferred_filters_enabled =
- !command_line.HasSwitch(switches::kDisableDeferredFilters);
prefs.container_culling_enabled =
command_line.HasSwitch(switches::kEnableContainerCulling);
+ prefs.text_blobs_enabled =
+ command_line.HasSwitch(switches::kEnableTextBlobs);
prefs.region_based_columns_enabled =
command_line.HasSwitch(switches::kEnableRegionBasedColumns);
@@ -420,8 +400,14 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
prefs.use_solid_color_scrollbars = ui::IsOverlayScrollbarEnabled();
#if defined(OS_ANDROID)
+ // On Android, user gestures are normally required, unless that requirement
+ // is disabled with a command-line switch or the equivalent field trial is
+ // is set to "Enabled".
+ const std::string autoplay_group_name = base::FieldTrialList::FindFullName(
+ "MediaElementAutoplay");
prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
- switches::kDisableGestureRequirementForMediaPlayback);
+ switches::kDisableGestureRequirementForMediaPlayback) &&
+ (autoplay_group_name.empty() || autoplay_group_name != "Enabled");
#endif
prefs.touch_enabled = ui::AreTouchEventsEnabled();
@@ -435,8 +421,9 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
prefs.touch_adjustment_enabled =
!command_line.HasSwitch(switches::kDisableTouchAdjustment);
- prefs.compositor_touch_hit_testing =
- !command_line.HasSwitch(cc::switches::kDisableCompositorTouchHitTesting);
+
+ prefs.slimming_paint_enabled =
+ command_line.HasSwitch(switches::kEnableSlimmingPaint);
#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
bool default_enable_scroll_animator = true;
@@ -462,9 +449,6 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
prefs.is_online =
prefs.connection_type != net::NetworkChangeNotifier::CONNECTION_NONE;
- prefs.gesture_tap_highlight_enabled = !command_line.HasSwitch(
- switches::kDisableGestureTapHighlight);
-
prefs.number_of_cpu_cores = base::SysInfo::NumberOfProcessors();
prefs.viewport_meta_enabled =
@@ -481,139 +465,51 @@ WebPreferences RenderViewHostImpl::GetWebkitPrefs(const GURL& url) {
command_line.HasSwitch(switches::kEnableDeferredImageDecoding) ||
content::IsImplSidePaintingEnabled();
+ prefs.image_color_profiles_enabled =
+ command_line.HasSwitch(switches::kEnableImageColorProfiles);
+
prefs.spatial_navigation_enabled = command_line.HasSwitch(
switches::kEnableSpatialNavigation);
- GetContentClient()->browser()->OverrideWebkitPrefs(this, url, &prefs);
- return prefs;
-}
-
-void RenderViewHostImpl::Navigate(const FrameMsg_Navigate_Params& params) {
- TRACE_EVENT0("renderer_host", "RenderViewHostImpl::Navigate");
- delegate_->GetFrameTree()->GetMainFrame()->Navigate(params);
-}
-
-void RenderViewHostImpl::NavigateToURL(const GURL& url) {
- delegate_->GetFrameTree()->GetMainFrame()->NavigateToURL(url);
-}
-
-void RenderViewHostImpl::SetNavigationsSuspended(
- bool suspend,
- const base::TimeTicks& proceed_time) {
- // This should only be called to toggle the state.
- DCHECK(navigations_suspended_ != suspend);
-
- navigations_suspended_ = suspend;
- if (!suspend && suspended_nav_params_) {
- // There's navigation message params waiting to be sent. Now that we're not
- // suspended anymore, resume navigation by sending them. If we were swapped
- // out, we should also stop filtering out the IPC messages now.
- SetState(STATE_DEFAULT);
-
- DCHECK(!proceed_time.is_null());
- suspended_nav_params_->browser_navigation_start = proceed_time;
- Send(new FrameMsg_Navigate(
- main_frame_routing_id_, *suspended_nav_params_.get()));
- suspended_nav_params_.reset();
- }
-}
-
-void RenderViewHostImpl::CancelSuspendedNavigations() {
- // Clear any state if a pending navigation is canceled or pre-empted.
- if (suspended_nav_params_)
- suspended_nav_params_.reset();
- navigations_suspended_ = false;
-}
-
-void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
- Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
-}
-
-void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
- // Ignore spurious swap out ack.
- if (!IsWaitingForUnloadACK())
- return;
- unload_event_monitor_timeout_->Stop();
- if (timed_out) {
- base::ProcessHandle process_handle = GetProcess()->GetHandle();
- int views = 0;
-
- // Count the number of active widget hosts for the process, which
- // is equivalent to views using the process as of this writing.
- scoped_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHost::GetRenderWidgetHosts());
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- if (widget->GetProcess()->GetID() == GetProcess()->GetID())
- ++views;
- }
-
- if (!RenderProcessHost::run_renderer_in_process() &&
- process_handle && views <= 1) {
- // The process can safely be terminated, only if WebContents sets
- // SuddenTerminationAllowed, which indicates that the timer has expired.
- // This is not the case if we load data URLs or about:blank. The reason
- // is that those have no network requests and this code is hit without
- // setting the unresponsiveness timer. This allows a corner case where a
- // navigation to a data URL will leave a process running, if the
- // beforeunload handler completes fine, but the unload handler hangs.
- // At this time, the complexity to solve this edge case is not worthwhile.
- if (SuddenTerminationAllowed()) {
- // We should kill the process, but for now, just log the data so we can
- // diagnose the kill rate and investigate if separate timer is needed.
- // http://crbug.com/104346.
-
- // Log a histogram point to help us diagnose how many of those kills
- // we have performed. 1 is the enum value for RendererType Normal for
- // the histogram.
- UMA_HISTOGRAM_PERCENTAGE(
- "BrowserRenderProcessHost.ChildKillsUnresponsive", 1);
- }
+ if (command_line.HasSwitch(switches::kV8CacheOptions)) {
+ const std::string v8_cache_options =
+ command_line.GetSwitchValueASCII(switches::kV8CacheOptions);
+ if (v8_cache_options == "parse") {
+ prefs.v8_cache_options = V8_CACHE_OPTIONS_PARSE;
+ } else if (v8_cache_options == "code") {
+ prefs.v8_cache_options = V8_CACHE_OPTIONS_CODE;
+ } else {
+ prefs.v8_cache_options = V8_CACHE_OPTIONS_OFF;
}
}
- switch (rvh_state_) {
- case STATE_WAITING_FOR_UNLOAD_ACK:
- SetState(STATE_WAITING_FOR_COMMIT);
- break;
- case STATE_PENDING_SWAP_OUT:
- SetState(STATE_SWAPPED_OUT);
- break;
- case STATE_PENDING_SHUTDOWN:
- DCHECK(!pending_shutdown_on_swap_out_.is_null());
- pending_shutdown_on_swap_out_.Run();
- break;
- default:
- NOTREACHED();
+ std::string streaming_experiment_group =
+ base::FieldTrialList::FindFullName("V8ScriptStreaming");
+ prefs.v8_script_streaming_enabled =
+ command_line.HasSwitch(switches::kEnableV8ScriptStreaming);
+ if (streaming_experiment_group == "Enabled") {
+ prefs.v8_script_streaming_enabled = true;
+ prefs.v8_script_streaming_mode = V8_SCRIPT_STREAMING_MODE_ALL;
+ } else if (streaming_experiment_group == "OnlyAsyncAndDefer") {
+ prefs.v8_script_streaming_enabled = true;
+ prefs.v8_script_streaming_mode =
+ V8_SCRIPT_STREAMING_MODE_ONLY_ASYNC_AND_DEFER;
+ } else if (streaming_experiment_group == "AllPlusBlockParserBlocking") {
+ prefs.v8_script_streaming_enabled = true;
+ prefs.v8_script_streaming_mode =
+ V8_SCRIPT_STREAMING_MODE_ALL_PLUS_BLOCK_PARSER_BLOCKING;
}
-}
-void RenderViewHostImpl::WasSwappedOut(
- const base::Closure& pending_delete_on_swap_out) {
- Send(new ViewMsg_WasSwappedOut(GetRoutingID()));
- if (rvh_state_ == STATE_WAITING_FOR_UNLOAD_ACK) {
- SetState(STATE_PENDING_SWAP_OUT);
- if (!instance_->active_view_count())
- SetPendingShutdown(pending_delete_on_swap_out);
- } else if (rvh_state_ == STATE_WAITING_FOR_COMMIT) {
- SetState(STATE_SWAPPED_OUT);
- } else if (rvh_state_ == STATE_DEFAULT) {
- // When the RenderView is not live, the RenderFrameHostManager will call
- // CommitPending directly, without calling SwapOut on the old RVH. This will
- // cause WasSwappedOut to be called directly on the live old RVH.
- DCHECK(!IsRenderViewLive());
- SetState(STATE_SWAPPED_OUT);
- } else {
- NOTREACHED();
- }
+ GetContentClient()->browser()->OverrideWebkitPrefs(this, url, &prefs);
+ return prefs;
}
-void RenderViewHostImpl::SetPendingShutdown(const base::Closure& on_swap_out) {
- pending_shutdown_on_swap_out_ = on_swap_out;
- SetState(STATE_PENDING_SHUTDOWN);
+void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
+ Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
}
void RenderViewHostImpl::ClosePage() {
- SetState(STATE_WAITING_FOR_CLOSE);
+ is_waiting_for_close_ack_ = true;
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
if (IsRenderViewLive()) {
@@ -639,44 +535,12 @@ void RenderViewHostImpl::ClosePage() {
void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
StopHangMonitorTimeout();
- is_waiting_for_beforeunload_ack_ = false;
+ is_waiting_for_close_ack_ = false;
sudden_termination_allowed_ = true;
delegate_->Close(this);
}
-bool RenderViewHostImpl::HasPendingCrossSiteRequest() {
- return CrossSiteRequestManager::GetInstance()->HasPendingCrossSiteRequest(
- GetProcess()->GetID(), GetRoutingID());
-}
-
-void RenderViewHostImpl::SetHasPendingCrossSiteRequest(
- bool has_pending_request) {
- CrossSiteRequestManager::GetInstance()->SetHasPendingCrossSiteRequest(
- GetProcess()->GetID(), GetRoutingID(), has_pending_request);
-}
-
-void RenderViewHostImpl::SetWebUIHandle(mojo::ScopedMessagePipeHandle handle) {
- // Never grant any bindings to browser plugin guests.
- if (GetProcess()->IsIsolatedGuest()) {
- NOTREACHED() << "Never grant bindings to a guest process.";
- return;
- }
-
- if ((enabled_bindings_ & BINDINGS_POLICY_WEB_UI) == 0) {
- NOTREACHED() << "You must grant bindings before setting the handle";
- return;
- }
-
- DCHECK(renderer_initialized_);
-
- WebUISetupPtr web_ui_setup;
- static_cast<RenderProcessHostImpl*>(GetProcess())->ConnectTo(
- kRendererService_WebUISetup, &web_ui_setup);
-
- web_ui_setup->SetWebUIHandle(GetRoutingID(), handle.Pass());
-}
-
#if defined(OS_ANDROID)
void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
float x,
@@ -700,6 +564,13 @@ void RenderViewHostImpl::DragTargetDragEnter(
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
+#if defined(OS_CHROMEOS)
+ // The externalfile:// scheme is used in Chrome OS to open external files in a
+ // browser tab.
+ if (drop_data.url.SchemeIs(content::kExternalFileScheme))
+ policy->GrantRequestURL(renderer_id, drop_data.url);
+#endif
+
// The URL could have been cobbled together from any highlighted text string,
// and can't be interpreted as a capability.
DropData filtered_data(drop_data);
@@ -710,7 +581,7 @@ void RenderViewHostImpl::DragTargetDragEnter(
// The filenames vector, on the other hand, does represent a capability to
// access the given files.
- fileapi::IsolatedContext::FileInfoSet files;
+ storage::IsolatedContext::FileInfoSet files;
for (std::vector<ui::FileInfo>::iterator iter(
filtered_data.filenames.begin());
iter != filtered_data.filenames.end();
@@ -743,8 +614,8 @@ void RenderViewHostImpl::DragTargetDragEnter(
policy->GrantReadFile(renderer_id, iter->path);
}
- fileapi::IsolatedContext* isolated_context =
- fileapi::IsolatedContext::GetInstance();
+ storage::IsolatedContext* isolated_context =
+ storage::IsolatedContext::GetInstance();
DCHECK(isolated_context);
std::string filesystem_id = isolated_context->RegisterDraggedFileSystem(
files);
@@ -754,12 +625,12 @@ void RenderViewHostImpl::DragTargetDragEnter(
}
filtered_data.filesystem_id = base::UTF8ToUTF16(filesystem_id);
- fileapi::FileSystemContext* file_system_context =
- BrowserContext::GetStoragePartition(
- GetProcess()->GetBrowserContext(),
- GetSiteInstance())->GetFileSystemContext();
+ storage::FileSystemContext* file_system_context =
+ BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
+ GetSiteInstance())
+ ->GetFileSystemContext();
for (size_t i = 0; i < filtered_data.file_system_files.size(); ++i) {
- fileapi::FileSystemURL file_system_url =
+ storage::FileSystemURL file_system_url =
file_system_context->CrackURL(filtered_data.file_system_files[i].url);
std::string register_name;
@@ -770,11 +641,10 @@ void RenderViewHostImpl::DragTargetDragEnter(
// Note: We are using the origin URL provided by the sender here. It may be
// different from the receiver's.
- filtered_data.file_system_files[i].url = GURL(
- fileapi::GetIsolatedFileSystemRootURIString(
- file_system_url.origin(),
- filesystem_id,
- std::string()).append(register_name));
+ filtered_data.file_system_files[i].url =
+ GURL(storage::GetIsolatedFileSystemRootURIString(
+ file_system_url.origin(), filesystem_id, std::string())
+ .append(register_name));
}
Send(new DragMsg_TargetDragEnter(GetRoutingID(), filtered_data, client_pt,
@@ -839,7 +709,8 @@ void RenderViewHostImpl::AllowBindings(int bindings_flags) {
static_cast<RenderProcessHostImpl*>(GetProcess());
// --single-process only has one renderer.
if (process->GetActiveViewCount() > 1 &&
- !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess))
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess))
return;
}
@@ -896,17 +767,27 @@ void RenderViewHostImpl::SetInitialFocus(bool reverse) {
}
void RenderViewHostImpl::FilesSelectedInChooser(
- const std::vector<ui::SelectedFileInfo>& files,
+ const std::vector<content::FileChooserFileInfo>& files,
FileChooserParams::Mode permissions) {
+ storage::FileSystemContext* const file_system_context =
+ BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
+ GetSiteInstance())
+ ->GetFileSystemContext();
// Grant the security access requested to the given files.
for (size_t i = 0; i < files.size(); ++i) {
- const ui::SelectedFileInfo& file = files[i];
+ const content::FileChooserFileInfo& file = files[i];
if (permissions == FileChooserParams::Save) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantCreateReadWriteFile(
- GetProcess()->GetID(), file.local_path);
+ GetProcess()->GetID(), file.file_path);
} else {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
- GetProcess()->GetID(), file.local_path);
+ GetProcess()->GetID(), file.file_path);
+ }
+ if (file.file_system_url.is_valid()) {
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFileSystem(
+ GetProcess()->GetID(),
+ file_system_context->CrackURL(file.file_system_url)
+ .mount_filesystem_id());
}
}
Send(new ViewMsg_RunFileChooserResponse(GetRoutingID(), files));
@@ -926,6 +807,20 @@ void RenderViewHostImpl::DirectoryEnumerationFinished(
files));
}
+void RenderViewHostImpl::SetIsLoading(bool is_loading) {
+ if (ResourceDispatcherHostImpl::Get()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(),
+ GetRoutingID(),
+ is_loading));
+ }
+ RenderWidgetHostImpl::SetIsLoading(is_loading);
+}
+
void RenderViewHostImpl::LoadStateChanged(
const GURL& url,
const net::LoadStateWithParam& load_state,
@@ -948,7 +843,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
// Filter out most IPC messages if this renderer is swapped out.
// We still want to handle certain ACKs to keep our state consistent.
- if (IsSwappedOut()) {
+ if (is_swapped_out_) {
if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
// If this is a synchronous message and we decided not to handle it,
// we must send an error reply, or else the renderer will be stuck
@@ -977,8 +872,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateState, OnUpdateState)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateInspectorSetting,
- OnUpdateInspectorSetting)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
@@ -986,8 +879,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
OnDidContentsPreferredSizeChange)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffset,
- OnDidChangeScrollOffset)
IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent,
OnRouteCloseEvent)
IPC_MESSAGE_HANDLER(ViewHostMsg_RouteMessageEvent, OnRouteMessageEvent)
@@ -998,14 +889,7 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidZoomURL, OnDidZoomURL)
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
- IPC_MESSAGE_HANDLER(ViewHostMsg_HidePopup, OnHidePopup)
-#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
- IPC_MESSAGE_HANDLER(AccessibilityHostMsg_Events, OnAccessibilityEvents)
- IPC_MESSAGE_HANDLER(AccessibilityHostMsg_LocationChanges,
- OnAccessibilityLocationChanges)
IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeTouched, OnFocusedNodeTouched)
// Have the super handle all other messages.
IPC_MESSAGE_UNHANDLED(
@@ -1047,6 +931,30 @@ void RenderViewHostImpl::Shutdown() {
RenderWidgetHostImpl::Shutdown();
}
+void RenderViewHostImpl::WasHidden() {
+ if (ResourceDispatcherHostImpl::Get()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostWasHidden,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID()));
+ }
+
+ RenderWidgetHostImpl::WasHidden();
+}
+
+void RenderViewHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
+ if (ResourceDispatcherHostImpl::Get()) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostWasShown,
+ base::Unretained(ResourceDispatcherHostImpl::Get()),
+ GetProcess()->GetID(), GetRoutingID()));
+ }
+
+ RenderWidgetHostImpl::WasShown(latency_info);
+}
+
bool RenderViewHostImpl::IsRenderView() const {
return true;
}
@@ -1079,7 +987,7 @@ void RenderViewHostImpl::OnShowView(int route_id,
WindowOpenDisposition disposition,
const gfx::Rect& initial_pos,
bool user_gesture) {
- if (IsRVHStateActive(rvh_state_)) {
+ if (is_active_) {
delegate_->ShowCreatedWindow(
route_id, disposition, initial_pos, user_gesture);
}
@@ -1088,13 +996,13 @@ void RenderViewHostImpl::OnShowView(int route_id,
void RenderViewHostImpl::OnShowWidget(int route_id,
const gfx::Rect& initial_pos) {
- if (IsRVHStateActive(rvh_state_))
+ if (is_active_)
delegate_->ShowCreatedWidget(route_id, initial_pos);
Send(new ViewMsg_Move_ACK(route_id));
}
void RenderViewHostImpl::OnShowFullscreenWidget(int route_id) {
- if (IsRVHStateActive(rvh_state_))
+ if (is_active_)
delegate_->ShowCreatedFullscreenWidget(route_id);
Send(new ViewMsg_Move_ACK(route_id));
}
@@ -1146,6 +1054,12 @@ void RenderViewHostImpl::OnRenderProcessGone(int status, int exit_code) {
}
void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
+ // If the following DCHECK fails, you have encountered a tricky edge-case that
+ // has evaded reproduction for a very long time. Please report what you were
+ // doing on http://crbug.com/407376, whether or not you can reproduce the
+ // failure.
+ DCHECK_EQ(page_id, page_id_);
+
// Without this check, the renderer can trick the browser into using
// filenames it can't access in a future session restore.
if (!CanAccessFilesOfPageState(state)) {
@@ -1156,21 +1070,15 @@ void RenderViewHostImpl::OnUpdateState(int32 page_id, const PageState& state) {
delegate_->UpdateState(this, page_id, state);
}
-void RenderViewHostImpl::OnUpdateTargetURL(int32 page_id, const GURL& url) {
- if (IsRVHStateActive(rvh_state_))
- delegate_->UpdateTargetURL(page_id, url);
+void RenderViewHostImpl::OnUpdateTargetURL(const GURL& url) {
+ if (is_active_)
+ delegate_->UpdateTargetURL(url);
// Send a notification back to the renderer that we are ready to
// receive more target urls.
Send(new ViewMsg_UpdateTargetURL_ACK(GetRoutingID()));
}
-void RenderViewHostImpl::OnUpdateInspectorSetting(
- const std::string& key, const std::string& value) {
- GetContentClient()->browser()->UpdateInspectorSetting(
- this, key, value);
-}
-
void RenderViewHostImpl::OnClose() {
// If the renderer is telling us to close, it has already run the unload
// events, and we can take the fast path.
@@ -1178,7 +1086,7 @@ void RenderViewHostImpl::OnClose() {
}
void RenderViewHostImpl::OnRequestMove(const gfx::Rect& pos) {
- if (IsRVHStateActive(rvh_state_))
+ if (is_active_)
delegate_->RequestMove(pos);
Send(new ViewMsg_Move_ACK(GetRoutingID()));
}
@@ -1190,8 +1098,9 @@ void RenderViewHostImpl::OnDocumentAvailableInMainFrame(
if (!uses_temporary_zoom_level)
return;
- HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
- HostZoomMap::GetForBrowserContext(GetProcess()->GetBrowserContext()));
+ HostZoomMapImpl* host_zoom_map =
+ static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
+ GetProcess()->GetBrowserContext()));
host_zoom_map->SetTemporaryZoomLevel(GetProcess()->GetID(),
GetRoutingID(),
host_zoom_map->GetDefaultZoomLevel());
@@ -1214,11 +1123,6 @@ void RenderViewHostImpl::OnRenderAutoResized(const gfx::Size& new_size) {
delegate_->ResizeDueToAutoResize(new_size);
}
-void RenderViewHostImpl::OnDidChangeScrollOffset() {
- if (view_)
- view_->ScrollOffsetChanged();
-}
-
void RenderViewHostImpl::OnRouteCloseEvent() {
// Have the delegate route this to the active RenderViewHost.
delegate_->RouteCloseEvent(this);
@@ -1266,13 +1170,13 @@ void RenderViewHostImpl::OnStartDragging(
filtered_data.filenames.push_back(*it);
}
- fileapi::FileSystemContext* file_system_context =
- BrowserContext::GetStoragePartition(
- GetProcess()->GetBrowserContext(),
- GetSiteInstance())->GetFileSystemContext();
+ storage::FileSystemContext* file_system_context =
+ BrowserContext::GetStoragePartition(GetProcess()->GetBrowserContext(),
+ GetSiteInstance())
+ ->GetFileSystemContext();
filtered_data.file_system_files.clear();
for (size_t i = 0; i < drop_data.file_system_files.size(); ++i) {
- fileapi::FileSystemURL file_system_url =
+ storage::FileSystemURL file_system_url =
file_system_context->CrackURL(drop_data.file_system_files[i].url);
if (policy->CanReadFileSystemFile(GetProcess()->GetID(), file_system_url))
filtered_data.file_system_files.push_back(drop_data.file_system_files[i]);
@@ -1332,8 +1236,7 @@ void RenderViewHostImpl::OnClosePageACK() {
}
void RenderViewHostImpl::NotifyRendererUnresponsive() {
- delegate_->RendererUnresponsive(
- this, is_waiting_for_beforeunload_ack_, IsWaitingForUnloadACK());
+ delegate_->RendererUnresponsive(this);
}
void RenderViewHostImpl::NotifyRendererResponsive() {
@@ -1407,36 +1310,6 @@ void RenderViewHostImpl::ForwardKeyboardEvent(
RenderWidgetHostImpl::ForwardKeyboardEvent(key_event);
}
-#if defined(OS_ANDROID)
-void RenderViewHostImpl::DidSelectPopupMenuItems(
- const std::vector<int>& selected_indices) {
- Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), false,
- selected_indices));
-}
-
-void RenderViewHostImpl::DidCancelPopupMenu() {
- Send(new ViewMsg_SelectPopupMenuItems(GetRoutingID(), true,
- std::vector<int>()));
-}
-#endif
-
-#if defined(OS_MACOSX)
-void RenderViewHostImpl::DidSelectPopupMenuItem(int selected_index) {
- Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), selected_index));
-}
-
-void RenderViewHostImpl::DidCancelPopupMenu() {
- Send(new ViewMsg_SelectPopupMenuItem(GetRoutingID(), -1));
-}
-#endif
-
-bool RenderViewHostImpl::IsWaitingForUnloadACK() const {
- return rvh_state_ == STATE_WAITING_FOR_UNLOAD_ACK ||
- rvh_state_ == STATE_WAITING_FOR_CLOSE ||
- rvh_state_ == STATE_PENDING_SHUTDOWN ||
- rvh_state_ == STATE_PENDING_SWAP_OUT;
-}
-
void RenderViewHostImpl::OnTextSurroundingSelectionResponse(
const base::string16& content,
size_t start_offset,
@@ -1453,28 +1326,31 @@ void RenderViewHostImpl::ExitFullscreen() {
}
WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
- return delegate_->GetWebkitPrefs();
-}
-
-void RenderViewHostImpl::DisownOpener() {
- // This should only be called when swapped out.
- DCHECK(IsSwappedOut());
-
- Send(new ViewMsg_DisownOpener(GetRoutingID()));
-}
-
-void RenderViewHostImpl::SetAccessibilityCallbackForTesting(
- const base::Callback<void(ui::AXEvent, int)>& callback) {
- accessibility_testing_callback_ = callback;
+ if (!web_preferences_.get()) {
+ OnWebkitPreferencesChanged();
+ }
+ return *web_preferences_;
}
void RenderViewHostImpl::UpdateWebkitPreferences(const WebPreferences& prefs) {
+ web_preferences_.reset(new WebPreferences(prefs));
Send(new ViewMsg_UpdateWebPreferences(GetRoutingID(), prefs));
}
+void RenderViewHostImpl::OnWebkitPreferencesChanged() {
+ // This is defensive code to avoid infinite loops due to code run inside
+ // UpdateWebkitPreferences() accidentally updating more preferences and thus
+ // calling back into this code. See crbug.com/398751 for one past example.
+ if (updating_web_preferences_)
+ return;
+ updating_web_preferences_ = true;
+ UpdateWebkitPreferences(delegate_->ComputeWebkitPrefs());
+ updating_web_preferences_ = false;
+}
+
void RenderViewHostImpl::GetAudioOutputControllers(
const GetAudioOutputControllersCallback& callback) const {
- AudioRendererHost* audio_host =
+ scoped_refptr<AudioRendererHost> audio_host =
static_cast<RenderProcessHostImpl*>(GetProcess())->audio_renderer_host();
audio_host->GetOutputControllers(GetRoutingID(), callback);
}
@@ -1509,6 +1385,8 @@ void RenderViewHostImpl::EnableAutoResize(const gfx::Size& min_size,
void RenderViewHostImpl::DisableAutoResize(const gfx::Size& new_size) {
SetShouldAutoResize(false);
Send(new ViewMsg_DisableAutoResize(GetRoutingID(), new_size));
+ if (!new_size.IsEmpty())
+ GetView()->SetSize(new_size);
}
void RenderViewHostImpl::CopyImageAt(int x, int y) {
@@ -1533,70 +1411,11 @@ void RenderViewHostImpl::NotifyMoveOrResizeStarted() {
Send(new ViewMsg_MoveOrResizeStarted(GetRoutingID()));
}
-void RenderViewHostImpl::OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params) {
- if ((accessibility_mode() != AccessibilityModeOff) && view_ &&
- IsRVHStateActive(rvh_state_)) {
- if (accessibility_mode() & AccessibilityModeFlagPlatform) {
- view_->CreateBrowserAccessibilityManagerIfNeeded();
- BrowserAccessibilityManager* manager =
- view_->GetBrowserAccessibilityManager();
- if (manager)
- manager->OnAccessibilityEvents(params);
- }
-
- std::vector<AXEventNotificationDetails> details;
- for (unsigned int i = 0; i < params.size(); ++i) {
- const AccessibilityHostMsg_EventParams& param = params[i];
- AXEventNotificationDetails detail(param.update.nodes,
- param.event_type,
- param.id,
- GetProcess()->GetID(),
- GetRoutingID());
- details.push_back(detail);
- }
-
- delegate_->AccessibilityEventReceived(details);
- }
-
- // Always send an ACK or the renderer can be in a bad state.
- Send(new AccessibilityMsg_Events_ACK(GetRoutingID()));
-
- // The rest of this code is just for testing; bail out if we're not
- // in that mode.
- if (accessibility_testing_callback_.is_null())
- return;
-
- for (unsigned i = 0; i < params.size(); i++) {
- const AccessibilityHostMsg_EventParams& param = params[i];
- if (static_cast<int>(param.event_type) < 0)
- continue;
- if (!ax_tree_)
- ax_tree_.reset(new ui::AXTree(param.update));
- else
- CHECK(ax_tree_->Unserialize(param.update)) << ax_tree_->error();
- accessibility_testing_callback_.Run(param.event_type, param.id);
- }
-}
-
-void RenderViewHostImpl::OnAccessibilityLocationChanges(
- const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
- if (view_ && IsRVHStateActive(rvh_state_)) {
- if (accessibility_mode() & AccessibilityModeFlagPlatform) {
- view_->CreateBrowserAccessibilityManagerIfNeeded();
- BrowserAccessibilityManager* manager =
- view_->GetBrowserAccessibilityManager();
- if (manager)
- manager->OnLocationChanges(params);
- }
- // TODO(aboxhall): send location change events to web contents observers too
- }
-}
-
void RenderViewHostImpl::OnDidZoomURL(double zoom_level,
const GURL& url) {
- HostZoomMapImpl* host_zoom_map = static_cast<HostZoomMapImpl*>(
- HostZoomMap::GetForBrowserContext(GetProcess()->GetBrowserContext()));
+ HostZoomMapImpl* host_zoom_map =
+ static_cast<HostZoomMapImpl*>(HostZoomMap::GetDefaultForBrowserContext(
+ GetProcess()->GetBrowserContext()));
host_zoom_map->SetZoomLevelForView(GetProcess()->GetID(),
GetRoutingID(),
@@ -1619,49 +1438,6 @@ void RenderViewHostImpl::OnFocusedNodeTouched(bool editable) {
#endif
}
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
-void RenderViewHostImpl::OnShowPopup(
- const ViewHostMsg_ShowPopup_Params& params) {
- RenderViewHostDelegateView* view = delegate_->GetDelegateView();
- if (view) {
- view->ShowPopupMenu(params.bounds,
- params.item_height,
- params.item_font_size,
- params.selected_item,
- params.popup_items,
- params.right_aligned,
- params.allow_multiple_selection);
- }
-}
-
-void RenderViewHostImpl::OnHidePopup() {
- RenderViewHostDelegateView* view = delegate_->GetDelegateView();
- if (view)
- view->HidePopupMenu();
-}
-#endif
-
-void RenderViewHostImpl::SetState(RenderViewHostImplState rvh_state) {
- // We update the number of RenderViews in a SiteInstance when the
- // swapped out status of this RenderView gets flipped to/from live.
- if (!IsRVHStateActive(rvh_state_) && IsRVHStateActive(rvh_state))
- instance_->increment_active_view_count();
- else if (IsRVHStateActive(rvh_state_) && !IsRVHStateActive(rvh_state))
- instance_->decrement_active_view_count();
-
- // Whenever we change the RVH state to and from live or swapped out state, we
- // should not be waiting for beforeunload or unload acks. We clear them here
- // to be safe, since they can cause navigations to be ignored in OnNavigate.
- if (rvh_state == STATE_DEFAULT ||
- rvh_state == STATE_SWAPPED_OUT ||
- rvh_state_ == STATE_DEFAULT ||
- rvh_state_ == STATE_SWAPPED_OUT) {
- is_waiting_for_beforeunload_ack_ = false;
- }
- rvh_state_ = rvh_state;
-
-}
-
bool RenderViewHostImpl::CanAccessFilesOfPageState(
const PageState& state) const {
ChildProcessSecurityPolicyImpl* policy =
diff --git a/chromium/content/browser/renderer_host/render_view_host_impl.h b/chromium/content/browser/renderer_host/render_view_host_impl.h
index 5f7344f7f5b..c6fdf055b0d 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -25,17 +25,13 @@
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/accessibility/ax_node_data.h"
#include "ui/base/window_open_disposition.h"
class SkBitmap;
class FrameMsg_Navigate;
-struct AccessibilityHostMsg_EventParams;
-struct AccessibilityHostMsg_LocationChangeParams;
+struct FrameMsg_Navigate_Params;
struct MediaPlayerAction;
struct ViewHostMsg_CreateWindow_Params;
-struct ViewHostMsg_ShowPopup_Params;
-struct FrameMsg_Navigate_Params;
struct ViewMsg_PostMessage_Params;
namespace base {
@@ -48,7 +44,6 @@ class Range;
namespace ui {
class AXTree;
-struct SelectedFileInfo;
}
namespace content {
@@ -60,7 +55,7 @@ class RenderWidgetHostDelegate;
class SessionStorageNamespace;
class SessionStorageNamespaceImpl;
class TestRenderViewHost;
-class TimeoutMonitor;
+struct FileChooserFileInfo;
struct FileChooserParams;
#if defined(COMPILER_MSVC)
@@ -93,39 +88,6 @@ class CONTENT_EXPORT RenderViewHostImpl
: public RenderViewHost,
public RenderWidgetHostImpl {
public:
- // Keeps track of the state of the RenderViewHostImpl, particularly with
- // respect to swap out.
- enum RenderViewHostImplState {
- // The standard state for a RVH handling the communication with a
- // RenderView.
- STATE_DEFAULT = 0,
- // The RVH has sent the SwapOut request to the renderer, but has not
- // received the SwapOutACK yet. The new page has not been committed yet
- // either.
- STATE_WAITING_FOR_UNLOAD_ACK,
- // The RVH received the SwapOutACK from the RenderView, but the new page has
- // not been committed yet.
- STATE_WAITING_FOR_COMMIT,
- // The RVH is waiting for the CloseACK from the RenderView.
- STATE_WAITING_FOR_CLOSE,
- // The RVH has not received the SwapOutACK yet, but the new page has
- // committed in a different RVH. The number of active views of the RVH
- // SiteInstanceImpl is not zero. Upon reception of the SwapOutACK, the RVH
- // will be swapped out.
- STATE_PENDING_SWAP_OUT,
- // The RVH has not received the SwapOutACK yet, but the new page has
- // committed in a different RVH. The number of active views of the RVH
- // SiteInstanceImpl is zero. Upon reception of the SwapOutACK, the RVH will
- // be shutdown.
- STATE_PENDING_SHUTDOWN,
- // The RVH is swapped out, and it is being used as a placeholder to allow
- // for cross-process communication.
- STATE_SWAPPED_OUT,
- };
- // Helper function to determine whether the RVH state should contribute to the
- // number of active views of a SiteInstance or not.
- static bool IsRVHStateActive(RenderViewHostImplState rvh_state);
-
// Convenience function, just like RenderViewHost::FromID.
static RenderViewHostImpl* FromID(int render_process_id, int render_view_id);
@@ -140,83 +102,82 @@ class CONTENT_EXPORT RenderViewHostImpl
// spec) space. This is useful when restoring contentses, but most callers
// should pass in NULL which will cause a new SessionStorageNamespace to be
// created.
- RenderViewHostImpl(
- SiteInstance* instance,
- RenderViewHostDelegate* delegate,
- RenderWidgetHostDelegate* widget_delegate,
- int routing_id,
- int main_frame_routing_id,
- bool swapped_out,
- bool hidden);
- virtual ~RenderViewHostImpl();
+ RenderViewHostImpl(SiteInstance* instance,
+ RenderViewHostDelegate* delegate,
+ RenderWidgetHostDelegate* widget_delegate,
+ int routing_id,
+ int main_frame_routing_id,
+ bool swapped_out,
+ bool hidden,
+ bool has_initialized_audio_host);
+ ~RenderViewHostImpl() override;
// RenderViewHost implementation.
- virtual RenderFrameHost* GetMainFrame() OVERRIDE;
- virtual void AllowBindings(int binding_flags) OVERRIDE;
- virtual void ClearFocusedElement() OVERRIDE;
- virtual bool IsFocusedElementEditable() OVERRIDE;
- virtual void ClosePage() OVERRIDE;
- virtual void CopyImageAt(int x, int y) OVERRIDE;
- virtual void SaveImageAt(int x, int y) OVERRIDE;
- virtual void DirectoryEnumerationFinished(
+ RenderFrameHost* GetMainFrame() override;
+ void AllowBindings(int binding_flags) override;
+ void ClearFocusedElement() override;
+ bool IsFocusedElementEditable() override;
+ void ClosePage() override;
+ void CopyImageAt(int x, int y) override;
+ void SaveImageAt(int x, int y) override;
+ void DirectoryEnumerationFinished(
int request_id,
- const std::vector<base::FilePath>& files) OVERRIDE;
- virtual void DisableScrollbarsForThreshold(const gfx::Size& size) OVERRIDE;
- virtual void DragSourceEndedAt(
- int client_x, int client_y, int screen_x, int screen_y,
- blink::WebDragOperation operation) OVERRIDE;
- virtual void DragSourceSystemDragEnded() OVERRIDE;
- virtual void DragTargetDragEnter(
- const DropData& drop_data,
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- blink::WebDragOperationsMask operations_allowed,
- int key_modifiers) OVERRIDE;
- virtual void DragTargetDragOver(
- const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- blink::WebDragOperationsMask operations_allowed,
- int key_modifiers) OVERRIDE;
- virtual void DragTargetDragLeave() OVERRIDE;
- virtual void DragTargetDrop(const gfx::Point& client_pt,
- const gfx::Point& screen_pt,
- int key_modifiers) OVERRIDE;
- virtual void EnableAutoResize(const gfx::Size& min_size,
- const gfx::Size& max_size) OVERRIDE;
- virtual void DisableAutoResize(const gfx::Size& new_size) OVERRIDE;
- virtual void EnablePreferredSizeMode() OVERRIDE;
- virtual void ExecuteMediaPlayerActionAtLocation(
+ const std::vector<base::FilePath>& files) override;
+ void DisableScrollbarsForThreshold(const gfx::Size& size) override;
+ void DragSourceEndedAt(int client_x,
+ int client_y,
+ int screen_x,
+ int screen_y,
+ blink::WebDragOperation operation) override;
+ void DragSourceSystemDragEnded() override;
+ void DragTargetDragEnter(const DropData& drop_data,
+ const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperationsMask operations_allowed,
+ int key_modifiers) override;
+ void DragTargetDragOver(const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ blink::WebDragOperationsMask operations_allowed,
+ int key_modifiers) override;
+ void DragTargetDragLeave() override;
+ void DragTargetDrop(const gfx::Point& client_pt,
+ const gfx::Point& screen_pt,
+ int key_modifiers) override;
+ void EnableAutoResize(const gfx::Size& min_size,
+ const gfx::Size& max_size) override;
+ void DisableAutoResize(const gfx::Size& new_size) override;
+ void EnablePreferredSizeMode() override;
+ void ExecuteMediaPlayerActionAtLocation(
const gfx::Point& location,
- const blink::WebMediaPlayerAction& action) OVERRIDE;
- virtual void ExecutePluginActionAtLocation(
+ const blink::WebMediaPlayerAction& action) override;
+ void ExecutePluginActionAtLocation(
const gfx::Point& location,
- const blink::WebPluginAction& action) OVERRIDE;
- virtual void ExitFullscreen() OVERRIDE;
- virtual void FilesSelectedInChooser(
- const std::vector<ui::SelectedFileInfo>& files,
- FileChooserParams::Mode permissions) OVERRIDE;
- virtual RenderViewHostDelegate* GetDelegate() const OVERRIDE;
- virtual int GetEnabledBindings() const OVERRIDE;
- virtual SiteInstance* GetSiteInstance() const OVERRIDE;
- virtual bool IsRenderViewLive() const OVERRIDE;
- virtual void NotifyMoveOrResizeStarted() OVERRIDE;
- virtual void SetWebUIProperty(const std::string& name,
- const std::string& value) OVERRIDE;
- virtual void Zoom(PageZoom zoom) OVERRIDE;
- virtual void SyncRendererPrefs() OVERRIDE;
- virtual WebPreferences GetWebkitPreferences() OVERRIDE;
- virtual void UpdateWebkitPreferences(
- const WebPreferences& prefs) OVERRIDE;
- virtual void GetAudioOutputControllers(
- const GetAudioOutputControllersCallback& callback) const OVERRIDE;
- virtual void SetWebUIHandle(mojo::ScopedMessagePipeHandle handle) OVERRIDE;
- virtual void SelectWordAroundCaret() OVERRIDE;
+ const blink::WebPluginAction& action) override;
+ void ExitFullscreen() override;
+ void FilesSelectedInChooser(
+ const std::vector<content::FileChooserFileInfo>& files,
+ FileChooserParams::Mode permissions) override;
+ RenderViewHostDelegate* GetDelegate() const override;
+ int GetEnabledBindings() const override;
+ SiteInstanceImpl* GetSiteInstance() const override;
+ bool IsRenderViewLive() const override;
+ void NotifyMoveOrResizeStarted() override;
+ void SetWebUIProperty(const std::string& name,
+ const std::string& value) override;
+ void Zoom(PageZoom zoom) override;
+ void SyncRendererPrefs() override;
+ WebPreferences GetWebkitPreferences() override;
+ void UpdateWebkitPreferences(const WebPreferences& prefs) override;
+ void OnWebkitPreferencesChanged() override;
+ void GetAudioOutputControllers(
+ const GetAudioOutputControllersCallback& callback) const override;
+ void SelectWordAroundCaret() override;
#if defined(OS_ANDROID)
virtual void ActivateNearestFindResult(int request_id,
float x,
- float y) OVERRIDE;
- virtual void RequestFindMatchRects(int current_version) OVERRIDE;
+ float y) override;
+ virtual void RequestFindMatchRects(int current_version) override;
#endif
void set_delegate(RenderViewHostDelegate* d) {
@@ -245,54 +206,22 @@ class CONTENT_EXPORT RenderViewHostImpl
}
// Returns the content specific prefs for this RenderViewHost.
- WebPreferences GetWebkitPrefs(const GURL& url);
+ WebPreferences ComputeWebkitPrefs(const GURL& url);
+
+ // Tracks whether this RenderViewHost is in an active state (rather than
+ // pending swap out, pending deletion, or swapped out), according to its main
+ // frame RenderFrameHost.
+ bool is_active() const { return is_active_; }
+ void set_is_active(bool is_active) { is_active_ = is_active; }
+
+ // Tracks whether this RenderViewHost is swapped out, according to its main
+ // frame RenderFrameHost.
+ void set_is_swapped_out(bool is_swapped_out) {
+ is_swapped_out_ = is_swapped_out;
+ }
- // Sends the given navigation message. Use this rather than sending it
- // yourself since this does the internal bookkeeping described below. This
- // function takes ownership of the provided message pointer.
- //
- // If a cross-site request is in progress, we may be suspended while waiting
- // for the onbeforeunload handler, so this function might buffer the message
- // rather than sending it.
- // TODO(nasko): Remove this method once all callers are converted to use
- // RenderFrameHostImpl.
- void Navigate(const FrameMsg_Navigate_Params& message);
-
- // Load the specified URL, this is a shortcut for Navigate().
- // TODO(nasko): Remove this method once all callers are converted to use
- // RenderFrameHostImpl.
- void NavigateToURL(const GURL& url);
-
- // Returns whether navigation messages are currently suspended for this
- // RenderViewHost. Only true during a cross-site navigation, while waiting
- // for the onbeforeunload handler.
- bool are_navigations_suspended() const { return navigations_suspended_; }
-
- // Suspends (or unsuspends) any navigation messages from being sent from this
- // RenderViewHost. This is called when a pending RenderViewHost is created
- // for a cross-site navigation, because we must suspend any navigations until
- // we hear back from the old renderer's onbeforeunload handler. Note that it
- // is important that only one navigation event happen after calling this
- // method with |suspend| equal to true. If |suspend| is false and there is
- // a suspended_nav_message_, this will send the message. This function
- // should only be called to toggle the state; callers should check
- // are_navigations_suspended() first. If |suspend| is false, the time that the
- // user decided the navigation should proceed should be passed as
- // |proceed_time|.
- void SetNavigationsSuspended(bool suspend,
- const base::TimeTicks& proceed_time);
-
- // Clears any suspended navigation state after a cross-site navigation is
- // canceled or suspended. This is important if we later return to this
- // RenderViewHost.
- void CancelSuspendedNavigations();
-
- // Whether this RenderViewHost has been swapped out to be displayed by a
- // different process.
- bool IsSwappedOut() const { return rvh_state_ == STATE_SWAPPED_OUT; }
-
- // The current state of this RVH.
- RenderViewHostImplState rvh_state() const { return rvh_state_; }
+ // TODO(creis): Remove as part of http://crbug.com/418265.
+ bool is_waiting_for_close_ack() const { return is_waiting_for_close_ack_; }
// Tells the renderer that this RenderView will soon be swapped out, and thus
// not to create any new modal dialogs until it happens. This must be done
@@ -300,36 +229,11 @@ class CONTENT_EXPORT RenderViewHostImpl
// longer on the stack when we attempt to swap it out.
void SuppressDialogsUntilSwapOut();
- // Called when either the SwapOut request has been acknowledged or has timed
- // out.
- void OnSwappedOut(bool timed_out);
-
- // Called when the RenderFrameHostManager has swapped in a new
- // RenderFrameHost. Should |this| RVH switch to the pending shutdown state,
- // |pending_delete_on_swap_out| will be executed upon reception of the
- // SwapOutACK, or when the unload timer times out.
- void WasSwappedOut(const base::Closure& pending_delete_on_swap_out);
-
- // Set |this| as pending shutdown. |on_swap_out| will be called
- // when the SwapOutACK is received, or when the unload timer times out.
- void SetPendingShutdown(const base::Closure& on_swap_out);
-
// Close the page ignoring whether it has unload events registers.
// This is called after the beforeunload and unload events have fired
// and the user has agreed to continue with closing the page.
void ClosePageIgnoringUnloadEvents();
- // Returns whether this RenderViewHost has an outstanding cross-site request.
- // Cleared when we hear the response and start to swap out the old
- // RenderViewHost, or if we hear a commit here without a network request.
- bool HasPendingCrossSiteRequest();
-
- // Sets whether this RenderViewHost has an outstanding cross-site request,
- // for which another renderer will need to run an onunload event handler.
- // This is called before the first navigation event for this RenderViewHost,
- // and cleared when we hear the response or commit.
- void SetHasPendingCrossSiteRequest(bool has_pending_request);
-
// Tells the renderer view to focus the first (last if reverse is true) node.
void SetInitialFocus(bool reverse);
@@ -357,19 +261,20 @@ class CONTENT_EXPORT RenderViewHostImpl
}
// RenderWidgetHost public overrides.
- virtual void Init() OVERRIDE;
- virtual void Shutdown() OVERRIDE;
- virtual bool IsRenderView() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void GotFocus() OVERRIDE;
- virtual void LostCapture() OVERRIDE;
- virtual void LostMouseLock() OVERRIDE;
- virtual void ForwardMouseEvent(
- const blink::WebMouseEvent& mouse_event) OVERRIDE;
- virtual void OnPointerEventActivate() OVERRIDE;
- virtual void ForwardKeyboardEvent(
- const NativeWebKeyboardEvent& key_event) OVERRIDE;
- virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
+ void Init() override;
+ void Shutdown() override;
+ void WasHidden() override;
+ void WasShown(const ui::LatencyInfo& latency_info) override;
+ bool IsRenderView() const override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void GotFocus() override;
+ void LostCapture() override;
+ void LostMouseLock() override;
+ void SetIsLoading(bool is_loading) override;
+ void ForwardMouseEvent(const blink::WebMouseEvent& mouse_event) override;
+ void OnPointerEventActivate() override;
+ void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event) override;
+ gfx::Rect GetRootWindowResizerRect() const override;
// Creates a new RenderView with the given route id.
void CreateNewWindow(
@@ -385,61 +290,16 @@ class CONTENT_EXPORT RenderViewHostImpl
// Creates a full screen RenderWidget.
void CreateNewFullscreenWidget(int route_id);
-#if defined(OS_MACOSX)
- // Select popup menu related methods (for external popup menus).
- void DidSelectPopupMenuItem(int selected_index);
- void DidCancelPopupMenu();
-#endif
-
#if defined(ENABLE_BROWSER_CDMS)
MediaWebContentsObserver* media_web_contents_observer() {
return media_web_contents_observer_.get();
}
#endif
-#if defined(OS_ANDROID)
- void DidSelectPopupMenuItems(const std::vector<int>& selected_indices);
- void DidCancelPopupMenu();
-#endif
-
int main_frame_routing_id() const {
return main_frame_routing_id_;
}
- // Set the opener to null in the renderer process.
- void DisownOpener();
-
- // Turn on accessibility testing. The given callback will be run
- // every time an accessibility notification is received from the
- // renderer process, and the accessibility tree it sent can be
- // retrieved using accessibility_tree_for_testing().
- void SetAccessibilityCallbackForTesting(
- const base::Callback<void(ui::AXEvent, int)>& callback);
-
- // Only valid if SetAccessibilityCallbackForTesting was called and
- // the callback was run at least once. Returns a snapshot of the
- // accessibility tree received from the renderer as of the last time
- // an accessibility notification was received.
- const ui::AXTree& ax_tree_for_testing() {
- CHECK(ax_tree_.get());
- return *ax_tree_.get();
- }
-
- // Set accessibility callbacks.
- void SetAccessibilityLayoutCompleteCallbackForTesting(
- const base::Closure& callback);
- void SetAccessibilityLoadCompleteCallbackForTesting(
- const base::Closure& callback);
- void SetAccessibilityOtherCallbackForTesting(
- const base::Closure& callback);
-
- bool is_waiting_for_beforeunload_ack() {
- return is_waiting_for_beforeunload_ack_;
- }
-
- // Whether the RVH is waiting for the unload ack from the renderer.
- bool IsWaitingForUnloadACK() const;
-
void OnTextSurroundingSelectionResponse(const base::string16& content,
size_t start_offset,
size_t end_offset);
@@ -470,15 +330,15 @@ class CONTENT_EXPORT RenderViewHostImpl
protected:
// RenderWidgetHost protected overrides.
- virtual void OnUserGesture() OVERRIDE;
- virtual void NotifyRendererUnresponsive() OVERRIDE;
- virtual void NotifyRendererResponsive() OVERRIDE;
- virtual void OnRenderAutoResized(const gfx::Size& size) OVERRIDE;
- virtual void RequestToLockMouse(bool user_gesture,
- bool last_unlocked_by_target) OVERRIDE;
- virtual bool IsFullscreen() const OVERRIDE;
- virtual void OnFocus() OVERRIDE;
- virtual void OnBlur() OVERRIDE;
+ void OnUserGesture() override;
+ void NotifyRendererUnresponsive() override;
+ void NotifyRendererResponsive() override;
+ void OnRenderAutoResized(const gfx::Size& size) override;
+ void RequestToLockMouse(bool user_gesture,
+ bool last_unlocked_by_target) override;
+ bool IsFullscreen() const override;
+ void OnFocus() override;
+ void OnBlur() override;
// IPC message handlers.
void OnShowView(int route_id,
@@ -491,13 +351,12 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnRenderViewReady();
void OnRenderProcessGone(int status, int error_code);
void OnUpdateState(int32 page_id, const PageState& state);
- void OnUpdateTargetURL(int32 page_id, const GURL& url);
+ void OnUpdateTargetURL(const GURL& url);
void OnClose();
void OnRequestMove(const gfx::Rect& pos);
void OnDocumentAvailableInMainFrame(bool uses_temporary_zoom_level);
void OnToggleFullscreen(bool enter_fullscreen);
void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
- void OnDidChangeScrollOffset();
void OnPasteFromSelectionClipboard();
void OnRouteCloseEvent();
void OnRouteMessageEvent(const ViewMsg_PostMessage_Params& params);
@@ -510,22 +369,11 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnTargetDropACK();
void OnTakeFocus(bool reverse);
void OnFocusedNodeChanged(bool is_editable_node);
- void OnUpdateInspectorSetting(const std::string& key,
- const std::string& value);
void OnClosePageACK();
- void OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params);
- void OnAccessibilityLocationChanges(
- const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
void OnDidZoomURL(double zoom_level, const GURL& url);
void OnRunFileChooser(const FileChooserParams& params);
void OnFocusedNodeTouched(bool editable);
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
- void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
- void OnHidePopup();
-#endif
-
private:
// TODO(nasko): Temporarily friend RenderFrameHostImpl, so we don't duplicate
// utility functions and state needed in both classes, while we move frame
@@ -538,11 +386,7 @@ class CONTENT_EXPORT RenderViewHostImpl
// TODO(creis): Move to a private namespace on RenderFrameHostImpl.
// Delay to wait on closing the WebContents for a beforeunload/unload handler
// to fire.
- static const int kUnloadTimeoutMS;
-
- // Updates the state of this RenderViewHost and clears any waiting state
- // that is no longer relevant.
- void SetState(RenderViewHostImplState rvh_state);
+ static const int64 kUnloadTimeoutMS;
bool CanAccessFilesOfPageState(const PageState& state) const;
@@ -553,7 +397,7 @@ class CONTENT_EXPORT RenderViewHostImpl
RenderViewHostDelegate* delegate_;
// The SiteInstance associated with this RenderViewHost. All pages drawn
- // in this RenderViewHost are part of this SiteInstance. Should not change
+ // in this RenderViewHost are part of this SiteInstance. Cannot change
// over time.
scoped_refptr<SiteInstanceImpl> instance_;
@@ -565,23 +409,21 @@ class CONTENT_EXPORT RenderViewHostImpl
// See BindingsPolicy for details.
int enabled_bindings_;
- // Whether we should buffer outgoing Navigate messages rather than sending
- // them. This will be true when a RenderViewHost is created for a cross-site
- // request, until we hear back from the onbeforeunload handler of the old
- // RenderViewHost.
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- bool navigations_suspended_;
+ // The most recent page ID we've heard from the renderer process. This is
+ // used as context when other session history related IPCs arrive.
+ // TODO(creis): Allocate this in WebContents/NavigationController instead.
+ int32 page_id_;
- // We only buffer the params for a suspended navigation while we have a
- // pending RVH for a WebContentsImpl. There will only ever be one suspended
- // navigation, because WebContentsImpl will destroy the pending RVH and create
- // a new one if a second navigation occurs.
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- scoped_ptr<FrameMsg_Navigate_Params> suspended_nav_params_;
+ // Tracks whether this RenderViewHost is in an active state. False if the
+ // main frame is pending swap out, pending deletion, or swapped out, because
+ // it is not visible to the user in any of these cases.
+ bool is_active_;
- // The current state of this RVH.
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- RenderViewHostImplState rvh_state_;
+ // Tracks whether the main frame RenderFrameHost is swapped out. Unlike
+ // is_active_, this is false when the frame is pending swap out or deletion.
+ // TODO(creis): Remove this when we no longer use swappedout://.
+ // See http://crbug.com/357747.
+ bool is_swapped_out_;
// Routing ID for the main frame's RenderFrameHost.
int main_frame_routing_id_;
@@ -592,28 +434,10 @@ class CONTENT_EXPORT RenderViewHostImpl
// This will hold the routing id of the RenderView that opened us.
int run_modal_opener_id_;
- // Set to true when there is a pending ViewMsg_ShouldClose message. This
- // ensures we don't spam the renderer with multiple beforeunload requests.
- // When either this value or IsWaitingForUnloadACK is true, the value of
- // unload_ack_is_for_cross_site_transition_ indicates whether this is for a
- // cross-site transition or a tab close attempt.
- // TODO(clamy): Remove this boolean and add one more state to the state
- // machine.
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- bool is_waiting_for_beforeunload_ack_;
-
- // Valid only when is_waiting_for_beforeunload_ack_ or
- // IsWaitingForUnloadACK is true. This tells us if the unload request
- // is for closing the entire tab ( = false), or only this RenderViewHost in
- // the case of a cross-site transition ( = true).
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- bool unload_ack_is_for_cross_site_transition_;
-
- // Accessibility callback for testing.
- base::Callback<void(ui::AXEvent, int)> accessibility_testing_callback_;
-
- // The most recently received accessibility tree - for testing only.
- scoped_ptr<ui::AXTree> ax_tree_;
+ // Set to true when waiting for a ViewHostMsg_ClosePageACK.
+ // TODO(creis): Move to RenderFrameHost and RenderWidgetHost.
+ // See http://crbug.com/418265.
+ bool is_waiting_for_close_ack_;
// True if the render view can be shut down suddenly.
bool sudden_termination_allowed_;
@@ -629,21 +453,17 @@ class CONTENT_EXPORT RenderViewHostImpl
scoped_ptr<MediaWebContentsObserver> media_web_contents_observer_;
#endif
- // Used to swap out or shutdown this RVH when the unload event is taking too
- // long to execute, depending on the number of active views in the
- // SiteInstance.
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- scoped_ptr<TimeoutMonitor> unload_event_monitor_timeout_;
+ // True if the current focused element is editable.
+ bool is_focused_element_editable_;
- // Called after receiving the SwapOutACK when the RVH is in state pending
- // shutdown. Also called if the unload timer times out.
- // TODO(nasko): Move to RenderFrameHost, as this is per-frame state.
- base::Closure pending_shutdown_on_swap_out_;
+ // This is updated every time UpdateWebkitPreferences is called. That method
+ // is in turn called when any of the settings change that the WebPreferences
+ // values depend on.
+ scoped_ptr<WebPreferences> web_preferences_;
- base::WeakPtrFactory<RenderViewHostImpl> weak_factory_;
+ bool updating_web_preferences_;
- // True if the current focused element is editable.
- bool is_focused_element_editable_;
+ base::WeakPtrFactory<RenderViewHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderViewHostImpl);
};
diff --git a/chromium/content/browser/renderer_host/render_view_host_unittest.cc b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
index 6889cd6f0bd..638442e5f60 100644
--- a/chromium/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_unittest.cc
@@ -6,13 +6,15 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_message_filter.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
+#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/drop_data.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/test/test_content_browser_client.h"
@@ -20,15 +22,16 @@
#include "content/test/test_web_contents.h"
#include "net/base/filename_util.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
+#include "ui/base/page_transition_types.h"
namespace content {
class RenderViewHostTestBrowserClient : public TestContentBrowserClient {
public:
RenderViewHostTestBrowserClient() {}
- virtual ~RenderViewHostTestBrowserClient() {}
+ ~RenderViewHostTestBrowserClient() override {}
- virtual bool IsHandledURL(const GURL& url) OVERRIDE {
+ bool IsHandledURL(const GURL& url) override {
return url.scheme() == url::kFileScheme;
}
@@ -39,14 +42,14 @@ class RenderViewHostTestBrowserClient : public TestContentBrowserClient {
class RenderViewHostTest : public RenderViewHostImplTestHarness {
public:
RenderViewHostTest() : old_browser_client_(NULL) {}
- virtual ~RenderViewHostTest() {}
+ ~RenderViewHostTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
SetBrowserClientForTesting(old_browser_client_);
RenderViewHostImplTestHarness::TearDown();
}
@@ -61,7 +64,7 @@ class RenderViewHostTest : public RenderViewHostImplTestHarness {
// All about URLs reported by the renderer should get rewritten to about:blank.
// See RenderViewHost::OnNavigate for a discussion.
TEST_F(RenderViewHostTest, FilterAbout) {
- test_rvh()->SendNavigate(1, GURL("about:cache"));
+ contents()->GetMainFrame()->SendNavigate(1, GURL("about:cache"));
ASSERT_TRUE(controller().GetVisibleEntry());
EXPECT_EQ(GURL(url::kAboutBlankURL),
controller().GetVisibleEntry()->GetURL());
@@ -93,14 +96,14 @@ TEST_F(RenderViewHostTest, ResetUnloadOnReload) {
NavigateAndCommit(url1);
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
// Simulate the ClosePage call which is normally sent by the net::URLRequest.
rvh()->ClosePage();
- // Needed so that navigations are not suspended on the RVH.
- test_rvh()->SendBeforeUnloadACK(true);
+ // Needed so that navigations are not suspended on the RFH.
+ main_test_rfh()->SendBeforeUnloadACK(true);
contents()->Stop();
controller().Reload(false);
- EXPECT_FALSE(test_rvh()->IsWaitingForUnloadACK());
+ EXPECT_FALSE(main_test_rfh()->IsWaitingForUnloadACK());
}
// Ensure we do not grant bindings to a process shared with unprivileged views.
@@ -116,18 +119,18 @@ TEST_F(RenderViewHostTest, DontGrantBindingsToSharedProcess) {
class MockDraggingRenderViewHostDelegateView
: public RenderViewHostDelegateView {
public:
- virtual ~MockDraggingRenderViewHostDelegateView() {}
- virtual void StartDragging(const DropData& drop_data,
- blink::WebDragOperationsMask allowed_ops,
- const gfx::ImageSkia& image,
- const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) OVERRIDE {
+ ~MockDraggingRenderViewHostDelegateView() override {}
+ void StartDragging(const DropData& drop_data,
+ blink::WebDragOperationsMask allowed_ops,
+ const gfx::ImageSkia& image,
+ const gfx::Vector2d& image_offset,
+ const DragEventSourceInfo& event_info) override {
drag_url_ = drop_data.url;
html_base_url_ = drop_data.html_base_url;
}
- virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE {}
- virtual void GotFocus() OVERRIDE {}
- virtual void TakeFocus(bool reverse) OVERRIDE {}
+ void UpdateDragCursor(blink::WebDragOperation operation) override {}
+ void GotFocus() override {}
+ void TakeFocus(bool reverse) override {}
virtual void UpdatePreferredSize(const gfx::Size& pref_size) {}
GURL drag_url() {
@@ -214,12 +217,12 @@ TEST_F(RenderViewHostTest, MessageWithBadHistoryItemFiles) {
EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
file_path = file_path.AppendASCII("foo");
EXPECT_EQ(0, process()->bad_msg_count());
- test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path);
+ test_rvh()->TestOnUpdateStateWithFile(-1, file_path);
EXPECT_EQ(1, process()->bad_msg_count());
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
process()->GetID(), file_path);
- test_rvh()->TestOnUpdateStateWithFile(process()->GetID(), file_path);
+ test_rvh()->TestOnUpdateStateWithFile(-1, file_path);
EXPECT_EQ(1, process()->bad_msg_count());
}
@@ -229,20 +232,89 @@ TEST_F(RenderViewHostTest, NavigationWithBadHistoryItemFiles) {
EXPECT_TRUE(PathService::Get(base::DIR_TEMP, &file_path));
file_path = file_path.AppendASCII("bar");
EXPECT_EQ(0, process()->bad_msg_count());
- test_rvh()->SendNavigateWithFile(1, url, file_path);
+ contents()->GetMainFrame()->SendNavigateWithFile(1, url, file_path);
EXPECT_EQ(1, process()->bad_msg_count());
ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
process()->GetID(), file_path);
- test_rvh()->SendNavigateWithFile(process()->GetID(), url, file_path);
+ contents()->GetMainFrame()->SendNavigateWithFile(process()->GetID(), url,
+ file_path);
EXPECT_EQ(1, process()->bad_msg_count());
}
TEST_F(RenderViewHostTest, RoutingIdSane) {
RenderFrameHostImpl* root_rfh =
contents()->GetFrameTree()->root()->current_frame_host();
+ EXPECT_EQ(contents()->GetMainFrame(), root_rfh);
EXPECT_EQ(test_rvh()->GetProcess(), root_rfh->GetProcess());
EXPECT_NE(test_rvh()->GetRoutingID(), root_rfh->routing_id());
}
+class TestSaveImageFromDataURL : public RenderMessageFilter {
+ public:
+ TestSaveImageFromDataURL(
+ BrowserContext* context)
+ : RenderMessageFilter(
+ 0,
+ nullptr,
+ context,
+ context->GetRequestContext(),
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr) {
+ Reset();
+ }
+
+ void Reset() {
+ url_string_ = std::string();
+ is_downloaded_ = false;
+ }
+
+ std::string& UrlString() const {
+ return url_string_;
+ }
+
+ bool IsDownloaded() const {
+ return is_downloaded_;
+ }
+
+ void Test(const std::string& url) {
+ OnMessageReceived(ViewHostMsg_SaveImageFromDataURL(0, url));
+ }
+
+ protected:
+ ~TestSaveImageFromDataURL() override {}
+ void DownloadUrl(int render_view_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& suggested_name,
+ const bool use_prompt) const override {
+ url_string_ = url.spec();
+ is_downloaded_ = true;
+ }
+
+ private:
+ mutable std::string url_string_;
+ mutable bool is_downloaded_;
+};
+
+TEST_F(RenderViewHostTest, SaveImageFromDataURL) {
+ scoped_refptr<TestSaveImageFromDataURL> tester(
+ new TestSaveImageFromDataURL(browser_context()));
+
+ tester->Reset();
+ tester->Test("http://non-data-url.com");
+ EXPECT_EQ(tester->UrlString(), "");
+ EXPECT_FALSE(tester->IsDownloaded());
+
+ const std::string data_url = "data:image/gif;base64,"
+ "R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
+
+ tester->Reset();
+ tester->Test(data_url);
+ EXPECT_EQ(tester->UrlString(), data_url);
+ EXPECT_TRUE(tester->IsDownloaded());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.cc b/chromium/content/browser/renderer_host/render_widget_helper.cc
index 169347f3288..9261de92d62 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.cc
+++ b/chromium/content/browser/renderer_host/render_widget_helper.cc
@@ -10,11 +10,12 @@
#include "base/posix/eintr_wrapper.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
+#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/common/view_messages.h"
namespace content {
@@ -34,53 +35,8 @@ void AddWidgetHelper(int render_process_id,
} // namespace
-// A helper used with DidReceiveBackingStoreMsg that we hold a pointer to in
-// pending_paints_.
-class RenderWidgetHelper::BackingStoreMsgProxy {
- public:
- BackingStoreMsgProxy(RenderWidgetHelper* h, const IPC::Message& m);
- ~BackingStoreMsgProxy();
- void Run();
- void Cancel() { cancelled_ = true; }
-
- const IPC::Message& message() const { return message_; }
-
- private:
- scoped_refptr<RenderWidgetHelper> helper_;
- IPC::Message message_;
- bool cancelled_; // If true, then the message will not be dispatched.
-
- DISALLOW_COPY_AND_ASSIGN(BackingStoreMsgProxy);
-};
-
-RenderWidgetHelper::BackingStoreMsgProxy::BackingStoreMsgProxy(
- RenderWidgetHelper* h, const IPC::Message& m)
- : helper_(h),
- message_(m),
- cancelled_(false) {
-}
-
-RenderWidgetHelper::BackingStoreMsgProxy::~BackingStoreMsgProxy() {
- // If the paint message was never dispatched, then we need to let the
- // helper know that we are going away.
- if (!cancelled_ && helper_.get())
- helper_->OnDiscardBackingStoreMsg(this);
-}
-
-void RenderWidgetHelper::BackingStoreMsgProxy::Run() {
- if (!cancelled_) {
- helper_->OnDispatchBackingStoreMsg(this);
- helper_ = NULL;
- }
-}
-
RenderWidgetHelper::RenderWidgetHelper()
: render_process_id_(-1),
-#if defined(OS_WIN)
- event_(CreateEvent(NULL, FALSE /* auto-reset */, FALSE, NULL)),
-#elif defined(OS_POSIX)
- event_(false /* auto-reset */, false),
-#endif
resource_dispatcher_host_(NULL) {
}
@@ -93,10 +49,6 @@ RenderWidgetHelper::~RenderWidgetHelper() {
if (it != widget_map.end() && it->second == this)
widget_map.erase(it);
- // The elements of pending_paints_ each hold an owning reference back to this
- // object, so we should not be destroyed unless pending_paints_ is empty!
- DCHECK(pending_paints_.empty());
-
#if defined(OS_POSIX) && !defined(OS_ANDROID)
ClearAllocatedDIBs();
#endif
@@ -136,49 +88,14 @@ void RenderWidgetHelper::ResumeDeferredNavigation(
request_id));
}
-bool RenderWidgetHelper::WaitForBackingStoreMsg(
- int render_widget_id, const base::TimeDelta& max_delay, IPC::Message* msg) {
- base::TimeTicks time_start = base::TimeTicks::Now();
-
- for (;;) {
- BackingStoreMsgProxy* proxy = NULL;
- {
- base::AutoLock lock(pending_paints_lock_);
-
- BackingStoreMsgProxyMap::iterator it =
- pending_paints_.find(render_widget_id);
- if (it != pending_paints_.end()) {
- BackingStoreMsgProxyQueue &queue = it->second;
- DCHECK(!queue.empty());
- proxy = queue.front();
-
- // Flag the proxy as cancelled so that when it is run as a task it will
- // do nothing.
- proxy->Cancel();
-
- queue.pop_front();
- if (queue.empty())
- pending_paints_.erase(it);
- }
- }
-
- if (proxy) {
- *msg = proxy->message();
- DCHECK(msg->routing_id() == render_widget_id);
- return true;
- }
-
- // Calculate the maximum amount of time that we are willing to sleep.
- base::TimeDelta max_sleep_time =
- max_delay - (base::TimeTicks::Now() - time_start);
- if (max_sleep_time <= base::TimeDelta::FromMilliseconds(0))
- break;
-
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- event_.TimedWait(max_sleep_time);
- }
-
- return false;
+void RenderWidgetHelper::ResumeResponseDeferredAtStart(
+ const GlobalRequestID& request_id) {
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&RenderWidgetHelper::OnResumeResponseDeferredAtStart,
+ this,
+ request_id));
}
void RenderWidgetHelper::ResumeRequestsForView(int route_id) {
@@ -192,59 +109,16 @@ void RenderWidgetHelper::ResumeRequestsForView(int route_id) {
}
}
-void RenderWidgetHelper::DidReceiveBackingStoreMsg(const IPC::Message& msg) {
- int render_widget_id = msg.routing_id();
-
- BackingStoreMsgProxy* proxy = new BackingStoreMsgProxy(this, msg);
- {
- base::AutoLock lock(pending_paints_lock_);
-
- pending_paints_[render_widget_id].push_back(proxy);
- }
-
- // Notify anyone waiting on the UI thread that there is a new entry in the
- // proxy map. If they don't find the entry they are looking for, then they
- // will just continue waiting.
- event_.Signal();
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&BackingStoreMsgProxy::Run, base::Owned(proxy)));
-}
-
-void RenderWidgetHelper::OnDiscardBackingStoreMsg(BackingStoreMsgProxy* proxy) {
- const IPC::Message& msg = proxy->message();
-
- // Remove the proxy from the map now that we are going to handle it normally.
- {
- base::AutoLock lock(pending_paints_lock_);
-
- BackingStoreMsgProxyMap::iterator it =
- pending_paints_.find(msg.routing_id());
- DCHECK(it != pending_paints_.end());
- BackingStoreMsgProxyQueue &queue = it->second;
- DCHECK(queue.front() == proxy);
-
- queue.pop_front();
- if (queue.empty())
- pending_paints_.erase(it);
- }
-}
-
-void RenderWidgetHelper::OnDispatchBackingStoreMsg(
- BackingStoreMsgProxy* proxy) {
- OnDiscardBackingStoreMsg(proxy);
-
- // It is reasonable for the host to no longer exist.
- RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_);
- if (host)
- host->OnMessageReceived(proxy->message());
-}
-
void RenderWidgetHelper::OnResumeDeferredNavigation(
const GlobalRequestID& request_id) {
resource_dispatcher_host_->ResumeDeferredNavigation(request_id);
}
+void RenderWidgetHelper::OnResumeResponseDeferredAtStart(
+ const GlobalRequestID& request_id) {
+ resource_dispatcher_host_->ResumeResponseDeferredAtStart(request_id);
+}
+
void RenderWidgetHelper::CreateNewWindow(
const ViewHostMsg_CreateWindow_Params& params,
bool no_javascript_access,
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.h b/chromium/content/browser/renderer_host/render_widget_helper.h
index af5c6612b5e..98b3ca6cdb8 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_helper.h
@@ -5,15 +5,12 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HELPER_H_
#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HELPER_H_
-#include <deque>
#include <map>
#include "base/atomic_sequence_num.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/process/process.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/global_request_id.h"
@@ -30,7 +27,6 @@ namespace base {
class TimeDelta;
}
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
struct ViewHostMsg_CreateWindow_Params;
struct ViewMsg_SwapOut_Params;
@@ -45,38 +41,6 @@ class SessionStorageNamespace;
// the RenderWidgetHost lives.
//
//
-// OPTIMIZED RESIZE
-//
-// RenderWidgetHelper is used to implement optimized resize. When the
-// RenderWidgetHost is resized, it sends a Resize message to its RenderWidget
-// counterpart in the renderer process. In response to the Resize message,
-// the RenderWidget generates a new BackingStore and sends an UpdateRect
-// message (or BuffersSwapped via the GPU process in the case of accelerated
-// compositing), and it sets the IS_RESIZE_ACK flag in the UpdateRect message
-// to true. In the accelerated case, an UpdateRect is still sent from the
-// renderer to the browser with acks and plugin moves even though the GPU
-// BackingStore was sent earlier in the BuffersSwapped message. "BackingStore
-// message" is used throughout this code and documentation to mean either a
-// software UpdateRect or GPU BuffersSwapped message.
-//
-// Back in the browser process, when the RenderProcessHost's MessageFilter
-// sees an UpdateRect message (or when the GpuProcessHost sees a
-// BuffersSwapped message), it directs it to the RenderWidgetHelper by calling
-// the DidReceiveBackingStoreMsg method. That method stores the data for the
-// message in a map, where it can be directly accessed by the RenderWidgetHost
-// on the UI thread during a call to RenderWidgetHost's GetBackingStore
-// method.
-//
-// When the RenderWidgetHost's GetBackingStore method is called, it first
-// checks to see if it is waiting for a resize ack. If it is, then it calls
-// the RenderWidgetHelper's WaitForBackingStoreMsg to check if there is
-// already a resulting BackingStore message (or to wait a short amount of time
-// for one to arrive). The main goal of this mechanism is to short-cut the
-// usual way in which IPC messages are proxied over to the UI thread via
-// InvokeLater. This approach is necessary since window resize is followed up
-// immediately by a request to repaint the window.
-//
-//
// OPTIMIZED TAB SWITCHING
//
// When a RenderWidgetHost is in a background tab, it is flagged as hidden.
@@ -104,6 +68,7 @@ class SessionStorageNamespace;
// allocation and maintains the set of allocated transport DIBs which the
// renderers can refer to.
//
+
class RenderWidgetHelper
: public base::RefCountedThreadSafe<RenderWidgetHelper,
BrowserThread::DeleteOnIOThread> {
@@ -125,22 +90,18 @@ class RenderWidgetHelper
// UI THREAD ONLY -----------------------------------------------------------
- // These three functions provide the backend implementation of the
+ // These four functions provide the backend implementation of the
// corresponding functions in RenderProcessHost. See those declarations
// for documentation.
void ResumeDeferredNavigation(const GlobalRequestID& request_id);
- bool WaitForBackingStoreMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ void ResumeResponseDeferredAtStart(const GlobalRequestID& request_id);
+
// Called to resume the requests for a view after it's ready. The view was
// created by CreateNewWindow which initially blocked the requests.
void ResumeRequestsForView(int route_id);
// IO THREAD ONLY -----------------------------------------------------------
- // Called on the IO thread when a BackingStore message is received.
- void DidReceiveBackingStoreMsg(const IPC::Message& msg);
-
void CreateNewWindow(
const ViewHostMsg_CreateWindow_Params& params,
bool no_javascript_access,
@@ -169,34 +130,13 @@ class RenderWidgetHelper
void FreeTransportDIB(TransportDIB::Id dib_id);
#endif
-#if defined(OS_MACOSX)
- static void OnNativeSurfaceBuffersSwappedOnIOThread(
- GpuProcessHost* gpu_process_host,
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
-#endif
-
private:
- // A class used to proxy a paint message. PaintMsgProxy objects are created
- // on the IO thread and destroyed on the UI thread.
- class BackingStoreMsgProxy;
- friend class BackingStoreMsgProxy;
friend class base::RefCountedThreadSafe<RenderWidgetHelper>;
friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
friend class base::DeleteHelper<RenderWidgetHelper>;
- typedef std::deque<BackingStoreMsgProxy*> BackingStoreMsgProxyQueue;
- // Map from render_widget_id to a queue of live PaintMsgProxy instances.
- typedef base::hash_map<int, BackingStoreMsgProxyQueue >
- BackingStoreMsgProxyMap;
-
~RenderWidgetHelper();
- // Called on the UI thread to discard a paint message.
- void OnDiscardBackingStoreMsg(BackingStoreMsgProxy* proxy);
-
- // Called on the UI thread to dispatch a paint message if necessary.
- void OnDispatchBackingStoreMsg(BackingStoreMsgProxy* proxy);
-
// Called on the UI thread to finish creating a window.
void OnCreateWindowOnUI(
const ViewHostMsg_CreateWindow_Params& params,
@@ -219,6 +159,10 @@ class RenderWidgetHelper
// stack without transferring it to a new renderer process.
void OnResumeDeferredNavigation(const GlobalRequestID& request_id);
+ // Called on the IO thread to resume a navigation paused immediately after
+ // receiving response headers.
+ void OnResumeResponseDeferredAtStart(const GlobalRequestID& request_id);
+
#if defined(OS_POSIX)
// Called on destruction to release all allocated transport DIBs
void ClearAllocatedDIBs();
@@ -229,18 +173,8 @@ class RenderWidgetHelper
std::map<TransportDIB::Id, int> allocated_dibs_;
#endif
- // A map of live paint messages. Must hold pending_paints_lock_ to access.
- // The BackingStoreMsgProxy objects are not owned by this map. (See
- // BackingStoreMsgProxy for details about how the lifetime of instances are
- // managed.)
- BackingStoreMsgProxyMap pending_paints_;
- base::Lock pending_paints_lock_;
-
int render_process_id_;
- // Event used to implement WaitForBackingStoreMsg.
- base::WaitableEvent event_;
-
// The next routing id to use.
base::AtomicSequenceNumber next_routing_id_;
diff --git a/chromium/content/browser/renderer_host/render_widget_helper_mac.mm b/chromium/content/browser/renderer_host/render_widget_helper_mac.mm
deleted file mode 100644
index 824b2265d70..00000000000
--- a/chromium/content/browser/renderer_host/render_widget_helper_mac.mm
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/render_widget_helper.h"
-
-#import <Cocoa/Cocoa.h>
-#include <IOSurface/IOSurfaceAPI.h>
-
-#include "base/bind.h"
-#include "content/browser/compositor/browser_compositor_view_mac.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
-#include "content/common/gpu/gpu_messages.h"
-
-namespace {
-
-void OnNativeSurfaceBuffersSwappedOnUIThread(
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- gfx::AcceleratedWidget native_widget =
- content::GpuSurfaceTracker::Get()->AcquireNativeWidget(params.surface_id);
- IOSurfaceID io_surface_handle = static_cast<IOSurfaceID>(
- params.surface_handle);
- [native_widget gotAcceleratedIOSurfaceFrame:io_surface_handle
- withOutputSurfaceID:params.surface_id
- withPixelSize:params.size
- withScaleFactor:params.scale_factor];
-}
-
-} // namespace
-
-namespace content {
-
-void RenderWidgetHelper::OnNativeSurfaceBuffersSwappedOnIOThread(
- GpuProcessHost* gpu_process_host,
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- // Immediately acknowledge this frame on the IO thread instead of the UI
- // thread. The UI thread will wait on the GPU process. If the UI thread
- // were to be responsible for acking swaps, then there would be a cycle
- // and a potential deadlock.
- // TODO(ccameron): This immediate ack circumvents GPU back-pressure that
- // is necessary to throttle renderers. Fix that.
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.sync_point = 0;
- ack_params.renderer_id = 0;
- gpu_process_host->Send(new AcceleratedSurfaceMsg_BufferPresented(
- params.route_id, ack_params));
-
- // Open the IOSurface handle before returning, to ensure that it is not
- // closed as soon as the frame is acknowledged.
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceLookup(
- static_cast<uint32>(params.surface_handle)));
-
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&OnNativeSurfaceBuffersSwappedOnUIThread, io_surface, params));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
index 483778167b2..e85a4856824 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -19,7 +19,7 @@ class RenderWidgetHostBrowserTest : public ContentBrowserTest {
public:
RenderWidgetHostBrowserTest() {}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
index 23687d0f24d..a3a474ffab1 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/basictypes.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
namespace content {
@@ -27,9 +28,19 @@ bool RenderWidgetHostDelegate::HandleGestureEvent(
return false;
}
+BrowserAccessibilityManager*
+ RenderWidgetHostDelegate::GetRootBrowserAccessibilityManager() {
+ return NULL;
+}
+
+BrowserAccessibilityManager*
+ RenderWidgetHostDelegate::GetOrCreateRootBrowserAccessibilityManager() {
+ return NULL;
+}
+
#if defined(OS_WIN)
gfx::NativeViewAccessible
-RenderWidgetHostDelegate::GetParentNativeViewAccessible() {
+ RenderWidgetHostDelegate::GetParentNativeViewAccessible() {
return NULL;
}
#endif
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
index 91ce94316f9..669dc255ba4 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_RENDER_WIDGET_HOST_DELEGATE_H_
#define CONTENT_BROWSER_RENDER_WIDGET_HOST_DELEGATE_H_
+#include "base/basictypes.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
@@ -16,6 +17,7 @@ class WebGestureEvent;
namespace content {
+class BrowserAccessibilityManager;
class RenderWidgetHostImpl;
struct NativeWebKeyboardEvent;
@@ -29,6 +31,9 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// The RenderWidgetHost is going to be deleted.
virtual void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) {}
+ // The RenderWidgetHost got the focus.
+ virtual void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) {}
+
// Callback to give the browser a chance to handle the specified keyboard
// event before sending it to the renderer.
// Returns true if the |event| was handled. Otherwise, if the |event| would
@@ -59,11 +64,15 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Notifies that screen rects were sent to renderer process.
virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) {}
- // Notifies that RenderWidgetHost will toggle touch emulation.
- virtual void OnTouchEmulationEnabled(bool enabled) {}
+ // Get the root BrowserAccessibilityManager for this frame tree.
+ virtual BrowserAccessibilityManager* GetRootBrowserAccessibilityManager();
+
+ // Get the root BrowserAccessibilityManager for this frame tree,
+ // or create it if it doesn't exist.
+ virtual BrowserAccessibilityManager*
+ GetOrCreateRootBrowserAccessibilityManager();
#if defined(OS_WIN)
- // Returns the widget's parent's NativeViewAccessible.
virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
#endif
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.cc b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
index eb03476699a..9a1d709a2ef 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -44,7 +44,7 @@
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/common/accessibility_messages.h"
+#include "content/browser/renderer_host/render_widget_resize_helper.h"
#include "content/common/content_constants_internal.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/gpu/gpu_messages.h"
@@ -59,16 +59,16 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
+#include "content/public/common/web_preferences.h"
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/gfx/geometry/vector2d_conversions.h"
#include "ui/gfx/size_conversions.h"
#include "ui/gfx/skbitmap_operations.h"
-#include "ui/gfx/vector2d_conversions.h"
#include "ui/snapshot/snapshot.h"
-#include "webkit/common/webpreferences.h"
#if defined(OS_WIN)
#include "content/common/plugin_constants_win.h"
@@ -89,11 +89,9 @@ namespace {
bool g_check_for_pending_resize_ack = true;
-// How long to (synchronously) wait for the renderer to respond with a
-// PaintRect message, when our backing-store is invalid, before giving up and
-// returning a null or incorrectly sized backing-store from GetBackingStore.
-// This timeout impacts the "choppiness" of our window resize perf.
-const int kPaintMsgTimeoutMS = 50;
+const size_t kBrowserCompositeLatencyHistorySize = 60;
+const double kBrowserCompositeLatencyEstimationPercentile = 90.0;
+const double kBrowserCompositeLatencyEstimationSlack = 1.1;
typedef std::pair<int32, int32> RenderWidgetHostID;
typedef base::hash_map<RenderWidgetHostID, RenderWidgetHostImpl*>
@@ -108,8 +106,8 @@ int GetInputRouterViewFlagsFromCompositorFrameMetadata(
if (metadata.min_page_scale_factor == metadata.max_page_scale_factor)
view_flags |= InputRouter::FIXED_PAGE_SCALE;
- const float window_width_dip =
- std::ceil(metadata.page_scale_factor * metadata.viewport_size.width());
+ const float window_width_dip = std::ceil(
+ metadata.page_scale_factor * metadata.scrollable_viewport_size.width());
const float content_width_css = metadata.root_layer_size.width();
if (content_width_css <= window_width_dip)
view_flags |= InputRouter::MOBILE_VIEWPORT;
@@ -126,8 +124,7 @@ class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
: current_index_(0) {
}
- virtual ~RenderWidgetHostIteratorImpl() {
- }
+ ~RenderWidgetHostIteratorImpl() override {}
void Add(RenderWidgetHost* host) {
hosts_.push_back(RenderWidgetHostID(host->GetProcess()->GetID(),
@@ -135,7 +132,7 @@ class RenderWidgetHostIteratorImpl : public RenderWidgetHostIterator {
}
// RenderWidgetHostIterator:
- virtual RenderWidgetHost* GetNextHost() OVERRIDE {
+ RenderWidgetHost* GetNextHost() override {
RenderWidgetHost* host = NULL;
while (current_index_ < hosts_.size() && !host) {
RenderWidgetHostID id = hosts_[current_index_];
@@ -174,10 +171,9 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
repaint_ack_pending_(false),
resize_ack_pending_(false),
screen_info_out_of_date_(false),
- overdraw_bottom_height_(0.f),
+ top_controls_layout_height_(0.f),
should_auto_resize_(false),
waiting_for_screen_rects_ack_(false),
- accessibility_mode_(AccessibilityModeOff),
needs_repainting_on_restore_(false),
is_unresponsive_(false),
in_flight_event_count_(0),
@@ -191,8 +187,10 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
pending_mouse_lock_request_(false),
allow_privileged_mouse_lock_(false),
has_touch_handler_(false),
- weak_factory_(this),
- last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32) {
+ last_input_number_(static_cast<int64>(GetProcess()->GetID()) << 32),
+ next_browser_snapshot_id_(1),
+ browser_composite_latency_history_(kBrowserCompositeLatencyHistorySize),
+ weak_factory_(this) {
CHECK(delegate_);
if (routing_id_ == MSG_ROUTING_NONE) {
routing_id_ = process_->GetNextRoutingID();
@@ -224,9 +222,6 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
if (!hidden)
process_->WidgetRestored();
- accessibility_mode_ =
- BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode();
-
input_router_.reset(new InputRouterImpl(
process_, this, this, routing_id_, GetInputRouterConfigForPlatform()));
@@ -235,7 +230,7 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
IsRenderView() ? RenderViewHost::From(this) : NULL);
if (BrowserPluginGuest::IsGuest(rvh) ||
- !CommandLine::ForCurrentProcess()->HasSwitch(
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableHangMonitor)) {
hang_monitor_timeout_.reset(new TimeoutMonitor(
base::Bind(&RenderWidgetHostImpl::RendererIsUnresponsive,
@@ -244,6 +239,8 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
}
RenderWidgetHostImpl::~RenderWidgetHostImpl() {
+ if (view_weak_)
+ view_weak_->RenderWidgetHostGone();
SetView(NULL);
GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
@@ -291,8 +288,7 @@ scoped_ptr<RenderWidgetHostIterator> RenderWidgetHost::GetRenderWidgetHosts() {
// Add only active RenderViewHosts.
RenderViewHost* rvh = RenderViewHost::From(widget);
- if (RenderViewHostImpl::IsRVHStateActive(
- static_cast<RenderViewHostImpl*>(rvh)->rvh_state()))
+ if (static_cast<RenderViewHostImpl*>(rvh)->is_active())
hosts->Add(widget);
}
@@ -319,6 +315,10 @@ RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
}
void RenderWidgetHostImpl::SetView(RenderWidgetHostViewBase* view) {
+ if (view)
+ view_weak_ = view->GetWeakPtr();
+ else
+ view_weak_.reset();
view_ = view;
GpuSurfaceTracker::Get()->SetSurfaceHandle(
@@ -442,6 +442,8 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
OnQueueSyntheticGesture)
+ IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
+ OnImeCancelComposition)
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady)
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderProcessGone, OnRenderProcessGone)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnClose)
@@ -456,12 +458,8 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnBlur)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCursor, OnSetCursor)
- IPC_MESSAGE_HANDLER(ViewHostMsg_SetTouchEventEmulationEnabled,
- OnSetTouchEventEmulationEnabled)
- IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
- OnTextInputStateChanged)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCancelComposition,
- OnImeCancelComposition)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputTypeChanged,
+ OnTextInputTypeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_LockMouse, OnLockMouse)
IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
@@ -475,12 +473,8 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
OnWindowlessPluginDummyWindowDestroyed)
#endif
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
- OnCompositorSurfaceBuffersSwapped)
-#endif
-#if defined(OS_MACOSX) || defined(USE_AURA)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
OnImeCompositionRangeChanged)
#endif
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -502,6 +496,13 @@ bool RenderWidgetHostImpl::Send(IPC::Message* msg) {
return process_->Send(msg);
}
+void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
+ is_loading_ = is_loading;
+ if (!view_)
+ return;
+ view_->SetIsLoading(is_loading);
+}
+
void RenderWidgetHostImpl::WasHidden() {
if (is_hidden_)
return;
@@ -525,7 +526,7 @@ void RenderWidgetHostImpl::WasHidden() {
Details<bool>(&is_visible));
}
-void RenderWidgetHostImpl::WasShown() {
+void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
if (!is_hidden_)
return;
is_hidden_ = false;
@@ -535,7 +536,7 @@ void RenderWidgetHostImpl::WasShown() {
// Always repaint on restore.
bool needs_repainting = true;
needs_repainting_on_restore_ = false;
- Send(new ViewMsg_WasShown(routing_id_, needs_repainting));
+ Send(new ViewMsg_WasShown(routing_id_, needs_repainting, latency_info));
process_->WidgetRestored();
@@ -577,8 +578,10 @@ void RenderWidgetHostImpl::WasResized() {
physical_backing_size_ = view_->GetPhysicalBackingSize();
bool was_fullscreen = is_fullscreen_;
is_fullscreen_ = IsFullscreen();
- float old_overdraw_bottom_height = overdraw_bottom_height_;
- overdraw_bottom_height_ = view_->GetOverdrawBottomHeight();
+ float old_top_controls_layout_height =
+ top_controls_layout_height_;
+ top_controls_layout_height_ =
+ view_->GetTopControlsLayoutHeight();
gfx::Size old_visible_viewport_size = visible_viewport_size_;
visible_viewport_size_ = view_->GetVisibleViewportSize();
@@ -587,7 +590,8 @@ void RenderWidgetHostImpl::WasResized() {
screen_info_out_of_date_ ||
old_physical_backing_size != physical_backing_size_ ||
was_fullscreen != is_fullscreen_ ||
- old_overdraw_bottom_height != overdraw_bottom_height_ ||
+ old_top_controls_layout_height !=
+ top_controls_layout_height_ ||
old_visible_viewport_size != visible_viewport_size_;
if (!size_changed && !side_payload_changed)
@@ -607,7 +611,7 @@ void RenderWidgetHostImpl::WasResized() {
params.screen_info = *screen_info_;
params.new_size = new_size;
params.physical_backing_size = physical_backing_size_;
- params.overdraw_bottom_height = overdraw_bottom_height_;
+ params.top_controls_layout_height = top_controls_layout_height_;
params.visible_viewport_size = visible_viewport_size_;
params.resizer_rect = GetRootWindowResizerRect();
params.is_fullscreen = is_fullscreen_;
@@ -624,6 +628,8 @@ void RenderWidgetHostImpl::ResizeRectChanged(const gfx::Rect& new_rect) {
void RenderWidgetHostImpl::GotFocus() {
Focus();
+ if (delegate_)
+ delegate_->RenderWidgetGotFocus(this);
}
void RenderWidgetHostImpl::Focus() {
@@ -666,25 +672,18 @@ void RenderWidgetHostImpl::ViewDestroyed() {
SetView(NULL);
}
-void RenderWidgetHostImpl::SetIsLoading(bool is_loading) {
- is_loading_ = is_loading;
- if (!view_)
- return;
- view_->SetIsLoading(is_loading);
-}
-
void RenderWidgetHostImpl::CopyFromBackingStore(
const gfx::Rect& src_subrect,
const gfx::Size& accelerated_dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config& bitmap_config) {
+ const SkColorType color_type) {
if (view_) {
TRACE_EVENT0("browser",
"RenderWidgetHostImpl::CopyFromBackingStore::FromCompositingSurface");
gfx::Rect accelerated_copy_rect = src_subrect.IsEmpty() ?
gfx::Rect(view_->GetViewBounds().size()) : src_subrect;
view_->CopyFromCompositingSurface(
- accelerated_copy_rect, accelerated_dst_size, callback, bitmap_config);
+ accelerated_copy_rect, accelerated_dst_size, callback, color_type);
return;
}
@@ -709,6 +708,7 @@ void RenderWidgetHostImpl::UnlockBackingStore() {
}
#endif
+#if defined(OS_MACOSX)
void RenderWidgetHostImpl::PauseForPendingResizeOrRepaints() {
TRACE_EVENT0("browser",
"RenderWidgetHostImpl::PauseForPendingResizeOrRepaints");
@@ -734,6 +734,11 @@ bool RenderWidgetHostImpl::CanPauseForPendingResizeOrRepaints() {
void RenderWidgetHostImpl::WaitForSurface() {
TRACE_EVENT0("browser", "RenderWidgetHostImpl::WaitForSurface");
+ // How long to (synchronously) wait for the renderer to respond with a
+ // new frame when our current frame doesn't exist or is the wrong size.
+ // This timeout impacts the "choppiness" of our window resize.
+ const int kPaintMsgTimeoutMS = 50;
+
if (!view_)
return;
@@ -791,8 +796,7 @@ void RenderWidgetHostImpl::WaitForSurface() {
// on a response, block for a little while to see if we can't get a response
// before returning the old (incorrectly sized) backing store.
IPC::Message msg;
- if (process_->WaitForBackingStoreMsg(routing_id_, max_delay, &msg)) {
- OnMessageReceived(msg);
+ if (RenderWidgetResizeHelper::Get()->WaitForSingleTaskToRun(max_delay)) {
// For auto-resized views, current_size_ determines the view_size and it
// may have changed during the handling of an UpdateRect message.
@@ -815,6 +819,7 @@ void RenderWidgetHostImpl::WaitForSurface() {
max_delay = end_time - TimeTicks::Now();
} while (max_delay > TimeDelta::FromSeconds(0));
}
+#endif
bool RenderWidgetHostImpl::ScheduleComposite() {
if (is_hidden_ || current_size_.IsEmpty() || repaint_ack_pending_ ||
@@ -848,22 +853,6 @@ void RenderWidgetHostImpl::StopHangMonitorTimeout() {
RendererIsResponsive();
}
-void RenderWidgetHostImpl::EnableFullAccessibilityMode() {
- AddAccessibilityMode(AccessibilityModeComplete);
-}
-
-bool RenderWidgetHostImpl::IsFullAccessibilityModeForTesting() {
- return accessibility_mode() == AccessibilityModeComplete;
-}
-
-void RenderWidgetHostImpl::EnableTreeOnlyAccessibilityMode() {
- AddAccessibilityMode(AccessibilityModeTreeOnly);
-}
-
-bool RenderWidgetHostImpl::IsTreeOnlyAccessibilityModeForTesting() {
- return accessibility_mode() == AccessibilityModeTreeOnly;
-}
-
void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
ForwardMouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo());
}
@@ -873,9 +862,11 @@ void RenderWidgetHostImpl::ForwardMouseEventWithLatencyInfo(
const ui::LatencyInfo& ui_latency) {
TRACE_EVENT2("input", "RenderWidgetHostImpl::ForwardMouseEvent",
"x", mouse_event.x, "y", mouse_event.y);
+ ui::LatencyInfo::InputCoordinate logical_coordinate(mouse_event.x,
+ mouse_event.y);
- ui::LatencyInfo latency_info =
- CreateRWHLatencyInfoIfNotExist(&ui_latency, mouse_event.type);
+ ui::LatencyInfo latency_info = CreateInputEventLatencyInfoIfNotExist(
+ &ui_latency, mouse_event.type, &logical_coordinate, 1);
for (size_t i = 0; i < mouse_event_callbacks_.size(); ++i) {
if (mouse_event_callbacks_[i].Run(mouse_event))
@@ -905,8 +896,11 @@ void RenderWidgetHostImpl::ForwardWheelEventWithLatencyInfo(
const ui::LatencyInfo& ui_latency) {
TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardWheelEvent");
- ui::LatencyInfo latency_info =
- CreateRWHLatencyInfoIfNotExist(&ui_latency, wheel_event.type);
+ ui::LatencyInfo::InputCoordinate logical_coordinate(wheel_event.x,
+ wheel_event.y);
+
+ ui::LatencyInfo latency_info = CreateInputEventLatencyInfoIfNotExist(
+ &ui_latency, wheel_event.type, &logical_coordinate, 1);
if (IgnoreInputEvents())
return;
@@ -934,8 +928,11 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
if (delegate_->PreHandleGestureEvent(gesture_event))
return;
- ui::LatencyInfo latency_info =
- CreateRWHLatencyInfoIfNotExist(&ui_latency, gesture_event.type);
+ ui::LatencyInfo::InputCoordinate logical_coordinate(gesture_event.x,
+ gesture_event.y);
+
+ ui::LatencyInfo latency_info = CreateInputEventLatencyInfoIfNotExist(
+ &ui_latency, gesture_event.type, &logical_coordinate, 1);
if (gesture_event.type == blink::WebInputEvent::GestureScrollUpdate) {
latency_info.AddLatencyNumber(
@@ -963,9 +960,24 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
input_router_->SendGestureEvent(gesture_with_latency);
}
-void RenderWidgetHostImpl::ForwardTouchEvent(
+void RenderWidgetHostImpl::ForwardEmulatedTouchEvent(
const blink::WebTouchEvent& touch_event) {
- ForwardTouchEventWithLatencyInfo(touch_event, ui::LatencyInfo());
+ TRACE_EVENT0("input", "RenderWidgetHostImpl::ForwardEmulatedTouchEvent");
+
+ ui::LatencyInfo::InputCoordinate
+ logical_coordinates[ui::LatencyInfo::kMaxInputCoordinates];
+ size_t logical_coordinates_size =
+ std::min(arraysize(logical_coordinates),
+ static_cast<size_t>(touch_event.touchesLength));
+ for (size_t i = 0; i < logical_coordinates_size; i++) {
+ logical_coordinates[i] = ui::LatencyInfo::InputCoordinate(
+ touch_event.touches[i].position.x, touch_event.touches[i].position.y);
+ }
+
+ ui::LatencyInfo latency_info = CreateInputEventLatencyInfoIfNotExist(
+ NULL, touch_event.type, logical_coordinates, logical_coordinates_size);
+ TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
+ input_router_->SendTouchEvent(touch_with_latency);
}
void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
@@ -976,9 +988,32 @@ void RenderWidgetHostImpl::ForwardTouchEventWithLatencyInfo(
// Always forward TouchEvents for touch stream consistency. They will be
// ignored if appropriate in FilterInputEvent().
- ui::LatencyInfo latency_info =
- CreateRWHLatencyInfoIfNotExist(&ui_latency, touch_event.type);
+ ui::LatencyInfo::InputCoordinate
+ logical_coordinates[ui::LatencyInfo::kMaxInputCoordinates];
+ size_t logical_coordinates_size =
+ std::min(arraysize(logical_coordinates),
+ static_cast<size_t>(touch_event.touchesLength));
+ for (size_t i = 0; i < logical_coordinates_size; i++) {
+ logical_coordinates[i] = ui::LatencyInfo::InputCoordinate(
+ touch_event.touches[i].position.x, touch_event.touches[i].position.y);
+ }
+
+ ui::LatencyInfo latency_info = CreateInputEventLatencyInfoIfNotExist(
+ &ui_latency,
+ touch_event.type,
+ logical_coordinates,
+ logical_coordinates_size);
TouchEventWithLatencyInfo touch_with_latency(touch_event, latency_info);
+
+ if (touch_emulator_ &&
+ touch_emulator_->HandleTouchEvent(touch_with_latency.event)) {
+ if (view_) {
+ view_->ProcessAckedTouchEvent(
+ touch_with_latency, INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+ return;
+ }
+
input_router_->SendTouchEvent(touch_with_latency);
}
@@ -1048,7 +1083,7 @@ void RenderWidgetHostImpl::ForwardKeyboardEvent(
input_router_->SendKeyboardEvent(
key_event,
- CreateRWHLatencyInfoIfNotExist(NULL, key_event.type),
+ CreateInputEventLatencyInfoIfNotExist(NULL, key_event.type, NULL, 0),
is_shortcut);
}
@@ -1072,11 +1107,16 @@ void RenderWidgetHostImpl::SetCursor(const WebCursor& cursor) {
view_->UpdateCursor(cursor);
}
+void RenderWidgetHostImpl::ShowContextMenuAtPoint(const gfx::Point& point) {
+ Send(new ViewMsg_ShowContextMenu(
+ GetRoutingID(), ui::MENU_SOURCE_MOUSE, point));
+}
+
void RenderWidgetHostImpl::SendCursorVisibilityState(bool is_visible) {
Send(new InputMsg_CursorVisibilityChange(GetRoutingID(), is_visible));
}
-int64 RenderWidgetHostImpl::GetLatencyComponentId() {
+int64 RenderWidgetHostImpl::GetLatencyComponentId() const {
return GetRoutingID() | (static_cast<int64>(GetProcess()->GetID()) << 32);
}
@@ -1085,8 +1125,11 @@ void RenderWidgetHostImpl::DisableResizeAckCheckForTesting() {
g_check_for_pending_resize_ack = false;
}
-ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
- const ui::LatencyInfo* original, WebInputEvent::Type type) {
+ui::LatencyInfo RenderWidgetHostImpl::CreateInputEventLatencyInfoIfNotExist(
+ const ui::LatencyInfo* original,
+ WebInputEvent::Type type,
+ const ui::LatencyInfo::InputCoordinate* logical_coordinates,
+ size_t logical_coordinates_size) {
ui::LatencyInfo info;
if (original)
info = *original;
@@ -1099,7 +1142,21 @@ ui::LatencyInfo RenderWidgetHostImpl::CreateRWHLatencyInfoIfNotExist(
GetLatencyComponentId(),
++last_input_number_);
info.TraceEventType(WebInputEventTraits::GetName(type));
+
+ // Convert logical coordinates to physical coordinates, based on the
+ // device scale factor.
+ float device_scale_factor =
+ screen_info_ ? screen_info_->deviceScaleFactor : 1;
+ DCHECK(logical_coordinates_size <= ui::LatencyInfo::kMaxInputCoordinates);
+ info.input_coordinates_size = logical_coordinates_size;
+ for (size_t i = 0; i < info.input_coordinates_size; i++) {
+ info.input_coordinates[i].x =
+ logical_coordinates[i].x * device_scale_factor;
+ info.input_coordinates[i].y =
+ logical_coordinates[i].y * device_scale_factor;
+ }
}
+
return info;
}
@@ -1162,6 +1219,13 @@ void RenderWidgetHostImpl::InvalidateScreenInfo() {
screen_info_.reset();
}
+void RenderWidgetHostImpl::GetSnapshotFromBrowser(
+ const base::Callback<void(const unsigned char*,size_t)> callback) {
+ int id = next_browser_snapshot_id_++;
+ pending_browser_snapshots_.insert(std::make_pair(id, callback));
+ Send(new ViewMsg_ForceRedraw(GetRoutingID(), id));
+}
+
void RenderWidgetHostImpl::OnSelectionChanged(const base::string16& text,
size_t offset,
const gfx::Range& range) {
@@ -1195,7 +1259,18 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
// Reset some fields in preparation for recovering from a crash.
ResetSizeAndRepaintPendingFlags();
current_size_.SetSize(0, 0);
- is_hidden_ = false;
+ // After the renderer crashes, the view is destroyed and so the
+ // RenderWidgetHost cannot track its visibility anymore. We assume such
+ // RenderWidgetHost to be visible for the sake of internal accounting - be
+ // careful about changing this - see http://crbug.com/401859.
+ //
+ // We need to at least make sure that the RenderProcessHost is notified about
+ // the |is_hidden_| change, so that the renderer will have correct visibility
+ // set when respawned.
+ if (is_hidden_) {
+ process_->WidgetRestored();
+ is_hidden_ = false;
+ }
// Reset this to ensure the hung renderer mechanism is working properly.
in_flight_event_count_ = 0;
@@ -1204,7 +1279,8 @@ void RenderWidgetHostImpl::RendererExited(base::TerminationStatus status,
GpuSurfaceTracker::Get()->SetSurfaceHandle(surface_id_,
gfx::GLSurfaceHandle());
view_->RenderProcessGone(status, exit_code);
- view_ = NULL; // The View should be deleted by RenderProcessGone.
+ view_ = NULL; // The View should be deleted by RenderProcessGone.
+ view_weak_.reset();
}
// Reconstruct the input router to ensure that it has fresh state for a new
@@ -1258,7 +1334,7 @@ void RenderWidgetHostImpl::ImeSetComposition(
const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
int selection_end) {
- Send(new ViewMsg_ImeSetComposition(
+ Send(new InputMsg_ImeSetComposition(
GetRoutingID(), text, underlines, selection_start, selection_end));
}
@@ -1266,12 +1342,12 @@ void RenderWidgetHostImpl::ImeConfirmComposition(
const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection) {
- Send(new ViewMsg_ImeConfirmComposition(
+ Send(new InputMsg_ImeConfirmComposition(
GetRoutingID(), text, replacement_range, keep_selection));
}
void RenderWidgetHostImpl::ImeCancelComposition() {
- Send(new ViewMsg_ImeSetComposition(GetRoutingID(), base::string16(),
+ Send(new InputMsg_ImeSetComposition(GetRoutingID(), base::string16(),
std::vector<blink::WebCompositionUnderline>(), 0, 0));
}
@@ -1408,55 +1484,20 @@ void RenderWidgetHostImpl::OnRequestMove(const gfx::Rect& pos) {
}
}
-#if defined(OS_MACOSX)
-void RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped(
- const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params) {
- // This trace event is used in
- // chrome/browser/extensions/api/cast_streaming/performance_test.cc
- TRACE_EVENT0("renderer_host",
- "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwapped");
- // This trace event is used in
- // chrome/browser/extensions/api/cast_streaming/performance_test.cc
- UNSHIPPED_TRACE_EVENT0("test_fps",
- TRACE_DISABLED_BY_DEFAULT("OnSwapCompositorFrame"));
- if (!ui::LatencyInfo::Verify(params.latency_info,
- "ViewHostMsg_CompositorSurfaceBuffersSwapped"))
- return;
- if (!view_) {
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.sync_point = 0;
- RenderWidgetHostImpl::AcknowledgeBufferPresent(params.route_id,
- params.gpu_process_host_id,
- ack_params);
- return;
- }
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params gpu_params;
- gpu_params.surface_id = params.surface_id;
- gpu_params.surface_handle = params.surface_handle;
- gpu_params.route_id = params.route_id;
- gpu_params.size = params.size;
- gpu_params.scale_factor = params.scale_factor;
- gpu_params.latency_info = params.latency_info;
- for (size_t i = 0; i < gpu_params.latency_info.size(); i++)
- AddLatencyInfoComponentIds(&gpu_params.latency_info[i]);
- view_->AcceleratedSurfaceBuffersSwapped(gpu_params,
- params.gpu_process_host_id);
- view_->DidReceiveRendererFrame();
-}
-#endif // OS_MACOSX
-
bool RenderWidgetHostImpl::OnSwapCompositorFrame(
const IPC::Message& message) {
// This trace event is used in
// chrome/browser/extensions/api/cast_streaming/performance_test.cc
- UNSHIPPED_TRACE_EVENT0("test_fps",
- TRACE_DISABLED_BY_DEFAULT("OnSwapCompositorFrame"));
+ TRACE_EVENT0("test_fps",
+ TRACE_DISABLED_BY_DEFAULT("OnSwapCompositorFrame"));
ViewHostMsg_SwapCompositorFrame::Param param;
if (!ViewHostMsg_SwapCompositorFrame::Read(&message, &param))
return false;
scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
uint32 output_surface_id = param.a;
param.b.AssignTo(frame.get());
+ std::vector<IPC::Message> messages_to_deliver_with_frame;
+ messages_to_deliver_with_frame.swap(param.c);
for (size_t i = 0; i < frame->metadata.latency_info.size(); i++)
AddLatencyInfoComponentIds(&frame->metadata.latency_info[i]);
@@ -1464,6 +1505,11 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
input_router_->OnViewUpdated(
GetInputRouterViewFlagsFromCompositorFrameMetadata(frame->metadata));
+ for (size_t i = 0; i < frame->metadata.latency_info.size(); ++i) {
+ frame->metadata.latency_info[i].AddLatencyNumber(
+ ui::INPUT_EVENT_BROWSER_COMPOSITE_COMPONENT, 0, 0);
+ }
+
if (view_) {
view_->OnSwapCompositorFrame(output_surface_id, frame.Pass());
view_->DidReceiveRendererFrame();
@@ -1482,6 +1528,18 @@ bool RenderWidgetHostImpl::OnSwapCompositorFrame(
SendSwapCompositorFrameAck(routing_id_, output_surface_id,
process_->GetID(), ack);
}
+
+ RenderProcessHost* rph = GetProcess();
+ for (std::vector<IPC::Message>::const_iterator i =
+ messages_to_deliver_with_frame.begin();
+ i != messages_to_deliver_with_frame.end();
+ ++i) {
+ rph->OnMessageReceived(*i);
+ if (i->dispatch_error())
+ rph->OnBadMessageReceived(*i);
+ }
+ messages_to_deliver_with_frame.clear();
+
return true;
}
@@ -1497,8 +1555,6 @@ void RenderWidgetHostImpl::OnUpdateRect(
// Update our knowledge of the RenderWidget's size.
current_size_ = params.view_size;
- // Update our knowledge of the RenderWidget's scroll offset.
- last_scroll_offset_ = params.scroll_offset;
bool is_resize_ack =
ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
@@ -1583,7 +1639,7 @@ void RenderWidgetHostImpl::DidUpdateBackingStore(
void RenderWidgetHostImpl::OnQueueSyntheticGesture(
const SyntheticGesturePacket& gesture_packet) {
// Only allow untrustworthy gestures if explicitly enabled.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
cc::switches::kEnableGpuBenchmarking)) {
RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH7"));
GetProcess()->ReceivedBadMessage();
@@ -1612,28 +1668,27 @@ void RenderWidgetHostImpl::OnSetCursor(const WebCursor& cursor) {
SetCursor(cursor);
}
-void RenderWidgetHostImpl::OnSetTouchEventEmulationEnabled(
- bool enabled, bool allow_pinch) {
- if (delegate_)
- delegate_->OnTouchEmulationEnabled(enabled);
-
+void RenderWidgetHostImpl::SetTouchEventEmulationEnabled(bool enabled) {
if (enabled) {
if (!touch_emulator_)
touch_emulator_.reset(new TouchEmulator(this));
- touch_emulator_->Enable(allow_pinch);
+ touch_emulator_->Enable();
} else {
if (touch_emulator_)
touch_emulator_->Disable();
}
}
-void RenderWidgetHostImpl::OnTextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) {
+void RenderWidgetHostImpl::OnTextInputTypeChanged(
+ ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
if (view_)
- view_->TextInputStateChanged(params);
+ view_->TextInputTypeChanged(type, input_mode, can_compose_inline, flags);
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
void RenderWidgetHostImpl::OnImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
@@ -1673,10 +1728,10 @@ void RenderWidgetHostImpl::OnUnlockMouse() {
}
void RenderWidgetHostImpl::OnShowDisambiguationPopup(
- const gfx::Rect& rect,
+ const gfx::Rect& rect_pixels,
const gfx::Size& size,
const cc::SharedBitmapId& id) {
- DCHECK(!rect.IsEmpty());
+ DCHECK(!rect_pixels.IsEmpty());
DCHECK(!size.IsEmpty());
scoped_ptr<cc::SharedBitmap> bitmap =
@@ -1689,18 +1744,17 @@ void RenderWidgetHostImpl::OnShowDisambiguationPopup(
DCHECK(bitmap->pixels());
+ SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
SkBitmap zoomed_bitmap;
- zoomed_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- size.width(), size.height());
- zoomed_bitmap.setPixels(bitmap->pixels());
+ zoomed_bitmap.installPixels(info, bitmap->pixels(), info.minRowBytes());
-#if defined(OS_ANDROID)
+ // Note that |rect| is in coordinates of pixels relative to the window origin.
+ // Aura-based systems will want to convert this to DIPs.
if (view_)
- view_->ShowDisambiguationPopup(rect, zoomed_bitmap);
-#else
- NOTIMPLEMENTED();
-#endif
+ view_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
+ // It is assumed that the disambiguation popup will make a copy of the
+ // provided zoomed image, so we delete this one.
zoomed_bitmap.setPixels(0);
Send(new ViewMsg_ReleaseDisambiguationPopupBitmap(GetRoutingID(), id));
}
@@ -1794,9 +1848,13 @@ void RenderWidgetHostImpl::IncrementInFlightEventCount() {
void RenderWidgetHostImpl::DecrementInFlightEventCount() {
DCHECK_GE(in_flight_event_count_, 0);
- // Cancel pending hung renderer checks since the renderer is responsive.
- if (decrement_in_flight_event_count() <= 0)
+ if (decrement_in_flight_event_count() <= 0) {
+ // Cancel pending hung renderer checks since the renderer is responsive.
StopHangMonitorTimeout();
+ } else {
+ // The renderer is responsive, but there are in-flight events to wait for.
+ RestartHangMonitorTimeout();
+ }
}
void RenderWidgetHostImpl::OnHasTouchEventHandlers(bool has_handlers) {
@@ -1839,14 +1897,17 @@ void RenderWidgetHostImpl::OnKeyboardEventAck(
void RenderWidgetHostImpl::OnWheelEventAck(
const MouseWheelEventWithLatencyInfo& wheel_event,
InputEventAckState ack_result) {
+ ui::LatencyInfo latency = wheel_event.latency;
+ latency.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
if (!wheel_event.latency.FindLatency(
ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
// MouseWheelEvent latency ends when it is acked but does not cause any
// rendering scheduled.
- ui::LatencyInfo latency = wheel_event.latency;
latency.AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, 0);
}
+ ComputeInputLatencyHistograms(blink::WebInputEvent::MouseWheel, latency);
if (!is_hidden() && view_) {
if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
@@ -1883,17 +1944,20 @@ void RenderWidgetHostImpl::OnTouchEventAck(
InputEventAckState ack_result) {
TouchEventWithLatencyInfo touch_event = event;
touch_event.latency.AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT, 0, 0);
+ ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT, 0, 0);
// TouchEvent latency ends at ack if it didn't cause any rendering.
if (!touch_event.latency.FindLatency(
ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_COMPONENT, 0, NULL)) {
touch_event.latency.AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, 0);
}
- ComputeTouchLatency(touch_event.latency);
+ ComputeInputLatencyHistograms(
+ blink::WebInputEvent::TouchTypeFirst, touch_event.latency);
- if (touch_emulator_ && touch_emulator_->HandleTouchEventAck(ack_result))
+ if (touch_emulator_ &&
+ touch_emulator_->HandleTouchEventAck(event.event, ack_result)) {
return;
+ }
if (view_)
view_->ProcessAckedTouchEvent(touch_event, ack_result);
@@ -1913,15 +1977,18 @@ void RenderWidgetHostImpl::OnSyntheticGestureCompleted(
Send(new InputMsg_SyntheticGestureCompleted(GetRoutingID()));
}
-const gfx::Vector2d& RenderWidgetHostImpl::GetLastScrollOffset() const {
- return last_scroll_offset_;
-}
-
bool RenderWidgetHostImpl::IgnoreInputEvents() const {
return ignore_input_events_ || process_->IgnoreInputEvents();
}
bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const {
+ // It's important that the emulator sees a complete native touch stream,
+ // allowing it to perform touch filtering as appropriate.
+ // TODO(dgozman): Remove when touch stream forwarding issues resolved, see
+ // crbug.com/375940.
+ if (touch_emulator_ && touch_emulator_->enabled())
+ return true;
+
return input_router_->ShouldForwardTouchEvent();
}
@@ -1929,10 +1996,6 @@ void RenderWidgetHostImpl::StartUserGesture() {
OnUserGesture();
}
-void RenderWidgetHostImpl::Stop() {
- Send(new ViewMsg_Stop(GetRoutingID()));
-}
-
void RenderWidgetHostImpl::SetBackgroundOpaque(bool opaque) {
Send(new ViewMsg_SetBackgroundOpaque(GetRoutingID(), opaque));
}
@@ -1942,92 +2005,6 @@ void RenderWidgetHostImpl::SetEditCommandsForNextKeyEvent(
Send(new InputMsg_SetEditCommandsForNextKeyEvent(GetRoutingID(), commands));
}
-void RenderWidgetHostImpl::AddAccessibilityMode(AccessibilityMode mode) {
- SetAccessibilityMode(
- content::AddAccessibilityModeTo(accessibility_mode_, mode));
-}
-
-void RenderWidgetHostImpl::RemoveAccessibilityMode(AccessibilityMode mode) {
- SetAccessibilityMode(
- content::RemoveAccessibilityModeFrom(accessibility_mode_, mode));
-}
-
-void RenderWidgetHostImpl::ResetAccessibilityMode() {
- SetAccessibilityMode(
- BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode());
-}
-
-void RenderWidgetHostImpl::SetAccessibilityMode(AccessibilityMode mode) {
- accessibility_mode_ = mode;
- Send(new ViewMsg_SetAccessibilityMode(GetRoutingID(), mode));
-}
-
-void RenderWidgetHostImpl::AccessibilitySetFocus(int object_id) {
- Send(new AccessibilityMsg_SetFocus(GetRoutingID(), object_id));
- view_->OnAccessibilitySetFocus(object_id);
-}
-
-void RenderWidgetHostImpl::AccessibilityDoDefaultAction(int object_id) {
- Send(new AccessibilityMsg_DoDefaultAction(GetRoutingID(), object_id));
-}
-
-void RenderWidgetHostImpl::AccessibilityShowMenu(int object_id) {
- view_->AccessibilityShowMenu(object_id);
-}
-
-void RenderWidgetHostImpl::AccessibilityScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) {
- Send(new AccessibilityMsg_ScrollToMakeVisible(
- GetRoutingID(), acc_obj_id, subfocus));
-}
-
-void RenderWidgetHostImpl::AccessibilityScrollToPoint(
- int acc_obj_id, gfx::Point point) {
- Send(new AccessibilityMsg_ScrollToPoint(
- GetRoutingID(), acc_obj_id, point));
-}
-
-void RenderWidgetHostImpl::AccessibilitySetTextSelection(
- int object_id, int start_offset, int end_offset) {
- Send(new AccessibilityMsg_SetTextSelection(
- GetRoutingID(), object_id, start_offset, end_offset));
-}
-
-bool RenderWidgetHostImpl::AccessibilityViewHasFocus() const {
- return view_->HasFocus();
-}
-
-gfx::Rect RenderWidgetHostImpl::AccessibilityGetViewBounds() const {
- return view_->GetViewBounds();
-}
-
-gfx::Point RenderWidgetHostImpl::AccessibilityOriginInScreen(
- const gfx::Rect& bounds) const {
- return view_->AccessibilityOriginInScreen(bounds);
-}
-
-void RenderWidgetHostImpl::AccessibilityHitTest(const gfx::Point& point) {
- Send(new AccessibilityMsg_HitTest(GetRoutingID(), point));
-}
-
-void RenderWidgetHostImpl::AccessibilityFatalError() {
- Send(new AccessibilityMsg_FatalError(GetRoutingID()));
- view_->SetBrowserAccessibilityManager(NULL);
-}
-
-#if defined(OS_WIN)
-void RenderWidgetHostImpl::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
- if (view_)
- view_->SetParentNativeViewAccessible(accessible_parent);
-}
-
-gfx::NativeViewAccessible
-RenderWidgetHostImpl::GetParentNativeViewAccessible() const {
- return delegate_->GetParentNativeViewAccessible();
-}
-#endif
-
void RenderWidgetHostImpl::ExecuteEditCommand(const std::string& command,
const std::string& value) {
Send(new InputMsg_ExecuteEditCommand(GetRoutingID(), command, value));
@@ -2065,17 +2042,6 @@ bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
}
// static
-void RenderWidgetHostImpl::AcknowledgeBufferPresent(
- int32 route_id, int gpu_host_id,
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
- GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id);
- if (ui_shim) {
- ui_shim->Send(new AcceleratedSurfaceMsg_BufferPresented(route_id,
- params));
- }
-}
-
-// static
void RenderWidgetHostImpl::SendSwapCompositorFrameAck(
int32 route_id,
uint32 output_surface_id,
@@ -2117,49 +2083,73 @@ void RenderWidgetHostImpl::DetachDelegate() {
delegate_ = NULL;
}
-void RenderWidgetHostImpl::ComputeTouchLatency(
- const ui::LatencyInfo& latency_info) {
- ui::LatencyInfo::LatencyComponent ui_component;
+void RenderWidgetHostImpl::ComputeInputLatencyHistograms(
+ blink::WebInputEvent::Type type,
+ const ui::LatencyInfo& latency_info) const {
ui::LatencyInfo::LatencyComponent rwh_component;
- ui::LatencyInfo::LatencyComponent acked_component;
-
- if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
- 0,
- &ui_component) ||
- !latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
GetLatencyComponentId(),
&rwh_component))
return;
+ DCHECK_EQ(rwh_component.event_count, 1u);
- DCHECK(ui_component.event_count == 1);
- DCHECK(rwh_component.event_count == 1);
-
- base::TimeDelta ui_delta =
- rwh_component.event_time - ui_component.event_time;
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.Browser.TouchUI",
- ui_delta.InMicroseconds(),
- 1,
- 20000,
- 100);
+ ui::LatencyInfo::LatencyComponent ui_component;
+ if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_UI_COMPONENT,
+ 0,
+ &ui_component)) {
+ DCHECK_EQ(ui_component.event_count, 1u);
+ base::TimeDelta ui_delta =
+ rwh_component.event_time - ui_component.event_time;
+ switch (type) {
+ case blink::WebInputEvent::MouseWheel:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.WheelUI",
+ ui_delta.InMicroseconds(), 1, 20000, 100);
+ break;
+ case blink::WebInputEvent::TouchTypeFirst:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.TouchUI",
+ ui_delta.InMicroseconds(), 1, 20000, 100);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
- if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACKED_TOUCH_COMPONENT,
+ ui::LatencyInfo::LatencyComponent acked_component;
+ if (latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_ACK_RWH_COMPONENT,
0,
&acked_component)) {
- DCHECK(acked_component.event_count == 1);
+ DCHECK_EQ(acked_component.event_count, 1u);
base::TimeDelta acked_delta =
acked_component.event_time - rwh_component.event_time;
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.Browser.TouchAcked",
- acked_delta.InMicroseconds(),
- 1,
- 1000000,
- 100);
+ switch (type) {
+ case blink::WebInputEvent::MouseWheel:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.WheelAcked",
+ acked_delta.InMicroseconds(), 1, 1000000, 100);
+ break;
+ case blink::WebInputEvent::TouchTypeFirst:
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.Browser.TouchAcked",
+ acked_delta.InMicroseconds(), 1, 1000000, 100);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
}
}
void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
ui::LatencyInfo::LatencyComponent window_snapshot_component;
+ if (latency_info.FindLatency(ui::WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT,
+ GetLatencyComponentId(),
+ &window_snapshot_component)) {
+ WindowOldSnapshotReachedScreen(
+ static_cast<int>(window_snapshot_component.sequence_number));
+ }
if (latency_info.FindLatency(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
GetLatencyComponentId(),
&window_snapshot_component)) {
@@ -2181,14 +2171,28 @@ void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
#endif
}
- ui::LatencyInfo::LatencyComponent rwh_component;
ui::LatencyInfo::LatencyComponent swap_component;
+ if (!latency_info.FindLatency(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
+ 0,
+ &swap_component)) {
+ return;
+ }
+ ui::LatencyInfo::LatencyComponent tab_switch_component;
+ if (latency_info.FindLatency(ui::TAB_SHOW_COMPONENT,
+ GetLatencyComponentId(),
+ &tab_switch_component)) {
+ base::TimeDelta delta =
+ swap_component.event_time - tab_switch_component.event_time;
+ for (size_t i = 0; i < tab_switch_component.event_count; i++) {
+ UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta);
+ }
+ }
+
+ ui::LatencyInfo::LatencyComponent rwh_component;
if (!latency_info.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
GetLatencyComponentId(),
- &rwh_component) ||
- !latency_info.FindLatency(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT,
- 0, &swap_component)) {
+ &rwh_component)) {
return;
}
@@ -2211,6 +2215,21 @@ void RenderWidgetHostImpl::FrameSwapped(const ui::LatencyInfo& latency_info) {
100);
}
}
+
+ ui::LatencyInfo::LatencyComponent gpu_swap_component;
+ if (!latency_info.FindLatency(
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, &gpu_swap_component)) {
+ return;
+ }
+
+ ui::LatencyInfo::LatencyComponent composite_component;
+ if (latency_info.FindLatency(ui::INPUT_EVENT_BROWSER_COMPOSITE_COMPONENT,
+ 0,
+ &composite_component)) {
+ base::TimeDelta delta =
+ gpu_swap_component.event_time - composite_component.event_time;
+ browser_composite_latency_history_.InsertSample(delta);
+ }
}
void RenderWidgetHostImpl::DidReceiveRendererFrame() {
@@ -2222,7 +2241,7 @@ void RenderWidgetHostImpl::WindowSnapshotAsyncCallback(
int snapshot_id,
gfx::Size snapshot_size,
scoped_refptr<base::RefCountedBytes> png_data) {
- if (!png_data) {
+ if (!png_data.get()) {
std::vector<unsigned char> png_vector;
Send(new ViewMsg_WindowSnapshotCompleted(
routing_id, snapshot_id, gfx::Size(), png_vector));
@@ -2233,14 +2252,15 @@ void RenderWidgetHostImpl::WindowSnapshotAsyncCallback(
routing_id, snapshot_id, snapshot_size, png_data->data()));
}
-void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
+void RenderWidgetHostImpl::WindowOldSnapshotReachedScreen(int snapshot_id) {
DCHECK(base::MessageLoopForUI::IsCurrent());
std::vector<unsigned char> png;
// This feature is behind the kEnableGpuBenchmarking command line switch
// because it poses security concerns and should only be used for testing.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking)) {
Send(new ViewMsg_WindowSnapshotCompleted(
GetRoutingID(), snapshot_id, gfx::Size(), png));
@@ -2269,6 +2289,53 @@ void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
snapshot_size));
}
+void RenderWidgetHostImpl::WindowSnapshotReachedScreen(int snapshot_id) {
+ DCHECK(base::MessageLoopForUI::IsCurrent());
+
+ gfx::Rect view_bounds = GetView()->GetViewBounds();
+ gfx::Rect snapshot_bounds(view_bounds.size());
+
+ std::vector<unsigned char> png;
+ if (ui::GrabViewSnapshot(
+ GetView()->GetNativeView(), &png, snapshot_bounds)) {
+ OnSnapshotDataReceived(snapshot_id, &png.front(), png.size());
+ return;
+ }
+
+ ui::GrabViewSnapshotAsync(
+ GetView()->GetNativeView(),
+ snapshot_bounds,
+ base::ThreadTaskRunnerHandle::Get(),
+ base::Bind(&RenderWidgetHostImpl::OnSnapshotDataReceivedAsync,
+ weak_factory_.GetWeakPtr(),
+ snapshot_id));
+}
+
+void RenderWidgetHostImpl::OnSnapshotDataReceived(int snapshot_id,
+ const unsigned char* data,
+ size_t size) {
+ // Any pending snapshots with a lower ID than the one received are considered
+ // to be implicitly complete, and returned the same snapshot data.
+ PendingSnapshotMap::iterator it = pending_browser_snapshots_.begin();
+ while(it != pending_browser_snapshots_.end()) {
+ if (it->first <= snapshot_id) {
+ it->second.Run(data, size);
+ pending_browser_snapshots_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void RenderWidgetHostImpl::OnSnapshotDataReceivedAsync(
+ int snapshot_id,
+ scoped_refptr<base::RefCountedBytes> png_data) {
+ if (png_data.get())
+ OnSnapshotDataReceived(snapshot_id, png_data->front(), png_data->size());
+ else
+ OnSnapshotDataReceived(snapshot_id, NULL, 0);
+}
+
// static
void RenderWidgetHostImpl::CompositorFrameDrawn(
const std::vector<ui::LatencyInfo>& latency_info) {
@@ -2279,7 +2346,9 @@ void RenderWidgetHostImpl::CompositorFrameDrawn(
b != latency_info[i].latency_components.end();
++b) {
if (b->first.first == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT ||
- b->first.first == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
+ b->first.first == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT ||
+ b->first.first == ui::WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT ||
+ b->first.first == ui::TAB_SHOW_COMPONENT) {
// Matches with GetLatencyComponentId
int routing_id = b->first.second & 0xffffffff;
int process_id = (b->first.second >> 32) & 0xffffffff;
@@ -2303,7 +2372,8 @@ void RenderWidgetHostImpl::AddLatencyInfoComponentIds(
latency_info->latency_components.begin();
while (lc != latency_info->latency_components.end()) {
ui::LatencyComponentType component_type = lc->first.first;
- if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
+ if (component_type == ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT ||
+ component_type == ui::WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT) {
// Generate a new component entry with the correct component ID
ui::LatencyInfo::LatencyMap::key_type key =
std::make_pair(component_type, GetLatencyComponentId());
@@ -2322,10 +2392,39 @@ void RenderWidgetHostImpl::AddLatencyInfoComponentIds(
}
}
-SkBitmap::Config RenderWidgetHostImpl::PreferredReadbackFormat() {
+BrowserAccessibilityManager*
+ RenderWidgetHostImpl::GetRootBrowserAccessibilityManager() {
+ return delegate_ ? delegate_->GetRootBrowserAccessibilityManager() : NULL;
+}
+
+BrowserAccessibilityManager*
+ RenderWidgetHostImpl::GetOrCreateRootBrowserAccessibilityManager() {
+ return delegate_ ?
+ delegate_->GetOrCreateRootBrowserAccessibilityManager() : NULL;
+}
+
+base::TimeDelta RenderWidgetHostImpl::GetEstimatedBrowserCompositeTime() {
+ // TODO(orglofch) remove lower bound on estimate once we're sure it won't
+ // cause regressions
+ return std::max(
+ browser_composite_latency_history_.Percentile(
+ kBrowserCompositeLatencyEstimationPercentile) *
+ kBrowserCompositeLatencyEstimationSlack,
+ base::TimeDelta::FromMicroseconds(
+ (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60)));
+}
+
+#if defined(OS_WIN)
+gfx::NativeViewAccessible
+ RenderWidgetHostImpl::GetParentNativeViewAccessible() {
+ return delegate_ ? delegate_->GetParentNativeViewAccessible() : NULL;
+}
+#endif
+
+SkColorType RenderWidgetHostImpl::PreferredReadbackFormat() {
if (view_)
return view_->PreferredReadbackFormat();
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.h b/chromium/content/browser/renderer_host/render_widget_host_impl.h
index 65fa860df34..71aa04fcf34 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -23,8 +23,8 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
+#include "cc/base/rolling_time_delta_history.h"
#include "cc/resources/shared_bitmap.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/input/input_ack_handler.h"
#include "content/browser/renderer_host/input/input_router_client.h"
@@ -43,7 +43,6 @@
struct AcceleratedSurfaceMsg_BufferPresented_Params;
struct ViewHostMsg_BeginSmoothScroll_Params;
-struct ViewHostMsg_CompositorSurfaceBuffersSwapped_Params;
struct ViewHostMsg_SelectionBounds_Params;
struct ViewHostMsg_TextInputState_Params;
struct ViewHostMsg_UpdateRect_Params;
@@ -79,6 +78,7 @@ class WebLayer;
#endif
namespace content {
+class BrowserAccessibilityManager;
class InputRouter;
class MockRenderWidgetHost;
class RenderWidgetHostDelegate;
@@ -96,8 +96,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
public InputRouterClient,
public InputAckHandler,
public TouchEmulatorClient,
- public IPC::Listener,
- public BrowserAccessibilityDelegate {
+ public IPC::Listener {
public:
// routing_id can be MSG_ROUTING_NONE, in which case the next available
// routing id is taken from the RenderProcessHost.
@@ -107,7 +106,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
RenderProcessHost* process,
int routing_id,
bool hidden);
- virtual ~RenderWidgetHostImpl();
+ ~RenderWidgetHostImpl() override;
// Similar to RenderWidgetHost::FromID, but returning the Impl object.
static RenderWidgetHostImpl* FromID(int32 process_id, int32 routing_id);
@@ -127,70 +126,46 @@ class CONTENT_EXPORT RenderWidgetHostImpl
}
// RenderWidgetHost implementation.
- virtual void UpdateTextDirection(blink::WebTextDirection direction) OVERRIDE;
- virtual void NotifyTextDirection() OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void Blur() OVERRIDE;
- virtual void SetActive(bool active) OVERRIDE;
- virtual void CopyFromBackingStore(
+ void UpdateTextDirection(blink::WebTextDirection direction) override;
+ void NotifyTextDirection() override;
+ void Focus() override;
+ void Blur() override;
+ void SetActive(bool active) override;
+ void CopyFromBackingStore(
const gfx::Rect& src_rect,
const gfx::Size& accelerated_dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config& bitmap_config) OVERRIDE;
- virtual bool CanCopyFromBackingStore() OVERRIDE;
+ const SkColorType color_type) override;
+ bool CanCopyFromBackingStore() override;
#if defined(OS_ANDROID)
- virtual void LockBackingStore() OVERRIDE;
- virtual void UnlockBackingStore() OVERRIDE;
+ virtual void LockBackingStore() override;
+ virtual void UnlockBackingStore() override;
#endif
- virtual void EnableFullAccessibilityMode() OVERRIDE;
- virtual bool IsFullAccessibilityModeForTesting() OVERRIDE;
- virtual void EnableTreeOnlyAccessibilityMode() OVERRIDE;
- virtual bool IsTreeOnlyAccessibilityModeForTesting() OVERRIDE;
- virtual void ForwardMouseEvent(
- const blink::WebMouseEvent& mouse_event) OVERRIDE;
- virtual void ForwardWheelEvent(
- const blink::WebMouseWheelEvent& wheel_event) OVERRIDE;
- virtual void ForwardKeyboardEvent(
- const NativeWebKeyboardEvent& key_event) OVERRIDE;
- virtual const gfx::Vector2d& GetLastScrollOffset() const OVERRIDE;
- virtual RenderProcessHost* GetProcess() const OVERRIDE;
- virtual int GetRoutingID() const OVERRIDE;
- virtual RenderWidgetHostView* GetView() const OVERRIDE;
- virtual bool IsLoading() const OVERRIDE;
- virtual bool IsRenderView() const OVERRIDE;
- virtual void ResizeRectChanged(const gfx::Rect& new_rect) OVERRIDE;
- virtual void RestartHangMonitorTimeout() OVERRIDE;
- virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void WasResized() OVERRIDE;
- virtual void AddKeyPressEventCallback(
- const KeyPressEventCallback& callback) OVERRIDE;
- virtual void RemoveKeyPressEventCallback(
- const KeyPressEventCallback& callback) OVERRIDE;
- virtual void AddMouseEventCallback(
- const MouseEventCallback& callback) OVERRIDE;
- virtual void RemoveMouseEventCallback(
- const MouseEventCallback& callback) OVERRIDE;
- virtual void GetWebScreenInfo(blink::WebScreenInfo* result) OVERRIDE;
-
- virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
-
- // BrowserAccessibilityDelegate
- virtual void AccessibilitySetFocus(int acc_obj_id) OVERRIDE;
- virtual void AccessibilityDoDefaultAction(int acc_obj_id) OVERRIDE;
- virtual void AccessibilityShowMenu(int acc_obj_id) OVERRIDE;
- virtual void AccessibilityScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) OVERRIDE;
- virtual void AccessibilityScrollToPoint(
- int acc_obj_id, gfx::Point point) OVERRIDE;
- virtual void AccessibilitySetTextSelection(
- int acc_obj_id, int start_offset, int end_offset) OVERRIDE;
- virtual bool AccessibilityViewHasFocus() const OVERRIDE;
- virtual gfx::Rect AccessibilityGetViewBounds() const OVERRIDE;
- virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds)
- const OVERRIDE;
- virtual void AccessibilityHitTest(const gfx::Point& point) OVERRIDE;
- virtual void AccessibilityFatalError() OVERRIDE;
+ void ForwardMouseEvent(const blink::WebMouseEvent& mouse_event) override;
+ void ForwardWheelEvent(const blink::WebMouseWheelEvent& wheel_event) override;
+ void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event) override;
+ RenderProcessHost* GetProcess() const override;
+ int GetRoutingID() const override;
+ RenderWidgetHostView* GetView() const override;
+ bool IsLoading() const override;
+ bool IsRenderView() const override;
+ void ResizeRectChanged(const gfx::Rect& new_rect) override;
+ void RestartHangMonitorTimeout() override;
+ void SetIgnoreInputEvents(bool ignore_input_events) override;
+ void WasResized() override;
+ void AddKeyPressEventCallback(const KeyPressEventCallback& callback) override;
+ void RemoveKeyPressEventCallback(
+ const KeyPressEventCallback& callback) override;
+ void AddMouseEventCallback(const MouseEventCallback& callback) override;
+ void RemoveMouseEventCallback(const MouseEventCallback& callback) override;
+ void GetWebScreenInfo(blink::WebScreenInfo* result) override;
+
+ SkColorType PreferredReadbackFormat() override;
+
+ // Forces redraw in the renderer and when the update reaches the browser
+ // grabs snapshot from the compositor. Returns PNG-encoded snapshot.
+ void GetSnapshotFromBrowser(
+ const base::Callback<void(const unsigned char*,size_t)> callback);
const NativeWebKeyboardEvent* GetLastKeyboardEvent() const;
@@ -218,15 +193,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl
virtual void Shutdown();
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// Sends a message to the corresponding object in the renderer.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+
+ // Indicates if the page has finished loading.
+ virtual void SetIsLoading(bool is_loading);
// Called to notify the RenderWidget that it has been hidden or restored from
// having been hidden.
- void WasHidden();
- void WasShown();
+ virtual void WasHidden();
+ virtual void WasShown(const ui::LatencyInfo& latency_info);
// Returns true if the RenderWidget is hidden.
bool is_hidden() const { return is_hidden_; }
@@ -245,9 +223,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Notifies the RenderWidgetHost that the View was destroyed.
void ViewDestroyed();
- // Indicates if the page has finished loading.
- void SetIsLoading(bool is_loading);
-
+#if defined(OS_MACOSX)
// Pause for a moment to wait for pending repaint or resize messages sent to
// the renderer to arrive. If pending resize messages are for an old window
// size, then also pump through a new resize message if there is time.
@@ -259,6 +235,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Wait for a surface matching the size of the widget's view, possibly
// blocking until the renderer sends a new frame.
void WaitForSurface();
+#endif
+
+ bool resize_ack_pending_for_testing() { return resize_ack_pending_; }
// GPU accelerated version of GetBackingStore function. This will
// trigger a re-composite to the view. It may fail if a resize is pending, or
@@ -289,12 +268,16 @@ class CONTENT_EXPORT RenderWidgetHostImpl
const blink::WebMouseWheelEvent& wheel_event,
const ui::LatencyInfo& ui_latency);
- // TouchEmulatorClient overrides.
- virtual void ForwardGestureEvent(
- const blink::WebGestureEvent& gesture_event) OVERRIDE;
- virtual void ForwardTouchEvent(
- const blink::WebTouchEvent& touch_event) OVERRIDE;
- virtual void SetCursor(const WebCursor& cursor) OVERRIDE;
+ // Enables/disables touch emulation using mouse event. See TouchEmulator.
+ void SetTouchEventEmulationEnabled(bool enabled);
+
+ // TouchEmulatorClient implementation.
+ void ForwardGestureEvent(
+ const blink::WebGestureEvent& gesture_event) override;
+ void ForwardEmulatedTouchEvent(
+ const blink::WebTouchEvent& touch_event) override;
+ void SetCursor(const WebCursor& cursor) override;
+ void ShowContextMenuAtPoint(const gfx::Point& point) override;
// Queues a synthetic gesture for testing purposes. Invokes the on_complete
// callback when the gesture is finished running.
@@ -387,30 +370,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void SetEditCommandsForNextKeyEvent(
const std::vector<EditCommand>& commands);
- // Gets the accessibility mode.
- AccessibilityMode accessibility_mode() const {
- return accessibility_mode_;
- }
-
- // Adds the given accessibility mode to the current accessibility mode bitmap.
- void AddAccessibilityMode(AccessibilityMode mode);
-
- // Removes the given accessibility mode from the current accessibility mode
- // bitmap, managing the bits that are shared with other modes such that a
- // bit will only be turned off when all modes that depend on it have been
- // removed.
- void RemoveAccessibilityMode(AccessibilityMode mode);
-
- // Resets the accessibility mode to the default setting in
- // BrowserStateAccessibilityImpl.
- void ResetAccessibilityMode();
-
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent);
- gfx::NativeViewAccessible GetParentNativeViewAccessible() const;
-#endif
-
// Executes the edit command on the RenderView.
void ExecuteEditCommand(const std::string& command,
const std::string& value);
@@ -435,13 +394,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
virtual void UpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
- // Called by the view in response to AcceleratedSurfaceBuffersSwapped or
- // AcceleratedSurfacePostSubBuffer.
- static void AcknowledgeBufferPresent(
- int32 route_id,
- int gpu_host_id,
- const AcceleratedSurfaceMsg_BufferPresented_Params& params);
-
// Called by the view in response to OnSwapCompositorFrame.
static void SendSwapCompositorFrameAck(
int32 route_id,
@@ -479,19 +431,18 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void FlushInput();
// InputRouterClient
- virtual void SetNeedsFlush() OVERRIDE;
+ void SetNeedsFlush() override;
// Indicates whether the renderer drives the RenderWidgetHosts's size or the
// other way around.
bool should_auto_resize() { return should_auto_resize_; }
- void ComputeTouchLatency(const ui::LatencyInfo& latency_info);
void FrameSwapped(const ui::LatencyInfo& latency_info);
void DidReceiveRendererFrame();
// Returns the ID that uniquely describes this component to the latency
// subsystem.
- int64 GetLatencyComponentId();
+ int64 GetLatencyComponentId() const;
static void CompositorFrameDrawn(
const std::vector<ui::LatencyInfo>& latency_info);
@@ -512,14 +463,35 @@ class CONTENT_EXPORT RenderWidgetHostImpl
InputRouter* input_router() { return input_router_.get(); }
+ // Get the BrowserAccessibilityManager for the root of the frame tree,
+ BrowserAccessibilityManager* GetRootBrowserAccessibilityManager();
+
+ // Get the BrowserAccessibilityManager for the root of the frame tree,
+ // or create it if it doesn't already exist.
+ BrowserAccessibilityManager* GetOrCreateRootBrowserAccessibilityManager();
+
+ base::TimeDelta GetEstimatedBrowserCompositeTime();
+
+#if defined(OS_WIN)
+ gfx::NativeViewAccessible GetParentNativeViewAccessible();
+#endif
+
protected:
- virtual RenderWidgetHostImpl* AsRenderWidgetHostImpl() OVERRIDE;
+ RenderWidgetHostImpl* AsRenderWidgetHostImpl() override;
// Create a LatencyInfo struct with INPUT_EVENT_LATENCY_RWH_COMPONENT
// component if it is not already in |original|. And if |original| is
// not NULL, it is also merged into the resulting LatencyInfo.
- ui::LatencyInfo CreateRWHLatencyInfoIfNotExist(
- const ui::LatencyInfo* original, blink::WebInputEvent::Type type);
+ ui::LatencyInfo CreateInputEventLatencyInfoIfNotExist(
+ const ui::LatencyInfo* original,
+ blink::WebInputEvent::Type type,
+ const ui::LatencyInfo::InputCoordinate* logical_coordinates,
+ size_t logical_coordinates_size);
+ // Add UMA histograms for the latency to the renderer and roundtrip latency
+ // for a given event type.
+ void ComputeInputLatencyHistograms(
+ blink::WebInputEvent::Type type,
+ const ui::LatencyInfo& latency_info) const;
// Called when we receive a notification indicating that the renderer
// process has gone. This will reset our state so that our state will be
@@ -585,13 +557,19 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// doing so).
RenderWidgetHostViewBase* view_;
+ // A weak pointer to the view. The above pointer should be weak, but changing
+ // that to be weak causes crashes on Android.
+ // TODO(ccameron): Fix this.
+ // http://crbug.com/404828
+ base::WeakPtr<RenderWidgetHostViewBase> view_weak_;
+
// true if a renderer has once been valid. We use this flag to display a sad
// tab only when we lose our renderer and not if a paint occurs during
// initialization.
bool renderer_initialized_;
// This value indicates how long to wait before we consider a renderer hung.
- int hung_renderer_delay_ms_;
+ int64 hung_renderer_delay_ms_;
private:
friend class MockRenderWidgetHost;
@@ -615,10 +593,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
void OnRequestMove(const gfx::Rect& pos);
void OnSetTooltipText(const base::string16& tooltip_text,
blink::WebTextDirection text_direction_hint);
-#if defined(OS_MACOSX)
- void OnCompositorSurfaceBuffersSwapped(
- const ViewHostMsg_CompositorSurfaceBuffersSwapped_Params& params);
-#endif
bool OnSwapCompositorFrame(const IPC::Message& message);
void OnFlingingStopped();
void OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
@@ -626,11 +600,12 @@ class CONTENT_EXPORT RenderWidgetHostImpl
virtual void OnFocus();
virtual void OnBlur();
void OnSetCursor(const WebCursor& cursor);
- void OnSetTouchEventEmulationEnabled(bool enabled, bool allow_pinch);
- void OnTextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params);
+ void OnTextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags);
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
void OnImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds);
@@ -640,7 +615,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
bool last_unlocked_by_target,
bool privileged);
void OnUnlockMouse();
- void OnShowDisambiguationPopup(const gfx::Rect& rect,
+ void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels,
const gfx::Size& size,
const cc::SharedBitmapId& id);
#if defined(OS_WIN)
@@ -667,25 +642,25 @@ class CONTENT_EXPORT RenderWidgetHostImpl
bool KeyPressListenersHandleEvent(const NativeWebKeyboardEvent& event);
// InputRouterClient
- virtual InputEventAckState FilterInputEvent(
+ InputEventAckState FilterInputEvent(
const blink::WebInputEvent& event,
- const ui::LatencyInfo& latency_info) OVERRIDE;
- virtual void IncrementInFlightEventCount() OVERRIDE;
- virtual void DecrementInFlightEventCount() OVERRIDE;
- virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
- virtual void DidFlush() OVERRIDE;
- virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
+ const ui::LatencyInfo& latency_info) override;
+ void IncrementInFlightEventCount() override;
+ void DecrementInFlightEventCount() override;
+ void OnHasTouchEventHandlers(bool has_handlers) override;
+ void DidFlush() override;
+ void DidOverscroll(const DidOverscrollParams& params) override;
// InputAckHandler
- virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void OnUnexpectedEventAck(UnexpectedEventAckType type) OVERRIDE;
+ void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
+ InputEventAckState ack_result) override;
+ void OnWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void OnUnexpectedEventAck(UnexpectedEventAckType type) override;
void OnSyntheticGestureCompleted(SyntheticGesture::Result result);
@@ -693,10 +668,17 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// which may get in recursive loops).
void DelayedAutoResized();
+ void WindowOldSnapshotReachedScreen(int snapshot_id);
+
void WindowSnapshotReachedScreen(int snapshot_id);
- // Send a message to the renderer process to change the accessibility mode.
- void SetAccessibilityMode(AccessibilityMode AccessibilityMode);
+ void OnSnapshotDataReceived(int snapshot_id,
+ const unsigned char* png,
+ size_t size);
+
+ void OnSnapshotDataReceivedAsync(
+ int snapshot_id,
+ scoped_refptr<base::RefCountedBytes> png_data);
// Our delegate, which wants to know mainly about keyboard events.
// It will remain non-NULL until DetachDelegate() is called.
@@ -716,7 +698,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// Indicates whether a page is loading or not.
bool is_loading_;
- // Indicates whether a page is hidden or not.
+ // Indicates whether a page is hidden or not. It has to stay in sync with the
+ // most recent call to process_->WidgetRestored() / WidgetHidden().
bool is_hidden_;
// Indicates whether a page is fullscreen or not.
@@ -742,9 +725,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// The size of the view's backing surface in non-DPI-adjusted pixels.
gfx::Size physical_backing_size_;
- // The height of the physical backing surface that is overdrawn opaquely in
- // the browser, for example by an on-screen-keyboard (in DPI-adjusted pixels).
- float overdraw_bottom_height_;
+ // The amount that the viewport size given to Blink was shrunk by the URL-bar
+ // (always 0 on platforms where URL-bar hiding isn't supported).
+ float top_controls_layout_height_;
// The size of the visible viewport, which may be smaller than the view if the
// view is partially occluded (e.g. by a virtual keyboard). The size is in
@@ -769,8 +752,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
gfx::Rect last_view_screen_rect_;
gfx::Rect last_window_screen_rect_;
- AccessibilityMode accessibility_mode_;
-
// Keyboard event listeners.
std::vector<KeyPressEventCallback> key_press_event_callbacks_;
@@ -834,9 +815,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// changed.
bool suppress_next_char_events_;
- // The last scroll offset of the render widget.
- gfx::Vector2d last_scroll_offset_;
-
bool pending_mouse_lock_request_;
bool allow_privileged_mouse_lock_;
@@ -845,8 +823,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl
// not sent to the renderer.
bool has_touch_handler_;
- base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
-
scoped_ptr<SyntheticGestureController> synthetic_gesture_controller_;
scoped_ptr<TouchEmulator> touch_emulator_;
@@ -862,6 +838,15 @@ class CONTENT_EXPORT RenderWidgetHostImpl
int64 last_input_number_;
+ int next_browser_snapshot_id_;
+ typedef std::map<int,
+ base::Callback<void(const unsigned char*, size_t)> > PendingSnapshotMap;
+ PendingSnapshotMap pending_browser_snapshots_;
+
+ cc::RollingTimeDeltaHistory browser_composite_latency_history_;
+
+ base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostImpl);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
index 710719c7706..830ab01ed0c 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -9,6 +9,7 @@
#include "base/memory/shared_memory.h"
#include "base/timer/timer.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
@@ -28,13 +29,15 @@
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#endif
+#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
+#endif
+
#if defined(USE_AURA)
-#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/env.h"
#include "ui/aura/test/test_screen.h"
-#include "ui/compositor/test/in_process_context_factory.h"
#include "ui/events/event.h"
#endif
@@ -64,50 +67,45 @@ class MockInputRouter : public InputRouter {
message_received_(false),
client_(client) {
}
- virtual ~MockInputRouter() {}
+ ~MockInputRouter() override {}
// InputRouter
- virtual void Flush() OVERRIDE {
- flush_called_ = true;
- }
- virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE {
+ void Flush() override { flush_called_ = true; }
+ bool SendInput(scoped_ptr<IPC::Message> message) override {
send_event_called_ = true;
return true;
}
- virtual void SendMouseEvent(
- const MouseEventWithLatencyInfo& mouse_event) OVERRIDE {
+ void SendMouseEvent(const MouseEventWithLatencyInfo& mouse_event) override {
sent_mouse_event_ = true;
}
- virtual void SendWheelEvent(
- const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE {
+ void SendWheelEvent(
+ const MouseWheelEventWithLatencyInfo& wheel_event) override {
sent_wheel_event_ = true;
}
- virtual void SendKeyboardEvent(
- const NativeWebKeyboardEvent& key_event,
- const ui::LatencyInfo& latency_info,
- bool is_shortcut) OVERRIDE {
+ void SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
+ const ui::LatencyInfo& latency_info,
+ bool is_shortcut) override {
sent_keyboard_event_ = true;
}
- virtual void SendGestureEvent(
- const GestureEventWithLatencyInfo& gesture_event) OVERRIDE {
+ void SendGestureEvent(
+ const GestureEventWithLatencyInfo& gesture_event) override {
sent_gesture_event_ = true;
}
- virtual void SendTouchEvent(
- const TouchEventWithLatencyInfo& touch_event) OVERRIDE {
+ void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override {
send_touch_event_not_cancelled_ =
client_->FilterInputEvent(touch_event.event, touch_event.latency) ==
INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
- virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE {
+ const NativeWebKeyboardEvent* GetLastKeyboardEvent() const override {
NOTREACHED();
return NULL;
}
- virtual bool ShouldForwardTouchEvent() const OVERRIDE { return true; }
- virtual void OnViewUpdated(int view_flags) OVERRIDE {}
- virtual bool HasPendingEvents() const OVERRIDE { return false; }
+ bool ShouldForwardTouchEvent() const override { return true; }
+ void OnViewUpdated(int view_flags) override {}
+ bool HasPendingEvents() const override { return false; }
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
message_received_ = true;
return false;
}
@@ -148,9 +146,8 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
using RenderWidgetHostImpl::resize_ack_pending_;
using RenderWidgetHostImpl::input_router_;
- virtual void OnTouchEventAck(
- const TouchEventWithLatencyInfo& event,
- InputEventAckState ack_result) OVERRIDE {
+ void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
// Sniff touch acks.
acked_touch_event_type_ = event.event.type;
RenderWidgetHostImpl::OnTouchEventAck(event, ack_result);
@@ -160,7 +157,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
return unresponsive_timer_fired_;
}
- void set_hung_renderer_delay_ms(int delay_ms) {
+ void set_hung_renderer_delay_ms(int64 delay_ms) {
hung_renderer_delay_ms_ = delay_ms;
}
@@ -182,7 +179,7 @@ class MockRenderWidgetHost : public RenderWidgetHostImpl {
}
protected:
- virtual void NotifyRendererUnresponsive() OVERRIDE {
+ void NotifyRendererUnresponsive() override {
unresponsive_timer_fired_ = true;
}
@@ -200,15 +197,10 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
public:
explicit RenderWidgetHostProcess(BrowserContext* browser_context)
: MockRenderProcessHost(browser_context),
- update_msg_should_reply_(false),
update_msg_reply_flags_(0) {
}
- virtual ~RenderWidgetHostProcess() {
- }
+ ~RenderWidgetHostProcess() override {}
- void set_update_msg_should_reply(bool reply) {
- update_msg_should_reply_ = reply;
- }
void set_update_msg_reply_flags(int flags) {
update_msg_reply_flags_ = flags;
}
@@ -216,17 +208,9 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
// Fills the given update parameters with resonable default values.
void InitUpdateRectParams(ViewHostMsg_UpdateRect_Params* params);
- virtual bool HasConnection() const OVERRIDE { return true; }
+ bool HasConnection() const override { return true; }
protected:
- virtual bool WaitForBackingStoreMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) OVERRIDE;
-
- // Set to true when WaitForBackingStoreMsg should return a successful update
- // message reply. False implies timeout.
- bool update_msg_should_reply_;
-
// Indicates the flags that should be sent with a repaint request. This
// only has an effect when update_msg_should_reply_ is true.
int update_msg_reply_flags_;
@@ -242,22 +226,6 @@ void RenderWidgetHostProcess::InitUpdateRectParams(
params->flags = update_msg_reply_flags_;
}
-bool RenderWidgetHostProcess::WaitForBackingStoreMsg(
- int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
- if (!update_msg_should_reply_)
- return false;
-
- // Construct a fake update reply.
- ViewHostMsg_UpdateRect_Params params;
- InitUpdateRectParams(&params);
-
- ViewHostMsg_UpdateRect message(render_widget_id, params);
- *msg = message;
- return true;
-}
-
// TestView --------------------------------------------------------------------
// This test view allows us to specify the size, and keep track of acked
@@ -303,33 +271,31 @@ class TestView : public TestRenderWidgetHostView {
}
// RenderWidgetHostView override.
- virtual gfx::Rect GetViewBounds() const OVERRIDE {
- return bounds_;
- }
- virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) OVERRIDE {
+ gfx::Rect GetViewBounds() const override { return bounds_; }
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) override {
acked_event_ = touch.event;
++acked_event_count_;
}
- virtual void WheelEventAck(const WebMouseWheelEvent& event,
- InputEventAckState ack_result) OVERRIDE {
+ void WheelEventAck(const WebMouseWheelEvent& event,
+ InputEventAckState ack_result) override {
if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
return;
unhandled_wheel_event_count_++;
unhandled_wheel_event_ = event;
}
- virtual void GestureEventAck(const WebGestureEvent& event,
- InputEventAckState ack_result) OVERRIDE {
+ void GestureEventAck(const WebGestureEvent& event,
+ InputEventAckState ack_result) override {
gesture_event_type_ = event.type;
ack_result_ = ack_result;
}
- virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE {
+ gfx::Size GetPhysicalBackingSize() const override {
if (use_fake_physical_backing_size_)
return mock_physical_backing_size_;
return TestRenderWidgetHostView::GetPhysicalBackingSize();
}
#if defined(USE_AURA)
- virtual ~TestView() {
+ ~TestView() override {
// Simulate the mouse exit event dispatched when an aura window is
// destroyed. (MakeWebMouseEventFromAuraEvent translates ET_MOUSE_EXITED
// into WebInputEvent::MouseMove.)
@@ -367,7 +333,7 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
handle_wheel_event_(false),
handle_wheel_event_called_(false) {
}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
// Tests that make sure we ignore keyboard event acknowledgments to events we
// didn't send work by making sure we didn't call UnhandledKeyboardEvent().
@@ -400,21 +366,19 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
}
protected:
- virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
- bool* is_keyboard_shortcut) OVERRIDE {
+ bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) override {
prehandle_keyboard_event_type_ = event.type;
prehandle_keyboard_event_called_ = true;
return prehandle_keyboard_event_;
}
- virtual void HandleKeyboardEvent(
- const NativeWebKeyboardEvent& event) OVERRIDE {
+ void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override {
unhandled_keyboard_event_type_ = event.type;
unhandled_keyboard_event_called_ = true;
}
- virtual bool HandleWheelEvent(
- const blink::WebMouseWheelEvent& event) OVERRIDE {
+ bool HandleWheelEvent(const blink::WebMouseWheelEvent& event) override {
handle_wheel_event_called_ = true;
return handle_wheel_event_;
}
@@ -443,8 +407,7 @@ class RenderWidgetHostTest : public testing::Test {
last_simulated_event_time_seconds_ =
(base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
}
- virtual ~RenderWidgetHostTest() {
- }
+ ~RenderWidgetHostTest() override {}
bool KeyPressEventCallback(const NativeWebKeyboardEvent& /* event */) {
return handle_key_press_event_;
@@ -455,16 +418,21 @@ class RenderWidgetHostTest : public testing::Test {
protected:
// testing::Test
- virtual void SetUp() {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ void SetUp() override {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(switches::kValidateInputEventStream);
browser_context_.reset(new TestBrowserContext());
delegate_.reset(new MockRenderWidgetHostDelegate());
process_ = new RenderWidgetHostProcess(browser_context_.get());
+#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+ if (IsDelegatedRendererEnabled()) {
+ ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactory>(
+ new NoTransportImageTransportFactory));
+ }
+#endif
#if defined(USE_AURA)
- ImageTransportFactory::InitializeForUnitTests(
- scoped_ptr<ui::ContextFactory>(new ui::InProcessContextFactory));
aura::Env::CreateInstance(true);
screen_.reset(aura::TestScreen::Create(gfx::Size()));
gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
@@ -476,7 +444,7 @@ class RenderWidgetHostTest : public testing::Test {
host_->Init();
host_->DisableGestureDebounce();
}
- virtual void TearDown() {
+ void TearDown() override {
view_.reset();
host_.reset();
delegate_.reset();
@@ -486,7 +454,10 @@ class RenderWidgetHostTest : public testing::Test {
#if defined(USE_AURA)
aura::Env::DeleteInstance();
screen_.reset();
- ImageTransportFactory::Terminate();
+#endif
+#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+ if (IsDelegatedRendererEnabled())
+ ImageTransportFactory::Terminate();
#endif
// Process all pending tasks to avoid leaks.
@@ -779,7 +750,7 @@ TEST_F(RenderWidgetHostTest, ResizeThenCrash) {
TEST_F(RenderWidgetHostTest, Background) {
scoped_ptr<RenderWidgetHostViewBase> view;
#if defined(USE_AURA)
- view.reset(new RenderWidgetHostViewAura(host_.get()));
+ view.reset(new RenderWidgetHostViewAura(host_.get(), false));
// TODO(derat): Call this on all platforms: http://crbug.com/102450.
view->InitAsChild(NULL);
#elif defined(OS_ANDROID)
@@ -788,7 +759,7 @@ TEST_F(RenderWidgetHostTest, Background) {
host_->SetView(view.get());
EXPECT_TRUE(view->GetBackgroundOpaque());
- view->SetBackgroundOpaque(false);
+ view->SetBackgroundColor(SK_ColorTRANSPARENT);
EXPECT_FALSE(view->GetBackgroundOpaque());
const IPC::Message* set_background =
@@ -825,14 +796,14 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
// Now unhide.
process_->sink().ClearMessages();
- host_->WasShown();
+ host_->WasShown(ui::LatencyInfo());
EXPECT_FALSE(host_->is_hidden_);
// It should have sent out a restored message with a request to paint.
const IPC::Message* restored = process_->sink().GetUniqueMessageMatching(
ViewMsg_WasShown::ID);
ASSERT_TRUE(restored);
- Tuple1<bool> needs_repaint;
+ Tuple2<bool, ui::LatencyInfo> needs_repaint;
ViewMsg_WasShown::Read(restored, &needs_repaint);
EXPECT_TRUE(needs_repaint.a);
}
@@ -1049,8 +1020,7 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
simulated_event_time_delta_seconds_ = 0.1;
// Immediately ack all touches instead of sending them to the renderer.
host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
- host_->OnMessageReceived(
- ViewHostMsg_SetTouchEventEmulationEnabled(0, true, true));
+ host_->SetTouchEventEmulationEnabled(true);
process_->sink().ClearMessages();
view_->set_bounds(gfx::Rect(0, 0, 400, 200));
view_->Show();
@@ -1149,8 +1119,7 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
EXPECT_EQ(0U, process_->sink().message_count());
// Turn off emulation during a pinch.
- host_->OnMessageReceived(
- ViewHostMsg_SetTouchEventEmulationEnabled(0, false, false));
+ host_->SetTouchEventEmulationEnabled(false);
EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type());
EXPECT_EQ("GesturePinchEnd GestureScrollEnd",
GetInputMessageTypes(process_));
@@ -1165,8 +1134,7 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
EXPECT_EQ(0U, process_->sink().message_count());
// Turn on emulation.
- host_->OnMessageReceived(
- ViewHostMsg_SetTouchEventEmulationEnabled(0, true, true));
+ host_->SetTouchEventEmulationEnabled(true);
EXPECT_EQ(0U, process_->sink().message_count());
// Another touch.
@@ -1185,8 +1153,7 @@ TEST_F(RenderWidgetHostTest, TouchEmulator) {
INPUT_EVENT_ACK_STATE_CONSUMED);
// Turn off emulation during a scroll.
- host_->OnMessageReceived(
- ViewHostMsg_SetTouchEventEmulationEnabled(0, false, false));
+ host_->SetTouchEventEmulationEnabled(false);
EXPECT_EQ(WebInputEvent::TouchCancel, host_->acked_touch_event_type());
EXPECT_EQ("GestureScrollEnd", GetInputMessageTypes(process_));
@@ -1334,7 +1301,7 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesHandleInputEvent_ACK) {
TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) {
host_->SetupForInputRouterTest();
- host_->OnMessageReceived(ViewHostMsg_MoveCaret_ACK(0));
+ host_->OnMessageReceived(InputHostMsg_MoveCaret_ACK(0));
EXPECT_TRUE(host_->mock_input_router()->message_received_);
}
@@ -1342,7 +1309,7 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesMoveCaret_ACK) {
TEST_F(RenderWidgetHostTest, InputRouterReceivesSelectRange_ACK) {
host_->SetupForInputRouterTest();
- host_->OnMessageReceived(ViewHostMsg_SelectRange_ACK(0));
+ host_->OnMessageReceived(InputHostMsg_SelectRange_ACK(0));
EXPECT_TRUE(host_->mock_input_router()->message_received_);
}
@@ -1355,21 +1322,24 @@ TEST_F(RenderWidgetHostTest, InputRouterReceivesHasTouchEventHandlers) {
EXPECT_TRUE(host_->mock_input_router()->message_received_);
}
-
-void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process,
- int64 component_id,
- WebInputEvent::Type input_type) {
+ui::LatencyInfo GetLatencyInfoFromInputEvent(RenderWidgetHostProcess* process) {
const IPC::Message* message = process->sink().GetUniqueMessageMatching(
InputMsg_HandleInputEvent::ID);
- ASSERT_TRUE(message);
+ EXPECT_TRUE(message);
InputMsg_HandleInputEvent::Param params;
EXPECT_TRUE(InputMsg_HandleInputEvent::Read(message, &params));
- ui::LatencyInfo latency_info = params.b;
+ process->sink().ClearMessages();
+ return params.b;
+}
+
+void CheckLatencyInfoComponentInMessage(RenderWidgetHostProcess* process,
+ int64 component_id,
+ WebInputEvent::Type input_type) {
+ ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process);
EXPECT_TRUE(latency_info.FindLatency(
ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
component_id,
NULL));
- process->sink().ClearMessages();
}
// Tests that after input event passes through RWHI through ForwardXXXEvent()
@@ -1428,6 +1398,79 @@ TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED);
}
+// Tests that after input event passes through RWHI through
+// ForwardXXXEventWithLatencyInfo(), input event coordinates will be present in
+// the latency info.
+TEST_F(RenderWidgetHostTest, InputEventRWHLatencyInfoCoordinates) {
+ host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true));
+ process_->sink().ClearMessages();
+
+ {
+ WebMouseWheelEvent event =
+ SyntheticWebMouseWheelEventBuilder::Build(-5, 0, 0, true);
+ event.x = 100;
+ event.y = 200;
+ host_->ForwardWheelEvent(event);
+ ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process_);
+ EXPECT_EQ(1u, latency_info.input_coordinates_size);
+ EXPECT_EQ(100, latency_info.input_coordinates[0].x);
+ EXPECT_EQ(200, latency_info.input_coordinates[0].y);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+
+ {
+ WebMouseEvent event =
+ SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove);
+ event.x = 300;
+ event.y = 400;
+ host_->ForwardMouseEvent(event);
+ ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process_);
+ EXPECT_EQ(1u, latency_info.input_coordinates_size);
+ EXPECT_EQ(300, latency_info.input_coordinates[0].x);
+ EXPECT_EQ(400, latency_info.input_coordinates[0].y);
+ SendInputEventACK(WebInputEvent::MouseMove, INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+
+ {
+ WebGestureEvent event = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollBegin, blink::WebGestureDeviceTouchscreen);
+ event.x = 500;
+ event.y = 600;
+ host_->ForwardGestureEvent(event);
+ ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process_);
+ EXPECT_EQ(1u, latency_info.input_coordinates_size);
+ EXPECT_EQ(500, latency_info.input_coordinates[0].x);
+ EXPECT_EQ(600, latency_info.input_coordinates[0].y);
+ SendInputEventACK(WebInputEvent::GestureScrollBegin,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+
+ {
+ PressTouchPoint(700, 800);
+ PressTouchPoint(900, 1000);
+ PressTouchPoint(1100, 1200); // LatencyInfo only holds two coordinates.
+ SendTouchEvent();
+ ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process_);
+ EXPECT_EQ(2u, latency_info.input_coordinates_size);
+ EXPECT_EQ(700, latency_info.input_coordinates[0].x);
+ EXPECT_EQ(800, latency_info.input_coordinates[0].y);
+ EXPECT_EQ(900, latency_info.input_coordinates[1].x);
+ EXPECT_EQ(1000, latency_info.input_coordinates[1].y);
+ SendInputEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+
+ {
+ NativeWebKeyboardEvent event;
+ event.type = WebKeyboardEvent::KeyDown;
+ host_->ForwardKeyboardEvent(event);
+ ui::LatencyInfo latency_info = GetLatencyInfoFromInputEvent(process_);
+ EXPECT_EQ(0u, latency_info.input_coordinates_size);
+ SendInputEventACK(WebInputEvent::KeyDown, INPUT_EVENT_ACK_STATE_CONSUMED);
+ }
+}
+
TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
// RendererExited will delete the view.
host_->SetView(new TestView(host_.get()));
@@ -1437,4 +1480,18 @@ TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
ASSERT_FALSE(host_->input_router()->HasPendingEvents());
}
+// Regression test for http://crbug.com/401859.
+TEST_F(RenderWidgetHostTest, RendererExitedResetsIsHidden) {
+ // RendererExited will delete the view.
+ host_->SetView(new TestView(host_.get()));
+ host_->WasHidden();
+
+ ASSERT_TRUE(host_->is_hidden());
+ host_->RendererExited(base::TERMINATION_STATUS_PROCESS_CRASHED, -1);
+ ASSERT_FALSE(host_->is_hidden());
+
+ // Make sure the input router is in a fresh state.
+ ASSERT_FALSE(host_->input_router()->HasPendingEvents());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
index f4217357c75..e8a4f55e0c8 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -6,7 +6,7 @@
#include <android/bitmap.h>
-#include "base/android/sys_utils.h"
+#include "base/android/build_info.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -15,6 +15,7 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
#include "base/threading/worker_pool.h"
#include "cc/base/latency_info_swap_promise.h"
#include "cc/layers/delegated_frame_provider.h"
@@ -24,10 +25,14 @@
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
+#include "cc/output/viewport_selection_bound.h"
#include "cc/resources/single_release_callback.h"
#include "cc/trees/layer_tree_host.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
+#include "content/browser/android/composited_touch_handle_drawable.h"
#include "content/browser/android/content_view_core_impl.h"
+#include "content/browser/android/edge_effect.h"
+#include "content/browser/android/edge_effect_l.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/browser/android/overscroll_glow.h"
#include "content/browser/devtools/render_view_devtools_agent_host.h"
@@ -40,6 +45,8 @@
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_android.h"
+#include "content/browser/renderer_host/input/touch_selection_controller.h"
+#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -61,10 +68,11 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/android/window_android.h"
#include "ui/base/android/window_android_compositor.h"
-#include "ui/events/gesture_detection/gesture_config_helper.h"
+#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/gfx/android/device_display_info.h"
#include "ui/gfx/android/java_bitmap.h"
+#include "ui/gfx/android/view_configuration.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
@@ -80,6 +88,9 @@ const int kUndefinedOutputSurfaceId = -1;
// V1 saw errors of ~0.065 between computed window and content widths.
const float kMobileViewportWidthEpsilon = 0.15f;
+// Used for conditional creation of EdgeEffect types for overscroll.
+const int kKitKatMR2SDKVersion = 19;
+
static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
// Sends an acknowledgement to the renderer of a processed IME event.
@@ -94,8 +105,17 @@ void CopyFromCompositingSurfaceFinished(
const base::TimeTicks& start_time,
scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
+ TRACE_EVENT0(
+ "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
bitmap_pixels_lock.reset();
- release_callback->Run(0, false);
+ uint32 sync_point = 0;
+ if (result) {
+ GLHelper* gl_helper =
+ ImageTransportFactoryAndroid::GetInstance()->GetGLHelper();
+ sync_point = gl_helper->InsertSyncPoint();
+ }
+ bool lost_resource = sync_point == 0;
+ release_callback->Run(sync_point, lost_resource);
UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
base::TimeTicks::Now() - start_time);
callback.Run(result, *bitmap);
@@ -126,28 +146,81 @@ OverscrollGlow::DisplayParameters CreateOverscrollDisplayParameters(
// the viewport and offset by the distance of each viewport edge to the
// respective content edge.
OverscrollGlow::DisplayParameters params;
- params.size = gfx::ScaleSize(frame_metadata.viewport_size, scale_factor);
- params.edge_offsets[EdgeEffect::EDGE_TOP] =
+ params.size = gfx::ScaleSize(
+ frame_metadata.scrollable_viewport_size, scale_factor);
+ params.edge_offsets[OverscrollGlow::EDGE_TOP] =
-frame_metadata.root_scroll_offset.y() * scale_factor;
- params.edge_offsets[EdgeEffect::EDGE_LEFT] =
+ params.edge_offsets[OverscrollGlow::EDGE_LEFT] =
-frame_metadata.root_scroll_offset.x() * scale_factor;
- params.edge_offsets[EdgeEffect::EDGE_BOTTOM] =
+ params.edge_offsets[OverscrollGlow::EDGE_BOTTOM] =
(frame_metadata.root_layer_size.height() -
frame_metadata.root_scroll_offset.y() -
- frame_metadata.viewport_size.height()) * scale_factor;
- params.edge_offsets[EdgeEffect::EDGE_RIGHT] =
+ frame_metadata.scrollable_viewport_size.height()) *
+ scale_factor;
+ params.edge_offsets[OverscrollGlow::EDGE_RIGHT] =
(frame_metadata.root_layer_size.width() -
frame_metadata.root_scroll_offset.x() -
- frame_metadata.viewport_size.width()) * scale_factor;
- params.device_scale_factor = frame_metadata.device_scale_factor;
+ frame_metadata.scrollable_viewport_size.width()) *
+ scale_factor;
return params;
}
+bool UseEdgeEffectL() {
+ static bool use_edge_effect_l =
+ base::android::BuildInfo::GetInstance()->sdk_int() > kKitKatMR2SDKVersion;
+ return use_edge_effect_l;
+}
+
+scoped_ptr<EdgeEffectBase> CreateEdgeEffect(
+ ui::SystemUIResourceManager* resource_manager,
+ float device_scale_factor) {
+ DCHECK(resource_manager);
+ if (UseEdgeEffectL())
+ return scoped_ptr<EdgeEffectBase>(new EdgeEffectL(resource_manager));
+
+ return scoped_ptr<EdgeEffectBase>(
+ new EdgeEffect(resource_manager, device_scale_factor));
+}
+
+scoped_ptr<OverscrollGlow> CreateOverscrollEffect(
+ ContentViewCore* content_view_core) {
+ DCHECK(content_view_core);
+ ui::WindowAndroidCompositor* compositor =
+ content_view_core->GetWindowAndroid()->GetCompositor();
+ DCHECK(compositor);
+ ui::SystemUIResourceManager* system_resource_manager =
+ &compositor->GetSystemUIResourceManager();
+
+ if (UseEdgeEffectL())
+ EdgeEffectL::PreloadResources(system_resource_manager);
+ else
+ EdgeEffect::PreloadResources(system_resource_manager);
+
+ return make_scoped_ptr(
+ new OverscrollGlow(base::Bind(&CreateEdgeEffect,
+ system_resource_manager,
+ content_view_core->GetDpiScale())));
+}
+
+scoped_ptr<TouchSelectionController> CreateSelectionController(
+ TouchSelectionControllerClient* client,
+ ContentViewCore* content_view_core) {
+ DCHECK(client);
+ DCHECK(content_view_core);
+ int tap_timeout_ms = gfx::ViewConfiguration::GetTapTimeoutInMs();
+ int touch_slop_pixels = gfx::ViewConfiguration::GetTouchSlopInPixels();
+ return make_scoped_ptr(new TouchSelectionController(
+ client,
+ base::TimeDelta::FromMilliseconds(tap_timeout_ms),
+ touch_slop_pixels / content_view_core->GetDpiScale()));
+}
+
ui::GestureProvider::Config CreateGestureProviderConfig() {
ui::GestureProvider::Config config = ui::DefaultGestureProviderConfig();
config.disable_click_delay =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableClickDelay);
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableClickDelay);
return config;
}
@@ -158,13 +231,31 @@ bool HasFixedPageScale(const cc::CompositorFrameMetadata& frame_metadata) {
bool HasMobileViewport(const cc::CompositorFrameMetadata& frame_metadata) {
float window_width_dip =
- frame_metadata.page_scale_factor * frame_metadata.viewport_size.width();
+ frame_metadata.page_scale_factor *
+ frame_metadata.scrollable_viewport_size.width();
float content_width_css = frame_metadata.root_layer_size.width();
return content_width_css <= window_width_dip + kMobileViewportWidthEpsilon;
}
} // anonymous namespace
+ReadbackRequest::ReadbackRequest(
+ float scale,
+ SkColorType color_type,
+ gfx::Rect src_subrect,
+ const base::Callback<void(bool, const SkBitmap&)>& result_callback)
+ : scale_(scale),
+ color_type_(color_type),
+ src_subrect_(src_subrect),
+ result_callback_(result_callback) {
+}
+
+ReadbackRequest::ReadbackRequest() {
+}
+
+ReadbackRequest::~ReadbackRequest() {
+}
+
RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
uint32 output_id,
scoped_ptr<cc::CompositorFrame> output_frame)
@@ -176,25 +267,25 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
RenderWidgetHostImpl* widget_host,
ContentViewCoreImpl* content_view_core)
: host_(widget_host),
- needs_begin_frame_(false),
+ outstanding_vsync_requests_(0),
is_showing_(!widget_host->is_hidden()),
content_view_core_(NULL),
ime_adapter_android_(this),
cached_background_color_(SK_ColorWHITE),
last_output_surface_id_(kUndefinedOutputSurfaceId),
- weak_ptr_factory_(this),
- overscroll_effect_enabled_(!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableOverscrollEdgeEffect)),
- overscroll_effect_(OverscrollGlow::Create(overscroll_effect_enabled_)),
+ overscroll_effect_enabled_(
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableOverscrollEdgeEffect)),
gesture_provider_(CreateGestureProviderConfig(), this),
- flush_input_requested_(false),
+ gesture_text_selector_(this),
accelerated_surface_route_id_(0),
using_synchronous_compositor_(SynchronousCompositorImpl::FromID(
widget_host->GetProcess()->GetID(),
widget_host->GetRoutingID()) != NULL),
frame_evictor_(new DelegatedFrameEvictor(this)),
locks_on_frame_count_(0),
- observing_root_window_(false) {
+ observing_root_window_(false),
+ weak_ptr_factory_(this) {
host_->SetView(this);
SetContentViewCore(content_view_core);
ImageTransportFactoryAndroid::AddObserver(this);
@@ -204,6 +295,7 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
ImageTransportFactoryAndroid::RemoveObserver(this);
SetContentViewCore(NULL);
DCHECK(ack_callbacks_.empty());
+ DCHECK(readbacks_waiting_for_frame_.empty());
if (resource_collection_.get())
resource_collection_->SetClient(NULL);
}
@@ -218,6 +310,8 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived(
OnDidChangeBodyBackgroundColor)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
OnSetNeedsBeginFrame)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
+ OnTextInputStateChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_SmartClipDataExtracted,
OnSmartClipDataExtracted)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -248,12 +342,11 @@ void RenderWidgetHostViewAndroid::WasShown() {
if (!host_ || !host_->is_hidden())
return;
- host_->WasShown();
+ host_->WasShown(ui::LatencyInfo());
- if (content_view_core_ && !using_synchronous_compositor_) {
- content_view_core_->GetWindowAndroid()->AddObserver(this);
- content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
- observing_root_window_ = true;
+ if (content_view_core_) {
+ StartObservingRootWindow();
+ RequestVSyncUpdate(BEGIN_FRAME);
}
}
@@ -267,10 +360,7 @@ void RenderWidgetHostViewAndroid::WasHidden() {
// utilization.
host_->WasHidden();
- if (content_view_core_ && !using_synchronous_compositor_) {
- content_view_core_->GetWindowAndroid()->RemoveObserver(this);
- observing_root_window_ = false;
- }
+ StopObservingRootWindow();
}
void RenderWidgetHostViewAndroid::WasResized() {
@@ -287,15 +377,31 @@ void RenderWidgetHostViewAndroid::SetBounds(const gfx::Rect& rect) {
SetSize(rect.size());
}
+void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() {
+ while (!readbacks_waiting_for_frame_.empty()) {
+ ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
+ readback_request.GetResultCallback().Run(false, SkBitmap());
+ readbacks_waiting_for_frame_.pop();
+ }
+}
+
void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
float scale,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
gfx::Rect src_subrect,
- const base::Callback<void(bool, const SkBitmap&)>& result_callback) {
- if (!IsSurfaceAvailableForCopy()) {
+ CopyFromCompositingSurfaceCallback& result_callback) {
+ if (!host_ || host_->is_hidden()) {
result_callback.Run(false, SkBitmap());
return;
}
+ if (!IsSurfaceAvailableForCopy()) {
+ // The view is visible, probably the frame has not yet arrived.
+ // Just add the ReadbackRequest to queue and wait for frame arrival
+ // to get this request processed.
+ readbacks_waiting_for_frame_.push(
+ ReadbackRequest(scale, color_type, src_subrect, result_callback));
+ return;
+ }
gfx::Size bounds = layer_->bounds();
if (src_subrect.IsEmpty())
@@ -309,24 +415,41 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
gfx::Size dst_size(
gfx::ToCeiledSize(gfx::ScaleSize(bounds, scale / device_scale_factor)));
CopyFromCompositingSurface(
- src_subrect, dst_size, result_callback, bitmap_config);
+ src_subrect, dst_size, result_callback, color_type);
+}
+
+scoped_refptr<cc::DelegatedRendererLayer>
+RenderWidgetHostViewAndroid::CreateDelegatedLayerForFrameProvider() const {
+ DCHECK(frame_provider_.get());
+
+ scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
+ cc::DelegatedRendererLayer::Create(frame_provider_);
+ delegated_layer->SetBounds(content_size_in_layer_);
+ delegated_layer->SetIsDrawable(true);
+ delegated_layer->SetContentsOpaque(true);
+
+ return delegated_layer;
}
bool RenderWidgetHostViewAndroid::HasValidFrame() const {
if (!content_view_core_)
return false;
- if (!layer_)
+ if (!layer_.get())
return false;
if (texture_size_in_layer_.IsEmpty())
return false;
-
+ // This tell us whether a valid frame has arrived or not.
if (!frame_evictor_->HasFrame())
return false;
return true;
}
+gfx::Vector2dF RenderWidgetHostViewAndroid::GetLastScrollOffset() const {
+ return last_scroll_offset_;
+}
+
gfx::NativeView RenderWidgetHostViewAndroid::GetNativeView() const {
return content_view_core_->GetViewAndroid();
}
@@ -352,15 +475,15 @@ void RenderWidgetHostViewAndroid::MovePluginWindows(
void RenderWidgetHostViewAndroid::Focus() {
host_->Focus();
host_->SetInputMethodActive(true);
- if (overscroll_effect_enabled_)
+ if (overscroll_effect_)
overscroll_effect_->Enable();
}
void RenderWidgetHostViewAndroid::Blur() {
- host_->ExecuteEditCommand("Unselect", "");
host_->SetInputMethodActive(false);
host_->Blur();
- overscroll_effect_->Disable();
+ if (overscroll_effect_)
+ overscroll_effect_->Disable();
}
bool RenderWidgetHostViewAndroid::HasFocus() const {
@@ -379,7 +502,7 @@ void RenderWidgetHostViewAndroid::Show() {
return;
is_showing_ = true;
- if (layer_)
+ if (layer_.get())
layer_->SetHideLayerAndSubtree(false);
frame_evictor_->SetVisible(true);
@@ -391,10 +514,13 @@ void RenderWidgetHostViewAndroid::Hide() {
return;
is_showing_ = false;
- if (layer_ && locks_on_frame_count_ == 0)
+ if (layer_.get() && locks_on_frame_count_ == 0)
layer_->SetHideLayerAndSubtree(true);
frame_evictor_->SetVisible(false);
+ // We don't know if we will ever get a frame if we are hiding the renderer, so
+ // we need to cancel all requests
+ AbortPendingReadbackRequests();
WasHidden();
}
@@ -428,7 +554,7 @@ void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
last_frame_info_.reset();
}
- if (!is_showing_ && layer_)
+ if (!is_showing_ && layer_.get())
layer_->SetHideLayerAndSubtree(true);
}
}
@@ -475,11 +601,12 @@ gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
return content_view_core_->GetPhysicalBackingSize();
}
-float RenderWidgetHostViewAndroid::GetOverdrawBottomHeight() const {
+float RenderWidgetHostViewAndroid::GetTopControlsLayoutHeight() const {
if (!content_view_core_)
return 0.f;
- return content_view_core_->GetOverdrawBottomHeightDip();
+ // The amount that the viewport size given to Blink is shrunk by the URL-bar.
+ return content_view_core_->GetTopControlsLayoutHeightDip();
}
void RenderWidgetHostViewAndroid::UpdateCursor(const WebCursor& cursor) {
@@ -491,12 +618,29 @@ void RenderWidgetHostViewAndroid::SetIsLoading(bool is_loading) {
// is TabContentsDelegate.
}
+void RenderWidgetHostViewAndroid::TextInputTypeChanged(
+ ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
+ // Unused on Android, which uses OnTextInputChanged instead.
+}
+
long RenderWidgetHostViewAndroid::GetNativeImeAdapter() {
return reinterpret_cast<intptr_t>(&ime_adapter_android_);
}
-void RenderWidgetHostViewAndroid::TextInputStateChanged(
+void RenderWidgetHostViewAndroid::OnTextInputStateChanged(
const ViewHostMsg_TextInputState_Params& params) {
+ if (selection_controller_) {
+ // This call is semi-redundant with that in |OnFocusedNodeChanged|. The
+ // latter is guaranteed to be called before |OnSelectionBoundsChanged|,
+ // while this call is present to ensure consistency with IME after
+ // navigation and tab focus changes
+ const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE;
+ selection_controller_->OnSelectionEditable(is_editable_node);
+ }
+
// If the change is not originated from IME (e.g. Javascript, autofill),
// send back the renderer an acknowledgement, regardless of how we exit from
// this method.
@@ -509,7 +653,7 @@ void RenderWidgetHostViewAndroid::TextInputStateChanged(
content_view_core_->UpdateImeAdapter(
GetNativeImeAdapter(),
- static_cast<int>(params.type),
+ static_cast<int>(params.type), params.flags,
params.value, params.selection_start, params.selection_end,
params.composition_start, params.composition_end,
params.show_ime_if_needed, params.is_non_ime_change);
@@ -526,15 +670,13 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
}
void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
- if (enabled == needs_begin_frame_)
- return;
-
+ DCHECK(!using_synchronous_compositor_);
TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame",
"enabled", enabled);
- if (content_view_core_ && enabled)
- content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
-
- needs_begin_frame_ = enabled;
+ if (enabled)
+ RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
+ else
+ outstanding_vsync_requests_ &= ~PERSISTENT_BEGIN_FRAME;
}
void RenderWidgetHostViewAndroid::OnStartContentIntent(
@@ -544,13 +686,11 @@ void RenderWidgetHostViewAndroid::OnStartContentIntent(
}
void RenderWidgetHostViewAndroid::OnSmartClipDataExtracted(
- const base::string16& result) {
- // Custom serialization over IPC isn't allowed normally for security reasons.
- // Since this feature is only used in (single-process) WebView, there are no
- // security issues. Enforce that it's only called in single process mode.
- CHECK(RenderProcessHost::run_renderer_in_process());
+ const base::string16& text,
+ const base::string16& html,
+ const gfx::Rect rect) {
if (content_view_core_)
- content_view_core_->OnSmartClipDataExtracted(result);
+ content_view_core_->OnSmartClipDataExtracted(text, html, rect);
}
bool RenderWidgetHostViewAndroid::OnTouchEvent(
@@ -558,20 +698,40 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
if (!host_)
return false;
+ if (selection_controller_ &&
+ selection_controller_->WillHandleTouchEvent(event))
+ return true;
+
+ if (gesture_text_selector_.OnTouchEvent(event))
+ return true;
+
if (!gesture_provider_.OnTouchEvent(event))
return false;
- // Short-circuit touch forwarding if no touch handlers exist.
- if (!host_->ShouldForwardTouchEvent()) {
+ if (host_->ShouldForwardTouchEvent()) {
+ blink::WebTouchEvent web_event = CreateWebTouchEventFromMotionEvent(event);
+ host_->ForwardTouchEventWithLatencyInfo(web_event,
+ CreateLatencyInfo(web_event));
+ } else {
const bool event_consumed = false;
gesture_provider_.OnTouchEventAck(event_consumed);
- return true;
}
- SendTouchEvent(CreateWebTouchEventFromMotionEvent(event));
+ // Send a proactive BeginFrame on the next vsync to reduce latency.
+ // This is good enough as long as the first touch event has Begin semantics
+ // and the actual scroll happens on the next vsync.
+ if (observing_root_window_)
+ RequestVSyncUpdate(BEGIN_FRAME);
+
return true;
}
+bool RenderWidgetHostViewAndroid::OnTouchHandleEvent(
+ const ui::MotionEvent& event) {
+ return selection_controller_ &&
+ selection_controller_->WillHandleTouchEvent(event);
+}
+
void RenderWidgetHostViewAndroid::ResetGestureDetection() {
const ui::MotionEvent* current_down_event =
gesture_provider_.GetCurrentDownEvent();
@@ -596,8 +756,16 @@ void RenderWidgetHostViewAndroid::ImeCancelComposition() {
ime_adapter_android_.CancelComposition();
}
+void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
+ const gfx::Range& range,
+ const std::vector<gfx::Rect>& character_bounds) {
+ ime_adapter_android_.SetCharacterBounds(character_bounds);
+}
+
void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
ime_adapter_android_.FocusedNodeChanged(is_editable_node);
+ if (selection_controller_)
+ selection_controller_->OnSelectionEditable(is_editable_node);
}
void RenderWidgetHostViewAndroid::RenderProcessGone(
@@ -625,8 +793,17 @@ void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
const gfx::Range& range) {
RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
- if (text.empty() || range.is_empty() || !content_view_core_)
+ if (selection_controller_)
+ selection_controller_->OnSelectionEmpty(text.empty());
+
+ if (!content_view_core_)
+ return;
+ if (range.is_empty()) {
+ content_view_core_->OnSelectionChanged("");
return;
+ }
+
+ DCHECK(!text.empty());
size_t pos = range.GetMin() - offset;
size_t n = range.length();
@@ -643,25 +820,23 @@ void RenderWidgetHostViewAndroid::SelectionChanged(const base::string16& text,
void RenderWidgetHostViewAndroid::SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) {
- if (content_view_core_) {
- content_view_core_->OnSelectionBoundsChanged(params);
- }
+ NOTREACHED() << "Selection bounds should be routed through the compositor.";
}
-void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
-}
-
-void RenderWidgetHostViewAndroid::SetBackgroundOpaque(bool opaque) {
- RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
- host_->SetBackgroundOpaque(opaque);
+void RenderWidgetHostViewAndroid::SetBackgroundColor(SkColor color) {
+ RenderWidgetHostViewBase::SetBackgroundColor(color);
+ host_->SetBackgroundOpaque(GetBackgroundOpaque());
+ OnDidChangeBodyBackgroundColor(color);
}
void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config bitmap_config) {
- if (!IsReadbackConfigSupported(bitmap_config)) {
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) {
+ TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurface");
+ if ((!host_ || host_->is_hidden()) ||
+ !IsReadbackConfigSupported(color_type)) {
callback.Run(false, SkBitmap());
return;
}
@@ -680,7 +855,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
if (using_synchronous_compositor_) {
SynchronousCopyContents(src_subrect_in_pixel, dst_size_in_pixel, callback,
- bitmap_config);
+ color_type);
UMA_HISTOGRAM_TIMES("Compositing.CopyFromSurfaceTimeSynchronous",
base::TimeTicks::Now() - start_time);
return;
@@ -693,13 +868,10 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
ui::WindowAndroidCompositor* compositor =
content_view_core_->GetWindowAndroid()->GetCompositor();
DCHECK(compositor);
- DCHECK(frame_provider_);
+ DCHECK(frame_provider_.get());
scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
- cc::DelegatedRendererLayer::Create(frame_provider_);
- delegated_layer->SetBounds(content_size_in_layer_);
+ CreateDelegatedLayerForFrameProvider();
delegated_layer->SetHideLayerAndSubtree(true);
- delegated_layer->SetIsDrawable(true);
- delegated_layer->SetContentsOpaque(true);
compositor->AttachLayerForReadback(delegated_layer);
readback_layer = delegated_layer;
@@ -707,7 +879,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
base::Bind(&RenderWidgetHostViewAndroid::
PrepareTextureCopyOutputResultForDelegatedReadback,
dst_size_in_pixel,
- bitmap_config,
+ color_type,
start_time,
readback_layer,
callback));
@@ -728,11 +900,11 @@ bool RenderWidgetHostViewAndroid::CanCopyToVideoFrame() const {
}
void RenderWidgetHostViewAndroid::ShowDisambiguationPopup(
- const gfx::Rect& target_rect, const SkBitmap& zoomed_bitmap) {
+ const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) {
if (!content_view_core_)
return;
- content_view_core_->ShowDisambiguationPopup(target_rect, zoomed_bitmap);
+ content_view_core_->ShowDisambiguationPopup(rect_pixels, zoomed_bitmap);
}
scoped_ptr<SyntheticGestureTarget>
@@ -755,7 +927,7 @@ void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
uint32 output_surface_id) {
- DCHECK(resource_collection_);
+ DCHECK(resource_collection_.get());
cc::CompositorFrameAck ack;
resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
@@ -778,6 +950,9 @@ void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
RemoveLayers();
frame_provider_ = NULL;
layer_ = NULL;
+ // This gets called when ever any eviction, loosing resources, swapping
+ // problems are encountered and so we abort any pending readbacks here.
+ AbortPendingReadbackRequests();
}
void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
@@ -814,7 +989,7 @@ void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
resource_collection_ = new cc::DelegatedFrameResourceCollection;
resource_collection_->SetClient(this);
}
- if (!frame_provider_ ||
+ if (!frame_provider_.get() ||
texture_size_in_layer_ != frame_provider_->frame_size()) {
RemoveLayers();
frame_provider_ = new cc::DelegatedFrameProvider(
@@ -847,21 +1022,22 @@ void RenderWidgetHostViewAndroid::ComputeContentsSize(
const cc::CompositorFrameMetadata& frame_metadata) {
// Calculate the content size. This should be 0 if the texture_size is 0.
gfx::Vector2dF offset;
- if (texture_size_in_layer_.GetArea() > 0)
- offset = frame_metadata.location_bar_content_translation;
- offset.set_y(offset.y() + frame_metadata.overdraw_bottom_height);
- offset.Scale(frame_metadata.device_scale_factor);
- content_size_in_layer_ =
- gfx::Size(texture_size_in_layer_.width() - offset.x(),
- texture_size_in_layer_.height() - offset.y());
-
- overscroll_effect_->UpdateDisplayParameters(
- CreateOverscrollDisplayParameters(frame_metadata));
+ if (texture_size_in_layer_.IsEmpty())
+ content_size_in_layer_ = gfx::Size();
+ content_size_in_layer_ = gfx::ToCeiledSize(gfx::ScaleSize(
+ frame_metadata.scrollable_viewport_size,
+ frame_metadata.device_scale_factor * frame_metadata.page_scale_factor));
+
+ if (overscroll_effect_) {
+ overscroll_effect_->UpdateDisplayParameters(
+ CreateOverscrollDisplayParameters(frame_metadata));
+ }
}
void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
+ last_scroll_offset_ = frame->metadata.root_scroll_offset;
if (!frame->delegated_frame_data) {
LOG(ERROR) << "Non-delegated renderer path no longer supported";
return;
@@ -873,7 +1049,7 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
return;
}
- if (layer_ && layer_->layer_tree_host()) {
+ if (layer_.get() && layer_->layer_tree_host()) {
for (size_t i = 0; i < frame->metadata.latency_info.size(); i++) {
scoped_ptr<cc::SwapPromise> swap_promise(
new cc::LatencyInfoSwapPromise(frame->metadata.latency_info[i]));
@@ -891,7 +1067,21 @@ void RenderWidgetHostViewAndroid::InternalSwapCompositorFrame(
SwapDelegatedFrame(output_surface_id, frame->delegated_frame_data.Pass());
frame_evictor_->SwappedFrame(!host_->is_hidden());
+ // As the metadata update may trigger view invalidation, always call it after
+ // any potential compositor scheduling.
OnFrameMetadataUpdated(frame->metadata);
+ // Check if we have any pending readbacks, see if we have a frame available
+ // and process them here.
+ if (!readbacks_waiting_for_frame_.empty()) {
+ while (!readbacks_waiting_for_frame_.empty()) {
+ ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front();
+ GetScaledContentBitmap(readback_request.GetScale(),
+ readback_request.GetColorFormat(),
+ readback_request.GetCaptureRect(),
+ readback_request.GetResultCallback());
+ readbacks_waiting_for_frame_.pop();
+ }
+ }
}
void RenderWidgetHostViewAndroid::OnSwapCompositorFrame(
@@ -923,16 +1113,19 @@ void RenderWidgetHostViewAndroid::RetainFrame(
void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
const cc::CompositorFrameMetadata& frame_metadata) {
+ if (!content_view_core_)
+ return;
+
// This is a subset of OnSwapCompositorFrame() used in the synchronous
// compositor flow.
OnFrameMetadataUpdated(frame_metadata);
ComputeContentsSize(frame_metadata);
// DevTools ScreenCast support for Android WebView.
- if (DevToolsAgentHost::HasFor(RenderViewHost::From(GetRenderWidgetHost()))) {
+ WebContents* web_contents = content_view_core_->GetWebContents();
+ if (DevToolsAgentHost::HasFor(web_contents)) {
scoped_refptr<DevToolsAgentHost> dtah =
- DevToolsAgentHost::GetOrCreateFor(
- RenderViewHost::From(GetRenderWidgetHost()));
+ DevToolsAgentHost::GetOrCreateFor(web_contents);
// Unblock the compositor.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -943,15 +1136,64 @@ void RenderWidgetHostViewAndroid::SynchronousFrameMetadata(
}
void RenderWidgetHostViewAndroid::SetOverlayVideoMode(bool enabled) {
- if (layer_)
+ if (layer_.get())
layer_->SetContentsOpaque(!enabled);
}
+bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
+ // The synchronous (WebView) compositor does not have a proper browser
+ // compositor with which to drive animations.
+ return !using_synchronous_compositor_;
+}
+
+void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
+ DCHECK(content_view_core_);
+ DCHECK(!using_synchronous_compositor_);
+ content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
+}
+
+void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
+ MoveCaret(gfx::Point(position.x(), position.y()));
+}
+
+void RenderWidgetHostViewAndroid::MoveRangeSelectionExtent(
+ const gfx::PointF& extent) {
+ DCHECK(content_view_core_);
+ content_view_core_->MoveRangeSelectionExtent(extent);
+}
+
+void RenderWidgetHostViewAndroid::SelectBetweenCoordinates(
+ const gfx::PointF& base,
+ const gfx::PointF& extent) {
+ DCHECK(content_view_core_);
+ content_view_core_->SelectBetweenCoordinates(base, extent);
+}
+
+void RenderWidgetHostViewAndroid::OnSelectionEvent(
+ SelectionEventType event,
+ const gfx::PointF& position) {
+ DCHECK(content_view_core_);
+ content_view_core_->OnSelectionEvent(event, position);
+}
+
+scoped_ptr<TouchHandleDrawable> RenderWidgetHostViewAndroid::CreateDrawable() {
+ DCHECK(content_view_core_);
+ if (using_synchronous_compositor_)
+ return content_view_core_->CreatePopupTouchHandleDrawable();
+
+ return scoped_ptr<TouchHandleDrawable>(new CompositedTouchHandleDrawable(
+ content_view_core_->GetLayer().get(),
+ content_view_core_->GetDpiScale(),
+ // Use the activity context (instead of the application context) to ensure
+ // proper handle theming.
+ content_view_core_->GetContext().obj()));
+}
+
void RenderWidgetHostViewAndroid::SynchronousCopyContents(
const gfx::Rect& src_subrect_in_pixel,
const gfx::Size& dst_size_in_pixel,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) {
+ const SkColorType color_type) {
SynchronousCompositor* compositor =
SynchronousCompositorImpl::FromID(host_->GetProcess()->GetID(),
host_->GetRoutingID());
@@ -961,10 +1203,10 @@ void RenderWidgetHostViewAndroid::SynchronousCopyContents(
}
SkBitmap bitmap;
- bitmap.setConfig(config,
- dst_size_in_pixel.width(),
- dst_size_in_pixel.height());
- bitmap.allocPixels();
+ bitmap.allocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
+ dst_size_in_pixel.height(),
+ color_type,
+ kPremul_SkAlphaType));
SkCanvas canvas(bitmap);
canvas.scale(
(float)dst_size_in_pixel.width() / (float)src_subrect_in_pixel.width(),
@@ -987,6 +1229,12 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
if (!content_view_core_)
return;
+
+ if (selection_controller_) {
+ selection_controller_->OnSelectionBoundsChanged(
+ frame_metadata.selection_start, frame_metadata.selection_end);
+ }
+
// All offsets and sizes are in CSS pixels.
content_view_core_->UpdateFrameInfo(
frame_metadata.root_scroll_offset,
@@ -994,10 +1242,9 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
gfx::Vector2dF(frame_metadata.min_page_scale_factor,
frame_metadata.max_page_scale_factor),
frame_metadata.root_layer_size,
- frame_metadata.viewport_size,
+ frame_metadata.scrollable_viewport_size,
frame_metadata.location_bar_offset,
- frame_metadata.location_bar_content_translation,
- frame_metadata.overdraw_bottom_height);
+ frame_metadata.location_bar_content_translation);
#if defined(VIDEO_HOLE)
if (host_ && host_->IsRenderView()) {
RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
@@ -1007,17 +1254,11 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
#endif // defined(VIDEO_HOLE)
}
-void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int host_id,
- int route_id) {
+void RenderWidgetHostViewAndroid::AcceleratedSurfaceInitialized(int route_id) {
+ // TODO: remove need for the surface id here
accelerated_surface_route_id_ = route_id;
}
-void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) {
- NOTREACHED() << "Need --composite-to-mailbox or --enable-delegated-renderer";
-}
-
void RenderWidgetHostViewAndroid::AttachLayers() {
if (!content_view_core_)
return;
@@ -1025,7 +1266,7 @@ void RenderWidgetHostViewAndroid::AttachLayers() {
return;
content_view_core_->AttachLayer(layer_);
- if (overscroll_effect_enabled_)
+ if (overscroll_effect_)
overscroll_effect_->Enable();
layer_->SetHideLayerAndSubtree(!is_showing_);
}
@@ -1033,39 +1274,85 @@ void RenderWidgetHostViewAndroid::AttachLayers() {
void RenderWidgetHostViewAndroid::RemoveLayers() {
if (!content_view_core_)
return;
+
if (!layer_.get())
return;
content_view_core_->RemoveLayer(layer_);
- overscroll_effect_->Disable();
+ if (overscroll_effect_)
+ overscroll_effect_->Disable();
}
-void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
- content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
+void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) {
+ // The synchronous compositor does not requre BeginFrame messages.
+ if (using_synchronous_compositor_)
+ requests &= FLUSH_INPUT;
+
+ bool should_request_vsync = !outstanding_vsync_requests_ && requests;
+ outstanding_vsync_requests_ |= requests;
+ // Note that if we're not currently observing the root window, outstanding
+ // vsync requests will be pushed if/when we resume observing in
+ // |StartObservingRootWindow()|.
+ if (observing_root_window_ && should_request_vsync)
+ content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
}
-bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
- return overscroll_effect_->Animate(frame_time);
+void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
+ DCHECK(content_view_core_);
+ if (observing_root_window_)
+ return;
+
+ observing_root_window_ = true;
+ content_view_core_->GetWindowAndroid()->AddObserver(this);
+
+ // Clear existing vsync requests to allow a request to the new window.
+ uint32 outstanding_vsync_requests = outstanding_vsync_requests_;
+ outstanding_vsync_requests_ = 0;
+ RequestVSyncUpdate(outstanding_vsync_requests);
}
-void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) {
- NOTREACHED();
+void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
+ if (!content_view_core_) {
+ DCHECK(!observing_root_window_);
+ return;
+ }
+
+ if (!observing_root_window_)
+ return;
+
+ observing_root_window_ = false;
+ content_view_core_->GetWindowAndroid()->RemoveObserver(this);
}
-void RenderWidgetHostViewAndroid::AcceleratedSurfaceSuspend() {
- NOTREACHED();
+void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
+ base::TimeDelta vsync_period) {
+ TRACE_EVENT1("cc", "RenderWidgetHostViewAndroid::SendBeginFrame",
+ "frame_time_us", frame_time.ToInternalValue());
+ base::TimeTicks display_time = frame_time + vsync_period;
+
+ base::TimeTicks deadline =
+ display_time - host_->GetEstimatedBrowserCompositeTime();
+
+ host_->Send(new ViewMsg_BeginFrame(
+ host_->GetRoutingID(),
+ cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
}
-void RenderWidgetHostViewAndroid::AcceleratedSurfaceRelease() {
- NOTREACHED();
+bool RenderWidgetHostViewAndroid::Animate(base::TimeTicks frame_time) {
+ bool needs_animate =
+ overscroll_effect_ ? overscroll_effect_->Animate(frame_time) : false;
+ if (selection_controller_)
+ needs_animate |= selection_controller_->Animate(frame_time);
+ return needs_animate;
}
void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
if (layer_.get())
DestroyDelegatedContent();
frame_evictor_->DiscardedFrame();
+ // We are evicting the delegated frame,
+ // so there should be no pending readback requests
+ DCHECK(readbacks_waiting_for_frame_.empty());
}
bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
@@ -1087,7 +1374,7 @@ gfx::Rect RenderWidgetHostViewAndroid::GetBoundsInRootWindow() {
gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() {
gfx::GLSurfaceHandle handle =
- gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT);
+ gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
if (CompositorImpl::IsInitialized()) {
handle.parent_client_id =
ImageTransportFactoryAndroid::GetInstance()->GetChannelID();
@@ -1104,12 +1391,32 @@ void RenderWidgetHostViewAndroid::ProcessAckedTouchEvent(
void RenderWidgetHostViewAndroid::GestureEventAck(
const blink::WebGestureEvent& event,
InputEventAckState ack_result) {
+ // The overscroll effect requires an explicit release signal that may not be
+ // sent from the renderer compositor.
+ if (event.type == blink::WebInputEvent::GestureScrollEnd ||
+ event.type == blink::WebInputEvent::GestureFlingStart) {
+ DidOverscroll(DidOverscrollParams());
+ }
+
if (content_view_core_)
content_view_core_->OnGestureEventAck(event, ack_result);
}
InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
const blink::WebInputEvent& input_event) {
+ if (selection_controller_) {
+ switch (input_event.type) {
+ case blink::WebInputEvent::GestureLongPress:
+ selection_controller_->OnLongPressEvent();
+ break;
+ case blink::WebInputEvent::GestureTap:
+ selection_controller_->OnTapEvent();
+ break;
+ default:
+ break;
+ }
+ }
+
if (content_view_core_ &&
content_view_core_->FilterInputEvent(input_event))
return INPUT_EVENT_ACK_STATE_CONSUMED;
@@ -1136,27 +1443,30 @@ InputEventAckState RenderWidgetHostViewAndroid::FilterInputEvent(
}
void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
- if (flush_input_requested_ || !content_view_core_)
- return;
TRACE_EVENT0("input", "RenderWidgetHostViewAndroid::OnSetNeedsFlushInput");
- flush_input_requested_ = true;
- content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
-}
-
-void RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManagerIfNeeded() {
- if (!host_ || host_->accessibility_mode() != AccessibilityModeComplete)
- return;
-
- if (!GetBrowserAccessibilityManager()) {
- base::android::ScopedJavaLocalRef<jobject> obj;
- if (content_view_core_)
- obj = content_view_core_->GetJavaObject();
- SetBrowserAccessibilityManager(
- new BrowserAccessibilityManagerAndroid(
- obj,
- BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
- host_));
- }
+ RequestVSyncUpdate(FLUSH_INPUT);
+}
+
+BrowserAccessibilityManager*
+ RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) {
+ // TODO(dmazzoni): Currently there can only be one
+ // BrowserAccessibilityManager per ContentViewCore, so return NULL
+ // if there's already a BrowserAccessibilityManager for the main
+ // frame. Eventually, in order to support cross-process iframes on
+ // Android we'll need to add support for a
+ // BrowserAccessibilityManager for a child frame.
+ // http://crbug.com/423846
+ if (!host_ || host_->GetRootBrowserAccessibilityManager())
+ return NULL;
+
+ base::android::ScopedJavaLocalRef<jobject> obj;
+ if (content_view_core_)
+ obj = content_view_core_->GetJavaObject();
+ return new BrowserAccessibilityManagerAndroid(
+ obj,
+ BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
+ delegate);
}
bool RenderWidgetHostViewAndroid::LockMouse() {
@@ -1176,20 +1486,6 @@ void RenderWidgetHostViewAndroid::SendKeyEvent(
host_->ForwardKeyboardEvent(event);
}
-void RenderWidgetHostViewAndroid::SendTouchEvent(
- const blink::WebTouchEvent& event) {
- if (host_)
- host_->ForwardTouchEventWithLatencyInfo(event, CreateLatencyInfo(event));
-
- // Send a proactive BeginFrame on the next vsync to reduce latency.
- // This is good enough as long as the first touch event has Begin semantics
- // and the actual scroll happens on the next vsync.
- // TODO: Is this actually still needed?
- if (content_view_core_) {
- content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
- }
-}
-
void RenderWidgetHostViewAndroid::SendMouseEvent(
const blink::WebMouseEvent& event) {
if (host_)
@@ -1205,8 +1501,8 @@ void RenderWidgetHostViewAndroid::SendMouseWheelEvent(
void RenderWidgetHostViewAndroid::SendGestureEvent(
const blink::WebGestureEvent& event) {
// Sending a gesture that may trigger overscroll should resume the effect.
- if (overscroll_effect_enabled_)
- overscroll_effect_->Enable();
+ if (overscroll_effect_)
+ overscroll_effect_->Enable();
if (host_)
host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
@@ -1217,25 +1513,62 @@ void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
host_->MoveCaret(point);
}
+void RenderWidgetHostViewAndroid::DismissTextHandles() {
+ if (selection_controller_)
+ selection_controller_->HideAndDisallowShowingAutomatically();
+}
+
+void RenderWidgetHostViewAndroid::SetTextHandlesTemporarilyHidden(bool hidden) {
+ if (selection_controller_)
+ selection_controller_->SetTemporarilyHidden(hidden);
+}
+
+void RenderWidgetHostViewAndroid::OnShowingPastePopup(
+ const gfx::PointF& point) {
+ if (!selection_controller_)
+ return;
+
+ // As the paste popup may be triggered *before* the bounds and editability
+ // of the region have been updated, explicitly set the properties now.
+ // TODO(jdduke): Remove this workaround when auxiliary paste popup
+ // notifications are no longer required, crbug.com/398170.
+ cc::ViewportSelectionBound insertion_bound;
+ insertion_bound.type = cc::SELECTION_BOUND_CENTER;
+ insertion_bound.visible = true;
+ insertion_bound.edge_top = point;
+ insertion_bound.edge_bottom = point;
+ DismissTextHandles();
+ ShowSelectionHandlesAutomatically();
+ selection_controller_->OnSelectionEditable(true);
+ selection_controller_->OnSelectionEmpty(true);
+ selection_controller_->OnSelectionBoundsChanged(insertion_bound,
+ insertion_bound);
+}
+
SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
return cached_background_color_;
}
void RenderWidgetHostViewAndroid::DidOverscroll(
const DidOverscrollParams& params) {
- if (!content_view_core_ || !layer_ || !is_showing_)
+ if (!content_view_core_ || !layer_.get() || !is_showing_)
return;
const float device_scale_factor = content_view_core_->GetDpiScale();
- if (overscroll_effect_->OnOverscrolled(
- content_view_core_->GetLayer(),
+
+ if (overscroll_effect_ &&
+ overscroll_effect_->OnOverscrolled(
+ content_view_core_->GetLayer().get(),
base::TimeTicks::Now(),
gfx::ScaleVector2d(params.accumulated_overscroll,
device_scale_factor),
gfx::ScaleVector2d(params.latest_overscroll_delta,
device_scale_factor),
gfx::ScaleVector2d(params.current_fling_velocity,
- device_scale_factor))) {
+ device_scale_factor),
+ gfx::ScaleVector2d(
+ params.causal_event_viewport_point.OffsetFromOrigin(),
+ device_scale_factor))) {
SetNeedsAnimate();
}
}
@@ -1248,37 +1581,44 @@ void RenderWidgetHostViewAndroid::DidStopFlinging() {
void RenderWidgetHostViewAndroid::SetContentViewCore(
ContentViewCoreImpl* content_view_core) {
RemoveLayers();
- if (observing_root_window_ && content_view_core_) {
- content_view_core_->GetWindowAndroid()->RemoveObserver(this);
- observing_root_window_ = false;
- }
+ StopObservingRootWindow();
bool resize = false;
if (content_view_core != content_view_core_) {
+ overscroll_effect_.reset();
+ selection_controller_.reset();
ReleaseLocksOnSurface();
resize = true;
}
content_view_core_ = content_view_core;
- if (GetBrowserAccessibilityManager()) {
+ BrowserAccessibilityManager* manager = NULL;
+ if (host_)
+ manager = host_->GetRootBrowserAccessibilityManager();
+ if (manager) {
base::android::ScopedJavaLocalRef<jobject> obj;
if (content_view_core_)
obj = content_view_core_->GetJavaObject();
- GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerAndroid()->
- SetContentViewCore(obj);
+ manager->ToBrowserAccessibilityManagerAndroid()->SetContentViewCore(obj);
}
AttachLayers();
- if (content_view_core_ && !using_synchronous_compositor_) {
- content_view_core_->GetWindowAndroid()->AddObserver(this);
- observing_root_window_ = true;
- if (needs_begin_frame_)
- content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
- }
- if (resize && content_view_core_)
+ if (!content_view_core_)
+ return;
+
+ StartObservingRootWindow();
+
+ if (resize)
WasResized();
+
+ if (!selection_controller_)
+ selection_controller_ = CreateSelectionController(this, content_view_core_);
+
+ if (overscroll_effect_enabled_ && !overscroll_effect_ &&
+ content_view_core_->GetWindowAndroid()->GetCompositor())
+ overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
}
void RenderWidgetHostViewAndroid::RunAckCallbacks() {
@@ -1297,10 +1637,17 @@ void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
RunAckCallbacks();
}
+void RenderWidgetHostViewAndroid::OnAttachCompositor() {
+ DCHECK(content_view_core_);
+ if (overscroll_effect_enabled_ && !overscroll_effect_)
+ overscroll_effect_ = CreateOverscrollEffect(content_view_core_);
+}
+
void RenderWidgetHostViewAndroid::OnDetachCompositor() {
DCHECK(content_view_core_);
DCHECK(!using_synchronous_compositor_);
RunAckCallbacks();
+ overscroll_effect_.reset();
}
void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
@@ -1309,27 +1656,19 @@ void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time,
if (!host_)
return;
- if (flush_input_requested_) {
- flush_input_requested_ = false;
- host_->FlushInput();
- }
-
- TRACE_EVENT0("cc", "RenderWidgetHostViewAndroid::SendBeginFrame");
- base::TimeTicks display_time = frame_time + vsync_period;
-
- // TODO(brianderson): Use adaptive draw-time estimation.
- base::TimeDelta estimated_browser_composite_time =
- base::TimeDelta::FromMicroseconds(
- (1.0f * base::Time::kMicrosecondsPerSecond) / (3.0f * 60));
+ const uint32 current_vsync_requests = outstanding_vsync_requests_;
+ outstanding_vsync_requests_ = 0;
- base::TimeTicks deadline = display_time - estimated_browser_composite_time;
+ if (current_vsync_requests & FLUSH_INPUT)
+ host_->FlushInput();
- host_->Send(new ViewMsg_BeginFrame(
- host_->GetRoutingID(),
- cc::BeginFrameArgs::Create(frame_time, deadline, vsync_period)));
+ if (current_vsync_requests & BEGIN_FRAME ||
+ current_vsync_requests & PERSISTENT_BEGIN_FRAME) {
+ SendBeginFrame(frame_time, vsync_period);
+ }
- if (needs_begin_frame_)
- content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
+ if (current_vsync_requests & PERSISTENT_BEGIN_FRAME)
+ RequestVSyncUpdate(PERSISTENT_BEGIN_FRAME);
}
void RenderWidgetHostViewAndroid::OnAnimate(base::TimeTicks begin_frame_time) {
@@ -1342,41 +1681,44 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
if (layer_.get())
DestroyDelegatedContent();
DCHECK(ack_callbacks_.empty());
+ // We should not loose a frame if we have readback requests pending.
+ DCHECK(readbacks_waiting_for_frame_.empty());
}
// static
void
RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::TimeTicks& start_time,
scoped_refptr<cc::Layer> readback_layer,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result) {
readback_layer->RemoveFromParent();
PrepareTextureCopyOutputResult(
- dst_size_in_pixel, config, start_time, callback, result.Pass());
+ dst_size_in_pixel, color_type, start_time, callback, result.Pass());
}
// static
void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config bitmap_config,
+ const SkColorType color_type,
const base::TimeTicks& start_time,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result) {
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, false, SkBitmap()));
+ TRACE_EVENT0("cc",
+ "RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
return;
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- bitmap->setConfig(bitmap_config,
- dst_size_in_pixel.width(),
- dst_size_in_pixel.height(),
- 0, kOpaque_SkAlphaType);
- if (!bitmap->allocPixels())
+ if (!bitmap->tryAllocPixels(SkImageInfo::Make(dst_size_in_pixel.width(),
+ dst_size_in_pixel.height(),
+ color_type,
+ kOpaque_SkAlphaType)))
return;
ImageTransportFactoryAndroid* factory =
@@ -1406,7 +1748,7 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
gfx::Rect(result->size()),
dst_size_in_pixel,
pixels,
- bitmap_config,
+ color_type,
base::Bind(&CopyFromCompositingSurfaceFinished,
callback,
base::Passed(&release_callback),
@@ -1417,24 +1759,45 @@ void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
}
bool RenderWidgetHostViewAndroid::IsReadbackConfigSupported(
- SkBitmap::Config bitmap_config) {
+ SkColorType color_type) {
ImageTransportFactoryAndroid* factory =
ImageTransportFactoryAndroid::GetInstance();
GLHelper* gl_helper = factory->GetGLHelper();
if (!gl_helper)
return false;
- return gl_helper->IsReadbackConfigSupported(bitmap_config);
+ return gl_helper->IsReadbackConfigSupported(color_type);
}
-SkBitmap::Config RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
+SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() {
// Define the criteria here. If say the 16 texture readback is
// supported we should go with that (this degrades quality)
// or stick back to the default format.
- if (base::android::SysUtils::IsLowEndDevice()) {
- if (IsReadbackConfigSupported(SkBitmap::kRGB_565_Config))
- return SkBitmap::kRGB_565_Config;
+ if (base::SysInfo::IsLowEndDevice()) {
+ if (IsReadbackConfigSupported(kRGB_565_SkColorType))
+ return kRGB_565_SkColorType;
}
- return SkBitmap::kARGB_8888_Config;
+ return kN32_SkColorType;
+}
+
+void RenderWidgetHostViewAndroid::ShowSelectionHandlesAutomatically() {
+ // Fake a long press to allow automatic selection handle showing.
+ if (selection_controller_)
+ selection_controller_->OnLongPressEvent();
+}
+
+void RenderWidgetHostViewAndroid::SelectRange(
+ float x1, float y1, float x2, float y2) {
+ if (content_view_core_)
+ static_cast<WebContentsImpl*>(content_view_core_->GetWebContents())->
+ SelectRange(gfx::Point(x1, y1), gfx::Point(x2, y2));
+}
+
+void RenderWidgetHostViewAndroid::LongPress(
+ base::TimeTicks time, float x, float y) {
+ blink::WebGestureEvent long_press = WebGestureEventBuilder::Build(
+ blink::WebInputEvent::GestureLongPress,
+ (time - base::TimeTicks()).InSecondsF(), x, y);
+ SendGestureEvent(long_press);
}
// static
@@ -1447,6 +1810,8 @@ void RenderWidgetHostViewBase::GetDefaultScreenInfo(
results->availableRect = display.work_area();
results->deviceScaleFactor = display.device_scale_factor();
results->orientationAngle = display.RotationAsDegree();
+ results->orientationType =
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display);
gfx::DeviceDisplayInfo info;
results->depth = info.GetBitsPerPixel();
results->depthPerComponent = info.GetBitsPerComponent();
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_android.h b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
index 4707734a8e8..129b773fbfc 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
@@ -20,6 +20,8 @@
#include "content/browser/renderer_host/delegated_frame_evictor.h"
#include "content/browser/renderer_host/image_transport_factory_android.h"
#include "content/browser/renderer_host/ime_adapter_android.h"
+#include "content/browser/renderer_host/input/gesture_text_selector.h"
+#include "content/browser/renderer_host/input/touch_selection_controller.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "gpu/command_buffer/common/mailbox.h"
@@ -32,9 +34,6 @@
struct ViewHostMsg_TextInputState_Params;
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
-
namespace cc {
class CopyOutputResult;
class DelegatedFrameProvider;
@@ -56,6 +55,29 @@ class RenderWidgetHostImpl;
struct DidOverscrollParams;
struct NativeWebKeyboardEvent;
+class ReadbackRequest {
+ public:
+ explicit ReadbackRequest(
+ float scale,
+ SkColorType color_type,
+ gfx::Rect src_subrect,
+ const base::Callback<void(bool, const SkBitmap&)>& result_callback);
+ ~ReadbackRequest();
+ float GetScale() { return scale_; }
+ SkColorType GetColorFormat() { return color_type_; }
+ const gfx::Rect GetCaptureRect() { return src_subrect_; }
+ const base::Callback<void(bool, const SkBitmap&)>& GetResultCallback() {
+ return result_callback_;
+ }
+
+ private:
+ ReadbackRequest();
+ float scale_;
+ SkColorType color_type_;
+ gfx::Rect src_subrect_;
+ base::Callback<void(bool, const SkBitmap&)> result_callback_;
+};
+
// -----------------------------------------------------------------------------
// See comments in render_widget_host_view.h about this class and its members.
// -----------------------------------------------------------------------------
@@ -65,142 +87,149 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
public ImageTransportFactoryAndroidObserver,
public ui::GestureProviderClient,
public ui::WindowAndroidObserver,
- public DelegatedFrameEvictorClient {
+ public DelegatedFrameEvictorClient,
+ public GestureTextSelectorClient,
+ public TouchSelectionControllerClient {
public:
RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
ContentViewCoreImpl* content_view_core);
virtual ~RenderWidgetHostViewAndroid();
// RenderWidgetHostView implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) override;
+ virtual void InitAsChild(gfx::NativeView parent_view) override;
virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
- const gfx::Rect& pos) OVERRIDE;
+ const gfx::Rect& pos) override;
virtual void InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) OVERRIDE;
- virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
- virtual void WasShown() OVERRIDE;
- virtual void WasHidden() OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void SetBounds(const gfx::Rect& rect) OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
+ RenderWidgetHostView* reference_host_view) override;
+ virtual RenderWidgetHost* GetRenderWidgetHost() const override;
+ virtual void WasShown() override;
+ virtual void WasHidden() override;
+ virtual void SetSize(const gfx::Size& size) override;
+ virtual void SetBounds(const gfx::Rect& rect) override;
+ virtual gfx::Vector2dF GetLastScrollOffset() const override;
+ virtual gfx::NativeView GetNativeView() const override;
+ virtual gfx::NativeViewId GetNativeViewId() const override;
+ virtual gfx::NativeViewAccessible GetNativeViewAccessible() override;
virtual void MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void Blur() OVERRIDE;
- virtual bool HasFocus() const OVERRIDE;
- virtual bool IsSurfaceAvailableForCopy() const OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsShowing() OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual gfx::Size GetPhysicalBackingSize() const OVERRIDE;
- virtual float GetOverdrawBottomHeight() const OVERRIDE;
- virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
- virtual void SetIsLoading(bool is_loading) OVERRIDE;
- virtual void TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) OVERRIDE;
- virtual void ImeCancelComposition() OVERRIDE;
- virtual void FocusedNodeChanged(bool is_editable_node) OVERRIDE;
+ const std::vector<WebPluginGeometry>& moves) override;
+ virtual void Focus() override;
+ virtual void Blur() override;
+ virtual bool HasFocus() const override;
+ virtual bool IsSurfaceAvailableForCopy() const override;
+ virtual void Show() override;
+ virtual void Hide() override;
+ virtual bool IsShowing() override;
+ virtual gfx::Rect GetViewBounds() const override;
+ virtual gfx::Size GetPhysicalBackingSize() const override;
+ virtual float GetTopControlsLayoutHeight() const override;
+ virtual void UpdateCursor(const WebCursor& cursor) override;
+ virtual void SetIsLoading(bool is_loading) override;
+ virtual void TextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) override;
+ virtual void ImeCancelComposition() override;
+ virtual void ImeCompositionRangeChanged(
+ const gfx::Range& range,
+ const std::vector<gfx::Rect>& character_bounds) override;
+ virtual void FocusedNodeChanged(bool is_editable_node) override;
virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
+ int error_code) override;
+ virtual void Destroy() override;
+ virtual void SetTooltipText(const base::string16& tooltip_text) override;
virtual void SelectionChanged(const base::string16& text,
size_t offset,
- const gfx::Range& range) OVERRIDE;
+ const gfx::Range& range) override;
virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
- virtual void ScrollOffsetChanged() OVERRIDE;
- virtual void AcceleratedSurfaceInitialized(int host_id,
- int route_id) OVERRIDE;
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfaceSuspend() OVERRIDE;
- virtual void AcceleratedSurfaceRelease() OVERRIDE;
- virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void SetBackgroundOpaque(bool transparent) OVERRIDE;
+ const ViewHostMsg_SelectionBounds_Params& params) override;
+ virtual void AcceleratedSurfaceInitialized(int route_id) override;
+ virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
+ virtual void SetBackgroundColor(SkColor color) override;
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) OVERRIDE;
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) override;
virtual void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool CanCopyToVideoFrame() const OVERRIDE;
- virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
- virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
- virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
+ const base::Callback<void(bool)>& callback) override;
+ virtual bool CanCopyToVideoFrame() const override;
+ virtual void GetScreenInfo(blink::WebScreenInfo* results) override;
+ virtual gfx::Rect GetBoundsInRootWindow() override;
+ virtual gfx::GLSurfaceHandle GetCompositingSurface() override;
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) OVERRIDE;
+ InputEventAckState ack_result) override;
virtual InputEventAckState FilterInputEvent(
- const blink::WebInputEvent& input_event) OVERRIDE;
- virtual void OnSetNeedsFlushInput() OVERRIDE;
+ const blink::WebInputEvent& input_event) override;
+ virtual void OnSetNeedsFlushInput() override;
virtual void GestureEventAck(const blink::WebGestureEvent& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void CreateBrowserAccessibilityManagerIfNeeded() OVERRIDE;
- virtual bool LockMouse() OVERRIDE;
- virtual void UnlockMouse() OVERRIDE;
+ InputEventAckState ack_result) override;
+ virtual BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) override;
+ virtual bool LockMouse() override;
+ virtual void UnlockMouse() override;
virtual void OnSwapCompositorFrame(
uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
- virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
- virtual void DidStopFlinging() OVERRIDE;
- virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
- const SkBitmap& zoomed_bitmap) OVERRIDE;
+ scoped_ptr<cc::CompositorFrame> frame) override;
+ virtual void DidOverscroll(const DidOverscrollParams& params) override;
+ virtual void DidStopFlinging() override;
+ virtual void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap) override;
virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
- OVERRIDE;
- virtual void LockCompositingSurface() OVERRIDE;
- virtual void UnlockCompositingSurface() OVERRIDE;
+ override;
+ virtual void LockCompositingSurface() override;
+ virtual void UnlockCompositingSurface() override;
virtual void OnTextSurroundingSelectionResponse(const base::string16& content,
size_t start_offset,
- size_t end_offset) OVERRIDE;
+ size_t end_offset) override;
// cc::DelegatedFrameResourceCollectionClient implementation.
- virtual void UnusedResourcesAreAvailable() OVERRIDE;
+ virtual void UnusedResourcesAreAvailable() override;
// ui::GestureProviderClient implementation.
- virtual void OnGestureEvent(const ui::GestureEventData& gesture) OVERRIDE;
+ virtual void OnGestureEvent(const ui::GestureEventData& gesture) override;
// ui::WindowAndroidObserver implementation.
- virtual void OnCompositingDidCommit() OVERRIDE;
- virtual void OnAttachCompositor() OVERRIDE {}
- virtual void OnDetachCompositor() OVERRIDE;
+ virtual void OnCompositingDidCommit() override;
+ virtual void OnAttachCompositor() override;
+ virtual void OnDetachCompositor() override;
virtual void OnVSync(base::TimeTicks frame_time,
- base::TimeDelta vsync_period) OVERRIDE;
- virtual void OnAnimate(base::TimeTicks begin_frame_time) OVERRIDE;
+ base::TimeDelta vsync_period) override;
+ virtual void OnAnimate(base::TimeTicks begin_frame_time) override;
// ImageTransportFactoryAndroidObserver implementation.
- virtual void OnLostResources() OVERRIDE;
+ virtual void OnLostResources() override;
// DelegatedFrameEvictor implementation
- virtual void EvictDelegatedFrame() OVERRIDE;
+ virtual void EvictDelegatedFrame() override;
+
+ virtual SkColorType PreferredReadbackFormat() override;
- virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
+ // GestureTextSelectorClient implementation.
+ virtual void ShowSelectionHandlesAutomatically() override;
+ virtual void SelectRange(float x1, float y1, float x2, float y2) override;
+ virtual void LongPress(base::TimeTicks time, float x, float y) override;
// Non-virtual methods
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
SkColor GetCachedBackgroundColor() const;
void SendKeyEvent(const NativeWebKeyboardEvent& event);
- void SendTouchEvent(const blink::WebTouchEvent& event);
void SendMouseEvent(const blink::WebMouseEvent& event);
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event);
void SendGestureEvent(const blink::WebGestureEvent& event);
+ void OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params& params);
void OnDidChangeBodyBackgroundColor(SkColor color);
void OnStartContentIntent(const GURL& content_url);
void OnSetNeedsBeginFrame(bool enabled);
- void OnSmartClipDataExtracted(const base::string16& result);
+ void OnSmartClipDataExtracted(const base::string16& text,
+ const base::string16& html,
+ const gfx::Rect rect);
bool OnTouchEvent(const ui::MotionEvent& event);
+ bool OnTouchHandleEvent(const ui::MotionEvent& event);
void ResetGestureDetection();
void SetDoubleTapSupportEnabled(bool enabled);
void SetMultiTouchZoomSupportEnabled(bool enabled);
@@ -211,13 +240,19 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void GetScaledContentBitmap(
float scale,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
gfx::Rect src_subrect,
const base::Callback<void(bool, const SkBitmap&)>& result_callback);
+ scoped_refptr<cc::DelegatedRendererLayer>
+ CreateDelegatedLayerForFrameProvider() const;
+
bool HasValidFrame() const;
void MoveCaret(const gfx::Point& point);
+ void DismissTextHandles();
+ void SetTextHandlesTemporarilyHidden(bool hidden);
+ void OnShowingPastePopup(const gfx::PointF& point);
void SynchronousFrameMetadata(
const cc::CompositorFrameMetadata& frame_metadata);
@@ -231,6 +266,17 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const TextSurroundingSelectionCallback& callback);
private:
+ // TouchSelectionControllerClient implementation.
+ virtual bool SupportsAnimation() const override;
+ virtual void SetNeedsAnimate() override;
+ virtual void MoveCaret(const gfx::PointF& position) override;
+ virtual void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
+ virtual void SelectBetweenCoordinates(const gfx::PointF& base,
+ const gfx::PointF& extent) override;
+ virtual void OnSelectionEvent(SelectionEventType event,
+ const gfx::PointF& anchor_position) override;
+ virtual scoped_ptr<TouchHandleDrawable> CreateDrawable() override;
+
void RunAckCallbacks();
void DestroyDelegatedContent();
@@ -242,8 +288,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnFrameMetadataUpdated(
const cc::CompositorFrameMetadata& frame_metadata);
void ComputeContentsSize(const cc::CompositorFrameMetadata& frame_metadata);
- void ResetClipping();
- void ClipContents(const gfx::Rect& clipping, const gfx::Size& content_size);
void AttachLayers();
void RemoveLayers();
@@ -252,13 +296,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// of the copy.
static void PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::TimeTicks& start_time,
const base::Callback<void(bool, const SkBitmap&)>& callback,
scoped_ptr<cc::CopyOutputResult> result);
static void PrepareTextureCopyOutputResultForDelegatedReadback(
const gfx::Size& dst_size_in_pixel,
- const SkBitmap::Config config,
+ const SkColorType color_type,
const base::TimeTicks& start_time,
scoped_refptr<cc::Layer> readback_layer,
const base::Callback<void(bool, const SkBitmap&)>& callback,
@@ -269,9 +313,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const gfx::Rect& src_subrect_in_pixel,
const gfx::Size& dst_size_in_pixel,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config);
+ const SkColorType color_type);
- bool IsReadbackConfigSupported(SkBitmap::Config bitmap_config);
+ bool IsReadbackConfigSupported(SkColorType color_type);
// If we have locks on a frame during a ContentViewCore swap or a context
// lost, the frame is no longer valid and we can safely release all the locks.
@@ -286,14 +330,25 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void InternalSwapCompositorFrame(uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame);
- void SetNeedsAnimate();
+ enum VSyncRequestType {
+ FLUSH_INPUT = 1 << 0,
+ BEGIN_FRAME = 1 << 1,
+ PERSISTENT_BEGIN_FRAME = 1 << 2
+ };
+ void RequestVSyncUpdate(uint32 requests);
+ void StartObservingRootWindow();
+ void StopObservingRootWindow();
+ void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period);
bool Animate(base::TimeTicks frame_time);
+ // Handles all unprocessed and pending readback requests.
+ void AbortPendingReadbackRequests();
+
// The model object.
RenderWidgetHostImpl* host_;
- // Used to track whether this render widget needs a BeginFrame.
- bool needs_begin_frame_;
+ // Used to control action dispatch at the next |OnVSync()| call.
+ uint32 outstanding_vsync_requests_;
bool is_showing_;
@@ -315,26 +370,26 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// The most recent content size that was pushed to the texture layer.
gfx::Size content_size_in_layer_;
- // The device scale of the last received frame.
- float device_scale_factor_;
-
// The output surface id of the last received frame.
uint32_t last_output_surface_id_;
- base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_;
std::queue<base::Closure> ack_callbacks_;
const bool overscroll_effect_enabled_;
// Used to render overscroll overlays.
- // Note: |overscroll_effect_| will never be NULL, even if it's never enabled.
scoped_ptr<OverscrollGlow> overscroll_effect_;
// Provides gesture synthesis given a stream of touch events (derived from
// Android MotionEvent's) and touch event acks.
ui::FilteredGestureProvider gesture_provider_;
- bool flush_input_requested_;
+ // Handles gesture based text selection
+ GestureTextSelector gesture_text_selector_;
+
+ // Manages selection handle rendering and manipulation.
+ // This will always be NULL if |content_view_core_| is NULL.
+ scoped_ptr<TouchSelectionController> selection_controller_;
int accelerated_surface_route_id_;
@@ -360,6 +415,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
TextSurroundingSelectionCallback text_surrounding_selection_callback_;
+ // List of readbackrequests waiting for arrival of a valid frame.
+ std::queue<ReadbackRequest> readbacks_waiting_for_frame_;
+
+ // The last scroll offset of the view.
+ gfx::Vector2dF last_scroll_offset_;
+
+ base::WeakPtrFactory<RenderWidgetHostViewAndroid> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAndroid);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
index 3c10f51e145..074a309e045 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -29,6 +29,7 @@
#include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/ui_events_helper.h"
@@ -62,6 +63,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/compositor_vsync_manager.h"
+#include "ui/compositor/dip_util.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/gestures/gesture_recognizer.h"
@@ -233,12 +235,15 @@ void UpdateWebTouchEventAfterDispatch(blink::WebTouchEvent* event,
if (point->state != blink::WebTouchPoint::StateReleased &&
point->state != blink::WebTouchPoint::StateCancelled)
return;
- --event->touchesLength;
- for (unsigned i = point - event->touches;
- i < event->touchesLength;
- ++i) {
+
+ const unsigned new_length = event->touchesLength - 1;
+ // Work around a gcc 4.9 bug. crbug.com/392872
+ if (new_length >= event->touchesLengthCap)
+ return;
+
+ for (unsigned i = point - event->touches; i < new_length; ++i)
event->touches[i] = event->touches[i + 1];
- }
+ event->touchesLength = new_length;
}
bool CanRendererHandleEvent(const ui::MouseEvent* event) {
@@ -316,6 +321,9 @@ void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
results->orientationAngle = 270;
else if (results->orientationAngle == 270)
results->orientationAngle = 90;
+
+ results->orientationType =
+ RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
}
bool PointerEventActivates(const ui::Event& event) {
@@ -344,16 +352,16 @@ class RenderWidgetHostViewAura::EventFilterForPopupExit
aura::Env::GetInstance()->AddPreTargetHandler(this);
}
- virtual ~EventFilterForPopupExit() {
+ ~EventFilterForPopupExit() override {
aura::Env::GetInstance()->RemovePreTargetHandler(this);
}
// Overridden from ui::EventHandler
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ void OnMouseEvent(ui::MouseEvent* event) override {
rwhva_->ApplyEventFilterForPopupExit(event);
}
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
+ void OnTouchEvent(ui::TouchEvent* event) override {
rwhva_->ApplyEventFilterForPopupExit(event);
}
@@ -379,8 +387,7 @@ void RenderWidgetHostViewAura::ApplyEventFilterForPopupExit(
target != popup_parent_host_view_->window_)) {
// Note: popup_parent_host_view_ may be NULL when there are multiple
// popup children per view. See: RenderWidgetHostViewAura::InitAsPopup().
- in_shutdown_ = true;
- host_->Shutdown();
+ Shutdown();
}
}
@@ -395,18 +402,16 @@ class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
view_->window_->AddObserver(this);
}
- virtual ~WindowObserver() {
- view_->window_->RemoveObserver(this);
- }
+ ~WindowObserver() override { view_->window_->RemoveObserver(this); }
// Overridden from aura::WindowObserver:
- virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
+ void OnWindowAddedToRootWindow(aura::Window* window) override {
if (window == view_->window_)
view_->AddedToRootWindow();
}
- virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
- aura::Window* new_root) OVERRIDE {
+ void OnWindowRemovingFromRootWindow(aura::Window* window,
+ aura::Window* new_root) override {
if (window == view_->window_)
view_->RemovingFromRootWindow();
}
@@ -420,7 +425,8 @@ class RenderWidgetHostViewAura::WindowObserver : public aura::WindowObserver {
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, public:
-RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
+RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
+ bool is_guest_view_hack)
: host_(RenderWidgetHostImpl::From(host)),
window_(new aura::Window(this)),
delegated_frame_host_(new DelegatedFrameHost(this)),
@@ -432,6 +438,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
is_loading_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
+ text_input_flags_(0),
can_compose_inline_(true),
has_composition_text_(false),
accept_return_character_(false),
@@ -439,9 +446,16 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
paint_canvas_(NULL),
synthetic_move_sent_(false),
cursor_visibility_state_in_renderer_(UNKNOWN),
+#if defined(OS_WIN)
+ legacy_render_widget_host_HWND_(NULL),
+#endif
+ has_snapped_to_boundary_(false),
touch_editing_client_(NULL),
+ is_guest_view_hack_(is_guest_view_hack),
weak_ptr_factory_(this) {
- host_->SetView(this);
+ if (!is_guest_view_hack_)
+ host_->SetView(this);
+
window_observer_.reset(new WindowObserver(this));
aura::client::SetTooltipText(window_, &tooltip_);
aura::client::SetActivationDelegate(window_, this);
@@ -450,7 +464,7 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
window_->set_layer_owner_delegate(delegated_frame_host_.get());
gfx::Screen::GetScreenFor(window_)->AddObserver(this);
- bool overscroll_enabled = CommandLine::ForCurrentProcess()->
+ bool overscroll_enabled = base::CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation) != "0";
SetOverscrollControllerEnabled(overscroll_enabled);
}
@@ -458,11 +472,26 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host)
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewAura, RenderWidgetHostView implementation:
+bool RenderWidgetHostViewAura::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewAura, message)
+ // TODO(kevers): Move to RenderWidgetHostViewImpl and consolidate IPC
+ // messages for TextInput<State|Type>Changed. Corresponding code in
+ // RenderWidgetHostViewAndroid should also be moved at the same time.
+ IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
+ OnTextInputStateChanged)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
void RenderWidgetHostViewAura::InitAsChild(
gfx::NativeView parent_view) {
window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
- window_->Init(aura::WINDOW_LAYER_TEXTURED);
+ window_->Init(aura::WINDOW_LAYER_SOLID_COLOR);
window_->SetName("RenderWidgetHostViewAura");
+ window_->layer()->SetColor(background_color_);
}
void RenderWidgetHostViewAura::InitAsPopup(
@@ -489,25 +518,26 @@ void RenderWidgetHostViewAura::InitAsPopup(
}
popup_parent_host_view_->popup_child_host_view_ = this;
window_->SetType(ui::wm::WINDOW_TYPE_MENU);
- window_->Init(aura::WINDOW_LAYER_TEXTURED);
+ window_->Init(aura::WINDOW_LAYER_SOLID_COLOR);
window_->SetName("RenderWidgetHostViewAura");
+ window_->layer()->SetColor(background_color_);
- aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
- aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
// Setting the transient child allows for the popup to get mouse events when
- // in a system modal dialog.
+ // in a system modal dialog. Do this before calling ParentWindowWithContext
+ // below so that the transient parent is visible to WindowTreeClient.
// This fixes crbug.com/328593.
if (transient_window_client) {
transient_window_client->AddTransientChild(
popup_parent_host_view_->window_, window_);
}
+ aura::Window* root = popup_parent_host_view_->window_->GetRootWindow();
+ aura::client::ParentWindowWithContext(window_, root, bounds_in_screen);
+
SetBounds(bounds_in_screen);
Show();
-#if !defined(OS_WIN) && !defined(OS_CHROMEOS)
- if (NeedsInputGrab())
+ if (NeedsMouseCapture())
window_->SetCapture();
-#endif
event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
}
@@ -516,9 +546,10 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
RenderWidgetHostView* reference_host_view) {
is_fullscreen_ = true;
window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
- window_->Init(aura::WINDOW_LAYER_TEXTURED);
+ window_->Init(aura::WINDOW_LAYER_SOLID_COLOR);
window_->SetName("RenderWidgetHostViewAura");
window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
+ window_->layer()->SetColor(background_color_);
aura::Window* parent = NULL;
gfx::Rect bounds;
@@ -547,7 +578,17 @@ void RenderWidgetHostViewAura::WasShown() {
DCHECK(host_);
if (!host_->is_hidden())
return;
- host_->WasShown();
+
+ bool has_saved_frame = delegated_frame_host_->HasSavedFrame();
+ ui::LatencyInfo renderer_latency_info, browser_latency_info;
+ if (has_saved_frame) {
+ browser_latency_info.AddLatencyNumber(
+ ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
+ } else {
+ renderer_latency_info.AddLatencyNumber(
+ ui::TAB_SHOW_COMPONENT, host_->GetLatencyComponentId(), 0);
+ }
+ host_->WasShown(renderer_latency_info);
aura::Window* root = window_->GetRootWindow();
if (root) {
@@ -557,19 +598,9 @@ void RenderWidgetHostViewAura::WasShown() {
NotifyRendererOfCursorVisibilityState(cursor_client->IsCursorVisible());
}
- delegated_frame_host_->WasShown();
+ delegated_frame_host_->WasShown(browser_latency_info);
#if defined(OS_WIN)
- if (legacy_render_widget_host_HWND_) {
- // Reparent the legacy Chrome_RenderWidgetHostHWND window to the parent
- // window before reparenting any plugins. This ensures that the plugin
- // windows stay on top of the child Zorder in the parent and receive
- // mouse events, etc.
- legacy_render_widget_host_HWND_->UpdateParent(
- GetNativeView()->GetHost()->GetAcceleratedWidget());
- legacy_render_widget_host_HWND_->SetBounds(
- window_->GetBoundsInRootWindow());
- }
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
#endif
@@ -588,10 +619,6 @@ void RenderWidgetHostViewAura::WasHidden() {
HWND parent = host->GetAcceleratedWidget();
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(parent, HideWindowsCallback, lparam);
- // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
- // hidden window on the same lines as Windowed plugin windows.
- if (legacy_render_widget_host_HWND_)
- legacy_render_widget_host_HWND_->UpdateParent(ui::GetHiddenWindow());
}
#endif
}
@@ -621,6 +648,10 @@ void RenderWidgetHostViewAura::SetBounds(const gfx::Rect& rect) {
InternalSetBounds(gfx::Rect(relative_origin, rect.size()));
}
+gfx::Vector2dF RenderWidgetHostViewAura::GetLastScrollOffset() const {
+ return last_scroll_offset_;
+}
+
gfx::NativeView RenderWidgetHostViewAura::GetNativeView() const {
return window_;
}
@@ -640,9 +671,8 @@ gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
if (!host)
return static_cast<gfx::NativeViewAccessible>(NULL);
HWND hwnd = host->GetAcceleratedWidget();
-
- CreateBrowserAccessibilityManagerIfNeeded();
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
+ BrowserAccessibilityManager* manager =
+ host_->GetOrCreateRootBrowserAccessibilityManager();
if (manager)
return manager->GetRoot()->ToBrowserAccessibilityWin();
#endif
@@ -753,19 +783,11 @@ bool RenderWidgetHostViewAura::IsSurfaceAvailableForCopy() const {
void RenderWidgetHostViewAura::Show() {
window_->Show();
WasShown();
-#if defined(OS_WIN)
- if (legacy_render_widget_host_HWND_)
- legacy_render_widget_host_HWND_->Show();
-#endif
}
void RenderWidgetHostViewAura::Hide() {
window_->Hide();
WasHidden();
-#if defined(OS_WIN)
- if (legacy_render_widget_host_HWND_)
- legacy_render_widget_host_HWND_->Hide();
-#endif
}
bool RenderWidgetHostViewAura::IsShowing() {
@@ -776,10 +798,12 @@ gfx::Rect RenderWidgetHostViewAura::GetViewBounds() const {
return window_->GetBoundsInScreen();
}
-void RenderWidgetHostViewAura::SetBackgroundOpaque(bool opaque) {
- RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
+void RenderWidgetHostViewAura::SetBackgroundColor(SkColor color) {
+ RenderWidgetHostViewBase::SetBackgroundColor(color);
+ bool opaque = GetBackgroundOpaque();
host_->SetBackgroundOpaque(opaque);
window_->layer()->SetFillsBoundsOpaquely(opaque);
+ window_->layer()->SetColor(color);
}
gfx::Size RenderWidgetHostViewAura::GetVisibleViewportSize() const {
@@ -808,19 +832,29 @@ void RenderWidgetHostViewAura::SetIsLoading(bool is_loading) {
UpdateCursorIfOverSelf();
}
-void RenderWidgetHostViewAura::TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) {
- if (text_input_type_ != params.type ||
- text_input_mode_ != params.mode ||
- can_compose_inline_ != params.can_compose_inline) {
- text_input_type_ = params.type;
- text_input_mode_ = params.mode;
- can_compose_inline_ = params.can_compose_inline;
+void RenderWidgetHostViewAura::TextInputTypeChanged(
+ ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
+ if (text_input_type_ != type ||
+ text_input_mode_ != input_mode ||
+ can_compose_inline_ != can_compose_inline ||
+ text_input_flags_ != flags) {
+ text_input_type_ = type;
+ text_input_mode_ = input_mode;
+ can_compose_inline_ = can_compose_inline;
+ text_input_flags_ = flags;
if (GetInputMethod())
GetInputMethod()->OnTextInputTypeChanged(this);
if (touch_editing_client_)
touch_editing_client_->OnTextInputTypeChanged(text_input_type_);
}
+}
+
+void RenderWidgetHostViewAura::OnTextInputStateChanged(
+ const ViewHostMsg_TextInputState_Params& params) {
+ text_input_flags_ = params.flags;
if (params.show_ime_if_needed && params.type != ui::TEXT_INPUT_TYPE_NONE) {
if (GetInputMethod())
GetInputMethod()->ShowImeIfNeeded();
@@ -884,9 +918,7 @@ void RenderWidgetHostViewAura::SelectionChanged(const base::string16& text,
}
// Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
- ui::ScopedClipboardWriter clipboard_writer(
- ui::Clipboard::GetForCurrentThread(),
- ui::CLIPBOARD_TYPE_SELECTION);
+ ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
clipboard_writer.WriteText(text.substr(pos, n));
#endif // defined(USE_X11) && !defined(OS_CHROMEOS)
}
@@ -913,23 +945,13 @@ void RenderWidgetHostViewAura::SelectionBoundsChanged(
}
}
-void RenderWidgetHostViewAura::ScrollOffsetChanged() {
- aura::Window* root = window_->GetRootWindow();
- if (!root)
- return;
- aura::client::CursorClient* cursor_client =
- aura::client::GetCursorClient(root);
- if (cursor_client && !cursor_client->IsCursorVisible())
- cursor_client->DisableMouseEvents();
-}
-
void RenderWidgetHostViewAura::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) {
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) {
delegated_frame_host_->CopyFromCompositingSurface(
- src_subrect, dst_size, callback, config);
+ src_subrect, dst_size, callback, color_type);
}
void RenderWidgetHostViewAura::CopyFromCompositingSurfaceToVideoFrame(
@@ -957,74 +979,6 @@ void RenderWidgetHostViewAura::EndFrameSubscription() {
delegated_frame_host_->EndFrameSubscription();
}
-void RenderWidgetHostViewAura::AcceleratedSurfaceInitialized(int host_id,
- int route_id) {
-}
-
-void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
- // The top left corner of our view in window coordinates might not land on a
- // device pixel boundary if we have a non-integer device scale. In that case,
- // to avoid the web contents area looking blurry we translate the web contents
- // in the +x, +y direction to land on the nearest pixel boundary. This may
- // cause the bottom and right edges to be clipped slightly, but that's ok.
- gfx::Point view_offset_dips = window_->GetBoundsInRootWindow().origin();
- gfx::PointF view_offset = view_offset_dips;
- view_offset.Scale(current_device_scale_factor_);
- gfx::PointF view_offset_snapped(std::ceil(view_offset.x()),
- std::ceil(view_offset.y()));
-
- gfx::Vector2dF fudge = view_offset_snapped - view_offset;
- fudge.Scale(1.0 / current_device_scale_factor_);
- GetLayer()->SetSubpixelPositionOffset(fudge);
-}
-
-void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
- if (HasDisplayPropertyChanged(window_))
- host_->InvalidateScreenInfo();
-
- SnapToPhysicalPixelBoundary();
- // Don't recursively call SetBounds if this bounds update is the result of
- // a Window::SetBoundsInternal call.
- if (!in_bounds_changed_)
- window_->SetBounds(rect);
- host_->WasResized();
- delegated_frame_host_->WasResized();
- if (touch_editing_client_) {
- touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
- selection_focus_rect_);
- }
-#if defined(OS_WIN)
- // Create the legacy dummy window which corresponds to the bounds of the
- // webcontents. This will be passed as the container window for windowless
- // plugins.
- // Plugins like Flash assume the container window which is returned via the
- // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
- // This is not true in Aura where we have only HWND which is the main Aura
- // window. If we return this window to plugins like Flash then it causes the
- // coordinate translations done by these plugins to break.
- // Additonally the legacy dummy window is needed for accessibility and for
- // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
- if (GetNativeViewId()) {
- if (!legacy_render_widget_host_HWND_) {
- legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
- reinterpret_cast<HWND>(GetNativeViewId()));
- BrowserAccessibilityManagerWin* manager =
- static_cast<BrowserAccessibilityManagerWin*>(
- GetBrowserAccessibilityManager());
- if (manager)
- manager->SetAccessibleHWND(legacy_render_widget_host_HWND_.get());
- }
- if (legacy_render_widget_host_HWND_) {
- legacy_render_widget_host_HWND_->SetBounds(
- window_->GetBoundsInRootWindow());
- }
- }
-
- if (mouse_locked_)
- UpdateMouseLockRegion();
-#endif
-}
-
#if defined(OS_WIN)
bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
return (legacy_render_widget_host_HWND_ != NULL);
@@ -1058,18 +1012,14 @@ void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
::ClipCursor(&window_rect);
}
}
-#endif
-
-void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
- int gpu_host_id) {
- // Oldschool composited mode is no longer supported.
-}
+#endif // defined(OS_WIN)
void RenderWidgetHostViewAura::OnSwapCompositorFrame(
uint32 output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
TRACE_EVENT0("content", "RenderWidgetHostViewAura::OnSwapCompositorFrame");
+
+ last_scroll_offset_ = frame->metadata.root_scroll_offset;
if (frame->delegated_frame_data) {
delegated_frame_host_->SwapDelegatedFrame(
output_surface_id,
@@ -1088,37 +1038,32 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame(
}
}
+void RenderWidgetHostViewAura::DidStopFlinging() {
+ if (touch_editing_client_)
+ touch_editing_client_->DidStopFlinging();
+}
+
#if defined(OS_WIN)
+void RenderWidgetHostViewAura::SetLegacyRenderWidgetHostHWND(
+ LegacyRenderWidgetHostHWND* legacy_hwnd) {
+ legacy_render_widget_host_HWND_ = legacy_hwnd;
+}
+
void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) {
- if (GetBrowserAccessibilityManager()) {
- GetBrowserAccessibilityManager()->ToBrowserAccessibilityManagerWin()
- ->set_parent_iaccessible(accessible_parent);
- }
}
gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
const {
if (legacy_render_widget_host_HWND_) {
- return reinterpret_cast<gfx::NativeViewId>(
- legacy_render_widget_host_HWND_->hwnd());
+ HWND hwnd = legacy_render_widget_host_HWND_->hwnd();
+ if (::IsWindow(hwnd))
+ return reinterpret_cast<gfx::NativeViewId>(hwnd);
}
return NULL;
}
#endif
-void RenderWidgetHostViewAura::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
- int gpu_host_id) {
- // Oldschool composited mode is no longer supported.
-}
-
-void RenderWidgetHostViewAura::AcceleratedSurfaceSuspend() {
-}
-
-void RenderWidgetHostViewAura::AcceleratedSurfaceRelease() {
-}
-
bool RenderWidgetHostViewAura::HasAcceleratedSurface(
const gfx::Size& desired_size) {
// Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
@@ -1239,30 +1184,129 @@ InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
: INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
-void RenderWidgetHostViewAura::CreateBrowserAccessibilityManagerIfNeeded() {
+BrowserAccessibilityManager*
+RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) {
+ BrowserAccessibilityManager* manager = NULL;
#if defined(OS_WIN)
- if (!GetBrowserAccessibilityManager()) {
- gfx::NativeViewAccessible accessible_parent =
- host_->GetParentNativeViewAccessible();
- LegacyRenderWidgetHostHWND* parent_hwnd =
- legacy_render_widget_host_HWND_.get();
- SetBrowserAccessibilityManager(new BrowserAccessibilityManagerWin(
- legacy_render_widget_host_HWND_.get(), accessible_parent,
- BrowserAccessibilityManagerWin::GetEmptyDocument(), host_));
- }
+ manager = new BrowserAccessibilityManagerWin(
+ BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
#else
- if (!GetBrowserAccessibilityManager()) {
- SetBrowserAccessibilityManager(
- BrowserAccessibilityManager::Create(
- BrowserAccessibilityManager::GetEmptyDocument(), host_));
+ manager = BrowserAccessibilityManager::Create(
+ BrowserAccessibilityManager::GetEmptyDocument(), delegate);
+#endif
+ return manager;
+}
+
+gfx::AcceleratedWidget
+RenderWidgetHostViewAura::AccessibilityGetAcceleratedWidget() {
+#if defined(OS_WIN)
+ if (legacy_render_widget_host_HWND_) {
+ HWND hwnd = legacy_render_widget_host_HWND_->hwnd();
+ if (::IsWindow(hwnd))
+ return hwnd;
}
#endif
+ return gfx::kNullAcceleratedWidget;
+}
+
+gfx::NativeViewAccessible
+RenderWidgetHostViewAura::AccessibilityGetNativeViewAccessible() {
+#if defined(OS_WIN)
+ if (legacy_render_widget_host_HWND_)
+ return legacy_render_widget_host_HWND_->window_accessible();
+#endif
+ return NULL;
+
}
gfx::GLSurfaceHandle RenderWidgetHostViewAura::GetCompositingSurface() {
return ImageTransportFactory::GetInstance()->GetSharedSurfaceHandle();
}
+void RenderWidgetHostViewAura::ShowDisambiguationPopup(
+ const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap) {
+ // |target_rect| is provided in pixels, not DIPs. So we convert it to DIPs
+ // by scaling it by the inverse of the device scale factor.
+ gfx::RectF screen_target_rect_f(rect_pixels);
+ screen_target_rect_f.Scale(1.0f / current_device_scale_factor_);
+ disambiguation_target_rect_ = gfx::ToEnclosingRect(screen_target_rect_f);
+
+ float scale = static_cast<float>(zoomed_bitmap.width()) /
+ static_cast<float>(rect_pixels.width());
+ gfx::Size zoomed_size(gfx::ToCeiledSize(
+ gfx::ScaleSize(disambiguation_target_rect_.size(), scale)));
+
+ // Save of a copy of the |last_scroll_offset_| for comparison when the copy
+ // callback fires, to ensure that we haven't scrolled.
+ disambiguation_scroll_offset_ = last_scroll_offset_;
+
+ CopyFromCompositingSurface(
+ disambiguation_target_rect_,
+ zoomed_size,
+ base::Bind(&RenderWidgetHostViewAura::DisambiguationPopupRendered,
+ base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
+ <RenderWidgetHostViewAura>(this)),
+ kN32_SkColorType);
+}
+
+void RenderWidgetHostViewAura::DisambiguationPopupRendered(
+ bool success,
+ const SkBitmap& result) {
+ if (!success || disambiguation_scroll_offset_ != last_scroll_offset_)
+ return;
+
+ // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
+ // actually show the delegate.
+ RenderViewHostDelegate* delegate = NULL;
+ if (host_->IsRenderView())
+ delegate = RenderViewHost::From(host_)->GetDelegate();
+ RenderViewHostDelegateView* delegate_view = NULL;
+ if (delegate)
+ delegate_view = delegate->GetDelegateView();
+ if (delegate_view) {
+ delegate_view->ShowDisambiguationPopup(
+ disambiguation_target_rect_,
+ result,
+ base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationGesture,
+ base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
+ <RenderWidgetHostViewAura>(this)),
+ base::Bind(&RenderWidgetHostViewAura::ProcessDisambiguationMouse,
+ base::internal::SupportsWeakPtrBase::StaticAsWeakPtr
+ <RenderWidgetHostViewAura>(this)));
+ }
+}
+
+void RenderWidgetHostViewAura::HideDisambiguationPopup() {
+ RenderViewHostDelegate* delegate = NULL;
+ if (host_->IsRenderView())
+ delegate = RenderViewHost::From(host_)->GetDelegate();
+ RenderViewHostDelegateView* delegate_view = NULL;
+ if (delegate)
+ delegate_view = delegate->GetDelegateView();
+ if (delegate_view)
+ delegate_view->HideDisambiguationPopup();
+}
+
+void RenderWidgetHostViewAura::ProcessDisambiguationGesture(
+ ui::GestureEvent* event) {
+ blink::WebGestureEvent web_gesture = content::MakeWebGestureEvent(event);
+ // If we fail to make a WebGestureEvent that is a Tap from the provided event,
+ // don't forward it to Blink.
+ if (web_gesture.type < blink::WebInputEvent::Type::GestureTap ||
+ web_gesture.type > blink::WebInputEvent::Type::GestureTapCancel)
+ return;
+
+ host_->ForwardGestureEvent(web_gesture);
+}
+
+void RenderWidgetHostViewAura::ProcessDisambiguationMouse(
+ ui::MouseEvent* event) {
+ blink::WebMouseEvent web_mouse = content::MakeWebMouseEvent(event);
+ host_->ForwardMouseEvent(web_mouse);
+}
+
bool RenderWidgetHostViewAura::LockMouse() {
aura::Window* root_window = window_->GetRootWindow();
if (!root_window)
@@ -1400,6 +1444,10 @@ ui::TextInputMode RenderWidgetHostViewAura::GetTextInputMode() const {
return text_input_mode_;
}
+int RenderWidgetHostViewAura::GetTextInputFlags() const {
+ return text_input_flags_;
+}
+
bool RenderWidgetHostViewAura::CanComposeInline() const {
return can_compose_inline_;
}
@@ -1651,16 +1699,12 @@ void RenderWidgetHostViewAura::OnCaptureLost() {
}
void RenderWidgetHostViewAura::OnPaint(gfx::Canvas* canvas) {
- // For non-opaque windows, we don't draw anything, since we depend on the
- // canvas coming from the compositor to already be initialized as
- // transparent.
- if (window_->layer()->fills_bounds_opaquely())
- canvas->DrawColor(SK_ColorWHITE);
+ NOTREACHED();
}
void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
float device_scale_factor) {
- if (!host_)
+ if (!host_ || !window_->GetRootWindow())
return;
UpdateScreenInfo(window_);
@@ -1669,6 +1713,7 @@ void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
GetDisplayNearestWindow(window_);
DCHECK_EQ(device_scale_factor, display.device_scale_factor());
current_cursor_.SetDisplayInfo(display);
+ SnapToPhysicalPixelBoundary();
}
void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
@@ -1683,6 +1728,7 @@ void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
}
LPARAM lparam = reinterpret_cast<LPARAM>(this);
EnumChildWindows(parent, WindowDestroyingCallback, lparam);
+ legacy_render_widget_host_HWND_ = NULL;
#endif
// Make sure that the input method no longer references to this object before
@@ -1697,7 +1743,10 @@ void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
}
void RenderWidgetHostViewAura::OnWindowDestroyed(aura::Window* window) {
- host_->ViewDestroyed();
+ // Ask the RWH to drop reference to us.
+ if (!is_guest_view_hack_)
+ host_->ViewDestroyed();
+
delete this;
}
@@ -1744,10 +1793,7 @@ void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
}
}
}
- if (!in_shutdown_) {
- in_shutdown_ = true;
- host_->Shutdown();
- }
+ Shutdown();
} else {
if (event->key_code() == ui::VKEY_RETURN) {
// Do not forward return key release events if no press event was handled.
@@ -1864,12 +1910,21 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
reinterpret_cast<LPARAM>(toplevel_hwnd));
}
#endif
+ // The Disambiguation popup does not parent itself from this window, so we
+ // manually dismiss it.
+ HideDisambiguationPopup();
+
blink::WebMouseWheelEvent mouse_wheel_event =
MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent*>(event));
if (mouse_wheel_event.deltaX != 0 || mouse_wheel_event.deltaY != 0)
host_->ForwardWheelEvent(mouse_wheel_event);
} else if (CanRendererHandleEvent(event) &&
!(event->flags() & ui::EF_FROM_TOUCH)) {
+ // Confirm existing composition text on mouse press, to make sure
+ // the input caret won't be moved with an ongoing composition text.
+ if (event->type() == ui::ET_MOUSE_PRESSED)
+ FinishImeCompositionSession();
+
blink::WebMouseEvent mouse_event = MakeWebMouseEvent(event);
ModifyEventMovementAndCoords(&mouse_event);
host_->ForwardMouseEvent(mouse_event);
@@ -1882,12 +1937,10 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
switch (event->type()) {
case ui::ET_MOUSE_PRESSED:
window_->SetCapture();
- // Confirm existing composition text on mouse click events, to make sure
- // the input caret won't be moved with an ongoing composition text.
- FinishImeCompositionSession();
break;
case ui::ET_MOUSE_RELEASED:
- window_->ReleaseCapture();
+ if (!NeedsMouseCapture())
+ window_->ReleaseCapture();
break;
default:
break;
@@ -1899,7 +1952,7 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
// In fullscreen mode which is typically used by flash, don't forward
// the mouse events to the parent. The renderer and the plugin process
// handle these events.
- if (!is_fullscreen_ && window_->parent()->delegate() &&
+ if (!is_fullscreen_ && window_->parent() && window_->parent()->delegate() &&
!(event->flags() & ui::EF_FROM_TOUCH)) {
event->ConvertLocationToTarget(window_, window_->parent());
window_->parent()->delegate()->OnMouseEvent(event);
@@ -1977,6 +2030,11 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
if (touch_editing_client_ && touch_editing_client_->HandleInputEvent(event))
return;
+ // Confirm existing composition text on TAP gesture, to make sure the input
+ // caret won't be moved with an ongoing composition text.
+ if (event->type() == ui::ET_GESTURE_TAP)
+ FinishImeCompositionSession();
+
RenderViewHostDelegate* delegate = NULL;
if (host_->IsRenderView())
delegate = RenderViewHost::From(host_)->GetDelegate();
@@ -2083,7 +2141,8 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
host_->SetInputMethodActive(false);
}
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
+ BrowserAccessibilityManager* manager =
+ host_->GetRootBrowserAccessibilityManager();
if (manager)
manager->OnWindowFocused();
} else if (window_ == lost_focus) {
@@ -2099,7 +2158,8 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
if (overscroll_controller_)
overscroll_controller_->Cancel();
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
+ BrowserAccessibilityManager* manager =
+ host_->GetRootBrowserAccessibilityManager();
if (manager)
manager->OnWindowBlurred();
@@ -2123,9 +2183,15 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
return;
}
#endif
- in_shutdown_ = true;
- host_->Shutdown();
+ Shutdown();
+ return;
}
+
+ // Close the child popup window if we lose focus (e.g. due to a JS alert or
+ // system modal dialog). This is particularly important if
+ // |popup_child_host_view_| has mouse capture.
+ if (popup_child_host_view_)
+ popup_child_host_view_->Shutdown();
}
}
@@ -2170,10 +2236,6 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
// Aura root window and we don't have a way to get an input method object
// associated with the window, but just in case.
DetachFromInputMethod();
-
-#if defined(OS_WIN)
- legacy_render_widget_host_HWND_.reset(NULL);
-#endif
}
void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
@@ -2213,10 +2275,24 @@ ui::InputMethod* RenderWidgetHostViewAura::GetInputMethod() const {
return root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
}
+void RenderWidgetHostViewAura::Shutdown() {
+ if (!in_shutdown_) {
+ in_shutdown_ = true;
+ host_->Shutdown();
+ }
+}
+
bool RenderWidgetHostViewAura::NeedsInputGrab() {
return popup_type_ == blink::WebPopupTypeSelect;
}
+bool RenderWidgetHostViewAura::NeedsMouseCapture() {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ return NeedsInputGrab();
+#endif
+ return false;
+}
+
void RenderWidgetHostViewAura::FinishImeCompositionSession() {
if (!has_composition_text_)
return;
@@ -2279,6 +2355,48 @@ void RenderWidgetHostViewAura::SetOverscrollControllerEnabled(bool enabled) {
overscroll_controller_.reset(new OverscrollController());
}
+void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
+ // The top left corner of our view in window coordinates might not land on a
+ // device pixel boundary if we have a non-integer device scale. In that case,
+ // to avoid the web contents area looking blurry we translate the web contents
+ // in the +x, +y direction to land on the nearest pixel boundary. This may
+ // cause the bottom and right edges to be clipped slightly, but that's ok.
+ aura::Window* snapped = NULL;
+ // On desktop, use the root window. On alternative environment (ash),
+ // use the toplevel window which must be already snapped.
+ if (gfx::Screen::GetScreenFor(window_) !=
+ gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE)) {
+ snapped = window_->GetRootWindow();
+ } else {
+ snapped = window_->GetToplevelWindow();
+ }
+ if (snapped && snapped != window_)
+ ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
+
+ has_snapped_to_boundary_ = true;
+}
+
+void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
+ if (HasDisplayPropertyChanged(window_))
+ host_->InvalidateScreenInfo();
+
+ SnapToPhysicalPixelBoundary();
+ // Don't recursively call SetBounds if this bounds update is the result of
+ // a Window::SetBoundsInternal call.
+ if (!in_bounds_changed_)
+ window_->SetBounds(rect);
+ host_->WasResized();
+ delegated_frame_host_->WasResized();
+ if (touch_editing_client_) {
+ touch_editing_client_->OnSelectionOrCursorChanged(selection_anchor_rect_,
+ selection_focus_rect_);
+ }
+#if defined(OS_WIN)
+ if (mouse_locked_)
+ UpdateMouseLockRegion();
+#endif
+}
+
void RenderWidgetHostViewAura::SchedulePaintIfNotInClip(
const gfx::Rect& rect,
const gfx::Rect& clip) {
@@ -2319,14 +2437,6 @@ void RenderWidgetHostViewAura::AddedToRootWindow() {
input_method->SetFocusedTextInputClient(this);
}
-#if defined(OS_WIN)
- // The parent may have changed here. Ensure that the legacy window is
- // reparented accordingly.
- if (legacy_render_widget_host_HWND_)
- legacy_render_widget_host_HWND_->UpdateParent(
- reinterpret_cast<HWND>(GetNativeViewId()));
-#endif
-
delegated_frame_host_->AddedToWindow();
}
@@ -2340,13 +2450,6 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
window_->GetHost()->RemoveObserver(this);
delegated_frame_host_->RemovingFromWindow();
-
-#if defined(OS_WIN)
- // Update the legacy window's parent temporarily to the desktop window. It
- // will eventually get reparented to the right root.
- if (legacy_render_widget_host_HWND_)
- legacy_render_widget_host_HWND_->UpdateParent(::GetDesktopWindow());
-#endif
}
void RenderWidgetHostViewAura::DetachFromInputMethod() {
@@ -2384,8 +2487,8 @@ void RenderWidgetHostViewAura::ForwardKeyboardEvent(
host_->ForwardKeyboardEvent(event);
}
-SkBitmap::Config RenderWidgetHostViewAura::PreferredReadbackFormat() {
- return SkBitmap::kARGB_8888_Config;
+SkColorType RenderWidgetHostViewAura::PreferredReadbackFormat() {
+ return kN32_SkColorType;
}
////////////////////////////////////////////////////////////////////////////////
@@ -2404,11 +2507,6 @@ RenderWidgetHostImpl* RenderWidgetHostViewAura::GetHost() {
return host_;
}
-void RenderWidgetHostViewAura::SchedulePaintInRect(
- const gfx::Rect& damage_rect_in_dip) {
- window_->SchedulePaintInRect(damage_rect_in_dip);
-}
-
bool RenderWidgetHostViewAura::IsVisible() {
return IsShowing();
}
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
index 8eab68b8851..ee70b04cac9 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -35,8 +35,6 @@
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/activation_delegate.h"
-struct ViewHostMsg_TextInputState_Params;
-
namespace aura {
class WindowTracker;
namespace client {
@@ -116,6 +114,10 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Notifies the client that a gesture event ack was received.
virtual void GestureEventAck(int gesture_event_type) = 0;
+ // Notifies the client that the fling has ended, so it can activate touch
+ // editing if needed.
+ virtual void DidStopFlinging() = 0;
+
// This is called when the view is destroyed, so that the client can
// perform any necessary clean-up.
virtual void OnViewDestroyed() = 0;
@@ -128,192 +130,193 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
touch_editing_client_ = client;
}
- explicit RenderWidgetHostViewAura(RenderWidgetHost* host);
+ // When |is_guest_view_hack| is true, this view isn't really the view for
+ // the |widget|, a RenderWidgetHostViewGuest is.
+ //
+ // TODO(lazyboy): Remove |is_guest_view_hack| once BrowserPlugin has migrated
+ // to use RWHVChildFrame (http://crbug.com/330264).
+ RenderWidgetHostViewAura(RenderWidgetHost* host, bool is_guest_view_hack);
// RenderWidgetHostView implementation.
- virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
- virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void SetBounds(const gfx::Rect& rect) OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
- virtual bool HasFocus() const OVERRIDE;
- virtual bool IsSurfaceAvailableForCopy() const OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsShowing() OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual void SetBackgroundOpaque(bool opaque) OVERRIDE;
- virtual gfx::Size GetVisibleViewportSize() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void InitAsChild(gfx::NativeView parent_view) override;
+ RenderWidgetHost* GetRenderWidgetHost() const override;
+ void SetSize(const gfx::Size& size) override;
+ void SetBounds(const gfx::Rect& rect) override;
+ gfx::Vector2dF GetLastScrollOffset() const override;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeViewId GetNativeViewId() const override;
+ gfx::NativeViewAccessible GetNativeViewAccessible() override;
+ ui::TextInputClient* GetTextInputClient() override;
+ bool HasFocus() const override;
+ bool IsSurfaceAvailableForCopy() const override;
+ void Show() override;
+ void Hide() override;
+ bool IsShowing() override;
+ gfx::Rect GetViewBounds() const override;
+ void SetBackgroundColor(SkColor color) override;
+ gfx::Size GetVisibleViewportSize() const override;
+ void SetInsets(const gfx::Insets& insets) override;
// Overridden from RenderWidgetHostViewBase:
- virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
- const gfx::Rect& pos) OVERRIDE;
- virtual void InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) OVERRIDE;
- virtual void WasShown() OVERRIDE;
- virtual void WasHidden() OVERRIDE;
- virtual void MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void Blur() OVERRIDE;
- virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
- virtual void SetIsLoading(bool is_loading) OVERRIDE;
- virtual void TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) OVERRIDE;
- virtual void ImeCancelComposition() OVERRIDE;
- virtual void ImeCompositionRangeChanged(
+ void InitAsPopup(RenderWidgetHostView* parent_host_view,
+ const gfx::Rect& pos) override;
+ void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
+ void WasShown() override;
+ void WasHidden() override;
+ void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
+ void Focus() override;
+ void Blur() override;
+ void UpdateCursor(const WebCursor& cursor) override;
+ void SetIsLoading(bool is_loading) override;
+ void TextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) override;
+ void ImeCancelComposition() override;
+ void ImeCompositionRangeChanged(
const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
- virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const base::string16& text,
- size_t offset,
- const gfx::Range& range) OVERRIDE;
- virtual gfx::Size GetRequestedRendererSize() const OVERRIDE;
- virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
- virtual void ScrollOffsetChanged() OVERRIDE;
- virtual void CopyFromCompositingSurface(
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) OVERRIDE;
- virtual void CopyFromCompositingSurfaceToVideoFrame(
+ const std::vector<gfx::Rect>& character_bounds) override;
+ void RenderProcessGone(base::TerminationStatus status,
+ int error_code) override;
+ void Destroy() override;
+ void SetTooltipText(const base::string16& tooltip_text) override;
+ void SelectionChanged(const base::string16& text,
+ size_t offset,
+ const gfx::Range& range) override;
+ gfx::Size GetRequestedRendererSize() const override;
+ void SelectionBoundsChanged(
+ const ViewHostMsg_SelectionBounds_Params& params) override;
+ void CopyFromCompositingSurface(const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) override;
+ void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool CanCopyToVideoFrame() const OVERRIDE;
- virtual bool CanSubscribeFrame() const OVERRIDE;
- virtual void BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
- virtual void EndFrameSubscription() OVERRIDE;
- virtual void AcceleratedSurfaceInitialized(int host_id,
- int route_id) OVERRIDE;
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfaceSuspend() OVERRIDE;
- virtual void AcceleratedSurfaceRelease() OVERRIDE;
- virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
- virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
- virtual void WheelEventAck(const blink::WebMouseWheelEvent& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void GestureEventAck(const blink::WebGestureEvent& event,
- InputEventAckState ack_result) OVERRIDE;
- virtual void ProcessAckedTouchEvent(
- const TouchEventWithLatencyInfo& touch,
- InputEventAckState ack_result) OVERRIDE;
- virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
- OVERRIDE;
- virtual InputEventAckState FilterInputEvent(
- const blink::WebInputEvent& input_event) OVERRIDE;
- virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
- virtual void CreateBrowserAccessibilityManagerIfNeeded() OVERRIDE;
- virtual bool LockMouse() OVERRIDE;
- virtual void UnlockMouse() OVERRIDE;
- virtual void OnSwapCompositorFrame(
- uint32 output_surface_id,
- scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
+ const base::Callback<void(bool)>& callback) override;
+ bool CanCopyToVideoFrame() const override;
+ bool CanSubscribeFrame() const override;
+ void BeginFrameSubscription(
+ scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
+ void EndFrameSubscription() override;
+ bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
+ void GetScreenInfo(blink::WebScreenInfo* results) override;
+ gfx::Rect GetBoundsInRootWindow() override;
+ void WheelEventAck(const blink::WebMouseWheelEvent& event,
+ InputEventAckState ack_result) override;
+ void GestureEventAck(const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) override;
+ void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) override;
+ scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() override;
+ InputEventAckState FilterInputEvent(
+ const blink::WebInputEvent& input_event) override;
+ gfx::GLSurfaceHandle GetCompositingSurface() override;
+ BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) override;
+ gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
+ gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
+ void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap) override;
+ bool LockMouse() override;
+ void UnlockMouse() override;
+ void OnSwapCompositorFrame(uint32 output_surface_id,
+ scoped_ptr<cc::CompositorFrame> frame) override;
+ void DidStopFlinging() override;
#if defined(OS_WIN)
+ void SetLegacyRenderWidgetHostHWND(LegacyRenderWidgetHostHWND* legacy_hwnd);
virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) OVERRIDE;
- virtual gfx::NativeViewId GetParentForWindowlessPlugin() const OVERRIDE;
+ gfx::NativeViewAccessible accessible_parent) override;
+ virtual gfx::NativeViewId GetParentForWindowlessPlugin() const override;
#endif
// Overridden from ui::TextInputClient:
- virtual void SetCompositionText(
- const ui::CompositionText& composition) OVERRIDE;
- virtual void ConfirmCompositionText() OVERRIDE;
- virtual void ClearCompositionText() OVERRIDE;
- virtual void InsertText(const base::string16& text) OVERRIDE;
- virtual void InsertChar(base::char16 ch, int flags) OVERRIDE;
- virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
- virtual ui::TextInputType GetTextInputType() const OVERRIDE;
- virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
- virtual bool CanComposeInline() const OVERRIDE;
- virtual gfx::Rect GetCaretBounds() const OVERRIDE;
- virtual bool GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) const OVERRIDE;
- virtual bool HasCompositionText() const OVERRIDE;
- virtual bool GetTextRange(gfx::Range* range) const OVERRIDE;
- virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE;
- virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE;
- virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE;
- virtual bool DeleteRange(const gfx::Range& range) OVERRIDE;
- virtual bool GetTextFromRange(const gfx::Range& range,
- base::string16* text) const OVERRIDE;
- virtual void OnInputMethodChanged() OVERRIDE;
- virtual bool ChangeTextDirectionAndLayoutAlignment(
- base::i18n::TextDirection direction) OVERRIDE;
- virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
- virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
- virtual void OnCandidateWindowShown() OVERRIDE;
- virtual void OnCandidateWindowUpdated() OVERRIDE;
- virtual void OnCandidateWindowHidden() OVERRIDE;
- virtual bool IsEditingCommandEnabled(int command_id) OVERRIDE;
- virtual void ExecuteEditingCommand(int command_id) OVERRIDE;
+ void SetCompositionText(const ui::CompositionText& composition) override;
+ void ConfirmCompositionText() override;
+ void ClearCompositionText() override;
+ void InsertText(const base::string16& text) override;
+ void InsertChar(base::char16 ch, int flags) override;
+ gfx::NativeWindow GetAttachedWindow() const override;
+ ui::TextInputType GetTextInputType() const override;
+ ui::TextInputMode GetTextInputMode() const override;
+ int GetTextInputFlags() const override;
+ bool CanComposeInline() const override;
+ gfx::Rect GetCaretBounds() const override;
+ bool GetCompositionCharacterBounds(uint32 index,
+ gfx::Rect* rect) const override;
+ bool HasCompositionText() const override;
+ bool GetTextRange(gfx::Range* range) const override;
+ bool GetCompositionTextRange(gfx::Range* range) const override;
+ bool GetSelectionRange(gfx::Range* range) const override;
+ bool SetSelectionRange(const gfx::Range& range) override;
+ bool DeleteRange(const gfx::Range& range) override;
+ bool GetTextFromRange(const gfx::Range& range,
+ base::string16* text) const override;
+ void OnInputMethodChanged() override;
+ bool ChangeTextDirectionAndLayoutAlignment(
+ base::i18n::TextDirection direction) override;
+ void ExtendSelectionAndDelete(size_t before, size_t after) override;
+ void EnsureCaretInRect(const gfx::Rect& rect) override;
+ void OnCandidateWindowShown() override;
+ void OnCandidateWindowUpdated() override;
+ void OnCandidateWindowHidden() override;
+ bool IsEditingCommandEnabled(int command_id) override;
+ void ExecuteEditingCommand(int command_id) override;
// Overridden from gfx::DisplayObserver:
- virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE;
- virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE;
- virtual void OnDisplayMetricsChanged(const gfx::Display& display,
- uint32_t metrics) OVERRIDE;
+ void OnDisplayAdded(const gfx::Display& new_display) override;
+ void OnDisplayRemoved(const gfx::Display& old_display) override;
+ void OnDisplayMetricsChanged(const gfx::Display& display,
+ uint32_t metrics) override;
// Overridden from aura::WindowDelegate:
- virtual gfx::Size GetMinimumSize() const OVERRIDE;
- virtual gfx::Size GetMaximumSize() const OVERRIDE;
- virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE;
- virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE;
- virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE;
- virtual bool ShouldDescendIntoChildForEventHandling(
+ gfx::Size GetMinimumSize() const override;
+ gfx::Size GetMaximumSize() const override;
+ void OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
+ gfx::NativeCursor GetCursor(const gfx::Point& point) override;
+ int GetNonClientComponent(const gfx::Point& point) const override;
+ bool ShouldDescendIntoChildForEventHandling(
aura::Window* child,
- const gfx::Point& location) OVERRIDE;
- virtual bool CanFocus() OVERRIDE;
- virtual void OnCaptureLost() OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
- virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
- virtual bool HasHitTestMask() const OVERRIDE;
- virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
+ const gfx::Point& location) override;
+ bool CanFocus() override;
+ void OnCaptureLost() override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ void OnWindowDestroying(aura::Window* window) override;
+ void OnWindowDestroyed(aura::Window* window) override;
+ void OnWindowTargetVisibilityChanged(bool visible) override;
+ bool HasHitTestMask() const override;
+ void GetHitTestMask(gfx::Path* mask) const override;
// Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+ void OnKeyEvent(ui::KeyEvent* event) override;
+ void OnMouseEvent(ui::MouseEvent* event) override;
+ void OnScrollEvent(ui::ScrollEvent* event) override;
+ void OnTouchEvent(ui::TouchEvent* event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
// Overridden from aura::client::ActivationDelegate:
- virtual bool ShouldActivate() const OVERRIDE;
+ bool ShouldActivate() const override;
// Overridden from aura::client::ActivationChangeObserver:
- virtual void OnWindowActivated(aura::Window* gained_activation,
- aura::Window* lost_activation) OVERRIDE;
+ void OnWindowActivated(aura::Window* gained_activation,
+ aura::Window* lost_activation) override;
// Overridden from aura::client::CursorClientObserver:
- virtual void OnCursorVisibilityChanged(bool is_visible) OVERRIDE;
+ void OnCursorVisibilityChanged(bool is_visible) override;
// Overridden from aura::client::FocusChangeObserver:
- virtual void OnWindowFocused(aura::Window* gained_focus,
- aura::Window* lost_focus) OVERRIDE;
+ void OnWindowFocused(aura::Window* gained_focus,
+ aura::Window* lost_focus) override;
// Overridden from aura::WindowTreeHostObserver:
- virtual void OnHostMoved(const aura::WindowTreeHost* host,
- const gfx::Point& new_origin) OVERRIDE;
+ void OnHostMoved(const aura::WindowTreeHost* host,
+ const gfx::Point& new_origin) override;
+
+ void OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params& params);
#if defined(OS_WIN)
// Sets the cutout rects from constrained windows. These are rectangles that
@@ -325,6 +328,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void UpdateMouseLockRegion();
#endif
+ void DisambiguationPopupRendered(bool success, const SkBitmap& result);
+
+ void HideDisambiguationPopup();
+
+ void ProcessDisambiguationGesture(ui::GestureEvent* event);
+
+ void ProcessDisambiguationMouse(ui::MouseEvent* event);
+
// Method to indicate if this instance is shutting down or closing.
// TODO(shrikant): Discuss around to see if it makes sense to add this method
// as part of RenderWidgetHostView.
@@ -333,25 +344,30 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Sets whether the overscroll controller should be enabled for this page.
void SetOverscrollControllerEnabled(bool enabled);
+ void SnapToPhysicalPixelBoundary();
+
OverscrollController* overscroll_controller() const {
return overscroll_controller_.get();
}
protected:
- virtual ~RenderWidgetHostViewAura();
+ ~RenderWidgetHostViewAura() override;
// Exposed for tests.
aura::Window* window() { return window_; }
- virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
- virtual DelegatedFrameHost* GetDelegatedFrameHost() const OVERRIDE;
+ SkColorType PreferredReadbackFormat() override;
+ DelegatedFrameHost* GetDelegatedFrameHost() const override;
private:
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ PopupRetainsCaptureAfterMouseRelease);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
TouchEventPositionsArentRounded);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventSyncAsync);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SwapNotifiesWindow);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, RecreateLayers);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
SkippedDelegatedFrames);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange);
@@ -368,13 +384,19 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
VisibleViewportTest);
FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
OverscrollResetsOnBlur);
+ FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest,
+ FinishCompositionByMouse);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest,
+ WebContentsViewReparent);
class WindowObserver;
friend class WindowObserver;
void UpdateCursorIfOverSelf();
- void SnapToPhysicalPixelBoundary();
+ // Tracks whether SnapToPhysicalPixelBoundary() has been called.
+ bool has_snapped_to_boundary() { return has_snapped_to_boundary_; }
+ void ResetHasSnappedToBoundary() { has_snapped_to_boundary_ = false; }
// Set the bounds of the window and handle size changes. Assumes the caller
// has already adjusted the origin of |rect| to conform to whatever coordinate
@@ -387,9 +409,15 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
ui::InputMethod* GetInputMethod() const;
+ // Sends shutdown request.
+ void Shutdown();
+
// Returns whether the widget needs an input grab to work properly.
bool NeedsInputGrab();
+ // Returns whether the widget needs to grab mouse capture to work properly.
+ bool NeedsMouseCapture();
+
// Confirm existing composition text in the webpage and ask the input method
// to cancel its ongoing composition session.
void FinishImeCompositionSession();
@@ -417,17 +445,14 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void RemovingFromRootWindow();
// DelegatedFrameHostClient implementation.
- virtual ui::Compositor* GetCompositor() const OVERRIDE;
- virtual ui::Layer* GetLayer() OVERRIDE;
- virtual RenderWidgetHostImpl* GetHost() OVERRIDE;
- virtual void SchedulePaintInRect(
- const gfx::Rect& damage_rect_in_dip) OVERRIDE;
- virtual bool IsVisible() OVERRIDE;
- virtual scoped_ptr<ResizeLock> CreateResizeLock(
- bool defer_compositor_lock) OVERRIDE;
- virtual gfx::Size DesiredFrameSize() OVERRIDE;
- virtual float CurrentDeviceScaleFactor() OVERRIDE;
- virtual gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) OVERRIDE;
+ ui::Compositor* GetCompositor() const override;
+ ui::Layer* GetLayer() override;
+ RenderWidgetHostImpl* GetHost() override;
+ bool IsVisible() override;
+ scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) override;
+ gfx::Size DesiredFrameSize() override;
+ float CurrentDeviceScaleFactor() override;
+ gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) override;
// Detaches |this| from the input method object.
void DetachFromInputMethod();
@@ -497,6 +522,8 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
ui::TextInputType text_input_type_;
// The current text input mode corresponding to HTML5 inputmode attribute.
ui::TextInputMode text_input_mode_;
+ // The current text input flags.
+ int text_input_flags_;
bool can_compose_inline_;
// Rectangles for the selection anchor and focus.
@@ -531,7 +558,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
gfx::Point unlocked_global_mouse_position_;
// Last cursor position relative to screen. Used to compute movementX/Y.
gfx::Point global_mouse_position_;
- // In mouse locked mode, we syntheticaly move the mouse cursor to the center
+ // In mouse locked mode, we synthetically move the mouse cursor to the center
// of the window when it reaches the window borders to avoid it going outside.
// This flag is used to differentiate between these synthetic mouse move
// events vs. normal mouse move events.
@@ -557,32 +584,46 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
typedef std::map<HWND, WebPluginGeometry> PluginWindowMoves;
// Contains information about each windowed plugin's clip and cutout rects (
- // from the renderer). This is needed because when the transient windoiws
+ // from the renderer). This is needed because when the transient windows
// over this view changes, we need this information in order to create a new
// region for the HWND.
PluginWindowMoves plugin_window_moves_;
+
+ // The LegacyRenderWidgetHostHWND class provides a dummy HWND which is used
+ // for accessibility, as the container for windowless plugins like
+ // Flash/Silverlight, etc and for legacy drivers for trackpoints/trackpads,
+ // etc.
+ content::LegacyRenderWidgetHostHWND* legacy_render_widget_host_HWND_;
#endif
+ bool has_snapped_to_boundary_;
+
TouchEditingClient* touch_editing_client_;
scoped_ptr<OverscrollController> overscroll_controller_;
+ // The last scroll offset of the view.
+ gfx::Vector2dF last_scroll_offset_;
+
gfx::Insets insets_;
std::vector<ui::LatencyInfo> software_latency_info_;
scoped_ptr<aura::client::ScopedTooltipDisabler> tooltip_disabler_;
+ // True when this view acts as a platform view hack for a
+ // RenderWidgetHostViewGuest.
+ bool is_guest_view_hack_;
+
base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
-#if defined(OS_WIN)
- // The LegacyRenderWidgetHostHWND class provides a dummy HWND which is used
- // for accessibility, as the container for windowless plugins like
- // Flash/Silverlight, etc and for legacy drivers for trackpoints/trackpads,
- // etc.
- scoped_ptr<content::LegacyRenderWidgetHostHWND>
- legacy_render_widget_host_HWND_;
-#endif
+ gfx::Rect disambiguation_target_rect_;
+
+ // The last scroll offset when we start to render the link disambiguation
+ // view, so we can ensure the window hasn't moved between copying from the
+ // compositing surface and showing the disambiguation popup.
+ gfx::Vector2dF disambiguation_scroll_offset_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index d05bd44da8b..511c68cec11 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -13,8 +13,12 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_metadata.h"
#include "cc/output/copy_output_request.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_manager.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
+#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
@@ -38,7 +42,6 @@
#include "ui/aura/env.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/test/aura_test_helper.h"
-#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_cursor_client.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/test/test_window_delegate.h"
@@ -47,12 +50,15 @@
#include "ui/aura/window_observer.h"
#include "ui/base/ui_base_types.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/layer_tree_owner.h"
#include "ui/compositor/test/draw_waiter_for_test.h"
-#include "ui/compositor/test/in_process_context_factory.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
-#include "ui/events/gestures/gesture_configuration.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
+#include "ui/events/test/event_generator.h"
#include "ui/wm/core/default_activation_client.h"
+#include "ui/wm/core/default_screen_position_client.h"
+#include "ui/wm/core/window_util.h"
using testing::_;
@@ -66,35 +72,6 @@ using blink::WebTouchPoint;
namespace content {
namespace {
-// Simple screen position client to test coordinate system conversion.
-class TestScreenPositionClient
- : public aura::client::ScreenPositionClient {
- public:
- TestScreenPositionClient() {}
- virtual ~TestScreenPositionClient() {}
-
- // aura::client::ScreenPositionClient overrides:
- virtual void ConvertPointToScreen(const aura::Window* window,
- gfx::Point* point) OVERRIDE {
- point->Offset(-1, -1);
- }
-
- virtual void ConvertPointFromScreen(const aura::Window* window,
- gfx::Point* point) OVERRIDE {
- point->Offset(1, 1);
- }
-
- virtual void ConvertHostPointToScreen(aura::Window* window,
- gfx::Point* point) OVERRIDE {
- ConvertPointToScreen(window, point);
- }
-
- virtual void SetBounds(aura::Window* window,
- const gfx::Rect& bounds,
- const gfx::Display& display) OVERRIDE {
- }
-};
-
class TestOverscrollDelegate : public OverscrollControllerDelegate {
public:
explicit TestOverscrollDelegate(RenderWidgetHostView* view)
@@ -104,7 +81,7 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
delta_x_(0.f),
delta_y_(0.f) {}
- virtual ~TestOverscrollDelegate() {}
+ ~TestOverscrollDelegate() override {}
OverscrollMode current_mode() const { return current_mode_; }
OverscrollMode completed_mode() const { return completed_mode_; }
@@ -119,23 +96,24 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
private:
// Overridden from OverscrollControllerDelegate:
- virtual gfx::Rect GetVisibleBounds() const OVERRIDE {
+ gfx::Rect GetVisibleBounds() const override {
return view_->IsShowing() ? view_->GetViewBounds() : gfx::Rect();
}
- virtual void OnOverscrollUpdate(float delta_x, float delta_y) OVERRIDE {
+ bool OnOverscrollUpdate(float delta_x, float delta_y) override {
delta_x_ = delta_x;
delta_y_ = delta_y;
+ return true;
}
- virtual void OnOverscrollComplete(OverscrollMode overscroll_mode) OVERRIDE {
+ void OnOverscrollComplete(OverscrollMode overscroll_mode) override {
EXPECT_EQ(current_mode_, overscroll_mode);
completed_mode_ = overscroll_mode;
current_mode_ = OVERSCROLL_NONE;
}
- virtual void OnOverscrollModeChange(OverscrollMode old_mode,
- OverscrollMode new_mode) OVERRIDE {
+ void OnOverscrollModeChange(OverscrollMode old_mode,
+ OverscrollMode new_mode) override {
EXPECT_EQ(current_mode_, old_mode);
current_mode_ = new_mode;
delta_x_ = delta_y_ = 0.f;
@@ -153,7 +131,7 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
};
// Simple observer that keeps track of changes to a window for tests.
@@ -163,7 +141,7 @@ class TestWindowObserver : public aura::WindowObserver {
: window_(window_to_observe) {
window_->AddObserver(this);
}
- virtual ~TestWindowObserver() {
+ ~TestWindowObserver() override {
if (window_)
window_->RemoveObserver(this);
}
@@ -171,7 +149,7 @@ class TestWindowObserver : public aura::WindowObserver {
bool destroyed() const { return destroyed_; }
// aura::WindowObserver overrides:
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
+ void OnWindowDestroyed(aura::Window* window) override {
CHECK_EQ(window, window_);
destroyed_ = true;
window_ = NULL;
@@ -192,9 +170,10 @@ class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
FakeFrameSubscriber(gfx::Size size, base::Callback<void(bool)> callback)
: size_(size), callback_(callback) {}
- virtual bool ShouldCaptureFrame(base::TimeTicks present_time,
- scoped_refptr<media::VideoFrame>* storage,
- DeliverFrameCallback* callback) OVERRIDE {
+ bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
+ base::TimeTicks present_time,
+ scoped_refptr<media::VideoFrame>* storage,
+ DeliverFrameCallback* callback) override {
*storage = media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
size_,
gfx::Rect(size_),
@@ -217,13 +196,14 @@ class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
public:
- FakeRenderWidgetHostViewAura(RenderWidgetHost* widget)
- : RenderWidgetHostViewAura(widget), has_resize_lock_(false) {}
+ FakeRenderWidgetHostViewAura(RenderWidgetHost* widget,
+ bool is_guest_view_hack)
+ : RenderWidgetHostViewAura(widget, is_guest_view_hack),
+ has_resize_lock_(false) {}
- virtual ~FakeRenderWidgetHostViewAura() {}
+ ~FakeRenderWidgetHostViewAura() override {}
- virtual scoped_ptr<ResizeLock> CreateResizeLock(
- bool defer_compositor_lock) OVERRIDE {
+ scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) override {
gfx::Size desired_size = window()->bounds().size();
return scoped_ptr<ResizeLock>(
new FakeResizeLock(desired_size, defer_compositor_lock));
@@ -234,12 +214,11 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
window()->GetHost()->compositor());
}
- virtual bool ShouldCreateResizeLock() OVERRIDE {
+ bool ShouldCreateResizeLock() override {
return GetDelegatedFrameHost()->ShouldCreateResizeLockForTesting();
}
- virtual void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request)
- OVERRIDE {
+ void RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) override {
last_copy_request_ = request.Pass();
if (last_copy_request_->has_texture_mailbox()) {
// Give the resulting texture a size.
@@ -256,6 +235,18 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return GetDelegatedFrameHost()->FrameProviderForTesting();
}
+ cc::SurfaceId surface_id() const {
+ return GetDelegatedFrameHost()->SurfaceIdForTesting();
+ }
+
+ bool HasFrameData() const {
+ return frame_provider() || !surface_id().is_null();
+ }
+
+ bool released_front_lock_active() const {
+ return GetDelegatedFrameHost()->ReleasedFrontLockActiveForTesting();
+ }
+
// A lock that doesn't actually do anything to the compositor, and does not
// time out.
class FakeResizeLock : public ResizeLock {
@@ -273,24 +264,24 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
class FullscreenLayoutManager : public aura::LayoutManager {
public:
explicit FullscreenLayoutManager(aura::Window* owner) : owner_(owner) {}
- virtual ~FullscreenLayoutManager() {}
+ ~FullscreenLayoutManager() override {}
// Overridden from aura::LayoutManager:
- virtual void OnWindowResized() OVERRIDE {
+ void OnWindowResized() override {
aura::Window::Windows::const_iterator i;
for (i = owner_->children().begin(); i != owner_->children().end(); ++i) {
(*i)->SetBounds(gfx::Rect());
}
}
- virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
+ void OnWindowAddedToLayout(aura::Window* child) override {
child->SetBounds(gfx::Rect());
}
- virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
- virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
- virtual void OnChildWindowVisibilityChanged(aura::Window* child,
- bool visible) OVERRIDE {}
- virtual void SetChildBounds(aura::Window* child,
- const gfx::Rect& requested_bounds) OVERRIDE {
+ void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
+ void OnWindowRemovedFromLayout(aura::Window* child) override {}
+ void OnChildWindowVisibilityChanged(aura::Window* child,
+ bool visible) override {}
+ void SetChildBounds(aura::Window* child,
+ const gfx::Rect& requested_bounds) override {
SetChildBoundsDirect(child, gfx::Rect(owner_->bounds().size()));
}
@@ -301,7 +292,7 @@ class FullscreenLayoutManager : public aura::LayoutManager {
class MockWindowObserver : public aura::WindowObserver {
public:
- MOCK_METHOD2(OnWindowPaintScheduled, void(aura::Window*, const gfx::Rect&));
+ MOCK_METHOD2(OnDelegatedFrameDamage, void(aura::Window*, const gfx::Rect&));
};
} // namespace
@@ -309,14 +300,17 @@ class MockWindowObserver : public aura::WindowObserver {
class RenderWidgetHostViewAuraTest : public testing::Test {
public:
RenderWidgetHostViewAuraTest()
- : browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
+ : widget_host_uses_shutdown_to_destroy_(false),
+ is_guest_view_hack_(false),
+ browser_thread_for_ui_(BrowserThread::UI, &message_loop_) {}
void SetUpEnvironment() {
- ui::ContextFactory* context_factory = new ui::InProcessContextFactory;
ImageTransportFactory::InitializeForUnitTests(
- scoped_ptr<ui::ContextFactory>(context_factory));
+ scoped_ptr<ImageTransportFactory>(
+ new NoTransportImageTransportFactory));
aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
- aura_test_helper_->SetUp(context_factory);
+ aura_test_helper_->SetUp(
+ ImageTransportFactory::GetInstance()->GetContextFactory());
new wm::DefaultActivationClient(aura_test_helper_->root_window());
browser_context_.reset(new TestBrowserContext);
@@ -326,7 +320,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
parent_host_ = new RenderWidgetHostImpl(
&delegate_, process_host_, MSG_ROUTING_NONE, false);
- parent_view_ = new RenderWidgetHostViewAura(parent_host_);
+ parent_view_ = new RenderWidgetHostViewAura(parent_host_,
+ is_guest_view_hack_);
parent_view_->InitAsChild(NULL);
aura::client::ParentWindowWithContext(parent_view_->GetNativeView(),
aura_test_helper_->root_window(),
@@ -335,7 +330,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
widget_host_ = new RenderWidgetHostImpl(
&delegate_, process_host_, MSG_ROUTING_NONE, false);
widget_host_->Init();
- view_ = new FakeRenderWidgetHostViewAura(widget_host_);
+ view_ = new FakeRenderWidgetHostViewAura(widget_host_, is_guest_view_hack_);
}
void TearDownEnvironment() {
@@ -343,7 +338,11 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
process_host_ = NULL;
if (view_)
view_->Destroy();
- delete widget_host_;
+
+ if (widget_host_uses_shutdown_to_destroy_)
+ widget_host_->Shutdown();
+ else
+ delete widget_host_;
parent_view_->Destroy();
delete parent_host_;
@@ -356,11 +355,20 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
ImageTransportFactory::Terminate();
}
- virtual void SetUp() { SetUpEnvironment(); }
+ void SetUp() override { SetUpEnvironment(); }
- virtual void TearDown() { TearDownEnvironment(); }
+ void TearDown() override { TearDownEnvironment(); }
+
+ void set_widget_host_uses_shutdown_to_destroy(bool use) {
+ widget_host_uses_shutdown_to_destroy_ = use;
+ }
protected:
+ // If true, then calls RWH::Shutdown() instead of deleting RWH.
+ bool widget_host_uses_shutdown_to_destroy_;
+
+ bool is_guest_view_hack_;
+
base::MessageLoopForUI message_loop_;
BrowserThreadImpl browser_thread_for_ui_;
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
@@ -384,13 +392,47 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraTest);
};
+// Helper class to instantiate RenderWidgetHostViewGuest which is backed
+// by an aura platform view.
+class RenderWidgetHostViewGuestAuraTest : public RenderWidgetHostViewAuraTest {
+ public:
+ RenderWidgetHostViewGuestAuraTest() {
+ // Use RWH::Shutdown to destroy RWH, instead of deleting.
+ // This will ensure that the RenderWidgetHostViewGuest is not leaked and
+ // is deleted properly upon RWH going away.
+ set_widget_host_uses_shutdown_to_destroy(true);
+ }
+
+ // We explicitly invoke SetUp to allow gesture debounce customization.
+ void SetUp() override {
+ is_guest_view_hack_ = true;
+
+ RenderWidgetHostViewAuraTest::SetUp();
+
+ guest_view_weak_ = (new RenderWidgetHostViewGuest(
+ widget_host_, NULL, view_->GetWeakPtr()))->GetWeakPtr();
+ }
+
+ void TearDown() override {
+ // Internal override to do nothing, we clean up ourselves in the test body.
+ // This helps us test that |guest_view_weak_| does not leak.
+ }
+
+ protected:
+ base::WeakPtr<RenderWidgetHostViewBase> guest_view_weak_;
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewGuestAuraTest);
+};
+
class RenderWidgetHostViewAuraOverscrollTest
: public RenderWidgetHostViewAuraTest {
public:
RenderWidgetHostViewAuraOverscrollTest() {}
// We explicitly invoke SetUp to allow gesture debounce customization.
- virtual void SetUp() {}
+ void SetUp() override {}
protected:
void SetUpOverscrollEnvironmentWithDebounce(int debounce_interval_in_ms) {
@@ -400,7 +442,7 @@ class RenderWidgetHostViewAuraOverscrollTest
void SetUpOverscrollEnvironment() { SetUpOverscrollEnvironmentImpl(0); }
void SetUpOverscrollEnvironmentImpl(int debounce_interval_in_ms) {
- ui::GestureConfiguration::set_scroll_debounce_interval_in_ms(
+ ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
debounce_interval_in_ms);
RenderWidgetHostViewAuraTest::SetUp();
@@ -610,7 +652,7 @@ class RenderWidgetHostViewAuraShutdownTest
public:
RenderWidgetHostViewAuraShutdownTest() {}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
// No TearDownEnvironment here, we do this explicitly during the test.
}
@@ -638,7 +680,7 @@ TEST_F(RenderWidgetHostViewAuraTest, FocusFullscreen) {
// Checks that a popup is positioned correctly relative to its parent using
// screen coordinates.
TEST_F(RenderWidgetHostViewAuraTest, PositionChildPopup) {
- TestScreenPositionClient screen_position_client;
+ wm::DefaultScreenPositionClient screen_position_client;
aura::Window* window = parent_view_->GetNativeView();
aura::Window* root = window->GetRootWindow();
@@ -714,7 +756,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupClickOutsidePopup) {
EXPECT_FALSE(parent_window->GetBoundsInRootWindow().Contains(click_point));
TestWindowObserver observer(window);
- aura::test::EventGenerator generator(window->GetRootWindow(), click_point);
+ ui::test::EventGenerator generator(window->GetRootWindow(), click_point);
generator.ClickLeftButton();
ASSERT_TRUE(parent_view_->HasFocus());
ASSERT_TRUE(observer.destroyed());
@@ -741,7 +783,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupTapOutsidePopup) {
EXPECT_FALSE(parent_window->GetBoundsInRootWindow().Contains(tap_point));
TestWindowObserver observer(window);
- aura::test::EventGenerator generator(window->GetRootWindow(), tap_point);
+ ui::test::EventGenerator generator(window->GetRootWindow(), tap_point);
generator.GestureTapAt(tap_point);
ASSERT_TRUE(parent_view_->HasFocus());
ASSERT_TRUE(observer.destroyed());
@@ -750,6 +792,60 @@ TEST_F(RenderWidgetHostViewAuraTest, DestroyPopupTapOutsidePopup) {
view_ = NULL;
}
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+
+// On Desktop Linux, select boxes need mouse capture in order to work. Test that
+// when a select box is opened via a mouse press that it retains mouse capture
+// after the mouse is released.
+TEST_F(RenderWidgetHostViewAuraTest, PopupRetainsCaptureAfterMouseRelease) {
+ parent_view_->SetBounds(gfx::Rect(10, 10, 400, 400));
+ parent_view_->Focus();
+ EXPECT_TRUE(parent_view_->HasFocus());
+
+ ui::test::EventGenerator generator(
+ parent_view_->GetNativeView()->GetRootWindow(), gfx::Point(300, 300));
+ generator.PressLeftButton();
+
+ view_->SetPopupType(blink::WebPopupTypeSelect);
+ view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
+ ASSERT_TRUE(view_->NeedsMouseCapture());
+ aura::Window* window = view_->GetNativeView();
+ EXPECT_TRUE(window->HasCapture());
+
+ generator.ReleaseLeftButton();
+ EXPECT_TRUE(window->HasCapture());
+}
+#endif
+
+// Test that select boxes close when their parent window loses focus (e.g. due
+// to an alert or system modal dialog).
+TEST_F(RenderWidgetHostViewAuraTest, PopupClosesWhenParentLosesFocus) {
+ parent_view_->SetBounds(gfx::Rect(10, 10, 400, 400));
+ parent_view_->Focus();
+ EXPECT_TRUE(parent_view_->HasFocus());
+
+ view_->SetPopupType(blink::WebPopupTypeSelect);
+ view_->InitAsPopup(parent_view_, gfx::Rect(10, 10, 100, 100));
+
+ aura::Window* popup_window = view_->GetNativeView();
+ TestWindowObserver observer(popup_window);
+
+ aura::test::TestWindowDelegate delegate;
+ scoped_ptr<aura::Window> dialog_window(new aura::Window(&delegate));
+ dialog_window->Init(aura::WINDOW_LAYER_TEXTURED);
+ aura::client::ParentWindowWithContext(
+ dialog_window.get(), popup_window, gfx::Rect());
+ dialog_window->Show();
+ wm::ActivateWindow(dialog_window.get());
+ dialog_window->Focus();
+
+ ASSERT_TRUE(wm::IsActiveWindow(dialog_window.get()));
+ EXPECT_TRUE(observer.destroyed());
+
+ widget_host_ = NULL;
+ view_ = NULL;
+}
+
// Checks that IME-composition-event state is maintained correctly.
TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
view_->InitAsChild(NULL);
@@ -776,11 +872,11 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
EXPECT_TRUE(view_->has_composition_text_);
{
const IPC::Message* msg =
- sink_->GetFirstMessageMatching(ViewMsg_ImeSetComposition::ID);
+ sink_->GetFirstMessageMatching(InputMsg_ImeSetComposition::ID);
ASSERT_TRUE(msg != NULL);
- ViewMsg_ImeSetComposition::Param params;
- ViewMsg_ImeSetComposition::Read(msg, &params);
+ InputMsg_ImeSetComposition::Param params;
+ InputMsg_ImeSetComposition::Read(msg, &params);
// composition text
EXPECT_EQ(composition_text.text, params.a);
// underlines
@@ -801,6 +897,49 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
EXPECT_FALSE(view_->has_composition_text_);
}
+// Checks that sequence of IME-composition-event and mouse-event when mouse
+// clicking to cancel the composition.
+TEST_F(RenderWidgetHostViewAuraTest, FinishCompositionByMouse) {
+ view_->InitAsChild(NULL);
+ view_->Show();
+
+ ui::CompositionText composition_text;
+ composition_text.text = base::ASCIIToUTF16("|a|b");
+
+ // Focused segment
+ composition_text.underlines.push_back(
+ ui::CompositionUnderline(0, 3, 0xff000000, true, 0x78563412));
+
+ // Non-focused segment, with different background color.
+ composition_text.underlines.push_back(
+ ui::CompositionUnderline(3, 4, 0xff000000, false, 0xefcdab90));
+
+ // Caret is at the end. (This emulates Japanese MSIME 2007 and later)
+ composition_text.selection = gfx::Range(4);
+
+ view_->SetCompositionText(composition_text);
+ EXPECT_TRUE(view_->has_composition_text_);
+ sink_->ClearMessages();
+
+ // Simulates the mouse press.
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED,
+ gfx::Point(), gfx::Point(),
+ ui::EF_LEFT_MOUSE_BUTTON, 0);
+ view_->OnMouseEvent(&mouse_event);
+
+ EXPECT_FALSE(view_->has_composition_text_);
+
+ EXPECT_EQ(2U, sink_->message_count());
+
+ if (sink_->message_count() == 2) {
+ // Verify mouse event happens after the confirm-composition event.
+ EXPECT_EQ(InputMsg_ImeConfirmComposition::ID,
+ sink_->GetMessageAt(0)->type());
+ EXPECT_EQ(InputMsg_HandleInputEvent::ID,
+ sink_->GetMessageAt(1)->type());
+ }
+}
+
// Checks that touch-event state is maintained correctly.
TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
view_->InitAsChild(NULL);
@@ -882,6 +1021,13 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
view_->touch_event_.touches[0].state);
widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
+ EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent());
+
+ // Ack'ing the outstanding event should flush the pending touch queue.
+ InputHostMsg_HandleInputEvent_ACK_Params ack;
+ ack.type = blink::WebInputEvent::TouchStart;
+ ack.state = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ widget_host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent());
ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0,
@@ -1147,13 +1293,14 @@ scoped_ptr<cc::CompositorFrame> MakeDelegatedFrame(float scale_factor,
scoped_ptr<cc::RenderPass> pass = cc::RenderPass::Create();
pass->SetNew(
- cc::RenderPass::Id(1, 1), gfx::Rect(size), damage, gfx::Transform());
+ cc::RenderPassId(1, 1), gfx::Rect(size), damage, gfx::Transform());
frame->delegated_frame_data->render_pass_list.push_back(pass.Pass());
return frame.Pass();
}
// Resizing in fullscreen mode should send the up-to-date screen info.
-TEST_F(RenderWidgetHostViewAuraTest, FullscreenResize) {
+// http://crbug.com/324350
+TEST_F(RenderWidgetHostViewAuraTest, DISABLED_FullscreenResize) {
aura::Window* root_window = aura_test_helper_->root_window();
root_window->SetLayoutManager(new FullscreenLayoutManager(root_window));
view_->InitAsFullscreen(parent_view_);
@@ -1223,12 +1370,12 @@ TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
view_->window_->AddObserver(&observer);
// Delegated renderer path
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, view_size, view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_,
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_,
gfx::Rect(5, 5, 5, 5)));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, view_size, gfx::Rect(5, 5, 5, 5)));
@@ -1237,6 +1384,35 @@ TEST_F(RenderWidgetHostViewAuraTest, SwapNotifiesWindow) {
view_->window_->RemoveObserver(&observer);
}
+// Recreating the layers for a window should cause Surface destruction to
+// depend on both layers.
+TEST_F(RenderWidgetHostViewAuraTest, RecreateLayers) {
+ gfx::Size view_size(100, 100);
+ gfx::Rect view_rect(view_size);
+
+ view_->InitAsChild(NULL);
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ view_->SetSize(view_size);
+ view_->WasShown();
+
+ view_->OnSwapCompositorFrame(0,
+ MakeDelegatedFrame(1.f, view_size, view_rect));
+ scoped_ptr<ui::LayerTreeOwner> cloned_owner(
+ wm::RecreateLayers(view_->GetNativeView()));
+
+ cc::SurfaceId id = view_->GetDelegatedFrameHost()->SurfaceIdForTesting();
+ if (!id.is_null()) {
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ cc::Surface* surface = manager->GetSurfaceForId(id);
+ EXPECT_TRUE(surface);
+ // Should be a SurfaceSequence for both the original and new layers.
+ EXPECT_EQ(2u, surface->GetDestructionDependencyCount());
+ }
+}
+
TEST_F(RenderWidgetHostViewAuraTest, Resize) {
gfx::Size size1(100, 100);
gfx::Size size2(200, 200);
@@ -1254,7 +1430,6 @@ TEST_F(RenderWidgetHostViewAuraTest, Resize) {
root_window->GetHost()->compositor());
ViewHostMsg_UpdateRect_Params update_params;
update_params.view_size = size1;
- update_params.scale_factor = 1.f;
update_params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
widget_host_->OnMessageReceived(
ViewHostMsg_UpdateRect(widget_host_->GetRoutingID(), update_params));
@@ -1308,10 +1483,23 @@ TEST_F(RenderWidgetHostViewAuraTest, Resize) {
ui::DrawWaiterForTest::WaitForCommit(
root_window->GetHost()->compositor());
EXPECT_EQ(size3.ToString(), view_->GetRequestedRendererSize().ToString());
+ cc::SurfaceId surface_id = view_->surface_id();
+ int swap_index = 0;
+ int resize_index = 1;
+ if (!surface_id.is_null()) {
+ // Frame ack is sent only due to a draw callback with surfaces.
+ ImageTransportFactory::GetInstance()
+ ->GetSurfaceManager()
+ ->GetSurfaceForId(surface_id)
+ ->RunDrawCallbacks();
+ swap_index = 1;
+ resize_index = 0;
+ }
EXPECT_EQ(2u, sink_->message_count());
- EXPECT_EQ(ViewMsg_SwapCompositorFrameAck::ID, sink_->GetMessageAt(0)->type());
+ EXPECT_EQ(ViewMsg_SwapCompositorFrameAck::ID,
+ sink_->GetMessageAt(swap_index)->type());
{
- const IPC::Message* msg = sink_->GetMessageAt(1);
+ const IPC::Message* msg = sink_->GetMessageAt(resize_index);
EXPECT_EQ(ViewMsg_Resize::ID, msg->type());
ViewMsg_Resize::Param params;
ViewMsg_Resize::Read(msg, &params);
@@ -1339,7 +1527,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
view_->window_->AddObserver(&observer);
// A full frame of damage.
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1348,7 +1536,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
// A partial damage frame.
gfx::Rect partial_view_rect(30, 30, 20, 20);
EXPECT_CALL(observer,
- OnWindowPaintScheduled(view_->window_, partial_view_rect));
+ OnDelegatedFrameDamage(view_->window_, partial_view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1360,14 +1548,14 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
// This frame is dropped.
gfx::Rect dropped_damage_rect_1(10, 20, 30, 40);
- EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(_, _)).Times(0);
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_1));
testing::Mock::VerifyAndClearExpectations(&observer);
view_->RunOnCompositingDidCommit();
gfx::Rect dropped_damage_rect_2(40, 50, 10, 20);
- EXPECT_CALL(observer, OnWindowPaintScheduled(_, _)).Times(0);
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(_, _)).Times(0);
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, dropped_damage_rect_2));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1378,7 +1566,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
gfx::Rect new_damage_rect(5, 6, 10, 10);
EXPECT_CALL(observer,
- OnWindowPaintScheduled(view_->window_, view_rect));
+ OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, new_damage_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1386,7 +1574,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
// A partial damage frame, this should not be dropped.
EXPECT_CALL(observer,
- OnWindowPaintScheduled(view_->window_, partial_view_rect));
+ OnDelegatedFrameDamage(view_->window_, partial_view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, partial_view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1402,7 +1590,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SkippedDelegatedFrames) {
view_->SetSize(view_rect.size());
// This frame should not be dropped.
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, view_rect.size(), view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1426,14 +1614,14 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
view_->window_->AddObserver(&observer);
// Swap a frame.
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(
0, MakeDelegatedFrame(1.f, frame_size, view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
view_->RunOnCompositingDidCommit();
// Swap a frame with a different surface id.
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1446,7 +1634,7 @@ TEST_F(RenderWidgetHostViewAuraTest, OutputSurfaceIdChange) {
view_->RunOnCompositingDidCommit();
// Swap another frame, with a different surface id.
- EXPECT_CALL(observer, OnWindowPaintScheduled(view_->window_, view_rect));
+ EXPECT_CALL(observer, OnDelegatedFrameDamage(view_->window_, view_rect));
view_->OnSwapCompositorFrame(3,
MakeDelegatedFrame(1.f, frame_size, view_rect));
testing::Mock::VerifyAndClearExpectations(&observer);
@@ -1474,7 +1662,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
hosts[i] = new RenderWidgetHostImpl(
&delegate_, process_host_, MSG_ROUTING_NONE, false);
hosts[i]->Init();
- views[i] = new FakeRenderWidgetHostViewAura(hosts[i]);
+ views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
views[i]->InitAsChild(NULL);
aura::client::ParentWindowWithContext(
views[i]->GetNativeView(),
@@ -1488,64 +1676,99 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
views[i]->WasShown();
views[i]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_TRUE(views[i]->frame_provider());
+ EXPECT_TRUE(views[i]->HasFrameData());
views[i]->WasHidden();
}
// There should be max_renderer_frames with a frame in it, and one without it.
// Since the logic is LRU eviction, the first one should be without.
- EXPECT_FALSE(views[0]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
for (size_t i = 1; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->frame_provider());
+ EXPECT_TRUE(views[i]->HasFrameData());
// LRU renderer is [0], make it visible, it shouldn't evict anything yet.
views[0]->WasShown();
- EXPECT_FALSE(views[0]->frame_provider());
- EXPECT_TRUE(views[1]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
+ EXPECT_TRUE(views[1]->HasFrameData());
+ // Since [0] doesn't have a frame, it should be waiting for the renderer to
+ // give it one.
+ EXPECT_TRUE(views[0]->released_front_lock_active());
// Swap a frame on it, it should evict the next LRU [1].
views[0]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_TRUE(views[0]->frame_provider());
- EXPECT_FALSE(views[1]->frame_provider());
+ EXPECT_TRUE(views[0]->HasFrameData());
+ EXPECT_FALSE(views[1]->HasFrameData());
+ // Now that [0] got a frame, it shouldn't be waiting any more.
+ EXPECT_FALSE(views[0]->released_front_lock_active());
views[0]->WasHidden();
// LRU renderer is [1], still hidden. Swap a frame on it, it should evict
// the next LRU [2].
views[1]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_TRUE(views[0]->frame_provider());
- EXPECT_TRUE(views[1]->frame_provider());
- EXPECT_FALSE(views[2]->frame_provider());
+ EXPECT_TRUE(views[0]->HasFrameData());
+ EXPECT_TRUE(views[1]->HasFrameData());
+ EXPECT_FALSE(views[2]->HasFrameData());
for (size_t i = 3; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->frame_provider());
+ EXPECT_TRUE(views[i]->HasFrameData());
// Make all renderers but [0] visible and swap a frame on them, keep [0]
// hidden, it becomes the LRU.
for (size_t i = 1; i < renderer_count; ++i) {
views[i]->WasShown();
+ // The renderers who don't have a frame should be waiting. The ones that
+ // have a frame should not.
+ // In practice, [1] has a frame, but anything after has its frame evicted.
+ EXPECT_EQ(!views[i]->HasFrameData(),
+ views[i]->released_front_lock_active());
views[i]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_TRUE(views[i]->frame_provider());
+ // Now everyone has a frame.
+ EXPECT_FALSE(views[i]->released_front_lock_active());
+ EXPECT_TRUE(views[i]->HasFrameData());
}
- EXPECT_FALSE(views[0]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
// Swap a frame on [0], it should be evicted immediately.
views[0]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_FALSE(views[0]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
// Make [0] visible, and swap a frame on it. Nothing should be evicted
// although we're above the limit.
views[0]->WasShown();
+ // We don't have a frame, wait.
+ EXPECT_TRUE(views[0]->released_front_lock_active());
views[0]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
+ EXPECT_FALSE(views[0]->released_front_lock_active());
for (size_t i = 0; i < renderer_count; ++i)
- EXPECT_TRUE(views[i]->frame_provider());
+ EXPECT_TRUE(views[i]->HasFrameData());
// Make [0] hidden, it should evict its frame.
views[0]->WasHidden();
- EXPECT_FALSE(views[0]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
+
+ // Make [0] visible, don't give it a frame, it should be waiting.
+ views[0]->WasShown();
+ EXPECT_TRUE(views[0]->released_front_lock_active());
+ // Make [0] hidden, it should stop waiting.
+ views[0]->WasHidden();
+ EXPECT_FALSE(views[0]->released_front_lock_active());
+
+ // Make [1] hidden, resize it. It should drop its frame.
+ views[1]->WasHidden();
+ EXPECT_TRUE(views[1]->HasFrameData());
+ gfx::Size size2(200, 200);
+ views[1]->SetSize(size2);
+ EXPECT_FALSE(views[1]->HasFrameData());
+ // Show it, it should block until we give it a frame.
+ views[1]->WasShown();
+ EXPECT_TRUE(views[1]->released_front_lock_active());
+ views[1]->OnSwapCompositorFrame(
+ 1, MakeDelegatedFrame(1.f, size2, gfx::Rect(size2)));
+ EXPECT_FALSE(views[1]->released_front_lock_active());
for (size_t i = 0; i < renderer_count - 1; ++i)
views[i]->WasHidden();
@@ -1567,9 +1790,9 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
views[renderer_count - 1]->WasHidden();
for (size_t i = 0; i < renderer_count; ++i) {
if (i + 2 < renderer_count)
- EXPECT_FALSE(views[i]->frame_provider());
+ EXPECT_FALSE(views[i]->HasFrameData());
else
- EXPECT_TRUE(views[i]->frame_provider());
+ EXPECT_TRUE(views[i]->HasFrameData());
}
HostSharedBitmapManager::current()->ProcessRemoved(
base::GetCurrentProcessHandle());
@@ -1601,7 +1824,7 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
hosts[i] = new RenderWidgetHostImpl(
&delegate_, process_host_, MSG_ROUTING_NONE, false);
hosts[i]->Init();
- views[i] = new FakeRenderWidgetHostViewAura(hosts[i]);
+ views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
views[i]->InitAsChild(NULL);
aura::client::ParentWindowWithContext(
views[i]->GetNativeView(),
@@ -1616,25 +1839,25 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
views[i]->WasShown();
views[i]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_TRUE(views[i]->frame_provider());
+ EXPECT_TRUE(views[i]->HasFrameData());
}
// If we hide [0], then [0] should be evicted.
views[0]->WasHidden();
- EXPECT_FALSE(views[0]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
// If we lock [0] before hiding it, then [0] should not be evicted.
views[0]->WasShown();
views[0]->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, view_rect));
- EXPECT_TRUE(views[0]->frame_provider());
+ EXPECT_TRUE(views[0]->HasFrameData());
views[0]->GetDelegatedFrameHost()->LockResources();
views[0]->WasHidden();
- EXPECT_TRUE(views[0]->frame_provider());
+ EXPECT_TRUE(views[0]->HasFrameData());
// If we unlock [0] now, then [0] should be evicted.
views[0]->GetDelegatedFrameHost()->UnlockResources();
- EXPECT_FALSE(views[0]->frame_provider());
+ EXPECT_FALSE(views[0]->HasFrameData());
for (size_t i = 0; i < renderer_count; ++i) {
views[i]->Destroy();
@@ -1661,6 +1884,7 @@ TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
// Save the frame provider.
scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
view_->frame_provider();
+ cc::SurfaceId surface_id = view_->surface_id();
// This frame will have the same number of physical pixels, but has a new
// scale on it.
@@ -1670,7 +1894,10 @@ TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
// When we get a new frame with the same frame size in physical pixels, but a
// different scale, we should generate a new frame provider, as the final
// result will need to be scaled differently to the screen.
- EXPECT_NE(frame_provider.get(), view_->frame_provider());
+ if (frame_provider.get())
+ EXPECT_NE(frame_provider.get(), view_->frame_provider());
+ else
+ EXPECT_NE(surface_id, view_->surface_id());
}
class RenderWidgetHostViewAuraCopyRequestTest
@@ -1715,8 +1942,7 @@ TEST_F(RenderWidgetHostViewAuraCopyRequestTest, DestroyedAfterCopyRequest) {
EXPECT_EQ(0, callback_count_);
EXPECT_FALSE(view_->last_copy_request_);
- view_->BeginFrameSubscription(
- frame_subscriber.PassAs<RenderWidgetHostViewFrameSubscriber>());
+ view_->BeginFrameSubscription(frame_subscriber.Pass());
view_->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, view_rect.size(), gfx::Rect(view_rect)));
@@ -2492,9 +2718,10 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDirectionChange) {
EXPECT_EQ(0U, sink_->message_count());
// Send another update event, but in the reverse direction. The overscroll
- // controller will consume the event, and reset the overscroll mode.
+ // controller will not consume the event, because it is not triggering
+ // gesture-nav.
SimulateGestureScrollUpdateEvent(-260, 0, 0);
- EXPECT_EQ(0U, sink_->message_count());
+ EXPECT_EQ(1U, sink_->message_count());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
// Since the overscroll mode has been reset, the next scroll update events
@@ -2504,6 +2731,33 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollDirectionChange) {
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
}
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ OverscrollDirectionChangeMouseWheel) {
+ SetUpOverscrollEnvironment();
+
+ // Send wheel event and receive ack as not consumed.
+ SimulateWheelEvent(125, -5, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(0U, sink_->message_count());
+
+ // Send another wheel event, but in the reverse direction. The overscroll
+ // controller will not consume the event, because it is not triggering
+ // gesture-nav.
+ SimulateWheelEvent(-260, 0, 0, true);
+ EXPECT_EQ(1U, sink_->message_count());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+
+ // Since the overscroll mode has been reset, the next wheel event should reach
+ // the renderer.
+ SimulateWheelEvent(-20, 0, 0, true);
+ EXPECT_EQ(1U, sink_->message_count());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+}
+
// Tests that if a mouse-move event completes the overscroll gesture, future
// move events do reach the renderer.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
@@ -2682,4 +2936,11 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollResetsOnBlur) {
EXPECT_EQ(3U, sink_->message_count());
}
+// Tests that when view initiated shutdown happens (i.e. RWHView is deleted
+// before RWH), we clean up properly and don't leak the RWHVGuest.
+TEST_F(RenderWidgetHostViewGuestAuraTest, GuestViewDoesNotLeak) {
+ TearDownEnvironment();
+ ASSERT_FALSE(guest_view_weak_.get());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
index d5f58e0aab7..b11990ae990 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -12,7 +12,6 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/content_switches_internal.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
-#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
@@ -367,7 +366,7 @@ const int kFlushInputRateInUs = 16666;
RenderWidgetHostViewBase::RenderWidgetHostViewBase()
: popup_type_(blink::WebPopupTypeNone),
- background_opaque_(true),
+ background_color_(SK_ColorWHITE),
mouse_locked_(false),
showing_context_menu_(false),
selection_text_offset_(0),
@@ -375,7 +374,8 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase()
current_device_scale_factor_(0),
current_display_rotation_(gfx::Display::ROTATE_0),
pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
- renderer_frame_number_(0) {
+ renderer_frame_number_(0),
+ weak_factory_(this) {
}
RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
@@ -386,12 +386,16 @@ bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){
return false;
}
-void RenderWidgetHostViewBase::SetBackgroundOpaque(bool opaque) {
- background_opaque_ = opaque;
+void RenderWidgetHostViewBase::SetBackgroundColor(SkColor color) {
+ background_color_ = color;
+}
+
+void RenderWidgetHostViewBase::SetBackgroundColorToDefault() {
+ SetBackgroundColor(SK_ColorWHITE);
}
bool RenderWidgetHostViewBase::GetBackgroundOpaque() {
- return background_opaque_;
+ return SkColorGetA(background_color_) == SK_AlphaOPAQUE;
}
gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
@@ -402,7 +406,7 @@ gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
display.device_scale_factor()));
}
-float RenderWidgetHostViewBase::GetOverdrawBottomHeight() const {
+float RenderWidgetHostViewBase::GetTopControlsLayoutHeight() const {
return 0.f;
}
@@ -485,27 +489,28 @@ blink::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
}
BrowserAccessibilityManager*
- RenderWidgetHostViewBase::GetBrowserAccessibilityManager() const {
- return browser_accessibility_manager_.get();
-}
-
-void RenderWidgetHostViewBase::CreateBrowserAccessibilityManagerIfNeeded() {
+RenderWidgetHostViewBase::CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) {
+ NOTREACHED();
+ return NULL;
}
-void RenderWidgetHostViewBase::SetBrowserAccessibilityManager(
- BrowserAccessibilityManager* manager) {
- browser_accessibility_manager_.reset(manager);
+void RenderWidgetHostViewBase::AccessibilityShowMenu(const gfx::Point& point) {
}
-void RenderWidgetHostViewBase::OnAccessibilitySetFocus(int acc_obj_id) {
+gfx::Point RenderWidgetHostViewBase::AccessibilityOriginInScreen(
+ const gfx::Rect& bounds) {
+ return bounds.origin();
}
-void RenderWidgetHostViewBase::AccessibilityShowMenu(int acc_obj_id) {
+gfx::AcceleratedWidget
+ RenderWidgetHostViewBase::AccessibilityGetAcceleratedWidget() {
+ return gfx::kNullAcceleratedWidget;
}
-gfx::Point RenderWidgetHostViewBase::AccessibilityOriginInScreen(
- const gfx::Rect& bounds) {
- return bounds.origin();
+gfx::NativeViewAccessible
+ RenderWidgetHostViewBase::AccessibilityGetNativeViewAccessible() {
+ return NULL;
}
void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
@@ -535,6 +540,10 @@ bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
return true;
}
+base::WeakPtr<RenderWidgetHostViewBase> RenderWidgetHostViewBase::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
scoped_ptr<SyntheticGestureTarget>
RenderWidgetHostViewBase::CreateSyntheticGestureTarget() {
RenderWidgetHostImpl* host =
@@ -596,8 +605,21 @@ void RenderWidgetHostViewBase::FlushInput() {
impl->FlushInput();
}
-SkBitmap::Config RenderWidgetHostViewBase::PreferredReadbackFormat() {
- return SkBitmap::kARGB_8888_Config;
+SkColorType RenderWidgetHostViewBase::PreferredReadbackFormat() {
+ return kN32_SkColorType;
+}
+
+void RenderWidgetHostViewBase::OnTextSurroundingSelectionResponse(
+ const base::string16& content,
+ size_t start_offset,
+ size_t end_offset) {
+ NOTIMPLEMENTED();
+}
+
+void RenderWidgetHostViewBase::ShowDisambiguationPopup(
+ const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap) {
+ NOTIMPLEMENTED();
}
gfx::Size RenderWidgetHostViewBase::GetVisibleViewportSize() const {
@@ -608,4 +630,65 @@ void RenderWidgetHostViewBase::SetInsets(const gfx::Insets& insets) {
NOTIMPLEMENTED();
}
+// static
+blink::WebScreenOrientationType
+RenderWidgetHostViewBase::GetOrientationTypeForMobile(
+ const gfx::Display& display) {
+ int angle = display.RotationAsDegree();
+ const gfx::Rect& bounds = display.bounds();
+
+ // Whether the device's natural orientation is portrait.
+ bool natural_portrait = false;
+ if (angle == 0 || angle == 180) // The device is in its natural orientation.
+ natural_portrait = bounds.height() >= bounds.width();
+ else
+ natural_portrait = bounds.height() <= bounds.width();
+
+ switch (angle) {
+ case 0:
+ return natural_portrait ? blink::WebScreenOrientationPortraitPrimary
+ : blink::WebScreenOrientationLandscapePrimary;
+ case 90:
+ return natural_portrait ? blink::WebScreenOrientationLandscapePrimary
+ : blink::WebScreenOrientationPortraitSecondary;
+ case 180:
+ return natural_portrait ? blink::WebScreenOrientationPortraitSecondary
+ : blink::WebScreenOrientationLandscapeSecondary;
+ case 270:
+ return natural_portrait ? blink::WebScreenOrientationLandscapeSecondary
+ : blink::WebScreenOrientationPortraitPrimary;
+ default:
+ NOTREACHED();
+ return blink::WebScreenOrientationPortraitPrimary;
+ }
+}
+
+// static
+blink::WebScreenOrientationType
+RenderWidgetHostViewBase::GetOrientationTypeForDesktop(
+ const gfx::Display& display) {
+ static int primary_landscape_angle = -1;
+ static int primary_portrait_angle = -1;
+
+ int angle = display.RotationAsDegree();
+ const gfx::Rect& bounds = display.bounds();
+ bool is_portrait = bounds.height() >= bounds.width();
+
+ if (is_portrait && primary_portrait_angle == -1)
+ primary_portrait_angle = angle;
+
+ if (!is_portrait && primary_landscape_angle == -1)
+ primary_landscape_angle = angle;
+
+ if (is_portrait) {
+ return primary_portrait_angle == angle
+ ? blink::WebScreenOrientationPortraitPrimary
+ : blink::WebScreenOrientationPortraitSecondary;
+ }
+
+ return primary_landscape_angle == angle
+ ? blink::WebScreenOrientationLandscapePrimary
+ : blink::WebScreenOrientationLandscapeSecondary;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.h b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
index 9bf2e60a48a..9e3a4f384ca 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_base.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
@@ -22,6 +22,7 @@
#include "content/common/input/input_event_ack_state.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ipc/ipc_listener.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
#include "ui/base/ime/text_input_mode.h"
@@ -35,10 +36,7 @@
class SkBitmap;
struct AccessibilityHostMsg_EventParams;
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
struct ViewHostMsg_SelectionBounds_Params;
-struct ViewHostMsg_TextInputState_Params;
namespace media {
class VideoFrame;
@@ -49,6 +47,7 @@ struct WebScreenInfo;
}
namespace content {
+class BrowserAccessibilityDelegate;
class BrowserAccessibilityManager;
class SyntheticGesture;
class SyntheticGestureTarget;
@@ -57,28 +56,35 @@ struct DidOverscrollParams;
struct NativeWebKeyboardEvent;
struct WebPluginGeometry;
+// TODO(Sikugu): Though we have the return status of the result here,
+// we should add the reason for failure as a new parameter to handle cases
+// efficiently.
+typedef const base::Callback<void(bool, const SkBitmap&)>
+ CopyFromCompositingSurfaceCallback;
+
// Basic implementation shared by concrete RenderWidgetHostView subclasses.
class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
public IPC::Listener {
public:
- virtual ~RenderWidgetHostViewBase();
+ ~RenderWidgetHostViewBase() override;
// RenderWidgetHostView implementation.
- virtual void SetBackgroundOpaque(bool opaque) OVERRIDE;
- virtual bool GetBackgroundOpaque() OVERRIDE;
- virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
- virtual bool IsShowingContextMenu() const OVERRIDE;
- virtual void SetShowingContextMenu(bool showing_menu) OVERRIDE;
- virtual base::string16 GetSelectedText() const OVERRIDE;
- virtual bool IsMouseLocked() OVERRIDE;
- virtual gfx::Size GetVisibleViewportSize() const OVERRIDE;
- virtual void SetInsets(const gfx::Insets& insets) OVERRIDE;
- virtual void BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
- virtual void EndFrameSubscription() OVERRIDE;
+ void SetBackgroundColor(SkColor color) override;
+ void SetBackgroundColorToDefault() final;
+ bool GetBackgroundOpaque() override;
+ ui::TextInputClient* GetTextInputClient() override;
+ bool IsShowingContextMenu() const override;
+ void SetShowingContextMenu(bool showing_menu) override;
+ base::string16 GetSelectedText() const override;
+ bool IsMouseLocked() override;
+ gfx::Size GetVisibleViewportSize() const override;
+ void SetInsets(const gfx::Insets& insets) override;
+ void BeginFrameSubscription(
+ scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
+ void EndFrameSubscription() override;
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// Called by the host when the input flush has completed.
void OnDidFlushInput();
@@ -87,11 +93,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
blink::WebPopupType GetPopupType();
- // Get the BrowserAccessibilityManager if it exists, may return NULL.
- BrowserAccessibilityManager* GetBrowserAccessibilityManager() const;
-
- void SetBrowserAccessibilityManager(BrowserAccessibilityManager* manager);
-
// Return a value that is incremented each time the renderer swaps a new frame
// to the view.
uint32 RendererFrameNumber();
@@ -107,6 +108,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// changed since the last time.
bool HasDisplayPropertyChanged(gfx::NativeView view);
+ base::WeakPtr<RenderWidgetHostViewBase> GetWeakPtr();
+
//----------------------------------------------------------------------------
// The following methods can be overridden by derived classes.
@@ -122,9 +125,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// The size of the view's backing surface in non-DPI-adjusted pixels.
virtual gfx::Size GetPhysicalBackingSize() const;
- // The height of the physical backing surface that is overdrawn opaquely in
- // the browser, for example by an on-screen-keyboard (in DPI-adjusted pixels).
- virtual float GetOverdrawBottomHeight() const;
+ // The amount that the viewport size given to Blink is shrunk by the URL-bar.
+ virtual float GetTopControlsLayoutHeight() const;
// Called prior to forwarding input event messages to the renderer, giving
// the view a chance to perform in-process event filtering or processing.
@@ -150,16 +152,16 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// Return true if frame subscription is supported on this platform.
virtual bool CanSubscribeFrame() const;
- // Create a BrowserAccessibilityManager for this view if it's possible to
- // create one and if one doesn't exist already. Some ports may not create
- // one depending on the current state.
- virtual void CreateBrowserAccessibilityManagerIfNeeded();
+ // Create a BrowserAccessibilityManager for this view.
+ virtual BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate);
- virtual void OnAccessibilitySetFocus(int acc_obj_id);
- virtual void AccessibilityShowMenu(int acc_obj_id);
+ virtual void AccessibilityShowMenu(const gfx::Point& point);
virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds);
+ virtual gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget();
+ virtual gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible();
- virtual SkBitmap::Config PreferredReadbackFormat();
+ virtual SkColorType PreferredReadbackFormat();
// Informs that the focused DOM node has changed.
virtual void FocusedNodeChanged(bool is_editable_node) {}
@@ -219,8 +221,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual void SetIsLoading(bool is_loading) = 0;
// Updates the type of the input method attached to the view.
- virtual void TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) = 0;
+ virtual void TextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode mode,
+ bool can_compose_inline,
+ int flags) = 0;
// Cancel the ongoing composition of the input method attached to the view.
virtual void ImeCancelComposition() = 0;
@@ -229,6 +233,13 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual void RenderProcessGone(base::TerminationStatus status,
int error_code) = 0;
+ // Notifies the View that the renderer's host has ceased to exist.
+ // The default implementation of this is a no-op. This hack exists to fix
+ // a crash on the branch.
+ // TODO(ccameron): Clean this up.
+ // http://crbug.com/404828
+ virtual void RenderWidgetHostGone() {}
+
// Tells the View to destroy itself.
virtual void Destroy() = 0;
@@ -243,30 +254,27 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual void SelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params) = 0;
- // Notifies the view that the scroll offset has changed.
- virtual void ScrollOffsetChanged() = 0;
-
- // Copies the contents of the compositing surface into the given
- // (uninitialized) PlatformCanvas if any.
- // The rectangle region specified with |src_subrect| is copied from the
- // contents, scaled to |dst_size|, and written to |output|.
- // |callback| is invoked with true on success, false otherwise. |output| can
- // be initialized even on failure.
- // A smaller region than |src_subrect| may be copied if the underlying surface
- // is smaller than |src_subrect|.
- // NOTE: |callback| is called asynchronously.
+ // Copies the contents of the compositing surface, providing a new SkBitmap
+ // result via an asynchronously-run |callback|. |src_subrect| is specified in
+ // layer space coordinates for the current platform (e.g., DIP for Aura/Mac,
+ // physical for Android), and is the region to be copied from this view. The
+ // copy is then scaled to a SkBitmap of size |dst_size|. |callback| is run
+ // with true on success, false otherwise. A smaller region than |src_subrect|
+ // may be copied if the underlying surface is smaller than |src_subrect|.
virtual void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
- const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) = 0;
-
- // Copies a given subset of the compositing surface's content into a YV12
- // VideoFrame, and invokes a callback with a success/fail parameter. |target|
- // must contain an allocated, YV12 video frame of the intended size. If the
- // copy rectangle does not match |target|'s size, the copied content will be
- // scaled and letterboxed with black borders. The copy will happen
- // asynchronously. This operation will fail if there is no available
+ CopyFromCompositingSurfaceCallback& callback,
+ const SkColorType color_type) = 0;
+
+ // Copies the contents of the compositing surface, populating the given
+ // |target| with YV12 image data. |src_subrect| is specified in layer space
+ // coordinates for the current platform (e.g., DIP for Aura/Mac, physical for
+ // Android), and is the region to be copied from this view. The copy is then
+ // scaled and letterboxed with black borders to fit |target|. Finally,
+ // |callback| is asynchronously run with true/false for
+ // success/failure. |target| must point to an allocated, YV12 video frame of
+ // the intended size. This operation will fail if there is no available
// compositing surface.
virtual void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
@@ -281,33 +289,22 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// IsSurfaceAvailableForCopy() and HasAcceleratedSurface().
virtual bool CanCopyToVideoFrame() const = 0;
- // Called when an accelerated compositing surface is initialized.
- virtual void AcceleratedSurfaceInitialized(int host_id, int route_id) = 0;
- // |params.window| and |params.surface_id| indicate which accelerated
- // surface's buffers swapped. |params.renderer_id| and |params.route_id|
- // are used to formulate a reply to the GPU process to prevent it from getting
- // too far ahead. They may all be zero, in which case no flow control is
- // enforced; this case is currently used for accelerated plugins.
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params_in_pixel,
- int gpu_host_id) = 0;
- // Similar to above, except |params.(x|y|width|height)| define the region
- // of the surface that changed.
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params_in_pixel,
- int gpu_host_id) = 0;
-
- // Release the accelerated surface temporarily. It will be recreated on the
- // next swap buffers or post sub buffer.
- virtual void AcceleratedSurfaceSuspend() = 0;
-
- virtual void AcceleratedSurfaceRelease() = 0;
+ // DEPRECATED. Called when an accelerated compositing surface is initialized.
+ virtual void AcceleratedSurfaceInitialized(int route_id) {}
// Return true if the view has an accelerated surface that contains the last
// presented frame for the view. If |desired_size| is non-empty, true is
// returned only if the accelerated surface size matches.
virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) = 0;
+ // Compute the orientation type of the display assuming it is a mobile device.
+ static blink::WebScreenOrientationType GetOrientationTypeForMobile(
+ const gfx::Display& display);
+
+ // Compute the orientation type of the display assuming it is a desktop.
+ static blink::WebScreenOrientationType GetOrientationTypeForDesktop(
+ const gfx::Display& display);
+
virtual void GetScreenInfo(blink::WebScreenInfo* results) = 0;
// Gets the bounds of the window, in screen coordinates.
@@ -315,14 +312,18 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual gfx::GLSurfaceHandle GetCompositingSurface() = 0;
+ // Called by the RenderFrameHost when it receives an IPC response to a
+ // TextSurroundingSelectionRequest.
virtual void OnTextSurroundingSelectionResponse(const base::string16& content,
size_t start_offset,
- size_t end_offset) {};
+ size_t end_offset);
-#if defined(OS_ANDROID)
- virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
- const SkBitmap& zoomed_bitmap) = 0;
+ // Called by the RenderWidgetHost when an ambiguous gesture is detected to
+ // show the disambiguation popup bubble.
+ virtual void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
+ const SkBitmap& zoomed_bitmap);
+#if defined(OS_ANDROID)
// Instructs the view to not drop the surface even when the view is hidden.
virtual void LockCompositingSurface() = 0;
virtual void UnlockCompositingSurface() = 0;
@@ -337,7 +338,7 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
const NativeWebKeyboardEvent& event) = 0;
#endif
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
// Updates the range of the marked text in an IME composition.
virtual void ImeCompositionRangeChanged(
const gfx::Range& range,
@@ -380,8 +381,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// autofill...).
blink::WebPopupType popup_type_;
- // When false, the background of the web content is not fully opaque.
- bool background_opaque_;
+ // The background color of the web content.
+ SkColor background_color_;
// While the mouse is locked, the cursor is hidden from the user. Mouse events
// are still generated. However, the position they report is the last known
@@ -417,15 +418,14 @@ protected:
private:
void FlushInput();
- // Manager of the tree representation of the WebKit render tree.
- scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_;
-
gfx::Rect current_display_area_;
uint32 renderer_frame_number_;
base::OneShotTimer<RenderWidgetHostViewBase> flush_input_timer_;
+ base::WeakPtrFactory<RenderWidgetHostViewBase> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBase);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc
new file mode 100644
index 00000000000..6cc861d8927
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base_unittest.cc
@@ -0,0 +1,124 @@
+// Copyright 2014 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 "content/browser/renderer_host/render_widget_host_view_base.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
+#include "ui/gfx/display.h"
+
+namespace content {
+
+namespace {
+
+gfx::Display CreateDisplay(int width, int height, int angle) {
+ gfx::Display display;
+ display.SetRotationAsDegree(angle);
+ display.set_bounds(gfx::Rect(width, height));
+
+ return display;
+}
+
+} // anonymous namespace
+
+TEST(RenderWidgetHostViewBaseTest, OrientationTypeForMobile) {
+ // Square display (width == height).
+ {
+ gfx::Display display = CreateDisplay(100, 100, 0);
+ EXPECT_EQ(blink::WebScreenOrientationPortraitPrimary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(200, 200, 90);
+ EXPECT_EQ(blink::WebScreenOrientationLandscapePrimary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(0, 0, 180);
+ EXPECT_EQ(blink::WebScreenOrientationPortraitSecondary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(10000, 10000, 270);
+ EXPECT_EQ(blink::WebScreenOrientationLandscapeSecondary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+ }
+
+ // natural width > natural height.
+ {
+ gfx::Display display = CreateDisplay(1, 0, 0);
+ EXPECT_EQ(blink::WebScreenOrientationLandscapePrimary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(19999, 20000, 90);
+ EXPECT_EQ(blink::WebScreenOrientationPortraitSecondary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(200, 100, 180);
+ EXPECT_EQ(blink::WebScreenOrientationLandscapeSecondary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(1, 10000, 270);
+ EXPECT_EQ(blink::WebScreenOrientationPortraitPrimary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+ }
+
+ // natural width < natural height.
+ {
+ gfx::Display display = CreateDisplay(0, 1, 0);
+ EXPECT_EQ(blink::WebScreenOrientationPortraitPrimary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(20000, 19999, 90);
+ EXPECT_EQ(blink::WebScreenOrientationLandscapePrimary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(100, 200, 180);
+ EXPECT_EQ(blink::WebScreenOrientationPortraitSecondary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+
+ display = CreateDisplay(10000, 1, 270);
+ EXPECT_EQ(blink::WebScreenOrientationLandscapeSecondary,
+ RenderWidgetHostViewBase::GetOrientationTypeForMobile(display));
+ }
+}
+
+TEST(RenderWidgetHostViewBaseTest, OrientationTypeForDesktop) {
+ // On Desktop, the primary orientation is the first computed one so a test
+ // similar to OrientationTypeForMobile is not possible.
+ // Instead this test will only check one configuration and verify that the
+ // method reports two landscape and two portrait orientations with one primary
+ // and one secondary for each.
+
+ // natural width > natural height.
+ {
+ gfx::Display display = CreateDisplay(1, 0, 0);
+ blink::WebScreenOrientationType landscape_1 =
+ RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
+ EXPECT_TRUE(landscape_1 == blink::WebScreenOrientationLandscapePrimary ||
+ landscape_1 == blink::WebScreenOrientationLandscapeSecondary);
+
+ display = CreateDisplay(200, 100, 180);
+ blink::WebScreenOrientationType landscape_2 =
+ RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
+ EXPECT_TRUE(landscape_2 == blink::WebScreenOrientationLandscapePrimary ||
+ landscape_2 == blink::WebScreenOrientationLandscapeSecondary);
+
+ EXPECT_NE(landscape_1, landscape_2);
+
+ display = CreateDisplay(19999, 20000, 90);
+ blink::WebScreenOrientationType portrait_1 =
+ RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
+ EXPECT_TRUE(portrait_1 == blink::WebScreenOrientationPortraitPrimary ||
+ portrait_1 == blink::WebScreenOrientationPortraitSecondary);
+
+ display = CreateDisplay(1, 10000, 270);
+ blink::WebScreenOrientationType portrait_2 =
+ RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
+ EXPECT_TRUE(portrait_2 == blink::WebScreenOrientationPortraitPrimary ||
+ portrait_2 == blink::WebScreenOrientationPortraitSecondary);
+
+ EXPECT_NE(portrait_1, portrait_2);
+
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 34327a164fb..a04a117f292 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -29,7 +29,7 @@
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
@@ -61,7 +61,7 @@ class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
callback_invoke_count_(0),
frames_captured_(0) {}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &test_dir_));
}
@@ -157,7 +157,7 @@ class RenderWidgetHostViewBrowserTest : public ContentBrowserTest {
&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
base::Unretained(this),
run_loop.QuitClosure()),
- SkBitmap::kARGB_8888_Config);
+ kN32_SkColorType);
run_loop.Run();
if (frames_captured())
@@ -207,7 +207,7 @@ class CompositingRenderWidgetHostViewBrowserTest
explicit CompositingRenderWidgetHostViewBrowserTest()
: compositing_mode_(GetParam()) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
if (compositing_mode_ == SOFTWARE_COMPOSITING)
UseSoftwareCompositing();
RenderWidgetHostViewBrowserTest::SetUp();
@@ -218,7 +218,7 @@ class CompositingRenderWidgetHostViewBrowserTest
test_dir().AppendASCII("rwhv_compositing_animation.html"));
}
- virtual bool SetUpSourceSurface(const char* wait_message) OVERRIDE {
+ bool SetUpSourceSurface(const char* wait_message) override {
content::DOMMessageQueue message_queue;
NavigateToURL(shell(), TestUrl());
if (wait_message != NULL) {
@@ -247,9 +247,10 @@ class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
: callback_(callback) {
}
- virtual bool ShouldCaptureFrame(base::TimeTicks present_time,
- scoped_refptr<media::VideoFrame>* storage,
- DeliverFrameCallback* callback) OVERRIDE {
+ bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
+ base::TimeTicks present_time,
+ scoped_refptr<media::VideoFrame>* storage,
+ DeliverFrameCallback* callback) override {
// Only allow one frame capture to be made. Otherwise, the compositor could
// start multiple captures, unbounded, and eventually its own limiter logic
// will begin invoking |callback| with a |false| result. This flakes out
@@ -291,9 +292,7 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
base::Bind(&RenderWidgetHostViewBrowserTest::FinishCopyFromBackingStore,
base::Unretained(this),
run_loop.QuitClosure()),
- SkBitmap::kARGB_8888_Config);
- // Delete the surface before the callback is run.
- GetRenderWidgetHostView()->AcceleratedSurfaceRelease();
+ kN32_SkColorType);
run_loop.Run();
EXPECT_EQ(1, callback_invoke_count());
@@ -329,8 +328,6 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTest,
gfx::Rect(view->GetViewBounds().size()), dest, base::Bind(
&RenderWidgetHostViewBrowserTest::FinishCopyFromCompositingSurface,
base::Unretained(this), run_loop.QuitClosure()));
- // Delete the surface before the callback is run.
- view->AcceleratedSurfaceRelease();
run_loop.Run();
EXPECT_EQ(1, callback_invoke_count());
@@ -411,7 +408,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
allowable_error_(0),
test_url_("data:text/html,<!doctype html>") {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
EnablePixelOutput();
CompositingRenderWidgetHostViewBrowserTest::SetUp();
}
@@ -429,7 +426,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
expected_copy_from_compositing_surface_bitmap_;
EXPECT_EQ(expected_bitmap.width(), bitmap.width());
EXPECT_EQ(expected_bitmap.height(), bitmap.height());
- EXPECT_EQ(expected_bitmap.config(), bitmap.config());
+ EXPECT_EQ(expected_bitmap.colorType(), bitmap.colorType());
SkAutoLockPixels expected_bitmap_lock(expected_bitmap);
SkAutoLockPixels bitmap_lock(bitmap);
int fails = 0;
@@ -488,17 +485,11 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
media::SkCanvasVideoRenderer video_renderer;
SkBitmap bitmap;
- bitmap.allocPixels(SkImageInfo::Make(video_frame->visible_rect().width(),
- video_frame->visible_rect().height(),
- kPMColor_SkColorType,
- kPremul_SkAlphaType));
- bitmap.eraseColor(SK_ColorTRANSPARENT);
+ bitmap.allocN32Pixels(video_frame->visible_rect().width(),
+ video_frame->visible_rect().height());
+ // Don't clear the canvas because drawing a video frame by Src mode.
SkCanvas canvas(bitmap);
-
- video_renderer.Paint(video_frame.get(),
- &canvas,
- video_frame->visible_rect(),
- 0xff);
+ video_renderer.Copy(video_frame, &canvas);
CopyFromCompositingSurfaceCallback(quit_callback,
result,
@@ -514,24 +505,19 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
void SetAllowableError(int amount) { allowable_error_ = amount; }
void SetExcludeRect(gfx::Rect exclude) { exclude_rect_ = exclude; }
- virtual GURL TestUrl() OVERRIDE {
- return GURL(test_url_);
- }
+ GURL TestUrl() override { return GURL(test_url_); }
void SetTestUrl(std::string url) { test_url_ = url; }
// Loads a page two boxes side-by-side, each half the width of
// |html_rect_size|, and with different background colors. The test then
// copies from |copy_rect| region of the page into a bitmap of size
- // |output_size|, and compares that with a bitmap of size
- // |expected_bitmap_size|.
+ // |output_size|, and examines the resulting bitmap/VideoFrame.
// Note that |output_size| may not have the same size as |copy_rect| (e.g.
- // when the output is scaled). Also note that |expected_bitmap_size| may not
- // be the same as |output_size| (e.g. when the device scale factor is not 1).
+ // when the output is scaled).
void PerformTestWithLeftRightRects(const gfx::Size& html_rect_size,
const gfx::Rect& copy_rect,
const gfx::Size& output_size,
- const gfx::Size& expected_bitmap_size,
bool video_frame) {
const gfx::Size box_size(html_rect_size.width() / 2,
html_rect_size.height());
@@ -592,7 +578,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
GiveItSomeTime();
SkBitmap expected_bitmap;
- SetupLeftRightBitmap(expected_bitmap_size, &expected_bitmap);
+ SetupLeftRightBitmap(output_size, &expected_bitmap);
SetExpectedCopyFromCompositingSurfaceResult(true, expected_bitmap);
base::RunLoop run_loop;
@@ -605,9 +591,9 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
- expected_bitmap_size,
- gfx::Rect(expected_bitmap_size),
- expected_bitmap_size,
+ output_size,
+ gfx::Rect(output_size),
+ output_size,
base::TimeDelta());
base::Callback<void(bool success)> callback =
@@ -620,16 +606,16 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
video_frame,
callback);
} else {
-#if defined(USE_AURA)
- if (!content::GpuDataManager::GetInstance()
- ->CanUseGpuBrowserCompositor()) {
- // Skia rendering can cause color differences, particularly in the
- // middle two columns.
- SetAllowableError(2);
- SetExcludeRect(
- gfx::Rect(output_size.width() / 2 - 1, 0, 2, output_size.height()));
+ if (IsDelegatedRendererEnabled()) {
+ if (!content::GpuDataManager::GetInstance()
+ ->CanUseGpuBrowserCompositor()) {
+ // Skia rendering can cause color differences, particularly in the
+ // middle two columns.
+ SetAllowableError(2);
+ SetExcludeRect(gfx::Rect(
+ output_size.width() / 2 - 1, 0, 2, output_size.height()));
+ }
}
-#endif
base::Callback<void(bool, const SkBitmap&)> callback =
base::Bind(&CompositingRenderWidgetHostViewBrowserTestTabCapture::
@@ -639,7 +625,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
rwhvp->CopyFromCompositingSurface(copy_rect,
output_size,
callback,
- SkBitmap::kARGB_8888_Config);
+ kN32_SkColorType);
}
run_loop.Run();
}
@@ -647,9 +633,7 @@ class CompositingRenderWidgetHostViewBrowserTestTabCapture
// Sets up |bitmap| to have size |copy_size|. It floods the left half with
// #0ff and the right half with #ff0.
void SetupLeftRightBitmap(const gfx::Size& copy_size, SkBitmap* bitmap) {
- bitmap->setConfig(
- SkBitmap::kARGB_8888_Config, copy_size.width(), copy_size.height());
- bitmap->allocPixels();
+ bitmap->allocN32Pixels(copy_size.width(), copy_size.height());
// Left half is #0ff.
bitmap->eraseARGB(255, 0, 255, 255);
// Right half is #ff0.
@@ -681,13 +665,11 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
CopyFromCompositingSurface_Origin_Unscaled) {
gfx::Rect copy_rect(400, 300);
gfx::Size output_size = copy_rect.size();
- gfx::Size expected_bitmap_size = output_size;
gfx::Size html_rect_size(400, 300);
bool video_frame = false;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
@@ -695,13 +677,11 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
CopyFromCompositingSurface_Origin_Scaled) {
gfx::Rect copy_rect(400, 300);
gfx::Size output_size(200, 100);
- gfx::Size expected_bitmap_size = output_size;
gfx::Size html_rect_size(400, 300);
bool video_frame = false;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
@@ -712,13 +692,11 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
gfx::Size(60, 60));
gfx::Size output_size = copy_rect.size();
- gfx::Size expected_bitmap_size = output_size;
gfx::Size html_rect_size(400, 300);
bool video_frame = false;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
@@ -729,13 +707,11 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(30, 30),
gfx::Size(60, 60));
gfx::Size output_size(20, 10);
- gfx::Size expected_bitmap_size = output_size;
gfx::Size html_rect_size(400, 300);
bool video_frame = false;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
@@ -746,13 +722,11 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
copy_rect = gfx::Rect(copy_rect.CenterPoint() - gfx::Vector2d(45, 30),
gfx::Size(90, 60));
gfx::Size output_size = copy_rect.size();
- gfx::Size expected_bitmap_size = output_size;
gfx::Size html_rect_size(400, 300);
bool video_frame = true;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
@@ -764,101 +738,176 @@ IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewBrowserTestTabCapture,
gfx::Size(90, 60));
// Scale to 30 x 20 (preserve aspect ratio).
gfx::Size output_size(30, 20);
- gfx::Size expected_bitmap_size = output_size;
gfx::Size html_rect_size(400, 300);
bool video_frame = true;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
-class CompositingRenderWidgetHostViewTabCaptureHighDPI
+class CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI
: public CompositingRenderWidgetHostViewBrowserTestTabCapture {
public:
- CompositingRenderWidgetHostViewTabCaptureHighDPI() : kScale(2.f) {}
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI() {}
- virtual void SetUpOnMainThread() OVERRIDE {
- CommandLine* cmd = CommandLine::ForCurrentProcess();
+ protected:
+ void SetUpCommandLine(base::CommandLine* cmd) override {
+ CompositingRenderWidgetHostViewBrowserTestTabCapture::SetUpCommandLine(cmd);
cmd->AppendSwitchASCII(switches::kForceDeviceScaleFactor,
base::StringPrintf("%f", scale()));
-#if defined(OS_WIN)
- gfx::ForceHighDPISupportForTesting(scale());
- gfx::EnableHighDPISupport();
-#endif
}
- float scale() const { return kScale; }
-
- private:
- virtual bool ShouldContinueAfterTestURLLoad() OVERRIDE {
+ bool ShouldContinueAfterTestURLLoad() override {
// Short-circuit a pass for platforms where setting up high-DPI fails.
- if (ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(
- GetScaleFactorForView(GetRenderWidgetHostView()))) != scale()) {
- LOG(WARNING) << "Blindly passing this test: failed to set up "
- "scale factor: " << scale();
+ const float actual_scale_factor =
+ GetScaleFactorForView(GetRenderWidgetHostView());
+ if (actual_scale_factor != scale()) {
+ LOG(WARNING) << "Blindly passing this test; unable to force device scale "
+ << "factor: seems to be " << actual_scale_factor
+ << " but expected " << scale();
return false;
}
+ VLOG(1) << ("Successfully forced device scale factor. Moving forward with "
+ "this test! :-)");
return true;
}
- const float kScale;
+ static float scale() { return 2.0f; }
- DISALLOW_COPY_AND_ASSIGN(CompositingRenderWidgetHostViewTabCaptureHighDPI);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI);
};
-IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI,
- CopyFromCompositingSurface) {
+// ImageSkia (related to ResourceBundle) implementation crashes the process on
+// Windows when this content_browsertest forces a device scale factor.
+// http://crbug.com/399349
+//
+// These tests are flaky on ChromeOS builders. See http://crbug.com/406018.
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
+#define MAYBE_CopyToBitmap_EntireRegion DISABLED_CopyToBitmap_EntireRegion
+#define MAYBE_CopyToBitmap_CenterRegion DISABLED_CopyToBitmap_CenterRegion
+#define MAYBE_CopyToBitmap_ScaledResult DISABLED_CopyToBitmap_ScaledResult
+#define MAYBE_CopyToVideoFrame_EntireRegion \
+ DISABLED_CopyToVideoFrame_EntireRegion
+#define MAYBE_CopyToVideoFrame_CenterRegion \
+ DISABLED_CopyToVideoFrame_CenterRegion
+#define MAYBE_CopyToVideoFrame_ScaledResult \
+ DISABLED_CopyToVideoFrame_ScaledResult
+#else
+#define MAYBE_CopyToBitmap_EntireRegion CopyToBitmap_EntireRegion
+#define MAYBE_CopyToBitmap_CenterRegion CopyToBitmap_CenterRegion
+#define MAYBE_CopyToBitmap_ScaledResult CopyToBitmap_ScaledResult
+#define MAYBE_CopyToVideoFrame_EntireRegion CopyToVideoFrame_EntireRegion
+#define MAYBE_CopyToVideoFrame_CenterRegion CopyToVideoFrame_CenterRegion
+#define MAYBE_CopyToVideoFrame_ScaledResult CopyToVideoFrame_ScaledResult
+#endif
+
+IN_PROC_BROWSER_TEST_P(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ MAYBE_CopyToBitmap_EntireRegion) {
+ gfx::Size html_rect_size(200, 150);
gfx::Rect copy_rect(200, 150);
- gfx::Size output_size = copy_rect.size();
- gfx::Size expected_bitmap_size =
- gfx::ToFlooredSize(gfx::ScaleSize(output_size, scale(), scale()));
+ // Scale the output size so that, internally, scaling is not occurring.
+ gfx::Size output_size =
+ gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
+ bool video_frame = false;
+ PerformTestWithLeftRightRects(html_rect_size,
+ copy_rect,
+ output_size,
+ video_frame);
+}
+
+IN_PROC_BROWSER_TEST_P(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ MAYBE_CopyToBitmap_CenterRegion) {
gfx::Size html_rect_size(200, 150);
+ // Grab 90x60 pixels from the center of the tab contents.
+ gfx::Rect copy_rect =
+ gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
+ gfx::Size(90, 60));
+ // Scale the output size so that, internally, scaling is not occurring.
+ gfx::Size output_size =
+ gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
bool video_frame = false;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
-IN_PROC_BROWSER_TEST_P(CompositingRenderWidgetHostViewTabCaptureHighDPI,
- CopyFromCompositingSurfaceVideoFrame) {
+IN_PROC_BROWSER_TEST_P(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ MAYBE_CopyToBitmap_ScaledResult) {
+ gfx::Size html_rect_size(200, 100);
+ gfx::Rect copy_rect(200, 100);
+ // Output is being down-scaled since output_size is in phyiscal pixels.
+ gfx::Size output_size(200, 100);
+ bool video_frame = false;
+ PerformTestWithLeftRightRects(html_rect_size,
+ copy_rect,
+ output_size,
+ video_frame);
+}
+
+IN_PROC_BROWSER_TEST_P(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ MAYBE_CopyToVideoFrame_EntireRegion) {
+ gfx::Size html_rect_size(200, 150);
+ gfx::Rect copy_rect(200, 150);
+ // Scale the output size so that, internally, scaling is not occurring.
+ gfx::Size output_size =
+ gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
+ bool video_frame = true;
+ PerformTestWithLeftRightRects(html_rect_size,
+ copy_rect,
+ output_size,
+ video_frame);
+}
+
+IN_PROC_BROWSER_TEST_P(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ MAYBE_CopyToVideoFrame_CenterRegion) {
gfx::Size html_rect_size(200, 150);
// Grab 90x60 pixels from the center of the tab contents.
gfx::Rect copy_rect =
gfx::Rect(gfx::Rect(html_rect_size).CenterPoint() - gfx::Vector2d(45, 30),
gfx::Size(90, 60));
- gfx::Size output_size = copy_rect.size();
- gfx::Size expected_bitmap_size =
- gfx::ToFlooredSize(gfx::ScaleSize(output_size, scale(), scale()));
+ // Scale the output size so that, internally, scaling is not occurring.
+ gfx::Size output_size =
+ gfx::ToRoundedSize(gfx::ScaleSize(copy_rect.size(), scale()));
bool video_frame = true;
PerformTestWithLeftRightRects(html_rect_size,
copy_rect,
output_size,
- expected_bitmap_size,
video_frame);
}
-#if !defined(USE_AURA) && !defined(OS_MACOSX)
-// TODO(danakj): Remove this case when GTK linux is no more and move the
-// values inline to testing::Values() below.
-static const CompositingMode kAllCompositingModes[] = {GL_COMPOSITING};
-#else
-static const CompositingMode kAllCompositingModes[] = {GL_COMPOSITING,
- SOFTWARE_COMPOSITING};
-#endif
+IN_PROC_BROWSER_TEST_P(
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ MAYBE_CopyToVideoFrame_ScaledResult) {
+ gfx::Size html_rect_size(200, 100);
+ gfx::Rect copy_rect(200, 100);
+ // Output is being down-scaled since output_size is in phyiscal pixels.
+ gfx::Size output_size(200, 100);
+ bool video_frame = true;
+ PerformTestWithLeftRightRects(html_rect_size,
+ copy_rect,
+ output_size,
+ video_frame);
+}
INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
CompositingRenderWidgetHostViewBrowserTest,
- testing::ValuesIn(kAllCompositingModes));
+ testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
CompositingRenderWidgetHostViewBrowserTestTabCapture,
- testing::ValuesIn(kAllCompositingModes));
-INSTANTIATE_TEST_CASE_P(GLAndSoftwareCompositing,
- CompositingRenderWidgetHostViewTabCaptureHighDPI,
- testing::ValuesIn(kAllCompositingModes));
+ testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
+INSTANTIATE_TEST_CASE_P(
+ GLAndSoftwareCompositing,
+ CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
+ testing::Values(GL_COMPOSITING, SOFTWARE_COMPOSITING));
#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
index 8fb2e4a5fe8..2be8d87df02 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -19,7 +19,7 @@
#include "base/time/time.h"
#include "content/browser/compositor/browser_compositor_view_mac.h"
#include "content/browser/compositor/delegated_frame_host.h"
-#include "content/browser/renderer_host/compositing_iosurface_layer_mac.h"
+#include "content/browser/compositor/io_surface_layer_mac.h"
#include "content/browser/renderer_host/display_link_mac.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/software_frame_manager.h"
@@ -30,12 +30,11 @@
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "ui/base/cocoa/base_view.h"
-
-struct ViewHostMsg_TextInputState_Params;
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/gfx/display_observer.h"
namespace content {
-class CompositingIOSurfaceMac;
-class CompositingIOSurfaceContext;
+class BrowserCompositorviewMac;
class RenderWidgetHostViewMac;
class RenderWidgetHostViewMacEditCommandHelper;
class WebContents;
@@ -46,11 +45,8 @@ class Compositor;
class Layer;
}
-@class BrowserCompositorViewMac;
-@class CompositingIOSurfaceLayer;
@class FullscreenWindowManager;
@protocol RenderWidgetHostViewMacDelegate;
-@class SoftwareLayer;
@class ToolTip;
@protocol RenderWidgetHostViewMacOwner
@@ -71,7 +67,6 @@ class Layer;
base::scoped_nsobject<NSObject<RenderWidgetHostViewMacDelegate>>
responderDelegate_;
BOOL canBeKeyView_;
- BOOL takesFocusOnlyOnMouseDown_;
BOOL closeOnDeactivate_;
scoped_ptr<content::RenderWidgetHostViewMacEditCommandHelper>
editCommand_helper_;
@@ -153,14 +148,6 @@ class Layer;
// Event monitor for scroll wheel end event.
id endWheelMonitor_;
- // OpenGL Support:
-
- // recursive globalFrameDidChange protection:
- BOOL handlingGlobalFrameDidChange_;
-
- // The scale factor of the display this view is in.
- float deviceScaleFactor_;
-
// If true then escape key down events are suppressed until the first escape
// key up event. (The up event is suppressed as well). This is used by the
// flash fullscreen code to avoid sending a key up event without a matching
@@ -172,7 +159,6 @@ class Layer;
@property(nonatomic, readonly) BOOL suppressNextEscapeKeyUp;
- (void)setCanBeKeyView:(BOOL)can;
-- (void)setTakesFocusOnlyOnMouseDown:(BOOL)b;
- (void)setCloseOnDeactivate:(BOOL)b;
- (void)setToolTipAtMousePoint:(NSString *)string;
// True for always-on-top special windows (e.g. Balloons and Panels).
@@ -215,15 +201,20 @@ class RenderWidgetHostImpl;
class CONTENT_EXPORT RenderWidgetHostViewMac
: public RenderWidgetHostViewBase,
public DelegatedFrameHostClient,
+ public BrowserCompositorViewMacClient,
public IPC::Sender,
- public SoftwareFrameManagerClient,
- public CompositingIOSurfaceLayerClient {
+ public gfx::DisplayObserver {
public:
// The view will associate itself with the given widget. The native view must
// be hooked up immediately to the view hierarchy, or else when it is
// deleted it will delete this out from under the caller.
- explicit RenderWidgetHostViewMac(RenderWidgetHost* widget);
- virtual ~RenderWidgetHostViewMac();
+ //
+ // When |is_guest_view_hack| is true, this view isn't really the view for
+ // the |widget|, a RenderWidgetHostViewGuest is.
+ // TODO(lazyboy): Remove |is_guest_view_hack| once BrowserPlugin has migrated
+ // to use RWHVChildFrame (http://crbug.com/330264).
+ RenderWidgetHostViewMac(RenderWidgetHost* widget, bool is_guest_view_hack);
+ ~RenderWidgetHostViewMac() override;
RenderWidgetHostViewCocoa* cocoa_view() const { return cocoa_view_; }
@@ -232,120 +223,107 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// |delegate| should be set at most once.
CONTENT_EXPORT void SetDelegate(
NSObject<RenderWidgetHostViewMacDelegate>* delegate);
- void SetAllowOverlappingViews(bool overlapping);
+ void SetAllowPauseForResizeOrRepaint(bool allow);
// RenderWidgetHostView implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void InitAsChild(gfx::NativeView parent_view) OVERRIDE;
- virtual RenderWidgetHost* GetRenderWidgetHost() const OVERRIDE;
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual void SetBounds(const gfx::Rect& rect) OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const OVERRIDE;
- virtual gfx::NativeViewAccessible GetNativeViewAccessible() OVERRIDE;
- virtual bool HasFocus() const OVERRIDE;
- virtual bool IsSurfaceAvailableForCopy() const OVERRIDE;
- virtual void Show() OVERRIDE;
- virtual void Hide() OVERRIDE;
- virtual bool IsShowing() OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual void SetShowingContextMenu(bool showing) OVERRIDE;
- virtual void SetActive(bool active) OVERRIDE;
- virtual void SetTakesFocusOnlyOnMouseDown(bool flag) OVERRIDE;
- virtual void SetWindowVisibility(bool visible) OVERRIDE;
- virtual void WindowFrameChanged() OVERRIDE;
- virtual void ShowDefinitionForSelection() OVERRIDE;
- virtual bool SupportsSpeech() const OVERRIDE;
- virtual void SpeakSelection() OVERRIDE;
- virtual bool IsSpeaking() const OVERRIDE;
- virtual void StopSpeaking() OVERRIDE;
- virtual void SetBackgroundOpaque(bool opaque) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void InitAsChild(gfx::NativeView parent_view) override;
+ RenderWidgetHost* GetRenderWidgetHost() const override;
+ void SetSize(const gfx::Size& size) override;
+ void SetBounds(const gfx::Rect& rect) override;
+ gfx::Vector2dF GetLastScrollOffset() const override;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeViewId GetNativeViewId() const override;
+ gfx::NativeViewAccessible GetNativeViewAccessible() override;
+ bool HasFocus() const override;
+ bool IsSurfaceAvailableForCopy() const override;
+ void Show() override;
+ void Hide() override;
+ bool IsShowing() override;
+ gfx::Rect GetViewBounds() const override;
+ void SetShowingContextMenu(bool showing) override;
+ void SetActive(bool active) override;
+ void SetWindowVisibility(bool visible) override;
+ void WindowFrameChanged() override;
+ void ShowDefinitionForSelection() override;
+ bool SupportsSpeech() const override;
+ void SpeakSelection() override;
+ bool IsSpeaking() const override;
+ void StopSpeaking() override;
+ void SetBackgroundColor(SkColor color) override;
// Implementation of RenderWidgetHostViewBase.
- virtual void InitAsPopup(RenderWidgetHostView* parent_host_view,
- const gfx::Rect& pos) OVERRIDE;
- virtual void InitAsFullscreen(
- RenderWidgetHostView* reference_host_view) OVERRIDE;
- virtual void WasShown() OVERRIDE;
- virtual void WasHidden() OVERRIDE;
- virtual void MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void Blur() OVERRIDE;
- virtual void UpdateCursor(const WebCursor& cursor) OVERRIDE;
- virtual void SetIsLoading(bool is_loading) OVERRIDE;
- virtual void TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) OVERRIDE;
- virtual void ImeCancelComposition() OVERRIDE;
- virtual void ImeCompositionRangeChanged(
+ void InitAsPopup(RenderWidgetHostView* parent_host_view,
+ const gfx::Rect& pos) override;
+ void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
+ void WasShown() override;
+ void WasHidden() override;
+ void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
+ void Focus() override;
+ void Blur() override;
+ void UpdateCursor(const WebCursor& cursor) override;
+ void SetIsLoading(bool is_loading) override;
+ void TextInputTypeChanged(ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) override;
+ void ImeCancelComposition() override;
+ void ImeCompositionRangeChanged(
const gfx::Range& range,
- const std::vector<gfx::Rect>& character_bounds) OVERRIDE;
- virtual void RenderProcessGone(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual void SetTooltipText(const base::string16& tooltip_text) OVERRIDE;
- virtual void SelectionChanged(const base::string16& text,
- size_t offset,
- const gfx::Range& range) OVERRIDE;
- virtual void SelectionBoundsChanged(
- const ViewHostMsg_SelectionBounds_Params& params) OVERRIDE;
- virtual void ScrollOffsetChanged() OVERRIDE;
- virtual void CopyFromCompositingSurface(
+ const std::vector<gfx::Rect>& character_bounds) override;
+ void RenderProcessGone(base::TerminationStatus status,
+ int error_code) override;
+ void RenderWidgetHostGone() override;
+ void Destroy() override;
+ void SetTooltipText(const base::string16& tooltip_text) override;
+ void SelectionChanged(const base::string16& text,
+ size_t offset,
+ const gfx::Range& range) override;
+ void SelectionBoundsChanged(
+ const ViewHostMsg_SelectionBounds_Params& params) override;
+ void CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- SkBitmap::Config config) OVERRIDE;
- virtual void CopyFromCompositingSurfaceToVideoFrame(
+ SkColorType color_type) override;
+ void CopyFromCompositingSurfaceToVideoFrame(
const gfx::Rect& src_subrect,
const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool CanCopyToVideoFrame() const OVERRIDE;
- virtual bool CanSubscribeFrame() const OVERRIDE;
- virtual void BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) OVERRIDE;
- virtual void EndFrameSubscription() OVERRIDE;
- virtual void OnSwapCompositorFrame(
- uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
- virtual void AcceleratedSurfaceInitialized(int host_id,
- int route_id) OVERRIDE;
- virtual void CreateBrowserAccessibilityManagerIfNeeded() OVERRIDE;
- virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds)
- OVERRIDE;
- virtual void OnAccessibilitySetFocus(int acc_obj_id) OVERRIDE;
- virtual void AccessibilityShowMenu(int acc_obj_id) OVERRIDE;
- virtual bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) OVERRIDE;
-
- virtual void AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) OVERRIDE;
- virtual void AcceleratedSurfaceSuspend() OVERRIDE;
- virtual void AcceleratedSurfaceRelease() OVERRIDE;
- virtual bool HasAcceleratedSurface(const gfx::Size& desired_size) OVERRIDE;
- virtual void GetScreenInfo(blink::WebScreenInfo* results) OVERRIDE;
- virtual gfx::Rect GetBoundsInRootWindow() OVERRIDE;
- virtual gfx::GLSurfaceHandle GetCompositingSurface() OVERRIDE;
-
- virtual bool LockMouse() OVERRIDE;
- virtual void UnlockMouse() OVERRIDE;
- virtual void WheelEventAck(const blink::WebMouseWheelEvent& event,
- InputEventAckState ack_result) OVERRIDE;
+ const base::Callback<void(bool)>& callback) override;
+ bool CanCopyToVideoFrame() const override;
+ bool CanSubscribeFrame() const override;
+ void BeginFrameSubscription(
+ scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
+ void EndFrameSubscription() override;
+ void OnSwapCompositorFrame(uint32 output_surface_id,
+ scoped_ptr<cc::CompositorFrame> frame) override;
+ BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) override;
+ gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) override;
+ void AccessibilityShowMenu(const gfx::Point& point) override;
+ bool PostProcessEventForPluginIme(
+ const NativeWebKeyboardEvent& event) override;
+
+ bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
+ void GetScreenInfo(blink::WebScreenInfo* results) override;
+ gfx::Rect GetBoundsInRootWindow() override;
+ gfx::GLSurfaceHandle GetCompositingSurface() override;
+
+ bool LockMouse() override;
+ void UnlockMouse() override;
+ void WheelEventAck(const blink::WebMouseWheelEvent& event,
+ InputEventAckState ack_result) override;
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* message) OVERRIDE;
-
- // SoftwareFrameManagerClient implementation:
- virtual void SoftwareFrameWasFreed(
- uint32 output_surface_id, unsigned frame_id) OVERRIDE;
- virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE;
+ bool Send(IPC::Message* message) override;
- virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
+ SkColorType PreferredReadbackFormat() override;
- // CompositingIOSurfaceLayerClient implementation.
- virtual void AcceleratedLayerDidDrawFrame(bool succeeded) OVERRIDE;
+ // gfx::DisplayObserver implementation.
+ void OnDisplayAdded(const gfx::Display& new_display) override;
+ void OnDisplayRemoved(const gfx::Display& old_display) override;
+ void OnDisplayMetricsChanged(const gfx::Display& display,
+ uint32_t metrics) override;
// Forwards the mouse event to the renderer.
void ForwardMouseEvent(const blink::WebMouseEvent& event);
@@ -359,26 +337,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
const std::string& selected_text() const { return selected_text_; }
- // Update the IOSurface to be drawn and call setNeedsDisplay on
- // |cocoa_view_|.
- void CompositorSwapBuffers(IOSurfaceID surface_handle,
- const gfx::Size& size,
- float scale_factor,
- const std::vector<ui::LatencyInfo>& latency_info);
-
- // Called when a GPU error is detected. Posts a task to destroy all
- // compositing state.
- void GotAcceleratedCompositingError();
-
- // Sets the overlay view, which should be drawn in the same IOSurface
- // atop of this view, if both views are drawing accelerated content.
- // Overlay is stored as a weak ptr.
- void SetOverlayView(RenderWidgetHostViewMac* overlay,
- const gfx::Point& offset);
-
- // Removes the previously set overlay view.
- void RemoveOverlayView();
-
// Returns true and stores first rectangle for character range if the
// requested |range| is already cached, otherwise returns false.
// Exposed for testing.
@@ -417,30 +375,52 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
bool can_compose_inline_;
// The background CoreAnimation layer which is hosted by |cocoa_view_|.
- // The compositing or software layers will be added as sublayers to this.
base::scoped_nsobject<CALayer> background_layer_;
- // The CoreAnimation layer for software compositing. This should be NULL
- // when software compositing is not in use.
- base::scoped_nsobject<SoftwareLayer> software_layer_;
-
- // Accelerated compositing structures. These may be dynamically created and
- // destroyed together in Create/DestroyCompositedIOSurfaceAndLayer.
- base::scoped_nsobject<CompositingIOSurfaceLayer> compositing_iosurface_layer_;
- scoped_refptr<CompositingIOSurfaceMac> compositing_iosurface_;
- scoped_refptr<CompositingIOSurfaceContext> compositing_iosurface_context_;
+ // The state of |delegated_frame_host_| and |browser_compositor_view_| to
+ // manage being visible, hidden, or occluded.
+ enum BrowserCompositorViewState {
+ // Effects:
+ // - |browser_compositor_view_| exists and |delegated_frame_host_| is
+ // visible.
+ // Happens when:
+ // - |render_widet_host_| is in the visible state (this includes when
+ // the tab isn't visible, but tab capture is enabled).
+ BrowserCompositorActive,
+ // Effects:
+ // - |browser_compositor_view_| exists, but |delegated_frame_host_| has
+ // been hidden.
+ // Happens when:
+ // - The |render_widget_host_| is hidden, but |cocoa_view_| is still in the
+ // NSWindow hierarchy.
+ // - This happens when |cocoa_view_| is hidden (minimized, on another
+ // occluded by other windows, etc). The |browser_compositor_view_| and
+ // its CALayers are kept around so that we will have content to show when
+ // we are un-occluded.
+ BrowserCompositorSuspended,
+ // Effects:
+ // - |browser_compositor_view_| has been destroyed and
+ // |delegated_frame_host_| has been hidden.
+ // Happens when:
+ // - The |render_widget_host_| is hidden or dead, and |cocoa_view_| is not
+ // attached to a NSWindow.
+ // - This happens for backgrounded tabs.
+ BrowserCompositorDestroyed,
+ };
+ BrowserCompositorViewState browser_compositor_state_;
// Delegated frame management and compositior.
- base::scoped_nsobject<BrowserCompositorViewMac> browser_compositor_view_;
scoped_ptr<DelegatedFrameHost> delegated_frame_host_;
scoped_ptr<ui::Layer> root_layer_;
- // This holds the current software compositing framebuffer, if any.
- scoped_ptr<SoftwareFrameManager> software_frame_manager_;
+ // Container for the CALayer tree drawn by the browser compositor.
+ scoped_ptr<BrowserCompositorViewMac> browser_compositor_view_;
- // Latency info to send back when the next frame appears on the
- // screen.
- std::vector<ui::LatencyInfo> pending_latency_info_;
+ // Placeholder that is allocated while browser_compositor_view_ is NULL,
+ // indicating that a BrowserCompositorViewMac may be allocated. This is to
+ // help in recycling the internals of BrowserCompositorViewMac.
+ scoped_ptr<BrowserCompositorViewPlaceholderMac>
+ browser_compositor_view_placeholder_;
NSWindow* pepper_fullscreen_window() const {
return pepper_fullscreen_window_;
@@ -452,10 +432,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
return fullscreen_parent_host_view_;
}
- RenderWidgetHostViewFrameSubscriber* frame_subscriber() const {
- return frame_subscriber_.get();
- }
-
int window_number() const;
// The scale factor for the screen that the view is currently on.
@@ -467,53 +443,31 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Ensure that the display link is associated with the correct display.
void UpdateDisplayLink();
- // The scale factor of the backing store. Note that this is updated based on
- // ViewScaleFactor with some delay.
- float backing_store_scale_factor_;
-
- void AddPendingLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info);
- void SendPendingLatencyInfoToHost();
-
- void SendPendingSwapAck();
-
void PauseForPendingResizeOrRepaintsAndDraw();
- // The geometric arrangement of the layers depends on cocoa_view's size, the
- // compositing IOSurface's rounded size, and the software frame size. Update
- // all of them using this function when any of those parameters changes. Also
- // update the scale factor of the layers.
- void LayoutLayers();
-
// DelegatedFrameHostClient implementation.
- virtual ui::Compositor* GetCompositor() const OVERRIDE;
- virtual ui::Layer* GetLayer() OVERRIDE;
- virtual RenderWidgetHostImpl* GetHost() OVERRIDE;
- virtual void SchedulePaintInRect(
- const gfx::Rect& damage_rect_in_dip) OVERRIDE;
- virtual bool IsVisible() OVERRIDE;
- virtual scoped_ptr<ResizeLock> CreateResizeLock(
- bool defer_compositor_lock) OVERRIDE;
- virtual gfx::Size DesiredFrameSize() OVERRIDE;
- virtual float CurrentDeviceScaleFactor() OVERRIDE;
- virtual gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) OVERRIDE;
- virtual DelegatedFrameHost* GetDelegatedFrameHost() const OVERRIDE;
+ ui::Compositor* GetCompositor() const override;
+ ui::Layer* GetLayer() override;
+ RenderWidgetHostImpl* GetHost() override;
+ bool IsVisible() override;
+ scoped_ptr<ResizeLock> CreateResizeLock(bool defer_compositor_lock) override;
+ gfx::Size DesiredFrameSize() override;
+ float CurrentDeviceScaleFactor() override;
+ gfx::Size ConvertViewSizeToPixel(const gfx::Size& size) override;
+ DelegatedFrameHost* GetDelegatedFrameHost() const override;
+
+ // BrowserCompositorViewMacClient implementation.
+ bool BrowserCompositorViewShouldAckImmediately() const override;
+ void BrowserCompositorViewFrameSwapped(
+ const std::vector<ui::LatencyInfo>& latency_info) override;
+
+ // Transition from being in the Suspended state to being in the Destroyed
+ // state, if appropriate (see BrowserCompositorViewState for details).
+ void DestroySuspendedBrowserCompositorViewIfNeeded();
private:
friend class RenderWidgetHostViewMacTest;
- struct PendingSwapAck {
- PendingSwapAck(int32 route_id, int gpu_host_id, int32 renderer_id)
- : route_id(route_id),
- gpu_host_id(gpu_host_id),
- renderer_id(renderer_id) {}
- int32 route_id;
- int gpu_host_id;
- int32 renderer_id;
- };
- scoped_ptr<PendingSwapAck> pending_swap_ack_;
- void AddPendingSwapAck(int32 route_id, int gpu_host_id, int32 renderer_id);
-
// Returns whether this render view is a popup (autocomplete window).
bool IsPopup() const;
@@ -521,38 +475,27 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// invoke it from the message loop.
void ShutdownHost();
- void EnsureSoftwareLayer();
- void DestroySoftwareLayer();
-
- bool EnsureCompositedIOSurface() WARN_UNUSED_RESULT;
- void EnsureCompositedIOSurfaceLayer();
- enum DestroyCompositedIOSurfaceLayerBehavior {
- kLeaveLayerInHierarchy,
- kRemoveLayerFromHierarchy,
- };
- void DestroyCompositedIOSurfaceLayer(
- DestroyCompositedIOSurfaceLayerBehavior destroy_layer_behavior);
- void DestroyCompositedIOSurfaceAndLayer();
-
- void DestroyCompositingStateOnError();
-
- // Called when a GPU SwapBuffers is received.
- void GotAcceleratedFrame();
+ // Tear down all components of the browser compositor in an order that will
+ // ensure no dangling references.
+ void ShutdownBrowserCompositor();
- // Called when a software DIB is received.
- void GotSoftwareFrame();
+ // The state of the the browser compositor and delegated frame host. See
+ // BrowserCompositorViewState for details.
+ void EnsureBrowserCompositorView();
+ void SuspendBrowserCompositorView();
+ void DestroyBrowserCompositorView();
// IPC message handlers.
void OnPluginFocusChanged(bool focused, int plugin_id);
void OnStartPluginIme();
-
- // Convert |rect| from the views coordinate (upper-left origin) into
- // the OpenGL coordinate (lower-left origin) and scale for HiDPI displays.
- gfx::Rect GetScaledOpenGLPixelRect(const gfx::Rect& rect);
+ void OnGetRenderedTextCompleted(const std::string& text);
// Send updated vsync parameters to the renderer.
void SendVSyncParametersToRenderer();
+ // Dispatches a TTS session.
+ void SpeakText(const std::string& text);
+
// The associated view. This is weak and is inserted into the view hierarchy
// to own this RenderWidgetHostViewMac object. Set to nil at the start of the
// destructor.
@@ -561,9 +504,19 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Indicates if the page is loading.
bool is_loading_;
+ // Whether it's allowed to pause waiting for a new frame.
+ bool allow_pause_for_resize_or_repaint_;
+
+ // The last scroll offset of the view.
+ gfx::Vector2dF last_scroll_offset_;
+
// The text to be shown in the tooltip, supplied by the renderer.
base::string16 tooltip_text_;
+ // True when this view acts as a platform view hack for a
+ // RenderWidgetHostViewGuest.
+ bool is_guest_view_hack_;
+
// Factory used to safely scope delayed calls to ShutdownHost().
base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
@@ -579,23 +532,14 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Our parent host view, if this is fullscreen. NULL otherwise.
RenderWidgetHostViewMac* fullscreen_parent_host_view_;
- // The overlay view which is rendered above this one in the same
- // accelerated IOSurface.
- // Overlay view has |underlay_view_| set to this view.
- base::WeakPtr<RenderWidgetHostViewMac> overlay_view_;
-
- // The underlay view which this view is rendered above in the same
- // accelerated IOSurface.
- // Underlay view has |overlay_view_| set to this view.
- base::WeakPtr<RenderWidgetHostViewMac> underlay_view_;
-
- // Factory used to safely reference overlay view set in SetOverlayView.
- base::WeakPtrFactory<RenderWidgetHostViewMac>
- overlay_view_weak_factory_;
-
// Display link for getting vsync info.
scoped_refptr<DisplayLinkMac> display_link_;
+ // The current VSync timebase and interval. This is zero until the first call
+ // to SendVSyncParametersToRenderer(), and refreshed regularly thereafter.
+ base::TimeTicks vsync_timebase_;
+ base::TimeDelta vsync_interval_;
+
// The current composition character range and its bounds.
gfx::Range composition_range_;
std::vector<gfx::Rect> composition_bounds_;
@@ -603,11 +547,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// The current caret bounds.
gfx::Rect caret_rect_;
- // Subscriber that listens to frame presentation events.
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
-
- base::WeakPtrFactory<RenderWidgetHostViewMac>
- software_frame_weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewMac);
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
index 375833cec29..84a6008c5a0 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -28,22 +28,24 @@
#include "base/sys_info.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
+#import "content/browser/cocoa/system_hotkey_helper_mac.h"
+#import "content/browser/cocoa/system_hotkey_map.h"
+#include "content/browser/compositor/io_surface_layer_mac.h"
#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/compositor/software_layer_mac.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_layer_mac.h"
-#include "content/browser/renderer_host/compositing_iosurface_mac.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
-#import "content/browser/renderer_host/software_layer_mac.h"
#import "content/browser/renderer_host/text_input_client_mac.h"
#include "content/common/accessibility_messages.h"
#include "content/common/edit_command.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/common/webplugin_geometry.h"
@@ -56,6 +58,7 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "skia/ext/platform_canvas.h"
+#include "skia/ext/skia_utils_mac.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
@@ -68,6 +71,7 @@
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/display.h"
+#include "ui/gfx/frame_time.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
@@ -94,6 +98,17 @@ using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebGestureEvent;
+namespace {
+
+// Whether a keyboard event has been reserved by OSX.
+BOOL EventIsReservedBySystem(NSEvent* event) {
+ content::SystemHotkeyHelperMac* helper =
+ content::SystemHotkeyHelperMac::GetInstance();
+ return helper->map()->IsEventReserved(event);
+}
+
+} // namespace
+
// These are not documented, so use only after checking -respondsToSelector:.
@interface NSApplication (UndocumentedSpeechMethods)
- (void)speakString:(NSString*)string;
@@ -101,15 +116,6 @@ using blink::WebGestureEvent;
- (BOOL)isSpeaking;
@end
-// Declare things that are part of the 10.7 SDK.
-#if !defined(MAC_OS_X_VERSION_10_7) || \
- MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
-
-static NSString* const NSWindowDidChangeBackingPropertiesNotification =
- @"NSWindowDidChangeBackingPropertiesNotification";
-
-#endif // 10.7
-
// This method will return YES for OS X versions 10.7.3 and later, and NO
// otherwise.
// Used to prevent a crash when building with the 10.7 SDK and accessing the
@@ -375,17 +381,12 @@ blink::WebScreenInfo GetWebScreenInfo(NSView* view) {
results.rect = display.bounds();
results.availableRect = display.work_area();
results.orientationAngle = display.RotationAsDegree();
+ results.orientationType =
+ content::RenderWidgetHostViewBase::GetOrientationTypeForDesktop(display);
return results;
}
-void RemoveLayerFromSuperlayer(
- base::scoped_nsobject<CompositingIOSurfaceLayer> layer) {
- // Disable the fade-out animation as the layer is removed.
- ScopedCAActionDisabler disabler;
- [layer removeFromSuperlayer];
-}
-
} // namespace
namespace content {
@@ -394,7 +395,11 @@ namespace content {
// DelegatedFrameHost, public:
ui::Compositor* RenderWidgetHostViewMac::GetCompositor() const {
- return [browser_compositor_view_ compositor];
+ // When |browser_compositor_view_| is suspended or destroyed, the connection
+ // between its ui::Compositor and |delegated_frame_host_| has been severed.
+ if (browser_compositor_state_ == BrowserCompositorActive)
+ return browser_compositor_view_->GetCompositor();
+ return NULL;
}
ui::Layer* RenderWidgetHostViewMac::GetLayer() {
@@ -405,11 +410,6 @@ RenderWidgetHostImpl* RenderWidgetHostViewMac::GetHost() {
return render_widget_host_;
}
-void RenderWidgetHostViewMac::SchedulePaintInRect(
- const gfx::Rect& damage_rect_in_dip) {
- [browser_compositor_view_ compositor]->ScheduleFullRedraw();
-}
-
bool RenderWidgetHostViewMac::IsVisible() {
return !render_widget_host_->is_hidden();
}
@@ -439,6 +439,62 @@ DelegatedFrameHost* RenderWidgetHostViewMac::GetDelegatedFrameHost() const {
return delegated_frame_host_.get();
}
+////////////////////////////////////////////////////////////////////////////////
+// BrowserCompositorViewMacClient, public:
+
+bool RenderWidgetHostViewMac::BrowserCompositorViewShouldAckImmediately()
+ const {
+ // If vsync is disabled, then always draw and ack frames immediately.
+ static bool is_vsync_disabled =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuVsync);
+ if (is_vsync_disabled)
+ return true;
+
+ // If the window is occluded, then this frame's display call may be severely
+ // throttled. This is a good thing, unless tab capture may be active, because
+ // the broadcast will be inappropriately throttled.
+ // http://crbug.com/350410
+
+ // If tab capture isn't active then only ack frames when we draw them.
+ if (delegated_frame_host_ && !delegated_frame_host_->HasFrameSubscriber())
+ return false;
+
+ NSWindow* window = [cocoa_view_ window];
+ // If the view isn't even in the heirarchy then frames will never be drawn,
+ // so ack them immediately.
+ if (!window)
+ return true;
+
+ // Check the window occlusion API.
+ if ([window respondsToSelector:@selector(occlusionState)]) {
+ if ([window occlusionState] & NSWindowOcclusionStateVisible) {
+ // If the window is visible then it is safe to wait until frames are
+ // drawn to ack them.
+ return false;
+ } else {
+ // If the window is occluded then frames may never be drawn, so ack them
+ // immediately.
+ return true;
+ }
+ }
+
+ // If the window occlusion API is not present then ack frames when we draw
+ // them.
+ return false;
+}
+
+void RenderWidgetHostViewMac::BrowserCompositorViewFrameSwapped(
+ const std::vector<ui::LatencyInfo>& all_latency_info) {
+ if (!render_widget_host_)
+ return;
+ for (auto latency_info : all_latency_info) {
+ latency_info.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
+ render_widget_host_->FrameSwapped(latency_info);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewBase, public:
@@ -451,49 +507,66 @@ void RenderWidgetHostViewBase::GetDefaultScreenInfo(
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewMac, public:
-RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget)
+RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
+ bool is_guest_view_hack)
: render_widget_host_(RenderWidgetHostImpl::From(widget)),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
can_compose_inline_(true),
- backing_store_scale_factor_(1),
+ browser_compositor_state_(BrowserCompositorDestroyed),
+ browser_compositor_view_placeholder_(
+ new BrowserCompositorViewPlaceholderMac),
is_loading_(false),
+ allow_pause_for_resize_or_repaint_(true),
+ is_guest_view_hack_(is_guest_view_hack),
weak_factory_(this),
- fullscreen_parent_host_view_(NULL),
- overlay_view_weak_factory_(this),
- software_frame_weak_ptr_factory_(this) {
- software_frame_manager_.reset(new SoftwareFrameManager(
- software_frame_weak_ptr_factory_.GetWeakPtr()));
+ fullscreen_parent_host_view_(NULL) {
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_|
// goes away. Since we autorelease it, our caller must put
// |GetNativeView()| into the view hierarchy right after calling us.
cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc]
initWithRenderWidgetHostViewMac:this] autorelease];
+ // Paint this view host with |background_color_| when there is no content
+ // ready to draw.
background_layer_.reset([[CALayer alloc] init]);
[background_layer_
- setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
+ setBackgroundColor:gfx::CGColorCreateFromSkColor(background_color_)];
[cocoa_view_ setLayer:background_layer_];
[cocoa_view_ setWantsLayer:YES];
- render_widget_host_->SetView(this);
+ if (IsDelegatedRendererEnabled()) {
+ root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
+ delegated_frame_host_.reset(new DelegatedFrameHost(this));
+ }
+
+ gfx::Screen::GetScreenFor(cocoa_view_)->AddObserver(this);
+
+ if (!is_guest_view_hack_)
+ render_widget_host_->SetView(this);
}
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
+ gfx::Screen::GetScreenFor(cocoa_view_)->RemoveObserver(this);
+
// This is being called from |cocoa_view_|'s destructor, so invalidate the
// pointer.
cocoa_view_ = nil;
UnlockMouse();
- // Make sure that the layer doesn't reach into the now-invalid object.
- DestroyCompositedIOSurfaceAndLayer();
- DestroySoftwareLayer();
+ // Ensure that the browser compositor is destroyed in a safe order.
+ ShutdownBrowserCompositor();
// We are owned by RenderWidgetHostViewCocoa, so if we go away before the
// RenderWidgetHost does we need to tell it not to hold a stale pointer to
// us.
- if (render_widget_host_)
- render_widget_host_->SetView(NULL);
+ if (render_widget_host_) {
+ // If this is a RenderWidgetHostViewGuest's platform_view_, we're not the
+ // RWH's view, the RenderWidgetHostViewGuest is. So don't reset the RWH's
+ // view, the RenderWidgetHostViewGuest will do it.
+ if (!is_guest_view_hack_)
+ render_widget_host_->SetView(NULL);
+ }
}
void RenderWidgetHostViewMac::SetDelegate(
@@ -501,130 +574,74 @@ void RenderWidgetHostViewMac::SetDelegate(
[cocoa_view_ setResponderDelegate:delegate];
}
-void RenderWidgetHostViewMac::SetAllowOverlappingViews(bool overlapping) {
- // TODO(ccameron): Remove callers of this function.
+void RenderWidgetHostViewMac::SetAllowPauseForResizeOrRepaint(bool allow) {
+ allow_pause_for_resize_or_repaint_ = allow;
}
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewMac, RenderWidgetHostView implementation:
-bool RenderWidgetHostViewMac::EnsureCompositedIOSurface() {
- // If the context or the IOSurface's context has had an error, re-build
- // everything from scratch.
- if (compositing_iosurface_context_ &&
- compositing_iosurface_context_->HasBeenPoisoned()) {
- LOG(ERROR) << "Failing EnsureCompositedIOSurface because "
- << "context was poisoned";
- return false;
- }
- if (compositing_iosurface_ &&
- compositing_iosurface_->HasBeenPoisoned()) {
- LOG(ERROR) << "Failing EnsureCompositedIOSurface because "
- << "surface was poisoned";
- return false;
- }
-
- int current_window_number =
- CompositingIOSurfaceContext::kOffscreenContextWindowNumber;
- bool new_surface_needed = !compositing_iosurface_;
- bool new_context_needed =
- !compositing_iosurface_context_ ||
- (compositing_iosurface_context_ &&
- compositing_iosurface_context_->window_number() !=
- current_window_number);
-
- if (!new_surface_needed && !new_context_needed)
- return true;
+void RenderWidgetHostViewMac::EnsureBrowserCompositorView() {
+ TRACE_EVENT0("browser",
+ "RenderWidgetHostViewMac::EnsureBrowserCompositorView");
- // Create the GL context and shaders.
- if (new_context_needed) {
- scoped_refptr<CompositingIOSurfaceContext> new_context =
- CompositingIOSurfaceContext::Get(current_window_number);
- // Un-bind the GL context from this view before binding the new GL
- // context. Having two GL contexts bound to a view will result in
- // crashes and corruption.
- // http://crbug.com/230883
- if (!new_context) {
- LOG(ERROR) << "Failed to create CompositingIOSurfaceContext";
- return false;
- }
- compositing_iosurface_context_ = new_context;
+ // Create the view, to transition from Destroyed -> Suspended.
+ if (browser_compositor_state_ == BrowserCompositorDestroyed) {
+ browser_compositor_view_.reset(
+ new BrowserCompositorViewMac(this, cocoa_view_, root_layer_.get()));
+ browser_compositor_state_ = BrowserCompositorSuspended;
}
- // Create the IOSurface texture.
- if (new_surface_needed) {
- compositing_iosurface_ = CompositingIOSurfaceMac::Create();
- if (!compositing_iosurface_) {
- LOG(ERROR) << "Failed to create CompositingIOSurface";
- return false;
- }
+ // Show the DelegatedFrameHost to transition from Suspended -> Active.
+ if (browser_compositor_state_ == BrowserCompositorSuspended) {
+ delegated_frame_host_->AddedToWindow();
+ delegated_frame_host_->WasShown(ui::LatencyInfo());
+ browser_compositor_state_ = BrowserCompositorActive;
}
-
- return true;
}
-void RenderWidgetHostViewMac::EnsureSoftwareLayer() {
- TRACE_EVENT0("browser", "RenderWidgetHostViewMac::EnsureSoftwareLayer");
- if (software_layer_)
- return;
-
- software_layer_.reset([[SoftwareLayer alloc] init]);
- DCHECK(software_layer_);
-
- // Disable the fade-in animation as the layer is added.
- ScopedCAActionDisabler disabler;
- [background_layer_ addSublayer:software_layer_];
-}
-
-void RenderWidgetHostViewMac::DestroySoftwareLayer() {
- if (!software_layer_)
- return;
+void RenderWidgetHostViewMac::SuspendBrowserCompositorView() {
+ TRACE_EVENT0("browser",
+ "RenderWidgetHostViewMac::SuspendBrowserCompositorView");
- // Disable the fade-out animation as the layer is removed.
- ScopedCAActionDisabler disabler;
- [software_layer_ removeFromSuperlayer];
- software_layer_.reset();
+ // Hide the DelegatedFrameHost to transition from Active -> Suspended.
+ if (browser_compositor_state_ == BrowserCompositorActive) {
+ // Marking the DelegatedFrameHost as removed from the window hierarchy is
+ // necessary to remove all connections to its old ui::Compositor.
+ delegated_frame_host_->WasHidden();
+ delegated_frame_host_->RemovingFromWindow();
+ browser_compositor_state_ = BrowserCompositorSuspended;
+ }
}
-void RenderWidgetHostViewMac::EnsureCompositedIOSurfaceLayer() {
+void RenderWidgetHostViewMac::DestroyBrowserCompositorView() {
TRACE_EVENT0("browser",
- "RenderWidgetHostViewMac::EnsureCompositedIOSurfaceLayer");
- DCHECK(compositing_iosurface_context_);
- if (compositing_iosurface_layer_)
- return;
+ "RenderWidgetHostViewMac::DestroyBrowserCompositorView");
- compositing_iosurface_layer_.reset([[CompositingIOSurfaceLayer alloc]
- initWithIOSurface:compositing_iosurface_
- withScaleFactor:compositing_iosurface_->scale_factor()
- withClient:this]);
- DCHECK(compositing_iosurface_layer_);
+ // Transition from Active -> Suspended if need be.
+ SuspendBrowserCompositorView();
- // Disable the fade-in animation as the layer is added.
- ScopedCAActionDisabler disabler;
- [background_layer_ addSublayer:compositing_iosurface_layer_];
+ // Destroy the BrowserCompositorView to transition Suspended -> Destroyed.
+ if (browser_compositor_state_ == BrowserCompositorSuspended) {
+ browser_compositor_view_.reset();
+ browser_compositor_state_ = BrowserCompositorDestroyed;
+ }
}
-void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceLayer(
- DestroyCompositedIOSurfaceLayerBehavior destroy_layer_behavior) {
- if (!compositing_iosurface_layer_)
+void RenderWidgetHostViewMac::DestroySuspendedBrowserCompositorViewIfNeeded() {
+ if (browser_compositor_state_ != BrowserCompositorSuspended)
return;
- if (destroy_layer_behavior == kRemoveLayerFromHierarchy) {
- // Disable the fade-out animation as the layer is removed.
- ScopedCAActionDisabler disabler;
- [compositing_iosurface_layer_ removeFromSuperlayer];
- }
- [compositing_iosurface_layer_ resetClient];
- compositing_iosurface_layer_.reset();
-}
-
-void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceAndLayer() {
- // Any pending frames will not be displayed, so ack them now.
- SendPendingSwapAck();
+ // If this view is in a window that is visible, keep around the suspended
+ // BrowserCompositorView in case |cocoa_view_| is suddenly revealed (so that
+ // we don't flash white).
+ NSWindow* window = [cocoa_view_ window];
+ if (window)
+ return;
- DestroyCompositedIOSurfaceLayer(kRemoveLayerFromHierarchy);
- compositing_iosurface_ = NULL;
- compositing_iosurface_context_ = NULL;
+ // This should only be reached if |render_widget_host_| is hidden, destroyed,
+ // or in the process of being destroyed.
+ DestroyBrowserCompositorView();
}
bool RenderWidgetHostViewMac::OnMessageReceived(const IPC::Message& message) {
@@ -632,6 +649,8 @@ bool RenderWidgetHostViewMac::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewMac, message)
IPC_MESSAGE_HANDLER(ViewHostMsg_PluginFocusChanged, OnPluginFocusChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_StartPluginIme, OnStartPluginIme)
+ IPC_MESSAGE_HANDLER(ViewMsg_GetRenderedTextCompleted,
+ OnGetRenderedTextCompleted)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -742,7 +761,8 @@ float RenderWidgetHostViewMac::ViewScaleFactor() const {
void RenderWidgetHostViewMac::UpdateDisplayLink() {
static bool is_vsync_disabled =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync);
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuVsync);
if (is_vsync_disabled)
return;
@@ -752,7 +772,7 @@ void RenderWidgetHostViewMac::UpdateDisplayLink() {
CGDirectDisplayID display_id = [screen_number unsignedIntValue];
display_link_ = DisplayLinkMac::GetForDisplay(display_id);
- if (!display_link_) {
+ if (!display_link_.get()) {
// Note that on some headless systems, the display link will fail to be
// created, so this should not be a fatal error.
LOG(ERROR) << "Failed to create display link.";
@@ -760,26 +780,25 @@ void RenderWidgetHostViewMac::UpdateDisplayLink() {
}
void RenderWidgetHostViewMac::SendVSyncParametersToRenderer() {
- if (!render_widget_host_ || !display_link_)
+ if (!render_widget_host_ || !display_link_.get())
return;
- base::TimeTicks timebase;
- base::TimeDelta interval;
- if (!display_link_->GetVSyncParameters(&timebase, &interval))
+ if (!display_link_->GetVSyncParameters(&vsync_timebase_, &vsync_interval_)) {
+ vsync_timebase_ = base::TimeTicks();
+ vsync_interval_ = base::TimeDelta();
return;
+ }
+
+ render_widget_host_->UpdateVSyncParameters(vsync_timebase_, vsync_interval_);
+}
- render_widget_host_->UpdateVSyncParameters(timebase, interval);
+void RenderWidgetHostViewMac::SpeakText(const std::string& text) {
+ [NSApp speakString:base::SysUTF8ToNSString(text)];
}
void RenderWidgetHostViewMac::UpdateBackingStoreScaleFactor() {
if (!render_widget_host_)
return;
-
- float new_scale_factor = ui::GetScaleFactorForNativeView(cocoa_view_);
- if (new_scale_factor == backing_store_scale_factor_)
- return;
- backing_store_scale_factor_ = new_scale_factor;
-
render_widget_host_->NotifyScreenInfoChanged();
}
@@ -791,17 +810,16 @@ void RenderWidgetHostViewMac::WasShown() {
if (!render_widget_host_->is_hidden())
return;
- render_widget_host_->WasShown();
- software_frame_manager_->SetVisibility(true);
- if (delegated_frame_host_)
- delegated_frame_host_->WasShown();
-
- // Call setNeedsDisplay before pausing for new frames to come in -- if any
- // do, and are drawn, then the needsDisplay bit will be cleared.
- // Workaround for crbug.com/395827
- if ([compositing_iosurface_layer_ isAsynchronous])
- [compositing_iosurface_layer_ setAsynchronous:NO];
- [compositing_iosurface_layer_ setNeedsDisplay];
+ ui::LatencyInfo renderer_latency_info;
+ renderer_latency_info.AddLatencyNumber(
+ ui::TAB_SHOW_COMPONENT,
+ render_widget_host_->GetLatencyComponentId(),
+ 0);
+ render_widget_host_->WasShown(renderer_latency_info);
+
+ // If there is not a frame being currently drawn, kick one, so that the below
+ // pause will have a frame to wait on.
+ render_widget_host_->ScheduleComposite();
PauseForPendingResizeOrRepaintsAndDraw();
}
@@ -809,16 +827,12 @@ void RenderWidgetHostViewMac::WasHidden() {
if (render_widget_host_->is_hidden())
return;
- // Any pending frames will not be displayed until this is shown again. Ack
- // them now.
- SendPendingSwapAck();
-
// If we have a renderer, then inform it that we are being hidden so it can
// reduce its resource utilization.
render_widget_host_->WasHidden();
- software_frame_manager_->SetVisibility(false);
- if (delegated_frame_host_)
- delegated_frame_host_->WasHidden();
+
+ SuspendBrowserCompositorView();
+ DestroySuspendedBrowserCompositorViewIfNeeded();
}
void RenderWidgetHostViewMac::SetSize(const gfx::Size& size) {
@@ -875,6 +889,10 @@ void RenderWidgetHostViewMac::SetBounds(const gfx::Rect& rect) {
}
}
+gfx::Vector2dF RenderWidgetHostViewMac::GetLastScrollOffset() const {
+ return last_scroll_offset_;
+}
+
gfx::NativeView RenderWidgetHostViewMac::GetNativeView() const {
return cocoa_view_;
}
@@ -912,9 +930,7 @@ bool RenderWidgetHostViewMac::HasFocus() const {
bool RenderWidgetHostViewMac::IsSurfaceAvailableForCopy() const {
if (delegated_frame_host_)
return delegated_frame_host_->CanCopyToBitmap();
-
- return software_frame_manager_->HasCurrentFrame() ||
- (compositing_iosurface_ && compositing_iosurface_->HasIOSurface());
+ return false;
}
void RenderWidgetHostViewMac::Show() {
@@ -958,12 +974,15 @@ void RenderWidgetHostViewMac::SetIsLoading(bool is_loading) {
// like Chrome does on Windows, call |UpdateCursor()| here.
}
-void RenderWidgetHostViewMac::TextInputStateChanged(
- const ViewHostMsg_TextInputState_Params& params) {
- if (text_input_type_ != params.type ||
- can_compose_inline_ != params.can_compose_inline) {
- text_input_type_ = params.type;
- can_compose_inline_ = params.can_compose_inline;
+void RenderWidgetHostViewMac::TextInputTypeChanged(
+ ui::TextInputType type,
+ ui::TextInputMode input_mode,
+ bool can_compose_inline,
+ int flags) {
+ if (text_input_type_ != type
+ || can_compose_inline_ != can_compose_inline) {
+ text_input_type_ = type;
+ can_compose_inline_ = can_compose_inline;
if (HasFocus()) {
SetTextInputActive(true);
@@ -997,6 +1016,13 @@ void RenderWidgetHostViewMac::RenderProcessGone(base::TerminationStatus status,
Destroy();
}
+void RenderWidgetHostViewMac::RenderWidgetHostGone() {
+ // Destroy the DelegatedFrameHost, to prevent crashes when Destroy is never
+ // called on the view.
+ // http://crbug.com/404828
+ ShutdownBrowserCompositor();
+}
+
void RenderWidgetHostViewMac::Destroy() {
[[NSNotificationCenter defaultCenter]
removeObserver:cocoa_view_
@@ -1022,9 +1048,7 @@ void RenderWidgetHostViewMac::Destroy() {
// Delete the delegated frame state, which will reach back into
// render_widget_host_.
- [browser_compositor_view_ resetClient];
- delegated_frame_host_.reset();
- root_layer_.reset();
+ ShutdownBrowserCompositor();
// We get this call just before |render_widget_host_| deletes
// itself. But we are owned by |cocoa_view_|, which may be retained
@@ -1061,8 +1085,19 @@ bool RenderWidgetHostViewMac::SupportsSpeech() const {
}
void RenderWidgetHostViewMac::SpeakSelection() {
- if ([NSApp respondsToSelector:@selector(speakString:)])
- [NSApp speakString:base::SysUTF8ToNSString(selected_text_)];
+ if (![NSApp respondsToSelector:@selector(speakString:)])
+ return;
+
+ if (selected_text_.empty() && render_widget_host_) {
+ // If there's no selection, speak all text. Send an asynchronous IPC
+ // request for fetching all the text for a webcontent.
+ // ViewMsg_GetRenderedTextCompleted is sent back to IPC Message receiver.
+ render_widget_host_->Send(new ViewMsg_GetRenderedText(
+ render_widget_host_->GetRoutingID()));
+ return;
+ }
+
+ SpeakText(selected_text_);
}
bool RenderWidgetHostViewMac::IsSpeaking() const {
@@ -1113,9 +1148,6 @@ void RenderWidgetHostViewMac::SelectionBoundsChanged(
caret_rect_ = params.anchor_rect;
}
-void RenderWidgetHostViewMac::ScrollOffsetChanged() {
-}
-
void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) {
RenderWidgetHostViewBase::SetShowingContextMenu(showing);
@@ -1152,65 +1184,10 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config config) {
+ const SkColorType color_type) {
if (delegated_frame_host_) {
delegated_frame_host_->CopyFromCompositingSurface(
- src_subrect, dst_size, callback, config);
- return;
- }
-
- if (config != SkBitmap::kARGB_8888_Config) {
- NOTIMPLEMENTED();
- callback.Run(false, SkBitmap());
- }
- base::ScopedClosureRunner scoped_callback_runner(
- base::Bind(callback, false, SkBitmap()));
- float scale = ui::GetScaleFactorForNativeView(cocoa_view_);
- gfx::Size dst_pixel_size = gfx::ToFlooredSize(
- gfx::ScaleSize(dst_size, scale));
- if (compositing_iosurface_ && compositing_iosurface_->HasIOSurface()) {
- ignore_result(scoped_callback_runner.Release());
- compositing_iosurface_->CopyTo(GetScaledOpenGLPixelRect(src_subrect),
- dst_pixel_size,
- callback);
- } else if (software_frame_manager_->HasCurrentFrame()) {
- gfx::Rect src_pixel_rect = gfx::ToEnclosingRect(gfx::ScaleRect(
- src_subrect,
- software_frame_manager_->GetCurrentFrameDeviceScaleFactor()));
- SkBitmap source_bitmap;
- source_bitmap.setConfig(
- SkBitmap::kARGB_8888_Config,
- software_frame_manager_->GetCurrentFrameSizeInPixels().width(),
- software_frame_manager_->GetCurrentFrameSizeInPixels().height(),
- 0,
- kOpaque_SkAlphaType);
- source_bitmap.setPixels(software_frame_manager_->GetCurrentFramePixels());
-
- SkBitmap target_bitmap;
- target_bitmap.setConfig(
- SkBitmap::kARGB_8888_Config,
- dst_pixel_size.width(),
- dst_pixel_size.height(),
- 0,
- kOpaque_SkAlphaType);
- if (!target_bitmap.allocPixels())
- return;
-
- SkCanvas target_canvas(target_bitmap);
- SkRect src_pixel_skrect = SkRect::MakeXYWH(
- src_pixel_rect.x(), src_pixel_rect.y(),
- src_pixel_rect.width(), src_pixel_rect.height());
- target_canvas.drawBitmapRectToRect(
- source_bitmap,
- &src_pixel_skrect,
- SkRect::MakeXYWH(0, 0, dst_pixel_size.width(), dst_pixel_size.height()),
- NULL,
- SkCanvas::kNone_DrawBitmapRectFlag);
-
- ignore_result(scoped_callback_runner.Release());
- callback.Run(true, target_bitmap);
- } else {
- callback.Run(false, SkBitmap());
+ src_subrect, dst_size, callback, color_type);
}
}
@@ -1221,71 +1198,30 @@ void RenderWidgetHostViewMac::CopyFromCompositingSurfaceToVideoFrame(
if (delegated_frame_host_) {
delegated_frame_host_->CopyFromCompositingSurfaceToVideoFrame(
src_subrect, target, callback);
- return;
- }
-
- base::ScopedClosureRunner scoped_callback_runner(base::Bind(callback, false));
- if (!compositing_iosurface_ || !compositing_iosurface_->HasIOSurface())
- return;
-
- if (!target.get()) {
- NOTREACHED();
- return;
}
-
- if (target->format() != media::VideoFrame::YV12 &&
- target->format() != media::VideoFrame::I420) {
- NOTREACHED();
- return;
- }
-
- if (src_subrect.IsEmpty())
- return;
-
- ignore_result(scoped_callback_runner.Release());
- compositing_iosurface_->CopyToVideoFrame(
- GetScaledOpenGLPixelRect(src_subrect),
- target,
- callback);
}
bool RenderWidgetHostViewMac::CanCopyToVideoFrame() const {
if (delegated_frame_host_)
return delegated_frame_host_->CanCopyToVideoFrame();
-
- return (!software_frame_manager_->HasCurrentFrame() &&
- compositing_iosurface_ &&
- compositing_iosurface_->HasIOSurface());
+ return false;
}
bool RenderWidgetHostViewMac::CanSubscribeFrame() const {
if (delegated_frame_host_)
return delegated_frame_host_->CanSubscribeFrame();
-
- return !software_frame_manager_->HasCurrentFrame();
+ return false;
}
void RenderWidgetHostViewMac::BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
- if (delegated_frame_host_) {
+ if (delegated_frame_host_)
delegated_frame_host_->BeginFrameSubscription(subscriber.Pass());
- return;
- }
- frame_subscriber_ = subscriber.Pass();
}
void RenderWidgetHostViewMac::EndFrameSubscription() {
- if (delegated_frame_host_) {
+ if (delegated_frame_host_)
delegated_frame_host_->EndFrameSubscription();
- return;
- }
-
- frame_subscriber_.reset();
-}
-
-// Sets whether or not to accept first responder status.
-void RenderWidgetHostViewMac::SetTakesFocusOnlyOnMouseDown(bool flag) {
- [cocoa_view_ setTakesFocusOnlyOnMouseDown:flag];
}
void RenderWidgetHostViewMac::ForwardMouseEvent(const WebMouseEvent& event) {
@@ -1328,205 +1264,6 @@ void RenderWidgetHostViewMac::PluginImeCompositionCompleted(
}
}
-void RenderWidgetHostViewMac::CompositorSwapBuffers(
- IOSurfaceID surface_handle,
- const gfx::Size& size,
- float surface_scale_factor,
- const std::vector<ui::LatencyInfo>& latency_info) {
- // Ensure that the frame be acked unless it is explicitly passed to a
- // display function.
- base::ScopedClosureRunner scoped_ack(
- base::Bind(&RenderWidgetHostViewMac::SendPendingSwapAck,
- weak_factory_.GetWeakPtr()));
-
- if (render_widget_host_->is_hidden())
- return;
-
- // Ensure that if this function exits before the frame is set up (but not
- // necessarily drawn) then it is treated as an error.
- base::ScopedClosureRunner scoped_error(
- base::Bind(&RenderWidgetHostViewMac::GotAcceleratedCompositingError,
- weak_factory_.GetWeakPtr()));
-
- AddPendingLatencyInfo(latency_info);
-
- // If compositing_iosurface_ exists and has been poisoned, destroy it
- // and allow EnsureCompositedIOSurface to recreate it below. Keep a
- // reference to the destroyed layer around until after the below call
- // to LayoutLayers, to avoid flickers.
- base::ScopedClosureRunner scoped_layer_remover;
- if (compositing_iosurface_context_ &&
- compositing_iosurface_context_->HasBeenPoisoned()) {
- scoped_layer_remover.Reset(
- base::Bind(RemoveLayerFromSuperlayer, compositing_iosurface_layer_));
- DestroyCompositedIOSurfaceLayer(kLeaveLayerInHierarchy);
- DestroyCompositedIOSurfaceAndLayer();
- }
-
- // Ensure compositing_iosurface_ and compositing_iosurface_context_ be
- // allocated.
- if (!EnsureCompositedIOSurface()) {
- LOG(ERROR) << "Failed EnsureCompositingIOSurface";
- return;
- }
-
- // Make the context current and update the IOSurface with the handle
- // passed in by the swap command.
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- compositing_iosurface_context_->cgl_context());
- if (!compositing_iosurface_->SetIOSurfaceWithContextCurrent(
- compositing_iosurface_context_, surface_handle, size,
- surface_scale_factor)) {
- LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
- return;
- }
- }
-
- // Grab video frames now that the IOSurface has been set up. Note that this
- // will be done in an offscreen context, so it is necessary to re-set the
- // current context afterward.
- bool frame_was_captured = false;
- if (frame_subscriber_) {
- const base::TimeTicks present_time = base::TimeTicks::Now();
- scoped_refptr<media::VideoFrame> frame;
- RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
- if (frame_subscriber_->ShouldCaptureFrame(present_time,
- &frame, &callback)) {
- // Flush the context that updated the IOSurface, to ensure that the
- // context that does the copy picks up the correct version.
- {
- gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
- compositing_iosurface_context_->cgl_context());
- glFlush();
- }
- compositing_iosurface_->CopyToVideoFrame(
- gfx::Rect(size), frame,
- base::Bind(callback, present_time));
- frame_was_captured = true;
- }
- }
-
- // At this point the surface, its context, and its layer have been set up, so
- // don't generate an error (one may be generated when drawing).
- ignore_result(scoped_error.Release());
-
- GotAcceleratedFrame();
-
- gfx::Size window_size(NSSizeToCGSize([cocoa_view_ frame].size));
- if (window_size.IsEmpty()) {
- // setNeedsDisplay will never display and we'll never ack if the window is
- // empty, so ack now and don't bother calling setNeedsDisplay below.
- return;
- }
- if (window_number() <= 0) {
- // It's normal for a backgrounded tab that is being captured to have no
- // window but not be hidden. Immediately ack the frame, and don't try to
- // draw it.
- if (frame_was_captured)
- return;
-
- // If this frame was not captured, there is likely some sort of bug. Ack
- // the frame and hope for the best. Because the IOSurface and layer are
- // populated, it will likely be displayed when the view is added to a
- // window's hierarchy.
-
- // TODO(shess) If the view does not have a window, or the window
- // does not have backing, the IOSurface will log "invalid drawable"
- // in -setView:. It is not clear how this code is reached with such
- // a case, so record some info into breakpad (some subset of
- // browsers are likely to crash later for unrelated reasons).
- // http://crbug.com/148882
- const char* const kCrashKey = "rwhvm_window";
- NSWindow* window = [cocoa_view_ window];
- if (!window) {
- base::debug::SetCrashKeyValue(kCrashKey, "Missing window");
- } else {
- std::string value =
- base::StringPrintf("window %s delegate %s controller %s",
- object_getClassName(window),
- object_getClassName([window delegate]),
- object_getClassName([window windowController]));
- base::debug::SetCrashKeyValue(kCrashKey, value);
- }
- return;
- }
-
- // If the window is occluded, then this frame's display call may be severely
- // throttled. This is a good thing, unless tab capture may be active,
- // because the broadcast will be inappropriately throttled.
- // http://crbug.com/350410
- NSWindow* window = [cocoa_view_ window];
- if (window && [window respondsToSelector:@selector(occlusionState)]) {
- bool window_is_occluded =
- !([window occlusionState] & NSWindowOcclusionStateVisible);
- // Note that we aggressively ack even if this particular frame is not being
- // captured.
- if (window_is_occluded && frame_subscriber_)
- scoped_ack.Reset();
- }
-
- // If we reach here, then the frame will be displayed by a future draw
- // call, so don't make the callback.
- ignore_result(scoped_ack.Release());
- DCHECK(compositing_iosurface_layer_);
- [compositing_iosurface_layer_ gotNewFrame];
-
- // Try to finish previous copy requests after draw to get better pipelining.
- if (compositing_iosurface_)
- compositing_iosurface_->CheckIfAllCopiesAreFinished(false);
-
- // The IOSurface's size may have changed, so re-layout the layers to take
- // this into account. This may force an immediate draw.
- LayoutLayers();
-}
-
-void RenderWidgetHostViewMac::GotAcceleratedCompositingError() {
- LOG(ERROR) << "Encountered accelerated compositing error";
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&RenderWidgetHostViewMac::DestroyCompositingStateOnError,
- weak_factory_.GetWeakPtr()));
-}
-
-void RenderWidgetHostViewMac::DestroyCompositingStateOnError() {
- // This should be called with a clean stack. Make sure that no context is
- // current.
- DCHECK(!CGLGetCurrentContext());
-
- // The existing GL contexts may be in a bad state, so don't re-use any of the
- // existing ones anymore, rather, allocate new ones.
- if (compositing_iosurface_context_)
- compositing_iosurface_context_->PoisonContextAndSharegroup();
-
- DestroyCompositedIOSurfaceAndLayer();
-
- // Request that a new frame be generated and dirty the view.
- if (render_widget_host_)
- render_widget_host_->ScheduleComposite();
- [cocoa_view_ setNeedsDisplay:YES];
-
- // TODO(ccameron): It may be a good idea to request that the renderer recreate
- // its GL context as well, and fall back to software if this happens
- // repeatedly.
-}
-
-void RenderWidgetHostViewMac::SetOverlayView(
- RenderWidgetHostViewMac* overlay, const gfx::Point& offset) {
- if (overlay_view_)
- overlay_view_->underlay_view_.reset();
-
- overlay_view_ = overlay->overlay_view_weak_factory_.GetWeakPtr();
- overlay_view_->underlay_view_ = overlay_view_weak_factory_.GetWeakPtr();
-}
-
-void RenderWidgetHostViewMac::RemoveOverlayView() {
- if (overlay_view_) {
- overlay_view_->underlay_view_.reset();
- overlay_view_.reset();
- }
-}
-
bool RenderWidgetHostViewMac::GetLineBreakIndex(
const std::vector<gfx::Rect>& bounds,
const gfx::Range& range,
@@ -1660,65 +1397,10 @@ bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
return true;
}
-void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
- int gpu_host_id) {
- TRACE_EVENT0("browser",
- "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped");
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- IOSurfaceID io_surface_handle =
- static_cast<IOSurfaceID>(params.surface_handle);
- AddPendingSwapAck(params.route_id,
- gpu_host_id,
- compositing_iosurface_ ?
- compositing_iosurface_->GetRendererID() : 0);
- CompositorSwapBuffers(io_surface_handle,
- params.size,
- params.scale_factor,
- params.latency_info);
-}
-
-void RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer(
- const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params& params,
- int gpu_host_id) {
- TRACE_EVENT0("browser",
- "RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer");
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- IOSurfaceID io_surface_handle =
- static_cast<IOSurfaceID>(params.surface_handle);
- AddPendingSwapAck(params.route_id,
- gpu_host_id,
- compositing_iosurface_ ?
- compositing_iosurface_->GetRendererID() : 0);
- CompositorSwapBuffers(io_surface_handle,
- params.surface_size,
- params.surface_scale_factor,
- params.latency_info);
-}
-
-void RenderWidgetHostViewMac::AcceleratedSurfaceSuspend() {
- if (!render_widget_host_->is_hidden())
- DestroyCompositedIOSurfaceAndLayer();
-}
-
-void RenderWidgetHostViewMac::AcceleratedSurfaceRelease() {
- DestroyCompositedIOSurfaceAndLayer();
-}
-
bool RenderWidgetHostViewMac::HasAcceleratedSurface(
const gfx::Size& desired_size) {
- if (compositing_iosurface_) {
- return compositing_iosurface_->HasIOSurface() &&
- (desired_size.IsEmpty() ||
- compositing_iosurface_->dip_io_surface_size() == desired_size);
- }
- if (software_frame_manager_->HasCurrentFrame()) {
- return (desired_size.IsEmpty() ||
- software_frame_manager_->GetCurrentFrameSizeInDIP() ==
- desired_size);
- }
+ if (browser_compositor_view_)
+ return browser_compositor_view_->HasFrameOfSize(desired_size);
return false;
}
@@ -1726,72 +1408,31 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame(
uint32 output_surface_id, scoped_ptr<cc::CompositorFrame> frame) {
TRACE_EVENT0("browser", "RenderWidgetHostViewMac::OnSwapCompositorFrame");
+ last_scroll_offset_ = frame->metadata.root_scroll_offset;
if (frame->delegated_frame_data) {
- if (!browser_compositor_view_) {
- browser_compositor_view_.reset(
- [[BrowserCompositorViewMac alloc] initWithSuperview:cocoa_view_]);
- root_layer_.reset(new ui::Layer(ui::LAYER_TEXTURED));
- delegated_frame_host_.reset(new DelegatedFrameHost(this));
- [browser_compositor_view_ compositor]->SetRootLayer(root_layer_.get());
- }
-
float scale_factor = frame->metadata.device_scale_factor;
- gfx::Size dip_size = ToCeiledSize(frame->metadata.viewport_size);
- gfx::Size pixel_size = ConvertSizeToPixel(
- scale_factor, dip_size);
- [browser_compositor_view_ compositor]->SetScaleAndSize(
- scale_factor, pixel_size);
+
+ // Compute the frame size based on the root render pass rect size.
+ cc::RenderPass* root_pass =
+ frame->delegated_frame_data->render_pass_list.back();
+ gfx::Size pixel_size = root_pass->output_rect.size();
+ gfx::Size dip_size =
+ ConvertSizeToDIP(scale_factor, pixel_size);
+
root_layer_->SetBounds(gfx::Rect(dip_size));
+ if (!render_widget_host_->is_hidden()) {
+ EnsureBrowserCompositorView();
+ browser_compositor_view_->GetCompositor()->SetScaleAndSize(
+ scale_factor, pixel_size);
+ }
+
+ SendVSyncParametersToRenderer();
delegated_frame_host_->SwapDelegatedFrame(
output_surface_id,
frame->delegated_frame_data.Pass(),
frame->metadata.device_scale_factor,
frame->metadata.latency_info);
- } else if (frame->software_frame_data) {
- if (!software_frame_manager_->SwapToNewFrame(
- output_surface_id,
- frame->software_frame_data.get(),
- frame->metadata.device_scale_factor,
- render_widget_host_->GetProcess()->GetHandle())) {
- render_widget_host_->GetProcess()->ReceivedBadMessage();
- return;
- }
-
- // Add latency info to report when the frame finishes drawing.
- AddPendingLatencyInfo(frame->metadata.latency_info);
-
- const void* pixels = software_frame_manager_->GetCurrentFramePixels();
- gfx::Size size_in_pixels =
- software_frame_manager_->GetCurrentFrameSizeInPixels();
-
- EnsureSoftwareLayer();
- [software_layer_ setContentsToData:pixels
- withRowBytes:4 * size_in_pixels.width()
- withPixelSize:size_in_pixels
- withScaleFactor:frame->metadata.device_scale_factor];
-
- // Send latency information to the host immediately, as there will be no
- // subsequent draw call in which to do so.
- SendPendingLatencyInfoToHost();
-
- GotSoftwareFrame();
-
- cc::CompositorFrameAck ack;
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- render_widget_host_->GetRoutingID(),
- software_frame_manager_->GetCurrentFrameOutputSurfaceId(),
- render_widget_host_->GetProcess()->GetID(),
- ack);
- software_frame_manager_->SwapToNewFrameComplete(
- !render_widget_host_->is_hidden());
-
- // Notify observers, tab capture observers in particular, that a new
- // software frame has come in.
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
- Source<RenderWidgetHost>(render_widget_host_),
- NotificationService::NoDetails());
} else {
DLOG(ERROR) << "Received unexpected frame type.";
RecordAction(
@@ -1800,10 +1441,6 @@ void RenderWidgetHostViewMac::OnSwapCompositorFrame(
}
}
-void RenderWidgetHostViewMac::AcceleratedSurfaceInitialized(int host_id,
- int route_id) {
-}
-
void RenderWidgetHostViewMac::GetScreenInfo(blink::WebScreenInfo* results) {
*results = GetWebScreenInfo(GetNativeView());
}
@@ -1823,7 +1460,7 @@ gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
gfx::GLSurfaceHandle RenderWidgetHostViewMac::GetCompositingSurface() {
// TODO(kbr): may be able to eliminate PluginWindowHandle argument
// completely on Mac OS.
- return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_TRANSPORT);
+ return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NULL_TRANSPORT);
}
bool RenderWidgetHostViewMac::LockMouse() {
@@ -1872,54 +1509,17 @@ bool RenderWidgetHostViewMac::Send(IPC::Message* message) {
return false;
}
-void RenderWidgetHostViewMac::SoftwareFrameWasFreed(
- uint32 output_surface_id, unsigned frame_id) {
- if (!render_widget_host_)
- return;
- cc::CompositorFrameAck ack;
- ack.last_software_frame_id = frame_id;
- RenderWidgetHostImpl::SendReclaimCompositorResources(
- render_widget_host_->GetRoutingID(),
- output_surface_id,
- render_widget_host_->GetProcess()->GetID(),
- ack);
-}
-
-void RenderWidgetHostViewMac::ReleaseReferencesToSoftwareFrame() {
- DestroySoftwareLayer();
-}
-
void RenderWidgetHostViewMac::ShutdownHost() {
weak_factory_.InvalidateWeakPtrs();
render_widget_host_->Shutdown();
// Do not touch any members at this point, |this| has been deleted.
}
-void RenderWidgetHostViewMac::GotAcceleratedFrame() {
- EnsureCompositedIOSurfaceLayer();
- SendVSyncParametersToRenderer();
-
- // Delete software backingstore and layer.
- software_frame_manager_->DiscardCurrentFrame();
- DestroySoftwareLayer();
-}
-
-void RenderWidgetHostViewMac::GotSoftwareFrame() {
- TRACE_EVENT0("browser", "RenderWidgetHostViewMac::GotSoftwareFrame");
-
- if (!render_widget_host_)
- return;
-
- EnsureSoftwareLayer();
- LayoutLayers();
- SendVSyncParametersToRenderer();
-
- // Draw the contents of the frame immediately. It is critical that this
- // happen before the frame be acked, otherwise the new frame will likely be
- // ready before the drawing is complete, thrashing the browser main thread.
- [software_layer_ displayIfNeeded];
-
- DestroyCompositedIOSurfaceAndLayer();
+void RenderWidgetHostViewMac::ShutdownBrowserCompositor() {
+ DestroyBrowserCompositorView();
+ delegated_frame_host_.reset();
+ root_layer_.reset();
+ browser_compositor_view_placeholder_.reset();
}
void RenderWidgetHostViewMac::SetActive(bool active) {
@@ -1960,22 +1560,26 @@ void RenderWidgetHostViewMac::ShowDefinitionForSelection() {
helper.ShowDefinitionForSelection();
}
-void RenderWidgetHostViewMac::SetBackgroundOpaque(bool opaque) {
- RenderWidgetHostViewBase::SetBackgroundOpaque(opaque);
+void RenderWidgetHostViewMac::SetBackgroundColor(SkColor color) {
+ RenderWidgetHostViewBase::SetBackgroundColor(color);
if (render_widget_host_)
- render_widget_host_->SetBackgroundOpaque(opaque);
-}
+ render_widget_host_->SetBackgroundOpaque(GetBackgroundOpaque());
-void RenderWidgetHostViewMac::CreateBrowserAccessibilityManagerIfNeeded() {
- if (!GetBrowserAccessibilityManager()) {
- SetBrowserAccessibilityManager(
- new BrowserAccessibilityManagerMac(
- cocoa_view_,
- BrowserAccessibilityManagerMac::GetEmptyDocument(),
- render_widget_host_));
+ if (background_layer_) {
+ [background_layer_
+ setBackgroundColor:gfx::CGColorCreateFromSkColor(background_color_)];
}
}
+BrowserAccessibilityManager*
+ RenderWidgetHostViewMac::CreateBrowserAccessibilityManager(
+ BrowserAccessibilityDelegate* delegate) {
+ return new BrowserAccessibilityManagerMac(
+ cocoa_view_,
+ BrowserAccessibilityManagerMac::GetEmptyDocument(),
+ delegate);
+}
+
gfx::Point RenderWidgetHostViewMac::AccessibilityOriginInScreen(
const gfx::Rect& bounds) {
NSPoint origin = NSMakePoint(bounds.x(), bounds.y());
@@ -1988,33 +1592,9 @@ gfx::Point RenderWidgetHostViewMac::AccessibilityOriginInScreen(
return gfx::Point(originInScreen.x, originInScreen.y);
}
-void RenderWidgetHostViewMac::OnAccessibilitySetFocus(int accObjId) {
- // Immediately set the focused item even though we have not officially set
- // focus on it as VoiceOver expects to get the focused item after this
- // method returns.
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
- if (manager)
- manager->SetFocus(manager->GetFromID(accObjId), false);
-}
-
-void RenderWidgetHostViewMac::AccessibilityShowMenu(int accObjId) {
- BrowserAccessibilityManager* manager = GetBrowserAccessibilityManager();
- if (!manager)
- return;
- BrowserAccessibilityCocoa* obj =
- manager->GetFromID(accObjId)->ToBrowserAccessibilityCocoa();
-
- // Performs a right click copying WebKit's
- // accessibilityPerformShowMenuAction.
- NSPoint objOrigin = [obj origin];
- NSSize size = [[obj size] sizeValue];
- gfx::Point origin = AccessibilityOriginInScreen(
- gfx::Rect(objOrigin.x, objOrigin.y, size.width, size.height));
- NSPoint location = NSMakePoint(origin.x(), origin.y());
+void RenderWidgetHostViewMac::AccessibilityShowMenu(const gfx::Point& point) {
+ NSPoint location = NSMakePoint(point.x(), point.y());
location = [[cocoa_view_ window] convertScreenToBase:location];
- location.x += size.width/2;
- location.y += size.height/2;
-
NSEvent* fakeRightClick = [NSEvent
mouseEventWithType:NSRightMouseDown
location:location
@@ -2029,8 +1609,6 @@ void RenderWidgetHostViewMac::AccessibilityShowMenu(int accObjId) {
[cocoa_view_ mouseEvent:fakeRightClick];
}
-
-
void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
if (active) {
if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
@@ -2052,159 +1630,48 @@ void RenderWidgetHostViewMac::OnStartPluginIme() {
[cocoa_view_ setPluginImeActive:YES];
}
-gfx::Rect RenderWidgetHostViewMac::GetScaledOpenGLPixelRect(
- const gfx::Rect& rect) {
- gfx::Rect src_gl_subrect = rect;
- src_gl_subrect.set_y(GetViewBounds().height() - rect.bottom());
-
- return gfx::ToEnclosingRect(gfx::ScaleRect(src_gl_subrect,
- ViewScaleFactor()));
-}
-
-void RenderWidgetHostViewMac::AddPendingLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- for (size_t i = 0; i < latency_info.size(); i++) {
- pending_latency_info_.push_back(latency_info[i]);
- }
-}
-
-void RenderWidgetHostViewMac::SendPendingLatencyInfoToHost() {
- for (size_t i = 0; i < pending_latency_info_.size(); i++) {
- pending_latency_info_[i].AddLatencyNumber(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
- render_widget_host_->FrameSwapped(pending_latency_info_[i]);
- }
- pending_latency_info_.clear();
-}
-
-void RenderWidgetHostViewMac::AddPendingSwapAck(
- int32 route_id, int gpu_host_id, int32 renderer_id) {
- // Note that multiple un-acked swaps can come in the event of a GPU process
- // loss. Drop the old acks.
- pending_swap_ack_.reset(new PendingSwapAck(
- route_id, gpu_host_id, renderer_id));
-}
-
-void RenderWidgetHostViewMac::SendPendingSwapAck() {
- if (!pending_swap_ack_)
- return;
-
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
- ack_params.sync_point = 0;
- ack_params.renderer_id = pending_swap_ack_->renderer_id;
- RenderWidgetHostImpl::AcknowledgeBufferPresent(pending_swap_ack_->route_id,
- pending_swap_ack_->gpu_host_id,
- ack_params);
- pending_swap_ack_.reset();
+void RenderWidgetHostViewMac::OnGetRenderedTextCompleted(
+ const std::string& text) {
+ SpeakText(text);
}
void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
if (!render_widget_host_ || render_widget_host_->is_hidden())
return;
- // Pausing for the overlay/underlay view prevents the other one from receiving
- // frames. This may lead to large delays, causing overlaps.
- // See crbug.com/352020.
- if (underlay_view_ || overlay_view_)
+ // Pausing for one view prevents others from receiving frames.
+ // This may lead to large delays, causing overlaps. See crbug.com/352020.
+ if (!allow_pause_for_resize_or_repaint_)
return;
- // Ensure that all frames are acked before waiting for a frame to come in.
- // Note that we will draw a frame at the end of this function, so it is safe
- // to ack a never-drawn frame here.
- SendPendingSwapAck();
-
// Wait for a frame of the right size to come in.
+ if (browser_compositor_view_)
+ browser_compositor_view_->BeginPumpingFrames();
render_widget_host_->PauseForPendingResizeOrRepaints();
-
- // Immediately draw any frames that haven't been drawn yet. This is necessary
- // to keep the window and the window's contents in sync.
- [cocoa_view_ displayIfNeeded];
- [software_layer_ displayIfNeeded];
- [compositing_iosurface_layer_ displayIfNeededAndAck];
+ if (browser_compositor_view_)
+ browser_compositor_view_->EndPumpingFrames();
}
-void RenderWidgetHostViewMac::LayoutLayers() {
- if (browser_compositor_view_) {
- [browser_compositor_view_ layoutLayers];
- return;
- }
-
- // Disable animation of the layer's resizing or change in contents scale.
- ScopedCAActionDisabler disabler;
-
- CGRect new_background_frame = NSRectToCGRect([cocoa_view() bounds]);
+SkColorType RenderWidgetHostViewMac::PreferredReadbackFormat() {
+ return kN32_SkColorType;
+}
- // Dynamically calling setContentsScale on a CAOpenGLLayer for which
- // setAsynchronous is dynamically toggled can result in flashes of corrupt
- // content. Work around this by replacing the entire layer when the scale
- // factor changes.
- if (compositing_iosurface_ &&
- [compositing_iosurface_layer_
- respondsToSelector:(@selector(contentsScale))]) {
- if (compositing_iosurface_->scale_factor() !=
- [compositing_iosurface_layer_ contentsScale]) {
- DestroyCompositedIOSurfaceLayer(kRemoveLayerFromHierarchy);
- EnsureCompositedIOSurfaceLayer();
- }
- }
- if (compositing_iosurface_ &&
- compositing_iosurface_->HasIOSurface() &&
- compositing_iosurface_layer_) {
- CGRect layer_bounds = CGRectMake(
- 0,
- 0,
- compositing_iosurface_->dip_io_surface_size().width(),
- compositing_iosurface_->dip_io_surface_size().height());
- CGPoint layer_position = CGPointMake(
- 0,
- CGRectGetHeight(new_background_frame) - CGRectGetHeight(layer_bounds));
- bool bounds_changed = !CGRectEqualToRect(
- layer_bounds, [compositing_iosurface_layer_ bounds]);
- [compositing_iosurface_layer_ setPosition:layer_position];
- [compositing_iosurface_layer_ setBounds:layer_bounds];
-
- // If the bounds changed, then draw the frame immediately, to ensure that
- // content displayed is in sync with the window size.
- if (bounds_changed) {
- // Also, sometimes, especially when infobars are being removed, the
- // setNeedsDisplay calls are dropped on the floor, and stale content is
- // displayed. Calling displayIfNeeded will ensure that the right size
- // frame is drawn to the screen.
- // http://crbug.com/350817
- // Workaround for crbug.com/395827
- if ([compositing_iosurface_layer_ isAsynchronous])
- [compositing_iosurface_layer_ setAsynchronous:NO];
- [compositing_iosurface_layer_ setNeedsDisplayAndDisplayAndAck];
- }
- }
+////////////////////////////////////////////////////////////////////////////////
+// gfx::DisplayObserver, public:
- // Changing the software layer's bounds and position doesn't always result
- // in the layer being anchored to the top-left. Set the layer's frame
- // explicitly, since this is more reliable in practice.
- if (software_layer_) {
- bool frame_changed = !CGRectEqualToRect(
- new_background_frame, [software_layer_ frame]);
- if (frame_changed) {
- [software_layer_ setFrame:new_background_frame];
- }
- }
+void RenderWidgetHostViewMac::OnDisplayAdded(const gfx::Display& display) {
}
-SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() {
- return SkBitmap::kARGB_8888_Config;
+void RenderWidgetHostViewMac::OnDisplayRemoved(const gfx::Display& display) {
}
-////////////////////////////////////////////////////////////////////////////////
-// CompositingIOSurfaceLayerClient, public:
-
-void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
- if (!render_widget_host_)
+void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
+ const gfx::Display& display, uint32_t metrics) {
+ gfx::Screen* screen = gfx::Screen::GetScreenFor(cocoa_view_);
+ if (display.id() != screen->GetDisplayNearestWindow(cocoa_view_).id())
return;
- SendPendingLatencyInfoToHost();
- SendPendingSwapAck();
- if (!succeeded)
- GotAcceleratedCompositingError();
+ UpdateScreenInfo(cocoa_view_);
}
} // namespace content
@@ -2226,15 +1693,12 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
renderWidgetHostView_.reset(r);
canBeKeyView_ = YES;
focusedPluginIdentifier_ = -1;
- renderWidgetHostView_->backing_store_scale_factor_ =
- ui::GetScaleFactorForNativeView(self);
// OpenGL support:
if ([self respondsToSelector:
@selector(setWantsBestResolutionOpenGLSurface:)]) {
[self setWantsBestResolutionOpenGLSurface:YES];
}
- handlingGlobalFrameDidChange_ = NO;
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didChangeScreenParameters:)
@@ -2245,13 +1709,6 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
}
- (void)dealloc {
- // Unbind the GL context from this view. If this is not done before super's
- // dealloc is called then the GL context will crash when it reaches into
- // the view in its destructor.
- // http://crbug.com/255608
- if (renderWidgetHostView_)
- renderWidgetHostView_->AcceleratedSurfaceRelease();
-
if (responderDelegate_ &&
[responderDelegate_ respondsToSelector:@selector(viewGone:)])
[responderDelegate_ viewGone:self];
@@ -2319,10 +1776,6 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
return [self acceptsMouseEventsWhenInactive];
}
-- (void)setTakesFocusOnlyOnMouseDown:(BOOL)b {
- takesFocusOnlyOnMouseDown_ = b;
-}
-
- (void)setCloseOnDeactivate:(BOOL)b {
closeOnDeactivate_ = b;
}
@@ -2403,16 +1856,6 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
}
mouseEventWasIgnored_ = NO;
- // TODO(rohitrao): Probably need to handle other mouse down events here.
- if ([theEvent type] == NSLeftMouseDown && takesFocusOnlyOnMouseDown_) {
- if (renderWidgetHostView_->render_widget_host_)
- renderWidgetHostView_->render_widget_host_->OnPointerEventActivate();
-
- // Manually take focus after the click but before forwarding it to the
- // renderer.
- [[self window] makeFirstResponder:self];
- }
-
// Don't cancel child popups; killing them on a mouse click would prevent the
// user from positioning the insertion point in the text field spawning the
// popup. A click outside the text field would cause the text field to drop
@@ -2449,6 +1892,10 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
if ([[self window] firstResponder] != self)
return NO;
+ // If the event is reserved by the system, then do not pass it to web content.
+ if (EventIsReservedBySystem(theEvent))
+ return NO;
+
// If we return |NO| from this function, cocoa will send the key event to
// the menu and only if the menu does not process the event to |keyDown:|. We
// want to send the event to a renderer _before_ sending it to the menu, so
@@ -2496,6 +1943,19 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
- (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv {
TRACE_EVENT0("browser", "RenderWidgetHostViewCocoa::keyEvent");
+
+ // If the user changes the system hotkey mapping after Chrome has been
+ // launched, then it is possible that a formerly reserved system hotkey is no
+ // longer reserved. The hotkey would have skipped the renderer, but would
+ // also have not been handled by the system. If this is the case, immediately
+ // return.
+ // TODO(erikchen): SystemHotkeyHelperMac should use the File System Events
+ // api to monitor changes to system hotkeys. This logic will have to be
+ // updated.
+ // http://crbug.com/383558.
+ if (EventIsReservedBySystem(theEvent))
+ return;
+
DCHECK([theEvent type] != NSKeyDown ||
!equiv == !([theEvent modifierFlags] & NSCommandKeyMask));
@@ -2931,11 +2391,6 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
if (!renderWidgetHostView_->render_widget_host_)
return;
- // Move the CALayers to their positions in the new view size. Note that
- // this will not draw anything because the non-background layers' sizes
- // didn't actually change.
- renderWidgetHostView_->LayoutLayers();
-
renderWidgetHostView_->render_widget_host_->SendScreenRects();
renderWidgetHostView_->render_widget_host_->WasResized();
if (renderWidgetHostView_->delegated_frame_host_)
@@ -2959,7 +2414,7 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
if (!renderWidgetHostView_->render_widget_host_)
return NO;
- return canBeKeyView_ && !takesFocusOnlyOnMouseDown_;
+ return canBeKeyView_;
}
- (BOOL)becomeFirstResponder {
@@ -3077,7 +2532,7 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
- (id)accessibilityAttributeValue:(NSString *)attribute {
BrowserAccessibilityManager* manager =
- renderWidgetHostView_->GetBrowserAccessibilityManager();
+ renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager();
// Contents specifies document view of RenderWidgetHostViewCocoa provided by
// BrowserAccessibilityManager. Children includes all subviews in addition to
@@ -3102,25 +2557,28 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
}
- (id)accessibilityHitTest:(NSPoint)point {
- if (!renderWidgetHostView_->GetBrowserAccessibilityManager())
+ BrowserAccessibilityManager* manager =
+ renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager();
+ if (!manager)
return self;
NSPoint pointInWindow = [[self window] convertScreenToBase:point];
NSPoint localPoint = [self convertPoint:pointInWindow fromView:nil];
localPoint.y = NSHeight([self bounds]) - localPoint.y;
- BrowserAccessibilityCocoa* root = renderWidgetHostView_->
- GetBrowserAccessibilityManager()->
- GetRoot()->ToBrowserAccessibilityCocoa();
+ BrowserAccessibilityCocoa* root =
+ manager->GetRoot()->ToBrowserAccessibilityCocoa();
id obj = [root accessibilityHitTest:localPoint];
return obj;
}
- (BOOL)accessibilityIsIgnored {
- return !renderWidgetHostView_->GetBrowserAccessibilityManager();
+ BrowserAccessibilityManager* manager =
+ renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager();
+ return !manager;
}
- (NSUInteger)accessibilityGetIndexOf:(id)child {
BrowserAccessibilityManager* manager =
- renderWidgetHostView_->GetBrowserAccessibilityManager();
+ renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager();
// Only child is root.
if (manager &&
manager->GetRoot()->ToBrowserAccessibilityCocoa() == child) {
@@ -3132,7 +2590,7 @@ void RenderWidgetHostViewMac::AcceleratedLayerDidDrawFrame(bool succeeded) {
- (id)accessibilityFocusedUIElement {
BrowserAccessibilityManager* manager =
- renderWidgetHostView_->GetBrowserAccessibilityManager();
+ renderWidgetHostView_->GetHost()->GetRootBrowserAccessibilityManager();
if (manager) {
BrowserAccessibility* focused_item = manager->GetFocus(NULL);
DCHECK(focused_item);
@@ -3627,8 +3085,13 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
}
- (void)viewDidMoveToWindow {
- if ([self window])
+ if ([self window]) {
[self updateScreenProperties];
+ } else {
+ // If the RenderWidgetHostViewCocoa is being removed from its window, tear
+ // down its browser compositor resources, if needed.
+ renderWidgetHostView_->DestroySuspendedBrowserCompositorViewIfNeeded();
+ }
if (canBeKeyView_) {
NSWindow* newWindow = [self window];
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 94f499e7c32..6ecb6698d52 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -8,6 +8,8 @@
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/message_loop/message_loop.h"
+#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/input_messages.h"
@@ -70,7 +72,7 @@ bool CheckObjectRespondsToEditCommands(NSArray* edit_commands, id test_obj) {
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
};
// Create a RenderWidget for which we can filter messages.
@@ -84,7 +86,7 @@ class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl {
edit_command_message_count_(0) {
}
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
if (message->type() == InputMsg_ExecuteEditCommand::ID)
edit_command_message_count_++;
return RenderWidgetHostImpl::Send(message);
@@ -94,6 +96,18 @@ class RenderWidgetHostEditCommandCounter : public RenderWidgetHostImpl {
};
class RenderWidgetHostViewMacEditCommandHelperTest : public PlatformTest {
+ protected:
+ virtual void SetUp() {
+ if (IsDelegatedRendererEnabled()) {
+ ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactory>(
+ new NoTransportImageTransportFactory));
+ }
+ }
+ virtual void TearDown() {
+ if (IsDelegatedRendererEnabled())
+ ImageTransportFactory::Terminate();
+ }
};
} // namespace
@@ -119,7 +133,7 @@ TEST_F(RenderWidgetHostViewMacEditCommandHelperTest,
// Owned by its |cocoa_view()|, i.e. |rwhv_cocoa|.
RenderWidgetHostViewMac* rwhv_mac = new RenderWidgetHostViewMac(
- render_widget);
+ render_widget, false);
base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa(
[rwhv_mac->cocoa_view() retain]);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index da766eac4ad..685039aefcd 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -9,6 +9,9 @@
#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
+#include "content/browser/frame_host/render_widget_host_view_guest.h"
+#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
@@ -88,7 +91,7 @@ namespace {
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
};
class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
@@ -165,6 +168,11 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
virtual void SetUp() {
RenderViewHostImplTestHarness::SetUp();
+ if (IsDelegatedRendererEnabled()) {
+ ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactory>(
+ new NoTransportImageTransportFactory));
+ }
// TestRenderViewHost's destruction assumes that its view is a
// TestRenderWidgetHostView, so store its view and reset it back to the
@@ -172,21 +180,27 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
old_rwhv_ = rvh()->GetView();
// Owned by its |cocoa_view()|, i.e. |rwhv_cocoa_|.
- rwhv_mac_ = new RenderWidgetHostViewMac(rvh());
+ rwhv_mac_ = new RenderWidgetHostViewMac(rvh(), false);
rwhv_cocoa_.reset([rwhv_mac_->cocoa_view() retain]);
}
virtual void TearDown() {
// Make sure the rwhv_mac_ is gone once the superclass's |TearDown()| runs.
rwhv_cocoa_.reset();
- pool_.Recycle();
- base::MessageLoop::current()->RunUntilIdle();
- pool_.Recycle();
+ RecycleAndWait();
// See comment in SetUp().
test_rvh()->SetView(static_cast<RenderWidgetHostViewBase*>(old_rwhv_));
+ if (IsDelegatedRendererEnabled())
+ ImageTransportFactory::Terminate();
RenderViewHostImplTestHarness::TearDown();
}
+
+ void RecycleAndWait() {
+ pool_.Recycle();
+ base::MessageLoop::current()->RunUntilIdle();
+ pool_.Recycle();
+ }
protected:
private:
// This class isn't derived from PlatformTest.
@@ -208,34 +222,6 @@ TEST_F(RenderWidgetHostViewMacTest, Basic) {
TEST_F(RenderWidgetHostViewMacTest, AcceptsFirstResponder) {
// The RWHVCocoa should normally accept first responder status.
EXPECT_TRUE([rwhv_cocoa_.get() acceptsFirstResponder]);
-
- // Unless we tell it not to.
- rwhv_mac_->SetTakesFocusOnlyOnMouseDown(true);
- EXPECT_FALSE([rwhv_cocoa_.get() acceptsFirstResponder]);
-
- // But we can set things back to the way they were originally.
- rwhv_mac_->SetTakesFocusOnlyOnMouseDown(false);
- EXPECT_TRUE([rwhv_cocoa_.get() acceptsFirstResponder]);
-}
-
-TEST_F(RenderWidgetHostViewMacTest, TakesFocusOnMouseDown) {
- base::scoped_nsobject<CocoaTestHelperWindow> window(
- [[CocoaTestHelperWindow alloc] init]);
- [[window contentView] addSubview:rwhv_cocoa_.get()];
-
- // Even if the RWHVCocoa disallows first responder, clicking on it gives it
- // focus.
- [window setPretendIsKeyWindow:YES];
- [window makeFirstResponder:nil];
- ASSERT_NE(rwhv_cocoa_.get(), [window firstResponder]);
-
- rwhv_mac_->SetTakesFocusOnlyOnMouseDown(true);
- EXPECT_FALSE([rwhv_cocoa_.get() acceptsFirstResponder]);
-
- std::pair<NSEvent*, NSEvent*> clicks =
- cocoa_test_event_utils::MouseClickInView(rwhv_cocoa_.get(), 1);
- [rwhv_cocoa_.get() mouseDown:clicks.first];
- EXPECT_EQ(rwhv_cocoa_.get(), [window firstResponder]);
}
TEST_F(RenderWidgetHostViewMacTest, Fullscreen) {
@@ -259,7 +245,7 @@ TEST_F(RenderWidgetHostViewMacTest, FullscreenCloseOnEscape) {
// Owned by its |cocoa_view()|.
RenderWidgetHostImpl* rwh = new RenderWidgetHostImpl(
&delegate, process_host, MSG_ROUTING_NONE, false);
- RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, false);
view->InitAsFullscreen(rwhv_mac_);
@@ -292,7 +278,7 @@ TEST_F(RenderWidgetHostViewMacTest, AcceleratorDestroy) {
// Owned by its |cocoa_view()|.
RenderWidgetHostImpl* rwh = new RenderWidgetHostImpl(
&delegate, process_host, MSG_ROUTING_NONE, false);
- RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, false);
view->InitAsFullscreen(rwhv_mac_);
@@ -646,7 +632,7 @@ TEST_F(RenderWidgetHostViewMacTest, BlurAndFocusOnSetActive) {
// Owned by its |cocoa_view()|.
MockRenderWidgetHostImpl* rwh = new MockRenderWidgetHostImpl(
&delegate, process_host, MSG_ROUTING_NONE);
- RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, false);
base::scoped_nsobject<CocoaTestHelperWindow> window(
[[CocoaTestHelperWindow alloc] init]);
@@ -692,7 +678,7 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
MockRenderWidgetHostDelegate delegate;
MockRenderWidgetHostImpl* host = new MockRenderWidgetHostImpl(
&delegate, process_host, MSG_ROUTING_NONE);
- RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
// Send an initial wheel event with NSEventPhaseBegan to the view.
NSEvent* event1 = MockScrollWheelEventWithPhase(@selector(phaseBegan), 0);
@@ -732,7 +718,7 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
MockRenderWidgetHostDelegate delegate;
MockRenderWidgetHostImpl* host = new MockRenderWidgetHostImpl(
&delegate, process_host, MSG_ROUTING_NONE);
- RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
// Add a delegate to the view.
base::scoped_nsobject<MockRenderWidgetHostViewMacDelegate> view_delegate(
@@ -774,4 +760,45 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
host->Shutdown();
}
+// Tests that when view initiated shutdown happens (i.e. RWHView is deleted
+// before RWH), we clean up properly and don't leak the RWHVGuest.
+TEST_F(RenderWidgetHostViewMacTest, GuestViewDoesNotLeak) {
+ MockRenderWidgetHostDelegate delegate;
+ TestBrowserContext browser_context;
+ MockRenderProcessHost* process_host =
+ new MockRenderProcessHost(&browser_context);
+
+ // Owned by its |cocoa_view()|.
+ MockRenderWidgetHostImpl* rwh = new MockRenderWidgetHostImpl(
+ &delegate, process_host, MSG_ROUTING_NONE);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(rwh, true);
+
+ // Add a delegate to the view.
+ base::scoped_nsobject<MockRenderWidgetHostViewMacDelegate> view_delegate(
+ [[MockRenderWidgetHostViewMacDelegate alloc] init]);
+ view->SetDelegate(view_delegate.get());
+
+ base::WeakPtr<RenderWidgetHostViewBase> guest_rwhv_weak =
+ (new RenderWidgetHostViewGuest(
+ rwh, NULL, view->GetWeakPtr()))->GetWeakPtr();
+
+ // Remove the cocoa_view() so |view| also goes away before |rwh|.
+ {
+ base::scoped_nsobject<RenderWidgetHostViewCocoa> rwhv_cocoa;
+ rwhv_cocoa.reset([view->cocoa_view() retain]);
+ }
+ RecycleAndWait();
+
+ // Clean up.
+ rwh->Shutdown();
+
+ // Let |guest_rwhv_weak| have a chance to delete itself.
+ base::RunLoop run_loop;
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE, run_loop.QuitClosure());
+ run_loop.Run();
+
+ ASSERT_FALSE(guest_rwhv_weak.get());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_resize_helper.cc b/chromium/content/browser/renderer_host/render_widget_resize_helper.cc
new file mode 100644
index 00000000000..3cc329d71ee
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_resize_helper.cc
@@ -0,0 +1,356 @@
+// Copyright 2014 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 "content/browser/renderer_host/render_widget_resize_helper.h"
+
+#include <list>
+
+#include "content/browser/gpu/gpu_process_host_ui_shim.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+namespace {
+
+class WrappedTask;
+class PumpableTaskRunner;
+typedef std::list<WrappedTask*> WrappedTaskQueue;
+typedef base::Callback<void(base::WaitableEvent*, base::TimeDelta)>
+ EventTimedWaitCallback;
+
+// A wrapper for IPCs and tasks that we may potentially execute in
+// WaitForSingleTaskToRun. Because these tasks are sent to two places to run,
+// we to wrap them in this structure and track whether or not they have run
+// yet, to avoid running them twice.
+class WrappedTask {
+ public:
+ WrappedTask(
+ const base::Closure& closure,
+ base::TimeDelta delay);
+ ~WrappedTask();
+ bool ShouldRunBefore(const WrappedTask& other);
+ void Run();
+ void AddToTaskRunnerQueue(PumpableTaskRunner* pumpable_task_runner);
+ void RemoveFromTaskRunnerQueue();
+ const base::TimeTicks& can_run_time() const { return can_run_time_; }
+
+ private:
+ base::Closure closure_;
+ base::TimeTicks can_run_time_;
+ bool has_run_;
+ uint64 sequence_number_;
+ WrappedTaskQueue::iterator iterator_;
+
+ // Back pointer to the pumpable task runner that this task is enqueued in.
+ scoped_refptr<PumpableTaskRunner> pumpable_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(WrappedTask);
+};
+
+// The PumpableTaskRunner is a task runner that will wrap tasks in an
+// WrappedTask, enqueues that wrapped task in the queue to be pumped via
+// WaitForSingleWrappedTaskToRun during resizes, and posts the task to a
+// target task runner. The posted task will run only once, either through a
+// WaitForSingleWrappedTaskToRun call or through the target task runner.
+class PumpableTaskRunner
+ : public base::SingleThreadTaskRunner {
+ public:
+ explicit PumpableTaskRunner(
+ const EventTimedWaitCallback& event_timed_wait_callback);
+
+ // Enqueue WrappedTask and post it to |target_task_runner_|.
+ bool EnqueueAndPostWrappedTask(
+ const tracked_objects::Location& from_here,
+ WrappedTask* task,
+ base::TimeDelta delay);
+
+ // Wait at most |max_delay| to run an enqueued task.
+ bool WaitForSingleWrappedTaskToRun(const base::TimeDelta& max_delay);
+
+ // Remove a wrapped task from the queue.
+ void RemoveWrappedTaskFromQueue(WrappedTask* task);
+
+ // base::SingleThreadTaskRunner implementation:
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
+
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
+
+ bool RunsTasksOnCurrentThread() const override;
+
+ private:
+ friend class WrappedTask;
+
+ ~PumpableTaskRunner() override;
+
+ // A queue of live messages. Must hold |task_queue_lock_| to access. Tasks
+ // are added only on the IO thread and removed only on the UI thread. The
+ // WrappedTask objects are removed from the queue when they are run (by
+ // |target_task_runner_| or by a call to WaitForSingleWrappedTaskToRun
+ // removing them out of the queue, or by TaskRunner when it is destroyed).
+ WrappedTaskQueue task_queue_;
+ base::Lock task_queue_lock_;
+
+ // Event used to wake up the UI thread if it is sleeping in
+ // WaitForSingleTaskToRun.
+ base::WaitableEvent event_;
+
+ // Callback to call TimedWait on |event_| from an appropriate class.
+ EventTimedWaitCallback event_timed_wait_callback_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> target_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(PumpableTaskRunner);
+};
+
+void HandleGpuIPC(int gpu_host_id, const IPC::Message& message) {
+ GpuProcessHostUIShim* host = GpuProcessHostUIShim::FromID(gpu_host_id);
+ if (host)
+ host->OnMessageReceived(message);
+}
+
+void HandleRendererIPC(int render_process_id, const IPC::Message& message) {
+ RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
+ if (host)
+ host->OnMessageReceived(message);
+}
+
+base::LazyInstance<RenderWidgetResizeHelper> g_render_widget_task_runner =
+ LAZY_INSTANCE_INITIALIZER;
+
+////////////////////////////////////////////////////////////////////////////////
+// WrappedTask
+
+WrappedTask::WrappedTask(
+ const base::Closure& closure,
+ base::TimeDelta delay)
+ : closure_(closure),
+ can_run_time_(base::TimeTicks::Now() + delay),
+ has_run_(false),
+ sequence_number_(0) {
+}
+
+WrappedTask::~WrappedTask() {
+ RemoveFromTaskRunnerQueue();
+}
+
+bool WrappedTask::ShouldRunBefore(const WrappedTask& other) {
+ if (can_run_time_ < other.can_run_time_)
+ return true;
+ if (can_run_time_ > other.can_run_time_)
+ return false;
+ if (sequence_number_ < other.sequence_number_)
+ return true;
+ if (sequence_number_ > other.sequence_number_)
+ return false;
+ // Sequence numbers are unique, so this should never happen.
+ NOTREACHED();
+ return false;
+}
+
+void WrappedTask::Run() {
+ if (has_run_)
+ return;
+ RemoveFromTaskRunnerQueue();
+ has_run_ = true;
+ closure_.Run();
+}
+
+void WrappedTask::AddToTaskRunnerQueue(
+ PumpableTaskRunner* pumpable_task_runner) {
+ pumpable_task_runner_ = pumpable_task_runner;
+ base::AutoLock lock(pumpable_task_runner_->task_queue_lock_);
+ static uint64 last_sequence_number = 0;
+ last_sequence_number += 1;
+ sequence_number_ = last_sequence_number;
+ iterator_ = pumpable_task_runner_->task_queue_.insert(
+ pumpable_task_runner_->task_queue_.end(), this);
+}
+
+void WrappedTask::RemoveFromTaskRunnerQueue() {
+ if (!pumpable_task_runner_.get())
+ return;
+ // The scope of the task runner's lock must be limited because removing
+ // this reference to the task runner may destroy it.
+ {
+ base::AutoLock lock(pumpable_task_runner_->task_queue_lock_);
+ pumpable_task_runner_->task_queue_.erase(iterator_);
+ iterator_ = pumpable_task_runner_->task_queue_.end();
+ }
+ pumpable_task_runner_ = NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PumpableTaskRunner
+
+PumpableTaskRunner::PumpableTaskRunner(
+ const EventTimedWaitCallback& event_timed_wait_callback)
+ : event_(false /* auto-reset */, false /* initially signalled */),
+ event_timed_wait_callback_(event_timed_wait_callback),
+ target_task_runner_(BrowserThread::GetMessageLoopProxyForThread(
+ BrowserThread::UI)) {}
+
+PumpableTaskRunner::~PumpableTaskRunner() {
+ // Because tasks hold a reference to the task runner, the task queue must
+ // be empty when it is destroyed.
+ DCHECK(task_queue_.empty());
+}
+
+bool PumpableTaskRunner::WaitForSingleWrappedTaskToRun(
+ const base::TimeDelta& max_delay) {
+ base::TimeTicks stop_waiting_time = base::TimeTicks::Now() + max_delay;
+
+ for (;;) {
+ base::TimeTicks current_time = base::TimeTicks::Now();
+ base::TimeTicks next_task_time = stop_waiting_time;
+
+ // Find the first task to execute in the list. This lookup takes O(n) time,
+ // but n is rarely more than 2, and has never been observed to be more than
+ // 12.
+ WrappedTask* task_to_execute = NULL;
+ {
+ base::AutoLock lock(task_queue_lock_);
+
+ for (WrappedTaskQueue::iterator it = task_queue_.begin(); it !=
+ task_queue_.end(); ++it) {
+ WrappedTask* potential_task = *it;
+
+ // If this task is scheduled for the future, take it into account when
+ // deciding how long to sleep, and continue on to the next task.
+ if (potential_task->can_run_time() > current_time) {
+ if (potential_task->can_run_time() < next_task_time)
+ next_task_time = potential_task->can_run_time();
+ continue;
+ }
+ // If there is a better candidate than this task, continue to the next
+ // task.
+ if (task_to_execute &&
+ task_to_execute->ShouldRunBefore(*potential_task)) {
+ continue;
+ }
+ task_to_execute = potential_task;
+ }
+ }
+
+ if (task_to_execute) {
+ task_to_execute->Run();
+ return true;
+ }
+
+ // Calculate how much time we have left before we have to stop waiting or
+ // until a currently-enqueued task will be ready to run.
+ base::TimeDelta max_sleep_time = next_task_time - current_time;
+ if (max_sleep_time <= base::TimeDelta::FromMilliseconds(0))
+ break;
+
+ event_timed_wait_callback_.Run(&event_, max_sleep_time);
+ }
+
+ return false;
+}
+
+bool PumpableTaskRunner::EnqueueAndPostWrappedTask(
+ const tracked_objects::Location& from_here,
+ WrappedTask* task,
+ base::TimeDelta delay) {
+ task->AddToTaskRunnerQueue(this);
+
+ // Notify anyone waiting on the UI thread that there is a new entry in the
+ // task map. If they don't find the entry they are looking for, then they
+ // will just continue waiting.
+ event_.Signal();
+
+ return target_task_runner_->PostDelayedTask(
+ from_here, base::Bind(&WrappedTask::Run, base::Owned(task)), delay);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PumpableTaskRunner, base::SingleThreadTaskRunner implementation:
+
+bool PumpableTaskRunner::PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ return EnqueueAndPostWrappedTask(
+ from_here,
+ new WrappedTask(task, delay),
+ delay);
+}
+
+bool PumpableTaskRunner::PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ // The correctness of non-nestable events hasn't been proven for this
+ // structure.
+ NOTREACHED();
+ return false;
+}
+
+bool PumpableTaskRunner::RunsTasksOnCurrentThread() const {
+ return target_task_runner_->RunsTasksOnCurrentThread();
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetResizeHelper
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ RenderWidgetResizeHelper::task_runner() const {
+ return task_runner_;
+}
+
+// static
+RenderWidgetResizeHelper* RenderWidgetResizeHelper::Get() {
+ return g_render_widget_task_runner.Pointer();
+}
+
+bool RenderWidgetResizeHelper::WaitForSingleTaskToRun(
+ const base::TimeDelta& max_delay) {
+ PumpableTaskRunner* pumpable_task_runner =
+ reinterpret_cast<PumpableTaskRunner*>(task_runner_.get());
+ return pumpable_task_runner->WaitForSingleWrappedTaskToRun(max_delay);
+}
+
+void RenderWidgetResizeHelper::PostRendererProcessMsg(
+ int render_process_id, const IPC::Message& msg) {
+ PumpableTaskRunner* pumpable_task_runner =
+ reinterpret_cast<PumpableTaskRunner*>(task_runner_.get());
+ pumpable_task_runner->EnqueueAndPostWrappedTask(
+ FROM_HERE,
+ new WrappedTask(base::Bind(HandleRendererIPC, render_process_id, msg),
+ base::TimeDelta()),
+ base::TimeDelta());
+}
+
+void RenderWidgetResizeHelper::PostGpuProcessMsg(
+ int gpu_host_id, const IPC::Message& msg) {
+ PumpableTaskRunner* pumpable_task_runner =
+ reinterpret_cast<PumpableTaskRunner*>(task_runner_.get());
+ pumpable_task_runner->EnqueueAndPostWrappedTask(
+ FROM_HERE,
+ new WrappedTask(base::Bind(HandleGpuIPC, gpu_host_id, msg),
+ base::TimeDelta()),
+ base::TimeDelta());
+}
+
+RenderWidgetResizeHelper::RenderWidgetResizeHelper() {
+ task_runner_ = new PumpableTaskRunner(base::Bind(&EventTimedWait));
+}
+
+RenderWidgetResizeHelper::~RenderWidgetResizeHelper() {}
+
+// static
+void RenderWidgetResizeHelper::EventTimedWait(
+ base::WaitableEvent* event, base::TimeDelta delay) {
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
+ event->TimedWait(delay);
+}
+
+} // namespace content
+
diff --git a/chromium/content/browser/renderer_host/render_widget_resize_helper.h b/chromium/content/browser/renderer_host/render_widget_resize_helper.h
new file mode 100644
index 00000000000..92e2cd2676e
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_resize_helper.h
@@ -0,0 +1,92 @@
+// Copyright 2014 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 CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_RESIZE_HELPER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_RESIZE_HELPER_H_
+
+#include "base/lazy_instance.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "ipc/ipc_message.h"
+
+namespace content {
+
+// RenderWidgetResizeHelper is used to make resize appear smooth. That is to
+// say, make sure that the window size and the size of the content being drawn
+// in that window are resized in lock-step. This is accomplished by waiting
+// inside -[RenderWidgetHostViewCocoa setFrameSize:] for the renderer (and
+// potentially browser compositor as well) to produce a frame of same size
+// as the RenderWidgetHostViewCocoa.
+//
+// The function of waiting for a frame of the correct size is done inside
+// RenderWidgetHostImpl::WaitForSurface. That function will call
+// RenderWidgetResizeHelper::WaitForSingleTaskToRun until a timeout occurs,
+// or the corresponding RenderWidgetHostViewCocoa has a renderer frame of the
+// same size as its NSView.
+//
+// This is somewhat complicated because waiting for frames requires that
+// that the browser handle the IPCs (from the renderer and the GPU processes)
+// that are required to pick up a new frame. In the ordinary run of things
+// (ignoring RenderWidgetResizeHelper), those IPCs arrive on the IO thread
+// and are posted as tasks to the UI thread either by the RenderMessageFilter
+// (for renderer processes) or the GpuProcessHostUIShim (for the GPU process).
+// The IPCs that are required to create new frames for smooth resize are sent
+// to the RenderWidgetResizeHelper using the PostRendererProcessMsg and
+// PostGpuProcessMsg methods. These functions will post them as tasks to the UI
+// thread (as usual), and will also enqueue them into a queue which will be
+// read and run in RenderWidgetResizeHelper::WaitForSingleTaskToRun, potentially
+// before the task posted to the UI thread is run. Some care is taken (see
+// WrappedTask) to make sure that the messages are only executed once.
+//
+// This is further complicated because, in order for a frame to appear, it is
+// necessary to run tasks posted by the ui::Compositor. To accomplish this, the
+// RenderWidgetResizeHelper provides a base::SingleThreadTaskRunner which,
+// when a task is posted to it, enqueues the task in the aforementioned queue,
+// which may be pumped by RenderWidgetResizeHelper::WaitForSingleTaskToRun.
+//
+class RenderWidgetResizeHelper {
+ public:
+ static RenderWidgetResizeHelper* Get();
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner() const;
+
+ // UI THREAD ONLY -----------------------------------------------------------
+
+ // Waits at most |max_delay| for a task to run. Returns true if a task ran,
+ // false if no task ran.
+ bool WaitForSingleTaskToRun(const base::TimeDelta& max_delay);
+
+ // IO THREAD ONLY -----------------------------------------------------------
+
+ // This will cause |msg| to be handled by the RenderProcessHost corresponding
+ // to |render_process_id|, on the UI thread. This will either happen when the
+ // ordinary message loop would run it, or potentially earlier in a call to
+ // WaitForSingleTaskToRun .
+ void PostRendererProcessMsg(int render_process_id, const IPC::Message& msg);
+
+ // This is similar to PostRendererProcessMsg, but will handle the message in
+ // the GpuProcessHostUIShim corresponding to |gpu_host_id|.
+ void PostGpuProcessMsg(int gpu_host_id, const IPC::Message& msg);
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<RenderWidgetResizeHelper>;
+ RenderWidgetResizeHelper();
+ ~RenderWidgetResizeHelper();
+
+ // This helper is needed to create a ScopedAllowWait inside the scope of a
+ // class where it is allowed.
+ static void EventTimedWait(
+ base::WaitableEvent* event,
+ base::TimeDelta delay);
+
+ // The task runner to which the helper will post tasks. This also maintains
+ // the task queue and does the actual work for WaitForSingleTaskToRun.
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetResizeHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_RESIZE_HELPER_H_
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
index 7598bdbcc13..b2e024e1e8c 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
@@ -5,20 +5,22 @@
#include "content/browser/renderer_host/sandbox_ipc_linux.h"
#include <fcntl.h>
-#include <fontconfig/fontconfig.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/files/scoped_file.h"
#include "base/linux_util.h"
+#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/process/launch.h"
#include "base/strings/string_number_conversions.h"
+#include "content/browser/renderer_host/font_utils_linux.h"
#include "content/common/font_config_ipc_linux.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/common/set_process_title.h"
@@ -28,122 +30,52 @@
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/npapi/bindings/npapi_extensions.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
-#include "ui/gfx/font_render_params_linux.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/font_render_params.h"
using blink::WebCString;
using blink::WebFontInfo;
using blink::WebUChar;
using blink::WebUChar32;
+namespace content {
+
namespace {
-// MSCharSetToFontconfig translates a Microsoft charset identifier to a
-// fontconfig language set by appending to |langset|.
-// Returns true if |langset| is Latin/Greek/Cyrillic.
-bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
- // We have need to translate raw fdwCharSet values into terms that
- // fontconfig can understand. (See the description of fdwCharSet in the MSDN
- // documentation for CreateFont:
- // http://msdn.microsoft.com/en-us/library/dd183499(VS.85).aspx )
- //
- // Although the argument is /called/ 'charset', the actual values conflate
- // character sets (which are sets of Unicode code points) and character
- // encodings (which are algorithms for turning a series of bits into a
- // series of code points.) Sometimes the values will name a language,
- // sometimes they'll name an encoding. In the latter case I'm assuming that
- // they mean the set of code points in the domain of that encoding.
- //
- // fontconfig deals with ISO 639-1 language codes:
- // http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
- //
- // So, for each of the documented fdwCharSet values I've had to take a
- // guess at the set of ISO 639-1 languages intended.
-
- bool is_lgc = false;
- switch (fdwCharSet) {
- case NPCharsetAnsi:
- // These values I don't really know what to do with, so I'm going to map
- // them to English also.
- case NPCharsetDefault:
- case NPCharsetMac:
- case NPCharsetOEM:
- case NPCharsetSymbol:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("en"));
- break;
- case NPCharsetBaltic:
- // The three baltic languages.
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("et"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lv"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lt"));
- break;
- case NPCharsetChineseBIG5:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-tw"));
- break;
- case NPCharsetGB2312:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-cn"));
- break;
- case NPCharsetEastEurope:
- // A scattering of eastern European languages.
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("cs"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("sk"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hu"));
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr"));
- break;
- case NPCharsetGreek:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el"));
- break;
- case NPCharsetHangul:
- case NPCharsetJohab:
- // Korean
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko"));
- break;
- case NPCharsetRussian:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru"));
- break;
- case NPCharsetShiftJIS:
- // Japanese
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ja"));
- break;
- case NPCharsetTurkish:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr"));
- break;
- case NPCharsetVietnamese:
- is_lgc = true;
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi"));
- break;
- case NPCharsetArabic:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ar"));
- break;
- case NPCharsetHebrew:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("he"));
- break;
- case NPCharsetThai:
- FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("th"));
- break;
- // default:
- // Don't add any languages in that case that we don't recognise the
- // constant.
+// Converts gfx::FontRenderParams::Hinting to WebFontRenderStyle::hintStyle.
+// Returns an int for serialization, but the underlying Blink type is a char.
+int ConvertHinting(gfx::FontRenderParams::Hinting hinting) {
+ switch (hinting) {
+ case gfx::FontRenderParams::HINTING_NONE: return 0;
+ case gfx::FontRenderParams::HINTING_SLIGHT: return 1;
+ case gfx::FontRenderParams::HINTING_MEDIUM: return 2;
+ case gfx::FontRenderParams::HINTING_FULL: return 3;
}
- return is_lgc;
+ NOTREACHED() << "Unexpected hinting value " << hinting;
+ return 0;
}
-} // namespace
+// Converts gfx::FontRenderParams::SubpixelRendering to
+// WebFontRenderStyle::useSubpixelRendering. Returns an int for serialization,
+// but the underlying Blink type is a char.
+int ConvertSubpixelRendering(
+ gfx::FontRenderParams::SubpixelRendering rendering) {
+ switch (rendering) {
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE: return 0;
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB: return 1;
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR: return 1;
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB: return 1;
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR: return 1;
+ }
+ NOTREACHED() << "Unexpected subpixel rendering value " << rendering;
+ return 0;
+}
-namespace content {
+} // namespace
SandboxIPCHandler::SandboxIPCHandler(int lifeline_fd, int browser_socket)
- : lifeline_fd_(lifeline_fd), browser_socket_(browser_socket) {
- // FontConfig doesn't provide a standard property to control subpixel
- // positioning, so we pass the current setting through to WebKit.
- WebFontInfo::setSubpixelPositioning(
- gfx::GetDefaultWebkitSubpixelPositioning());
+ : lifeline_fd_(lifeline_fd),
+ browser_socket_(browser_socket) {
}
void SandboxIPCHandler::Run() {
@@ -331,6 +263,9 @@ void SandboxIPCHandler::HandleGetFallbackFontForChar(
blink::WebFallbackFont fallbackFont;
WebFontInfo::fallbackFontForChar(c, preferred_locale.c_str(), &fallbackFont);
+ int pathIndex = FindOrAddPath(SkString(fallbackFont.filename.data()));
+ fallbackFont.fontconfigInterfaceId = pathIndex;
+
Pickle reply;
if (fallbackFont.name.data()) {
reply.WriteString(fallbackFont.name.data());
@@ -342,6 +277,7 @@ void SandboxIPCHandler::HandleGetFallbackFontForChar(
} else {
reply.WriteString(std::string());
}
+ reply.WriteInt(fallbackFont.fontconfigInterfaceId);
reply.WriteInt(fallbackFont.ttcIndex);
reply.WriteBool(fallbackFont.isBold);
reply.WriteBool(fallbackFont.isItalic);
@@ -354,25 +290,35 @@ void SandboxIPCHandler::HandleGetStyleForStrike(
PickleIterator iter,
const std::vector<base::ScopedFD*>& fds) {
std::string family;
- int sizeAndStyle;
+ bool bold, italic;
+ uint16 pixel_size;
if (!pickle.ReadString(&iter, &family) ||
- !pickle.ReadInt(&iter, &sizeAndStyle)) {
+ !pickle.ReadBool(&iter, &bold) ||
+ !pickle.ReadBool(&iter, &italic) ||
+ !pickle.ReadUInt16(&iter, &pixel_size)) {
return;
}
EnsureWebKitInitialized();
- blink::WebFontRenderStyle style;
- WebFontInfo::renderStyleForStrike(family.c_str(), sizeAndStyle, &style);
+ gfx::FontRenderParamsQuery query(true);
+ query.families.push_back(family);
+ query.pixel_size = pixel_size;
+ query.style = gfx::Font::NORMAL |
+ (bold ? gfx::Font::BOLD : 0) | (italic ? gfx::Font::ITALIC : 0);
+ const gfx::FontRenderParams params = gfx::GetFontRenderParams(query, NULL);
+
+ // These are passed as ints since they're interpreted as tri-state chars in
+ // Blink.
Pickle reply;
- reply.WriteInt(style.useBitmaps);
- reply.WriteInt(style.useAutoHint);
- reply.WriteInt(style.useHinting);
- reply.WriteInt(style.hintStyle);
- reply.WriteInt(style.useAntiAlias);
- reply.WriteInt(style.useSubpixelRendering);
- reply.WriteInt(style.useSubpixelPositioning);
+ reply.WriteInt(params.use_bitmaps);
+ reply.WriteInt(params.autohinter);
+ reply.WriteInt(params.hinting != gfx::FontRenderParams::HINTING_NONE);
+ reply.WriteInt(ConvertHinting(params.hinting));
+ reply.WriteInt(params.antialiasing);
+ reply.WriteInt(ConvertSubpixelRendering(params.subpixel_rendering));
+ reply.WriteInt(params.subpixel_positioning);
SendRendererReply(fds, reply, -1);
}
@@ -435,10 +381,6 @@ void SandboxIPCHandler::HandleMatchWithFallback(
const Pickle& pickle,
PickleIterator iter,
const std::vector<base::ScopedFD*>& fds) {
- // Unlike the other calls, for which we are an indirection in front of
- // WebKit or Skia, this call is always made via this sandbox helper
- // process. Therefore the fontconfig code goes in here directly.
-
std::string face;
bool is_bold, is_italic;
uint32 charset, fallback_family;
@@ -451,138 +393,8 @@ void SandboxIPCHandler::HandleMatchWithFallback(
return;
}
- FcLangSet* langset = FcLangSetCreate();
- bool is_lgc = MSCharSetToFontconfig(langset, charset);
-
- FcPattern* pattern = FcPatternCreate();
- FcPatternAddString(
- pattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(face.c_str()));
-
- // TODO(thestig) Check if we can access Chrome's per-script font preference
- // here and select better default fonts for non-LGC case.
- std::string generic_font_name;
- if (is_lgc) {
- switch (fallback_family) {
- case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF:
- generic_font_name = "Times New Roman";
- break;
- case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF:
- generic_font_name = "Arial";
- break;
- case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE:
- generic_font_name = "Courier New";
- break;
- }
- }
- if (!generic_font_name.empty()) {
- const FcChar8* fc_generic_font_name =
- reinterpret_cast<const FcChar8*>(generic_font_name.c_str());
- FcPatternAddString(pattern, FC_FAMILY, fc_generic_font_name);
- }
-
- if (is_bold)
- FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
- if (is_italic)
- FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
- FcPatternAddLangSet(pattern, FC_LANG, langset);
- FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
- FcConfigSubstitute(NULL, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
-
- FcResult result;
- FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
- int font_fd = -1;
- int good_enough_index = -1;
- bool good_enough_index_set = false;
-
- if (font_set) {
- for (int i = 0; i < font_set->nfont; ++i) {
- FcPattern* current = font_set->fonts[i];
-
- // Older versions of fontconfig have a bug where they cannot select
- // only scalable fonts so we have to manually filter the results.
- FcBool is_scalable;
- if (FcPatternGetBool(current, FC_SCALABLE, 0, &is_scalable) !=
- FcResultMatch ||
- !is_scalable) {
- continue;
- }
-
- FcChar8* c_filename;
- if (FcPatternGetString(current, FC_FILE, 0, &c_filename) !=
- FcResultMatch) {
- continue;
- }
-
- // We only want to return sfnt (TrueType) based fonts. We don't have a
- // very good way of detecting this so we'll filter based on the
- // filename.
- bool is_sfnt = false;
- static const char kSFNTExtensions[][5] = {".ttf", ".otc", ".TTF", ".ttc",
- ""};
- const size_t filename_len = strlen(reinterpret_cast<char*>(c_filename));
- for (unsigned j = 0;; j++) {
- if (kSFNTExtensions[j][0] == 0) {
- // None of the extensions matched.
- break;
- }
- const size_t ext_len = strlen(kSFNTExtensions[j]);
- if (filename_len > ext_len &&
- memcmp(c_filename + filename_len - ext_len,
- kSFNTExtensions[j],
- ext_len) == 0) {
- is_sfnt = true;
- break;
- }
- }
-
- if (!is_sfnt)
- continue;
-
- // This font is good enough to pass muster, but we might be able to do
- // better with subsequent ones.
- if (!good_enough_index_set) {
- good_enough_index = i;
- good_enough_index_set = true;
- }
-
- FcValue matrix;
- bool have_matrix = FcPatternGet(current, FC_MATRIX, 0, &matrix) == 0;
-
- if (is_italic && have_matrix) {
- // we asked for an italic font, but fontconfig is giving us a
- // non-italic font with a transformation matrix.
- continue;
- }
-
- FcValue embolden;
- const bool have_embolden =
- FcPatternGet(current, FC_EMBOLDEN, 0, &embolden) == 0;
-
- if (is_bold && have_embolden) {
- // we asked for a bold font, but fontconfig gave us a non-bold font
- // and asked us to apply fake bolding.
- continue;
- }
-
- font_fd = open(reinterpret_cast<char*>(c_filename), O_RDONLY);
- if (font_fd >= 0)
- break;
- }
- }
-
- if (font_fd == -1 && good_enough_index_set) {
- // We didn't find a font that we liked, so we fallback to something
- // acceptable.
- FcPattern* current = font_set->fonts[good_enough_index];
- FcChar8* c_filename;
- FcPatternGetString(current, FC_FILE, 0, &c_filename);
- font_fd = open(reinterpret_cast<char*>(c_filename), O_RDONLY);
- }
-
- if (font_set)
- FcFontSetDestroy(font_set);
- FcPatternDestroy(pattern);
+ int font_fd = MatchFontFaceWithFallback(
+ face, is_bold, is_italic, charset, fallback_family);
Pickle reply;
SendRendererReply(fds, reply, font_fd);
@@ -631,7 +443,7 @@ void SandboxIPCHandler::SendRendererReply(
SandboxIPCHandler::~SandboxIPCHandler() {
paths_.deleteAll();
- if (webkit_platform_support_)
+ if (blink_platform_impl_)
blink::shutdownWithoutV8();
if (IGNORE_EINTR(close(lifeline_fd_)) < 0)
@@ -641,10 +453,10 @@ SandboxIPCHandler::~SandboxIPCHandler() {
}
void SandboxIPCHandler::EnsureWebKitInitialized() {
- if (webkit_platform_support_)
+ if (blink_platform_impl_)
return;
- webkit_platform_support_.reset(new BlinkPlatformImpl);
- blink::initializeWithoutV8(webkit_platform_support_.get());
+ blink_platform_impl_.reset(new BlinkPlatformImpl);
+ blink::initializeWithoutV8(blink_platform_impl_.get());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.h b/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
index fc986a6189c..e6ac19bbfac 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
@@ -24,9 +24,9 @@ class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
// the other end of.
// browser_socket: the browser's end of the sandbox IPC socketpair.
SandboxIPCHandler(int lifeline_fd, int browser_socket);
- virtual ~SandboxIPCHandler();
+ ~SandboxIPCHandler() override;
- virtual void Run() OVERRIDE;
+ void Run() override;
private:
void EnsureWebKitInitialized();
@@ -76,7 +76,7 @@ class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
const int lifeline_fd_;
const int browser_socket_;
- scoped_ptr<BlinkPlatformImpl> webkit_platform_support_;
+ scoped_ptr<BlinkPlatformImpl> blink_platform_impl_;
SkTDArray<SkString*> paths_;
DISALLOW_COPY_AND_ASSIGN(SandboxIPCHandler);
diff --git a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
deleted file mode 100644
index b08b119ed92..00000000000
--- a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.cc
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/socket_stream_dispatcher_host.h"
-
-#include <string>
-
-#include "base/logging.h"
-#include "content/browser/renderer_host/socket_stream_host.h"
-#include "content/browser/ssl/ssl_manager.h"
-#include "content/common/resource_messages.h"
-#include "content/common/socket_stream.h"
-#include "content/common/socket_stream_messages.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/global_request_id.h"
-#include "net/base/net_errors.h"
-#include "net/cookies/canonical_cookie.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "net/websockets/websocket_job.h"
-#include "net/websockets/websocket_throttle.h"
-
-namespace content {
-
-namespace {
-
-const size_t kMaxSocketStreamHosts = 16 * 1024;
-
-} // namespace
-
-SocketStreamDispatcherHost::SocketStreamDispatcherHost(
- int render_process_id,
- const GetRequestContextCallback& request_context_callback,
- ResourceContext* resource_context)
- : BrowserMessageFilter(SocketStreamMsgStart),
- render_process_id_(render_process_id),
- request_context_callback_(request_context_callback),
- resource_context_(resource_context),
- weak_ptr_factory_(this),
- on_shutdown_(false) {
- net::WebSocketJob::EnsureInit();
-}
-
-bool SocketStreamDispatcherHost::OnMessageReceived(
- const IPC::Message& message) {
- if (on_shutdown_)
- return false;
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcherHost, message)
- IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Connect, OnConnect)
- IPC_MESSAGE_HANDLER(SocketStreamHostMsg_SendData, OnSendData)
- IPC_MESSAGE_HANDLER(SocketStreamHostMsg_Close, OnCloseReq)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-// SocketStream::Delegate methods implementations.
-void SocketStreamDispatcherHost::OnConnected(net::SocketStream* socket,
- int max_pending_send_allowed) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- DVLOG(2) << "SocketStreamDispatcherHost::OnConnected socket_id=" << socket_id
- << " max_pending_send_allowed=" << max_pending_send_allowed;
- if (socket_id == kNoSocketId) {
- DVLOG(1) << "NoSocketId in OnConnected";
- return;
- }
- if (!Send(new SocketStreamMsg_Connected(
- socket_id, max_pending_send_allowed))) {
- DVLOG(1) << "SocketStreamMsg_Connected failed.";
- DeleteSocketStreamHost(socket_id);
- }
-}
-
-void SocketStreamDispatcherHost::OnSentData(net::SocketStream* socket,
- int amount_sent) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- DVLOG(2) << "SocketStreamDispatcherHost::OnSentData socket_id=" << socket_id
- << " amount_sent=" << amount_sent;
- if (socket_id == kNoSocketId) {
- DVLOG(1) << "NoSocketId in OnSentData";
- return;
- }
- if (!Send(new SocketStreamMsg_SentData(socket_id, amount_sent))) {
- DVLOG(1) << "SocketStreamMsg_SentData failed.";
- DeleteSocketStreamHost(socket_id);
- }
-}
-
-void SocketStreamDispatcherHost::OnReceivedData(
- net::SocketStream* socket, const char* data, int len) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- DVLOG(2) << "SocketStreamDispatcherHost::OnReceiveData socket_id="
- << socket_id;
- if (socket_id == kNoSocketId) {
- DVLOG(1) << "NoSocketId in OnReceivedData";
- return;
- }
- if (!Send(new SocketStreamMsg_ReceivedData(
- socket_id, std::vector<char>(data, data + len)))) {
- DVLOG(1) << "SocketStreamMsg_ReceivedData failed.";
- DeleteSocketStreamHost(socket_id);
- }
-}
-
-void SocketStreamDispatcherHost::OnClose(net::SocketStream* socket) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- DVLOG(2) << "SocketStreamDispatcherHost::OnClosed socket_id=" << socket_id;
- if (socket_id == kNoSocketId) {
- DVLOG(1) << "NoSocketId in OnClose";
- return;
- }
- DeleteSocketStreamHost(socket_id);
-}
-
-void SocketStreamDispatcherHost::OnError(const net::SocketStream* socket,
- int error) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- DVLOG(2) << "SocketStreamDispatcherHost::OnError socket_id=" << socket_id;
- if (socket_id == content::kNoSocketId) {
- DVLOG(1) << "NoSocketId in OnError";
- return;
- }
- // SocketStream::Delegate::OnError() events are handled as WebSocket error
- // event when user agent was required to fail WebSocket connection or the
- // WebSocket connection is closed with prejudice.
- if (!Send(new SocketStreamMsg_Failed(socket_id, error))) {
- DVLOG(1) << "SocketStreamMsg_Failed failed.";
- DeleteSocketStreamHost(socket_id);
- }
-}
-
-void SocketStreamDispatcherHost::OnSSLCertificateError(
- net::SocketStream* socket, const net::SSLInfo& ssl_info, bool fatal) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- DVLOG(2) << "SocketStreamDispatcherHost::OnSSLCertificateError socket_id="
- << socket_id;
- if (socket_id == kNoSocketId) {
- DVLOG(1) << "NoSocketId in OnSSLCertificateError";
- return;
- }
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- DCHECK(socket_stream_host);
- GlobalRequestID request_id(-1, socket_id);
- SSLManager::OnSSLCertificateError(
- weak_ptr_factory_.GetWeakPtr(), request_id, ResourceType::SUB_RESOURCE,
- socket->url(), render_process_id_, socket_stream_host->render_frame_id(),
- ssl_info, fatal);
-}
-
-bool SocketStreamDispatcherHost::CanGetCookies(net::SocketStream* socket,
- const GURL& url) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(socket);
- if (socket_id == kNoSocketId) {
- return false;
- }
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- DCHECK(socket_stream_host);
- return GetContentClient()->browser()->AllowGetCookie(
- url,
- url,
- net::CookieList(),
- resource_context_,
- render_process_id_,
- socket_stream_host->render_frame_id());
-}
-
-bool SocketStreamDispatcherHost::CanSetCookie(net::SocketStream* request,
- const GURL& url,
- const std::string& cookie_line,
- net::CookieOptions* options) {
- int socket_id = SocketStreamHost::SocketIdFromSocketStream(request);
- if (socket_id == kNoSocketId) {
- return false;
- }
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- DCHECK(socket_stream_host);
- return GetContentClient()->browser()->AllowSetCookie(
- url,
- url,
- cookie_line,
- resource_context_,
- render_process_id_,
- socket_stream_host->render_frame_id(),
- options);
-}
-
-void SocketStreamDispatcherHost::CancelSSLRequest(
- const GlobalRequestID& id,
- int error,
- const net::SSLInfo* ssl_info) {
- int socket_id = id.request_id;
- DVLOG(2) << "SocketStreamDispatcherHost::CancelSSLRequest socket_id="
- << socket_id;
- DCHECK_NE(kNoSocketId, socket_id);
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- DCHECK(socket_stream_host);
- if (ssl_info)
- socket_stream_host->CancelWithSSLError(*ssl_info);
- else
- socket_stream_host->CancelWithError(error);
-}
-
-void SocketStreamDispatcherHost::ContinueSSLRequest(
- const GlobalRequestID& id) {
- int socket_id = id.request_id;
- DVLOG(2) << "SocketStreamDispatcherHost::ContinueSSLRequest socket_id="
- << socket_id;
- DCHECK_NE(kNoSocketId, socket_id);
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- DCHECK(socket_stream_host);
- socket_stream_host->ContinueDespiteError();
-}
-
-SocketStreamDispatcherHost::~SocketStreamDispatcherHost() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- Shutdown();
-}
-
-// Message handlers called by OnMessageReceived.
-void SocketStreamDispatcherHost::OnConnect(int render_frame_id,
- const GURL& url,
- int socket_id) {
- DVLOG(2) << "SocketStreamDispatcherHost::OnConnect"
- << " render_frame_id=" << render_frame_id
- << " url=" << url
- << " socket_id=" << socket_id;
- DCHECK_NE(kNoSocketId, socket_id);
-
- if (hosts_.size() >= kMaxSocketStreamHosts) {
- if (!Send(new SocketStreamMsg_Failed(socket_id,
- net::ERR_TOO_MANY_SOCKET_STREAMS))) {
- DVLOG(1) << "SocketStreamMsg_Failed failed.";
- }
- if (!Send(new SocketStreamMsg_Closed(socket_id))) {
- DVLOG(1) << "SocketStreamMsg_Closed failed.";
- }
- return;
- }
-
- if (hosts_.Lookup(socket_id)) {
- DVLOG(1) << "socket_id=" << socket_id << " already registered.";
- return;
- }
-
- // Note that the SocketStreamHost is responsible for checking that |url|
- // is valid.
- SocketStreamHost* socket_stream_host =
- new SocketStreamHost(this, render_process_id_, render_frame_id,
- socket_id);
- hosts_.AddWithID(socket_stream_host, socket_id);
- socket_stream_host->Connect(url, GetURLRequestContext());
- DVLOG(2) << "SocketStreamDispatcherHost::OnConnect -> " << socket_id;
-}
-
-void SocketStreamDispatcherHost::OnSendData(
- int socket_id, const std::vector<char>& data) {
- DVLOG(2) << "SocketStreamDispatcherHost::OnSendData socket_id=" << socket_id;
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- if (!socket_stream_host) {
- DVLOG(1) << "socket_id=" << socket_id << " already closed.";
- return;
- }
- if (!socket_stream_host->SendData(data)) {
- // Cannot accept more data to send.
- socket_stream_host->Close();
- }
-}
-
-void SocketStreamDispatcherHost::OnCloseReq(int socket_id) {
- DVLOG(2) << "SocketStreamDispatcherHost::OnCloseReq socket_id=" << socket_id;
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- if (!socket_stream_host)
- return;
- socket_stream_host->Close();
-}
-
-void SocketStreamDispatcherHost::DeleteSocketStreamHost(int socket_id) {
- SocketStreamHost* socket_stream_host = hosts_.Lookup(socket_id);
- DCHECK(socket_stream_host);
- delete socket_stream_host;
- hosts_.Remove(socket_id);
- if (!Send(new SocketStreamMsg_Closed(socket_id))) {
- DVLOG(1) << "SocketStreamMsg_Closed failed.";
- }
-}
-
-net::URLRequestContext* SocketStreamDispatcherHost::GetURLRequestContext() {
- return request_context_callback_.Run(ResourceType::SUB_RESOURCE);
-}
-
-void SocketStreamDispatcherHost::Shutdown() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(ukai): Implement IDMap::RemoveAll().
- for (IDMap<SocketStreamHost>::const_iterator iter(&hosts_);
- !iter.IsAtEnd();
- iter.Advance()) {
- int socket_id = iter.GetCurrentKey();
- const SocketStreamHost* socket_stream_host = iter.GetCurrentValue();
- delete socket_stream_host;
- hosts_.Remove(socket_id);
- }
- on_shutdown_ = true;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h b/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
deleted file mode 100644
index c0836138826..00000000000
--- a/chromium/content/browser/renderer_host/socket_stream_dispatcher_host.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_SOCKET_STREAM_DISPATCHER_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SOCKET_STREAM_DISPATCHER_HOST_H_
-
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/id_map.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/ssl/ssl_error_handler.h"
-#include "content/public/browser/browser_message_filter.h"
-#include "net/socket_stream/socket_stream.h"
-
-class GURL;
-
-namespace net {
-class SSLInfo;
-}
-
-namespace content {
-class ResourceContext;
-class SocketStreamHost;
-
-// Dispatches ViewHostMsg_SocketStream_* messages sent from renderer.
-// It also acts as SocketStream::Delegate so that it sends
-// ViewMsg_SocketStream_* messages back to renderer.
-class SocketStreamDispatcherHost
- : public BrowserMessageFilter,
- public net::SocketStream::Delegate,
- public SSLErrorHandler::Delegate {
- public:
- typedef base::Callback<net::URLRequestContext*(ResourceType::Type)>
- GetRequestContextCallback;
- SocketStreamDispatcherHost(
- int render_process_id,
- const GetRequestContextCallback& request_context_callback,
- ResourceContext* resource_context);
-
- // BrowserMessageFilter:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // Make this object inactive.
- // Remove all active SocketStreamHost objects.
- void Shutdown();
-
- // SocketStream::Delegate:
- virtual void OnConnected(net::SocketStream* socket,
- int max_pending_send_allowed) OVERRIDE;
- virtual void OnSentData(net::SocketStream* socket, int amount_sent) OVERRIDE;
- virtual void OnReceivedData(net::SocketStream* socket,
- const char* data, int len) OVERRIDE;
- virtual void OnClose(net::SocketStream* socket) OVERRIDE;
- virtual void OnError(const net::SocketStream* socket, int error) OVERRIDE;
- virtual void OnSSLCertificateError(net::SocketStream* socket,
- const net::SSLInfo& ssl_info,
- bool fatal) OVERRIDE;
- virtual bool CanGetCookies(net::SocketStream* socket,
- const GURL& url) OVERRIDE;
- virtual bool CanSetCookie(net::SocketStream* request,
- const GURL& url,
- const std::string& cookie_line,
- net::CookieOptions* options) OVERRIDE;
-
- // SSLErrorHandler::Delegate methods:
- virtual void CancelSSLRequest(const GlobalRequestID& id,
- int error,
- const net::SSLInfo* ssl_info) OVERRIDE;
- virtual void ContinueSSLRequest(const GlobalRequestID& id) OVERRIDE;
-
- protected:
- virtual ~SocketStreamDispatcherHost();
-
- private:
- // Message handlers called by OnMessageReceived.
- void OnConnect(int render_frame_id, const GURL& url, int socket_id);
- void OnSendData(int socket_id, const std::vector<char>& data);
- void OnCloseReq(int socket_id);
-
- void DeleteSocketStreamHost(int socket_id);
-
- net::URLRequestContext* GetURLRequestContext();
-
- IDMap<SocketStreamHost> hosts_;
- int render_process_id_;
- GetRequestContextCallback request_context_callback_;
- ResourceContext* resource_context_;
-
- base::WeakPtrFactory<SocketStreamDispatcherHost> weak_ptr_factory_;
- bool on_shutdown_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamDispatcherHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SOCKET_STREAM_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/renderer_host/socket_stream_host.cc b/chromium/content/browser/renderer_host/socket_stream_host.cc
deleted file mode 100644
index 364b8d09dde..00000000000
--- a/chromium/content/browser/renderer_host/socket_stream_host.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/renderer_host/socket_stream_host.h"
-
-#include "base/logging.h"
-#include "content/common/socket_stream.h"
-#include "content/public/browser/content_browser_client.h"
-#include "net/socket_stream/socket_stream_job.h"
-#include "net/url_request/url_request_context.h"
-
-namespace content {
-namespace {
-
-const char* kSocketIdKey = "socketId";
-
-class SocketStreamId : public net::SocketStream::UserData {
- public:
- explicit SocketStreamId(int socket_id) : socket_id_(socket_id) {}
- virtual ~SocketStreamId() {}
- int socket_id() const { return socket_id_; }
-
- private:
- int socket_id_;
-};
-
-} // namespace
-
-SocketStreamHost::SocketStreamHost(
- net::SocketStream::Delegate* delegate,
- int child_id,
- int render_frame_id,
- int socket_id)
- : delegate_(delegate),
- child_id_(child_id),
- render_frame_id_(render_frame_id),
- socket_id_(socket_id) {
- DCHECK_NE(socket_id_, kNoSocketId);
- VLOG(1) << "SocketStreamHost: render_frame_id=" << render_frame_id
- << " socket_id=" << socket_id_;
-}
-
-/* static */
-int SocketStreamHost::SocketIdFromSocketStream(
- const net::SocketStream* socket) {
- net::SocketStream::UserData* d = socket->GetUserData(kSocketIdKey);
- if (d) {
- SocketStreamId* socket_stream_id = static_cast<SocketStreamId*>(d);
- return socket_stream_id->socket_id();
- }
- return kNoSocketId;
-}
-
-SocketStreamHost::~SocketStreamHost() {
- VLOG(1) << "SocketStreamHost destructed socket_id=" << socket_id_;
- job_->DetachContext();
- job_->DetachDelegate();
-}
-
-void SocketStreamHost::Connect(const GURL& url,
- net::URLRequestContext* request_context) {
- VLOG(1) << "SocketStreamHost::Connect url=" << url;
- job_ = net::SocketStreamJob::CreateSocketStreamJob(
- url, delegate_, request_context->transport_security_state(),
- request_context->ssl_config_service(),
- request_context,
- GetContentClient()->browser()->OverrideCookieStoreForRenderProcess(
- child_id_));
- job_->SetUserData(kSocketIdKey, new SocketStreamId(socket_id_));
- job_->Connect();
-}
-
-bool SocketStreamHost::SendData(const std::vector<char>& data) {
- VLOG(1) << "SocketStreamHost::SendData";
- return job_.get() && job_->SendData(&data[0], data.size());
-}
-
-void SocketStreamHost::Close() {
- VLOG(1) << "SocketStreamHost::Close";
- if (!job_.get())
- return;
- job_->Close();
-}
-
-void SocketStreamHost::CancelWithError(int error) {
- VLOG(1) << "SocketStreamHost::CancelWithError: error=" << error;
- if (!job_.get())
- return;
- job_->CancelWithError(error);
-}
-
-void SocketStreamHost::CancelWithSSLError(const net::SSLInfo& ssl_info) {
- VLOG(1) << "SocketStreamHost::CancelWithSSLError";
- if (!job_.get())
- return;
- job_->CancelWithSSLError(ssl_info);
-}
-
-void SocketStreamHost::ContinueDespiteError() {
- VLOG(1) << "SocketStreamHost::ContinueDespiteError";
- if (!job_.get())
- return;
- job_->ContinueDespiteError();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/socket_stream_host.h b/chromium/content/browser/renderer_host/socket_stream_host.h
deleted file mode 100644
index da4716c00af..00000000000
--- a/chromium/content/browser/renderer_host/socket_stream_host.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_RENDERER_HOST_SOCKET_STREAM_HOST_H_
-#define CONTENT_BROWSER_RENDERER_HOST_SOCKET_STREAM_HOST_H_
-
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "net/socket_stream/socket_stream.h"
-
-class GURL;
-
-namespace net {
-class SocketStreamJob;
-class URLRequestContext;
-class SSLInfo;
-} // namespace net
-
-namespace content {
-
-// Host of SocketStreamHandle. Each SocketStreamHandle will have an unique
-// socket_id assigned by SocketStreamHost constructor. If socket id is
-// kNoSocketId, there is no SocketStreamHost. Each SocketStreamHost has
-// SocketStream to manage bi-directional communication over socket stream. The
-// lifetime of an instance of this class is completely controlled by the
-// SocketStreamDispatcherHost.
-class SocketStreamHost {
- public:
- SocketStreamHost(net::SocketStream::Delegate* delegate,
- int child_id,
- int render_frame_id,
- int socket_id);
- ~SocketStreamHost();
-
- // Gets socket_id associated with |socket|.
- static int SocketIdFromSocketStream(const net::SocketStream* socket);
-
- int render_frame_id() const { return render_frame_id_; }
- int socket_id() const { return socket_id_; }
-
- // Starts to open connection to |url|.
- void Connect(const GURL& url, net::URLRequestContext* request_context);
-
- // Sends |data| over the socket stream.
- // socket stream must be open to send data.
- // Returns true if the data is put in transmit buffer in socket stream.
- // Returns false otherwise (transmit buffer exceeds limit, or socket
- // stream is closed).
- bool SendData(const std::vector<char>& data);
-
- // Closes the socket stream.
- void Close();
-
- // Following CancelWithError, CancelWithSSLError, and ContinueDespiteError
- // will be called by net::SocketStream::Delegate in OnSSLCertificateError.
- // CancelWithError Cancels the connection because of an error.
- // |error| is net::Error which represents the error.
- void CancelWithError(int error);
-
- // Cancels the connection because of receiving a certificate with an error.
- void CancelWithSSLError(const net::SSLInfo& ssl_info);
-
- // Continue to establish the connection in spite of an error.
- void ContinueDespiteError();
-
- private:
- net::SocketStream::Delegate* delegate_;
- int child_id_;
- int render_frame_id_;
- int socket_id_;
-
- scoped_refptr<net::SocketStreamJob> job_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_SOCKET_STREAM_HOST_H_
diff --git a/chromium/content/browser/renderer_host/software_frame_manager.h b/chromium/content/browser/renderer_host/software_frame_manager.h
index 6d19afd972f..55729857080 100644
--- a/chromium/content/browser/renderer_host/software_frame_manager.h
+++ b/chromium/content/browser/renderer_host/software_frame_manager.h
@@ -39,7 +39,7 @@ class CONTENT_EXPORT SoftwareFrameManager : public RendererFrameManagerClient {
public:
explicit SoftwareFrameManager(
base::WeakPtr<SoftwareFrameManagerClient> client);
- virtual ~SoftwareFrameManager();
+ ~SoftwareFrameManager() override;
// Swaps to a new frame from shared memory. This frame is guaranteed to
// not be evicted until SwapToNewFrameComplete is called.
@@ -64,7 +64,7 @@ class CONTENT_EXPORT SoftwareFrameManager : public RendererFrameManagerClient {
private:
// Called by SoftwareFrameMemoryManager to demand that the current frame
// be evicted.
- virtual void EvictCurrentFrame() OVERRIDE;
+ void EvictCurrentFrame() override;
base::WeakPtr<SoftwareFrameManagerClient> client_;
diff --git a/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc b/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc
index e700f69f155..0569f259f1b 100644
--- a/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc
+++ b/chromium/content/browser/renderer_host/software_frame_manager_unittest.cc
@@ -25,13 +25,11 @@ class FakeSoftwareFrameManagerClient : public SoftwareFrameManagerClient {
HostSharedBitmapManager::current()->ProcessRemoved(
base::GetCurrentProcessHandle());
}
- virtual void SoftwareFrameWasFreed(uint32 output_surface_id,
- unsigned frame_id) OVERRIDE {
+ void SoftwareFrameWasFreed(uint32 output_surface_id,
+ unsigned frame_id) override {
freed_frames_.push_back(std::make_pair(output_surface_id, frame_id));
}
- virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE {
- ++evicted_count_;
- }
+ void ReleaseReferencesToSoftwareFrame() override { ++evicted_count_; }
bool SwapToNewFrame(uint32 output_surface, unsigned frame_id) {
cc::SoftwareFrameData frame;
diff --git a/chromium/content/browser/renderer_host/software_layer_mac.mm b/chromium/content/browser/renderer_host/software_layer_mac.mm
deleted file mode 100644
index 896e3d25595..00000000000
--- a/chromium/content/browser/renderer_host/software_layer_mac.mm
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 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 "content/browser/renderer_host/software_layer_mac.h"
-
-#include "base/debug/trace_event.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/sdk_forward_declarations.h"
-#include "ui/base/cocoa/animation_utils.h"
-
-@implementation SoftwareLayer
-
-- (id)init {
- if (self = [super init]) {
- [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
- [self setAnchorPoint:CGPointMake(0, 0)];
- // Setting contents gravity is necessary to prevent the layer from being
- // scaled during dyanmic resizes (especially with devtools open).
- [self setContentsGravity:kCAGravityTopLeft];
- }
- return self;
-}
-
-- (void)setContentsToData:(const void *)data
- withRowBytes:(size_t)rowBytes
- withPixelSize:(gfx::Size)pixelSize
- withScaleFactor:(float)scaleFactor {
- TRACE_EVENT0("browser", "-[SoftwareLayer setContentsToData]");
-
- // Disable animating the contents change or the scale factor change.
- ScopedCAActionDisabler disabler;
-
- // Set the contents of the software CALayer to be a CGImage with the provided
- // pixel data. Make a copy of the data before backing the image with them,
- // because the same buffer will be reused for the next frame.
- base::ScopedCFTypeRef<CFDataRef> dataCopy(
- CFDataCreate(NULL,
- static_cast<const UInt8 *>(data),
- rowBytes * pixelSize.height()));
- base::ScopedCFTypeRef<CGDataProviderRef> dataProvider(
- CGDataProviderCreateWithCFData(dataCopy));
- base::ScopedCFTypeRef<CGImageRef> image(
- CGImageCreate(pixelSize.width(),
- pixelSize.height(),
- 8,
- 32,
- rowBytes,
- base::mac::GetSystemColorSpace(),
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
- dataProvider,
- NULL,
- false,
- kCGRenderingIntentDefault));
- [self setContents:(id)image.get()];
-
- // Set the contents scale of the software CALayer.
- if ([self respondsToSelector:(@selector(contentsScale))] &&
- [self respondsToSelector:(@selector(setContentsScale:))] &&
- [self contentsScale] != scaleFactor) {
- [self setContentsScale:scaleFactor];
- }
-}
-
-@end
diff --git a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
index eddff7b3764..e208ccd953e 100644
--- a/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -26,7 +26,7 @@ const int64 kTaskDelayMs = 200;
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
MockRenderWidgetHostDelegate() {}
- virtual ~MockRenderWidgetHostDelegate() {}
+ ~MockRenderWidgetHostDelegate() override {}
};
// This test does not test the WebKit side of the dictionary system (which
diff --git a/chromium/content/browser/renderer_host/text_input_client_message_filter.h b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
index 4706346202e..1918620644d 100644
--- a/chromium/content/browser/renderer_host/text_input_client_message_filter.h
+++ b/chromium/content/browser/renderer_host/text_input_client_message_filter.h
@@ -25,10 +25,10 @@ class CONTENT_EXPORT TextInputClientMessageFilter
explicit TextInputClientMessageFilter(int child_id);
// BrowserMessageFilter override:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~TextInputClientMessageFilter();
+ ~TextInputClientMessageFilter() override;
private:
// IPC Message handlers:
diff --git a/chromium/content/browser/renderer_host/ui_events_helper.cc b/chromium/content/browser/renderer_host/ui_events_helper.cc
index c521ee60452..b514425cc88 100644
--- a/chromium/content/browser/renderer_host/ui_events_helper.cc
+++ b/chromium/content/browser/renderer_host/ui_events_helper.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/ui_events_helper.h"
+#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/common/input/web_touch_event_traits.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/event.h"
@@ -20,6 +21,8 @@ int WebModifiersToUIFlags(int modifiers) {
flags |= ui::EF_CONTROL_DOWN;
if (modifiers & blink::WebInputEvent::AltKey)
flags |= ui::EF_ALT_DOWN;
+ if (modifiers & blink::WebInputEvent::MetaKey)
+ flags |= ui::EF_COMMAND_DOWN;
if (modifiers & blink::WebInputEvent::LeftButtonDown)
flags |= ui::EF_LEFT_MOUSE_BUTTON;
@@ -240,27 +243,6 @@ blink::WebGestureEvent MakeWebGestureEventFromUIEvent(
return gesture_event;
}
-int EventFlagsToWebEventModifiers(int flags) {
- int modifiers = 0;
-
- if (flags & ui::EF_SHIFT_DOWN)
- modifiers |= blink::WebInputEvent::ShiftKey;
- if (flags & ui::EF_CONTROL_DOWN)
- modifiers |= blink::WebInputEvent::ControlKey;
- if (flags & ui::EF_ALT_DOWN)
- modifiers |= blink::WebInputEvent::AltKey;
- // TODO(beng): MetaKey/META_MASK
- if (flags & ui::EF_LEFT_MOUSE_BUTTON)
- modifiers |= blink::WebInputEvent::LeftButtonDown;
- if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
- modifiers |= blink::WebInputEvent::MiddleButtonDown;
- if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
- modifiers |= blink::WebInputEvent::RightButtonDown;
- if (flags & ui::EF_CAPS_LOCK_DOWN)
- modifiers |= blink::WebInputEvent::CapsLockOn;
- return modifiers;
-}
-
blink::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
const ui::TouchEvent& event,
blink::WebTouchEvent* web_event) {
@@ -304,13 +286,6 @@ blink::WebTouchPoint* UpdateWebTouchEventFromUIEvent(
// Update the location and state of the point.
point->state = TouchPointStateFromEvent(event);
- if (point->state == blink::WebTouchPoint::StateMoved) {
- // It is possible for badly written touch drivers to emit Move events even
- // when the touch location hasn't changed. In such cases, consume the event
- // and pretend nothing happened.
- if (point->position.x == event.x() && point->position.y == event.y())
- return NULL;
- }
point->position.x = event.x();
point->position.y = event.y();
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura.cc b/chromium/content/browser/renderer_host/web_input_event_aura.cc
index b754b494c81..4fe79c16dd1 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.cc
@@ -4,63 +4,18 @@
#include "content/browser/renderer_host/web_input_event_aura.h"
+#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
-#if defined(USE_OZONE)
-#include "ui/events/keycodes/keyboard_code_conversion.h"
+#if defined(USE_X11) || defined(USE_OZONE)
+#include "ui/events/keycodes/dom4/keycode_converter.h"
#endif
namespace content {
-#if defined(USE_X11) || defined(USE_OZONE)
-// From third_party/WebKit/Source/web/gtk/WebInputEventFactory.cpp:
-blink::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
- if (windows_key_code >= ui::VKEY_A &&
- windows_key_code <= ui::VKEY_Z) {
- // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
- return windows_key_code - ui::VKEY_A + 1;
- }
- if (shift) {
- // following graphics chars require shift key to input.
- switch (windows_key_code) {
- // ctrl-@ maps to \x00 (Null byte)
- case ui::VKEY_2:
- return 0;
- // ctrl-^ maps to \x1E (Record separator, Information separator two)
- case ui::VKEY_6:
- return 0x1E;
- // ctrl-_ maps to \x1F (Unit separator, Information separator one)
- case ui::VKEY_OEM_MINUS:
- return 0x1F;
- // Returns 0 for all other keys to avoid inputting unexpected chars.
- default:
- break;
- }
- } else {
- switch (windows_key_code) {
- // ctrl-[ maps to \x1B (Escape)
- case ui::VKEY_OEM_4:
- return 0x1B;
- // ctrl-\ maps to \x1C (File separator, Information separator four)
- case ui::VKEY_OEM_5:
- return 0x1C;
- // ctrl-] maps to \x1D (Group separator, Information separator three)
- case ui::VKEY_OEM_6:
- return 0x1D;
- // ctrl-Enter maps to \x0A (Line feed)
- case ui::VKEY_RETURN:
- return 0x0A;
- // Returns 0 for all other keys to avoid inputting unexpected chars.
- default:
- break;
- }
- }
- return 0;
-}
-#endif
#if defined(OS_WIN)
blink::WebMouseEvent MakeUntranslatedWebMouseEventFromNativeEvent(
const base::NativeEvent& native_event);
@@ -70,20 +25,16 @@ blink::WebKeyboardEvent MakeWebKeyboardEventFromNativeEvent(
const base::NativeEvent& native_event);
blink::WebGestureEvent MakeWebGestureEventFromNativeEvent(
const base::NativeEvent& native_event);
-#elif defined(USE_X11)
-blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
- ui::KeyEvent* event);
-#elif defined(USE_OZONE)
+#endif
+#if defined(USE_X11) || defined(USE_OZONE)
blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
ui::KeyEvent* event) {
- const base::NativeEvent& native_event = event->native_event();
- ui::EventType type = ui::EventTypeFromNative(native_event);
blink::WebKeyboardEvent webkit_event;
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
- switch (type) {
+ switch (event->type()) {
case ui::ET_KEY_PRESSED:
webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
blink::WebInputEvent::RawKeyDown;
@@ -98,32 +49,17 @@ blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
webkit_event.isSystemKey = true;
- wchar_t character = ui::KeyboardCodeFromNative(native_event);
- webkit_event.windowsKeyCode = character;
- webkit_event.nativeKeyCode = character;
-
- if (webkit_event.windowsKeyCode == ui::VKEY_RETURN)
- webkit_event.unmodifiedText[0] = '\r';
- else
- webkit_event.unmodifiedText[0] = ui::GetCharacterFromKeyCode(
- ui::KeyboardCodeFromNative(native_event),
- ui::EventFlagsFromNative(native_event));
-
- if (webkit_event.modifiers & blink::WebInputEvent::ControlKey) {
- webkit_event.text[0] =
- GetControlCharacter(
- webkit_event.windowsKeyCode,
- webkit_event.modifiers & blink::WebInputEvent::ShiftKey);
- } else {
- webkit_event.text[0] = webkit_event.unmodifiedText[0];
- }
+ webkit_event.windowsKeyCode = event->GetLocatedWindowsKeyboardCode();
+ webkit_event.nativeKeyCode =
+ ui::KeycodeConverter::CodeToNativeKeycode(event->code().c_str());
+ webkit_event.unmodifiedText[0] = event->GetUnmodifiedText();
+ webkit_event.text[0] = event->GetText();
webkit_event.setKeyIdentifierFromWindowsKeyCode();
return webkit_event;
}
-#endif
-#if defined(USE_X11) || defined(USE_OZONE)
+
blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
ui::ScrollEvent* event) {
blink::WebMouseWheelEvent webkit_event;
@@ -287,9 +223,6 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEvent(ui::ScrollEvent* event) {
}
blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
- if (!event->HasNativeEvent())
- return blink::WebKeyboardEvent();
-
// Windows can figure out whether or not to construct a RawKeyDown or a Char
// WebInputEvent based on the type of message carried in
// event->native_event(). X11 is not so fortunate, there is no separate
@@ -297,6 +230,9 @@ blink::WebKeyboardEvent MakeWebKeyboardEvent(ui::KeyEvent* event) {
// is_char() == true. We need to pass the ui::KeyEvent to the X11 function
// to detect this case so the right event type can be constructed.
#if defined(OS_WIN)
+ if (!event->HasNativeEvent())
+ return blink::WebKeyboardEvent();
+
// Key events require no translation by the aura system.
return MakeWebKeyboardEventFromNativeEvent(event->native_event());
#else
@@ -360,11 +296,20 @@ blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(ui::MouseEvent* event) {
webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
webkit_event.button = blink::WebMouseEvent::ButtonNone;
- if (event->flags() & ui::EF_LEFT_MOUSE_BUTTON)
+ int button_flags = event->flags();
+ if (event->type() == ui::ET_MOUSE_PRESSED ||
+ event->type() == ui::ET_MOUSE_RELEASED) {
+ // We want to use changed_button_flags() for mouse pressed & released.
+ // These flags can be used only if they are set which is not always the case
+ // (see e.g. GetChangedMouseButtonFlagsFromNative() in events_win.cc).
+ if (event->changed_button_flags())
+ button_flags = event->changed_button_flags();
+ }
+ if (button_flags & ui::EF_LEFT_MOUSE_BUTTON)
webkit_event.button = blink::WebMouseEvent::ButtonLeft;
- if (event->flags() & ui::EF_MIDDLE_MOUSE_BUTTON)
+ if (button_flags & ui::EF_MIDDLE_MOUSE_BUTTON)
webkit_event.button = blink::WebMouseEvent::ButtonMiddle;
- if (event->flags() & ui::EF_RIGHT_MOUSE_BUTTON)
+ if (button_flags & ui::EF_RIGHT_MOUSE_BUTTON)
webkit_event.button = blink::WebMouseEvent::ButtonRight;
switch (event->type()) {
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura.h b/chromium/content/browser/renderer_host/web_input_event_aura.h
index eeff8866a82..7d6e6ca1bf3 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.h
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.h
@@ -22,10 +22,6 @@ namespace content {
// Used for scrolling. This matches Firefox behavior.
const int kPixelsPerTick = 53;
-#if defined(USE_X11) || defined(USE_OZONE)
-CONTENT_EXPORT blink::WebUChar GetControlCharacter(
- int windows_key_code, bool shift);
-#endif
CONTENT_EXPORT blink::WebMouseEvent MakeWebMouseEvent(
ui::MouseEvent* event);
CONTENT_EXPORT blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
diff --git a/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc b/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
index d67d0cd2278..5a86f734d69 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc
@@ -25,7 +25,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEvent) {
{
// Press Ctrl.
xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
- ui::KeyEvent event(xev, false /* is_char */);
+ ui::KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// However, modifier bit for Control in |webkit_event| should be set.
EXPECT_EQ(webkit_event.modifiers, blink::WebInputEvent::ControlKey);
@@ -33,7 +33,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEvent) {
{
// Release Ctrl.
xev.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL, ControlMask);
- ui::KeyEvent event(xev, false /* is_char */);
+ ui::KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// However, modifier bit for Control in |webkit_event| shouldn't be set.
EXPECT_EQ(webkit_event.modifiers, 0);
@@ -50,7 +50,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
XEvent* xevent = xev;
xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
- ui::KeyEvent event(xev, false /* is_char */);
+ ui::KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_LCONTROL, instead of ui::VKEY_CONTROL, should be filled.
EXPECT_EQ(ui::VKEY_LCONTROL, webkit_event.windowsKeyCode);
@@ -60,7 +60,7 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
XEvent* xevent = xev;
xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_R);
- ui::KeyEvent event(xev, false /* is_char */);
+ ui::KeyEvent event(xev);
blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
// ui::VKEY_RCONTROL, instead of ui::VKEY_CONTROL, should be filled.
EXPECT_EQ(ui::VKEY_RCONTROL, webkit_event.windowsKeyCode);
@@ -73,4 +73,71 @@ TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventWindowsKeyCode) {
#endif
}
+// Checks that MakeWebKeyboardEvent fills a correct keypard modifier.
+TEST(WebInputEventAuraTest, TestMakeWebKeyboardEventKeyPadKeyCode) {
+#if defined(USE_X11)
+ struct TestCase {
+ ui::KeyboardCode ui_keycode; // The virtual key code.
+ uint32 x_keycode; // The platform key code.
+ bool expected_result; // true if the event has "isKeyPad" modifier.
+ } kTesCases[] = {
+ {ui::VKEY_0, XK_0, false},
+ {ui::VKEY_1, XK_1, false},
+ {ui::VKEY_2, XK_2, false},
+ {ui::VKEY_3, XK_3, false},
+ {ui::VKEY_4, XK_4, false},
+ {ui::VKEY_5, XK_5, false},
+ {ui::VKEY_6, XK_6, false},
+ {ui::VKEY_7, XK_7, false},
+ {ui::VKEY_8, XK_8, false},
+ {ui::VKEY_9, XK_9, false},
+
+ {ui::VKEY_NUMPAD0, XK_KP_0, true},
+ {ui::VKEY_NUMPAD1, XK_KP_1, true},
+ {ui::VKEY_NUMPAD2, XK_KP_2, true},
+ {ui::VKEY_NUMPAD3, XK_KP_3, true},
+ {ui::VKEY_NUMPAD4, XK_KP_4, true},
+ {ui::VKEY_NUMPAD5, XK_KP_5, true},
+ {ui::VKEY_NUMPAD6, XK_KP_6, true},
+ {ui::VKEY_NUMPAD7, XK_KP_7, true},
+ {ui::VKEY_NUMPAD8, XK_KP_8, true},
+ {ui::VKEY_NUMPAD9, XK_KP_9, true},
+
+ {ui::VKEY_MULTIPLY, XK_KP_Multiply, true},
+ {ui::VKEY_SUBTRACT, XK_KP_Subtract, true},
+ {ui::VKEY_ADD, XK_KP_Add, true},
+ {ui::VKEY_DIVIDE, XK_KP_Divide, true},
+ {ui::VKEY_DECIMAL, XK_KP_Decimal, true},
+ {ui::VKEY_DELETE, XK_KP_Delete, true},
+ {ui::VKEY_INSERT, XK_KP_Insert, true},
+ {ui::VKEY_END, XK_KP_End, true},
+ {ui::VKEY_DOWN, XK_KP_Down, true},
+ {ui::VKEY_NEXT, XK_KP_Page_Down, true},
+ {ui::VKEY_LEFT, XK_KP_Left, true},
+ {ui::VKEY_CLEAR, XK_KP_Begin, true},
+ {ui::VKEY_RIGHT, XK_KP_Right, true},
+ {ui::VKEY_HOME, XK_KP_Home, true},
+ {ui::VKEY_UP, XK_KP_Up, true},
+ {ui::VKEY_PRIOR, XK_KP_Page_Up, true},
+ };
+ ui::ScopedXI2Event xev;
+ for (size_t i = 0; i < arraysize(kTesCases); ++i) {
+ const TestCase& test_case = kTesCases[i];
+
+ xev.InitKeyEvent(ui::ET_KEY_PRESSED, test_case.ui_keycode, 0);
+ XEvent* xevent = xev;
+ xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(),
+ test_case.x_keycode);
+ ui::KeyEvent event(xev);
+ blink::WebKeyboardEvent webkit_event = MakeWebKeyboardEvent(&event);
+ EXPECT_EQ(test_case.expected_result,
+ (webkit_event.modifiers & blink::WebInputEvent::IsKeyPad) != 0)
+ << "Failed in " << i << "th test case: "
+ << "{ui_keycode:" << test_case.ui_keycode
+ << ", x_keycode:" << test_case.x_keycode
+ << "}, expect: " << test_case.expected_result;
+ }
+#endif
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc b/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
deleted file mode 100644
index 6a9430a62d6..00000000000
--- a/chromium/content/browser/renderer_host/web_input_event_aurax11.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Portions based heavily on:
-// third_party/WebKit/public/web/gtk/WebInputEventFactory.cpp
-//
-/*
- * Copyright (C) 2006-2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "content/browser/renderer_host/web_input_event_aura.h"
-
-#include <X11/keysym.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <cstdlib>
-
-#include "base/event_types.h"
-#include "base/logging.h"
-#include "content/browser/renderer_host/ui_events_helper.h"
-#include "ui/events/event.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/keycodes/keyboard_code_conversion_x.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-
-namespace content {
-
-// chromium WebKit does not provide a WebInputEventFactory for X11, so we have
-// to do the work here ourselves.
-
-namespace {
-
-int XKeyEventToWindowsKeyCode(XKeyEvent* event) {
- int windows_key_code =
- ui::KeyboardCodeFromXKeyEvent(reinterpret_cast<XEvent*>(event));
- if (windows_key_code == ui::VKEY_SHIFT ||
- windows_key_code == ui::VKEY_CONTROL ||
- windows_key_code == ui::VKEY_MENU) {
- // To support DOM3 'location' attribute, we need to lookup an X KeySym and
- // set ui::VKEY_[LR]XXX instead of ui::VKEY_XXX.
- KeySym keysym = XK_VoidSymbol;
- XLookupString(event, NULL, 0, &keysym, NULL);
- switch (keysym) {
- case XK_Shift_L:
- return ui::VKEY_LSHIFT;
- case XK_Shift_R:
- return ui::VKEY_RSHIFT;
- case XK_Control_L:
- return ui::VKEY_LCONTROL;
- case XK_Control_R:
- return ui::VKEY_RCONTROL;
- case XK_Meta_L:
- case XK_Alt_L:
- return ui::VKEY_LMENU;
- case XK_Meta_R:
- case XK_Alt_R:
- return ui::VKEY_RMENU;
- }
- }
- return windows_key_code;
-}
-
-} // namespace
-
-blink::WebKeyboardEvent MakeWebKeyboardEventFromAuraEvent(
- ui::KeyEvent* event) {
- const base::NativeEvent& native_event = event->native_event();
- blink::WebKeyboardEvent webkit_event;
- XKeyEvent* native_key_event = &native_event->xkey;
-
- webkit_event.timeStampSeconds = event->time_stamp().InSecondsF();
- webkit_event.modifiers = EventFlagsToWebEventModifiers(event->flags());
-
- switch (native_event->type) {
- case KeyPress:
- webkit_event.type = event->is_char() ? blink::WebInputEvent::Char :
- blink::WebInputEvent::RawKeyDown;
- break;
- case KeyRelease:
- webkit_event.type = blink::WebInputEvent::KeyUp;
- break;
- default:
- NOTREACHED();
- }
-
- if (webkit_event.modifiers & blink::WebInputEvent::AltKey)
- webkit_event.isSystemKey = true;
-
- webkit_event.windowsKeyCode = XKeyEventToWindowsKeyCode(native_key_event);
- webkit_event.nativeKeyCode = native_key_event->keycode;
-
- if (webkit_event.windowsKeyCode == ui::VKEY_RETURN)
- webkit_event.unmodifiedText[0] = '\r';
- else
- webkit_event.unmodifiedText[0] = ui::GetCharacterFromXEvent(native_event);
-
- if (webkit_event.modifiers & blink::WebInputEvent::ControlKey) {
- webkit_event.text[0] =
- GetControlCharacter(
- webkit_event.windowsKeyCode,
- webkit_event.modifiers & blink::WebInputEvent::ShiftKey);
- } else {
- webkit_event.text[0] = webkit_event.unmodifiedText[0];
- }
-
- webkit_event.setKeyIdentifierFromWindowsKeyCode();
-
- // TODO: IsAutoRepeat/IsKeyPad?
-
- return webkit_event;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc b/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
index 2af2f0814c8..d49199a7cb8 100644
--- a/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/websocket_dispatcher_host.h"
#include <string>
+#include <vector>
#include "base/callback.h"
#include "base/logging.h"
@@ -178,6 +179,21 @@ WebSocketHostState WebSocketDispatcherHost::DoDropChannel(
}
WebSocketDispatcherHost::~WebSocketDispatcherHost() {
+ std::vector<WebSocketHost*> hosts;
+ for (base::hash_map<int, WebSocketHost*>::const_iterator i = hosts_.begin();
+ i != hosts_.end(); ++i) {
+ // In order to avoid changing the container while iterating, we copy
+ // the hosts.
+ hosts.push_back(i->second);
+ }
+
+ for (size_t i = 0; i < hosts.size(); ++i) {
+ // Note that some calls to GoAway could fail. In that case hosts[i] will be
+ // deleted and removed from |hosts_| in |DoDropChannel|.
+ hosts[i]->GoAway();
+ hosts[i] = NULL;
+ }
+
STLDeleteContainerPairSecondPointers(hosts_.begin(), hosts_.end());
}
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host.h b/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
index 4179b71b2e2..b9cdd343837 100644
--- a/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
@@ -56,7 +56,7 @@ class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
const WebSocketHostFactory& websocket_host_factory);
// BrowserMessageFilter:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// The following methods are used by WebSocketHost::EventInterface to send
// IPCs from the browser to the renderer or child process. Any of them may
@@ -116,7 +116,7 @@ class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
private:
typedef base::hash_map<int, WebSocketHost*> WebSocketHostTable;
- virtual ~WebSocketDispatcherHost();
+ ~WebSocketDispatcherHost() override;
WebSocketHost* CreateWebSocketHost(int routing_id);
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
index e1506d99dd1..0d2e7057bbc 100644
--- a/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
@@ -4,11 +4,13 @@
#include "content/browser/renderer_host/websocket_dispatcher_host.h"
+#include <algorithm>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/renderer_host/websocket_host.h"
#include "content/common/websocket.h"
#include "content/common/websocket_messages.h"
@@ -23,28 +25,33 @@ namespace {
// This number is unlikely to occur by chance.
static const int kMagicRenderProcessId = 506116062;
+class WebSocketDispatcherHostTest;
+
// A mock of WebsocketHost which records received messages.
class MockWebSocketHost : public WebSocketHost {
public:
MockWebSocketHost(int routing_id,
WebSocketDispatcherHost* dispatcher,
- net::URLRequestContext* url_request_context)
- : WebSocketHost(routing_id, dispatcher, url_request_context) {
- }
+ net::URLRequestContext* url_request_context,
+ WebSocketDispatcherHostTest* owner);
- virtual ~MockWebSocketHost() {}
+ ~MockWebSocketHost() override {}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE{
+ bool OnMessageReceived(const IPC::Message& message) override {
received_messages_.push_back(message);
return true;
}
+ void GoAway() override;
+
std::vector<IPC::Message> received_messages_;
+ base::WeakPtr<WebSocketDispatcherHostTest> owner_;
};
class WebSocketDispatcherHostTest : public ::testing::Test {
public:
- WebSocketDispatcherHostTest() {
+ WebSocketDispatcherHostTest()
+ : weak_ptr_factory_(this) {
dispatcher_host_ = new WebSocketDispatcherHost(
kMagicRenderProcessId,
base::Bind(&WebSocketDispatcherHostTest::OnGetRequestContext,
@@ -53,7 +60,19 @@ class WebSocketDispatcherHostTest : public ::testing::Test {
base::Unretained(this)));
}
- virtual ~WebSocketDispatcherHostTest() {}
+ ~WebSocketDispatcherHostTest() override {
+ // We need to invalidate the issued WeakPtrs at the beginning of the
+ // destructor in order not to access destructed member variables.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ }
+
+ void GoAway(int routing_id) {
+ gone_hosts_.push_back(routing_id);
+ }
+
+ base::WeakPtr<WebSocketDispatcherHostTest> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
protected:
scoped_refptr<WebSocketDispatcherHost> dispatcher_host_;
@@ -61,6 +80,9 @@ class WebSocketDispatcherHostTest : public ::testing::Test {
// Stores allocated MockWebSocketHost instances. Doesn't take ownership of
// them.
std::vector<MockWebSocketHost*> mock_hosts_;
+ std::vector<int> gone_hosts_;
+
+ base::WeakPtrFactory<WebSocketDispatcherHostTest> weak_ptr_factory_;
private:
net::URLRequestContext* OnGetRequestContext() {
@@ -69,12 +91,25 @@ class WebSocketDispatcherHostTest : public ::testing::Test {
WebSocketHost* CreateWebSocketHost(int routing_id) {
MockWebSocketHost* host =
- new MockWebSocketHost(routing_id, dispatcher_host_.get(), NULL);
+ new MockWebSocketHost(routing_id, dispatcher_host_.get(), NULL, this);
mock_hosts_.push_back(host);
return host;
}
};
+MockWebSocketHost::MockWebSocketHost(
+ int routing_id,
+ WebSocketDispatcherHost* dispatcher,
+ net::URLRequestContext* url_request_context,
+ WebSocketDispatcherHostTest* owner)
+ : WebSocketHost(routing_id, dispatcher, url_request_context),
+ owner_(owner->GetWeakPtr()) {}
+
+void MockWebSocketHost::GoAway() {
+ if (owner_)
+ owner_->GoAway(routing_id());
+}
+
TEST_F(WebSocketDispatcherHostTest, Construct) {
// Do nothing.
}
@@ -156,5 +191,29 @@ TEST_F(WebSocketDispatcherHostTest, SendFrame) {
}
}
+TEST_F(WebSocketDispatcherHostTest, Destruct) {
+ WebSocketHostMsg_AddChannelRequest message1(
+ 123, GURL("ws://example.com/test"), std::vector<std::string>(),
+ url::Origin("http://example.com"), -1);
+ WebSocketHostMsg_AddChannelRequest message2(
+ 456, GURL("ws://example.com/test2"), std::vector<std::string>(),
+ url::Origin("http://example.com"), -1);
+
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message1));
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message2));
+
+ ASSERT_EQ(2u, mock_hosts_.size());
+
+ mock_hosts_.clear();
+ dispatcher_host_ = NULL;
+
+ ASSERT_EQ(2u, gone_hosts_.size());
+ // The gone_hosts_ ordering is not predictable because it depends on the
+ // hash_map ordering.
+ std::sort(gone_hosts_.begin(), gone_hosts_.end());
+ EXPECT_EQ(123, gone_hosts_[0]);
+ EXPECT_EQ(456, gone_hosts_[1]);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_host.cc b/chromium/content/browser/renderer_host/websocket_host.cc
index 7f639180372..9b557fedab3 100644
--- a/chromium/content/browser/renderer_host/websocket_host.cc
+++ b/chromium/content/browser/renderer_host/websocket_host.cc
@@ -17,6 +17,7 @@
#include "net/http/http_util.h"
#include "net/ssl/ssl_info.h"
#include "net/websockets/websocket_channel.h"
+#include "net/websockets/websocket_errors.h"
#include "net/websockets/websocket_event_interface.h"
#include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode
#include "net/websockets/websocket_handshake_request_info.h"
@@ -87,47 +88,44 @@ class WebSocketEventHandler : public net::WebSocketEventInterface {
WebSocketEventHandler(WebSocketDispatcherHost* dispatcher,
int routing_id,
int render_frame_id);
- virtual ~WebSocketEventHandler();
+ ~WebSocketEventHandler() override;
// net::WebSocketEventInterface implementation
- virtual ChannelState OnAddChannelResponse(
- bool fail,
- const std::string& selected_subprotocol,
- const std::string& extensions) OVERRIDE;
- virtual ChannelState OnDataFrame(bool fin,
- WebSocketMessageType type,
- const std::vector<char>& data) OVERRIDE;
- virtual ChannelState OnClosingHandshake() OVERRIDE;
- virtual ChannelState OnFlowControl(int64 quota) OVERRIDE;
- virtual ChannelState OnDropChannel(bool was_clean,
- uint16 code,
- const std::string& reason) OVERRIDE;
- virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE;
- virtual ChannelState OnStartOpeningHandshake(
- scoped_ptr<net::WebSocketHandshakeRequestInfo> request) OVERRIDE;
- virtual ChannelState OnFinishOpeningHandshake(
- scoped_ptr<net::WebSocketHandshakeResponseInfo> response) OVERRIDE;
- virtual ChannelState OnSSLCertificateError(
+ ChannelState OnAddChannelResponse(bool fail,
+ const std::string& selected_subprotocol,
+ const std::string& extensions) override;
+ ChannelState OnDataFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) override;
+ ChannelState OnClosingHandshake() override;
+ ChannelState OnFlowControl(int64 quota) override;
+ ChannelState OnDropChannel(bool was_clean,
+ uint16 code,
+ const std::string& reason) override;
+ ChannelState OnFailChannel(const std::string& message) override;
+ ChannelState OnStartOpeningHandshake(
+ scoped_ptr<net::WebSocketHandshakeRequestInfo> request) override;
+ ChannelState OnFinishOpeningHandshake(
+ scoped_ptr<net::WebSocketHandshakeResponseInfo> response) override;
+ ChannelState OnSSLCertificateError(
scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
const GURL& url,
const net::SSLInfo& ssl_info,
- bool fatal) OVERRIDE;
+ bool fatal) override;
private:
class SSLErrorHandlerDelegate : public SSLErrorHandler::Delegate {
public:
SSLErrorHandlerDelegate(
scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks);
- virtual ~SSLErrorHandlerDelegate();
+ ~SSLErrorHandlerDelegate() override;
base::WeakPtr<SSLErrorHandler::Delegate> GetWeakPtr();
// SSLErrorHandler::Delegate methods
- virtual void CancelSSLRequest(const GlobalRequestID& id,
- int error,
- const net::SSLInfo* ssl_info) OVERRIDE;
- virtual void ContinueSSLRequest(const GlobalRequestID& id) OVERRIDE;
+ void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) override;
+ void ContinueSSLRequest() override;
private:
scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks_;
@@ -275,11 +273,8 @@ ChannelState WebSocketEventHandler::OnSSLCertificateError(
<< " cert_status=" << ssl_info.cert_status << " fatal=" << fatal;
ssl_error_handler_delegate_.reset(
new SSLErrorHandlerDelegate(callbacks.Pass()));
- // We don't need request_id to be unique so just make a fake one.
- GlobalRequestID request_id(-1, -1);
SSLManager::OnSSLCertificateError(ssl_error_handler_delegate_->GetWeakPtr(),
- request_id,
- ResourceType::SUB_RESOURCE,
+ RESOURCE_TYPE_SUB_RESOURCE,
url,
dispatcher_->render_process_id(),
render_frame_id_,
@@ -301,7 +296,6 @@ WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
}
void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
- const GlobalRequestID& id,
int error,
const net::SSLInfo* ssl_info) {
DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
@@ -311,8 +305,7 @@ void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
callbacks_->CancelSSLRequest(error, ssl_info);
}
-void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest(
- const GlobalRequestID& id) {
+void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest() {
DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
callbacks_->ContinueSSLRequest();
}
@@ -330,6 +323,10 @@ WebSocketHost::WebSocketHost(int routing_id,
WebSocketHost::~WebSocketHost() {}
+void WebSocketHost::GoAway() {
+ OnDropChannel(false, static_cast<uint16>(net::kWebSocketErrorGoingAway), "");
+}
+
bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
diff --git a/chromium/content/browser/renderer_host/websocket_host.h b/chromium/content/browser/renderer_host/websocket_host.h
index 21c77dcbbd5..39c1e41edbe 100644
--- a/chromium/content/browser/renderer_host/websocket_host.h
+++ b/chromium/content/browser/renderer_host/websocket_host.h
@@ -40,10 +40,16 @@ class CONTENT_EXPORT WebSocketHost {
net::URLRequestContext* url_request_context);
virtual ~WebSocketHost();
+ // The renderer process is going away.
+ // This function is virtual for testing.
+ virtual void GoAway();
+
// General message dispatch. WebSocketDispatcherHost::OnMessageReceived
// delegates to this method after looking up the |routing_id|.
virtual bool OnMessageReceived(const IPC::Message& message);
+ int routing_id() const { return routing_id_; }
+
private:
// Handlers for each message type, dispatched by OnMessageReceived(), as
// defined in content/common/websocket_messages.h
diff --git a/chromium/content/browser/resolve_proxy_msg_helper.cc b/chromium/content/browser/resolve_proxy_msg_helper.cc
index 5f0a6cd52d7..e189f1c83d3 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "content/common/view_messages.h"
+#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
@@ -91,10 +92,10 @@ void ResolveProxyMsgHelper::StartPendingRequest() {
// Start the request.
int result = proxy_service_->ResolveProxy(
- req.url, &proxy_info_,
+ req.url, net::LOAD_NORMAL, &proxy_info_,
base::Bind(&ResolveProxyMsgHelper::OnResolveProxyCompleted,
base::Unretained(this)),
- &req.pac_req, net::BoundNetLog());
+ &req.pac_req, NULL, net::BoundNetLog());
// Completed synchronously.
if (result != net::ERR_IO_PENDING)
diff --git a/chromium/content/browser/resolve_proxy_msg_helper.h b/chromium/content/browser/resolve_proxy_msg_helper.h
index 167d946e545..f076d97d64f 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper.h
+++ b/chromium/content/browser/resolve_proxy_msg_helper.h
@@ -38,14 +38,14 @@ class CONTENT_EXPORT ResolveProxyMsgHelper : public BrowserMessageFilter {
explicit ResolveProxyMsgHelper(net::ProxyService* proxy_service);
// BrowserMessageFilter implementation
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnResolveProxy(const GURL& url, IPC::Message* reply_msg);
protected:
// Destruction cancels the current outstanding request, and clears the
// pending queue.
- virtual ~ResolveProxyMsgHelper();
+ ~ResolveProxyMsgHelper() override;
private:
// Callback for the ProxyService (bound to |callback_|).
diff --git a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
index 023fe43567a..1a19018e711 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -18,10 +18,9 @@ namespace content {
// This ProxyConfigService always returns "http://pac" as the PAC url to use.
class MockProxyConfigService : public net::ProxyConfigService {
public:
- virtual void AddObserver(Observer* observer) OVERRIDE {}
- virtual void RemoveObserver(Observer* observer) OVERRIDE {}
- virtual ConfigAvailability GetLatestProxyConfig(
- net::ProxyConfig* results) OVERRIDE {
+ void AddObserver(Observer* observer) override {}
+ void RemoveObserver(Observer* observer) override {}
+ ConfigAvailability GetLatestProxyConfig(net::ProxyConfig* results) override {
*results = net::ProxyConfig::CreateFromCustomPacURL(GURL("http://pac"));
return CONFIG_VALID;
}
@@ -34,14 +33,14 @@ class TestResolveProxyMsgHelper : public ResolveProxyMsgHelper {
IPC::Listener* listener)
: ResolveProxyMsgHelper(proxy_service),
listener_(listener) {}
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
listener_->OnMessageReceived(*message);
delete message;
return true;
}
protected:
- virtual ~TestResolveProxyMsgHelper() {}
+ ~TestResolveProxyMsgHelper() override {}
IPC::Listener* listener_;
};
@@ -87,7 +86,7 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
scoped_ptr<PendingResult> pending_result_;
private:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& msg) override {
TupleTypes<ViewHostMsg_ResolveProxy::ReplyParam>::ValueTuple reply_data;
EXPECT_TRUE(ViewHostMsg_ResolveProxy::ReadReplyParam(&msg, &reply_data));
DCHECK(!pending_result_.get());
diff --git a/chromium/content/browser/resource_context_impl.cc b/chromium/content/browser/resource_context_impl.cc
index 14115a4887c..f9f3bc890a7 100644
--- a/chromium/content/browser/resource_context_impl.cc
+++ b/chromium/content/browser/resource_context_impl.cc
@@ -94,8 +94,11 @@ StreamContext* GetStreamContextForResourceContext(
HostZoomMap* GetHostZoomMapForResourceContext(ResourceContext* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return static_cast<NonOwningZoomData*>(
- context->GetUserData(kHostZoomMapKeyName))->host_zoom_map();
+ NonOwningZoomData* result = static_cast<NonOwningZoomData*>(
+ context->GetUserData(kHostZoomMapKeyName));
+ if (!result)
+ return NULL;
+ return result->host_zoom_map();
}
URLDataManagerBackend* GetURLDataManagerForResourceContext(
@@ -128,7 +131,7 @@ void InitializeResourceContext(BrowserContext* browser_context) {
resource_context->SetUserData(
kHostZoomMapKeyName,
new NonOwningZoomData(
- HostZoomMap::GetForBrowserContext(browser_context)));
+ HostZoomMap::GetDefaultForBrowserContext(browser_context)));
resource_context->DetachUserDataThread();
}
diff --git a/chromium/content/browser/resources/gpu/gpu_internals.html b/chromium/content/browser/resources/gpu/gpu_internals.html
index a54861b404a..709af4326f9 100644
--- a/chromium/content/browser/resources/gpu/gpu_internals.html
+++ b/chromium/content/browser/resources/gpu/gpu_internals.html
@@ -40,6 +40,7 @@ tabbox tabpanels {
<script src="chrome://resources/js/cr/ui.js"></script>
<script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
<script src="chrome://resources/js/cr/ui/tabs.js"></script>
+<script src="chrome://resources/js/load_time_data.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="gpu_internals.js"></script>
<script src="strings.js"></script>
@@ -48,8 +49,7 @@ tabbox tabpanels {
<div id="debug-div">
</div>
<include src="info_view.html">
- <script src="chrome://resources/js/i18n_template.js"></script>
- <script src="chrome://resources/js/i18n_process.js"></script>
+ <script src="chrome://resources/js/i18n_template2.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
</body>
</html>
diff --git a/chromium/content/browser/resources/gpu/info_view.css b/chromium/content/browser/resources/gpu/info_view.css
index b78ab1974a6..39e8d6b6e7f 100644
--- a/chromium/content/browser/resources/gpu/info_view.css
+++ b/chromium/content/browser/resources/gpu/info_view.css
@@ -19,12 +19,12 @@
#info-view h3,
#info-view ul {
- -webkit-margin-after: 0;
- -webkit-margin-before: 0;
+ margin-bottom: 0;
+ margin-top: 0;
}
#info-view > div {
- -webkit-margin-after: 1em;
+ margin-bottom: 1em;
}
#info-view .row-title {
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index 2dbe5a174b2..e4d1795cf99 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -94,6 +94,7 @@ cr.define('gpu', function() {
'panel_fitting': 'Panel Fitting',
'rasterization': 'Rasterization',
'threaded_rasterization': 'Threaded Rasterization',
+ 'multiple_raster_threads': 'Multiple Raster Threads',
};
var statusMap = {
@@ -101,10 +102,6 @@ cr.define('gpu', function() {
'label': 'Software only. Hardware acceleration disabled',
'class': 'feature-yellow'
},
- 'disabled_software_threaded': {
- 'label': 'Software only, threaded. Hardware acceleration disabled',
- 'class': 'feature-yellow'
- },
'disabled_off': {
'label': 'Disabled',
'class': 'feature-red'
@@ -117,10 +114,6 @@ cr.define('gpu', function() {
'label': 'Software only, hardware acceleration unavailable',
'class': 'feature-yellow'
},
- 'unavailable_software_threaded': {
- 'label': 'Software only, threaded. Hardware acceleration unavailable',
- 'class': 'feature-yellow'
- },
'unavailable_off': {
'label': 'Unavailable',
'class': 'feature-red'
@@ -137,10 +130,6 @@ cr.define('gpu', function() {
'label': 'Hardware accelerated on all pages',
'class': 'feature-green'
},
- 'enabled_threaded': {
- 'label': 'Hardware accelerated and threaded',
- 'class': 'feature-green'
- },
'enabled': {
'label': 'Hardware accelerated',
'class': 'feature-green'
@@ -148,7 +137,11 @@ cr.define('gpu', function() {
'enabled_on': {
'label': 'Enabled',
'class': 'feature-green'
- }
+ },
+ 'enabled_force_on': {
+ 'label': 'Force enabled',
+ 'class': 'feature-green'
+ },
};
// GPU info, basic
diff --git a/chromium/content/browser/resources/gpu/timeline_test.html b/chromium/content/browser/resources/gpu/timeline_test.html
index e21f90e705e..107840a8dd8 100644
--- a/chromium/content/browser/resources/gpu/timeline_test.html
+++ b/chromium/content/browser/resources/gpu/timeline_test.html
@@ -8,7 +8,7 @@ found in the LICENSE file.
<head>
<title></title>
<link rel="stylesheet" href="timeline.css">
-<!--<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>-->
+<!--<script src="https://cdn.rawgit.com/google/closure-library/master/closure/goog/base.js"></script>-->
<script src="../../../../ui/webui/resources/js/cr.js"></script>
<script src="../../../../ui/webui/resources/js/cr/event_target.js"></script>
<script src="../../../../ui/webui/resources/js/cr/ui.js"></script>
diff --git a/chromium/content/browser/resources/indexed_db/OWNERS b/chromium/content/browser/resources/indexed_db/OWNERS
index b106dad853f..95724907398 100644
--- a/chromium/content/browser/resources/indexed_db/OWNERS
+++ b/chromium/content/browser/resources/indexed_db/OWNERS
@@ -1,4 +1,3 @@
dgrogan@chromium.org
michaeln@chromium.org
jsbell@chromium.org
-alecflett@chromium.org
diff --git a/chromium/content/browser/resources/indexed_db/indexeddb_internals.html b/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
index bf7fa1ce78a..f389e9fbc89 100644
--- a/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
+++ b/chromium/content/browser/resources/indexed_db/indexeddb_internals.html
@@ -13,8 +13,13 @@
<div id="indexeddb-list-template"
jsvalues="$partition_path:$this.partition_path">
<div class="indexeddb-summary">
- <span>Instances in: </span>
- <span jscontent="$this.partition_path"></span>
+ <span jsdisplay="$this.partition_path">
+ <span>Instances in: </span>
+ <span jscontent="$this.partition_path"></span>
+ </span>
+ <span jsdisplay="!$this.partition_path">
+ <span>Instances: Incognito </span>
+ </span>
<span jscontent="'(' + $this.idbs.length + ')'"></span>
</div>
<div class="indexeddb-item" jsselect="$this.idbs">
@@ -181,4 +186,3 @@
<script src="chrome://resources/js/i18n_template2.js"></script>
</body>
</html>
-
diff --git a/chromium/content/browser/resources/media/OWNERS b/chromium/content/browser/resources/media/OWNERS
index bcb6c2496fd..ad545785604 100644
--- a/chromium/content/browser/resources/media/OWNERS
+++ b/chromium/content/browser/resources/media/OWNERS
@@ -1,8 +1,6 @@
-acolwell@chromium.org
dalecurtis@chromium.org
ddorwin@chromium.org
scherkus@chromium.org
-shadi@chromium.org
tommi@chromium.org
vrk@chromium.org
wjia@chromium.org
diff --git a/chromium/content/browser/resources/media/client_renderer.js b/chromium/content/browser/resources/media/client_renderer.js
index 5cdedaabb47..0eedb35df46 100644
--- a/chromium/content/browser/resources/media/client_renderer.js
+++ b/chromium/content/browser/resources/media/client_renderer.js
@@ -122,6 +122,67 @@ var ClientRenderer = (function() {
}
},
+ createVideoCaptureFormatTable: function(formats) {
+ if (!formats || formats.length == 0)
+ return document.createTextNode('No formats');
+
+ var table = document.createElement('table');
+ var thead = document.createElement('thead');
+ var theadRow = document.createElement('tr');
+ for (var key in formats[0]) {
+ var th = document.createElement('th');
+ th.appendChild(document.createTextNode(key));
+ theadRow.appendChild(th);
+ }
+ thead.appendChild(theadRow);
+ table.appendChild(thead);
+ var tbody = document.createElement('tbody');
+ for (var i=0; i < formats.length; ++i) {
+ var tr = document.createElement('tr')
+ for (var key in formats[i]) {
+ var td = document.createElement('td');
+ td.appendChild(document.createTextNode(formats[i][key]));
+ tr.appendChild(td);
+ }
+ tbody.appendChild(tr);
+ }
+ table.appendChild(tbody);
+ table.classList.add('video-capture-formats-table');
+ return table;
+ },
+
+ redrawVideoCaptureCapabilities: function(videoCaptureCapabilities, keys) {
+ var copyButtonElement =
+ document.getElementById('video-capture-capabilities-copy-button');
+ copyButtonElement.onclick = function() {
+ window.prompt('Copy to clipboard: Ctrl+C, Enter',
+ JSON.stringify(videoCaptureCapabilities))
+ }
+
+ var videoTableBodyElement =
+ document.getElementById('video-capture-capabilities-tbody');
+ removeChildren(videoTableBodyElement);
+
+ for (var component in videoCaptureCapabilities) {
+ var tableRow = document.createElement('tr');
+ var device = videoCaptureCapabilities[ component ];
+ for (var i in keys) {
+ var value = device[keys[i]];
+ var tableCell = document.createElement('td');
+ var cellElement;
+ if ((typeof value) == (typeof [])) {
+ cellElement = this.createVideoCaptureFormatTable(value);
+ } else {
+ cellElement = document.createTextNode(
+ ((typeof value) == 'undefined') ? 'n/a' : value);
+ }
+ tableCell.appendChild(cellElement)
+ tableRow.appendChild(tableCell);
+ }
+ videoTableBodyElement.appendChild(tableRow);
+ }
+ },
+
redrawAudioComponentList_: function(componentType, components) {
function redrawList(renderer, baseName, element) {
var fragment = document.createDocumentFragment();
diff --git a/chromium/content/browser/resources/media/disjoint_range_set_test.html b/chromium/content/browser/resources/media/disjoint_range_set_test.html
index 39db9b34b45..7f2d128a79d 100644
--- a/chromium/content/browser/resources/media/disjoint_range_set_test.html
+++ b/chromium/content/browser/resources/media/disjoint_range_set_test.html
@@ -7,7 +7,7 @@ found in the LICENSE file.
-->
<head>
<title></title>
- <script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
+ <script src="https://cdn.rawgit.com/google/closure-library/master/closure/goog/base.js"></script>
<script src="../../../../ui/webui/resources/js/cr.js"></script>
<script src="disjoint_range_set.js"></script>
<script>
diff --git a/chromium/content/browser/resources/media/dump_creator.js b/chromium/content/browser/resources/media/dump_creator.js
index 24f6d6a18fa..15d708b3daf 100644
--- a/chromium/content/browser/resources/media/dump_creator.js
+++ b/chromium/content/browser/resources/media/dump_creator.js
@@ -40,11 +40,11 @@ var DumpCreator = (function() {
' calls and for future WebRTC calls. When the box is unchecked or' +
' this page is closed, all ongoing recordings will be stopped and' +
' this recording functionality will be disabled for future WebRTC' +
- ' calls. Recordings in multiple tabs is supported as well as multiple' +
- ' recordings in the same tab. When enabling, you select a base' +
- ' filename to save the dump(s) to. The base filename will have a' +
- ' suffix appended to it as &lt;base filename&gt;.&lt;unique ID for' +
- ' the render process&gt;.&lt;recording ID&gt;. If recordings are' +
+ ' calls. Recordings in multiple tabs are supported as well as' +
+ ' multiple recordings in the same tab. When enabling, you select a' +
+ ' base filename to save the dump(s) to. The base filename will have a' +
+ ' suffix appended to it as &lt;base filename&gt;.&lt;render process' +
+ ' ID&gt;.&lt;recording ID&gt;. If recordings are' +
' disabled and then enabled using the same base filename, the' +
' file(s) will be appended to and may become invalid. It is' +
' recommended to choose a new base filename each time or move' +
@@ -86,7 +86,9 @@ var DumpCreator = (function() {
{type: 'octet/stream'});
var URL = window.URL.createObjectURL(textBlob);
- this.root_.getElementsByTagName('a')[0].href = URL;
+ var anchor = this.root_.getElementsByTagName('a')[0];
+ anchor.href = URL;
+ anchor.download = 'webrtc_internals_dump.txt';
// The default action of the anchor will download the URL.
},
diff --git a/chromium/content/browser/resources/media/main.js b/chromium/content/browser/resources/media/main.js
index cb239da2d54..7045197ebe9 100644
--- a/chromium/content/browser/resources/media/main.js
+++ b/chromium/content/browser/resources/media/main.js
@@ -39,12 +39,16 @@ var media = (function() {
manager = theManager;
};
- media.onReceiveEverything = function(everything) {
- for (var component in everything) {
- media.updateAudioComponent(everything[component]);
+ media.onReceiveAudioStreamData = function(audioStreamData) {
+ for (var component in audioStreamData) {
+ media.updateAudioComponent(audioStreamData[component]);
}
};
+ media.onReceiveVideoCaptureCapabilities = function(videoCaptureCapabilities) {
+ manager.updateVideoCaptureCapabilities(videoCaptureCapabilities)
+ }
+
media.onReceiveConstants = function(constants) {
for (var key in constants.eventTypes) {
var value = constants.eventTypes[key];
diff --git a/chromium/content/browser/resources/media/manager.js b/chromium/content/browser/resources/media/manager.js
index 80cd03273b7..5508c66cd79 100644
--- a/chromium/content/browser/resources/media/manager.js
+++ b/chromium/content/browser/resources/media/manager.js
@@ -109,6 +109,49 @@ var Manager = (function() {
this.players_[id],
key,
value);
+ },
+
+ parseVideoCaptureFormat_: function(format) {
+ /**
+ * Example:
+ *
+ * format:
+ * "resolution: 1280x720, fps: 30.000000, pixel format: I420"
+ *
+ * formatDict:
+ * {'resolution':'1280x720', 'fps': '30.00'}
+ */
+ var parts = format.split(', ');
+ var formatDict = {};
+ for (var i in parts) {
+ var kv = parts[i].split(': ');
+ formatDict[kv[0]] = kv[1];
+ }
+
+ // Round down the FPS to 2 decimals.
+ formatDict['fps'] = parseFloat(formatDict['fps']).toFixed(2);
+
+ // The camera does not actually output I420 so this info is misleading.
+ delete formatDict['pixel format'];
+
+ return formatDict;
+ },
+
+ updateVideoCaptureCapabilities: function(videoCaptureCapabilities) {
+ // Parse the video formats to be structured for the table.
+ for (var i in videoCaptureCapabilities) {
+ for (var j in videoCaptureCapabilities[i]['formats']) {
+ videoCaptureCapabilities[i]['formats'][j] =
+ this.parseVideoCaptureFormat_(
+ videoCaptureCapabilities[i]['formats'][j]);
+ }
+ }
+
+ // The keys of each device to be shown in order of appearance.
+ var videoCaptureDeviceKeys = ['name','formats','captureApi','id'];
+
+ this.clientRenderer_.redrawVideoCaptureCapabilities(
+ videoCaptureCapabilities, videoCaptureDeviceKeys);
}
};
diff --git a/chromium/content/browser/resources/media/media_internals.css b/chromium/content/browser/resources/media/media_internals.css
index 041527f951c..0165c3f4010 100644
--- a/chromium/content/browser/resources/media/media_internals.css
+++ b/chromium/content/browser/resources/media/media_internals.css
@@ -9,6 +9,7 @@ body,
padding: 0;
width: 100%;
height: 100%;
+ font-family:Arial;
}
table {
@@ -86,6 +87,12 @@ h3 {
#property-wrapper,
#log-wrapper {
display:block;
+ flex-grow: 0.25;
+ align-self: stretch;
+ overflow: auto;
+}
+
+#video-capture-capabilities-wrapper {
flex-grow: 0.5;
align-self: stretch;
overflow: auto;
@@ -114,4 +121,39 @@ h3 {
.timestamp {
min-width: 115px;
-} \ No newline at end of file
+}
+
+#video-capture-capabilities-table {
+ margin-bottom:30px;
+}
+
+#video-capture-capabilities-table th,
+#video-capture-capabilities-table td {
+ min-width:120px;
+}
+
+#video-capture-capabilities-table td {
+ padding:5px;
+}
+
+#video-capture-capabilities-table tr td {
+ font-size:13px;
+ text-align:center;
+}
+
+#video-capture-capabilities-table .video-capture-formats-table th,
+#video-capture-capabilities-table .video-capture-formats-table td {
+ text-align:right;
+ min-width:80px;
+}
+
+#video-capture-capabilities-table .video-capture-formats-table th {
+ background:none;
+ color:#666;
+ font-size:13px;
+ font-weight:bold;
+}
+
+#video-capture-capabilities-table .video-capture-formats-table td {
+ padding:2px;
+}
diff --git a/chromium/content/browser/resources/media/media_internals.html b/chromium/content/browser/resources/media/media_internals.html
index 1f762305598..d271082d2da 100644
--- a/chromium/content/browser/resources/media/media_internals.html
+++ b/chromium/content/browser/resources/media/media_internals.html
@@ -36,7 +36,7 @@ found in the LICENSE file.
<div id="property-wrapper">
<h2>
<span id="property-name"></span> Properties
- <button id="copy-button">copy to clipboard</button>
+ <button id="copy-button">Copy to clipboard</button>
</h2>
<table id="property-table">
<thead>
@@ -64,6 +64,24 @@ found in the LICENSE file.
<tbody></tbody>
</table>
</div>
+ <div id="video-capture-capabilities-wrapper">
+ <h2>Video Capture Device Capabilities</h2>
+ <button id="video-capture-capabilities-copy-button">
+ Copy to clipboard</button>
+ <table id="video-capture-capabilities-table">
+ <thead>
+ <tr>
+ <th>Device Name</th>
+ <th>Formats</th>
+ <th>Capture API</th>
+ <th>Device ID</th>
+ </tr>
+ </thead>
+ <tbody id="video-capture-capabilities-tbody">
+
+ <tbody>
+ </table>
+ </div>
</div>
<script src="media_internals.js"></script>
</body>
diff --git a/chromium/content/browser/resources/media/peer_connection_update_table.js b/chromium/content/browser/resources/media/peer_connection_update_table.js
index 0f4cc0cde90..f5e58b5be0c 100644
--- a/chromium/content/browser/resources/media/peer_connection_update_table.js
+++ b/chromium/content/browser/resources/media/peer_connection_update_table.js
@@ -81,7 +81,8 @@ var PeerConnectionUpdateTable = (function() {
var row = document.createElement('tr');
tableElement.firstChild.appendChild(row);
- row.innerHTML = '<td>' + (new Date()).toLocaleString() + '</td>';
+ var time = new Date(parseFloat(update.time));
+ row.innerHTML = '<td>' + time.toLocaleString() + '</td>';
if (update.value.length == 0) {
row.innerHTML += '<td>' + update.type + '</td>';
diff --git a/chromium/content/browser/resources/media/stats_table.js b/chromium/content/browser/resources/media/stats_table.js
index 418be756c65..07b5687fb33 100644
--- a/chromium/content/browser/resources/media/stats_table.js
+++ b/chromium/content/browser/resources/media/stats_table.js
@@ -114,7 +114,7 @@ var StatsTable = (function(ssrcInfoManager) {
* @private
*/
addStatsToTable_: function(statsTable, time, statsData) {
- var date = Date(time);
+ var date = new Date(time);
this.updateStatsTableRow_(statsTable, 'timestamp', date.toLocaleString());
for (var i = 0; i < statsData.length - 1; i = i + 2) {
this.updateStatsTableRow_(statsTable, statsData[i], statsData[i + 1]);
diff --git a/chromium/content/browser/resources/media/tab_view.js b/chromium/content/browser/resources/media/tab_view.js
index 6fc8d73410d..274336ee465 100644
--- a/chromium/content/browser/resources/media/tab_view.js
+++ b/chromium/content/browser/resources/media/tab_view.js
@@ -50,9 +50,9 @@ var TabView = (function() {
if (this.tabElements_[id])
throw 'Tab already exists: ' + id;
- var head = document.createElement('div');
+ var head = document.createElement('span');
head.className = this.TAB_HEAD_CLASS_;
- head.textContent = title + ' [' + id + ']';
+ head.textContent = title;
head.title = title;
this.headBar_.appendChild(head);
head.addEventListener('click', this.switchTab_.bind(this, id));
diff --git a/chromium/content/browser/resources/media/webrtc_internals.css b/chromium/content/browser/resources/media/webrtc_internals.css
index cc976ebd931..e98d3995e98 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.css
+++ b/chromium/content/browser/resources/media/webrtc_internals.css
@@ -88,8 +88,9 @@ th {
text-decoration: underline;
cursor: pointer;
display: inline-block;
- word-break: break-all;
+ overflow: hidden;
width: 20em;
+ height: 3em;
}
.active-tab-head {
@@ -107,3 +108,12 @@ th {
.active-tab-body {
display: block;
}
+
+.user-media-request-div-class {
+ background-color: lightgray;
+ margin: 10px 0 10px 0;
+}
+
+.user-media-request-div-class > div {
+ margin: 5px 0 5px 0;
+}
diff --git a/chromium/content/browser/resources/media/webrtc_internals.js b/chromium/content/browser/resources/media/webrtc_internals.js
index 52ab9f711f4..3a1f9cd25c1 100644
--- a/chromium/content/browser/resources/media/webrtc_internals.js
+++ b/chromium/content/browser/resources/media/webrtc_internals.js
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+var USER_MEDIA_TAB_ID = 'user-media-tab-id';
+
var tabView = null;
var ssrcInfoManager = null;
var peerConnectionUpdateTable = null;
@@ -19,7 +21,7 @@ var PeerConnectionRecord = (function() {
/** @private */
this.record_ = {
constraints: {},
- servers: [],
+ rtcConfiguration: [],
stats: {},
updateLog: [],
url: '',
@@ -35,12 +37,12 @@ var PeerConnectionRecord = (function() {
/**
* Adds the initilization info of the peer connection.
* @param {string} url The URL of the web page owning the peer connection.
- * @param {Array} servers STUN servers used by the peer connection.
+ * @param {Array} rtcConfiguration
* @param {!Object} constraints Media constraints.
*/
- initialize: function(url, servers, constraints) {
+ initialize: function(url, rtcConfiguration, constraints) {
this.record_.url = url;
- this.record_.servers = servers;
+ this.record_.rtcConfiguration = rtcConfiguration;
this.record_.constraints = constraints;
},
@@ -61,14 +63,15 @@ var PeerConnectionRecord = (function() {
},
/**
- * @param {string} type The type of the update.
- * @param {string} value The value of the update.
+ * @param {!Object} update The object contains keys "time", "type", and
+ * "value".
*/
- addUpdate: function(type, value) {
+ addUpdate: function(update) {
+ var time = new Date(parseFloat(update.time));
this.record_.updateLog.push({
- time: (new Date()).toLocaleString(),
- type: type,
- value: value,
+ time: time.toLocaleString(),
+ type: update.type,
+ value: update.value,
});
},
};
@@ -137,6 +140,21 @@ function extractSsrcInfo(data) {
/**
+ * A helper function for appending a child element to |parent|.
+ *
+ * @param {!Element} parent The parent element.
+ * @param {string} tag The child element tag.
+ * @param {string} text The textContent of the new DIV.
+ * @return {!Element} the new DIV element.
+ */
+function appendChildWithText(parent, tag, text) {
+ var child = document.createElement(tag);
+ child.textContent = text;
+ parent.appendChild(child);
+ return child;
+}
+
+/**
* Helper for adding a peer connection update.
*
* @param {Element} peerConnectionElement
@@ -146,8 +164,7 @@ function addPeerConnectionUpdate(peerConnectionElement, update) {
peerConnectionUpdateTable.addPeerConnectionUpdate(peerConnectionElement,
update);
extractSsrcInfo(update);
- peerConnectionDataStore[peerConnectionElement.id].addUpdate(
- update.type, update.value);
+ peerConnectionDataStore[peerConnectionElement.id].addUpdate(update);
}
@@ -172,8 +189,8 @@ function removePeerConnection(data) {
/**
* Adds a peer connection.
*
- * @param {!Object} data The object containing the pid, lid, url, servers, and
- * constraints of a peer connection.
+ * @param {!Object} data The object containing the pid, lid, url,
+ * rtcConfiguration, and constraints of a peer connection.
*/
function addPeerConnection(data) {
var id = getPeerConnectionId(data);
@@ -182,14 +199,14 @@ function addPeerConnection(data) {
peerConnectionDataStore[id] = new PeerConnectionRecord();
}
peerConnectionDataStore[id].initialize(
- data.url, data.servers, data.constraints);
+ data.url, data.rtcConfiguration, data.constraints);
var peerConnectionElement = $(id);
if (!peerConnectionElement) {
- peerConnectionElement = tabView.addTab(id, data.url);
+ peerConnectionElement = tabView.addTab(id, data.url + ' [' + id + ']');
}
peerConnectionElement.innerHTML =
- '<p>' + data.url + ' ' + data.servers + ' ' + data.constraints +
+ '<p>' + data.url + ' ' + data.rtcConfiguration + ' ' + data.constraints +
'</p>';
return peerConnectionElement;
@@ -211,7 +228,7 @@ function updatePeerConnection(data) {
* Adds the information of all peer connections created so far.
*
* @param {Array.<!Object>} data An array of the information of all peer
- * connections. Each array item contains pid, lid, url, servers,
+ * connections. Each array item contains pid, lid, url, rtcConfiguration,
* constraints, and an array of updates as the log.
*/
function updateAllPeerConnections(data) {
@@ -258,8 +275,26 @@ function addStats(data) {
* origin {string}, audio {string}, video {string}.
*/
function addGetUserMedia(data) {
- // TODO(jiayl): add the getUserMedia info to the tabbed UI.
userMediaRequests.push(data);
+
+ if (!$(USER_MEDIA_TAB_ID)) {
+ tabView.addTab(USER_MEDIA_TAB_ID, 'GetUserMedia Requests');
+ }
+
+ var requestDiv = document.createElement('div');
+ requestDiv.className = 'user-media-request-div-class';
+ requestDiv.rid = data.rid;
+ $(USER_MEDIA_TAB_ID).appendChild(requestDiv);
+
+ appendChildWithText(requestDiv, 'div', 'Caller origin: ' + data.origin);
+ appendChildWithText(requestDiv, 'div', 'Caller process id: ' + data.pid);
+ appendChildWithText(requestDiv, 'span', 'Audio Constraints').style.fontWeight
+ = 'bold';
+ appendChildWithText(requestDiv, 'div', data.audio);
+
+ appendChildWithText(requestDiv, 'span', 'Video Constraints').style.fontWeight
+ = 'bold';
+ appendChildWithText(requestDiv, 'div', data.video);
}
@@ -269,11 +304,19 @@ function addGetUserMedia(data) {
* @param {!Object} data The object containing rid {number}, the render id.
*/
function removeGetUserMediaForRenderer(data) {
- // TODO(jiayl): remove the getUserMedia info from the tabbed UI.
for (var i = userMediaRequests.length - 1; i >= 0; --i) {
if (userMediaRequests[i].rid == data.rid)
userMediaRequests.splice(i, 1);
}
+
+ var requests = $(USER_MEDIA_TAB_ID).childNodes;
+ for (var i = 0; i < requests.length; ++i) {
+ if (requests[i].rid == data.rid)
+ $(USER_MEDIA_TAB_ID).removeChild(requests[i]);
+
+ }
+ if ($(USER_MEDIA_TAB_ID).childNodes.length == 0)
+ tabView.removeTab(USER_MEDIA_TAB_ID);
}
diff --git a/chromium/content/browser/resources/service_worker/OWNERS b/chromium/content/browser/resources/service_worker/OWNERS
index a143cc76541..df9c7767103 100644
--- a/chromium/content/browser/resources/service_worker/OWNERS
+++ b/chromium/content/browser/resources/service_worker/OWNERS
@@ -1,5 +1,7 @@
michaeln@chromium.org
horo@chromium.org
+falken@chromium.org
+nhiroki@chromium.org
# may not be available
kinuko@chromium.org
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.css b/chromium/content/browser/resources/service_worker/serviceworker_internals.css
index 0ac2528098c..760c993ab16 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.css
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.css
@@ -24,12 +24,9 @@
.serviceworker-scope {
color: rgb(85, 102, 221);
display: inline-block;
- max-width: 500px;
- overflow: hidden;
padding-bottom: 1px;
padding-top: 4px;
text-decoration: none;
- text-overflow: ellipsis;
white-space: nowrap;
}
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.html b/chromium/content/browser/resources/service_worker/serviceworker_internals.html
index 85e70454664..8c4e6afbd58 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.html
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!DOCTYPE html>
<html i18n-values="dir:textdirection;">
<head>
<meta charset="utf-8">
@@ -19,6 +19,10 @@
<span>Running Status:</span>
<span jscontent="$this.running_status"></span>
</div>
+ <div class="serviceworker-script_url">
+ <span>Script:</span>
+ <span jscontent="$this.script_url"></span>
+ </div>
<div class="serviceworker-vid">
<span>Version ID:</span>
<span jscontent="$this.version_id"></span>
@@ -63,10 +67,6 @@
<span>Scope:</span>
<span jscontent="scope"></span>
</div>
- <div class="serviceworker-script_url">
- <span>Script:</span>
- <span jscontent="script_url"></span>
- </div>
<div class="serviceworker-rid">
<span>Registration ID:</span>
<span jscontent="registration_id"></span>
@@ -97,8 +97,13 @@
jsvalues="$partition_id:$this.partition_id;.partition_id:$this.partition_id"
jsdisplay="$this.stored_registrations.length + $this.unregistered_registrations.length + $this.unregistered_versions.length > 0">
<div class="serviceworker-summary">
- <span>Registrations in: </span>
- <span jscontent="$this.partition_path"></span>
+ <span jsdisplay="$this.partition_path">
+ <span>Registrations in: </span>
+ <span jscontent="$this.partition_path"></span>
+ </span>
+ <span jsdisplay="!$this.partition_path">
+ <span>Registrations: Incognito </span>
+ </span>
<span jscontent="'(' + $this.stored_registrations.length + ')'"></span>
</div>
<div class="serviceworker-item" jsselect="$this.stored_registrations">
@@ -115,13 +120,15 @@
</div>
<div id="serviceworker-options-template">
<div>
- <span>
- <input type="checkbox" class="debug_on_start"
- jsvalues=".checked:$this.debug_on_start">
- </span>
- <span>
- Opens the DevTools window for ServiceWorker on start for debugging.
- </span>
+ <label>
+ <span>
+ <input type="checkbox" class="debug_on_start"
+ jsvalues=".checked:$this.debug_on_start">
+ </span>
+ <span>
+ Opens the DevTools window for ServiceWorker on start for debugging.
+ </span>
+ </label>
</div>
</div>
</div>
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.js b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
index 5e698b80d5c..93bf437fbc5 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.js
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
@@ -6,20 +6,9 @@ cr.define('serviceworker', function() {
'use strict';
function initialize() {
- if (window.location.hash == "#iframe") {
- // This page is loaded from chrome://inspect.
- window.addEventListener('message', onMessage.bind(this), false);
- }
update();
}
- function onMessage(event) {
- if (event.origin != 'chrome://inspect') {
- return;
- }
- sendCommand(event.data.action, event.data.worker);
- }
-
function update() {
chrome.send('GetOptions');
chrome.send('getAllRegistrations');
@@ -85,34 +74,9 @@ cr.define('serviceworker', function() {
update();
}
- // Send the active ServiceWorker information to chrome://inspect.
- function sendToInspectPage(live_registrations,
- partition_id) {
- var workers = [];
- live_registrations.forEach(function(registration) {
- [registration.active, registration.waiting].forEach(function(version) {
- if (!version || version.running_status != 'RUNNING') {
- return;
- }
- workers.push({
- 'scope': registration.scope,
- 'url': registration.script_url,
- 'partition_id': partition_id,
- 'version_id': version.version_id,
- 'process_id': version.process_id,
- 'devtools_agent_route_id':
- version.devtools_agent_route_id
- });
- });
- });
- window.parent.postMessage(
- {'partition_id': partition_id, 'workers': workers},
- 'chrome://inspect');
- }
-
var allLogMessages = {};
// Set log for a worker version.
- function fillLogForVersion(partition_id, version) {
+ function fillLogForVersion(container, partition_id, version) {
if (!version) {
return;
}
@@ -125,6 +89,14 @@ cr.define('serviceworker', function() {
} else {
version.log = '';
}
+ var logAreas = container.querySelectorAll('textarea.serviceworker-log');
+ for (var i = 0; i < logAreas.length; ++i) {
+ var logArea = logAreas[i];
+ if (logArea.partition_id == partition_id &&
+ logArea.version_id == version.version_id) {
+ logArea.value = version.log;
+ }
+ }
}
// Get the unregistered workers.
@@ -171,11 +143,6 @@ cr.define('serviceworker', function() {
stored_registrations,
partition_id,
partition_path) {
- if (window.location.hash == "#iframe") {
- // This page is loaded from chrome://inspect.
- sendToInspectPage(live_registrations, partition_id);
- return;
- }
var unregistered_registrations = [];
var unregistered_versions = [];
getUnregisteredWorkers(stored_registrations,
@@ -198,7 +165,7 @@ cr.define('serviceworker', function() {
template = jstGetTemplate('serviceworker-list-template');
container.appendChild(template);
}
- var fillLogFunc = fillLogForVersion.bind(this, partition_id);
+ var fillLogFunc = fillLogForVersion.bind(this, container, partition_id);
stored_registrations.forEach(function(registration) {
[registration.active, registration.waiting].forEach(fillLogFunc);
});
@@ -280,7 +247,7 @@ cr.define('serviceworker', function() {
for (var i = 0; i < logAreas.length; ++i) {
var logArea = logAreas[i];
if (logArea.partition_id == partition_id &&
- logArea.version_id == version_id) {
+ logArea.version_id == version_id) {
logArea.value += message;
}
}
diff --git a/chromium/content/browser/safe_util_win.cc b/chromium/content/browser/safe_util_win.cc
index e5843fd2bca..2a1f18c7679 100644
--- a/chromium/content/browser/safe_util_win.cc
+++ b/chromium/content/browser/safe_util_win.cc
@@ -9,7 +9,6 @@
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_comptr.h"
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
new file mode 100644
index 00000000000..33b026cf5bb
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -0,0 +1,239 @@
+// Copyright 2014 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 <stdlib.h>
+
+#include "base/command_line.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/common/shell_switches.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+#include "ui/compositor/compositor_switches.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif // OS_WIN
+
+namespace content {
+
+class ScreenOrientationBrowserTest : public ContentBrowserTest {
+ public:
+ ScreenOrientationBrowserTest() {
+ }
+
+ void SetUp() override {
+ // Painting has to happen otherwise the Resize messages will be added on top
+ // of each other without properly ack-painting which will fail and crash.
+ UseSoftwareCompositing();
+
+ ContentBrowserTest::SetUp();
+ }
+
+ protected:
+ void SendFakeScreenOrientation(unsigned angle, const std::string& strType) {
+ RenderWidgetHost* rwh = shell()->web_contents()->GetRenderWidgetHostView()
+ ->GetRenderWidgetHost();
+ blink::WebScreenInfo screen_info;
+ rwh->GetWebScreenInfo(&screen_info);
+ screen_info.orientationAngle = angle;
+
+ blink::WebScreenOrientationType type = blink::WebScreenOrientationUndefined;
+ if (strType == "portrait-primary") {
+ type = blink::WebScreenOrientationPortraitPrimary;
+ } else if (strType == "portrait-secondary") {
+ type = blink::WebScreenOrientationPortraitSecondary;
+ } else if (strType == "landscape-primary") {
+ type = blink::WebScreenOrientationLandscapePrimary;
+ } else if (strType == "landscape-secondary") {
+ type = blink::WebScreenOrientationLandscapeSecondary;
+ }
+ ASSERT_NE(blink::WebScreenOrientationUndefined, type);
+ screen_info.orientationType = type;
+
+ ViewMsg_Resize_Params params;
+ params.screen_info = screen_info;
+ params.new_size = gfx::Size(0, 0);
+ params.physical_backing_size = gfx::Size(300, 300);
+ params.top_controls_layout_height = 0.f;
+ params.resizer_rect = gfx::Rect();
+ params.is_fullscreen = false;
+ rwh->Send(new ViewMsg_Resize(rwh->GetRoutingID(), params));
+ }
+
+ int GetOrientationAngle() {
+ int angle;
+ ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
+ "screen.orientation.angle")->GetAsInteger(&angle);
+ return angle;
+ }
+
+ std::string GetOrientationType() {
+ std::string type;
+ ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
+ "screen.orientation.type")->GetAsString(&type);
+ return type;
+ }
+
+ bool ScreenOrientationSupported() {
+ bool support;
+ ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
+ "'orientation' in screen")->GetAsBoolean(&support);
+ return support;
+ }
+
+ bool WindowOrientationSupported() {
+ bool support;
+ ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
+ "'orientation' in window")->GetAsBoolean(&support);
+ return support;
+ }
+
+ int GetWindowOrientationAngle() {
+ int angle;
+ ExecuteScriptAndGetValue(shell()->web_contents()->GetMainFrame(),
+ "window.orientation")->GetAsInteger(&angle);
+ return angle;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationBrowserTest);
+};
+
+// This test doesn't work on MacOS X but the reason is mostly because it is not
+// used Aura. It could be set as !defined(OS_MACOSX) but the rule below will
+// actually support MacOS X if and when it switches to Aura.
+#if defined(USE_AURA) || defined(OS_ANDROID)
+IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, ScreenOrientationChange) {
+ std::string types[] = { "portrait-primary",
+ "portrait-secondary",
+ "landscape-primary",
+ "landscape-secondary" };
+ GURL test_url = GetTestUrl("screen_orientation",
+ "screen_orientation_screenorientationchange.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+#if USE_AURA
+ WaitForResizeComplete(shell()->web_contents());
+#endif // USE_AURA
+
+#if defined(OS_WIN)
+ // Screen Orientation is currently disabled on Windows 8.
+ // This test will break, requiring an update when the API will be enabled.
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_WIN8) {
+ EXPECT_EQ(false, ScreenOrientationSupported());
+ return;
+ }
+#endif // defined(OS_WIN)
+
+ int angle = GetOrientationAngle();
+
+ for (int i = 0; i < 4; ++i) {
+ angle = (angle + 90) % 360;
+ SendFakeScreenOrientation(angle, types[i]);
+
+ TestNavigationObserver navigation_observer(shell()->web_contents());
+ navigation_observer.Wait();
+ EXPECT_EQ(angle, GetOrientationAngle());
+ EXPECT_EQ(types[i], GetOrientationType());
+ }
+}
+#endif // defined(USE_AURA) || defined(OS_ANDROID)
+
+IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, WindowOrientationChange) {
+ GURL test_url = GetTestUrl("screen_orientation",
+ "screen_orientation_windoworientationchange.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(test_url);
+ navigation_observer.Wait();
+#if USE_AURA
+ WaitForResizeComplete(shell()->web_contents());
+#endif // USE_AURA
+
+ if (!WindowOrientationSupported())
+ return;
+
+ int angle = GetWindowOrientationAngle();
+
+ for (int i = 0; i < 4; ++i) {
+ angle = (angle + 90) % 360;
+ SendFakeScreenOrientation(angle, "portrait-primary");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ navigation_observer.Wait();
+ EXPECT_EQ(angle == 270 ? -90 : angle, GetWindowOrientationAngle());
+ }
+}
+
+// Chromium Android does not support fullscreen
+IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, LockSmoke) {
+ GURL test_url = GetTestUrl("screen_orientation",
+ "screen_orientation_lock_smoke.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+ shell()->LoadURL(test_url);
+
+#if defined(OS_WIN)
+ // Screen Orientation is currently disabled on Windows 8.
+ // This test will break, requiring an update when the API will be enabled.
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_WIN8) {
+ EXPECT_EQ(false, ScreenOrientationSupported());
+ return;
+ }
+#endif // defined(OS_WIN)
+
+ navigation_observer.Wait();
+#if USE_AURA
+ WaitForResizeComplete(shell()->web_contents());
+#endif // USE_AURA
+
+ std::string expected =
+#if defined(OS_ANDROID)
+ "SecurityError"; // WebContents need to be fullscreen.
+#else
+ "NotSupportedError"; // Locking isn't supported.
+#endif
+
+ EXPECT_EQ(expected, shell()->web_contents()->GetLastCommittedURL().ref());
+}
+
+// Check that using screen orientation after a frame is detached doesn't crash
+// the renderer process.
+// This could be a LayoutTest if they were not using a mock screen orientation
+// controller.
+IN_PROC_BROWSER_TEST_F(ScreenOrientationBrowserTest, CrashTest_UseAfterDetach) {
+ GURL test_url = GetTestUrl("screen_orientation",
+ "screen_orientation_use_after_detach.html");
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+ shell()->LoadURL(test_url);
+
+#if defined(OS_WIN)
+ // Screen Orientation is currently disabled on Windows 8.
+ // When implemented, this test will break, requiring an update.
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_WIN8) {
+ EXPECT_EQ(false, ScreenOrientationSupported());
+ return;
+ }
+#endif // defined(OS_WIN)
+
+ navigation_observer.Wait();
+
+ // This is a success if the renderer process did not crash, thus, we end up
+ // here.
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
new file mode 100644
index 00000000000..bb2f5bc61f9
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 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 "content/browser/screen_orientation/screen_orientation_delegate_android.h"
+
+#include "content/browser/android/content_view_core_impl.h"
+#include "jni/ScreenOrientationProvider_jni.h"
+
+namespace content {
+
+ScreenOrientationDelegateAndroid::ScreenOrientationDelegateAndroid() {
+}
+
+ScreenOrientationDelegateAndroid::~ScreenOrientationDelegateAndroid() {
+}
+
+// static
+bool ScreenOrientationDelegateAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+// static
+void ScreenOrientationDelegateAndroid::StartAccurateListening() {
+ Java_ScreenOrientationProvider_startAccurateListening(
+ base::android::AttachCurrentThread());
+}
+
+// static
+void ScreenOrientationDelegateAndroid::StopAccurateListening() {
+ Java_ScreenOrientationProvider_stopAccurateListening(
+ base::android::AttachCurrentThread());
+}
+
+bool ScreenOrientationDelegateAndroid::FullScreenRequired(
+ WebContents* web_contents) {
+ ContentViewCoreImpl* cvc =
+ ContentViewCoreImpl::FromWebContents(web_contents);
+ bool fullscreen_required = cvc ? cvc->IsFullscreenRequiredForOrientationLock()
+ : true;
+ return fullscreen_required;
+}
+
+void ScreenOrientationDelegateAndroid::Lock(
+ blink::WebScreenOrientationLockType lock_orientation) {
+ Java_ScreenOrientationProvider_lockOrientation(
+ base::android::AttachCurrentThread(), lock_orientation);
+}
+
+bool ScreenOrientationDelegateAndroid::ScreenOrientationProviderSupported() {
+ // Always supported on Android
+ return true;
+}
+
+void ScreenOrientationDelegateAndroid::Unlock() {
+ Java_ScreenOrientationProvider_unlockOrientation(
+ base::android::AttachCurrentThread());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h
new file mode 100644
index 00000000000..fa3ee6e2211
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_android.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DELEGATE_H_
+#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DELEGATE_H_
+
+#include <jni.h>
+
+#include "base/macros.h"
+#include "content/public/browser/screen_orientation_delegate.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+
+namespace content {
+
+class WebContents;
+
+// Android implementation of ScreenOrientationDelegate. The functionality of
+// ScreenOrientationProvider is always supported.
+class ScreenOrientationDelegateAndroid : public ScreenOrientationDelegate {
+ public:
+ ScreenOrientationDelegateAndroid();
+ virtual ~ScreenOrientationDelegateAndroid();
+
+ static bool Register(JNIEnv* env);
+
+ // Ask the ScreenOrientationListener (Java) to start accurately listening to
+ // the screen orientation. It keep track of the number of start request if it
+ // is already running an accurate listening.
+ static void StartAccurateListening();
+
+ // Ask the ScreenOrientationListener (Java) to stop accurately listening to
+ // the screen orientation. It will actually stop only if the number of stop
+ // requests matches the number of start requests.
+ static void StopAccurateListening();
+
+ // ScreenOrientationDelegate:
+ virtual bool FullScreenRequired(WebContents* web_contents) override;
+ virtual void Lock(
+ blink::WebScreenOrientationLockType lock_orientation) override;
+ virtual bool ScreenOrientationProviderSupported() override;
+ virtual void Unlock() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegateAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DELEGATE_H_
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc b/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc
deleted file mode 100644
index 67174d028ea..00000000000
--- a/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2014 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 "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
-
-#include "content/browser/screen_orientation/screen_orientation_provider.h"
-#include "content/common/screen_orientation_messages.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/web_contents.h"
-
-namespace content {
-
-ScreenOrientationDispatcherHost::ScreenOrientationDispatcherHost(
- WebContents* web_contents)
- : WebContentsObserver(web_contents) {
- if (!provider_.get())
- provider_.reset(CreateProvider());
-}
-
-ScreenOrientationDispatcherHost::~ScreenOrientationDispatcherHost() {
-}
-
-bool ScreenOrientationDispatcherHost::OnMessageReceived(
- const IPC::Message& message,
- RenderFrameHost* render_frame_host) {
- bool handled = true;
-
- IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ScreenOrientationDispatcherHost, message,
- render_frame_host)
- IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_LockRequest, OnLockRequest)
- IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_Unlock, OnUnlockRequest)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void ScreenOrientationDispatcherHost::OnOrientationChange(
- blink::WebScreenOrientationType orientation) {
- Send(new ScreenOrientationMsg_OrientationChange(orientation));
-}
-
-void ScreenOrientationDispatcherHost::SetProviderForTests(
- ScreenOrientationProvider* provider) {
- provider_.reset(provider);
-}
-
-void ScreenOrientationDispatcherHost::OnLockRequest(
- RenderFrameHost* render_frame_host,
- blink::WebScreenOrientationLockType orientation,
- int request_id) {
- if (!provider_) {
- render_frame_host->Send(new ScreenOrientationMsg_LockError(
- render_frame_host->GetRoutingID(),
- request_id,
- blink::WebLockOrientationCallback::ErrorTypeNotAvailable));
- return;
- }
-
- // TODO(mlamouri): pass real values.
- render_frame_host->Send(new ScreenOrientationMsg_LockSuccess(
- render_frame_host->GetRoutingID(),
- request_id,
- 0,
- blink::WebScreenOrientationPortraitPrimary));
- provider_->LockOrientation(orientation);
-}
-
-void ScreenOrientationDispatcherHost::OnUnlockRequest(
- RenderFrameHost* render_frame_host) {
- if (!provider_.get())
- return;
-
- provider_->UnlockOrientation();
-}
-
-#if !defined(OS_ANDROID)
-// static
-ScreenOrientationProvider* ScreenOrientationDispatcherHost::CreateProvider() {
- return NULL;
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.h b/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.h
deleted file mode 100644
index c86854a83ad..00000000000
--- a/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_HOST_H_
-#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_HOST_H_
-
-#include "content/public/browser/web_contents_observer.h"
-#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
-#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
-
-namespace content {
-
-class RenderFrameHost;
-class ScreenOrientationProvider;
-class WebContents;
-
-// ScreenOrientationDispatcherHost receives lock and unlock requests from the
-// RenderFrames and dispatch them to the ScreenOrientationProvider. It also
-// make sure that the right RenderFrame get replied for each lock request.
-class CONTENT_EXPORT ScreenOrientationDispatcherHost
- : public WebContentsObserver {
- public:
- explicit ScreenOrientationDispatcherHost(WebContents* web_contents);
- virtual ~ScreenOrientationDispatcherHost();
-
- // WebContentsObserver
- virtual bool OnMessageReceived(const IPC::Message&,
- RenderFrameHost* render_frame_host) OVERRIDE;
-
- void OnOrientationChange(blink::WebScreenOrientationType orientation);
-
- void SetProviderForTests(ScreenOrientationProvider* provider);
-
- private:
- void OnLockRequest(RenderFrameHost* render_frame_host,
- blink::WebScreenOrientationLockType orientation,
- int request_id);
- void OnUnlockRequest(RenderFrameHost* render_frame_host);
-
- static ScreenOrientationProvider* CreateProvider();
-
- scoped_ptr<ScreenOrientationProvider> provider_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDispatcherHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc b/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc
new file mode 100644
index 00000000000..1e5240d9b97
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc
@@ -0,0 +1,146 @@
+// Copyright 2014 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 "content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h"
+
+#include "content/common/screen_orientation_messages.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/screen_orientation_provider.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+
+namespace content {
+
+ScreenOrientationDispatcherHostImpl::LockInformation::LockInformation(
+ int request_id, int process_id, int routing_id)
+ : request_id(request_id),
+ process_id(process_id),
+ routing_id(routing_id) {
+}
+
+ScreenOrientationDispatcherHostImpl::ScreenOrientationDispatcherHostImpl(
+ WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ current_lock_(NULL) {
+ provider_.reset(new ScreenOrientationProvider(this, web_contents));
+}
+
+ScreenOrientationDispatcherHostImpl::~ScreenOrientationDispatcherHostImpl() {
+ ResetCurrentLock();
+}
+
+void ScreenOrientationDispatcherHostImpl::ResetCurrentLock() {
+ if (current_lock_) {
+ delete current_lock_;
+ current_lock_ = 0;
+ }
+}
+
+bool ScreenOrientationDispatcherHostImpl::OnMessageReceived(
+ const IPC::Message& message,
+ RenderFrameHost* render_frame_host) {
+ bool handled = true;
+
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(ScreenOrientationDispatcherHostImpl, message,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_LockRequest, OnLockRequest)
+ IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_Unlock, OnUnlockRequest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void ScreenOrientationDispatcherHostImpl::DidNavigateMainFrame(
+ const LoadCommittedDetails& details, const FrameNavigateParams& params) {
+ if (!provider_ || details.is_in_page)
+ return;
+ provider_->UnlockOrientation();
+}
+
+RenderFrameHost*
+ScreenOrientationDispatcherHostImpl::GetRenderFrameHostForRequestID(
+ int request_id) {
+ if (!current_lock_ || current_lock_->request_id != request_id)
+ return NULL;
+
+ return RenderFrameHost::FromID(current_lock_->process_id,
+ current_lock_->routing_id);
+}
+
+void ScreenOrientationDispatcherHostImpl::NotifyLockSuccess(int request_id) {
+ RenderFrameHost* render_frame_host =
+ GetRenderFrameHostForRequestID(request_id);
+ if (!render_frame_host)
+ return;
+
+ render_frame_host->Send(new ScreenOrientationMsg_LockSuccess(
+ render_frame_host->GetRoutingID(), request_id));
+ ResetCurrentLock();
+}
+
+void ScreenOrientationDispatcherHostImpl::NotifyLockError(
+ int request_id, blink::WebLockOrientationError error) {
+ RenderFrameHost* render_frame_host =
+ GetRenderFrameHostForRequestID(request_id);
+ if (!render_frame_host)
+ return;
+
+ NotifyLockError(request_id, render_frame_host, error);
+}
+
+void ScreenOrientationDispatcherHostImpl::NotifyLockError(
+ int request_id,
+ RenderFrameHost* render_frame_host,
+ blink::WebLockOrientationError error) {
+ render_frame_host->Send(new ScreenOrientationMsg_LockError(
+ render_frame_host->GetRoutingID(), request_id, error));
+ ResetCurrentLock();
+}
+
+void ScreenOrientationDispatcherHostImpl::OnOrientationChange() {
+ if (provider_)
+ provider_->OnOrientationChange();
+}
+
+void ScreenOrientationDispatcherHostImpl::OnLockRequest(
+ RenderFrameHost* render_frame_host,
+ blink::WebScreenOrientationLockType orientation,
+ int request_id) {
+ if (current_lock_) {
+ NotifyLockError(current_lock_->request_id, render_frame_host,
+ blink::WebLockOrientationErrorCanceled);
+ }
+
+ if (!provider_) {
+ NotifyLockError(request_id, render_frame_host,
+ blink::WebLockOrientationErrorNotAvailable);
+ return;
+ }
+
+ current_lock_ = new LockInformation(request_id,
+ render_frame_host->GetProcess()->GetID(),
+ render_frame_host->GetRoutingID());
+
+ provider_->LockOrientation(request_id, orientation);
+}
+
+void ScreenOrientationDispatcherHostImpl::OnUnlockRequest(
+ RenderFrameHost* render_frame_host) {
+ if (current_lock_) {
+ NotifyLockError(current_lock_->request_id, render_frame_host,
+ blink::WebLockOrientationErrorCanceled);
+ }
+
+ if (!provider_)
+ return;
+
+ provider_->UnlockOrientation();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h b/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h
new file mode 100644
index 00000000000..a8840837883
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h
@@ -0,0 +1,72 @@
+// Copyright 2014 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 CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_HOST_IMPL_H_
+#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_HOST_IMPL_H_
+
+#include "content/public/browser/screen_orientation_dispatcher_host.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationError.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+
+namespace content {
+
+class RenderFrameHost;
+class ScreenOrientationProvider;
+class WebContents;
+
+// ScreenOrientationDispatcherHost receives lock and unlock requests from the
+// RenderFrames and dispatch them to the ScreenOrientationProvider. It also
+// make sure that the right RenderFrame get replied for each lock request.
+class CONTENT_EXPORT ScreenOrientationDispatcherHostImpl
+ : public ScreenOrientationDispatcherHost,
+ public WebContentsObserver {
+ public:
+ explicit ScreenOrientationDispatcherHostImpl(WebContents* web_contents);
+ ~ScreenOrientationDispatcherHostImpl() override;
+
+ // ScreenOrientationDispatcherHost:
+ void NotifyLockSuccess(int request_id) override;
+ void NotifyLockError(int request_id,
+ blink::WebLockOrientationError error) override;
+ void OnOrientationChange() override;
+
+ // WebContentsObserver:
+ bool OnMessageReceived(const IPC::Message&,
+ RenderFrameHost* render_frame_host) override;
+ void DidNavigateMainFrame(const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override;
+
+ private:
+ void OnLockRequest(RenderFrameHost* render_frame_host,
+ blink::WebScreenOrientationLockType orientation,
+ int request_id);
+ void OnUnlockRequest(RenderFrameHost* render_frame_host);
+
+ // Returns a RenderFrameHost if the request_id is still valid and the
+ // associated RenderFrameHost still exists. Returns NULL otherwise.
+ RenderFrameHost* GetRenderFrameHostForRequestID(int request_id);
+
+ void ResetCurrentLock();
+ void NotifyLockError(int request_id,
+ RenderFrameHost* render_frame_host,
+ blink::WebLockOrientationError error);
+
+ scoped_ptr<ScreenOrientationProvider> provider_;
+
+ struct LockInformation {
+ LockInformation(int request_id, int process_id, int routing_id);
+ int request_id;
+ int process_id;
+ int routing_id;
+ };
+ // current_lock_ will be NULL if there are no current lock.
+ LockInformation* current_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDispatcherHostImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DISPATCHER_HOST_IMPL_H_
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.cc b/chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.cc
new file mode 100644
index 00000000000..cd7bd186a22
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 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 "content/browser/screen_orientation/screen_orientation_message_filter_android.h"
+
+#include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
+#include "content/common/screen_orientation_messages.h"
+
+namespace content {
+
+ScreenOrientationMessageFilterAndroid::ScreenOrientationMessageFilterAndroid()
+ : BrowserMessageFilter(ScreenOrientationMsgStart)
+ , listeners_count_(0) {
+}
+
+ScreenOrientationMessageFilterAndroid::~ScreenOrientationMessageFilterAndroid()
+{
+ if (listeners_count_ > 0)
+ ScreenOrientationDelegateAndroid::StopAccurateListening();
+}
+
+bool ScreenOrientationMessageFilterAndroid::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ScreenOrientationMessageFilterAndroid, message)
+ IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_StartListening,
+ OnStartListening)
+ IPC_MESSAGE_HANDLER(ScreenOrientationHostMsg_StopListening,
+ OnStopListening)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void ScreenOrientationMessageFilterAndroid::OnStartListening() {
+ ++listeners_count_;
+ if (listeners_count_ == 1)
+ ScreenOrientationDelegateAndroid::StartAccurateListening();
+}
+
+void ScreenOrientationMessageFilterAndroid::OnStopListening() {
+ DCHECK(listeners_count_ > 0);
+ --listeners_count_;
+ if (listeners_count_ == 0)
+ ScreenOrientationDelegateAndroid::StopAccurateListening();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.h b/chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.h
new file mode 100644
index 00000000000..9a01ed4e866
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_message_filter_android.h
@@ -0,0 +1,32 @@
+// Copyright 2014 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 CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_MESSAGE_FILTER_ANDROID_H_
+#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_MESSAGE_FILTER_ANDROID_H_
+
+#include "content/public/browser/browser_message_filter.h"
+
+namespace content {
+
+class ScreenOrientationMessageFilterAndroid : public BrowserMessageFilter {
+ public:
+ ScreenOrientationMessageFilterAndroid();
+
+ // BrowserMessageFilter implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
+
+ private:
+ virtual ~ScreenOrientationMessageFilterAndroid();
+
+ void OnStartListening();
+ void OnStopListening();
+
+ int listeners_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationMessageFilterAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_MESSAGE_FILTER_ANDROID_H_
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider.h b/chromium/content/browser/screen_orientation/screen_orientation_provider.h
deleted file mode 100644
index 4ae858805b0..00000000000
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_PROVIDER_H_
-#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_PROVIDER_H_
-
-#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
-
-namespace content {
-
-// Interface that needs to be implemented by any backend that wants to handle
-// screen orientation lock/unlock.
-class ScreenOrientationProvider {
- public:
- // Lock the screen orientation to |orientations|.
- virtual void LockOrientation(
- blink::WebScreenOrientationLockType orientations) = 0;
-
- // Unlock the screen orientation.
- virtual void UnlockOrientation() = 0;
-
- virtual ~ScreenOrientationProvider() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_PROVIDER_H_
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider_android.cc b/chromium/content/browser/screen_orientation/screen_orientation_provider_android.cc
deleted file mode 100644
index e8961bc4726..00000000000
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider_android.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 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 "content/browser/screen_orientation/screen_orientation_provider_android.h"
-
-#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
-#include "jni/ScreenOrientationProvider_jni.h"
-
-namespace content {
-
-ScreenOrientationProviderAndroid::ScreenOrientationProviderAndroid() {
-}
-
-ScreenOrientationProviderAndroid::~ScreenOrientationProviderAndroid() {
-}
-
-// static
-bool ScreenOrientationProviderAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-void ScreenOrientationProviderAndroid::LockOrientation(
- blink::WebScreenOrientationLockType orientation) {
- if (j_screen_orientation_provider_.is_null()) {
- j_screen_orientation_provider_.Reset(Java_ScreenOrientationProvider_create(
- base::android::AttachCurrentThread()));
- }
-
- Java_ScreenOrientationProvider_lockOrientation(
- base::android::AttachCurrentThread(),
- j_screen_orientation_provider_.obj(), orientation);
-}
-
-void ScreenOrientationProviderAndroid::UnlockOrientation() {
- // j_screen_orientation_provider_ is set when locking. If the screen
- // orientation was not locked, unlocking should be a no-op.
- if (j_screen_orientation_provider_.is_null())
- return;
-
- Java_ScreenOrientationProvider_unlockOrientation(
- base::android::AttachCurrentThread(),
- j_screen_orientation_provider_.obj());
-}
-
-// static
-ScreenOrientationProvider* ScreenOrientationDispatcherHost::CreateProvider() {
- return new ScreenOrientationProviderAndroid();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_provider_android.h b/chromium/content/browser/screen_orientation/screen_orientation_provider_android.h
deleted file mode 100644
index a526e24596c..00000000000
--- a/chromium/content/browser/screen_orientation/screen_orientation_provider_android.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_PROVIDER_ANDROID_H_
-#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_PROVIDER_ANDROID_H_
-
-#include "base/android/jni_android.h"
-#include "base/compiler_specific.h"
-#include "content/browser/screen_orientation/screen_orientation_provider.h"
-
-namespace content {
-
-class ScreenOrientationProviderAndroid : public ScreenOrientationProvider {
- public:
- ScreenOrientationProviderAndroid();
-
- static bool Register(JNIEnv* env);
-
- // ScreenOrientationProvider
- virtual void LockOrientation(blink::WebScreenOrientationLockType) OVERRIDE;
- virtual void UnlockOrientation() OVERRIDE;
-
- private:
- virtual ~ScreenOrientationProviderAndroid();
-
- base::android::ScopedJavaGlobalRef<jobject> j_screen_orientation_provider_;
-
- DISALLOW_COPY_AND_ASSIGN(ScreenOrientationProviderAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_PROVIDER_ANDROID_H_
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index 9fadec049a7..2a1be07b9a9 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -84,7 +84,7 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
class SecurityExploitBrowserTest : public ContentBrowserTest {
public:
SecurityExploitBrowserTest() {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
ASSERT_TRUE(test_server()->Start());
// Add a host resolver rule to map all outgoing requests to the test server.
@@ -139,8 +139,10 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
new SessionStorageNamespaceImpl(dom_storage_context));
// Cause a deliberate collision in routing ids.
int main_frame_routing_id = duplicate_routing_id + 1;
- pending_rvh->CreateNewWindow(
- duplicate_routing_id, main_frame_routing_id, params, session_storage);
+ pending_rvh->CreateNewWindow(duplicate_routing_id,
+ main_frame_routing_id,
+ params,
+ session_storage.get());
// If the above operation doesn't cause a crash, the test has succeeded!
}
diff --git a/chromium/content/browser/service_worker/BUILD.gn b/chromium/content/browser/service_worker/BUILD.gn
index d9f206615fb..43a2ff1b435 100644
--- a/chromium/content/browser/service_worker/BUILD.gn
+++ b/chromium/content/browser/service_worker/BUILD.gn
@@ -4,8 +4,9 @@
import("//third_party/protobuf/proto_library.gni")
-proto_library("database_proto") {
+proto_library("proto") {
sources = [
+ "service_worker_cache.proto",
"service_worker_database.proto",
]
}
diff --git a/chromium/content/browser/service_worker/OWNERS b/chromium/content/browser/service_worker/OWNERS
index f9916062308..c84704de993 100644
--- a/chromium/content/browser/service_worker/OWNERS
+++ b/chromium/content/browser/service_worker/OWNERS
@@ -1,12 +1,7 @@
michaeln@chromium.org
falken@chromium.org
+horo@chromium.org
+nhiroki@chromium.org
# may not be available
kinuko@chromium.org
-
-# per-file owners
-per-file embedded_worker*=horo@chromium.org
-per-file service_worker_process_manager*=horo@chromium.org
-per-file service_worker_internals_ui*=horo@chromium.org
-per-file service_worker_database*=nhiroki@chromium.org
-per-file service_worker_storage*=nhiroki@chromium.org
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index fd2d201a660..3eb9bda1c5f 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -4,11 +4,16 @@
#include "content/browser/service_worker/embedded_worker_instance.h"
+#include <algorithm>
+#include <utility>
+
#include "base/bind_helpers.h"
+#include "base/debug/trace_event.h"
#include "content/browser/devtools/embedded_worker_devtools_manager.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/common/service_worker/embedded_worker_messages.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "ipc/ipc_message.h"
@@ -26,16 +31,17 @@ struct SecondGreater {
}
};
-void NotifyWorkerContextStarted(int worker_process_id, int worker_route_id) {
+void NotifyWorkerReadyForInspection(int worker_process_id,
+ int worker_route_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- NotifyWorkerContextStarted, worker_process_id, worker_route_id));
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(NotifyWorkerReadyForInspection,
+ worker_process_id,
+ worker_route_id));
return;
}
- EmbeddedWorkerDevToolsManager::GetInstance()->WorkerContextStarted(
+ EmbeddedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
worker_process_id, worker_route_id);
}
@@ -53,36 +59,43 @@ void NotifyWorkerDestroyed(int worker_process_id, int worker_route_id) {
void RegisterToWorkerDevToolsManager(
int process_id,
- const ServiceWorkerContextCore* const service_worker_context,
+ const ServiceWorkerContextCore* service_worker_context,
+ base::WeakPtr<ServiceWorkerContextCore> service_worker_context_weak,
int64 service_worker_version_id,
+ const GURL& url,
const base::Callback<void(int worker_devtools_agent_route_id,
- bool pause_on_start)>& callback) {
+ bool wait_for_debugger)>& callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(RegisterToWorkerDevToolsManager,
process_id,
service_worker_context,
+ service_worker_context_weak,
service_worker_version_id,
+ url,
callback));
return;
}
int worker_devtools_agent_route_id = MSG_ROUTING_NONE;
- bool pause_on_start = false;
+ bool wait_for_debugger = false;
if (RenderProcessHost* rph = RenderProcessHost::FromID(process_id)) {
// |rph| may be NULL in unit tests.
worker_devtools_agent_route_id = rph->GetNextRoutingID();
- pause_on_start =
+ wait_for_debugger =
EmbeddedWorkerDevToolsManager::GetInstance()->ServiceWorkerCreated(
process_id,
worker_devtools_agent_route_id,
EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier(
- service_worker_context, service_worker_version_id));
+ service_worker_context,
+ service_worker_context_weak,
+ service_worker_version_id,
+ url));
}
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
- base::Bind(callback, worker_devtools_agent_route_id, pause_on_start));
+ base::Bind(callback, worker_devtools_agent_route_id, wait_for_debugger));
}
} // namespace
@@ -100,7 +113,7 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
void EmbeddedWorkerInstance::Start(int64 service_worker_version_id,
const GURL& scope,
const GURL& script_url,
- const std::vector<int>& possible_process_ids,
+ bool pause_after_download,
const StatusCallback& callback) {
if (!context_) {
callback.Run(SERVICE_WORKER_ERROR_ABORT);
@@ -110,15 +123,21 @@ void EmbeddedWorkerInstance::Start(int64 service_worker_version_id,
status_ = STARTING;
scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
new EmbeddedWorkerMsg_StartWorker_Params());
+ TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
+ "EmbeddedWorkerInstance::ProcessAllocate",
+ params.get(),
+ "Scope", scope.spec(),
+ "Script URL", script_url.spec());
params->embedded_worker_id = embedded_worker_id_;
params->service_worker_version_id = service_worker_version_id;
params->scope = scope;
params->script_url = script_url;
params->worker_devtools_agent_route_id = MSG_ROUTING_NONE;
- params->pause_on_start = false;
+ params->pause_after_download = pause_after_download;
+ params->wait_for_debugger = false;
context_->process_manager()->AllocateWorkerProcess(
embedded_worker_id_,
- SortProcesses(possible_process_ids),
+ scope,
script_url,
base::Bind(&EmbeddedWorkerInstance::RunProcessAllocated,
weak_factory_.GetWeakPtr(),
@@ -136,31 +155,23 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::Stop() {
return status;
}
+void EmbeddedWorkerInstance::ResumeAfterDownload() {
+ DCHECK_EQ(STARTING, status_);
+ registry_->Send(
+ process_id_,
+ new EmbeddedWorkerMsg_ResumeAfterDownload(embedded_worker_id_));
+}
+
ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMessage(
const IPC::Message& message) {
- DCHECK(status_ == RUNNING);
+ DCHECK_NE(kInvalidEmbeddedWorkerThreadId, thread_id_);
+ if (status_ != RUNNING && status_ != STARTING)
+ return SERVICE_WORKER_ERROR_IPC_FAILED;
return registry_->Send(process_id_,
new EmbeddedWorkerContextMsg_MessageToWorker(
thread_id_, embedded_worker_id_, message));
}
-void EmbeddedWorkerInstance::AddProcessReference(int process_id) {
- ProcessRefMap::iterator found = process_refs_.find(process_id);
- if (found == process_refs_.end())
- found = process_refs_.insert(std::make_pair(process_id, 0)).first;
- ++found->second;
-}
-
-void EmbeddedWorkerInstance::ReleaseProcessReference(int process_id) {
- ProcessRefMap::iterator found = process_refs_.find(process_id);
- if (found == process_refs_.end()) {
- NOTREACHED() << "Releasing unknown process ref " << process_id;
- return;
- }
- if (--found->second == 0)
- process_refs_.erase(found);
-}
-
EmbeddedWorkerInstance::EmbeddedWorkerInstance(
base::WeakPtr<ServiceWorkerContextCore> context,
int embedded_worker_id)
@@ -169,7 +180,7 @@ EmbeddedWorkerInstance::EmbeddedWorkerInstance(
embedded_worker_id_(embedded_worker_id),
status_(STOPPED),
process_id_(-1),
- thread_id_(-1),
+ thread_id_(kInvalidEmbeddedWorkerThreadId),
worker_devtools_agent_route_id_(MSG_ROUTING_NONE),
weak_factory_(this) {
}
@@ -204,6 +215,10 @@ void EmbeddedWorkerInstance::ProcessAllocated(
int process_id,
ServiceWorkerStatusCode status) {
DCHECK_EQ(process_id_, -1);
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "EmbeddedWorkerInstance::ProcessAllocate",
+ params.get(),
+ "Status", status);
if (status != SERVICE_WORKER_OK) {
status_ = STOPPED;
callback.Run(status);
@@ -211,10 +226,13 @@ void EmbeddedWorkerInstance::ProcessAllocated(
}
const int64 service_worker_version_id = params->service_worker_version_id;
process_id_ = process_id;
+ GURL script_url(params->script_url);
RegisterToWorkerDevToolsManager(
process_id,
context_.get(),
+ context_,
service_worker_version_id,
+ script_url,
base::Bind(&EmbeddedWorkerInstance::SendStartWorker,
weak_factory_.GetWeakPtr(),
base::Passed(&params),
@@ -225,28 +243,46 @@ void EmbeddedWorkerInstance::SendStartWorker(
scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
const StatusCallback& callback,
int worker_devtools_agent_route_id,
- bool pause_on_start) {
+ bool wait_for_debugger) {
worker_devtools_agent_route_id_ = worker_devtools_agent_route_id;
params->worker_devtools_agent_route_id = worker_devtools_agent_route_id;
- params->pause_on_start = pause_on_start;
- registry_->SendStartWorker(params.Pass(), callback, process_id_);
+ params->wait_for_debugger = wait_for_debugger;
+ ServiceWorkerStatusCode status =
+ registry_->SendStartWorker(params.Pass(), process_id_);
+ if (status != SERVICE_WORKER_OK) {
+ callback.Run(status);
+ return;
+ }
+ DCHECK(start_callback_.is_null());
+ start_callback_ = callback;
}
-void EmbeddedWorkerInstance::OnScriptLoaded() {
+void EmbeddedWorkerInstance::OnReadyForInspection() {
if (worker_devtools_agent_route_id_ != MSG_ROUTING_NONE)
- NotifyWorkerContextStarted(process_id_, worker_devtools_agent_route_id_);
+ NotifyWorkerReadyForInspection(process_id_,
+ worker_devtools_agent_route_id_);
+}
+
+void EmbeddedWorkerInstance::OnScriptLoaded(int thread_id) {
+ thread_id_ = thread_id;
}
void EmbeddedWorkerInstance::OnScriptLoadFailed() {
}
-void EmbeddedWorkerInstance::OnStarted(int thread_id) {
+void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
+ DCHECK(!start_callback_.is_null());
+ start_callback_.Run(success ? SERVICE_WORKER_OK
+ : SERVICE_WORKER_ERROR_START_WORKER_FAILED);
+ start_callback_.Reset();
+}
+
+void EmbeddedWorkerInstance::OnStarted() {
// Stop is requested before OnStarted is sent back from the worker.
if (status_ == STOPPING)
return;
DCHECK(status_ == STARTING);
status_ = RUNNING;
- thread_id_ = thread_id;
FOR_EACH_OBSERVER(Listener, listener_list_, OnStarted());
}
@@ -259,9 +295,18 @@ void EmbeddedWorkerInstance::OnStopped() {
process_id_ = -1;
thread_id_ = -1;
worker_devtools_agent_route_id_ = MSG_ROUTING_NONE;
+ start_callback_.Reset();
FOR_EACH_OBSERVER(Listener, listener_list_, OnStopped());
}
+void EmbeddedWorkerInstance::OnPausedAfterDownload() {
+ // Stop can be requested before getting this far.
+ if (status_ == STOPPING)
+ return;
+ DCHECK(status_ == STARTING);
+ FOR_EACH_OBSERVER(Listener, listener_list_, OnPausedAfterDownload());
+}
+
bool EmbeddedWorkerInstance::OnMessageReceived(const IPC::Message& message) {
ListenerList::Iterator it(listener_list_);
while (Listener* listener = it.GetNext()) {
@@ -303,26 +348,4 @@ void EmbeddedWorkerInstance::RemoveListener(Listener* listener) {
listener_list_.RemoveObserver(listener);
}
-std::vector<int> EmbeddedWorkerInstance::SortProcesses(
- const std::vector<int>& possible_process_ids) const {
- // Add the |possible_process_ids| to the existing process_refs_ since each one
- // is likely to take a reference once the SW starts up.
- ProcessRefMap refs_with_new_ids = process_refs_;
- for (std::vector<int>::const_iterator it = possible_process_ids.begin();
- it != possible_process_ids.end();
- ++it) {
- refs_with_new_ids[*it]++;
- }
-
- std::vector<std::pair<int, int> > counted(refs_with_new_ids.begin(),
- refs_with_new_ids.end());
- // Sort descending by the reference count.
- std::sort(counted.begin(), counted.end(), SecondGreater());
-
- std::vector<int> result(counted.size());
- for (size_t i = 0; i < counted.size(); ++i)
- result[i] = counted[i].first;
- return result;
-}
-
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index 9e404ff4640..75813248ff6 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/logging.h"
@@ -48,8 +49,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
class Listener {
public:
virtual ~Listener() {}
- virtual void OnStarted() = 0;
- virtual void OnStopped() = 0;
+ virtual void OnStarted() {}
+ virtual void OnStopped() {}
+ virtual void OnPausedAfterDownload() {}
virtual void OnReportException(const base::string16& error_message,
int line_number,
int column_number,
@@ -74,7 +76,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
void Start(int64 service_worker_version_id,
const GURL& scope,
const GURL& script_url,
- const std::vector<int>& possible_process_ids,
+ bool pause_after_download,
const StatusCallback& callback);
// Stops the worker. It is invalid to call this when the worker is
@@ -87,11 +89,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
// It is invalid to call this while the worker is not in RUNNING status.
ServiceWorkerStatusCode SendMessage(const IPC::Message& message);
- // Add or remove |process_id| to the internal process set where this
- // worker can be started.
- void AddProcessReference(int process_id);
- void ReleaseProcessReference(int process_id);
- bool HasProcessToRun() const { return !process_refs_.empty(); }
+ void ResumeAfterDownload();
int embedded_worker_id() const { return embedded_worker_id_; }
Status status() const { return status_; }
@@ -109,9 +107,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
friend class EmbeddedWorkerRegistry;
FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, StartAndStop);
- FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest, SortProcesses);
-
- typedef std::map<int, int> ProcessRefMap;
// Constructor is called via EmbeddedWorkerRegistry::CreateWorker().
// This instance holds a ref of |registry|.
@@ -136,21 +131,30 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
void SendStartWorker(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
const StatusCallback& callback,
int worker_devtools_agent_route_id,
- bool pause_on_start);
+ bool wait_for_debugger);
+
+ // Called back from Registry when the worker instance has ack'ed that
+ // it is ready for inspection.
+ void OnReadyForInspection();
// Called back from Registry when the worker instance has ack'ed that
- // it finished loading the script.
- void OnScriptLoaded();
+ // it finished loading the script and has started a worker thread.
+ void OnScriptLoaded(int thread_id);
// Called back from Registry when the worker instance has ack'ed that
// it failed to load the script.
void OnScriptLoadFailed();
// Called back from Registry when the worker instance has ack'ed that
- // its WorkerGlobalScope is actually started and parsed on |thread_id| in the
- // child process.
+ // it finished evaluating the script.
+ void OnScriptEvaluated(bool success);
+
+ // Called back from Registry when the worker instance has ack'ed that
+ // its WorkerGlobalScope is actually started and parsed.
// This will change the internal status from STARTING to RUNNING.
- void OnStarted(int thread_id);
+ void OnStarted();
+
+ void OnPausedAfterDownload();
// Called back from Registry when the worker instance has ack'ed that
// its WorkerGlobalScope is actually stopped in the child process.
@@ -176,11 +180,6 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
int line_number,
const GURL& source_url);
- // Chooses a list of processes to try to start this worker in, ordered by how
- // many clients are currently in those processes.
- std::vector<int> SortProcesses(
- const std::vector<int>& possible_process_ids) const;
-
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<EmbeddedWorkerRegistry> registry_;
const int embedded_worker_id_;
@@ -191,7 +190,8 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
int thread_id_;
int worker_devtools_agent_route_id_;
- ProcessRefMap process_refs_;
+ StatusCallback start_callback_;
+
ListenerList listener_list_;
base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_;
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
index d14ccd22f25..c5f190eef42 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -24,13 +24,11 @@ class EmbeddedWorkerInstanceTest : public testing::Test {
EmbeddedWorkerInstanceTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
}
- virtual void TearDown() OVERRIDE {
- helper_.reset();
- }
+ void TearDown() override { helper_.reset(); }
ServiceWorkerContextCore* context() { return helper_->context(); }
@@ -44,6 +42,7 @@ class EmbeddedWorkerInstanceTest : public testing::Test {
TestBrowserThreadBundle thread_bundle_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ private:
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
};
@@ -59,29 +58,28 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
embedded_worker_registry()->CreateWorker();
EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
- const int embedded_worker_id = worker->embedded_worker_id();
const int64 service_worker_version_id = 55L;
- const GURL scope("http://example.com/*");
+ const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
- // Simulate adding one process to the worker.
- helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
+ // Simulate adding one process to the pattern.
+ helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId);
// Start should succeed.
ServiceWorkerStatusCode status;
base::RunLoop run_loop;
worker->Start(
service_worker_version_id,
- scope,
+ pattern,
url,
- std::vector<int>(),
+ false,
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
- base::RunLoop().RunUntilIdle();
- // Worker started message should be notified (by EmbeddedWorkerTestHelper).
+ // The 'WorkerStarted' message should have been sent by
+ // EmbeddedWorkerTestHelper.
EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
EXPECT_EQ(kRenderProcessId, worker->process_id());
@@ -90,7 +88,8 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
EXPECT_EQ(EmbeddedWorkerInstance::STOPPING, worker->status());
base::RunLoop().RunUntilIdle();
- // Worker stopped message should be notified (by EmbeddedWorkerTestHelper).
+ // The 'WorkerStopped' message should have been sent by
+ // EmbeddedWorkerTestHelper.
EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
// Verify that we've sent two messages to start and terminate the worker.
@@ -106,19 +105,19 @@ TEST_F(EmbeddedWorkerInstanceTest, InstanceDestroyedBeforeStartFinishes) {
EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
const int64 service_worker_version_id = 55L;
- const GURL scope("http://example.com/*");
+ const GURL pattern("http://example.com/");
const GURL url("http://example.com/worker.js");
ServiceWorkerStatusCode status;
base::RunLoop run_loop;
// Begin starting the worker.
- std::vector<int> available_process;
- available_process.push_back(kRenderProcessId);
+ context()->process_manager()->AddProcessReferenceToPattern(
+ pattern, kRenderProcessId);
worker->Start(
service_worker_version_id,
- scope,
+ pattern,
url,
- available_process,
+ false,
base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
// But destroy it before it gets a chance to complete.
worker.reset();
@@ -130,38 +129,4 @@ TEST_F(EmbeddedWorkerInstanceTest, InstanceDestroyedBeforeStartFinishes) {
ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID));
}
-TEST_F(EmbeddedWorkerInstanceTest, SortProcesses) {
- scoped_ptr<EmbeddedWorkerInstance> worker =
- embedded_worker_registry()->CreateWorker();
- EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
-
- // Simulate adding processes to the worker.
- // Process 1 has 1 ref, 2 has 2 refs and 3 has 3 refs.
- const int embedded_worker_id = worker->embedded_worker_id();
- helper_->SimulateAddProcessToWorker(embedded_worker_id, 1);
- helper_->SimulateAddProcessToWorker(embedded_worker_id, 2);
- helper_->SimulateAddProcessToWorker(embedded_worker_id, 2);
- helper_->SimulateAddProcessToWorker(embedded_worker_id, 3);
- helper_->SimulateAddProcessToWorker(embedded_worker_id, 3);
- helper_->SimulateAddProcessToWorker(embedded_worker_id, 3);
-
- // Process 3 has the biggest # of references and it should be chosen.
- EXPECT_THAT(worker->SortProcesses(std::vector<int>()),
- testing::ElementsAre(3, 2, 1));
- EXPECT_EQ(-1, worker->process_id());
-
- // Argument processes are added to the existing set, but only for a single
- // call.
- std::vector<int> registering_processes;
- registering_processes.push_back(1);
- registering_processes.push_back(1);
- registering_processes.push_back(1);
- registering_processes.push_back(4);
- EXPECT_THAT(worker->SortProcesses(registering_processes),
- testing::ElementsAre(1, 3, 2, 4));
-
- EXPECT_THAT(worker->SortProcesses(std::vector<int>()),
- testing::ElementsAre(3, 2, 1));
-}
-
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.cc b/chromium/content/browser/service_worker/embedded_worker_registry.cc
index 988b0563f42..adf2579d733 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.cc
@@ -17,9 +17,22 @@
namespace content {
-EmbeddedWorkerRegistry::EmbeddedWorkerRegistry(
- base::WeakPtr<ServiceWorkerContextCore> context)
- : context_(context), next_embedded_worker_id_(0) {
+// static
+scoped_refptr<EmbeddedWorkerRegistry> EmbeddedWorkerRegistry::Create(
+ const base::WeakPtr<ServiceWorkerContextCore>& context) {
+ return make_scoped_refptr(new EmbeddedWorkerRegistry(context, 0));
+}
+
+// static
+scoped_refptr<EmbeddedWorkerRegistry> EmbeddedWorkerRegistry::Create(
+ const base::WeakPtr<ServiceWorkerContextCore>& context,
+ EmbeddedWorkerRegistry* old_registry) {
+ scoped_refptr<EmbeddedWorkerRegistry> registry =
+ new EmbeddedWorkerRegistry(
+ context,
+ old_registry->next_embedded_worker_id_);
+ registry->process_sender_map_.swap(old_registry->process_sender_map_);
+ return registry;
}
scoped_ptr<EmbeddedWorkerInstance> EmbeddedWorkerRegistry::CreateWorker() {
@@ -40,10 +53,9 @@ bool EmbeddedWorkerRegistry::OnMessageReceived(const IPC::Message& message) {
// ServiceWorkerDispatcherHost.
WorkerInstanceMap::iterator found = worker_map_.find(message.routing_id());
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << message.routing_id() << " not registered";
+ DCHECK(found != worker_map_.end());
+ if (found == worker_map_.end())
return false;
- }
return found->second->OnMessageReceived(message);
}
@@ -55,66 +67,91 @@ void EmbeddedWorkerRegistry::Shutdown() {
}
}
-void EmbeddedWorkerRegistry::OnWorkerScriptLoaded(int process_id,
- int embedded_worker_id) {
+void EmbeddedWorkerRegistry::OnWorkerReadyForInspection(
+ int process_id,
+ int embedded_worker_id) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
return;
- }
- if (found->second->process_id() != process_id) {
- LOG(ERROR) << "Incorrect embedded_worker_id";
+ found->second->OnReadyForInspection();
+}
+
+void EmbeddedWorkerRegistry::OnWorkerScriptLoaded(
+ int process_id,
+ int thread_id,
+ int embedded_worker_id ) {
+ WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
return;
- }
- found->second->OnScriptLoaded();
+ found->second->OnScriptLoaded(thread_id);
}
void EmbeddedWorkerRegistry::OnWorkerScriptLoadFailed(int process_id,
int embedded_worker_id) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
- return;
- }
- if (found->second->process_id() != process_id) {
- LOG(ERROR) << "Incorrect embedded_worker_id";
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
return;
- }
found->second->OnScriptLoadFailed();
}
+void EmbeddedWorkerRegistry::OnWorkerScriptEvaluated(int process_id,
+ int embedded_worker_id,
+ bool success) {
+ WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
+ return;
+ found->second->OnScriptEvaluated(success);
+}
+
void EmbeddedWorkerRegistry::OnWorkerStarted(
- int process_id, int thread_id, int embedded_worker_id) {
- DCHECK(!ContainsKey(worker_process_map_, process_id) ||
- worker_process_map_[process_id].count(embedded_worker_id) == 0);
+ int process_id, int embedded_worker_id) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
+ // TODO(falken): Instead of DCHECK, we should terminate the process on
+ // unexpected message. Same with most of the DCHECKs in this file.
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
return;
- }
- if (found->second->process_id() != process_id) {
- LOG(ERROR) << "Incorrect embedded_worker_id";
+
+ DCHECK(ContainsKey(worker_process_map_, process_id) &&
+ worker_process_map_[process_id].count(embedded_worker_id) == 1);
+ if (!ContainsKey(worker_process_map_, process_id) ||
+ worker_process_map_[process_id].count(embedded_worker_id) == 0) {
return;
}
- worker_process_map_[process_id].insert(embedded_worker_id);
- found->second->OnStarted(thread_id);
+
+ found->second->OnStarted();
}
void EmbeddedWorkerRegistry::OnWorkerStopped(
int process_id, int embedded_worker_id) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
return;
- }
- if (found->second->process_id() != process_id) {
- LOG(ERROR) << "Incorrect embedded_worker_id";
- return;
- }
worker_process_map_[process_id].erase(embedded_worker_id);
found->second->OnStopped();
}
+void EmbeddedWorkerRegistry::OnPausedAfterDownload(
+ int process_id, int embedded_worker_id) {
+ WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+ if (found == worker_map_.end() || found->second->process_id() != process_id)
+ return;
+ found->second->OnPausedAfterDownload();
+}
+
void EmbeddedWorkerRegistry::OnReportException(
int embedded_worker_id,
const base::string16& error_message,
@@ -122,10 +159,9 @@ void EmbeddedWorkerRegistry::OnReportException(
int column_number,
const GURL& source_url) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
+ DCHECK(found != worker_map_.end());
+ if (found == worker_map_.end())
return;
- }
found->second->OnReportException(
error_message, line_number, column_number, source_url);
}
@@ -138,10 +174,9 @@ void EmbeddedWorkerRegistry::OnReportConsoleMessage(
int line_number,
const GURL& source_url) {
WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
- if (found == worker_map_.end()) {
- LOG(ERROR) << "Worker " << embedded_worker_id << " not registered";
+ DCHECK(found != worker_map_.end());
+ if (found == worker_map_.end())
return;
- }
found->second->OnReportConsoleMessage(
source_identifier, message_level, message, line_number, source_url);
}
@@ -177,19 +212,47 @@ EmbeddedWorkerInstance* EmbeddedWorkerRegistry::GetWorker(
return found->second;
}
+bool EmbeddedWorkerRegistry::CanHandle(int embedded_worker_id) const {
+ if (embedded_worker_id < initial_embedded_worker_id_ ||
+ next_embedded_worker_id_ <= embedded_worker_id) {
+ return false;
+ }
+ return true;
+}
+
+EmbeddedWorkerRegistry::EmbeddedWorkerRegistry(
+ const base::WeakPtr<ServiceWorkerContextCore>& context,
+ int initial_embedded_worker_id)
+ : context_(context),
+ next_embedded_worker_id_(initial_embedded_worker_id),
+ initial_embedded_worker_id_(initial_embedded_worker_id) {
+}
+
EmbeddedWorkerRegistry::~EmbeddedWorkerRegistry() {
Shutdown();
}
-void EmbeddedWorkerRegistry::SendStartWorker(
+ServiceWorkerStatusCode EmbeddedWorkerRegistry::SendStartWorker(
scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
- const StatusCallback& callback,
int process_id) {
// The ServiceWorkerDispatcherHost is supposed to be created when the process
// is created, and keep an entry in process_sender_map_ for its whole
// lifetime.
DCHECK(ContainsKey(process_sender_map_, process_id));
- callback.Run(Send(process_id, new EmbeddedWorkerMsg_StartWorker(*params)));
+
+ int embedded_worker_id = params->embedded_worker_id;
+ WorkerInstanceMap::iterator found = worker_map_.find(embedded_worker_id);
+ DCHECK(found != worker_map_.end());
+ DCHECK_EQ(found->second->process_id(), process_id);
+
+ DCHECK(!ContainsKey(worker_process_map_, process_id) ||
+ worker_process_map_[process_id].count(embedded_worker_id) == 0);
+
+ ServiceWorkerStatusCode status =
+ Send(process_id, new EmbeddedWorkerMsg_StartWorker(*params));
+ if (status == SERVICE_WORKER_OK)
+ worker_process_map_[process_id].insert(embedded_worker_id);
+ return status;
}
ServiceWorkerStatusCode EmbeddedWorkerRegistry::Send(
diff --git a/chromium/content/browser/service_worker/embedded_worker_registry.h b/chromium/content/browser/service_worker/embedded_worker_registry.h
index 3df2e238071..31ed59d0020 100644
--- a/chromium/content/browser/service_worker/embedded_worker_registry.h
+++ b/chromium/content/browser/service_worker/embedded_worker_registry.h
@@ -40,8 +40,14 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
public:
typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
- explicit EmbeddedWorkerRegistry(
- base::WeakPtr<ServiceWorkerContextCore> context);
+ static scoped_refptr<EmbeddedWorkerRegistry> Create(
+ const base::WeakPtr<ServiceWorkerContextCore>& contxet);
+
+ // Used for DeleteAndStartOver. Creates a new registry which takes over
+ // |next_embedded_worker_id_| and |process_sender_map_| from |old_registry|.
+ static scoped_refptr<EmbeddedWorkerRegistry> Create(
+ const base::WeakPtr<ServiceWorkerContextCore>& context,
+ EmbeddedWorkerRegistry* old_registry);
bool OnMessageReceived(const IPC::Message& message);
@@ -50,9 +56,9 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
scoped_ptr<EmbeddedWorkerInstance> CreateWorker();
// Called from EmbeddedWorkerInstance, relayed to the child process.
- void SendStartWorker(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
- const StatusCallback& callback,
- int process_id);
+ ServiceWorkerStatusCode SendStartWorker(
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+ int process_id);
ServiceWorkerStatusCode StopWorker(int process_id,
int embedded_worker_id);
@@ -61,10 +67,17 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
// Called back from EmbeddedWorker in the child process, relayed via
// ServiceWorkerDispatcherHost.
- void OnWorkerScriptLoaded(int process_id, int embedded_worker_id);
+ void OnWorkerReadyForInspection(int process_id, int embedded_worker_id);
+ void OnWorkerScriptLoaded(int process_id,
+ int thread_id,
+ int embedded_worker_id);
void OnWorkerScriptLoadFailed(int process_id, int embedded_worker_id);
- void OnWorkerStarted(int process_id, int thread_id, int embedded_worker_id);
+ void OnWorkerScriptEvaluated(int process_id,
+ int embedded_worker_id,
+ bool success);
+ void OnWorkerStarted(int process_id, int embedded_worker_id);
void OnWorkerStopped(int process_id, int embedded_worker_id);
+ void OnPausedAfterDownload(int process_id, int embedded_worker_id);
void OnReportException(int embedded_worker_id,
const base::string16& error_message,
int line_number,
@@ -84,6 +97,9 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
// Returns an embedded worker instance for given |embedded_worker_id|.
EmbeddedWorkerInstance* GetWorker(int embedded_worker_id);
+ // Returns true if |embedded_worker_id| is managed by this registry.
+ bool CanHandle(int embedded_worker_id) const;
+
private:
friend class base::RefCounted<EmbeddedWorkerRegistry>;
friend class EmbeddedWorkerInstance;
@@ -91,6 +107,9 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap;
typedef std::map<int, IPC::Sender*> ProcessToSenderMap;
+ EmbeddedWorkerRegistry(
+ const base::WeakPtr<ServiceWorkerContextCore>& context,
+ int initial_embedded_worker_id);
~EmbeddedWorkerRegistry();
ServiceWorkerStatusCode Send(int process_id, IPC::Message* message);
@@ -105,10 +124,11 @@ class CONTENT_EXPORT EmbeddedWorkerRegistry
ProcessToSenderMap process_sender_map_;
// Map from process_id to embedded_worker_id.
- // This map only contains running workers.
+ // This map only contains starting and running workers.
std::map<int, std::set<int> > worker_process_map_;
int next_embedded_worker_id_;
+ const int initial_embedded_worker_id_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerRegistry);
};
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
index 82d206142a1..abc0c2b5c88 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -4,6 +4,9 @@
#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include <map>
+#include <string>
+
#include "base/bind.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -18,27 +21,32 @@ namespace content {
EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(int mock_render_process_id)
: wrapper_(new ServiceWorkerContextWrapper(NULL)),
next_thread_id_(0),
+ mock_render_process_id_(mock_render_process_id),
weak_factory_(this) {
+ scoped_ptr<MockServiceWorkerDatabaseTaskManager> database_task_manager(
+ new MockServiceWorkerDatabaseTaskManager(
+ base::MessageLoopProxy::current()));
wrapper_->InitInternal(base::FilePath(),
base::MessageLoopProxy::current(),
+ database_task_manager.Pass(),
base::MessageLoopProxy::current(),
+ NULL,
NULL);
wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id);
registry()->AddChildProcessSender(mock_render_process_id, this);
}
EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
- if (wrapper_)
+ if (wrapper_.get())
wrapper_->Shutdown();
}
-void EmbeddedWorkerTestHelper::SimulateAddProcessToWorker(
- int embedded_worker_id,
+void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(
+ const GURL& pattern,
int process_id) {
- EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
- ASSERT_TRUE(worker);
registry()->AddChildProcessSender(process_id, this);
- worker->AddProcessReference(process_id);
+ wrapper_->process_manager()->AddProcessReferenceToPattern(
+ pattern, process_id);
}
bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) {
@@ -54,6 +62,8 @@ bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorkerStub)
IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker,
OnMessageToWorkerStub)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
+ OnResumeAfterDownloadStub)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -77,9 +87,23 @@ void EmbeddedWorkerTestHelper::OnStartWorker(
int embedded_worker_id,
int64 service_worker_version_id,
const GURL& scope,
- const GURL& script_url) {
- // By default just notify the sender that the worker is started.
- SimulateWorkerStarted(next_thread_id_++, embedded_worker_id);
+ const GURL& script_url,
+ bool pause_after_download) {
+ if (pause_after_download) {
+ SimulatePausedAfterDownload(embedded_worker_id);
+ return;
+ }
+ SimulateWorkerReadyForInspection(embedded_worker_id);
+ SimulateWorkerScriptLoaded(next_thread_id_++, embedded_worker_id);
+ SimulateWorkerScriptEvaluated(embedded_worker_id);
+ SimulateWorkerStarted(embedded_worker_id);
+}
+
+void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
+ SimulateWorkerReadyForInspection(embedded_worker_id);
+ SimulateWorkerScriptLoaded(next_thread_id_++, embedded_worker_id);
+ SimulateWorkerScriptEvaluated(embedded_worker_id);
+ SimulateWorkerStarted(embedded_worker_id);
}
void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
@@ -125,23 +149,56 @@ void EmbeddedWorkerTestHelper::OnFetchEvent(
int embedded_worker_id,
int request_id,
const ServiceWorkerFetchRequest& request) {
- SimulateSend(
- new ServiceWorkerHostMsg_FetchEventFinished(
- embedded_worker_id,
- request_id,
- SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
- ServiceWorkerResponse(200, "OK",
- std::map<std::string, std::string>(),
- std::string())));
+ SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
+ embedded_worker_id,
+ request_id,
+ SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
+ ServiceWorkerResponse(GURL(""),
+ 200,
+ "OK",
+ blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(),
+ std::string(),
+ 0)));
}
-void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
+void EmbeddedWorkerTestHelper::SimulatePausedAfterDownload(
+ int embedded_worker_id) {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ ASSERT_TRUE(worker != NULL);
+ registry()->OnPausedAfterDownload(worker->process_id(), embedded_worker_id);
+}
+
+void EmbeddedWorkerTestHelper::SimulateWorkerReadyForInspection(
+ int embedded_worker_id) {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ ASSERT_TRUE(worker != NULL);
+ registry()->OnWorkerReadyForInspection(worker->process_id(),
+ embedded_worker_id);
+}
+
+void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
int thread_id, int embedded_worker_id) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker != NULL);
+ registry()->OnWorkerScriptLoaded(
+ worker->process_id(), thread_id, embedded_worker_id);
+}
+
+void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
+ int embedded_worker_id) {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ ASSERT_TRUE(worker != NULL);
+ registry()->OnWorkerScriptEvaluated(
+ worker->process_id(), embedded_worker_id, true /* success */);
+}
+
+void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
+ int embedded_worker_id) {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ ASSERT_TRUE(worker != NULL);
registry()->OnWorkerStarted(
worker->process_id(),
- thread_id,
embedded_worker_id);
}
@@ -167,11 +224,23 @@ void EmbeddedWorkerTestHelper::OnStartWorkerStub(
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
+ weak_factory_.GetWeakPtr(),
+ params.embedded_worker_id,
+ params.service_worker_version_id,
+ params.scope,
+ params.script_url,
+ params.pause_after_download));
+}
+
+void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
+ int embedded_worker_id) {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ ASSERT_TRUE(worker != NULL);
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
weak_factory_.GetWeakPtr(),
- params.embedded_worker_id,
- params.service_worker_version_id,
- params.scope,
- params.script_url));
+ embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.h b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
index 7cd817df6b9..6640d853fd6 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -45,18 +45,18 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
public:
// Initialize this helper for |context|, and enable this as an IPC
// sender for |mock_render_process_id|.
- EmbeddedWorkerTestHelper(int mock_render_process_id);
- virtual ~EmbeddedWorkerTestHelper();
+ explicit EmbeddedWorkerTestHelper(int mock_render_process_id);
+ ~EmbeddedWorkerTestHelper() override;
- // Call this to simulate add/associate a process to a worker.
+ // Call this to simulate add/associate a process to a pattern.
// This also registers this sender for the process.
- void SimulateAddProcessToWorker(int embedded_worker_id, int process_id);
+ void SimulateAddProcessToPattern(const GURL& pattern, int process_id);
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// IPC sink for EmbeddedWorker messages.
IPC::TestSink* ipc_sink() { return &sink_; }
@@ -67,6 +67,8 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
ServiceWorkerContextWrapper* context_wrapper() { return wrapper_.get(); }
void ShutdownContext();
+ int mock_render_process_id() const { return mock_render_process_id_;}
+
protected:
// Called when StartWorker, StopWorker and SendMessageToWorker message
// is sent to the embedded worker. Override if necessary. By default
@@ -77,7 +79,9 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
virtual void OnStartWorker(int embedded_worker_id,
int64 service_worker_version_id,
const GURL& scope,
- const GURL& script_url);
+ const GURL& script_url,
+ bool pause_after_download);
+ virtual void OnResumeAfterDownload(int embedded_worker_id);
virtual void OnStopWorker(int embedded_worker_id);
virtual bool OnMessageToWorker(int thread_id,
int embedded_worker_id,
@@ -97,15 +101,19 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
// These functions simulate sending an EmbeddedHostMsg message to the
// browser.
- void SimulateWorkerStarted(int thread_id, int embedded_worker_id);
+ void SimulatePausedAfterDownload(int embedded_worker_id);
+ void SimulateWorkerReadyForInspection(int embedded_worker_id);
+ void SimulateWorkerScriptLoaded(int thread_id, int embedded_worker_id);
+ void SimulateWorkerScriptEvaluated(int embedded_worker_id);
+ void SimulateWorkerStarted(int embedded_worker_id);
void SimulateWorkerStopped(int embedded_worker_id);
void SimulateSend(IPC::Message* message);
- protected:
EmbeddedWorkerRegistry* registry();
private:
void OnStartWorkerStub(const EmbeddedWorkerMsg_StartWorker_Params& params);
+ void OnResumeAfterDownloadStub(int embedded_worker_id);
void OnStopWorkerStub(int embedded_worker_id);
void OnMessageToWorkerStub(int thread_id,
int embedded_worker_id,
@@ -121,6 +129,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
IPC::TestSink inner_sink_;
int next_thread_id_;
+ int mock_render_process_id_;
// Updated each time MessageToWorker message is received.
int current_embedded_worker_id_;
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index 8e5b8871f9e..0a67c102206 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -6,10 +6,12 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
@@ -23,13 +25,19 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/common/blob/blob_data.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "net/url_request/url_request_filter.h"
+#include "net/url_request/url_request_interceptor.h"
+#include "net/url_request/url_request_test_job.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/common/blob/blob_data.h"
namespace content {
@@ -39,7 +47,7 @@ struct FetchResult {
ServiceWorkerStatusCode status;
ServiceWorkerFetchEventResult result;
ServiceWorkerResponse response;
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
};
void RunAndQuit(const base::Closure& closure,
@@ -72,6 +80,14 @@ void RunOnIOThread(
run_loop.Run();
}
+void ReceivePrepareResult(bool* is_prepared) {
+ *is_prepared = true;
+}
+
+base::Closure CreatePrepareReceiver(bool* is_prepared) {
+ return base::Bind(&ReceivePrepareResult, is_prepared);
+}
+
// Contrary to the style guide, the output parameter of this function comes
// before input parameters so Bind can be used on it to create a FetchCallback
// to pass to DispatchFetchEvent.
@@ -105,24 +121,156 @@ ServiceWorkerVersion::FetchCallback CreateResponseReceiver(
}
void ReadResponseBody(std::string* body,
- webkit_blob::BlobDataHandle* blob_data_handle) {
+ storage::BlobDataHandle* blob_data_handle) {
ASSERT_TRUE(blob_data_handle);
ASSERT_EQ(1U, blob_data_handle->data()->items().size());
*body = std::string(blob_data_handle->data()->items()[0].bytes(),
blob_data_handle->data()->items()[0].length());
}
+void ExpectResultAndRun(bool expected,
+ const base::Closure& continuation,
+ bool actual) {
+ EXPECT_EQ(expected, actual);
+ continuation.Run();
+}
+
+class WorkerActivatedObserver
+ : public ServiceWorkerContextObserver,
+ public base::RefCountedThreadSafe<WorkerActivatedObserver> {
+ public:
+ explicit WorkerActivatedObserver(ServiceWorkerContextWrapper* context)
+ : context_(context) {}
+ void Init() {
+ RunOnIOThread(base::Bind(&WorkerActivatedObserver::InitOnIOThread, this));
+ }
+ // ServiceWorkerContextObserver overrides.
+ void OnVersionStateChanged(int64 version_id) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const ServiceWorkerVersion* version =
+ context_->context()->GetLiveVersion(version_id);
+ if (version->status() == ServiceWorkerVersion::ACTIVATED) {
+ context_->RemoveObserver(this);
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&WorkerActivatedObserver::Quit, this));
+ }
+ }
+ void Wait() { run_loop_.Run(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<WorkerActivatedObserver>;
+ ~WorkerActivatedObserver() override {}
+ void InitOnIOThread() { context_->AddObserver(this); }
+ void Quit() { run_loop_.Quit(); }
+
+ base::RunLoop run_loop_;
+ ServiceWorkerContextWrapper* context_;
+ DISALLOW_COPY_AND_ASSIGN(WorkerActivatedObserver);
+};
+
+scoped_ptr<net::test_server::HttpResponse> VerifyServiceWorkerHeaderInRequest(
+ const net::test_server::HttpRequest& request) {
+ EXPECT_EQ(request.relative_url, "/service_worker/generated_sw.js");
+ std::map<std::string, std::string>::const_iterator it =
+ request.headers.find("Service-Worker");
+ EXPECT_TRUE(it != request.headers.end());
+ EXPECT_EQ("script", it->second);
+
+ scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+ new net::test_server::BasicHttpResponse());
+ http_response->set_content_type("text/javascript");
+ return http_response.Pass();
+}
+
+// The ImportsBustMemcache test requires that the imported script
+// would naturally be cached in blink's memcache, but the embedded
+// test server doesn't produce headers that allow the blink's memcache
+// to do that. This interceptor injects headers that give the import
+// an experiration far in the future.
+class LongLivedResourceInterceptor : public net::URLRequestInterceptor {
+ public:
+ LongLivedResourceInterceptor(const std::string& body)
+ : body_(body) {}
+ ~LongLivedResourceInterceptor() override {}
+
+ // net::URLRequestInterceptor implementation
+ net::URLRequestJob* MaybeInterceptRequest(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ const char kHeaders[] =
+ "HTTP/1.1 200 OK\0"
+ "Content-Type: text/javascript\0"
+ "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
+ "\0";
+ std::string headers(kHeaders, arraysize(kHeaders));
+ return new net::URLRequestTestJob(
+ request, network_delegate, headers, body_, true);
+ }
+
+ private:
+ std::string body_;
+ DISALLOW_COPY_AND_ASSIGN(LongLivedResourceInterceptor);
+};
+
+void CreateLongLivedResourceInterceptors(
+ const GURL& worker_url, const GURL& import_url) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ scoped_ptr<net::URLRequestInterceptor> interceptor;
+
+ interceptor.reset(new LongLivedResourceInterceptor(
+ "importScripts('long_lived_import.js');"));
+ net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
+ worker_url, interceptor.Pass());
+
+ interceptor.reset(new LongLivedResourceInterceptor(
+ "// the imported script does nothing"));
+ net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
+ import_url, interceptor.Pass());
+}
+
+void CountScriptResources(
+ ServiceWorkerContextWrapper* wrapper,
+ const GURL& scope,
+ int* num_resources) {
+ *num_resources = -1;
+
+ std::vector<ServiceWorkerRegistrationInfo> infos =
+ wrapper->context()->GetAllLiveRegistrationInfo();
+ if (infos.empty())
+ return;
+
+ int version_id;
+ size_t index = infos.size() - 1;
+ if (infos[index].installing_version.version_id !=
+ kInvalidServiceWorkerVersionId)
+ version_id = infos[index].installing_version.version_id;
+ else if (infos[index].waiting_version.version_id !=
+ kInvalidServiceWorkerVersionId)
+ version_id = infos[1].waiting_version.version_id;
+ else if (infos[index].active_version.version_id !=
+ kInvalidServiceWorkerVersionId)
+ version_id = infos[index].active_version.version_id;
+ else
+ return;
+
+ ServiceWorkerVersion* version =
+ wrapper->context()->GetLiveVersion(version_id);
+ *num_resources = static_cast<int>(version->script_cache_map()->size());
+}
+
} // namespace
class ServiceWorkerBrowserTest : public ContentBrowserTest {
protected:
typedef ServiceWorkerBrowserTest self;
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- command_line->AppendSwitch(switches::kEnableServiceWorker);
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
shell()->web_contents()->GetBrowserContext());
@@ -138,7 +286,7 @@ class ServiceWorkerBrowserTest : public ContentBrowserTest {
RunOnIOThread(base::Bind(&self::SetUpOnIOThread, this));
}
- virtual void TearDownOnMainThread() OVERRIDE {
+ void TearDownOnMainThread() override {
RunOnIOThread(base::Bind(&self::TearDownOnIOThread, this));
wrapper_ = NULL;
}
@@ -149,9 +297,9 @@ class ServiceWorkerBrowserTest : public ContentBrowserTest {
ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
ServiceWorkerContext* public_context() { return wrapper(); }
- void AssociateRendererProcessToWorker(EmbeddedWorkerInstance* worker) {
- worker->AddProcessReference(
- shell()->web_contents()->GetRenderProcessHost()->GetID());
+ void AssociateRendererProcessToPattern(const GURL& pattern) {
+ wrapper_->process_manager()->AddProcessReferenceToPattern(
+ pattern, shell()->web_contents()->GetRenderProcessHost()->GetID());
}
private:
@@ -164,10 +312,11 @@ class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
typedef EmbeddedWorkerBrowserTest self;
EmbeddedWorkerBrowserTest()
- : last_worker_status_(EmbeddedWorkerInstance::STOPPED) {}
- virtual ~EmbeddedWorkerBrowserTest() {}
+ : last_worker_status_(EmbeddedWorkerInstance::STOPPED),
+ pause_mode_(DONT_PAUSE) {}
+ ~EmbeddedWorkerBrowserTest() override {}
- virtual void TearDownOnIOThread() OVERRIDE {
+ void TearDownOnIOThread() override {
if (worker_) {
worker_->RemoveListener(this);
worker_.reset();
@@ -180,20 +329,20 @@ class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker_->status());
worker_->AddListener(this);
- AssociateRendererProcessToWorker(worker_.get());
const int64 service_worker_version_id = 33L;
- const GURL scope = embedded_test_server()->GetURL("/*");
+ const GURL pattern = embedded_test_server()->GetURL("/");
const GURL script_url = embedded_test_server()->GetURL(
"/service_worker/worker.js");
- std::vector<int> processes;
- processes.push_back(
- shell()->web_contents()->GetRenderProcessHost()->GetID());
+ AssociateRendererProcessToPattern(pattern);
+ int process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+ wrapper()->process_manager()->AddProcessReferenceToPattern(
+ pattern, process_id);
worker_->Start(
service_worker_version_id,
- scope,
+ pattern,
script_url,
- processes,
+ pause_mode_ != DONT_PAUSE,
base::Bind(&EmbeddedWorkerBrowserTest::StartOnIOThread2, this));
}
void StartOnIOThread2(ServiceWorkerStatusCode status) {
@@ -221,34 +370,46 @@ class EmbeddedWorkerBrowserTest : public ServiceWorkerBrowserTest,
protected:
// EmbeddedWorkerInstance::Observer overrides:
- virtual void OnStarted() OVERRIDE {
+ void OnStarted() override {
ASSERT_TRUE(worker_ != NULL);
ASSERT_FALSE(done_closure_.is_null());
last_worker_status_ = worker_->status();
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
}
- virtual void OnStopped() OVERRIDE {
+ void OnStopped() override {
ASSERT_TRUE(worker_ != NULL);
ASSERT_FALSE(done_closure_.is_null());
last_worker_status_ = worker_->status();
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, done_closure_);
}
- virtual void OnReportException(const base::string16& error_message,
- int line_number,
- int column_number,
- const GURL& source_url) OVERRIDE {}
- virtual void OnReportConsoleMessage(int source_identifier,
- int message_level,
- const base::string16& message,
- int line_number,
- const GURL& source_url) OVERRIDE {}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
- return false;
- }
+ void OnPausedAfterDownload() override {
+ if (pause_mode_ == PAUSE_THEN_RESUME)
+ worker_->ResumeAfterDownload();
+ else if (pause_mode_ == PAUSE_THEN_STOP)
+ worker_->Stop();
+ else
+ ASSERT_TRUE(false);
+ }
+ void OnReportException(const base::string16& error_message,
+ int line_number,
+ int column_number,
+ const GURL& source_url) override {}
+ void OnReportConsoleMessage(int source_identifier,
+ int message_level,
+ const base::string16& message,
+ int line_number,
+ const GURL& source_url) override {}
+ bool OnMessageReceived(const IPC::Message& message) override { return false; }
scoped_ptr<EmbeddedWorkerInstance> worker_;
EmbeddedWorkerInstance::Status last_worker_status_;
+ enum {
+ DONT_PAUSE,
+ PAUSE_THEN_RESUME,
+ PAUSE_THEN_STOP,
+ } pause_mode_;
+
// Called by EmbeddedWorkerInstance::Observer overrides so that
// test code can wait for the worker status notifications.
base::Closure done_closure_;
@@ -258,9 +419,9 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
public:
typedef ServiceWorkerVersionBrowserTest self;
- virtual ~ServiceWorkerVersionBrowserTest() {}
+ ~ServiceWorkerVersionBrowserTest() override {}
- virtual void TearDownOnIOThread() OVERRIDE {
+ void TearDownOnIOThread() override {
registration_ = NULL;
version_ = NULL;
}
@@ -296,7 +457,6 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
ServiceWorkerStatusCode expected_status) {
RunOnIOThread(
base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
- version_->SetStatus(ServiceWorkerVersion::INSTALLED);
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
base::RunLoop run_loop;
BrowserThread::PostTask(
@@ -311,9 +471,10 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void FetchOnRegisteredWorker(
ServiceWorkerFetchEventResult* result,
ServiceWorkerResponse* response,
- scoped_ptr<webkit_blob::BlobDataHandle>* blob_data_handle) {
+ scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
blob_context_ = ChromeBlobStorageContext::GetFor(
shell()->web_contents()->GetBrowserContext());
+ bool prepare_result = false;
FetchResult fetch_result;
fetch_result.status = SERVICE_WORKER_ERROR_FAILED;
base::RunLoop fetch_run_loop;
@@ -322,35 +483,37 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
base::Bind(&self::FetchOnIOThread,
this,
fetch_run_loop.QuitClosure(),
+ &prepare_result,
&fetch_result));
fetch_run_loop.Run();
+ ASSERT_TRUE(prepare_result);
*result = fetch_result.result;
*response = fetch_result.response;
*blob_data_handle = fetch_result.blob_data_handle.Pass();
ASSERT_EQ(SERVICE_WORKER_OK, fetch_result.status);
}
- void FetchTestHelper(
- const std::string& worker_url,
- ServiceWorkerFetchEventResult* result,
- ServiceWorkerResponse* response,
- scoped_ptr<webkit_blob::BlobDataHandle>* blob_data_handle) {
+ void FetchTestHelper(const std::string& worker_url,
+ ServiceWorkerFetchEventResult* result,
+ ServiceWorkerResponse* response,
+ scoped_ptr<storage::BlobDataHandle>* blob_data_handle) {
RunOnIOThread(
base::Bind(&self::SetUpRegistrationOnIOThread, this, worker_url));
FetchOnRegisteredWorker(result, response, blob_data_handle);
}
void SetUpRegistrationOnIOThread(const std::string& worker_url) {
+ const GURL pattern = embedded_test_server()->GetURL("/");
registration_ = new ServiceWorkerRegistration(
- embedded_test_server()->GetURL("/*"),
- embedded_test_server()->GetURL(worker_url),
+ pattern,
wrapper()->context()->storage()->NewRegistrationId(),
wrapper()->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_,
+ registration_.get(),
+ embedded_test_server()->GetURL(worker_url),
wrapper()->context()->storage()->NewVersionId(),
wrapper()->context()->AsWeakPtr());
- AssociateRendererProcessToWorker(version_->embedded_worker());
+ AssociateRendererProcessToPattern(pattern);
}
void StartOnIOThread(const base::Closure& done,
@@ -362,6 +525,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void InstallOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ version_->SetStatus(ServiceWorkerVersion::INSTALLING);
version_->DispatchInstallEvent(
-1, CreateReceiver(BrowserThread::UI, done, result));
}
@@ -369,33 +533,39 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void ActivateOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- version_->SetStatus(ServiceWorkerVersion::INSTALLED);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
version_->DispatchActivateEvent(
CreateReceiver(BrowserThread::UI, done, result));
}
- void FetchOnIOThread(const base::Closure& done, FetchResult* result) {
+ void FetchOnIOThread(const base::Closure& done,
+ bool* prepare_result,
+ FetchResult* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
ServiceWorkerFetchRequest request(
embedded_test_server()->GetURL("/service_worker/empty.html"),
"GET",
- std::map<std::string, std::string>());
- version_->SetStatus(ServiceWorkerVersion::ACTIVE);
+ ServiceWorkerHeaderMap(),
+ GURL(""),
+ false);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
version_->DispatchFetchEvent(
- request, CreateResponseReceiver(BrowserThread::UI, done,
- blob_context_, result));
+ request,
+ CreatePrepareReceiver(prepare_result),
+ CreateResponseReceiver(
+ BrowserThread::UI, done, blob_context_.get(), result));
}
void StopOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result) {
- ASSERT_TRUE(version_);
+ ASSERT_TRUE(version_.get());
version_->StopWorker(CreateReceiver(BrowserThread::UI, done, result));
}
void SyncEventOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- version_->SetStatus(ServiceWorkerVersion::ACTIVE);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
version_->DispatchSyncEvent(
CreateReceiver(BrowserThread::UI, done, result));
}
@@ -426,6 +596,27 @@ IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartAndStop) {
ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
}
+IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest, StartPaused_ThenResume) {
+ pause_mode_ = PAUSE_THEN_RESUME;
+ base::RunLoop start_run_loop;
+ done_closure_ = start_run_loop.QuitClosure();
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&self::StartOnIOThread, this));
+ start_run_loop.Run();
+ ASSERT_EQ(EmbeddedWorkerInstance::RUNNING, last_worker_status_);
+}
+
+IN_PROC_BROWSER_TEST_F(EmbeddedWorkerBrowserTest,
+ StartPaused_ThenStop) {
+ pause_mode_ = PAUSE_THEN_STOP;
+ base::RunLoop start_run_loop;
+ done_closure_ = start_run_loop.QuitClosure();
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&self::StartOnIOThread, this));
+ start_run_loop.Run();
+ ASSERT_EQ(EmbeddedWorkerInstance::STOPPED, last_worker_status_);
+}
+
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
"/service_worker/worker.js"));
@@ -476,10 +667,19 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
SERVICE_WORKER_OK);
}
+// Check that ServiceWorker script requests set a "Service-Worker: script"
+// header.
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+ ServiceWorkerScriptHeader) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&VerifyServiceWorkerHeaderInRequest));
+ InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
+}
+
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
Activate_NoEventListener) {
ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
- ASSERT_EQ(ServiceWorkerVersion::ACTIVE, version_->status());
+ ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
@@ -496,15 +696,15 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
ServiceWorkerFetchEventResult result;
ServiceWorkerResponse response;
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
FetchTestHelper("/service_worker/fetch_event.js",
&result, &response, &blob_data_handle);
ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
EXPECT_EQ(301, response.status_code);
EXPECT_EQ("Moved Permanently", response.status_text);
- std::map<std::string, std::string> expected_headers;
- expected_headers["Content-Language"] = "fi";
- expected_headers["Content-Type"] = "text/html; charset=UTF-8";
+ ServiceWorkerHeaderMap expected_headers;
+ expected_headers["content-language"] = "fi";
+ expected_headers["content-type"] = "text/html; charset=UTF-8";
EXPECT_EQ(expected_headers, response.headers);
std::string body;
@@ -533,14 +733,14 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, SyncEventHandled) {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitch(switches::kEnableServiceWorkerSync);
RunOnIOThread(base::Bind(
&self::SetUpRegistrationOnIOThread, this, "/service_worker/sync.js"));
ServiceWorkerFetchEventResult result;
ServiceWorkerResponse response;
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
// Should 404 before sync event.
FetchOnRegisteredWorker(&result, &response, &blob_data_handle);
EXPECT_EQ(404, response.status_code);
@@ -562,42 +762,94 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, SyncEventHandled) {
EXPECT_EQ(200, response.status_code);
}
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
+ const std::string kPageUrl = "/service_worker/reload.html";
+ const std::string kWorkerUrl = "/service_worker/fetch_event_reload.js";
+ {
+ scoped_refptr<WorkerActivatedObserver> observer =
+ new WorkerActivatedObserver(wrapper());
+ observer->Init();
+ public_context()->RegisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ embedded_test_server()->GetURL(kWorkerUrl),
+ base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
+ observer->Wait();
+ }
+ {
+ const base::string16 title = base::ASCIIToUTF16("reload=false");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+ {
+ const base::string16 title = base::ASCIIToUTF16("reload=true");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ ReloadBlockUntilNavigationsComplete(shell(), 1);
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+ }
+ shell()->Close();
+ {
+ base::RunLoop run_loop;
+ public_context()->UnregisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
+ run_loop.Run();
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
+ const std::string kScopeUrl = "/service_worker/imports_bust_memcache_scope/";
+ const std::string kPageUrl = "/service_worker/imports_bust_memcache.html";
+ const std::string kScriptUrl = "/service_worker/worker_with_one_import.js";
+ const std::string kImportUrl = "/service_worker/long_lived_import.js";
+ const base::string16 kOKTitle(base::ASCIIToUTF16("OK"));
+ const base::string16 kFailTitle(base::ASCIIToUTF16("FAIL"));
+
+ RunOnIOThread(
+ base::Bind(&CreateLongLivedResourceInterceptors,
+ embedded_test_server()->GetURL(kScriptUrl),
+ embedded_test_server()->GetURL(kImportUrl)));
+
+ TitleWatcher title_watcher(shell()->web_contents(), kOKTitle);
+ title_watcher.AlsoWaitForTitle(kFailTitle);
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
+ base::string16 title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(kOKTitle, title);
+
+ // Verify the number of resources in the implicit script cache is correct.
+ const int kExpectedNumResources = 2;
+ int num_resources = 0;
+ RunOnIOThread(
+ base::Bind(&CountScriptResources,
+ base::Unretained(wrapper()),
+ embedded_test_server()->GetURL(kScopeUrl),
+ &num_resources));
+ EXPECT_EQ(kExpectedNumResources, num_resources);
+}
+
class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
public:
typedef ServiceWorkerBlackBoxBrowserTest self;
- static void ExpectResultAndRun(bool expected,
- const base::Closure& continuation,
- bool actual) {
- EXPECT_EQ(expected, actual);
- continuation.Run();
- }
-
void FindRegistrationOnIO(const GURL& document_url,
ServiceWorkerStatusCode* status,
- GURL* script_url,
const base::Closure& continuation) {
wrapper()->context()->storage()->FindRegistrationForDocument(
document_url,
base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2,
this,
status,
- script_url,
continuation));
}
void FindRegistrationOnIO2(
ServiceWorkerStatusCode* out_status,
- GURL* script_url,
const base::Closure& continuation,
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration) {
*out_status = status;
- if (registration) {
- *script_url = registration->script_url();
- } else {
+ if (!registration.get())
EXPECT_NE(SERVICE_WORKER_OK, status);
- }
continuation.Run();
}
};
@@ -612,8 +864,8 @@ static int CountRenderProcessHosts() {
return result;
}
-// Crashes on Android: http://crbug.com/387045
-#if defined(OS_ANDROID)
+// Flaky timeouts on CrOS: http://crbug.com/387045
+#if defined(OS_CHROMEOS)
#define MAYBE_Registration DISABLED_Registration
#else
#define MAYBE_Registration Registration
@@ -625,14 +877,12 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
const std::string kWorkerUrl = "/service_worker/fetch_event.js";
- // Unregistering nothing should return true.
+ // Unregistering nothing should return false.
{
base::RunLoop run_loop;
public_context()->UnregisterServiceWorker(
- embedded_test_server()->GetURL("/*"),
- base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
- true,
- run_loop.QuitClosure()));
+ embedded_test_server()->GetURL("/"),
+ base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure()));
run_loop.Run();
}
@@ -640,11 +890,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
{
base::RunLoop run_loop;
public_context()->RegisterServiceWorker(
- embedded_test_server()->GetURL("/*"),
+ embedded_test_server()->GetURL("/"),
embedded_test_server()->GetURL("/does/not/exist"),
- base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
- false,
- run_loop.QuitClosure()));
+ base::Bind(&ExpectResultAndRun, false, run_loop.QuitClosure()));
run_loop.Run();
}
EXPECT_EQ(0, CountRenderProcessHosts());
@@ -653,11 +901,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
{
base::RunLoop run_loop;
public_context()->RegisterServiceWorker(
- embedded_test_server()->GetURL("/*"),
+ embedded_test_server()->GetURL("/"),
embedded_test_server()->GetURL(kWorkerUrl),
- base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
- true,
- run_loop.QuitClosure()));
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
run_loop.Run();
}
EXPECT_EQ(1, CountRenderProcessHosts());
@@ -667,11 +913,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
{
base::RunLoop run_loop;
public_context()->RegisterServiceWorker(
- embedded_test_server()->GetURL("/*"),
+ embedded_test_server()->GetURL("/"),
embedded_test_server()->GetURL(kWorkerUrl),
- base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
- true,
- run_loop.QuitClosure()));
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
run_loop.Run();
}
@@ -683,10 +927,8 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
{
base::RunLoop run_loop;
public_context()->UnregisterServiceWorker(
- embedded_test_server()->GetURL("/*"),
- base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
- true,
- run_loop.QuitClosure()));
+ embedded_test_server()->GetURL("/"),
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
run_loop.Run();
}
EXPECT_GE(1, CountRenderProcessHosts()) << "Unregistering doesn't stop the "
@@ -696,13 +938,11 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, MAYBE_Registration) {
// Should not be able to find it.
{
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- GURL script_url;
RunOnIOThread(
base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
this,
embedded_test_server()->GetURL("/service_worker/empty.html"),
- &status,
- &script_url));
+ &status));
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status);
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_cache.cc b/chromium/content/browser/service_worker/service_worker_cache.cc
new file mode 100644
index 00000000000..c19793af49e
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache.cc
@@ -0,0 +1,1259 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/guid.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/strings/string_util.h"
+#include "content/browser/service_worker/service_worker_cache.pb.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/url_request/url_request_context.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
+
+namespace content {
+
+namespace {
+
+typedef scoped_ptr<disk_cache::Backend> ScopedBackendPtr;
+typedef base::Callback<void(bool)> BoolCallback;
+typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
+ EntryBoolCallback;
+typedef base::Callback<void(scoped_ptr<ServiceWorkerCacheMetadata>)>
+ MetadataCallback;
+
+enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
+
+// The maximum size of an individual cache. Ultimately cache size is controlled
+// per-origin.
+const int kMaxCacheBytes = 512 * 1024 * 1024;
+
+// Buffer size for cache and blob reading/writing.
+const int kBufferSize = 1024 * 512;
+
+void NotReachedCompletionCallback(int rv) {
+ NOTREACHED();
+}
+
+blink::WebServiceWorkerResponseType ProtoResponseTypeToWebResponseType(
+ ServiceWorkerCacheResponse::ResponseType response_type) {
+ switch (response_type) {
+ case ServiceWorkerCacheResponse::BASIC_TYPE:
+ return blink::WebServiceWorkerResponseTypeBasic;
+ case ServiceWorkerCacheResponse::CORS_TYPE:
+ return blink::WebServiceWorkerResponseTypeCORS;
+ case ServiceWorkerCacheResponse::DEFAULT_TYPE:
+ return blink::WebServiceWorkerResponseTypeDefault;
+ case ServiceWorkerCacheResponse::ERROR_TYPE:
+ return blink::WebServiceWorkerResponseTypeError;
+ case ServiceWorkerCacheResponse::OPAQUE_TYPE:
+ return blink::WebServiceWorkerResponseTypeOpaque;
+ }
+ NOTREACHED();
+ return blink::WebServiceWorkerResponseTypeOpaque;
+}
+
+ServiceWorkerCacheResponse::ResponseType WebResponseTypeToProtoResponseType(
+ blink::WebServiceWorkerResponseType response_type) {
+ switch (response_type) {
+ case blink::WebServiceWorkerResponseTypeBasic:
+ return ServiceWorkerCacheResponse::BASIC_TYPE;
+ case blink::WebServiceWorkerResponseTypeCORS:
+ return ServiceWorkerCacheResponse::CORS_TYPE;
+ case blink::WebServiceWorkerResponseTypeDefault:
+ return ServiceWorkerCacheResponse::DEFAULT_TYPE;
+ case blink::WebServiceWorkerResponseTypeError:
+ return ServiceWorkerCacheResponse::ERROR_TYPE;
+ case blink::WebServiceWorkerResponseTypeOpaque:
+ return ServiceWorkerCacheResponse::OPAQUE_TYPE;
+ }
+ NOTREACHED();
+ return ServiceWorkerCacheResponse::OPAQUE_TYPE;
+}
+
+struct ResponseReadContext {
+ ResponseReadContext(scoped_refptr<net::IOBufferWithSize> buff,
+ scoped_refptr<storage::BlobData> blob)
+ : buffer(buff), blob_data(blob), total_bytes_read(0) {}
+
+ scoped_refptr<net::IOBufferWithSize> buffer;
+ scoped_refptr<storage::BlobData> blob_data;
+ int total_bytes_read;
+
+ DISALLOW_COPY_AND_ASSIGN(ResponseReadContext);
+};
+
+// Match callbacks
+void MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ int rv);
+void MatchDidReadMetadata(
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ disk_cache::ScopedEntryPtr entry,
+ scoped_ptr<ServiceWorkerCacheMetadata> headers);
+void MatchDidReadResponseBodyData(
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ disk_cache::ScopedEntryPtr entry,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<ResponseReadContext> response_context,
+ int rv);
+void MatchDoneWithBody(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<ResponseReadContext> response_context);
+
+// Delete callbacks
+void DeleteDidOpenEntry(
+ const GURL& origin,
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ErrorCallback& callback,
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ int rv);
+
+// Copy headers out of a cache entry and into a protobuf. The callback is
+// guaranteed to be run.
+void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback);
+void ReadMetadataDidReadMetadata(
+ disk_cache::Entry* entry,
+ const MetadataCallback& callback,
+ const scoped_refptr<net::IOBufferWithSize>& buffer,
+ int rv);
+
+// CreateBackend callbacks
+void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
+ scoped_ptr<ScopedBackendPtr> backend_ptr,
+ base::WeakPtr<ServiceWorkerCache> cache,
+ int rv);
+
+void MatchDidOpenEntry(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ int rv) {
+ if (rv != net::OK) {
+ callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ DCHECK(entryptr);
+ disk_cache::ScopedEntryPtr entry(*entryptr);
+
+ // Copy the entry pointer before passing it in base::Bind.
+ disk_cache::Entry* tmp_entry_ptr = entry.get();
+
+ MetadataCallback headers_callback = base::Bind(MatchDidReadMetadata,
+ base::Passed(request.Pass()),
+ callback,
+ blob_storage,
+ base::Passed(entry.Pass()));
+
+ ReadMetadata(tmp_entry_ptr, headers_callback);
+}
+
+bool VaryMatches(const ServiceWorkerHeaderMap& request,
+ const ServiceWorkerHeaderMap& cached_request,
+ const ServiceWorkerHeaderMap& response) {
+ ServiceWorkerHeaderMap::const_iterator vary_iter = response.find("vary");
+ if (vary_iter == response.end())
+ return true;
+
+ std::vector<std::string> vary_keys;
+ Tokenize(vary_iter->second, ",", &vary_keys);
+ for (std::vector<std::string>::const_iterator it = vary_keys.begin();
+ it != vary_keys.end();
+ ++it) {
+ std::string trimmed;
+ base::TrimWhitespaceASCII(*it, base::TRIM_ALL, &trimmed);
+ if (trimmed == "*")
+ return false;
+
+ ServiceWorkerHeaderMap::const_iterator request_iter = request.find(trimmed);
+ ServiceWorkerHeaderMap::const_iterator cached_request_iter =
+ cached_request.find(trimmed);
+
+ // If the header exists in one but not the other, no match.
+ if ((request_iter == request.end()) !=
+ (cached_request_iter == cached_request.end()))
+ return false;
+
+ // If the header exists in one, it exists in both. Verify that the values
+ // are equal.
+ if (request_iter != request.end() &&
+ request_iter->second != cached_request_iter->second)
+ return false;
+ }
+
+ return true;
+}
+
+void MatchDidReadMetadata(
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ disk_cache::ScopedEntryPtr entry,
+ scoped_ptr<ServiceWorkerCacheMetadata> metadata) {
+ if (!metadata) {
+ callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ scoped_ptr<ServiceWorkerResponse> response(new ServiceWorkerResponse(
+ request->url,
+ metadata->response().status_code(),
+ metadata->response().status_text(),
+ ProtoResponseTypeToWebResponseType(metadata->response().response_type()),
+ ServiceWorkerHeaderMap(),
+ "",
+ 0));
+
+ if (metadata->response().has_url())
+ response->url = GURL(metadata->response().url());
+
+ for (int i = 0; i < metadata->response().headers_size(); ++i) {
+ const ServiceWorkerCacheHeaderMap header = metadata->response().headers(i);
+ response->headers.insert(std::make_pair(header.name(), header.value()));
+ }
+
+ ServiceWorkerHeaderMap cached_request_headers;
+ for (int i = 0; i < metadata->request().headers_size(); ++i) {
+ const ServiceWorkerCacheHeaderMap header = metadata->request().headers(i);
+ cached_request_headers[header.name()] = header.value();
+ }
+
+ if (!VaryMatches(
+ request->headers, cached_request_headers, response->headers)) {
+ callback.Run(ServiceWorkerCache::ErrorTypeNotFound,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ if (entry->GetDataSize(INDEX_RESPONSE_BODY) == 0) {
+ callback.Run(ServiceWorkerCache::ErrorTypeOK,
+ response.Pass(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ // Stream the response body into a blob.
+ if (!blob_storage) {
+ callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ response->blob_uuid = base::GenerateGUID();
+
+ scoped_refptr<storage::BlobData> blob_data =
+ new storage::BlobData(response->blob_uuid);
+ scoped_refptr<net::IOBufferWithSize> response_body_buffer(
+ new net::IOBufferWithSize(kBufferSize));
+
+ scoped_ptr<ResponseReadContext> read_context(
+ new ResponseReadContext(response_body_buffer, blob_data));
+
+ // Copy the entry pointer before passing it in base::Bind.
+ disk_cache::Entry* tmp_entry_ptr = entry.get();
+
+ net::CompletionCallback read_callback =
+ base::Bind(MatchDidReadResponseBodyData,
+ base::Passed(request.Pass()),
+ callback,
+ blob_storage,
+ base::Passed(entry.Pass()),
+ base::Passed(response.Pass()),
+ base::Passed(read_context.Pass()));
+
+ int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
+ 0,
+ response_body_buffer.get(),
+ response_body_buffer->size(),
+ read_callback);
+
+ if (read_rv != net::ERR_IO_PENDING)
+ read_callback.Run(read_rv);
+}
+
+void MatchDidReadResponseBodyData(
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ disk_cache::ScopedEntryPtr entry,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<ResponseReadContext> response_context,
+ int rv) {
+ if (rv < 0) {
+ callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ if (rv == 0) {
+ response->blob_uuid = response_context->blob_data->uuid();
+ response->blob_size = response_context->total_bytes_read;
+ MatchDoneWithBody(request.Pass(),
+ callback,
+ blob_storage,
+ response.Pass(),
+ response_context.Pass());
+ return;
+ }
+
+ // TODO(jkarlin): This copying of the the entire cache response into memory is
+ // awful. Create a new interface around SimpleCache that provides access the
+ // data directly from the file. See bug http://crbug.com/403493.
+ response_context->blob_data->AppendData(response_context->buffer->data(), rv);
+ response_context->total_bytes_read += rv;
+ int total_bytes_read = response_context->total_bytes_read;
+
+ // Grab some pointers before passing them in bind.
+ net::IOBufferWithSize* buffer = response_context->buffer.get();
+ disk_cache::Entry* tmp_entry_ptr = entry.get();
+
+ net::CompletionCallback read_callback =
+ base::Bind(MatchDidReadResponseBodyData,
+ base::Passed(request.Pass()),
+ callback,
+ blob_storage,
+ base::Passed(entry.Pass()),
+ base::Passed(response.Pass()),
+ base::Passed(response_context.Pass()));
+
+ int read_rv = tmp_entry_ptr->ReadData(INDEX_RESPONSE_BODY,
+ total_bytes_read,
+ buffer,
+ buffer->size(),
+ read_callback);
+
+ if (read_rv != net::ERR_IO_PENDING)
+ read_callback.Run(read_rv);
+}
+
+void MatchDoneWithBody(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<ResponseReadContext> response_context) {
+ if (!blob_storage) {
+ callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle(
+ blob_storage->AddFinishedBlob(response_context->blob_data.get()));
+
+ callback.Run(ServiceWorkerCache::ErrorTypeOK,
+ response.Pass(),
+ blob_data_handle.Pass());
+}
+
+void DeleteDidOpenEntry(
+ const GURL& origin,
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ServiceWorkerCache::ErrorCallback& callback,
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ int rv) {
+ if (rv != net::OK) {
+ callback.Run(ServiceWorkerCache::ErrorTypeNotFound);
+ return;
+ }
+
+ DCHECK(entryptr);
+ disk_cache::ScopedEntryPtr entry(*entryptr);
+
+ if (quota_manager_proxy.get()) {
+ quota_manager_proxy->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorkerCache,
+ origin,
+ storage::kStorageTypeTemporary,
+ -1 * (entry->GetDataSize(INDEX_HEADERS) +
+ entry->GetDataSize(INDEX_RESPONSE_BODY)));
+ }
+
+ entry->Doom();
+ callback.Run(ServiceWorkerCache::ErrorTypeOK);
+}
+
+void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback) {
+ DCHECK(entry);
+
+ scoped_refptr<net::IOBufferWithSize> buffer(
+ new net::IOBufferWithSize(entry->GetDataSize(INDEX_HEADERS)));
+
+ net::CompletionCallback read_header_callback =
+ base::Bind(ReadMetadataDidReadMetadata, entry, callback, buffer);
+
+ int read_rv = entry->ReadData(
+ INDEX_HEADERS, 0, buffer.get(), buffer->size(), read_header_callback);
+
+ if (read_rv != net::ERR_IO_PENDING)
+ read_header_callback.Run(read_rv);
+}
+
+void ReadMetadataDidReadMetadata(
+ disk_cache::Entry* entry,
+ const MetadataCallback& callback,
+ const scoped_refptr<net::IOBufferWithSize>& buffer,
+ int rv) {
+ if (rv != buffer->size()) {
+ callback.Run(scoped_ptr<ServiceWorkerCacheMetadata>());
+ return;
+ }
+
+ scoped_ptr<ServiceWorkerCacheMetadata> metadata(
+ new ServiceWorkerCacheMetadata());
+
+ if (!metadata->ParseFromArray(buffer->data(), buffer->size())) {
+ callback.Run(scoped_ptr<ServiceWorkerCacheMetadata>());
+ return;
+ }
+
+ callback.Run(metadata.Pass());
+}
+
+void CreateBackendDidCreate(const ServiceWorkerCache::ErrorCallback& callback,
+ scoped_ptr<ScopedBackendPtr> backend_ptr,
+ base::WeakPtr<ServiceWorkerCache> cache,
+ int rv) {
+ if (rv != net::OK || !cache) {
+ callback.Run(ServiceWorkerCache::ErrorTypeStorage);
+ return;
+ }
+
+ cache->set_backend(backend_ptr->Pass());
+ callback.Run(ServiceWorkerCache::ErrorTypeOK);
+}
+
+} // namespace
+
+// Streams data from a blob and writes it to a given disk_cache::Entry.
+class ServiceWorkerCache::BlobReader : public net::URLRequest::Delegate {
+ public:
+ typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)>
+ EntryAndBoolCallback;
+
+ BlobReader()
+ : cache_entry_offset_(0),
+ buffer_(new net::IOBufferWithSize(kBufferSize)),
+ weak_ptr_factory_(this) {}
+
+ // |entry| is passed to the callback once complete.
+ void StreamBlobToCache(disk_cache::ScopedEntryPtr entry,
+ net::URLRequestContext* request_context,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle,
+ const EntryAndBoolCallback& callback) {
+ DCHECK(entry);
+ entry_ = entry.Pass();
+ callback_ = callback;
+ blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
+ blob_data_handle.Pass(), request_context, this);
+ blob_request_->Start();
+ }
+
+ // net::URLRequest::Delegate overrides for reading blobs.
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) override {
+ NOTREACHED();
+ }
+ void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* auth_info) override {
+ NOTREACHED();
+ }
+ void OnCertificateRequested(
+ net::URLRequest* request,
+ net::SSLCertRequestInfo* cert_request_info) override {
+ NOTREACHED();
+ }
+ void OnSSLCertificateError(net::URLRequest* request,
+ const net::SSLInfo& ssl_info,
+ bool fatal) override {
+ NOTREACHED();
+ }
+ void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override {
+ NOTREACHED();
+ }
+
+ void OnResponseStarted(net::URLRequest* request) override {
+ if (!request->status().is_success()) {
+ callback_.Run(entry_.Pass(), false);
+ return;
+ }
+ ReadFromBlob();
+ }
+
+ virtual void ReadFromBlob() {
+ int bytes_read = 0;
+ bool done =
+ blob_request_->Read(buffer_.get(), buffer_->size(), &bytes_read);
+ if (done)
+ OnReadCompleted(blob_request_.get(), bytes_read);
+ }
+
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override {
+ if (!request->status().is_success()) {
+ callback_.Run(entry_.Pass(), false);
+ return;
+ }
+
+ if (bytes_read == 0) {
+ callback_.Run(entry_.Pass(), true);
+ return;
+ }
+
+ net::CompletionCallback cache_write_callback =
+ base::Bind(&BlobReader::DidWriteDataToEntry,
+ weak_ptr_factory_.GetWeakPtr(),
+ bytes_read);
+
+ int rv = entry_->WriteData(INDEX_RESPONSE_BODY,
+ cache_entry_offset_,
+ buffer_.get(),
+ bytes_read,
+ cache_write_callback,
+ true /* truncate */);
+ if (rv != net::ERR_IO_PENDING)
+ cache_write_callback.Run(rv);
+ }
+
+ void DidWriteDataToEntry(int expected_bytes, int rv) {
+ if (rv != expected_bytes) {
+ callback_.Run(entry_.Pass(), false);
+ return;
+ }
+
+ cache_entry_offset_ += rv;
+ ReadFromBlob();
+ }
+
+ private:
+ int cache_entry_offset_;
+ disk_cache::ScopedEntryPtr entry_;
+ scoped_ptr<net::URLRequest> blob_request_;
+ EntryAndBoolCallback callback_;
+ scoped_refptr<net::IOBufferWithSize> buffer_;
+ base::WeakPtrFactory<BlobReader> weak_ptr_factory_;
+};
+
+// The state needed to pass between ServiceWorkerCache::Keys callbacks.
+struct ServiceWorkerCache::KeysContext {
+ KeysContext(const ServiceWorkerCache::RequestsCallback& callback,
+ base::WeakPtr<ServiceWorkerCache> cache)
+ : original_callback(callback),
+ cache(cache),
+ out_keys(new ServiceWorkerCache::Requests()),
+ enumerated_entry(NULL) {}
+
+ ~KeysContext() {
+ for (size_t i = 0, max = entries.size(); i < max; ++i)
+ entries[i]->Close();
+ if (enumerated_entry)
+ enumerated_entry->Close();
+ }
+
+ // The callback passed to the Keys() function.
+ ServiceWorkerCache::RequestsCallback original_callback;
+
+ // The ServiceWorkerCache that Keys was called on.
+ base::WeakPtr<ServiceWorkerCache> cache;
+
+ // The vector of open entries in the backend.
+ Entries entries;
+
+ // The output of the Keys function.
+ scoped_ptr<ServiceWorkerCache::Requests> out_keys;
+
+ // Used for enumerating cache entries.
+ scoped_ptr<disk_cache::Backend::Iterator> backend_iterator;
+ disk_cache::Entry* enumerated_entry;
+
+ DISALLOW_COPY_AND_ASSIGN(KeysContext);
+};
+
+// The state needed to pass between ServiceWorkerCache::Put callbacks.
+struct ServiceWorkerCache::PutContext {
+ PutContext(
+ const GURL& origin,
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle,
+ const ServiceWorkerCache::ResponseCallback& callback,
+ base::WeakPtr<ServiceWorkerCache> cache,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy)
+ : origin(origin),
+ request(request.Pass()),
+ response(response.Pass()),
+ blob_data_handle(blob_data_handle.Pass()),
+ callback(callback),
+ cache(cache),
+ request_context(request_context),
+ quota_manager_proxy(quota_manager_proxy),
+ cache_entry(NULL) {}
+ ~PutContext() {
+ if (cache_entry)
+ cache_entry->Close();
+ }
+
+ // Input parameters to the Put function.
+ GURL origin;
+ scoped_ptr<ServiceWorkerFetchRequest> request;
+ scoped_ptr<ServiceWorkerResponse> response;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
+ ServiceWorkerCache::ResponseCallback callback;
+ base::WeakPtr<ServiceWorkerCache> cache;
+ net::URLRequestContext* request_context;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy;
+
+ // This isn't a scoped_ptr because the disk_cache needs an Entry** as input to
+ // CreateEntry.
+ disk_cache::Entry* cache_entry;
+
+ // The BlobDataHandle for the output ServiceWorkerResponse.
+ scoped_ptr<storage::BlobDataHandle> out_blob_data_handle;
+
+ DISALLOW_COPY_AND_ASSIGN(PutContext);
+};
+
+// static
+scoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreateMemoryCache(
+ const GURL& origin,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context) {
+ return make_scoped_refptr(new ServiceWorkerCache(origin,
+ base::FilePath(),
+ request_context,
+ quota_manager_proxy,
+ blob_context));
+}
+
+// static
+scoped_refptr<ServiceWorkerCache> ServiceWorkerCache::CreatePersistentCache(
+ const GURL& origin,
+ const base::FilePath& path,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context) {
+ return make_scoped_refptr(new ServiceWorkerCache(
+ origin, path, request_context, quota_manager_proxy, blob_context));
+}
+
+ServiceWorkerCache::~ServiceWorkerCache() {
+}
+
+base::WeakPtr<ServiceWorkerCache> ServiceWorkerCache::AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+}
+
+void ServiceWorkerCache::Put(scoped_ptr<ServiceWorkerFetchRequest> request,
+ scoped_ptr<ServiceWorkerResponse> response,
+ const ResponseCallback& callback) {
+ IncPendingOps();
+ ResponseCallback pending_callback =
+ base::Bind(&ServiceWorkerCache::PendingResponseCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
+
+ if (!response->blob_uuid.empty()) {
+ if (!blob_storage_context_) {
+ pending_callback.Run(ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+ blob_data_handle =
+ blob_storage_context_->GetBlobDataFromUUID(response->blob_uuid);
+ if (!blob_data_handle) {
+ pending_callback.Run(ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+ }
+
+ scoped_ptr<PutContext> put_context(new PutContext(
+ origin_, request.Pass(), response.Pass(), blob_data_handle.Pass(),
+ pending_callback, weak_ptr_factory_.GetWeakPtr(), request_context_,
+ quota_manager_proxy_));
+
+ if (put_context->blob_data_handle) {
+ // Grab another handle to the blob for the callback response.
+ put_context->out_blob_data_handle =
+ blob_storage_context_->GetBlobDataFromUUID(
+ put_context->response->blob_uuid);
+ }
+
+ base::Closure continuation = base::Bind(&ServiceWorkerCache::PutImpl,
+ base::Passed(put_context.Pass()));
+
+ if (!initialized_) {
+ Init(continuation);
+ return;
+ }
+
+ continuation.Run();
+}
+
+void ServiceWorkerCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ResponseCallback& callback) {
+ IncPendingOps();
+ ResponseCallback pending_callback =
+ base::Bind(&ServiceWorkerCache::PendingResponseCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
+
+ if (!initialized_) {
+ Init(base::Bind(&ServiceWorkerCache::Match, weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(request.Pass()), pending_callback));
+ return;
+ }
+ if (!backend_) {
+ pending_callback.Run(ErrorTypeStorage, scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
+
+ disk_cache::Entry** entry_ptr = entry.get();
+
+ ServiceWorkerFetchRequest* request_ptr = request.get();
+
+ net::CompletionCallback open_entry_callback = base::Bind(
+ MatchDidOpenEntry, base::Passed(request.Pass()), pending_callback,
+ blob_storage_context_, base::Passed(entry.Pass()));
+
+ int rv = backend_->OpenEntry(
+ request_ptr->url.spec(), entry_ptr, open_entry_callback);
+ if (rv != net::ERR_IO_PENDING)
+ open_entry_callback.Run(rv);
+}
+
+void ServiceWorkerCache::Delete(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ErrorCallback& callback) {
+ IncPendingOps();
+ ErrorCallback pending_callback =
+ base::Bind(&ServiceWorkerCache::PendingErrorCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
+
+ if (!initialized_) {
+ Init(base::Bind(&ServiceWorkerCache::Delete, weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(request.Pass()), pending_callback));
+ return;
+ }
+ if (!backend_) {
+ pending_callback.Run(ErrorTypeStorage);
+ return;
+ }
+
+ scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
+
+ disk_cache::Entry** entry_ptr = entry.get();
+
+ ServiceWorkerFetchRequest* request_ptr = request.get();
+
+ net::CompletionCallback open_entry_callback = base::Bind(
+ DeleteDidOpenEntry, origin_, base::Passed(request.Pass()),
+ pending_callback, base::Passed(entry.Pass()), quota_manager_proxy_);
+
+ int rv = backend_->OpenEntry(
+ request_ptr->url.spec(), entry_ptr, open_entry_callback);
+ if (rv != net::ERR_IO_PENDING)
+ open_entry_callback.Run(rv);
+}
+
+void ServiceWorkerCache::Keys(const RequestsCallback& callback) {
+ IncPendingOps();
+ RequestsCallback pending_callback =
+ base::Bind(&ServiceWorkerCache::PendingRequestsCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
+ if (!initialized_) {
+ Init(base::Bind(&ServiceWorkerCache::Keys, weak_ptr_factory_.GetWeakPtr(),
+ pending_callback));
+ return;
+ }
+ if (!backend_) {
+ pending_callback.Run(ErrorTypeStorage, scoped_ptr<Requests>());
+ return;
+ }
+
+ // 1. Iterate through all of the entries, open them, and add them to a vector.
+ // 2. For each open entry:
+ // 2.1. Read the headers into a protobuf.
+ // 2.2. Copy the protobuf into a ServiceWorkerFetchRequest (a "key").
+ // 2.3. Push the response into a vector of requests to be returned.
+ // 3. Return the vector of requests (keys).
+
+ // The entries have to be loaded into a vector first because enumeration loops
+ // forever if you read data from a cache entry while enumerating.
+
+ scoped_ptr<KeysContext> keys_context(
+ new KeysContext(pending_callback, weak_ptr_factory_.GetWeakPtr()));
+
+ keys_context->backend_iterator = backend_->CreateIterator();
+ disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator;
+ disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry;
+
+ net::CompletionCallback open_entry_callback =
+ base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass()));
+
+ int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback);
+
+ if (rv != net::ERR_IO_PENDING)
+ open_entry_callback.Run(rv);
+}
+
+void ServiceWorkerCache::Close(const base::Closure& callback) {
+ DCHECK(!initialized_ || backend_)
+ << "Don't call ServiceWorkerCache::Close() twice.";
+
+ if (pending_ops_ > 0) {
+ DCHECK(ops_complete_callback_.is_null());
+ initialized_ = true; // So that future operations halt.
+ ops_complete_callback_ = base::Bind(
+ &ServiceWorkerCache::Close, weak_ptr_factory_.GetWeakPtr(), callback);
+ return;
+ }
+
+ initialized_ = true;
+ backend_.reset();
+ callback.Run();
+}
+
+int64 ServiceWorkerCache::MemoryBackedSize() const {
+ if (!backend_ || !memory_only_)
+ return 0;
+
+ scoped_ptr<disk_cache::Backend::Iterator> backend_iter =
+ backend_->CreateIterator();
+ disk_cache::Entry* entry = nullptr;
+
+ int64 sum = 0;
+
+ std::vector<disk_cache::Entry*> entries;
+ int rv = net::OK;
+ while ((rv = backend_iter->OpenNextEntry(
+ &entry, base::Bind(NotReachedCompletionCallback))) == net::OK) {
+ entries.push_back(entry); // Open the entries without mutating them.
+ }
+ DCHECK(rv !=
+ net::ERR_IO_PENDING); // Expect all memory ops to be synchronous.
+
+ for (disk_cache::Entry* entry : entries) {
+ sum += entry->GetDataSize(INDEX_HEADERS) +
+ entry->GetDataSize(INDEX_RESPONSE_BODY);
+ entry->Close();
+ }
+
+ return sum;
+}
+
+ServiceWorkerCache::ServiceWorkerCache(
+ const GURL& origin,
+ const base::FilePath& path,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context)
+ : origin_(origin),
+ path_(path),
+ request_context_(request_context),
+ quota_manager_proxy_(quota_manager_proxy),
+ blob_storage_context_(blob_context),
+ initialized_(false),
+ memory_only_(path.empty()),
+ pending_ops_(0),
+ weak_ptr_factory_(this) {
+}
+
+// static
+void ServiceWorkerCache::PutImpl(scoped_ptr<PutContext> put_context) {
+ if (!put_context->cache || !put_context->cache->backend_) {
+ put_context->callback.Run(ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ scoped_ptr<ServiceWorkerFetchRequest> request_copy(
+ new ServiceWorkerFetchRequest(*put_context->request));
+ ServiceWorkerCache* cache_ptr = put_context->cache.get();
+
+ cache_ptr->Delete(request_copy.Pass(),
+ base::Bind(PutDidDelete, base::Passed(put_context.Pass())));
+}
+
+// static
+void ServiceWorkerCache::PutDidDelete(scoped_ptr<PutContext> put_context,
+ ErrorType delete_error) {
+ if (!put_context->cache || !put_context->cache->backend_) {
+ put_context->callback.Run(ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ disk_cache::Entry** entry_ptr = &put_context->cache_entry;
+ ServiceWorkerFetchRequest* request_ptr = put_context->request.get();
+ disk_cache::Backend* backend_ptr = put_context->cache->backend_.get();
+
+ net::CompletionCallback create_entry_callback =
+ base::Bind(PutDidCreateEntry, base::Passed(put_context.Pass()));
+
+ int create_rv = backend_ptr->CreateEntry(
+ request_ptr->url.spec(), entry_ptr, create_entry_callback);
+
+ if (create_rv != net::ERR_IO_PENDING)
+ create_entry_callback.Run(create_rv);
+}
+
+// static
+void ServiceWorkerCache::PutDidCreateEntry(scoped_ptr<PutContext> put_context,
+ int rv) {
+ if (rv != net::OK) {
+ put_context->callback.Run(ServiceWorkerCache::ErrorTypeExists,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ DCHECK(put_context->cache_entry);
+
+ ServiceWorkerCacheMetadata metadata;
+ ServiceWorkerCacheRequest* request_metadata = metadata.mutable_request();
+ request_metadata->set_method(put_context->request->method);
+ for (ServiceWorkerHeaderMap::const_iterator it =
+ put_context->request->headers.begin();
+ it != put_context->request->headers.end();
+ ++it) {
+ ServiceWorkerCacheHeaderMap* header_map = request_metadata->add_headers();
+ header_map->set_name(it->first);
+ header_map->set_value(it->second);
+ }
+
+ ServiceWorkerCacheResponse* response_metadata = metadata.mutable_response();
+ response_metadata->set_status_code(put_context->response->status_code);
+ response_metadata->set_status_text(put_context->response->status_text);
+ response_metadata->set_response_type(
+ WebResponseTypeToProtoResponseType(put_context->response->response_type));
+ response_metadata->set_url(put_context->response->url.spec());
+ for (ServiceWorkerHeaderMap::const_iterator it =
+ put_context->response->headers.begin();
+ it != put_context->response->headers.end();
+ ++it) {
+ ServiceWorkerCacheHeaderMap* header_map = response_metadata->add_headers();
+ header_map->set_name(it->first);
+ header_map->set_value(it->second);
+ }
+
+ scoped_ptr<std::string> serialized(new std::string());
+ if (!metadata.SerializeToString(serialized.get())) {
+ put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ scoped_refptr<net::StringIOBuffer> buffer(
+ new net::StringIOBuffer(serialized.Pass()));
+
+ // Get a temporary copy of the entry pointer before passing it in base::Bind.
+ disk_cache::Entry* tmp_entry_ptr = put_context->cache_entry;
+
+ net::CompletionCallback write_headers_callback = base::Bind(
+ PutDidWriteHeaders, base::Passed(put_context.Pass()), buffer->size());
+
+ rv = tmp_entry_ptr->WriteData(INDEX_HEADERS,
+ 0 /* offset */,
+ buffer.get(),
+ buffer->size(),
+ write_headers_callback,
+ true /* truncate */);
+
+ if (rv != net::ERR_IO_PENDING)
+ write_headers_callback.Run(rv);
+}
+
+// static
+void ServiceWorkerCache::PutDidWriteHeaders(scoped_ptr<PutContext> put_context,
+ int expected_bytes,
+ int rv) {
+ if (rv != expected_bytes) {
+ put_context->cache_entry->Doom();
+ put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ // The metadata is written, now for the response content. The data is streamed
+ // from the blob into the cache entry.
+
+ if (put_context->response->blob_uuid.empty()) {
+ if (put_context->quota_manager_proxy.get()) {
+ put_context->quota_manager_proxy->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorkerCache,
+ put_context->origin,
+ storage::kStorageTypeTemporary,
+ put_context->cache_entry->GetDataSize(INDEX_HEADERS));
+ }
+
+ put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK,
+ put_context->response.Pass(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ DCHECK(put_context->blob_data_handle);
+
+ disk_cache::ScopedEntryPtr entry(put_context->cache_entry);
+ put_context->cache_entry = NULL;
+ scoped_ptr<BlobReader> reader(new BlobReader());
+ BlobReader* reader_ptr = reader.get();
+
+ // Grab some pointers before passing put_context in Bind.
+ net::URLRequestContext* request_context = put_context->request_context;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle =
+ put_context->blob_data_handle.Pass();
+
+ reader_ptr->StreamBlobToCache(entry.Pass(),
+ request_context,
+ blob_data_handle.Pass(),
+ base::Bind(PutDidWriteBlobToCache,
+ base::Passed(put_context.Pass()),
+ base::Passed(reader.Pass())));
+}
+
+// static
+void ServiceWorkerCache::PutDidWriteBlobToCache(
+ scoped_ptr<PutContext> put_context,
+ scoped_ptr<BlobReader> blob_reader,
+ disk_cache::ScopedEntryPtr entry,
+ bool success) {
+ DCHECK(entry);
+ put_context->cache_entry = entry.release();
+
+ if (!success) {
+ put_context->cache_entry->Doom();
+ put_context->callback.Run(ServiceWorkerCache::ErrorTypeStorage,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
+ return;
+ }
+
+ if (put_context->quota_manager_proxy.get()) {
+ put_context->quota_manager_proxy->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorkerCache,
+ put_context->origin,
+ storage::kStorageTypeTemporary,
+ put_context->cache_entry->GetDataSize(INDEX_HEADERS) +
+ put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY));
+ }
+
+ put_context->callback.Run(ServiceWorkerCache::ErrorTypeOK,
+ put_context->response.Pass(),
+ put_context->out_blob_data_handle.Pass());
+}
+
+// static
+void ServiceWorkerCache::KeysDidOpenNextEntry(
+ scoped_ptr<KeysContext> keys_context,
+ int rv) {
+ if (rv == net::ERR_FAILED) {
+ DCHECK(!keys_context->enumerated_entry);
+ // Enumeration is complete, extract the requests from the entries.
+ Entries::iterator iter = keys_context->entries.begin();
+ KeysProcessNextEntry(keys_context.Pass(), iter);
+ return;
+ }
+
+ base::WeakPtr<ServiceWorkerCache> cache = keys_context->cache;
+ if (rv < 0 || !cache) {
+ keys_context->original_callback.Run(ErrorTypeStorage,
+ scoped_ptr<Requests>());
+ return;
+ }
+
+ if (!cache->backend_) {
+ keys_context->original_callback.Run(ErrorTypeNotFound,
+ scoped_ptr<Requests>());
+ return;
+ }
+
+ // Store the entry.
+ keys_context->entries.push_back(keys_context->enumerated_entry);
+ keys_context->enumerated_entry = NULL;
+
+ // Enumerate the next entry.
+ disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator;
+ disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry;
+ net::CompletionCallback open_entry_callback =
+ base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass()));
+
+ rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback);
+
+ if (rv != net::ERR_IO_PENDING)
+ open_entry_callback.Run(rv);
+}
+
+// static
+void ServiceWorkerCache::KeysProcessNextEntry(
+ scoped_ptr<KeysContext> keys_context,
+ const Entries::iterator& iter) {
+ if (iter == keys_context->entries.end()) {
+ // All done. Return all of the keys.
+ keys_context->original_callback.Run(ErrorTypeOK,
+ keys_context->out_keys.Pass());
+ return;
+ }
+
+ ReadMetadata(
+ *iter,
+ base::Bind(KeysDidReadMetadata, base::Passed(keys_context.Pass()), iter));
+}
+
+// static
+void ServiceWorkerCache::KeysDidReadMetadata(
+ scoped_ptr<KeysContext> keys_context,
+ const Entries::iterator& iter,
+ scoped_ptr<ServiceWorkerCacheMetadata> metadata) {
+ disk_cache::Entry* entry = *iter;
+
+ if (metadata) {
+ keys_context->out_keys->push_back(
+ ServiceWorkerFetchRequest(GURL(entry->GetKey()),
+ metadata->request().method(),
+ ServiceWorkerHeaderMap(),
+ GURL(),
+ false));
+
+ ServiceWorkerHeaderMap& req_headers =
+ keys_context->out_keys->back().headers;
+
+ for (int i = 0; i < metadata->request().headers_size(); ++i) {
+ const ServiceWorkerCacheHeaderMap header = metadata->request().headers(i);
+ req_headers.insert(std::make_pair(header.name(), header.value()));
+ }
+ } else {
+ entry->Doom();
+ }
+
+ KeysProcessNextEntry(keys_context.Pass(), iter + 1);
+}
+
+void ServiceWorkerCache::CreateBackend(const ErrorCallback& callback) {
+ DCHECK(!backend_);
+
+ // Use APP_CACHE as opposed to DISK_CACHE to prevent cache eviction.
+ net::CacheType cache_type = memory_only_ ? net::MEMORY_CACHE : net::APP_CACHE;
+
+ scoped_ptr<ScopedBackendPtr> backend_ptr(new ScopedBackendPtr());
+
+ // Temporary pointer so that backend_ptr can be Pass()'d in Bind below.
+ ScopedBackendPtr* backend = backend_ptr.get();
+
+ net::CompletionCallback create_cache_callback =
+ base::Bind(CreateBackendDidCreate,
+ callback,
+ base::Passed(backend_ptr.Pass()),
+ weak_ptr_factory_.GetWeakPtr());
+
+ // TODO(jkarlin): Use the cache MessageLoopProxy that ServiceWorkerCacheCore
+ // has for disk caches.
+ int rv = disk_cache::CreateCacheBackend(
+ cache_type,
+ net::CACHE_BACKEND_SIMPLE,
+ path_,
+ kMaxCacheBytes,
+ false, /* force */
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(),
+ NULL,
+ backend,
+ create_cache_callback);
+ if (rv != net::ERR_IO_PENDING)
+ create_cache_callback.Run(rv);
+}
+
+void ServiceWorkerCache::Init(const base::Closure& callback) {
+ DCHECK(!initialized_);
+ init_callbacks_.push_back(callback);
+
+ // If this isn't the first call to Init then return as the initialization
+ // has already started.
+ if (init_callbacks_.size() > 1u)
+ return;
+
+ CreateBackend(base::Bind(&ServiceWorkerCache::InitDone,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void ServiceWorkerCache::InitDone(ErrorType error) {
+ initialized_ = true;
+ for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
+ it != init_callbacks_.end();
+ ++it) {
+ it->Run();
+ }
+ init_callbacks_.clear();
+}
+
+void ServiceWorkerCache::DecPendingOps() {
+ DCHECK(pending_ops_ > 0);
+ pending_ops_--;
+ if (pending_ops_ == 0 && !ops_complete_callback_.is_null()) {
+ ops_complete_callback_.Run();
+ ops_complete_callback_.Reset();
+ }
+}
+
+void ServiceWorkerCache::PendingErrorCallback(const ErrorCallback& callback,
+ ErrorType error) {
+ callback.Run(error);
+ DecPendingOps();
+}
+
+void ServiceWorkerCache::PendingResponseCallback(
+ const ResponseCallback& callback,
+ ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ callback.Run(error, response.Pass(), blob_data_handle.Pass());
+ DecPendingOps();
+}
+
+void ServiceWorkerCache::PendingRequestsCallback(
+ const RequestsCallback& callback,
+ ErrorType error,
+ scoped_ptr<Requests> requests) {
+ callback.Run(error, requests.Pass());
+ DecPendingOps();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache.h b/chromium/content/browser/service_worker/service_worker_cache.h
new file mode 100644
index 00000000000..6683797e992
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache.h
@@ -0,0 +1,195 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "net/base/completion_callback.h"
+#include "net/disk_cache/disk_cache.h"
+
+namespace net {
+class URLRequestContext;
+class IOBufferWithSize;
+}
+
+namespace storage {
+class BlobData;
+class BlobDataHandle;
+class BlobStorageContext;
+class QuotaManagerProxy;
+}
+
+namespace content {
+class ChromeBlobStorageContext;
+class ServiceWorkerCacheMetadata;
+class TestServiceWorkerCache;
+
+// Represents a ServiceWorker Cache as seen in
+// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html.
+// Callbacks to the public functions will be called so long as the cache object
+// lives.
+class CONTENT_EXPORT ServiceWorkerCache
+ : public base::RefCounted<ServiceWorkerCache> {
+ public:
+ enum ErrorType {
+ ErrorTypeOK = 0,
+ ErrorTypeExists,
+ ErrorTypeStorage,
+ ErrorTypeNotFound
+ };
+
+ enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
+ typedef base::Callback<void(ErrorType)> ErrorCallback;
+ typedef base::Callback<void(ErrorType,
+ scoped_ptr<ServiceWorkerResponse>,
+ scoped_ptr<storage::BlobDataHandle>)>
+ ResponseCallback;
+ typedef std::vector<ServiceWorkerFetchRequest> Requests;
+ typedef base::Callback<void(ErrorType, scoped_ptr<Requests>)>
+ RequestsCallback;
+
+ static scoped_refptr<ServiceWorkerCache> CreateMemoryCache(
+ const GURL& origin,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context);
+ static scoped_refptr<ServiceWorkerCache> CreatePersistentCache(
+ const GURL& origin,
+ const base::FilePath& path,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context);
+
+ // Returns ErrorTypeNotFound if not found.
+ void Match(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ResponseCallback& callback);
+
+ // Puts the request and response object in the cache. The response body (if
+ // present) is stored in the cache, but not the request body. Returns
+ // ErrorTypeOK on success.
+ void Put(scoped_ptr<ServiceWorkerFetchRequest> request,
+ scoped_ptr<ServiceWorkerResponse> response,
+ const ResponseCallback& callback);
+
+ // Returns ErrorNotFound if not found. Otherwise deletes and returns
+ // ErrorTypeOK.
+ void Delete(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ErrorCallback& callback);
+
+ // TODO(jkarlin): Have keys take an optional ServiceWorkerFetchRequest.
+ // Returns ErrorTypeOK and a vector of requests if there are no errors.
+ void Keys(const RequestsCallback& callback);
+
+ // Prevents further operations from starting on this object, waits for
+ // existing operations to finish, and then deletes the backend. Close should
+ // only be called once per ServiceWorkerCache.
+ void Close(const base::Closure& callback);
+
+ // The size of the cache contents in memory. Returns 0 if the cache backend is
+ // not a memory cache backend.
+ int64 MemoryBackedSize() const;
+
+ void set_backend(scoped_ptr<disk_cache::Backend> backend) {
+ backend_ = backend.Pass();
+ }
+
+ base::WeakPtr<ServiceWorkerCache> AsWeakPtr();
+
+ private:
+ friend class base::RefCounted<ServiceWorkerCache>;
+ friend class TestServiceWorkerCache;
+
+ class BlobReader;
+ struct KeysContext;
+ struct PutContext;
+ typedef std::vector<disk_cache::Entry*> Entries;
+
+ ServiceWorkerCache(
+ const GURL& origin,
+ const base::FilePath& path,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context);
+
+ // Operations in progress will complete after the cache is deleted but pending
+ // operations (those operations waiting for init to finish) won't.
+ virtual ~ServiceWorkerCache();
+
+ // Put callbacks.
+ static void PutImpl(scoped_ptr<PutContext> put_context);
+ static void PutDidDelete(scoped_ptr<PutContext> put_context,
+ ErrorType delete_error);
+ static void PutDidCreateEntry(scoped_ptr<PutContext> put_context, int rv);
+ static void PutDidWriteHeaders(scoped_ptr<PutContext> put_context,
+ int expected_bytes,
+ int rv);
+ static void PutDidWriteBlobToCache(scoped_ptr<PutContext> put_context,
+ scoped_ptr<BlobReader> blob_reader,
+ disk_cache::ScopedEntryPtr entry,
+ bool success);
+
+ // Static callbacks for the Keys function.
+ static void KeysDidOpenNextEntry(scoped_ptr<KeysContext> keys_context,
+ int rv);
+ static void KeysProcessNextEntry(scoped_ptr<KeysContext> keys_context,
+ const Entries::iterator& iter);
+ static void KeysDidReadMetadata(
+ scoped_ptr<KeysContext> keys_context,
+ const Entries::iterator& iter,
+ scoped_ptr<ServiceWorkerCacheMetadata> metadata);
+
+ // Loads the backend and calls the callback with the result (true for
+ // success). The callback will always be called. Virtual for tests.
+ virtual void CreateBackend(const ErrorCallback& callback);
+
+ void Init(const base::Closure& callback);
+ void InitDone(ErrorType error);
+
+ void IncPendingOps() { pending_ops_++; }
+ void DecPendingOps();
+ void PendingErrorCallback(const ErrorCallback& callback, ErrorType error);
+ void PendingResponseCallback(
+ const ResponseCallback& callback,
+ ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle);
+ void PendingRequestsCallback(const RequestsCallback& callback,
+ ErrorType error,
+ scoped_ptr<Requests> requests);
+
+ // The backend can be deleted via the Close function at any time so always
+ // check for its existence before use.
+ scoped_ptr<disk_cache::Backend> backend_;
+ GURL origin_;
+ base::FilePath path_;
+ net::URLRequestContext* request_context_;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
+ bool initialized_;
+ std::vector<base::Closure> init_callbacks_;
+
+ // Whether or not to store data in disk or memory.
+ bool memory_only_;
+
+ // The number of started operations that have yet to complete.
+ // TODO(jkarlin): pending_ops_ gets double counted on lazy initialization (say
+ // in ::Put). The counting still works but pending_ops_ doesn't accurately
+ // represent the number of operations in flight. Fix this by having the lazy
+ // init callback call a different function than the original caller (::Put).
+ size_t pending_ops_;
+ base::Closure ops_complete_callback_;
+
+ base::WeakPtrFactory<ServiceWorkerCache> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCache);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_cache.proto b/chromium/content/browser/service_worker/service_worker_cache.proto
new file mode 100644
index 00000000000..37b429b0618
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache.proto
@@ -0,0 +1,48 @@
+// Copyright 2014 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 content;
+
+message ServiceWorkerCacheStorageIndex {
+ message Cache {
+ required string name = 1;
+ }
+ repeated Cache cache = 1;
+ optional string origin = 2;
+}
+
+message ServiceWorkerCacheHeaderMap {
+ required string name = 1;
+ required string value = 2;
+}
+
+message ServiceWorkerCacheRequest {
+ required string method = 1;
+ repeated ServiceWorkerCacheHeaderMap headers = 2;
+}
+
+message ServiceWorkerCacheResponse {
+ enum ResponseType {
+ BASIC_TYPE = 0;
+ CORS_TYPE = 1;
+ DEFAULT_TYPE = 2;
+ ERROR_TYPE = 3;
+ OPAQUE_TYPE = 4;
+ }
+
+ required int32 status_code = 1;
+ required string status_text = 2;
+ required ResponseType response_type = 3;
+ repeated ServiceWorkerCacheHeaderMap headers = 4;
+ optional string url = 5;
+}
+
+message ServiceWorkerCacheMetadata {
+ required ServiceWorkerCacheRequest request = 1;
+ required ServiceWorkerCacheResponse response = 2;
+} \ No newline at end of file
diff --git a/chromium/content/browser/service_worker/service_worker_cache_listener.cc b/chromium/content/browser/service_worker/service_worker_cache_listener.cc
new file mode 100644
index 00000000000..e52c940666d
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_listener.cc
@@ -0,0 +1,459 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache_listener.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/service_worker/service_worker_cache.h"
+#include "content/browser/service_worker/service_worker_cache_storage_manager.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_messages.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h"
+
+namespace content {
+
+using blink::WebServiceWorkerCacheError;
+
+namespace {
+
+WebServiceWorkerCacheError ToWebServiceWorkerCacheError(
+ ServiceWorkerCacheStorage::CacheStorageError err) {
+ switch (err) {
+ case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR:
+ NOTREACHED();
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+ case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_IMPLEMENTED:
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+ case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND:
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_EXISTS:
+ return blink::WebServiceWorkerCacheErrorExists;
+ case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_STORAGE:
+ // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's
+ // added.
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ case ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_CLOSING:
+ // TODO(jkarlin): Update this to CACHE_STORAGE_ERROR_CLOSING once that's
+ // added.
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ }
+ NOTREACHED();
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+}
+
+// TODO(jkarlin): ServiceWorkerCache and ServiceWorkerCacheStorage should share
+// an error enum type.
+WebServiceWorkerCacheError CacheErrorToWebServiceWorkerCacheError(
+ ServiceWorkerCache::ErrorType err) {
+ switch (err) {
+ case ServiceWorkerCache::ErrorTypeOK:
+ NOTREACHED();
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+ case ServiceWorkerCache::ErrorTypeExists:
+ return blink::WebServiceWorkerCacheErrorExists;
+ case ServiceWorkerCache::ErrorTypeStorage:
+ // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's
+ // added.
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ case ServiceWorkerCache::ErrorTypeNotFound:
+ return blink::WebServiceWorkerCacheErrorNotFound;
+ }
+ NOTREACHED();
+ return blink::WebServiceWorkerCacheErrorNotImplemented;
+}
+
+} // namespace
+
+ServiceWorkerCacheListener::ServiceWorkerCacheListener(
+ ServiceWorkerVersion* version,
+ base::WeakPtr<ServiceWorkerContextCore> context)
+ : version_(version),
+ context_(context),
+ next_cache_id_(0),
+ weak_factory_(this) {
+ version_->embedded_worker()->AddListener(this);
+}
+
+ServiceWorkerCacheListener::~ServiceWorkerCacheListener() {
+ version_->embedded_worker()->RemoveListener(this);
+}
+
+bool ServiceWorkerCacheListener::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ServiceWorkerCacheListener, message)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageHas,
+ OnCacheStorageHas)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageOpen,
+ OnCacheStorageOpen)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageDelete,
+ OnCacheStorageDelete)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheStorageKeys,
+ OnCacheStorageKeys)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheMatch,
+ OnCacheMatch)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheMatchAll,
+ OnCacheMatchAll)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheKeys,
+ OnCacheKeys)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheBatch,
+ OnCacheBatch)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_CacheClosed,
+ OnCacheClosed)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_BlobDataHandled, OnBlobDataHandled)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageHas(
+ int request_id,
+ const base::string16& cache_name) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerCacheListener::OnCacheStorageHas");
+ context_->cache_manager()->HasCache(
+ version_->scope().GetOrigin(),
+ base::UTF16ToUTF8(cache_name),
+ base::Bind(&ServiceWorkerCacheListener::OnCacheStorageHasCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageOpen(
+ int request_id,
+ const base::string16& cache_name) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerCacheListener::OnCacheStorageOpen");
+ context_->cache_manager()->OpenCache(
+ version_->scope().GetOrigin(),
+ base::UTF16ToUTF8(cache_name),
+ base::Bind(&ServiceWorkerCacheListener::OnCacheStorageOpenCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageDelete(
+ int request_id,
+ const base::string16& cache_name) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerCacheListener::OnCacheStorageDelete");
+ context_->cache_manager()->DeleteCache(
+ version_->scope().GetOrigin(),
+ base::UTF16ToUTF8(cache_name),
+ base::Bind(&ServiceWorkerCacheListener::OnCacheStorageDeleteCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageKeys(int request_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerCacheListener::OnCacheStorageKeys");
+ context_->cache_manager()->EnumerateCaches(
+ version_->scope().GetOrigin(),
+ base::Bind(&ServiceWorkerCacheListener::OnCacheStorageKeysCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheMatch(
+ int request_id,
+ int cache_id,
+ const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerCacheQueryParams& match_params) {
+ IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
+ if (it == id_to_cache_map_.end()) {
+ Send(ServiceWorkerMsg_CacheMatchError(
+ request_id, blink::WebServiceWorkerCacheErrorNotFound));
+ return;
+ }
+
+ scoped_refptr<ServiceWorkerCache> cache = it->second;
+ scoped_ptr<ServiceWorkerFetchRequest> scoped_request(
+ new ServiceWorkerFetchRequest(request.url,
+ request.method,
+ request.headers,
+ request.referrer,
+ request.is_reload));
+ cache->Match(scoped_request.Pass(),
+ base::Bind(&ServiceWorkerCacheListener::OnCacheMatchCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ cache));
+}
+
+void ServiceWorkerCacheListener::OnCacheMatchAll(
+ int request_id,
+ int cache_id,
+ const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerCacheQueryParams& match_params) {
+ // TODO(gavinp,jkarlin): Implement this method.
+ Send(ServiceWorkerMsg_CacheMatchAllError(
+ request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
+}
+
+void ServiceWorkerCacheListener::OnCacheKeys(
+ int request_id,
+ int cache_id,
+ const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerCacheQueryParams& match_params) {
+ IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
+ if (it == id_to_cache_map_.end()) {
+ Send(ServiceWorkerMsg_CacheKeysError(
+ request_id, blink::WebServiceWorkerCacheErrorNotFound));
+ return;
+ }
+
+ scoped_refptr<ServiceWorkerCache> cache = it->second;
+
+ cache->Keys(base::Bind(&ServiceWorkerCacheListener::OnCacheKeysCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ cache));
+}
+
+void ServiceWorkerCacheListener::OnCacheBatch(
+ int request_id,
+ int cache_id,
+ const std::vector<ServiceWorkerBatchOperation>& operations) {
+ if (operations.size() != 1u) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
+ return;
+ }
+
+ IDToCacheMap::iterator it = id_to_cache_map_.find(cache_id);
+ if (it == id_to_cache_map_.end()) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, blink::WebServiceWorkerCacheErrorNotFound));
+ return;
+ }
+
+ const ServiceWorkerBatchOperation& operation = operations[0];
+
+ scoped_refptr<ServiceWorkerCache> cache = it->second;
+ scoped_ptr<ServiceWorkerFetchRequest> scoped_request(
+ new ServiceWorkerFetchRequest(operation.request.url,
+ operation.request.method,
+ operation.request.headers,
+ operation.request.referrer,
+ operation.request.is_reload));
+
+ if (operation.operation_type == SERVICE_WORKER_CACHE_OPERATION_TYPE_DELETE) {
+ cache->Delete(scoped_request.Pass(),
+ base::Bind(&ServiceWorkerCacheListener::OnCacheDeleteCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ cache));
+ return;
+ }
+
+ if (operation.operation_type == SERVICE_WORKER_CACHE_OPERATION_TYPE_PUT) {
+ scoped_ptr<ServiceWorkerResponse> scoped_response(
+ new ServiceWorkerResponse(operation.response.url,
+ operation.response.status_code,
+ operation.response.status_text,
+ operation.response.response_type,
+ operation.response.headers,
+ operation.response.blob_uuid,
+ operation.response.blob_size));
+ cache->Put(scoped_request.Pass(),
+ scoped_response.Pass(),
+ base::Bind(&ServiceWorkerCacheListener::OnCachePutCallback,
+ weak_factory_.GetWeakPtr(),
+ request_id,
+ cache));
+
+ return;
+ }
+
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, blink::WebServiceWorkerCacheErrorNotImplemented));
+}
+
+void ServiceWorkerCacheListener::OnCacheClosed(int cache_id) {
+ DropCacheReference(cache_id);
+}
+
+void ServiceWorkerCacheListener::OnBlobDataHandled(const std::string& uuid) {
+ DropBlobDataHandle(uuid);
+}
+
+void ServiceWorkerCacheListener::Send(const IPC::Message& message) {
+ version_->embedded_worker()->SendMessage(message);
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageHasCallback(
+ int request_id,
+ bool has_cache,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
+ Send(ServiceWorkerMsg_CacheStorageHasError(
+ request_id, ToWebServiceWorkerCacheError(error)));
+ return;
+ }
+ if (!has_cache) {
+ Send(ServiceWorkerMsg_CacheStorageHasError(
+ request_id,
+ blink::WebServiceWorkerCacheErrorNotFound));
+ return;
+ }
+ Send(ServiceWorkerMsg_CacheStorageHasSuccess(request_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageOpenCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
+ Send(ServiceWorkerMsg_CacheStorageOpenError(
+ request_id, ToWebServiceWorkerCacheError(error)));
+ return;
+ }
+ CacheID cache_id = StoreCacheReference(cache);
+ Send(ServiceWorkerMsg_CacheStorageOpenSuccess(request_id, cache_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageDeleteCallback(
+ int request_id,
+ bool deleted,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ if (!deleted ||
+ error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
+ Send(ServiceWorkerMsg_CacheStorageDeleteError(
+ request_id, ToWebServiceWorkerCacheError(error)));
+ return;
+ }
+ Send(ServiceWorkerMsg_CacheStorageDeleteSuccess(request_id));
+}
+
+void ServiceWorkerCacheListener::OnCacheStorageKeysCallback(
+ int request_id,
+ const std::vector<std::string>& strings,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ if (error != ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) {
+ Send(ServiceWorkerMsg_CacheStorageKeysError(
+ request_id, ToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ std::vector<base::string16> string16s;
+ for (size_t i = 0, max = strings.size(); i < max; ++i) {
+ string16s.push_back(base::UTF8ToUTF16(strings[i]));
+ }
+ Send(ServiceWorkerMsg_CacheStorageKeysSuccess(request_id, string16s));
+}
+
+void ServiceWorkerCacheListener::OnCacheMatchCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ if (error != ServiceWorkerCache::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheMatchError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ if (blob_data_handle)
+ StoreBlobDataHandle(blob_data_handle.Pass());
+
+ Send(ServiceWorkerMsg_CacheMatchSuccess(request_id, *response));
+}
+
+void ServiceWorkerCacheListener::OnCacheKeysCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerCache::Requests> requests) {
+ if (error != ServiceWorkerCache::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheKeysError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ ServiceWorkerCache::Requests out;
+
+ for (ServiceWorkerCache::Requests::const_iterator it = requests->begin();
+ it != requests->end();
+ ++it) {
+ ServiceWorkerFetchRequest request(
+ it->url, it->method, it->headers, it->referrer, it->is_reload);
+ out.push_back(request);
+ }
+
+ Send(ServiceWorkerMsg_CacheKeysSuccess(request_id, out));
+}
+
+void ServiceWorkerCacheListener::OnCacheDeleteCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error) {
+ if (error != ServiceWorkerCache::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ Send(ServiceWorkerMsg_CacheBatchSuccess(
+ request_id, std::vector<ServiceWorkerResponse>()));
+}
+
+void ServiceWorkerCacheListener::OnCachePutCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ if (error != ServiceWorkerCache::ErrorTypeOK) {
+ Send(ServiceWorkerMsg_CacheBatchError(
+ request_id, CacheErrorToWebServiceWorkerCacheError(error)));
+ return;
+ }
+
+ if (blob_data_handle)
+ StoreBlobDataHandle(blob_data_handle.Pass());
+
+ std::vector<ServiceWorkerResponse> responses;
+ responses.push_back(*response);
+ Send(ServiceWorkerMsg_CacheBatchSuccess(request_id, responses));
+}
+
+ServiceWorkerCacheListener::CacheID
+ServiceWorkerCacheListener::StoreCacheReference(
+ const scoped_refptr<ServiceWorkerCache>& cache) {
+ int cache_id = next_cache_id_++;
+ id_to_cache_map_[cache_id] = cache;
+ return cache_id;
+}
+
+void ServiceWorkerCacheListener::DropCacheReference(CacheID cache_id) {
+ id_to_cache_map_.erase(cache_id);
+}
+
+void ServiceWorkerCacheListener::StoreBlobDataHandle(
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ DCHECK(blob_data_handle);
+ std::pair<UUIDToBlobDataHandleList::iterator, bool> rv =
+ blob_handle_store_.insert(std::make_pair(
+ blob_data_handle->uuid(), std::list<storage::BlobDataHandle>()));
+ rv.first->second.push_front(storage::BlobDataHandle(*blob_data_handle));
+}
+
+void ServiceWorkerCacheListener::DropBlobDataHandle(std::string uuid) {
+ UUIDToBlobDataHandleList::iterator it = blob_handle_store_.find(uuid);
+ if (it == blob_handle_store_.end())
+ return;
+ DCHECK(!it->second.empty());
+ it->second.pop_front();
+ if (it->second.empty())
+ blob_handle_store_.erase(it);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache_listener.h b/chromium/content/browser/service_worker/service_worker_cache_listener.h
new file mode 100644
index 00000000000..d0364f36d94
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_listener.h
@@ -0,0 +1,150 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_LISTENER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_LISTENER_H_
+
+#include <list>
+#include <map>
+
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/service_worker_cache.h"
+#include "content/browser/service_worker/service_worker_cache_storage.h"
+
+namespace content {
+
+struct ServiceWorkerBatchOperation;
+struct ServiceWorkerCacheQueryParams;
+struct ServiceWorkerFetchRequest;
+class ServiceWorkerVersion;
+
+// This class listens for requests on the Cache APIs, and sends response
+// messages to the renderer process. There is one instance per
+// ServiceWorkerVersion instance.
+class ServiceWorkerCacheListener : public EmbeddedWorkerInstance::Listener {
+ public:
+ ServiceWorkerCacheListener(ServiceWorkerVersion* version,
+ base::WeakPtr<ServiceWorkerContextCore> context);
+ ~ServiceWorkerCacheListener() override;
+
+ // From EmbeddedWorkerInstance::Listener:
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ private:
+ // The message receiver functions for the CacheStorage API:
+ void OnCacheStorageGet(int request_id, const base::string16& cache_name);
+ void OnCacheStorageHas(int request_id, const base::string16& cache_name);
+ void OnCacheStorageCreate(int request_id,
+ const base::string16& cache_name);
+ void OnCacheStorageOpen(int request_id, const base::string16& cache_name);
+ void OnCacheStorageDelete(int request_id,
+ const base::string16& cache_name);
+ void OnCacheStorageKeys(int request_id);
+
+ // The message receiver functions for the Cache API:
+ void OnCacheMatch(int request_id,
+ int cache_id,
+ const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerCacheQueryParams& match_params);
+ void OnCacheMatchAll(int request_id,
+ int cache_id,
+ const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerCacheQueryParams& match_params);
+ void OnCacheKeys(int request_id,
+ int cache_id,
+ const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerCacheQueryParams& match_params);
+ void OnCacheBatch(int request_id,
+ int cache_id,
+ const std::vector<ServiceWorkerBatchOperation>& operations);
+ void OnCacheClosed(int cache_id);
+ void OnBlobDataHandled(const std::string& uuid);
+
+ private:
+ typedef int32_t CacheID; // TODO(jkarlin): Bump to 64 bit.
+ typedef std::map<CacheID, scoped_refptr<ServiceWorkerCache>> IDToCacheMap;
+ typedef std::map<std::string, std::list<storage::BlobDataHandle>>
+ UUIDToBlobDataHandleList;
+
+ void Send(const IPC::Message& message);
+
+ // CacheStorageManager callbacks
+ void OnCacheStorageGetCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCacheStorage::CacheStorageError error);
+ void OnCacheStorageHasCallback(
+ int request_id,
+ bool has_cache,
+ ServiceWorkerCacheStorage::CacheStorageError error);
+ void OnCacheStorageCreateCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCacheStorage::CacheStorageError error);
+ void OnCacheStorageOpenCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCacheStorage::CacheStorageError error);
+ void OnCacheStorageDeleteCallback(
+ int request_id,
+ bool deleted,
+ ServiceWorkerCacheStorage::CacheStorageError error);
+ void OnCacheStorageKeysCallback(
+ int request_id,
+ const std::vector<std::string>& strings,
+ ServiceWorkerCacheStorage::CacheStorageError error);
+
+ // Cache callbacks
+ void OnCacheMatchCallback(
+ int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle);
+ void OnCacheKeysCallback(int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerCache::Requests> requests);
+ void OnCacheDeleteCallback(int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error);
+ void OnCachePutCallback(int request_id,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle);
+
+ // Hangs onto a scoped_refptr for the cache if it isn't already doing so.
+ // Returns a unique cache_id. Call DropCacheReference when the client is done
+ // with this cache.
+ CacheID StoreCacheReference(const scoped_refptr<ServiceWorkerCache>& cache);
+ void DropCacheReference(CacheID cache_id);
+
+ // Stores blob handles while waiting for acknowledgement of receipt from the
+ // renderer.
+ void StoreBlobDataHandle(
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle);
+ void DropBlobDataHandle(std::string uuid);
+
+ // The ServiceWorkerVersion to use for messaging back to the renderer thread.
+ ServiceWorkerVersion* version_;
+
+ // The ServiceWorkerContextCore should always outlive this.
+ base::WeakPtr<ServiceWorkerContextCore> context_;
+
+ IDToCacheMap id_to_cache_map_;
+ CacheID next_cache_id_;
+
+ UUIDToBlobDataHandleList blob_handle_store_;
+
+ base::WeakPtrFactory<ServiceWorkerCacheListener> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheListener);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_LISTENER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_cache_quota_client.cc b/chromium/content/browser/service_worker/service_worker_cache_quota_client.cc
new file mode 100644
index 00000000000..c7ed1c0cbd8
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_quota_client.cc
@@ -0,0 +1,97 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache_quota_client.h"
+
+#include "content/browser/service_worker/service_worker_cache_storage_manager.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+ServiceWorkerCacheQuotaClient::ServiceWorkerCacheQuotaClient(
+ base::WeakPtr<ServiceWorkerCacheStorageManager> cache_manager)
+ : cache_manager_(cache_manager) {
+}
+
+ServiceWorkerCacheQuotaClient::~ServiceWorkerCacheQuotaClient() {
+}
+
+storage::QuotaClient::ID ServiceWorkerCacheQuotaClient::id() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return kServiceWorkerCache;
+}
+
+void ServiceWorkerCacheQuotaClient::OnQuotaManagerDestroyed() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ delete this;
+}
+
+void ServiceWorkerCacheQuotaClient::GetOriginUsage(
+ const GURL& origin_url,
+ storage::StorageType type,
+ const GetUsageCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!cache_manager_ || !DoesSupport(type)) {
+ callback.Run(0);
+ return;
+ }
+
+ cache_manager_->GetOriginUsage(origin_url, callback);
+}
+
+void ServiceWorkerCacheQuotaClient::GetOriginsForType(
+ storage::StorageType type,
+ const GetOriginsCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!cache_manager_ || !DoesSupport(type)) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+
+ cache_manager_->GetOrigins(callback);
+}
+
+void ServiceWorkerCacheQuotaClient::GetOriginsForHost(
+ storage::StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!cache_manager_ || !DoesSupport(type)) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+
+ cache_manager_->GetOriginsForHost(host, callback);
+}
+
+void ServiceWorkerCacheQuotaClient::DeleteOriginData(
+ const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!cache_manager_) {
+ callback.Run(storage::kQuotaErrorAbort);
+ return;
+ }
+
+ if (!DoesSupport(type)) {
+ callback.Run(storage::kQuotaStatusOk);
+ return;
+ }
+
+ cache_manager_->DeleteOriginData(origin, callback);
+}
+
+bool ServiceWorkerCacheQuotaClient::DoesSupport(
+ storage::StorageType type) const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ return type == storage::kStorageTypeTemporary;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache_quota_client.h b/chromium/content/browser/service_worker/service_worker_cache_quota_client.h
new file mode 100644
index 00000000000..82111497b84
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_quota_client.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_QUOTA_CLIENT_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_QUOTA_CLIENT_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/common/quota/quota_types.h"
+
+namespace storage {
+class QuotaManagerProxy;
+}
+
+namespace content {
+class ServiceWorkerCacheStorageManager;
+
+// ServiceWorkerCacheQuotaClient is owned by the QuotaManager. There is one per
+// ServiceWorkerCacheStorageManager, and therefore one per
+// ServiceWorkerContextCore.
+class CONTENT_EXPORT ServiceWorkerCacheQuotaClient
+ : public storage::QuotaClient {
+ public:
+ explicit ServiceWorkerCacheQuotaClient(
+ base::WeakPtr<ServiceWorkerCacheStorageManager> cache_manager);
+ ~ServiceWorkerCacheQuotaClient() override;
+
+ // QuotaClient overrides
+ ID id() const override;
+ void OnQuotaManagerDestroyed() override;
+ void GetOriginUsage(const GURL& origin_url,
+ storage::StorageType type,
+ const GetUsageCallback& callback) override;
+ void GetOriginsForType(storage::StorageType type,
+ const GetOriginsCallback& callback) override;
+ void GetOriginsForHost(storage::StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) override;
+ void DeleteOriginData(const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) override;
+ bool DoesSupport(storage::StorageType type) const override;
+
+ private:
+ base::WeakPtr<ServiceWorkerCacheStorageManager> cache_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheQuotaClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_QUOTA_CLIENT_H_
diff --git a/chromium/content/browser/service_worker/service_worker_cache_storage.cc b/chromium/content/browser/service_worker/service_worker_cache_storage.cc
new file mode 100644
index 00000000000..62adb60dfbc
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_storage.cc
@@ -0,0 +1,683 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache_storage.h"
+
+#include <string>
+
+#include "base/barrier_closure.h"
+#include "base/files/file_util.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/memory/ref_counted.h"
+#include "base/sha1.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "content/browser/service_worker/service_worker_cache.h"
+#include "content/browser/service_worker/service_worker_cache.pb.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/directory_lister.h"
+#include "net/base/net_errors.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+
+namespace content {
+
+namespace {
+
+void CloseAllCachesDidCloseCache(const scoped_refptr<ServiceWorkerCache>& cache,
+ const base::Closure& barrier_closure) {
+ barrier_closure.Run();
+}
+
+} // namespace
+
+const char ServiceWorkerCacheStorage::kIndexFileName[] = "index.txt";
+
+// Handles the loading and clean up of ServiceWorkerCache objects. The
+// callback of every public method is guaranteed to be called.
+class ServiceWorkerCacheStorage::CacheLoader {
+ public:
+ typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)>
+ CacheCallback;
+ typedef base::Callback<void(bool)> BoolCallback;
+ typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)>
+ StringVectorCallback;
+
+ CacheLoader(
+ base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin)
+ : cache_task_runner_(cache_task_runner),
+ request_context_(request_context),
+ quota_manager_proxy_(quota_manager_proxy),
+ blob_context_(blob_context),
+ origin_(origin) {
+ DCHECK(!origin_.is_empty());
+ }
+
+ virtual ~CacheLoader() {}
+
+ // Creates a ServiceWorkerCache with the given name. It does not attempt to
+ // load the backend, that happens lazily when the cache is used.
+ virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
+ const std::string& cache_name) = 0;
+
+ // Deletes any pre-existing cache of the same name and then loads it.
+ virtual void CreateCache(const std::string& cache_name,
+ const CacheCallback& callback) = 0;
+
+ // After the backend has been deleted, do any extra house keeping such as
+ // removing the cache's directory.
+ virtual void CleanUpDeletedCache(const std::string& key,
+ const BoolCallback& callback) = 0;
+
+ // Writes the cache names (and sizes) to disk if applicable.
+ virtual void WriteIndex(const StringVector& cache_names,
+ const BoolCallback& callback) = 0;
+
+ // Loads the cache names from disk if applicable.
+ virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names,
+ const StringVectorCallback& callback) = 0;
+
+ protected:
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
+ net::URLRequestContext* request_context_;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+ base::WeakPtr<storage::BlobStorageContext> blob_context_;
+ GURL origin_;
+};
+
+// Creates memory-only ServiceWorkerCaches. Because these caches have no
+// persistent storage it is not safe to free them from memory if they might be
+// used again. Therefore this class holds a reference to each cache until the
+// cache is deleted.
+class ServiceWorkerCacheStorage::MemoryLoader
+ : public ServiceWorkerCacheStorage::CacheLoader {
+ public:
+ MemoryLoader(
+ base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin)
+ : CacheLoader(cache_task_runner,
+ request_context,
+ quota_manager_proxy,
+ blob_context,
+ origin) {}
+
+ scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
+ const std::string& cache_name) override {
+ return ServiceWorkerCache::CreateMemoryCache(
+ origin_, request_context_, quota_manager_proxy_, blob_context_);
+ }
+
+ void CreateCache(const std::string& cache_name,
+ const CacheCallback& callback) override {
+ scoped_refptr<ServiceWorkerCache> cache =
+ CreateServiceWorkerCache(cache_name);
+ cache_refs_.insert(std::make_pair(cache_name, cache));
+ callback.Run(cache);
+ }
+
+ void CleanUpDeletedCache(const std::string& cache_name,
+ const BoolCallback& callback) override {
+ CacheRefMap::iterator it = cache_refs_.find(cache_name);
+ DCHECK(it != cache_refs_.end());
+ cache_refs_.erase(it);
+ callback.Run(true);
+ }
+
+ void WriteIndex(const StringVector& cache_names,
+ const BoolCallback& callback) override {
+ callback.Run(false);
+ }
+
+ void LoadIndex(scoped_ptr<std::vector<std::string>> cache_names,
+ const StringVectorCallback& callback) override {
+ callback.Run(cache_names.Pass());
+ }
+
+ private:
+ typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap;
+ ~MemoryLoader() override {}
+
+ // Keep a reference to each cache to ensure that it's not freed before the
+ // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is
+ // freed.
+ CacheRefMap cache_refs_;
+};
+
+class ServiceWorkerCacheStorage::SimpleCacheLoader
+ : public ServiceWorkerCacheStorage::CacheLoader {
+ public:
+ SimpleCacheLoader(
+ const base::FilePath& origin_path,
+ base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin)
+ : CacheLoader(cache_task_runner,
+ request_context,
+ quota_manager_proxy,
+ blob_context,
+ origin),
+ origin_path_(origin_path),
+ weak_ptr_factory_(this) {}
+
+ scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache(
+ const std::string& cache_name) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ return ServiceWorkerCache::CreatePersistentCache(
+ origin_,
+ CreatePersistentCachePath(origin_path_, cache_name),
+ request_context_,
+ quota_manager_proxy_,
+ blob_context_);
+ }
+
+ void CreateCache(const std::string& cache_name,
+ const CacheCallback& callback) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // 1. Delete the cache's directory if it exists.
+ // (CreateCacheDeleteFilesInPool)
+ // 2. Load the cache. (LoadCreateDirectoryInPool)
+
+ base::FilePath cache_path =
+ CreatePersistentCachePath(origin_path_, cache_name);
+
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&SimpleCacheLoader::CreateCachePrepDirInPool, cache_path),
+ base::Bind(&SimpleCacheLoader::CreateCachePreppedDir,
+ cache_name,
+ callback,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ static bool CreateCachePrepDirInPool(const base::FilePath& cache_path) {
+ if (base::PathExists(cache_path))
+ base::DeleteFile(cache_path, /* recursive */ true);
+ return base::CreateDirectory(cache_path);
+ }
+
+ static void CreateCachePreppedDir(const std::string& cache_name,
+ const CacheCallback& callback,
+ base::WeakPtr<SimpleCacheLoader> loader,
+ bool success) {
+ if (!success || !loader) {
+ callback.Run(scoped_refptr<ServiceWorkerCache>());
+ return;
+ }
+
+ callback.Run(loader->CreateServiceWorkerCache(cache_name));
+ }
+
+ void CleanUpDeletedCache(const std::string& cache_name,
+ const BoolCallback& callback) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // 1. Delete the cache's directory. (CleanUpDeleteCacheDirInPool)
+
+ base::FilePath cache_path =
+ CreatePersistentCachePath(origin_path_, cache_name);
+ cache_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool,
+ cache_path,
+ callback,
+ base::MessageLoopProxy::current()));
+ }
+
+ static void CleanUpDeleteCacheDirInPool(
+ const base::FilePath& cache_path,
+ const BoolCallback& callback,
+ const scoped_refptr<base::MessageLoopProxy>& original_loop) {
+ bool rv = base::DeleteFile(cache_path, true);
+ original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
+ }
+
+ void WriteIndex(const StringVector& cache_names,
+ const BoolCallback& callback) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // 1. Create the index file as a string. (WriteIndex)
+ // 2. Write the file to disk. (WriteIndexWriteToFileInPool)
+
+ ServiceWorkerCacheStorageIndex index;
+ index.set_origin(origin_.spec());
+
+ for (size_t i = 0u, max = cache_names.size(); i < max; ++i) {
+ ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache();
+ index_cache->set_name(cache_names[i]);
+ }
+
+ std::string serialized;
+ bool success = index.SerializeToString(&serialized);
+ DCHECK(success);
+
+ base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
+ base::FilePath index_path =
+ origin_path_.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName);
+
+ cache_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
+ tmp_path,
+ index_path,
+ serialized,
+ callback,
+ base::MessageLoopProxy::current()));
+ }
+
+ static void WriteIndexWriteToFileInPool(
+ const base::FilePath& tmp_path,
+ const base::FilePath& index_path,
+ const std::string& data,
+ const BoolCallback& callback,
+ const scoped_refptr<base::MessageLoopProxy>& original_loop) {
+ int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
+ if (bytes_written != implicit_cast<int>(data.size())) {
+ base::DeleteFile(tmp_path, /* recursive */ false);
+ original_loop->PostTask(FROM_HERE, base::Bind(callback, false));
+ }
+
+ // Atomically rename the temporary index file to become the real one.
+ bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
+ original_loop->PostTask(FROM_HERE, base::Bind(callback, rv));
+ }
+
+ void LoadIndex(scoped_ptr<std::vector<std::string>> names,
+ const StringVectorCallback& callback) override {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // 1. Read the file from disk. (LoadIndexReadFileInPool)
+ // 2. Parse file and return the names of the caches (LoadIndexDidReadFile)
+
+ base::FilePath index_path =
+ origin_path_.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName);
+
+ cache_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool,
+ index_path,
+ base::Passed(names.Pass()),
+ callback,
+ base::MessageLoopProxy::current()));
+ }
+
+ static void LoadIndexReadFileInPool(
+ const base::FilePath& index_path,
+ scoped_ptr<std::vector<std::string> > names,
+ const StringVectorCallback& callback,
+ const scoped_refptr<base::MessageLoopProxy>& original_loop) {
+ std::string body;
+ base::ReadFileToString(index_path, &body);
+
+ original_loop->PostTask(FROM_HERE,
+ base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile,
+ base::Passed(names.Pass()),
+ callback,
+ body));
+ }
+
+ static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names,
+ const StringVectorCallback& callback,
+ const std::string& serialized) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerCacheStorageIndex index;
+ if (index.ParseFromString(serialized)) {
+ for (int i = 0, max = index.cache_size(); i < max; ++i) {
+ const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
+ names->push_back(cache.name());
+ }
+ }
+
+ // TODO(jkarlin): Delete caches that are in the directory and not returned
+ // in LoadIndex.
+ callback.Run(names.Pass());
+ }
+
+ private:
+ ~SimpleCacheLoader() override {}
+
+ static std::string HexedHash(const std::string& value) {
+ std::string value_hash = base::SHA1HashString(value);
+ std::string valued_hexed_hash = base::StringToLowerASCII(
+ base::HexEncode(value_hash.c_str(), value_hash.length()));
+ return valued_hexed_hash;
+ }
+
+ static base::FilePath CreatePersistentCachePath(
+ const base::FilePath& origin_path,
+ const std::string& cache_name) {
+ return origin_path.AppendASCII(HexedHash(cache_name));
+ }
+
+ const base::FilePath origin_path_;
+
+ base::WeakPtrFactory<SimpleCacheLoader> weak_ptr_factory_;
+};
+
+ServiceWorkerCacheStorage::ServiceWorkerCacheStorage(
+ const base::FilePath& path,
+ bool memory_only,
+ base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin)
+ : initialized_(false),
+ origin_path_(path),
+ cache_task_runner_(cache_task_runner),
+ memory_only_(memory_only),
+ weak_factory_(this) {
+ if (memory_only)
+ cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
+ request_context,
+ quota_manager_proxy,
+ blob_context,
+ origin));
+ else
+ cache_loader_.reset(new SimpleCacheLoader(origin_path_,
+ cache_task_runner_.get(),
+ request_context,
+ quota_manager_proxy,
+ blob_context,
+ origin));
+}
+
+ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() {
+}
+
+void ServiceWorkerCacheStorage::OpenCache(
+ const std::string& cache_name,
+ const CacheAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_) {
+ LazyInit(base::Bind(&ServiceWorkerCacheStorage::OpenCache,
+ weak_factory_.GetWeakPtr(),
+ cache_name,
+ callback));
+ return;
+ }
+
+ scoped_refptr<ServiceWorkerCache> cache = GetLoadedCache(cache_name);
+ if (cache.get()) {
+ callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
+ return;
+ }
+
+ cache_loader_->CreateCache(
+ cache_name,
+ base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache,
+ weak_factory_.GetWeakPtr(),
+ cache_name,
+ callback));
+}
+
+void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name,
+ const BoolAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_) {
+ LazyInit(base::Bind(&ServiceWorkerCacheStorage::HasCache,
+ weak_factory_.GetWeakPtr(),
+ cache_name,
+ callback));
+ return;
+ }
+
+ bool has_cache = cache_map_.find(cache_name) != cache_map_.end();
+
+ callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR);
+}
+
+void ServiceWorkerCacheStorage::DeleteCache(
+ const std::string& cache_name,
+ const BoolAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_) {
+ LazyInit(base::Bind(&ServiceWorkerCacheStorage::DeleteCache,
+ weak_factory_.GetWeakPtr(),
+ cache_name,
+ callback));
+ return;
+ }
+
+ CacheMap::iterator it = cache_map_.find(cache_name);
+ if (it == cache_map_.end()) {
+ callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
+ return;
+ }
+
+ base::WeakPtr<ServiceWorkerCache> cache = it->second;
+ cache_map_.erase(it);
+
+ // Delete the name from ordered_cache_names_.
+ StringVector::iterator iter = std::find(
+ ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name);
+ DCHECK(iter != ordered_cache_names_.end());
+ ordered_cache_names_.erase(iter);
+
+ base::Closure closure =
+ base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidClose,
+ weak_factory_.GetWeakPtr(), cache_name, callback,
+ ordered_cache_names_, make_scoped_refptr(cache.get()));
+
+ if (cache) {
+ cache->Close(closure);
+ return;
+ }
+
+ closure.Run();
+}
+
+void ServiceWorkerCacheStorage::EnumerateCaches(
+ const StringsAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_) {
+ LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches,
+ weak_factory_.GetWeakPtr(),
+ callback));
+ return;
+ }
+
+ callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR);
+}
+
+void ServiceWorkerCacheStorage::CloseAllCaches(const base::Closure& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_) {
+ callback.Run();
+ return;
+ }
+
+ int live_cache_count = 0;
+ for (const auto& key_value : cache_map_) {
+ if (key_value.second)
+ live_cache_count += 1;
+ }
+
+ if (live_cache_count == 0) {
+ callback.Run();
+ return;
+ }
+
+ // The closure might modify this object so delay calling it until after
+ // iterating through cache_map_ by adding one to the barrier.
+ base::Closure barrier_closure =
+ base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
+
+ for (auto& key_value : cache_map_) {
+ if (key_value.second) {
+ key_value.second->Close(base::Bind(
+ CloseAllCachesDidCloseCache,
+ make_scoped_refptr(key_value.second.get()), barrier_closure));
+ }
+ }
+
+ barrier_closure.Run();
+}
+
+int64 ServiceWorkerCacheStorage::MemoryBackedSize() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!initialized_ || !memory_only_)
+ return 0;
+
+ int64 sum = 0;
+ for (auto& key_value : cache_map_) {
+ if (key_value.second)
+ sum += key_value.second->MemoryBackedSize();
+ }
+ return sum;
+}
+
+// Init is run lazily so that it is called on the proper MessageLoop.
+void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!initialized_);
+
+ init_callbacks_.push_back(callback);
+
+ // If this isn't the first call to LazyInit then return as the initialization
+ // has already started.
+ if (init_callbacks_.size() > 1u)
+ return;
+
+ // 1. Get the list of cache names (async call)
+ // 2. For each cache name, load the cache (async call)
+ // 3. Once each load is complete, update the map variables.
+ // 4. Call the list of waiting callbacks.
+
+ scoped_ptr<std::vector<std::string> > indexed_cache_names(
+ new std::vector<std::string>());
+
+ cache_loader_->LoadIndex(
+ indexed_cache_names.Pass(),
+ base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
+void ServiceWorkerCacheStorage::LazyInitDidLoadIndex(
+ const base::Closure& callback,
+ scoped_ptr<std::vector<std::string> > indexed_cache_names) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) {
+ cache_map_.insert(std::make_pair(indexed_cache_names->at(i),
+ base::WeakPtr<ServiceWorkerCache>()));
+ ordered_cache_names_.push_back(indexed_cache_names->at(i));
+ }
+
+ initialized_ = true;
+ for (std::vector<base::Closure>::iterator it = init_callbacks_.begin();
+ it != init_callbacks_.end();
+ ++it) {
+ it->Run();
+ }
+ init_callbacks_.clear();
+}
+
+void ServiceWorkerCacheStorage::CreateCacheDidCreateCache(
+ const std::string& cache_name,
+ const CacheAndErrorCallback& callback,
+ const scoped_refptr<ServiceWorkerCache>& cache) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!cache.get()) {
+ callback.Run(scoped_refptr<ServiceWorkerCache>(),
+ CACHE_STORAGE_ERROR_CLOSING);
+ return;
+ }
+
+ cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr()));
+ ordered_cache_names_.push_back(cache_name);
+
+ cache_loader_->WriteIndex(
+ ordered_cache_names_,
+ base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ cache));
+}
+
+void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex(
+ const CacheAndErrorCallback& callback,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(cache.get());
+
+ callback.Run(cache, CACHE_STORAGE_ERROR_NO_ERROR);
+}
+
+void ServiceWorkerCacheStorage::DeleteCacheDidClose(
+ const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ const StringVector& ordered_cache_names,
+ const scoped_refptr<ServiceWorkerCache>& cache /* might be null */) {
+ cache_loader_->WriteIndex(
+ ordered_cache_names,
+ base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex,
+ weak_factory_.GetWeakPtr(), cache_name, callback));
+}
+
+void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex(
+ const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ cache_loader_->CleanUpDeletedCache(
+ cache_name,
+ base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
+void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp(
+ const BoolAndErrorCallback& callback,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR);
+}
+
+scoped_refptr<ServiceWorkerCache> ServiceWorkerCacheStorage::GetLoadedCache(
+ const std::string& cache_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(initialized_);
+
+ CacheMap::iterator map_iter = cache_map_.find(cache_name);
+ if (map_iter == cache_map_.end())
+ return scoped_refptr<ServiceWorkerCache>();
+
+ base::WeakPtr<ServiceWorkerCache> cache = map_iter->second;
+
+ if (!cache) {
+ scoped_refptr<ServiceWorkerCache> new_cache =
+ cache_loader_->CreateServiceWorkerCache(cache_name);
+ map_iter->second = new_cache->AsWeakPtr();
+ return new_cache;
+ }
+
+ return make_scoped_refptr(cache.get());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache_storage.h b/chromium/content/browser/service_worker/service_worker_cache_storage.h
new file mode 100644
index 00000000000..a102707356f
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_storage.h
@@ -0,0 +1,165 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_H_
+
+#include <map>
+#include <string>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_cache.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace net {
+class URLRequestContext;
+}
+
+namespace storage {
+class BlobStorageContext;
+}
+
+namespace content {
+
+// TODO(jkarlin): Constrain the total bytes used per origin.
+
+// ServiceWorkerCacheStorage holds the set of caches for a given origin. It is
+// owned by the ServiceWorkerCacheStorageManager. This class expects to be run
+// on the IO thread.
+class CONTENT_EXPORT ServiceWorkerCacheStorage {
+ public:
+ enum CacheStorageError {
+ CACHE_STORAGE_ERROR_NO_ERROR,
+ CACHE_STORAGE_ERROR_NOT_IMPLEMENTED,
+ CACHE_STORAGE_ERROR_NOT_FOUND,
+ CACHE_STORAGE_ERROR_EXISTS,
+ CACHE_STORAGE_ERROR_STORAGE,
+ CACHE_STORAGE_ERROR_CLOSING
+ };
+ typedef std::vector<std::string> StringVector;
+ typedef base::Callback<void(bool, CacheStorageError)> BoolAndErrorCallback;
+ typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&,
+ CacheStorageError)> CacheAndErrorCallback;
+ typedef base::Callback<void(const StringVector&, CacheStorageError)>
+ StringsAndErrorCallback;
+
+ static const char kIndexFileName[];
+
+ ServiceWorkerCacheStorage(
+ const base::FilePath& origin_path,
+ bool memory_only,
+ base::SequencedTaskRunner* cache_task_runner,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin);
+
+ // Any unfinished asynchronous operations may not complete or call their
+ // callbacks.
+ virtual ~ServiceWorkerCacheStorage();
+
+ // Get the cache for the given key. If the cache is not found it is
+ // created.
+ void OpenCache(const std::string& cache_name,
+ const CacheAndErrorCallback& callback);
+
+ // Calls the callback with whether or not the cache exists.
+ void HasCache(const std::string& cache_name,
+ const BoolAndErrorCallback& callback);
+
+ // Deletes the cache if it exists. If it doesn't exist,
+ // CACHE_STORAGE_ERROR_NOT_FOUND is returned.
+ void DeleteCache(const std::string& cache_name,
+ const BoolAndErrorCallback& callback);
+
+ // Calls the callback with a vector of cache names (keys) available.
+ void EnumerateCaches(const StringsAndErrorCallback& callback);
+
+ // TODO(jkarlin): Add match() function.
+
+ void CloseAllCaches(const base::Closure& callback);
+
+ // The size of all of the origin's contents in memory. Returns 0 if the cache
+ // backend is not a memory backend.
+ int64 MemoryBackedSize() const;
+
+ private:
+ class MemoryLoader;
+ class SimpleCacheLoader;
+ class CacheLoader;
+
+ typedef std::map<std::string, base::WeakPtr<ServiceWorkerCache> > CacheMap;
+
+ // Return a ServiceWorkerCache for the given name if the name is known. If the
+ // ServiceWorkerCache has been deleted, creates a new one.
+ scoped_refptr<ServiceWorkerCache> GetLoadedCache(
+ const std::string& cache_name);
+
+ // Initializer and its callback are below. While LazyInit is running any new
+ // operations will be queued and started in order after initialization.
+ void LazyInit(const base::Closure& closure);
+ void LazyInitDidLoadIndex(
+ const base::Closure& callback,
+ scoped_ptr<std::vector<std::string> > indexed_cache_names);
+
+ void AddCacheToMap(const std::string& cache_name,
+ base::WeakPtr<ServiceWorkerCache> cache);
+
+ // The CreateCache callbacks are below.
+ void CreateCacheDidCreateCache(
+ const std::string& cache_name,
+ const CacheAndErrorCallback& callback,
+ const scoped_refptr<ServiceWorkerCache>& cache);
+ void CreateCacheDidWriteIndex(const CacheAndErrorCallback& callback,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ bool success);
+
+ // The DeleteCache callbacks are below.
+ void DeleteCacheDidClose(const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ const StringVector& ordered_cache_names,
+ const scoped_refptr<ServiceWorkerCache>& cache);
+ void DeleteCacheDidWriteIndex(const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ bool success);
+ void DeleteCacheDidCleanUp(const BoolAndErrorCallback& callback,
+ bool success);
+
+ // Whether or not we've loaded the list of cache names into memory.
+ bool initialized_;
+
+ // The list of operations waiting on initialization.
+ std::vector<base::Closure> init_callbacks_;
+
+ // The map of cache names to ServiceWorkerCache objects.
+ CacheMap cache_map_;
+
+ // The names of caches in the order that they were created.
+ StringVector ordered_cache_names_;
+
+ // The file path for this CacheStorage.
+ base::FilePath origin_path_;
+
+ // The TaskRunner to run file IO on.
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
+
+ // Whether or not to store data in disk or memory.
+ bool memory_only_;
+
+ // Performs backend specific operations (memory vs disk).
+ scoped_ptr<CacheLoader> cache_loader_;
+
+ base::WeakPtrFactory<ServiceWorkerCacheStorage> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheStorage);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_cache_storage_manager.cc b/chromium/content/browser/service_worker/service_worker_cache_storage_manager.cc
new file mode 100644
index 00000000000..3c3203dc507
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_storage_manager.cc
@@ -0,0 +1,325 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache_storage_manager.h"
+
+#include <map>
+#include <string>
+
+#include "base/bind.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/id_map.h"
+#include "base/sha1.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "content/browser/service_worker/service_worker_cache.pb.h"
+#include "content/browser/service_worker/service_worker_cache_quota_client.h"
+#include "content/browser/service_worker/service_worker_cache_storage.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/net_util.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/quota/quota_status_code.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+base::FilePath ConstructOriginPath(const base::FilePath& root_path,
+ const GURL& origin) {
+ std::string origin_hash = base::SHA1HashString(origin.spec());
+ std::string origin_hash_hex = base::StringToLowerASCII(
+ base::HexEncode(origin_hash.c_str(), origin_hash.length()));
+ return root_path.AppendASCII(origin_hash_hex);
+}
+
+bool DeleteDir(const base::FilePath& path) {
+ return base::DeleteFile(path, true /* recursive */);
+}
+
+void DeleteOriginDidDeleteDir(
+ const storage::QuotaClient::DeletionCallback& callback,
+ bool rv) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ callback.Run(rv ? storage::kQuotaStatusOk : storage::kQuotaErrorAbort);
+}
+
+std::set<GURL> ListOriginsOnDisk(base::FilePath root_path_) {
+ std::set<GURL> origins;
+ base::FileEnumerator file_enum(
+ root_path_, false /* recursive */, base::FileEnumerator::DIRECTORIES);
+
+ base::FilePath path;
+ while (!(path = file_enum.Next()).empty()) {
+ std::string protobuf;
+ base::ReadFileToString(
+ path.AppendASCII(ServiceWorkerCacheStorage::kIndexFileName), &protobuf);
+
+ ServiceWorkerCacheStorageIndex index;
+ if (index.ParseFromString(protobuf)) {
+ if (index.has_origin())
+ origins.insert(GURL(index.origin()));
+ }
+ }
+
+ return origins;
+}
+
+void GetOriginsForHostDidListOrigins(
+ const std::string& host,
+ const storage::QuotaClient::GetOriginsCallback& callback,
+ const std::set<GURL>& origins) {
+ std::set<GURL> out_origins;
+ for (const GURL& origin : origins) {
+ if (host == net::GetHostOrSpecFromURL(origin))
+ out_origins.insert(origin);
+ }
+ callback.Run(out_origins);
+}
+
+} // namespace
+
+// static
+scoped_ptr<ServiceWorkerCacheStorageManager>
+ServiceWorkerCacheStorageManager::Create(
+ const base::FilePath& path,
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy) {
+ base::FilePath root_path = path;
+ if (!path.empty()) {
+ root_path = path.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ .AppendASCII("CacheStorage");
+ }
+
+ return make_scoped_ptr(new ServiceWorkerCacheStorageManager(
+ root_path, cache_task_runner, quota_manager_proxy));
+}
+
+// static
+scoped_ptr<ServiceWorkerCacheStorageManager>
+ServiceWorkerCacheStorageManager::Create(
+ ServiceWorkerCacheStorageManager* old_manager) {
+ scoped_ptr<ServiceWorkerCacheStorageManager> manager(
+ new ServiceWorkerCacheStorageManager(
+ old_manager->root_path(),
+ old_manager->cache_task_runner(),
+ old_manager->quota_manager_proxy_.get()));
+ // These values may be NULL, in which case this will be called again later by
+ // the dispatcher host per usual.
+ manager->SetBlobParametersForCache(old_manager->url_request_context(),
+ old_manager->blob_storage_context());
+ return manager.Pass();
+}
+
+ServiceWorkerCacheStorageManager::~ServiceWorkerCacheStorageManager() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (ServiceWorkerCacheStorageMap::iterator it = cache_storage_map_.begin();
+ it != cache_storage_map_.end();
+ ++it) {
+ delete it->second;
+ }
+}
+
+void ServiceWorkerCacheStorageManager::OpenCache(
+ const GURL& origin,
+ const std::string& cache_name,
+ const ServiceWorkerCacheStorage::CacheAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerCacheStorage* cache_storage =
+ FindOrCreateServiceWorkerCacheManager(origin);
+
+ cache_storage->OpenCache(cache_name, callback);
+}
+
+void ServiceWorkerCacheStorageManager::HasCache(
+ const GURL& origin,
+ const std::string& cache_name,
+ const ServiceWorkerCacheStorage::BoolAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerCacheStorage* cache_storage =
+ FindOrCreateServiceWorkerCacheManager(origin);
+ cache_storage->HasCache(cache_name, callback);
+}
+
+void ServiceWorkerCacheStorageManager::DeleteCache(
+ const GURL& origin,
+ const std::string& cache_name,
+ const ServiceWorkerCacheStorage::BoolAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerCacheStorage* cache_storage =
+ FindOrCreateServiceWorkerCacheManager(origin);
+ cache_storage->DeleteCache(cache_name, callback);
+}
+
+void ServiceWorkerCacheStorageManager::EnumerateCaches(
+ const GURL& origin,
+ const ServiceWorkerCacheStorage::StringsAndErrorCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerCacheStorage* cache_storage =
+ FindOrCreateServiceWorkerCacheManager(origin);
+
+ cache_storage->EnumerateCaches(callback);
+}
+
+void ServiceWorkerCacheStorageManager::SetBlobParametersForCache(
+ net::URLRequestContext* request_context,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(cache_storage_map_.empty());
+ DCHECK(!request_context_ || request_context_ == request_context);
+ DCHECK(!blob_context_ || blob_context_.get() == blob_storage_context.get());
+ request_context_ = request_context;
+ blob_context_ = blob_storage_context;
+}
+
+void ServiceWorkerCacheStorageManager::GetOriginUsage(
+ const GURL& origin_url,
+ const storage::QuotaClient::GetUsageCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (IsMemoryBacked()) {
+ int64 sum = 0;
+ for (const auto& key_value : cache_storage_map_)
+ sum += key_value.second->MemoryBackedSize();
+ callback.Run(sum);
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(base::ComputeDirectorySize,
+ ConstructOriginPath(root_path_, origin_url)),
+ base::Bind(callback));
+}
+
+void ServiceWorkerCacheStorageManager::GetOrigins(
+ const storage::QuotaClient::GetOriginsCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (IsMemoryBacked()) {
+ std::set<GURL> origins;
+ for (const auto& key_value : cache_storage_map_)
+ origins.insert(key_value.first);
+
+ callback.Run(origins);
+ return;
+ }
+
+ PostTaskAndReplyWithResult(cache_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&ListOriginsOnDisk, root_path_),
+ base::Bind(callback));
+}
+
+void ServiceWorkerCacheStorageManager::GetOriginsForHost(
+ const std::string& host,
+ const storage::QuotaClient::GetOriginsCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (IsMemoryBacked()) {
+ std::set<GURL> origins;
+ for (const auto& key_value : cache_storage_map_) {
+ if (host == net::GetHostOrSpecFromURL(key_value.first))
+ origins.insert(key_value.first);
+ }
+ callback.Run(origins);
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(),
+ FROM_HERE,
+ base::Bind(&ListOriginsOnDisk, root_path_),
+ base::Bind(&GetOriginsForHostDidListOrigins, host, callback));
+}
+
+void ServiceWorkerCacheStorageManager::DeleteOriginData(
+ const GURL& origin,
+ const storage::QuotaClient::DeletionCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ServiceWorkerCacheStorage* cache_storage =
+ FindOrCreateServiceWorkerCacheManager(origin);
+ cache_storage_map_.erase(origin);
+ cache_storage->CloseAllCaches(
+ base::Bind(&ServiceWorkerCacheStorageManager::DeleteOriginDidClose,
+ origin, callback, base::Passed(make_scoped_ptr(cache_storage)),
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+// static
+void ServiceWorkerCacheStorageManager::DeleteOriginDidClose(
+ const GURL& origin,
+ const storage::QuotaClient::DeletionCallback& callback,
+ scoped_ptr<ServiceWorkerCacheStorage> cache_storage,
+ base::WeakPtr<ServiceWorkerCacheStorageManager> cache_manager) {
+ // TODO(jkarlin): Deleting the storage leaves any unfinished operations
+ // hanging, resulting in unresolved promises. Fix this by guaranteeing that
+ // callbacks are called in ServiceWorkerStorage.
+ cache_storage.reset();
+
+ if (!cache_manager) {
+ callback.Run(storage::kQuotaErrorAbort);
+ return;
+ }
+
+ if (cache_manager->IsMemoryBacked()) {
+ callback.Run(storage::kQuotaStatusOk);
+ return;
+ }
+
+ PostTaskAndReplyWithResult(
+ cache_manager->cache_task_runner_.get(), FROM_HERE,
+ base::Bind(&DeleteDir,
+ ConstructOriginPath(cache_manager->root_path_, origin)),
+ base::Bind(&DeleteOriginDidDeleteDir, callback));
+}
+
+ServiceWorkerCacheStorageManager::ServiceWorkerCacheStorageManager(
+ const base::FilePath& path,
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy)
+ : root_path_(path),
+ cache_task_runner_(cache_task_runner),
+ quota_manager_proxy_(quota_manager_proxy),
+ request_context_(NULL),
+ weak_ptr_factory_(this) {
+ if (quota_manager_proxy_.get()) {
+ quota_manager_proxy_->RegisterClient(
+ new ServiceWorkerCacheQuotaClient(weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+ServiceWorkerCacheStorage*
+ServiceWorkerCacheStorageManager::FindOrCreateServiceWorkerCacheManager(
+ const GURL& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(request_context_);
+ ServiceWorkerCacheStorageMap::const_iterator it =
+ cache_storage_map_.find(origin);
+ if (it == cache_storage_map_.end()) {
+ ServiceWorkerCacheStorage* cache_storage =
+ new ServiceWorkerCacheStorage(ConstructOriginPath(root_path_, origin),
+ IsMemoryBacked(),
+ cache_task_runner_.get(),
+ request_context_,
+ quota_manager_proxy_,
+ blob_context_,
+ origin);
+ // The map owns fetch_stores.
+ cache_storage_map_.insert(std::make_pair(origin, cache_storage));
+ return cache_storage;
+ }
+ return it->second;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache_storage_manager.h b/chromium/content/browser/service_worker/service_worker_cache_storage_manager.h
new file mode 100644
index 00000000000..79ac6c07a26
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_storage_manager.h
@@ -0,0 +1,144 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_MANAGER_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "content/browser/service_worker/service_worker_cache_storage.h"
+#include "content/common/content_export.h"
+#include "storage/browser/quota/quota_client.h"
+#include "url/gurl.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace net {
+class URLRequestContext;
+}
+
+namespace storage {
+class BlobStorageContext;
+class QuotaManagerProxy;
+}
+
+namespace content {
+
+class ServiceWorkerCacheQuotaClient;
+class ServiceWorkerCacheStorageManagerTest;
+
+// Keeps track of a ServiceWorkerCacheStorage per origin. There is one
+// ServiceWorkerCacheStorageManager per ServiceWorkerContextCore.
+// TODO(jkarlin): Remove ServiceWorkerCacheStorage from memory once they're no
+// longer in active use.
+class CONTENT_EXPORT ServiceWorkerCacheStorageManager {
+ public:
+ static scoped_ptr<ServiceWorkerCacheStorageManager> Create(
+ const base::FilePath& path,
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy);
+
+ static scoped_ptr<ServiceWorkerCacheStorageManager> Create(
+ ServiceWorkerCacheStorageManager* old_manager);
+
+ virtual ~ServiceWorkerCacheStorageManager();
+
+ // Methods to support the CacheStorage spec. These methods call the
+ // corresponding ServiceWorkerCacheStorage method on the appropriate thread.
+ void OpenCache(
+ const GURL& origin,
+ const std::string& cache_name,
+ const ServiceWorkerCacheStorage::CacheAndErrorCallback& callback);
+ void HasCache(
+ const GURL& origin,
+ const std::string& cache_name,
+ const ServiceWorkerCacheStorage::BoolAndErrorCallback& callback);
+ void DeleteCache(
+ const GURL& origin,
+ const std::string& cache_name,
+ const ServiceWorkerCacheStorage::BoolAndErrorCallback& callback);
+ void EnumerateCaches(
+ const GURL& origin,
+ const ServiceWorkerCacheStorage::StringsAndErrorCallback& callback);
+ // TODO(jkarlin): Add match() function.
+
+ // This must be called before creating any of the public *Cache functions
+ // above.
+ void SetBlobParametersForCache(
+ net::URLRequestContext* request_context,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context);
+
+ base::WeakPtr<ServiceWorkerCacheStorageManager> AsWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ private:
+ friend class ServiceWorkerCacheQuotaClient;
+ friend class ServiceWorkerCacheStorageManagerTest;
+
+ typedef std::map<GURL, ServiceWorkerCacheStorage*>
+ ServiceWorkerCacheStorageMap;
+
+ ServiceWorkerCacheStorageManager(
+ const base::FilePath& path,
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy);
+
+ // The returned ServiceWorkerCacheStorage* is owned by
+ // service_worker_cache_storages_.
+ ServiceWorkerCacheStorage* FindOrCreateServiceWorkerCacheManager(
+ const GURL& origin);
+
+ // QuotaClient support
+ void GetOriginUsage(const GURL& origin_url,
+ const storage::QuotaClient::GetUsageCallback& callback);
+ void GetOrigins(const storage::QuotaClient::GetOriginsCallback& callback);
+ void GetOriginsForHost(
+ const std::string& host,
+ const storage::QuotaClient::GetOriginsCallback& callback);
+ void DeleteOriginData(const GURL& origin,
+ const storage::QuotaClient::DeletionCallback& callback);
+ static void DeleteOriginDidClose(
+ const GURL& origin,
+ const storage::QuotaClient::DeletionCallback& callback,
+ scoped_ptr<ServiceWorkerCacheStorage> cache_storage,
+ base::WeakPtr<ServiceWorkerCacheStorageManager> cache_manager);
+
+ net::URLRequestContext* url_request_context() const {
+ return request_context_;
+ }
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context() const {
+ return blob_context_;
+ }
+ base::FilePath root_path() const { return root_path_; }
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner() const {
+ return cache_task_runner_;
+ }
+
+ bool IsMemoryBacked() const { return root_path_.empty(); }
+
+ base::FilePath root_path_;
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
+
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+
+ // The map owns the CacheStorages and the CacheStorages are only accessed on
+ // |cache_task_runner_|.
+ ServiceWorkerCacheStorageMap cache_storage_map_;
+
+ net::URLRequestContext* request_context_;
+ base::WeakPtr<storage::BlobStorageContext> blob_context_;
+
+ base::WeakPtrFactory<ServiceWorkerCacheStorageManager> weak_ptr_factory_;
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheStorageManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_MANAGER_H_
diff --git a/chromium/content/browser/service_worker/service_worker_cache_storage_manager_unittest.cc b/chromium/content/browser/service_worker/service_worker_cache_storage_manager_unittest.cc
new file mode 100644
index 00000000000..8bfe7cce66d
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_storage_manager_unittest.cc
@@ -0,0 +1,631 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache_storage_manager.h"
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/browser/quota/mock_quota_manager_proxy.h"
+#include "content/browser/service_worker/service_worker_cache_quota_client.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class ServiceWorkerCacheStorageManagerTest : public testing::Test {
+ protected:
+ ServiceWorkerCacheStorageManagerTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ callback_bool_(false),
+ callback_error_(
+ ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR),
+ callback_cache_error_(ServiceWorkerCache::ErrorTypeOK),
+ origin1_("http://example1.com"),
+ origin2_("http://example2.com") {}
+
+ void SetUp() override {
+ ChromeBlobStorageContext* blob_storage_context(
+ ChromeBlobStorageContext::GetFor(&browser_context_));
+ // Wait for ChromeBlobStorageContext to finish initializing.
+ base::RunLoop().RunUntilIdle();
+
+ quota_manager_proxy_ = new MockQuotaManagerProxy(
+ nullptr, base::MessageLoopProxy::current().get());
+
+ net::URLRequestContext* url_request_context =
+ browser_context_.GetRequestContext()->GetURLRequestContext();
+ if (MemoryOnly()) {
+ cache_manager_ = ServiceWorkerCacheStorageManager::Create(
+ base::FilePath(),
+ base::MessageLoopProxy::current(),
+ quota_manager_proxy_);
+ } else {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ cache_manager_ = ServiceWorkerCacheStorageManager::Create(
+ temp_dir_.path(),
+ base::MessageLoopProxy::current(),
+ quota_manager_proxy_);
+ }
+
+ cache_manager_->SetBlobParametersForCache(
+ url_request_context, blob_storage_context->context()->AsWeakPtr());
+ }
+
+ void TearDown() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ virtual bool MemoryOnly() { return false; }
+
+ void BoolAndErrorCallback(
+ base::RunLoop* run_loop,
+ bool value,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ callback_bool_ = value;
+ callback_error_ = error;
+ run_loop->Quit();
+ }
+
+ void CacheAndErrorCallback(
+ base::RunLoop* run_loop,
+ const scoped_refptr<ServiceWorkerCache>& cache,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ callback_cache_ = cache;
+ callback_error_ = error;
+ run_loop->Quit();
+ }
+
+ void StringsAndErrorCallback(
+ base::RunLoop* run_loop,
+ const std::vector<std::string>& strings,
+ ServiceWorkerCacheStorage::CacheStorageError error) {
+ callback_strings_ = strings;
+ callback_error_ = error;
+ run_loop->Quit();
+ }
+
+ void CachePutCallback(base::RunLoop* run_loop,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ callback_cache_error_ = error;
+ run_loop->Quit();
+ }
+
+ void CacheMatchCallback(
+ base::RunLoop* run_loop,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ callback_cache_error_ = error;
+ callback_cache_response_ = response.Pass();
+ // Deliberately drop the data handle as only the url is being tested.
+ run_loop->Quit();
+ }
+
+ bool Open(const GURL& origin, const std::string& cache_name) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache_manager_->OpenCache(
+ origin,
+ cache_name,
+ base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ bool error = callback_error_ !=
+ ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
+ if (error)
+ EXPECT_TRUE(!callback_cache_.get());
+ else
+ EXPECT_TRUE(callback_cache_.get());
+ return !error;
+ }
+
+ bool Has(const GURL& origin, const std::string& cache_name) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache_manager_->HasCache(
+ origin,
+ cache_name,
+ base::Bind(&ServiceWorkerCacheStorageManagerTest::BoolAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ return callback_bool_;
+ }
+
+ bool Delete(const GURL& origin, const std::string& cache_name) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache_manager_->DeleteCache(
+ origin,
+ cache_name,
+ base::Bind(&ServiceWorkerCacheStorageManagerTest::BoolAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ return callback_bool_;
+ }
+
+ bool Keys(const GURL& origin) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache_manager_->EnumerateCaches(
+ origin,
+ base::Bind(
+ &ServiceWorkerCacheStorageManagerTest::StringsAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ bool error = callback_error_ !=
+ ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NO_ERROR;
+ return !error;
+ }
+
+ bool CachePut(const scoped_refptr<ServiceWorkerCache>& cache,
+ const GURL& url) {
+ scoped_ptr<ServiceWorkerFetchRequest> request(
+ new ServiceWorkerFetchRequest());
+ scoped_ptr<ServiceWorkerResponse> response(new ServiceWorkerResponse());
+ request->url = url;
+ response->url = url;
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache->Put(
+ request.Pass(),
+ response.Pass(),
+ base::Bind(&ServiceWorkerCacheStorageManagerTest::CachePutCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ bool error = callback_cache_error_ != ServiceWorkerCache::ErrorTypeOK;
+ return !error;
+ }
+
+ bool CacheMatch(const scoped_refptr<ServiceWorkerCache>& cache,
+ const GURL& url) {
+ scoped_ptr<ServiceWorkerFetchRequest> request(
+ new ServiceWorkerFetchRequest());
+ request->url = url;
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache->Match(
+ request.Pass(),
+ base::Bind(&ServiceWorkerCacheStorageManagerTest::CacheMatchCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ bool error = callback_cache_error_ != ServiceWorkerCache::ErrorTypeOK;
+ return !error;
+ }
+
+ ServiceWorkerCacheStorage* CacheStorageForOrigin(const GURL& origin) {
+ return cache_manager_->FindOrCreateServiceWorkerCacheManager(origin);
+ }
+
+ protected:
+ TestBrowserContext browser_context_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
+ scoped_ptr<ServiceWorkerCacheStorageManager> cache_manager_;
+
+ scoped_refptr<ServiceWorkerCache> callback_cache_;
+ int callback_bool_;
+ ServiceWorkerCacheStorage::CacheStorageError callback_error_;
+ ServiceWorkerCache::ErrorType callback_cache_error_;
+ scoped_ptr<ServiceWorkerResponse> callback_cache_response_;
+ std::vector<std::string> callback_strings_;
+
+ const GURL origin1_;
+ const GURL origin2_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheStorageManagerTest);
+};
+
+class ServiceWorkerCacheStorageManagerMemoryOnlyTest
+ : public ServiceWorkerCacheStorageManagerTest {
+ bool MemoryOnly() override { return true; }
+};
+
+class ServiceWorkerCacheStorageManagerTestP
+ : public ServiceWorkerCacheStorageManagerTest,
+ public testing::WithParamInterface<bool> {
+ bool MemoryOnly() override { return !GetParam(); }
+};
+
+TEST_F(ServiceWorkerCacheStorageManagerTest, TestsRunOnIOThread) {
+ EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, OpenCache) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, OpenTwoCaches) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Open(origin1_, "bar"));
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, CachePointersDiffer) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_NE(callback_cache_.get(), cache.get());
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, Open2CachesSameNameDiffOrigins) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
+ EXPECT_TRUE(Open(origin2_, "foo"));
+ EXPECT_NE(cache.get(), callback_cache_.get());
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, OpenExistingCache) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(callback_cache_.get(), cache.get());
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, HasCache) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Has(origin1_, "foo"));
+ EXPECT_TRUE(callback_bool_);
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, HasNonExistent) {
+ EXPECT_FALSE(Has(origin1_, "foo"));
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteCache) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_FALSE(Has(origin1_, "foo"));
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteTwice) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_FALSE(Delete(origin1_, "foo"));
+ EXPECT_EQ(ServiceWorkerCacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND,
+ callback_error_);
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, EmptyKeys) {
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_TRUE(callback_strings_.empty());
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, SomeKeys) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_TRUE(Open(origin2_, "baz"));
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(2u, callback_strings_.size());
+ std::vector<std::string> expected_keys;
+ expected_keys.push_back("foo");
+ expected_keys.push_back("bar");
+ EXPECT_EQ(expected_keys, callback_strings_);
+ EXPECT_TRUE(Keys(origin2_));
+ EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_STREQ("baz", callback_strings_[0].c_str());
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, DeletedKeysGone) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_TRUE(Open(origin2_, "baz"));
+ EXPECT_TRUE(Delete(origin1_, "bar"));
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_STREQ("foo", callback_strings_[0].c_str());
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, Chinese) {
+ EXPECT_TRUE(Open(origin1_, "你好"));
+ scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
+ EXPECT_TRUE(Open(origin1_, "你好"));
+ EXPECT_EQ(callback_cache_.get(), cache.get());
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_STREQ("你好", callback_strings_[0].c_str());
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerTest, EmptyKey) {
+ EXPECT_TRUE(Open(origin1_, ""));
+ scoped_refptr<ServiceWorkerCache> cache = callback_cache_;
+ EXPECT_TRUE(Open(origin1_, ""));
+ EXPECT_EQ(cache.get(), callback_cache_.get());
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_STREQ("", callback_strings_[0].c_str());
+ EXPECT_TRUE(Has(origin1_, ""));
+ EXPECT_TRUE(Delete(origin1_, ""));
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(0u, callback_strings_.size());
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerTest, DataPersists) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_TRUE(Open(origin1_, "baz"));
+ EXPECT_TRUE(Open(origin2_, "raz"));
+ EXPECT_TRUE(Delete(origin1_, "bar"));
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ cache_manager_ =
+ ServiceWorkerCacheStorageManager::Create(cache_manager_.get());
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(2u, callback_strings_.size());
+ std::vector<std::string> expected_keys;
+ expected_keys.push_back("foo");
+ expected_keys.push_back("baz");
+ EXPECT_EQ(expected_keys, callback_strings_);
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest, DataLostWhenMemoryOnly) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Open(origin2_, "baz"));
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ cache_manager_ =
+ ServiceWorkerCacheStorageManager::Create(cache_manager_.get());
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(0u, callback_strings_.size());
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerTest, BadCacheName) {
+ // Since the implementation writes cache names to disk, ensure that we don't
+ // escape the directory.
+ const std::string bad_name = "../../../../../../../../../../../../../../foo";
+ EXPECT_TRUE(Open(origin1_, bad_name));
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_STREQ(bad_name.c_str(), callback_strings_[0].c_str());
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerTest, BadOriginName) {
+ // Since the implementation writes origin names to disk, ensure that we don't
+ // escape the directory.
+ GURL bad_origin("http://../../../../../../../../../../../../../../foo");
+ EXPECT_TRUE(Open(bad_origin, "foo"));
+ EXPECT_TRUE(Keys(bad_origin));
+ EXPECT_EQ(1u, callback_strings_.size());
+ EXPECT_STREQ("foo", callback_strings_[0].c_str());
+}
+
+// With a persistent cache if the client drops its reference to a
+// ServiceWorkerCache
+// it should be deleted.
+TEST_F(ServiceWorkerCacheStorageManagerTest, DropReference) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ base::WeakPtr<ServiceWorkerCache> cache = callback_cache_->AsWeakPtr();
+ callback_cache_ = NULL;
+ EXPECT_TRUE(!cache);
+}
+
+// With a memory cache the cache can't be freed from memory until the client
+// calls delete.
+TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest,
+ MemoryLosesReferenceOnlyAfterDelete) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ base::WeakPtr<ServiceWorkerCache> cache = callback_cache_->AsWeakPtr();
+ callback_cache_ = NULL;
+ EXPECT_TRUE(cache);
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_FALSE(cache);
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, RecreateCacheOnDemand) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ callback_cache_ = NULL;
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(CacheMatch(callback_cache_, GURL("http://example.com/foo")));
+}
+
+TEST_P(ServiceWorkerCacheStorageManagerTestP, DeleteBeforeRelease) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_TRUE(callback_cache_->AsWeakPtr());
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerMemoryOnlyTest, MemoryBackedSize) {
+ ServiceWorkerCacheStorage* cache_storage = CacheStorageForOrigin(origin1_);
+ EXPECT_EQ(0, cache_storage->MemoryBackedSize());
+
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ scoped_refptr<ServiceWorkerCache> foo_cache = callback_cache_;
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ scoped_refptr<ServiceWorkerCache> bar_cache = callback_cache_;
+ EXPECT_EQ(0, cache_storage->MemoryBackedSize());
+
+ EXPECT_TRUE(CachePut(foo_cache, GURL("http://example.com/foo")));
+ EXPECT_LT(0, cache_storage->MemoryBackedSize());
+ int64 foo_size = cache_storage->MemoryBackedSize();
+
+ EXPECT_TRUE(CachePut(bar_cache, GURL("http://example.com/foo")));
+ EXPECT_EQ(foo_size * 2, cache_storage->MemoryBackedSize());
+}
+
+TEST_F(ServiceWorkerCacheStorageManagerTest, MemoryBackedSizePersistent) {
+ ServiceWorkerCacheStorage* cache_storage = CacheStorageForOrigin(origin1_);
+ EXPECT_EQ(0, cache_storage->MemoryBackedSize());
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_EQ(0, cache_storage->MemoryBackedSize());
+}
+
+class ServiceWorkerCacheQuotaClientTest
+ : public ServiceWorkerCacheStorageManagerTest {
+ protected:
+ ServiceWorkerCacheQuotaClientTest() {}
+
+ void SetUp() override {
+ ServiceWorkerCacheStorageManagerTest::SetUp();
+ quota_client_.reset(
+ new ServiceWorkerCacheQuotaClient(cache_manager_->AsWeakPtr()));
+ }
+
+ void UsageCallback(base::RunLoop* run_loop, int64 usage) {
+ callback_usage_ = usage;
+ run_loop->Quit();
+ }
+
+ void OriginsCallback(base::RunLoop* run_loop, const std::set<GURL>& origins) {
+ callback_origins_ = origins;
+ run_loop->Quit();
+ }
+
+ void DeleteOriginCallback(base::RunLoop* run_loop,
+ storage::QuotaStatusCode status) {
+ callback_status_ = status;
+ run_loop->Quit();
+ }
+
+ int64 QuotaGetOriginUsage(const GURL& origin) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ quota_client_->GetOriginUsage(
+ origin,
+ storage::kStorageTypeTemporary,
+ base::Bind(&ServiceWorkerCacheQuotaClientTest::UsageCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+ return callback_usage_;
+ }
+
+ size_t QuotaGetOriginsForType() {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ quota_client_->GetOriginsForType(
+ storage::kStorageTypeTemporary,
+ base::Bind(&ServiceWorkerCacheQuotaClientTest::OriginsCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+ return callback_origins_.size();
+ }
+
+ size_t QuotaGetOriginsForHost(const std::string& host) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ quota_client_->GetOriginsForHost(
+ storage::kStorageTypeTemporary,
+ host,
+ base::Bind(&ServiceWorkerCacheQuotaClientTest::OriginsCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+ return callback_origins_.size();
+ }
+
+ bool QuotaDeleteOriginData(const GURL& origin) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ quota_client_->DeleteOriginData(
+ origin,
+ storage::kStorageTypeTemporary,
+ base::Bind(&ServiceWorkerCacheQuotaClientTest::DeleteOriginCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+ return callback_status_ == storage::kQuotaStatusOk;
+ }
+
+ bool QuotaDoesSupport(storage::StorageType type) {
+ return quota_client_->DoesSupport(type);
+ }
+
+ scoped_ptr<ServiceWorkerCacheQuotaClient> quota_client_;
+
+ storage::QuotaStatusCode callback_status_;
+ int64 callback_usage_;
+ std::set<GURL> callback_origins_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheQuotaClientTest);
+};
+
+class ServiceWorkerCacheQuotaClientTestP
+ : public ServiceWorkerCacheQuotaClientTest,
+ public testing::WithParamInterface<bool> {
+ bool MemoryOnly() override { return !GetParam(); }
+};
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaID) {
+ EXPECT_EQ(storage::QuotaClient::kServiceWorkerCache, quota_client_->id());
+}
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaGetOriginUsage) {
+ EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_LT(0, QuotaGetOriginUsage(origin1_));
+}
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaGetOriginsForType) {
+ EXPECT_EQ(0u, QuotaGetOriginsForType());
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_TRUE(Open(origin2_, "foo"));
+ EXPECT_EQ(2u, QuotaGetOriginsForType());
+}
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaGetOriginsForHost) {
+ EXPECT_EQ(0u, QuotaGetOriginsForHost("example.com"));
+ EXPECT_TRUE(Open(GURL("http://example.com:8080"), "foo"));
+ EXPECT_TRUE(Open(GURL("http://example.com:9000"), "foo"));
+ EXPECT_TRUE(Open(GURL("ftp://example.com"), "foo"));
+ EXPECT_TRUE(Open(GURL("http://example2.com"), "foo"));
+ EXPECT_EQ(3u, QuotaGetOriginsForHost("example.com"));
+ EXPECT_EQ(1u, QuotaGetOriginsForHost("example2.com"));
+ EXPECT_TRUE(callback_origins_.find(GURL("http://example2.com")) !=
+ callback_origins_.end());
+ EXPECT_EQ(0u, QuotaGetOriginsForHost("unknown.com"));
+}
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaDeleteOriginData) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ // Call put to test that initialized caches are properly deleted too.
+ EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_TRUE(Open(origin2_, "baz"));
+
+ EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
+
+ EXPECT_FALSE(Has(origin1_, "foo"));
+ EXPECT_FALSE(Has(origin1_, "bar"));
+ EXPECT_TRUE(Has(origin2_, "baz"));
+ EXPECT_TRUE(Open(origin1_, "foo"));
+}
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaDeleteEmptyOrigin) {
+ EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
+}
+
+TEST_P(ServiceWorkerCacheQuotaClientTestP, QuotaDoesSupport) {
+ EXPECT_TRUE(QuotaDoesSupport(storage::kStorageTypeTemporary));
+ EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypePersistent));
+ EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypeSyncable));
+ EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypeQuotaNotManaged));
+ EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypeUnknown));
+}
+
+INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheStorageManagerTests,
+ ServiceWorkerCacheStorageManagerTestP,
+ ::testing::Values(false, true));
+
+INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheQuotaClientTests,
+ ServiceWorkerCacheQuotaClientTestP,
+ ::testing::Values(false, true));
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_cache_unittest.cc b/chromium/content/browser/service_worker/service_worker_cache_unittest.cc
new file mode 100644
index 00000000000..0d1c8fad3a5
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_cache_unittest.cc
@@ -0,0 +1,796 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_cache.h"
+
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/browser/fileapi/mock_url_request_delegate.h"
+#include "content/browser/quota/mock_quota_manager_proxy.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/common/blob/blob_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+const char kTestData[] = "Hello World";
+
+// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
+// the memory.
+storage::BlobProtocolHandler* CreateMockBlobProtocolHandler(
+ storage::BlobStorageContext* blob_storage_context) {
+ // The FileSystemContext and MessageLoopProxy are not actually used but a
+ // MessageLoopProxy is needed to avoid a DCHECK in BlobURLRequestJob ctor.
+ return new storage::BlobProtocolHandler(
+ blob_storage_context, NULL, base::MessageLoopProxy::current().get());
+}
+
+} // namespace
+
+// A ServiceWorkerCache that can optionally pause during backend creation.
+class TestServiceWorkerCache : public ServiceWorkerCache {
+ public:
+ TestServiceWorkerCache(
+ const GURL& origin,
+ const base::FilePath& path,
+ net::URLRequestContext* request_context,
+ const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context)
+ : ServiceWorkerCache(origin,
+ path,
+ request_context,
+ quota_manager_proxy,
+ blob_context),
+ pause_backend_creation_(false) {}
+
+ virtual void CreateBackend(const ErrorCallback& callback) override {
+ backend_creation_callback_ = callback;
+ if (pause_backend_creation_)
+ return;
+ ContinueCreateBackend();
+ }
+
+ void ContinueCreateBackend() {
+ ServiceWorkerCache::CreateBackend(backend_creation_callback_);
+ }
+
+ void set_pause_backend_creation(bool pause) {
+ pause_backend_creation_ = pause;
+ }
+
+ private:
+ virtual ~TestServiceWorkerCache() override {}
+
+ bool pause_backend_creation_;
+ ErrorCallback backend_creation_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestServiceWorkerCache);
+};
+
+class ServiceWorkerCacheTest : public testing::Test {
+ public:
+ ServiceWorkerCacheTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ callback_error_(ServiceWorkerCache::ErrorTypeOK),
+ callback_closed_(false) {}
+
+ void SetUp() override {
+ ChromeBlobStorageContext* blob_storage_context =
+ ChromeBlobStorageContext::GetFor(&browser_context_);
+ // Wait for chrome_blob_storage_context to finish initializing.
+ base::RunLoop().RunUntilIdle();
+ blob_storage_context_ = blob_storage_context->context();
+
+ quota_manager_proxy_ = new MockQuotaManagerProxy(
+ nullptr, base::MessageLoopProxy::current().get());
+
+ url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
+ url_request_job_factory_->SetProtocolHandler(
+ "blob", CreateMockBlobProtocolHandler(blob_storage_context->context()));
+
+ net::URLRequestContext* url_request_context =
+ browser_context_.GetRequestContext()->GetURLRequestContext();
+
+ url_request_context->set_job_factory(url_request_job_factory_.get());
+
+ CreateRequests(blob_storage_context);
+
+ if (!MemoryOnly())
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
+
+ cache_ = make_scoped_refptr(new TestServiceWorkerCache(
+ GURL("http://example.com"), path, url_request_context,
+ quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
+ }
+
+ void TearDown() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void CreateRequests(ChromeBlobStorageContext* blob_storage_context) {
+ ServiceWorkerHeaderMap headers;
+ headers.insert(std::make_pair("a", "a"));
+ headers.insert(std::make_pair("b", "b"));
+ body_request_ = ServiceWorkerFetchRequest(
+ GURL("http://example.com/body.html"), "GET", headers, GURL(""), false);
+ no_body_request_ =
+ ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
+ "GET",
+ headers,
+ GURL(""),
+ false);
+
+ std::string expected_response;
+ for (int i = 0; i < 100; ++i)
+ expected_blob_data_ += kTestData;
+
+ scoped_refptr<storage::BlobData> blob_data(
+ new storage::BlobData("blob-id:myblob"));
+ blob_data->AppendData(expected_blob_data_);
+
+ blob_handle_ =
+ blob_storage_context->context()->AddFinishedBlob(blob_data.get());
+
+ body_response_ =
+ ServiceWorkerResponse(GURL("http://example.com/body.html"),
+ 200,
+ "OK",
+ blink::WebServiceWorkerResponseTypeDefault,
+ headers,
+ blob_handle_->uuid(),
+ expected_blob_data_.size());
+
+ no_body_response_ =
+ ServiceWorkerResponse(GURL("http://example.com/no_body.html"),
+ 200,
+ "OK",
+ blink::WebServiceWorkerResponseTypeDefault,
+ headers,
+ "",
+ 0);
+ }
+
+ scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
+ const ServiceWorkerFetchRequest& request) {
+ return make_scoped_ptr(new ServiceWorkerFetchRequest(request.url,
+ request.method,
+ request.headers,
+ request.referrer,
+ request.is_reload));
+ }
+
+ scoped_ptr<ServiceWorkerResponse> CopyFetchResponse(
+ const ServiceWorkerResponse& response) {
+ scoped_ptr<ServiceWorkerResponse> sw_response(
+ new ServiceWorkerResponse(response.url,
+ response.status_code,
+ response.status_text,
+ response.response_type,
+ response.headers,
+ response.blob_uuid,
+ response.blob_size));
+ return sw_response.Pass();
+ }
+
+ bool Put(const ServiceWorkerFetchRequest& request,
+ const ServiceWorkerResponse& response) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+
+ cache_->Put(CopyFetchRequest(request),
+ CopyFetchResponse(response),
+ base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ // TODO(jkarlin): These functions should use base::RunLoop().RunUntilIdle()
+ // once the cache uses a passed in MessageLoopProxy instead of the CACHE
+ // thread.
+ loop->Run();
+
+ return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
+ }
+
+ bool Match(const ServiceWorkerFetchRequest& request) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+
+ cache_->Match(CopyFetchRequest(request),
+ base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
+ }
+
+ bool Delete(const ServiceWorkerFetchRequest& request) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+
+ cache_->Delete(CopyFetchRequest(request),
+ base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
+ }
+
+ bool Keys() {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+
+ cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+
+ return callback_error_ == ServiceWorkerCache::ErrorTypeOK;
+ }
+
+ bool Close() {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+
+ cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ loop->Run();
+ return callback_closed_;
+ }
+
+ void RequestsCallback(base::RunLoop* run_loop,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerCache::Requests> requests) {
+ callback_error_ = error;
+ callback_strings_.clear();
+ if (requests) {
+ for (size_t i = 0u; i < requests->size(); ++i)
+ callback_strings_.push_back(requests->at(i).url.spec());
+ }
+ if (run_loop)
+ run_loop->Quit();
+ }
+
+ void ErrorTypeCallback(base::RunLoop* run_loop,
+ ServiceWorkerCache::ErrorType error) {
+ callback_error_ = error;
+ if (run_loop)
+ run_loop->Quit();
+ }
+
+ void ResponseAndErrorCallback(
+ base::RunLoop* run_loop,
+ ServiceWorkerCache::ErrorType error,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> body_handle) {
+ callback_error_ = error;
+ callback_response_ = response.Pass();
+ callback_response_data_.reset();
+ if (error == ServiceWorkerCache::ErrorTypeOK &&
+ !callback_response_->blob_uuid.empty()) {
+ callback_response_data_ = body_handle.Pass();
+ }
+
+ if (run_loop)
+ run_loop->Quit();
+ }
+
+ void CloseCallback(base::RunLoop* run_loop) {
+ EXPECT_FALSE(callback_closed_);
+ callback_closed_ = true;
+ if (run_loop)
+ run_loop->Quit();
+ }
+
+ void CopyBody(storage::BlobDataHandle* blob_handle, std::string* output) {
+ storage::BlobData* data = blob_handle->data();
+ std::vector<storage::BlobData::Item> items = data->items();
+ for (size_t i = 0, max = items.size(); i < max; ++i)
+ output->append(items[i].bytes(), items[i].length());
+ }
+
+ bool VerifyKeys(const std::vector<std::string>& expected_keys) {
+ if (expected_keys.size() != callback_strings_.size())
+ return false;
+
+ std::set<std::string> found_set;
+ for (int i = 0, max = callback_strings_.size(); i < max; ++i)
+ found_set.insert(callback_strings_[i]);
+
+ for (int i = 0, max = expected_keys.size(); i < max; ++i) {
+ if (found_set.find(expected_keys[i]) == found_set.end())
+ return false;
+ }
+ return true;
+ }
+
+ bool TestResponseType(blink::WebServiceWorkerResponseType response_type) {
+ body_response_.response_type = response_type;
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_TRUE(Delete(body_request_));
+ return response_type == callback_response_->response_type;
+ }
+
+ void VerifyAllOpsFail() {
+ EXPECT_FALSE(Put(no_body_request_, no_body_response_));
+ EXPECT_FALSE(Match(no_body_request_));
+ EXPECT_FALSE(Delete(body_request_));
+ EXPECT_FALSE(Keys());
+ }
+
+ virtual bool MemoryOnly() { return false; }
+
+ protected:
+ TestBrowserContext browser_context_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
+ storage::BlobStorageContext* blob_storage_context_;
+
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<TestServiceWorkerCache> cache_;
+
+ ServiceWorkerFetchRequest body_request_;
+ ServiceWorkerResponse body_response_;
+ ServiceWorkerFetchRequest no_body_request_;
+ ServiceWorkerResponse no_body_response_;
+ scoped_ptr<storage::BlobDataHandle> blob_handle_;
+ std::string expected_blob_data_;
+
+ ServiceWorkerCache::ErrorType callback_error_;
+ scoped_ptr<ServiceWorkerResponse> callback_response_;
+ scoped_ptr<storage::BlobDataHandle> callback_response_data_;
+ std::vector<std::string> callback_strings_;
+ bool callback_closed_;
+};
+
+class ServiceWorkerCacheTestP : public ServiceWorkerCacheTest,
+ public testing::WithParamInterface<bool> {
+ bool MemoryOnly() override { return !GetParam(); }
+};
+
+class ServiceWorkerCacheMemoryOnlyTest
+ : public ServiceWorkerCacheTest,
+ public testing::WithParamInterface<bool> {
+ bool MemoryOnly() override { return true; }
+};
+
+TEST_P(ServiceWorkerCacheTestP, PutNoBody) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(callback_response_);
+ EXPECT_STREQ(no_body_response_.url.spec().c_str(),
+ callback_response_->url.spec().c_str());
+ EXPECT_FALSE(callback_response_data_);
+ EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
+ EXPECT_EQ(0u, callback_response_->blob_size);
+}
+
+TEST_P(ServiceWorkerCacheTestP, PutBody) {
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(callback_response_);
+ EXPECT_STREQ(body_response_.url.spec().c_str(),
+ callback_response_->url.spec().c_str());
+ EXPECT_TRUE(callback_response_data_);
+ EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
+ EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
+
+ std::string response_body;
+ CopyBody(callback_response_data_.get(), &response_body);
+ EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
+}
+
+TEST_P(ServiceWorkerCacheTestP, ResponseURLDiffersFromRequestURL) {
+ no_body_response_.url = GURL("http://example.com/foobar");
+ EXPECT_STRNE("http://example.com/foobar",
+ no_body_request_.url.spec().c_str());
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Match(no_body_request_));
+ EXPECT_STREQ("http://example.com/foobar",
+ callback_response_->url.spec().c_str());
+}
+
+TEST_P(ServiceWorkerCacheTestP, ResponseURLEmpty) {
+ no_body_response_.url = GURL();
+ EXPECT_STRNE("", no_body_request_.url.spec().c_str());
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Match(no_body_request_));
+ EXPECT_STREQ("", callback_response_->url.spec().c_str());
+}
+
+TEST_F(ServiceWorkerCacheTest, PutBodyDropBlobRef) {
+ scoped_ptr<base::RunLoop> loop(new base::RunLoop());
+ cache_->Put(CopyFetchRequest(body_request_),
+ CopyFetchResponse(body_response_),
+ base::Bind(&ServiceWorkerCacheTestP::ResponseAndErrorCallback,
+ base::Unretained(this),
+ base::Unretained(loop.get())));
+ // The handle should be held by the cache now so the deref here should be
+ // okay.
+ blob_handle_.reset();
+ loop->Run();
+
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
+}
+
+TEST_P(ServiceWorkerCacheTestP, PutReplace) {
+ EXPECT_TRUE(Put(body_request_, no_body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_FALSE(callback_response_data_);
+
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_TRUE(callback_response_data_);
+
+ EXPECT_TRUE(Put(body_request_, no_body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_FALSE(callback_response_data_);
+}
+
+TEST_P(ServiceWorkerCacheTestP, MatchNoBody) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Match(no_body_request_));
+ EXPECT_EQ(200, callback_response_->status_code);
+ EXPECT_STREQ("OK", callback_response_->status_text.c_str());
+ EXPECT_STREQ("http://example.com/no_body.html",
+ callback_response_->url.spec().c_str());
+ EXPECT_STREQ("", callback_response_->blob_uuid.c_str());
+ EXPECT_EQ(0u, callback_response_->blob_size);
+}
+
+TEST_P(ServiceWorkerCacheTestP, MatchBody) {
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_EQ(200, callback_response_->status_code);
+ EXPECT_STREQ("OK", callback_response_->status_text.c_str());
+ EXPECT_STREQ("http://example.com/body.html",
+ callback_response_->url.spec().c_str());
+ EXPECT_STRNE("", callback_response_->blob_uuid.c_str());
+ EXPECT_EQ(expected_blob_data_.size(), callback_response_->blob_size);
+
+ std::string response_body;
+ CopyBody(callback_response_data_.get(), &response_body);
+ EXPECT_STREQ(expected_blob_data_.c_str(), response_body.c_str());
+}
+
+TEST_P(ServiceWorkerCacheTestP, Vary) {
+ body_request_.headers["vary_foo"] = "foo";
+ body_response_.headers["vary"] = "vary_foo";
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+
+ body_request_.headers["vary_foo"] = "bar";
+ EXPECT_FALSE(Match(body_request_));
+
+ body_request_.headers.erase("vary_foo");
+ EXPECT_FALSE(Match(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, EmptyVary) {
+ body_response_.headers["vary"] = "";
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+
+ body_request_.headers["zoo"] = "zoo";
+ EXPECT_TRUE(Match(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, NoVaryButDiffHeaders) {
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+
+ body_request_.headers["zoo"] = "zoo";
+ EXPECT_TRUE(Match(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, VaryMultiple) {
+ body_request_.headers["vary_foo"] = "foo";
+ body_request_.headers["vary_bar"] = "bar";
+ body_response_.headers["vary"] = " vary_foo , vary_bar";
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+
+ body_request_.headers["vary_bar"] = "foo";
+ EXPECT_FALSE(Match(body_request_));
+
+ body_request_.headers.erase("vary_bar");
+ EXPECT_FALSE(Match(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, VaryNewHeader) {
+ body_request_.headers["vary_foo"] = "foo";
+ body_response_.headers["vary"] = " vary_foo, vary_bar";
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+
+ body_request_.headers["vary_bar"] = "bar";
+ EXPECT_FALSE(Match(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, VaryStar) {
+ body_response_.headers["vary"] = "*";
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_FALSE(Match(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, EmptyKeys) {
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(0u, callback_strings_.size());
+}
+
+TEST_P(ServiceWorkerCacheTestP, TwoKeys) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(2u, callback_strings_.size());
+ std::vector<std::string> expected_keys;
+ expected_keys.push_back(no_body_request_.url.spec());
+ expected_keys.push_back(body_request_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_keys));
+}
+
+TEST_P(ServiceWorkerCacheTestP, TwoKeysThenOne) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(2u, callback_strings_.size());
+ std::vector<std::string> expected_keys;
+ expected_keys.push_back(no_body_request_.url.spec());
+ expected_keys.push_back(body_request_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_keys));
+
+ EXPECT_TRUE(Delete(body_request_));
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(1u, callback_strings_.size());
+ std::vector<std::string> expected_key;
+ expected_key.push_back(no_body_request_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_key));
+}
+
+TEST_P(ServiceWorkerCacheTestP, DeleteNoBody) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Match(no_body_request_));
+ EXPECT_TRUE(Delete(no_body_request_));
+ EXPECT_FALSE(Match(no_body_request_));
+ EXPECT_FALSE(Delete(no_body_request_));
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Match(no_body_request_));
+ EXPECT_TRUE(Delete(no_body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, DeleteBody) {
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_TRUE(Delete(body_request_));
+ EXPECT_FALSE(Match(body_request_));
+ EXPECT_FALSE(Delete(body_request_));
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Match(body_request_));
+ EXPECT_TRUE(Delete(body_request_));
+}
+
+TEST_P(ServiceWorkerCacheTestP, QuickStressNoBody) {
+ for (int i = 0; i < 100; ++i) {
+ EXPECT_FALSE(Match(no_body_request_));
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Match(no_body_request_));
+ EXPECT_TRUE(Delete(no_body_request_));
+ }
+}
+
+TEST_P(ServiceWorkerCacheTestP, QuickStressBody) {
+ for (int i = 0; i < 100; ++i) {
+ ASSERT_FALSE(Match(body_request_));
+ ASSERT_TRUE(Put(body_request_, body_response_));
+ ASSERT_TRUE(Match(body_request_));
+ ASSERT_TRUE(Delete(body_request_));
+ }
+}
+
+TEST_P(ServiceWorkerCacheTestP, PutResponseType) {
+ EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeBasic));
+ EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeCORS));
+ EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeDefault));
+ EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeError));
+ EXPECT_TRUE(TestResponseType(blink::WebServiceWorkerResponseTypeOpaque));
+}
+
+TEST_F(ServiceWorkerCacheTest, CaselessServiceWorkerResponseHeaders) {
+ // ServiceWorkerCache depends on ServiceWorkerResponse having caseless
+ // headers so that it can quickly lookup vary headers.
+ ServiceWorkerResponse response(GURL("http://www.example.com"),
+ 200,
+ "OK",
+ blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(),
+ "",
+ 0);
+ response.headers["content-type"] = "foo";
+ response.headers["Content-Type"] = "bar";
+ EXPECT_EQ("bar", response.headers["content-type"]);
+}
+
+TEST_F(ServiceWorkerCacheTest, CaselessServiceWorkerFetchRequestHeaders) {
+ // ServiceWorkerCache depends on ServiceWorkerFetchRequest having caseless
+ // headers so that it can quickly lookup vary headers.
+ ServiceWorkerFetchRequest request(GURL("http://www.example.com"),
+ "GET",
+ ServiceWorkerHeaderMap(),
+ GURL(""),
+ false);
+ request.headers["content-type"] = "foo";
+ request.headers["Content-Type"] = "bar";
+ EXPECT_EQ("bar", request.headers["content-type"]);
+}
+
+TEST_P(ServiceWorkerCacheTestP, QuotaManagerModified) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
+
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
+ EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
+ int64 sum_delta = quota_manager_proxy_->last_notified_delta();
+
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
+ EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
+ sum_delta += quota_manager_proxy_->last_notified_delta();
+
+ EXPECT_TRUE(Delete(body_request_));
+ EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count());
+ sum_delta += quota_manager_proxy_->last_notified_delta();
+
+ EXPECT_TRUE(Delete(no_body_request_));
+ EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count());
+ sum_delta += quota_manager_proxy_->last_notified_delta();
+
+ EXPECT_EQ(0, sum_delta);
+}
+
+TEST_F(ServiceWorkerCacheMemoryOnlyTest, MemoryBackedSize) {
+ EXPECT_EQ(0, cache_->MemoryBackedSize());
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_LT(0, cache_->MemoryBackedSize());
+ int64 no_body_size = cache_->MemoryBackedSize();
+
+ EXPECT_TRUE(Delete(no_body_request_));
+ EXPECT_EQ(0, cache_->MemoryBackedSize());
+
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
+
+ EXPECT_TRUE(Delete(body_request_));
+ EXPECT_EQ(0, cache_->MemoryBackedSize());
+}
+
+TEST_F(ServiceWorkerCacheTest, MemoryBackedSizePersistent) {
+ EXPECT_EQ(0, cache_->MemoryBackedSize());
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_EQ(0, cache_->MemoryBackedSize());
+}
+
+TEST_P(ServiceWorkerCacheTestP, OpsFailOnClosedBackendNeverCreated) {
+ cache_->set_pause_backend_creation(
+ true); // Will hang the test if a backend is created.
+ EXPECT_TRUE(Close());
+ VerifyAllOpsFail();
+}
+
+TEST_P(ServiceWorkerCacheTestP, OpsFailOnClosedBackend) {
+ // Create the backend and put something in it.
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Close());
+ VerifyAllOpsFail();
+}
+
+TEST_F(ServiceWorkerCacheTest, ClosedDuringPut) {
+ // Even though Close is called in the middle of a Put operation (during
+ // backend creation), the put operation should still finish.
+ cache_->set_pause_backend_creation(true);
+ scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
+ cache_->Put(CopyFetchRequest(body_request_),
+ CopyFetchResponse(body_response_),
+ base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
+ base::Unretained(this), nullptr));
+ cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
+ base::Unretained(this), close_loop.get()));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(callback_response_);
+ EXPECT_FALSE(callback_closed_);
+
+ cache_->ContinueCreateBackend();
+
+ close_loop->Run();
+ EXPECT_TRUE(callback_response_);
+ EXPECT_TRUE(callback_closed_);
+
+ VerifyAllOpsFail();
+}
+
+TEST_F(ServiceWorkerCacheTest, ClosedDuringMatch) {
+ // Even though Close is called in the middle of a Match operation (during
+ // backend creation), the match operation should still finish.
+ cache_->set_pause_backend_creation(true);
+ scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
+ cache_->Match(CopyFetchRequest(body_request_),
+ base::Bind(&ServiceWorkerCacheTest::ResponseAndErrorCallback,
+ base::Unretained(this), nullptr));
+ cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
+ base::Unretained(this), close_loop.get()));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
+ EXPECT_FALSE(callback_closed_);
+
+ cache_->ContinueCreateBackend();
+
+ close_loop->Run();
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
+ EXPECT_TRUE(callback_closed_);
+
+ VerifyAllOpsFail();
+}
+
+TEST_F(ServiceWorkerCacheTest, ClosedDuringDelete) {
+ // Even though Close is called in the middle of a Delete operation (during
+ // backend creation), the delete operation should still finish.
+ cache_->set_pause_backend_creation(true);
+ scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
+ cache_->Delete(CopyFetchRequest(body_request_),
+ base::Bind(&ServiceWorkerCacheTest::ErrorTypeCallback,
+ base::Unretained(this), nullptr));
+ cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
+ base::Unretained(this), close_loop.get()));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
+ EXPECT_FALSE(callback_closed_);
+
+ cache_->ContinueCreateBackend();
+
+ close_loop->Run();
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
+ EXPECT_TRUE(callback_closed_);
+
+ VerifyAllOpsFail();
+}
+
+TEST_F(ServiceWorkerCacheTest, ClosedDuringKeys) {
+ // Even though Close is called in the middle of a Keys operation (during
+ // backend creation), the keys operation should still finish.
+ cache_->set_pause_backend_creation(true);
+ scoped_ptr<base::RunLoop> close_loop(new base::RunLoop());
+ callback_error_ = ServiceWorkerCache::ErrorTypeNotFound;
+ cache_->Keys(base::Bind(&ServiceWorkerCacheTest::RequestsCallback,
+ base::Unretained(this), nullptr));
+ cache_->Close(base::Bind(&ServiceWorkerCacheTest::CloseCallback,
+ base::Unretained(this), close_loop.get()));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeNotFound, callback_error_);
+ EXPECT_FALSE(callback_closed_);
+
+ cache_->ContinueCreateBackend();
+
+ close_loop->Run();
+ EXPECT_EQ(ServiceWorkerCache::ErrorTypeOK, callback_error_);
+ EXPECT_TRUE(callback_closed_);
+
+ VerifyAllOpsFail();
+}
+
+INSTANTIATE_TEST_CASE_P(ServiceWorkerCacheTest,
+ ServiceWorkerCacheTestP,
+ ::testing::Values(false, true));
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
index cdc67460bcc..2272c95851b 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -4,12 +4,17 @@
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/files/file_path.h"
-#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/service_worker_cache_storage_manager.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_database_task_manager.h"
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
@@ -18,9 +23,33 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/public/browser/browser_thread.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
#include "url/gurl.h"
namespace content {
+namespace {
+void SuccessCollectorCallback(const base::Closure& done_closure,
+ bool* overall_success,
+ ServiceWorkerStatusCode status) {
+ if (status != ServiceWorkerStatusCode::SERVICE_WORKER_OK) {
+ *overall_success = false;
+ }
+ done_closure.Run();
+}
+
+void SuccessReportingCallback(
+ const bool* success,
+ const ServiceWorkerContextCore::UnregistrationCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ bool result = *success;
+ callback.Run(result ? ServiceWorkerStatusCode::SERVICE_WORKER_OK
+ : ServiceWorkerStatusCode::SERVICE_WORKER_ERROR_FAILED);
+}
+} // namespace
+
+const base::FilePath::CharType
+ ServiceWorkerContextCore::kServiceWorkerDirectory[] =
+ FILE_PATH_LITERAL("Service Worker");
ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
@@ -33,7 +62,7 @@ ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
DCHECK(!IsAtEnd());
DCHECK(!provider_host_iterator_->IsAtEnd());
- DCHECK(!provider_iterator_->IsAtEnd());
+ DCHECK(!process_iterator_->IsAtEnd());
// Advance the inner iterator. If an element is reached, we're done.
provider_host_iterator_->Advance();
@@ -42,10 +71,10 @@ void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
// Advance the outer iterator until an element is reached, or end is hit.
while (true) {
- provider_iterator_->Advance();
- if (provider_iterator_->IsAtEnd())
+ process_iterator_->Advance();
+ if (process_iterator_->IsAtEnd())
return;
- ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
+ ProviderMap* provider_map = process_iterator_->GetCurrentValue();
provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
if (!provider_host_iterator_->IsAtEnd())
return;
@@ -53,7 +82,7 @@ void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
}
bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
- return provider_iterator_->IsAtEnd() &&
+ return process_iterator_->IsAtEnd() &&
(!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
}
@@ -65,37 +94,65 @@ ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
}
void ServiceWorkerContextCore::ProviderHostIterator::Initialize() {
- provider_iterator_.reset(new ProcessToProviderMap::iterator(map_));
+ process_iterator_.reset(new ProcessToProviderMap::iterator(map_));
// Advance to the first element.
- while (!provider_iterator_->IsAtEnd()) {
- ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
+ while (!process_iterator_->IsAtEnd()) {
+ ProviderMap* provider_map = process_iterator_->GetCurrentValue();
provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
if (!provider_host_iterator_->IsAtEnd())
return;
- provider_iterator_->Advance();
+ process_iterator_->Advance();
}
}
ServiceWorkerContextCore::ServiceWorkerContextCore(
const base::FilePath& path,
- base::SequencedTaskRunner* database_task_runner,
- base::MessageLoopProxy* disk_cache_thread,
- quota::QuotaManagerProxy* quota_manager_proxy,
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy,
ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
ServiceWorkerContextWrapper* wrapper)
: weak_factory_(this),
wrapper_(wrapper),
- storage_(new ServiceWorkerStorage(path,
- AsWeakPtr(),
- database_task_runner,
- disk_cache_thread,
- quota_manager_proxy)),
- embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())),
+ providers_(new ProcessToProviderMap),
+ storage_(ServiceWorkerStorage::Create(path,
+ AsWeakPtr(),
+ database_task_manager.Pass(),
+ disk_cache_thread,
+ quota_manager_proxy,
+ special_storage_policy)),
+ cache_manager_(ServiceWorkerCacheStorageManager::Create(
+ path,
+ cache_task_runner.get(),
+ make_scoped_refptr(quota_manager_proxy))),
+ embedded_worker_registry_(EmbeddedWorkerRegistry::Create(AsWeakPtr())),
job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
next_handle_id_(0),
+ next_registration_handle_id_(0),
observer_list_(observer_list) {
}
+ServiceWorkerContextCore::ServiceWorkerContextCore(
+ ServiceWorkerContextCore* old_context,
+ ServiceWorkerContextWrapper* wrapper)
+ : weak_factory_(this),
+ wrapper_(wrapper),
+ providers_(old_context->providers_.release()),
+ storage_(
+ ServiceWorkerStorage::Create(AsWeakPtr(), old_context->storage())),
+ cache_manager_(ServiceWorkerCacheStorageManager::Create(
+ old_context->cache_manager())),
+ embedded_worker_registry_(EmbeddedWorkerRegistry::Create(
+ AsWeakPtr(),
+ old_context->embedded_worker_registry())),
+ job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
+ next_handle_id_(old_context->next_handle_id_),
+ next_registration_handle_id_(old_context->next_registration_handle_id_),
+ observer_list_(old_context->observer_list_) {
+}
+
ServiceWorkerContextCore::~ServiceWorkerContextCore() {
for (VersionMap::iterator it = live_versions_.begin();
it != live_versions_.end();
@@ -119,7 +176,7 @@ void ServiceWorkerContextCore::AddProviderHost(
ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id());
if (!map) {
map = new ProviderMap;
- providers_.AddWithID(map, host_ptr->process_id());
+ providers_->AddWithID(map, host_ptr->process_id());
}
map->AddWithID(host_ptr, host_ptr->provider_id());
}
@@ -133,30 +190,31 @@ void ServiceWorkerContextCore::RemoveProviderHost(
void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
int process_id) {
- if (providers_.Lookup(process_id))
- providers_.Remove(process_id);
+ if (providers_->Lookup(process_id))
+ providers_->Remove(process_id);
}
scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
ServiceWorkerContextCore::GetProviderHostIterator() {
- return make_scoped_ptr(new ProviderHostIterator(&providers_));
+ return make_scoped_ptr(new ProviderHostIterator(providers_.get()));
}
void ServiceWorkerContextCore::RegisterServiceWorker(
const GURL& pattern,
const GURL& script_url,
- int source_process_id,
ServiceWorkerProviderHost* provider_host,
const RegistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // TODO(kinuko): Wire the provider_host so that we can tell which document
- // is calling .register.
+ if (storage()->IsDisabled()) {
+ callback.Run(SERVICE_WORKER_ERROR_ABORT,
+ kInvalidServiceWorkerRegistrationId);
+ return;
+ }
job_coordinator_->Register(
pattern,
script_url,
- source_process_id,
+ provider_host,
base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
AsWeakPtr(),
pattern,
@@ -167,6 +225,10 @@ void ServiceWorkerContextCore::UnregisterServiceWorker(
const GURL& pattern,
const UnregistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (storage()->IsDisabled()) {
+ callback.Run(SERVICE_WORKER_ERROR_ABORT);
+ return;
+ }
job_coordinator_->Unregister(
pattern,
@@ -176,26 +238,67 @@ void ServiceWorkerContextCore::UnregisterServiceWorker(
callback));
}
+void ServiceWorkerContextCore::UnregisterServiceWorkers(
+ const GURL& origin,
+ const UnregistrationCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (storage()->IsDisabled()) {
+ // Not posting as new task to match implementations above.
+ callback.Run(SERVICE_WORKER_ERROR_ABORT);
+ return;
+ }
+
+ storage()->GetAllRegistrations(base::Bind(
+ &ServiceWorkerContextCore::DidGetAllRegistrationsForUnregisterForOrigin,
+ AsWeakPtr(),
+ callback,
+ origin));
+}
+
+void ServiceWorkerContextCore::DidGetAllRegistrationsForUnregisterForOrigin(
+ const UnregistrationCallback& result,
+ const GURL& origin,
+ const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
+ std::set<GURL> scopes;
+ for (const auto& registration_info : registrations) {
+ if (origin == registration_info.pattern.GetOrigin()) {
+ scopes.insert(registration_info.pattern);
+ }
+ }
+ bool* overall_success = new bool(true);
+ base::Closure barrier = base::BarrierClosure(
+ scopes.size(),
+ base::Bind(
+ &SuccessReportingCallback, base::Owned(overall_success), result));
+
+ for (const GURL& scope : scopes) {
+ UnregisterServiceWorker(
+ scope, base::Bind(&SuccessCollectorCallback, barrier, overall_success));
+ }
+}
+
+void ServiceWorkerContextCore::UpdateServiceWorker(
+ ServiceWorkerRegistration* registration) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (storage()->IsDisabled())
+ return;
+ job_coordinator_->Update(registration);
+}
+
void ServiceWorkerContextCore::RegistrationComplete(
const GURL& pattern,
const ServiceWorkerContextCore::RegistrationCallback& callback,
ServiceWorkerStatusCode status,
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version) {
+ ServiceWorkerRegistration* registration) {
if (status != SERVICE_WORKER_OK) {
- DCHECK(!version);
- callback.Run(status,
- kInvalidServiceWorkerRegistrationId,
- kInvalidServiceWorkerVersionId);
+ DCHECK(!registration);
+ callback.Run(status, kInvalidServiceWorkerRegistrationId);
return;
}
- DCHECK(version);
- DCHECK_EQ(version->registration_id(), registration->id());
- callback.Run(status,
- registration->id(),
- version->version_id());
- if (observer_list_) {
+ DCHECK(registration);
+ callback.Run(status, registration->id());
+ if (observer_list_.get()) {
observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationStored,
pattern);
}
@@ -206,7 +309,7 @@ void ServiceWorkerContextCore::UnregistrationComplete(
const ServiceWorkerContextCore::UnregistrationCallback& callback,
ServiceWorkerStatusCode status) {
callback.Run(status);
- if (observer_list_) {
+ if (observer_list_.get()) {
observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationDeleted,
pattern);
}
@@ -272,8 +375,34 @@ int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
return next_handle_id_++;
}
+int ServiceWorkerContextCore::GetNewRegistrationHandleId() {
+ return next_registration_handle_id_++;
+}
+
+void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const {
+ storage_->Disable();
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ServiceWorkerContextWrapper::DeleteAndStartOver, wrapper_));
+}
+
+void ServiceWorkerContextCore::DeleteAndStartOver(
+ const StatusCallback& callback) {
+ job_coordinator_->AbortAll();
+ storage_->DeleteAndStartOver(callback);
+}
+
+void ServiceWorkerContextCore::SetBlobParametersForCache(
+ net::URLRequestContext* request_context,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ cache_manager_->SetBlobParametersForCache(request_context,
+ blob_storage_context);
+}
+
void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
- if (!observer_list_)
+ if (!observer_list_.get())
return;
observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
version->version_id(),
@@ -282,7 +411,7 @@ void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
}
void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
- if (!observer_list_)
+ if (!observer_list_.get())
return;
observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
version->version_id(),
@@ -292,7 +421,7 @@ void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
void ServiceWorkerContextCore::OnVersionStateChanged(
ServiceWorkerVersion* version) {
- if (!observer_list_)
+ if (!observer_list_.get())
return;
observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
version->version_id());
@@ -304,7 +433,7 @@ void ServiceWorkerContextCore::OnErrorReported(
int line_number,
int column_number,
const GURL& source_url) {
- if (!observer_list_)
+ if (!observer_list_.get())
return;
observer_list_->Notify(
&ServiceWorkerContextObserver::OnErrorReported,
@@ -322,7 +451,7 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
const base::string16& message,
int line_number,
const GURL& source_url) {
- if (!observer_list_)
+ if (!observer_list_.get())
return;
observer_list_->Notify(
&ServiceWorkerContextObserver::OnReportConsoleMessage,
@@ -334,7 +463,9 @@ void ServiceWorkerContextCore::OnReportConsoleMessage(
}
ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
- return wrapper_->process_manager();
+ if (wrapper_)
+ return wrapper_->process_manager();
+ return NULL;
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.h b/chromium/content/browser/service_worker/service_worker_context_core.h
index b3f97ae28f3..63522ea3b39 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -25,19 +25,26 @@ class GURL;
namespace base {
class FilePath;
-class MessageLoopProxy;
class SequencedTaskRunner;
+class SingleThreadTaskRunner;
}
-namespace quota {
+namespace net {
+class URLRequestContext;
+}
+
+namespace storage {
class QuotaManagerProxy;
+class SpecialStoragePolicy;
}
namespace content {
class EmbeddedWorkerRegistry;
+class ServiceWorkerCacheStorageManager;
class ServiceWorkerContextObserver;
class ServiceWorkerContextWrapper;
+class ServiceWorkerDatabaseTaskManager;
class ServiceWorkerHandle;
class ServiceWorkerJobCoordinator;
class ServiceWorkerProviderHost;
@@ -50,16 +57,19 @@ class ServiceWorkerStorage;
// is the root of the containment hierarchy for service worker data
// associated with a particular partition.
class CONTENT_EXPORT ServiceWorkerContextCore
- : public ServiceWorkerVersion::Listener {
+ : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
public:
+ typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
typedef base::Callback<void(ServiceWorkerStatusCode status,
- int64 registration_id,
- int64 version_id)> RegistrationCallback;
+ int64 registration_id)> RegistrationCallback;
typedef base::Callback<
void(ServiceWorkerStatusCode status)> UnregistrationCallback;
typedef IDMap<ServiceWorkerProviderHost, IDMapOwnPointer> ProviderMap;
typedef IDMap<ProviderMap, IDMapOwnPointer> ProcessToProviderMap;
+ // Directory for ServiceWorkerStorage and ServiceWorkerCacheManager.
+ static const base::FilePath::CharType kServiceWorkerDirectory[];
+
// Iterates over ServiceWorkerProviderHost objects in a ProcessToProviderMap.
class ProviderHostIterator {
public:
@@ -74,7 +84,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
void Initialize();
ProcessToProviderMap* map_;
- scoped_ptr<ProcessToProviderMap::iterator> provider_iterator_;
+ scoped_ptr<ProcessToProviderMap::iterator> process_iterator_;
scoped_ptr<ProviderMap::iterator> provider_host_iterator_;
DISALLOW_COPY_AND_ASSIGN(ProviderHostIterator);
@@ -88,30 +98,38 @@ class CONTENT_EXPORT ServiceWorkerContextCore
// be called on the thread which called AddObserver() of |observer_list|.
ServiceWorkerContextCore(
const base::FilePath& user_data_directory,
- base::SequencedTaskRunner* database_task_runner,
- base::MessageLoopProxy* disk_cache_thread,
- quota::QuotaManagerProxy* quota_manager_proxy,
+ const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_runner_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy,
ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
ServiceWorkerContextWrapper* wrapper);
- virtual ~ServiceWorkerContextCore();
+ ServiceWorkerContextCore(
+ ServiceWorkerContextCore* old_context,
+ ServiceWorkerContextWrapper* wrapper);
+ ~ServiceWorkerContextCore() override;
// ServiceWorkerVersion::Listener overrides.
- virtual void OnWorkerStarted(ServiceWorkerVersion* version) OVERRIDE;
- virtual void OnWorkerStopped(ServiceWorkerVersion* version) OVERRIDE;
- virtual void OnVersionStateChanged(ServiceWorkerVersion* version) OVERRIDE;
- virtual void OnErrorReported(ServiceWorkerVersion* version,
- const base::string16& error_message,
- int line_number,
- int column_number,
- const GURL& source_url) OVERRIDE;
- virtual void OnReportConsoleMessage(ServiceWorkerVersion* version,
- int source_identifier,
- int message_level,
- const base::string16& message,
- int line_number,
- const GURL& source_url) OVERRIDE;
+ void OnWorkerStarted(ServiceWorkerVersion* version) override;
+ void OnWorkerStopped(ServiceWorkerVersion* version) override;
+ void OnVersionStateChanged(ServiceWorkerVersion* version) override;
+ void OnErrorReported(ServiceWorkerVersion* version,
+ const base::string16& error_message,
+ int line_number,
+ int column_number,
+ const GURL& source_url) override;
+ void OnReportConsoleMessage(ServiceWorkerVersion* version,
+ int source_identifier,
+ int message_level,
+ const base::string16& message,
+ int line_number,
+ const GURL& source_url) override;
ServiceWorkerStorage* storage() { return storage_.get(); }
+ ServiceWorkerCacheStorageManager* cache_manager() {
+ return cache_manager_.get();
+ }
ServiceWorkerProcessManager* process_manager();
EmbeddedWorkerRegistry* embedded_worker_registry() {
return embedded_worker_registry_.get();
@@ -127,20 +145,21 @@ class CONTENT_EXPORT ServiceWorkerContextCore
void RemoveAllProviderHostsForProcess(int process_id);
scoped_ptr<ProviderHostIterator> GetProviderHostIterator();
- // The callback will be called on the IO thread.
// A child process of |source_process_id| may be used to run the created
// worker for initial installation.
- // Non-null |provider_host| must be given if this is called from a document,
- // whose process_id() must match with |source_process_id|.
+ // Non-null |provider_host| must be given if this is called from a document.
void RegisterServiceWorker(const GURL& pattern,
const GURL& script_url,
- int source_process_id,
ServiceWorkerProviderHost* provider_host,
const RegistrationCallback& callback);
-
- // The callback will be called on the IO thread.
void UnregisterServiceWorker(const GURL& pattern,
const UnregistrationCallback& callback);
+ // Callback is called issued after all unregistrations occur. The Status
+ // is populated as SERVICE_WORKER_OK if all succeed, or SERVICE_WORKER_FAILED
+ // if any did not succeed.
+ void UnregisterServiceWorkers(const GURL& origin,
+ const UnregistrationCallback& callback);
+ void UpdateServiceWorker(ServiceWorkerRegistration* registration);
// This class maintains collections of live instances, this class
// does not own these object or influence their lifetime.
@@ -154,8 +173,19 @@ class CONTENT_EXPORT ServiceWorkerContextCore
std::vector<ServiceWorkerRegistrationInfo> GetAllLiveRegistrationInfo();
std::vector<ServiceWorkerVersionInfo> GetAllLiveVersionInfo();
- // Returns new context-local unique ID for ServiceWorkerHandle.
+ // Returns new context-local unique ID.
int GetNewServiceWorkerHandleId();
+ int GetNewRegistrationHandleId();
+
+ void ScheduleDeleteAndStartOver() const;
+
+ // Deletes all files on disk and restarts the system. This leaves the system
+ // in a disabled state until it's done.
+ void DeleteAndStartOver(const StatusCallback& callback);
+
+ void SetBlobParametersForCache(
+ net::URLRequestContext* request_context,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context);
base::WeakPtr<ServiceWorkerContextCore> AsWeakPtr() {
return weak_factory_.GetWeakPtr();
@@ -166,31 +196,37 @@ class CONTENT_EXPORT ServiceWorkerContextCore
typedef std::map<int64, ServiceWorkerVersion*> VersionMap;
ProviderMap* GetProviderMapForProcess(int process_id) {
- return providers_.Lookup(process_id);
+ return providers_->Lookup(process_id);
}
void RegistrationComplete(const GURL& pattern,
const RegistrationCallback& callback,
ServiceWorkerStatusCode status,
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version);
+ ServiceWorkerRegistration* registration);
void UnregistrationComplete(const GURL& pattern,
const UnregistrationCallback& callback,
ServiceWorkerStatusCode status);
+ void DidGetAllRegistrationsForUnregisterForOrigin(
+ const UnregistrationCallback& result,
+ const GURL& origin,
+ const std::vector<ServiceWorkerRegistrationInfo>& registrations);
+
base::WeakPtrFactory<ServiceWorkerContextCore> weak_factory_;
// It's safe to store a raw pointer instead of a scoped_refptr to |wrapper_|
// because the Wrapper::Shutdown call that hops threads to destroy |this| uses
// Bind() to hold a reference to |wrapper_| until |this| is fully destroyed.
ServiceWorkerContextWrapper* wrapper_;
- ProcessToProviderMap providers_;
+ scoped_ptr<ProcessToProviderMap> providers_;
scoped_ptr<ServiceWorkerStorage> storage_;
+ scoped_ptr<ServiceWorkerCacheStorageManager> cache_manager_;
scoped_refptr<EmbeddedWorkerRegistry> embedded_worker_registry_;
scoped_ptr<ServiceWorkerJobCoordinator> job_coordinator_;
std::map<int64, ServiceWorkerRegistration*> live_registrations_;
std::map<int64, ServiceWorkerVersion*> live_versions_;
int next_handle_id_;
+ int next_registration_handle_id_;
scoped_refptr<ObserverListThreadSafe<ServiceWorkerContextObserver> >
observer_list_;
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
index 248587fceb7..3bd8418c227 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
@@ -4,12 +4,15 @@
#include "content/browser/service_worker/service_worker_context_request_handler.h"
+#include "base/time/time.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_read_from_cache_job.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
+#include "content/public/browser/resource_context.h"
+#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
namespace content {
@@ -17,8 +20,8 @@ namespace content {
ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
- ResourceType::Type resource_type)
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ ResourceType resource_type)
: ServiceWorkerRequestHandler(context,
provider_host,
blob_storage_context,
@@ -32,8 +35,9 @@ ServiceWorkerContextRequestHandler::~ServiceWorkerContextRequestHandler() {
net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) {
- if (!provider_host_ || !version_ || !context_)
+ net::NetworkDelegate* network_delegate,
+ ResourceContext* resource_context) {
+ if (!provider_host_ || !version_.get() || !context_)
return NULL;
// We currently have no use case for hijacking a redirected request.
@@ -45,17 +49,35 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
// retrieve it from the script cache.
// TODO(michaeln): Get the desired behavior clarified in the spec,
// and make tweak the behavior here to match.
- if (resource_type_ != ResourceType::SERVICE_WORKER &&
- resource_type_ != ResourceType::SCRIPT) {
+ if (resource_type_ != RESOURCE_TYPE_SERVICE_WORKER &&
+ resource_type_ != RESOURCE_TYPE_SCRIPT) {
return NULL;
}
if (ShouldAddToScriptCache(request->url())) {
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(version_->registration_id());
+ DCHECK(registration); // We're registering or updating so must be there.
+
int64 response_id = context_->storage()->NewResourceId();
if (response_id == kInvalidServiceWorkerResponseId)
return NULL;
- return new ServiceWorkerWriteToCacheJob(
- request, network_delegate, context_, version_, response_id);
+
+ // Bypass the browser cache for initial installs and update
+ // checks after 24 hours have passed.
+ int extra_load_flags = 0;
+ base::TimeDelta time_since_last_check =
+ base::Time::Now() - registration->last_update_check();
+ if (time_since_last_check > base::TimeDelta::FromHours(24))
+ extra_load_flags = net::LOAD_BYPASS_CACHE;
+
+ return new ServiceWorkerWriteToCacheJob(request,
+ network_delegate,
+ resource_type_,
+ context_,
+ version_.get(),
+ extra_load_flags,
+ response_id);
}
int64 response_id = kInvalidServiceWorkerResponseId;
@@ -68,13 +90,30 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
return NULL;
}
+void ServiceWorkerContextRequestHandler::GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const {
+ *was_fetched_via_service_worker = false;
+ *was_fallback_required_by_service_worker = false;
+ *original_url_via_service_worker = GURL();
+ *response_type_via_service_worker =
+ blink::WebServiceWorkerResponseTypeDefault;
+}
+
bool ServiceWorkerContextRequestHandler::ShouldAddToScriptCache(
const GURL& url) {
// We only write imports that occur during the initial eval.
- if (version_->status() != ServiceWorkerVersion::NEW)
+ if (version_->status() != ServiceWorkerVersion::NEW &&
+ version_->status() != ServiceWorkerVersion::INSTALLING) {
return false;
- return version_->script_cache_map()->Lookup(url) ==
- kInvalidServiceWorkerResponseId;
+ }
+ return version_->script_cache_map()->LookupResourceId(url) ==
+ kInvalidServiceWorkerResponseId;
}
bool ServiceWorkerContextRequestHandler::ShouldReadFromScriptCache(
@@ -83,7 +122,7 @@ bool ServiceWorkerContextRequestHandler::ShouldReadFromScriptCache(
if (version_->status() == ServiceWorkerVersion::NEW ||
version_->status() == ServiceWorkerVersion::INSTALLING)
return false;
- *response_id_out = version_->script_cache_map()->Lookup(url);
+ *response_id_out = version_->script_cache_map()->LookupResourceId(url);
return *response_id_out != kInvalidServiceWorkerResponseId;
}
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler.h b/chromium/content/browser/service_worker/service_worker_context_request_handler.h
index ca894ce237e..c8af8ed5fd9 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler.h
@@ -19,14 +19,24 @@ class CONTENT_EXPORT ServiceWorkerContextRequestHandler
ServiceWorkerContextRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
- ResourceType::Type resource_type);
- virtual ~ServiceWorkerContextRequestHandler();
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ ResourceType resource_type);
+ ~ServiceWorkerContextRequestHandler() override;
// Called via custom URLRequestJobFactory.
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) OVERRIDE;
+ net::NetworkDelegate* network_delegate,
+ ResourceContext* resource_context) override;
+
+ void GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const override;
private:
bool ShouldAddToScriptCache(const GURL& url);
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
new file mode 100644
index 00000000000..c1063d726fa
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright 2014 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/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/fileapi/mock_url_request_delegate.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_request_handler.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/load_flags.h"
+#include "net/url_request/url_request_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+int kMockRenderProcessId = 1224;
+
+void EmptyCallback() {}
+
+}
+
+class ServiceWorkerContextRequestHandlerTest : public testing::Test {
+ public:
+ ServiceWorkerContextRequestHandlerTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(kMockRenderProcessId));
+
+ // A new unstored registration/version.
+ scope_ = GURL("http://host/scope/");
+ script_url_ = GURL("http://host/script.js");
+ registration_ = new ServiceWorkerRegistration(
+ scope_, 1L, context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), script_url_, 1L, context()->AsWeakPtr());
+
+ // An empty host.
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kMockRenderProcessId, 1 /* provider_id */,
+ context()->AsWeakPtr(), NULL));
+ provider_host_ = host->AsWeakPtr();
+ context()->AddProviderHost(host.Pass());
+
+ context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void TearDown() override {
+ version_ = NULL;
+ registration_ = NULL;
+ helper_.reset();
+ }
+
+ ServiceWorkerContextCore* context() const { return helper_->context(); }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ net::URLRequestContext url_request_context_;
+ MockURLRequestDelegate url_request_delegate_;
+ GURL scope_;
+ GURL script_url_;
+};
+
+TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateBefore24Hours) {
+ // Give the registration a very recent last update time and pretend
+ // we're installing a new version.
+ registration_->set_last_update_check(base::Time::Now());
+ version_->SetStatus(ServiceWorkerVersion::NEW);
+ provider_host_->running_hosted_version_ = version_;
+
+ // Conduct a resource fetch for the main script.
+ const GURL kScriptUrl("http://host/script.js");
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kScriptUrl,
+ net::DEFAULT_PRIORITY,
+ &url_request_delegate_,
+ NULL);
+ scoped_ptr<ServiceWorkerContextRequestHandler> handler(
+ new ServiceWorkerContextRequestHandler(
+ context()->AsWeakPtr(),
+ provider_host_,
+ base::WeakPtr<storage::BlobStorageContext>(),
+ RESOURCE_TYPE_SERVICE_WORKER));
+ scoped_refptr<net::URLRequestJob> job =
+ handler->MaybeCreateJob(request.get(), NULL, NULL);
+ ASSERT_TRUE(job.get());
+ ServiceWorkerWriteToCacheJob* sw_job =
+ static_cast<ServiceWorkerWriteToCacheJob*>(job.get());
+
+ // Verify the net request is not initialized to bypass the browser cache.
+ EXPECT_FALSE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
+}
+
+TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateAfter24Hours) {
+ // Give the registration a old update time and pretend
+ // we're installing a new version.
+ registration_->set_last_update_check(
+ base::Time::Now() - base::TimeDelta::FromDays(7));
+ version_->SetStatus(ServiceWorkerVersion::NEW);
+ provider_host_->running_hosted_version_ = version_;
+
+ // Conduct a resource fetch for the main script.
+ const GURL kScriptUrl("http://host/script.js");
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kScriptUrl,
+ net::DEFAULT_PRIORITY,
+ &url_request_delegate_,
+ NULL);
+ scoped_ptr<ServiceWorkerContextRequestHandler> handler(
+ new ServiceWorkerContextRequestHandler(
+ context()->AsWeakPtr(),
+ provider_host_,
+ base::WeakPtr<storage::BlobStorageContext>(),
+ RESOURCE_TYPE_SERVICE_WORKER));
+ scoped_refptr<net::URLRequestJob> job =
+ handler->MaybeCreateJob(request.get(), NULL, NULL);
+ ASSERT_TRUE(job.get());
+ ServiceWorkerWriteToCacheJob* sw_job =
+ static_cast<ServiceWorkerWriteToCacheJob*>(job.get());
+
+ // Verify the net request is initialized to bypass the browser cache.
+ EXPECT_TRUE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
index 14f54f7cb50..a5bba95facb 100644
--- a/chromium/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_unittest.cc
@@ -25,23 +25,17 @@ namespace {
void SaveResponseCallback(bool* called,
int64* store_registration_id,
- int64* store_version_id,
ServiceWorkerStatusCode status,
- int64 registration_id,
- int64 version_id) {
+ int64 registration_id) {
EXPECT_EQ(SERVICE_WORKER_OK, status) << ServiceWorkerStatusToString(status);
*called = true;
*store_registration_id = registration_id;
- *store_version_id = version_id;
}
ServiceWorkerContextCore::RegistrationCallback MakeRegisteredCallback(
bool* called,
- int64* store_registration_id,
- int64* store_version_id) {
- return base::Bind(&SaveResponseCallback, called,
- store_registration_id,
- store_version_id);
+ int64* store_registration_id) {
+ return base::Bind(&SaveResponseCallback, called, store_registration_id);
}
void CallCompletedCallback(bool* called, ServiceWorkerStatusCode) {
@@ -55,29 +49,24 @@ ServiceWorkerContextCore::UnregistrationCallback MakeUnregisteredCallback(
void ExpectRegisteredWorkers(
ServiceWorkerStatusCode expect_status,
- int64 expect_version_id,
bool expect_waiting,
bool expect_active,
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration) {
ASSERT_EQ(expect_status, status);
if (status != SERVICE_WORKER_OK) {
- EXPECT_FALSE(registration);
+ EXPECT_FALSE(registration.get());
return;
}
if (expect_waiting) {
EXPECT_TRUE(registration->waiting_version());
- EXPECT_EQ(expect_version_id,
- registration->waiting_version()->version_id());
} else {
EXPECT_FALSE(registration->waiting_version());
}
if (expect_active) {
EXPECT_TRUE(registration->active_version());
- EXPECT_EQ(expect_version_id,
- registration->active_version()->version_id());
} else {
EXPECT_FALSE(registration->active_version());
}
@@ -85,12 +74,12 @@ void ExpectRegisteredWorkers(
class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
public:
- RejectInstallTestHelper(int mock_render_process_id)
+ explicit RejectInstallTestHelper(int mock_render_process_id)
: EmbeddedWorkerTestHelper(mock_render_process_id) {}
- virtual void OnInstallEvent(int embedded_worker_id,
- int request_id,
- int active_version_id) OVERRIDE {
+ void OnInstallEvent(int embedded_worker_id,
+ int request_id,
+ int active_version_id) override {
SimulateSend(
new ServiceWorkerHostMsg_InstallEventFinished(
embedded_worker_id, request_id,
@@ -100,11 +89,10 @@ class RejectInstallTestHelper : public EmbeddedWorkerTestHelper {
class RejectActivateTestHelper : public EmbeddedWorkerTestHelper {
public:
- RejectActivateTestHelper(int mock_render_process_id)
+ explicit RejectActivateTestHelper(int mock_render_process_id)
: EmbeddedWorkerTestHelper(mock_render_process_id) {}
- virtual void OnActivateEvent(int embedded_worker_id,
- int request_id) OVERRIDE {
+ void OnActivateEvent(int embedded_worker_id, int request_id) override {
SimulateSend(
new ServiceWorkerHostMsg_ActivateEventFinished(
embedded_worker_id, request_id,
@@ -120,13 +108,11 @@ class ServiceWorkerContextTest : public testing::Test {
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
render_process_id_(99) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(render_process_id_));
}
- virtual void TearDown() OVERRIDE {
- helper_.reset();
- }
+ void TearDown() override { helper_.reset(); }
ServiceWorkerContextCore* context() { return helper_->context(); }
@@ -139,14 +125,12 @@ class ServiceWorkerContextTest : public testing::Test {
// Make sure basic registration is working.
TEST_F(ServiceWorkerContextTest, Register) {
int64 registration_id = kInvalidServiceWorkerRegistrationId;
- int64 version_id = kInvalidServiceWorkerVersionId;
bool called = false;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &registration_id, &version_id));
+ MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -162,14 +146,12 @@ TEST_F(ServiceWorkerContextTest, Register) {
EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
EmbeddedWorkerMsg_StopWorker::ID));
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
context()->storage()->FindRegistrationForId(
registration_id,
GURL("http://www.example.com"),
base::Bind(&ExpectRegisteredWorkers,
SERVICE_WORKER_OK,
- version_id,
false /* expect_waiting */,
true /* expect_active */));
base::RunLoop().RunUntilIdle();
@@ -182,14 +164,12 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
helper_.reset(); // Make sure the process lookups stay overridden.
helper_.reset(new RejectInstallTestHelper(render_process_id_));
int64 registration_id = kInvalidServiceWorkerRegistrationId;
- int64 version_id = kInvalidServiceWorkerVersionId;
bool called = false;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &registration_id, &version_id));
+ MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -205,14 +185,12 @@ TEST_F(ServiceWorkerContextTest, Register_RejectInstall) {
EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
EmbeddedWorkerMsg_StopWorker::ID));
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
context()->storage()->FindRegistrationForId(
registration_id,
GURL("http://www.example.com"),
base::Bind(&ExpectRegisteredWorkers,
SERVICE_WORKER_ERROR_NOT_FOUND,
- kInvalidServiceWorkerVersionId,
false /* expect_waiting */,
false /* expect_active */));
base::RunLoop().RunUntilIdle();
@@ -225,14 +203,12 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
helper_.reset(); // Make sure the process lookups stay overridden.
helper_.reset(new RejectActivateTestHelper(render_process_id_));
int64 registration_id = kInvalidServiceWorkerRegistrationId;
- int64 version_id = kInvalidServiceWorkerVersionId;
bool called = false;
context()->RegisterServiceWorker(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &registration_id, &version_id));
+ MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -248,14 +224,12 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
EXPECT_TRUE(helper_->ipc_sink()->GetUniqueMessageMatching(
EmbeddedWorkerMsg_StopWorker::ID));
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
context()->storage()->FindRegistrationForId(
registration_id,
GURL("http://www.example.com"),
base::Bind(&ExpectRegisteredWorkers,
SERVICE_WORKER_ERROR_NOT_FOUND,
- kInvalidServiceWorkerVersionId,
false /* expect_waiting */,
false /* expect_active */));
base::RunLoop().RunUntilIdle();
@@ -263,23 +237,20 @@ TEST_F(ServiceWorkerContextTest, Register_RejectActivate) {
// Make sure registrations are cleaned up when they are unregistered.
TEST_F(ServiceWorkerContextTest, Unregister) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
bool called = false;
int64 registration_id = kInvalidServiceWorkerRegistrationId;
- int64 version_id = kInvalidServiceWorkerVersionId;
context()->RegisterServiceWorker(
pattern,
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &registration_id, &version_id));
+ MakeRegisteredCallback(&called, &registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, version_id);
called = false;
context()->UnregisterServiceWorker(pattern,
@@ -294,92 +265,234 @@ TEST_F(ServiceWorkerContextTest, Unregister) {
pattern.GetOrigin(),
base::Bind(&ExpectRegisteredWorkers,
SERVICE_WORKER_ERROR_NOT_FOUND,
- kInvalidServiceWorkerVersionId,
false /* expect_waiting */,
false /* expect_active */));
base::RunLoop().RunUntilIdle();
}
-// Make sure that when a new registration replaces an existing
-// registration, that the old one is cleaned up.
+// Make sure registrations are cleaned up when they are unregistered in bulk.
+TEST_F(ServiceWorkerContextTest, UnregisterMultiple) {
+ GURL origin1_p1("http://www.example.com/test");
+ GURL origin1_p2("http://www.example.com/hello");
+ GURL origin2_p1("http://www.example.com:8080/again");
+ GURL origin3_p1("http://www.other.com/");
+
+ bool called = false;
+ int64 registration_id1 = kInvalidServiceWorkerRegistrationId;
+ int64 registration_id2 = kInvalidServiceWorkerRegistrationId;
+ int64 registration_id3 = kInvalidServiceWorkerRegistrationId;
+ int64 registration_id4 = kInvalidServiceWorkerRegistrationId;
+ context()->RegisterServiceWorker(
+ origin1_p1,
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ MakeRegisteredCallback(&called, &registration_id1));
+ context()->RegisterServiceWorker(
+ origin1_p2,
+ GURL("http://www.example.com/service_worker2.js"),
+ NULL,
+ MakeRegisteredCallback(&called, &registration_id2));
+ context()->RegisterServiceWorker(
+ origin2_p1,
+ GURL("http://www.example.com:8080/service_worker3.js"),
+ NULL,
+ MakeRegisteredCallback(&called, &registration_id3));
+ context()->RegisterServiceWorker(
+ origin3_p1,
+ GURL("http://www.other.com/service_worker4.js"),
+ NULL,
+ MakeRegisteredCallback(&called, &registration_id4));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id1);
+ EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id2);
+ EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id3);
+ EXPECT_NE(kInvalidServiceWorkerRegistrationId, registration_id4);
+
+ called = false;
+ context()->UnregisterServiceWorkers(origin1_p1.GetOrigin(),
+ MakeUnregisteredCallback(&called));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ context()->storage()->FindRegistrationForId(
+ registration_id1,
+ origin1_p1.GetOrigin(),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_ERROR_NOT_FOUND,
+ false /* expect_waiting */,
+ false /* expect_active */));
+ context()->storage()->FindRegistrationForId(
+ registration_id2,
+ origin1_p2.GetOrigin(),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_ERROR_NOT_FOUND,
+ false /* expect_waiting */,
+ false /* expect_active */));
+ context()->storage()->FindRegistrationForId(
+ registration_id3,
+ origin2_p1.GetOrigin(),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_OK,
+ false /* expect_waiting */,
+ true /* expect_active */));
+
+ context()->storage()->FindRegistrationForId(
+ registration_id4,
+ origin3_p1.GetOrigin(),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_OK,
+ false /* expect_waiting */,
+ true /* expect_active */));
+
+ base::RunLoop().RunUntilIdle();
+}
+
+// Make sure registering a new script shares an existing registration.
TEST_F(ServiceWorkerContextTest, RegisterNewScript) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
bool called = false;
int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
- int64 old_version_id = kInvalidServiceWorkerVersionId;
context()->RegisterServiceWorker(
pattern,
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
+ MakeRegisteredCallback(&called, &old_registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
called = false;
int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
- int64 new_version_id = kInvalidServiceWorkerVersionId;
context()->RegisterServiceWorker(
pattern,
GURL("http://www.example.com/service_worker_new.js"),
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
+ MakeRegisteredCallback(&called, &new_registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
- // Returned IDs should be valid, and should differ from the values
- // returned for the previous registration.
EXPECT_NE(kInvalidServiceWorkerRegistrationId, new_registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, new_version_id);
- EXPECT_NE(old_registration_id, new_registration_id);
- EXPECT_NE(old_version_id, new_version_id);
+ EXPECT_EQ(old_registration_id, new_registration_id);
}
// Make sure that when registering a duplicate pattern+script_url
// combination, that the same registration is used.
TEST_F(ServiceWorkerContextTest, RegisterDuplicateScript) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
bool called = false;
int64 old_registration_id = kInvalidServiceWorkerRegistrationId;
- int64 old_version_id = kInvalidServiceWorkerVersionId;
context()->RegisterServiceWorker(
pattern,
script_url,
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &old_registration_id, &old_version_id));
+ MakeRegisteredCallback(&called, &old_registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
EXPECT_NE(kInvalidServiceWorkerRegistrationId, old_registration_id);
- EXPECT_NE(kInvalidServiceWorkerVersionId, old_version_id);
called = false;
int64 new_registration_id = kInvalidServiceWorkerRegistrationId;
- int64 new_version_id = kInvalidServiceWorkerVersionId;
context()->RegisterServiceWorker(
pattern,
script_url,
- render_process_id_,
NULL,
- MakeRegisteredCallback(&called, &new_registration_id, &new_version_id));
+ MakeRegisteredCallback(&called, &new_registration_id));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
EXPECT_EQ(old_registration_id, new_registration_id);
- EXPECT_EQ(old_version_id, new_version_id);
+}
+
+// TODO(nhiroki): Test this for on-disk storage.
+TEST_F(ServiceWorkerContextTest, DeleteAndStartOver) {
+ int64 registration_id = kInvalidServiceWorkerRegistrationId;
+ bool called = false;
+ context()->RegisterServiceWorker(
+ GURL("http://www.example.com/"),
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ MakeRegisteredCallback(&called, &registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ context()->storage()->FindRegistrationForId(
+ registration_id,
+ GURL("http://www.example.com"),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_OK,
+ false /* expect_waiting */,
+ true /* expect_active */));
+ base::RunLoop().RunUntilIdle();
+
+ // Next handle ids should be 0 (the next call should return 1).
+ EXPECT_EQ(0, context()->GetNewServiceWorkerHandleId());
+ EXPECT_EQ(0, context()->GetNewRegistrationHandleId());
+
+ context()->ScheduleDeleteAndStartOver();
+
+ // The storage is disabled while the recovery process is running, so the
+ // operation should be failed.
+ context()->storage()->FindRegistrationForId(
+ registration_id,
+ GURL("http://www.example.com"),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_ERROR_FAILED,
+ false /* expect_waiting */,
+ true /* expect_active */));
+ base::RunLoop().RunUntilIdle();
+
+ // The context started over and the storage was re-initialized, so the
+ // registration should not be found.
+ context()->storage()->FindRegistrationForId(
+ registration_id,
+ GURL("http://www.example.com"),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_ERROR_NOT_FOUND,
+ false /* expect_waiting */,
+ true /* expect_active */));
+ base::RunLoop().RunUntilIdle();
+
+ called = false;
+ context()->RegisterServiceWorker(
+ GURL("http://www.example.com/"),
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ MakeRegisteredCallback(&called, &registration_id));
+
+ ASSERT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ context()->storage()->FindRegistrationForId(
+ registration_id,
+ GURL("http://www.example.com"),
+ base::Bind(&ExpectRegisteredWorkers,
+ SERVICE_WORKER_OK,
+ false /* expect_waiting */,
+ true /* expect_active */));
+ base::RunLoop().RunUntilIdle();
+
+ // The new context should take over next handle ids.
+ EXPECT_EQ(1, context()->GetNewServiceWorkerHandleId());
+ EXPECT_EQ(1, context()->GetNewRegistrationHandleId());
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
index 460f6df36e4..6a4fc0892ee 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -4,21 +4,59 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
+#include "content/browser/service_worker/service_worker_quota_client.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
+#include "content/public/browser/service_worker_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/special_storage_policy.h"
namespace content {
+namespace {
+
+typedef std::set<std::string> HeaderNameSet;
+base::LazyInstance<HeaderNameSet> g_excluded_header_name_set =
+ LAZY_INSTANCE_INITIALIZER;
+}
+
+void ServiceWorkerContext::AddExcludedHeadersForFetchEvent(
+ const std::set<std::string>& header_names) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ g_excluded_header_name_set.Get().insert(header_names.begin(),
+ header_names.end());
+}
+
+bool ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(
+ const std::string& header_name) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ return g_excluded_header_name_set.Get().find(header_name) !=
+ g_excluded_header_name_set.Get().end();
+}
+
ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
BrowserContext* browser_context)
: observer_list_(
new ObserverListThreadSafe<ServiceWorkerContextObserver>()),
- process_manager_(new ServiceWorkerProcessManager(browser_context)) {
+ process_manager_(new ServiceWorkerProcessManager(browser_context)),
+ is_incognito_(false) {
}
ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
@@ -26,16 +64,24 @@ ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
void ServiceWorkerContextWrapper::Init(
const base::FilePath& user_data_directory,
- quota::QuotaManagerProxy* quota_manager_proxy) {
- scoped_refptr<base::SequencedTaskRunner> database_task_runner =
- BrowserThread::GetBlockingPool()->
- GetSequencedTaskRunnerWithShutdownBehavior(
- BrowserThread::GetBlockingPool()->GetSequenceToken(),
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
- scoped_refptr<base::MessageLoopProxy> disk_cache_thread =
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy) {
+ is_incognito_ = user_data_directory.empty();
+ base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
+ new ServiceWorkerDatabaseTaskManagerImpl(pool));
+ scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread =
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE);
- InitInternal(user_data_directory, database_task_runner,
- disk_cache_thread, quota_manager_proxy);
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner =
+ pool->GetSequencedTaskRunnerWithShutdownBehavior(
+ BrowserThread::GetBlockingPool()->GetSequenceToken(),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+ InitInternal(user_data_directory,
+ cache_task_runner,
+ database_task_manager.Pass(),
+ disk_cache_thread,
+ quota_manager_proxy,
+ special_storage_policy);
}
void ServiceWorkerContextWrapper::Shutdown() {
@@ -47,6 +93,12 @@ void ServiceWorkerContextWrapper::Shutdown() {
base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
}
+void ServiceWorkerContextWrapper::DeleteAndStartOver() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ context_core_->DeleteAndStartOver(
+ base::Bind(&ServiceWorkerContextWrapper::DidDeleteAndStartOver, this));
+}
+
ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return context_core_.get();
@@ -55,8 +107,7 @@ ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
static void FinishRegistrationOnIO(
const ServiceWorkerContext::ResultCallback& continuation,
ServiceWorkerStatusCode status,
- int64 registration_id,
- int64 version_id) {
+ int64 registration_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI,
@@ -79,11 +130,17 @@ void ServiceWorkerContextWrapper::RegisterServiceWorker(
continuation));
return;
}
-
+ if (!context_core_.get()) {
+ LOG(ERROR) << "ServiceWorkerContextCore is no longer alive.";
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(continuation, false));
+ return;
+ }
context()->RegisterServiceWorker(
pattern,
script_url,
- -1,
NULL /* provider_host */,
base::Bind(&FinishRegistrationOnIO, continuation));
}
@@ -111,15 +168,89 @@ void ServiceWorkerContextWrapper::UnregisterServiceWorker(
continuation));
return;
}
+ if (!context_core_.get()) {
+ LOG(ERROR) << "ServiceWorkerContextCore is no longer alive.";
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(continuation, false));
+ return;
+ }
context()->UnregisterServiceWorker(
pattern,
base::Bind(&FinishUnregistrationOnIO, continuation));
}
-void ServiceWorkerContextWrapper::Terminate() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- process_manager_->Shutdown();
+void ServiceWorkerContextWrapper::GetAllOriginsInfo(
+ const GetUsageInfoCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!context_core_.get()) {
+ LOG(ERROR) << "ServiceWorkerContextCore is no longer alive.";
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback, std::vector<ServiceWorkerUsageInfo>()));
+ return;
+ }
+ context()->storage()->GetAllRegistrations(base::Bind(
+ &ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins,
+ this,
+ callback));
+}
+
+void ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins(
+ const GetUsageInfoCallback& callback,
+ const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::vector<ServiceWorkerUsageInfo> usage_infos;
+
+ std::map<GURL, ServiceWorkerUsageInfo> origins;
+ for (const auto& registration_info : registrations) {
+ GURL origin = registration_info.pattern.GetOrigin();
+
+ ServiceWorkerUsageInfo& usage_info = origins[origin];
+ if (usage_info.origin.is_empty())
+ usage_info.origin = origin;
+ usage_info.scopes.push_back(registration_info.pattern);
+ usage_info.total_size_bytes += registration_info.stored_version_size_bytes;
+ }
+
+ for (const auto& origin_info_pair : origins) {
+ usage_infos.push_back(origin_info_pair.second);
+ }
+ callback.Run(usage_infos);
+}
+
+namespace {
+void StatusCodeToBoolCallbackAdapter(
+ const ServiceWorkerContext::ResultCallback& callback,
+ ServiceWorkerStatusCode code) {
+ callback.Run(code == ServiceWorkerStatusCode::SERVICE_WORKER_OK);
+}
+
+void EmptySuccessCallback(bool success) {
+}
+} // namespace
+
+void ServiceWorkerContextWrapper::DeleteForOrigin(
+ const GURL& origin_url,
+ const ResultCallback& result) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!context_core_.get()) {
+ LOG(ERROR) << "ServiceWorkerContextCore is no longer alive.";
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(result, false));
+ return;
+ }
+ context()->UnregisterServiceWorkers(
+ origin_url, base::Bind(&StatusCodeToBoolCallbackAdapter, result));
+}
+
+void ServiceWorkerContextWrapper::DeleteForOrigin(const GURL& origin_url) {
+ DeleteForOrigin(origin_url, base::Bind(&EmptySuccessCallback));
}
void ServiceWorkerContextWrapper::AddObserver(
@@ -132,11 +263,25 @@ void ServiceWorkerContextWrapper::RemoveObserver(
observer_list_->RemoveObserver(observer);
}
+void ServiceWorkerContextWrapper::SetBlobParametersForCache(
+ net::URLRequestContextGetter* request_context,
+ ChromeBlobStorageContext* blob_storage_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (context_core_ && request_context && blob_storage_context) {
+ context_core_->SetBlobParametersForCache(
+ request_context->GetURLRequestContext(),
+ blob_storage_context->context()->AsWeakPtr());
+ }
+}
+
void ServiceWorkerContextWrapper::InitInternal(
const base::FilePath& user_data_directory,
- base::SequencedTaskRunner* database_task_runner,
- base::MessageLoopProxy* disk_cache_thread,
- quota::QuotaManagerProxy* quota_manager_proxy) {
+ const scoped_refptr<base::SequencedTaskRunner>& stores_task_runner,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO,
@@ -144,17 +289,24 @@ void ServiceWorkerContextWrapper::InitInternal(
base::Bind(&ServiceWorkerContextWrapper::InitInternal,
this,
user_data_directory,
- make_scoped_refptr(database_task_runner),
- make_scoped_refptr(disk_cache_thread),
- make_scoped_refptr(quota_manager_proxy)));
+ stores_task_runner,
+ base::Passed(&database_task_manager),
+ disk_cache_thread,
+ make_scoped_refptr(quota_manager_proxy),
+ make_scoped_refptr(special_storage_policy)));
return;
}
DCHECK(!context_core_);
+ if (quota_manager_proxy) {
+ quota_manager_proxy->RegisterClient(new ServiceWorkerQuotaClient(this));
+ }
context_core_.reset(new ServiceWorkerContextCore(user_data_directory,
- database_task_runner,
+ stores_task_runner,
+ database_task_manager.Pass(),
disk_cache_thread,
quota_manager_proxy,
- observer_list_,
+ special_storage_policy,
+ observer_list_.get(),
this));
}
@@ -163,4 +315,15 @@ void ServiceWorkerContextWrapper::ShutdownOnIO() {
context_core_.reset();
}
+void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
+ ServiceWorkerStatusCode status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (status != SERVICE_WORKER_OK) {
+ context_core_.reset();
+ return;
+ }
+ context_core_.reset(new ServiceWorkerContextCore(context_core_.get(), this));
+ DVLOG(1) << "Restarted ServiceWorkerContextCore successfully.";
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.h b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
index 029af6f54ca..7df3cb093b1 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -16,17 +16,23 @@
namespace base {
class FilePath;
-class MessageLoopProxy;
class SequencedTaskRunner;
+class SingleThreadTaskRunner;
}
-namespace quota {
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace storage {
class QuotaManagerProxy;
+class SpecialStoragePolicy;
}
namespace content {
class BrowserContext;
+class ChromeBlobStorageContext;
class ServiceWorkerContextCore;
class ServiceWorkerContextObserver;
@@ -43,9 +49,15 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// Init and Shutdown are for use on the UI thread when the profile,
// storagepartition is being setup and torn down.
void Init(const base::FilePath& user_data_directory,
- quota::QuotaManagerProxy* quota_manager_proxy);
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy);
void Shutdown();
+ // Deletes all files on disk and restarts the system asynchronously. This
+ // leaves the system in a disabled state until it's done. This should be
+ // called on the IO thread.
+ void DeleteAndStartOver();
+
// The core context is only for use on the IO thread.
ServiceWorkerContextCore* context();
@@ -55,35 +67,65 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
}
// ServiceWorkerContext implementation:
- virtual void RegisterServiceWorker(
- const GURL& pattern,
- const GURL& script_url,
- const ResultCallback& continuation) OVERRIDE;
- virtual void UnregisterServiceWorker(const GURL& pattern,
- const ResultCallback& continuation)
- OVERRIDE;
- virtual void Terminate() OVERRIDE;
+ void RegisterServiceWorker(const GURL& pattern,
+ const GURL& script_url,
+ const ResultCallback& continuation) override;
+ void UnregisterServiceWorker(const GURL& pattern,
+ const ResultCallback& continuation) override;
+ void GetAllOriginsInfo(const GetUsageInfoCallback& callback) override;
+ void DeleteForOrigin(const GURL& origin_url) override;
+
+ // DeleteForOrigin with completion callback. Does not exit early, and returns
+ // false if one or more of the deletions fail.
+ virtual void DeleteForOrigin(const GURL& origin_url,
+ const ResultCallback& done);
void AddObserver(ServiceWorkerContextObserver* observer);
void RemoveObserver(ServiceWorkerContextObserver* observer);
+ bool is_incognito() const { return is_incognito_; }
+
+ // The URLRequestContext doesn't exist until after the StoragePartition is
+ // made (which is after this object is made). This function must be called
+ // after this object is created but before any ServiceWorkerCache operations.
+ // It must be called on the IO thread. If either parameter is NULL the
+ // function immediately returns without forwarding to the
+ // ServiceWorkerCacheStorageManager.
+ void SetBlobParametersForCache(
+ net::URLRequestContextGetter* request_context,
+ ChromeBlobStorageContext* blob_storage_context);
+
private:
friend class base::RefCountedThreadSafe<ServiceWorkerContextWrapper>;
friend class EmbeddedWorkerTestHelper;
friend class ServiceWorkerProcessManager;
- virtual ~ServiceWorkerContextWrapper();
+ friend class MockServiceWorkerContextWrapper;
- void InitInternal(const base::FilePath& user_data_directory,
- base::SequencedTaskRunner* database_task_runner,
- base::MessageLoopProxy* disk_cache_thread,
- quota::QuotaManagerProxy* quota_manager_proxy);
+ ~ServiceWorkerContextWrapper() override;
+
+ void InitInternal(
+ const base::FilePath& user_data_directory,
+ const scoped_refptr<base::SequencedTaskRunner>& stores_task_runner,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy);
void ShutdownOnIO();
+ void DidDeleteAndStartOver(ServiceWorkerStatusCode status);
+
+ void DidGetAllRegistrationsForGetAllOrigins(
+ const GetUsageInfoCallback& callback,
+ const std::vector<ServiceWorkerRegistrationInfo>& registrations);
+
const scoped_refptr<ObserverListThreadSafe<ServiceWorkerContextObserver> >
observer_list_;
const scoped_ptr<ServiceWorkerProcessManager> process_manager_;
// Cleared in Shutdown():
scoped_ptr<ServiceWorkerContextCore> context_core_;
+
+ // Initialized in Init(); true if the user data directory is empty.
+ bool is_incognito_;
};
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 14a707b62e8..da4bd123f23 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -4,12 +4,18 @@
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
+#include "base/debug/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+#include "net/base/load_flags.h"
#include "net/base/net_util.h"
#include "net/url_request/url_request.h"
@@ -18,22 +24,46 @@ namespace content {
ServiceWorkerControlleeRequestHandler::ServiceWorkerControlleeRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
- ResourceType::Type resource_type)
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ ResourceType resource_type,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ scoped_refptr<ResourceRequestBody> body)
: ServiceWorkerRequestHandler(context,
provider_host,
blob_storage_context,
resource_type),
+ is_main_resource_load_(
+ ServiceWorkerUtils::IsMainResourceType(resource_type)),
+ request_mode_(request_mode),
+ credentials_mode_(credentials_mode),
+ request_context_type_(request_context_type),
+ frame_type_(frame_type),
+ body_(body),
weak_factory_(this) {
}
ServiceWorkerControlleeRequestHandler::
~ServiceWorkerControlleeRequestHandler() {
+ // Navigation triggers an update to occur shortly after the page and
+ // its initial subresources load.
+ if (provider_host_ && provider_host_->active_version()) {
+ if (is_main_resource_load_)
+ provider_host_->active_version()->ScheduleUpdate();
+ else
+ provider_host_->active_version()->DeferScheduledUpdate();
+ }
+
+ if (is_main_resource_load_ && provider_host_)
+ provider_host_->SetAllowAssociation(true);
}
net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) {
+ net::NetworkDelegate* network_delegate,
+ ResourceContext* resource_context) {
if (!context_ || !provider_host_) {
// We can't do anything other than to fall back to network.
job_ = NULL;
@@ -57,10 +87,19 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
// It's for original request (A) or redirect case (B-a or B-b).
DCHECK(!job_.get() || job_->ShouldForwardToServiceWorker());
- job_ = new ServiceWorkerURLRequestJob(
- request, network_delegate, provider_host_, blob_storage_context_);
- if (ServiceWorkerUtils::IsMainResourceType(resource_type_))
- PrepareForMainResource(request->url());
+ job_ = new ServiceWorkerURLRequestJob(request,
+ network_delegate,
+ provider_host_,
+ blob_storage_context_,
+ request_mode_,
+ credentials_mode_,
+ request_context_type_,
+ frame_type_,
+ body_);
+ resource_context_ = resource_context;
+
+ if (is_main_resource_load_)
+ PrepareForMainResource(request);
else
PrepareForSubResource();
@@ -75,17 +114,50 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
return job_.get();
}
+void ServiceWorkerControlleeRequestHandler::GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const {
+ if (!job_.get()) {
+ *was_fetched_via_service_worker = false;
+ *was_fallback_required_by_service_worker = false;
+ *original_url_via_service_worker = GURL();
+ return;
+ }
+ job_->GetExtraResponseInfo(was_fetched_via_service_worker,
+ was_fallback_required_by_service_worker,
+ original_url_via_service_worker,
+ response_type_via_service_worker,
+ fetch_start_time,
+ fetch_ready_time,
+ fetch_end_time);
+}
+
void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
- const GURL& url) {
+ const net::URLRequest* request) {
DCHECK(job_.get());
DCHECK(context_);
- // The corresponding provider_host may already have associate version in
- // redirect case, unassociate it now.
- provider_host_->SetActiveVersion(NULL);
- provider_host_->SetWaitingVersion(NULL);
+ DCHECK(provider_host_);
+ TRACE_EVENT_ASYNC_BEGIN1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ job_.get(),
+ "URL", request->url().spec());
+ // The corresponding provider_host may already have associated a registration
+ // in redirect case, unassociate it now.
+ provider_host_->DisassociateRegistration();
+
+ // Also prevent a registrater job for establishing an association to a new
+ // registration while we're finding an existing registration.
+ provider_host_->SetAllowAssociation(false);
- GURL stripped_url = net::SimplifyUrlForRequest(url);
+ GURL stripped_url = net::SimplifyUrlForRequest(request->url());
provider_host_->SetDocumentUrl(stripped_url);
+ provider_host_->SetTopmostFrameUrl(request->first_party_for_cookies());
context_->storage()->FindRegistrationForDocument(
stripped_url,
base::Bind(&self::DidLookupRegistrationForMainResource,
@@ -97,17 +169,102 @@ ServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration) {
DCHECK(job_.get());
- if (status != SERVICE_WORKER_OK || !registration->active_version()) {
- // No registration, or no active version for the registration is available.
+ if (provider_host_)
+ provider_host_->SetAllowAssociation(true);
+ if (status != SERVICE_WORKER_OK || !provider_host_) {
job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ job_.get(),
+ "Status", status);
return;
}
- // TODO(michaeln): should SetWaitingVersion() even if no active version so
- // so the versions in the pipeline (.installing, .waiting) show up in the
- // attribute values.
- DCHECK(registration);
- provider_host_->SetActiveVersion(registration->active_version());
- provider_host_->SetWaitingVersion(registration->waiting_version());
+ DCHECK(registration.get());
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ registration->pattern(),
+ provider_host_->topmost_frame_url(),
+ resource_context_)) {
+ job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ job_.get(),
+ "Status", status,
+ "Info", "ServiceWorker is blocked");
+ return;
+ }
+
+ // Initiate activation of a waiting version.
+ // Usually a register job initiates activation but that
+ // doesn't happen if the browser exits prior to activation
+ // having occurred. This check handles that case.
+ if (registration->waiting_version())
+ registration->ActivateWaitingVersionWhenReady();
+
+ scoped_refptr<ServiceWorkerVersion> active_version =
+ registration->active_version();
+
+ // Wait until it's activated before firing fetch events.
+ if (active_version.get() &&
+ active_version->status() == ServiceWorkerVersion::ACTIVATING) {
+ provider_host_->SetAllowAssociation(false);
+ registration->active_version()->RegisterStatusChangeCallback(
+ base::Bind(&self::OnVersionStatusChanged,
+ weak_factory_.GetWeakPtr(),
+ registration,
+ active_version));
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ job_.get(),
+ "Status", status,
+ "Info", "Wait until finished SW activation");
+ return;
+ }
+
+ if (!active_version.get() ||
+ active_version->status() != ServiceWorkerVersion::ACTIVATED) {
+ job_->FallbackToNetwork();
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ job_.get(),
+ "Status", status,
+ "Info",
+ "ServiceWorkerVersion is not available, so falling back to network");
+ return;
+ }
+
+ ServiceWorkerMetrics::CountControlledPageLoad();
+
+ provider_host_->AssociateRegistration(registration.get());
+ job_->ForwardToServiceWorker();
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker",
+ "ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
+ job_.get(),
+ "Status", status,
+ "Info",
+ "Forwarded to the ServiceWorker");
+}
+
+void ServiceWorkerControlleeRequestHandler::OnVersionStatusChanged(
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version) {
+ if (provider_host_)
+ provider_host_->SetAllowAssociation(true);
+ if (version != registration->active_version() ||
+ version->status() != ServiceWorkerVersion::ACTIVATED ||
+ !provider_host_) {
+ job_->FallbackToNetwork();
+ return;
+ }
+
+ ServiceWorkerMetrics::CountControlledPageLoad();
+
+ provider_host_->AssociateRegistration(registration);
job_->ForwardToServiceWorker();
}
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
index 87227cb32dd..9c2beccba39 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -5,7 +5,13 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTROLLEE_REQUEST_HANDLER_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTROLLEE_REQUEST_HANDLER_H_
+#include "base/gtest_prod_util.h"
#include "content/browser/service_worker/service_worker_request_handler.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
namespace net {
class NetworkDelegate;
@@ -14,8 +20,10 @@ class URLRequest;
namespace content {
+class ResourceRequestBody;
class ServiceWorkerRegistration;
class ServiceWorkerURLRequestJob;
+class ServiceWorkerVersion;
// A request handler derivative used to handle requests from
// controlled documents.
@@ -25,28 +33,55 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
ServiceWorkerControlleeRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
- ResourceType::Type resource_type);
- virtual ~ServiceWorkerControlleeRequestHandler();
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ ResourceType resource_type,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ scoped_refptr<ResourceRequestBody> body);
+ ~ServiceWorkerControlleeRequestHandler() override;
// Called via custom URLRequestJobFactory.
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) OVERRIDE;
+ net::NetworkDelegate* network_delegate,
+ ResourceContext* resource_context) override;
+
+ void GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const override;
private:
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
+ ActivateWaitingVersion);
typedef ServiceWorkerControlleeRequestHandler self;
// For main resource case.
- void PrepareForMainResource(const GURL& url);
+ void PrepareForMainResource(const net::URLRequest* request);
void DidLookupRegistrationForMainResource(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
+ void OnVersionStatusChanged(
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version);
// For sub resource case.
void PrepareForSubResource();
+ bool is_main_resource_load_;
scoped_refptr<ServiceWorkerURLRequestJob> job_;
+ FetchRequestMode request_mode_;
+ FetchCredentialsMode credentials_mode_;
+ RequestContextType request_context_type_;
+ RequestContextFrameType frame_type_;
+ scoped_refptr<ResourceRequestBody> body_;
+ ResourceContext* resource_context_;
base::WeakPtrFactory<ServiceWorkerControlleeRequestHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerControlleeRequestHandler);
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
new file mode 100644
index 00000000000..9a6835addb7
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -0,0 +1,244 @@
+// Copyright 2014 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/files/scoped_temp_dir.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "content/browser/browser_thread_impl.h"
+#include "content/browser/fileapi/mock_url_request_delegate.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_url_request_job.h"
+#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/common/resource_request_body.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_content_browser_client.h"
+#include "net/url_request/url_request_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+int kMockRenderProcessId = 1224;
+int kMockProviderId = 1;
+
+void EmptyCallback() {}
+
+}
+
+class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
+ public:
+ ServiceWorkerControlleeRequestHandlerTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(kMockRenderProcessId));
+
+ // A new unstored registration/version.
+ scope_ = GURL("http://host/scope/");
+ script_url_ = GURL("http://host/script.js");
+ registration_ = new ServiceWorkerRegistration(
+ scope_, 1L, context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), script_url_, 1L, context()->AsWeakPtr());
+
+ // An empty host.
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kMockRenderProcessId, kMockProviderId,
+ context()->AsWeakPtr(), NULL));
+ provider_host_ = host->AsWeakPtr();
+ context()->AddProviderHost(host.Pass());
+
+ context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void TearDown() override {
+ version_ = NULL;
+ registration_ = NULL;
+ helper_.reset();
+ }
+
+ ServiceWorkerContextCore* context() const { return helper_->context(); }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ net::URLRequestContext url_request_context_;
+ MockURLRequestDelegate url_request_delegate_;
+ MockResourceContext mock_resource_context_;
+ GURL scope_;
+ GURL script_url_;
+};
+
+class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
+ public:
+ ServiceWorkerTestContentBrowserClient() {}
+ bool AllowServiceWorker(const GURL& scope,
+ const GURL& first_party,
+ content::ResourceContext* context) override {
+ return false;
+ }
+};
+
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, DisallowServiceWorker) {
+ ServiceWorkerTestContentBrowserClient test_browser_client;
+ ContentBrowserClient* old_browser_client =
+ SetBrowserClientForTesting(&test_browser_client);
+
+ // Store an activated worker.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_.get());
+ context()->storage()->StoreRegistration(
+ registration_.get(),
+ version_.get(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+
+ // Conduct a main resource load.
+ const GURL kDocUrl("http://host/scope/doc");
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kDocUrl, net::DEFAULT_PRIORITY, &url_request_delegate_, NULL);
+ scoped_ptr<ServiceWorkerControlleeRequestHandler> handler(
+ new ServiceWorkerControlleeRequestHandler(
+ context()->AsWeakPtr(),
+ provider_host_,
+ base::WeakPtr<storage::BlobStorageContext>(),
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_CREDENTIALS_MODE_OMIT,
+ RESOURCE_TYPE_MAIN_FRAME,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ scoped_refptr<ResourceRequestBody>()));
+ scoped_refptr<net::URLRequestJob> job =
+ handler->MaybeCreateJob(request.get(), NULL, &mock_resource_context_);
+ ServiceWorkerURLRequestJob* sw_job =
+ static_cast<ServiceWorkerURLRequestJob*>(job.get());
+
+ EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+ EXPECT_FALSE(version_->HasControllee());
+ base::RunLoop().RunUntilIdle();
+
+ // Verify we did not use the worker.
+ EXPECT_TRUE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+ EXPECT_FALSE(version_->HasControllee());
+
+ SetBrowserClientForTesting(old_browser_client);
+}
+
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
+ // Store a registration that is installed but not activated yet.
+ version_->SetStatus(ServiceWorkerVersion::INSTALLED);
+ registration_->SetWaitingVersion(version_.get());
+ context()->storage()->StoreRegistration(
+ registration_.get(),
+ version_.get(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+
+ // Conduct a main resource load.
+ const GURL kDocUrl("http://host/scope/doc");
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kDocUrl,
+ net::DEFAULT_PRIORITY,
+ &url_request_delegate_,
+ NULL);
+ scoped_ptr<ServiceWorkerControlleeRequestHandler> handler(
+ new ServiceWorkerControlleeRequestHandler(
+ context()->AsWeakPtr(),
+ provider_host_,
+ base::WeakPtr<storage::BlobStorageContext>(),
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_CREDENTIALS_MODE_OMIT,
+ RESOURCE_TYPE_MAIN_FRAME,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ scoped_refptr<ResourceRequestBody>()));
+ scoped_refptr<net::URLRequestJob> job =
+ handler->MaybeCreateJob(request.get(), NULL, &mock_resource_context_);
+ ServiceWorkerURLRequestJob* sw_job =
+ static_cast<ServiceWorkerURLRequestJob*>(job.get());
+
+ EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+ EXPECT_FALSE(version_->HasControllee());
+
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
+ version_->status());
+ EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_TRUE(sw_job->ShouldForwardToServiceWorker());
+ EXPECT_TRUE(version_->HasControllee());
+
+ // Navigations should trigger an update too.
+ handler.reset(NULL);
+ EXPECT_TRUE(version_->update_timer_.IsRunning());
+}
+
+// Test to not regress crbug/414118.
+TEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
+ // Store a registration so the call to FindRegistrationForDocument will read
+ // from the database.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_.get());
+ context()->storage()->StoreRegistration(
+ registration_.get(),
+ version_.get(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+ version_ = NULL;
+ registration_ = NULL;
+
+ // Conduct a main resource load.
+ const GURL kDocUrl("http://host/scope/doc");
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kDocUrl,
+ net::DEFAULT_PRIORITY,
+ &url_request_delegate_,
+ NULL);
+ scoped_ptr<ServiceWorkerControlleeRequestHandler> handler(
+ new ServiceWorkerControlleeRequestHandler(
+ context()->AsWeakPtr(),
+ provider_host_,
+ base::WeakPtr<storage::BlobStorageContext>(),
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_CREDENTIALS_MODE_OMIT,
+ RESOURCE_TYPE_MAIN_FRAME,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ scoped_refptr<ResourceRequestBody>()));
+ scoped_refptr<net::URLRequestJob> job =
+ handler->MaybeCreateJob(request.get(), NULL, &mock_resource_context_);
+ ServiceWorkerURLRequestJob* sw_job =
+ static_cast<ServiceWorkerURLRequestJob*>(job.get());
+
+ EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+
+ // Shouldn't crash if the ProviderHost is deleted prior to completion of
+ // the database lookup.
+ context()->RemoveProviderHost(kMockRenderProcessId, kMockProviderId);
+ EXPECT_FALSE(provider_host_.get());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(sw_job->ShouldFallbackToNetwork());
+ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index 1058acc6165..61b8659e77c 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -6,7 +6,7 @@
#include <string>
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
@@ -16,6 +16,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "content/browser/service_worker/service_worker_database.pb.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/service_worker/service_worker_types.h"
#include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
@@ -78,14 +79,6 @@ const char kPurgeableResIdKeyPrefix[] = "PRES:";
const int64 kCurrentSchemaVersion = 1;
-// For histogram.
-const char kOpenResultHistogramLabel[] =
- "ServiceWorker.Database.OpenResult";
-const char kReadResultHistogramLabel[] =
- "ServiceWorker.Database.ReadResult";
-const char kWriteResultHistogramLabel[] =
- "ServiceWorker.Database.WriteResult";
-
bool RemovePrefix(const std::string& str,
const std::string& prefix,
std::string* out) {
@@ -141,6 +134,7 @@ void PutRegistrationDataToBatch(
data.set_is_active(input.is_active);
data.set_has_fetch_handler(input.has_fetch_handler);
data.set_last_update_check_time(input.last_update_check.ToInternalValue());
+ data.set_resources_total_size_bytes(input.resources_total_size_bytes);
std::string value;
bool success = data.SerializeToString(&value);
@@ -154,11 +148,13 @@ void PutResourceRecordToBatch(
int64 version_id,
leveldb::WriteBatch* batch) {
DCHECK(batch);
+ DCHECK_GE(input.size_bytes, 0);
// Convert ResourceRecord to ServiceWorkerResourceRecord.
ServiceWorkerResourceRecord record;
record.set_resource_id(input.resource_id);
record.set_url(input.url.spec());
+ record.set_size_bytes(input.size_bytes);
std::string value;
bool success = record.SerializeToString(&value);
@@ -222,6 +218,9 @@ ServiceWorkerDatabase::Status ParseRegistrationData(
if (!scope_url.is_valid() ||
!script_url.is_valid() ||
scope_url.GetOrigin() != script_url.GetOrigin()) {
+ DLOG(ERROR) << "Scope URL '" << data.scope_url() << "' and/or script url '"
+ << data.script_url()
+ << "' are invalid or have mismatching origins.";
return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
}
@@ -234,6 +233,8 @@ ServiceWorkerDatabase::Status ParseRegistrationData(
out->has_fetch_handler = data.has_fetch_handler();
out->last_update_check =
base::Time::FromInternalValue(data.last_update_check_time());
+ out->resources_total_size_bytes = data.resources_total_size_bytes();
+
return ServiceWorkerDatabase::STATUS_OK;
}
@@ -252,6 +253,7 @@ ServiceWorkerDatabase::Status ParseResourceRecord(
// Convert ServiceWorkerResourceRecord to ResourceRecord.
out->resource_id = record.resource_id();
out->url = url;
+ out->size_bytes = record.size_bytes();
return ServiceWorkerDatabase::STATUS_OK;
}
@@ -269,7 +271,10 @@ ServiceWorkerDatabase::Status LevelDBStatusToStatus(
return ServiceWorkerDatabase::STATUS_ERROR_FAILED;
}
-const char* StatusToString(ServiceWorkerDatabase::Status status) {
+} // namespace
+
+const char* ServiceWorkerDatabase::StatusToString(
+ ServiceWorkerDatabase::Status status) {
switch (status) {
case ServiceWorkerDatabase::STATUS_OK:
return "Database OK";
@@ -289,13 +294,12 @@ const char* StatusToString(ServiceWorkerDatabase::Status status) {
return "Database unknown error";
}
-} // namespace
-
ServiceWorkerDatabase::RegistrationData::RegistrationData()
: registration_id(kInvalidServiceWorkerRegistrationId),
version_id(kInvalidServiceWorkerVersionId),
is_active(false),
- has_fetch_handler(false) {
+ has_fetch_handler(false),
+ resources_total_size_bytes(0) {
}
ServiceWorkerDatabase::RegistrationData::~RegistrationData() {
@@ -488,9 +492,12 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
const RegistrationData& registration,
const std::vector<ResourceRecord>& resources,
+ RegistrationData* old_registration,
std::vector<int64>* newly_purgeable_resources) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK(old_registration);
Status status = LazyOpen(true);
+ old_registration->version_id = kInvalidServiceWorkerVersionId;
if (status != STATUS_OK)
return status;
@@ -499,6 +506,15 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
BumpNextVersionIdIfNeeded(registration.version_id, &batch);
PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch);
+#if DCHECK_IS_ON
+ int64_t total_size_bytes = 0;
+ for (const auto& resource : resources) {
+ total_size_bytes += resource.size_bytes;
+ }
+ DCHECK_EQ(total_size_bytes, registration.resources_total_size_bytes)
+ << "The total size in the registration must match the cumulative "
+ << "sizes of the resources.";
+#endif
PutRegistrationDataToBatch(registration, &batch);
// Used for avoiding multiple writes for the same resource id or url.
@@ -518,19 +534,21 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
// Delete a resource from the uncommitted list.
batch.Delete(CreateResourceIdKey(
kUncommittedResIdKeyPrefix, itr->resource_id));
+ // Delete from the purgeable list in case this version was once deleted.
+ batch.Delete(
+ CreateResourceIdKey(kPurgeableResIdKeyPrefix, itr->resource_id));
}
// Retrieve a previous version to sweep purgeable resources.
- RegistrationData old_registration;
status = ReadRegistrationData(registration.registration_id,
registration.scope.GetOrigin(),
- &old_registration);
+ old_registration);
if (status != STATUS_OK && status != STATUS_ERROR_NOT_FOUND)
return status;
if (status == STATUS_OK) {
- DCHECK_LT(old_registration.version_id, registration.version_id);
+ DCHECK_LT(old_registration->version_id, registration.version_id);
status = DeleteResourceRecords(
- old_registration.version_id, newly_purgeable_resources, &batch);
+ old_registration->version_id, newly_purgeable_resources, &batch);
if (status != STATUS_OK)
return status;
@@ -550,7 +568,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateVersionToActive(
int64 registration_id,
const GURL& origin) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
- ServiceWorkerDatabase::Status status = LazyOpen(false);
+ Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
return STATUS_ERROR_NOT_FOUND;
if (status != STATUS_OK)
@@ -575,7 +593,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
const GURL& origin,
const base::Time& time) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
- ServiceWorkerDatabase::Status status = LazyOpen(false);
+ Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
return STATUS_ERROR_NOT_FOUND;
if (status != STATUS_OK)
@@ -598,8 +616,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
int64 registration_id,
const GURL& origin,
+ RegistrationData* deleted_version,
std::vector<int64>* newly_purgeable_resources) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK(deleted_version);
+ deleted_version->version_id = kInvalidServiceWorkerVersionId;
Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
return STATUS_OK;
@@ -627,11 +648,11 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
batch.Delete(CreateRegistrationKey(registration_id, origin));
// Delete resource records associated with the registration.
- for (std::vector<RegistrationData>::const_iterator itr =
- registrations.begin(); itr != registrations.end(); ++itr) {
- if (itr->registration_id == registration_id) {
+ for (const auto& registration : registrations) {
+ if (registration.registration_id == registration_id) {
+ *deleted_version = registration;
status = DeleteResourceRecords(
- itr->version_id, newly_purgeable_resources, &batch);
+ registration.version_id, newly_purgeable_resources, &batch);
if (status != STATUS_OK)
return status;
break;
@@ -685,8 +706,8 @@ ServiceWorkerDatabase::PurgeUncommittedResourceIds(
return WriteBatch(&batch);
}
-ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin(
- const GURL& origin,
+ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigins(
+ const std::set<GURL>& origins,
std::vector<int64>* newly_purgeable_resources) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
Status status = LazyOpen(false);
@@ -694,27 +715,28 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin(
return STATUS_OK;
if (status != STATUS_OK)
return status;
- if (!origin.is_valid())
- return STATUS_ERROR_FAILED;
-
leveldb::WriteBatch batch;
- // Delete from the unique origin list.
- batch.Delete(CreateUniqueOriginKey(origin));
+ for (const GURL& origin : origins) {
+ if (!origin.is_valid())
+ return STATUS_ERROR_FAILED;
- std::vector<RegistrationData> registrations;
- status = GetRegistrationsForOrigin(origin, &registrations);
- if (status != STATUS_OK)
- return status;
+ // Delete from the unique origin list.
+ batch.Delete(CreateUniqueOriginKey(origin));
- // Delete registrations and resource records.
- for (std::vector<RegistrationData>::const_iterator itr =
- registrations.begin(); itr != registrations.end(); ++itr) {
- batch.Delete(CreateRegistrationKey(itr->registration_id, origin));
- status = DeleteResourceRecords(
- itr->version_id, newly_purgeable_resources, &batch);
+ std::vector<RegistrationData> registrations;
+ status = GetRegistrationsForOrigin(origin, &registrations);
if (status != STATUS_OK)
return status;
+
+ // Delete registrations and resource records.
+ for (const RegistrationData& data : registrations) {
+ batch.Delete(CreateRegistrationKey(data.registration_id, origin));
+ status = DeleteResourceRecords(
+ data.version_id, newly_purgeable_resources, &batch);
+ if (status != STATUS_OK)
+ return status;
+ }
}
return WriteBatch(&batch);
@@ -723,8 +745,19 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DestroyDatabase() {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
Disable(FROM_HERE, STATUS_OK);
+
+ leveldb::Options options;
+ if (path_.empty()) {
+ if (env_) {
+ options.env = env_.get();
+ } else {
+ // In-memory database not initialized.
+ return STATUS_OK;
+ }
+ }
+
return LevelDBStatusToStatus(
- leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb::Options()));
+ leveldb::DestroyDB(path_.AsUTF8Unsafe(), options));
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
@@ -969,11 +1002,15 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteResourceIdsInBatch(
if (status != STATUS_OK)
return status;
+ if (ids.empty())
+ return STATUS_OK;
for (std::set<int64>::const_iterator itr = ids.begin();
itr != ids.end(); ++itr) {
// Value should be empty.
batch->Put(CreateResourceIdKey(id_key_prefix, *itr), "");
}
+ // std::set is sorted, so the last element is the largest.
+ BumpNextResourceIdIfNeeded(*ids.rbegin(), batch);
return STATUS_OK;
}
@@ -1055,6 +1092,15 @@ void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded(
}
}
+void ServiceWorkerDatabase::BumpNextResourceIdIfNeeded(
+ int64 used_id, leveldb::WriteBatch* batch) {
+ DCHECK(batch);
+ if (next_avail_resource_id_ <= used_id) {
+ next_avail_resource_id_ = used_id + 1;
+ batch->Put(kNextResIdKey, base::Int64ToString(next_avail_resource_id_));
+ }
+}
+
void ServiceWorkerDatabase::BumpNextVersionIdIfNeeded(
int64 used_id, leveldb::WriteBatch* batch) {
DCHECK(batch);
@@ -1083,31 +1129,25 @@ void ServiceWorkerDatabase::Disable(
void ServiceWorkerDatabase::HandleOpenResult(
const tracked_objects::Location& from_here,
Status status) {
- if (status != ServiceWorkerDatabase::STATUS_OK)
+ if (status != STATUS_OK)
Disable(from_here, status);
- UMA_HISTOGRAM_ENUMERATION(kOpenResultHistogramLabel,
- status,
- ServiceWorkerDatabase::STATUS_ERROR_MAX);
+ ServiceWorkerMetrics::CountOpenDatabaseResult(status);
}
void ServiceWorkerDatabase::HandleReadResult(
const tracked_objects::Location& from_here,
Status status) {
- if (status != ServiceWorkerDatabase::STATUS_OK)
+ if (status != STATUS_OK)
Disable(from_here, status);
- UMA_HISTOGRAM_ENUMERATION(kReadResultHistogramLabel,
- status,
- ServiceWorkerDatabase::STATUS_ERROR_MAX);
+ ServiceWorkerMetrics::CountReadDatabaseResult(status);
}
void ServiceWorkerDatabase::HandleWriteResult(
const tracked_objects::Location& from_here,
Status status) {
- if (status != ServiceWorkerDatabase::STATUS_OK)
+ if (status != STATUS_OK)
Disable(from_here, status);
- UMA_HISTOGRAM_ENUMERATION(kWriteResultHistogramLabel,
- status,
- ServiceWorkerDatabase::STATUS_ERROR_MAX);
+ ServiceWorkerMetrics::CountWriteDatabaseResult(status);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_database.h b/chromium/content/browser/service_worker/service_worker_database.h
index 6475de04a99..96283c95bd6 100644
--- a/chromium/content/browser/service_worker/service_worker_database.h
+++ b/chromium/content/browser/service_worker/service_worker_database.h
@@ -48,21 +48,25 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
STATUS_ERROR_FAILED,
STATUS_ERROR_MAX,
};
+ static const char* StatusToString(Status status);
struct CONTENT_EXPORT RegistrationData {
// These values are immutable for the life of a registration.
int64 registration_id;
GURL scope;
- GURL script;
// Versions are first stored once they successfully install and become
// the waiting version. Then transition to the active version. The stored
- // version may be in the ACTIVE state or in the INSTALLED state.
+ // version may be in the ACTIVATED state or in the INSTALLED state.
+ GURL script;
int64 version_id;
bool is_active;
bool has_fetch_handler;
base::Time last_update_check;
+ // Not populated until ServiceWorkerStorage::StoreRegistration is called.
+ int64_t resources_total_size_bytes;
+
RegistrationData();
~RegistrationData();
};
@@ -70,9 +74,13 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
struct ResourceRecord {
int64 resource_id;
GURL url;
+ // Signed so we can store -1 to specify an unknown or error state. When
+ // stored to the database, this value should always be >= 0.
+ int64 size_bytes;
- ResourceRecord() {}
- ResourceRecord(int64 id, GURL url) : resource_id(id), url(url) {}
+ ResourceRecord() : resource_id(-1), size_bytes(0) {}
+ ResourceRecord(int64 id, GURL url, int64 size_bytes)
+ : resource_id(id), url(url), size_bytes(size_bytes) {}
};
// Reads next available ids from the database. Returns OK if they are
@@ -114,14 +122,17 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// Writes |registration| and |resources| into the database and does following
// things:
- // - Deletes an old version of the registration if exists.
+ // - If an old version of the registration exists, deletes it and sets
+ // |deleted_version| to the old version registration data object
+ // |newly_purgeable_resources| to its resources. Otherwise, sets
+ // |deleted_version->version_id| to -1.
// - Bumps the next registration id and the next version id if needed.
// - Removes |resources| from the uncommitted list if exist.
// Returns OK they are successfully written. Otherwise, returns an error.
- Status WriteRegistration(
- const RegistrationData& registration,
- const std::vector<ResourceRecord>& resources,
- std::vector<int64>* newly_purgeable_resources);
+ Status WriteRegistration(const RegistrationData& registration,
+ const std::vector<ResourceRecord>& resources,
+ RegistrationData* deleted_version,
+ std::vector<int64>* newly_purgeable_resources);
// Updates a registration for |registration_id| to an active state. Returns OK
// if it's successfully updated. Otherwise, returns an error.
@@ -137,12 +148,15 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
const base::Time& time);
// Deletes a registration for |registration_id| and moves resource records
- // associated with it into the purgeable list. Returns OK if it's successfully
- // deleted or not found in the database. Otherwise, returns an error.
- Status DeleteRegistration(
- int64 registration_id,
- const GURL& origin,
- std::vector<int64>* newly_purgeable_resources);
+ // associated with it into the purgeable list. If deletion occurred, sets
+ // |version_id| to the id of the version that was deleted and
+ // |newly_purgeable_resources| to its resources; otherwise, sets |version_id|
+ // to -1. Returns OK if it's successfully deleted or not found in the
+ // database. Otherwise, returns an error.
+ Status DeleteRegistration(int64 registration_id,
+ const GURL& origin,
+ RegistrationData* deleted_version,
+ std::vector<int64>* newly_purgeable_resources);
// As new resources are put into the diskcache, they go into an uncommitted
// list. When a registration is saved that refers to those ids, they're
@@ -179,13 +193,12 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// Returns OK on success. Otherwise deletes nothing and returns an error.
Status PurgeUncommittedResourceIds(const std::set<int64>& ids);
- // Deletes all data for |origin|, namely, unique origin, registrations and
+ // Deletes all data for |origins|, namely, unique origin, registrations and
// resource records. Resources are moved to the purgeable list. Returns OK if
// they are successfully deleted or not found in the database. Otherwise,
// returns an error.
- Status DeleteAllDataForOrigin(
- const GURL& origin,
- std::vector<int64>* newly_purgeable_resources);
+ Status DeleteAllDataForOrigins(const std::set<GURL>& origins,
+ std::vector<int64>* newly_purgeable_resources);
// Completely deletes the contents of the database.
// Be careful using this function.
@@ -274,6 +287,9 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
void BumpNextRegistrationIdIfNeeded(
int64 used_id,
leveldb::WriteBatch* batch);
+ void BumpNextResourceIdIfNeeded(
+ int64 used_id,
+ leveldb::WriteBatch* batch);
void BumpNextVersionIdIfNeeded(
int64 used_id,
leveldb::WriteBatch* batch);
diff --git a/chromium/content/browser/service_worker/service_worker_database.proto b/chromium/content/browser/service_worker/service_worker_database.proto
index c2223ecdd76..bb4acef1fbf 100644
--- a/chromium/content/browser/service_worker/service_worker_database.proto
+++ b/chromium/content/browser/service_worker/service_worker_database.proto
@@ -23,9 +23,12 @@ message ServiceWorkerRegistrationData {
// Serialized by Time::ToInternalValue().
required int64 last_update_check_time = 7;
+
+ optional uint64 resources_total_size_bytes = 8;
}
message ServiceWorkerResourceRecord {
required int64 resource_id = 1;
required string url = 2;
+ optional uint64 size_bytes = 3;
}
diff --git a/chromium/content/browser/service_worker/service_worker_database_task_manager.cc b/chromium/content/browser/service_worker/service_worker_database_task_manager.cc
new file mode 100644
index 00000000000..be7f4d0e796
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_database_task_manager.cc
@@ -0,0 +1,71 @@
+// Copyright 2014 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/sequenced_task_runner.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/service_worker/service_worker_database_task_manager.h"
+
+namespace content {
+
+ServiceWorkerDatabaseTaskManagerImpl::ServiceWorkerDatabaseTaskManagerImpl(
+ base::SequencedWorkerPool* pool) {
+ base::SequencedWorkerPool::SequenceToken token = pool->GetSequenceToken();
+ task_runner_ = pool->GetSequencedTaskRunner(token);
+ shutdown_blocking_task_runner_ =
+ pool->GetSequencedTaskRunnerWithShutdownBehavior(
+ token, base::SequencedWorkerPool::BLOCK_SHUTDOWN);
+}
+
+ServiceWorkerDatabaseTaskManagerImpl::~ServiceWorkerDatabaseTaskManagerImpl() {
+}
+
+scoped_ptr<ServiceWorkerDatabaseTaskManager>
+ServiceWorkerDatabaseTaskManagerImpl::Clone() {
+ return make_scoped_ptr(new ServiceWorkerDatabaseTaskManagerImpl(
+ task_runner_, shutdown_blocking_task_runner_));
+}
+
+base::SequencedTaskRunner*
+ServiceWorkerDatabaseTaskManagerImpl::GetTaskRunner() {
+ return task_runner_.get();
+}
+
+base::SequencedTaskRunner*
+ServiceWorkerDatabaseTaskManagerImpl::GetShutdownBlockingTaskRunner() {
+ return shutdown_blocking_task_runner_.get();
+}
+
+ServiceWorkerDatabaseTaskManagerImpl::ServiceWorkerDatabaseTaskManagerImpl(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>&
+ shutdown_blocking_task_runner)
+ : task_runner_(task_runner),
+ shutdown_blocking_task_runner_(shutdown_blocking_task_runner) {
+}
+
+MockServiceWorkerDatabaseTaskManager::MockServiceWorkerDatabaseTaskManager(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner)
+ : task_runner_(task_runner) {
+}
+
+MockServiceWorkerDatabaseTaskManager::~MockServiceWorkerDatabaseTaskManager() {
+}
+
+scoped_ptr<ServiceWorkerDatabaseTaskManager>
+MockServiceWorkerDatabaseTaskManager::Clone() {
+ return make_scoped_ptr(
+ new MockServiceWorkerDatabaseTaskManager(task_runner_));
+}
+
+base::SequencedTaskRunner*
+MockServiceWorkerDatabaseTaskManager::GetTaskRunner() {
+ return task_runner_.get();
+}
+
+base::SequencedTaskRunner*
+MockServiceWorkerDatabaseTaskManager::GetShutdownBlockingTaskRunner() {
+ return task_runner_.get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_database_task_manager.h b/chromium/content/browser/service_worker/service_worker_database_task_manager.h
new file mode 100644
index 00000000000..fdf13f97228
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_database_task_manager.h
@@ -0,0 +1,75 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_RUNNER_MANAGER_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_RUNNER_MANAGER_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace content {
+
+// Used to sequence ServiceWorkerDatabase tasks. Vends two task runners: one
+// that blocks shutdown and one that doesn't. The task runners use the same
+// sequence token, so no matter which runner you post to, the tasks run in the
+// order they are posted. This lets you post sequenced tasks with mixed shutdown
+// behaviors.
+class ServiceWorkerDatabaseTaskManager {
+ public:
+ virtual ~ServiceWorkerDatabaseTaskManager(){};
+ virtual scoped_ptr<ServiceWorkerDatabaseTaskManager> Clone() = 0;
+ virtual base::SequencedTaskRunner* GetTaskRunner() = 0;
+ virtual base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() = 0;
+};
+
+class ServiceWorkerDatabaseTaskManagerImpl
+ : public ServiceWorkerDatabaseTaskManager {
+ public:
+ explicit ServiceWorkerDatabaseTaskManagerImpl(
+ base::SequencedWorkerPool* pool);
+ ~ServiceWorkerDatabaseTaskManagerImpl() override;
+
+ protected:
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> Clone() override;
+ base::SequencedTaskRunner* GetTaskRunner() override;
+ base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() override;
+
+ private:
+ ServiceWorkerDatabaseTaskManagerImpl(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ const scoped_refptr<base::SequencedTaskRunner>&
+ shutdown_blocking_task_runner);
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> shutdown_blocking_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabaseTaskManagerImpl);
+};
+
+// Dummy implementation for testing. It vends whatever you give it in the ctor.
+class CONTENT_EXPORT MockServiceWorkerDatabaseTaskManager
+ : public NON_EXPORTED_BASE(ServiceWorkerDatabaseTaskManager) {
+ public:
+ explicit MockServiceWorkerDatabaseTaskManager(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner);
+ ~MockServiceWorkerDatabaseTaskManager() override;
+
+ protected:
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> Clone() override;
+ base::SequencedTaskRunner* GetTaskRunner() override;
+ base::SequencedTaskRunner* GetShutdownBlockingTaskRunner() override;
+
+ private:
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerDatabaseTaskManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DATABASE_TASK_RUNNER_MANAGER_
diff --git a/chromium/content/browser/service_worker/service_worker_database_unittest.cc b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
index baa2542cbc1..0e052f5ff20 100644
--- a/chromium/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
@@ -6,10 +6,11 @@
#include <string>
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/stl_util.h"
#include "content/browser/service_worker/service_worker_database.pb.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -36,12 +37,9 @@ GURL URL(const GURL& origin, const std::string& path) {
return out;
}
-Resource CreateResource(int64 resource_id, const GURL& url) {
+Resource CreateResource(int64 resource_id, const GURL& url, uint64 size_bytes) {
EXPECT_TRUE(url.is_valid());
- Resource resource;
- resource.resource_id = resource_id;
- resource.url = url;
- return resource;
+ return Resource(resource_id, url, size_bytes);
}
ServiceWorkerDatabase* CreateDatabase(const base::FilePath& path) {
@@ -61,6 +59,8 @@ void VerifyRegistrationData(const RegistrationData& expected,
EXPECT_EQ(expected.is_active, actual.is_active);
EXPECT_EQ(expected.has_fetch_handler, actual.has_fetch_handler);
EXPECT_EQ(expected.last_update_check, actual.last_update_check);
+ EXPECT_EQ(expected.resources_total_size_bytes,
+ actual.resources_total_size_bytes);
}
void VerifyResourceRecords(const std::vector<Resource>& expected,
@@ -69,6 +69,7 @@ void VerifyResourceRecords(const std::vector<Resource>& expected,
for (size_t i = 0; i < expected.size(); ++i) {
EXPECT_EQ(expected[i].resource_id, actual[i].resource_id);
EXPECT_EQ(expected[i].url, actual[i].url);
+ EXPECT_EQ(expected[i].size_bytes, actual[i].size_bytes);
}
}
@@ -119,11 +120,12 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion) {
// First writing triggers database initialization and bumps the schema
// version.
std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
ServiceWorkerDatabase::RegistrationData data;
ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data, resources,
- &newly_purgeable_resources));
+ database->WriteRegistration(
+ data, resources, &deleted_version, &newly_purgeable_resources));
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
database->ReadDatabaseVersion(&db_version));
@@ -156,14 +158,16 @@ TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
// Writing a registration bumps the next available ids.
std::vector<Resource> resources;
RegistrationData data1;
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
data1.registration_id = 100;
data1.scope = URL(origin, "/foo");
data1.script = URL(origin, "/script1.js");
data1.version_id = 200;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data1, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data1, resources, &deleted_version, &newly_purgeable_resources));
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->GetNextAvailableIds(
&ids.reg_id, &ids.ver_id, &ids.res_id));
@@ -171,6 +175,31 @@ TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
EXPECT_EQ(201, ids.ver_id);
EXPECT_EQ(0, ids.res_id);
+ // Writing uncommitted resources bumps the next available id.
+ const int64 kUncommittedIds[] = {0, 1, 3, 5, 6, 10};
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteUncommittedResourceIds(std::set<int64>(
+ kUncommittedIds, kUncommittedIds + arraysize(kUncommittedIds))));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id));
+ EXPECT_EQ(101, ids.reg_id);
+ EXPECT_EQ(201, ids.ver_id);
+ EXPECT_EQ(11, ids.res_id);
+
+ // Writing purgeable resources bumps the next available id.
+ const int64 kPurgeableIds[] = {4, 12, 16, 17, 20};
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteUncommittedResourceIds(std::set<int64>(
+ kPurgeableIds, kPurgeableIds + arraysize(kPurgeableIds))));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->GetNextAvailableIds(&ids.reg_id, &ids.ver_id, &ids.res_id));
+ EXPECT_EQ(101, ids.reg_id);
+ EXPECT_EQ(201, ids.ver_id);
+ EXPECT_EQ(21, ids.res_id);
+
// Writing a registration whose ids are lower than the stored ones should not
// bump the next available ids.
RegistrationData data2;
@@ -178,9 +207,16 @@ TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
data2.scope = URL(origin, "/bar");
data2.script = URL(origin, "/script2.js");
data2.version_id = 20;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data2, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data2, resources, &deleted_version, &newly_purgeable_resources));
+
+ // Same with resources.
+ int64 kLowResourceId = 15;
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteUncommittedResourceIds(
+ std::set<int64>(&kLowResourceId, &kLowResourceId + 1)));
// Close and reopen the database to verify the stored values.
database.reset(CreateDatabase(database_dir.path()));
@@ -189,7 +225,7 @@ TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
&ids.reg_id, &ids.ver_id, &ids.res_id));
EXPECT_EQ(101, ids.reg_id);
EXPECT_EQ(201, ids.ver_id);
- EXPECT_EQ(0, ids.res_id);
+ EXPECT_EQ(21, ids.res_id);
}
TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
@@ -201,6 +237,7 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
EXPECT_TRUE(origins.empty());
std::vector<Resource> resources;
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
GURL origin1("http://example.com");
@@ -209,9 +246,10 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
data1.scope = URL(origin1, "/foo");
data1.script = URL(origin1, "/script1.js");
data1.version_id = 456;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data1, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data1, resources, &deleted_version, &newly_purgeable_resources));
GURL origin2("https://www.example.com");
RegistrationData data2;
@@ -219,9 +257,10 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
data2.scope = URL(origin2, "/bar");
data2.script = URL(origin2, "/script2.js");
data2.version_id = 567;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data2, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data2, resources, &deleted_version, &newly_purgeable_resources));
GURL origin3("https://example.org");
RegistrationData data3;
@@ -229,9 +268,10 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
data3.scope = URL(origin3, "/hoge");
data3.script = URL(origin3, "/script3.js");
data3.version_id = 678;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data3, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data3, resources, &deleted_version, &newly_purgeable_resources));
// |origin3| has two registrations.
RegistrationData data4;
@@ -239,9 +279,10 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
data4.scope = URL(origin3, "/fuga");
data4.script = URL(origin3, "/script4.js");
data4.version_id = 789;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data4, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data4, resources, &deleted_version, &newly_purgeable_resources));
origins.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -254,8 +295,11 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
// |origin3| has another registration, so should not remove it from the
// unique origin list.
ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(data4.registration_id, origin3,
+ database->DeleteRegistration(data4.registration_id,
+ origin3,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data4.registration_id, deleted_version.registration_id);
origins.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -267,8 +311,11 @@ TEST(ServiceWorkerDatabaseTest, GetOriginsWithRegistrations) {
// |origin3| should be removed from the unique origin list.
ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(data3.registration_id, origin3,
+ database->DeleteRegistration(data3.registration_id,
+ origin3,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data3.registration_id, deleted_version.registration_id);
origins.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -291,6 +338,7 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
EXPECT_TRUE(registrations.empty());
std::vector<Resource> resources;
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
RegistrationData data1;
@@ -298,27 +346,30 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
data1.scope = URL(origin1, "/foo");
data1.script = URL(origin1, "/script1.js");
data1.version_id = 1000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data1, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data1, resources, &deleted_version, &newly_purgeable_resources));
RegistrationData data2;
data2.registration_id = 200;
data2.scope = URL(origin2, "/bar");
data2.script = URL(origin2, "/script2.js");
data2.version_id = 2000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data2, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data2, resources, &deleted_version, &newly_purgeable_resources));
RegistrationData data3;
data3.registration_id = 300;
data3.scope = URL(origin3, "/hoge");
data3.script = URL(origin3, "/script3.js");
data3.version_id = 3000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data3, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data3, resources, &deleted_version, &newly_purgeable_resources));
// |origin3| has two registrations.
RegistrationData data4;
@@ -326,9 +377,10 @@ TEST(ServiceWorkerDatabaseTest, GetRegistrationsForOrigin) {
data4.scope = URL(origin3, "/fuga");
data4.script = URL(origin3, "/script4.js");
data4.version_id = 4000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data4, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data4, resources, &deleted_version, &newly_purgeable_resources));
registrations.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -347,6 +399,7 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
EXPECT_TRUE(registrations.empty());
std::vector<Resource> resources;
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
GURL origin1("http://www1.example.com");
@@ -355,9 +408,10 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
data1.scope = URL(origin1, "/foo");
data1.script = URL(origin1, "/script1.js");
data1.version_id = 1000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data1, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data1, resources, &deleted_version, &newly_purgeable_resources));
GURL origin2("http://www2.example.com");
RegistrationData data2;
@@ -365,9 +419,10 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
data2.scope = URL(origin2, "/bar");
data2.script = URL(origin2, "/script2.js");
data2.version_id = 2000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data2, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data2, resources, &deleted_version, &newly_purgeable_resources));
GURL origin3("http://www3.example.com");
RegistrationData data3;
@@ -375,9 +430,10 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
data3.scope = URL(origin3, "/hoge");
data3.script = URL(origin3, "/script3.js");
data3.version_id = 3000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data3, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data3, resources, &deleted_version, &newly_purgeable_resources));
// |origin3| has two registrations.
RegistrationData data4;
@@ -385,9 +441,10 @@ TEST(ServiceWorkerDatabaseTest, GetAllRegistrations) {
data4.scope = URL(origin3, "/fuga");
data4.script = URL(origin3, "/script4.js");
data4.version_id = 4000;
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data4, resources,
- &newly_purgeable_resources));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data4, resources, &deleted_version, &newly_purgeable_resources));
registrations.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -408,10 +465,11 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
data.scope = URL(origin, "/foo");
data.script = URL(origin, "/script.js");
data.version_id = 200;
+ data.resources_total_size_bytes = 10939 + 200;
std::vector<Resource> resources;
- resources.push_back(CreateResource(1, URL(origin, "/resource1")));
- resources.push_back(CreateResource(2, URL(origin, "/resource2")));
+ resources.push_back(CreateResource(1, URL(origin, "/resource1"), 10939));
+ resources.push_back(CreateResource(2, URL(origin, "/resource2"), 200));
// Write a resource to the uncommitted list to make sure that writing
// registration removes resource ids associated with the registration from
@@ -425,10 +483,15 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
database->GetUncommittedResourceIds(&uncommitted_ids_out));
EXPECT_EQ(uncommitted_ids, uncommitted_ids_out);
+ ServiceWorkerDatabase::RegistrationData deleted_version;
+ deleted_version.version_id = 222; // Dummy initial value
std::vector<int64> newly_purgeable_resources;
+
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data, resources,
- &newly_purgeable_resources));
+ database->WriteRegistration(
+ data, resources, &deleted_version, &newly_purgeable_resources));
+ EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version.version_id);
+ EXPECT_TRUE(newly_purgeable_resources.empty());
// Make sure that the registration and resource records are stored.
RegistrationData data_out;
@@ -446,8 +509,11 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
EXPECT_TRUE(uncommitted_ids_out.empty());
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(data.registration_id, origin,
+ database->DeleteRegistration(data.registration_id,
+ origin,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data.version_id, deleted_version.version_id);
ASSERT_EQ(resources.size(), newly_purgeable_resources.size());
for (size_t i = 0; i < resources.size(); ++i)
EXPECT_EQ(newly_purgeable_resources[i], resources[i].resource_id);
@@ -468,6 +534,56 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
EXPECT_TRUE(ContainsKey(purgeable_ids_out, resources[1].resource_id));
}
+TEST(ServiceWorkerDatabaseTest, DeleteNonExistentRegistration) {
+ scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
+
+ GURL origin("http://example.com");
+ RegistrationData data;
+ data.registration_id = 100;
+ data.scope = URL(origin, "/foo");
+ data.script = URL(origin, "/script.js");
+ data.version_id = 200;
+ data.resources_total_size_bytes = 19 + 29129;
+
+ std::vector<Resource> resources;
+ resources.push_back(CreateResource(1, URL(origin, "/resource1"), 19));
+ resources.push_back(CreateResource(2, URL(origin, "/resource2"), 29129));
+
+ const int64 kNonExistentRegistrationId = 999;
+ const int64 kArbitraryVersionId = 222; // Used as a dummy initial value
+
+ ServiceWorkerDatabase::RegistrationData deleted_version;
+ deleted_version.version_id = kArbitraryVersionId;
+ std::vector<int64> newly_purgeable_resources;
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data, resources, &deleted_version, &newly_purgeable_resources));
+ EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version.version_id);
+ EXPECT_TRUE(newly_purgeable_resources.empty());
+
+ // Delete from an origin that has a registration.
+ deleted_version.version_id = kArbitraryVersionId;
+ newly_purgeable_resources.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->DeleteRegistration(kNonExistentRegistrationId,
+ origin,
+ &deleted_version,
+ &newly_purgeable_resources));
+ EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version.version_id);
+ EXPECT_TRUE(newly_purgeable_resources.empty());
+
+ // Delete from an origin that has no registration.
+ deleted_version.version_id = kArbitraryVersionId;
+ newly_purgeable_resources.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->DeleteRegistration(kNonExistentRegistrationId,
+ GURL("http://example.net"),
+ &deleted_version,
+ &newly_purgeable_resources));
+ EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version.version_id);
+ EXPECT_TRUE(newly_purgeable_resources.empty());
+}
+
TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
@@ -477,15 +593,21 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
data.scope = URL(origin, "/foo");
data.script = URL(origin, "/script.js");
data.version_id = 200;
+ data.resources_total_size_bytes = 10 + 11;
std::vector<Resource> resources1;
- resources1.push_back(CreateResource(1, URL(origin, "/resource1")));
- resources1.push_back(CreateResource(2, URL(origin, "/resource2")));
+ resources1.push_back(CreateResource(1, URL(origin, "/resource1"), 10));
+ resources1.push_back(CreateResource(2, URL(origin, "/resource2"), 11));
+
+ ServiceWorkerDatabase::RegistrationData deleted_version;
+ deleted_version.version_id = 222; // Dummy inital value
std::vector<int64> newly_purgeable_resources;
- EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data, resources1,
- &newly_purgeable_resources));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data, resources1, &deleted_version, &newly_purgeable_resources));
+ EXPECT_EQ(kInvalidServiceWorkerVersionId, deleted_version.version_id);
EXPECT_TRUE(newly_purgeable_resources.empty());
// Make sure that the registration and resource records are stored.
@@ -499,15 +621,19 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
// Update the registration.
RegistrationData updated_data = data;
updated_data.version_id = data.version_id + 1;
+ updated_data.resources_total_size_bytes = 12 + 13;
std::vector<Resource> resources2;
- resources2.push_back(CreateResource(3, URL(origin, "/resource3")));
- resources2.push_back(CreateResource(4, URL(origin, "/resource4")));
+ resources2.push_back(CreateResource(3, URL(origin, "/resource3"), 12));
+ resources2.push_back(CreateResource(4, URL(origin, "/resource4"), 13));
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(updated_data, resources2,
+ database->WriteRegistration(updated_data,
+ resources2,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data.version_id, deleted_version.version_id);
ASSERT_EQ(resources1.size(), newly_purgeable_resources.size());
- for(size_t i = 0; i < resources1.size(); ++i)
+ for (size_t i = 0; i < resources1.size(); ++i)
EXPECT_EQ(newly_purgeable_resources[i], resources1[i].resource_id);
// Make sure that |updated_data| is stored and resources referred from |data|
@@ -530,6 +656,7 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("http://example.com");
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
// Add registration1.
@@ -538,13 +665,15 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
data1.scope = URL(origin, "/foo");
data1.script = URL(origin, "/script1.js");
data1.version_id = 200;
+ data1.resources_total_size_bytes = 1451 + 15234;
std::vector<Resource> resources1;
- resources1.push_back(CreateResource(1, URL(origin, "/resource1")));
- resources1.push_back(CreateResource(2, URL(origin, "/resource2")));
- EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data1, resources1,
- &newly_purgeable_resources));
+ resources1.push_back(CreateResource(1, URL(origin, "/resource1"), 1451));
+ resources1.push_back(CreateResource(2, URL(origin, "/resource2"), 15234));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data1, resources1, &deleted_version, &newly_purgeable_resources));
// Add registration2.
RegistrationData data2;
@@ -552,13 +681,15 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
data2.scope = URL(origin, "/bar");
data2.script = URL(origin, "/script2.js");
data2.version_id = 201;
+ data2.resources_total_size_bytes = 5 + 6;
std::vector<Resource> resources2;
- resources2.push_back(CreateResource(3, URL(origin, "/resource3")));
- resources2.push_back(CreateResource(4, URL(origin, "/resource4")));
- EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data2, resources2,
- &newly_purgeable_resources));
+ resources2.push_back(CreateResource(3, URL(origin, "/resource3"), 5));
+ resources2.push_back(CreateResource(4, URL(origin, "/resource4"), 6));
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data2, resources2, &deleted_version, &newly_purgeable_resources));
// Make sure that registration1 is stored.
RegistrationData data_out;
@@ -582,8 +713,11 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
// Delete registration1.
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(data1.registration_id, origin,
+ database->DeleteRegistration(data1.registration_id,
+ origin,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data1.registration_id, deleted_version.registration_id);
// Make sure that registration1 is gone.
resources_out.clear();
@@ -611,6 +745,7 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("http://example.com");
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
// Should be false because a registration does not exist.
@@ -625,7 +760,9 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
data.version_id = 200;
data.is_active = false;
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data, std::vector<Resource>(),
+ database->WriteRegistration(data,
+ std::vector<Resource>(),
+ &deleted_version,
&newly_purgeable_resources));
// Make sure that the registration is stored.
@@ -653,8 +790,11 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
// Delete the registration.
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(data.registration_id, origin,
+ database->DeleteRegistration(data.registration_id,
+ origin,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data.registration_id, deleted_version.registration_id);
// Should be false because the registration is gone.
EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
@@ -664,6 +804,7 @@ TEST(ServiceWorkerDatabaseTest, UpdateVersionToActive) {
TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
GURL origin("http://example.com");
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
// Should be false because a registration does not exist.
@@ -678,7 +819,9 @@ TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
data.version_id = 200;
data.last_update_check = base::Time::Now();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data, std::vector<Resource>(),
+ database->WriteRegistration(data,
+ std::vector<Resource>(),
+ &deleted_version,
&newly_purgeable_resources));
// Make sure that the registration is stored.
@@ -708,8 +851,11 @@ TEST(ServiceWorkerDatabaseTest, UpdateLastCheckTime) {
// Delete the registration.
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteRegistration(data.registration_id, origin,
+ database->DeleteRegistration(data.registration_id,
+ origin,
+ &deleted_version,
&newly_purgeable_resources));
+ EXPECT_EQ(data.registration_id, deleted_version.registration_id);
// Should be false because the registration is gone.
EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
@@ -805,6 +951,7 @@ TEST(ServiceWorkerDatabaseTest, PurgeableResourceIds) {
TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
scoped_ptr<ServiceWorkerDatabase> database(CreateDatabaseInMemory());
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
// Data associated with |origin1| will be removed.
@@ -817,26 +964,30 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
data1.scope = URL(origin1, "/foo");
data1.script = URL(origin1, "/script1.js");
data1.version_id = 100;
+ data1.resources_total_size_bytes = 2013 + 512;
std::vector<Resource> resources1;
- resources1.push_back(CreateResource(1, URL(origin1, "/resource1")));
- resources1.push_back(CreateResource(2, URL(origin1, "/resource2")));
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data1, resources1,
- &newly_purgeable_resources));
+ resources1.push_back(CreateResource(1, URL(origin1, "/resource1"), 2013));
+ resources1.push_back(CreateResource(2, URL(origin1, "/resource2"), 512));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data1, resources1, &deleted_version, &newly_purgeable_resources));
RegistrationData data2;
data2.registration_id = 11;
data2.scope = URL(origin1, "/bar");
data2.script = URL(origin1, "/script2.js");
data2.version_id = 101;
+ data2.resources_total_size_bytes = 4 + 5;
std::vector<Resource> resources2;
- resources2.push_back(CreateResource(3, URL(origin1, "/resource3")));
- resources2.push_back(CreateResource(4, URL(origin1, "/resource4")));
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data2, resources2,
- &newly_purgeable_resources));
+ resources2.push_back(CreateResource(3, URL(origin1, "/resource3"), 4));
+ resources2.push_back(CreateResource(4, URL(origin1, "/resource4"), 5));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data2, resources2, &deleted_version, &newly_purgeable_resources));
// |origin2| has one registration.
RegistrationData data3;
@@ -844,17 +995,21 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
data3.scope = URL(origin2, "/hoge");
data3.script = URL(origin2, "/script3.js");
data3.version_id = 102;
+ data3.resources_total_size_bytes = 6 + 7;
std::vector<Resource> resources3;
- resources3.push_back(CreateResource(5, URL(origin2, "/resource5")));
- resources3.push_back(CreateResource(6, URL(origin2, "/resource6")));
- ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->WriteRegistration(data3, resources3,
- &newly_purgeable_resources));
-
+ resources3.push_back(CreateResource(5, URL(origin2, "/resource5"), 6));
+ resources3.push_back(CreateResource(6, URL(origin2, "/resource6"), 7));
+ ASSERT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(
+ data3, resources3, &deleted_version, &newly_purgeable_resources));
+
+ std::set<GURL> origins_to_delete;
+ origins_to_delete.insert(origin1);
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- database->DeleteAllDataForOrigin(origin1,
- &newly_purgeable_resources));
+ database->DeleteAllDataForOrigins(origins_to_delete,
+ &newly_purgeable_resources));
// |origin1| should be removed from the unique origin list.
std::set<GURL> unique_origins;
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.cc b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
index a8ca52acae7..d31f00c62ae 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.cc
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
@@ -8,15 +8,12 @@ namespace content {
ServiceWorkerResponseReader::ServiceWorkerResponseReader(
int64 response_id, ServiceWorkerDiskCache* disk_cache)
- : appcache::AppCacheResponseReader(response_id, 0, disk_cache) {
+ : AppCacheResponseReader(response_id, 0, disk_cache) {
}
ServiceWorkerResponseWriter::ServiceWorkerResponseWriter(
int64 response_id, ServiceWorkerDiskCache* disk_cache)
- : appcache::AppCacheResponseWriter(response_id, 0, disk_cache) {
-}
-
-HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() {
+ : AppCacheResponseWriter(response_id, 0, disk_cache) {
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.h b/chromium/content/browser/service_worker/service_worker_disk_cache.h
index 83850129aad..7fa51eed634 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.h
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.h
@@ -5,8 +5,8 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISK_CACHE_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISK_CACHE_H_
+#include "content/browser/appcache/appcache_disk_cache.h"
#include "content/common/content_export.h"
-#include "webkit/browser/appcache/appcache_disk_cache.h"
namespace content {
@@ -17,11 +17,11 @@ namespace content {
// resused classes to a more common location.
class CONTENT_EXPORT ServiceWorkerDiskCache
- : public appcache::AppCacheDiskCache {
+ : public AppCacheDiskCache {
};
class CONTENT_EXPORT ServiceWorkerResponseReader
- : public appcache::AppCacheResponseReader {
+ : public AppCacheResponseReader {
protected:
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
@@ -31,7 +31,7 @@ class CONTENT_EXPORT ServiceWorkerResponseReader
};
class CONTENT_EXPORT ServiceWorkerResponseWriter
- : public appcache::AppCacheResponseWriter {
+ : public AppCacheResponseWriter {
protected:
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
@@ -40,16 +40,6 @@ class CONTENT_EXPORT ServiceWorkerResponseWriter
ServiceWorkerDiskCache* disk_cache);
};
-struct CONTENT_EXPORT HttpResponseInfoIOBuffer
- : public appcache::HttpResponseInfoIOBuffer {
- public:
- HttpResponseInfoIOBuffer() : appcache::HttpResponseInfoIOBuffer() {}
- explicit HttpResponseInfoIOBuffer(net::HttpResponseInfo* info)
- : appcache::HttpResponseInfoIOBuffer(info) {}
- protected:
- virtual ~HttpResponseInfoIOBuffer();
-};
-
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISK_CACHE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
index 964a393f8eb..8f00707381f 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -4,6 +4,7 @@
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/message_port_message_filter.h"
@@ -13,10 +14,14 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
#include "ipc/ipc_message_macros.h"
+#include "net/base/net_util.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "url/gurl.h"
@@ -26,41 +31,74 @@ namespace content {
namespace {
-const char kDisabledErrorMessage[] =
- "ServiceWorker is disabled";
-const char kDomainMismatchErrorMessage[] =
- "Scope and scripts do not have the same origin";
+const char kShutdownErrorMessage[] =
+ "The Service Worker system has shutdown.";
+const char kDisabledErrorMessage[] = "The browser has disabled Service Worker.";
const uint32 kFilteredMessageClasses[] = {
ServiceWorkerMsgStart,
EmbeddedWorkerMsgStart,
};
+bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
+ return url_a.GetOrigin() == url_b.GetOrigin() &&
+ url_a.GetOrigin() == url_c.GetOrigin();
+}
+
+// TODO(dominicc): When crbug.com/362214 is fixed use that to be
+// consistent with Blink's
+// SecurityOrigin::canAccessFeatureRequiringSecureOrigin.
+bool OriginCanAccessServiceWorkers(const GURL& url) {
+ return url.SchemeIsSecure() || net::IsLocalhost(url.host());
+}
+
+bool CheckPatternIsUnderTheScriptDirectory(const GURL& pattern,
+ const GURL& script_url) {
+ size_t slash_pos = script_url.spec().rfind('/');
+ if (slash_pos == std::string::npos)
+ return false;
+ return pattern.spec().compare(
+ 0, slash_pos + 1, script_url.spec(), 0, slash_pos + 1) == 0;
+}
+
bool CanRegisterServiceWorker(const GURL& document_url,
const GURL& pattern,
const GURL& script_url) {
- // TODO: Respect Chrome's content settings, if we add a setting for
- // controlling whether Service Worker is allowed.
- return document_url.GetOrigin() == pattern.GetOrigin() &&
- document_url.GetOrigin() == script_url.GetOrigin();
+ DCHECK(document_url.is_valid());
+ DCHECK(pattern.is_valid());
+ DCHECK(script_url.is_valid());
+ return AllOriginsMatch(document_url, pattern, script_url) &&
+ OriginCanAccessServiceWorkers(document_url) &&
+ CheckPatternIsUnderTheScriptDirectory(pattern, script_url);
}
bool CanUnregisterServiceWorker(const GURL& document_url,
const GURL& pattern) {
- // TODO: Respect Chrome's content settings, if we add a setting for
- // controlling whether Service Worker is allowed.
- return document_url.GetOrigin() == pattern.GetOrigin();
+ DCHECK(document_url.is_valid());
+ DCHECK(pattern.is_valid());
+ return document_url.GetOrigin() == pattern.GetOrigin() &&
+ OriginCanAccessServiceWorkers(document_url);
+}
+
+bool CanGetRegistration(const GURL& document_url,
+ const GURL& given_document_url) {
+ DCHECK(document_url.is_valid());
+ DCHECK(given_document_url.is_valid());
+ return document_url.GetOrigin() == given_document_url.GetOrigin() &&
+ OriginCanAccessServiceWorkers(document_url);
}
} // namespace
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
int render_process_id,
- MessagePortMessageFilter* message_port_message_filter)
+ MessagePortMessageFilter* message_port_message_filter,
+ ResourceContext* resource_context)
: BrowserMessageFilter(kFilteredMessageClasses,
arraysize(kFilteredMessageClasses)),
render_process_id_(render_process_id),
message_port_message_filter_(message_port_message_filter),
+ resource_context_(resource_context),
channel_ready_(false) {
}
@@ -81,13 +119,15 @@ void ServiceWorkerDispatcherHost::Init(
this, make_scoped_refptr(context_wrapper)));
return;
}
+
context_wrapper_ = context_wrapper;
GetContext()->embedded_worker_registry()->AddChildProcessSender(
render_process_id_, this);
}
void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
- BrowserMessageFilter::OnFilterAdded(sender);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnFilterAdded");
channel_ready_ = true;
std::vector<IPC::Message*> messages;
pending_messages_.release(&messages);
@@ -96,6 +136,18 @@ void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
}
}
+void ServiceWorkerDispatcherHost::OnFilterRemoved() {
+ // Don't wait until the destructor to teardown since a new dispatcher host
+ // for this process might be created before then.
+ if (GetContext()) {
+ GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
+ GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
+ render_process_id_);
+ }
+ context_wrapper_ = nullptr;
+ channel_ready_ = false;
+}
+
void ServiceWorkerDispatcherHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
@@ -108,6 +160,8 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
OnRegisterServiceWorker)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
OnUnregisterServiceWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
+ OnGetRegistration)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
OnProviderCreated)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
@@ -116,14 +170,20 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
OnSetHostedVersionId)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
OnPostMessageToWorker)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
+ OnWorkerReadyForInspection)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
OnWorkerScriptLoaded)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
OnWorkerScriptLoadFailed)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
+ OnWorkerScriptEvaluated)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
OnWorkerStarted)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
OnWorkerStopped)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
+ OnPausedAfterDownload)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
OnReportException)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
@@ -132,6 +192,10 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
OnIncrementServiceWorkerRefCount)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
OnDecrementServiceWorkerRefCount)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
+ OnIncrementRegistrationRefCount)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
+ OnDecrementRegistrationRefCount)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -156,24 +220,55 @@ bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
return true;
}
+ServiceWorkerRegistrationHandle*
+ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
+ int provider_id,
+ ServiceWorkerRegistration* registration) {
+ ServiceWorkerRegistrationHandle* handle =
+ FindRegistrationHandle(provider_id, registration->id());
+ if (handle) {
+ handle->IncrementRefCount();
+ return handle;
+ }
+
+ scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
+ new ServiceWorkerRegistrationHandle(
+ GetContext()->AsWeakPtr(), this, provider_id, registration));
+ handle = new_handle.get();
+ RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
+ return handle;
+}
+
void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
scoped_ptr<ServiceWorkerHandle> handle) {
int handle_id = handle->handle_id();
handles_.AddWithID(handle.release(), handle_id);
}
+void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
+ scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
+ int handle_id = handle->handle_id();
+ registration_handles_.AddWithID(handle.release(), handle_id);
+}
+
void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
int thread_id,
int request_id,
int provider_id,
const GURL& pattern,
const GURL& script_url) {
- if (!GetContext() || !ServiceWorkerUtils::IsFeatureEnabled()) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
+ if (!GetContext()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
- WebServiceWorkerError::ErrorTypeDisabled,
- base::ASCIIToUTF16(kDisabledErrorMessage)));
+ WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ }
+ if (!pattern.is_valid() || !script_url.is_valid()) {
+ BadMessageReceived();
return;
}
@@ -187,28 +282,40 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
- WebServiceWorkerError::ErrorTypeDisabled,
- base::ASCIIToUTF16(kDisabledErrorMessage)));
+ WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
}
if (!CanRegisterServiceWorker(
provider_host->document_url(), pattern, script_url)) {
+ BadMessageReceived();
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ pattern, provider_host->topmost_frame_url(), resource_context_)) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
- WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kDomainMismatchErrorMessage)));
+ WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
+
+ TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
+ "ServiceWorkerDispatcherHost::RegisterServiceWorker",
+ request_id,
+ "Pattern", pattern.spec(),
+ "Script URL", script_url.spec());
GetContext()->RegisterServiceWorker(
pattern,
script_url,
- render_process_id_,
provider_host,
base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
this,
thread_id,
+ provider_id,
request_id));
}
@@ -217,12 +324,18 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
int request_id,
int provider_id,
const GURL& pattern) {
- if (!GetContext() || !ServiceWorkerUtils::IsFeatureEnabled()) {
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
+ if (!GetContext()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
thread_id,
request_id,
- blink::WebServiceWorkerError::ErrorTypeDisabled,
- base::ASCIIToUTF16(kDisabledErrorMessage)));
+ blink::WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ }
+ if (!pattern.is_valid()) {
+ BadMessageReceived();
return;
}
@@ -233,23 +346,34 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
return;
}
if (!provider_host->IsContextAlive()) {
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
thread_id,
request_id,
- blink::WebServiceWorkerError::ErrorTypeDisabled,
- base::ASCIIToUTF16(kDisabledErrorMessage)));
+ blink::WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
return;
}
if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ BadMessageReceived();
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ pattern, provider_host->topmost_frame_url(), resource_context_)) {
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
thread_id,
request_id,
- WebServiceWorkerError::ErrorTypeSecurity,
- base::ASCIIToUTF16(kDomainMismatchErrorMessage)));
+ WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
+ TRACE_EVENT_ASYNC_BEGIN1(
+ "ServiceWorker",
+ "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
+ request_id,
+ "Pattern", pattern.spec());
GetContext()->UnregisterServiceWorker(
pattern,
base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
@@ -258,11 +382,86 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
request_id));
}
+void ServiceWorkerDispatcherHost::OnGetRegistration(
+ int thread_id,
+ int request_id,
+ int provider_id,
+ const GURL& document_url) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnGetRegistration");
+ if (!GetContext()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id,
+ request_id,
+ blink::WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ }
+ if (!document_url.is_valid()) {
+ BadMessageReceived();
+ return;
+ }
+
+ ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
+ render_process_id_, provider_id);
+ if (!provider_host) {
+ BadMessageReceived();
+ return;
+ }
+ if (!provider_host->IsContextAlive()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id,
+ request_id,
+ blink::WebServiceWorkerError::ErrorTypeAbort,
+ base::ASCIIToUTF16(kShutdownErrorMessage)));
+ return;
+ }
+
+ if (!CanGetRegistration(provider_host->document_url(), document_url)) {
+ BadMessageReceived();
+ return;
+ }
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ provider_host->document_url(),
+ provider_host->topmost_frame_url(),
+ resource_context_)) {
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id,
+ request_id,
+ WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
+ return;
+ }
+
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (GetContext()->storage()->IsDisabled()) {
+ SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
+ return;
+ }
+
+ TRACE_EVENT_ASYNC_BEGIN1(
+ "ServiceWorker",
+ "ServiceWorkerDispatcherHost::GetRegistration",
+ request_id,
+ "Document URL", document_url.spec());
+
+ GetContext()->storage()->FindRegistrationForDocument(
+ document_url,
+ base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
+ this,
+ thread_id,
+ provider_id,
+ request_id));
+}
+
void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
int handle_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids) {
- if (!GetContext() || !ServiceWorkerUtils::IsFeatureEnabled())
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
+ if (!GetContext())
return;
ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
@@ -282,6 +481,8 @@ void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
}
void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnProviderCreated");
if (!GetContext())
return;
if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
@@ -295,6 +496,8 @@ void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
}
void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnProviderDestroyed");
if (!GetContext())
return;
if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
@@ -306,6 +509,8 @@ void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
int provider_id, int64 version_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
if (!GetContext())
return;
ServiceWorkerProviderHost* provider_host =
@@ -320,12 +525,46 @@ void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
BadMessageReceived();
}
+ServiceWorkerRegistrationHandle*
+ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
+ int64 registration_id) {
+ for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
+ iter(&registration_handles_);
+ !iter.IsAtEnd();
+ iter.Advance()) {
+ ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
+ DCHECK(handle);
+ if (handle->provider_id() == provider_id && handle->registration() &&
+ handle->registration()->id() == registration_id) {
+ return handle;
+ }
+ }
+ return NULL;
+}
+
+void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
+ int provider_id,
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerRegistrationObjectInfo* info,
+ ServiceWorkerVersionAttributes* attrs) {
+ ServiceWorkerRegistrationHandle* handle =
+ GetOrCreateRegistrationHandle(provider_id, registration);
+ *info = handle->GetObjectInfo();
+
+ attrs->installing = handle->CreateServiceWorkerHandleAndPass(
+ registration->installing_version());
+ attrs->waiting = handle->CreateServiceWorkerHandleAndPass(
+ registration->waiting_version());
+ attrs->active = handle->CreateServiceWorkerHandleAndPass(
+ registration->active_version());
+}
+
void ServiceWorkerDispatcherHost::RegistrationComplete(
int thread_id,
+ int provider_id,
int request_id,
ServiceWorkerStatusCode status,
- int64 registration_id,
- int64 version_id) {
+ int64 registration_id) {
if (!GetContext())
return;
@@ -334,47 +573,105 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
return;
}
- ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
- DCHECK(version);
- DCHECK_EQ(registration_id, version->registration_id());
- scoped_ptr<ServiceWorkerHandle> handle =
- ServiceWorkerHandle::Create(GetContext()->AsWeakPtr(),
- this, thread_id, version);
+ ServiceWorkerRegistration* registration =
+ GetContext()->GetLiveRegistration(registration_id);
+ DCHECK(registration);
+
+ ServiceWorkerRegistrationObjectInfo info;
+ ServiceWorkerVersionAttributes attrs;
+ GetRegistrationObjectInfoAndVersionAttributes(
+ provider_id, registration, &info, &attrs);
+
Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
- thread_id, request_id, handle->GetObjectInfo()));
- RegisterServiceWorkerHandle(handle.Pass());
+ thread_id, request_id, info, attrs));
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "ServiceWorkerDispatcherHost::RegisterServiceWorker",
+ request_id,
+ "Registration ID",
+ registration_id);
}
-// TODO(nhiroki): These message handlers that take |embedded_worker_id| as an
-// input should check if the worker refers to the live context. If the context
-// was deleted, handle the messege gracefully (http://crbug.com/371675).
-void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(int embedded_worker_id) {
+void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
+ int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
if (!GetContext())
return;
- GetContext()->embedded_worker_registry()->OnWorkerScriptLoaded(
- render_process_id_, embedded_worker_id);
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
+ int embedded_worker_id,
+ int thread_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
+ if (!GetContext())
+ return;
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnWorkerScriptLoaded(
+ render_process_id_, thread_id, embedded_worker_id);
}
void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
if (!GetContext())
return;
- GetContext()->embedded_worker_registry()->OnWorkerScriptLoadFailed(
- render_process_id_, embedded_worker_id);
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
}
-void ServiceWorkerDispatcherHost::OnWorkerStarted(
- int thread_id, int embedded_worker_id) {
+void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
+ int embedded_worker_id,
+ bool success) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
if (!GetContext())
return;
- GetContext()->embedded_worker_registry()->OnWorkerStarted(
- render_process_id_, thread_id, embedded_worker_id);
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnWorkerScriptEvaluated(
+ render_process_id_, embedded_worker_id, success);
+}
+
+void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnWorkerStarted");
+ if (!GetContext())
+ return;
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
}
void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnWorkerStopped");
if (!GetContext())
return;
- GetContext()->embedded_worker_registry()->OnWorkerStopped(
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
+ int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
render_process_id_, embedded_worker_id);
}
@@ -384,32 +681,42 @@ void ServiceWorkerDispatcherHost::OnReportException(
int line_number,
int column_number,
const GURL& source_url) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnReportException");
if (!GetContext())
return;
- GetContext()->embedded_worker_registry()->OnReportException(
- embedded_worker_id,
- error_message,
- line_number,
- column_number,
- source_url);
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnReportException(embedded_worker_id,
+ error_message,
+ line_number,
+ column_number,
+ source_url);
}
void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
int embedded_worker_id,
const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
if (!GetContext())
return;
- GetContext()->embedded_worker_registry()->OnReportConsoleMessage(
- embedded_worker_id,
- params.source_identifier,
- params.message_level,
- params.message,
- params.line_number,
- params.source_url);
+ EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
+ if (!registry->CanHandle(embedded_worker_id))
+ return;
+ registry->OnReportConsoleMessage(embedded_worker_id,
+ params.source_identifier,
+ params.message_level,
+ params.message,
+ params.line_number,
+ params.source_url);
}
void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
int handle_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
if (!handle) {
BadMessageReceived();
@@ -420,6 +727,8 @@ void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
int handle_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
if (!handle) {
BadMessageReceived();
@@ -430,16 +739,86 @@ void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
handles_.Remove(handle_id);
}
+void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
+ int registration_handle_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
+ ServiceWorkerRegistrationHandle* handle =
+ registration_handles_.Lookup(registration_handle_id);
+ if (!handle) {
+ BadMessageReceived();
+ return;
+ }
+ handle->IncrementRefCount();
+}
+
+void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
+ int registration_handle_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
+ ServiceWorkerRegistrationHandle* handle =
+ registration_handles_.Lookup(registration_handle_id);
+ if (!handle) {
+ BadMessageReceived();
+ return;
+ }
+ handle->DecrementRefCount();
+ if (handle->HasNoRefCount())
+ registration_handles_.Remove(registration_handle_id);
+}
+
void ServiceWorkerDispatcherHost::UnregistrationComplete(
int thread_id,
int request_id,
ServiceWorkerStatusCode status) {
- if (status != SERVICE_WORKER_OK) {
- SendRegistrationError(thread_id, request_id, status);
+ if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
+ SendUnregistrationError(thread_id, request_id, status);
+ return;
+ }
+ const bool is_success = (status == SERVICE_WORKER_OK);
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
+ request_id,
+ is_success));
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
+ request_id,
+ "Status", status);
+}
+
+void ServiceWorkerDispatcherHost::GetRegistrationComplete(
+ int thread_id,
+ int provider_id,
+ int request_id,
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "ServiceWorkerDispatcherHost::GetRegistration",
+ request_id,
+ "Registration ID",
+ registration.get() ? registration->id()
+ : kInvalidServiceWorkerRegistrationId);
+
+ if (!GetContext())
+ return;
+
+ if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
+ SendGetRegistrationError(thread_id, request_id, status);
return;
}
- Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, request_id));
+ ServiceWorkerRegistrationObjectInfo info;
+ ServiceWorkerVersionAttributes attrs;
+ if (status == SERVICE_WORKER_OK) {
+ DCHECK(registration.get());
+ if (!registration->is_uninstalling()) {
+ GetRegistrationObjectInfoAndVersionAttributes(
+ provider_id, registration.get(), &info, &attrs);
+ }
+ }
+
+ Send(new ServiceWorkerMsg_DidGetRegistration(
+ thread_id, request_id, info, attrs));
}
void ServiceWorkerDispatcherHost::SendRegistrationError(
@@ -454,7 +833,33 @@ void ServiceWorkerDispatcherHost::SendRegistrationError(
thread_id, request_id, error_type, error_message));
}
+void ServiceWorkerDispatcherHost::SendUnregistrationError(
+ int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status) {
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(
+ status, &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
+ thread_id, request_id, error_type, error_message));
+}
+
+void ServiceWorkerDispatcherHost::SendGetRegistrationError(
+ int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status) {
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(
+ status, &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id, request_id, error_type, error_message));
+}
+
ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
+ if (!context_wrapper_.get())
+ return nullptr;
return context_wrapper_->context();
}
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
index b269311497b..61126f9c3a8 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_DISPATCHER_HOST_H_
+#include <vector>
+
#include "base/id_map.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
@@ -17,24 +19,30 @@ struct EmbeddedWorkerHostMsg_ReportConsoleMessage_Params;
namespace content {
class MessagePortMessageFilter;
+class ResourceContext;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class ServiceWorkerHandle;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
+class ServiceWorkerRegistrationHandle;
+struct ServiceWorkerRegistrationObjectInfo;
+struct ServiceWorkerVersionAttributes;
class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
public:
ServiceWorkerDispatcherHost(
int render_process_id,
- MessagePortMessageFilter* message_port_message_filter);
+ MessagePortMessageFilter* message_port_message_filter,
+ ResourceContext* resource_context);
void Init(ServiceWorkerContextWrapper* context_wrapper);
// BrowserMessageFilter implementation
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnDestruct() const OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// IPC::Sender implementation
@@ -42,16 +50,24 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
// class assumes that Send() can only fail after that when the renderer
// process has terminated, at which point the whole instance will eventually
// be destroyed.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
+
+ // Returns the existing registration handle whose reference count is
+ // incremented or newly created one if it doesn't exist.
+ ServiceWorkerRegistrationHandle* GetOrCreateRegistrationHandle(
+ int provider_id,
+ ServiceWorkerRegistration* registration);
void RegisterServiceWorkerHandle(scoped_ptr<ServiceWorkerHandle> handle);
+ void RegisterServiceWorkerRegistrationHandle(
+ scoped_ptr<ServiceWorkerRegistrationHandle> handle);
MessagePortMessageFilter* message_port_message_filter() {
return message_port_message_filter_;
}
protected:
- virtual ~ServiceWorkerDispatcherHost();
+ ~ServiceWorkerDispatcherHost() override;
private:
friend class BrowserThread;
@@ -68,14 +84,20 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
int request_id,
int provider_id,
const GURL& pattern);
+ void OnGetRegistration(int thread_id,
+ int request_id,
+ int provider_id,
+ const GURL& document_url);
void OnProviderCreated(int provider_id);
void OnProviderDestroyed(int provider_id);
void OnSetHostedVersionId(int provider_id, int64 version_id);
- void OnWorkerScriptLoaded(int embedded_worker_id);
+ void OnWorkerReadyForInspection(int embedded_worker_id);
+ void OnWorkerScriptLoaded(int embedded_worker_id, int thread_id);
void OnWorkerScriptLoadFailed(int embedded_worker_id);
- void OnWorkerStarted(int thread_id,
- int embedded_worker_id);
+ void OnWorkerScriptEvaluated(int embedded_worker_id, bool success);
+ void OnWorkerStarted(int embedded_worker_id);
void OnWorkerStopped(int embedded_worker_id);
+ void OnPausedAfterDownload(int embedded_worker_id);
void OnReportException(int embedded_worker_id,
const base::string16& error_message,
int line_number,
@@ -89,33 +111,62 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
const std::vector<int>& sent_message_port_ids);
void OnIncrementServiceWorkerRefCount(int handle_id);
void OnDecrementServiceWorkerRefCount(int handle_id);
+ void OnIncrementRegistrationRefCount(int registration_handle_id);
+ void OnDecrementRegistrationRefCount(int registration_handle_id);
void OnPostMessageToWorker(int handle_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids);
void OnServiceWorkerObjectDestroyed(int handle_id);
+ ServiceWorkerRegistrationHandle* FindRegistrationHandle(
+ int provider_id,
+ int64 registration_id);
+
+ void GetRegistrationObjectInfoAndVersionAttributes(
+ int provider_id,
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerRegistrationObjectInfo* info,
+ ServiceWorkerVersionAttributes* attrs);
+
// Callbacks from ServiceWorkerContextCore
void RegistrationComplete(int thread_id,
+ int provider_id,
int request_id,
ServiceWorkerStatusCode status,
- int64 registration_id,
- int64 version_id);
+ int64 registration_id);
void UnregistrationComplete(int thread_id,
int request_id,
ServiceWorkerStatusCode status);
+ void GetRegistrationComplete(
+ int thread_id,
+ int provider_id,
+ int request_id,
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+
void SendRegistrationError(int thread_id,
int request_id,
ServiceWorkerStatusCode status);
+ void SendUnregistrationError(int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status);
+
+ void SendGetRegistrationError(int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status);
+
ServiceWorkerContextCore* GetContext();
int render_process_id_;
MessagePortMessageFilter* const message_port_message_filter_;
+ ResourceContext* resource_context_;
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
IDMap<ServiceWorkerHandle, IDMapOwnPointer> handles_;
+ IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer> registration_handles_;
bool channel_ready_; // True after BrowserMessageFilter::sender_ != NULL.
ScopedVector<IPC::Message> pending_messages_;
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 079c8de65fb..3f21c458832 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -16,11 +16,24 @@
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/common/content_switches.h"
+#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/test_content_browser_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
+namespace {
+
+static void SaveStatusCallback(bool* called,
+ ServiceWorkerStatusCode* out,
+ ServiceWorkerStatusCode status) {
+ *called = true;
+ *out = status;
+}
+
+}
+
static const int kRenderProcessId = 1;
class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
@@ -28,28 +41,25 @@ class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
TestingServiceWorkerDispatcherHost(
int process_id,
ServiceWorkerContextWrapper* context_wrapper,
+ ResourceContext* resource_context,
EmbeddedWorkerTestHelper* helper)
- : ServiceWorkerDispatcherHost(process_id, NULL),
+ : ServiceWorkerDispatcherHost(process_id, NULL, resource_context),
bad_messages_received_count_(0),
helper_(helper) {
Init(context_wrapper);
}
- virtual bool Send(IPC::Message* message) OVERRIDE {
- return helper_->Send(message);
- }
+ bool Send(IPC::Message* message) override { return helper_->Send(message); }
IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
- virtual void BadMessageReceived() OVERRIDE {
- ++bad_messages_received_count_;
- }
+ void BadMessageReceived() override { ++bad_messages_received_count_; }
int bad_messages_received_count_;
protected:
EmbeddedWorkerTestHelper* helper_;
- virtual ~TestingServiceWorkerDispatcherHost() {}
+ ~TestingServiceWorkerDispatcherHost() override {}
};
class ServiceWorkerDispatcherHostTest : public testing::Test {
@@ -57,149 +67,310 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
ServiceWorkerDispatcherHostTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
- virtual void SetUp() {
+ void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
- kRenderProcessId, context_wrapper(), helper_.get());
+ kRenderProcessId, context_wrapper(), &resource_context_, helper_.get());
}
- virtual void TearDown() {
- helper_.reset();
- }
+ void TearDown() override { helper_.reset(); }
ServiceWorkerContextCore* context() { return helper_->context(); }
ServiceWorkerContextWrapper* context_wrapper() {
return helper_->context_wrapper();
}
- void Register(int64 provider_id,
- GURL pattern,
- GURL worker_url,
- uint32 expected_message) {
+ void SendRegister(int64 provider_id, GURL pattern, GURL worker_url) {
dispatcher_host_->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(
-1, -1, provider_id, pattern, worker_url));
base::RunLoop().RunUntilIdle();
+ }
+
+ void Register(int64 provider_id,
+ GURL pattern,
+ GURL worker_url,
+ uint32 expected_message) {
+ SendRegister(provider_id, pattern, worker_url);
EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
expected_message));
dispatcher_host_->ipc_sink()->ClearMessages();
}
- void Unregister(int64 provider_id, GURL pattern, uint32 expected_message) {
+ void SendUnregister(int64 provider_id, GURL pattern) {
dispatcher_host_->OnMessageReceived(
ServiceWorkerHostMsg_UnregisterServiceWorker(
-1, -1, provider_id, pattern));
base::RunLoop().RunUntilIdle();
+ }
+
+ void Unregister(int64 provider_id, GURL pattern, uint32 expected_message) {
+ SendUnregister(provider_id, pattern);
+ EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
+ expected_message));
+ dispatcher_host_->ipc_sink()->ClearMessages();
+ }
+
+ void SendGetRegistration(int64 provider_id, GURL document_url) {
+ dispatcher_host_->OnMessageReceived(
+ ServiceWorkerHostMsg_GetRegistration(
+ -1, -1, provider_id, document_url));
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void GetRegistration(int64 provider_id,
+ GURL document_url,
+ uint32 expected_message) {
+ SendGetRegistration(provider_id, document_url);
EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
expected_message));
dispatcher_host_->ipc_sink()->ClearMessages();
}
TestBrowserThreadBundle browser_thread_bundle_;
+ content::MockResourceContext resource_context_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
};
-TEST_F(ServiceWorkerDispatcherHostTest, DisabledCausesError) {
- DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableServiceWorker));
-
- dispatcher_host_->OnMessageReceived(
- ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()));
+class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
+ public:
+ ServiceWorkerTestContentBrowserClient() {}
+ bool AllowServiceWorker(const GURL& scope,
+ const GURL& first_party,
+ content::ResourceContext* context) override {
+ return false;
+ }
+};
- // TODO(alecflett): Pump the message loop when this becomes async.
- ASSERT_EQ(1UL, dispatcher_host_->ipc_sink()->message_count());
- EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_ServiceWorkerRegistrationError::ID));
-}
+TEST_F(ServiceWorkerDispatcherHostTest,
+ Register_ContentSettingsDisallowsServiceWorker) {
+ ServiceWorkerTestContentBrowserClient test_browser_client;
+ ContentBrowserClient* old_browser_client =
+ SetBrowserClientForTesting(&test_browser_client);
-// TODO(falken): Enable this test when we remove the
-// --enable-service-worker-flag (see crbug.com/352581)
-TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_RegisterSameOrigin) {
const int64 kProviderId = 99; // Dummy value
scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
- host->SetDocumentUrl(GURL("http://www.example.com/foo"));
- base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
context()->AddProviderHost(host.Pass());
Register(kProviderId,
- GURL("http://www.example.com/*"),
- GURL("http://foo.example.com/bar"),
- ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
- Register(kProviderId,
- GURL("http://foo.example.com/*"),
- GURL("http://www.example.com/bar"),
+ GURL("https://www.example.com/"),
+ GURL("https://www.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
+ Unregister(kProviderId,
+ GURL("https://www.example.com/"),
+ ServiceWorkerMsg_ServiceWorkerUnregistrationError::ID);
+ GetRegistration(kProviderId,
+ GURL("https://www.example.com/"),
+ ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
+
+ SetBrowserClientForTesting(old_browser_client);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Register_HTTPS) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
Register(kProviderId,
- GURL("http://foo.example.com/*"),
- GURL("http://foo.example.com/bar"),
- ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
+ GURL("https://www.example.com/"),
+ GURL("https://www.example.com/bar"),
+ ServiceWorkerMsg_ServiceWorkerRegistered::ID);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureTransportLocalhost) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("http://127.0.0.3:81/foo"));
+ context()->AddProviderHost(host.Pass());
+
Register(kProviderId,
- GURL("http://www.example.com/*"),
- GURL("http://www.example.com/bar"),
+ GURL("http://127.0.0.3:81/bar"),
+ GURL("http://127.0.0.3:81/baz"),
ServiceWorkerMsg_ServiceWorkerRegistered::ID);
}
-// TODO(falken): Enable this test when we remove the
-// --enable-service-worker-flag (see crbug.com/352581)
-TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_UnregisterSameOrigin) {
+TEST_F(ServiceWorkerDispatcherHostTest,
+ Register_DifferentDirectoryThanScriptShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendRegister(kProviderId,
+ GURL("https://www.example.com/hoge/piyo"),
+ GURL("https://www.example.com/bar/hoge.js"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest,
+ Register_SameDirectoryAsScriptButNoSlashShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendRegister(kProviderId,
+ GURL("https://www.example.com/bar"),
+ GURL("https://www.example.com/bar/hoge.js"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScopeShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendRegister(
+ kProviderId, GURL(""), GURL("https://www.example.com/bar/hoge.js"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Register_InvalidScriptShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendRegister(kProviderId, GURL("https://www.example.com/bar/"), GURL(""));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureOriginShouldFail) {
const int64 kProviderId = 99; // Dummy value
scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
host->SetDocumentUrl(GURL("http://www.example.com/foo"));
- base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
+ context()->AddProviderHost(host.Pass());
+
+ SendRegister(kProviderId,
+ GURL("http://www.example.com/"),
+ GURL("http://www.example.com/bar"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Register_CrossOriginShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ // Script has a different host
+ SendRegister(kProviderId,
+ GURL("https://www.example.com/"),
+ GURL("https://foo.example.com/bar"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+
+ // Scope has a different host
+ SendRegister(kProviderId,
+ GURL("https://foo.example.com/"),
+ GURL("https://www.example.com/bar"));
+ EXPECT_EQ(2, dispatcher_host_->bad_messages_received_count_);
+
+ // Script has a different port
+ SendRegister(kProviderId,
+ GURL("https://www.example.com/"),
+ GURL("https://www.example.com:8080/bar"));
+ EXPECT_EQ(3, dispatcher_host_->bad_messages_received_count_);
+
+ // Scope has a different transport
+ SendRegister(kProviderId,
+ GURL("wss://www.example.com/"),
+ GURL("https://www.example.com/bar"));
+ EXPECT_EQ(4, dispatcher_host_->bad_messages_received_count_);
+
+ // Script and scope have a different host but match each other
+ SendRegister(kProviderId,
+ GURL("https://foo.example.com/"),
+ GURL("https://foo.example.com/bar"));
+ EXPECT_EQ(5, dispatcher_host_->bad_messages_received_count_);
+
+ // Script and scope URLs are invalid
+ SendRegister(kProviderId,
+ GURL(),
+ GURL("h@ttps://@"));
+ EXPECT_EQ(6, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Unregister_HTTPS) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
context()->AddProviderHost(host.Pass());
Unregister(kProviderId,
- GURL("http://foo.example.com/*"),
- ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
+ GURL("https://www.example.com/"),
+ ServiceWorkerMsg_ServiceWorkerUnregistered::ID);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest,
+ Unregister_NonSecureTransportLocalhost) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("http://localhost/foo"));
+ context()->AddProviderHost(host.Pass());
+
Unregister(kProviderId,
- GURL("http://www.example.com/*"),
+ GURL("http://localhost/"),
ServiceWorkerMsg_ServiceWorkerUnregistered::ID);
}
-// Disable this since now we cache command-line switch in
-// ServiceWorkerUtils::IsFeatureEnabled() and this could be flaky depending
-// on testing order. (crbug.com/352581)
-// TODO(kinuko): Just remove DisabledCausesError test above and enable
-// this test when we remove the --enable-service-worker flag.
-TEST_F(ServiceWorkerDispatcherHostTest, DISABLED_Enabled) {
- DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableServiceWorker));
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableServiceWorker);
+TEST_F(ServiceWorkerDispatcherHostTest, Unregister_CrossOriginShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
- dispatcher_host_->OnMessageReceived(
- ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()));
- base::RunLoop().RunUntilIdle();
+ SendUnregister(kProviderId, GURL("https://foo.example.com/"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, Unregister_InvalidScopeShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
- // TODO(alecflett): Pump the message loop when this becomes async.
- ASSERT_EQ(2UL, dispatcher_host_->ipc_sink()->message_count());
- EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
- EmbeddedWorkerMsg_StartWorker::ID));
- EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_ServiceWorkerRegistered::ID));
+ SendUnregister(kProviderId, GURL(""));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}
-TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
- DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableServiceWorker));
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableServiceWorker);
+TEST_F(ServiceWorkerDispatcherHostTest, Unregister_NonSecureOriginShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("http://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendUnregister(kProviderId, GURL("http://www.example.com/"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
helper_->ShutdownContext();
// Let the shutdown reach the simulated IO thread.
base::RunLoop().RunUntilIdle();
- dispatcher_host_->OnMessageReceived(
- ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, -1, GURL(), GURL()));
-
- // TODO(alecflett): Pump the message loop when this becomes async.
- ASSERT_EQ(1UL, dispatcher_host_->ipc_sink()->message_count());
- EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
- ServiceWorkerMsg_ServiceWorkerRegistrationError::ID));
+ Register(-1,
+ GURL(),
+ GURL(),
+ ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
}
TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
@@ -233,4 +404,116 @@ TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) {
EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
}
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ GetRegistration(kProviderId,
+ GURL("https://www.example.com/"),
+ ServiceWorkerMsg_DidGetRegistration::ID);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_CrossOriginShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendGetRegistration(kProviderId, GURL("https://foo.example.com/"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest,
+ GetRegistration_InvalidScopeShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("https://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendGetRegistration(kProviderId, GURL(""));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest,
+ GetRegistration_NotSecureOriginShouldFail) {
+ const int64 kProviderId = 99; // Dummy value
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
+ host->SetDocumentUrl(GURL("http://www.example.com/foo"));
+ context()->AddProviderHost(host.Pass());
+
+ SendGetRegistration(kProviderId, GURL("http://www.example.com/"));
+ EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_EarlyContextDeletion) {
+ helper_->ShutdownContext();
+
+ // Let the shutdown reach the simulated IO thread.
+ base::RunLoop().RunUntilIdle();
+
+ GetRegistration(-1,
+ GURL(),
+ ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
+ // Add a provider and worker.
+ const int64 kProviderId = 99; // Dummy value
+ dispatcher_host_->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderCreated(kProviderId));
+
+ GURL pattern = GURL("http://www.example.com/");
+ scoped_refptr<ServiceWorkerRegistration> registration(
+ new ServiceWorkerRegistration(pattern,
+ 1L,
+ helper_->context()->AsWeakPtr()));
+ scoped_refptr<ServiceWorkerVersion> version(
+ new ServiceWorkerVersion(registration.get(),
+ GURL("http://www.example.com/service_worker.js"),
+ 1L,
+ helper_->context()->AsWeakPtr()));
+ helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId);
+
+ // Start up the worker.
+ bool called;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
+ version->StartWorker(base::Bind(&SaveStatusCallback, &called, &status));
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ EXPECT_TRUE(context()->GetProviderHost(kRenderProcessId, kProviderId));
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+
+ // Simulate the render process crashing.
+ dispatcher_host_->OnFilterRemoved();
+
+ // The dispatcher host should clean up the state from the process.
+ EXPECT_FALSE(context()->GetProviderHost(kRenderProcessId, kProviderId));
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+
+ // We should be able to hook up a new dispatcher host although the old object
+ // is not yet destroyed. This is what the browser does when reusing a crashed
+ // render process.
+ scoped_refptr<TestingServiceWorkerDispatcherHost> new_dispatcher_host(
+ new TestingServiceWorkerDispatcherHost(kRenderProcessId,
+ context_wrapper(),
+ &resource_context_,
+ helper_.get()));
+
+ // To show the new dispatcher can operate, simulate provider creation. Since
+ // the old dispatcher cleaned up the old provider host, the new one won't
+ // complain.
+ new_dispatcher_host->OnMessageReceived(
+ ServiceWorkerHostMsg_ProviderCreated(kProviderId));
+ EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 81be9aff2a7..7ed3051e3f1 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -5,30 +5,28 @@
#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
#include "base/bind.h"
+#include "base/debug/trace_event.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "net/url_request/url_request.h"
namespace content {
ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
- net::URLRequest* request,
+ scoped_ptr<ServiceWorkerFetchRequest> request,
ServiceWorkerVersion* version,
- const FetchCallback& callback)
+ const base::Closure& prepare_callback,
+ const FetchCallback& fetch_callback)
: version_(version),
- callback_(callback),
+ prepare_callback_(prepare_callback),
+ fetch_callback_(fetch_callback),
+ request_(request.Pass()),
weak_factory_(this) {
- request_.url = request->url();
- request_.method = request->method();
- const net::HttpRequestHeaders& headers = request->extra_request_headers();
- for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();)
- request_.headers[it.name()] = it.value();
}
ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {}
void ServiceWorkerFetchDispatcher::Run() {
DCHECK(version_->status() == ServiceWorkerVersion::ACTIVATING ||
- version_->status() == ServiceWorkerVersion::ACTIVE)
+ version_->status() == ServiceWorkerVersion::ACTIVATED)
<< version_->status();
if (version_->status() == ServiceWorkerVersion::ACTIVATING) {
@@ -41,7 +39,7 @@ void ServiceWorkerFetchDispatcher::Run() {
}
void ServiceWorkerFetchDispatcher::DidWaitActivation() {
- if (version_->status() != ServiceWorkerVersion::ACTIVE) {
+ if (version_->status() != ServiceWorkerVersion::ACTIVATED) {
DCHECK_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
DidFailActivation();
return;
@@ -60,19 +58,35 @@ void ServiceWorkerFetchDispatcher::DidFailActivation() {
}
void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
+ TRACE_EVENT_ASYNC_BEGIN0(
+ "ServiceWorker",
+ "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
+ request_.get());
version_->DispatchFetchEvent(
- request_,
+ *request_.get(),
+ base::Bind(&ServiceWorkerFetchDispatcher::DidPrepare,
+ weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerFetchDispatcher::DidFinish,
weak_factory_.GetWeakPtr()));
}
+void ServiceWorkerFetchDispatcher::DidPrepare() {
+ DCHECK(!prepare_callback_.is_null());
+ base::Closure prepare_callback = prepare_callback_;
+ prepare_callback.Run();
+}
+
void ServiceWorkerFetchDispatcher::DidFinish(
ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response) {
- DCHECK(!callback_.is_null());
- FetchCallback callback = callback_;
- callback.Run(status, fetch_result, response);
+ TRACE_EVENT_ASYNC_END0(
+ "ServiceWorker",
+ "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
+ request_.get());
+ DCHECK(!fetch_callback_.is_null());
+ FetchCallback fetch_callback = fetch_callback_;
+ fetch_callback.Run(status, fetch_result, response);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
index 9e595ab0870..f20fb949548 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -11,10 +11,6 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
-namespace net {
-class URLRequest;
-}
-
namespace content {
class ServiceWorkerVersion;
@@ -26,10 +22,10 @@ class ServiceWorkerFetchDispatcher {
ServiceWorkerFetchEventResult,
const ServiceWorkerResponse&)> FetchCallback;
- ServiceWorkerFetchDispatcher(
- net::URLRequest* request,
- ServiceWorkerVersion* version,
- const FetchCallback& callback);
+ ServiceWorkerFetchDispatcher(scoped_ptr<ServiceWorkerFetchRequest> request,
+ ServiceWorkerVersion* version,
+ const base::Closure& prepare_callback,
+ const FetchCallback& fetch_callback);
~ServiceWorkerFetchDispatcher();
// Dispatches a fetch event to the |version| given in ctor, and fires
@@ -40,13 +36,15 @@ class ServiceWorkerFetchDispatcher {
void DidWaitActivation();
void DidFailActivation();
void DispatchFetchEvent();
+ void DidPrepare();
void DidFinish(ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response);
scoped_refptr<ServiceWorkerVersion> version_;
- FetchCallback callback_;
- ServiceWorkerFetchRequest request_;
+ base::Closure prepare_callback_;
+ FetchCallback fetch_callback_;
+ scoped_ptr<ServiceWorkerFetchRequest> request_;
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFetchDispatcher);
diff --git a/chromium/content/browser/service_worker/service_worker_handle.cc b/chromium/content/browser/service_worker/service_worker_handle.cc
index a07ab9e9d91..f39904e4035 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle.cc
@@ -18,20 +18,17 @@ GetWebServiceWorkerState(ServiceWorkerVersion* version) {
DCHECK(version);
switch (version->status()) {
case ServiceWorkerVersion::NEW:
- if (version->running_status() == ServiceWorkerVersion::RUNNING)
- return blink::WebServiceWorkerStateParsed;
- else
- return blink::WebServiceWorkerStateUnknown;
+ return blink::WebServiceWorkerStateUnknown;
case ServiceWorkerVersion::INSTALLING:
return blink::WebServiceWorkerStateInstalling;
case ServiceWorkerVersion::INSTALLED:
return blink::WebServiceWorkerStateInstalled;
case ServiceWorkerVersion::ACTIVATING:
return blink::WebServiceWorkerStateActivating;
- case ServiceWorkerVersion::ACTIVE:
- return blink::WebServiceWorkerStateActive;
- case ServiceWorkerVersion::DEACTIVATED:
- return blink::WebServiceWorkerStateDeactivated;
+ case ServiceWorkerVersion::ACTIVATED:
+ return blink::WebServiceWorkerStateActivated;
+ case ServiceWorkerVersion::REDUNDANT:
+ return blink::WebServiceWorkerStateRedundant;
}
NOTREACHED() << version->status();
return blink::WebServiceWorkerStateUnknown;
@@ -43,25 +40,27 @@ scoped_ptr<ServiceWorkerHandle> ServiceWorkerHandle::Create(
base::WeakPtr<ServiceWorkerContextCore> context,
IPC::Sender* sender,
int thread_id,
+ int provider_id,
ServiceWorkerVersion* version) {
if (!context || !version)
return scoped_ptr<ServiceWorkerHandle>();
ServiceWorkerRegistration* registration =
context->GetLiveRegistration(version->registration_id());
- return make_scoped_ptr(
- new ServiceWorkerHandle(context, sender, thread_id,
- registration, version));
+ return make_scoped_ptr(new ServiceWorkerHandle(
+ context, sender, thread_id, provider_id, registration, version));
}
ServiceWorkerHandle::ServiceWorkerHandle(
base::WeakPtr<ServiceWorkerContextCore> context,
IPC::Sender* sender,
int thread_id,
+ int provider_id,
ServiceWorkerRegistration* registration,
ServiceWorkerVersion* version)
: context_(context),
sender_(sender),
thread_id_(thread_id),
+ provider_id_(provider_id),
handle_id_(context.get() ? context->GetNewServiceWorkerHandleId() : -1),
ref_count_(1),
registration_(registration),
@@ -108,8 +107,9 @@ ServiceWorkerObjectInfo ServiceWorkerHandle::GetObjectInfo() {
ServiceWorkerObjectInfo info;
info.handle_id = handle_id_;
info.scope = registration_->pattern();
- info.url = registration_->script_url();
- info.state = GetWebServiceWorkerState(version_);
+ info.url = version_->script_url();
+ info.state = GetWebServiceWorkerState(version_.get());
+ info.version_id = version_->version_id();
return info;
}
diff --git a/chromium/content/browser/service_worker/service_worker_handle.h b/chromium/content/browser/service_worker/service_worker_handle.h
index 81d5b3574a2..b7696407089 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_handle.h
@@ -28,7 +28,7 @@ class ServiceWorkerRegistration;
// ServiceWorkerRegistration (therefore they're guaranteed to be alive while
// this handle is around).
class CONTENT_EXPORT ServiceWorkerHandle
- : public ServiceWorkerVersion::Listener {
+ : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
public:
// Creates a handle for a live version. The version's corresponding
// registration must be also alive.
@@ -40,36 +40,40 @@ class CONTENT_EXPORT ServiceWorkerHandle
base::WeakPtr<ServiceWorkerContextCore> context,
IPC::Sender* sender,
int thread_id,
+ int provider_id,
ServiceWorkerVersion* version);
ServiceWorkerHandle(base::WeakPtr<ServiceWorkerContextCore> context,
IPC::Sender* sender,
int thread_id,
+ int provider_id,
ServiceWorkerRegistration* registration,
ServiceWorkerVersion* version);
- virtual ~ServiceWorkerHandle();
+ ~ServiceWorkerHandle() override;
// ServiceWorkerVersion::Listener overrides.
- virtual void OnWorkerStarted(ServiceWorkerVersion* version) OVERRIDE;
- virtual void OnWorkerStopped(ServiceWorkerVersion* version) OVERRIDE;
- virtual void OnErrorReported(ServiceWorkerVersion* version,
- const base::string16& error_message,
- int line_number,
- int column_number,
- const GURL& source_url) OVERRIDE;
- virtual void OnReportConsoleMessage(ServiceWorkerVersion* version,
- int source_identifier,
- int message_level,
- const base::string16& message,
- int line_number,
- const GURL& source_url) OVERRIDE;
- virtual void OnVersionStateChanged(ServiceWorkerVersion* version) OVERRIDE;
+ void OnWorkerStarted(ServiceWorkerVersion* version) override;
+ void OnWorkerStopped(ServiceWorkerVersion* version) override;
+ void OnErrorReported(ServiceWorkerVersion* version,
+ const base::string16& error_message,
+ int line_number,
+ int column_number,
+ const GURL& source_url) override;
+ void OnReportConsoleMessage(ServiceWorkerVersion* version,
+ int source_identifier,
+ int message_level,
+ const base::string16& message,
+ int line_number,
+ const GURL& source_url) override;
+ void OnVersionStateChanged(ServiceWorkerVersion* version) override;
ServiceWorkerObjectInfo GetObjectInfo();
+ int thread_id() const { return thread_id_; }
+ int provider_id() const { return provider_id_; }
+ int handle_id() const { return handle_id_; }
ServiceWorkerRegistration* registration() { return registration_.get(); }
ServiceWorkerVersion* version() { return version_.get(); }
- int handle_id() const { return handle_id_; }
bool HasNoRefCount() const { return ref_count_ <= 0; }
void IncrementRefCount();
@@ -79,6 +83,7 @@ class CONTENT_EXPORT ServiceWorkerHandle
base::WeakPtr<ServiceWorkerContextCore> context_;
IPC::Sender* sender_; // Not owned, it should always outlive this.
const int thread_id_;
+ const int provider_id_;
const int handle_id_;
int ref_count_; // Created with 1.
scoped_refptr<ServiceWorkerRegistration> registration_;
diff --git a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
index 70c445613c9..8adf4f50bfe 100644
--- a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -43,23 +43,24 @@ class ServiceWorkerHandleTest : public testing::Test {
ServiceWorkerHandleTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
+ const GURL pattern("http://www.example.com/");
registration_ = new ServiceWorkerRegistration(
- GURL("http://www.example.com/*"),
- GURL("http://www.example.com/service_worker.js"),
+ pattern,
1L,
helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_, 1L, helper_->context()->AsWeakPtr());
+ registration_.get(),
+ GURL("http://www.example.com/service_worker.js"),
+ 1L,
+ helper_->context()->AsWeakPtr());
- // Simulate adding one process to the worker.
- int embedded_worker_id = version_->embedded_worker()->embedded_worker_id();
- helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
+ helper_->SimulateAddProcessToPattern(pattern, kRenderProcessId);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
registration_ = NULL;
version_ = NULL;
helper_.reset();
@@ -71,6 +72,8 @@ class ServiceWorkerHandleTest : public testing::Test {
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerHandleTest);
};
@@ -79,7 +82,8 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
ServiceWorkerHandle::Create(helper_->context()->AsWeakPtr(),
helper_.get(),
1 /* thread_id */,
- version_);
+ 33 /* provider_id */,
+ version_.get());
// Start the worker, and then...
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
@@ -89,10 +93,13 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
// ...dispatch install event.
status = SERVICE_WORKER_ERROR_FAILED;
+ version_->SetStatus(ServiceWorkerVersion::INSTALLING);
version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
+ version_->SetStatus(ServiceWorkerVersion::INSTALLED);
+
ASSERT_EQ(4UL, ipc_sink()->message_count());
// We should be sending 1. StartWorker,
diff --git a/chromium/content/browser/service_worker/service_worker_histograms.cc b/chromium/content/browser/service_worker/service_worker_histograms.cc
deleted file mode 100644
index 8d1df4bef4b..00000000000
--- a/chromium/content/browser/service_worker/service_worker_histograms.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 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 "content/browser/service_worker/service_worker_histograms.h"
-
-#include "base/metrics/histogram.h"
-
-namespace content {
-
-// static
-void ServiceWorkerHistograms::CountInitDiskCacheResult(bool result) {
- UMA_HISTOGRAM_BOOLEAN("ServiceWorker.DiskCache.InitResult", result);
-}
-
-// static
-void ServiceWorkerHistograms::CountReadResponseResult(
- ServiceWorkerHistograms::ReadResponseResult result) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCache.ReadResponseResult",
- result, NUM_READ_RESPONSE_RESULT_TYPES);
-}
-
-// static
-void ServiceWorkerHistograms::CountWriteResponseResult(
- ServiceWorkerHistograms::WriteResponseResult result) {
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCache.WriteResponseResult",
- result, NUM_WRITE_RESPONSE_RESULT_TYPES);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_histograms.h b/chromium/content/browser/service_worker/service_worker_histograms.h
deleted file mode 100644
index a9ad8c6ef06..00000000000
--- a/chromium/content/browser/service_worker/service_worker_histograms.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HISTOGRAMS_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HISTOGRAMS_H_
-
-#include "base/macros.h"
-
-namespace content {
-
-class ServiceWorkerHistograms {
- public:
- enum ReadResponseResult {
- READ_OK,
- READ_HEADERS_ERROR,
- READ_DATA_ERROR,
- NUM_READ_RESPONSE_RESULT_TYPES,
- };
-
- enum WriteResponseResult {
- WRITE_OK,
- WRITE_HEADERS_ERROR,
- WRITE_DATA_ERROR,
- NUM_WRITE_RESPONSE_RESULT_TYPES,
- };
-
- static void CountInitDiskCacheResult(bool result);
- static void CountReadResponseResult(ReadResponseResult result);
- static void CountWriteResponseResult(WriteResponseResult result);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerHistograms);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_HISTOGRAMS_H_
diff --git a/chromium/content/browser/service_worker/service_worker_info.cc b/chromium/content/browser/service_worker/service_worker_info.cc
index 8933340c2ff..1efe110c62f 100644
--- a/chromium/content/browser/service_worker/service_worker_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_info.cc
@@ -10,8 +10,7 @@
namespace content {
ServiceWorkerVersionInfo::ServiceWorkerVersionInfo()
- : is_null(true),
- running_status(ServiceWorkerVersion::STOPPED),
+ : running_status(ServiceWorkerVersion::STOPPED),
status(ServiceWorkerVersion::NEW),
version_id(kInvalidServiceWorkerVersionId),
process_id(-1),
@@ -22,13 +21,14 @@ ServiceWorkerVersionInfo::ServiceWorkerVersionInfo()
ServiceWorkerVersionInfo::ServiceWorkerVersionInfo(
ServiceWorkerVersion::RunningStatus running_status,
ServiceWorkerVersion::Status status,
+ const GURL& script_url,
int64 version_id,
int process_id,
int thread_id,
int devtools_agent_route_id)
- : is_null(false),
- running_status(running_status),
+ : running_status(running_status),
status(status),
+ script_url(script_url),
version_id(version_id),
process_id(process_id),
thread_id(thread_id),
@@ -37,19 +37,24 @@ ServiceWorkerVersionInfo::ServiceWorkerVersionInfo(
ServiceWorkerVersionInfo::~ServiceWorkerVersionInfo() {}
-ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo() {}
+ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo()
+ : registration_id(kInvalidServiceWorkerRegistrationId),
+ stored_version_size_bytes(0) {
+}
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
- const GURL& script_url,
const GURL& pattern,
int64 registration_id,
const ServiceWorkerVersionInfo& active_version,
- const ServiceWorkerVersionInfo& waiting_version)
- : script_url(script_url),
- pattern(pattern),
+ const ServiceWorkerVersionInfo& waiting_version,
+ const ServiceWorkerVersionInfo& installing_version,
+ int64_t stored_version_size_bytes)
+ : pattern(pattern),
registration_id(registration_id),
active_version(active_version),
- waiting_version(waiting_version) {
+ waiting_version(waiting_version),
+ installing_version(installing_version),
+ stored_version_size_bytes(stored_version_size_bytes) {
}
ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo() {}
diff --git a/chromium/content/browser/service_worker/service_worker_info.h b/chromium/content/browser/service_worker/service_worker_info.h
index 99e374696b0..0e93bd0748b 100644
--- a/chromium/content/browser/service_worker/service_worker_info.h
+++ b/chromium/content/browser/service_worker/service_worker_info.h
@@ -18,15 +18,16 @@ class CONTENT_EXPORT ServiceWorkerVersionInfo {
ServiceWorkerVersionInfo();
ServiceWorkerVersionInfo(ServiceWorkerVersion::RunningStatus running_status,
ServiceWorkerVersion::Status status,
+ const GURL& script_url,
int64 version_id,
int process_id,
int thread_id,
int devtools_agent_route_id);
~ServiceWorkerVersionInfo();
- bool is_null;
ServiceWorkerVersion::RunningStatus running_status;
ServiceWorkerVersion::Status status;
+ GURL script_url;
int64 version_id;
int process_id;
int thread_id;
@@ -37,18 +38,22 @@ class CONTENT_EXPORT ServiceWorkerRegistrationInfo {
public:
ServiceWorkerRegistrationInfo();
ServiceWorkerRegistrationInfo(
- const GURL& script_url,
const GURL& pattern,
int64 registration_id,
const ServiceWorkerVersionInfo& active_version,
- const ServiceWorkerVersionInfo& waiting_version);
+ const ServiceWorkerVersionInfo& waiting_version,
+ const ServiceWorkerVersionInfo& installing_version,
+ int64_t active_version_total_size_bytes);
~ServiceWorkerRegistrationInfo();
- GURL script_url;
GURL pattern;
int64 registration_id;
+ ServiceWorkerVersionInfo controlling_version;
ServiceWorkerVersionInfo active_version;
ServiceWorkerVersionInfo waiting_version;
+ ServiceWorkerVersionInfo installing_version;
+
+ int64_t stored_version_size_bytes;
};
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.cc b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
index e976ad82884..a7c8d716813 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -11,12 +11,13 @@
#include "base/memory/scoped_vector.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
-#include "content/browser/devtools/devtools_manager_impl.h"
+#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/embedded_worker_devtools_manager.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
@@ -24,7 +25,6 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/url_constants.h"
-#include "grit/content_resources.h"
using base::DictionaryValue;
using base::FundamentalValue;
@@ -75,11 +75,11 @@ void CallServiceWorkerVersionMethodWithVersionID(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
scoped_refptr<ServiceWorkerVersion> version =
context->context()->GetLiveVersion(version_id);
- if (!version) {
+ if (!version.get()) {
callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
return;
}
- (*version.*method)(callback);
+ (*version.get().*method)(callback);
}
void DispatchPushEventWithVersionID(
@@ -99,7 +99,7 @@ void DispatchPushEventWithVersionID(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
scoped_refptr<ServiceWorkerVersion> version =
context->context()->GetLiveVersion(version_id);
- if (!version) {
+ if (!version.get()) {
callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
return;
}
@@ -189,13 +189,14 @@ void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
case ServiceWorkerVersion::ACTIVATING:
info->SetString("status", "ACTIVATING");
break;
- case ServiceWorkerVersion::ACTIVE:
- info->SetString("status", "ACTIVE");
+ case ServiceWorkerVersion::ACTIVATED:
+ info->SetString("status", "ACTIVATED");
break;
- case ServiceWorkerVersion::DEACTIVATED:
- info->SetString("status", "DEACTIVATED");
+ case ServiceWorkerVersion::REDUNDANT:
+ info->SetString("status", "REDUNDANT");
break;
}
+ info->SetString("script_url", version.script_url.spec());
info->SetString("version_id", base::Int64ToString(version.version_id));
info->SetInteger("process_id", version.process_id);
info->SetInteger("thread_id", version.thread_id);
@@ -212,17 +213,18 @@ ListValue* GetRegistrationListValue(
const ServiceWorkerRegistrationInfo& registration = *it;
DictionaryValue* registration_info = new DictionaryValue();
registration_info->SetString("scope", registration.pattern.spec());
- registration_info->SetString("script_url", registration.script_url.spec());
registration_info->SetString(
"registration_id", base::Int64ToString(registration.registration_id));
- if (!registration.active_version.is_null) {
+ if (registration.active_version.version_id !=
+ kInvalidServiceWorkerVersionId) {
DictionaryValue* active_info = new DictionaryValue();
UpdateVersionInfo(registration.active_version, active_info);
registration_info->Set("active", active_info);
}
- if (!registration.waiting_version.is_null) {
+ if (registration.waiting_version.version_id !=
+ kInvalidServiceWorkerVersionId) {
DictionaryValue* waiting_info = new DictionaryValue();
UpdateVersionInfo(registration.waiting_version, waiting_info);
registration_info->Set("waiting", waiting_info);
@@ -300,11 +302,11 @@ class ServiceWorkerInternalsUI::PartitionObserver
public:
PartitionObserver(int partition_id, WebUI* web_ui)
: partition_id_(partition_id), web_ui_(web_ui) {}
- virtual ~PartitionObserver() {}
+ ~PartitionObserver() override {}
// ServiceWorkerContextObserver overrides:
- virtual void OnWorkerStarted(int64 version_id,
- int process_id,
- int thread_id) OVERRIDE {
+ void OnWorkerStarted(int64 version_id,
+ int process_id,
+ int thread_id) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
web_ui_->CallJavascriptFunction(
"serviceworker.onWorkerStarted",
@@ -313,9 +315,9 @@ class ServiceWorkerInternalsUI::PartitionObserver
FundamentalValue(process_id),
FundamentalValue(thread_id));
}
- virtual void OnWorkerStopped(int64 version_id,
- int process_id,
- int thread_id) OVERRIDE {
+ void OnWorkerStopped(int64 version_id,
+ int process_id,
+ int thread_id) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
web_ui_->CallJavascriptFunction(
"serviceworker.onWorkerStopped",
@@ -324,17 +326,17 @@ class ServiceWorkerInternalsUI::PartitionObserver
FundamentalValue(process_id),
FundamentalValue(thread_id));
}
- virtual void OnVersionStateChanged(int64 version_id) OVERRIDE {
+ void OnVersionStateChanged(int64 version_id) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
web_ui_->CallJavascriptFunction(
"serviceworker.onVersionStateChanged",
FundamentalValue(partition_id_),
StringValue(base::Int64ToString(version_id)));
}
- virtual void OnErrorReported(int64 version_id,
- int process_id,
- int thread_id,
- const ErrorInfo& info) OVERRIDE {
+ void OnErrorReported(int64 version_id,
+ int process_id,
+ int thread_id,
+ const ErrorInfo& info) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ScopedVector<const Value> args;
args.push_back(new FundamentalValue(partition_id_));
@@ -350,10 +352,10 @@ class ServiceWorkerInternalsUI::PartitionObserver
web_ui_->CallJavascriptFunction("serviceworker.onErrorReported",
args.get());
}
- virtual void OnReportConsoleMessage(int64 version_id,
- int process_id,
- int thread_id,
- const ConsoleMessage& message) OVERRIDE {
+ void OnReportConsoleMessage(int64 version_id,
+ int process_id,
+ int thread_id,
+ const ConsoleMessage& message) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
ScopedVector<const Value> args;
args.push_back(new FundamentalValue(partition_id_));
@@ -370,12 +372,12 @@ class ServiceWorkerInternalsUI::PartitionObserver
web_ui_->CallJavascriptFunction("serviceworker.onConsoleMessageReported",
args.get());
}
- virtual void OnRegistrationStored(const GURL& pattern) OVERRIDE {
+ void OnRegistrationStored(const GURL& pattern) override {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
web_ui_->CallJavascriptFunction("serviceworker.onRegistrationStored",
StringValue(pattern.spec()));
}
- virtual void OnRegistrationDeleted(const GURL& pattern) OVERRIDE {
+ void OnRegistrationDeleted(const GURL& pattern) override {
web_ui_->CallJavascriptFunction("serviceworker.onRegistrationDeleted",
StringValue(pattern.spec()));
}
@@ -390,7 +392,6 @@ ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
: WebUIController(web_ui), next_partition_id_(0) {
WebUIDataSource* source =
WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost);
- source->SetUseJsonJSFormatV2();
source->SetJsonPath("strings.js");
source->AddResourcePath("serviceworker_internals.js",
IDR_SERVICE_WORKER_INTERNALS_JS);
@@ -500,6 +501,7 @@ void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
context->AddObserver(new_observer.get());
observers_.set(reinterpret_cast<uintptr_t>(partition), new_observer.Pass());
}
+
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -510,7 +512,9 @@ void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
base::Bind(OnAllRegistrations,
AsWeakPtr(),
partition_id,
- partition->GetPath()))));
+ context->is_incognito()
+ ? base::FilePath()
+ : partition->GetPath()))));
}
void ServiceWorkerInternalsUI::RemoveObserverFromStoragePartition(
@@ -560,11 +564,11 @@ void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
const ListValue* args) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
int callback_id;
- int partition_id;
- int64 version_id;
- std::string version_id_string;
const DictionaryValue* cmd_args = NULL;
+ int partition_id;
scoped_refptr<ServiceWorkerContextWrapper> context;
+ std::string version_id_string;
+ int64 version_id = 0;
if (!args->GetInteger(0, &callback_id) ||
!args->GetDictionary(1, &cmd_args) ||
!cmd_args->GetInteger("partition_id", &partition_id) ||
@@ -585,7 +589,7 @@ void ServiceWorkerInternalsUI::DispatchPushEvent(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
int callback_id;
int partition_id;
- int64 version_id;
+ int64 version_id = 0;
std::string version_id_string;
const DictionaryValue* cmd_args = NULL;
scoped_refptr<ServiceWorkerContextWrapper> context;
@@ -606,10 +610,9 @@ void ServiceWorkerInternalsUI::DispatchPushEvent(
void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
int callback_id;
- int process_id;
- int devtools_agent_route_id;
const DictionaryValue* cmd_args = NULL;
- scoped_refptr<ServiceWorkerContextWrapper> context;
+ int process_id = 0;
+ int devtools_agent_route_id = 0;
if (!args->GetInteger(0, &callback_id) ||
!args->GetDictionary(1, &cmd_args) ||
!cmd_args->GetInteger("process_id", &process_id) ||
@@ -619,15 +622,14 @@ void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
}
base::Callback<void(ServiceWorkerStatusCode)> callback =
base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
- scoped_refptr<DevToolsAgentHost> agent_host(
+ scoped_refptr<DevToolsAgentHostImpl> agent_host(
EmbeddedWorkerDevToolsManager::GetInstance()
->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
- if (!agent_host) {
+ if (!agent_host.get()) {
callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
return;
}
- DevToolsManagerImpl::GetInstance()->Inspect(
- web_ui()->GetWebContents()->GetBrowserContext(), agent_host.get());
+ agent_host->Inspect(web_ui()->GetWebContents()->GetBrowserContext());
callback.Run(SERVICE_WORKER_OK);
}
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.h b/chromium/content/browser/service_worker/service_worker_internals_ui.h
index 84c1e19204e..f0c09d68616 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.h
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.h
@@ -42,7 +42,7 @@ class ServiceWorkerInternalsUI
class OperationProxy;
class PartitionObserver;
- virtual ~ServiceWorkerInternalsUI();
+ ~ServiceWorkerInternalsUI() override;
void AddContextFromStoragePartition(StoragePartition* partition);
void RemoveObserverFromStoragePartition(StoragePartition* partition);
diff --git a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
index 8152b490272..c3bfb396b4f 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
@@ -71,14 +71,14 @@ ServiceWorkerJobCoordinator::~ServiceWorkerJobCoordinator() {
void ServiceWorkerJobCoordinator::Register(
const GURL& pattern,
const GURL& script_url,
- int source_process_id,
+ ServiceWorkerProviderHost* provider_host,
const ServiceWorkerRegisterJob::RegistrationCallback& callback) {
scoped_ptr<ServiceWorkerRegisterJobBase> job(
new ServiceWorkerRegisterJob(context_, pattern, script_url));
ServiceWorkerRegisterJob* queued_job =
static_cast<ServiceWorkerRegisterJob*>(
job_queues_[pattern].Push(job.Pass()));
- queued_job->AddCallback(callback, source_process_id);
+ queued_job->AddCallback(callback, provider_host);
}
void ServiceWorkerJobCoordinator::Unregister(
@@ -92,6 +92,15 @@ void ServiceWorkerJobCoordinator::Unregister(
queued_job->AddCallback(callback);
}
+void ServiceWorkerJobCoordinator::Update(
+ ServiceWorkerRegistration* registration) {
+ DCHECK(registration);
+ DCHECK(registration->GetNewestVersion());
+ job_queues_[registration->pattern()].Push(
+ make_scoped_ptr<ServiceWorkerRegisterJobBase>(
+ new ServiceWorkerRegisterJob(context_, registration)));
+}
+
void ServiceWorkerJobCoordinator::AbortAll() {
for (RegistrationJobMap::iterator it = job_queues_.begin();
it != job_queues_.end(); ++it) {
diff --git a/chromium/content/browser/service_worker/service_worker_job_coordinator.h b/chromium/content/browser/service_worker/service_worker_job_coordinator.h
index 06a1057d76e..b85a84bc52c 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.h
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.h
@@ -16,6 +16,7 @@
namespace content {
class EmbeddedWorkerRegistry;
+class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
class ServiceWorkerStorage;
@@ -28,13 +29,15 @@ class CONTENT_EXPORT ServiceWorkerJobCoordinator {
void Register(const GURL& pattern,
const GURL& script_url,
- int source_process_id,
+ ServiceWorkerProviderHost* provider_host,
const ServiceWorkerRegisterJob::RegistrationCallback& callback);
void Unregister(
const GURL& pattern,
const ServiceWorkerUnregisterJob::UnregistrationCallback& callback);
+ void Update(ServiceWorkerRegistration* registration);
+
// Calls ServiceWorkerRegisterJobBase::Abort() on all jobs and removes them.
void AbortAll();
diff --git a/chromium/content/browser/service_worker/service_worker_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
index efa8bd1aa1e..515e0f82fdc 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -9,27 +9,36 @@
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_registration_status.h"
+#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_test_sink.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
+using net::IOBuffer;
+using net::TestCompletionCallback;
+using net::WrappedIOBuffer;
+
// Unit tests for testing all job registration tasks.
namespace content {
namespace {
+int kMockRenderProcessId = 88;
+
void SaveRegistrationCallback(
ServiceWorkerStatusCode expected_status,
bool* called,
scoped_refptr<ServiceWorkerRegistration>* registration_out,
ServiceWorkerStatusCode status,
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version) {
- ASSERT_TRUE(!version || version->registration_id() == registration->id())
- << version << " " << registration;
+ ServiceWorkerRegistration* registration) {
EXPECT_EQ(expected_status, status);
*called = true;
*registration_out = registration;
@@ -91,15 +100,13 @@ class ServiceWorkerJobTest : public testing::Test {
public:
ServiceWorkerJobTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- render_process_id_(88) {}
+ render_process_id_(kMockRenderProcessId) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(render_process_id_));
}
- virtual void TearDown() OVERRIDE {
- helper_.reset();
- }
+ void TearDown() override { helper_.reset(); }
ServiceWorkerContextCore* context() const { return helper_->context(); }
@@ -111,7 +118,6 @@ class ServiceWorkerJobTest : public testing::Test {
protected:
TestBrowserThreadBundle browser_thread_bundle_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
-
int render_process_id_;
};
@@ -119,9 +125,9 @@ TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
scoped_refptr<ServiceWorkerRegistration> original_registration;
bool called;
job_coordinator()->Register(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &original_registration));
EXPECT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -137,7 +143,7 @@ TEST_F(ServiceWorkerJobTest, SameDocumentSameRegistration) {
SaveFoundRegistration(SERVICE_WORKER_OK, &called, &registration2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
- ASSERT_TRUE(registration1);
+ ASSERT_TRUE(registration1.get());
ASSERT_EQ(registration1, original_registration);
ASSERT_EQ(registration1, registration2);
}
@@ -146,9 +152,9 @@ TEST_F(ServiceWorkerJobTest, SameMatchSameRegistration) {
bool called;
scoped_refptr<ServiceWorkerRegistration> original_registration;
job_coordinator()->Register(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &original_registration));
EXPECT_FALSE(called);
base::RunLoop().RunUntilIdle();
@@ -177,17 +183,17 @@ TEST_F(ServiceWorkerJobTest, DifferentMatchDifferentRegistration) {
bool called1;
scoped_refptr<ServiceWorkerRegistration> original_registration1;
job_coordinator()->Register(
- GURL("http://www.example.com/one/*"),
+ GURL("http://www.example.com/one/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called1, &original_registration1));
bool called2;
scoped_refptr<ServiceWorkerRegistration> original_registration2;
job_coordinator()->Register(
- GURL("http://www.example.com/two/*"),
+ GURL("http://www.example.com/two/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called2, &original_registration2));
EXPECT_FALSE(called1);
@@ -216,9 +222,9 @@ TEST_F(ServiceWorkerJobTest, Register) {
bool called = false;
scoped_refptr<ServiceWorkerRegistration> registration;
job_coordinator()->Register(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
ASSERT_FALSE(called);
@@ -230,14 +236,14 @@ TEST_F(ServiceWorkerJobTest, Register) {
// Make sure registrations are cleaned up when they are unregistered.
TEST_F(ServiceWorkerJobTest, Unregister) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
bool called;
scoped_refptr<ServiceWorkerRegistration> registration;
job_coordinator()->Register(
pattern,
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
ASSERT_FALSE(called);
@@ -266,28 +272,29 @@ TEST_F(ServiceWorkerJobTest, Unregister) {
}
TEST_F(ServiceWorkerJobTest, Unregister_NothingRegistered) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
bool called;
- job_coordinator()->Unregister(pattern,
- SaveUnregistration(SERVICE_WORKER_OK, &called));
+ job_coordinator()->Unregister(
+ pattern,
+ SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND, &called));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
}
-// Make sure that when a new registration replaces an existing
-// registration, that the old one is cleaned up.
+// Make sure registering a new script creates a new version and shares an
+// existing registration.
TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
bool called;
scoped_refptr<ServiceWorkerRegistration> old_registration;
job_coordinator()->Register(
pattern,
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &old_registration));
ASSERT_FALSE(called);
@@ -311,16 +318,14 @@ TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
job_coordinator()->Register(
pattern,
GURL("http://www.example.com/service_worker_new.js"),
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &new_registration));
ASSERT_FALSE(called);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
- ASSERT_TRUE(old_registration->HasOneRef());
-
- ASSERT_NE(old_registration, new_registration);
+ ASSERT_EQ(old_registration, new_registration);
scoped_refptr<ServiceWorkerRegistration> new_registration_by_pattern;
storage()->FindRegistrationForPattern(
@@ -338,7 +343,7 @@ TEST_F(ServiceWorkerJobTest, RegisterNewScript) {
// Make sure that when registering a duplicate pattern+script_url
// combination, that the same registration is used.
TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
bool called;
@@ -346,7 +351,7 @@ TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
job_coordinator()->Register(
pattern,
script_url,
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &old_registration));
ASSERT_FALSE(called);
@@ -362,13 +367,13 @@ TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(called);
- ASSERT_TRUE(old_registration_by_pattern);
+ ASSERT_TRUE(old_registration_by_pattern.get());
scoped_refptr<ServiceWorkerRegistration> new_registration;
job_coordinator()->Register(
pattern,
script_url,
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &called, &new_registration));
ASSERT_FALSE(called);
@@ -394,14 +399,14 @@ TEST_F(ServiceWorkerJobTest, RegisterDuplicateScript) {
class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
public:
- FailToStartWorkerTestHelper(int mock_render_process_id)
+ explicit FailToStartWorkerTestHelper(int mock_render_process_id)
: EmbeddedWorkerTestHelper(mock_render_process_id) {}
- virtual void OnStartWorker(int embedded_worker_id,
- int64 service_worker_version_id,
- const GURL& scope,
- const GURL& script_url) OVERRIDE {
- // Simulate failure by sending worker stopped instead of started.
+ void OnStartWorker(int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download) override {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
}
@@ -413,9 +418,9 @@ TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
bool called = false;
scoped_refptr<ServiceWorkerRegistration> registration;
job_coordinator()->Register(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/service_worker.js"),
- render_process_id_,
+ NULL,
SaveRegistration(
SERVICE_WORKER_ERROR_START_WORKER_FAILED, &called, &registration));
@@ -429,7 +434,7 @@ TEST_F(ServiceWorkerJobTest, Register_FailToStartWorker) {
// Register and then unregister the pattern, in parallel. Job coordinator should
// process jobs until the last job.
TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
bool registration_called = false;
@@ -437,7 +442,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
job_coordinator()->Register(
pattern,
script_url,
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_OK, &registration_called, &registration));
bool unregistration_called = false;
@@ -466,7 +471,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegUnreg) {
// registration should win, and the old registration should have been
// shutdown.
TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url1("http://www.example.com/service_worker1.js");
bool registration1_called = false;
@@ -474,7 +479,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
job_coordinator()->Register(
pattern,
script_url1,
- render_process_id_,
+ NULL,
SaveRegistration(
SERVICE_WORKER_OK, &registration1_called, &registration1));
@@ -484,7 +489,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
job_coordinator()->Register(
pattern,
script_url2,
- render_process_id_,
+ NULL,
SaveRegistration(
SERVICE_WORKER_OK, &registration2_called, &registration2));
@@ -510,7 +515,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegNewScript) {
// coalesced such that both callers get the exact same registration
// object.
TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker1.js");
bool registration1_called = false;
@@ -518,7 +523,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
job_coordinator()->Register(
pattern,
script_url,
- render_process_id_,
+ NULL,
SaveRegistration(
SERVICE_WORKER_OK, &registration1_called, &registration1));
@@ -527,7 +532,7 @@ TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
job_coordinator()->Register(
pattern,
script_url,
- render_process_id_,
+ NULL,
SaveRegistration(
SERVICE_WORKER_OK, &registration2_called, &registration2));
@@ -552,17 +557,20 @@ TEST_F(ServiceWorkerJobTest, ParallelRegSameScript) {
// Call simulataneous unregister calls.
TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
bool unregistration1_called = false;
job_coordinator()->Unregister(
pattern,
- SaveUnregistration(SERVICE_WORKER_OK, &unregistration1_called));
+ SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
+ &unregistration1_called));
bool unregistration2_called = false;
job_coordinator()->Unregister(
- pattern, SaveUnregistration(SERVICE_WORKER_OK, &unregistration2_called));
+ pattern,
+ SaveUnregistration(SERVICE_WORKER_ERROR_NOT_FOUND,
+ &unregistration2_called));
ASSERT_FALSE(unregistration1_called);
ASSERT_FALSE(unregistration2_called);
@@ -585,8 +593,8 @@ TEST_F(ServiceWorkerJobTest, ParallelUnreg) {
}
TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
- GURL pattern1("http://www1.example.com/*");
- GURL pattern2("http://www2.example.com/*");
+ GURL pattern1("http://www1.example.com/");
+ GURL pattern2("http://www2.example.com/");
GURL script_url1("http://www1.example.com/service_worker.js");
GURL script_url2("http://www2.example.com/service_worker.js");
@@ -595,7 +603,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
job_coordinator()->Register(
pattern1,
script_url1,
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
&registration_called1, &registration1));
@@ -604,7 +612,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
job_coordinator()->Register(
pattern2,
script_url2,
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
&registration_called2, &registration2));
@@ -636,8 +644,8 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Register) {
}
TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
- GURL pattern1("http://www1.example.com/*");
- GURL pattern2("http://www2.example.com/*");
+ GURL pattern1("http://www1.example.com/");
+ GURL pattern2("http://www2.example.com/");
bool unregistration_called1 = false;
scoped_refptr<ServiceWorkerRegistration> registration1;
@@ -662,7 +670,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_Unregister) {
}
TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
- GURL pattern("http://www.example.com/*");
+ GURL pattern("http://www.example.com/");
GURL script_url("http://www.example.com/service_worker.js");
bool registration_called = false;
@@ -670,7 +678,7 @@ TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
job_coordinator()->Register(
pattern,
script_url,
- render_process_id_,
+ NULL,
SaveRegistration(SERVICE_WORKER_ERROR_ABORT,
&registration_called, &registration));
@@ -699,4 +707,499 @@ TEST_F(ServiceWorkerJobTest, AbortAll_RegUnreg) {
EXPECT_EQ(scoped_refptr<ServiceWorkerRegistration>(), registration);
}
+// Tests that the waiting worker enters the 'redundant' state upon
+// unregistration.
+TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ bool called = false;
+ GURL script_url("http://www.example.com/service_worker.js");
+ job_coordinator()->Register(
+ GURL("http://www.example.com/"),
+ script_url,
+ NULL,
+ SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+ ASSERT_TRUE(registration.get());
+
+ // Manually create the waiting worker since there is no way to become a
+ // waiting worker until Update is implemented.
+ scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
+ registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ version->StartWorker(CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(SERVICE_WORKER_OK, status);
+
+ version->SetStatus(ServiceWorkerVersion::INSTALLED);
+ registration->SetWaitingVersion(version.get());
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING,
+ version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status());
+
+ called = false;
+ job_coordinator()->Unregister(GURL("http://www.example.com/"),
+ SaveUnregistration(SERVICE_WORKER_OK, &called));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ // The version should be stopped since there is no controllee after
+ // unregistration.
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
+}
+
+// Tests that the active worker enters the 'redundant' state upon
+// unregistration.
+TEST_F(ServiceWorkerJobTest, UnregisterActiveSetsRedundant) {
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ bool called = false;
+ job_coordinator()->Register(
+ GURL("http://www.example.com/"),
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+ ASSERT_TRUE(registration.get());
+
+ scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
+
+ called = false;
+ job_coordinator()->Unregister(GURL("http://www.example.com/"),
+ SaveUnregistration(SERVICE_WORKER_OK, &called));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ // The version should be stopped since there is no controllee after
+ // unregistration.
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
+}
+
+// Tests that the active worker enters the 'redundant' state upon
+// unregistration.
+TEST_F(ServiceWorkerJobTest,
+ UnregisterActiveSetsRedundant_WaitForNoControllee) {
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ bool called = false;
+ job_coordinator()->Register(
+ GURL("http://www.example.com/"),
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+ ASSERT_TRUE(registration.get());
+
+ scoped_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(33 /* dummy render process id */,
+ 1 /* dummy provider_id */,
+ context()->AsWeakPtr(),
+ NULL));
+ registration->active_version()->AddControllee(host.get());
+
+ scoped_refptr<ServiceWorkerVersion> version = registration->active_version();
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
+
+ called = false;
+ job_coordinator()->Unregister(GURL("http://www.example.com/"),
+ SaveUnregistration(SERVICE_WORKER_OK, &called));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(called);
+
+ // The version should be running since there is still a controllee.
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED, version->status());
+
+ registration->active_version()->RemoveControllee(host.get());
+ base::RunLoop().RunUntilIdle();
+
+ // The version should be stopped since there is no controllee.
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_EQ(ServiceWorkerVersion::REDUNDANT, version->status());
+}
+
+namespace { // Helpers for the update job tests.
+
+const GURL kNoChangeOrigin("http://nochange/");
+const GURL kNewVersionOrigin("http://newversion/");
+const std::string kScope("scope/");
+const std::string kScript("script.js");
+
+void RunNestedUntilIdle() {
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+ base::MessageLoop::current()->RunUntilIdle();
+}
+
+void OnIOComplete(int* rv_out, int rv) {
+ *rv_out = rv;
+}
+
+void WriteResponse(
+ ServiceWorkerStorage* storage, int64 id,
+ const std::string& headers,
+ IOBuffer* body, int length) {
+ scoped_ptr<ServiceWorkerResponseWriter> writer =
+ storage->CreateResponseWriter(id);
+
+ scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
+ info->request_time = base::Time::Now();
+ info->response_time = base::Time::Now();
+ info->was_cached = false;
+ info->headers = new net::HttpResponseHeaders(headers);
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
+ new HttpResponseInfoIOBuffer(info.release());
+
+ int rv = -1234;
+ writer->WriteInfo(info_buffer.get(), base::Bind(&OnIOComplete, &rv));
+ RunNestedUntilIdle();
+ EXPECT_LT(0, rv);
+
+ rv = -1234;
+ writer->WriteData(body, length,
+ base::Bind(&OnIOComplete, &rv));
+ RunNestedUntilIdle();
+ EXPECT_EQ(length, rv);
+}
+
+void WriteStringResponse(
+ ServiceWorkerStorage* storage, int64 id,
+ const std::string& body) {
+ scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
+ const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
+ std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
+ WriteResponse(storage, id, headers, body_buffer.get(), body.length());
+}
+
+class UpdateJobTestHelper
+ : public EmbeddedWorkerTestHelper,
+ public ServiceWorkerRegistration::Listener,
+ public ServiceWorkerVersion::Listener {
+ public:
+ struct AttributeChangeLogEntry {
+ int64 registration_id;
+ ChangedVersionAttributesMask mask;
+ ServiceWorkerRegistrationInfo info;
+ };
+
+ struct StateChangeLogEntry {
+ int64 version_id;
+ ServiceWorkerVersion::Status status;
+ };
+
+ UpdateJobTestHelper(int mock_render_process_id)
+ : EmbeddedWorkerTestHelper(mock_render_process_id),
+ update_found_(false) {}
+ ~UpdateJobTestHelper() override {
+ if (registration_.get())
+ registration_->RemoveListener(this);
+ }
+
+ ServiceWorkerStorage* storage() { return context()->storage(); }
+ ServiceWorkerJobCoordinator* job_coordinator() {
+ return context()->job_coordinator();
+ }
+
+ scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
+ const GURL& test_origin) {
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ bool called = false;
+ job_coordinator()->Register(
+ test_origin.Resolve(kScope),
+ test_origin.Resolve(kScript),
+ NULL,
+ SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_TRUE(registration.get());
+ EXPECT_TRUE(registration->active_version());
+ EXPECT_FALSE(registration->installing_version());
+ EXPECT_FALSE(registration->waiting_version());
+ registration_ = registration;
+ return registration;
+ }
+
+ // EmbeddedWorkerTestHelper overrides
+ void OnStartWorker(int embedded_worker_id,
+ int64 version_id,
+ const GURL& scope,
+ const GURL& script,
+ bool pause_after_download) override {
+ const std::string kMockScriptBody = "mock_script";
+ const uint64 kMockScriptSize = 19284;
+ ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
+ ASSERT_TRUE(version);
+ version->AddListener(this);
+
+ if (!pause_after_download) {
+ // Spoof caching the script for the initial version.
+ int64 resource_id = storage()->NewResourceId();
+ version->script_cache_map()->NotifyStartedCaching(script, resource_id);
+ WriteStringResponse(storage(), resource_id, kMockScriptBody);
+ version->script_cache_map()->NotifyFinishedCaching(
+ script, kMockScriptSize, net::URLRequestStatus());
+ } else {
+ // Spoof caching the script for the new version.
+ int64 resource_id = storage()->NewResourceId();
+ version->script_cache_map()->NotifyStartedCaching(script, resource_id);
+ if (script.GetOrigin() == kNoChangeOrigin)
+ WriteStringResponse(storage(), resource_id, kMockScriptBody);
+ else
+ WriteStringResponse(storage(), resource_id, "mock_different_script");
+ version->script_cache_map()->NotifyFinishedCaching(
+ script, kMockScriptSize, net::URLRequestStatus());
+ }
+ EmbeddedWorkerTestHelper::OnStartWorker(
+ embedded_worker_id, version_id, scope, script, pause_after_download);
+ }
+
+ // ServiceWorkerRegistration::Listener overrides
+ void OnVersionAttributesChanged(
+ ServiceWorkerRegistration* registration,
+ ChangedVersionAttributesMask changed_mask,
+ const ServiceWorkerRegistrationInfo& info) override {
+ AttributeChangeLogEntry entry;
+ entry.registration_id = registration->id();
+ entry.mask = changed_mask;
+ entry.info = info;
+ attribute_change_log_.push_back(entry);
+ }
+
+ void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
+ NOTREACHED();
+ }
+
+ void OnRegistrationFinishedUninstalling(
+ ServiceWorkerRegistration* registration) override {
+ NOTREACHED();
+ }
+
+ void OnUpdateFound(ServiceWorkerRegistration* registration) override {
+ ASSERT_FALSE(update_found_);
+ update_found_ = true;
+ }
+
+ // ServiceWorkerVersion::Listener overrides
+ void OnVersionStateChanged(ServiceWorkerVersion* version) override {
+ StateChangeLogEntry entry;
+ entry.version_id = version->version_id();
+ entry.status = version->status();
+ state_change_log_.push_back(entry);
+ }
+
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+
+ std::vector<AttributeChangeLogEntry> attribute_change_log_;
+ std::vector<StateChangeLogEntry> state_change_log_;
+ bool update_found_;
+};
+
+} // namespace
+
+TEST_F(ServiceWorkerJobTest, Update_NoChange) {
+ UpdateJobTestHelper* update_helper =
+ new UpdateJobTestHelper(render_process_id_);
+ helper_.reset(update_helper);
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ update_helper->SetupInitialRegistration(kNoChangeOrigin);
+ ASSERT_TRUE(registration.get());
+ ASSERT_EQ(4u, update_helper->state_change_log_.size());
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
+ update_helper->state_change_log_[0].status);
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
+ update_helper->state_change_log_[1].status);
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
+ update_helper->state_change_log_[2].status);
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
+ update_helper->state_change_log_[3].status);
+ update_helper->state_change_log_.clear();
+
+ // Run the update job.
+ registration->AddListener(update_helper);
+ scoped_refptr<ServiceWorkerVersion> first_version =
+ registration->active_version();
+ first_version->StartUpdate();
+ base::RunLoop().RunUntilIdle();
+
+ // Verify results.
+ ASSERT_TRUE(registration->active_version());
+ EXPECT_EQ(first_version.get(), registration->active_version());
+ EXPECT_FALSE(registration->installing_version());
+ EXPECT_FALSE(registration->waiting_version());
+ EXPECT_TRUE(update_helper->attribute_change_log_.empty());
+ ASSERT_EQ(1u, update_helper->state_change_log_.size());
+ EXPECT_NE(registration->active_version()->version_id(),
+ update_helper->state_change_log_[0].version_id);
+ EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
+ update_helper->state_change_log_[0].status);
+ EXPECT_FALSE(update_helper->update_found_);
+}
+
+TEST_F(ServiceWorkerJobTest, Update_NewVersion) {
+ UpdateJobTestHelper* update_helper =
+ new UpdateJobTestHelper(render_process_id_);
+ helper_.reset(update_helper);
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ update_helper->SetupInitialRegistration(kNewVersionOrigin);
+ ASSERT_TRUE(registration.get());
+ update_helper->state_change_log_.clear();
+
+ // Run the update job.
+ registration->AddListener(update_helper);
+ scoped_refptr<ServiceWorkerVersion> first_version =
+ registration->active_version();
+ first_version->StartUpdate();
+ base::RunLoop().RunUntilIdle();
+
+ // Verify results.
+ ASSERT_TRUE(registration->active_version());
+ EXPECT_NE(first_version.get(), registration->active_version());
+ EXPECT_FALSE(registration->installing_version());
+ EXPECT_FALSE(registration->waiting_version());
+ ASSERT_EQ(3u, update_helper->attribute_change_log_.size());
+
+ UpdateJobTestHelper::AttributeChangeLogEntry entry;
+ entry = update_helper->attribute_change_log_[0];
+ EXPECT_TRUE(entry.mask.installing_changed());
+ EXPECT_FALSE(entry.mask.waiting_changed());
+ EXPECT_FALSE(entry.mask.active_changed());
+ EXPECT_NE(entry.info.installing_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(entry.info.waiting_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.active_version.version_id,
+ kInvalidServiceWorkerVersionId);
+
+ entry = update_helper->attribute_change_log_[1];
+ EXPECT_TRUE(entry.mask.installing_changed());
+ EXPECT_TRUE(entry.mask.waiting_changed());
+ EXPECT_FALSE(entry.mask.active_changed());
+ EXPECT_EQ(entry.info.installing_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.waiting_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.active_version.version_id,
+ kInvalidServiceWorkerVersionId);
+
+ entry = update_helper->attribute_change_log_[2];
+ EXPECT_FALSE(entry.mask.installing_changed());
+ EXPECT_TRUE(entry.mask.waiting_changed());
+ EXPECT_TRUE(entry.mask.active_changed());
+ EXPECT_EQ(entry.info.installing_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(entry.info.waiting_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_NE(entry.info.active_version.version_id,
+ kInvalidServiceWorkerVersionId);
+
+ // expected version state transitions:
+ // new.installing, new.installed,
+ // old.redundant,
+ // new.activating, new.activated
+ ASSERT_EQ(5u, update_helper->state_change_log_.size());
+
+ EXPECT_EQ(registration->active_version()->version_id(),
+ update_helper->state_change_log_[0].version_id);
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLING,
+ update_helper->state_change_log_[0].status);
+
+ EXPECT_EQ(registration->active_version()->version_id(),
+ update_helper->state_change_log_[1].version_id);
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
+ update_helper->state_change_log_[1].status);
+
+ EXPECT_EQ(first_version->version_id(),
+ update_helper->state_change_log_[2].version_id);
+ EXPECT_EQ(ServiceWorkerVersion::REDUNDANT,
+ update_helper->state_change_log_[2].status);
+
+ EXPECT_EQ(registration->active_version()->version_id(),
+ update_helper->state_change_log_[3].version_id);
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING,
+ update_helper->state_change_log_[3].status);
+
+ EXPECT_EQ(registration->active_version()->version_id(),
+ update_helper->state_change_log_[4].version_id);
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
+ update_helper->state_change_log_[4].status);
+
+ EXPECT_TRUE(update_helper->update_found_);
+}
+
+TEST_F(ServiceWorkerJobTest, Update_NewestVersionChanged) {
+ bool called;
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ job_coordinator()->Register(
+ GURL("http://www.example.com/one/"),
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ ServiceWorkerVersion* active_version = registration->active_version();
+
+ // Queue an Update, it should abort when it starts and sees the new version.
+ job_coordinator()->Update(registration.get());
+
+ // Add a waiting version with new script.
+ scoped_refptr<ServiceWorkerVersion> version =
+ new ServiceWorkerVersion(registration.get(),
+ GURL("http://www.example.com/new_worker.js"),
+ 2L /* dummy version id */,
+ helper_->context()->AsWeakPtr());
+ registration->SetWaitingVersion(version.get());
+
+ base::RunLoop().RunUntilIdle();
+
+ // Verify the registration was not modified by the Update.
+ EXPECT_EQ(active_version, registration->active_version());
+ EXPECT_EQ(version.get(), registration->waiting_version());
+ EXPECT_EQ(NULL, registration->installing_version());
+}
+
+TEST_F(ServiceWorkerJobTest, Update_UninstallingRegistration) {
+ bool called;
+ scoped_refptr<ServiceWorkerRegistration> registration;
+ job_coordinator()->Register(
+ GURL("http://www.example.com/one/"),
+ GURL("http://www.example.com/service_worker.js"),
+ NULL,
+ SaveRegistration(SERVICE_WORKER_OK, &called, &registration));
+
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ // Add a controllee and queue an unregister to force the uninstalling state.
+ scoped_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(33 /* dummy render_process id */,
+ 1 /* dummy provider_id */,
+ helper_->context()->AsWeakPtr(),
+ NULL));
+ ServiceWorkerVersion* active_version = registration->active_version();
+ active_version->AddControllee(host.get());
+ job_coordinator()->Unregister(GURL("http://www.example.com/one/"),
+ SaveUnregistration(SERVICE_WORKER_OK, &called));
+
+ // Update should abort after it starts and sees uninstalling.
+ job_coordinator()->Update(registration.get());
+
+ EXPECT_FALSE(called);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+
+ // Verify the registration was not modified by the Update.
+ EXPECT_TRUE(registration->is_uninstalling());
+ EXPECT_EQ(active_version, registration->active_version());
+ EXPECT_EQ(NULL, registration->waiting_version());
+ EXPECT_EQ(NULL, registration->installing_version());
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
new file mode 100644
index 00000000000..6e3ddf1d7aa
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -0,0 +1,58 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_metrics.h"
+
+#include "base/metrics/histogram.h"
+#include "base/metrics/user_metrics_action.h"
+#include "content/public/browser/user_metrics.h"
+
+namespace content {
+
+// static
+void ServiceWorkerMetrics::CountInitDiskCacheResult(bool result) {
+ UMA_HISTOGRAM_BOOLEAN("ServiceWorker.DiskCache.InitResult", result);
+}
+
+// static
+void ServiceWorkerMetrics::CountReadResponseResult(
+ ServiceWorkerMetrics::ReadResponseResult result) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCache.ReadResponseResult",
+ result, NUM_READ_RESPONSE_RESULT_TYPES);
+}
+
+// static
+void ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WriteResponseResult result) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.DiskCache.WriteResponseResult",
+ result, NUM_WRITE_RESPONSE_RESULT_TYPES);
+}
+
+// static
+void ServiceWorkerMetrics::CountOpenDatabaseResult(
+ ServiceWorkerDatabase::Status status) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.OpenResult",
+ status, ServiceWorkerDatabase::STATUS_ERROR_MAX);
+}
+
+// static
+void ServiceWorkerMetrics::CountReadDatabaseResult(
+ ServiceWorkerDatabase::Status status) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.ReadResult",
+ status, ServiceWorkerDatabase::STATUS_ERROR_MAX);
+}
+
+// static
+void ServiceWorkerMetrics::CountWriteDatabaseResult(
+ ServiceWorkerDatabase::Status status) {
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.Database.WriteResult",
+ status, ServiceWorkerDatabase::STATUS_ERROR_MAX);
+}
+
+// static
+void ServiceWorkerMetrics::CountControlledPageLoad() {
+ RecordAction(base::UserMetricsAction("ServiceWorker.ControlledPageLoad"));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
new file mode 100644
index 00000000000..deea3b3f1c4
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_METRICS_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_METRICS_H_
+
+#include "base/macros.h"
+#include "content/browser/service_worker/service_worker_database.h"
+
+namespace content {
+
+class ServiceWorkerMetrics {
+ public:
+ enum ReadResponseResult {
+ READ_OK,
+ READ_HEADERS_ERROR,
+ READ_DATA_ERROR,
+ NUM_READ_RESPONSE_RESULT_TYPES,
+ };
+
+ enum WriteResponseResult {
+ WRITE_OK,
+ WRITE_HEADERS_ERROR,
+ WRITE_DATA_ERROR,
+ NUM_WRITE_RESPONSE_RESULT_TYPES,
+ };
+
+ // Used for ServiceWorkerDiskCache.
+ static void CountInitDiskCacheResult(bool result);
+ static void CountReadResponseResult(ReadResponseResult result);
+ static void CountWriteResponseResult(WriteResponseResult result);
+
+ // Used for ServiceWorkerDatabase.
+ static void CountOpenDatabaseResult(ServiceWorkerDatabase::Status status);
+ static void CountReadDatabaseResult(ServiceWorkerDatabase::Status status);
+ static void CountWriteDatabaseResult(ServiceWorkerDatabase::Status status);
+
+ // Counts the number of page loads controlled by a Service Worker.
+ static void CountControlledPageLoad();
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerMetrics);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_METRICS_H_
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.cc b/chromium/content/browser/service_worker/service_worker_process_manager.cc
index 7395e7b7b77..fe7e5e34f7d 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.cc
@@ -12,6 +12,18 @@
namespace content {
+namespace {
+
+// Functor to sort by the .second element of a struct.
+struct SecondGreater {
+ template <typename Value>
+ bool operator()(const Value& lhs, const Value& rhs) {
+ return lhs.second > rhs.second;
+ }
+};
+
+} // namespace
+
static bool IncrementWorkerRefCountByPid(int process_id) {
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
if (!rph || rph->FastShutdownStarted())
@@ -50,6 +62,7 @@ ServiceWorkerProcessManager::~ServiceWorkerProcessManager() {
}
void ServiceWorkerProcessManager::Shutdown() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
browser_context_ = NULL;
for (std::map<int, ProcessInfo>::const_iterator it = instance_info_.begin();
it != instance_info_.end();
@@ -61,9 +74,66 @@ void ServiceWorkerProcessManager::Shutdown() {
instance_info_.clear();
}
+void ServiceWorkerProcessManager::AddProcessReferenceToPattern(
+ const GURL& pattern, int process_id) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&ServiceWorkerProcessManager::AddProcessReferenceToPattern,
+ weak_this_,
+ pattern,
+ process_id));
+ return;
+ }
+
+ ProcessRefMap& process_refs = pattern_processes_[pattern];
+ ++process_refs[process_id];
+}
+
+void ServiceWorkerProcessManager::RemoveProcessReferenceFromPattern(
+ const GURL& pattern, int process_id) {
+ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &ServiceWorkerProcessManager::RemoveProcessReferenceFromPattern,
+ weak_this_,
+ pattern,
+ process_id));
+ return;
+ }
+
+ PatternProcessRefMap::iterator it = pattern_processes_.find(pattern);
+ if (it == pattern_processes_.end()) {
+ NOTREACHED() << "process refrences not found for pattern: " << pattern;
+ return;
+ }
+ ProcessRefMap& process_refs = it->second;
+ ProcessRefMap::iterator found = process_refs.find(process_id);
+ if (found == process_refs.end()) {
+ NOTREACHED() << "Releasing unknown process ref " << process_id;
+ return;
+ }
+ if (--found->second == 0) {
+ process_refs.erase(found);
+ if (process_refs.empty())
+ pattern_processes_.erase(it);
+ }
+}
+
+bool ServiceWorkerProcessManager::PatternHasProcessToRun(
+ const GURL& pattern) const {
+ PatternProcessRefMap::const_iterator it = pattern_processes_.find(pattern);
+ if (it == pattern_processes_.end())
+ return false;
+ return !it->second.empty();
+}
+
void ServiceWorkerProcessManager::AllocateWorkerProcess(
int embedded_worker_id,
- const std::vector<int>& process_ids,
+ const GURL& pattern,
const GURL& script_url,
const base::Callback<void(ServiceWorkerStatusCode, int process_id)>&
callback) {
@@ -74,7 +144,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess,
weak_this_,
embedded_worker_id,
- process_ids,
+ pattern,
script_url,
callback));
return;
@@ -93,17 +163,18 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
DCHECK(!ContainsKey(instance_info_, embedded_worker_id))
<< embedded_worker_id << " already has a process allocated";
- for (std::vector<int>::const_iterator it = process_ids.begin();
- it != process_ids.end();
+ std::vector<int> sorted_candidates = SortProcessesForPattern(pattern);
+ for (std::vector<int>::const_iterator it = sorted_candidates.begin();
+ it != sorted_candidates.end();
++it) {
- if (IncrementWorkerRefCountByPid(*it)) {
- instance_info_.insert(
- std::make_pair(embedded_worker_id, ProcessInfo(*it)));
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(callback, SERVICE_WORKER_OK, *it));
- return;
- }
+ if (!IncrementWorkerRefCountByPid(*it))
+ continue;
+ instance_info_.insert(
+ std::make_pair(embedded_worker_id, ProcessInfo(*it)));
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(callback, SERVICE_WORKER_OK, *it));
+ return;
}
if (!browser_context_) {
@@ -164,7 +235,7 @@ void ServiceWorkerProcessManager::ReleaseWorkerProcess(int embedded_worker_id) {
instance_info_.find(embedded_worker_id);
DCHECK(info != instance_info_.end());
RenderProcessHost* rph = NULL;
- if (info->second.site_instance) {
+ if (info->second.site_instance.get()) {
rph = info->second.site_instance->GetProcess();
DCHECK_EQ(info->second.process_id, rph->GetID())
<< "A SiteInstance's process shouldn't get destroyed while we're "
@@ -179,6 +250,22 @@ void ServiceWorkerProcessManager::ReleaseWorkerProcess(int embedded_worker_id) {
instance_info_.erase(info);
}
+std::vector<int> ServiceWorkerProcessManager::SortProcessesForPattern(
+ const GURL& pattern) const {
+ PatternProcessRefMap::const_iterator it = pattern_processes_.find(pattern);
+ if (it == pattern_processes_.end())
+ return std::vector<int>();
+
+ std::vector<std::pair<int, int> > counted(
+ it->second.begin(), it->second.end());
+ std::sort(counted.begin(), counted.end(), SecondGreater());
+
+ std::vector<int> result(counted.size());
+ for (size_t i = 0; i < counted.size(); ++i)
+ result[i] = counted[i].first;
+ return result;
+}
+
} // namespace content
namespace base {
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.h b/chromium/content/browser/service_worker/service_worker_process_manager.h
index 85fbcc1c050..2a3bae1db3b 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.h
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/service_worker/service_worker_status_code.h"
@@ -21,9 +22,9 @@ class BrowserContext;
class SiteInstance;
// Interacts with the UI thread to keep RenderProcessHosts alive while the
-// ServiceWorker system is using them. Each instance of
-// ServiceWorkerProcessManager is destroyed on the UI thread shortly after its
-// ServiceWorkerContextWrapper is destroyed.
+// ServiceWorker system is using them. It also tracks candidate processes
+// for each pattern. Each instance of ServiceWorkerProcessManager is destroyed
+// on the UI thread shortly after its ServiceWorkerContextWrapper is destroyed.
class CONTENT_EXPORT ServiceWorkerProcessManager {
public:
// |*this| must be owned by a ServiceWorkerContextWrapper in a
@@ -33,21 +34,19 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
// Shutdown must be called before the ProcessManager is destroyed.
~ServiceWorkerProcessManager();
- // Synchronously prevents new processes from being allocated.
- // TODO(jyasskin): Drop references to RenderProcessHosts too.
+ // Synchronously prevents new processes from being allocated
+ // and drops references to RenderProcessHosts.
void Shutdown();
// Returns a reference to a running process suitable for starting the Service
- // Worker at |script_url|. Processes in |process_ids| will be checked in order
- // for existence, and if none exist, then a new process will be created. Posts
- // |callback| to the IO thread to indicate whether creation succeeded and the
- // process ID that has a new reference.
+ // Worker at |script_url|. Posts |callback| to the IO thread to indicate
+ // whether creation succeeded and the process ID that has a new reference.
//
// Allocation can fail with SERVICE_WORKER_ERROR_START_WORKER_FAILED if
// RenderProcessHost::Init fails.
void AllocateWorkerProcess(
int embedded_worker_id,
- const std::vector<int>& process_ids,
+ const GURL& pattern,
const GURL& script_url,
const base::Callback<void(ServiceWorkerStatusCode, int process_id)>&
callback);
@@ -65,7 +64,17 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
process_id_for_test_ = process_id;
}
+ // Adds/removes process reference for the |pattern|, the process with highest
+ // references count will be chosen to start a worker.
+ void AddProcessReferenceToPattern(const GURL& pattern, int process_id);
+ void RemoveProcessReferenceFromPattern(const GURL& pattern, int process_id);
+
+ // Returns true if the |pattern| has at least one process to run.
+ bool PatternHasProcessToRun(const GURL& pattern) const;
+
private:
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, SortProcess);
+
// Information about the process for an EmbeddedWorkerInstance.
struct ProcessInfo {
explicit ProcessInfo(const scoped_refptr<SiteInstance>& site_instance);
@@ -84,6 +93,15 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
int process_id;
};
+ // Maps the process ID to its reference count.
+ typedef std::map<int, int> ProcessRefMap;
+
+ // Maps registration scope pattern to ProcessRefMap.
+ typedef std::map<const GURL, ProcessRefMap> PatternProcessRefMap;
+
+ // Returns a process vector sorted by the reference count for the |pattern|.
+ std::vector<int> SortProcessesForPattern(const GURL& pattern) const;
+
// These fields are only accessed on the UI thread.
BrowserContext* browser_context_;
@@ -100,6 +118,10 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
// EmbeddedWorkerInstances.
int process_id_for_test_;
+ // Candidate processes info for each pattern, should be accessed on the
+ // UI thread.
+ PatternProcessRefMap pattern_processes_;
+
// Used to double-check that we don't access *this after it's destroyed.
base::WeakPtrFactory<ServiceWorkerProcessManager> weak_this_factory_;
const base::WeakPtr<ServiceWorkerProcessManager> weak_this_;
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
new file mode 100644
index 00000000000..3b53740aad4
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2014 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/basictypes.h"
+#include "content/browser/service_worker/service_worker_process_manager.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class ServiceWorkerProcessManagerTest : public testing::Test {
+ public:
+ ServiceWorkerProcessManagerTest() {}
+
+ void SetUp() override {
+ process_manager_.reset(new ServiceWorkerProcessManager(NULL));
+ pattern_ = GURL("http://www.example.com/");
+ }
+
+ void TearDown() override { process_manager_.reset(); }
+
+ protected:
+ scoped_ptr<ServiceWorkerProcessManager> process_manager_;
+ GURL pattern_;
+
+ private:
+ content::TestBrowserThreadBundle thread_bundle_;
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProcessManagerTest);
+};
+
+TEST_F(ServiceWorkerProcessManagerTest, SortProcess) {
+ // Process 1 has 2 ref, 2 has 3 refs and 3 has 1 refs.
+ process_manager_->AddProcessReferenceToPattern(pattern_, 1);
+ process_manager_->AddProcessReferenceToPattern(pattern_, 1);
+ process_manager_->AddProcessReferenceToPattern(pattern_, 2);
+ process_manager_->AddProcessReferenceToPattern(pattern_, 2);
+ process_manager_->AddProcessReferenceToPattern(pattern_, 2);
+ process_manager_->AddProcessReferenceToPattern(pattern_, 3);
+
+ // Process 2 has the biggest # of references and it should be chosen.
+ EXPECT_THAT(process_manager_->SortProcessesForPattern(pattern_),
+ testing::ElementsAre(2, 1, 3));
+
+ process_manager_->RemoveProcessReferenceFromPattern(pattern_, 1);
+ process_manager_->RemoveProcessReferenceFromPattern(pattern_, 1);
+ // Scores for each process: 2 : 3, 3 : 1, process 1 is removed.
+ EXPECT_THAT(process_manager_->SortProcessesForPattern(pattern_),
+ testing::ElementsAre(2, 3));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_proto.gyp b/chromium/content/browser/service_worker/service_worker_proto.gyp
index b2588fff6a5..aab5e63bb7f 100644
--- a/chromium/content/browser/service_worker/service_worker_proto.gyp
+++ b/chromium/content/browser/service_worker/service_worker_proto.gyp
@@ -1,10 +1,11 @@
{
'targets': [
{
- # GN version: //content/browser/service_worker:database_proto
- 'target_name': 'database_proto',
+ # GN version: //content/browser/service_worker:proto
+ 'target_name': 'proto',
'type': 'static_library',
'sources': [
+ 'service_worker_cache.proto',
'service_worker_database.proto',
],
'variables': {
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.cc b/chromium/content/browser/service_worker/service_worker_provider_host.cc
index eeba3736d03..e16454558e0 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -11,9 +11,12 @@
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_types.h"
namespace content {
@@ -26,14 +29,30 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost(
: process_id_(process_id),
provider_id_(provider_id),
context_(context),
- dispatcher_host_(dispatcher_host) {
+ dispatcher_host_(dispatcher_host),
+ allow_association_(true) {
}
ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
- if (active_version_)
- active_version_->RemoveControllee(this);
- if (waiting_version_)
- waiting_version_->RemoveWaitingControllee(this);
+ // Clear docurl so the deferred activation of a waiting worker
+ // won't associate the new version with a provider being destroyed.
+ document_url_ = GURL();
+ if (controlling_version_.get())
+ controlling_version_->RemoveControllee(this);
+ if (associated_registration_.get()) {
+ DecreaseProcessReference(associated_registration_->pattern());
+ associated_registration_->RemoveListener(this);
+ }
+ for (std::vector<GURL>::iterator it = associated_patterns_.begin();
+ it != associated_patterns_.end(); ++it) {
+ DecreaseProcessReference(*it);
+ }
+}
+
+void ServiceWorkerProviderHost::OnRegistrationFailed(
+ ServiceWorkerRegistration* registration) {
+ DCHECK_EQ(associated_registration_.get(), registration);
+ DisassociateRegistration();
}
void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
@@ -41,47 +60,33 @@ void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
document_url_ = url;
}
-void ServiceWorkerProviderHost::SetActiveVersion(
- ServiceWorkerVersion* version) {
- if (version == active_version_)
- return;
- scoped_refptr<ServiceWorkerVersion> previous_version = active_version_;
- active_version_ = version;
- if (version)
- version->AddControllee(this);
- if (previous_version)
- previous_version->RemoveControllee(this);
-
- if (!dispatcher_host_)
- return; // Could be NULL in some tests.
-
- dispatcher_host_->Send(new ServiceWorkerMsg_SetCurrentServiceWorker(
- kDocumentMainThreadId, provider_id(), CreateHandleAndPass(version)));
+void ServiceWorkerProviderHost::SetTopmostFrameUrl(const GURL& url) {
+ topmost_frame_url_ = url;
}
-void ServiceWorkerProviderHost::SetWaitingVersion(
+void ServiceWorkerProviderHost::SetControllerVersionAttribute(
ServiceWorkerVersion* version) {
- DCHECK(ValidateVersionForAssociation(version));
- if (version == waiting_version_)
+ if (version == controlling_version_.get())
return;
- scoped_refptr<ServiceWorkerVersion> previous_version = waiting_version_;
- waiting_version_ = version;
+
+ scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_;
+ controlling_version_ = version;
if (version)
- version->AddWaitingControllee(this);
- if (previous_version)
- previous_version->RemoveWaitingControllee(this);
+ version->AddControllee(this);
+ if (previous_version.get())
+ previous_version->RemoveControllee(this);
if (!dispatcher_host_)
return; // Could be NULL in some tests.
- dispatcher_host_->Send(new ServiceWorkerMsg_SetWaitingServiceWorker(
+ dispatcher_host_->Send(new ServiceWorkerMsg_SetControllerServiceWorker(
kDocumentMainThreadId, provider_id(), CreateHandleAndPass(version)));
}
bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) {
if (!context_)
return true; // System is shutting down.
- if (active_version_)
+ if (active_version())
return false; // Unexpected bad message.
ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id);
@@ -100,43 +105,87 @@ bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) {
return true;
}
+void ServiceWorkerProviderHost::AssociateRegistration(
+ ServiceWorkerRegistration* registration) {
+ DCHECK(CanAssociateRegistration(registration));
+ if (associated_registration_.get())
+ DecreaseProcessReference(associated_registration_->pattern());
+ IncreaseProcessReference(registration->pattern());
+
+ if (dispatcher_host_) {
+ ServiceWorkerRegistrationHandle* handle =
+ dispatcher_host_->GetOrCreateRegistrationHandle(
+ provider_id(), registration);
+
+ ServiceWorkerVersionAttributes attrs;
+ attrs.installing = handle->CreateServiceWorkerHandleAndPass(
+ registration->installing_version());
+ attrs.waiting = handle->CreateServiceWorkerHandleAndPass(
+ registration->waiting_version());
+ attrs.active = handle->CreateServiceWorkerHandleAndPass(
+ registration->active_version());
+
+ dispatcher_host_->Send(new ServiceWorkerMsg_AssociateRegistration(
+ kDocumentMainThreadId, provider_id(), handle->GetObjectInfo(), attrs));
+ }
+
+ associated_registration_ = registration;
+ associated_registration_->AddListener(this);
+ SetControllerVersionAttribute(registration->active_version());
+}
+
+void ServiceWorkerProviderHost::DisassociateRegistration() {
+ if (!associated_registration_.get())
+ return;
+ DecreaseProcessReference(associated_registration_->pattern());
+ associated_registration_->RemoveListener(this);
+ associated_registration_ = NULL;
+ SetControllerVersionAttribute(NULL);
+
+ if (dispatcher_host_) {
+ dispatcher_host_->Send(new ServiceWorkerMsg_DisassociateRegistration(
+ kDocumentMainThreadId, provider_id()));
+ }
+}
+
scoped_ptr<ServiceWorkerRequestHandler>
ServiceWorkerProviderHost::CreateRequestHandler(
- ResourceType::Type resource_type,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context) {
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ ResourceType resource_type,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ scoped_refptr<ResourceRequestBody> body) {
if (IsHostToRunningServiceWorker()) {
return scoped_ptr<ServiceWorkerRequestHandler>(
new ServiceWorkerContextRequestHandler(
context_, AsWeakPtr(), blob_storage_context, resource_type));
}
if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
- active_version()) {
+ controlling_version()) {
return scoped_ptr<ServiceWorkerRequestHandler>(
- new ServiceWorkerControlleeRequestHandler(
- context_, AsWeakPtr(), blob_storage_context, resource_type));
+ new ServiceWorkerControlleeRequestHandler(context_,
+ AsWeakPtr(),
+ blob_storage_context,
+ request_mode,
+ credentials_mode,
+ resource_type,
+ request_context_type,
+ frame_type,
+ body));
}
return scoped_ptr<ServiceWorkerRequestHandler>();
}
-bool ServiceWorkerProviderHost::ValidateVersionForAssociation(
- ServiceWorkerVersion* version) {
- if (running_hosted_version_)
+bool ServiceWorkerProviderHost::CanAssociateRegistration(
+ ServiceWorkerRegistration* registration) {
+ if (!context_)
+ return false;
+ if (running_hosted_version_.get())
+ return false;
+ if (!registration || associated_registration_.get() || !allow_association_)
return false;
- if (!version)
- return true;
-
- // A version to be associated with this provider should have the same
- // registration (scope) as current active/waiting versions.
- if (active_version_) {
- if (active_version_->registration_id() != version->registration_id())
- return false;
- DCHECK_EQ(active_version_->scope(), version->scope());
- }
- if (waiting_version_) {
- if (waiting_version_->registration_id() != version->registration_id())
- return false;
- DCHECK_EQ(waiting_version_->scope(), version->scope());
- }
return true;
}
@@ -159,20 +208,44 @@ void ServiceWorkerProviderHost::PostMessage(
new_routing_ids));
}
+void ServiceWorkerProviderHost::AddScopedProcessReferenceToPattern(
+ const GURL& pattern) {
+ associated_patterns_.push_back(pattern);
+ IncreaseProcessReference(pattern);
+}
+
ServiceWorkerObjectInfo ServiceWorkerProviderHost::CreateHandleAndPass(
ServiceWorkerVersion* version) {
- DCHECK(ValidateVersionForAssociation(version));
ServiceWorkerObjectInfo info;
if (context_ && version) {
scoped_ptr<ServiceWorkerHandle> handle =
- ServiceWorkerHandle::Create(context_, dispatcher_host_,
- kDocumentMainThreadId, version);
+ ServiceWorkerHandle::Create(context_,
+ dispatcher_host_,
+ kDocumentMainThreadId,
+ provider_id_,
+ version);
info = handle->GetObjectInfo();
dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
}
return info;
}
+void ServiceWorkerProviderHost::IncreaseProcessReference(
+ const GURL& pattern) {
+ if (context_ && context_->process_manager()) {
+ context_->process_manager()->AddProcessReferenceToPattern(
+ pattern, process_id_);
+ }
+}
+
+void ServiceWorkerProviderHost::DecreaseProcessReference(
+ const GURL& pattern) {
+ if (context_ && context_->process_manager()) {
+ context_->process_manager()->RemoveProcessReferenceFromPattern(
+ pattern, process_id_);
+ }
+}
+
bool ServiceWorkerProviderHost::IsContextAlive() {
return context_ != NULL;
}
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.h b/chromium/content/browser/service_worker/service_worker_provider_host.h
index 31f4a372b1b..04fb21d0a2b 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -10,20 +10,24 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "webkit/common/resource_type.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
namespace IPC {
class Sender;
}
-namespace webkit_blob {
+namespace storage {
class BlobStorageContext;
}
namespace content {
+class ResourceRequestBody;
class ServiceWorkerContextCore;
class ServiceWorkerDispatcherHost;
class ServiceWorkerRequestHandler;
@@ -38,31 +42,40 @@ class ServiceWorkerVersion;
// Note this class can also host a running service worker, in which
// case it will observe resource loads made directly by the service worker.
class CONTENT_EXPORT ServiceWorkerProviderHost
- : public base::SupportsWeakPtr<ServiceWorkerProviderHost> {
+ : public NON_EXPORTED_BASE(ServiceWorkerRegistration::Listener),
+ public base::SupportsWeakPtr<ServiceWorkerProviderHost> {
public:
ServiceWorkerProviderHost(int process_id,
int provider_id,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerDispatcherHost* dispatcher_host);
- ~ServiceWorkerProviderHost();
+ virtual ~ServiceWorkerProviderHost();
int process_id() const { return process_id_; }
int provider_id() const { return provider_id_; }
bool IsHostToRunningServiceWorker() {
- return running_hosted_version_ != NULL;
+ return running_hosted_version_.get() != NULL;
}
- // The service worker version that corresponds with
- // navigator.serviceWorker.active for our document.
+ ServiceWorkerVersion* controlling_version() const {
+ return controlling_version_.get();
+ }
ServiceWorkerVersion* active_version() const {
- return active_version_.get();
+ return associated_registration_.get() ?
+ associated_registration_->active_version() : NULL;
}
-
- // The service worker version that corresponds with
- // navigate.serviceWorker.waiting for our document.
ServiceWorkerVersion* waiting_version() const {
- return waiting_version_.get();
+ return associated_registration_.get() ?
+ associated_registration_->waiting_version() : NULL;
+ }
+ ServiceWorkerVersion* installing_version() const {
+ return associated_registration_.get() ?
+ associated_registration_->installing_version() : NULL;
+ }
+
+ ServiceWorkerRegistration* associated_registration() const {
+ return associated_registration_.get();
}
// The running version, if any, that this provider is providing resource
@@ -74,11 +87,14 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void SetDocumentUrl(const GURL& url);
const GURL& document_url() const { return document_url_; }
- // Associates |version| to this provider as its '.active' or '.waiting'
- // version.
- // Giving NULL to this method will unset the corresponding field.
- void SetActiveVersion(ServiceWorkerVersion* version);
- void SetWaitingVersion(ServiceWorkerVersion* version);
+ void SetTopmostFrameUrl(const GURL& url);
+ const GURL& topmost_frame_url() const { return topmost_frame_url_; }
+
+ // Associates to |registration| to listen for its version change events.
+ void AssociateRegistration(ServiceWorkerRegistration* registration);
+
+ // Clears the associated registration and stop listening to it.
+ void DisassociateRegistration();
// Returns false if the version is not in the expected STARTING in our
// process state. That would be indicative of a bad IPC message.
@@ -87,12 +103,21 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Returns a handler for a request, the handler may return NULL if
// the request doesn't require special handling.
scoped_ptr<ServiceWorkerRequestHandler> CreateRequestHandler(
- ResourceType::Type resource_type,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context);
-
- // Returns true if |version| has the same registration as active and waiting
- // versions.
- bool ValidateVersionForAssociation(ServiceWorkerVersion* version);
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ ResourceType resource_type,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ scoped_refptr<ResourceRequestBody> body);
+
+ // Returns true if |registration| can be associated with this provider.
+ bool CanAssociateRegistration(ServiceWorkerRegistration* registration);
+
+ // For use by the ServiceWorkerControlleeRequestHandler to disallow
+ // new registration association while a navigation is occurring and
+ // an existing registration is being looked for.
+ void SetAllowAssociation(bool allow) { allow_association_ = allow; }
// Returns true if the context referred to by this host (i.e. |context_|) is
// still alive.
@@ -102,20 +127,47 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void PostMessage(const base::string16& message,
const std::vector<int>& sent_message_port_ids);
+ // Adds reference of this host's process to the |pattern|, the reference will
+ // be removed in destructor.
+ void AddScopedProcessReferenceToPattern(const GURL& pattern);
+
private:
+ friend class ServiceWorkerProviderHostTest;
+ friend class ServiceWorkerWriteToCacheJobTest;
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ UpdateBefore24Hours);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ UpdateAfter24Hours);
+
+ // ServiceWorkerRegistration::Listener overrides.
+ void OnRegistrationFailed(ServiceWorkerRegistration* registration) override;
+
+ // Sets the controller version field to |version| or if |version| is NULL,
+ // clears the field.
+ void SetControllerVersionAttribute(ServiceWorkerVersion* version);
+
// Creates a ServiceWorkerHandle to retain |version| and returns a
// ServiceWorkerInfo with the handle ID to pass to the provider. The
// provider is responsible for releasing the handle.
ServiceWorkerObjectInfo CreateHandleAndPass(ServiceWorkerVersion* version);
+ // Increase/decrease this host's process reference for |pattern|.
+ void IncreaseProcessReference(const GURL& pattern);
+ void DecreaseProcessReference(const GURL& pattern);
+
const int process_id_;
const int provider_id_;
GURL document_url_;
- scoped_refptr<ServiceWorkerVersion> active_version_;
- scoped_refptr<ServiceWorkerVersion> waiting_version_;
+ GURL topmost_frame_url_;
+
+ std::vector<GURL> associated_patterns_;
+ scoped_refptr<ServiceWorkerRegistration> associated_registration_;
+
+ scoped_refptr<ServiceWorkerVersion> controlling_version_;
scoped_refptr<ServiceWorkerVersion> running_hosted_version_;
base::WeakPtr<ServiceWorkerContextCore> context_;
ServiceWorkerDispatcherHost* dispatcher_host_;
+ bool allow_association_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHost);
};
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
index 1f52514a603..fac7cb734ab 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -4,6 +4,8 @@
#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_register_job.h"
@@ -20,24 +22,17 @@ class ServiceWorkerProviderHostTest : public testing::Test {
protected:
ServiceWorkerProviderHostTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
- virtual ~ServiceWorkerProviderHostTest() {}
+ ~ServiceWorkerProviderHostTest() override {}
- virtual void SetUp() OVERRIDE {
- context_.reset(
- new ServiceWorkerContextCore(base::FilePath(),
- base::MessageLoopProxy::current(),
- base::MessageLoopProxy::current(),
- NULL,
- NULL,
- NULL));
-
- scope_ = GURL("http://www.example.com/*");
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
+ context_ = helper_->context();
+ pattern_ = GURL("http://www.example.com/");
script_url_ = GURL("http://www.example.com/service_worker.js");
registration_ = new ServiceWorkerRegistration(
- scope_, script_url_, 1L, context_->AsWeakPtr());
+ pattern_, 1L, context_->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_,
- 1L, context_->AsWeakPtr());
+ registration_.get(), script_url_, 1L, context_->AsWeakPtr());
// Prepare provider hosts (for the same process).
scoped_ptr<ServiceWorkerProviderHost> host1(new ServiceWorkerProviderHost(
@@ -46,31 +41,30 @@ class ServiceWorkerProviderHostTest : public testing::Test {
scoped_ptr<ServiceWorkerProviderHost> host2(new ServiceWorkerProviderHost(
kRenderProcessId, 2 /* provider_id */,
context_->AsWeakPtr(), NULL));
- scoped_ptr<ServiceWorkerProviderHost> host3(new ServiceWorkerProviderHost(
- kRenderProcessId, 3 /* provider_id */,
- context_->AsWeakPtr(), NULL));
provider_host1_ = host1->AsWeakPtr();
provider_host2_ = host2->AsWeakPtr();
- provider_host3_ = host3->AsWeakPtr();
context_->AddProviderHost(make_scoped_ptr(host1.release()));
context_->AddProviderHost(make_scoped_ptr(host2.release()));
- context_->AddProviderHost(make_scoped_ptr(host3.release()));
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
version_ = 0;
registration_ = 0;
- context_.reset();
+ helper_.reset();
+ }
+
+ bool HasProcessToRun() const {
+ return context_->process_manager()->PatternHasProcessToRun(pattern_);
}
content::TestBrowserThreadBundle thread_bundle_;
- scoped_ptr<ServiceWorkerContextCore> context_;
+ scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ ServiceWorkerContextCore* context_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host1_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host2_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host3_;
- GURL scope_;
+ GURL pattern_;
GURL script_url_;
private:
@@ -78,206 +72,81 @@ class ServiceWorkerProviderHostTest : public testing::Test {
};
TEST_F(ServiceWorkerProviderHostTest, SetActiveVersion_ProcessStatus) {
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host1_->AssociateRegistration(registration_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Associating version_ to a provider_host's active version will internally
// add the provider_host's process ref to the version.
- provider_host1_->SetActiveVersion(version_);
- ASSERT_TRUE(version_->HasProcessToRun());
+ registration_->SetActiveVersion(version_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Re-associating the same version and provider_host should just work too.
- provider_host1_->SetActiveVersion(version_);
- ASSERT_TRUE(version_->HasProcessToRun());
+ registration_->SetActiveVersion(version_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Resetting the provider_host's active version should remove process refs
// from the version.
- provider_host1_->SetActiveVersion(NULL);
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host1_->DisassociateRegistration();
+ ASSERT_FALSE(HasProcessToRun());
}
TEST_F(ServiceWorkerProviderHostTest,
SetActiveVersion_MultipleHostsForSameProcess) {
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host1_->AssociateRegistration(registration_.get());
+ provider_host2_->AssociateRegistration(registration_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Associating version_ to two providers as active version.
- provider_host1_->SetActiveVersion(version_);
- provider_host2_->SetActiveVersion(version_);
- ASSERT_TRUE(version_->HasProcessToRun());
+ registration_->SetActiveVersion(version_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Disassociating one provider_host shouldn't remove all process refs
// from the version yet.
- provider_host1_->SetActiveVersion(NULL);
- ASSERT_TRUE(version_->HasProcessToRun());
+ provider_host1_->DisassociateRegistration();
+ ASSERT_TRUE(HasProcessToRun());
// Disassociating the other provider_host will remove all process refs.
- provider_host2_->SetActiveVersion(NULL);
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host2_->DisassociateRegistration();
+ ASSERT_FALSE(HasProcessToRun());
}
TEST_F(ServiceWorkerProviderHostTest, SetWaitingVersion_ProcessStatus) {
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host1_->AssociateRegistration(registration_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Associating version_ to a provider_host's waiting version will internally
// add the provider_host's process ref to the version.
- provider_host1_->SetWaitingVersion(version_);
- ASSERT_TRUE(version_->HasProcessToRun());
+ registration_->SetWaitingVersion(version_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Re-associating the same version and provider_host should just work too.
- provider_host1_->SetWaitingVersion(version_);
- ASSERT_TRUE(version_->HasProcessToRun());
+ registration_->SetWaitingVersion(version_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Resetting the provider_host's waiting version should remove process refs
// from the version.
- provider_host1_->SetWaitingVersion(NULL);
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host1_->DisassociateRegistration();
+ ASSERT_FALSE(HasProcessToRun());
}
TEST_F(ServiceWorkerProviderHostTest,
SetWaitingVersion_MultipleHostsForSameProcess) {
- ASSERT_FALSE(version_->HasProcessToRun());
+ provider_host1_->AssociateRegistration(registration_.get());
+ provider_host2_->AssociateRegistration(registration_.get());
+ ASSERT_TRUE(HasProcessToRun());
- // Associating version_ to two providers as active version.
- provider_host1_->SetWaitingVersion(version_);
- provider_host2_->SetWaitingVersion(version_);
- ASSERT_TRUE(version_->HasProcessToRun());
+ // Associating version_ to two providers as waiting version.
+ registration_->SetWaitingVersion(version_.get());
+ ASSERT_TRUE(HasProcessToRun());
// Disassociating one provider_host shouldn't remove all process refs
// from the version yet.
- provider_host1_->SetWaitingVersion(NULL);
- ASSERT_TRUE(version_->HasProcessToRun());
+ provider_host1_->DisassociateRegistration();
+ ASSERT_TRUE(HasProcessToRun());
// Disassociating the other provider_host will remove all process refs.
- provider_host2_->SetWaitingVersion(NULL);
- ASSERT_FALSE(version_->HasProcessToRun());
-}
-
-class ServiceWorkerProviderHostWaitingVersionTest : public testing::Test {
- protected:
- ServiceWorkerProviderHostWaitingVersionTest()
- : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- next_provider_id_(1L) {}
- virtual ~ServiceWorkerProviderHostWaitingVersionTest() {}
-
- virtual void SetUp() OVERRIDE {
- context_.reset(
- new ServiceWorkerContextCore(base::FilePath(),
- base::MessageLoopProxy::current(),
- base::MessageLoopProxy::current(),
- NULL,
- NULL,
- NULL));
-
- // Prepare provider hosts (for the same process).
- provider_host1_ = CreateProviderHost(GURL("http://www.example.com/foo"));
- provider_host2_ = CreateProviderHost(GURL("http://www.example.com/bar"));
- provider_host3_ = CreateProviderHost(GURL("http://www.example.ca/foo"));
- }
-
- base::WeakPtr<ServiceWorkerProviderHost> CreateProviderHost(
- const GURL& document_url) {
- scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
- kRenderProcessId, next_provider_id_++, context_->AsWeakPtr(), NULL));
- host->SetDocumentUrl(document_url);
- base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
- context_->AddProviderHost(host.Pass());
- return provider_host;
- }
-
- virtual void TearDown() OVERRIDE {
- context_.reset();
- }
-
- content::TestBrowserThreadBundle thread_bundle_;
- scoped_ptr<ServiceWorkerContextCore> context_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host1_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host2_;
- base::WeakPtr<ServiceWorkerProviderHost> provider_host3_;
-
- private:
- int64 next_provider_id_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHostWaitingVersionTest);
-};
-
-TEST_F(ServiceWorkerProviderHostWaitingVersionTest,
- AssociateWaitingVersionToDocuments) {
- const GURL scope1("http://www.example.com/*");
- const GURL script_url1("http://www.example.com/service_worker1.js");
- scoped_refptr<ServiceWorkerRegistration> registration1(
- new ServiceWorkerRegistration(
- scope1, script_url1, 1L, context_->AsWeakPtr()));
- scoped_refptr<ServiceWorkerVersion> version1(
- new ServiceWorkerVersion(registration1, 1L, context_->AsWeakPtr()));
-
- ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
- context_->AsWeakPtr(), version1.get());
- EXPECT_EQ(version1.get(), provider_host1_->waiting_version());
- EXPECT_EQ(version1.get(), provider_host2_->waiting_version());
- EXPECT_EQ(NULL, provider_host3_->waiting_version());
-
- // Version2 is associated with the same registration as version1, so the
- // waiting version of host1 and host2 should be replaced.
- scoped_refptr<ServiceWorkerVersion> version2(
- new ServiceWorkerVersion(registration1, 2L, context_->AsWeakPtr()));
- ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
- context_->AsWeakPtr(), version2.get());
- EXPECT_EQ(version2.get(), provider_host1_->waiting_version());
- EXPECT_EQ(version2.get(), provider_host2_->waiting_version());
- EXPECT_EQ(NULL, provider_host3_->waiting_version());
-
- const GURL scope3(provider_host1_->document_url());
- const GURL script_url3("http://www.example.com/service_worker3.js");
- scoped_refptr<ServiceWorkerRegistration> registration3(
- new ServiceWorkerRegistration(
- scope3, script_url3, 3L, context_->AsWeakPtr()));
- scoped_refptr<ServiceWorkerVersion> version3(
- new ServiceWorkerVersion(registration3, 3L, context_->AsWeakPtr()));
-
- // Although version3 can match longer than version2 for host1, it should be
- // ignored because version3 is associated with a different registration from
- // version2.
- ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
- context_->AsWeakPtr(), version3.get());
- EXPECT_EQ(version2.get(), provider_host1_->waiting_version());
- EXPECT_EQ(version2.get(), provider_host2_->waiting_version());
- EXPECT_EQ(NULL, provider_host3_->waiting_version());
-}
-
-TEST_F(ServiceWorkerProviderHostWaitingVersionTest,
- DisassociateWaitingVersionFromDocuments) {
- const GURL scope1("http://www.example.com/*");
- const GURL script_url1("http://www.example.com/service_worker.js");
- scoped_refptr<ServiceWorkerRegistration> registration1(
- new ServiceWorkerRegistration(
- scope1, script_url1, 1L, context_->AsWeakPtr()));
- scoped_refptr<ServiceWorkerVersion> version1(
- new ServiceWorkerVersion(registration1, 1L, context_->AsWeakPtr()));
-
- const GURL scope2("http://www.example.ca/*");
- const GURL script_url2("http://www.example.ca/service_worker.js");
- scoped_refptr<ServiceWorkerRegistration> registration2(
- new ServiceWorkerRegistration(
- scope2, script_url2, 2L, context_->AsWeakPtr()));
- scoped_refptr<ServiceWorkerVersion> version2(
- new ServiceWorkerVersion(registration2, 2L, context_->AsWeakPtr()));
-
- ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
- context_->AsWeakPtr(), version1.get());
- ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
- context_->AsWeakPtr(), version2.get());
-
- // Host1 and host2 are associated with version1 as a waiting version, whereas
- // host3 is associated with version2.
- EXPECT_EQ(version1.get(), provider_host1_->waiting_version());
- EXPECT_EQ(version1.get(), provider_host2_->waiting_version());
- EXPECT_EQ(version2.get(), provider_host3_->waiting_version());
-
- // Disassociate version1 from host1 and host2.
- ServiceWorkerRegisterJob::DisassociateWaitingVersionFromDocuments(
- context_->AsWeakPtr(), version1->version_id());
- EXPECT_EQ(NULL, provider_host1_->waiting_version());
- EXPECT_EQ(NULL, provider_host2_->waiting_version());
- EXPECT_EQ(version2.get(), provider_host3_->waiting_version());
+ provider_host2_->DisassociateRegistration();
+ ASSERT_FALSE(HasProcessToRun());
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_quota_client.cc b/chromium/content/browser/service_worker/service_worker_quota_client.cc
new file mode 100644
index 00000000000..2a7842ff4d4
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_quota_client.cc
@@ -0,0 +1,111 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_quota_client.h"
+
+#include "base/bind.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/public/browser/browser_thread.h"
+
+using storage::QuotaClient;
+
+namespace content {
+namespace {
+void ReportOrigins(const QuotaClient::GetOriginsCallback& callback,
+ bool restrict_on_host,
+ const std::string host,
+ const std::vector<ServiceWorkerUsageInfo>& usage_info) {
+ std::set<GURL> origins;
+ for (const ServiceWorkerUsageInfo& info : usage_info) {
+ if (restrict_on_host && info.origin.host() != host) {
+ continue;
+ }
+ origins.insert(info.origin);
+ }
+ callback.Run(origins);
+}
+
+void ReportToQuotaStatus(const QuotaClient::DeletionCallback& callback,
+ bool status) {
+ callback.Run(status ? storage::QuotaStatusCode::kQuotaStatusOk
+ : storage::QuotaStatusCode::kQuotaStatusUnknown);
+}
+
+void FindUsageForOrigin(const QuotaClient::GetUsageCallback& callback,
+ const GURL& origin,
+ const std::vector<ServiceWorkerUsageInfo>& usage_info) {
+ for (const auto& info : usage_info) {
+ if (info.origin == origin) {
+ callback.Run(info.total_size_bytes);
+ return;
+ }
+ }
+ callback.Run(0);
+}
+} // namespace
+
+ServiceWorkerQuotaClient::ServiceWorkerQuotaClient(
+ ServiceWorkerContextWrapper* context)
+ : context_(context) {
+}
+
+ServiceWorkerQuotaClient::~ServiceWorkerQuotaClient() {
+}
+
+QuotaClient::ID ServiceWorkerQuotaClient::id() const {
+ return QuotaClient::kServiceWorker;
+}
+
+void ServiceWorkerQuotaClient::OnQuotaManagerDestroyed() {
+ delete this;
+}
+
+void ServiceWorkerQuotaClient::GetOriginUsage(
+ const GURL& origin,
+ storage::StorageType type,
+ const GetUsageCallback& callback) {
+ if (type != storage::StorageType::kStorageTypeTemporary) {
+ callback.Run(0);
+ return;
+ }
+ context_->GetAllOriginsInfo(
+ base::Bind(&FindUsageForOrigin, callback, origin));
+}
+
+void ServiceWorkerQuotaClient::GetOriginsForType(
+ storage::StorageType type,
+ const GetOriginsCallback& callback) {
+ if (type != storage::StorageType::kStorageTypeTemporary) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+ context_->GetAllOriginsInfo(base::Bind(&ReportOrigins, callback, false, ""));
+}
+
+void ServiceWorkerQuotaClient::GetOriginsForHost(
+ storage::StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) {
+ if (type != storage::StorageType::kStorageTypeTemporary) {
+ callback.Run(std::set<GURL>());
+ return;
+ }
+ context_->GetAllOriginsInfo(base::Bind(&ReportOrigins, callback, true, host));
+}
+
+void ServiceWorkerQuotaClient::DeleteOriginData(
+ const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) {
+ if (type != storage::StorageType::kStorageTypeTemporary) {
+ callback.Run(storage::QuotaStatusCode::kQuotaStatusOk);
+ return;
+ }
+ context_->DeleteForOrigin(origin, base::Bind(&ReportToQuotaStatus, callback));
+}
+
+bool ServiceWorkerQuotaClient::DoesSupport(storage::StorageType type) const {
+ return type == storage::StorageType::kStorageTypeTemporary;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_quota_client.h b/chromium/content/browser/service_worker/service_worker_quota_client.h
new file mode 100644
index 00000000000..a1cf91ddb80
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_quota_client.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_QUOTA_CLIENT_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_QUOTA_CLIENT_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "storage/browser/quota/quota_client.h"
+#include "storage/common/quota/quota_types.h"
+
+namespace content {
+class ServiceWorkerContextWrapper;
+
+class ServiceWorkerQuotaClient : public storage::QuotaClient {
+ public:
+ ~ServiceWorkerQuotaClient() override;
+
+ // QuotaClient method overrides
+ ID id() const override;
+ void OnQuotaManagerDestroyed() override;
+ void GetOriginUsage(const GURL& origin,
+ storage::StorageType type,
+ const GetUsageCallback& callback) override;
+ void GetOriginsForType(storage::StorageType type,
+ const GetOriginsCallback& callback) override;
+ void GetOriginsForHost(storage::StorageType type,
+ const std::string& host,
+ const GetOriginsCallback& callback) override;
+ void DeleteOriginData(const GURL& origin,
+ storage::StorageType type,
+ const DeletionCallback& callback) override;
+ bool DoesSupport(storage::StorageType type) const override;
+
+ private:
+ friend class ServiceWorkerContextWrapper;
+ friend class ServiceWorkerQuotaClientTest;
+
+ CONTENT_EXPORT explicit ServiceWorkerQuotaClient(
+ ServiceWorkerContextWrapper* context);
+
+ scoped_refptr<ServiceWorkerContextWrapper> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerQuotaClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_QUOTA_CLIENT_H_
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
index 5189a86c2bd..07f47e11016 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -4,9 +4,13 @@
#include "content/browser/service_worker/service_worker_read_from_cache_job.h"
+#include <string>
+#include <vector>
+
+#include "base/debug/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_histograms.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
@@ -33,6 +37,10 @@ ServiceWorkerReadFromCacheJob::~ServiceWorkerReadFromCacheJob() {
}
void ServiceWorkerReadFromCacheJob::Start() {
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerReadFromCacheJob::ReadInfo",
+ this,
+ "URL", request_->url().spec());
if (!context_) {
NotifyStartError(net::URLRequestStatus(
net::URLRequestStatus::FAILED, net::ERR_FAILED));
@@ -44,7 +52,7 @@ void ServiceWorkerReadFromCacheJob::Start() {
reader_ = context_->storage()->CreateResponseReader(response_id_);
http_info_io_buffer_ = new HttpResponseInfoIOBuffer;
reader_->ReadInfo(
- http_info_io_buffer_,
+ http_info_io_buffer_.get(),
base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete,
weak_factory_.GetWeakPtr()));
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
@@ -116,6 +124,10 @@ bool ServiceWorkerReadFromCacheJob::ReadRawData(
DCHECK_NE(buf_size, 0);
DCHECK(bytes_read);
DCHECK(!reader_->IsReadPending());
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerReadFromCacheJob::ReadRawData",
+ this,
+ "URL", request_->url().spec());
reader_->ReadData(
buf, buf_size, base::Bind(&ServiceWorkerReadFromCacheJob::OnReadComplete,
weak_factory_.GetWeakPtr()));
@@ -134,18 +146,22 @@ const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const {
void ServiceWorkerReadFromCacheJob::OnReadInfoComplete(int result) {
scoped_refptr<ServiceWorkerReadFromCacheJob> protect(this);
if (!http_info_io_buffer_->http_info) {
- DCHECK(result < 0);
- ServiceWorkerHistograms::CountReadResponseResult(
- ServiceWorkerHistograms::READ_HEADERS_ERROR);
+ DCHECK_LT(result, 0);
+ ServiceWorkerMetrics::CountReadResponseResult(
+ ServiceWorkerMetrics::READ_HEADERS_ERROR);
NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
return;
}
- DCHECK(result >= 0);
+ DCHECK_GE(result, 0);
SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
http_info_.reset(http_info_io_buffer_->http_info.release());
if (is_range_request())
SetupRangeResponse(http_info_io_buffer_->response_data_size);
http_info_io_buffer_ = NULL;
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "ServiceWorkerReadFromCacheJob::ReadInfo",
+ this,
+ "Result", result);
NotifyHeadersComplete();
}
@@ -173,19 +189,23 @@ void ServiceWorkerReadFromCacheJob::SetupRangeResponse(int resource_size) {
}
void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) {
- ServiceWorkerHistograms::ReadResponseResult check_result;
+ ServiceWorkerMetrics::ReadResponseResult check_result;
if (result == 0) {
- check_result = ServiceWorkerHistograms::READ_OK;
+ check_result = ServiceWorkerMetrics::READ_OK;
NotifyDone(net::URLRequestStatus());
} else if (result < 0) {
- check_result = ServiceWorkerHistograms::READ_DATA_ERROR;
+ check_result = ServiceWorkerMetrics::READ_DATA_ERROR;
NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
} else {
- check_result = ServiceWorkerHistograms::READ_OK;
+ check_result = ServiceWorkerMetrics::READ_OK;
SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
}
- ServiceWorkerHistograms::CountReadResponseResult(check_result);
+ ServiceWorkerMetrics::CountReadResponseResult(check_result);
NotifyReadComplete(result);
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "ServiceWorkerReadFromCacheJob::ReadRawData",
+ this,
+ "Result", result);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.h b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.h
index 5fb74015127..2a290d3c84d 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.h
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_READ_FROM_CACHE_JOB_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_READ_FROM_CACHE_JOB_H_
+#include <string>
+
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
@@ -30,21 +32,18 @@ class CONTENT_EXPORT ServiceWorkerReadFromCacheJob
int64 response_id);
private:
- virtual ~ServiceWorkerReadFromCacheJob();
+ ~ServiceWorkerReadFromCacheJob() override;
// net::URLRequestJob overrides
- virtual void Start() OVERRIDE;
- virtual void Kill() OVERRIDE;
- virtual net::LoadState GetLoadState() const OVERRIDE;
- virtual bool GetCharset(std::string* charset) OVERRIDE;
- virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
- virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE;
- virtual int GetResponseCode() const OVERRIDE;
- virtual void SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) OVERRIDE;
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int *bytes_read) OVERRIDE;
+ void Start() override;
+ void Kill() override;
+ net::LoadState GetLoadState() const override;
+ bool GetCharset(std::string* charset) override;
+ bool GetMimeType(std::string* mime_type) const override;
+ void GetResponseInfo(net::HttpResponseInfo* info) override;
+ int GetResponseCode() const override;
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
// Reader completion callbacks.
void OnReadInfoComplete(int result);
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.cc b/chromium/content/browser/service_worker/service_worker_register_job.cc
index 098b6b31df8..b68cd30f819 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -12,6 +12,7 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_utils.h"
+#include "net/base/net_errors.h"
namespace content {
@@ -21,7 +22,7 @@ void RunSoon(const base::Closure& closure) {
base::MessageLoop::current()->PostTask(FROM_HERE, closure);
}
-}
+} // namespace
typedef ServiceWorkerRegisterJobBase::RegistrationJobType RegistrationJobType;
@@ -30,6 +31,7 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
const GURL& pattern,
const GURL& script_url)
: context_(context),
+ job_type_(REGISTRATION_JOB),
pattern_(pattern),
script_url_(script_url),
phase_(INITIAL),
@@ -37,32 +39,58 @@ ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
promise_resolved_status_(SERVICE_WORKER_OK),
weak_factory_(this) {}
+ServiceWorkerRegisterJob::ServiceWorkerRegisterJob(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerRegistration* registration)
+ : context_(context),
+ job_type_(UPDATE_JOB),
+ pattern_(registration->pattern()),
+ script_url_(registration->GetNewestVersion()->script_url()),
+ phase_(INITIAL),
+ is_promise_resolved_(false),
+ promise_resolved_status_(SERVICE_WORKER_OK),
+ weak_factory_(this) {
+ internal_.registration = registration;
+}
+
ServiceWorkerRegisterJob::~ServiceWorkerRegisterJob() {
DCHECK(!context_ ||
phase_ == INITIAL || phase_ == COMPLETE || phase_ == ABORT)
<< "Jobs should only be interrupted during shutdown.";
}
-void ServiceWorkerRegisterJob::AddCallback(const RegistrationCallback& callback,
- int process_id) {
+void ServiceWorkerRegisterJob::AddCallback(
+ const RegistrationCallback& callback,
+ ServiceWorkerProviderHost* provider_host) {
if (!is_promise_resolved_) {
callbacks_.push_back(callback);
- if (process_id != -1 && (phase_ < UPDATE || !pending_version()))
- pending_process_ids_.push_back(process_id);
+ if (provider_host)
+ provider_host->AddScopedProcessReferenceToPattern(pattern_);
return;
}
RunSoon(base::Bind(
- callback, promise_resolved_status_,
- promise_resolved_registration_, promise_resolved_version_));
+ callback, promise_resolved_status_, promise_resolved_registration_));
}
void ServiceWorkerRegisterJob::Start() {
SetPhase(START);
- context_->storage()->FindRegistrationForPattern(
- pattern_,
- base::Bind(
- &ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue,
- weak_factory_.GetWeakPtr()));
+ ServiceWorkerStorage::FindRegistrationCallback next_step;
+ if (job_type_ == REGISTRATION_JOB) {
+ next_step = base::Bind(
+ &ServiceWorkerRegisterJob::ContinueWithRegistration,
+ weak_factory_.GetWeakPtr());
+ } else {
+ next_step = base::Bind(
+ &ServiceWorkerRegisterJob::ContinueWithUpdate,
+ weak_factory_.GetWeakPtr());
+ }
+
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ context_->storage()->GetUninstallingRegistration(pattern_);
+ if (registration.get())
+ RunSoon(base::Bind(next_step, SERVICE_WORKER_OK, registration));
+ else
+ context_->storage()->FindRegistrationForPattern(pattern_, next_step);
}
void ServiceWorkerRegisterJob::Abort() {
@@ -82,7 +110,7 @@ bool ServiceWorkerRegisterJob::Equals(ServiceWorkerRegisterJobBase* job) {
}
RegistrationJobType ServiceWorkerRegisterJob::GetType() {
- return REGISTRATION;
+ return job_type_;
}
ServiceWorkerRegisterJob::Internal::Internal() {}
@@ -90,27 +118,39 @@ ServiceWorkerRegisterJob::Internal::Internal() {}
ServiceWorkerRegisterJob::Internal::~Internal() {}
void ServiceWorkerRegisterJob::set_registration(
- ServiceWorkerRegistration* registration) {
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
- DCHECK(!internal_.registration);
+ DCHECK(!internal_.registration.get());
internal_.registration = registration;
}
ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
- DCHECK(phase_ >= REGISTER) << phase_;
- return internal_.registration;
+ DCHECK(phase_ >= REGISTER || job_type_ == UPDATE_JOB) << phase_;
+ return internal_.registration.get();
}
-void ServiceWorkerRegisterJob::set_pending_version(
+void ServiceWorkerRegisterJob::set_new_version(
ServiceWorkerVersion* version) {
DCHECK(phase_ == UPDATE) << phase_;
- DCHECK(!internal_.pending_version);
- internal_.pending_version = version;
+ DCHECK(!internal_.new_version.get());
+ internal_.new_version = version;
}
-ServiceWorkerVersion* ServiceWorkerRegisterJob::pending_version() {
+ServiceWorkerVersion* ServiceWorkerRegisterJob::new_version() {
DCHECK(phase_ >= UPDATE) << phase_;
- return internal_.pending_version;
+ return internal_.new_version.get();
+}
+
+void ServiceWorkerRegisterJob::set_uninstalling_registration(
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL);
+ internal_.uninstalling_registration = registration;
+}
+
+ServiceWorkerRegistration*
+ServiceWorkerRegisterJob::uninstalling_registration() {
+ DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL);
+ return internal_.uninstalling_registration.get();
}
void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
@@ -121,9 +161,12 @@ void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
case START:
DCHECK(phase_ == INITIAL) << phase_;
break;
- case REGISTER:
+ case WAIT_FOR_UNINSTALL:
DCHECK(phase_ == START) << phase_;
break;
+ case REGISTER:
+ DCHECK(phase_ == START || phase_ == WAIT_FOR_UNINSTALL) << phase_;
+ break;
case UPDATE:
DCHECK(phase_ == START || phase_ == REGISTER) << phase_;
break;
@@ -133,9 +176,6 @@ void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
case STORE:
DCHECK(phase_ == INSTALL) << phase_;
break;
- case ACTIVATE:
- DCHECK(phase_ == STORE) << phase_;
- break;
case COMPLETE:
DCHECK(phase_ != INITIAL && phase_ != COMPLETE) << phase_;
break;
@@ -145,57 +185,78 @@ void ServiceWorkerRegisterJob::SetPhase(Phase phase) {
phase_ = phase;
}
-// This function corresponds to the steps in Register following
-// "Let serviceWorkerRegistration be _GetRegistration(scope)"
-// |existing_registration| corresponds to serviceWorkerRegistration.
+// This function corresponds to the steps in [[Register]] following
+// "Let registration be the result of running the [[GetRegistration]] algorithm.
// Throughout this file, comments in quotes are excerpts from the spec.
-void ServiceWorkerRegisterJob::HandleExistingRegistrationAndContinue(
+void ServiceWorkerRegisterJob::ContinueWithRegistration(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
- // On unexpected error, abort this registration job.
+ DCHECK_EQ(REGISTRATION_JOB, job_type_);
if (status != SERVICE_WORKER_ERROR_NOT_FOUND && status != SERVICE_WORKER_OK) {
Complete(status);
return;
}
- // "If serviceWorkerRegistration is not null and script is equal to
- // serviceWorkerRegistration.scriptUrl..." resolve with the existing
- // registration and abort.
- if (existing_registration.get() &&
- existing_registration->script_url() == script_url_) {
- set_registration(existing_registration);
- // If there's no active version, go ahead to Update (this isn't in the spec
- // but seems reasonable, and without SoftUpdate implemented we can never
- // Update otherwise).
- if (!existing_registration->active_version()) {
- UpdateAndContinue(status);
- return;
- }
- ResolvePromise(
- status, existing_registration, existing_registration->active_version());
- Complete(SERVICE_WORKER_OK);
+ if (!existing_registration.get() || existing_registration->is_uninstalled()) {
+ RegisterAndContinue(SERVICE_WORKER_OK);
return;
}
- // "If serviceWorkerRegistration is null..." create a new registration.
- if (!existing_registration.get()) {
- RegisterAndContinue(SERVICE_WORKER_OK);
+ DCHECK(existing_registration->GetNewestVersion());
+ // "If scriptURL is equal to registration.[[ScriptURL]], then:"
+ if (existing_registration->GetNewestVersion()->script_url() == script_url_) {
+ // "Set registration.[[Uninstalling]] to false."
+ existing_registration->AbortPendingClear(base::Bind(
+ &ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl,
+ weak_factory_.GetWeakPtr(),
+ existing_registration));
return;
}
- // On script URL mismatch, "set serviceWorkerRegistration.scriptUrl to
- // script." We accomplish this by deleting the existing registration and
- // registering a new one.
- // TODO(falken): Match the spec. We now throw away the active_version_ and
- // waiting_version_ of the existing registration, which isn't in the spec.
- // TODO(michaeln): Deactivate the live existing_registration object and
- // eventually call storage->DeleteVersionResources()
- // when it no longer has any controllees.
- context_->storage()->DeleteRegistration(
- existing_registration->id(),
- existing_registration->script_url().GetOrigin(),
- base::Bind(&ServiceWorkerRegisterJob::RegisterAndContinue,
- weak_factory_.GetWeakPtr()));
+ if (existing_registration->is_uninstalling()) {
+ // "Wait until the Record {[[key]], [[value]]} entry of its
+ // [[ScopeToRegistrationMap]] where registation.scope matches entry.[[key]]
+ // is deleted."
+ WaitForUninstall(existing_registration);
+ return;
+ }
+
+ // "Set registration.[[Uninstalling]] to false."
+ DCHECK(!existing_registration->is_uninstalling());
+
+ // "Return the result of running the [[Update]] algorithm, or its equivalent,
+ // passing registration as the argument."
+ set_registration(existing_registration);
+ UpdateAndContinue();
+}
+
+void ServiceWorkerRegisterJob::ContinueWithUpdate(
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
+ DCHECK_EQ(UPDATE_JOB, job_type_);
+ if (status != SERVICE_WORKER_OK) {
+ Complete(status);
+ return;
+ }
+
+ if (existing_registration.get() != registration()) {
+ Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
+ return;
+ }
+
+ // A previous job may have unregistered or installed a new version to this
+ // registration.
+ if (registration()->is_uninstalling() ||
+ registration()->GetNewestVersion()->script_url() != script_url_) {
+ Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
+ return;
+ }
+
+ // TODO(michaeln): If the last update check was less than 24 hours
+ // ago, depending on the freshness of the cached worker script we
+ // may be able to complete the update job right here.
+
+ UpdateAndContinue();
}
// Creates a new ServiceWorkerRegistration.
@@ -209,76 +270,115 @@ void ServiceWorkerRegisterJob::RegisterAndContinue(
}
set_registration(new ServiceWorkerRegistration(
- pattern_, script_url_, context_->storage()->NewRegistrationId(),
- context_));
- context_->storage()->NotifyInstallingRegistration(registration());
- UpdateAndContinue(SERVICE_WORKER_OK);
+ pattern_, context_->storage()->NewRegistrationId(), context_));
+ AssociateProviderHostsToRegistration(registration());
+ UpdateAndContinue();
}
-// This function corresponds to the spec's _Update algorithm.
-void ServiceWorkerRegisterJob::UpdateAndContinue(
+void ServiceWorkerRegisterJob::WaitForUninstall(
+ const scoped_refptr<ServiceWorkerRegistration>& existing_registration) {
+ SetPhase(WAIT_FOR_UNINSTALL);
+ set_uninstalling_registration(existing_registration);
+ uninstalling_registration()->AddListener(this);
+}
+
+void ServiceWorkerRegisterJob::ContinueWithRegistrationForSameScriptUrl(
+ const scoped_refptr<ServiceWorkerRegistration>& existing_registration,
ServiceWorkerStatusCode status) {
- SetPhase(UPDATE);
if (status != SERVICE_WORKER_OK) {
- // Abort this registration job.
Complete(status);
return;
}
+ set_registration(existing_registration);
+
+ // "If newestWorker is not null, and scriptURL is equal to
+ // newestWorker.scriptURL, then:
+ // Return a promise resolved with registration."
+ // We resolve only if there's an active version. If there's not,
+ // then there is either no version or only a waiting version from
+ // the last browser session; it makes sense to proceed with registration in
+ // either case.
+ DCHECK(!existing_registration->installing_version());
+ if (existing_registration->active_version()) {
+ ResolvePromise(status, existing_registration.get());
+ Complete(SERVICE_WORKER_OK);
+ return;
+ }
- // TODO(falken): "If serviceWorkerRegistration.installingWorker is not null.."
- // then terminate the installing worker. It doesn't make sense to implement
- // yet since we always activate the worker if install completed, so there can
- // be no installing worker at this point.
- // TODO(nhiroki): Check 'installing_version()' instead when it's supported.
- DCHECK(!registration()->waiting_version());
+ // "Return the result of running the [[Update]] algorithm, or its equivalent,
+ // passing registration as the argument."
+ UpdateAndContinue();
+}
- // "Let serviceWorker be a newly-created ServiceWorker object..." and start
- // the worker.
- set_pending_version(new ServiceWorkerVersion(
- registration(), context_->storage()->NewVersionId(), context_));
+// This function corresponds to the spec's [[Update]] algorithm.
+void ServiceWorkerRegisterJob::UpdateAndContinue() {
+ SetPhase(UPDATE);
+ context_->storage()->NotifyInstallingRegistration(registration());
- // TODO(michaeln): Start the worker into a paused state where the
- // script resource is downloaded but not yet evaluated.
- pending_version()->StartWorkerWithCandidateProcesses(
- pending_process_ids_,
+ // "Let worker be a new ServiceWorker object..." and start
+ // the worker.
+ set_new_version(new ServiceWorkerVersion(registration(),
+ script_url_,
+ context_->storage()->NewVersionId(),
+ context_));
+
+ bool pause_after_download = job_type_ == UPDATE_JOB;
+ if (pause_after_download)
+ new_version()->embedded_worker()->AddListener(this);
+ new_version()->StartWorker(
+ pause_after_download,
base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished,
weak_factory_.GetWeakPtr()));
}
void ServiceWorkerRegisterJob::OnStartWorkerFinished(
ServiceWorkerStatusCode status) {
- // "If serviceWorker fails to start up..." then reject the promise with an
- // error and abort.
- if (status != SERVICE_WORKER_OK) {
- Complete(status);
+ if (status == SERVICE_WORKER_OK) {
+ InstallAndContinue();
return;
}
- // TODO(michaeln): Compare the old and new script.
- // If different unpause the worker and continue with
- // the job. If the same ResolvePromise with the current
- // version and complete the job, throwing away the new version
- // since there's nothing new.
-
- // "Resolve promise with serviceWorker."
- // Although the spec doesn't set waitingWorker until after resolving the
- // promise, our system's resolving works by passing ServiceWorkerRegistration
- // to the callbacks, so waitingWorker must be set first.
- DCHECK(!registration()->waiting_version());
- registration()->set_waiting_version(pending_version());
- ResolvePromise(status, registration(), pending_version());
-
- AssociateWaitingVersionToDocuments(context_, pending_version());
-
- InstallAndContinue();
+ // "If serviceWorker fails to start up..." then reject the promise with an
+ // error and abort. When there is a main script network error, the status will
+ // be updated to a more specific one.
+ const net::URLRequestStatus& main_script_status =
+ new_version()->script_cache_map()->main_script_status();
+ if (main_script_status.status() != net::URLRequestStatus::SUCCESS) {
+ switch (main_script_status.error()) {
+ case net::ERR_INSECURE_RESPONSE:
+ case net::ERR_UNSAFE_REDIRECT:
+ status = SERVICE_WORKER_ERROR_SECURITY;
+ break;
+ case net::ERR_ABORTED:
+ status = SERVICE_WORKER_ERROR_ABORT;
+ break;
+ default:
+ status = SERVICE_WORKER_ERROR_NETWORK;
+ }
+ }
+ Complete(status);
}
-// This function corresponds to the spec's _Install algorithm.
+// This function corresponds to the spec's [[Install]] algorithm.
void ServiceWorkerRegisterJob::InstallAndContinue() {
SetPhase(INSTALL);
- // "Set serviceWorkerRegistration.installingWorker._state to installing."
- // "Fire install event on the associated ServiceWorkerGlobalScope object."
- pending_version()->DispatchInstallEvent(
+
+ // "Set registration.installingWorker to worker."
+ DCHECK(!registration()->installing_version());
+ registration()->SetInstallingVersion(new_version());
+
+ // "Run the Update State algorithm passing registration's installing worker
+ // and installing as the arguments."
+ new_version()->SetStatus(ServiceWorkerVersion::INSTALLING);
+
+ // "Resolve registrationPromise with registration."
+ ResolvePromise(SERVICE_WORKER_OK, registration());
+
+ // "Fire a simple event named updatefound..."
+ registration()->NotifyUpdateFound();
+
+ // "Fire an event named install..."
+ new_version()->DispatchInstallEvent(
-1,
base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
weak_factory_.GetWeakPtr()));
@@ -286,19 +386,19 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
void ServiceWorkerRegisterJob::OnInstallFinished(
ServiceWorkerStatusCode status) {
- // "If any handler called waitUntil()..." and the resulting promise
- // is rejected, abort.
// TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is
// unexpectedly terminated) we may want to retry sending the event again.
if (status != SERVICE_WORKER_OK) {
+ // "8. If installFailed is true, then:..."
Complete(status);
return;
}
SetPhase(STORE);
+ registration()->set_last_update_check(base::Time::Now());
context_->storage()->StoreRegistration(
registration(),
- pending_version(),
+ new_version(),
base::Bind(&ServiceWorkerRegisterJob::OnStoreRegistrationComplete,
weak_factory_.GetWeakPtr()));
}
@@ -310,61 +410,28 @@ void ServiceWorkerRegisterJob::OnStoreRegistrationComplete(
return;
}
- ActivateAndContinue();
-}
-
-// This function corresponds to the spec's _Activate algorithm.
-void ServiceWorkerRegisterJob::ActivateAndContinue() {
- SetPhase(ACTIVATE);
-
- // "If existingWorker is not null, then: wait for exitingWorker to finish
- // handling any in-progress requests."
- // See if we already have an active_version for the scope and it has
- // controllee documents (if so activating the new version should wait
- // until we have no documents controlled by the version).
- if (registration()->active_version() &&
- registration()->active_version()->HasControllee()) {
- // TODO(kinuko,falken): Currently we immediately return if the existing
- // registration already has an active version, so we shouldn't come
- // this way.
- NOTREACHED();
- // TODO(falken): Register an continuation task to wait for NoControllees
- // notification so that we can resume activation later (see comments
- // in ServiceWorkerVersion::RemoveControllee).
- Complete(SERVICE_WORKER_OK);
- return;
+ // "9. If registration.waitingWorker is not null, then:..."
+ if (registration()->waiting_version()) {
+ // "1. Run the [[UpdateState]] algorithm passing registration.waitingWorker
+ // and "redundant" as the arguments."
+ registration()->waiting_version()->SetStatus(
+ ServiceWorkerVersion::REDUNDANT);
}
- // "Set serviceWorkerRegistration.waitingWorker to null."
- // "Set serviceWorkerRegistration.activeWorker to activatingWorker."
- DisassociateWaitingVersionFromDocuments(
- context_, pending_version()->version_id());
- registration()->set_waiting_version(NULL);
- DCHECK(!registration()->active_version());
- registration()->set_active_version(pending_version());
-
- // "Set serviceWorkerRegistration.activeWorker._state to activating."
- // "Fire activate event on the associated ServiceWorkerGlobalScope object."
- // "Set serviceWorkerRegistration.activeWorker._state to active."
- pending_version()->DispatchActivateEvent(
- base::Bind(&ServiceWorkerRegisterJob::OnActivateFinished,
- weak_factory_.GetWeakPtr()));
-}
+ // "10. Set registration.waitingWorker to registration.installingWorker."
+ // "11. Set registration.installingWorker to null."
+ registration()->SetWaitingVersion(new_version());
+
+ // "12. Run the [[UpdateState]] algorithm passing registration.waitingWorker
+ // and "installed" as the arguments."
+ new_version()->SetStatus(ServiceWorkerVersion::INSTALLED);
+
+ // TODO(michaeln): "13. If activateImmediate is true, then..."
+
+ // "14. Wait until no document is using registration as their
+ // Service Worker registration."
+ registration()->ActivateWaitingVersionWhenReady();
-void ServiceWorkerRegisterJob::OnActivateFinished(
- ServiceWorkerStatusCode status) {
- // "If any handler called waitUntil()..." and the resulting promise
- // is rejected, abort.
- // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is
- // unexpectedly terminated) we may want to retry sending the event again.
- if (status != SERVICE_WORKER_OK) {
- registration()->set_active_version(NULL);
- Complete(status);
- return;
- }
- context_->storage()->UpdateToActiveState(
- registration(),
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
Complete(SERVICE_WORKER_OK);
}
@@ -377,91 +444,115 @@ void ServiceWorkerRegisterJob::CompleteInternal(
ServiceWorkerStatusCode status) {
SetPhase(COMPLETE);
if (status != SERVICE_WORKER_OK) {
- if (registration() && registration()->waiting_version()) {
- DisassociateWaitingVersionFromDocuments(
- context_, registration()->waiting_version()->version_id());
- registration()->set_waiting_version(NULL);
- }
- if (registration() && !registration()->active_version()) {
- context_->storage()->DeleteRegistration(
- registration()->id(),
- registration()->script_url().GetOrigin(),
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ if (registration()) {
+ if (new_version()) {
+ registration()->UnsetVersion(new_version());
+ new_version()->Doom();
+ }
+ if (!registration()->waiting_version() &&
+ !registration()->active_version()) {
+ registration()->NotifyRegistrationFailed();
+ context_->storage()->DeleteRegistration(
+ registration()->id(),
+ registration()->pattern().GetOrigin(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ }
}
if (!is_promise_resolved_)
- ResolvePromise(status, NULL, NULL);
+ ResolvePromise(status, NULL);
}
DCHECK(callbacks_.empty());
if (registration()) {
context_->storage()->NotifyDoneInstallingRegistration(
- registration(), pending_version(), status);
+ registration(), new_version(), status);
}
+ if (new_version())
+ new_version()->embedded_worker()->RemoveListener(this);
}
void ServiceWorkerRegisterJob::ResolvePromise(
ServiceWorkerStatusCode status,
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version) {
+ ServiceWorkerRegistration* registration) {
DCHECK(!is_promise_resolved_);
is_promise_resolved_ = true;
promise_resolved_status_ = status;
promise_resolved_registration_ = registration;
- promise_resolved_version_ = version;
for (std::vector<RegistrationCallback>::iterator it = callbacks_.begin();
it != callbacks_.end();
++it) {
- it->Run(status, registration, version);
+ it->Run(status, registration);
}
callbacks_.clear();
}
-// static
-void ServiceWorkerRegisterJob::AssociateWaitingVersionToDocuments(
- base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerVersion* version) {
- DCHECK(context);
- DCHECK(version);
+void ServiceWorkerRegisterJob::OnPausedAfterDownload() {
+ // This happens prior to OnStartWorkerFinished time.
+ scoped_refptr<ServiceWorkerVersion> most_recent_version =
+ registration()->waiting_version() ?
+ registration()->waiting_version() :
+ registration()->active_version();
+ DCHECK(most_recent_version.get());
+ int64 most_recent_script_id =
+ most_recent_version->script_cache_map()->LookupResourceId(script_url_);
+ int64 new_script_id =
+ new_version()->script_cache_map()->LookupResourceId(script_url_);
+
+ // TODO(michaeln): It would be better to compare as the new resource
+ // is being downloaded and to avoid writing it to disk until we know
+ // its needed.
+ context_->storage()->CompareScriptResources(
+ most_recent_script_id,
+ new_script_id,
+ base::Bind(&ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete,
+ weak_factory_.GetWeakPtr()));
+}
- for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
- context->GetProviderHostIterator();
- !it->IsAtEnd();
- it->Advance()) {
- ServiceWorkerProviderHost* host = it->GetProviderHost();
- if (!host->IsContextAlive())
- continue;
- if (ServiceWorkerUtils::ScopeMatches(version->scope(),
- host->document_url())) {
- // The spec's _Update algorithm says, "upgrades active version to a new
- // version for the same URL scope.", so skip if the scope (registration)
- // of |version| is different from that of the current active/waiting
- // version.
- if (!host->ValidateVersionForAssociation(version))
- continue;
-
- // TODO(nhiroki): Keep |host->waiting_version()| to be replaced and set
- // status of them to 'redandunt' after breaking the loop.
-
- host->SetWaitingVersion(version);
- // TODO(nhiroki): Set |host|'s installing version to null.
+bool ServiceWorkerRegisterJob::OnMessageReceived(const IPC::Message& message) {
+ return false;
+}
+
+void ServiceWorkerRegisterJob::OnRegistrationFinishedUninstalling(
+ ServiceWorkerRegistration* existing_registration) {
+ DCHECK_EQ(phase_, WAIT_FOR_UNINSTALL);
+ DCHECK_EQ(existing_registration, uninstalling_registration());
+ existing_registration->RemoveListener(this);
+ set_uninstalling_registration(NULL);
+ RegisterAndContinue(SERVICE_WORKER_OK);
+}
+
+void ServiceWorkerRegisterJob::OnCompareScriptResourcesComplete(
+ ServiceWorkerStatusCode status,
+ bool are_equal) {
+ if (are_equal) {
+ // Only bump the last check time when we've bypassed the browser cache.
+ base::TimeDelta time_since_last_check =
+ base::Time::Now() - registration()->last_update_check();
+ if (time_since_last_check > base::TimeDelta::FromHours(24)) {
+ registration()->set_last_update_check(base::Time::Now());
+ context_->storage()->UpdateLastUpdateCheckTime(registration());
}
+
+ ResolvePromise(SERVICE_WORKER_OK, registration());
+ Complete(SERVICE_WORKER_ERROR_EXISTS);
+ return;
}
+
+ // Proceed with really starting the worker.
+ new_version()->embedded_worker()->ResumeAfterDownload();
+ new_version()->embedded_worker()->RemoveListener(this);
}
-// static
-void ServiceWorkerRegisterJob::DisassociateWaitingVersionFromDocuments(
- base::WeakPtr<ServiceWorkerContextCore> context,
- int64 version_id) {
- DCHECK(context);
+void ServiceWorkerRegisterJob::AssociateProviderHostsToRegistration(
+ ServiceWorkerRegistration* registration) {
+ DCHECK(registration);
for (scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator> it =
- context->GetProviderHostIterator();
- !it->IsAtEnd();
- it->Advance()) {
+ context_->GetProviderHostIterator();
+ !it->IsAtEnd(); it->Advance()) {
ServiceWorkerProviderHost* host = it->GetProviderHost();
- if (!host->IsContextAlive())
- continue;
- if (host->waiting_version() &&
- host->waiting_version()->version_id() == version_id) {
- host->SetWaitingVersion(NULL);
+ if (ServiceWorkerUtils::ScopeMatches(registration->pattern(),
+ host->document_url())) {
+ if (host->CanAssociateRegistration(registration))
+ host->AssociateRegistration(registration);
}
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.h b/chromium/content/browser/service_worker/service_worker_register_job.h
index db10fa61118..167501b82cf 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/common/service_worker/service_worker_status_code.h"
@@ -18,61 +19,69 @@ namespace content {
class ServiceWorkerJobCoordinator;
class ServiceWorkerStorage;
-// Handles the registration of a Service Worker.
+// Handles the initial registration of a Service Worker and the
+// subsequent update of existing registrations.
//
-// The registration flow includes most or all of the following,
+// The control flow includes most or all of the following,
// depending on what is already registered:
// - creating a ServiceWorkerRegistration instance if there isn't
// already something registered
-// - creating a ServiceWorkerVersion for the new registration instance.
+// - creating a ServiceWorkerVersion for the new version.
// - starting a worker for the ServiceWorkerVersion
-// - telling the Version to evaluate the script
// - firing the 'install' event at the ServiceWorkerVersion
// - firing the 'activate' event at the ServiceWorkerVersion
// - waiting for older ServiceWorkerVersions to deactivate
// - designating the new version to be the 'active' version
-class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
+// - updating storage
+class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
+ public EmbeddedWorkerInstance::Listener,
+ public ServiceWorkerRegistration::Listener {
public:
typedef base::Callback<void(ServiceWorkerStatusCode status,
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version)>
+ ServiceWorkerRegistration* registration)>
RegistrationCallback;
+ // For registration jobs.
CONTENT_EXPORT ServiceWorkerRegisterJob(
base::WeakPtr<ServiceWorkerContextCore> context,
const GURL& pattern,
const GURL& script_url);
- virtual ~ServiceWorkerRegisterJob();
+
+ // For update jobs.
+ CONTENT_EXPORT ServiceWorkerRegisterJob(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerRegistration* registration);
+ ~ServiceWorkerRegisterJob() override;
// Registers a callback to be called when the promise would resolve (whether
- // successfully or not). Multiple callbacks may be registered. If |process_id|
- // is not -1, it's added to the existing clients when deciding in which
- // process to create the Service Worker instance. If there are no existing
- // clients, a new RenderProcessHost will be created.
- void AddCallback(const RegistrationCallback& callback, int process_id);
+ // successfully or not). Multiple callbacks may be registered.
+ // If |provider_host| is not NULL, its process will be regarded as a candidate
+ // process to run the worker.
+ void AddCallback(const RegistrationCallback& callback,
+ ServiceWorkerProviderHost* provider_host);
// ServiceWorkerRegisterJobBase implementation:
- virtual void Start() OVERRIDE;
- virtual void Abort() OVERRIDE;
- virtual bool Equals(ServiceWorkerRegisterJobBase* job) OVERRIDE;
- virtual RegistrationJobType GetType() OVERRIDE;
+ void Start() override;
+ void Abort() override;
+ bool Equals(ServiceWorkerRegisterJobBase* job) override;
+ RegistrationJobType GetType() override;
private:
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostWaitingVersionTest,
- AssociateWaitingVersionToDocuments);
+ AssociateInstallingVersionToDocuments);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProviderHostWaitingVersionTest,
- DisassociateWaitingVersionFromDocuments);
+ DisassociateVersionFromDocuments);
enum Phase {
- INITIAL,
- START,
- REGISTER,
- UPDATE,
- INSTALL,
- STORE,
- ACTIVATE,
- COMPLETE,
- ABORT,
+ INITIAL,
+ START,
+ WAIT_FOR_UNINSTALL,
+ REGISTER,
+ UPDATE,
+ INSTALL,
+ STORE,
+ COMPLETE,
+ ABORT,
};
// Holds internal state of ServiceWorkerRegistrationJob, to compel use of the
@@ -82,22 +91,37 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
~Internal();
scoped_refptr<ServiceWorkerRegistration> registration;
- // Holds 'installing' or 'waiting' version depending on the phase.
- scoped_refptr<ServiceWorkerVersion> pending_version;
+ // Holds the version created by this job. It can be the 'installing',
+ // 'waiting', or 'active' version depending on the phase.
+ scoped_refptr<ServiceWorkerVersion> new_version;
+
+ scoped_refptr<ServiceWorkerRegistration> uninstalling_registration;
};
- void set_registration(ServiceWorkerRegistration* registration);
+ void set_registration(
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
ServiceWorkerRegistration* registration();
- void set_pending_version(ServiceWorkerVersion* version);
- ServiceWorkerVersion* pending_version();
+ void set_new_version(ServiceWorkerVersion* version);
+ ServiceWorkerVersion* new_version();
+ void set_uninstalling_registration(
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+ ServiceWorkerRegistration* uninstalling_registration();
void SetPhase(Phase phase);
- void HandleExistingRegistrationAndContinue(
+ void ContinueWithRegistration(
+ ServiceWorkerStatusCode status,
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+ void ContinueWithUpdate(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
void RegisterAndContinue(ServiceWorkerStatusCode status);
- void UpdateAndContinue(ServiceWorkerStatusCode status);
+ void WaitForUninstall(
+ const scoped_refptr<ServiceWorkerRegistration>& registration);
+ void ContinueWithRegistrationForSameScriptUrl(
+ const scoped_refptr<ServiceWorkerRegistration>& existing_registration,
+ ServiceWorkerStatusCode status);
+ void UpdateAndContinue();
void OnStartWorkerFinished(ServiceWorkerStatusCode status);
void OnStoreRegistrationComplete(ServiceWorkerStatusCode status);
void InstallAndContinue();
@@ -106,35 +130,36 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
void OnActivateFinished(ServiceWorkerStatusCode status);
void Complete(ServiceWorkerStatusCode status);
void CompleteInternal(ServiceWorkerStatusCode status);
-
void ResolvePromise(ServiceWorkerStatusCode status,
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version);
+ ServiceWorkerRegistration* registration);
- // Associates a waiting version to documents matched with a scope of the
- // version.
- CONTENT_EXPORT static void AssociateWaitingVersionToDocuments(
- base::WeakPtr<ServiceWorkerContextCore> context,
- ServiceWorkerVersion* version);
+ // EmbeddedWorkerInstance::Listener override of OnPausedAfterDownload.
+ void OnPausedAfterDownload() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
- // Disassociates a waiting version specified by |version_id| from documents.
- CONTENT_EXPORT static void DisassociateWaitingVersionFromDocuments(
- base::WeakPtr<ServiceWorkerContextCore> context,
- int64 version_id);
+ // ServiceWorkerRegistration::Listener overrides
+ void OnRegistrationFinishedUninstalling(
+ ServiceWorkerRegistration* registration) override;
+
+ void OnCompareScriptResourcesComplete(
+ ServiceWorkerStatusCode status,
+ bool are_equal);
+
+ void AssociateProviderHostsToRegistration(
+ ServiceWorkerRegistration* registration);
// The ServiceWorkerContextCore object should always outlive this.
base::WeakPtr<ServiceWorkerContextCore> context_;
+ RegistrationJobType job_type_;
const GURL pattern_;
const GURL script_url_;
std::vector<RegistrationCallback> callbacks_;
- std::vector<int> pending_process_ids_;
Phase phase_;
Internal internal_;
bool is_promise_resolved_;
ServiceWorkerStatusCode promise_resolved_status_;
scoped_refptr<ServiceWorkerRegistration> promise_resolved_registration_;
- scoped_refptr<ServiceWorkerVersion> promise_resolved_version_;
base::WeakPtrFactory<ServiceWorkerRegisterJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegisterJob);
diff --git a/chromium/content/browser/service_worker/service_worker_register_job_base.h b/chromium/content/browser/service_worker/service_worker_register_job_base.h
index 7995adda7c6..9233e7c69af 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job_base.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job_base.h
@@ -7,11 +7,13 @@
namespace content {
-// A base class for ServiceWorkerRegisterJob and ServiceWorkerUnregisterJob. A
-// job lives only for the lifetime of a single registration or unregistration.
class ServiceWorkerRegisterJobBase {
public:
- enum RegistrationJobType { REGISTRATION, UNREGISTRATION, };
+ enum RegistrationJobType {
+ REGISTRATION_JOB,
+ UNREGISTRATION_JOB,
+ UPDATE_JOB
+ };
virtual ~ServiceWorkerRegisterJobBase() {}
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index 9e166b6f7b1..0445f08f7e6 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -6,19 +6,33 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_info.h"
+#include "content/browser/service_worker/service_worker_register_job.h"
+#include "content/browser/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
namespace content {
+namespace {
+
+ServiceWorkerVersionInfo GetVersionInfo(ServiceWorkerVersion* version) {
+ if (!version)
+ return ServiceWorkerVersionInfo();
+ return version->GetInfo();
+}
+
+} // namespace
+
ServiceWorkerRegistration::ServiceWorkerRegistration(
const GURL& pattern,
- const GURL& script_url,
int64 registration_id,
base::WeakPtr<ServiceWorkerContextCore> context)
: pattern_(pattern),
- script_url_(script_url),
registration_id_(registration_id),
- is_shutdown_(false),
+ is_deleted_(false),
+ is_uninstalling_(false),
+ is_uninstalled_(false),
+ should_activate_when_ready_(false),
+ resources_total_size_bytes_(0),
context_(context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(context_);
@@ -27,33 +41,297 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(
ServiceWorkerRegistration::~ServiceWorkerRegistration() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(!listeners_.might_have_observers());
if (context_)
context_->RemoveLiveRegistration(registration_id_);
+ if (active_version())
+ active_version()->RemoveListener(this);
+}
+
+ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() const {
+ if (installing_version())
+ return installing_version();
+ if (waiting_version())
+ return waiting_version();
+ return active_version();
+}
+
+void ServiceWorkerRegistration::AddListener(Listener* listener) {
+ listeners_.AddObserver(listener);
+}
+
+void ServiceWorkerRegistration::RemoveListener(Listener* listener) {
+ listeners_.RemoveObserver(listener);
+}
+
+void ServiceWorkerRegistration::NotifyRegistrationFailed() {
+ FOR_EACH_OBSERVER(Listener, listeners_, OnRegistrationFailed(this));
+}
+
+void ServiceWorkerRegistration::NotifyUpdateFound() {
+ FOR_EACH_OBSERVER(Listener, listeners_, OnUpdateFound(this));
}
ServiceWorkerRegistrationInfo ServiceWorkerRegistration::GetInfo() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return ServiceWorkerRegistrationInfo(
- script_url(),
pattern(),
registration_id_,
- active_version_ ? active_version_->GetInfo() : ServiceWorkerVersionInfo(),
- waiting_version_ ? waiting_version_->GetInfo()
- : ServiceWorkerVersionInfo());
+ GetVersionInfo(active_version_.get()),
+ GetVersionInfo(waiting_version_.get()),
+ GetVersionInfo(installing_version_.get()),
+ resources_total_size_bytes_);
}
-ServiceWorkerVersion* ServiceWorkerRegistration::GetNewestVersion() {
- if (active_version())
- return active_version();
- return waiting_version();
+void ServiceWorkerRegistration::SetActiveVersion(
+ ServiceWorkerVersion* version) {
+ should_activate_when_ready_ = false;
+ SetVersionInternal(version, &active_version_,
+ ChangedVersionAttributesMask::ACTIVE_VERSION);
+}
+
+void ServiceWorkerRegistration::SetWaitingVersion(
+ ServiceWorkerVersion* version) {
+ should_activate_when_ready_ = false;
+ SetVersionInternal(version, &waiting_version_,
+ ChangedVersionAttributesMask::WAITING_VERSION);
+}
+
+void ServiceWorkerRegistration::SetInstallingVersion(
+ ServiceWorkerVersion* version) {
+ SetVersionInternal(version, &installing_version_,
+ ChangedVersionAttributesMask::INSTALLING_VERSION);
+}
+
+void ServiceWorkerRegistration::UnsetVersion(ServiceWorkerVersion* version) {
+ if (!version)
+ return;
+ ChangedVersionAttributesMask mask;
+ UnsetVersionInternal(version, &mask);
+ if (mask.changed()) {
+ ServiceWorkerRegistrationInfo info = GetInfo();
+ FOR_EACH_OBSERVER(Listener, listeners_,
+ OnVersionAttributesChanged(this, mask, info));
+ }
+}
+
+void ServiceWorkerRegistration::SetVersionInternal(
+ ServiceWorkerVersion* version,
+ scoped_refptr<ServiceWorkerVersion>* data_member,
+ int change_flag) {
+ if (version == data_member->get())
+ return;
+ scoped_refptr<ServiceWorkerVersion> protect(version);
+ ChangedVersionAttributesMask mask;
+ if (version)
+ UnsetVersionInternal(version, &mask);
+ *data_member = version;
+ if (active_version_.get() && active_version_.get() == version)
+ active_version_->AddListener(this);
+ mask.add(change_flag);
+ ServiceWorkerRegistrationInfo info = GetInfo();
+ FOR_EACH_OBSERVER(Listener, listeners_,
+ OnVersionAttributesChanged(this, mask, info));
+}
+
+void ServiceWorkerRegistration::UnsetVersionInternal(
+ ServiceWorkerVersion* version,
+ ChangedVersionAttributesMask* mask) {
+ DCHECK(version);
+ if (installing_version_.get() == version) {
+ installing_version_ = NULL;
+ mask->add(ChangedVersionAttributesMask::INSTALLING_VERSION);
+ } else if (waiting_version_.get() == version) {
+ waiting_version_ = NULL;
+ mask->add(ChangedVersionAttributesMask::WAITING_VERSION);
+ } else if (active_version_.get() == version) {
+ active_version_->RemoveListener(this);
+ active_version_ = NULL;
+ mask->add(ChangedVersionAttributesMask::ACTIVE_VERSION);
+ }
+}
+
+void ServiceWorkerRegistration::ActivateWaitingVersionWhenReady() {
+ DCHECK(waiting_version());
+ should_activate_when_ready_ = true;
+ if (!active_version() || !active_version()->HasControllee())
+ ActivateWaitingVersion();
+}
+
+void ServiceWorkerRegistration::ClearWhenReady() {
+ DCHECK(context_);
+ if (is_uninstalling_)
+ return;
+ is_uninstalling_ = true;
+
+ context_->storage()->NotifyUninstallingRegistration(this);
+ context_->storage()->DeleteRegistration(
+ id(),
+ pattern().GetOrigin(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+
+ if (!active_version() || !active_version()->HasControllee())
+ Clear();
+}
+
+void ServiceWorkerRegistration::AbortPendingClear(
+ const StatusCallback& callback) {
+ DCHECK(context_);
+ if (!is_uninstalling()) {
+ callback.Run(SERVICE_WORKER_OK);
+ return;
+ }
+ is_uninstalling_ = false;
+ context_->storage()->NotifyDoneUninstallingRegistration(this);
+
+ scoped_refptr<ServiceWorkerVersion> most_recent_version =
+ waiting_version() ? waiting_version() : active_version();
+ DCHECK(most_recent_version.get());
+ context_->storage()->NotifyInstallingRegistration(this);
+ context_->storage()->StoreRegistration(
+ this,
+ most_recent_version.get(),
+ base::Bind(&ServiceWorkerRegistration::OnRestoreFinished,
+ this,
+ callback,
+ most_recent_version));
+}
+
+void ServiceWorkerRegistration::OnNoControllees(ServiceWorkerVersion* version) {
+ DCHECK_EQ(active_version(), version);
+ if (is_uninstalling_)
+ Clear();
+ else if (should_activate_when_ready_)
+ ActivateWaitingVersion();
+ is_uninstalling_ = false;
+ should_activate_when_ready_ = false;
}
void ServiceWorkerRegistration::ActivateWaitingVersion() {
- active_version_->SetStatus(ServiceWorkerVersion::DEACTIVATED);
- active_version_ = waiting_version_;
- // TODO(kinuko): This should be set to ACTIVATING until activation finishes.
- active_version_->SetStatus(ServiceWorkerVersion::ACTIVE);
- waiting_version_ = NULL;
+ DCHECK(context_);
+ DCHECK(waiting_version());
+ DCHECK(should_activate_when_ready_);
+ should_activate_when_ready_ = false;
+ scoped_refptr<ServiceWorkerVersion> activating_version = waiting_version();
+ scoped_refptr<ServiceWorkerVersion> exiting_version = active_version();
+
+ if (activating_version->is_doomed() ||
+ activating_version->status() == ServiceWorkerVersion::REDUNDANT) {
+ return; // Activation is no longer relevant.
+ }
+
+ // "4. If exitingWorker is not null,
+ if (exiting_version.get()) {
+ DCHECK(!exiting_version->HasControllee());
+ // TODO(michaeln): should wait for events to be complete
+ // "1. Wait for exitingWorker to finish handling any in-progress requests."
+ // "2. Terminate exitingWorker."
+ exiting_version->StopWorker(
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ // "3. Run the [[UpdateState]] algorithm passing exitingWorker and
+ // "redundant" as the arguments."
+ exiting_version->SetStatus(ServiceWorkerVersion::REDUNDANT);
+ }
+
+ // "5. Set serviceWorkerRegistration.activeWorker to activatingWorker."
+ // "6. Set serviceWorkerRegistration.waitingWorker to null."
+ SetActiveVersion(activating_version.get());
+
+ // "7. Run the [[UpdateState]] algorithm passing registration.activeWorker and
+ // "activating" as arguments."
+ activating_version->SetStatus(ServiceWorkerVersion::ACTIVATING);
+
+ // TODO(nhiroki): "8. Fire a simple event named controllerchange..."
+
+ // "9. Queue a task to fire an event named activate..."
+ activating_version->DispatchActivateEvent(
+ base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished,
+ this, activating_version));
+}
+
+void ServiceWorkerRegistration::OnActivateEventFinished(
+ ServiceWorkerVersion* activating_version,
+ ServiceWorkerStatusCode status) {
+ if (!context_ || activating_version != active_version())
+ return;
+ // TODO(kinuko,falken): For some error cases (e.g. ServiceWorker is
+ // unexpectedly terminated) we may want to retry sending the event again.
+ if (status != SERVICE_WORKER_OK) {
+ // "11. If activateFailed is true, then:..."
+ UnsetVersion(activating_version);
+ activating_version->Doom();
+ if (!waiting_version()) {
+ // Delete the records from the db.
+ context_->storage()->DeleteRegistration(
+ id(), pattern().GetOrigin(),
+ base::Bind(&ServiceWorkerRegistration::OnDeleteFinished, this));
+ // But not from memory if there is a version in the pipeline.
+ if (installing_version())
+ is_deleted_ = false;
+ }
+ return;
+ }
+
+ // "12. Run the [[UpdateState]] algorithm passing registration.activeWorker
+ // and "activated" as the arguments."
+ activating_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ if (context_) {
+ context_->storage()->UpdateToActiveState(
+ this,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ }
+}
+
+void ServiceWorkerRegistration::OnDeleteFinished(
+ ServiceWorkerStatusCode status) {
+ // Intentionally empty completion callback, used to prevent
+ // |this| from being deleted until the storage method completes.
+}
+
+void ServiceWorkerRegistration::Clear() {
+ is_uninstalling_ = false;
+ is_uninstalled_ = true;
+ if (context_)
+ context_->storage()->NotifyDoneUninstallingRegistration(this);
+
+ ChangedVersionAttributesMask mask;
+ if (installing_version_.get()) {
+ installing_version_->Doom();
+ installing_version_ = NULL;
+ mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
+ }
+ if (waiting_version_.get()) {
+ waiting_version_->Doom();
+ waiting_version_ = NULL;
+ mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
+ }
+ if (active_version_.get()) {
+ active_version_->Doom();
+ active_version_->RemoveListener(this);
+ active_version_ = NULL;
+ mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
+ }
+ if (mask.changed()) {
+ ServiceWorkerRegistrationInfo info = GetInfo();
+ FOR_EACH_OBSERVER(Listener, listeners_,
+ OnVersionAttributesChanged(this, mask, info));
+ }
+
+ FOR_EACH_OBSERVER(
+ Listener, listeners_, OnRegistrationFinishedUninstalling(this));
+}
+
+void ServiceWorkerRegistration::OnRestoreFinished(
+ const StatusCallback& callback,
+ scoped_refptr<ServiceWorkerVersion> version,
+ ServiceWorkerStatusCode status) {
+ if (!context_) {
+ callback.Run(SERVICE_WORKER_ERROR_ABORT);
+ return;
+ }
+ context_->storage()->NotifyDoneInstallingRegistration(
+ this, version.get(), status);
+ callback.Run(status);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index df23dc3d61a..b386eecfad3 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "url/gurl.h"
namespace content {
@@ -19,76 +20,148 @@ namespace content {
class ServiceWorkerRegistrationInfo;
class ServiceWorkerVersion;
-// This class manages all persistence of service workers:
-// - Registrations
-// - Mapping of caches to registrations / versions
-//
-// This is the place where we manage simultaneous
-// requests for the same registrations and caches, making sure that
-// two pages that are registering the same pattern at the same time
-// have their registrations coalesced rather than overwriting each
-// other.
-//
-// This class also manages the state of the upgrade process, which
-// includes managing which ServiceWorkerVersion is "active" vs "in
-// waiting".
+// This class represents a Service Worker registration. The scope is constant
+// for the life of the persistent registration. It's refcounted to facilitate
+// multiple controllees being associated with the same registration.
class CONTENT_EXPORT ServiceWorkerRegistration
- : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerRegistration>) {
+ : NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerRegistration>),
+ public ServiceWorkerVersion::Listener {
public:
+ typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
+
+ class Listener {
+ public:
+ virtual void OnVersionAttributesChanged(
+ ServiceWorkerRegistration* registration,
+ ChangedVersionAttributesMask changed_mask,
+ const ServiceWorkerRegistrationInfo& info) {}
+ virtual void OnRegistrationFailed(
+ ServiceWorkerRegistration* registration) {}
+ virtual void OnRegistrationFinishedUninstalling(
+ ServiceWorkerRegistration* registration) {}
+ virtual void OnUpdateFound(
+ ServiceWorkerRegistration* registration) {}
+ };
+
ServiceWorkerRegistration(const GURL& pattern,
- const GURL& script_url,
int64 registration_id,
base::WeakPtr<ServiceWorkerContextCore> context);
int64 id() const { return registration_id_; }
- const GURL& script_url() const { return script_url_; }
const GURL& pattern() const { return pattern_; }
+ bool is_deleted() const { return is_deleted_; }
+ void set_is_deleted(bool deleted) { is_deleted_ = deleted; }
+
+ bool is_uninstalling() const { return is_uninstalling_; }
+ bool is_uninstalled() const { return is_uninstalled_; }
+
+ int64_t resources_total_size_bytes() const {
+ return resources_total_size_bytes_;
+ }
+
+ void set_resources_total_size_bytes(int64_t resources_total_size_bytes) {
+ resources_total_size_bytes_ = resources_total_size_bytes;
+ }
+
ServiceWorkerVersion* active_version() const {
- DCHECK(!is_shutdown_);
return active_version_.get();
}
ServiceWorkerVersion* waiting_version() const {
- DCHECK(!is_shutdown_);
return waiting_version_.get();
}
- void set_active_version(ServiceWorkerVersion* version) {
- DCHECK(!is_shutdown_);
- active_version_ = version;
+ ServiceWorkerVersion* installing_version() const {
+ return installing_version_.get();
}
- void set_waiting_version(ServiceWorkerVersion* version) {
- DCHECK(!is_shutdown_);
- waiting_version_ = version;
- }
+ ServiceWorkerVersion* GetNewestVersion() const;
+
+ void AddListener(Listener* listener);
+ void RemoveListener(Listener* listener);
+ void NotifyRegistrationFailed();
+ void NotifyUpdateFound();
ServiceWorkerRegistrationInfo GetInfo();
- // Returns the active version, if it is not null; otherwise, returns the
- // waiting version.
- ServiceWorkerVersion* GetNewestVersion();
+ // Sets the corresposding version attribute and resets the position
+ // (if any) left vacant (ie. by a waiting version being promoted).
+ // Also notifies listeners via OnVersionAttributesChanged.
+ void SetActiveVersion(ServiceWorkerVersion* version);
+ void SetWaitingVersion(ServiceWorkerVersion* version);
+ void SetInstallingVersion(ServiceWorkerVersion* version);
- // The final synchronous switchover after all events have been
- // fired, and the old "active version" is being shut down.
- void ActivateWaitingVersion();
+ // If version is the installing, waiting, active version of this
+ // registation, the method will reset that field to NULL, and notify
+ // listeners via OnVersionAttributesChanged.
+ void UnsetVersion(ServiceWorkerVersion* version);
+
+ // Triggers the [[Activate]] algorithm when the currently active version
+ // has no controllees. If there are no controllees at the time the method
+ // is called, activation is initiated immediately.
+ void ActivateWaitingVersionWhenReady();
+
+ // Triggers the [[ClearRegistration]] algorithm when the currently
+ // active version has no controllees. Deletes this registration
+ // from storage immediately.
+ void ClearWhenReady();
+
+ // Restores this registration in storage and cancels the pending
+ // [[ClearRegistration]] algorithm.
+ void AbortPendingClear(const StatusCallback& callback);
+
+ // The time of the most recent update check.
+ base::Time last_update_check() const { return last_update_check_; }
+ void set_last_update_check(base::Time last) { last_update_check_ = last; }
private:
- ~ServiceWorkerRegistration();
friend class base::RefCounted<ServiceWorkerRegistration>;
+ ~ServiceWorkerRegistration() override;
+
+ void SetVersionInternal(
+ ServiceWorkerVersion* version,
+ scoped_refptr<ServiceWorkerVersion>* data_member,
+ int change_flag);
+ void UnsetVersionInternal(
+ ServiceWorkerVersion* version,
+ ChangedVersionAttributesMask* mask);
+
+ // ServiceWorkerVersion::Listener override.
+ void OnNoControllees(ServiceWorkerVersion* version) override;
+
+ // This method corresponds to the [[Activate]] algorithm.
+ void ActivateWaitingVersion();
+ void OnActivateEventFinished(
+ ServiceWorkerVersion* activating_version,
+ ServiceWorkerStatusCode status);
+ void OnDeleteFinished(ServiceWorkerStatusCode status);
+
+ // This method corresponds to the [[ClearRegistration]] algorithm.
+ void Clear();
+
+ void OnRestoreFinished(const StatusCallback& callback,
+ scoped_refptr<ServiceWorkerVersion> version,
+ ServiceWorkerStatusCode status);
+
const GURL pattern_;
- const GURL script_url_;
const int64 registration_id_;
-
+ bool is_deleted_;
+ bool is_uninstalling_;
+ bool is_uninstalled_;
+ bool should_activate_when_ready_;
+ base::Time last_update_check_;
+ int64_t resources_total_size_bytes_;
scoped_refptr<ServiceWorkerVersion> active_version_;
scoped_refptr<ServiceWorkerVersion> waiting_version_;
-
- bool is_shutdown_;
+ scoped_refptr<ServiceWorkerVersion> installing_version_;
+ ObserverList<Listener> listeners_;
base::WeakPtr<ServiceWorkerContextCore> context_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistration);
};
+
} // namespace content
+
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
diff --git a/chromium/content/browser/service_worker/service_worker_registration_handle.cc b/chromium/content/browser/service_worker/service_worker_registration_handle.cc
new file mode 100644
index 00000000000..195a33a8235
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration_handle.cc
@@ -0,0 +1,147 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_registration_handle.h"
+
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "content/browser/service_worker/service_worker_handle.h"
+#include "content/common/service_worker/service_worker_messages.h"
+
+namespace content {
+
+static const int kDocumentMainThreadId = 0;
+
+ServiceWorkerRegistrationHandle::ServiceWorkerRegistrationHandle(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerDispatcherHost* dispatcher_host,
+ int provider_id,
+ ServiceWorkerRegistration* registration)
+ : context_(context),
+ dispatcher_host_(dispatcher_host),
+ provider_id_(provider_id),
+ handle_id_(context ? context->GetNewRegistrationHandleId()
+ : kInvalidServiceWorkerRegistrationHandleId),
+ ref_count_(1),
+ registration_(registration) {
+ DCHECK(registration_.get());
+ SetVersionAttributes(registration->installing_version(),
+ registration->waiting_version(),
+ registration->active_version());
+ registration_->AddListener(this);
+}
+
+ServiceWorkerRegistrationHandle::~ServiceWorkerRegistrationHandle() {
+ DCHECK(registration_.get());
+ registration_->RemoveListener(this);
+}
+
+ServiceWorkerRegistrationObjectInfo
+ServiceWorkerRegistrationHandle::GetObjectInfo() {
+ ServiceWorkerRegistrationObjectInfo info;
+ info.handle_id = handle_id_;
+ info.scope = registration_->pattern();
+ info.registration_id = registration_->id();
+ return info;
+}
+
+ServiceWorkerObjectInfo
+ServiceWorkerRegistrationHandle::CreateServiceWorkerHandleAndPass(
+ ServiceWorkerVersion* version) {
+ ServiceWorkerObjectInfo info;
+ if (context_ && version) {
+ scoped_ptr<ServiceWorkerHandle> handle =
+ ServiceWorkerHandle::Create(context_,
+ dispatcher_host_,
+ kDocumentMainThreadId,
+ provider_id_,
+ version);
+ info = handle->GetObjectInfo();
+ dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
+ }
+ return info;
+}
+
+void ServiceWorkerRegistrationHandle::IncrementRefCount() {
+ DCHECK_GT(ref_count_, 0);
+ ++ref_count_;
+}
+
+void ServiceWorkerRegistrationHandle::DecrementRefCount() {
+ DCHECK_GT(ref_count_, 0);
+ --ref_count_;
+}
+
+void ServiceWorkerRegistrationHandle::OnVersionAttributesChanged(
+ ServiceWorkerRegistration* registration,
+ ChangedVersionAttributesMask changed_mask,
+ const ServiceWorkerRegistrationInfo& info) {
+ DCHECK_EQ(registration->id(), registration_->id());
+ SetVersionAttributes(registration->installing_version(),
+ registration->waiting_version(),
+ registration->active_version());
+}
+
+void ServiceWorkerRegistrationHandle::OnRegistrationFailed(
+ ServiceWorkerRegistration* registration) {
+ DCHECK_EQ(registration->id(), registration_->id());
+ ClearVersionAttributes();
+}
+
+void ServiceWorkerRegistrationHandle::OnUpdateFound(
+ ServiceWorkerRegistration* registration) {
+ if (!dispatcher_host_)
+ return; // Could be NULL in some tests.
+ dispatcher_host_->Send(new ServiceWorkerMsg_UpdateFound(
+ kDocumentMainThreadId, GetObjectInfo()));
+}
+
+void ServiceWorkerRegistrationHandle::SetVersionAttributes(
+ ServiceWorkerVersion* installing_version,
+ ServiceWorkerVersion* waiting_version,
+ ServiceWorkerVersion* active_version) {
+ ChangedVersionAttributesMask mask;
+
+ if (installing_version != installing_version_.get()) {
+ installing_version_ = installing_version;
+ mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
+ }
+ if (waiting_version != waiting_version_.get()) {
+ waiting_version_ = waiting_version;
+ mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
+ }
+ if (active_version != active_version_.get()) {
+ active_version_ = active_version;
+ mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
+ }
+
+ if (!dispatcher_host_)
+ return; // Could be NULL in some tests.
+ if (!mask.changed())
+ return;
+
+ ServiceWorkerVersionAttributes attributes;
+ if (mask.installing_changed()) {
+ attributes.installing =
+ CreateServiceWorkerHandleAndPass(installing_version);
+ }
+ if (mask.waiting_changed()) {
+ attributes.waiting =
+ CreateServiceWorkerHandleAndPass(waiting_version);
+ }
+ if (mask.active_changed()) {
+ attributes.active =
+ CreateServiceWorkerHandleAndPass(active_version);
+ }
+
+ dispatcher_host_->Send(new ServiceWorkerMsg_SetVersionAttributes(
+ kDocumentMainThreadId, provider_id_, handle_id_,
+ mask.changed(), attributes));
+}
+
+void ServiceWorkerRegistrationHandle::ClearVersionAttributes() {
+ SetVersionAttributes(NULL, NULL, NULL);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_registration_handle.h b/chromium/content/browser/service_worker/service_worker_registration_handle.h
new file mode 100644
index 00000000000..9439027041b
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_registration_handle.h
@@ -0,0 +1,84 @@
+// Copyright 2014 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_types.h"
+
+namespace content {
+
+class ServiceWorkerContextCore;
+class ServiceWorkerDispatcherHost;
+class ServiceWorkerVersion;
+
+// Roughly Corresponds to one ServiceWorkerRegistration object in the renderer
+// process (WebServiceWorkerRegistrationImpl).
+// Has references to the corresponding ServiceWorkerRegistration and
+// ServiceWorkerVersions (therefore they're guaranteed to be alive while this
+// handle is around).
+class ServiceWorkerRegistrationHandle
+ : public ServiceWorkerRegistration::Listener {
+ public:
+ CONTENT_EXPORT ServiceWorkerRegistrationHandle(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerDispatcherHost* dispatcher_host,
+ int provider_id,
+ ServiceWorkerRegistration* registration);
+ virtual ~ServiceWorkerRegistrationHandle();
+
+ ServiceWorkerRegistrationObjectInfo GetObjectInfo();
+ ServiceWorkerObjectInfo CreateServiceWorkerHandleAndPass(
+ ServiceWorkerVersion* version);
+
+ bool HasNoRefCount() const { return ref_count_ <= 0; }
+ void IncrementRefCount();
+ void DecrementRefCount();
+
+ int provider_id() const { return provider_id_; }
+ int handle_id() const { return handle_id_; }
+
+ ServiceWorkerRegistration* registration() { return registration_.get(); }
+
+ private:
+ // ServiceWorkerRegistration::Listener overrides.
+ void OnVersionAttributesChanged(
+ ServiceWorkerRegistration* registration,
+ ChangedVersionAttributesMask changed_mask,
+ const ServiceWorkerRegistrationInfo& info) override;
+ void OnRegistrationFailed(ServiceWorkerRegistration* registration) override;
+ void OnUpdateFound(ServiceWorkerRegistration* registration) override;
+
+ // Sets the corresponding version field to the given version or if the given
+ // version is NULL, clears the field.
+ void SetVersionAttributes(
+ ServiceWorkerVersion* installing_version,
+ ServiceWorkerVersion* waiting_version,
+ ServiceWorkerVersion* active_version);
+
+ // Clears all version fields.
+ void ClearVersionAttributes();
+
+ base::WeakPtr<ServiceWorkerContextCore> context_;
+ ServiceWorkerDispatcherHost* dispatcher_host_;
+ const int provider_id_;
+ const int handle_id_;
+ int ref_count_; // Created with 1.
+
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> installing_version_;
+ scoped_refptr<ServiceWorkerVersion> waiting_version_;
+ scoped_refptr<ServiceWorkerVersion> active_version_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationHandle);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_H_
diff --git a/chromium/content/browser/service_worker/service_worker_registration_status.cc b/chromium/content/browser/service_worker/service_worker_registration_status.cc
index ee5ea906676..e67b833826d 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_status.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_status.cc
@@ -35,6 +35,14 @@ void GetServiceWorkerRegistrationStatusResponse(
*error_type = WebServiceWorkerError::ErrorTypeNotFound;
return;
+ case SERVICE_WORKER_ERROR_NETWORK:
+ *error_type = WebServiceWorkerError::ErrorTypeNetwork;
+ return;
+
+ case SERVICE_WORKER_ERROR_SECURITY:
+ *error_type = WebServiceWorkerError::ErrorTypeSecurity;
+ return;
+
case SERVICE_WORKER_ERROR_ABORT:
case SERVICE_WORKER_ERROR_IPC_FAILED:
case SERVICE_WORKER_ERROR_FAILED:
diff --git a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
index ccce6417526..cea4b47734b 100644
--- a/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -4,13 +4,14 @@
#include "content/browser/service_worker/service_worker_registration.h"
-
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -21,22 +22,69 @@ class ServiceWorkerRegistrationTest : public testing::Test {
ServiceWorkerRegistrationTest()
: io_thread_(BrowserThread::IO, &message_loop_) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
+ new MockServiceWorkerDatabaseTaskManager(
+ base::ThreadTaskRunnerHandle::Get()));
context_.reset(
new ServiceWorkerContextCore(base::FilePath(),
- base::MessageLoopProxy::current(),
- base::MessageLoopProxy::current(),
+ base::ThreadTaskRunnerHandle::Get(),
+ database_task_manager.Pass(),
+ base::ThreadTaskRunnerHandle::Get(),
+ NULL,
NULL,
NULL,
NULL));
context_ptr_ = context_->AsWeakPtr();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
context_.reset();
base::RunLoop().RunUntilIdle();
}
+ class RegistrationListener : public ServiceWorkerRegistration::Listener {
+ public:
+ RegistrationListener() {}
+ ~RegistrationListener() {
+ if (observed_registration_.get())
+ observed_registration_->RemoveListener(this);
+ }
+
+ void OnVersionAttributesChanged(
+ ServiceWorkerRegistration* registration,
+ ChangedVersionAttributesMask changed_mask,
+ const ServiceWorkerRegistrationInfo& info) override {
+ observed_registration_ = registration;
+ observed_changed_mask_ = changed_mask;
+ observed_info_ = info;
+ }
+
+ void OnRegistrationFailed(
+ ServiceWorkerRegistration* registration) override {
+ NOTREACHED();
+ }
+
+ void OnRegistrationFinishedUninstalling(
+ ServiceWorkerRegistration* registration) override {
+ NOTREACHED();
+ }
+
+ void OnUpdateFound(ServiceWorkerRegistration* registration) override {
+ NOTREACHED();
+ }
+
+ void Reset() {
+ observed_registration_ = NULL;
+ observed_changed_mask_ = ChangedVersionAttributesMask();
+ observed_info_ = ServiceWorkerRegistrationInfo();
+ }
+
+ scoped_refptr<ServiceWorkerRegistration> observed_registration_;
+ ChangedVersionAttributesMask observed_changed_mask_;
+ ServiceWorkerRegistrationInfo observed_info_;
+ };
+
protected:
scoped_ptr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
@@ -44,33 +92,100 @@ class ServiceWorkerRegistrationTest : public testing::Test {
BrowserThreadImpl io_thread_;
};
-// Make sure that activation does not leak
-TEST_F(ServiceWorkerRegistrationTest, ActivatePending) {
- int64 registration_id = -1L;
+TEST_F(ServiceWorkerRegistrationTest, SetAndUnsetVersions) {
+ const GURL kScope("http://www.example.not/");
+ const GURL kScript("http://www.example.not/service_worker.js");
+ int64 kRegistrationId = 1L;
scoped_refptr<ServiceWorkerRegistration> registration =
new ServiceWorkerRegistration(
- GURL("http://www.example.com/*"),
- GURL("http://www.example.com/service_worker.js"),
- registration_id,
+ kScope,
+ kRegistrationId,
context_ptr_);
const int64 version_1_id = 1L;
const int64 version_2_id = 2L;
- scoped_refptr<ServiceWorkerVersion> version_1 =
- new ServiceWorkerVersion(registration, version_1_id, context_ptr_);
- version_1->SetStatus(ServiceWorkerVersion::ACTIVE);
- registration->set_active_version(version_1);
+ scoped_refptr<ServiceWorkerVersion> version_1 = new ServiceWorkerVersion(
+ registration.get(), kScript, version_1_id, context_ptr_);
+ scoped_refptr<ServiceWorkerVersion> version_2 = new ServiceWorkerVersion(
+ registration.get(), kScript, version_2_id, context_ptr_);
+
+ RegistrationListener listener;
+ registration->AddListener(&listener);
+ registration->SetActiveVersion(version_1.get());
- scoped_refptr<ServiceWorkerVersion> version_2 =
- new ServiceWorkerVersion(registration, version_2_id, context_ptr_);
- registration->set_waiting_version(version_2);
+ EXPECT_EQ(version_1.get(), registration->active_version());
+ EXPECT_EQ(registration, listener.observed_registration_);
+ EXPECT_EQ(ChangedVersionAttributesMask::ACTIVE_VERSION,
+ listener.observed_changed_mask_.changed());
+ EXPECT_EQ(kScope, listener.observed_info_.pattern);
+ EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
+ EXPECT_EQ(kScript, listener.observed_info_.active_version.script_url);
+ EXPECT_EQ(listener.observed_info_.installing_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(listener.observed_info_.controlling_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ listener.Reset();
- registration->ActivateWaitingVersion();
- DCHECK_EQ(version_2, registration->active_version());
- DCHECK(version_1->HasOneRef());
- version_1 = NULL;
+ registration->SetInstallingVersion(version_2.get());
- DCHECK(!version_2->HasOneRef());
+ EXPECT_EQ(version_2.get(), registration->installing_version());
+ EXPECT_EQ(ChangedVersionAttributesMask::INSTALLING_VERSION,
+ listener.observed_changed_mask_.changed());
+ EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
+ EXPECT_EQ(version_2_id,
+ listener.observed_info_.installing_version.version_id);
+ EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(listener.observed_info_.controlling_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ listener.Reset();
+
+ registration->SetWaitingVersion(version_2.get());
+
+ EXPECT_EQ(version_2.get(), registration->waiting_version());
+ EXPECT_FALSE(registration->installing_version());
+ EXPECT_TRUE(listener.observed_changed_mask_.waiting_changed());
+ EXPECT_TRUE(listener.observed_changed_mask_.installing_changed());
+ EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
+ EXPECT_EQ(version_2_id, listener.observed_info_.waiting_version.version_id);
+ EXPECT_EQ(listener.observed_info_.installing_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(listener.observed_info_.controlling_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ listener.Reset();
+
+ registration->UnsetVersion(version_2.get());
+
+ EXPECT_FALSE(registration->waiting_version());
+ EXPECT_EQ(ChangedVersionAttributesMask::WAITING_VERSION,
+ listener.observed_changed_mask_.changed());
+ EXPECT_EQ(version_1_id, listener.observed_info_.active_version.version_id);
+ EXPECT_EQ(listener.observed_info_.waiting_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(listener.observed_info_.installing_version.version_id,
+ kInvalidServiceWorkerVersionId);
+ EXPECT_EQ(listener.observed_info_.controlling_version.version_id,
+ kInvalidServiceWorkerVersionId);
+}
+
+TEST_F(ServiceWorkerRegistrationTest, FailedRegistrationNoCrash) {
+ const GURL kScope("http://www.example.not/");
+ int64 kRegistrationId = 1L;
+ int kProviderId = 1;
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ new ServiceWorkerRegistration(
+ kScope,
+ kRegistrationId,
+ context_ptr_);
+ scoped_ptr<ServiceWorkerRegistrationHandle> handle(
+ new ServiceWorkerRegistrationHandle(context_ptr_,
+ NULL,
+ kProviderId,
+ registration.get()));
+ registration->NotifyRegistrationFailed();
+ // Don't crash when handle gets destructed.
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.cc b/chromium/content/browser/service_worker/service_worker_request_handler.cc
index a04e0116452..6c871e6cd55 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -4,16 +4,21 @@
#include "content/browser/service_worker/service_worker_request_handler.h"
+#include <string>
+
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/resource_context.h"
+#include "net/base/net_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_interceptor.h"
-#include "webkit/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_storage_context.h"
namespace content {
@@ -24,29 +29,30 @@ int kUserDataKey; // Key value is not important.
class ServiceWorkerRequestInterceptor
: public net::URLRequestInterceptor {
public:
- ServiceWorkerRequestInterceptor() {}
- virtual ~ServiceWorkerRequestInterceptor() {}
- virtual net::URLRequestJob* MaybeInterceptRequest(
+ explicit ServiceWorkerRequestInterceptor(ResourceContext* resource_context)
+ : resource_context_(resource_context) {}
+ ~ServiceWorkerRequestInterceptor() override {}
+ net::URLRequestJob* MaybeInterceptRequest(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
ServiceWorkerRequestHandler* handler =
ServiceWorkerRequestHandler::GetHandler(request);
if (!handler)
return NULL;
- return handler->MaybeCreateJob(request, network_delegate);
+ return handler->MaybeCreateJob(
+ request, network_delegate, resource_context_);
}
private:
+ ResourceContext* resource_context_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestInterceptor);
};
-bool IsMethodSupported(const std::string& method) {
- return (method == "GET") || (method == "HEAD");
-}
-
-bool IsSchemeAndMethodSupported(const net::URLRequest* request) {
- return request->url().SchemeIsHTTPOrHTTPS() &&
- IsMethodSupported(request->method());
+// This is work around to avoid hijacking CORS preflight.
+// TODO(horo): Remove this check when we implement "HTTP fetch" correctly.
+// http://fetch.spec.whatwg.org/#concept-http-fetch
+bool IsMethodSupportedForServiceWorker(const std::string& method) {
+ return method != "OPTIONS";
}
} // namespace
@@ -54,12 +60,18 @@ bool IsSchemeAndMethodSupported(const net::URLRequest* request) {
void ServiceWorkerRequestHandler::InitializeHandler(
net::URLRequest* request,
ServiceWorkerContextWrapper* context_wrapper,
- webkit_blob::BlobStorageContext* blob_storage_context,
+ storage::BlobStorageContext* blob_storage_context,
int process_id,
int provider_id,
- ResourceType::Type resource_type) {
- if (!ServiceWorkerUtils::IsFeatureEnabled() ||
- !IsSchemeAndMethodSupported(request)) {
+ bool skip_service_worker,
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ ResourceType resource_type,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ scoped_refptr<ResourceRequestBody> body) {
+ if (!request->url().SchemeIsHTTPOrHTTPS() ||
+ !IsMethodSupportedForServiceWorker(request->method())) {
return;
}
@@ -73,9 +85,22 @@ void ServiceWorkerRequestHandler::InitializeHandler(
if (!provider_host || !provider_host->IsContextAlive())
return;
+ if (skip_service_worker) {
+ if (ServiceWorkerUtils::IsMainResourceType(resource_type)) {
+ provider_host->SetDocumentUrl(net::SimplifyUrlForRequest(request->url()));
+ provider_host->SetTopmostFrameUrl(request->first_party_for_cookies());
+ }
+ return;
+ }
+
scoped_ptr<ServiceWorkerRequestHandler> handler(
- provider_host->CreateRequestHandler(resource_type,
- blob_storage_context->AsWeakPtr()));
+ provider_host->CreateRequestHandler(request_mode,
+ credentials_mode,
+ resource_type,
+ request_context_type,
+ frame_type,
+ blob_storage_context->AsWeakPtr(),
+ body));
if (!handler)
return;
@@ -84,14 +109,24 @@ void ServiceWorkerRequestHandler::InitializeHandler(
ServiceWorkerRequestHandler* ServiceWorkerRequestHandler::GetHandler(
net::URLRequest* request) {
- return reinterpret_cast<ServiceWorkerRequestHandler*>(
+ return static_cast<ServiceWorkerRequestHandler*>(
request->GetUserData(&kUserDataKey));
}
scoped_ptr<net::URLRequestInterceptor>
-ServiceWorkerRequestHandler::CreateInterceptor() {
+ServiceWorkerRequestHandler::CreateInterceptor(
+ ResourceContext* resource_context) {
return scoped_ptr<net::URLRequestInterceptor>(
- new ServiceWorkerRequestInterceptor);
+ new ServiceWorkerRequestInterceptor(resource_context));
+}
+
+bool ServiceWorkerRequestHandler::IsControlledByServiceWorker(
+ net::URLRequest* request) {
+ ServiceWorkerRequestHandler* handler = GetHandler(request);
+ if (!handler || !handler->provider_host_)
+ return false;
+ return handler->provider_host_->associated_registration() ||
+ handler->provider_host_->running_hosted_version();
}
ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
@@ -100,8 +135,8 @@ ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
ServiceWorkerRequestHandler::ServiceWorkerRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
- ResourceType::Type resource_type)
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ ResourceType resource_type)
: context_(context),
provider_host_(provider_host),
blob_storage_context_(blob_storage_context),
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.h b/chromium/content/browser/service_worker/service_worker_request_handler.h
index 0c666b548df..91afd2688e8 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -8,10 +8,15 @@
#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
#include "net/url_request/url_request_job_factory.h"
-#include "webkit/common/resource_type.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
namespace net {
class NetworkDelegate;
@@ -19,12 +24,14 @@ class URLRequest;
class URLRequestInterceptor;
}
-namespace webkit_blob {
+namespace storage {
class BlobStorageContext;
}
namespace content {
+class ResourceContext;
+class ResourceRequestBody;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class ServiceWorkerProviderHost;
@@ -43,10 +50,16 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
static void InitializeHandler(
net::URLRequest* request,
ServiceWorkerContextWrapper* context_wrapper,
- webkit_blob::BlobStorageContext* blob_storage_context,
+ storage::BlobStorageContext* blob_storage_context,
int process_id,
int provider_id,
- ResourceType::Type resource_type);
+ bool skip_service_worker,
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ ResourceType resource_type,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ scoped_refptr<ResourceRequestBody> body);
// Returns the handler attached to |request|. This may return NULL
// if no handler is attached.
@@ -54,27 +67,45 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
net::URLRequest* request);
// Creates a protocol interceptor for ServiceWorker.
- static scoped_ptr<net::URLRequestInterceptor> CreateInterceptor();
+ static scoped_ptr<net::URLRequestInterceptor> CreateInterceptor(
+ ResourceContext* resource_context);
- virtual ~ServiceWorkerRequestHandler();
+ // Returns true if the request falls into the scope of a ServiceWorker.
+ // It's only reliable after the ServiceWorkerRequestHandler MaybeCreateJob
+ // method runs to completion for this request. The AppCache handler uses
+ // this to avoid colliding with ServiceWorkers.
+ static bool IsControlledByServiceWorker(net::URLRequest* request);
+
+ ~ServiceWorkerRequestHandler() override;
// Called via custom URLRequestJobFactory.
virtual net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) = 0;
+ net::NetworkDelegate* network_delegate,
+ ResourceContext* context) = 0;
+
+ virtual void GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const = 0;
protected:
ServiceWorkerRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context,
- ResourceType::Type resource_type);
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ ResourceType resource_type);
base::WeakPtr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context_;
- ResourceType::Type resource_type_;
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
+ ResourceType resource_type_;
+ private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestHandler);
};
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
new file mode 100644
index 00000000000..fe5483de70e
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -0,0 +1,158 @@
+// Copyright 2014 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 "content/browser/service_worker/service_worker_request_handler.h"
+
+#include "base/run_loop.h"
+#include "content/browser/fileapi/mock_url_request_delegate.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/common/resource_request_body.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/url_request/url_request_context.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+int kMockRenderProcessId = 1224;
+int kMockProviderId = 1;
+
+void EmptyCallback() {
+}
+
+}
+
+class ServiceWorkerRequestHandlerTest : public testing::Test {
+ public:
+ ServiceWorkerRequestHandlerTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
+
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(kMockRenderProcessId));
+
+ // A new unstored registration/version.
+ registration_ = new ServiceWorkerRegistration(
+ GURL("http://host/scope/"), 1L, context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(registration_.get(),
+ GURL("http://host/script.js"),
+ 1L,
+ context()->AsWeakPtr());
+
+ // An empty host.
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kMockRenderProcessId, kMockProviderId, context()->AsWeakPtr(), NULL));
+ provider_host_ = host->AsWeakPtr();
+ context()->AddProviderHost(host.Pass());
+
+ context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
+ base::RunLoop().RunUntilIdle();
+
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ registration_->SetActiveVersion(version_.get());
+ context()->storage()->StoreRegistration(
+ registration_.get(),
+ version_.get(),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ provider_host_->AssociateRegistration(registration_.get());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void TearDown() override {
+ version_ = NULL;
+ registration_ = NULL;
+ helper_.reset();
+ }
+
+ ServiceWorkerContextCore* context() const { return helper_->context(); }
+ ServiceWorkerContextWrapper* context_wrapper() const {
+ return helper_->context_wrapper();
+ }
+
+ bool InitializeHandlerCheck(const std::string& url,
+ const std::string& method,
+ bool skip_service_worker,
+ ResourceType resource_type) {
+ const GURL kDocUrl(url);
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kDocUrl, net::DEFAULT_PRIORITY, &url_request_delegate_, NULL);
+ request->set_method(method);
+ ServiceWorkerRequestHandler::InitializeHandler(
+ request.get(),
+ context_wrapper(),
+ &blob_storage_context_,
+ kMockRenderProcessId,
+ kMockProviderId,
+ skip_service_worker,
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_CREDENTIALS_MODE_OMIT,
+ resource_type,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ NULL);
+ return ServiceWorkerRequestHandler::GetHandler(request.get()) != NULL;
+ }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ net::URLRequestContext url_request_context_;
+ MockURLRequestDelegate url_request_delegate_;
+ storage::BlobStorageContext blob_storage_context_;
+};
+
+TEST_F(ServiceWorkerRequestHandlerTest, InitializeHandler) {
+ EXPECT_TRUE(InitializeHandlerCheck(
+ "http://host/scope/doc", "GET", false, RESOURCE_TYPE_MAIN_FRAME));
+ EXPECT_TRUE(InitializeHandlerCheck(
+ "https://host/scope/doc", "GET", false, RESOURCE_TYPE_MAIN_FRAME));
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "ftp://host/scope/doc", "GET", false, RESOURCE_TYPE_MAIN_FRAME));
+
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "http://host/scope/doc", "OPTIONS", false, RESOURCE_TYPE_MAIN_FRAME));
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "https://host/scope/doc", "OPTIONS", false, RESOURCE_TYPE_MAIN_FRAME));
+
+ provider_host_->SetDocumentUrl(GURL(""));
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "http://host/scope/doc", "GET", true, RESOURCE_TYPE_MAIN_FRAME));
+ EXPECT_STREQ("http://host/scope/doc",
+ provider_host_->document_url().spec().c_str());
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "https://host/scope/doc", "GET", true, RESOURCE_TYPE_MAIN_FRAME));
+ EXPECT_STREQ("https://host/scope/doc",
+ provider_host_->document_url().spec().c_str());
+
+ provider_host_->SetDocumentUrl(GURL(""));
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "http://host/scope/doc", "GET", true, RESOURCE_TYPE_SUB_FRAME));
+ EXPECT_STREQ("http://host/scope/doc",
+ provider_host_->document_url().spec().c_str());
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "https://host/scope/doc", "GET", true, RESOURCE_TYPE_SUB_FRAME));
+ EXPECT_STREQ("https://host/scope/doc",
+ provider_host_->document_url().spec().c_str());
+
+ provider_host_->SetDocumentUrl(GURL(""));
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "http://host/scope/doc", "GET", true, RESOURCE_TYPE_IMAGE));
+ EXPECT_STREQ("", provider_host_->document_url().spec().c_str());
+ EXPECT_FALSE(InitializeHandlerCheck(
+ "https://host/scope/doc", "GET", true, RESOURCE_TYPE_IMAGE));
+ EXPECT_STREQ("", provider_host_->document_url().spec().c_str());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_script_cache_map.cc b/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
index 60876b8d716..062ae159a2a 100644
--- a/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
+++ b/chromium/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -16,56 +16,70 @@ ServiceWorkerScriptCacheMap::ServiceWorkerScriptCacheMap(
ServiceWorkerVersion* owner,
base::WeakPtr<ServiceWorkerContextCore> context)
: owner_(owner),
- context_(context),
- has_error_(false) {
+ context_(context) {
}
ServiceWorkerScriptCacheMap::~ServiceWorkerScriptCacheMap() {
}
-int64 ServiceWorkerScriptCacheMap::Lookup(const GURL& url) {
- ResourceIDMap::const_iterator found = resource_ids_.find(url);
- if (found == resource_ids_.end())
+int64 ServiceWorkerScriptCacheMap::LookupResourceId(const GURL& url) {
+ ResourceMap::const_iterator found = resource_map_.find(url);
+ if (found == resource_map_.end())
return kInvalidServiceWorkerResponseId;
- return found->second;
+ return found->second.resource_id;
+}
+
+int64 ServiceWorkerScriptCacheMap::LookupResourceSize(const GURL& url) {
+ ResourceMap::const_iterator found = resource_map_.find(url);
+ if (found == resource_map_.end())
+ return kInvalidServiceWorkerResponseId;
+ return found->second.size_bytes;
}
void ServiceWorkerScriptCacheMap::NotifyStartedCaching(
const GURL& url, int64 resource_id) {
- DCHECK_EQ(kInvalidServiceWorkerResponseId, Lookup(url));
- DCHECK(owner_->status() == ServiceWorkerVersion::NEW);
- resource_ids_[url] = resource_id;
- context_->storage()->StoreUncommittedReponseId(resource_id);
+ DCHECK_EQ(kInvalidServiceWorkerResponseId, LookupResourceId(url));
+ DCHECK(owner_->status() == ServiceWorkerVersion::NEW ||
+ owner_->status() == ServiceWorkerVersion::INSTALLING);
+ resource_map_[url] =
+ ServiceWorkerDatabase::ResourceRecord(resource_id, url, -1);
+ context_->storage()->StoreUncommittedResponseId(resource_id);
}
void ServiceWorkerScriptCacheMap::NotifyFinishedCaching(
- const GURL& url, bool success) {
- DCHECK_NE(kInvalidServiceWorkerResponseId, Lookup(url));
- DCHECK(owner_->status() == ServiceWorkerVersion::NEW);
- if (!success) {
- context_->storage()->DoomUncommittedResponse(Lookup(url));
- has_error_ = true;
- resource_ids_.erase(url);
+ const GURL& url,
+ int64 size_bytes,
+ const net::URLRequestStatus& status) {
+ DCHECK_NE(kInvalidServiceWorkerResponseId, LookupResourceId(url));
+ DCHECK(owner_->status() == ServiceWorkerVersion::NEW ||
+ owner_->status() == ServiceWorkerVersion::INSTALLING);
+ if (!status.is_success()) {
+ context_->storage()->DoomUncommittedResponse(LookupResourceId(url));
+ resource_map_.erase(url);
+ if (owner_->script_url() == url)
+ main_script_status_ = status;
+ } else {
+ resource_map_[url].size_bytes = size_bytes;
}
}
void ServiceWorkerScriptCacheMap::GetResources(
std::vector<ServiceWorkerDatabase::ResourceRecord>* resources) {
DCHECK(resources->empty());
- for (ResourceIDMap::const_iterator it = resource_ids_.begin();
- it != resource_ids_.end(); ++it) {
- resources->push_back(
- ServiceWorkerDatabase::ResourceRecord(it->second, it->first));
+ for (ResourceMap::const_iterator it = resource_map_.begin();
+ it != resource_map_.end();
+ ++it) {
+ resources->push_back(it->second);
}
}
void ServiceWorkerScriptCacheMap::SetResources(
const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources) {
- DCHECK(resource_ids_.empty());
+ DCHECK(resource_map_.empty());
typedef std::vector<ServiceWorkerDatabase::ResourceRecord> RecordVector;
for (RecordVector::const_iterator it = resources.begin();
it != resources.end(); ++it) {
- resource_ids_[it->url] = it->resource_id;
+ resource_map_[it->url] = *it;
}
}
diff --git a/chromium/content/browser/service_worker/service_worker_script_cache_map.h b/chromium/content/browser/service_worker/service_worker_script_cache_map.h
index 4513f3d9ea7..de814c210b1 100644
--- a/chromium/content/browser/service_worker/service_worker_script_cache_map.h
+++ b/chromium/content/browser/service_worker/service_worker_script_cache_map.h
@@ -11,6 +11,8 @@
#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_database.h"
+#include "content/common/content_export.h"
+#include "net/url_request/url_request_status.h"
class GURL;
@@ -20,18 +22,22 @@ class ServiceWorkerContextCore;
class ServiceWorkerVersion;
// Class that maintains the mapping between urls and a resource id
-// for a particular versions implicit script resources.
-class ServiceWorkerScriptCacheMap {
+// for a particular version's implicit script resources.
+class CONTENT_EXPORT ServiceWorkerScriptCacheMap {
public:
- int64 Lookup(const GURL& url);
+ int64 LookupResourceId(const GURL& url);
+ // A size of -1 means that we don't know the size yet
+ // (it has not finished caching).
+ int64 LookupResourceSize(const GURL& url);
// Used during the initial run of a new version to build the map
// of resources ids.
void NotifyStartedCaching(const GURL& url, int64 resource_id);
- void NotifyFinishedCaching(const GURL& url, bool success);
+ void NotifyFinishedCaching(const GURL& url,
+ int64 size_bytes,
+ const net::URLRequestStatus& status);
// Used to retrieve the results of the initial run of a new version.
- bool HasError() const { return has_error_; }
void GetResources(
std::vector<ServiceWorkerDatabase::ResourceRecord>* resources);
@@ -39,8 +45,14 @@ class ServiceWorkerScriptCacheMap {
void SetResources(
const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources);
+ size_t size() const { return resource_map_.size(); }
+
+ const net::URLRequestStatus& main_script_status() const {
+ return main_script_status_;
+ }
+
private:
- typedef std::map<GURL, int64> ResourceIDMap;
+ typedef std::map<GURL, ServiceWorkerDatabase::ResourceRecord> ResourceMap;
// The version objects owns its script cache and provides a rawptr to it.
friend class ServiceWorkerVersion;
@@ -51,8 +63,8 @@ class ServiceWorkerScriptCacheMap {
ServiceWorkerVersion* owner_;
base::WeakPtr<ServiceWorkerContextCore> context_;
- ResourceIDMap resource_ids_;
- bool has_error_;
+ ResourceMap resource_map_;
+ net::URLRequestStatus main_script_status_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptCacheMap);
};
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index 8a924e0c723..0a06823ca41 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -7,20 +7,26 @@
#include <string>
#include "base/bind_helpers.h"
+#include "base/debug/trace_event.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_histograms.h"
#include "content/browser/service_worker/service_worker_info.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "webkit/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
+#include "storage/browser/quota/special_storage_policy.h"
namespace content {
@@ -46,8 +52,6 @@ void CompleteFindSoon(
RunSoon(from_here, base::Bind(callback, status, registration));
}
-const base::FilePath::CharType kServiceWorkerDirectory[] =
- FILE_PATH_LITERAL("Service Worker");
const base::FilePath::CharType kDatabaseName[] =
FILE_PATH_LITERAL("Database");
const base::FilePath::CharType kDiskCacheName[] =
@@ -56,8 +60,6 @@ const base::FilePath::CharType kDiskCacheName[] =
const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
const int kMaxDiskCacheSize = 250 * 1024 * 1024;
-void EmptyCompletionCallback(int) {}
-
ServiceWorkerStatusCode DatabaseStatusToStatusCode(
ServiceWorkerDatabase::Status status) {
switch (status) {
@@ -72,6 +74,129 @@ ServiceWorkerStatusCode DatabaseStatusToStatusCode(
}
}
+class ResponseComparer : public base::RefCounted<ResponseComparer> {
+ public:
+ ResponseComparer(
+ base::WeakPtr<ServiceWorkerStorage> owner,
+ scoped_ptr<ServiceWorkerResponseReader> lhs,
+ scoped_ptr<ServiceWorkerResponseReader> rhs,
+ const ServiceWorkerStorage::CompareCallback& callback)
+ : owner_(owner),
+ completion_callback_(callback),
+ lhs_reader_(lhs.release()),
+ rhs_reader_(rhs.release()),
+ completion_count_(0),
+ previous_result_(0) {
+ }
+
+ void Start();
+
+ private:
+ friend class base::RefCounted<ResponseComparer>;
+
+ static const int kBufferSize = 16 * 1024;
+
+ ~ResponseComparer() {}
+ void ReadInfos();
+ void OnReadInfoComplete(int result);
+ void ReadSomeData();
+ void OnReadDataComplete(int result);
+
+ base::WeakPtr<ServiceWorkerStorage> owner_;
+ ServiceWorkerStorage::CompareCallback completion_callback_;
+ scoped_ptr<ServiceWorkerResponseReader> lhs_reader_;
+ scoped_refptr<HttpResponseInfoIOBuffer> lhs_info_;
+ scoped_refptr<net::IOBuffer> lhs_buffer_;
+ scoped_ptr<ServiceWorkerResponseReader> rhs_reader_;
+ scoped_refptr<HttpResponseInfoIOBuffer> rhs_info_;
+ scoped_refptr<net::IOBuffer> rhs_buffer_;
+ int completion_count_;
+ int previous_result_;
+ DISALLOW_COPY_AND_ASSIGN(ResponseComparer);
+};
+
+void ResponseComparer::Start() {
+ lhs_buffer_ = new net::IOBuffer(kBufferSize);
+ lhs_info_ = new HttpResponseInfoIOBuffer();
+ rhs_buffer_ = new net::IOBuffer(kBufferSize);
+ rhs_info_ = new HttpResponseInfoIOBuffer();
+
+ ReadInfos();
+}
+
+void ResponseComparer::ReadInfos() {
+ lhs_reader_->ReadInfo(
+ lhs_info_.get(), base::Bind(&ResponseComparer::OnReadInfoComplete, this));
+ rhs_reader_->ReadInfo(
+ rhs_info_.get(), base::Bind(&ResponseComparer::OnReadInfoComplete, this));
+}
+
+void ResponseComparer::OnReadInfoComplete(int result) {
+ if (completion_callback_.is_null() || !owner_)
+ return;
+ if (result < 0) {
+ completion_callback_.Run(SERVICE_WORKER_ERROR_FAILED, false);
+ completion_callback_.Reset();
+ return;
+ }
+ if (++completion_count_ != 2)
+ return;
+
+ if (lhs_info_->response_data_size != rhs_info_->response_data_size) {
+ completion_callback_.Run(SERVICE_WORKER_OK, false);
+ return;
+ }
+ ReadSomeData();
+}
+
+void ResponseComparer::ReadSomeData() {
+ completion_count_ = 0;
+ lhs_reader_->ReadData(
+ lhs_buffer_.get(),
+ kBufferSize,
+ base::Bind(&ResponseComparer::OnReadDataComplete, this));
+ rhs_reader_->ReadData(
+ rhs_buffer_.get(),
+ kBufferSize,
+ base::Bind(&ResponseComparer::OnReadDataComplete, this));
+}
+
+void ResponseComparer::OnReadDataComplete(int result) {
+ if (completion_callback_.is_null() || !owner_)
+ return;
+ if (result < 0) {
+ completion_callback_.Run(SERVICE_WORKER_ERROR_FAILED, false);
+ completion_callback_.Reset();
+ return;
+ }
+ if (++completion_count_ != 2) {
+ previous_result_ = result;
+ return;
+ }
+
+ // TODO(michaeln): Probably shouldn't assume that the amounts read from
+ // each reader will always be the same. This would wrongly signal false
+ // in that case.
+ if (result != previous_result_) {
+ completion_callback_.Run(SERVICE_WORKER_OK, false);
+ return;
+ }
+
+ if (result == 0) {
+ completion_callback_.Run(SERVICE_WORKER_OK, true);
+ return;
+ }
+
+ int compare_result =
+ memcmp(lhs_buffer_->data(), rhs_buffer_->data(), result);
+ if (compare_result != 0) {
+ completion_callback_.Run(SERVICE_WORKER_OK, false);
+ return;
+ }
+
+ ReadSomeData();
+}
+
} // namespace
ServiceWorkerStorage::InitialData::InitialData()
@@ -83,30 +208,49 @@ ServiceWorkerStorage::InitialData::InitialData()
ServiceWorkerStorage::InitialData::~InitialData() {
}
-ServiceWorkerStorage::ServiceWorkerStorage(
- const base::FilePath& path,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::SequencedTaskRunner* database_task_runner,
- base::MessageLoopProxy* disk_cache_thread,
- quota::QuotaManagerProxy* quota_manager_proxy)
- : next_registration_id_(kInvalidServiceWorkerRegistrationId),
- next_version_id_(kInvalidServiceWorkerVersionId),
- next_resource_id_(kInvalidServiceWorkerResourceId),
- state_(UNINITIALIZED),
- context_(context),
- database_task_runner_(database_task_runner),
- disk_cache_thread_(disk_cache_thread),
- quota_manager_proxy_(quota_manager_proxy),
- is_purge_pending_(false),
- weak_factory_(this) {
- if (!path.empty())
- path_ = path.Append(kServiceWorkerDirectory);
- database_.reset(new ServiceWorkerDatabase(GetDatabasePath()));
+ServiceWorkerStorage::
+DidDeleteRegistrationParams::DidDeleteRegistrationParams()
+ : registration_id(kInvalidServiceWorkerRegistrationId) {
+}
+
+ServiceWorkerStorage::
+DidDeleteRegistrationParams::~DidDeleteRegistrationParams() {
}
ServiceWorkerStorage::~ServiceWorkerStorage() {
+ ClearSessionOnlyOrigins();
weak_factory_.InvalidateWeakPtrs();
- database_task_runner_->DeleteSoon(FROM_HERE, database_.release());
+ database_task_manager_->GetTaskRunner()->DeleteSoon(FROM_HERE,
+ database_.release());
+}
+
+// static
+scoped_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
+ const base::FilePath& path,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy) {
+ return make_scoped_ptr(new ServiceWorkerStorage(path,
+ context,
+ database_task_manager.Pass(),
+ disk_cache_thread,
+ quota_manager_proxy,
+ special_storage_policy));
+}
+
+// static
+scoped_ptr<ServiceWorkerStorage> ServiceWorkerStorage::Create(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerStorage* old_storage) {
+ return make_scoped_ptr(
+ new ServiceWorkerStorage(old_storage->path_,
+ context,
+ old_storage->database_task_manager_->Clone(),
+ old_storage->disk_cache_thread_,
+ old_storage->quota_manager_proxy_.get(),
+ old_storage->special_storage_policy_.get()));
}
void ServiceWorkerStorage::FindRegistrationForDocument(
@@ -120,6 +264,11 @@ void ServiceWorkerStorage::FindRegistrationForDocument(
CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
SERVICE_WORKER_ERROR_FAILED, callback);
}
+ TRACE_EVENT_INSTANT1(
+ "ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument:LazyInitialize",
+ TRACE_EVENT_SCOPE_THREAD,
+ "URL", document_url.spec());
return;
}
DCHECK_EQ(INITIALIZED, state_);
@@ -129,15 +278,29 @@ void ServiceWorkerStorage::FindRegistrationForDocument(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForDocument(document_url);
- CompleteFindNow(
- installing_registration,
- installing_registration ?
- SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
- callback);
+ ServiceWorkerStatusCode status = installing_registration.get() ?
+ SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND;
+ TRACE_EVENT_INSTANT2(
+ "ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument:CheckInstalling",
+ TRACE_EVENT_SCOPE_THREAD,
+ "URL", document_url.spec(),
+ "Status", ServiceWorkerStatusToString(status));
+ CompleteFindNow(installing_registration,
+ status,
+ callback);
return;
}
- database_task_runner_->PostTask(
+ // To connect this TRACE_EVENT with the callback, TimeTicks is used for
+ // callback id.
+ int64 callback_id = base::TimeTicks::Now().ToInternalValue();
+ TRACE_EVENT_ASYNC_BEGIN1(
+ "ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument",
+ callback_id,
+ "URL", document_url.spec());
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(
&FindForDocumentInDB,
@@ -145,7 +308,10 @@ void ServiceWorkerStorage::FindRegistrationForDocument(
base::MessageLoopProxy::current(),
document_url,
base::Bind(&ServiceWorkerStorage::DidFindRegistrationForDocument,
- weak_factory_.GetWeakPtr(), document_url, callback)));
+ weak_factory_.GetWeakPtr(),
+ document_url,
+ callback,
+ callback_id)));
}
void ServiceWorkerStorage::FindRegistrationForPattern(
@@ -167,15 +333,16 @@ void ServiceWorkerStorage::FindRegistrationForPattern(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForPattern(scope);
- CompleteFindSoon(
- FROM_HERE, installing_registration,
- installing_registration ?
- SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
- callback);
+ CompleteFindSoon(FROM_HERE,
+ installing_registration,
+ installing_registration.get()
+ ? SERVICE_WORKER_OK
+ : SERVICE_WORKER_ERROR_NOT_FOUND,
+ callback);
return;
}
- database_task_runner_->PostTask(
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(
&FindForPatternInDB,
@@ -186,6 +353,22 @@ void ServiceWorkerStorage::FindRegistrationForPattern(
weak_factory_.GetWeakPtr(), scope, callback)));
}
+ServiceWorkerRegistration* ServiceWorkerStorage::GetUninstallingRegistration(
+ const GURL& scope) {
+ if (state_ != INITIALIZED || !context_)
+ return NULL;
+ for (RegistrationRefsById::const_iterator it =
+ uninstalling_registrations_.begin();
+ it != uninstalling_registrations_.end();
+ ++it) {
+ if (it->second->pattern() == scope) {
+ DCHECK(it->second->is_uninstalling());
+ return it->second.get();
+ }
+ }
+ return NULL;
+}
+
void ServiceWorkerStorage::FindRegistrationForId(
int64 registration_id,
const GURL& origin,
@@ -206,22 +389,22 @@ void ServiceWorkerStorage::FindRegistrationForId(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForId(registration_id);
- CompleteFindNow(
- installing_registration,
- installing_registration ?
- SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
- callback);
+ CompleteFindNow(installing_registration,
+ installing_registration.get()
+ ? SERVICE_WORKER_OK
+ : SERVICE_WORKER_ERROR_NOT_FOUND,
+ callback);
return;
}
scoped_refptr<ServiceWorkerRegistration> registration =
context_->GetLiveRegistration(registration_id);
- if (registration) {
+ if (registration.get()) {
CompleteFindNow(registration, SERVICE_WORKER_OK, callback);
return;
}
- database_task_runner_->PostTask(
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&FindForIdInDB,
database_.get(),
@@ -246,7 +429,7 @@ void ServiceWorkerStorage::GetAllRegistrations(
RegistrationList* registrations = new RegistrationList;
PostTaskAndReplyWithResult(
- database_task_runner_,
+ database_task_manager_->GetTaskRunner(),
FROM_HERE,
base::Bind(&ServiceWorkerDatabase::GetAllRegistrations,
base::Unretained(database_.get()),
@@ -264,8 +447,8 @@ void ServiceWorkerStorage::StoreRegistration(
DCHECK(registration);
DCHECK(version);
- DCHECK(state_ == INITIALIZED || state_ == DISABLED);
- if (state_ != INITIALIZED || !context_) {
+ DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
+ if (IsDisabled() || !context_) {
RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
return;
}
@@ -273,24 +456,37 @@ void ServiceWorkerStorage::StoreRegistration(
ServiceWorkerDatabase::RegistrationData data;
data.registration_id = registration->id();
data.scope = registration->pattern();
- data.script = registration->script_url();
+ data.script = version->script_url();
data.has_fetch_handler = true;
data.version_id = version->version_id();
- data.last_update_check = base::Time::Now();
- data.is_active = false; // initially stored in the waiting state
+ data.last_update_check = registration->last_update_check();
+ data.is_active = (version == registration->active_version());
ResourceList resources;
version->script_cache_map()->GetResources(&resources);
- database_task_runner_->PostTask(
+ uint64 resources_total_size_bytes = 0;
+ for (const auto& resource : resources) {
+ resources_total_size_bytes += resource.size_bytes;
+ }
+ data.resources_total_size_bytes = resources_total_size_bytes;
+
+ if (!has_checked_for_stale_resources_)
+ DeleteStaleResources();
+
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&WriteRegistrationInDB,
database_.get(),
base::MessageLoopProxy::current(),
- data, resources,
+ data,
+ resources,
base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
weak_factory_.GetWeakPtr(),
- callback)));
+ callback,
+ data)));
+
+ registration->set_is_deleted(false);
}
void ServiceWorkerStorage::UpdateToActiveState(
@@ -298,47 +494,75 @@ void ServiceWorkerStorage::UpdateToActiveState(
const StatusCallback& callback) {
DCHECK(registration);
- DCHECK(state_ == INITIALIZED || state_ == DISABLED);
- if (state_ != INITIALIZED || !context_) {
+ DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
+ if (IsDisabled() || !context_) {
RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
return;
}
PostTaskAndReplyWithResult(
- database_task_runner_,
+ database_task_manager_->GetTaskRunner(),
FROM_HERE,
base::Bind(&ServiceWorkerDatabase::UpdateVersionToActive,
base::Unretained(database_.get()),
registration->id(),
- registration->script_url().GetOrigin()),
+ registration->pattern().GetOrigin()),
base::Bind(&ServiceWorkerStorage::DidUpdateToActiveState,
weak_factory_.GetWeakPtr(),
callback));
}
+void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
+ ServiceWorkerRegistration* registration) {
+ DCHECK(registration);
+
+ DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
+ if (IsDisabled() || !context_)
+ return;
+
+ database_task_manager_->GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(&ServiceWorkerDatabase::UpdateLastCheckTime),
+ base::Unretained(database_.get()),
+ registration->id(),
+ registration->pattern().GetOrigin(),
+ registration->last_update_check()));
+}
+
void ServiceWorkerStorage::DeleteRegistration(
int64 registration_id,
const GURL& origin,
const StatusCallback& callback) {
- DCHECK(state_ == INITIALIZED || state_ == DISABLED);
- if (state_ != INITIALIZED || !context_) {
+ DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
+ if (IsDisabled() || !context_) {
RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
return;
}
- database_task_runner_->PostTask(
+ if (!has_checked_for_stale_resources_)
+ DeleteStaleResources();
+
+ DidDeleteRegistrationParams params;
+ params.registration_id = registration_id;
+ params.origin = origin;
+ params.callback = callback;
+
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&DeleteRegistrationFromDB,
database_.get(),
base::MessageLoopProxy::current(),
registration_id, origin,
base::Bind(&ServiceWorkerStorage::DidDeleteRegistration,
- weak_factory_.GetWeakPtr(), origin, callback)));
+ weak_factory_.GetWeakPtr(), params)));
- // TODO(michaeln): Either its instance should also be
- // removed from liveregistrations map or the live object
- // should marked as deleted in some way and not 'findable'
- // thereafter.
+ // The registration should no longer be findable.
+ pending_deletions_.insert(registration_id);
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(registration_id);
+ if (registration)
+ registration->set_is_deleted(true);
}
scoped_ptr<ServiceWorkerResponseReader>
@@ -353,9 +577,14 @@ ServiceWorkerStorage::CreateResponseWriter(int64 response_id) {
new ServiceWorkerResponseWriter(response_id, disk_cache()));
}
-void ServiceWorkerStorage::StoreUncommittedReponseId(int64 id) {
+void ServiceWorkerStorage::StoreUncommittedResponseId(int64 id) {
DCHECK_NE(kInvalidServiceWorkerResponseId, id);
- database_task_runner_->PostTask(
+ DCHECK_EQ(INITIALIZED, state_);
+
+ if (!has_checked_for_stale_resources_)
+ DeleteStaleResources();
+
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(
&ServiceWorkerDatabase::WriteUncommittedResourceIds),
@@ -365,7 +594,7 @@ void ServiceWorkerStorage::StoreUncommittedReponseId(int64 id) {
void ServiceWorkerStorage::DoomUncommittedResponse(int64 id) {
DCHECK_NE(kInvalidServiceWorkerResponseId, id);
- database_task_runner_->PostTask(
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(
&ServiceWorkerDatabase::PurgeUncommittedResourceIds),
@@ -374,6 +603,32 @@ void ServiceWorkerStorage::DoomUncommittedResponse(int64 id) {
StartPurgingResources(std::vector<int64>(1, id));
}
+void ServiceWorkerStorage::CompareScriptResources(
+ int64 lhs_id, int64 rhs_id,
+ const CompareCallback& callback) {
+ DCHECK(!callback.is_null());
+ scoped_refptr<ResponseComparer> comparer =
+ new ResponseComparer(weak_factory_.GetWeakPtr(),
+ CreateResponseReader(lhs_id),
+ CreateResponseReader(rhs_id),
+ callback);
+ comparer->Start(); // It deletes itself when done.
+}
+
+void ServiceWorkerStorage::DeleteAndStartOver(const StatusCallback& callback) {
+ Disable();
+
+ // Delete the database on the database thread.
+ PostTaskAndReplyWithResult(
+ database_task_manager_->GetTaskRunner(),
+ FROM_HERE,
+ base::Bind(&ServiceWorkerDatabase::DestroyDatabase,
+ base::Unretained(database_.get())),
+ base::Bind(&ServiceWorkerStorage::DidDeleteDatabase,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
int64 ServiceWorkerStorage::NewRegistrationId() {
if (state_ == DISABLED)
return kInvalidServiceWorkerRegistrationId;
@@ -397,6 +652,8 @@ int64 ServiceWorkerStorage::NewResourceId() {
void ServiceWorkerStorage::NotifyInstallingRegistration(
ServiceWorkerRegistration* registration) {
+ DCHECK(installing_registrations_.find(registration->id()) ==
+ installing_registrations_.end());
installing_registrations_[registration->id()] = registration;
}
@@ -413,27 +670,78 @@ void ServiceWorkerStorage::NotifyDoneInstallingRegistration(
for (size_t i = 0; i < resources.size(); ++i)
ids.insert(resources[i].resource_id);
- database_task_runner_->PostTask(
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(
&ServiceWorkerDatabase::PurgeUncommittedResourceIds),
base::Unretained(database_.get()),
ids));
-
- StartPurgingResources(resources);
}
}
+void ServiceWorkerStorage::NotifyUninstallingRegistration(
+ ServiceWorkerRegistration* registration) {
+ DCHECK(uninstalling_registrations_.find(registration->id()) ==
+ uninstalling_registrations_.end());
+ uninstalling_registrations_[registration->id()] = registration;
+}
+
+void ServiceWorkerStorage::NotifyDoneUninstallingRegistration(
+ ServiceWorkerRegistration* registration) {
+ uninstalling_registrations_.erase(registration->id());
+}
+
+void ServiceWorkerStorage::Disable() {
+ state_ = DISABLED;
+ if (disk_cache_)
+ disk_cache_->Disable();
+}
+
+bool ServiceWorkerStorage::IsDisabled() const {
+ return state_ == DISABLED;
+}
+
+void ServiceWorkerStorage::PurgeResources(const ResourceList& resources) {
+ if (!has_checked_for_stale_resources_)
+ DeleteStaleResources();
+ StartPurgingResources(resources);
+}
+
+ServiceWorkerStorage::ServiceWorkerStorage(
+ const base::FilePath& path,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy)
+ : next_registration_id_(kInvalidServiceWorkerRegistrationId),
+ next_version_id_(kInvalidServiceWorkerVersionId),
+ next_resource_id_(kInvalidServiceWorkerResourceId),
+ state_(UNINITIALIZED),
+ path_(path),
+ context_(context),
+ database_task_manager_(database_task_manager.Pass()),
+ disk_cache_thread_(disk_cache_thread),
+ quota_manager_proxy_(quota_manager_proxy),
+ special_storage_policy_(special_storage_policy),
+ is_purge_pending_(false),
+ has_checked_for_stale_resources_(false),
+ weak_factory_(this) {
+ database_.reset(new ServiceWorkerDatabase(GetDatabasePath()));
+}
+
base::FilePath ServiceWorkerStorage::GetDatabasePath() {
if (path_.empty())
return base::FilePath();
- return path_.Append(kDatabaseName);
+ return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ .Append(kDatabaseName);
}
base::FilePath ServiceWorkerStorage::GetDiskCachePath() {
if (path_.empty())
return base::FilePath();
- return path_.Append(kDiskCacheName);
+ return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
+ .Append(kDiskCacheName);
}
bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
@@ -454,7 +762,7 @@ bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
}
state_ = INITIALIZING;
- database_task_runner_->PostTask(
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&ReadInitialDataFromDB,
database_.get(),
@@ -477,10 +785,9 @@ void ServiceWorkerStorage::DidReadInitialData(
registered_origins_.swap(data->origins);
state_ = INITIALIZED;
} else {
- // TODO(nhiroki): If status==STATUS_ERROR_CORRUPTED, do corruption recovery
- // (http://crbug.com/371675).
- DLOG(WARNING) << "Failed to initialize: " << status;
- state_ = DISABLED;
+ DVLOG(2) << "Failed to initialize: "
+ << ServiceWorkerDatabase::StatusToString(status);
+ ScheduleDeleteAndStartOver();
}
for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin();
@@ -493,11 +800,17 @@ void ServiceWorkerStorage::DidReadInitialData(
void ServiceWorkerStorage::DidFindRegistrationForDocument(
const GURL& document_url,
const FindRegistrationCallback& callback,
+ int64 callback_id,
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status) {
if (status == ServiceWorkerDatabase::STATUS_OK) {
- callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources));
+ ReturnFoundRegistration(callback, data, resources);
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument",
+ callback_id,
+ "Status", ServiceWorkerDatabase::StatusToString(status));
return;
}
@@ -505,15 +818,29 @@ void ServiceWorkerStorage::DidFindRegistrationForDocument(
// Look for something currently being installed.
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForDocument(document_url);
- callback.Run(installing_registration ?
- SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
- installing_registration);
+ ServiceWorkerStatusCode installing_status = installing_registration.get() ?
+ SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND;
+ callback.Run(installing_status, installing_registration);
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument",
+ callback_id,
+ "Status", ServiceWorkerDatabase::StatusToString(status),
+ "Info",
+ (installing_status == SERVICE_WORKER_OK) ?
+ "Installing registration is found" :
+ "Any registrations are not found");
return;
}
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
+ ScheduleDeleteAndStartOver();
callback.Run(DatabaseStatusToStatusCode(status),
scoped_refptr<ServiceWorkerRegistration>());
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker",
+ "ServiceWorkerStorage::FindRegistrationForDocument",
+ callback_id,
+ "Status", ServiceWorkerDatabase::StatusToString(status));
}
void ServiceWorkerStorage::DidFindRegistrationForPattern(
@@ -523,20 +850,20 @@ void ServiceWorkerStorage::DidFindRegistrationForPattern(
const ResourceList& resources,
ServiceWorkerDatabase::Status status) {
if (status == ServiceWorkerDatabase::STATUS_OK) {
- callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources));
+ ReturnFoundRegistration(callback, data, resources);
return;
}
if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
scoped_refptr<ServiceWorkerRegistration> installing_registration =
FindInstallingRegistrationForPattern(scope);
- callback.Run(installing_registration ?
- SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
- installing_registration);
+ callback.Run(installing_registration.get() ? SERVICE_WORKER_OK
+ : SERVICE_WORKER_ERROR_NOT_FOUND,
+ installing_registration);
return;
}
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
+ ScheduleDeleteAndStartOver();
callback.Run(DatabaseStatusToStatusCode(status),
scoped_refptr<ServiceWorkerRegistration>());
}
@@ -547,22 +874,44 @@ void ServiceWorkerStorage::DidFindRegistrationForId(
const ResourceList& resources,
ServiceWorkerDatabase::Status status) {
if (status == ServiceWorkerDatabase::STATUS_OK) {
- callback.Run(SERVICE_WORKER_OK,
- GetOrCreateRegistration(data, resources));
+ ReturnFoundRegistration(callback, data, resources);
return;
}
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
+
+ if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
+ // TODO(nhiroki): Find a registration in |installing_registrations_|.
+ callback.Run(DatabaseStatusToStatusCode(status),
+ scoped_refptr<ServiceWorkerRegistration>());
+ return;
+ }
+
+ ScheduleDeleteAndStartOver();
callback.Run(DatabaseStatusToStatusCode(status),
scoped_refptr<ServiceWorkerRegistration>());
}
+void ServiceWorkerStorage::ReturnFoundRegistration(
+ const FindRegistrationCallback& callback,
+ const ServiceWorkerDatabase::RegistrationData& data,
+ const ResourceList& resources) {
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ GetOrCreateRegistration(data, resources);
+ if (registration->is_deleted()) {
+ // It's past the point of no return and no longer findable.
+ callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND, NULL);
+ return;
+ }
+ callback.Run(SERVICE_WORKER_OK, registration);
+}
+
void ServiceWorkerStorage::DidGetAllRegistrations(
const GetAllRegistrationInfosCallback& callback,
RegistrationList* registrations,
ServiceWorkerDatabase::Status status) {
DCHECK(registrations);
- if (status != ServiceWorkerDatabase::STATUS_OK) {
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
+ if (status != ServiceWorkerDatabase::STATUS_OK &&
+ status != ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
+ ScheduleDeleteAndStartOver();
callback.Run(std::vector<ServiceWorkerRegistrationInfo>());
return;
}
@@ -570,26 +919,26 @@ void ServiceWorkerStorage::DidGetAllRegistrations(
// Add all stored registrations.
std::set<int64> pushed_registrations;
std::vector<ServiceWorkerRegistrationInfo> infos;
- for (RegistrationList::const_iterator it = registrations->begin();
- it != registrations->end(); ++it) {
+ for (const auto& registration_data : *registrations) {
const bool inserted =
- pushed_registrations.insert(it->registration_id).second;
+ pushed_registrations.insert(registration_data.registration_id).second;
DCHECK(inserted);
ServiceWorkerRegistration* registration =
- context_->GetLiveRegistration(it->registration_id);
+ context_->GetLiveRegistration(registration_data.registration_id);
if (registration) {
infos.push_back(registration->GetInfo());
continue;
}
ServiceWorkerRegistrationInfo info;
- info.pattern = it->scope;
- info.script_url = it->script;
- info.registration_id = it->registration_id;
+ info.pattern = registration_data.scope;
+ info.registration_id = registration_data.registration_id;
+ info.stored_version_size_bytes =
+ registration_data.resources_total_size_bytes;
if (ServiceWorkerVersion* version =
- context_->GetLiveVersion(it->version_id)) {
- if (it->is_active)
+ context_->GetLiveVersion(registration_data.version_id)) {
+ if (registration_data.is_active)
info.active_version = version->GetInfo();
else
info.waiting_version = version->GetInfo();
@@ -597,14 +946,12 @@ void ServiceWorkerStorage::DidGetAllRegistrations(
continue;
}
- if (it->is_active) {
- info.active_version.is_null = false;
- info.active_version.status = ServiceWorkerVersion::ACTIVE;
- info.active_version.version_id = it->version_id;
+ if (registration_data.is_active) {
+ info.active_version.status = ServiceWorkerVersion::ACTIVATED;
+ info.active_version.version_id = registration_data.version_id;
} else {
- info.waiting_version.is_null = false;
info.waiting_version.status = ServiceWorkerVersion::INSTALLED;
- info.waiting_version.version_id = it->version_id;
+ info.waiting_version.version_id = registration_data.version_id;
}
infos.push_back(info);
}
@@ -622,41 +969,74 @@ void ServiceWorkerStorage::DidGetAllRegistrations(
void ServiceWorkerStorage::DidStoreRegistration(
const StatusCallback& callback,
+ const ServiceWorkerDatabase::RegistrationData& new_version,
const GURL& origin,
+ const ServiceWorkerDatabase::RegistrationData& deleted_version,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status) {
if (status != ServiceWorkerDatabase::STATUS_OK) {
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
+ ScheduleDeleteAndStartOver();
callback.Run(DatabaseStatusToStatusCode(status));
return;
}
registered_origins_.insert(origin);
+
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ context_->GetLiveRegistration(new_version.registration_id);
+ registration->set_resources_total_size_bytes(
+ new_version.resources_total_size_bytes);
+ if (quota_manager_proxy_.get()) {
+ // Can be nullptr in tests.
+ quota_manager_proxy_->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorker,
+ origin,
+ storage::StorageType::kStorageTypeTemporary,
+ new_version.resources_total_size_bytes -
+ deleted_version.resources_total_size_bytes);
+ }
+
callback.Run(SERVICE_WORKER_OK);
- StartPurgingResources(newly_purgeable_resources);
+
+ if (!context_ || !context_->GetLiveVersion(deleted_version.version_id))
+ StartPurgingResources(newly_purgeable_resources);
}
void ServiceWorkerStorage::DidUpdateToActiveState(
const StatusCallback& callback,
ServiceWorkerDatabase::Status status) {
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
+ if (status != ServiceWorkerDatabase::STATUS_OK &&
+ status != ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
+ ScheduleDeleteAndStartOver();
+ }
callback.Run(DatabaseStatusToStatusCode(status));
}
void ServiceWorkerStorage::DidDeleteRegistration(
- const GURL& origin,
- const StatusCallback& callback,
+ const DidDeleteRegistrationParams& params,
bool origin_is_deletable,
+ const ServiceWorkerDatabase::RegistrationData& deleted_version,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status) {
+ pending_deletions_.erase(params.registration_id);
if (status != ServiceWorkerDatabase::STATUS_OK) {
- // TODO(nhiroki): Handle database error (http://crbug.com/371675).
- callback.Run(DatabaseStatusToStatusCode(status));
+ ScheduleDeleteAndStartOver();
+ params.callback.Run(DatabaseStatusToStatusCode(status));
return;
}
+ if (quota_manager_proxy_.get()) {
+ // Can be nullptr in tests.
+ quota_manager_proxy_->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorker,
+ params.origin,
+ storage::StorageType::kStorageTypeTemporary,
+ -deleted_version.resources_total_size_bytes);
+ }
if (origin_is_deletable)
- registered_origins_.erase(origin);
- callback.Run(SERVICE_WORKER_OK);
- StartPurgingResources(newly_purgeable_resources);
+ registered_origins_.erase(params.origin);
+ params.callback.Run(SERVICE_WORKER_OK);
+
+ if (!context_ || !context_->GetLiveVersion(deleted_version.version_id))
+ StartPurgingResources(newly_purgeable_resources);
}
scoped_refptr<ServiceWorkerRegistration>
@@ -665,28 +1045,34 @@ ServiceWorkerStorage::GetOrCreateRegistration(
const ResourceList& resources) {
scoped_refptr<ServiceWorkerRegistration> registration =
context_->GetLiveRegistration(data.registration_id);
- if (registration)
+ if (registration.get())
return registration;
registration = new ServiceWorkerRegistration(
- data.scope, data.script, data.registration_id, context_);
+ data.scope, data.registration_id, context_);
+ registration->set_resources_total_size_bytes(data.resources_total_size_bytes);
+ registration->set_last_update_check(data.last_update_check);
+ if (pending_deletions_.find(data.registration_id) !=
+ pending_deletions_.end()) {
+ registration->set_is_deleted(true);
+ }
scoped_refptr<ServiceWorkerVersion> version =
context_->GetLiveVersion(data.version_id);
- if (!version) {
- version = new ServiceWorkerVersion(registration, data.version_id, context_);
+ if (!version.get()) {
+ version = new ServiceWorkerVersion(
+ registration.get(), data.script, data.version_id, context_);
version->SetStatus(data.is_active ?
- ServiceWorkerVersion::ACTIVE : ServiceWorkerVersion::INSTALLED);
+ ServiceWorkerVersion::ACTIVATED : ServiceWorkerVersion::INSTALLED);
version->script_cache_map()->SetResources(resources);
}
- if (version->status() == ServiceWorkerVersion::ACTIVE)
- registration->set_active_version(version);
+ if (version->status() == ServiceWorkerVersion::ACTIVATED)
+ registration->SetActiveVersion(version.get());
else if (version->status() == ServiceWorkerVersion::INSTALLED)
- registration->set_waiting_version(version);
+ registration->SetWaitingVersion(version.get());
else
NOTREACHED();
- // TODO(michaeln): Hmmm, what if DeleteReg was invoked after
- // the Find result we're returning here? NOTREACHED condition?
+
return registration;
}
@@ -704,7 +1090,7 @@ ServiceWorkerStorage::FindInstallingRegistrationForDocument(
installing_registrations_.begin();
it != installing_registrations_.end(); ++it) {
if (matcher.MatchLongest(it->second->pattern()))
- match = it->second;
+ match = it->second.get();
}
return match;
}
@@ -716,7 +1102,7 @@ ServiceWorkerStorage::FindInstallingRegistrationForPattern(
installing_registrations_.begin();
it != installing_registrations_.end(); ++it) {
if (it->second->pattern() == scope)
- return it->second;
+ return it->second.get();
}
return NULL;
}
@@ -728,7 +1114,7 @@ ServiceWorkerStorage::FindInstallingRegistrationForId(
installing_registrations_.find(registration_id);
if (found == installing_registrations_.end())
return NULL;
- return found->second;
+ return found->second.get();
}
ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
@@ -739,16 +1125,17 @@ ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
base::FilePath path = GetDiskCachePath();
if (path.empty()) {
- int rv = disk_cache_->InitWithMemBackend(
- kMaxMemDiskCacheSize,
- base::Bind(&EmptyCompletionCallback));
+ int rv = disk_cache_->InitWithMemBackend(kMaxMemDiskCacheSize,
+ net::CompletionCallback());
DCHECK_EQ(net::OK, rv);
return disk_cache_.get();
}
int rv = disk_cache_->InitWithDiskBackend(
- path, kMaxDiskCacheSize, false,
- disk_cache_thread_.get(),
+ path,
+ kMaxDiskCacheSize,
+ false,
+ disk_cache_thread_,
base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized,
weak_factory_.GetWeakPtr()));
if (rv != net::ERR_IO_PENDING)
@@ -761,36 +1148,36 @@ void ServiceWorkerStorage::OnDiskCacheInitialized(int rv) {
if (rv != net::OK) {
LOG(ERROR) << "Failed to open the serviceworker diskcache: "
<< net::ErrorToString(rv);
- // TODO(michaeln): DeleteAndStartOver()
- disk_cache_->Disable();
- state_ = DISABLED;
+ ScheduleDeleteAndStartOver();
}
- ServiceWorkerHistograms::CountInitDiskCacheResult(rv == net::OK);
+ ServiceWorkerMetrics::CountInitDiskCacheResult(rv == net::OK);
}
void ServiceWorkerStorage::StartPurgingResources(
const std::vector<int64>& ids) {
+ DCHECK(has_checked_for_stale_resources_);
for (size_t i = 0; i < ids.size(); ++i)
- purgeable_reource_ids_.push_back(ids[i]);
+ purgeable_resource_ids_.push_back(ids[i]);
ContinuePurgingResources();
}
void ServiceWorkerStorage::StartPurgingResources(
const ResourceList& resources) {
+ DCHECK(has_checked_for_stale_resources_);
for (size_t i = 0; i < resources.size(); ++i)
- purgeable_reource_ids_.push_back(resources[i].resource_id);
+ purgeable_resource_ids_.push_back(resources[i].resource_id);
ContinuePurgingResources();
}
void ServiceWorkerStorage::ContinuePurgingResources() {
- if (purgeable_reource_ids_.empty() || is_purge_pending_)
+ if (purgeable_resource_ids_.empty() || is_purge_pending_)
return;
// Do one at a time until we're done, use RunSoon to avoid recursion when
// DoomEntry returns immediately.
is_purge_pending_ = true;
- int64 id = purgeable_reource_ids_.front();
- purgeable_reource_ids_.pop_front();
+ int64 id = purgeable_resource_ids_.front();
+ purgeable_resource_ids_.pop_front();
RunSoon(FROM_HERE,
base::Bind(&ServiceWorkerStorage::PurgeResource,
weak_factory_.GetWeakPtr(), id));
@@ -809,7 +1196,7 @@ void ServiceWorkerStorage::OnResourcePurged(int64 id, int rv) {
DCHECK(is_purge_pending_);
is_purge_pending_ = false;
- database_task_runner_->PostTask(
+ database_task_manager_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(
&ServiceWorkerDatabase::ClearPurgeableResourceIds),
@@ -819,6 +1206,79 @@ void ServiceWorkerStorage::OnResourcePurged(int64 id, int rv) {
ContinuePurgingResources();
}
+void ServiceWorkerStorage::DeleteStaleResources() {
+ DCHECK(!has_checked_for_stale_resources_);
+ has_checked_for_stale_resources_ = true;
+ database_task_manager_->GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ServiceWorkerStorage::CollectStaleResourcesFromDB,
+ database_.get(),
+ base::MessageLoopProxy::current(),
+ base::Bind(&ServiceWorkerStorage::DidCollectStaleResources,
+ weak_factory_.GetWeakPtr())));
+}
+
+void ServiceWorkerStorage::DidCollectStaleResources(
+ const std::vector<int64>& stale_resource_ids,
+ ServiceWorkerDatabase::Status status) {
+ DCHECK_EQ(ServiceWorkerDatabase::STATUS_OK, status);
+ if (status != ServiceWorkerDatabase::STATUS_OK)
+ return;
+ StartPurgingResources(stale_resource_ids);
+}
+
+void ServiceWorkerStorage::ClearSessionOnlyOrigins() {
+ // Can be null in tests.
+ if (!special_storage_policy_.get())
+ return;
+
+ if (!special_storage_policy_->HasSessionOnlyOrigins())
+ return;
+
+ std::set<GURL> session_only_origins;
+ for (const GURL& origin : registered_origins_) {
+ if (special_storage_policy_->IsStorageSessionOnly(origin))
+ session_only_origins.insert(origin);
+ }
+
+ database_task_manager_->GetShutdownBlockingTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeleteAllDataForOriginsFromDB,
+ database_.get(),
+ session_only_origins));
+}
+
+void ServiceWorkerStorage::CollectStaleResourcesFromDB(
+ ServiceWorkerDatabase* database,
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ const GetResourcesCallback& callback) {
+ std::set<int64> ids;
+ ServiceWorkerDatabase::Status status =
+ database->GetUncommittedResourceIds(&ids);
+ if (status != ServiceWorkerDatabase::STATUS_OK) {
+ original_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ callback, std::vector<int64>(ids.begin(), ids.end()), status));
+ return;
+ }
+
+ status = database->PurgeUncommittedResourceIds(ids);
+ if (status != ServiceWorkerDatabase::STATUS_OK) {
+ original_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(
+ callback, std::vector<int64>(ids.begin(), ids.end()), status));
+ return;
+ }
+
+ ids.clear();
+ status = database->GetPurgeableResourceIds(&ids);
+ original_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(callback, std::vector<int64>(ids.begin(), ids.end()), status));
+}
+
void ServiceWorkerStorage::ReadInitialDataFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -850,13 +1310,15 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
const DeleteRegistrationCallback& callback) {
DCHECK(database);
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
- ServiceWorkerDatabase::Status status =
- database->DeleteRegistration(registration_id, origin,
- &newly_purgeable_resources);
+ ServiceWorkerDatabase::Status status = database->DeleteRegistration(
+ registration_id, origin, &deleted_version, &newly_purgeable_resources);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status));
+ FROM_HERE,
+ base::Bind(
+ callback, false, deleted_version, std::vector<int64>(), status));
return;
}
@@ -866,14 +1328,19 @@ void ServiceWorkerStorage::DeleteRegistrationFromDB(
status = database->GetRegistrationsForOrigin(origin, &registrations);
if (status != ServiceWorkerDatabase::STATUS_OK) {
original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status));
+ FROM_HERE,
+ base::Bind(
+ callback, false, deleted_version, std::vector<int64>(), status));
return;
}
bool deletable = registrations.empty();
- original_task_runner->PostTask(
- FROM_HERE, base::Bind(callback, deletable,
- newly_purgeable_resources, status));
+ original_task_runner->PostTask(FROM_HERE,
+ base::Bind(callback,
+ deletable,
+ deleted_version,
+ newly_purgeable_resources,
+ status));
}
void ServiceWorkerStorage::WriteRegistrationInDB(
@@ -883,13 +1350,16 @@ void ServiceWorkerStorage::WriteRegistrationInDB(
const ResourceList& resources,
const WriteRegistrationCallback& callback) {
DCHECK(database);
+ ServiceWorkerDatabase::RegistrationData deleted_version;
std::vector<int64> newly_purgeable_resources;
- ServiceWorkerDatabase::Status status =
- database->WriteRegistration(data, resources, &newly_purgeable_resources);
- original_task_runner->PostTask(
- FROM_HERE,
- base::Bind(callback, data.script.GetOrigin(),
- newly_purgeable_resources, status));
+ ServiceWorkerDatabase::Status status = database->WriteRegistration(
+ data, resources, &deleted_version, &newly_purgeable_resources);
+ original_task_runner->PostTask(FROM_HERE,
+ base::Bind(callback,
+ data.script.GetOrigin(),
+ deleted_version,
+ newly_purgeable_resources,
+ status));
}
void ServiceWorkerStorage::FindForDocumentInDB(
@@ -982,4 +1452,69 @@ void ServiceWorkerStorage::FindForIdInDB(
FROM_HERE, base::Bind(callback, data, resources, status));
}
+void ServiceWorkerStorage::DeleteAllDataForOriginsFromDB(
+ ServiceWorkerDatabase* database,
+ const std::set<GURL>& origins) {
+ DCHECK(database);
+
+ std::vector<int64> newly_purgeable_resources;
+ database->DeleteAllDataForOrigins(origins, &newly_purgeable_resources);
+}
+
+// TODO(nhiroki): The corruption recovery should not be scheduled if the error
+// is transient and it can get healed soon (e.g. IO error). To do that, the
+// database should not disable itself when an error occurs and the storage
+// controls it instead.
+void ServiceWorkerStorage::ScheduleDeleteAndStartOver() {
+ // TODO(dmurph): Notify the quota manager somehow that all of our data is now
+ // removed.
+ if (state_ == DISABLED) {
+ // Recovery process has already been scheduled.
+ return;
+ }
+ Disable();
+
+ DVLOG(1) << "Schedule to delete the context and start over.";
+ context_->ScheduleDeleteAndStartOver();
+}
+
+void ServiceWorkerStorage::DidDeleteDatabase(
+ const StatusCallback& callback,
+ ServiceWorkerDatabase::Status status) {
+ DCHECK_EQ(DISABLED, state_);
+ if (status != ServiceWorkerDatabase::STATUS_OK) {
+ // Give up the corruption recovery until the browser restarts.
+ LOG(ERROR) << "Failed to delete the database: "
+ << ServiceWorkerDatabase::StatusToString(status);
+ callback.Run(DatabaseStatusToStatusCode(status));
+ return;
+ }
+ DVLOG(1) << "Deleted ServiceWorkerDatabase successfully.";
+
+ // Delete the disk cache on the cache thread.
+ // TODO(nhiroki): What if there is a bunch of files in the cache directory?
+ // Deleting the directory could take a long time and restart could be delayed.
+ // We should probably rename the directory and delete it later.
+ PostTaskAndReplyWithResult(
+ database_task_manager_->GetTaskRunner(),
+ FROM_HERE,
+ base::Bind(&base::DeleteFile, GetDiskCachePath(), true),
+ base::Bind(&ServiceWorkerStorage::DidDeleteDiskCache,
+ weak_factory_.GetWeakPtr(),
+ callback));
+}
+
+void ServiceWorkerStorage::DidDeleteDiskCache(
+ const StatusCallback& callback, bool result) {
+ DCHECK_EQ(DISABLED, state_);
+ if (!result) {
+ // Give up the corruption recovery until the browser restarts.
+ LOG(ERROR) << "Failed to delete the diskcache.";
+ callback.Run(SERVICE_WORKER_ERROR_FAILED);
+ return;
+ }
+ DVLOG(1) << "Deleted ServiceWorkerDiskCache successfully.";
+ callback.Run(SERVICE_WORKER_OK);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 5d89864dc21..0eda8bf540e 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -16,17 +16,20 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_database.h"
+#include "content/browser/service_worker/service_worker_database_task_manager.h"
+#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
namespace base {
-class MessageLoopProxy;
class SequencedTaskRunner;
+class SingleThreadTaskRunner;
}
-namespace quota {
+namespace storage {
class QuotaManagerProxy;
+class SpecialStoragePolicy;
}
namespace content {
@@ -37,11 +40,11 @@ class ServiceWorkerRegistration;
class ServiceWorkerRegistrationInfo;
class ServiceWorkerResponseReader;
class ServiceWorkerResponseWriter;
-class ServiceWorkerVersion;
// This class provides an interface to store and retrieve ServiceWorker
// registration data.
-class CONTENT_EXPORT ServiceWorkerStorage {
+class CONTENT_EXPORT ServiceWorkerStorage
+ : NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
public:
typedef std::vector<ServiceWorkerDatabase::ResourceRecord> ResourceList;
typedef base::Callback<void(ServiceWorkerStatusCode status)> StatusCallback;
@@ -52,15 +55,23 @@ class CONTENT_EXPORT ServiceWorkerStorage {
void(const std::vector<ServiceWorkerRegistrationInfo>& registrations)>
GetAllRegistrationInfosCallback;
typedef base::Callback<
- void(ServiceWorkerStatusCode status, int result)>
+ void(ServiceWorkerStatusCode status, bool are_equal)>
CompareCallback;
- ServiceWorkerStorage(const base::FilePath& path,
- base::WeakPtr<ServiceWorkerContextCore> context,
- base::SequencedTaskRunner* database_task_runner,
- base::MessageLoopProxy* disk_cache_thread,
- quota::QuotaManagerProxy* quota_manager_proxy);
- ~ServiceWorkerStorage();
+ ~ServiceWorkerStorage() override;
+
+ static scoped_ptr<ServiceWorkerStorage> Create(
+ const base::FilePath& path,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy);
+
+ // Used for DeleteAndStartOver. Creates new storage based on |old_storage|.
+ static scoped_ptr<ServiceWorkerStorage> Create(
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerStorage* old_storage);
// Finds registration for |document_url| or |pattern| or |registration_id|.
// The Find methods will find stored and initially installing registrations.
@@ -79,27 +90,31 @@ class CONTENT_EXPORT ServiceWorkerStorage {
const GURL& origin,
const FindRegistrationCallback& callback);
+ ServiceWorkerRegistration* GetUninstallingRegistration(const GURL& scope);
+
// Returns info about all stored and initially installing registrations.
void GetAllRegistrations(const GetAllRegistrationInfosCallback& callback);
// Commits |registration| with the installed but not activated |version|
// to storage, overwritting any pre-existing registration data for the scope.
- // A pre-existing version's script resources will remain available until
- // either a browser restart or DeleteVersionResources is called.
- void StoreRegistration(
- ServiceWorkerRegistration* registration,
- ServiceWorkerVersion* version,
- const StatusCallback& callback);
+ // A pre-existing version's script resources remain available if that version
+ // is live. PurgeResources should be called when it's OK to delete them.
+ void StoreRegistration(ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version,
+ const StatusCallback& callback);
// Updates the state of the registration's stored version to active.
void UpdateToActiveState(
ServiceWorkerRegistration* registration,
const StatusCallback& callback);
- // Deletes the registration data for |registration_id|, the
- // script resources for the registration's stored version
- // will remain available until either a browser restart or
- // DeleteVersionResources is called.
+ // Updates the stored time to match the value of
+ // registration->last_update_check().
+ void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration);
+
+ // Deletes the registration data for |registration_id|. If the registration's
+ // version is live, its script resources will remain available.
+ // PurgeResources should be called when it's OK to delete them.
void DeleteRegistration(int64 registration_id,
const GURL& origin,
const StatusCallback& callback);
@@ -111,29 +126,60 @@ class CONTENT_EXPORT ServiceWorkerStorage {
// Adds |id| to the set of resources ids that are in the disk
// cache but not yet stored with a registration.
- void StoreUncommittedReponseId(int64 id);
+ void StoreUncommittedResponseId(int64 id);
// Removes |id| from uncommitted list, adds it to the
// purgeable list and purges it.
void DoomUncommittedResponse(int64 id);
+ // Compares only the response bodies.
+ void CompareScriptResources(int64 lhs_id, int64 rhs_id,
+ const CompareCallback& callback);
+
+ // Deletes the storage and starts over.
+ void DeleteAndStartOver(const StatusCallback& callback);
+
// Returns new IDs which are guaranteed to be unique in the storage.
int64 NewRegistrationId();
int64 NewVersionId();
int64 NewResourceId();
- // Intended for use only by ServiceWorkerRegisterJob.
+ // Intended for use only by ServiceWorkerRegisterJob and
+ // ServiceWorkerRegistration.
void NotifyInstallingRegistration(
ServiceWorkerRegistration* registration);
void NotifyDoneInstallingRegistration(
ServiceWorkerRegistration* registration,
ServiceWorkerVersion* version,
ServiceWorkerStatusCode status);
+ void NotifyUninstallingRegistration(ServiceWorkerRegistration* registration);
+ void NotifyDoneUninstallingRegistration(
+ ServiceWorkerRegistration* registration);
+
+ void Disable();
+ bool IsDisabled() const;
+
+ // |resources| must already be on the purgeable list.
+ void PurgeResources(const ResourceList& resources);
private:
- friend class ServiceWorkerStorageTest;
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStorageTest,
- ResourceIdsAreStoredAndPurged);
+ friend class ServiceWorkerResourceStorageTest;
+ friend class ServiceWorkerControlleeRequestHandlerTest;
+ friend class ServiceWorkerContextRequestHandlerTest;
+ friend class ServiceWorkerRequestHandlerTest;
+ friend class ServiceWorkerWriteToCacheJobTest;
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
+ DeleteRegistration_NoLiveVersion);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
+ DeleteRegistration_WaitingVersion);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
+ DeleteRegistration_ActiveVersion);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageTest,
+ UpdateRegistration);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageDiskTest,
+ CleanupOnRestart);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerResourceStorageDiskTest,
+ ClearOnExit);
struct InitialData {
int64 next_registration_id;
@@ -145,6 +191,16 @@ class CONTENT_EXPORT ServiceWorkerStorage {
~InitialData();
};
+ // Because there are too many params for base::Bind to wrap a closure around.
+ struct DidDeleteRegistrationParams {
+ int64 registration_id;
+ GURL origin;
+ StatusCallback callback;
+
+ DidDeleteRegistrationParams();
+ ~DidDeleteRegistrationParams();
+ };
+
typedef std::vector<ServiceWorkerDatabase::RegistrationData> RegistrationList;
typedef std::map<int64, scoped_refptr<ServiceWorkerRegistration> >
RegistrationRefsById;
@@ -153,16 +209,29 @@ class CONTENT_EXPORT ServiceWorkerStorage {
ServiceWorkerDatabase::Status status)> InitializeCallback;
typedef base::Callback<void(
const GURL& origin,
+ const ServiceWorkerDatabase::RegistrationData& deleted_version_data,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status)> WriteRegistrationCallback;
typedef base::Callback<void(
bool origin_is_deletable,
+ const ServiceWorkerDatabase::RegistrationData& deleted_version_data,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status)> DeleteRegistrationCallback;
typedef base::Callback<void(
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status)> FindInDBCallback;
+ typedef base::Callback<void(const std::vector<int64>& resource_ids,
+ ServiceWorkerDatabase::Status status)>
+ GetResourcesCallback;
+
+ ServiceWorkerStorage(
+ const base::FilePath& path,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ storage::SpecialStoragePolicy* special_storage_policy);
base::FilePath GetDatabasePath();
base::FilePath GetDiskCachePath();
@@ -175,6 +244,7 @@ class CONTENT_EXPORT ServiceWorkerStorage {
void DidFindRegistrationForDocument(
const GURL& document_url,
const FindRegistrationCallback& callback,
+ int64 callback_id,
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status);
@@ -195,18 +265,24 @@ class CONTENT_EXPORT ServiceWorkerStorage {
ServiceWorkerDatabase::Status status);
void DidStoreRegistration(
const StatusCallback& callback,
+ const ServiceWorkerDatabase::RegistrationData& new_version,
const GURL& origin,
+ const ServiceWorkerDatabase::RegistrationData& deleted_version,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status);
void DidUpdateToActiveState(
const StatusCallback& callback,
ServiceWorkerDatabase::Status status);
void DidDeleteRegistration(
- const GURL& origin,
- const StatusCallback& callback,
+ const DidDeleteRegistrationParams& params,
bool origin_is_deletable,
+ const ServiceWorkerDatabase::RegistrationData& deleted_version,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status);
+ void ReturnFoundRegistration(
+ const FindRegistrationCallback& callback,
+ const ServiceWorkerDatabase::RegistrationData& data,
+ const ResourceList& resources);
scoped_refptr<ServiceWorkerRegistration> GetOrCreateRegistration(
const ServiceWorkerDatabase::RegistrationData& data,
@@ -228,7 +304,20 @@ class CONTENT_EXPORT ServiceWorkerStorage {
void PurgeResource(int64 id);
void OnResourcePurged(int64 id, int rv);
+ // Deletes purgeable and uncommitted resources left over from the previous
+ // browser session. This must be called once per session before any database
+ // operation that may mutate the purgeable or uncommitted resource lists.
+ void DeleteStaleResources();
+ void DidCollectStaleResources(const std::vector<int64>& stale_resource_ids,
+ ServiceWorkerDatabase::Status status);
+
+ void ClearSessionOnlyOrigins();
+
// Static cross-thread helpers.
+ static void CollectStaleResourcesFromDB(
+ ServiceWorkerDatabase* database,
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ const GetResourcesCallback& callback);
static void ReadInitialDataFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
@@ -261,9 +350,21 @@ class CONTENT_EXPORT ServiceWorkerStorage {
int64 registration_id,
const GURL& origin,
const FindInDBCallback& callback);
+ static void DeleteAllDataForOriginsFromDB(
+ ServiceWorkerDatabase* database,
+ const std::set<GURL>& origins);
+
+ void ScheduleDeleteAndStartOver();
+ void DidDeleteDatabase(
+ const StatusCallback& callback,
+ ServiceWorkerDatabase::Status status);
+ void DidDeleteDiskCache(
+ const StatusCallback& callback,
+ bool result);
- // For finding registrations being installed.
+ // For finding registrations being installed or uninstalled.
RegistrationRefsById installing_registrations_;
+ RegistrationRefsById uninstalling_registrations_;
// Origins having registations.
std::set<GURL> registered_origins_;
@@ -286,15 +387,18 @@ class CONTENT_EXPORT ServiceWorkerStorage {
base::FilePath path_;
base::WeakPtr<ServiceWorkerContextCore> context_;
- // Only accessed on |database_task_runner_|.
+ // Only accessed using |database_task_manager_|.
scoped_ptr<ServiceWorkerDatabase> database_;
- scoped_refptr<base::SequencedTaskRunner> database_task_runner_;
- scoped_refptr<base::MessageLoopProxy> disk_cache_thread_;
- scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager_;
+ scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread_;
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
scoped_ptr<ServiceWorkerDiskCache> disk_cache_;
- std::deque<int64> purgeable_reource_ids_;
+ std::deque<int64> purgeable_resource_ids_;
bool is_purge_pending_;
+ bool has_checked_for_stale_resources_;
+ std::set<int64> pending_deletions_;
base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
index 417a0b7f237..e98b83dbc6c 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -4,23 +4,27 @@
#include <string>
+#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/browser/service_worker/service_worker_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::IOBuffer;
+using net::TestCompletionCallback;
using net::WrappedIOBuffer;
namespace content {
@@ -75,74 +79,108 @@ ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback(
return base::Bind(&GetAllCallback, was_called, all);
}
-void OnIOComplete(int* rv_out, int rv) {
- *rv_out = rv;
+void OnCompareComplete(
+ ServiceWorkerStatusCode* status_out, bool* are_equal_out,
+ ServiceWorkerStatusCode status, bool are_equal) {
+ *status_out = status;
+ *are_equal_out = are_equal;
}
-void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
+void WriteResponse(
+ ServiceWorkerStorage* storage, int64 id,
+ const std::string& headers,
+ IOBuffer* body, int length) {
scoped_ptr<ServiceWorkerResponseWriter> writer =
storage->CreateResponseWriter(id);
- const char kHttpHeaders[] =
- "HTTP/1.0 200 HONKYDORY\0Content-Length: 6\0\0";
- const char kHttpBody[] = "Hello\0";
- scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
- std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
- info->headers = new net::HttpResponseHeaders(raw_headers);
+ info->headers = new net::HttpResponseHeaders(headers);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
new HttpResponseInfoIOBuffer(info.release());
+ {
+ TestCompletionCallback cb;
+ writer->WriteInfo(info_buffer.get(), cb.callback());
+ int rv = cb.WaitForResult();
+ EXPECT_LT(0, rv);
+ }
+ {
+ TestCompletionCallback cb;
+ writer->WriteData(body, length, cb.callback());
+ int rv = cb.WaitForResult();
+ EXPECT_EQ(length, rv);
+ }
+}
- int rv = -1234;
- writer->WriteInfo(info_buffer, base::Bind(&OnIOComplete, &rv));
- base::RunLoop().RunUntilIdle();
- EXPECT_LT(0, rv);
+void WriteStringResponse(
+ ServiceWorkerStorage* storage, int64 id,
+ const std::string& headers,
+ const std::string& body) {
+ scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
+ WriteResponse(storage, id, headers, body_buffer.get(), body.length());
+}
- rv = -1234;
- writer->WriteData(body, arraysize(kHttpBody),
- base::Bind(&OnIOComplete, &rv));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(arraysize(kHttpBody)), rv);
+void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
+ scoped_ptr<ServiceWorkerResponseWriter> writer =
+ storage->CreateResponseWriter(id);
+
+ const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0Content-Length: 5\0\0";
+ const char kHttpBody[] = "Hello";
+ std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
+ WriteStringResponse(storage, id, headers, std::string(kHttpBody));
}
bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id,
bool expected_positive_result) {
- const char kExpectedHttpBody[] = "Hello\0";
+ const std::string kExpectedHttpBody("Hello");
scoped_ptr<ServiceWorkerResponseReader> reader =
storage->CreateResponseReader(id);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
new HttpResponseInfoIOBuffer();
- int rv = -1234;
- reader->ReadInfo(info_buffer, base::Bind(&OnIOComplete, &rv));
- base::RunLoop().RunUntilIdle();
- if (expected_positive_result)
- EXPECT_LT(0, rv);
- if (rv <= 0)
- return false;
+ {
+ TestCompletionCallback cb;
+ reader->ReadInfo(info_buffer.get(), cb.callback());
+ int rv = cb.WaitForResult();
+ if (expected_positive_result)
+ EXPECT_LT(0, rv);
+ if (rv <= 0)
+ return false;
+ }
- const int kBigEnough = 512;
- scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
- rv = -1234;
- reader->ReadData(buffer, kBigEnough, base::Bind(&OnIOComplete, &rv));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(static_cast<int>(arraysize(kExpectedHttpBody)), rv);
- if (rv <= 0)
- return false;
+ std::string received_body;
+ {
+ const int kBigEnough = 512;
+ scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
+ TestCompletionCallback cb;
+ reader->ReadData(buffer.get(), kBigEnough, cb.callback());
+ int rv = cb.WaitForResult();
+ EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
+ if (rv <= 0)
+ return false;
+ received_body.assign(buffer->data(), rv);
+ }
bool status_match =
std::string("HONKYDORY") ==
info_buffer->http_info->headers->GetStatusText();
- bool data_match =
- std::string(kExpectedHttpBody) == std::string(buffer->data());
+ bool data_match = kExpectedHttpBody == received_body;
EXPECT_TRUE(status_match);
EXPECT_TRUE(data_match);
return status_match && data_match;
}
+void WriteResponseOfSize(ServiceWorkerStorage* storage, int64 id,
+ char val, int size) {
+ const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\00";
+ std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
+ scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size);
+ memset(buffer->data(), val, size);
+ WriteResponse(storage, id, headers, buffer.get(), size);
+}
+
} // namespace
class ServiceWorkerStorageTest : public testing::Test {
@@ -151,20 +189,25 @@ class ServiceWorkerStorageTest : public testing::Test {
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
+ new MockServiceWorkerDatabaseTaskManager(
+ base::ThreadTaskRunnerHandle::Get()));
context_.reset(
- new ServiceWorkerContextCore(base::FilePath(),
- base::MessageLoopProxy::current(),
- base::MessageLoopProxy::current(),
+ new ServiceWorkerContextCore(GetUserDataDirectory(),
+ base::ThreadTaskRunnerHandle::Get(),
+ database_task_manager.Pass(),
+ base::ThreadTaskRunnerHandle::Get(),
+ NULL,
NULL,
NULL,
NULL));
context_ptr_ = context_->AsWeakPtr();
}
- virtual void TearDown() OVERRIDE {
- context_.reset();
- }
+ void TearDown() override { context_.reset(); }
+
+ virtual base::FilePath GetUserDataDirectory() { return base::FilePath(); }
ServiceWorkerStorage* storage() { return context_->storage(); }
@@ -187,8 +230,9 @@ class ServiceWorkerStorageTest : public testing::Test {
scoped_refptr<ServiceWorkerVersion> version) {
bool was_called = false;
ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
- storage()->StoreRegistration(
- registration, version, MakeStatusCallback(&was_called, &result));
+ storage()->StoreRegistration(registration.get(),
+ version.get(),
+ MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
@@ -222,14 +266,19 @@ class ServiceWorkerStorageTest : public testing::Test {
scoped_refptr<ServiceWorkerRegistration> registration) {
bool was_called = false;
ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
- storage()->UpdateToActiveState(
- registration, MakeStatusCallback(&was_called, &result));
+ storage()->UpdateToActiveState(registration.get(),
+ MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
return result;
}
+ void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration) {
+ storage()->UpdateLastUpdateCheckTime(registration);
+ base::RunLoop().RunUntilIdle();
+ }
+
ServiceWorkerStatusCode FindRegistrationForDocument(
const GURL& document_url,
scoped_refptr<ServiceWorkerRegistration>* registration) {
@@ -275,37 +324,51 @@ class ServiceWorkerStorageTest : public testing::Test {
};
TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
- const GURL kScope("http://www.test.not/scope/*");
+ const GURL kScope("http://www.test.not/scope/");
const GURL kScript("http://www.test.not/script.js");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
+ const GURL kResource1("http://www.test.not/scope/resource1.js");
+ const int64 kResource1Size = 1591234;
+ const GURL kResource2("http://www.test.not/scope/resource2.js");
+ const int64 kResource2Size = 51;
const int64 kRegistrationId = 0;
const int64 kVersionId = 0;
+ const base::Time kToday = base::Time::Now();
+ const base::Time kYesterday = kToday - base::TimeDelta::FromDays(1);
scoped_refptr<ServiceWorkerRegistration> found_registration;
// We shouldn't find anything without having stored anything.
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForPattern(kScope, &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForId(
kRegistrationId, kScope.GetOrigin(), &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
+
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ resources.push_back(
+ ServiceWorkerDatabase::ResourceRecord(1, kResource1, kResource1Size));
+ resources.push_back(
+ ServiceWorkerDatabase::ResourceRecord(2, kResource2, kResource2Size));
// Store something.
scoped_refptr<ServiceWorkerRegistration> live_registration =
new ServiceWorkerRegistration(
- kScope, kScript, kRegistrationId, context_ptr_);
+ kScope, kRegistrationId, context_ptr_);
scoped_refptr<ServiceWorkerVersion> live_version =
new ServiceWorkerVersion(
- live_registration, kVersionId, context_ptr_);
+ live_registration.get(), kScript, kVersionId, context_ptr_);
live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
- live_registration->set_waiting_version(live_version);
+ live_version->script_cache_map()->SetResources(resources);
+ live_registration->SetWaitingVersion(live_version.get());
+ live_registration->set_last_update_check(kYesterday);
EXPECT_EQ(SERVICE_WORKER_OK,
StoreRegistration(live_registration, live_version));
@@ -313,6 +376,10 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_EQ(live_registration, found_registration);
+ EXPECT_EQ(kResource1Size + kResource2Size,
+ live_registration->resources_total_size_bytes());
+ EXPECT_EQ(kResource1Size + kResource2Size,
+ found_registration->resources_total_size_bytes());
found_registration = NULL;
// But FindRegistrationForPattern is always async.
@@ -325,7 +392,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationForId(
kRegistrationId, kScope.GetOrigin(), &found_registration));
- ASSERT_TRUE(found_registration);
+ ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
EXPECT_EQ(live_registration, found_registration);
found_registration = NULL;
@@ -336,10 +403,21 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
// Now FindRegistrationForDocument should be async.
EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
- ASSERT_TRUE(found_registration);
+ ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
EXPECT_TRUE(found_registration->HasOneRef());
- EXPECT_EQ(live_version, found_registration->waiting_version());
+
+ // Check that sizes are populated correctly
+ EXPECT_EQ(live_version.get(), found_registration->waiting_version());
+ EXPECT_EQ(kResource1Size + kResource2Size,
+ found_registration->resources_total_size_bytes());
+ std::vector<ServiceWorkerRegistrationInfo> all_registrations;
+ GetAllRegistrations(&all_registrations);
+ EXPECT_EQ(1u, all_registrations.size());
+ ServiceWorkerRegistrationInfo info = all_registrations[0];
+ EXPECT_EQ(kResource1Size + kResource2Size, info.stored_version_size_bytes);
+ all_registrations.clear();
+
found_registration = NULL;
// Drop the live version too.
@@ -348,42 +426,47 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
// And FindRegistrationForPattern is always async.
EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationForPattern(kScope, &found_registration));
- ASSERT_TRUE(found_registration);
+ ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
EXPECT_TRUE(found_registration->HasOneRef());
EXPECT_FALSE(found_registration->active_version());
ASSERT_TRUE(found_registration->waiting_version());
+ EXPECT_EQ(kYesterday, found_registration->last_update_check());
EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
found_registration->waiting_version()->status());
- // Update to active.
+ // Update to active and update the last check time.
scoped_refptr<ServiceWorkerVersion> temp_version =
found_registration->waiting_version();
- found_registration->set_waiting_version(NULL);
- temp_version->SetStatus(ServiceWorkerVersion::ACTIVE);
- found_registration->set_active_version(temp_version);
+ temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ found_registration->SetActiveVersion(temp_version.get());
temp_version = NULL;
EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration));
+ found_registration->set_last_update_check(kToday);
+ UpdateLastUpdateCheckTime(found_registration.get());
+
found_registration = NULL;
// Trying to update a unstored registration to active should fail.
scoped_refptr<ServiceWorkerRegistration> unstored_registration =
new ServiceWorkerRegistration(
- kScope, kScript, kRegistrationId + 1, context_ptr_);
+ kScope, kRegistrationId + 1, context_ptr_);
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
UpdateToActiveState(unstored_registration));
unstored_registration = NULL;
- // The Find methods should return a registration with an active version.
+ // The Find methods should return a registration with an active version
+ // and the expected update time.
EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
- ASSERT_TRUE(found_registration);
+ ASSERT_TRUE(found_registration.get());
EXPECT_EQ(kRegistrationId, found_registration->id());
EXPECT_TRUE(found_registration->HasOneRef());
EXPECT_FALSE(found_registration->waiting_version());
ASSERT_TRUE(found_registration->active_version());
- EXPECT_EQ(ServiceWorkerVersion::ACTIVE,
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
found_registration->active_version()->status());
+ EXPECT_EQ(kToday, found_registration->last_update_check());
// Delete from storage but with a instance still live.
EXPECT_TRUE(context_->GetLiveVersion(kRegistrationId));
@@ -395,7 +478,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForId(
kRegistrationId, kScope.GetOrigin(), &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
// Deleting an unstored registration should succeed.
EXPECT_EQ(SERVICE_WORKER_OK,
@@ -403,7 +486,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
}
TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
- const GURL kScope("http://www.test.not/scope/*");
+ const GURL kScope("http://www.test.not/scope/");
const GURL kScript("http://www.test.not/script.js");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
const int64 kRegistrationId = 0;
@@ -414,33 +497,33 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
// Create an unstored registration.
scoped_refptr<ServiceWorkerRegistration> live_registration =
new ServiceWorkerRegistration(
- kScope, kScript, kRegistrationId, context_ptr_);
+ kScope, kRegistrationId, context_ptr_);
scoped_refptr<ServiceWorkerVersion> live_version =
new ServiceWorkerVersion(
- live_registration, kVersionId, context_ptr_);
+ live_registration.get(), kScript, kVersionId, context_ptr_);
live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
- live_registration->set_waiting_version(live_version);
+ live_registration->SetWaitingVersion(live_version.get());
// Should not be findable, including by GetAllRegistrations.
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForId(
kRegistrationId, kScope.GetOrigin(), &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForPattern(kScope, &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
std::vector<ServiceWorkerRegistrationInfo> all_registrations;
GetAllRegistrations(&all_registrations);
EXPECT_TRUE(all_registrations.empty());
// Notify storage of it being installed.
- storage()->NotifyInstallingRegistration(live_registration);
+ storage()->NotifyInstallingRegistration(live_registration.get());
// Now should be findable.
EXPECT_EQ(SERVICE_WORKER_OK,
@@ -465,85 +548,371 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
// Notify storage of installation no longer happening.
storage()->NotifyDoneInstallingRegistration(
- live_registration, NULL, SERVICE_WORKER_OK);
+ live_registration.get(), NULL, SERVICE_WORKER_OK);
// Once again, should not be findable.
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForId(
kRegistrationId, kScope.GetOrigin(), &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForPattern(kScope, &found_registration));
- EXPECT_FALSE(found_registration);
+ EXPECT_FALSE(found_registration.get());
GetAllRegistrations(&all_registrations);
EXPECT_TRUE(all_registrations.empty());
}
-TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) {
- storage()->LazyInitialize(base::Bind(&base::DoNothing));
+class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
+ public:
+ void SetUp() override {
+ ServiceWorkerStorageTest::SetUp();
+
+ storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+ scope_ = GURL("http://www.test.not/scope/");
+ script_ = GURL("http://www.test.not/script.js");
+ import_ = GURL("http://www.test.not/import.js");
+ document_url_ = GURL("http://www.test.not/scope/document.html");
+ registration_id_ = storage()->NewRegistrationId();
+ version_id_ = storage()->NewVersionId();
+ resource_id1_ = storage()->NewResourceId();
+ resource_id2_ = storage()->NewResourceId();
+ resource_id1_size_ = 239193;
+ resource_id2_size_ = 59923;
+
+ // Cons up a new registration+version with two script resources.
+ RegistrationData data;
+ data.registration_id = registration_id_;
+ data.scope = scope_;
+ data.script = script_;
+ data.version_id = version_id_;
+ data.is_active = false;
+ std::vector<ResourceRecord> resources;
+ resources.push_back(
+ ResourceRecord(resource_id1_, script_, resource_id1_size_));
+ resources.push_back(
+ ResourceRecord(resource_id2_, import_, resource_id2_size_));
+ registration_ = storage()->GetOrCreateRegistration(data, resources);
+ registration_->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);
+
+ // Add the resources ids to the uncommitted list.
+ storage()->StoreUncommittedResponseId(resource_id1_);
+ storage()->StoreUncommittedResponseId(resource_id2_);
+ base::RunLoop().RunUntilIdle();
+ std::set<int64> verify_ids;
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetUncommittedResourceIds(&verify_ids));
+ EXPECT_EQ(2u, verify_ids.size());
+
+ // And dump something in the disk cache for them.
+ WriteBasicResponse(storage(), resource_id1_);
+ WriteBasicResponse(storage(), resource_id2_);
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
+
+ // Storing the registration/version should take the resources ids out
+ // of the uncommitted list.
+ EXPECT_EQ(
+ SERVICE_WORKER_OK,
+ StoreRegistration(registration_, registration_->waiting_version()));
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetUncommittedResourceIds(&verify_ids));
+ EXPECT_TRUE(verify_ids.empty());
+ }
+
+ protected:
+ GURL scope_;
+ GURL script_;
+ GURL import_;
+ GURL document_url_;
+ int64 registration_id_;
+ int64 version_id_;
+ int64 resource_id1_;
+ uint64 resource_id1_size_;
+ int64 resource_id2_;
+ uint64 resource_id2_size_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+};
+
+class ServiceWorkerResourceStorageDiskTest
+ : public ServiceWorkerResourceStorageTest {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(user_data_directory_.CreateUniqueTempDir());
+ ServiceWorkerResourceStorageTest::SetUp();
+ }
+
+ base::FilePath GetUserDataDirectory() override {
+ return user_data_directory_.path();
+ }
+
+ protected:
+ base::ScopedTempDir user_data_directory_;
+};
+
+TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
+ bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ std::set<int64> verify_ids;
+
+ registration_->SetWaitingVersion(NULL);
+ registration_ = NULL;
+
+ // Deleting the registration should result in the resources being added to the
+ // purgeable list and then doomed in the disk cache and removed from that
+ // list.
+ storage()->DeleteRegistration(
+ registration_id_,
+ scope_.GetOrigin(),
+ base::Bind(&VerifyPurgeableListStatusCallback,
+ base::Unretained(storage()->database_.get()),
+ &verify_ids,
+ &was_called,
+ &result));
base::RunLoop().RunUntilIdle();
- const GURL kScope("http://www.test.not/scope/*");
- const GURL kScript("http://www.test.not/script.js");
- const GURL kImport("http://www.test.not/import.js");
- const GURL kDocumentUrl("http://www.test.not/scope/document.html");
- const int64 kRegistrationId = storage()->NewRegistrationId();
- const int64 kVersionId = storage()->NewVersionId();
- const int64 kResourceId1 = storage()->NewResourceId();
- const int64 kResourceId2 = storage()->NewResourceId();
-
- // Cons up a new registration+version with two script resources.
- RegistrationData data;
- data.registration_id = kRegistrationId;
- data.scope = kScope;
- data.script = kScript;
- data.version_id = kVersionId;
- data.is_active = false;
- std::vector<ResourceRecord> resources;
- resources.push_back(ResourceRecord(kResourceId1, kScript));
- resources.push_back(ResourceRecord(kResourceId2, kImport));
- scoped_refptr<ServiceWorkerRegistration> registration =
- storage()->GetOrCreateRegistration(data, resources);
- registration->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);
-
- // Add the resources ids to the uncommitted list.
- std::set<int64> resource_ids;
- resource_ids.insert(kResourceId1);
- resource_ids.insert(kResourceId2);
+ ASSERT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(2u, verify_ids.size());
+ verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- storage()->database_->WriteUncommittedResourceIds(resource_ids));
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_TRUE(verify_ids.empty());
- // And dump something in the disk cache for them.
- WriteBasicResponse(storage(), kResourceId1);
- WriteBasicResponse(storage(), kResourceId2);
- EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId1, true));
- EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId2, true));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
+}
- // Storing the registration/version should take the resources ids out
- // of the uncommitted list.
- EXPECT_EQ(SERVICE_WORKER_OK,
- StoreRegistration(registration, registration->waiting_version()));
+TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
+ bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
std::set<int64> verify_ids;
+
+ // Deleting the registration should result in the resources being added to the
+ // purgeable list and then doomed in the disk cache and removed from that
+ // list.
+ storage()->DeleteRegistration(
+ registration_->id(),
+ scope_.GetOrigin(),
+ base::Bind(&VerifyPurgeableListStatusCallback,
+ base::Unretained(storage()->database_.get()),
+ &verify_ids,
+ &was_called,
+ &result));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(2u, verify_ids.size());
+ verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
- storage()->database_->GetUncommittedResourceIds(&verify_ids));
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_EQ(2u, verify_ids.size());
+
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
+
+ // Doom the version, now it happens.
+ registration_->waiting_version()->Doom();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(2u, verify_ids.size());
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
EXPECT_TRUE(verify_ids.empty());
- // Deleting it should result in the resources being added to the
- // purgeable list and then doomed in the disk cache and removed from
- // that list.
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
+}
+
+TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
+ // Promote the worker to active and add a controllee.
+ registration_->SetActiveVersion(registration_->waiting_version());
+ storage()->UpdateToActiveState(
+ registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ scoped_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(33 /* dummy render process id */,
+ 1 /* dummy provider_id */,
+ context_->AsWeakPtr(),
+ NULL));
+ registration_->active_version()->AddControllee(host.get());
+
bool was_called = false;
ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ std::set<int64> verify_ids;
+
+ // Deleting the registration should move the resources to the purgeable list
+ // but keep them available.
+ storage()->DeleteRegistration(
+ registration_->id(),
+ scope_.GetOrigin(),
+ base::Bind(&VerifyPurgeableListStatusCallback,
+ base::Unretained(storage()->database_.get()),
+ &verify_ids,
+ &was_called,
+ &result));
+ registration_->active_version()->Doom();
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(2u, verify_ids.size());
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_EQ(2u, verify_ids.size());
+
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
+
+ // Removing the controllee should cause the resources to be deleted.
+ registration_->active_version()->RemoveControllee(host.get());
+ base::RunLoop().RunUntilIdle();
verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_TRUE(verify_ids.empty());
+
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
+}
+
+TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
+ // Promote the worker to active and add a controllee.
+ registration_->SetActiveVersion(registration_->waiting_version());
+ registration_->SetWaitingVersion(NULL);
+ storage()->UpdateToActiveState(
+ registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ scoped_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(33 /* dummy render process id */,
+ 1 /* dummy provider_id */,
+ context_->AsWeakPtr(),
+ NULL));
+ registration_->active_version()->AddControllee(host.get());
+
+ bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ std::set<int64> verify_ids;
+
+ // Deleting the registration should move the resources to the purgeable list
+ // but keep them available.
storage()->DeleteRegistration(
- registration->id(), kScope.GetOrigin(),
+ registration_->id(),
+ scope_.GetOrigin(),
+ base::Bind(&VerifyPurgeableListStatusCallback,
+ base::Unretained(storage()->database_.get()),
+ &verify_ids,
+ &was_called,
+ &result));
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(was_called);
+ EXPECT_EQ(SERVICE_WORKER_OK, result);
+ EXPECT_EQ(2u, verify_ids.size());
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_EQ(2u, verify_ids.size());
+
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));
+
+ // Also add an uncommitted resource.
+ int64 kStaleUncommittedResourceId = storage()->NewResourceId();
+ storage()->StoreUncommittedResponseId(kStaleUncommittedResourceId);
+ base::RunLoop().RunUntilIdle();
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetUncommittedResourceIds(&verify_ids));
+ EXPECT_EQ(1u, verify_ids.size());
+ WriteBasicResponse(storage(), kStaleUncommittedResourceId);
+ EXPECT_TRUE(
+ VerifyBasicResponse(storage(), kStaleUncommittedResourceId, true));
+
+ // Simulate browser shutdown. The purgeable and uncommitted resources are now
+ // stale.
+ context_.reset();
+ scoped_ptr<ServiceWorkerDatabaseTaskManager> database_task_manager(
+ new MockServiceWorkerDatabaseTaskManager(
+ base::ThreadTaskRunnerHandle::Get()));
+ context_.reset(
+ new ServiceWorkerContextCore(GetUserDataDirectory(),
+ base::ThreadTaskRunnerHandle::Get(),
+ database_task_manager.Pass(),
+ base::ThreadTaskRunnerHandle::Get(),
+ NULL,
+ NULL,
+ NULL,
+ NULL));
+ storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+
+ // Store a new uncommitted resource. This triggers stale resource cleanup.
+ int64 kNewResourceId = storage()->NewResourceId();
+ WriteBasicResponse(storage(), kNewResourceId);
+ storage()->StoreUncommittedResponseId(kNewResourceId);
+ base::RunLoop().RunUntilIdle();
+
+ // The stale resources should be purged, but the new resource should persist.
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetUncommittedResourceIds(&verify_ids));
+ ASSERT_EQ(1u, verify_ids.size());
+ EXPECT_EQ(kNewResourceId, *verify_ids.begin());
+
+ // Purging resources needs interactions with SimpleCache's worker thread,
+ // so single RunUntilIdle() call may not be sufficient.
+ while (storage()->is_purge_pending_)
+ base::RunLoop().RunUntilIdle();
+
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_TRUE(verify_ids.empty());
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
+ EXPECT_FALSE(
+ VerifyBasicResponse(storage(), kStaleUncommittedResourceId, false));
+ EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
+}
+
+TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
+ // Promote the worker to active worker and add a controllee.
+ registration_->SetActiveVersion(registration_->waiting_version());
+ storage()->UpdateToActiveState(
+ registration_.get(), base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ scoped_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(33 /* dummy render process id */,
+ 1 /* dummy provider_id */,
+ context_->AsWeakPtr(),
+ NULL));
+ registration_->active_version()->AddControllee(host.get());
+
+ bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ std::set<int64> verify_ids;
+
+ // Make an updated registration.
+ scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
+ registration_.get(), script_, storage()->NewVersionId(), context_ptr_);
+ live_version->SetStatus(ServiceWorkerVersion::NEW);
+ registration_->SetWaitingVersion(live_version.get());
+
+ // Writing the registration should move the old version's resources to the
+ // purgeable list but keep them available.
+ storage()->StoreRegistration(
+ registration_.get(),
+ registration_->waiting_version(),
base::Bind(&VerifyPurgeableListStatusCallback,
base::Unretained(storage()->database_.get()),
- &verify_ids, &was_called, &result));
+ &verify_ids,
+ &was_called,
+ &result));
+ registration_->active_version()->Doom();
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
EXPECT_EQ(SERVICE_WORKER_OK, result);
@@ -551,62 +920,74 @@ TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) {
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
storage()->database_->GetPurgeableResourceIds(&verify_ids));
+ EXPECT_EQ(2u, verify_ids.size());
+
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));
+
+ // Removing the controllee should cause the old version's resources to be
+ // deleted.
+ registration_->active_version()->RemoveControllee(host.get());
+ base::RunLoop().RunUntilIdle();
+ verify_ids.clear();
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ storage()->database_->GetPurgeableResourceIds(&verify_ids));
EXPECT_TRUE(verify_ids.empty());
- EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId1, false));
- EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId2, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
+ EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}
TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
const GURL kDocumentUrl("http://www.example.com/scope/foo");
scoped_refptr<ServiceWorkerRegistration> found_registration;
- // Registration for "/scope/*".
- const GURL kScope1("http://www.example.com/scope/*");
+ // Registration for "/scope/".
+ const GURL kScope1("http://www.example.com/scope/");
const GURL kScript1("http://www.example.com/script1.js");
const int64 kRegistrationId1 = 1;
const int64 kVersionId1 = 1;
scoped_refptr<ServiceWorkerRegistration> live_registration1 =
new ServiceWorkerRegistration(
- kScope1, kScript1, kRegistrationId1, context_ptr_);
+ kScope1, kRegistrationId1, context_ptr_);
scoped_refptr<ServiceWorkerVersion> live_version1 =
new ServiceWorkerVersion(
- live_registration1, kVersionId1, context_ptr_);
+ live_registration1.get(), kScript1, kVersionId1, context_ptr_);
live_version1->SetStatus(ServiceWorkerVersion::INSTALLED);
- live_registration1->set_waiting_version(live_version1);
+ live_registration1->SetWaitingVersion(live_version1.get());
- // Registration for "/scope/foo*".
- const GURL kScope2("http://www.example.com/scope/foo*");
+ // Registration for "/scope/foo".
+ const GURL kScope2("http://www.example.com/scope/foo");
const GURL kScript2("http://www.example.com/script2.js");
const int64 kRegistrationId2 = 2;
const int64 kVersionId2 = 2;
scoped_refptr<ServiceWorkerRegistration> live_registration2 =
new ServiceWorkerRegistration(
- kScope2, kScript2, kRegistrationId2, context_ptr_);
+ kScope2, kRegistrationId2, context_ptr_);
scoped_refptr<ServiceWorkerVersion> live_version2 =
new ServiceWorkerVersion(
- live_registration2, kVersionId2, context_ptr_);
+ live_registration2.get(), kScript2, kVersionId2, context_ptr_);
live_version2->SetStatus(ServiceWorkerVersion::INSTALLED);
- live_registration2->set_waiting_version(live_version2);
+ live_registration2->SetWaitingVersion(live_version2.get());
- // Registration for "/scope/foo".
- const GURL kScope3("http://www.example.com/scope/foo");
+ // Registration for "/scope/foobar".
+ const GURL kScope3("http://www.example.com/scope/foobar");
const GURL kScript3("http://www.example.com/script3.js");
const int64 kRegistrationId3 = 3;
const int64 kVersionId3 = 3;
scoped_refptr<ServiceWorkerRegistration> live_registration3 =
new ServiceWorkerRegistration(
- kScope3, kScript3, kRegistrationId3, context_ptr_);
+ kScope3, kRegistrationId3, context_ptr_);
scoped_refptr<ServiceWorkerVersion> live_version3 =
new ServiceWorkerVersion(
- live_registration3, kVersionId3, context_ptr_);
+ live_registration3.get(), kScript3, kVersionId3, context_ptr_);
live_version3->SetStatus(ServiceWorkerVersion::INSTALLED);
- live_registration3->set_waiting_version(live_version3);
+ live_registration3->SetWaitingVersion(live_version3.get());
// Notify storage of they being installed.
- storage()->NotifyInstallingRegistration(live_registration1);
- storage()->NotifyInstallingRegistration(live_registration2);
- storage()->NotifyInstallingRegistration(live_registration3);
+ storage()->NotifyInstallingRegistration(live_registration1.get());
+ storage()->NotifyInstallingRegistration(live_registration2.get());
+ storage()->NotifyInstallingRegistration(live_registration3.get());
// Find a registration among installing ones.
EXPECT_EQ(SERVICE_WORKER_OK,
@@ -624,11 +1005,11 @@ TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
// Notify storage of installations no longer happening.
storage()->NotifyDoneInstallingRegistration(
- live_registration1, NULL, SERVICE_WORKER_OK);
+ live_registration1.get(), NULL, SERVICE_WORKER_OK);
storage()->NotifyDoneInstallingRegistration(
- live_registration2, NULL, SERVICE_WORKER_OK);
+ live_registration2.get(), NULL, SERVICE_WORKER_OK);
storage()->NotifyDoneInstallingRegistration(
- live_registration3, NULL, SERVICE_WORKER_OK);
+ live_registration3.get(), NULL, SERVICE_WORKER_OK);
// Find a registration among installed ones.
EXPECT_EQ(SERVICE_WORKER_OK,
@@ -636,4 +1017,66 @@ TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
EXPECT_EQ(live_registration2, found_registration);
}
+TEST_F(ServiceWorkerStorageTest, CompareResources) {
+ // Compare two small responses containing the same data.
+ WriteBasicResponse(storage(), 1);
+ WriteBasicResponse(storage(), 2);
+ ServiceWorkerStatusCode status = static_cast<ServiceWorkerStatusCode>(-1);
+ bool are_equal = false;
+ storage()->CompareScriptResources(
+ 1, 2,
+ base::Bind(&OnCompareComplete, &status, &are_equal));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_TRUE(are_equal);
+
+ // Compare two small responses with different data.
+ const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0\0";
+ const char kHttpBody[] = "Goodbye";
+ std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
+ WriteStringResponse(storage(), 3, headers, std::string(kHttpBody));
+ status = static_cast<ServiceWorkerStatusCode>(-1);
+ are_equal = true;
+ storage()->CompareScriptResources(
+ 1, 3,
+ base::Bind(&OnCompareComplete, &status, &are_equal));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_FALSE(are_equal);
+
+ // Compare two large responses with the same data.
+ const int k32K = 32 * 1024;
+ WriteResponseOfSize(storage(), 4, 'a', k32K);
+ WriteResponseOfSize(storage(), 5, 'a', k32K);
+ status = static_cast<ServiceWorkerStatusCode>(-1);
+ are_equal = false;
+ storage()->CompareScriptResources(
+ 4, 5,
+ base::Bind(&OnCompareComplete, &status, &are_equal));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_TRUE(are_equal);
+
+ // Compare a large and small response.
+ status = static_cast<ServiceWorkerStatusCode>(-1);
+ are_equal = true;
+ storage()->CompareScriptResources(
+ 1, 5,
+ base::Bind(&OnCompareComplete, &status, &are_equal));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_FALSE(are_equal);
+
+ // Compare two large responses with different data.
+ WriteResponseOfSize(storage(), 6, 'b', k32K);
+ status = static_cast<ServiceWorkerStatusCode>(-1);
+ are_equal = true;
+ storage()->CompareScriptResources(
+ 5, 6,
+ base::Bind(&OnCompareComplete, &status, &are_equal));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_FALSE(are_equal);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_unregister_job.cc b/chromium/content/browser/service_worker/service_worker_unregister_job.cc
index dabcd22f108..8889039407a 100644
--- a/chromium/content/browser/service_worker/service_worker_unregister_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_unregister_job.cc
@@ -4,10 +4,13 @@
#include "content/browser/service_worker/service_worker_unregister_job.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/browser/service_worker/service_worker_version.h"
namespace content {
@@ -18,7 +21,9 @@ ServiceWorkerUnregisterJob::ServiceWorkerUnregisterJob(
const GURL& pattern)
: context_(context),
pattern_(pattern),
- weak_factory_(this) {}
+ is_promise_resolved_(false),
+ weak_factory_(this) {
+}
ServiceWorkerUnregisterJob::~ServiceWorkerUnregisterJob() {}
@@ -30,7 +35,7 @@ void ServiceWorkerUnregisterJob::AddCallback(
void ServiceWorkerUnregisterJob::Start() {
context_->storage()->FindRegistrationForPattern(
pattern_,
- base::Bind(&ServiceWorkerUnregisterJob::DeleteExistingRegistration,
+ base::Bind(&ServiceWorkerUnregisterJob::OnRegistrationFound,
weak_factory_.GetWeakPtr()));
}
@@ -45,32 +50,31 @@ bool ServiceWorkerUnregisterJob::Equals(ServiceWorkerRegisterJobBase* job) {
}
RegistrationJobType ServiceWorkerUnregisterJob::GetType() {
- return ServiceWorkerRegisterJobBase::UNREGISTRATION;
+ return UNREGISTRATION_JOB;
}
-void ServiceWorkerUnregisterJob::DeleteExistingRegistration(
+void ServiceWorkerUnregisterJob::OnRegistrationFound(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration) {
- if (status == SERVICE_WORKER_OK) {
- DCHECK(registration);
- // TODO(michaeln): Deactivate the live registration object and
- // eventually call storage->DeleteVersionResources()
- // when the version no longer has any controllees.
- context_->storage()->DeleteRegistration(
- registration->id(),
- registration->script_url().GetOrigin(),
- base::Bind(&ServiceWorkerUnregisterJob::Complete,
- weak_factory_.GetWeakPtr()));
+ if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
+ DCHECK(!registration.get());
+ Complete(SERVICE_WORKER_ERROR_NOT_FOUND);
return;
}
- if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
- DCHECK(!registration);
- Complete(SERVICE_WORKER_OK);
+ if (status != SERVICE_WORKER_OK || registration->is_uninstalling()) {
+ Complete(status);
return;
}
- Complete(status);
+ // TODO: "7. If registration.updatePromise is not null..."
+
+ // "8. Resolve promise."
+ ResolvePromise(SERVICE_WORKER_OK);
+
+ registration->ClearWhenReady();
+
+ Complete(SERVICE_WORKER_OK);
}
void ServiceWorkerUnregisterJob::Complete(ServiceWorkerStatusCode status) {
@@ -80,6 +84,14 @@ void ServiceWorkerUnregisterJob::Complete(ServiceWorkerStatusCode status) {
void ServiceWorkerUnregisterJob::CompleteInternal(
ServiceWorkerStatusCode status) {
+ if (!is_promise_resolved_)
+ ResolvePromise(status);
+}
+
+void ServiceWorkerUnregisterJob::ResolvePromise(
+ ServiceWorkerStatusCode status) {
+ DCHECK(!is_promise_resolved_);
+ is_promise_resolved_ = true;
for (std::vector<UnregistrationCallback>::iterator it = callbacks_.begin();
it != callbacks_.end();
++it) {
diff --git a/chromium/content/browser/service_worker/service_worker_unregister_job.h b/chromium/content/browser/service_worker/service_worker_unregister_job.h
index 484318136f3..fef9c272de6 100644
--- a/chromium/content/browser/service_worker/service_worker_unregister_job.h
+++ b/chromium/content/browser/service_worker/service_worker_unregister_job.h
@@ -32,29 +32,30 @@ class ServiceWorkerUnregisterJob : public ServiceWorkerRegisterJobBase {
ServiceWorkerUnregisterJob(base::WeakPtr<ServiceWorkerContextCore> context,
const GURL& pattern);
- virtual ~ServiceWorkerUnregisterJob();
+ ~ServiceWorkerUnregisterJob() override;
// Registers a callback to be called when the job completes (whether
// successfully or not). Multiple callbacks may be registered.
void AddCallback(const UnregistrationCallback& callback);
// ServiceWorkerRegisterJobBase implementation:
- virtual void Start() OVERRIDE;
- virtual void Abort() OVERRIDE;
- virtual bool Equals(ServiceWorkerRegisterJobBase* job) OVERRIDE;
- virtual RegistrationJobType GetType() OVERRIDE;
+ void Start() override;
+ void Abort() override;
+ bool Equals(ServiceWorkerRegisterJobBase* job) override;
+ RegistrationJobType GetType() override;
private:
- void DeleteExistingRegistration(
+ void OnRegistrationFound(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
void Complete(ServiceWorkerStatusCode status);
void CompleteInternal(ServiceWorkerStatusCode status);
+ void ResolvePromise(ServiceWorkerStatusCode status);
- // The ServiceWorkerStorage object should always outlive this.
base::WeakPtr<ServiceWorkerContextCore> context_;
const GURL pattern_;
std::vector<UnregistrationCallback> callbacks_;
+ bool is_promise_resolved_;
base::WeakPtrFactory<ServiceWorkerUnregisterJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerUnregisterJob);
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.cc b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
index 9d75b93ec25..0e6ef2b98fc 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
@@ -4,17 +4,30 @@
#include "content/browser/service_worker/service_worker_url_request_job.h"
+#include <map>
+#include <string>
+#include <vector>
+
#include "base/bind.h"
+#include "base/guid.h"
#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/common/resource_request_body.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/browser/blob_handle.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/browser/service_worker_context.h"
+#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
-#include "webkit/browser/blob/blob_data_handle.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/blob/blob_url_request_job_factory.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "ui/base/page_transition_types.h"
namespace content {
@@ -22,12 +35,24 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context)
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ scoped_refptr<ResourceRequestBody> body)
: net::URLRequestJob(request, network_delegate),
provider_host_(provider_host),
response_type_(NOT_DETERMINED),
is_started_(false),
+ service_worker_response_type_(blink::WebServiceWorkerResponseTypeDefault),
blob_storage_context_(blob_storage_context),
+ request_mode_(request_mode),
+ credentials_mode_(credentials_mode),
+ request_context_type_(request_context_type),
+ frame_type_(frame_type),
+ fall_back_required_(false),
+ body_(body),
weak_factory_(this) {
}
@@ -76,6 +101,12 @@ void ServiceWorkerURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) {
if (!http_info())
return;
*info = *http_info();
+ info->response_time = response_time_;
+}
+
+void ServiceWorkerURLRequestJob::GetLoadTimingInfo(
+ net::LoadTimingInfo* load_timing_info) const {
+ *load_timing_info = load_timing_info_;
}
int ServiceWorkerURLRequestJob::GetResponseCode() const {
@@ -113,9 +144,10 @@ bool ServiceWorkerURLRequestJob::ReadRawData(
return status.is_success();
}
-void ServiceWorkerURLRequestJob::OnReceivedRedirect(net::URLRequest* request,
- const GURL& new_url,
- bool* defer_redirect) {
+void ServiceWorkerURLRequestJob::OnReceivedRedirect(
+ net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) {
NOTREACHED();
}
@@ -146,6 +178,7 @@ void ServiceWorkerURLRequestJob::OnBeforeNetworkStart(net::URLRequest* request,
void ServiceWorkerURLRequestJob::OnResponseStarted(net::URLRequest* request) {
// TODO(falken): Add Content-Length, Content-Type if they were not provided in
// the ServiceWorkerResponse.
+ response_time_ = base::Time::Now();
CommitResponseHeader();
}
@@ -169,6 +202,32 @@ const net::HttpResponseInfo* ServiceWorkerURLRequestJob::http_info() const {
return http_response_info_.get();
}
+void ServiceWorkerURLRequestJob::GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const {
+ if (response_type_ != FORWARD_TO_SERVICE_WORKER) {
+ *was_fetched_via_service_worker = false;
+ *was_fallback_required_by_service_worker = false;
+ *original_url_via_service_worker = GURL();
+ *response_type_via_service_worker =
+ blink::WebServiceWorkerResponseTypeDefault;
+ return;
+ }
+ *was_fetched_via_service_worker = true;
+ *was_fallback_required_by_service_worker = fall_back_required_;
+ *original_url_via_service_worker = response_url_;
+ *response_type_via_service_worker = service_worker_response_type_;
+ *fetch_start_time = fetch_start_time_;
+ *fetch_ready_time = fetch_ready_time_;
+ *fetch_end_time = fetch_end_time_;
+}
+
+
ServiceWorkerURLRequestJob::~ServiceWorkerURLRequestJob() {
}
@@ -198,13 +257,17 @@ void ServiceWorkerURLRequestJob::StartRequest() {
case FORWARD_TO_SERVICE_WORKER:
DCHECK(provider_host_ && provider_host_->active_version());
DCHECK(!fetch_dispatcher_);
-
// Send a fetch event to the ServiceWorker associated to the
// provider_host.
fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
- request(), provider_host_->active_version(),
+ CreateFetchRequest(),
+ provider_host_->active_version(),
+ base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
+ weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
weak_factory_.GetWeakPtr())));
+ fetch_start_time_ = base::TimeTicks::Now();
+ load_timing_info_.send_start = fetch_start_time_;
fetch_dispatcher_->Run();
return;
}
@@ -212,6 +275,104 @@ void ServiceWorkerURLRequestJob::StartRequest() {
NOTREACHED();
}
+scoped_ptr<ServiceWorkerFetchRequest>
+ServiceWorkerURLRequestJob::CreateFetchRequest() {
+ std::string blob_uuid;
+ uint64 blob_size = 0;
+ CreateRequestBodyBlob(&blob_uuid, &blob_size);
+ scoped_ptr<ServiceWorkerFetchRequest> request(
+ new ServiceWorkerFetchRequest());
+ request->mode = request_mode_;
+ request->request_context_type = request_context_type_;
+ request->frame_type = frame_type_;
+ request->url = request_->url();
+ request->method = request_->method();
+ const net::HttpRequestHeaders& headers = request_->extra_request_headers();
+ for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) {
+ if (ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(it.name()))
+ continue;
+ request->headers[it.name()] = it.value();
+ }
+ request->blob_uuid = blob_uuid;
+ request->blob_size = blob_size;
+ request->referrer = GURL(request_->referrer());
+ request->credentials_mode = credentials_mode_;
+ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_);
+ if (info) {
+ request->is_reload = ui::PageTransitionCoreTypeIs(
+ info->GetPageTransition(), ui::PAGE_TRANSITION_RELOAD);
+ }
+ return request.Pass();
+}
+
+bool ServiceWorkerURLRequestJob::CreateRequestBodyBlob(std::string* blob_uuid,
+ uint64* blob_size) {
+ if (!body_.get() || !blob_storage_context_)
+ return false;
+
+ std::vector<const ResourceRequestBody::Element*> resolved_elements;
+ for (size_t i = 0; i < body_->elements()->size(); ++i) {
+ const ResourceRequestBody::Element& element = (*body_->elements())[i];
+ if (element.type() != ResourceRequestBody::Element::TYPE_BLOB) {
+ resolved_elements.push_back(&element);
+ continue;
+ }
+ scoped_ptr<storage::BlobDataHandle> handle =
+ blob_storage_context_->GetBlobDataFromUUID(element.blob_uuid());
+ if (handle->data()->items().empty())
+ continue;
+ for (size_t i = 0; i < handle->data()->items().size(); ++i) {
+ const storage::BlobData::Item& item = handle->data()->items().at(i);
+ DCHECK_NE(storage::BlobData::Item::TYPE_BLOB, item.type());
+ resolved_elements.push_back(&item);
+ }
+ }
+
+ const std::string uuid(base::GenerateGUID());
+ uint64 total_size = 0;
+ scoped_refptr<storage::BlobData> blob_data = new storage::BlobData(uuid);
+ for (size_t i = 0; i < resolved_elements.size(); ++i) {
+ const ResourceRequestBody::Element& element = *resolved_elements[i];
+ if (total_size != kuint64max && element.length() != kuint64max)
+ total_size += element.length();
+ else
+ total_size = kuint64max;
+ switch (element.type()) {
+ case ResourceRequestBody::Element::TYPE_BYTES:
+ blob_data->AppendData(element.bytes(), element.length());
+ break;
+ case ResourceRequestBody::Element::TYPE_FILE:
+ blob_data->AppendFile(element.path(),
+ element.offset(),
+ element.length(),
+ element.expected_modification_time());
+ break;
+ case ResourceRequestBody::Element::TYPE_BLOB:
+ // Blob elements should be resolved beforehand.
+ NOTREACHED();
+ break;
+ case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
+ blob_data->AppendFileSystemFile(element.filesystem_url(),
+ element.offset(),
+ element.length(),
+ element.expected_modification_time());
+ break;
+ default:
+ NOTIMPLEMENTED();
+ }
+ }
+
+ request_body_blob_data_handle_ =
+ blob_storage_context_->AddFinishedBlob(blob_data.get());
+ *blob_uuid = uuid;
+ *blob_size = total_size;
+ return true;
+}
+
+void ServiceWorkerURLRequestJob::DidPrepareFetchEvent() {
+ fetch_ready_time_ = base::TimeTicks::Now();
+}
+
void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
@@ -234,6 +395,18 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
}
if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) {
+ // When the request_mode is |CORS| or |CORS-with-forced-preflight| we can't
+ // simply fallback to the network in the browser process. It is because the
+ // CORS preflight logic is implemented in the renderer. So we returns a
+ // fall_back_required response to the renderer.
+ if (request_mode_ == FETCH_REQUEST_MODE_CORS ||
+ request_mode_ == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT) {
+ fall_back_required_ = true;
+ CreateResponseHeader(
+ 400, "Service Worker Fallback Required", ServiceWorkerHeaderMap());
+ CommitResponseHeader();
+ return;
+ }
// Change the response type and restart the request to fallback to
// the network.
response_type_ = FALLBACK_TO_NETWORK;
@@ -244,22 +417,35 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
// We should have a response now.
DCHECK_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, fetch_result);
+ // Treat a response whose status is 0 as a Network Error.
+ if (response.status_code == 0) {
+ NotifyDone(
+ net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_FAILED));
+ return;
+ }
+
+ fetch_end_time_ = base::TimeTicks::Now();
+ load_timing_info_.send_end = fetch_end_time_;
+
// Set up a request for reading the blob.
if (!response.blob_uuid.empty() && blob_storage_context_) {
- scoped_ptr<webkit_blob::BlobDataHandle> blob_data_handle =
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle =
blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid);
if (!blob_data_handle) {
// The renderer gave us a bad blob UUID.
DeliverErrorResponse();
return;
}
- blob_request_ = webkit_blob::BlobProtocolHandler::CreateBlobRequest(
+ blob_request_ = storage::BlobProtocolHandler::CreateBlobRequest(
blob_data_handle.Pass(), request()->context(), this);
blob_request_->Start();
}
+ response_url_ = response.url;
+ service_worker_response_type_ = response.response_type;
CreateResponseHeader(
response.status_code, response.status_text, response.headers);
+ load_timing_info_.receive_headers_end = base::TimeTicks::Now();
if (!blob_request_)
CommitResponseHeader();
}
@@ -267,14 +453,14 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
void ServiceWorkerURLRequestJob::CreateResponseHeader(
int status_code,
const std::string& status_text,
- const std::map<std::string, std::string>& headers) {
+ const ServiceWorkerHeaderMap& headers) {
// TODO(kinuko): If the response has an identifier to on-disk cache entry,
// pull response header from the disk.
std::string status_line(
base::StringPrintf("HTTP/1.1 %d %s", status_code, status_text.c_str()));
status_line.push_back('\0');
http_response_headers_ = new net::HttpResponseHeaders(status_line);
- for (std::map<std::string, std::string>::const_iterator it = headers.begin();
+ for (ServiceWorkerHeaderMap::const_iterator it = headers.begin();
it != headers.end();
++it) {
std::string header;
@@ -295,9 +481,8 @@ void ServiceWorkerURLRequestJob::CommitResponseHeader() {
void ServiceWorkerURLRequestJob::DeliverErrorResponse() {
// TODO(falken): Print an error to the console of the ServiceWorker and of
// the requesting page.
- CreateResponseHeader(500,
- "Service Worker Response Error",
- std::map<std::string, std::string>());
+ CreateResponseHeader(
+ 500, "Service Worker Response Error", ServiceWorkerHeaderMap());
CommitResponseHeader();
}
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.h b/chromium/content/browser/service_worker/service_worker_url_request_job.h
index 498058cffb4..e8f0f0b2f7d 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.h
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.h
@@ -5,20 +5,30 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_URL_REQUEST_JOB_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_URL_REQUEST_JOB_H_
+#include <map>
+#include <string>
+
#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
#include "net/http/http_byte_range.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
-namespace webkit_blob {
+namespace storage {
+class BlobDataHandle;
class BlobStorageContext;
}
namespace content {
+class ResourceRequestBody;
class ServiceWorkerContextCore;
class ServiceWorkerFetchDispatcher;
class ServiceWorkerProviderHost;
@@ -31,7 +41,12 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context);
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
+ FetchRequestMode request_mode,
+ FetchCredentialsMode credentials_mode,
+ RequestContextType request_context_type,
+ RequestContextFrameType frame_type,
+ scoped_refptr<ResourceRequestBody> body);
// Sets the response type.
void FallbackToNetwork();
@@ -45,42 +60,47 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
}
// net::URLRequestJob overrides:
- virtual void Start() OVERRIDE;
- virtual void Kill() OVERRIDE;
- virtual net::LoadState GetLoadState() const OVERRIDE;
- virtual bool GetCharset(std::string* charset) OVERRIDE;
- virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
- virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE;
- virtual int GetResponseCode() const OVERRIDE;
- virtual void SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) OVERRIDE;
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int *bytes_read) OVERRIDE;
+ void Start() override;
+ void Kill() override;
+ net::LoadState GetLoadState() const override;
+ bool GetCharset(std::string* charset) override;
+ bool GetMimeType(std::string* mime_type) const override;
+ void GetResponseInfo(net::HttpResponseInfo* info) override;
+ void GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override;
+ int GetResponseCode() const override;
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
// net::URLRequest::Delegate overrides that read the blob from the
// ServiceWorkerFetchResponse.
- virtual void OnReceivedRedirect(net::URLRequest* request,
- const GURL& new_url,
- bool* defer_redirect) OVERRIDE;
- virtual void OnAuthRequired(net::URLRequest* request,
- net::AuthChallengeInfo* auth_info) OVERRIDE;
- virtual void OnCertificateRequested(
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) override;
+ void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* auth_info) override;
+ void OnCertificateRequested(
net::URLRequest* request,
- net::SSLCertRequestInfo* cert_request_info) OVERRIDE;
- virtual void OnSSLCertificateError(net::URLRequest* request,
- const net::SSLInfo& ssl_info,
- bool fatal) OVERRIDE;
- virtual void OnBeforeNetworkStart(net::URLRequest* request,
- bool* defer) OVERRIDE;
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
- virtual void OnReadCompleted(net::URLRequest* request,
- int bytes_read) OVERRIDE;
+ net::SSLCertRequestInfo* cert_request_info) override;
+ void OnSSLCertificateError(net::URLRequest* request,
+ const net::SSLInfo& ssl_info,
+ bool fatal) override;
+ void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override;
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
const net::HttpResponseInfo* http_info() const;
+ void GetExtraResponseInfo(
+ bool* was_fetched_via_service_worker,
+ bool* was_fallback_required_by_service_worker,
+ GURL* original_url_via_service_worker,
+ blink::WebServiceWorkerResponseType* response_type_via_service_worker,
+ base::TimeTicks* fetch_start_time,
+ base::TimeTicks* fetch_ready_time,
+ base::TimeTicks* fetch_end_time) const;
+
protected:
- virtual ~ServiceWorkerURLRequestJob();
+ ~ServiceWorkerURLRequestJob() override;
private:
enum ResponseType {
@@ -94,7 +114,16 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
void MaybeStartRequest();
void StartRequest();
+ // Creates ServiceWorkerFetchRequest from |request_| and |body_|.
+ scoped_ptr<ServiceWorkerFetchRequest> CreateFetchRequest();
+
+ // Creates BlobDataHandle of the request body from |body_|. This handle
+ // |request_body_blob_data_handle_| will be deleted when
+ // ServiceWorkerURLRequestJob is deleted.
+ bool CreateRequestBodyBlob(std::string* blob_uuid, uint64* blob_size);
+
// For FORWARD_TO_SERVICE_WORKER case.
+ void DidPrepareFetchEvent();
void DidDispatchFetchEvent(ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response);
@@ -102,7 +131,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
// Populates |http_response_headers_|.
void CreateResponseHeader(int status_code,
const std::string& status_text,
- const std::map<std::string, std::string>& headers);
+ const ServiceWorkerHeaderMap& headers);
// Creates |http_response_info_| using |http_response_headers_| and calls
// NotifyHeadersComplete.
@@ -113,6 +142,13 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ // Timing info to show on the popup in Devtools' Network tab.
+ net::LoadTimingInfo load_timing_info_;
+ base::TimeTicks fetch_start_time_;
+ base::TimeTicks fetch_ready_time_;
+ base::TimeTicks fetch_end_time_;
+ base::Time response_time_;
+
ResponseType response_type_;
bool is_started_;
@@ -121,11 +157,22 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
scoped_ptr<net::HttpResponseInfo> http_response_info_;
// Headers that have not yet been committed to |http_response_info_|.
scoped_refptr<net::HttpResponseHeaders> http_response_headers_;
+ GURL response_url_;
+ blink::WebServiceWorkerResponseType service_worker_response_type_;
// Used when response type is FORWARD_TO_SERVICE_WORKER.
scoped_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context_;
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
scoped_ptr<net::URLRequest> blob_request_;
+ FetchRequestMode request_mode_;
+ FetchCredentialsMode credentials_mode_;
+ RequestContextType request_context_type_;
+ RequestContextFrameType frame_type_;
+ bool fall_back_required_;
+ // ResourceRequestBody has a collection of BlobDataHandles attached to it
+ // using the userdata mechanism. So we have to keep it not to free the blobs.
+ scoped_refptr<ResourceRequestBody> body_;
+ scoped_ptr<storage::BlobDataHandle> request_body_blob_data_handle_;
base::WeakPtrFactory<ServiceWorkerURLRequestJob> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 54a2cc966fc..76f718e27dc 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -17,8 +17,12 @@
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/blob_handle.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/io_buffer.h"
@@ -27,11 +31,11 @@
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory_impl.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "storage/common/blob/blob_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/blob/blob_url_request_job.h"
-#include "webkit/browser/blob/blob_url_request_job_factory.h"
-#include "webkit/common/blob/blob_data.h"
namespace content {
@@ -48,32 +52,40 @@ class MockHttpProtocolHandler
public:
MockHttpProtocolHandler(
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context)
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context)
: provider_host_(provider_host),
blob_storage_context_(blob_storage_context) {}
- virtual ~MockHttpProtocolHandler() {}
+ ~MockHttpProtocolHandler() override {}
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
- ServiceWorkerURLRequestJob* job = new ServiceWorkerURLRequestJob(
- request, network_delegate, provider_host_, blob_storage_context_);
+ net::NetworkDelegate* network_delegate) const override {
+ ServiceWorkerURLRequestJob* job =
+ new ServiceWorkerURLRequestJob(request,
+ network_delegate,
+ provider_host_,
+ blob_storage_context_,
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_CREDENTIALS_MODE_OMIT,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ scoped_refptr<ResourceRequestBody>());
job->ForwardToServiceWorker();
return job;
}
private:
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
- base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context_;
+ base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
};
// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
// the memory.
-webkit_blob::BlobProtocolHandler* CreateMockBlobProtocolHandler(
- webkit_blob::BlobStorageContext* blob_storage_context) {
+storage::BlobProtocolHandler* CreateMockBlobProtocolHandler(
+ storage::BlobStorageContext* blob_storage_context) {
// The FileSystemContext and MessageLoopProxy are not actually used but a
// MessageLoopProxy is needed to avoid a DCHECK in BlobURLRequestJob ctor.
- return new webkit_blob::BlobProtocolHandler(
+ return new storage::BlobProtocolHandler(
blob_storage_context, NULL, base::MessageLoopProxy::current().get());
}
@@ -83,10 +95,10 @@ class ServiceWorkerURLRequestJobTest : public testing::Test {
protected:
ServiceWorkerURLRequestJobTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- blob_data_(new webkit_blob::BlobData("blob-id:myblob")) {}
- virtual ~ServiceWorkerURLRequestJobTest() {}
+ blob_data_(new storage::BlobData("blob-id:myblob")) {}
+ ~ServiceWorkerURLRequestJobTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
browser_context_.reset(new TestBrowserContext);
SetUpWithHelper(new EmbeddedWorkerTestHelper(kProcessID));
}
@@ -95,23 +107,26 @@ class ServiceWorkerURLRequestJobTest : public testing::Test {
helper_.reset(helper);
registration_ = new ServiceWorkerRegistration(
- GURL("http://example.com/*"),
- GURL("http://example.com/service_worker.js"),
+ GURL("http://example.com/"),
1L,
helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_, 1L, helper_->context()->AsWeakPtr());
+ registration_.get(),
+ GURL("http://example.com/service_worker.js"),
+ 1L,
+ helper_->context()->AsWeakPtr());
scoped_ptr<ServiceWorkerProviderHost> provider_host(
new ServiceWorkerProviderHost(
kProcessID, kProviderID, helper_->context()->AsWeakPtr(), NULL));
- provider_host->SetActiveVersion(version_.get());
+ provider_host->AssociateRegistration(registration_.get());
+ registration_->SetActiveVersion(version_.get());
ChromeBlobStorageContext* chrome_blob_storage_context =
ChromeBlobStorageContext::GetFor(browser_context_.get());
// Wait for chrome_blob_storage_context to finish initializing.
base::RunLoop().RunUntilIdle();
- webkit_blob::BlobStorageContext* blob_storage_context =
+ storage::BlobStorageContext* blob_storage_context =
chrome_blob_storage_context->context();
url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
@@ -126,7 +141,7 @@ class ServiceWorkerURLRequestJobTest : public testing::Test {
helper_->context()->AddProviderHost(provider_host.Pass());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
version_ = NULL;
registration_ = NULL;
helper_.reset();
@@ -164,49 +179,49 @@ class ServiceWorkerURLRequestJobTest : public testing::Test {
MockURLRequestDelegate url_request_delegate_;
scoped_ptr<net::URLRequest> request_;
- scoped_refptr<webkit_blob::BlobData> blob_data_;
+ scoped_refptr<storage::BlobData> blob_data_;
+ private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJobTest);
};
TEST_F(ServiceWorkerURLRequestJobTest, Simple) {
- version_->SetStatus(ServiceWorkerVersion::ACTIVE);
- TestRequest(200, "OK", std::string());
-}
-
-TEST_F(ServiceWorkerURLRequestJobTest, WaitForActivation) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->SetStatus(ServiceWorkerVersion::INSTALLED);
- version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
-
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
TestRequest(200, "OK", std::string());
-
- EXPECT_EQ(SERVICE_WORKER_OK, status);
}
// Responds to fetch events with a blob.
class BlobResponder : public EmbeddedWorkerTestHelper {
public:
- BlobResponder(int mock_render_process_id, const std::string& blob_uuid)
+ BlobResponder(int mock_render_process_id,
+ const std::string& blob_uuid,
+ uint64 blob_size)
: EmbeddedWorkerTestHelper(mock_render_process_id),
- blob_uuid_(blob_uuid) {}
- virtual ~BlobResponder() {}
+ blob_uuid_(blob_uuid),
+ blob_size_(blob_size) {}
+ ~BlobResponder() override {}
protected:
- virtual void OnFetchEvent(int embedded_worker_id,
- int request_id,
- const ServiceWorkerFetchRequest& request) OVERRIDE {
+ void OnFetchEvent(int embedded_worker_id,
+ int request_id,
+ const ServiceWorkerFetchRequest& request) override {
SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
embedded_worker_id,
request_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
- ServiceWorkerResponse(200,
+ ServiceWorkerResponse(GURL(""),
+ 200,
"OK",
- std::map<std::string, std::string>(),
- blob_uuid_)));
+ blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(),
+ blob_uuid_,
+ blob_size_)));
}
std::string blob_uuid_;
+ uint64 blob_size_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(BlobResponder);
};
@@ -218,17 +233,18 @@ TEST_F(ServiceWorkerURLRequestJobTest, BlobResponse) {
blob_data_->AppendData(kTestData);
expected_response += kTestData;
}
- scoped_ptr<webkit_blob::BlobDataHandle> blob_handle =
- blob_storage_context->context()->AddFinishedBlob(blob_data_);
- SetUpWithHelper(new BlobResponder(kProcessID, blob_handle->uuid()));
+ scoped_ptr<storage::BlobDataHandle> blob_handle =
+ blob_storage_context->context()->AddFinishedBlob(blob_data_.get());
+ SetUpWithHelper(new BlobResponder(
+ kProcessID, blob_handle->uuid(), expected_response.size()));
- version_->SetStatus(ServiceWorkerVersion::ACTIVE);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
TestRequest(200, "OK", expected_response);
}
TEST_F(ServiceWorkerURLRequestJobTest, NonExistentBlobUUIDResponse) {
- SetUpWithHelper(new BlobResponder(kProcessID, "blob-id:nothing-is-here"));
- version_->SetStatus(ServiceWorkerVersion::ACTIVE);
+ SetUpWithHelper(new BlobResponder(kProcessID, "blob-id:nothing-is-here", 0));
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
TestRequest(500, "Service Worker Response Error", std::string());
}
diff --git a/chromium/content/browser/service_worker/service_worker_utils.cc b/chromium/content/browser/service_worker/service_worker_utils.cc
index 2c3d05b773f..edbe9f97b22 100644
--- a/chromium/content/browser/service_worker/service_worker_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_utils.cc
@@ -6,59 +6,25 @@
#include <string>
-#include "base/command_line.h"
#include "base/logging.h"
-#include "content/public/common/content_switches.h"
-#include "url/gurl.h"
+#include "base/strings/string_util.h"
namespace content {
// static
-bool ServiceWorkerUtils::IsFeatureEnabled() {
- static bool enabled = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableServiceWorker);
- return enabled;
-}
-
-// static
bool ServiceWorkerUtils::ScopeMatches(const GURL& scope, const GURL& url) {
DCHECK(!scope.has_ref());
DCHECK(!url.has_ref());
- const std::string& scope_spec = scope.spec();
- const std::string& url_spec = url.spec();
-
- size_t len = scope_spec.size();
- if (len > 0 && scope_spec[len - 1] == '*')
- return scope_spec.compare(0, len - 1, url_spec, 0, len - 1) == 0;
- return scope_spec == url_spec;
+ return StartsWithASCII(url.spec(), scope.spec(), true);
}
bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
if (!ServiceWorkerUtils::ScopeMatches(scope, url_))
return false;
- if (match_.is_empty()) {
+ if (match_.is_empty() || match_.spec().size() < scope.spec().size()) {
match_ = scope;
return true;
}
-
- const std::string match_spec = match_.spec();
- const std::string scope_spec = scope.spec();
- if (match_spec.size() < scope_spec.size()) {
- match_ = scope;
- return true;
- }
-
- // If |scope| has the same length with |match_|, they are compared as strings.
- // For example:
- // 1) for a document "/foo", "/foo" is prioritized over "/fo*".
- // 2) for a document "/f(1)", "/f(1*" is prioritized over "/f(1)".
- // TODO(nhiroki): This isn't in the spec.
- // (https://github.com/slightlyoff/ServiceWorker/issues/287)
- if (match_spec.size() == scope_spec.size() && match_spec < scope_spec) {
- match_ = scope;
- return true;
- }
-
return false;
}
diff --git a/chromium/content/browser/service_worker/service_worker_utils.h b/chromium/content/browser/service_worker/service_worker_utils.h
index 25700dee2bd..81d6c44f17c 100644
--- a/chromium/content/browser/service_worker/service_worker_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_utils.h
@@ -5,29 +5,20 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_UTILS_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_UTILS_H_
+#include "base/macros.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
-#include "webkit/common/resource_type.h"
-
-class GURL;
+#include "content/public/common/resource_type.h"
+#include "url/gurl.h"
namespace content {
class ServiceWorkerUtils {
public:
- static bool IsMainResourceType(ResourceType::Type type) {
- return ResourceType::IsFrame(type) ||
- ResourceType::IsSharedWorker(type);
- }
-
- static bool IsServiceWorkerResourceType(ResourceType::Type type) {
- return ResourceType::IsServiceWorker(type);
+ static bool IsMainResourceType(ResourceType type) {
+ return IsResourceTypeFrame(type) || type == RESOURCE_TYPE_SHARED_WORKER;
}
- // Returns true if the feature is enabled (or not disabled) by command-line
- // flag.
- static bool IsFeatureEnabled();
-
// A helper for creating a do-nothing status callback.
static void NoOpStatusCallback(ServiceWorkerStatusCode status) {}
diff --git a/chromium/content/browser/service_worker/service_worker_utils_unittest.cc b/chromium/content/browser/service_worker/service_worker_utils_unittest.cc
index 67a74801d6c..30e26b49d43 100644
--- a/chromium/content/browser/service_worker/service_worker_utils_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_utils_unittest.cc
@@ -9,26 +9,42 @@ namespace content {
TEST(ServiceWorkerUtilsTest, ScopeMatches) {
ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"), GURL("http://www.example.com/")));
+ GURL("http://www.example.com/"), GURL("http://www.example.com/")));
ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("http://www.example.com/page.html")));
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"), GURL("https://www.example.com/")));
+ GURL("http://www.example.com/"), GURL("https://www.example.com/")));
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"),
+ GURL("http://www.example.com/"),
GURL("https://www.example.com/page.html")));
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"), GURL("http://www.foo.com/")));
+ GURL("http://www.example.com/"), GURL("http://www.foo.com/")));
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"), GURL("https://www.foo.com/page.html")));
+ GURL("http://www.example.com/"), GURL("https://www.foo.com/page.html")));
+ // '*' is not a wildcard.
+ ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
+ GURL("http://www.example.com/*"), GURL("http://www.example.com/x")));
+ ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
+ GURL("http://www.example.com/*"), GURL("http://www.example.com/")));
+ ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
+ GURL("http://www.example.com/*"), GURL("http://www.example.com/xx")));
ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/"), GURL("http://www.example.com/")));
+ GURL("http://www.example.com/*"), GURL("http://www.example.com/*")));
+
+ ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
+ GURL("http://www.example.com/*/x"), GURL("http://www.example.com/*/x")));
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/"), GURL("http://www.example.com/x")));
+ GURL("http://www.example.com/*/x"), GURL("http://www.example.com/a/x")));
+ ASSERT_FALSE(
+ ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/*/x/*"),
+ GURL("http://www.example.com/a/x/b")));
+ ASSERT_FALSE(
+ ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/*/x/*"),
+ GURL("http://www.example.com/*/x/b")));
// '?' is not a wildcard.
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
@@ -45,59 +61,28 @@ TEST(ServiceWorkerUtilsTest, ScopeMatches) {
ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/?a=b"),
GURL("http://www.example.com/?a=b")));
ASSERT_TRUE(
- ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/?a=*"),
+ ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/?a="),
GURL("http://www.example.com/?a=b")));
ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*"), GURL("http://www.example.com/?a=b")));
- ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
GURL("http://www.example.com/"), GURL("http://www.example.com/?a=b")));
- // '*' only has special meaning in terminal position.
+ // URLs canonicalize \ to / so this is equivalent to "...//x"
ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*/x"), GURL("http://www.example.com/*/x")));
- ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/*/x"), GURL("http://www.example.com/a/x")));
- ASSERT_FALSE(
- ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/*/x/*"),
- GURL("http://www.example.com/a/x/b")));
- ASSERT_TRUE(
- ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/*/x/*"),
- GURL("http://www.example.com/*/x/b")));
-
- // URLs canonicalize \ to / so this is equivalent to "...//*" and "...//x"
- ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
- GURL("http://www.example.com/\\*"), GURL("http://www.example.com/\\x")));
+ GURL("http://www.example.com/\\x"), GURL("http://www.example.com//x")));
}
-TEST(ServiceWorkerUtilsTest, FindLongestScopeMatch_Basic) {
+TEST(ServiceWorkerUtilsTest, FindLongestScopeMatch) {
LongestScopeMatcher matcher(GURL("http://www.example.com/xxx"));
- // "/xx*" should be matched longest.
- ASSERT_TRUE(matcher.MatchLongest(GURL("http://www.example.com/x*")));
- ASSERT_FALSE(matcher.MatchLongest(GURL("http://www.example.com/*")));
- ASSERT_TRUE(matcher.MatchLongest(GURL("http://www.example.com/xx*")));
-
- // "xxx*" should be matched longer than "/xx*".
- ASSERT_TRUE(matcher.MatchLongest(GURL("http://www.example.com/xxx*")));
-
- ASSERT_FALSE(matcher.MatchLongest(GURL("http://www.example.com/xxxx*")));
-}
-
-TEST(ServiceWorkerUtilsTest, FindLongestScopeMatch_SameLength) {
- LongestScopeMatcher matcher1(GURL("http://www.example.com/xxx"));
-
- // "/xxx" has the same length with "/xx*", so they are compared as strings
- // and "/xxx" should win.
- // TODO(nhiroki): This isn't in the spec (see: service_worker_utils.cc)
- ASSERT_TRUE(matcher1.MatchLongest(GURL("http://www.example.com/xxx")));
- ASSERT_FALSE(matcher1.MatchLongest(GURL("http://www.example.com/xx*")));
+ // "/xx" should be matched longest.
+ ASSERT_TRUE(matcher.MatchLongest(GURL("http://www.example.com/x")));
+ ASSERT_FALSE(matcher.MatchLongest(GURL("http://www.example.com/")));
+ ASSERT_TRUE(matcher.MatchLongest(GURL("http://www.example.com/xx")));
- LongestScopeMatcher matcher2(GURL("http://www.example.com/x(1)"));
+ // "/xxx" should be matched longer than "/xx".
+ ASSERT_TRUE(matcher.MatchLongest(GURL("http://www.example.com/xxx")));
- // "/xx*" should be prioritized over "/x(1)".
- // TODO(nhiroki): This isn't in the spec (see: service_worker_utils.cc)
- ASSERT_TRUE(matcher2.MatchLongest(GURL("http://www.example.com/x(1)")));
- ASSERT_TRUE(matcher2.MatchLongest(GURL("http://www.example.com/x(1*")));
+ ASSERT_FALSE(matcher.MatchLongest(GURL("http://www.example.com/xxxx")));
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 50f24df48b6..30d9fd5a0a1 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -23,12 +23,14 @@ typedef ServiceWorkerVersion::MessageCallback MessageCallback;
namespace {
-// Default delay to stop the worker context after all documents that
-// are associated to the worker are closed.
+// Default delay for scheduled stop.
// (Note that if all references to the version is dropped the worker
// is also stopped without delay)
const int64 kStopWorkerDelay = 30; // 30 secs.
+// Default delay for scheduled update.
+const int kUpdateDelaySeconds = 1;
+
void RunSoon(const base::Closure& callback) {
if (!callback.is_null())
base::MessageLoop::current()->PostTask(FROM_HERE, callback);
@@ -89,19 +91,21 @@ void RunErrorFetchCallback(const ServiceWorkerVersion::FetchCallback& callback,
ServiceWorkerVersion::ServiceWorkerVersion(
ServiceWorkerRegistration* registration,
+ const GURL& script_url,
int64 version_id,
base::WeakPtr<ServiceWorkerContextCore> context)
: version_id_(version_id),
registration_id_(kInvalidServiceWorkerVersionId),
+ script_url_(script_url),
status_(NEW),
context_(context),
script_cache_map_(this, context),
+ is_doomed_(false),
weak_factory_(this) {
DCHECK(context_);
DCHECK(registration);
if (registration) {
registration_id_ = registration->id();
- script_url_ = registration->script_url();
scope_ = registration->pattern();
}
context_->AddLiveVersion(this);
@@ -120,6 +124,10 @@ void ServiceWorkerVersion::SetStatus(Status status) {
if (status_ == status)
return;
+ // Schedule to stop worker after registration successfully completed.
+ if (status_ == ACTIVATING && status == ACTIVATED && !HasControllee())
+ ScheduleStopWorker();
+
status_ = status;
std::vector<base::Closure> callbacks;
@@ -142,6 +150,7 @@ ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
return ServiceWorkerVersionInfo(
running_status(),
status(),
+ script_url(),
version_id(),
embedded_worker()->process_id(),
embedded_worker()->thread_id(),
@@ -149,11 +158,11 @@ ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
}
void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) {
- StartWorkerWithCandidateProcesses(std::vector<int>(), callback);
+ StartWorker(false, callback);
}
-void ServiceWorkerVersion::StartWorkerWithCandidateProcesses(
- const std::vector<int>& possible_process_ids,
+void ServiceWorkerVersion::StartWorker(
+ bool pause_after_download,
const StatusCallback& callback) {
switch (running_status()) {
case RUNNING:
@@ -166,12 +175,14 @@ void ServiceWorkerVersion::StartWorkerWithCandidateProcesses(
case STARTING:
start_callbacks_.push_back(callback);
if (running_status() == STOPPED) {
+ DCHECK(!cache_listener_.get());
+ cache_listener_.reset(new ServiceWorkerCacheListener(this, context_));
embedded_worker_->Start(
version_id_,
scope_,
script_url_,
- possible_process_ids,
- base::Bind(&ServiceWorkerVersion::RunStartWorkerCallbacksOnError,
+ pause_after_download,
+ base::Bind(&ServiceWorkerVersion::OnStartMessageSent,
weak_factory_.GetWeakPtr()));
}
return;
@@ -193,6 +204,33 @@ void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
stop_callbacks_.push_back(callback);
}
+void ServiceWorkerVersion::ScheduleUpdate() {
+ if (update_timer_.IsRunning()) {
+ update_timer_.Reset();
+ return;
+ }
+ update_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(kUpdateDelaySeconds),
+ base::Bind(&ServiceWorkerVersion::StartUpdate,
+ weak_factory_.GetWeakPtr()));
+}
+
+void ServiceWorkerVersion::DeferScheduledUpdate() {
+ if (update_timer_.IsRunning())
+ update_timer_.Reset();
+}
+
+void ServiceWorkerVersion::StartUpdate() {
+ update_timer_.Stop();
+ if (!context_)
+ return;
+ ServiceWorkerRegistration* registration =
+ context_->GetLiveRegistration(registration_id_);
+ if (!registration || !registration->GetNewestVersion())
+ return;
+ context_->UpdateServiceWorker(registration);
+}
+
void ServiceWorkerVersion::SendMessage(
const IPC::Message& message, const StatusCallback& callback) {
if (running_status() != RUNNING) {
@@ -212,8 +250,7 @@ void ServiceWorkerVersion::SendMessage(
void ServiceWorkerVersion::DispatchInstallEvent(
int active_version_id,
const StatusCallback& callback) {
- DCHECK_EQ(NEW, status()) << status();
- SetStatus(INSTALLING);
+ DCHECK_EQ(INSTALLING, status()) << status();
if (running_status() != RUNNING) {
// Schedule calling this method after starting the worker.
@@ -232,8 +269,7 @@ void ServiceWorkerVersion::DispatchInstallEvent(
void ServiceWorkerVersion::DispatchActivateEvent(
const StatusCallback& callback) {
- DCHECK_EQ(INSTALLED, status()) << status();
- SetStatus(ACTIVATING);
+ DCHECK_EQ(ACTIVATING, status()) << status();
if (running_status() != RUNNING) {
// Schedule calling this method after starting the worker.
@@ -251,33 +287,38 @@ void ServiceWorkerVersion::DispatchActivateEvent(
void ServiceWorkerVersion::DispatchFetchEvent(
const ServiceWorkerFetchRequest& request,
- const FetchCallback& callback) {
- DCHECK_EQ(ACTIVE, status()) << status();
+ const base::Closure& prepare_callback,
+ const FetchCallback& fetch_callback) {
+ DCHECK_EQ(ACTIVATED, status()) << status();
if (running_status() != RUNNING) {
// Schedule calling this method after starting the worker.
StartWorker(base::Bind(&RunTaskAfterStartWorker,
weak_factory_.GetWeakPtr(),
- base::Bind(&RunErrorFetchCallback, callback),
+ base::Bind(&RunErrorFetchCallback, fetch_callback),
base::Bind(&self::DispatchFetchEvent,
weak_factory_.GetWeakPtr(),
- request, callback)));
+ request,
+ prepare_callback,
+ fetch_callback)));
return;
}
- int request_id = fetch_callbacks_.Add(new FetchCallback(callback));
+ prepare_callback.Run();
+
+ int request_id = fetch_callbacks_.Add(new FetchCallback(fetch_callback));
ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
ServiceWorkerMsg_FetchEvent(request_id, request));
if (status != SERVICE_WORKER_OK) {
fetch_callbacks_.Remove(request_id);
RunSoon(base::Bind(&RunErrorFetchCallback,
- callback,
+ fetch_callback,
SERVICE_WORKER_ERROR_FAILED));
}
}
void ServiceWorkerVersion::DispatchSyncEvent(const StatusCallback& callback) {
- DCHECK_EQ(ACTIVE, status()) << status();
+ DCHECK_EQ(ACTIVATED, status()) << status();
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorkerSync)) {
@@ -306,7 +347,7 @@ void ServiceWorkerVersion::DispatchSyncEvent(const StatusCallback& callback) {
void ServiceWorkerVersion::DispatchPushEvent(const StatusCallback& callback,
const std::string& data) {
- DCHECK_EQ(ACTIVE, status()) << status();
+ DCHECK_EQ(ACTIVATED, status()) << status();
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableExperimentalWebPlatformFeatures)) {
@@ -333,16 +374,41 @@ void ServiceWorkerVersion::DispatchPushEvent(const StatusCallback& callback,
}
}
-void ServiceWorkerVersion::AddProcessToWorker(int process_id) {
- embedded_worker_->AddProcessReference(process_id);
-}
+void ServiceWorkerVersion::DispatchGeofencingEvent(
+ const StatusCallback& callback,
+ blink::WebGeofencingEventType event_type,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region) {
+ DCHECK_EQ(ACTIVATED, status()) << status();
-void ServiceWorkerVersion::RemoveProcessFromWorker(int process_id) {
- embedded_worker_->ReleaseProcessReference(process_id);
-}
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ callback.Run(SERVICE_WORKER_ERROR_ABORT);
+ return;
+ }
+
+ if (running_status() != RUNNING) {
+ // Schedule calling this method after starting the worker.
+ StartWorker(base::Bind(&RunTaskAfterStartWorker,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ base::Bind(&self::DispatchGeofencingEvent,
+ weak_factory_.GetWeakPtr(),
+ callback,
+ event_type,
+ region_id,
+ region)));
+ return;
+ }
-bool ServiceWorkerVersion::HasProcessToRun() const {
- return embedded_worker_->HasProcessToRun();
+ int request_id = geofencing_callbacks_.Add(new StatusCallback(callback));
+ ServiceWorkerStatusCode status =
+ embedded_worker_->SendMessage(ServiceWorkerMsg_GeofencingEvent(
+ request_id, event_type, region_id, region));
+ if (status != SERVICE_WORKER_OK) {
+ geofencing_callbacks_.Remove(request_id);
+ RunSoon(base::Bind(callback, status));
+ }
}
void ServiceWorkerVersion::AddControllee(
@@ -350,7 +416,6 @@ void ServiceWorkerVersion::AddControllee(
DCHECK(!ContainsKey(controllee_map_, provider_host));
int controllee_id = controllee_by_id_.Add(provider_host);
controllee_map_[provider_host] = controllee_id;
- AddProcessToWorker(provider_host->process_id());
if (stop_worker_timer_.IsRunning())
stop_worker_timer_.Stop();
}
@@ -361,25 +426,14 @@ void ServiceWorkerVersion::RemoveControllee(
DCHECK(found != controllee_map_.end());
controllee_by_id_.Remove(found->second);
controllee_map_.erase(found);
- RemoveProcessFromWorker(provider_host->process_id());
- if (!HasControllee())
- ScheduleStopWorker();
- // TODO(kinuko): Fire NoControllees notification when the # of controllees
- // reaches 0, so that a new pending version can be activated (which will
- // deactivate this version).
- // TODO(michaeln): On no controllees call storage DeleteVersionResources
- // if this version has been deactivated. Probably storage can listen for
- // NoControllees for versions that have been deleted.
-}
-
-void ServiceWorkerVersion::AddWaitingControllee(
- ServiceWorkerProviderHost* provider_host) {
- AddProcessToWorker(provider_host->process_id());
-}
-
-void ServiceWorkerVersion::RemoveWaitingControllee(
- ServiceWorkerProviderHost* provider_host) {
- RemoveProcessFromWorker(provider_host->process_id());
+ if (HasControllee())
+ return;
+ FOR_EACH_OBSERVER(Listener, listeners_, OnNoControllees(this));
+ if (is_doomed_) {
+ DoomInternal();
+ return;
+ }
+ ScheduleStopWorker();
}
void ServiceWorkerVersion::AddListener(Listener* listener) {
@@ -390,8 +444,19 @@ void ServiceWorkerVersion::RemoveListener(Listener* listener) {
listeners_.RemoveObserver(listener);
}
+void ServiceWorkerVersion::Doom() {
+ if (is_doomed_)
+ return;
+ is_doomed_ = true;
+ if (!HasControllee())
+ DoomInternal();
+}
+
void ServiceWorkerVersion::OnStarted() {
DCHECK_EQ(RUNNING, running_status());
+ DCHECK(cache_listener_.get());
+ if (status() == ACTIVATED && !HasControllee())
+ ScheduleStopWorker();
// Fire all start callbacks.
RunCallbacks(this, &start_callbacks_, SERVICE_WORKER_OK);
FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStarted(this));
@@ -428,8 +493,16 @@ void ServiceWorkerVersion::OnStopped() {
RunIDMapCallbacks(&push_callbacks_,
&StatusCallback::Run,
MakeTuple(SERVICE_WORKER_ERROR_FAILED));
+ RunIDMapCallbacks(&geofencing_callbacks_,
+ &StatusCallback::Run,
+ MakeTuple(SERVICE_WORKER_ERROR_FAILED));
FOR_EACH_OBSERVER(Listener, listeners_, OnWorkerStopped(this));
+
+ // There should be no more communication from/to a stopped worker. Deleting
+ // the listener prevents any pending completion callbacks from causing
+ // messages to be sent to the stopped worker.
+ cache_listener_.reset();
}
void ServiceWorkerVersion::OnReportException(
@@ -474,6 +547,8 @@ bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
OnSyncEventFinished)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished,
OnPushEventFinished)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GeofencingEventFinished,
+ OnGeofencingEventFinished)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToDocument,
OnPostMessageToDocument)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -481,7 +556,7 @@ bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-void ServiceWorkerVersion::RunStartWorkerCallbacksOnError(
+void ServiceWorkerVersion::OnStartMessageSent(
ServiceWorkerStatusCode status) {
if (status != SERVICE_WORKER_OK)
RunCallbacks(this, &start_callbacks_, status);
@@ -492,6 +567,7 @@ void ServiceWorkerVersion::DispatchInstallEventAfterStartWorker(
const StatusCallback& callback) {
DCHECK_EQ(RUNNING, running_status())
<< "Worker stopped too soon after it was started.";
+
int request_id = install_callbacks_.Add(new StatusCallback(callback));
ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
ServiceWorkerMsg_InstallEvent(request_id, active_version_id));
@@ -505,6 +581,7 @@ void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker(
const StatusCallback& callback) {
DCHECK_EQ(RUNNING, running_status())
<< "Worker stopped too soon after it was started.";
+
int request_id = activate_callbacks_.Add(new StatusCallback(callback));
ServiceWorkerStatusCode status =
embedded_worker_->SendMessage(ServiceWorkerMsg_ActivateEvent(request_id));
@@ -517,6 +594,8 @@ void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker(
void ServiceWorkerVersion::OnGetClientDocuments(int request_id) {
std::vector<int> client_ids;
ControlleeByIDMap::iterator it(&controllee_by_id_);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerVersion::OnGetClientDocuments");
while (!it.IsAtEnd()) {
client_ids.push_back(it.GetCurrentKey());
it.Advance();
@@ -531,25 +610,34 @@ void ServiceWorkerVersion::OnGetClientDocuments(int request_id) {
void ServiceWorkerVersion::OnActivateEventFinished(
int request_id,
blink::WebServiceWorkerEventResult result) {
+ DCHECK(ACTIVATING == status() ||
+ REDUNDANT == status()) << status();
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerVersion::OnActivateEventFinished");
+
StatusCallback* callback = activate_callbacks_.Lookup(request_id);
if (!callback) {
NOTREACHED() << "Got unexpected message: " << request_id;
return;
}
- ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
- if (result == blink::WebServiceWorkerEventResultRejected)
- status = SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED;
- else
- SetStatus(ACTIVE);
+ ServiceWorkerStatusCode rv = SERVICE_WORKER_OK;
+ if (result == blink::WebServiceWorkerEventResultRejected ||
+ status() != ACTIVATING) {
+ rv = SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED;
+ }
scoped_refptr<ServiceWorkerVersion> protect(this);
- callback->Run(status);
+ callback->Run(rv);
activate_callbacks_.Remove(request_id);
}
void ServiceWorkerVersion::OnInstallEventFinished(
int request_id,
blink::WebServiceWorkerEventResult result) {
+ DCHECK_EQ(INSTALLING, status()) << status();
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerVersion::OnInstallEventFinished");
+
StatusCallback* callback = install_callbacks_.Lookup(request_id);
if (!callback) {
NOTREACHED() << "Got unexpected message: " << request_id;
@@ -558,8 +646,6 @@ void ServiceWorkerVersion::OnInstallEventFinished(
ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
if (result == blink::WebServiceWorkerEventResultRejected)
status = SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED;
- else
- SetStatus(INSTALLED);
scoped_refptr<ServiceWorkerVersion> protect(this);
callback->Run(status);
@@ -570,6 +656,9 @@ void ServiceWorkerVersion::OnFetchEventFinished(
int request_id,
ServiceWorkerFetchEventResult result,
const ServiceWorkerResponse& response) {
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerVersion::OnFetchEventFinished",
+ "Request id", request_id);
FetchCallback* callback = fetch_callbacks_.Lookup(request_id);
if (!callback) {
NOTREACHED() << "Got unexpected message: " << request_id;
@@ -583,6 +672,9 @@ void ServiceWorkerVersion::OnFetchEventFinished(
void ServiceWorkerVersion::OnSyncEventFinished(
int request_id) {
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerVersion::OnSyncEventFinished",
+ "Request id", request_id);
StatusCallback* callback = sync_callbacks_.Lookup(request_id);
if (!callback) {
NOTREACHED() << "Got unexpected message: " << request_id;
@@ -596,6 +688,9 @@ void ServiceWorkerVersion::OnSyncEventFinished(
void ServiceWorkerVersion::OnPushEventFinished(
int request_id) {
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerVersion::OnPushEventFinished",
+ "Request id", request_id);
StatusCallback* callback = push_callbacks_.Lookup(request_id);
if (!callback) {
NOTREACHED() << "Got unexpected message: " << request_id;
@@ -607,10 +702,29 @@ void ServiceWorkerVersion::OnPushEventFinished(
push_callbacks_.Remove(request_id);
}
+void ServiceWorkerVersion::OnGeofencingEventFinished(int request_id) {
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerVersion::OnGeofencingEventFinished",
+ "Request id",
+ request_id);
+ StatusCallback* callback = geofencing_callbacks_.Lookup(request_id);
+ if (!callback) {
+ NOTREACHED() << "Got unexpected message: " << request_id;
+ return;
+ }
+
+ scoped_refptr<ServiceWorkerVersion> protect(this);
+ callback->Run(SERVICE_WORKER_OK);
+ geofencing_callbacks_.Remove(request_id);
+}
+
void ServiceWorkerVersion::OnPostMessageToDocument(
int client_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids) {
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerVersion::OnPostMessageToDocument",
+ "Client id", client_id);
ServiceWorkerProviderHost* provider_host =
controllee_by_id_.Lookup(client_id);
if (!provider_host) {
@@ -634,4 +748,15 @@ void ServiceWorkerVersion::ScheduleStopWorker() {
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)));
}
+void ServiceWorkerVersion::DoomInternal() {
+ DCHECK(!HasControllee());
+ SetStatus(REDUNDANT);
+ StopWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ if (!context_)
+ return;
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ script_cache_map_.GetResources(&resources);
+ context_->storage()->PurgeResources(resources);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index 0c7bda50775..0dcf9a4c912 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_VERSION_H_
+#include <map>
#include <string>
#include <vector>
@@ -17,14 +18,20 @@
#include "base/observer_list.h"
#include "base/timer/timer.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
+#include "content/browser/service_worker/service_worker_cache_listener.h"
#include "content/browser/service_worker/service_worker_script_cache_map.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/WebKit/public/platform/WebGeofencingEventType.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
class GURL;
+namespace blink {
+struct WebCircularGeofencingRegion;
+}
+
namespace content {
class EmbeddedWorkerRegistry;
@@ -36,12 +43,8 @@ class ServiceWorkerVersionInfo;
// This class corresponds to a specific version of a ServiceWorker
// script for a given pattern. When a script is upgraded, there may be
// more than one ServiceWorkerVersion "running" at a time, but only
-// one of them is active. This class connects the actual script with a
+// one of them is activated. This class connects the actual script with a
// running worker.
-//
-// is_shutdown_ detects the live-ness of the object itself. If the object is
-// shut down, then it is in the process of being deleted from memory.
-// This happens when a version is replaced as well as at browser shutdown.
class CONTENT_EXPORT ServiceWorkerVersion
: NON_EXPORTED_BASE(public base::RefCounted<ServiceWorkerVersion>),
public EmbeddedWorkerInstance::Listener {
@@ -60,39 +63,44 @@ class CONTENT_EXPORT ServiceWorkerVersion
STOPPING = EmbeddedWorkerInstance::STOPPING,
};
- // Current version status; some of the status (e.g. INSTALLED and ACTIVE)
+ // Current version status; some of the status (e.g. INSTALLED and ACTIVATED)
// should be persisted unlike running status.
enum Status {
NEW, // The version is just created.
INSTALLING, // Install event is dispatched and being handled.
INSTALLED, // Install event is finished and is ready to be activated.
ACTIVATING, // Activate event is dispatched and being handled.
- ACTIVE, // Activation is finished and can run as active.
- DEACTIVATED, // The version is no longer running as active, due to
- // unregistration or replace. (TODO(kinuko): we may need
- // different states for different termination sequences)
+ ACTIVATED, // Activation is finished and can run as activated.
+ REDUNDANT, // The version is no longer running as activated, due to
+ // unregistration or replace.
};
class Listener {
public:
- virtual void OnWorkerStarted(ServiceWorkerVersion* version) = 0;
- virtual void OnWorkerStopped(ServiceWorkerVersion* version) = 0;
- virtual void OnVersionStateChanged(ServiceWorkerVersion* version) = 0;
+ virtual void OnWorkerStarted(ServiceWorkerVersion* version) {}
+ virtual void OnWorkerStopped(ServiceWorkerVersion* version) {}
+ virtual void OnVersionStateChanged(ServiceWorkerVersion* version) {}
virtual void OnErrorReported(ServiceWorkerVersion* version,
const base::string16& error_message,
int line_number,
int column_number,
- const GURL& source_url) = 0;
+ const GURL& source_url) {}
virtual void OnReportConsoleMessage(ServiceWorkerVersion* version,
int source_identifier,
int message_level,
const base::string16& message,
int line_number,
- const GURL& source_url) = 0;
+ const GURL& source_url) {}
+ // Fires when a version transitions from having a controllee to not.
+ virtual void OnNoControllees(ServiceWorkerVersion* version) {}
+
+ protected:
+ virtual ~Listener() {}
};
ServiceWorkerVersion(
ServiceWorkerRegistration* registration,
+ const GURL& script_url,
int64 version_id,
base::WeakPtr<ServiceWorkerContextCore> context);
@@ -120,17 +128,26 @@ class CONTENT_EXPORT ServiceWorkerVersion
void StartWorker(const StatusCallback& callback);
// Starts an embedded worker for this version.
- // |potential_process_ids| is a list of processes in which to start the
- // worker.
+ // |pause_after_download| notifies worker to pause after download finished
+ // which could be resumed by EmbeddedWorkerInstance::ResumeAfterDownload.
// This returns OK (success) if the worker is already running.
- void StartWorkerWithCandidateProcesses(
- const std::vector<int>& potential_process_ids,
- const StatusCallback& callback);
+ void StartWorker(bool pause_after_download,
+ const StatusCallback& callback);
- // Starts an embedded worker for this version.
+ // Stops an embedded worker for this version.
// This returns OK (success) if the worker is already stopped.
void StopWorker(const StatusCallback& callback);
+ // Schedules an update to be run 'soon'.
+ void ScheduleUpdate();
+
+ // If an update is scheduled but not yet started, this resets the timer
+ // delaying the start time by a 'small' amount.
+ void DeferScheduledUpdate();
+
+ // Starts an update now.
+ void StartUpdate();
+
// Sends an IPC message to the worker.
// If the worker is not running this first tries to start it by
// calling StartWorker internally.
@@ -139,10 +156,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
void SendMessage(const IPC::Message& message, const StatusCallback& callback);
// Sends install event to the associated embedded worker and asynchronously
- // calls |callback| when it errors out or it gets response from the worker
+ // calls |callback| when it errors out or it gets a response from the worker
// to notify install completion.
// |active_version_id| must be a valid positive ID
- // if there's an active (previous) version running.
+ // if there's an activated (previous) version running.
//
// This must be called when the status() is NEW. Calling this changes
// the version's status to INSTALLING.
@@ -152,52 +169,55 @@ class CONTENT_EXPORT ServiceWorkerVersion
const StatusCallback& callback);
// Sends activate event to the associated embedded worker and asynchronously
- // calls |callback| when it errors out or it gets response from the worker
+ // calls |callback| when it errors out or it gets a response from the worker
// to notify activation completion.
//
// This must be called when the status() is INSTALLED. Calling this changes
// the version's status to ACTIVATING.
- // Upon completion, the version's status will be changed to ACTIVE
+ // Upon completion, the version's status will be changed to ACTIVATED
// on success, or back to INSTALLED on failure.
void DispatchActivateEvent(const StatusCallback& callback);
// Sends fetch event to the associated embedded worker and calls
// |callback| with the response from the worker.
//
- // This must be called when the status() is ACTIVE. Calling this in other
+ // This must be called when the status() is ACTIVATED. Calling this in other
// statuses will result in an error SERVICE_WORKER_ERROR_FAILED.
void DispatchFetchEvent(const ServiceWorkerFetchRequest& request,
- const FetchCallback& callback);
+ const base::Closure& prepare_callback,
+ const FetchCallback& fetch_callback);
// Sends sync event to the associated embedded worker and asynchronously calls
- // |callback| when it errors out or it gets response from the worker to notify
- // completion.
+ // |callback| when it errors out or it gets a response from the worker to
+ // notify completion.
//
- // This must be called when the status() is ACTIVE.
+ // This must be called when the status() is ACTIVATED.
void DispatchSyncEvent(const StatusCallback& callback);
// Sends push event to the associated embedded worker and asynchronously calls
- // |callback| when it errors out or it gets response from the worker to notify
- // completion.
+ // |callback| when it errors out or it gets a response from the worker to
+ // notify completion.
//
- // This must be called when the status() is ACTIVE.
+ // This must be called when the status() is ACTIVATED.
void DispatchPushEvent(const StatusCallback& callback,
const std::string& data);
- // These are expected to be called when a renderer process host for the
- // same-origin as for this ServiceWorkerVersion is created. The added
- // processes are used to run an in-renderer embedded worker.
- void AddProcessToWorker(int process_id);
- void RemoveProcessFromWorker(int process_id);
-
- // Returns true if this has at least one process to run.
- bool HasProcessToRun() const;
+ // Sends geofencing event to the associated embedded worker and asynchronously
+ // calls |callback| when it errors out or it gets a response from the worker
+ // to notify completion.
+ //
+ // This must be called when the status() is ACTIVATED.
+ void DispatchGeofencingEvent(
+ const StatusCallback& callback,
+ blink::WebGeofencingEventType event_type,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region);
// Adds and removes |provider_host| as a controllee of this ServiceWorker.
+ // A potential controllee is a host having the version as its .installing
+ // or .waiting version.
void AddControllee(ServiceWorkerProviderHost* provider_host);
void RemoveControllee(ServiceWorkerProviderHost* provider_host);
- void AddWaitingControllee(ServiceWorkerProviderHost* provider_host);
- void RemoveWaitingControllee(ServiceWorkerProviderHost* provider_host);
// Returns if it has controllee.
bool HasControllee() const { return !controllee_map_.empty(); }
@@ -209,29 +229,39 @@ class CONTENT_EXPORT ServiceWorkerVersion
ServiceWorkerScriptCacheMap* script_cache_map() { return &script_cache_map_; }
EmbeddedWorkerInstance* embedded_worker() { return embedded_worker_.get(); }
+ // Dooms this version to have REDUNDANT status and its resources deleted. If
+ // the version is controlling a page, these changes will happen when the
+ // version no longer controls any pages.
+ void Doom();
+ bool is_doomed() const { return is_doomed_; }
+
private:
+ friend class base::RefCounted<ServiceWorkerVersion>;
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
+ ActivateWaitingVersion);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, ScheduleStopWorker);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, ListenerAvailability);
typedef ServiceWorkerVersion self;
typedef std::map<ServiceWorkerProviderHost*, int> ControlleeMap;
typedef IDMap<ServiceWorkerProviderHost> ControlleeByIDMap;
- friend class base::RefCounted<ServiceWorkerVersion>;
- virtual ~ServiceWorkerVersion();
+ ~ServiceWorkerVersion() override;
// EmbeddedWorkerInstance::Listener overrides:
- virtual void OnStarted() OVERRIDE;
- virtual void OnStopped() OVERRIDE;
- virtual void OnReportException(const base::string16& error_message,
- int line_number,
- int column_number,
- const GURL& source_url) OVERRIDE;
- virtual void OnReportConsoleMessage(int source_identifier,
- int message_level,
- const base::string16& message,
- int line_number,
- const GURL& source_url) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void RunStartWorkerCallbacksOnError(ServiceWorkerStatusCode status);
+ void OnStarted() override;
+ void OnStopped() override;
+ void OnReportException(const base::string16& error_message,
+ int line_number,
+ int column_number,
+ const GURL& source_url) override;
+ void OnReportConsoleMessage(int source_identifier,
+ int message_level,
+ const base::string16& message,
+ int line_number,
+ const GURL& source_url) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnStartMessageSent(ServiceWorkerStatusCode status);
void DispatchInstallEventAfterStartWorker(int active_version_id,
const StatusCallback& callback);
@@ -248,11 +278,13 @@ class CONTENT_EXPORT ServiceWorkerVersion
const ServiceWorkerResponse& response);
void OnSyncEventFinished(int request_id);
void OnPushEventFinished(int request_id);
+ void OnGeofencingEventFinished(int request_id);
void OnPostMessageToDocument(int client_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids);
void ScheduleStopWorker();
+ void DoomInternal();
const int64 version_id_;
int64 registration_id_;
@@ -260,6 +292,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
GURL scope_;
Status status_;
scoped_ptr<EmbeddedWorkerInstance> embedded_worker_;
+ scoped_ptr<ServiceWorkerCacheListener> cache_listener_;
std::vector<StatusCallback> start_callbacks_;
std::vector<StatusCallback> stop_callbacks_;
std::vector<base::Closure> status_change_callbacks_;
@@ -270,6 +303,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
IDMap<FetchCallback, IDMapOwnPointer> fetch_callbacks_;
IDMap<StatusCallback, IDMapOwnPointer> sync_callbacks_;
IDMap<StatusCallback, IDMapOwnPointer> push_callbacks_;
+ IDMap<StatusCallback, IDMapOwnPointer> geofencing_callbacks_;
ControlleeMap controllee_map_;
ControlleeByIDMap controllee_by_id_;
@@ -277,6 +311,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
ObserverList<Listener> listeners_;
ServiceWorkerScriptCacheMap script_cache_map_;
base::OneShotTimer<ServiceWorkerVersion> stop_worker_timer_;
+ base::OneShotTimer<ServiceWorkerVersion> update_timer_;
+ bool is_doomed_;
base::WeakPtrFactory<ServiceWorkerVersion> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_version_unittest.cc b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
index 6622e5aba83..31225e96357 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -36,11 +36,11 @@ class MessageReceiver : public EmbeddedWorkerTestHelper {
MessageReceiver()
: EmbeddedWorkerTestHelper(kRenderProcessId),
current_embedded_worker_id_(0) {}
- virtual ~MessageReceiver() {}
+ ~MessageReceiver() override {}
- virtual bool OnMessageToWorker(int thread_id,
- int embedded_worker_id,
- const IPC::Message& message) OVERRIDE {
+ bool OnMessageToWorker(int thread_id,
+ int embedded_worker_id,
+ const IPC::Message& message) override {
if (EmbeddedWorkerTestHelper::OnMessageToWorker(
thread_id, embedded_worker_id, message)) {
return true;
@@ -85,13 +85,11 @@ class MessageReceiverFromWorker : public EmbeddedWorkerInstance::Listener {
: instance_(instance) {
instance_->AddListener(this);
}
- virtual ~MessageReceiverFromWorker() {
- instance_->RemoveListener(this);
- }
+ ~MessageReceiverFromWorker() override { instance_->RemoveListener(this); }
- virtual void OnStarted() OVERRIDE { NOTREACHED(); }
- virtual void OnStopped() OVERRIDE { NOTREACHED(); }
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ void OnStarted() override { NOTREACHED(); }
+ void OnStopped() override { NOTREACHED(); }
+ bool OnMessageReceived(const IPC::Message& message) override {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MessageReceiverFromWorker, message)
IPC_MESSAGE_HANDLER(TestMsg_MessageFromWorker, OnMessageFromWorker)
@@ -116,24 +114,31 @@ class ServiceWorkerVersionTest : public testing::Test {
ServiceWorkerVersionTest()
: thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
- virtual void SetUp() OVERRIDE {
- helper_.reset(new MessageReceiver());
+ void SetUp() override {
+ helper_ = GetMessageReceiver();
+ pattern_ = GURL("http://www.example.com/");
registration_ = new ServiceWorkerRegistration(
- GURL("http://www.example.com/*"),
- GURL("http://www.example.com/service_worker.js"),
+ pattern_,
1L,
helper_->context()->AsWeakPtr());
version_ = new ServiceWorkerVersion(
- registration_, 1L, helper_->context()->AsWeakPtr());
+ registration_.get(),
+ GURL("http://www.example.com/service_worker.js"),
+ 1L,
+ helper_->context()->AsWeakPtr());
+
+ // Simulate adding one process to the pattern.
+ helper_->SimulateAddProcessToPattern(pattern_, kRenderProcessId);
+ ASSERT_TRUE(helper_->context()->process_manager()
+ ->PatternHasProcessToRun(pattern_));
+ }
- // Simulate adding one process to the worker.
- int embedded_worker_id = version_->embedded_worker()->embedded_worker_id();
- helper_->SimulateAddProcessToWorker(embedded_worker_id, kRenderProcessId);
- ASSERT_TRUE(version_->HasProcessToRun());
+ virtual scoped_ptr<MessageReceiver> GetMessageReceiver() {
+ return make_scoped_ptr(new MessageReceiver());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
version_ = 0;
registration_ = 0;
helper_.reset();
@@ -143,9 +148,43 @@ class ServiceWorkerVersionTest : public testing::Test {
scoped_ptr<MessageReceiver> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
+ GURL pattern_;
+
+ private:
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersionTest);
};
+class MessageReceiverDisallowStart : public MessageReceiver {
+ public:
+ MessageReceiverDisallowStart()
+ : MessageReceiver() {}
+ ~MessageReceiverDisallowStart() override {}
+
+ void OnStartWorker(int embedded_worker_id,
+ int64 service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download) override {
+ // Do nothing.
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
+};
+
+class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
+ protected:
+ ServiceWorkerFailToStartTest()
+ : ServiceWorkerVersionTest() {}
+
+ virtual scoped_ptr<MessageReceiver> GetMessageReceiver() override {
+ return make_scoped_ptr(new MessageReceiverDisallowStart());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFailToStartTest);
+};
+
TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
// Call StartWorker() multiple times.
ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
@@ -261,7 +300,7 @@ TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
}
TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
- EXPECT_EQ(ServiceWorkerVersion::NEW, version_->status());
+ version_->SetStatus(ServiceWorkerVersion::INSTALLING);
// Dispatch an install event.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
@@ -274,16 +313,14 @@ TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
base::RunLoop().RunUntilIdle();
- // After successful completion, version's status must be changed to
- // INSTALLED, and status change callback must have been fired.
+ // Version's status must not have changed during installation.
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(status_change_called);
- EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
+ EXPECT_FALSE(status_change_called);
+ EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
}
TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
- version_->SetStatus(ServiceWorkerVersion::INSTALLED);
- EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version_->status());
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
// Dispatch an activate event.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
@@ -296,11 +333,10 @@ TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
base::RunLoop().RunUntilIdle();
- // After successful completion, version's status must be changed to
- // ACTIVE, and status change callback must have been fired.
+ // Version's status must not have changed during activation.
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(status_change_called);
- EXPECT_EQ(ServiceWorkerVersion::ACTIVE, version_->status());
+ EXPECT_FALSE(status_change_called);
+ EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
@@ -311,45 +347,109 @@ TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
version_->RegisterStatusChangeCallback(
base::Bind(&ObserveStatusChanges, version_, &statuses));
- // Dispatch some events.
+ version_->SetStatus(ServiceWorkerVersion::INSTALLING);
+ version_->SetStatus(ServiceWorkerVersion::INSTALLED);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ version_->SetStatus(ServiceWorkerVersion::REDUNDANT);
+
+ // Verify that we could successfully observe repeated status changes.
+ ASSERT_EQ(5U, statuses.size());
+ ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
+ ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
+ ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
+ ASSERT_EQ(ServiceWorkerVersion::ACTIVATED, statuses[3]);
+ ASSERT_EQ(ServiceWorkerVersion::REDUNDANT, statuses[4]);
+}
+
+TEST_F(ServiceWorkerVersionTest, ScheduleStopWorker) {
+ // Verify the timer is not running when version initializes its status.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
+
+ // Verify the timer is running when version status changes frome ACTIVATING
+ // to ACTIVATED.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->DispatchInstallEvent(-1, CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
+ // The timer should be running if the worker is restarted without controllee.
status = SERVICE_WORKER_ERROR_FAILED;
- version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
+ version_->StopWorker(CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ status = SERVICE_WORKER_ERROR_FAILED;
+ version_->StartWorker(CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
+
+ // The timer should not be running if a controllee is added.
+ scoped_ptr<ServiceWorkerProviderHost> host(
+ new ServiceWorkerProviderHost(33 /* dummy render process id */,
+ 1 /* dummy provider_id */,
+ helper_->context()->AsWeakPtr(),
+ NULL));
+ version_->AddControllee(host.get());
+ EXPECT_FALSE(version_->stop_worker_timer_.IsRunning());
+
+ // The timer should be running if the controllee is removed.
+ version_->RemoveControllee(host.get());
+ EXPECT_TRUE(version_->stop_worker_timer_.IsRunning());
+}
- // Verify that we could successfully observe repeated status changes.
- ASSERT_EQ(4U, statuses.size());
- ASSERT_EQ(ServiceWorkerVersion::INSTALLING, statuses[0]);
- ASSERT_EQ(ServiceWorkerVersion::INSTALLED, statuses[1]);
- ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, statuses[2]);
- ASSERT_EQ(ServiceWorkerVersion::ACTIVE, statuses[3]);
+TEST_F(ServiceWorkerVersionTest, ListenerAvailability) {
+ // Initially the worker is not running. There should be no cache_listener_.
+ EXPECT_FALSE(version_->cache_listener_.get());
+
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+ version_->StartWorker(
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // A new cache listener should be available once the worker starts.
+ EXPECT_TRUE(version_->cache_listener_.get());
+
+ version_->StopWorker(
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // Should be destroyed when the worker stops.
+ EXPECT_FALSE(version_->cache_listener_.get());
+
+ version_->StartWorker(
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // Recreated when the worker starts again.
+ EXPECT_TRUE(version_->cache_listener_.get());
}
-TEST_F(ServiceWorkerVersionTest, AddAndRemoveProcesses) {
- // Preparation (to reset the process count to 0).
- ASSERT_TRUE(version_->HasProcessToRun());
- version_->RemoveProcessFromWorker(kRenderProcessId);
- ASSERT_FALSE(version_->HasProcessToRun());
-
- // Add another process to the worker twice, and then remove process once.
- const int another_process_id = kRenderProcessId + 1;
- version_->AddProcessToWorker(another_process_id);
- version_->AddProcessToWorker(another_process_id);
- version_->RemoveProcessFromWorker(another_process_id);
-
- // We're ref-counting the process internally, so adding the same process
- // multiple times should be handled correctly.
- ASSERT_TRUE(version_->HasProcessToRun());
-
- // Removing the process again (so that # of AddProcess == # of RemoveProcess
- // for the process) should remove all process references.
- version_->RemoveProcessFromWorker(another_process_id);
- ASSERT_FALSE(version_->HasProcessToRun());
+TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
+ version_->StartWorker(
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // Callback has not completed yet.
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
+ EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
+
+ // Simulate renderer crash: do what
+ // ServiceWorkerDispatcherHost::OnFilterRemoved does.
+ int process_id = helper_->mock_render_process_id();
+ helper_->context()->RemoveAllProviderHostsForProcess(process_id);
+ helper_->context()->embedded_worker_registry()->RemoveChildProcessSender(
+ process_id);
+ base::RunLoop().RunUntilIdle();
+
+ // Callback completed.
+ EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
index bd16a132004..0baf702a259 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -4,11 +4,13 @@
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
+#include "base/debug/trace_event.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_histograms.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
@@ -21,10 +23,13 @@ namespace content {
ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
+ ResourceType resource_type,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerVersion* version,
+ int extra_load_flags,
int64 response_id)
: net::URLRequestJob(request, network_delegate),
+ resource_type_(resource_type),
context_(context),
url_(request->url()),
response_id_(response_id),
@@ -33,7 +38,7 @@ ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
did_notify_started_(false),
did_notify_finished_(false),
weak_factory_(this) {
- InitNetRequest();
+ InitNetRequest(extra_load_flags);
}
ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() {
@@ -41,6 +46,10 @@ ServiceWorkerWriteToCacheJob::~ServiceWorkerWriteToCacheJob() {
}
void ServiceWorkerWriteToCacheJob::Start() {
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::ExecutingJob",
+ this,
+ "URL", request_->url().spec());
if (!context_) {
NotifyStartError(net::URLRequestStatus(
net::URLRequestStatus::FAILED, net::ERR_FAILED));
@@ -60,7 +69,9 @@ void ServiceWorkerWriteToCacheJob::Kill() {
net_request_.reset();
if (did_notify_started_ && !did_notify_finished_) {
version_->script_cache_map()->NotifyFinishedCaching(
- url_, false);
+ url_,
+ -1,
+ net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_ABORTED));
did_notify_finished_ = true;
}
writer_.reset();
@@ -120,7 +131,7 @@ bool ServiceWorkerWriteToCacheJob::ReadRawData(
// No more data to process, the job is complete.
io_buffer_ = NULL;
version_->script_cache_map()->NotifyFinishedCaching(
- url_, status.is_success());
+ url_, writer_->amount_written(), status);
did_notify_finished_ = true;
return status.is_success();
}
@@ -129,7 +140,8 @@ const net::HttpResponseInfo* ServiceWorkerWriteToCacheJob::http_info() const {
return http_info_.get();
}
-void ServiceWorkerWriteToCacheJob::InitNetRequest() {
+void ServiceWorkerWriteToCacheJob::InitNetRequest(
+ int extra_load_flags) {
DCHECK(request());
net_request_ = request()->context()->CreateRequest(
request()->url(),
@@ -139,10 +151,21 @@ void ServiceWorkerWriteToCacheJob::InitNetRequest() {
net_request_->set_first_party_for_cookies(
request()->first_party_for_cookies());
net_request_->SetReferrer(request()->referrer());
- net_request_->SetExtraRequestHeaders(request()->extra_request_headers());
+ if (extra_load_flags)
+ net_request_->SetLoadFlags(net_request_->load_flags() | extra_load_flags);
+
+ if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER) {
+ // This will get copied into net_request_ when URLRequest::StartJob calls
+ // ServiceWorkerWriteToCacheJob::SetExtraRequestHeaders.
+ request()->SetExtraRequestHeaderByName("Service-Worker", "script", true);
+ }
}
void ServiceWorkerWriteToCacheJob::StartNetRequest() {
+ TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::ExecutingJob",
+ this,
+ "NetRequest");
net_request_->Start(); // We'll continue in OnResponseStarted.
}
@@ -179,11 +202,15 @@ void ServiceWorkerWriteToCacheJob::WriteHeadersToCache() {
net::URLRequestStatus::FAILED, net::ERR_FAILED));
return;
}
+ TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::ExecutingJob",
+ this,
+ "WriteHeadersToCache");
writer_ = context_->storage()->CreateResponseWriter(response_id_);
info_buffer_ = new HttpResponseInfoIOBuffer(
new net::HttpResponseInfo(net_request_->response_info()));
writer_->WriteInfo(
- info_buffer_,
+ info_buffer_.get(),
base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete,
weak_factory_.GetWeakPtr()));
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
@@ -192,22 +219,32 @@ void ServiceWorkerWriteToCacheJob::WriteHeadersToCache() {
void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(int result) {
SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
if (result < 0) {
- ServiceWorkerHistograms::CountWriteResponseResult(
- ServiceWorkerHistograms::WRITE_HEADERS_ERROR);
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_HEADERS_ERROR);
AsyncNotifyDoneHelper(net::URLRequestStatus(
net::URLRequestStatus::FAILED, result));
return;
}
http_info_.reset(info_buffer_->http_info.release());
info_buffer_ = NULL;
+ TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::ExecutingJob",
+ this,
+ "WriteHeadersToCacheCompleted");
NotifyHeadersComplete();
}
void ServiceWorkerWriteToCacheJob::WriteDataToCache(int amount_to_write) {
DCHECK_NE(0, amount_to_write);
+ TRACE_EVENT_ASYNC_STEP_INTO1("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::ExecutingJob",
+ this,
+ "WriteDataToCache",
+ "Amount to write", amount_to_write);
SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
writer_->WriteData(
- io_buffer_, amount_to_write,
+ io_buffer_.get(),
+ amount_to_write,
base::Bind(&ServiceWorkerWriteToCacheJob::OnWriteDataComplete,
weak_factory_.GetWeakPtr()));
}
@@ -221,32 +258,39 @@ void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(int result) {
return;
}
if (result < 0) {
- ServiceWorkerHistograms::CountWriteResponseResult(
- ServiceWorkerHistograms::WRITE_DATA_ERROR);
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_DATA_ERROR);
AsyncNotifyDoneHelper(net::URLRequestStatus(
net::URLRequestStatus::FAILED, result));
return;
}
- ServiceWorkerHistograms::CountWriteResponseResult(
- ServiceWorkerHistograms::WRITE_OK);
+ ServiceWorkerMetrics::CountWriteResponseResult(
+ ServiceWorkerMetrics::WRITE_OK);
SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
NotifyReadComplete(result);
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::ExecutingJob",
+ this);
}
void ServiceWorkerWriteToCacheJob::OnReceivedRedirect(
net::URLRequest* request,
- const GURL& new_url,
+ const net::RedirectInfo& redirect_info,
bool* defer_redirect) {
DCHECK_EQ(net_request_, request);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::OnReceivedRedirect");
// Script resources can't redirect.
AsyncNotifyDoneHelper(net::URLRequestStatus(
- net::URLRequestStatus::FAILED, net::ERR_FAILED));
+ net::URLRequestStatus::FAILED, net::ERR_UNSAFE_REDIRECT));
}
void ServiceWorkerWriteToCacheJob::OnAuthRequired(
net::URLRequest* request,
net::AuthChallengeInfo* auth_info) {
DCHECK_EQ(net_request_, request);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::OnAuthRequired");
// TODO(michaeln): Pass this thru to our jobs client.
AsyncNotifyDoneHelper(net::URLRequestStatus(
net::URLRequestStatus::FAILED, net::ERR_FAILED));
@@ -256,27 +300,33 @@ void ServiceWorkerWriteToCacheJob::OnCertificateRequested(
net::URLRequest* request,
net::SSLCertRequestInfo* cert_request_info) {
DCHECK_EQ(net_request_, request);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::OnCertificateRequested");
// TODO(michaeln): Pass this thru to our jobs client.
// see NotifyCertificateRequested.
AsyncNotifyDoneHelper(net::URLRequestStatus(
net::URLRequestStatus::FAILED, net::ERR_FAILED));
}
-void ServiceWorkerWriteToCacheJob:: OnSSLCertificateError(
+void ServiceWorkerWriteToCacheJob::OnSSLCertificateError(
net::URLRequest* request,
const net::SSLInfo& ssl_info,
bool fatal) {
DCHECK_EQ(net_request_, request);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::OnSSLCertificateError");
// TODO(michaeln): Pass this thru to our jobs client,
// see NotifySSLCertificateError.
AsyncNotifyDoneHelper(net::URLRequestStatus(
- net::URLRequestStatus::FAILED, net::ERR_FAILED));
+ net::URLRequestStatus::FAILED, net::ERR_INSECURE_RESPONSE));
}
void ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart(
net::URLRequest* request,
bool* defer) {
DCHECK_EQ(net_request_, request);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerWriteToCacheJob::OnBeforeNetworkStart");
NotifyBeforeNetworkStart(defer);
}
@@ -294,6 +344,29 @@ void ServiceWorkerWriteToCacheJob::OnResponseStarted(
// response to our consumer, just don't cache it?
return;
}
+ // OnSSLCertificateError is not called when the HTTPS connection is reused.
+ // So we check cert_status here.
+ if (net::IsCertStatusError(request->ssl_info().cert_status)) {
+ const net::HttpNetworkSession::Params* session_params =
+ request->context()->GetNetworkSessionParams();
+ if (!session_params || !session_params->ignore_certificate_errors) {
+ AsyncNotifyDoneHelper(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_INSECURE_RESPONSE));
+ return;
+ }
+ }
+ // To prevent most user-uploaded content from being used as a serviceworker.
+ if (version_->script_url() == url_) {
+ std::string mime_type;
+ request->GetMimeType(&mime_type);
+ if (mime_type != "application/x-javascript" &&
+ mime_type != "text/javascript" &&
+ mime_type != "application/javascript") {
+ AsyncNotifyDoneHelper(net::URLRequestStatus(
+ net::URLRequestStatus::FAILED, net::ERR_INSECURE_RESPONSE));
+ return;
+ }
+ }
WriteHeadersToCache();
}
@@ -301,7 +374,8 @@ void ServiceWorkerWriteToCacheJob::OnReadCompleted(
net::URLRequest* request,
int bytes_read) {
DCHECK_EQ(net_request_, request);
- if (!request->status().is_success()) {
+ if (bytes_read < 0) {
+ DCHECK(!request->status().is_success());
AsyncNotifyDoneHelper(request->status());
return;
}
@@ -309,16 +383,25 @@ void ServiceWorkerWriteToCacheJob::OnReadCompleted(
WriteDataToCache(bytes_read);
return;
}
- // We're done with all.
- AsyncNotifyDoneHelper(request->status());
- return;
+ // No more data to process, the job is complete.
+ DCHECK(request->status().is_success());
+ io_buffer_ = NULL;
+ version_->script_cache_map()->NotifyFinishedCaching(
+ url_, writer_->amount_written(), net::URLRequestStatus());
+ did_notify_finished_ = true;
+ SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
+ NotifyReadComplete(0);
}
void ServiceWorkerWriteToCacheJob::AsyncNotifyDoneHelper(
const net::URLRequestStatus& status) {
DCHECK(!status.is_io_pending());
- version_->script_cache_map()->NotifyFinishedCaching(
- url_, status.is_success());
+ DCHECK(!did_notify_finished_);
+ int size = -1;
+ if (writer_.get()) {
+ size = writer_->amount_written();
+ }
+ version_->script_cache_map()->NotifyFinishedCaching(url_, size, status);
did_notify_finished_ = true;
SetStatus(status);
NotifyDone(status);
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
index 040df41b4c6..ec3bfa7464b 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -5,12 +5,15 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_WRITE_TO_CACHE_JOB_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_WRITE_TO_CACHE_JOB_H_
+#include <string>
+
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/resource_type.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
@@ -34,32 +37,36 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
ServiceWorkerWriteToCacheJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
+ ResourceType resource_type,
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerVersion* version,
+ int extra_load_flags,
int64 response_id);
private:
- virtual ~ServiceWorkerWriteToCacheJob();
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ UpdateBefore24Hours);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ UpdateAfter24Hours);
+
+ ~ServiceWorkerWriteToCacheJob() override;
// net::URLRequestJob overrides
- virtual void Start() OVERRIDE;
- virtual void Kill() OVERRIDE;
- virtual net::LoadState GetLoadState() const OVERRIDE;
- virtual bool GetCharset(std::string* charset) OVERRIDE;
- virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
- virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE;
- virtual int GetResponseCode() const OVERRIDE;
- virtual void SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) OVERRIDE;
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int *bytes_read) OVERRIDE;
+ void Start() override;
+ void Kill() override;
+ net::LoadState GetLoadState() const override;
+ bool GetCharset(std::string* charset) override;
+ bool GetMimeType(std::string* mime_type) const override;
+ void GetResponseInfo(net::HttpResponseInfo* info) override;
+ int GetResponseCode() const override;
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
const net::HttpResponseInfo* http_info() const;
// Methods to drive the net request forward and
// write data to the disk cache.
- void InitNetRequest();
+ void InitNetRequest(int extra_load_flags);
void StartNetRequest();
net::URLRequestStatus ReadNetData(
net::IOBuffer* buf,
@@ -71,30 +78,24 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
void OnWriteDataComplete(int result);
// net::URLRequest::Delegate overrides that observe the net request.
- virtual void OnReceivedRedirect(
- net::URLRequest* request,
- const GURL& new_url,
- bool* defer_redirect) OVERRIDE;
- virtual void OnAuthRequired(
- net::URLRequest* request,
- net::AuthChallengeInfo* auth_info) OVERRIDE;
- virtual void OnCertificateRequested(
- net::URLRequest* request,
- net::SSLCertRequestInfo* cert_request_info) OVERRIDE;
- virtual void OnSSLCertificateError(
- net::URLRequest* request,
- const net::SSLInfo& ssl_info,
- bool fatal) OVERRIDE;
- virtual void OnBeforeNetworkStart(
- net::URLRequest* request,
- bool* defer) OVERRIDE;
- virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
- virtual void OnReadCompleted(
+ void OnReceivedRedirect(net::URLRequest* request,
+ const net::RedirectInfo& redirect_info,
+ bool* defer_redirect) override;
+ void OnAuthRequired(net::URLRequest* request,
+ net::AuthChallengeInfo* auth_info) override;
+ void OnCertificateRequested(
net::URLRequest* request,
- int bytes_read) OVERRIDE;
+ net::SSLCertRequestInfo* cert_request_info) override;
+ void OnSSLCertificateError(net::URLRequest* request,
+ const net::SSLInfo& ssl_info,
+ bool fatal) override;
+ void OnBeforeNetworkStart(net::URLRequest* request, bool* defer) override;
+ void OnResponseStarted(net::URLRequest* request) override;
+ void OnReadCompleted(net::URLRequest* request, int bytes_read) override;
void AsyncNotifyDoneHelper(const net::URLRequestStatus& status);
+ ResourceType resource_type_; // Differentiate main script and imports
scoped_refptr<net::IOBuffer> io_buffer_;
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
base::WeakPtr<ServiceWorkerContextCore> context_;
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
new file mode 100644
index 00000000000..7c6ad3282a7
--- /dev/null
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -0,0 +1,300 @@
+// Copyright 2014 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/run_loop.h"
+#include "content/browser/fileapi/mock_url_request_delegate.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_request_handler.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/browser/service_worker/service_worker_utils.h"
+#include "content/common/resource_request_body.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+int kMockRenderProcessId = 1224;
+int kMockProviderId = 1;
+const char kHeaders[] =
+ "HTTP/1.1 200 OK\0"
+ "Content-Type: text/javascript\0"
+ "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
+ "\0";
+const char kScriptCode[] = "// no script code\n";
+
+void EmptyCallback() {
+}
+
+net::URLRequestJob* CreateNormalURLRequestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) {
+ return new net::URLRequestTestJob(request,
+ network_delegate,
+ std::string(kHeaders, arraysize(kHeaders)),
+ kScriptCode,
+ true);
+}
+
+net::URLRequestJob* CreateInvalidMimeTypeJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) {
+ const char kPlainTextHeaders[] =
+ "HTTP/1.1 200 OK\0"
+ "Content-Type: text/plain\0"
+ "Expires: Thu, 1 Jan 2100 20:00:00 GMT\0"
+ "\0";
+ return new net::URLRequestTestJob(
+ request,
+ network_delegate,
+ std::string(kPlainTextHeaders, arraysize(kPlainTextHeaders)),
+ kScriptCode,
+ true);
+}
+
+class SSLCertificateErrorJob : public net::URLRequestTestJob {
+ public:
+ SSLCertificateErrorJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& response_headers,
+ const std::string& response_data,
+ bool auto_advance)
+ : net::URLRequestTestJob(request,
+ network_delegate,
+ response_headers,
+ response_data,
+ auto_advance),
+ weak_factory_(this) {}
+ void Start() override {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&SSLCertificateErrorJob::NotifyError,
+ weak_factory_.GetWeakPtr()));
+ }
+ void NotifyError() {
+ net::SSLInfo info;
+ info.cert_status = net::CERT_STATUS_DATE_INVALID;
+ NotifySSLCertificateError(info, true);
+ }
+
+ protected:
+ ~SSLCertificateErrorJob() override {}
+ base::WeakPtrFactory<SSLCertificateErrorJob> weak_factory_;
+};
+
+net::URLRequestJob* CreateSSLCertificateErrorJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) {
+ return new SSLCertificateErrorJob(request,
+ network_delegate,
+ std::string(kHeaders, arraysize(kHeaders)),
+ kScriptCode,
+ true);
+}
+
+class CertStatusErrorJob : public net::URLRequestTestJob {
+ public:
+ CertStatusErrorJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& response_headers,
+ const std::string& response_data,
+ bool auto_advance)
+ : net::URLRequestTestJob(request,
+ network_delegate,
+ response_headers,
+ response_data,
+ auto_advance) {}
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ URLRequestTestJob::GetResponseInfo(info);
+ info->ssl_info.cert_status = net::CERT_STATUS_DATE_INVALID;
+ }
+
+ protected:
+ ~CertStatusErrorJob() override {}
+};
+
+net::URLRequestJob* CreateCertStatusErrorJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) {
+ return new CertStatusErrorJob(request,
+ network_delegate,
+ std::string(kHeaders, arraysize(kHeaders)),
+ kScriptCode,
+ true);
+}
+
+class MockHttpProtocolHandler
+ : public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ typedef base::Callback<
+ net::URLRequestJob*(net::URLRequest*, net::NetworkDelegate*)> JobCallback;
+
+ MockHttpProtocolHandler(ResourceContext* resource_context)
+ : resource_context_(resource_context) {}
+ ~MockHttpProtocolHandler() override {}
+
+ net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ ServiceWorkerRequestHandler* handler =
+ ServiceWorkerRequestHandler::GetHandler(request);
+ if (handler) {
+ return handler->MaybeCreateJob(
+ request, network_delegate, resource_context_);
+ }
+ return create_job_callback_.Run(request, network_delegate);
+ }
+ void SetCreateJobCallback(const JobCallback& callback) {
+ create_job_callback_ = callback;
+ }
+
+ private:
+ ResourceContext* resource_context_;
+ JobCallback create_job_callback_;
+};
+}
+
+class ServiceWorkerWriteToCacheJobTest : public testing::Test {
+ public:
+ ServiceWorkerWriteToCacheJobTest()
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ mock_protocol_handler_(NULL) {}
+ ~ServiceWorkerWriteToCacheJobTest() override {}
+
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(kMockRenderProcessId));
+
+ // A new unstored registration/version.
+ scope_ = GURL("https://host/scope/");
+ script_url_ = GURL("https://host/script.js");
+ registration_ =
+ new ServiceWorkerRegistration(scope_, 1L, context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(
+ registration_.get(), script_url_, 1L, context()->AsWeakPtr());
+
+ // An empty host.
+ scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
+ kMockRenderProcessId, kMockProviderId, context()->AsWeakPtr(), NULL));
+ provider_host_ = host->AsWeakPtr();
+ context()->AddProviderHost(host.Pass());
+ provider_host_->running_hosted_version_ = version_;
+
+ context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
+ base::RunLoop().RunUntilIdle();
+
+ url_request_context_.reset(new net::URLRequestContext);
+ mock_protocol_handler_ = new MockHttpProtocolHandler(&resource_context_);
+ url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
+ url_request_job_factory_->SetProtocolHandler("https",
+ mock_protocol_handler_);
+ url_request_context_->set_job_factory(url_request_job_factory_.get());
+
+ request_ = url_request_context_->CreateRequest(
+ script_url_, net::DEFAULT_PRIORITY, &url_request_delegate_, NULL);
+ ServiceWorkerRequestHandler::InitializeHandler(
+ request_.get(),
+ context_wrapper(),
+ &blob_storage_context_,
+ kMockRenderProcessId,
+ kMockProviderId,
+ false,
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_CREDENTIALS_MODE_OMIT,
+ RESOURCE_TYPE_SERVICE_WORKER,
+ REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ scoped_refptr<ResourceRequestBody>());
+ }
+
+ void TearDown() override {
+ request_.reset();
+ url_request_context_.reset();
+ url_request_job_factory_.reset();
+ mock_protocol_handler_ = NULL;
+ version_ = NULL;
+ registration_ = NULL;
+ helper_.reset();
+ // URLRequestJobs may post clean-up tasks on destruction.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ ServiceWorkerContextCore* context() const { return helper_->context(); }
+ ServiceWorkerContextWrapper* context_wrapper() const {
+ return helper_->context_wrapper();
+ }
+
+ protected:
+ TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
+ scoped_ptr<net::URLRequestContext> url_request_context_;
+ scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
+ scoped_ptr<net::URLRequest> request_;
+ MockHttpProtocolHandler* mock_protocol_handler_;
+
+ storage::BlobStorageContext blob_storage_context_;
+ content::MockResourceContext resource_context_;
+
+ MockURLRequestDelegate url_request_delegate_;
+ GURL scope_;
+ GURL script_url_;
+};
+
+TEST_F(ServiceWorkerWriteToCacheJobTest, Normal) {
+ mock_protocol_handler_->SetCreateJobCallback(
+ base::Bind(&CreateNormalURLRequestJob));
+ request_->Start();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(net::URLRequestStatus::SUCCESS, request_->status().status());
+ EXPECT_NE(kInvalidServiceWorkerResponseId,
+ version_->script_cache_map()->LookupResourceId(script_url_));
+}
+
+TEST_F(ServiceWorkerWriteToCacheJobTest, InvalidMimeType) {
+ mock_protocol_handler_->SetCreateJobCallback(
+ base::Bind(&CreateInvalidMimeTypeJob));
+ request_->Start();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
+ EXPECT_EQ(kInvalidServiceWorkerResponseId,
+ version_->script_cache_map()->LookupResourceId(script_url_));
+}
+
+TEST_F(ServiceWorkerWriteToCacheJobTest, SSLCertificateError) {
+ mock_protocol_handler_->SetCreateJobCallback(
+ base::Bind(&CreateSSLCertificateErrorJob));
+ request_->Start();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
+ EXPECT_EQ(kInvalidServiceWorkerResponseId,
+ version_->script_cache_map()->LookupResourceId(script_url_));
+}
+
+TEST_F(ServiceWorkerWriteToCacheJobTest, CertStatusError) {
+ mock_protocol_handler_->SetCreateJobCallback(
+ base::Bind(&CreateCertStatusErrorJob));
+ request_->Start();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(net::URLRequestStatus::FAILED, request_->status().status());
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE, request_->status().error());
+ EXPECT_EQ(kInvalidServiceWorkerResponseId,
+ version_->script_cache_map()->LookupResourceId(script_url_));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/session_history_browsertest.cc b/chromium/content/browser/session_history_browsertest.cc
index 4465510ec38..2d81581ee99 100644
--- a/chromium/content/browser/session_history_browsertest.cc
+++ b/chromium/content/browser/session_history_browsertest.cc
@@ -38,7 +38,7 @@ scoped_ptr<net::test_server::HttpResponse> HandleEchoTitleRequest(
base::StringPrintf(
"<html><head><title>%s</title></head></html>",
request.content.c_str()));
- return http_response.PassAs<net::test_server::HttpResponse>();
+ return http_response.Pass();
}
} // namespace
@@ -47,7 +47,7 @@ class SessionHistoryTest : public ContentBrowserTest {
protected:
SessionHistoryTest() {}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
embedded_test_server()->RegisterRequestHandler(
base::Bind(&HandleEchoTitleRequest, "/echotitle"));
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index 9fc9d67ec3a..40499930675 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -12,7 +12,7 @@
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_message_filter.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
-#include "content/browser/worker_host/worker_document_set.h"
+#include "content/browser/shared_worker/worker_document_set.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
#include "content/public/browser/browser_thread.h"
@@ -31,16 +31,17 @@ void WorkerCrashCallback(int render_process_unique_id, int render_frame_id) {
host->delegate()->WorkerCrashed(host);
}
-void NotifyWorkerContextStarted(int worker_process_id, int worker_route_id) {
+void NotifyWorkerReadyForInspection(int worker_process_id,
+ int worker_route_id) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- NotifyWorkerContextStarted, worker_process_id, worker_route_id));
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(NotifyWorkerReadyForInspection,
+ worker_process_id,
+ worker_route_id));
return;
}
- EmbeddedWorkerDevToolsManager::GetInstance()->WorkerContextStarted(
+ EmbeddedWorkerDevToolsManager::GetInstance()->WorkerReadyForInspection(
worker_process_id, worker_route_id);
}
@@ -68,7 +69,8 @@ SharedWorkerHost::SharedWorkerHost(SharedWorkerInstance* instance,
worker_route_id_(worker_route_id),
load_failed_(false),
closed_(false),
- creation_time_(base::TimeTicks::Now()) {
+ creation_time_(base::TimeTicks::Now()),
+ weak_factory_(this) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
@@ -174,10 +176,13 @@ void SharedWorkerHost::WorkerContextDestroyed() {
worker_document_set_ = NULL;
}
+void SharedWorkerHost::WorkerReadyForInspection() {
+ NotifyWorkerReadyForInspection(worker_process_id_, worker_route_id_);
+}
+
void SharedWorkerHost::WorkerScriptLoaded() {
UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded",
base::TimeTicks::Now() - creation_time_);
- NotifyWorkerContextStarted(worker_process_id_, worker_route_id_);
}
void SharedWorkerHost::WorkerScriptLoadFailed() {
@@ -221,11 +226,25 @@ void SharedWorkerHost::AllowDatabase(const GURL& url,
}
void SharedWorkerHost::AllowFileSystem(const GURL& url,
- bool* result) {
+ scoped_ptr<IPC::Message> reply_msg) {
if (!instance_)
return;
- *result = GetContentClient()->browser()->AllowWorkerFileSystem(
- url, instance_->resource_context(), GetRenderFrameIDsForWorker());
+ GetContentClient()->browser()->AllowWorkerFileSystem(
+ url,
+ instance_->resource_context(),
+ GetRenderFrameIDsForWorker(),
+ base::Bind(&SharedWorkerHost::AllowFileSystemResponse,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(&reply_msg)));
+}
+
+void SharedWorkerHost::AllowFileSystemResponse(
+ scoped_ptr<IPC::Message> reply_msg,
+ bool allowed) {
+ WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams(
+ reply_msg.get(),
+ allowed);
+ Send(reply_msg.release());
}
void SharedWorkerHost::AllowIndexedDB(const GURL& url,
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index 53cc218669c..e729589c2ee 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -9,10 +9,11 @@
#include <vector>
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "content/browser/shared_worker/shared_worker_message_filter.h"
-#include "content/browser/worker_host/worker_document_set.h"
+#include "content/browser/shared_worker/worker_document_set.h"
class GURL;
@@ -55,6 +56,7 @@ class SharedWorkerHost {
unsigned long long document_id);
void WorkerContextClosed();
+ void WorkerReadyForInspection();
void WorkerScriptLoaded();
void WorkerScriptLoadFailed();
void WorkerConnected(int message_port_id);
@@ -64,7 +66,7 @@ class SharedWorkerHost {
const base::string16& display_name,
unsigned long estimated_size,
bool* result);
- void AllowFileSystem(const GURL& url, bool* result);
+ void AllowFileSystem(const GURL& url, scoped_ptr<IPC::Message> reply_msg);
void AllowIndexedDB(const GURL& url,
const base::string16& name,
bool* result);
@@ -118,7 +120,8 @@ class SharedWorkerHost {
void SetMessagePortID(SharedWorkerMessageFilter* filter,
int route_id,
int message_port_id);
-
+ void AllowFileSystemResponse(scoped_ptr<IPC::Message> reply_msg,
+ bool allowed);
scoped_ptr<SharedWorkerInstance> instance_;
scoped_refptr<WorkerDocumentSet> worker_document_set_;
FilterList filters_;
@@ -128,6 +131,9 @@ class SharedWorkerHost {
bool load_failed_;
bool closed_;
const base::TimeTicks creation_time_;
+
+ base::WeakPtrFactory<SharedWorkerHost> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SharedWorkerHost);
};
} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_instance.h b/chromium/content/browser/shared_worker/shared_worker_instance.h
index 2785c409d57..b7c5fdb2d70 100644
--- a/chromium/content/browser/shared_worker/shared_worker_instance.h
+++ b/chromium/content/browser/shared_worker/shared_worker_instance.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/basictypes.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "url/gurl.h"
diff --git a/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc
index 83e51c171b3..7811e77af30 100644
--- a/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc
@@ -7,8 +7,9 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -37,6 +38,7 @@ class SharedWorkerInstanceTest : public testing::Test {
browser_context_->GetResourceContext());
}
+ TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestBrowserContext> browser_context_;
scoped_ptr<WorkerStoragePartition> partition_;
const WorkerStoragePartitionId partition_id_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_message_filter.cc b/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
index fa5f15b603f..20e2526899b 100644
--- a/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
@@ -4,7 +4,6 @@
#include "content/browser/shared_worker/shared_worker_message_filter.h"
-#include "content/browser/devtools/worker_devtools_manager.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
#include "content/common/devtools_messages.h"
@@ -54,6 +53,8 @@ bool SharedWorkerMessageFilter::OnMessageReceived(const IPC::Message& message) {
OnWorkerContextClosed)
IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextDestroyed,
OnWorkerContextDestroyed)
+ IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerReadyForInspection,
+ OnWorkerReadyForInspection)
IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerScriptLoaded,
OnWorkerScriptLoaded)
IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerScriptLoadFailed,
@@ -61,8 +62,9 @@ bool SharedWorkerMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerConnected,
OnWorkerConnected)
IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_RequestFileSystemAccessSync,
- OnRequestFileSystemAccessSync)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(
+ WorkerProcessHostMsg_RequestFileSystemAccessSync,
+ OnRequestFileSystemAccess)
IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowIndexedDB, OnAllowIndexedDB)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -109,6 +111,12 @@ void SharedWorkerMessageFilter::OnWorkerContextDestroyed(int worker_route_id) {
this);
}
+void SharedWorkerMessageFilter::OnWorkerReadyForInspection(
+ int worker_route_id) {
+ SharedWorkerServiceImpl::GetInstance()->WorkerReadyForInspection(
+ worker_route_id, this);
+}
+
void SharedWorkerMessageFilter::OnWorkerScriptLoaded(int worker_route_id) {
SharedWorkerServiceImpl::GetInstance()->WorkerScriptLoaded(worker_route_id,
this);
@@ -144,14 +152,12 @@ void SharedWorkerMessageFilter::OnAllowDatabase(
this);
}
-void SharedWorkerMessageFilter::OnRequestFileSystemAccessSync(
+void SharedWorkerMessageFilter::OnRequestFileSystemAccess(
int worker_route_id,
const GURL& url,
- bool* result) {
- SharedWorkerServiceImpl::GetInstance()->AllowFileSystem(worker_route_id,
- url,
- result,
- this);
+ IPC::Message* reply_msg) {
+ SharedWorkerServiceImpl::GetInstance()->AllowFileSystem(
+ worker_route_id, url, reply_msg, this);
}
void SharedWorkerMessageFilter::OnAllowIndexedDB(int worker_route_id,
diff --git a/chromium/content/browser/shared_worker/shared_worker_message_filter.h b/chromium/content/browser/shared_worker/shared_worker_message_filter.h
index 8fb927b805e..e283a22f2d9 100644
--- a/chromium/content/browser/shared_worker/shared_worker_message_filter.h
+++ b/chromium/content/browser/shared_worker/shared_worker_message_filter.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_SHARED_WORKER_SHARED_WORKER_MESSAGE_FILTER_H_
-#include "content/browser/worker_host/worker_storage_partition.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
@@ -26,8 +26,8 @@ class CONTENT_EXPORT SharedWorkerMessageFilter : public BrowserMessageFilter {
MessagePortMessageFilter* message_port_filter);
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
int GetNextRoutingID();
int render_process_id() const { return render_process_id_; }
@@ -38,7 +38,7 @@ class CONTENT_EXPORT SharedWorkerMessageFilter : public BrowserMessageFilter {
protected:
// This is protected, so we can define sub classes for testing.
- virtual ~SharedWorkerMessageFilter();
+ ~SharedWorkerMessageFilter() override;
private:
// Message handlers.
@@ -48,6 +48,8 @@ class CONTENT_EXPORT SharedWorkerMessageFilter : public BrowserMessageFilter {
void OnDocumentDetached(unsigned long long document_id);
void OnWorkerContextClosed(int worker_route_id);
void OnWorkerContextDestroyed(int worker_route_id);
+
+ void OnWorkerReadyForInspection(int worker_route_id);
void OnWorkerScriptLoaded(int worker_route_id);
void OnWorkerScriptLoadFailed(int worker_route_id);
void OnWorkerConnected(int message_port_id, int worker_route_id);
@@ -57,9 +59,9 @@ class CONTENT_EXPORT SharedWorkerMessageFilter : public BrowserMessageFilter {
const base::string16& display_name,
unsigned long estimated_size,
bool* result);
- void OnRequestFileSystemAccessSync(int worker_route_id,
- const GURL& url,
- bool* result);
+ void OnRequestFileSystemAccess(int worker_route_id,
+ const GURL& url,
+ IPC::Message* reply_msg);
void OnAllowIndexedDB(int worker_route_id,
const GURL& url,
const base::string16& name,
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
index 4a689fa812f..b773127db63 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -16,13 +16,18 @@
#include "content/browser/shared_worker/shared_worker_host.h"
#include "content/browser/shared_worker/shared_worker_instance.h"
#include "content/browser/shared_worker/shared_worker_message_filter.h"
-#include "content/browser/worker_host/worker_document_set.h"
+#include "content/browser/shared_worker/worker_document_set.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/worker_service_observer.h"
namespace content {
+
+WorkerService* WorkerService::GetInstance() {
+ return SharedWorkerServiceImpl::GetInstance();
+}
+
namespace {
class ScopedWorkerDependencyChecker {
@@ -352,6 +357,13 @@ void SharedWorkerServiceImpl::WorkerContextDestroyed(
host->WorkerContextDestroyed();
}
+void SharedWorkerServiceImpl::WorkerReadyForInspection(
+ int worker_route_id,
+ SharedWorkerMessageFilter* filter) {
+ if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
+ host->WorkerReadyForInspection();
+}
+
void SharedWorkerServiceImpl::WorkerScriptLoaded(
int worker_route_id,
SharedWorkerMessageFilter* filter) {
@@ -394,10 +406,14 @@ void SharedWorkerServiceImpl::AllowDatabase(
void SharedWorkerServiceImpl::AllowFileSystem(
int worker_route_id,
const GURL& url,
- bool* result,
+ IPC::Message* reply_msg,
SharedWorkerMessageFilter* filter) {
- if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
- host->AllowFileSystem(url, result);
+ if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id)) {
+ host->AllowFileSystem(url, make_scoped_ptr(reply_msg));
+ } else {
+ filter->Send(reply_msg);
+ return;
+ }
}
void SharedWorkerServiceImpl::AllowIndexedDB(
@@ -626,18 +642,10 @@ SharedWorkerServiceImpl::GetRenderersWithWorkerDependency() {
void SharedWorkerServiceImpl::CheckWorkerDependency() {
const std::set<int> current_worker_depended_renderers =
GetRenderersWithWorkerDependency();
- std::vector<int> added_items;
- std::vector<int> removed_items;
- std::set_difference(current_worker_depended_renderers.begin(),
- current_worker_depended_renderers.end(),
- last_worker_depended_renderers_.begin(),
- last_worker_depended_renderers_.end(),
- std::back_inserter(added_items));
- std::set_difference(last_worker_depended_renderers_.begin(),
- last_worker_depended_renderers_.end(),
- current_worker_depended_renderers.begin(),
- current_worker_depended_renderers.end(),
- std::back_inserter(removed_items));
+ std::vector<int> added_items = base::STLSetDifference<std::vector<int> >(
+ current_worker_depended_renderers, last_worker_depended_renderers_);
+ std::vector<int> removed_items = base::STLSetDifference<std::vector<int> >(
+ last_worker_depended_renderers_, current_worker_depended_renderers);
if (!added_items.empty() || !removed_items.empty()) {
last_worker_depended_renderers_ = current_worker_depended_renderers;
update_worker_dependency_(added_items, removed_items);
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.h b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
index e97c259493e..b09d58345a9 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -41,10 +41,10 @@ class CONTENT_EXPORT SharedWorkerServiceImpl
static SharedWorkerServiceImpl* GetInstance();
// WorkerService implementation:
- virtual bool TerminateWorker(int process_id, int route_id) OVERRIDE;
- virtual std::vector<WorkerInfo> GetWorkers() OVERRIDE;
- virtual void AddObserver(WorkerServiceObserver* observer) OVERRIDE;
- virtual void RemoveObserver(WorkerServiceObserver* observer) OVERRIDE;
+ bool TerminateWorker(int process_id, int route_id) override;
+ std::vector<WorkerInfo> GetWorkers() override;
+ void AddObserver(WorkerServiceObserver* observer) override;
+ void RemoveObserver(WorkerServiceObserver* observer) override;
// These methods correspond to worker related IPCs.
void CreateWorker(const ViewHostMsg_CreateWorker_Params& params,
@@ -61,6 +61,8 @@ class CONTENT_EXPORT SharedWorkerServiceImpl
SharedWorkerMessageFilter* filter);
void WorkerContextDestroyed(int worker_route_id,
SharedWorkerMessageFilter* filter);
+ void WorkerReadyForInspection(int worker_route_id,
+ SharedWorkerMessageFilter* filter);
void WorkerScriptLoaded(int worker_route_id,
SharedWorkerMessageFilter* filter);
void WorkerScriptLoadFailed(int worker_route_id,
@@ -77,7 +79,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl
SharedWorkerMessageFilter* filter);
void AllowFileSystem(int worker_route_id,
const GURL& url,
- bool* result,
+ IPC::Message* reply_msg,
SharedWorkerMessageFilter* filter);
void AllowIndexedDB(int worker_route_id,
const GURL& url,
@@ -113,7 +115,7 @@ class CONTENT_EXPORT SharedWorkerServiceImpl
PendingInstaneMap;
SharedWorkerServiceImpl();
- virtual ~SharedWorkerServiceImpl();
+ ~SharedWorkerServiceImpl() override;
void ResetForTesting();
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
index e08da83efb2..8e1dd80104d 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl_unittest.cc
@@ -16,7 +16,7 @@
#include "content/browser/message_port_message_filter.h"
#include "content/browser/shared_worker/shared_worker_message_filter.h"
#include "content/browser/shared_worker/shared_worker_service_impl.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
+#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/common/message_port_messages.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
@@ -60,8 +60,8 @@ class SharedWorkerServiceImplTest : public testing::Test {
&SharedWorkerServiceImplTest::MockTryIncrementWorkerRefCount);
}
- virtual void SetUp() OVERRIDE {}
- virtual void TearDown() OVERRIDE {
+ void SetUp() override {}
+ void TearDown() override {
s_update_worker_dependency_call_count_ = 0;
s_worker_dependency_added_ids_.clear();
s_worker_dependency_removed_ids_.clear();
@@ -110,7 +110,7 @@ class MockMessagePortMessageFilter : public MessagePortMessageFilter {
ScopedVector<IPC::Message>* message_queue)
: MessagePortMessageFilter(callback), message_queue_(message_queue) {}
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
if (!message_queue_) {
delete message;
return false;
@@ -125,7 +125,7 @@ class MockMessagePortMessageFilter : public MessagePortMessageFilter {
}
private:
- virtual ~MockMessagePortMessageFilter() {}
+ ~MockMessagePortMessageFilter() override {}
ScopedVector<IPC::Message>* message_queue_;
};
@@ -142,7 +142,7 @@ class MockSharedWorkerMessageFilter : public SharedWorkerMessageFilter {
message_port_filter),
message_queue_(message_queue) {}
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
if (!message_queue_) {
delete message;
return false;
@@ -157,7 +157,7 @@ class MockSharedWorkerMessageFilter : public SharedWorkerMessageFilter {
}
private:
- virtual ~MockSharedWorkerMessageFilter() {}
+ ~MockSharedWorkerMessageFilter() override {}
ScopedVector<IPC::Message>* message_queue_;
};
@@ -436,6 +436,12 @@ TEST_F(SharedWorkerServiceImplTest, BasicTest) {
connector->SendSendQueuedMessages(empty_messages);
EXPECT_EQ(0U, renderer_host->QueuedMessageCount());
+ // SharedWorker sends WorkerHostMsg_WorkerReadyForInspection in
+ // EmbeddedSharedWorkerStub::WorkerReadyForInspection().
+ EXPECT_TRUE(renderer_host->OnMessageReceived(
+ new WorkerHostMsg_WorkerReadyForInspection(worker_route_id)));
+ EXPECT_EQ(0U, renderer_host->QueuedMessageCount());
+
// SharedWorker sends WorkerHostMsg_WorkerScriptLoaded in
// EmbeddedSharedWorkerStub::workerScriptLoaded().
EXPECT_TRUE(renderer_host->OnMessageReceived(
@@ -527,6 +533,12 @@ TEST_F(SharedWorkerServiceImplTest, TwoRendererTest) {
connector0->SendSendQueuedMessages(empty_messages);
EXPECT_EQ(0U, renderer_host0->QueuedMessageCount());
+ // SharedWorker sends WorkerHostMsg_WorkerReadyForInspection in
+ // EmbeddedSharedWorkerStub::WorkerReadyForInspection().
+ EXPECT_TRUE(renderer_host0->OnMessageReceived(
+ new WorkerHostMsg_WorkerReadyForInspection(worker_route_id)));
+ EXPECT_EQ(0U, renderer_host0->QueuedMessageCount());
+
// SharedWorker sends WorkerHostMsg_WorkerScriptLoaded in
// EmbeddedSharedWorkerStub::workerScriptLoaded().
EXPECT_TRUE(renderer_host0->OnMessageReceived(
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
new file mode 100644
index 00000000000..ce39df5788c
--- /dev/null
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -0,0 +1,145 @@
+// Copyright 2014 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/bind.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
+#include "base/test/test_timeouts.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
+#include "net/base/test_data_directory.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class WorkerTest : public ContentBrowserTest {
+ public:
+ WorkerTest() {}
+
+ GURL GetTestURL(const std::string& test_case, const std::string& query) {
+ base::FilePath test_file_path = GetTestFilePath(
+ "workers", test_case.c_str());
+ return GetFileUrlWithQuery(test_file_path, query);
+ }
+
+ void RunTest(Shell* window,
+ const std::string& test_case,
+ const std::string& query) {
+ GURL url = GetTestURL(test_case, query);
+ const base::string16 expected_title = base::ASCIIToUTF16("OK");
+ TitleWatcher title_watcher(window->web_contents(), expected_title);
+ NavigateToURL(window, url);
+ base::string16 final_title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(expected_title, final_title);
+ }
+
+ void RunTest(const std::string& test_case, const std::string& query) {
+ RunTest(shell(), test_case, query);
+ }
+
+ static void QuitUIMessageLoop(base::Callback<void()> callback) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
+ }
+
+ void NavigateAndWaitForAuth(const GURL& url) {
+ ShellContentBrowserClient* browser_client =
+ ShellContentBrowserClient::Get();
+ scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
+ browser_client->resource_dispatcher_host_delegate()->
+ set_login_request_callback(
+ base::Bind(&QuitUIMessageLoop, runner->QuitClosure()));
+ shell()->LoadURL(url);
+ runner->Run();
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(WorkerTest, SingleWorker) {
+ RunTest("single_worker.html", std::string());
+}
+
+IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleWorkers) {
+ RunTest("multi_worker.html", std::string());
+}
+
+IN_PROC_BROWSER_TEST_F(WorkerTest, SingleSharedWorker) {
+ RunTest("single_worker.html", "shared=true");
+}
+
+// http://crbug.com/96435
+IN_PROC_BROWSER_TEST_F(WorkerTest, MultipleSharedWorkers) {
+ RunTest("multi_worker.html", "shared=true");
+}
+
+// Incognito windows should not share workers with non-incognito windows
+// http://crbug.com/30021
+IN_PROC_BROWSER_TEST_F(WorkerTest, IncognitoSharedWorkers) {
+ // Load a non-incognito tab and have it create a shared worker
+ RunTest("incognito_worker.html", std::string());
+
+ // Incognito worker should not share with non-incognito
+ RunTest(CreateOffTheRecordBrowser(), "incognito_worker.html", std::string());
+}
+
+// Make sure that auth dialog is displayed from worker context.
+// http://crbug.com/33344
+IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerHttpAuth) {
+ ASSERT_TRUE(test_server()->Start());
+ GURL url = test_server()->GetURL("files/workers/worker_auth.html");
+
+ NavigateAndWaitForAuth(url);
+}
+
+// Make sure that auth dialog is displayed from shared worker context.
+// http://crbug.com/33344
+IN_PROC_BROWSER_TEST_F(WorkerTest, SharedWorkerHttpAuth) {
+ ASSERT_TRUE(test_server()->Start());
+ GURL url = test_server()->GetURL("files/workers/shared_worker_auth.html");
+ NavigateAndWaitForAuth(url);
+}
+
+IN_PROC_BROWSER_TEST_F(WorkerTest, WebSocketSharedWorker) {
+ // Launch WebSocket server.
+ net::SpawnedTestServer ws_server(net::SpawnedTestServer::TYPE_WS,
+ net::SpawnedTestServer::kLocalhost,
+ net::GetWebSocketTestDataDirectory());
+ ASSERT_TRUE(ws_server.Start());
+
+ // Generate test URL.
+ std::string scheme("http");
+ GURL::Replacements replacements;
+ replacements.SetSchemeStr(scheme);
+ GURL url = ws_server.GetURL(
+ "websocket_shared_worker.html").ReplaceComponents(replacements);
+
+ // Run test.
+ Shell* window = shell();
+ const base::string16 expected_title = base::ASCIIToUTF16("OK");
+ TitleWatcher title_watcher(window->web_contents(), expected_title);
+ NavigateToURL(window, url);
+ base::string16 final_title = title_watcher.WaitAndGetTitle();
+ EXPECT_EQ(expected_title, final_title);
+}
+
+IN_PROC_BROWSER_TEST_F(WorkerTest, PassMessagePortToSharedWorker) {
+ RunTest("pass_messageport_to_sharedworker.html", "");
+}
+
+IN_PROC_BROWSER_TEST_F(WorkerTest,
+ PassMessagePortToSharedWorkerDontWaitForConnect) {
+ RunTest("pass_messageport_to_sharedworker_dont_wait_for_connect.html", "");
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/worker_document_set.cc b/chromium/content/browser/shared_worker/worker_document_set.cc
new file mode 100644
index 00000000000..f3ef7d2636d
--- /dev/null
+++ b/chromium/content/browser/shared_worker/worker_document_set.cc
@@ -0,0 +1,83 @@
+// Copyright 2014 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 "content/browser/shared_worker/worker_document_set.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+WorkerDocumentSet::WorkerDocumentSet() {
+}
+
+void WorkerDocumentSet::Add(BrowserMessageFilter* parent,
+ unsigned long long document_id,
+ int render_process_id,
+ int render_frame_id) {
+ DocumentInfo info(parent, document_id, render_process_id, render_frame_id);
+ document_set_.insert(info);
+}
+
+bool WorkerDocumentSet::Contains(BrowserMessageFilter* parent,
+ unsigned long long document_id) const {
+ for (DocumentInfoSet::const_iterator i = document_set_.begin();
+ i != document_set_.end(); ++i) {
+ if (i->filter() == parent && i->document_id() == document_id)
+ return true;
+ }
+ return false;
+}
+
+bool WorkerDocumentSet::ContainsExternalRenderer(
+ int worker_process_id) const {
+ for (DocumentInfoSet::const_iterator i = document_set_.begin();
+ i != document_set_.end(); ++i) {
+ if (i->render_process_id() != worker_process_id)
+ return true;
+ }
+ return false;
+}
+
+void WorkerDocumentSet::Remove(BrowserMessageFilter* parent,
+ unsigned long long document_id) {
+ for (DocumentInfoSet::iterator i = document_set_.begin();
+ i != document_set_.end(); i++) {
+ if (i->filter() == parent && i->document_id() == document_id) {
+ document_set_.erase(i);
+ break;
+ }
+ }
+ // Should not be duplicate copies in the document set.
+ DCHECK(!Contains(parent, document_id));
+}
+
+void WorkerDocumentSet::RemoveAll(BrowserMessageFilter* parent) {
+ for (DocumentInfoSet::iterator i = document_set_.begin();
+ i != document_set_.end();) {
+
+ // Note this idiom is somewhat tricky - calling document_set_.erase(iter)
+ // invalidates any iterators that point to the element being removed, so
+ // bump the iterator beyond the item being removed before calling erase.
+ if (i->filter() == parent) {
+ DocumentInfoSet::iterator item_to_delete = i++;
+ document_set_.erase(item_to_delete);
+ } else {
+ ++i;
+ }
+ }
+}
+
+WorkerDocumentSet::DocumentInfo::DocumentInfo(
+ BrowserMessageFilter* filter, unsigned long long document_id,
+ int render_process_id, int render_frame_id)
+ : filter_(filter),
+ document_id_(document_id),
+ render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id) {
+}
+
+WorkerDocumentSet::~WorkerDocumentSet() {
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/worker_document_set.h b/chromium/content/browser/shared_worker/worker_document_set.h
new file mode 100644
index 00000000000..54ae9e93daa
--- /dev/null
+++ b/chromium/content/browser/shared_worker/worker_document_set.h
@@ -0,0 +1,96 @@
+// Copyright 2014 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 CONTENT_BROWSER_SHARED_WORKER_WORKER_DOCUMENT_SET_H_
+#define CONTENT_BROWSER_SHARED_WORKER_WORKER_DOCUMENT_SET_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+
+namespace content {
+class BrowserMessageFilter;
+
+// The WorkerDocumentSet tracks all of the DOM documents associated with a
+// set of workers. With nested workers, multiple workers can share the same
+// WorkerDocumentSet (meaning that they all share the same lifetime, and will
+// all exit when the last document in that set exits, per the WebWorkers spec).
+class WorkerDocumentSet : public base::RefCounted<WorkerDocumentSet> {
+ public:
+ WorkerDocumentSet();
+
+ // The information we track for each document
+ class DocumentInfo {
+ public:
+ DocumentInfo(BrowserMessageFilter* filter, unsigned long long document_id,
+ int renderer_process_id, int render_frame_id);
+ BrowserMessageFilter* filter() const { return filter_; }
+ unsigned long long document_id() const { return document_id_; }
+ int render_process_id() const { return render_process_id_; }
+ int render_frame_id() const { return render_frame_id_; }
+
+ // Define operator "<", which is used to determine uniqueness within
+ // the set.
+ bool operator <(const DocumentInfo& other) const {
+ // Items are identical if the sender and document_id are identical,
+ // otherwise create an arbitrary stable ordering based on the document
+ // id/filter.
+ if (filter() == other.filter()) {
+ return document_id() < other.document_id();
+ } else {
+ return reinterpret_cast<unsigned long long>(filter()) <
+ reinterpret_cast<unsigned long long>(other.filter());
+ }
+ }
+
+ private:
+ BrowserMessageFilter* filter_;
+ unsigned long long document_id_;
+ int render_process_id_;
+ int render_frame_id_;
+ };
+
+ // Adds a document to a shared worker's document set. Also includes the
+ // associated render_process_id the document is associated with, to enable
+ // communication with the parent tab for things like http auth dialogs.
+ void Add(BrowserMessageFilter* parent,
+ unsigned long long document_id,
+ int render_process_id,
+ int render_frame_id);
+
+ // Checks to see if a document is in a shared worker's document set.
+ bool Contains(BrowserMessageFilter* parent,
+ unsigned long long document_id) const;
+
+ // Checks to see if the document set contains any documents which is
+ // associated with other renderer process than worker_process_id.
+ bool ContainsExternalRenderer(int worker_process_id) const;
+
+ // Removes a specific document from a worker's document set when that document
+ // is detached.
+ void Remove(BrowserMessageFilter* parent, unsigned long long document_id);
+
+ // Invoked when a render process exits, to remove all associated documents
+ // from a worker's document set.
+ void RemoveAll(BrowserMessageFilter* parent);
+
+ bool IsEmpty() const { return document_set_.empty(); }
+
+ // Define a typedef for convenience here when declaring iterators, etc.
+ typedef std::set<DocumentInfo> DocumentInfoSet;
+
+ // Returns the set of documents associated with this worker.
+ const DocumentInfoSet& documents() { return document_set_; }
+
+ private:
+ friend class base::RefCounted<WorkerDocumentSet>;
+ virtual ~WorkerDocumentSet();
+
+ DocumentInfoSet document_set_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SHARED_WORKER_WORKER_DOCUMENT_SET_H_
diff --git a/chromium/content/browser/shared_worker/worker_storage_partition.cc b/chromium/content/browser/shared_worker/worker_storage_partition.cc
new file mode 100644
index 00000000000..c9bb5bedd9d
--- /dev/null
+++ b/chromium/content/browser/shared_worker/worker_storage_partition.cc
@@ -0,0 +1,103 @@
+// Copyright 2014 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 "content/browser/shared_worker/worker_storage_partition.h"
+
+#include <string>
+
+#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/database/database_tracker.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/quota/quota_manager.h"
+
+namespace content {
+
+WorkerStoragePartition::WorkerStoragePartition(
+ net::URLRequestContextGetter* url_request_context,
+ net::URLRequestContextGetter* media_url_request_context,
+ ChromeAppCacheService* appcache_service,
+ storage::QuotaManager* quota_manager,
+ storage::FileSystemContext* filesystem_context,
+ storage::DatabaseTracker* database_tracker,
+ IndexedDBContextImpl* indexed_db_context,
+ ServiceWorkerContextWrapper* service_worker_context)
+ : url_request_context_(url_request_context),
+ media_url_request_context_(media_url_request_context),
+ appcache_service_(appcache_service),
+ quota_manager_(quota_manager),
+ filesystem_context_(filesystem_context),
+ database_tracker_(database_tracker),
+ indexed_db_context_(indexed_db_context),
+ service_worker_context_(service_worker_context) {
+}
+
+WorkerStoragePartition::WorkerStoragePartition(
+ const WorkerStoragePartition& other) {
+ Copy(other);
+}
+
+const WorkerStoragePartition& WorkerStoragePartition::operator=(
+ const WorkerStoragePartition& rhs) {
+ Copy(rhs);
+ return *this;
+}
+
+bool WorkerStoragePartition::Equals(
+ const WorkerStoragePartition& other) const {
+ return url_request_context_.get() == other.url_request_context_.get() &&
+ media_url_request_context_.get() ==
+ other.media_url_request_context_.get() &&
+ appcache_service_.get() == other.appcache_service_.get() &&
+ quota_manager_.get() == other.quota_manager_.get() &&
+ filesystem_context_.get() == other.filesystem_context_.get() &&
+ database_tracker_.get() == other.database_tracker_.get() &&
+ indexed_db_context_.get() == other.indexed_db_context_.get() &&
+ service_worker_context_.get() == other.service_worker_context_.get();
+}
+
+WorkerStoragePartition::~WorkerStoragePartition() {
+}
+
+void WorkerStoragePartition::Copy(const WorkerStoragePartition& other) {
+ url_request_context_ = other.url_request_context_;
+ media_url_request_context_ = other.media_url_request_context_;
+ appcache_service_ = other.appcache_service_;
+ quota_manager_ = other.quota_manager_;
+ filesystem_context_ = other.filesystem_context_;
+ database_tracker_ = other.database_tracker_;
+ indexed_db_context_ = other.indexed_db_context_;
+ service_worker_context_ = other.service_worker_context_;
+}
+
+WorkerStoragePartitionId::WorkerStoragePartitionId(
+ const WorkerStoragePartition& partition)
+ : url_request_context_(partition.url_request_context()),
+ media_url_request_context_(partition.media_url_request_context()),
+ appcache_service_(partition.appcache_service()),
+ quota_manager_(partition.quota_manager()),
+ filesystem_context_(partition.filesystem_context()),
+ database_tracker_(partition.database_tracker()),
+ indexed_db_context_(partition.indexed_db_context()),
+ service_worker_context_(partition.service_worker_context()) {
+}
+
+WorkerStoragePartitionId::~WorkerStoragePartitionId() {
+}
+
+bool WorkerStoragePartitionId::Equals(
+ const WorkerStoragePartitionId& other) const {
+ return url_request_context_ == other.url_request_context_ &&
+ media_url_request_context_ == other.media_url_request_context_ &&
+ appcache_service_ == other.appcache_service_ &&
+ quota_manager_ == other.quota_manager_ &&
+ filesystem_context_ == other.filesystem_context_ &&
+ database_tracker_ == other.database_tracker_ &&
+ indexed_db_context_ == other.indexed_db_context_ &&
+ service_worker_context_ == other.service_worker_context_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/shared_worker/worker_storage_partition.h b/chromium/content/browser/shared_worker/worker_storage_partition.h
new file mode 100644
index 00000000000..2f595b0e72f
--- /dev/null
+++ b/chromium/content/browser/shared_worker/worker_storage_partition.h
@@ -0,0 +1,132 @@
+// Copyright 2014 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 CONTENT_BROWSER_SHARED_WORKERT_WORKER_STORAGE_PARTITION_H_
+#define CONTENT_BROWSER_SHARED_WORKERT_WORKER_STORAGE_PARTITION_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+
+namespace storage {
+class QuotaManager;
+}
+
+namespace storage {
+class FileSystemContext;
+} // namespace storage
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace storage {
+class DatabaseTracker;
+} // namespace storage
+
+namespace content {
+class ChromeAppCacheService;
+class IndexedDBContextImpl;
+class ServiceWorkerContextWrapper;
+
+// Contains the data from StoragePartition for use by Worker APIs.
+//
+// StoragePartition meant for the UI so we can't use it directly in many
+// Worker APIs that run on the IO thread. While we could make it RefCounted,
+// the Worker system is the only place that really needs access on the IO
+// thread. Instead of changing the lifetime semantics of StoragePartition,
+// we just create a parallel struct here to simplify the APIs of various
+// methods in WorkerServiceImpl.
+//
+// This class is effectively a struct, but we make it a class because we want to
+// define copy constructors, assignment operators, and an Equals() function for
+// it which makes it look awkward as a struct.
+class CONTENT_EXPORT WorkerStoragePartition {
+ public:
+ WorkerStoragePartition(
+ net::URLRequestContextGetter* url_request_context,
+ net::URLRequestContextGetter* media_url_request_context,
+ ChromeAppCacheService* appcache_service,
+ storage::QuotaManager* quota_manager,
+ storage::FileSystemContext* filesystem_context,
+ storage::DatabaseTracker* database_tracker,
+ IndexedDBContextImpl* indexed_db_context,
+ ServiceWorkerContextWrapper* service_worker_context);
+ ~WorkerStoragePartition();
+
+ // Declaring so these don't get inlined which has the unfortunate effect of
+ // requiring all including classes to have the full definition of every member
+ // type.
+ WorkerStoragePartition(const WorkerStoragePartition& other);
+ const WorkerStoragePartition& operator=(const WorkerStoragePartition& rhs);
+
+ bool Equals(const WorkerStoragePartition& other) const;
+
+ net::URLRequestContextGetter* url_request_context() const {
+ return url_request_context_.get();
+ }
+
+ net::URLRequestContextGetter* media_url_request_context() const {
+ return media_url_request_context_.get();
+ }
+
+ ChromeAppCacheService* appcache_service() const {
+ return appcache_service_.get();
+ }
+
+ storage::QuotaManager* quota_manager() const { return quota_manager_.get(); }
+
+ storage::FileSystemContext* filesystem_context() const {
+ return filesystem_context_.get();
+ }
+
+ storage::DatabaseTracker* database_tracker() const {
+ return database_tracker_.get();
+ }
+
+ IndexedDBContextImpl* indexed_db_context() const {
+ return indexed_db_context_.get();
+ }
+
+ ServiceWorkerContextWrapper* service_worker_context() const {
+ return service_worker_context_.get();
+ }
+
+ private:
+ void Copy(const WorkerStoragePartition& other);
+
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_;
+ scoped_refptr<net::URLRequestContextGetter> media_url_request_context_;
+ scoped_refptr<ChromeAppCacheService> appcache_service_;
+ scoped_refptr<storage::QuotaManager> quota_manager_;
+ scoped_refptr<storage::FileSystemContext> filesystem_context_;
+ scoped_refptr<storage::DatabaseTracker> database_tracker_;
+ scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
+ scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+};
+
+// WorkerStoragePartitionId can be used to identify each
+// WorkerStoragePartitions. We can hold WorkerStoragePartitionId without
+// extending the lifetime of all objects in the WorkerStoragePartition.
+// That means that holding a WorkerStoragePartitionId doesn't mean the
+// corresponding partition and its members are kept alive.
+class CONTENT_EXPORT WorkerStoragePartitionId {
+ public:
+ explicit WorkerStoragePartitionId(const WorkerStoragePartition& partition);
+ ~WorkerStoragePartitionId();
+ bool Equals(const WorkerStoragePartitionId& other) const;
+
+ private:
+ net::URLRequestContextGetter* url_request_context_;
+ net::URLRequestContextGetter* media_url_request_context_;
+ ChromeAppCacheService* appcache_service_;
+ storage::QuotaManager* quota_manager_;
+ storage::FileSystemContext* filesystem_context_;
+ storage::DatabaseTracker* database_tracker_;
+ IndexedDBContextImpl* indexed_db_context_;
+ ServiceWorkerContextWrapper* service_worker_context_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SHARED_WORKERT_WORKER_STORAGE_PARTITION_H_
diff --git a/chromium/content/browser/signed_certificate_timestamp_store_impl.h b/chromium/content/browser/signed_certificate_timestamp_store_impl.h
index 4cd98ccb041..b2f728a57dd 100644
--- a/chromium/content/browser/signed_certificate_timestamp_store_impl.h
+++ b/chromium/content/browser/signed_certificate_timestamp_store_impl.h
@@ -20,18 +20,17 @@ class SignedCertificateTimestampStoreImpl
static SignedCertificateTimestampStoreImpl* GetInstance();
// SignedCertificateTimestampStore implementation:
- virtual int Store(
- net::ct::SignedCertificateTimestamp* sct,
- int render_process_host_id) OVERRIDE;
- virtual bool Retrieve(
+ int Store(net::ct::SignedCertificateTimestamp* sct,
+ int render_process_host_id) override;
+ bool Retrieve(
int sct_id,
- scoped_refptr<net::ct::SignedCertificateTimestamp>* sct) OVERRIDE;
+ scoped_refptr<net::ct::SignedCertificateTimestamp>* sct) override;
private:
friend struct DefaultSingletonTraits<SignedCertificateTimestampStoreImpl>;
SignedCertificateTimestampStoreImpl();
- virtual ~SignedCertificateTimestampStoreImpl();
+ ~SignedCertificateTimestampStoreImpl() override;
RendererDataMemoizingStore<net::ct::SignedCertificateTimestamp> store_;
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index b6e6918c0a4..f1555dc1af8 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -25,7 +25,7 @@ int32 SiteInstanceImpl::next_site_instance_id_ = 1;
SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
: id_(next_site_instance_id_++),
- active_view_count_(0),
+ active_frame_count_(0),
browsing_instance_(browsing_instance),
process_(NULL),
has_site_(false) {
@@ -120,6 +120,8 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() {
process_, site_);
}
+ TRACE_EVENT2("navigation", "SiteInstanceImpl::GetProcess",
+ "site id", id_, "process id", process_->GetID());
GetContentClient()->browser()->SiteInstanceGotProcess(this);
if (has_site_)
@@ -131,6 +133,8 @@ RenderProcessHost* SiteInstanceImpl::GetProcess() {
}
void SiteInstanceImpl::SetSite(const GURL& url) {
+ TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite",
+ "site id", id_, "url", url.possibly_invalid_spec());
// A SiteInstance's site should not change.
// TODO(creis): When following links or script navigations, we can currently
// render pages from other sites in this SiteInstance. This will eventually
@@ -241,10 +245,12 @@ SiteInstance* SiteInstance::CreateForURL(BrowserContext* browser_context,
/*static*/
bool SiteInstance::IsSameWebSite(BrowserContext* browser_context,
- const GURL& real_url1,
- const GURL& real_url2) {
- GURL url1 = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url1);
- GURL url2 = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url2);
+ const GURL& real_src_url,
+ const GURL& real_dest_url) {
+ GURL src_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
+ real_src_url);
+ GURL dest_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
+ real_dest_url);
// We infer web site boundaries based on the registered domain name of the
// top-level page and the scheme. We do not pay attention to the port if
@@ -254,20 +260,26 @@ bool SiteInstance::IsSameWebSite(BrowserContext* browser_context,
// Some special URLs will match the site instance of any other URL. This is
// done before checking both of them for validity, since we want these URLs
// to have the same site instance as even an invalid one.
- if (IsRendererDebugURL(url1) || IsRendererDebugURL(url2))
+ if (IsRendererDebugURL(src_url) || IsRendererDebugURL(dest_url))
return true;
// If either URL is invalid, they aren't part of the same site.
- if (!url1.is_valid() || !url2.is_valid())
+ if (!src_url.is_valid() || !dest_url.is_valid())
return false;
+ // If the destination url is just a blank page, we treat them as part of the
+ // same site.
+ GURL blank_page(url::kAboutBlankURL);
+ if (dest_url == blank_page)
+ return true;
+
// If the schemes differ, they aren't part of the same site.
- if (url1.scheme() != url2.scheme())
+ if (src_url.scheme() != dest_url.scheme())
return false;
return net::registry_controlled_domains::SameDomainOrHost(
- url1,
- url2,
+ src_url,
+ dest_url,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
}
@@ -329,7 +341,8 @@ void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
void SiteInstanceImpl::LockToOrigin() {
// We currently only restrict this process to a particular site if the
// --enable-strict-site-isolation or --site-per-process flags are present.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
command_line.HasSwitch(switches::kSitePerProcess)) {
ChildProcessSecurityPolicyImpl* policy =
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index 69197eeeab4..2c55688bc32 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -19,14 +19,14 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
public RenderProcessHostObserver {
public:
// SiteInstance interface overrides.
- virtual int32 GetId() OVERRIDE;
- virtual bool HasProcess() const OVERRIDE;
- virtual RenderProcessHost* GetProcess() OVERRIDE;
- virtual BrowserContext* GetBrowserContext() const OVERRIDE;
- virtual const GURL& GetSiteURL() const OVERRIDE;
- virtual SiteInstance* GetRelatedSiteInstance(const GURL& url) OVERRIDE;
- virtual bool IsRelatedSiteInstance(const SiteInstance* instance) OVERRIDE;
- virtual size_t GetRelatedActiveContentsCount() OVERRIDE;
+ int32 GetId() override;
+ bool HasProcess() const override;
+ RenderProcessHost* GetProcess() override;
+ BrowserContext* GetBrowserContext() const override;
+ const GURL& GetSiteURL() const override;
+ SiteInstance* GetRelatedSiteInstance(const GURL& url) override;
+ bool IsRelatedSiteInstance(const SiteInstance* instance) override;
+ size_t GetRelatedActiveContentsCount() override;
// Set the web site that this SiteInstance is rendering pages for.
// This includes the scheme and registered domain, but not the port. If the
@@ -45,28 +45,27 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
// navigating to the URL.
bool HasWrongProcessForURL(const GURL& url);
- // Increase the number of active views in this SiteInstance. This is
- // increased when a view is created, or a currently swapped out view
+ // Increase the number of active frames in this SiteInstance. This is
+ // increased when a frame is created, or a currently swapped out frame
// is swapped in.
- void increment_active_view_count() { active_view_count_++; }
+ void increment_active_frame_count() { active_frame_count_++; }
- // Decrease the number of active views in this SiteInstance. This is
- // decreased when a view is destroyed, or a currently active view is
+ // Decrease the number of active frames in this SiteInstance. This is
+ // decreased when a frame is destroyed, or a currently active frame is
// swapped out.
- void decrement_active_view_count() { active_view_count_--; }
+ void decrement_active_frame_count() { active_frame_count_--; }
- // Get the number of active views which belong to this
- // SiteInstance. If there is no active view left in this
- // SiteInstance, all view in this SiteInstance can be safely
- // discarded to save memory.
- size_t active_view_count() { return active_view_count_; }
+ // Get the number of active frames which belong to this SiteInstance. If
+ // there are no active frames left, all frames in this SiteInstance can be
+ // safely discarded.
+ size_t active_frame_count() { return active_frame_count_; }
// Increase the number of active WebContentses using this SiteInstance. Note
- // that, unlike active_view_count, this does not count pending RVHs.
+ // that, unlike active_frame_count, this does not count pending RFHs.
void IncrementRelatedActiveContentsCount();
// Decrease the number of active WebContentses using this SiteInstance. Note
- // that, unlike active_view_count, this does not count pending RVHs.
+ // that, unlike active_frame_count, this does not count pending RFHs.
void DecrementRelatedActiveContentsCount();
// Sets the global factory used to create new RenderProcessHosts. It may be
@@ -90,7 +89,7 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
friend class SiteInstance;
// Virtual to allow tests to extend it.
- virtual ~SiteInstanceImpl();
+ ~SiteInstanceImpl() override;
// Create a new SiteInstance. Protected to give access to BrowsingInstance
// and tests; most callers should use Create or GetRelatedSiteInstance
@@ -99,7 +98,7 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
private:
// RenderProcessHostObserver implementation.
- virtual void RenderProcessHostDestroyed(RenderProcessHost* host) OVERRIDE;
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override;
// Used to restrict a process' origin access rights.
void LockToOrigin();
@@ -113,8 +112,8 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
// A unique ID for this SiteInstance.
int32 id_;
- // The number of active views under this SiteInstance.
- size_t active_view_count_;
+ // The number of active frames in this SiteInstance.
+ size_t active_frame_count_;
// BrowsingInstance to which this SiteInstance belongs.
scoped_refptr<BrowsingInstance> browsing_instance_;
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index 646f4d07957..993ef35179a 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -36,20 +36,20 @@ const char kPrivilegedScheme[] = "privileged";
class SiteInstanceTestWebUIControllerFactory : public WebUIControllerFactory {
public:
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const OVERRIDE {
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override {
return NULL;
}
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override {
return WebUI::kNoWebUI;
}
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return HasWebUIScheme(url);
}
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return HasWebUIScheme(url);
}
};
@@ -61,12 +61,12 @@ class SiteInstanceTestBrowserClient : public TestContentBrowserClient {
WebUIControllerFactory::RegisterFactory(&factory_);
}
- virtual ~SiteInstanceTestBrowserClient() {
+ ~SiteInstanceTestBrowserClient() override {
WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
}
- virtual bool IsSuitableHost(RenderProcessHost* process_host,
- const GURL& site_url) OVERRIDE {
+ bool IsSuitableHost(RenderProcessHost* process_host,
+ const GURL& site_url) override {
return (privileged_process_id_ == process_host->GetID()) ==
site_url.SchemeIs(kPrivilegedScheme);
}
@@ -90,7 +90,7 @@ class SiteInstanceTest : public testing::Test {
old_browser_client_(NULL) {
}
- virtual void SetUp() {
+ void SetUp() override {
old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
url::AddStandardScheme(kPrivilegedScheme);
url::AddStandardScheme(kChromeUIScheme);
@@ -98,7 +98,7 @@ class SiteInstanceTest : public testing::Test {
SiteInstanceImpl::set_render_process_host_factory(&rph_factory_);
}
- virtual void TearDown() {
+ void TearDown() override {
// Ensure that no RenderProcessHosts are left over after the tests.
EXPECT_TRUE(RenderProcessHost::AllHostsIterator().IsAtEnd());
@@ -157,9 +157,7 @@ class TestBrowsingInstance : public BrowsingInstance {
using BrowsingInstance::UnregisterSiteInstance;
private:
- virtual ~TestBrowsingInstance() {
- (*delete_counter_)++;
- }
+ ~TestBrowsingInstance() override { (*delete_counter_)++; }
int* delete_counter_;
};
@@ -179,9 +177,7 @@ class TestSiteInstance : public SiteInstanceImpl {
private:
TestSiteInstance(BrowsingInstance* browsing_instance, int* delete_counter)
: SiteInstanceImpl(browsing_instance), delete_counter_(delete_counter) {}
- virtual ~TestSiteInstance() {
- (*delete_counter_)++;
- }
+ ~TestSiteInstance() override { (*delete_counter_)++; }
int* delete_counter_;
};
@@ -204,7 +200,7 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
EXPECT_EQ(0, site_delete_counter);
NavigationEntryImpl* e1 = new NavigationEntryImpl(
- instance, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK,
+ instance, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
false);
// Redundantly setting e1's SiteInstance shouldn't affect the ref count.
@@ -213,7 +209,7 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// Add a second reference
NavigationEntryImpl* e2 = new NavigationEntryImpl(
- instance, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK,
+ instance, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
false);
// Now delete both entries and be sure the SiteInstance goes away.
@@ -266,7 +262,7 @@ TEST_F(SiteInstanceTest, CloneNavigationEntry) {
&browsing_delete_counter);
NavigationEntryImpl* e1 = new NavigationEntryImpl(
- instance1, 0, url, Referrer(), base::string16(), PAGE_TRANSITION_LINK,
+ instance1, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
false);
// Clone the entry
NavigationEntryImpl* e2 = new NavigationEntryImpl(*e1);
@@ -372,6 +368,7 @@ TEST_F(SiteInstanceTest, IsSameWebSite) {
GURL url_foo_https = GURL("https://foo/a.html");
GURL url_foo_port = GURL("http://foo:8080/a.html");
GURL url_javascript = GURL("javascript:alert(1);");
+ GURL url_blank = GURL(url::kAboutBlankURL);
// Same scheme and port -> same site.
EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo, url_foo2));
@@ -388,13 +385,23 @@ TEST_F(SiteInstanceTest, IsSameWebSite) {
EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_javascript, url_foo_https));
EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_javascript, url_foo_port));
+ // Navigating to a blank page is considered the same site.
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo, url_blank));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo_https, url_blank));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo_port, url_blank));
+
+ // Navigating from a blank site is not considered to be the same site.
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_blank, url_foo));
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_blank, url_foo_https));
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_blank, url_foo_port));
+
DrainMessageLoops();
}
// Test to ensure that there is only one SiteInstance per site in a given
// BrowsingInstance, when process-per-site is not in use.
TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
- ASSERT_FALSE(CommandLine::ForCurrentProcess()->HasSwitch(
+ ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kProcessPerSite));
int delete_counter = 0;
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
@@ -468,7 +475,7 @@ TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
// Test to ensure that there is only one RenderProcessHost per site for an
// entire BrowserContext, if process-per-site is in use.
TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInBrowserContext) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kProcessPerSite);
int delete_counter = 0;
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
@@ -557,11 +564,20 @@ static SiteInstanceImpl* CreateSiteInstance(BrowserContext* browser_context,
// Test to ensure that pages that require certain privileges are grouped
// in processes with similar pages.
TEST_F(SiteInstanceTest, ProcessSharingByType) {
- // This test shouldn't run with --site-per-process mode, since it doesn't
- // allow render process reuse, which this test explicitly exercises.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
+ // This test shouldn't run with --site-per-process or
+ // --enable-strict-site-isolation modes, since they don't allow render
+ // process reuse, which this test explicitly exercises.
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kSitePerProcess) ||
+ command_line.HasSwitch(switches::kEnableStrictSiteIsolation))
return;
+ // On Android by default the number of renderer hosts is unlimited and process
+ // sharing doesn't happen. We set the override so that the test can run
+ // everywhere.
+ RenderProcessHost::SetMaxRendererProcessCount(kMaxRendererProcessCount);
+
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -607,6 +623,9 @@ TEST_F(SiteInstanceTest, ProcessSharingByType) {
}
DrainMessageLoops();
+
+ // Disable the process limit override.
+ RenderProcessHost::SetMaxRendererProcessCount(0u);
}
// Test to ensure that HasWrongProcessForURL behaves properly for different
@@ -671,7 +690,7 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
// Test to ensure that HasWrongProcessForURL behaves properly even when
// --site-per-process is used (http://crbug.com/160671).
TEST_F(SiteInstanceTest, HasWrongProcessForURLInSitePerProcess) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kSitePerProcess);
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
@@ -745,7 +764,7 @@ TEST_F(SiteInstanceTest, ProcessPerSiteWithWrongBindings) {
// Test that we do not register processes with empty sites for process-per-site
// mode.
TEST_F(SiteInstanceTest, NoProcessPerSiteForEmptySite) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kProcessPerSite);
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
scoped_ptr<RenderProcessHost> host;
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 3adb455acc2..145a24989e3 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/site_per_process_browsertest.h"
+
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -16,13 +19,13 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/test_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
-#include "url/gurl.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
namespace content {
@@ -31,38 +34,28 @@ class SitePerProcessWebContentsObserver: public WebContentsObserver {
explicit SitePerProcessWebContentsObserver(WebContents* web_contents)
: WebContentsObserver(web_contents),
navigation_succeeded_(false) {}
- virtual ~SitePerProcessWebContentsObserver() {}
+ ~SitePerProcessWebContentsObserver() override {}
- virtual void DidStartProvisionalLoadForFrame(
- int64 frame_id,
- int64 parent_frame_id,
- bool is_main_frame,
- const GURL& validated_url,
- bool is_error_page,
- bool is_iframe_srcdoc,
- RenderViewHost* render_view_host) OVERRIDE {
+ void DidStartProvisionalLoadForFrame(RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) override {
navigation_succeeded_ = false;
}
- virtual void DidFailProvisionalLoad(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ void DidFailProvisionalLoad(
+ RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) OVERRIDE {
+ const base::string16& error_description) override {
navigation_url_ = validated_url;
navigation_succeeded_ = false;
}
- virtual void DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ void DidCommitProvisionalLoadForFrame(
+ RenderFrameHost* render_frame_host,
const GURL& url,
- PageTransition transition_type,
- RenderViewHost* render_view_host) OVERRIDE{
+ ui::PageTransition transition_type) override {
navigation_url_ = url;
navigation_succeeded_ = true;
}
@@ -87,7 +80,7 @@ class RedirectNotificationObserver : public NotificationObserver {
// NotificationService::AllSources().
RedirectNotificationObserver(int notification_type,
const NotificationSource& source);
- virtual ~RedirectNotificationObserver();
+ ~RedirectNotificationObserver() override;
// Wait until the specified notification occurs. If the notification was
// emitted between the construction of this object and this call then it
@@ -105,9 +98,9 @@ class RedirectNotificationObserver : public NotificationObserver {
}
// NotificationObserver:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
private:
bool seen_;
@@ -158,53 +151,56 @@ void RedirectNotificationObserver::Observe(
running_ = false;
}
-class SitePerProcessBrowserTest : public ContentBrowserTest {
- public:
- SitePerProcessBrowserTest() {}
-
- protected:
- // Start at a data URL so each extra navigation creates a navigation entry.
- // (The first navigation will silently be classified as AUTO_SUBFRAME.)
- // TODO(creis): This won't be necessary when we can wait for LOAD_STOP.
- void StartFrameAtDataURL() {
- std::string data_url_script =
+//
+// SitePerProcessBrowserTest
+//
+
+SitePerProcessBrowserTest::SitePerProcessBrowserTest() {
+};
+
+void SitePerProcessBrowserTest::StartFrameAtDataURL() {
+ std::string data_url_script =
"var iframes = document.getElementById('test');iframes.src="
"'data:text/html,dataurl';";
- ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script));
- }
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script));
+}
- bool NavigateIframeToURL(Shell* window,
- const GURL& url,
- std::string iframe_id) {
- // TODO(creis): This should wait for LOAD_STOP, but cross-site subframe
- // navigations generate extra DidStartLoading and DidStopLoading messages.
- // Until we replace swappedout:// with frame proxies, we need to listen for
- // something else. For now, we trigger NEW_SUBFRAME navigations and listen
- // for commit.
- std::string script = base::StringPrintf(
- "setTimeout(\""
- "var iframes = document.getElementById('%s');iframes.src='%s';"
- "\",0)",
- iframe_id.c_str(), url.spec().c_str());
- WindowedNotificationObserver load_observer(
- NOTIFICATION_NAV_ENTRY_COMMITTED,
- Source<NavigationController>(
- &window->web_contents()->GetController()));
- bool result = ExecuteScript(window->web_contents(), script);
- load_observer.Wait();
- return result;
- }
+bool SitePerProcessBrowserTest::NavigateIframeToURL(Shell* window,
+ const GURL& url,
+ std::string iframe_id) {
+ // TODO(creis): This should wait for LOAD_STOP, but cross-site subframe
+ // navigations generate extra DidStartLoading and DidStopLoading messages.
+ // Until we replace swappedout:// with frame proxies, we need to listen for
+ // something else. For now, we trigger NEW_SUBFRAME navigations and listen
+ // for commit.
+ std::string script = base::StringPrintf(
+ "setTimeout(\""
+ "var iframes = document.getElementById('%s');iframes.src='%s';"
+ "\",0)",
+ iframe_id.c_str(), url.spec().c_str());
+ WindowedNotificationObserver load_observer(
+ NOTIFICATION_NAV_ENTRY_COMMITTED,
+ Source<NavigationController>(
+ &window->web_contents()->GetController()));
+ bool result = ExecuteScript(window->web_contents(), script);
+ load_observer.Wait();
+ return result;
+}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
- command_line->AppendSwitch(switches::kSitePerProcess);
- }
+void SitePerProcessBrowserTest::SetUpCommandLine(CommandLine* command_line) {
+ command_line->AppendSwitch(switches::kSitePerProcess);
};
-// Ensure that we can complete a cross-process subframe navigation.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
+void SitePerProcessBrowserTest::SetUpOnMainThread() {
host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(test_server()->Start());
- GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ SetupCrossSiteRedirector(embedded_test_server());
+}
+
+// Ensure that navigating subframes in --site-per-process mode works and the
+// correct documents are committed.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
NavigateToURL(shell(), main_url);
// It is safe to obtain the root frame tree node here, as it doesn't change.
@@ -216,7 +212,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
// Load same-site page into iframe.
FrameTreeNode* child = root->child_at(0);
- GURL http_url(test_server()->GetURL("files/title1.html"));
+ GURL http_url(embedded_test_server()->GetURL("/title1.html"));
NavigateFrameToURL(child, http_url);
EXPECT_EQ(http_url, observer.navigation_url());
EXPECT_TRUE(observer.navigation_succeeded());
@@ -233,20 +229,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
shell()->web_contents()->GetSiteInstance());
EXPECT_FALSE(proxy_to_parent);
- // These must stay in scope with replace_host.
- GURL::Replacements replace_host;
- std::string foo_com("foo.com");
-
// Load cross-site page into iframe.
- GURL cross_site_url(test_server()->GetURL("files/title2.html"));
- replace_host.SetHostStr(foo_com);
- cross_site_url = cross_site_url.ReplaceComponents(replace_host);
- NavigateFrameToURL(root->child_at(0), cross_site_url);
- EXPECT_EQ(cross_site_url, observer.navigation_url());
+ GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
+ NavigateFrameToURL(root->child_at(0), url);
+ // Verify that the navigation succeeded and the expected URL was loaded.
EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(url, observer.navigation_url());
// Ensure that we have created a new process for the subframe.
- ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(2U, root->child_count());
SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
RenderViewHost* rvh = child->current_frame_host()->render_view_host();
RenderProcessHost* rph = child->current_frame_host()->GetProcess();
@@ -269,17 +260,14 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
// Load another cross-site page into the same iframe.
- cross_site_url = test_server()->GetURL("files/title3.html");
- std::string bar_com("bar.com");
- replace_host.SetHostStr(bar_com);
- cross_site_url = cross_site_url.ReplaceComponents(replace_host);
- NavigateFrameToURL(root->child_at(0), cross_site_url);
- EXPECT_EQ(cross_site_url, observer.navigation_url());
+ url = embedded_test_server()->GetURL("bar.com", "/title3.html");
+ NavigateFrameToURL(root->child_at(0), url);
EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(url, observer.navigation_url());
// Check again that a new process is created and is different from the
// top level one and the previous one.
- ASSERT_EQ(1U, root->child_count());
+ ASSERT_EQ(2U, root->child_count());
child = root->child_at(0);
EXPECT_NE(shell()->web_contents()->GetRenderViewHost(),
child->current_frame_host()->render_view_host());
@@ -304,18 +292,66 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
proxy_to_parent->cross_process_frame_connector()->get_view_for_testing());
}
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateRemoteFrame) {
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+
+ SitePerProcessWebContentsObserver observer(shell()->web_contents());
+
+ // Load same-site page into iframe.
+ FrameTreeNode* child = root->child_at(0);
+ GURL http_url(embedded_test_server()->GetURL("/title1.html"));
+ NavigateFrameToURL(child, http_url);
+ EXPECT_EQ(http_url, observer.navigation_url());
+ EXPECT_TRUE(observer.navigation_succeeded());
+
+ // Load cross-site page into iframe.
+ GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
+ NavigateFrameToURL(root->child_at(0), url);
+ EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(url, observer.navigation_url());
+
+ // Ensure that we have created a new process for the subframe.
+ ASSERT_EQ(2U, root->child_count());
+ SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance();
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
+
+ // Emulate the main frame changing the src of the iframe such that it
+ // navigates cross-site.
+ url = embedded_test_server()->GetURL("bar.com", "/title3.html");
+ NavigateIframeToURL(shell(), url, "test");
+ EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(url, observer.navigation_url());
+
+ // Check again that a new process is created and is different from the
+ // top level one and the previous one.
+ ASSERT_EQ(2U, root->child_count());
+ child = root->child_at(0);
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(site_instance,
+ child->current_frame_host()->GetSiteInstance());
+
+ // Navigate back to the parent's origin and ensure we return to the
+ // parent's process.
+ NavigateFrameToURL(child, http_url);
+ EXPECT_EQ(http_url, observer.navigation_url());
+ EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+}
+
// Crash a subframe and ensures its children are cleared from the FrameTree.
// See http://crbug.com/338508.
+// TODO(creis): Disabled for flakiness; see http://crbug.com/405582.
// TODO(creis): Enable this on Android when we can kill the process there.
-#if defined(OS_ANDROID)
-#define MAYBE_CrashSubframe DISABLED_CrashSubframe
-#else
-#define MAYBE_CrashSubframe CrashSubframe
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrashSubframe) {
- host_resolver()->AddRule("*", "127.0.0.1");
- ASSERT_TRUE(test_server()->Start());
- GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DISABLED_CrashSubframe) {
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
NavigateToURL(shell(), main_url);
StartFrameAtDataURL();
@@ -325,10 +361,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrashSubframe) {
std::string foo_com("foo.com");
// Load cross-site page into iframe.
- GURL cross_site_url(test_server()->GetURL("files/title2.html"));
- replace_host.SetHostStr(foo_com);
- cross_site_url = cross_site_url.ReplaceComponents(replace_host);
- EXPECT_TRUE(NavigateIframeToURL(shell(), cross_site_url, "test"));
+ EXPECT_TRUE(NavigateIframeToURL(
+ shell(),
+ embedded_test_server()->GetURL("/cross-site/foo.com/title2.html"),
+ "test"));
// Check the subframe process.
FrameTreeNode* root =
@@ -337,7 +373,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrashSubframe) {
ASSERT_EQ(1U, root->child_count());
FrameTreeNode* child = root->child_at(0);
EXPECT_EQ(main_url, root->current_url());
- EXPECT_EQ(cross_site_url, child->current_url());
+ EXPECT_EQ("foo.com", child->current_url().host());
+ EXPECT_EQ("/title2.html", child->current_url().path());
+
+ EXPECT_TRUE(
+ child->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_TRUE(child->current_frame_host()->IsRenderFrameLive());
// Crash the subframe process.
RenderProcessHost* root_process = root->current_frame_host()->GetProcess();
@@ -355,6 +396,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CrashSubframe) {
EXPECT_EQ(main_url, root->current_url());
EXPECT_EQ(GURL(), child->current_url());
+ EXPECT_FALSE(
+ child->current_frame_host()->render_view_host()->IsRenderViewLive());
+ EXPECT_FALSE(child->current_frame_host()->IsRenderFrameLive());
+ EXPECT_FALSE(child->current_frame_host()->render_frame_created_);
+
// Now crash the top-level page to clear the child frame.
{
RenderProcessHostWatcher crash_observer(
@@ -577,4 +623,116 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
}
+// Ensure that when navigating a frame cross-process RenderFrameProxyHosts are
+// created in the FrameTree skipping the subtree of the navigating frame.
+//
+// Disabled on Mac due to flakiness on ASAN. http://crbug.com/425248
+#if defined(OS_MACOSX)
+#define MAYBE_ProxyCreationSkipsSubtree DISABLED_ProxyCreationSkipsSubtree
+#else
+#define MAYBE_ProxyCreationSkipsSubtree ProxyCreationSkipsSubtree
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_ProxyCreationSkipsSubtree) {
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+
+ EXPECT_TRUE(root->child_at(1) != NULL);
+ EXPECT_EQ(2U, root->child_at(1)->child_count());
+
+ {
+ // Load same-site page into iframe.
+ SitePerProcessWebContentsObserver observer(shell()->web_contents());
+ GURL http_url(embedded_test_server()->GetURL("/title1.html"));
+ NavigateFrameToURL(root->child_at(0), http_url);
+ EXPECT_EQ(http_url, observer.navigation_url());
+ EXPECT_TRUE(observer.navigation_succeeded());
+ RenderFrameProxyHost* proxy_to_parent =
+ root->child_at(0)->render_manager()->GetRenderFrameProxyHost(
+ shell()->web_contents()->GetSiteInstance());
+ EXPECT_FALSE(proxy_to_parent);
+ }
+
+ // Create the cross-site URL to navigate to.
+ GURL cross_site_url =
+ embedded_test_server()->GetURL("foo.com", "/frame_tree/1-1.html");
+
+ // Load cross-site page into the second iframe without waiting for the
+ // navigation to complete. Once LoadURLWithParams returns, we would expect
+ // proxies to have been created in the frame tree, but children of the
+ // navigating frame to still be present. The reason is that we don't run the
+ // message loop, so no IPCs that alter the frame tree can be processed.
+ FrameTreeNode* child = root->child_at(1);
+ SiteInstance* site = NULL;
+ {
+ SitePerProcessWebContentsObserver observer(shell()->web_contents());
+ TestFrameNavigationObserver navigation_observer(child);
+ NavigationController::LoadURLParams params(cross_site_url);
+ params.transition_type = PageTransitionFromInt(ui::PAGE_TRANSITION_LINK);
+ params.frame_tree_node_id = child->frame_tree_node_id();
+ child->navigator()->GetController()->LoadURLWithParams(params);
+ EXPECT_TRUE(child->render_manager()->pending_frame_host());
+
+ site = child->render_manager()->pending_frame_host()->GetSiteInstance();
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site);
+
+ EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site));
+ EXPECT_TRUE(
+ root->child_at(0)->render_manager()->GetRenderFrameProxyHost(site));
+ EXPECT_FALSE(child->render_manager()->GetRenderFrameProxyHost(site));
+ for (size_t i = 0; i < child->child_count(); ++i) {
+ EXPECT_FALSE(
+ child->child_at(i)->render_manager()->GetRenderFrameProxyHost(site));
+ }
+ // Now that the verification is done, run the message loop and wait for the
+ // navigation to complete.
+ navigation_observer.Wait();
+ EXPECT_FALSE(child->render_manager()->pending_frame_host());
+ EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(cross_site_url, observer.navigation_url());
+ }
+
+ // Load another cross-site page into the same iframe.
+ cross_site_url = embedded_test_server()->GetURL("bar.com", "/title2.html");
+ {
+ // Perform the same checks as the first cross-site navigation, since
+ // there have been issues in subsequent cross-site navigations. Also ensure
+ // that the SiteInstance has properly changed.
+ // TODO(nasko): Once we have proper cleanup of resources, add code to
+ // verify that the intermediate SiteInstance/RenderFrameHost have been
+ // properly cleaned up.
+ SitePerProcessWebContentsObserver observer(shell()->web_contents());
+ TestFrameNavigationObserver navigation_observer(child);
+ NavigationController::LoadURLParams params(cross_site_url);
+ params.transition_type = PageTransitionFromInt(ui::PAGE_TRANSITION_LINK);
+ params.frame_tree_node_id = child->frame_tree_node_id();
+ child->navigator()->GetController()->LoadURLWithParams(params);
+ EXPECT_TRUE(child->render_manager()->pending_frame_host() != NULL);
+
+ SiteInstance* site2 =
+ child->render_manager()->pending_frame_host()->GetSiteInstance();
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site2);
+ EXPECT_NE(site, site2);
+
+ EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site2));
+ EXPECT_TRUE(
+ root->child_at(0)->render_manager()->GetRenderFrameProxyHost(site2));
+ EXPECT_FALSE(child->render_manager()->GetRenderFrameProxyHost(site2));
+ for (size_t i = 0; i < child->child_count(); ++i) {
+ EXPECT_FALSE(
+ child->child_at(i)->render_manager()->GetRenderFrameProxyHost(site2));
+ }
+
+ navigation_observer.Wait();
+ EXPECT_TRUE(observer.navigation_succeeded());
+ EXPECT_EQ(cross_site_url, observer.navigation_url());
+ EXPECT_EQ(0U, child->child_count());
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/site_per_process_browsertest.h b/chromium/content/browser/site_per_process_browsertest.h
new file mode 100644
index 00000000000..19dfc01c598
--- /dev/null
+++ b/chromium/content/browser/site_per_process_browsertest.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2014 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 "content/public/test/content_browser_test.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class Shell;
+
+class SitePerProcessBrowserTest : public ContentBrowserTest {
+ public:
+ SitePerProcessBrowserTest();
+
+ protected:
+ // Start at a data URL so each extra navigation creates a navigation entry.
+ // (The first navigation will silently be classified as AUTO_SUBFRAME.)
+ // TODO(creis): This won't be necessary when we can wait for LOAD_STOP.
+ void StartFrameAtDataURL();
+
+ bool NavigateIframeToURL(Shell* window,
+ const GURL& url,
+ std::string iframe_id);
+
+ void SetUpCommandLine(base::CommandLine* command_line) override;
+ void SetUpOnMainThread() override;
+};
+
+} // namespace content
diff --git a/chromium/content/browser/speech/audio_encoder.cc b/chromium/content/browser/speech/audio_encoder.cc
index db8e2015c1d..09b5dca287d 100644
--- a/chromium/content/browser/speech/audio_encoder.cc
+++ b/chromium/content/browser/speech/audio_encoder.cc
@@ -24,9 +24,9 @@ const int kFLACCompressionLevel = 0; // 0 for speed
class FLACEncoder : public AudioEncoder {
public:
FLACEncoder(int sampling_rate, int bits_per_sample);
- virtual ~FLACEncoder();
- virtual void Encode(const AudioChunk& raw_audio) OVERRIDE;
- virtual void Flush() OVERRIDE;
+ ~FLACEncoder() override;
+ void Encode(const AudioChunk& raw_audio) override;
+ void Flush() override;
private:
static FLAC__StreamEncoderWriteStatus WriteCallback(
@@ -113,9 +113,9 @@ COMPILE_ASSERT(kMaxSpeexFrameLength <= 0xFF, invalidLength);
class SpeexEncoder : public AudioEncoder {
public:
explicit SpeexEncoder(int sampling_rate, int bits_per_sample);
- virtual ~SpeexEncoder();
- virtual void Encode(const AudioChunk& raw_audio) OVERRIDE;
- virtual void Flush() OVERRIDE {}
+ ~SpeexEncoder() override;
+ void Encode(const AudioChunk& raw_audio) override;
+ void Flush() override {}
private:
void* encoder_state_;
diff --git a/chromium/content/browser/speech/endpointer/endpointer_unittest.cc b/chromium/content/browser/speech/endpointer/endpointer_unittest.cc
index 306a5eeca28..807b6f68287 100644
--- a/chromium/content/browser/speech/endpointer/endpointer_unittest.cc
+++ b/chromium/content/browser/speech/endpointer/endpointer_unittest.cc
@@ -73,9 +73,7 @@ class EnergyEndpointerFrameProcessor : public FrameProcessor {
explicit EnergyEndpointerFrameProcessor(EnergyEndpointer* endpointer)
: endpointer_(endpointer) {}
- virtual EpStatus ProcessFrame(int64 time,
- int16* samples,
- int frame_size) OVERRIDE {
+ EpStatus ProcessFrame(int64 time, int16* samples, int frame_size) override {
endpointer_->ProcessAudioFrame(time, samples, kFrameSize, NULL);
int64 ep_time;
return endpointer_->Status(&ep_time);
@@ -118,9 +116,7 @@ class EndpointerFrameProcessor : public FrameProcessor {
explicit EndpointerFrameProcessor(Endpointer* endpointer)
: endpointer_(endpointer) {}
- virtual EpStatus ProcessFrame(int64 time,
- int16* samples,
- int frame_size) OVERRIDE {
+ EpStatus ProcessFrame(int64 time, int16* samples, int frame_size) override {
scoped_refptr<AudioChunk> frame(
new AudioChunk(reinterpret_cast<uint8*>(samples), kFrameSize * 2, 2));
endpointer_->ProcessAudio(*frame.get(), NULL);
diff --git a/chromium/content/browser/speech/google_one_shot_remote_engine.h b/chromium/content/browser/speech/google_one_shot_remote_engine.h
index b02766597b7..0e5b09f904e 100644
--- a/chromium/content/browser/speech/google_one_shot_remote_engine.h
+++ b/chromium/content/browser/speech/google_one_shot_remote_engine.h
@@ -33,19 +33,19 @@ class CONTENT_EXPORT GoogleOneShotRemoteEngine
static int url_fetcher_id_for_tests;
explicit GoogleOneShotRemoteEngine(net::URLRequestContextGetter* context);
- virtual ~GoogleOneShotRemoteEngine();
+ ~GoogleOneShotRemoteEngine() override;
// SpeechRecognitionEngine methods.
- virtual void SetConfig(const SpeechRecognitionEngineConfig& config) OVERRIDE;
- virtual void StartRecognition() OVERRIDE;
- virtual void EndRecognition() OVERRIDE;
- virtual void TakeAudioChunk(const AudioChunk& data) OVERRIDE;
- virtual void AudioChunksEnded() OVERRIDE;
- virtual bool IsRecognitionPending() const OVERRIDE;
- virtual int GetDesiredAudioChunkDurationMs() const OVERRIDE;
+ void SetConfig(const SpeechRecognitionEngineConfig& config) override;
+ void StartRecognition() override;
+ void EndRecognition() override;
+ void TakeAudioChunk(const AudioChunk& data) override;
+ void AudioChunksEnded() override;
+ bool IsRecognitionPending() const override;
+ int GetDesiredAudioChunkDurationMs() const override;
// net::URLFetcherDelegate methods.
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+ void OnURLFetchComplete(const net::URLFetcher* source) override;
private:
SpeechRecognitionEngineConfig config_;
diff --git a/chromium/content/browser/speech/google_one_shot_remote_engine_unittest.cc b/chromium/content/browser/speech/google_one_shot_remote_engine_unittest.cc
index a16329cadff..16950102a28 100644
--- a/chromium/content/browser/speech/google_one_shot_remote_engine_unittest.cc
+++ b/chromium/content/browser/speech/google_one_shot_remote_engine_unittest.cc
@@ -26,13 +26,13 @@ class GoogleOneShotRemoteEngineTest : public SpeechRecognitionEngineDelegate,
void CreateAndTestRequest(bool success, const std::string& http_response);
// SpeechRecognitionRequestDelegate methods.
- virtual void OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) OVERRIDE {
+ void OnSpeechRecognitionEngineResults(
+ const SpeechRecognitionResults& results) override {
results_ = results;
}
- virtual void OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) OVERRIDE {
+ void OnSpeechRecognitionEngineError(
+ const SpeechRecognitionError& error) override {
error_ = error.code;
}
diff --git a/chromium/content/browser/speech/google_streaming_remote_engine.cc b/chromium/content/browser/speech/google_streaming_remote_engine.cc
index f9e2e6ea04d..7fea0fa90a6 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine.cc
+++ b/chromium/content/browser/speech/google_streaming_remote_engine.cc
@@ -53,7 +53,7 @@ void DumpResponse(const std::string& response) {
DVLOG(1) << "RESULT #" << i << ":";
const proto::SpeechRecognitionResult& res = event.result(i);
if (res.has_final())
- DVLOG(1) << " FINAL:\t" << res.final();
+ DVLOG(1) << " final:\t" << res.final();
if (res.has_stability())
DVLOG(1) << " STABILITY:\t" << res.stability();
for (int j = 0; j < res.alternative_size(); ++j) {
diff --git a/chromium/content/browser/speech/google_streaming_remote_engine.h b/chromium/content/browser/speech/google_streaming_remote_engine.h
index 11afae00e6c..961ef0877db 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine.h
+++ b/chromium/content/browser/speech/google_streaming_remote_engine.h
@@ -57,21 +57,22 @@ class CONTENT_EXPORT GoogleStreamingRemoteEngine
static const int kDownstreamUrlFetcherIdForTesting;
explicit GoogleStreamingRemoteEngine(net::URLRequestContextGetter* context);
- virtual ~GoogleStreamingRemoteEngine();
+ ~GoogleStreamingRemoteEngine() override;
// SpeechRecognitionEngine methods.
- virtual void SetConfig(const SpeechRecognitionEngineConfig& config) OVERRIDE;
- virtual void StartRecognition() OVERRIDE;
- virtual void EndRecognition() OVERRIDE;
- virtual void TakeAudioChunk(const AudioChunk& data) OVERRIDE;
- virtual void AudioChunksEnded() OVERRIDE;
- virtual bool IsRecognitionPending() const OVERRIDE;
- virtual int GetDesiredAudioChunkDurationMs() const OVERRIDE;
+ void SetConfig(const SpeechRecognitionEngineConfig& config) override;
+ void StartRecognition() override;
+ void EndRecognition() override;
+ void TakeAudioChunk(const AudioChunk& data) override;
+ void AudioChunksEnded() override;
+ bool IsRecognitionPending() const override;
+ int GetDesiredAudioChunkDurationMs() const override;
// net::URLFetcherDelegate methods.
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
- virtual void OnURLFetchDownloadProgress(const net::URLFetcher* source,
- int64 current, int64 total) OVERRIDE;
+ void OnURLFetchComplete(const net::URLFetcher* source) override;
+ void OnURLFetchDownloadProgress(const net::URLFetcher* source,
+ int64 current,
+ int64 total) override;
private:
// Response status codes from the speech recognition webservice.
diff --git a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
index ab703d7ac04..57947e61e5d 100644
--- a/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
+++ b/chromium/content/browser/speech/google_streaming_remote_engine_unittest.cc
@@ -42,18 +42,18 @@ class GoogleStreamingRemoteEngineTest : public SpeechRecognitionEngineDelegate,
void CreateAndTestRequest(bool success, const std::string& http_response);
// SpeechRecognitionRequestDelegate methods.
- virtual void OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) OVERRIDE {
+ void OnSpeechRecognitionEngineResults(
+ const SpeechRecognitionResults& results) override {
results_.push(results);
}
- virtual void OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) OVERRIDE {
+ void OnSpeechRecognitionEngineError(
+ const SpeechRecognitionError& error) override {
error_ = error.code;
}
// testing::Test methods.
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
+ void SetUp() override;
+ void TearDown() override;
protected:
enum DownstreamError {
diff --git a/chromium/content/browser/speech/speech_recognition_browsertest.cc b/chromium/content/browser/speech/speech_recognition_browsertest.cc
index 5871aa193f8..02671a4786f 100644
--- a/chromium/content/browser/speech/speech_recognition_browsertest.cc
+++ b/chromium/content/browser/speech/speech_recognition_browsertest.cc
@@ -44,29 +44,29 @@ class SpeechRecognitionBrowserTest :
};
// MockGoogleStreamingServerDelegate methods.
- virtual void OnClientConnected() OVERRIDE {
+ void OnClientConnected() override {
ASSERT_EQ(kTestAudioControllerOpened, streaming_server_state_);
streaming_server_state_ = kClientConnected;
}
- virtual void OnClientAudioUpload() OVERRIDE {
+ void OnClientAudioUpload() override {
if (streaming_server_state_ == kClientConnected)
streaming_server_state_ = kClientAudioUpload;
}
- virtual void OnClientAudioUploadComplete() OVERRIDE {
+ void OnClientAudioUploadComplete() override {
ASSERT_EQ(kTestAudioControllerClosed, streaming_server_state_);
streaming_server_state_ = kClientAudioUploadComplete;
}
- virtual void OnClientDisconnected() OVERRIDE {
+ void OnClientDisconnected() override {
ASSERT_EQ(kClientAudioUploadComplete, streaming_server_state_);
streaming_server_state_ = kClientDisconnected;
}
// media::TestAudioInputControllerDelegate methods.
- virtual void TestAudioControllerOpened(
- media::TestAudioInputController* controller) OVERRIDE {
+ void TestAudioControllerOpened(
+ media::TestAudioInputController* controller) override {
ASSERT_EQ(kIdle, streaming_server_state_);
streaming_server_state_ = kTestAudioControllerOpened;
const int capture_packet_interval_ms =
@@ -79,8 +79,8 @@ class SpeechRecognitionBrowserTest :
FeedAudioController(1000 /* ms */, /*noise=*/ false);
}
- virtual void TestAudioControllerClosed(
- media::TestAudioInputController* controller) OVERRIDE {
+ void TestAudioControllerClosed(
+ media::TestAudioInputController* controller) override {
ASSERT_EQ(kClientAudioUpload, streaming_server_state_);
streaming_server_state_ = kTestAudioControllerClosed;
mock_streaming_server_->MockGoogleStreamingServer::SimulateResult(
@@ -103,7 +103,7 @@ class SpeechRecognitionBrowserTest :
protected:
// ContentBrowserTest methods.
- virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ void SetUpInProcessBrowserTestFixture() override {
test_audio_input_controller_factory_.set_delegate(this);
media::AudioInputController::set_factory_for_testing(
&test_audio_input_controller_factory_);
@@ -111,18 +111,18 @@ class SpeechRecognitionBrowserTest :
streaming_server_state_ = kIdle;
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
ASSERT_TRUE(SpeechRecognitionManagerImpl::GetInstance());
SpeechRecognizerImpl::SetAudioManagerForTesting(
new media::MockAudioManager(BrowserThread::GetMessageLoopProxyForThread(
BrowserThread::IO)));
}
- virtual void TearDownOnMainThread() OVERRIDE {
+ void TearDownOnMainThread() override {
SpeechRecognizerImpl::SetAudioManagerForTesting(NULL);
}
- virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
+ void TearDownInProcessBrowserTestFixture() override {
test_audio_input_controller_factory_.set_delegate(NULL);
mock_streaming_server_.reset();
}
@@ -148,7 +148,7 @@ class SpeechRecognitionBrowserTest :
audio_bus->FromInterleaved(&audio_buffer.get()[0],
audio_bus->frames(),
audio_params.bits_per_sample() / 8);
- controller->event_handler()->OnData(controller, audio_bus.get());
+ controller->event_handler()->OnData(controller.get(), audio_bus.get());
}
void FeedAudioController(int duration_ms, bool feed_with_noise) {
@@ -188,7 +188,13 @@ class SpeechRecognitionBrowserTest :
// Simply loads the test page and checks if it was able to create a Speech
// Recognition object in JavaScript, to make sure the Web Speech API is enabled.
-IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, Precheck) {
+// http://crbug.com/396414
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#define MAYBE_Precheck DISABLED_Precheck
+#else
+#define MAYBE_Precheck Precheck
+#endif
+IN_PROC_BROWSER_TEST_F(SpeechRecognitionBrowserTest, MAYBE_Precheck) {
NavigateToURLBlockUntilNavigationsComplete(
shell(), GetTestUrlFromFragment("precheck"), 2);
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
index 05a24527efe..f920c51e779 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -42,6 +42,10 @@ SpeechRecognitionDispatcherHost::AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
+void SpeechRecognitionDispatcherHost::OnDestruct() const {
+ BrowserThread::DeleteOnIOThread::Destruct(this);
+}
+
bool SpeechRecognitionDispatcherHost::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
@@ -88,6 +92,12 @@ void SpeechRecognitionDispatcherHost::OnStartRequest(
int embedder_render_view_id = MSG_ROUTING_NONE;
RenderViewHostImpl* render_view_host =
RenderViewHostImpl::FromID(render_process_id_, params.render_view_id);
+ if (!render_view_host) {
+ // RVH can be null if the tab was closed while continuous mode speech
+ // recognition was running. This seems to happen on mac.
+ LOG(WARNING) << "SRDH::OnStartRequest, RenderViewHost does not exist";
+ return;
+ }
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
WebContents::FromRenderViewHost(render_view_host));
BrowserPluginGuest* guest = web_contents->GetBrowserPluginGuest();
@@ -110,6 +120,12 @@ void SpeechRecognitionDispatcherHost::OnStartRequest(
SpeechRecognitionManagerImpl::GetInstance()->delegate()->
FilterProfanities(render_process_id_);
+ // TODO(miu): This is a hack to allow SpeechRecognition to operate with the
+ // MediaStreamManager, which partitions requests per RenderFrame, not per
+ // RenderView. http://crbug.com/390749
+ const int params_render_frame_id = render_view_host ?
+ render_view_host->GetMainFrame()->GetRoutingID() : MSG_ROUTING_NONE;
+
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -118,6 +134,7 @@ void SpeechRecognitionDispatcherHost::OnStartRequest(
embedder_render_process_id,
embedder_render_view_id,
input_params,
+ params_render_frame_id,
filter_profanities));
}
@@ -125,11 +142,13 @@ void SpeechRecognitionDispatcherHost::OnStartRequestOnIO(
int embedder_render_process_id,
int embedder_render_view_id,
const SpeechRecognitionHostMsg_StartRequest_Params& params,
+ int params_render_frame_id,
bool filter_profanities) {
SpeechRecognitionSessionContext context;
context.context_name = params.origin_url;
context.render_process_id = render_process_id_;
context.render_view_id = params.render_view_id;
+ context.render_frame_id = params_render_frame_id;
context.embedder_render_process_id = embedder_render_process_id;
context.embedder_render_view_id = embedder_render_view_id;
if (embedder_render_process_id)
diff --git a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
index 72e7ee147d1..34b333207e8 100644
--- a/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
+++ b/chromium/content/browser/speech/speech_recognition_dispatcher_host.h
@@ -34,33 +34,34 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
base::WeakPtr<SpeechRecognitionDispatcherHost> AsWeakPtr();
// SpeechRecognitionEventListener methods.
- virtual void OnRecognitionStart(int session_id) OVERRIDE;
- virtual void OnAudioStart(int session_id) OVERRIDE;
- virtual void OnEnvironmentEstimationComplete(int session_id) OVERRIDE;
- virtual void OnSoundStart(int session_id) OVERRIDE;
- virtual void OnSoundEnd(int session_id) OVERRIDE;
- virtual void OnAudioEnd(int session_id) OVERRIDE;
- virtual void OnRecognitionEnd(int session_id) OVERRIDE;
- virtual void OnRecognitionResults(
- int session_id,
- const SpeechRecognitionResults& results) OVERRIDE;
- virtual void OnRecognitionError(
- int session_id,
- const SpeechRecognitionError& error) OVERRIDE;
- virtual void OnAudioLevelsChange(int session_id,
- float volume,
- float noise_volume) OVERRIDE;
+ void OnRecognitionStart(int session_id) override;
+ void OnAudioStart(int session_id) override;
+ void OnEnvironmentEstimationComplete(int session_id) override;
+ void OnSoundStart(int session_id) override;
+ void OnSoundEnd(int session_id) override;
+ void OnAudioEnd(int session_id) override;
+ void OnRecognitionEnd(int session_id) override;
+ void OnRecognitionResults(int session_id,
+ const SpeechRecognitionResults& results) override;
+ void OnRecognitionError(int session_id,
+ const SpeechRecognitionError& error) override;
+ void OnAudioLevelsChange(int session_id,
+ float volume,
+ float noise_volume) override;
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OverrideThreadForMessage(
- const IPC::Message& message,
- BrowserThread::ID* thread) OVERRIDE;
+ void OnDestruct() const override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OverrideThreadForMessage(const IPC::Message& message,
+ BrowserThread::ID* thread) override;
- virtual void OnChannelClosing() OVERRIDE;
+ void OnChannelClosing() override;
private:
- virtual ~SpeechRecognitionDispatcherHost();
+ friend class base::DeleteHelper<SpeechRecognitionDispatcherHost>;
+ friend class BrowserThread;
+
+ ~SpeechRecognitionDispatcherHost() override;
void OnStartRequest(
const SpeechRecognitionHostMsg_StartRequest_Params& params);
@@ -68,6 +69,7 @@ class CONTENT_EXPORT SpeechRecognitionDispatcherHost
int embedder_render_process_id,
int embedder_render_view_id,
const SpeechRecognitionHostMsg_StartRequest_Params& params,
+ int params_render_frame_id,
bool filter_profanities);
void OnAbortRequest(int render_view_id, int request_id);
void OnStopCaptureRequest(int render_view_id, int request_id);
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.cc b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
index 4b0827a6b62..1a054204c44 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.cc
@@ -196,7 +196,7 @@ void SpeechRecognitionManagerImpl::RecognitionAllowedCallback(int session_id,
SpeechRecognitionSessionContext& context = session->context;
context.label = media_stream_manager_->MakeMediaAccessRequest(
context.render_process_id,
- context.render_view_id,
+ context.render_frame_id,
context.request_id,
StreamOptions(true, false),
GURL(context.context_name),
diff --git a/chromium/content/browser/speech/speech_recognition_manager_impl.h b/chromium/content/browser/speech/speech_recognition_manager_impl.h
index 9a60e077437..9b8da39fc47 100644
--- a/chromium/content/browser/speech/speech_recognition_manager_impl.h
+++ b/chromium/content/browser/speech/speech_recognition_manager_impl.h
@@ -58,39 +58,39 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
static SpeechRecognitionManagerImpl* GetInstance();
// SpeechRecognitionManager implementation.
- virtual int CreateSession(
- const SpeechRecognitionSessionConfig& config) OVERRIDE;
- virtual void StartSession(int session_id) OVERRIDE;
- virtual void AbortSession(int session_id) OVERRIDE;
- virtual void AbortAllSessionsForRenderProcess(int render_process_id) OVERRIDE;
- virtual void AbortAllSessionsForRenderView(int render_process_id,
- int render_view_id) OVERRIDE;
- virtual void StopAudioCaptureForSession(int session_id) OVERRIDE;
- virtual const SpeechRecognitionSessionConfig& GetSessionConfig(
- int session_id) const OVERRIDE;
- virtual SpeechRecognitionSessionContext GetSessionContext(
- int session_id) const OVERRIDE;
- virtual int GetSession(int render_process_id,
- int render_view_id,
- int request_id) const OVERRIDE;
- virtual bool HasAudioInputDevices() OVERRIDE;
- virtual base::string16 GetAudioInputDeviceModel() OVERRIDE;
- virtual void ShowAudioInputSettings() OVERRIDE;
+ int CreateSession(const SpeechRecognitionSessionConfig& config) override;
+ void StartSession(int session_id) override;
+ void AbortSession(int session_id) override;
+ void AbortAllSessionsForRenderProcess(int render_process_id) override;
+ void AbortAllSessionsForRenderView(int render_process_id,
+ int render_view_id) override;
+ void StopAudioCaptureForSession(int session_id) override;
+ const SpeechRecognitionSessionConfig& GetSessionConfig(
+ int session_id) const override;
+ SpeechRecognitionSessionContext GetSessionContext(
+ int session_id) const override;
+ int GetSession(int render_process_id,
+ int render_view_id,
+ int request_id) const override;
+ bool HasAudioInputDevices() override;
+ base::string16 GetAudioInputDeviceModel() override;
+ void ShowAudioInputSettings() override;
// SpeechRecognitionEventListener methods.
- virtual void OnRecognitionStart(int session_id) OVERRIDE;
- virtual void OnAudioStart(int session_id) OVERRIDE;
- virtual void OnEnvironmentEstimationComplete(int session_id) OVERRIDE;
- virtual void OnSoundStart(int session_id) OVERRIDE;
- virtual void OnSoundEnd(int session_id) OVERRIDE;
- virtual void OnAudioEnd(int session_id) OVERRIDE;
- virtual void OnRecognitionEnd(int session_id) OVERRIDE;
- virtual void OnRecognitionResults(
- int session_id, const SpeechRecognitionResults& result) OVERRIDE;
- virtual void OnRecognitionError(
- int session_id, const SpeechRecognitionError& error) OVERRIDE;
- virtual void OnAudioLevelsChange(int session_id, float volume,
- float noise_volume) OVERRIDE;
+ void OnRecognitionStart(int session_id) override;
+ void OnAudioStart(int session_id) override;
+ void OnEnvironmentEstimationComplete(int session_id) override;
+ void OnSoundStart(int session_id) override;
+ void OnSoundEnd(int session_id) override;
+ void OnAudioEnd(int session_id) override;
+ void OnRecognitionEnd(int session_id) override;
+ void OnRecognitionResults(int session_id,
+ const SpeechRecognitionResults& result) override;
+ void OnRecognitionError(int session_id,
+ const SpeechRecognitionError& error) override;
+ void OnAudioLevelsChange(int session_id,
+ float volume,
+ float noise_volume) override;
SpeechRecognitionManagerDelegate* delegate() const { return delegate_.get(); }
@@ -101,7 +101,7 @@ class CONTENT_EXPORT SpeechRecognitionManagerImpl :
friend struct base::DefaultDeleter<SpeechRecognitionManagerImpl>;
SpeechRecognitionManagerImpl(media::AudioManager* audio_manager,
MediaStreamManager* media_stream_manager);
- virtual ~SpeechRecognitionManagerImpl();
+ ~SpeechRecognitionManagerImpl() override;
private:
// Data types for the internal Finite State Machine (FSM).
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index e49d30139aa..f6fb3900a5e 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/time/time.h"
#include "content/browser/browser_main_loop.h"
+#include "content/browser/media/media_internals.h"
#include "content/browser/speech/audio_buffer.h"
#include "content/browser/speech/google_one_shot_remote_engine.h"
#include "content/public/browser/speech_recognition_event_listener.h"
@@ -35,7 +36,7 @@ class SpeechRecognizerImpl::OnDataConverter
public:
OnDataConverter(const AudioParameters& input_params,
const AudioParameters& output_params);
- virtual ~OnDataConverter();
+ ~OnDataConverter() override;
// Converts input audio |data| bus into an AudioChunk where the input format
// is given by |input_parameters_| and the output format by
@@ -44,8 +45,7 @@ class SpeechRecognizerImpl::OnDataConverter
private:
// media::AudioConverter::InputCallback implementation.
- virtual double ProvideInput(AudioBus* dest,
- base::TimeDelta buffer_delay) OVERRIDE;
+ double ProvideInput(AudioBus* dest, base::TimeDelta buffer_delay) override;
// Handles resampling, buffering, and channel mixing between input and output
// parameters.
@@ -178,6 +178,8 @@ SpeechRecognizerImpl::SpeechRecognizerImpl(
: SpeechRecognizer(listener, session_id),
recognition_engine_(engine),
endpointer_(kAudioSampleRate),
+ audio_log_(MediaInternals::GetInstance()->CreateAudioLog(
+ media::AudioLogFactory::AUDIO_INPUT_CONTROLLER)),
is_dispatching_event_(false),
provisional_results_(provisional_results),
state_(STATE_IDLE) {
@@ -258,6 +260,7 @@ SpeechRecognizerImpl::~SpeechRecognizerImpl() {
if (audio_controller_.get()) {
audio_controller_->Close(
base::Bind(&KeepAudioControllerRefcountedForDtor, audio_controller_));
+ audio_log_->OnClosed(0);
}
}
@@ -552,7 +555,6 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
input_parameters.Reset(in_params.format(),
in_params.channel_layout(),
in_params.channels(),
- in_params.input_channels(),
in_params.sample_rate(),
in_params.bits_per_sample(),
frames_per_buffer);
@@ -570,12 +572,15 @@ SpeechRecognizerImpl::StartRecording(const FSMEventArgs&) {
return Abort(SpeechRecognitionError(SPEECH_RECOGNITION_ERROR_AUDIO));
}
+ audio_log_->OnCreated(0, input_parameters, device_id_);
+
// The endpointer needs to estimate the environment/background noise before
// starting to treat the audio as user input. We wait in the state
// ESTIMATING_ENVIRONMENT until such interval has elapsed before switching
// to user input mode.
endpointer_.SetEnvironmentEstimationMode();
audio_controller_->Record();
+ audio_log_->OnStarted(0);
return STATE_STARTING;
}
@@ -772,6 +777,7 @@ void SpeechRecognizerImpl::CloseAudioControllerAsynchronously() {
audio_controller_->Close(base::Bind(&SpeechRecognizerImpl::OnAudioClosed,
this, audio_controller_));
audio_controller_ = NULL; // The controller is still refcounted by Bind.
+ audio_log_->OnClosed(0);
}
int SpeechRecognizerImpl::GetElapsedTimeMs() const {
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index 55e07f04ef6..3a26d335cac 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -13,6 +13,7 @@
#include "content/public/common/speech_recognition_error.h"
#include "content/public/common/speech_recognition_result.h"
#include "media/audio/audio_input_controller.h"
+#include "media/audio/audio_logging.h"
#include "net/url_request/url_request_context_getter.h"
namespace media {
@@ -46,11 +47,11 @@ class CONTENT_EXPORT SpeechRecognizerImpl
bool provisional_results,
SpeechRecognitionEngine* engine);
- virtual void StartRecognition(const std::string& device_id) OVERRIDE;
- virtual void AbortRecognition() OVERRIDE;
- virtual void StopAudioCapture() OVERRIDE;
- virtual bool IsActive() const OVERRIDE;
- virtual bool IsCapturingAudio() const OVERRIDE;
+ void StartRecognition(const std::string& device_id) override;
+ void AbortRecognition() override;
+ void StopAudioCapture() override;
+ bool IsActive() const override;
+ bool IsCapturingAudio() const override;
const SpeechRecognitionEngine& recognition_engine() const;
private:
@@ -88,7 +89,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
SpeechRecognitionError engine_error;
};
- virtual ~SpeechRecognizerImpl();
+ ~SpeechRecognizerImpl() override;
// Entry point for pushing any new external event into the recognizer FSM.
void DispatchEvent(const FSMEventArgs& event_args);
@@ -128,26 +129,27 @@ class CONTENT_EXPORT SpeechRecognizerImpl
void OnAudioClosed(media::AudioInputController*);
// AudioInputController::EventHandler methods.
- virtual void OnCreated(media::AudioInputController* controller) OVERRIDE {}
- virtual void OnRecording(media::AudioInputController* controller) OVERRIDE {}
- virtual void OnError(media::AudioInputController* controller,
- media::AudioInputController::ErrorCode error_code) OVERRIDE;
- virtual void OnData(media::AudioInputController* controller,
- const media::AudioBus* data) OVERRIDE;
- virtual void OnLog(media::AudioInputController* controller,
- const std::string& message) OVERRIDE {}
+ void OnCreated(media::AudioInputController* controller) override {}
+ void OnRecording(media::AudioInputController* controller) override {}
+ void OnError(media::AudioInputController* controller,
+ media::AudioInputController::ErrorCode error_code) override;
+ void OnData(media::AudioInputController* controller,
+ const media::AudioBus* data) override;
+ void OnLog(media::AudioInputController* controller,
+ const std::string& message) override {}
// SpeechRecognitionEngineDelegate methods.
- virtual void OnSpeechRecognitionEngineResults(
- const SpeechRecognitionResults& results) OVERRIDE;
- virtual void OnSpeechRecognitionEngineError(
- const SpeechRecognitionError& error) OVERRIDE;
+ void OnSpeechRecognitionEngineResults(
+ const SpeechRecognitionResults& results) override;
+ void OnSpeechRecognitionEngineError(
+ const SpeechRecognitionError& error) override;
static media::AudioManager* audio_manager_for_tests_;
scoped_ptr<SpeechRecognitionEngine> recognition_engine_;
Endpointer endpointer_;
scoped_refptr<media::AudioInputController> audio_controller_;
+ scoped_ptr<media::AudioLog> audio_log_;
int num_samples_recorded_;
float audio_level_;
bool is_dispatching_event_;
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_android.h b/chromium/content/browser/speech/speech_recognizer_impl_android.h
index e6e7f09ec69..cdf0b4db6d8 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_android.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl_android.h
@@ -24,11 +24,11 @@ class CONTENT_EXPORT SpeechRecognizerImplAndroid : public SpeechRecognizer {
int session_id);
// SpeechRecognizer methods.
- virtual void StartRecognition(const std::string& device_id) OVERRIDE;
- virtual void AbortRecognition() OVERRIDE;
- virtual void StopAudioCapture() OVERRIDE;
- virtual bool IsActive() const OVERRIDE;
- virtual bool IsCapturingAudio() const OVERRIDE;
+ virtual void StartRecognition(const std::string& device_id) override;
+ virtual void AbortRecognition() override;
+ virtual void StopAudioCapture() override;
+ virtual bool IsActive() const override;
+ virtual bool IsCapturingAudio() const override;
// Called from Java methods via JNI.
void OnAudioStart(JNIEnv* env, jobject obj);
diff --git a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
index 13d5eba7dfc..7168fb64973 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -95,63 +95,64 @@ class SpeechRecognizerImplTest : public SpeechRecognitionEventListener,
}
// Overridden from SpeechRecognitionEventListener:
- virtual void OnAudioStart(int session_id) OVERRIDE {
+ void OnAudioStart(int session_id) override {
audio_started_ = true;
CheckEventsConsistency();
}
- virtual void OnAudioEnd(int session_id) OVERRIDE {
+ void OnAudioEnd(int session_id) override {
audio_ended_ = true;
CheckEventsConsistency();
}
- virtual void OnRecognitionResults(
- int session_id, const SpeechRecognitionResults& results) OVERRIDE {
+ void OnRecognitionResults(int session_id,
+ const SpeechRecognitionResults& results) override {
result_received_ = true;
}
- virtual void OnRecognitionError(
- int session_id, const SpeechRecognitionError& error) OVERRIDE {
+ void OnRecognitionError(int session_id,
+ const SpeechRecognitionError& error) override {
EXPECT_TRUE(recognition_started_);
EXPECT_FALSE(recognition_ended_);
error_ = error.code;
}
- virtual void OnAudioLevelsChange(int session_id, float volume,
- float noise_volume) OVERRIDE {
+ void OnAudioLevelsChange(int session_id,
+ float volume,
+ float noise_volume) override {
volume_ = volume;
noise_volume_ = noise_volume;
}
- virtual void OnRecognitionEnd(int session_id) OVERRIDE {
+ void OnRecognitionEnd(int session_id) override {
recognition_ended_ = true;
CheckEventsConsistency();
}
- virtual void OnRecognitionStart(int session_id) OVERRIDE {
+ void OnRecognitionStart(int session_id) override {
recognition_started_ = true;
CheckEventsConsistency();
}
- virtual void OnEnvironmentEstimationComplete(int session_id) OVERRIDE {}
+ void OnEnvironmentEstimationComplete(int session_id) override {}
- virtual void OnSoundStart(int session_id) OVERRIDE {
+ void OnSoundStart(int session_id) override {
sound_started_ = true;
CheckEventsConsistency();
}
- virtual void OnSoundEnd(int session_id) OVERRIDE {
+ void OnSoundEnd(int session_id) override {
sound_ended_ = true;
CheckEventsConsistency();
}
// testing::Test methods.
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
AudioInputController::set_factory_for_testing(
&audio_input_controller_factory_);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
AudioInputController::set_factory_for_testing(NULL);
}
diff --git a/chromium/content/browser/ssl/ssl_cert_error_handler.cc b/chromium/content/browser/ssl/ssl_cert_error_handler.cc
index a69e993380a..9ec7885d58d 100644
--- a/chromium/content/browser/ssl/ssl_cert_error_handler.cc
+++ b/chromium/content/browser/ssl/ssl_cert_error_handler.cc
@@ -13,14 +13,16 @@ namespace content {
SSLCertErrorHandler::SSLCertErrorHandler(
const base::WeakPtr<Delegate>& delegate,
- const GlobalRequestID& id,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
const GURL& url,
int render_process_id,
int render_frame_id,
const net::SSLInfo& ssl_info,
bool fatal)
- : SSLErrorHandler(delegate, id, resource_type, url, render_process_id,
+ : SSLErrorHandler(delegate,
+ resource_type,
+ url,
+ render_process_id,
render_frame_id),
ssl_info_(ssl_info),
cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)),
diff --git a/chromium/content/browser/ssl/ssl_cert_error_handler.h b/chromium/content/browser/ssl/ssl_cert_error_handler.h
index 6946f42921f..e3c4378f167 100644
--- a/chromium/content/browser/ssl/ssl_cert_error_handler.h
+++ b/chromium/content/browser/ssl/ssl_cert_error_handler.h
@@ -20,15 +20,14 @@ class SSLCertErrorHandler : public SSLErrorHandler {
public:
// Construct on the IO thread.
SSLCertErrorHandler(const base::WeakPtr<Delegate>& delegate,
- const GlobalRequestID& id,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
const GURL& url,
int render_process_id,
int render_frame_id,
const net::SSLInfo& ssl_info,
bool fatal);
- virtual SSLCertErrorHandler* AsSSLCertErrorHandler() OVERRIDE;
+ SSLCertErrorHandler* AsSSLCertErrorHandler() override;
// These accessors are available on either thread
const net::SSLInfo& ssl_info() const { return ssl_info_; }
@@ -37,11 +36,11 @@ class SSLCertErrorHandler : public SSLErrorHandler {
protected:
// SSLErrorHandler methods
- virtual void OnDispatchFailed() OVERRIDE;
- virtual void OnDispatched() OVERRIDE;
+ void OnDispatchFailed() override;
+ void OnDispatched() override;
private:
- virtual ~SSLCertErrorHandler();
+ ~SSLCertErrorHandler() override;
// These read-only members may be accessed on any thread.
const net::SSLInfo ssl_info_;
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.cc b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
index b7fe9f0a7fa..8cab2c75229 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.cc
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
@@ -5,77 +5,84 @@
#include "content/browser/ssl/ssl_client_auth_handler.h"
#include "base/bind.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "base/logging.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "net/cert/x509_certificate.h"
-#include "net/http/http_transaction_factory.h"
#include "net/ssl/client_cert_store.h"
#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context.h"
namespace content {
+namespace {
+
+typedef base::Callback<void(net::X509Certificate*)> CertificateCallback;
+
+void CertificateSelectedOnUIThread(
+ const CertificateCallback& io_thread_callback,
+ net::X509Certificate* cert) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(io_thread_callback, make_scoped_refptr(cert)));
+}
+
+void SelectCertificateOnUIThread(
+ int render_process_host_id,
+ int render_frame_host_id,
+ net::SSLCertRequestInfo* cert_request_info,
+ const CertificateCallback& io_thread_callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ GetContentClient()->browser()->SelectClientCertificate(
+ render_process_host_id, render_frame_host_id, cert_request_info,
+ base::Bind(&CertificateSelectedOnUIThread, io_thread_callback));
+}
+
+} // namespace
+
SSLClientAuthHandler::SSLClientAuthHandler(
scoped_ptr<net::ClientCertStore> client_cert_store,
net::URLRequest* request,
- net::SSLCertRequestInfo* cert_request_info)
+ net::SSLCertRequestInfo* cert_request_info,
+ const SSLClientAuthHandler::CertificateCallback& callback)
: request_(request),
- http_network_session_(
- request_->context()->http_transaction_factory()->GetSession()),
cert_request_info_(cert_request_info),
- client_cert_store_(client_cert_store.Pass()) {
+ client_cert_store_(client_cert_store.Pass()),
+ callback_(callback),
+ weak_factory_(this) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
SSLClientAuthHandler::~SSLClientAuthHandler() {
- // If we were simply dropped, then act as if we selected no certificate.
- DoCertificateSelected(NULL);
-}
-
-void SSLClientAuthHandler::OnRequestCancelled() {
- request_ = NULL;
}
void SSLClientAuthHandler::SelectCertificate() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(request_);
if (client_cert_store_) {
client_cert_store_->GetClientCerts(
*cert_request_info_,
&cert_request_info_->client_certs,
- base::Bind(&SSLClientAuthHandler::DidGetClientCerts, this));
+ base::Bind(&SSLClientAuthHandler::DidGetClientCerts,
+ weak_factory_.GetWeakPtr()));
} else {
DidGetClientCerts();
}
}
-void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- VLOG(1) << this << " CertificateSelected " << cert;
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(
- &SSLClientAuthHandler::DoCertificateSelected, this,
- make_scoped_refptr(cert)));
-}
-
void SSLClientAuthHandler::DidGetClientCerts() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // Request may have cancelled while we were getting client certs.
- if (!request_)
- return;
// Note that if |client_cert_store_| is NULL, we intentionally fall through to
// DoCertificateSelected. This is for platforms where the client cert matching
- // is not performed by Chrome, the platform can handle the cert matching
- // before showing the dialog.
+ // is not performed by Chrome. Those platforms handle the cert matching before
+ // showing the dialog.
if (client_cert_store_ && cert_request_info_->client_certs.empty()) {
// No need to query the user if there are no certs to choose from.
- DoCertificateSelected(NULL);
+ CertificateSelected(NULL);
return;
}
@@ -83,43 +90,27 @@ void SSLClientAuthHandler::DidGetClientCerts() {
int render_frame_host_id;
if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame(
&render_process_host_id,
- &render_frame_host_id))
+ &render_frame_host_id)) {
NOTREACHED();
+ CertificateSelected(NULL);
+ return;
+ }
- // If the RVH does not exist by the time this task gets run, then the task
- // will be dropped and the scoped_refptr to SSLClientAuthHandler will go
- // away, so we do not leak anything. The destructor takes care of ensuring
- // the net::URLRequest always gets a response.
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(
- &SSLClientAuthHandler::DoSelectCertificate, this,
- render_process_host_id, render_frame_host_id));
+ base::Bind(&SelectCertificateOnUIThread,
+ render_process_host_id, render_frame_host_id,
+ cert_request_info_,
+ base::Bind(&SSLClientAuthHandler::CertificateSelected,
+ weak_factory_.GetWeakPtr())));
}
-void SSLClientAuthHandler::DoCertificateSelected(net::X509Certificate* cert) {
+void SSLClientAuthHandler::CertificateSelected(net::X509Certificate* cert) {
VLOG(1) << this << " DoCertificateSelected " << cert;
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- // request_ could have been NULLed if the request was cancelled while the
- // user was choosing a cert, or because we have already responded to the
- // certificate.
- if (request_) {
- request_->ContinueWithCertificate(cert);
-
- ResourceDispatcherHostImpl::Get()->
- ClearSSLClientAuthHandlerForRequest(request_);
- request_ = NULL;
- }
-}
-void SSLClientAuthHandler::DoSelectCertificate(
- int render_process_host_id, int render_frame_host_id) {
- GetContentClient()->browser()->SelectClientCertificate(
- render_process_host_id,
- render_frame_host_id,
- http_network_session_,
- cert_request_info_.get(),
- base::Bind(&SSLClientAuthHandler::CertificateSelected, this));
+ callback_.Run(cert);
+ // |this| may be deleted at this point.
}
} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.h b/chromium/content/browser/ssl/ssl_client_auth_handler.h
index b848d54d7ff..f95e65d71bb 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.h
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.h
@@ -6,79 +6,57 @@
#define CONTENT_BROWSER_SSL_SSL_CLIENT_AUTH_HANDLER_H_
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner_helpers.h"
-#include "content/common/content_export.h"
+#include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_thread.h"
#include "net/ssl/ssl_cert_request_info.h"
namespace net {
class ClientCertStore;
-class HttpNetworkSession;
class URLRequest;
class X509Certificate;
} // namespace net
namespace content {
-class ResourceContext;
-
// This class handles the approval and selection of a certificate for SSL client
-// authentication by the user.
-// It is self-owned and deletes itself when the UI reports the user selection or
-// when the net::URLRequest is cancelled.
-class CONTENT_EXPORT SSLClientAuthHandler
- : public base::RefCountedThreadSafe<
- SSLClientAuthHandler, BrowserThread::DeleteOnIOThread> {
+// authentication by the user. Should only be used on the IO thread. If the
+// SSLClientAuthHandler is destroyed before the certificate is selected, the
+// selection is canceled and the callback never called.
+class SSLClientAuthHandler {
public:
+ typedef base::Callback<void(net::X509Certificate*)> CertificateCallback;
+
SSLClientAuthHandler(scoped_ptr<net::ClientCertStore> client_cert_store,
net::URLRequest* request,
- net::SSLCertRequestInfo* cert_request_info);
+ net::SSLCertRequestInfo* cert_request_info,
+ const CertificateCallback& callback);
+ ~SSLClientAuthHandler();
// Selects a certificate and resumes the URL request with that certificate.
- // Should only be called on the IO thread.
void SelectCertificate();
- // Invoked when the request associated with this handler is cancelled.
- // Should only be called on the IO thread.
- void OnRequestCancelled();
-
- // Calls DoCertificateSelected on the I/O thread.
- // Called on the UI thread after the user has made a selection (which may
- // be long after DoSelectCertificate returns, if the UI is modeless/async.)
- void CertificateSelected(net::X509Certificate* cert);
-
- protected:
- virtual ~SSLClientAuthHandler();
-
private:
- friend class base::RefCountedThreadSafe<
- SSLClientAuthHandler, BrowserThread::DeleteOnIOThread>;
- friend class BrowserThread;
- friend class base::DeleteHelper<SSLClientAuthHandler>;
-
// Called when ClientCertStore is done retrieving the cert list.
void DidGetClientCerts();
- // Notifies that the user has selected a cert.
- // Called on the IO thread.
- void DoCertificateSelected(net::X509Certificate* cert);
-
- // Selects a client certificate on the UI thread.
- void DoSelectCertificate(int render_process_host_id,
- int render_frame_host_id);
+ // Called when the user has selected a cert.
+ void CertificateSelected(net::X509Certificate* cert);
// The net::URLRequest that triggered this client auth.
net::URLRequest* request_;
- // The HttpNetworkSession |request_| is associated with.
- const net::HttpNetworkSession* http_network_session_;
-
// The certs to choose from.
scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
scoped_ptr<net::ClientCertStore> client_cert_store_;
+ // The callback to call when the certificate is selected.
+ CertificateCallback callback_;
+
+ base::WeakPtrFactory<SSLClientAuthHandler> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(SSLClientAuthHandler);
};
diff --git a/chromium/content/browser/ssl/ssl_error_handler.cc b/chromium/content/browser/ssl/ssl_error_handler.cc
index 6d120a9e2fb..f8deb75e534 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.cc
+++ b/chromium/content/browser/ssl/ssl_error_handler.cc
@@ -19,13 +19,11 @@ using net::SSLInfo;
namespace content {
SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate,
- const GlobalRequestID& id,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
const GURL& url,
int render_process_id,
int render_frame_id)
: manager_(NULL),
- request_id_(id),
delegate_(delegate),
render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
@@ -133,7 +131,7 @@ void SSLErrorHandler::CompleteCancelRequest(int error) {
if (cert_error)
ssl_info = &cert_error->ssl_info();
if (delegate_.get())
- delegate_->CancelSSLRequest(request_id_, error, ssl_info);
+ delegate_->CancelSSLRequest(error, ssl_info);
request_has_been_notified_ = true;
// We're done with this object on the IO thread.
@@ -151,7 +149,7 @@ void SSLErrorHandler::CompleteContinueRequest() {
return;
if (delegate_.get())
- delegate_->ContinueSSLRequest(request_id_);
+ delegate_->ContinueSSLRequest();
request_has_been_notified_ = true;
// We're done with this object on the IO thread.
diff --git a/chromium/content/browser/ssl/ssl_error_handler.h b/chromium/content/browser/ssl/ssl_error_handler.h
index 87bc1da445e..26fc147c3f4 100644
--- a/chromium/content/browser/ssl/ssl_error_handler.h
+++ b/chromium/content/browser/ssl/ssl_error_handler.h
@@ -12,8 +12,8 @@
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
+#include "content/public/common/resource_type.h"
#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
namespace net {
class SSLInfo;
@@ -42,22 +42,18 @@ class SSLManager;
//
class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> {
public:
- // Delegate functions must be called from IO thread. All functions accept
- // |id| as the first argument. |id| is a copy of the second argument of
- // SSLManager::OnSSLCertificateError() and represents the request.
- // Finally, CancelSSLRequest() or ContinueSSLRequest() will be called after
+ // Delegate functions must be called from IO thread. Finally,
+ // CancelSSLRequest() or ContinueSSLRequest() will be called after
// SSLErrorHandler makes a decision on the SSL error.
class CONTENT_EXPORT Delegate {
public:
// Called when SSLErrorHandler decides to cancel the request because of
// the SSL error.
- virtual void CancelSSLRequest(const GlobalRequestID& id,
- int error,
- const net::SSLInfo* ssl_info) = 0;
+ virtual void CancelSSLRequest(int error, const net::SSLInfo* ssl_info) = 0;
// Called when SSLErrorHandler decides to continue the request despite the
// SSL error.
- virtual void ContinueSSLRequest(const GlobalRequestID& id) = 0;
+ virtual void ContinueSSLRequest() = 0;
protected:
virtual ~Delegate() {}
@@ -75,7 +71,7 @@ class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> {
const GURL& request_url() const { return request_url_; }
// Available on either thread.
- ResourceType::Type resource_type() const { return resource_type_; }
+ ResourceType resource_type() const { return resource_type_; }
// Cancels the associated net::URLRequest.
// This method can be called from OnDispatchFailed and OnDispatched.
@@ -108,8 +104,7 @@ class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> {
// Construct on the IO thread.
SSLErrorHandler(const base::WeakPtr<Delegate>& delegate,
- const GlobalRequestID& id,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
const GURL& url,
int render_process_id,
int render_frame_id);
@@ -125,10 +120,6 @@ class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> {
// Should only be accessed on the UI thread.
SSLManager* manager_; // Our manager.
- // The id of the request associated with this object.
- // Should only be accessed from the IO thread.
- GlobalRequestID request_id_;
-
// The delegate we are associated with.
base::WeakPtr<Delegate> delegate_;
@@ -158,7 +149,7 @@ class SSLErrorHandler : public base::RefCountedThreadSafe<SSLErrorHandler> {
// What kind of resource is associated with the requested that generated
// that error.
// This read-only member can be accessed on any thread.
- const ResourceType::Type resource_type_;
+ const ResourceType resource_type_;
// A flag to make sure we notify the net::URLRequest exactly once.
// Should only be accessed on the IO thread
diff --git a/chromium/content/browser/ssl/ssl_host_state.cc b/chromium/content/browser/ssl/ssl_host_state.cc
deleted file mode 100644
index 06c600205fa..00000000000
--- a/chromium/content/browser/ssl/ssl_host_state.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/ssl/ssl_host_state.h"
-
-#include "base/logging.h"
-#include "base/lazy_instance.h"
-#include "content/public/browser/browser_context.h"
-
-const char kKeyName[] = "content_ssl_host_state";
-
-namespace content {
-
-SSLHostState* SSLHostState::GetFor(BrowserContext* context) {
- SSLHostState* rv = static_cast<SSLHostState*>(context->GetUserData(kKeyName));
- if (!rv) {
- rv = new SSLHostState();
- context->SetUserData(kKeyName, rv);
- }
- return rv;
-}
-
-SSLHostState::SSLHostState() {
-}
-
-SSLHostState::~SSLHostState() {
-}
-
-void SSLHostState::HostRanInsecureContent(const std::string& host, int pid) {
- DCHECK(CalledOnValidThread());
- ran_insecure_content_hosts_.insert(BrokenHostEntry(host, pid));
-}
-
-bool SSLHostState::DidHostRunInsecureContent(const std::string& host,
- int pid) const {
- DCHECK(CalledOnValidThread());
- return !!ran_insecure_content_hosts_.count(BrokenHostEntry(host, pid));
-}
-
-void SSLHostState::DenyCertForHost(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error) {
- DCHECK(CalledOnValidThread());
-
- cert_policy_for_host_[host].Deny(cert, error);
-}
-
-void SSLHostState::AllowCertForHost(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error) {
- DCHECK(CalledOnValidThread());
-
- cert_policy_for_host_[host].Allow(cert, error);
-}
-
-void SSLHostState::Clear() {
- DCHECK(CalledOnValidThread());
-
- cert_policy_for_host_.clear();
-}
-
-net::CertPolicy::Judgment SSLHostState::QueryPolicy(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error) {
- DCHECK(CalledOnValidThread());
-
- return cert_policy_for_host_[host].Check(cert, error);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_host_state.h b/chromium/content/browser/ssl/ssl_host_state.h
deleted file mode 100644
index 820821786d3..00000000000
--- a/chromium/content/browser/ssl/ssl_host_state.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
-#define CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/supports_user_data.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/common/content_export.h"
-#include "net/cert/cert_status_flags.h"
-#include "net/cert/x509_certificate.h"
-
-namespace content {
-class BrowserContext;
-
-// SSLHostState
-//
-// The SSLHostState encapulates the host-specific state for SSL errors. For
-// example, SSLHostState remembers whether the user has whitelisted a
-// particular broken cert for use with particular host. We separate this state
-// from the SSLManager because this state is shared across many navigation
-// controllers.
-
-class CONTENT_EXPORT SSLHostState
- : NON_EXPORTED_BASE(base::SupportsUserData::Data),
- NON_EXPORTED_BASE(public base::NonThreadSafe) {
- public:
- static SSLHostState* GetFor(BrowserContext* browser_context);
-
- SSLHostState();
- virtual ~SSLHostState();
-
- // Records that a host has run insecure content.
- void HostRanInsecureContent(const std::string& host, int pid);
-
- // Returns whether the specified host ran insecure content.
- bool DidHostRunInsecureContent(const std::string& host, int pid) const;
-
- // Records that |cert| is not permitted to be used for |host| in the future,
- // for a specified |error| type..
- void DenyCertForHost(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error);
-
- // Records that |cert| is permitted to be used for |host| in the future, for
- // a specified |error| type.
- void AllowCertForHost(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error);
-
- // Clear all allow/deny preferences.
- void Clear();
-
- // Queries whether |cert| is allowed or denied for |host| and |error|.
- net::CertPolicy::Judgment QueryPolicy(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error);
-
- private:
- // A BrokenHostEntry is a pair of (host, process_id) that indicates the host
- // contains insecure content in that renderer process.
- typedef std::pair<std::string, int> BrokenHostEntry;
-
- // Hosts which have been contaminated with insecure content in the
- // specified process. Note that insecure content can travel between
- // same-origin frames in one processs but cannot jump between processes.
- std::set<BrokenHostEntry> ran_insecure_content_hosts_;
-
- // Certificate policies for each host.
- std::map<std::string, net::CertPolicy> cert_policy_for_host_;
-
- DISALLOW_COPY_AND_ASSIGN(SSLHostState);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SSL_SSL_HOST_STATE_H_
diff --git a/chromium/content/browser/ssl/ssl_host_state_unittest.cc b/chromium/content/browser/ssl/ssl_host_state_unittest.cc
deleted file mode 100644
index 5e4366d375d..00000000000
--- a/chromium/content/browser/ssl/ssl_host_state_unittest.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/ssl/ssl_host_state.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Certificates for test data. They're obtained with:
-//
-// $ openssl s_client -connect [host]:443 -showcerts
-// $ openssl x509 -inform PEM -outform DER > /tmp/host.der
-// $ xxd -i /tmp/host.der
-
-// Google's cert.
-
-unsigned char google_der[] = {
- 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x8a, 0xa0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x10, 0x3c, 0x8d, 0x3a, 0x64, 0xee, 0x18, 0xdd, 0x1b, 0x73,
- 0x0b, 0xa1, 0x92, 0xee, 0xf8, 0x98, 0x1b, 0x30, 0x0d, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c,
- 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a,
- 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c,
- 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75,
- 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20,
- 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
- 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47,
- 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x35,
- 0x30, 0x32, 0x31, 0x37, 0x30, 0x32, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x30,
- 0x39, 0x30, 0x35, 0x30, 0x32, 0x31, 0x37, 0x30, 0x32, 0x35, 0x35, 0x5a,
- 0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
- 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61,
- 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0d, 0x4d,
- 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77,
- 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47,
- 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x17, 0x30,
- 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x77, 0x77, 0x77, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x81,
- 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
- 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
- 0x81, 0x81, 0x00, 0x9b, 0x19, 0xed, 0x5d, 0xa5, 0x56, 0xaf, 0x49, 0x66,
- 0xdb, 0x79, 0xfd, 0xc2, 0x1c, 0x78, 0x4e, 0x4f, 0x11, 0xa5, 0x8a, 0xac,
- 0xe2, 0x94, 0xee, 0xe3, 0xe2, 0x4b, 0xc0, 0x03, 0x25, 0xa7, 0x99, 0xcc,
- 0x65, 0xe1, 0xec, 0x94, 0xae, 0xae, 0xf0, 0xa7, 0x99, 0xbc, 0x10, 0xd7,
- 0xed, 0x87, 0x30, 0x47, 0xcd, 0x50, 0xf9, 0xaf, 0xd3, 0xd3, 0xf4, 0x0b,
- 0x8d, 0x47, 0x8a, 0x2e, 0xe2, 0xce, 0x53, 0x9b, 0x91, 0x99, 0x7f, 0x1e,
- 0x5c, 0xf9, 0x1b, 0xd6, 0xe9, 0x93, 0x67, 0xe3, 0x4a, 0xf8, 0xcf, 0xc4,
- 0x8c, 0x0c, 0x68, 0xd1, 0x97, 0x54, 0x47, 0x0e, 0x0a, 0x24, 0x30, 0xa7,
- 0x82, 0x94, 0xae, 0xde, 0xae, 0x3f, 0xbf, 0xba, 0x14, 0xc6, 0xf8, 0xb2,
- 0x90, 0x8e, 0x36, 0xad, 0xe1, 0xd0, 0xbe, 0x16, 0x9a, 0xb3, 0x5e, 0x72,
- 0x38, 0x49, 0xda, 0x74, 0xa1, 0x3f, 0xff, 0xd2, 0x87, 0x81, 0xed, 0x02,
- 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, 0x30, 0x28,
- 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b,
- 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01,
- 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86,
- 0xf8, 0x42, 0x04, 0x01, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04,
- 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0, 0x27, 0x86, 0x25, 0x68,
- 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68,
- 0x61, 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61,
- 0x77, 0x74, 0x65, 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c,
- 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
- 0x04, 0x66, 0x30, 0x64, 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
- 0x05, 0x07, 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
- 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65,
- 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
- 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
- 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2e,
- 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
- 0x72, 0x79, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x5f, 0x53, 0x47,
- 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0c, 0x06, 0x03,
- 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0d,
- 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
- 0x00, 0x03, 0x81, 0x81, 0x00, 0x31, 0x0a, 0x6c, 0xa2, 0x9e, 0xe9, 0x54,
- 0x19, 0x16, 0x68, 0x99, 0x91, 0xd6, 0x43, 0xcb, 0x6b, 0xb4, 0xcc, 0x6c,
- 0xcc, 0xb0, 0xfb, 0xf1, 0xee, 0x81, 0xbf, 0x00, 0x2b, 0x6f, 0x50, 0x12,
- 0xc6, 0xaf, 0x02, 0x2a, 0x36, 0xc1, 0x28, 0xde, 0xc5, 0x4c, 0x56, 0x20,
- 0x6d, 0xf5, 0x3d, 0x42, 0xb9, 0x18, 0x81, 0x20, 0xb2, 0xdd, 0x57, 0x5d,
- 0xeb, 0xbe, 0x32, 0x84, 0x50, 0x45, 0x51, 0x6e, 0xcd, 0xe4, 0x2e, 0x2a,
- 0x38, 0x88, 0x9f, 0x52, 0xed, 0x28, 0xff, 0xfc, 0x8d, 0x57, 0xb5, 0xad,
- 0x64, 0xae, 0x4d, 0x0e, 0x0e, 0xd9, 0x3d, 0xac, 0xb8, 0xfe, 0x66, 0x4c,
- 0x15, 0x8f, 0x44, 0x52, 0xfa, 0x7c, 0x3c, 0x04, 0xed, 0x7f, 0x37, 0x61,
- 0x04, 0xfe, 0xd5, 0xe9, 0xb9, 0xb0, 0x9e, 0xfe, 0xa5, 0x11, 0x69, 0xc9,
- 0x63, 0xd6, 0x46, 0x81, 0x6f, 0x00, 0xd8, 0x72, 0x2f, 0x82, 0x37, 0x44,
- 0xc1
-};
-
-} // namespace
-
-namespace content {
-
-class SSLHostStateTest : public testing::Test {
-};
-
-TEST_F(SSLHostStateTest, DidHostRunInsecureContent) {
- SSLHostState state;
-
- EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 42));
- EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 191));
- EXPECT_FALSE(state.DidHostRunInsecureContent("example.com", 42));
-
- state.HostRanInsecureContent("www.google.com", 42);
-
- EXPECT_TRUE(state.DidHostRunInsecureContent("www.google.com", 42));
- EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 191));
- EXPECT_FALSE(state.DidHostRunInsecureContent("example.com", 42));
-
- state.HostRanInsecureContent("example.com", 42);
-
- EXPECT_TRUE(state.DidHostRunInsecureContent("www.google.com", 42));
- EXPECT_FALSE(state.DidHostRunInsecureContent("www.google.com", 191));
- EXPECT_TRUE(state.DidHostRunInsecureContent("example.com", 42));
-}
-
-TEST_F(SSLHostStateTest, QueryPolicy) {
- scoped_refptr<net::X509Certificate> google_cert(
- net::X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der)));
-
- SSLHostState state;
-
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "www.google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID));
-
- state.AllowCertForHost(google_cert.get(),
- "www.google.com",
- net::CERT_STATUS_DATE_INVALID);
-
- EXPECT_EQ(net::CertPolicy::ALLOWED,
- state.QueryPolicy(google_cert.get(),
- "www.google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID));
-
- state.AllowCertForHost(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID);
-
- EXPECT_EQ(net::CertPolicy::ALLOWED,
- state.QueryPolicy(google_cert.get(),
- "www.google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::ALLOWED,
- state.QueryPolicy(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID));
-
- state.DenyCertForHost(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID);
-
- EXPECT_EQ(net::CertPolicy::ALLOWED,
- state.QueryPolicy(google_cert.get(),
- "www.google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::DENIED,
- state.QueryPolicy(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID));
-
- state.Clear();
-
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "www.google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "google.com",
- net::CERT_STATUS_DATE_INVALID));
- EXPECT_EQ(net::CertPolicy::UNKNOWN,
- state.QueryPolicy(google_cert.get(),
- "example.com",
- net::CERT_STATUS_DATE_INVALID));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_manager.cc b/chromium/content/browser/ssl/ssl_manager.cc
index 68906ced1ec..ccaf9cf2062 100644
--- a/chromium/content/browser/ssl/ssl_manager.cc
+++ b/chromium/content/browser/ssl/ssl_manager.cc
@@ -49,8 +49,7 @@ class SSLManagerSet : public base::SupportsUserData::Data {
// static
void SSLManager::OnSSLCertificateError(
const base::WeakPtr<SSLErrorHandler::Delegate>& delegate,
- const GlobalRequestID& id,
- const ResourceType::Type resource_type,
+ const ResourceType resource_type,
const GURL& url,
int render_process_id,
int render_frame_id,
@@ -58,10 +57,11 @@ void SSLManager::OnSSLCertificateError(
bool fatal) {
DCHECK(delegate.get());
DVLOG(1) << "OnSSLCertificateError() cert_error: "
- << net::MapCertStatusToNetError(ssl_info.cert_status) << " id: "
- << id.child_id << "," << id.request_id << " resource_type: "
- << resource_type << " url: " << url.spec() << " render_process_id: "
- << render_process_id << " render_frame_id: " << render_frame_id
+ << net::MapCertStatusToNetError(ssl_info.cert_status)
+ << " resource_type: " << resource_type
+ << " url: " << url.spec()
+ << " render_process_id: " << render_process_id
+ << " render_frame_id: " << render_frame_id
<< " cert_status: " << std::hex << ssl_info.cert_status;
// A certificate error occurred. Construct a SSLCertErrorHandler object and
@@ -70,7 +70,6 @@ void SSLManager::OnSSLCertificateError(
BrowserThread::UI, FROM_HERE,
base::Bind(&SSLCertErrorHandler::Dispatch,
new SSLCertErrorHandler(delegate,
- id,
resource_type,
url,
render_process_id,
@@ -171,7 +170,7 @@ void SSLManager::DidLoadFromMemoryCache(
// resouces aren't cachable.
scoped_refptr<SSLRequestInfo> info(new SSLRequestInfo(
details.url,
- ResourceType::SUB_RESOURCE,
+ RESOURCE_TYPE_SUB_RESOURCE,
details.pid,
details.cert_id,
details.cert_status));
diff --git a/chromium/content/browser/ssl/ssl_manager.h b/chromium/content/browser/ssl/ssl_manager.h
index c195e981bcb..d4fca43e6b9 100644
--- a/chromium/content/browser/ssl/ssl_manager.h
+++ b/chromium/content/browser/ssl/ssl_manager.h
@@ -45,13 +45,12 @@ class SSLManager {
// Entry point for SSLCertificateErrors. This function begins the process
// of resolving a certificate error during an SSL connection. SSLManager
// will adjust the security UI and either call |CancelSSLRequest| or
- // |ContinueSSLRequest| of |delegate| with |id| as the first argument.
+ // |ContinueSSLRequest| of |delegate|.
//
// Called on the IO thread.
static void OnSSLCertificateError(
const base::WeakPtr<SSLErrorHandler::Delegate>& delegate,
- const GlobalRequestID& id,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
const GURL& url,
int render_process_id,
int render_frame_id,
diff --git a/chromium/content/browser/ssl/ssl_policy.cc b/chromium/content/browser/ssl/ssl_policy.cc
index 731645505b4..51ae7b2a1c8 100644
--- a/chromium/content/browser/ssl/ssl_policy.cc
+++ b/chromium/content/browser/ssl/ssl_policy.cc
@@ -18,10 +18,10 @@
#include "content/browser/ssl/ssl_request_info.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/resource_type.h"
#include "content/public/common/ssl_status.h"
#include "content/public/common/url_constants.h"
#include "net/ssl/ssl_info.h"
-#include "webkit/common/resource_type.h"
namespace content {
@@ -32,21 +32,23 @@ SSLPolicy::SSLPolicy(SSLPolicyBackend* backend)
}
void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
+ bool expired_previous_decision;
// First we check if we know the policy for this error.
- net::CertPolicy::Judgment judgment = backend_->QueryPolicy(
- handler->ssl_info().cert.get(),
- handler->request_url().host(),
- handler->cert_error());
-
- if (judgment == net::CertPolicy::ALLOWED) {
+ DCHECK(handler->ssl_info().is_valid());
+ SSLHostStateDelegate::CertJudgment judgment =
+ backend_->QueryPolicy(*handler->ssl_info().cert.get(),
+ handler->request_url().host(),
+ handler->cert_error(),
+ &expired_previous_decision);
+
+ if (judgment == SSLHostStateDelegate::ALLOWED) {
handler->ContinueRequest();
return;
}
- // The judgment is either DENIED or UNKNOWN.
- // For now we handle the DENIED as the UNKNOWN, which means a blocking
- // page is shown to the user every time he comes back to the page.
-
+ // For all other hosts, which must be DENIED, a blocking page is shown to the
+ // user every time they come back to the page.
+ int options_mask = 0;
switch (handler->cert_error()) {
case net::ERR_CERT_COMMON_NAME_INVALID:
case net::ERR_CERT_DATE_INVALID:
@@ -54,7 +56,13 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM:
case net::ERR_CERT_WEAK_KEY:
case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION:
- OnCertErrorInternal(handler, !handler->fatal(), handler->fatal());
+ if (!handler->fatal())
+ options_mask |= OVERRIDABLE;
+ else
+ options_mask |= STRICT_ENFORCEMENT;
+ if (expired_previous_decision)
+ options_mask |= EXPIRED_PREVIOUS_DECISION;
+ OnCertErrorInternal(handler, options_mask);
break;
case net::ERR_CERT_NO_REVOCATION_MECHANISM:
// Ignore this error.
@@ -70,7 +78,11 @@ void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
case net::ERR_CERT_INVALID:
case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
- OnCertErrorInternal(handler, false, handler->fatal());
+ if (handler->fatal())
+ options_mask |= STRICT_ENFORCEMENT;
+ if (expired_previous_decision)
+ options_mask |= EXPIRED_PREVIOUS_DECISION;
+ OnCertErrorInternal(handler, options_mask);
break;
default:
NOTREACHED();
@@ -150,6 +162,7 @@ void SSLPolicy::UpdateEntry(NavigationEntryImpl* entry,
void SSLPolicy::OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
bool allow) {
+ DCHECK(handler->ssl_info().is_valid());
if (allow) {
// Default behavior for accepting a certificate.
// Note that we should not call SetMaxSecurityStyle here, because the active
@@ -161,19 +174,12 @@ void SSLPolicy::OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
// While AllowCertForHost() executes synchronously on this thread,
// ContinueRequest() gets posted to a different thread. Calling
// AllowCertForHost() first ensures deterministic ordering.
- backend_->AllowCertForHost(handler->ssl_info().cert.get(),
+ backend_->AllowCertForHost(*handler->ssl_info().cert.get(),
handler->request_url().host(),
handler->cert_error());
handler->ContinueRequest();
} else {
// Default behavior for rejecting a certificate.
- //
- // While DenyCertForHost() executes synchronously on this thread,
- // CancelRequest() gets posted to a different thread. Calling
- // DenyCertForHost() first ensures deterministic ordering.
- backend_->DenyCertForHost(handler->ssl_info().cert.get(),
- handler->request_url().host(),
- handler->cert_error());
handler->CancelRequest();
}
}
@@ -182,8 +188,11 @@ void SSLPolicy::OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
// Certificate Error Routines
void SSLPolicy::OnCertErrorInternal(SSLCertErrorHandler* handler,
- bool overridable,
- bool strict_enforcement) {
+ int options_mask) {
+ bool overridable = (options_mask & OVERRIDABLE) != 0;
+ bool strict_enforcement = (options_mask & STRICT_ENFORCEMENT) != 0;
+ bool expired_previous_decision =
+ (options_mask & EXPIRED_PREVIOUS_DECISION) != 0;
CertificateRequestResultType result =
CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE;
GetContentClient()->browser()->AllowCertificateError(
@@ -195,7 +204,9 @@ void SSLPolicy::OnCertErrorInternal(SSLCertErrorHandler* handler,
handler->resource_type(),
overridable,
strict_enforcement,
- base::Bind(&SSLPolicy::OnAllowCertificate, base::Unretained(this),
+ expired_previous_decision,
+ base::Bind(&SSLPolicy::OnAllowCertificate,
+ base::Unretained(this),
make_scoped_refptr(handler)),
&result);
switch (result) {
diff --git a/chromium/content/browser/ssl/ssl_policy.h b/chromium/content/browser/ssl/ssl_policy.h
index c88e10c8440..78dbb6d8960 100644
--- a/chromium/content/browser/ssl/ssl_policy.h
+++ b/chromium/content/browser/ssl/ssl_policy.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "webkit/common/resource_type.h"
+#include "content/public/common/resource_type.h"
namespace content {
class NavigationEntryImpl;
@@ -44,20 +44,27 @@ class SSLPolicy {
SSLPolicyBackend* backend() const { return backend_; }
private:
+ enum OnCertErrorInternalOptionsMask {
+ OVERRIDABLE = 1 << 0,
+ STRICT_ENFORCEMENT = 1 << 1,
+ EXPIRED_PREVIOUS_DECISION = 1 << 2
+ };
+
// Callback that the user chose to accept or deny the certificate.
void OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
bool allow);
// Helper method for derived classes handling certificate errors.
//
- // |overridable| indicates whether or not the user could (assuming perfect
+ // Options should be a bitmask combination of OnCertErrorInternalOptionsMask.
+ // OVERRIDABLE indicates whether or not the user could (assuming perfect
// knowledge) successfully override the error and still get the security
- // guarantees of TLS. |strict_enforcement| indicates whether or not the
- // site the user is trying to connect to has requested strict enforcement
- // of certificate validation (e.g. with HTTP Strict-Transport-Security).
- void OnCertErrorInternal(SSLCertErrorHandler* handler,
- bool overridable,
- bool strict_enforcement);
+ // guarantees of TLS. STRICT_ENFORCEMENT indicates whether or not the site the
+ // user is trying to connect to has requested strict enforcement of
+ // certificate validation (e.g. with HTTP Strict-Transport-Security).
+ // EXPIRED_PREVIOUS_DECISION indicates whether a user decision had been
+ // previously made but the decision has expired.
+ void OnCertErrorInternal(SSLCertErrorHandler* handler, int options_mask);
// If the security style of |entry| has not been initialized, then initialize
// it with the default style for its URL.
diff --git a/chromium/content/browser/ssl/ssl_policy_backend.cc b/chromium/content/browser/ssl/ssl_policy_backend.cc
index 3eb4f467e70..5c658748219 100644
--- a/chromium/content/browser/ssl/ssl_policy_backend.cc
+++ b/chromium/content/browser/ssl/ssl_policy_backend.cc
@@ -5,44 +5,48 @@
#include "content/browser/ssl/ssl_policy_backend.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
-#include "content/browser/ssl/ssl_host_state.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/ssl_host_state_delegate.h"
namespace content {
SSLPolicyBackend::SSLPolicyBackend(NavigationControllerImpl* controller)
- : ssl_host_state_(SSLHostState::GetFor(controller->GetBrowserContext())),
+ : ssl_host_state_delegate_(
+ controller->GetBrowserContext()->GetSSLHostStateDelegate()),
controller_(controller) {
DCHECK(controller_);
}
void SSLPolicyBackend::HostRanInsecureContent(const std::string& host, int id) {
- ssl_host_state_->HostRanInsecureContent(host, id);
+ if (ssl_host_state_delegate_)
+ ssl_host_state_delegate_->HostRanInsecureContent(host, id);
SSLManager::NotifySSLInternalStateChanged(controller_->GetBrowserContext());
}
bool SSLPolicyBackend::DidHostRunInsecureContent(const std::string& host,
int pid) const {
- return ssl_host_state_->DidHostRunInsecureContent(host, pid);
-}
+ if (!ssl_host_state_delegate_)
+ return false;
-void SSLPolicyBackend::DenyCertForHost(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error) {
- ssl_host_state_->DenyCertForHost(cert, host, error);
+ return ssl_host_state_delegate_->DidHostRunInsecureContent(host, pid);
}
-void SSLPolicyBackend::AllowCertForHost(net::X509Certificate* cert,
+void SSLPolicyBackend::AllowCertForHost(const net::X509Certificate& cert,
const std::string& host,
net::CertStatus error) {
- ssl_host_state_->AllowCertForHost(cert, host, error);
+ if (ssl_host_state_delegate_)
+ ssl_host_state_delegate_->AllowCert(host, cert, error);
}
-net::CertPolicy::Judgment SSLPolicyBackend::QueryPolicy(
- net::X509Certificate* cert,
+SSLHostStateDelegate::CertJudgment SSLPolicyBackend::QueryPolicy(
+ const net::X509Certificate& cert,
const std::string& host,
- net::CertStatus error) {
- return ssl_host_state_->QueryPolicy(cert, host, error);
+ net::CertStatus error,
+ bool* expired_previous_decision) {
+ return ssl_host_state_delegate_ ?
+ ssl_host_state_delegate_->QueryPolicy(
+ host, cert, error, expired_previous_decision) :
+ SSLHostStateDelegate::DENIED;
}
} // namespace content
diff --git a/chromium/content/browser/ssl/ssl_policy_backend.h b/chromium/content/browser/ssl/ssl_policy_backend.h
index 06ea23eccca..15ebe310a0e 100644
--- a/chromium/content/browser/ssl/ssl_policy_backend.h
+++ b/chromium/content/browser/ssl/ssl_policy_backend.h
@@ -10,12 +10,12 @@
#include "base/basictypes.h"
#include "base/strings/string16.h"
+#include "content/public/browser/ssl_host_state_delegate.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/x509_certificate.h"
namespace content {
class NavigationControllerImpl;
-class SSLHostState;
class SSLPolicyBackend {
public:
@@ -27,26 +27,24 @@ class SSLPolicyBackend {
// Returns whether the specified host ran insecure content.
bool DidHostRunInsecureContent(const std::string& host, int pid) const;
- // Records that |cert| is not permitted to be used for |host| in the future,
- // for a specific error type.
- void DenyCertForHost(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error);
-
// Records that |cert| is permitted to be used for |host| in the future, for
// a specific error type.
- void AllowCertForHost(net::X509Certificate* cert,
+ void AllowCertForHost(const net::X509Certificate& cert,
const std::string& host,
net::CertStatus error);
- // Queries whether |cert| is allowed or denied for |host|.
- net::CertPolicy::Judgment QueryPolicy(net::X509Certificate* cert,
- const std::string& host,
- net::CertStatus error);
+ // Queries whether |cert| is allowed for |host|. Returns true in
+ // |expired_previous_decision| if a user decision had been made previously but
+ // that decision has expired, otherwise false.
+ SSLHostStateDelegate::CertJudgment QueryPolicy(
+ const net::X509Certificate& cert,
+ const std::string& host,
+ net::CertStatus error,
+ bool* expired_previous_decision);
private:
- // SSL state specific for each host.
- SSLHostState* ssl_host_state_;
+ // SSL state delegate specific for each host.
+ SSLHostStateDelegate* ssl_host_state_delegate_;
NavigationControllerImpl* controller_;
diff --git a/chromium/content/browser/ssl/ssl_request_info.cc b/chromium/content/browser/ssl/ssl_request_info.cc
index 0c23f83a3ca..f22376acff2 100644
--- a/chromium/content/browser/ssl/ssl_request_info.cc
+++ b/chromium/content/browser/ssl/ssl_request_info.cc
@@ -7,7 +7,7 @@
namespace content {
SSLRequestInfo::SSLRequestInfo(const GURL& url,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int child_id,
int ssl_cert_id,
net::CertStatus ssl_cert_status)
diff --git a/chromium/content/browser/ssl/ssl_request_info.h b/chromium/content/browser/ssl/ssl_request_info.h
index cf745fe7cfe..9f50448f4ed 100644
--- a/chromium/content/browser/ssl/ssl_request_info.h
+++ b/chromium/content/browser/ssl/ssl_request_info.h
@@ -8,9 +8,9 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "content/public/common/resource_type.h"
#include "net/cert/cert_status_flags.h"
#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
namespace content {
@@ -20,13 +20,13 @@ namespace content {
class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> {
public:
SSLRequestInfo(const GURL& url,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int child_id,
int ssl_cert_id,
net::CertStatus ssl_cert_status);
const GURL& url() const { return url_; }
- ResourceType::Type resource_type() const { return resource_type_; }
+ ResourceType resource_type() const { return resource_type_; }
int child_id() const { return child_id_; }
int ssl_cert_id() const { return ssl_cert_id_; }
net::CertStatus ssl_cert_status() const { return ssl_cert_status_; }
@@ -37,7 +37,7 @@ class SSLRequestInfo : public base::RefCounted<SSLRequestInfo> {
virtual ~SSLRequestInfo();
GURL url_;
- ResourceType::Type resource_type_;
+ ResourceType resource_type_;
int child_id_;
int ssl_cert_id_;
net::CertStatus ssl_cert_status_;
diff --git a/chromium/content/browser/startup_task_runner.cc b/chromium/content/browser/startup_task_runner.cc
index 4746afea6b0..8e680bd6d08 100644
--- a/chromium/content/browser/startup_task_runner.cc
+++ b/chromium/content/browser/startup_task_runner.cc
@@ -22,7 +22,7 @@ void StartupTaskRunner::AddTask(StartupTask& callback) {
}
void StartupTaskRunner::StartRunningTasksAsync() {
- DCHECK(proxy_);
+ DCHECK(proxy_.get());
int result = 0;
if (task_list_.empty()) {
if (!startup_complete_callback_.is_null()) {
diff --git a/chromium/content/browser/startup_task_runner_unittest.cc b/chromium/content/browser/startup_task_runner_unittest.cc
index fcd2b3d1da6..2ecf9ca63c5 100644
--- a/chromium/content/browser/startup_task_runner_unittest.cc
+++ b/chromium/content/browser/startup_task_runner_unittest.cc
@@ -42,8 +42,7 @@ void Observer(int result) {
class StartupTaskRunnerTest : public testing::Test {
public:
-
- virtual void SetUp() {
+ void SetUp() override {
last_task_ = 0;
observer_calls = 0;
task_count = 0;
@@ -96,22 +95,21 @@ class MockTaskRunner {
class TaskRunnerProxy : public base::SingleThreadTaskRunner {
public:
TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
- virtual bool RunsTasksOnCurrentThread() const OVERRIDE { return true; }
- virtual bool PostDelayedTask(const tracked_objects::Location& location,
- const Closure& closure,
- base::TimeDelta delta) OVERRIDE {
+ bool RunsTasksOnCurrentThread() const override { return true; }
+ bool PostDelayedTask(const tracked_objects::Location& location,
+ const Closure& closure,
+ base::TimeDelta delta) override {
return mock_->PostDelayedTask(location, closure, delta);
}
- virtual bool PostNonNestableDelayedTask(
- const tracked_objects::Location& location,
- const Closure& closure,
- base::TimeDelta delta) OVERRIDE {
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& location,
+ const Closure& closure,
+ base::TimeDelta delta) override {
return mock_->PostNonNestableDelayedTask(location, closure, delta);
}
private:
MockTaskRunner* mock_;
- virtual ~TaskRunnerProxy() {}
+ ~TaskRunnerProxy() override {}
};
TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index 9a876b5cff8..d4e49f60f13 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -8,6 +8,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
+#include "content/browser/geofencing/geofencing_manager.h"
#include "content/browser/gpu/shader_disk_cache.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_context.h"
@@ -21,8 +22,8 @@
#include "net/cookies/cookie_monster.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
-#include "webkit/browser/database/database_tracker.h"
-#include "webkit/browser/quota/quota_manager.h"
+#include "storage/browser/database/database_tracker.h"
+#include "storage/browser/quota/quota_manager.h"
namespace content {
@@ -72,13 +73,13 @@ void CheckQuotaManagedDataDeletionStatus(size_t* deletion_task_count,
}
void OnQuotaManagedOriginDeleted(const GURL& origin,
- quota::StorageType type,
+ storage::StorageType type,
size_t* deletion_task_count,
const base::Closure& callback,
- quota::QuotaStatusCode status) {
+ storage::QuotaStatusCode status) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK_GT(*deletion_task_count, 0u);
- if (status != quota::kQuotaStatusOk) {
+ if (status != storage::kQuotaStatusOk) {
DLOG(ERROR) << "Couldn't remove data of type " << type << " for origin "
<< origin << ". Status: " << status;
}
@@ -108,7 +109,7 @@ void ClearShaderCacheOnIOThread(const base::FilePath& path,
void OnLocalStorageUsageInfo(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Time delete_begin,
const base::Time delete_end,
@@ -132,7 +133,7 @@ void OnLocalStorageUsageInfo(
void OnSessionStorageUsageInfo(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback,
const std::vector<SessionStorageUsageInfo>& infos) {
@@ -151,7 +152,7 @@ void OnSessionStorageUsageInfo(
void ClearLocalStorageOnUIThread(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const GURL& storage_origin,
const base::Time begin,
@@ -178,7 +179,7 @@ void ClearLocalStorageOnUIThread(
void ClearSessionStorageOnUIThread(
const scoped_refptr<DOMStorageContextWrapper>& dom_storage_context,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -191,18 +192,53 @@ void ClearSessionStorageOnUIThread(
} // namespace
+// static
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_APPCACHE;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_COOKIES;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_WEBSQL;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_WEBRTC_IDENTITY;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::REMOVE_DATA_MASK_ALL;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
+STATIC_CONST_MEMBER_DEFINITION const uint32
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
+
// Static.
int StoragePartitionImpl::GenerateQuotaClientMask(uint32 remove_mask) {
int quota_client_mask = 0;
if (remove_mask & StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS)
- quota_client_mask |= quota::QuotaClient::kFileSystem;
+ quota_client_mask |= storage::QuotaClient::kFileSystem;
if (remove_mask & StoragePartition::REMOVE_DATA_MASK_WEBSQL)
- quota_client_mask |= quota::QuotaClient::kDatabase;
+ quota_client_mask |= storage::QuotaClient::kDatabase;
if (remove_mask & StoragePartition::REMOVE_DATA_MASK_APPCACHE)
- quota_client_mask |= quota::QuotaClient::kAppcache;
+ quota_client_mask |= storage::QuotaClient::kAppcache;
if (remove_mask & StoragePartition::REMOVE_DATA_MASK_INDEXEDDB)
- quota_client_mask |= quota::QuotaClient::kIndexedDatabase;
+ quota_client_mask |= storage::QuotaClient::kIndexedDatabase;
+ if (remove_mask & StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS) {
+ quota_client_mask |= storage::QuotaClient::kServiceWorker;
+ quota_client_mask |= storage::QuotaClient::kServiceWorkerCache;
+ }
+
return quota_client_mask;
}
@@ -226,18 +262,20 @@ struct StoragePartitionImpl::QuotaManagedDataDeletionHelper {
void DecrementTaskCountOnIO();
void ClearDataOnIOThread(
- const scoped_refptr<quota::QuotaManager>& quota_manager,
+ const scoped_refptr<storage::QuotaManager>& quota_manager,
const base::Time begin,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>&
+ special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher);
void ClearOriginsOnIOThread(
- quota::QuotaManager* quota_manager,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ storage::QuotaManager* quota_manager,
+ const scoped_refptr<storage::SpecialStoragePolicy>&
+ special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback,
const std::set<GURL>& origins,
- quota::StorageType quota_storage_type);
+ storage::StorageType quota_storage_type);
// All of these data are accessed on IO thread.
uint32 remove_mask;
@@ -270,22 +308,24 @@ struct StoragePartitionImpl::DataDeletionHelper {
void IncrementTaskCountOnUI();
void DecrementTaskCountOnUI();
- void ClearDataOnUIThread(const GURL& storage_origin,
- const OriginMatcherFunction& origin_matcher,
- const base::FilePath& path,
- net::URLRequestContextGetter* rq_context,
- DOMStorageContextWrapper* dom_storage_context,
- quota::QuotaManager* quota_manager,
- quota::SpecialStoragePolicy* special_storage_policy,
- WebRTCIdentityStore* webrtc_identity_store,
- const base::Time begin,
- const base::Time end);
+ void ClearDataOnUIThread(
+ const GURL& storage_origin,
+ const OriginMatcherFunction& origin_matcher,
+ const base::FilePath& path,
+ net::URLRequestContextGetter* rq_context,
+ DOMStorageContextWrapper* dom_storage_context,
+ storage::QuotaManager* quota_manager,
+ storage::SpecialStoragePolicy* special_storage_policy,
+ WebRTCIdentityStore* webrtc_identity_store,
+ const base::Time begin,
+ const base::Time end);
void ClearQuotaManagedDataOnIOThread(
- const scoped_refptr<quota::QuotaManager>& quota_manager,
+ const scoped_refptr<storage::QuotaManager>& quota_manager,
const base::Time begin,
const GURL& storage_origin,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>&
+ special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback);
@@ -299,10 +339,10 @@ struct StoragePartitionImpl::DataDeletionHelper {
};
void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread(
- const scoped_refptr<quota::QuotaManager>& quota_manager,
+ const scoped_refptr<storage::QuotaManager>& quota_manager,
const base::Time begin,
const GURL& storage_origin,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -319,15 +359,16 @@ void StoragePartitionImpl::DataDeletionHelper::ClearQuotaManagedDataOnIOThread(
StoragePartitionImpl::StoragePartitionImpl(
const base::FilePath& partition_path,
- quota::QuotaManager* quota_manager,
+ storage::QuotaManager* quota_manager,
ChromeAppCacheService* appcache_service,
- fileapi::FileSystemContext* filesystem_context,
- webkit_database::DatabaseTracker* database_tracker,
+ storage::FileSystemContext* filesystem_context,
+ storage::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
ServiceWorkerContextWrapper* service_worker_context,
WebRTCIdentityStore* webrtc_identity_store,
- quota::SpecialStoragePolicy* special_storage_policy)
+ storage::SpecialStoragePolicy* special_storage_policy,
+ GeofencingManager* geofencing_manager)
: partition_path_(partition_path),
quota_manager_(quota_manager),
appcache_service_(appcache_service),
@@ -337,16 +378,18 @@ StoragePartitionImpl::StoragePartitionImpl(
indexed_db_context_(indexed_db_context),
service_worker_context_(service_worker_context),
webrtc_identity_store_(webrtc_identity_store),
- special_storage_policy_(special_storage_policy) {}
+ special_storage_policy_(special_storage_policy),
+ geofencing_manager_(geofencing_manager) {
+}
StoragePartitionImpl::~StoragePartitionImpl() {
// These message loop checks are just to avoid leaks in unittests.
if (GetDatabaseTracker() &&
BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) {
BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&webkit_database::DatabaseTracker::Shutdown,
- GetDatabaseTracker()));
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&storage::DatabaseTracker::Shutdown, GetDatabaseTracker()));
}
if (GetFileSystemContext())
@@ -357,6 +400,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
if (GetServiceWorkerContext())
GetServiceWorkerContext()->Shutdown();
+
+ if (GetGeofencingManager())
+ GetGeofencingManager()->Shutdown();
}
// TODO(ajwong): Break the direct dependency on |context|. We only
@@ -374,28 +420,27 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
// QuotaManager prior to the QuotaManger being used. We do them
// all together here prior to handing out a reference to anything
// that utilizes the QuotaManager.
- scoped_refptr<quota::QuotaManager> quota_manager = new quota::QuotaManager(
- in_memory,
- partition_path,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
- context->GetSpecialStoragePolicy());
+ scoped_refptr<storage::QuotaManager> quota_manager =
+ new storage::QuotaManager(
+ in_memory,
+ partition_path,
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
+ context->GetSpecialStoragePolicy());
// Each consumer is responsible for registering its QuotaClient during
// its construction.
- scoped_refptr<fileapi::FileSystemContext> filesystem_context =
- CreateFileSystemContext(context,
- partition_path, in_memory,
- quota_manager->proxy());
-
- scoped_refptr<webkit_database::DatabaseTracker> database_tracker =
- new webkit_database::DatabaseTracker(
- partition_path,
- in_memory,
- context->GetSpecialStoragePolicy(),
- quota_manager->proxy(),
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
- .get());
+ scoped_refptr<storage::FileSystemContext> filesystem_context =
+ CreateFileSystemContext(
+ context, partition_path, in_memory, quota_manager->proxy());
+
+ scoped_refptr<storage::DatabaseTracker> database_tracker =
+ new storage::DatabaseTracker(partition_path,
+ in_memory,
+ context->GetSpecialStoragePolicy(),
+ quota_manager->proxy(),
+ BrowserThread::GetMessageLoopProxyForThread(
+ BrowserThread::FILE).get());
base::FilePath path = in_memory ? base::FilePath() : partition_path;
scoped_refptr<DOMStorageContextWrapper> dom_storage_context =
@@ -417,7 +462,8 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
new ServiceWorkerContextWrapper(context);
- service_worker_context->Init(path, quota_manager->proxy());
+ service_worker_context->Init(
+ path, quota_manager->proxy(), context->GetSpecialStoragePolicy());
scoped_refptr<ChromeAppCacheService> appcache_service =
new ChromeAppCacheService(quota_manager->proxy());
@@ -425,9 +471,13 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
scoped_refptr<WebRTCIdentityStore> webrtc_identity_store(
new WebRTCIdentityStore(path, context->GetSpecialStoragePolicy()));
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy(
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy(
context->GetSpecialStoragePolicy());
+ scoped_refptr<GeofencingManager> geofencing_manager =
+ new GeofencingManager(service_worker_context);
+ geofencing_manager->Init();
+
return new StoragePartitionImpl(partition_path,
quota_manager.get(),
appcache_service.get(),
@@ -437,7 +487,8 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
indexed_db_context.get(),
service_worker_context.get(),
webrtc_identity_store.get(),
- special_storage_policy.get());
+ special_storage_policy.get(),
+ geofencing_manager.get());
}
base::FilePath StoragePartitionImpl::GetPath() {
@@ -453,7 +504,7 @@ StoragePartitionImpl::GetMediaURLRequestContext() {
return media_url_request_context_.get();
}
-quota::QuotaManager* StoragePartitionImpl::GetQuotaManager() {
+storage::QuotaManager* StoragePartitionImpl::GetQuotaManager() {
return quota_manager_.get();
}
@@ -461,11 +512,11 @@ ChromeAppCacheService* StoragePartitionImpl::GetAppCacheService() {
return appcache_service_.get();
}
-fileapi::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() {
+storage::FileSystemContext* StoragePartitionImpl::GetFileSystemContext() {
return filesystem_context_.get();
}
-webkit_database::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() {
+storage::DatabaseTracker* StoragePartitionImpl::GetDatabaseTracker() {
return database_tracker_.get();
}
@@ -481,6 +532,10 @@ ServiceWorkerContextWrapper* StoragePartitionImpl::GetServiceWorkerContext() {
return service_worker_context_.get();
}
+GeofencingManager* StoragePartitionImpl::GetGeofencingManager() {
+ return geofencing_manager_.get();
+}
+
void StoragePartitionImpl::ClearDataImpl(
uint32 remove_mask,
uint32 quota_storage_remove_mask,
@@ -496,10 +551,16 @@ void StoragePartitionImpl::ClearDataImpl(
callback);
// |helper| deletes itself when done in
// DataDeletionHelper::DecrementTaskCountOnUI().
- helper->ClearDataOnUIThread(storage_origin, origin_matcher, GetPath(),
- rq_context, dom_storage_context_, quota_manager_,
+ helper->ClearDataOnUIThread(storage_origin,
+ origin_matcher,
+ GetPath(),
+ rq_context,
+ dom_storage_context_.get(),
+ quota_manager_.get(),
special_storage_policy_.get(),
- webrtc_identity_store_, begin, end);
+ webrtc_identity_store_.get(),
+ begin,
+ end);
}
void StoragePartitionImpl::
@@ -521,9 +582,9 @@ void StoragePartitionImpl::
}
void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
- const scoped_refptr<quota::QuotaManager>& quota_manager,
+ const scoped_refptr<storage::QuotaManager>& quota_manager,
const base::Time begin,
- const scoped_refptr<quota::SpecialStoragePolicy>& special_storage_policy,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
const StoragePartition::OriginMatcherFunction& origin_matcher) {
IncrementTaskCountOnIO();
base::Closure decrement_callback = base::Bind(
@@ -536,7 +597,8 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
// within the user-specified timeframe, and deal with the resulting set in
// ClearQuotaManagedOriginsOnIOThread().
quota_manager->GetOriginsModifiedSince(
- quota::kStorageTypePersistent, begin,
+ storage::kStorageTypePersistent,
+ begin,
base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
base::Unretained(this),
quota_manager,
@@ -549,7 +611,8 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) {
IncrementTaskCountOnIO();
quota_manager->GetOriginsModifiedSince(
- quota::kStorageTypeTemporary, begin,
+ storage::kStorageTypeTemporary,
+ begin,
base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
base::Unretained(this),
quota_manager,
@@ -562,7 +625,8 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) {
IncrementTaskCountOnIO();
quota_manager->GetOriginsModifiedSince(
- quota::kStorageTypeSyncable, begin,
+ storage::kStorageTypeSyncable,
+ begin,
base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
base::Unretained(this),
quota_manager,
@@ -574,15 +638,14 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
DecrementTaskCountOnIO();
}
-void StoragePartitionImpl::
- QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread(
- quota::QuotaManager* quota_manager,
- const scoped_refptr<quota::SpecialStoragePolicy>&
- special_storage_policy,
- const StoragePartition::OriginMatcherFunction& origin_matcher,
- const base::Closure& callback,
- const std::set<GURL>& origins,
- quota::StorageType quota_storage_type) {
+void
+StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread(
+ storage::QuotaManager* quota_manager,
+ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy,
+ const StoragePartition::OriginMatcherFunction& origin_matcher,
+ const base::Closure& callback,
+ const std::set<GURL>& origins,
+ storage::StorageType quota_storage_type) {
// The QuotaManager manages all storage other than cookies, LocalStorage,
// and SessionStorage. This loop wipes out most HTML5 storage for the given
// origins.
@@ -645,8 +708,8 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
const base::FilePath& path,
net::URLRequestContextGetter* rq_context,
DOMStorageContextWrapper* dom_storage_context,
- quota::QuotaManager* quota_manager,
- quota::SpecialStoragePolicy* special_storage_policy,
+ storage::QuotaManager* quota_manager,
+ storage::SpecialStoragePolicy* special_storage_policy,
WebRTCIdentityStore* webrtc_identity_store,
const base::Time begin,
const base::Time end) {
@@ -670,7 +733,8 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
if (remove_mask & REMOVE_DATA_MASK_INDEXEDDB ||
remove_mask & REMOVE_DATA_MASK_WEBSQL ||
remove_mask & REMOVE_DATA_MASK_APPCACHE ||
- remove_mask & REMOVE_DATA_MASK_FILE_SYSTEMS) {
+ remove_mask & REMOVE_DATA_MASK_FILE_SYSTEMS ||
+ remove_mask & REMOVE_DATA_MASK_SERVICE_WORKERS) {
IncrementTaskCountOnUI();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
@@ -729,16 +793,21 @@ void StoragePartitionImpl::DataDeletionHelper::ClearDataOnUIThread(
DecrementTaskCountOnUI();
}
-
void StoragePartitionImpl::ClearDataForOrigin(
uint32 remove_mask,
uint32 quota_storage_remove_mask,
const GURL& storage_origin,
- net::URLRequestContextGetter* request_context_getter) {
+ net::URLRequestContextGetter* request_context_getter,
+ const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- ClearDataImpl(remove_mask, quota_storage_remove_mask, storage_origin,
- OriginMatcherFunction(), request_context_getter,
- base::Time(), base::Time::Max(), base::Bind(&base::DoNothing));
+ ClearDataImpl(remove_mask,
+ quota_storage_remove_mask,
+ storage_origin,
+ OriginMatcherFunction(),
+ request_context_getter,
+ base::Time(),
+ base::Time::Max(),
+ callback);
}
void StoragePartitionImpl::ClearData(
@@ -758,12 +827,12 @@ WebRTCIdentityStore* StoragePartitionImpl::GetWebRTCIdentityStore() {
}
void StoragePartitionImpl::OverrideQuotaManagerForTesting(
- quota::QuotaManager* quota_manager) {
+ storage::QuotaManager* quota_manager) {
quota_manager_ = quota_manager;
}
void StoragePartitionImpl::OverrideSpecialStoragePolicyForTesting(
- quota::SpecialStoragePolicy* special_storage_policy) {
+ storage::SpecialStoragePolicy* special_storage_policy) {
special_storage_policy_ = special_storage_policy;
}
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index 717038e7afc..30377392100 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -15,47 +15,48 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/content_export.h"
#include "content/public/browser/storage_partition.h"
-#include "webkit/browser/quota/special_storage_policy.h"
+#include "storage/browser/quota/special_storage_policy.h"
namespace content {
class StoragePartitionImpl : public StoragePartition {
public:
- CONTENT_EXPORT virtual ~StoragePartitionImpl();
+ CONTENT_EXPORT ~StoragePartitionImpl() override;
// Quota managed data uses a different bitmask for types than
// StoragePartition uses. This method generates that mask.
CONTENT_EXPORT static int GenerateQuotaClientMask(uint32 remove_mask);
CONTENT_EXPORT void OverrideQuotaManagerForTesting(
- quota::QuotaManager* quota_manager);
+ storage::QuotaManager* quota_manager);
CONTENT_EXPORT void OverrideSpecialStoragePolicyForTesting(
- quota::SpecialStoragePolicy* special_storage_policy);
+ storage::SpecialStoragePolicy* special_storage_policy);
// StoragePartition interface.
- virtual base::FilePath GetPath() OVERRIDE;
- virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE;
- virtual net::URLRequestContextGetter* GetMediaURLRequestContext() OVERRIDE;
- virtual quota::QuotaManager* GetQuotaManager() OVERRIDE;
- virtual ChromeAppCacheService* GetAppCacheService() OVERRIDE;
- virtual fileapi::FileSystemContext* GetFileSystemContext() OVERRIDE;
- virtual webkit_database::DatabaseTracker* GetDatabaseTracker() OVERRIDE;
- virtual DOMStorageContextWrapper* GetDOMStorageContext() OVERRIDE;
- virtual IndexedDBContextImpl* GetIndexedDBContext() OVERRIDE;
- virtual ServiceWorkerContextWrapper* GetServiceWorkerContext() OVERRIDE;
-
- virtual void ClearDataForOrigin(
- uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const GURL& storage_origin,
- net::URLRequestContextGetter* request_context_getter) OVERRIDE;
- virtual void ClearData(uint32 remove_mask,
- uint32 quota_storage_remove_mask,
- const GURL& storage_origin,
- const OriginMatcherFunction& origin_matcher,
- const base::Time begin,
- const base::Time end,
- const base::Closure& callback) OVERRIDE;
+ base::FilePath GetPath() override;
+ net::URLRequestContextGetter* GetURLRequestContext() override;
+ net::URLRequestContextGetter* GetMediaURLRequestContext() override;
+ storage::QuotaManager* GetQuotaManager() override;
+ ChromeAppCacheService* GetAppCacheService() override;
+ storage::FileSystemContext* GetFileSystemContext() override;
+ storage::DatabaseTracker* GetDatabaseTracker() override;
+ DOMStorageContextWrapper* GetDOMStorageContext() override;
+ IndexedDBContextImpl* GetIndexedDBContext() override;
+ ServiceWorkerContextWrapper* GetServiceWorkerContext() override;
+ GeofencingManager* GetGeofencingManager() override;
+
+ void ClearDataForOrigin(uint32 remove_mask,
+ uint32 quota_storage_remove_mask,
+ const GURL& storage_origin,
+ net::URLRequestContextGetter* request_context_getter,
+ const base::Closure& callback) override;
+ void ClearData(uint32 remove_mask,
+ uint32 quota_storage_remove_mask,
+ const GURL& storage_origin,
+ const OriginMatcherFunction& origin_matcher,
+ const base::Time begin,
+ const base::Time end,
+ const base::Closure& callback) override;
WebRTCIdentityStore* GetWebRTCIdentityStore();
@@ -108,15 +109,16 @@ class StoragePartitionImpl : public StoragePartition {
CONTENT_EXPORT StoragePartitionImpl(
const base::FilePath& partition_path,
- quota::QuotaManager* quota_manager,
+ storage::QuotaManager* quota_manager,
ChromeAppCacheService* appcache_service,
- fileapi::FileSystemContext* filesystem_context,
- webkit_database::DatabaseTracker* database_tracker,
+ storage::FileSystemContext* filesystem_context,
+ storage::DatabaseTracker* database_tracker,
DOMStorageContextWrapper* dom_storage_context,
IndexedDBContextImpl* indexed_db_context,
ServiceWorkerContextWrapper* service_worker_context,
WebRTCIdentityStore* webrtc_identity_store,
- quota::SpecialStoragePolicy* special_storage_policy);
+ storage::SpecialStoragePolicy* special_storage_policy,
+ GeofencingManager* geofencing_manager);
void ClearDataImpl(uint32 remove_mask,
uint32 quota_storage_remove_mask,
@@ -147,15 +149,16 @@ class StoragePartitionImpl : public StoragePartition {
base::FilePath partition_path_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_;
scoped_refptr<net::URLRequestContextGetter> media_url_request_context_;
- scoped_refptr<quota::QuotaManager> quota_manager_;
+ scoped_refptr<storage::QuotaManager> quota_manager_;
scoped_refptr<ChromeAppCacheService> appcache_service_;
- scoped_refptr<fileapi::FileSystemContext> filesystem_context_;
- scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
+ scoped_refptr<storage::FileSystemContext> filesystem_context_;
+ scoped_refptr<storage::DatabaseTracker> database_tracker_;
scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<GeofencingManager> geofencing_manager_;
DISALLOW_COPY_AND_ASSIGN(StoragePartitionImpl);
};
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index fdfb34e3ebd..d36968b9e28 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -6,14 +6,15 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "content/browser/appcache/appcache_interceptor.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
@@ -35,14 +36,13 @@
#include "crypto/sha2.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
-#include "webkit/browser/blob/blob_storage_context.h"
-#include "webkit/browser/blob/blob_url_request_job_factory.h"
-#include "webkit/browser/fileapi/file_system_url_request_job_factory.h"
-#include "webkit/common/blob/blob_data.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
+#include "storage/browser/fileapi/file_system_url_request_job_factory.h"
+#include "storage/common/blob/blob_data.h"
-using appcache::AppCacheServiceImpl;
-using fileapi::FileSystemContext;
-using webkit_blob::BlobStorageContext;
+using storage::FileSystemContext;
+using storage::BlobStorageContext;
namespace content {
@@ -53,18 +53,16 @@ class BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
public:
BlobProtocolHandler(ChromeBlobStorageContext* blob_storage_context,
StreamContext* stream_context,
- fileapi::FileSystemContext* file_system_context)
+ storage::FileSystemContext* file_system_context)
: blob_storage_context_(blob_storage_context),
stream_context_(stream_context),
- file_system_context_(file_system_context) {
- }
+ file_system_context_(file_system_context) {}
- virtual ~BlobProtocolHandler() {
- }
+ ~BlobProtocolHandler() override {}
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
scoped_refptr<Stream> stream =
stream_context_->registry()->GetStream(request->url());
if (stream.get())
@@ -74,12 +72,11 @@ class BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
// Construction is deferred because 'this' is constructed on
// the main thread but we want blob_protocol_handler_ constructed
// on the IO thread.
- blob_protocol_handler_.reset(
- new webkit_blob::BlobProtocolHandler(
- blob_storage_context_->context(),
- file_system_context_,
- BrowserThread::GetMessageLoopProxyForThread(
- BrowserThread::FILE).get()));
+ blob_protocol_handler_.reset(new storage::BlobProtocolHandler(
+ blob_storage_context_->context(),
+ file_system_context_.get(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)
+ .get()));
}
return blob_protocol_handler_->MaybeCreateJob(request, network_delegate);
}
@@ -87,8 +84,8 @@ class BlobProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
private:
const scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
const scoped_refptr<StreamContext> stream_context_;
- const scoped_refptr<fileapi::FileSystemContext> file_system_context_;
- mutable scoped_ptr<webkit_blob::BlobProtocolHandler> blob_protocol_handler_;
+ const scoped_refptr<storage::FileSystemContext> file_system_context_;
+ mutable scoped_ptr<storage::BlobProtocolHandler> blob_protocol_handler_;
DISALLOW_COPY_AND_ASSIGN(BlobProtocolHandler);
};
@@ -438,7 +435,10 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
URLRequestInterceptorScopedVector request_interceptors;
request_interceptors.push_back(
- ServiceWorkerRequestHandler::CreateInterceptor().release());
+ ServiceWorkerRequestHandler::CreateInterceptor(
+ browser_context_->GetResourceContext()).release());
+ request_interceptors.push_back(
+ AppCacheInterceptor::CreateStartInterceptor().release());
// These calls must happen after StoragePartitionImpl::Create().
if (partition_domain.empty()) {
@@ -495,8 +495,7 @@ void StoragePartitionImplMap::AsyncObliterate(
if (config.partition_domain == partition_domain) {
it->second->ClearData(
// All except shader cache.
- StoragePartition::REMOVE_DATA_MASK_ALL &
- (~StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE),
+ ~StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE,
StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
GURL(),
StoragePartition::OriginMatcherFunction(),
@@ -582,6 +581,15 @@ void StoragePartitionImplMap::PostCreateInitialization(
make_scoped_refptr(
browser_context_->GetSpecialStoragePolicy())));
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ServiceWorkerContextWrapper::SetBlobParametersForCache,
+ partition->GetServiceWorkerContext(),
+ make_scoped_refptr(partition->GetURLRequestContext()),
+ make_scoped_refptr(
+ ChromeBlobStorageContext::GetFor(browser_context_))));
+
// We do not call InitializeURLRequestContext() for media contexts because,
// other than the HTTP cache, the media contexts share the same backing
// objects as their associated "normal" request context. Thus, the previous
diff --git a/chromium/content/browser/storage_partition_impl_map.h b/chromium/content/browser/storage_partition_impl_map.h
index c15fefc3d8c..6536621e544 100644
--- a/chromium/content/browser/storage_partition_impl_map.h
+++ b/chromium/content/browser/storage_partition_impl_map.h
@@ -30,7 +30,7 @@ class CONTENT_EXPORT StoragePartitionImplMap
public:
explicit StoragePartitionImplMap(BrowserContext* browser_context);
- virtual ~StoragePartitionImplMap();
+ ~StoragePartitionImplMap() override;
// This map retains ownership of the returned StoragePartition objects.
StoragePartitionImpl* Get(const std::string& partition_domain,
diff --git a/chromium/content/browser/storage_partition_impl_map_unittest.cc b/chromium/content/browser/storage_partition_impl_map_unittest.cc
index ae7fa6d43d2..c88fb538764 100644
--- a/chromium/content/browser/storage_partition_impl_map_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_map_unittest.cc
@@ -4,7 +4,7 @@
#include "content/browser/storage_partition_impl_map.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/storage_partition_impl_unittest.cc b/chromium/content/browser/storage_partition_impl_unittest.cc
index 5fbdfbbab88..a2950c850aa 100644
--- a/chromium/content/browser/storage_partition_impl_unittest.cc
+++ b/chromium/content/browser/storage_partition_impl_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "base/threading/thread.h"
@@ -20,8 +20,8 @@
#include "net/cookies/cookie_monster.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "storage/browser/quota/quota_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/browser/quota/quota_manager.h"
namespace content {
namespace {
@@ -49,16 +49,16 @@ const base::FilePath::CharType kDomStorageOrigin2[] =
const base::FilePath::CharType kDomStorageOrigin3[] =
FILE_PATH_LITERAL("http_host3_1.localstorage");
-const quota::StorageType kTemporary = quota::kStorageTypeTemporary;
-const quota::StorageType kPersistent = quota::kStorageTypePersistent;
+const storage::StorageType kTemporary = storage::kStorageTypeTemporary;
+const storage::StorageType kPersistent = storage::kStorageTypePersistent;
-const quota::QuotaClient::ID kClientFile = quota::QuotaClient::kFileSystem;
+const storage::QuotaClient::ID kClientFile = storage::QuotaClient::kFileSystem;
const uint32 kAllQuotaRemoveMask =
- StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
- StoragePartition::REMOVE_DATA_MASK_WEBSQL |
+ StoragePartition::REMOVE_DATA_MASK_APPCACHE |
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
- StoragePartition::REMOVE_DATA_MASK_APPCACHE;
+ StoragePartition::REMOVE_DATA_MASK_INDEXEDDB |
+ StoragePartition::REMOVE_DATA_MASK_WEBSQL;
class AwaitCompletionHelper {
public:
@@ -225,7 +225,7 @@ bool IsWebSafeSchemeForTest(const std::string& scheme) {
bool DoesOriginMatchForUnprotectedWeb(
const GURL& origin,
- quota::SpecialStoragePolicy* special_storage_policy) {
+ storage::SpecialStoragePolicy* special_storage_policy) {
if (IsWebSafeSchemeForTest(origin.scheme()))
return !special_storage_policy->IsStorageProtected(origin.GetOrigin());
@@ -234,23 +234,22 @@ bool DoesOriginMatchForUnprotectedWeb(
bool DoesOriginMatchForBothProtectedAndUnprotectedWeb(
const GURL& origin,
- quota::SpecialStoragePolicy* special_storage_policy) {
+ storage::SpecialStoragePolicy* special_storage_policy) {
return true;
}
bool DoesOriginMatchUnprotected(
const GURL& origin,
- quota::SpecialStoragePolicy* special_storage_policy) {
+ storage::SpecialStoragePolicy* special_storage_policy) {
return origin.GetOrigin().scheme() != kOriginDevTools.scheme();
}
void ClearQuotaData(content::StoragePartition* partition,
base::RunLoop* loop_to_quit) {
- partition->ClearData(
- kAllQuotaRemoveMask,
- StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL,
- GURL(), StoragePartition::OriginMatcherFunction(),
- base::Time(), base::Time::Max(), loop_to_quit->QuitClosure());
+ partition->ClearData(kAllQuotaRemoveMask,
+ StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, GURL(),
+ StoragePartition::OriginMatcherFunction(), base::Time(),
+ base::Time::Max(), loop_to_quit->QuitClosure());
}
void ClearQuotaDataWithOriginMatcher(
@@ -280,13 +279,11 @@ void ClearQuotaDataForNonPersistent(
content::StoragePartition* partition,
const base::Time delete_begin,
base::RunLoop* loop_to_quit) {
- uint32 quota_storage_remove_mask_no_persistent =
- StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL &
- ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
partition->ClearData(
- kAllQuotaRemoveMask, quota_storage_remove_mask_no_persistent,
- GURL(), StoragePartition::OriginMatcherFunction(),
- delete_begin, base::Time::Max(), loop_to_quit->QuitClosure());
+ kAllQuotaRemoveMask,
+ ~StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT,
+ GURL(), StoragePartition::OriginMatcherFunction(), delete_begin,
+ base::Time::Max(), loop_to_quit->QuitClosure());
}
void ClearCookies(content::StoragePartition* partition,
@@ -367,7 +364,7 @@ class StoragePartitionShaderClearTest : public testing::Test {
cache_ = ShaderCacheFactory::GetInstance()->Get(kDefaultClientId);
}
- virtual ~StoragePartitionShaderClearTest() {
+ ~StoragePartitionShaderClearTest() override {
cache_ = NULL;
ShaderCacheFactory::GetInstance()->RemoveCacheInfo(kDefaultClientId);
}
@@ -416,27 +413,23 @@ TEST_F(StoragePartitionShaderClearTest, ClearShaderCache) {
}
TEST_F(StoragePartitionImplTest, QuotaClientMaskGeneration) {
- EXPECT_EQ(quota::QuotaClient::kFileSystem,
+ EXPECT_EQ(storage::QuotaClient::kFileSystem,
StoragePartitionImpl::GenerateQuotaClientMask(
StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS));
- EXPECT_EQ(quota::QuotaClient::kDatabase,
+ EXPECT_EQ(storage::QuotaClient::kDatabase,
StoragePartitionImpl::GenerateQuotaClientMask(
StoragePartition::REMOVE_DATA_MASK_WEBSQL));
- EXPECT_EQ(quota::QuotaClient::kAppcache,
+ EXPECT_EQ(storage::QuotaClient::kAppcache,
StoragePartitionImpl::GenerateQuotaClientMask(
StoragePartition::REMOVE_DATA_MASK_APPCACHE));
- EXPECT_EQ(quota::QuotaClient::kIndexedDatabase,
- StoragePartitionImpl::GenerateQuotaClientMask(
- StoragePartition::REMOVE_DATA_MASK_INDEXEDDB));
- EXPECT_EQ(quota::QuotaClient::kFileSystem |
- quota::QuotaClient::kDatabase |
- quota::QuotaClient::kAppcache |
- quota::QuotaClient::kIndexedDatabase,
+ EXPECT_EQ(storage::QuotaClient::kIndexedDatabase,
StoragePartitionImpl::GenerateQuotaClientMask(
- StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS |
- StoragePartition::REMOVE_DATA_MASK_WEBSQL |
- StoragePartition::REMOVE_DATA_MASK_APPCACHE |
StoragePartition::REMOVE_DATA_MASK_INDEXEDDB));
+ EXPECT_EQ(storage::QuotaClient::kFileSystem |
+ storage::QuotaClient::kDatabase |
+ storage::QuotaClient::kAppcache |
+ storage::QuotaClient::kIndexedDatabase,
+ StoragePartitionImpl::GenerateQuotaClientMask(kAllQuotaRemoveMask));
}
void PopulateTestQuotaManagedPersistentData(MockQuotaManager* manager) {
@@ -679,7 +672,7 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedUnprotectedOrigins) {
BrowserContext::GetDefaultStoragePartition(browser_context()));
partition->OverrideQuotaManagerForTesting(
GetMockManager());
- partition->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get());
base::RunLoop run_loop;
base::MessageLoop::current()->PostTask(
@@ -715,7 +708,7 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedSpecificOrigin) {
BrowserContext::GetDefaultStoragePartition(browser_context()));
partition->OverrideQuotaManagerForTesting(
GetMockManager());
- partition->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get());
// Try to remove kOrigin1. Expect failure.
base::RunLoop run_loop;
@@ -754,7 +747,7 @@ TEST_F(StoragePartitionImplTest, RemoveQuotaManagedProtectedOrigins) {
BrowserContext::GetDefaultStoragePartition(browser_context()));
partition->OverrideQuotaManagerForTesting(
GetMockManager());
- partition->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get());
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&ClearQuotaDataWithOriginMatcher,
@@ -855,7 +848,7 @@ TEST_F(StoragePartitionImplTest, RemoveUnprotectedLocalStorageForever) {
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context()));
- partition->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get());
base::RunLoop run_loop;
base::MessageLoop::current()->PostTask(
@@ -887,7 +880,7 @@ TEST_F(StoragePartitionImplTest, RemoveProtectedLocalStorageForever) {
StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(browser_context()));
- partition->OverrideSpecialStoragePolicyForTesting(mock_policy);
+ partition->OverrideSpecialStoragePolicyForTesting(mock_policy.get());
base::RunLoop run_loop;
base::MessageLoop::current()->PostTask(
diff --git a/chromium/content/browser/streams/stream.cc b/chromium/content/browser/streams/stream.cc
index d10770c42d2..966313cc45d 100644
--- a/chromium/content/browser/streams/stream.cc
+++ b/chromium/content/browser/streams/stream.cc
@@ -160,15 +160,9 @@ Stream::StreamState Stream::ReadRawData(net::IOBuffer* buf,
return STREAM_HAS_DATA;
}
-scoped_ptr<StreamHandle> Stream::CreateHandle(
- const GURL& original_url,
- const std::string& mime_type,
- scoped_refptr<net::HttpResponseHeaders> response_headers) {
+scoped_ptr<StreamHandle> Stream::CreateHandle() {
CHECK(!stream_handle_);
- stream_handle_ = new StreamHandleImpl(weak_ptr_factory_.GetWeakPtr(),
- original_url,
- mime_type,
- response_headers);
+ stream_handle_ = new StreamHandleImpl(weak_ptr_factory_.GetWeakPtr());
return scoped_ptr<StreamHandle>(stream_handle_).Pass();
}
diff --git a/chromium/content/browser/streams/stream.h b/chromium/content/browser/streams/stream.h
index e7e9586ca96..7c938b87c47 100644
--- a/chromium/content/browser/streams/stream.h
+++ b/chromium/content/browser/streams/stream.h
@@ -13,7 +13,6 @@
#include "url/gurl.h"
namespace net {
-class HttpResponseHeaders;
class IOBuffer;
}
@@ -78,10 +77,7 @@ class CONTENT_EXPORT Stream : public base::RefCountedThreadSafe<Stream> {
// and STREAM_COMPLETE if the stream is finalized and all data has been read.
StreamState ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
- scoped_ptr<StreamHandle> CreateHandle(
- const GURL& original_url,
- const std::string& mime_type,
- scoped_refptr<net::HttpResponseHeaders> response_headers);
+ scoped_ptr<StreamHandle> CreateHandle();
void CloseHandle();
// Indicates whether there is space in the buffer to add more data.
diff --git a/chromium/content/browser/streams/stream_handle_impl.cc b/chromium/content/browser/streams/stream_handle_impl.cc
index 6ff49621b57..5bc2acbf4fa 100644
--- a/chromium/content/browser/streams/stream_handle_impl.cc
+++ b/chromium/content/browser/streams/stream_handle_impl.cc
@@ -8,7 +8,6 @@
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
#include "content/browser/streams/stream.h"
-#include "net/http/http_response_headers.h"
namespace content {
@@ -21,16 +20,9 @@ void RunCloseListeners(const std::vector<base::Closure>& close_listeners) {
} // namespace
-StreamHandleImpl::StreamHandleImpl(
- const base::WeakPtr<Stream>& stream,
- const GURL& original_url,
- const std::string& mime_type,
- scoped_refptr<net::HttpResponseHeaders> response_headers)
+StreamHandleImpl::StreamHandleImpl(const base::WeakPtr<Stream>& stream)
: stream_(stream),
url_(stream->url()),
- original_url_(original_url),
- mime_type_(mime_type),
- response_headers_(response_headers),
stream_message_loop_(base::MessageLoopProxy::current().get()) {}
StreamHandleImpl::~StreamHandleImpl() {
@@ -43,18 +35,6 @@ const GURL& StreamHandleImpl::GetURL() {
return url_;
}
-const GURL& StreamHandleImpl::GetOriginalURL() {
- return original_url_;
-}
-
-const std::string& StreamHandleImpl::GetMimeType() {
- return mime_type_;
-}
-
-scoped_refptr<net::HttpResponseHeaders> StreamHandleImpl::GetResponseHeaders() {
- return response_headers_;
-}
-
void StreamHandleImpl::AddCloseListener(const base::Closure& callback) {
close_listeners_.push_back(callback);
}
diff --git a/chromium/content/browser/streams/stream_handle_impl.h b/chromium/content/browser/streams/stream_handle_impl.h
index dc64dade6da..d2bd94def8e 100644
--- a/chromium/content/browser/streams/stream_handle_impl.h
+++ b/chromium/content/browser/streams/stream_handle_impl.h
@@ -8,7 +8,6 @@
#include <vector>
#include "base/memory/weak_ptr.h"
-#include "base/synchronization/lock.h"
#include "content/public/browser/stream_handle.h"
namespace base {
@@ -21,25 +20,16 @@ class Stream;
class StreamHandleImpl : public StreamHandle {
public:
- StreamHandleImpl(const base::WeakPtr<Stream>& stream,
- const GURL& original_url,
- const std::string& mime_type,
- scoped_refptr<net::HttpResponseHeaders> response_headers);
- virtual ~StreamHandleImpl();
+ StreamHandleImpl(const base::WeakPtr<Stream>& stream);
+ ~StreamHandleImpl() override;
private:
// StreamHandle overrides
- virtual const GURL& GetURL() OVERRIDE;
- virtual const GURL& GetOriginalURL() OVERRIDE;
- virtual const std::string& GetMimeType() OVERRIDE;
- virtual scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders() OVERRIDE;
- virtual void AddCloseListener(const base::Closure& callback) OVERRIDE;
+ const GURL& GetURL() override;
+ void AddCloseListener(const base::Closure& callback) override;
base::WeakPtr<Stream> stream_;
GURL url_;
- GURL original_url_;
- std::string mime_type_;
- scoped_refptr<net::HttpResponseHeaders> response_headers_;
base::MessageLoopProxy* stream_message_loop_;
std::vector<base::Closure> close_listeners_;
};
diff --git a/chromium/content/browser/streams/stream_unittest.cc b/chromium/content/browser/streams/stream_unittest.cc
index a2d959305fa..e0346e5a76e 100644
--- a/chromium/content/browser/streams/stream_unittest.cc
+++ b/chromium/content/browser/streams/stream_unittest.cc
@@ -16,9 +16,7 @@ class StreamTest : public testing::Test {
public:
StreamTest() : producing_seed_key_(0) {}
- virtual void SetUp() OVERRIDE {
- registry_.reset(new StreamRegistry());
- }
+ void SetUp() override { registry_.reset(new StreamRegistry()); }
// Create a new IO buffer of the given |buffer_size| and fill it with random
// data.
@@ -43,7 +41,7 @@ class TestStreamReader : public StreamReadObserver {
public:
TestStreamReader() : buffer_(new net::GrowableIOBuffer()), completed_(false) {
}
- virtual ~TestStreamReader() {}
+ ~TestStreamReader() override {}
void Read(Stream* stream) {
const size_t kBufferSize = 32768;
@@ -76,9 +74,7 @@ class TestStreamReader : public StreamReadObserver {
}
}
- virtual void OnDataAvailable(Stream* stream) OVERRIDE {
- Read(stream);
- }
+ void OnDataAvailable(Stream* stream) override { Read(stream); }
scoped_refptr<net::GrowableIOBuffer> buffer() { return buffer_; }
@@ -94,7 +90,7 @@ class TestStreamReader : public StreamReadObserver {
class TestStreamWriter : public StreamWriteObserver {
public:
TestStreamWriter() {}
- virtual ~TestStreamWriter() {}
+ ~TestStreamWriter() override {}
void Write(Stream* stream,
scoped_refptr<net::IOBuffer> buffer,
@@ -102,11 +98,9 @@ class TestStreamWriter : public StreamWriteObserver {
stream->AddData(buffer, buffer_size);
}
- virtual void OnSpaceAvailable(Stream* stream) OVERRIDE {
- }
+ void OnSpaceAvailable(Stream* stream) override {}
- virtual void OnClose(Stream* stream) OVERRIDE {
- }
+ void OnClose(Stream* stream) override {}
};
TEST_F(StreamTest, SetReadObserver) {
diff --git a/chromium/content/browser/streams/stream_url_request_job.h b/chromium/content/browser/streams/stream_url_request_job.h
index 03187bf2399..17e7eb2e3da 100644
--- a/chromium/content/browser/streams/stream_url_request_job.h
+++ b/chromium/content/browser/streams/stream_url_request_job.h
@@ -24,22 +24,19 @@ class CONTENT_EXPORT StreamURLRequestJob
scoped_refptr<Stream> stream);
// StreamObserver methods.
- virtual void OnDataAvailable(Stream* stream) OVERRIDE;
+ void OnDataAvailable(Stream* stream) override;
// net::URLRequestJob methods.
- virtual void Start() OVERRIDE;
- virtual void Kill() OVERRIDE;
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int* bytes_read) OVERRIDE;
- virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
- virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE;
- virtual int GetResponseCode() const OVERRIDE;
- virtual void SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) OVERRIDE;
+ void Start() override;
+ void Kill() override;
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
+ bool GetMimeType(std::string* mime_type) const override;
+ void GetResponseInfo(net::HttpResponseInfo* info) override;
+ int GetResponseCode() const override;
+ void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
protected:
- virtual ~StreamURLRequestJob();
+ ~StreamURLRequestJob() override;
private:
void DidStart();
diff --git a/chromium/content/browser/streams/stream_url_request_job_unittest.cc b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
index 035a588bc96..ad33f938a71 100644
--- a/chromium/content/browser/streams/stream_url_request_job_unittest.cc
+++ b/chromium/content/browser/streams/stream_url_request_job_unittest.cc
@@ -38,9 +38,9 @@ class StreamURLRequestJobTest : public testing::Test {
MockProtocolHandler(StreamRegistry* registry) : registry_(registry) {}
// net::URLRequestJobFactory::ProtocolHandler override.
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
scoped_refptr<Stream> stream = registry_->GetStream(request->url());
if (stream.get())
return new StreamURLRequestJob(request, network_delegate, stream);
@@ -53,7 +53,7 @@ class StreamURLRequestJobTest : public testing::Test {
StreamURLRequestJobTest() {}
- virtual void SetUp() {
+ void SetUp() override {
registry_.reset(new StreamRegistry());
url_request_job_factory_.SetProtocolHandler(
@@ -61,8 +61,7 @@ class StreamURLRequestJobTest : public testing::Test {
url_request_context_.set_job_factory(&url_request_job_factory_);
}
- virtual void TearDown() {
- }
+ void TearDown() override {}
void TestSuccessRequest(const GURL& url,
const std::string& expected_response) {
diff --git a/chromium/content/browser/system_message_window_win_unittest.cc b/chromium/content/browser/system_message_window_win_unittest.cc
index 25c77c9d141..f317f7be7cc 100644
--- a/chromium/content/browser/system_message_window_win_unittest.cc
+++ b/chromium/content/browser/system_message_window_win_unittest.cc
@@ -21,7 +21,7 @@ class SystemMessageWindowWinTest : public testing::Test {
virtual ~SystemMessageWindowWinTest() { }
protected:
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
system_monitor_.AddDevicesChangedObserver(&observer_);
}
diff --git a/chromium/content/browser/tcmalloc_internals_request_job.cc b/chromium/content/browser/tcmalloc_internals_request_job.cc
index 58e78afeea2..750eae35868 100644
--- a/chromium/content/browser/tcmalloc_internals_request_job.cc
+++ b/chromium/content/browser/tcmalloc_internals_request_job.cc
@@ -5,6 +5,7 @@
#include "content/browser/tcmalloc_internals_request_job.h"
#include "base/allocator/allocator_extension.h"
+#include "base/profiler/scoped_tracker.h"
#include "content/common/child_process_messages.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
@@ -108,6 +109,11 @@ int TcmallocInternalsRequestJob::GetData(
std::string* charset,
std::string* data,
const net::CompletionCallback& callback) const {
+ // TODO(vadimt): Remove ScopedTracker below once crbug.com/422489 is fixed.
+ tracked_objects::ScopedTracker tracking_profile(
+ FROM_HERE_WITH_EXPLICIT_FUNCTION(
+ "422489 TcmallocInternalsRequestJob::GetData"));
+
mime_type->assign("text/html");
charset->assign("UTF8");
diff --git a/chromium/content/browser/tcmalloc_internals_request_job.h b/chromium/content/browser/tcmalloc_internals_request_job.h
index 20b2d4fc5f7..d6d7e008d97 100644
--- a/chromium/content/browser/tcmalloc_internals_request_job.h
+++ b/chromium/content/browser/tcmalloc_internals_request_job.h
@@ -50,13 +50,13 @@ class TcmallocInternalsRequestJob : public net::URLRequestSimpleJob {
TcmallocInternalsRequestJob(net::URLRequest* request,
net::NetworkDelegate* network_delegate);
- virtual int GetData(std::string* mime_type,
- std::string* charset,
- std::string* data,
- const net::CompletionCallback& callback) const OVERRIDE;
+ int GetData(std::string* mime_type,
+ std::string* charset,
+ std::string* data,
+ const net::CompletionCallback& callback) const override;
protected:
- virtual ~TcmallocInternalsRequestJob() {}
+ ~TcmallocInternalsRequestJob() override {}
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(TcmallocInternalsRequestJob);
diff --git a/chromium/content/browser/theme_helper_mac.h b/chromium/content/browser/theme_helper_mac.h
index 565903bbe3e..935ab3fe238 100644
--- a/chromium/content/browser/theme_helper_mac.h
+++ b/chromium/content/browser/theme_helper_mac.h
@@ -33,12 +33,12 @@ class ThemeHelperMac : public NotificationObserver {
friend struct DefaultSingletonTraits<ThemeHelperMac>;
ThemeHelperMac();
- virtual ~ThemeHelperMac();
+ ~ThemeHelperMac() override;
// Overridden from NotificationObserver:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
NotificationRegistrar registrar_;
diff --git a/chromium/content/browser/time_zone_monitor_chromeos.cc b/chromium/content/browser/time_zone_monitor_chromeos.cc
index 6fc885edba0..8c6aa0bd0a3 100644
--- a/chromium/content/browser/time_zone_monitor_chromeos.cc
+++ b/chromium/content/browser/time_zone_monitor_chromeos.cc
@@ -21,7 +21,7 @@ class TimeZoneMonitorChromeOS
}
// chromeos::system::TimezoneSettings::Observer implementation.
- virtual void TimezoneChanged(const icu::TimeZone& time_zone) OVERRIDE {
+ virtual void TimezoneChanged(const icu::TimeZone& time_zone) override {
NotifyRenderers();
}
diff --git a/chromium/content/browser/time_zone_monitor_linux.cc b/chromium/content/browser/time_zone_monitor_linux.cc
index f8cae0e2430..0836d5b8398 100644
--- a/chromium/content/browser/time_zone_monitor_linux.cc
+++ b/chromium/content/browser/time_zone_monitor_linux.cc
@@ -27,7 +27,7 @@ class TimeZoneMonitorLinuxImpl;
class TimeZoneMonitorLinux : public TimeZoneMonitor {
public:
TimeZoneMonitorLinux();
- virtual ~TimeZoneMonitorLinux();
+ ~TimeZoneMonitorLinux() override;
void NotifyRenderersFromImpl() {
NotifyRenderers();
@@ -151,7 +151,7 @@ TimeZoneMonitorLinux::TimeZoneMonitorLinux()
}
TimeZoneMonitorLinux::~TimeZoneMonitorLinux() {
- if (impl_) {
+ if (impl_.get()) {
impl_->StopWatching();
}
}
diff --git a/chromium/content/browser/time_zone_monitor_mac.mm b/chromium/content/browser/time_zone_monitor_mac.mm
index c435aae818e..700c17e6c58 100644
--- a/chromium/content/browser/time_zone_monitor_mac.mm
+++ b/chromium/content/browser/time_zone_monitor_mac.mm
@@ -21,7 +21,7 @@ class TimeZoneMonitorMac : public TimeZoneMonitor {
}];
}
- virtual ~TimeZoneMonitorMac() {
+ ~TimeZoneMonitorMac() override {
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:notification_observer_];
}
diff --git a/chromium/content/browser/time_zone_monitor_win.cc b/chromium/content/browser/time_zone_monitor_win.cc
index 6d99b940e41..2e8f9a56ed1 100644
--- a/chromium/content/browser/time_zone_monitor_win.cc
+++ b/chromium/content/browser/time_zone_monitor_win.cc
@@ -26,7 +26,7 @@ class TimeZoneMonitorWin : public TimeZoneMonitor,
virtual void OnWndProc(HWND hwnd,
UINT message,
WPARAM wparam,
- LPARAM lparam) OVERRIDE {
+ LPARAM lparam) override {
if (message != WM_TIMECHANGE) {
return;
}
diff --git a/chromium/content/browser/tracing/BUILD.gn b/chromium/content/browser/tracing/BUILD.gn
index 94694ee2fa4..ae9c7dfaf3c 100644
--- a/chromium/content/browser/tracing/BUILD.gn
+++ b/chromium/content/browser/tracing/BUILD.gn
@@ -12,14 +12,14 @@ tracing_gen_dir = "$root_gen_dir/content/browser/tracing"
tracing_grd = "$tracing_gen_dir/tracing_resources.grd"
action("generate_tracing_grd") {
- visibility = ":resources"
+ visibility = [ ":*" ]
script = "generate_trace_viewer_grd.py"
input_pages = [
"$tracing_gen_dir/about_tracing.html",
"$tracing_gen_dir/about_tracing.js",
]
- source_prereqs = input_pages
+ inputs = input_pages
outputs = [ tracing_grd ]
args = rebase_path(input_pages, target_gen_dir) + [
@@ -31,36 +31,19 @@ action("generate_tracing_grd") {
]
}
-# This can't use the grit template because the grd file is generated at build
-# time, so the trick of using grit_info to get the real inputs/outputs at GYP
-# time isn't possible.
-action("resources") {
- script = "//tools/grit/grit.py"
-
- # Get the list of grit script sources.
- grit_inputs_build_rel =
- exec_script("//tools/grit/grit_info.py", [ "--inputs" ], "list lines")
-
- source_prereqs = rebase_path(grit_inputs_build_rel, ".", root_build_dir) + [
- grit_resource_id_file,
- ]
+grit("resources") {
+ source = tracing_grd
outputs = [
- "$target_gen_dir/grit/tracing_resources.h",
- "$target_gen_dir/tracing_resources.pak",
+ "grit/tracing_resources.h",
+ "tracing_resources.pak",
]
- args = [
- "-i", rebase_path(tracing_grd, root_build_dir), "build",
- "-f", rebase_path(grit_resource_id_file, root_build_dir),
- "-o", rebase_path(target_gen_dir, root_build_dir),
- # resource_ids has an entry for our .grd file that looks like:
- # "<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.grd"
- # and what we pass here should make that resolve to our .grd file.
- "-DSHARED_INTERMEDIATE_DIR=" +
- rebase_path(root_gen_dir, root_build_dir),
- ] + grit_defines
-
- deps = [
- ":generate_tracing_grd",
+ # resource_ids has an entry for our .grd file that looks like:
+ # "<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.grd"
+ # and what we pass here should make that resolve to our .grd file.
+ defines = [
+ "SHARED_INTERMEDIATE_DIR=" + rebase_path(root_gen_dir, root_build_dir),
]
+
+ deps = [ ":generate_tracing_grd" ]
}
diff --git a/chromium/content/browser/tracing/DEPS b/chromium/content/browser/tracing/DEPS
index b4d8715021b..b99424f6482 100644
--- a/chromium/content/browser/tracing/DEPS
+++ b/chromium/content/browser/tracing/DEPS
@@ -1,4 +1,5 @@
include_rules = [
# Generated by the local tracing_resources.gyp:tracing_resources
"+grit/tracing_resources.h",
+ "+third_party/zlib/zlib.h",
]
diff --git a/chromium/content/browser/tracing/etw_system_event_consumer_win.cc b/chromium/content/browser/tracing/etw_system_event_consumer_win.cc
index df20bce41d7..fc3522fd81e 100644
--- a/chromium/content/browser/tracing/etw_system_event_consumer_win.cc
+++ b/chromium/content/browser/tracing/etw_system_event_consumer_win.cc
@@ -195,7 +195,7 @@ void EtwSystemEventConsumer::TraceAndConsumeOnThread() {
void EtwSystemEventConsumer::FlushOnThread(const OutputCallback& callback) {
// Add the header information to the stream.
scoped_ptr<base::DictionaryValue> header(new base::DictionaryValue());
- header->Set("name", base::Value::CreateStringValue("ETW"));
+ header->Set("name", new base::StringValue("ETW"));
// Release and pass the events buffer.
header->Set("content", events_.release());
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index ba8ec65de16..e74ca96caa6 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -57,12 +57,12 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
}
void TraceMessageFilter::SendBeginTracing(
- const std::string& category_filter_str,
- base::debug::TraceLog::Options options) {
+ const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& options) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- Send(new TracingMsg_BeginTracing(category_filter_str,
+ Send(new TracingMsg_BeginTracing(category_filter.ToString(),
base::TimeTicks::NowFromSystemTraceTime(),
- options));
+ options.ToString()));
}
void TraceMessageFilter::SendEndTracing() {
@@ -73,12 +73,12 @@ void TraceMessageFilter::SendEndTracing() {
}
void TraceMessageFilter::SendEnableMonitoring(
- const std::string& category_filter_str,
- base::debug::TraceLog::Options options) {
+ const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& options) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- Send(new TracingMsg_EnableMonitoring(category_filter_str,
+ Send(new TracingMsg_EnableMonitoring(category_filter.ToString(),
base::TimeTicks::NowFromSystemTraceTime(),
- options));
+ options.ToString()));
}
void TraceMessageFilter::SendDisableMonitoring() {
diff --git a/chromium/content/browser/tracing/trace_message_filter.h b/chromium/content/browser/tracing/trace_message_filter.h
index 4233fe04480..3d12d76d300 100644
--- a/chromium/content/browser/tracing/trace_message_filter.h
+++ b/chromium/content/browser/tracing/trace_message_filter.h
@@ -21,14 +21,14 @@ class TraceMessageFilter : public BrowserMessageFilter {
TraceMessageFilter();
// BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
- void SendBeginTracing(const std::string& category_filter_str,
- base::debug::TraceLog::Options options);
+ void SendBeginTracing(const base::debug::CategoryFilter& category_filter_str,
+ const base::debug::TraceOptions& options);
void SendEndTracing();
- void SendEnableMonitoring(const std::string& category_filter_str,
- base::debug::TraceLog::Options options);
+ void SendEnableMonitoring(const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& options);
void SendDisableMonitoring();
void SendCaptureMonitoringSnapshot();
void SendGetTraceBufferPercentFull();
@@ -37,7 +37,7 @@ class TraceMessageFilter : public BrowserMessageFilter {
void SendCancelWatchEvent();
protected:
- virtual ~TraceMessageFilter();
+ ~TraceMessageFilter() override;
private:
// Message handlers.
diff --git a/chromium/content/browser/tracing/trace_uploader.cc b/chromium/content/browser/tracing/trace_uploader.cc
new file mode 100644
index 00000000000..3bcc1872817
--- /dev/null
+++ b/chromium/content/browser/tracing/trace_uploader.cc
@@ -0,0 +1,210 @@
+// Copyright 2014 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 "content/browser/tracing/trace_uploader.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/memory/shared_memory.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/mime_util.h"
+#include "net/base/network_delegate.h"
+#include "net/proxy/proxy_config.h"
+#include "net/proxy/proxy_config_service.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_builder.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "third_party/zlib/zlib.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+const char kUploadContentType[] = "multipart/form-data";
+const char kMultipartBoundary[] =
+ "----**--yradnuoBgoLtrapitluMklaTelgooG--**----";
+
+const int kHttpResponseOk = 200;
+
+} // namespace
+
+TraceUploader::TraceUploader(const std::string& product,
+ const std::string& version,
+ const std::string& upload_url,
+ net::URLRequestContextGetter* request_context)
+ : product_(product),
+ version_(version),
+ upload_url_(upload_url),
+ request_context_(request_context) {
+ DCHECK(!product_.empty());
+ DCHECK(!version_.empty());
+ DCHECK(!upload_url_.empty());
+}
+
+TraceUploader::~TraceUploader() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+void TraceUploader::OnURLFetchComplete(const net::URLFetcher* source) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(source, url_fetcher_.get());
+ int response_code = source->GetResponseCode();
+ string report_id;
+ string error_message;
+ bool success = (response_code == kHttpResponseOk);
+ if (success) {
+ source->GetResponseAsString(&report_id);
+ } else {
+ error_message = "Uploading failed, response code: " +
+ base::IntToString(response_code);
+ }
+
+ BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(done_callback_, success, report_id, error_message));
+ url_fetcher_.reset();
+}
+
+void TraceUploader::OnURLFetchUploadProgress(
+ const net::URLFetcher* source, int64 current, int64 total) {
+ DCHECK(url_fetcher_.get());
+
+ LOG(WARNING) << "Upload progress: " << current << " of " << total;
+ BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(progress_callback_, current, total));
+}
+
+void TraceUploader::DoUpload(
+ const std::string& file_contents,
+ UploadProgressCallback progress_callback,
+ UploadDoneCallback done_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ DCHECK(!url_fetcher_.get());
+
+ progress_callback_ = progress_callback;
+ done_callback_ = done_callback;
+
+ if (url_fetcher_.get()) {
+ OnUploadError("Already uploading.");
+ }
+
+ scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]);
+ int compressed_bytes;
+ if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(),
+ &compressed_bytes)) {
+ OnUploadError("Compressing file failed.");
+ return;
+ }
+
+ std::string post_data;
+ SetupMultipart("trace.json.gz",
+ std::string(compressed_contents.get(), compressed_bytes),
+ &post_data);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&TraceUploader::CreateAndStartURLFetcher,
+ base::Unretained(this),
+ post_data));
+}
+
+void TraceUploader::OnUploadError(std::string error_message) {
+ LOG(ERROR) << error_message;
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(done_callback_, false, "", error_message));
+}
+
+void TraceUploader::SetupMultipart(const std::string& trace_filename,
+ const std::string& trace_contents,
+ std::string* post_data) {
+ net::AddMultipartValueForUpload("prod", product_, kMultipartBoundary, "",
+ post_data);
+ net::AddMultipartValueForUpload("ver", version_ + "-trace",
+ kMultipartBoundary, "", post_data);
+ net::AddMultipartValueForUpload("guid", "0", kMultipartBoundary,
+ "", post_data);
+ net::AddMultipartValueForUpload("type", "trace", kMultipartBoundary,
+ "", post_data);
+ // No minidump means no need for crash to process the report.
+ net::AddMultipartValueForUpload("should_process", "false", kMultipartBoundary,
+ "", post_data);
+
+ AddTraceFile(trace_filename, trace_contents, post_data);
+
+ net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data);
+}
+
+void TraceUploader::AddTraceFile(const std::string& trace_filename,
+ const std::string& trace_contents,
+ std::string* post_data) {
+ post_data->append("--");
+ post_data->append(kMultipartBoundary);
+ post_data->append("\r\n");
+ post_data->append("Content-Disposition: form-data; name=\"trace\"");
+ post_data->append("; filename=\"");
+ post_data->append(trace_filename);
+ post_data->append("\"\r\n");
+ post_data->append("Content-Type: application/gzip\r\n\r\n");
+ post_data->append(trace_contents);
+ post_data->append("\r\n");
+}
+
+bool TraceUploader::Compress(std::string input,
+ int max_compressed_bytes,
+ char* compressed,
+ int* compressed_bytes) {
+ DCHECK(compressed);
+ DCHECK(compressed_bytes);
+ z_stream stream = {0};
+ int result = deflateInit2(&stream,
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ // 16 is added to produce a gzip header + trailer.
+ MAX_WBITS + 16,
+ 8, // memLevel = 8 is default.
+ Z_DEFAULT_STRATEGY);
+ DCHECK_EQ(Z_OK, result);
+ stream.next_in = reinterpret_cast<uint8*>(&input[0]);
+ stream.avail_in = input.size();
+ stream.next_out = reinterpret_cast<uint8*>(compressed);
+ stream.avail_out = max_compressed_bytes;
+ // Do a one-shot compression. This will return Z_STREAM_END only if |output|
+ // is large enough to hold all compressed data.
+ result = deflate(&stream, Z_FINISH);
+ bool success = (result == Z_STREAM_END);
+ result = deflateEnd(&stream);
+ DCHECK(result == Z_OK || result == Z_DATA_ERROR);
+
+ if (success)
+ *compressed_bytes = max_compressed_bytes - stream.avail_out;
+
+ LOG(WARNING) << "input size: " << input.size()
+ << ", output size: " << *compressed_bytes;
+ return success;
+}
+
+void TraceUploader::CreateAndStartURLFetcher(const std::string& post_data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(!url_fetcher_.get());
+
+ std::string content_type = kUploadContentType;
+ content_type.append("; boundary=");
+ content_type.append(kMultipartBoundary);
+
+ url_fetcher_.reset(
+ net::URLFetcher::Create(GURL(upload_url_), net::URLFetcher::POST, this));
+ url_fetcher_->SetRequestContext(request_context_);
+ url_fetcher_->SetUploadData(content_type, post_data);
+ url_fetcher_->Start();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/trace_uploader.h b/chromium/content/browser/tracing/trace_uploader.h
new file mode 100644
index 00000000000..323a4c54668
--- /dev/null
+++ b/chromium/content/browser/tracing/trace_uploader.h
@@ -0,0 +1,92 @@
+// Copyright 2014 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 CONTENT_BROWSER_TRACING_TRACE_UPLOADER_H_
+#define CONTENT_BROWSER_TRACING_TRACE_UPLOADER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "net/url_request/url_fetcher_delegate.h"
+
+namespace net {
+class URLFetcher;
+class URLRequestContextGetter;
+} // namespace net
+
+namespace content {
+
+namespace {
+
+// Allow up to 10MB for trace upload
+const int kMaxUploadBytes = 10000000;
+
+} // namespace
+
+// TraceUploader uploads traces.
+class TraceUploader : public net::URLFetcherDelegate {
+ public:
+ typedef base::Callback<void(bool, const std::string&, const std::string&)>
+ UploadDoneCallback;
+ typedef base::Callback<void(int64, int64)> UploadProgressCallback;
+
+ TraceUploader(const std::string& product,
+ const std::string& version,
+ const std::string& upload_url,
+ net::URLRequestContextGetter* request_context);
+ ~TraceUploader() override;
+
+ // net::URLFetcherDelegate implementation.
+ void OnURLFetchComplete(const net::URLFetcher* source) override;
+ void OnURLFetchUploadProgress(const net::URLFetcher* source,
+ int64 current,
+ int64 total) override;
+
+ // Compresses and uploads the given file contents.
+ void DoUpload(const std::string& file_contents,
+ UploadProgressCallback progress_callback,
+ UploadDoneCallback done_callback);
+
+ private:
+ // Sets up a multipart body to be uploaded. The body is produced according
+ // to RFC 2046.
+ void SetupMultipart(const std::string& trace_filename,
+ const std::string& trace_contents,
+ std::string* post_data);
+ void AddTraceFile(const std::string& trace_filename,
+ const std::string& trace_contents,
+ std::string* post_data);
+ // Compresses the input and returns whether compression was successful.
+ bool Compress(std::string input,
+ int max_compressed_bytes,
+ char* compressed_contents,
+ int* compressed_bytes);
+ void CreateAndStartURLFetcher(const std::string& post_data);
+ void OnUploadError(std::string error_message);
+
+ std::string product_;
+ std::string version_;
+
+ std::string upload_url_;
+
+ scoped_ptr<net::URLFetcher> url_fetcher_;
+ UploadProgressCallback progress_callback_;
+ UploadDoneCallback done_callback_;
+
+ net::URLRequestContextGetter* request_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(TraceUploader);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_TRACING_TRACE_UPLOADER_H_
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index 36f0dce85a8..cb74923afc1 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -2,21 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/file_util.h"
+#include "base/files/file_util.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
-#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/browser/tracing_controller.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
+using base::debug::CategoryFilter;
+using base::debug::TraceOptions;
+using base::debug::RECORD_CONTINUOUSLY;
+using base::debug::RECORD_UNTIL_FULL;
+
namespace content {
class TracingControllerTest : public ContentBrowserTest {
public:
TracingControllerTest() {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
get_categories_done_callback_count_ = 0;
enable_recording_done_callback_count_ = 0;
disable_recording_done_callback_count_ = 0;
@@ -26,9 +32,7 @@ class TracingControllerTest : public ContentBrowserTest {
ContentBrowserTest::SetUp();
}
- virtual void TearDown() OVERRIDE {
- ContentBrowserTest::TearDown();
- }
+ void TearDown() override { ContentBrowserTest::TearDown(); }
void Navigate(Shell* shell) {
NavigateToURL(shell, GetTestUrl("", "title.html"));
@@ -46,8 +50,15 @@ class TracingControllerTest : public ContentBrowserTest {
quit_callback.Run();
}
- void DisableRecordingDoneCallbackTest(base::Closure quit_callback,
- const base::FilePath& file_path) {
+ void DisableRecordingStringDoneCallbackTest(base::Closure quit_callback,
+ base::RefCountedString* data) {
+ disable_recording_done_callback_count_++;
+ EXPECT_TRUE(data->size() > 0);
+ quit_callback.Run();
+ }
+
+ void DisableRecordingFileDoneCallbackTest(base::Closure quit_callback,
+ const base::FilePath& file_path) {
disable_recording_done_callback_count_++;
EXPECT_TRUE(PathExists(file_path));
int64 file_size;
@@ -110,7 +121,7 @@ class TracingControllerTest : public ContentBrowserTest {
return last_actual_monitoring_file_path_;
}
- void TestEnableAndDisableRecording(const base::FilePath& result_file_path) {
+ void TestEnableAndDisableRecordingString() {
Navigate(shell());
TracingController* controller = TracingController::GetInstance();
@@ -122,7 +133,7 @@ class TracingControllerTest : public ContentBrowserTest {
base::Unretained(this),
run_loop.QuitClosure());
bool result = controller->EnableRecording(
- "", TracingController::DEFAULT_OPTIONS, callback);
+ CategoryFilter(), TraceOptions(), callback);
ASSERT_TRUE(result);
run_loop.Run();
EXPECT_EQ(enable_recording_done_callback_count(), 1);
@@ -130,11 +141,46 @@ class TracingControllerTest : public ContentBrowserTest {
{
base::RunLoop run_loop;
- TracingController::TracingFileResultCallback callback =
- base::Bind(&TracingControllerTest::DisableRecordingDoneCallbackTest,
+ base::Callback<void(base::RefCountedString*)> callback = base::Bind(
+ &TracingControllerTest::DisableRecordingStringDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure());
+ bool result = controller->DisableRecording(
+ TracingController::CreateStringSink(callback));
+ ASSERT_TRUE(result);
+ run_loop.Run();
+ EXPECT_EQ(disable_recording_done_callback_count(), 1);
+ }
+ }
+
+ void TestEnableAndDisableRecordingFile(
+ const base::FilePath& result_file_path) {
+ Navigate(shell());
+
+ TracingController* controller = TracingController::GetInstance();
+
+ {
+ base::RunLoop run_loop;
+ TracingController::EnableRecordingDoneCallback callback =
+ base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest,
base::Unretained(this),
run_loop.QuitClosure());
- bool result = controller->DisableRecording(result_file_path, callback);
+ bool result = controller->EnableRecording(
+ CategoryFilter(), TraceOptions(), callback);
+ ASSERT_TRUE(result);
+ run_loop.Run();
+ EXPECT_EQ(enable_recording_done_callback_count(), 1);
+ }
+
+ {
+ base::RunLoop run_loop;
+ base::Closure callback = base::Bind(
+ &TracingControllerTest::DisableRecordingFileDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure(),
+ result_file_path);
+ bool result = controller->DisableRecording(
+ TracingController::CreateFileSink(result_file_path, callback));
ASSERT_TRUE(result);
run_loop.Run();
EXPECT_EQ(disable_recording_done_callback_count(), 1);
@@ -149,16 +195,15 @@ class TracingControllerTest : public ContentBrowserTest {
{
bool is_monitoring;
- std::string category_filter;
- TracingController::Options options;
- controller->GetMonitoringStatus(&is_monitoring,
- &category_filter,
- &options);
+ CategoryFilter category_filter("");
+ TraceOptions options;
+ controller->GetMonitoringStatus(
+ &is_monitoring, &category_filter, &options);
EXPECT_FALSE(is_monitoring);
- EXPECT_EQ("-*Debug,-*Test", category_filter);
- EXPECT_FALSE(options & TracingController::ENABLE_SYSTRACE);
- EXPECT_FALSE(options & TracingController::RECORD_CONTINUOUSLY);
- EXPECT_FALSE(options & TracingController::ENABLE_SAMPLING);
+ EXPECT_EQ("-*Debug,-*Test", category_filter.ToString());
+ EXPECT_FALSE(options.record_mode == RECORD_CONTINUOUSLY);
+ EXPECT_FALSE(options.enable_sampling);
+ EXPECT_FALSE(options.enable_systrace);
}
{
@@ -167,8 +212,14 @@ class TracingControllerTest : public ContentBrowserTest {
base::Bind(&TracingControllerTest::EnableMonitoringDoneCallbackTest,
base::Unretained(this),
run_loop.QuitClosure());
+
+ TraceOptions trace_options;
+ trace_options.enable_sampling = true;
+
bool result = controller->EnableMonitoring(
- "*", TracingController::ENABLE_SAMPLING, callback);
+ CategoryFilter("*"),
+ trace_options,
+ callback);
ASSERT_TRUE(result);
run_loop.Run();
EXPECT_EQ(enable_monitoring_done_callback_count(), 1);
@@ -176,27 +227,26 @@ class TracingControllerTest : public ContentBrowserTest {
{
bool is_monitoring;
- std::string category_filter;
- TracingController::Options options;
- controller->GetMonitoringStatus(&is_monitoring,
- &category_filter,
- &options);
+ CategoryFilter category_filter("");
+ TraceOptions options;
+ controller->GetMonitoringStatus(
+ &is_monitoring, &category_filter, &options);
EXPECT_TRUE(is_monitoring);
- EXPECT_EQ("*", category_filter);
- EXPECT_FALSE(options & TracingController::ENABLE_SYSTRACE);
- EXPECT_FALSE(options & TracingController::RECORD_CONTINUOUSLY);
- EXPECT_TRUE(options & TracingController::ENABLE_SAMPLING);
+ EXPECT_EQ("*", category_filter.ToString());
+ EXPECT_FALSE(options.record_mode == RECORD_CONTINUOUSLY);
+ EXPECT_TRUE(options.enable_sampling);
+ EXPECT_FALSE(options.enable_systrace);
}
{
base::RunLoop run_loop;
- TracingController::TracingFileResultCallback callback =
- base::Bind(&TracingControllerTest::
- CaptureMonitoringSnapshotDoneCallbackTest,
- base::Unretained(this),
- run_loop.QuitClosure());
- ASSERT_TRUE(controller->CaptureMonitoringSnapshot(result_file_path,
- callback));
+ base::Closure callback = base::Bind(
+ &TracingControllerTest::CaptureMonitoringSnapshotDoneCallbackTest,
+ base::Unretained(this),
+ run_loop.QuitClosure(),
+ result_file_path);
+ ASSERT_TRUE(controller->CaptureMonitoringSnapshot(
+ TracingController::CreateFileSink(result_file_path, callback)));
run_loop.Run();
EXPECT_EQ(capture_monitoring_snapshot_done_callback_count(), 1);
}
@@ -215,16 +265,16 @@ class TracingControllerTest : public ContentBrowserTest {
{
bool is_monitoring;
- std::string category_filter;
- TracingController::Options options;
+ CategoryFilter category_filter("");
+ TraceOptions options;
controller->GetMonitoringStatus(&is_monitoring,
&category_filter,
&options);
EXPECT_FALSE(is_monitoring);
- EXPECT_EQ("", category_filter);
- EXPECT_FALSE(options & TracingController::ENABLE_SYSTRACE);
- EXPECT_FALSE(options & TracingController::RECORD_CONTINUOUSLY);
- EXPECT_FALSE(options & TracingController::ENABLE_SAMPLING);
+ EXPECT_EQ("", category_filter.ToString());
+ EXPECT_FALSE(options.record_mode == RECORD_CONTINUOUSLY);
+ EXPECT_FALSE(options.enable_sampling);
+ EXPECT_FALSE(options.enable_systrace);
}
}
@@ -255,14 +305,14 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) {
}
IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) {
- TestEnableAndDisableRecording(base::FilePath());
+ TestEnableAndDisableRecordingString();
}
IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EnableAndDisableRecordingWithFilePath) {
base::FilePath file_path;
base::CreateTemporaryFile(&file_path);
- TestEnableAndDisableRecording(file_path);
+ TestEnableAndDisableRecordingFile(file_path);
EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value());
}
@@ -272,16 +322,18 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
TracingController* controller = TracingController::GetInstance();
EXPECT_TRUE(controller->EnableRecording(
- "", TracingController::DEFAULT_OPTIONS,
+ CategoryFilter(),
+ TraceOptions(),
TracingController::EnableRecordingDoneCallback()));
- EXPECT_TRUE(controller->DisableRecording(
- base::FilePath(), TracingController::TracingFileResultCallback()));
+ EXPECT_TRUE(controller->DisableRecording(NULL));
base::RunLoop().RunUntilIdle();
}
IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EnableCaptureAndDisableMonitoring) {
- TestEnableCaptureAndDisableMonitoring(base::FilePath());
+ base::FilePath file_path;
+ base::CreateTemporaryFile(&file_path);
+ TestEnableCaptureAndDisableMonitoring(file_path);
}
IN_PROC_BROWSER_TEST_F(TracingControllerTest,
@@ -292,17 +344,27 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
EXPECT_EQ(file_path.value(), last_actual_monitoring_file_path().value());
}
+// See http://crbug.com/392446
+#if defined(OS_ANDROID)
+#define MAYBE_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback \
+ DISABLED_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback
+#else
+#define MAYBE_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback \
+ EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback
+#endif
IN_PROC_BROWSER_TEST_F(
TracingControllerTest,
- EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback) {
+ MAYBE_EnableCaptureAndDisableMonitoringWithEmptyFileAndNullCallback) {
Navigate(shell());
TracingController* controller = TracingController::GetInstance();
+ TraceOptions trace_options;
+ trace_options.enable_sampling = true;
EXPECT_TRUE(controller->EnableMonitoring(
- "*", TracingController::ENABLE_SAMPLING,
+ CategoryFilter("*"),
+ trace_options,
TracingController::EnableMonitoringDoneCallback()));
- controller->CaptureMonitoringSnapshot(
- base::FilePath(), TracingController::TracingFileResultCallback());
+ controller->CaptureMonitoringSnapshot(NULL);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(controller->DisableMonitoring(
TracingController::DisableMonitoringDoneCallback()));
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 63a44fcbcbf..3e8e1ac7cd1 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -5,8 +5,9 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/json/string_escape.h"
+#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_ui.h"
@@ -24,6 +25,8 @@
#endif
using base::debug::TraceLog;
+using base::debug::TraceOptions;
+using base::debug::CategoryFilter;
namespace content {
@@ -32,134 +35,133 @@ namespace {
base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
LAZY_INSTANCE_INITIALIZER;
-} // namespace
-
-TracingController* TracingController::GetInstance() {
- return TracingControllerImpl::GetInstance();
-}
-
-class TracingControllerImpl::ResultFile {
+class FileTraceDataSink : public TracingController::TraceDataSink {
public:
- explicit ResultFile(const base::FilePath& path);
- void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::ResultFile::WriteTask,
- base::Unretained(this), events_str_ptr));
+ explicit FileTraceDataSink(const base::FilePath& trace_file_path,
+ const base::Closure& callback)
+ : file_path_(trace_file_path),
+ completion_callback_(callback),
+ file_(NULL) {}
+
+ void AddTraceChunk(const std::string& chunk) override {
+ std::string tmp = chunk;
+ scoped_refptr<base::RefCountedString> chunk_ptr =
+ base::RefCountedString::TakeString(&tmp);
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(
+ &FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr));
}
- void Close(const base::Closure& callback) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::ResultFile::CloseTask,
- base::Unretained(this), callback));
+ void SetSystemTrace(const std::string& data) override {
+ system_trace_ = data;
}
- void WriteSystemTrace(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
+ void Close() override {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
- base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask,
- base::Unretained(this), events_str_ptr));
+ base::Bind(&FileTraceDataSink::CloseOnFileThread, this));
}
- const base::FilePath& path() const { return path_; }
-
private:
- void OpenTask();
- void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr);
- void WriteSystemTraceTask(
- const scoped_refptr<base::RefCountedString>& events_str_ptr);
- void CloseTask(const base::Closure& callback);
+ ~FileTraceDataSink() override { DCHECK(file_ == NULL); }
+
+ void AddTraceChunkOnFileThread(
+ const scoped_refptr<base::RefCountedString> chunk) {
+ if (file_ != NULL)
+ fputc(',', file_);
+ else if (!OpenFileIfNeededOnFileThread())
+ return;
+ ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()),
+ 1, file_));
+ }
+
+ bool OpenFileIfNeededOnFileThread() {
+ if (file_ != NULL)
+ return true;
+ file_ = base::OpenFile(file_path_, "w");
+ if (file_ == NULL) {
+ LOG(ERROR) << "Failed to open " << file_path_.value();
+ return false;
+ }
+ const char preamble[] = "{\"traceEvents\": [";
+ ignore_result(fwrite(preamble, strlen(preamble), 1, file_));
+ return true;
+ }
+
+ void CloseOnFileThread() {
+ if (OpenFileIfNeededOnFileThread()) {
+ fputc(']', file_);
+ if (!system_trace_.empty()) {
+ const char systemTraceEvents[] = ",\"systemTraceEvents\": ";
+ ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents),
+ 1, file_));
+ ignore_result(fwrite(system_trace_.c_str(),
+ strlen(system_trace_.c_str()), 1, file_));
+ }
+ fputc('}', file_);
+ base::CloseFile(file_);
+ file_ = NULL;
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this));
+ }
+ void FinalizeOnUIThread() { completion_callback_.Run(); }
+
+ base::FilePath file_path_;
+ base::Closure completion_callback_;
FILE* file_;
- base::FilePath path_;
- bool has_at_least_one_result_;
- scoped_refptr<base::RefCountedString> system_trace_;
+ std::string system_trace_;
- DISALLOW_COPY_AND_ASSIGN(ResultFile);
+ DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink);
};
-TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path)
- : file_(NULL),
- path_(path),
- has_at_least_one_result_(false) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::ResultFile::OpenTask,
- base::Unretained(this)));
-}
-
-void TracingControllerImpl::ResultFile::OpenTask() {
- if (path_.empty())
- base::CreateTemporaryFile(&path_);
- file_ = base::OpenFile(path_, "w");
- if (!file_) {
- LOG(ERROR) << "Failed to open " << path_.value();
- return;
- }
- const char* preamble = "{\"traceEvents\": [";
- size_t written = fwrite(preamble, strlen(preamble), 1, file_);
- DCHECK(written == 1);
-}
+class StringTraceDataSink : public TracingController::TraceDataSink {
+ public:
+ typedef base::Callback<void(base::RefCountedString*)> CompletionCallback;
-void TracingControllerImpl::ResultFile::WriteTask(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- if (!file_ || !events_str_ptr->data().size())
- return;
+ explicit StringTraceDataSink(CompletionCallback callback)
+ : completion_callback_(callback) {}
- // If there is already a result in the file, then put a comma
- // before the next batch of results.
- if (has_at_least_one_result_) {
- size_t written = fwrite(",", 1, 1, file_);
- DCHECK(written == 1);
+ // TracingController::TraceDataSink implementation
+ void AddTraceChunk(const std::string& chunk) override {
+ if (!trace_.empty())
+ trace_ += ",";
+ trace_ += chunk;
}
- has_at_least_one_result_ = true;
- size_t written = fwrite(events_str_ptr->data().c_str(),
- events_str_ptr->data().size(), 1,
- file_);
- DCHECK(written == 1);
-}
-
-void TracingControllerImpl::ResultFile::WriteSystemTraceTask(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- system_trace_ = events_str_ptr;
-}
-
-void TracingControllerImpl::ResultFile::CloseTask(
- const base::Closure& callback) {
- if (!file_)
- return;
-
- const char* trailevents = "]";
- size_t written = fwrite(trailevents, strlen(trailevents), 1, file_);
- DCHECK(written == 1);
+ void SetSystemTrace(const std::string& data) override {
+ system_trace_ = data;
+ }
+ void Close() override {
+ std::string result = "{\"traceEvents\":[" + trace_ + "]";
+ if (!system_trace_.empty())
+ result += ",\"systemTraceEvents\": " + system_trace_;
+ result += "}";
- if (system_trace_) {
-#if defined(OS_WIN)
- // The Windows kernel events are kept into a JSon format stored as string
- // and must not be escaped.
- std::string json_string = system_trace_->data();
-#else
- std::string json_string = base::GetQuotedJSONString(system_trace_->data());
-#endif
+ scoped_refptr<base::RefCountedString> str =
+ base::RefCountedString::TakeString(&result);
+ completion_callback_.Run(str.get());
+ }
- const char* systemTraceHead = ",\n\"systemTraceEvents\": ";
- written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_);
- DCHECK(written == 1);
+ private:
+ ~StringTraceDataSink() override {}
- written = fwrite(json_string.data(), json_string.size(), 1, file_);
- DCHECK(written == 1);
+ std::string trace_;
+ std::string system_trace_;
+ CompletionCallback completion_callback_;
- system_trace_ = NULL;
- }
+ DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink);
+};
- const char* trailout = "}";
- written = fwrite(trailout, strlen(trailout), 1, file_);
- DCHECK(written == 1);
- base::CloseFile(file_);
- file_ = NULL;
+} // namespace
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
+TracingController* TracingController::GetInstance() {
+ return TracingControllerImpl::GetInstance();
}
-
TracingControllerImpl::TracingControllerImpl() :
pending_disable_recording_ack_count_(0),
pending_capture_monitoring_snapshot_ack_count_(0),
@@ -191,28 +193,26 @@ bool TracingControllerImpl::GetCategories(
// message. So to get known categories, just begin and end tracing immediately
// afterwards. This will ping all the child processes for categories.
pending_get_categories_done_callback_ = callback;
- if (!EnableRecording("*", TracingController::Options(),
- EnableRecordingDoneCallback())) {
+ if (!EnableRecording(
+ CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) {
pending_get_categories_done_callback_.Reset();
return false;
}
- bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback());
+ bool ok = DisableRecording(NULL);
DCHECK(ok);
return true;
}
void TracingControllerImpl::SetEnabledOnFileThread(
- const std::string& category_filter,
+ const CategoryFilter& category_filter,
int mode,
- int trace_options,
+ const TraceOptions& trace_options,
const base::Closure& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
TraceLog::GetInstance()->SetEnabled(
- base::debug::CategoryFilter(category_filter),
- static_cast<TraceLog::Mode>(mode),
- static_cast<TraceLog::Options>(trace_options));
+ category_filter, static_cast<TraceLog::Mode>(mode), trace_options);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
}
@@ -225,8 +225,8 @@ void TracingControllerImpl::SetDisabledOnFileThread(
}
bool TracingControllerImpl::EnableRecording(
- const std::string& category_filter,
- TracingController::Options options,
+ const CategoryFilter& category_filter,
+ const TraceOptions& trace_options,
const EnableRecordingDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -239,14 +239,9 @@ bool TracingControllerImpl::EnableRecording(
TraceLog::GetInstance()->AddClockSyncMetadataEvent();
#endif
- options_ = options;
- int trace_options = (options & RECORD_CONTINUOUSLY) ?
- TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL;
- if (options & ENABLE_SAMPLING) {
- trace_options |= TraceLog::ENABLE_SAMPLING;
- }
+ trace_options_ = trace_options;
- if (options & ENABLE_SYSTRACE) {
+ if (trace_options.enable_systrace) {
#if defined(OS_CHROMEOS)
DCHECK(!is_system_tracing_);
chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
@@ -275,16 +270,15 @@ bool TracingControllerImpl::EnableRecording(
}
void TracingControllerImpl::OnEnableRecordingDone(
- const std::string& category_filter,
- int trace_options,
+ const CategoryFilter& category_filter,
+ const TraceOptions& trace_options,
const EnableRecordingDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Notify all child processes.
for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
it != trace_message_filters_.end(); ++it) {
- it->get()->SendBeginTracing(category_filter,
- static_cast<TraceLog::Options>(trace_options));
+ it->get()->SendBeginTracing(category_filter, trace_options);
}
if (!callback.is_null())
@@ -292,20 +286,18 @@ void TracingControllerImpl::OnEnableRecordingDone(
}
bool TracingControllerImpl::DisableRecording(
- const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) {
+ const scoped_refptr<TraceDataSink>& trace_data_sink) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!can_disable_recording())
return false;
- options_ = TracingController::Options();
+ trace_data_sink_ = trace_data_sink;
+ trace_options_ = TraceOptions();
// Disable local trace early to avoid traces during end-tracing process from
// interfering with the process.
- base::Closure on_disable_recording_done_callback =
- base::Bind(&TracingControllerImpl::OnDisableRecordingDone,
- base::Unretained(this),
- result_file_path, callback);
+ base::Closure on_disable_recording_done_callback = base::Bind(
+ &TracingControllerImpl::OnDisableRecordingDone, base::Unretained(this));
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
base::Unretained(this),
@@ -313,21 +305,14 @@ bool TracingControllerImpl::DisableRecording(
return true;
}
-void TracingControllerImpl::OnDisableRecordingDone(
- const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) {
+void TracingControllerImpl::OnDisableRecordingDone() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- pending_disable_recording_done_callback_ = callback;
-
#if defined(OS_ANDROID)
if (pending_get_categories_done_callback_.is_null())
TraceLog::GetInstance()->AddClockSyncMetadataEvent();
#endif
- if (!callback.is_null() || !result_file_path.empty())
- result_file_.reset(new ResultFile(result_file_path));
-
// Count myself (local trace) in pending_disable_recording_ack_count_,
// acked below.
pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
@@ -340,10 +325,14 @@ void TracingControllerImpl::OnDisableRecordingDone(
++pending_disable_recording_ack_count_;
#if defined(OS_CHROMEOS)
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->
- RequestStopSystemTracing(
- base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
- base::Unretained(this)));
+ scoped_refptr<base::TaskRunner> task_runner =
+ BrowserThread::GetBlockingPool();
+ chromeos::DBusThreadManager::Get()
+ ->GetDebugDaemonClient()
+ ->RequestStopSystemTracing(
+ task_runner,
+ base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
+ base::Unretained(this)));
#elif defined(OS_WIN)
EtwSystemEventConsumer::GetInstance()->StopSystemTracing(
base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked,
@@ -370,8 +359,8 @@ void TracingControllerImpl::OnDisableRecordingDone(
}
bool TracingControllerImpl::EnableMonitoring(
- const std::string& category_filter,
- TracingController::Options options,
+ const CategoryFilter& category_filter,
+ const TraceOptions& trace_options,
const EnableMonitoringDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -383,10 +372,7 @@ bool TracingControllerImpl::EnableMonitoring(
TraceLog::GetInstance()->AddClockSyncMetadataEvent();
#endif
- options_ = options;
- int trace_options = 0;
- if (options & ENABLE_SAMPLING)
- trace_options |= TraceLog::ENABLE_SAMPLING;
+ trace_options_ = trace_options;
base::Closure on_enable_monitoring_done_callback =
base::Bind(&TracingControllerImpl::OnEnableMonitoringDone,
@@ -403,16 +389,15 @@ bool TracingControllerImpl::EnableMonitoring(
}
void TracingControllerImpl::OnEnableMonitoringDone(
- const std::string& category_filter,
- int trace_options,
+ const CategoryFilter& category_filter,
+ const TraceOptions& trace_options,
const EnableMonitoringDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// Notify all child processes.
for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
it != trace_message_filters_.end(); ++it) {
- it->get()->SendEnableMonitoring(category_filter,
- static_cast<TraceLog::Options>(trace_options));
+ it->get()->SendEnableMonitoring(category_filter, trace_options);
}
if (!callback.is_null())
@@ -426,7 +411,7 @@ bool TracingControllerImpl::DisableMonitoring(
if (!can_disable_monitoring())
return false;
- options_ = TracingController::Options();
+ trace_options_ = TraceOptions();
base::Closure on_disable_monitoring_done_callback =
base::Bind(&TracingControllerImpl::OnDisableMonitoringDone,
base::Unretained(this), callback);
@@ -437,6 +422,18 @@ bool TracingControllerImpl::DisableMonitoring(
return true;
}
+scoped_refptr<TracingController::TraceDataSink>
+TracingController::CreateStringSink(
+ const base::Callback<void(base::RefCountedString*)>& callback) {
+ return new StringTraceDataSink(callback);
+}
+
+scoped_refptr<TracingController::TraceDataSink>
+TracingController::CreateFileSink(const base::FilePath& file_path,
+ const base::Closure& callback) {
+ return new FileTraceDataSink(file_path, callback);
+}
+
void TracingControllerImpl::OnDisableMonitoringDone(
const DisableMonitoringDoneCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -448,34 +445,30 @@ void TracingControllerImpl::OnDisableMonitoringDone(
it != trace_message_filters_.end(); ++it) {
it->get()->SendDisableMonitoring();
}
-
if (!callback.is_null())
callback.Run();
}
void TracingControllerImpl::GetMonitoringStatus(
bool* out_enabled,
- std::string* out_category_filter,
- TracingController::Options* out_options) {
+ CategoryFilter* out_category_filter,
+ TraceOptions* out_trace_options) {
*out_enabled = is_monitoring_;
- *out_category_filter =
- TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString();
- *out_options = options_;
+ *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter();
+ *out_trace_options = trace_options_;
}
bool TracingControllerImpl::CaptureMonitoringSnapshot(
- const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) {
+ const scoped_refptr<TraceDataSink>& monitoring_data_sink) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!can_disable_monitoring())
return false;
- if (callback.is_null() && result_file_path.empty())
+ if (!monitoring_data_sink.get())
return false;
- pending_capture_monitoring_snapshot_done_callback_ = callback;
- monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
+ monitoring_data_sink_ = monitoring_data_sink;
// Count myself in pending_capture_monitoring_snapshot_ack_count_,
// acked below.
@@ -595,13 +588,13 @@ void TracingControllerImpl::AddTraceMessageFilter(
}
if (can_disable_recording()) {
trace_message_filter->SendBeginTracing(
- TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
- TraceLog::GetInstance()->trace_options());
+ TraceLog::GetInstance()->GetCurrentCategoryFilter(),
+ TraceLog::GetInstance()->GetCurrentTraceOptions());
}
if (can_disable_monitoring()) {
trace_message_filter->SendEnableMonitoring(
- TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
- TraceLog::GetInstance()->trace_options());
+ TraceLog::GetInstance()->GetCurrentCategoryFilter(),
+ TraceLog::GetInstance()->GetCurrentTraceOptions());
}
}
@@ -692,10 +685,6 @@ void TracingControllerImpl::OnDisableRecordingAcked(
if (pending_disable_recording_ack_count_ != 0)
return;
- OnDisableRecordingComplete();
-}
-
-void TracingControllerImpl::OnDisableRecordingComplete() {
// All acks (including from the subprocesses and the local trace) have been
// received.
is_recording_ = false;
@@ -704,34 +693,28 @@ void TracingControllerImpl::OnDisableRecordingComplete() {
if (!pending_get_categories_done_callback_.is_null()) {
pending_get_categories_done_callback_.Run(known_category_groups_);
pending_get_categories_done_callback_.Reset();
- } else if (result_file_) {
- result_file_->Close(
- base::Bind(&TracingControllerImpl::OnResultFileClosed,
- base::Unretained(this)));
+ } else if (trace_data_sink_.get()) {
+ trace_data_sink_->Close();
+ trace_data_sink_ = NULL;
}
}
-void TracingControllerImpl::OnResultFileClosed() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!result_file_)
- return;
-
- if (!pending_disable_recording_done_callback_.is_null()) {
- pending_disable_recording_done_callback_.Run(result_file_->path());
- pending_disable_recording_done_callback_.Reset();
- }
- result_file_.reset();
-}
-
#if defined(OS_CHROMEOS) || defined(OS_WIN)
void TracingControllerImpl::OnEndSystemTracingAcked(
const scoped_refptr<base::RefCountedString>& events_str_ptr) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (result_file_)
- result_file_->WriteSystemTrace(events_str_ptr);
-
+ if (trace_data_sink_.get()) {
+#if defined(OS_WIN)
+ // The Windows kernel events are kept into a JSon format stored as string
+ // and must not be escaped.
+ std::string json_string = events_str_ptr->data();
+#else
+ std::string json_string =
+ base::GetQuotedJSONString(events_str_ptr->data());
+#endif
+ trace_data_sink_->SetSystemTrace(json_string);
+ }
DCHECK(!is_system_tracing_);
std::vector<std::string> category_groups;
OnDisableRecordingAcked(NULL, category_groups);
@@ -770,25 +753,10 @@ void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
if (pending_capture_monitoring_snapshot_ack_count_ != 0)
return;
- if (monitoring_snapshot_file_) {
- monitoring_snapshot_file_->Close(
- base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed,
- base::Unretained(this)));
- }
-}
-
-void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- if (!monitoring_snapshot_file_)
- return;
-
- if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) {
- pending_capture_monitoring_snapshot_done_callback_.Run(
- monitoring_snapshot_file_->path());
- pending_capture_monitoring_snapshot_done_callback_.Reset();
+ if (monitoring_data_sink_.get()) {
+ monitoring_data_sink_->Close();
+ monitoring_data_sink_ = NULL;
}
- monitoring_snapshot_file_.reset();
}
void TracingControllerImpl::OnTraceDataCollected(
@@ -802,8 +770,8 @@ void TracingControllerImpl::OnTraceDataCollected(
return;
}
- if (result_file_)
- result_file_->Write(events_str_ptr);
+ if (trace_data_sink_.get())
+ trace_data_sink_->AddTraceChunk(events_str_ptr->data());
}
void TracingControllerImpl::OnMonitoringTraceDataCollected(
@@ -815,8 +783,8 @@ void TracingControllerImpl::OnMonitoringTraceDataCollected(
return;
}
- if (monitoring_snapshot_file_)
- monitoring_snapshot_file_->Write(events_str_ptr);
+ if (monitoring_data_sink_.get())
+ monitoring_data_sink_->AddTraceChunk(events_str_ptr->data());
}
void TracingControllerImpl::OnLocalTraceDataCollected(
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index d4d5722d85b..9bd84200d45 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -9,12 +9,12 @@
#include <string>
#include <vector>
-#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "content/public/browser/tracing_controller.h"
namespace base {
class RefCountedString;
+class RefCountedMemory;
}
namespace content {
@@ -27,53 +27,47 @@ class TracingControllerImpl : public TracingController {
static TracingControllerImpl* GetInstance();
// TracingController implementation.
- virtual bool GetCategories(
- const GetCategoriesDoneCallback& callback) OVERRIDE;
- virtual bool EnableRecording(
- const std::string& category_filter,
- TracingController::Options options,
- const EnableRecordingDoneCallback& callback) OVERRIDE;
- virtual bool DisableRecording(
- const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) OVERRIDE;
- virtual bool EnableMonitoring(const std::string& category_filter,
- TracingController::Options options,
- const EnableMonitoringDoneCallback& callback) OVERRIDE;
- virtual bool DisableMonitoring(
- const DisableMonitoringDoneCallback& callback) OVERRIDE;
- virtual void GetMonitoringStatus(
+ bool GetCategories(const GetCategoriesDoneCallback& callback) override;
+ bool EnableRecording(const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& trace_options,
+ const EnableRecordingDoneCallback& callback) override;
+ bool DisableRecording(const scoped_refptr<TraceDataSink>& sink) override;
+ bool EnableMonitoring(const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& trace_options,
+ const EnableMonitoringDoneCallback& callback) override;
+ bool DisableMonitoring(
+ const DisableMonitoringDoneCallback& callback) override;
+ void GetMonitoringStatus(
bool* out_enabled,
- std::string* out_category_filter,
- TracingController::Options* out_options) OVERRIDE;
- virtual bool CaptureMonitoringSnapshot(
- const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) OVERRIDE;
- virtual bool GetTraceBufferPercentFull(
- const GetTraceBufferPercentFullCallback& callback) OVERRIDE;
- virtual bool SetWatchEvent(const std::string& category_name,
- const std::string& event_name,
- const WatchEventCallback& callback) OVERRIDE;
- virtual bool CancelWatchEvent() OVERRIDE;
+ base::debug::CategoryFilter* out_category_filter,
+ base::debug::TraceOptions* out_trace_options) override;
+ bool CaptureMonitoringSnapshot(
+ const scoped_refptr<TraceDataSink>& sink) override;
+ bool GetTraceBufferPercentFull(
+ const GetTraceBufferPercentFullCallback& callback) override;
+ bool SetWatchEvent(const std::string& category_name,
+ const std::string& event_name,
+ const WatchEventCallback& callback) override;
+ bool CancelWatchEvent() override;
void RegisterTracingUI(TracingUI* tracing_ui);
void UnregisterTracingUI(TracingUI* tracing_ui);
private:
typedef std::set<scoped_refptr<TraceMessageFilter> > TraceMessageFilterSet;
- class ResultFile;
friend struct base::DefaultLazyInstanceTraits<TracingControllerImpl>;
friend class TraceMessageFilter;
TracingControllerImpl();
- virtual ~TracingControllerImpl();
+ ~TracingControllerImpl() override;
bool can_enable_recording() const {
return !is_recording_;
}
bool can_disable_recording() const {
- return is_recording_ && !result_file_;
+ return is_recording_ && !trace_data_sink_.get();
}
bool can_enable_monitoring() const {
@@ -81,7 +75,7 @@ class TracingControllerImpl : public TracingController {
}
bool can_disable_monitoring() const {
- return is_monitoring_ && !monitoring_snapshot_file_;
+ return is_monitoring_ && !monitoring_data_sink_.get();
}
bool can_get_trace_buffer_percent_full() const {
@@ -113,8 +107,6 @@ class TracingControllerImpl : public TracingController {
void OnDisableRecordingAcked(
TraceMessageFilter* trace_message_filter,
const std::vector<std::string>& known_category_groups);
- void OnDisableRecordingComplete();
- void OnResultFileClosed();
#if defined(OS_CHROMEOS) || defined(OS_WIN)
void OnEndSystemTracingAcked(
@@ -123,7 +115,6 @@ class TracingControllerImpl : public TracingController {
void OnCaptureMonitoringSnapshotAcked(
TraceMessageFilter* trace_message_filter);
- void OnMonitoringSnapshotFileClosed();
void OnTraceBufferPercentFullReply(
TraceMessageFilter* trace_message_filter,
@@ -131,19 +122,20 @@ class TracingControllerImpl : public TracingController {
void OnWatchEventMatched();
- void SetEnabledOnFileThread(const std::string& category_filter,
- int mode,
- int options,
- const base::Closure& callback);
+ void SetEnabledOnFileThread(
+ const base::debug::CategoryFilter& category_filter,
+ int mode,
+ const base::debug::TraceOptions& trace_options,
+ const base::Closure& callback);
void SetDisabledOnFileThread(const base::Closure& callback);
- void OnEnableRecordingDone(const std::string& category_filter,
- int trace_options,
+ void OnEnableRecordingDone(const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& trace_options,
const EnableRecordingDoneCallback& callback);
- void OnDisableRecordingDone(const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback);
- void OnEnableMonitoringDone(const std::string& category_filter,
- int trace_options,
- const EnableMonitoringDoneCallback& callback);
+ void OnDisableRecordingDone();
+ void OnEnableMonitoringDone(
+ const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& trace_options,
+ const EnableMonitoringDoneCallback& callback);
void OnDisableMonitoringDone(const DisableMonitoringDoneCallback& callback);
void OnMonitoringStateChanged(bool is_monitoring);
@@ -166,11 +158,9 @@ class TracingControllerImpl : public TracingController {
#endif
bool is_recording_;
bool is_monitoring_;
- TracingController::Options options_;
+ base::debug::TraceOptions trace_options_;
GetCategoriesDoneCallback pending_get_categories_done_callback_;
- TracingFileResultCallback pending_disable_recording_done_callback_;
- TracingFileResultCallback pending_capture_monitoring_snapshot_done_callback_;
GetTraceBufferPercentFullCallback pending_trace_buffer_percent_full_callback_;
std::string watch_category_name_;
@@ -179,8 +169,8 @@ class TracingControllerImpl : public TracingController {
std::set<std::string> known_category_groups_;
std::set<TracingUI*> tracing_uis_;
- scoped_ptr<ResultFile> result_file_;
- scoped_ptr<ResultFile> monitoring_snapshot_file_;
+ scoped_refptr<TraceDataSink> trace_data_sink_;
+ scoped_refptr<TraceDataSink> monitoring_data_sink_;
DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl);
};
diff --git a/chromium/content/browser/tracing/tracing_resources.gyp b/chromium/content/browser/tracing/tracing_resources.gyp
index 7ad5b9652cb..1efc0ad72c6 100644
--- a/chromium/content/browser/tracing/tracing_resources.gyp
+++ b/chromium/content/browser/tracing/tracing_resources.gyp
@@ -9,6 +9,7 @@
},
'targets': [
{
+ # GN version: //content/browser/tracing:generate_tracing_grd
'target_name': 'generate_tracing_grd',
'type': 'none',
'dependencies': [
@@ -37,6 +38,7 @@
},
{
+ # GN version: //content/browser/tracing:resources
'target_name': 'tracing_resources',
'type': 'none',
'dependencies': [
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index 9f3175366eb..95e3ab92cde 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -4,33 +4,44 @@
#include "content/browser/tracing/tracing_ui.h"
+#include <set>
#include <string>
+#include <vector>
#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/file_util.h"
+#include "base/command_line.h"
+#include "base/debug/trace_event.h"
+#include "base/format_macros.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "content/browser/tracing/grit/tracing_resources.h"
+#include "content/browser/tracing/trace_uploader.h"
#include "content/browser/tracing/tracing_controller_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
namespace content {
namespace {
+const char kUploadURL[] = "https://clients2.google.com/cr/staging_report";
+
void OnGotCategories(const WebUIDataSource::GotDataCallback& callback,
const std::set<std::string>& categorySet) {
-
scoped_ptr<base::ListValue> category_list(new base::ListValue());
for (std::set<std::string>::const_iterator it = categorySet.begin();
it != categorySet.end(); it++) {
@@ -43,8 +54,8 @@ void OnGotCategories(const WebUIDataSource::GotDataCallback& callback,
}
bool GetTracingOptions(const std::string& data64,
- std::string* category_filter_string,
- int* tracing_options) {
+ base::debug::CategoryFilter* category_filter,
+ base::debug::TraceOptions* tracing_options) {
std::string data;
if (!base::Base64Decode(data64, &data)) {
LOG(ERROR) << "Options were not base64 encoded.";
@@ -62,28 +73,39 @@ bool GetTracingOptions(const std::string& data64,
return false;
}
- bool use_system_tracing;
- bool use_continuous_tracing;
- bool use_sampling;
+ if (!category_filter) {
+ LOG(ERROR) << "category_filter can't be passed as NULL";
+ return false;
+ }
+
+ if (!tracing_options) {
+ LOG(ERROR) << "tracing_options can't be passed as NULL";
+ return false;
+ }
bool options_ok = true;
- options_ok &= options->GetString("categoryFilter", category_filter_string);
- options_ok &= options->GetBoolean("useSystemTracing", &use_system_tracing);
- options_ok &= options->GetBoolean("useContinuousTracing",
- &use_continuous_tracing);
- options_ok &= options->GetBoolean("useSampling", &use_sampling);
+ std::string category_filter_string;
+ options_ok &= options->GetString("categoryFilter", &category_filter_string);
+ *category_filter = base::debug::CategoryFilter(category_filter_string);
+
+ options_ok &= options->GetBoolean("useSystemTracing",
+ &tracing_options->enable_systrace);
+ options_ok &=
+ options->GetBoolean("useSampling", &tracing_options->enable_sampling);
+
+ bool use_continuous_tracing;
+ options_ok &=
+ options->GetBoolean("useContinuousTracing", &use_continuous_tracing);
+
+ if (use_continuous_tracing)
+ tracing_options->record_mode = base::debug::RECORD_CONTINUOUSLY;
+ else
+ tracing_options->record_mode = base::debug::RECORD_UNTIL_FULL;
+
if (!options_ok) {
LOG(ERROR) << "Malformed options";
return false;
}
-
- *tracing_options = 0;
- if (use_system_tracing)
- *tracing_options |= TracingController::ENABLE_SYSTRACE;
- if (use_sampling)
- *tracing_options |= TracingController::ENABLE_SAMPLING;
- if (use_continuous_tracing)
- *tracing_options |= TracingController::RECORD_CONTINUOUSLY;
return true;
}
@@ -91,14 +113,14 @@ void OnRecordingEnabledAck(const WebUIDataSource::GotDataCallback& callback);
bool BeginRecording(const std::string& data64,
const WebUIDataSource::GotDataCallback& callback) {
- std::string category_filter_string;
- int tracing_options = 0;
- if (!GetTracingOptions(data64, &category_filter_string, &tracing_options))
+ base::debug::CategoryFilter category_filter("");
+ base::debug::TraceOptions tracing_options;
+ if (!GetTracingOptions(data64, &category_filter, &tracing_options))
return false;
return TracingController::GetInstance()->EnableRecording(
- category_filter_string,
- static_cast<TracingController::Options>(tracing_options),
+ category_filter,
+ tracing_options,
base::Bind(&OnRecordingEnabledAck, callback));
}
@@ -113,35 +135,18 @@ void OnTraceBufferPercentFullResult(
callback.Run(base::RefCountedString::TakeString(&str));
}
-void ReadRecordingResult(const WebUIDataSource::GotDataCallback& callback,
- const base::FilePath& path) {
- std::string tmp;
- if (!base::ReadFileToString(path, &tmp))
- LOG(ERROR) << "Failed to read file " << path.value();
- base::DeleteFile(path, false);
- callback.Run(base::RefCountedString::TakeString(&tmp));
-}
-
-void BeginReadingRecordingResult(
- const WebUIDataSource::GotDataCallback& callback,
- const base::FilePath& path) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(ReadRecordingResult, callback, path));
-}
-
void OnMonitoringEnabledAck(const WebUIDataSource::GotDataCallback& callback);
bool EnableMonitoring(const std::string& data64,
const WebUIDataSource::GotDataCallback& callback) {
- std::string category_filter_string;
- int tracing_options = 0;
- if (!GetTracingOptions(data64, &category_filter_string, &tracing_options))
+ base::debug::TraceOptions tracing_options;
+ base::debug::CategoryFilter category_filter("");
+ if (!GetTracingOptions(data64, &category_filter, &tracing_options))
return false;
return TracingController::GetInstance()->EnableMonitoring(
- category_filter_string,
- static_cast<TracingController::Options>(tracing_options),
+ category_filter,
+ tracing_options,
base::Bind(OnMonitoringEnabledAck, callback));
}
@@ -157,21 +162,20 @@ void OnMonitoringDisabled(const WebUIDataSource::GotDataCallback& callback) {
void GetMonitoringStatus(const WebUIDataSource::GotDataCallback& callback) {
bool is_monitoring;
- std::string category_filter;
- TracingController::Options options;
+ base::debug::CategoryFilter category_filter("");
+ base::debug::TraceOptions options;
TracingController::GetInstance()->GetMonitoringStatus(
&is_monitoring, &category_filter, &options);
scoped_ptr<base::DictionaryValue>
monitoring_options(new base::DictionaryValue());
monitoring_options->SetBoolean("isMonitoring", is_monitoring);
- monitoring_options->SetString("categoryFilter", category_filter);
- monitoring_options->SetBoolean("useSystemTracing",
- (options & TracingController::ENABLE_SYSTRACE) != 0);
- monitoring_options->SetBoolean("useContinuousTracing",
- (options & TracingController::RECORD_CONTINUOUSLY) != 0);
- monitoring_options->SetBoolean("useSampling",
- (options & TracingController::ENABLE_SAMPLING) != 0);
+ monitoring_options->SetString("categoryFilter", category_filter.ToString());
+ monitoring_options->SetBoolean("useSystemTracing", options.enable_systrace);
+ monitoring_options->SetBoolean(
+ "useContinuousTracing",
+ options.record_mode == base::debug::RECORD_CONTINUOUSLY);
+ monitoring_options->SetBoolean("useSampling", options.enable_sampling);
std::string monitoring_options_json;
base::JSONWriter::Write(monitoring_options.get(), &monitoring_options_json);
@@ -183,21 +187,9 @@ void GetMonitoringStatus(const WebUIDataSource::GotDataCallback& callback) {
callback.Run(monitoring_options_base64);
}
-void ReadMonitoringSnapshot(const WebUIDataSource::GotDataCallback& callback,
- const base::FilePath& path) {
- std::string tmp;
- if (!base::ReadFileToString(path, &tmp))
- LOG(ERROR) << "Failed to read file " << path.value();
- base::DeleteFile(path, false);
- callback.Run(base::RefCountedString::TakeString(&tmp));
-}
-
-void OnMonitoringSnapshotCaptured(
- const WebUIDataSource::GotDataCallback& callback,
- const base::FilePath& path) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(ReadMonitoringSnapshot, callback, path));
+void TracingCallbackWrapper(const WebUIDataSource::GotDataCallback& callback,
+ base::RefCountedString* data) {
+ callback.Run(data);
}
bool OnBeginJSONRequest(const std::string& path,
@@ -218,7 +210,8 @@ bool OnBeginJSONRequest(const std::string& path,
}
if (path == "json/end_recording") {
return TracingController::GetInstance()->DisableRecording(
- base::FilePath(), base::Bind(BeginReadingRecordingResult, callback));
+ TracingControllerImpl::CreateStringSink(
+ base::Bind(TracingCallbackWrapper, callback)));
}
const char* enableMonitoringPath = "json/begin_monitoring?";
@@ -232,7 +225,8 @@ bool OnBeginJSONRequest(const std::string& path,
}
if (path == "json/capture_monitoring") {
TracingController::GetInstance()->CaptureMonitoringSnapshot(
- base::FilePath(), base::Bind(OnMonitoringSnapshotCaptured, callback));
+ TracingControllerImpl::CreateStringSink(
+ base::Bind(TracingCallbackWrapper, callback)));
return true;
}
if (path == "json/get_monitoring_status") {
@@ -265,7 +259,13 @@ bool OnTracingRequest(const std::string& path,
//
////////////////////////////////////////////////////////////////////////////////
-TracingUI::TracingUI(WebUI* web_ui) : WebUIController(web_ui) {
+TracingUI::TracingUI(WebUI* web_ui)
+ : WebUIController(web_ui),
+ weak_factory_(this) {
+ web_ui->RegisterMessageCallback(
+ "doUpload",
+ base::Bind(&TracingUI::DoUpload, base::Unretained(this)));
+
// Set up the chrome://tracing/ source.
BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext();
@@ -288,4 +288,99 @@ void TracingUI::OnMonitoringStateChanged(bool is_monitoring) {
"onMonitoringStateChanged", base::FundamentalValue(is_monitoring));
}
+void TracingUI::DoUpload(const base::ListValue* args) {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::string upload_url = kUploadURL;
+ if (command_line.HasSwitch(switches::kTraceUploadURL)) {
+ upload_url =
+ command_line.GetSwitchValueASCII(switches::kTraceUploadURL);
+ }
+ if (!GURL(upload_url).is_valid()) {
+ upload_url.clear();
+ }
+
+ if (upload_url.empty()) {
+ web_ui()->CallJavascriptFunction("onUploadError",
+ base::StringValue("Upload URL empty or invalid"));
+ return;
+ }
+
+ std::string file_contents;
+ if (!args || args->empty() || !args->GetString(0, &file_contents)) {
+ web_ui()->CallJavascriptFunction("onUploadError",
+ base::StringValue("Missing data"));
+ return;
+ }
+
+ TraceUploader::UploadProgressCallback progress_callback =
+ base::Bind(&TracingUI::OnTraceUploadProgress,
+ weak_factory_.GetWeakPtr());
+ TraceUploader::UploadDoneCallback done_callback =
+ base::Bind(&TracingUI::OnTraceUploadComplete,
+ weak_factory_.GetWeakPtr());
+
+#if defined(OS_WIN)
+ const char product[] = "Chrome";
+#elif defined(OS_MACOSX)
+ const char product[] = "Chrome_Mac";
+#elif defined(OS_LINUX)
+ const char product[] = "Chrome_Linux";
+#elif defined(OS_ANDROID)
+ const char product[] = "Chrome_Android";
+#elif defined(OS_CHROMEOS)
+ const char product[] = "Chrome_ChromeOS";
+#else
+#error Platform not supported.
+#endif
+
+ // GetProduct() returns a string like "Chrome/aa.bb.cc.dd", split out
+ // the part before the "/".
+ std::vector<std::string> product_components;
+ base::SplitString(content::GetContentClient()->GetProduct(), '/',
+ &product_components);
+ DCHECK_EQ(2U, product_components.size());
+ std::string version;
+ if (product_components.size() == 2U) {
+ version = product_components[1];
+ } else {
+ version = "unknown";
+ }
+
+ BrowserContext* browser_context =
+ web_ui()->GetWebContents()->GetBrowserContext();
+ TraceUploader* uploader = new TraceUploader(
+ product, version, upload_url, browser_context->GetRequestContext());
+
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
+ &TraceUploader::DoUpload,
+ base::Unretained(uploader),
+ file_contents,
+ progress_callback,
+ done_callback));
+ // TODO(mmandlis): Add support for stopping the upload in progress.
+}
+
+void TracingUI::OnTraceUploadProgress(int64 current, int64 total) {
+ DCHECK(current <= total);
+ int percent = (current / total) * 100;
+ web_ui()->CallJavascriptFunction(
+ "onUploadProgress",
+ base::FundamentalValue(percent),
+ base::StringValue(base::StringPrintf("%" PRId64, current)),
+ base::StringValue(base::StringPrintf("%" PRId64, total)));
+}
+
+void TracingUI::OnTraceUploadComplete(bool success,
+ const std::string& report_id,
+ const std::string& error_message) {
+ if (success) {
+ web_ui()->CallJavascriptFunction("onUploadComplete",
+ base::StringValue(report_id));
+ } else {
+ web_ui()->CallJavascriptFunction("onUploadError",
+ base::StringValue(error_message));
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_ui.h b/chromium/content/browser/tracing/tracing_ui.h
index 40ce0821e2d..7b69337c091 100644
--- a/chromium/content/browser/tracing/tracing_ui.h
+++ b/chromium/content/browser/tracing/tracing_ui.h
@@ -5,6 +5,10 @@
#ifndef CONTENT_BROWSER_TRACING_UI_H_
#define CONTENT_BROWSER_TRACING_UI_H_
+#include <map>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_ui_controller.h"
namespace content {
@@ -13,10 +17,17 @@ namespace content {
class CONTENT_EXPORT TracingUI : public WebUIController {
public:
explicit TracingUI(WebUI* web_ui);
- virtual ~TracingUI();
+ ~TracingUI() override;
void OnMonitoringStateChanged(bool is_monitoring);
+ void DoUpload(const base::ListValue* args);
+ void OnTraceUploadProgress(int64 current, int64 total);
+ void OnTraceUploadComplete(bool success,
+ const std::string& report_id,
+ const std::string& error_message);
private:
+ base::WeakPtrFactory<TracingUI> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(TracingUI);
};
diff --git a/chromium/content/browser/transition_browsertest.cc b/chromium/content/browser/transition_browsertest.cc
new file mode 100644
index 00000000000..1fba073174c
--- /dev/null
+++ b/chromium/content/browser/transition_browsertest.cc
@@ -0,0 +1,191 @@
+// Copyright 2014 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/bind.h"
+#include "base/command_line.h"
+#include "content/browser/loader/cross_site_resource_handler.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/transition_request_manager.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+class TransitionBrowserTest : public ContentBrowserTest {
+ public:
+ TransitionBrowserTest() {}
+
+ void SetUpCommandLine(CommandLine* command_line) override {
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TransitionBrowserTest);
+};
+
+class TransitionBrowserTestObserver
+ : public WebContentsObserver,
+ public ShellResourceDispatcherHostDelegate {
+ public:
+ TransitionBrowserTestObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ request_(NULL),
+ did_defer_response_(false),
+ is_transition_request_(false),
+ did_clear_data_(false) {
+ }
+
+ void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles) override {
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ShellResourceDispatcherHostDelegate::RequestBeginning(request,
+ resource_context,
+ appcache_service,
+ resource_type,
+ throttles);
+ request_ = request;
+
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+
+ if (is_transition_request_) {
+ TransitionRequestManager::GetInstance(
+ )->AddPendingTransitionRequestDataForTesting(
+ info->GetChildID(), info->GetRenderFrameID());
+ }
+ }
+
+ void OnResponseStarted(net::URLRequest* request,
+ ResourceContext* resource_context,
+ ResourceResponse* response,
+ IPC::Sender* sender) override {
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+
+ did_defer_response_ = info->cross_site_handler()->did_defer_for_testing();
+ }
+
+ void RequestComplete(net::URLRequest* url_request) override {
+ if (is_transition_request_) {
+ ResourceRequestInfoImpl* info =
+ ResourceRequestInfoImpl::ForRequest(request_);
+ TransitionLayerData transition_data;
+ did_clear_data_ = !TransitionRequestManager::GetInstance(
+ )->GetPendingTransitionRequest(info->GetChildID(),
+ info->GetRenderFrameID(),
+ request_->url(),
+ &transition_data);
+ }
+ }
+
+ void set_pending_transition_request(bool is_transition_request) {
+ is_transition_request_ = is_transition_request;
+ }
+
+ bool did_defer_response() const { return did_defer_response_; }
+ bool did_clear_data() const { return did_clear_data_; }
+
+ private:
+ net::URLRequest* request_;
+ bool did_defer_response_;
+ bool is_transition_request_;
+ bool did_clear_data_;
+};
+
+// This tests that normal navigations don't defer at first response.
+IN_PROC_BROWSER_TEST_F(TransitionBrowserTest,
+ NormalNavigationNotDeferred) {
+ // This test shouldn't run in --site-per-process mode, where normal
+ // navigations are also deferred.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSitePerProcess))
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ scoped_ptr<TransitionBrowserTestObserver> observer(
+ new TransitionBrowserTestObserver(shell()->web_contents()));
+
+ ResourceDispatcherHost::Get()->SetDelegate(observer.get());
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+
+ EXPECT_FALSE(observer->did_defer_response());
+}
+
+// This tests that when a navigation transition is detected, the response is
+// deferred.
+IN_PROC_BROWSER_TEST_F(TransitionBrowserTest,
+ TransitionNavigationIsDeferred) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ scoped_ptr<TransitionBrowserTestObserver> observer(
+ new TransitionBrowserTestObserver(shell()->web_contents()));
+
+ ResourceDispatcherHost::Get()->SetDelegate(observer.get());
+ observer->set_pending_transition_request(true);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+
+ EXPECT_TRUE(observer->did_defer_response());
+}
+
+// This tests that the renderer is reused between the outgoing and transition.
+IN_PROC_BROWSER_TEST_F(TransitionBrowserTest,
+ TransitionNavigationSharesRenderer) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+
+ int outgoing_process_id =
+ shell()->web_contents()->GetRenderProcessHost()->GetID();
+
+ WebContents::CreateParams create_params(
+ shell()->web_contents()->GetBrowserContext(),
+ shell()->web_contents()->GetSiteInstance());
+ scoped_ptr<WebContents> transition_web_contents(
+ WebContents::Create(create_params));
+
+ GURL about_blank(url::kAboutBlankURL);
+ NavigationController::LoadURLParams params(about_blank);
+ transition_web_contents->GetController().LoadURLWithParams(params);
+ transition_web_contents->Focus();
+
+ WaitForLoadStop(transition_web_contents.get());
+
+ int transition_process_id =
+ transition_web_contents->GetRenderProcessHost()->GetID();
+
+ EXPECT_EQ(outgoing_process_id, transition_process_id);
+}
+
+// This tests that the transition data is cleared after the transition.
+IN_PROC_BROWSER_TEST_F(TransitionBrowserTest,
+ TransitionNavigationDataIsCleared) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ scoped_ptr<TransitionBrowserTestObserver> observer(
+ new TransitionBrowserTestObserver(shell()->web_contents()));
+
+ ResourceDispatcherHost::Get()->SetDelegate(observer.get());
+ observer->set_pending_transition_request(true);
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+ WaitForLoadStop(shell()->web_contents());
+
+ EXPECT_TRUE(observer->did_clear_data());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/transition_request_manager.cc b/chromium/content/browser/transition_request_manager.cc
new file mode 100644
index 00000000000..e3f4317695f
--- /dev/null
+++ b/chromium/content/browser/transition_request_manager.cc
@@ -0,0 +1,215 @@
+// Copyright 2014 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 "content/browser/transition_request_manager.h"
+
+#include "base/command_line.h"
+#include "base/memory/singleton.h"
+#include "base/metrics/field_trial.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+
+namespace {
+
+// Enumerate all Link: headers with the specified relation in this
+// response, and optionally returns the URL and any additional attributes of
+// each one. See EnumerateHeaders for |iter| usage.
+bool EnumerateLinkHeaders(
+ const scoped_refptr<net::HttpResponseHeaders>& headers,
+ void** iter,
+ const std::string& rel,
+ std::string* url,
+ base::StringPairs* attributes) {
+ std::string header_body;
+ bool rel_matched = false;
+ while (!rel_matched && headers->EnumerateHeader(iter, "link", &header_body)) {
+ const std::string::const_iterator begin = header_body.begin();
+ size_t url_start = header_body.find_first_of('<');
+ size_t url_end = header_body.find_first_of('>');
+ if (url_start == std::string::npos || url_end == std::string::npos ||
+ url_start > url_end) {
+ break;
+ }
+
+ if (attributes)
+ attributes->clear();
+
+ net::HttpUtil::NameValuePairsIterator param_iter(
+ begin + url_end + 1, header_body.end(), ';');
+
+ while (param_iter.GetNext()) {
+ if (LowerCaseEqualsASCII(
+ param_iter.name_begin(), param_iter.name_end(), "rel")) {
+ if (LowerCaseEqualsASCII(param_iter.value_begin(),
+ param_iter.value_end(),
+ rel.c_str())) {
+ if (url) {
+ url->assign(begin + url_start + 1, begin + url_end);
+ }
+ rel_matched = true;
+ } else {
+ break;
+ }
+ } else if (attributes) {
+ std::string attribute_name(param_iter.name_begin(),
+ param_iter.name_end());
+ std::string attribute_value(param_iter.value_begin(),
+ param_iter.value_end());
+ attributes->push_back(std::make_pair(attribute_name, attribute_value));
+ }
+ }
+ }
+
+ if (!rel_matched && attributes) {
+ attributes->clear();
+ }
+
+ return rel_matched;
+}
+
+} // namespace
+
+namespace content {
+
+TransitionLayerData::TransitionLayerData() {
+}
+
+TransitionLayerData::~TransitionLayerData() {
+}
+
+TransitionRequestManager::TransitionRequestData::AllowedEntry::AllowedEntry(
+ const std::string& allowed_destination_host_pattern,
+ const std::string& css_selector,
+ const std::string& markup,
+ const std::vector<TransitionElement>& elements)
+ : allowed_destination_host_pattern(allowed_destination_host_pattern),
+ css_selector(css_selector),
+ markup(markup),
+ elements(elements) {
+}
+
+TransitionRequestManager::TransitionRequestData::AllowedEntry::~AllowedEntry() {
+}
+
+void TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ const scoped_refptr<net::HttpResponseHeaders>& headers,
+ std::vector<GURL>& entering_stylesheets,
+ const GURL& resolve_address) {
+ if (headers.get() == NULL)
+ return;
+
+ std::string transition_stylesheet;
+ base::StringPairs attributes;
+ void* header_iter = NULL;
+ while (EnumerateLinkHeaders(headers,
+ &header_iter,
+ "transition-entering-stylesheet",
+ &transition_stylesheet,
+ &attributes)) {
+ GURL stylesheet_url = resolve_address.Resolve(transition_stylesheet);
+ if (stylesheet_url.is_valid())
+ entering_stylesheets.push_back(stylesheet_url);
+ }
+}
+
+TransitionRequestManager::TransitionRequestData::TransitionRequestData() {
+}
+
+TransitionRequestManager::TransitionRequestData::~TransitionRequestData() {
+}
+
+void TransitionRequestManager::TransitionRequestData::AddEntry(
+ const std::string& allowed_destination_host_pattern,
+ const std::string& css_selector,
+ const std::string& markup,
+ const std::vector<TransitionElement>& elements) {
+ allowed_entries_.push_back(AllowedEntry(allowed_destination_host_pattern,
+ css_selector,
+ markup,
+ elements));
+}
+
+bool TransitionRequestManager::TransitionRequestData::FindEntry(
+ const GURL& request_url,
+ TransitionLayerData* transition_data) {
+ DCHECK(!allowed_entries_.empty());
+ CHECK(transition_data);
+ // TODO(oysteine): Add CSP check to validate the host pattern and the
+ // request_url. Must be done before this feature is moved out from the flag.
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures) ||
+ base::FieldTrialList::FindFullName("NavigationTransitions") ==
+ "Enabled");
+
+ const AllowedEntry& allowed_entry = allowed_entries_[0];
+ transition_data->markup = allowed_entry.markup;
+ transition_data->css_selector = allowed_entry.css_selector;
+ transition_data->elements = allowed_entry.elements;
+ return true;
+}
+
+bool TransitionRequestManager::GetPendingTransitionRequest(
+ int render_process_id,
+ int render_frame_id,
+ const GURL& request_url,
+ TransitionLayerData* transition_data) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(transition_data);
+ std::pair<int, int> key(render_process_id, render_frame_id);
+ RenderFrameRequestDataMap::iterator iter =
+ pending_transition_frames_.find(key);
+ return iter != pending_transition_frames_.end() &&
+ iter->second.FindEntry(request_url, transition_data);
+}
+
+void TransitionRequestManager::AddPendingTransitionRequestData(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& allowed_destination_host_pattern,
+ const std::string& css_selector,
+ const std::string& markup,
+ const std::vector<TransitionElement>& elements) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ std::pair<int, int> key(render_process_id, render_frame_id);
+ pending_transition_frames_[key].AddEntry(
+ allowed_destination_host_pattern, css_selector, markup, elements);
+}
+
+void TransitionRequestManager::AddPendingTransitionRequestDataForTesting(
+ int render_process_id,
+ int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ std::pair<int, int> key(render_process_id, render_frame_id);
+ pending_transition_frames_[key].AddEntry(
+ "*", /* allowed_destination_host_pattern */
+ "", /* css_selector */
+ "", /* markup */
+ std::vector<TransitionElement>()); /* elements */
+}
+
+void TransitionRequestManager::ClearPendingTransitionRequestData(
+ int render_process_id, int render_frame_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::pair<int, int> key(render_process_id, render_frame_id);
+ pending_transition_frames_.erase(key);
+}
+
+TransitionRequestManager::TransitionRequestManager() {
+}
+
+TransitionRequestManager::~TransitionRequestManager() {
+}
+
+// static
+TransitionRequestManager* TransitionRequestManager::GetInstance() {
+ return Singleton<TransitionRequestManager>::get();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/transition_request_manager.h b/chromium/content/browser/transition_request_manager.h
new file mode 100644
index 00000000000..65b57924134
--- /dev/null
+++ b/chromium/content/browser/transition_request_manager.h
@@ -0,0 +1,139 @@
+// Copyright 2014 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 CONTENT_BROWSER_TRANSITION_REQUEST_MANAGER_H_
+#define CONTENT_BROWSER_TRANSITION_REQUEST_MANAGER_H_
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "content/public/common/transition_element.h"
+#include "ui/gfx/geometry/rect.h"
+#include "url/gurl.h"
+
+template <typename T>
+struct DefaultSingletonTraits;
+
+namespace net {
+class HttpResponseHeaders;
+}
+class GURL;
+
+namespace content {
+
+// This struct passes data about an imminent transition between threads.
+struct TransitionLayerData {
+ CONTENT_EXPORT TransitionLayerData();
+ CONTENT_EXPORT ~TransitionLayerData();
+
+ std::string markup;
+ std::string css_selector;
+ std::vector<TransitionElement> elements;
+ scoped_refptr<net::HttpResponseHeaders> response_headers;
+ GURL request_url;
+};
+
+// TransitionRequestManager is used to handle bookkeeping for transition
+// requests and responses.
+//
+// TransitionRequestManager is a singleton and should only be accessed on the IO
+// thread.
+//
+class TransitionRequestManager {
+ public:
+ // Returns the singleton instance.
+ CONTENT_EXPORT static TransitionRequestManager* GetInstance();
+
+ // Parses out any transition-entering-stylesheet link headers from the
+ // response headers.
+ CONTENT_EXPORT static void ParseTransitionStylesheetsFromHeaders(
+ const scoped_refptr<net::HttpResponseHeaders>& headers,
+ std::vector<GURL>& entering_stylesheets,
+ const GURL& resolve_address);
+
+ // Get pending transition request data from RenderFrameHost specified by the
+ // given IDs and return true if the data exists. For web to web transition, we
+ // will have to delay the response until the embedder resumes the request if
+ // the data exists.
+ CONTENT_EXPORT bool GetPendingTransitionRequest(
+ int render_process_id,
+ int render_frame_id,
+ const GURL& request_url,
+ TransitionLayerData* transition_data);
+
+ // Adds pending request data for a transition navigation for the
+ // RenderFrameHost specified by the given IDs.
+ CONTENT_EXPORT void AddPendingTransitionRequestData(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& allowed_destination_host_pattern,
+ const std::string& css_selector,
+ const std::string& markup,
+ const std::vector<TransitionElement>& elements);
+ CONTENT_EXPORT void AddPendingTransitionRequestDataForTesting(
+ int render_process_id,
+ int render_frame_id);
+
+ CONTENT_EXPORT void ClearPendingTransitionRequestData(int render_process_id,
+ int render_frame_id);
+
+ // The maximum number of elements is meant to avoid passing arbitrarily large
+ // amount of objects across the IPC boundary.
+ static const int kMaxNumOfElements = 1024;
+
+ private:
+ class TransitionRequestData {
+ public:
+ TransitionRequestData();
+ ~TransitionRequestData();
+ void AddEntry(const std::string& allowed_destination_host_pattern,
+ const std::string& selector,
+ const std::string& markup,
+ const std::vector<TransitionElement>& elements);
+ bool FindEntry(const GURL& request_url,
+ TransitionLayerData* transition_data);
+
+ private:
+ struct AllowedEntry {
+ // These strings could have originated from a compromised renderer,
+ // and should not be trusted or assumed safe. They are only used within
+ // a sandboxed iframe with scripts disabled.
+ std::string allowed_destination_host_pattern;
+ std::string css_selector;
+ std::string markup;
+ std::vector<TransitionElement> elements;
+
+ AllowedEntry(const std::string& allowed_destination_host_pattern,
+ const std::string& css_selector,
+ const std::string& markup,
+ const std::vector<TransitionElement>& elements);
+ ~AllowedEntry();
+ };
+ std::vector<AllowedEntry> allowed_entries_;
+ };
+
+ friend struct DefaultSingletonTraits<TransitionRequestManager>;
+ typedef std::map<std::pair<int, int>, TransitionRequestData>
+ RenderFrameRequestDataMap;
+
+ TransitionRequestManager();
+ ~TransitionRequestManager();
+
+ // Map of (render_process_host_id, render_frame_id) pairs of all
+ // RenderFrameHosts that have pending cross-site requests and their data.
+ // Used to pass information to the CrossSiteResourceHandler without doing a
+ // round-trip between IO->UI->IO threads.
+ RenderFrameRequestDataMap pending_transition_frames_;
+
+ DISALLOW_COPY_AND_ASSIGN(TransitionRequestManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_TRANSITION_REQUEST_MANAGER_H_
diff --git a/chromium/content/browser/transition_request_manager_unittest.cc b/chromium/content/browser/transition_request_manager_unittest.cc
new file mode 100644
index 00000000000..95bc01e0242
--- /dev/null
+++ b/chromium/content/browser/transition_request_manager_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright 2014 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 "content/browser/transition_request_manager.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class TransitionRequestManagerTest : public testing::Test {
+ public:
+ ~TransitionRequestManagerTest() override {}
+};
+
+TEST_F(TransitionRequestManagerTest,
+ ParseTransitionStylesheetsFromNullHeaders) {
+ const GURL url("http://www.test.com/");
+ std::vector<GURL> entering_stylesheets;
+ scoped_refptr<net::HttpResponseHeaders> headers;
+
+ TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ headers, entering_stylesheets, url);
+ ASSERT_TRUE(entering_stylesheets.empty());
+}
+
+TEST_F(TransitionRequestManagerTest,
+ ParseTransitionStylesheetsFromEmptyHeaders) {
+ const GURL url("http://www.test.com/");
+ std::vector<GURL> entering_stylesheets;
+
+ char headers_string[] = "";
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+ headers_string, sizeof(headers_string))));
+
+ TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ headers, entering_stylesheets, url);
+ ASSERT_TRUE(entering_stylesheets.empty());
+}
+
+TEST_F(TransitionRequestManagerTest,
+ ParseTransitionStylesheetsFromHeadersForInvalidURL) {
+ const GURL url;
+ std::vector<GURL> entering_stylesheets;
+
+ char headers_string[] =
+ "HTTP/1.0 200 OK\r\n"
+ "link: <transition.css>;rel=transition-entering-stylesheet;scope=*\r\n"
+ "\r\n";
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+ headers_string, sizeof(headers_string))));
+
+ TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ headers, entering_stylesheets, url);
+ ASSERT_TRUE(entering_stylesheets.empty());
+}
+
+TEST_F(TransitionRequestManagerTest, ParseTransitionStylesheetsFromHeaders) {
+ const GURL url("http://www.test.com/");
+ std::vector<GURL> entering_stylesheets;
+
+ char headers_string[] =
+ "HTTP/1.0 200 OK\r\n"
+ "link: <transition.css>;rel=transition-entering-stylesheet;scope=*\r\n"
+ "\r\n";
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+ headers_string, sizeof(headers_string))));
+
+ TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ headers, entering_stylesheets, url);
+ ASSERT_TRUE(entering_stylesheets.size() == 1);
+ ASSERT_STREQ((url.spec() + "transition.css").c_str(),
+ entering_stylesheets[0].spec().c_str());
+}
+
+TEST_F(TransitionRequestManagerTest,
+ ParseMultipleTransitionStylesheetsFromHeaders) {
+ const GURL url("http://www.test.com/");
+ std::vector<GURL> entering_stylesheets;
+
+ char headers_string[] =
+ "HTTP/1.0 200 OK\r\n"
+ "link: <transition0.css>;rel=transition-entering-stylesheet;scope=*\r\n"
+ "link: <transition1.css>;rel=transition-entering-stylesheet;scope=*\r\n"
+ "link: <transition2.css>;rel=transition-entering-stylesheet;scope=*\r\n"
+ "\r\n";
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+ headers_string, sizeof(headers_string))));
+
+ TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ headers, entering_stylesheets, url);
+ ASSERT_TRUE(entering_stylesheets.size() == 3);
+ ASSERT_STREQ((url.spec() + "transition0.css").c_str(),
+ entering_stylesheets[0].spec().c_str());
+ ASSERT_STREQ((url.spec() + "transition1.css").c_str(),
+ entering_stylesheets[1].spec().c_str());
+ ASSERT_STREQ((url.spec() + "transition2.css").c_str(),
+ entering_stylesheets[2].spec().c_str());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/udev_linux.cc b/chromium/content/browser/udev_linux.cc
index f6f9443ab3f..80c929bf0ec 100644
--- a/chromium/content/browser/udev_linux.cc
+++ b/chromium/content/browser/udev_linux.cc
@@ -13,23 +13,21 @@ namespace content {
UdevLinux::UdevLinux(const std::vector<UdevMonitorFilter>& filters,
const UdevNotificationCallback& callback)
: udev_(udev_new()),
- monitor_(NULL),
+ monitor_(udev_monitor_new_from_netlink(udev_.get(), "udev")),
monitor_fd_(-1),
callback_(callback) {
CHECK(udev_);
-
- monitor_ = udev_monitor_new_from_netlink(udev_, "udev");
CHECK(monitor_);
for (size_t i = 0; i < filters.size(); ++i) {
int ret = udev_monitor_filter_add_match_subsystem_devtype(
- monitor_, filters[i].subsystem, filters[i].devtype);
+ monitor_.get(), filters[i].subsystem, filters[i].devtype);
CHECK_EQ(0, ret);
}
- int ret = udev_monitor_enable_receiving(monitor_);
+ int ret = udev_monitor_enable_receiving(monitor_.get());
CHECK_EQ(0, ret);
- monitor_fd_ = udev_monitor_get_fd(monitor_);
+ monitor_fd_ = udev_monitor_get_fd(monitor_.get());
CHECK_GE(monitor_fd_, 0);
bool success = base::MessageLoopForIO::current()->WatchFileDescriptor(
@@ -43,12 +41,10 @@ UdevLinux::UdevLinux(const std::vector<UdevMonitorFilter>& filters,
UdevLinux::~UdevLinux() {
monitor_watcher_.StopWatchingFileDescriptor();
- udev_monitor_unref(monitor_);
- udev_unref(udev_);
}
udev* UdevLinux::udev_handle() {
- return udev_;
+ return udev_.get();
}
void UdevLinux::OnFileCanReadWithoutBlocking(int fd) {
@@ -56,12 +52,12 @@ void UdevLinux::OnFileCanReadWithoutBlocking(int fd) {
// change state. udev_monitor_receive_device() will return a device object
// representing the device which changed and what type of change occured.
DCHECK_EQ(monitor_fd_, fd);
- udev_device* dev = udev_monitor_receive_device(monitor_);
+ device::ScopedUdevDevicePtr dev(
+ udev_monitor_receive_device(monitor_.get()));
if (!dev)
return;
- callback_.Run(dev);
- udev_device_unref(dev);
+ callback_.Run(dev.get());
}
void UdevLinux::OnFileCanWriteWithoutBlocking(int fd) {
diff --git a/chromium/content/browser/udev_linux.h b/chromium/content/browser/udev_linux.h
index 2b89094c8b6..0160fd3241b 100644
--- a/chromium/content/browser/udev_linux.h
+++ b/chromium/content/browser/udev_linux.h
@@ -42,6 +42,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/message_loop/message_pump_libevent.h"
+#include "device/udev_linux/scoped_udev.h"
extern "C" {
struct udev;
@@ -70,21 +71,20 @@ class UdevLinux : public base::MessagePumpLibevent::Watcher {
// Calls |callback| upon device change events.
UdevLinux(const std::vector<UdevMonitorFilter>& filters,
const UdevNotificationCallback& callback);
- virtual ~UdevLinux();
-
+ ~UdevLinux() override;
// Returns the udev handle to be passed into other udev_*() functions.
udev* udev_handle();
private:
// base::MessagePump:Libevent::Watcher implementation.
- virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
- virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE;
+ void OnFileCanReadWithoutBlocking(int fd) override;
+ void OnFileCanWriteWithoutBlocking(int fd) override;
// libudev-related items, the main context, and the monitoring context to be
// notified about changes to device states.
- udev* udev_;
- udev_monitor* monitor_;
+ device::ScopedUdevPtr udev_;
+ device::ScopedUdevMonitorPtr monitor_;
int monitor_fd_;
base::MessagePumpLibevent::FileDescriptorWatcher monitor_watcher_;
UdevNotificationCallback callback_;
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index ddc41a74131..0d24e3a5e69 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -47,27 +47,23 @@ class UtilitySandboxedProcessLauncherDelegate
#endif // OS_WIN
{}
- virtual ~UtilitySandboxedProcessLauncherDelegate() {}
+ ~UtilitySandboxedProcessLauncherDelegate() override {}
#if defined(OS_WIN)
- virtual bool ShouldLaunchElevated() OVERRIDE {
+ virtual bool ShouldLaunchElevated() override {
return launch_elevated_;
}
virtual void PreSandbox(bool* disable_default_policy,
- base::FilePath* exposed_dir) OVERRIDE {
+ base::FilePath* exposed_dir) override {
*exposed_dir = exposed_dir_;
}
#elif defined(OS_POSIX)
- virtual bool ShouldUseZygote() OVERRIDE {
+ bool ShouldUseZygote() override {
return !no_sandbox_ && exposed_dir_.empty();
}
- virtual base::EnvironmentMap GetEnvironment() OVERRIDE {
- return env_;
- }
- virtual int GetIpcFd() OVERRIDE {
- return ipc_fd_;
- }
+ base::EnvironmentMap GetEnvironment() override { return env_; }
+ base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); }
#endif // OS_WIN
private:
@@ -79,15 +75,15 @@ class UtilitySandboxedProcessLauncherDelegate
#elif defined(OS_POSIX)
base::EnvironmentMap env_;
bool no_sandbox_;
- int ipc_fd_;
+ base::ScopedFD ipc_fd_;
#endif // OS_WIN
};
UtilityMainThreadFactoryFunction g_utility_main_thread_factory = NULL;
UtilityProcessHost* UtilityProcessHost::Create(
- UtilityProcessHostClient* client,
- base::SequencedTaskRunner* client_task_runner) {
+ const scoped_refptr<UtilityProcessHostClient>& client,
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner) {
return new UtilityProcessHostImpl(client, client_task_runner);
}
@@ -97,8 +93,8 @@ void UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(
}
UtilityProcessHostImpl::UtilityProcessHostImpl(
- UtilityProcessHostClient* client,
- base::SequencedTaskRunner* client_task_runner)
+ const scoped_refptr<UtilityProcessHostClient>& client,
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner)
: client_(client),
client_task_runner_(client_task_runner),
is_batch_mode_(false),
@@ -194,7 +190,8 @@ bool UtilityProcessHostImpl::StartProcess() {
in_process_thread_.reset(g_utility_main_thread_factory(channel_id));
in_process_thread_->Start();
} else {
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
int child_flags = child_flags_;
#if defined(OS_POSIX)
@@ -216,7 +213,7 @@ bool UtilityProcessHostImpl::StartProcess() {
return false;
}
- CommandLine* cmd_line = new CommandLine(exe_path);
+ base::CommandLine* cmd_line = new base::CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType,
switches::kUtilityProcess);
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
@@ -267,15 +264,23 @@ bool UtilityProcessHostImpl::StartProcess() {
}
bool UtilityProcessHostImpl::OnMessageReceived(const IPC::Message& message) {
+ if (!client_.get())
+ return true;
+
client_task_runner_->PostTask(
FROM_HERE,
- base::Bind(base::IgnoreResult(
- &UtilityProcessHostClient::OnMessageReceived), client_.get(),
+ base::Bind(
+ base::IgnoreResult(&UtilityProcessHostClient::OnMessageReceived),
+ client_.get(),
message));
+
return true;
}
void UtilityProcessHostImpl::OnProcessLaunchFailed() {
+ if (!client_.get())
+ return;
+
client_task_runner_->PostTask(
FROM_HERE,
base::Bind(&UtilityProcessHostClient::OnProcessLaunchFailed,
@@ -283,6 +288,9 @@ void UtilityProcessHostImpl::OnProcessLaunchFailed() {
}
void UtilityProcessHostImpl::OnProcessCrashed(int exit_code) {
+ if (!client_.get())
+ return;
+
client_task_runner_->PostTask(
FROM_HERE,
base::Bind(&UtilityProcessHostClient::OnProcessCrashed, client_.get(),
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index 84866551a3b..c310e9b4bf0 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -35,23 +35,24 @@ class CONTENT_EXPORT UtilityProcessHostImpl
static void RegisterUtilityMainThreadFactory(
UtilityMainThreadFactoryFunction create);
- UtilityProcessHostImpl(UtilityProcessHostClient* client,
- base::SequencedTaskRunner* client_task_runner);
- virtual ~UtilityProcessHostImpl();
+ UtilityProcessHostImpl(
+ const scoped_refptr<UtilityProcessHostClient>& client,
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner);
+ ~UtilityProcessHostImpl() override;
// UtilityProcessHost implementation:
- virtual bool Send(IPC::Message* message) OVERRIDE;
- virtual bool StartBatchMode() OVERRIDE;
- virtual void EndBatchMode() OVERRIDE;
- virtual void SetExposedDir(const base::FilePath& dir) OVERRIDE;
- virtual void EnableMDns() OVERRIDE;
- virtual void DisableSandbox() OVERRIDE;
+ bool Send(IPC::Message* message) override;
+ bool StartBatchMode() override;
+ void EndBatchMode() override;
+ void SetExposedDir(const base::FilePath& dir) override;
+ void EnableMDns() override;
+ void DisableSandbox() override;
#if defined(OS_WIN)
- virtual void ElevatePrivileges() OVERRIDE;
+ virtual void ElevatePrivileges() override;
#endif
- virtual const ChildProcessData& GetData() OVERRIDE;
+ const ChildProcessData& GetData() override;
#if defined(OS_POSIX)
- virtual void SetEnv(const base::EnvironmentMap& env) OVERRIDE;
+ void SetEnv(const base::EnvironmentMap& env) override;
#endif
void set_child_flags(int flags) { child_flags_ = flags; }
@@ -62,9 +63,9 @@ class CONTENT_EXPORT UtilityProcessHostImpl
bool StartProcess();
// BrowserChildProcessHost:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnProcessLaunchFailed() OVERRIDE;
- virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnProcessLaunchFailed() override;
+ void OnProcessCrashed(int exit_code) override;
// A pointer to our client interface, who will be informed of progress.
scoped_refptr<UtilityProcessHostClient> client_;
diff --git a/chromium/content/browser/vibration/vibration_message_filter.h b/chromium/content/browser/vibration/vibration_message_filter.h
index 1d603ee412a..19e0e6121db 100644
--- a/chromium/content/browser/vibration/vibration_message_filter.h
+++ b/chromium/content/browser/vibration/vibration_message_filter.h
@@ -17,9 +17,9 @@ class VibrationMessageFilter : public BrowserMessageFilter {
VibrationMessageFilter();
private:
- virtual ~VibrationMessageFilter();
+ ~VibrationMessageFilter() override;
// BrowserMessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnVibrate(int64 milliseconds);
void OnCancelVibration();
diff --git a/chromium/content/browser/vibration/vibration_provider_android.h b/chromium/content/browser/vibration/vibration_provider_android.h
index 4d39c748fcd..e0bd1c1d7cb 100644
--- a/chromium/content/browser/vibration/vibration_provider_android.h
+++ b/chromium/content/browser/vibration/vibration_provider_android.h
@@ -19,8 +19,8 @@ class VibrationProviderAndroid : public VibrationProvider {
private:
virtual ~VibrationProviderAndroid();
- virtual void Vibrate(int64 milliseconds) OVERRIDE;
- virtual void CancelVibration() OVERRIDE;
+ virtual void Vibrate(int64 milliseconds) override;
+ virtual void CancelVibration() override;
base::android::ScopedJavaGlobalRef<jobject> j_vibration_provider_;
};
diff --git a/chromium/content/browser/web_contents/OWNERS b/chromium/content/browser/web_contents/OWNERS
index 7454076fe49..8a66bc176f1 100644
--- a/chromium/content/browser/web_contents/OWNERS
+++ b/chromium/content/browser/web_contents/OWNERS
@@ -1,6 +1,5 @@
# for *aura*
-per-file *aura*=ben@chromium.org
+per-file *aura*=sadrul@chromium.org
# for *android*
-per-file *android*=sievers@chromium.org
per-file *android*=tedchoc@chromium.org
diff --git a/chromium/content/browser/web_contents/aura/OWNERS b/chromium/content/browser/web_contents/aura/OWNERS
new file mode 100644
index 00000000000..6e8111fb817
--- /dev/null
+++ b/chromium/content/browser/web_contents/aura/OWNERS
@@ -0,0 +1,2 @@
+mfomitchev@chromium.org
+sadrul@chromium.org
diff --git a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
index f904fe28cf1..406f5545e28 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -12,7 +12,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/common/content_client.h"
-#include "grit/ui_resources.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_observer.h"
@@ -21,6 +20,7 @@
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
+#include "ui/resources/grit/ui_resources.h"
namespace content {
@@ -56,7 +56,7 @@ class DeleteAfterAnimation : public ui::ImplicitAnimationObserver {
virtual ~DeleteAfterAnimation() {}
// ui::ImplicitAnimationObserver:
- virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ virtual void OnImplicitAnimationsCompleted() override {
// Deleting an observer when a ScopedLayerAnimationSettings is iterating
// over them can cause a crash (which can happen during tests). So instead,
// schedule this observer to be deleted soon.
@@ -78,13 +78,13 @@ class ArrowLayerDelegate : public ui::LayerDelegate {
CHECK(!image_.IsEmpty());
}
- virtual ~ArrowLayerDelegate() {}
+ ~ArrowLayerDelegate() override {}
bool left() const { return left_arrow_; }
private:
// ui::LayerDelegate:
- virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
+ void OnPaintLayer(gfx::Canvas* canvas) override {
SkPaint paint;
paint.setColor(SkColorSetARGB(0xa0, 0, 0, 0));
paint.setStyle(SkPaint::kFill_Style);
@@ -99,9 +99,11 @@ class ArrowLayerDelegate : public ui::LayerDelegate {
(kArrowHeight - image_.Height()) / 2);
}
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {}
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
- virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
+
+ base::Closure PrepareForLayerBoundsChange() override {
return base::Closure();
}
@@ -145,9 +147,9 @@ void GestureNavSimple::CompleteGestureAnimation() {
ApplyEffectsAndDestroy(arrow_->transform(), 0.f);
}
-void GestureNavSimple::ApplyEffectsForDelta(float delta_x) {
+bool GestureNavSimple::ApplyEffectsForDelta(float delta_x) {
if (!arrow_)
- return;
+ return false;
CHECK_GT(completion_threshold_, 0.f);
CHECK_GE(delta_x, 0.f);
double complete = std::min(1.f, delta_x / completion_threshold_);
@@ -157,14 +159,15 @@ void GestureNavSimple::ApplyEffectsForDelta(float delta_x) {
0.f);
arrow_->SetTransform(transform);
arrow_->SetOpacity(gfx::Tween::FloatValueBetween(complete, kMinOpacity, 1.f));
+ return true;
}
gfx::Rect GestureNavSimple::GetVisibleBounds() const {
return web_contents_->GetNativeView()->bounds();
}
-void GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) {
- ApplyEffectsForDelta(std::abs(delta_x) + 50.f);
+bool GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) {
+ return ApplyEffectsForDelta(std::abs(delta_x) + 50.f);
}
void GestureNavSimple::OnOverscrollComplete(OverscrollMode overscroll_mode) {
diff --git a/chromium/content/browser/web_contents/aura/gesture_nav_simple.h b/chromium/content/browser/web_contents/aura/gesture_nav_simple.h
index e8466e5e6e2..46da9098470 100644
--- a/chromium/content/browser/web_contents/aura/gesture_nav_simple.h
+++ b/chromium/content/browser/web_contents/aura/gesture_nav_simple.h
@@ -26,20 +26,21 @@ class WebContentsImpl;
class GestureNavSimple : public OverscrollControllerDelegate {
public:
explicit GestureNavSimple(WebContentsImpl* web_contents);
- virtual ~GestureNavSimple();
+ ~GestureNavSimple() override;
private:
void ApplyEffectsAndDestroy(const gfx::Transform& transform, float opacity);
void AbortGestureAnimation();
void CompleteGestureAnimation();
- void ApplyEffectsForDelta(float delta_x);
+ bool ApplyEffectsForDelta(float delta_x);
// OverscrollControllerDelegate:
- virtual gfx::Rect GetVisibleBounds() const OVERRIDE;
- virtual void OnOverscrollUpdate(float delta_x, float delta_y) OVERRIDE;
- virtual void OnOverscrollComplete(OverscrollMode overscroll_mode) OVERRIDE;
- virtual void OnOverscrollModeChange(OverscrollMode old_mode,
- OverscrollMode new_mode) OVERRIDE;
+ gfx::Rect GetVisibleBounds() const override;
+ // Returns true if the scroll update was consumed.
+ bool OnOverscrollUpdate(float delta_x, float delta_y) override;
+ void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
+ void OnOverscrollModeChange(OverscrollMode old_mode,
+ OverscrollMode new_mode) override;
WebContentsImpl* web_contents_;
scoped_ptr<ui::Layer> clip_layer_;
diff --git a/chromium/content/browser/web_contents/aura/image_window_delegate.cc b/chromium/content/browser/web_contents/aura/image_window_delegate.cc
index 0b40c0f0905..ccfd2c5bcb9 100644
--- a/chromium/content/browser/web_contents/aura/image_window_delegate.cc
+++ b/chromium/content/browser/web_contents/aura/image_window_delegate.cc
@@ -66,7 +66,7 @@ void ImageWindowDelegate::OnCaptureLost() {
void ImageWindowDelegate::OnPaint(gfx::Canvas* canvas) {
if (image_.IsEmpty()) {
- canvas->DrawColor(SK_ColorGRAY);
+ canvas->DrawColor(SK_ColorWHITE);
} else {
if (size_mismatch_)
canvas->DrawColor(SK_ColorWHITE);
diff --git a/chromium/content/browser/web_contents/aura/image_window_delegate.h b/chromium/content/browser/web_contents/aura/image_window_delegate.h
index d0f9b061918..53cf88e79eb 100644
--- a/chromium/content/browser/web_contents/aura/image_window_delegate.h
+++ b/chromium/content/browser/web_contents/aura/image_window_delegate.h
@@ -22,27 +22,27 @@ class CONTENT_EXPORT ImageWindowDelegate : public aura::WindowDelegate {
bool has_image() const { return !image_.IsEmpty(); }
protected:
- virtual ~ImageWindowDelegate();
+ ~ImageWindowDelegate() override;
// Overridden from aura::WindowDelegate:
- virtual gfx::Size GetMinimumSize() const OVERRIDE;
- virtual gfx::Size GetMaximumSize() const OVERRIDE;
- virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE;
- virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE;
- virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE;
- virtual bool ShouldDescendIntoChildForEventHandling(
+ gfx::Size GetMinimumSize() const override;
+ gfx::Size GetMaximumSize() const override;
+ void OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
+ gfx::NativeCursor GetCursor(const gfx::Point& point) override;
+ int GetNonClientComponent(const gfx::Point& point) const override;
+ bool ShouldDescendIntoChildForEventHandling(
aura::Window* child,
- const gfx::Point& location) OVERRIDE;
- virtual bool CanFocus() OVERRIDE;
- virtual void OnCaptureLost() OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
- virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
- virtual bool HasHitTestMask() const OVERRIDE;
- virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
+ const gfx::Point& location) override;
+ bool CanFocus() override;
+ void OnCaptureLost() override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ void OnWindowDestroying(aura::Window* window) override;
+ void OnWindowDestroyed(aura::Window* window) override;
+ void OnWindowTargetVisibilityChanged(bool visible) override;
+ bool HasHitTestMask() const override;
+ void GetHitTestMask(gfx::Path* mask) const override;
protected:
gfx::Image image_;
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
index d2b8b6e7726..3660897dab3 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
@@ -21,13 +21,31 @@
#include "ui/gfx/image/image_skia.h"
namespace content {
+namespace {
+
+// Returns true if the entry's URL or any of the URLs in entry's redirect chain
+// match |url|.
+bool DoesEntryMatchURL(NavigationEntry* entry, const GURL& url) {
+ if (entry->GetURL() == url)
+ return true;
+ const std::vector<GURL>& redirect_chain = entry->GetRedirectChain();
+ for (std::vector<GURL>::const_iterator it = redirect_chain.begin();
+ it != redirect_chain.end();
+ it++) {
+ if (*it == url)
+ return true;
+ }
+ return false;
+}
+
+} // namespace
// A LayerDelegate that paints an image for the layer.
class ImageLayerDelegate : public ui::LayerDelegate {
public:
ImageLayerDelegate() {}
- virtual ~ImageLayerDelegate() {}
+ ~ImageLayerDelegate() override {}
void SetImage(const gfx::Image& image) {
image_ = image;
@@ -37,9 +55,9 @@ class ImageLayerDelegate : public ui::LayerDelegate {
private:
// Overridden from ui::LayerDelegate:
- virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
+ void OnPaintLayer(gfx::Canvas* canvas) override {
if (image_.IsEmpty()) {
- canvas->DrawColor(SK_ColorGRAY);
+ canvas->DrawColor(SK_ColorWHITE);
} else {
SkISize size = canvas->sk_canvas()->getDeviceSize();
if (size.width() != image_size_.width() ||
@@ -50,13 +68,14 @@ class ImageLayerDelegate : public ui::LayerDelegate {
}
}
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
+
// Called when the layer's device scale factor has changed.
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
- }
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
// Invoked prior to the bounds changing. The returned closured is run after
// the bounds change.
- virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
+ base::Closure PrepareForLayerBoundsChange() override {
return base::Closure();
}
@@ -89,21 +108,19 @@ class OverlayDismissAnimator
}
// Overridden from ui::LayerAnimationObserver
- virtual void OnLayerAnimationEnded(
- ui::LayerAnimationSequence* sequence) OVERRIDE {
+ void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
delete this;
}
- virtual void OnLayerAnimationAborted(
- ui::LayerAnimationSequence* sequence) OVERRIDE {
+ void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {
delete this;
}
- virtual void OnLayerAnimationScheduled(
- ui::LayerAnimationSequence* sequence) OVERRIDE {}
+ void OnLayerAnimationScheduled(
+ ui::LayerAnimationSequence* sequence) override {}
private:
- virtual ~OverlayDismissAnimator() {}
+ ~OverlayDismissAnimator() override {}
scoped_ptr<ui::Layer> layer_;
@@ -116,7 +133,6 @@ OverscrollNavigationOverlay::OverscrollNavigationOverlay(
image_delegate_(NULL),
loading_complete_(false),
received_paint_update_(false),
- pending_entry_id_(0),
slide_direction_(SLIDE_UNKNOWN) {
}
@@ -127,7 +143,6 @@ void OverscrollNavigationOverlay::StartObserving() {
loading_complete_ = false;
received_paint_update_ = false;
overlay_dismiss_layer_.reset();
- pending_entry_id_ = 0;
Observe(web_contents_);
// Make sure the overlay window is on top.
@@ -137,10 +152,10 @@ void OverscrollNavigationOverlay::StartObserving() {
// Assumes the navigation has been initiated.
NavigationEntry* pending_entry =
web_contents_->GetController().GetPendingEntry();
- // Save id of the pending entry to identify when it loads and paints later.
+ // Save url of the pending entry to identify when it loads and paints later.
// Under some circumstances navigation can leave a null pending entry -
// see comments in NavigationControllerImpl::NavigateToPendingEntry().
- pending_entry_id_ = pending_entry ? pending_entry->GetUniqueID() : 0;
+ pending_entry_url_ = pending_entry ? pending_entry->GetURL() : GURL();
}
void OverscrollNavigationOverlay::SetOverlayWindow(
@@ -197,8 +212,7 @@ ui::Layer* OverscrollNavigationOverlay::CreateSlideLayer(int offset) {
gfx::Image image;
if (entry && entry->screenshot().get()) {
std::vector<gfx::ImagePNGRep> image_reps;
- image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
- ui::GetScaleFactorForNativeView(window_.get())));
+ image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
image = gfx::Image(image_reps);
}
if (!layer_delegate_)
@@ -274,29 +288,27 @@ void OverscrollNavigationOverlay::OnWindowSliderDestroyed() {
// (including recursively) for a single event.
if (window_slider_.get()) {
// The slider has just been destroyed. Release the ownership.
- WindowSlider* slider ALLOW_UNUSED = window_slider_.release();
+ ignore_result(window_slider_.release());
StopObservingIfDone();
}
}
void OverscrollNavigationOverlay::DidFirstVisuallyNonEmptyPaint() {
- int visible_entry_id =
- web_contents_->GetController().GetVisibleEntry()->GetUniqueID();
- if (visible_entry_id == pending_entry_id_ || !pending_entry_id_) {
+ NavigationEntry* visible_entry =
+ web_contents_->GetController().GetVisibleEntry();
+ if (pending_entry_url_.is_empty() ||
+ DoesEntryMatchURL(visible_entry, pending_entry_url_)) {
received_paint_update_ = true;
StopObservingIfDone();
}
}
void OverscrollNavigationOverlay::DidStopLoading(RenderViewHost* host) {
- // Use the last committed entry rather than the active one, in case a
- // pending entry has been created.
- int committed_entry_id =
- web_contents_->GetController().GetLastCommittedEntry()->GetUniqueID();
- if (committed_entry_id == pending_entry_id_ || !pending_entry_id_) {
- loading_complete_ = true;
- StopObservingIfDone();
- }
+ // Don't compare URLs in this case - it's possible they won't match if
+ // a gesture-nav initiated navigation was interrupted by some other in-site
+ // navigation ((e.g., from a script, or from a bookmark).
+ loading_complete_ = true;
+ StopObservingIfDone();
}
} // namespace content
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
index e8e917136ca..d65d374a848 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay.h
@@ -29,7 +29,7 @@ class CONTENT_EXPORT OverscrollNavigationOverlay
public WindowSlider::Delegate {
public:
explicit OverscrollNavigationOverlay(WebContentsImpl* web_contents);
- virtual ~OverscrollNavigationOverlay();
+ ~OverscrollNavigationOverlay() override;
bool has_window() const { return !!window_.get(); }
@@ -77,16 +77,16 @@ class CONTENT_EXPORT OverscrollNavigationOverlay
ui::Layer* CreateSlideLayer(int offset);
// Overridden from WindowSlider::Delegate:
- virtual ui::Layer* CreateBackLayer() OVERRIDE;
- virtual ui::Layer* CreateFrontLayer() OVERRIDE;
- virtual void OnWindowSlideCompleting() OVERRIDE;
- virtual void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) OVERRIDE;
- virtual void OnWindowSlideAborted() OVERRIDE;
- virtual void OnWindowSliderDestroyed() OVERRIDE;
+ ui::Layer* CreateBackLayer() override;
+ ui::Layer* CreateFrontLayer() override;
+ void OnWindowSlideCompleting() override;
+ void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) override;
+ void OnWindowSlideAborted() override;
+ void OnWindowSliderDestroyed() override;
// Overridden from WebContentsObserver:
- virtual void DidFirstVisuallyNonEmptyPaint() OVERRIDE;
- virtual void DidStopLoading(RenderViewHost* host) OVERRIDE;
+ void DidFirstVisuallyNonEmptyPaint() override;
+ void DidStopLoading(RenderViewHost* host) override;
// The WebContents which is being navigated.
WebContentsImpl* web_contents_;
@@ -101,10 +101,10 @@ class CONTENT_EXPORT OverscrollNavigationOverlay
bool loading_complete_;
bool received_paint_update_;
- // Unique ID of the NavigationEntry we are navigating to. This is needed to
+ // URL of the NavigationEntry we are navigating to. This is needed to
// filter on WebContentsObserver callbacks and is used to dismiss the overlay
// when the relevant page loads and paints.
- int pending_entry_id_;
+ GURL pending_entry_url_;
// The |WindowSlider| that allows sliding history layers while the page is
// being reloaded.
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index 4ff49761095..0e9eb4ef65a 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -7,8 +7,10 @@
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/web_contents/aura/image_window_delegate.h"
#include "content/browser/web_contents/web_contents_view.h"
+#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "ui/aura/test/test_windows.h"
@@ -20,20 +22,18 @@ namespace content {
class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
public:
OverscrollNavigationOverlayTest() {}
- virtual ~OverscrollNavigationOverlayTest() {}
+ ~OverscrollNavigationOverlayTest() override {}
gfx::Image CreateDummyScreenshot() {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(1, 1);
bitmap.eraseColor(SK_ColorWHITE);
return gfx::Image::CreateFrom1xBitmap(bitmap);
}
void SetDummyScreenshotOnNavEntry(NavigationEntry* entry) {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(1, 1);
bitmap.eraseColor(SK_ColorWHITE);
std::vector<unsigned char> png_data;
gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, true, &png_data);
@@ -45,7 +45,8 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
}
void ReceivePaintUpdate() {
- ViewHostMsg_DidFirstVisuallyNonEmptyPaint msg(test_rvh()->GetRoutingID());
+ FrameHostMsg_DidFirstVisuallyNonEmptyPaint msg(
+ main_test_rfh()->GetRoutingID());
RenderViewHostTester::TestOnMessageReceived(test_rvh(), msg);
}
@@ -61,7 +62,7 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
protected:
// RenderViewHostImplTestHarness:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
const GURL first("https://www.google.com");
@@ -102,7 +103,7 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
EXPECT_FALSE(overlay_->received_paint_update_);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
overlay_.reset();
RenderViewHostImplTestHarness::TearDown();
}
@@ -156,7 +157,7 @@ TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_PaintUpdate) {
EXPECT_FALSE(GetOverlay()->received_paint_update_);
ReceivePaintUpdate();
- // Paint updates until the navigation is committed represent updates
+ // Paint updates until the navigation is committed typically represent updates
// for the previous page, so they shouldn't affect the flag.
EXPECT_FALSE(GetOverlay()->received_paint_update_);
@@ -178,17 +179,13 @@ TEST_F(OverscrollNavigationOverlayTest, MultiNavigation_LoadingUpdate) {
// Navigation was started, so the loading status flag should be reset.
EXPECT_FALSE(GetOverlay()->loading_complete_);
- // Load updates until the navigation is committed represent updates for the
- // previous page, so they shouldn't affect the flag.
+ // DidStopLoading for any navigation should always reset the load flag and
+ // dismiss the overlay even if the pending navigation wasn't committed -
+ // this is a "safety net" in case we mis-identify the destination webpage
+ // (which can happen if a new navigation is performed while while a GestureNav
+ // navigation is in progress).
contents()->TestSetIsLoading(true);
contents()->TestSetIsLoading(false);
- EXPECT_FALSE(GetOverlay()->loading_complete_);
-
- contents()->CommitPendingNavigation();
- contents()->TestSetIsLoading(true);
- contents()->TestSetIsLoading(false);
- // Navigation was committed and the load update was received - the flag
- // should now be updated.
EXPECT_TRUE(GetOverlay()->loading_complete_);
EXPECT_FALSE(GetOverlay()->web_contents());
diff --git a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
index 0d0fe934260..83e403b00b2 100644
--- a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
+++ b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -51,6 +51,10 @@ void ShadowLayerDelegate::OnPaintLayer(gfx::Canvas* canvas) {
canvas->sk_canvas()->drawRect(gfx::RectToSkRect(paint_rect), paint);
}
+void ShadowLayerDelegate::OnDelegatedFrameDamage(
+ const gfx::Rect& damage_rect_in_dip) {
+}
+
void ShadowLayerDelegate::OnDeviceScaleFactorChanged(float scale_factor) {
}
diff --git a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h
index 22659d91f11..69c2dcbc7da 100644
--- a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h
+++ b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.h
@@ -24,7 +24,7 @@ namespace content {
class ShadowLayerDelegate : public ui::LayerDelegate {
public:
explicit ShadowLayerDelegate(ui::Layer* shadow_for);
- virtual ~ShadowLayerDelegate();
+ ~ShadowLayerDelegate() override;
// Returns the layer for the shadow. Note that the ShadowLayerDelegate owns
// the layer, and the layer is destroyed when the delegate is destroyed.
@@ -32,9 +32,10 @@ class ShadowLayerDelegate : public ui::LayerDelegate {
private:
// Overridden from ui::LayerDelegate:
- virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE;
+ void OnPaintLayer(gfx::Canvas* canvas) override;
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ base::Closure PrepareForLayerBoundsChange() override;
scoped_ptr<ui::Layer> layer_;
diff --git a/chromium/content/browser/web_contents/aura/window_slider.cc b/chromium/content/browser/web_contents/aura/window_slider.cc
index 8248d6c7318..f7ffa7e3839 100644
--- a/chromium/content/browser/web_contents/aura/window_slider.cc
+++ b/chromium/content/browser/web_contents/aura/window_slider.cc
@@ -27,11 +27,11 @@ class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
: closure_(closure) {
}
- virtual ~CallbackAnimationObserver() {}
+ ~CallbackAnimationObserver() override {}
private:
// Overridden from ui::ImplicitAnimationObserver:
- virtual void OnImplicitAnimationsCompleted() OVERRIDE {
+ void OnImplicitAnimationsCompleted() override {
if (!closure_.is_null())
closure_.Run();
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
@@ -52,14 +52,14 @@ WindowSlider::WindowSlider(Delegate* delegate,
owner_(owner),
active_animator_(NULL),
delta_x_(0.f),
- weak_factory_(this),
active_start_threshold_(0.f),
start_threshold_touchscreen_(content::GetOverscrollConfig(
content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN)),
start_threshold_touchpad_(content::GetOverscrollConfig(
content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD)),
complete_threshold_(content::GetOverscrollConfig(
- content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE)) {
+ content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE)),
+ weak_factory_(this) {
event_window_->AddPreTargetHandler(this);
event_window_->AddObserver(this);
diff --git a/chromium/content/browser/web_contents/aura/window_slider.h b/chromium/content/browser/web_contents/aura/window_slider.h
index 83e56de330a..3263aadadf5 100644
--- a/chromium/content/browser/web_contents/aura/window_slider.h
+++ b/chromium/content/browser/web_contents/aura/window_slider.h
@@ -70,7 +70,7 @@ class CONTENT_EXPORT WindowSlider : public ui::EventHandler,
aura::Window* event_window,
aura::Window* owner);
- virtual ~WindowSlider();
+ ~WindowSlider() override;
// Changes the owner of the slider.
void ChangeOwner(aura::Window* new_owner);
@@ -105,14 +105,14 @@ class CONTENT_EXPORT WindowSlider : public ui::EventHandler,
scoped_ptr<ShadowLayerDelegate> shadow);
// Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+ void OnKeyEvent(ui::KeyEvent* event) override;
+ void OnMouseEvent(ui::MouseEvent* event) override;
+ void OnScrollEvent(ui::ScrollEvent* event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
// Overridden from aura::WindowObserver:
- virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
- aura::Window* new_root) OVERRIDE;
+ void OnWindowRemovingFromRootWindow(aura::Window* window,
+ aura::Window* new_root) override;
Delegate* delegate_;
@@ -140,14 +140,14 @@ class CONTENT_EXPORT WindowSlider : public ui::EventHandler,
// This manages the shadow for the layers.
scoped_ptr<ShadowLayerDelegate> shadow_;
- base::WeakPtrFactory<WindowSlider> weak_factory_;
-
float active_start_threshold_;
const float start_threshold_touchscreen_;
const float start_threshold_touchpad_;
const float complete_threshold_;
+ base::WeakPtrFactory<WindowSlider> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(WindowSlider);
};
diff --git a/chromium/content/browser/web_contents/aura/window_slider_unittest.cc b/chromium/content/browser/web_contents/aura/window_slider_unittest.cc
index 4a2d0a56001..a1988d4990b 100644
--- a/chromium/content/browser/web_contents/aura/window_slider_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/window_slider_unittest.cc
@@ -8,7 +8,6 @@
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/test/aura_test_base.h"
-#include "ui/aura/test/event_generator.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
@@ -17,6 +16,7 @@
#include "ui/compositor/test/layer_animator_test_controller.h"
#include "ui/events/event_processor.h"
#include "ui/events/event_utils.h"
+#include "ui/events/test/event_generator.h"
#include "ui/gfx/frame_time.h"
namespace content {
@@ -72,11 +72,11 @@ class NoEventWindowDelegate : public aura::test::TestWindowDelegate {
public:
NoEventWindowDelegate() {
}
- virtual ~NoEventWindowDelegate() {}
+ ~NoEventWindowDelegate() override {}
private:
// Overridden from aura::WindowDelegate:
- virtual bool HasHitTestMask() const OVERRIDE { return true; }
+ bool HasHitTestMask() const override { return true; }
DISALLOW_COPY_AND_ASSIGN(NoEventWindowDelegate);
};
@@ -92,7 +92,7 @@ class WindowSliderDelegateTest : public WindowSlider::Delegate {
slide_aborted_(false),
slider_destroyed_(false) {
}
- virtual ~WindowSliderDelegateTest() {
+ ~WindowSliderDelegateTest() override {
// Make sure slide_completed() gets called if slide_completing() was called.
CHECK(!slide_completing_ || slide_completed_);
}
@@ -127,35 +127,29 @@ class WindowSliderDelegateTest : public WindowSlider::Delegate {
}
// Overridden from WindowSlider::Delegate:
- virtual ui::Layer* CreateBackLayer() OVERRIDE {
+ ui::Layer* CreateBackLayer() override {
if (!can_create_layer_)
return NULL;
created_back_layer_ = true;
return CreateLayerForTest();
}
- virtual ui::Layer* CreateFrontLayer() OVERRIDE {
+ ui::Layer* CreateFrontLayer() override {
if (!can_create_layer_)
return NULL;
created_front_layer_ = true;
return CreateLayerForTest();
}
- virtual void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) OVERRIDE {
+ void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) override {
slide_completed_ = true;
}
- virtual void OnWindowSlideCompleting() OVERRIDE {
- slide_completing_ = true;
- }
+ void OnWindowSlideCompleting() override { slide_completing_ = true; }
- virtual void OnWindowSlideAborted() OVERRIDE {
- slide_aborted_ = true;
- }
+ void OnWindowSlideAborted() override { slide_aborted_ = true; }
- virtual void OnWindowSliderDestroyed() OVERRIDE {
- slider_destroyed_ = true;
- }
+ void OnWindowSliderDestroyed() override { slider_destroyed_ = true; }
private:
bool can_create_layer_;
@@ -175,11 +169,11 @@ class WindowSliderDeleteOwnerOnDestroy : public WindowSliderDelegateTest {
explicit WindowSliderDeleteOwnerOnDestroy(aura::Window* owner)
: owner_(owner) {
}
- virtual ~WindowSliderDeleteOwnerOnDestroy() {}
+ ~WindowSliderDeleteOwnerOnDestroy() override {}
private:
// Overridden from WindowSlider::Delegate:
- virtual void OnWindowSliderDestroyed() OVERRIDE {
+ void OnWindowSliderDestroyed() override {
WindowSliderDelegateTest::OnWindowSliderDestroyed();
delete owner_;
}
@@ -194,11 +188,11 @@ class WindowSliderDeleteOwnerOnComplete : public WindowSliderDelegateTest {
explicit WindowSliderDeleteOwnerOnComplete(aura::Window* owner)
: owner_(owner) {
}
- virtual ~WindowSliderDeleteOwnerOnComplete() {}
+ ~WindowSliderDeleteOwnerOnComplete() override {}
private:
// Overridden from WindowSlider::Delegate:
- virtual void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) OVERRIDE {
+ void OnWindowSlideCompleted(scoped_ptr<ui::Layer> layer) override {
WindowSliderDelegateTest::OnWindowSlideCompleted(layer.Pass());
delete owner_;
}
@@ -214,7 +208,7 @@ TEST_F(WindowSliderTest, WindowSlideUsingGesture) {
window->SetBounds(gfx::Rect(0, 0, 400, 400));
WindowSliderDelegateTest slider_delegate;
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
// Generate a horizontal overscroll.
WindowSlider* slider =
@@ -300,17 +294,14 @@ TEST_F(WindowSliderTest, WindowSlideIsCancelledOnEvent) {
gfx::Point(55, 10),
gfx::Point(55, 10),
0, 0),
- new ui::KeyEvent(ui::ET_KEY_PRESSED,
- ui::VKEY_A,
- 0,
- true),
+ new ui::KeyEvent('a', ui::VKEY_A, ui::EF_NONE),
NULL
};
new WindowSlider(&slider_delegate, root_window(), window.get());
for (int i = 0; events[i]; ++i) {
// Generate a horizontal overscroll.
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
generator.GestureScrollSequenceWithCallback(
gfx::Point(10, 10),
gfx::Point(80, 10),
@@ -352,7 +343,7 @@ TEST_F(WindowSliderTest, WindowSlideInterruptedThenContinues) {
gfx::Point(55, 10),
0, 0);
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
// Start the scroll sequence. Scroll forward so that |window|'s layer is the
// one animating.
@@ -452,7 +443,7 @@ TEST_F(WindowSliderTest, OwnerWindowChangesDuringWindowSlide) {
// Generate a horizontal scroll, and change the owner in the middle of the
// scroll.
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
aura::Window* old_window = window.get();
generator.GestureScrollSequenceWithCallback(
gfx::Point(10, 10),
@@ -484,7 +475,7 @@ TEST_F(WindowSliderTest, NoSlideWhenLayerCantBeCreated) {
WindowSlider* slider =
new WindowSlider(&slider_delegate, root_window(), window.get());
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
// No slide in progress should be reported during scroll since the layer
// wasn't created.
@@ -530,7 +521,7 @@ TEST_F(WindowSliderTest, OwnerIsDestroyedOnSliderDestroy) {
EXPECT_EQ(child_windows + 1, root_window()->children().size());
WindowSliderDeleteOwnerOnDestroy slider_delegate(window);
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
// Generate a horizontal overscroll.
scoped_ptr<WindowSlider> slider(
@@ -561,7 +552,7 @@ TEST_F(WindowSliderTest, OwnerIsDestroyedOnSlideComplete) {
EXPECT_EQ(child_windows + 1, root_window()->children().size());
WindowSliderDeleteOwnerOnComplete slider_delegate(window);
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
// Generate a horizontal overscroll.
new WindowSlider(&slider_delegate, root_window(), window);
@@ -592,13 +583,14 @@ TEST_F(WindowSliderTest, SwipeDuringSwipeAnimation) {
WindowSliderDelegateTest slider_delegate;
new WindowSlider(&slider_delegate, root_window(), window.get());
- ui::ScopedAnimationDurationScaleMode normal_duration_(
+ // This test uses explicit durations so needs a normal duration.
+ ui::ScopedAnimationDurationScaleMode normal_duration(
ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
ui::LayerAnimator* animator = window->layer()->GetAnimator();
animator->set_disable_timer_for_test(true);
ui::LayerAnimatorTestController test_controller(animator);
- aura::test::EventGenerator generator(root_window());
+ ui::test::EventGenerator generator(root_window());
// Swipe forward so that |window|'s layer is the one animating.
generator.GestureScrollSequence(
diff --git a/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc b/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc
index 1c2d94099ce..0a89f7189bd 100644
--- a/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc
+++ b/chromium/content/browser/web_contents/opened_by_dom_browsertest.cc
@@ -28,7 +28,7 @@ class CloseTrackingDelegate : public WebContentsDelegate {
bool close_contents_called() const { return close_contents_called_; }
- virtual void CloseContents(WebContents* source) OVERRIDE {
+ void CloseContents(WebContents* source) override {
close_contents_called_ = true;
}
@@ -42,7 +42,7 @@ class CloseTrackingDelegate : public WebContentsDelegate {
class OpenedByDOMTest : public ContentBrowserTest {
protected:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
// Use --site-per-process to force process swaps on cross-site navigations.
command_line->AppendSwitch(switches::kSitePerProcess);
}
@@ -114,7 +114,8 @@ IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, Popup) {
// Tests that window.close() works in a popup window that has navigated a few
// times and swapped processes.
-IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, CrossProcessPopup) {
+// Crashes on all platforms. http://crbug.com/399709
+IN_PROC_BROWSER_TEST_F(OpenedByDOMTest, DISABLED_CrossProcessPopup) {
host_resolver()->AddRule("*", "127.0.0.1");
ASSERT_TRUE(test_server()->Start());
diff --git a/chromium/content/browser/web_contents/touch_editable_impl_aura.cc b/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
index d28fa92deac..bef8ff7c6f9 100644
--- a/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
+++ b/chromium/content/browser/web_contents/touch_editable_impl_aura.cc
@@ -10,13 +10,13 @@
#include "content/common/view_messages.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
-#include "grit/ui_strings.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/gfx/range/range.h"
+#include "ui/strings/grit/ui_strings.h"
#include "ui/wm/public/activation_client.h"
namespace content {
@@ -61,26 +61,11 @@ void TouchEditableImplAura::UpdateEditingController() {
}
void TouchEditableImplAura::OverscrollStarted() {
- overscroll_in_progress_ = true;
+ scrolls_in_progress_++;
}
void TouchEditableImplAura::OverscrollCompleted() {
- // We might receive multiple OverscrollStarted() and OverscrollCompleted()
- // during the same scroll session (for example, when the scroll direction
- // changes). We want to show the handles only when:
- // 1. Overscroll has completed
- // 2. Scrolling session is over, i.e. we have received ET_GESTURE_SCROLL_END.
- // 3. If we had hidden the handles when scrolling started
- // 4. If there is still a need to show handles (there is a non-empty selection
- // or non-NONE |text_input_type_|)
- if (overscroll_in_progress_ && !scroll_in_progress_ &&
- handles_hidden_due_to_scroll_ &&
- (selection_anchor_rect_ != selection_focus_rect_ ||
- text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
- StartTouchEditing();
- UpdateEditingController();
- }
- overscroll_in_progress_ = false;
+ ScrollEnded();
}
////////////////////////////////////////////////////////////////////////////////
@@ -116,12 +101,10 @@ void TouchEditableImplAura::OnSelectionOrCursorChanged(const gfx::Rect& anchor,
selection_anchor_rect_ = anchor;
selection_focus_rect_ = focus;
- // If touch editing handles were not visible, we bring them up only if
- // there is non-zero selection on the page. And the current event is a
- // gesture event (we dont want to show handles if the user is selecting
- // using mouse or keyboard).
- if (selection_gesture_in_process_ && !scroll_in_progress_ &&
- !overscroll_in_progress_ &&
+ // If touch editing handles were not visible, we bring them up only if the
+ // current event is a gesture event, no scroll/fling/overscoll is in progress,
+ // and there is non-zero selection on the page
+ if (selection_gesture_in_process_ && !scrolls_in_progress_ &&
selection_anchor_rect_ != selection_focus_rect_) {
StartTouchEditing();
selection_gesture_in_process_ = false;
@@ -163,36 +146,29 @@ bool TouchEditableImplAura::HandleInputEvent(const ui::Event* event) {
}
// For single taps, not inside selected region, we want to show handles
// only when the tap is on an already focused textfield.
- textfield_was_focused_on_tap_ = false;
- if (gesture_event->details().tap_count() == 1 &&
- text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)
- textfield_was_focused_on_tap_ = true;
+ textfield_was_focused_on_tap_ =
+ gesture_event->details().tap_count() == 1 &&
+ text_input_type_ != ui::TEXT_INPUT_TYPE_NONE;
break;
case ui::ET_GESTURE_LONG_PRESS:
selection_gesture_in_process_ = true;
break;
case ui::ET_GESTURE_SCROLL_BEGIN:
- // If selection handles are currently visible, we want to get them back up
- // when scrolling ends. So we set |handles_hidden_due_to_scroll_| so that
- // we can re-start touch editing on scroll end gesture.
- scroll_in_progress_ = true;
- handles_hidden_due_to_scroll_ = false;
- if (touch_selection_controller_)
- handles_hidden_due_to_scroll_ = true;
+ scrolls_in_progress_++;
+ // We need to hide selection handles during scroll (including fling and
+ // overscroll), but they should be re-activated after scrolling if:
+ // - an existing scroll decided that handles should be shown after
+ // scrolling; or
+ // - the gesture in progress is going to end in selection; or
+ // - selection handles are currently active.
+ handles_hidden_due_to_scroll_ = handles_hidden_due_to_scroll_ ||
+ selection_gesture_in_process_ ||
+ touch_selection_controller_ != NULL;
+ selection_gesture_in_process_ = false;
EndTouchEditing(true);
break;
case ui::ET_GESTURE_SCROLL_END:
- // Scroll has ended, but we might still be in overscroll animation.
- if (handles_hidden_due_to_scroll_ && !overscroll_in_progress_ &&
- (selection_anchor_rect_ != selection_focus_rect_ ||
- text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
- StartTouchEditing();
- UpdateEditingController();
- }
- // fall through to reset |scroll_in_progress_|.
- case ui::ET_SCROLL_FLING_START:
- selection_gesture_in_process_ = false;
- scroll_in_progress_ = false;
+ ScrollEnded();
break;
default:
break;
@@ -210,6 +186,10 @@ void TouchEditableImplAura::GestureEventAck(int gesture_event_type) {
}
}
+void TouchEditableImplAura::DidStopFlinging() {
+ ScrollEnded();
+}
+
void TouchEditableImplAura::OnViewDestroyed() {
Cleanup();
}
@@ -280,7 +260,8 @@ void TouchEditableImplAura::OpenContextMenu(const gfx::Point& anchor) {
gfx::Point point = anchor;
ConvertPointFromScreen(&point);
RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
- host->Send(new ViewMsg_ShowContextMenu(host->GetRoutingID(), point));
+ host->Send(new ViewMsg_ShowContextMenu(
+ host->GetRoutingID(), ui::MENU_SOURCE_TOUCH_EDIT_MENU, point));
EndTouchEditing(false);
}
@@ -293,14 +274,15 @@ bool TouchEditableImplAura::IsCommandIdEnabled(int command_id) const {
if (!rwhva_)
return false;
bool editable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
+ bool readable = rwhva_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
gfx::Range selection_range;
rwhva_->GetSelectionRange(&selection_range);
bool has_selection = !selection_range.is_empty();
switch (command_id) {
case IDS_APP_CUT:
- return editable && has_selection;
+ return editable && readable && has_selection;
case IDS_APP_COPY:
- return has_selection;
+ return readable && has_selection;
case IDS_APP_PASTE: {
base::string16 result;
ui::Clipboard::GetForCurrentThread()->ReadText(
@@ -362,11 +344,23 @@ TouchEditableImplAura::TouchEditableImplAura()
rwhva_(NULL),
selection_gesture_in_process_(false),
handles_hidden_due_to_scroll_(false),
- scroll_in_progress_(false),
- overscroll_in_progress_(false),
+ scrolls_in_progress_(0),
textfield_was_focused_on_tap_(false) {
}
+void TouchEditableImplAura::ScrollEnded() {
+ scrolls_in_progress_--;
+ // If there is no scrolling left in progress, show selection handles if they
+ // were hidden due to scroll and there is a selection.
+ if (!scrolls_in_progress_ && handles_hidden_due_to_scroll_ &&
+ (selection_anchor_rect_ != selection_focus_rect_ ||
+ text_input_type_ != ui::TEXT_INPUT_TYPE_NONE)) {
+ StartTouchEditing();
+ UpdateEditingController();
+ handles_hidden_due_to_scroll_ = false;
+ }
+}
+
void TouchEditableImplAura::Cleanup() {
if (rwhva_) {
rwhva_->set_touch_editing_client(NULL);
@@ -376,8 +370,7 @@ void TouchEditableImplAura::Cleanup() {
EndTouchEditing(true);
selection_gesture_in_process_ = false;
handles_hidden_due_to_scroll_ = false;
- scroll_in_progress_ = false;
- overscroll_in_progress_ = false;
+ scrolls_in_progress_ = 0;
}
} // namespace content
diff --git a/chromium/content/browser/web_contents/touch_editable_impl_aura.h b/chromium/content/browser/web_contents/touch_editable_impl_aura.h
index dd19e8e4de6..050d559124b 100644
--- a/chromium/content/browser/web_contents/touch_editable_impl_aura.h
+++ b/chromium/content/browser/web_contents/touch_editable_impl_aura.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT TouchEditableImplAura
: public ui::TouchEditable,
public NON_EXPORTED_BASE(RenderWidgetHostViewAura::TouchEditingClient) {
public:
- virtual ~TouchEditableImplAura();
+ ~TouchEditableImplAura() override;
static TouchEditableImplAura* Create();
@@ -42,33 +42,32 @@ class CONTENT_EXPORT TouchEditableImplAura
void OverscrollCompleted();
// Overridden from RenderWidgetHostViewAura::TouchEditingClient.
- virtual void StartTouchEditing() OVERRIDE;
- virtual void EndTouchEditing(bool quick) OVERRIDE;
- virtual void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
- const gfx::Rect& focus) OVERRIDE;
- virtual void OnTextInputTypeChanged(ui::TextInputType type) OVERRIDE;
- virtual bool HandleInputEvent(const ui::Event* event) OVERRIDE;
- virtual void GestureEventAck(int gesture_event_type) OVERRIDE;
- virtual void OnViewDestroyed() OVERRIDE;
+ void StartTouchEditing() override;
+ void EndTouchEditing(bool quick) override;
+ void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
+ const gfx::Rect& focus) override;
+ void OnTextInputTypeChanged(ui::TextInputType type) override;
+ bool HandleInputEvent(const ui::Event* event) override;
+ void GestureEventAck(int gesture_event_type) override;
+ void DidStopFlinging() override;
+ void OnViewDestroyed() override;
// Overridden from ui::TouchEditable:
- virtual void SelectRect(const gfx::Point& start,
- const gfx::Point& end) OVERRIDE;
- virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE;
- virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE;
- virtual gfx::Rect GetBounds() OVERRIDE;
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE;
- virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE;
- virtual bool DrawsHandles() OVERRIDE;
- virtual void OpenContextMenu(const gfx::Point& anchor) OVERRIDE;
- virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
- virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
- virtual bool GetAcceleratorForCommandId(
- int command_id,
- ui::Accelerator* accelerator) OVERRIDE;
- virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
- virtual void DestroyTouchSelection() OVERRIDE;
+ void SelectRect(const gfx::Point& start, const gfx::Point& end) override;
+ void MoveCaretTo(const gfx::Point& point) override;
+ void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) override;
+ gfx::Rect GetBounds() override;
+ gfx::NativeView GetNativeView() const override;
+ void ConvertPointToScreen(gfx::Point* point) override;
+ void ConvertPointFromScreen(gfx::Point* point) override;
+ bool DrawsHandles() override;
+ void OpenContextMenu(const gfx::Point& anchor) override;
+ bool IsCommandIdChecked(int command_id) const override;
+ bool IsCommandIdEnabled(int command_id) const override;
+ bool GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) override;
+ void ExecuteCommand(int command_id, int event_flags) override;
+ void DestroyTouchSelection() override;
protected:
TouchEditableImplAura();
@@ -76,6 +75,10 @@ class CONTENT_EXPORT TouchEditableImplAura
private:
friend class TouchEditableImplAuraTest;
+ // A convenience function that is called after scroll/fling/overscroll ends to
+ // re-activate touch selection if necessary.
+ void ScrollEnded();
+
void Cleanup();
// Rectangles for the selection anchor and focus.
@@ -96,11 +99,8 @@ class CONTENT_EXPORT TouchEditableImplAura
// whether to re-show handles after a scrolling session.
bool handles_hidden_due_to_scroll_;
- // Keeps track of when the user is scrolling.
- bool scroll_in_progress_;
-
- // Set to true when the page starts an overscroll.
- bool overscroll_in_progress_;
+ // Keeps track of number of scrolls/flings/overscrolls in progress.
+ int scrolls_in_progress_;
// Used to track if a textfield was focused when the current tap gesture
// happened.
diff --git a/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc b/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
index 9b4757f9c88..a35f28165b3 100644
--- a/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
+++ b/chromium/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
@@ -19,12 +19,12 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/aura/test/event_generator.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ui_base_switches.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/event_utils.h"
+#include "ui/events/test/event_generator.h"
using blink::WebInputEvent;
@@ -36,24 +36,28 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
: selection_changed_callback_arrived_(false),
waiting_for_selection_changed_callback_(false),
waiting_for_gesture_ack_type_(WebInputEvent::Undefined),
- last_gesture_ack_type_(WebInputEvent::Undefined) {}
+ last_gesture_ack_type_(WebInputEvent::Undefined),
+ fling_stop_callback_arrived_(false),
+ waiting_for_fling_stop_callback_(false) {}
virtual void Reset() {
selection_changed_callback_arrived_ = false;
waiting_for_selection_changed_callback_ = false;
waiting_for_gesture_ack_type_ = WebInputEvent::Undefined;
last_gesture_ack_type_ = WebInputEvent::Undefined;
+ fling_stop_callback_arrived_ = false;
+ waiting_for_fling_stop_callback_ = false;
}
virtual void OnSelectionOrCursorChanged(const gfx::Rect& anchor,
- const gfx::Rect& focus) OVERRIDE {
+ const gfx::Rect& focus) override {
selection_changed_callback_arrived_ = true;
TouchEditableImplAura::OnSelectionOrCursorChanged(anchor, focus);
if (waiting_for_selection_changed_callback_)
selection_changed_wait_run_loop_->Quit();
}
- virtual void GestureEventAck(int gesture_event_type) OVERRIDE {
+ virtual void GestureEventAck(int gesture_event_type) override {
last_gesture_ack_type_ =
static_cast<WebInputEvent::Type>(gesture_event_type);
TouchEditableImplAura::GestureEventAck(gesture_event_type);
@@ -61,6 +65,13 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
gesture_ack_wait_run_loop_->Quit();
}
+ virtual void DidStopFlinging() override {
+ fling_stop_callback_arrived_ = true;
+ TouchEditableImplAura::DidStopFlinging();
+ if (waiting_for_fling_stop_callback_)
+ fling_stop_wait_run_loop_->Quit();
+ }
+
virtual void WaitForSelectionChangeCallback() {
if (selection_changed_callback_arrived_)
return;
@@ -77,6 +88,14 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
gesture_ack_wait_run_loop_->Run();
}
+ virtual void WaitForFlingStopCallback() {
+ if (fling_stop_callback_arrived_)
+ return;
+ waiting_for_fling_stop_callback_ = true;
+ fling_stop_wait_run_loop_.reset(new base::RunLoop());
+ fling_stop_wait_run_loop_->Run();
+ }
+
protected:
virtual ~TestTouchEditableImplAura() {}
@@ -85,8 +104,11 @@ class TestTouchEditableImplAura : public TouchEditableImplAura {
bool waiting_for_selection_changed_callback_;
WebInputEvent::Type waiting_for_gesture_ack_type_;
WebInputEvent::Type last_gesture_ack_type_;
+ bool fling_stop_callback_arrived_;
+ bool waiting_for_fling_stop_callback_;
scoped_ptr<base::RunLoop> selection_changed_wait_run_loop_;
scoped_ptr<base::RunLoop> gesture_ack_wait_run_loop_;
+ scoped_ptr<base::RunLoop> fling_stop_wait_run_loop_;
DISALLOW_COPY_AND_ASSIGN(TestTouchEditableImplAura);
};
@@ -96,7 +118,7 @@ class TouchEditableImplAuraTest : public ContentBrowserTest {
TouchEditableImplAuraTest() {}
protected:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ virtual void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kEnableTouchEditing);
}
@@ -149,7 +171,7 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
web_contents->GetRenderWidgetHostView());
aura::Window* content = web_contents->GetContentNativeView();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
gfx::Rect bounds = content->GetBoundsInRootWindow();
touch_editable->Reset();
@@ -202,14 +224,12 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
// Long press to select word.
- ui::GestureEvent long_press(ui::ET_GESTURE_LONG_PRESS,
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(
- ui::ET_GESTURE_LONG_PRESS, 0, 0),
- 1);
+ ui::GestureEvent long_press(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
touch_editable->Reset();
rwhva->OnGestureEvent(&long_press);
touch_editable->WaitForSelectionChangeCallback();
@@ -224,31 +244,83 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
EXPECT_STREQ("Some", selection.c_str());
// Start scrolling. Handles should get hidden.
- ui::GestureEvent scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN,
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(
- ui::ET_GESTURE_SCROLL_BEGIN, 0, 0),
- 1);
+ ui::GestureEvent scroll_begin(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
rwhva->OnGestureEvent(&scroll_begin);
EXPECT_FALSE(GetTouchSelectionController(touch_editable));
// Handles should come back after scroll ends.
- ui::GestureEvent scroll_end(ui::ET_GESTURE_SCROLL_END,
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(
- ui::ET_GESTURE_SCROLL_END, 0, 0),
- 1);
+ ui::GestureEvent scroll_end(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
rwhva->OnGestureEvent(&scroll_end);
EXPECT_TRUE(GetTouchSelectionController(touch_editable));
}
IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
+ TestTouchSelectionReshownAfterFling) {
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHost* main_frame = web_contents->GetMainFrame();
+ WebContentsViewAura* view_aura = static_cast<WebContentsViewAura*>(
+ web_contents->GetView());
+ TestTouchEditableImplAura* touch_editable = new TestTouchEditableImplAura;
+ view_aura->SetTouchEditableForTest(touch_editable);
+ RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
+
+ // Long press to select word.
+ ui::GestureEvent long_press(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ touch_editable->Reset();
+ rwhva->OnGestureEvent(&long_press);
+ touch_editable->WaitForSelectionChangeCallback();
+
+ // Check if selection handles are showing.
+ EXPECT_TRUE(GetTouchSelectionController(touch_editable));
+
+ scoped_ptr<base::Value> value =
+ content::ExecuteScriptAndGetValue(main_frame, "get_selection()");
+ std::string selection;
+ value->GetAsString(&selection);
+ EXPECT_STREQ("Some", selection.c_str());
+
+ // Start scrolling. Handles should get hidden.
+ ui::GestureEvent scroll_begin(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0));
+ rwhva->OnGestureEvent(&scroll_begin);
+ EXPECT_FALSE(GetTouchSelectionController(touch_editable));
+
+ // Start a fling. Handles should come back after fling stops.
+ ui::GestureEvent fling_start(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 1, 0));
+ rwhva->OnGestureEvent(&fling_start);
+ touch_editable->WaitForFlingStopCallback();
+ EXPECT_TRUE(GetTouchSelectionController(touch_editable));
+}
+
+IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
TouchSelectionOnLongPressTest) {
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
WebContentsImpl* web_contents =
@@ -263,14 +335,12 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
// Long press to select word.
- ui::GestureEvent long_press(ui::ET_GESTURE_LONG_PRESS,
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(
- ui::ET_GESTURE_LONG_PRESS, 0, 0),
- 1);
+ ui::GestureEvent long_press(
+ 10,
+ 10,
+ 0,
+ ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
touch_editable->Reset();
rwhva->OnGestureEvent(&long_press);
touch_editable->WaitForSelectionChangeCallback();
@@ -300,13 +370,9 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
// Double-tap to select word.
- ui::GestureEvent double_tap(ui::ET_GESTURE_TAP,
- 10,
- 10,
- 0,
- ui::EventTimeForNow(),
- ui::GestureEventDetails(ui::ET_GESTURE_TAP, 2, 0),
- 1);
+ ui::GestureEventDetails details(ui::ET_GESTURE_TAP);
+ details.set_tap_count(2);
+ ui::GestureEvent double_tap(10, 10, 0, ui::EventTimeForNow(), details);
touch_editable->Reset();
rwhva->OnGestureEvent(&double_tap);
touch_editable->WaitForSelectionChangeCallback();
@@ -321,8 +387,14 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
EXPECT_STREQ("Some", selection.c_str());
}
+#if defined(OS_CHROMEOS)
+// http://crbug.com/396509
+#define MAYBE_TouchCursorInTextfieldTest DISABLED_TouchCursorInTextfieldTest
+#else
+#define MAYBE_TouchCursorInTextfieldTest TouchCursorInTextfieldTest
+#endif
IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
- TouchCursorInTextfieldTest) {
+ MAYBE_TouchCursorInTextfieldTest) {
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("files/touch_selection.html"));
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
@@ -334,7 +406,7 @@ IN_PROC_BROWSER_TEST_F(TouchEditableImplAuraTest,
RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
web_contents->GetRenderWidgetHostView());
aura::Window* content = web_contents->GetContentNativeView();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
gfx::Rect bounds = content->GetBoundsInRootWindow();
EXPECT_EQ(GetRenderWidgetHostViewAura(touch_editable), rwhva);
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index fb8c0db8aa5..85490c178b8 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -6,12 +6,43 @@
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
+#include "base/command_line.h"
+#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "content/browser/android/interstitial_page_delegate_android.h"
+#include "content/browser/frame_host/interstitial_page_impl.h"
+#include "content/browser/media/android/browser_media_player_manager.h"
+#include "content/browser/media/media_web_contents_observer.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/frame_messages.h"
+#include "content/common/input_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
#include "jni/WebContentsImpl_jni.h"
using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertJavaStringToUTF16;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaGlobalRef;
+
+namespace {
+
+void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
+ const base::Value* result) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ std::string json;
+ base::JSONWriter::Write(result, &json);
+ ScopedJavaLocalRef<jstring> j_json = ConvertUTF8ToJavaString(env, json);
+ content::Java_WebContentsImpl_onEvaluateJavaScriptResult(
+ env, j_json.obj(), callback.obj());
+}
+
+} // namespace
namespace content {
@@ -62,8 +93,307 @@ ScopedJavaLocalRef<jstring> WebContentsAndroid::GetTitle(
web_contents_->GetTitle());
}
+ScopedJavaLocalRef<jstring> WebContentsAndroid::GetVisibleURL(
+ JNIEnv* env, jobject obj) const {
+ return base::android::ConvertUTF8ToJavaString(
+ env, web_contents_->GetVisibleURL().spec());
+}
+
+bool WebContentsAndroid::IsLoading(JNIEnv* env, jobject obj) const {
+ return web_contents_->IsLoading();
+}
+
+bool WebContentsAndroid::IsLoadingToDifferentDocument(JNIEnv* env,
+ jobject obj) const {
+ return web_contents_->IsLoadingToDifferentDocument();
+}
+
void WebContentsAndroid::Stop(JNIEnv* env, jobject obj) {
web_contents_->Stop();
}
+void WebContentsAndroid::InsertCSS(
+ JNIEnv* env, jobject jobj, jstring jcss) {
+ web_contents_->InsertCSS(base::android::ConvertJavaStringToUTF8(env, jcss));
+}
+
+RenderWidgetHostViewAndroid*
+ WebContentsAndroid::GetRenderWidgetHostViewAndroid() {
+ RenderWidgetHostView* rwhv = NULL;
+ rwhv = web_contents_->GetRenderWidgetHostView();
+ if (web_contents_->ShowingInterstitialPage()) {
+ rwhv = static_cast<InterstitialPageImpl*>(
+ web_contents_->GetInterstitialPage())->
+ GetRenderViewHost()->GetView();
+ }
+ return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
+}
+
+jint WebContentsAndroid::GetBackgroundColor(JNIEnv* env, jobject obj) {
+ RenderWidgetHostViewAndroid* rwhva = GetRenderWidgetHostViewAndroid();
+ if (!rwhva)
+ return SK_ColorWHITE;
+ return rwhva->GetCachedBackgroundColor();
+}
+
+ScopedJavaLocalRef<jstring> WebContentsAndroid::GetURL(JNIEnv* env,
+ jobject obj) const {
+ return ConvertUTF8ToJavaString(env, web_contents_->GetURL().spec());
+}
+
+jboolean WebContentsAndroid::IsIncognito(JNIEnv* env, jobject obj) {
+ return web_contents_->GetBrowserContext()->IsOffTheRecord();
+}
+
+void WebContentsAndroid::ResumeResponseDeferredAtStart(JNIEnv* env,
+ jobject obj) {
+ static_cast<WebContentsImpl*>(web_contents_)->ResumeResponseDeferredAtStart();
+}
+
+void WebContentsAndroid::SetHasPendingNavigationTransitionForTesting(
+ JNIEnv* env,
+ jobject obj) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ RenderFrameHost* frame =
+ static_cast<WebContentsImpl*>(web_contents_)->GetMainFrame();
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &TransitionRequestManager::AddPendingTransitionRequestDataForTesting,
+ base::Unretained(TransitionRequestManager::GetInstance()),
+ frame->GetProcess()->GetID(),
+ frame->GetRoutingID()));
+}
+
+void WebContentsAndroid::SetupTransitionView(JNIEnv* env,
+ jobject jobj,
+ jstring markup) {
+ web_contents_->GetMainFrame()->Send(new FrameMsg_SetupTransitionView(
+ web_contents_->GetMainFrame()->GetRoutingID(),
+ ConvertJavaStringToUTF8(env, markup)));
+}
+
+void WebContentsAndroid::BeginExitTransition(JNIEnv* env,
+ jobject jobj,
+ jstring css_selector) {
+ web_contents_->GetMainFrame()->Send(new FrameMsg_BeginExitTransition(
+ web_contents_->GetMainFrame()->GetRoutingID(),
+ ConvertJavaStringToUTF8(env, css_selector)));
+}
+
+void WebContentsAndroid::ClearNavigationTransitionData(JNIEnv* env,
+ jobject jobj) {
+ static_cast<WebContentsImpl*>(web_contents_)->ClearNavigationTransitionData();
+}
+
+void WebContentsAndroid::OnHide(JNIEnv* env, jobject obj) {
+ web_contents_->WasHidden();
+}
+
+void WebContentsAndroid::OnShow(JNIEnv* env, jobject obj) {
+ web_contents_->WasShown();
+}
+
+void WebContentsAndroid::ReleaseMediaPlayers(JNIEnv* env, jobject jobj) {
+#if defined(ENABLE_BROWSER_CDMS)
+ RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
+ web_contents_->GetRenderViewHost());
+ if (!rvhi || !rvhi->GetMainFrame())
+ return;
+
+ BrowserMediaPlayerManager* manager =
+ rvhi->media_web_contents_observer()->GetMediaPlayerManager(
+ rvhi->GetMainFrame());
+ if (manager)
+ manager->ReleaseAllMediaPlayers();
+#endif // defined(ENABLE_BROWSER_CDMS)
+}
+
+void WebContentsAndroid::AddStyleSheetByURL(
+ JNIEnv* env,
+ jobject obj,
+ jstring url) {
+ web_contents_->GetMainFrame()->Send(new FrameMsg_AddStyleSheetByURL(
+ web_contents_->GetMainFrame()->GetRoutingID(),
+ ConvertJavaStringToUTF8(env, url)));
+}
+
+void WebContentsAndroid::ShowInterstitialPage(
+ JNIEnv* env,
+ jobject obj,
+ jstring jurl,
+ jlong delegate_ptr) {
+ GURL url(base::android::ConvertJavaStringToUTF8(env, jurl));
+ InterstitialPageDelegateAndroid* delegate =
+ reinterpret_cast<InterstitialPageDelegateAndroid*>(delegate_ptr);
+ InterstitialPage* interstitial = InterstitialPage::Create(
+ web_contents_, false, url, delegate);
+ delegate->set_interstitial_page(interstitial);
+ interstitial->Show();
+}
+
+jboolean WebContentsAndroid::IsShowingInterstitialPage(JNIEnv* env,
+ jobject obj) {
+ return web_contents_->ShowingInterstitialPage();
+}
+
+jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
+ JNIEnv* env,
+ jobject obj) {
+ RenderWidgetHostViewAndroid* view = GetRenderWidgetHostViewAndroid();
+ return view && view->HasValidFrame();
+}
+
+void WebContentsAndroid::ExitFullscreen(JNIEnv* env, jobject obj) {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
+ host->ExitFullscreen();
+}
+
+void WebContentsAndroid::UpdateTopControlsState(
+ JNIEnv* env,
+ jobject obj,
+ bool enable_hiding,
+ bool enable_showing,
+ bool animate) {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
+ host->Send(new ViewMsg_UpdateTopControlsState(host->GetRoutingID(),
+ enable_hiding,
+ enable_showing,
+ animate));
+}
+
+void WebContentsAndroid::ShowImeIfNeeded(JNIEnv* env, jobject obj) {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
+ host->Send(new ViewMsg_ShowImeIfNeeded(host->GetRoutingID()));
+}
+
+void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
+ JNIEnv* env,
+ jobject obj) {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
+ host->Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(
+ host->GetRoutingID(), gfx::Rect()));
+}
+
+void WebContentsAndroid::SelectWordAroundCaret(JNIEnv* env, jobject obj) {
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
+ host->SelectWordAroundCaret();
+}
+
+bool WebContentsAndroid::WillHandleDeferAfterResponseStarted() {
+ JNIEnv* env = AttachCurrentThread();
+ return Java_WebContentsImpl_willHandleDeferAfterResponseStarted(env,
+ obj_.obj());
+}
+
+void WebContentsAndroid::DidDeferAfterResponseStarted(
+ const TransitionLayerData& transition_data) {
+ JNIEnv* env = AttachCurrentThread();
+ std::vector<GURL> entering_stylesheets;
+ std::string transition_color;
+ if (transition_data.response_headers.get()) {
+ TransitionRequestManager::ParseTransitionStylesheetsFromHeaders(
+ transition_data.response_headers,
+ entering_stylesheets,
+ transition_data.request_url);
+
+ transition_data.response_headers->EnumerateHeader(
+ NULL, "X-Transition-Entering-Color", &transition_color);
+ }
+
+ ScopedJavaLocalRef<jstring> jstring_markup(
+ ConvertUTF8ToJavaString(env, transition_data.markup));
+
+ ScopedJavaLocalRef<jstring> jstring_css_selector(
+ ConvertUTF8ToJavaString(env, transition_data.css_selector));
+
+ ScopedJavaLocalRef<jstring> jstring_transition_color(
+ ConvertUTF8ToJavaString(env, transition_color));
+
+ Java_WebContentsImpl_didDeferAfterResponseStarted(
+ env,
+ obj_.obj(),
+ jstring_markup.obj(),
+ jstring_css_selector.obj(),
+ jstring_transition_color.obj());
+
+ std::vector<GURL>::const_iterator iter = entering_stylesheets.begin();
+ for (; iter != entering_stylesheets.end(); ++iter) {
+ ScopedJavaLocalRef<jstring> jstring_url(
+ ConvertUTF8ToJavaString(env, iter->spec()));
+ Java_WebContentsImpl_addEnteringStylesheetToTransition(
+ env, obj_.obj(), jstring_url.obj());
+ }
+}
+
+void WebContentsAndroid::DidStartNavigationTransitionForFrame(int64 frame_id) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_WebContentsImpl_didStartNavigationTransitionForFrame(
+ env, obj_.obj(), frame_id);
+}
+
+void WebContentsAndroid::EvaluateJavaScript(JNIEnv* env,
+ jobject obj,
+ jstring script,
+ jobject callback) {
+ RenderViewHost* rvh = web_contents_->GetRenderViewHost();
+ DCHECK(rvh);
+
+ if (!rvh->IsRenderViewLive()) {
+ if (!static_cast<WebContentsImpl*>(web_contents_)->
+ CreateRenderViewForInitialEmptyDocument()) {
+ LOG(ERROR) << "Failed to create RenderView in EvaluateJavaScript";
+ return;
+ }
+ }
+
+ if (!callback) {
+ // No callback requested.
+ web_contents_->GetMainFrame()->ExecuteJavaScript(
+ ConvertJavaStringToUTF16(env, script));
+ return;
+ }
+
+ // Secure the Java callback in a scoped object and give ownership of it to the
+ // base::Callback.
+ ScopedJavaGlobalRef<jobject> j_callback;
+ j_callback.Reset(env, callback);
+ content::RenderFrameHost::JavaScriptResultCallback js_callback =
+ base::Bind(&JavaScriptResultCallback, j_callback);
+
+ web_contents_->GetMainFrame()->ExecuteJavaScript(
+ ConvertJavaStringToUTF16(env, script), js_callback);
+}
+
+// TODO(sgurun) add support for posting a frame whose name is known (only
+// main frame is supported at this time, see crbug.com/389721)
+// TODO(sgurun) add support for passing message ports
+void WebContentsAndroid::PostMessageToFrame(JNIEnv* env, jobject obj,
+ jstring frame_name, jstring message, jstring source_origin,
+ jstring target_origin) {
+
+ RenderViewHost* host = web_contents_->GetRenderViewHost();
+ if (!host)
+ return;
+ ViewMsg_PostMessage_Params params;
+ params.source_origin = ConvertJavaStringToUTF16(env, source_origin);
+ params.target_origin = ConvertJavaStringToUTF16(env, target_origin);
+ params.data = ConvertJavaStringToUTF16(env, message);
+ params.is_data_raw_string = true;
+ params.source_routing_id = MSG_ROUTING_NONE;
+ host->Send(new ViewMsg_PostMessageEvent(host->GetRoutingID(), params));
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index eec6127220a..4b79231c005 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -12,11 +12,14 @@
#include "base/compiler_specific.h"
#include "base/supports_user_data.h"
#include "content/browser/frame_host/navigation_controller_android.h"
+#include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/browser/transition_request_manager.h"
#include "content/common/content_export.h"
namespace content {
class WebContents;
+struct TransitionLayerData;
// Android wrapper around WebContents that provides safer passage from java and
// back to native and provides java with a means of communicating with its
@@ -36,9 +39,65 @@ class CONTENT_EXPORT WebContentsAndroid
// Methods called from Java
base::android::ScopedJavaLocalRef<jstring> GetTitle(JNIEnv* env,
jobject obj) const;
+ base::android::ScopedJavaLocalRef<jstring> GetVisibleURL(JNIEnv* env,
+ jobject obj) const;
+
+ bool IsLoading(JNIEnv* env, jobject obj) const;
+ bool IsLoadingToDifferentDocument(JNIEnv* env, jobject obj) const;
+
void Stop(JNIEnv* env, jobject obj);
+ jint GetBackgroundColor(JNIEnv* env, jobject obj);
+ base::android::ScopedJavaLocalRef<jstring> GetURL(JNIEnv* env, jobject) const;
+ jboolean IsIncognito(JNIEnv* env, jobject obj);
+
+ void ResumeResponseDeferredAtStart(JNIEnv* env, jobject obj);
+ void SetHasPendingNavigationTransitionForTesting(JNIEnv* env, jobject obj);
+ void SetupTransitionView(JNIEnv* env, jobject jobj, jstring markup);
+ void BeginExitTransition(JNIEnv* env, jobject jobj, jstring css_selector);
+ void ClearNavigationTransitionData(JNIEnv* env, jobject jobj);
+
+ // This method is invoked when the request is deferred immediately after
+ // receiving response headers.
+ void DidDeferAfterResponseStarted(const TransitionLayerData& transition_data);
+
+ // This method is invoked when a navigation transition is detected, to
+ // determine if the embedder intends to handle it.
+ bool WillHandleDeferAfterResponseStarted();
+ // This method is invoked when a navigation transition has started.
+ void DidStartNavigationTransitionForFrame(int64 frame_id);
+
+ void OnHide(JNIEnv* env, jobject obj);
+ void OnShow(JNIEnv* env, jobject obj);
+ void ReleaseMediaPlayers(JNIEnv* env, jobject jobj);
+
+ void AddStyleSheetByURL(
+ JNIEnv* env, jobject obj, jstring url);
+ void ShowInterstitialPage(
+ JNIEnv* env, jobject obj, jstring jurl, jlong delegate_ptr);
+ jboolean IsShowingInterstitialPage(JNIEnv* env, jobject obj);
+ jboolean IsRenderWidgetHostViewReady(JNIEnv* env, jobject obj);
+ void ExitFullscreen(JNIEnv* env, jobject obj);
+ void UpdateTopControlsState(
+ JNIEnv* env,
+ jobject obj,
+ bool enable_hiding,
+ bool enable_showing,
+ bool animate);
+ void ShowImeIfNeeded(JNIEnv* env, jobject obj);
+ void ScrollFocusedEditableNodeIntoView(JNIEnv* env, jobject obj);
+ void SelectWordAroundCaret(JNIEnv* env, jobject obj);
+
+ void InsertCSS(JNIEnv* env, jobject jobj, jstring jcss);
+ void EvaluateJavaScript(JNIEnv* env,
+ jobject obj,
+ jstring script,
+ jobject callback);
+ void PostMessageToFrame(JNIEnv* env, jobject obj, jstring frame_id,
+ jstring message, jstring source_origin, jstring target_origin);
private:
+ RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid();
+
WebContents* web_contents_;
NavigationControllerAndroid navigation_controller_;
base::android::ScopedJavaGlobalRef<jobject> obj_;
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index 817093a03f6..d3e8b13b9d3 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -18,10 +18,12 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "content/browser/accessibility/accessibility_mode_helper.h"
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/render_view_devtools_agent_host.h"
+#include "content/browser/devtools/devtools_manager.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/download_stats.h"
@@ -34,18 +36,23 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/manifest/manifest_manager_host.h"
+#include "content/browser/media/audio_stream_monitor.h"
+#include "content/browser/media/capture/web_contents_audio_muter.h"
#include "content/browser/media/midi_dispatcher_host.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/message_port_service.h"
+#include "content/browser/plugin_content_origin_whitelist.h"
#include "content/browser/power_save_blocker_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/browser/screen_orientation/screen_orientation_dispatcher_host.h"
+#include "content/browser/screen_orientation/screen_orientation_dispatcher_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/web_contents/web_contents_view_guest.h"
#include "content/browser/webui/generic_handler.h"
@@ -72,7 +79,9 @@
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/resource_request_details.h"
+#include "content/public/browser/screen_orientation_dispatcher_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents_delegate.h"
@@ -84,6 +93,7 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
+#include "content/public/common/web_preferences.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"
#include "net/http/http_cache.h"
@@ -94,70 +104,17 @@
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
#include "ui/gl/gl_switches.h"
-#include "webkit/common/webpreferences.h"
#if defined(OS_ANDROID)
#include "content/browser/android/date_time_chooser_android.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/web_contents/web_contents_android.h"
-#include "content/public/browser/android/content_view_core.h"
#endif
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#endif
-// Cross-Site Navigations
-//
-// If a WebContentsImpl is told to navigate to a different web site (as
-// determined by SiteInstance), it will replace its current RenderViewHost with
-// a new RenderViewHost dedicated to the new SiteInstance. This works as
-// follows:
-//
-// - RVHM::Navigate determines whether the destination is cross-site, and if so,
-// it creates a pending_render_view_host_.
-// - The pending RVH is "suspended," so that no navigation messages are sent to
-// its renderer until the beforeunload JavaScript handler has a chance to
-// run in the current RVH.
-// - The pending RVH tells CrossSiteRequestManager (a thread-safe singleton)
-// that it has a pending cross-site request. We will check this on the IO
-// thread when deciding how to handle the response.
-// - The current RVH runs its beforeunload handler. If it returns false, we
-// cancel all the pending logic. Otherwise we allow the pending RVH to send
-// the navigation request to its renderer.
-// - ResourceDispatcherHost receives a ResourceRequest on the IO thread for the
-// main resource load on the pending RVH. It creates a
-// CrossSiteResourceHandler to check whether a process swap is needed when
-// the request is ready to commit.
-// - When RDH receives a response, the BufferedResourceHandler determines
-// whether it is a download. If so, it sends a message to the new renderer
-// causing it to cancel the request, and the download proceeds. For now, the
-// pending RVH remains until the next DidNavigate event for this
-// WebContentsImpl. This isn't ideal, but it doesn't affect any functionality.
-// - After RDH receives a response and determines that it is safe and not a
-// download, the CrossSiteResourceHandler checks whether a process swap is
-// needed (either because CrossSiteRequestManager has state for it or because
-// a transfer was needed for a redirect).
-// - If so, CrossSiteResourceHandler pauses the response to first run the old
-// page's unload handler. It does this by asynchronously calling the
-// OnCrossSiteResponse method of RenderFrameHostManager on the UI thread,
-// which sends a SwapOut message to the current RVH.
-// - Once the unload handler is finished, RVHM::SwappedOut checks if a transfer
-// to a new process is needed, based on the stored pending_nav_params_. (This
-// is independent of whether we started out with a cross-process navigation.)
-// - If not, it just tells the ResourceDispatcherHost to resume the response
-// to its current RenderViewHost.
-// - If so, it cancels the current pending RenderViewHost and sets up a new
-// navigation using RequestTransferURL. When the transferred request
-// arrives in the ResourceDispatcherHost, we transfer the response and
-// resume it.
-// - The pending renderer sends a FrameNavigate message that invokes the
-// DidNavigate method. This replaces the current RVH with the
-// pending RVH.
-// - The previous renderer is kept swapped out in RenderFrameHostManager in case
-// the user goes back. The process only stays live if another tab is using
-// it, but if so, the existing frame relationships will be maintained.
-
namespace content {
namespace {
@@ -176,7 +133,7 @@ const char kWebContentsAndroidKey[] = "web_contents_android";
base::LazyInstance<std::vector<WebContentsImpl::CreatedCallback> >
g_created_callbacks = LAZY_INSTANCE_INITIALIZER;
-static int StartDownload(content::RenderFrameHost* rfh,
+static int StartDownload(RenderFrameHost* rfh,
const GURL& url,
bool is_favicon,
uint32_t max_bitmap_size) {
@@ -212,6 +169,16 @@ bool ForEachFrameInternal(
return true;
}
+bool ForEachPendingFrameInternal(
+ const base::Callback<void(RenderFrameHost*)>& on_frame,
+ FrameTreeNode* node) {
+ RenderFrameHost* pending_frame_host =
+ node->render_manager()->pending_frame_host();
+ if (pending_frame_host)
+ on_frame.Run(pending_frame_host);
+ return true;
+}
+
void SendToAllFramesInternal(IPC::Message* message, RenderFrameHost* rfh) {
IPC::Message* message_copy = new IPC::Message(*message);
message_copy->set_routing_id(rfh->GetRoutingID());
@@ -227,6 +194,11 @@ void AddRenderWidgetHostViewToSet(std::set<RenderWidgetHostView*>* set,
set->insert(rwhv);
}
+void SetAccessibilityModeOnFrame(AccessibilityMode mode,
+ RenderFrameHost* frame_host) {
+ static_cast<RenderFrameHostImpl*>(frame_host)->SetAccessibilityMode(mode);
+}
+
} // namespace
WebContents* WebContents::Create(const WebContents::CreateParams& params) {
@@ -286,7 +258,7 @@ class WebContentsImpl::DestructionObserver : public WebContentsObserver {
}
// WebContentsObserver:
- virtual void WebContentsDestroyed() OVERRIDE {
+ void WebContentsDestroyed() override {
owner_->OnWebContentsDestroyed(
static_cast<WebContentsImpl*>(web_contents()));
}
@@ -312,9 +284,8 @@ WebContentsImpl::ColorChooserInfo::~ColorChooserInfo() {
// WebContentsImpl -------------------------------------------------------------
-WebContentsImpl::WebContentsImpl(
- BrowserContext* browser_context,
- WebContentsImpl* opener)
+WebContentsImpl::WebContentsImpl(BrowserContext* browser_context,
+ WebContentsImpl* opener)
: delegate_(NULL),
controller_(this, browser_context),
render_view_host_delegate_view_(NULL),
@@ -324,7 +295,10 @@ WebContentsImpl::WebContentsImpl(
accessible_parent_(NULL),
#endif
frame_tree_(new NavigatorImpl(&controller_, this),
- this, this, this, this),
+ this,
+ this,
+ this,
+ this),
is_loading_(false),
is_load_to_different_document_(false),
crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
@@ -332,7 +306,6 @@ WebContentsImpl::WebContentsImpl(
waiting_for_response_(false),
load_state_(net::LOAD_STATE_IDLE, base::string16()),
loading_total_progress_(0.0),
- loading_weak_factory_(this),
loading_frames_in_progress_(0),
upload_size_(0),
upload_position_(0),
@@ -352,9 +325,15 @@ WebContentsImpl::WebContentsImpl(
currentPinchZoomStepDelta_(0),
render_view_message_source_(NULL),
fullscreen_widget_routing_id_(MSG_ROUTING_NONE),
+ fullscreen_widget_had_focus_at_shutdown_(false),
is_subframe_(false),
- touch_emulation_enabled_(false),
- last_dialog_suppressed_(false) {
+ force_disable_overscroll_content_(false),
+ last_dialog_suppressed_(false),
+ geolocation_service_context_(new GeolocationServiceContext()),
+ accessibility_mode_(
+ BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
+ audio_stream_monitor_(this),
+ loading_weak_factory_(this) {
for (size_t i = 0; i < g_created_callbacks.Get().size(); i++)
g_created_callbacks.Get().at(i).Run(this);
frame_tree_.SetFrameRemoveListener(
@@ -439,17 +418,10 @@ WebContentsImpl* WebContentsImpl::CreateWithOpener(
WebContentsImpl* new_contents = new WebContentsImpl(
params.browser_context, params.opener_suppressed ? NULL : opener);
- if (params.guest_instance_id) {
- scoped_ptr<base::DictionaryValue> extra_params;
- if (params.guest_extra_params)
- extra_params.reset(params.guest_extra_params->DeepCopy());
+ if (params.guest_delegate) {
// This makes |new_contents| act as a guest.
// For more info, see comment above class BrowserPluginGuest.
- BrowserPluginGuest::Create(params.guest_instance_id,
- params.site_instance,
- new_contents,
- extra_params.Pass(),
- opener ? opener->GetBrowserPluginGuest() : NULL);
+ BrowserPluginGuest::Create(new_contents, params.guest_delegate);
// We are instantiating a WebContents for browser plugin. Set its subframe
// bit to true.
new_contents->is_subframe_ = true;
@@ -458,6 +430,30 @@ WebContentsImpl* WebContentsImpl::CreateWithOpener(
return new_contents;
}
+// static
+std::vector<WebContentsImpl*> WebContentsImpl::GetAllWebContents() {
+ std::vector<WebContentsImpl*> result;
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHostImpl::GetRenderWidgetHosts());
+ std::set<WebContentsImpl*> web_contents_set;
+ while (RenderWidgetHost* rwh = widgets->GetNextHost()) {
+ if (!rwh->IsRenderView())
+ continue;
+ RenderViewHost* rvh = RenderViewHost::From(rwh);
+ if (!rvh)
+ continue;
+ WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
+ if (!web_contents)
+ continue;
+ WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents);
+ if (web_contents_set.find(wci) == web_contents_set.end()) {
+ web_contents_set.insert(wci);
+ result.push_back(wci);
+ }
+ }
+ return result;
+}
+
RenderFrameHostManager* WebContentsImpl::GetRenderManagerForTesting() {
return GetRenderManager();
}
@@ -491,22 +487,13 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
// Message handlers should be aware of which
// RenderViewHost/RenderFrameHost sent the message, which is temporarily
// stored in render_(view|frame)_message_source_.
- if (render_frame_host) {
- if (RenderViewDevToolsAgentHost::DispatchIPCMessage(
- render_frame_host->GetRenderViewHost(), message))
- return true;
+ if (render_frame_host)
render_frame_message_source_ = render_frame_host;
- } else {
- if (RenderViewDevToolsAgentHost::DispatchIPCMessage(
- render_view_host, message))
- return true;
+ else
render_view_message_source_ = render_view_host;
- }
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebContentsImpl, message)
- IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
- IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
IPC_MESSAGE_HANDLER(FrameHostMsg_DomOperationResponse,
OnDomOperationResponse)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeThemeColor,
@@ -526,6 +513,8 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
OnMediaPlayingNotification)
IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
OnMediaPausedNotification)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_DidFirstVisuallyNonEmptyPaint,
+ OnFirstVisuallyNonEmptyPaint)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
OnDidLoadResourceFromMemoryCache)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
@@ -537,17 +526,21 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
IPC_MESSAGE_HANDLER(ViewHostMsg_EnumerateDirectory, OnEnumerateDirectory)
IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterProtocolHandler,
OnRegisterProtocolHandler)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterProtocolHandler,
+ OnUnregisterProtocolHandler)
IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
+#if defined(ENABLE_PLUGINS)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_PepperPluginHung, OnPepperPluginHung)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_PluginCrashed, OnPluginCrashed)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestPpapiBrokerPermission,
OnRequestPpapiBrokerPermission)
IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginHostMsg_Attach,
OnBrowserPluginMessage(message))
+#endif
IPC_MESSAGE_HANDLER(ImageHostMsg_DidDownloadImage, OnDidDownloadImage)
IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateFaviconURL, OnUpdateFaviconURL)
- IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstVisuallyNonEmptyPaint,
- OnFirstVisuallyNonEmptyPaint)
IPC_MESSAGE_HANDLER(ViewHostMsg_ShowValidationMessage,
OnShowValidationMessage)
IPC_MESSAGE_HANDLER(ViewHostMsg_HideValidationMessage,
@@ -680,6 +673,32 @@ WebContentsView* WebContentsImpl::GetView() const {
return view_.get();
}
+void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) {
+ if (mode == accessibility_mode_)
+ return;
+
+ accessibility_mode_ = mode;
+ frame_tree_.ForEach(
+ base::Bind(&ForEachFrameInternal,
+ base::Bind(&SetAccessibilityModeOnFrame, mode)));
+ frame_tree_.ForEach(
+ base::Bind(&ForEachPendingFrameInternal,
+ base::Bind(&SetAccessibilityModeOnFrame, mode)));
+}
+
+void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode) {
+ SetAccessibilityMode(AddAccessibilityModeTo(accessibility_mode_, mode));
+}
+
+void WebContentsImpl::RemoveAccessibilityMode(AccessibilityMode mode) {
+ SetAccessibilityMode(RemoveAccessibilityModeFrom(accessibility_mode_, mode));
+}
+
+void WebContentsImpl::ClearNavigationTransitionData() {
+ FrameTreeNode* node = frame_tree_.root();
+ node->render_manager()->ClearNavigationTransitionData();
+}
+
WebUI* WebContentsImpl::CreateWebUI(const GURL& url) {
WebUIImpl* web_ui = new WebUIImpl(this);
WebUIController* controller = WebUIControllerFactoryRegistry::GetInstance()->
@@ -728,12 +747,25 @@ const std::string& WebContentsImpl::GetUserAgentOverride() const {
return renderer_preferences_.user_agent_override;
}
+void WebContentsImpl::EnableTreeOnlyAccessibilityMode() {
+ AddAccessibilityMode(AccessibilityModeTreeOnly);
+}
+
+bool WebContentsImpl::IsTreeOnlyAccessibilityModeForTesting() const {
+ return accessibility_mode_ == AccessibilityModeTreeOnly;
+}
+
+bool WebContentsImpl::IsFullAccessibilityModeForTesting() const {
+ return accessibility_mode_ == AccessibilityModeComplete;
+}
+
#if defined(OS_WIN)
void WebContentsImpl::SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) {
accessible_parent_ = accessible_parent;
- if (GetRenderViewHost())
- GetRenderViewHostImpl()->SetParentNativeViewAccessible(accessible_parent);
+ RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
+ if (rfh)
+ rfh->SetParentNativeViewAccessible(accessible_parent);
}
#endif
@@ -819,14 +851,15 @@ void WebContentsImpl::CopyMaxPageIDsFrom(WebContents* web_contents) {
max_page_ids_ = contents->max_page_ids_;
}
-SiteInstance* WebContentsImpl::GetSiteInstance() const {
+SiteInstanceImpl* WebContentsImpl::GetSiteInstance() const {
return GetRenderManager()->current_host()->GetSiteInstance();
}
-SiteInstance* WebContentsImpl::GetPendingSiteInstance() const {
- RenderViewHost* dest_rvh = GetRenderManager()->pending_render_view_host() ?
- GetRenderManager()->pending_render_view_host() :
- GetRenderManager()->current_host();
+SiteInstanceImpl* WebContentsImpl::GetPendingSiteInstance() const {
+ RenderViewHostImpl* dest_rvh =
+ GetRenderManager()->pending_render_view_host() ?
+ GetRenderManager()->pending_render_view_host() :
+ GetRenderManager()->current_host();
return dest_rvh->GetSiteInstance();
}
@@ -913,6 +946,30 @@ int WebContentsImpl::GetCapturerCount() const {
return capturer_count_;
}
+bool WebContentsImpl::IsAudioMuted() const {
+ return audio_muter_.get() && audio_muter_->is_muting();
+}
+
+void WebContentsImpl::SetAudioMuted(bool mute) {
+ DVLOG(1) << "SetAudioMuted(mute=" << mute << "), was " << IsAudioMuted()
+ << " for WebContentsImpl@" << this;
+
+ if (mute == IsAudioMuted())
+ return;
+
+ if (mute) {
+ if (!audio_muter_)
+ audio_muter_.reset(new WebContentsAudioMuter(this));
+ audio_muter_->StartMuting();
+ } else {
+ DCHECK(audio_muter_);
+ audio_muter_->StopMuting();
+ }
+
+ // Notification for UI updates in response to the changed muting state.
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+}
+
bool WebContentsImpl::IsCrashed() const {
return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
@@ -937,7 +994,20 @@ bool WebContentsImpl::IsBeingDestroyed() const {
return is_being_destroyed_;
}
-void WebContentsImpl::NotifyNavigationStateChanged(unsigned changed_flags) {
+void WebContentsImpl::NotifyNavigationStateChanged(
+ InvalidateTypes changed_flags) {
+ // Create and release the audio power save blocker depending on whether the
+ // tab is actively producing audio or not.
+ if (changed_flags == INVALIDATE_TYPE_TAB &&
+ AudioStreamMonitor::monitoring_available()) {
+ if (WasRecentlyAudible()) {
+ if (!audio_power_save_blocker_)
+ CreateAudioPowerSaveBlocker();
+ } else {
+ audio_power_save_blocker_.reset();
+ }
+ }
+
if (delegate_)
delegate_->NavigationStateChanged(this, changed_flags);
}
@@ -971,6 +1041,10 @@ void WebContentsImpl::WasShown() {
rvh->ResizeRectChanged(GetRootWindowResizerRect());
}
+ // Restore power save blocker if there are active video players running.
+ if (!active_video_players_.empty() && !video_power_save_blocker_)
+ CreateVideoPowerSaveBlocker();
+
FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasShown());
should_normally_be_visible_ = true;
@@ -993,6 +1067,9 @@ void WebContentsImpl::WasHidden() {
if (*iter)
(*iter)->Hide();
}
+
+ // Release any video power save blockers held as video is not visible.
+ video_power_save_blocker_.reset();
}
FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
@@ -1038,11 +1115,21 @@ void WebContentsImpl::Observe(int type,
switch (type) {
case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
RenderWidgetHost* host = Source<RenderWidgetHost>(source).ptr();
- for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
- i != pending_widget_views_.end(); ++i) {
- if (host->GetView() == i->second) {
- pending_widget_views_.erase(i);
- break;
+ RenderWidgetHostView* view = host->GetView();
+ if (view == GetFullscreenRenderWidgetHostView()) {
+ // We cannot just call view_->RestoreFocus() here. On some platforms,
+ // attempting to focus the currently-invisible WebContentsView will be
+ // flat-out ignored. Therefore, this boolean is used to track whether
+ // we will request focus after the fullscreen widget has been
+ // destroyed.
+ fullscreen_widget_had_focus_at_shutdown_ = (view && view->HasFocus());
+ } else {
+ for (PendingWidgetViews::iterator i = pending_widget_views_.begin();
+ i != pending_widget_views_.end(); ++i) {
+ if (host->GetView() == i->second) {
+ pending_widget_views_.erase(i);
+ break;
+ }
}
}
break;
@@ -1093,6 +1180,11 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
if (opener_)
AddDestructionObserver(opener_);
+#if defined(ENABLE_PLUGINS)
+ plugin_content_origin_whitelist_.reset(
+ new PluginContentOriginWhitelist(this));
+#endif
+
registrar_.Add(this,
NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
NotificationService::AllBrowserContextsAndSources());
@@ -1101,7 +1193,9 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
midi_dispatcher_host_.reset(new MidiDispatcherHost(this));
screen_orientation_dispatcher_host_.reset(
- new ScreenOrientationDispatcherHost(this));
+ new ScreenOrientationDispatcherHostImpl(this));
+
+ manifest_manager_host_.reset(new ManifestManagerHost(this));
#if defined(OS_ANDROID)
date_time_chooser_.reset(new DateTimeChooserAndroid());
@@ -1200,9 +1294,20 @@ void WebContentsImpl::RenderWidgetDeleted(
DidDestroyFullscreenWidget(
fullscreen_widget_routing_id_));
fullscreen_widget_routing_id_ = MSG_ROUTING_NONE;
+ if (fullscreen_widget_had_focus_at_shutdown_)
+ view_->RestoreFocus();
}
}
+void WebContentsImpl::RenderWidgetGotFocus(
+ RenderWidgetHostImpl* render_widget_host) {
+ // Notify the delegate if an embedded fullscreen widget was focused.
+ if (delegate_ && render_widget_host &&
+ delegate_->EmbedsFullscreenWidget() &&
+ render_widget_host->GetView() == GetFullscreenRenderWidgetHostView())
+ delegate_->WebContentsFocused(this);
+}
+
bool WebContentsImpl::PreHandleKeyboardEvent(
const NativeWebKeyboardEvent& event,
bool* is_keyboard_shortcut) {
@@ -1211,6 +1316,10 @@ bool WebContentsImpl::PreHandleKeyboardEvent(
}
void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
+ if (browser_plugin_embedder_ &&
+ browser_plugin_embedder_->HandleKeyboardEvent(event)) {
+ return;
+ }
if (delegate_)
delegate_->HandleKeyboardEvent(this, event);
}
@@ -1282,12 +1391,6 @@ bool WebContentsImpl::HandleGestureEvent(
return false;
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
- return accessible_parent_;
-}
-#endif
-
void WebContentsImpl::HandleMouseDown() {
if (delegate_)
delegate_->HandleMouseDown();
@@ -1378,7 +1481,7 @@ void WebContentsImpl::CreateNewWindow(
if (process_handle != base::kNullProcessHandle) {
RecordAction(
base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow"));
- base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
+ base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
}
return;
}
@@ -1428,15 +1531,15 @@ void WebContentsImpl::CreateNewWindow(
if (params.disposition == NEW_BACKGROUND_TAB)
create_params.initially_hidden = true;
+ WebContentsImpl* new_contents = NULL;
if (!is_guest) {
create_params.context = view_->GetNativeView();
create_params.initial_size = GetContainerBounds().size();
- } else {
- create_params.guest_instance_id =
- GetBrowserContext()->GetGuestManager()->GetNextInstanceID();
+ new_contents = static_cast<WebContentsImpl*>(
+ WebContents::Create(create_params));
+ } else {
+ new_contents = GetBrowserPluginGuest()->CreateNewGuestWindow(create_params);
}
- WebContentsImpl* new_contents = static_cast<WebContentsImpl*>(
- WebContents::Create(create_params));
new_contents->GetController().SetSessionStorageNamespace(
partition_id,
session_storage_namespace);
@@ -1450,7 +1553,7 @@ void WebContentsImpl::CreateNewWindow(
// TODO(brettw): It seems bogus that we have to call this function on the
// newly created object and give it one of its own member variables.
- new_view->CreateViewForWidget(new_contents->GetRenderViewHost());
+ new_view->CreateViewForWidget(new_contents->GetRenderViewHost(), false);
}
// Save the created window associated with the route so we can show it
// later.
@@ -1479,7 +1582,7 @@ void WebContentsImpl::CreateNewWindow(
OpenURLParams open_params(params.target_url,
Referrer(),
CURRENT_TAB,
- PAGE_TRANSITION_LINK,
+ ui::PAGE_TRANSITION_LINK,
true /* is_renderer_initiated */);
open_params.user_gesture = params.user_gesture;
new_contents->OpenURL(open_params);
@@ -1512,7 +1615,7 @@ void WebContentsImpl::CreateNewWidget(int render_process_id,
if (process_handle != base::kNullProcessHandle) {
RecordAction(
base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
- base::KillProcess(process_handle, content::RESULT_CODE_KILLED, false);
+ base::KillProcess(process_handle, RESULT_CODE_KILLED, false);
}
return;
}
@@ -1581,6 +1684,7 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
if (is_fullscreen) {
DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
+ view_->StoreFocus();
fullscreen_widget_routing_id_ = route_id;
if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
@@ -1633,8 +1737,11 @@ WebContentsImpl* WebContentsImpl::GetCreatedWindow(int route_id) {
!new_contents->GetRenderViewHost()->GetView())
return NULL;
+ // Resume blocked requests for both the RenderViewHost and RenderFrameHost.
// TODO(brettw): It seems bogus to reach into here and initialize the host.
static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init();
+ static_cast<RenderFrameHostImpl*>(new_contents->GetMainFrame())->Init();
+
return new_contents;
}
@@ -1664,11 +1771,19 @@ void WebContentsImpl::RequestMediaAccessPermission(
delegate_->RequestMediaAccessPermission(this, request, callback);
} else {
callback.Run(MediaStreamDevices(),
- MEDIA_DEVICE_INVALID_STATE,
+ MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
scoped_ptr<MediaStreamUI>());
}
}
+bool WebContentsImpl::CheckMediaAccessPermission(const GURL& security_origin,
+ MediaStreamType type) {
+ DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
+ type == MEDIA_DEVICE_VIDEO_CAPTURE);
+ return delegate_ &&
+ delegate_->CheckMediaAccessPermission(this, security_origin, type);
+}
+
SessionStorageNamespace* WebContentsImpl::GetSessionStorageNamespace(
SiteInstance* instance) {
return controller_.GetSessionStorageNamespace(instance);
@@ -1682,12 +1797,31 @@ FrameTree* WebContentsImpl::GetFrameTree() {
return &frame_tree_;
}
+AccessibilityMode WebContentsImpl::GetAccessibilityMode() const {
+ return accessibility_mode_;
+}
+
void WebContentsImpl::AccessibilityEventReceived(
const std::vector<AXEventNotificationDetails>& details) {
FOR_EACH_OBSERVER(
WebContentsObserver, observers_, AccessibilityEventReceived(details));
}
+RenderFrameHost* WebContentsImpl::GetGuestByInstanceID(
+ int browser_plugin_instance_id) {
+ BrowserPluginGuestManager* guest_manager =
+ GetBrowserContext()->GetGuestManager();
+ WebContents* guest = guest_manager->GetGuestByInstanceID(
+ this, browser_plugin_instance_id);
+ if (!guest)
+ return NULL;
+ return guest->GetMainFrame();
+}
+
+GeolocationServiceContext* WebContentsImpl::GetGeolocationServiceContext() {
+ return geolocation_service_context_.get();
+}
+
void WebContentsImpl::OnShowValidationMessage(
const gfx::Rect& anchor_in_root_view,
const base::string16& main_text,
@@ -1713,10 +1847,16 @@ void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
browser_plugin_embedder_->DidSendScreenRects();
}
-void WebContentsImpl::OnTouchEmulationEnabled(bool enabled) {
- touch_emulation_enabled_ = enabled;
- if (view_)
- view_->SetOverscrollControllerEnabled(CanOverscrollContent());
+BrowserAccessibilityManager*
+ WebContentsImpl::GetRootBrowserAccessibilityManager() {
+ RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
+ return rfh ? rfh->browser_accessibility_manager() : NULL;
+}
+
+BrowserAccessibilityManager*
+ WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() {
+ RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame());
+ return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : NULL;
}
void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) {
@@ -1751,13 +1891,16 @@ bool WebContentsImpl::NavigateToPendingEntry(
NavigationController::ReloadType reload_type) {
FrameTreeNode* node = frame_tree_.root();
- // If we are using --site-per-process, we should navigate in the FrameTreeNode
- // specified in the pending entry.
+ // Navigate in the FrameTreeNode specified in the pending entry, if any. This
+ // is currently only used in --site-per-process and tests.
NavigationEntryImpl* pending_entry =
NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry());
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
- pending_entry->frame_tree_node_id() != -1) {
- node = frame_tree_.FindByID(pending_entry->frame_tree_node_id());
+ if (pending_entry->frame_tree_node_id() != -1) {
+ FrameTreeNode* subframe =
+ frame_tree_.FindByID(pending_entry->frame_tree_node_id());
+ DCHECK(subframe);
+ if (subframe)
+ node = subframe;
}
return node->navigator()->NavigateToPendingEntry(
@@ -2003,6 +2146,12 @@ void WebContentsImpl::FocusThroughTabTraversal(bool reverse) {
GetRenderManager()->interstitial_page()->FocusThroughTabTraversal(reverse);
return;
}
+ RenderWidgetHostView* const fullscreen_view =
+ GetFullscreenRenderWidgetHostView();
+ if (fullscreen_view) {
+ fullscreen_view->Focus();
+ return;
+ }
GetRenderViewHostImpl()->SetInitialFocus(reverse);
}
@@ -2176,18 +2325,6 @@ bool WebContentsImpl::GetClosedByUserGesture() const {
return closed_by_user_gesture_;
}
-int WebContentsImpl::GetZoomPercent(bool* enable_increment,
- bool* enable_decrement) const {
- *enable_decrement = *enable_increment = false;
- // Calculate the zoom percent from the factor. Round up to the nearest whole
- // number.
- int percent = static_cast<int>(
- ZoomLevelToZoomFactor(HostZoomMap::GetZoomLevel(this)) * 100 + 0.5);
- *enable_decrement = percent > minimum_zoom_percent_;
- *enable_increment = percent < maximum_zoom_percent_;
- return percent;
-}
-
void WebContentsImpl::ViewSource() {
if (!delegate_)
return;
@@ -2274,6 +2411,11 @@ bool WebContentsImpl::IsSubframe() const {
void WebContentsImpl::Find(int request_id,
const base::string16& search_text,
const blink::WebFindOptions& options) {
+ // See if a top level browser plugin handles the find request first.
+ if (browser_plugin_embedder_ &&
+ browser_plugin_embedder_->Find(request_id, search_text, options)) {
+ return;
+ }
Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
}
@@ -2286,6 +2428,14 @@ void WebContentsImpl::InsertCSS(const std::string& css) {
GetMainFrame()->GetRoutingID(), css));
}
+bool WebContentsImpl::WasRecentlyAudible() {
+ return audio_stream_monitor_.WasRecentlyAudible();
+}
+
+void WebContentsImpl::GetManifest(const GetManifestCallback& callback) {
+ manifest_manager_host_->GetManifest(GetMainFrame(), callback);
+}
+
bool WebContentsImpl::FocusLocationBarByDefault() {
NavigationEntry* entry = controller_.GetVisibleEntry();
if (entry && entry->GetURL() == GURL(url::kAboutBlankURL))
@@ -2300,47 +2450,36 @@ void WebContentsImpl::SetFocusToLocationBar(bool select_all) {
void WebContentsImpl::DidStartProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
- int parent_routing_id,
const GURL& validated_url,
bool is_error_page,
bool is_iframe_srcdoc) {
- bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
-
// Notify observers about the start of the provisional load.
- int render_frame_id = render_frame_host->GetRoutingID();
- RenderViewHost* render_view_host = render_frame_host->render_view_host();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidStartProvisionalLoadForFrame(
- render_frame_id, parent_routing_id, is_main_frame,
- validated_url, is_error_page, is_iframe_srcdoc,
- render_view_host));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver,
+ observers_,
+ DidStartProvisionalLoadForFrame(
+ render_frame_host, validated_url, is_error_page, is_iframe_srcdoc));
+}
- if (is_main_frame) {
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- ProvisionalChangeToMainFrameUrl(validated_url,
- render_frame_host));
- }
+void WebContentsImpl::DidStartNavigationTransition(
+ RenderFrameHostImpl* render_frame_host) {
+#if defined(OS_ANDROID)
+ int render_frame_id = render_frame_host->GetRoutingID();
+ GetWebContentsAndroid()->DidStartNavigationTransitionForFrame(
+ render_frame_id);
+#endif
}
void WebContentsImpl::DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
GURL validated_url(params.url);
- int render_frame_id = render_frame_host->GetRoutingID();
- bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
- RenderViewHost* render_view_host = render_frame_host->render_view_host();
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- DidFailProvisionalLoad(render_frame_id,
- params.frame_unique_name,
- is_main_frame,
- validated_url,
- params.error_code,
- params.error_description,
- render_view_host));
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ DidFailProvisionalLoad(render_frame_host,
+ validated_url,
+ params.error_code,
+ params.error_description));
}
void WebContentsImpl::DidFailLoadWithError(
@@ -2348,12 +2487,10 @@ void WebContentsImpl::DidFailLoadWithError(
const GURL& url,
int error_code,
const base::string16& error_description) {
- int render_frame_id = render_frame_host->GetRoutingID();
- bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
- RenderViewHost* render_view_host = render_frame_host->render_view_host();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidFailLoad(render_frame_id, url, is_main_frame, error_code,
- error_description, render_view_host));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver,
+ observers_,
+ DidFailLoad(render_frame_host, url, error_code, error_description));
}
void WebContentsImpl::NotifyChangedNavigationState(
@@ -2405,45 +2542,23 @@ bool WebContentsImpl::ShouldPreserveAbortedURLs() {
return delegate_->ShouldPreserveAbortedURLs(this);
}
-void WebContentsImpl::DidRedirectProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& validated_target_url) {
- // Notify observers about the provisional change in the main frame URL.
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- ProvisionalChangeToMainFrameUrl(validated_target_url,
- render_frame_host));
-}
-
void WebContentsImpl::DidCommitProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
- const base::string16& frame_unique_name,
- bool is_main_frame,
const GURL& url,
- PageTransition transition_type) {
- int render_frame_id = render_frame_host->GetRoutingID();
- RenderViewHost* render_view_host = render_frame_host->render_view_host();
+ ui::PageTransition transition_type) {
// Notify observers about the commit of the provisional load.
- FOR_EACH_OBSERVER(
- WebContentsObserver,
- observers_,
- DidCommitProvisionalLoadForFrame(render_frame_id,
- frame_unique_name,
- is_main_frame,
- url,
- transition_type,
- render_view_host));
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ DidCommitProvisionalLoadForFrame(
+ render_frame_host, url, transition_type));
}
void WebContentsImpl::DidNavigateMainFramePreCommit(
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
+ bool navigation_is_within_page) {
// Ensure fullscreen mode is exited before committing the navigation to a
// different page. The next page will not start out assuming it is in
// fullscreen mode.
- if (controller_.IsURLInPageNavigation(params.url,
- params.was_within_same_page,
- NAVIGATION_TYPE_UNKNOWN)) {
+ if (navigation_is_within_page) {
// No page change? Then, the renderer and browser can remain in fullscreen.
return;
}
@@ -2462,7 +2577,7 @@ void WebContentsImpl::DidNavigateMainFramePostCommit(
// clicking on a link); see bugs 1184641 and 980803. We don't want to
// clear the bubble when a user navigates to a named anchor in the same
// page.
- UpdateTargetURL(details.entry->GetPageID(), GURL());
+ UpdateTargetURL(GURL());
}
if (!details.is_in_page) {
@@ -2496,7 +2611,7 @@ void WebContentsImpl::DidNavigateAnyFramePostCommit(
// Notify observers about navigation.
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidNavigateAnyFrame(details, params));
+ DidNavigateAnyFrame(render_frame_host, details, params));
}
void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
@@ -2505,7 +2620,7 @@ void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) {
bool WebContentsImpl::CanOverscrollContent() const {
// Disable overscroll when touch emulation is on. See crbug.com/369938.
- if (touch_emulation_enabled_)
+ if (force_disable_overscroll_content_)
return false;
if (delegate_)
@@ -2524,7 +2639,7 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
const std::string& security_info,
const std::string& http_method,
const std::string& mime_type,
- ResourceType::Type resource_type) {
+ ResourceType resource_type) {
base::StatsCounter cache("WebKit.CacheHit");
cache.Increment();
@@ -2549,7 +2664,7 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) {
scoped_refptr<net::URLRequestContextGetter> request_context(
- resource_type == ResourceType::MEDIA ?
+ resource_type == RESOURCE_TYPE_MEDIA ?
GetBrowserContext()->GetMediaRequestContextForRenderProcess(
GetRenderProcessHost()->GetID()) :
GetBrowserContext()->GetRequestContextForRenderProcess(
@@ -2586,12 +2701,8 @@ void WebContentsImpl::OnDocumentLoadedInFrame() {
CHECK(!render_view_message_source_);
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
-
- int render_frame_id = rfh->GetRoutingID();
- RenderViewHost* render_view_host = rfh->render_view_host();
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DocumentLoadedInFrame(render_frame_id, render_view_host));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver, observers_, DocumentLoadedInFrame(rfh));
}
void WebContentsImpl::OnDidFinishLoad(
@@ -2609,12 +2720,8 @@ void WebContentsImpl::OnDidFinishLoad(
RenderFrameHostImpl* rfh =
static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
- int render_frame_id = rfh->GetRoutingID();
- RenderViewHost* render_view_host = rfh->render_view_host();
- bool is_main_frame = rfh->frame_tree_node()->IsMainFrame();
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidFinishLoad(render_frame_id, validated_url,
- is_main_frame, render_view_host));
+ FOR_EACH_OBSERVER(
+ WebContentsObserver, observers_, DidFinishLoad(rfh, validated_url));
}
void WebContentsImpl::OnDidStartLoading(bool to_different_document) {
@@ -2739,6 +2846,20 @@ void WebContentsImpl::OnRegisterProtocolHandler(const std::string& protocol,
delegate_->RegisterProtocolHandler(this, protocol, url, user_gesture);
}
+void WebContentsImpl::OnUnregisterProtocolHandler(const std::string& protocol,
+ const GURL& url,
+ bool user_gesture) {
+ if (!delegate_)
+ return;
+
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ if (policy->IsPseudoScheme(protocol))
+ return;
+
+ delegate_->UnregisterProtocolHandler(this, protocol, url, user_gesture);
+}
+
void WebContentsImpl::OnFindReply(int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
@@ -2761,7 +2882,7 @@ void WebContentsImpl::OnFindMatchRectsReply(
void WebContentsImpl::OnOpenDateTimeDialog(
const ViewHostMsg_DateTimeDialogValue_Params& value) {
- date_time_chooser_->ShowDialog(ContentViewCore::FromWebContents(this),
+ date_time_chooser_->ShowDialog(GetTopLevelNativeWindow(),
GetRenderViewHost(),
value.dialog_type,
value.dialog_value,
@@ -2770,24 +2891,8 @@ void WebContentsImpl::OnOpenDateTimeDialog(
value.step,
value.suggestions);
}
-
#endif
-void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
- const base::FilePath& path,
- bool is_hung) {
- UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
-
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PluginHungStatusChanged(plugin_child_id, path, is_hung));
-}
-
-void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
- base::ProcessId plugin_pid) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- PluginCrashed(plugin_path, plugin_pid));
-}
-
void WebContentsImpl::OnDomOperationResponse(const std::string& json_string,
int automation_id) {
DomOperationNotificationDetails details(json_string, automation_id);
@@ -2845,6 +2950,22 @@ void WebContentsImpl::OnWebUISend(const GURL& source_url,
delegate_->WebUISend(this, source_url, name, args);
}
+#if defined(ENABLE_PLUGINS)
+void WebContentsImpl::OnPepperPluginHung(int plugin_child_id,
+ const base::FilePath& path,
+ bool is_hung) {
+ UMA_HISTOGRAM_COUNTS("Pepper.PluginHung", 1);
+
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ PluginHungStatusChanged(plugin_child_id, path, is_hung));
+}
+
+void WebContentsImpl::OnPluginCrashed(const base::FilePath& plugin_path,
+ base::ProcessId plugin_pid) {
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ PluginCrashed(plugin_path, plugin_pid));
+}
+
void WebContentsImpl::OnRequestPpapiBrokerPermission(
int routing_id,
const GURL& url,
@@ -2878,6 +2999,7 @@ void WebContentsImpl::OnBrowserPluginMessage(const IPC::Message& message) {
browser_plugin_embedder_.reset(BrowserPluginEmbedder::Create(this));
browser_plugin_embedder_->OnMessageReceived(message);
}
+#endif // defined(ENABLE_PLUGINS)
void WebContentsImpl::OnDidDownloadImage(
int id,
@@ -2907,37 +3029,75 @@ void WebContentsImpl::OnUpdateFaviconURL(
DidUpdateFaviconURL(candidates));
}
-void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie,
- bool has_video,
- bool has_audio) {
-// Chrome OS does its own detection of audio and video.
+void WebContentsImpl::CreateAudioPowerSaveBlocker() {
+ // ChromeOS has its own way of handling power save blocks for media.
#if !defined(OS_CHROMEOS)
- scoped_ptr<PowerSaveBlocker> blocker;
- if (has_video) {
- blocker = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing video");
+ DCHECK(!audio_power_save_blocker_);
+ audio_power_save_blocker_ = PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing Audio");
+#endif
+}
+
+void WebContentsImpl::CreateVideoPowerSaveBlocker() {
+ // ChromeOS has its own way of handling power save blocks for media.
+#if !defined(OS_CHROMEOS)
+ DCHECK(!video_power_save_blocker_);
+ DCHECK(!active_video_players_.empty());
+ video_power_save_blocker_ = PowerSaveBlocker::Create(
+ PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, "Playing Video");
#if defined(OS_ANDROID)
- static_cast<PowerSaveBlockerImpl*>(blocker.get())
- ->InitDisplaySleepBlocker(GetView()->GetNativeView());
+ static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
+ ->InitDisplaySleepBlocker(GetView()->GetNativeView());
+#endif
#endif
- } else if (has_audio) {
- blocker = PowerSaveBlocker::Create(
- PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, "Playing audio");
+}
+
+void WebContentsImpl::MaybeReleasePowerSaveBlockers() {
+ // If there are no more audio players and we don't have audio stream
+ // monitoring, release the audio power save blocker here instead of during
+ // NotifyNavigationStateChanged().
+ if (active_audio_players_.empty() &&
+ !AudioStreamMonitor::monitoring_available()) {
+ audio_power_save_blocker_.reset();
+ }
+
+ // If there are no more video players, clear the video power save blocker.
+ if (active_video_players_.empty())
+ video_power_save_blocker_.reset();
+}
+
+void WebContentsImpl::OnMediaPlayingNotification(int64 player_cookie,
+ bool has_video,
+ bool has_audio,
+ bool is_remote) {
+ // Ignore the videos playing remotely and don't hold the wake lock for the
+ // screen.
+ if (is_remote) return;
+
+ if (has_audio) {
+ AddMediaPlayerEntry(player_cookie, &active_audio_players_);
+
+ // If we don't have audio stream monitoring, allocate the audio power save
+ // blocker here instead of during NotifyNavigationStateChanged().
+ if (!audio_power_save_blocker_ &&
+ !AudioStreamMonitor::monitoring_available()) {
+ CreateAudioPowerSaveBlocker();
+ }
}
- if (blocker) {
- power_save_blockers_[render_frame_message_source_][player_cookie] =
- blocker.release();
+ if (has_video) {
+ AddMediaPlayerEntry(player_cookie, &active_video_players_);
+
+ // If we're not hidden and have just created a player, create a blocker.
+ if (!video_power_save_blocker_ && !IsHidden())
+ CreateVideoPowerSaveBlocker();
}
-#endif // !defined(OS_CHROMEOS)
}
void WebContentsImpl::OnMediaPausedNotification(int64 player_cookie) {
- // Chrome OS does its own detection of audio and video.
-#if !defined(OS_CHROMEOS)
- delete power_save_blockers_[render_frame_message_source_][player_cookie];
- power_save_blockers_[render_frame_message_source_].erase(player_cookie);
-#endif // !defined(OS_CHROMEOS)
+ RemoveMediaPlayerEntry(player_cookie, &active_audio_players_);
+ RemoveMediaPlayerEntry(player_cookie, &active_video_players_);
+ MaybeReleasePowerSaveBlockers();
}
void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
@@ -2955,7 +3115,6 @@ void WebContentsImpl::NotifyBeforeFormRepostWarningShow() {
BeforeFormRepostWarningShow());
}
-
void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() {
Activate();
if (delegate_)
@@ -2995,13 +3154,13 @@ void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
if (is_loading) {
- TRACE_EVENT_ASYNC_BEGIN1("browser", "WebContentsImpl Loading", this,
- "URL", url);
+ TRACE_EVENT_ASYNC_BEGIN1("browser,navigation", "WebContentsImpl Loading",
+ this, "URL", url);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidStartLoading(render_view_host));
} else {
- TRACE_EVENT_ASYNC_END1("browser", "WebContentsImpl Loading", this,
- "URL", url);
+ TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
+ this, "URL", url);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidStopLoading(render_view_host));
}
@@ -3015,14 +3174,23 @@ void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
type, Source<NavigationController>(&controller_), det);
}
-void WebContentsImpl::SelectRange(const gfx::Point& start,
- const gfx::Point& end) {
+void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
+ RenderFrameHost* focused_frame = GetFocusedFrame();
+ if (!focused_frame)
+ return;
+
+ focused_frame->Send(new InputMsg_MoveRangeSelectionExtent(
+ focused_frame->GetRoutingID(), extent));
+}
+
+void WebContentsImpl::SelectRange(const gfx::Point& base,
+ const gfx::Point& extent) {
RenderFrameHost* focused_frame = GetFocusedFrame();
if (!focused_frame)
return;
focused_frame->Send(
- new InputMsg_SelectRange(focused_frame->GetRoutingID(), start, end));
+ new InputMsg_SelectRange(focused_frame->GetRoutingID(), base, extent));
}
void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
@@ -3117,8 +3285,8 @@ void WebContentsImpl::ResetLoadProgressState() {
loading_last_progress_update_ = base::TimeTicks();
}
-void WebContentsImpl::NotifySwapped(RenderViewHost* old_host,
- RenderViewHost* new_host) {
+void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
+ RenderViewHost* new_host) {
// After sending out a swap notification, we need to send a disconnect
// notification so that clients that pick up a pointer to |this| can NULL the
// pointer. See Bug 1230284.
@@ -3140,6 +3308,13 @@ void WebContentsImpl::NotifySwapped(RenderViewHost* old_host,
RemoveBrowserPluginEmbedder();
}
+void WebContentsImpl::NotifyFrameSwapped(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) {
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ RenderFrameHostChanged(old_host, new_host));
+}
+
// TODO(avi): Remove this entire function because this notification is already
// covered by two observer functions. http://crbug.com/170921
void WebContentsImpl::NotifyDisconnected() {
@@ -3174,6 +3349,7 @@ void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
RenderFrameCreated(render_frame_host));
+ SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host);
}
void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
@@ -3215,8 +3391,7 @@ void WebContentsImpl::RunJavaScriptMessage(
// showing an interstitial as it's shown over the previous page and we don't
// want the hidden page's dialogs to interfere with the interstitial.
bool suppress_this_message =
- static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost())->
- IsSwappedOut() ||
+ static_cast<RenderFrameHostImpl*>(render_frame_host)->is_swapped_out() ||
ShowingInterstitialPage() ||
!delegate_ ||
delegate_->ShouldSuppressDialogs() ||
@@ -3261,13 +3436,11 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
IPC::Message* reply_msg) {
RenderFrameHostImpl* rfhi =
static_cast<RenderFrameHostImpl*>(render_frame_host);
- RenderViewHostImpl* rvhi =
- static_cast<RenderViewHostImpl*>(render_frame_host->GetRenderViewHost());
if (delegate_)
delegate_->WillRunBeforeUnloadConfirm();
bool suppress_this_message =
- rvhi->rvh_state() != RenderViewHostImpl::STATE_DEFAULT ||
+ rfhi->rfh_state() != RenderFrameHostImpl::STATE_DEFAULT ||
!delegate_ ||
delegate_->ShouldSuppressDialogs() ||
!delegate_->GetJavaScriptDialogManager();
@@ -3296,6 +3469,12 @@ bool WebContentsImpl::IsNeverVisible() {
return delegate_->IsNeverVisible(this);
}
+#if defined(OS_WIN)
+gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
+ return accessible_parent_;
+}
+#endif
+
RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
return render_view_host_delegate_view_;
}
@@ -3320,7 +3499,7 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
// Don't send notifications if we are just creating a swapped-out RVH for
// the opener chain. These won't be used for view-source or WebUI, so it's
// ok to return early.
- if (static_cast<RenderViewHostImpl*>(render_view_host)->IsSwappedOut())
+ if (!static_cast<RenderViewHostImpl*>(render_view_host)->is_active())
return;
if (delegate_)
@@ -3354,6 +3533,9 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
RenderFrameHost* main_frame = render_view_host->GetMainFrame();
FOR_EACH_OBSERVER(
WebContentsObserver, observers_, RenderFrameCreated(main_frame));
+ SetAccessibilityModeOnFrame(accessibility_mode_, main_frame);
+
+ DevToolsManager::GetInstance()->RenderViewCreated(this, render_view_host);
}
void WebContentsImpl::RenderViewReady(RenderViewHost* rvh) {
@@ -3454,9 +3636,9 @@ void WebContentsImpl::UpdateState(RenderViewHost* rvh,
controller_.NotifyEntryChanged(entry, entry_index);
}
-void WebContentsImpl::UpdateTargetURL(int32 page_id, const GURL& url) {
+void WebContentsImpl::UpdateTargetURL(const GURL& url) {
if (delegate_)
- delegate_->UpdateTargetURL(this, page_id, url);
+ delegate_->UpdateTargetURL(this, url);
}
void WebContentsImpl::Close(RenderViewHost* rvh) {
@@ -3484,6 +3666,21 @@ void WebContentsImpl::SwappedOut(RenderFrameHost* rfh) {
delegate_->SwappedOut(this);
}
+void WebContentsImpl::DidDeferAfterResponseStarted(
+ const TransitionLayerData& transition_data) {
+#if defined(OS_ANDROID)
+ GetWebContentsAndroid()->DidDeferAfterResponseStarted(transition_data);
+#endif
+}
+
+bool WebContentsImpl::WillHandleDeferAfterResponseStarted() {
+#if defined(OS_ANDROID)
+ return GetWebContentsAndroid()->WillHandleDeferAfterResponseStarted();
+#else
+ return false;
+#endif
+}
+
void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
if (delegate_ && delegate_->IsPopupOrPanel(this))
delegate_->MoveContents(this, new_bounds);
@@ -3538,21 +3735,23 @@ void WebContentsImpl::DidAccessInitialDocument() {
controller_.DiscardPendingEntry();
// Update the URL display.
- NotifyNavigationStateChanged(content::INVALIDATE_TYPE_URL);
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
}
void WebContentsImpl::DidDisownOpener(RenderFrameHost* render_frame_host) {
- if (opener_) {
- // Clear our opener so that future cross-process navigations don't have an
- // opener assigned.
- RemoveDestructionObserver(opener_);
- opener_ = NULL;
- }
+ // No action is necessary if the opener has already been cleared.
+ if (!opener_)
+ return;
+
+ // Clear our opener so that future cross-process navigations don't have an
+ // opener assigned.
+ RemoveDestructionObserver(opener_);
+ opener_ = NULL;
// Notify all swapped out RenderViewHosts for this tab. This is important
// in case we go back to them, or if another window in those processes tries
// to access window.opener.
- GetRenderManager()->DidDisownOpener(render_frame_host->GetRenderViewHost());
+ GetRenderManager()->DidDisownOpener(render_frame_host);
}
void WebContentsImpl::DocumentOnLoadCompleted(
@@ -3690,7 +3889,7 @@ bool WebContentsImpl::AddMessageToConsole(int32 level,
source_id);
}
-WebPreferences WebContentsImpl::GetWebkitPrefs() {
+WebPreferences WebContentsImpl::ComputeWebkitPrefs() {
// We want to base the page config off of the actual URL, rather than the
// virtual URL.
// TODO(nasko): Investigate how to remove the GetActiveEntry usage here,
@@ -3698,13 +3897,13 @@ WebPreferences WebContentsImpl::GetWebkitPrefs() {
GURL url = controller_.GetActiveEntry()
? controller_.GetActiveEntry()->GetURL() : GURL::EmptyGURL();
- return GetRenderManager()->current_host()->GetWebkitPrefs(url);
+ return GetRenderManager()->current_host()->ComputeWebkitPrefs(url);
}
int WebContentsImpl::CreateSwappedOutRenderView(
SiteInstance* instance) {
- return GetRenderManager()->CreateRenderFrame(instance, MSG_ROUTING_NONE,
- true, true);
+ return GetRenderManager()->CreateRenderFrame(
+ instance, MSG_ROUTING_NONE, true, true, true);
}
void WebContentsImpl::OnUserGesture() {
@@ -3721,14 +3920,14 @@ void WebContentsImpl::OnIgnoredUIEvent() {
FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
}
-void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
- bool is_during_beforeunload,
- bool is_during_unload) {
+void WebContentsImpl::RendererUnresponsive(RenderViewHost* render_view_host) {
// Don't show hung renderer dialog for a swapped out RVH.
- if (rvh != GetRenderViewHost())
+ if (render_view_host != GetRenderViewHost())
return;
- RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(rvh);
+ RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(render_view_host);
+ RenderFrameHostImpl* rfhi =
+ static_cast<RenderFrameHostImpl*>(rvhi->GetMainFrame());
// Ignore renderer unresponsive event if debugger is attached to the tab
// since the event may be a result of the renderer sitting on a breakpoint.
@@ -3736,7 +3935,8 @@ void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
if (DevToolsAgentHost::IsDebuggerAttached(this))
return;
- if (is_during_beforeunload || is_during_unload) {
+ if (rfhi->is_waiting_for_beforeunload_ack() ||
+ rfhi->IsWaitingForUnloadACK()) {
// Hang occurred while firing the beforeunload/unload handler.
// Pretend the handler fired so tab closing continues as if it had.
rvhi->set_sudden_termination_allowed(true);
@@ -3751,11 +3951,11 @@ void WebContentsImpl::RendererUnresponsive(RenderViewHost* rvh,
// close. Otherwise, pretend the unload listeners have all fired and close
// the tab.
bool close = true;
- if (is_during_beforeunload && delegate_) {
+ if (rfhi->is_waiting_for_beforeunload_ack() && delegate_) {
delegate_->BeforeUnloadFired(this, true, &close);
}
if (close)
- Close(rvh);
+ Close(rvhi);
return;
}
@@ -3785,7 +3985,8 @@ void WebContentsImpl::LoadStateChanged(
if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
SetNotWaitingForResponse();
if (IsLoading()) {
- NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB);
+ NotifyNavigationStateChanged(static_cast<InvalidateTypes>(
+ INVALIDATE_TYPE_LOAD | INVALIDATE_TYPE_TAB));
}
}
@@ -3823,15 +4024,21 @@ void WebContentsImpl::CancelModalDialogsForRenderManager() {
dialog_manager_->CancelActiveAndPendingDialogs(this);
}
-void WebContentsImpl::NotifySwappedFromRenderManager(RenderViewHost* old_host,
- RenderViewHost* new_host) {
- NotifySwapped(old_host, new_host);
+void WebContentsImpl::NotifySwappedFromRenderManager(RenderFrameHost* old_host,
+ RenderFrameHost* new_host,
+ bool is_main_frame) {
+ if (is_main_frame) {
+ NotifyViewSwapped(old_host ? old_host->GetRenderViewHost() : NULL,
+ new_host->GetRenderViewHost());
- // Make sure the visible RVH reflects the new delegate's preferences.
- if (delegate_)
- view_->SetOverscrollControllerEnabled(CanOverscrollContent());
+ // Make sure the visible RVH reflects the new delegate's preferences.
+ if (delegate_)
+ view_->SetOverscrollControllerEnabled(CanOverscrollContent());
- view_->RenderViewSwappedIn(new_host);
+ view_->RenderViewSwappedIn(new_host->GetRenderViewHost());
+ }
+
+ NotifyFrameSwapped(old_host, new_host);
}
int WebContentsImpl::CreateOpenerRenderViewsForRenderManager(
@@ -3868,8 +4075,8 @@ int WebContentsImpl::CreateOpenerRenderViews(SiteInstance* instance) {
// Create a swapped out RenderView in the given SiteInstance if none exists,
// setting its opener to the given route_id. Return the new view's route_id.
- return GetRenderManager()->CreateRenderFrame(instance, opener_route_id,
- true, true);
+ return GetRenderManager()->CreateRenderFrame(
+ instance, opener_route_id, true, true, true);
}
NavigationControllerImpl& WebContentsImpl::GetControllerForRenderManager() {
@@ -3889,20 +4096,21 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
RenderViewHost* render_view_host,
int opener_route_id,
int proxy_routing_id,
- bool for_main_frame) {
- TRACE_EVENT0("browser", "WebContentsImpl::CreateRenderViewForRenderManager");
+ bool for_main_frame_navigation) {
+ TRACE_EVENT0("browser,navigation",
+ "WebContentsImpl::CreateRenderViewForRenderManager");
// Can be NULL during tests.
RenderWidgetHostViewBase* rwh_view;
// TODO(kenrb): RenderWidgetHostViewChildFrame special casing is temporary
// until RenderWidgetHost is attached to RenderFrameHost. We need to special
// case this because RWH is still a base class of RenderViewHost, and child
// frame RWHVs are unique in that they do not have their own WebContents.
- if (!for_main_frame) {
+ if (!for_main_frame_navigation) {
RenderWidgetHostViewChildFrame* rwh_view_child =
new RenderWidgetHostViewChildFrame(render_view_host);
rwh_view = rwh_view_child;
} else {
- rwh_view = view_->CreateViewForWidget(render_view_host);
+ rwh_view = view_->CreateViewForWidget(render_view_host, false);
}
// Now that the RenderView has been created, we need to tell it its size.
@@ -3935,19 +4143,41 @@ bool WebContentsImpl::CreateRenderViewForRenderManager(
return true;
}
+bool WebContentsImpl::CreateRenderFrameForRenderManager(
+ RenderFrameHost* render_frame_host,
+ int parent_routing_id,
+ int proxy_routing_id) {
+ TRACE_EVENT0("browser,navigation",
+ "WebContentsImpl::CreateRenderFrameForRenderManager");
+
+ RenderFrameHostImpl* rfh =
+ static_cast<RenderFrameHostImpl*>(render_frame_host);
+ if (!rfh->CreateRenderFrame(parent_routing_id, proxy_routing_id))
+ return false;
+
+ // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed
+ // RenderFrameHost will have to be associated with the appropriate
+ // RenderWidgetHostView or a new one should be created here.
+
+ return true;
+}
+
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject>
WebContentsImpl::GetJavaWebContents() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return GetWebContentsAndroid()->GetJavaObject();
+}
+WebContentsAndroid* WebContentsImpl::GetWebContentsAndroid() {
WebContentsAndroid* web_contents_android =
static_cast<WebContentsAndroid*>(GetUserData(kWebContentsAndroidKey));
if (!web_contents_android) {
web_contents_android = new WebContentsAndroid(this);
SetUserData(kWebContentsAndroidKey, web_contents_android);
}
- return web_contents_android->GetJavaObject();
+ return web_contents_android;
}
bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
@@ -3959,22 +4189,12 @@ bool WebContentsImpl::CreateRenderViewForInitialEmptyDocument() {
#elif defined(OS_MACOSX)
-void WebContentsImpl::SetAllowOverlappingViews(bool overlapping) {
- view_->SetAllowOverlappingViews(overlapping);
+void WebContentsImpl::SetAllowOtherViews(bool allow) {
+ view_->SetAllowOtherViews(allow);
}
-bool WebContentsImpl::GetAllowOverlappingViews() {
- return view_->GetAllowOverlappingViews();
-}
-
-void WebContentsImpl::SetOverlayView(WebContents* overlay,
- const gfx::Point& offset) {
- view_->SetOverlayView(static_cast<WebContentsImpl*>(overlay)->GetView(),
- offset);
-}
-
-void WebContentsImpl::RemoveOverlayView() {
- view_->RemoveOverlayView();
+bool WebContentsImpl::GetAllowOtherViews() {
+ return view_->GetAllowOtherViews();
}
#endif
@@ -4019,13 +4239,6 @@ void WebContentsImpl::SetEncoding(const std::string& encoding) {
GetCanonicalEncodingNameByAliasName(encoding);
}
-void WebContentsImpl::CreateViewAndSetSizeForRVH(RenderViewHost* rvh) {
- RenderWidgetHostViewBase* rwh_view = view_->CreateViewForWidget(rvh);
- // Can be NULL during tests.
- if (rwh_view)
- rwh_view->SetSize(GetContainerBounds().size());
-}
-
bool WebContentsImpl::IsHidden() {
return capturer_count_ == 0 && !should_normally_be_visible_;
}
@@ -4053,15 +4266,16 @@ BrowserPluginEmbedder* WebContentsImpl::GetBrowserPluginEmbedder() const {
void WebContentsImpl::ClearPowerSaveBlockers(
RenderFrameHost* render_frame_host) {
- STLDeleteValues(&power_save_blockers_[render_frame_host]);
- power_save_blockers_.erase(render_frame_host);
+ RemoveAllMediaPlayerEntries(render_frame_host, &active_audio_players_);
+ RemoveAllMediaPlayerEntries(render_frame_host, &active_video_players_);
+ MaybeReleasePowerSaveBlockers();
}
void WebContentsImpl::ClearAllPowerSaveBlockers() {
- for (PowerSaveBlockerMap::iterator i(power_save_blockers_.begin());
- i != power_save_blockers_.end(); ++i)
- STLDeleteValues(&power_save_blockers_[i->first]);
- power_save_blockers_.clear();
+ active_audio_players_.clear();
+ active_video_players_.clear();
+ audio_power_save_blocker_.reset();
+ video_power_save_blocker_.reset();
}
gfx::Size WebContentsImpl::GetSizeForNewRenderView() {
@@ -4073,11 +4287,9 @@ gfx::Size WebContentsImpl::GetSizeForNewRenderView() {
return size;
}
-void WebContentsImpl::OnFrameRemoved(
- RenderViewHostImpl* render_view_host,
- int frame_routing_id) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- FrameDetached(render_view_host, frame_routing_id));
+void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) {
+ FOR_EACH_OBSERVER(
+ WebContentsObserver, observers_, FrameDetached(render_frame_host));
}
void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
@@ -4088,4 +4300,54 @@ void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) {
delegate_->UpdatePreferredSize(this, new_size);
}
+void WebContentsImpl::AddMediaPlayerEntry(int64 player_cookie,
+ ActiveMediaPlayerMap* player_map) {
+ const uintptr_t key =
+ reinterpret_cast<uintptr_t>(render_frame_message_source_);
+ DCHECK(std::find((*player_map)[key].begin(),
+ (*player_map)[key].end(),
+ player_cookie) == (*player_map)[key].end());
+ (*player_map)[key].push_back(player_cookie);
+}
+
+void WebContentsImpl::RemoveMediaPlayerEntry(int64 player_cookie,
+ ActiveMediaPlayerMap* player_map) {
+ const uintptr_t key =
+ reinterpret_cast<uintptr_t>(render_frame_message_source_);
+ ActiveMediaPlayerMap::iterator it = player_map->find(key);
+ if (it == player_map->end())
+ return;
+
+ // Remove the player.
+ PlayerList::iterator player_it =
+ std::find(it->second.begin(), it->second.end(), player_cookie);
+ if (player_it != it->second.end())
+ it->second.erase(player_it);
+
+ // If there are no players left, remove the map entry.
+ if (it->second.empty())
+ player_map->erase(it);
+}
+
+void WebContentsImpl::RemoveAllMediaPlayerEntries(
+ RenderFrameHost* render_frame_host,
+ ActiveMediaPlayerMap* player_map) {
+ ActiveMediaPlayerMap::iterator it =
+ player_map->find(reinterpret_cast<uintptr_t>(render_frame_host));
+ if (it == player_map->end())
+ return;
+ player_map->erase(it);
+}
+
+void WebContentsImpl::ResumeResponseDeferredAtStart() {
+ FrameTreeNode* node = frame_tree_.root();
+ node->render_manager()->ResumeResponseDeferredAtStart();
+}
+
+void WebContentsImpl::SetForceDisableOverscrollContent(bool force_disable) {
+ force_disable_overscroll_content_ = force_disable;
+ if (view_)
+ view_->SetOverscrollControllerEnabled(CanOverscrollContent());
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index ba10e415d14..7869292bdb0 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -10,6 +10,7 @@
#include <string>
#include "base/compiler_specific.h"
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
@@ -21,21 +22,24 @@
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_manager.h"
+#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/common/accessibility_mode_enums.h"
#include "content/common/content_export.h"
#include "content/public/browser/color_chooser.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/renderer_preferences.h"
+#include "content/public/common/resource_type.h"
#include "content/public/common/three_d_api_types.h"
#include "net/base/load_states.h"
+#include "net/http/http_response_headers.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
+#include "ui/base/page_transition_types.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/size.h"
-#include "webkit/common/resource_type.h"
struct BrowserPluginHostMsg_ResizeGuest_Params;
struct ViewHostMsg_DateTimeDialogValue_Params;
@@ -48,9 +52,12 @@ class BrowserPluginGuestManager;
class DateTimeChooserAndroid;
class DownloadItem;
class GeolocationDispatcherHost;
+class GeolocationServiceContext;
class InterstitialPageImpl;
class JavaScriptDialogManager;
+class ManifestManagerHost;
class MidiDispatcherHost;
+class PluginContentOriginWhitelist;
class PowerSaveBlocker;
class RenderViewHost;
class RenderViewHostDelegateView;
@@ -60,6 +67,7 @@ class SavePackage;
class ScreenOrientationDispatcherHost;
class SiteInstance;
class TestWebContents;
+class WebContentsAudioMuter;
class WebContentsDelegate;
class WebContentsImpl;
class WebContentsObserver;
@@ -72,6 +80,10 @@ struct LoadNotificationDetails;
struct ResourceRedirectDetails;
struct ResourceRequestDetails;
+#if defined(OS_ANDROID)
+class WebContentsAndroid;
+#endif
+
// Factory function for the implementations that content knows about. Takes
// ownership of |delegate|.
WebContentsView* CreateWebContentsView(
@@ -89,12 +101,14 @@ class CONTENT_EXPORT WebContentsImpl
public NON_EXPORTED_BASE(NavigationControllerDelegate),
public NON_EXPORTED_BASE(NavigatorDelegate) {
public:
- virtual ~WebContentsImpl();
+ ~WebContentsImpl() override;
static WebContentsImpl* CreateWithOpener(
const WebContents::CreateParams& params,
WebContentsImpl* opener);
+ static std::vector<WebContentsImpl*> GetAllWebContents();
+
// Returns the opener WebContentsImpl, if any. This can be set to null if the
// opener is closed or the page clears its window.opener.
WebContentsImpl* opener() const { return opener_; }
@@ -161,422 +175,426 @@ class CONTENT_EXPORT WebContentsImpl
WebContentsView* GetView() const;
- GeolocationDispatcherHost* geolocation_dispatcher_host() {
- return geolocation_dispatcher_host_.get();
+ ScreenOrientationDispatcherHost* screen_orientation_dispatcher_host() {
+ return screen_orientation_dispatcher_host_.get();
}
bool should_normally_be_visible() { return should_normally_be_visible_; }
+ // Broadcasts the mode change to all frames.
+ void SetAccessibilityMode(AccessibilityMode mode);
+
+ // Adds the given accessibility mode to the current accessibility mode
+ // bitmap.
+ void AddAccessibilityMode(AccessibilityMode mode);
+
+ // Removes the given accessibility mode from the current accessibility
+ // mode bitmap, managing the bits that are shared with other modes such
+ // that a bit will only be turned off when all modes that depend on it
+ // have been removed.
+ void RemoveAccessibilityMode(AccessibilityMode mode);
+
+ // Clear the navigation transition data when the user navigates back to Chrome
+ // from a native app.
+ void ClearNavigationTransitionData();
+
// WebContents ------------------------------------------------------
- virtual WebContentsDelegate* GetDelegate() OVERRIDE;
- virtual void SetDelegate(WebContentsDelegate* delegate) OVERRIDE;
- virtual NavigationControllerImpl& GetController() OVERRIDE;
- virtual const NavigationControllerImpl& GetController() const OVERRIDE;
- virtual BrowserContext* GetBrowserContext() const OVERRIDE;
- virtual const GURL& GetURL() const OVERRIDE;
- virtual const GURL& GetVisibleURL() const OVERRIDE;
- virtual const GURL& GetLastCommittedURL() const OVERRIDE;
- virtual RenderProcessHost* GetRenderProcessHost() const OVERRIDE;
- virtual RenderFrameHost* GetMainFrame() OVERRIDE;
- virtual RenderFrameHost* GetFocusedFrame() OVERRIDE;
- virtual void ForEachFrame(
- const base::Callback<void(RenderFrameHost*)>& on_frame) OVERRIDE;
- virtual void SendToAllFrames(IPC::Message* message) OVERRIDE;
- virtual RenderViewHost* GetRenderViewHost() const OVERRIDE;
- virtual int GetRoutingID() const OVERRIDE;
- virtual RenderWidgetHostView* GetRenderWidgetHostView() const OVERRIDE;
- virtual RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const
- OVERRIDE;
- virtual WebUI* CreateWebUI(const GURL& url) OVERRIDE;
- virtual WebUI* GetWebUI() const OVERRIDE;
- virtual WebUI* GetCommittedWebUI() const OVERRIDE;
- virtual void SetUserAgentOverride(const std::string& override) OVERRIDE;
- virtual const std::string& GetUserAgentOverride() const OVERRIDE;
+ WebContentsDelegate* GetDelegate() override;
+ void SetDelegate(WebContentsDelegate* delegate) override;
+ NavigationControllerImpl& GetController() override;
+ const NavigationControllerImpl& GetController() const override;
+ BrowserContext* GetBrowserContext() const override;
+ const GURL& GetURL() const override;
+ const GURL& GetVisibleURL() const override;
+ const GURL& GetLastCommittedURL() const override;
+ RenderProcessHost* GetRenderProcessHost() const override;
+ RenderFrameHost* GetMainFrame() override;
+ RenderFrameHost* GetFocusedFrame() override;
+ void ForEachFrame(
+ const base::Callback<void(RenderFrameHost*)>& on_frame) override;
+ void SendToAllFrames(IPC::Message* message) override;
+ RenderViewHost* GetRenderViewHost() const override;
+ int GetRoutingID() const override;
+ RenderWidgetHostView* GetRenderWidgetHostView() const override;
+ RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const override;
+ WebUI* CreateWebUI(const GURL& url) override;
+ WebUI* GetWebUI() const override;
+ WebUI* GetCommittedWebUI() const override;
+ void SetUserAgentOverride(const std::string& override) override;
+ const std::string& GetUserAgentOverride() const override;
+ void EnableTreeOnlyAccessibilityMode() override;
+ bool IsTreeOnlyAccessibilityModeForTesting() const override;
+ bool IsFullAccessibilityModeForTesting() const override;
#if defined(OS_WIN)
virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) OVERRIDE;
+ gfx::NativeViewAccessible accessible_parent) override;
#endif
- virtual const base::string16& GetTitle() const OVERRIDE;
- virtual int32 GetMaxPageID() OVERRIDE;
- virtual int32 GetMaxPageIDForSiteInstance(
- SiteInstance* site_instance) OVERRIDE;
- virtual SiteInstance* GetSiteInstance() const OVERRIDE;
- virtual SiteInstance* GetPendingSiteInstance() const OVERRIDE;
- virtual bool IsLoading() const OVERRIDE;
- virtual bool IsLoadingToDifferentDocument() const OVERRIDE;
- virtual bool IsWaitingForResponse() const OVERRIDE;
- virtual const net::LoadStateWithParam& GetLoadState() const OVERRIDE;
- virtual const base::string16& GetLoadStateHost() const OVERRIDE;
- virtual uint64 GetUploadSize() const OVERRIDE;
- virtual uint64 GetUploadPosition() const OVERRIDE;
- virtual std::set<GURL> GetSitesInTab() const OVERRIDE;
- virtual const std::string& GetEncoding() const OVERRIDE;
- virtual bool DisplayedInsecureContent() const OVERRIDE;
- virtual void IncrementCapturerCount(const gfx::Size& capture_size) OVERRIDE;
- virtual void DecrementCapturerCount() OVERRIDE;
- virtual int GetCapturerCount() const OVERRIDE;
- virtual bool IsCrashed() const OVERRIDE;
- virtual void SetIsCrashed(base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual base::TerminationStatus GetCrashedStatus() const OVERRIDE;
- virtual bool IsBeingDestroyed() const OVERRIDE;
- virtual void NotifyNavigationStateChanged(unsigned changed_flags) OVERRIDE;
- virtual base::TimeTicks GetLastActiveTime() const OVERRIDE;
- virtual void WasShown() OVERRIDE;
- virtual void WasHidden() OVERRIDE;
- virtual bool NeedToFireBeforeUnload() OVERRIDE;
- virtual void DispatchBeforeUnload(bool for_cross_site_transition) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual WebContents* Clone() OVERRIDE;
- virtual void ReloadFocusedFrame(bool ignore_cache) OVERRIDE;
- virtual void Undo() OVERRIDE;
- virtual void Redo() OVERRIDE;
- virtual void Cut() OVERRIDE;
- virtual void Copy() OVERRIDE;
- virtual void CopyToFindPboard() OVERRIDE;
- virtual void Paste() OVERRIDE;
- virtual void PasteAndMatchStyle() OVERRIDE;
- virtual void Delete() OVERRIDE;
- virtual void SelectAll() OVERRIDE;
- virtual void Unselect() OVERRIDE;
- virtual void Replace(const base::string16& word) OVERRIDE;
- virtual void ReplaceMisspelling(const base::string16& word) OVERRIDE;
- virtual void NotifyContextMenuClosed(
- const CustomContextMenuContext& context) OVERRIDE;
- virtual void ExecuteCustomContextMenuCommand(
- int action, const CustomContextMenuContext& context) OVERRIDE;
- virtual gfx::NativeView GetNativeView() OVERRIDE;
- virtual gfx::NativeView GetContentNativeView() OVERRIDE;
- virtual gfx::NativeWindow GetTopLevelNativeWindow() OVERRIDE;
- virtual gfx::Rect GetContainerBounds() OVERRIDE;
- virtual gfx::Rect GetViewBounds() OVERRIDE;
- virtual DropData* GetDropData() OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void SetInitialFocus() OVERRIDE;
- virtual void StoreFocus() OVERRIDE;
- virtual void RestoreFocus() OVERRIDE;
- virtual void FocusThroughTabTraversal(bool reverse) OVERRIDE;
- virtual bool ShowingInterstitialPage() const OVERRIDE;
- virtual InterstitialPage* GetInterstitialPage() const OVERRIDE;
- virtual bool IsSavable() OVERRIDE;
- virtual void OnSavePage() OVERRIDE;
- virtual bool SavePage(const base::FilePath& main_file,
- const base::FilePath& dir_path,
- SavePageType save_type) OVERRIDE;
- virtual void SaveFrame(const GURL& url,
- const Referrer& referrer) OVERRIDE;
- virtual void GenerateMHTML(
- const base::FilePath& file,
- const base::Callback<void(int64)>& callback)
- OVERRIDE;
- virtual const std::string& GetContentsMimeType() const OVERRIDE;
- virtual bool WillNotifyDisconnection() const OVERRIDE;
- virtual void SetOverrideEncoding(const std::string& encoding) OVERRIDE;
- virtual void ResetOverrideEncoding() OVERRIDE;
- virtual RendererPreferences* GetMutableRendererPrefs() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void SystemDragEnded() OVERRIDE;
- virtual void UserGestureDone() OVERRIDE;
- virtual void SetClosedByUserGesture(bool value) OVERRIDE;
- virtual bool GetClosedByUserGesture() const OVERRIDE;
- virtual int GetZoomPercent(bool* enable_increment,
- bool* enable_decrement) const OVERRIDE;
- virtual void ViewSource() OVERRIDE;
- virtual void ViewFrameSource(const GURL& url,
- const PageState& page_state) OVERRIDE;
- virtual int GetMinimumZoomPercent() const OVERRIDE;
- virtual int GetMaximumZoomPercent() const OVERRIDE;
- virtual gfx::Size GetPreferredSize() const OVERRIDE;
- virtual bool GotResponseToLockMouseRequest(bool allowed) OVERRIDE;
- virtual bool HasOpener() const OVERRIDE;
- virtual void DidChooseColorInColorChooser(SkColor color) OVERRIDE;
- virtual void DidEndColorChooser() OVERRIDE;
- virtual int DownloadImage(const GURL& url,
- bool is_favicon,
- uint32_t max_bitmap_size,
- const ImageDownloadCallback& callback) OVERRIDE;
- virtual bool IsSubframe() const OVERRIDE;
- virtual void Find(int request_id,
- const base::string16& search_text,
- const blink::WebFindOptions& options) OVERRIDE;
- virtual void StopFinding(StopFindAction action) OVERRIDE;
- virtual void InsertCSS(const std::string& css) OVERRIDE;
+ const base::string16& GetTitle() const override;
+ int32 GetMaxPageID() override;
+ int32 GetMaxPageIDForSiteInstance(SiteInstance* site_instance) override;
+ SiteInstanceImpl* GetSiteInstance() const override;
+ SiteInstanceImpl* GetPendingSiteInstance() const override;
+ bool IsLoading() const override;
+ bool IsLoadingToDifferentDocument() const override;
+ bool IsWaitingForResponse() const override;
+ const net::LoadStateWithParam& GetLoadState() const override;
+ const base::string16& GetLoadStateHost() const override;
+ uint64 GetUploadSize() const override;
+ uint64 GetUploadPosition() const override;
+ std::set<GURL> GetSitesInTab() const override;
+ const std::string& GetEncoding() const override;
+ bool DisplayedInsecureContent() const override;
+ void IncrementCapturerCount(const gfx::Size& capture_size) override;
+ void DecrementCapturerCount() override;
+ int GetCapturerCount() const override;
+ bool IsAudioMuted() const override;
+ void SetAudioMuted(bool mute) override;
+ bool IsCrashed() const override;
+ void SetIsCrashed(base::TerminationStatus status, int error_code) override;
+ base::TerminationStatus GetCrashedStatus() const override;
+ bool IsBeingDestroyed() const override;
+ void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override;
+ base::TimeTicks GetLastActiveTime() const override;
+ void WasShown() override;
+ void WasHidden() override;
+ bool NeedToFireBeforeUnload() override;
+ void DispatchBeforeUnload(bool for_cross_site_transition) override;
+ void Stop() override;
+ WebContents* Clone() override;
+ void ReloadFocusedFrame(bool ignore_cache) override;
+ void Undo() override;
+ void Redo() override;
+ void Cut() override;
+ void Copy() override;
+ void CopyToFindPboard() override;
+ void Paste() override;
+ void PasteAndMatchStyle() override;
+ void Delete() override;
+ void SelectAll() override;
+ void Unselect() override;
+ void Replace(const base::string16& word) override;
+ void ReplaceMisspelling(const base::string16& word) override;
+ void NotifyContextMenuClosed(
+ const CustomContextMenuContext& context) override;
+ void ExecuteCustomContextMenuCommand(
+ int action,
+ const CustomContextMenuContext& context) override;
+ gfx::NativeView GetNativeView() override;
+ gfx::NativeView GetContentNativeView() override;
+ gfx::NativeWindow GetTopLevelNativeWindow() override;
+ gfx::Rect GetContainerBounds() override;
+ gfx::Rect GetViewBounds() override;
+ DropData* GetDropData() override;
+ void Focus() override;
+ void SetInitialFocus() override;
+ void StoreFocus() override;
+ void RestoreFocus() override;
+ void FocusThroughTabTraversal(bool reverse) override;
+ bool ShowingInterstitialPage() const override;
+ InterstitialPage* GetInterstitialPage() const override;
+ bool IsSavable() override;
+ void OnSavePage() override;
+ bool SavePage(const base::FilePath& main_file,
+ const base::FilePath& dir_path,
+ SavePageType save_type) override;
+ void SaveFrame(const GURL& url, const Referrer& referrer) override;
+ void GenerateMHTML(const base::FilePath& file,
+ const base::Callback<void(int64)>& callback) override;
+ const std::string& GetContentsMimeType() const override;
+ bool WillNotifyDisconnection() const override;
+ void SetOverrideEncoding(const std::string& encoding) override;
+ void ResetOverrideEncoding() override;
+ RendererPreferences* GetMutableRendererPrefs() override;
+ void Close() override;
+ void SystemDragEnded() override;
+ void UserGestureDone() override;
+ void SetClosedByUserGesture(bool value) override;
+ bool GetClosedByUserGesture() const override;
+ void ViewSource() override;
+ void ViewFrameSource(const GURL& url, const PageState& page_state) override;
+ int GetMinimumZoomPercent() const override;
+ int GetMaximumZoomPercent() const override;
+ gfx::Size GetPreferredSize() const override;
+ bool GotResponseToLockMouseRequest(bool allowed) override;
+ bool HasOpener() const override;
+ void DidChooseColorInColorChooser(SkColor color) override;
+ void DidEndColorChooser() override;
+ int DownloadImage(const GURL& url,
+ bool is_favicon,
+ uint32_t max_bitmap_size,
+ const ImageDownloadCallback& callback) override;
+ bool IsSubframe() const override;
+ void Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options) override;
+ void StopFinding(StopFindAction action) override;
+ void InsertCSS(const std::string& css) override;
+ bool WasRecentlyAudible() override;
+ void GetManifest(const GetManifestCallback&) override;
#if defined(OS_ANDROID)
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents()
- OVERRIDE;
+ override;
+ virtual WebContentsAndroid* GetWebContentsAndroid();
#elif defined(OS_MACOSX)
- virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE;
- virtual bool GetAllowOverlappingViews() OVERRIDE;
- virtual void SetOverlayView(WebContents* overlay,
- const gfx::Point& offset) OVERRIDE;
- virtual void RemoveOverlayView() OVERRIDE;
+ void SetAllowOtherViews(bool allow) override;
+ bool GetAllowOtherViews() override;
#endif
// Implementation of PageNavigator.
- virtual WebContents* OpenURL(const OpenURLParams& params) OVERRIDE;
+ WebContents* OpenURL(const OpenURLParams& params) override;
// Implementation of IPC::Sender.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// RenderFrameHostDelegate ---------------------------------------------------
- virtual bool OnMessageReceived(RenderFrameHost* render_frame_host,
- const IPC::Message& message) OVERRIDE;
- virtual const GURL& GetMainFrameLastCommittedURL() const OVERRIDE;
- virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void DidStartLoading(RenderFrameHost* render_frame_host,
- bool to_different_document) OVERRIDE;
- virtual void SwappedOut(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void WorkerCrashed(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
- const ContextMenuParams& params) OVERRIDE;
- virtual void RunJavaScriptMessage(RenderFrameHost* render_frame_host,
- const base::string16& message,
- const base::string16& default_prompt,
- const GURL& frame_url,
- JavaScriptMessageType type,
- IPC::Message* reply_msg) OVERRIDE;
- virtual void RunBeforeUnloadConfirm(RenderFrameHost* render_frame_host,
- const base::string16& message,
- bool is_reload,
- IPC::Message* reply_msg) OVERRIDE;
- virtual void DidAccessInitialDocument() OVERRIDE;
- virtual void DidDisownOpener(RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void DocumentOnLoadCompleted(
- RenderFrameHost* render_frame_host) OVERRIDE;
- virtual void UpdateTitle(RenderFrameHost* render_frame_host,
- int32 page_id,
- const base::string16& title,
- base::i18n::TextDirection title_direction) OVERRIDE;
- virtual void UpdateEncoding(RenderFrameHost* render_frame_host,
- const std::string& encoding) OVERRIDE;
- virtual WebContents* GetAsWebContents() OVERRIDE;
- virtual bool IsNeverVisible() OVERRIDE;
+ bool OnMessageReceived(RenderFrameHost* render_frame_host,
+ const IPC::Message& message) override;
+ const GURL& GetMainFrameLastCommittedURL() const override;
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+ void DidStartLoading(RenderFrameHost* render_frame_host,
+ bool to_different_document) override;
+ void SwappedOut(RenderFrameHost* render_frame_host) override;
+ void DidDeferAfterResponseStarted(
+ const TransitionLayerData& transition_data) override;
+ bool WillHandleDeferAfterResponseStarted() override;
+ void WorkerCrashed(RenderFrameHost* render_frame_host) override;
+ void ShowContextMenu(RenderFrameHost* render_frame_host,
+ const ContextMenuParams& params) override;
+ void RunJavaScriptMessage(RenderFrameHost* render_frame_host,
+ const base::string16& message,
+ const base::string16& default_prompt,
+ const GURL& frame_url,
+ JavaScriptMessageType type,
+ IPC::Message* reply_msg) override;
+ void RunBeforeUnloadConfirm(RenderFrameHost* render_frame_host,
+ const base::string16& message,
+ bool is_reload,
+ IPC::Message* reply_msg) override;
+ void DidAccessInitialDocument() override;
+ void DidDisownOpener(RenderFrameHost* render_frame_host) override;
+ void DocumentOnLoadCompleted(RenderFrameHost* render_frame_host) override;
+ void UpdateTitle(RenderFrameHost* render_frame_host,
+ int32 page_id,
+ const base::string16& title,
+ base::i18n::TextDirection title_direction) override;
+ void UpdateEncoding(RenderFrameHost* render_frame_host,
+ const std::string& encoding) override;
+ WebContents* GetAsWebContents() override;
+ bool IsNeverVisible() override;
+ AccessibilityMode GetAccessibilityMode() const override;
+ void AccessibilityEventReceived(
+ const std::vector<AXEventNotificationDetails>& details) override;
+ RenderFrameHost* GetGuestByInstanceID(
+ int browser_plugin_instance_id) override;
+ GeolocationServiceContext* GetGeolocationServiceContext() override;
+#if defined(OS_WIN)
+ gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
+#endif
// RenderViewHostDelegate ----------------------------------------------------
- virtual RenderViewHostDelegateView* GetDelegateView() OVERRIDE;
- virtual bool OnMessageReceived(RenderViewHost* render_view_host,
- const IPC::Message& message) OVERRIDE;
+ RenderViewHostDelegateView* GetDelegateView() override;
+ bool OnMessageReceived(RenderViewHost* render_view_host,
+ const IPC::Message& message) override;
// RenderFrameHostDelegate has the same method, so list it there because this
// interface is going away.
- // virtual WebContents* GetAsWebContents() OVERRIDE;
- virtual gfx::Rect GetRootWindowResizerRect() const OVERRIDE;
- virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE;
- virtual void RenderViewReady(RenderViewHost* render_view_host) OVERRIDE;
- virtual void RenderViewTerminated(RenderViewHost* render_view_host,
- base::TerminationStatus status,
- int error_code) OVERRIDE;
- virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE;
- virtual void UpdateState(RenderViewHost* render_view_host,
- int32 page_id,
- const PageState& page_state) OVERRIDE;
- virtual void UpdateTargetURL(int32 page_id, const GURL& url) OVERRIDE;
- virtual void Close(RenderViewHost* render_view_host) OVERRIDE;
- virtual void RequestMove(const gfx::Rect& new_bounds) OVERRIDE;
- virtual void DidCancelLoading() OVERRIDE;
- virtual void DocumentAvailableInMainFrame(
- RenderViewHost* render_view_host) OVERRIDE;
- virtual void RouteCloseEvent(RenderViewHost* rvh) OVERRIDE;
- virtual void RouteMessageEvent(
- RenderViewHost* rvh,
- const ViewMsg_PostMessage_Params& params) OVERRIDE;
- virtual bool AddMessageToConsole(int32 level,
- const base::string16& message,
- int32 line_no,
- const base::string16& source_id) OVERRIDE;
- virtual RendererPreferences GetRendererPrefs(
- BrowserContext* browser_context) const OVERRIDE;
- virtual WebPreferences GetWebkitPrefs() OVERRIDE;
- virtual void OnUserGesture() OVERRIDE;
- virtual void OnIgnoredUIEvent() OVERRIDE;
- virtual void RendererUnresponsive(RenderViewHost* render_view_host,
- bool is_during_beforeunload,
- bool is_during_unload) OVERRIDE;
- virtual void RendererResponsive(RenderViewHost* render_view_host) OVERRIDE;
- virtual void LoadStateChanged(const GURL& url,
- const net::LoadStateWithParam& load_state,
- uint64 upload_position,
- uint64 upload_size) OVERRIDE;
- virtual void Activate() OVERRIDE;
- virtual void Deactivate() OVERRIDE;
- virtual void LostCapture() OVERRIDE;
- virtual void HandleMouseDown() OVERRIDE;
- virtual void HandleMouseUp() OVERRIDE;
- virtual void HandlePointerActivate() OVERRIDE;
- virtual void HandleGestureBegin() OVERRIDE;
- virtual void HandleGestureEnd() OVERRIDE;
- virtual void RunFileChooser(
- RenderViewHost* render_view_host,
- const FileChooserParams& params) OVERRIDE;
- virtual void ToggleFullscreenMode(bool enter_fullscreen) OVERRIDE;
- virtual bool IsFullscreenForCurrentTab() const OVERRIDE;
- virtual void UpdatePreferredSize(const gfx::Size& pref_size) OVERRIDE;
- virtual void ResizeDueToAutoResize(const gfx::Size& new_size) OVERRIDE;
- virtual void RequestToLockMouse(bool user_gesture,
- bool last_unlocked_by_target) OVERRIDE;
- virtual void LostMouseLock() OVERRIDE;
- virtual void CreateNewWindow(
+ // virtual WebContents* GetAsWebContents() override;
+ gfx::Rect GetRootWindowResizerRect() const override;
+ void RenderViewCreated(RenderViewHost* render_view_host) override;
+ void RenderViewReady(RenderViewHost* render_view_host) override;
+ void RenderViewTerminated(RenderViewHost* render_view_host,
+ base::TerminationStatus status,
+ int error_code) override;
+ void RenderViewDeleted(RenderViewHost* render_view_host) override;
+ void UpdateState(RenderViewHost* render_view_host,
+ int32 page_id,
+ const PageState& page_state) override;
+ void UpdateTargetURL(const GURL& url) override;
+ void Close(RenderViewHost* render_view_host) override;
+ void RequestMove(const gfx::Rect& new_bounds) override;
+ void DidCancelLoading() override;
+ void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) override;
+ void RouteCloseEvent(RenderViewHost* rvh) override;
+ void RouteMessageEvent(RenderViewHost* rvh,
+ const ViewMsg_PostMessage_Params& params) override;
+ bool AddMessageToConsole(int32 level,
+ const base::string16& message,
+ int32 line_no,
+ const base::string16& source_id) override;
+ RendererPreferences GetRendererPrefs(
+ BrowserContext* browser_context) const override;
+ WebPreferences ComputeWebkitPrefs() override;
+ void OnUserGesture() override;
+ void OnIgnoredUIEvent() override;
+ void RendererUnresponsive(RenderViewHost* render_view_host) override;
+ void RendererResponsive(RenderViewHost* render_view_host) override;
+ void LoadStateChanged(const GURL& url,
+ const net::LoadStateWithParam& load_state,
+ uint64 upload_position,
+ uint64 upload_size) override;
+ void Activate() override;
+ void Deactivate() override;
+ void LostCapture() override;
+ void HandleMouseDown() override;
+ void HandleMouseUp() override;
+ void HandlePointerActivate() override;
+ void HandleGestureBegin() override;
+ void HandleGestureEnd() override;
+ void RunFileChooser(RenderViewHost* render_view_host,
+ const FileChooserParams& params) override;
+ void ToggleFullscreenMode(bool enter_fullscreen) override;
+ bool IsFullscreenForCurrentTab() const override;
+ void UpdatePreferredSize(const gfx::Size& pref_size) override;
+ void ResizeDueToAutoResize(const gfx::Size& new_size) override;
+ void RequestToLockMouse(bool user_gesture,
+ bool last_unlocked_by_target) override;
+ void LostMouseLock() override;
+ void CreateNewWindow(
int render_process_id,
int route_id,
int main_frame_route_id,
const ViewHostMsg_CreateWindow_Params& params,
- SessionStorageNamespace* session_storage_namespace) OVERRIDE;
- virtual void CreateNewWidget(int render_process_id,
- int route_id,
- blink::WebPopupType popup_type) OVERRIDE;
- virtual void CreateNewFullscreenWidget(int render_process_id,
- int route_id) OVERRIDE;
- virtual void ShowCreatedWindow(int route_id,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_pos,
- bool user_gesture) OVERRIDE;
- virtual void ShowCreatedWidget(int route_id,
- const gfx::Rect& initial_pos) OVERRIDE;
- virtual void ShowCreatedFullscreenWidget(int route_id) OVERRIDE;
- virtual void RequestMediaAccessPermission(
+ SessionStorageNamespace* session_storage_namespace) override;
+ void CreateNewWidget(int render_process_id,
+ int route_id,
+ blink::WebPopupType popup_type) override;
+ void CreateNewFullscreenWidget(int render_process_id, int route_id) override;
+ void ShowCreatedWindow(int route_id,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) override;
+ void ShowCreatedWidget(int route_id, const gfx::Rect& initial_pos) override;
+ void ShowCreatedFullscreenWidget(int route_id) override;
+ void RequestMediaAccessPermission(
const MediaStreamRequest& request,
- const MediaResponseCallback& callback) OVERRIDE;
- virtual SessionStorageNamespace* GetSessionStorageNamespace(
- SiteInstance* instance) OVERRIDE;
- virtual SessionStorageNamespaceMap GetSessionStorageNamespaceMap() OVERRIDE;
- virtual FrameTree* GetFrameTree() OVERRIDE;
- virtual void AccessibilityEventReceived(
- const std::vector<AXEventNotificationDetails>& details) OVERRIDE;
+ const MediaResponseCallback& callback) override;
+ bool CheckMediaAccessPermission(const GURL& security_origin,
+ MediaStreamType type) override;
+ SessionStorageNamespace* GetSessionStorageNamespace(
+ SiteInstance* instance) override;
+ SessionStorageNamespaceMap GetSessionStorageNamespaceMap() override;
+ FrameTree* GetFrameTree() override;
// NavigatorDelegate ---------------------------------------------------------
- virtual void DidStartProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- int parent_routing_id,
- const GURL& validated_url,
- bool is_error_page,
- bool is_iframe_srcdoc) OVERRIDE;
- virtual void DidFailProvisionalLoadWithError(
+ void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
+ const GURL& validated_url,
+ bool is_error_page,
+ bool is_iframe_srcdoc) override;
+ void DidStartNavigationTransition(
+ RenderFrameHostImpl* render_frame_host) override;
+ void DidFailProvisionalLoadWithError(
RenderFrameHostImpl* render_frame_host,
const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params)
- OVERRIDE;
- virtual void DidFailLoadWithError(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url,
- int error_code,
- const base::string16& error_description) OVERRIDE;
- virtual void DidRedirectProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const GURL& validated_target_url) OVERRIDE;
- virtual void DidCommitProvisionalLoad(
- RenderFrameHostImpl* render_frame_host,
- const base::string16& frame_unique_name,
- bool is_main_frame,
- const GURL& url,
- PageTransition transition_type) OVERRIDE;
- virtual void DidNavigateMainFramePreCommit(
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) OVERRIDE;
- virtual void DidNavigateMainFramePostCommit(
+ override;
+ void DidFailLoadWithError(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ int error_code,
+ const base::string16& error_description) override;
+ void DidCommitProvisionalLoad(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ ui::PageTransition transition_type) override;
+ void DidNavigateMainFramePreCommit(bool navigation_is_within_page) override;
+ void DidNavigateMainFramePostCommit(
const LoadCommittedDetails& details,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) OVERRIDE;
- virtual void DidNavigateAnyFramePostCommit(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params) override;
+ void DidNavigateAnyFramePostCommit(
RenderFrameHostImpl* render_frame_host,
const LoadCommittedDetails& details,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) OVERRIDE;
- virtual void SetMainFrameMimeType(const std::string& mime_type) OVERRIDE;
- virtual bool CanOverscrollContent() const OVERRIDE;
- virtual void NotifyChangedNavigationState(
- InvalidateTypes changed_flags) OVERRIDE;
- virtual void AboutToNavigateRenderFrame(
- RenderFrameHostImpl* render_frame_host) OVERRIDE;
- virtual void DidStartNavigationToPendingEntry(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params) override;
+ void SetMainFrameMimeType(const std::string& mime_type) override;
+ bool CanOverscrollContent() const override;
+ void NotifyChangedNavigationState(InvalidateTypes changed_flags) override;
+ void AboutToNavigateRenderFrame(
+ RenderFrameHostImpl* render_frame_host) override;
+ void DidStartNavigationToPendingEntry(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
- NavigationController::ReloadType reload_type) OVERRIDE;
- virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
- const OpenURLParams& params) OVERRIDE;
- virtual bool ShouldPreserveAbortedURLs() OVERRIDE;
+ NavigationController::ReloadType reload_type) override;
+ void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
+ const OpenURLParams& params) override;
+ bool ShouldPreserveAbortedURLs() override;
// RenderWidgetHostDelegate --------------------------------------------------
- virtual void RenderWidgetDeleted(
- RenderWidgetHostImpl* render_widget_host) OVERRIDE;
- virtual bool PreHandleKeyboardEvent(
- const NativeWebKeyboardEvent& event,
- bool* is_keyboard_shortcut) OVERRIDE;
- virtual void HandleKeyboardEvent(
- const NativeWebKeyboardEvent& event) OVERRIDE;
- virtual bool HandleWheelEvent(
- const blink::WebMouseWheelEvent& event) OVERRIDE;
- virtual bool PreHandleGestureEvent(
- const blink::WebGestureEvent& event) OVERRIDE;
- virtual bool HandleGestureEvent(
- const blink::WebGestureEvent& event) OVERRIDE;
- virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) OVERRIDE;
- virtual void OnTouchEmulationEnabled(bool enabled) OVERRIDE;
-#if defined(OS_WIN)
- virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
-#endif
+ void RenderWidgetDeleted(RenderWidgetHostImpl* render_widget_host) override;
+ void RenderWidgetGotFocus(RenderWidgetHostImpl* render_widget_host) override;
+ bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
+ bool* is_keyboard_shortcut) override;
+ void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
+ bool HandleWheelEvent(const blink::WebMouseWheelEvent& event) override;
+ bool PreHandleGestureEvent(const blink::WebGestureEvent& event) override;
+ bool HandleGestureEvent(const blink::WebGestureEvent& event) override;
+ void DidSendScreenRects(RenderWidgetHostImpl* rwh) override;
+ BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override;
+ BrowserAccessibilityManager* GetOrCreateRootBrowserAccessibilityManager()
+ override;
// RenderFrameHostManager::Delegate ------------------------------------------
- virtual bool CreateRenderViewForRenderManager(
+ bool CreateRenderViewForRenderManager(
RenderViewHost* render_view_host,
int opener_route_id,
int proxy_routing_id,
- bool for_main_frame) OVERRIDE;
- virtual void BeforeUnloadFiredFromRenderManager(
- bool proceed, const base::TimeTicks& proceed_time,
- bool* proceed_to_fire_unload) OVERRIDE;
- virtual void RenderProcessGoneFromRenderManager(
- RenderViewHost* render_view_host) OVERRIDE;
- virtual void UpdateRenderViewSizeForRenderManager() OVERRIDE;
- virtual void CancelModalDialogsForRenderManager() OVERRIDE;
- virtual void NotifySwappedFromRenderManager(
- RenderViewHost* old_host, RenderViewHost* new_host) OVERRIDE;
- virtual int CreateOpenerRenderViewsForRenderManager(
- SiteInstance* instance) OVERRIDE;
- virtual NavigationControllerImpl&
- GetControllerForRenderManager() OVERRIDE;
- virtual WebUIImpl* CreateWebUIForRenderManager(const GURL& url) OVERRIDE;
- virtual NavigationEntry*
- GetLastCommittedNavigationEntryForRenderManager() OVERRIDE;
- virtual bool FocusLocationBarByDefault() OVERRIDE;
- virtual void SetFocusToLocationBar(bool select_all) OVERRIDE;
- virtual void CreateViewAndSetSizeForRVH(RenderViewHost* rvh) OVERRIDE;
- virtual bool IsHidden() OVERRIDE;
+ bool for_main_frame_navigation) override;
+ bool CreateRenderFrameForRenderManager(RenderFrameHost* render_frame_host,
+ int parent_routing_id,
+ int proxy_routing_id) override;
+ void BeforeUnloadFiredFromRenderManager(
+ bool proceed,
+ const base::TimeTicks& proceed_time,
+ bool* proceed_to_fire_unload) override;
+ void RenderProcessGoneFromRenderManager(
+ RenderViewHost* render_view_host) override;
+ void UpdateRenderViewSizeForRenderManager() override;
+ void CancelModalDialogsForRenderManager() override;
+ void NotifySwappedFromRenderManager(RenderFrameHost* old_host,
+ RenderFrameHost* new_host,
+ bool is_main_frame) override;
+ int CreateOpenerRenderViewsForRenderManager(SiteInstance* instance) override;
+ NavigationControllerImpl& GetControllerForRenderManager() override;
+ WebUIImpl* CreateWebUIForRenderManager(const GURL& url) override;
+ NavigationEntry* GetLastCommittedNavigationEntryForRenderManager() override;
+ bool FocusLocationBarByDefault() override;
+ void SetFocusToLocationBar(bool select_all) override;
+ bool IsHidden() override;
// NotificationObserver ------------------------------------------------------
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override;
// NavigationControllerDelegate ----------------------------------------------
- virtual WebContents* GetWebContents() OVERRIDE;
- virtual void NotifyNavigationEntryCommitted(
- const LoadCommittedDetails& load_details) OVERRIDE;
+ WebContents* GetWebContents() override;
+ void NotifyNavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) override;
// Invoked before a form repost warning is shown.
- virtual void NotifyBeforeFormRepostWarningShow() OVERRIDE;
+ void NotifyBeforeFormRepostWarningShow() override;
// Activate this WebContents and show a form repost warning.
- virtual void ActivateAndShowRepostFormWarningDialog() OVERRIDE;
+ void ActivateAndShowRepostFormWarningDialog() override;
// Whether the initial empty page of this view has been accessed by another
// page, making it unsafe to show the pending URL. Always false after the
// first commit.
- virtual bool HasAccessedInitialDocument() OVERRIDE;
+ bool HasAccessedInitialDocument() override;
// Updates the max page ID for the current SiteInstance in this
// WebContentsImpl to be at least |page_id|.
- virtual void UpdateMaxPageID(int32 page_id) OVERRIDE;
+ void UpdateMaxPageID(int32 page_id) override;
// Updates the max page ID for the given SiteInstance in this WebContentsImpl
// to be at least |page_id|.
- virtual void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
- int32 page_id) OVERRIDE;
+ void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance,
+ int32 page_id) override;
// Copy the current map of SiteInstance ID to max page ID from another tab.
// This is necessary when this tab adopts the NavigationEntries from
// |web_contents|.
- virtual void CopyMaxPageIDsFrom(WebContents* web_contents) OVERRIDE;
+ void CopyMaxPageIDsFrom(WebContents* web_contents) override;
// Called by the NavigationController to cause the WebContentsImpl to navigate
// to the current pending entry. The NavigationController should be called
@@ -588,43 +606,63 @@ class CONTENT_EXPORT WebContentsImpl
//
// If this method returns false, then the navigation is discarded (equivalent
// to calling DiscardPendingEntry on the NavigationController).
- virtual bool NavigateToPendingEntry(
- NavigationController::ReloadType reload_type) OVERRIDE;
+ bool NavigateToPendingEntry(
+ NavigationController::ReloadType reload_type) override;
// Sets the history for this WebContentsImpl to |history_length| entries, and
// moves the current page_id to the last entry in the list if it's valid.
// This is mainly used when a prerendered page is swapped into the current
// tab. The method is virtual for testing.
- virtual void SetHistoryLengthAndPrune(
- const SiteInstance* site_instance,
- int merge_history_length,
- int32 minimum_page_id) OVERRIDE;
+ void SetHistoryLengthAndPrune(const SiteInstance* site_instance,
+ int merge_history_length,
+ int32 minimum_page_id) override;
// Called by InterstitialPageImpl when it creates a RenderFrameHost.
- virtual void RenderFrameForInterstitialPageCreated(
- RenderFrameHost* render_frame_host) OVERRIDE;
+ void RenderFrameForInterstitialPageCreated(
+ RenderFrameHost* render_frame_host) override;
// Sets the passed interstitial as the currently showing interstitial.
// No interstitial page should already be attached.
- virtual void AttachInterstitialPage(
- InterstitialPageImpl* interstitial_page) OVERRIDE;
+ void AttachInterstitialPage(InterstitialPageImpl* interstitial_page) override;
// Unsets the currently showing interstitial.
- virtual void DetachInterstitialPage() OVERRIDE;
+ void DetachInterstitialPage() override;
// Changes the IsLoading state and notifies the delegate as needed.
// |details| is used to provide details on the load that just finished
// (but can be null if not applicable).
- virtual void SetIsLoading(RenderViewHost* render_view_host,
- bool is_loading,
- bool to_different_document,
- LoadNotificationDetails* details) OVERRIDE;
+ void SetIsLoading(RenderViewHost* render_view_host,
+ bool is_loading,
+ bool to_different_document,
+ LoadNotificationDetails* details) override;
typedef base::Callback<void(WebContents*)> CreatedCallback;
+ // Requests the renderer to move the selection extent to a new position.
+ void MoveRangeSelectionExtent(const gfx::Point& extent);
+
// Requests the renderer to select the region between two points in the
// currently focused frame.
- void SelectRange(const gfx::Point& start, const gfx::Point& end);
+ void SelectRange(const gfx::Point& base, const gfx::Point& extent);
+
+ // Notifies the main frame that it can continue navigation (if it was deferred
+ // immediately at first response).
+ void ResumeResponseDeferredAtStart();
+
+ // Forces overscroll to be disabled (used by touch emulation).
+ void SetForceDisableOverscrollContent(bool force_disable);
+
+ AudioStreamMonitor* audio_stream_monitor() {
+ return &audio_stream_monitor_;
+ }
+
+ bool has_audio_power_save_blocker_for_testing() const {
+ return audio_power_save_blocker_;
+ }
+
+ bool has_video_power_save_blocker_for_testing() const {
+ return video_power_save_blocker_;
+ }
private:
friend class TestNavigationObserver;
@@ -644,6 +682,8 @@ class CONTENT_EXPORT WebContentsImpl
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrossSiteIframe);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessAccessibilityBrowserTest,
+ CrossSiteIframeAccessibility);
// So InterstitialPageImpl can access SetIsLoading.
friend class InterstitialPageImpl;
@@ -688,10 +728,6 @@ class CONTENT_EXPORT WebContentsImpl
bool success,
const base::string16& user_input);
- // Callback function when requesting permission to access the PPAPI broker.
- // |result| is true if permission was granted.
- void OnPpapiBrokerPermissionResult(int routing_id, bool result);
-
bool OnMessageReceived(RenderViewHost* render_view_host,
RenderFrameHost* render_frame_host,
const IPC::Message& message);
@@ -702,7 +738,7 @@ class CONTENT_EXPORT WebContentsImpl
const std::string& security_info,
const std::string& http_request,
const std::string& mime_type,
- ResourceType::Type resource_type);
+ ResourceType resource_type);
void OnDidDisplayInsecureContent();
void OnDidRunInsecureContent(const std::string& security_origin,
const GURL& target_url);
@@ -720,6 +756,9 @@ class CONTENT_EXPORT WebContentsImpl
const GURL& url,
const base::string16& title,
bool user_gesture);
+ void OnUnregisterProtocolHandler(const std::string& protocol,
+ const GURL& url,
+ bool user_gesture);
void OnFindReply(int request_id,
int number_of_matches,
const gfx::Rect& selection_rect,
@@ -733,11 +772,6 @@ class CONTENT_EXPORT WebContentsImpl
void OnOpenDateTimeDialog(
const ViewHostMsg_DateTimeDialogValue_Params& value);
#endif
- void OnPepperPluginHung(int plugin_child_id,
- const base::FilePath& path,
- bool is_hung);
- void OnPluginCrashed(const base::FilePath& plugin_path,
- base::ProcessId plugin_pid);
void OnDomOperationResponse(const std::string& json_string,
int automation_id);
void OnAppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy);
@@ -749,10 +783,22 @@ class CONTENT_EXPORT WebContentsImpl
void OnWebUISend(const GURL& source_url,
const std::string& name,
const base::ListValue& args);
+#if defined(ENABLE_PLUGINS)
+ void OnPepperPluginHung(int plugin_child_id,
+ const base::FilePath& path,
+ bool is_hung);
+ void OnPluginCrashed(const base::FilePath& plugin_path,
+ base::ProcessId plugin_pid);
void OnRequestPpapiBrokerPermission(int routing_id,
const GURL& url,
const base::FilePath& plugin_path);
+
+ // Callback function when requesting permission to access the PPAPI broker.
+ // |result| is true if permission was granted.
+ void OnPpapiBrokerPermissionResult(int routing_id, bool result);
+
void OnBrowserPluginMessage(const IPC::Message& message);
+#endif // defined(ENABLE_PLUGINS)
void OnDidDownloadImage(int id,
int http_status_code,
const GURL& image_url,
@@ -762,7 +808,8 @@ class CONTENT_EXPORT WebContentsImpl
void OnFirstVisuallyNonEmptyPaint();
void OnMediaPlayingNotification(int64 player_cookie,
bool has_video,
- bool has_audio);
+ bool has_audio,
+ bool is_remote);
void OnMediaPausedNotification(int64 player_cookie);
void OnShowValidationMessage(const gfx::Rect& anchor_in_root_view,
const base::string16& main_text,
@@ -841,7 +888,8 @@ class CONTENT_EXPORT WebContentsImpl
// Misc non-view stuff -------------------------------------------------------
// Helper functions for sending notifications.
- void NotifySwapped(RenderViewHost* old_host, RenderViewHost* new_host);
+ void NotifyViewSwapped(RenderViewHost* old_host, RenderViewHost* new_host);
+ void NotifyFrameSwapped(RenderFrameHost* old_host, RenderFrameHost* new_host);
void NotifyDisconnected();
void SetEncoding(const std::string& encoding);
@@ -855,23 +903,44 @@ class CONTENT_EXPORT WebContentsImpl
// Removes browser plugin embedder if there is one.
void RemoveBrowserPluginEmbedder();
- // Clear |render_frame_host|'s PowerSaveBlockers.
+ // Clear |render_frame_host|'s tracking entry for its power save blockers.
void ClearPowerSaveBlockers(RenderFrameHost* render_frame_host);
- // Clear all PowerSaveBlockers, leave power_save_blocker_ empty.
+ // Clear tracking entries for all RenderFrameHosts, clears
+ // |audio_power_save_blocker_| and |video_power_save_blocker_|.
void ClearAllPowerSaveBlockers();
+ // Creates an audio or video power save blocker respectively.
+ void CreateAudioPowerSaveBlocker();
+ void CreateVideoPowerSaveBlocker();
+
+ // Releases the audio power save blockers if |active_audio_players_| is empty.
+ // Likewise, releases the video power save blockers if |active_video_players_|
+ // is empty.
+ void MaybeReleasePowerSaveBlockers();
+
// Helper function to invoke WebContentsDelegate::GetSizeForNewRenderView().
gfx::Size GetSizeForNewRenderView();
- void OnFrameRemoved(RenderViewHostImpl* render_view_host,
- int frame_routing_id);
+ void OnFrameRemoved(RenderFrameHost* render_frame_host);
// Helper method that's called whenever |preferred_size_| or
// |preferred_size_for_capture_| changes, to propagate the new value to the
// |delegate_|.
void OnPreferredSizeChanged(const gfx::Size& old_size);
+ // Helper methods for adding or removing player entries in |player_map| under
+ // the key |render_frame_message_source_|.
+ typedef std::vector<int64> PlayerList;
+ typedef std::map<uintptr_t, PlayerList> ActiveMediaPlayerMap;
+ void AddMediaPlayerEntry(int64 player_cookie,
+ ActiveMediaPlayerMap* player_map);
+ void RemoveMediaPlayerEntry(int64 player_cookie,
+ ActiveMediaPlayerMap* player_map);
+ // Removes all entries from |player_map| for |render_frame_host|.
+ void RemoveAllMediaPlayerEntries(RenderFrameHost* render_frame_host,
+ ActiveMediaPlayerMap* player_map);
+
// Adds/removes a callback called on creation of each new WebContents.
// Deprecated, about to remove.
static void AddCreatedCallback(const CreatedCallback& callback);
@@ -926,12 +995,11 @@ class CONTENT_EXPORT WebContentsImpl
// Helper classes ------------------------------------------------------------
- // Maps the RenderFrameHost to its media_player_cookie and PowerSaveBlocker
- // pairs. Key is the RenderFrameHost, value is the map which maps
- // player_cookie on to PowerSaveBlocker.
- typedef std::map<RenderFrameHost*, std::map<int64, PowerSaveBlocker*> >
- PowerSaveBlockerMap;
- PowerSaveBlockerMap power_save_blockers_;
+ // Tracking variables and associated power save blockers for media playback.
+ ActiveMediaPlayerMap active_audio_players_;
+ ActiveMediaPlayerMap active_video_players_;
+ scoped_ptr<PowerSaveBlocker> audio_power_save_blocker_;
+ scoped_ptr<PowerSaveBlocker> video_power_save_blocker_;
// Manages the frame tree of the page and process swaps in each node.
FrameTree frame_tree_;
@@ -974,8 +1042,6 @@ class CONTENT_EXPORT WebContentsImpl
base::TimeTicks loading_last_progress_update_;
- base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_;
-
// Counter to track how many frames have sent start notifications but not
// stop notifications.
int loading_frames_in_progress_;
@@ -1101,6 +1167,11 @@ class CONTENT_EXPORT WebContentsImpl
// NULL otherwise.
scoped_ptr<BrowserPluginGuest> browser_plugin_guest_;
+#if defined(ENABLE_PLUGINS)
+ // Manages the whitelist of plugin content origins exempt from power saving.
+ scoped_ptr<PluginContentOriginWhitelist> plugin_content_origin_whitelist_;
+#endif
+
// This must be at the end, or else we might get notifications and use other
// member variables that are gone.
NotificationRegistrar registrar_;
@@ -1118,6 +1189,12 @@ class CONTENT_EXPORT WebContentsImpl
// Routing id of the shown fullscreen widget or MSG_ROUTING_NONE otherwise.
int fullscreen_widget_routing_id_;
+ // At the time the fullscreen widget was being shut down, did it have focus?
+ // This is used to restore focus to the WebContentsView after both: 1) the
+ // fullscreen widget is destroyed, and 2) the WebContentsDelegate has
+ // completed making layout changes to effect an exit from fullscreen mode.
+ bool fullscreen_widget_had_focus_at_shutdown_;
+
// Maps the ids of pending image downloads to their callbacks
typedef std::map<int, ImageDownloadCallback> ImageDownloadMap;
ImageDownloadMap image_download_map_;
@@ -1126,12 +1203,14 @@ class CONTENT_EXPORT WebContentsImpl
// different process from its parent page.
bool is_subframe_;
- // Whether touch emulation is enabled in RenderWidgetHost.
- bool touch_emulation_enabled_;
+ // Whether overscroll should be unconditionally disabled.
+ bool force_disable_overscroll_content_;
// Whether the last JavaScript dialog shown was suppressed. Used for testing.
bool last_dialog_suppressed_;
+ scoped_ptr<GeolocationServiceContext> geolocation_service_context_;
+
scoped_ptr<GeolocationDispatcherHost> geolocation_dispatcher_host_;
scoped_ptr<MidiDispatcherHost> midi_dispatcher_host_;
@@ -1139,6 +1218,20 @@ class CONTENT_EXPORT WebContentsImpl
scoped_ptr<ScreenOrientationDispatcherHost>
screen_orientation_dispatcher_host_;
+ scoped_ptr<ManifestManagerHost> manifest_manager_host_;
+
+ // The accessibility mode for all frames. This is queried when each frame
+ // is created, and broadcast to all frames when it changes.
+ AccessibilityMode accessibility_mode_;
+
+ // Monitors power levels for audio streams associated with this WebContents.
+ AudioStreamMonitor audio_stream_monitor_;
+
+ // Created on-demand to mute all audio output from this WebContents.
+ scoped_ptr<WebContentsAudioMuter> audio_muter_;
+
+ base::WeakPtrFactory<WebContentsImpl> loading_weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsImpl);
};
diff --git a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
index 1f0586cd33d..349af0e73e5 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -63,9 +63,9 @@ class LoadStopNotificationObserver : public WindowedNotificationObserver {
session_index_(-1),
controller_(NULL) {
}
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE {
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override {
if (type == NOTIFICATION_LOAD_STOP) {
const Details<LoadNotificationDetails> load_details(details);
url_ = load_details->url;
@@ -93,8 +93,8 @@ class NavigateOnCommitObserver : public WebContentsObserver {
}
// WebContentsObserver:
- virtual void NavigationEntryCommitted(
- const LoadCommittedDetails& load_details) OVERRIDE {
+ void NavigationEntryCommitted(
+ const LoadCommittedDetails& load_details) override {
if (!done_) {
done_ = true;
shell_->Stop();
@@ -114,8 +114,7 @@ class RenderViewSizeDelegate : public WebContentsDelegate {
}
// WebContentsDelegate:
- virtual gfx::Size GetSizeForNewRenderView(
- WebContents* web_contents) const OVERRIDE {
+ gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const override {
gfx::Size size(web_contents->GetContainerBounds().size());
size.Enlarge(size_insets_.width(), size_insets_.height());
return size;
@@ -134,13 +133,13 @@ class RenderViewSizeObserver : public WebContentsObserver {
}
// WebContentsObserver:
- virtual void RenderViewCreated(RenderViewHost* rvh) OVERRIDE {
+ void RenderViewCreated(RenderViewHost* rvh) override {
rwhv_create_size_ = rvh->GetView()->GetViewBounds().size();
}
- virtual void DidStartNavigationToPendingEntry(
+ void DidStartNavigationToPendingEntry(
const GURL& url,
- NavigationController::ReloadType reload_type) OVERRIDE {
+ NavigationController::ReloadType reload_type) override {
ResizeWebContentsView(shell_, wcv_new_size_, false);
}
@@ -160,8 +159,8 @@ class LoadingStateChangedDelegate : public WebContentsDelegate {
}
// WebContentsDelegate:
- virtual void LoadingStateChanged(WebContents* contents,
- bool to_different_document) OVERRIDE {
+ void LoadingStateChanged(WebContents* contents,
+ bool to_different_document) override {
loadingStateChangedCount_++;
if (to_different_document)
loadingStateToDifferentDocumentCount_++;
@@ -259,9 +258,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
shell()->web_contents()->GetVisibleURL());
}
-// TODO(shrikant): enable this for Windows when issue with
-// force-compositing-mode is resolved (http://crbug.com/281726).
-// Also crashes under ThreadSanitizer, http://crbug.com/356758.
+// Crashes under ThreadSanitizer, http://crbug.com/356758.
#if defined(OS_WIN) || defined(OS_ANDROID) \
|| defined(THREAD_SANITIZER)
#define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
@@ -341,20 +338,43 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, OpenURLSubframe) {
-
- // Navigate with FrameTreeNode ID 4.
- const GURL url("http://foo");
- OpenURLParams params(url, Referrer(), 4, CURRENT_TAB, PAGE_TRANSITION_LINK,
- true);
+ // Navigate to a page with frames and grab a subframe's FrameTreeNode ID.
+ ASSERT_TRUE(test_server()->Start());
+ NavigateToURL(shell(),
+ test_server()->GetURL("files/frame_tree/top.html"));
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = wc->GetFrameTree()->root();
+ ASSERT_EQ(3UL, root->child_count());
+ int64 frame_tree_node_id = root->child_at(0)->frame_tree_node_id();
+ EXPECT_NE(-1, frame_tree_node_id);
+
+ // Navigate with the subframe's FrameTreeNode ID.
+ const GURL url(test_server()->GetURL("files/title1.html"));
+ OpenURLParams params(url, Referrer(), frame_tree_node_id, CURRENT_TAB,
+ ui::PAGE_TRANSITION_LINK, true);
shell()->web_contents()->OpenURL(params);
// Make sure the NavigationEntry ends up with the FrameTreeNode ID.
NavigationController* controller = &shell()->web_contents()->GetController();
EXPECT_TRUE(controller->GetPendingEntry());
- EXPECT_EQ(4, NavigationEntryImpl::FromNavigationEntry(
+ EXPECT_EQ(frame_tree_node_id,
+ NavigationEntryImpl::FromNavigationEntry(
controller->GetPendingEntry())->frame_tree_node_id());
}
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ AppendingFrameInWebUIDoesNotCrash) {
+ const GURL kWebUIUrl("chrome://tracing");
+ const char kJSCodeForAppendingFrame[] =
+ "document.body.appendChild(document.createElement('iframe'));";
+
+ NavigateToURL(shell(), kWebUIUrl);
+
+ bool js_executed = content::ExecuteScript(shell()->web_contents(),
+ kJSCodeForAppendingFrame);
+ EXPECT_TRUE(js_executed);
+}
+
// Observer class to track the creation of RenderFrameHost objects. It is used
// in subsequent tests.
class RenderFrameCreatedObserver : public WebContentsObserver {
@@ -364,7 +384,7 @@ class RenderFrameCreatedObserver : public WebContentsObserver {
last_rfh_(NULL) {
}
- virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE {
+ void RenderFrameCreated(RenderFrameHost* render_frame_host) override {
last_rfh_ = render_frame_host;
}
@@ -468,22 +488,21 @@ struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
}
// WebContentsDelegate:
- virtual void LoadProgressChanged(WebContents* source,
- double progress) OVERRIDE {
+ void LoadProgressChanged(WebContents* source, double progress) override {
EXPECT_TRUE(did_start_loading);
EXPECT_FALSE(did_stop_loading);
progresses.push_back(progress);
}
// WebContentsObserver:
- virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE {
+ void DidStartLoading(RenderViewHost* render_view_host) override {
EXPECT_FALSE(did_start_loading);
EXPECT_EQ(0U, progresses.size());
EXPECT_FALSE(did_stop_loading);
did_start_loading = true;
}
- virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE {
+ void DidStopLoading(RenderViewHost* render_view_host) override {
EXPECT_TRUE(did_start_loading);
EXPECT_GE(progresses.size(), 1U);
EXPECT_FALSE(did_stop_loading);
@@ -517,5 +536,46 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, LoadProgress) {
EXPECT_EQ(1.0, *progresses.rbegin());
}
+struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
+ FirstVisuallyNonEmptyPaintObserver(Shell* shell)
+ : WebContentsObserver(shell->web_contents()),
+ did_fist_visually_non_empty_paint_(false) {}
+
+ void DidFirstVisuallyNonEmptyPaint() override {
+ did_fist_visually_non_empty_paint_ = true;
+ on_did_first_visually_non_empty_paint_.Run();
+ }
+
+ void WaitForDidFirstVisuallyNonEmptyPaint() {
+ if (did_fist_visually_non_empty_paint_)
+ return;
+ base::RunLoop run_loop;
+ on_did_first_visually_non_empty_paint_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+
+ base::Closure on_did_first_visually_non_empty_paint_;
+ bool did_fist_visually_non_empty_paint_;
+};
+
+// See: http://crbug.com/395664
+#if defined(OS_ANDROID)
+#define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
+#else
+// http://crbug.com/398471
+#define MAYBE_FirstVisuallyNonEmptyPaint DISABLED_FirstVisuallyNonEmptyPaint
+#endif
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ MAYBE_FirstVisuallyNonEmptyPaint) {
+ ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+ scoped_ptr<FirstVisuallyNonEmptyPaintObserver> observer(
+ new FirstVisuallyNonEmptyPaintObserver(shell()));
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
+
+ observer->WaitForDidFirstVisuallyNonEmptyPaint();
+ ASSERT_TRUE(observer->did_fist_visually_non_empty_paint_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
index a345598fcf0..a361553dd25 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -7,6 +7,7 @@
#include "content/browser/frame_host/cross_site_transferring_request.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
@@ -30,6 +31,7 @@
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
+#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -42,25 +44,25 @@ const char kTestWebUIUrl[] = "chrome://blah";
class WebContentsImplTestWebUIControllerFactory
: public WebUIControllerFactory {
public:
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const OVERRIDE {
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override {
if (!UseWebUI(url))
return NULL;
return new WebUIController(web_ui);
}
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override {
return WebUI::kNoWebUI;
}
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return UseWebUI(url);
}
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return UseWebUI(url);
}
@@ -76,10 +78,11 @@ class TestInterstitialPageDelegate : public InterstitialPageDelegate {
public:
explicit TestInterstitialPageDelegate(TestInterstitialPage* interstitial_page)
: interstitial_page_(interstitial_page) {}
- virtual void CommandReceived(const std::string& command) OVERRIDE;
- virtual std::string GetHTMLContents() OVERRIDE { return std::string(); }
- virtual void OnDontProceed() OVERRIDE;
- virtual void OnProceed() OVERRIDE;
+ void CommandReceived(const std::string& command) override;
+ std::string GetHTMLContents() override { return std::string(); }
+ void OnDontProceed() override;
+ void OnProceed() override;
+
private:
TestInterstitialPage* interstitial_page_;
};
@@ -128,7 +131,7 @@ class TestInterstitialPage : public InterstitialPageImpl {
*deleted_ = false;
}
- virtual ~TestInterstitialPage() {
+ ~TestInterstitialPage() override {
if (deleted_)
*deleted_ = true;
if (delegate_)
@@ -155,7 +158,7 @@ class TestInterstitialPage : public InterstitialPageImpl {
void TestDidNavigate(int page_id, const GURL& url) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- InitNavigateParams(&params, page_id, url, PAGE_TRANSITION_TYPED);
+ InitNavigateParams(&params, page_id, url, ui::PAGE_TRANSITION_TYPED);
DidNavigate(GetRenderViewHostForTesting(), params);
}
@@ -184,9 +187,7 @@ class TestInterstitialPage : public InterstitialPageImpl {
}
protected:
- virtual WebContentsView* CreateWebContentsView() OVERRIDE {
- return NULL;
- }
+ WebContentsView* CreateWebContentsView() override { return NULL; }
private:
InterstitialState* state_;
@@ -215,13 +216,13 @@ class TestInterstitialPageStateGuard : public TestInterstitialPage::Delegate {
DCHECK(interstitial_page_);
interstitial_page_->set_delegate(this);
}
- virtual ~TestInterstitialPageStateGuard() {
+ ~TestInterstitialPageStateGuard() override {
if (interstitial_page_)
interstitial_page_->ClearStates();
}
- virtual void TestInterstitialPageDeleted(
- TestInterstitialPage* interstitial) OVERRIDE {
+ void TestInterstitialPageDeleted(
+ TestInterstitialPage* interstitial) override {
DCHECK(interstitial_page_ == interstitial);
interstitial_page_ = NULL;
}
@@ -235,9 +236,9 @@ class WebContentsImplTestBrowserClient : public TestContentBrowserClient {
WebContentsImplTestBrowserClient()
: assign_site_for_url_(false) {}
- virtual ~WebContentsImplTestBrowserClient() {}
+ ~WebContentsImplTestBrowserClient() override {}
- virtual bool ShouldAssignSiteForURL(const GURL& url) OVERRIDE {
+ bool ShouldAssignSiteForURL(const GURL& url) override {
return assign_site_for_url_;
}
@@ -251,12 +252,12 @@ class WebContentsImplTestBrowserClient : public TestContentBrowserClient {
class WebContentsImplTest : public RenderViewHostImplTestHarness {
public:
- virtual void SetUp() {
+ void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
WebUIControllerFactory::RegisterFactory(&factory_);
}
- virtual void TearDown() {
+ void TearDown() override {
WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
RenderViewHostImplTestHarness::TearDown();
}
@@ -270,20 +271,16 @@ class TestWebContentsObserver : public WebContentsObserver {
explicit TestWebContentsObserver(WebContents* contents)
: WebContentsObserver(contents) {
}
- virtual ~TestWebContentsObserver() {}
+ ~TestWebContentsObserver() override {}
- virtual void DidFinishLoad(int64 frame_id,
- const GURL& validated_url,
- bool is_main_frame,
- RenderViewHost* render_view_host) OVERRIDE {
+ void DidFinishLoad(RenderFrameHost* render_frame_host,
+ const GURL& validated_url) override {
last_url_ = validated_url;
}
- virtual void DidFailLoad(int64 frame_id,
- const GURL& validated_url,
- bool is_main_frame,
- int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) OVERRIDE {
+ void DidFailLoad(RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ int error_code,
+ const base::string16& error_description) override {
last_url_ = validated_url;
}
@@ -300,15 +297,15 @@ class TestWebContentsObserver : public WebContentsObserver {
class FakeFullscreenDelegate : public WebContentsDelegate {
public:
FakeFullscreenDelegate() : fullscreened_contents_(NULL) {}
- virtual ~FakeFullscreenDelegate() {}
+ ~FakeFullscreenDelegate() override {}
- virtual void ToggleFullscreenModeForTab(WebContents* web_contents,
- bool enter_fullscreen) OVERRIDE {
+ void ToggleFullscreenModeForTab(WebContents* web_contents,
+ bool enter_fullscreen) override {
fullscreened_contents_ = enter_fullscreen ? web_contents : NULL;
}
- virtual bool IsFullscreenForTabOrPending(const WebContents* web_contents)
- const OVERRIDE {
+ bool IsFullscreenForTabOrPending(
+ const WebContents* web_contents) const override {
return fullscreened_contents_ && web_contents == fullscreened_contents_;
}
@@ -322,9 +319,9 @@ class FakeValidationMessageDelegate : public WebContentsDelegate {
public:
FakeValidationMessageDelegate()
: hide_validation_message_was_called_(false) {}
- virtual ~FakeValidationMessageDelegate() {}
+ ~FakeValidationMessageDelegate() override {}
- virtual void HideValidationMessage(WebContents* web_contents) OVERRIDE {
+ void HideValidationMessage(WebContents* web_contents) override {
hide_validation_message_was_called_ = true;
}
@@ -346,12 +343,12 @@ TEST_F(WebContentsImplTest, UpdateTitle) {
static_cast<NavigationControllerImpl&>(controller());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
InitNavigateParams(
- &params, 0, GURL(url::kAboutBlankURL), PAGE_TRANSITION_TYPED);
+ &params, 0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED);
LoadCommittedDetails details;
- cont.RendererDidNavigate(main_test_rfh(), params, &details);
+ cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details);
- contents()->UpdateTitle(main_test_rfh(), 0,
+ contents()->UpdateTitle(contents()->GetMainFrame(), 0,
base::ASCIIToUTF16(" Lots O' Whitespace\n"),
base::i18n::LEFT_TO_RIGHT);
EXPECT_EQ(base::ASCIIToUTF16("Lots O' Whitespace"), contents()->GetTitle());
@@ -360,7 +357,7 @@ TEST_F(WebContentsImplTest, UpdateTitle) {
TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) {
const GURL kGURL("chrome://blah");
controller().LoadURL(
- kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_EQ(base::string16(), contents()->GetTitle());
}
@@ -368,7 +365,7 @@ TEST_F(WebContentsImplTest, UseTitleFromPendingEntryIfSet) {
const GURL kGURL("chrome://blah");
const base::string16 title = base::ASCIIToUTF16("My Title");
controller().LoadURL(
- kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
NavigationEntry* entry = controller().GetVisibleEntry();
ASSERT_EQ(kGURL, entry->GetURL());
@@ -387,16 +384,16 @@ TEST_F(WebContentsImplTest, NTPViewSource) {
process()->sink().ClearMessages();
cont.LoadURL(
- kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
rvh()->GetDelegate()->RenderViewCreated(rvh());
// Did we get the expected message?
EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
ViewMsg_EnableViewSourceMode::ID));
FrameHostMsg_DidCommitProvisionalLoad_Params params;
- InitNavigateParams(&params, 0, kGURL, PAGE_TRANSITION_TYPED);
+ InitNavigateParams(&params, 0, kGURL, ui::PAGE_TRANSITION_TYPED);
LoadCommittedDetails details;
- cont.RendererDidNavigate(main_test_rfh(), params, &details);
+ cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details);
// Also check title and url.
EXPECT_EQ(base::ASCIIToUTF16(kUrl), contents()->GetTitle());
}
@@ -426,16 +423,16 @@ TEST_F(WebContentsImplTest, UpdateMaxPageID) {
// Test simple same-SiteInstance navigation.
TEST_F(WebContentsImplTest, SimpleNavigation) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
SiteInstance* instance1 = contents()->GetSiteInstance();
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
// Navigate to URL
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(instance1, orig_rvh->GetSiteInstance());
+ EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
// Controller's pending entry will have a NULL site instance until we assign
// it in DidNavigate.
EXPECT_TRUE(
@@ -443,10 +440,10 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
site_instance() == NULL);
// DidNavigate from the page
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
- EXPECT_EQ(instance1, orig_rvh->GetSiteInstance());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
+ EXPECT_EQ(instance1, orig_rfh->GetSiteInstance());
// Controller's entry should now have the SiteInstance, or else we won't be
// able to find it later.
EXPECT_EQ(
@@ -462,73 +459,66 @@ TEST_F(WebContentsImplTest, NavigateToExcessivelyLongURL) {
GetMaxURLChars() + 1, 'a'));
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_GENERATED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_GENERATED, std::string());
EXPECT_TRUE(controller().GetVisibleEntry() == NULL);
}
// Test that navigating across a site boundary creates a new RenderViewHost
// with a new SiteInstance. Going back should do the same.
TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
- TestRenderViewHost* orig_rvh = test_rvh();
- RenderFrameHostImpl* orig_rfh =
- contents()->GetFrameTree()->root()->current_frame_host();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
int orig_rvh_delete_count = 0;
- orig_rvh->set_delete_counter(&orig_rvh_delete_count);
+ orig_rfh->GetRenderViewHost()->set_delete_counter(&orig_rvh_delete_count);
SiteInstance* instance1 = contents()->GetSiteInstance();
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
- // Keep the number of active views in orig_rvh's SiteInstance
- // non-zero so that orig_rvh doesn't get deleted when it gets
- // swapped out.
- static_cast<SiteInstanceImpl*>(orig_rvh->GetSiteInstance())->
- increment_active_view_count();
+ // Keep the number of active frames in orig_rfh's SiteInstance non-zero so
+ // that orig_rfh doesn't get deleted when it gets swapped out.
+ orig_rfh->GetSiteInstance()->increment_active_frame_count();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url, contents()->GetVisibleURL());
// Navigate to new site
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(contents()->cross_navigation_pending());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
- TestRenderViewHost* pending_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
int pending_rvh_delete_count = 0;
- pending_rvh->set_delete_counter(&pending_rvh_delete_count);
- RenderFrameHostImpl* pending_rfh = contents()->GetFrameTree()->root()->
- render_manager()->pending_frame_host();
+ pending_rfh->GetRenderViewHost()->set_delete_counter(
+ &pending_rvh_delete_count);
- // Navigations should be suspended in pending_rvh until BeforeUnloadACK.
- EXPECT_TRUE(pending_rvh->are_navigations_suspended());
- orig_rvh->SendBeforeUnloadACK(true);
- EXPECT_FALSE(pending_rvh->are_navigations_suspended());
+ // Navigations should be suspended in pending_rfh until BeforeUnloadACK.
+ EXPECT_TRUE(pending_rfh->are_navigations_suspended());
+ orig_rfh->SendBeforeUnloadACK(true);
+ EXPECT_FALSE(pending_rfh->are_navigations_suspended());
// DidNavigate from the pending page
contents()->TestDidNavigate(
- pending_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents()->GetSiteInstance();
- // Keep the number of active views in pending_rvh's SiteInstance
- // non-zero so that orig_rvh doesn't get deleted when it gets
+ // Keep the number of active frames in pending_rfh's SiteInstance
+ // non-zero so that orig_rfh doesn't get deleted when it gets
// swapped out.
- static_cast<SiteInstanceImpl*>(pending_rvh->GetSiteInstance())->
- increment_active_view_count();
+ pending_rfh->GetSiteInstance()->increment_active_frame_count();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(pending_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
EXPECT_EQ(url2, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
EXPECT_NE(instance1, instance2);
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
// We keep the original RFH around, swapped out.
EXPECT_TRUE(contents()->GetRenderManagerForTesting()->IsOnSwappedOutList(
orig_rfh));
@@ -536,29 +526,27 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
// Going back should switch SiteInstances again. The first SiteInstance is
// stored in the NavigationEntry, so it should be the same as at the start.
- // We should use the same RVH as before, swapping it back in.
+ // We should use the same RFH as before, swapping it back in.
controller().GoBack();
- TestRenderViewHost* goback_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
- EXPECT_EQ(orig_rvh, goback_rvh);
+ TestRenderFrameHost* goback_rfh = contents()->GetPendingMainFrame();
+ EXPECT_EQ(orig_rfh, goback_rfh);
EXPECT_TRUE(contents()->cross_navigation_pending());
- // Navigations should be suspended in goback_rvh until BeforeUnloadACK.
- EXPECT_TRUE(goback_rvh->are_navigations_suspended());
- pending_rvh->SendBeforeUnloadACK(true);
- EXPECT_FALSE(goback_rvh->are_navigations_suspended());
+ // Navigations should be suspended in goback_rfh until BeforeUnloadACK.
+ EXPECT_TRUE(goback_rfh->are_navigations_suspended());
+ pending_rfh->SendBeforeUnloadACK(true);
+ EXPECT_FALSE(goback_rfh->are_navigations_suspended());
// DidNavigate from the back action
- contents()->TestDidNavigate(
- goback_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(goback_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(goback_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(goback_rfh, contents()->GetMainFrame());
EXPECT_EQ(instance1, contents()->GetSiteInstance());
// The pending RFH should now be swapped out, not deleted.
EXPECT_TRUE(contents()->GetRenderManagerForTesting()->
IsOnSwappedOutList(pending_rfh));
EXPECT_EQ(pending_rvh_delete_count, 0);
- pending_rvh->OnSwappedOut(false);
+ pending_rfh->OnSwappedOut();
// Close contents and ensure RVHs are deleted.
DeleteContents();
@@ -567,43 +555,45 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
}
// Test that navigating across a site boundary after a crash creates a new
-// RVH without requiring a cross-site transition (i.e., PENDING state).
+// RFH without requiring a cross-site transition (i.e., PENDING state).
TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
+
int orig_rvh_delete_count = 0;
- orig_rvh->set_delete_counter(&orig_rvh_delete_count);
+ orig_rfh->GetRenderViewHost()->set_delete_counter(&orig_rvh_delete_count);
SiteInstance* instance1 = contents()->GetSiteInstance();
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost());
- // Crash the renderer.
- orig_rvh->set_render_view_created(false);
+ // Simulate a renderer crash.
+ orig_rfh->GetRenderViewHost()->set_render_view_created(false);
+ orig_rfh->set_render_frame_created(false);
// Navigate to new site. We should not go into PENDING.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- RenderViewHost* new_rvh = rvh();
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ TestRenderFrameHost* new_rfh = contents()->GetMainFrame();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
- EXPECT_NE(orig_rvh, new_rvh);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
+ EXPECT_NE(orig_rfh, new_rfh);
EXPECT_EQ(orig_rvh_delete_count, 1);
// DidNavigate from the new page
- contents()->TestDidNavigate(new_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(new_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(new_rvh, rvh());
+ EXPECT_EQ(new_rfh, main_rfh());
EXPECT_NE(instance1, instance2);
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
// Close contents and ensure RVHs are deleted.
DeleteContents();
@@ -614,56 +604,53 @@ TEST_F(WebContentsImplTest, CrossSiteBoundariesAfterCrash) {
// both contentses to a new site will place both contentses in a single
// SiteInstance.
TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
SiteInstance* instance1 = contents()->GetSiteInstance();
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
// Open a new contents with the same SiteInstance, navigated to the same site.
scoped_ptr<TestWebContents> contents2(
TestWebContents::Create(browser_context(), instance1));
contents2->GetController().LoadURL(url, Referrer(),
- PAGE_TRANSITION_TYPED,
- std::string());
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
// Need this page id to be 2 since the site instance is the same (which is the
// scope of page IDs) and we want to consider this a new page.
contents2->TestDidNavigate(
- contents2->GetRenderViewHost(), 2, url, PAGE_TRANSITION_TYPED);
+ contents2->GetMainFrame(), 2, url, ui::PAGE_TRANSITION_TYPED);
// Navigate first contents to a new site.
const GURL url2a("http://www.yahoo.com");
controller().LoadURL(
- url2a, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- orig_rvh->SendBeforeUnloadACK(true);
- TestRenderViewHost* pending_rvh_a =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ url2a, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ orig_rfh->SendBeforeUnloadACK(true);
+ TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame();
contents()->TestDidNavigate(
- pending_rvh_a, 1, url2a, PAGE_TRANSITION_TYPED);
+ pending_rfh_a, 1, url2a, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2a = contents()->GetSiteInstance();
EXPECT_NE(instance1, instance2a);
// Navigate second contents to the same site as the first tab.
const GURL url2b("http://mail.yahoo.com");
contents2->GetController().LoadURL(url2b, Referrer(),
- PAGE_TRANSITION_TYPED,
- std::string());
- TestRenderViewHost* rvh2 =
- static_cast<TestRenderViewHost*>(contents2->GetRenderViewHost());
- rvh2->SendBeforeUnloadACK(true);
- TestRenderViewHost* pending_rvh_b =
- static_cast<TestRenderViewHost*>(contents2->GetPendingRenderViewHost());
- EXPECT_TRUE(pending_rvh_b != NULL);
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
+ TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
+ rfh2->SendBeforeUnloadACK(true);
+ TestRenderFrameHost* pending_rfh_b = contents2->GetPendingMainFrame();
+ EXPECT_TRUE(pending_rfh_b != NULL);
EXPECT_TRUE(contents2->cross_navigation_pending());
// NOTE(creis): We used to be in danger of showing a crash page here if the
// second contents hadn't navigated somewhere first (bug 1145430). That case
// is now covered by the CrossSiteBoundariesAfterCrash test.
contents2->TestDidNavigate(
- pending_rvh_b, 2, url2b, PAGE_TRANSITION_TYPED);
+ pending_rfh_b, 2, url2b, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2b = contents2->GetSiteInstance();
EXPECT_NE(instance1, instance2b);
@@ -671,27 +658,29 @@ TEST_F(WebContentsImplTest, NavigateTwoTabsCrossSite) {
EXPECT_EQ(instance2a, instance2b);
}
-TEST_F(WebContentsImplTest, NavigateDoesNotUseUpSiteInstance) {
+// The embedder can request sites for certain urls not be be assigned to the
+// SiteInstance through ShouldAssignSiteForURL() in content browser client,
+// allowing to reuse the renderer backing certain chrome urls for subsequent
+// navigation. The test verifies that the override is honored.
+TEST_F(WebContentsImplTest, NavigateFromSitelessUrl) {
WebContentsImplTestBrowserClient browser_client;
SetBrowserClientForTesting(&browser_client);
- TestRenderViewHost* orig_rvh = test_rvh();
- RenderFrameHostImpl* orig_rfh =
- contents()->GetFrameTree()->root()->current_frame_host();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
int orig_rvh_delete_count = 0;
- orig_rvh->set_delete_counter(&orig_rvh_delete_count);
- SiteInstanceImpl* orig_instance =
- static_cast<SiteInstanceImpl*>(contents()->GetSiteInstance());
+ orig_rfh->GetRenderViewHost()->set_delete_counter(&orig_rvh_delete_count);
+ SiteInstanceImpl* orig_instance = contents()->GetSiteInstance();
browser_client.set_assign_site_for_url(false);
// Navigate to an URL that will not assign a new SiteInstance.
const GURL native_url("non-site-url://stuffandthings");
controller().LoadURL(
- native_url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, native_url, PAGE_TRANSITION_TYPED);
+ native_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(
+ orig_rfh, 1, native_url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
EXPECT_EQ(native_url, contents()->GetVisibleURL());
EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
@@ -702,18 +691,17 @@ TEST_F(WebContentsImplTest, NavigateDoesNotUseUpSiteInstance) {
// Navigate to new site (should keep same site instance).
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(contents()->cross_navigation_pending());
EXPECT_EQ(native_url, contents()->GetLastCommittedURL());
EXPECT_EQ(url, contents()->GetVisibleURL());
- EXPECT_FALSE(contents()->GetPendingRenderViewHost());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
- // Keep the number of active views in orig_rvh's SiteInstance
- // non-zero so that orig_rvh doesn't get deleted when it gets
+ // Keep the number of active frames in orig_rfh's SiteInstance
+ // non-zero so that orig_rfh doesn't get deleted when it gets
// swapped out.
- static_cast<SiteInstanceImpl*>(orig_rvh->GetSiteInstance())->
- increment_active_view_count();
+ orig_rfh->GetSiteInstance()->increment_active_frame_count();
EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
EXPECT_TRUE(
@@ -723,36 +711,36 @@ TEST_F(WebContentsImplTest, NavigateDoesNotUseUpSiteInstance) {
// Navigate to another new site (should create a new site instance).
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(contents()->cross_navigation_pending());
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
- TestRenderViewHost* pending_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
int pending_rvh_delete_count = 0;
- pending_rvh->set_delete_counter(&pending_rvh_delete_count);
+ pending_rfh->GetRenderViewHost()->set_delete_counter(
+ &pending_rvh_delete_count);
// Navigations should be suspended in pending_rvh until BeforeUnloadACK.
- EXPECT_TRUE(pending_rvh->are_navigations_suspended());
- orig_rvh->SendBeforeUnloadACK(true);
- EXPECT_FALSE(pending_rvh->are_navigations_suspended());
+ EXPECT_TRUE(pending_rfh->are_navigations_suspended());
+ orig_rfh->SendBeforeUnloadACK(true);
+ EXPECT_FALSE(pending_rfh->are_navigations_suspended());
// DidNavigate from the pending page.
contents()->TestDidNavigate(
- pending_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
SiteInstance* new_instance = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(pending_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
EXPECT_EQ(url2, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
EXPECT_NE(new_instance, orig_instance);
- EXPECT_FALSE(contents()->GetPendingRenderViewHost());
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
// We keep the original RFH around, swapped out.
EXPECT_TRUE(contents()->GetRenderManagerForTesting()->IsOnSwappedOutList(
orig_rfh));
EXPECT_EQ(orig_rvh_delete_count, 0);
- orig_rvh->OnSwappedOut(false);
+ orig_rfh->OnSwappedOut();
// Close contents and ensure RVHs are deleted.
DeleteContents();
@@ -760,61 +748,146 @@ TEST_F(WebContentsImplTest, NavigateDoesNotUseUpSiteInstance) {
EXPECT_EQ(pending_rvh_delete_count, 1);
}
+// Regression test for http://crbug.com/386542 - variation of
+// NavigateFromSitelessUrl in which the original navigation is a session
+// restore.
+TEST_F(WebContentsImplTest, NavigateFromRestoredSitelessUrl) {
+ WebContentsImplTestBrowserClient browser_client;
+ SetBrowserClientForTesting(&browser_client);
+ SiteInstanceImpl* orig_instance = contents()->GetSiteInstance();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
+
+ // Restore a navigation entry for URL that should not assign site to the
+ // SiteInstance.
+ browser_client.set_assign_site_for_url(false);
+ const GURL native_url("non-site-url://stuffandthings");
+ std::vector<NavigationEntry*> entries;
+ NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
+ native_url, Referrer(), ui::PAGE_TRANSITION_LINK, false, std::string(),
+ browser_context());
+ entry->SetPageID(0);
+ entries.push_back(entry);
+ controller().Restore(
+ 0,
+ NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
+ &entries);
+ ASSERT_EQ(0u, entries.size());
+ ASSERT_EQ(1, controller().GetEntryCount());
+ controller().GoToIndex(0);
+ contents()->TestDidNavigate(
+ orig_rfh, 0, native_url, ui::PAGE_TRANSITION_RELOAD);
+ EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
+ EXPECT_EQ(GURL(), contents()->GetSiteInstance()->GetSiteURL());
+ EXPECT_FALSE(orig_instance->HasSite());
+
+ // Navigate to a regular site and verify that the SiteInstance was kept.
+ browser_client.set_assign_site_for_url(true);
+ const GURL url("http://www.google.com");
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 2, url, ui::PAGE_TRANSITION_TYPED);
+ EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
+
+ // Cleanup.
+ DeleteContents();
+}
+
+// Complement for NavigateFromRestoredSitelessUrl, verifying that when a regular
+// tab is restored, the SiteInstance will change upon navigation.
+TEST_F(WebContentsImplTest, NavigateFromRestoredRegularUrl) {
+ WebContentsImplTestBrowserClient browser_client;
+ SetBrowserClientForTesting(&browser_client);
+ SiteInstanceImpl* orig_instance = contents()->GetSiteInstance();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
+
+ // Restore a navigation entry for a regular URL ensuring that the embedder
+ // ShouldAssignSiteForUrl override is disabled (i.e. returns true).
+ browser_client.set_assign_site_for_url(true);
+ const GURL regular_url("http://www.yahoo.com");
+ std::vector<NavigationEntry*> entries;
+ NavigationEntry* entry = NavigationControllerImpl::CreateNavigationEntry(
+ regular_url, Referrer(), ui::PAGE_TRANSITION_LINK, false, std::string(),
+ browser_context());
+ entry->SetPageID(0);
+ entries.push_back(entry);
+ controller().Restore(
+ 0,
+ NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY,
+ &entries);
+ ASSERT_EQ(0u, entries.size());
+ ASSERT_EQ(1, controller().GetEntryCount());
+ controller().GoToIndex(0);
+ contents()->TestDidNavigate(
+ orig_rfh, 0, regular_url, ui::PAGE_TRANSITION_RELOAD);
+ EXPECT_EQ(orig_instance, contents()->GetSiteInstance());
+ EXPECT_TRUE(orig_instance->HasSite());
+
+ // Navigate to another site and verify that a new SiteInstance was created.
+ const GURL url("http://www.google.com");
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(
+ contents()->GetPendingMainFrame(), 2, url, ui::PAGE_TRANSITION_TYPED);
+ EXPECT_NE(orig_instance, contents()->GetSiteInstance());
+
+ // Cleanup.
+ DeleteContents();
+}
+
// Test that we can find an opener RVH even if it's pending.
// http://crbug.com/176252.
TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
// Navigate to a URL.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
// Start to navigate first tab to a new site, so that it has a pending RVH.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- orig_rvh->SendBeforeUnloadACK(true);
- TestRenderViewHost* pending_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ orig_rfh->SendBeforeUnloadACK(true);
+ TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
// While it is still pending, simulate opening a new tab with the first tab
// as its opener. This will call WebContentsImpl::CreateOpenerRenderViews
// on the opener to ensure that an RVH exists.
- int opener_routing_id = contents()->CreateOpenerRenderViews(
- pending_rvh->GetSiteInstance());
+ int opener_routing_id =
+ contents()->CreateOpenerRenderViews(pending_rfh->GetSiteInstance());
// We should find the pending RVH and not create a new one.
- EXPECT_EQ(pending_rvh->GetRoutingID(), opener_routing_id);
+ EXPECT_EQ(pending_rfh->GetRenderViewHost()->GetRoutingID(),
+ opener_routing_id);
}
// Tests that WebContentsImpl uses the current URL, not the SiteInstance's site,
// to determine whether a navigation is cross-site.
TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
- RenderViewHost* orig_rvh = rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
SiteInstance* instance1 = contents()->GetSiteInstance();
// Navigate to URL.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
contents()->TestDidNavigate(
- orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
// Open a related contents to a second site.
scoped_ptr<TestWebContents> contents2(
TestWebContents::Create(browser_context(), instance1));
const GURL url2("http://www.yahoo.com");
contents2->GetController().LoadURL(url2, Referrer(),
- PAGE_TRANSITION_TYPED,
- std::string());
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
// The first RVH in contents2 isn't live yet, so we shortcut the cross site
// pending.
- TestRenderViewHost* rvh2 = static_cast<TestRenderViewHost*>(
- contents2->GetRenderViewHost());
+ TestRenderFrameHost* rfh2 = contents2->GetMainFrame();
EXPECT_FALSE(contents2->cross_navigation_pending());
- contents2->TestDidNavigate(rvh2, 2, url2, PAGE_TRANSITION_TYPED);
+ contents2->TestDidNavigate(rfh2, 2, url2, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents2->GetSiteInstance();
EXPECT_NE(instance1, instance2);
EXPECT_FALSE(contents2->cross_navigation_pending());
@@ -822,7 +895,7 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// Simulate a link click in first contents to second site. Doesn't switch
// SiteInstances, because we don't intercept WebKit navigations.
contents()->TestDidNavigate(
- orig_rvh, 2, url2, PAGE_TRANSITION_TYPED);
+ orig_rfh, 2, url2, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance3 = contents()->GetSiteInstance();
EXPECT_EQ(instance1, instance3);
EXPECT_FALSE(contents()->cross_navigation_pending());
@@ -831,10 +904,10 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// compare against the current URL, not the SiteInstance's site.
const GURL url3("http://mail.yahoo.com");
controller().LoadURL(
- url3, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(contents()->cross_navigation_pending());
contents()->TestDidNavigate(
- orig_rvh, 3, url3, PAGE_TRANSITION_TYPED);
+ orig_rfh, 3, url3, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance4 = contents()->GetSiteInstance();
EXPECT_EQ(instance1, instance4);
}
@@ -842,150 +915,149 @@ TEST_F(WebContentsImplTest, CrossSiteComparesAgainstCurrentPage) {
// Test that the onbeforeunload and onunload handlers run when navigating
// across site boundaries.
TEST_F(WebContentsImplTest, CrossSiteUnloadHandlers) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
SiteInstance* instance1 = contents()->GetSiteInstance();
// Navigate to URL. First URL should use first RenderViewHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Navigate to new site, but simulate an onbeforeunload denial.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
base::TimeTicks now = base::TimeTicks::Now();
- orig_rvh->GetMainFrame()->OnMessageReceived(
+ orig_rfh->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, false, now, now));
- EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Navigate again, but simulate an onbeforeunload approval.
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
now = base::TimeTicks::Now();
- orig_rvh->GetMainFrame()->OnMessageReceived(
+ orig_rfh->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
- EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetPendingRenderViewHost());
+ TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
// We won't hear DidNavigate until the onunload handler has finished running.
// DidNavigate from the pending page.
contents()->TestDidNavigate(
- pending_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(pending_rvh, rvh());
+ EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
EXPECT_NE(instance1, instance2);
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
}
// Test that during a slow cross-site navigation, the original renderer can
// navigate to a different URL and have it displayed, canceling the slow
// navigation.
TEST_F(WebContentsImplTest, CrossSiteNavigationPreempted) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
SiteInstance* instance1 = contents()->GetSiteInstance();
- // Navigate to URL. First URL should use first RenderViewHost.
+ // Navigate to URL. First URL should use first RenderFrameHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Navigate to new site, simulating an onbeforeunload approval.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
base::TimeTicks now = base::TimeTicks::Now();
- orig_rvh->GetMainFrame()->OnMessageReceived(
- FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
+ orig_rfh->OnMessageReceived(FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
EXPECT_TRUE(contents()->cross_navigation_pending());
// Suppose the original renderer navigates before the new one is ready.
- orig_rvh->SendNavigate(2, GURL("http://www.google.com/foo"));
+ orig_rfh->SendNavigate(2, GURL("http://www.google.com/foo"));
// Verify that the pending navigation is cancelled.
- EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, rvh());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
EXPECT_EQ(instance1, instance2);
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
}
TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
// Start with a web ui page, which gets a new RVH with WebUI bindings.
const GURL url1("chrome://blah");
controller().LoadURL(
- url1, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- TestRenderViewHost* ntp_rvh = test_rvh();
- contents()->TestDidNavigate(ntp_rvh, 1, url1, PAGE_TRANSITION_TYPED);
+ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ TestRenderFrameHost* ntp_rfh = contents()->GetMainFrame();
+ contents()->TestDidNavigate(ntp_rfh, 1, url1, ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry1 = controller().GetLastCommittedEntry();
SiteInstance* instance1 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(ntp_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(ntp_rfh, contents()->GetMainFrame());
EXPECT_EQ(url1, entry1->GetURL());
EXPECT_EQ(instance1,
NavigationEntryImpl::FromNavigationEntry(entry1)->site_instance());
- EXPECT_TRUE(ntp_rvh->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
+ EXPECT_TRUE(ntp_rfh->GetRenderViewHost()->GetEnabledBindings() &
+ BINDINGS_POLICY_WEB_UI);
// Navigate to new site.
const GURL url2("http://www.google.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* google_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ TestRenderFrameHost* google_rfh = contents()->GetPendingMainFrame();
// Simulate beforeunload approval.
- EXPECT_TRUE(ntp_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_TRUE(ntp_rfh->is_waiting_for_beforeunload_ack());
base::TimeTicks now = base::TimeTicks::Now();
- ntp_rvh->GetMainFrame()->OnMessageReceived(
+ ntp_rfh->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
// DidNavigate from the pending page.
contents()->TestDidNavigate(
- google_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ google_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry2 = controller().GetLastCommittedEntry();
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(google_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(google_rfh, contents()->GetMainFrame());
EXPECT_NE(instance1, instance2);
- EXPECT_FALSE(contents()->GetPendingRenderViewHost());
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
EXPECT_EQ(url2, entry2->GetURL());
EXPECT_EQ(instance2,
NavigationEntryImpl::FromNavigationEntry(entry2)->site_instance());
- EXPECT_FALSE(google_rvh->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
+ EXPECT_FALSE(google_rfh->GetRenderViewHost()->GetEnabledBindings() &
+ BINDINGS_POLICY_WEB_UI);
// Navigate to third page on same site.
const GURL url3("http://news.google.com");
controller().LoadURL(
- url3, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(contents()->cross_navigation_pending());
contents()->TestDidNavigate(
- google_rvh, 2, url3, PAGE_TRANSITION_TYPED);
+ google_rfh, 2, url3, ui::PAGE_TRANSITION_TYPED);
NavigationEntry* entry3 = controller().GetLastCommittedEntry();
SiteInstance* instance3 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(google_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(google_rfh, contents()->GetMainFrame());
EXPECT_EQ(instance2, instance3);
- EXPECT_FALSE(contents()->GetPendingRenderViewHost());
+ EXPECT_FALSE(contents()->GetPendingMainFrame());
EXPECT_EQ(url3, entry3->GetURL());
EXPECT_EQ(instance3,
NavigationEntryImpl::FromNavigationEntry(entry3)->site_instance());
@@ -998,22 +1070,22 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
// Before that commits, go back again.
controller().GoBack();
EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost());
+ EXPECT_TRUE(contents()->GetPendingMainFrame());
EXPECT_EQ(entry1, controller().GetPendingEntry());
// Simulate beforeunload approval.
- EXPECT_TRUE(google_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_TRUE(google_rfh->is_waiting_for_beforeunload_ack());
now = base::TimeTicks::Now();
- google_rvh->GetMainFrame()->OnMessageReceived(
+ google_rfh->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
- // DidNavigate from the first back. This aborts the second back's pending RVH.
- contents()->TestDidNavigate(google_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ // DidNavigate from the first back. This aborts the second back's pending RFH.
+ contents()->TestDidNavigate(google_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
// We should commit this page and forget about the second back.
EXPECT_FALSE(contents()->cross_navigation_pending());
EXPECT_FALSE(controller().GetPendingEntry());
- EXPECT_EQ(google_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(google_rfh, contents()->GetMainFrame());
EXPECT_EQ(url2, controller().GetLastCommittedEntry()->GetURL());
// We should not have corrupted the NTP entry.
@@ -1029,33 +1101,34 @@ TEST_F(WebContentsImplTest, CrossSiteNavigationBackPreempted) {
// Test that during a slow cross-site navigation, a sub-frame navigation in the
// original renderer will not cancel the slow navigation (bug 42029).
TEST_F(WebContentsImplTest, CrossSiteNavigationNotPreemptedByFrame) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
- // Navigate to URL. First URL should use first RenderViewHost.
+ // Navigate to URL. First URL should use the original RenderFrameHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Start navigating to new site.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Simulate a sub-frame navigation arriving and ensure the RVH is still
// waiting for a before unload response.
- orig_rvh->SendNavigateWithTransition(1, GURL("http://google.com/frame"),
- PAGE_TRANSITION_AUTO_SUBFRAME);
- EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
+ TestRenderFrameHost* child_rfh = orig_rfh->AppendChild("subframe");
+ child_rfh->SendNavigateWithTransition(
+ 1, GURL("http://google.com/frame"), ui::PAGE_TRANSITION_AUTO_SUBFRAME);
+ EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
// Now simulate the onbeforeunload approval and verify the navigation is
// not canceled.
base::TimeTicks now = base::TimeTicks::Now();
- orig_rvh->GetMainFrame()->OnMessageReceived(
+ orig_rfh->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
- EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
EXPECT_TRUE(contents()->cross_navigation_pending());
}
@@ -1067,163 +1140,107 @@ TEST_F(WebContentsImplTest, CrossSiteNotPreemptedDuringBeforeUnload) {
// Navigate to NTP URL.
const GURL url("chrome://blah");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- TestRenderViewHost* orig_rvh = test_rvh();
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
EXPECT_FALSE(contents()->cross_navigation_pending());
// Navigate to new site, with the beforeunload request in flight.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- TestRenderViewHost* pending_rvh =
- static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
// Suppose the first navigation tries to commit now, with a
- // ViewMsg_Stop in flight. This should not cancel the pending navigation,
+ // FrameMsg_Stop in flight. This should not cancel the pending navigation,
// but it should act as if the beforeunload ack arrived.
- orig_rvh->SendNavigate(1, GURL("chrome://blah"));
+ orig_rfh->SendNavigate(1, GURL("chrome://blah"));
EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
- EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
+ EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
// The pending navigation should be able to commit successfully.
- contents()->TestDidNavigate(pending_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(pending_rvh, contents()->GetRenderViewHost());
-}
-
-// Test that the original renderer cannot preempt a cross-site navigation once
-// the unload request has been made. At this point, the cross-site navigation
-// is almost ready to be displayed, and the original renderer is only given a
-// short chance to run an unload handler. Prevents regression of bug 23942.
-TEST_F(WebContentsImplTest, CrossSiteCantPreemptAfterUnload) {
- TestRenderViewHost* orig_rvh = test_rvh();
- SiteInstance* instance1 = contents()->GetSiteInstance();
-
- // Navigate to URL. First URL should use first RenderViewHost.
- const GURL url("http://www.google.com");
- controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
- EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
-
- // Navigate to new site, simulating an onbeforeunload approval.
- const GURL url2("http://www.yahoo.com");
- controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- base::TimeTicks now = base::TimeTicks::Now();
- orig_rvh->GetMainFrame()->OnMessageReceived(
- FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
- EXPECT_TRUE(contents()->cross_navigation_pending());
- TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>(
- contents()->GetPendingRenderViewHost());
-
- // Simulate the pending renderer's response, which leads to an unload request
- // being sent to orig_rvh.
- std::vector<GURL> url_chain;
- url_chain.push_back(GURL());
- contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
- contents()->GetRenderManagerForTesting()->pending_frame_host(),
- GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
- url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
-
- // Suppose the original renderer navigates now, while the unload request is in
- // flight. We should ignore it, wait for the unload ack, and let the pending
- // request continue. Otherwise, the contents may close spontaneously or stop
- // responding to navigation requests. (See bug 23942.)
- FrameHostMsg_DidCommitProvisionalLoad_Params params1a;
- InitNavigateParams(&params1a, 2, GURL("http://www.google.com/foo"),
- PAGE_TRANSITION_TYPED);
- orig_rvh->SendNavigate(2, GURL("http://www.google.com/foo"));
-
- // Verify that the pending navigation is still in progress.
- EXPECT_TRUE(contents()->cross_navigation_pending());
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() != NULL);
-
- // DidNavigate from the pending page should commit it.
- contents()->TestDidNavigate(
- pending_rvh, 1, url2, PAGE_TRANSITION_TYPED);
- SiteInstance* instance2 = contents()->GetSiteInstance();
- EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(pending_rvh, rvh());
- EXPECT_NE(instance1, instance2);
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_EQ(pending_rfh, contents()->GetMainFrame());
}
// Test that a cross-site navigation that doesn't commit after the unload
// handler doesn't leave the contents in a stuck state. http://crbug.com/88562
TEST_F(WebContentsImplTest, CrossSiteNavigationCanceled) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
SiteInstance* instance1 = contents()->GetSiteInstance();
- // Navigate to URL. First URL should use first RenderViewHost.
+ // Navigate to URL. First URL should use original RenderFrameHost.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Navigate to new site, simulating an onbeforeunload approval.
const GURL url2("http://www.yahoo.com");
- controller().LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- EXPECT_TRUE(orig_rvh->is_waiting_for_beforeunload_ack());
+ controller().LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ EXPECT_TRUE(orig_rfh->is_waiting_for_beforeunload_ack());
base::TimeTicks now = base::TimeTicks::Now();
- orig_rvh->GetMainFrame()->OnMessageReceived(
+ orig_rfh->OnMessageReceived(
FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
EXPECT_TRUE(contents()->cross_navigation_pending());
// Simulate swap out message when the response arrives.
- orig_rvh->OnSwappedOut(false);
+ orig_rfh->OnSwappedOut();
// Suppose the navigation doesn't get a chance to commit, and the user
- // navigates in the current RVH's SiteInstance.
- controller().LoadURL(url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ // navigates in the current RFH's SiteInstance.
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Verify that the pending navigation is cancelled and the renderer is no
// longer swapped out.
- EXPECT_FALSE(orig_rvh->is_waiting_for_beforeunload_ack());
+ EXPECT_FALSE(orig_rfh->is_waiting_for_beforeunload_ack());
SiteInstance* instance2 = contents()->GetSiteInstance();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, rvh());
- EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, orig_rvh->rvh_state());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, orig_rfh->rfh_state());
EXPECT_EQ(instance1, instance2);
- EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+ EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
}
// Test that NavigationEntries have the correct page state after going
// forward and back. Prevents regression for bug 1116137.
TEST_F(WebContentsImplTest, NavigationEntryContentState) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
// Navigate to URL. There should be no committed entry yet.
const GURL url("http://www.google.com");
- controller().LoadURL(url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
NavigationEntry* entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry == NULL);
// Committed entry should have page state after DidNavigate.
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
// Navigate to same site.
const GURL url2("http://images.google.com");
- controller().LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller().LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
// Committed entry should have page state after DidNavigate.
- contents()->TestDidNavigate(orig_rvh, 2, url2, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(orig_rfh, 2, url2, ui::PAGE_TRANSITION_TYPED);
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
// Now go back. Committed entry should still have page state.
controller().GoBack();
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
entry = controller().GetLastCommittedEntry();
EXPECT_TRUE(entry->GetPageState().IsValid());
}
@@ -1232,13 +1249,13 @@ TEST_F(WebContentsImplTest, NavigationEntryContentState) {
// state after opening a new window to about:blank. Prevents regression for
// bugs b/1116137 and http://crbug.com/111975.
TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
// When opening a new window, it is navigated to about:blank internally.
// Currently, this results in two DidNavigate events.
const GURL url(url::kAboutBlankURL);
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
// Should have a page state here.
NavigationEntry* entry = controller().GetLastCommittedEntry();
@@ -1253,10 +1270,10 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
// Navigating to a normal page should not cause a process swap.
const GURL new_url("http://www.google.com");
controller().LoadURL(new_url, Referrer(),
- PAGE_TRANSITION_TYPED, std::string());
+ ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
- contents()->TestDidNavigate(orig_rvh, 1, new_url, PAGE_TRANSITION_TYPED);
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
+ contents()->TestDidNavigate(orig_rfh, 1, new_url, ui::PAGE_TRANSITION_TYPED);
NavigationEntryImpl* entry_impl2 = NavigationEntryImpl::FromNavigationEntry(
controller().GetLastCommittedEntry());
EXPECT_EQ(site_instance_id, entry_impl2->site_instance()->GetId());
@@ -1268,14 +1285,15 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) {
TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
FakeFullscreenDelegate fake_delegate;
contents()->SetDelegate(&fake_delegate);
- TestRenderViewHost* orig_rvh = test_rvh();
+ TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
+ TestRenderViewHost* orig_rvh = orig_rfh->GetRenderViewHost();
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
EXPECT_FALSE(orig_rvh->IsFullscreen());
@@ -1290,10 +1308,10 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
// Navigate to a new site.
const GURL url2("http://www.yahoo.com");
controller().LoadURL(
- url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- RenderViewHost* const pending_rvh = contents()->GetPendingRenderViewHost();
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ TestRenderFrameHost* const pending_rfh = contents()->GetPendingMainFrame();
contents()->TestDidNavigate(
- pending_rvh, 1, url2, PAGE_TRANSITION_TYPED);
+ pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED);
// Confirm fullscreen has exited.
EXPECT_FALSE(orig_rvh->IsFullscreen());
@@ -1308,20 +1326,23 @@ TEST_F(WebContentsImplTest, NavigationExitsFullscreen) {
TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
FakeFullscreenDelegate fake_delegate;
contents()->SetDelegate(&fake_delegate);
- TestRenderViewHost* const orig_rvh = test_rvh();
+ TestRenderFrameHost* const orig_rfh = contents()->GetMainFrame();
+ TestRenderViewHost* const orig_rvh = orig_rfh->GetRenderViewHost();
// Navigate to a site.
const GURL url("http://www.google.com");
- controller().LoadURL(url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(orig_rvh, 1, url, PAGE_TRANSITION_TYPED);
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED);
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Now, navigate to another page on the same site.
const GURL url2("http://www.google.com/search?q=kittens");
- controller().LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller().LoadURL(
+ url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(contents()->cross_navigation_pending());
- contents()->TestDidNavigate(orig_rvh, 2, url2, PAGE_TRANSITION_TYPED);
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ contents()->TestDidNavigate(orig_rfh, 2, url2, ui::PAGE_TRANSITION_TYPED);
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
// Sanity-check: Confirm we're not starting out in fullscreen mode.
EXPECT_FALSE(orig_rvh->IsFullscreen());
@@ -1342,9 +1363,9 @@ TEST_F(WebContentsImplTest, HistoryNavigationExitsFullscreen) {
else
controller().GoForward();
EXPECT_FALSE(contents()->cross_navigation_pending());
- EXPECT_EQ(orig_rvh, contents()->GetRenderViewHost());
+ EXPECT_EQ(orig_rfh, contents()->GetMainFrame());
contents()->TestDidNavigate(
- orig_rvh, i + 1, url, PAGE_TRANSITION_FORWARD_BACK);
+ orig_rfh, i + 1, url, ui::PAGE_TRANSITION_FORWARD_BACK);
// Confirm fullscreen has exited.
EXPECT_FALSE(orig_rvh->IsFullscreen());
@@ -1361,7 +1382,7 @@ TEST_F(WebContentsImplTest, TerminateHidesValidationMessage) {
EXPECT_FALSE(fake_delegate.hide_validation_message_was_called());
// Crash the renderer.
- test_rvh()->OnMessageReceived(
+ contents()->GetMainFrame()->GetRenderViewHost()->OnMessageReceived(
ViewHostMsg_RenderProcessGone(
0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1));
@@ -1380,9 +1401,9 @@ TEST_F(WebContentsImplTest, CrashExitsFullscreen) {
// Navigate to a site.
const GURL url("http://www.google.com");
controller().LoadURL(
- url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
- contents()->TestDidNavigate(test_rvh(), 1, url, PAGE_TRANSITION_TYPED);
- EXPECT_EQ(test_rvh(), contents()->GetRenderViewHost());
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ contents()->TestDidNavigate(
+ contents()->GetMainFrame(), 1, url, ui::PAGE_TRANSITION_TYPED);
// Toggle fullscreen mode on (as if initiated via IPC from renderer).
EXPECT_FALSE(test_rvh()->IsFullscreen());
@@ -1418,12 +1439,12 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
- PAGE_TRANSITION_TYPED, std::string());
+ ui::PAGE_TRANSITION_TYPED, std::string());
// Show an interstitial.
TestInterstitialPage::InterstitialState state =
@@ -1468,7 +1489,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitiaFromRendererlWithNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial (no pending entry, the interstitial would have been
@@ -1514,7 +1535,7 @@ TEST_F(WebContentsImplTest,
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1561,12 +1582,12 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromBrowserNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
- PAGE_TRANSITION_TYPED, std::string());
+ ui::PAGE_TRANSITION_TYPED, std::string());
// Show an interstitial.
TestInterstitialPage::InterstitialState state =
@@ -1602,7 +1623,7 @@ TEST_F(WebContentsImplTest,
// Simulate the navigation to the page, that's when the interstitial gets
// hidden.
GURL url3("http://www.thepage.com");
- test_rvh()->SendNavigate(2, url3);
+ contents()->GetMainFrame()->SendNavigate(2, url3);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
@@ -1623,7 +1644,7 @@ TEST_F(WebContentsImplTest,
ShowInterstitialFromRendererNewNavigationProceed) {
// Navigate to a page.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1660,7 +1681,7 @@ TEST_F(WebContentsImplTest,
// Simulate the navigation to the page, that's when the interstitial gets
// hidden.
GURL url3("http://www.thepage.com");
- test_rvh()->SendNavigate(2, url3);
+ contents()->GetMainFrame()->SendNavigate(2, url3);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
@@ -1680,7 +1701,7 @@ TEST_F(WebContentsImplTest,
TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1738,7 +1759,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
// While interstitial showing, navigate to a new URL.
const GURL url2("http://www.yahoo.com");
- test_rvh()->SendNavigate(1, url2);
+ contents()->GetMainFrame()->SendNavigate(1, url2);
EXPECT_EQ(TestInterstitialPage::CANCELED, state);
@@ -1750,7 +1771,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenNavigate) {
TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -1767,7 +1788,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
// While the interstitial is showing, go back.
controller().GoBack();
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
// Make sure we are back to the original page and that the interstitial is
// gone.
@@ -1785,7 +1806,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) {
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -1807,7 +1828,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
// While the interstitial is showing, go back.
controller().GoBack();
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
// Make sure we are back to the original page and that the interstitial is
// gone.
@@ -1825,7 +1846,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) {
TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show interstitial.
@@ -1904,7 +1925,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenCloseAndShutdown) {
TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
// Navigate to a page so we have a navigation entry in the controller.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1939,7 +1960,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) {
TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
// Navigate to a page so we have a navigation entry in the controller.
GURL start_url("http://www.google.com");
- test_rvh()->SendNavigate(1, start_url);
+ contents()->GetMainFrame()->SendNavigate(1, start_url);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -1975,7 +1996,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
// Let's make sure interstitial2 is working as intended.
interstitial2->Proceed();
GURL landing_url("http://www.thepage.com");
- test_rvh()->SendNavigate(2, landing_url);
+ contents()->GetMainFrame()->SendNavigate(2, landing_url);
EXPECT_FALSE(contents()->ShowingInterstitialPage());
EXPECT_TRUE(contents()->GetInterstitialPage() == NULL);
@@ -1992,7 +2013,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) {
TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
// Navigate to a page so we have a navigation entry in the controller.
GURL start_url("http://www.google.com");
- test_rvh()->SendNavigate(1, start_url);
+ contents()->GetMainFrame()->SendNavigate(1, start_url);
EXPECT_EQ(1, controller().GetEntryCount());
// Show an interstitial.
@@ -2032,7 +2053,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) {
// Let's make sure interstitial2 is working as intended.
interstitial2->Proceed();
GURL landing_url("http://www.thepage.com");
- test_rvh()->SendNavigate(2, landing_url);
+ contents()->GetMainFrame()->SendNavigate(2, landing_url);
RunAllPendingInMessageLoop();
EXPECT_TRUE(deleted2);
@@ -2061,7 +2082,8 @@ TEST_F(WebContentsImplTest, NavigateBeforeInterstitialShows) {
// Let's simulate a navigation initiated from the browser before the
// interstitial finishes loading.
const GURL url("http://www.google.com");
- controller().LoadURL(url, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ controller().LoadURL(
+ url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
EXPECT_FALSE(interstitial->is_showing());
RunAllPendingInMessageLoop();
ASSERT_FALSE(deleted);
@@ -2158,7 +2180,7 @@ TEST_F(WebContentsImplTest, NewInterstitialDoesNotCancelPendingEntry) {
// Start a navigation to a page
contents()->GetController().LoadURL(
- kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// Simulate that navigation triggering an interstitial.
TestInterstitialPage::InterstitialState state =
@@ -2173,7 +2195,7 @@ TEST_F(WebContentsImplTest, NewInterstitialDoesNotCancelPendingEntry) {
// Initiate a new navigation from the browser that also triggers an
// interstitial.
contents()->GetController().LoadURL(
- kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
TestInterstitialPage::InterstitialState state2 =
TestInterstitialPage::INVALID;
bool deleted2 = false;
@@ -2204,9 +2226,10 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
// Start a navigation to a page
contents()->GetController().LoadURL(
- kGURL, Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
// DidNavigate from the page
- contents()->TestDidNavigate(rvh(), 1, kGURL, PAGE_TRANSITION_TYPED);
+ contents()->TestDidNavigate(
+ contents()->GetMainFrame(), 1, kGURL, ui::PAGE_TRANSITION_TYPED);
// Simulate showing an interstitial while the page is showing.
TestInterstitialPage::InterstitialState state =
@@ -2233,12 +2256,12 @@ TEST_F(WebContentsImplTest, NoJSMessageOnInterstitials) {
TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) {
// Navigate to a page.
GURL url1("http://www.google.com");
- test_rvh()->SendNavigate(1, url1);
+ contents()->GetMainFrame()->SendNavigate(1, url1);
EXPECT_EQ(1, controller().GetEntryCount());
// Initiate a browser navigation that will trigger the interstitial
controller().LoadURL(GURL("http://www.evil.com"), Referrer(),
- PAGE_TRANSITION_TYPED, std::string());
+ ui::PAGE_TRANSITION_TYPED, std::string());
// Show an interstitial.
TestInterstitialPage::InterstitialState state =
@@ -2429,7 +2452,7 @@ class ContentsZoomChangedDelegate : public WebContentsDelegate {
}
// WebContentsDelegate:
- virtual void ContentsZoomChange(bool zoom_in) OVERRIDE {
+ void ContentsZoomChange(bool zoom_in) override {
contents_zoom_changed_call_count_++;
last_zoom_in_ = zoom_in;
}
@@ -2567,12 +2590,12 @@ TEST_F(WebContentsImplTest, ActiveContentsCountBasic) {
EXPECT_EQ(0u, instance2->GetRelatedActiveContentsCount());
scoped_ptr<TestWebContents> contents1(
- TestWebContents::Create(browser_context(), instance1));
+ TestWebContents::Create(browser_context(), instance1.get()));
EXPECT_EQ(1u, instance1->GetRelatedActiveContentsCount());
EXPECT_EQ(1u, instance2->GetRelatedActiveContentsCount());
scoped_ptr<TestWebContents> contents2(
- TestWebContents::Create(browser_context(), instance1));
+ TestWebContents::Create(browser_context(), instance1.get()));
EXPECT_EQ(2u, instance1->GetRelatedActiveContentsCount());
EXPECT_EQ(2u, instance2->GetRelatedActiveContentsCount());
@@ -2594,26 +2617,32 @@ TEST_F(WebContentsImplTest, ActiveContentsCountNavigate) {
EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());
scoped_ptr<TestWebContents> contents(
- TestWebContents::Create(browser_context(), instance));
+ TestWebContents::Create(browser_context(), instance.get()));
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
// Navigate to a URL.
- contents->GetController().LoadURL(
- GURL("http://a.com/1"), Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ contents->GetController().LoadURL(GURL("http://a.com/1"),
+ Referrer(),
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
contents->CommitPendingNavigation();
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
// Navigate to a URL in the same site.
- contents->GetController().LoadURL(
- GURL("http://a.com/2"), Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ contents->GetController().LoadURL(GURL("http://a.com/2"),
+ Referrer(),
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
contents->CommitPendingNavigation();
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
// Navigate to a URL in a different site.
- contents->GetController().LoadURL(
- GURL("http://b.com"), Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ contents->GetController().LoadURL(GURL("http://b.com"),
+ Referrer(),
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
EXPECT_TRUE(contents->cross_navigation_pending());
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
contents->CommitPendingNavigation();
@@ -2632,7 +2661,7 @@ TEST_F(WebContentsImplTest, ActiveContentsCountChangeBrowsingInstance) {
EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount());
scoped_ptr<TestWebContents> contents(
- TestWebContents::Create(browser_context(), instance));
+ TestWebContents::Create(browser_context(), instance.get()));
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
// Navigate to a URL.
@@ -2640,11 +2669,13 @@ TEST_F(WebContentsImplTest, ActiveContentsCountChangeBrowsingInstance) {
EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount());
// Navigate to a URL with WebUI. This will change BrowsingInstances.
- contents->GetController().LoadURL(
- GURL(kTestWebUIUrl), Referrer(), PAGE_TRANSITION_TYPED, std::string());
+ contents->GetController().LoadURL(GURL(kTestWebUIUrl),
+ Referrer(),
+ ui::PAGE_TRANSITION_TYPED,
+ std::string());
EXPECT_TRUE(contents->cross_navigation_pending());
scoped_refptr<SiteInstance> instance_webui(
- contents->GetPendingRenderViewHost()->GetSiteInstance());
+ contents->GetPendingMainFrame()->GetSiteInstance());
EXPECT_FALSE(instance->IsRelatedSiteInstance(instance_webui.get()));
// At this point, contents still counts for the old BrowsingInstance.
@@ -2661,4 +2692,106 @@ TEST_F(WebContentsImplTest, ActiveContentsCountChangeBrowsingInstance) {
EXPECT_EQ(0u, instance_webui->GetRelatedActiveContentsCount());
}
+// ChromeOS doesn't use WebContents based power save blocking.
+#if !defined(OS_CHROMEOS)
+TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
+ // PlayerIDs are actually pointers cast to int64, so verify that both negative
+ // and positive player ids don't blow up.
+ const int kPlayerAudioVideoId = 15;
+ const int kPlayerAudioOnlyId = -15;
+ const int kPlayerVideoOnlyId = 30;
+ const int kPlayerRemoteId = -30;
+
+ EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
+ EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
+
+ TestRenderFrameHost* rfh = contents()->GetMainFrame();
+ AudioStreamMonitor* monitor = contents()->audio_stream_monitor();
+
+ // The audio power save blocker should not be based on having a media player
+ // when audio stream monitoring is available.
+ if (AudioStreamMonitor::monitoring_available()) {
+ // Send a fake audio stream monitor notification. The audio power save
+ // blocker should be created.
+ monitor->set_was_recently_audible_for_testing(true);
+ contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ EXPECT_TRUE(contents()->has_audio_power_save_blocker_for_testing());
+
+ // Send another fake notification, this time when WasRecentlyAudible() will
+ // be false. The power save blocker should be released.
+ monitor->set_was_recently_audible_for_testing(false);
+ contents()->NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
+ }
+
+ // Start a player with both audio and video. A video power save blocker
+ // should be created. If audio stream monitoring is available, an audio power
+ // save blocker should be created too.
+ rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
+ 0, kPlayerAudioVideoId, true, true, false));
+ EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
+ !AudioStreamMonitor::monitoring_available());
+
+ // Upon hiding the video power save blocker should be released.
+ contents()->WasHidden();
+ EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
+
+ // Start another player that only has video. There should be no change in
+ // the power save blockers. The notification should take into account the
+ // visibility state of the WebContents.
+ rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
+ 0, kPlayerVideoOnlyId, true, false, false));
+ EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
+ !AudioStreamMonitor::monitoring_available());
+
+ // Showing the WebContents should result in the creation of the blocker.
+ contents()->WasShown();
+ EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
+
+ // Start another player that only has audio. There should be no change in
+ // the power save blockers.
+ rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
+ 0, kPlayerAudioOnlyId, false, true, false));
+ EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
+ !AudioStreamMonitor::monitoring_available());
+
+ // Start a remote player. There should be no change in the power save
+ // blockers.
+ rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
+ 0, kPlayerRemoteId, true, true, true));
+ EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
+ !AudioStreamMonitor::monitoring_available());
+
+ // Destroy the original audio video player. Both power save blockers should
+ // remain.
+ rfh->OnMessageReceived(
+ FrameHostMsg_MediaPausedNotification(0, kPlayerAudioVideoId));
+ EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_EQ(contents()->has_audio_power_save_blocker_for_testing(),
+ !AudioStreamMonitor::monitoring_available());
+
+ // Destroy the audio only player. The video power save blocker should remain.
+ rfh->OnMessageReceived(
+ FrameHostMsg_MediaPausedNotification(0, kPlayerAudioOnlyId));
+ EXPECT_TRUE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
+
+ // Destroy the video only player. No power save blockers should remain.
+ rfh->OnMessageReceived(
+ FrameHostMsg_MediaPausedNotification(0, kPlayerVideoOnlyId));
+ EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
+
+ // Destroy the remote player. No power save blockers should remain.
+ rfh->OnMessageReceived(
+ FrameHostMsg_MediaPausedNotification(0, kPlayerRemoteId));
+ EXPECT_FALSE(contents()->has_video_power_save_blocker_for_testing());
+ EXPECT_FALSE(contents()->has_audio_power_save_blocker_for_testing());
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc b/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc
index acec01ded69..eeb2acb3de2 100644
--- a/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_user_data_unittest.cc
@@ -15,7 +15,8 @@ namespace content {
class WebContentsAttachedClass1
: public WebContentsUserData<WebContentsAttachedClass1> {
public:
- virtual ~WebContentsAttachedClass1() {}
+ ~WebContentsAttachedClass1() override {}
+
private:
explicit WebContentsAttachedClass1(WebContents* contents) {}
friend class WebContentsUserData<WebContentsAttachedClass1>;
@@ -24,7 +25,8 @@ class WebContentsAttachedClass1
class WebContentsAttachedClass2
: public WebContentsUserData<WebContentsAttachedClass2> {
public:
- virtual ~WebContentsAttachedClass2() {}
+ ~WebContentsAttachedClass2() override {}
+
private:
explicit WebContentsAttachedClass2(WebContents* contents) {}
friend class WebContentsUserData<WebContentsAttachedClass2>;
diff --git a/chromium/content/browser/web_contents/web_contents_view.h b/chromium/content/browser/web_contents/web_contents_view.h
index b2eb5090138..47daee9bac8 100644
--- a/chromium/content/browser/web_contents/web_contents_view.h
+++ b/chromium/content/browser/web_contents/web_contents_view.h
@@ -79,8 +79,13 @@ class WebContentsView {
// Sets up the View that holds the rendered web page, receives messages for
// it and contains page plugins. The host view should be sized to the current
// size of the WebContents.
+ //
+ // |is_guest_view_hack| is temporary hack and will be removed once
+ // RenderWidgetHostViewGuest is not dependent on platform view.
+ // TODO(lazyboy): Remove |is_guest_view_hack| once http://crbug.com/330264 is
+ // fixed.
virtual RenderWidgetHostViewBase* CreateViewForWidget(
- RenderWidgetHost* render_widget_host) = 0;
+ RenderWidgetHost* render_widget_host, bool is_guest_view_hack) = 0;
// Creates a new View that holds a popup and receives messages for it.
virtual RenderWidgetHostViewBase* CreateViewForPopupWidget(
@@ -104,23 +109,12 @@ class WebContentsView {
virtual void SetOverscrollControllerEnabled(bool enabled) = 0;
#if defined(OS_MACOSX)
- // The web contents view assumes that its view will never be overlapped by
- // another view (either partially or fully). This allows it to perform
- // optimizations. If the view is in a view hierarchy where it might be
- // overlapped by another view, notify the view by calling this with |true|.
- virtual void SetAllowOverlappingViews(bool overlapping) = 0;
-
- // Returns true if overlapping views are allowed, false otherwise.
- virtual bool GetAllowOverlappingViews() const = 0;
-
- // To draw two overlapping web contents view, the underlaying one should
- // know about the overlaying one. Caller must ensure that |overlay| exists
- // until |RemoveOverlayView| is called.
- virtual void SetOverlayView(WebContentsView* overlay,
- const gfx::Point& offset) = 0;
-
- // Removes the previously set overlay view.
- virtual void RemoveOverlayView() = 0;
+ // Allowing other views disables optimizations which assume that only a single
+ // WebContents is present.
+ virtual void SetAllowOtherViews(bool allow) = 0;
+
+ // Returns true if other views are allowed, false otherwise.
+ virtual bool GetAllowOtherViews() const = 0;
// If we close the tab while a UI control is in an event-tracking
// loop, the control may message freed objects and crash.
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.cc b/chromium/content/browser/web_contents/web_contents_view_android.cc
index 3378595be7e..b276b191409 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_android.cc
@@ -121,7 +121,7 @@ void WebContentsViewAndroid::CreateView(
}
RenderWidgetHostViewBase* WebContentsViewAndroid::CreateViewForWidget(
- RenderWidgetHost* render_widget_host) {
+ RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
if (render_widget_host->GetView()) {
// During testing, the view will already be set up in most cases to the
// test view, so we don't want to clobber it with a real one. To verify that
@@ -163,6 +163,7 @@ void WebContentsViewAndroid::ShowContextMenu(
}
void WebContentsViewAndroid::ShowPopupMenu(
+ RenderFrameHost* render_frame_host,
const gfx::Rect& bounds,
int item_height,
double item_font_size,
@@ -171,8 +172,11 @@ void WebContentsViewAndroid::ShowPopupMenu(
bool right_aligned,
bool allow_multiple_selection) {
if (content_view_core_) {
- content_view_core_->ShowSelectPopupMenu(
- bounds, items, selected_item, allow_multiple_selection);
+ content_view_core_->ShowSelectPopupMenu(render_frame_host,
+ bounds,
+ items,
+ selected_item,
+ allow_multiple_selection);
}
}
diff --git a/chromium/content/browser/web_contents/web_contents_view_android.h b/chromium/content/browser/web_contents/web_contents_view_android.h
index 2503595e840..c480c0e9bd9 100644
--- a/chromium/content/browser/web_contents/web_contents_view_android.h
+++ b/chromium/content/browser/web_contents/web_contents_view_android.h
@@ -30,47 +30,48 @@ class WebContentsViewAndroid : public WebContentsView,
void SetContentViewCore(ContentViewCoreImpl* content_view_core);
// WebContentsView implementation --------------------------------------------
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeView GetContentNativeView() const OVERRIDE;
- virtual gfx::NativeWindow GetTopLevelNativeWindow() const OVERRIDE;
- virtual void GetContainerBounds(gfx::Rect* out) const OVERRIDE;
- virtual void SizeContents(const gfx::Size& size) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void SetInitialFocus() OVERRIDE;
- virtual void StoreFocus() OVERRIDE;
- virtual void RestoreFocus() OVERRIDE;
- virtual DropData* GetDropData() const OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
+ virtual gfx::NativeView GetNativeView() const override;
+ virtual gfx::NativeView GetContentNativeView() const override;
+ virtual gfx::NativeWindow GetTopLevelNativeWindow() const override;
+ virtual void GetContainerBounds(gfx::Rect* out) const override;
+ virtual void SizeContents(const gfx::Size& size) override;
+ virtual void Focus() override;
+ virtual void SetInitialFocus() override;
+ virtual void StoreFocus() override;
+ virtual void RestoreFocus() override;
+ virtual DropData* GetDropData() const override;
+ virtual gfx::Rect GetViewBounds() const override;
virtual void CreateView(
- const gfx::Size& initial_size, gfx::NativeView context) OVERRIDE;
+ const gfx::Size& initial_size, gfx::NativeView context) override;
virtual RenderWidgetHostViewBase* CreateViewForWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
+ RenderWidgetHost* render_widget_host, bool is_guest_view_hack) override;
virtual RenderWidgetHostViewBase* CreateViewForPopupWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const base::string16& title) OVERRIDE;
- virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
- virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
- virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
+ RenderWidgetHost* render_widget_host) override;
+ virtual void SetPageTitle(const base::string16& title) override;
+ virtual void RenderViewCreated(RenderViewHost* host) override;
+ virtual void RenderViewSwappedIn(RenderViewHost* host) override;
+ virtual void SetOverscrollControllerEnabled(bool enabled) override;
// Backend implementation of RenderViewHostDelegateView.
virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
- const ContextMenuParams& params) OVERRIDE;
- virtual void ShowPopupMenu(const gfx::Rect& bounds,
+ const ContextMenuParams& params) override;
+ virtual void ShowPopupMenu(RenderFrameHost* render_frame_host,
+ const gfx::Rect& bounds,
int item_height,
double item_font_size,
int selected_item,
const std::vector<MenuItem>& items,
bool right_aligned,
- bool allow_multiple_selection) OVERRIDE;
- virtual void HidePopupMenu() OVERRIDE;
+ bool allow_multiple_selection) override;
+ virtual void HidePopupMenu() override;
virtual void StartDragging(const DropData& drop_data,
blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
- virtual void GotFocus() OVERRIDE;
- virtual void TakeFocus(bool reverse) OVERRIDE;
+ const DragEventSourceInfo& event_info) override;
+ virtual void UpdateDragCursor(blink::WebDragOperation operation) override;
+ virtual void GotFocus() override;
+ virtual void TakeFocus(bool reverse) override;
private:
// The WebContents whose contents we display.
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.cc b/chromium/content/browser/web_contents/web_contents_view_aura.cc
index db7b056258f..056bb3e3cc3 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -6,7 +6,7 @@
#include "base/auto_reset.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/browser_plugin/browser_plugin_guest.h"
@@ -19,6 +19,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#include "content/browser/renderer_host/web_input_event_aura.h"
#include "content/browser/web_contents/aura/gesture_nav_simple.h"
#include "content/browser/web_contents/aura/image_window_delegate.h"
#include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
@@ -66,10 +67,17 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/screen.h"
#include "ui/wm/public/drag_drop_client.h"
#include "ui/wm/public/drag_drop_delegate.h"
+#if defined(OS_WIN)
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/accessibility/browser_accessibility_win.h"
+#include "ui/base/win/hidden_window.h"
+#endif
+
namespace content {
WebContentsView* CreateWebContentsView(
WebContentsImpl* web_contents,
@@ -83,7 +91,7 @@ WebContentsView* CreateWebContentsView(
namespace {
bool IsScrollEndEffectEnabled() {
- return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kScrollEndEffect) == "1";
}
@@ -99,17 +107,6 @@ bool ShouldNavigateBack(const NavigationController& controller,
controller.CanGoBack();
}
-// Update the |web contents| to be |visible|.
-void UpdateWebContentsVisibility(WebContentsImpl* web_contents, bool visible) {
- if (visible) {
- if (!web_contents->should_normally_be_visible())
- web_contents->WasShown();
- } else {
- if (web_contents->should_normally_be_visible())
- web_contents->WasHidden();
- }
-}
-
RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
RenderWidgetHostView* view) {
if (!view || RenderViewHostFactory::has_factory())
@@ -145,8 +142,7 @@ class OverscrollWindowDelegate : public ImageWindowDelegate {
gfx::Image image;
if (entry && entry->screenshot().get()) {
std::vector<gfx::ImagePNGRep> image_reps;
- image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(),
- ui::GetScaleFactorForNativeView(web_contents_window())));
+ image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
image = gfx::Image(image_reps);
}
SetImage(image);
@@ -155,19 +151,19 @@ class OverscrollWindowDelegate : public ImageWindowDelegate {
void stop_forwarding_events() { forward_events_ = false; }
private:
- virtual ~OverscrollWindowDelegate() {}
+ ~OverscrollWindowDelegate() override {}
aura::Window* web_contents_window() {
return web_contents_->GetView()->GetContentNativeView();
}
// Overridden from ui::EventHandler.
- virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
+ void OnScrollEvent(ui::ScrollEvent* event) override {
if (forward_events_ && web_contents_window())
web_contents_window()->delegate()->OnScrollEvent(event);
}
- virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
+ void OnGestureEvent(ui::GestureEvent* event) override {
if (forward_events_ && web_contents_window())
web_contents_window()->delegate()->OnGestureEvent(event);
}
@@ -197,13 +193,12 @@ class WebDragSourceAura : public NotificationObserver {
Source<WebContents>(contents));
}
- virtual ~WebDragSourceAura() {
- }
+ ~WebDragSourceAura() override {}
// NotificationObserver:
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE {
+ void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) override {
if (type != NOTIFICATION_WEB_CONTENTS_DISCONNECTED)
return;
@@ -320,7 +315,7 @@ const ui::OSExchangeData::CustomFormat& GetFileSystemFileCustomFormat() {
void WriteFileSystemFilesToPickle(
const std::vector<DropData::FileSystemFileInfo>& file_system_files,
Pickle* pickle) {
- pickle->WriteUInt64(file_system_files.size());
+ pickle->WriteSizeT(file_system_files.size());
for (size_t i = 0; i < file_system_files.size(); ++i) {
pickle->WriteString(file_system_files[i].url.spec());
pickle->WriteInt64(file_system_files[i].size);
@@ -333,12 +328,12 @@ bool ReadFileSystemFilesFromPickle(
std::vector<DropData::FileSystemFileInfo>* file_system_files) {
PickleIterator iter(pickle);
- uint64 num_files = 0;
- if (!pickle.ReadUInt64(&iter, &num_files))
+ size_t num_files = 0;
+ if (!pickle.ReadSizeT(&iter, &num_files))
return false;
file_system_files->resize(num_files);
- for (uint64 i = 0; i < num_files; ++i) {
+ for (size_t i = 0; i < num_files; ++i) {
std::string url_string;
int64 size = 0;
if (!pickle.ReadString(&iter, &url_string) ||
@@ -373,6 +368,10 @@ void PrepareDragData(const DropData& drop_data,
if (!drop_data.file_contents.empty())
PrepareDragForFileContents(drop_data, provider);
#endif
+ // Call SetString() before SetURL() when we actually have a custom string.
+ // SetURL() will itself do SetString() when a string hasn't been set yet,
+ // but we want to prefer drop_data.text.string() over the URL string if it
+ // exists.
if (!drop_data.text.string().empty())
provider->SetString(drop_data.text.string());
if (drop_data.url.is_valid())
@@ -477,7 +476,7 @@ class WebContentsViewAura::WindowObserver
public:
explicit WindowObserver(WebContentsViewAura* view)
: view_(view),
- parent_(NULL) {
+ host_window_(NULL) {
view_->window_->AddObserver(this);
#if defined(OS_WIN)
@@ -486,16 +485,15 @@ class WebContentsViewAura::WindowObserver
#endif
}
- virtual ~WindowObserver() {
+ ~WindowObserver() override {
view_->window_->RemoveObserver(this);
if (view_->window_->GetHost())
view_->window_->GetHost()->RemoveObserver(this);
- if (parent_)
- parent_->RemoveObserver(this);
-
+ if (host_window_)
+ host_window_->RemoveObserver(this);
#if defined(OS_WIN)
- if (parent_) {
- const aura::Window::Windows& children = parent_->children();
+ if (host_window_) {
+ const aura::Window::Windows& children = host_window_->children();
for (size_t i = 0; i < children.size(); ++i)
children[i]->RemoveObserver(this);
}
@@ -511,6 +509,20 @@ class WebContentsViewAura::WindowObserver
}
// Overridden from aura::WindowObserver:
+ void OnWindowHierarchyChanged(
+ const aura::WindowObserver::HierarchyChangeParams& params) override {
+ if (params.receiver != view_->window_.get() ||
+ !params.target->Contains(view_->window_.get())) {
+ return;
+ }
+
+ // Use the new parent's root window for calculating HiDPI subpixel offset.
+ RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
+ view_->web_contents_->GetRenderWidgetHostView());
+ if (rwhv)
+ rwhv->SnapToPhysicalPixelBoundary();
+ }
+
#if defined(OS_WIN)
// Constrained windows are added as children of the parent's parent's view
// which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
@@ -518,25 +530,25 @@ class WebContentsViewAura::WindowObserver
// Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
// going to be deprecated in a year, this is ok for now. The test for this is
// PrintPreviewTest.WindowedNPAPIPluginHidden.
- virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
- if (new_window != view_->window_) {
+ virtual void OnWindowAdded(aura::Window* new_window) override {
+ if (!new_window->Contains(view_->window_.get())) {
// Skip the case when the parent moves to the root window.
- if (new_window != parent_) {
+ if (new_window != host_window_) {
// Observe sibling windows of the WebContents, or children of the root
// window.
- if (new_window->parent() == parent_ ||
+ if (new_window->parent() == host_window_ ||
new_window->parent() == view_->window_->GetRootWindow()) {
new_window->AddObserver(this);
}
}
}
- if (new_window->parent() == parent_) {
+ if (new_window->parent() == host_window_) {
UpdateConstrainedWindows(NULL);
}
}
- virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
+ virtual void OnWillRemoveWindow(aura::Window* window) override {
if (window == view_->window_)
return;
@@ -545,58 +557,63 @@ class WebContentsViewAura::WindowObserver
}
virtual void OnWindowVisibilityChanged(aura::Window* window,
- bool visible) OVERRIDE {
+ bool visible) override {
if (window == view_->window_ ||
- window->parent() == parent_ ||
+ window->parent() == host_window_ ||
window->parent() == view_->window_->GetRootWindow()) {
UpdateConstrainedWindows(NULL);
}
}
#endif
- virtual void OnWindowParentChanged(aura::Window* window,
- aura::Window* parent) OVERRIDE {
+ void OnWindowParentChanged(aura::Window* window,
+ aura::Window* parent) override {
if (window != view_->window_)
return;
- if (parent_)
- parent_->RemoveObserver(this);
+
+ aura::Window* host_window =
+ window->GetProperty(aura::client::kHostWindowKey);
+ if (!host_window)
+ host_window = parent;
+
+ if (host_window_)
+ host_window_->RemoveObserver(this);
#if defined(OS_WIN)
- if (parent_) {
- const aura::Window::Windows& children = parent_->children();
+ if (host_window_) {
+ const aura::Window::Windows& children = host_window_->children();
for (size_t i = 0; i < children.size(); ++i)
children[i]->RemoveObserver(this);
-
- RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
+ RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
view_->web_contents_->GetRenderWidgetHostView());
- if (view)
- view->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
+ if (rwhv)
+ rwhv->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
}
// When we get parented to the root window, the code below will watch the
- // parent, aka root window. Since we already watch the root window on
+ // host window, aka root window. Since we already watch the root window on
// Windows, unregister first so that the debug check doesn't fire.
- if (parent && parent == window->GetRootWindow())
- parent->RemoveObserver(this);
+ if (host_window && host_window == window->GetRootWindow())
+ host_window->RemoveObserver(this);
// We need to undo the above if we were parented to the root window and then
// got parented to another window. At that point, the code before the ifdef
// would have stopped watching the root window.
if (window->GetRootWindow() &&
- parent != window->GetRootWindow() &&
+ host_window != window->GetRootWindow() &&
!window->GetRootWindow()->HasObserver(this)) {
window->GetRootWindow()->AddObserver(this);
}
#endif
- parent_ = parent;
- if (parent) {
- parent->AddObserver(this);
+ host_window_ = host_window;
+ if (host_window) {
+ host_window->AddObserver(this);
#if defined(OS_WIN)
- if (parent != window->GetRootWindow()) {
- const aura::Window::Windows& children = parent->children();
+ if (host_window != window->GetRootWindow()) {
+ const aura::Window::Windows& children = host_window->children();
for (size_t i = 0; i < children.size(); ++i) {
- if (children[i] != view_->window_)
+ if (!children[i]->Contains(view_->window_.get()))
children[i]->AddObserver(this);
}
}
@@ -604,10 +621,10 @@ class WebContentsViewAura::WindowObserver
}
}
- virtual void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE {
- if (window == parent_ || window == view_->window_) {
+ void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override {
+ if (window == host_window_ || window == view_->window_) {
SendScreenRects();
if (view_->touch_editable_)
view_->touch_editable_->UpdateEditingController();
@@ -618,18 +635,29 @@ class WebContentsViewAura::WindowObserver
}
}
- virtual void OnWindowAddedToRootWindow(aura::Window* window) OVERRIDE {
+ void OnWindowDestroying(aura::Window* window) override {
+ if (window == host_window_) {
+ host_window_->RemoveObserver(this);
+ host_window_ = NULL;
+ }
+ }
+
+ void OnWindowAddedToRootWindow(aura::Window* window) override {
if (window == view_->window_) {
window->GetHost()->AddObserver(this);
#if defined(OS_WIN)
if (!window->GetRootWindow()->HasObserver(this))
window->GetRootWindow()->AddObserver(this);
+ if (view_->legacy_hwnd_) {
+ view_->legacy_hwnd_->UpdateParent(
+ window->GetHost()->GetAcceleratedWidget());
+ }
#endif
}
}
- virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
- aura::Window* new_root) OVERRIDE {
+ void OnWindowRemovingFromRootWindow(aura::Window* window,
+ aura::Window* new_root) override {
if (window == view_->window_) {
window->GetHost()->RemoveObserver(this);
#if defined(OS_WIN)
@@ -638,16 +666,21 @@ class WebContentsViewAura::WindowObserver
const aura::Window::Windows& root_children =
window->GetRootWindow()->children();
for (size_t i = 0; i < root_children.size(); ++i) {
- if (root_children[i] != view_->window_ && root_children[i] != parent_)
+ if (root_children[i] != view_->window_ &&
+ root_children[i] != host_window_) {
root_children[i]->RemoveObserver(this);
+ }
}
+
+ if (view_->legacy_hwnd_)
+ view_->legacy_hwnd_->UpdateParent(ui::GetHiddenWindow());
#endif
}
}
// Overridden WindowTreeHostObserver:
- virtual void OnHostMoved(const aura::WindowTreeHost* host,
- const gfx::Point& new_origin) OVERRIDE {
+ void OnHostMoved(const aura::WindowTreeHost* host,
+ const gfx::Point& new_origin) override {
TRACE_EVENT1("ui",
"WebContentsViewAura::WindowObserver::OnHostMoved",
"new_origin", new_origin.ToString());
@@ -670,10 +703,10 @@ class WebContentsViewAura::WindowObserver
return;
std::vector<gfx::Rect> constrained_windows;
- if (parent_) {
- const aura::Window::Windows& children = parent_->children();
+ if (host_window_) {
+ const aura::Window::Windows& children = host_window_->children();
for (size_t i = 0; i < children.size(); ++i) {
- if (children[i] != view_->window_ &&
+ if (!children[i]->Contains(view_->window_.get()) &&
children[i] != exclude &&
children[i]->IsVisible()) {
constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
@@ -699,9 +732,9 @@ class WebContentsViewAura::WindowObserver
WebContentsViewAura* view_;
- // We cache the old parent so that we can unregister when it's not the parent
- // anymore.
- aura::Window* parent_;
+ // The parent window that hosts the constrained windows. We cache the old host
+ // view so that we can unregister when it's not the parent anymore.
+ aura::Window* host_window_;
DISALLOW_COPY_AND_ASSIGN(WindowObserver);
};
@@ -720,7 +753,8 @@ WebContentsViewAura::WebContentsViewAura(
overscroll_change_brightness_(false),
current_overscroll_gesture_(OVERSCROLL_NONE),
completed_overscroll_gesture_(OVERSCROLL_NONE),
- touch_editable_(TouchEditableImplAura::Create()) {
+ touch_editable_(TouchEditableImplAura::Create()),
+ is_or_was_visible_(false) {
}
////////////////////////////////////////////////////////////////////////////////
@@ -769,7 +803,7 @@ void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
void WebContentsViewAura::InstallOverscrollControllerDelegate(
RenderWidgetHostViewAura* view) {
- const std::string value = CommandLine::ForCurrentProcess()->
+ const std::string value = base::CommandLine::ForCurrentProcess()->
GetSwitchValueASCII(switches::kOverscrollHistoryNavigation);
if (value == "0") {
navigation_overlay_.reset();
@@ -790,7 +824,7 @@ void WebContentsViewAura::InstallOverscrollControllerDelegate(
void WebContentsViewAura::PrepareOverscrollWindow() {
// If there is an existing |overscroll_window_| which is in the middle of an
// animation, then destroying the window here causes the animation to be
- // completed immidiately, which triggers |OnImplicitAnimationsCompleted()|
+ // completed immediately, which triggers |OnImplicitAnimationsCompleted()|
// callback, and that tries to reset |overscroll_window_| again, causing a
// double-free. So use a temporary variable here.
if (overscroll_window_) {
@@ -891,7 +925,8 @@ void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
gfx::Transform transform;
int content_width =
web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
- int translate_x = mode == OVERSCROLL_WEST ? -content_width : content_width;
+ float translate_x = static_cast<float>(mode == OVERSCROLL_WEST ?
+ -content_width : content_width);
transform.Translate(translate_x, 0);
target->SetTransform(transform);
UpdateOverscrollWindowBrightness(translate_x);
@@ -906,21 +941,22 @@ aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
overscroll_window_.get() : GetContentNativeView();
}
-gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
- int delta_y) {
+gfx::Vector2dF WebContentsViewAura::GetTranslationForOverscroll(float delta_x,
+ float delta_y) {
if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
- return gfx::Vector2d(0, delta_y);
+ return gfx::Vector2dF(0, delta_y);
}
// For horizontal overscroll, scroll freely if a navigation is possible. Do a
// resistive scroll otherwise.
const NavigationControllerImpl& controller = web_contents_->GetController();
const gfx::Rect& bounds = GetViewBounds();
+ const float bounds_width = static_cast<float>(bounds.width());
if (ShouldNavigateForward(controller, current_overscroll_gesture_))
- return gfx::Vector2d(std::max(-bounds.width(), delta_x), 0);
+ return gfx::Vector2dF(std::max(-bounds_width, delta_x), 0);
else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
- return gfx::Vector2d(std::min(bounds.width(), delta_x), 0);
- return gfx::Vector2d();
+ return gfx::Vector2dF(std::min(bounds_width, delta_x), 0);
+ return gfx::Vector2dF();
}
void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
@@ -963,7 +999,8 @@ void WebContentsViewAura::AttachTouchEditableToRenderView() {
touch_editable_->AttachToView(rwhva);
}
-void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(int delta_y) {
+void WebContentsViewAura::OverscrollUpdateForWebContentsDelegate(
+ float delta_y) {
if (web_contents_->GetDelegate() && IsScrollEndEffectEnabled())
web_contents_->GetDelegate()->OverscrollUpdate(delta_y);
}
@@ -993,6 +1030,10 @@ void WebContentsViewAura::SizeContents(const gfx::Size& size) {
if (bounds.size() != size) {
bounds.set_size(size);
window_->SetBounds(bounds);
+#if defined(OS_WIN)
+ if (legacy_hwnd_)
+ legacy_hwnd_->SetBounds(window_->GetBoundsInRootWindow());
+#endif
} else {
// Our size matches what we want but the renderers size may not match.
// Pretend we were resized so that the renderers size is updated too.
@@ -1009,7 +1050,10 @@ void WebContentsViewAura::Focus() {
if (delegate_.get() && delegate_->Focus())
return;
- RenderWidgetHostView* rwhv = web_contents_->GetRenderWidgetHostView();
+ RenderWidgetHostView* rwhv =
+ web_contents_->GetFullscreenRenderWidgetHostView();
+ if (!rwhv)
+ rwhv = web_contents_->GetRenderWidgetHostView();
if (rwhv)
rwhv->Focus();
}
@@ -1086,10 +1130,18 @@ void WebContentsViewAura::CreateView(
// platforms as well.
if (delegate_)
drag_dest_delegate_ = delegate_->GetDragDestDelegate();
+
+#if defined(OS_WIN)
+ if (context && context->GetHost()) {
+ HWND parent_hwnd = context->GetHost()->GetAcceleratedWidget();
+ CHECK(parent_hwnd);
+ legacy_hwnd_.reset(LegacyRenderWidgetHostHWND::Create(parent_hwnd, this));
+ }
+#endif
}
RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
- RenderWidgetHost* render_widget_host) {
+ RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
if (render_widget_host->GetView()) {
// During testing, the view will already be set up in most cases to the
// test view, so we don't want to clobber it with a real one. To verify that
@@ -1102,7 +1154,7 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
}
RenderWidgetHostViewAura* view =
- new RenderWidgetHostViewAura(render_widget_host);
+ new RenderWidgetHostViewAura(render_widget_host, is_guest_view_hack);
view->InitAsChild(NULL);
GetNativeView()->AddChild(view->GetNativeView());
@@ -1126,16 +1178,28 @@ RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForWidget(
}
AttachTouchEditableToRenderView();
+
+#if defined(OS_WIN)
+ if (legacy_hwnd_)
+ view->SetLegacyRenderWidgetHostHWND(legacy_hwnd_.get());
+#endif
+
return view;
}
RenderWidgetHostViewBase* WebContentsViewAura::CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) {
- return new RenderWidgetHostViewAura(render_widget_host);
+ RenderWidgetHostViewAura* view =
+ new RenderWidgetHostViewAura(render_widget_host, false);
+#if defined(OS_WIN)
+ if (legacy_hwnd_)
+ view->SetLegacyRenderWidgetHostHWND(legacy_hwnd_.get());
+#endif
+ return view;
}
void WebContentsViewAura::SetPageTitle(const base::string16& title) {
- window_->set_title(title);
+ window_->SetTitle(title);
}
void WebContentsViewAura::RenderViewCreated(RenderViewHost* host) {
@@ -1249,6 +1313,22 @@ void WebContentsViewAura::TakeFocus(bool reverse) {
}
}
+void WebContentsViewAura::ShowDisambiguationPopup(
+ const gfx::Rect& target_rect,
+ const SkBitmap& zoomed_bitmap,
+ const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
+ const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
+ if (delegate_) {
+ delegate_->ShowDisambiguationPopup(target_rect, zoomed_bitmap,
+ window_.get(), gesture_cb, mouse_cb);
+ }
+}
+
+void WebContentsViewAura::HideDisambiguationPopup() {
+ if (delegate_)
+ delegate_->HideDisambiguationPopup();
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, OverscrollControllerDelegate implementation:
@@ -1260,28 +1340,34 @@ gfx::Rect WebContentsViewAura::GetVisibleBounds() const {
return rwhv->GetViewBounds();
}
-void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
+bool WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
if (current_overscroll_gesture_ == OVERSCROLL_NONE)
- return;
+ return false;
aura::Window* target = GetWindowToAnimateForOverscroll();
- gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y);
+ gfx::Vector2dF translate = GetTranslationForOverscroll(delta_x, delta_y);
gfx::Transform transform;
- // Vertical overscrolls don't participate in the navigation gesture.
- if (current_overscroll_gesture_ != OVERSCROLL_NORTH &&
- current_overscroll_gesture_ != OVERSCROLL_SOUTH) {
+ if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
+ current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
+ OverscrollUpdateForWebContentsDelegate(translate.y());
+ } else {
+ // Only horizontal overscrolls participate in the navigation gesture.
transform.Translate(translate.x(), translate.y());
target->SetTransform(transform);
UpdateOverscrollWindowBrightness(delta_x);
}
- OverscrollUpdateForWebContentsDelegate(translate.y());
+ return !translate.IsZero();
}
void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
UMA_HISTOGRAM_ENUMERATION("Overscroll.Completed", mode, OVERSCROLL_COUNT);
- OverscrollUpdateForWebContentsDelegate(0);
+ if (web_contents_->GetDelegate() &&
+ IsScrollEndEffectEnabled() &&
+ (mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
+ web_contents_->GetDelegate()->OverscrollComplete();
+ }
NavigationControllerImpl& controller = web_contents_->GetController();
if (ShouldNavigateForward(controller, mode) ||
ShouldNavigateBack(controller, mode)) {
@@ -1297,6 +1383,9 @@ void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
// Reset any in-progress overscroll animation first.
ResetOverscrollTransform();
+ if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
+ OverscrollUpdateForWebContentsDelegate(0);
+
if (new_mode != OVERSCROLL_NONE && touch_editable_)
touch_editable_->OverscrollStarted();
@@ -1305,7 +1394,6 @@ void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
navigation_overlay_.get() && navigation_overlay_->has_window())) {
current_overscroll_gesture_ = OVERSCROLL_NONE;
- OverscrollUpdateForWebContentsDelegate(0);
} else {
aura::Window* target = GetWindowToAnimateForOverscroll();
if (target) {
@@ -1481,9 +1569,9 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
// Give the delegate an opportunity to cancel the drag.
- if (!web_contents_->GetDelegate()->CanDragEnter(web_contents_,
- *current_drop_data_.get(),
- op)) {
+ if (web_contents_->GetDelegate() &&
+ !web_contents_->GetDelegate()->CanDragEnter(
+ web_contents_, *current_drop_data_.get(), op)) {
current_drop_data_.reset(NULL);
return;
}
@@ -1557,22 +1645,65 @@ int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
return ConvertFromWeb(current_drag_op_);
}
-void WebContentsViewAura::OnWindowParentChanged(aura::Window* window,
- aura::Window* parent) {
- // On Windows we will get called with a parent of NULL as part of the shut
- // down process. As such we do only change the visibility when a parent gets
- // set.
- if (parent)
- UpdateWebContentsVisibility(web_contents_, window->IsVisible());
-}
-
void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
bool visible) {
// Ignore any visibility changes in the hierarchy below.
if (window != window_.get() && window_->Contains(window))
return;
- UpdateWebContentsVisibility(web_contents_, visible);
+ UpdateWebContentsVisibility(visible);
}
+void WebContentsViewAura::UpdateWebContentsVisibility(bool visible) {
+ if (!is_or_was_visible_) {
+ // We should not hide the web contents before it was shown the first time,
+ // since resources would immediately be destroyed and only re-created after
+ // content got loaded. In this state the window content is undefined and can
+ // show garbage.
+ // However - the page load mechanism requires an activation call through a
+ // visibility call to (re)load.
+ if (visible) {
+ is_or_was_visible_ = true;
+ web_contents_->WasShown();
+ }
+ return;
+ }
+ if (visible) {
+ if (!web_contents_->should_normally_be_visible())
+ web_contents_->WasShown();
+ } else {
+ if (web_contents_->should_normally_be_visible())
+ web_contents_->WasHidden();
+ }
+
+#if defined(OS_WIN)
+ if (!legacy_hwnd_)
+ return;
+
+ if (visible && GetNativeView() && GetNativeView()->GetHost()) {
+ legacy_hwnd_->UpdateParent(
+ GetNativeView()->GetHost()->GetAcceleratedWidget());
+ legacy_hwnd_->SetBounds(window_->GetBoundsInRootWindow());
+ legacy_hwnd_->Show();
+ } else {
+ // We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
+ // hidden window on the same lines as Windowed plugin windows.
+ legacy_hwnd_->UpdateParent(ui::GetHiddenWindow());
+ legacy_hwnd_->Hide();
+ }
+#endif
+}
+
+#if defined(OS_WIN)
+gfx::NativeViewAccessible
+WebContentsViewAura::GetNativeViewAccessible() {
+ BrowserAccessibilityManager* manager =
+ web_contents_->GetRootBrowserAccessibilityManager();
+ if (!manager)
+ return nullptr;
+
+ return manager->GetRoot()->ToBrowserAccessibilityWin();
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.h b/chromium/content/browser/web_contents/web_contents_view_aura.h
index 71a425a18f8..cf5177662ae 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -18,6 +18,11 @@
#include "ui/compositor/layer_animation_observer.h"
#include "ui/wm/public/drag_drop_delegate.h"
+#if defined(OS_WIN)
+#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
+#include "content/browser/renderer_host/legacy_render_widget_host_win_delegate.h"
+#endif
+
namespace aura {
class Window;
}
@@ -37,8 +42,15 @@ class WebContentsViewDelegate;
class WebContentsImpl;
class WebDragDestDelegate;
+#if defined(OS_WIN)
+class LegacyRenderWidgetHostHWND;
+#endif
+
class WebContentsViewAura
: public WebContentsView,
+#if defined(OS_WIN)
+ public LegacyRenderWidgetHostHWNDDelegate,
+#endif
public RenderViewHostDelegateView,
public OverscrollControllerDelegate,
public ui::ImplicitAnimationObserver,
@@ -55,7 +67,7 @@ class WebContentsViewAura
private:
class WindowObserver;
- virtual ~WebContentsViewAura();
+ ~WebContentsViewAura() override;
void SizeChangedCommon(const gfx::Size& size);
@@ -88,7 +100,7 @@ class WebContentsViewAura
// Returns the amount the animating window should be translated in response to
// the overscroll gesture.
- gfx::Vector2d GetTranslationForOverscroll(int delta_x, int delta_y);
+ gfx::Vector2dF GetTranslationForOverscroll(float delta_x, float delta_y);
// A window showing the screenshot is overlayed during a navigation triggered
// by overscroll. This function sets this up.
@@ -100,88 +112,100 @@ class WebContentsViewAura
void AttachTouchEditableToRenderView();
- void OverscrollUpdateForWebContentsDelegate(int delta_y);
+ void OverscrollUpdateForWebContentsDelegate(float delta_y);
// Overridden from WebContentsView:
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeView GetContentNativeView() const OVERRIDE;
- virtual gfx::NativeWindow GetTopLevelNativeWindow() const OVERRIDE;
- virtual void GetContainerBounds(gfx::Rect *out) const OVERRIDE;
- virtual void SizeContents(const gfx::Size& size) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void SetInitialFocus() OVERRIDE;
- virtual void StoreFocus() OVERRIDE;
- virtual void RestoreFocus() OVERRIDE;
- virtual DropData* GetDropData() const OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual void CreateView(
- const gfx::Size& initial_size, gfx::NativeView context) OVERRIDE;
- virtual RenderWidgetHostViewBase* CreateViewForWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual RenderWidgetHostViewBase* CreateViewForPopupWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const base::string16& title) OVERRIDE;
- virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
- virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
- virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeView GetContentNativeView() const override;
+ gfx::NativeWindow GetTopLevelNativeWindow() const override;
+ void GetContainerBounds(gfx::Rect* out) const override;
+ void SizeContents(const gfx::Size& size) override;
+ void Focus() override;
+ void SetInitialFocus() override;
+ void StoreFocus() override;
+ void RestoreFocus() override;
+ DropData* GetDropData() const override;
+ gfx::Rect GetViewBounds() const override;
+ void CreateView(const gfx::Size& initial_size,
+ gfx::NativeView context) override;
+ RenderWidgetHostViewBase* CreateViewForWidget(
+ RenderWidgetHost* render_widget_host,
+ bool is_guest_view_hack) override;
+ RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHost* render_widget_host) override;
+ void SetPageTitle(const base::string16& title) override;
+ void RenderViewCreated(RenderViewHost* host) override;
+ void RenderViewSwappedIn(RenderViewHost* host) override;
+ void SetOverscrollControllerEnabled(bool enabled) override;
// Overridden from RenderViewHostDelegateView:
- virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
- const ContextMenuParams& params) OVERRIDE;
- virtual void StartDragging(const DropData& drop_data,
- blink::WebDragOperationsMask operations,
- const gfx::ImageSkia& image,
- const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
- virtual void GotFocus() OVERRIDE;
- virtual void TakeFocus(bool reverse) OVERRIDE;
+ void ShowContextMenu(RenderFrameHost* render_frame_host,
+ const ContextMenuParams& params) override;
+ void StartDragging(const DropData& drop_data,
+ blink::WebDragOperationsMask operations,
+ const gfx::ImageSkia& image,
+ const gfx::Vector2d& image_offset,
+ const DragEventSourceInfo& event_info) override;
+ void UpdateDragCursor(blink::WebDragOperation operation) override;
+ void GotFocus() override;
+ void TakeFocus(bool reverse) override;
+ void ShowDisambiguationPopup(
+ const gfx::Rect& target_rect,
+ const SkBitmap& zoomed_bitmap,
+ const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
+ const base::Callback<void(ui::MouseEvent*)>& mouse_cb) override;
+ void HideDisambiguationPopup() override;
// Overridden from OverscrollControllerDelegate:
- virtual gfx::Rect GetVisibleBounds() const OVERRIDE;
- virtual void OnOverscrollUpdate(float delta_x, float delta_y) OVERRIDE;
- virtual void OnOverscrollComplete(OverscrollMode overscroll_mode) OVERRIDE;
- virtual void OnOverscrollModeChange(OverscrollMode old_mode,
- OverscrollMode new_mode) OVERRIDE;
+ gfx::Rect GetVisibleBounds() const override;
+ bool OnOverscrollUpdate(float delta_x, float delta_y) override;
+ void OnOverscrollComplete(OverscrollMode overscroll_mode) override;
+ void OnOverscrollModeChange(OverscrollMode old_mode,
+ OverscrollMode new_mode) override;
// Overridden from ui::ImplicitAnimationObserver:
- virtual void OnImplicitAnimationsCompleted() OVERRIDE;
+ void OnImplicitAnimationsCompleted() override;
// Overridden from aura::WindowDelegate:
- virtual gfx::Size GetMinimumSize() const OVERRIDE;
- virtual gfx::Size GetMaximumSize() const OVERRIDE;
- virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) OVERRIDE;
- virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE;
- virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE;
- virtual bool ShouldDescendIntoChildForEventHandling(
+ gfx::Size GetMinimumSize() const override;
+ gfx::Size GetMaximumSize() const override;
+ void OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
+ gfx::NativeCursor GetCursor(const gfx::Point& point) override;
+ int GetNonClientComponent(const gfx::Point& point) const override;
+ bool ShouldDescendIntoChildForEventHandling(
aura::Window* child,
- const gfx::Point& location) OVERRIDE;
- virtual bool CanFocus() OVERRIDE;
- virtual void OnCaptureLost() OVERRIDE;
- virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
- virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
- virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE;
- virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
- virtual bool HasHitTestMask() const OVERRIDE;
- virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
+ const gfx::Point& location) override;
+ bool CanFocus() override;
+ void OnCaptureLost() override;
+ void OnPaint(gfx::Canvas* canvas) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+ void OnWindowDestroying(aura::Window* window) override;
+ void OnWindowDestroyed(aura::Window* window) override;
+ void OnWindowTargetVisibilityChanged(bool visible) override;
+ bool HasHitTestMask() const override;
+ void GetHitTestMask(gfx::Path* mask) const override;
// Overridden from ui::EventHandler:
- virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
- virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
+ void OnKeyEvent(ui::KeyEvent* event) override;
+ void OnMouseEvent(ui::MouseEvent* event) override;
// Overridden from aura::client::DragDropDelegate:
- virtual void OnDragEntered(const ui::DropTargetEvent& event) OVERRIDE;
- virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
- virtual void OnDragExited() OVERRIDE;
- virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
+ void OnDragEntered(const ui::DropTargetEvent& event) override;
+ int OnDragUpdated(const ui::DropTargetEvent& event) override;
+ void OnDragExited() override;
+ int OnPerformDrop(const ui::DropTargetEvent& event) override;
// Overridden from aura::WindowObserver:
- virtual void OnWindowParentChanged(aura::Window* window,
- aura::Window* parent) OVERRIDE;
- virtual void OnWindowVisibilityChanged(aura::Window* window,
- bool visible) OVERRIDE;
+ void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
+
+ // Update the web contents visiblity.
+ void UpdateWebContentsVisibility(bool visible);
+
+#if defined(OS_WIN)
+ // Overridden from LegacyRenderWidgetHostHWNDDelegate:
+ virtual gfx::NativeViewAccessible GetNativeViewAccessible() override;
+#endif
scoped_ptr<aura::Window> window_;
@@ -226,6 +250,18 @@ class WebContentsViewAura
scoped_ptr<TouchEditableImplAura> touch_editable_;
scoped_ptr<GestureNavSimple> gesture_nav_simple_;
+#if defined(OS_WIN)
+ // The LegacyRenderWidgetHostHWND class provides a dummy HWND which is used
+ // for accessibility, as the container for windowless plugins like
+ // Flash/Silverlight, etc and for legacy drivers for trackpoints/trackpads,
+ // etc.
+ scoped_ptr<LegacyRenderWidgetHostHWND> legacy_hwnd_;
+#endif
+
+ // On Windows we can run into problems if resources get released within the
+ // initialization phase while the content (and its dimensions) are not known.
+ bool is_or_was_visible_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
};
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 41dab4c5c18..2687376c109 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -15,10 +15,15 @@
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -27,12 +32,61 @@
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
-#include "ui/aura/test/event_generator.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/event_processor.h"
+#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
+#include "ui/events/test/event_generator.h"
+
+namespace {
+
+// TODO(tdresser): Find a way to avoid sleeping like this. See crbug.com/405282
+// for details.
+void GiveItSomeTime() {
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromMillisecondsD(10));
+ run_loop.Run();
+}
+
+// WebContentsDelegate which tracks vertical overscroll updates.
+class VerticalOverscrollTracker : public content::WebContentsDelegate {
+ public:
+ VerticalOverscrollTracker() : count_(0), completed_(false) {}
+ ~VerticalOverscrollTracker() override {}
+
+ int num_overscroll_updates() const {
+ return count_;
+ }
+
+ bool overscroll_completed() const {
+ return completed_;
+ }
+
+ void Reset() {
+ count_ = 0;
+ completed_ = false;
+ }
+
+ private:
+ bool CanOverscrollContent() const override { return true; }
+
+ void OverscrollUpdate(float delta_y) override { ++count_; }
+
+ void OverscrollComplete() override { completed_ = true; }
+
+ int count_;
+ bool completed_;
+
+ DISALLOW_COPY_AND_ASSIGN(VerticalOverscrollTracker);
+};
+
+} //namespace
+
namespace content {
@@ -45,8 +99,7 @@ class ScreenshotTracker : public NavigationEntryScreenshotManager {
waiting_for_screenshots_(0) {
}
- virtual ~ScreenshotTracker() {
- }
+ ~ScreenshotTracker() override {}
RenderViewHost* screenshot_taken_for() { return screenshot_taken_for_; }
@@ -72,14 +125,14 @@ class ScreenshotTracker : public NavigationEntryScreenshotManager {
private:
// Overridden from NavigationEntryScreenshotManager:
- virtual void TakeScreenshotImpl(RenderViewHost* host,
- NavigationEntryImpl* entry) OVERRIDE {
+ void TakeScreenshotImpl(RenderViewHost* host,
+ NavigationEntryImpl* entry) override {
++waiting_for_screenshots_;
screenshot_taken_for_ = host;
NavigationEntryScreenshotManager::TakeScreenshotImpl(host, entry);
}
- virtual void OnScreenshotSet(NavigationEntryImpl* entry) OVERRIDE {
+ void OnScreenshotSet(NavigationEntryImpl* entry) override {
--waiting_for_screenshots_;
screenshot_set_[entry] = true;
NavigationEntryScreenshotManager::OnScreenshotSet(entry);
@@ -103,7 +156,7 @@ class NavigationWatcher : public WebContentsObserver {
should_quit_loop_(false) {
}
- virtual ~NavigationWatcher() {}
+ ~NavigationWatcher() override {}
void WaitUntilNavigationStarts() {
if (navigated_)
@@ -114,7 +167,7 @@ class NavigationWatcher : public WebContentsObserver {
private:
// Overridden from WebContentsObserver:
- virtual void AboutToNavigateRenderView(RenderViewHost* host) OVERRIDE {
+ void AboutToNavigateRenderView(RenderViewHost* host) override {
navigated_ = true;
if (should_quit_loop_)
base::MessageLoop::current()->Quit();
@@ -126,6 +179,55 @@ class NavigationWatcher : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(NavigationWatcher);
};
+class InputEventMessageFilterWaitsForAcks : public BrowserMessageFilter {
+ public:
+ InputEventMessageFilterWaitsForAcks()
+ : BrowserMessageFilter(InputMsgStart),
+ type_(blink::WebInputEvent::Undefined),
+ state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+
+ void WaitForAck(blink::WebInputEvent::Type type) {
+ base::RunLoop run_loop;
+ base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
+ base::AutoReset<blink::WebInputEvent::Type> reset_type(&type_, type);
+ run_loop.Run();
+ }
+
+ InputEventAckState last_ack_state() const { return state_; }
+
+ protected:
+ ~InputEventMessageFilterWaitsForAcks() override {}
+
+ private:
+ void ReceivedEventAck(blink::WebInputEvent::Type type,
+ InputEventAckState state) {
+ if (type_ == type) {
+ state_ = state;
+ quit_.Run();
+ }
+ }
+
+ // BrowserMessageFilter:
+ bool OnMessageReceived(const IPC::Message& message) override {
+ if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
+ InputHostMsg_HandleInputEvent_ACK::Param params;
+ InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
+ blink::WebInputEvent::Type type = params.a.type;
+ InputEventAckState ack = params.a.state;
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&InputEventMessageFilterWaitsForAcks::ReceivedEventAck,
+ this, type, ack));
+ }
+ return false;
+ }
+
+ base::Closure quit_;
+ blink::WebInputEvent::Type type_;
+ InputEventAckState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilterWaitsForAcks);
+};
+
class WebContentsViewAuraTest : public ContentBrowserTest {
public:
WebContentsViewAuraTest()
@@ -155,6 +257,11 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
controller->SetScreenshotManager(screenshot_manager_);
}
+ void SetUpCommandLine(CommandLine* cmd) override {
+ cmd->AppendSwitchASCII(switches::kTouchEvents,
+ switches::kTouchEventsEnabled);
+ }
+
void TestOverscrollNavigation(bool touch_handler) {
ASSERT_NO_FATAL_FAILURE(
StartTestWithPage("files/overscroll_navigation.html"));
@@ -184,7 +291,7 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
aura::Window* content = web_contents->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
const int kScrollDurationMs = 20;
const int kScrollSteps = 10;
@@ -255,21 +362,74 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
return index;
}
+ int ExecuteScriptAndExtractInt(const std::string& script) {
+ int value = 0;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
+ shell()->web_contents(),
+ "domAutomationController.send(" + script + ")",
+ &value));
+ return value;
+ }
+
+ RenderViewHost* GetRenderViewHost() const {
+ RenderViewHost* const rvh = shell()->web_contents()->GetRenderViewHost();
+ CHECK(rvh);
+ return rvh;
+ }
+
+ RenderWidgetHostImpl* GetRenderWidgetHost() const {
+ RenderWidgetHostImpl* const rwh =
+ RenderWidgetHostImpl::From(shell()
+ ->web_contents()
+ ->GetRenderWidgetHostView()
+ ->GetRenderWidgetHost());
+ CHECK(rwh);
+ return rwh;
+ }
+
+ RenderWidgetHostViewBase* GetRenderWidgetHostView() const {
+ return static_cast<RenderWidgetHostViewBase*>(
+ GetRenderViewHost()->GetView());
+ }
+
+ InputEventMessageFilterWaitsForAcks* filter() {
+ return filter_.get();
+ }
+
+ void WaitAFrame() {
+ uint32 frame = GetRenderWidgetHostView()->RendererFrameNumber();
+ while (!GetRenderWidgetHost()->ScheduleComposite())
+ GiveItSomeTime();
+ while (GetRenderWidgetHostView()->RendererFrameNumber() == frame)
+ GiveItSomeTime();
+ }
+
protected:
ScreenshotTracker* screenshot_manager() { return screenshot_manager_; }
void set_min_screenshot_interval(int interval_ms) {
screenshot_manager_->SetScreenshotInterval(interval_ms);
}
+ void AddInputEventMessageFilter() {
+ filter_ = new InputEventMessageFilterWaitsForAcks();
+ GetRenderWidgetHost()->GetProcess()->AddFilter(filter_.get());
+ }
+
private:
ScreenshotTracker* screenshot_manager_;
+ scoped_refptr<InputEventMessageFilterWaitsForAcks> filter_;
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAuraTest);
};
-// Flaky on Windows and ChromeOS: http://crbug.com/305722
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
- DISABLED_OverscrollNavigation) {
+// Flaky on Windows: http://crbug.com/305722
+#if defined(OS_WIN)
+#define MAYBE_OverscrollNavigation DISABLED_OverscrollNavigation
+#else
+#define MAYBE_OverscrollNavigation OverscrollNavigation
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollNavigation) {
TestOverscrollNavigation(false);
}
@@ -377,9 +537,16 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
// - interactively, when user does an overscroll gesture
// - interactively, when user navigates in history without the overscroll
// gesture.
-// Flaky on Windows and ChromeOS (http://crbug.com/357311). Might be related to
+// Flaky on Windows (http://crbug.com/357311). Might be related to
// OverscrollNavigation test.
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, DISABLED_OverscrollScreenshot) {
+// Flaky on Ozone (http://crbug.com/399676).
+// Flaky on ChromeOS (http://crbug.com/405945).
+#if defined(OS_WIN) || defined(USE_OZONE) || defined(OS_CHROMEOS)
+#define MAYBE_OverscrollScreenshot DISABLED_OverscrollScreenshot
+#else
+#define MAYBE_OverscrollScreenshot OverscrollScreenshot
+#endif
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) {
// Disable the test for WinXP. See http://crbug/294116.
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA) {
@@ -434,7 +601,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, DISABLED_OverscrollScreenshot) {
content::TitleWatcher title_watcher(web_contents, expected_title);
aura::Window* content = web_contents->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
@@ -504,11 +671,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
int transition;
} navigations[] = {
{ https_server.GetURL("files/title1.html"),
- PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR },
{ test_server()->GetURL("files/title2.html"),
- PAGE_TRANSITION_AUTO_BOOKMARK },
+ ui::PAGE_TRANSITION_AUTO_BOOKMARK },
{ https_server.GetURL("files/title3.html"),
- PAGE_TRANSITION_TYPED | PAGE_TRANSITION_FROM_ADDRESS_BAR },
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR },
{ GURL(), 0 }
};
@@ -516,7 +683,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
for (int i = 0; !navigations[i].url.is_empty(); ++i) {
// Navigate via the user initiating a navigation from the UI.
NavigationController::LoadURLParams params(navigations[i].url);
- params.transition_type = PageTransitionFromInt(navigations[i].transition);
+ params.transition_type =
+ ui::PageTransitionFromInt(navigations[i].transition);
RenderViewHost* old_host = web_contents->GetRenderViewHost();
web_contents->GetController().LoadURLWithParams(params);
@@ -544,7 +712,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
// Navigate again. This should not take any screenshot because of the
// increased screenshot interval.
NavigationController::LoadURLParams params(navigations[0].url);
- params.transition_type = PageTransitionFromInt(navigations[0].transition);
+ params.transition_type = ui::PageTransitionFromInt(navigations[0].transition);
web_contents->GetController().LoadURLWithParams(params);
WaitForLoadStop(web_contents);
screenshot_manager()->WaitUntilScreenshotIsReady();
@@ -607,7 +775,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
aura::Window* content = web_contents->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
@@ -628,7 +796,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
aura::Window* content = web_contents->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
generator.GestureScrollSequence(
gfx::Point(bounds.x() + 2, bounds.y() + 10),
gfx::Point(bounds.right() - 10, bounds.y() + 10),
@@ -676,7 +844,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
aura::Window* content = web_contents->GetContentNativeView();
gfx::Rect bounds = content->GetBoundsInRootWindow();
- aura::test::EventGenerator generator(content->GetRootWindow(), content);
+ ui::test::EventGenerator generator(content->GetRootWindow(), content);
// Do a swipe left to start a forward navigation. Then quickly do a swipe
// right.
@@ -717,4 +885,266 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, HideContentOnParenHide) {
EXPECT_TRUE(web_contents->should_normally_be_visible());
}
+// Ensure that SnapToPhysicalPixelBoundary() is called on WebContentsView parent
+// change. This is a regression test for http://crbug.com/388908.
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, WebContentsViewReparent) {
+ ASSERT_NO_FATAL_FAILURE(
+ StartTestWithPage("files/overscroll_navigation.html"));
+
+ scoped_ptr<aura::Window> window(new aura::Window(NULL));
+ window->Init(aura::WINDOW_LAYER_NOT_DRAWN);
+
+ RenderWidgetHostViewAura* rwhva =
+ static_cast<RenderWidgetHostViewAura*>(
+ shell()->web_contents()->GetRenderWidgetHostView());
+ rwhva->ResetHasSnappedToBoundary();
+ EXPECT_FALSE(rwhva->has_snapped_to_boundary());
+ window->AddChild(shell()->web_contents()->GetNativeView());
+ EXPECT_TRUE(rwhva->has_snapped_to_boundary());
+}
+
+// Flaky on some platforms, likely for the same reason as other flaky overscroll
+// tests. http://crbug.com/305722
+// TODO(tdresser): Re-enable this once eager GR is back on. See
+// crbug.com/410280.
+#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+#define MAYBE_OverscrollNavigationTouchThrottling \
+ DISABLED_OverscrollNavigationTouchThrottling
+#else
+#define MAYBE_OverscrollNavigationTouchThrottling \
+ DISABLED_OverscrollNavigationTouchThrottling
+#endif
+
+// Tests that touch moves are not throttled when performing a scroll gesture on
+// a non-scrollable area, except during gesture-nav.
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
+ MAYBE_OverscrollNavigationTouchThrottling) {
+ ASSERT_NO_FATAL_FAILURE(
+ StartTestWithPage("files/overscroll_navigation.html"));
+
+ AddInputEventMessageFilter();
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ aura::Window* content = web_contents->GetContentNativeView();
+ gfx::Rect bounds = content->GetBoundsInRootWindow();
+ const int dx = 20;
+
+ ExecuteSyncJSFunction(web_contents->GetMainFrame(),
+ "install_touchmove_handler()");
+
+ WaitAFrame();
+
+ for (int navigated = 0; navigated <= 1; ++navigated) {
+ if (navigated) {
+ ExecuteSyncJSFunction(web_contents->GetMainFrame(), "navigate_next()");
+ ExecuteSyncJSFunction(web_contents->GetMainFrame(),
+ "reset_touchmove_count()");
+ }
+ // Send touch press.
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(bounds.x() + 2, bounds.y() + 10);
+ GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
+ ui::LatencyInfo());
+ filter()->WaitForAck(blink::WebInputEvent::TouchStart);
+ WaitAFrame();
+
+ // Assert on the ack, because we'll end up waiting for acks that will never
+ // come if this is not true.
+ ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+
+ // Send first touch move, and then a scroll begin.
+ touch.MovePoint(0, bounds.x() + 20 + 1 * dx, bounds.y() + 100);
+ GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
+ ui::LatencyInfo());
+ filter()->WaitForAck(blink::WebInputEvent::TouchMove);
+ ASSERT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+
+ blink::WebGestureEvent scroll_begin =
+ SyntheticWebGestureEventBuilder::BuildScrollBegin(1, 1);
+ GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
+ scroll_begin, ui::LatencyInfo());
+ // Scroll begin ignores ack disposition, so don't wait for the ack.
+ WaitAFrame();
+
+ // First touchmove already sent, start at 2.
+ for (int i = 2; i <= 10; ++i) {
+ // Send a touch move, followed by a scroll update
+ touch.MovePoint(0, bounds.x() + 20 + i * dx, bounds.y() + 100);
+ GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(
+ touch, ui::LatencyInfo());
+ WaitAFrame();
+
+ blink::WebGestureEvent scroll_update =
+ SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, 5, 0);
+
+ GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
+ scroll_update, ui::LatencyInfo());
+
+ WaitAFrame();
+ }
+
+ touch.ReleasePoint(0);
+ GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch,
+ ui::LatencyInfo());
+ WaitAFrame();
+
+ blink::WebGestureEvent scroll_end;
+ scroll_end.type = blink::WebInputEvent::GestureScrollEnd;
+ GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo(
+ scroll_end, ui::LatencyInfo());
+ WaitAFrame();
+
+ if (!navigated)
+ EXPECT_EQ(10, ExecuteScriptAndExtractInt("touchmoveCount"));
+ else
+ EXPECT_GT(10, ExecuteScriptAndExtractInt("touchmoveCount"));
+ }
+}
+
+// Test that vertical overscroll updates are sent only when a user overscrolls
+// vertically.
+#if defined(OS_WIN)
+#define MAYBE_VerticalOverscroll DISABLED_VerticalOverscroll
+#else
+#define MAYBE_VerticalOverscroll VerticalOverscroll
+#endif
+
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_VerticalOverscroll) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kScrollEndEffect, "1");
+
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("about:blank"));
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ VerticalOverscrollTracker tracker;
+ web_contents->SetDelegate(&tracker);
+
+ // This test triggers a large number of animations. Speed them up to ensure
+ // the test completes within its time limit.
+ ui::ScopedAnimationDurationScaleMode fast_duration_mode(
+ ui::ScopedAnimationDurationScaleMode::FAST_DURATION);
+
+ aura::Window* content = web_contents->GetContentNativeView();
+ ui::EventProcessor* dispatcher = content->GetHost()->event_processor();
+ gfx::Rect bounds = content->GetBoundsInRootWindow();
+
+ // Overscroll horizontally.
+ {
+ int kXStep = bounds.width() / 10;
+ gfx::Point location(bounds.right() - kXStep, bounds.y() + 5);
+ base::TimeDelta timestamp = ui::EventTimeForNow();
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED,
+ location,
+ 0,
+ timestamp);
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location -= gfx::Vector2d(kXStep, 0);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+
+ while (location.x() > bounds.x() + kXStep) {
+ ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&inc);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location -= gfx::Vector2d(10, 0);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+ }
+
+ ui::TouchEvent release(ui::ET_TOUCH_RELEASED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&press);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+
+ EXPECT_EQ(0, tracker.num_overscroll_updates());
+ EXPECT_FALSE(tracker.overscroll_completed());
+ }
+
+ // Overscroll vertically.
+ {
+ tracker.Reset();
+
+ int kYStep = bounds.height() / 10;
+ gfx::Point location(bounds.x() + 10, bounds.y() + kYStep);
+ base::TimeDelta timestamp = ui::EventTimeForNow();
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED,
+ location,
+ 0,
+ timestamp);
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location += gfx::Vector2d(0, kYStep);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+
+ while (location.y() < bounds.bottom() - kYStep) {
+ ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&inc);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location += gfx::Vector2d(0, kYStep);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+ }
+
+ ui::TouchEvent release(ui::ET_TOUCH_RELEASED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&release);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+
+ EXPECT_LT(0, tracker.num_overscroll_updates());
+ EXPECT_TRUE(tracker.overscroll_completed());
+ }
+
+ // Start out overscrolling vertically, then switch directions and finish
+ // overscrolling horizontally.
+ {
+ tracker.Reset();
+
+ int kXStep = bounds.width() / 10;
+ int kYStep = bounds.height() / 10;
+ gfx::Point location = bounds.origin() + gfx::Vector2d(0, kYStep);
+ base::TimeDelta timestamp = ui::EventTimeForNow();
+ ui::TouchEvent press(
+ ui::ET_TOUCH_PRESSED,
+ location,
+ 0,
+ timestamp);
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location += gfx::Vector2d(0, kYStep);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+
+ for (size_t i = 0; i < 3; ++i) {
+ ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&inc);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location += gfx::Vector2d(0, kYStep);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+ }
+
+ while (location.x() < bounds.right() - kXStep) {
+ ui::TouchEvent inc(ui::ET_TOUCH_MOVED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&inc);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+ location += gfx::Vector2d(kXStep, 0);
+ timestamp += base::TimeDelta::FromMilliseconds(10);
+ }
+
+ ui::TouchEvent release(ui::ET_TOUCH_RELEASED, location, 0, timestamp);
+ details = dispatcher->OnEventFromSource(&release);
+ ASSERT_FALSE(details.dispatcher_destroyed);
+ WaitAFrame();
+
+ EXPECT_LT(0, tracker.num_overscroll_updates());
+ EXPECT_FALSE(tracker.overscroll_completed());
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.cc b/chromium/content/browser/web_contents/web_contents_view_guest.cc
index 14f460077b8..6cc1581e6a3 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.cc
@@ -60,7 +60,7 @@ gfx::NativeWindow WebContentsViewGuest::GetTopLevelNativeWindow() const {
return guest_->embedder_web_contents()->GetTopLevelNativeWindow();
}
-void WebContentsViewGuest::OnGuestInitialized(WebContentsView* parent_view) {
+void WebContentsViewGuest::OnGuestAttached(WebContentsView* parent_view) {
#if defined(USE_AURA)
// In aura, ScreenPositionClient doesn't work properly if we do
// not have the native view associated with this WebContentsViewGuest in the
@@ -71,14 +71,17 @@ void WebContentsViewGuest::OnGuestInitialized(WebContentsView* parent_view) {
#endif // defined(USE_AURA)
}
+void WebContentsViewGuest::OnGuestDetached(WebContentsView* old_parent_view) {
+#if defined(USE_AURA)
+ old_parent_view->GetNativeView()->RemoveChild(
+ platform_view_->GetNativeView());
+#endif // defined(USE_AURA)
+}
+
ContextMenuParams WebContentsViewGuest::ConvertContextMenuParams(
const ContextMenuParams& params) const {
-#if defined(USE_AURA)
- // Context menu uses ScreenPositionClient::ConvertPointToScreen() in aura
- // to calculate popup position. Guest's native view
- // (platform_view_->GetNativeView()) is part of the embedder's view hierarchy,
- // but is placed at (0, 0) w.r.t. the embedder's position. Therefore, |offset|
- // is added to |params|.
+ // We need to add |offset| of the guest from the embedder to position the
+ // menu properly.
gfx::Rect embedder_bounds;
guest_->embedder_web_contents()->GetView()->GetContainerBounds(
&embedder_bounds);
@@ -90,16 +93,18 @@ ContextMenuParams WebContentsViewGuest::ConvertContextMenuParams(
params_in_embedder.x += offset.x();
params_in_embedder.y += offset.y();
return params_in_embedder;
-#else
- return params;
-#endif
}
void WebContentsViewGuest::GetContainerBounds(gfx::Rect* out) const {
- // We need embedder container's bounds to calculate our bounds.
- guest_->embedder_web_contents()->GetView()->GetContainerBounds(out);
- gfx::Point guest_coordinates = guest_->GetScreenCoordinates(gfx::Point());
- out->Offset(guest_coordinates.x(), guest_coordinates.y());
+ if (guest_->embedder_web_contents()) {
+ // We need embedder container's bounds to calculate our bounds.
+ guest_->embedder_web_contents()->GetView()->GetContainerBounds(out);
+ gfx::Point guest_coordinates = guest_->GetScreenCoordinates(gfx::Point());
+ out->Offset(guest_coordinates.x(), guest_coordinates.y());
+ } else {
+ out->set_origin(gfx::Point());
+ }
+
out->set_size(size_);
}
@@ -119,21 +124,12 @@ gfx::Rect WebContentsViewGuest::GetViewBounds() const {
}
#if defined(OS_MACOSX)
-void WebContentsViewGuest::SetAllowOverlappingViews(bool overlapping) {
- platform_view_->SetAllowOverlappingViews(overlapping);
-}
-
-bool WebContentsViewGuest::GetAllowOverlappingViews() const {
- return platform_view_->GetAllowOverlappingViews();
+void WebContentsViewGuest::SetAllowOtherViews(bool allow) {
+ platform_view_->SetAllowOtherViews(allow);
}
-void WebContentsViewGuest::SetOverlayView(
- WebContentsView* overlay, const gfx::Point& offset) {
- platform_view_->SetOverlayView(overlay, offset);
-}
-
-void WebContentsViewGuest::RemoveOverlayView() {
- platform_view_->RemoveOverlayView();
+bool WebContentsViewGuest::GetAllowOtherViews() const {
+ return platform_view_->GetAllowOtherViews();
}
#endif
@@ -144,7 +140,7 @@ void WebContentsViewGuest::CreateView(const gfx::Size& initial_size,
}
RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForWidget(
- RenderWidgetHost* render_widget_host) {
+ RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
if (render_widget_host->GetView()) {
// During testing, the view will already be set up in most cases to the
// test view, so we don't want to clobber it with a real one. To verify that
@@ -157,14 +153,11 @@ RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForWidget(
}
RenderWidgetHostViewBase* platform_widget =
- platform_view_->CreateViewForWidget(render_widget_host);
-
- RenderWidgetHostViewBase* view = new RenderWidgetHostViewGuest(
- render_widget_host,
- guest_,
- platform_widget);
+ platform_view_->CreateViewForWidget(render_widget_host, true);
- return view;
+ return new RenderWidgetHostViewGuest(render_widget_host,
+ guest_,
+ platform_widget->GetWeakPtr());
}
RenderWidgetHostViewBase* WebContentsViewGuest::CreateViewForPopupWidget(
diff --git a/chromium/content/browser/web_contents/web_contents_view_guest.h b/chromium/content/browser/web_contents/web_contents_view_guest.h
index 53edd64e47f..e21f19a6956 100644
--- a/chromium/content/browser/web_contents/web_contents_view_guest.h
+++ b/chromium/content/browser/web_contents/web_contents_view_guest.h
@@ -31,11 +31,13 @@ class WebContentsViewGuest : public WebContentsView,
BrowserPluginGuest* guest,
scoped_ptr<WebContentsView> platform_view,
RenderViewHostDelegateView* platform_view_delegate_view);
- virtual ~WebContentsViewGuest();
+ ~WebContentsViewGuest() override;
WebContents* web_contents();
- void OnGuestInitialized(WebContentsView* parent_view);
+ void OnGuestAttached(WebContentsView* parent_view);
+
+ void OnGuestDetached(WebContentsView* old_parent_view);
// Converts the guest specific coordinates in |params| to embedder specific
// ones.
@@ -43,48 +45,46 @@ class WebContentsViewGuest : public WebContentsView,
const ContextMenuParams& params) const;
// WebContentsView implementation --------------------------------------------
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeView GetContentNativeView() const OVERRIDE;
- virtual gfx::NativeWindow GetTopLevelNativeWindow() const OVERRIDE;
- virtual void GetContainerBounds(gfx::Rect* out) const OVERRIDE;
- virtual void SizeContents(const gfx::Size& size) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void SetInitialFocus() OVERRIDE;
- virtual void StoreFocus() OVERRIDE;
- virtual void RestoreFocus() OVERRIDE;
- virtual DropData* GetDropData() const OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual void CreateView(const gfx::Size& initial_size,
- gfx::NativeView context) OVERRIDE;
- virtual RenderWidgetHostViewBase* CreateViewForWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual RenderWidgetHostViewBase* CreateViewForPopupWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const base::string16& title) OVERRIDE;
- virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
- virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
- virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeView GetContentNativeView() const override;
+ gfx::NativeWindow GetTopLevelNativeWindow() const override;
+ void GetContainerBounds(gfx::Rect* out) const override;
+ void SizeContents(const gfx::Size& size) override;
+ void Focus() override;
+ void SetInitialFocus() override;
+ void StoreFocus() override;
+ void RestoreFocus() override;
+ DropData* GetDropData() const override;
+ gfx::Rect GetViewBounds() const override;
+ void CreateView(const gfx::Size& initial_size,
+ gfx::NativeView context) override;
+ RenderWidgetHostViewBase* CreateViewForWidget(
+ RenderWidgetHost* render_widget_host,
+ bool is_guest_view_hack) override;
+ RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHost* render_widget_host) override;
+ void SetPageTitle(const base::string16& title) override;
+ void RenderViewCreated(RenderViewHost* host) override;
+ void RenderViewSwappedIn(RenderViewHost* host) override;
+ void SetOverscrollControllerEnabled(bool enabled) override;
#if defined(OS_MACOSX)
- virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE;
- virtual bool GetAllowOverlappingViews() const OVERRIDE;
- virtual void SetOverlayView(WebContentsView* overlay,
- const gfx::Point& offset) OVERRIDE;
- virtual void RemoveOverlayView() OVERRIDE;
- virtual bool IsEventTracking() const OVERRIDE;
- virtual void CloseTabAfterEventTracking() OVERRIDE;
+ void SetAllowOtherViews(bool allow) override;
+ bool GetAllowOtherViews() const override;
+ bool IsEventTracking() const override;
+ void CloseTabAfterEventTracking() override;
#endif
// Backend implementation of RenderViewHostDelegateView.
- virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
- const ContextMenuParams& params) OVERRIDE;
- virtual void StartDragging(const DropData& drop_data,
- blink::WebDragOperationsMask allowed_ops,
- const gfx::ImageSkia& image,
- const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
- virtual void GotFocus() OVERRIDE;
- virtual void TakeFocus(bool reverse) OVERRIDE;
+ void ShowContextMenu(RenderFrameHost* render_frame_host,
+ const ContextMenuParams& params) override;
+ void StartDragging(const DropData& drop_data,
+ blink::WebDragOperationsMask allowed_ops,
+ const gfx::ImageSkia& image,
+ const gfx::Vector2d& image_offset,
+ const DragEventSourceInfo& event_info) override;
+ void UpdateDragCursor(blink::WebDragOperation operation) override;
+ void GotFocus() override;
+ void TakeFocus(bool reverse) override;
private:
// The WebContentsImpl whose contents we display.
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.h b/chromium/content/browser/web_contents/web_contents_view_mac.h
index c6bc9dac7b8..93c1eaff906 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -63,57 +63,56 @@ class WebContentsViewMac : public WebContentsView,
// because that's what was easiest when they were split.
WebContentsViewMac(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate);
- virtual ~WebContentsViewMac();
+ ~WebContentsViewMac() override;
// WebContentsView implementation --------------------------------------------
- virtual gfx::NativeView GetNativeView() const OVERRIDE;
- virtual gfx::NativeView GetContentNativeView() const OVERRIDE;
- virtual gfx::NativeWindow GetTopLevelNativeWindow() const OVERRIDE;
- virtual void GetContainerBounds(gfx::Rect* out) const OVERRIDE;
- virtual void SizeContents(const gfx::Size& size) OVERRIDE;
- virtual void Focus() OVERRIDE;
- virtual void SetInitialFocus() OVERRIDE;
- virtual void StoreFocus() OVERRIDE;
- virtual void RestoreFocus() OVERRIDE;
- virtual DropData* GetDropData() const OVERRIDE;
- virtual gfx::Rect GetViewBounds() const OVERRIDE;
- virtual void SetAllowOverlappingViews(bool overlapping) OVERRIDE;
- virtual bool GetAllowOverlappingViews() const OVERRIDE;
- virtual void SetOverlayView(WebContentsView* overlay,
- const gfx::Point& offset) OVERRIDE;
- virtual void RemoveOverlayView() OVERRIDE;
- virtual void CreateView(
- const gfx::Size& initial_size, gfx::NativeView context) OVERRIDE;
- virtual RenderWidgetHostViewBase* CreateViewForWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual RenderWidgetHostViewBase* CreateViewForPopupWidget(
- RenderWidgetHost* render_widget_host) OVERRIDE;
- virtual void SetPageTitle(const base::string16& title) OVERRIDE;
- virtual void RenderViewCreated(RenderViewHost* host) OVERRIDE;
- virtual void RenderViewSwappedIn(RenderViewHost* host) OVERRIDE;
- virtual void SetOverscrollControllerEnabled(bool enabled) OVERRIDE;
- virtual bool IsEventTracking() const OVERRIDE;
- virtual void CloseTabAfterEventTracking() OVERRIDE;
+ gfx::NativeView GetNativeView() const override;
+ gfx::NativeView GetContentNativeView() const override;
+ gfx::NativeWindow GetTopLevelNativeWindow() const override;
+ void GetContainerBounds(gfx::Rect* out) const override;
+ void SizeContents(const gfx::Size& size) override;
+ void Focus() override;
+ void SetInitialFocus() override;
+ void StoreFocus() override;
+ void RestoreFocus() override;
+ DropData* GetDropData() const override;
+ gfx::Rect GetViewBounds() const override;
+ void SetAllowOtherViews(bool allow) override;
+ bool GetAllowOtherViews() const override;
+ void CreateView(const gfx::Size& initial_size,
+ gfx::NativeView context) override;
+ RenderWidgetHostViewBase* CreateViewForWidget(
+ RenderWidgetHost* render_widget_host,
+ bool is_guest_view_hack) override;
+ RenderWidgetHostViewBase* CreateViewForPopupWidget(
+ RenderWidgetHost* render_widget_host) override;
+ void SetPageTitle(const base::string16& title) override;
+ void RenderViewCreated(RenderViewHost* host) override;
+ void RenderViewSwappedIn(RenderViewHost* host) override;
+ void SetOverscrollControllerEnabled(bool enabled) override;
+ bool IsEventTracking() const override;
+ void CloseTabAfterEventTracking() override;
// Backend implementation of RenderViewHostDelegateView.
- virtual void ShowContextMenu(content::RenderFrameHost* render_frame_host,
- const ContextMenuParams& params) OVERRIDE;
- virtual void ShowPopupMenu(const gfx::Rect& bounds,
- int item_height,
- double item_font_size,
- int selected_item,
- const std::vector<MenuItem>& items,
- bool right_aligned,
- bool allow_multiple_selection) OVERRIDE;
- virtual void HidePopupMenu() OVERRIDE;
- virtual void StartDragging(const DropData& drop_data,
- blink::WebDragOperationsMask allowed_operations,
- const gfx::ImageSkia& image,
- const gfx::Vector2d& image_offset,
- const DragEventSourceInfo& event_info) OVERRIDE;
- virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
- virtual void GotFocus() OVERRIDE;
- virtual void TakeFocus(bool reverse) OVERRIDE;
+ void ShowContextMenu(RenderFrameHost* render_frame_host,
+ const ContextMenuParams& params) override;
+ void ShowPopupMenu(RenderFrameHost* render_frame_host,
+ const gfx::Rect& bounds,
+ int item_height,
+ double item_font_size,
+ int selected_item,
+ const std::vector<MenuItem>& items,
+ bool right_aligned,
+ bool allow_multiple_selection) override;
+ void HidePopupMenu() override;
+ void StartDragging(const DropData& drop_data,
+ blink::WebDragOperationsMask allowed_operations,
+ const gfx::ImageSkia& image,
+ const gfx::Vector2d& image_offset,
+ const DragEventSourceInfo& event_info) override;
+ void UpdateDragCursor(blink::WebDragOperation operation) override;
+ void GotFocus() override;
+ void TakeFocus(bool reverse) override;
// A helper method for closing the tab in the
// CloseTabAfterEventTracking() implementation.
@@ -123,8 +122,10 @@ class WebContentsViewMac : public WebContentsView,
WebContentsViewDelegate* delegate() { return delegate_.get(); }
private:
- // Updates overlay view on current RenderWidgetHostView.
- void UpdateRenderWidgetHostViewOverlay();
+ // Returns the fullscreen view, if one exists; otherwise, returns the content
+ // native view. This ensures that the view currently attached to a NSWindow is
+ // being used to query or set first responder state.
+ gfx::NativeView GetNativeViewForFocus() const;
// The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_;
@@ -139,19 +140,8 @@ class WebContentsViewMac : public WebContentsView,
// Our optional delegate.
scoped_ptr<WebContentsViewDelegate> delegate_;
- // Whether to allow overlapping views.
- bool allow_overlapping_views_;
-
- // The overlay view which is rendered above this one.
- // Overlay view has |underlay_view_| set to this view.
- WebContentsViewMac* overlay_view_;
-
- // The offset of overlay view relative to this view.
- gfx::Point overlay_view_offset_;
-
- // The underlay view which this view is rendered above.
- // Underlay view has |overlay_view_| set to this view.
- WebContentsViewMac* underlay_view_;
+ // Whether to allow other views.
+ bool allow_other_views_;
scoped_ptr<PopupMenuHelper> popup_menu_helper_;
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.mm b/chromium/content/browser/web_contents/web_contents_view_mac.mm
index 39e579baec2..3c99ac330cc 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -8,10 +8,12 @@
#include <string>
+#import "base/mac/mac_util.h"
#import "base/mac/scoped_sending_event.h"
+#include "base/mac/sdk_forward_declarations.h"
#include "base/message_loop/message_loop.h"
#import "base/message_loop/message_pump_mac.h"
-#include "content/browser/renderer_host/popup_menu_helper_mac.h"
+#include "content/browser/frame_host/popup_menu_helper_mac.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_mac.h"
@@ -68,6 +70,7 @@ COMPILE_ASSERT_MATCHING_ENUM(DragOperationEvery);
@end
namespace content {
+
WebContentsView* CreateWebContentsView(
WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate,
@@ -81,9 +84,7 @@ WebContentsViewMac::WebContentsViewMac(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
- allow_overlapping_views_(false),
- overlay_view_(NULL),
- underlay_view_(NULL) {
+ allow_other_views_(false) {
}
WebContentsViewMac::~WebContentsViewMac() {
@@ -159,9 +160,18 @@ void WebContentsViewMac::SizeContents(const gfx::Size& size) {
// previous implementation.
}
+gfx::NativeView WebContentsViewMac::GetNativeViewForFocus() const {
+ RenderWidgetHostView* rwhv =
+ web_contents_->GetFullscreenRenderWidgetHostView();
+ if (!rwhv)
+ rwhv = web_contents_->GetRenderWidgetHostView();
+ return rwhv ? rwhv->GetNativeView() : nil;
+}
+
void WebContentsViewMac::Focus() {
- NSWindow* window = [cocoa_view_.get() window];
- [window makeFirstResponder:GetContentNativeView()];
+ gfx::NativeView native_view = GetNativeViewForFocus();
+ NSWindow* window = [native_view window];
+ [window makeFirstResponder:native_view];
if (![window isVisible])
return;
[window makeKeyAndOrderFront:nil];
@@ -171,21 +181,23 @@ void WebContentsViewMac::SetInitialFocus() {
if (web_contents_->FocusLocationBarByDefault())
web_contents_->SetFocusToLocationBar(false);
else
- [[cocoa_view_.get() window] makeFirstResponder:GetContentNativeView()];
+ Focus();
}
void WebContentsViewMac::StoreFocus() {
+ gfx::NativeView native_view = GetNativeViewForFocus();
// We're explicitly being asked to store focus, so don't worry if there's
// already a view saved.
focus_tracker_.reset(
- [[FocusTracker alloc] initWithWindow:[cocoa_view_ window]]);
+ [[FocusTracker alloc] initWithWindow:[native_view window]]);
}
void WebContentsViewMac::RestoreFocus() {
+ gfx::NativeView native_view = GetNativeViewForFocus();
// TODO(avi): Could we be restoring a view that's no longer in the key view
// chain?
if (!(focus_tracker_.get() &&
- [focus_tracker_ restoreFocusInWindow:[cocoa_view_ window]])) {
+ [focus_tracker_ restoreFocusInWindow:[native_view window]])) {
// Fall back to the default focus behavior if we could not restore focus.
// TODO(shess): If location-bar gets focus by default, this will
// select-all in the field. If there was a specific selection in
@@ -221,7 +233,7 @@ void WebContentsViewMac::TakeFocus(bool reverse) {
}
void WebContentsViewMac::ShowContextMenu(
- content::RenderFrameHost* render_frame_host,
+ RenderFrameHost* render_frame_host,
const ContextMenuParams& params) {
// Allow delegates to handle the context menu operation first.
if (web_contents_->GetDelegate() &&
@@ -235,8 +247,8 @@ void WebContentsViewMac::ShowContextMenu(
DLOG(ERROR) << "Cannot show context menus without a delegate.";
}
-// Display a popup menu for WebKit using Cocoa widgets.
void WebContentsViewMac::ShowPopupMenu(
+ RenderFrameHost* render_frame_host,
const gfx::Rect& bounds,
int item_height,
double item_font_size,
@@ -244,8 +256,7 @@ void WebContentsViewMac::ShowPopupMenu(
const std::vector<MenuItem>& items,
bool right_aligned,
bool allow_multiple_selection) {
- popup_menu_helper_.reset(
- new PopupMenuHelper(web_contents_->GetRenderViewHost()));
+ popup_menu_helper_.reset(new PopupMenuHelper(render_frame_host));
popup_menu_helper_->ShowPopupMenu(bounds, item_height, item_font_size,
selected_item, items, right_aligned,
allow_multiple_selection);
@@ -263,67 +274,19 @@ gfx::Rect WebContentsViewMac::GetViewBounds() const {
return gfx::Rect();
}
-void WebContentsViewMac::SetAllowOverlappingViews(bool overlapping) {
- if (allow_overlapping_views_ == overlapping)
+void WebContentsViewMac::SetAllowOtherViews(bool allow) {
+ if (allow_other_views_ == allow)
return;
- allow_overlapping_views_ = overlapping;
+ allow_other_views_ = allow;
RenderWidgetHostViewMac* view = static_cast<RenderWidgetHostViewMac*>(
web_contents_->GetRenderWidgetHostView());
if (view)
- view->SetAllowOverlappingViews(allow_overlapping_views_);
+ view->SetAllowPauseForResizeOrRepaint(!allow_other_views_);
}
-bool WebContentsViewMac::GetAllowOverlappingViews() const {
- return allow_overlapping_views_;
-}
-
-void WebContentsViewMac::SetOverlayView(
- WebContentsView* overlay, const gfx::Point& offset) {
- DCHECK(!underlay_view_);
- if (overlay_view_)
- RemoveOverlayView();
-
- overlay_view_ = static_cast<WebContentsViewMac*>(overlay);
- DCHECK(!overlay_view_->overlay_view_);
- overlay_view_->underlay_view_ = this;
- overlay_view_offset_ = offset;
- UpdateRenderWidgetHostViewOverlay();
-}
-
-void WebContentsViewMac::RemoveOverlayView() {
- DCHECK(overlay_view_);
-
- RenderWidgetHostViewMac* rwhv = static_cast<RenderWidgetHostViewMac*>(
- web_contents_->GetRenderWidgetHostView());
- if (rwhv)
- rwhv->RemoveOverlayView();
-
- overlay_view_->underlay_view_ = NULL;
- overlay_view_ = NULL;
-}
-
-void WebContentsViewMac::UpdateRenderWidgetHostViewOverlay() {
- RenderWidgetHostViewMac* rwhv = static_cast<RenderWidgetHostViewMac*>(
- web_contents_->GetRenderWidgetHostView());
- if (!rwhv)
- return;
-
- if (overlay_view_) {
- RenderWidgetHostViewMac* overlay_rwhv =
- static_cast<RenderWidgetHostViewMac*>(
- overlay_view_->web_contents_->GetRenderWidgetHostView());
- if (overlay_rwhv)
- rwhv->SetOverlayView(overlay_rwhv, overlay_view_offset_);
- }
-
- if (underlay_view_) {
- RenderWidgetHostViewMac* underlay_rwhv =
- static_cast<RenderWidgetHostViewMac*>(
- underlay_view_->web_contents_->GetRenderWidgetHostView());
- if (underlay_rwhv)
- underlay_rwhv->SetOverlayView(rwhv, underlay_view_->overlay_view_offset_);
- }
+bool WebContentsViewMac::GetAllowOtherViews() const {
+ return allow_other_views_;
}
void WebContentsViewMac::CreateView(
@@ -334,7 +297,7 @@ void WebContentsViewMac::CreateView(
}
RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
- RenderWidgetHost* render_widget_host) {
+ RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
if (render_widget_host->GetView()) {
// During testing, the view will already be set up in most cases to the
// test view, so we don't want to clobber it with a real one. To verify that
@@ -347,7 +310,7 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
}
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(
- render_widget_host);
+ render_widget_host, is_guest_view_hack);
if (delegate()) {
base::scoped_nsobject<NSObject<RenderWidgetHostViewMacDelegate> >
rw_delegate(
@@ -355,7 +318,7 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
view->SetDelegate(rw_delegate.get());
}
- view->SetAllowOverlappingViews(allow_overlapping_views_);
+ view->SetAllowPauseForResizeOrRepaint(!allow_other_views_);
// Fancy layout comes later; for now just make it our size and resize it
// with us. In case there are other siblings of the content area, we want
@@ -381,7 +344,7 @@ RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForWidget(
RenderWidgetHostViewBase* WebContentsViewMac::CreateViewForPopupWidget(
RenderWidgetHost* render_widget_host) {
- return new RenderWidgetHostViewMac(render_widget_host);
+ return new RenderWidgetHostViewMac(render_widget_host, false);
}
void WebContentsViewMac::SetPageTitle(const base::string16& title) {
@@ -397,7 +360,6 @@ void WebContentsViewMac::RenderViewCreated(RenderViewHost* host) {
}
void WebContentsViewMac::RenderViewSwappedIn(RenderViewHost* host) {
- UpdateRenderWidgetHostViewOverlay();
}
void WebContentsViewMac::SetOverscrollControllerEnabled(bool enabled) {
@@ -634,4 +596,51 @@ void WebContentsViewMac::CloseTab() {
[subview setFrame:self.bounds];
}
+- (void)viewWillMoveToWindow:(NSWindow*)newWindow {
+ NSWindow* oldWindow = [self window];
+
+ NSNotificationCenter* notificationCenter =
+ [NSNotificationCenter defaultCenter];
+
+ // Occlusion notification APIs are new in Mavericks.
+ bool supportsOcclusionAPIs = base::mac::IsOSMavericksOrLater();
+
+ // Use of occlusion APIs is causing bugs:
+ // http://crbug.com/430968: focus set incorrectly.
+ // http://crbug.com/431272: flashes of incorrect content.
+ // http://crbug.com/310374: white flashes (comment 22).
+ supportsOcclusionAPIs = false;
+
+ if (supportsOcclusionAPIs) {
+ if (oldWindow) {
+ [notificationCenter
+ removeObserver:self
+ name:NSWindowDidChangeOcclusionStateNotification
+ object:oldWindow];
+ }
+ if (newWindow) {
+ [notificationCenter
+ addObserver:self
+ selector:@selector(windowChangedOcclusionState:)
+ name:NSWindowDidChangeOcclusionStateNotification
+ object:newWindow];
+ }
+ }
+}
+
+- (void)windowChangedOcclusionState:(NSNotification*)notification {
+ DCHECK(base::mac::IsOSMavericksOrLater());
+ NSWindow* window = [notification object];
+ WebContentsImpl* webContents = [self webContents];
+ if (window && webContents) {
+ if ([window occlusionState] & NSWindowOcclusionStateVisible) {
+ if (!webContents->should_normally_be_visible())
+ webContents->WasShown();
+ } else {
+ if (webContents->should_normally_be_visible())
+ webContents->WasHidden();
+ }
+ }
+}
+
@end
diff --git a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm b/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
index 29c84c1cdf5..5d21e7293b1 100644
--- a/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
@@ -72,7 +72,7 @@ class WebContentsPaintObserver : public content::WebContentsObserver {
OverscrollAnimatorSliderView* slider_view)
: WebContentsObserver(web_contents), slider_view_(slider_view) {}
- virtual void DidFirstVisuallyNonEmptyPaint() OVERRIDE {
+ virtual void DidFirstVisuallyNonEmptyPaint() override {
[slider_view_ webContentsFinishedNonEmptyPaint];
}
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.mm b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
index b0cb8e2d376..0e57d4fffde 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
@@ -216,7 +216,7 @@ int GetModifierFlags() {
GURL url;
ui::PopulateURLAndTitleFromPasteboard(&url, NULL, pboard, YES);
webContents_->OpenURL(OpenURLParams(
- url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_AUTO_BOOKMARK,
+ url, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_AUTO_BOOKMARK,
false));
return YES;
} else {
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac.mm b/chromium/content/browser/web_contents/web_drag_source_mac.mm
index b0f21609338..f8b639c434f 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -24,13 +24,13 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/drop_data.h"
-#include "grit/ui_resources.h"
#include "net/base/escape.h"
#include "net/base/filename_util.h"
#include "net/base/mime_util.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/gfx/image/image.h"
+#include "ui/resources/grit/ui_resources.h"
#include "url/url_constants.h"
using base::SysNSStringToUTF8;
diff --git a/chromium/content/browser/webui/content_web_ui_controller_factory.h b/chromium/content/browser/webui/content_web_ui_controller_factory.h
index cee0ec728b0..f2638117720 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.h
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.h
@@ -14,21 +14,20 @@ namespace content {
class ContentWebUIControllerFactory : public WebUIControllerFactory {
public:
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE;
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE;
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE;
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui,
- const GURL& url) const OVERRIDE;
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override;
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override;
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override;
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override;
static ContentWebUIControllerFactory* GetInstance();
protected:
ContentWebUIControllerFactory();
- virtual ~ContentWebUIControllerFactory();
+ ~ContentWebUIControllerFactory() override;
private:
friend struct DefaultSingletonTraits<ContentWebUIControllerFactory>;
diff --git a/chromium/content/browser/webui/generic_handler.cc b/chromium/content/browser/webui/generic_handler.cc
index 058382fa8a8..b26bcd9294a 100644
--- a/chromium/content/browser/webui/generic_handler.cc
+++ b/chromium/content/browser/webui/generic_handler.cc
@@ -50,8 +50,11 @@ void GenericHandler::HandleNavigateToUrl(const base::ListValue* args) {
if (disposition == CURRENT_TAB && target_string == "_blank")
disposition = NEW_FOREGROUND_TAB;
- web_ui()->GetWebContents()->OpenURL(OpenURLParams(
- GURL(url_string), Referrer(), disposition, PAGE_TRANSITION_LINK, false));
+ web_ui()->GetWebContents()->OpenURL(OpenURLParams(GURL(url_string),
+ Referrer(),
+ disposition,
+ ui::PAGE_TRANSITION_LINK,
+ false));
// This may delete us!
}
diff --git a/chromium/content/browser/webui/generic_handler.h b/chromium/content/browser/webui/generic_handler.h
index 431373dd3b1..dd352555d0d 100644
--- a/chromium/content/browser/webui/generic_handler.h
+++ b/chromium/content/browser/webui/generic_handler.h
@@ -18,10 +18,10 @@ namespace content {
class GenericHandler : public WebUIMessageHandler {
public:
GenericHandler();
- virtual ~GenericHandler();
+ ~GenericHandler() override;
// WebUIMessageHandler implementation.
- virtual void RegisterMessages() OVERRIDE;
+ void RegisterMessages() override;
private:
void HandleNavigateToUrl(const base::ListValue* args);
diff --git a/chromium/content/browser/webui/shared_resources_data_source.cc b/chromium/content/browser/webui/shared_resources_data_source.cc
index aa1dc390100..2ce6e147b09 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.cc
+++ b/chromium/content/browser/webui/shared_resources_data_source.cc
@@ -10,8 +10,8 @@
#include "base/threading/thread_restrictions.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
-#include "grit/webui_resources_map.h"
#include "net/base/mime_util.h"
+#include "ui/resources/grit/webui_resources_map.h"
namespace {
@@ -89,3 +89,17 @@ std::string SharedResourcesDataSource::GetMimeType(
net::GetMimeTypeFromFile(base::FilePath().AppendASCII(path), &mime_type);
return mime_type;
}
+
+std::string
+SharedResourcesDataSource::GetAccessControlAllowOriginForOrigin(
+ const std::string& origin) const {
+ // For now we give access only for "chrome://*" origins.
+ // According to CORS spec, Access-Control-Allow-Origin header doesn't support
+ // wildcards, so we need to set its value explicitly by passing the |origin|
+ // back.
+ std::string allowed_origin_prefix = content::kChromeUIScheme;
+ allowed_origin_prefix += "://";
+ if (origin.find(allowed_origin_prefix) != 0)
+ return "none";
+ return origin;
+}
diff --git a/chromium/content/browser/webui/shared_resources_data_source.h b/chromium/content/browser/webui/shared_resources_data_source.h
index 9c3a3c464ef..87b5121ad22 100644
--- a/chromium/content/browser/webui/shared_resources_data_source.h
+++ b/chromium/content/browser/webui/shared_resources_data_source.h
@@ -15,16 +15,18 @@ class SharedResourcesDataSource : public content::URLDataSource {
SharedResourcesDataSource();
// content::URLDataSource implementation.
- virtual std::string GetSource() const OVERRIDE;
- virtual void StartDataRequest(
+ std::string GetSource() const override;
+ void StartDataRequest(
const std::string& path,
int render_process_id,
int render_frame_id,
- const content::URLDataSource::GotDataCallback& callback) OVERRIDE;
- virtual std::string GetMimeType(const std::string&) const OVERRIDE;
+ const content::URLDataSource::GotDataCallback& callback) override;
+ std::string GetMimeType(const std::string&) const override;
+ std::string GetAccessControlAllowOriginForOrigin(
+ const std::string& origin) const override;
private:
- virtual ~SharedResourcesDataSource();
+ ~SharedResourcesDataSource() override;
DISALLOW_COPY_AND_ASSIGN(SharedResourcesDataSource);
};
diff --git a/chromium/content/browser/webui/url_data_manager.h b/chromium/content/browser/webui/url_data_manager.h
index e94568d7c82..8a318b73dba 100644
--- a/chromium/content/browser/webui/url_data_manager.h
+++ b/chromium/content/browser/webui/url_data_manager.h
@@ -26,7 +26,7 @@ class WebUIDataSource;
class CONTENT_EXPORT URLDataManager : public base::SupportsUserData::Data {
public:
explicit URLDataManager(BrowserContext* browser_context);
- virtual ~URLDataManager();
+ ~URLDataManager() override;
// Adds a DataSource to the collection of data sources. This *must* be invoked
// on the UI thread.
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index 9f661af2f6a..9e12864b322 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -44,8 +44,6 @@
#include "net/url_request/url_request_job_factory.h"
#include "url/url_util.h"
-using appcache::AppCacheServiceImpl;
-
namespace content {
namespace {
@@ -92,6 +90,19 @@ void URLToRequestPath(const GURL& url, std::string* path) {
path->assign(spec.substr(offset));
}
+// Returns a value of 'Origin:' header for the |request| if the header is set.
+// Otherwise returns an empty string.
+std::string GetOriginHeaderValue(const net::URLRequest* request) {
+ std::string result;
+ if (request->extra_request_headers().GetHeader(
+ net::HttpRequestHeaders::kOrigin, &result))
+ return result;
+ net::HttpRequestHeaders headers;
+ if (request->GetFullRequestHeaders(&headers))
+ headers.GetHeader(net::HttpRequestHeaders::kOrigin, &result);
+ return result;
+}
+
} // namespace
// URLRequestChromeJob is a net::URLRequestJob that manages running
@@ -108,14 +119,12 @@ class URLRequestChromeJob : public net::URLRequestJob,
bool is_incognito);
// net::URLRequestJob implementation.
- virtual void Start() OVERRIDE;
- virtual void Kill() OVERRIDE;
- virtual bool ReadRawData(net::IOBuffer* buf,
- int buf_size,
- int* bytes_read) OVERRIDE;
- virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
- virtual int GetResponseCode() const OVERRIDE;
- virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE;
+ void Start() override;
+ void Kill() override;
+ bool ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read) override;
+ bool GetMimeType(std::string* mime_type) const override;
+ int GetResponseCode() const override;
+ void GetResponseInfo(net::HttpResponseInfo* info) override;
// Used to notify that the requested data's |mime_type| is ready.
void MimeTypeAvailable(const std::string& mime_type);
@@ -154,13 +163,17 @@ class URLRequestChromeJob : public net::URLRequestJob,
send_content_type_header_ = send_content_type_header;
}
+ void set_access_control_allow_origin(const std::string& value) {
+ access_control_allow_origin_ = value;
+ }
+
// Returns true when job was generated from an incognito profile.
bool is_incognito() const {
return is_incognito_;
}
private:
- virtual ~URLRequestChromeJob();
+ ~URLRequestChromeJob() override;
// Helper for Start(), to let us start asynchronously.
// (This pattern is shared by most net::URLRequestJob implementations.)
@@ -204,10 +217,14 @@ class URLRequestChromeJob : public net::URLRequestJob,
// If true, sets the "Content-Type: <mime-type>" header.
bool send_content_type_header_;
+ // If not empty, "Access-Control-Allow-Origin:" is set to the value of this
+ // string.
+ std::string access_control_allow_origin_;
+
// True when job is generated from an incognito profile.
const bool is_incognito_;
- // The backend is owned by ChromeURLRequestContext and always outlives us.
+ // The backend is owned by net::URLRequestContext and always outlives us.
URLDataManagerBackend* backend_;
base::WeakPtrFactory<URLRequestChromeJob> weak_factory_;
@@ -295,6 +312,12 @@ void URLRequestChromeJob::GetResponseInfo(net::HttpResponseInfo* info) {
mime_type_.c_str());
info->headers->AddHeader(content_type);
}
+
+ if (!access_control_allow_origin_.empty()) {
+ info->headers->AddHeader("Access-Control-Allow-Origin: " +
+ access_control_allow_origin_);
+ info->headers->AddHeader("Vary: Origin");
+ }
}
void URLRequestChromeJob::MimeTypeAvailable(const std::string& mime_type) {
@@ -434,11 +457,11 @@ class ChromeProtocolHandler
is_incognito_(is_incognito),
appcache_service_(appcache_service),
blob_storage_context_(blob_storage_context) {}
- virtual ~ChromeProtocolHandler() {}
+ ~ChromeProtocolHandler() override {}
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE {
+ net::NetworkDelegate* network_delegate) const override {
DCHECK(request);
// Check for chrome://view-http-cache/*, which uses its own job type.
@@ -479,7 +502,7 @@ class ChromeProtocolHandler
GetURLDataManagerForResourceContext(resource_context_), is_incognito_);
}
- virtual bool IsSafeRedirectTarget(const GURL& location) const OVERRIDE {
+ bool IsSafeRedirectTarget(const GURL& location) const override {
return false;
}
@@ -580,6 +603,15 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
job->set_send_content_type_header(
source->source()->ShouldServeMimeTypeAsContentTypeHeader());
+ std::string origin = GetOriginHeaderValue(request);
+ if (!origin.empty()) {
+ std::string header =
+ source->source()->GetAccessControlAllowOriginForOrigin(origin);
+ DCHECK(header.empty() || header == origin || header == "*" ||
+ header == "null");
+ job->set_access_control_allow_origin(header);
+ }
+
// Look up additional request info to pass down.
int render_process_id = -1;
int render_frame_id = -1;
@@ -695,11 +727,11 @@ class DevToolsJobFactory
// |is_incognito| should be set for incognito profiles.
DevToolsJobFactory(content::ResourceContext* resource_context,
bool is_incognito);
- virtual ~DevToolsJobFactory();
+ ~DevToolsJobFactory() override;
- virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequestJob* MaybeCreateJob(
net::URLRequest* request,
- net::NetworkDelegate* network_delegate) const OVERRIDE;
+ net::NetworkDelegate* network_delegate) const override;
private:
// |resource_context_| and |network_delegate_| are owned by ProfileIOData,
diff --git a/chromium/content/browser/webui/url_data_manager_backend.h b/chromium/content/browser/webui/url_data_manager_backend.h
index a307cdbfa10..19d6bd24aec 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.h
+++ b/chromium/content/browser/webui/url_data_manager_backend.h
@@ -18,15 +18,13 @@
class GURL;
-namespace appcache {
-class AppCacheServiceImpl;
-}
-
namespace base {
class RefCountedMemory;
}
namespace content {
+
+class AppCacheServiceImpl;
class ChromeBlobStorageContext;
class ResourceContext;
class URLDataManagerBackend;
@@ -41,14 +39,14 @@ class URLDataManagerBackend : public base::SupportsUserData::Data {
typedef int RequestID;
URLDataManagerBackend();
- virtual ~URLDataManagerBackend();
+ ~URLDataManagerBackend() override;
// Invoked to create the protocol handler for chrome://. |is_incognito| should
// be set for incognito profiles. Called on the UI thread.
static net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler(
content::ResourceContext* resource_context,
bool is_incognito,
- appcache::AppCacheServiceImpl* appcache_service,
+ AppCacheServiceImpl* appcache_service,
ChromeBlobStorageContext* blob_storage_context);
// Adds a DataSource to the collection of data sources.
diff --git a/chromium/content/browser/webui/web_ui_controller_factory_registry.h b/chromium/content/browser/webui/web_ui_controller_factory_registry.h
index 6d0da82edeb..b59162f6e1d 100644
--- a/chromium/content/browser/webui/web_ui_controller_factory_registry.h
+++ b/chromium/content/browser/webui/web_ui_controller_factory_registry.h
@@ -19,14 +19,14 @@ class CONTENT_EXPORT WebUIControllerFactoryRegistry
// WebUIControllerFactory implementation. Each method loops through the same
// method on all the factories.
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const OVERRIDE;
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE;
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE;
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE;
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override;
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override;
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override;
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override;
// Returns true if the given URL can be loaded by Web UI system. This allows
// URLs that UseWebUIForURL returns true for, and also URLs that can be loaded
@@ -38,7 +38,7 @@ class CONTENT_EXPORT WebUIControllerFactoryRegistry
friend struct DefaultSingletonTraits<WebUIControllerFactoryRegistry>;
WebUIControllerFactoryRegistry();
- virtual ~WebUIControllerFactoryRegistry();
+ ~WebUIControllerFactoryRegistry() override;
DISALLOW_COPY_AND_ASSIGN(WebUIControllerFactoryRegistry);
};
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.cc b/chromium/content/browser/webui/web_ui_data_source_impl.cc
index 052396746fe..caa8f9ad858 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -9,9 +9,9 @@
#include "base/bind.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_util.h"
+#include "content/grit/content_resources.h"
#include "content/public/common/content_client.h"
-#include "grit/content_resources.h"
-#include "mojo/public/js/bindings/constants.h"
+#include "mojo/public/js/constants.h"
#include "ui/base/webui/jstemplate_builder.h"
#include "ui/base/webui/web_ui_util.h"
@@ -31,13 +31,15 @@ WebUIDataSource* WebUIDataSource::AddMojoDataSource(
const char* path;
int id;
} resources[] = {
+ { mojo::kBufferModuleName, IDR_MOJO_BUFFER_JS },
{ mojo::kCodecModuleName, IDR_MOJO_CODEC_JS },
{ mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS },
{ mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS },
{ mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS },
{ mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS },
+ { mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS },
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i)
+ for (size_t i = 0; i < arraysize(resources); ++i)
mojo_source->AddResourcePath(resources[i].path, resources[i].id);
URLDataManager::AddWebUIDataSource(browser_context, mojo_source);
@@ -57,44 +59,39 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
InternalDataSource(WebUIDataSourceImpl* parent) : parent_(parent) {
}
- virtual ~InternalDataSource() {
- }
+ ~InternalDataSource() override {}
// URLDataSource implementation.
- virtual std::string GetSource() const OVERRIDE {
- return parent_->GetSource();
- }
- virtual std::string GetMimeType(const std::string& path) const OVERRIDE {
+ std::string GetSource() const override { return parent_->GetSource(); }
+ std::string GetMimeType(const std::string& path) const override {
return parent_->GetMimeType(path);
}
- virtual void StartDataRequest(
+ void StartDataRequest(
const std::string& path,
int render_process_id,
int render_frame_id,
- const URLDataSource::GotDataCallback& callback) OVERRIDE {
+ const URLDataSource::GotDataCallback& callback) override {
return parent_->StartDataRequest(path, render_process_id, render_frame_id,
callback);
}
- virtual bool ShouldReplaceExistingSource() const OVERRIDE {
+ bool ShouldReplaceExistingSource() const override {
return parent_->replace_existing_source_;
}
- virtual bool AllowCaching() const OVERRIDE {
- return false;
- }
- virtual bool ShouldAddContentSecurityPolicy() const OVERRIDE {
+ bool AllowCaching() const override { return false; }
+ bool ShouldAddContentSecurityPolicy() const override {
return parent_->add_csp_;
}
- virtual std::string GetContentSecurityPolicyObjectSrc() const OVERRIDE {
+ std::string GetContentSecurityPolicyObjectSrc() const override {
if (parent_->object_src_set_)
return parent_->object_src_;
return URLDataSource::GetContentSecurityPolicyObjectSrc();
}
- virtual std::string GetContentSecurityPolicyFrameSrc() const OVERRIDE {
+ std::string GetContentSecurityPolicyFrameSrc() const override {
if (parent_->frame_src_set_)
return parent_->frame_src_;
return URLDataSource::GetContentSecurityPolicyFrameSrc();
}
- virtual bool ShouldDenyXFrameOptions() const OVERRIDE {
+ bool ShouldDenyXFrameOptions() const override {
return parent_->deny_xframe_options_;
}
@@ -108,7 +105,6 @@ WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
new InternalDataSource(this)),
source_name_(source_name),
default_resource_(-1),
- json_js_format_v2_(false),
add_csp_(true),
object_src_set_(false),
frame_src_set_(false),
@@ -149,10 +145,6 @@ void WebUIDataSourceImpl::SetJsonPath(const std::string& path) {
json_path_ = path;
}
-void WebUIDataSourceImpl::SetUseJsonJSFormatV2() {
- json_js_format_v2_ = true;
-}
-
void WebUIDataSourceImpl::AddResourcePath(const std::string &path,
int resource_id) {
path_to_idr_map_[path] = resource_id;
@@ -241,10 +233,6 @@ void WebUIDataSourceImpl::SendLocalizedStringsAsJSON(
if (!disable_set_font_strings_)
webui::SetFontAndTextDirection(&localized_strings_);
- scoped_ptr<webui::UseVersion2> version2;
- if (json_js_format_v2_)
- version2.reset(new webui::UseVersion2);
-
webui::AppendJsonJS(&localized_strings_, &template_data);
callback.Run(base::RefCountedString::TakeString(&template_data));
}
diff --git a/chromium/content/browser/webui/web_ui_data_source_impl.h b/chromium/content/browser/webui/web_ui_data_source_impl.h
index 9a015899c1a..d9f44887d1c 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -27,31 +27,25 @@ class CONTENT_EXPORT WebUIDataSourceImpl
public NON_EXPORTED_BASE(WebUIDataSource) {
public:
// WebUIDataSource implementation:
- virtual void AddString(const std::string& name,
- const base::string16& value) OVERRIDE;
- virtual void AddString(const std::string& name,
- const std::string& value) OVERRIDE;
- virtual void AddLocalizedString(const std::string& name, int ids) OVERRIDE;
- virtual void AddLocalizedStrings(
- const base::DictionaryValue& localized_strings) OVERRIDE;
- virtual void AddBoolean(const std::string& name, bool value) OVERRIDE;
- virtual void SetJsonPath(const std::string& path) OVERRIDE;
- virtual void SetUseJsonJSFormatV2() OVERRIDE;
- virtual void AddResourcePath(const std::string &path,
- int resource_id) OVERRIDE;
- virtual void SetDefaultResource(int resource_id) OVERRIDE;
- virtual void SetRequestFilter(
- const WebUIDataSource::HandleRequestCallback& callback) OVERRIDE;
- virtual void DisableReplaceExistingSource() OVERRIDE;
- virtual void DisableContentSecurityPolicy() OVERRIDE;
- virtual void OverrideContentSecurityPolicyObjectSrc(
- const std::string& data) OVERRIDE;
- virtual void OverrideContentSecurityPolicyFrameSrc(
- const std::string& data) OVERRIDE;
- virtual void DisableDenyXFrameOptions() OVERRIDE;
+ void AddString(const std::string& name, const base::string16& value) override;
+ void AddString(const std::string& name, const std::string& value) override;
+ void AddLocalizedString(const std::string& name, int ids) override;
+ void AddLocalizedStrings(
+ const base::DictionaryValue& localized_strings) override;
+ void AddBoolean(const std::string& name, bool value) override;
+ void SetJsonPath(const std::string& path) override;
+ void AddResourcePath(const std::string& path, int resource_id) override;
+ void SetDefaultResource(int resource_id) override;
+ void SetRequestFilter(
+ const WebUIDataSource::HandleRequestCallback& callback) override;
+ void DisableReplaceExistingSource() override;
+ void DisableContentSecurityPolicy() override;
+ void OverrideContentSecurityPolicyObjectSrc(const std::string& data) override;
+ void OverrideContentSecurityPolicyFrameSrc(const std::string& data) override;
+ void DisableDenyXFrameOptions() override;
protected:
- virtual ~WebUIDataSourceImpl();
+ ~WebUIDataSourceImpl() override;
// Completes a request by sending our dictionary of localized strings.
void SendLocalizedStringsAsJSON(
@@ -88,7 +82,6 @@ class CONTENT_EXPORT WebUIDataSourceImpl
// specific resources like "favicon/34" getting sent to this source.
std::string source_name_;
int default_resource_;
- bool json_js_format_v2_;
std::string json_path_;
std::map<std::string, int> path_to_idr_map_;
base::DictionaryValue localized_strings_;
diff --git a/chromium/content/browser/webui/web_ui_data_source_unittest.cc b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
index 97fa85ec82f..c5b469860a2 100644
--- a/chromium/content/browser/webui/web_ui_data_source_unittest.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_unittest.cc
@@ -6,6 +6,7 @@
#include "base/memory/ref_counted_memory.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/webui/web_ui_data_source_impl.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_client.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -23,17 +24,17 @@ const char kDummytResource[] = "<html>blah</html>";
class TestClient : public TestContentClient {
public:
TestClient() {}
- virtual ~TestClient() {}
+ ~TestClient() override {}
- virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE {
+ base::string16 GetLocalizedString(int message_id) const override {
if (message_id == kDummyStringId)
return base::UTF8ToUTF16(kDummyString);
return base::string16();
}
- virtual base::RefCountedStaticMemory* GetDataResourceBytes(
- int resource_id) const OVERRIDE {
+ base::RefCountedStaticMemory* GetDataResourceBytes(
+ int resource_id) const override {
base::RefCountedStaticMemory* bytes = NULL;
if (resource_id == kDummyDefaultResourceId) {
bytes = new base::RefCountedStaticMemory(
@@ -51,7 +52,7 @@ class TestClient : public TestContentClient {
class WebUIDataSourceTest : public testing::Test {
public:
WebUIDataSourceTest() : result_data_(NULL) {}
- virtual ~WebUIDataSourceTest() {}
+ ~WebUIDataSourceTest() override {}
WebUIDataSourceImpl* source() { return source_.get(); }
void StartDataRequest(const std::string& path) {
@@ -69,7 +70,7 @@ class WebUIDataSourceTest : public testing::Test {
scoped_refptr<base::RefCountedMemory> result_data_;
private:
- virtual void SetUp() {
+ void SetUp() override {
SetContentClient(&client_);
WebUIDataSource* source = WebUIDataSourceImpl::Create("host");
WebUIDataSourceImpl* source_impl = static_cast<WebUIDataSourceImpl*>(
@@ -83,6 +84,7 @@ class WebUIDataSourceTest : public testing::Test {
result_data_ = data;
}
+ TestBrowserThreadBundle thread_bundle_;
scoped_refptr<WebUIDataSourceImpl> source_;
TestClient client_;
};
@@ -91,7 +93,7 @@ TEST_F(WebUIDataSourceTest, EmptyStrings) {
source()->SetJsonPath("strings.js");
StartDataRequest("strings.js");
std::string result(result_data_->front_as<char>(), result_data_->size());
- EXPECT_NE(result.find("var templateData = {"), std::string::npos);
+ EXPECT_NE(result.find("loadTimeData.data = {"), std::string::npos);
EXPECT_NE(result.find("};"), std::string::npos);
}
diff --git a/chromium/content/browser/webui/web_ui_impl.cc b/chromium/content/browser/webui/web_ui_impl.cc
index 340a047b398..a9194a992fd 100644
--- a/chromium/content/browser/webui/web_ui_impl.cc
+++ b/chromium/content/browser/webui/web_ui_impl.cc
@@ -44,7 +44,7 @@ base::string16 WebUI::GetJavascriptCall(
}
WebUIImpl::WebUIImpl(WebContents* contents)
- : link_transition_type_(PAGE_TRANSITION_LINK),
+ : link_transition_type_(ui::PAGE_TRANSITION_LINK),
bindings_(BINDINGS_POLICY_WEB_UI),
web_contents_(contents) {
DCHECK(contents);
@@ -110,11 +110,11 @@ void WebUIImpl::OverrideTitle(const base::string16& title) {
overridden_title_ = title;
}
-PageTransition WebUIImpl::GetLinkTransitionType() const {
+ui::PageTransition WebUIImpl::GetLinkTransitionType() const {
return link_transition_type_;
}
-void WebUIImpl::SetLinkTransitionType(PageTransition type) {
+void WebUIImpl::SetLinkTransitionType(ui::PageTransition type) {
link_transition_type_ = type;
}
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index 40cb559c1f6..c08db2927f6 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -23,7 +23,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
public base::SupportsWeakPtr<WebUIImpl> {
public:
explicit WebUIImpl(WebContents* contents);
- virtual ~WebUIImpl();
+ ~WebUIImpl() override;
// Called by WebContentsImpl when the RenderView is first created. This is
// *not* called for every page load because in some cases
@@ -31,47 +31,45 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
void RenderViewCreated(RenderViewHost* render_view_host);
// WebUI implementation:
- virtual WebContents* GetWebContents() const OVERRIDE;
- virtual WebUIController* GetController() const OVERRIDE;
- virtual void SetController(WebUIController* controller) OVERRIDE;
- virtual float GetDeviceScaleFactor() const OVERRIDE;
- virtual const base::string16& GetOverriddenTitle() const OVERRIDE;
- virtual void OverrideTitle(const base::string16& title) OVERRIDE;
- virtual PageTransition GetLinkTransitionType() const OVERRIDE;
- virtual void SetLinkTransitionType(PageTransition type) OVERRIDE;
- virtual int GetBindings() const OVERRIDE;
- virtual void SetBindings(int bindings) OVERRIDE;
- virtual void OverrideJavaScriptFrame(const std::string& frame_name) OVERRIDE;
- virtual void AddMessageHandler(WebUIMessageHandler* handler) OVERRIDE;
+ WebContents* GetWebContents() const override;
+ WebUIController* GetController() const override;
+ void SetController(WebUIController* controller) override;
+ float GetDeviceScaleFactor() const override;
+ const base::string16& GetOverriddenTitle() const override;
+ void OverrideTitle(const base::string16& title) override;
+ ui::PageTransition GetLinkTransitionType() const override;
+ void SetLinkTransitionType(ui::PageTransition type) override;
+ int GetBindings() const override;
+ void SetBindings(int bindings) override;
+ void OverrideJavaScriptFrame(const std::string& frame_name) override;
+ void AddMessageHandler(WebUIMessageHandler* handler) override;
typedef base::Callback<void(const base::ListValue*)> MessageCallback;
- virtual void RegisterMessageCallback(
- const std::string& message,
- const MessageCallback& callback) OVERRIDE;
- virtual void ProcessWebUIMessage(const GURL& source_url,
- const std::string& message,
- const base::ListValue& args) OVERRIDE;
- virtual void CallJavascriptFunction(
- const std::string& function_name) OVERRIDE;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg) OVERRIDE;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2) OVERRIDE;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3) OVERRIDE;
- virtual void CallJavascriptFunction(const std::string& function_name,
- const base::Value& arg1,
- const base::Value& arg2,
- const base::Value& arg3,
- const base::Value& arg4) OVERRIDE;
- virtual void CallJavascriptFunction(
+ void RegisterMessageCallback(const std::string& message,
+ const MessageCallback& callback) override;
+ void ProcessWebUIMessage(const GURL& source_url,
+ const std::string& message,
+ const base::ListValue& args) override;
+ void CallJavascriptFunction(const std::string& function_name) override;
+ void CallJavascriptFunction(const std::string& function_name,
+ const base::Value& arg) override;
+ void CallJavascriptFunction(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2) override;
+ void CallJavascriptFunction(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3) override;
+ void CallJavascriptFunction(const std::string& function_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3,
+ const base::Value& arg4) override;
+ void CallJavascriptFunction(
const std::string& function_name,
- const std::vector<const base::Value*>& args) OVERRIDE;
+ const std::vector<const base::Value*>& args) override;
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
// IPC message handling.
@@ -99,7 +97,7 @@ class CONTENT_EXPORT WebUIImpl : public WebUI,
// Options that may be overridden by individual Web UI implementations. The
// bool options default to false. See the public getters for more information.
base::string16 overridden_title_; // Defaults to empty string.
- PageTransition link_transition_type_; // Defaults to LINK.
+ ui::PageTransition link_transition_type_; // Defaults to LINK.
int bindings_; // The bindings from BindingsPolicy that should be enabled for
// this page.
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 5007a8da6a0..9830f1df006 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -5,26 +5,30 @@
#include <limits>
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
-#include "base/path_service.h"
+#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/service_registry.h"
#include "content/public/common/url_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
-#include "grit/content_resources.h"
-#include "mojo/common/test/test_utils.h"
-#include "mojo/public/js/bindings/constants.h"
+#include "mojo/edk/test/test_utils.h"
+#include "mojo/public/cpp/bindings/interface_impl.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/js/constants.h"
namespace content {
namespace {
@@ -36,11 +40,13 @@ bool got_message = false;
bool GetResource(const std::string& id,
const WebUIDataSource::GotDataCallback& callback) {
// These are handled by the WebUIDataSource that AddMojoDataSource() creates.
- if (id == mojo::kCodecModuleName ||
+ if (id == mojo::kBufferModuleName ||
+ id == mojo::kCodecModuleName ||
id == mojo::kConnectionModuleName ||
id == mojo::kConnectorModuleName ||
id == mojo::kUnicodeModuleName ||
- id == mojo::kRouterModuleName)
+ id == mojo::kRouterModuleName ||
+ id == mojo::kValidatorModuleName)
return false;
std::string contents;
@@ -53,24 +59,16 @@ bool GetResource(const std::string& id,
return true;
}
-class BrowserTargetImpl : public BrowserTarget {
+class BrowserTargetImpl : public mojo::InterfaceImpl<BrowserTarget> {
public:
- BrowserTargetImpl(mojo::ScopedMessagePipeHandle handle,
- base::RunLoop* run_loop)
- : run_loop_(run_loop) {
- renderer_.Bind(handle.Pass());
- renderer_.set_client(this);
- }
+ explicit BrowserTargetImpl(base::RunLoop* run_loop) : run_loop_(run_loop) {}
- virtual ~BrowserTargetImpl() {}
+ ~BrowserTargetImpl() override {}
- // BrowserTarget overrides:
- virtual void PingResponse() OVERRIDE {
- NOTREACHED();
- }
+ // mojo::InterfaceImpl<BrowserTarget> overrides:
+ void PingResponse() override { NOTREACHED(); }
protected:
- RendererTargetPtr renderer_;
base::RunLoop* run_loop_;
private:
@@ -79,17 +77,16 @@ class BrowserTargetImpl : public BrowserTarget {
class PingBrowserTargetImpl : public BrowserTargetImpl {
public:
- PingBrowserTargetImpl(mojo::ScopedMessagePipeHandle handle,
- base::RunLoop* run_loop)
- : BrowserTargetImpl(handle.Pass(), run_loop) {
- renderer_->Ping();
- }
+ explicit PingBrowserTargetImpl(base::RunLoop* run_loop)
+ : BrowserTargetImpl(run_loop) {}
- virtual ~PingBrowserTargetImpl() {}
+ ~PingBrowserTargetImpl() override {}
+
+ // mojo::InterfaceImpl<BrowserTarget> overrides:
+ void OnConnectionEstablished() override { client()->Ping(); }
- // BrowserTarget overrides:
// Quit the RunLoop when called.
- virtual void PingResponse() OVERRIDE {
+ void PingResponse() override {
got_message = true;
run_loop_->Quit();
}
@@ -125,13 +122,18 @@ class PingTestWebUIController : public TestWebUIController {
PingTestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
: TestWebUIController(web_ui, run_loop) {
}
+ ~PingTestWebUIController() override {}
// WebUIController overrides:
- virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE {
- mojo::MessagePipe pipe;
- browser_target_.reset(
- new PingBrowserTargetImpl(pipe.handle0.Pass(), run_loop_));
- render_view_host->SetWebUIHandle(pipe.handle1.Pass());
+ void RenderViewCreated(RenderViewHost* render_view_host) override {
+ render_view_host->GetMainFrame()->GetServiceRegistry()->
+ AddService<BrowserTarget>(base::Bind(
+ &PingTestWebUIController::CreateHandler, base::Unretained(this)));
+ }
+
+ void CreateHandler(mojo::InterfaceRequest<BrowserTarget> request) {
+ browser_target_.reset(mojo::WeakBindToRequest(
+ new PingBrowserTargetImpl(run_loop_), &request));
}
private:
@@ -145,22 +147,22 @@ class TestWebUIControllerFactory : public WebUIControllerFactory {
void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const OVERRIDE {
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override {
if (url.query() == "ping")
return new PingTestWebUIController(web_ui, run_loop_);
return NULL;
}
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override {
return reinterpret_cast<WebUI::TypeID>(1);
}
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return true;
}
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return true;
}
@@ -176,7 +178,7 @@ class WebUIMojoTest : public ContentBrowserTest {
WebUIControllerFactory::RegisterFactory(&factory_);
}
- virtual ~WebUIMojoTest() {
+ ~WebUIMojoTest() override {
WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
}
@@ -212,6 +214,19 @@ IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEndPing) {
// RunLoop is quit when message received from page.
run_loop.Run();
EXPECT_TRUE(got_message);
+
+ // Check that a second render frame in the same renderer process works
+ // correctly.
+ Shell* other_shell = CreateBrowser();
+ got_message = false;
+ base::RunLoop other_run_loop;
+ factory()->set_run_loop(&other_run_loop);
+ NavigateToURL(other_shell, test_url);
+ // RunLoop is quit when message received from page.
+ other_run_loop.Run();
+ EXPECT_TRUE(got_message);
+ EXPECT_EQ(shell()->web_contents()->GetRenderProcessHost(),
+ other_shell->web_contents()->GetRenderProcessHost());
}
} // namespace
diff --git a/chromium/content/browser/worker.sb b/chromium/content/browser/worker.sb
deleted file mode 100644
index 2e408883e87..00000000000
--- a/chromium/content/browser/worker.sb
+++ /dev/null
@@ -1,12 +0,0 @@
-;;
-;; Copyright (c) 2011 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 is the Sandbox configuration file used for safeguarding the worker
-; process which is used to run web workers in a sandboxed environment.
-;
-; This is the most restrictive sandbox profile and only enables just enough
-; to allow basic use of Cocoa.
-
-; *** The contents of content/common/common.sb are implicitly included here. ***
diff --git a/chromium/content/browser/worker_host/OWNERS b/chromium/content/browser/worker_host/OWNERS
deleted file mode 100644
index 61fc3fd49ea..00000000000
--- a/chromium/content/browser/worker_host/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-atwilson@chromium.org
-kinuko@chromium.org
-horo@chromium.org
diff --git a/chromium/content/browser/worker_host/worker_document_set.cc b/chromium/content/browser/worker_host/worker_document_set.cc
deleted file mode 100644
index 3031493783e..00000000000
--- a/chromium/content/browser/worker_host/worker_document_set.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/worker_host/worker_document_set.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-WorkerDocumentSet::WorkerDocumentSet() {
-}
-
-void WorkerDocumentSet::Add(BrowserMessageFilter* parent,
- unsigned long long document_id,
- int render_process_id,
- int render_frame_id) {
- DocumentInfo info(parent, document_id, render_process_id, render_frame_id);
- document_set_.insert(info);
-}
-
-bool WorkerDocumentSet::Contains(BrowserMessageFilter* parent,
- unsigned long long document_id) const {
- for (DocumentInfoSet::const_iterator i = document_set_.begin();
- i != document_set_.end(); ++i) {
- if (i->filter() == parent && i->document_id() == document_id)
- return true;
- }
- return false;
-}
-
-bool WorkerDocumentSet::ContainsExternalRenderer(
- int worker_process_id) const {
- for (DocumentInfoSet::const_iterator i = document_set_.begin();
- i != document_set_.end(); ++i) {
- if (i->render_process_id() != worker_process_id)
- return true;
- }
- return false;
-}
-
-void WorkerDocumentSet::Remove(BrowserMessageFilter* parent,
- unsigned long long document_id) {
- for (DocumentInfoSet::iterator i = document_set_.begin();
- i != document_set_.end(); i++) {
- if (i->filter() == parent && i->document_id() == document_id) {
- document_set_.erase(i);
- break;
- }
- }
- // Should not be duplicate copies in the document set.
- DCHECK(!Contains(parent, document_id));
-}
-
-void WorkerDocumentSet::RemoveAll(BrowserMessageFilter* parent) {
- for (DocumentInfoSet::iterator i = document_set_.begin();
- i != document_set_.end();) {
-
- // Note this idiom is somewhat tricky - calling document_set_.erase(iter)
- // invalidates any iterators that point to the element being removed, so
- // bump the iterator beyond the item being removed before calling erase.
- if (i->filter() == parent) {
- DocumentInfoSet::iterator item_to_delete = i++;
- document_set_.erase(item_to_delete);
- } else {
- ++i;
- }
- }
-}
-
-WorkerDocumentSet::DocumentInfo::DocumentInfo(
- BrowserMessageFilter* filter, unsigned long long document_id,
- int render_process_id, int render_frame_id)
- : filter_(filter),
- document_id_(document_id),
- render_process_id_(render_process_id),
- render_frame_id_(render_frame_id) {
-}
-
-WorkerDocumentSet::~WorkerDocumentSet() {
-}
-
-} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_document_set.h b/chromium/content/browser/worker_host/worker_document_set.h
deleted file mode 100644
index e497aa80e53..00000000000
--- a/chromium/content/browser/worker_host/worker_document_set.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_WORKER_HOST_WORKER_DOCUMENT_SET_H_
-#define CONTENT_BROWSER_WORKER_HOST_WORKER_DOCUMENT_SET_H_
-
-#include <set>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-
-namespace content {
-class BrowserMessageFilter;
-
-// The WorkerDocumentSet tracks all of the DOM documents associated with a
-// set of workers. With nested workers, multiple workers can share the same
-// WorkerDocumentSet (meaning that they all share the same lifetime, and will
-// all exit when the last document in that set exits, per the WebWorkers spec).
-class WorkerDocumentSet : public base::RefCounted<WorkerDocumentSet> {
- public:
- WorkerDocumentSet();
-
- // The information we track for each document
- class DocumentInfo {
- public:
- DocumentInfo(BrowserMessageFilter* filter, unsigned long long document_id,
- int renderer_process_id, int render_frame_id);
- BrowserMessageFilter* filter() const { return filter_; }
- unsigned long long document_id() const { return document_id_; }
- int render_process_id() const { return render_process_id_; }
- int render_frame_id() const { return render_frame_id_; }
-
- // Define operator "<", which is used to determine uniqueness within
- // the set.
- bool operator <(const DocumentInfo& other) const {
- // Items are identical if the sender and document_id are identical,
- // otherwise create an arbitrary stable ordering based on the document
- // id/filter.
- if (filter() == other.filter()) {
- return document_id() < other.document_id();
- } else {
- return reinterpret_cast<unsigned long long>(filter()) <
- reinterpret_cast<unsigned long long>(other.filter());
- }
- }
-
- private:
- BrowserMessageFilter* filter_;
- unsigned long long document_id_;
- int render_process_id_;
- int render_frame_id_;
- };
-
- // Adds a document to a shared worker's document set. Also includes the
- // associated render_process_id the document is associated with, to enable
- // communication with the parent tab for things like http auth dialogs.
- void Add(BrowserMessageFilter* parent,
- unsigned long long document_id,
- int render_process_id,
- int render_frame_id);
-
- // Checks to see if a document is in a shared worker's document set.
- bool Contains(BrowserMessageFilter* parent,
- unsigned long long document_id) const;
-
- // Checks to see if the document set contains any documents which is
- // associated with other renderer process than worker_process_id.
- bool ContainsExternalRenderer(int worker_process_id) const;
-
- // Removes a specific document from a worker's document set when that document
- // is detached.
- void Remove(BrowserMessageFilter* parent, unsigned long long document_id);
-
- // Invoked when a render process exits, to remove all associated documents
- // from a worker's document set.
- void RemoveAll(BrowserMessageFilter* parent);
-
- bool IsEmpty() const { return document_set_.empty(); }
-
- // Define a typedef for convenience here when declaring iterators, etc.
- typedef std::set<DocumentInfo> DocumentInfoSet;
-
- // Returns the set of documents associated with this worker.
- const DocumentInfoSet& documents() { return document_set_; }
-
- private:
- friend class base::RefCounted<WorkerDocumentSet>;
- virtual ~WorkerDocumentSet();
-
- DocumentInfoSet document_set_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_DOCUMENT_SET_H_
diff --git a/chromium/content/browser/worker_host/worker_message_filter.cc b/chromium/content/browser/worker_host/worker_message_filter.cc
deleted file mode 100644
index 62348b5ff0b..00000000000
--- a/chromium/content/browser/worker_host/worker_message_filter.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2011 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 "content/browser/worker_host/worker_message_filter.h"
-
-#include "content/browser/message_port_message_filter.h"
-#include "content/browser/worker_host/worker_service_impl.h"
-#include "content/common/view_messages.h"
-#include "content/common/worker_messages.h"
-#include "content/public/browser/resource_context.h"
-
-namespace content {
-
-WorkerMessageFilter::WorkerMessageFilter(
- int render_process_id,
- ResourceContext* resource_context,
- const WorkerStoragePartition& partition,
- MessagePortMessageFilter* message_port_message_filter)
- : BrowserMessageFilter(ViewMsgStart),
- render_process_id_(render_process_id),
- resource_context_(resource_context),
- partition_(partition),
- message_port_message_filter_(message_port_message_filter) {
- // Note: This constructor is called on both IO or UI thread.
- DCHECK(resource_context);
-}
-
-WorkerMessageFilter::~WorkerMessageFilter() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-}
-
-void WorkerMessageFilter::OnChannelClosing() {
- WorkerServiceImpl::GetInstance()->OnWorkerMessageFilterClosing(this);
-}
-
-bool WorkerMessageFilter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WorkerMessageFilter, message)
- // Worker messages.
- // Only sent from renderer for now, until we have nested workers.
- IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker)
- IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, OnForwardToWorker)
- // Only sent from renderer.
- IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentDetached, OnDocumentDetached)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-int WorkerMessageFilter::GetNextRoutingID() {
- return message_port_message_filter_->GetNextRoutingID();
-}
-
-void WorkerMessageFilter::OnCreateWorker(
- const ViewHostMsg_CreateWorker_Params& params,
- int* route_id) {
- bool url_error = false;
- *route_id = GetNextRoutingID();
- WorkerServiceImpl::GetInstance()->CreateWorker(
- params, *route_id, this, resource_context_, partition_, &url_error);
- if (url_error)
- *route_id = MSG_ROUTING_NONE;
-}
-
-void WorkerMessageFilter::OnForwardToWorker(const IPC::Message& message) {
- WorkerServiceImpl::GetInstance()->ForwardToWorker(message, this);
-}
-
-void WorkerMessageFilter::OnDocumentDetached(unsigned long long document_id) {
- WorkerServiceImpl::GetInstance()->DocumentDetached(document_id, this);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_message_filter.h b/chromium/content/browser/worker_host/worker_message_filter.h
deleted file mode 100644
index ab9bade8e64..00000000000
--- a/chromium/content/browser/worker_host/worker_message_filter.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2011 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 CONTENT_BROWSER_WORKER_HOST_WORKER_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_WORKER_HOST_WORKER_MESSAGE_FILTER_H_
-
-#include "base/callback.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
-#include "content/public/browser/browser_message_filter.h"
-
-class ResourceDispatcherHost;
-struct ViewHostMsg_CreateWorker_Params;
-
-namespace content {
-class MessagePortMessageFilter;
-class ResourceContext;
-
-class WorkerMessageFilter : public BrowserMessageFilter {
- public:
- WorkerMessageFilter(int render_process_id,
- ResourceContext* resource_context,
- const WorkerStoragePartition& partition,
- MessagePortMessageFilter* message_port_filter);
-
- // BrowserMessageFilter implementation.
- virtual void OnChannelClosing() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- int GetNextRoutingID();
- int render_process_id() const { return render_process_id_; }
-
- MessagePortMessageFilter* message_port_message_filter() const {
- return message_port_message_filter_;
- }
-
- private:
- virtual ~WorkerMessageFilter();
-
- // Message handlers.
- void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params,
- int* route_id);
- void OnForwardToWorker(const IPC::Message& message);
- void OnDocumentDetached(unsigned long long document_id);
-
- int render_process_id_;
- ResourceContext* const resource_context_;
- WorkerStoragePartition partition_;
-
- MessagePortMessageFilter* message_port_message_filter_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(WorkerMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/worker_host/worker_process_host.cc b/chromium/content/browser/worker_host/worker_process_host.cc
deleted file mode 100644
index 81645f66732..00000000000
--- a/chromium/content/browser/worker_host/worker_process_host.cc
+++ /dev/null
@@ -1,830 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/worker_host/worker_process_host.h"
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/appcache/appcache_dispatcher_host.h"
-#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/browser/browser_child_process_host_impl.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/devtools/worker_devtools_manager.h"
-#include "content/browser/devtools/worker_devtools_message_filter.h"
-#include "content/browser/fileapi/fileapi_message_filter.h"
-#include "content/browser/frame_host/render_frame_host_delegate.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
-#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/message_port_message_filter.h"
-#include "content/browser/message_port_service.h"
-#include "content/browser/mime_registry_message_filter.h"
-#include "content/browser/quota_dispatcher_host.h"
-#include "content/browser/renderer_host/database_message_filter.h"
-#include "content/browser/renderer_host/file_utilities_message_filter.h"
-#include "content/browser/renderer_host/render_view_host_delegate.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
-#include "content/browser/renderer_host/websocket_dispatcher_host.h"
-#include "content/browser/resource_context_impl.h"
-#include "content/browser/worker_host/worker_message_filter.h"
-#include "content/browser/worker_host/worker_service_impl.h"
-#include "content/common/child_process_host_impl.h"
-#include "content/common/view_messages.h"
-#include "content/common/worker_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/user_metrics.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/result_codes.h"
-#include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "ipc/ipc_switches.h"
-#include "net/base/mime_util.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "ui/base/ui_base_switches.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/fileapi/sandbox_file_system_backend.h"
-#include "webkit/common/resource_type.h"
-
-#if defined(OS_WIN)
-#include "content/common/sandbox_win.h"
-#endif
-
-namespace content {
-namespace {
-
-// NOTE: changes to this class need to be reviewed by the security team.
-class WorkerSandboxedProcessLauncherDelegate
- : public content::SandboxedProcessLauncherDelegate {
- public:
- WorkerSandboxedProcessLauncherDelegate(ChildProcessHost* host,
- bool debugging_child)
-#if defined(OS_POSIX)
- : ipc_fd_(host->TakeClientFileDescriptor()),
- debugging_child_(debugging_child)
-#endif // OS_POSIX
- {}
-
- virtual ~WorkerSandboxedProcessLauncherDelegate() {}
-
-#if defined(OS_WIN)
- virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
- bool* success) {
- AddBaseHandleClosePolicy(policy);
- }
-#elif defined(OS_POSIX)
- virtual bool ShouldUseZygote() OVERRIDE {
- return !debugging_child_;
- }
- virtual int GetIpcFd() OVERRIDE {
- return ipc_fd_;
- }
-#endif // OS_WIN
-
- private:
-#if defined(OS_POSIX)
- int ipc_fd_;
- bool debugging_child_;
-#endif // OS_POSIX
-};
-
-// Notifies RenderViewHost that one or more worker objects crashed.
-void WorkerCrashCallback(int render_process_unique_id, int render_frame_id) {
- RenderFrameHostImpl* host =
- RenderFrameHostImpl::FromID(render_process_unique_id, render_frame_id);
- if (host)
- host->delegate()->WorkerCrashed(host);
-}
-
-void WorkerCreatedCallback(int render_process_id,
- int render_frame_id,
- int worker_process_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderFrameHost* render_frame_host =
- RenderFrameHost::FromID(render_process_id, render_frame_id);
- if (!render_frame_host)
- return;
- SiteInstance* site_instance = render_frame_host->GetSiteInstance();
- GetContentClient()->browser()->WorkerProcessCreated(site_instance,
- worker_process_id);
-}
-
-void WorkerTerminatedCallback(int render_process_id,
- int render_frame_id,
- int worker_process_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- RenderFrameHost* render_frame_host =
- RenderFrameHost::FromID(render_process_id, render_frame_id);
- if (!render_frame_host)
- return;
- SiteInstance* site_instance = render_frame_host->GetSiteInstance();
- GetContentClient()->browser()->WorkerProcessTerminated(site_instance,
- worker_process_id);
-}
-
-} // namespace
-
-WorkerProcessHost::WorkerProcessHost(
- ResourceContext* resource_context,
- const WorkerStoragePartition& partition)
- : resource_context_(resource_context),
- partition_(partition),
- process_launched_(false) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(resource_context_);
- process_.reset(
- new BrowserChildProcessHostImpl(PROCESS_TYPE_WORKER, this));
-}
-
-WorkerProcessHost::~WorkerProcessHost() {
- // If we crashed, tell the RenderViewHosts.
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- if (!i->load_failed()) {
- const WorkerDocumentSet::DocumentInfoSet& parents =
- i->worker_document_set()->documents();
- for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
- parents.begin(); parent_iter != parents.end(); ++parent_iter) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WorkerCrashCallback, parent_iter->render_process_id(),
- parent_iter->render_frame_id()));
- }
- }
- WorkerServiceImpl::GetInstance()->NotifyWorkerDestroyed(
- this, i->worker_route_id());
- }
-
- ChildProcessSecurityPolicyImpl::GetInstance()->Remove(
- process_->GetData().id);
-}
-
-bool WorkerProcessHost::Send(IPC::Message* message) {
- return process_->Send(message);
-}
-
-bool WorkerProcessHost::Init(int render_process_id, int render_frame_id) {
- std::string channel_id = process_->GetHost()->CreateChannel();
- if (channel_id.empty())
- return false;
-
-#if defined(OS_LINUX)
- int flags = ChildProcessHost::CHILD_ALLOW_SELF;
-#else
- int flags = ChildProcessHost::CHILD_NORMAL;
-#endif
-
- base::FilePath exe_path = ChildProcessHost::GetChildPath(flags);
- if (exe_path.empty())
- return false;
-
- CommandLine* cmd_line = new CommandLine(exe_path);
- cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kWorkerProcess);
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
- std::string locale = GetContentClient()->browser()->GetApplicationLocale();
- cmd_line->AppendSwitchASCII(switches::kLang, locale);
-
- static const char* const kSwitchNames[] = {
- switches::kDisableApplicationCache,
- switches::kDisableDatabases,
-#if defined(OS_WIN)
- switches::kDisableDesktopNotifications,
-#endif
- switches::kDisableFileSystem,
- switches::kDisableSeccompFilterSandbox,
- switches::kEnableExperimentalWebPlatformFeatures,
- switches::kEnablePreciseMemoryInfo,
- switches::kEnableServiceWorker,
-#if defined(OS_MACOSX)
- switches::kEnableSandboxLogging,
-#endif
- switches::kJavaScriptFlags,
- switches::kNoSandbox
- };
- cmd_line->CopySwitchesFrom(*CommandLine::ForCurrentProcess(), kSwitchNames,
- arraysize(kSwitchNames));
-
-bool debugging_child = false;
-#if defined(OS_POSIX)
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kWaitForDebuggerChildren)) {
- // Look to pass-on the kWaitForDebugger flag.
- std::string value = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kWaitForDebuggerChildren);
- if (value.empty() || value == switches::kWorkerProcess) {
- cmd_line->AppendSwitch(switches::kWaitForDebugger);
- debugging_child = true;
- }
- }
-#endif
-
- process_->Launch(
- new WorkerSandboxedProcessLauncherDelegate(process_->GetHost(),
- debugging_child),
- cmd_line);
-
- ChildProcessSecurityPolicyImpl::GetInstance()->AddWorker(
- process_->GetData().id, render_process_id);
- CreateMessageFilters(render_process_id);
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WorkerCreatedCallback,
- render_process_id,
- render_frame_id,
- process_->GetData().id));
- return true;
-}
-
-void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
- ChromeBlobStorageContext* blob_storage_context =
- GetChromeBlobStorageContextForResourceContext(resource_context_);
- StreamContext* stream_context =
- GetStreamContextForResourceContext(resource_context_);
-
- net::URLRequestContextGetter* url_request_context =
- partition_.url_request_context();
-
- ResourceMessageFilter::GetContextsCallback get_contexts_callback(
- base::Bind(&WorkerProcessHost::GetContexts,
- base::Unretained(this)));
-
- ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
- process_->GetData().id, PROCESS_TYPE_WORKER,
- partition_.appcache_service(),
- blob_storage_context,
- partition_.filesystem_context(),
- partition_.service_worker_context(),
- get_contexts_callback);
- process_->AddFilter(resource_message_filter);
-
- MessagePortMessageFilter* message_port_message_filter =
- new MessagePortMessageFilter(
- base::Bind(&WorkerServiceImpl::next_worker_route_id,
- base::Unretained(WorkerServiceImpl::GetInstance())));
- process_->AddFilter(message_port_message_filter);
- worker_message_filter_ = new WorkerMessageFilter(render_process_id,
- resource_context_,
- partition_,
- message_port_message_filter);
- process_->AddFilter(worker_message_filter_.get());
- process_->AddFilter(new AppCacheDispatcherHost(
- partition_.appcache_service(), process_->GetData().id));
- process_->AddFilter(new FileAPIMessageFilter(
- process_->GetData().id,
- url_request_context,
- partition_.filesystem_context(),
- blob_storage_context,
- stream_context));
- process_->AddFilter(new FileUtilitiesMessageFilter(
- process_->GetData().id));
- process_->AddFilter(new MimeRegistryMessageFilter());
- process_->AddFilter(new DatabaseMessageFilter(partition_.database_tracker()));
- process_->AddFilter(new QuotaDispatcherHost(
- process_->GetData().id,
- partition_.quota_manager(),
- GetContentClient()->browser()->CreateQuotaPermissionContext()));
-
- SocketStreamDispatcherHost::GetRequestContextCallback
- request_context_callback(
- base::Bind(&WorkerProcessHost::GetRequestContext,
- base::Unretained(this)));
-
- SocketStreamDispatcherHost* socket_stream_dispatcher_host =
- new SocketStreamDispatcherHost(
- render_process_id,
- request_context_callback,
- resource_context_);
- socket_stream_dispatcher_host_ = socket_stream_dispatcher_host;
- process_->AddFilter(socket_stream_dispatcher_host);
-
- WebSocketDispatcherHost::GetRequestContextCallback
- websocket_request_context_callback(
- base::Bind(&WorkerProcessHost::GetRequestContext,
- base::Unretained(this),
- ResourceType::SUB_RESOURCE));
-
- process_->AddFilter(new WebSocketDispatcherHost(
- render_process_id, websocket_request_context_callback));
-
- process_->AddFilter(new WorkerDevToolsMessageFilter(process_->GetData().id));
- process_->AddFilter(
- new IndexedDBDispatcherHost(process_->GetData().id,
- url_request_context,
- partition_.indexed_db_context(),
- blob_storage_context));
-}
-
-void WorkerProcessHost::CreateWorker(const WorkerInstance& instance,
- bool pause_on_start) {
- ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
- process_->GetData().id, instance.url());
-
- instances_.push_back(instance);
-
- WorkerProcessMsg_CreateWorker_Params params;
- params.url = instance.url();
- params.name = instance.name();
- params.content_security_policy = instance.content_security_policy();
- params.security_policy_type = instance.security_policy_type();
- params.pause_on_start = pause_on_start;
- params.route_id = instance.worker_route_id();
- Send(new WorkerProcessMsg_CreateWorker(params));
-
- UpdateTitle();
-
- // Walk all pending filters and let them know the worker has been created
- // (could be more than one in the case where we had to queue up worker
- // creation because the worker process limit was reached).
- for (WorkerInstance::FilterList::const_iterator i =
- instance.filters().begin();
- i != instance.filters().end(); ++i) {
- i->filter()->Send(new ViewMsg_WorkerCreated(i->route_id()));
- }
-}
-
-bool WorkerProcessHost::FilterMessage(const IPC::Message& message,
- WorkerMessageFilter* filter) {
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- if (!i->closed() && i->HasFilter(filter, message.routing_id())) {
- RelayMessage(message, filter, &(*i));
- return true;
- }
- }
-
- return false;
-}
-
-void WorkerProcessHost::OnProcessLaunched() {
- process_launched_ = true;
-
- WorkerServiceImpl::GetInstance()->NotifyWorkerProcessCreated();
-}
-
-bool WorkerProcessHost::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WorkerProcessHost, message)
- IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed,
- OnWorkerContextClosed)
- IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextDestroyed,
- OnWorkerContextDestroyed)
- IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerScriptLoaded,
- OnWorkerScriptLoaded)
- IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerScriptLoadFailed,
- OnWorkerScriptLoadFailed)
- IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerConnected,
- OnWorkerConnected)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_RequestFileSystemAccessSync,
- OnRequestFileSystemAccessSync)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowIndexedDB, OnAllowIndexedDB)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_ForceKillWorker,
- OnForceKillWorkerProcess)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-// Sent to notify the browser process when a worker context invokes close(), so
-// no new connections are sent to shared workers.
-void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) {
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- if (i->worker_route_id() == worker_route_id) {
- // Set the closed flag - this will stop any further messages from
- // being sent to the worker (messages can still be sent from the worker,
- // for exception reporting, etc).
- i->set_closed(true);
- break;
- }
- }
-}
-
-void WorkerProcessHost::OnWorkerContextDestroyed(int worker_route_id) {
- WorkerServiceImpl::GetInstance()->NotifyWorkerDestroyed(
- this, worker_route_id);
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- if (i->worker_route_id() == worker_route_id) {
- instances_.erase(i);
- UpdateTitle();
- return;
- }
- }
-}
-
-void WorkerProcessHost::OnWorkerScriptLoaded(int worker_route_id) {
- WorkerDevToolsManager::GetInstance()->WorkerContextStarted(this,
- worker_route_id);
-}
-
-void WorkerProcessHost::OnWorkerScriptLoadFailed(int worker_route_id) {
- bool shutdown = true;
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- if (i->worker_route_id() != worker_route_id) {
- shutdown = false;
- continue;
- }
- i->set_load_failed(true);
- for (WorkerInstance::FilterList::const_iterator j = i->filters().begin();
- j != i->filters().end(); ++j) {
- j->filter()->Send(new ViewMsg_WorkerScriptLoadFailed(j->route_id()));
- }
- }
- if (shutdown) {
- base::KillProcess(
- process_->GetData().handle, RESULT_CODE_NORMAL_EXIT, false);
- }
-}
-
-void WorkerProcessHost::OnWorkerConnected(int message_port_id,
- int worker_route_id) {
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- if (i->worker_route_id() != worker_route_id)
- continue;
- for (WorkerInstance::FilterList::const_iterator j = i->filters().begin();
- j != i->filters().end(); ++j) {
- if (j->message_port_id() != message_port_id)
- continue;
- j->filter()->Send(new ViewMsg_WorkerConnected(j->route_id()));
- return;
- }
- }
-}
-
-void WorkerProcessHost::OnAllowDatabase(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result) {
- *result = GetContentClient()->browser()->AllowWorkerDatabase(
- url, name, display_name, estimated_size, resource_context_,
- GetRenderFrameIDsForWorker(worker_route_id));
-}
-
-void WorkerProcessHost::OnRequestFileSystemAccessSync(int worker_route_id,
- const GURL& url,
- bool* result) {
- *result = GetContentClient()->browser()->AllowWorkerFileSystem(
- url, resource_context_, GetRenderFrameIDsForWorker(worker_route_id));
-}
-
-void WorkerProcessHost::OnAllowIndexedDB(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- bool* result) {
- *result = GetContentClient()->browser()->AllowWorkerIndexedDB(
- url, name, resource_context_,
- GetRenderFrameIDsForWorker(worker_route_id));
-}
-
-void WorkerProcessHost::OnForceKillWorkerProcess() {
- if (process_ && process_launched_)
- base::KillProcess(
- process_->GetData().handle, RESULT_CODE_NORMAL_EXIT, false);
- else
- RecordAction(base::UserMetricsAction("WorkerProcess_BadProcessToKill"));
-}
-
-void WorkerProcessHost::RelayMessage(
- const IPC::Message& message,
- WorkerMessageFilter* incoming_filter,
- WorkerInstance* instance) {
- if (message.type() == WorkerMsg_Connect::ID) {
- // Crack the SharedWorker Connect message to setup routing for the port.
- WorkerMsg_Connect::Param params;
- if (!WorkerMsg_Connect::Read(&message, &params))
- return;
-
- int sent_message_port_id = params.a;
- int new_routing_id = params.b;
- new_routing_id = worker_message_filter_->GetNextRoutingID();
- MessagePortService::GetInstance()->UpdateMessagePort(
- sent_message_port_id,
- worker_message_filter_->message_port_message_filter(),
- new_routing_id);
-
- instance->SetMessagePortID(incoming_filter,
- message.routing_id(),
- sent_message_port_id);
- // Resend the message with the new routing id.
- worker_message_filter_->Send(new WorkerMsg_Connect(
- instance->worker_route_id(), sent_message_port_id, new_routing_id));
-
- // Send any queued messages for the sent port.
- MessagePortService::GetInstance()->SendQueuedMessagesIfPossible(
- sent_message_port_id);
- } else {
- IPC::Message* new_message = new IPC::Message(message);
- new_message->set_routing_id(instance->worker_route_id());
- worker_message_filter_->Send(new_message);
- return;
- }
-}
-
-void WorkerProcessHost::ShutdownSocketStreamDispatcherHostIfNecessary() {
- if (!instances_.size() && socket_stream_dispatcher_host_.get()) {
- // We can assume that this object is going to delete, because
- // currently a WorkerInstance will never be added to a WorkerProcessHost
- // once it is initialized.
-
- // SocketStreamDispatcherHost should be notified now that the worker
- // process will shutdown soon.
- socket_stream_dispatcher_host_->Shutdown();
- socket_stream_dispatcher_host_ = NULL;
- }
-}
-
-void WorkerProcessHost::FilterShutdown(WorkerMessageFilter* filter) {
- for (Instances::iterator i = instances_.begin(); i != instances_.end();) {
- bool shutdown = false;
- i->RemoveFilters(filter);
-
- int render_frame_id = 0;
- const WorkerDocumentSet::DocumentInfoSet& documents =
- i->worker_document_set()->documents();
- for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc =
- documents.begin(); doc != documents.end(); ++doc) {
- if (doc->filter() == filter) {
- render_frame_id = doc->render_frame_id();
- break;
- }
- }
- i->worker_document_set()->RemoveAll(filter);
- if (i->worker_document_set()->IsEmpty()) {
- shutdown = true;
- }
- if (shutdown) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WorkerTerminatedCallback,
- filter->render_process_id(),
- render_frame_id,
- process_->GetData().id));
- Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id()));
- i = instances_.erase(i);
- } else {
- ++i;
- }
- }
- ShutdownSocketStreamDispatcherHostIfNecessary();
-}
-
-bool WorkerProcessHost::CanShutdown() {
- return instances_.empty();
-}
-
-void WorkerProcessHost::UpdateTitle() {
- std::set<std::string> titles;
- for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- // Allow the embedder first crack at special casing the title.
- std::string title = GetContentClient()->browser()->
- GetWorkerProcessTitle(i->url(), resource_context_);
-
- if (title.empty()) {
- title = net::registry_controlled_domains::GetDomainAndRegistry(
- i->url(),
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- }
-
- // Use the host name if the domain is empty, i.e. localhost or IP address.
- if (title.empty())
- title = i->url().host();
-
- // If the host name is empty, i.e. file url, use the path.
- if (title.empty())
- title = i->url().path();
- titles.insert(title);
- }
-
- std::string display_title;
- for (std::set<std::string>::iterator i = titles.begin();
- i != titles.end(); ++i) {
- if (!display_title.empty())
- display_title += ", ";
- display_title += *i;
- }
-
- process_->SetName(base::UTF8ToUTF16(display_title));
-}
-
-void WorkerProcessHost::DocumentDetached(WorkerMessageFilter* filter,
- unsigned long long document_id) {
- // Walk all instances and remove the document from their document set.
- for (Instances::iterator i = instances_.begin(); i != instances_.end();) {
- int render_frame_id = 0;
- const WorkerDocumentSet::DocumentInfoSet& documents =
- i->worker_document_set()->documents();
- for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc =
- documents.begin(); doc != documents.end(); ++doc) {
- if (doc->filter() == filter && doc->document_id() == document_id) {
- render_frame_id = doc->render_frame_id();
- break;
- }
- }
- i->worker_document_set()->Remove(filter, document_id);
- if (i->worker_document_set()->IsEmpty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WorkerTerminatedCallback,
- filter->render_process_id(),
- render_frame_id,
- process_->GetData().id));
- // This worker has no more associated documents - shut it down.
- Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id()));
- i = instances_.erase(i);
- } else {
- ++i;
- }
- }
- ShutdownSocketStreamDispatcherHostIfNecessary();
-}
-
-void WorkerProcessHost::TerminateWorker(int worker_route_id) {
- Send(new WorkerMsg_TerminateWorkerContext(worker_route_id));
-}
-
-void WorkerProcessHost::SetBackgrounded(bool backgrounded) {
- process_->SetBackgrounded(backgrounded);
-}
-
-const ChildProcessData& WorkerProcessHost::GetData() {
- return process_->GetData();
-}
-
-std::vector<std::pair<int, int> > WorkerProcessHost::GetRenderFrameIDsForWorker(
- int worker_route_id) {
- std::vector<std::pair<int, int> > result;
- WorkerProcessHost::Instances::const_iterator i;
- for (i = instances_.begin(); i != instances_.end(); ++i) {
- if (i->worker_route_id() != worker_route_id)
- continue;
- const WorkerDocumentSet::DocumentInfoSet& documents =
- i->worker_document_set()->documents();
- for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc =
- documents.begin(); doc != documents.end(); ++doc) {
- result.push_back(
- std::make_pair(doc->render_process_id(), doc->render_frame_id()));
- }
- break;
- }
- return result;
-}
-
-void WorkerProcessHost::GetContexts(const ResourceHostMsg_Request& request,
- ResourceContext** resource_context,
- net::URLRequestContext** request_context) {
- *resource_context = resource_context_;
- *request_context = partition_.url_request_context()->GetURLRequestContext();
-}
-
-net::URLRequestContext* WorkerProcessHost::GetRequestContext(
- ResourceType::Type resource_type) {
- return partition_.url_request_context()->GetURLRequestContext();
-}
-
-WorkerProcessHost::WorkerInstance::WorkerInstance(
- const GURL& url,
- const base::string16& name,
- const base::string16& content_security_policy,
- blink::WebContentSecurityPolicyType security_policy_type,
- int worker_route_id,
- int render_frame_id,
- ResourceContext* resource_context,
- const WorkerStoragePartition& partition)
- : url_(url),
- closed_(false),
- name_(name),
- content_security_policy_(content_security_policy),
- security_policy_type_(security_policy_type),
- worker_route_id_(worker_route_id),
- render_frame_id_(render_frame_id),
- worker_document_set_(new WorkerDocumentSet()),
- resource_context_(resource_context),
- partition_(partition),
- load_failed_(false) {
- DCHECK(resource_context_);
-}
-
-WorkerProcessHost::WorkerInstance::~WorkerInstance() {
-}
-
-void WorkerProcessHost::WorkerInstance::SetMessagePortID(
- WorkerMessageFilter* filter,
- int route_id,
- int message_port_id) {
- for (FilterList::iterator i = filters_.begin(); i != filters_.end(); ++i) {
- if (i->filter() == filter && i->route_id() == route_id) {
- i->set_message_port_id(message_port_id);
- return;
- }
- }
-}
-
-// Compares an instance based on the algorithm in the WebWorkers spec - an
-// instance matches if the origins of the URLs match, and:
-// a) the names are non-empty and equal
-// -or-
-// b) the names are both empty, and the urls are equal
-bool WorkerProcessHost::WorkerInstance::Matches(
- const GURL& match_url,
- const base::string16& match_name,
- const WorkerStoragePartition& partition,
- ResourceContext* resource_context) const {
- // Only match open shared workers.
- if (closed_)
- return false;
-
- // ResourceContext equivalence is being used as a proxy to ensure we only
- // matched shared workers within the same BrowserContext.
- if (resource_context_ != resource_context)
- return false;
-
- // We must be in the same storage partition otherwise sharing will violate
- // isolation.
- if (!partition_.Equals(partition))
- return false;
-
- if (url_.GetOrigin() != match_url.GetOrigin())
- return false;
-
- if (name_.empty() && match_name.empty())
- return url_ == match_url;
-
- return name_ == match_name;
-}
-
-void WorkerProcessHost::WorkerInstance::AddFilter(WorkerMessageFilter* filter,
- int route_id) {
- CHECK(filter);
- if (!HasFilter(filter, route_id)) {
- FilterInfo info(filter, route_id);
- filters_.push_back(info);
- }
-}
-
-void WorkerProcessHost::WorkerInstance::RemoveFilter(
- WorkerMessageFilter* filter, int route_id) {
- for (FilterList::iterator i = filters_.begin(); i != filters_.end();) {
- if (i->filter() == filter && i->route_id() == route_id)
- i = filters_.erase(i);
- else
- ++i;
- }
- // Should not be duplicate copies in the filter set.
- DCHECK(!HasFilter(filter, route_id));
-}
-
-void WorkerProcessHost::WorkerInstance::RemoveFilters(
- WorkerMessageFilter* filter) {
- for (FilterList::iterator i = filters_.begin(); i != filters_.end();) {
- if (i->filter() == filter)
- i = filters_.erase(i);
- else
- ++i;
- }
-}
-
-bool WorkerProcessHost::WorkerInstance::HasFilter(
- WorkerMessageFilter* filter, int route_id) const {
- for (FilterList::const_iterator i = filters_.begin(); i != filters_.end();
- ++i) {
- if (i->filter() == filter && i->route_id() == route_id)
- return true;
- }
- return false;
-}
-
-bool WorkerProcessHost::WorkerInstance::FrameIsParent(
- int render_process_id, int render_frame_id) const {
- const WorkerDocumentSet::DocumentInfoSet& parents =
- worker_document_set()->documents();
- for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
- parents.begin();
- parent_iter != parents.end(); ++parent_iter) {
- if (parent_iter->render_process_id() == render_process_id &&
- parent_iter->render_frame_id() == render_frame_id) {
- return true;
- }
- }
- return false;
-}
-
-WorkerProcessHost::WorkerInstance::FilterInfo
-WorkerProcessHost::WorkerInstance::GetFilter() const {
- DCHECK(NumFilters() == 1);
- return *filters_.begin();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_process_host.h b/chromium/content/browser/worker_host/worker_process_host.h
deleted file mode 100644
index 150153139fe..00000000000
--- a/chromium/content/browser/worker_host/worker_process_host.h
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_WORKER_HOST_WORKER_PROCESS_HOST_H_
-#define CONTENT_BROWSER_WORKER_HOST_WORKER_PROCESS_HOST_H_
-
-#include <list>
-#include <string>
-#include <utility>
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/worker_host/worker_document_set.h"
-#include "content/browser/worker_host/worker_storage_partition.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_child_process_host_delegate.h"
-#include "content/public/browser/browser_child_process_host_iterator.h"
-#include "content/public/common/process_type.h"
-#include "ipc/ipc_sender.h"
-#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
-#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
-
-struct ResourceHostMsg_Request;
-
-namespace fileapi {
-class FileSystemContext;
-} // namespace fileapi
-
-namespace net {
-class URLRequestContext;
-}
-
-namespace webkit_database {
-class DatabaseTracker;
-} // namespace webkit_database
-
-namespace content {
-class BrowserChildProcessHostImpl;
-class IndexedDBContextImpl;
-class ResourceContext;
-class SocketStreamDispatcherHost;
-class WorkerMessageFilter;
-class WorkerServiceImpl;
-
-// The WorkerProcessHost is the interface that represents the browser side of
-// the browser <-> worker communication channel. There will be one
-// WorkerProcessHost per worker process. Currently each worker runs in its own
-// process, but that may change. However, we do assume (by storing a
-// net::URLRequestContext) that a WorkerProcessHost serves a single
-// BrowserContext.
-class WorkerProcessHost : public BrowserChildProcessHostDelegate,
- public IPC::Sender {
- public:
- // Contains information about each worker instance, needed to forward messages
- // between the renderer and worker processes.
- class WorkerInstance {
- public:
- WorkerInstance(const GURL& url,
- const base::string16& name,
- const base::string16& content_security_policy,
- blink::WebContentSecurityPolicyType security_policy_type,
- int worker_route_id,
- int render_frame_id,
- ResourceContext* resource_context,
- const WorkerStoragePartition& partition);
- ~WorkerInstance();
-
- // Unique identifier for a worker client.
- class FilterInfo {
- public:
- FilterInfo(WorkerMessageFilter* filter, int route_id)
- : filter_(filter), route_id_(route_id), message_port_id_(0) { }
- WorkerMessageFilter* filter() const { return filter_; }
- int route_id() const { return route_id_; }
- int message_port_id() const { return message_port_id_; }
- void set_message_port_id(int id) { message_port_id_ = id; }
-
- private:
- WorkerMessageFilter* filter_;
- int route_id_;
- int message_port_id_;
- };
-
- // APIs to manage the filter list for a given instance.
- void AddFilter(WorkerMessageFilter* filter, int route_id);
- void RemoveFilter(WorkerMessageFilter* filter, int route_id);
- void RemoveFilters(WorkerMessageFilter* filter);
- bool HasFilter(WorkerMessageFilter* filter, int route_id) const;
- bool FrameIsParent(int render_process_id, int render_frame_id) const;
- int NumFilters() const { return filters_.size(); }
- void SetMessagePortID(WorkerMessageFilter* filter,
- int route_id,
- int message_port_id);
- // Returns the single filter (must only be one).
- FilterInfo GetFilter() const;
-
- typedef std::list<FilterInfo> FilterList;
- const FilterList& filters() const { return filters_; }
-
- // Checks if this WorkerInstance matches the passed url/name params
- // (per the comparison algorithm in the WebWorkers spec). This API only
- // applies to shared workers.
- bool Matches(
- const GURL& url,
- const base::string16& name,
- const WorkerStoragePartition& partition,
- ResourceContext* resource_context) const;
-
- // Shares the passed instance's WorkerDocumentSet with this instance. This
- // instance's current WorkerDocumentSet is dereferenced (and freed if this
- // is the only reference) as a result.
- void ShareDocumentSet(const WorkerInstance& instance) {
- worker_document_set_ = instance.worker_document_set_;
- };
-
- // Accessors
- bool closed() const { return closed_; }
- void set_closed(bool closed) { closed_ = closed; }
- const GURL& url() const { return url_; }
- const base::string16 name() const { return name_; }
- const base::string16 content_security_policy() const {
- return content_security_policy_;
- }
- blink::WebContentSecurityPolicyType security_policy_type() const {
- return security_policy_type_;
- }
- int worker_route_id() const { return worker_route_id_; }
- int render_frame_id() const { return render_frame_id_; }
- WorkerDocumentSet* worker_document_set() const {
- return worker_document_set_.get();
- }
- ResourceContext* resource_context() const {
- return resource_context_;
- }
- const WorkerStoragePartition& partition() const {
- return partition_;
- }
- void set_load_failed(bool failed) { load_failed_ = failed; }
- bool load_failed() { return load_failed_; }
-
- private:
- // Set of all filters (clients) associated with this worker.
- GURL url_;
- bool closed_;
- base::string16 name_;
- base::string16 content_security_policy_;
- blink::WebContentSecurityPolicyType security_policy_type_;
- int worker_route_id_;
- int render_frame_id_;
- FilterList filters_;
- scoped_refptr<WorkerDocumentSet> worker_document_set_;
- ResourceContext* const resource_context_;
- WorkerStoragePartition partition_;
- bool load_failed_;
- };
-
- WorkerProcessHost(ResourceContext* resource_context,
- const WorkerStoragePartition& partition);
- virtual ~WorkerProcessHost();
-
- // IPC::Sender implementation:
- virtual bool Send(IPC::Message* message) OVERRIDE;
-
- // Starts the process. Returns true iff it succeeded.
- // |render_process_id| and |render_frame_id| are the renderer process and the
- // renderer frame responsible for starting this worker.
- bool Init(int render_process_id, int render_frame_id);
-
- // Creates a worker object in the process.
- void CreateWorker(const WorkerInstance& instance, bool pause_on_start);
-
- // Returns true iff the given message from a renderer process was forwarded to
- // the worker.
- bool FilterMessage(const IPC::Message& message, WorkerMessageFilter* filter);
-
- void FilterShutdown(WorkerMessageFilter* filter);
-
- // Shuts down any shared workers that are no longer referenced by active
- // documents.
- void DocumentDetached(WorkerMessageFilter* filter,
- unsigned long long document_id);
-
- // Terminates the given worker, i.e. based on a UI action.
- CONTENT_EXPORT void TerminateWorker(int worker_route_id);
-
- // Callers can reduce the WorkerProcess' priority.
- void SetBackgrounded(bool backgrounded);
-
- CONTENT_EXPORT const ChildProcessData& GetData();
-
- typedef std::list<WorkerInstance> Instances;
- const Instances& instances() const { return instances_; }
-
- ResourceContext* resource_context() const {
- return resource_context_;
- }
-
- bool process_launched() const { return process_launched_; }
-
- protected:
- friend class WorkerServiceImpl;
-
- Instances& mutable_instances() { return instances_; }
-
- private:
- // BrowserChildProcessHostDelegate implementation:
- virtual void OnProcessLaunched() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // Creates and adds the message filters.
- void CreateMessageFilters(int render_process_id);
-
- void OnWorkerContextClosed(int worker_route_id);
- void OnWorkerContextDestroyed(int worker_route_id);
- void OnWorkerScriptLoaded(int worker_route_id);
- void OnWorkerScriptLoadFailed(int worker_route_id);
- void OnWorkerConnected(int message_port_id, int worker_route_id);
- void OnAllowDatabase(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result);
- void OnRequestFileSystemAccessSync(int worker_route_id,
- const GURL& url,
- bool* result);
- void OnAllowIndexedDB(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- bool* result);
- void OnForceKillWorkerProcess();
-
- // Relays a message to the given endpoint. Takes care of parsing the message
- // if it contains a message port and sending it a valid route id.
- void RelayMessage(const IPC::Message& message,
- WorkerMessageFilter* incoming_filter,
- WorkerInstance* instance);
-
- void ShutdownSocketStreamDispatcherHostIfNecessary();
-
- virtual bool CanShutdown() OVERRIDE;
-
- // Updates the title shown in the task manager.
- void UpdateTitle();
-
- // Return a vector of all the render process/render frame IDs that use the
- // given worker.
- std::vector<std::pair<int, int> > GetRenderFrameIDsForWorker(int route_id);
-
- // Callbacks for ResourceMessageFilter and SocketStreamDispatcherHost.
- void GetContexts(const ResourceHostMsg_Request& request,
- ResourceContext** resource_context,
- net::URLRequestContext** request_context);
- net::URLRequestContext* GetRequestContext(ResourceType::Type resource_type);
-
- Instances instances_;
-
- ResourceContext* const resource_context_;
- WorkerStoragePartition partition_;
-
- // A reference to the filter associated with this worker process. We need to
- // keep this around since we'll use it when forward messages to the worker
- // process.
- scoped_refptr<WorkerMessageFilter> worker_message_filter_;
-
- scoped_ptr<BrowserChildProcessHostImpl> process_;
- bool process_launched_;
-
- scoped_refptr<SocketStreamDispatcherHost> socket_stream_dispatcher_host_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerProcessHost);
-};
-
-class WorkerProcessHostIterator
- : public BrowserChildProcessHostTypeIterator<WorkerProcessHost> {
- public:
- WorkerProcessHostIterator()
- : BrowserChildProcessHostTypeIterator<WorkerProcessHost>(
- PROCESS_TYPE_WORKER) {
- }
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_PROCESS_HOST_H_
diff --git a/chromium/content/browser/worker_host/worker_service_impl.cc b/chromium/content/browser/worker_host/worker_service_impl.cc
deleted file mode 100644
index 4636777e1ce..00000000000
--- a/chromium/content/browser/worker_host/worker_service_impl.cc
+++ /dev/null
@@ -1,600 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/worker_host/worker_service_impl.h"
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/threading/thread.h"
-#include "content/browser/devtools/worker_devtools_manager.h"
-#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/browser/shared_worker/shared_worker_service_impl.h"
-#include "content/browser/worker_host/worker_message_filter.h"
-#include "content/browser/worker_host/worker_process_host.h"
-#include "content/common/view_messages.h"
-#include "content/common/worker_messages.h"
-#include "content/public/browser/child_process_data.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
-#include "content/public/browser/render_widget_host_iterator.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/resource_context.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/worker_service_observer.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/process_type.h"
-
-namespace content {
-
-namespace {
-void AddRenderFrameID(std::set<std::pair<int, int> >* visible_frame_ids,
- RenderFrameHost* rfh) {
- visible_frame_ids->insert(
- std::pair<int, int>(rfh->GetProcess()->GetID(),
- rfh->GetRoutingID()));
-}
-}
-
-const int WorkerServiceImpl::kMaxWorkersWhenSeparate = 64;
-const int WorkerServiceImpl::kMaxWorkersPerFrameWhenSeparate = 16;
-
-class WorkerPrioritySetter
- : public NotificationObserver,
- public base::RefCountedThreadSafe<WorkerPrioritySetter,
- BrowserThread::DeleteOnUIThread> {
- public:
- WorkerPrioritySetter();
-
- // Posts a task to the UI thread to register to receive notifications.
- void Initialize();
-
- // Invoked by WorkerServiceImpl when a worker process is created.
- void NotifyWorkerProcessCreated();
-
- private:
- friend class base::RefCountedThreadSafe<WorkerPrioritySetter>;
- friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
- friend class base::DeleteHelper<WorkerPrioritySetter>;
- virtual ~WorkerPrioritySetter();
-
- // Posts a task to perform a worker priority update.
- void PostTaskToGatherAndUpdateWorkerPriorities();
-
- // Gathers up a list of the visible tabs and then updates priorities for
- // all the shared workers.
- void GatherVisibleIDsAndUpdateWorkerPriorities();
-
- // Registers as an observer to receive notifications about
- // widgets being shown.
- void RegisterObserver();
-
- // Sets priorities for shared workers given a set of visible frames (as a
- // std::set of std::pair<render_process, render_frame> ids.
- void UpdateWorkerPrioritiesFromVisibleSet(
- const std::set<std::pair<int, int> >* visible);
-
- // Called to refresh worker priorities when focus changes between tabs.
- void OnRenderWidgetVisibilityChanged(std::pair<int, int>);
-
- // NotificationObserver implementation.
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) OVERRIDE;
-
- NotificationRegistrar registrar_;
-};
-
-WorkerPrioritySetter::WorkerPrioritySetter() {
-}
-
-WorkerPrioritySetter::~WorkerPrioritySetter() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void WorkerPrioritySetter::Initialize() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&WorkerPrioritySetter::RegisterObserver, this));
-}
-
-void WorkerPrioritySetter::NotifyWorkerProcessCreated() {
- PostTaskToGatherAndUpdateWorkerPriorities();
-}
-
-void WorkerPrioritySetter::PostTaskToGatherAndUpdateWorkerPriorities() {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities,
- this));
-}
-
-void WorkerPrioritySetter::GatherVisibleIDsAndUpdateWorkerPriorities() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- std::set<std::pair<int, int> >* visible_frame_ids =
- new std::set<std::pair<int, int> >();
-
- // Gather up all the visible renderer process/view pairs
- scoped_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHost::GetRenderWidgetHosts());
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- if (widget->GetProcess()->VisibleWidgetCount() == 0)
- continue;
- if (!widget->IsRenderView())
- continue;
-
- RenderWidgetHostView* widget_view = widget->GetView();
- if (!widget_view || !widget_view->IsShowing())
- continue;
- RenderViewHost* rvh = RenderViewHost::From(widget);
- WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
- if (!web_contents)
- continue;
- web_contents->ForEachFrame(
- base::Bind(&AddRenderFrameID, visible_frame_ids));
- }
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet,
- this, base::Owned(visible_frame_ids)));
-}
-
-void WorkerPrioritySetter::UpdateWorkerPrioritiesFromVisibleSet(
- const std::set<std::pair<int, int> >* visible_frame_ids) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- if (!iter->process_launched())
- continue;
- bool throttle = true;
-
- for (WorkerProcessHost::Instances::const_iterator instance =
- iter->instances().begin(); instance != iter->instances().end();
- ++instance) {
-
- // This code assumes one worker per process
- WorkerProcessHost::Instances::const_iterator first_instance =
- iter->instances().begin();
- if (first_instance == iter->instances().end())
- continue;
-
- WorkerDocumentSet::DocumentInfoSet::const_iterator info =
- first_instance->worker_document_set()->documents().begin();
-
- for (; info != first_instance->worker_document_set()->documents().end();
- ++info) {
- std::pair<int, int> id(
- info->render_process_id(), info->render_frame_id());
- if (visible_frame_ids->find(id) != visible_frame_ids->end()) {
- throttle = false;
- break;
- }
- }
-
- if (!throttle ) {
- break;
- }
- }
-
- iter->SetBackgrounded(throttle);
- }
-}
-
-void WorkerPrioritySetter::OnRenderWidgetVisibilityChanged(
- std::pair<int, int> id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- std::set<std::pair<int, int> > visible_frame_ids;
-
- visible_frame_ids.insert(id);
-
- UpdateWorkerPrioritiesFromVisibleSet(&visible_frame_ids);
-}
-
-void WorkerPrioritySetter::RegisterObserver() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- registrar_.Add(this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
- NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
- NotificationService::AllBrowserContextsAndSources());
-}
-
-void WorkerPrioritySetter::Observe(int type,
- const NotificationSource& source, const NotificationDetails& details) {
- if (type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
- bool visible = *Details<bool>(details).ptr();
-
- if (visible) {
- int render_widget_id =
- Source<RenderWidgetHost>(source).ptr()->GetRoutingID();
- int render_process_pid =
- Source<RenderWidgetHost>(source).ptr()->GetProcess()->GetID();
-
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&WorkerPrioritySetter::OnRenderWidgetVisibilityChanged,
- this, std::pair<int, int>(render_process_pid, render_widget_id)));
- }
- }
- else if (type == NOTIFICATION_RENDERER_PROCESS_CREATED) {
- PostTaskToGatherAndUpdateWorkerPriorities();
- }
-}
-
-WorkerService* WorkerService::GetInstance() {
- if (EmbeddedSharedWorkerEnabled())
- return SharedWorkerServiceImpl::GetInstance();
- else
- return WorkerServiceImpl::GetInstance();
-}
-
-bool WorkerService::EmbeddedSharedWorkerEnabled() {
- static bool disabled = CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableEmbeddedSharedWorker);
- return !disabled;
-}
-
-WorkerServiceImpl* WorkerServiceImpl::GetInstance() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return Singleton<WorkerServiceImpl>::get();
-}
-
-WorkerServiceImpl::WorkerServiceImpl()
- : priority_setter_(new WorkerPrioritySetter()),
- next_worker_route_id_(0) {
- priority_setter_->Initialize();
-}
-
-WorkerServiceImpl::~WorkerServiceImpl() {
- // The observers in observers_ can't be used here because they might be
- // gone already.
-}
-
-void WorkerServiceImpl::PerformTeardownForTesting() {
- priority_setter_ = NULL;
-}
-
-void WorkerServiceImpl::OnWorkerMessageFilterClosing(
- WorkerMessageFilter* filter) {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- iter->FilterShutdown(filter);
- }
-
- // See if that process had any queued workers.
- for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin();
- i != queued_workers_.end();) {
- i->RemoveFilters(filter);
- if (i->NumFilters() == 0) {
- i = queued_workers_.erase(i);
- } else {
- ++i;
- }
- }
-
- // Either a worker proceess has shut down, in which case we can start one of
- // the queued workers, or a renderer has shut down, in which case it doesn't
- // affect anything. We call this function in both scenarios because then we
- // don't have to keep track which filters are from worker processes.
- TryStartingQueuedWorker();
-}
-
-void WorkerServiceImpl::CreateWorker(
- const ViewHostMsg_CreateWorker_Params& params,
- int route_id,
- WorkerMessageFilter* filter,
- ResourceContext* resource_context,
- const WorkerStoragePartition& partition,
- bool* url_mismatch) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- *url_mismatch = false;
- WorkerProcessHost::WorkerInstance* existing_instance =
- FindSharedWorkerInstance(
- params.url, params.name, partition, resource_context);
- if (existing_instance) {
- if (params.url != existing_instance->url()) {
- *url_mismatch = true;
- return;
- }
- if (existing_instance->load_failed()) {
- filter->Send(new ViewMsg_WorkerScriptLoadFailed(route_id));
- return;
- }
- existing_instance->AddFilter(filter, route_id);
- existing_instance->worker_document_set()->Add(
- filter, params.document_id, filter->render_process_id(),
- params.render_frame_route_id);
- filter->Send(new ViewMsg_WorkerCreated(route_id));
- return;
- }
- for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin();
- i != queued_workers_.end(); ++i) {
- if (i->Matches(params.url, params.name, partition, resource_context) &&
- params.url != i->url()) {
- *url_mismatch = true;
- return;
- }
- }
-
- // Generate a unique route id for the browser-worker communication that's
- // unique among all worker processes. That way when the worker process sends
- // a wrapped IPC message through us, we know which WorkerProcessHost to give
- // it to.
- WorkerProcessHost::WorkerInstance instance(
- params.url,
- params.name,
- params.content_security_policy,
- params.security_policy_type,
- next_worker_route_id(),
- params.render_frame_route_id,
- resource_context,
- partition);
- instance.AddFilter(filter, route_id);
- instance.worker_document_set()->Add(
- filter, params.document_id, filter->render_process_id(),
- params.render_frame_route_id);
-
- CreateWorkerFromInstance(instance);
-}
-
-void WorkerServiceImpl::ForwardToWorker(const IPC::Message& message,
- WorkerMessageFilter* filter) {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter->FilterMessage(message, filter))
- return;
- }
-
- // TODO(jabdelmalek): tell filter that callee is gone
-}
-
-void WorkerServiceImpl::DocumentDetached(unsigned long long document_id,
- WorkerMessageFilter* filter) {
- // Any associated shared workers can be shut down.
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter)
- iter->DocumentDetached(filter, document_id);
-
- // Remove any queued shared workers for this document.
- for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin();
- iter != queued_workers_.end();) {
-
- iter->worker_document_set()->Remove(filter, document_id);
- if (iter->worker_document_set()->IsEmpty()) {
- iter = queued_workers_.erase(iter);
- continue;
- }
- ++iter;
- }
-}
-
-bool WorkerServiceImpl::CreateWorkerFromInstance(
- WorkerProcessHost::WorkerInstance instance) {
- if (!CanCreateWorkerProcess(instance)) {
- queued_workers_.push_back(instance);
- return true;
- }
-
- // Remove any queued instances of this worker and copy over the filter to
- // this instance.
- for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin();
- iter != queued_workers_.end();) {
- if (iter->Matches(instance.url(), instance.name(),
- instance.partition(), instance.resource_context())) {
- DCHECK(iter->NumFilters() == 1);
- DCHECK_EQ(instance.url(), iter->url());
- WorkerProcessHost::WorkerInstance::FilterInfo filter_info =
- iter->GetFilter();
- instance.AddFilter(filter_info.filter(), filter_info.route_id());
- iter = queued_workers_.erase(iter);
- } else {
- ++iter;
- }
- }
-
- WorkerMessageFilter* first_filter = instance.filters().begin()->filter();
- WorkerProcessHost* worker = new WorkerProcessHost(
- instance.resource_context(), instance.partition());
- // TODO(atwilson): This won't work if the message is from a worker process.
- // We don't support that yet though (this message is only sent from
- // renderers) but when we do, we'll need to add code to pass in the current
- // worker's document set for nested workers.
- if (!worker->Init(first_filter->render_process_id(),
- instance.render_frame_id())) {
- delete worker;
- return false;
- }
-
- worker->CreateWorker(
- instance,
- WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance));
- FOR_EACH_OBSERVER(
- WorkerServiceObserver, observers_,
- WorkerCreated(instance.url(), instance.name(), worker->GetData().id,
- instance.worker_route_id()));
- return true;
-}
-
-bool WorkerServiceImpl::CanCreateWorkerProcess(
- const WorkerProcessHost::WorkerInstance& instance) {
- // Worker can be fired off if *any* parent has room.
- const WorkerDocumentSet::DocumentInfoSet& parents =
- instance.worker_document_set()->documents();
-
- for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
- parents.begin();
- parent_iter != parents.end(); ++parent_iter) {
- bool hit_total_worker_limit = false;
- if (FrameCanCreateWorkerProcess(parent_iter->render_process_id(),
- parent_iter->render_frame_id(),
- &hit_total_worker_limit)) {
- return true;
- }
- // Return false if already at the global worker limit (no need to continue
- // checking parent tabs).
- if (hit_total_worker_limit)
- return false;
- }
- // If we've reached here, none of the parent tabs is allowed to create an
- // instance.
- return false;
-}
-
-bool WorkerServiceImpl::FrameCanCreateWorkerProcess(
- int render_process_id,
- int render_frame_id,
- bool* hit_total_worker_limit) {
- int total_workers = 0;
- int workers_per_tab = 0;
- *hit_total_worker_limit = false;
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- for (WorkerProcessHost::Instances::const_iterator cur_instance =
- iter->instances().begin();
- cur_instance != iter->instances().end(); ++cur_instance) {
- total_workers++;
- if (total_workers >= kMaxWorkersWhenSeparate) {
- *hit_total_worker_limit = true;
- return false;
- }
- if (cur_instance->FrameIsParent(render_process_id, render_frame_id)) {
- workers_per_tab++;
- if (workers_per_tab >= kMaxWorkersPerFrameWhenSeparate)
- return false;
- }
- }
- }
-
- return true;
-}
-
-void WorkerServiceImpl::TryStartingQueuedWorker() {
- if (queued_workers_.empty())
- return;
-
- for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin();
- i != queued_workers_.end();) {
- if (CanCreateWorkerProcess(*i)) {
- WorkerProcessHost::WorkerInstance instance = *i;
- queued_workers_.erase(i);
- CreateWorkerFromInstance(instance);
-
- // CreateWorkerFromInstance can modify the queued_workers_ list when it
- // coalesces queued instances after starting a shared worker, so we
- // have to rescan the list from the beginning (our iterator is now
- // invalid). This is not a big deal as having any queued workers will be
- // rare in practice so the list will be small.
- i = queued_workers_.begin();
- } else {
- ++i;
- }
- }
-}
-
-bool WorkerServiceImpl::GetRendererForWorker(int worker_process_id,
- int* render_process_id,
- int* render_frame_id) const {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter.GetData().id != worker_process_id)
- continue;
-
- // This code assumes one worker per process, see function comment in header!
- WorkerProcessHost::Instances::const_iterator first_instance =
- iter->instances().begin();
- if (first_instance == iter->instances().end())
- return false;
-
- WorkerDocumentSet::DocumentInfoSet::const_iterator info =
- first_instance->worker_document_set()->documents().begin();
- *render_process_id = info->render_process_id();
- *render_frame_id = info->render_frame_id();
- return true;
- }
- return false;
-}
-
-const WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindWorkerInstance(
- int worker_process_id) {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter.GetData().id != worker_process_id)
- continue;
-
- WorkerProcessHost::Instances::const_iterator instance =
- iter->instances().begin();
- return instance == iter->instances().end() ? NULL : &*instance;
- }
- return NULL;
-}
-
-bool WorkerServiceImpl::TerminateWorker(int process_id, int route_id) {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter.GetData().id == process_id) {
- iter->TerminateWorker(route_id);
- return true;
- }
- }
- return false;
-}
-
-std::vector<WorkerService::WorkerInfo> WorkerServiceImpl::GetWorkers() {
- std::vector<WorkerService::WorkerInfo> results;
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- const WorkerProcessHost::Instances& instances = (*iter)->instances();
- for (WorkerProcessHost::Instances::const_iterator i = instances.begin();
- i != instances.end(); ++i) {
- WorkerService::WorkerInfo info;
- info.url = i->url();
- info.name = i->name();
- info.route_id = i->worker_route_id();
- info.process_id = iter.GetData().id;
- info.handle = iter.GetData().handle;
- results.push_back(info);
- }
- }
- return results;
-}
-
-void WorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- observers_.AddObserver(observer);
-}
-
-void WorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- observers_.RemoveObserver(observer);
-}
-
-void WorkerServiceImpl::NotifyWorkerDestroyed(
- WorkerProcessHost* process,
- int worker_route_id) {
- WorkerDevToolsManager::GetInstance()->WorkerDestroyed(
- process, worker_route_id);
- FOR_EACH_OBSERVER(WorkerServiceObserver, observers_,
- WorkerDestroyed(process->GetData().id, worker_route_id));
-}
-
-void WorkerServiceImpl::NotifyWorkerProcessCreated() {
- priority_setter_->NotifyWorkerProcessCreated();
-}
-
-WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance(
- const GURL& url,
- const base::string16& name,
- const WorkerStoragePartition& partition,
- ResourceContext* resource_context) {
- for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) {
- for (WorkerProcessHost::Instances::iterator instance_iter =
- iter->mutable_instances().begin();
- instance_iter != iter->mutable_instances().end();
- ++instance_iter) {
- if (instance_iter->Matches(url, name, partition, resource_context))
- return &(*instance_iter);
- }
- }
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_service_impl.h b/chromium/content/browser/worker_host/worker_service_impl.h
deleted file mode 100644
index 133c0a38e1a..00000000000
--- a/chromium/content/browser/worker_host/worker_service_impl.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_WORKER_HOST_WORKER_SERVICE_H_
-#define CONTENT_BROWSER_WORKER_HOST_WORKER_SERVICE_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/singleton.h"
-#include "base/observer_list.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/browser/worker_host/worker_process_host.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/worker_service.h"
-
-class GURL;
-struct ViewHostMsg_CreateWorker_Params;
-
-namespace content {
-class ResourceContext;
-class WorkerServiceObserver;
-class WorkerStoragePartition;
-class WorkerPrioritySetter;
-
-class CONTENT_EXPORT WorkerServiceImpl
- : public NON_EXPORTED_BASE(WorkerService) {
- public:
- // Returns the WorkerServiceImpl singleton.
- static WorkerServiceImpl* GetInstance();
-
- // Releases the priority setter to avoid memory leak error.
- void PerformTeardownForTesting();
-
- // WorkerService implementation:
- virtual bool TerminateWorker(int process_id, int route_id) OVERRIDE;
- virtual std::vector<WorkerInfo> GetWorkers() OVERRIDE;
- virtual void AddObserver(WorkerServiceObserver* observer) OVERRIDE;
- virtual void RemoveObserver(WorkerServiceObserver* observer) OVERRIDE;
-
- // These methods correspond to worker related IPCs.
- void CreateWorker(const ViewHostMsg_CreateWorker_Params& params,
- int route_id,
- WorkerMessageFilter* filter,
- ResourceContext* resource_context,
- const WorkerStoragePartition& worker_partition,
- bool* url_mismatch);
- void ForwardToWorker(const IPC::Message& message,
- WorkerMessageFilter* filter);
- void DocumentDetached(unsigned long long document_id,
- WorkerMessageFilter* filter);
-
- void OnWorkerMessageFilterClosing(WorkerMessageFilter* filter);
-
- int next_worker_route_id() { return ++next_worker_route_id_; }
-
- // Given a worker's process id, return the IDs of the renderer process and
- // render frame that created it. For shared workers, this returns the first
- // parent.
- // TODO(dimich): This code assumes there is 1 worker per worker process, which
- // is how it is today until V8 can run in separate threads.
- bool GetRendererForWorker(int worker_process_id,
- int* render_process_id,
- int* render_frame_id) const;
- const WorkerProcessHost::WorkerInstance* FindWorkerInstance(
- int worker_process_id);
-
- void NotifyWorkerDestroyed(
- WorkerProcessHost* process,
- int worker_route_id);
-
- void NotifyWorkerProcessCreated();
-
- // Used when we run each worker in a separate process.
- static const int kMaxWorkersWhenSeparate;
- static const int kMaxWorkersPerFrameWhenSeparate;
-
- private:
- friend struct DefaultSingletonTraits<WorkerServiceImpl>;
-
- WorkerServiceImpl();
- virtual ~WorkerServiceImpl();
-
- // Given a WorkerInstance, create an associated worker process.
- bool CreateWorkerFromInstance(WorkerProcessHost::WorkerInstance instance);
-
- // Checks if we can create a worker process based on the process limit when
- // we're using a strategy of one process per core.
- bool CanCreateWorkerProcess(
- const WorkerProcessHost::WorkerInstance& instance);
-
- // Checks if the frame associated with the passed RenderFrame can create a
- // worker process based on the process limit when we're using a strategy of
- // one worker per process.
- bool FrameCanCreateWorkerProcess(
- int render_process_id, int render_frame_id, bool* hit_total_worker_limit);
-
- // Tries to see if any of the queued workers can be created.
- void TryStartingQueuedWorker();
-
- WorkerProcessHost::WorkerInstance* FindSharedWorkerInstance(
- const GURL& url,
- const base::string16& name,
- const WorkerStoragePartition& worker_partition,
- ResourceContext* resource_context);
-
- scoped_refptr<WorkerPrioritySetter> priority_setter_;
-
- int next_worker_route_id_;
-
- WorkerProcessHost::Instances queued_workers_;
-
- ObserverList<WorkerServiceObserver> observers_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerServiceImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_SERVICE_H_
diff --git a/chromium/content/browser/worker_host/worker_storage_partition.cc b/chromium/content/browser/worker_host/worker_storage_partition.cc
deleted file mode 100644
index e7a5f40660c..00000000000
--- a/chromium/content/browser/worker_host/worker_storage_partition.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2012 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 "content/browser/worker_host/worker_storage_partition.h"
-
-#include <string>
-
-#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/browser/indexed_db/indexed_db_context_impl.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "webkit/browser/database/database_tracker.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/browser/quota/quota_manager.h"
-
-namespace content {
-
-WorkerStoragePartition::WorkerStoragePartition(
- net::URLRequestContextGetter* url_request_context,
- net::URLRequestContextGetter* media_url_request_context,
- ChromeAppCacheService* appcache_service,
- quota::QuotaManager* quota_manager,
- fileapi::FileSystemContext* filesystem_context,
- webkit_database::DatabaseTracker* database_tracker,
- IndexedDBContextImpl* indexed_db_context,
- ServiceWorkerContextWrapper* service_worker_context)
- : url_request_context_(url_request_context),
- media_url_request_context_(media_url_request_context),
- appcache_service_(appcache_service),
- quota_manager_(quota_manager),
- filesystem_context_(filesystem_context),
- database_tracker_(database_tracker),
- indexed_db_context_(indexed_db_context),
- service_worker_context_(service_worker_context) {
-}
-
-WorkerStoragePartition::WorkerStoragePartition(
- const WorkerStoragePartition& other) {
- Copy(other);
-}
-
-const WorkerStoragePartition& WorkerStoragePartition::operator=(
- const WorkerStoragePartition& rhs) {
- Copy(rhs);
- return *this;
-}
-
-bool WorkerStoragePartition::Equals(
- const WorkerStoragePartition& other) const {
- return url_request_context_.get() == other.url_request_context_.get() &&
- media_url_request_context_.get() ==
- other.media_url_request_context_.get() &&
- appcache_service_.get() == other.appcache_service_.get() &&
- quota_manager_.get() == other.quota_manager_.get() &&
- filesystem_context_.get() == other.filesystem_context_.get() &&
- database_tracker_.get() == other.database_tracker_.get() &&
- indexed_db_context_.get() == other.indexed_db_context_.get() &&
- service_worker_context_.get() == other.service_worker_context_.get();
-}
-
-WorkerStoragePartition::~WorkerStoragePartition() {
-}
-
-void WorkerStoragePartition::Copy(const WorkerStoragePartition& other) {
- url_request_context_ = other.url_request_context_;
- media_url_request_context_ = other.media_url_request_context_;
- appcache_service_ = other.appcache_service_;
- quota_manager_ = other.quota_manager_;
- filesystem_context_ = other.filesystem_context_;
- database_tracker_ = other.database_tracker_;
- indexed_db_context_ = other.indexed_db_context_;
- service_worker_context_ = other.service_worker_context_;
-}
-
-WorkerStoragePartitionId::WorkerStoragePartitionId(
- const WorkerStoragePartition& partition)
- : url_request_context_(partition.url_request_context()),
- media_url_request_context_(partition.media_url_request_context()),
- appcache_service_(partition.appcache_service()),
- quota_manager_(partition.quota_manager()),
- filesystem_context_(partition.filesystem_context()),
- database_tracker_(partition.database_tracker()),
- indexed_db_context_(partition.indexed_db_context()),
- service_worker_context_(partition.service_worker_context()) {
-}
-
-WorkerStoragePartitionId::~WorkerStoragePartitionId() {
-}
-
-bool WorkerStoragePartitionId::Equals(
- const WorkerStoragePartitionId& other) const {
- return url_request_context_ == other.url_request_context_ &&
- media_url_request_context_ == other.media_url_request_context_ &&
- appcache_service_ == other.appcache_service_ &&
- quota_manager_ == other.quota_manager_ &&
- filesystem_context_ == other.filesystem_context_ &&
- database_tracker_ == other.database_tracker_ &&
- indexed_db_context_ == other.indexed_db_context_ &&
- service_worker_context_ == other.service_worker_context_;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/worker_host/worker_storage_partition.h b/chromium/content/browser/worker_host/worker_storage_partition.h
deleted file mode 100644
index aebd683c3f5..00000000000
--- a/chromium/content/browser/worker_host/worker_storage_partition.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_WORKER_HOST_WORKER_STORAGE_PARTITION_H_
-#define CONTENT_BROWSER_WORKER_HOST_WORKER_STORAGE_PARTITION_H_
-
-#include "base/memory/ref_counted.h"
-#include "content/common/content_export.h"
-
-namespace quota {
-class QuotaManager;
-}
-
-namespace fileapi {
-class FileSystemContext;
-} // namespace fileapi
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-namespace webkit_database {
-class DatabaseTracker;
-} // namespace webkit_database
-
-namespace content {
-class ChromeAppCacheService;
-class IndexedDBContextImpl;
-class ServiceWorkerContextWrapper;
-
-// Contains the data from StoragePartition for use by Worker APIs.
-//
-// StoragePartition meant for the UI so we can't use it directly in many
-// Worker APIs that run on the IO thread. While we could make it RefCounted,
-// the Worker system is the only place that really needs access on the IO
-// thread. Instead of changing the lifetime semantics of StoragePartition,
-// we just create a parallel struct here to simplify the APIs of various
-// methods in WorkerServiceImpl.
-//
-// This class is effectively a struct, but we make it a class because we want to
-// define copy constructors, assignment operators, and an Equals() function for
-// it which makes it look awkward as a struct.
-class CONTENT_EXPORT WorkerStoragePartition {
- public:
- WorkerStoragePartition(
- net::URLRequestContextGetter* url_request_context,
- net::URLRequestContextGetter* media_url_request_context,
- ChromeAppCacheService* appcache_service,
- quota::QuotaManager* quota_manager,
- fileapi::FileSystemContext* filesystem_context,
- webkit_database::DatabaseTracker* database_tracker,
- IndexedDBContextImpl* indexed_db_context,
- ServiceWorkerContextWrapper* service_worker_context);
- ~WorkerStoragePartition();
-
- // Declaring so these don't get inlined which has the unfortunate effect of
- // requiring all including classes to have the full definition of every member
- // type.
- WorkerStoragePartition(const WorkerStoragePartition& other);
- const WorkerStoragePartition& operator=(const WorkerStoragePartition& rhs);
-
- bool Equals(const WorkerStoragePartition& other) const;
-
- net::URLRequestContextGetter* url_request_context() const {
- return url_request_context_.get();
- }
-
- net::URLRequestContextGetter* media_url_request_context() const {
- return media_url_request_context_.get();
- }
-
- ChromeAppCacheService* appcache_service() const {
- return appcache_service_.get();
- }
-
- quota::QuotaManager* quota_manager() const {
- return quota_manager_.get();
- }
-
- fileapi::FileSystemContext* filesystem_context() const {
- return filesystem_context_.get();
- }
-
- webkit_database::DatabaseTracker* database_tracker() const {
- return database_tracker_.get();
- }
-
- IndexedDBContextImpl* indexed_db_context() const {
- return indexed_db_context_.get();
- }
-
- ServiceWorkerContextWrapper* service_worker_context() const {
- return service_worker_context_.get();
- }
-
- private:
- void Copy(const WorkerStoragePartition& other);
-
- scoped_refptr<net::URLRequestContextGetter> url_request_context_;
- scoped_refptr<net::URLRequestContextGetter> media_url_request_context_;
- scoped_refptr<ChromeAppCacheService> appcache_service_;
- scoped_refptr<quota::QuotaManager> quota_manager_;
- scoped_refptr<fileapi::FileSystemContext> filesystem_context_;
- scoped_refptr<webkit_database::DatabaseTracker> database_tracker_;
- scoped_refptr<IndexedDBContextImpl> indexed_db_context_;
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
-};
-
-// WorkerStoragePartitionId can be used to identify each
-// WorkerStoragePartitions. We can hold WorkerStoragePartitionId without
-// extending the lifetime of all objects in the WorkerStoragePartition.
-// That means that holding a WorkerStoragePartitionId doesn't mean the
-// corresponding partition and its members are kept alive.
-class CONTENT_EXPORT WorkerStoragePartitionId {
- public:
- explicit WorkerStoragePartitionId(const WorkerStoragePartition& partition);
- ~WorkerStoragePartitionId();
- bool Equals(const WorkerStoragePartitionId& other) const;
-
- private:
- net::URLRequestContextGetter* url_request_context_;
- net::URLRequestContextGetter* media_url_request_context_;
- ChromeAppCacheService* appcache_service_;
- quota::QuotaManager* quota_manager_;
- fileapi::FileSystemContext* filesystem_context_;
- webkit_database::DatabaseTracker* database_tracker_;
- IndexedDBContextImpl* indexed_db_context_;
- ServiceWorkerContextWrapper* service_worker_context_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_WORKER_HOST_WORKER_STORAGE_PARTITION_H_
diff --git a/chromium/content/browser/zygote_host/OWNERS b/chromium/content/browser/zygote_host/OWNERS
index 602e00e0750..c2dd4263b5c 100644
--- a/chromium/content/browser/zygote_host/OWNERS
+++ b/chromium/content/browser/zygote_host/OWNERS
@@ -1,3 +1,2 @@
-markus@chromium.org
-cevans@chromium.org
jln@chromium.org
+mdempsky@chromium.org
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
index 81d075688d7..c2f1c908c0a 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -13,8 +13,8 @@
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/environment.h"
-#include "base/file_util.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/linux_util.h"
#include "base/logging.h"
@@ -100,7 +100,7 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
base::FilePath chrome_path;
CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
- CommandLine cmd_line(chrome_path);
+ base::CommandLine cmd_line(chrome_path);
cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess);
@@ -111,7 +111,8 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
base::LaunchOptions options;
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
cmd_line.PrependWrapper(
browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix));
@@ -121,18 +122,17 @@ void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
// Should this list be obtained from browser_render_process_host.cc?
static const char* kForwardSwitches[] = {
switches::kAllowSandboxDebugging,
- switches::kLoggingLevel,
- switches::kEnableLogging, // Support, e.g., --enable-logging=stderr.
- switches::kV,
- switches::kVModule,
- switches::kRegisterPepperPlugins,
switches::kDisableSeccompFilterSandbox,
-
+ switches::kEnableLogging, // Support, e.g., --enable-logging=stderr.
// Zygote process needs to know what resources to have loaded when it
// becomes a renderer process.
switches::kForceDeviceScaleFactor,
-
+ switches::kLoggingLevel,
switches::kNoSandbox,
+ switches::kPpapiInProcess,
+ switches::kRegisterPepperPlugins,
+ switches::kV,
+ switches::kVModule,
};
cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
@@ -287,10 +287,9 @@ ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) {
return HANDLE_EINTR(read(control_fd_, buf, buf_len));
}
-pid_t ZygoteHostImpl::ForkRequest(
- const std::vector<std::string>& argv,
- const std::vector<FileDescriptorInfo>& mapping,
- const std::string& process_type) {
+pid_t ZygoteHostImpl::ForkRequest(const std::vector<std::string>& argv,
+ scoped_ptr<FileDescriptorInfo> mapping,
+ const std::string& process_type) {
DCHECK(init_);
Pickle pickle;
@@ -309,26 +308,20 @@ pid_t ZygoteHostImpl::ForkRequest(
// Fork requests contain one file descriptor for the PID oracle, and one
// more for each file descriptor mapping for the child process.
- const size_t num_fds_to_send = 1 + mapping.size();
+ const size_t num_fds_to_send = 1 + mapping->GetMappingSize();
pickle.WriteInt(num_fds_to_send);
std::vector<int> fds;
- ScopedVector<base::ScopedFD> autoclose_fds;
// First FD to send is peer_sock.
+ // TODO(morrita): Ideally, this should be part of the mapping so that
+ // FileDescriptorInfo can manages its lifetime.
fds.push_back(peer_sock.get());
- autoclose_fds.push_back(new base::ScopedFD(peer_sock.Pass()));
// The rest come from mapping.
- for (std::vector<FileDescriptorInfo>::const_iterator
- i = mapping.begin(); i != mapping.end(); ++i) {
- pickle.WriteUInt32(i->id);
- fds.push_back(i->fd.fd);
- if (i->fd.auto_close) {
- // Auto-close means we need to close the FDs after they have been passed
- // to the other process.
- autoclose_fds.push_back(new base::ScopedFD(i->fd.fd));
- }
+ for (size_t i = 0; i < mapping->GetMappingSize(); ++i) {
+ pickle.WriteUInt32(mapping->GetIDAt(i));
+ fds.push_back(mapping->GetFDAt(i));
}
// Sanity check that we've populated |fds| correctly.
@@ -339,7 +332,8 @@ pid_t ZygoteHostImpl::ForkRequest(
base::AutoLock lock(control_lock_);
if (!SendMessage(pickle, &fds))
return base::kNullProcessHandle;
- autoclose_fds.clear();
+ mapping.reset();
+ peer_sock.reset();
{
char buf[sizeof(kZygoteChildPingMessage) + 1];
diff --git a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
index c4435469849..e18e098088b 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
@@ -34,7 +34,7 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
// Returns its pid on success, otherwise
// base::kNullProcessHandle;
pid_t ForkRequest(const std::vector<std::string>& command_line,
- const std::vector<FileDescriptorInfo>& mapping,
+ scoped_ptr<FileDescriptorInfo> mapping,
const std::string& process_type);
void EnsureProcessTerminated(pid_t process);
@@ -54,16 +54,16 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
int* exit_code);
// ZygoteHost implementation:
- virtual pid_t GetPid() const OVERRIDE;
- virtual int GetSandboxStatus() const OVERRIDE;
- virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
- int score) OVERRIDE;
+ pid_t GetPid() const override;
+ int GetSandboxStatus() const override;
+ void AdjustRendererOOMScore(base::ProcessHandle process_handle,
+ int score) override;
private:
friend struct DefaultSingletonTraits<ZygoteHostImpl>;
ZygoteHostImpl();
- virtual ~ZygoteHostImpl();
+ ~ZygoteHostImpl() override;
// Notify the Zygote to exit immediately. This object should not be
// used afterwards.
diff --git a/chromium/content/child/BUILD.gn b/chromium/content/child/BUILD.gn
index bf3a43ad5f2..8e400c3cd7a 100644
--- a/chromium/content/child/BUILD.gn
+++ b/chromium/content/child/BUILD.gn
@@ -8,8 +8,9 @@ import("//build/config/ui.gni")
import("//content/child/child.gni")
source_set("child") {
- # Only targets in the content tree can depend directly on this target.
- visibility = [ "//content/*" ]
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/child:child_sources" ]
sources = rebase_path(content_child_gypi_values.private_child_sources,
".", "//content")
@@ -17,8 +18,9 @@ source_set("child") {
deps = [
"//base",
"//components/tracing",
+ "//mojo/common",
"//mojo/environment:chromium",
- "//mojo/public/interfaces/service_provider",
+ "//mojo/public/interfaces/application",
"//skia",
"//third_party/icu",
"//ui/base",
@@ -47,7 +49,6 @@ source_set("child") {
"npapi/plugin_host.h",
"npapi/plugin_instance.cc",
"npapi/plugin_instance.h",
- "npapi/plugin_instance_mac.mm",
"npapi/plugin_lib.cc",
"npapi/plugin_lib.h",
"npapi/plugin_stream.cc",
@@ -55,26 +56,42 @@ source_set("child") {
"npapi/plugin_stream_posix.cc",
"npapi/plugin_stream_url.cc",
"npapi/plugin_stream_url.h",
- "npapi/plugin_stream_win.cc",
"npapi/plugin_string_stream.cc",
"npapi/plugin_string_stream.h",
"npapi/plugin_url_fetcher.cc",
"npapi/plugin_url_fetcher.h",
- "npapi/plugin_web_event_converter_mac.h",
- "npapi/plugin_web_event_converter_mac.mm",
"npapi/webplugin.h",
- "npapi/webplugin_accelerated_surface_mac.h",
"npapi/webplugin_delegate.h",
"npapi/webplugin_delegate_impl.cc",
"npapi/webplugin_delegate_impl.h",
- "npapi/webplugin_delegate_impl_android.cc",
- "npapi/webplugin_delegate_impl_aura.cc",
- "npapi/webplugin_delegate_impl_mac.mm",
- "npapi/webplugin_delegate_impl_win.cc",
- "npapi/webplugin_ime_win.cc",
- "npapi/webplugin_ime_win.h",
"npapi/webplugin_resource_client.h",
]
+
+ if (is_mac) {
+ sources -= [
+ "npapi/plugin_instance_mac.mm",
+ "npapi/plugin_web_event_converter_mac.h",
+ "npapi/plugin_web_event_converter_mac.mm",
+ "npapi/webplugin_accelerated_surface_mac.h",
+ "npapi/webplugin_delegate_impl_mac.mm",
+ ]
+ } else if (is_win) {
+ sources -= [
+ "npapi/plugin_stream_win.cc",
+ "npapi/webplugin_delegate_impl_win.cc",
+ "npapi/webplugin_ime_win.cc",
+ "npapi/webplugin_ime_win.h",
+ ]
+ } else if (is_android) {
+ sources -= [
+ "npapi/webplugin_delegate_impl_android.cc",
+ ]
+ }
+ if (use_aura) {
+ sources -= [
+ "npapi/webplugin_delegate_impl_aura.cc",
+ ]
+ }
}
configs += [
@@ -87,13 +104,13 @@ source_set("child") {
sources = []
} else {
deps += [
+ "//content/app/resources",
+ "//content/app/strings",
"//crypto:platform",
- #"//third_party/WebKit/public:blink", # TODO(GYP)
+ "//storage/common",
+ "//third_party/WebKit/public:blink",
+ "//third_party/WebKit/public:resources",
"//third_party/npapi",
- "//webkit:resources",
- "//webkit:strings",
- "//webkit/child",
- "//webkit/common",
]
}
@@ -102,13 +119,15 @@ source_set("child") {
sources -= [ "npapi/webplugin_delegate_impl_mac.mm" ]
}
- if (is_win) {
+ if (is_win || !use_aura) {
sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
}
if (!use_openssl) {
- sources -= [ "webcrypto/platform_crypto_openssl.cc" ]
+ sources += rebase_path(content_child_gypi_values.webcrypto_nss_sources,
+ ".", "//content")
} else {
- sources -= [ "webcrypto/platform_crypto_nss.cc" ]
+ sources += rebase_path(content_child_gypi_values.webcrypto_openssl_sources,
+ ".", "//content")
}
}
diff --git a/chromium/content/child/DEPS b/chromium/content/child/DEPS
index 3adcf04965d..be1e09fb539 100644
--- a/chromium/content/child/DEPS
+++ b/chromium/content/child/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/tracing",
+ "+content/app/strings/grit", # For generated headers
"+content/public/child",
"+media/base/android",
]
diff --git a/chromium/content/child/OWNERS b/chromium/content/child/OWNERS
index d486c11aa55..df38750b2e1 100644
--- a/chromium/content/child/OWNERS
+++ b/chromium/content/child/OWNERS
@@ -1,6 +1,6 @@
per-file appcache*=michaeln@chromium.org
-per-file *fling*=jdduke@chromium.org
+per-file *curve*=jdduke@chromium.org
# WebSocket
per-file *websocket*=ricea@chromium.org
diff --git a/chromium/content/child/appcache/appcache_backend_proxy.cc b/chromium/content/child/appcache/appcache_backend_proxy.cc
index e1d96d636f2..bf3149409f9 100644
--- a/chromium/content/child/appcache/appcache_backend_proxy.cc
+++ b/chromium/content/child/appcache/appcache_backend_proxy.cc
@@ -54,8 +54,8 @@ void AppCacheBackendProxy::MarkAsForeignEntry(
cache_document_was_loaded_from));
}
-appcache::AppCacheStatus AppCacheBackendProxy::GetStatus(int host_id) {
- appcache::AppCacheStatus status = appcache::APPCACHE_STATUS_UNCACHED;
+AppCacheStatus AppCacheBackendProxy::GetStatus(int host_id) {
+ AppCacheStatus status = APPCACHE_STATUS_UNCACHED;
sender_->Send(new AppCacheHostMsg_GetStatus(host_id, &status));
return status;
}
@@ -73,7 +73,7 @@ bool AppCacheBackendProxy::SwapCache(int host_id) {
}
void AppCacheBackendProxy::GetResourceList(
- int host_id, std::vector<appcache::AppCacheResourceInfo>* resource_infos) {
+ int host_id, std::vector<AppCacheResourceInfo>* resource_infos) {
sender_->Send(new AppCacheHostMsg_GetResourceList(host_id, resource_infos));
}
diff --git a/chromium/content/child/appcache/appcache_backend_proxy.h b/chromium/content/child/appcache/appcache_backend_proxy.h
index 389f08c6a9d..ee41cb933fe 100644
--- a/chromium/content/child/appcache/appcache_backend_proxy.h
+++ b/chromium/content/child/appcache/appcache_backend_proxy.h
@@ -7,43 +7,39 @@
#include <vector>
+#include "content/common/appcache_interfaces.h"
#include "ipc/ipc_sender.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
namespace content {
// Sends appcache related messages to the main process.
-class AppCacheBackendProxy : public appcache::AppCacheBackend {
+class AppCacheBackendProxy : public AppCacheBackend {
public:
explicit AppCacheBackendProxy(IPC::Sender* sender) : sender_(sender) {}
IPC::Sender* sender() const { return sender_; }
// AppCacheBackend methods
- virtual void RegisterHost(int host_id) OVERRIDE;
- virtual void UnregisterHost(int host_id) OVERRIDE;
- virtual void SetSpawningHostId(int host_id, int spawning_host_id) OVERRIDE;
- virtual void SelectCache(int host_id,
- const GURL& document_url,
- const int64 cache_document_was_loaded_from,
- const GURL& manifest_url) OVERRIDE;
- virtual void SelectCacheForWorker(
- int host_id,
- int parent_process_id,
- int parent_host_id) OVERRIDE;
- virtual void SelectCacheForSharedWorker(
- int host_id,
- int64 appcache_id) OVERRIDE;
- virtual void MarkAsForeignEntry(
+ void RegisterHost(int host_id) override;
+ void UnregisterHost(int host_id) override;
+ void SetSpawningHostId(int host_id, int spawning_host_id) override;
+ void SelectCache(int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url) override;
+ void SelectCacheForWorker(int host_id,
+ int parent_process_id,
+ int parent_host_id) override;
+ void SelectCacheForSharedWorker(int host_id, int64 appcache_id) override;
+ void MarkAsForeignEntry(int host_id,
+ const GURL& document_url,
+ int64 cache_document_was_loaded_from) override;
+ AppCacheStatus GetStatus(int host_id) override;
+ bool StartUpdate(int host_id) override;
+ bool SwapCache(int host_id) override;
+ void GetResourceList(
int host_id,
- const GURL& document_url,
- int64 cache_document_was_loaded_from) OVERRIDE;
- virtual appcache::AppCacheStatus GetStatus(int host_id) OVERRIDE;
- virtual bool StartUpdate(int host_id) OVERRIDE;
- virtual bool SwapCache(int host_id) OVERRIDE;
- virtual void GetResourceList(
- int host_id,
- std::vector<appcache::AppCacheResourceInfo>* resource_infos) OVERRIDE;
+ std::vector<AppCacheResourceInfo>* resource_infos) override;
private:
IPC::Sender* sender_;
diff --git a/chromium/content/child/appcache/appcache_dispatcher.cc b/chromium/content/child/appcache/appcache_dispatcher.cc
index 11e5b9d3bfe..02986b19d7f 100644
--- a/chromium/content/child/appcache/appcache_dispatcher.cc
+++ b/chromium/content/child/appcache/appcache_dispatcher.cc
@@ -10,7 +10,7 @@ namespace content {
AppCacheDispatcher::AppCacheDispatcher(
IPC::Sender* sender,
- appcache::AppCacheFrontend* frontend)
+ AppCacheFrontend* frontend)
: backend_proxy_(sender),
frontend_(frontend) {}
@@ -32,17 +32,17 @@ bool AppCacheDispatcher::OnMessageReceived(const IPC::Message& msg) {
}
void AppCacheDispatcher::OnCacheSelected(
- int host_id, const appcache::AppCacheInfo& info) {
+ int host_id, const AppCacheInfo& info) {
frontend_->OnCacheSelected(host_id, info);
}
void AppCacheDispatcher::OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) {
+ AppCacheStatus status) {
frontend_->OnStatusChanged(host_ids, status);
}
void AppCacheDispatcher::OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) {
+ AppCacheEventID event_id) {
frontend_->OnEventRaised(host_ids, event_id);
}
@@ -54,14 +54,14 @@ void AppCacheDispatcher::OnProgressEventRaised(
void AppCacheDispatcher::OnErrorEventRaised(
const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details) {
+ const AppCacheErrorDetails& details) {
frontend_->OnErrorEventRaised(host_ids, details);
}
void AppCacheDispatcher::OnLogMessage(
int host_id, int log_level, const std::string& message) {
frontend_->OnLogMessage(
- host_id, static_cast<appcache::AppCacheLogLevel>(log_level), message);
+ host_id, static_cast<AppCacheLogLevel>(log_level), message);
}
void AppCacheDispatcher::OnContentBlocked(int host_id,
diff --git a/chromium/content/child/appcache/appcache_dispatcher.h b/chromium/content/child/appcache/appcache_dispatcher.h
index 6b627279d32..4dffb180e76 100644
--- a/chromium/content/child/appcache/appcache_dispatcher.h
+++ b/chromium/content/child/appcache/appcache_dispatcher.h
@@ -10,8 +10,8 @@
#include "base/memory/scoped_ptr.h"
#include "content/child/appcache/appcache_backend_proxy.h"
+#include "content/common/appcache_interfaces.h"
#include "ipc/ipc_listener.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
namespace content {
@@ -22,30 +22,30 @@ namespace content {
class AppCacheDispatcher : public IPC::Listener {
public:
AppCacheDispatcher(IPC::Sender* sender,
- appcache::AppCacheFrontend* frontend);
- virtual ~AppCacheDispatcher();
+ AppCacheFrontend* frontend);
+ ~AppCacheDispatcher() override;
AppCacheBackendProxy* backend_proxy() { return &backend_proxy_; }
// IPC::Listener implementation
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
private:
// Ipc message handlers
- void OnCacheSelected(int host_id, const appcache::AppCacheInfo& info);
+ void OnCacheSelected(int host_id, const AppCacheInfo& info);
void OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status);
+ AppCacheStatus status);
void OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id);
+ AppCacheEventID event_id);
void OnProgressEventRaised(const std::vector<int>& host_ids,
const GURL& url, int num_total, int num_complete);
void OnErrorEventRaised(const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details);
+ const AppCacheErrorDetails& details);
void OnLogMessage(int host_id, int log_level, const std::string& message);
void OnContentBlocked(int host_id, const GURL& manifest_url);
AppCacheBackendProxy backend_proxy_;
- scoped_ptr<appcache::AppCacheFrontend> frontend_;
+ scoped_ptr<AppCacheFrontend> frontend_;
};
} // namespace content
diff --git a/chromium/content/child/appcache/appcache_frontend_impl.cc b/chromium/content/child/appcache/appcache_frontend_impl.cc
index 1a33e0de2e3..8ede37a21ba 100644
--- a/chromium/content/child/appcache/appcache_frontend_impl.cc
+++ b/chromium/content/child/appcache/appcache_frontend_impl.cc
@@ -19,14 +19,14 @@ inline WebApplicationCacheHostImpl* GetHost(int id) {
}
void AppCacheFrontendImpl::OnCacheSelected(int host_id,
- const appcache::AppCacheInfo& info) {
+ const AppCacheInfo& info) {
WebApplicationCacheHostImpl* host = GetHost(host_id);
if (host)
host->OnCacheSelected(info);
}
void AppCacheFrontendImpl::OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) {
+ AppCacheStatus status) {
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -36,10 +36,10 @@ void AppCacheFrontendImpl::OnStatusChanged(const std::vector<int>& host_ids,
}
void AppCacheFrontendImpl::OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) {
+ AppCacheEventID event_id) {
DCHECK(event_id !=
- appcache::APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised.
- DCHECK(event_id != appcache::APPCACHE_ERROR_EVENT); // See OnErrorEventRaised.
+ APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised.
+ DCHECK(event_id != APPCACHE_ERROR_EVENT); // See OnErrorEventRaised.
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -63,7 +63,7 @@ void AppCacheFrontendImpl::OnProgressEventRaised(
void AppCacheFrontendImpl::OnErrorEventRaised(
const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details) {
+ const AppCacheErrorDetails& details) {
for (std::vector<int>::const_iterator i = host_ids.begin();
i != host_ids.end(); ++i) {
WebApplicationCacheHostImpl* host = GetHost(*i);
@@ -73,7 +73,7 @@ void AppCacheFrontendImpl::OnErrorEventRaised(
}
void AppCacheFrontendImpl::OnLogMessage(int host_id,
- appcache::AppCacheLogLevel log_level,
+ AppCacheLogLevel log_level,
const std::string& message) {
WebApplicationCacheHostImpl* host = GetHost(host_id);
if (host)
@@ -90,67 +90,67 @@ void AppCacheFrontendImpl::OnContentBlocked(int host_id,
// Ensure that enum values never get out of sync with the
// ones declared for use within the WebKit api
COMPILE_ASSERT((int)WebApplicationCacheHost::Uncached ==
- (int)appcache::APPCACHE_STATUS_UNCACHED, Uncached);
+ (int)APPCACHE_STATUS_UNCACHED, Uncached);
COMPILE_ASSERT((int)WebApplicationCacheHost::Idle ==
- (int)appcache::APPCACHE_STATUS_IDLE, Idle);
+ (int)APPCACHE_STATUS_IDLE, Idle);
COMPILE_ASSERT((int)WebApplicationCacheHost::Checking ==
- (int)appcache::APPCACHE_STATUS_CHECKING, Checking);
+ (int)APPCACHE_STATUS_CHECKING, Checking);
COMPILE_ASSERT((int)WebApplicationCacheHost::Downloading ==
- (int)appcache::APPCACHE_STATUS_DOWNLOADING, Downloading);
+ (int)APPCACHE_STATUS_DOWNLOADING, Downloading);
COMPILE_ASSERT((int)WebApplicationCacheHost::UpdateReady ==
- (int)appcache::APPCACHE_STATUS_UPDATE_READY, UpdateReady);
+ (int)APPCACHE_STATUS_UPDATE_READY, UpdateReady);
COMPILE_ASSERT((int)WebApplicationCacheHost::Obsolete ==
- (int)appcache::APPCACHE_STATUS_OBSOLETE, Obsolete);
+ (int)APPCACHE_STATUS_OBSOLETE, Obsolete);
COMPILE_ASSERT((int)WebApplicationCacheHost::CheckingEvent ==
- (int)appcache::APPCACHE_CHECKING_EVENT, CheckingEvent);
+ (int)APPCACHE_CHECKING_EVENT, CheckingEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::ErrorEvent ==
- (int)appcache::APPCACHE_ERROR_EVENT, ErrorEvent);
+ (int)APPCACHE_ERROR_EVENT, ErrorEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::NoUpdateEvent ==
- (int)appcache::APPCACHE_NO_UPDATE_EVENT, NoUpdateEvent);
+ (int)APPCACHE_NO_UPDATE_EVENT, NoUpdateEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::DownloadingEvent ==
- (int)appcache::APPCACHE_DOWNLOADING_EVENT, DownloadingEvent);
+ (int)APPCACHE_DOWNLOADING_EVENT, DownloadingEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::ProgressEvent ==
- (int)appcache::APPCACHE_PROGRESS_EVENT, ProgressEvent);
+ (int)APPCACHE_PROGRESS_EVENT, ProgressEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::UpdateReadyEvent ==
- (int)appcache::APPCACHE_UPDATE_READY_EVENT, UpdateReadyEvent);
+ (int)APPCACHE_UPDATE_READY_EVENT, UpdateReadyEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::CachedEvent ==
- (int)appcache::APPCACHE_CACHED_EVENT, CachedEvent);
+ (int)APPCACHE_CACHED_EVENT, CachedEvent);
COMPILE_ASSERT((int)WebApplicationCacheHost::ObsoleteEvent ==
- (int)appcache::APPCACHE_OBSOLETE_EVENT, ObsoleteEvent);
+ (int)APPCACHE_OBSOLETE_EVENT, ObsoleteEvent);
COMPILE_ASSERT((int)WebConsoleMessage::LevelDebug ==
- (int)appcache::APPCACHE_LOG_DEBUG, LevelDebug);
+ (int)APPCACHE_LOG_DEBUG, LevelDebug);
COMPILE_ASSERT((int)WebConsoleMessage::LevelLog ==
- (int)appcache::APPCACHE_LOG_INFO, LevelLog);
+ (int)APPCACHE_LOG_INFO, LevelLog);
COMPILE_ASSERT((int)WebConsoleMessage::LevelWarning ==
- (int)appcache::APPCACHE_LOG_WARNING, LevelWarning);
+ (int)APPCACHE_LOG_WARNING, LevelWarning);
COMPILE_ASSERT((int)WebConsoleMessage::LevelError ==
- (int)appcache::APPCACHE_LOG_ERROR, LevelError);
+ (int)APPCACHE_LOG_ERROR, LevelError);
COMPILE_ASSERT((int)WebApplicationCacheHost::ManifestError ==
- (int)appcache::APPCACHE_MANIFEST_ERROR,
+ (int)APPCACHE_MANIFEST_ERROR,
ManifestError);
COMPILE_ASSERT((int)WebApplicationCacheHost::SignatureError ==
- (int)appcache::APPCACHE_SIGNATURE_ERROR,
+ (int)APPCACHE_SIGNATURE_ERROR,
SignatureError);
COMPILE_ASSERT((int)WebApplicationCacheHost::ResourceError ==
- (int)appcache::APPCACHE_RESOURCE_ERROR,
+ (int)APPCACHE_RESOURCE_ERROR,
ResourceError);
COMPILE_ASSERT((int)WebApplicationCacheHost::ChangedError ==
- (int)appcache::APPCACHE_CHANGED_ERROR,
+ (int)APPCACHE_CHANGED_ERROR,
ChangedError);
COMPILE_ASSERT((int)WebApplicationCacheHost::AbortError ==
- (int)appcache::APPCACHE_ABORT_ERROR,
+ (int)APPCACHE_ABORT_ERROR,
AbortError);
COMPILE_ASSERT((int)WebApplicationCacheHost::QuotaError ==
- (int)appcache::APPCACHE_QUOTA_ERROR,
+ (int)APPCACHE_QUOTA_ERROR,
QuotaError);
COMPILE_ASSERT((int)WebApplicationCacheHost::PolicyError ==
- (int)appcache::APPCACHE_POLICY_ERROR,
+ (int)APPCACHE_POLICY_ERROR,
PolicyError);
COMPILE_ASSERT((int)WebApplicationCacheHost::UnknownError ==
- (int)appcache::APPCACHE_UNKNOWN_ERROR,
+ (int)APPCACHE_UNKNOWN_ERROR,
UnknownError);
} // namespace content
diff --git a/chromium/content/child/appcache/appcache_frontend_impl.h b/chromium/content/child/appcache/appcache_frontend_impl.h
index 90ac4fe3c9c..e0bbdc6999e 100644
--- a/chromium/content/child/appcache/appcache_frontend_impl.h
+++ b/chromium/content/child/appcache/appcache_frontend_impl.h
@@ -5,29 +5,27 @@
#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
#define CONTENT_CHILD_APPCACHE_APPCACHE_FRONTEND_IMPL_H_
-#include "webkit/common/appcache/appcache_interfaces.h"
+#include "content/common/appcache_interfaces.h"
namespace content {
-class AppCacheFrontendImpl : public appcache::AppCacheFrontend {
+class AppCacheFrontendImpl : public AppCacheFrontend {
public:
- virtual void OnCacheSelected(int host_id,
- const appcache::AppCacheInfo& info) OVERRIDE;
- virtual void OnStatusChanged(const std::vector<int>& host_ids,
- appcache::AppCacheStatus status) OVERRIDE;
- virtual void OnEventRaised(const std::vector<int>& host_ids,
- appcache::AppCacheEventID event_id) OVERRIDE;
- virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
- const GURL& url,
- int num_total,
- int num_complete) OVERRIDE;
- virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
- const appcache::AppCacheErrorDetails& details)
- OVERRIDE;
- virtual void OnLogMessage(int host_id,
- appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE;
- virtual void OnContentBlocked(int host_id, const GURL& manifest_url) OVERRIDE;
+ void OnCacheSelected(int host_id, const AppCacheInfo& info) override;
+ void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) override;
+ void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) override;
+ void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total,
+ int num_complete) override;
+ void OnErrorEventRaised(const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) override;
+ void OnLogMessage(int host_id,
+ AppCacheLogLevel log_level,
+ const std::string& message) override;
+ void OnContentBlocked(int host_id, const GURL& manifest_url) override;
};
} // namespace content
diff --git a/chromium/content/child/appcache/web_application_cache_host_impl.cc b/chromium/content/child/appcache/web_application_cache_host_impl.cc
index 427262ed0b9..bf110b16e4e 100644
--- a/chromium/content/child/appcache/web_application_cache_host_impl.cc
+++ b/chromium/content/child/appcache/web_application_cache_host_impl.cc
@@ -20,8 +20,6 @@ using blink::WebURLRequest;
using blink::WebURL;
using blink::WebURLResponse;
using blink::WebVector;
-using appcache::AppCacheBackend;
-using appcache::AppCacheResourceInfo;
namespace content {
@@ -61,12 +59,12 @@ WebApplicationCacheHostImpl::WebApplicationCacheHostImpl(
: client_(client),
backend_(backend),
host_id_(all_hosts()->Add(this)),
- status_(appcache::APPCACHE_STATUS_UNCACHED),
+ status_(APPCACHE_STATUS_UNCACHED),
is_scheme_supported_(false),
is_get_method_(false),
is_new_master_entry_(MAYBE),
was_select_cache_called_(false) {
- DCHECK(client && backend && (host_id_ != appcache::kAppCacheNoHostId));
+ DCHECK(client && backend && (host_id_ != kAppCacheNoHostId));
backend_->RegisterHost(host_id_);
}
@@ -77,45 +75,45 @@ WebApplicationCacheHostImpl::~WebApplicationCacheHostImpl() {
}
void WebApplicationCacheHostImpl::OnCacheSelected(
- const appcache::AppCacheInfo& info) {
+ const AppCacheInfo& info) {
cache_info_ = info;
client_->didChangeCacheAssociation();
}
void WebApplicationCacheHostImpl::OnStatusChanged(
- appcache::AppCacheStatus status) {
+ AppCacheStatus status) {
// TODO(michaeln): delete me, not used
}
void WebApplicationCacheHostImpl::OnEventRaised(
- appcache::AppCacheEventID event_id) {
+ AppCacheEventID event_id) {
DCHECK(event_id !=
- appcache::APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised.
- DCHECK(event_id != appcache::APPCACHE_ERROR_EVENT); // See OnErrorEventRaised.
+ APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised.
+ DCHECK(event_id != APPCACHE_ERROR_EVENT); // See OnErrorEventRaised.
// Emit logging output prior to calling out to script as we can get
// deleted within the script event handler.
const char* kFormatString = "Application Cache %s event";
std::string message = base::StringPrintf(kFormatString,
kEventNames[event_id]);
- OnLogMessage(appcache::APPCACHE_LOG_INFO, message);
+ OnLogMessage(APPCACHE_LOG_INFO, message);
switch (event_id) {
- case appcache::APPCACHE_CHECKING_EVENT:
- status_ = appcache::APPCACHE_STATUS_CHECKING;
+ case APPCACHE_CHECKING_EVENT:
+ status_ = APPCACHE_STATUS_CHECKING;
break;
- case appcache::APPCACHE_DOWNLOADING_EVENT:
- status_ = appcache::APPCACHE_STATUS_DOWNLOADING;
+ case APPCACHE_DOWNLOADING_EVENT:
+ status_ = APPCACHE_STATUS_DOWNLOADING;
break;
- case appcache::APPCACHE_UPDATE_READY_EVENT:
- status_ = appcache::APPCACHE_STATUS_UPDATE_READY;
+ case APPCACHE_UPDATE_READY_EVENT:
+ status_ = APPCACHE_STATUS_UPDATE_READY;
break;
- case appcache::APPCACHE_CACHED_EVENT:
- case appcache::APPCACHE_NO_UPDATE_EVENT:
- status_ = appcache::APPCACHE_STATUS_IDLE;
+ case APPCACHE_CACHED_EVENT:
+ case APPCACHE_NO_UPDATE_EVENT:
+ status_ = APPCACHE_STATUS_IDLE;
break;
- case appcache::APPCACHE_OBSOLETE_EVENT:
- status_ = appcache::APPCACHE_STATUS_OBSOLETE;
+ case APPCACHE_OBSOLETE_EVENT:
+ status_ = APPCACHE_STATUS_OBSOLETE;
break;
default:
NOTREACHED();
@@ -132,25 +130,25 @@ void WebApplicationCacheHostImpl::OnProgressEventRaised(
const char* kFormatString = "Application Cache Progress event (%d of %d) %s";
std::string message = base::StringPrintf(kFormatString, num_complete,
num_total, url.spec().c_str());
- OnLogMessage(appcache::APPCACHE_LOG_INFO, message);
- status_ = appcache::APPCACHE_STATUS_DOWNLOADING;
+ OnLogMessage(APPCACHE_LOG_INFO, message);
+ status_ = APPCACHE_STATUS_DOWNLOADING;
client_->notifyProgressEventListener(url, num_total, num_complete);
}
void WebApplicationCacheHostImpl::OnErrorEventRaised(
- const appcache::AppCacheErrorDetails& details) {
+ const AppCacheErrorDetails& details) {
// Emit logging output prior to calling out to script as we can get
// deleted within the script event handler.
const char* kFormatString = "Application Cache Error event: %s";
std::string full_message =
base::StringPrintf(kFormatString, details.message.c_str());
- OnLogMessage(appcache::APPCACHE_LOG_ERROR, full_message);
+ OnLogMessage(APPCACHE_LOG_ERROR, full_message);
- status_ = cache_info_.is_complete ? appcache::APPCACHE_STATUS_IDLE :
- appcache::APPCACHE_STATUS_UNCACHED;
+ status_ = cache_info_.is_complete ? APPCACHE_STATUS_IDLE :
+ APPCACHE_STATUS_UNCACHED;
if (details.is_cross_origin) {
// Don't leak detailed information to script for cross-origin resources.
- DCHECK_EQ(appcache::APPCACHE_RESOURCE_ERROR, details.reason);
+ DCHECK_EQ(APPCACHE_RESOURCE_ERROR, details.reason);
client_->notifyErrorEventListener(
static_cast<ErrorReason>(details.reason), details.url, 0, WebString());
} else {
@@ -168,13 +166,13 @@ void WebApplicationCacheHostImpl::willStartMainResourceRequest(
original_main_resource_url_ = ClearUrlRef(request.url());
std::string method = request.httpMethod().utf8();
- is_get_method_ = (method == appcache::kHttpGETMethod);
+ is_get_method_ = (method == kHttpGETMethod);
DCHECK(method == StringToUpperASCII(method));
const WebApplicationCacheHostImpl* spawning_host_impl =
static_cast<const WebApplicationCacheHostImpl*>(spawning_host);
if (spawning_host_impl && (spawning_host_impl != this) &&
- (spawning_host_impl->status_ != appcache::APPCACHE_STATUS_UNCACHED)) {
+ (spawning_host_impl->status_ != APPCACHE_STATUS_UNCACHED)) {
backend_->SetSpawningHostId(host_id_, spawning_host_impl->host_id());
}
}
@@ -189,8 +187,8 @@ void WebApplicationCacheHostImpl::selectCacheWithoutManifest() {
return;
was_select_cache_called_ = true;
- status_ = (document_response_.appCacheID() == appcache::kAppCacheNoCacheId) ?
- appcache::APPCACHE_STATUS_UNCACHED : appcache::APPCACHE_STATUS_CHECKING;
+ status_ = (document_response_.appCacheID() == kAppCacheNoCacheId) ?
+ APPCACHE_STATUS_UNCACHED : APPCACHE_STATUS_CHECKING;
is_new_master_entry_ = NO;
backend_->SelectCache(host_id_, document_url_,
document_response_.appCacheID(),
@@ -207,18 +205,18 @@ bool WebApplicationCacheHostImpl::selectCacheWithManifest(
// 6.9.6 The application cache selection algorithm
// Check for new 'master' entries.
- if (document_response_.appCacheID() == appcache::kAppCacheNoCacheId) {
+ if (document_response_.appCacheID() == kAppCacheNoCacheId) {
if (is_scheme_supported_ && is_get_method_ &&
(manifest_gurl.GetOrigin() == document_url_.GetOrigin())) {
- status_ = appcache::APPCACHE_STATUS_CHECKING;
+ status_ = APPCACHE_STATUS_CHECKING;
is_new_master_entry_ = YES;
} else {
- status_ = appcache::APPCACHE_STATUS_UNCACHED;
+ status_ = APPCACHE_STATUS_UNCACHED;
is_new_master_entry_ = NO;
manifest_gurl = GURL();
}
backend_->SelectCache(
- host_id_, document_url_, appcache::kAppCacheNoCacheId, manifest_gurl);
+ host_id_, document_url_, kAppCacheNoCacheId, manifest_gurl);
return true;
}
@@ -230,11 +228,11 @@ bool WebApplicationCacheHostImpl::selectCacheWithManifest(
if (document_manifest_gurl != manifest_gurl) {
backend_->MarkAsForeignEntry(host_id_, document_url_,
document_response_.appCacheID());
- status_ = appcache::APPCACHE_STATUS_UNCACHED;
+ status_ = APPCACHE_STATUS_UNCACHED;
return false; // the navigation will be restarted
}
- status_ = appcache::APPCACHE_STATUS_CHECKING;
+ status_ = APPCACHE_STATUS_CHECKING;
// Its a 'master' entry thats already in the cache.
backend_->SelectCache(host_id_, document_url_,
@@ -251,14 +249,14 @@ void WebApplicationCacheHostImpl::didReceiveResponseForMainResource(
is_get_method_ = true; // A redirect was involved.
original_main_resource_url_ = GURL();
- is_scheme_supported_ = appcache::IsSchemeSupported(document_url_);
- if ((document_response_.appCacheID() != appcache::kAppCacheNoCacheId) ||
+ is_scheme_supported_ = IsSchemeSupportedForAppCache(document_url_);
+ if ((document_response_.appCacheID() != kAppCacheNoCacheId) ||
!is_scheme_supported_ || !is_get_method_)
is_new_master_entry_ = NO;
}
void WebApplicationCacheHostImpl::didReceiveDataForMainResource(
- const char* data, int len) {
+ const char* data, unsigned len) {
if (is_new_master_entry_ == NO)
return;
// TODO(michaeln): write me
@@ -277,9 +275,9 @@ WebApplicationCacheHost::Status WebApplicationCacheHostImpl::status() {
bool WebApplicationCacheHostImpl::startUpdate() {
if (!backend_->StartUpdate(host_id_))
return false;
- if (status_ == appcache::APPCACHE_STATUS_IDLE ||
- status_ == appcache::APPCACHE_STATUS_UPDATE_READY)
- status_ = appcache::APPCACHE_STATUS_CHECKING;
+ if (status_ == APPCACHE_STATUS_IDLE ||
+ status_ == APPCACHE_STATUS_UPDATE_READY)
+ status_ = APPCACHE_STATUS_CHECKING;
else
status_ = backend_->GetStatus(host_id_);
return true;
diff --git a/chromium/content/child/appcache/web_application_cache_host_impl.h b/chromium/content/child/appcache/web_application_cache_host_impl.h
index 07ec2dbaa3c..4c81d46bb96 100644
--- a/chromium/content/child/appcache/web_application_cache_host_impl.h
+++ b/chromium/content/child/appcache/web_application_cache_host_impl.h
@@ -7,12 +7,12 @@
#include <string>
+#include "content/common/appcache_interfaces.h"
#include "third_party/WebKit/public/platform/WebApplicationCacheHost.h"
#include "third_party/WebKit/public/platform/WebApplicationCacheHostClient.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "url/gurl.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
namespace content {
@@ -23,19 +23,19 @@ class WebApplicationCacheHostImpl
static WebApplicationCacheHostImpl* FromId(int id);
WebApplicationCacheHostImpl(blink::WebApplicationCacheHostClient* client,
- appcache::AppCacheBackend* backend);
+ AppCacheBackend* backend);
virtual ~WebApplicationCacheHostImpl();
int host_id() const { return host_id_; }
- appcache::AppCacheBackend* backend() const { return backend_; }
+ AppCacheBackend* backend() const { return backend_; }
blink::WebApplicationCacheHostClient* client() const { return client_; }
- virtual void OnCacheSelected(const appcache::AppCacheInfo& info);
- void OnStatusChanged(appcache::AppCacheStatus);
- void OnEventRaised(appcache::AppCacheEventID);
+ virtual void OnCacheSelected(const AppCacheInfo& info);
+ void OnStatusChanged(AppCacheStatus);
+ void OnEventRaised(AppCacheEventID);
void OnProgressEventRaised(const GURL& url, int num_total, int num_complete);
- void OnErrorEventRaised(const appcache::AppCacheErrorDetails& details);
- virtual void OnLogMessage(appcache::AppCacheLogLevel log_level,
+ void OnErrorEventRaised(const AppCacheErrorDetails& details);
+ virtual void OnLogMessage(AppCacheLogLevel log_level,
const std::string& message) {}
virtual void OnContentBlocked(const GURL& manifest_url) {}
@@ -46,7 +46,7 @@ class WebApplicationCacheHostImpl
virtual void selectCacheWithoutManifest();
virtual bool selectCacheWithManifest(const blink::WebURL& manifestURL);
virtual void didReceiveResponseForMainResource(const blink::WebURLResponse&);
- virtual void didReceiveDataForMainResource(const char* data, int len);
+ virtual void didReceiveDataForMainResource(const char* data, unsigned len);
virtual void didFinishLoadingMainResource(bool success);
virtual blink::WebApplicationCacheHost::Status status();
virtual bool startUpdate();
@@ -62,15 +62,15 @@ class WebApplicationCacheHostImpl
};
blink::WebApplicationCacheHostClient* client_;
- appcache::AppCacheBackend* backend_;
+ AppCacheBackend* backend_;
int host_id_;
- appcache::AppCacheStatus status_;
+ AppCacheStatus status_;
blink::WebURLResponse document_response_;
GURL document_url_;
bool is_scheme_supported_;
bool is_get_method_;
IsNewMasterEntry is_new_master_entry_;
- appcache::AppCacheInfo cache_info_;
+ AppCacheInfo cache_info_;
GURL original_main_resource_url_; // Used to detect redirection.
bool was_select_cache_called_;
};
diff --git a/chromium/content/child/assert_matching_enums.cc b/chromium/content/child/assert_matching_enums.cc
index df3d030149a..89ff842d483 100644
--- a/chromium/content/child/assert_matching_enums.cc
+++ b/chromium/content/child/assert_matching_enums.cc
@@ -8,7 +8,8 @@
#include "base/macros.h"
#include "cc/animation/animation.h"
#include "content/public/common/screen_orientation_values.h"
-#include "third_party/WebKit/public/platform/WebAnimation.h"
+#include "net/base/mime_util.h"
+#include "third_party/WebKit/public/platform/WebCompositorAnimation.h"
#include "third_party/WebKit/public/platform/WebMimeRegistry.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
@@ -19,32 +20,44 @@ namespace content {
// ScreenOrientationValues
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockDefault,
- DEFAULT);
+ SCREEN_ORIENTATION_VALUES_DEFAULT);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockPortraitPrimary,
- PORTRAIT_PRIMARY);
+ SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockPortraitSecondary,
- PORTRAIT_SECONDARY);
+ SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockLandscapePrimary,
- LANDSCAPE_PRIMARY);
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockLandscapeSecondary,
- LANDSCAPE_SECONDARY);
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockAny,
- ANY);
+ SCREEN_ORIENTATION_VALUES_ANY);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockLandscape,
- LANDSCAPE);
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE);
COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockPortrait,
- PORTRAIT);
+ SCREEN_ORIENTATION_VALUES_PORTRAIT);
+COMPILE_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockNatural,
+ SCREEN_ORIENTATION_VALUES_NATURAL);
+
+// SupportsType
+COMPILE_ASSERT_MATCHING_ENUM(blink::WebMimeRegistry::IsNotSupported,
+ net::IsNotSupported);
+COMPILE_ASSERT_MATCHING_ENUM(blink::WebMimeRegistry::IsSupported,
+ net::IsSupported);
+COMPILE_ASSERT_MATCHING_ENUM(blink::WebMimeRegistry::MayBeSupported,
+ net::MayBeSupported);
// TargetProperty
-COMPILE_ASSERT_MATCHING_ENUM(blink::WebAnimation::TargetPropertyTransform,
+COMPILE_ASSERT_MATCHING_ENUM(
+ blink::WebCompositorAnimation::TargetPropertyTransform,
cc::Animation::Transform);
-COMPILE_ASSERT_MATCHING_ENUM(blink::WebAnimation::TargetPropertyOpacity,
+COMPILE_ASSERT_MATCHING_ENUM(
+ blink::WebCompositorAnimation::TargetPropertyOpacity,
cc::Animation::Opacity);
-COMPILE_ASSERT_MATCHING_ENUM(blink::WebAnimation::TargetPropertyFilter,
+COMPILE_ASSERT_MATCHING_ENUM(
+ blink::WebCompositorAnimation::TargetPropertyFilter,
cc::Animation::Filter);
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-COMPILE_ASSERT_MATCHING_ENUM(blink::WebAnimation::TargetPropertyScrollOffset,
+COMPILE_ASSERT_MATCHING_ENUM(
+ blink::WebCompositorAnimation::TargetPropertyScrollOffset,
cc::Animation::ScrollOffset);
-#endif
} // namespace content
diff --git a/chromium/content/child/blink_glue.cc b/chromium/content/child/blink_glue.cc
deleted file mode 100644
index 9a3af757baf..00000000000
--- a/chromium/content/child/blink_glue.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 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 "content/child/blink_glue.h"
-
-#include "base/logging.h"
-#include "third_party/WebKit/public/platform/WebFileInfo.h"
-
-namespace content {
-
-void FileInfoToWebFileInfo(const base::File::Info& file_info,
- blink::WebFileInfo* web_file_info) {
- DCHECK(web_file_info);
- // WebKit now expects NaN as uninitialized/null Date.
- if (file_info.last_modified.is_null())
- web_file_info->modificationTime = std::numeric_limits<double>::quiet_NaN();
- else
- web_file_info->modificationTime = file_info.last_modified.ToDoubleT();
- web_file_info->length = file_info.size;
- if (file_info.is_directory)
- web_file_info->type = blink::WebFileInfo::TypeDirectory;
- else
- web_file_info->type = blink::WebFileInfo::TypeFile;
-}
-
-COMPILE_ASSERT(std::numeric_limits<double>::has_quiet_NaN, has_quiet_NaN);
-
-} // namespace content
diff --git a/chromium/content/child/blink_glue.h b/chromium/content/child/blink_glue.h
deleted file mode 100644
index 0181472d831..00000000000
--- a/chromium/content/child/blink_glue.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_BLINK_GLUE_H_
-#define CONTENT_CHILD_BLINK_GLUE_H_
-
-#include "base/files/file.h"
-#include "content/common/content_export.h"
-
-namespace blink {
-struct WebFileInfo;
-}
-
-namespace content {
-
-// File info conversion
-CONTENT_EXPORT void FileInfoToWebFileInfo(const base::File::Info& file_info,
- blink::WebFileInfo* web_file_info);
-
-} // namespace content
-
-#endif // CONTENT_CHILD_BLINK_GLUE_H_
diff --git a/chromium/content/child/blink_platform_impl.cc b/chromium/content/child/blink_platform_impl.cc
index ab0afb6a58f..144a98314ee 100644
--- a/chromium/content/child/blink_platform_impl.cc
+++ b/chromium/content/child/blink_platform_impl.cc
@@ -25,33 +25,37 @@
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/sys_info.h"
+#include "base/threading/platform_thread.h"
#include "base/time/time.h"
+#include "blink/public/resources/grit/blink_resources.h"
+#include "content/app/resources/grit/content_resources.h"
+#include "content/app/strings/grit/content_strings.h"
+#include "content/child/child_thread.h"
#include "content/child/content_child_helpers.h"
-#include "content/child/fling_curve_configuration.h"
+#include "content/child/geofencing/web_geofencing_provider_impl.h"
+#include "content/child/notifications/notification_dispatcher.h"
+#include "content/child/notifications/notification_manager.h"
+#include "content/child/thread_safe_sender.h"
#include "content/child/web_discardable_memory_impl.h"
-#include "content/child/web_socket_stream_handle_impl.h"
+#include "content/child/web_gesture_curve_impl.h"
#include "content/child/web_url_loader_impl.h"
#include "content/child/websocket_bridge.h"
#include "content/child/webthread_impl.h"
#include "content/child/worker_task_runner.h"
#include "content/public/common/content_client.h"
-#include "grit/blink_resources.h"
-#include "grit/webkit_resources.h"
-#include "grit/webkit_strings.h"
#include "net/base/data_url.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
#include "third_party/WebKit/public/platform/WebConvertableToTraceFormat.h"
#include "third_party/WebKit/public/platform/WebData.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebWaitableEvent.h"
+#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "ui/base/layout.h"
-#if defined(OS_ANDROID)
-#include "base/android/sys_utils.h"
-#include "content/child/fling_animator_impl_android.h"
-#endif
-
#if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
#endif
@@ -60,7 +64,6 @@ using blink::WebData;
using blink::WebFallbackThemeEngine;
using blink::WebLocalizedString;
using blink::WebString;
-using blink::WebSocketStreamHandle;
using blink::WebThemeEngine;
using blink::WebURL;
using blink::WebURLError;
@@ -141,16 +144,23 @@ class ConvertableToTraceFormatWrapper
explicit ConvertableToTraceFormatWrapper(
const blink::WebConvertableToTraceFormat& convertable)
: convertable_(convertable) {}
- virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
+ void AppendAsTraceFormat(std::string* out) const override {
*out += convertable_.asTraceFormat().utf8();
}
private:
- virtual ~ConvertableToTraceFormatWrapper() {}
+ ~ConvertableToTraceFormatWrapper() override {}
blink::WebConvertableToTraceFormat convertable_;
};
+bool isHostnameReservedIPAddress(const std::string& host) {
+ net::IPAddressNumber address;
+ if (!net::ParseURLHostnameToNumber(host, &address))
+ return false;
+ return net::IsIPAddressReserved(address);
+}
+
} // namespace
static int ToMessageID(WebLocalizedString::Name name) {
@@ -159,6 +169,14 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_AM_PM_FIELD_TEXT;
case WebLocalizedString::AXButtonActionVerb:
return IDS_AX_BUTTON_ACTION_VERB;
+ case WebLocalizedString::AXCalendarShowMonthSelector:
+ return IDS_AX_CALENDAR_SHOW_MONTH_SELECTOR;
+ case WebLocalizedString::AXCalendarShowNextMonth:
+ return IDS_AX_CALENDAR_SHOW_NEXT_MONTH;
+ case WebLocalizedString::AXCalendarShowPreviousMonth:
+ return IDS_AX_CALENDAR_SHOW_PREVIOUS_MONTH;
+ case WebLocalizedString::AXCalendarWeekDescription:
+ return IDS_AX_CALENDAR_WEEK_DESCRIPTION;
case WebLocalizedString::AXCheckedCheckBoxActionVerb:
return IDS_AX_CHECKED_CHECK_BOX_ACTION_VERB;
case WebLocalizedString::AXDateTimeFieldEmptyValueText:
@@ -209,6 +227,10 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON;
case WebLocalizedString::AXMediaHideClosedCaptionsButton:
return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON;
+ case WebLocalizedString::AxMediaCastOffButton:
+ return IDS_AX_MEDIA_CAST_OFF_BUTTON;
+ case WebLocalizedString::AxMediaCastOnButton:
+ return IDS_AX_MEDIA_CAST_ON_BUTTON;
case WebLocalizedString::AXMediaAudioElementHelp:
return IDS_AX_MEDIA_AUDIO_ELEMENT_HELP;
case WebLocalizedString::AXMediaVideoElementHelp:
@@ -239,6 +261,10 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_MEDIA_SHOW_CLOSED_CAPTIONS_BUTTON_HELP;
case WebLocalizedString::AXMediaHideClosedCaptionsButtonHelp:
return IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON_HELP;
+ case WebLocalizedString::AxMediaCastOffButtonHelp:
+ return IDS_AX_MEDIA_CAST_OFF_BUTTON_HELP;
+ case WebLocalizedString::AxMediaCastOnButtonHelp:
+ return IDS_AX_MEDIA_CAST_ON_BUTTON_HELP;
case WebLocalizedString::AXMillisecondFieldText:
return IDS_AX_MILLISECOND_FIELD_TEXT;
case WebLocalizedString::AXMinuteFieldText:
@@ -341,6 +367,8 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_FORM_VALIDATION_STEP_MISMATCH_CLOSE_TO_LIMIT;
case WebLocalizedString::ValidationTooLong:
return IDS_FORM_VALIDATION_TOO_LONG;
+ case WebLocalizedString::ValidationTooShort:
+ return IDS_FORM_VALIDATION_TOO_SHORT;
case WebLocalizedString::ValidationTypeMismatch:
return IDS_FORM_VALIDATION_TYPE_MISMATCH;
case WebLocalizedString::ValidationTypeMismatchForEmail:
@@ -395,18 +423,26 @@ BlinkPlatformImpl::BlinkPlatformImpl()
shared_timer_fire_time_(0.0),
shared_timer_fire_time_was_set_while_suspended_(false),
shared_timer_suspended_(0),
- fling_curve_configuration_(new FlingCurveConfiguration),
- current_thread_slot_(&DestroyCurrentThread) {}
+ current_thread_slot_(&DestroyCurrentThread) {
+ // ChildThread may not exist in some tests.
+ if (ChildThread::current()) {
+ geofencing_provider_.reset(new WebGeofencingProviderImpl(
+ ChildThread::current()->thread_safe_sender()));
+ thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
+ notification_dispatcher_ =
+ ChildThread::current()->notification_dispatcher();
+ }
+}
BlinkPlatformImpl::~BlinkPlatformImpl() {
}
WebURLLoader* BlinkPlatformImpl::createURLLoader() {
- return new WebURLLoaderImpl;
-}
-
-WebSocketStreamHandle* BlinkPlatformImpl::createSocketStreamHandle() {
- return new WebSocketStreamHandleImpl;
+ ChildThread* child_thread = ChildThread::current();
+ // There may be no child thread in RenderViewTests. These tests can still use
+ // data URLs to bypass the ResourceDispatcher.
+ return new WebURLLoaderImpl(
+ child_thread ? child_thread->resource_dispatcher() : NULL);
}
blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
@@ -435,6 +471,15 @@ WebURLError BlinkPlatformImpl::cancelledError(
return WebURLLoaderImpl::CreateError(unreachableURL, false, net::ERR_ABORTED);
}
+bool BlinkPlatformImpl::isReservedIPAddress(
+ const blink::WebSecurityOrigin& securityOrigin) const {
+ return isHostnameReservedIPAddress(securityOrigin.host().utf8());
+}
+
+bool BlinkPlatformImpl::isReservedIPAddress(const blink::WebURL& url) const {
+ return isHostnameReservedIPAddress(GURL(url).host());
+}
+
blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
return new WebThreadImpl(name);
}
@@ -455,6 +500,10 @@ blink::WebThread* BlinkPlatformImpl::currentThread() {
return thread;
}
+void BlinkPlatformImpl::yieldCurrentThread() {
+ base::PlatformThread::YieldCurrentThread();
+}
+
blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() {
return new WebWaitableEventImpl();
}
@@ -731,8 +780,14 @@ const DataResource kDataResources[] = {
IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_HOVER, ui::SCALE_FACTOR_100P },
{ "mediaplayerFullscreenDown",
IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DOWN, ui::SCALE_FACTOR_100P },
+ { "mediaplayerCastOff",
+ IDR_MEDIAPLAYER_CAST_BUTTON_OFF, ui::SCALE_FACTOR_100P },
+ { "mediaplayerCastOn",
+ IDR_MEDIAPLAYER_CAST_BUTTON_ON, ui::SCALE_FACTOR_100P },
{ "mediaplayerFullscreenDisabled",
IDR_MEDIAPLAYER_FULLSCREEN_BUTTON_DISABLED, ui::SCALE_FACTOR_100P },
+ { "mediaplayerOverlayCastOff",
+ IDR_MEDIAPLAYER_OVERLAY_CAST_BUTTON_OFF, ui::SCALE_FACTOR_100P },
{ "mediaplayerOverlayPlay",
IDR_MEDIAPLAYER_OVERLAY_PLAY_BUTTON, ui::SCALE_FACTOR_100P },
#if defined(OS_MACOSX)
@@ -750,6 +805,73 @@ const DataResource kDataResources[] = {
{ "generatePassword", IDR_PASSWORD_GENERATION_ICON, ui::SCALE_FACTOR_100P },
{ "generatePasswordHover",
IDR_PASSWORD_GENERATION_ICON_HOVER, ui::SCALE_FACTOR_100P },
+ { "html.css", IDR_UASTYLE_HTML_CSS, ui::SCALE_FACTOR_NONE },
+ { "quirks.css", IDR_UASTYLE_QUIRKS_CSS, ui::SCALE_FACTOR_NONE },
+ { "view-source.css", IDR_UASTYLE_VIEW_SOURCE_CSS, ui::SCALE_FACTOR_NONE },
+ { "themeChromium.css", IDR_UASTYLE_THEME_CHROMIUM_CSS,
+ ui::SCALE_FACTOR_NONE },
+#if defined(OS_ANDROID)
+ { "themeChromiumAndroid.css", IDR_UASTYLE_THEME_CHROMIUM_ANDROID_CSS,
+ ui::SCALE_FACTOR_NONE },
+ { "mediaControlsAndroid.css", IDR_UASTYLE_MEDIA_CONTROLS_ANDROID_CSS,
+ ui::SCALE_FACTOR_NONE },
+#endif
+#if !defined(OS_WIN)
+ { "themeChromiumLinux.css", IDR_UASTYLE_THEME_CHROMIUM_LINUX_CSS,
+ ui::SCALE_FACTOR_NONE },
+#endif
+ { "themeChromiumSkia.css", IDR_UASTYLE_THEME_CHROMIUM_SKIA_CSS,
+ ui::SCALE_FACTOR_NONE },
+ { "themeInputMultipleFields.css",
+ IDR_UASTYLE_THEME_INPUT_MULTIPLE_FIELDS_CSS, ui::SCALE_FACTOR_NONE },
+#if defined(OS_MACOSX)
+ { "themeMac.css", IDR_UASTYLE_THEME_MAC_CSS, ui::SCALE_FACTOR_NONE },
+#endif
+ { "themeWin.css", IDR_UASTYLE_THEME_WIN_CSS, ui::SCALE_FACTOR_NONE },
+ { "themeWinQuirks.css", IDR_UASTYLE_THEME_WIN_QUIRKS_CSS,
+ ui::SCALE_FACTOR_NONE },
+ { "svg.css", IDR_UASTYLE_SVG_CSS, ui::SCALE_FACTOR_NONE},
+ { "navigationTransitions.css", IDR_UASTYLE_NAVIGATION_TRANSITIONS_CSS,
+ ui::SCALE_FACTOR_NONE },
+ { "mathml.css", IDR_UASTYLE_MATHML_CSS, ui::SCALE_FACTOR_NONE},
+ { "mediaControls.css", IDR_UASTYLE_MEDIA_CONTROLS_CSS,
+ ui::SCALE_FACTOR_NONE },
+ { "fullscreen.css", IDR_UASTYLE_FULLSCREEN_CSS, ui::SCALE_FACTOR_NONE},
+ { "xhtmlmp.css", IDR_UASTYLE_XHTMLMP_CSS, ui::SCALE_FACTOR_NONE},
+ { "viewportAndroid.css", IDR_UASTYLE_VIEWPORT_ANDROID_CSS,
+ ui::SCALE_FACTOR_NONE},
+ { "InspectorOverlayPage.html", IDR_INSPECTOR_OVERLAY_PAGE_HTML,
+ ui::SCALE_FACTOR_NONE },
+ { "InjectedScriptCanvasModuleSource.js",
+ IDR_INSPECTOR_INJECTED_SCRIPT_CANVAS_MODULE_SOURCE_JS,
+ ui::SCALE_FACTOR_NONE },
+ { "InjectedScriptSource.js", IDR_INSPECTOR_INJECTED_SCRIPT_SOURCE_JS,
+ ui::SCALE_FACTOR_NONE },
+ { "DebuggerScriptSource.js", IDR_INSPECTOR_DEBUGGER_SCRIPT_SOURCE_JS,
+ ui::SCALE_FACTOR_NONE },
+ { "DocumentExecCommand.js", IDR_PRIVATE_SCRIPT_DOCUMENTEXECCOMMAND_JS,
+ ui::SCALE_FACTOR_NONE },
+ { "DocumentXMLTreeViewer.js", IDR_PRIVATE_SCRIPT_DOCUMENTXMLTREEVIEWER_JS,
+ ui::SCALE_FACTOR_NONE },
+ { "HTMLMarqueeElement.js", IDR_PRIVATE_SCRIPT_HTMLMARQUEEELEMENT_JS,
+ ui::SCALE_FACTOR_NONE },
+ { "PluginPlaceholderElement.js",
+ IDR_PRIVATE_SCRIPT_PLUGINPLACEHOLDERELEMENT_JS, ui::SCALE_FACTOR_NONE },
+ { "PrivateScriptRunner.js", IDR_PRIVATE_SCRIPT_PRIVATESCRIPTRUNNER_JS,
+ ui::SCALE_FACTOR_NONE },
+#ifdef IDR_PICKER_COMMON_JS
+ { "pickerCommon.js", IDR_PICKER_COMMON_JS, ui::SCALE_FACTOR_NONE },
+ { "pickerCommon.css", IDR_PICKER_COMMON_CSS, ui::SCALE_FACTOR_NONE },
+ { "calendarPicker.js", IDR_CALENDAR_PICKER_JS, ui::SCALE_FACTOR_NONE },
+ { "calendarPicker.css", IDR_CALENDAR_PICKER_CSS, ui::SCALE_FACTOR_NONE },
+ { "pickerButton.css", IDR_PICKER_BUTTON_CSS, ui::SCALE_FACTOR_NONE },
+ { "suggestionPicker.js", IDR_SUGGESTION_PICKER_JS, ui::SCALE_FACTOR_NONE },
+ { "suggestionPicker.css", IDR_SUGGESTION_PICKER_CSS, ui::SCALE_FACTOR_NONE },
+ { "colorSuggestionPicker.js",
+ IDR_COLOR_SUGGESTION_PICKER_JS, ui::SCALE_FACTOR_NONE },
+ { "colorSuggestionPicker.css",
+ IDR_COLOR_SUGGESTION_PICKER_CSS, ui::SCALE_FACTOR_NONE },
+#endif
};
} // namespace
@@ -879,18 +1001,10 @@ blink::WebGestureCurve* BlinkPlatformImpl::createFlingAnimationCurve(
blink::WebGestureDevice device_source,
const blink::WebFloatPoint& velocity,
const blink::WebSize& cumulative_scroll) {
-#if defined(OS_ANDROID)
- return FlingAnimatorImpl::CreateAndroidGestureCurve(
- velocity,
- cumulative_scroll);
-#endif
-
- if (device_source == blink::WebGestureDeviceTouchscreen)
- return fling_curve_configuration_->CreateForTouchScreen(velocity,
- cumulative_scroll);
-
- return fling_curve_configuration_->CreateForTouchPad(velocity,
- cumulative_scroll);
+ auto curve = WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
+ gfx::Vector2dF(velocity.x, velocity.y),
+ gfx::Vector2dF(cumulative_scroll.width, cumulative_scroll.height));
+ return curve.release();
}
void BlinkPlatformImpl::didStartWorkerRunLoop(
@@ -906,10 +1020,22 @@ void BlinkPlatformImpl::didStopWorkerRunLoop(
}
blink::WebCrypto* BlinkPlatformImpl::crypto() {
- WebCryptoImpl::EnsureInit();
return &web_crypto_;
}
+blink::WebGeofencingProvider* BlinkPlatformImpl::geofencingProvider() {
+ return geofencing_provider_.get();
+}
+
+blink::WebNotificationManager*
+BlinkPlatformImpl::notificationManager() {
+ if (!thread_safe_sender_.get() || !notification_dispatcher_.get())
+ return nullptr;
+
+ return NotificationManager::ThreadSpecificInstance(
+ thread_safe_sender_.get(),
+ notification_dispatcher_.get());
+}
WebThemeEngine* BlinkPlatformImpl::themeEngine() {
return &native_theme_engine_;
@@ -1054,7 +1180,7 @@ BlinkPlatformImpl::allocateAndLockDiscardableMemory(size_t bytes) {
size_t BlinkPlatformImpl::maxDecodedImageBytes() {
#if defined(OS_ANDROID)
- if (base::android::SysUtils::IsLowEndDevice()) {
+ if (base::SysInfo::IsLowEndDevice()) {
// Limit image decoded size to 3M pixels on low end devices.
// 4 is maximum number of bytes per pixel.
return 3 * 1024 * 1024 * 4;
@@ -1072,12 +1198,6 @@ size_t BlinkPlatformImpl::maxDecodedImageBytes() {
#endif
}
-void BlinkPlatformImpl::SetFlingCurveParameters(
- const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen) {
- fling_curve_configuration_->SetCurveParameters(new_touchpad, new_touchscreen);
-}
-
void BlinkPlatformImpl::SuspendSharedTimer() {
++shared_timer_suspended_;
}
diff --git a/chromium/content/child/blink_platform_impl.h b/chromium/content/child/blink_platform_impl.h
index e9d3e186cc9..785b0d6418a 100644
--- a/chromium/content/child/blink_platform_impl.h
+++ b/chromium/content/child/blink_platform_impl.h
@@ -33,7 +33,10 @@ class MessageLoop;
namespace content {
class FlingCurveConfiguration;
+class NotificationDispatcher;
+class ThreadSafeSender;
class WebCryptoImpl;
+class WebGeofencingProviderImpl;
class CONTENT_EXPORT BlinkPlatformImpl
: NON_EXPORTED_BASE(public blink::Platform) {
@@ -63,26 +66,29 @@ class CONTENT_EXPORT BlinkPlatformImpl
virtual size_t numberOfProcessors();
virtual void startHeapProfiling(const blink::WebString& prefix);
- virtual void stopHeapProfiling() OVERRIDE;
+ virtual void stopHeapProfiling();
virtual void dumpHeapProfiling(const blink::WebString& reason);
- virtual blink::WebString getHeapProfile() OVERRIDE;
+ virtual blink::WebString getHeapProfile();
virtual bool processMemorySizesInBytes(size_t* private_bytes,
size_t* shared_bytes);
virtual bool memoryAllocatorWasteInBytes(size_t* size);
virtual blink::WebDiscardableMemory* allocateAndLockDiscardableMemory(
size_t bytes);
- virtual size_t maxDecodedImageBytes() OVERRIDE;
+ virtual size_t maxDecodedImageBytes();
virtual blink::WebURLLoader* createURLLoader();
- virtual blink::WebSocketStreamHandle* createSocketStreamHandle();
- virtual blink::WebSocketHandle* createWebSocketHandle() OVERRIDE;
+ virtual blink::WebSocketHandle* createWebSocketHandle();
virtual blink::WebString userAgent();
virtual blink::WebData parseDataURL(
const blink::WebURL& url, blink::WebString& mimetype,
blink::WebString& charset);
virtual blink::WebURLError cancelledError(const blink::WebURL& url) const;
+ virtual bool isReservedIPAddress(
+ const blink::WebSecurityOrigin&) const;
+ virtual bool isReservedIPAddress(const blink::WebURL&) const;
virtual blink::WebThread* createThread(const char* name);
virtual blink::WebThread* currentThread();
+ virtual void yieldCurrentThread();
virtual blink::WebWaitableEvent* createWaitableEvent();
virtual blink::WebWaitableEvent* waitMultipleEvents(
const blink::WebVector<blink::WebWaitableEvent*>& events);
@@ -143,15 +149,14 @@ class CONTENT_EXPORT BlinkPlatformImpl
virtual blink::WebGestureCurve* createFlingAnimationCurve(
blink::WebGestureDevice device_source,
const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulative_scroll) OVERRIDE;
+ const blink::WebSize& cumulative_scroll);
virtual void didStartWorkerRunLoop(
- const blink::WebWorkerRunLoop& runLoop) OVERRIDE;
+ const blink::WebWorkerRunLoop& runLoop);
virtual void didStopWorkerRunLoop(
- const blink::WebWorkerRunLoop& runLoop) OVERRIDE;
- virtual blink::WebCrypto* crypto() OVERRIDE;
-
- void SetFlingCurveParameters(const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen);
+ const blink::WebWorkerRunLoop& runLoop);
+ virtual blink::WebCrypto* crypto();
+ virtual blink::WebGeofencingProvider* geofencingProvider();
+ virtual blink::WebNotificationManager* notificationManager();
void SuspendSharedTimer();
void ResumeSharedTimer();
@@ -173,9 +178,12 @@ class CONTENT_EXPORT BlinkPlatformImpl
double shared_timer_fire_time_;
bool shared_timer_fire_time_was_set_while_suspended_;
int shared_timer_suspended_; // counter
- scoped_ptr<FlingCurveConfiguration> fling_curve_configuration_;
base::ThreadLocalStorage::Slot current_thread_slot_;
WebCryptoImpl web_crypto_;
+ scoped_ptr<WebGeofencingProviderImpl> geofencing_provider_;
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+ scoped_refptr<NotificationDispatcher> notification_dispatcher_;
};
} // namespace content
diff --git a/chromium/content/child/blink_platform_impl_unittest.cc b/chromium/content/child/blink_platform_impl_unittest.cc
new file mode 100644
index 00000000000..661ce192e9a
--- /dev/null
+++ b/chromium/content/child/blink_platform_impl_unittest.cc
@@ -0,0 +1,197 @@
+// Copyright 2014 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 "content/child/blink_platform_impl.h"
+
+#include "base/run_loop.h"
+#include "base/time/time.h"
+#include "net/base/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
+
+namespace content {
+
+// Derives BlinkPlatformImpl for testing shared timers.
+class TestBlinkPlatformImpl : public BlinkPlatformImpl {
+ public:
+ TestBlinkPlatformImpl() : mock_monotonically_increasing_time_(0) {}
+
+ // Returns mock time when enabled.
+ virtual double monotonicallyIncreasingTime() override {
+ if (mock_monotonically_increasing_time_ > 0.0)
+ return mock_monotonically_increasing_time_;
+ return BlinkPlatformImpl::monotonicallyIncreasingTime();
+ }
+
+ void OnStartSharedTimer(base::TimeDelta delay) override {
+ shared_timer_delay_ = delay;
+ }
+
+ base::TimeDelta shared_timer_delay() { return shared_timer_delay_; }
+
+ void set_mock_monotonically_increasing_time(double mock_time) {
+ mock_monotonically_increasing_time_ = mock_time;
+ }
+
+ private:
+ base::TimeDelta shared_timer_delay_;
+ double mock_monotonically_increasing_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBlinkPlatformImpl);
+};
+
+TEST(BlinkPlatformTest, SuspendResumeSharedTimer) {
+ base::MessageLoop message_loop;
+
+ TestBlinkPlatformImpl platform_impl;
+
+ // Set a timer to fire as soon as possible.
+ platform_impl.setSharedTimerFireInterval(0);
+
+ // Suspend timers immediately so the above timer wouldn't be fired.
+ platform_impl.SuspendSharedTimer();
+
+ // The above timer would have posted a task which can be processed out of the
+ // message loop.
+ base::RunLoop().RunUntilIdle();
+
+ // Set a mock time after 1 second to simulate timers suspended for 1 second.
+ double new_time = base::Time::Now().ToDoubleT() + 1;
+ platform_impl.set_mock_monotonically_increasing_time(new_time);
+
+ // Resume timers so that the timer set above will be set again to fire
+ // immediately.
+ platform_impl.ResumeSharedTimer();
+
+ EXPECT_TRUE(base::TimeDelta() == platform_impl.shared_timer_delay());
+}
+
+TEST(BlinkPlatformTest, IsReservedIPAddress_WebURL) {
+ TestBlinkPlatformImpl platform_impl;
+
+ // Unreserved IPv4 addresses (in various forms).
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://8.8.8.8/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://99.64.0.0/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://212.15.0.0/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://212.15/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://212.15.0/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://3557752832/")));
+
+ // Reserved IPv4 addresses (in various forms).
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://192.168.0.0/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://192.168.0.6/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://10.0.0.5/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://10.0.0/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://10.0/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://3232235526/")));
+
+ // Unreserved IPv6 addresses.
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ GURL("http://[FFC0:ba98:7654:3210:FEDC:BA98:7654:3210]/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ GURL("http://[2000:ba98:7654:2301:EFCD:BA98:7654:3210]/")));
+
+ // Reserved IPv6 addresses.
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://[::1]/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://[::192.9.5.5]/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(GURL("http://[FEED::BEEF]/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ GURL("http://[FEC0:ba98:7654:3210:FEDC:BA98:7654:3210]/")));
+
+ // Not IP addresses at all.
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(GURL("http://example.com/")));
+ EXPECT_FALSE(
+ platform_impl.isReservedIPAddress(GURL("http://127.0.0.1.example.com/")));
+
+ // Moar IPv4
+ uint8 address[4] = {0, 0, 0, 1};
+ for (int i = 0; i < 256; i++) {
+ address[0] = i;
+ std::string addressString =
+ net::IPAddressToString(address, sizeof(address));
+ if (i == 0 || i == 10 || i == 127 || i > 223) {
+ EXPECT_TRUE(
+ platform_impl.isReservedIPAddress(GURL("http://" + addressString)));
+ } else {
+ EXPECT_FALSE(
+ platform_impl.isReservedIPAddress(GURL("http://" + addressString)));
+ }
+ }
+}
+
+TEST(BlinkPlatformTest, IsReservedIPAddress_WebSecurityOrigin) {
+ TestBlinkPlatformImpl platform_impl;
+
+ // Unreserved IPv4 addresses (in various forms).
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://8.8.8.8/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://99.64.0.0/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://212.15.0.0/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://212.15/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://212.15.0/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://3557752832/")));
+
+ // Reserved IPv4 addresses (in various forms).
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://192.168.0.0/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://192.168.0.6/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://10.0.0.5/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://10.0.0/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://10.0/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://3232235526/")));
+
+ // Unreserved IPv6 addresses.
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString(
+ "http://[FFC0:ba98:7654:3210:FEDC:BA98:7654:3210]/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString(
+ "http://[2000:ba98:7654:2301:EFCD:BA98:7654:3210]/")));
+
+ // Reserved IPv6 addresses.
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://[::1]/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://[::192.9.5.5]/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://[FEED::BEEF]/")));
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString(
+ "http://[FEC0:ba98:7654:3210:FEDC:BA98:7654:3210]/")));
+
+ // Not IP addresses at all.
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString("http://example.com/")));
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString(
+ "http://127.0.0.1.example.com/")));
+
+ // Moar IPv4
+ uint8 address[4] = {0, 0, 0, 1};
+ for (int i = 0; i < 256; i++) {
+ address[0] = i;
+ blink::WebString addressString = blink::WebString::fromUTF8(
+ "http://" + net::IPAddressToString(address, sizeof(address)) + "/");
+ if (i == 0 || i == 10 || i == 127 || i > 223) {
+ EXPECT_TRUE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString(addressString)));
+ } else {
+ EXPECT_FALSE(platform_impl.isReservedIPAddress(
+ blink::WebSecurityOrigin::createFromString(addressString)));
+ }
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/child/blink_platform_unittest.cc b/chromium/content/child/blink_platform_unittest.cc
deleted file mode 100644
index 88a3c0dc518..00000000000
--- a/chromium/content/child/blink_platform_unittest.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 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/run_loop.h"
-#include "base/time/time.h"
-#include "content/child/blink_platform_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-// Derives BlinkPlatformImpl for testing shared timers.
-class TestBlinkPlatformImpl : public BlinkPlatformImpl {
- public:
- TestBlinkPlatformImpl() : mock_monotonically_increasing_time_(0) {}
-
- // Returns mock time when enabled.
- virtual double monotonicallyIncreasingTime() OVERRIDE {
- if (mock_monotonically_increasing_time_ > 0.0)
- return mock_monotonically_increasing_time_;
- return BlinkPlatformImpl::monotonicallyIncreasingTime();
- }
-
- virtual void OnStartSharedTimer(base::TimeDelta delay) OVERRIDE {
- shared_timer_delay_ = delay;
- }
-
- base::TimeDelta shared_timer_delay() { return shared_timer_delay_; }
-
- void set_mock_monotonically_increasing_time(double mock_time) {
- mock_monotonically_increasing_time_ = mock_time;
- }
-
- private:
- base::TimeDelta shared_timer_delay_;
- double mock_monotonically_increasing_time_;
-
- DISALLOW_COPY_AND_ASSIGN(TestBlinkPlatformImpl);
-};
-
-TEST(BlinkPlatformTest, SuspendResumeSharedTimer) {
- base::MessageLoop message_loop;
-
- TestBlinkPlatformImpl platform_impl;
-
- // Set a timer to fire as soon as possible.
- platform_impl.setSharedTimerFireInterval(0);
-
- // Suspend timers immediately so the above timer wouldn't be fired.
- platform_impl.SuspendSharedTimer();
-
- // The above timer would have posted a task which can be processed out of the
- // message loop.
- base::RunLoop().RunUntilIdle();
-
- // Set a mock time after 1 second to simulate timers suspended for 1 second.
- double new_time = base::Time::Now().ToDoubleT() + 1;
- platform_impl.set_mock_monotonically_increasing_time(new_time);
-
- // Resume timers so that the timer set above will be set again to fire
- // immediately.
- platform_impl.ResumeSharedTimer();
-
- EXPECT_TRUE(base::TimeDelta() == platform_impl.shared_timer_delay());
-}
-
-} // namespace content
diff --git a/chromium/content/child/bluetooth/web_bluetooth_impl.cc b/chromium/content/child/bluetooth/web_bluetooth_impl.cc
new file mode 100644
index 00000000000..406ae7d3a59
--- /dev/null
+++ b/chromium/content/child/bluetooth/web_bluetooth_impl.cc
@@ -0,0 +1,56 @@
+// Copyright 2014 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 "content/child/bluetooth/web_bluetooth_impl.h"
+
+namespace content {
+
+WebBluetoothImpl::WebBluetoothImpl()
+ : m_bluetoothMockDataSet(MockData::NOT_MOCKING),
+ m_bluetoothRequestDeviceRejectType(
+ blink::WebBluetoothError::NotFoundError) {
+}
+
+void WebBluetoothImpl::requestDevice(
+ blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
+ // Mock implementation of blink::WebBluetooth until a more complete
+ // implementation is built out.
+ switch (m_bluetoothMockDataSet) {
+ case MockData::NOT_MOCKING: {
+ blink::WebBluetoothError* error = new blink::WebBluetoothError(
+ blink::WebBluetoothError::NotFoundError, "");
+ callbacks->onError(error);
+ break;
+ }
+ case MockData::REJECT: {
+ blink::WebBluetoothError* error =
+ new blink::WebBluetoothError(m_bluetoothRequestDeviceRejectType, "");
+ callbacks->onError(error);
+ break;
+ }
+ case MockData::RESOLVE: {
+ callbacks->onSuccess();
+ break;
+ }
+ }
+}
+
+void WebBluetoothImpl::SetBluetoothMockDataSetForTesting(
+ const std::string& name) {
+ if (name == "RejectRequestDevice_NotFoundError") {
+ m_bluetoothMockDataSet = MockData::REJECT;
+ m_bluetoothRequestDeviceRejectType =
+ blink::WebBluetoothError::NotFoundError;
+ } else if (name == "RejectRequestDevice_SecurityError") {
+ m_bluetoothMockDataSet = MockData::REJECT;
+ m_bluetoothRequestDeviceRejectType =
+ blink::WebBluetoothError::SecurityError;
+ } else if (name == "ResolveRequestDevice_Empty") {
+ m_bluetoothMockDataSet = MockData::RESOLVE;
+ } else {
+ m_bluetoothMockDataSet = MockData::NOT_MOCKING;
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/child/bluetooth/web_bluetooth_impl.h b/chromium/content/child/bluetooth/web_bluetooth_impl.h
new file mode 100644
index 00000000000..e338cc5cf05
--- /dev/null
+++ b/chromium/content/child/bluetooth/web_bluetooth_impl.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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 CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+#define CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebBluetooth.h"
+#include "third_party/WebKit/public/platform/WebBluetoothError.h"
+
+namespace content {
+
+// Mock implementation of blink::WebBluetooth until a more complete
+// implementation is built out.
+class CONTENT_EXPORT WebBluetoothImpl
+ : NON_EXPORTED_BASE(public blink::WebBluetooth) {
+ public:
+ WebBluetoothImpl();
+
+ // WebBluetooth interface:
+ void requestDevice(blink::WebBluetoothRequestDeviceCallbacks*) override;
+
+ // Testing interface:
+ void SetBluetoothMockDataSetForTesting(const std::string& name);
+
+ private:
+ enum class MockData { NOT_MOCKING, REJECT, RESOLVE };
+ MockData m_bluetoothMockDataSet;
+ blink::WebBluetoothError::ErrorType m_bluetoothRequestDeviceRejectType;
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
diff --git a/chromium/content/child/browser_font_resource_trusted.cc b/chromium/content/child/browser_font_resource_trusted.cc
index 39746a82fc5..37e428304b5 100644
--- a/chromium/content/child/browser_font_resource_trusted.cc
+++ b/chromium/content/child/browser_font_resource_trusted.cc
@@ -6,6 +6,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/web_preferences.h"
#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/proxy/connection.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
@@ -43,11 +44,9 @@ namespace {
// undefined reference linker error.
const char kCommonScript[] = "Zyyy";
-base::string16 GetFontFromMap(
- const webkit_glue::ScriptFontFamilyMap& map,
- const std::string& script) {
- webkit_glue::ScriptFontFamilyMap::const_iterator it =
- map.find(script);
+base::string16 GetFontFromMap(const ScriptFontFamilyMap& map,
+ const std::string& script) {
+ ScriptFontFamilyMap::const_iterator it = map.find(script);
if (it != map.end())
return it->second;
return base::string16();
@@ -202,9 +201,9 @@ WebFontDescription PPFontDescToWebFontDesc(
// we should use the fixed or regular font size. It's difficult at this
// level to detect if the requested font is fixed width, so we only apply
// the alternate font size to the default fixed font family.
- if (StringToLowerASCII(resolved_family) ==
- StringToLowerASCII(GetFontFromMap(prefs.fixed_font_family_map,
- kCommonScript)))
+ if (base::StringToLowerASCII(resolved_family) ==
+ base::StringToLowerASCII(GetFontFromMap(prefs.fixed_font_family_map,
+ kCommonScript)))
result.size = static_cast<float>(prefs.default_fixed_font_size);
else
result.size = static_cast<float>(prefs.default_font_size);
diff --git a/chromium/content/child/browser_font_resource_trusted.h b/chromium/content/child/browser_font_resource_trusted.h
index 09afe0c0a48..f29e51fa1a5 100644
--- a/chromium/content/child/browser_font_resource_trusted.h
+++ b/chromium/content/child/browser_font_resource_trusted.h
@@ -39,29 +39,26 @@ class BrowserFontResource_Trusted
const PP_BrowserFont_Trusted_Description& desc);
// Resource override.
- virtual ::ppapi::thunk::PPB_BrowserFont_Trusted_API*
- AsPPB_BrowserFont_Trusted_API() OVERRIDE;
+ ::ppapi::thunk::PPB_BrowserFont_Trusted_API* AsPPB_BrowserFont_Trusted_API()
+ override;
// PPB_BrowserFont_Trusted_API implementation.
- virtual PP_Bool Describe(PP_BrowserFont_Trusted_Description* description,
- PP_BrowserFont_Trusted_Metrics* metrics) OVERRIDE;
- virtual PP_Bool DrawTextAt(PP_Resource image_data,
- const PP_BrowserFont_Trusted_TextRun* text,
- const PP_Point* position,
- uint32_t color,
- const PP_Rect* clip,
- PP_Bool image_data_is_opaque) OVERRIDE;
- virtual int32_t MeasureText(
- const PP_BrowserFont_Trusted_TextRun* text) OVERRIDE;
- virtual uint32_t CharacterOffsetForPixel(
- const PP_BrowserFont_Trusted_TextRun* text,
- int32_t pixel_position) OVERRIDE;
- virtual int32_t PixelOffsetForCharacter(
- const PP_BrowserFont_Trusted_TextRun* text,
- uint32_t char_offset) OVERRIDE;
+ PP_Bool Describe(PP_BrowserFont_Trusted_Description* description,
+ PP_BrowserFont_Trusted_Metrics* metrics) override;
+ PP_Bool DrawTextAt(PP_Resource image_data,
+ const PP_BrowserFont_Trusted_TextRun* text,
+ const PP_Point* position,
+ uint32_t color,
+ const PP_Rect* clip,
+ PP_Bool image_data_is_opaque) override;
+ int32_t MeasureText(const PP_BrowserFont_Trusted_TextRun* text) override;
+ uint32_t CharacterOffsetForPixel(const PP_BrowserFont_Trusted_TextRun* text,
+ int32_t pixel_position) override;
+ int32_t PixelOffsetForCharacter(const PP_BrowserFont_Trusted_TextRun* text,
+ uint32_t char_offset) override;
private:
- virtual ~BrowserFontResource_Trusted();
+ ~BrowserFontResource_Trusted() override;
// Internal version of DrawTextAt that takes a mapped PlatformCanvas.
void DrawTextToCanvas(SkCanvas* destination,
diff --git a/chromium/content/child/child_discardable_shared_memory_manager.cc b/chromium/content/child/child_discardable_shared_memory_manager.cc
new file mode 100644
index 00000000000..606ca6ceb06
--- /dev/null
+++ b/chromium/content/child/child_discardable_shared_memory_manager.cc
@@ -0,0 +1,40 @@
+// Copyright 2014 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 "content/child/child_discardable_shared_memory_manager.h"
+
+#include "base/memory/discardable_shared_memory.h"
+#include "content/child/child_thread.h"
+#include "content/common/child_process_messages.h"
+
+namespace content {
+
+ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager(
+ ThreadSafeSender* sender)
+ : sender_(sender) {
+}
+
+ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() {
+}
+
+scoped_ptr<base::DiscardableSharedMemory>
+ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
+ size_t size) {
+ TRACE_EVENT1("renderer",
+ "ChildDiscardableSharedMemoryManager::"
+ "AllocateLockedDiscardableSharedMemory",
+ "size",
+ size);
+
+ base::SharedMemoryHandle handle = base::SharedMemory::NULLHandle();
+ sender_->Send(
+ new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory(
+ size, &handle));
+ scoped_ptr<base::DiscardableSharedMemory> memory(
+ new base::DiscardableSharedMemory(handle));
+ CHECK(memory->Map(size));
+ return memory.Pass();
+}
+
+} // namespace content
diff --git a/chromium/content/child/child_discardable_shared_memory_manager.h b/chromium/content/child/child_discardable_shared_memory_manager.h
new file mode 100644
index 00000000000..e35c57b4a26
--- /dev/null
+++ b/chromium/content/child/child_discardable_shared_memory_manager.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 CONTENT_CHILD_CHILD_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
+#define CONTENT_CHILD_CHILD_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
+
+#include "base/memory/discardable_memory_shmem_allocator.h"
+#include "base/memory/ref_counted.h"
+#include "content/child/thread_safe_sender.h"
+
+namespace content {
+
+// Implementation of DiscardableMemoryShmemAllocator that allocates
+// discardable memory segments through the browser process.
+class ChildDiscardableSharedMemoryManager
+ : public base::DiscardableMemoryShmemAllocator {
+ public:
+ explicit ChildDiscardableSharedMemoryManager(ThreadSafeSender* sender);
+ ~ChildDiscardableSharedMemoryManager() override;
+
+ // Overridden from base::DiscardableMemoryShmemAllocator:
+ scoped_ptr<base::DiscardableSharedMemory>
+ AllocateLockedDiscardableSharedMemory(size_t size) override;
+
+ private:
+ scoped_refptr<ThreadSafeSender> sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildDiscardableSharedMemoryManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_CHILD_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
diff --git a/chromium/content/child/child_gpu_memory_buffer_manager.cc b/chromium/content/child/child_gpu_memory_buffer_manager.cc
new file mode 100644
index 00000000000..7cb793d5240
--- /dev/null
+++ b/chromium/content/child/child_gpu_memory_buffer_manager.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 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 "content/child/child_gpu_memory_buffer_manager.h"
+
+#include "content/child/child_thread.h"
+#include "content/common/child_process_messages.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+namespace content {
+namespace {
+
+void DeletedGpuMemoryBuffer(ThreadSafeSender* sender,
+ gfx::GpuMemoryBufferId id,
+ uint32 sync_point) {
+ TRACE_EVENT0("renderer",
+ "ChildGpuMemoryBufferManager::DeletedGpuMemoryBuffer");
+ sender->Send(new ChildProcessHostMsg_DeletedGpuMemoryBuffer(id, sync_point));
+}
+
+} // namespace
+
+ChildGpuMemoryBufferManager::ChildGpuMemoryBufferManager(
+ ThreadSafeSender* sender)
+ : sender_(sender) {
+}
+
+ChildGpuMemoryBufferManager::~ChildGpuMemoryBufferManager() {
+}
+
+scoped_ptr<gfx::GpuMemoryBuffer>
+ChildGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage) {
+ TRACE_EVENT2("renderer",
+ "ChildGpuMemoryBufferManager::AllocateGpuMemoryBuffer",
+ "width",
+ size.width(),
+ "height",
+ size.height());
+
+ gfx::GpuMemoryBufferHandle handle;
+ IPC::Message* message = new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(
+ size.width(), size.height(), format, usage, &handle);
+ bool success = sender_->Send(message);
+ if (!success)
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+
+ scoped_ptr<GpuMemoryBufferImpl> buffer(GpuMemoryBufferImpl::CreateFromHandle(
+ handle,
+ size,
+ format,
+ base::Bind(&DeletedGpuMemoryBuffer, sender_, handle.id)));
+ if (!buffer) {
+ sender_->Send(new ChildProcessHostMsg_DeletedGpuMemoryBuffer(handle.id, 0));
+ return scoped_ptr<gfx::GpuMemoryBuffer>();
+ }
+
+ return buffer.Pass();
+}
+
+gfx::GpuMemoryBuffer*
+ChildGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
+ ClientBuffer buffer) {
+ return GpuMemoryBufferImpl::FromClientBuffer(buffer);
+}
+
+void ChildGpuMemoryBufferManager::SetDestructionSyncPoint(
+ gfx::GpuMemoryBuffer* buffer,
+ uint32 sync_point) {
+ static_cast<GpuMemoryBufferImpl*>(buffer)
+ ->set_destruction_sync_point(sync_point);
+}
+
+} // namespace content
diff --git a/chromium/content/child/child_gpu_memory_buffer_manager.h b/chromium/content/child/child_gpu_memory_buffer_manager.h
new file mode 100644
index 00000000000..07c9f5bcb06
--- /dev/null
+++ b/chromium/content/child/child_gpu_memory_buffer_manager.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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 CONTENT_CHILD_CHILD_GPU_MEMORY_BUFFER_MANAGER_H_
+#define CONTENT_CHILD_CHILD_GPU_MEMORY_BUFFER_MANAGER_H_
+
+#include "content/child/thread_safe_sender.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+
+namespace content {
+
+class ChildGpuMemoryBufferManager : public gpu::GpuMemoryBufferManager {
+ public:
+ explicit ChildGpuMemoryBufferManager(ThreadSafeSender* sender);
+ ~ChildGpuMemoryBufferManager() override;
+
+ // Overridden from gpu::GpuMemoryBufferManager:
+ scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage) override;
+ gfx::GpuMemoryBuffer* GpuMemoryBufferFromClientBuffer(
+ ClientBuffer buffer) override;
+ void SetDestructionSyncPoint(gfx::GpuMemoryBuffer* buffer,
+ uint32 sync_point) override;
+
+ private:
+ scoped_refptr<ThreadSafeSender> sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChildGpuMemoryBufferManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_CHILD_GPU_MEMORY_BUFFER_MANAGER_H_
diff --git a/chromium/content/child/child_histogram_message_filter.cc b/chromium/content/child/child_histogram_message_filter.cc
index 3cf36ce46c0..3e895fcfe8d 100644
--- a/chromium/content/child/child_histogram_message_filter.cc
+++ b/chromium/content/child/child_histogram_message_filter.cc
@@ -63,9 +63,11 @@ void ChildHistogramMessageFilter::UploadAllHistograms(int sequence_number) {
sender_->Send(
new ChildProcessHostMsg_ChildHistogramData(sequence_number, deltas));
+#ifndef NDEBUG
static int count = 0;
count++;
- DHISTOGRAM_COUNTS("Histogram.ChildProcessHistogramSentCount", count);
+ LOCAL_HISTOGRAM_COUNTS("Histogram.ChildProcessHistogramSentCount", count);
+#endif
}
} // namespace content
diff --git a/chromium/content/child/child_histogram_message_filter.h b/chromium/content/child/child_histogram_message_filter.h
index 34498c786ab..072e2c60679 100644
--- a/chromium/content/child/child_histogram_message_filter.h
+++ b/chromium/content/child/child_histogram_message_filter.h
@@ -24,16 +24,16 @@ class ChildHistogramMessageFilter : public IPC::MessageFilter {
ChildHistogramMessageFilter();
// IPC::MessageFilter implementation.
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
void SendHistograms(int sequence_number);
private:
typedef std::vector<std::string> HistogramPickledList;
- virtual ~ChildHistogramMessageFilter();
+ ~ChildHistogramMessageFilter() override;
// Message handlers.
virtual void OnGetChildHistogramData(int sequence_number);
diff --git a/chromium/content/child/child_message_filter.cc b/chromium/content/child/child_message_filter.cc
index 5d2f2e46297..9e5ff63e99a 100644
--- a/chromium/content/child/child_message_filter.cc
+++ b/chromium/content/child/child_message_filter.cc
@@ -18,10 +18,10 @@ class ChildMessageFilter::Internal : public IPC::MessageFilter {
public:
explicit Internal(ChildMessageFilter* filter) : filter_(filter) {}
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& msg) override {
scoped_refptr<base::TaskRunner> runner =
filter_->OverrideTaskRunnerForMessage(msg);
- if (runner && !runner->RunsTasksOnCurrentThread()) {
+ if (runner.get() && !runner->RunsTasksOnCurrentThread()) {
if (!runner->PostTask(
FROM_HERE,
base::Bind(
@@ -35,7 +35,7 @@ class ChildMessageFilter::Internal : public IPC::MessageFilter {
}
private:
- virtual ~Internal() {}
+ ~Internal() override {}
scoped_refptr<ChildMessageFilter> filter_;
DISALLOW_COPY_AND_ASSIGN(Internal);
diff --git a/chromium/content/child/child_message_filter.h b/chromium/content/child/child_message_filter.h
index 0d9c4ffc41c..a79ceecf2de 100644
--- a/chromium/content/child/child_message_filter.h
+++ b/chromium/content/child/child_message_filter.h
@@ -27,7 +27,7 @@ class ChildMessageFilter
public IPC::Sender {
public:
// IPC::Sender implementation. Can be called on any threads.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// If implementers want to run OnMessageReceived on a different task
// runner it should override this and return the TaskRunner for the message.
@@ -47,7 +47,7 @@ class ChildMessageFilter
protected:
ChildMessageFilter();
- virtual ~ChildMessageFilter();
+ ~ChildMessageFilter() override;
private:
class Internal;
diff --git a/chromium/content/child/child_process.h b/chromium/content/child/child_process.h
index af2d91343e1..1aedcb688a1 100644
--- a/chromium/content/child/child_process.h
+++ b/chromium/content/child/child_process.h
@@ -54,8 +54,7 @@ class CONTENT_EXPORT ChildProcess {
// process goes away prematurely, the background thread can at least notice
// the child processes's main thread exiting to determine that it should give
// up waiting.
- // For example, see the renderer code used to implement
- // webkit_glue::GetCookies.
+ // For example, see the renderer code used to implement GetCookies().
base::WaitableEvent* GetShutDownEvent();
// These are used for ref-counting the child process. The process shuts
diff --git a/chromium/content/child/child_resource_message_filter.h b/chromium/content/child/child_resource_message_filter.h
index 66e7bf65147..0037eab5d09 100644
--- a/chromium/content/child/child_resource_message_filter.h
+++ b/chromium/content/child/child_resource_message_filter.h
@@ -32,10 +32,10 @@ class ChildResourceMessageFilter : public IPC::MessageFilter {
explicit ChildResourceMessageFilter(ResourceDispatcher* resource_dispatcher);
// IPC::MessageFilter implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~ChildResourceMessageFilter();
+ ~ChildResourceMessageFilter() override;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
ResourceDispatcher* resource_dispatcher_;
diff --git a/chromium/content/child/child_shared_bitmap_manager.h b/chromium/content/child/child_shared_bitmap_manager.h
index d83856b998f..e4d6b4989fd 100644
--- a/chromium/content/child/child_shared_bitmap_manager.h
+++ b/chromium/content/child/child_shared_bitmap_manager.h
@@ -16,15 +16,15 @@ namespace content {
class ChildSharedBitmapManager : public cc::SharedBitmapManager {
public:
ChildSharedBitmapManager(scoped_refptr<ThreadSafeSender> sender);
- virtual ~ChildSharedBitmapManager();
+ ~ChildSharedBitmapManager() override;
- virtual scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
- const gfx::Size& size) OVERRIDE;
- virtual scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
+ scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
+ const gfx::Size& size) override;
+ scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
const gfx::Size&,
- const cc::SharedBitmapId&) OVERRIDE;
- virtual scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
- base::SharedMemory* mem) OVERRIDE;
+ const cc::SharedBitmapId&) override;
+ scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
+ base::SharedMemory* mem) override;
private:
scoped_refptr<ThreadSafeSender> sender_;
diff --git a/chromium/content/child/child_thread.cc b/chromium/content/child/child_thread.cc
index 3222b4167a1..b665e8914ad 100644
--- a/chromium/content/child/child_thread.cc
+++ b/chromium/content/child/child_thread.cc
@@ -26,20 +26,22 @@
#include "base/threading/thread_local.h"
#include "base/tracked_objects.h"
#include "components/tracing/child_trace_message_filter.h"
+#include "content/child/child_discardable_shared_memory_manager.h"
+#include "content/child/child_gpu_memory_buffer_manager.h"
#include "content/child/child_histogram_message_filter.h"
#include "content/child/child_process.h"
#include "content/child/child_resource_message_filter.h"
#include "content/child/child_shared_bitmap_manager.h"
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/fileapi/webfilesystem_impl.h"
+#include "content/child/geofencing/geofencing_message_filter.h"
#include "content/child/mojo/mojo_application.h"
+#include "content/child/notifications/notification_dispatcher.h"
#include "content/child/power_monitor_broadcast_source.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/quota_message_filter.h"
#include "content/child/resource_dispatcher.h"
-#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_message_filter.h"
-#include "content/child/socket_stream_dispatcher.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/websocket_dispatcher.h"
#include "content/common/child_process_messages.h"
@@ -48,6 +50,7 @@
#include "ipc/ipc_switches.h"
#include "ipc/ipc_sync_channel.h"
#include "ipc/ipc_sync_message_filter.h"
+#include "ipc/mojo/ipc_channel_mojo.h"
#if defined(OS_WIN)
#include "content/common/handle_enumerator_win.h"
@@ -82,9 +85,9 @@ class WaitAndExitDelegate : public base::PlatformThread::Delegate {
public:
explicit WaitAndExitDelegate(base::TimeDelta duration)
: duration_(duration) {}
- virtual ~WaitAndExitDelegate() OVERRIDE {}
+ virtual ~WaitAndExitDelegate() override {}
- virtual void ThreadMain() OVERRIDE {
+ virtual void ThreadMain() override {
base::PlatformThread::Sleep(duration_);
_exit(0);
}
@@ -115,7 +118,7 @@ bool CreateWaitAndExitThread(base::TimeDelta duration) {
class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
public:
// IPC::MessageFilter
- virtual void OnChannelError() OVERRIDE {
+ void OnChannelError() override {
// For renderer/worker processes:
// On POSIX, at least, one can install an unload handler which loops
// forever and leave behind a renderer process which eats 100% CPU forever.
@@ -149,7 +152,7 @@ class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
}
protected:
- virtual ~SuicideOnChannelErrorFilter() {}
+ ~SuicideOnChannelErrorFilter() override {}
};
#endif // OS(POSIX)
@@ -192,6 +195,17 @@ void QuitMainThreadMessageLoop() {
} // namespace
+ChildThread::Options::Options()
+ : channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessChannelID)),
+ use_mojo_channel(false) {}
+
+ChildThread::Options::Options(bool mojo)
+ : channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessChannelID)),
+ use_mojo_channel(mojo) {}
+
+
ChildThread::ChildThreadMessageRouter::ChildThreadMessageRouter(
IPC::Sender* sender)
: sender_(sender) {}
@@ -202,22 +216,42 @@ bool ChildThread::ChildThreadMessageRouter::Send(IPC::Message* msg) {
ChildThread::ChildThread()
: router_(this),
- channel_connected_factory_(this),
- in_browser_process_(false) {
- channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kProcessChannelID);
- Init();
+ in_browser_process_(false),
+ channel_connected_factory_(this) {
+ Init(Options());
+}
+
+ChildThread::ChildThread(const Options& options)
+ : router_(this),
+ in_browser_process_(true),
+ channel_connected_factory_(this) {
+ Init(options);
}
-ChildThread::ChildThread(const std::string& channel_name)
- : channel_name_(channel_name),
- router_(this),
- channel_connected_factory_(this),
- in_browser_process_(true) {
- Init();
+scoped_ptr<IPC::SyncChannel> ChildThread::CreateChannel(bool use_mojo_channel) {
+ if (use_mojo_channel) {
+ VLOG(1) << "Mojo is enabled on child";
+ return IPC::SyncChannel::Create(
+ IPC::ChannelMojo::CreateClientFactory(channel_name_),
+ this,
+ ChildProcess::current()->io_message_loop_proxy(),
+ true,
+ ChildProcess::current()->GetShutDownEvent());
+ }
+
+ VLOG(1) << "Mojo is disabled on child";
+ return IPC::SyncChannel::Create(
+ channel_name_,
+ IPC::Channel::MODE_CLIENT,
+ this,
+ ChildProcess::current()->io_message_loop_proxy(),
+ true,
+ ChildProcess::current()->GetShutDownEvent());
}
-void ChildThread::Init() {
+void ChildThread::Init(const Options& options) {
+ channel_name_ = options.channel_name;
+
g_lazy_tls.Pointer()->Set(this);
on_channel_error_called_ = false;
message_loop_ = base::MessageLoop::current();
@@ -227,19 +261,13 @@ void ChildThread::Init() {
// the logger, and the logger does not like being created on the IO thread.
IPC::Logging::GetInstance();
#endif
- channel_ =
- IPC::SyncChannel::Create(channel_name_,
- IPC::Channel::MODE_CLIENT,
- this,
- ChildProcess::current()->io_message_loop_proxy(),
- true,
- ChildProcess::current()->GetShutDownEvent());
+ channel_ = CreateChannel(options.use_mojo_channel);
#ifdef IPC_MESSAGE_LOG_ENABLED
if (!in_browser_process_)
IPC::Logging::GetInstance()->SetIPCSender(this);
#endif
- mojo_application_.reset(new MojoApplication(this));
+ mojo_application_.reset(new MojoApplication);
sync_message_filter_ =
new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent());
@@ -247,7 +275,6 @@ void ChildThread::Init() {
base::MessageLoopProxy::current().get(), sync_message_filter_.get());
resource_dispatcher_.reset(new ResourceDispatcher(this));
- socket_stream_dispatcher_.reset(new SocketStreamDispatcher());
websocket_dispatcher_.reset(new WebSocketDispatcher);
file_system_dispatcher_.reset(new FileSystemDispatcher());
@@ -257,21 +284,25 @@ void ChildThread::Init() {
service_worker_message_filter_ =
new ServiceWorkerMessageFilter(thread_safe_sender_.get());
- service_worker_dispatcher_.reset(
- new ServiceWorkerDispatcher(thread_safe_sender_.get()));
quota_message_filter_ =
new QuotaMessageFilter(thread_safe_sender_.get());
quota_dispatcher_.reset(new QuotaDispatcher(thread_safe_sender_.get(),
quota_message_filter_.get()));
-
+ geofencing_message_filter_ =
+ new GeofencingMessageFilter(thread_safe_sender_.get());
+ notification_dispatcher_ =
+ new NotificationDispatcher(thread_safe_sender_.get());
channel_->AddFilter(histogram_message_filter_.get());
channel_->AddFilter(sync_message_filter_.get());
channel_->AddFilter(resource_message_filter_.get());
channel_->AddFilter(quota_message_filter_->GetFilter());
+ channel_->AddFilter(notification_dispatcher_->GetFilter());
channel_->AddFilter(service_worker_message_filter_->GetFilter());
+ channel_->AddFilter(geofencing_message_filter_->GetFilter());
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)) {
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
// In single process mode, browser-side tracing will cover the whole
// process including renderers.
channel_->AddFilter(new tracing::ChildTraceMessageFilter(
@@ -285,19 +316,19 @@ void ChildThread::Init() {
channel_->AddFilter(power_monitor_source->GetMessageFilter());
power_monitor_.reset(new base::PowerMonitor(
- power_monitor_source.PassAs<base::PowerMonitorSource>()));
+ power_monitor_source.Pass()));
}
#if defined(OS_POSIX)
// Check that --process-type is specified so we don't do this in unit tests
// and single-process mode.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType))
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType))
channel_->AddFilter(new SuicideOnChannelErrorFilter());
#endif
int connection_timeout = kConnectionTimeoutS;
std::string connection_override =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kIPCConnectionTimeout);
if (!connection_override.empty()) {
int temp;
@@ -331,6 +362,12 @@ void ChildThread::Init() {
shared_bitmap_manager_.reset(
new ChildSharedBitmapManager(thread_safe_sender()));
+
+ gpu_memory_buffer_manager_.reset(
+ new ChildGpuMemoryBufferManager(thread_safe_sender()));
+
+ discardable_shared_memory_manager_.reset(
+ new ChildDiscardableSharedMemoryManager(thread_safe_sender()));
}
ChildThread::~ChildThread() {
@@ -370,15 +407,6 @@ void ChildThread::OnChannelError() {
base::MessageLoop::current()->Quit();
}
-void ChildThread::ConnectToService(
- const mojo::String& service_url,
- const mojo::String& service_name,
- mojo::ScopedMessagePipeHandle message_pipe,
- const mojo::String& requestor_url) {
- // By default, we don't expect incoming connections.
- NOTREACHED();
-}
-
bool ChildThread::Send(IPC::Message* msg) {
DCHECK(base::MessageLoop::current() == message_loop());
if (!channel_) {
@@ -440,8 +468,6 @@ bool ChildThread::OnMessageReceived(const IPC::Message& msg) {
// Resource responses are sent to the resource dispatcher.
if (resource_dispatcher_->OnMessageReceived(msg))
return true;
- if (socket_stream_dispatcher_->OnMessageReceived(msg))
- return true;
if (websocket_dispatcher_->OnMessageReceived(msg))
return true;
if (file_system_dispatcher_->OnMessageReceived(msg))
@@ -509,7 +535,7 @@ void ChildThread::OnDumpHandles() {
#if defined(OS_WIN)
scoped_refptr<HandleEnumerator> handle_enum(
new HandleEnumerator(
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAuditAllHandles)));
handle_enum->EnumerateHandles();
Send(new ChildProcessHostMsg_DumpHandlesDone);
@@ -575,14 +601,6 @@ void ChildThread::OnProcessBackgrounded(bool background) {
if (background)
timer_slack = base::TIMER_SLACK_MAXIMUM;
base::MessageLoop::current()->SetTimerSlack(timer_slack);
-
-#ifdef OS_WIN
- // Windows Vista+ has a fancy process backgrounding mode that can only be set
- // from within the process.
- // TODO(wfh) Do not set background from within process until the issue with
- // white tabs is resolved. See http://crbug.com/398103.
- // base::Process::Current().SetProcessBackgrounded(background);
-#endif // OS_WIN
}
} // namespace content
diff --git a/chromium/content/child/child_thread.h b/chromium/content/child/child_thread.h
index b272db3348f..969194e8a3f 100644
--- a/chromium/content/child/child_thread.h
+++ b/chromium/content/child/child_thread.h
@@ -13,10 +13,10 @@
#include "base/memory/weak_ptr.h"
#include "base/power_monitor/power_monitor.h"
#include "base/tracked_objects.h"
+#include "content/child/mojo/mojo_application.h"
#include "content/common/content_export.h"
#include "content/common/message_router.h"
#include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED.
-#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
namespace base {
class MessageLoop;
@@ -35,46 +35,50 @@ namespace blink {
class WebFrame;
} // namespace blink
-namespace webkit_glue {
-class ResourceLoaderBridge;
-} // namespace webkit_glue
-
namespace content {
+class ChildDiscardableSharedMemoryManager;
+class ChildGpuMemoryBufferManager;
class ChildHistogramMessageFilter;
class ChildResourceMessageFilter;
class ChildSharedBitmapManager;
class FileSystemDispatcher;
-class MojoApplication;
-class ServiceWorkerDispatcher;
+class GeofencingMessageFilter;
+class NotificationDispatcher;
class ServiceWorkerMessageFilter;
class QuotaDispatcher;
class QuotaMessageFilter;
class ResourceDispatcher;
-class SocketStreamDispatcher;
class ThreadSafeSender;
class WebSocketDispatcher;
struct RequestInfo;
// The main thread of a child process derives from this class.
-class CONTENT_EXPORT ChildThread
- : public IPC::Listener,
- public IPC::Sender,
- public NON_EXPORTED_BASE(mojo::ServiceProvider) {
+class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
public:
+ struct CONTENT_EXPORT Options {
+ Options();
+ explicit Options(bool mojo);
+ Options(std::string name, bool mojo)
+ : channel_name(name), use_mojo_channel(mojo) {}
+
+ std::string channel_name;
+ bool use_mojo_channel;
+ };
+
// Creates the thread.
ChildThread();
// Used for single-process mode and for in process gpu mode.
- explicit ChildThread(const std::string& channel_name);
+ explicit ChildThread(const Options& options);
// ChildProcess::main_thread() is reset after Shutdown(), and before the
// destructor, so any subsystem that relies on ChildProcess::main_thread()
// must be terminated before Shutdown returns. In particular, if a subsystem
// has a thread that post tasks to ChildProcess::main_thread(), that thread
// should be joined in Shutdown().
- virtual ~ChildThread();
+ ~ChildThread() override;
virtual void Shutdown();
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
IPC::SyncChannel* channel() { return channel_.get(); }
@@ -95,12 +99,17 @@ class CONTENT_EXPORT ChildThread
return shared_bitmap_manager_.get();
}
- ResourceDispatcher* resource_dispatcher() const {
- return resource_dispatcher_.get();
+ ChildGpuMemoryBufferManager* gpu_memory_buffer_manager() const {
+ return gpu_memory_buffer_manager_.get();
+ }
+
+ ChildDiscardableSharedMemoryManager* discardable_shared_memory_manager()
+ const {
+ return discardable_shared_memory_manager_.get();
}
- SocketStreamDispatcher* socket_stream_dispatcher() const {
- return socket_stream_dispatcher_.get();
+ ResourceDispatcher* resource_dispatcher() const {
+ return resource_dispatcher_.get();
}
WebSocketDispatcher* websocket_dispatcher() const {
@@ -111,14 +120,14 @@ class CONTENT_EXPORT ChildThread
return file_system_dispatcher_.get();
}
- ServiceWorkerDispatcher* service_worker_dispatcher() const {
- return service_worker_dispatcher_.get();
- }
-
QuotaDispatcher* quota_dispatcher() const {
return quota_dispatcher_.get();
}
+ NotificationDispatcher* notification_dispatcher() const {
+ return notification_dispatcher_.get();
+ }
+
IPC::SyncMessageFilter* sync_message_filter() const {
return sync_message_filter_.get();
}
@@ -153,6 +162,10 @@ class CONTENT_EXPORT ChildThread
static void ShutdownThread();
#endif
+ ServiceRegistry* service_registry() const {
+ return mojo_application_->service_registry();
+ }
+
protected:
friend class ChildProcess;
@@ -166,29 +179,23 @@ class CONTENT_EXPORT ChildThread
}
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
-
- // mojo::ServiceProvider implementation:
- virtual void ConnectToService(
- const mojo::String& service_url,
- const mojo::String& service_name,
- mojo::ScopedMessagePipeHandle message_pipe,
- const mojo::String& requestor_url) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
private:
class ChildThreadMessageRouter : public MessageRouter {
public:
// |sender| must outlive this object.
explicit ChildThreadMessageRouter(IPC::Sender* sender);
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
private:
IPC::Sender* const sender_;
};
- void Init();
+ void Init(const Options& options);
+ scoped_ptr<IPC::SyncChannel> CreateChannel(bool use_mojo_channel);
// IPC message handlers.
void OnShutdown();
@@ -221,9 +228,6 @@ class CONTENT_EXPORT ChildThread
// Handles resource loads for this process.
scoped_ptr<ResourceDispatcher> resource_dispatcher_;
- // Handles SocketStream for this process.
- scoped_ptr<SocketStreamDispatcher> socket_stream_dispatcher_;
-
scoped_ptr<WebSocketDispatcher> websocket_dispatcher_;
// The OnChannelError() callback was invoked - the channel is dead, don't
@@ -234,8 +238,6 @@ class CONTENT_EXPORT ChildThread
scoped_ptr<FileSystemDispatcher> file_system_dispatcher_;
- scoped_ptr<ServiceWorkerDispatcher> service_worker_dispatcher_;
-
scoped_ptr<QuotaDispatcher> quota_dispatcher_;
scoped_refptr<ChildHistogramMessageFilter> histogram_message_filter_;
@@ -246,9 +248,14 @@ class CONTENT_EXPORT ChildThread
scoped_refptr<QuotaMessageFilter> quota_message_filter_;
+ scoped_refptr<NotificationDispatcher> notification_dispatcher_;
+
scoped_ptr<ChildSharedBitmapManager> shared_bitmap_manager_;
- base::WeakPtrFactory<ChildThread> channel_connected_factory_;
+ scoped_ptr<ChildGpuMemoryBufferManager> gpu_memory_buffer_manager_;
+
+ scoped_ptr<ChildDiscardableSharedMemoryManager>
+ discardable_shared_memory_manager_;
// Observes the trace event system. When tracing is enabled, optionally
// starts profiling the tcmalloc heap.
@@ -256,8 +263,12 @@ class CONTENT_EXPORT ChildThread
scoped_ptr<base::PowerMonitor> power_monitor_;
+ scoped_refptr<GeofencingMessageFilter> geofencing_message_filter_;
+
bool in_browser_process_;
+ base::WeakPtrFactory<ChildThread> channel_connected_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ChildThread);
};
diff --git a/chromium/content/child/database_util.h b/chromium/content/child/database_util.h
index 8be607c9c00..c53e7cef732 100644
--- a/chromium/content/child/database_util.h
+++ b/chromium/content/child/database_util.h
@@ -12,8 +12,9 @@ class SyncMessageFilter;
}
namespace content {
-// A class of utility functions used by RendererWebKitPlatformSupportImpl and
-// WorkerWebKitPlatformSupportImpl to handle database file accesses.
+
+// A class of utility functions used by RendererBlinkPlatformImpl to handle
+// database file accesses.
class DatabaseUtil {
public:
static blink::Platform::FileHandle DatabaseOpenFile(
diff --git a/chromium/content/child/db_message_filter.h b/chromium/content/child/db_message_filter.h
index 7297a04817d..783b827a8d6 100644
--- a/chromium/content/child/db_message_filter.h
+++ b/chromium/content/child/db_message_filter.h
@@ -17,10 +17,10 @@ class DBMessageFilter : public IPC::MessageFilter {
DBMessageFilter();
// IPC::MessageFilter
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~DBMessageFilter() {}
+ ~DBMessageFilter() override {}
private:
void OnDatabaseUpdateSize(const std::string& origin_identifier,
diff --git a/chromium/content/child/file_info_util.cc b/chromium/content/child/file_info_util.cc
new file mode 100644
index 00000000000..c605adfd6cf
--- /dev/null
+++ b/chromium/content/child/file_info_util.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 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 "content/child/file_info_util.h"
+
+#include "base/logging.h"
+#include "third_party/WebKit/public/platform/WebFileInfo.h"
+
+namespace content {
+
+void FileInfoToWebFileInfo(const base::File::Info& file_info,
+ blink::WebFileInfo* web_file_info) {
+ DCHECK(web_file_info);
+ // WebKit now expects NaN as uninitialized/null Date.
+ if (file_info.last_modified.is_null())
+ web_file_info->modificationTime = std::numeric_limits<double>::quiet_NaN();
+ else
+ web_file_info->modificationTime = file_info.last_modified.ToDoubleT();
+ web_file_info->length = file_info.size;
+ if (file_info.is_directory)
+ web_file_info->type = blink::WebFileInfo::TypeDirectory;
+ else
+ web_file_info->type = blink::WebFileInfo::TypeFile;
+}
+
+COMPILE_ASSERT(std::numeric_limits<double>::has_quiet_NaN, has_quiet_NaN);
+
+} // namespace content
diff --git a/chromium/content/child/file_info_util.h b/chromium/content/child/file_info_util.h
new file mode 100644
index 00000000000..82a11728b72
--- /dev/null
+++ b/chromium/content/child/file_info_util.h
@@ -0,0 +1,22 @@
+// Copyright 2014 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 CONTENT_CHILD_FILE_INFO_UTIL_H_
+#define CONTENT_CHILD_FILE_INFO_UTIL_H_
+
+#include "base/files/file.h"
+
+namespace blink {
+struct WebFileInfo;
+}
+
+namespace content {
+
+// File info conversion
+void FileInfoToWebFileInfo(const base::File::Info& file_info,
+ blink::WebFileInfo* web_file_info);
+
+} // namespace content
+
+#endif // CONTENT_CHILD_FILE_INFO_UTIL_H_
diff --git a/chromium/content/child/fileapi/OWNERS b/chromium/content/child/fileapi/OWNERS
index 2c20f1191f1..334a61ec4c5 100644
--- a/chromium/content/child/fileapi/OWNERS
+++ b/chromium/content/child/fileapi/OWNERS
@@ -1,16 +1,18 @@
-ericu@chromium.org
kinuko@chromium.org
michaeln@chromium.org
jianli@chromium.org
+tzik@chromium.org
+nhiroki@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/child/fileapi/file_system_dispatcher.cc b/chromium/content/child/fileapi/file_system_dispatcher.cc
index 1e69c82faeb..8ba8764ead4 100644
--- a/chromium/content/child/fileapi/file_system_dispatcher.cc
+++ b/chromium/content/child/fileapi/file_system_dispatcher.cc
@@ -5,12 +5,12 @@
#include "content/child/fileapi/file_system_dispatcher.h"
#include "base/callback.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/process/process.h"
#include "content/child/child_thread.h"
#include "content/common/fileapi/file_system_messages.h"
-#include "webkit/common/fileapi/file_system_info.h"
+#include "storage/common/fileapi/file_system_info.h"
namespace content {
@@ -96,9 +96,8 @@ class FileSystemDispatcher::CallbackDispatcher {
snapshot_callback_.Run(file_info, platform_path, request_id);
}
- void DidReadDirectory(
- const std::vector<fileapi::DirectoryEntry>& entries,
- bool has_more) {
+ void DidReadDirectory(const std::vector<storage::DirectoryEntry>& entries,
+ bool has_more) {
directory_callback_.Run(entries, has_more);
}
@@ -107,7 +106,7 @@ class FileSystemDispatcher::CallbackDispatcher {
filesystem_callback_.Run(name, root);
}
- void DidResolveURL(const fileapi::FileSystemInfo& info,
+ void DidResolveURL(const storage::FileSystemInfo& info,
const base::FilePath& file_path,
bool is_directory) {
resolve_callback_.Run(info, file_path, is_directory);
@@ -117,12 +116,6 @@ class FileSystemDispatcher::CallbackDispatcher {
write_callback_.Run(bytes, complete);
}
- void DidOpenFile(base::PlatformFile file,
- int file_open_id,
- quota::QuotaLimitType quota_policy) {
- open_callback_.Run(file, file_open_id, quota_policy);
- }
-
private:
CallbackDispatcher() {}
@@ -133,7 +126,6 @@ class FileSystemDispatcher::CallbackDispatcher {
OpenFileSystemCallback filesystem_callback_;
ResolveURLCallback resolve_callback_;
WriteCallback write_callback_;
- OpenFileCallback open_callback_;
StatusCallback error_callback_;
@@ -167,7 +159,6 @@ bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
OnDidCreateSnapshotFile)
IPC_MESSAGE_HANDLER(FileSystemMsg_DidFail, OnDidFail)
IPC_MESSAGE_HANDLER(FileSystemMsg_DidWrite, OnDidWrite)
- IPC_MESSAGE_HANDLER(FileSystemMsg_DidOpenFile, OnDidOpenFile)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -175,7 +166,7 @@ bool FileSystemDispatcher::OnMessageReceived(const IPC::Message& msg) {
void FileSystemDispatcher::OpenFileSystem(
const GURL& origin_url,
- fileapi::FileSystemType type,
+ storage::FileSystemType type,
const OpenFileSystemCallback& success_callback,
const StatusCallback& error_callback) {
int request_id = dispatchers_.Add(
@@ -194,10 +185,9 @@ void FileSystemDispatcher::ResolveURL(
request_id, filesystem_url));
}
-void FileSystemDispatcher::DeleteFileSystem(
- const GURL& origin_url,
- fileapi::FileSystemType type,
- const StatusCallback& callback) {
+void FileSystemDispatcher::DeleteFileSystem(const GURL& origin_url,
+ storage::FileSystemType type,
+ const StatusCallback& callback) {
int request_id = dispatchers_.Add(CallbackDispatcher::Create(callback));
ChildThread::current()->Send(new FileSystemHostMsg_DeleteFileSystem(
request_id, origin_url, type));
@@ -349,7 +339,7 @@ void FileSystemDispatcher::OnDidOpenFileSystem(int request_id,
}
void FileSystemDispatcher::OnDidResolveURL(int request_id,
- const fileapi::FileSystemInfo& info,
+ const storage::FileSystemInfo& info,
const base::FilePath& file_path,
bool is_directory) {
DCHECK(info.root_url.is_valid());
@@ -385,7 +375,7 @@ void FileSystemDispatcher::OnDidCreateSnapshotFile(
void FileSystemDispatcher::OnDidReadDirectory(
int request_id,
- const std::vector<fileapi::DirectoryEntry>& entries,
+ const std::vector<storage::DirectoryEntry>& entries,
bool has_more) {
CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
DCHECK(dispatcher);
@@ -411,17 +401,4 @@ void FileSystemDispatcher::OnDidWrite(
dispatchers_.Remove(request_id);
}
-void FileSystemDispatcher::OnDidOpenFile(
- int request_id,
- IPC::PlatformFileForTransit file,
- int file_open_id,
- quota::QuotaLimitType quota_policy) {
- CallbackDispatcher* dispatcher = dispatchers_.Lookup(request_id);
- DCHECK(dispatcher);
- dispatcher->DidOpenFile(IPC::PlatformFileForTransitToPlatformFile(file),
- file_open_id,
- quota_policy);
- dispatchers_.Remove(request_id);
-}
-
} // namespace content
diff --git a/chromium/content/child/fileapi/file_system_dispatcher.h b/chromium/content/child/fileapi/file_system_dispatcher.h
index 6d098b6fd30..d255fb359f5 100644
--- a/chromium/content/child/fileapi/file_system_dispatcher.h
+++ b/chromium/content/child/fileapi/file_system_dispatcher.h
@@ -14,14 +14,14 @@
#include "base/process/process.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_platform_file.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/quota/quota_types.h"
namespace base {
class FilePath;
}
-namespace fileapi {
+namespace storage {
struct DirectoryEntry;
struct FileSystemInfo;
}
@@ -42,39 +42,38 @@ class FileSystemDispatcher : public IPC::Listener {
const base::File::Info& file_info,
const base::FilePath& platform_path,
int request_id)> CreateSnapshotFileCallback;
- typedef base::Callback<void(
- const std::vector<fileapi::DirectoryEntry>& entries,
- bool has_more)> ReadDirectoryCallback;
+ typedef base::Callback<
+ void(const std::vector<storage::DirectoryEntry>& entries, bool has_more)>
+ ReadDirectoryCallback;
typedef base::Callback<void(
const std::string& name,
const GURL& root)> OpenFileSystemCallback;
- typedef base::Callback<void(
- const fileapi::FileSystemInfo& info,
- const base::FilePath& file_path,
- bool is_directory)> ResolveURLCallback;
+ typedef base::Callback<void(const storage::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ bool is_directory)> ResolveURLCallback;
typedef base::Callback<void(
int64 bytes,
bool complete)> WriteCallback;
- typedef base::Callback<void(
- base::PlatformFile file,
- int file_open_id,
- quota::QuotaLimitType quota_policy)> OpenFileCallback;
+ typedef base::Callback<void(base::PlatformFile file,
+ int file_open_id,
+ storage::QuotaLimitType quota_policy)>
+ OpenFileCallback;
FileSystemDispatcher();
- virtual ~FileSystemDispatcher();
+ ~FileSystemDispatcher() override;
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
void OpenFileSystem(const GURL& origin_url,
- fileapi::FileSystemType type,
+ storage::FileSystemType type,
const OpenFileSystemCallback& success_callback,
const StatusCallback& error_callback);
void ResolveURL(const GURL& filesystem_url,
const ResolveURLCallback& success_callback,
const StatusCallback& error_callback);
void DeleteFileSystem(const GURL& origin_url,
- fileapi::FileSystemType type,
+ storage::FileSystemType type,
const StatusCallback& callback);
void Move(const GURL& src_path,
const GURL& dest_path,
@@ -133,7 +132,7 @@ class FileSystemDispatcher : public IPC::Listener {
const std::string& name,
const GURL& root);
void OnDidResolveURL(int request_id,
- const fileapi::FileSystemInfo& info,
+ const storage::FileSystemInfo& info,
const base::FilePath& file_path,
bool is_directory);
void OnDidSucceed(int request_id);
@@ -143,15 +142,10 @@ class FileSystemDispatcher : public IPC::Listener {
const base::File::Info& file_info,
const base::FilePath& platform_path);
void OnDidReadDirectory(int request_id,
- const std::vector<fileapi::DirectoryEntry>& entries,
+ const std::vector<storage::DirectoryEntry>& entries,
bool has_more);
void OnDidFail(int request_id, base::File::Error error_code);
void OnDidWrite(int request_id, int64 bytes, bool complete);
- void OnDidOpenFile(
- int request_id,
- IPC::PlatformFileForTransit file,
- int file_open_id,
- quota::QuotaLimitType quota_policy);
IDMap<CallbackDispatcher, IDMapOwnPointer> dispatchers_;
diff --git a/chromium/content/child/fileapi/webfilesystem_impl.cc b/chromium/content/child/fileapi/webfilesystem_impl.cc
index 62e9f0eda62..6bc18eeca06 100644
--- a/chromium/content/child/fileapi/webfilesystem_impl.cc
+++ b/chromium/content/child/fileapi/webfilesystem_impl.cc
@@ -11,20 +11,20 @@
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_local.h"
-#include "content/child/blink_glue.h"
#include "content/child/child_thread.h"
+#include "content/child/file_info_util.h"
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/fileapi/webfilewriter_impl.h"
#include "content/child/worker_task_runner.h"
#include "content/common/fileapi/file_system_messages.h"
+#include "storage/common/fileapi/directory_entry.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "third_party/WebKit/public/platform/WebFileInfo.h"
#include "third_party/WebKit/public/platform/WebFileSystemCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebHeap.h"
#include "url/gurl.h"
-#include "webkit/common/fileapi/directory_entry.h"
-#include "webkit/common/fileapi/file_system_util.h"
using blink::WebFileInfo;
using blink::WebFileSystemCallbacks;
@@ -123,10 +123,63 @@ enum CallbacksUnregisterMode {
DO_NOT_UNREGISTER_CALLBACKS,
};
+// Bridging functions that convert the arguments into Blink objects
+// (e.g. WebFileInfo, WebString, WebVector<WebFileSystemEntry>)
+// and call WebFileSystemCallbacks's methods.
+// These are called by RunCallbacks after crossing threads to ensure
+// thread safety, because the Blink objects cannot be passed across
+// threads by base::Bind().
+void DidSucceed(WebFileSystemCallbacks* callbacks) {
+ callbacks->didSucceed();
+}
+
+void DidReadMetadata(const base::File::Info& file_info,
+ WebFileSystemCallbacks* callbacks) {
+ WebFileInfo web_file_info;
+ FileInfoToWebFileInfo(file_info, &web_file_info);
+ callbacks->didReadMetadata(web_file_info);
+}
+
+void DidReadDirectory(const std::vector<storage::DirectoryEntry>& entries,
+ bool has_more,
+ WebFileSystemCallbacks* callbacks) {
+ WebVector<WebFileSystemEntry> file_system_entries(entries.size());
+ for (size_t i = 0; i < entries.size(); ++i) {
+ file_system_entries[i].name =
+ base::FilePath(entries[i].name).AsUTF16Unsafe();
+ file_system_entries[i].isDirectory = entries[i].is_directory;
+ }
+ callbacks->didReadDirectory(file_system_entries, has_more);
+}
+
+void DidOpenFileSystem(const base::string16& name, const GURL& root,
+ WebFileSystemCallbacks* callbacks) {
+ callbacks->didOpenFileSystem(name, root);
+}
+
+void DidResolveURL(const base::string16& name,
+ const GURL& root_url,
+ storage::FileSystemType mount_type,
+ const base::string16& file_path,
+ bool is_directory,
+ WebFileSystemCallbacks* callbacks) {
+ callbacks->didResolveURL(
+ name,
+ root_url,
+ static_cast<blink::WebFileSystemType>(mount_type),
+ file_path,
+ is_directory);
+}
+
+void DidFail(base::File::Error error, WebFileSystemCallbacks* callbacks) {
+ callbacks->didFail(storage::FileErrorToWebFileError(error));
+}
+
// Run WebFileSystemCallbacks's |method| with |params|.
-template <typename Method, typename Params>
-void RunCallbacks(int callbacks_id, Method method, const Params& params,
- CallbacksUnregisterMode callbacks_unregister_mode) {
+void RunCallbacks(
+ int callbacks_id,
+ const base::Callback<void(WebFileSystemCallbacks*)>& callback,
+ CallbacksUnregisterMode callbacks_unregister_mode) {
WebFileSystemImpl* filesystem =
WebFileSystemImpl::ThreadSpecificInstance(NULL);
if (!filesystem)
@@ -134,7 +187,7 @@ void RunCallbacks(int callbacks_id, Method method, const Params& params,
WebFileSystemCallbacks callbacks = filesystem->GetCallbacks(callbacks_id);
if (callbacks_unregister_mode == UNREGISTER_CALLBACKS)
filesystem->UnregisterCallbacks(callbacks_id);
- DispatchToMethod(&callbacks, method, params);
+ callback.Run(&callbacks);
}
void DispatchResultsClosure(int thread_id, int callbacks_id,
@@ -157,16 +210,15 @@ void DispatchResultsClosure(int thread_id, int callbacks_id,
results_closure.Run();
}
-template <typename Method, typename Params>
void CallbackFileSystemCallbacks(
int thread_id, int callbacks_id,
WaitableCallbackResults* waitable_results,
- Method method, const Params& params,
- CallbacksUnregisterMode callbacks_unregister_mode) {
+ const base::Callback<void(WebFileSystemCallbacks*)>& callback,
+ CallbacksUnregisterMode callbacksunregister_mode) {
DispatchResultsClosure(
thread_id, callbacks_id, waitable_results,
- base::Bind(&RunCallbacks<Method, Params>, callbacks_id, method, params,
- callbacks_unregister_mode));
+ base::Bind(&RunCallbacks, callbacks_id, callback,
+ callbacksunregister_mode));
}
//-----------------------------------------------------------------------------
@@ -180,24 +232,23 @@ void OpenFileSystemCallbackAdapter(
const std::string& name, const GURL& root) {
CallbackFileSystemCallbacks(
thread_id, callbacks_id, waitable_results,
- &WebFileSystemCallbacks::didOpenFileSystem,
- MakeTuple(base::UTF8ToUTF16(name), root),
+ base::Bind(&DidOpenFileSystem, base::UTF8ToUTF16(name), root),
UNREGISTER_CALLBACKS);
}
-void ResolveURLCallbackAdapter(
- int thread_id, int callbacks_id,
- WaitableCallbackResults* waitable_results,
- const fileapi::FileSystemInfo& info,
- const base::FilePath& file_path, bool is_directory) {
+void ResolveURLCallbackAdapter(int thread_id,
+ int callbacks_id,
+ WaitableCallbackResults* waitable_results,
+ const storage::FileSystemInfo& info,
+ const base::FilePath& file_path,
+ bool is_directory) {
base::FilePath normalized_path(
- fileapi::VirtualPath::GetNormalizedFilePath(file_path));
+ storage::VirtualPath::GetNormalizedFilePath(file_path));
CallbackFileSystemCallbacks(
thread_id, callbacks_id, waitable_results,
- &WebFileSystemCallbacks::didResolveURL,
- MakeTuple(base::UTF8ToUTF16(info.name), info.root_url,
- static_cast<blink::WebFileSystemType>(info.mount_type),
- normalized_path.AsUTF16Unsafe(), is_directory),
+ base::Bind(&DidResolveURL, base::UTF8ToUTF16(info.name), info.root_url,
+ info.mount_type,
+ normalized_path.AsUTF16Unsafe(), is_directory),
UNREGISTER_CALLBACKS);
}
@@ -207,13 +258,12 @@ void StatusCallbackAdapter(int thread_id, int callbacks_id,
if (error == base::File::FILE_OK) {
CallbackFileSystemCallbacks(
thread_id, callbacks_id, waitable_results,
- &WebFileSystemCallbacks::didSucceed, MakeTuple(),
+ base::Bind(&DidSucceed),
UNREGISTER_CALLBACKS);
} else {
CallbackFileSystemCallbacks(
thread_id, callbacks_id, waitable_results,
- &WebFileSystemCallbacks::didFail,
- MakeTuple(fileapi::FileErrorToWebFileError(error)),
+ base::Bind(&DidFail, error),
UNREGISTER_CALLBACKS);
}
}
@@ -221,29 +271,21 @@ void StatusCallbackAdapter(int thread_id, int callbacks_id,
void ReadMetadataCallbackAdapter(int thread_id, int callbacks_id,
WaitableCallbackResults* waitable_results,
const base::File::Info& file_info) {
- WebFileInfo web_file_info;
- FileInfoToWebFileInfo(file_info, &web_file_info);
CallbackFileSystemCallbacks(
thread_id, callbacks_id, waitable_results,
- &WebFileSystemCallbacks::didReadMetadata,
- MakeTuple(web_file_info),
+ base::Bind(&DidReadMetadata, file_info),
UNREGISTER_CALLBACKS);
}
void ReadDirectoryCallbackAdapter(
- int thread_id, int callbacks_id, WaitableCallbackResults* waitable_results,
- const std::vector<fileapi::DirectoryEntry>& entries,
+ int thread_id,
+ int callbacks_id,
+ WaitableCallbackResults* waitable_results,
+ const std::vector<storage::DirectoryEntry>& entries,
bool has_more) {
- WebVector<WebFileSystemEntry> file_system_entries(entries.size());
- for (size_t i = 0; i < entries.size(); i++) {
- file_system_entries[i].name =
- base::FilePath(entries[i].name).AsUTF16Unsafe();
- file_system_entries[i].isDirectory = entries[i].is_directory;
- }
CallbackFileSystemCallbacks(
thread_id, callbacks_id, waitable_results,
- &WebFileSystemCallbacks::didReadDirectory,
- MakeTuple(file_system_entries, has_more),
+ base::Bind(&DidReadDirectory, entries, has_more),
has_more ? DO_NOT_UNREGISTER_CALLBACKS : UNREGISTER_CALLBACKS);
}
@@ -371,11 +413,15 @@ void WebFileSystemImpl::openFileSystem(
main_thread_loop_.get(),
&FileSystemDispatcher::OpenFileSystem,
MakeTuple(GURL(storage_partition),
- static_cast<fileapi::FileSystemType>(type),
+ static_cast<storage::FileSystemType>(type),
base::Bind(&OpenFileSystemCallbackAdapter,
- CurrentWorkerId(), callbacks_id, waitable_results),
+ CurrentWorkerId(),
+ callbacks_id,
+ waitable_results),
base::Bind(&StatusCallbackAdapter,
- CurrentWorkerId(), callbacks_id, waitable_results)),
+ CurrentWorkerId(),
+ callbacks_id,
+ waitable_results)),
waitable_results.get());
}
@@ -407,9 +453,11 @@ void WebFileSystemImpl::deleteFileSystem(
main_thread_loop_.get(),
&FileSystemDispatcher::DeleteFileSystem,
MakeTuple(GURL(storage_partition),
- static_cast<fileapi::FileSystemType>(type),
+ static_cast<storage::FileSystemType>(type),
base::Bind(&StatusCallbackAdapter,
- CurrentWorkerId(), callbacks_id, waitable_results)),
+ CurrentWorkerId(),
+ callbacks_id,
+ waitable_results)),
waitable_results.get());
}
diff --git a/chromium/content/child/fileapi/webfilesystem_impl.h b/chromium/content/child/fileapi/webfilesystem_impl.h
index 3be74634b64..b10a57fbea5 100644
--- a/chromium/content/child/fileapi/webfilesystem_impl.h
+++ b/chromium/content/child/fileapi/webfilesystem_impl.h
@@ -48,7 +48,7 @@ class WebFileSystemImpl : public blink::WebFileSystem,
virtual ~WebFileSystemImpl();
// WorkerTaskRunner::Observer implementation.
- virtual void OnWorkerRunLoopStopped() OVERRIDE;
+ void OnWorkerRunLoopStopped() override;
// WebFileSystem implementation.
virtual void openFileSystem(
@@ -57,7 +57,7 @@ class WebFileSystemImpl : public blink::WebFileSystem,
blink::WebFileSystemCallbacks);
virtual void resolveURL(
const blink::WebURL& filesystem_url,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void deleteFileSystem(
const blink::WebURL& storage_partition,
const blink::WebFileSystemType type,
@@ -65,41 +65,41 @@ class WebFileSystemImpl : public blink::WebFileSystem,
virtual void move(
const blink::WebURL& src_path,
const blink::WebURL& dest_path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void copy(
const blink::WebURL& src_path,
const blink::WebURL& dest_path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void remove(
const blink::WebURL& path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void removeRecursively(
const blink::WebURL& path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void readMetadata(
const blink::WebURL& path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void createFile(
const blink::WebURL& path,
bool exclusive,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void createDirectory(
const blink::WebURL& path,
bool exclusive,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void fileExists(
const blink::WebURL& path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void directoryExists(
const blink::WebURL& path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual int readDirectory(
const blink::WebURL& path,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void createFileWriter(
const blink::WebURL& path,
blink::WebFileWriterClient*,
- blink::WebFileSystemCallbacks) OVERRIDE;
+ blink::WebFileSystemCallbacks) override;
virtual void createSnapshotFileAndReadMetadata(
const blink::WebURL& path,
blink::WebFileSystemCallbacks);
diff --git a/chromium/content/child/fileapi/webfilewriter_base.cc b/chromium/content/child/fileapi/webfilewriter_base.cc
index a0ede790814..2236998de52 100644
--- a/chromium/content/child/fileapi/webfilewriter_base.cc
+++ b/chromium/content/child/fileapi/webfilewriter_base.cc
@@ -5,12 +5,12 @@
#include "content/child/fileapi/webfilewriter_base.h"
#include "base/logging.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "third_party/WebKit/public/platform/WebFileError.h"
#include "third_party/WebKit/public/platform/WebFileWriterClient.h"
#include "third_party/WebKit/public/platform/WebURL.h"
-#include "webkit/common/fileapi/file_system_util.h"
-using fileapi::FileErrorToWebFileError;
+using storage::FileErrorToWebFileError;
namespace content {
diff --git a/chromium/content/child/fileapi/webfilewriter_base_unittest.cc b/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
index 1c3448a1c27..68f58ff9f88 100644
--- a/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
+++ b/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
@@ -65,7 +65,7 @@ class TestableFileWriter : public WebFileWriterBase {
bool received_cancel_;
protected:
- virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE {
+ void DoTruncate(const GURL& path, int64 offset) override {
received_truncate_ = true;
received_truncate_path_ = path;
received_truncate_offset_ = offset;
@@ -87,9 +87,9 @@ class TestableFileWriter : public WebFileWriterBase {
}
}
- virtual void DoWrite(
- const GURL& path, const std::string& blob_uuid,
- int64 offset) OVERRIDE {
+ void DoWrite(const GURL& path,
+ const std::string& blob_uuid,
+ int64 offset) override {
received_write_ = true;
received_write_path_ = path;
received_write_offset_ = offset;
@@ -122,9 +122,7 @@ class TestableFileWriter : public WebFileWriterBase {
}
}
- virtual void DoCancel() OVERRIDE {
- received_cancel_ = true;
- }
+ void DoCancel() override { received_cancel_ = true; }
};
class FileWriterTest : public testing::Test,
diff --git a/chromium/content/child/fileapi/webfilewriter_impl.h b/chromium/content/child/fileapi/webfilewriter_impl.h
index 34f63bd3fb1..8aefaf51698 100644
--- a/chromium/content/child/fileapi/webfilewriter_impl.h
+++ b/chromium/content/child/fileapi/webfilewriter_impl.h
@@ -31,10 +31,11 @@ class WebFileWriterImpl : public WebFileWriterBase,
protected:
// WebFileWriterBase overrides
- virtual void DoTruncate(const GURL& path, int64 offset) OVERRIDE;
- virtual void DoWrite(const GURL& path, const std::string& blob_id,
- int64 offset) OVERRIDE;
- virtual void DoCancel() OVERRIDE;
+ void DoTruncate(const GURL& path, int64 offset) override;
+ void DoWrite(const GURL& path,
+ const std::string& blob_id,
+ int64 offset) override;
+ void DoCancel() override;
private:
class WriterBridge;
diff --git a/chromium/content/child/fling_animator_impl_android.cc b/chromium/content/child/fling_animator_impl_android.cc
deleted file mode 100644
index 7583c03772f..00000000000
--- a/chromium/content/child/fling_animator_impl_android.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2014 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 "content/child/fling_animator_impl_android.h"
-
-#include "base/logging.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
-#include "ui/gfx/frame_time.h"
-#include "ui/gfx/vector2d.h"
-
-namespace content {
-
-namespace {
-
-// Value taken directly from Android's ViewConfiguration. As the value has not
-// changed in 4+ years, and does not depend on any device-specific configuration
-// parameters, copy it directly to avoid potential JNI interop issues in the
-// render process (see crbug.com/362614).
-const float kDefaultAndroidPlatformScrollFriction = 0.015f;
-
-gfx::Scroller::Config GetScrollerConfig() {
- gfx::Scroller::Config config;
- config.flywheel_enabled = false;
- config.fling_friction = kDefaultAndroidPlatformScrollFriction;
- return config;
-}
-
-} // namespace
-
-FlingAnimatorImpl::FlingAnimatorImpl()
- : is_active_(false),
- scroller_(GetScrollerConfig()) {}
-
-FlingAnimatorImpl::~FlingAnimatorImpl() {}
-
-void FlingAnimatorImpl::StartFling(const gfx::PointF& velocity) {
- // No bounds on the fling. See http://webkit.org/b/96403
- // Instead, use the largest possible bounds for minX/maxX/minY/maxY. The
- // compositor will ignore any attempt to scroll beyond the end of the page.
-
- DCHECK(velocity.x() || velocity.y());
- if (is_active_)
- CancelFling();
-
- is_active_ = true;
- scroller_.Fling(0,
- 0,
- velocity.x(),
- velocity.y(),
- INT_MIN,
- INT_MAX,
- INT_MIN,
- INT_MAX,
- base::TimeTicks());
-}
-
-void FlingAnimatorImpl::CancelFling() {
- if (!is_active_)
- return;
-
- is_active_ = false;
- scroller_.AbortAnimation();
-}
-
-bool FlingAnimatorImpl::apply(double time,
- blink::WebGestureCurveTarget* target) {
- // If the fling has yet to start, simply return and report true to prevent
- // fling termination.
- if (time <= 0)
- return true;
-
- const base::TimeTicks time_ticks =
- base::TimeTicks() + base::TimeDelta::FromMicroseconds(
- time * base::Time::kMicrosecondsPerSecond);
- if (!scroller_.ComputeScrollOffset(time_ticks)) {
- is_active_ = false;
- return false;
- }
-
- gfx::PointF current_position(scroller_.GetCurrX(), scroller_.GetCurrY());
- gfx::Vector2dF scroll_amount(current_position - last_position_);
- last_position_ = current_position;
-
- // scrollBy() could delete this curve if the animation is over, so don't touch
- // any member variables after making that call.
- return target->scrollBy(blink::WebFloatSize(scroll_amount),
- blink::WebFloatSize(scroller_.GetCurrVelocityX(),
- scroller_.GetCurrVelocityY()));
-}
-
-FlingAnimatorImpl* FlingAnimatorImpl::CreateAndroidGestureCurve(
- const blink::WebFloatPoint& velocity,
- const blink::WebSize&) {
- FlingAnimatorImpl* gesture_curve = new FlingAnimatorImpl();
- gesture_curve->StartFling(velocity);
- return gesture_curve;
-}
-
-} // namespace content
diff --git a/chromium/content/child/fling_animator_impl_android.h b/chromium/content/child/fling_animator_impl_android.h
deleted file mode 100644
index ea33ba29196..00000000000
--- a/chromium/content/child/fling_animator_impl_android.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_FLING_ANIMATOR_IMPL_ANDROID_H_
-#define CONTENT_CHILD_FLING_ANIMATOR_IMPL_ANDROID_H_
-
-
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "ui/gfx/android/scroller.h"
-#include "ui/gfx/point_f.h"
-
-namespace blink {
-class WebGestureCurveTarget;
-}
-
-namespace content {
-
-class FlingAnimatorImpl : public blink::WebGestureCurve {
- public:
- FlingAnimatorImpl();
- virtual ~FlingAnimatorImpl();
-
- static FlingAnimatorImpl* CreateAndroidGestureCurve(
- const blink::WebFloatPoint& velocity,
- const blink::WebSize&);
-
- virtual bool apply(double time, blink::WebGestureCurveTarget* target);
-
- private:
- void StartFling(const gfx::PointF& velocity);
- void CancelFling();
-
- bool is_active_;
-
- gfx::Scroller scroller_;
-
- gfx::PointF last_position_;
-
- DISALLOW_COPY_AND_ASSIGN(FlingAnimatorImpl);
-};
-
-} // namespace webkit_glue
-
-#endif // CONTENT_CHILD_FLING_ANIMATOR_IMPL_ANDROID_H_
diff --git a/chromium/content/child/fling_curve_configuration.cc b/chromium/content/child/fling_curve_configuration.cc
deleted file mode 100644
index 8beeb3672c6..00000000000
--- a/chromium/content/child/fling_curve_configuration.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 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 "content/child/fling_curve_configuration.h"
-
-#include "base/logging.h"
-#include "content/child/touch_fling_gesture_curve.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-
-namespace content {
-
-FlingCurveConfiguration::FlingCurveConfiguration() { }
-
-FlingCurveConfiguration::~FlingCurveConfiguration() { }
-
-void FlingCurveConfiguration::SetCurveParameters(
- const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen) {
- DCHECK(new_touchpad.size() >= 3);
- DCHECK(new_touchscreen.size() >= 3);
- base::AutoLock scoped_lock(lock_);
- touchpad_coefs_ = new_touchpad;
- touchscreen_coefs_ = new_touchscreen;
-}
-
-blink::WebGestureCurve* FlingCurveConfiguration::CreateCore(
- const std::vector<float>& coefs,
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll) {
- float p0, p1, p2;
-
- {
- base::AutoLock scoped_lock(lock_);
- p0 = coefs[0];
- p1 = coefs[1];
- p2 = coefs[2];
- }
-
- return TouchFlingGestureCurve::Create(velocity, p0, p1, p2,
- cumulativeScroll);
-}
-
-blink::WebGestureCurve* FlingCurveConfiguration::CreateForTouchPad(
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll) {
- return CreateCore(touchpad_coefs_, velocity, cumulativeScroll);
-}
-
-blink::WebGestureCurve* FlingCurveConfiguration::CreateForTouchScreen(
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll) {
- return CreateCore(touchscreen_coefs_, velocity, cumulativeScroll);
-}
-
-} // namespace content
diff --git a/chromium/content/child/fling_curve_configuration.h b/chromium/content/child/fling_curve_configuration.h
deleted file mode 100644
index 1a6573dccee..00000000000
--- a/chromium/content/child/fling_curve_configuration.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_FLING_CURVE_CONFIGURATION_H_
-#define CONTENT_CHILD_FLING_CURVE_CONFIGURATION_H_
-
-#include <vector>
-
-#include "base/synchronization/lock.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-
-namespace blink {
-class WebGestureCurve;
-}
-
-namespace content {
-
-// A class to manage dynamically adjustable parameters controlling the
-// shape of the fling deacceleration function.
-class FlingCurveConfiguration {
- public:
- FlingCurveConfiguration();
- virtual ~FlingCurveConfiguration();
-
- // Create a touchpad fling curve using the current parameters.
- blink::WebGestureCurve* CreateForTouchPad(
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll);
-
- // Create a touchscreen fling curve using the current parameters.
- blink::WebGestureCurve* CreateForTouchScreen(
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll);
-
- // Set the curve parameters.
- void SetCurveParameters(
- const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen);
-
- private:
- blink::WebGestureCurve* CreateCore(
- const std::vector<float>& coefs,
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll);
-
- // Protect access to touchpad_coefs_ and touchscreen_coefs_.
- base::Lock lock_;
- std::vector<float> touchpad_coefs_;
- std::vector<float> touchscreen_coefs_;
-
- DISALLOW_COPY_AND_ASSIGN(FlingCurveConfiguration);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_FLING_CURVE_CONFIGURATION_H_
diff --git a/chromium/content/child/ftp_directory_listing_response_delegate.cc b/chromium/content/child/ftp_directory_listing_response_delegate.cc
index c3cc82705d9..82fa6482bf8 100644
--- a/chromium/content/child/ftp_directory_listing_response_delegate.cc
+++ b/chromium/content/child/ftp_directory_listing_response_delegate.cc
@@ -13,19 +13,18 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "content/child/weburlresponse_extradata_impl.h"
#include "net/base/escape.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/ftp/ftp_directory_listing_parser.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "webkit/child/weburlresponse_extradata_impl.h"
using blink::WebURLLoader;
using blink::WebURLLoaderClient;
using blink::WebURLResponse;
using net::FtpDirectoryListingEntry;
-using webkit_glue::WebURLResponseExtraDataImpl;
namespace {
@@ -82,7 +81,10 @@ void FtpDirectoryListingResponseDelegate::OnReceivedData(const char* data,
void FtpDirectoryListingResponseDelegate::OnCompletedRequest() {
std::vector<FtpDirectoryListingEntry> entries;
- int rv = net::ParseFtpDirectoryListing(buffer_, base::Time::Now(), &entries);
+ int rv = -1;
+#if !defined(DISABLE_FTP_SUPPORT)
+ rv = net::ParseFtpDirectoryListing(buffer_, base::Time::Now(), &entries);
+#endif
if (rv != net::OK) {
SendDataToClient("<script>onListingParsingError();</script>\n");
return;
diff --git a/chromium/content/child/geofencing/OWNERS b/chromium/content/child/geofencing/OWNERS
new file mode 100644
index 00000000000..1b10b3436d9
--- /dev/null
+++ b/chromium/content/child/geofencing/OWNERS
@@ -0,0 +1 @@
+mek@chromium.org
diff --git a/chromium/content/child/geofencing/geofencing_dispatcher.cc b/chromium/content/child/geofencing/geofencing_dispatcher.cc
new file mode 100644
index 00000000000..eec721faf97
--- /dev/null
+++ b/chromium/content/child/geofencing/geofencing_dispatcher.cc
@@ -0,0 +1,218 @@
+// Copyright 2014 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 "content/child/geofencing/geofencing_dispatcher.h"
+
+#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/child/service_worker/web_service_worker_registration_impl.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_thread_task_runner.h"
+#include "content/common/geofencing_messages.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+#include "third_party/WebKit/public/platform/WebGeofencingError.h"
+#include "third_party/WebKit/public/platform/WebGeofencingRegistration.h"
+
+using blink::WebGeofencingError;
+
+namespace content {
+
+namespace {
+
+base::LazyInstance<base::ThreadLocalPointer<GeofencingDispatcher>>::Leaky
+ g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
+
+GeofencingDispatcher* const kHasBeenDeleted =
+ reinterpret_cast<GeofencingDispatcher*>(0x1);
+
+int CurrentWorkerId() {
+ return WorkerTaskRunner::Instance()->CurrentWorkerId();
+}
+
+} // namespace
+
+GeofencingDispatcher::GeofencingDispatcher(ThreadSafeSender* sender)
+ : thread_safe_sender_(sender) {
+ g_dispatcher_tls.Pointer()->Set(this);
+}
+
+GeofencingDispatcher::~GeofencingDispatcher() {
+ g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
+}
+
+bool GeofencingDispatcher::Send(IPC::Message* msg) {
+ return thread_safe_sender_->Send(msg);
+}
+
+void GeofencingDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GeofencingDispatcher, msg)
+ IPC_MESSAGE_HANDLER(GeofencingMsg_RegisterRegionComplete,
+ OnRegisterRegionComplete)
+ IPC_MESSAGE_HANDLER(GeofencingMsg_UnregisterRegionComplete,
+ OnUnregisterRegionComplete)
+ IPC_MESSAGE_HANDLER(GeofencingMsg_GetRegisteredRegionsComplete,
+ OnGetRegisteredRegionsComplete)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled) << "Unhandled message:" << msg.type();
+}
+
+void GeofencingDispatcher::RegisterRegion(
+ const blink::WebString& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = region_registration_requests_.Add(callbacks);
+ // TODO(mek): Immediately reject requests lacking a service worker
+ // registration, without bouncing through browser process.
+ int64 serviceworker_registration_id = kInvalidServiceWorkerRegistrationId;
+ if (service_worker_registration) {
+ serviceworker_registration_id =
+ static_cast<WebServiceWorkerRegistrationImpl*>(
+ service_worker_registration)->registration_id();
+ }
+ Send(new GeofencingHostMsg_RegisterRegion(CurrentWorkerId(),
+ request_id,
+ region_id.utf8(),
+ region,
+ serviceworker_registration_id));
+}
+
+void GeofencingDispatcher::UnregisterRegion(
+ const blink::WebString& region_id,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = region_unregistration_requests_.Add(callbacks);
+ // TODO(mek): Immediately reject requests lacking a service worker
+ // registration, without bouncing through browser process.
+ int64 serviceworker_registration_id = kInvalidServiceWorkerRegistrationId;
+ if (service_worker_registration) {
+ serviceworker_registration_id =
+ static_cast<WebServiceWorkerRegistrationImpl*>(
+ service_worker_registration)->registration_id();
+ }
+ Send(new GeofencingHostMsg_UnregisterRegion(CurrentWorkerId(),
+ request_id,
+ region_id.utf8(),
+ serviceworker_registration_id));
+}
+
+void GeofencingDispatcher::GetRegisteredRegions(
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingRegionsCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = get_registered_regions_requests_.Add(callbacks);
+ // TODO(mek): Immediately reject requests lacking a service worker
+ // registration, without bouncing through browser process.
+ int64 serviceworker_registration_id = kInvalidServiceWorkerRegistrationId;
+ if (service_worker_registration) {
+ serviceworker_registration_id =
+ static_cast<WebServiceWorkerRegistrationImpl*>(
+ service_worker_registration)->registration_id();
+ }
+ Send(new GeofencingHostMsg_GetRegisteredRegions(
+ CurrentWorkerId(), request_id, serviceworker_registration_id));
+}
+
+GeofencingDispatcher* GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender) {
+ if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
+ NOTREACHED() << "Re-instantiating TLS GeofencingDispatcher.";
+ g_dispatcher_tls.Pointer()->Set(NULL);
+ }
+ if (g_dispatcher_tls.Pointer()->Get())
+ return g_dispatcher_tls.Pointer()->Get();
+
+ GeofencingDispatcher* dispatcher =
+ new GeofencingDispatcher(thread_safe_sender);
+ if (WorkerTaskRunner::Instance()->CurrentWorkerId())
+ WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
+ return dispatcher;
+}
+
+GeofencingDispatcher* GeofencingDispatcher::GetThreadSpecificInstance() {
+ if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
+ return NULL;
+ return g_dispatcher_tls.Pointer()->Get();
+}
+
+void GeofencingDispatcher::OnRegisterRegionComplete(int thread_id,
+ int request_id,
+ GeofencingStatus status) {
+ blink::WebGeofencingCallbacks* callbacks =
+ region_registration_requests_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ if (status == GEOFENCING_STATUS_OK) {
+ callbacks->onSuccess();
+ } else {
+ callbacks->onError(new WebGeofencingError(
+ WebGeofencingError::ErrorTypeAbort,
+ blink::WebString::fromUTF8(GeofencingStatusToString(status))));
+ }
+ region_registration_requests_.Remove(request_id);
+}
+
+void GeofencingDispatcher::OnUnregisterRegionComplete(int thread_id,
+ int request_id,
+ GeofencingStatus status) {
+ blink::WebGeofencingCallbacks* callbacks =
+ region_unregistration_requests_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ if (status == GEOFENCING_STATUS_OK) {
+ callbacks->onSuccess();
+ } else {
+ callbacks->onError(new WebGeofencingError(
+ WebGeofencingError::ErrorTypeAbort,
+ blink::WebString::fromUTF8(GeofencingStatusToString(status))));
+ }
+ region_unregistration_requests_.Remove(request_id);
+}
+
+void GeofencingDispatcher::OnGetRegisteredRegionsComplete(
+ int thread_id,
+ int request_id,
+ GeofencingStatus status,
+ const GeofencingRegistrations& regions) {
+ blink::WebGeofencingRegionsCallbacks* callbacks =
+ get_registered_regions_requests_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ if (status == GEOFENCING_STATUS_OK) {
+ scoped_ptr<blink::WebVector<blink::WebGeofencingRegistration>> result(
+ new blink::WebVector<blink::WebGeofencingRegistration>(regions.size()));
+ size_t index = 0;
+ for (GeofencingRegistrations::const_iterator it = regions.begin();
+ it != regions.end();
+ ++it, ++index) {
+ (*result)[index].id = blink::WebString::fromUTF8(it->first);
+ (*result)[index].region = it->second;
+ }
+ callbacks->onSuccess(result.release());
+ } else {
+ callbacks->onError(new WebGeofencingError(
+ WebGeofencingError::ErrorTypeAbort,
+ blink::WebString::fromUTF8(GeofencingStatusToString(status))));
+ }
+ get_registered_regions_requests_.Remove(request_id);
+}
+
+void GeofencingDispatcher::OnWorkerRunLoopStopped() {
+ delete this;
+}
+
+} // namespace content
diff --git a/chromium/content/child/geofencing/geofencing_dispatcher.h b/chromium/content/child/geofencing/geofencing_dispatcher.h
new file mode 100644
index 00000000000..57a2a437b5d
--- /dev/null
+++ b/chromium/content/child/geofencing/geofencing_dispatcher.h
@@ -0,0 +1,87 @@
+// Copyright 2014 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 CONTENT_CHILD_GEOFENCING_GEOFENCING_DISPATCHER_H_
+#define CONTENT_CHILD_GEOFENCING_GEOFENCING_DISPATCHER_H_
+
+#include "base/id_map.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/child/worker_task_runner.h"
+#include "content/common/geofencing_status.h"
+#include "third_party/WebKit/public/platform/WebGeofencingProvider.h"
+
+namespace base {
+class MessageLoop;
+class TaskRunner;
+}
+
+namespace IPC {
+class Message;
+}
+
+namespace content {
+class ThreadSafeSender;
+
+class GeofencingDispatcher : public WorkerTaskRunner::Observer {
+ public:
+ explicit GeofencingDispatcher(ThreadSafeSender* sender);
+ ~GeofencingDispatcher() override;
+
+ bool Send(IPC::Message* msg);
+ void OnMessageReceived(const IPC::Message& msg);
+
+ // Corresponding to WebGeofencingProvider methods.
+ void RegisterRegion(
+ const blink::WebString& region_id,
+ const blink::WebCircularGeofencingRegion& region,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks);
+ void UnregisterRegion(
+ const blink::WebString& region_id,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks);
+ void GetRegisteredRegions(
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingRegionsCallbacks* callbacks);
+
+ // |thread_safe_sender| needs to be passed in because if the call leads to
+ // construction it will be needed.
+ static GeofencingDispatcher* GetOrCreateThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender);
+
+ // Unlike GetOrCreateThreadSpecificInstance() this doesn't create a new
+ // instance if thread-local instance doesn't exist.
+ static GeofencingDispatcher* GetThreadSpecificInstance();
+
+ private:
+ void OnRegisterRegionComplete(int thread_id,
+ int request_id,
+ GeofencingStatus status);
+ void OnUnregisterRegionComplete(int thread_id,
+ int request_id,
+ GeofencingStatus status);
+ void OnGetRegisteredRegionsComplete(
+ int thread_id,
+ int request_id,
+ GeofencingStatus status,
+ const std::map<std::string, blink::WebCircularGeofencingRegion>& regions);
+
+ // WorkerTaskRunner::Observer implementation.
+ void OnWorkerRunLoopStopped() override;
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+ IDMap<blink::WebGeofencingCallbacks, IDMapOwnPointer>
+ region_registration_requests_;
+ IDMap<blink::WebGeofencingCallbacks, IDMapOwnPointer>
+ region_unregistration_requests_;
+ IDMap<blink::WebGeofencingRegionsCallbacks, IDMapOwnPointer>
+ get_registered_regions_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeofencingDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_GEOFENCING_GEOFENCING_DISPATCHER_H_
diff --git a/chromium/content/child/geofencing/geofencing_message_filter.cc b/chromium/content/child/geofencing/geofencing_message_filter.cc
new file mode 100644
index 00000000000..a8334571d5b
--- /dev/null
+++ b/chromium/content/child/geofencing/geofencing_message_filter.cc
@@ -0,0 +1,43 @@
+// Copyright 2014 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 "content/child/geofencing/geofencing_message_filter.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/child/geofencing/geofencing_dispatcher.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_thread_task_runner.h"
+#include "ipc/ipc_message_macros.h"
+
+namespace content {
+
+GeofencingMessageFilter::GeofencingMessageFilter(ThreadSafeSender* sender)
+ : main_thread_loop_proxy_(base::MessageLoopProxy::current()),
+ thread_safe_sender_(sender) {
+}
+
+GeofencingMessageFilter::~GeofencingMessageFilter() {
+}
+
+base::TaskRunner* GeofencingMessageFilter::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != GeofencingMsgStart)
+ return NULL;
+ int ipc_thread_id = 0;
+ const bool success = PickleIterator(msg).ReadInt(&ipc_thread_id);
+ DCHECK(success);
+ if (!ipc_thread_id)
+ return main_thread_loop_proxy_.get();
+ return new WorkerThreadTaskRunner(ipc_thread_id);
+}
+
+bool GeofencingMessageFilter::OnMessageReceived(const IPC::Message& msg) {
+ if (IPC_MESSAGE_CLASS(msg) != GeofencingMsgStart)
+ return false;
+ GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
+ thread_safe_sender_.get())->OnMessageReceived(msg);
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/child/geofencing/geofencing_message_filter.h b/chromium/content/child/geofencing/geofencing_message_filter.h
new file mode 100644
index 00000000000..3a95d423ccd
--- /dev/null
+++ b/chromium/content/child/geofencing/geofencing_message_filter.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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 CONTENT_CHILD_GEOFENCING_GEOFENCING_MESSAGE_FILTER_H_
+#define CONTENT_CHILD_GEOFENCING_GEOFENCING_MESSAGE_FILTER_H_
+
+#include "content/child/child_message_filter.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+class ThreadSafeSender;
+
+class GeofencingMessageFilter : public ChildMessageFilter {
+ public:
+ explicit GeofencingMessageFilter(ThreadSafeSender* thread_safe_sender);
+
+ private:
+ ~GeofencingMessageFilter() override;
+
+ // ChildMessageFilter implementation:
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
+ scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(GeofencingMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_GEOFENCING_GEOFENCING_MESSAGE_FILTER_H_
diff --git a/chromium/content/child/geofencing/web_geofencing_provider_impl.cc b/chromium/content/child/geofencing/web_geofencing_provider_impl.cc
new file mode 100644
index 00000000000..5d78b9810b8
--- /dev/null
+++ b/chromium/content/child/geofencing/web_geofencing_provider_impl.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 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 "content/child/geofencing/web_geofencing_provider_impl.h"
+
+#include "content/child/geofencing/geofencing_dispatcher.h"
+#include "content/child/thread_safe_sender.h"
+
+namespace content {
+
+WebGeofencingProviderImpl::WebGeofencingProviderImpl(
+ ThreadSafeSender* thread_safe_sender)
+ : thread_safe_sender_(thread_safe_sender) {
+}
+
+WebGeofencingProviderImpl::~WebGeofencingProviderImpl() {
+}
+
+void WebGeofencingProviderImpl::registerRegion(
+ const blink::WebString& regionId,
+ const blink::WebCircularGeofencingRegion& region,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks) {
+ GetDispatcher()->RegisterRegion(
+ regionId, region, service_worker_registration, callbacks);
+}
+
+void WebGeofencingProviderImpl::unregisterRegion(
+ const blink::WebString& regionId,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks) {
+ GetDispatcher()->UnregisterRegion(
+ regionId, service_worker_registration, callbacks);
+}
+
+void WebGeofencingProviderImpl::getRegisteredRegions(
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingRegionsCallbacks* callbacks) {
+ GetDispatcher()->GetRegisteredRegions(service_worker_registration, callbacks);
+}
+
+GeofencingDispatcher* WebGeofencingProviderImpl::GetDispatcher() {
+ return GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
+ thread_safe_sender_.get());
+}
+
+} // namespace content
diff --git a/chromium/content/child/geofencing/web_geofencing_provider_impl.h b/chromium/content/child/geofencing/web_geofencing_provider_impl.h
new file mode 100644
index 00000000000..9aac7951731
--- /dev/null
+++ b/chromium/content/child/geofencing/web_geofencing_provider_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2014 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 CONTENT_CHILD_GEOFENCING_WEB_GEOFENCING_PROVIDER_IMPL_H_
+#define CONTENT_CHILD_GEOFENCING_WEB_GEOFENCING_PROVIDER_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "third_party/WebKit/public/platform/WebGeofencingProvider.h"
+
+namespace content {
+class GeofencingDispatcher;
+class ThreadSafeSender;
+
+class WebGeofencingProviderImpl
+ : NON_EXPORTED_BASE(public blink::WebGeofencingProvider) {
+ public:
+ explicit WebGeofencingProviderImpl(ThreadSafeSender* thread_safe_sender);
+ virtual ~WebGeofencingProviderImpl();
+
+ private:
+ // WebGeofencingProvider implementation.
+ virtual void registerRegion(
+ const blink::WebString& regionId,
+ const blink::WebCircularGeofencingRegion& region,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks);
+ virtual void unregisterRegion(
+ const blink::WebString& regionId,
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingCallbacks* callbacks);
+ virtual void getRegisteredRegions(
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ blink::WebGeofencingRegionsCallbacks* callbacks);
+
+ GeofencingDispatcher* GetDispatcher();
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebGeofencingProviderImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_GEOFENCING_WEB_GEOFENCING_PROVIDER_IMPL_H_
diff --git a/chromium/content/child/indexed_db/OWNERS b/chromium/content/child/indexed_db/OWNERS
index c7ad25e64c2..1f0a278156e 100644
--- a/chromium/content/child/indexed_db/OWNERS
+++ b/chromium/content/child/indexed_db/OWNERS
@@ -1,17 +1,17 @@
dgrogan@chromium.org
michaeln@chromium.org
jsbell@chromium.org
-ericu@chromium.org
cmumford@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher.cc b/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
index e814cc87420..9cd48e2c1ce 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
@@ -278,12 +278,17 @@ void IndexedDBDispatcher::RequestIDBDatabaseClose(
pending_database_callbacks_.Remove(ipc_database_callbacks_id);
}
+void IndexedDBDispatcher::NotifyIDBDatabaseVersionChangeIgnored(
+ int32 ipc_database_id) {
+ Send(new IndexedDBHostMsg_DatabaseVersionChangeIgnored(ipc_database_id));
+}
+
void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
int32 ipc_database_id,
int64 transaction_id,
WebIDBDatabaseCallbacks* database_callbacks_ptr,
WebVector<long long> object_store_ids,
- WebIDBDatabase::TransactionMode mode) {
+ blink::WebIDBTransactionMode mode) {
scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
database_callbacks_ptr);
IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
@@ -327,11 +332,10 @@ void IndexedDBDispatcher::RequestIDBDatabasePut(
const WebData& value,
const blink::WebVector<WebBlobInfo>& web_blob_info,
const IndexedDBKey& key,
- WebIDBDatabase::PutMode put_mode,
+ blink::WebIDBPutMode put_mode,
WebIDBCallbacks* callbacks,
const WebVector<long long>& index_ids,
const WebVector<WebVector<WebIDBKey> >& index_keys) {
-
if (value.size() + key.size_estimate() > kMaxIDBValueSizeInBytes) {
callbacks->onError(WebIDBDatabaseError(
blink::WebIDBDatabaseExceptionUnknownError,
@@ -391,9 +395,9 @@ void IndexedDBDispatcher::RequestIDBDatabaseOpenCursor(
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- WebIDBCursor::Direction direction,
+ blink::WebIDBCursorDirection direction,
bool key_only,
- WebIDBDatabase::TaskType task_type,
+ blink::WebIDBTaskType task_type,
WebIDBCallbacks* callbacks) {
ResetCursorPrefetchCaches(transaction_id, kAllCursors);
IndexedDBHostMsg_DatabaseOpenCursor_Params params;
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher.h b/chromium/content/child/indexed_db/indexed_db_dispatcher.h
index d0e1118dc81..e2df2893bdb 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher.h
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher.h
@@ -18,9 +18,8 @@
#include "ipc/ipc_sync_message_filter.h"
#include "third_party/WebKit/public/platform/WebBlobInfo.h"
#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
-#include "third_party/WebKit/public/platform/WebIDBCursor.h"
-#include "third_party/WebKit/public/platform/WebIDBDatabase.h"
#include "third_party/WebKit/public/platform/WebIDBDatabaseCallbacks.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
struct IndexedDBDatabaseMetadata;
struct IndexedDBMsg_CallbacksSuccessCursorContinue_Params;
@@ -53,7 +52,7 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerTaskRunner::Observer {
// two copies of RenderThreadImpl on the same thread. Everyone else probably
// wants to use ThreadSpecificInstance().
explicit IndexedDBDispatcher(ThreadSafeSender* thread_safe_sender);
- virtual ~IndexedDBDispatcher();
+ ~IndexedDBDispatcher() override;
// |thread_safe_sender| needs to be passed in because if the call leads to
// construction it will be needed.
@@ -61,7 +60,7 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerTaskRunner::Observer {
ThreadSafeSender* thread_safe_sender);
// WorkerTaskRunner::Observer implementation.
- virtual void OnWorkerRunLoopStopped() OVERRIDE;
+ void OnWorkerRunLoopStopped() override;
static blink::WebIDBMetadata ConvertMetadata(
const IndexedDBDatabaseMetadata& idb_metadata);
@@ -113,12 +112,14 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerTaskRunner::Observer {
void RequestIDBDatabaseClose(int32 ipc_database_id,
int32 ipc_database_callbacks_id);
+ void NotifyIDBDatabaseVersionChangeIgnored(int32 ipc_database_id);
+
void RequestIDBDatabaseCreateTransaction(
int32 ipc_database_id,
int64 transaction_id,
blink::WebIDBDatabaseCallbacks* database_callbacks_ptr,
blink::WebVector<long long> object_store_ids,
- blink::WebIDBDatabase::TransactionMode mode);
+ blink::WebIDBTransactionMode mode);
void RequestIDBDatabaseGet(int32 ipc_database_id,
int64 transaction_id,
@@ -135,7 +136,7 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerTaskRunner::Observer {
const blink::WebData& value,
const blink::WebVector<blink::WebBlobInfo>& web_blob_info,
const IndexedDBKey& key,
- blink::WebIDBDatabase::PutMode put_mode,
+ blink::WebIDBPutMode put_mode,
blink::WebIDBCallbacks* callbacks,
const blink::WebVector<long long>& index_ids,
const blink::WebVector<blink::WebVector<blink::WebIDBKey> >& index_keys);
@@ -145,9 +146,9 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerTaskRunner::Observer {
int64 object_store_id,
int64 index_id,
const IndexedDBKeyRange& key_range,
- blink::WebIDBCursor::Direction direction,
+ blink::WebIDBCursorDirection direction,
bool key_only,
- blink::WebIDBDatabase::TaskType task_type,
+ blink::WebIDBTaskType task_type,
blink::WebIDBCallbacks* callbacks);
void RequestIDBDatabaseCount(int32 ipc_database_id,
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc b/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
index 6bc4d5df4cd..4f29998f02c 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
@@ -16,6 +16,7 @@
#include "third_party/WebKit/public/platform/WebBlobInfo.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebIDBCallbacks.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
using blink::WebBlobInfo;
using blink::WebData;
@@ -48,7 +49,7 @@ class MockDispatcher : public IndexedDBDispatcher {
explicit MockDispatcher(ThreadSafeSender* sender)
: IndexedDBDispatcher(sender) {}
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
delete msg;
return true;
}
@@ -67,6 +68,8 @@ class IndexedDBDispatcherTest : public testing::Test {
thread_safe_sender_(new ThreadSafeSender(message_loop_proxy_.get(),
sync_message_filter_.get())) {}
+ void TearDown() override { blink::WebHeap::collectAllGarbageForTesting(); }
+
protected:
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
@@ -93,7 +96,7 @@ TEST_F(IndexedDBDispatcherTest, ValueSizeTest) {
value,
web_blob_info,
key,
- WebIDBDatabase::AddOrUpdate,
+ blink::WebIDBPutModeAddOrUpdate,
&callbacks,
WebVector<long long>(),
WebVector<WebVector<WebIDBKey> >());
@@ -122,7 +125,7 @@ TEST_F(IndexedDBDispatcherTest, KeyAndValueSizeTest) {
value,
web_blob_info,
key,
- WebIDBDatabase::AddOrUpdate,
+ blink::WebIDBPutModeAddOrUpdate,
&callbacks,
WebVector<long long>(),
WebVector<WebVector<WebIDBKey> >());
@@ -138,12 +141,12 @@ class CursorCallbacks : public WebIDBCallbacks {
: cursor_(cursor) {}
virtual void onSuccess(const WebData&,
- const WebVector<WebBlobInfo>&) OVERRIDE {}
+ const WebVector<WebBlobInfo>&) override {}
virtual void onSuccess(WebIDBCursor* cursor,
const WebIDBKey& key,
const WebIDBKey& primaryKey,
const WebData& value,
- const WebVector<WebBlobInfo>&) OVERRIDE {
+ const WebVector<WebBlobInfo>&) override {
cursor_->reset(cursor);
}
@@ -160,7 +163,8 @@ TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
const int64 transaction_id = 1234;
const int64 object_store_id = 2;
const int32 index_id = 3;
- const WebIDBCursor::Direction direction = WebIDBCursor::Next;
+ const blink::WebIDBCursorDirection direction =
+ blink::WebIDBCursorDirectionNext;
const bool key_only = false;
MockDispatcher dispatcher(thread_safe_sender_.get());
@@ -178,7 +182,7 @@ TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
IndexedDBKeyRange(),
direction,
key_only,
- blink::WebIDBDatabase::NormalTask,
+ blink::WebIDBTaskTypeNormal,
new CursorCallbacks(&cursor));
// Verify that the transaction id was captured.
@@ -219,7 +223,7 @@ TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
IndexedDBKeyRange(),
direction,
key_only,
- blink::WebIDBDatabase::NormalTask,
+ blink::WebIDBTaskTypeNormal,
new CursorCallbacks(&cursor));
// Verify that the transaction id was captured.
@@ -251,7 +255,7 @@ class MockCursor : public WebIDBCursorImpl {
reset_count_(0) {}
// This method is virtual so it can be overridden in unit tests.
- virtual void ResetPrefetchCache() OVERRIDE { ++reset_count_; }
+ void ResetPrefetchCache() override { ++reset_count_; }
int reset_count() const { return reset_count_; }
diff --git a/chromium/content/child/indexed_db/indexed_db_message_filter.h b/chromium/content/child/indexed_db/indexed_db_message_filter.h
index 8b17954d2e1..e2d1ed541d7 100644
--- a/chromium/content/child/indexed_db/indexed_db_message_filter.h
+++ b/chromium/content/child/indexed_db/indexed_db_message_filter.h
@@ -28,14 +28,14 @@ class IndexedDBMessageFilter : public ChildMessageFilter {
explicit IndexedDBMessageFilter(ThreadSafeSender* thread_safe_sender);
protected:
- virtual ~IndexedDBMessageFilter();
+ ~IndexedDBMessageFilter() override;
private:
// ChildMessageFilter implementation:
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnStaleMessageReceived(const IPC::Message& msg) OVERRIDE;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnStaleMessageReceived(const IPC::Message& msg) override;
void OnStaleSuccessIDBDatabase(int32 ipc_thread_id,
int32 ipc_callbacks_id,
diff --git a/chromium/content/child/indexed_db/webidbcursor_impl.h b/chromium/content/child/indexed_db/webidbcursor_impl.h
index 1a06d99fdc2..604cf42bcd1 100644
--- a/chromium/content/child/indexed_db/webidbcursor_impl.h
+++ b/chromium/content/child/indexed_db/webidbcursor_impl.h
@@ -59,6 +59,11 @@ class CONTENT_EXPORT WebIDBCursorImpl
FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchReset);
FRIEND_TEST_ALL_PREFIXES(WebIDBCursorImplTest, PrefetchTest);
+ enum { kInvalidCursorId = -1 };
+ enum { kPrefetchContinueThreshold = 2 };
+ enum { kMinPrefetchAmount = 5 };
+ enum { kMaxPrefetchAmount = 100 };
+
int32 ipc_cursor_id_;
int64 transaction_id_;
@@ -81,11 +86,6 @@ class CONTENT_EXPORT WebIDBCursorImpl
int prefetch_amount_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
-
- enum { kInvalidCursorId = -1 };
- enum { kPrefetchContinueThreshold = 2 };
- enum { kMinPrefetchAmount = 5 };
- enum { kMaxPrefetchAmount = 100 };
};
} // namespace content
diff --git a/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc b/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
index 2ff4617c781..ab56cd2d330 100644
--- a/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
+++ b/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
@@ -38,39 +38,39 @@ class MockDispatcher : public IndexedDBDispatcher {
continue_calls_(0),
destroyed_cursor_id_(0) {}
- virtual void RequestIDBCursorPrefetch(int n,
- WebIDBCallbacks* callbacks,
- int32 ipc_cursor_id) OVERRIDE {
+ void RequestIDBCursorPrefetch(int n,
+ WebIDBCallbacks* callbacks,
+ int32 ipc_cursor_id) override {
++prefetch_calls_;
last_prefetch_count_ = n;
callbacks_.reset(callbacks);
}
- virtual void RequestIDBCursorPrefetchReset(int used_prefetches,
- int unused_prefetches,
- int32 ipc_cursor_id) OVERRIDE {
+ void RequestIDBCursorPrefetchReset(int used_prefetches,
+ int unused_prefetches,
+ int32 ipc_cursor_id) override {
++reset_calls_;
last_used_count_ = used_prefetches;
}
- virtual void RequestIDBCursorAdvance(unsigned long count,
- WebIDBCallbacks* callbacks,
- int32 ipc_cursor_id,
- int64 transaction_id) OVERRIDE {
+ void RequestIDBCursorAdvance(unsigned long count,
+ WebIDBCallbacks* callbacks,
+ int32 ipc_cursor_id,
+ int64 transaction_id) override {
++advance_calls_;
callbacks_.reset(callbacks);
}
- virtual void RequestIDBCursorContinue(const IndexedDBKey& key,
- const IndexedDBKey& primary_key,
- WebIDBCallbacks* callbacks,
- int32 ipc_cursor_id,
- int64 transaction_id) OVERRIDE {
+ void RequestIDBCursorContinue(const IndexedDBKey& key,
+ const IndexedDBKey& primary_key,
+ WebIDBCallbacks* callbacks,
+ int32 ipc_cursor_id,
+ int64 transaction_id) override {
++continue_calls_;
callbacks_.reset(callbacks);
}
- virtual void CursorDestroyed(int32 ipc_cursor_id) OVERRIDE {
+ void CursorDestroyed(int32 ipc_cursor_id) override {
destroyed_cursor_id_ = ipc_cursor_id;
}
@@ -102,7 +102,7 @@ class MockContinueCallbacks : public WebIDBCallbacks {
virtual void onSuccess(const WebIDBKey& key,
const WebIDBKey& primaryKey,
const WebData& value,
- const WebVector<WebBlobInfo>& webBlobInfo) OVERRIDE {
+ const WebVector<WebBlobInfo>& webBlobInfo) override {
if (key_)
*key_ = IndexedDBKeyBuilder::Build(key);
if (webBlobInfo_)
diff --git a/chromium/content/child/indexed_db/webidbdatabase_impl.cc b/chromium/content/child/indexed_db/webidbdatabase_impl.cc
index 757d19509c9..55d69c1e65a 100644
--- a/chromium/content/child/indexed_db/webidbdatabase_impl.cc
+++ b/chromium/content/child/indexed_db/webidbdatabase_impl.cc
@@ -78,7 +78,7 @@ void WebIDBDatabaseImpl::createTransaction(
long long transaction_id,
WebIDBDatabaseCallbacks* callbacks,
const WebVector<long long>& object_store_ids,
- WebIDBDatabase::TransactionMode mode) {
+ blink::WebIDBTransactionMode mode) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
dispatcher->RequestIDBDatabaseCreateTransaction(
@@ -92,6 +92,12 @@ void WebIDBDatabaseImpl::close() {
ipc_database_callbacks_id_);
}
+void WebIDBDatabaseImpl::versionChangeIgnored() {
+ IndexedDBDispatcher* dispatcher =
+ IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
+ dispatcher->NotifyIDBDatabaseVersionChangeIgnored(ipc_database_id_);
+}
+
void WebIDBDatabaseImpl::get(long long transaction_id,
long long object_store_id,
long long index_id,
@@ -114,7 +120,7 @@ void WebIDBDatabaseImpl::put(long long transaction_id,
const blink::WebData& value,
const blink::WebVector<WebBlobInfo>& web_blob_info,
const WebIDBKey& key,
- PutMode put_mode,
+ blink::WebIDBPutMode put_mode,
WebIDBCallbacks* callbacks,
const WebVector<long long>& web_index_ids,
const WebVector<WebIndexKeys>& web_index_keys) {
@@ -172,9 +178,9 @@ void WebIDBDatabaseImpl::openCursor(long long transaction_id,
long long object_store_id,
long long index_id,
const WebIDBKeyRange& key_range,
- WebIDBCursor::Direction direction,
+ blink::WebIDBCursorDirection direction,
bool key_only,
- TaskType task_type,
+ blink::WebIDBTaskType task_type,
WebIDBCallbacks* callbacks) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
diff --git a/chromium/content/child/indexed_db/webidbdatabase_impl.h b/chromium/content/child/indexed_db/webidbdatabase_impl.h
index c488af6fe46..61f20018636 100644
--- a/chromium/content/child/indexed_db/webidbdatabase_impl.h
+++ b/chromium/content/child/indexed_db/webidbdatabase_impl.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "third_party/WebKit/public/platform/WebIDBCursor.h"
#include "third_party/WebKit/public/platform/WebIDBDatabase.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
namespace blink {
class WebBlobInfo;
@@ -38,8 +39,11 @@ class WebIDBDatabaseImpl : public blink::WebIDBDatabase {
virtual void createTransaction(long long transaction_id,
blink::WebIDBDatabaseCallbacks* callbacks,
const blink::WebVector<long long>& scope,
- blink::WebIDBDatabase::TransactionMode mode);
+ blink::WebIDBTransactionMode mode);
+
virtual void close();
+ virtual void versionChangeIgnored();
+
virtual void get(long long transactionId,
long long objectStoreId,
long long indexId,
@@ -51,7 +55,7 @@ class WebIDBDatabaseImpl : public blink::WebIDBDatabase {
const blink::WebData& value,
const blink::WebVector<blink::WebBlobInfo>& webBlobInfo,
const blink::WebIDBKey&,
- PutMode,
+ blink::WebIDBPutMode,
blink::WebIDBCallbacks*,
const blink::WebVector<long long>& indexIds,
const blink::WebVector<WebIndexKeys>&);
@@ -67,9 +71,9 @@ class WebIDBDatabaseImpl : public blink::WebIDBDatabase {
long long objectStoreId,
long long indexId,
const blink::WebIDBKeyRange&,
- blink::WebIDBCursor::Direction direction,
+ blink::WebIDBCursorDirection direction,
bool keyOnly,
- TaskType,
+ blink::WebIDBTaskType,
blink::WebIDBCallbacks*);
virtual void count(long long transactionId,
long long objectStoreId,
diff --git a/chromium/content/child/mojo/mojo_application.cc b/chromium/content/child/mojo/mojo_application.cc
index 79eea23846c..bc1426ff3e1 100644
--- a/chromium/content/child/mojo/mojo_application.cc
+++ b/chromium/content/child/mojo/mojo_application.cc
@@ -10,8 +10,7 @@
namespace content {
-MojoApplication::MojoApplication(mojo::ServiceProvider* service_provider)
- : service_provider_(service_provider) {
+MojoApplication::MojoApplication() {
}
MojoApplication::~MojoApplication() {
@@ -37,9 +36,7 @@ void MojoApplication::OnActivate(
channel_init_.Init(handle,
ChildProcess::current()->io_message_loop_proxy());
DCHECK(message_pipe.is_valid());
-
- host_service_provider_.Bind(message_pipe.Pass());
- host_service_provider_.set_client(service_provider_);
+ service_registry_.BindRemoteServiceProvider(message_pipe.Pass());
}
} // namespace content
diff --git a/chromium/content/child/mojo/mojo_application.h b/chromium/content/child/mojo/mojo_application.h
index 53fd54171e2..8aee2e869c7 100644
--- a/chromium/content/child/mojo/mojo_application.h
+++ b/chromium/content/child/mojo/mojo_application.h
@@ -5,9 +5,9 @@
#ifndef CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
#define CONTENT_CHILD_MOJO_MOJO_APPLICATION_H_
+#include "content/common/mojo/service_registry_impl.h"
#include "ipc/ipc_platform_file.h"
-#include "mojo/embedder/channel_init.h"
-#include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
+#include "mojo/edk/embedder/channel_init.h"
namespace IPC {
class Message;
@@ -18,27 +18,22 @@ namespace content {
// MojoApplication represents the code needed to setup a child process as a
// Mojo application via Chrome IPC. Instantiate MojoApplication and call its
// OnMessageReceived method to give it a shot at handling Chrome IPC messages.
-// It makes the mojo::Shell interface available and calls methods on the given
-// mojo::ShellClient interface as calls come in.
+// It makes the ServiceRegistry interface available.
class MojoApplication {
public:
- // The ShellClient pointer must remain valid for the lifetime of the
- // MojoApplication instance.
- explicit MojoApplication(mojo::ServiceProvider* service_provider);
- ~MojoApplication();
+ MojoApplication();
+ virtual ~MojoApplication();
bool OnMessageReceived(const IPC::Message& msg);
- mojo::ServiceProvider* host_service_provider() {
- return host_service_provider_.get();
- }
+ ServiceRegistry* service_registry() { return &service_registry_; }
private:
void OnActivate(const IPC::PlatformFileForTransit& file);
mojo::embedder::ChannelInit channel_init_;
- mojo::ServiceProviderPtr host_service_provider_;
- mojo::ServiceProvider* service_provider_;
+
+ ServiceRegistryImpl service_registry_;
DISALLOW_COPY_AND_ASSIGN(MojoApplication);
};
diff --git a/chromium/content/child/multipart_response_delegate.cc b/chromium/content/child/multipart_response_delegate.cc
new file mode 100644
index 00000000000..21d2d51e02a
--- /dev/null
+++ b/chromium/content/child/multipart_response_delegate.cc
@@ -0,0 +1,404 @@
+// Copyright 2014 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 "content/child/multipart_response_delegate.h"
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "net/base/net_util.h"
+#include "net/http/http_util.h"
+#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+
+using blink::WebHTTPHeaderVisitor;
+using blink::WebString;
+using blink::WebURLLoader;
+using blink::WebURLLoaderClient;
+using blink::WebURLResponse;
+
+namespace content {
+
+namespace {
+
+// The list of response headers that we do not copy from the original
+// response when generating a WebURLResponse for a MIME payload.
+const char* kReplaceHeaders[] = {
+ "content-type",
+ "content-length",
+ "content-disposition",
+ "content-range",
+ "range",
+ "set-cookie"
+};
+
+class HeaderCopier : public WebHTTPHeaderVisitor {
+ public:
+ HeaderCopier(WebURLResponse* response)
+ : response_(response) {
+ }
+ virtual void visitHeader(const WebString& name, const WebString& value) {
+ const std::string& name_utf8 = name.utf8();
+ for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
+ if (LowerCaseEqualsASCII(name_utf8, kReplaceHeaders[i]))
+ return;
+ }
+ response_->setHTTPHeaderField(name, value);
+ }
+ private:
+ WebURLResponse* response_;
+};
+
+} // namespace
+
+MultipartResponseDelegate::MultipartResponseDelegate(
+ WebURLLoaderClient* client,
+ WebURLLoader* loader,
+ const WebURLResponse& response,
+ const std::string& boundary)
+ : client_(client),
+ loader_(loader),
+ original_response_(response),
+ encoded_data_length_(0),
+ boundary_("--"),
+ first_received_data_(true),
+ processing_headers_(false),
+ stop_sending_(false),
+ has_sent_first_response_(false) {
+ // Some servers report a boundary prefixed with "--". See bug 5786.
+ if (StartsWithASCII(boundary, "--", true)) {
+ boundary_.assign(boundary);
+ } else {
+ boundary_.append(boundary);
+ }
+}
+
+void MultipartResponseDelegate::OnReceivedData(const char* data,
+ int data_len,
+ int encoded_data_length) {
+ // stop_sending_ means that we've already received the final boundary token.
+ // The server should stop sending us data at this point, but if it does, we
+ // just throw it away.
+ if (stop_sending_)
+ return;
+
+ data_.append(data, data_len);
+ encoded_data_length_ += encoded_data_length;
+ if (first_received_data_) {
+ // Some servers don't send a boundary token before the first chunk of
+ // data. We handle this case anyway (Gecko does too).
+ first_received_data_ = false;
+
+ // Eat leading \r\n
+ int pos = PushOverLine(data_, 0);
+ if (pos)
+ data_ = data_.substr(pos);
+
+ if (data_.length() < boundary_.length() + 2) {
+ // We don't have enough data yet to make a boundary token. Just wait
+ // until the next chunk of data arrives.
+ first_received_data_ = true;
+ return;
+ }
+
+ if (0 != data_.compare(0, boundary_.length(), boundary_)) {
+ data_ = boundary_ + "\n" + data_;
+ }
+ }
+ DCHECK(!first_received_data_);
+
+ // Headers
+ if (processing_headers_) {
+ // Eat leading \r\n
+ int pos = PushOverLine(data_, 0);
+ if (pos)
+ data_ = data_.substr(pos);
+
+ if (ParseHeaders()) {
+ // Successfully parsed headers.
+ processing_headers_ = false;
+ } else {
+ // Get more data before trying again.
+ return;
+ }
+ }
+ DCHECK(!processing_headers_);
+
+ size_t boundary_pos;
+ while ((boundary_pos = FindBoundary()) != std::string::npos) {
+ if (client_) {
+ // Strip out trailing \n\r characters in the buffer preceding the
+ // boundary on the same lines as Firefox.
+ size_t data_length = boundary_pos;
+ if (boundary_pos > 0 && data_[boundary_pos - 1] == '\n') {
+ data_length--;
+ if (boundary_pos > 1 && data_[boundary_pos - 2] == '\r') {
+ data_length--;
+ }
+ }
+ if (data_length > 0) {
+ // Send the last data chunk.
+ client_->didReceiveData(loader_,
+ data_.data(),
+ static_cast<int>(data_length),
+ encoded_data_length_);
+ encoded_data_length_ = 0;
+ }
+ }
+ size_t boundary_end_pos = boundary_pos + boundary_.length();
+ if (boundary_end_pos < data_.length() && '-' == data_[boundary_end_pos]) {
+ // This was the last boundary so we can stop processing.
+ stop_sending_ = true;
+ data_.clear();
+ return;
+ }
+
+ // We can now throw out data up through the boundary
+ int offset = PushOverLine(data_, boundary_end_pos);
+ data_ = data_.substr(boundary_end_pos + offset);
+
+ // Ok, back to parsing headers
+ if (!ParseHeaders()) {
+ processing_headers_ = true;
+ break;
+ }
+ }
+
+ // At this point, we should send over any data we have, but keep enough data
+ // buffered to handle a boundary that may have been truncated.
+ if (!processing_headers_ && data_.length() > boundary_.length()) {
+ // If the last character is a new line character, go ahead and just send
+ // everything we have buffered. This matches an optimization in Gecko.
+ int send_length = data_.length() - boundary_.length();
+ if (data_[data_.length() - 1] == '\n')
+ send_length = data_.length();
+ if (client_)
+ client_->didReceiveData(loader_,
+ data_.data(),
+ send_length,
+ encoded_data_length_);
+ data_ = data_.substr(send_length);
+ encoded_data_length_ = 0;
+ }
+}
+
+void MultipartResponseDelegate::OnCompletedRequest() {
+ // If we have any pending data and we're not in a header, go ahead and send
+ // it to WebCore.
+ if (!processing_headers_ && !data_.empty() && !stop_sending_ && client_) {
+ client_->didReceiveData(loader_,
+ data_.data(),
+ static_cast<int>(data_.length()),
+ encoded_data_length_);
+ encoded_data_length_ = 0;
+ }
+}
+
+int MultipartResponseDelegate::PushOverLine(const std::string& data,
+ size_t pos) {
+ int offset = 0;
+ if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) {
+ ++offset;
+ if (pos + 1 < data.length() && data[pos + 1] == '\n')
+ ++offset;
+ }
+ return offset;
+}
+
+bool MultipartResponseDelegate::ParseHeaders() {
+ int line_feed_increment = 1;
+
+ // Grab the headers being liberal about line endings.
+ size_t line_start_pos = 0;
+ size_t line_end_pos = data_.find('\n');
+ while (line_end_pos != std::string::npos) {
+ // Handle CRLF
+ if (line_end_pos > line_start_pos && data_[line_end_pos - 1] == '\r') {
+ line_feed_increment = 2;
+ --line_end_pos;
+ } else {
+ line_feed_increment = 1;
+ }
+ if (line_start_pos == line_end_pos) {
+ // A blank line, end of headers
+ line_end_pos += line_feed_increment;
+ break;
+ }
+ // Find the next header line.
+ line_start_pos = line_end_pos + line_feed_increment;
+ line_end_pos = data_.find('\n', line_start_pos);
+ }
+ // Truncated in the middle of a header, stop parsing.
+ if (line_end_pos == std::string::npos)
+ return false;
+
+ // Eat headers
+ std::string headers("\n");
+ headers.append(data_, 0, line_end_pos);
+ data_ = data_.substr(line_end_pos);
+
+ // Create a WebURLResponse based on the original set of headers + the
+ // replacement headers. We only replace the same few headers that gecko
+ // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp.
+ std::string content_type = net::GetSpecificHeader(headers, "content-type");
+ std::string mime_type;
+ std::string charset;
+ bool has_charset = false;
+ net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
+ &has_charset, NULL);
+ WebURLResponse response(original_response_.url());
+ response.setMIMEType(WebString::fromUTF8(mime_type));
+ response.setTextEncodingName(WebString::fromUTF8(charset));
+
+ HeaderCopier copier(&response);
+ original_response_.visitHTTPHeaderFields(&copier);
+
+ for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
+ std::string name(kReplaceHeaders[i]);
+ std::string value = net::GetSpecificHeader(headers, name);
+ if (!value.empty()) {
+ response.setHTTPHeaderField(WebString::fromUTF8(name),
+ WebString::fromUTF8(value));
+ }
+ }
+ // To avoid recording every multipart load as a separate visit in
+ // the history database, we want to keep track of whether the response
+ // is part of a multipart payload. We do want to record the first visit,
+ // so we only set isMultipartPayload to true after the first visit.
+ response.setIsMultipartPayload(has_sent_first_response_);
+ has_sent_first_response_ = true;
+ // Send the response!
+ if (client_)
+ client_->didReceiveResponse(loader_, response);
+
+ return true;
+}
+
+// Boundaries are supposed to be preceeded with --, but it looks like gecko
+// doesn't require the dashes to exist. See nsMultiMixedConv::FindToken.
+size_t MultipartResponseDelegate::FindBoundary() {
+ size_t boundary_pos = data_.find(boundary_);
+ if (boundary_pos != std::string::npos) {
+ // Back up over -- for backwards compat
+ // TODO(tc): Don't we only want to do this once? Gecko code doesn't seem
+ // to care.
+ if (boundary_pos >= 2) {
+ if ('-' == data_[boundary_pos - 1] && '-' == data_[boundary_pos - 2]) {
+ boundary_pos -= 2;
+ boundary_ = "--" + boundary_;
+ }
+ }
+ }
+ return boundary_pos;
+}
+
+bool MultipartResponseDelegate::ReadMultipartBoundary(
+ const WebURLResponse& response,
+ std::string* multipart_boundary) {
+ std::string content_type =
+ response.httpHeaderField(WebString::fromUTF8("Content-Type")).utf8();
+
+ size_t boundary_start_offset = content_type.find("boundary=");
+ if (boundary_start_offset == std::string::npos)
+ return false;
+
+ boundary_start_offset += strlen("boundary=");
+
+ size_t boundary_end_offset = content_type.find(';', boundary_start_offset);
+
+ if (boundary_end_offset == std::string::npos)
+ boundary_end_offset = content_type.length();
+
+ size_t boundary_length = boundary_end_offset - boundary_start_offset;
+
+ *multipart_boundary =
+ content_type.substr(boundary_start_offset, boundary_length);
+ // The byte range response can have quoted boundary strings. This is legal
+ // as per MIME specifications. Individual data fragements however don't
+ // contain quoted boundary strings.
+ base::TrimString(*multipart_boundary, "\"", multipart_boundary);
+ return true;
+}
+
+bool MultipartResponseDelegate::ReadContentRanges(
+ const WebURLResponse& response,
+ int64* content_range_lower_bound,
+ int64* content_range_upper_bound,
+ int64* content_range_instance_size) {
+
+ std::string content_range = response.httpHeaderField("Content-Range").utf8();
+ if (content_range.empty()) {
+ content_range = response.httpHeaderField("Range").utf8();
+ }
+
+ if (content_range.empty()) {
+ DLOG(WARNING) << "Failed to read content range from response.";
+ return false;
+ }
+
+ size_t byte_range_lower_bound_start_offset = content_range.find(" ");
+ if (byte_range_lower_bound_start_offset == std::string::npos) {
+ return false;
+ }
+
+ // Skip over the initial space.
+ byte_range_lower_bound_start_offset++;
+
+ // Find the lower bound.
+ size_t byte_range_lower_bound_end_offset =
+ content_range.find("-", byte_range_lower_bound_start_offset);
+ if (byte_range_lower_bound_end_offset == std::string::npos) {
+ return false;
+ }
+
+ size_t byte_range_lower_bound_characters =
+ byte_range_lower_bound_end_offset - byte_range_lower_bound_start_offset;
+ std::string byte_range_lower_bound =
+ content_range.substr(byte_range_lower_bound_start_offset,
+ byte_range_lower_bound_characters);
+
+ // Find the upper bound.
+ size_t byte_range_upper_bound_start_offset =
+ byte_range_lower_bound_end_offset + 1;
+
+ size_t byte_range_upper_bound_end_offset =
+ content_range.find("/", byte_range_upper_bound_start_offset);
+ if (byte_range_upper_bound_end_offset == std::string::npos) {
+ return false;
+ }
+
+ size_t byte_range_upper_bound_characters =
+ byte_range_upper_bound_end_offset - byte_range_upper_bound_start_offset;
+ std::string byte_range_upper_bound =
+ content_range.substr(byte_range_upper_bound_start_offset,
+ byte_range_upper_bound_characters);
+
+ // Find the instance size.
+ size_t byte_range_instance_size_start_offset =
+ byte_range_upper_bound_end_offset + 1;
+
+ size_t byte_range_instance_size_end_offset =
+ content_range.length();
+
+ size_t byte_range_instance_size_characters =
+ byte_range_instance_size_end_offset -
+ byte_range_instance_size_start_offset;
+ std::string byte_range_instance_size =
+ content_range.substr(byte_range_instance_size_start_offset,
+ byte_range_instance_size_characters);
+
+ if (!base::StringToInt64(byte_range_lower_bound, content_range_lower_bound))
+ return false;
+ if (!base::StringToInt64(byte_range_upper_bound, content_range_upper_bound))
+ return false;
+ if (!base::StringToInt64(byte_range_instance_size,
+ content_range_instance_size)) {
+ return false;
+ }
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/child/multipart_response_delegate.h b/chromium/content/child/multipart_response_delegate.h
new file mode 100644
index 00000000000..aac659eb756
--- /dev/null
+++ b/chromium/content/child/multipart_response_delegate.h
@@ -0,0 +1,150 @@
+// Copyright 2014 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.
+//
+// A delegate class of WebURLLoaderImpl that handles multipart/x-mixed-replace
+// data. We special case multipart/x-mixed-replace because WebCore expects a
+// separate didReceiveResponse for each new message part.
+//
+// Most of the logic and edge case handling are based on the Mozilla's
+// implementation in netwerk/streamconv/converters/nsMultiMixedConv.cpp.
+// This seems like a derivative work, so here's the original license:
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef CONTENT_CHILD_MULTIPART_RESPONSE_DELEGATE_H_
+#define CONTENT_CHILD_MULTIPART_RESPONSE_DELEGATE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+
+namespace blink {
+class WebURLLoader;
+class WebURLLoaderClient;
+}
+
+namespace content {
+
+class CONTENT_EXPORT MultipartResponseDelegate {
+ public:
+ MultipartResponseDelegate(blink::WebURLLoaderClient* client,
+ blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response,
+ const std::string& boundary);
+
+ // Passed through from ResourceHandleInternal
+ void OnReceivedData(const char* data, int data_len, int encoded_data_length);
+ void OnCompletedRequest();
+
+ // The request has been canceled, so stop making calls to the client.
+ void Cancel() {
+ client_ = NULL;
+ loader_ = NULL;
+ }
+
+ // Returns the multi part boundary string from the Content-type header
+ // in the response.
+ // Returns true on success.
+ static bool ReadMultipartBoundary(const blink::WebURLResponse& response,
+ std::string* multipart_boundary);
+
+ // Returns the lower and higher content ranges from an individual multipart
+ // in a multipart response.
+ // Returns true on success.
+ static bool ReadContentRanges(
+ const blink::WebURLResponse& response,
+ int64* content_range_lower_bound,
+ int64* content_range_upper_bound,
+ int64* content_range_instance_size);
+
+ private:
+ friend class MultipartResponseDelegateTester; // For unittests.
+
+ // Pointers to the client and associated loader so we can make callbacks as
+ // we parse pieces of data.
+ blink::WebURLLoaderClient* client_;
+ blink::WebURLLoader* loader_;
+
+ // The original resource response for this request. We use this as a
+ // starting point for each parts response.
+ blink::WebURLResponse original_response_;
+
+ // Checks to see if data[pos] character is a line break; handles crlf, lflf,
+ // lf, or cr. Returns the number of characters to skip over (0, 1 or 2).
+ int PushOverLine(const std::string& data, size_t pos);
+
+ // Tries to parse http headers from the start of data_. Returns true if it
+ // succeeds and sends a didReceiveResponse to m_client. Returns false if
+ // the header is incomplete (in which case we just wait for more data).
+ bool ParseHeaders();
+
+ // Find the next boundary in data_. Returns std::string::npos if there's no
+ // full token.
+ size_t FindBoundary();
+
+ // Transferred data size accumulated between client callbacks.
+ int encoded_data_length_;
+
+ // A temporary buffer to hold data between reads for multipart data that
+ // gets split in the middle of a header.
+ std::string data_;
+
+ // Multipart boundary token
+ std::string boundary_;
+
+ // true until we get our first on received data call
+ bool first_received_data_;
+
+ // true if we're truncated in the middle of a header
+ bool processing_headers_;
+
+ // true when we're done sending information. At that point, we stop
+ // processing AddData requests.
+ bool stop_sending_;
+
+ // true after we've sent our first response to the WebURLLoaderClient.
+ bool has_sent_first_response_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultipartResponseDelegate);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_MULTIPART_RESPONSE_DELEGATE_H_
diff --git a/chromium/content/child/multipart_response_delegate_unittest.cc b/chromium/content/child/multipart_response_delegate_unittest.cc
index e12133a3158..182a1f30fff 100644
--- a/chromium/content/child/multipart_response_delegate_unittest.cc
+++ b/chromium/content/child/multipart_response_delegate_unittest.cc
@@ -2,17 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/child/multipart_response_delegate.h"
+
#include <vector>
-#include "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "webkit/child/multipart_response_delegate.h"
-using std::string;
using blink::WebString;
using blink::WebURL;
using blink::WebURLError;
@@ -20,8 +19,7 @@ using blink::WebURLLoader;
using blink::WebURLLoaderClient;
using blink::WebURLRequest;
using blink::WebURLResponse;
-using content::MultipartResponseDelegateTester;
-using webkit_glue::MultipartResponseDelegate;
+using std::string;
namespace content {
@@ -124,7 +122,7 @@ TEST(MultipartResponseTest, Functions) {
{ "Line\rLine", 4, 1 },
{ "Line\r\rLine", 4, 1 },
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(line_tests); ++i) {
+ for (size_t i = 0; i < arraysize(line_tests); ++i) {
EXPECT_EQ(line_tests[i].expected,
delegate_tester.PushOverLine(line_tests[i].input,
line_tests[i].position));
@@ -146,7 +144,7 @@ TEST(MultipartResponseTest, Functions) {
{ "Foo: bar\r\nBaz:\n", false, 0, "Foo: bar\r\nBaz:\n" },
{ "\r\n", true, 1, "" },
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(header_tests); ++i) {
+ for (size_t i = 0; i < arraysize(header_tests); ++i) {
client.Reset();
delegate_tester.data().assign(header_tests[i].data);
EXPECT_EQ(header_tests[i].rv,
@@ -192,7 +190,7 @@ TEST(MultipartResponseTest, Functions) {
{ "foo", "bound", string::npos },
{ "bound", "--boundbound", 0 },
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(boundary_tests); ++i) {
+ for (size_t i = 0; i < arraysize(boundary_tests); ++i) {
delegate_tester.boundary().assign(boundary_tests[i].boundary);
delegate_tester.data().assign(boundary_tests[i].data);
EXPECT_EQ(boundary_tests[i].position,
diff --git a/chromium/content/child/notifications/OWNERS b/chromium/content/child/notifications/OWNERS
new file mode 100644
index 00000000000..2fca67fdfda
--- /dev/null
+++ b/chromium/content/child/notifications/OWNERS
@@ -0,0 +1 @@
+peter@chromium.org \ No newline at end of file
diff --git a/chromium/content/child/notifications/notification_dispatcher.cc b/chromium/content/child/notifications/notification_dispatcher.cc
new file mode 100644
index 00000000000..45f6df01719
--- /dev/null
+++ b/chromium/content/child/notifications/notification_dispatcher.cc
@@ -0,0 +1,70 @@
+// Copyright 2014 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 "content/child/notifications/notification_dispatcher.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "content/child/notifications/notification_manager.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_thread_task_runner.h"
+#include "content/common/platform_notification_messages.h"
+
+namespace content {
+
+NotificationDispatcher::NotificationDispatcher(
+ ThreadSafeSender* thread_safe_sender)
+ : main_thread_loop_proxy_(base::MessageLoopProxy::current()),
+ thread_safe_sender_(thread_safe_sender) {
+}
+
+NotificationDispatcher::~NotificationDispatcher() {}
+
+int NotificationDispatcher::GenerateNotificationId(int thread_id) {
+ base::AutoLock lock(notification_id_map_lock_);
+ notification_id_map_[next_notification_id_] = thread_id;
+ return next_notification_id_++;
+}
+
+base::TaskRunner* NotificationDispatcher::OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) {
+ if (!ShouldHandleMessage(msg))
+ return NULL;
+
+ int notification_id = -1,
+ thread_id = 0;
+
+ const bool success = PickleIterator(msg).ReadInt(&notification_id);
+ DCHECK(success);
+
+ {
+ base::AutoLock lock(notification_id_map_lock_);
+ auto iterator = notification_id_map_.find(notification_id);
+ if (iterator != notification_id_map_.end())
+ thread_id = iterator->second;
+ }
+
+ if (!thread_id)
+ return main_thread_loop_proxy_.get();
+
+ return new WorkerThreadTaskRunner(thread_id);
+}
+
+bool NotificationDispatcher::OnMessageReceived(const IPC::Message& msg) {
+ if (!ShouldHandleMessage(msg))
+ return false;
+
+ NotificationManager::ThreadSpecificInstance(thread_safe_sender_.get(), this)
+ ->OnMessageReceived(msg);
+ return true;
+}
+
+bool NotificationDispatcher::ShouldHandleMessage(const IPC::Message& msg) {
+ // The thread-safe message filter is responsible for handling all the messages
+ // except for the routed permission-request-completed message, which will be
+ // picked up by the RenderFrameImpl instead.
+ return IPC_MESSAGE_CLASS(msg) == PlatformNotificationMsgStart &&
+ msg.type() != PlatformNotificationMsg_PermissionRequestComplete::ID;
+}
+
+} // namespace content
diff --git a/chromium/content/child/notifications/notification_dispatcher.h b/chromium/content/child/notifications/notification_dispatcher.h
new file mode 100644
index 00000000000..be4ada94f24
--- /dev/null
+++ b/chromium/content/child/notifications/notification_dispatcher.h
@@ -0,0 +1,55 @@
+// Copyright 2014 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 CONTENT_CHILD_NOTIFICATIONS_NOTIFICATION_DISPATCHER_H_
+#define CONTENT_CHILD_NOTIFICATIONS_NOTIFICATION_DISPATCHER_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "content/child/child_message_filter.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace content {
+
+class ThreadSafeSender;
+
+class NotificationDispatcher : public ChildMessageFilter {
+ public:
+ explicit NotificationDispatcher(ThreadSafeSender* thread_safe_sender);
+
+ // Generates a, process-unique new notification Id mapped to |thread_id|, and
+ // return the notification Id. This method can be called on any thread.
+ int GenerateNotificationId(int thread_id);
+
+ protected:
+ ~NotificationDispatcher() override;
+
+ private:
+ bool ShouldHandleMessage(const IPC::Message& msg);
+
+ // ChildMessageFilter implementation.
+ base::TaskRunner* OverrideTaskRunnerForMessage(const IPC::Message& msg)
+ override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
+ scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+
+ using NotificationIdToThreadId = std::map<int, int>;
+
+ base::Lock notification_id_map_lock_;
+ NotificationIdToThreadId notification_id_map_;
+ int next_notification_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_NOTIFICATIONS_NOTIFICATION_DISPATCHER_H_
diff --git a/chromium/content/child/notifications/notification_manager.cc b/chromium/content/child/notifications/notification_manager.cc
new file mode 100644
index 00000000000..4ffc890718f
--- /dev/null
+++ b/chromium/content/child/notifications/notification_manager.cc
@@ -0,0 +1,167 @@
+// Copyright 2014 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 "content/child/notifications/notification_manager.h"
+
+#include "base/lazy_instance.h"
+#include "base/threading/thread_local.h"
+#include "content/child/notifications/notification_dispatcher.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/child/worker_task_runner.h"
+#include "content/common/platform_notification_messages.h"
+#include "content/public/common/show_desktop_notification_params.h"
+#include "third_party/WebKit/public/platform/WebNotificationData.h"
+#include "third_party/WebKit/public/platform/WebNotificationDelegate.h"
+#include "third_party/WebKit/public/platform/WebSerializedOrigin.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+using blink::WebNotificationPermission;
+
+namespace content {
+namespace {
+
+int CurrentWorkerId() {
+ return WorkerTaskRunner::Instance()->CurrentWorkerId();
+}
+
+} // namespace
+
+static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
+ g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;
+
+NotificationManager::NotificationManager(
+ ThreadSafeSender* thread_safe_sender,
+ NotificationDispatcher* notification_dispatcher)
+ : thread_safe_sender_(thread_safe_sender),
+ notification_dispatcher_(notification_dispatcher) {
+ g_notification_manager_tls.Pointer()->Set(this);
+}
+
+NotificationManager::~NotificationManager() {
+ g_notification_manager_tls.Pointer()->Set(nullptr);
+}
+
+NotificationManager* NotificationManager::ThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender,
+ NotificationDispatcher* notification_dispatcher) {
+ if (g_notification_manager_tls.Pointer()->Get())
+ return g_notification_manager_tls.Pointer()->Get();
+
+ NotificationManager* manager = new NotificationManager(
+ thread_safe_sender, notification_dispatcher);
+ if (WorkerTaskRunner::Instance()->CurrentWorkerId())
+ WorkerTaskRunner::Instance()->AddStopObserver(manager);
+ return manager;
+}
+
+void NotificationManager::OnWorkerRunLoopStopped() {
+ delete this;
+}
+
+void NotificationManager::show(
+ const blink::WebSerializedOrigin& origin,
+ const blink::WebNotificationData& notification_data,
+ blink::WebNotificationDelegate* delegate) {
+ int notification_id =
+ notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
+
+ active_notifications_[notification_id] = delegate;
+
+ ShowDesktopNotificationHostMsgParams params;
+ params.origin = GURL(origin.string());
+
+ // TODO(peter): Move the notification_icon_loader to //content/child/ and use
+ // it to download Notification icons here.
+ params.icon = SkBitmap();
+ params.title = notification_data.title;
+ params.body = notification_data.body;
+
+ // TODO(peter): Remove the usage of the Blink WebTextDirection enumeration for
+ // the text direction of notifications throughout Chrome.
+ params.direction = blink::WebTextDirectionLeftToRight;
+ params.replace_id = notification_data.tag;
+
+ thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
+ notification_id, params));
+}
+
+void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
+ auto iter = active_notifications_.begin();
+ for (; iter != active_notifications_.end(); ++iter) {
+ if (iter->second != delegate)
+ continue;
+
+ thread_safe_sender_->Send(
+ new PlatformNotificationHostMsg_Close(iter->first));
+ active_notifications_.erase(iter);
+
+ delegate->dispatchCloseEvent();
+ return;
+ }
+
+ // It should not be possible for Blink to call close() on a Notification which
+ // does not exist anymore in the manager.
+ NOTREACHED();
+}
+
+void NotificationManager::notifyDelegateDestroyed(
+ blink::WebNotificationDelegate* delegate) {
+ auto iter = active_notifications_.begin();
+ for (; iter != active_notifications_.end(); ++iter) {
+ if (iter->second != delegate)
+ continue;
+
+ active_notifications_.erase(iter);
+ return;
+ }
+}
+
+WebNotificationPermission NotificationManager::checkPermission(
+ const blink::WebSerializedOrigin& origin) {
+ WebNotificationPermission permission =
+ blink::WebNotificationPermissionAllowed;
+ thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
+ GURL(origin.string()), &permission));
+
+ return permission;
+}
+
+bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
+ IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShow, OnShow);
+ IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClose, OnClose);
+ IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClick, OnClick);
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void NotificationManager::OnShow(int id) {
+ const auto& iter = active_notifications_.find(id);
+ if (iter == active_notifications_.end())
+ return;
+
+ iter->second->dispatchShowEvent();
+}
+
+void NotificationManager::OnClose(int id) {
+ const auto& iter = active_notifications_.find(id);
+ if (iter == active_notifications_.end())
+ return;
+
+ iter->second->dispatchCloseEvent();
+ active_notifications_.erase(iter);
+}
+
+void NotificationManager::OnClick(int id) {
+ const auto& iter = active_notifications_.find(id);
+ if (iter == active_notifications_.end())
+ return;
+
+ iter->second->dispatchClickEvent();
+}
+
+} // namespace content
diff --git a/chromium/content/child/notifications/notification_manager.h b/chromium/content/child/notifications/notification_manager.h
new file mode 100644
index 00000000000..53013487d82
--- /dev/null
+++ b/chromium/content/child/notifications/notification_manager.h
@@ -0,0 +1,69 @@
+// Copyright 2014 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 CONTENT_CHILD_NOTIFICATIONS_NOTIFICATION_MANAGER_H_
+#define CONTENT_CHILD_NOTIFICATIONS_NOTIFICATION_MANAGER_H_
+
+#include <map>
+
+#include "base/memory/ref_counted.h"
+#include "content/child/notifications/notification_dispatcher.h"
+#include "content/child/worker_task_runner.h"
+#include "third_party/WebKit/public/platform/WebNotificationManager.h"
+
+class SkBitmap;
+
+namespace content {
+
+class ThreadSafeSender;
+
+class NotificationManager : public blink::WebNotificationManager,
+ public WorkerTaskRunner::Observer {
+ public:
+ ~NotificationManager() override;
+
+ // |thread_safe_sender| and |notification_dispatcher| are used if
+ // calling this leads to construction.
+ static NotificationManager* ThreadSpecificInstance(
+ ThreadSafeSender* thread_safe_sender,
+ NotificationDispatcher* notification_dispatcher);
+
+ // WorkerTaskRunner::Observer implementation.
+ void OnWorkerRunLoopStopped() override;
+
+ // blink::WebNotificationManager implementation.
+ virtual void show(const blink::WebSerializedOrigin& origin,
+ const blink::WebNotificationData& notification_data,
+ blink::WebNotificationDelegate* delegate);
+ virtual void close(blink::WebNotificationDelegate* delegate);
+ virtual void notifyDelegateDestroyed(
+ blink::WebNotificationDelegate* delegate);
+ virtual blink::WebNotificationPermission checkPermission(
+ const blink::WebSerializedOrigin& origin);
+
+ // Called by the NotificationDispatcher.
+ bool OnMessageReceived(const IPC::Message& message);
+
+ private:
+ NotificationManager(
+ ThreadSafeSender* thread_safe_sender,
+ NotificationDispatcher* notification_dispatcher);
+
+ // IPC message handlers.
+ void OnShow(int id);
+ void OnClose(int id);
+ void OnClick(int id);
+
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+ scoped_refptr<NotificationDispatcher> notification_dispatcher_;
+
+ // Map to store the delegate associated with a notification request Id.
+ std::map<int, blink::WebNotificationDelegate*> active_notifications_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_NOTIFICATIONS_NOTIFICATION_MANAGER_H_
diff --git a/chromium/content/child/npapi/np_channel_base.cc b/chromium/content/child/npapi/np_channel_base.cc
index e7f2ca26bd2..c39ff4cdc2a 100644
--- a/chromium/content/child/npapi/np_channel_base.cc
+++ b/chromium/content/child/npapi/np_channel_base.cc
@@ -13,7 +13,7 @@
#include "ipc/ipc_sync_message.h"
#if defined(OS_POSIX)
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "ipc/ipc_channel_posix.h"
#endif
diff --git a/chromium/content/child/npapi/np_channel_base.h b/chromium/content/child/npapi/np_channel_base.h
index 0f6e11fe366..d718936425f 100644
--- a/chromium/content/child/npapi/np_channel_base.h
+++ b/chromium/content/child/npapi/np_channel_base.h
@@ -21,35 +21,6 @@ namespace base {
class MessageLoopProxy;
}
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
-
-template<>
-struct hash<NPObject*> {
- std::size_t operator()(NPObject* const& ptr) const {
- return hash<size_t>()(reinterpret_cast<size_t>(ptr));
- }
-};
-
-template<>
-struct hash<struct _NPP*> {
- std::size_t operator()(struct _NPP* const& ptr) const {
- return hash<size_t>()(reinterpret_cast<size_t>(ptr));
- }
-};
-
-} // namespace __gnu_cxx
-#elif defined(COMPILER_MSVC)
-namespace stdext {
-
-template<>
-inline size_t hash_value(NPObject* const& ptr) {
- return hash_value(reinterpret_cast<size_t>(ptr));
-}
-
-} // namespace stdext
-#endif // COMPILER
-
namespace content {
// Encapsulates an IPC channel between a renderer and another process. Used to
@@ -84,7 +55,7 @@ class NPChannelBase : public IPC::Listener,
int GetExistingRouteForNPObjectOwner(struct _NPP* owner);
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
base::ProcessId peer_pid() { return channel_->GetPeerPID(); }
IPC::ChannelHandle channel_handle() const { return channel_handle_; }
@@ -121,7 +92,7 @@ class NPChannelBase : public IPC::Listener,
friend class base::RefCountedThreadSafe<NPChannelBase>;
- virtual ~NPChannelBase();
+ ~NPChannelBase() override;
// Returns a NPChannelBase derived object for the given channel name.
// If an existing channel exists returns that object, otherwise creates a
@@ -145,9 +116,9 @@ class NPChannelBase : public IPC::Listener,
virtual bool OnControlMessageReceived(const IPC::Message& msg);
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
void set_send_unblocking_only_during_unblock_dispatch() {
send_unblocking_only_during_unblock_dispatch_ = true;
diff --git a/chromium/content/child/npapi/npobject_proxy.h b/chromium/content/child/npapi/npobject_proxy.h
index 7462531faa1..cdc5ee2f544 100644
--- a/chromium/content/child/npapi/npobject_proxy.h
+++ b/chromium/content/child/npapi/npobject_proxy.h
@@ -33,7 +33,7 @@ class NPObjectProxy : public IPC::Listener,
public IPC::Sender,
public NPObjectBase {
public:
- virtual ~NPObjectProxy();
+ ~NPObjectProxy() override;
static NPObject* Create(NPChannelBase* channel,
int route_id,
@@ -42,7 +42,7 @@ class NPObjectProxy : public IPC::Listener,
NPP owner);
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
int route_id() { return route_id_; }
NPChannelBase* channel() { return channel_.get(); }
@@ -94,9 +94,9 @@ class NPObjectProxy : public IPC::Listener,
static const NPClass* npclass() { return &npclass_proxy_; }
// NPObjectBase implementation.
- virtual NPObject* GetUnderlyingNPObject() OVERRIDE;
+ NPObject* GetUnderlyingNPObject() override;
- virtual IPC::Listener* GetChannelListener() OVERRIDE;
+ IPC::Listener* GetChannelListener() override;
private:
NPObjectProxy(NPChannelBase* channel,
@@ -105,8 +105,8 @@ class NPObjectProxy : public IPC::Listener,
const GURL& page_url);
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelError() override;
static NPObject* NPAllocate(NPP, NPClass*);
static void NPDeallocate(NPObject* npObj);
diff --git a/chromium/content/child/npapi/npobject_stub.cc b/chromium/content/child/npapi/npobject_stub.cc
index 9746623767d..fb910d9b412 100644
--- a/chromium/content/child/npapi/npobject_stub.cc
+++ b/chromium/content/child/npapi/npobject_stub.cc
@@ -257,9 +257,9 @@ void NPObjectStub::OnSetProperty(const NPIdentifier_Param& name,
if (npobject_->_class->setProperty) {
#if defined(OS_WIN)
static base::FilePath plugin_path =
- CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kPluginPath);
- static std::wstring filename = StringToLowerASCII(
+ static std::wstring filename = base::StringToLowerASCII(
plugin_path.BaseName().value());
static NPIdentifier fullscreen =
WebBindings::getStringIdentifier("fullScreen");
diff --git a/chromium/content/child/npapi/npobject_stub.h b/chromium/content/child/npapi/npobject_stub.h
index d73c27d11f6..81cec4287fa 100644
--- a/chromium/content/child/npapi/npobject_stub.h
+++ b/chromium/content/child/npapi/npobject_stub.h
@@ -37,7 +37,7 @@ class NPObjectStub : public IPC::Listener,
int route_id,
int render_view_id,
const GURL& page_url);
- virtual ~NPObjectStub();
+ ~NPObjectStub() override;
// Schedules tear-down of this stub. The underlying NPObject reference is
// released, and further invokations from the IPC channel will fail once this
@@ -47,16 +47,16 @@ class NPObjectStub : public IPC::Listener,
void DeleteSoon();
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// NPObjectBase implementation.
- virtual NPObject* GetUnderlyingNPObject() OVERRIDE;
- virtual IPC::Listener* GetChannelListener() OVERRIDE;
+ NPObject* GetUnderlyingNPObject() override;
+ IPC::Listener* GetChannelListener() override;
private:
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelError() override;
// message handlers
void OnRelease(IPC::Message* reply_msg);
diff --git a/chromium/content/child/npapi/plugin_host.cc b/chromium/content/child/npapi/plugin_host.cc
index a5eb536b5a7..b32f8ddc185 100644
--- a/chromium/content/child/npapi/plugin_host.cc
+++ b/chromium/content/child/npapi/plugin_host.cc
@@ -5,7 +5,7 @@
#include "content/child/npapi/plugin_host.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -275,7 +275,7 @@ bool PluginHost::SetPostData(const char* buf,
break;
case GETVALUE:
// Got a header.
- name = StringToLowerASCII(std::string(start, ptr - start));
+ name = base::StringToLowerASCII(std::string(start, ptr - start));
base::TrimWhitespace(name, base::TRIM_ALL, &name);
start = ptr + 1;
break;
diff --git a/chromium/content/child/npapi/plugin_instance.cc b/chromium/content/child/npapi/plugin_instance.cc
index b141c5af15b..4555f01c187 100644
--- a/chromium/content/child/npapi/plugin_instance.cc
+++ b/chromium/content/child/npapi/plugin_instance.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -406,7 +406,8 @@ void PluginInstance::DidReceiveManualResponse(const GURL& url,
uint32 last_modified) {
DCHECK(load_manually_);
- plugin_data_stream_ = CreateStream(-1, url, mime_type, 0);
+ plugin_data_stream_ =
+ CreateStream(static_cast<unsigned long>(-1), url, mime_type, 0);
plugin_data_stream_->DidReceiveResponse(mime_type, headers, expected_length,
last_modified, true);
}
diff --git a/chromium/content/child/npapi/plugin_lib_unittest.cc b/chromium/content/child/npapi/plugin_lib_unittest.cc
index 0438ead6b98..1469828019c 100644
--- a/chromium/content/child/npapi/plugin_lib_unittest.cc
+++ b/chromium/content/child/npapi/plugin_lib_unittest.cc
@@ -20,7 +20,7 @@ class PluginLibTest : public PluginLib {
using PluginLib::Unload;
protected:
- virtual ~PluginLibTest() {}
+ ~PluginLibTest() override {}
};
TEST(PluginLibLoading, UnloadAllPlugins) {
diff --git a/chromium/content/child/npapi/plugin_stream.cc b/chromium/content/child/npapi/plugin_stream.cc
index 8b8a7f7c583..b069c26f950 100644
--- a/chromium/content/child/npapi/plugin_stream.cc
+++ b/chromium/content/child/npapi/plugin_stream.cc
@@ -62,7 +62,7 @@ bool PluginStream::Open(const std::string& mime_type,
bool seekable_stream = false;
if (request_is_seekable) {
- std::string headers_lc = StringToLowerASCII(headers);
+ std::string headers_lc = base::StringToLowerASCII(headers);
if (headers_lc.find("accept-ranges: bytes") != std::string::npos) {
seekable_stream = true;
}
diff --git a/chromium/content/child/npapi/plugin_stream_posix.cc b/chromium/content/child/npapi/plugin_stream_posix.cc
index 8c74d83cd2c..ed9687c038f 100644
--- a/chromium/content/child/npapi/plugin_stream_posix.cc
+++ b/chromium/content/child/npapi/plugin_stream_posix.cc
@@ -6,8 +6,8 @@
#include <string.h>
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "content/child/npapi/plugin_instance.h"
diff --git a/chromium/content/child/npapi/plugin_stream_url.h b/chromium/content/child/npapi/plugin_stream_url.h
index f63593dd142..c43f7892c72 100644
--- a/chromium/content/child/npapi/plugin_stream_url.h
+++ b/chromium/content/child/npapi/plugin_stream_url.h
@@ -39,28 +39,26 @@ class PluginStreamUrl : public PluginStream,
// Stop sending the stream to the client.
// Overrides the base Close so we can cancel our fetching the URL if
// it is still loading.
- virtual bool Close(NPReason reason) OVERRIDE;
- virtual WebPluginResourceClient* AsResourceClient() OVERRIDE;
- virtual void CancelRequest() OVERRIDE;
+ bool Close(NPReason reason) override;
+ WebPluginResourceClient* AsResourceClient() override;
+ void CancelRequest() override;
// WebPluginResourceClient methods
- virtual void WillSendRequest(const GURL& url, int http_status_code) OVERRIDE;
- virtual void DidReceiveResponse(const std::string& mime_type,
- const std::string& headers,
- uint32 expected_length,
- uint32 last_modified,
- bool request_is_seekable) OVERRIDE;
- virtual void DidReceiveData(const char* buffer,
- int length,
- int data_offset) OVERRIDE;
- virtual void DidFinishLoading(unsigned long resource_id) OVERRIDE;
- virtual void DidFail(unsigned long resource_id) OVERRIDE;
- virtual bool IsMultiByteResponseExpected() OVERRIDE;
- virtual int ResourceId() OVERRIDE;
- virtual void AddRangeRequestResourceId(unsigned long resource_id) OVERRIDE;
+ void WillSendRequest(const GURL& url, int http_status_code) override;
+ void DidReceiveResponse(const std::string& mime_type,
+ const std::string& headers,
+ uint32 expected_length,
+ uint32 last_modified,
+ bool request_is_seekable) override;
+ void DidReceiveData(const char* buffer, int length, int data_offset) override;
+ void DidFinishLoading(unsigned long resource_id) override;
+ void DidFail(unsigned long resource_id) override;
+ bool IsMultiByteResponseExpected() override;
+ int ResourceId() override;
+ void AddRangeRequestResourceId(unsigned long resource_id) override;
protected:
- virtual ~PluginStreamUrl();
+ ~PluginStreamUrl() override;
private:
void SetDeferLoading(bool value);
diff --git a/chromium/content/child/npapi/plugin_string_stream.h b/chromium/content/child/npapi/plugin_string_stream.h
index 8445003c0e3..fff88639ca6 100644
--- a/chromium/content/child/npapi/plugin_string_stream.h
+++ b/chromium/content/child/npapi/plugin_string_stream.h
@@ -29,7 +29,7 @@ class PluginStringStream : public PluginStream {
const std::string& mime_type);
private:
- virtual ~PluginStringStream();
+ ~PluginStringStream() override;
DISALLOW_COPY_AND_ASSIGN(PluginStringStream);
};
diff --git a/chromium/content/child/npapi/plugin_url_fetcher.cc b/chromium/content/child/npapi/plugin_url_fetcher.cc
index acd508ba922..ff3e79884df 100644
--- a/chromium/content/child/npapi/plugin_url_fetcher.cc
+++ b/chromium/content/child/npapi/plugin_url_fetcher.cc
@@ -6,6 +6,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/child/child_thread.h"
+#include "content/child/multipart_response_delegate.h"
#include "content/child/npapi/plugin_host.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/child/npapi/plugin_stream_url.h"
@@ -15,6 +16,7 @@
#include "content/child/request_extra_data.h"
#include "content/child/request_info.h"
#include "content/child/resource_dispatcher.h"
+#include "content/child/resource_loader_bridge.h"
#include "content/child/web_url_loader_impl.h"
#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -22,11 +24,9 @@
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
-#include "net/url_request/url_request.h"
+#include "net/url_request/redirect_info.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "webkit/child/multipart_response_delegate.h"
-#include "webkit/child/resource_loader_bridge.h"
namespace content {
namespace {
@@ -46,18 +46,19 @@ class MultiPartResponseClient : public blink::WebURLLoaderClient {
// blink::WebURLLoaderClient implementation:
virtual void didReceiveResponse(
blink::WebURLLoader* loader,
- const blink::WebURLResponse& response) OVERRIDE {
+ const blink::WebURLResponse& response) override {
int64 byte_range_upper_bound, instance_size;
- if (!webkit_glue::MultipartResponseDelegate::ReadContentRanges(
- response, &byte_range_lower_bound_, &byte_range_upper_bound,
- &instance_size)) {
+ if (!MultipartResponseDelegate::ReadContentRanges(response,
+ &byte_range_lower_bound_,
+ &byte_range_upper_bound,
+ &instance_size)) {
NOTREACHED();
}
}
virtual void didReceiveData(blink::WebURLLoader* loader,
const char* data,
int data_length,
- int encoded_data_length) OVERRIDE {
+ int encoded_data_length) override {
// TODO(ananta)
// We should defer further loads on multipart resources on the same lines
// as regular resources requested by plugins to prevent reentrancy.
@@ -94,7 +95,6 @@ PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream,
: plugin_stream_(plugin_stream),
url_(url),
first_party_for_cookies_(first_party_for_cookies),
- method_(method),
referrer_(referrer),
notify_redirects_(notify_redirects),
is_plugin_src_load_(is_plugin_src_load),
@@ -112,8 +112,10 @@ PluginURLFetcher::PluginURLFetcher(PluginStreamUrl* plugin_stream,
request_info.referrer = referrer;
request_info.load_flags = net::LOAD_NORMAL;
request_info.requestor_pid = origin_pid;
- request_info.request_type = ResourceType::OBJECT;
+ request_info.request_type = RESOURCE_TYPE_OBJECT;
request_info.routing_id = render_view_id;
+ // ServiceWorker is disabled for NPAPI.
+ request_info.skip_service_worker = true;
RequestExtraData extra_data;
extra_data.set_render_frame_id(render_frame_id);
@@ -190,8 +192,7 @@ void PluginURLFetcher::OnUploadProgress(uint64 position, uint64 size) {
}
bool PluginURLFetcher::OnReceivedRedirect(
- const GURL& new_url,
- const GURL& new_first_party_for_cookies,
+ const net::RedirectInfo& redirect_info,
const ResourceResponseInfo& info) {
if (!plugin_stream_)
return false;
@@ -205,32 +206,28 @@ bool PluginURLFetcher::OnReceivedRedirect(
// initiated by plug-ins.
if (is_plugin_src_load_ &&
!plugin_stream_->instance()->webplugin()->CheckIfRunInsecureContent(
- new_url)) {
+ redirect_info.new_url)) {
plugin_stream_->DidFail(resource_id_); // That will delete |this|.
return false;
}
- // It's unfortunate that this logic of when a redirect's method changes is
- // in url_request.cc, but weburlloader_impl.cc and this file have to duplicate
- // it instead of passing that information.
- int response_code = info.headers->response_code();
- method_ = net::URLRequest::ComputeMethodForRedirect(method_, response_code);
GURL old_url = url_;
- url_ = new_url;
- first_party_for_cookies_ = new_first_party_for_cookies;
+ url_ = redirect_info.new_url;
+ first_party_for_cookies_ = redirect_info.new_first_party_for_cookies;
// If the plugin does not participate in url redirect notifications then just
// block cross origin 307 POST redirects.
if (!notify_redirects_) {
- if (response_code == 307 && method_ == "POST" &&
- old_url.GetOrigin() != new_url.GetOrigin()) {
+ if (redirect_info.status_code == 307 &&
+ redirect_info.new_method == "POST" &&
+ old_url.GetOrigin() != url_.GetOrigin()) {
plugin_stream_->DidFail(resource_id_); // That will delete |this|.
return false;
}
} else {
// Pause the request while we ask the plugin what to do about the redirect.
bridge_->SetDefersLoading(true);
- plugin_stream_->WillSendRequest(url_, response_code);
+ plugin_stream_->WillSendRequest(url_, redirect_info.status_code);
}
return true;
@@ -254,14 +251,14 @@ void PluginURLFetcher::OnReceivedResponse(const ResourceResponseInfo& info) {
WebURLLoaderImpl::PopulateURLResponse(url_, info, &response);
std::string multipart_boundary;
- if (webkit_glue::MultipartResponseDelegate::ReadMultipartBoundary(
+ if (MultipartResponseDelegate::ReadMultipartBoundary(
response, &multipart_boundary)) {
plugin_stream_->instance()->webplugin()->DidStartLoading();
MultiPartResponseClient* multi_part_response_client =
new MultiPartResponseClient(plugin_stream_);
- multipart_delegate_.reset(new webkit_glue::MultipartResponseDelegate(
+ multipart_delegate_.reset(new MultipartResponseDelegate(
multi_part_response_client, NULL, response, multipart_boundary));
// Multiple ranges requested, data will be delivered by
@@ -273,7 +270,7 @@ void PluginURLFetcher::OnReceivedResponse(const ResourceResponseInfo& info) {
int64 upper_bound = 0, instance_size = 0;
// Single range requested - go through original processing for
// non-multipart requests, but update data offset.
- webkit_glue::MultipartResponseDelegate::ReadContentRanges(
+ MultipartResponseDelegate::ReadContentRanges(
response, &data_offset_, &upper_bound, &instance_size);
} else if (response_code == 200) {
// TODO: should we handle this case? We used to but it's not clear that we
@@ -289,7 +286,7 @@ void PluginURLFetcher::OnReceivedResponse(const ResourceResponseInfo& info) {
base::Time temp;
uint32 last_modified = 0;
std::string headers;
- if (info.headers) { // NULL for data: urls.
+ if (info.headers.get()) { // NULL for data: urls.
if (info.headers->GetLastModifiedValue(&temp))
last_modified = static_cast<uint32>(temp.ToDoubleT());
@@ -312,7 +309,7 @@ void PluginURLFetcher::OnReceivedResponse(const ResourceResponseInfo& info) {
// of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF destroy
// the stream and invoke the NPP_DestroyStream function on the plugin if the
// HTTPrequest fails.
- if ((url_.SchemeIs("http") || url_.SchemeIs("https")) &&
+ if ((url_.SchemeIs(url::kHttpScheme) || url_.SchemeIs(url::kHttpsScheme)) &&
(response_code < 100 || response_code >= 400)) {
pending_failure_notification_ = true;
}
diff --git a/chromium/content/child/npapi/plugin_url_fetcher.h b/chromium/content/child/npapi/plugin_url_fetcher.h
index 7eab78e4326..57eb5a5beba 100644
--- a/chromium/content/child/npapi/plugin_url_fetcher.h
+++ b/chromium/content/child/npapi/plugin_url_fetcher.h
@@ -11,13 +11,10 @@
#include "content/public/child/request_peer.h"
#include "url/gurl.h"
-namespace webkit_glue {
-class MultipartResponseDelegate;
-class ResourceLoaderBridge;
-}
-
namespace content {
+class MultipartResponseDelegate;
class PluginStreamUrl;
+class ResourceLoaderBridge;
// Fetches URLS for a plugin using ResourceDispatcher.
class PluginURLFetcher : public RequestPeer {
@@ -37,7 +34,7 @@ class PluginURLFetcher : public RequestPeer {
int render_view_id,
unsigned long resource_id,
bool copy_stream_data);
- virtual ~PluginURLFetcher();
+ ~PluginURLFetcher() override;
// Cancels the current request.
void Cancel();
@@ -55,28 +52,26 @@ class PluginURLFetcher : public RequestPeer {
private:
// RequestPeer implementation:
- virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
- virtual bool OnReceivedRedirect(const GURL& new_url,
- const GURL& new_first_party_for_cookies,
- const ResourceResponseInfo& info) OVERRIDE;
- virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE;
- virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE;
- virtual void OnReceivedData(const char* data,
- int data_length,
- int encoded_data_length) OVERRIDE;
- virtual void OnCompletedRequest(int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64 total_transfer_size) OVERRIDE;
+ void OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) override;
+ void OnReceivedResponse(const ResourceResponseInfo& info) override;
+ void OnDownloadedData(int len, int encoded_data_length) override;
+ void OnReceivedData(const char* data,
+ int data_length,
+ int encoded_data_length) override;
+ void OnCompletedRequest(int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64 total_transfer_size) override;
// |plugin_stream_| becomes NULL after Cancel() to ensure no further calls
// |reach it.
PluginStreamUrl* plugin_stream_;
GURL url_;
GURL first_party_for_cookies_;
- std::string method_;
GURL referrer_;
bool notify_redirects_;
bool is_plugin_src_load_;
@@ -88,9 +83,9 @@ class PluginURLFetcher : public RequestPeer {
int64 data_offset_;
bool pending_failure_notification_;
- scoped_ptr<webkit_glue::MultipartResponseDelegate> multipart_delegate_;
+ scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
- scoped_ptr<webkit_glue::ResourceLoaderBridge> bridge_;
+ scoped_ptr<ResourceLoaderBridge> bridge_;
DISALLOW_COPY_AND_ASSIGN(PluginURLFetcher);
};
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl.h b/chromium/content/child/npapi/webplugin_delegate_impl.h
index d9ab5b9c626..e37a651a1e4 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl.h
+++ b/chromium/content/child/npapi/webplugin_delegate_impl.h
@@ -78,53 +78,55 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
const std::string& mime_type);
// WebPluginDelegate implementation
- virtual bool Initialize(const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) OVERRIDE;
- virtual void PluginDestroyed() OVERRIDE;
- virtual void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) OVERRIDE;
- virtual void Paint(SkCanvas* canvas, const gfx::Rect& rect) OVERRIDE;
- virtual void SetFocus(bool focused) OVERRIDE;
- virtual bool HandleInputEvent(const blink::WebInputEvent& event,
- WebCursor::CursorInfo* cursor_info) OVERRIDE;
- virtual NPObject* GetPluginScriptableObject() OVERRIDE;
- virtual NPP GetPluginNPP() OVERRIDE;
- virtual bool GetFormValue(base::string16* value) OVERRIDE;
- virtual void DidFinishLoadWithReason(const GURL& url,
- NPReason reason,
- int notify_id) OVERRIDE;
- virtual int GetProcessId() OVERRIDE;
- virtual void SendJavaScriptStream(const GURL& url,
- const std::string& result,
- bool success,
- int notify_id) OVERRIDE;
- virtual void DidReceiveManualResponse(const GURL& url,
- const std::string& mime_type,
- const std::string& headers,
- uint32 expected_length,
- uint32 last_modified) OVERRIDE;
- virtual void DidReceiveManualData(const char* buffer, int length) OVERRIDE;
- virtual void DidFinishManualLoading() OVERRIDE;
- virtual void DidManualLoadFail() OVERRIDE;
- virtual WebPluginResourceClient* CreateResourceClient(
- unsigned long resource_id, const GURL& url, int notify_id) OVERRIDE;
- virtual WebPluginResourceClient* CreateSeekableResourceClient(
- unsigned long resource_id, int range_request_id) OVERRIDE;
- virtual void FetchURL(unsigned long resource_id,
- int notify_id,
- const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& method,
- const char* buf,
- unsigned int len,
- const GURL& referrer,
- bool notify_redirects,
- bool is_plugin_src_load,
- int origin_pid,
- int render_frame_id,
- int render_view_id) OVERRIDE;
+ bool Initialize(const GURL& url,
+ const std::vector<std::string>& arg_names,
+ const std::vector<std::string>& arg_values,
+ bool load_manually) override;
+ void PluginDestroyed() override;
+ void UpdateGeometry(const gfx::Rect& window_rect,
+ const gfx::Rect& clip_rect) override;
+ void Paint(SkCanvas* canvas, const gfx::Rect& rect) override;
+ void SetFocus(bool focused) override;
+ bool HandleInputEvent(const blink::WebInputEvent& event,
+ WebCursor::CursorInfo* cursor_info) override;
+ NPObject* GetPluginScriptableObject() override;
+ NPP GetPluginNPP() override;
+ bool GetFormValue(base::string16* value) override;
+ void DidFinishLoadWithReason(const GURL& url,
+ NPReason reason,
+ int notify_id) override;
+ int GetProcessId() override;
+ void SendJavaScriptStream(const GURL& url,
+ const std::string& result,
+ bool success,
+ int notify_id) override;
+ void DidReceiveManualResponse(const GURL& url,
+ const std::string& mime_type,
+ const std::string& headers,
+ uint32 expected_length,
+ uint32 last_modified) override;
+ void DidReceiveManualData(const char* buffer, int length) override;
+ void DidFinishManualLoading() override;
+ void DidManualLoadFail() override;
+ WebPluginResourceClient* CreateResourceClient(unsigned long resource_id,
+ const GURL& url,
+ int notify_id) override;
+ WebPluginResourceClient* CreateSeekableResourceClient(
+ unsigned long resource_id,
+ int range_request_id) override;
+ void FetchURL(unsigned long resource_id,
+ int notify_id,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& method,
+ const char* buf,
+ unsigned int len,
+ const GURL& referrer,
+ bool notify_redirects,
+ bool is_plugin_src_load,
+ int origin_pid,
+ int render_frame_id,
+ int render_view_id) override;
// End of WebPluginDelegate implementation.
gfx::PluginWindowHandle windowed_handle() const { return windowed_handle_; }
@@ -197,7 +199,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
friend class WebPluginDelegate;
WebPluginDelegateImpl(WebPlugin* plugin, PluginInstance* instance);
- virtual ~WebPluginDelegateImpl();
+ ~WebPluginDelegateImpl() override;
// Called by Initialize() for platform-specific initialization.
// If this returns false, the plugin shouldn't be started--see Initialize().
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_win.cc b/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
index a879f67aa42..f570c7c29de 100644
--- a/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
+++ b/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
@@ -252,7 +252,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
std::wstring filename =
- StringToLowerASCII(plugin_info.path.BaseName().value());
+ base::StringToLowerASCII(plugin_info.path.BaseName().value());
if (instance_->mime_type() == kFlashPluginSwfMimeType ||
filename == kFlashPlugin) {
@@ -499,34 +499,6 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() {
BOOL result = SetProp(windowed_handle_, kWebPluginDelegateProperty, this);
DCHECK(result == TRUE) << "SetProp failed, last error = " << GetLastError();
- // Get the name and version of the plugin, create atoms and set them in a
- // window property. Use atoms so that other processes can access the name and
- // version of the plugin that this window is hosting.
- if (instance_ != NULL) {
- PluginLib* plugin_lib = instance()->plugin_lib();
- if (plugin_lib != NULL) {
- std::wstring plugin_name = plugin_lib->plugin_info().name;
- if (!plugin_name.empty()) {
- ATOM plugin_name_atom = GlobalAddAtomW(plugin_name.c_str());
- DCHECK_NE(0, plugin_name_atom);
- result = SetProp(windowed_handle_,
- kPluginNameAtomProperty,
- reinterpret_cast<HANDLE>(plugin_name_atom));
- DCHECK(result == TRUE) << "SetProp failed, last error = " <<
- GetLastError();
- }
- base::string16 plugin_version = plugin_lib->plugin_info().version;
- if (!plugin_version.empty()) {
- ATOM plugin_version_atom = GlobalAddAtomW(plugin_version.c_str());
- DCHECK_NE(0, plugin_version_atom);
- result = SetProp(windowed_handle_,
- kPluginVersionAtomProperty,
- reinterpret_cast<HANDLE>(plugin_version_atom));
- DCHECK(result == TRUE) << "SetProp failed, last error = " <<
- GetLastError();
- }
- }
- }
// Calling SetWindowLongPtrA here makes the window proc ASCII, which is
// required by at least the Shockwave Director plug-in.
@@ -1026,14 +998,6 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
if (message == WM_NCDESTROY) {
RemoveProp(hwnd, kWebPluginDelegateProperty);
- ATOM plugin_name_atom = reinterpret_cast<ATOM>(
- RemoveProp(hwnd, kPluginNameAtomProperty));
- if (plugin_name_atom != 0)
- GlobalDeleteAtom(plugin_name_atom);
- ATOM plugin_version_atom = reinterpret_cast<ATOM>(
- RemoveProp(hwnd, kPluginVersionAtomProperty));
- if (plugin_version_atom != 0)
- GlobalDeleteAtom(plugin_version_atom);
ClearThrottleQueueForWindow(hwnd);
}
}
@@ -1065,7 +1029,7 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry(
NPEvent pos_changed_event;
pos_changed_event.event = WM_WINDOWPOSCHANGED;
pos_changed_event.wParam = 0;
- pos_changed_event.lParam = PtrToUlong(&win_pos);
+ pos_changed_event.lParam = reinterpret_cast<uintptr_t>(&win_pos);
instance()->NPP_HandleEvent(&pos_changed_event);
}
@@ -1087,9 +1051,8 @@ void WebPluginDelegateImpl::WindowlessPaint(HDC hdc,
NPEvent paint_event;
paint_event.event = WM_PAINT;
- // NOTE: NPAPI is not 64bit safe. It puts pointers into 32bit values.
paint_event.wParam = PtrToUlong(hdc);
- paint_event.lParam = PtrToUlong(&damage_rect_win);
+ paint_event.lParam = reinterpret_cast<uintptr_t>(&damage_rect_win);
base::StatsRate plugin_paint("Plugin.Paint");
base::StatsScope<base::StatsRate> scope(plugin_paint);
instance()->NPP_HandleEvent(&paint_event);
diff --git a/chromium/content/child/plugin_messages.h b/chromium/content/child/plugin_messages.h
index b71441ea53d..2e17c98a4a8 100644
--- a/chromium/content/child/plugin_messages.h
+++ b/chromium/content/child/plugin_messages.h
@@ -12,6 +12,7 @@
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
diff --git a/chromium/content/child/power_monitor_broadcast_source.cc b/chromium/content/child/power_monitor_broadcast_source.cc
index 0cbd75a3a7c..0fa58897202 100644
--- a/chromium/content/child/power_monitor_broadcast_source.cc
+++ b/chromium/content/child/power_monitor_broadcast_source.cc
@@ -19,7 +19,7 @@ class PowerMessageFilter : public IPC::MessageFilter {
message_loop_(message_loop) {
}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PowerMessageFilter, message)
IPC_MESSAGE_HANDLER(PowerMonitorMsg_PowerStateChange, OnPowerStateChange)
@@ -37,7 +37,7 @@ class PowerMessageFilter : public IPC::MessageFilter {
private:
friend class base::RefCounted<PowerMessageFilter>;
- virtual ~PowerMessageFilter() {};
+ ~PowerMessageFilter() override{};
void OnPowerStateChange(bool on_battery_power) {
message_loop_->PostTask(FROM_HERE,
diff --git a/chromium/content/child/power_monitor_broadcast_source.h b/chromium/content/child/power_monitor_broadcast_source.h
index 7bed46beb4f..b0d34162fbb 100644
--- a/chromium/content/child/power_monitor_broadcast_source.h
+++ b/chromium/content/child/power_monitor_broadcast_source.h
@@ -23,14 +23,14 @@ class CONTENT_EXPORT PowerMonitorBroadcastSource :
public base::PowerMonitorSource {
public:
explicit PowerMonitorBroadcastSource();
- virtual ~PowerMonitorBroadcastSource();
+ ~PowerMonitorBroadcastSource() override;
IPC::MessageFilter* GetMessageFilter();
private:
friend class PowerMessageFilter;
- virtual bool IsOnBatteryPowerImpl() OVERRIDE;
+ bool IsOnBatteryPowerImpl() override;
void OnPowerStateChange(bool on_battery_power);
void OnSuspend();
diff --git a/chromium/content/child/power_monitor_broadcast_source_unittest.cc b/chromium/content/child/power_monitor_broadcast_source_unittest.cc
index 4e469435372..030e1353365 100644
--- a/chromium/content/child/power_monitor_broadcast_source_unittest.cc
+++ b/chromium/content/child/power_monitor_broadcast_source_unittest.cc
@@ -18,7 +18,7 @@ class PowerMonitorBroadcastSourceTest : public testing::Test {
power_monitor_.reset(new base::PowerMonitor(
scoped_ptr<base::PowerMonitorSource>(power_monitor_source_)));
}
- virtual ~PowerMonitorBroadcastSourceTest() {}
+ ~PowerMonitorBroadcastSourceTest() override {}
PowerMonitorBroadcastSource* source() { return power_monitor_source_; }
base::PowerMonitor* monitor() { return power_monitor_.get(); }
diff --git a/chromium/content/child/quota_dispatcher.cc b/chromium/content/child/quota_dispatcher.cc
index 7f47d662199..5862783768f 100644
--- a/chromium/content/child/quota_dispatcher.cc
+++ b/chromium/content/child/quota_dispatcher.cc
@@ -19,8 +19,8 @@
using blink::WebStorageQuotaCallbacks;
using blink::WebStorageQuotaError;
using blink::WebStorageQuotaType;
-using quota::QuotaStatusCode;
-using quota::StorageType;
+using storage::QuotaStatusCode;
+using storage::StorageType;
namespace content {
@@ -35,15 +35,15 @@ class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
explicit WebStorageQuotaDispatcherCallback(
blink::WebStorageQuotaCallbacks callback)
: callbacks_(callback) {}
- virtual ~WebStorageQuotaDispatcherCallback() {}
+ ~WebStorageQuotaDispatcherCallback() override {}
- virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
+ void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) override {
callbacks_.didQueryStorageUsageAndQuota(usage, quota);
}
- virtual void DidGrantStorageQuota(int64 usage, int64 granted_quota) OVERRIDE {
+ void DidGrantStorageQuota(int64 usage, int64 granted_quota) override {
callbacks_.didGrantStorageQuota(usage, granted_quota);
}
- virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
+ void DidFail(storage::QuotaStatusCode error) override {
callbacks_.didFail(static_cast<WebStorageQuotaError>(error));
}
@@ -69,7 +69,7 @@ QuotaDispatcher::QuotaDispatcher(ThreadSafeSender* thread_safe_sender,
QuotaDispatcher::~QuotaDispatcher() {
IDMap<Callback, IDMapOwnPointer>::iterator iter(&pending_quota_callbacks_);
while (!iter.IsAtEnd()) {
- iter.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort);
+ iter.GetCurrentValue()->DidFail(storage::kQuotaErrorAbort);
iter.Advance();
}
@@ -175,14 +175,18 @@ void QuotaDispatcher::DidFail(
pending_quota_callbacks_.Remove(request_id);
}
-COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) == \
- int(quota::kStorageTypeTemporary), mismatching_enums);
-COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) == \
- int(quota::kStorageTypePersistent), mismatching_enums);
-
-COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) == \
- int(quota::kQuotaErrorNotSupported), mismatching_enums);
-COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) == \
- int(quota::kQuotaErrorAbort), mismatching_enums);
+COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) ==
+ int(storage::kStorageTypeTemporary),
+ mismatching_enums);
+COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) ==
+ int(storage::kStorageTypePersistent),
+ mismatching_enums);
+
+COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) ==
+ int(storage::kQuotaErrorNotSupported),
+ mismatching_enums);
+COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) ==
+ int(storage::kQuotaErrorAbort),
+ mismatching_enums);
} // namespace content
diff --git a/chromium/content/child/quota_dispatcher.h b/chromium/content/child/quota_dispatcher.h
index b80b194b5fd..f4111e6245f 100644
--- a/chromium/content/child/quota_dispatcher.h
+++ b/chromium/content/child/quota_dispatcher.h
@@ -12,7 +12,7 @@
#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "content/child/worker_task_runner.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/common/quota/quota_types.h"
class GURL;
@@ -40,12 +40,12 @@ class QuotaDispatcher : public WorkerTaskRunner::Observer {
virtual ~Callback() {}
virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) = 0;
virtual void DidGrantStorageQuota(int64 usage, int64 granted_quota) = 0;
- virtual void DidFail(quota::QuotaStatusCode status) = 0;
+ virtual void DidFail(storage::QuotaStatusCode status) = 0;
};
QuotaDispatcher(ThreadSafeSender* thread_safe_sender,
QuotaMessageFilter* quota_message_filter);
- virtual ~QuotaDispatcher();
+ ~QuotaDispatcher() override;
// |thread_safe_sender| and |quota_message_filter| are used if
// calling this leads to construction.
@@ -54,16 +54,16 @@ class QuotaDispatcher : public WorkerTaskRunner::Observer {
QuotaMessageFilter* quota_message_filter);
// WorkerTaskRunner::Observer implementation.
- virtual void OnWorkerRunLoopStopped() OVERRIDE;
+ void OnWorkerRunLoopStopped() override;
void OnMessageReceived(const IPC::Message& msg);
void QueryStorageUsageAndQuota(const GURL& gurl,
- quota::StorageType type,
+ storage::StorageType type,
Callback* callback);
void RequestStorageQuota(int render_view_id,
const GURL& gurl,
- quota::StorageType type,
+ storage::StorageType type,
uint64 requested_size,
Callback* callback);
@@ -79,8 +79,7 @@ class QuotaDispatcher : public WorkerTaskRunner::Observer {
void DidGrantStorageQuota(int request_id,
int64 current_usage,
int64 granted_quota);
- void DidFail(int request_id,
- quota::QuotaStatusCode error);
+ void DidFail(int request_id, storage::QuotaStatusCode error);
IDMap<Callback, IDMapOwnPointer> pending_quota_callbacks_;
diff --git a/chromium/content/child/quota_message_filter.h b/chromium/content/child/quota_message_filter.h
index 7ae0c0cc5e6..b13e705e920 100644
--- a/chromium/content/child/quota_message_filter.h
+++ b/chromium/content/child/quota_message_filter.h
@@ -32,13 +32,13 @@ class QuotaMessageFilter : public ChildMessageFilter {
void ClearThreadRequests(int thread_id);
protected:
- virtual ~QuotaMessageFilter();
+ ~QuotaMessageFilter() override;
private:
// ChildMessageFilter implementation:
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
typedef std::map<int, int> RequestIdToThreadId;
diff --git a/chromium/content/child/request_extra_data.cc b/chromium/content/child/request_extra_data.cc
index f926f380b84..5a1c689fc36 100644
--- a/chromium/content/child/request_extra_data.cc
+++ b/chromium/content/child/request_extra_data.cc
@@ -18,12 +18,11 @@ RequestExtraData::RequestExtraData()
parent_is_main_frame_(false),
parent_render_frame_id_(-1),
allow_download_(true),
- transition_type_(PAGE_TRANSITION_LINK),
+ transition_type_(ui::PAGE_TRANSITION_LINK),
should_replace_current_entry_(false),
transferred_request_child_id_(-1),
transferred_request_request_id_(-1),
- service_worker_provider_id_(kInvalidServiceWorkerProviderId),
- was_after_preconnect_request_(false) {
+ service_worker_provider_id_(kInvalidServiceWorkerProviderId) {
}
RequestExtraData::~RequestExtraData() {
diff --git a/chromium/content/child/request_extra_data.h b/chromium/content/child/request_extra_data.h
index 96582ec1193..4ba5fbcb790 100644
--- a/chromium/content/child/request_extra_data.h
+++ b/chromium/content/child/request_extra_data.h
@@ -6,11 +6,12 @@
#define CONTENT_CHILD_REQUEST_EXTRA_DATA_H_
#include "base/compiler_specific.h"
+#include "content/child/web_url_loader_impl.h"
#include "content/common/content_export.h"
-#include "content/public/common/page_transition_types.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
+#include "ui/base/page_transition_types.h"
namespace content {
@@ -53,8 +54,8 @@ class CONTENT_EXPORT RequestExtraData
void set_allow_download(bool allow_download) {
allow_download_ = allow_download;
}
- PageTransition transition_type() const { return transition_type_; }
- void set_transition_type(PageTransition transition_type) {
+ ui::PageTransition transition_type() const { return transition_type_; }
+ void set_transition_type(ui::PageTransition transition_type) {
transition_type_ = transition_type;
}
bool should_replace_current_entry() const {
@@ -90,16 +91,27 @@ class CONTENT_EXPORT RequestExtraData
// override and an empty string to indicate that there should be no user
// agent.
const blink::WebString& custom_user_agent() const {
- return custom_user_agent_;
+ return custom_user_agent_;
}
- void set_custom_user_agent(
- const blink::WebString& custom_user_agent) {
+ void set_custom_user_agent(const blink::WebString& custom_user_agent) {
custom_user_agent_ = custom_user_agent;
}
- bool was_after_preconnect_request() { return was_after_preconnect_request_; }
- void set_was_after_preconnect_request(
- bool was_after_preconnect_request) {
- was_after_preconnect_request_ = was_after_preconnect_request;
+ const blink::WebString& requested_with() const {
+ return requested_with_;
+ }
+ void set_requested_with(const blink::WebString& requested_with) {
+ requested_with_ = requested_with;
+ }
+
+ // PlzNavigate: |stream_override| is used to override certain parameters of
+ // navigation requests.
+ scoped_ptr<StreamOverrideParameters> TakeStreamOverrideOwnership() {
+ return stream_override_.Pass();
+ }
+
+ void set_stream_override(
+ scoped_ptr<StreamOverrideParameters> stream_override) {
+ stream_override_ = stream_override.Pass();
}
private:
@@ -110,13 +122,14 @@ class CONTENT_EXPORT RequestExtraData
bool parent_is_main_frame_;
int parent_render_frame_id_;
bool allow_download_;
- PageTransition transition_type_;
+ ui::PageTransition transition_type_;
bool should_replace_current_entry_;
int transferred_request_child_id_;
int transferred_request_request_id_;
int service_worker_provider_id_;
blink::WebString custom_user_agent_;
- bool was_after_preconnect_request_;
+ blink::WebString requested_with_;
+ scoped_ptr<StreamOverrideParameters> stream_override_;
DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
};
diff --git a/chromium/content/child/request_info.cc b/chromium/content/child/request_info.cc
index e75c54a7f8c..e52f2aa688f 100644
--- a/chromium/content/child/request_info.cc
+++ b/chromium/content/child/request_info.cc
@@ -10,13 +10,20 @@ RequestInfo::RequestInfo()
: referrer_policy(blink::WebReferrerPolicyDefault),
load_flags(0),
requestor_pid(0),
- request_type(ResourceType::MAIN_FRAME),
+ request_type(RESOURCE_TYPE_MAIN_FRAME),
+ fetch_request_context_type(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
+ fetch_frame_type(REQUEST_CONTEXT_FRAME_TYPE_NONE),
priority(net::LOW),
request_context(0),
appcache_host_id(0),
routing_id(0),
download_to_file(false),
has_user_gesture(false),
+ skip_service_worker(false),
+ fetch_request_mode(FETCH_REQUEST_MODE_NO_CORS),
+ fetch_credentials_mode(FETCH_CREDENTIALS_MODE_OMIT),
+ enable_load_timing(false),
+ enable_upload_progress(false),
extra_data(NULL) {
}
diff --git a/chromium/content/child/request_info.h b/chromium/content/child/request_info.h
index 6dd1bed698f..6861741905b 100644
--- a/chromium/content/child/request_info.h
+++ b/chromium/content/child/request_info.h
@@ -10,11 +10,14 @@
#include <string>
#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
#include "net/base/request_priority.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
namespace content {
@@ -54,7 +57,9 @@ struct CONTENT_EXPORT RequestInfo {
// Indicates if the current request is the main frame load, a sub-frame
// load, or a sub objects load.
- ResourceType::Type request_type;
+ ResourceType request_type;
+ RequestContextType fetch_request_context_type;
+ RequestContextFrameType fetch_frame_type;
// Indicates the priority of this request, as determined by WebKit.
net::RequestPriority priority;
@@ -75,6 +80,22 @@ struct CONTENT_EXPORT RequestInfo {
// True if the request was user initiated.
bool has_user_gesture;
+ // True if the request should not be handled by the ServiceWorker.
+ bool skip_service_worker;
+
+ // The request mode passed to the ServiceWorker.
+ FetchRequestMode fetch_request_mode;
+
+ // The credentials mode passed to the ServiceWorker.
+ FetchCredentialsMode fetch_credentials_mode;
+
+ // TODO(mmenke): Investigate if enable_load_timing is safe to remove.
+ // True if load timing data should be collected for the request.
+ bool enable_load_timing;
+
+ // True if upload progress should be available.
+ bool enable_upload_progress;
+
// Extra data associated with this request. We do not own this pointer.
blink::WebURLRequest::ExtraData* extra_data;
diff --git a/chromium/content/child/resource_dispatcher.cc b/chromium/content/child/resource_dispatcher.cc
index 95697d944d7..ac2ff3b5f01 100644
--- a/chromium/content/child/resource_dispatcher.cc
+++ b/chromium/content/child/resource_dispatcher.cc
@@ -17,6 +17,7 @@
#include "base/strings/string_util.h"
#include "content/child/request_extra_data.h"
#include "content/child/request_info.h"
+#include "content/child/resource_loader_bridge.h"
#include "content/child/site_isolation_policy.h"
#include "content/child/sync_load_response.h"
#include "content/child/threaded_data_provider.h"
@@ -25,14 +26,11 @@
#include "content/public/child/request_peer.h"
#include "content/public/child/resource_dispatcher_delegate.h"
#include "content/public/common/resource_response.h"
+#include "content/public/common/resource_type.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
-#include "webkit/child/resource_loader_bridge.h"
-#include "webkit/common/resource_type.h"
-
-using webkit_glue::ResourceLoaderBridge;
namespace content {
@@ -72,18 +70,18 @@ class IPCResourceLoaderBridge : public ResourceLoaderBridge {
public:
IPCResourceLoaderBridge(ResourceDispatcher* dispatcher,
const RequestInfo& request_info);
- virtual ~IPCResourceLoaderBridge();
+ ~IPCResourceLoaderBridge() override;
// ResourceLoaderBridge
- virtual void SetRequestBody(ResourceRequestBody* request_body) OVERRIDE;
- virtual bool Start(RequestPeer* peer) OVERRIDE;
- virtual void Cancel() OVERRIDE;
- virtual void SetDefersLoading(bool value) OVERRIDE;
- virtual void DidChangePriority(net::RequestPriority new_priority,
- int intra_priority_value) OVERRIDE;
- virtual bool AttachThreadedDataReceiver(
- blink::WebThreadedDataReceiver* threaded_data_receiver) OVERRIDE;
- virtual void SyncLoad(SyncLoadResponse* response) OVERRIDE;
+ void SetRequestBody(ResourceRequestBody* request_body) override;
+ bool Start(RequestPeer* peer) override;
+ void Cancel() override;
+ void SetDefersLoading(bool value) override;
+ void DidChangePriority(net::RequestPriority new_priority,
+ int intra_priority_value) override;
+ bool AttachThreadedDataReceiver(
+ blink::WebThreadedDataReceiver* threaded_data_receiver) override;
+ void SyncLoad(SyncLoadResponse* response) override;
private:
// The resource dispatcher for this loader. The bridge doesn't own it, but
@@ -128,6 +126,13 @@ IPCResourceLoaderBridge::IPCResourceLoaderBridge(
request_.appcache_host_id = request_info.appcache_host_id;
request_.download_to_file = request_info.download_to_file;
request_.has_user_gesture = request_info.has_user_gesture;
+ request_.skip_service_worker = request_info.skip_service_worker;
+ request_.fetch_request_mode = request_info.fetch_request_mode;
+ request_.fetch_credentials_mode = request_info.fetch_credentials_mode;
+ request_.fetch_request_context_type = request_info.fetch_request_context_type;
+ request_.fetch_frame_type = request_info.fetch_frame_type;
+ request_.enable_load_timing = request_info.enable_load_timing;
+ request_.enable_upload_progress = request_info.enable_upload_progress;
const RequestExtraData kEmptyData;
const RequestExtraData* extra_data;
@@ -269,9 +274,9 @@ void IPCResourceLoaderBridge::SyncLoad(SyncLoadResponse* response) {
ResourceDispatcher::ResourceDispatcher(IPC::Sender* sender)
: message_sender_(sender),
- weak_factory_(this),
delegate_(NULL),
- io_timestamp_(base::TimeTicks()) {
+ io_timestamp_(base::TimeTicks()),
+ weak_factory_(this) {
}
ResourceDispatcher::~ResourceDispatcher() {
@@ -358,6 +363,13 @@ void ResourceDispatcher::OnReceivedResponse(
request_info->peer = new_peer;
}
+ // Updates the response_url if the response was fetched by a ServiceWorker,
+ // and it was not generated inside the ServiceWorker.
+ if (response_head.was_fetched_via_service_worker &&
+ !response_head.original_url_via_service_worker.is_empty()) {
+ request_info->response_url = response_head.original_url_via_service_worker;
+ }
+
ResourceResponseInfo renderer_response_info;
ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
request_info->site_isolation_metadata =
@@ -491,8 +503,7 @@ void ResourceDispatcher::OnDownloadedData(int request_id,
void ResourceDispatcher::OnReceivedRedirect(
int request_id,
- const GURL& new_url,
- const GURL& new_first_party_for_cookies,
+ const net::RedirectInfo& redirect_info,
const ResourceResponseHead& response_head) {
TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedRedirect");
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
@@ -502,8 +513,8 @@ void ResourceDispatcher::OnReceivedRedirect(
ResourceResponseInfo renderer_response_info;
ToResourceResponseInfo(*request_info, response_head, &renderer_response_info);
- if (request_info->peer->OnReceivedRedirect(
- new_url, new_first_party_for_cookies, renderer_response_info)) {
+ if (request_info->peer->OnReceivedRedirect(redirect_info,
+ renderer_response_info)) {
// Double-check if the request is still around. The call above could
// potentially remove it.
request_info = GetPendingRequestInfo(request_id);
@@ -511,7 +522,7 @@ void ResourceDispatcher::OnReceivedRedirect(
return;
// We update the response_url here so that we can send it to
// SiteIsolationPolicy later when OnReceivedResponse is called.
- request_info->response_url = new_url;
+ request_info->response_url = redirect_info.new_url;
request_info->pending_redirect_message.reset(
new ResourceHostMsg_FollowRedirect(request_id));
if (!request_info->is_deferred) {
@@ -567,7 +578,7 @@ void ResourceDispatcher::OnRequestComplete(
}
int ResourceDispatcher::AddPendingRequest(RequestPeer* callback,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int origin_pid,
const GURL& frame_origin,
const GURL& request_url,
@@ -665,7 +676,7 @@ bool ResourceDispatcher::AttachThreadedDataReceiver(
ResourceDispatcher::PendingRequestInfo::PendingRequestInfo()
: peer(NULL),
threaded_data_provider(NULL),
- resource_type(ResourceType::SUB_RESOURCE),
+ resource_type(RESOURCE_TYPE_SUB_RESOURCE),
is_deferred(false),
download_to_file(false),
blocked_response(false),
@@ -674,7 +685,7 @@ ResourceDispatcher::PendingRequestInfo::PendingRequestInfo()
ResourceDispatcher::PendingRequestInfo::PendingRequestInfo(
RequestPeer* peer,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int origin_pid,
const GURL& frame_origin,
const GURL& request_url,
@@ -777,6 +788,29 @@ void ResourceDispatcher::ToResourceResponseInfo(
RemoteToLocalTimeTicks(converter, &load_timing->send_start);
RemoteToLocalTimeTicks(converter, &load_timing->send_end);
RemoteToLocalTimeTicks(converter, &load_timing->receive_headers_end);
+ RemoteToLocalTimeTicks(converter,
+ &renderer_info->service_worker_fetch_start);
+ RemoteToLocalTimeTicks(converter,
+ &renderer_info->service_worker_fetch_ready);
+ RemoteToLocalTimeTicks(converter,
+ &renderer_info->service_worker_fetch_end);
+
+ // Collect UMA on the inter-process skew.
+ bool is_skew_additive = false;
+ if (converter.IsSkewAdditiveForMetrics()) {
+ is_skew_additive = true;
+ base::TimeDelta skew = converter.GetSkewForMetrics();
+ if (skew >= base::TimeDelta()) {
+ UMA_HISTOGRAM_TIMES(
+ "InterProcessTimeTicks.BrowserAhead_BrowserToRenderer", skew);
+ } else {
+ UMA_HISTOGRAM_TIMES(
+ "InterProcessTimeTicks.BrowserBehind_BrowserToRenderer", -skew);
+ }
+ }
+ UMA_HISTOGRAM_BOOLEAN(
+ "InterProcessTimeTicks.IsSkewAdditive_BrowserToRenderer",
+ is_skew_additive);
}
base::TimeTicks ResourceDispatcher::ToRendererCompletionTime(
diff --git a/chromium/content/child/resource_dispatcher.h b/chromium/content/child/resource_dispatcher.h
index b21ec3962fb..ac6fbda9cc1 100644
--- a/chromium/content/child/resource_dispatcher.h
+++ b/chromium/content/child/resource_dispatcher.h
@@ -16,10 +16,11 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "content/public/common/resource_type.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "net/base/request_priority.h"
-#include "webkit/common/resource_type.h"
+#include "url/gurl.h"
struct ResourceMsg_RequestCompleteData;
@@ -27,13 +28,14 @@ namespace blink {
class WebThreadedDataReceiver;
}
-namespace webkit_glue {
-class ResourceLoaderBridge;
+namespace net {
+struct RedirectInfo;
}
namespace content {
class RequestPeer;
class ResourceDispatcherDelegate;
+class ResourceLoaderBridge;
class ThreadedDataProvider;
struct ResourceResponseInfo;
struct RequestInfo;
@@ -46,21 +48,20 @@ struct SiteIsolationResponseMetaData;
class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
public:
explicit ResourceDispatcher(IPC::Sender* sender);
- virtual ~ResourceDispatcher();
+ ~ResourceDispatcher() override;
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Creates a ResourceLoaderBridge for this type of dispatcher, this is so
// this can be tested regardless of the ResourceLoaderBridge::Create
- // implementation.
- webkit_glue::ResourceLoaderBridge* CreateBridge(
- const RequestInfo& request_info);
+ // implementation. Virtual for tests.
+ virtual ResourceLoaderBridge* CreateBridge(const RequestInfo& request_info);
// Adds a request from the |pending_requests_| list, returning the new
// requests' ID.
int AddPendingRequest(RequestPeer* callback,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int origin_pid,
const GURL& frame_origin,
const GURL& request_url,
@@ -108,7 +109,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
PendingRequestInfo();
PendingRequestInfo(RequestPeer* peer,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int origin_pid,
const GURL& frame_origin,
const GURL& request_url,
@@ -118,7 +119,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
RequestPeer* peer;
ThreadedDataProvider* threaded_data_provider;
- ResourceType::Type resource_type;
+ ResourceType resource_type;
// The PID of the original process which issued this request. This gets
// non-zero only for a request proxied by another renderer, particularly
// requests from plugins.
@@ -155,8 +156,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
void OnReceivedResponse(int request_id, const ResourceResponseHead&);
void OnReceivedCachedMetadata(int request_id, const std::vector<char>& data);
void OnReceivedRedirect(int request_id,
- const GURL& new_url,
- const GURL& new_first_party_for_cookies,
+ const net::RedirectInfo& redirect_info,
const ResourceResponseHead& response_head);
void OnSetDataBuffer(int request_id,
base::SharedMemoryHandle shm_handle,
@@ -210,13 +210,13 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
// All pending requests issued to the host
PendingRequestList pending_requests_;
- base::WeakPtrFactory<ResourceDispatcher> weak_factory_;
-
ResourceDispatcherDelegate* delegate_;
// IO thread timestamp for ongoing IPC message.
base::TimeTicks io_timestamp_;
+ base::WeakPtrFactory<ResourceDispatcher> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ResourceDispatcher);
};
diff --git a/chromium/content/child/resource_dispatcher_unittest.cc b/chromium/content/child/resource_dispatcher_unittest.cc
index 86dc17fe71a..434433eced7 100644
--- a/chromium/content/child/resource_dispatcher_unittest.cc
+++ b/chromium/content/child/resource_dispatcher_unittest.cc
@@ -9,13 +9,14 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
-#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "content/child/request_extra_data.h"
#include "content/child/request_info.h"
#include "content/child/resource_dispatcher.h"
+#include "content/child/resource_loader_bridge.h"
+#include "content/common/appcache_interfaces.h"
#include "content/common/resource_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/child/request_peer.h"
@@ -23,10 +24,6 @@
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/child/resource_loader_bridge.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-
-using webkit_glue::ResourceLoaderBridge;
namespace content {
@@ -56,46 +53,43 @@ class TestRequestPeer : public RequestPeer {
bridge_(bridge) {
}
- virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
- }
+ void OnUploadProgress(uint64 position, uint64 size) override {}
- virtual bool OnReceivedRedirect(const GURL& new_url,
- const GURL& new_first_party_for_cookies,
- const ResourceResponseInfo& info) OVERRIDE {
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) override {
++seen_redirects_;
if (defer_on_redirect_)
bridge_->SetDefersLoading(true);
return follow_redirects_;
}
- virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
+ void OnReceivedResponse(const ResourceResponseInfo& info) override {
EXPECT_FALSE(received_response_);
received_response_ = true;
if (cancel_on_receive_response_)
bridge_->Cancel();
}
- virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
+ void OnDownloadedData(int len, int encoded_data_length) override {
total_downloaded_data_length_ += len;
total_encoded_data_length_ += encoded_data_length;
}
- virtual void OnReceivedData(const char* data,
- int data_length,
- int encoded_data_length) OVERRIDE {
+ void OnReceivedData(const char* data,
+ int data_length,
+ int encoded_data_length) override {
EXPECT_TRUE(received_response_);
EXPECT_FALSE(complete_);
data_.append(data, data_length);
total_encoded_data_length_ += encoded_data_length;
}
- virtual void OnCompletedRequest(
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64 total_transfer_size) OVERRIDE {
+ void OnCompletedRequest(int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64 total_transfer_size) override {
EXPECT_TRUE(received_response_);
EXPECT_FALSE(complete_);
complete_ = true;
@@ -160,14 +154,14 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
public:
ResourceDispatcherTest() : dispatcher_(this) {}
- virtual ~ResourceDispatcherTest() {
+ ~ResourceDispatcherTest() override {
STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
shared_memory_map_.end());
}
// Emulates IPC send operations (IPC::Sender) by adding
// pending messages to the queue.
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
message_queue_.push_back(IPC::Message(*msg));
delete msg;
return true;
@@ -251,10 +245,13 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
std::string raw_headers(kTestRedirectHeaders);
std::replace(raw_headers.begin(), raw_headers.end(), '\n', '\0');
head.headers = new net::HttpResponseHeaders(raw_headers);
- head.error_code = net::OK;
+ net::RedirectInfo redirect_info;
+ redirect_info.status_code = 302;
+ redirect_info.new_method = "GET";
+ redirect_info.new_url = GURL(kTestPageUrl);
+ redirect_info.new_first_party_for_cookies = GURL(kTestPageUrl);
EXPECT_EQ(true, dispatcher_.OnMessageReceived(
- ResourceMsg_ReceivedRedirect(request_id, GURL(kTestPageUrl),
- GURL(kTestPageUrl), head)));
+ ResourceMsg_ReceivedRedirect(request_id, redirect_info, head)));
}
void NotifyReceivedResponse(int request_id) {
@@ -264,7 +261,6 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
head.headers = new net::HttpResponseHeaders(raw_headers);
head.mime_type = kTestPageMimeType;
head.charset = kTestPageCharset;
- head.error_code = net::OK;
EXPECT_EQ(true,
dispatcher_.OnMessageReceived(
ResourceMsg_ReceivedResponse(request_id, head)));
@@ -277,8 +273,8 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
EXPECT_TRUE(shared_memory->CreateAndMapAnonymous(buffer_size));
base::SharedMemoryHandle duplicate_handle;
- EXPECT_TRUE(shared_memory->ShareToProcess(
- base::Process::Current().handle(), &duplicate_handle));
+ EXPECT_TRUE(shared_memory->ShareToProcess(base::GetCurrentProcessHandle(),
+ &duplicate_handle));
EXPECT_TRUE(dispatcher_.OnMessageReceived(
ResourceMsg_SetDataBuffer(request_id, duplicate_handle,
shared_memory->requested_size(), 0)));
@@ -330,8 +326,8 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
request_info.headers = std::string();
request_info.load_flags = 0;
request_info.requestor_pid = 0;
- request_info.request_type = ResourceType::SUB_RESOURCE;
- request_info.appcache_host_id = appcache::kAppCacheNoHostId;
+ request_info.request_type = RESOURCE_TYPE_SUB_RESOURCE;
+ request_info.appcache_host_id = kAppCacheNoHostId;
request_info.routing_id = 0;
request_info.download_to_file = download_to_file;
RequestExtraData extra_data;
@@ -705,7 +701,7 @@ TEST_F(ResourceDispatcherTest, SerializedPostData) {
class TimeConversionTest : public ResourceDispatcherTest,
public RequestPeer {
public:
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
delete msg;
return true;
}
@@ -719,35 +715,29 @@ class TimeConversionTest : public ResourceDispatcherTest,
}
// RequestPeer methods.
- virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE {
- }
+ void OnUploadProgress(uint64 position, uint64 size) override {}
- virtual bool OnReceivedRedirect(const GURL& new_url,
- const GURL& new_first_party_for_cookies,
- const ResourceResponseInfo& info) OVERRIDE {
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) override {
return true;
}
- virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE {
+ void OnReceivedResponse(const ResourceResponseInfo& info) override {
response_info_ = info;
}
- virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE {
- }
+ void OnDownloadedData(int len, int encoded_data_length) override {}
- virtual void OnReceivedData(const char* data,
- int data_length,
- int encoded_data_length) OVERRIDE {
- }
+ void OnReceivedData(const char* data,
+ int data_length,
+ int encoded_data_length) override {}
- virtual void OnCompletedRequest(
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64 total_transfer_size) OVERRIDE {
- }
+ void OnCompletedRequest(int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64 total_transfer_size) override {}
const ResourceResponseInfo& response_info() const { return response_info_; }
@@ -758,7 +748,6 @@ class TimeConversionTest : public ResourceDispatcherTest,
// TODO(simonjam): Enable this when 10829031 lands.
TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) {
ResourceResponseHead response_head;
- response_head.error_code = net::OK;
response_head.request_start = base::TimeTicks::FromInternalValue(5);
response_head.response_start = base::TimeTicks::FromInternalValue(15);
response_head.load_timing.request_start_time = base::Time::Now();
@@ -778,7 +767,6 @@ TEST_F(TimeConversionTest, DISABLED_ProperlyInitialized) {
TEST_F(TimeConversionTest, PartiallyInitialized) {
ResourceResponseHead response_head;
- response_head.error_code = net::OK;
response_head.request_start = base::TimeTicks::FromInternalValue(5);
response_head.response_start = base::TimeTicks::FromInternalValue(15);
@@ -791,7 +779,6 @@ TEST_F(TimeConversionTest, PartiallyInitialized) {
TEST_F(TimeConversionTest, NotInitialized) {
ResourceResponseHead response_head;
- response_head.error_code = net::OK;
PerformTest(response_head);
diff --git a/chromium/content/child/resource_loader_bridge.cc b/chromium/content/child/resource_loader_bridge.cc
new file mode 100644
index 00000000000..dd68ccbbcc6
--- /dev/null
+++ b/chromium/content/child/resource_loader_bridge.cc
@@ -0,0 +1,13 @@
+// Copyright 2014 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 "content/child/resource_loader_bridge.h"
+
+namespace content {
+
+ResourceLoaderBridge::ResourceLoaderBridge() {}
+
+ResourceLoaderBridge::~ResourceLoaderBridge() {}
+
+} // namespace content
diff --git a/chromium/content/child/resource_loader_bridge.h b/chromium/content/child/resource_loader_bridge.h
new file mode 100644
index 00000000000..759f832737b
--- /dev/null
+++ b/chromium/content/child/resource_loader_bridge.h
@@ -0,0 +1,92 @@
+// Copyright 2014 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.
+//
+// The intent of this file is to provide a type-neutral abstraction between
+// Chrome and WebKit for resource loading. This pure-virtual interface is
+// implemented by the embedder.
+//
+// One of these objects will be created by WebKit for each request. WebKit
+// will own the pointer to the bridge, and will delete it when the request is
+// no longer needed.
+//
+// In turn, the bridge's owner on the WebKit end will implement the
+// RequestPeer interface, which we will use to communicate notifications
+// back.
+
+#ifndef CONTENT_CHILD_RESOURCE_LOADER_BRIDGE_H_
+#define CONTENT_CHILD_RESOURCE_LOADER_BRIDGE_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "net/base/request_priority.h"
+
+namespace blink {
+class WebThreadedDataReceiver;
+}
+
+namespace content {
+
+class RequestPeer;
+class ResourceRequestBody;
+struct SyncLoadResponse;
+
+// TODO(tfarina): Refactor code that uses this class. This shouldn't be needed
+// now that it lives in content/.
+class CONTENT_EXPORT ResourceLoaderBridge {
+ public:
+ // use BlinkPlatformImpl::CreateResourceLoader() for construction, but
+ // anybody can delete at any time, INCLUDING during processing of callbacks.
+ virtual ~ResourceLoaderBridge();
+
+ // Call this method before calling Start() to set the request body.
+ // May only be used with HTTP(S) POST requests.
+ virtual void SetRequestBody(ResourceRequestBody* request_body) = 0;
+
+ // Call this method to initiate the request. If this method succeeds, then
+ // the peer's methods will be called asynchronously to report various events.
+ virtual bool Start(RequestPeer* peer) = 0;
+
+ // Call this method to cancel a request that is in progress. This method
+ // causes the request to immediately transition into the 'done' state. The
+ // OnCompletedRequest method will be called asynchronously; this assumes
+ // the peer is still valid.
+ virtual void Cancel() = 0;
+
+ // Call this method to suspend or resume a load that is in progress. This
+ // method may only be called after a successful call to the Start method.
+ virtual void SetDefersLoading(bool value) = 0;
+
+ // Call this method when the priority of the requested resource changes after
+ // Start() has been called. This method may only be called after a successful
+ // call to the Start method.
+ virtual void DidChangePriority(net::RequestPriority new_priority,
+ int intra_priority_value) = 0;
+
+ // Call this method to attach a data receiver which will receive resource data
+ // on its own thread.
+ virtual bool AttachThreadedDataReceiver(
+ blink::WebThreadedDataReceiver* threaded_data_receiver) = 0;
+
+ // Call this method to load the resource synchronously (i.e., in one shot).
+ // This is an alternative to the Start method. Be warned that this method
+ // will block the calling thread until the resource is fully downloaded or an
+ // error occurs. It could block the calling thread for a long time, so only
+ // use this if you really need it! There is also no way for the caller to
+ // interrupt this method. Errors are reported via the status field of the
+ // response parameter.
+ virtual void SyncLoad(SyncLoadResponse* response) = 0;
+
+ protected:
+ // Construction must go through BlinkPlatformImpl::CreateResourceLoader().
+ // For HTTP(S) POST requests, the AppendDataToUpload and AppendFileToUpload
+ // methods may be called to construct the body of the request.
+ ResourceLoaderBridge();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ResourceLoaderBridge);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_RESOURCE_LOADER_BRIDGE_H_
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index 2a67eb1b7e8..891e22b295e 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -5,6 +5,7 @@
#include "content/child/runtime_features.h"
#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
#include "content/common/content_switches_internal.h"
#include "content/public/common/content_switches.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
@@ -13,7 +14,10 @@
#if defined(OS_ANDROID)
#include <cpu-features.h>
#include "base/android/build_info.h"
+#include "base/metrics/field_trial.h"
#include "media/base/android/media_codec_bridge.h"
+#elif defined(OS_WIN)
+#include "base/win/windows_version.h"
#endif
using blink::WebRuntimeFeatures;
@@ -38,9 +42,6 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
(cpu_family == ANDROID_CPU_FAMILY_X86) ||
(cpu_family == ANDROID_CPU_FAMILY_MIPS)));
- // Android supports gamepad API for JellyBean and beyond
- WebRuntimeFeatures::enableGamepad(
- base::android::BuildInfo::GetInstance()->sdk_int() >= 16);
// Android does not have support for PagePopup
WebRuntimeFeatures::enablePagePopup(false);
// Android does not yet support the Web Notification API. crbug.com/115320
@@ -52,13 +53,34 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
WebRuntimeFeatures::enableTouchIconLoading(true);
WebRuntimeFeatures::enableOrientationEvent(true);
WebRuntimeFeatures::enableFastMobileScrolling(true);
+ WebRuntimeFeatures::enableMediaCapture(true);
+ WebRuntimeFeatures::enableCompositedSelectionUpdate(true);
+ // If navigation transitions gets activated via field trial, enable it in
+ // blink. We don't set this to false in case the user has manually enabled
+ // the feature via experimental web platform features.
+ if (base::FieldTrialList::FindFullName("NavigationTransitions") == "Enabled")
+ WebRuntimeFeatures::enableNavigationTransitions(true);
#else
WebRuntimeFeatures::enableNavigatorContentUtils(true);
#endif // defined(OS_ANDROID)
+
+#if !(defined OS_ANDROID || defined OS_CHROMEOS || defined OS_IOS)
+ // Only Android, ChromeOS, and IOS support NetInfo right now.
+ WebRuntimeFeatures::enableNetworkInformation(false);
+#endif
+
+#if defined(OS_WIN)
+ // Screen Orientation API is currently broken on Windows 8 Metro mode and
+ // until we can find how to disable it only for Blink instances running in a
+ // renderer process in Metro, we need to disable the API altogether for Win8.
+ // See http://crbug.com/400846
+ if (base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_WIN8)
+ WebRuntimeFeatures::enableScreenOrientation(false);
+#endif // OS_WIN
}
void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
- const CommandLine& command_line) {
+ const base::CommandLine& command_line) {
if (command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures))
WebRuntimeFeatures::enableExperimentalFeatures(true);
@@ -70,11 +92,8 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kDisableApplicationCache))
WebRuntimeFeatures::enableApplicationCache(false);
- if (command_line.HasSwitch(switches::kDisableDesktopNotifications))
- WebRuntimeFeatures::enableNotifications(false);
-
- if (command_line.HasSwitch(switches::kDisableNavigatorContentUtils))
- WebRuntimeFeatures::enableNavigatorContentUtils(false);
+ if (command_line.HasSwitch(switches::kDisableBlinkScheduler))
+ WebRuntimeFeatures::enableBlinkScheduler(false);
if (command_line.HasSwitch(switches::kDisableLocalStorage))
WebRuntimeFeatures::enableLocalStorage(false);
@@ -89,19 +108,15 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::enableSharedWorker(false);
#if defined(OS_ANDROID)
- if (command_line.HasSwitch(switches::kDisableWebRTC)) {
- WebRuntimeFeatures::enableMediaStream(false);
+ if (command_line.HasSwitch(switches::kDisableWebRTC))
WebRuntimeFeatures::enablePeerConnection(false);
- }
if (!command_line.HasSwitch(switches::kEnableSpeechRecognition))
WebRuntimeFeatures::enableScriptedSpeech(false);
-#endif
- if (command_line.HasSwitch(switches::kEnableServiceWorker))
- WebRuntimeFeatures::enableServiceWorker(true);
+ if (command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures))
+ WebRuntimeFeatures::enableNotifications(true);
-#if defined(OS_ANDROID)
// WebAudio is enabled by default on ARM and X86, if the MediaCodec
// API is available.
WebRuntimeFeatures::enableWebAudio(
@@ -118,9 +133,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kDisablePrefixedEncryptedMedia))
WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
- if (command_line.HasSwitch(switches::kEnableWebAnimationsSVG))
- WebRuntimeFeatures::enableWebAnimationsSVG(true);
-
if (command_line.HasSwitch(switches::kEnableWebMIDI))
WebRuntimeFeatures::enableWebMIDI(true);
@@ -130,8 +142,18 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableExperimentalCanvasFeatures))
WebRuntimeFeatures::enableExperimentalCanvasFeatures(true);
- if (command_line.HasSwitch(switches::kEnableSpeechSynthesis))
- WebRuntimeFeatures::enableSpeechSynthesis(true);
+ if (command_line.HasSwitch(switches::kEnableAcceleratedJpegDecoding))
+ WebRuntimeFeatures::enableDecodeToYUV(true);
+
+ if (command_line.HasSwitch(switches::kDisableDisplayList2dCanvas)) {
+ WebRuntimeFeatures::enableDisplayList2dCanvas(false);
+ } else if (command_line.HasSwitch(switches::kEnableDisplayList2dCanvas)) {
+ WebRuntimeFeatures::enableDisplayList2dCanvas(true);
+ } else {
+ WebRuntimeFeatures::enableDisplayList2dCanvas(
+ base::FieldTrialList::FindFullName("DisplayList2dCanvas") == "Enabled"
+ );
+ }
if (command_line.HasSwitch(switches::kEnableWebGLDraftExtensions))
WebRuntimeFeatures::enableWebGLDraftExtensions(true);
@@ -145,21 +167,6 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (ui::IsOverlayScrollbarEnabled())
WebRuntimeFeatures::enableOverlayScrollbars(true);
- if (command_line.HasSwitch(switches::kEnableFastTextAutosizing))
- WebRuntimeFeatures::enableFastTextAutosizing(true);
-
- if (command_line.HasSwitch(switches::kDisableFastTextAutosizing))
- WebRuntimeFeatures::enableFastTextAutosizing(false);
-
- if (command_line.HasSwitch(switches::kDisableRepaintAfterLayout))
- WebRuntimeFeatures::enableRepaintAfterLayout(false);
-
- if (command_line.HasSwitch(switches::kEnableRepaintAfterLayout))
- WebRuntimeFeatures::enableRepaintAfterLayout(true);
-
- if (command_line.HasSwitch(switches::kEnableTargetedStyleRecalc))
- WebRuntimeFeatures::enableTargetedStyleRecalc(true);
-
if (command_line.HasSwitch(switches::kEnableBleedingEdgeRenderingFastPaths))
WebRuntimeFeatures::enableBleedingEdgeFastPaths(true);
@@ -168,6 +175,22 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableLayerSquashing))
WebRuntimeFeatures::enableLayerSquashing(true);
+
+ if (command_line.HasSwitch(switches::kEnableNetworkInformation) ||
+ command_line.HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ WebRuntimeFeatures::enableNetworkInformation(true);
+ }
+
+ if (command_line.HasSwitch(switches::kEnableCredentialManagerAPI))
+ WebRuntimeFeatures::enableCredentialManagerAPI(true);
+
+ if (command_line.HasSwitch(switches::kEnableViewport))
+ WebRuntimeFeatures::enableCSSViewport(true);
+
+ if (command_line.HasSwitch(switches::kDisableSVG1DOM)) {
+ WebRuntimeFeatures::enableSVG1DOM(false);
+ }
}
} // namespace content
diff --git a/chromium/content/child/service_worker/OWNERS b/chromium/content/child/service_worker/OWNERS
index bac2f14ac4b..c84704de993 100644
--- a/chromium/content/child/service_worker/OWNERS
+++ b/chromium/content/child/service_worker/OWNERS
@@ -1,5 +1,7 @@
michaeln@chromium.org
falken@chromium.org
+horo@chromium.org
+nhiroki@chromium.org
# may not be available
kinuko@chromium.org
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher.cc b/chromium/content/child/service_worker/service_worker_dispatcher.cc
index 936f5c84dc5..7e38a3efd8e 100644
--- a/chromium/content/child/service_worker/service_worker_dispatcher.cc
+++ b/chromium/content/child/service_worker/service_worker_dispatcher.cc
@@ -4,13 +4,16 @@
#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/stl_util.h"
#include "base/threading/thread_local.h"
#include "content/child/child_thread.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_provider_context.h"
+#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/service_worker/web_service_worker_impl.h"
+#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
@@ -51,17 +54,29 @@ ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_AssociateRegistration,
+ OnAssociateRegistration)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DisassociateRegistration,
+ OnDisassociateRegistration)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
OnUnregistered)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetRegistration,
+ OnDidGetRegistration)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
OnRegistrationError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
+ OnUnregistrationError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
+ OnGetRegistrationError)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerStateChanged,
OnServiceWorkerStateChanged)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetWaitingServiceWorker,
- OnSetWaitingServiceWorker)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetCurrentServiceWorker,
- OnSetCurrentServiceWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
+ OnSetVersionAttributes)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
+ OnUpdateFound)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
+ OnSetControllerServiceWorker)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
OnPostMessage)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -77,12 +92,12 @@ void ServiceWorkerDispatcher::RegisterServiceWorker(
int provider_id,
const GURL& pattern,
const GURL& script_url,
- WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
+ WebServiceWorkerRegistrationCallbacks* callbacks) {
DCHECK(callbacks);
if (pattern.possibly_invalid_spec().size() > GetMaxURLChars() ||
script_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
- scoped_ptr<WebServiceWorkerProvider::WebServiceWorkerCallbacks>
+ scoped_ptr<WebServiceWorkerRegistrationCallbacks>
owned_callbacks(callbacks);
scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
@@ -90,7 +105,12 @@ void ServiceWorkerDispatcher::RegisterServiceWorker(
return;
}
- int request_id = pending_callbacks_.Add(callbacks);
+ int request_id = pending_registration_callbacks_.Add(callbacks);
+ TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
+ "ServiceWorkerDispatcher::RegisterServiceWorker",
+ request_id,
+ "Scope", pattern.spec(),
+ "Script URL", script_url.spec());
thread_safe_sender_->Send(new ServiceWorkerHostMsg_RegisterServiceWorker(
CurrentWorkerId(), request_id, provider_id, pattern, script_url));
}
@@ -98,11 +118,11 @@ void ServiceWorkerDispatcher::RegisterServiceWorker(
void ServiceWorkerDispatcher::UnregisterServiceWorker(
int provider_id,
const GURL& pattern,
- WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks) {
+ WebServiceWorkerUnregistrationCallbacks* callbacks) {
DCHECK(callbacks);
if (pattern.possibly_invalid_spec().size() > GetMaxURLChars()) {
- scoped_ptr<WebServiceWorkerProvider::WebServiceWorkerCallbacks>
+ scoped_ptr<WebServiceWorkerUnregistrationCallbacks>
owned_callbacks(callbacks);
scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
@@ -110,11 +130,39 @@ void ServiceWorkerDispatcher::UnregisterServiceWorker(
return;
}
- int request_id = pending_callbacks_.Add(callbacks);
+ int request_id = pending_unregistration_callbacks_.Add(callbacks);
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerDispatcher::UnregisterServiceWorker",
+ request_id,
+ "Scope", pattern.spec());
thread_safe_sender_->Send(new ServiceWorkerHostMsg_UnregisterServiceWorker(
CurrentWorkerId(), request_id, provider_id, pattern));
}
+void ServiceWorkerDispatcher::GetRegistration(
+ int provider_id,
+ const GURL& document_url,
+ WebServiceWorkerRegistrationCallbacks* callbacks) {
+ DCHECK(callbacks);
+
+ if (document_url.possibly_invalid_spec().size() > GetMaxURLChars()) {
+ scoped_ptr<WebServiceWorkerRegistrationCallbacks>
+ owned_callbacks(callbacks);
+ scoped_ptr<WebServiceWorkerError> error(new WebServiceWorkerError(
+ WebServiceWorkerError::ErrorTypeSecurity, "URL too long"));
+ callbacks->onError(error.release());
+ return;
+ }
+
+ int request_id = pending_get_registration_callbacks_.Add(callbacks);
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerDispatcher::GetRegistration",
+ request_id,
+ "Document URL", document_url.spec());
+ thread_safe_sender_->Send(new ServiceWorkerHostMsg_GetRegistration(
+ CurrentWorkerId(), request_id, provider_id, document_url));
+}
+
void ServiceWorkerDispatcher::AddProviderContext(
ServiceWorkerProviderContext* provider_context) {
DCHECK(provider_context);
@@ -128,8 +176,10 @@ void ServiceWorkerDispatcher::RemoveProviderContext(
DCHECK(provider_context);
DCHECK(ContainsKey(provider_contexts_, provider_context->provider_id()));
provider_contexts_.erase(provider_context->provider_id());
+ worker_to_provider_.erase(provider_context->installing_handle_id());
worker_to_provider_.erase(provider_context->waiting_handle_id());
- worker_to_provider_.erase(provider_context->current_handle_id());
+ worker_to_provider_.erase(provider_context->active_handle_id());
+ worker_to_provider_.erase(provider_context->controller_handle_id());
}
void ServiceWorkerDispatcher::AddScriptClient(
@@ -186,44 +236,153 @@ WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
if (adopt_handle) {
// We are instructed to adopt a handle but we already have one, so
// adopt and destroy a handle ref.
- ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_);
+ ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
}
return existing_worker->second;
}
scoped_ptr<ServiceWorkerHandleReference> handle_ref =
adopt_handle
- ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_)
- : ServiceWorkerHandleReference::Create(info, thread_safe_sender_);
+ ? ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get())
+ : ServiceWorkerHandleReference::Create(info,
+ thread_safe_sender_.get());
// WebServiceWorkerImpl constructor calls AddServiceWorker.
- return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_);
+ return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_.get());
+}
+
+WebServiceWorkerRegistrationImpl*
+ServiceWorkerDispatcher::FindServiceWorkerRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ bool adopt_handle) {
+ RegistrationObjectMap::iterator registration =
+ registrations_.find(info.handle_id);
+ if (registration == registrations_.end())
+ return NULL;
+ if (adopt_handle) {
+ // We are instructed to adopt a handle but we already have one, so
+ // adopt and destroy a handle ref.
+ ServiceWorkerRegistrationHandleReference::Adopt(
+ info, thread_safe_sender_.get());
+ }
+ return registration->second;
+}
+
+WebServiceWorkerRegistrationImpl*
+ServiceWorkerDispatcher::CreateServiceWorkerRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ bool adopt_handle) {
+ DCHECK(!FindServiceWorkerRegistration(info, adopt_handle));
+ if (info.handle_id == kInvalidServiceWorkerRegistrationHandleId)
+ return NULL;
+
+ scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
+ adopt_handle ? ServiceWorkerRegistrationHandleReference::Adopt(
+ info, thread_safe_sender_.get())
+ : ServiceWorkerRegistrationHandleReference::Create(
+ info, thread_safe_sender_.get());
+
+ // WebServiceWorkerRegistrationImpl constructor calls
+ // AddServiceWorkerRegistration.
+ return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
+}
+
+void ServiceWorkerDispatcher::OnAssociateRegistration(
+ int thread_id,
+ int provider_id,
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs) {
+ ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
+ if (provider == provider_contexts_.end())
+ return;
+ provider->second->OnAssociateRegistration(info, attrs);
+ if (attrs.installing.handle_id != kInvalidServiceWorkerHandleId)
+ worker_to_provider_[attrs.installing.handle_id] = provider->second;
+ if (attrs.waiting.handle_id != kInvalidServiceWorkerHandleId)
+ worker_to_provider_[attrs.waiting.handle_id] = provider->second;
+ if (attrs.active.handle_id != kInvalidServiceWorkerHandleId)
+ worker_to_provider_[attrs.active.handle_id] = provider->second;
+}
+
+void ServiceWorkerDispatcher::OnDisassociateRegistration(
+ int thread_id,
+ int provider_id) {
+ ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
+ if (provider == provider_contexts_.end())
+ return;
+ provider->second->OnDisassociateRegistration();
+ worker_to_provider_.erase(provider->second->installing_handle_id());
+ worker_to_provider_.erase(provider->second->waiting_handle_id());
+ worker_to_provider_.erase(provider->second->active_handle_id());
+ worker_to_provider_.erase(provider->second->controller_handle_id());
}
void ServiceWorkerDispatcher::OnRegistered(
int thread_id,
int request_id,
- const ServiceWorkerObjectInfo& info) {
- WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
- pending_callbacks_.Lookup(request_id);
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs) {
+ TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+ "ServiceWorkerDispatcher::RegisterServiceWorker",
+ request_id,
+ "OnRegistered");
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerDispatcher::RegisterServiceWorker",
+ request_id);
+ WebServiceWorkerRegistrationCallbacks* callbacks =
+ pending_registration_callbacks_.Lookup(request_id);
DCHECK(callbacks);
if (!callbacks)
return;
- callbacks->onSuccess(GetServiceWorker(info, true));
- pending_callbacks_.Remove(request_id);
+ callbacks->onSuccess(FindOrCreateRegistration(info, attrs));
+ pending_registration_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerDispatcher::OnUnregistered(int thread_id,
+ int request_id,
+ bool is_success) {
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "ServiceWorker",
+ "ServiceWorkerDispatcher::UnregisterServiceWorker",
+ request_id,
+ "OnUnregistered");
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerDispatcher::UnregisterServiceWorker",
+ request_id);
+ WebServiceWorkerUnregistrationCallbacks* callbacks =
+ pending_unregistration_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+ callbacks->onSuccess(&is_success);
+ pending_unregistration_callbacks_.Remove(request_id);
}
-void ServiceWorkerDispatcher::OnUnregistered(
+void ServiceWorkerDispatcher::OnDidGetRegistration(
int thread_id,
- int request_id) {
- WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
- pending_callbacks_.Lookup(request_id);
+ int request_id,
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs) {
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "ServiceWorker",
+ "ServiceWorkerDispatcher::GetRegistration",
+ request_id,
+ "OnDidGetRegistration");
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerDispatcher::GetRegistration",
+ request_id);
+ WebServiceWorkerRegistrationCallbacks* callbacks =
+ pending_get_registration_callbacks_.Lookup(request_id);
DCHECK(callbacks);
if (!callbacks)
return;
- callbacks->onSuccess(NULL);
- pending_callbacks_.Remove(request_id);
+ WebServiceWorkerRegistrationImpl* registration = NULL;
+ if (info.handle_id != kInvalidServiceWorkerHandleId)
+ registration = FindOrCreateRegistration(info, attrs);
+
+ callbacks->onSuccess(registration);
+ pending_get_registration_callbacks_.Remove(request_id);
}
void ServiceWorkerDispatcher::OnRegistrationError(
@@ -231,8 +390,65 @@ void ServiceWorkerDispatcher::OnRegistrationError(
int request_id,
WebServiceWorkerError::ErrorType error_type,
const base::string16& message) {
- WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
- pending_callbacks_.Lookup(request_id);
+ TRACE_EVENT_ASYNC_STEP_INTO0("ServiceWorker",
+ "ServiceWorkerDispatcher::RegisterServiceWorker",
+ request_id,
+ "OnRegistrationError");
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerDispatcher::RegisterServiceWorker",
+ request_id);
+ WebServiceWorkerRegistrationCallbacks* callbacks =
+ pending_registration_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ scoped_ptr<WebServiceWorkerError> error(
+ new WebServiceWorkerError(error_type, message));
+ callbacks->onError(error.release());
+ pending_registration_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerDispatcher::OnUnregistrationError(
+ int thread_id,
+ int request_id,
+ WebServiceWorkerError::ErrorType error_type,
+ const base::string16& message) {
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "ServiceWorker",
+ "ServiceWorkerDispatcher::UnregisterServiceWorker",
+ request_id,
+ "OnUnregistrationError");
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerDispatcher::UnregisterServiceWorker",
+ request_id);
+ WebServiceWorkerUnregistrationCallbacks* callbacks =
+ pending_unregistration_callbacks_.Lookup(request_id);
+ DCHECK(callbacks);
+ if (!callbacks)
+ return;
+
+ scoped_ptr<WebServiceWorkerError> error(
+ new WebServiceWorkerError(error_type, message));
+ callbacks->onError(error.release());
+ pending_unregistration_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerDispatcher::OnGetRegistrationError(
+ int thread_id,
+ int request_id,
+ WebServiceWorkerError::ErrorType error_type,
+ const base::string16& message) {
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "ServiceWorker",
+ "ServiceWorkerDispatcher::GetRegistration",
+ request_id,
+ "OnGetRegistrationError");
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "ServiceWorkerDispatcher::GetRegistration",
+ request_id);
+ WebServiceWorkerGetRegistrationCallbacks* callbacks =
+ pending_get_registration_callbacks_.Lookup(request_id);
DCHECK(callbacks);
if (!callbacks)
return;
@@ -240,13 +456,17 @@ void ServiceWorkerDispatcher::OnRegistrationError(
scoped_ptr<WebServiceWorkerError> error(
new WebServiceWorkerError(error_type, message));
callbacks->onError(error.release());
- pending_callbacks_.Remove(request_id);
+ pending_get_registration_callbacks_.Remove(request_id);
}
void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
int thread_id,
int handle_id,
blink::WebServiceWorkerState state) {
+ TRACE_EVENT2("ServiceWorker",
+ "ServiceWorkerDispatcher::OnServiceWorkerStateChanged",
+ "Thread ID", thread_id,
+ "State", state);
WorkerObjectMap::iterator worker = service_workers_.find(handle_id);
if (worker != service_workers_.end())
worker->second->OnStateChanged(state);
@@ -256,12 +476,81 @@ void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
provider->second->OnServiceWorkerStateChanged(handle_id, state);
}
-void ServiceWorkerDispatcher::OnSetWaitingServiceWorker(
+void ServiceWorkerDispatcher::OnSetVersionAttributes(
+ int thread_id,
+ int provider_id,
+ int registration_handle_id,
+ int changed_mask,
+ const ServiceWorkerVersionAttributes& attributes) {
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerDispatcher::OnSetVersionAttributes",
+ "Thread ID", thread_id);
+ ChangedVersionAttributesMask mask(changed_mask);
+ if (mask.installing_changed()) {
+ SetInstallingServiceWorker(provider_id,
+ registration_handle_id,
+ attributes.installing);
+ }
+ if (mask.waiting_changed()) {
+ SetWaitingServiceWorker(provider_id,
+ registration_handle_id,
+ attributes.waiting);
+ }
+ if (mask.active_changed()) {
+ SetActiveServiceWorker(provider_id,
+ registration_handle_id,
+ attributes.active);
+ SetReadyRegistration(provider_id, registration_handle_id);
+ }
+}
+
+void ServiceWorkerDispatcher::OnUpdateFound(
int thread_id,
+ const ServiceWorkerRegistrationObjectInfo& info) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcher::OnUpdateFound");
+ RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
+ if (found != registrations_.end())
+ found->second->OnUpdateFound();
+}
+
+void ServiceWorkerDispatcher::SetInstallingServiceWorker(
int provider_id,
+ int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
- if (provider != provider_contexts_.end()) {
+ if (provider != provider_contexts_.end() &&
+ provider->second->registration_handle_id() == registration_handle_id) {
+ int existing_installing_id = provider->second->installing_handle_id();
+ if (existing_installing_id != info.handle_id &&
+ existing_installing_id != kInvalidServiceWorkerHandleId) {
+ WorkerToProviderMap::iterator associated_provider =
+ worker_to_provider_.find(existing_installing_id);
+ DCHECK(associated_provider != worker_to_provider_.end());
+ DCHECK(associated_provider->second->provider_id() == provider_id);
+ worker_to_provider_.erase(associated_provider);
+ }
+ provider->second->OnSetInstallingServiceWorker(
+ registration_handle_id, info);
+ if (info.handle_id != kInvalidServiceWorkerHandleId)
+ worker_to_provider_[info.handle_id] = provider->second;
+ }
+
+ RegistrationObjectMap::iterator found =
+ registrations_.find(registration_handle_id);
+ if (found != registrations_.end()) {
+ // Populate the .installing field with the new worker object.
+ found->second->SetInstalling(GetServiceWorker(info, false));
+ }
+}
+
+void ServiceWorkerDispatcher::SetWaitingServiceWorker(
+ int provider_id,
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info) {
+ ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
+ if (provider != provider_contexts_.end() &&
+ provider->second->registration_handle_id() == registration_handle_id) {
int existing_waiting_id = provider->second->waiting_handle_id();
if (existing_waiting_id != info.handle_id &&
existing_waiting_id != kInvalidServiceWorkerHandleId) {
@@ -271,25 +560,91 @@ void ServiceWorkerDispatcher::OnSetWaitingServiceWorker(
DCHECK(associated_provider->second->provider_id() == provider_id);
worker_to_provider_.erase(associated_provider);
}
- provider->second->OnSetWaitingServiceWorker(provider_id, info);
+ provider->second->OnSetWaitingServiceWorker(registration_handle_id, info);
if (info.handle_id != kInvalidServiceWorkerHandleId)
worker_to_provider_[info.handle_id] = provider->second;
}
- ScriptClientMap::iterator found = script_clients_.find(provider_id);
- if (found != script_clients_.end()) {
+ RegistrationObjectMap::iterator found =
+ registrations_.find(registration_handle_id);
+ if (found != registrations_.end()) {
// Populate the .waiting field with the new worker object.
- found->second->setWaiting(GetServiceWorker(info, false));
+ found->second->SetWaiting(GetServiceWorker(info, false));
+ }
+}
+
+void ServiceWorkerDispatcher::SetActiveServiceWorker(
+ int provider_id,
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info) {
+ ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
+ if (provider != provider_contexts_.end() &&
+ provider->second->registration_handle_id() == registration_handle_id) {
+ int existing_active_id = provider->second->active_handle_id();
+ if (existing_active_id != info.handle_id &&
+ existing_active_id != kInvalidServiceWorkerHandleId) {
+ WorkerToProviderMap::iterator associated_provider =
+ worker_to_provider_.find(existing_active_id);
+ DCHECK(associated_provider != worker_to_provider_.end());
+ DCHECK(associated_provider->second->provider_id() == provider_id);
+ worker_to_provider_.erase(associated_provider);
+ }
+ provider->second->OnSetActiveServiceWorker(registration_handle_id, info);
+ if (info.handle_id != kInvalidServiceWorkerHandleId)
+ worker_to_provider_[info.handle_id] = provider->second;
+ }
+
+ RegistrationObjectMap::iterator found =
+ registrations_.find(registration_handle_id);
+ if (found != registrations_.end()) {
+ // Populate the .active field with the new worker object.
+ found->second->SetActive(GetServiceWorker(info, false));
+ }
+}
+
+void ServiceWorkerDispatcher::SetReadyRegistration(
+ int provider_id,
+ int registration_handle_id) {
+ ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
+ if (provider == provider_contexts_.end() ||
+ provider->second->registration_handle_id() != registration_handle_id ||
+ provider->second->active_handle_id() == kInvalidServiceWorkerHandleId) {
+ return;
+ }
+
+ ScriptClientMap::iterator client = script_clients_.find(provider_id);
+ if (client == script_clients_.end())
+ return;
+
+ ServiceWorkerRegistrationObjectInfo info =
+ provider->second->registration()->info();
+ WebServiceWorkerRegistrationImpl* registration =
+ FindServiceWorkerRegistration(info, false);
+ if (!registration) {
+ registration = CreateServiceWorkerRegistration(info, false);
+ ServiceWorkerVersionAttributes attrs =
+ provider->second->GetVersionAttributes();
+ registration->SetInstalling(GetServiceWorker(attrs.installing, false));
+ registration->SetWaiting(GetServiceWorker(attrs.waiting, false));
+ registration->SetActive(GetServiceWorker(attrs.active, false));
}
+
+ // Resolve the .ready promise with the registration object.
+ client->second->setReadyRegistration(registration);
}
-void ServiceWorkerDispatcher::OnSetCurrentServiceWorker(
+void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
int thread_id,
int provider_id,
const ServiceWorkerObjectInfo& info) {
+ TRACE_EVENT2("ServiceWorker",
+ "ServiceWorkerDispatcher::OnSetControllerServiceWorker",
+ "Thread ID", thread_id,
+ "Provider ID", provider_id);
ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
if (provider != provider_contexts_.end()) {
- provider->second->OnSetCurrentServiceWorker(provider_id, info);
+ provider->second->OnSetControllerServiceWorker(
+ provider->second->registration_handle_id(), info);
worker_to_provider_[info.handle_id] = provider->second;
}
@@ -309,6 +664,9 @@ void ServiceWorkerDispatcher::OnPostMessage(
// Make sure we're on the main document thread. (That must be the only
// thread we get this message)
DCHECK(ChildThread::current());
+ TRACE_EVENT1("ServiceWorker",
+ "ServiceWorkerDispatcher::OnPostMessage",
+ "Thread ID", thread_id);
ScriptClientMap::iterator found = script_clients_.find(provider_id);
if (found == script_clients_.end()) {
@@ -341,4 +699,41 @@ void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
service_workers_.erase(handle_id);
}
+void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
+ int registration_handle_id,
+ WebServiceWorkerRegistrationImpl* registration) {
+ DCHECK(!ContainsKey(registrations_, registration_handle_id));
+ registrations_[registration_handle_id] = registration;
+}
+
+void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
+ int registration_handle_id) {
+ DCHECK(ContainsKey(registrations_, registration_handle_id));
+ registrations_.erase(registration_handle_id);
+}
+
+WebServiceWorkerRegistrationImpl*
+ServiceWorkerDispatcher::FindOrCreateRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs) {
+ WebServiceWorkerRegistrationImpl* registration =
+ FindServiceWorkerRegistration(info, true);
+ if (!registration) {
+ registration = CreateServiceWorkerRegistration(info, true);
+ registration->SetInstalling(GetServiceWorker(attrs.installing, true));
+ registration->SetWaiting(GetServiceWorker(attrs.waiting, true));
+ registration->SetActive(GetServiceWorker(attrs.active, true));
+ } else {
+ // |registration| must already have version attributes, so adopt and destroy
+ // handle refs for them.
+ ServiceWorkerHandleReference::Adopt(
+ attrs.installing, thread_safe_sender_.get());
+ ServiceWorkerHandleReference::Adopt(
+ attrs.waiting, thread_safe_sender_.get());
+ ServiceWorkerHandleReference::Adopt(
+ attrs.active, thread_safe_sender_.get());
+ }
+ return registration;
+}
+
} // namespace content
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher.h b/chromium/content/child/service_worker/service_worker_dispatcher.h
index 84ea3874933..2d01452fa69 100644
--- a/chromium/content/child/service_worker/service_worker_dispatcher.h
+++ b/chromium/content/child/service_worker/service_worker_dispatcher.h
@@ -29,18 +29,30 @@ class Message;
namespace content {
class ServiceWorkerMessageFilter;
-struct ServiceWorkerObjectInfo;
class ServiceWorkerProviderContext;
class ThreadSafeSender;
class WebServiceWorkerImpl;
+class WebServiceWorkerRegistrationImpl;
+struct ServiceWorkerObjectInfo;
+struct ServiceWorkerRegistrationObjectInfo;
+struct ServiceWorkerVersionAttributes;
// This class manages communication with the browser process about
// registration of the service worker, exposed to renderer and worker
// scripts through methods like navigator.registerServiceWorker().
class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
public:
+ typedef blink::WebServiceWorkerProvider::WebServiceWorkerRegistrationCallbacks
+ WebServiceWorkerRegistrationCallbacks;
+ typedef
+ blink::WebServiceWorkerProvider::WebServiceWorkerUnregistrationCallbacks
+ WebServiceWorkerUnregistrationCallbacks;
+ typedef
+ blink::WebServiceWorkerProvider::WebServiceWorkerGetRegistrationCallbacks
+ WebServiceWorkerGetRegistrationCallbacks;
+
explicit ServiceWorkerDispatcher(ThreadSafeSender* thread_safe_sender);
- virtual ~ServiceWorkerDispatcher();
+ ~ServiceWorkerDispatcher() override;
void OnMessageReceived(const IPC::Message& msg);
bool Send(IPC::Message* msg);
@@ -50,12 +62,17 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
int provider_id,
const GURL& pattern,
const GURL& script_url,
- blink::WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks);
+ WebServiceWorkerRegistrationCallbacks* callbacks);
// Corresponds to navigator.serviceWorker.unregister()
void UnregisterServiceWorker(
int provider_id,
const GURL& pattern,
- blink::WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks);
+ WebServiceWorkerUnregistrationCallbacks* callbacks);
+ // Corresponds to navigator.serviceWorker.getRegistration()
+ void GetRegistration(
+ int provider_id,
+ const GURL& document_url,
+ WebServiceWorkerRegistrationCallbacks* callbacks);
// Called when a new provider context for a document is created. Usually
// this happens when a new document is being loaded, and is called much
@@ -83,8 +100,25 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
// WebServiceWorkerImpl, in which case ownership is transferred to
// the caller who must bounce it to a method that will associate it
// with a WebCore::ServiceWorker.
- WebServiceWorkerImpl* GetServiceWorker(const ServiceWorkerObjectInfo&,
- bool adopt_handle);
+ WebServiceWorkerImpl* GetServiceWorker(
+ const ServiceWorkerObjectInfo& info,
+ bool adopt_handle);
+
+ // Finds a WebServiceWorkerRegistrationImpl for the specified registration.
+ // If it's not found, returns NULL. If |adopt_handle| is true,
+ // a ServiceWorkerRegistrationHandleReference will be adopted for the
+ // registration.
+ WebServiceWorkerRegistrationImpl* FindServiceWorkerRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ bool adopt_handle);
+
+ // Creates a WebServiceWorkerRegistrationImpl for the specified registration
+ // and transfers its ownership to the caller. If |adopt_handle| is true, a
+ // ServiceWorkerRegistrationHandleReference will be adopted for the
+ // registration.
+ WebServiceWorkerRegistrationImpl* CreateServiceWorkerRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ bool adopt_handle);
// |thread_safe_sender| needs to be passed in because if the call leads to
// construction it will be needed.
@@ -96,50 +130,112 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
static ServiceWorkerDispatcher* GetThreadSpecificInstance();
private:
- typedef IDMap<blink::WebServiceWorkerProvider::WebServiceWorkerCallbacks,
- IDMapOwnPointer> CallbackMap;
+ typedef IDMap<WebServiceWorkerRegistrationCallbacks,
+ IDMapOwnPointer> RegistrationCallbackMap;
+ typedef IDMap<WebServiceWorkerUnregistrationCallbacks,
+ IDMapOwnPointer> UnregistrationCallbackMap;
+ typedef IDMap<WebServiceWorkerGetRegistrationCallbacks,
+ IDMapOwnPointer> GetRegistrationCallbackMap;
typedef std::map<int, blink::WebServiceWorkerProviderClient*> ScriptClientMap;
typedef std::map<int, ServiceWorkerProviderContext*> ProviderContextMap;
typedef std::map<int, WebServiceWorkerImpl*> WorkerObjectMap;
typedef std::map<int, ServiceWorkerProviderContext*> WorkerToProviderMap;
+ typedef std::map<int, WebServiceWorkerRegistrationImpl*>
+ RegistrationObjectMap;
friend class WebServiceWorkerImpl;
+ friend class WebServiceWorkerRegistrationImpl;
// WorkerTaskRunner::Observer implementation.
- virtual void OnWorkerRunLoopStopped() OVERRIDE;
-
+ void OnWorkerRunLoopStopped() override;
+
+ void OnAssociateRegistration(int thread_id,
+ int provider_id,
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs);
+ void OnDisassociateRegistration(int thread_id,
+ int provider_id);
void OnRegistered(int thread_id,
int request_id,
- const ServiceWorkerObjectInfo& info);
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs);
void OnUnregistered(int thread_id,
- int request_id);
+ int request_id,
+ bool is_success);
+ void OnDidGetRegistration(int thread_id,
+ int request_id,
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs);
void OnRegistrationError(int thread_id,
int request_id,
blink::WebServiceWorkerError::ErrorType error_type,
const base::string16& message);
+ void OnUnregistrationError(int thread_id,
+ int request_id,
+ blink::WebServiceWorkerError::ErrorType error_type,
+ const base::string16& message);
+ void OnGetRegistrationError(
+ int thread_id,
+ int request_id,
+ blink::WebServiceWorkerError::ErrorType error_type,
+ const base::string16& message);
void OnServiceWorkerStateChanged(int thread_id,
int handle_id,
blink::WebServiceWorkerState state);
- void OnSetWaitingServiceWorker(int thread_id,
- int provider_id,
- const ServiceWorkerObjectInfo& info);
- void OnSetCurrentServiceWorker(int thread_id,
- int provider_id,
- const ServiceWorkerObjectInfo& info);
+ void OnSetVersionAttributes(int thread_id,
+ int provider_id,
+ int registration_handle_id,
+ int changed_mask,
+ const ServiceWorkerVersionAttributes& attributes);
+ void OnUpdateFound(int thread_id,
+ const ServiceWorkerRegistrationObjectInfo& info);
+ void OnSetControllerServiceWorker(int thread_id,
+ int provider_id,
+ const ServiceWorkerObjectInfo& info);
void OnPostMessage(int thread_id,
int provider_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids,
const std::vector<int>& new_routing_ids);
+ void SetInstallingServiceWorker(
+ int provider_id,
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info);
+ void SetWaitingServiceWorker(
+ int provider_id,
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info);
+ void SetActiveServiceWorker(
+ int provider_id,
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info);
+ void SetReadyRegistration(
+ int provider_id,
+ int registration_handle_id);
+
// Keeps map from handle_id to ServiceWorker object.
void AddServiceWorker(int handle_id, WebServiceWorkerImpl* worker);
void RemoveServiceWorker(int handle_id);
- CallbackMap pending_callbacks_;
+ // Keeps map from registration_handle_id to ServiceWorkerRegistration object.
+ void AddServiceWorkerRegistration(
+ int registration_handle_id,
+ WebServiceWorkerRegistrationImpl* registration);
+ void RemoveServiceWorkerRegistration(
+ int registration_handle_id);
+
+ WebServiceWorkerRegistrationImpl* FindOrCreateRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs);
+
+ RegistrationCallbackMap pending_registration_callbacks_;
+ UnregistrationCallbackMap pending_unregistration_callbacks_;
+ GetRegistrationCallbackMap pending_get_registration_callbacks_;
ScriptClientMap script_clients_;
ProviderContextMap provider_contexts_;
WorkerObjectMap service_workers_;
+ RegistrationObjectMap registrations_;
// A map for ServiceWorkers that are associated to a particular document
// (e.g. as .current).
diff --git a/chromium/content/child/service_worker/service_worker_handle_reference.h b/chromium/content/child/service_worker/service_worker_handle_reference.h
index 0393e55aa96..d70d665c625 100644
--- a/chromium/content/child/service_worker/service_worker_handle_reference.h
+++ b/chromium/content/child/service_worker/service_worker_handle_reference.h
@@ -39,6 +39,7 @@ class ServiceWorkerHandleReference {
const GURL& url() const { return info_.url; }
blink::WebServiceWorkerState state() const { return info_.state; }
void set_state(blink::WebServiceWorkerState state) { info_.state = state; }
+ int64 version_id() const { return info_.version_id; }
private:
ServiceWorkerHandleReference(const ServiceWorkerObjectInfo& info,
diff --git a/chromium/content/child/service_worker/service_worker_message_filter.cc b/chromium/content/child/service_worker/service_worker_message_filter.cc
index 71632f765d3..72cf320084a 100644
--- a/chromium/content/child/service_worker/service_worker_message_filter.cc
+++ b/chromium/content/child/service_worker/service_worker_message_filter.cc
@@ -9,6 +9,7 @@
#include "content/child/thread_safe_sender.h"
#include "content/child/worker_thread_task_runner.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "ipc/ipc_message_macros.h"
namespace content {
@@ -18,7 +19,7 @@ namespace {
// Sends a ServiceWorkerObjectDestroyed message to the browser so it can delete
// the ServiceWorker handle.
void SendServiceWorkerObjectDestroyed(
- scoped_refptr<ThreadSafeSender> sender,
+ ThreadSafeSender* sender,
int handle_id) {
if (handle_id == kInvalidServiceWorkerHandleId)
return;
@@ -26,6 +27,15 @@ void SendServiceWorkerObjectDestroyed(
new ServiceWorkerHostMsg_DecrementServiceWorkerRefCount(handle_id));
}
+void SendRegistrationObjectDestroyed(
+ ThreadSafeSender* sender,
+ int handle_id) {
+ if (handle_id == kInvalidServiceWorkerRegistrationHandleId)
+ return;
+ sender->Send(
+ new ServiceWorkerHostMsg_DecrementRegistrationRefCount(handle_id));
+}
+
} // namespace
ServiceWorkerMessageFilter::ServiceWorkerMessageFilter(ThreadSafeSender* sender)
@@ -61,25 +71,48 @@ void ServiceWorkerMessageFilter::OnStaleMessageReceived(
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerMessageFilter, msg)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered,
OnStaleRegistered)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetWaitingServiceWorker,
- OnStaleSetServiceWorker)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetCurrentServiceWorker,
- OnStaleSetServiceWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
+ OnStaleSetVersionAttributes)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetControllerServiceWorker,
+ OnStaleSetControllerServiceWorker)
IPC_END_MESSAGE_MAP()
}
void ServiceWorkerMessageFilter::OnStaleRegistered(
int thread_id,
int request_id,
- const ServiceWorkerObjectInfo& info) {
- SendServiceWorkerObjectDestroyed(thread_safe_sender_, info.handle_id);
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs) {
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(),
+ attrs.installing.handle_id);
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(),
+ attrs.waiting.handle_id);
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(),
+ attrs.active.handle_id);
+ SendRegistrationObjectDestroyed(thread_safe_sender_.get(), info.handle_id);
+}
+
+void ServiceWorkerMessageFilter::OnStaleSetVersionAttributes(
+ int thread_id,
+ int provider_id,
+ int registration_handle_id,
+ int changed_mask,
+ const ServiceWorkerVersionAttributes& attrs) {
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(),
+ attrs.installing.handle_id);
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(),
+ attrs.waiting.handle_id);
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(),
+ attrs.active.handle_id);
+ SendRegistrationObjectDestroyed(thread_safe_sender_.get(),
+ registration_handle_id);
}
-void ServiceWorkerMessageFilter::OnStaleSetServiceWorker(
+void ServiceWorkerMessageFilter::OnStaleSetControllerServiceWorker(
int thread_id,
int provider_id,
const ServiceWorkerObjectInfo& info) {
- SendServiceWorkerObjectDestroyed(thread_safe_sender_, info.handle_id);
+ SendServiceWorkerObjectDestroyed(thread_safe_sender_.get(), info.handle_id);
}
} // namespace content
diff --git a/chromium/content/child/service_worker/service_worker_message_filter.h b/chromium/content/child/service_worker/service_worker_message_filter.h
index d9b40848549..8581f8de588 100644
--- a/chromium/content/child/service_worker/service_worker_message_filter.h
+++ b/chromium/content/child/service_worker/service_worker_message_filter.h
@@ -14,8 +14,10 @@ class MessageLoopProxy;
namespace content {
-struct ServiceWorkerObjectInfo;
class ThreadSafeSender;
+struct ServiceWorkerObjectInfo;
+struct ServiceWorkerRegistrationObjectInfo;
+struct ServiceWorkerVersionAttributes;
class CONTENT_EXPORT ServiceWorkerMessageFilter
: public NON_EXPORTED_BASE(ChildMessageFilter) {
@@ -23,22 +25,31 @@ class CONTENT_EXPORT ServiceWorkerMessageFilter
explicit ServiceWorkerMessageFilter(ThreadSafeSender* thread_safe_sender);
protected:
- virtual ~ServiceWorkerMessageFilter();
+ ~ServiceWorkerMessageFilter() override;
private:
// ChildMessageFilter implementation:
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnStaleMessageReceived(const IPC::Message& msg) OVERRIDE;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnStaleMessageReceived(const IPC::Message& msg) override;
// Message handlers for stale messages.
- void OnStaleRegistered(int thread_id,
- int request_id,
- const ServiceWorkerObjectInfo& info);
- void OnStaleSetServiceWorker(int thread_id,
- int provider_id,
- const ServiceWorkerObjectInfo& info);
+ void OnStaleRegistered(
+ int thread_id,
+ int request_id,
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs);
+ void OnStaleSetVersionAttributes(
+ int thread_id,
+ int provider_id,
+ int registration_handle_id,
+ int changed_mask,
+ const ServiceWorkerVersionAttributes& attrs);
+ void OnStaleSetControllerServiceWorker(
+ int thread_id,
+ int provider_id,
+ const ServiceWorkerObjectInfo& info);
scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
diff --git a/chromium/content/child/service_worker/service_worker_network_provider.h b/chromium/content/child/service_worker/service_worker_network_provider.h
index 0d6f494421e..85030c390de 100644
--- a/chromium/content/child/service_worker/service_worker_network_provider.h
+++ b/chromium/content/child/service_worker/service_worker_network_provider.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_NETWORK_PROVIDER_IMPL_H_
-#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_NETWORK_PROVIDER_IMPL_H_
+#ifndef CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_NETWORK_PROVIDER_H_
+#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_NETWORK_PROVIDER_H_
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
@@ -37,7 +37,7 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider
base::SupportsUserData* document_state);
ServiceWorkerNetworkProvider();
- virtual ~ServiceWorkerNetworkProvider();
+ ~ServiceWorkerNetworkProvider() override;
int provider_id() const { return provider_id_; }
ServiceWorkerProviderContext* context() { return context_.get(); }
@@ -55,4 +55,4 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider
} // namespace content
-#endif // CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_PROVIDER_IMPL_H_
+#endif // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_NETWORK_PROVIDER_H_
diff --git a/chromium/content/child/service_worker/service_worker_provider_context.cc b/chromium/content/child/service_worker/service_worker_provider_context.cc
index 246a19c5c6f..cb86fa56050 100644
--- a/chromium/content/child/service_worker/service_worker_provider_context.cc
+++ b/chromium/content/child/service_worker/service_worker_provider_context.cc
@@ -10,6 +10,7 @@
#include "content/child/child_thread.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
+#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/worker_task_runner.h"
#include "content/common/service_worker/service_worker_messages.h"
@@ -24,7 +25,7 @@ ServiceWorkerProviderContext::ServiceWorkerProviderContext(int provider_id)
thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
- thread_safe_sender_);
+ thread_safe_sender_.get());
DCHECK(dispatcher);
dispatcher->AddProviderContext(this);
}
@@ -36,25 +37,79 @@ ServiceWorkerProviderContext::~ServiceWorkerProviderContext() {
}
}
+ServiceWorkerHandleReference* ServiceWorkerProviderContext::installing() {
+ DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
+ return installing_.get();
+}
+
ServiceWorkerHandleReference* ServiceWorkerProviderContext::waiting() {
DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
return waiting_.get();
}
-ServiceWorkerHandleReference* ServiceWorkerProviderContext::current() {
+ServiceWorkerHandleReference* ServiceWorkerProviderContext::active() {
+ DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
+ return active_.get();
+}
+
+ServiceWorkerHandleReference* ServiceWorkerProviderContext::controller() {
+ DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
+ return controller_.get();
+}
+
+ServiceWorkerRegistrationHandleReference*
+ServiceWorkerProviderContext::registration() {
DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
- return current_.get();
+ return registration_.get();
+}
+
+ServiceWorkerVersionAttributes
+ServiceWorkerProviderContext::GetVersionAttributes() {
+ ServiceWorkerVersionAttributes attrs;
+ if (installing())
+ attrs.installing = installing()->info();
+ if (waiting())
+ attrs.waiting = waiting()->info();
+ if (active())
+ attrs.active = active()->info();
+ return attrs;
+}
+
+void ServiceWorkerProviderContext::OnAssociateRegistration(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs) {
+ DCHECK(!registration_);
+ DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId, info.handle_id);
+ registration_ = ServiceWorkerRegistrationHandleReference::Adopt(
+ info, thread_safe_sender_.get());
+ installing_ = ServiceWorkerHandleReference::Adopt(
+ attrs.installing, thread_safe_sender_.get());
+ waiting_ = ServiceWorkerHandleReference::Adopt(
+ attrs.waiting, thread_safe_sender_.get());
+ active_ = ServiceWorkerHandleReference::Adopt(
+ attrs.active, thread_safe_sender_.get());
+}
+
+void ServiceWorkerProviderContext::OnDisassociateRegistration() {
+ controller_.reset();
+ active_.reset();
+ waiting_.reset();
+ installing_.reset();
+ registration_.reset();
}
void ServiceWorkerProviderContext::OnServiceWorkerStateChanged(
int handle_id,
blink::WebServiceWorkerState state) {
ServiceWorkerHandleReference* which = NULL;
- if (handle_id == current_handle_id()) {
- which = current_.get();
- } else if (handle_id == waiting_handle_id()) {
+ if (handle_id == controller_handle_id())
+ which = controller_.get();
+ else if (handle_id == active_handle_id())
+ which = active_.get();
+ else if (handle_id == waiting_handle_id())
which = waiting_.get();
- }
+ else if (handle_id == installing_handle_id())
+ which = installing_.get();
// We should only get messages for ServiceWorkers associated with
// this provider.
@@ -66,34 +121,81 @@ void ServiceWorkerProviderContext::OnServiceWorkerStateChanged(
// when we support navigator.serviceWorker in dedicated workers.
}
+void ServiceWorkerProviderContext::OnSetInstallingServiceWorker(
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info) {
+ DCHECK(IsAssociatedWithRegistration(registration_handle_id));
+ installing_ =
+ ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
+}
+
void ServiceWorkerProviderContext::OnSetWaitingServiceWorker(
- int provider_id,
+ int registration_handle_id,
+ const ServiceWorkerObjectInfo& info) {
+ DCHECK(IsAssociatedWithRegistration(registration_handle_id));
+ waiting_ =
+ ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
+}
+
+void ServiceWorkerProviderContext::OnSetActiveServiceWorker(
+ int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
- DCHECK_EQ(provider_id_, provider_id);
- waiting_ = ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_);
+ DCHECK(IsAssociatedWithRegistration(registration_handle_id));
+ active_ =
+ ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
}
-void ServiceWorkerProviderContext::OnSetCurrentServiceWorker(
- int provider_id,
+void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
+ int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
- DCHECK_EQ(provider_id_, provider_id);
+ DCHECK(IsAssociatedWithRegistration(registration_handle_id));
// This context is is the primary owner of this handle, keeps the
// initial reference until it goes away.
- current_ = ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_);
+ controller_ =
+ ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
// TODO(kinuko): We can forward the message to other threads here
// when we support navigator.serviceWorker in dedicated workers.
}
-int ServiceWorkerProviderContext::current_handle_id() const {
+int ServiceWorkerProviderContext::installing_handle_id() const {
DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
- return current_ ? current_->info().handle_id : kInvalidServiceWorkerHandleId;
+ return installing_ ? installing_->info().handle_id
+ : kInvalidServiceWorkerHandleId;
}
int ServiceWorkerProviderContext::waiting_handle_id() const {
DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
- return waiting_ ? waiting_->info().handle_id : kInvalidServiceWorkerHandleId;
+ return waiting_ ? waiting_->info().handle_id
+ : kInvalidServiceWorkerHandleId;
+}
+
+int ServiceWorkerProviderContext::active_handle_id() const {
+ DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
+ return active_ ? active_->info().handle_id
+ : kInvalidServiceWorkerHandleId;
+}
+
+int ServiceWorkerProviderContext::controller_handle_id() const {
+ DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
+ return controller_ ? controller_->info().handle_id
+ : kInvalidServiceWorkerHandleId;
+}
+
+int ServiceWorkerProviderContext::registration_handle_id() const {
+ DCHECK(main_thread_loop_proxy_->RunsTasksOnCurrentThread());
+ return registration_ ? registration_->info().handle_id
+ : kInvalidServiceWorkerRegistrationHandleId;
+}
+
+bool ServiceWorkerProviderContext::IsAssociatedWithRegistration(
+ int registration_handle_id) const {
+ if (!registration_)
+ return false;
+ if (registration_handle_id == kInvalidServiceWorkerRegistrationHandleId)
+ return false;
+ return registration_->info().handle_id == registration_handle_id;
}
} // namespace content
diff --git a/chromium/content/child/service_worker/service_worker_provider_context.h b/chromium/content/child/service_worker/service_worker_provider_context.h
index 5fe68ae6c55..75348bb95fa 100644
--- a/chromium/content/child/service_worker/service_worker_provider_context.h
+++ b/chromium/content/child/service_worker/service_worker_provider_context.h
@@ -24,13 +24,14 @@ class Message;
namespace content {
class ServiceWorkerHandleReference;
+class ServiceWorkerRegistrationHandleReference;
struct ServiceWorkerProviderContextDeleter;
class ThreadSafeSender;
// An instance of this class holds document-related information (e.g.
-// .current). Created and destructed on the main thread.
+// .controller). Created and destructed on the main thread.
// TODO(kinuko): To support navigator.serviceWorker in dedicated workers
-// this needs to be RefCountedThreadSafe and .current info needs to be
+// this needs to be RefCountedThreadSafe and .controller info needs to be
// handled in a thread-safe manner (e.g. by a lock etc).
class ServiceWorkerProviderContext
: public base::RefCounted<ServiceWorkerProviderContext> {
@@ -38,39 +39,69 @@ class ServiceWorkerProviderContext
explicit ServiceWorkerProviderContext(int provider_id);
// Called from ServiceWorkerDispatcher.
+ void OnAssociateRegistration(const ServiceWorkerRegistrationObjectInfo& info,
+ const ServiceWorkerVersionAttributes& attrs);
+ void OnDisassociateRegistration();
void OnServiceWorkerStateChanged(int handle_id,
blink::WebServiceWorkerState state);
- void OnSetWaitingServiceWorker(int provider_id,
- const ServiceWorkerObjectInfo& info);
- void OnSetCurrentServiceWorker(int provider_id,
+ void OnSetInstallingServiceWorker(int registration_handle_id,
+ const ServiceWorkerObjectInfo& info);
+ void OnSetWaitingServiceWorker(int registration_handle_id,
const ServiceWorkerObjectInfo& info);
+ void OnSetActiveServiceWorker(int registration_handle_id,
+ const ServiceWorkerObjectInfo& info);
+ void OnSetControllerServiceWorker(int registration_handle_id,
+ const ServiceWorkerObjectInfo& info);
int provider_id() const { return provider_id_; }
+ ServiceWorkerHandleReference* installing();
ServiceWorkerHandleReference* waiting();
- // Gets the context's handle reference for .controller.
- // TODO(dominicc): Rename this to "controller".
- ServiceWorkerHandleReference* current();
+ ServiceWorkerHandleReference* active();
+ ServiceWorkerHandleReference* controller();
+ ServiceWorkerRegistrationHandleReference* registration();
- // Gets the handle ID of the controller, or
- // kInvalidServiceWorkerHandleId if the provider is not controlled
- // by a Service Worker.
- int current_handle_id() const;
+ ServiceWorkerVersionAttributes GetVersionAttributes();
+
+ // Gets the handle ID of the installing Service Worker, or
+ // kInvalidServiceWorkerHandleId if the provider does not have a
+ // installing Service Worker.
+ int installing_handle_id() const;
// Gets the handle ID of the waiting Service Worker, or
// kInvalidServiceWorkerHandleId if the provider does not have a
// waiting Service Worker.
int waiting_handle_id() const;
+ // Gets the handle ID of the active Service Worker, or
+ // kInvalidServiceWorkerHandleId if the provider does not have an active
+ // Service Worker.
+ int active_handle_id() const;
+
+ // Gets the handle ID of the controller Service Worker, or
+ // kInvalidServiceWorkerHandleId if the provider is not controlled
+ // by a Service Worker.
+ int controller_handle_id() const;
+
+ // Gets the handle ID of the associated registration, or
+ // kInvalidRegistrationHandleId if the provider is not associated with any
+ // registration.
+ int registration_handle_id() const;
+
private:
friend class base::RefCounted<ServiceWorkerProviderContext>;
~ServiceWorkerProviderContext();
+ bool IsAssociatedWithRegistration(int registration_handle_id) const;
+
const int provider_id_;
scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+ scoped_ptr<ServiceWorkerHandleReference> installing_;
scoped_ptr<ServiceWorkerHandleReference> waiting_;
- scoped_ptr<ServiceWorkerHandleReference> current_;
+ scoped_ptr<ServiceWorkerHandleReference> active_;
+ scoped_ptr<ServiceWorkerHandleReference> controller_;
+ scoped_ptr<ServiceWorkerRegistrationHandleReference> registration_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContext);
};
diff --git a/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc b/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc
new file mode 100644
index 00000000000..438bce486c0
--- /dev/null
+++ b/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 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 "content/child/service_worker/service_worker_registration_handle_reference.h"
+
+#include "content/child/thread_safe_sender.h"
+#include "content/common/service_worker/service_worker_messages.h"
+
+namespace content {
+
+scoped_ptr<ServiceWorkerRegistrationHandleReference>
+ServiceWorkerRegistrationHandleReference::Create(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ ThreadSafeSender* sender) {
+ return make_scoped_ptr(new ServiceWorkerRegistrationHandleReference(
+ info, sender, true));
+}
+
+scoped_ptr<ServiceWorkerRegistrationHandleReference>
+ServiceWorkerRegistrationHandleReference::Adopt(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ ThreadSafeSender* sender) {
+ return make_scoped_ptr(new ServiceWorkerRegistrationHandleReference(
+ info, sender, false));
+}
+
+ServiceWorkerRegistrationHandleReference::
+ServiceWorkerRegistrationHandleReference(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ ThreadSafeSender* sender,
+ bool increment_ref_in_ctor)
+ : info_(info),
+ sender_(sender) {
+ DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId, info_.handle_id);
+ DCHECK(sender_.get());
+ if (increment_ref_in_ctor)
+ return;
+ sender_->Send(
+ new ServiceWorkerHostMsg_IncrementRegistrationRefCount(info_.handle_id));
+}
+
+ServiceWorkerRegistrationHandleReference::
+~ServiceWorkerRegistrationHandleReference() {
+ sender_->Send(
+ new ServiceWorkerHostMsg_DecrementRegistrationRefCount(info_.handle_id));
+}
+
+} // namespace content
diff --git a/chromium/content/child/service_worker/service_worker_registration_handle_reference.h b/chromium/content/child/service_worker/service_worker_registration_handle_reference.h
new file mode 100644
index 00000000000..c7138e622c9
--- /dev/null
+++ b/chromium/content/child/service_worker/service_worker_registration_handle_reference.h
@@ -0,0 +1,52 @@
+// Copyright 2014 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 CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
+#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class ThreadSafeSender;
+
+class ServiceWorkerRegistrationHandleReference {
+ public:
+ // Creates a new ServiceWorkerRegistrationHandleReference and increments
+ // ref-count.
+ static scoped_ptr<ServiceWorkerRegistrationHandleReference> Create(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ ThreadSafeSender* sender);
+
+ // Creates a new ServiceWorkerRegistrationHandleReference by adopting a
+ // ref-count.
+ static scoped_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ ThreadSafeSender* sender);
+
+ ~ServiceWorkerRegistrationHandleReference();
+
+ const ServiceWorkerRegistrationObjectInfo& info() const { return info_; }
+ int handle_id() const { return info_.handle_id; }
+ GURL scope() const { return info_.scope; }
+ int64 registration_id() const { return info_.registration_id; }
+
+ private:
+ ServiceWorkerRegistrationHandleReference(
+ const ServiceWorkerRegistrationObjectInfo& info,
+ ThreadSafeSender* sender,
+ bool increment_ref_in_ctor);
+
+ ServiceWorkerRegistrationObjectInfo info_;
+ scoped_refptr<ThreadSafeSender> sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationHandleReference);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.cc b/chromium/content/child/service_worker/web_service_worker_impl.cc
index 685c68cb8ab..dcd69ca8a90 100644
--- a/chromium/content/child/service_worker/web_service_worker_impl.cc
+++ b/chromium/content/child/service_worker/web_service_worker_impl.cc
@@ -43,9 +43,8 @@ WebServiceWorkerImpl::~WebServiceWorkerImpl() {
void WebServiceWorkerImpl::OnStateChanged(
blink::WebServiceWorkerState new_state) {
- DCHECK(proxy_);
- if (proxy_->isReady())
- ChangeState(new_state);
+ if (proxy_ && proxy_->isReady())
+ CommitState(new_state);
else
queued_states_.push_back(new_state);
}
@@ -65,7 +64,7 @@ void WebServiceWorkerImpl::proxyReadyChanged() {
queued_states_.begin();
it != queued_states_.end();
++it) {
- ChangeState(*it);
+ CommitState(*it);
}
queued_states_.clear();
}
@@ -90,7 +89,7 @@ void WebServiceWorkerImpl::postMessage(const WebString& message,
WebMessagePortChannelImpl::ExtractMessagePortIDs(channels)));
}
-void WebServiceWorkerImpl::ChangeState(blink::WebServiceWorkerState new_state) {
+void WebServiceWorkerImpl::CommitState(blink::WebServiceWorkerState new_state) {
DCHECK(proxy_);
DCHECK(proxy_->isReady());
state_ = new_state;
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.h b/chromium/content/child/service_worker/web_service_worker_impl.h
index 47260404f2d..b1ede903677 100644
--- a/chromium/content/child/service_worker/web_service_worker_impl.h
+++ b/chromium/content/child/service_worker/web_service_worker_impl.h
@@ -55,7 +55,7 @@ class WebServiceWorkerImpl
private:
// Commits the new state internally and notifies the proxy of the change.
- void ChangeState(blink::WebServiceWorkerState new_state);
+ void CommitState(blink::WebServiceWorkerState new_state);
scoped_ptr<ServiceWorkerHandleReference> handle_ref_;
blink::WebServiceWorkerState state_;
diff --git a/chromium/content/child/service_worker/web_service_worker_provider_impl.cc b/chromium/content/child/service_worker/web_service_worker_provider_impl.cc
index f6ed0fca746..ef46bf8cc19 100644
--- a/chromium/content/child/service_worker/web_service_worker_provider_impl.cc
+++ b/chromium/content/child/service_worker/web_service_worker_provider_impl.cc
@@ -10,7 +10,9 @@
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_provider_context.h"
+#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/service_worker/web_service_worker_impl.h"
+#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerProviderClient.h"
@@ -47,32 +49,57 @@ void WebServiceWorkerProviderImpl::setClient(
// for more context)
GetDispatcher()->AddScriptClient(provider_id_, client);
- if (context_->waiting_handle_id() != kInvalidServiceWorkerHandleId) {
- client->setWaiting(
- GetDispatcher()->GetServiceWorker(context_->waiting()->info(), false));
+ if (!context_->registration()) {
+ // This provider is not associated with any registration.
+ return;
+ }
+
+ // Set .ready if the associated registration has the active service worker.
+ if (context_->active_handle_id() != kInvalidServiceWorkerHandleId) {
+ WebServiceWorkerRegistrationImpl* registration =
+ GetDispatcher()->FindServiceWorkerRegistration(
+ context_->registration()->info(), false);
+ if (!registration) {
+ registration = GetDispatcher()->CreateServiceWorkerRegistration(
+ context_->registration()->info(), false);
+ ServiceWorkerVersionAttributes attrs = context_->GetVersionAttributes();
+ registration->SetInstalling(
+ GetDispatcher()->GetServiceWorker(attrs.installing, false));
+ registration->SetWaiting(
+ GetDispatcher()->GetServiceWorker(attrs.waiting, false));
+ registration->SetActive(
+ GetDispatcher()->GetServiceWorker(attrs.active, false));
+ }
+ client->setReadyRegistration(registration);
}
- if (context_->current_handle_id() != kInvalidServiceWorkerHandleId) {
- client->setController(
- GetDispatcher()->GetServiceWorker(context_->current()->info(), false));
+ if (context_->controller_handle_id() != kInvalidServiceWorkerHandleId) {
+ client->setController(GetDispatcher()->GetServiceWorker(
+ context_->controller()->info(), false));
}
}
void WebServiceWorkerProviderImpl::registerServiceWorker(
const WebURL& pattern,
const WebURL& script_url,
- WebServiceWorkerCallbacks* callbacks) {
+ WebServiceWorkerRegistrationCallbacks* callbacks) {
GetDispatcher()->RegisterServiceWorker(
provider_id_, pattern, script_url, callbacks);
}
void WebServiceWorkerProviderImpl::unregisterServiceWorker(
const WebURL& pattern,
- WebServiceWorkerCallbacks* callbacks) {
+ WebServiceWorkerUnregistrationCallbacks* callbacks) {
GetDispatcher()->UnregisterServiceWorker(
provider_id_, pattern, callbacks);
}
+void WebServiceWorkerProviderImpl::getRegistration(
+ const blink::WebURL& document_url,
+ WebServiceWorkerRegistrationCallbacks* callbacks) {
+ GetDispatcher()->GetRegistration(provider_id_, document_url, callbacks);
+}
+
void WebServiceWorkerProviderImpl::RemoveScriptClient() {
// Remove the script client, but only if the dispatcher is still there.
// (For cleanup path we don't need to bother creating a new dispatcher)
@@ -84,7 +111,7 @@ void WebServiceWorkerProviderImpl::RemoveScriptClient() {
ServiceWorkerDispatcher* WebServiceWorkerProviderImpl::GetDispatcher() {
return ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
- thread_safe_sender_);
+ thread_safe_sender_.get());
}
} // namespace content
diff --git a/chromium/content/child/service_worker/web_service_worker_provider_impl.h b/chromium/content/child/service_worker/web_service_worker_provider_impl.h
index 912d2f48a2d..e56f913c360 100644
--- a/chromium/content/child/service_worker/web_service_worker_provider_impl.h
+++ b/chromium/content/child/service_worker/web_service_worker_provider_impl.h
@@ -34,13 +34,19 @@ class WebServiceWorkerProviderImpl
virtual void registerServiceWorker(const blink::WebURL& pattern,
const blink::WebURL& script_url,
- WebServiceWorkerCallbacks*);
+ WebServiceWorkerRegistrationCallbacks*);
- virtual void unregisterServiceWorker(const blink::WebURL& pattern,
- WebServiceWorkerCallbacks*);
+ virtual void unregisterServiceWorker(
+ const blink::WebURL& pattern,
+ WebServiceWorkerUnregistrationCallbacks*);
+
+ virtual void getRegistration(const blink::WebURL& document_url,
+ WebServiceWorkerGetRegistrationCallbacks*);
ServiceWorkerProviderContext* context() { return context_.get(); }
+ int provider_id() const { return provider_id_; }
+
private:
void RemoveScriptClient();
ServiceWorkerDispatcher* GetDispatcher();
diff --git a/chromium/content/child/service_worker/web_service_worker_registration_impl.cc b/chromium/content/child/service_worker/web_service_worker_registration_impl.cc
new file mode 100644
index 00000000000..12db5310dad
--- /dev/null
+++ b/chromium/content/child/service_worker/web_service_worker_registration_impl.cc
@@ -0,0 +1,119 @@
+// Copyright 2014 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 "content/child/service_worker/web_service_worker_registration_impl.h"
+
+#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "content/child/service_worker/service_worker_registration_handle_reference.h"
+#include "content/child/service_worker/web_service_worker_impl.h"
+#include "content/common/service_worker/service_worker_types.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerRegistrationProxy.h"
+
+namespace content {
+
+WebServiceWorkerRegistrationImpl::QueuedTask::QueuedTask(
+ QueuedTaskType type,
+ blink::WebServiceWorker* worker)
+ : type(type),
+ worker(worker) {
+}
+
+WebServiceWorkerRegistrationImpl::WebServiceWorkerRegistrationImpl(
+ scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref)
+ : handle_ref_(handle_ref.Pass()),
+ proxy_(NULL) {
+ DCHECK(handle_ref_);
+ DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId,
+ handle_ref_->handle_id());
+ ServiceWorkerDispatcher* dispatcher =
+ ServiceWorkerDispatcher::GetThreadSpecificInstance();
+ DCHECK(dispatcher);
+ dispatcher->AddServiceWorkerRegistration(handle_ref_->handle_id(), this);
+}
+
+WebServiceWorkerRegistrationImpl::~WebServiceWorkerRegistrationImpl() {
+ ServiceWorkerDispatcher* dispatcher =
+ ServiceWorkerDispatcher::GetThreadSpecificInstance();
+ if (dispatcher)
+ dispatcher->RemoveServiceWorkerRegistration(handle_ref_->handle_id());
+ ClearQueuedTasks();
+}
+
+void WebServiceWorkerRegistrationImpl::SetInstalling(
+ blink::WebServiceWorker* service_worker) {
+ if (proxy_)
+ proxy_->setInstalling(service_worker);
+ else
+ queued_tasks_.push_back(QueuedTask(INSTALLING, service_worker));
+}
+
+void WebServiceWorkerRegistrationImpl::SetWaiting(
+ blink::WebServiceWorker* service_worker) {
+ if (proxy_)
+ proxy_->setWaiting(service_worker);
+ else
+ queued_tasks_.push_back(QueuedTask(WAITING, service_worker));
+}
+
+void WebServiceWorkerRegistrationImpl::SetActive(
+ blink::WebServiceWorker* service_worker) {
+ if (proxy_)
+ proxy_->setActive(service_worker);
+ else
+ queued_tasks_.push_back(QueuedTask(ACTIVE, service_worker));
+}
+
+void WebServiceWorkerRegistrationImpl::OnUpdateFound() {
+ if (proxy_)
+ proxy_->dispatchUpdateFoundEvent();
+ else
+ queued_tasks_.push_back(QueuedTask(UPDATE_FOUND, NULL));
+}
+
+void WebServiceWorkerRegistrationImpl::setProxy(
+ blink::WebServiceWorkerRegistrationProxy* proxy) {
+ proxy_ = proxy;
+ RunQueuedTasks();
+}
+
+void WebServiceWorkerRegistrationImpl::RunQueuedTasks() {
+ DCHECK(proxy_);
+ for (std::vector<QueuedTask>::const_iterator it = queued_tasks_.begin();
+ it != queued_tasks_.end(); ++it) {
+ if (it->type == INSTALLING)
+ proxy_->setInstalling(it->worker);
+ else if (it->type == WAITING)
+ proxy_->setWaiting(it->worker);
+ else if (it->type == ACTIVE)
+ proxy_->setActive(it->worker);
+ else if (it->type == UPDATE_FOUND)
+ proxy_->dispatchUpdateFoundEvent();
+ }
+ queued_tasks_.clear();
+}
+
+void WebServiceWorkerRegistrationImpl::ClearQueuedTasks() {
+ for (std::vector<QueuedTask>::const_iterator it = queued_tasks_.begin();
+ it != queued_tasks_.end(); ++it) {
+ // If the owner of the WebServiceWorker does not exist, delete it.
+ if (it->worker && !it->worker->proxy())
+ delete it->worker;
+ }
+ queued_tasks_.clear();
+}
+
+blink::WebServiceWorkerRegistrationProxy*
+WebServiceWorkerRegistrationImpl::proxy() {
+ return proxy_;
+}
+
+blink::WebURL WebServiceWorkerRegistrationImpl::scope() const {
+ return handle_ref_->scope();
+}
+
+int64 WebServiceWorkerRegistrationImpl::registration_id() const {
+ return handle_ref_->registration_id();
+}
+
+} // namespace content
diff --git a/chromium/content/child/service_worker/web_service_worker_registration_impl.h b/chromium/content/child/service_worker/web_service_worker_registration_impl.h
new file mode 100644
index 00000000000..52ee1029ddf
--- /dev/null
+++ b/chromium/content/child/service_worker/web_service_worker_registration_impl.h
@@ -0,0 +1,72 @@
+// Copyright 2014 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 CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_REGISTRATION_IMPL_H_
+#define CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_REGISTRATION_IMPL_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerRegistration.h"
+
+namespace blink {
+class WebServiceWorker;
+class WebServiceWorkerRegistrationProxy;
+}
+
+namespace content {
+
+class ServiceWorkerRegistrationHandleReference;
+class ThreadSafeSender;
+struct ServiceWorkerObjectInfo;
+
+class WebServiceWorkerRegistrationImpl
+ : NON_EXPORTED_BASE(public blink::WebServiceWorkerRegistration) {
+ public:
+ explicit WebServiceWorkerRegistrationImpl(
+ scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref);
+ virtual ~WebServiceWorkerRegistrationImpl();
+
+ void SetInstalling(blink::WebServiceWorker* service_worker);
+ void SetWaiting(blink::WebServiceWorker* service_worker);
+ void SetActive(blink::WebServiceWorker* service_worker);
+
+ void OnUpdateFound();
+
+ // blink::WebServiceWorkerRegistration overrides.
+ virtual void setProxy(blink::WebServiceWorkerRegistrationProxy* proxy);
+ virtual blink::WebServiceWorkerRegistrationProxy* proxy();
+ virtual blink::WebURL scope() const;
+
+ int64 registration_id() const;
+
+ private:
+ enum QueuedTaskType {
+ INSTALLING,
+ WAITING,
+ ACTIVE,
+ UPDATE_FOUND,
+ };
+
+ struct QueuedTask {
+ QueuedTask(QueuedTaskType type,
+ blink::WebServiceWorker* worker);
+ QueuedTaskType type;
+ blink::WebServiceWorker* worker;
+ };
+
+ void RunQueuedTasks();
+ void ClearQueuedTasks();
+
+ scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref_;
+ blink::WebServiceWorkerRegistrationProxy* proxy_;
+
+ std::vector<QueuedTask> queued_tasks_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerRegistrationImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_REGISTRATION_IMPL_H_
diff --git a/chromium/content/child/shared_worker_devtools_agent.cc b/chromium/content/child/shared_worker_devtools_agent.cc
index fc5a1c363f7..5d127378fb9 100644
--- a/chromium/content/child/shared_worker_devtools_agent.cc
+++ b/chromium/content/child/shared_worker_devtools_agent.cc
@@ -6,6 +6,7 @@
#include "content/child/child_thread.h"
#include "content/common/devtools_messages.h"
+#include "ipc/ipc_channel.h"
#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebSharedWorker.h"
@@ -15,6 +16,9 @@ using blink::WebString;
namespace content {
+static const size_t kMaxMessageChunkSize =
+ IPC::Channel::kMaximumMessageSize / 4;
+
SharedWorkerDevToolsAgent::SharedWorkerDevToolsAgent(
int route_id,
WebSharedWorker* webworker)
@@ -34,8 +38,6 @@ bool SharedWorkerDevToolsAgent::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
OnDispatchOnInspectorBackend)
- IPC_MESSAGE_HANDLER(DevToolsAgentMsg_ResumeWorkerContext,
- OnResumeWorkerContext)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -43,9 +45,19 @@ bool SharedWorkerDevToolsAgent::OnMessageReceived(const IPC::Message& message) {
void SharedWorkerDevToolsAgent::SendDevToolsMessage(
const blink::WebString& message) {
+ std::string msg(message.utf8());
+ if (message.length() < kMaxMessageChunkSize) {
+ Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
+ route_id_, msg, msg.size()));
+ return;
+ }
+
+ for (size_t pos = 0; pos < msg.length(); pos += kMaxMessageChunkSize) {
Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
route_id_,
- message.utf8()));
+ msg.substr(pos, kMaxMessageChunkSize),
+ pos ? 0 : msg.size()));
+ }
}
void SharedWorkerDevToolsAgent::SaveDevToolsAgentState(
@@ -55,12 +67,13 @@ void SharedWorkerDevToolsAgent::SaveDevToolsAgentState(
}
void SharedWorkerDevToolsAgent::OnAttach(const std::string& host_id) {
- webworker_->attachDevTools();
+ webworker_->attachDevTools(WebString::fromUTF8(host_id));
}
void SharedWorkerDevToolsAgent::OnReattach(const std::string& host_id,
const std::string& state) {
- webworker_->reattachDevTools(WebString::fromUTF8(state));
+ webworker_->reattachDevTools(WebString::fromUTF8(host_id),
+ WebString::fromUTF8(state));
}
void SharedWorkerDevToolsAgent::OnDetach() {
@@ -72,10 +85,6 @@ void SharedWorkerDevToolsAgent::OnDispatchOnInspectorBackend(
webworker_->dispatchDevToolsMessage(WebString::fromUTF8(message));
}
-void SharedWorkerDevToolsAgent::OnResumeWorkerContext() {
- webworker_->resumeWorkerContext();
-}
-
bool SharedWorkerDevToolsAgent::Send(IPC::Message* message) {
return ChildThread::current()->Send(message);
}
diff --git a/chromium/content/child/shared_worker_devtools_agent.h b/chromium/content/child/shared_worker_devtools_agent.h
index 724e2f5645d..a2d028e7d4e 100644
--- a/chromium/content/child/shared_worker_devtools_agent.h
+++ b/chromium/content/child/shared_worker_devtools_agent.h
@@ -35,7 +35,6 @@ class SharedWorkerDevToolsAgent {
void OnReattach(const std::string& host_id, const std::string& state);
void OnDetach();
void OnDispatchOnInspectorBackend(const std::string& message);
- void OnResumeWorkerContext();
bool Send(IPC::Message* message);
const int route_id_;
diff --git a/chromium/content/child/simple_webmimeregistry_impl.cc b/chromium/content/child/simple_webmimeregistry_impl.cc
index e7416d92041..510b25b7341 100644
--- a/chromium/content/child/simple_webmimeregistry_impl.cc
+++ b/chromium/content/child/simple_webmimeregistry_impl.cc
@@ -35,6 +35,16 @@ WebMimeRegistry::SupportsType SimpleWebMimeRegistryImpl::supportsImageMIMEType(
}
WebMimeRegistry::SupportsType
+ SimpleWebMimeRegistryImpl::supportsImagePrefixedMIMEType(
+ const WebString& mime_type) {
+ std::string ascii_mime_type = ToASCIIOrEmpty(mime_type);
+ return (net::IsSupportedImageMimeType(ascii_mime_type) ||
+ (StartsWithASCII(ascii_mime_type, "image/", true) &&
+ net::IsSupportedNonImageMimeType(ascii_mime_type))) ?
+ WebMimeRegistry::IsSupported : WebMimeRegistry::IsNotSupported;
+}
+
+WebMimeRegistry::SupportsType
SimpleWebMimeRegistryImpl::supportsJavaScriptMIMEType(
const WebString& mime_type) {
return net::IsSupportedJavascriptMimeType(ToASCIIOrEmpty(mime_type)) ?
diff --git a/chromium/content/child/simple_webmimeregistry_impl.h b/chromium/content/child/simple_webmimeregistry_impl.h
index 4f880157d44..3e9b95e37db 100644
--- a/chromium/content/child/simple_webmimeregistry_impl.h
+++ b/chromium/content/child/simple_webmimeregistry_impl.h
@@ -28,6 +28,8 @@ class CONTENT_EXPORT SimpleWebMimeRegistryImpl :
const blink::WebString&);
virtual blink::WebMimeRegistry::SupportsType supportsImageMIMEType(
const blink::WebString&);
+ virtual blink::WebMimeRegistry::SupportsType supportsImagePrefixedMIMEType(
+ const blink::WebString&);
virtual blink::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType(
const blink::WebString&);
virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
diff --git a/chromium/content/child/simple_webmimeregistry_impl_unittest.cc b/chromium/content/child/simple_webmimeregistry_impl_unittest.cc
new file mode 100644
index 00000000000..40d3bd5f06c
--- /dev/null
+++ b/chromium/content/child/simple_webmimeregistry_impl_unittest.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 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.
+
+// Tests for SimpleWebMimeRegistryImpl.
+
+#include "content/child/simple_webmimeregistry_impl.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+
+TEST(SimpleWebMimeRegistryImpl, mimeTypeTest)
+{
+ content::SimpleWebMimeRegistryImpl registry;
+
+ EXPECT_TRUE(registry.supportsImagePrefixedMIMEType("image/gif"));
+ EXPECT_TRUE(registry.supportsImagePrefixedMIMEType("image/svg+xml"));
+ EXPECT_FALSE(registry.supportsImageMIMEType("image/svg+xml"));
+ EXPECT_TRUE(registry.supportsImageMIMEType("image/gif"));
+}
+
diff --git a/chromium/content/child/site_isolation_policy.cc b/chromium/content/child/site_isolation_policy.cc
index 026f625a1d4..87ac9cc849c 100644
--- a/chromium/content/child/site_isolation_policy.cc
+++ b/chromium/content/child/site_isolation_policy.cc
@@ -117,7 +117,7 @@ void HistogramCountBlockedResponse(
IncrementHistogramEnum(
bucket_prefix + block_label + ".RenderableStatusCode",
resp_data->resource_type,
- ResourceType::LAST_TYPE);
+ RESOURCE_TYPE_LAST_TYPE);
} else {
IncrementHistogramCount(bucket_prefix + block_label +
".NonRenderableStatusCode");
@@ -142,7 +142,7 @@ void SiteIsolationPolicy::SetPolicyEnabled(bool enabled) {
linked_ptr<SiteIsolationResponseMetaData>
SiteIsolationPolicy::OnReceivedResponse(const GURL& frame_origin,
const GURL& response_url,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int origin_pid,
const ResourceResponseInfo& info) {
if (!g_policy_enabled)
@@ -160,7 +160,7 @@ SiteIsolationPolicy::OnReceivedResponse(const GURL& frame_origin,
// See if this is for navigation. If it is, don't block it, under the
// assumption that we will put it in an appropriate process.
- if (ResourceType::IsFrame(resource_type))
+ if (IsResourceTypeFrame(resource_type))
return linked_ptr<SiteIsolationResponseMetaData>();
if (!IsBlockableScheme(response_url))
@@ -333,7 +333,7 @@ bool SiteIsolationPolicy::IsBlockableScheme(const GURL& url) {
// We exclude ftp:// from here. FTP doesn't provide a Content-Type
// header which our policy depends on, so we cannot protect any
// document from FTP servers.
- return url.SchemeIs("http") || url.SchemeIs("https");
+ return url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme);
}
bool SiteIsolationPolicy::IsSameSite(const GURL& frame_origin,
diff --git a/chromium/content/child/site_isolation_policy.h b/chromium/content/child/site_isolation_policy.h
index 6c48697b596..f0842889b1b 100644
--- a/chromium/content/child/site_isolation_policy.h
+++ b/chromium/content/child/site_isolation_policy.h
@@ -12,9 +12,8 @@
#include "base/memory/linked_ptr.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
-#include "webkit/common/resource_type.h"
-
-class GURL;
+#include "content/public/common/resource_type.h"
+#include "url/gurl.h"
namespace content {
@@ -55,7 +54,6 @@ struct ResourceResponseInfo;
// # of responses that are plausibly sniffed to be JavaScript.
struct SiteIsolationResponseMetaData {
-
enum CanonicalMimeType {
HTML = 0,
XML = 1,
@@ -69,7 +67,7 @@ struct SiteIsolationResponseMetaData {
std::string frame_origin;
GURL response_url;
- ResourceType::Type resource_type;
+ ResourceType resource_type;
CanonicalMimeType canonical_mime_type;
int http_status_code;
bool no_sniff;
@@ -86,7 +84,7 @@ class CONTENT_EXPORT SiteIsolationPolicy {
static linked_ptr<SiteIsolationResponseMetaData> OnReceivedResponse(
const GURL& frame_origin,
const GURL& response_url,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
int origin_pid,
const ResourceResponseInfo& info);
diff --git a/chromium/content/child/site_isolation_policy_browsertest.cc b/chromium/content/child/site_isolation_policy_browsertest.cc
index 20d14eff074..c23b9b98759 100644
--- a/chromium/content/child/site_isolation_policy_browsertest.cc
+++ b/chromium/content/child/site_isolation_policy_browsertest.cc
@@ -17,9 +17,9 @@ namespace content {
class SiteIsolationPolicyBrowserTest : public ContentBrowserTest {
public:
SiteIsolationPolicyBrowserTest() {}
- virtual ~SiteIsolationPolicyBrowserTest() {}
+ ~SiteIsolationPolicyBrowserTest() override {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
ASSERT_TRUE(test_server()->Start());
net::SpawnedTestServer https_server(
net::SpawnedTestServer::TYPE_HTTPS,
diff --git a/chromium/content/child/socket_stream_dispatcher.cc b/chromium/content/child/socket_stream_dispatcher.cc
deleted file mode 100644
index 017a116466a..00000000000
--- a/chromium/content/child/socket_stream_dispatcher.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright (c) 2012 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 "content/child/socket_stream_dispatcher.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/id_map.h"
-#include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/child_thread.h"
-#include "content/child/web_socket_stream_handle_bridge.h"
-#include "content/child/web_socket_stream_handle_delegate.h"
-#include "content/child/web_socket_stream_handle_impl.h"
-#include "content/common/socket_stream.h"
-#include "content/common/socket_stream_handle_data.h"
-#include "content/common/socket_stream_messages.h"
-#include "net/base/net_errors.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// IPCWebSocketStreamHandleBridge is owned by each SocketStreamHandle.
-// It communicates with the main browser process via SocketStreamDispatcher.
-class IPCWebSocketStreamHandleBridge : public WebSocketStreamHandleBridge {
- public:
- IPCWebSocketStreamHandleBridge(blink::WebSocketStreamHandle* handle,
- WebSocketStreamHandleDelegate* delegate)
- : socket_id_(kNoSocketId), handle_(handle), delegate_(delegate) {}
-
- // Returns the handle having given id or NULL if there is no such handle.
- static IPCWebSocketStreamHandleBridge* FromSocketId(int id);
-
- // WebSocketStreamHandleBridge methods.
- virtual void Connect(const GURL& url) OVERRIDE;
- virtual bool Send(const std::vector<char>& data) OVERRIDE;
- virtual void Close() OVERRIDE;
-
- // Called by SocketStreamDispatcher.
- void OnConnected(int max_amount_send_allowed);
- void OnSentData(int amount_sent);
- void OnReceivedData(const std::vector<char>& data);
- void OnClosed();
- void OnFailed(int error_code, const char* error_msg);
-
- private:
- virtual ~IPCWebSocketStreamHandleBridge();
-
- // The ID for this bridge and corresponding SocketStream instance in the
- // browser process.
- int socket_id_;
-
- blink::WebSocketStreamHandle* handle_;
- WebSocketStreamHandleDelegate* delegate_;
-
- // Map from ID to bridge instance.
- static base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
- all_bridges;
-};
-
-// static
-base::LazyInstance<IDMap<IPCWebSocketStreamHandleBridge> >::Leaky
- IPCWebSocketStreamHandleBridge::all_bridges = LAZY_INSTANCE_INITIALIZER;
-
-/* static */
-IPCWebSocketStreamHandleBridge* IPCWebSocketStreamHandleBridge::FromSocketId(
- int id) {
- return all_bridges.Get().Lookup(id);
-}
-
-IPCWebSocketStreamHandleBridge::~IPCWebSocketStreamHandleBridge() {
- DVLOG(1) << "Bridge (" << this << ", socket_id_=" << socket_id_
- << ") Destructor";
-
- if (socket_id_ == kNoSocketId)
- return;
-
- ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
- socket_id_ = kNoSocketId;
-}
-
-void IPCWebSocketStreamHandleBridge::Connect(const GURL& url) {
- DVLOG(1) << "Bridge (" << this << ") Connect (url=" << url << ")";
-
- DCHECK_EQ(socket_id_, kNoSocketId);
- if (delegate_)
- delegate_->WillOpenStream(handle_, url);
-
- socket_id_ = all_bridges.Get().Add(this);
- DCHECK_NE(socket_id_, kNoSocketId);
- int render_frame_id = MSG_ROUTING_NONE;
- WebSocketStreamHandleImpl* impl =
- static_cast<WebSocketStreamHandleImpl*>(handle_);
- const SocketStreamHandleData* data =
- static_cast<SocketStreamHandleData*>(impl->GetUserData(handle_));
- if (data)
- render_frame_id = data->render_frame_id();
- AddRef(); // Released in OnClosed().
- ChildThread::current()->Send(
- new SocketStreamHostMsg_Connect(render_frame_id, url, socket_id_));
- DVLOG(1) << "Bridge #" << socket_id_ << " sent IPC Connect";
- // TODO(ukai): timeout to OnConnected.
-}
-
-bool IPCWebSocketStreamHandleBridge::Send(const std::vector<char>& data) {
- DVLOG(1) << "Bridge #" << socket_id_ << " Send (" << data.size()
- << " bytes)";
-
- ChildThread::current()->Send(
- new SocketStreamHostMsg_SendData(socket_id_, data));
- if (delegate_)
- delegate_->WillSendData(handle_, &data[0], data.size());
- return true;
-}
-
-void IPCWebSocketStreamHandleBridge::Close() {
- DVLOG(1) << "Bridge #" << socket_id_ << " Close";
-
- ChildThread::current()->Send(new SocketStreamHostMsg_Close(socket_id_));
-}
-
-void IPCWebSocketStreamHandleBridge::OnConnected(int max_pending_send_allowed) {
- DVLOG(1) << "Bridge #" << socket_id_
- << " OnConnected (max_pending_send_allowed="
- << max_pending_send_allowed << ")";
-
- if (delegate_)
- delegate_->DidOpenStream(handle_, max_pending_send_allowed);
-}
-
-void IPCWebSocketStreamHandleBridge::OnSentData(int amount_sent) {
- DVLOG(1) << "Bridge #" << socket_id_ << " OnSentData (" << amount_sent
- << " bytes)";
-
- if (delegate_)
- delegate_->DidSendData(handle_, amount_sent);
-}
-
-void IPCWebSocketStreamHandleBridge::OnReceivedData(
- const std::vector<char>& data) {
- DVLOG(1) << "Bridge #" << socket_id_ << " OnReceiveData (" << data.size()
- << " bytes)";
- if (delegate_)
- delegate_->DidReceiveData(handle_, &data[0], data.size());
-}
-
-void IPCWebSocketStreamHandleBridge::OnClosed() {
- DVLOG(1) << "Bridge #" << socket_id_ << " OnClosed";
-
- if (socket_id_ != kNoSocketId) {
- all_bridges.Get().Remove(socket_id_);
- socket_id_ = kNoSocketId;
- }
- if (delegate_)
- delegate_->DidClose(handle_);
- delegate_ = NULL;
- Release();
-}
-
-void IPCWebSocketStreamHandleBridge::OnFailed(int error_code,
- const char* error_msg) {
- DVLOG(1) << "Bridge #" << socket_id_ << " OnFailed (error_code=" << error_code
- << ")";
- if (delegate_)
- delegate_->DidFail(handle_, error_code, base::ASCIIToUTF16(error_msg));
-}
-
-SocketStreamDispatcher::SocketStreamDispatcher() {
-}
-
-// static
-WebSocketStreamHandleBridge* SocketStreamDispatcher::CreateBridge(
- blink::WebSocketStreamHandle* handle,
- WebSocketStreamHandleDelegate* delegate) {
- return new IPCWebSocketStreamHandleBridge(handle, delegate);
-}
-
-bool SocketStreamDispatcher::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(SocketStreamDispatcher, msg)
- IPC_MESSAGE_HANDLER(SocketStreamMsg_Connected, OnConnected)
- IPC_MESSAGE_HANDLER(SocketStreamMsg_SentData, OnSentData)
- IPC_MESSAGE_HANDLER(SocketStreamMsg_ReceivedData, OnReceivedData)
- IPC_MESSAGE_HANDLER(SocketStreamMsg_Closed, OnClosed)
- IPC_MESSAGE_HANDLER(SocketStreamMsg_Failed, OnFailed)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void SocketStreamDispatcher::OnConnected(int socket_id,
- int max_pending_send_allowed) {
- DVLOG(1) << "SocketStreamDispatcher::OnConnected (max_pending_send_allowed="
- << max_pending_send_allowed << ") to socket_id=" << socket_id;
-
- IPCWebSocketStreamHandleBridge* bridge =
- IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
- if (bridge)
- bridge->OnConnected(max_pending_send_allowed);
- else
- DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
-}
-
-void SocketStreamDispatcher::OnSentData(int socket_id, int amount_sent) {
- DVLOG(1) << "SocketStreamDispatcher::OnSentData (" << amount_sent
- << " bytes) to socket_id=" << socket_id;
-
- IPCWebSocketStreamHandleBridge* bridge =
- IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
- if (bridge)
- bridge->OnSentData(amount_sent);
- else
- DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
-}
-
-void SocketStreamDispatcher::OnReceivedData(
- int socket_id, const std::vector<char>& data) {
- DVLOG(1) << "SocketStreamDispatcher::OnReceivedData (" << data.size()
- << " bytes) to socket_id=" << socket_id;
-
- IPCWebSocketStreamHandleBridge* bridge =
- IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
- if (bridge)
- bridge->OnReceivedData(data);
- else
- DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
-}
-
-void SocketStreamDispatcher::OnClosed(int socket_id) {
- DVLOG(1) << "SocketStreamDispatcher::OnClosed to socket_id=" << socket_id;
-
- IPCWebSocketStreamHandleBridge* bridge =
- IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
- if (bridge)
- bridge->OnClosed();
- else
- DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
-}
-
-void SocketStreamDispatcher::OnFailed(int socket_id, int error_code) {
- IPCWebSocketStreamHandleBridge* bridge =
- IPCWebSocketStreamHandleBridge::FromSocketId(socket_id);
- if (bridge)
- bridge->OnFailed(error_code, net::ErrorToString(error_code));
- else
- DLOG(ERROR) << "No bridge for socket_id=" << socket_id;
-}
-
-} // namespace content
diff --git a/chromium/content/child/socket_stream_dispatcher.h b/chromium/content/child/socket_stream_dispatcher.h
deleted file mode 100644
index 25596005c7e..00000000000
--- a/chromium/content/child/socket_stream_dispatcher.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_CHILD_SOCKET_STREAM_DISPATCHER_H_
-#define CONTENT_CHILD_SOCKET_STREAM_DISPATCHER_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ipc/ipc_listener.h"
-
-namespace blink {
-class WebSocketStreamHandle;
-}
-
-namespace content {
-
-class WebSocketStreamHandleBridge;
-class WebSocketStreamHandleDelegate;
-
-// Dispatches socket stream related messages sent to a child process from the
-// main browser process. There is one instance per child process. Messages
-// are dispatched on the main child thread. The RenderThread class
-// creates an instance of SocketStreamDispatcher and delegates calls to it.
-class SocketStreamDispatcher : public IPC::Listener {
- public:
- SocketStreamDispatcher();
- virtual ~SocketStreamDispatcher() {}
-
- static WebSocketStreamHandleBridge* CreateBridge(
- blink::WebSocketStreamHandle* handle,
- WebSocketStreamHandleDelegate* delegate);
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- private:
- void OnConnected(int socket_id, int max_amount_send_allowed);
- void OnSentData(int socket_id, int amount_sent);
- void OnReceivedData(int socket_id, const std::vector<char>& data);
- void OnClosed(int socket_id);
- void OnFailed(int socket_id, int error_code);
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_SOCKET_STREAM_DISPATCHER_H_
diff --git a/chromium/content/child/thread_safe_sender.cc b/chromium/content/child/thread_safe_sender.cc
index 44fc89907cd..d9ecfd1ca30 100644
--- a/chromium/content/child/thread_safe_sender.cc
+++ b/chromium/content/child/thread_safe_sender.cc
@@ -10,8 +10,9 @@
namespace content {
-ThreadSafeSender::ThreadSafeSender(base::MessageLoopProxy* main_loop,
- IPC::SyncMessageFilter* sync_filter)
+ThreadSafeSender::ThreadSafeSender(
+ const scoped_refptr<base::MessageLoopProxy>& main_loop,
+ const scoped_refptr<IPC::SyncMessageFilter>& sync_filter)
: main_loop_(main_loop), sync_filter_(sync_filter) {
}
diff --git a/chromium/content/child/thread_safe_sender.h b/chromium/content/child/thread_safe_sender.h
index 6cd5c7517e9..443e20a720a 100644
--- a/chromium/content/child/thread_safe_sender.h
+++ b/chromium/content/child/thread_safe_sender.h
@@ -26,7 +26,7 @@ class CONTENT_EXPORT ThreadSafeSender
: public IPC::Sender,
public base::RefCountedThreadSafe<ThreadSafeSender> {
public:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
private:
friend class ChildThread; // for construction
@@ -34,9 +34,9 @@ class CONTENT_EXPORT ThreadSafeSender
friend class WebIDBCursorImplTest;
friend class base::RefCountedThreadSafe<ThreadSafeSender>;
- ThreadSafeSender(base::MessageLoopProxy* main_loop,
- IPC::SyncMessageFilter* sync_filter);
- virtual ~ThreadSafeSender();
+ ThreadSafeSender(const scoped_refptr<base::MessageLoopProxy>& main_loop,
+ const scoped_refptr<IPC::SyncMessageFilter>& sync_filter);
+ ~ThreadSafeSender() override;
scoped_refptr<base::MessageLoopProxy> main_loop_;
scoped_refptr<IPC::SyncMessageFilter> sync_filter_;
diff --git a/chromium/content/child/threaded_data_provider.cc b/chromium/content/child/threaded_data_provider.cc
index 118b60cdfa2..f7a6c66f1dd 100644
--- a/chromium/content/child/threaded_data_provider.cc
+++ b/chromium/content/child/threaded_data_provider.cc
@@ -31,11 +31,11 @@ class DataProviderMessageFilter : public IPC::MessageFilter {
int request_id);
// IPC::ChannelProxy::MessageFilter
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE FINAL;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE FINAL;
+ void OnFilterAdded(IPC::Sender* sender) final;
+ bool OnMessageReceived(const IPC::Message& message) final;
private:
- virtual ~DataProviderMessageFilter() { }
+ ~DataProviderMessageFilter() override {}
void OnReceivedData(int request_id, int data_offset, int data_length,
int encoded_data_length);
@@ -124,14 +124,14 @@ ThreadedDataProvider::ThreadedDataProvider(
: request_id_(request_id),
shm_buffer_(shm_buffer),
shm_size_(shm_size),
- main_thread_weak_factory_(this),
background_thread_(
static_cast<WebThreadImpl&>(
*threaded_data_receiver->backgroundThread())),
ipc_channel_(ChildThread::current()->channel()),
threaded_data_receiver_(threaded_data_receiver),
resource_filter_active_(false),
- main_thread_message_loop_(ChildThread::current()->message_loop()) {
+ main_thread_message_loop_(ChildThread::current()->message_loop()),
+ main_thread_weak_factory_(this) {
DCHECK(ChildThread::current());
DCHECK(ipc_channel_);
DCHECK(threaded_data_receiver_);
@@ -148,13 +148,13 @@ ThreadedDataProvider::ThreadedDataProvider(
main_thread_weak_factory_.GetWeakPtr(),
request_id);
- ChildThread::current()->channel()->AddFilter(filter_);
+ ChildThread::current()->channel()->AddFilter(filter_.get());
}
ThreadedDataProvider::~ThreadedDataProvider() {
DCHECK(ChildThread::current());
- ChildThread::current()->channel()->RemoveFilter(filter_);
+ ChildThread::current()->channel()->RemoveFilter(filter_.get());
delete threaded_data_receiver_;
}
diff --git a/chromium/content/child/threaded_data_provider.h b/chromium/content/child/threaded_data_provider.h
index 223153f414e..27e6d6062e7 100644
--- a/chromium/content/child/threaded_data_provider.h
+++ b/chromium/content/child/threaded_data_provider.h
@@ -22,12 +22,7 @@ namespace IPC {
class SyncChannel;
}
-namespace webkit_glue {
-class WebThreadImpl;
-}
-
namespace content {
-class ResourceDispatcher;
class WebThreadImpl;
class ThreadedDataProvider {
@@ -61,8 +56,6 @@ class ThreadedDataProvider {
int shm_size_;
scoped_ptr<base::WeakPtrFactory<ThreadedDataProvider> >
background_thread_weak_factory_;
- base::WeakPtrFactory<ThreadedDataProvider>
- main_thread_weak_factory_;
WebThreadImpl& background_thread_;
IPC::SyncChannel* ipc_channel_;
blink::WebThreadedDataReceiver* threaded_data_receiver_;
@@ -75,6 +68,9 @@ class ThreadedDataProvider {
};
std::vector<QueuedSharedMemoryData> queued_data_;
+ base::WeakPtrFactory<ThreadedDataProvider>
+ main_thread_weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ThreadedDataProvider);
};
diff --git a/chromium/content/child/touch_fling_gesture_curve.cc b/chromium/content/child/touch_fling_gesture_curve.cc
deleted file mode 100644
index cc94bd62128..00000000000
--- a/chromium/content/child/touch_fling_gesture_curve.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2014 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 "content/child/touch_fling_gesture_curve.h"
-
-#include <cmath>
-
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-
-using blink::WebFloatPoint;
-using blink::WebFloatSize;
-using blink::WebGestureCurve;
-using blink::WebGestureCurveTarget;
-using blink::WebSize;
-
-namespace {
-
-const char* kCurveName = "TouchFlingGestureCurve";
-
-inline double position(double t, float* p) {
- return p[0] * exp(-p[2] * t) - p[1] * t - p[0];
-}
-
-inline double velocity(double t, float* p) {
- return -p[0] * p[2] * exp(-p[2] * t) - p[1];
-}
-
-inline double timeAtVelocity(double v, float* p) {
- DCHECK(p[0]);
- DCHECK(p[2]);
- return -log((v + p[1]) / (-p[0] * p[2])) / p[2];
-}
-
-} // namespace
-
-
-namespace content {
-
-// This curve implementation is based on the notion of a single, absolute
-// curve, which starts at a large velocity and smoothly decreases to
-// zero. For a given input velocity, we find where on the curve this
-// velocity occurs, and start the animation at this point---denoted by
-// (time_offset_, position_offset_).
-//
-// This has the effect of automatically determining an animation duration
-// that scales with input velocity, as faster initial velocities start
-// earlier on the curve and thus take longer to reach the end. No
-// complicated time scaling is required.
-//
-// Since the starting velocity is implicitly determined by our starting
-// point, we only store the relative magnitude and direction of both
-// initial x- and y-velocities, and use this to scale the computed
-// displacement at any point in time. This guarantees that fling
-// trajectories are straight lines when viewed in x-y space. Initial
-// velocities that lie outside the max velocity are constrained to start
-// at zero (and thus are implicitly scaled).
-//
-// The curve is modelled as a 4th order polynomial, starting at t = 0,
-// and ending at t = curve_duration_. Attempts to generate
-// position/velocity estimates outside this range are undefined.
-
-WebGestureCurve* TouchFlingGestureCurve::Create(
- const WebFloatPoint& initial_velocity,
- float p0,
- float p1,
- float p2,
- const WebSize& cumulative_scroll) {
- return new TouchFlingGestureCurve(initial_velocity, p0, p1, p2,
- cumulative_scroll);
-}
-
-TouchFlingGestureCurve::TouchFlingGestureCurve(
- const WebFloatPoint& initial_velocity,
- float alpha,
- float beta,
- float gamma,
- const WebSize& cumulative_scroll)
- : cumulative_scroll_(WebFloatSize(cumulative_scroll.width,
- cumulative_scroll.height)) {
- DCHECK(initial_velocity != WebFloatPoint());
-
- coefficients_[0] = alpha;
- coefficients_[1] = beta;
- coefficients_[2] = gamma;
-
- // Curve ends when velocity reaches zero.
- curve_duration_ = timeAtVelocity(0, coefficients_);
- DCHECK(curve_duration_ > 0);
-
- float max_start_velocity = std::max(fabs(initial_velocity.x),
- fabs(initial_velocity.y));
-
- // Force max_start_velocity to lie in the range v(0) to v(curve_duration),
- // and assume that the curve parameters define a monotonically decreasing
- // velocity, or else bisection search may fail.
- if (max_start_velocity > velocity(0, coefficients_))
- max_start_velocity = velocity(0, coefficients_);
-
- if (max_start_velocity < 0)
- max_start_velocity = 0;
-
- // We keep track of relative magnitudes and directions of the
- // velocity/displacement components here.
- displacement_ratio_ = WebFloatPoint(initial_velocity.x / max_start_velocity,
- initial_velocity.y / max_start_velocity);
-
- // Compute time-offset for start velocity.
- time_offset_ = timeAtVelocity(max_start_velocity, coefficients_);
-
- // Compute curve position at offset time
- position_offset_ = position(time_offset_, coefficients_);
- TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve",
- kCurveName);
-}
-
-TouchFlingGestureCurve::~TouchFlingGestureCurve() {
- TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
-}
-
-bool TouchFlingGestureCurve::apply(double time, WebGestureCurveTarget* target) {
- // If the fling has yet to start, simply return and report true to prevent
- // fling termination.
- if (time <= 0)
- return true;
-
- float displacement;
- float speed;
- if (time + time_offset_ < curve_duration_) {
- displacement =
- position(time + time_offset_, coefficients_) - position_offset_;
- speed = velocity(time + time_offset_, coefficients_);
- } else {
- displacement = position(curve_duration_, coefficients_) - position_offset_;
- speed = 0.f;
- }
-
- // Keep track of integer portion of scroll thus far, and prepare increment.
- WebFloatSize scroll(displacement * displacement_ratio_.x,
- displacement * displacement_ratio_.y);
- WebFloatSize scroll_increment(scroll.width - cumulative_scroll_.width,
- scroll.height - cumulative_scroll_.height);
- WebFloatSize scroll_velocity(speed * displacement_ratio_.x,
- speed * displacement_ratio_.y);
- cumulative_scroll_ = scroll;
-
- if (time + time_offset_ < curve_duration_ ||
- scroll_increment != WebFloatSize()) {
- // scrollBy() could delete this curve if the animation is over, so don't
- // touch any member variables after making that call.
- return target->scrollBy(scroll_increment, scroll_velocity);
- }
-
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/child/touch_fling_gesture_curve.h b/chromium/content/child/touch_fling_gesture_curve.h
deleted file mode 100644
index 555fc740dad..00000000000
--- a/chromium/content/child/touch_fling_gesture_curve.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
-#define CONTENT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
-
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-
-namespace blink {
-class WebGestureCurveTarget;
-}
-
-namespace content {
-
-// Implementation of WebGestureCurve suitable for touch pad/screen-based
-// fling scroll. Starts with a flat velocity profile based on 'velocity', which
-// tails off to zero. Time is scaled to that duration of the fling is
-// proportional to the initial velocity.
-class TouchFlingGestureCurve : public blink::WebGestureCurve {
- public:
-
- static CONTENT_EXPORT WebGestureCurve* Create(
- const blink::WebFloatPoint& initial_velocity,
- float p0, float p1, float p2,
- const blink::WebSize& cumulativeScroll);
-
- virtual bool apply(double monotonicTime,
- blink::WebGestureCurveTarget*) OVERRIDE;
-
- private:
- TouchFlingGestureCurve(const blink::WebFloatPoint& initial_velocity,
- float p0,
- float p1,
- float p2,
- const blink::WebSize& cumulativeScroll);
- virtual ~TouchFlingGestureCurve();
-
- blink::WebFloatPoint displacement_ratio_;
- blink::WebFloatSize cumulative_scroll_;
- float coefficients_[3];
- float time_offset_;
- float curve_duration_;
- float position_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(TouchFlingGestureCurve);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
diff --git a/chromium/content/child/touch_fling_gesture_curve_unittest.cc b/chromium/content/child/touch_fling_gesture_curve_unittest.cc
deleted file mode 100644
index 9c42e638d56..00000000000
--- a/chromium/content/child/touch_fling_gesture_curve_unittest.cc
+++ /dev/null
@@ -1,70 +0,0 @@
- // Copyright 2014 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.
-
-// Tests for the TouchFlingGestureCurve.
-
-#include "content/child/touch_fling_gesture_curve.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-
-using blink::WebFloatPoint;
-using blink::WebFloatSize;
-using blink::WebGestureCurve;
-using blink::WebGestureCurveTarget;
-using blink::WebSize;
-
-namespace {
-
-class MockGestureCurveTarget : public WebGestureCurveTarget {
- public:
- virtual bool scrollBy(const WebFloatSize& delta,
- const WebFloatSize& velocity) OVERRIDE {
- cumulative_delta_.width += delta.width;
- cumulative_delta_.height += delta.height;
- current_velocity_ = velocity;
- return true;
- }
-
- WebFloatSize cumulative_delta() const { return cumulative_delta_; }
- void resetCumulativeDelta() { cumulative_delta_ = WebFloatSize(); }
-
- WebFloatSize current_velocity() const { return current_velocity_; }
-
- private:
- WebFloatSize cumulative_delta_;
- WebFloatSize current_velocity_;
-};
-
-} // namespace anonymous
-
-TEST(TouchFlingGestureCurve, flingCurveTouch)
-{
- double initialVelocity = 5000;
- MockGestureCurveTarget target;
-
- scoped_ptr<WebGestureCurve> curve(content::TouchFlingGestureCurve::Create(
- WebFloatPoint(initialVelocity, 0),
- -5.70762e+03f, 1.72e+02f, 3.7e+00f, WebSize()));
-
- // Note: the expectations below are dependent on the curve parameters hard
- // coded into the create call above.
- EXPECT_TRUE(curve->apply(0, &target));
- EXPECT_TRUE(curve->apply(0.25, &target));
- EXPECT_NEAR(target.current_velocity().width, 1878, 1);
- EXPECT_EQ(target.current_velocity().height, 0);
- EXPECT_TRUE(curve->apply(0.45f, &target)); // Use non-uniform tick spacing.
- EXPECT_TRUE(curve->apply(1, &target));
- EXPECT_FALSE(curve->apply(1.5, &target));
- EXPECT_NEAR(target.cumulative_delta().width, 1193, 1);
- EXPECT_EQ(target.cumulative_delta().height, 0);
- EXPECT_EQ(target.current_velocity().width, 0);
- EXPECT_EQ(target.current_velocity().height, 0);
-}
-
diff --git a/chromium/content/child/web_data_consumer_handle_impl.cc b/chromium/content/child/web_data_consumer_handle_impl.cc
new file mode 100644
index 00000000000..ab97b57e361
--- /dev/null
+++ b/chromium/content/child/web_data_consumer_handle_impl.cc
@@ -0,0 +1,116 @@
+// Copyright 2014 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 "content/child/web_data_consumer_handle_impl.h"
+
+#include <limits>
+#include "base/bind.h"
+#include "base/logging.h"
+#include "mojo/public/c/system/types.h"
+
+namespace content {
+
+typedef blink::WebDataConsumerHandle::Result Result;
+
+WebDataConsumerHandleImpl::WebDataConsumerHandleImpl(Handle handle)
+ : handle_(handle.Pass()), client_(nullptr) {}
+
+WebDataConsumerHandleImpl::~WebDataConsumerHandleImpl() {}
+
+Result WebDataConsumerHandleImpl::read(
+ void* data,
+ size_t size,
+ Flags flags,
+ size_t* read_size) {
+ // We need this variable definition to avoid a link error.
+ const Flags kNone = FlagNone;
+ DCHECK_EQ(flags, kNone);
+ DCHECK_LE(size, std::numeric_limits<uint32_t>::max());
+
+ *read_size = 0;
+
+ uint32_t size_to_pass = size;
+ MojoReadDataFlags flags_to_pass = MOJO_READ_DATA_FLAG_NONE;
+ MojoResult rv =
+ mojo::ReadDataRaw(handle_.get(), data, &size_to_pass, flags_to_pass);
+ if (rv == MOJO_RESULT_OK)
+ *read_size = size_to_pass;
+
+ return HandleReadResult(rv);
+}
+
+Result WebDataConsumerHandleImpl::beginRead(
+ const void** buffer, Flags flags, size_t* available) {
+ // We need this variable definition to avoid a link error.
+ const Flags kNone = FlagNone;
+ DCHECK_EQ(flags, kNone);
+
+ *buffer = nullptr;
+ *available = 0;
+
+ uint32_t size_to_pass = 0;
+ MojoReadDataFlags flags_to_pass = MOJO_READ_DATA_FLAG_NONE;
+
+ MojoResult rv = mojo::BeginReadDataRaw(handle_.get(), buffer,
+ &size_to_pass, flags_to_pass);
+ if (rv == MOJO_RESULT_OK)
+ *available = size_to_pass;
+ return HandleReadResult(rv);
+}
+
+Result WebDataConsumerHandleImpl::endRead(size_t read_size) {
+ MojoResult rv = mojo::EndReadDataRaw(handle_.get(), read_size);
+ return
+ rv == MOJO_RESULT_OK ? Ok : UnexpectedError;
+}
+
+void WebDataConsumerHandleImpl::registerClient(Client* client) {
+ DCHECK(!client_);
+ DCHECK(client);
+ client_ = client;
+
+ handle_watcher_.Start(
+ handle_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE,
+ base::Bind(&WebDataConsumerHandleImpl::OnHandleGotReadable,
+ base::Unretained(this)));
+}
+
+void WebDataConsumerHandleImpl::unregisterClient() {
+ client_ = nullptr;
+ handle_watcher_.Stop();
+}
+
+Result WebDataConsumerHandleImpl::HandleReadResult(MojoResult mojo_result) {
+ switch (mojo_result) {
+ case MOJO_RESULT_OK:
+ return Ok;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ return Done;
+ case MOJO_RESULT_BUSY:
+ return Busy;
+ case MOJO_RESULT_SHOULD_WAIT:
+ if (client_) {
+ handle_watcher_.Start(
+ handle_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE,
+ MOJO_DEADLINE_INDEFINITE,
+ base::Bind(&WebDataConsumerHandleImpl::OnHandleGotReadable,
+ base::Unretained(this)));
+ }
+ return ShouldWait;
+ case MOJO_RESULT_RESOURCE_EXHAUSTED:
+ return ResourceExhausted;
+ default:
+ return UnexpectedError;
+ }
+}
+
+void WebDataConsumerHandleImpl::OnHandleGotReadable(MojoResult) {
+ DCHECK(client_);
+ client_->didGetReadable();
+}
+
+} // namespace content
diff --git a/chromium/content/child/web_data_consumer_handle_impl.h b/chromium/content/child/web_data_consumer_handle_impl.h
new file mode 100644
index 00000000000..5edef3f21a5
--- /dev/null
+++ b/chromium/content/child/web_data_consumer_handle_impl.h
@@ -0,0 +1,40 @@
+// Copyright 2014 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 CONTENT_CHILD_WEB_DATA_CONSUMER_HANDLE_IMPL_H_
+#define CONTENT_CHILD_WEB_DATA_CONSUMER_HANDLE_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "mojo/common/handle_watcher.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "third_party/WebKit/public/platform/WebDataConsumerHandle.h"
+
+namespace content {
+
+class CONTENT_EXPORT WebDataConsumerHandleImpl final
+ : public NON_EXPORTED_BASE(blink::WebDataConsumerHandle) {
+ typedef mojo::ScopedDataPipeConsumerHandle Handle;
+ public:
+ explicit WebDataConsumerHandleImpl(Handle handle);
+ virtual ~WebDataConsumerHandleImpl();
+
+ virtual Result read(void* data, size_t size, Flags flags, size_t* readSize);
+ virtual Result beginRead(const void** buffer, Flags flags, size_t* available);
+ virtual Result endRead(size_t readSize);
+ virtual void registerClient(Client* client);
+ virtual void unregisterClient();
+
+ private:
+ Result HandleReadResult(MojoResult);
+ void OnHandleGotReadable(MojoResult);
+
+ Handle handle_;
+ Client* client_;
+ mojo::common::HandleWatcher handle_watcher_;
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEB_DATA_CONSUMER_HANDLE_IMPL_H_
diff --git a/chromium/content/child/web_data_consumer_handle_impl_unittest.cc b/chromium/content/child/web_data_consumer_handle_impl_unittest.cc
new file mode 100644
index 00000000000..7ad9d400973
--- /dev/null
+++ b/chromium/content/child/web_data_consumer_handle_impl_unittest.cc
@@ -0,0 +1,270 @@
+// Copyright 2014 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 "content/child/web_data_consumer_handle_impl.h"
+
+#include <algorithm>
+#include <string>
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+using blink::WebDataConsumerHandle;
+
+class ReadDataOperationBase {
+ public:
+ virtual ~ReadDataOperationBase() {}
+ virtual void ReadMore() = 0;
+
+ static const WebDataConsumerHandle::Flags kNone =
+ WebDataConsumerHandle::FlagNone;
+ static const WebDataConsumerHandle::Result kOk = WebDataConsumerHandle::Ok;
+ static const WebDataConsumerHandle::Result kDone =
+ WebDataConsumerHandle::Done;
+ static const WebDataConsumerHandle::Result kShouldWait =
+ WebDataConsumerHandle::ShouldWait;
+};
+
+class ClientImpl final : public WebDataConsumerHandle::Client {
+ public:
+ explicit ClientImpl(ReadDataOperationBase* operation)
+ : operation_(operation) {}
+
+ void didGetReadable() override {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&ReadDataOperationBase::ReadMore,
+ base::Unretained(operation_)));
+ }
+
+ private:
+ ReadDataOperationBase* operation_;
+};
+
+class ReadDataOperation : public ReadDataOperationBase {
+ public:
+ typedef WebDataConsumerHandle::Result Result;
+ ReadDataOperation(mojo::ScopedDataPipeConsumerHandle handle,
+ base::MessageLoop* main_message_loop,
+ const base::Closure& on_done)
+ : handle_(new WebDataConsumerHandleImpl(handle.Pass())),
+ main_message_loop_(main_message_loop),
+ on_done_(on_done) {}
+
+ const std::string& result() const { return result_; }
+
+ void ReadMore() override { ReadData(); }
+
+ void ReadData() {
+ if (!client_) {
+ client_.reset(new ClientImpl(this));
+ handle_->registerClient(client_.get());
+ }
+
+ Result rv = kOk;
+ size_t readSize = 0;
+
+ while (true) {
+ char buffer[16];
+ rv = handle_->read(&buffer, sizeof(buffer), kNone, &readSize);
+ if (rv != kOk)
+ break;
+ result_.insert(result_.size(), &buffer[0], readSize);
+ }
+
+ if (rv == kShouldWait) {
+ // Wait a while...
+ return;
+ }
+
+ if (rv != kDone) {
+ // Something is wrong.
+ result_ = "error";
+ }
+
+ // The operation is done.
+ main_message_loop_->PostTask(FROM_HERE, on_done_);
+ }
+
+ private:
+ scoped_ptr<WebDataConsumerHandle> handle_;
+ scoped_ptr<WebDataConsumerHandle::Client> client_;
+ base::MessageLoop* main_message_loop_;
+ base::Closure on_done_;
+ std::string result_;
+};
+
+class TwoPhaseReadDataOperation : public ReadDataOperationBase {
+ public:
+ typedef WebDataConsumerHandle::Result Result;
+ TwoPhaseReadDataOperation(mojo::ScopedDataPipeConsumerHandle handle,
+ base::MessageLoop* main_message_loop,
+ const base::Closure& on_done)
+ : handle_(new WebDataConsumerHandleImpl(handle.Pass())),
+ main_message_loop_(main_message_loop), on_done_(on_done) {}
+
+ const std::string& result() const { return result_; }
+
+ void ReadMore() override {
+ ReadData();
+ }
+
+ void ReadData() {
+ if (!client_) {
+ client_.reset(new ClientImpl(this));
+ handle_->registerClient(client_.get());
+ }
+
+ Result rv;
+ while (true) {
+ const void* buffer = nullptr;
+ size_t size;
+ rv = handle_->beginRead(&buffer, kNone, &size);
+ if (rv != kOk)
+ break;
+ // In order to verify endRead, we read at most one byte for each time.
+ size_t read_size = std::max(static_cast<size_t>(1), size);
+ result_.insert(result_.size(), static_cast<const char*>(buffer),
+ read_size);
+ rv = handle_->endRead(read_size);
+ if (rv != kOk) {
+ // Something is wrong.
+ result_ = "error";
+ main_message_loop_->PostTask(FROM_HERE, on_done_);
+ return;
+ }
+ }
+
+ if (rv == kShouldWait) {
+ // Wait a while...
+ return;
+ }
+
+ if (rv != kDone) {
+ // Something is wrong.
+ result_ = "error";
+ }
+
+ // The operation is done.
+ main_message_loop_->PostTask(FROM_HERE, on_done_);
+ }
+
+ private:
+ scoped_ptr<WebDataConsumerHandle> handle_;
+ scoped_ptr<WebDataConsumerHandle::Client> client_;
+ base::MessageLoop* main_message_loop_;
+ base::Closure on_done_;
+ std::string result_;
+};
+
+class WebDataConsumerHandleImplTest : public ::testing::Test {
+ public:
+ typedef WebDataConsumerHandle::Result Result;
+
+ void SetUp() override {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = 4;
+
+ MojoResult result = mojo::CreateDataPipe(&options, &producer_, &consumer_);
+ ASSERT_EQ(MOJO_RESULT_OK, result);
+ }
+
+ // This function can be blocked if the associated consumer doesn't consume
+ // the data.
+ std::string ProduceData(size_t total_size) {
+ int index = 0;
+ std::string expected;
+ for (size_t i = 0; i < total_size; ++i) {
+ expected += static_cast<char>(index + 'a');
+ index = (37 * index + 11) % 26;
+ }
+
+ const char* p = expected.data();
+ size_t remaining = total_size;
+ const MojoWriteDataFlags kNone = MOJO_WRITE_DATA_FLAG_NONE;
+ MojoResult rv;
+ while (remaining > 0) {
+ uint32_t size = remaining;
+ rv = mojo::WriteDataRaw(producer_.get(), p, &size, kNone);
+ if (rv == MOJO_RESULT_OK) {
+ remaining -= size;
+ p += size;
+ } else if (rv != MOJO_RESULT_SHOULD_WAIT) {
+ // Something is wrong.
+ EXPECT_TRUE(false) << "mojo::WriteDataRaw returns an invalid value.";
+ return "error on writing";
+ }
+ }
+ return expected;
+ }
+
+ base::MessageLoop message_loop_;
+
+ mojo::ScopedDataPipeProducerHandle producer_;
+ mojo::ScopedDataPipeConsumerHandle consumer_;
+};
+
+TEST_F(WebDataConsumerHandleImplTest, ReadData) {
+ base::RunLoop run_loop;
+ auto operation = make_scoped_ptr(new ReadDataOperation(
+ consumer_.Pass(),
+ &message_loop_,
+ run_loop.QuitClosure()));
+
+ base::Thread t("DataConsumerHandle test thread");
+ ASSERT_TRUE(t.Start());
+
+ t.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&ReadDataOperation::ReadData,
+ base::Unretained(operation.get())));
+
+ std::string expected = ProduceData(24 * 1024);
+ producer_.reset();
+
+ run_loop.Run();
+ t.Stop();
+
+ EXPECT_EQ(expected, operation->result());
+}
+
+TEST_F(WebDataConsumerHandleImplTest, TwoPhaseReadData) {
+ base::RunLoop run_loop;
+ auto operation = make_scoped_ptr(new TwoPhaseReadDataOperation(
+ consumer_.Pass(),
+ &message_loop_,
+ run_loop.QuitClosure()));
+
+ base::Thread t("DataConsumerHandle test thread");
+ ASSERT_TRUE(t.Start());
+
+ t.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&TwoPhaseReadDataOperation::ReadData,
+ base::Unretained(operation.get())));
+
+ std::string expected = ProduceData(24 * 1024);
+ producer_.reset();
+
+ run_loop.Run();
+ t.Stop();
+
+ EXPECT_EQ(expected, operation->result());
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/child/web_database_observer_impl.cc b/chromium/content/child/web_database_observer_impl.cc
index f06823eee6c..3a88133a31c 100644
--- a/chromium/content/child/web_database_observer_impl.cc
+++ b/chromium/content/child/web_database_observer_impl.cc
@@ -38,34 +38,22 @@ int DetermineHistogramResult(int websql_error, int sqlite_error) {
return std::min(websql_error + 30, kResultHistogramSize - 1);
}
-#define HISTOGRAM_WEBSQL_RESULT(name, is_sync_database, \
- callsite, websql_error, sqlite_error) \
+#define UMA_HISTOGRAM_WEBSQL_RESULT(name, callsite, websql_error, sqlite_error) \
do { \
DCHECK(callsite < kCallsiteHistogramSize); \
int result = DetermineHistogramResult(websql_error, sqlite_error); \
- if (is_sync_database) { \
- UMA_HISTOGRAM_ENUMERATION("websql.Sync." name, \
- result, kResultHistogramSize); \
- if (result) { \
- UMA_HISTOGRAM_ENUMERATION("websql.Sync." name ".ErrorSite", \
- callsite, kCallsiteHistogramSize); \
- } \
- } else { \
- UMA_HISTOGRAM_ENUMERATION("websql.Async." name, \
- result, kResultHistogramSize); \
- if (result) { \
- UMA_HISTOGRAM_ENUMERATION("websql.Async." name ".ErrorSite", \
- callsite, kCallsiteHistogramSize); \
- } \
+ UMA_HISTOGRAM_ENUMERATION("websql.Async." name, \
+ result, kResultHistogramSize); \
+ if (result) { \
+ UMA_HISTOGRAM_ENUMERATION("websql.Async." name ".ErrorSite", \
+ callsite, kCallsiteHistogramSize); \
} \
} while (0)
-
} // namespace
-WebDatabaseObserverImpl::WebDatabaseObserverImpl(
- IPC::SyncMessageFilter* sender)
+WebDatabaseObserverImpl::WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender)
: sender_(sender),
- open_connections_(new webkit_database::DatabaseConnectionsWrapper) {
+ open_connections_(new storage::DatabaseConnectionsWrapper) {
DCHECK(sender);
}
@@ -103,66 +91,56 @@ void WebDatabaseObserverImpl::databaseClosed(
void WebDatabaseObserverImpl::reportOpenDatabaseResult(
const WebString& origin_identifier,
const WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("OpenResult", is_sync_database,
- callsite, websql_error, sqlite_error);
+ UMA_HISTOGRAM_WEBSQL_RESULT("OpenResult", callsite,
+ websql_error, sqlite_error);
HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportChangeVersionResult(
const WebString& origin_identifier,
const WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", is_sync_database,
- callsite, websql_error, sqlite_error);
+ UMA_HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", callsite,
+ websql_error, sqlite_error);
HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportStartTransactionResult(
const WebString& origin_identifier,
const WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("BeginResult", is_sync_database,
- callsite, websql_error, sqlite_error);
+ UMA_HISTOGRAM_WEBSQL_RESULT("BeginResult", callsite,
+ websql_error, sqlite_error);
HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportCommitTransactionResult(
const WebString& origin_identifier,
const WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("CommitResult", is_sync_database,
- callsite, websql_error, sqlite_error);
+ UMA_HISTOGRAM_WEBSQL_RESULT("CommitResult", callsite,
+ websql_error, sqlite_error);
HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportExecuteStatementResult(
const WebString& origin_identifier,
const WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error) {
- HISTOGRAM_WEBSQL_RESULT("StatementResult", is_sync_database,
- callsite, websql_error, sqlite_error);
+ UMA_HISTOGRAM_WEBSQL_RESULT("StatementResult", callsite,
+ websql_error, sqlite_error);
HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportVacuumDatabaseResult(
const WebString& origin_identifier,
const WebString& database_name,
- bool is_sync_database,
int sqlite_error) {
int result = DetermineHistogramResult(-1, sqlite_error);
- if (is_sync_database) {
- UMA_HISTOGRAM_ENUMERATION("websql.Sync.VacuumResult",
- result, kResultHistogramSize);
- } else {
- UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
+ UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
result, kResultHistogramSize);
- }
+
HandleSqliteError(origin_identifier, database_name, sqlite_error);
}
diff --git a/chromium/content/child/web_database_observer_impl.h b/chromium/content/child/web_database_observer_impl.h
index ed85b9213b5..09761096163 100644
--- a/chromium/content/child/web_database_observer_impl.h
+++ b/chromium/content/child/web_database_observer_impl.h
@@ -7,8 +7,8 @@
#include "base/memory/ref_counted.h"
#include "ipc/ipc_sync_message_filter.h"
+#include "storage/common/database/database_connections.h"
#include "third_party/WebKit/public/platform/WebDatabaseObserver.h"
-#include "webkit/common/database/database_connections.h"
namespace content {
@@ -31,32 +31,26 @@ class WebDatabaseObserverImpl : public blink::WebDatabaseObserver {
virtual void reportOpenDatabaseResult(
const blink::WebString& origin_identifier,
const blink::WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error);
virtual void reportChangeVersionResult(
const blink::WebString& origin_identifier,
const blink::WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error);
virtual void reportStartTransactionResult(
const blink::WebString& origin_identifier,
const blink::WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error);
virtual void reportCommitTransactionResult(
const blink::WebString& origin_identifier,
const blink::WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error);
virtual void reportExecuteStatementResult(
const blink::WebString& origin_identifier,
const blink::WebString& database_name,
- bool is_sync_database,
int callsite, int websql_error, int sqlite_error);
virtual void reportVacuumDatabaseResult(
const blink::WebString& origin_identifier,
const blink::WebString& database_name,
- bool is_sync_database,
int sqlite_error);
void WaitForAllDatabasesToClose();
@@ -67,7 +61,7 @@ class WebDatabaseObserverImpl : public blink::WebDatabaseObserver {
int error);
scoped_refptr<IPC::SyncMessageFilter> sender_;
- scoped_refptr<webkit_database::DatabaseConnectionsWrapper> open_connections_;
+ scoped_refptr<storage::DatabaseConnectionsWrapper> open_connections_;
DISALLOW_COPY_AND_ASSIGN(WebDatabaseObserverImpl);
};
diff --git a/chromium/content/child/web_gesture_curve_impl.cc b/chromium/content/child/web_gesture_curve_impl.cc
new file mode 100644
index 00000000000..5324b363969
--- /dev/null
+++ b/chromium/content/child/web_gesture_curve_impl.cc
@@ -0,0 +1,97 @@
+// Copyright 2014 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 "content/child/web_gesture_curve_impl.h"
+
+#include "base/logging.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "ui/events/gestures/fling_curve.h"
+#include "ui/gfx/vector2d.h"
+
+#if defined(OS_ANDROID)
+#include "ui/events/android/scroller.h"
+#endif
+
+using blink::WebGestureCurve;
+
+namespace content {
+namespace {
+
+scoped_ptr<ui::GestureCurve> CreateDefaultPlatformCurve(
+ const gfx::Vector2dF& initial_velocity) {
+ DCHECK(!initial_velocity.IsZero());
+#if defined(OS_ANDROID)
+ auto scroller = make_scoped_ptr(new ui::Scroller(ui::Scroller::Config()));
+ scroller->Fling(0,
+ 0,
+ initial_velocity.x(),
+ initial_velocity.y(),
+ INT_MIN,
+ INT_MAX,
+ INT_MIN,
+ INT_MAX,
+ base::TimeTicks());
+ return scroller.Pass();
+#else
+ return make_scoped_ptr(
+ new ui::FlingCurve(initial_velocity, base::TimeTicks()));
+#endif
+}
+
+} // namespace
+
+// static
+scoped_ptr<WebGestureCurve> WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
+ const gfx::Vector2dF& initial_velocity,
+ const gfx::Vector2dF& initial_offset) {
+ return CreateFrom(CreateDefaultPlatformCurve(initial_velocity),
+ initial_offset);
+}
+
+// static
+scoped_ptr<WebGestureCurve> WebGestureCurveImpl::CreateFrom(
+ scoped_ptr<ui::GestureCurve> curve,
+ const gfx::Vector2dF& initial_offset) {
+ return scoped_ptr<WebGestureCurve>(
+ new WebGestureCurveImpl(curve.Pass(), initial_offset));
+}
+
+WebGestureCurveImpl::WebGestureCurveImpl(scoped_ptr<ui::GestureCurve> curve,
+ const gfx::Vector2dF& initial_offset)
+ : curve_(curve.Pass()), last_offset_(initial_offset) {
+}
+
+WebGestureCurveImpl::~WebGestureCurveImpl() {
+}
+
+bool WebGestureCurveImpl::apply(double time,
+ blink::WebGestureCurveTarget* target) {
+ // If the fling has yet to start, simply return and report true to prevent
+ // fling termination.
+ if (time <= 0)
+ return true;
+
+ const base::TimeTicks time_ticks =
+ base::TimeTicks() + base::TimeDelta::FromSecondsD(time);
+ gfx::Vector2dF offset, velocity;
+ bool still_active =
+ curve_->ComputeScrollOffset(time_ticks, &offset, &velocity);
+
+ gfx::Vector2dF delta = offset - last_offset_;
+ last_offset_ = offset;
+
+ // As successive timestamps can be arbitrarily close (but monotonic!), don't
+ // assume that a zero delta means the curve has terminated.
+ if (delta.IsZero())
+ return still_active;
+
+ // scrollBy() could delete this curve if the animation is over, so don't touch
+ // any member variables after making that call.
+ bool did_scroll = target->scrollBy(blink::WebFloatSize(delta),
+ blink::WebFloatSize(velocity));
+ return did_scroll && still_active;
+}
+
+} // namespace content
diff --git a/chromium/content/child/web_gesture_curve_impl.h b/chromium/content/child/web_gesture_curve_impl.h
new file mode 100644
index 00000000000..cb0d0bfeef5
--- /dev/null
+++ b/chromium/content/child/web_gesture_curve_impl.h
@@ -0,0 +1,53 @@
+// Copyright 2014 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 CONTENT_CHILD_WEB_GESTURE_CURVE_IMPL_H_
+#define CONTENT_CHILD_WEB_GESTURE_CURVE_IMPL_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+namespace blink {
+class WebGestureCurveTarget;
+}
+
+namespace ui {
+class GestureCurve;
+}
+
+namespace content {
+
+class CONTENT_EXPORT WebGestureCurveImpl
+ : public NON_EXPORTED_BASE(blink::WebGestureCurve) {
+ public:
+ static scoped_ptr<blink::WebGestureCurve> CreateFromDefaultPlatformCurve(
+ const gfx::Vector2dF& initial_velocity,
+ const gfx::Vector2dF& initial_offset);
+ static scoped_ptr<blink::WebGestureCurve> CreateFrom(
+ scoped_ptr<ui::GestureCurve> curve,
+ const gfx::Vector2dF& initial_offset);
+
+ virtual ~WebGestureCurveImpl();
+
+ // WebGestureCurve implementation.
+ virtual bool apply(double time,
+ blink::WebGestureCurveTarget* target) override;
+
+ private:
+ WebGestureCurveImpl(scoped_ptr<ui::GestureCurve> curve,
+ const gfx::Vector2dF& initial_offset);
+
+ scoped_ptr<ui::GestureCurve> curve_;
+
+ gfx::Vector2dF last_offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebGestureCurveImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEB_GESTURE_CURVE_IMPL_H_
diff --git a/chromium/content/child/web_gesture_curve_impl_unittest.cc b/chromium/content/child/web_gesture_curve_impl_unittest.cc
new file mode 100644
index 00000000000..787aa8f1145
--- /dev/null
+++ b/chromium/content/child/web_gesture_curve_impl_unittest.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 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 "content/child/web_gesture_curve_impl.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "ui/events/gestures/fling_curve.h"
+
+using blink::WebFloatSize;
+using blink::WebGestureCurve;
+using blink::WebGestureCurveTarget;
+
+namespace content {
+namespace {
+
+class MockGestureCurveTarget : public WebGestureCurveTarget {
+ public:
+ virtual bool scrollBy(const WebFloatSize& delta,
+ const WebFloatSize& velocity) override {
+ cumulative_delta_.width += delta.width;
+ cumulative_delta_.height += delta.height;
+ current_velocity_ = velocity;
+ return true;
+ }
+
+ const WebFloatSize& cumulative_delta() const { return cumulative_delta_; }
+ const WebFloatSize& current_velocity() const { return current_velocity_; }
+
+ private:
+ WebFloatSize cumulative_delta_;
+ WebFloatSize current_velocity_;
+};
+
+} // namespace anonymous
+
+TEST(WebGestureCurveImplTest, Basic) {
+ gfx::Vector2dF velocity(5000, 0);
+ gfx::Vector2dF offset;
+ base::TimeTicks time;
+ auto curve = WebGestureCurveImpl::CreateFrom(
+ scoped_ptr<ui::GestureCurve>(new ui::FlingCurve(velocity, time)), offset);
+
+ // coded into the create call above.
+ MockGestureCurveTarget target;
+ EXPECT_TRUE(curve->apply(0, &target));
+ EXPECT_TRUE(curve->apply(0.25, &target));
+ EXPECT_NEAR(target.current_velocity().width, 1878, 1);
+ EXPECT_EQ(target.current_velocity().height, 0);
+ EXPECT_GT(target.cumulative_delta().width, 0);
+ EXPECT_TRUE(curve->apply(0.45, &target)); // Use non-uniform tick spacing.
+
+ // Ensure fling persists even if successive timestamps are identical.
+ gfx::Vector2dF cumulative_delta = target.cumulative_delta();
+ gfx::Vector2dF current_velocity = target.current_velocity();
+ EXPECT_TRUE(curve->apply(0.45, &target));
+ EXPECT_EQ(cumulative_delta, gfx::Vector2dF(target.cumulative_delta()));
+ EXPECT_EQ(current_velocity, gfx::Vector2dF(target.current_velocity()));
+
+ EXPECT_TRUE(curve->apply(0.75, &target));
+ EXPECT_FALSE(curve->apply(1.5, &target));
+ EXPECT_NEAR(target.cumulative_delta().width, 1193, 1);
+ EXPECT_EQ(target.cumulative_delta().height, 0);
+ EXPECT_EQ(target.current_velocity().width, 0);
+ EXPECT_EQ(target.current_velocity().height, 0);
+}
+
+} // namespace content
diff --git a/chromium/content/child/web_socket_stream_handle_bridge.h b/chromium/content/child/web_socket_stream_handle_bridge.h
deleted file mode 100644
index 2655c102b29..00000000000
--- a/chromium/content/child/web_socket_stream_handle_bridge.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_BRIDGE_H_
-#define CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_BRIDGE_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-
-class GURL;
-
-namespace content {
-
-class WebSocketStreamHandleBridge
- : public base::RefCountedThreadSafe<WebSocketStreamHandleBridge> {
- public:
- virtual void Connect(const GURL& url) = 0;
-
- virtual bool Send(const std::vector<char>& data) = 0;
-
- virtual void Close() = 0;
-
- protected:
- friend class base::RefCountedThreadSafe<WebSocketStreamHandleBridge>;
- WebSocketStreamHandleBridge() {}
- virtual ~WebSocketStreamHandleBridge() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebSocketStreamHandleBridge);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_BRIDGE_H_
diff --git a/chromium/content/child/web_socket_stream_handle_delegate.h b/chromium/content/child/web_socket_stream_handle_delegate.h
deleted file mode 100644
index f7243637806..00000000000
--- a/chromium/content/child/web_socket_stream_handle_delegate.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_DELEGATE_H_
-#define CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_DELEGATE_H_
-
-#include "base/strings/string16.h"
-
-class GURL;
-
-namespace blink {
-class WebSocketStreamHandle;
-}
-
-namespace content {
-
-class WebSocketStreamHandleDelegate {
- public:
- WebSocketStreamHandleDelegate() {}
-
- virtual void WillOpenStream(blink::WebSocketStreamHandle* handle,
- const GURL& url) {}
- virtual void WillSendData(blink::WebSocketStreamHandle* handle,
- const char* data, int len) {}
-
- virtual void DidOpenStream(blink::WebSocketStreamHandle* handle,
- int max_amount_send_allowed) {}
- virtual void DidSendData(blink::WebSocketStreamHandle* handle,
- int amount_sent) {}
- virtual void DidReceiveData(blink::WebSocketStreamHandle* handle,
- const char* data, int len) {}
- virtual void DidClose(blink::WebSocketStreamHandle*) {}
- virtual void DidFail(blink::WebSocketStreamHandle* handle,
- int error_code,
- const base::string16& error_msg) {}
-
- protected:
- virtual ~WebSocketStreamHandleDelegate() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_DELEGATE_H_
diff --git a/chromium/content/child/web_socket_stream_handle_impl.cc b/chromium/content/child/web_socket_stream_handle_impl.cc
deleted file mode 100644
index 24136df7648..00000000000
--- a/chromium/content/child/web_socket_stream_handle_impl.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2014 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.
-
-// An implementation of WebSocketStreamHandle.
-
-#include "content/child/web_socket_stream_handle_impl.h"
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string16.h"
-#include "content/child/child_thread.h"
-#include "content/child/socket_stream_dispatcher.h"
-#include "content/child/web_socket_stream_handle_bridge.h"
-#include "content/child/web_socket_stream_handle_delegate.h"
-#include "third_party/WebKit/public/platform/WebData.h"
-#include "third_party/WebKit/public/platform/WebSocketStreamError.h"
-#include "third_party/WebKit/public/platform/WebSocketStreamHandleClient.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-
-using blink::WebData;
-using blink::WebSocketStreamError;
-using blink::WebSocketStreamHandle;
-using blink::WebSocketStreamHandleClient;
-using blink::WebURL;
-
-namespace content {
-
-// WebSocketStreamHandleImpl::Context -----------------------------------------
-
-class WebSocketStreamHandleImpl::Context
- : public base::RefCounted<Context>,
- public WebSocketStreamHandleDelegate {
- public:
- explicit Context(WebSocketStreamHandleImpl* handle);
-
- WebSocketStreamHandleClient* client() const { return client_; }
- void set_client(WebSocketStreamHandleClient* client) {
- client_ = client;
- }
-
- void Connect(const WebURL& url);
- bool Send(const WebData& data);
- void Close();
-
- // Must be called before |handle_| or |client_| is deleted.
- // Once detached, it never calls |client_| back.
- void Detach();
-
- // WebSocketStreamHandleDelegate methods:
- virtual void DidOpenStream(WebSocketStreamHandle*, int) OVERRIDE;
- virtual void DidSendData(WebSocketStreamHandle*, int) OVERRIDE;
- virtual void DidReceiveData(WebSocketStreamHandle*,
- const char*,
- int) OVERRIDE;
- virtual void DidClose(WebSocketStreamHandle*) OVERRIDE;
- virtual void DidFail(WebSocketStreamHandle*,
- int,
- const base::string16&) OVERRIDE;
-
- private:
- friend class base::RefCounted<Context>;
- virtual ~Context() {
- DCHECK(!handle_);
- DCHECK(!client_);
- DCHECK(!bridge_.get());
- }
-
- WebSocketStreamHandleImpl* handle_;
- WebSocketStreamHandleClient* client_;
- // |bridge_| is alive from Connect to DidClose, so Context must be alive
- // in the time period.
- scoped_refptr<WebSocketStreamHandleBridge> bridge_;
-
- DISALLOW_COPY_AND_ASSIGN(Context);
-};
-
-WebSocketStreamHandleImpl::Context::Context(WebSocketStreamHandleImpl* handle)
- : handle_(handle),
- client_(NULL) {
-}
-
-void WebSocketStreamHandleImpl::Context::Connect(const WebURL& url) {
- VLOG(1) << "Connect url=" << url;
- DCHECK(!bridge_.get());
-
- SocketStreamDispatcher* dispatcher =
- ChildThread::current()->socket_stream_dispatcher();
- bridge_ = dispatcher->CreateBridge(handle_, this);
-
- AddRef(); // Will be released by DidClose().
- bridge_->Connect(url);
-}
-
-bool WebSocketStreamHandleImpl::Context::Send(const WebData& data) {
- VLOG(1) << "Send data.size=" << data.size();
- DCHECK(bridge_.get());
- return bridge_->Send(
- std::vector<char>(data.data(), data.data() + data.size()));
-}
-
-void WebSocketStreamHandleImpl::Context::Close() {
- VLOG(1) << "Close";
- if (bridge_.get())
- bridge_->Close();
-}
-
-void WebSocketStreamHandleImpl::Context::Detach() {
- handle_ = NULL;
- client_ = NULL;
- // If Connect was called, |bridge_| is not NULL, so that this Context closes
- // the |bridge_| here. Then |bridge_| will call back DidClose, and will
- // be released by itself.
- // Otherwise, |bridge_| is NULL.
- if (bridge_.get())
- bridge_->Close();
-}
-
-void WebSocketStreamHandleImpl::Context::DidOpenStream(
- WebSocketStreamHandle* web_handle, int max_amount_send_allowed) {
- VLOG(1) << "DidOpen";
- if (client_)
- client_->didOpenStream(handle_, max_amount_send_allowed);
-}
-
-void WebSocketStreamHandleImpl::Context::DidSendData(
- WebSocketStreamHandle* web_handle, int amount_sent) {
- if (client_)
- client_->didSendData(handle_, amount_sent);
-}
-
-void WebSocketStreamHandleImpl::Context::DidReceiveData(
- WebSocketStreamHandle* web_handle, const char* data, int size) {
- if (client_)
- client_->didReceiveData(handle_, WebData(data, size));
-}
-
-void WebSocketStreamHandleImpl::Context::DidClose(
- WebSocketStreamHandle* web_handle) {
- VLOG(1) << "DidClose";
- bridge_ = NULL;
- WebSocketStreamHandleImpl* handle = handle_;
- handle_ = NULL;
- if (client_) {
- WebSocketStreamHandleClient* client = client_;
- client_ = NULL;
- client->didClose(handle);
- }
- Release();
-}
-
-void WebSocketStreamHandleImpl::Context::DidFail(
- WebSocketStreamHandle* web_handle,
- int error_code,
- const base::string16& error_msg) {
- VLOG(1) << "DidFail";
- if (client_) {
- client_->didFail(
- handle_,
- WebSocketStreamError(error_code, error_msg));
- }
-}
-
-// WebSocketStreamHandleImpl ------------------------------------------------
-
-WebSocketStreamHandleImpl::WebSocketStreamHandleImpl()
- : context_(new Context(this)) {
-}
-
-WebSocketStreamHandleImpl::~WebSocketStreamHandleImpl() {
- // We won't receive any events from |context_|.
- // |context_| is ref counted, and will be released when it received
- // DidClose.
- context_->Detach();
-}
-
-void WebSocketStreamHandleImpl::connect(
- const WebURL& url, WebSocketStreamHandleClient* client) {
- VLOG(1) << "connect url=" << url;
- DCHECK(!context_->client());
- context_->set_client(client);
-
- context_->Connect(url);
-}
-
-bool WebSocketStreamHandleImpl::send(const WebData& data) {
- return context_->Send(data);
-}
-
-void WebSocketStreamHandleImpl::close() {
- context_->Close();
-}
-
-} // namespace content
diff --git a/chromium/content/child/web_socket_stream_handle_impl.h b/chromium/content/child/web_socket_stream_handle_impl.h
deleted file mode 100644
index c8c2aca6a47..00000000000
--- a/chromium/content/child/web_socket_stream_handle_impl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_IMPL_H_
-#define CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_IMPL_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/supports_user_data.h"
-#include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
-
-namespace content {
-
-class WebSocketStreamHandleImpl : public base::SupportsUserData,
- public blink::WebSocketStreamHandle {
- public:
- WebSocketStreamHandleImpl();
- virtual ~WebSocketStreamHandleImpl();
-
- // WebSocketStreamHandle methods:
- virtual void connect(const blink::WebURL& url,
- blink::WebSocketStreamHandleClient* client);
- virtual bool send(const blink::WebData& data);
- virtual void close();
-
- private:
- class Context;
- scoped_refptr<Context> context_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSocketStreamHandleImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_SOCKET_STREAM_HANDLE_IMPL_H_
diff --git a/chromium/content/child/web_url_loader_impl.cc b/chromium/content/child/web_url_loader_impl.cc
index 138963b82a5..b51d799047c 100644
--- a/chromium/content/child/web_url_loader_impl.cc
+++ b/chromium/content/child/web_url_loader_impl.cc
@@ -7,28 +7,33 @@
#include "content/child/web_url_loader_impl.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
-#include "content/child/child_thread.h"
#include "content/child/ftp_directory_listing_response_delegate.h"
+#include "content/child/multipart_response_delegate.h"
#include "content/child/request_extra_data.h"
#include "content/child/request_info.h"
#include "content/child/resource_dispatcher.h"
+#include "content/child/resource_loader_bridge.h"
#include "content/child/sync_load_response.h"
+#include "content/child/web_url_request_util.h"
+#include "content/child/weburlresponse_extradata_impl.h"
#include "content/common/resource_request_body.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/public/child/request_peer.h"
+#include "content/public/common/content_switches.h"
#include "net/base/data_url.h"
#include "net/base/filename_util.h"
-#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
-#include "net/url_request/url_request.h"
-#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request_data_job.h"
#include "third_party/WebKit/public/platform/WebHTTPLoadInfo.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
@@ -37,9 +42,6 @@
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
-#include "webkit/child/multipart_response_delegate.h"
-#include "webkit/child/resource_loader_bridge.h"
-#include "webkit/child/weburlresponse_extradata_impl.h"
using base::Time;
using base::TimeTicks;
@@ -57,9 +59,6 @@ using blink::WebURLLoader;
using blink::WebURLLoaderClient;
using blink::WebURLRequest;
using blink::WebURLResponse;
-using webkit_glue::MultipartResponseDelegate;
-using webkit_glue::ResourceLoaderBridge;
-using webkit_glue::WebURLResponseExtraDataImpl;
namespace content {
@@ -71,74 +70,6 @@ const char kThrottledErrorDescription[] =
"Request throttled. Visit http://dev.chromium.org/throttling for more "
"information.";
-class HeaderFlattener : public WebHTTPHeaderVisitor {
- public:
- explicit HeaderFlattener() : has_accept_header_(false) {}
-
- virtual void visitHeader(const WebString& name, const WebString& value) {
- // Headers are latin1.
- const std::string& name_latin1 = name.latin1();
- const std::string& value_latin1 = value.latin1();
-
- // Skip over referrer headers found in the header map because we already
- // pulled it out as a separate parameter.
- if (LowerCaseEqualsASCII(name_latin1, "referer"))
- return;
-
- if (LowerCaseEqualsASCII(name_latin1, "accept"))
- has_accept_header_ = true;
-
- if (!buffer_.empty())
- buffer_.append("\r\n");
- buffer_.append(name_latin1 + ": " + value_latin1);
- }
-
- const std::string& GetBuffer() {
- // In some cases, WebKit doesn't add an Accept header, but not having the
- // header confuses some web servers. See bug 808613.
- if (!has_accept_header_) {
- if (!buffer_.empty())
- buffer_.append("\r\n");
- buffer_.append("Accept: */*");
- has_accept_header_ = true;
- }
- return buffer_;
- }
-
- private:
- std::string buffer_;
- bool has_accept_header_;
-};
-
-// Extracts the information from a data: url.
-bool GetInfoFromDataURL(const GURL& url,
- ResourceResponseInfo* info,
- std::string* data,
- int* error_code) {
- std::string mime_type;
- std::string charset;
- if (net::DataURL::Parse(url, &mime_type, &charset, data)) {
- *error_code = net::OK;
- // Assure same time for all time fields of data: URLs.
- Time now = Time::Now();
- info->load_timing.request_start = TimeTicks::Now();
- info->load_timing.request_start_time = now;
- info->request_time = now;
- info->response_time = now;
- info->headers = NULL;
- info->mime_type.swap(mime_type);
- info->charset.swap(charset);
- info->security_info.clear();
- info->content_length = data->length();
- info->encoded_data_length = 0;
-
- return true;
- }
-
- *error_code = net::ERR_INVALID_URL;
- return false;
-}
-
typedef ResourceDevToolsInfo::HeadersVector HeadersVector;
// Converts timing data from |load_timing| to the format used by WebKit.
@@ -199,17 +130,165 @@ net::RequestPriority ConvertWebKitPriorityToNetPriority(
}
}
+// Extracts info from a data scheme URL into |info| and |data|. Returns net::OK
+// if successful. Returns a net error code otherwise. Exported only for testing.
+int GetInfoFromDataURL(const GURL& url,
+ ResourceResponseInfo* info,
+ std::string* data) {
+ // Assure same time for all time fields of data: URLs.
+ Time now = Time::Now();
+ info->load_timing.request_start = TimeTicks::Now();
+ info->load_timing.request_start_time = now;
+ info->request_time = now;
+ info->response_time = now;
+
+ std::string mime_type;
+ std::string charset;
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders(std::string()));
+ int result = net::URLRequestDataJob::BuildResponse(
+ url, &mime_type, &charset, data, headers.get());
+ if (result != net::OK)
+ return result;
+
+ info->headers = headers;
+ info->mime_type.swap(mime_type);
+ info->charset.swap(charset);
+ info->security_info.clear();
+ info->content_length = data->length();
+ info->encoded_data_length = 0;
+
+ return net::OK;
+}
+
+#define COMPILE_ASSERT_MATCHING_ENUMS(content_name, blink_name) \
+ COMPILE_ASSERT( \
+ static_cast<int>(content_name) == static_cast<int>(blink_name), \
+ mismatching_enums)
+
+COMPILE_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_SAME_ORIGIN,
+ WebURLRequest::FetchRequestModeSameOrigin);
+COMPILE_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_NO_CORS,
+ WebURLRequest::FetchRequestModeNoCORS);
+COMPILE_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_CORS,
+ WebURLRequest::FetchRequestModeCORS);
+COMPILE_ASSERT_MATCHING_ENUMS(
+ FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT,
+ WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
+
+FetchRequestMode GetFetchRequestMode(const WebURLRequest& request) {
+ return static_cast<FetchRequestMode>(request.fetchRequestMode());
+}
+
+COMPILE_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_OMIT,
+ WebURLRequest::FetchCredentialsModeOmit);
+COMPILE_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_SAME_ORIGIN,
+ WebURLRequest::FetchCredentialsModeSameOrigin);
+COMPILE_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_INCLUDE,
+ WebURLRequest::FetchCredentialsModeInclude);
+
+FetchCredentialsMode GetFetchCredentialsMode(const WebURLRequest& request) {
+ return static_cast<FetchCredentialsMode>(request.fetchCredentialsMode());
+}
+
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY,
+ WebURLRequest::FrameTypeAuxiliary);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_NESTED,
+ WebURLRequest::FrameTypeNested);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ WebURLRequest::FrameTypeNone);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ WebURLRequest::FrameTypeTopLevel);
+
+RequestContextFrameType GetRequestContextFrameType(
+ const WebURLRequest& request) {
+ return static_cast<RequestContextFrameType>(request.frameType());
+}
+
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_UNSPECIFIED,
+ WebURLRequest::RequestContextUnspecified);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_AUDIO,
+ WebURLRequest::RequestContextAudio);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_BEACON,
+ WebURLRequest::RequestContextBeacon);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_CSP_REPORT,
+ WebURLRequest::RequestContextCSPReport);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_DOWNLOAD,
+ WebURLRequest::RequestContextDownload);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_EMBED,
+ WebURLRequest::RequestContextEmbed);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_EVENT_SOURCE,
+ WebURLRequest::RequestContextEventSource);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FAVICON,
+ WebURLRequest::RequestContextFavicon);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FETCH,
+ WebURLRequest::RequestContextFetch);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FONT,
+ WebURLRequest::RequestContextFont);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FORM,
+ WebURLRequest::RequestContextForm);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FRAME,
+ WebURLRequest::RequestContextFrame);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_HYPERLINK,
+ WebURLRequest::RequestContextHyperlink);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IFRAME,
+ WebURLRequest::RequestContextIframe);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMAGE,
+ WebURLRequest::RequestContextImage);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMAGE_SET,
+ WebURLRequest::RequestContextImageSet);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMPORT,
+ WebURLRequest::RequestContextImport);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_INTERNAL,
+ WebURLRequest::RequestContextInternal);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_LOCATION,
+ WebURLRequest::RequestContextLocation);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_MANIFEST,
+ WebURLRequest::RequestContextManifest);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_OBJECT,
+ WebURLRequest::RequestContextObject);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PING,
+ WebURLRequest::RequestContextPing);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PLUGIN,
+ WebURLRequest::RequestContextPlugin);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PREFETCH,
+ WebURLRequest::RequestContextPrefetch);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SCRIPT,
+ WebURLRequest::RequestContextScript);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ WebURLRequest::RequestContextServiceWorker);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SHARED_WORKER,
+ WebURLRequest::RequestContextSharedWorker);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SUBRESOURCE,
+ WebURLRequest::RequestContextSubresource);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_STYLE,
+ WebURLRequest::RequestContextStyle);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_TRACK,
+ WebURLRequest::RequestContextTrack);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_VIDEO,
+ WebURLRequest::RequestContextVideo);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_WORKER,
+ WebURLRequest::RequestContextWorker);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_XML_HTTP_REQUEST,
+ WebURLRequest::RequestContextXMLHttpRequest);
+COMPILE_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_XSLT,
+ WebURLRequest::RequestContextXSLT);
+
+RequestContextType GetRequestContextType(const WebURLRequest& request) {
+ return static_cast<RequestContextType>(request.requestContext());
+}
+
} // namespace
// WebURLLoaderImpl::Context --------------------------------------------------
// This inner class exists since the WebURLLoader may be deleted while inside a
-// call to WebURLLoaderClient. The bridge requires its Peer to stay alive
-// until it receives OnCompletedRequest.
+// call to WebURLLoaderClient. Refcounting is to keep the context from being
+// deleted if it may have work to do after calling into the client.
class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
public RequestPeer {
public:
- explicit Context(WebURLLoaderImpl* loader);
+ Context(WebURLLoaderImpl* loader, ResourceDispatcher* resource_dispatcher);
WebURLLoaderClient* client() const { return client_; }
void set_client(WebURLLoaderClient* client) { client_ = client; }
@@ -224,53 +303,55 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
SyncLoadResponse* sync_load_response);
// RequestPeer methods:
- virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
- virtual bool OnReceivedRedirect(const GURL& new_url,
- const GURL& new_first_party_for_cookies,
- const ResourceResponseInfo& info) OVERRIDE;
- virtual void OnReceivedResponse(const ResourceResponseInfo& info) OVERRIDE;
- virtual void OnDownloadedData(int len, int encoded_data_length) OVERRIDE;
- virtual void OnReceivedData(const char* data,
- int data_length,
- int encoded_data_length) OVERRIDE;
- virtual void OnReceivedCachedMetadata(const char* data, int len) OVERRIDE;
- virtual void OnCompletedRequest(
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64 total_transfer_size) OVERRIDE;
+ void OnUploadProgress(uint64 position, uint64 size) override;
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) override;
+ void OnReceivedResponse(const ResourceResponseInfo& info) override;
+ void OnDownloadedData(int len, int encoded_data_length) override;
+ void OnReceivedData(const char* data,
+ int data_length,
+ int encoded_data_length) override;
+ void OnReceivedCachedMetadata(const char* data, int len) override;
+ void OnCompletedRequest(int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64 total_transfer_size) override;
private:
friend class base::RefCounted<Context>;
- virtual ~Context() {}
+ ~Context() override {}
// We can optimize the handling of data URLs in most cases.
- bool CanHandleDataURL(const GURL& url) const;
+ bool CanHandleDataURLRequestLocally() const;
void HandleDataURL();
WebURLLoaderImpl* loader_;
WebURLRequest request_;
WebURLLoaderClient* client_;
+ ResourceDispatcher* resource_dispatcher_;
WebReferrerPolicy referrer_policy_;
scoped_ptr<ResourceLoaderBridge> bridge_;
scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
scoped_ptr<ResourceLoaderBridge> completed_bridge_;
+ scoped_ptr<StreamOverrideParameters> stream_override_;
};
-WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader)
+WebURLLoaderImpl::Context::Context(WebURLLoaderImpl* loader,
+ ResourceDispatcher* resource_dispatcher)
: loader_(loader),
client_(NULL),
+ resource_dispatcher_(resource_dispatcher),
referrer_policy_(blink::WebReferrerPolicyDefault) {
}
void WebURLLoaderImpl::Context::Cancel() {
- // The bridge will still send OnCompletedRequest, which will Release() us, so
- // we don't do that here.
- if (bridge_)
+ if (bridge_) {
bridge_->Cancel();
+ bridge_.reset();
+ }
// Ensure that we do not notify the multipart delegate anymore as it has
// its own pointer to the client.
@@ -310,18 +391,34 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
DCHECK(!bridge_.get());
request_ = request; // Save the request.
+ if (request.extraData()) {
+ RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request.extraData());
+ stream_override_ = extra_data->TakeStreamOverrideOwnership();
+ }
GURL url = request.url();
- if (url.SchemeIs("data") && CanHandleDataURL(url)) {
+
+ // PlzNavigate: during navigation, the renderer should request a stream which
+ // contains the body of the response. The request has already been made by the
+ // browser.
+ if (stream_override_.get()) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ DCHECK(!sync_load_response);
+ DCHECK_NE(WebURLRequest::FrameTypeNone, request.frameType());
+ DCHECK_EQ("GET", request.httpMethod().latin1());
+ url = stream_override_->stream_url;
+ }
+
+ if (CanHandleDataURLRequestLocally()) {
if (sync_load_response) {
// This is a sync load. Do the work now.
sync_load_response->url = url;
- std::string data;
- GetInfoFromDataURL(sync_load_response->url, sync_load_response,
- &sync_load_response->data,
- &sync_load_response->error_code);
+ sync_load_response->error_code =
+ GetInfoFromDataURL(sync_load_response->url, sync_load_response,
+ &sync_load_response->data);
} else {
- AddRef(); // Balanced in OnCompletedRequest
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&Context::HandleDataURL, this));
}
@@ -332,75 +429,41 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
request.httpHeaderField(WebString::fromUTF8("Referer")).latin1());
const std::string& method = request.httpMethod().latin1();
- int load_flags = net::LOAD_NORMAL | net::LOAD_ENABLE_LOAD_TIMING;
- switch (request.cachePolicy()) {
- case WebURLRequest::ReloadIgnoringCacheData:
- // Required by LayoutTests/http/tests/misc/refresh-headers.php
- load_flags |= net::LOAD_VALIDATE_CACHE;
- break;
- case WebURLRequest::ReloadBypassingCache:
- load_flags |= net::LOAD_BYPASS_CACHE;
- break;
- case WebURLRequest::ReturnCacheDataElseLoad:
- load_flags |= net::LOAD_PREFERRING_CACHE;
- break;
- case WebURLRequest::ReturnCacheDataDontLoad:
- load_flags |= net::LOAD_ONLY_FROM_CACHE;
- break;
- case WebURLRequest::UseProtocolCachePolicy:
- break;
- default:
- NOTREACHED();
- }
-
- if (request.reportUploadProgress())
- load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS;
- if (request.reportRawHeaders())
- load_flags |= net::LOAD_REPORT_RAW_HEADERS;
-
- if (!request.allowStoredCredentials()) {
- load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
- load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
- }
-
- if (!request.allowStoredCredentials())
- load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
-
- if (request.targetType() == WebURLRequest::TargetIsXHR &&
- (url.has_username() || url.has_password())) {
- load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN;
- }
-
- HeaderFlattener flattener;
- request.visitHTTPHeaderFields(&flattener);
-
// TODO(brettw) this should take parameter encoding into account when
// creating the GURLs.
+ // TODO(horo): Check credentials flag is unset when credentials mode is omit.
+ // Check credentials flag is set when credentials mode is include.
+
RequestInfo request_info;
request_info.method = method;
request_info.url = url;
request_info.first_party_for_cookies = request.firstPartyForCookies();
request_info.referrer = referrer_url;
- request_info.headers = flattener.GetBuffer();
- request_info.load_flags = load_flags;
+ request_info.headers = GetWebURLRequestHeaders(request);
+ request_info.load_flags = GetLoadFlagsForWebURLRequest(request);
+ request_info.enable_load_timing = true;
+ request_info.enable_upload_progress = request.reportUploadProgress();
// requestor_pid only needs to be non-zero if the request originates outside
// the render process, so we can use requestorProcessID even for requests
// from in-process plugins.
request_info.requestor_pid = request.requestorProcessID();
- request_info.request_type =
- ResourceType::FromTargetType(request.targetType());
+ request_info.request_type = WebURLRequestToResourceType(request);
request_info.priority =
ConvertWebKitPriorityToNetPriority(request.priority());
request_info.appcache_host_id = request.appCacheHostID();
request_info.routing_id = request.requestorID();
request_info.download_to_file = request.downloadToFile();
request_info.has_user_gesture = request.hasUserGesture();
+ request_info.skip_service_worker = request.skipServiceWorker();
+ request_info.fetch_request_mode = GetFetchRequestMode(request);
+ request_info.fetch_credentials_mode = GetFetchCredentialsMode(request);
+ request_info.fetch_request_context_type = GetRequestContextType(request);
+ request_info.fetch_frame_type = GetRequestContextFrameType(request);
request_info.extra_data = request.extraData();
referrer_policy_ = request.referrerPolicy();
request_info.referrer_policy = request.referrerPolicy();
- bridge_.reset(ChildThread::current()->resource_dispatcher()->CreateBridge(
- request_info));
+ bridge_.reset(resource_dispatcher_->CreateBridge(request_info));
if (!request.httpBody().isNull()) {
// GET and HEAD requests shouldn't have http bodies.
@@ -458,11 +521,11 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
return;
}
- if (bridge_->Start(this)) {
- AddRef(); // Balanced in OnCompletedRequest
- } else {
+ // TODO(mmenke): This case probably never happens, anyways. Probably should
+ // not handle this case at all. If it's worth handling, this code currently
+ // results in the request just hanging, which should be fixed.
+ if (!bridge_->Start(this))
bridge_.reset();
- }
}
void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
@@ -471,8 +534,7 @@ void WebURLLoaderImpl::Context::OnUploadProgress(uint64 position, uint64 size) {
}
bool WebURLLoaderImpl::Context::OnReceivedRedirect(
- const GURL& new_url,
- const GURL& new_first_party_for_cookies,
+ const net::RedirectInfo& redirect_info,
const ResourceResponseInfo& info) {
if (!client_)
return false;
@@ -483,34 +545,36 @@ bool WebURLLoaderImpl::Context::OnReceivedRedirect(
// TODO(darin): We lack sufficient information to construct the actual
// request that resulted from the redirect.
- WebURLRequest new_request(new_url);
- new_request.setFirstPartyForCookies(new_first_party_for_cookies);
+ WebURLRequest new_request(redirect_info.new_url);
+ new_request.setFirstPartyForCookies(
+ redirect_info.new_first_party_for_cookies);
new_request.setDownloadToFile(request_.downloadToFile());
-
- WebString referrer_string = WebString::fromUTF8("Referer");
- WebString referrer = WebSecurityPolicy::generateReferrerHeader(
- referrer_policy_,
- new_url,
- request_.httpHeaderField(referrer_string));
- if (!referrer.isEmpty())
- new_request.setHTTPReferrer(referrer, referrer_policy_);
-
- std::string method = request_.httpMethod().utf8();
- std::string new_method = net::URLRequest::ComputeMethodForRedirect(
- method, response.httpStatusCode());
- new_request.setHTTPMethod(WebString::fromUTF8(new_method));
- if (new_method == method)
+ new_request.setRequestContext(request_.requestContext());
+ new_request.setFrameType(request_.frameType());
+ new_request.setSkipServiceWorker(request_.skipServiceWorker());
+ new_request.setFetchRequestMode(request_.fetchRequestMode());
+ new_request.setFetchCredentialsMode(request_.fetchCredentialsMode());
+
+ new_request.setHTTPReferrer(WebString::fromUTF8(redirect_info.new_referrer),
+ referrer_policy_);
+
+ std::string old_method = request_.httpMethod().utf8();
+ new_request.setHTTPMethod(WebString::fromUTF8(redirect_info.new_method));
+ if (redirect_info.new_method == old_method)
new_request.setHTTPBody(request_.httpBody());
+ // Protect from deletion during call to willSendRequest.
+ scoped_refptr<Context> protect(this);
+
client_->willSendRequest(loader_, new_request, response);
request_ = new_request;
// Only follow the redirect if WebKit left the URL unmodified.
- if (new_url == GURL(new_request.url())) {
+ if (redirect_info.new_url == GURL(new_request.url())) {
// First-party cookie logic moved from DocumentLoader in Blink to
- // CrossSiteResourceHandler in the browser. Assert that Blink didn't try to
- // change it to something else.
- DCHECK_EQ(new_first_party_for_cookies.spec(),
+ // net::URLRequest in the browser. Assert that Blink didn't try to change it
+ // to something else.
+ DCHECK_EQ(redirect_info.new_first_party_for_cookies.spec(),
request_.firstPartyForCookies().string().utf8());
return true;
}
@@ -522,12 +586,28 @@ bool WebURLLoaderImpl::Context::OnReceivedRedirect(
}
void WebURLLoaderImpl::Context::OnReceivedResponse(
- const ResourceResponseInfo& info) {
+ const ResourceResponseInfo& initial_info) {
if (!client_)
return;
+ ResourceResponseInfo info = initial_info;
+
+ // PlzNavigate: during navigations, the ResourceResponse has already been
+ // received on the browser side, and has been passed down to the renderer.
+ if (stream_override_.get()) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ info = stream_override_->response;
+ }
+
WebURLResponse response;
response.initialize();
+ // Updates the request url if the response was fetched by a ServiceWorker,
+ // and it was not generated inside the ServiceWorker.
+ if (info.was_fetched_via_service_worker &&
+ !info.original_url_via_service_worker.is_empty()) {
+ request_.setURL(info.original_url_via_service_worker);
+ }
PopulateURLResponse(request_.url(), info, &response);
bool show_raw_listing = (GURL(request_.url()).query() == "raw");
@@ -542,6 +622,9 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
}
}
+ // Prevent |this| from being destroyed if the client destroys the loader,
+ // ether in didReceiveResponse, or when the multipart/ftp delegate calls into
+ // it.
scoped_refptr<Context> protect(this);
client_->didReceiveResponse(loader_, response);
@@ -591,11 +674,17 @@ void WebURLLoaderImpl::Context::OnReceivedData(const char* data,
if (ftp_listing_delegate_) {
// The FTP listing delegate will make the appropriate calls to
- // client_->didReceiveData and client_->didReceiveResponse.
+ // client_->didReceiveData and client_->didReceiveResponse. Since the
+ // delegate may want to do work after sending data to the delegate, keep
+ // |this| and the delegate alive until it's finished handling the data.
+ scoped_refptr<Context> protect(this);
ftp_listing_delegate_->OnReceivedData(data, data_length);
} else if (multipart_delegate_) {
// The multipart delegate will make the appropriate calls to
- // client_->didReceiveData and client_->didReceiveResponse.
+ // client_->didReceiveData and client_->didReceiveResponse. Since the
+ // delegate may want to do work after sending data to the delegate, keep
+ // |this| and the delegate alive until it's finished handling the data.
+ scoped_refptr<Context> protect(this);
multipart_delegate_->OnReceivedData(data, data_length, encoded_data_length);
} else {
client_->didReceiveData(loader_, data, data_length, encoded_data_length);
@@ -615,6 +704,12 @@ void WebURLLoaderImpl::Context::OnCompletedRequest(
const std::string& security_info,
const base::TimeTicks& completion_time,
int64 total_transfer_size) {
+ // The WebURLLoaderImpl may be deleted in any of the calls to the client or
+ // the delegates below (As they also may call in to the client). Keep |this|
+ // alive in that case, to avoid a crash. If that happens, the request will be
+ // cancelled and |client_| will be set to NULL.
+ scoped_refptr<Context> protect(this);
+
if (ftp_listing_delegate_) {
ftp_listing_delegate_->OnCompletedRequest();
ftp_listing_delegate_.reset(NULL);
@@ -639,15 +734,17 @@ void WebURLLoaderImpl::Context::OnCompletedRequest(
total_transfer_size);
}
}
-
- // We are done with the bridge now, and so we need to release the reference
- // to ourselves that we took on behalf of the bridge. This may cause our
- // destruction.
- Release();
}
-bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const {
- DCHECK(url.SchemeIs("data"));
+bool WebURLLoaderImpl::Context::CanHandleDataURLRequestLocally() const {
+ GURL url = request_.url();
+ if (!url.SchemeIs(url::kDataScheme))
+ return false;
+
+ // The fast paths for data URL, Start() and HandleDataURL(), don't support
+ // the downloadToFile option.
+ if (request_.downloadToFile())
+ return false;
// Optimize for the case where we can handle a data URL locally. We must
// skip this for data URLs targetted at frames since those could trigger a
@@ -660,16 +757,16 @@ bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const {
#if defined(OS_ANDROID)
// For compatibility reasons on Android we need to expose top-level data://
// to the browser.
- if (request_.targetType() == WebURLRequest::TargetIsMainFrame)
+ if (request_.frameType() == WebURLRequest::FrameTypeTopLevel)
return false;
#endif
- if (request_.targetType() != WebURLRequest::TargetIsMainFrame &&
- request_.targetType() != WebURLRequest::TargetIsSubframe)
+ if (request_.frameType() != WebURLRequest::FrameTypeTopLevel &&
+ request_.frameType() != WebURLRequest::FrameTypeNested)
return true;
std::string mime_type, unused_charset;
- if (net::DataURL::Parse(url, &mime_type, &unused_charset, NULL) &&
+ if (net::DataURL::Parse(request_.url(), &mime_type, &unused_charset, NULL) &&
net::IsSupportedMimeType(mime_type))
return true;
@@ -678,10 +775,11 @@ bool WebURLLoaderImpl::Context::CanHandleDataURL(const GURL& url) const {
void WebURLLoaderImpl::Context::HandleDataURL() {
ResourceResponseInfo info;
- int error_code;
std::string data;
- if (GetInfoFromDataURL(request_.url(), &info, &data, &error_code)) {
+ int error_code = GetInfoFromDataURL(request_.url(), &info, &data);
+
+ if (error_code == net::OK) {
OnReceivedResponse(info);
if (!data.empty())
OnReceivedData(data.data(), data.size(), 0);
@@ -693,8 +791,8 @@ void WebURLLoaderImpl::Context::HandleDataURL() {
// WebURLLoaderImpl -----------------------------------------------------------
-WebURLLoaderImpl::WebURLLoaderImpl()
- : context_(new Context(this)) {
+WebURLLoaderImpl::WebURLLoaderImpl(ResourceDispatcher* resource_dispatcher)
+ : context_(new Context(this, resource_dispatcher)) {
}
WebURLLoaderImpl::~WebURLLoaderImpl() {
@@ -740,6 +838,10 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
response->setConnectionID(info.load_timing.socket_log_id);
response->setConnectionReused(info.load_timing.socket_reused);
response->setDownloadFilePath(info.download_file_path.AsUTF16Unsafe());
+ response->setWasFetchedViaServiceWorker(info.was_fetched_via_service_worker);
+ response->setWasFallbackRequiredByServiceWorker(
+ info.was_fallback_required_by_service_worker);
+ response->setServiceWorkerResponseType(info.response_type_via_service_worker);
WebURLResponseExtraDataImpl* extra_data =
new WebURLResponseExtraDataImpl(info.npn_negotiated_protocol);
response->setExtraData(extra_data);
@@ -749,6 +851,7 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
info.was_alternate_protocol_available);
extra_data->set_connection_info(info.connection_info);
extra_data->set_was_fetched_via_proxy(info.was_fetched_via_proxy);
+ extra_data->set_proxy_server(info.proxy_server);
// If there's no received headers end time, don't set load timing. This is
// the case for non-HTTP requests, requests that don't go over the wire, and
@@ -756,6 +859,13 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
if (!info.load_timing.receive_headers_end.is_null()) {
WebURLLoadTiming timing;
PopulateURLLoadTiming(info.load_timing, &timing);
+ const TimeTicks kNullTicks;
+ timing.setServiceWorkerFetchStart(
+ (info.service_worker_fetch_start - kNullTicks).InSecondsF());
+ timing.setServiceWorkerFetchReady(
+ (info.service_worker_fetch_ready - kNullTicks).InSecondsF());
+ timing.setServiceWorkerFetchEnd(
+ (info.service_worker_fetch_end - kNullTicks).InSecondsF());
response->setLoadTiming(timing);
}
diff --git a/chromium/content/child/web_url_loader_impl.h b/chromium/content/child/web_url_loader_impl.h
index affe1ab3443..36aafa633ae 100644
--- a/chromium/content/child/web_url_loader_impl.h
+++ b/chromium/content/child/web_url_loader_impl.h
@@ -5,23 +5,37 @@
#ifndef CONTENT_CHILD_WEB_URL_LOADER_IMPL_H_
#define CONTENT_CHILD_WEB_URL_LOADER_IMPL_H_
+#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "content/public/common/resource_response.h"
#include "third_party/WebKit/public/platform/WebURLLoader.h"
+#include "url/gurl.h"
namespace content {
+class ResourceDispatcher;
struct ResourceResponseInfo;
-class WebURLLoaderImpl : public blink::WebURLLoader {
+// PlzNavigate: Used to override parameters of the navigation request.
+struct StreamOverrideParameters {
public:
- WebURLLoaderImpl();
+ // TODO(clamy): The browser should be made aware on destruction of this struct
+ // that it can release its associated stream handle.
+ GURL stream_url;
+ ResourceResponseHead response;
+};
+
+class CONTENT_EXPORT WebURLLoaderImpl
+ : public NON_EXPORTED_BASE(blink::WebURLLoader) {
+ public:
+ explicit WebURLLoaderImpl(ResourceDispatcher* resource_dispatcher);
virtual ~WebURLLoaderImpl();
static blink::WebURLError CreateError(const blink::WebURL& unreachable_url,
bool stale_copy_in_cache,
int reason);
- CONTENT_EXPORT static void PopulateURLResponse(
+ static void PopulateURLResponse(
const GURL& url,
const ResourceResponseInfo& info,
blink::WebURLResponse* response);
@@ -31,20 +45,22 @@ class WebURLLoaderImpl : public blink::WebURLLoader {
const blink::WebURLRequest& request,
blink::WebURLResponse& response,
blink::WebURLError& error,
- blink::WebData& data);
+ blink::WebData& data) override;
virtual void loadAsynchronously(
const blink::WebURLRequest& request,
- blink::WebURLLoaderClient* client);
- virtual void cancel();
- virtual void setDefersLoading(bool value);
+ blink::WebURLLoaderClient* client) override;
+ virtual void cancel() override;
+ virtual void setDefersLoading(bool value) override;
virtual void didChangePriority(blink::WebURLRequest::Priority new_priority,
- int intra_priority_value);
+ int intra_priority_value) override;
virtual bool attachThreadedDataReceiver(
- blink::WebThreadedDataReceiver* threaded_data_receiver);
+ blink::WebThreadedDataReceiver* threaded_data_receiver) override;
private:
class Context;
scoped_refptr<Context> context_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebURLLoaderImpl);
};
} // namespace content
diff --git a/chromium/content/child/web_url_loader_impl_unittest.cc b/chromium/content/child/web_url_loader_impl_unittest.cc
new file mode 100644
index 00000000000..50cff38b7c7
--- /dev/null
+++ b/chromium/content/child/web_url_loader_impl_unittest.cc
@@ -0,0 +1,707 @@
+// Copyright 2014 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 "content/child/web_url_loader_impl.h"
+
+#include <string.h>
+
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
+#include "content/child/request_extra_data.h"
+#include "content/child/request_info.h"
+#include "content/child/resource_dispatcher.h"
+#include "content/child/resource_loader_bridge.h"
+#include "content/public/child/request_peer.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/resource_response_info.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
+#include "net/url_request/redirect_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "url/gurl.h"
+
+namespace content {
+namespace {
+
+const char kTestURL[] = "http://foo";
+const char kTestData[] = "blah!";
+
+const char kFtpDirMimeType[] = "text/vnd.chromium.ftp-dir";
+// Simple FTP directory listing. Tests are not concerned with correct parsing,
+// but rather correct cleanup when deleted while parsing. Important details of
+// this list are that it contains more than one entry that are not "." or "..".
+const char kFtpDirListing[] =
+ "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 goat\n"
+ "drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 hat";
+
+const char kMultipartResponseMimeType[] = "multipart/x-mixed-replace";
+const char kMultipartResponseHeaders[] =
+ "HTTP/1.0 200 Peachy\r\n"
+ "Content-Type: multipart/x-mixed-replace; boundary=boundary\r\n\r\n";
+// Simple multipart response. Imporant details for the tests are that it
+// contains multiple chunks, and that it doesn't end with a boundary, so will
+// send data in OnResponseComplete. Also, it will resolve to kTestData.
+const char kMultipartResponse[] =
+ "--boundary\n"
+ "Content-type: text/html\n\n"
+ "bl"
+ "--boundary\n"
+ "Content-type: text/html\n\n"
+ "ah!";
+
+class TestBridge : public ResourceLoaderBridge,
+ public base::SupportsWeakPtr<TestBridge> {
+ public:
+ TestBridge(const RequestInfo& info) :
+ peer_(NULL),
+ canceled_(false),
+ url_(info.url) {
+ }
+
+ ~TestBridge() override {}
+
+ // ResourceLoaderBridge implementation:
+ void SetRequestBody(ResourceRequestBody* request_body) override {}
+
+ bool Start(RequestPeer* peer) override {
+ EXPECT_FALSE(peer_);
+ peer_ = peer;
+ return true;
+ }
+
+ void Cancel() override {
+ EXPECT_FALSE(canceled_);
+ canceled_ = true;
+ }
+
+ void SetDefersLoading(bool value) override {}
+
+ void DidChangePriority(net::RequestPriority new_priority,
+ int intra_priority_value) override {}
+
+ bool AttachThreadedDataReceiver(
+ blink::WebThreadedDataReceiver* threaded_data_receiver) override {
+ NOTREACHED();
+ return false;
+ }
+
+ void SyncLoad(SyncLoadResponse* response) override {}
+
+ RequestPeer* peer() { return peer_; }
+
+ bool canceled() { return canceled_; }
+
+ const GURL& url() { return url_; }
+
+ private:
+ RequestPeer* peer_;
+ bool canceled_;
+ GURL url_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBridge);
+};
+
+class TestResourceDispatcher : public ResourceDispatcher {
+ public:
+ TestResourceDispatcher() : ResourceDispatcher(NULL) {}
+ ~TestResourceDispatcher() override {}
+
+ // ResourceDispatcher implementation:
+ ResourceLoaderBridge* CreateBridge(const RequestInfo& request_info) override {
+ EXPECT_FALSE(bridge_.get());
+ TestBridge* bridge = new TestBridge(request_info);
+ bridge_ = bridge->AsWeakPtr();
+ return bridge;
+ }
+
+ TestBridge* bridge() { return bridge_.get(); }
+
+ private:
+ base::WeakPtr<TestBridge> bridge_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcher);
+};
+
+class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
+ public:
+ TestWebURLLoaderClient(ResourceDispatcher* dispatcher)
+ : loader_(new WebURLLoaderImpl(dispatcher)),
+ expect_multipart_response_(false),
+ delete_on_receive_redirect_(false),
+ delete_on_receive_response_(false),
+ delete_on_receive_data_(false),
+ delete_on_finish_(false),
+ delete_on_fail_(false),
+ did_receive_redirect_(false),
+ did_receive_response_(false),
+ did_finish_(false) {
+ }
+
+ virtual ~TestWebURLLoaderClient() {}
+
+ // blink::WebURLLoaderClient implementation:
+ virtual void willSendRequest(
+ blink::WebURLLoader* loader,
+ blink::WebURLRequest& newRequest,
+ const blink::WebURLResponse& redirectResponse) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+ // No test currently simulates mutiple redirects.
+ EXPECT_FALSE(did_receive_redirect_);
+ did_receive_redirect_ = true;
+
+ if (delete_on_receive_redirect_)
+ loader_.reset();
+ }
+
+ virtual void didSendData(blink::WebURLLoader* loader,
+ unsigned long long bytesSent,
+ unsigned long long totalBytesToBeSent) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+ }
+
+ virtual void didReceiveResponse(
+ blink::WebURLLoader* loader,
+ const blink::WebURLResponse& response) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+
+ // Only multipart requests may receive multiple response headers.
+ EXPECT_TRUE(expect_multipart_response_ || !did_receive_response_);
+
+ did_receive_response_ = true;
+ response_ = response;
+ if (delete_on_receive_response_)
+ loader_.reset();
+ }
+
+ virtual void didDownloadData(blink::WebURLLoader* loader,
+ int dataLength,
+ int encodedDataLength) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+ }
+
+ virtual void didReceiveData(blink::WebURLLoader* loader,
+ const char* data,
+ int dataLength,
+ int encodedDataLength) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+ // The response should have started, but must not have finished, or failed.
+ EXPECT_TRUE(did_receive_response_);
+ EXPECT_FALSE(did_finish_);
+ EXPECT_EQ(net::OK, error_.reason);
+ EXPECT_EQ("", error_.domain.utf8());
+
+ received_data_.append(data, dataLength);
+
+ if (delete_on_receive_data_)
+ loader_.reset();
+ }
+
+ virtual void didReceiveCachedMetadata(blink::WebURLLoader* loader,
+ const char* data,
+ int dataLength) override {
+ EXPECT_EQ(loader_.get(), loader);
+ }
+
+ virtual void didFinishLoading(blink::WebURLLoader* loader,
+ double finishTime,
+ int64_t totalEncodedDataLength) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+ EXPECT_TRUE(did_receive_response_);
+ EXPECT_FALSE(did_finish_);
+ did_finish_ = true;
+
+ if (delete_on_finish_)
+ loader_.reset();
+ }
+
+ virtual void didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error) override {
+ EXPECT_TRUE(loader_);
+ EXPECT_EQ(loader_.get(), loader);
+ EXPECT_FALSE(did_finish_);
+ error_ = error;
+
+ if (delete_on_fail_)
+ loader_.reset();
+ }
+
+ WebURLLoaderImpl* loader() { return loader_.get(); }
+ void DeleteLoader() {
+ loader_.reset();
+ }
+
+ void set_expect_multipart_response() { expect_multipart_response_ = true; }
+
+ void set_delete_on_receive_redirect() { delete_on_receive_redirect_ = true; }
+ void set_delete_on_receive_response() { delete_on_receive_response_ = true; }
+ void set_delete_on_receive_data() { delete_on_receive_data_ = true; }
+ void set_delete_on_finish() { delete_on_finish_ = true; }
+ void set_delete_on_fail() { delete_on_fail_ = true; }
+
+ bool did_receive_redirect() const { return did_receive_redirect_; }
+ bool did_receive_response() const { return did_receive_response_; }
+ const std::string& received_data() const { return received_data_; }
+ bool did_finish() const { return did_finish_; }
+ const blink::WebURLError& error() const { return error_; }
+ const blink::WebURLResponse& response() const { return response_; }
+
+ private:
+ scoped_ptr<WebURLLoaderImpl> loader_;
+
+ bool expect_multipart_response_;
+
+ bool delete_on_receive_redirect_;
+ bool delete_on_receive_response_;
+ bool delete_on_receive_data_;
+ bool delete_on_finish_;
+ bool delete_on_fail_;
+
+ bool did_receive_redirect_;
+ bool did_receive_response_;
+ std::string received_data_;
+ bool did_finish_;
+ blink::WebURLError error_;
+ blink::WebURLResponse response_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestWebURLLoaderClient);
+};
+
+class WebURLLoaderImplTest : public testing::Test {
+ public:
+ explicit WebURLLoaderImplTest() : client_(&dispatcher_) {}
+ ~WebURLLoaderImplTest() override {}
+
+ void DoStartAsyncRequest() {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL(kTestURL));
+ client()->loader()->loadAsynchronously(request, client());
+ ASSERT_TRUE(bridge());
+ ASSERT_TRUE(peer());
+ }
+
+ void DoReceiveRedirect() {
+ EXPECT_FALSE(client()->did_receive_redirect());
+ net::RedirectInfo redirect_info;
+ redirect_info.status_code = 302;
+ redirect_info.new_method = "GET";
+ redirect_info.new_url = GURL(kTestURL);
+ redirect_info.new_first_party_for_cookies = GURL(kTestURL);
+ peer()->OnReceivedRedirect(redirect_info,
+ content::ResourceResponseInfo());
+ EXPECT_TRUE(client()->did_receive_redirect());
+ }
+
+ void DoReceiveResponse() {
+ EXPECT_FALSE(client()->did_receive_response());
+ peer()->OnReceivedResponse(content::ResourceResponseInfo());
+ EXPECT_TRUE(client()->did_receive_response());
+ }
+
+ // Assumes it is called only once for a request.
+ void DoReceiveData() {
+ EXPECT_EQ("", client()->received_data());
+ peer()->OnReceivedData(kTestData, strlen(kTestData), strlen(kTestData));
+ EXPECT_EQ(kTestData, client()->received_data());
+ }
+
+ void DoCompleteRequest() {
+ EXPECT_FALSE(client()->did_finish());
+ peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
+ strlen(kTestData));
+ EXPECT_TRUE(client()->did_finish());
+ // There should be no error.
+ EXPECT_EQ(net::OK, client()->error().reason);
+ EXPECT_EQ("", client()->error().domain.utf8());
+ }
+
+ void DoFailRequest() {
+ EXPECT_FALSE(client()->did_finish());
+ peer()->OnCompletedRequest(net::ERR_FAILED, false, false, "",
+ base::TimeTicks(), strlen(kTestData));
+ EXPECT_FALSE(client()->did_finish());
+ EXPECT_EQ(net::ERR_FAILED, client()->error().reason);
+ EXPECT_EQ(net::kErrorDomain, client()->error().domain.utf8());
+ }
+
+ void DoReceiveResponseFtp() {
+ EXPECT_FALSE(client()->did_receive_response());
+ content::ResourceResponseInfo response_info;
+ response_info.mime_type = kFtpDirMimeType;
+ peer()->OnReceivedResponse(response_info);
+ EXPECT_TRUE(client()->did_receive_response());
+ }
+
+ void DoReceiveDataFtp() {
+ peer()->OnReceivedData(kFtpDirListing, strlen(kFtpDirListing),
+ strlen(kFtpDirListing));
+ // The FTP delegate should modify the data the client sees.
+ EXPECT_NE(kFtpDirListing, client()->received_data());
+ }
+
+ void DoReceiveResponseMultipart() {
+ EXPECT_FALSE(client()->did_receive_response());
+ content::ResourceResponseInfo response_info;
+ response_info.headers = new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(kMultipartResponseHeaders,
+ strlen(kMultipartResponseHeaders)));
+ response_info.mime_type = kMultipartResponseMimeType;
+ peer()->OnReceivedResponse(response_info);
+ EXPECT_TRUE(client()->did_receive_response());
+ }
+
+ void DoReceiveDataMultipart() {
+ peer()->OnReceivedData(kMultipartResponse, strlen(kMultipartResponse),
+ strlen(kMultipartResponse));
+ // Multipart delegate should modify the data the client sees.
+ EXPECT_NE(kMultipartResponse, client()->received_data());
+ }
+
+ TestWebURLLoaderClient* client() { return &client_; }
+ TestBridge* bridge() { return dispatcher_.bridge(); }
+ RequestPeer* peer() { return bridge()->peer(); }
+ base::MessageLoop* message_loop() { return &message_loop_; }
+
+ private:
+ TestResourceDispatcher dispatcher_;
+ TestWebURLLoaderClient client_;
+
+ base::MessageLoop message_loop_;
+};
+
+TEST_F(WebURLLoaderImplTest, Success) {
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoReceiveData();
+ DoCompleteRequest();
+ EXPECT_FALSE(bridge()->canceled());
+ EXPECT_EQ(kTestData, client()->received_data());
+}
+
+TEST_F(WebURLLoaderImplTest, Redirect) {
+ DoStartAsyncRequest();
+ DoReceiveRedirect();
+ DoReceiveResponse();
+ DoReceiveData();
+ DoCompleteRequest();
+ EXPECT_FALSE(bridge()->canceled());
+ EXPECT_EQ(kTestData, client()->received_data());
+}
+
+TEST_F(WebURLLoaderImplTest, Failure) {
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoReceiveData();
+ DoFailRequest();
+ EXPECT_FALSE(bridge()->canceled());
+}
+
+// The client may delete the WebURLLoader during any callback from the loader.
+// These tests make sure that doesn't result in a crash.
+TEST_F(WebURLLoaderImplTest, DeleteOnReceiveRedirect) {
+ client()->set_delete_on_receive_redirect();
+ DoStartAsyncRequest();
+ DoReceiveRedirect();
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DeleteOnReceiveResponse) {
+ client()->set_delete_on_receive_response();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DeleteOnReceiveData) {
+ client()->set_delete_on_receive_data();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoReceiveData();
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DeleteOnFinish) {
+ client()->set_delete_on_finish();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoReceiveData();
+ DoCompleteRequest();
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DeleteOnFail) {
+ client()->set_delete_on_fail();
+ DoStartAsyncRequest();
+ DoReceiveResponse();
+ DoReceiveData();
+ DoFailRequest();
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DeleteBeforeResponseDataURL) {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
+ client()->loader()->loadAsynchronously(request, client());
+ client()->DeleteLoader();
+ message_loop()->RunUntilIdle();
+ EXPECT_FALSE(client()->did_receive_response());
+ EXPECT_FALSE(bridge());
+}
+
+// Data URL tests.
+
+TEST_F(WebURLLoaderImplTest, DataURL) {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
+ client()->loader()->loadAsynchronously(request, client());
+ message_loop()->RunUntilIdle();
+ EXPECT_EQ("blah!", client()->received_data());
+ EXPECT_TRUE(client()->did_finish());
+ EXPECT_EQ(net::OK, client()->error().reason);
+ EXPECT_EQ("", client()->error().domain.utf8());
+}
+
+TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveResponse) {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
+ client()->set_delete_on_receive_response();
+ client()->loader()->loadAsynchronously(request, client());
+ message_loop()->RunUntilIdle();
+ EXPECT_TRUE(client()->did_receive_response());
+ EXPECT_EQ("", client()->received_data());
+ EXPECT_FALSE(client()->did_finish());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveData) {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
+ client()->set_delete_on_receive_data();
+ client()->loader()->loadAsynchronously(request, client());
+ message_loop()->RunUntilIdle();
+ EXPECT_TRUE(client()->did_receive_response());
+ EXPECT_EQ("blah!", client()->received_data());
+ EXPECT_FALSE(client()->did_finish());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, DataURLDeleteOnFinisha) {
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL("data:text/html;charset=utf-8,blah!"));
+ client()->set_delete_on_finish();
+ client()->loader()->loadAsynchronously(request, client());
+ message_loop()->RunUntilIdle();
+ EXPECT_TRUE(client()->did_receive_response());
+ EXPECT_EQ("blah!", client()->received_data());
+ EXPECT_TRUE(client()->did_finish());
+ EXPECT_FALSE(bridge());
+}
+
+// FTP integration tests. These are focused more on safe deletion than correct
+// parsing of FTP responses.
+
+TEST_F(WebURLLoaderImplTest, Ftp) {
+ DoStartAsyncRequest();
+ DoReceiveResponseFtp();
+ DoReceiveDataFtp();
+ DoCompleteRequest();
+ EXPECT_FALSE(bridge()->canceled());
+}
+
+TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveResponse) {
+ client()->set_delete_on_receive_response();
+ DoStartAsyncRequest();
+ DoReceiveResponseFtp();
+
+ // No data should have been received.
+ EXPECT_EQ("", client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveFirstData) {
+ client()->set_delete_on_receive_data();
+ DoStartAsyncRequest();
+ // Some data is sent in ReceiveResponse for FTP requests, so the bridge should
+ // be deleted here.
+ DoReceiveResponseFtp();
+
+ EXPECT_NE("", client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, FtpDeleteOnReceiveMoreData) {
+ DoStartAsyncRequest();
+ DoReceiveResponseFtp();
+ DoReceiveDataFtp();
+
+ // Directory listings are only parsed once the request completes, so this will
+ // cancel in DoReceiveDataFtp, before the request finishes.
+ client()->set_delete_on_receive_data();
+ peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
+ strlen(kTestData));
+ EXPECT_FALSE(client()->did_finish());
+
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, FtpDeleteOnFinish) {
+ client()->set_delete_on_finish();
+ DoStartAsyncRequest();
+ DoReceiveResponseFtp();
+ DoReceiveDataFtp();
+ DoCompleteRequest();
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, FtpDeleteOnFail) {
+ client()->set_delete_on_fail();
+ DoStartAsyncRequest();
+ DoReceiveResponseFtp();
+ DoReceiveDataFtp();
+ DoFailRequest();
+ EXPECT_FALSE(bridge());
+}
+
+// Multipart integration tests. These are focused more on safe deletion than
+// correct parsing of Multipart responses.
+
+TEST_F(WebURLLoaderImplTest, Multipart) {
+ client()->set_expect_multipart_response();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ DoReceiveDataMultipart();
+ DoCompleteRequest();
+ EXPECT_EQ(kTestData, client()->received_data());
+ EXPECT_FALSE(bridge()->canceled());
+}
+
+TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveFirstResponse) {
+ client()->set_expect_multipart_response();
+ client()->set_delete_on_receive_response();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ EXPECT_EQ("", client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveSecondResponse) {
+ client()->set_expect_multipart_response();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ client()->set_delete_on_receive_response();
+ DoReceiveDataMultipart();
+ EXPECT_EQ("", client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveFirstData) {
+ client()->set_expect_multipart_response();
+ client()->set_delete_on_receive_data();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ DoReceiveDataMultipart();
+ EXPECT_EQ("bl", client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveMoreData) {
+ client()->set_expect_multipart_response();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ DoReceiveDataMultipart();
+ // For multipart responses, the delegate may send some data when notified
+ // of a request completing.
+ client()->set_delete_on_receive_data();
+ peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
+ strlen(kTestData));
+ EXPECT_FALSE(client()->did_finish());
+ EXPECT_EQ(kTestData, client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, MultipartDeleteFinish) {
+ client()->set_expect_multipart_response();
+ client()->set_delete_on_finish();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ DoReceiveDataMultipart();
+ DoCompleteRequest();
+ EXPECT_EQ(kTestData, client()->received_data());
+ EXPECT_FALSE(bridge());
+}
+
+TEST_F(WebURLLoaderImplTest, MultipartDeleteFail) {
+ client()->set_expect_multipart_response();
+ client()->set_delete_on_fail();
+ DoStartAsyncRequest();
+ DoReceiveResponseMultipart();
+ DoReceiveDataMultipart();
+ DoFailRequest();
+ EXPECT_FALSE(bridge());
+}
+
+// PlzNavigate: checks that the stream override parameters provided on
+// navigation commit are properly applied.
+TEST_F(WebURLLoaderImplTest, BrowserSideNavigationCommit) {
+ // Initialize the request and the stream override.
+ const GURL kStreamURL = GURL("http://bar");
+ const std::string kMimeType = "text/html";
+ blink::WebURLRequest request;
+ request.initialize();
+ request.setURL(GURL(kTestURL));
+ request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel);
+ request.setRequestContext(blink::WebURLRequest::RequestContextFrame);
+ scoped_ptr<StreamOverrideParameters> stream_override(
+ new StreamOverrideParameters());
+ stream_override->stream_url = kStreamURL;
+ stream_override->response.mime_type = kMimeType;
+ RequestExtraData* extra_data = new RequestExtraData();
+ extra_data->set_stream_override(stream_override.Pass());
+ request.setExtraData(extra_data);
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBrowserSideNavigation);
+
+ client()->loader()->loadAsynchronously(request, client());
+
+ // The stream url should have been requestead instead of the request url.
+ ASSERT_TRUE(bridge());
+ ASSERT_TRUE(peer());
+ EXPECT_EQ(kStreamURL, bridge()->url());
+
+ EXPECT_FALSE(client()->did_receive_response());
+ peer()->OnReceivedResponse(content::ResourceResponseInfo());
+ EXPECT_TRUE(client()->did_receive_response());
+
+ // The response info should have been overriden.
+ ASSERT_FALSE(client()->response().isNull());
+ EXPECT_EQ(kMimeType, client()->response().mimeType().latin1());
+
+ DoReceiveData();
+ DoCompleteRequest();
+ EXPECT_FALSE(bridge()->canceled());
+ EXPECT_EQ(kTestData, client()->received_data());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/child/web_url_request_util.cc b/chromium/content/child/web_url_request_util.cc
new file mode 100644
index 00000000000..6f03e998b97
--- /dev/null
+++ b/chromium/content/child/web_url_request_util.cc
@@ -0,0 +1,218 @@
+// Copyright 2014 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 "content/child/web_url_request_util.h"
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "net/base/load_flags.h"
+#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+
+using blink::WebURLRequest;
+using blink::WebString;
+
+namespace content {
+
+namespace {
+
+class HeaderFlattener : public blink::WebHTTPHeaderVisitor {
+ public:
+ HeaderFlattener() : has_accept_header_(false) {}
+
+ virtual void visitHeader(const WebString& name, const WebString& value) {
+ // Headers are latin1.
+ const std::string& name_latin1 = name.latin1();
+ const std::string& value_latin1 = value.latin1();
+
+ // Skip over referrer headers found in the header map because we already
+ // pulled it out as a separate parameter.
+ if (LowerCaseEqualsASCII(name_latin1, "referer"))
+ return;
+
+ if (LowerCaseEqualsASCII(name_latin1, "accept"))
+ has_accept_header_ = true;
+
+ if (!buffer_.empty())
+ buffer_.append("\r\n");
+ buffer_.append(name_latin1 + ": " + value_latin1);
+ }
+
+ const std::string& GetBuffer() {
+ // In some cases, WebKit doesn't add an Accept header, but not having the
+ // header confuses some web servers. See bug 808613.
+ if (!has_accept_header_) {
+ if (!buffer_.empty())
+ buffer_.append("\r\n");
+ buffer_.append("Accept: */*");
+ has_accept_header_ = true;
+ }
+ return buffer_;
+ }
+
+ private:
+ std::string buffer_;
+ bool has_accept_header_;
+};
+
+} // namespace
+
+ResourceType WebURLRequestToResourceType(const WebURLRequest& request) {
+ WebURLRequest::RequestContext requestContext = request.requestContext();
+ if (request.frameType() != WebURLRequest::FrameTypeNone) {
+ DCHECK(requestContext == WebURLRequest::RequestContextForm ||
+ requestContext == WebURLRequest::RequestContextFrame ||
+ requestContext == WebURLRequest::RequestContextHyperlink ||
+ requestContext == WebURLRequest::RequestContextIframe ||
+ requestContext == WebURLRequest::RequestContextInternal ||
+ requestContext == WebURLRequest::RequestContextLocation);
+ if (request.frameType() == WebURLRequest::FrameTypeTopLevel ||
+ request.frameType() == WebURLRequest::FrameTypeAuxiliary) {
+ return RESOURCE_TYPE_MAIN_FRAME;
+ }
+ if (request.frameType() == WebURLRequest::FrameTypeNested)
+ return RESOURCE_TYPE_SUB_FRAME;
+ NOTREACHED();
+ return RESOURCE_TYPE_SUB_RESOURCE;
+ }
+
+ switch (requestContext) {
+ // Favicon
+ case WebURLRequest::RequestContextFavicon:
+ return RESOURCE_TYPE_FAVICON;
+
+ // Font
+ case WebURLRequest::RequestContextFont:
+ return RESOURCE_TYPE_FONT_RESOURCE;
+
+ // Image
+ case WebURLRequest::RequestContextImage:
+ case WebURLRequest::RequestContextImageSet:
+ return RESOURCE_TYPE_IMAGE;
+
+ // Media
+ case WebURLRequest::RequestContextAudio:
+ case WebURLRequest::RequestContextVideo:
+ return RESOURCE_TYPE_MEDIA;
+
+ // Object
+ case WebURLRequest::RequestContextEmbed:
+ case WebURLRequest::RequestContextObject:
+ return RESOURCE_TYPE_OBJECT;
+
+ // Ping
+ case WebURLRequest::RequestContextBeacon:
+ case WebURLRequest::RequestContextCSPReport:
+ case WebURLRequest::RequestContextPing:
+ return RESOURCE_TYPE_PING;
+
+ // Prefetch
+ case WebURLRequest::RequestContextPrefetch:
+ return RESOURCE_TYPE_PREFETCH;
+
+ // Script
+ case WebURLRequest::RequestContextImport:
+ case WebURLRequest::RequestContextScript:
+ return RESOURCE_TYPE_SCRIPT;
+
+ // Style
+ case WebURLRequest::RequestContextXSLT:
+ case WebURLRequest::RequestContextStyle:
+ return RESOURCE_TYPE_STYLESHEET;
+
+ // Subresource
+ case WebURLRequest::RequestContextDownload:
+ case WebURLRequest::RequestContextManifest:
+ case WebURLRequest::RequestContextSubresource:
+ case WebURLRequest::RequestContextPlugin:
+ return RESOURCE_TYPE_SUB_RESOURCE;
+
+ // TextTrack
+ case WebURLRequest::RequestContextTrack:
+ return RESOURCE_TYPE_MEDIA;
+
+ // Workers
+ case WebURLRequest::RequestContextServiceWorker:
+ return RESOURCE_TYPE_SERVICE_WORKER;
+ case WebURLRequest::RequestContextSharedWorker:
+ return RESOURCE_TYPE_SHARED_WORKER;
+ case WebURLRequest::RequestContextWorker:
+ return RESOURCE_TYPE_WORKER;
+
+ // Unspecified
+ case WebURLRequest::RequestContextInternal:
+ case WebURLRequest::RequestContextUnspecified:
+ return RESOURCE_TYPE_SUB_RESOURCE;
+
+ // XHR
+ case WebURLRequest::RequestContextEventSource:
+ case WebURLRequest::RequestContextFetch:
+ case WebURLRequest::RequestContextXMLHttpRequest:
+ return RESOURCE_TYPE_XHR;
+
+ // These should be handled by the FrameType checks at the top of the
+ // function.
+ case WebURLRequest::RequestContextForm:
+ case WebURLRequest::RequestContextHyperlink:
+ case WebURLRequest::RequestContextLocation:
+ case WebURLRequest::RequestContextFrame:
+ case WebURLRequest::RequestContextIframe:
+ NOTREACHED();
+ return RESOURCE_TYPE_SUB_RESOURCE;
+
+ default:
+ NOTREACHED();
+ return RESOURCE_TYPE_SUB_RESOURCE;
+ }
+}
+
+std::string GetWebURLRequestHeaders(const blink::WebURLRequest& request) {
+ HeaderFlattener flattener;
+ request.visitHTTPHeaderFields(&flattener);
+ return flattener.GetBuffer();
+}
+
+int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request) {
+ int load_flags = net::LOAD_NORMAL;
+ GURL url = request.url();
+ switch (request.cachePolicy()) {
+ case WebURLRequest::ReloadIgnoringCacheData:
+ // Required by LayoutTests/http/tests/misc/refresh-headers.php
+ load_flags |= net::LOAD_VALIDATE_CACHE;
+ break;
+ case WebURLRequest::ReloadBypassingCache:
+ load_flags |= net::LOAD_BYPASS_CACHE;
+ break;
+ case WebURLRequest::ReturnCacheDataElseLoad:
+ load_flags |= net::LOAD_PREFERRING_CACHE;
+ break;
+ case WebURLRequest::ReturnCacheDataDontLoad:
+ load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ break;
+ case WebURLRequest::UseProtocolCachePolicy:
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ if (request.reportRawHeaders())
+ load_flags |= net::LOAD_REPORT_RAW_HEADERS;
+
+ if (!request.allowStoredCredentials()) {
+ load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
+ load_flags |= net::LOAD_DO_NOT_SEND_COOKIES;
+ }
+
+ if (!request.allowStoredCredentials())
+ load_flags |= net::LOAD_DO_NOT_SEND_AUTH_DATA;
+
+ if (request.requestContext() == WebURLRequest::RequestContextXMLHttpRequest &&
+ (url.has_username() || url.has_password())) {
+ load_flags |= net::LOAD_DO_NOT_PROMPT_FOR_LOGIN;
+ }
+ return load_flags;
+}
+
+} // namespace content
diff --git a/chromium/content/child/web_url_request_util.h b/chromium/content/child/web_url_request_util.h
new file mode 100644
index 00000000000..b746d8067d2
--- /dev/null
+++ b/chromium/content/child/web_url_request_util.h
@@ -0,0 +1,28 @@
+// Copyright 2014 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 CONTENT_CHILD_TARGET_TYPE_CONVERSION_H_
+#define CONTENT_CHILD_TARGET_TYPE_CONVERSION_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+#include "content/public/common/resource_type.h"
+
+namespace blink {
+class WebURLRequest;
+}
+
+namespace content {
+
+CONTENT_EXPORT ResourceType WebURLRequestToResourceType(
+ const blink::WebURLRequest& request);
+
+std::string GetWebURLRequestHeaders(const blink::WebURLRequest& request);
+
+int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request);
+
+} // namespace content
+
+#endif // CONTENT_CHILD_TARGET_TYPE_CONVERSION_H_
diff --git a/chromium/content/child/webblobregistry_impl.cc b/chromium/content/child/webblobregistry_impl.cc
index fcc3ebf051a..9503ec5a6e6 100644
--- a/chromium/content/child/webblobregistry_impl.cc
+++ b/chromium/content/child/webblobregistry_impl.cc
@@ -12,11 +12,11 @@
#include "content/child/child_thread.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/fileapi/webblob_messages.h"
+#include "storage/common/blob/blob_data.h"
#include "third_party/WebKit/public/platform/WebBlobData.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebThreadSafeData.h"
#include "third_party/WebKit/public/platform/WebURL.h"
-#include "webkit/common/blob/blob_data.h"
using blink::WebBlobData;
using blink::WebString;
@@ -56,7 +56,7 @@ void WebBlobRegistryImpl::registerBlobData(
}
case WebBlobData::Item::TypeFile:
if (data_item.length) {
- webkit_blob::BlobData::Item item;
+ storage::BlobData::Item item;
item.SetToFilePathRange(
base::FilePath::FromUTF16Unsafe(data_item.filePath),
static_cast<uint64>(data_item.offset),
@@ -68,7 +68,7 @@ void WebBlobRegistryImpl::registerBlobData(
break;
case WebBlobData::Item::TypeBlob:
if (data_item.length) {
- webkit_blob::BlobData::Item item;
+ storage::BlobData::Item item;
item.SetToBlobRange(
data_item.blobUUID.utf8(),
static_cast<uint64>(data_item.offset),
@@ -81,7 +81,7 @@ void WebBlobRegistryImpl::registerBlobData(
if (data_item.length) {
// We only support filesystem URL as of now.
DCHECK(GURL(data_item.fileSystemURL).SchemeIsFileSystem());
- webkit_blob::BlobData::Item item;
+ storage::BlobData::Item item;
item.SetToFileSystemUrlRange(
data_item.fileSystemURL,
static_cast<uint64>(data_item.offset),
@@ -122,7 +122,7 @@ void WebBlobRegistryImpl::SendDataForBlob(const std::string& uuid_str,
if (data.size() == 0)
return;
if (data.size() < kLargeThresholdBytes) {
- webkit_blob::BlobData::Item item;
+ storage::BlobData::Item item;
item.SetToBytes(data.data(), data.size());
sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_str, item));
} else {
@@ -163,33 +163,33 @@ void WebBlobRegistryImpl::registerStreamURL(
}
void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
- WebThreadSafeData& data) {
+ const char* data, size_t length) {
DCHECK(ChildThread::current());
- if (data.size() == 0)
+ if (length == 0)
return;
- if (data.size() < kLargeThresholdBytes) {
- webkit_blob::BlobData::Item item;
- item.SetToBytes(data.data(), data.size());
+ if (length < kLargeThresholdBytes) {
+ storage::BlobData::Item item;
+ item.SetToBytes(data, length);
sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item));
} else {
// We handle larger amounts of data via SharedMemory instead of
// writing it directly to the IPC channel.
size_t shared_memory_size = std::min(
- data.size(), kMaxSharedMemoryBytes);
+ length, kMaxSharedMemoryBytes);
scoped_ptr<base::SharedMemory> shared_memory(
ChildThread::AllocateSharedMemory(shared_memory_size,
sender_.get()));
CHECK(shared_memory.get());
- size_t data_size = data.size();
- const char* data_ptr = data.data();
- while (data_size) {
- size_t chunk_size = std::min(data_size, shared_memory_size);
- memcpy(shared_memory->memory(), data_ptr, chunk_size);
+ size_t remaining_bytes = length;
+ const char* current_ptr = data;
+ while (remaining_bytes) {
+ size_t chunk_size = std::min(remaining_bytes, shared_memory_size);
+ memcpy(shared_memory->memory(), current_ptr, chunk_size);
sender_->Send(new StreamHostMsg_SyncAppendSharedMemory(
url, shared_memory->handle(), chunk_size));
- data_size -= chunk_size;
- data_ptr += chunk_size;
+ remaining_bytes -= chunk_size;
+ current_ptr += chunk_size;
}
}
}
diff --git a/chromium/content/child/webblobregistry_impl.h b/chromium/content/child/webblobregistry_impl.h
index 6588a529073..8fa967d9de7 100644
--- a/chromium/content/child/webblobregistry_impl.h
+++ b/chromium/content/child/webblobregistry_impl.h
@@ -2,19 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_FILEAPI_WEBBLOBREGISTRY_IMPL_H_
-#define CONTENT_CHILD_FILEAPI_WEBBLOBREGISTRY_IMPL_H_
+#ifndef CONTENT_CHILD_WEBBLOBREGISTRY_IMPL_H_
+#define CONTENT_CHILD_WEBBLOBREGISTRY_IMPL_H_
+
+#include <string>
#include "base/memory/ref_counted.h"
#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
-#include "webkit/common/blob/blob_data.h"
namespace blink {
-class WebBlobData;
-class WebString;
class WebThreadSafeData;
-class WebURL;
-}
+} // namespace blink
namespace content {
class ThreadSafeSender;
@@ -38,7 +36,7 @@ class WebBlobRegistryImpl : public blink::WebBlobRegistry {
virtual void registerStreamURL(const blink::WebURL& url,
const blink::WebURL& src_url);
virtual void addDataToStream(const blink::WebURL& url,
- blink::WebThreadSafeData& data);
+ const char* data, size_t length);
virtual void finalizeStream(const blink::WebURL& url);
virtual void abortStream(const blink::WebURL& url);
virtual void unregisterStreamURL(const blink::WebURL& url);
diff --git a/chromium/content/child/webcrypto/OWNERS b/chromium/content/child/webcrypto/OWNERS
index a1853a1bcb1..6b60858e6e8 100644
--- a/chromium/content/child/webcrypto/OWNERS
+++ b/chromium/content/child/webcrypto/OWNERS
@@ -1,2 +1,2 @@
-eroman@chromium.org
-rsleevi@chromium.org
+eroman@chromium.org
+rsleevi@chromium.org
diff --git a/chromium/content/child/webcrypto/algorithm_dispatch.cc b/chromium/content/child/webcrypto/algorithm_dispatch.cc
new file mode 100644
index 00000000000..f8d7933c8fc
--- /dev/null
+++ b/chromium/content/child/webcrypto/algorithm_dispatch.cc
@@ -0,0 +1,253 @@
+// Copyright 2014 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 "content/child/webcrypto/algorithm_dispatch.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/algorithm_registry.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/platform_crypto.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ if (algorithm.id() != key.algorithm().id())
+ return Status::ErrorUnexpected();
+
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ return impl->Decrypt(algorithm, key, data, buffer);
+}
+
+Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ if (algorithm.id() != key.algorithm().id())
+ return Status::ErrorUnexpected();
+
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ return impl->Encrypt(algorithm, key, data, buffer);
+}
+
+Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) {
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(key.algorithm().id(), &impl);
+ if (status.IsError())
+ return status;
+
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ return impl->ExportKeyRaw(key, buffer);
+ case blink::WebCryptoKeyFormatSpki:
+ return impl->ExportKeySpki(key, buffer);
+ case blink::WebCryptoKeyFormatPkcs8:
+ return impl->ExportKeyPkcs8(key, buffer);
+ case blink::WebCryptoKeyFormatJwk:
+ return impl->ExportKeyJwk(key, buffer);
+ default:
+ return Status::ErrorUnsupported();
+ }
+}
+
+} // namespace
+
+Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
+ return Status::ErrorUnexpected();
+ return EncryptDontCheckUsage(algorithm, key, data, buffer);
+}
+
+Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
+ return Status::ErrorUnexpected();
+ return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
+}
+
+Status Digest(const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ return impl->Digest(algorithm, data, buffer);
+}
+
+Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) {
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ return impl->GenerateKey(algorithm, extractable, usages, result);
+}
+
+// Note that this function may be called from the target Blink thread.
+Status ImportKey(blink::WebCryptoKeyFormat format,
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ status = impl->VerifyKeyUsagesBeforeImportKey(format, usages);
+ if (status.IsError())
+ return status;
+
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ return impl->ImportKeyRaw(key_data, algorithm, extractable, usages, key);
+ case blink::WebCryptoKeyFormatSpki:
+ return impl->ImportKeySpki(key_data, algorithm, extractable, usages, key);
+ case blink::WebCryptoKeyFormatPkcs8:
+ return impl->ImportKeyPkcs8(
+ key_data, algorithm, extractable, usages, key);
+ case blink::WebCryptoKeyFormatJwk:
+ return impl->ImportKeyJwk(key_data, algorithm, extractable, usages, key);
+ default:
+ return Status::ErrorUnsupported();
+ }
+}
+
+Status ExportKey(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) {
+ if (!key.extractable())
+ return Status::ErrorKeyNotExtractable();
+ return ExportKeyDontCheckExtractability(format, key, buffer);
+}
+
+Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign))
+ return Status::ErrorUnexpected();
+ if (algorithm.id() != key.algorithm().id())
+ return Status::ErrorUnexpected();
+
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ return impl->Sign(algorithm, key, data, buffer);
+}
+
+Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) {
+ if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageVerify))
+ return Status::ErrorUnexpected();
+ if (algorithm.id() != key.algorithm().id())
+ return Status::ErrorUnexpected();
+
+ const AlgorithmImplementation* impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &impl);
+ if (status.IsError())
+ return status;
+
+ return impl->Verify(algorithm, key, signature, data, signature_match);
+}
+
+Status WrapKey(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key_to_wrap,
+ const blink::WebCryptoKey& wrapping_key,
+ const blink::WebCryptoAlgorithm& wrapping_algorithm,
+ std::vector<uint8_t>* buffer) {
+ if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey))
+ return Status::ErrorUnexpected();
+
+ std::vector<uint8_t> exported_data;
+ Status status = ExportKey(format, key_to_wrap, &exported_data);
+ if (status.IsError())
+ return status;
+ return EncryptDontCheckUsage(
+ wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer);
+}
+
+Status UnwrapKey(blink::WebCryptoKeyFormat format,
+ const CryptoData& wrapped_key_data,
+ const blink::WebCryptoKey& wrapping_key,
+ const blink::WebCryptoAlgorithm& wrapping_algorithm,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
+ return Status::ErrorUnexpected();
+ if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
+ return Status::ErrorUnexpected();
+
+ // Fail fast if the import is doomed to fail.
+ const AlgorithmImplementation* import_impl = NULL;
+ Status status = GetAlgorithmImplementation(algorithm.id(), &import_impl);
+ if (status.IsError())
+ return status;
+
+ status = import_impl->VerifyKeyUsagesBeforeImportKey(format, usages);
+ if (status.IsError())
+ return status;
+
+ std::vector<uint8_t> buffer;
+ status = DecryptDontCheckKeyUsage(
+ wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
+ if (status.IsError())
+ return status;
+
+ // NOTE that returning the details of ImportKey() failures may leak
+ // information about the plaintext of the encrypted key (for instance the JWK
+ // key_ops). As long as the ImportKey error messages don't describe actual
+ // key bytes however this should be OK. For more discussion see
+ // http://crubg.com/372040
+ return ImportKey(
+ format, CryptoData(buffer), algorithm, extractable, usages, key);
+}
+
+scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
+ blink::WebCryptoAlgorithmId algorithm) {
+ PlatformInit();
+ return CreatePlatformDigestor(algorithm);
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/algorithm_dispatch.h b/chromium/content/child/webcrypto/algorithm_dispatch.h
new file mode 100644
index 00000000000..3eefb46de5d
--- /dev/null
+++ b/chromium/content/child/webcrypto/algorithm_dispatch.h
@@ -0,0 +1,97 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_ALGORITHM_DISPATCH_H_
+#define CONTENT_CHILD_WEBCRYPTO_ALGORITHM_DISPATCH_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class AlgorithmImplementation;
+class CryptoData;
+class GenerateKeyResult;
+class Status;
+
+// These functions provide an entry point for synchronous webcrypto operations.
+//
+// The inputs to these methods come from Blink, and hence the validations done
+// by Blink can be assumed:
+//
+// * The algorithm parameters are consistent with the algorithm
+// * The key contains the required usage for the operation
+
+CONTENT_EXPORT Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer);
+
+CONTENT_EXPORT Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer);
+
+CONTENT_EXPORT Status Digest(const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer);
+
+CONTENT_EXPORT Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result);
+
+CONTENT_EXPORT Status ImportKey(blink::WebCryptoKeyFormat format,
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key);
+
+CONTENT_EXPORT Status ExportKey(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer);
+
+CONTENT_EXPORT Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer);
+
+CONTENT_EXPORT Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match);
+
+CONTENT_EXPORT Status
+ WrapKey(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key_to_wrap,
+ const blink::WebCryptoKey& wrapping_key,
+ const blink::WebCryptoAlgorithm& wrapping_algorithm,
+ std::vector<uint8_t>* buffer);
+
+CONTENT_EXPORT Status
+ UnwrapKey(blink::WebCryptoKeyFormat format,
+ const CryptoData& wrapped_key_data,
+ const blink::WebCryptoKey& wrapping_key,
+ const blink::WebCryptoAlgorithm& wrapping_algorithm,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key);
+
+CONTENT_EXPORT scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
+ blink::WebCryptoAlgorithmId algorithm);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_ALGORITHM_DISPATCH_H_
diff --git a/chromium/content/child/webcrypto/algorithm_implementation.cc b/chromium/content/child/webcrypto/algorithm_implementation.cc
new file mode 100644
index 00000000000..b815a527cf6
--- /dev/null
+++ b/chromium/content/child/webcrypto/algorithm_implementation.cc
@@ -0,0 +1,131 @@
+// Copyright 2014 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 "content/child/webcrypto/algorithm_implementation.h"
+
+#include "content/child/webcrypto/status.h"
+
+namespace content {
+
+namespace webcrypto {
+
+AlgorithmImplementation::~AlgorithmImplementation() {
+}
+
+Status AlgorithmImplementation::Encrypt(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupported();
+}
+
+Status AlgorithmImplementation::Decrypt(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupported();
+}
+
+Status AlgorithmImplementation::Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupported();
+}
+
+Status AlgorithmImplementation::Verify(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const {
+ return Status::ErrorUnsupported();
+}
+
+Status AlgorithmImplementation::Digest(
+ const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupported();
+}
+
+Status AlgorithmImplementation::GenerateKey(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const {
+ return Status::ErrorUnsupported();
+}
+
+Status AlgorithmImplementation::VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const {
+ return Status::ErrorUnsupportedImportKeyFormat();
+}
+
+Status AlgorithmImplementation::ImportKeyRaw(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ return Status::ErrorUnsupportedImportKeyFormat();
+}
+
+Status AlgorithmImplementation::ImportKeyPkcs8(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ return Status::ErrorUnsupportedImportKeyFormat();
+}
+
+Status AlgorithmImplementation::ImportKeySpki(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ return Status::ErrorUnsupportedImportKeyFormat();
+}
+
+Status AlgorithmImplementation::ImportKeyJwk(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ return Status::ErrorUnsupportedImportKeyFormat();
+}
+
+Status AlgorithmImplementation::ExportKeyRaw(
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupportedExportKeyFormat();
+}
+
+Status AlgorithmImplementation::ExportKeyPkcs8(
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupportedExportKeyFormat();
+}
+
+Status AlgorithmImplementation::ExportKeySpki(
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupportedExportKeyFormat();
+}
+
+Status AlgorithmImplementation::ExportKeyJwk(
+ const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ return Status::ErrorUnsupportedExportKeyFormat();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/algorithm_implementation.h b/chromium/content/child/webcrypto/algorithm_implementation.h
new file mode 100644
index 00000000000..e926ad0324d
--- /dev/null
+++ b/chromium/content/child/webcrypto/algorithm_implementation.h
@@ -0,0 +1,157 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_ALGORITHM_IMPLEMENTATION_H_
+#define CONTENT_CHILD_WEBCRYPTO_ALGORITHM_IMPLEMENTATION_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class GenerateKeyResult;
+class Status;
+
+// AlgorithmImplementation is a base class for *executing* the operations of an
+// algorithm (generating keys, encrypting, signing, etc.).
+//
+// This is in contrast to blink::WebCryptoAlgorithm which instead *describes*
+// the operation and its parameters.
+//
+// AlgorithmImplementation has reasonable default implementations for all
+// methods which behave as if the operation is it is unsupported, so
+// implementations need only override the applicable methods.
+//
+// Unless stated otherwise methods of AlgorithmImplementation are responsible
+// for sanitizing their inputs. The following can be assumed:
+//
+// * |algorithm.id()| and |key.algorithm.id()| matches the algorithm under
+// which the implementation was registerd.
+// * |algorithm| has the correct parameters type for the operation.
+// * The key usages have already been verified. In fact in the case of calls
+// to Encrypt()/Decrypt() the corresponding key usages may not be present
+// (when wrapping/unwrapping).
+class AlgorithmImplementation {
+ public:
+ virtual ~AlgorithmImplementation();
+
+ // This method corresponds to Web Crypto's crypto.subtle.encrypt().
+ virtual Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const;
+
+ // This method corresponds to Web Crypto's crypto.subtle.decrypt().
+ virtual Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const;
+
+ // This method corresponds to Web Crypto's crypto.subtle.sign().
+ virtual Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const;
+
+ // This method corresponds to Web Crypto's crypto.subtle.verify().
+ virtual Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const;
+
+ // This method corresponds to Web Crypto's crypto.subtle.digest().
+ virtual Status Digest(const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const;
+
+ // This method corresponds to Web Crypto's crypto.subtle.generateKey().
+ //
+ // Implementations MUST verify |usages| and return an error if it is not
+ // appropriate.
+ virtual Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const;
+
+ // -----------------------------------------------
+ // Key import
+ // -----------------------------------------------
+
+ // VerifyKeyUsagesBeforeImportKey() must be called before either
+ // importing a key, or unwrapping a key.
+ //
+ // Implementations should return an error if the requested usages are invalid
+ // when importing for the specified format.
+ //
+ // For instance, importing an RSA-SSA key with 'spki' format and Sign usage
+ // is invalid. The 'spki' format implies it will be a public key, and public
+ // keys do not support signing.
+ //
+ // When called with format=JWK the key type may be unknown. The
+ // ImportKeyJwk() must do the final usage check.
+ virtual Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const;
+
+ // This method corresponds to Web Crypto's
+ // crypto.subtle.importKey(format='raw').
+ virtual Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const;
+
+ // This method corresponds to Web Crypto's
+ // crypto.subtle.importKey(format='pkcs8').
+ virtual Status ImportKeyPkcs8(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const;
+
+ // This method corresponds to Web Crypto's
+ // crypto.subtle.importKey(format='spki').
+ virtual Status ImportKeySpki(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const;
+
+ // This method corresponds to Web Crypto's
+ // crypto.subtle.importKey(format='jwk').
+ virtual Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const;
+
+ // -----------------------------------------------
+ // Key export
+ // -----------------------------------------------
+
+ virtual Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const;
+
+ virtual Status ExportKeyPkcs8(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const;
+
+ virtual Status ExportKeySpki(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const;
+
+ virtual Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_ALGORITHM_IMPLEMENTATION_H_
diff --git a/chromium/content/child/webcrypto/algorithm_registry.cc b/chromium/content/child/webcrypto/algorithm_registry.cc
new file mode 100644
index 00000000000..7f674db0bbe
--- /dev/null
+++ b/chromium/content/child/webcrypto/algorithm_registry.cc
@@ -0,0 +1,90 @@
+// Copyright 2014 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 "content/child/webcrypto/algorithm_registry.h"
+
+#include "base/lazy_instance.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/platform_crypto.h"
+#include "content/child/webcrypto/status.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// This class is used as a singleton. All methods must be threadsafe.
+class AlgorithmRegistry {
+ public:
+ AlgorithmRegistry()
+ : sha_(CreatePlatformShaImplementation()),
+ aes_gcm_(CreatePlatformAesGcmImplementation()),
+ aes_cbc_(CreatePlatformAesCbcImplementation()),
+ aes_ctr_(CreatePlatformAesCtrImplementation()),
+ aes_kw_(CreatePlatformAesKwImplementation()),
+ hmac_(CreatePlatformHmacImplementation()),
+ rsa_ssa_(CreatePlatformRsaSsaImplementation()),
+ rsa_oaep_(CreatePlatformRsaOaepImplementation()),
+ rsa_pss_(CreatePlatformRsaPssImplementation()) {
+ PlatformInit();
+ }
+
+ const AlgorithmImplementation* GetAlgorithm(
+ blink::WebCryptoAlgorithmId id) const {
+ switch (id) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ case blink::WebCryptoAlgorithmIdSha256:
+ case blink::WebCryptoAlgorithmIdSha384:
+ case blink::WebCryptoAlgorithmIdSha512:
+ return sha_.get();
+ case blink::WebCryptoAlgorithmIdAesGcm:
+ return aes_gcm_.get();
+ case blink::WebCryptoAlgorithmIdAesCbc:
+ return aes_cbc_.get();
+ case blink::WebCryptoAlgorithmIdAesCtr:
+ return aes_ctr_.get();
+ case blink::WebCryptoAlgorithmIdAesKw:
+ return aes_kw_.get();
+ case blink::WebCryptoAlgorithmIdHmac:
+ return hmac_.get();
+ case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
+ return rsa_ssa_.get();
+ case blink::WebCryptoAlgorithmIdRsaOaep:
+ return rsa_oaep_.get();
+ case blink::WebCryptoAlgorithmIdRsaPss:
+ return rsa_pss_.get();
+ default:
+ return NULL;
+ }
+ }
+
+ private:
+ const scoped_ptr<AlgorithmImplementation> sha_;
+ const scoped_ptr<AlgorithmImplementation> aes_gcm_;
+ const scoped_ptr<AlgorithmImplementation> aes_cbc_;
+ const scoped_ptr<AlgorithmImplementation> aes_ctr_;
+ const scoped_ptr<AlgorithmImplementation> aes_kw_;
+ const scoped_ptr<AlgorithmImplementation> hmac_;
+ const scoped_ptr<AlgorithmImplementation> rsa_ssa_;
+ const scoped_ptr<AlgorithmImplementation> rsa_oaep_;
+ const scoped_ptr<AlgorithmImplementation> rsa_pss_;
+};
+
+} // namespace
+
+base::LazyInstance<AlgorithmRegistry>::Leaky g_algorithm_registry =
+ LAZY_INSTANCE_INITIALIZER;
+
+Status GetAlgorithmImplementation(blink::WebCryptoAlgorithmId id,
+ const AlgorithmImplementation** impl) {
+ *impl = g_algorithm_registry.Get().GetAlgorithm(id);
+ if (*impl)
+ return Status::Success();
+ return Status::ErrorUnsupported();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/algorithm_registry.h b/chromium/content/child/webcrypto/algorithm_registry.h
new file mode 100644
index 00000000000..6db5f5f56dd
--- /dev/null
+++ b/chromium/content/child/webcrypto/algorithm_registry.h
@@ -0,0 +1,32 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_ALGORITHM_REGISTRY_H_
+#define CONTENT_CHILD_WEBCRYPTO_ALGORITHM_REGISTRY_H_
+
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class AlgorithmImplementation;
+class Status;
+
+// Retrieves the AlgorithmImplementation applicable for |id|.
+//
+// If there is no available implementation, then an error is returned, and
+// *impl is set to NULL.
+//
+// Otherwise Success is returned and *impl is set to a non-NULL value. The
+// AlgorithmImplementation pointer will remain valid until the program's
+// termination.
+Status GetAlgorithmImplementation(blink::WebCryptoAlgorithmId id,
+ const AlgorithmImplementation** impl);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_ALGORITHM_REGISTRY_H_
diff --git a/chromium/content/child/webcrypto/generate_key_result.cc b/chromium/content/child/webcrypto/generate_key_result.cc
new file mode 100644
index 00000000000..3c61657eb55
--- /dev/null
+++ b/chromium/content/child/webcrypto/generate_key_result.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 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 "content/child/webcrypto/generate_key_result.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+namespace webcrypto {
+
+GenerateKeyResult::GenerateKeyResult() : type_(TYPE_NULL) {
+}
+
+GenerateKeyResult::Type GenerateKeyResult::type() const {
+ return type_;
+}
+
+const blink::WebCryptoKey& GenerateKeyResult::secret_key() const {
+ DCHECK_EQ(TYPE_SECRET_KEY, type_);
+ return secret_key_;
+}
+
+const blink::WebCryptoKey& GenerateKeyResult::public_key() const {
+ DCHECK_EQ(TYPE_PUBLIC_PRIVATE_KEY_PAIR, type_);
+ return public_key_;
+}
+
+const blink::WebCryptoKey& GenerateKeyResult::private_key() const {
+ DCHECK_EQ(TYPE_PUBLIC_PRIVATE_KEY_PAIR, type_);
+ return private_key_;
+}
+
+void GenerateKeyResult::AssignSecretKey(const blink::WebCryptoKey& key) {
+ type_ = TYPE_SECRET_KEY;
+ secret_key_ = key;
+}
+
+void GenerateKeyResult::AssignKeyPair(const blink::WebCryptoKey& public_key,
+ const blink::WebCryptoKey& private_key) {
+ type_ = TYPE_PUBLIC_PRIVATE_KEY_PAIR;
+ public_key_ = public_key;
+ private_key_ = private_key;
+}
+
+void GenerateKeyResult::Complete(blink::WebCryptoResult* out) const {
+ switch (type_) {
+ case TYPE_NULL:
+ NOTREACHED();
+ break;
+ case TYPE_SECRET_KEY:
+ out->completeWithKey(secret_key());
+ break;
+ case TYPE_PUBLIC_PRIVATE_KEY_PAIR:
+ out->completeWithKeyPair(public_key(), private_key());
+ break;
+ }
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/generate_key_result.h b/chromium/content/child/webcrypto/generate_key_result.h
new file mode 100644
index 00000000000..fcc13f80855
--- /dev/null
+++ b/chromium/content/child/webcrypto/generate_key_result.h
@@ -0,0 +1,60 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_GENERATE_KEY_RESULT_H_
+#define CONTENT_CHILD_WEBCRYPTO_GENERATE_KEY_RESULT_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+// This is the result object when generating keys. It encapsulates either a
+// secret key, or a public/private key pair.
+class CONTENT_EXPORT GenerateKeyResult {
+ public:
+ enum Type {
+ // An empty (or "null") result.
+ TYPE_NULL,
+
+ // The result is a secret key, accessible through secret_key()
+ TYPE_SECRET_KEY,
+
+ // The result is a public/private key pair, accessible through public_key()
+ // and private_key()
+ TYPE_PUBLIC_PRIVATE_KEY_PAIR
+ };
+
+ // Initializes a "null" instance.
+ GenerateKeyResult();
+
+ Type type() const;
+
+ const blink::WebCryptoKey& secret_key() const;
+ const blink::WebCryptoKey& public_key() const;
+ const blink::WebCryptoKey& private_key() const;
+
+ void AssignSecretKey(const blink::WebCryptoKey& key);
+ void AssignKeyPair(const blink::WebCryptoKey& public_key,
+ const blink::WebCryptoKey& private_key);
+
+ // Sends the key(s) to the Blink result. Should not be called for "null"
+ // results.
+ void Complete(blink::WebCryptoResult* out) const;
+
+ private:
+ Type type_;
+
+ blink::WebCryptoKey secret_key_;
+ blink::WebCryptoKey public_key_;
+ blink::WebCryptoKey private_key_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_GENERATE_KEY_RESULT_H_
diff --git a/chromium/content/child/webcrypto/jwk.cc b/chromium/content/child/webcrypto/jwk.cc
index a3d65da2051..b0073cc1b8f 100644
--- a/chromium/content/child/webcrypto/jwk.cc
+++ b/chromium/content/child/webcrypto/jwk.cc
@@ -2,23 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "jwk.h"
-
-#include <algorithm>
-#include <functional>
-#include <map>
+#include "content/child/webcrypto/jwk.h"
+#include "base/base64.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
+#include "base/stl_util.h"
#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
#include "content/child/webcrypto/crypto_data.h"
-#include "content/child/webcrypto/platform_crypto.h"
-#include "content/child/webcrypto/shared_crypto.h"
#include "content/child/webcrypto/status.h"
#include "content/child/webcrypto/webcrypto_util.h"
-#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+// TODO(eroman): The algorithm-specific logic in this file for AES and RSA
+// should be moved into the corresponding AlgorithmImplementation file. It
+// exists in this file to avoid duplication between OpenSSL and NSS
+// implementations.
// JSON Web Key Format (JWK)
// http://tools.ietf.org/html/draft-ietf-jose-json-web-key-21
@@ -44,7 +42,7 @@
// Web Crypto Key type <-- (deduced)
// Web Crypto Key extractable <-- JWK ext + input extractable
// Web Crypto Key algorithm <-- JWK alg + input algorithm
-// Web Crypto Key keyUsage <-- JWK use, key_ops + input usage_mask
+// Web Crypto Key keyUsage <-- JWK use, key_ops + input usages
// Web Crypto Key keying material <-- kty-specific parameters
//
// Values for each JWK entry are case-sensitive and defined in
@@ -181,7 +179,7 @@
// +-------+--------------------------------------------------------------+
//
// Consistency and conflict resolution
-// The 'algorithm', 'extractable', and 'usage_mask' input parameters
+// The 'algorithm', 'extractable', and 'usages' input parameters
// may be different than the corresponding values inside the JWK. The Web
// Crypto spec says that if a JWK value is present but is inconsistent with
// the input value, it is an error and the operation must fail. If no
@@ -197,10 +195,10 @@
// false but the input parameter is true, it is an inconsistency. If both
// are true or both are false, use that value.
//
-// usage_mask
-// The input usage_mask must be a strict subset of the interpreted JWK use
-// value, else it is judged inconsistent. In all cases the input usage_mask
-// is used as the final usage_mask.
+// usages
+// The input usages must be a strict subset of the interpreted JWK use
+// value, else it is judged inconsistent. In all cases the input usages
+// is used as the final usages.
//
namespace content {
@@ -209,22 +207,6 @@ namespace webcrypto {
namespace {
-// Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a
-// hash_id that is not a SHA*.
-blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(
- blink::WebCryptoAlgorithmId hash_id) {
- return CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, hash_id);
-}
-
-// Creates an RSA-OAEP algorithm. It is an error to call this with a hash_id
-// that is not a SHA*.
-blink::WebCryptoAlgorithm CreateRsaOaepImportAlgorithm(
- blink::WebCryptoAlgorithmId hash_id) {
- return CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
- hash_id);
-}
-
// Web Crypto equivalent usage mask for JWK 'use' = 'enc'.
const blink::WebCryptoKeyUsageMask kJwkEncUsage =
blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
@@ -234,783 +216,494 @@ const blink::WebCryptoKeyUsageMask kJwkEncUsage =
const blink::WebCryptoKeyUsageMask kJwkSigUsage =
blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
-typedef blink::WebCryptoAlgorithm (*AlgorithmCreationFunc)();
-
-class JwkAlgorithmInfo {
- public:
- JwkAlgorithmInfo()
- : creation_func_(NULL),
- required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {}
-
- explicit JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func)
- : creation_func_(algorithm_creation_func),
- required_key_length_bytes_(NO_KEY_SIZE_REQUIREMENT) {}
+// Checks that the "ext" member of the JWK is consistent with
+// "expected_extractable".
+Status VerifyExt(const JwkReader& jwk, bool expected_extractable) {
+ // JWK "ext" (optional) --> extractable parameter
+ bool jwk_ext_value = false;
+ bool has_jwk_ext;
+ Status status = jwk.GetOptionalBool("ext", &jwk_ext_value, &has_jwk_ext);
+ if (status.IsError())
+ return status;
+ if (has_jwk_ext && expected_extractable && !jwk_ext_value)
+ return Status::ErrorJwkExtInconsistent();
+ return Status::Success();
+}
- JwkAlgorithmInfo(AlgorithmCreationFunc algorithm_creation_func,
- unsigned int required_key_length_bits)
- : creation_func_(algorithm_creation_func),
- required_key_length_bytes_(required_key_length_bits / 8) {
- DCHECK_EQ(0u, required_key_length_bits % 8);
+// Checks that the usages ("use" and "key_ops") of the JWK is consistent with
+// "expected_usages".
+Status VerifyUsages(const JwkReader& jwk,
+ blink::WebCryptoKeyUsageMask expected_usages) {
+ // JWK "key_ops" (optional) --> usages parameter
+ base::ListValue* jwk_key_ops_value = NULL;
+ bool has_jwk_key_ops;
+ Status status =
+ jwk.GetOptionalList("key_ops", &jwk_key_ops_value, &has_jwk_key_ops);
+ if (status.IsError())
+ return status;
+ blink::WebCryptoKeyUsageMask jwk_key_ops_mask = 0;
+ if (has_jwk_key_ops) {
+ status =
+ GetWebCryptoUsagesFromJwkKeyOps(jwk_key_ops_value, &jwk_key_ops_mask);
+ if (status.IsError())
+ return status;
+ // The input usages must be a subset of jwk_key_ops_mask.
+ if (!ContainsKeyUsages(jwk_key_ops_mask, expected_usages))
+ return Status::ErrorJwkKeyopsInconsistent();
}
- bool CreateImportAlgorithm(blink::WebCryptoAlgorithm* algorithm) const {
- *algorithm = creation_func_();
- return !algorithm->isNull();
+ // JWK "use" (optional) --> usages parameter
+ std::string jwk_use_value;
+ bool has_jwk_use;
+ status = jwk.GetOptionalString("use", &jwk_use_value, &has_jwk_use);
+ if (status.IsError())
+ return status;
+ blink::WebCryptoKeyUsageMask jwk_use_mask = 0;
+ if (has_jwk_use) {
+ if (jwk_use_value == "enc")
+ jwk_use_mask = kJwkEncUsage;
+ else if (jwk_use_value == "sig")
+ jwk_use_mask = kJwkSigUsage;
+ else
+ return Status::ErrorJwkUnrecognizedUse();
+ // The input usages must be a subset of jwk_use_mask.
+ if (!ContainsKeyUsages(jwk_use_mask, expected_usages))
+ return Status::ErrorJwkUseInconsistent();
}
- bool IsInvalidKeyByteLength(size_t byte_length) const {
- if (required_key_length_bytes_ == NO_KEY_SIZE_REQUIREMENT)
- return false;
- return required_key_length_bytes_ != byte_length;
- }
+ // If both 'key_ops' and 'use' are present, ensure they are consistent.
+ if (has_jwk_key_ops && has_jwk_use &&
+ !ContainsKeyUsages(jwk_use_mask, jwk_key_ops_mask))
+ return Status::ErrorJwkUseAndKeyopsInconsistent();
- private:
- enum { NO_KEY_SIZE_REQUIREMENT = UINT_MAX };
-
- AlgorithmCreationFunc creation_func_;
-
- // The expected key size for the algorithm or NO_KEY_SIZE_REQUIREMENT.
- unsigned int required_key_length_bytes_;
-};
-
-typedef std::map<std::string, JwkAlgorithmInfo> JwkAlgorithmInfoMap;
-
-class JwkAlgorithmRegistry {
- public:
- JwkAlgorithmRegistry() {
- // TODO(eroman):
- // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-20
- // says HMAC with SHA-2 should have a key size at least as large as the
- // hash output.
- alg_to_info_["HS1"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha1>);
- alg_to_info_["HS256"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha256>);
- alg_to_info_["HS384"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha384>);
- alg_to_info_["HS512"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha512>);
- alg_to_info_["RS1"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha1>);
- alg_to_info_["RS256"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha256>);
- alg_to_info_["RS384"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha384>);
- alg_to_info_["RS512"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha512>);
- alg_to_info_["RSA-OAEP"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha1>);
- alg_to_info_["RSA-OAEP-256"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha256>);
- alg_to_info_["RSA-OAEP-384"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha384>);
- alg_to_info_["RSA-OAEP-512"] =
- JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaOaepImportAlgorithm,
- blink::WebCryptoAlgorithmIdSha512>);
- alg_to_info_["A128KW"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesKw>,
- 128);
- alg_to_info_["A192KW"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesKw>,
- 192);
- alg_to_info_["A256KW"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesKw>,
- 256);
- alg_to_info_["A128GCM"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>,
- 128);
- alg_to_info_["A192GCM"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>,
- 192);
- alg_to_info_["A256GCM"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesGcm>,
- 256);
- alg_to_info_["A128CBC"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesCbc>,
- 128);
- alg_to_info_["A192CBC"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesCbc>,
- 192);
- alg_to_info_["A256CBC"] = JwkAlgorithmInfo(
- &BindAlgorithmId<CreateAlgorithm, blink::WebCryptoAlgorithmIdAesCbc>,
- 256);
- }
+ return Status::Success();
+}
- // Returns NULL if the algorithm name was not registered.
- const JwkAlgorithmInfo* GetAlgorithmInfo(const std::string& jwk_alg) const {
- const JwkAlgorithmInfoMap::const_iterator pos = alg_to_info_.find(jwk_alg);
- if (pos == alg_to_info_.end())
- return NULL;
- return &pos->second;
- }
+} // namespace
- private:
- // Binds a WebCryptoAlgorithmId value to a compatible factory function.
- typedef blink::WebCryptoAlgorithm (*FuncWithWebCryptoAlgIdArg)(
- blink::WebCryptoAlgorithmId);
- template <FuncWithWebCryptoAlgIdArg func,
- blink::WebCryptoAlgorithmId algorithm_id>
- static blink::WebCryptoAlgorithm BindAlgorithmId() {
- return func(algorithm_id);
- }
+JwkReader::JwkReader() {
+}
- JwkAlgorithmInfoMap alg_to_info_;
-};
-
-base::LazyInstance<JwkAlgorithmRegistry> jwk_alg_registry =
- LAZY_INSTANCE_INITIALIZER;
-
-bool ImportAlgorithmsConsistent(const blink::WebCryptoAlgorithm& alg1,
- const blink::WebCryptoAlgorithm& alg2) {
- DCHECK(!alg1.isNull());
- DCHECK(!alg2.isNull());
- if (alg1.id() != alg2.id())
- return false;
- if (alg1.paramsType() != alg2.paramsType())
- return false;
- switch (alg1.paramsType()) {
- case blink::WebCryptoAlgorithmParamsTypeNone:
- return true;
- case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
- return ImportAlgorithmsConsistent(alg1.rsaHashedImportParams()->hash(),
- alg2.rsaHashedImportParams()->hash());
- case blink::WebCryptoAlgorithmParamsTypeHmacImportParams:
- return ImportAlgorithmsConsistent(alg1.hmacImportParams()->hash(),
- alg2.hmacImportParams()->hash());
- default:
- return false;
+JwkReader::~JwkReader() {
+}
+
+Status JwkReader::Init(const CryptoData& bytes,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ const std::string& expected_kty,
+ const std::string& expected_alg) {
+ if (!bytes.byte_length())
+ return Status::ErrorImportEmptyKeyData();
+
+ // Parse the incoming JWK JSON.
+ base::StringPiece json_string(reinterpret_cast<const char*>(bytes.bytes()),
+ bytes.byte_length());
+
+ scoped_ptr<base::Value> value(base::JSONReader::Read(json_string));
+ base::DictionaryValue* dict_value = NULL;
+
+ if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value)
+ return Status::ErrorJwkNotDictionary();
+
+ // Release |value|, as ownership will be transferred to |dict| via
+ // |dict_value|, which points to the same object as |value|.
+ ignore_result(value.release());
+ dict_.reset(dict_value);
+
+ // JWK "kty". Exit early if this required JWK parameter is missing.
+ std::string kty;
+ Status status = GetString("kty", &kty);
+ if (status.IsError())
+ return status;
+
+ if (kty != expected_kty)
+ return Status::ErrorJwkUnexpectedKty(expected_kty);
+
+ status = VerifyExt(*this, expected_extractable);
+ if (status.IsError())
+ return status;
+
+ status = VerifyUsages(*this, expected_usages);
+ if (status.IsError())
+ return status;
+
+ // Verify the algorithm if an expectation was provided.
+ if (!expected_alg.empty()) {
+ status = VerifyAlg(expected_alg);
+ if (status.IsError())
+ return status;
}
+
+ return Status::Success();
}
-// Extracts the required string property with key |path| from |dict| and saves
-// the result to |*result|. If the property does not exist or is not a string,
-// returns an error.
-Status GetJwkString(base::DictionaryValue* dict,
- const std::string& path,
- std::string* result) {
+bool JwkReader::HasMember(const std::string& member_name) const {
+ return dict_->HasKey(member_name);
+}
+
+Status JwkReader::GetString(const std::string& member_name,
+ std::string* result) const {
base::Value* value = NULL;
- if (!dict->Get(path, &value))
- return Status::ErrorJwkPropertyMissing(path);
+ if (!dict_->Get(member_name, &value))
+ return Status::ErrorJwkPropertyMissing(member_name);
if (!value->GetAsString(result))
- return Status::ErrorJwkPropertyWrongType(path, "string");
+ return Status::ErrorJwkPropertyWrongType(member_name, "string");
return Status::Success();
}
-// Extracts the optional string property with key |path| from |dict| and saves
-// the result to |*result| if it was found. If the property exists and is not a
-// string, returns an error. Otherwise returns success, and sets
-// |*property_exists| if it was found.
-Status GetOptionalJwkString(base::DictionaryValue* dict,
- const std::string& path,
- std::string* result,
- bool* property_exists) {
- *property_exists = false;
+Status JwkReader::GetOptionalString(const std::string& member_name,
+ std::string* result,
+ bool* member_exists) const {
+ *member_exists = false;
base::Value* value = NULL;
- if (!dict->Get(path, &value))
+ if (!dict_->Get(member_name, &value))
return Status::Success();
if (!value->GetAsString(result))
- return Status::ErrorJwkPropertyWrongType(path, "string");
+ return Status::ErrorJwkPropertyWrongType(member_name, "string");
- *property_exists = true;
+ *member_exists = true;
return Status::Success();
}
-// Extracts the optional array property with key |path| from |dict| and saves
-// the result to |*result| if it was found. If the property exists and is not an
-// array, returns an error. Otherwise returns success, and sets
-// |*property_exists| if it was found. Note that |*result| is owned by |dict|.
-Status GetOptionalJwkList(base::DictionaryValue* dict,
- const std::string& path,
- base::ListValue** result,
- bool* property_exists) {
- *property_exists = false;
+Status JwkReader::GetOptionalList(const std::string& member_name,
+ base::ListValue** result,
+ bool* member_exists) const {
+ *member_exists = false;
base::Value* value = NULL;
- if (!dict->Get(path, &value))
+ if (!dict_->Get(member_name, &value))
return Status::Success();
if (!value->GetAsList(result))
- return Status::ErrorJwkPropertyWrongType(path, "list");
+ return Status::ErrorJwkPropertyWrongType(member_name, "list");
- *property_exists = true;
+ *member_exists = true;
return Status::Success();
}
-// Extracts the required string property with key |path| from |dict| and saves
-// the base64url-decoded bytes to |*result|. If the property does not exist or
-// is not a string, or could not be base64url-decoded, returns an error.
-Status GetJwkBytes(base::DictionaryValue* dict,
- const std::string& path,
- std::string* result) {
+Status JwkReader::GetBytes(const std::string& member_name,
+ std::string* result) const {
std::string base64_string;
- Status status = GetJwkString(dict, path, &base64_string);
+ Status status = GetString(member_name, &base64_string);
if (status.IsError())
return status;
if (!Base64DecodeUrlSafe(base64_string, result))
- return Status::ErrorJwkBase64Decode(path);
+ return Status::ErrorJwkBase64Decode(member_name);
return Status::Success();
}
-// Extracts the optional string property with key |path| from |dict| and saves
-// the base64url-decoded bytes to |*result|. If the property exist and is not a
-// string, or could not be base64url-decoded, returns an error. In the case
-// where the property does not exist, |result| is guaranteed to be empty.
-Status GetOptionalJwkBytes(base::DictionaryValue* dict,
- const std::string& path,
- std::string* result,
- bool* property_exists) {
- std::string base64_string;
- Status status =
- GetOptionalJwkString(dict, path, &base64_string, property_exists);
+Status JwkReader::GetBigInteger(const std::string& member_name,
+ std::string* result) const {
+ Status status = GetBytes(member_name, result);
if (status.IsError())
return status;
- if (!*property_exists) {
- result->clear();
- return Status::Success();
- }
+ if (result->empty())
+ return Status::ErrorJwkEmptyBigInteger(member_name);
- if (!Base64DecodeUrlSafe(base64_string, result))
- return Status::ErrorJwkBase64Decode(path);
+ // The JWA spec says that "The octet sequence MUST utilize the minimum number
+ // of octets to represent the value." This means there shouldn't be any
+ // leading zeros.
+ if (result->size() > 1 && (*result)[0] == 0)
+ return Status::ErrorJwkBigIntegerHasLeadingZero(member_name);
return Status::Success();
}
-// Extracts the optional boolean property with key |path| from |dict| and saves
-// the result to |*result| if it was found. If the property exists and is not a
-// boolean, returns an error. Otherwise returns success, and sets
-// |*property_exists| if it was found.
-Status GetOptionalJwkBool(base::DictionaryValue* dict,
- const std::string& path,
- bool* result,
- bool* property_exists) {
- *property_exists = false;
+Status JwkReader::GetOptionalBool(const std::string& member_name,
+ bool* result,
+ bool* member_exists) const {
+ *member_exists = false;
base::Value* value = NULL;
- if (!dict->Get(path, &value))
+ if (!dict_->Get(member_name, &value))
return Status::Success();
if (!value->GetAsBoolean(result))
- return Status::ErrorJwkPropertyWrongType(path, "boolean");
+ return Status::ErrorJwkPropertyWrongType(member_name, "boolean");
- *property_exists = true;
+ *member_exists = true;
return Status::Success();
}
-// Writes a secret/symmetric key to a JWK dictionary.
-void WriteSecretKey(const std::vector<uint8>& raw_key,
- base::DictionaryValue* jwk_dict) {
- DCHECK(jwk_dict);
- jwk_dict->SetString("kty", "oct");
- // For a secret/symmetric key, the only extra JWK field is 'k', containing the
- // base64url encoding of the raw key.
- const base::StringPiece key_str(
- reinterpret_cast<const char*>(Uint8VectorStart(raw_key)), raw_key.size());
- jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str));
+Status JwkReader::GetAlg(std::string* alg, bool* has_alg) const {
+ return GetOptionalString("alg", alg, has_alg);
}
-// Writes an RSA public key to a JWK dictionary
-void WriteRsaPublicKey(const std::vector<uint8>& modulus,
- const std::vector<uint8>& public_exponent,
- base::DictionaryValue* jwk_dict) {
- DCHECK(jwk_dict);
- DCHECK(modulus.size());
- DCHECK(public_exponent.size());
- jwk_dict->SetString("kty", "RSA");
- jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus));
- jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent));
-}
-
-// Writes an RSA private key to a JWK dictionary
-Status ExportRsaPrivateKeyJwk(const blink::WebCryptoKey& key,
- base::DictionaryValue* jwk_dict) {
- platform::PrivateKey* private_key;
- Status status = ToPlatformPrivateKey(key, &private_key);
- if (status.IsError())
- return status;
-
- // TODO(eroman): Copying the key properties to temporary vectors is
- // inefficient. Once there aren't two implementations of platform_crypto this
- // and other code will be easier to streamline.
- std::vector<uint8> modulus;
- std::vector<uint8> public_exponent;
- std::vector<uint8> private_exponent;
- std::vector<uint8> prime1;
- std::vector<uint8> prime2;
- std::vector<uint8> exponent1;
- std::vector<uint8> exponent2;
- std::vector<uint8> coefficient;
-
- status = platform::ExportRsaPrivateKey(private_key,
- &modulus,
- &public_exponent,
- &private_exponent,
- &prime1,
- &prime2,
- &exponent1,
- &exponent2,
- &coefficient);
+Status JwkReader::VerifyAlg(const std::string& expected_alg) const {
+ bool has_jwk_alg;
+ std::string jwk_alg_value;
+ Status status = GetAlg(&jwk_alg_value, &has_jwk_alg);
if (status.IsError())
return status;
- jwk_dict->SetString("kty", "RSA");
- jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus));
- jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent));
- jwk_dict->SetString("d", Base64EncodeUrlSafe(private_exponent));
- // Although these are "optional" in the JWA, WebCrypto spec requires them to
- // be emitted.
- jwk_dict->SetString("p", Base64EncodeUrlSafe(prime1));
- jwk_dict->SetString("q", Base64EncodeUrlSafe(prime2));
- jwk_dict->SetString("dp", Base64EncodeUrlSafe(exponent1));
- jwk_dict->SetString("dq", Base64EncodeUrlSafe(exponent2));
- jwk_dict->SetString("qi", Base64EncodeUrlSafe(coefficient));
+ if (has_jwk_alg && jwk_alg_value != expected_alg)
+ return Status::ErrorJwkAlgorithmInconsistent();
return Status::Success();
}
-// Writes a Web Crypto usage mask to a JWK dictionary.
-void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages,
- base::DictionaryValue* jwk_dict) {
- jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages));
-}
-
-// Writes a Web Crypto extractable value to a JWK dictionary.
-void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) {
- jwk_dict->SetBoolean("ext", extractable);
-}
-
-// Writes a Web Crypto algorithm to a JWK dictionary.
-Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm,
- base::DictionaryValue* jwk_dict) {
- switch (algorithm.paramsType()) {
- case blink::WebCryptoKeyAlgorithmParamsTypeAes: {
- DCHECK(algorithm.aesParams());
- const char* aes_prefix = "";
- switch (algorithm.aesParams()->lengthBits()) {
- case 128:
- aes_prefix = "A128";
- break;
- case 192:
- aes_prefix = "A192";
- break;
- case 256:
- aes_prefix = "A256";
- break;
- default:
- NOTREACHED(); // bad key length means algorithm was built improperly
- return Status::ErrorUnexpected();
- }
- const char* aes_suffix = "";
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- aes_suffix = "CBC";
- break;
- case blink::WebCryptoAlgorithmIdAesCtr:
- aes_suffix = "CTR";
- break;
- case blink::WebCryptoAlgorithmIdAesGcm:
- aes_suffix = "GCM";
- break;
- case blink::WebCryptoAlgorithmIdAesKw:
- aes_suffix = "KW";
- break;
- default:
- return Status::ErrorUnsupported();
- }
- jwk_dict->SetString("alg",
- base::StringPrintf("%s%s", aes_prefix, aes_suffix));
- break;
- }
- case blink::WebCryptoKeyAlgorithmParamsTypeHmac: {
- DCHECK(algorithm.hmacParams());
- switch (algorithm.hmacParams()->hash().id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- jwk_dict->SetString("alg", "HS1");
- break;
- case blink::WebCryptoAlgorithmIdSha256:
- jwk_dict->SetString("alg", "HS256");
- break;
- case blink::WebCryptoAlgorithmIdSha384:
- jwk_dict->SetString("alg", "HS384");
- break;
- case blink::WebCryptoAlgorithmIdSha512:
- jwk_dict->SetString("alg", "HS512");
- break;
- default:
- NOTREACHED();
- return Status::ErrorUnexpected();
- }
- break;
- }
- case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: {
- switch (algorithm.rsaHashedParams()->hash().id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- jwk_dict->SetString("alg", "RS1");
- break;
- case blink::WebCryptoAlgorithmIdSha256:
- jwk_dict->SetString("alg", "RS256");
- break;
- case blink::WebCryptoAlgorithmIdSha384:
- jwk_dict->SetString("alg", "RS384");
- break;
- case blink::WebCryptoAlgorithmIdSha512:
- jwk_dict->SetString("alg", "RS512");
- break;
- default:
- NOTREACHED();
- return Status::ErrorUnexpected();
- }
- break;
- }
- case blink::WebCryptoAlgorithmIdRsaOaep: {
- switch (algorithm.rsaHashedParams()->hash().id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- jwk_dict->SetString("alg", "RSA-OAEP");
- break;
- case blink::WebCryptoAlgorithmIdSha256:
- jwk_dict->SetString("alg", "RSA-OAEP-256");
- break;
- case blink::WebCryptoAlgorithmIdSha384:
- jwk_dict->SetString("alg", "RSA-OAEP-384");
- break;
- case blink::WebCryptoAlgorithmIdSha512:
- jwk_dict->SetString("alg", "RSA-OAEP-512");
- break;
- default:
- NOTREACHED();
- return Status::ErrorUnexpected();
- }
- break;
- }
- default:
- NOTREACHED();
- return Status::ErrorUnexpected();
- }
- break;
- default:
- return Status::ErrorUnsupported();
- }
- return Status::Success();
+JwkWriter::JwkWriter(const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const std::string& kty) {
+ dict_.SetString("alg", algorithm);
+ dict_.Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(usages));
+ dict_.SetBoolean("ext", extractable);
+ dict_.SetString("kty", kty);
}
-bool IsRsaKey(const blink::WebCryptoKey& key) {
- return IsAlgorithmRsa(key.algorithm().id());
+void JwkWriter::SetString(const std::string& member_name,
+ const std::string& value) {
+ dict_.SetString(member_name, value);
}
-Status ImportRsaKey(base::DictionaryValue* dict,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
- // in the JWK, while an RSA private key must have those, plus at least a "d"
- // (private exponent) entry.
- // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
- // section 6.3.
- std::string jwk_n_value;
- Status status = GetJwkBytes(dict, "n", &jwk_n_value);
- if (status.IsError())
- return status;
- std::string jwk_e_value;
- status = GetJwkBytes(dict, "e", &jwk_e_value);
- if (status.IsError())
- return status;
-
- bool is_public_key = !dict->HasKey("d");
+void JwkWriter::SetBytes(const std::string& member_name,
+ const CryptoData& value) {
+ dict_.SetString(
+ member_name,
+ Base64EncodeUrlSafe(base::StringPiece(
+ reinterpret_cast<const char*>(value.bytes()), value.byte_length())));
+}
- // Now that the key type is known, do an additional check on the usages to
- // make sure they are all applicable for this algorithm + key type.
- status = CheckKeyUsages(algorithm.id(),
- is_public_key ? blink::WebCryptoKeyTypePublic
- : blink::WebCryptoKeyTypePrivate,
- usage_mask);
+void JwkWriter::ToJson(std::vector<uint8_t>* utf8_bytes) const {
+ std::string json;
+ base::JSONWriter::Write(&dict_, &json);
+ utf8_bytes->assign(json.begin(), json.end());
+}
+Status ReadSecretKeyNoExpectedAlg(const CryptoData& key_data,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ std::vector<uint8_t>* raw_key_data,
+ JwkReader* jwk) {
+ Status status = jwk->Init(
+ key_data, expected_extractable, expected_usages, "oct", std::string());
if (status.IsError())
return status;
- if (is_public_key) {
- return platform::ImportRsaPublicKey(algorithm,
- extractable,
- usage_mask,
- CryptoData(jwk_n_value),
- CryptoData(jwk_e_value),
- key);
- }
-
- std::string jwk_d_value;
- status = GetJwkBytes(dict, "d", &jwk_d_value);
+ std::string jwk_k_value;
+ status = jwk->GetBytes("k", &jwk_k_value);
if (status.IsError())
return status;
+ raw_key_data->assign(jwk_k_value.begin(), jwk_k_value.end());
- // The "p", "q", "dp", "dq", and "qi" properties are optional. Treat these
- // properties the same if they are unspecified, as if they were specified-but
- // empty, since ImportRsaPrivateKey() doesn't do validation checks anyway.
+ return Status::Success();
+}
- std::string jwk_p_value;
- bool has_p;
- status = GetOptionalJwkBytes(dict, "p", &jwk_p_value, &has_p);
- if (status.IsError())
- return status;
+void WriteSecretKeyJwk(const CryptoData& raw_key_data,
+ const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ std::vector<uint8_t>* jwk_key_data) {
+ JwkWriter writer(algorithm, extractable, usages, "oct");
+ writer.SetBytes("k", raw_key_data);
+ writer.ToJson(jwk_key_data);
+}
- std::string jwk_q_value;
- bool has_q;
- status = GetOptionalJwkBytes(dict, "q", &jwk_q_value, &has_q);
+Status ReadSecretKeyJwk(const CryptoData& key_data,
+ const std::string& expected_alg,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ std::vector<uint8_t>* raw_key_data) {
+ JwkReader jwk;
+ Status status = ReadSecretKeyNoExpectedAlg(
+ key_data, expected_extractable, expected_usages, raw_key_data, &jwk);
if (status.IsError())
return status;
+ return jwk.VerifyAlg(expected_alg);
+}
- std::string jwk_dp_value;
- bool has_dp;
- status = GetOptionalJwkBytes(dict, "dp", &jwk_dp_value, &has_dp);
- if (status.IsError())
- return status;
+std::string MakeJwkAesAlgorithmName(const std::string& suffix,
+ unsigned int keylen_bytes) {
+ if (keylen_bytes == 16)
+ return std::string("A128") + suffix;
+ if (keylen_bytes == 24)
+ return std::string("A192") + suffix;
+ if (keylen_bytes == 32)
+ return std::string("A256") + suffix;
+ return std::string();
+}
- std::string jwk_dq_value;
- bool has_dq;
- status = GetOptionalJwkBytes(dict, "dq", &jwk_dq_value, &has_dq);
+Status ReadAesSecretKeyJwk(const CryptoData& key_data,
+ const std::string& algorithm_name_suffix,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ std::vector<uint8_t>* raw_key_data) {
+ JwkReader jwk;
+ Status status = ReadSecretKeyNoExpectedAlg(
+ key_data, expected_extractable, expected_usages, raw_key_data, &jwk);
if (status.IsError())
return status;
- std::string jwk_qi_value;
- bool has_qi;
- status = GetOptionalJwkBytes(dict, "qi", &jwk_qi_value, &has_qi);
+ bool has_jwk_alg;
+ std::string jwk_alg;
+ status = jwk.GetAlg(&jwk_alg, &has_jwk_alg);
if (status.IsError())
return status;
- int num_optional_properties = has_p + has_q + has_dp + has_dq + has_qi;
- if (num_optional_properties != 0 && num_optional_properties != 5)
- return Status::ErrorJwkIncompleteOptionalRsaPrivateKey();
-
- return platform::ImportRsaPrivateKey(
- algorithm,
- extractable,
- usage_mask,
- CryptoData(jwk_n_value), // modulus
- CryptoData(jwk_e_value), // public_exponent
- CryptoData(jwk_d_value), // private_exponent
- CryptoData(jwk_p_value), // prime1
- CryptoData(jwk_q_value), // prime2
- CryptoData(jwk_dp_value), // exponent1
- CryptoData(jwk_dq_value), // exponent2
- CryptoData(jwk_qi_value), // coefficient
- key);
+ if (has_jwk_alg) {
+ std::string expected_algorithm_name =
+ MakeJwkAesAlgorithmName(algorithm_name_suffix, raw_key_data->size());
+
+ if (jwk_alg != expected_algorithm_name) {
+ // Give a different error message if the key length was wrong.
+ if (jwk_alg == MakeJwkAesAlgorithmName(algorithm_name_suffix, 16) ||
+ jwk_alg == MakeJwkAesAlgorithmName(algorithm_name_suffix, 24) ||
+ jwk_alg == MakeJwkAesAlgorithmName(algorithm_name_suffix, 32)) {
+ return Status::ErrorJwkIncorrectKeyLength();
+ }
+ return Status::ErrorJwkAlgorithmInconsistent();
+ }
+ }
+
+ return Status::Success();
}
-} // namespace
+// Writes an RSA public key to a JWK dictionary
+void WriteRsaPublicKeyJwk(const CryptoData& n,
+ const CryptoData& e,
+ const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ std::vector<uint8_t>* jwk_key_data) {
+ JwkWriter writer(algorithm, extractable, usages, "RSA");
+ writer.SetBytes("n", n);
+ writer.SetBytes("e", e);
+ writer.ToJson(jwk_key_data);
+}
-// TODO(eroman): Split this up into smaller functions.
-Status ImportKeyJwk(const CryptoData& key_data,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- if (!key_data.byte_length())
- return Status::ErrorImportEmptyKeyData();
- DCHECK(key);
+// Writes an RSA private key to a JWK dictionary
+void WriteRsaPrivateKeyJwk(const CryptoData& n,
+ const CryptoData& e,
+ const CryptoData& d,
+ const CryptoData& p,
+ const CryptoData& q,
+ const CryptoData& dp,
+ const CryptoData& dq,
+ const CryptoData& qi,
+ const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ std::vector<uint8_t>* jwk_key_data) {
+ JwkWriter writer(algorithm, extractable, usages, "RSA");
+
+ writer.SetBytes("n", n);
+ writer.SetBytes("e", e);
+ writer.SetBytes("d", d);
+ // Although these are "optional" in the JWA, WebCrypto spec requires them to
+ // be emitted.
+ writer.SetBytes("p", p);
+ writer.SetBytes("q", q);
+ writer.SetBytes("dp", dp);
+ writer.SetBytes("dq", dq);
+ writer.SetBytes("qi", qi);
+ writer.ToJson(jwk_key_data);
+}
- // Parse the incoming JWK JSON.
- base::StringPiece json_string(reinterpret_cast<const char*>(key_data.bytes()),
- key_data.byte_length());
- scoped_ptr<base::Value> value(base::JSONReader::Read(json_string));
- // Note, bare pointer dict_value is ok since it points into scoped value.
- base::DictionaryValue* dict_value = NULL;
- if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value)
- return Status::ErrorJwkNotDictionary();
+JwkRsaInfo::JwkRsaInfo() : is_private_key(false) {
+}
- // JWK "kty". Exit early if this required JWK parameter is missing.
- std::string jwk_kty_value;
- Status status = GetJwkString(dict_value, "kty", &jwk_kty_value);
+JwkRsaInfo::~JwkRsaInfo() {
+}
+
+Status ReadRsaKeyJwk(const CryptoData& key_data,
+ const std::string& expected_alg,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ JwkRsaInfo* result) {
+ JwkReader jwk;
+ Status status = jwk.Init(
+ key_data, expected_extractable, expected_usages, "RSA", expected_alg);
if (status.IsError())
return status;
- // JWK "ext" (optional) --> extractable parameter
- {
- bool jwk_ext_value = false;
- bool has_jwk_ext;
- status =
- GetOptionalJwkBool(dict_value, "ext", &jwk_ext_value, &has_jwk_ext);
- if (status.IsError())
- return status;
- if (has_jwk_ext && !jwk_ext_value && extractable)
- return Status::ErrorJwkExtInconsistent();
- }
-
- // JWK "alg" --> algorithm parameter
- // 1. JWK alg present but unrecognized: error
- // 2. JWK alg valid and inconsistent with input algorithm: error
- // 3. JWK alg valid and consistent with input algorithm: use input value
- // 4. JWK alg is missing: use input value
- const JwkAlgorithmInfo* algorithm_info = NULL;
- std::string jwk_alg_value;
- bool has_jwk_alg;
- status =
- GetOptionalJwkString(dict_value, "alg", &jwk_alg_value, &has_jwk_alg);
+ // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
+ // in the JWK, while an RSA private key must have those, plus at least a "d"
+ // (private exponent) entry.
+ // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
+ // section 6.3.
+ status = jwk.GetBigInteger("n", &result->n);
+ if (status.IsError())
+ return status;
+ status = jwk.GetBigInteger("e", &result->e);
if (status.IsError())
return status;
- if (has_jwk_alg) {
- // JWK alg present
-
- // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can
- // only be from the RSA family.
+ result->is_private_key = jwk.HasMember("d");
+ if (!result->is_private_key)
+ return Status::Success();
- blink::WebCryptoAlgorithm jwk_algorithm =
- blink::WebCryptoAlgorithm::createNull();
- algorithm_info = jwk_alg_registry.Get().GetAlgorithmInfo(jwk_alg_value);
- if (!algorithm_info ||
- !algorithm_info->CreateImportAlgorithm(&jwk_algorithm))
- return Status::ErrorJwkUnrecognizedAlgorithm();
+ status = jwk.GetBigInteger("d", &result->d);
+ if (status.IsError())
+ return status;
- if (!ImportAlgorithmsConsistent(jwk_algorithm, algorithm))
- return Status::ErrorJwkAlgorithmInconsistent();
- }
- DCHECK(!algorithm.isNull());
+ // The "p", "q", "dp", "dq", and "qi" properties are optional in the JWA
+ // spec. However they are required by Chromium's WebCrypto implementation.
- // JWK "key_ops" (optional) --> usage_mask parameter
- base::ListValue* jwk_key_ops_value = NULL;
- bool has_jwk_key_ops;
- status = GetOptionalJwkList(
- dict_value, "key_ops", &jwk_key_ops_value, &has_jwk_key_ops);
+ status = jwk.GetBigInteger("p", &result->p);
if (status.IsError())
return status;
- blink::WebCryptoKeyUsageMask jwk_key_ops_mask = 0;
- if (has_jwk_key_ops) {
- status =
- GetWebCryptoUsagesFromJwkKeyOps(jwk_key_ops_value, &jwk_key_ops_mask);
- if (status.IsError())
- return status;
- // The input usage_mask must be a subset of jwk_key_ops_mask.
- if (!ContainsKeyUsages(jwk_key_ops_mask, usage_mask))
- return Status::ErrorJwkKeyopsInconsistent();
- }
- // JWK "use" (optional) --> usage_mask parameter
- std::string jwk_use_value;
- bool has_jwk_use;
- status =
- GetOptionalJwkString(dict_value, "use", &jwk_use_value, &has_jwk_use);
+ status = jwk.GetBigInteger("q", &result->q);
if (status.IsError())
return status;
- blink::WebCryptoKeyUsageMask jwk_use_mask = 0;
- if (has_jwk_use) {
- if (jwk_use_value == "enc")
- jwk_use_mask = kJwkEncUsage;
- else if (jwk_use_value == "sig")
- jwk_use_mask = kJwkSigUsage;
- else
- return Status::ErrorJwkUnrecognizedUse();
- // The input usage_mask must be a subset of jwk_use_mask.
- if (!ContainsKeyUsages(jwk_use_mask, usage_mask))
- return Status::ErrorJwkUseInconsistent();
- }
- // If both 'key_ops' and 'use' are present, ensure they are consistent.
- if (has_jwk_key_ops && has_jwk_use &&
- !ContainsKeyUsages(jwk_use_mask, jwk_key_ops_mask))
- return Status::ErrorJwkUseAndKeyopsInconsistent();
-
- // JWK keying material --> ImportKeyInternal()
- if (jwk_kty_value == "oct") {
- std::string jwk_k_value;
- status = GetJwkBytes(dict_value, "k", &jwk_k_value);
- if (status.IsError())
- return status;
-
- // Some JWK alg ID's embed information about the key length in the alg ID
- // string. For example "A128CBC" implies the JWK carries 128 bits
- // of key material. For such keys validate that enough bytes were provided.
- // If this validation is not done, then it would be possible to select a
- // different algorithm by passing a different lengthed key, since that is
- // how WebCrypto interprets things.
- if (algorithm_info &&
- algorithm_info->IsInvalidKeyByteLength(jwk_k_value.size())) {
- return Status::ErrorJwkIncorrectKeyLength();
- }
+ status = jwk.GetBigInteger("dp", &result->dp);
+ if (status.IsError())
+ return status;
- return ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(jwk_k_value),
- algorithm,
- extractable,
- usage_mask,
- key);
- }
+ status = jwk.GetBigInteger("dq", &result->dq);
+ if (status.IsError())
+ return status;
- if (jwk_kty_value == "RSA")
- return ImportRsaKey(dict_value, algorithm, extractable, usage_mask, key);
+ status = jwk.GetBigInteger("qi", &result->qi);
+ if (status.IsError())
+ return status;
- return Status::ErrorJwkUnrecognizedKty();
+ return Status::Success();
}
-Status ExportKeyJwk(const blink::WebCryptoKey& key,
- std::vector<uint8>* buffer) {
- DCHECK(key.extractable());
- base::DictionaryValue jwk_dict;
- Status status = Status::OperationError();
-
- switch (key.type()) {
- case blink::WebCryptoKeyTypeSecret: {
- std::vector<uint8> exported_key;
- status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key);
- if (status.IsError())
- return status;
- WriteSecretKey(exported_key, &jwk_dict);
- break;
- }
- case blink::WebCryptoKeyTypePublic: {
- // TODO(eroman): Update when there are asymmetric keys other than RSA.
- if (!IsRsaKey(key))
- return Status::ErrorUnsupported();
- platform::PublicKey* public_key;
- status = ToPlatformPublicKey(key, &public_key);
- if (status.IsError())
- return status;
- std::vector<uint8> modulus;
- std::vector<uint8> public_exponent;
- status =
- platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent);
- if (status.IsError())
- return status;
- WriteRsaPublicKey(modulus, public_exponent, &jwk_dict);
- break;
- }
- case blink::WebCryptoKeyTypePrivate: {
- // TODO(eroman): Update when there are asymmetric keys other than RSA.
- if (!IsRsaKey(key))
- return Status::ErrorUnsupported();
-
- status = ExportRsaPrivateKeyJwk(key, &jwk_dict);
- if (status.IsError())
- return status;
- break;
- }
-
+const char* GetJwkHmacAlgorithmName(blink::WebCryptoAlgorithmId hash) {
+ switch (hash) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return "HS1";
+ case blink::WebCryptoAlgorithmIdSha256:
+ return "HS256";
+ case blink::WebCryptoAlgorithmIdSha384:
+ return "HS384";
+ case blink::WebCryptoAlgorithmIdSha512:
+ return "HS512";
default:
- return Status::ErrorUnsupported();
+ return NULL;
}
+}
- WriteKeyOps(key.usages(), &jwk_dict);
- WriteExt(key.extractable(), &jwk_dict);
- status = WriteAlg(key.algorithm(), &jwk_dict);
- if (status.IsError())
- return status;
+// TODO(eroman): This accepts invalid inputs. http://crbug.com/378034
+bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
+ std::string base64_encoded_text(input);
+ std::replace(
+ base64_encoded_text.begin(), base64_encoded_text.end(), '-', '+');
+ std::replace(
+ base64_encoded_text.begin(), base64_encoded_text.end(), '_', '/');
+ base64_encoded_text.append((4 - base64_encoded_text.size() % 4) % 4, '=');
+ return base::Base64Decode(base64_encoded_text, output);
+}
- std::string json;
- base::JSONWriter::Write(&jwk_dict, &json);
- buffer->assign(json.data(), json.data() + json.size());
- return Status::Success();
+std::string Base64EncodeUrlSafe(const base::StringPiece& input) {
+ std::string output;
+ base::Base64Encode(input, &output);
+ std::replace(output.begin(), output.end(), '+', '-');
+ std::replace(output.begin(), output.end(), '/', '_');
+ output.erase(std::remove(output.begin(), output.end(), '='), output.end());
+ return output;
+}
+
+std::string Base64EncodeUrlSafe(const std::vector<uint8_t>& input) {
+ const base::StringPiece string_piece(
+ reinterpret_cast<const char*>(vector_as_array(&input)), input.size());
+ return Base64EncodeUrlSafe(string_piece);
}
} // namespace webcrypto
diff --git a/chromium/content/child/webcrypto/jwk.h b/chromium/content/child/webcrypto/jwk.h
index c9191888256..cb6866df178 100644
--- a/chromium/content/child/webcrypto/jwk.h
+++ b/chromium/content/child/webcrypto/jwk.h
@@ -5,12 +5,13 @@
#ifndef CONTENT_CHILD_WEBCRYPTO_JWK_H_
#define CONTENT_CHILD_WEBCRYPTO_JWK_H_
+#include <stdint.h>
#include <vector>
-#include "base/basictypes.h"
-#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "base/strings/string_piece.h"
+#include "base/values.h"
+#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebCrypto.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
namespace content {
@@ -19,13 +20,223 @@ namespace webcrypto {
class CryptoData;
class Status;
-Status ImportKeyJwk(const CryptoData& key_data,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
+// Helper class for parsing a JWK from JSON.
+//
+// This primarily exists to ensure strict enforcement of the JWK schema, as the
+// type and presence of particular members is security relevant. For example,
+// GetString() will ensure a given JSON member is present and is a string type,
+// and will fail if these conditions aren't met.
+//
+// Users of JwkReader must call Init() successfully before any other method can
+// be called.
+class JwkReader {
+ public:
+ JwkReader();
+ ~JwkReader();
-Status ExportKeyJwk(const blink::WebCryptoKey& key, std::vector<uint8>* buffer);
+ // Initializes a JWK reader by parsing the JSON |bytes|. To succeed, the JWK
+ // must:
+ // * Have "kty" matching |expected_kty|
+ // * Have "ext" compatible with |expected_extractable|
+ // * Have usages ("use", "key_ops") compatible with |expected_usages|
+ // * Have an "alg" matching |expected_alg|
+ //
+ // NOTE: If |expected_alg| is empty, then the test on "alg" is skipped.
+ Status Init(const CryptoData& bytes,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ const std::string& expected_kty,
+ const std::string& expected_alg);
+
+ // Returns true if the member |member_name| is present.
+ bool HasMember(const std::string& member_name) const;
+
+ // Extracts the required string member |member_name| and saves the result to
+ // |*result|. If the member does not exist or is not a string, returns an
+ // error.
+ Status GetString(const std::string& member_name, std::string* result) const;
+
+ // Extracts the optional string member |member_name| and saves the result to
+ // |*result| if it was found. If the member exists and is not a string,
+ // returns an error. Otherwise returns success, and sets |*member_exists| if
+ // it was found.
+ Status GetOptionalString(const std::string& member_name,
+ std::string* result,
+ bool* member_exists) const;
+
+ // Extracts the optional array member |member_name| and saves the result to
+ // |*result| if it was found. If the member exists and is not an array,
+ // returns an error. Otherwise returns success, and sets |*member_exists| if
+ // it was found.
+ //
+ // NOTE: |*result| is owned by the JwkReader.
+ Status GetOptionalList(const std::string& member_name,
+ base::ListValue** result,
+ bool* member_exists) const;
+
+ // Extracts the required string member |member_name| and saves the
+ // base64url-decoded bytes to |*result|. If the member does not exist or is
+ // not a string, or could not be base64url-decoded, returns an error.
+ Status GetBytes(const std::string& member_name, std::string* result) const;
+
+ // Extracts the required base64url member, which is interpreted as being a
+ // big-endian unsigned integer.
+ //
+ // Sequences that contain leading zeros will be rejected.
+ Status GetBigInteger(const std::string& member_name,
+ std::string* result) const;
+
+ // Extracts the optional boolean member |member_name| and saves the result to
+ // |*result| if it was found. If the member exists and is not a boolean,
+ // returns an error. Otherwise returns success, and sets |*member_exists| if
+ // it was found.
+ Status GetOptionalBool(const std::string& member_name,
+ bool* result,
+ bool* member_exists) const;
+
+ // Gets the optional algorithm ("alg") string.
+ Status GetAlg(std::string* alg, bool* has_alg) const;
+
+ // Checks if the "alg" member matches |expected_alg|.
+ Status VerifyAlg(const std::string& expected_alg) const;
+
+ private:
+ scoped_ptr<base::DictionaryValue> dict_;
+};
+
+// Helper class for building the JSON for a JWK.
+class JwkWriter {
+ public:
+ // Initializes a writer, and sets the standard JWK members as indicated.
+ JwkWriter(const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const std::string& kty);
+
+ // Sets a string member |member_name| to |value|.
+ void SetString(const std::string& member_name, const std::string& value);
+
+ // Sets a bytes member |value| to |value| by base64 url-safe encoding it.
+ void SetBytes(const std::string& member_name, const CryptoData& value);
+
+ // Flattens the JWK to JSON (UTF-8 encoded if necessary, however in practice
+ // it will be ASCII).
+ void ToJson(std::vector<uint8_t>* utf8_bytes) const;
+
+ private:
+ base::DictionaryValue dict_;
+};
+
+// Writes a JWK-formatted symmetric key to |jwk_key_data|.
+// * raw_key_data: The actual key data
+// * algorithm: The JWK algorithm name (i.e. "alg")
+// * extractable: The JWK extractability (i.e. "ext")
+// * usages: The JWK usages (i.e. "key_ops")
+void WriteSecretKeyJwk(const CryptoData& raw_key_data,
+ const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ std::vector<uint8_t>* jwk_key_data);
+
+// Parses a UTF-8 encoded JWK (key_data), and extracts the key material to
+// |*raw_key_data|. Returns Status::Success() on success, otherwise an error.
+// In order for this to succeed:
+// * expected_alg must match the JWK's "alg", if present.
+// * expected_extractable must be consistent with the JWK's "ext", if
+// present.
+// * expected_usages must be a subset of the JWK's "key_ops" if present.
+Status ReadSecretKeyJwk(const CryptoData& key_data,
+ const std::string& expected_alg,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ std::vector<uint8_t>* raw_key_data);
+
+// Creates an AES algorithm name for the given key size (in bytes). For
+// instance "A128CBC" is the result of suffix="CBC", keylen_bytes=16.
+std::string MakeJwkAesAlgorithmName(const std::string& suffix,
+ unsigned int keylen_bytes);
+
+// This is very similar to ReadSecretKeyJwk(), except instead of specifying an
+// absolute "expected_alg", the suffix for an AES algorithm name is given
+// (See MakeJwkAesAlgorithmName() for an explanation of what the suffix is).
+//
+// This is because the algorithm name for AES keys is dependent on the length
+// of the key. This function expects key lengths to be either 128, 192, or 256
+// bits.
+Status ReadAesSecretKeyJwk(const CryptoData& key_data,
+ const std::string& algorithm_name_suffix,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ std::vector<uint8_t>* raw_key_data);
+
+// Writes a JWK-formated RSA public key and saves the result to
+// |*jwk_key_data|.
+void WriteRsaPublicKeyJwk(const CryptoData& n,
+ const CryptoData& e,
+ const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ std::vector<uint8_t>* jwk_key_data);
+
+// Writes a JWK-formated RSA private key and saves the result to
+// |*jwk_key_data|.
+void WriteRsaPrivateKeyJwk(const CryptoData& n,
+ const CryptoData& e,
+ const CryptoData& d,
+ const CryptoData& p,
+ const CryptoData& q,
+ const CryptoData& dp,
+ const CryptoData& dq,
+ const CryptoData& qi,
+ const std::string& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ std::vector<uint8_t>* jwk_key_data);
+
+// Describes the RSA components for a parsed key. The names of the properties
+// correspond with those from the JWK spec. Note that Chromium's WebCrypto
+// implementation does not support multi-primes, so there is no parsed field
+// for othinfo.
+struct JwkRsaInfo {
+ JwkRsaInfo();
+ ~JwkRsaInfo();
+
+ bool is_private_key;
+ std::string n;
+ std::string e;
+ std::string d;
+ std::string p;
+ std::string q;
+ std::string dp;
+ std::string dq;
+ std::string qi;
+};
+
+// Parses a UTF-8 encoded JWK (key_data), and extracts the RSA components to
+// |*result|. Returns Status::Success() on success, otherwise an error.
+// In order for this to succeed:
+// * expected_alg must match the JWK's "alg", if present.
+// * expected_extractable must be consistent with the JWK's "ext", if
+// present.
+// * expected_usages must be a subset of the JWK's "key_ops" if present.
+Status ReadRsaKeyJwk(const CryptoData& key_data,
+ const std::string& expected_alg,
+ bool expected_extractable,
+ blink::WebCryptoKeyUsageMask expected_usages,
+ JwkRsaInfo* result);
+
+const char* GetJwkHmacAlgorithmName(blink::WebCryptoAlgorithmId hash);
+
+// This function decodes unpadded 'base64url' encoded data, as described in
+// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5.
+CONTENT_EXPORT bool Base64DecodeUrlSafe(const std::string& input,
+ std::string* output);
+
+// Returns an unpadded 'base64url' encoding of the input data, the opposite of
+// Base64DecodeUrlSafe() above.
+CONTENT_EXPORT std::string Base64EncodeUrlSafe(const base::StringPiece& input);
+CONTENT_EXPORT std::string Base64EncodeUrlSafe(
+ const std::vector<uint8_t>& input);
} // namespace webcrypto
diff --git a/chromium/content/child/webcrypto/nss/aes_cbc_nss.cc b/chromium/content/child/webcrypto/nss/aes_cbc_nss.cc
new file mode 100644
index 00000000000..abe371802b2
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/aes_cbc_nss.cc
@@ -0,0 +1,128 @@
+// Copyright 2014 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 <cryptohi.h>
+
+#include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/nss/aes_key_nss.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
+ if (!params)
+ return Status::ErrorUnexpected();
+
+ CryptoData iv(params->iv().data(), params->iv().size());
+ if (iv.byte_length() != 16)
+ return Status::ErrorIncorrectSizeAesCbcIv();
+
+ PK11SymKey* sym_key = SymKeyNss::Cast(key)->key();
+
+ CK_ATTRIBUTE_TYPE operation = (mode == ENCRYPT) ? CKA_ENCRYPT : CKA_DECRYPT;
+
+ SECItem iv_item = MakeSECItemForBuffer(iv);
+
+ crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
+ if (!param)
+ return Status::OperationError();
+
+ crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
+ CKM_AES_CBC_PAD, operation, sym_key, param.get()));
+
+ if (!context.get())
+ return Status::OperationError();
+
+ // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
+ // "unsigned int". Do some checks now to avoid integer overflowing.
+ base::CheckedNumeric<int> output_max_len = data.byte_length();
+ output_max_len += AES_BLOCK_SIZE;
+ if (!output_max_len.IsValid()) {
+ // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
+ // it doesn't make much difference since the one-shot API would end up
+ // blowing out the memory and crashing anyway.
+ return Status::ErrorDataTooLarge();
+ }
+
+ // PK11_CipherOp does an invalid memory access when given empty decryption
+ // input, or input which is not a multiple of the block size. See also
+ // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
+ if (operation == CKA_DECRYPT &&
+ (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) {
+ return Status::OperationError();
+ }
+
+ // TODO(eroman): Refine the output buffer size. It can be computed exactly for
+ // encryption, and can be smaller for decryption.
+ buffer->resize(output_max_len.ValueOrDie());
+
+ unsigned char* buffer_data = vector_as_array(buffer);
+
+ int output_len;
+ if (SECSuccess != PK11_CipherOp(context.get(),
+ buffer_data,
+ &output_len,
+ buffer->size(),
+ data.bytes(),
+ data.byte_length())) {
+ return Status::OperationError();
+ }
+
+ unsigned int final_output_chunk_len;
+ if (SECSuccess !=
+ PK11_DigestFinal(context.get(),
+ buffer_data + output_len,
+ &final_output_chunk_len,
+ (output_max_len - output_len).ValueOrDie())) {
+ return Status::OperationError();
+ }
+
+ buffer->resize(final_output_chunk_len + output_len);
+ return Status::Success();
+}
+
+class AesCbcImplementation : public AesAlgorithm {
+ public:
+ AesCbcImplementation() : AesAlgorithm(CKM_AES_CBC, "CBC") {}
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesCbcEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesCbcEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesCbcImplementation() {
+ return new AesCbcImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/aes_gcm_nss.cc b/chromium/content/child/webcrypto/nss/aes_gcm_nss.cc
new file mode 100644
index 00000000000..242fdfd48c4
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/aes_gcm_nss.cc
@@ -0,0 +1,191 @@
+// Copyright 2014 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/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/nss/aes_key_nss.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+// At the time of this writing:
+// * Windows and Mac builds ship with their own copy of NSS (3.15+)
+// * Linux builds use the system's libnss, which is 3.14 on Debian (but 3.15+
+// on other distros).
+//
+// Since NSS provides AES-GCM support starting in version 3.15, it may be
+// unavailable for Linux Chrome users.
+//
+// * !defined(CKM_AES_GCM)
+//
+// This means that at build time, the NSS header pkcs11t.h is older than
+// 3.15. However at runtime support may be present.
+//
+// TODO(eroman): Simplify this once 3.15+ is required by Linux builds.
+#if !defined(CKM_AES_GCM)
+#define CKM_AES_GCM 0x00001087
+
+struct CK_GCM_PARAMS {
+ CK_BYTE_PTR pIv;
+ CK_ULONG ulIvLen;
+ CK_BYTE_PTR pAAD;
+ CK_ULONG ulAADLen;
+ CK_ULONG ulTagBits;
+};
+#endif // !defined(CKM_AES_GCM)
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+Status NssSupportsAesGcm() {
+ if (NssRuntimeSupport::Get()->IsAesGcmSupported())
+ return Status::Success();
+ return Status::ErrorUnsupported(
+ "NSS version doesn't support AES-GCM. Try using version 3.15 or later");
+}
+
+// Helper to either encrypt or decrypt for AES-GCM. The result of encryption is
+// the concatenation of the ciphertext and the authentication tag. Similarly,
+// this is the expectation for the input to decryption.
+Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ Status status = NssSupportsAesGcm();
+ if (status.IsError())
+ return status;
+
+ PK11SymKey* sym_key = SymKeyNss::Cast(key)->key();
+ const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
+ if (!params)
+ return Status::ErrorUnexpected();
+
+ unsigned int tag_length_bits;
+ status = GetAesGcmTagLengthInBits(params, &tag_length_bits);
+ if (status.IsError())
+ return status;
+ unsigned int tag_length_bytes = tag_length_bits / 8;
+
+ CryptoData iv(params->iv());
+ CryptoData additional_data(params->optionalAdditionalData());
+
+ CK_GCM_PARAMS gcm_params = {0};
+ gcm_params.pIv = const_cast<unsigned char*>(iv.bytes());
+ gcm_params.ulIvLen = iv.byte_length();
+
+ gcm_params.pAAD = const_cast<unsigned char*>(additional_data.bytes());
+ gcm_params.ulAADLen = additional_data.byte_length();
+
+ gcm_params.ulTagBits = tag_length_bits;
+
+ SECItem param;
+ param.type = siBuffer;
+ param.data = reinterpret_cast<unsigned char*>(&gcm_params);
+ param.len = sizeof(gcm_params);
+
+ base::CheckedNumeric<unsigned int> buffer_size(data.byte_length());
+
+ // Calculate the output buffer size.
+ if (mode == ENCRYPT) {
+ buffer_size += tag_length_bytes;
+ if (!buffer_size.IsValid())
+ return Status::ErrorDataTooLarge();
+ }
+
+ // TODO(eroman): In theory the buffer allocated for the plain text should be
+ // sized as |data.byte_length() - tag_length_bytes|.
+ //
+ // However NSS has a bug whereby it will fail if the output buffer size is
+ // not at least as large as the ciphertext:
+ //
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674
+ //
+ // From the analysis of that bug it looks like it might be safe to pass a
+ // correctly sized buffer but lie about its size. Since resizing the
+ // WebCryptoArrayBuffer is expensive that hack may be worth looking into.
+
+ buffer->resize(buffer_size.ValueOrDie());
+ unsigned char* buffer_data = vector_as_array(buffer);
+
+ PK11_EncryptDecryptFunction encrypt_or_decrypt_func =
+ (mode == ENCRYPT) ? NssRuntimeSupport::Get()->pk11_encrypt_func()
+ : NssRuntimeSupport::Get()->pk11_decrypt_func();
+
+ unsigned int output_len = 0;
+ SECStatus result = encrypt_or_decrypt_func(sym_key,
+ CKM_AES_GCM,
+ &param,
+ buffer_data,
+ &output_len,
+ buffer->size(),
+ data.bytes(),
+ data.byte_length());
+
+ if (result != SECSuccess)
+ return Status::OperationError();
+
+ // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug
+ // above).
+ buffer->resize(output_len);
+
+ return Status::Success();
+}
+
+class AesGcmImplementation : public AesAlgorithm {
+ public:
+ AesGcmImplementation() : AesAlgorithm(CKM_AES_GCM, "GCM") {}
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override {
+ // Prevent importing AES-GCM keys if it is unavailable.
+ Status status = NssSupportsAesGcm();
+ if (status.IsError())
+ return status;
+ return AesAlgorithm::VerifyKeyUsagesBeforeImportKey(format, usages);
+ }
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override {
+ // Prevent generating AES-GCM keys if it is unavailable.
+ Status status = NssSupportsAesGcm();
+ if (status.IsError())
+ return status;
+
+ return AesAlgorithm::GenerateKey(algorithm, extractable, usages, result);
+ }
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesGcmEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesGcmEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesGcmImplementation() {
+ return new AesGcmImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/aes_key_nss.cc b/chromium/content/child/webcrypto/nss/aes_key_nss.cc
new file mode 100644
index 00000000000..2bd0c57e396
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/aes_key_nss.cc
@@ -0,0 +1,134 @@
+// Copyright 2014 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 "content/child/webcrypto/nss/aes_key_nss.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/sym_key_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+AesAlgorithm::AesAlgorithm(CK_MECHANISM_TYPE import_mechanism,
+ CK_FLAGS import_flags,
+ blink::WebCryptoKeyUsageMask all_key_usages,
+ const std::string& jwk_suffix)
+ : import_mechanism_(import_mechanism),
+ import_flags_(import_flags),
+ all_key_usages_(all_key_usages),
+ jwk_suffix_(jwk_suffix) {
+}
+
+AesAlgorithm::AesAlgorithm(CK_MECHANISM_TYPE import_mechanism,
+ const std::string& jwk_suffix)
+ : import_mechanism_(import_mechanism),
+ import_flags_(CKF_ENCRYPT | CKF_DECRYPT),
+ all_key_usages_(blink::WebCryptoKeyUsageEncrypt |
+ blink::WebCryptoKeyUsageDecrypt |
+ blink::WebCryptoKeyUsageWrapKey |
+ blink::WebCryptoKeyUsageUnwrapKey),
+ jwk_suffix_(jwk_suffix) {
+}
+
+Status AesAlgorithm::GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const {
+ Status status = CheckKeyCreationUsages(all_key_usages_, usages);
+ if (status.IsError())
+ return status;
+
+ unsigned int keylen_bits;
+ status = GetAesKeyGenLengthInBits(algorithm.aesKeyGenParams(), &keylen_bits);
+ if (status.IsError())
+ return status;
+
+ return GenerateSecretKeyNss(
+ blink::WebCryptoKeyAlgorithm::createAes(algorithm.id(), keylen_bits),
+ extractable,
+ usages,
+ keylen_bits / 8,
+ CKM_AES_KEY_GEN,
+ result);
+}
+
+Status AesAlgorithm::VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ case blink::WebCryptoKeyFormatJwk:
+ return CheckKeyCreationUsages(all_key_usages_, usages);
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+}
+Status AesAlgorithm::ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ const unsigned int keylen_bytes = key_data.byte_length();
+ Status status = VerifyAesKeyLengthForImport(keylen_bytes);
+ if (status.IsError())
+ return status;
+
+ // No possibility of overflow.
+ unsigned int keylen_bits = keylen_bytes * 8;
+
+ return ImportKeyRawNss(
+ key_data,
+ blink::WebCryptoKeyAlgorithm::createAes(algorithm.id(), keylen_bits),
+ extractable,
+ usages,
+ import_mechanism_,
+ import_flags_,
+ key);
+}
+
+Status AesAlgorithm::ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ std::vector<uint8_t> raw_data;
+ Status status = ReadAesSecretKeyJwk(
+ key_data, jwk_suffix_, extractable, usages, &raw_data);
+ if (status.IsError())
+ return status;
+
+ return ImportKeyRaw(
+ CryptoData(raw_data), algorithm, extractable, usages, key);
+}
+
+Status AesAlgorithm::ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ *buffer = SymKeyNss::Cast(key)->raw_key_data();
+ return Status::Success();
+}
+
+Status AesAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ SymKeyNss* sym_key = SymKeyNss::Cast(key);
+ const std::vector<uint8_t>& raw_data = sym_key->raw_key_data();
+
+ WriteSecretKeyJwk(CryptoData(raw_data),
+ MakeJwkAesAlgorithmName(jwk_suffix_, raw_data.size()),
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/aes_key_nss.h b/chromium/content/child/webcrypto/nss/aes_key_nss.h
new file mode 100644
index 00000000000..5e4cba35e42
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/aes_key_nss.h
@@ -0,0 +1,77 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_NSS_AES_NSS_H_
+#define CONTENT_CHILD_WEBCRYPTO_NSS_AES_NSS_H_
+
+#include <pkcs11t.h>
+
+#include "content/child/webcrypto/algorithm_implementation.h"
+
+namespace content {
+
+namespace webcrypto {
+
+// Base class for AES algorithms that provides the implementation for key
+// creation and export.
+class AesAlgorithm : public AlgorithmImplementation {
+ public:
+ // Constructs an AES algorithm whose keys will be imported using the NSS
+ // mechanism |import_mechanism| and NSS flags |import_flags|.
+ // |all_key_usages| is the set of all WebCrypto key usages that are
+ // allowed for imported or generated keys. |jwk_suffix| is the suffix
+ // used when constructing JWK names for the algorithm. For instance A128CBC
+ // is the JWK name for 128-bit AES-CBC. The |jwk_suffix| in this case would
+ // be "CBC".
+ AesAlgorithm(CK_MECHANISM_TYPE import_mechanism,
+ CK_FLAGS import_flags,
+ blink::WebCryptoKeyUsageMask all_key_usages,
+ const std::string& jwk_suffix);
+
+ // This is the same as the other AesAlgorithm constructor, however
+ // |import_flags| and |all_key_usages| are pre-filled to values for
+ // encryption/decryption algorithms (supports usages for: encrypt, decrypt,
+ // wrap, unwrap).
+ AesAlgorithm(CK_MECHANISM_TYPE import_mechanism,
+ const std::string& jwk_suffix);
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override;
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override;
+
+ Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ private:
+ const CK_MECHANISM_TYPE import_mechanism_;
+ const CK_FLAGS import_flags_;
+ const blink::WebCryptoKeyUsageMask all_key_usages_;
+ const std::string jwk_suffix_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_NSS_AES_NSS_H_
diff --git a/chromium/content/child/webcrypto/nss/aes_kw_nss.cc b/chromium/content/child/webcrypto/nss/aes_kw_nss.cc
new file mode 100644
index 00000000000..76d3337d51b
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/aes_kw_nss.cc
@@ -0,0 +1,206 @@
+// Copyright 2014 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 <secerr.h>
+
+#include "base/numerics/safe_math.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/nss/aes_key_nss.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/sym_key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// The Default IV for AES-KW. See http://www.ietf.org/rfc/rfc3394.txt
+// Section 2.2.3.1.
+const unsigned char kAesIv[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
+
+// The result of unwrapping is a SymKey rather than a buffer. This is a
+// consequence of how NSS exposes AES-KW. Subsequent code can extract the value
+// of the sym key to interpret it as key bytes in another format.
+Status DoUnwrapSymKeyAesKw(const CryptoData& wrapped_key_data,
+ PK11SymKey* wrapping_key,
+ CK_MECHANISM_TYPE mechanism,
+ CK_FLAGS flags,
+ crypto::ScopedPK11SymKey* unwrapped_key) {
+ DCHECK_GE(wrapped_key_data.byte_length(), 24u);
+ DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u);
+
+ SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
+ crypto::ScopedSECItem param_item(
+ PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
+ if (!param_item)
+ return Status::ErrorUnexpected();
+
+ SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data);
+
+ // The plaintext length is always 64 bits less than the data size.
+ const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8;
+
+#if defined(USE_NSS)
+ // Part of workaround for
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=981170. See the explanation
+ // later in this function.
+ PORT_SetError(0);
+#endif
+
+ crypto::ScopedPK11SymKey new_key(
+ PK11_UnwrapSymKeyWithFlags(wrapping_key,
+ CKM_NSS_AES_KEY_WRAP,
+ param_item.get(),
+ &cipher_text,
+ mechanism,
+ CKA_FLAGS_ONLY,
+ plaintext_length,
+ flags));
+
+ // TODO(padolph): Use NSS PORT_GetError() and friends to report a more
+ // accurate error, providing if doesn't leak any information to web pages
+ // about other web crypto users, key details, etc.
+ if (!new_key)
+ return Status::OperationError();
+
+#if defined(USE_NSS)
+ // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=981170
+ // which was fixed in NSS 3.16.0.
+ // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey,
+ // with a reasonable length but with key data pointing to uninitialized
+ // memory.
+ // To understand this workaround see the fix for 981170:
+ // https://hg.mozilla.org/projects/nss/rev/753bb69e543c
+ if (!NSS_VersionCheck("3.16") && PORT_GetError() == SEC_ERROR_BAD_DATA)
+ return Status::OperationError();
+#endif
+
+ *unwrapped_key = new_key.Pass();
+ return Status::Success();
+}
+
+Status WrapSymKeyAesKw(PK11SymKey* key,
+ PK11SymKey* wrapping_key,
+ std::vector<uint8_t>* buffer) {
+ // The data size must be at least 16 bytes and a multiple of 8 bytes.
+ // RFC 3394 does not specify a maximum allowed data length, but since only
+ // keys are being wrapped in this application (which are small), a reasonable
+ // max limit is whatever will fit into an unsigned. For the max size test,
+ // note that AES Key Wrap always adds 8 bytes to the input data size.
+ const unsigned int input_length = PK11_GetKeyLength(key);
+ DCHECK_GE(input_length, 16u);
+ DCHECK((input_length % 8) == 0);
+
+ SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
+ crypto::ScopedSECItem param_item(
+ PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
+ if (!param_item)
+ return Status::ErrorUnexpected();
+
+ base::CheckedNumeric<unsigned int> output_length = input_length;
+ output_length += 8;
+ if (!output_length.IsValid())
+ return Status::ErrorDataTooLarge();
+
+ buffer->resize(output_length.ValueOrDie());
+ SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer));
+
+ if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP,
+ param_item.get(),
+ wrapping_key,
+ key,
+ &wrapped_key_item)) {
+ return Status::OperationError();
+ }
+ if (output_length.ValueOrDie() != wrapped_key_item.len)
+ return Status::ErrorUnexpected();
+
+ return Status::Success();
+}
+
+class AesKwCryptoAlgorithmNss : public AesAlgorithm {
+ public:
+ AesKwCryptoAlgorithmNss()
+ : AesAlgorithm(
+ CKM_NSS_AES_KEY_WRAP,
+ CKF_WRAP | CKF_WRAP,
+ blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
+ "KW") {}
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& wrapping_key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (data.byte_length() < 16)
+ return Status::ErrorDataTooSmall();
+ if (data.byte_length() % 8)
+ return Status::ErrorInvalidAesKwDataLength();
+
+ // Due to limitations in the NSS API for the AES-KW algorithm, |data| must
+ // be temporarily viewed as a symmetric key to be wrapped (encrypted).
+ SECItem data_item = MakeSECItemForBuffer(data);
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
+ crypto::ScopedPK11SymKey data_as_sym_key(
+ PK11_ImportSymKey(slot.get(),
+ CKK_GENERIC_SECRET,
+ PK11_OriginUnwrap,
+ CKA_SIGN,
+ &data_item,
+ NULL));
+ if (!data_as_sym_key)
+ return Status::OperationError();
+
+ return WrapSymKeyAesKw(
+ data_as_sym_key.get(), SymKeyNss::Cast(wrapping_key)->key(), buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& wrapping_key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (data.byte_length() < 24)
+ return Status::ErrorDataTooSmall();
+ if (data.byte_length() % 8)
+ return Status::ErrorInvalidAesKwDataLength();
+
+ // Due to limitations in the NSS API for the AES-KW algorithm, |data| must
+ // be temporarily viewed as a symmetric key to be unwrapped (decrypted).
+ crypto::ScopedPK11SymKey decrypted;
+ Status status = DoUnwrapSymKeyAesKw(data,
+ SymKeyNss::Cast(wrapping_key)->key(),
+ CKK_GENERIC_SECRET,
+ 0,
+ &decrypted);
+ if (status.IsError())
+ return status;
+
+ // Once the decrypt is complete, extract the resultant raw bytes from NSS
+ // and return them to the caller.
+ if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess)
+ return Status::OperationError();
+ const SECItem* const key_data = PK11_GetKeyData(decrypted.get());
+ if (!key_data)
+ return Status::OperationError();
+ buffer->assign(key_data->data, key_data->data + key_data->len);
+
+ return Status::Success();
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesKwImplementation() {
+ return new AesKwCryptoAlgorithmNss;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/hmac_nss.cc b/chromium/content/child/webcrypto/nss/hmac_nss.cc
new file mode 100644
index 00000000000..c3424fb94f4
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/hmac_nss.cc
@@ -0,0 +1,240 @@
+// Copyright 2014 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 <cryptohi.h>
+#include <pk11pub.h>
+#include <secerr.h>
+#include <sechash.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/sym_key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/secure_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const blink::WebCryptoKeyUsageMask kAllKeyUsages =
+ blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
+
+bool WebCryptoHashToHMACMechanism(const blink::WebCryptoAlgorithm& algorithm,
+ CK_MECHANISM_TYPE* mechanism) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ *mechanism = CKM_SHA_1_HMAC;
+ return true;
+ case blink::WebCryptoAlgorithmIdSha256:
+ *mechanism = CKM_SHA256_HMAC;
+ return true;
+ case blink::WebCryptoAlgorithmIdSha384:
+ *mechanism = CKM_SHA384_HMAC;
+ return true;
+ case blink::WebCryptoAlgorithmIdSha512:
+ *mechanism = CKM_SHA512_HMAC;
+ return true;
+ default:
+ return false;
+ }
+}
+
+class HmacImplementation : public AlgorithmImplementation {
+ public:
+ HmacImplementation() {}
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override {
+ Status status = CheckKeyCreationUsages(kAllKeyUsages, usages);
+ if (status.IsError())
+ return status;
+
+ const blink::WebCryptoHmacKeyGenParams* params =
+ algorithm.hmacKeyGenParams();
+
+ const blink::WebCryptoAlgorithm& hash = params->hash();
+ CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
+ if (!WebCryptoHashToHMACMechanism(hash, &mechanism))
+ return Status::ErrorUnsupported();
+
+ unsigned int keylen_bits = 0;
+ status = GetHmacKeyGenLengthInBits(params, &keylen_bits);
+ if (status.IsError())
+ return status;
+
+ return GenerateSecretKeyNss(
+ blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bits),
+ extractable,
+ usages,
+ keylen_bits / 8,
+ mechanism,
+ result);
+ }
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ case blink::WebCryptoKeyFormatJwk:
+ return CheckKeyCreationUsages(kAllKeyUsages, usages);
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+ }
+
+ Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override {
+ const blink::WebCryptoAlgorithm& hash =
+ algorithm.hmacImportParams()->hash();
+
+ CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
+ if (!WebCryptoHashToHMACMechanism(hash, &mechanism))
+ return Status::ErrorUnsupported();
+
+ base::CheckedNumeric<unsigned int> keylen_bits(key_data.byte_length());
+ keylen_bits *= 8;
+
+ if (!keylen_bits.IsValid())
+ return Status::ErrorDataTooLarge();
+
+ return ImportKeyRawNss(key_data,
+ blink::WebCryptoKeyAlgorithm::createHmac(
+ hash.id(), keylen_bits.ValueOrDie()),
+ extractable,
+ usages,
+ mechanism,
+ CKF_SIGN | CKF_VERIFY,
+ key);
+ }
+
+ Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override {
+ const char* algorithm_name =
+ GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
+ if (!algorithm_name)
+ return Status::ErrorUnexpected();
+
+ std::vector<uint8_t> raw_data;
+ Status status = ReadSecretKeyJwk(
+ key_data, algorithm_name, extractable, usages, &raw_data);
+ if (status.IsError())
+ return status;
+
+ return ImportKeyRaw(
+ CryptoData(raw_data), algorithm, extractable, usages, key);
+ }
+
+ Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override {
+ *buffer = SymKeyNss::Cast(key)->raw_key_data();
+ return Status::Success();
+ }
+
+ Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override {
+ SymKeyNss* sym_key = SymKeyNss::Cast(key);
+ const std::vector<uint8_t>& raw_data = sym_key->raw_key_data();
+
+ const char* algorithm_name =
+ GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
+ if (!algorithm_name)
+ return Status::ErrorUnexpected();
+
+ WriteSecretKeyJwk(CryptoData(raw_data),
+ algorithm_name,
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+ }
+
+ Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ const blink::WebCryptoAlgorithm& hash =
+ key.algorithm().hmacParams()->hash();
+ PK11SymKey* sym_key = SymKeyNss::Cast(key)->key();
+
+ CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
+ if (!WebCryptoHashToHMACMechanism(hash, &mechanism))
+ return Status::ErrorUnexpected();
+
+ SECItem param_item = {siBuffer, NULL, 0};
+ SECItem data_item = MakeSECItemForBuffer(data);
+ // First call is to figure out the length.
+ SECItem signature_item = {siBuffer, NULL, 0};
+
+ if (PK11_SignWithSymKey(
+ sym_key, mechanism, &param_item, &signature_item, &data_item) !=
+ SECSuccess) {
+ return Status::OperationError();
+ }
+
+ DCHECK_NE(0u, signature_item.len);
+
+ buffer->resize(signature_item.len);
+ signature_item.data = vector_as_array(buffer);
+
+ if (PK11_SignWithSymKey(
+ sym_key, mechanism, &param_item, &signature_item, &data_item) !=
+ SECSuccess) {
+ return Status::OperationError();
+ }
+
+ CHECK_EQ(buffer->size(), signature_item.len);
+ return Status::Success();
+ }
+
+ Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const override {
+ std::vector<uint8_t> result;
+ Status status = Sign(algorithm, key, data, &result);
+
+ if (status.IsError())
+ return status;
+
+ // Do not allow verification of truncated MACs.
+ *signature_match = result.size() == signature.byte_length() &&
+ crypto::SecureMemEqual(vector_as_array(&result),
+ signature.bytes(),
+ signature.byte_length());
+
+ return Status::Success();
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformHmacImplementation() {
+ return new HmacImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/key_nss.cc b/chromium/content/child/webcrypto/nss/key_nss.cc
new file mode 100644
index 00000000000..9193963fb59
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/key_nss.cc
@@ -0,0 +1,96 @@
+// Copyright 2014 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 "content/child/webcrypto/nss/key_nss.h"
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+
+namespace content {
+
+namespace webcrypto {
+
+KeyNss::KeyNss(const CryptoData& serialized_key_data)
+ : serialized_key_data_(
+ serialized_key_data.bytes(),
+ serialized_key_data.bytes() + serialized_key_data.byte_length()) {
+}
+
+KeyNss::~KeyNss() {
+}
+
+SymKeyNss* KeyNss::AsSymKey() {
+ return NULL;
+}
+
+PublicKeyNss* KeyNss::AsPublicKey() {
+ return NULL;
+}
+
+PrivateKeyNss* KeyNss::AsPrivateKey() {
+ return NULL;
+}
+
+SymKeyNss::~SymKeyNss() {
+}
+
+SymKeyNss* SymKeyNss::Cast(const blink::WebCryptoKey& key) {
+ KeyNss* platform_key = reinterpret_cast<KeyNss*>(key.handle());
+ return platform_key->AsSymKey();
+}
+
+SymKeyNss* SymKeyNss::AsSymKey() {
+ return this;
+}
+
+SymKeyNss::SymKeyNss(crypto::ScopedPK11SymKey key,
+ const CryptoData& raw_key_data)
+ : KeyNss(raw_key_data), key_(key.Pass()) {
+}
+
+PublicKeyNss::~PublicKeyNss() {
+}
+
+PublicKeyNss* PublicKeyNss::Cast(const blink::WebCryptoKey& key) {
+ KeyNss* platform_key = reinterpret_cast<KeyNss*>(key.handle());
+ return platform_key->AsPublicKey();
+}
+
+PublicKeyNss* PublicKeyNss::AsPublicKey() {
+ return this;
+}
+
+PublicKeyNss::PublicKeyNss(crypto::ScopedSECKEYPublicKey key,
+ const CryptoData& spki_data)
+ : KeyNss(spki_data), key_(key.Pass()) {
+}
+
+PrivateKeyNss::~PrivateKeyNss() {
+}
+
+PrivateKeyNss* PrivateKeyNss::Cast(const blink::WebCryptoKey& key) {
+ KeyNss* platform_key = reinterpret_cast<KeyNss*>(key.handle());
+ return platform_key->AsPrivateKey();
+}
+
+PrivateKeyNss* PrivateKeyNss::AsPrivateKey() {
+ return this;
+}
+
+PrivateKeyNss::PrivateKeyNss(crypto::ScopedSECKEYPrivateKey key,
+ const CryptoData& pkcs8_data)
+ : KeyNss(pkcs8_data), key_(key.Pass()) {
+}
+
+bool PlatformSerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8_t>* key_data) {
+ const KeyNss* nss_key = static_cast<KeyNss*>(key.handle());
+ *key_data = nss_key->serialized_key_data();
+ return true;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/key_nss.h b/chromium/content/child/webcrypto/nss/key_nss.h
new file mode 100644
index 00000000000..9eaf7c427b0
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/key_nss.h
@@ -0,0 +1,109 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_NSS_KEY_NSS_H_
+#define CONTENT_CHILD_WEBCRYPTO_NSS_KEY_NSS_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "crypto/scoped_nss_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoKey.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class PrivateKeyNss;
+class PublicKeyNss;
+class SymKeyNss;
+
+// Base key class for all NSS keys, used to safely cast between types. Each key
+// maintains a copy of its serialized form in either 'raw', 'pkcs8', or 'spki'
+// format. This is to allow structured cloning of keys synchronously from the
+// target Blink thread without having to lock access to the key.
+class KeyNss : public blink::WebCryptoKeyHandle {
+ public:
+ explicit KeyNss(const CryptoData& serialized_key_data);
+ ~KeyNss() override;
+
+ virtual SymKeyNss* AsSymKey();
+ virtual PublicKeyNss* AsPublicKey();
+ virtual PrivateKeyNss* AsPrivateKey();
+
+ const std::vector<uint8_t>& serialized_key_data() const {
+ return serialized_key_data_;
+ }
+
+ private:
+ const std::vector<uint8_t> serialized_key_data_;
+};
+
+class SymKeyNss : public KeyNss {
+ public:
+ ~SymKeyNss() override;
+ SymKeyNss(crypto::ScopedPK11SymKey key, const CryptoData& raw_key_data);
+
+ static SymKeyNss* Cast(const blink::WebCryptoKey& key);
+
+ PK11SymKey* key() { return key_.get(); }
+ SymKeyNss* AsSymKey() override;
+
+ const std::vector<uint8_t>& raw_key_data() const {
+ return serialized_key_data();
+ }
+
+ private:
+ crypto::ScopedPK11SymKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(SymKeyNss);
+};
+
+class PublicKeyNss : public KeyNss {
+ public:
+ ~PublicKeyNss() override;
+ PublicKeyNss(crypto::ScopedSECKEYPublicKey key, const CryptoData& spki_data);
+
+ static PublicKeyNss* Cast(const blink::WebCryptoKey& key);
+
+ SECKEYPublicKey* key() { return key_.get(); }
+ PublicKeyNss* AsPublicKey() override;
+
+ const std::vector<uint8_t>& spki_data() const {
+ return serialized_key_data();
+ }
+
+ private:
+ crypto::ScopedSECKEYPublicKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(PublicKeyNss);
+};
+
+class PrivateKeyNss : public KeyNss {
+ public:
+ ~PrivateKeyNss() override;
+ PrivateKeyNss(crypto::ScopedSECKEYPrivateKey key,
+ const CryptoData& pkcs8_data);
+
+ static PrivateKeyNss* Cast(const blink::WebCryptoKey& key);
+
+ SECKEYPrivateKey* key() { return key_.get(); }
+ PrivateKeyNss* AsPrivateKey() override;
+
+ const std::vector<uint8_t>& pkcs8_data() const {
+ return serialized_key_data();
+ }
+
+ private:
+ crypto::ScopedSECKEYPrivateKey key_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrivateKeyNss);
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_NSS_KEY_NSS_H_
diff --git a/chromium/content/child/webcrypto/nss/rsa_key_nss.cc b/chromium/content/child/webcrypto/nss/rsa_key_nss.cc
new file mode 100644
index 00000000000..f9619a62a16
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/rsa_key_nss.cc
@@ -0,0 +1,852 @@
+// Copyright 2014 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 "content/child/webcrypto/nss/rsa_key_nss.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/generate_key_result.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+#if defined(USE_NSS) && !defined(OS_CHROMEOS)
+Status ErrorRsaPrivateKeyImportNotSupported() {
+ return Status::ErrorUnsupported(
+ "NSS version must be at least 3.16.2 for RSA private key import. See "
+ "http://crbug.com/380424");
+}
+
+// Prior to NSS 3.16.2 RSA key parameters were not validated. This is
+// a security problem for RSA private key import from JWK which uses a
+// CKA_ID based on the public modulus to retrieve the private key.
+Status NssSupportsRsaPrivateKeyImport() {
+ if (!NSS_VersionCheck("3.16.2"))
+ return ErrorRsaPrivateKeyImportNotSupported();
+
+ // Also ensure that the version of Softoken is 3.16.2 or later.
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
+ CK_SLOT_INFO info = {};
+ if (PK11_GetSlotInfo(slot.get(), &info) != SECSuccess)
+ return ErrorRsaPrivateKeyImportNotSupported();
+
+ // CK_SLOT_INFO.hardwareVersion contains the major.minor
+ // version info for Softoken in the corresponding .major/.minor
+ // fields, and .firmwareVersion contains the patch.build
+ // version info (in the .major/.minor fields)
+ if ((info.hardwareVersion.major > 3) ||
+ (info.hardwareVersion.major == 3 &&
+ (info.hardwareVersion.minor > 16 ||
+ (info.hardwareVersion.minor == 16 &&
+ info.firmwareVersion.major >= 2)))) {
+ return Status::Success();
+ }
+
+ return ErrorRsaPrivateKeyImportNotSupported();
+}
+#else
+Status NssSupportsRsaPrivateKeyImport() {
+ return Status::Success();
+}
+#endif
+
+bool CreateRsaHashedPublicKeyAlgorithm(
+ blink::WebCryptoAlgorithmId rsa_algorithm,
+ blink::WebCryptoAlgorithmId hash_algorithm,
+ SECKEYPublicKey* key,
+ blink::WebCryptoKeyAlgorithm* key_algorithm) {
+ // TODO(eroman): What about other key types rsaPss, rsaOaep.
+ if (!key || key->keyType != rsaKey)
+ return false;
+
+ unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8;
+ CryptoData public_exponent(key->u.rsa.publicExponent.data,
+ key->u.rsa.publicExponent.len);
+
+ *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(
+ rsa_algorithm,
+ modulus_length_bits,
+ public_exponent.bytes(),
+ public_exponent.byte_length(),
+ hash_algorithm);
+ return true;
+}
+
+bool CreateRsaHashedPrivateKeyAlgorithm(
+ blink::WebCryptoAlgorithmId rsa_algorithm,
+ blink::WebCryptoAlgorithmId hash_algorithm,
+ SECKEYPrivateKey* key,
+ blink::WebCryptoKeyAlgorithm* key_algorithm) {
+ crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key));
+ if (!public_key)
+ return false;
+ return CreateRsaHashedPublicKeyAlgorithm(
+ rsa_algorithm, hash_algorithm, public_key.get(), key_algorithm);
+}
+
+// From PKCS#1 [http://tools.ietf.org/html/rfc3447]:
+//
+// RSAPrivateKey ::= SEQUENCE {
+// version Version,
+// modulus INTEGER, -- n
+// publicExponent INTEGER, -- e
+// privateExponent INTEGER, -- d
+// prime1 INTEGER, -- p
+// prime2 INTEGER, -- q
+// exponent1 INTEGER, -- d mod (p-1)
+// exponent2 INTEGER, -- d mod (q-1)
+// coefficient INTEGER, -- (inverse of q) mod p
+// otherPrimeInfos OtherPrimeInfos OPTIONAL
+// }
+//
+// Note that otherPrimeInfos is only applicable for version=1. Since NSS
+// doesn't use multi-prime can safely use version=0.
+struct RSAPrivateKey {
+ SECItem version;
+ SECItem modulus;
+ SECItem public_exponent;
+ SECItem private_exponent;
+ SECItem prime1;
+ SECItem prime2;
+ SECItem exponent1;
+ SECItem exponent2;
+ SECItem coefficient;
+};
+
+// The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo
+// function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we
+// provide a fallback implementation.
+#if defined(USE_NSS)
+const SEC_ASN1Template RSAPrivateKeyTemplate[] = {
+ {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)},
+ {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)},
+ {0}};
+#endif // defined(USE_NSS)
+
+// On success |value| will be filled with data which must be freed by
+// SECITEM_FreeItem(value, PR_FALSE);
+bool ReadUint(SECKEYPrivateKey* key,
+ CK_ATTRIBUTE_TYPE attribute,
+ SECItem* value) {
+ SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value);
+
+ // PK11_ReadRawAttribute() returns items of type siBuffer. However in order
+ // for the ASN.1 encoding to be correct, the items must be of type
+ // siUnsignedInteger.
+ value->type = siUnsignedInteger;
+
+ return rv == SECSuccess;
+}
+
+// Fills |out| with the RSA private key properties. Returns true on success.
+// Regardless of the return value, the caller must invoke FreeRSAPrivateKey()
+// to free up any allocated memory.
+//
+// The passed in RSAPrivateKey must be zero-initialized.
+bool InitRSAPrivateKey(SECKEYPrivateKey* key, RSAPrivateKey* out) {
+ if (key->keyType != rsaKey)
+ return false;
+
+ // Everything should be zero-ed out. These are just some spot checks.
+ DCHECK(!out->version.data);
+ DCHECK(!out->version.len);
+ DCHECK(!out->modulus.data);
+ DCHECK(!out->modulus.len);
+
+ // Always use version=0 since not using multi-prime.
+ if (!SEC_ASN1EncodeInteger(NULL, &out->version, 0))
+ return false;
+
+ if (!ReadUint(key, CKA_MODULUS, &out->modulus))
+ return false;
+ if (!ReadUint(key, CKA_PUBLIC_EXPONENT, &out->public_exponent))
+ return false;
+ if (!ReadUint(key, CKA_PRIVATE_EXPONENT, &out->private_exponent))
+ return false;
+ if (!ReadUint(key, CKA_PRIME_1, &out->prime1))
+ return false;
+ if (!ReadUint(key, CKA_PRIME_2, &out->prime2))
+ return false;
+ if (!ReadUint(key, CKA_EXPONENT_1, &out->exponent1))
+ return false;
+ if (!ReadUint(key, CKA_EXPONENT_2, &out->exponent2))
+ return false;
+ if (!ReadUint(key, CKA_COEFFICIENT, &out->coefficient))
+ return false;
+
+ return true;
+}
+
+struct FreeRsaPrivateKey {
+ void operator()(RSAPrivateKey* out) {
+ SECITEM_FreeItem(&out->version, PR_FALSE);
+ SECITEM_FreeItem(&out->modulus, PR_FALSE);
+ SECITEM_FreeItem(&out->public_exponent, PR_FALSE);
+ SECITEM_FreeItem(&out->private_exponent, PR_FALSE);
+ SECITEM_FreeItem(&out->prime1, PR_FALSE);
+ SECITEM_FreeItem(&out->prime2, PR_FALSE);
+ SECITEM_FreeItem(&out->exponent1, PR_FALSE);
+ SECITEM_FreeItem(&out->exponent2, PR_FALSE);
+ SECITEM_FreeItem(&out->coefficient, PR_FALSE);
+ }
+};
+
+typedef scoped_ptr<CERTSubjectPublicKeyInfo,
+ crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
+ SECKEY_DestroySubjectPublicKeyInfo> >
+ ScopedCERTSubjectPublicKeyInfo;
+
+struct DestroyGenericObject {
+ void operator()(PK11GenericObject* o) const {
+ if (o)
+ PK11_DestroyGenericObject(o);
+ }
+};
+
+typedef scoped_ptr<PK11GenericObject, DestroyGenericObject>
+ ScopedPK11GenericObject;
+
+// Helper to add an attribute to a template.
+void AddAttribute(CK_ATTRIBUTE_TYPE type,
+ void* value,
+ unsigned long length,
+ std::vector<CK_ATTRIBUTE>* templ) {
+ CK_ATTRIBUTE attribute = {type, value, length};
+ templ->push_back(attribute);
+}
+
+void AddAttribute(CK_ATTRIBUTE_TYPE type,
+ const CryptoData& data,
+ std::vector<CK_ATTRIBUTE>* templ) {
+ CK_ATTRIBUTE attribute = {type, const_cast<unsigned char*>(data.bytes()),
+ data.byte_length()};
+ templ->push_back(attribute);
+}
+
+void AddAttribute(CK_ATTRIBUTE_TYPE type,
+ const std::string& data,
+ std::vector<CK_ATTRIBUTE>* templ) {
+ AddAttribute(type, CryptoData(data), templ);
+}
+
+Status ExportKeyPkcs8Nss(SECKEYPrivateKey* key, std::vector<uint8_t>* buffer) {
+ if (key->keyType != rsaKey)
+ return Status::ErrorUnsupported();
+
+// TODO(rsleevi): Implement OAEP support according to the spec.
+
+#if defined(USE_NSS)
+ // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code.
+ const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
+ const int kPrivateKeyInfoVersion = 0;
+
+ SECKEYPrivateKeyInfo private_key_info = {};
+ RSAPrivateKey rsa_private_key = {};
+ scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(
+ &rsa_private_key);
+
+ // http://crbug.com/366427: the spec does not define any other failures for
+ // exporting, so none of the subsequent errors are spec compliant.
+ if (!InitRSAPrivateKey(key, &rsa_private_key))
+ return Status::OperationError();
+
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+ if (!arena.get())
+ return Status::OperationError();
+
+ if (!SEC_ASN1EncodeItem(arena.get(),
+ &private_key_info.privateKey,
+ &rsa_private_key,
+ RSAPrivateKeyTemplate))
+ return Status::OperationError();
+
+ if (SECSuccess !=
+ SECOID_SetAlgorithmID(
+ arena.get(), &private_key_info.algorithm, algorithm, NULL))
+ return Status::OperationError();
+
+ if (!SEC_ASN1EncodeInteger(
+ arena.get(), &private_key_info.version, kPrivateKeyInfoVersion))
+ return Status::OperationError();
+
+ crypto::ScopedSECItem encoded_key(
+ SEC_ASN1EncodeItem(NULL,
+ NULL,
+ &private_key_info,
+ SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate)));
+#else // defined(USE_NSS)
+ crypto::ScopedSECItem encoded_key(PK11_ExportDERPrivateKeyInfo(key, NULL));
+#endif // defined(USE_NSS)
+
+ if (!encoded_key.get())
+ return Status::OperationError();
+
+ buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len);
+ return Status::Success();
+}
+
+Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const JwkRsaInfo& params,
+ blink::WebCryptoKey* key) {
+ Status status = NssSupportsRsaPrivateKeyImport();
+ if (status.IsError())
+ return status;
+
+ CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
+ CK_KEY_TYPE key_type = CKK_RSA;
+ CK_BBOOL ck_false = CK_FALSE;
+
+ std::vector<CK_ATTRIBUTE> key_template;
+
+ AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template);
+ AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template);
+ AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template);
+ AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template);
+ AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template);
+
+ // Required properties by JWA.
+ AddAttribute(CKA_MODULUS, params.n, &key_template);
+ AddAttribute(CKA_PUBLIC_EXPONENT, params.e, &key_template);
+ AddAttribute(CKA_PRIVATE_EXPONENT, params.d, &key_template);
+
+ // Manufacture a CKA_ID so the created key can be retrieved later as a
+ // SECKEYPrivateKey using FindKeyByKeyID(). Unfortunately there isn't a more
+ // direct way to do this in NSS.
+ //
+ // For consistency with other NSS key creation methods, set the CKA_ID to
+ // PK11_MakeIDFromPubKey(). There are some problems with
+ // this approach:
+ //
+ // (1) Prior to NSS 3.16.2, there is no parameter validation when creating
+ // private keys. It is therefore possible to construct a key using the
+ // known public modulus, and where all the other parameters are bogus.
+ // FindKeyByKeyID() returns the first key matching the ID. So this would
+ // effectively allow an attacker to retrieve a private key of their
+ // choice.
+ //
+ // (2) The ID space is shared by different key types. So theoretically
+ // possible to retrieve a key of the wrong type which has a matching
+ // CKA_ID. In practice I am told this is not likely except for small key
+ // sizes, since would require constructing keys with the same public
+ // data.
+ //
+ // (3) FindKeyByKeyID() doesn't necessarily return the object that was just
+ // created by CreateGenericObject. If the pre-existing key was
+ // provisioned with flags incompatible with WebCrypto (for instance
+ // marked sensitive) then this will break things.
+ SECItem modulus_item = MakeSECItemForBuffer(CryptoData(params.n));
+ crypto::ScopedSECItem object_id(PK11_MakeIDFromPubKey(&modulus_item));
+ AddAttribute(
+ CKA_ID, CryptoData(object_id->data, object_id->len), &key_template);
+
+ // Optional properties by JWA, however guaranteed to be present by Chromium's
+ // implementation.
+ AddAttribute(CKA_PRIME_1, params.p, &key_template);
+ AddAttribute(CKA_PRIME_2, params.q, &key_template);
+ AddAttribute(CKA_EXPONENT_1, params.dp, &key_template);
+ AddAttribute(CKA_EXPONENT_2, params.dq, &key_template);
+ AddAttribute(CKA_COEFFICIENT, params.qi, &key_template);
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
+
+ ScopedPK11GenericObject key_object(PK11_CreateGenericObject(
+ slot.get(), &key_template[0], key_template.size(), PR_FALSE));
+
+ if (!key_object)
+ return Status::OperationError();
+
+ crypto::ScopedSECKEYPrivateKey private_key_tmp(
+ PK11_FindKeyByKeyID(slot.get(), object_id.get(), NULL));
+
+ // PK11_FindKeyByKeyID() may return a handle to an existing key, rather than
+ // the object created by PK11_CreateGenericObject().
+ crypto::ScopedSECKEYPrivateKey private_key(
+ SECKEY_CopyPrivateKey(private_key_tmp.get()));
+
+ if (!private_key)
+ return Status::OperationError();
+
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ if (!CreateRsaHashedPrivateKeyAlgorithm(
+ algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash().id(),
+ private_key.get(),
+ &key_algorithm)) {
+ return Status::ErrorUnexpected();
+ }
+
+ std::vector<uint8_t> pkcs8_data;
+ status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data);
+ if (status.IsError())
+ return status;
+
+ scoped_ptr<PrivateKeyNss> key_handle(
+ new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data)));
+
+ *key = blink::WebCryptoKey::create(key_handle.release(),
+ blink::WebCryptoKeyTypePrivate,
+ extractable,
+ key_algorithm,
+ usages);
+ return Status::Success();
+}
+
+Status ExportKeySpkiNss(SECKEYPublicKey* key, std::vector<uint8_t>* buffer) {
+ const crypto::ScopedSECItem spki_der(
+ SECKEY_EncodeDERSubjectPublicKeyInfo(key));
+ if (!spki_der)
+ return Status::OperationError();
+
+ buffer->assign(spki_der->data, spki_der->data + spki_der->len);
+ return Status::Success();
+}
+
+Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const CryptoData& modulus_data,
+ const CryptoData& exponent_data,
+ blink::WebCryptoKey* key) {
+ if (!modulus_data.byte_length())
+ return Status::ErrorImportRsaEmptyModulus();
+
+ if (!exponent_data.byte_length())
+ return Status::ErrorImportRsaEmptyExponent();
+
+ DCHECK(modulus_data.bytes());
+ DCHECK(exponent_data.bytes());
+
+ // NSS does not provide a way to create an RSA public key directly from the
+ // modulus and exponent values, but it can import an DER-encoded ASN.1 blob
+ // with these values and create the public key from that. The code below
+ // follows the recommendation described in
+ // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7
+
+ // Pack the input values into a struct compatible with NSS ASN.1 encoding, and
+ // set up an ASN.1 encoder template for it.
+ struct RsaPublicKeyData {
+ SECItem modulus;
+ SECItem exponent;
+ };
+ const RsaPublicKeyData pubkey_in = {
+ {siUnsignedInteger, const_cast<unsigned char*>(modulus_data.bytes()),
+ modulus_data.byte_length()},
+ {siUnsignedInteger, const_cast<unsigned char*>(exponent_data.bytes()),
+ exponent_data.byte_length()}};
+ const SEC_ASN1Template rsa_public_key_template[] = {
+ {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
+ {
+ SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus),
+ },
+ {
+ SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent),
+ },
+ {
+ 0,
+ }};
+
+ // DER-encode the public key.
+ crypto::ScopedSECItem pubkey_der(
+ SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template));
+ if (!pubkey_der)
+ return Status::OperationError();
+
+ // Import the DER-encoded public key to create an RSA SECKEYPublicKey.
+ crypto::ScopedSECKEYPublicKey pubkey(
+ SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA));
+ if (!pubkey)
+ return Status::OperationError();
+
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ if (!CreateRsaHashedPublicKeyAlgorithm(
+ algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash().id(),
+ pubkey.get(),
+ &key_algorithm)) {
+ return Status::ErrorUnexpected();
+ }
+
+ std::vector<uint8_t> spki_data;
+ Status status = ExportKeySpkiNss(pubkey.get(), &spki_data);
+ if (status.IsError())
+ return status;
+
+ scoped_ptr<PublicKeyNss> key_handle(
+ new PublicKeyNss(pubkey.Pass(), CryptoData(spki_data)));
+
+ *key = blink::WebCryptoKey::create(key_handle.release(),
+ blink::WebCryptoKeyTypePublic,
+ extractable,
+ key_algorithm,
+ usages);
+ return Status::Success();
+}
+
+} // namespace
+
+Status RsaHashedAlgorithm::GenerateKey(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask combined_usages,
+ GenerateKeyResult* result) const {
+ Status status = CheckKeyCreationUsages(
+ all_public_key_usages_ | all_private_key_usages_, combined_usages);
+ if (status.IsError())
+ return status;
+
+ const blink::WebCryptoKeyUsageMask public_usages =
+ combined_usages & all_public_key_usages_;
+ const blink::WebCryptoKeyUsageMask private_usages =
+ combined_usages & all_private_key_usages_;
+
+ unsigned int public_exponent = 0;
+ unsigned int modulus_length_bits = 0;
+ status = GetRsaKeyGenParameters(algorithm.rsaHashedKeyGenParams(),
+ &public_exponent,
+ &modulus_length_bits);
+ if (status.IsError())
+ return status;
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
+ if (!slot)
+ return Status::OperationError();
+
+ PK11RSAGenParams rsa_gen_params;
+ rsa_gen_params.keySizeInBits = modulus_length_bits;
+ rsa_gen_params.pe = public_exponent;
+
+ const CK_FLAGS operation_flags_mask =
+ CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_WRAP | CKF_UNWRAP;
+
+ // The private key must be marked as insensitive and extractable, otherwise it
+ // cannot later be exported in unencrypted form or structured-cloned.
+ const PK11AttrFlags attribute_flags =
+ PK11_ATTR_INSENSITIVE | PK11_ATTR_EXTRACTABLE;
+
+ // Note: NSS does not generate an sec_public_key if the call below fails,
+ // so there is no danger of a leaked sec_public_key.
+ SECKEYPublicKey* sec_public_key;
+ crypto::ScopedSECKEYPrivateKey scoped_sec_private_key(
+ PK11_GenerateKeyPairWithOpFlags(slot.get(),
+ CKM_RSA_PKCS_KEY_PAIR_GEN,
+ &rsa_gen_params,
+ &sec_public_key,
+ attribute_flags,
+ generate_flags_,
+ operation_flags_mask,
+ NULL));
+ if (!scoped_sec_private_key)
+ return Status::OperationError();
+
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ if (!CreateRsaHashedPublicKeyAlgorithm(
+ algorithm.id(),
+ algorithm.rsaHashedKeyGenParams()->hash().id(),
+ sec_public_key,
+ &key_algorithm)) {
+ return Status::ErrorUnexpected();
+ }
+
+ std::vector<uint8_t> spki_data;
+ status = ExportKeySpkiNss(sec_public_key, &spki_data);
+ if (status.IsError())
+ return status;
+
+ scoped_ptr<PublicKeyNss> public_key_handle(new PublicKeyNss(
+ crypto::ScopedSECKEYPublicKey(sec_public_key), CryptoData(spki_data)));
+
+ std::vector<uint8_t> pkcs8_data;
+ status = ExportKeyPkcs8Nss(scoped_sec_private_key.get(), &pkcs8_data);
+ if (status.IsError())
+ return status;
+
+ scoped_ptr<PrivateKeyNss> private_key_handle(
+ new PrivateKeyNss(scoped_sec_private_key.Pass(), CryptoData(pkcs8_data)));
+
+ blink::WebCryptoKey public_key =
+ blink::WebCryptoKey::create(public_key_handle.release(),
+ blink::WebCryptoKeyTypePublic,
+ true,
+ key_algorithm,
+ public_usages);
+
+ blink::WebCryptoKey private_key =
+ blink::WebCryptoKey::create(private_key_handle.release(),
+ blink::WebCryptoKeyTypePrivate,
+ extractable,
+ key_algorithm,
+ private_usages);
+
+ result->AssignKeyPair(public_key, private_key);
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const {
+ switch (format) {
+ case blink::WebCryptoKeyFormatSpki:
+ return CheckKeyCreationUsages(all_public_key_usages_, usages);
+ case blink::WebCryptoKeyFormatPkcs8:
+ return CheckKeyCreationUsages(all_private_key_usages_, usages);
+ case blink::WebCryptoKeyFormatJwk:
+ // The JWK could represent either a public key or private key. The usages
+ // must make sense for one of the two. The usages will be checked again by
+ // ImportKeyJwk() once the key type has been determined.
+ if (CheckKeyCreationUsages(all_private_key_usages_, usages)
+ .IsSuccess() ||
+ CheckKeyCreationUsages(all_public_key_usages_, usages)
+ .IsSuccess()) {
+ return Status::Success();
+ }
+ return Status::ErrorCreateKeyBadUsages();
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+}
+
+Status RsaHashedAlgorithm::ImportKeyPkcs8(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ Status status = NssSupportsRsaPrivateKeyImport();
+ if (status.IsError())
+ return status;
+
+ if (!key_data.byte_length())
+ return Status::ErrorImportEmptyKeyData();
+
+ // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
+ // private key info object.
+ SECItem pki_der = MakeSECItemForBuffer(key_data);
+
+ SECKEYPrivateKey* seckey_private_key = NULL;
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
+ if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot.get(),
+ &pki_der,
+ NULL, // nickname
+ NULL, // publicValue
+ false, // isPerm
+ false, // isPrivate
+ KU_ALL, // usage
+ &seckey_private_key,
+ NULL) != SECSuccess) {
+ return Status::DataError();
+ }
+ DCHECK(seckey_private_key);
+ crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
+
+ const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
+ if (sec_key_type != rsaKey)
+ return Status::DataError();
+
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ if (!CreateRsaHashedPrivateKeyAlgorithm(
+ algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash().id(),
+ private_key.get(),
+ &key_algorithm)) {
+ return Status::ErrorUnexpected();
+ }
+
+ // TODO(eroman): This is probably going to be the same as the input.
+ std::vector<uint8_t> pkcs8_data;
+ status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data);
+ if (status.IsError())
+ return status;
+
+ scoped_ptr<PrivateKeyNss> key_handle(
+ new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data)));
+
+ *key = blink::WebCryptoKey::create(key_handle.release(),
+ blink::WebCryptoKeyTypePrivate,
+ extractable,
+ key_algorithm,
+ usages);
+
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::ImportKeySpki(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ if (!key_data.byte_length())
+ return Status::ErrorImportEmptyKeyData();
+
+ // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
+ // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
+ SECItem spki_item = MakeSECItemForBuffer(key_data);
+ const ScopedCERTSubjectPublicKeyInfo spki(
+ SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
+ if (!spki)
+ return Status::DataError();
+
+ crypto::ScopedSECKEYPublicKey sec_public_key(
+ SECKEY_ExtractPublicKey(spki.get()));
+ if (!sec_public_key)
+ return Status::DataError();
+
+ const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
+ if (sec_key_type != rsaKey)
+ return Status::DataError();
+
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ if (!CreateRsaHashedPublicKeyAlgorithm(
+ algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash().id(),
+ sec_public_key.get(),
+ &key_algorithm)) {
+ return Status::ErrorUnexpected();
+ }
+
+ // TODO(eroman): This is probably going to be the same as the input.
+ std::vector<uint8_t> spki_data;
+ Status status = ExportKeySpkiNss(sec_public_key.get(), &spki_data);
+ if (status.IsError())
+ return status;
+
+ scoped_ptr<PublicKeyNss> key_handle(
+ new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data)));
+
+ *key = blink::WebCryptoKey::create(key_handle.release(),
+ blink::WebCryptoKeyTypePublic,
+ extractable,
+ key_algorithm,
+ usages);
+
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return Status::ErrorUnexpectedKeyType();
+ *buffer = PrivateKeyNss::Cast(key)->pkcs8_data();
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return Status::ErrorUnexpectedKeyType();
+ *buffer = PublicKeyNss::Cast(key)->spki_data();
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::ImportKeyJwk(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ const char* jwk_algorithm =
+ GetJwkAlgorithm(algorithm.rsaHashedImportParams()->hash().id());
+
+ if (!jwk_algorithm)
+ return Status::ErrorUnexpected();
+
+ JwkRsaInfo jwk;
+ Status status =
+ ReadRsaKeyJwk(key_data, jwk_algorithm, extractable, usages, &jwk);
+ if (status.IsError())
+ return status;
+
+ // Once the key type is known, verify the usages.
+ status = CheckKeyCreationUsages(
+ jwk.is_private_key ? all_private_key_usages_ : all_public_key_usages_,
+ usages);
+ if (status.IsError())
+ return Status::ErrorCreateKeyBadUsages();
+
+ return jwk.is_private_key
+ ? ImportRsaPrivateKey(algorithm, extractable, usages, jwk, key)
+ : ImportRsaPublicKey(algorithm,
+ extractable,
+ usages,
+ CryptoData(jwk.n),
+ CryptoData(jwk.e),
+ key);
+}
+
+Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ const char* jwk_algorithm =
+ GetJwkAlgorithm(key.algorithm().rsaHashedParams()->hash().id());
+
+ if (!jwk_algorithm)
+ return Status::ErrorUnexpected();
+
+ switch (key.type()) {
+ case blink::WebCryptoKeyTypePublic: {
+ SECKEYPublicKey* nss_key = PublicKeyNss::Cast(key)->key();
+ if (nss_key->keyType != rsaKey)
+ return Status::ErrorUnsupported();
+
+ WriteRsaPublicKeyJwk(SECItemToCryptoData(nss_key->u.rsa.modulus),
+ SECItemToCryptoData(nss_key->u.rsa.publicExponent),
+ jwk_algorithm,
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+ }
+
+ case blink::WebCryptoKeyTypePrivate: {
+ SECKEYPrivateKey* nss_key = PrivateKeyNss::Cast(key)->key();
+ RSAPrivateKey key_props = {};
+ scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(&key_props);
+
+ if (!InitRSAPrivateKey(nss_key, &key_props))
+ return Status::OperationError();
+
+ WriteRsaPrivateKeyJwk(SECItemToCryptoData(key_props.modulus),
+ SECItemToCryptoData(key_props.public_exponent),
+ SECItemToCryptoData(key_props.private_exponent),
+ SECItemToCryptoData(key_props.prime1),
+ SECItemToCryptoData(key_props.prime2),
+ SECItemToCryptoData(key_props.exponent1),
+ SECItemToCryptoData(key_props.exponent2),
+ SECItemToCryptoData(key_props.coefficient),
+ jwk_algorithm,
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+ }
+ default:
+ return Status::ErrorUnexpected();
+ }
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/rsa_key_nss.h b/chromium/content/child/webcrypto/nss/rsa_key_nss.h
new file mode 100644
index 00000000000..725a25e837b
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/rsa_key_nss.h
@@ -0,0 +1,92 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_NSS_RSA_KEY_NSS_H_
+#define CONTENT_CHILD_WEBCRYPTO_NSS_RSA_KEY_NSS_H_
+
+#include <pkcs11t.h>
+
+#include "content/child/webcrypto/algorithm_implementation.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class PublicKeyNss;
+class PrivateKeyNss;
+
+// Base class for an RSA algorithm whose keys additionaly have a hash parameter
+// bound to them. Provides functionality for generating, importing, and
+// exporting keys.
+class RsaHashedAlgorithm : public AlgorithmImplementation {
+ public:
+ // Constructs an RSA algorithm which will use the NSS flags |generate_flags|
+ // when generating keys. |all_public_key_usages| and |all_private_key_usages|
+ // are the set of WebCrypto key usages that are valid for created keys
+ // (public and private respectively).
+ //
+ // For instance if public keys support encryption and wrapping, and private
+ // keys support decryption and unwrapping callers should set:
+ // all_public_key_usages = UsageEncrypt | UsageWrap
+ // all_private_key_usages = UsageDecrypt | UsageUnwrap
+ // This information is used when importing or generating keys, to enforce
+ // that valid key usages are allowed.
+ RsaHashedAlgorithm(CK_FLAGS generate_flags,
+ blink::WebCryptoKeyUsageMask all_public_key_usages,
+ blink::WebCryptoKeyUsageMask all_private_key_usages)
+ : generate_flags_(generate_flags),
+ all_public_key_usages_(all_public_key_usages),
+ all_private_key_usages_(all_private_key_usages) {}
+
+ // For instance "RSA-OAEP-256".
+ virtual const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const = 0;
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override;
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override;
+
+ Status ImportKeyPkcs8(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ImportKeySpki(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ExportKeyPkcs8(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ Status ExportKeySpki(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ private:
+ CK_FLAGS generate_flags_;
+ blink::WebCryptoKeyUsageMask all_public_key_usages_;
+ blink::WebCryptoKeyUsageMask all_private_key_usages_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_NSS_RSA_KEY_NSS_H_
diff --git a/chromium/content/child/webcrypto/nss/rsa_oaep_nss.cc b/chromium/content/child/webcrypto/nss/rsa_oaep_nss.cc
new file mode 100644
index 00000000000..f7484f6503a
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/rsa_oaep_nss.cc
@@ -0,0 +1,246 @@
+// Copyright 2014 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 <cryptohi.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <secerr.h>
+#include <sechash.h>
+
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/rsa_key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+Status NssSupportsRsaOaep() {
+ if (NssRuntimeSupport::Get()->IsRsaOaepSupported())
+ return Status::Success();
+ return Status::ErrorUnsupported(
+ "NSS version doesn't support RSA-OAEP. Try using version 3.16.2 or "
+ "later");
+}
+
+CK_MECHANISM_TYPE WebCryptoHashToMGFMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return CKG_MGF1_SHA1;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return CKG_MGF1_SHA256;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return CKG_MGF1_SHA384;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return CKG_MGF1_SHA512;
+ default:
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+CK_MECHANISM_TYPE WebCryptoHashToDigestMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return CKM_SHA_1;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return CKM_SHA256;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return CKM_SHA384;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return CKM_SHA512;
+ default:
+ // Not a supported algorithm.
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+bool InitializeRsaOaepParams(const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& label,
+ CK_RSA_PKCS_OAEP_PARAMS* oaep_params) {
+ oaep_params->source = CKZ_DATA_SPECIFIED;
+ oaep_params->pSourceData = const_cast<unsigned char*>(label.bytes());
+ oaep_params->ulSourceDataLen = label.byte_length();
+ oaep_params->mgf = WebCryptoHashToMGFMechanism(hash);
+ oaep_params->hashAlg = WebCryptoHashToDigestMechanism(hash);
+
+ if (oaep_params->mgf == CKM_INVALID_MECHANISM ||
+ oaep_params->hashAlg == CKM_INVALID_MECHANISM) {
+ return false;
+ }
+
+ return true;
+}
+
+Status EncryptRsaOaep(SECKEYPublicKey* key,
+ const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& label,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
+ if (!InitializeRsaOaepParams(hash, label, &oaep_params))
+ return Status::ErrorUnsupported();
+
+ SECItem param;
+ param.type = siBuffer;
+ param.data = reinterpret_cast<unsigned char*>(&oaep_params);
+ param.len = sizeof(oaep_params);
+
+ buffer->resize(SECKEY_PublicKeyStrength(key));
+ unsigned char* buffer_data = vector_as_array(buffer);
+ unsigned int output_len;
+ if (NssRuntimeSupport::Get()->pk11_pub_encrypt_func()(key,
+ CKM_RSA_PKCS_OAEP,
+ &param,
+ buffer_data,
+ &output_len,
+ buffer->size(),
+ data.bytes(),
+ data.byte_length(),
+ NULL) != SECSuccess) {
+ return Status::OperationError();
+ }
+
+ CHECK_LE(output_len, buffer->size());
+ buffer->resize(output_len);
+ return Status::Success();
+}
+
+Status DecryptRsaOaep(SECKEYPrivateKey* key,
+ const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& label,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ Status status = NssSupportsRsaOaep();
+ if (status.IsError())
+ return status;
+
+ CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
+ if (!InitializeRsaOaepParams(hash, label, &oaep_params))
+ return Status::ErrorUnsupported();
+
+ SECItem param;
+ param.type = siBuffer;
+ param.data = reinterpret_cast<unsigned char*>(&oaep_params);
+ param.len = sizeof(oaep_params);
+
+ const int modulus_length_bytes = PK11_GetPrivateModulusLen(key);
+ if (modulus_length_bytes <= 0)
+ return Status::ErrorUnexpected();
+
+ buffer->resize(modulus_length_bytes);
+
+ unsigned char* buffer_data = vector_as_array(buffer);
+ unsigned int output_len;
+ if (NssRuntimeSupport::Get()->pk11_priv_decrypt_func()(key,
+ CKM_RSA_PKCS_OAEP,
+ &param,
+ buffer_data,
+ &output_len,
+ buffer->size(),
+ data.bytes(),
+ data.byte_length()) !=
+ SECSuccess) {
+ return Status::OperationError();
+ }
+
+ CHECK_LE(output_len, buffer->size());
+ buffer->resize(output_len);
+ return Status::Success();
+}
+
+class RsaOaepImplementation : public RsaHashedAlgorithm {
+ public:
+ RsaOaepImplementation()
+ : RsaHashedAlgorithm(
+ CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP,
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
+ blink::WebCryptoKeyUsageDecrypt |
+ blink::WebCryptoKeyUsageUnwrapKey) {}
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override {
+ Status status = NssSupportsRsaOaep();
+ if (status.IsError())
+ return status;
+ return RsaHashedAlgorithm::GenerateKey(
+ algorithm, extractable, usages, result);
+ }
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override {
+ Status status = NssSupportsRsaOaep();
+ if (status.IsError())
+ return status;
+ return RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(format, usages);
+ }
+
+ const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const override {
+ switch (hash) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return "RSA-OAEP";
+ case blink::WebCryptoAlgorithmIdSha256:
+ return "RSA-OAEP-256";
+ case blink::WebCryptoAlgorithmIdSha384:
+ return "RSA-OAEP-384";
+ case blink::WebCryptoAlgorithmIdSha512:
+ return "RSA-OAEP-512";
+ default:
+ return NULL;
+ }
+ }
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return Status::ErrorUnexpectedKeyType();
+
+ return EncryptRsaOaep(
+ PublicKeyNss::Cast(key)->key(),
+ key.algorithm().rsaHashedParams()->hash(),
+ CryptoData(algorithm.rsaOaepParams()->optionalLabel()),
+ data,
+ buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return Status::ErrorUnexpectedKeyType();
+
+ return DecryptRsaOaep(
+ PrivateKeyNss::Cast(key)->key(),
+ key.algorithm().rsaHashedParams()->hash(),
+ CryptoData(algorithm.rsaOaepParams()->optionalLabel()),
+ data,
+ buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformRsaOaepImplementation() {
+ return new RsaOaepImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/rsa_ssa_nss.cc b/chromium/content/child/webcrypto/nss/rsa_ssa_nss.cc
new file mode 100644
index 00000000000..471aaedb4b3
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/rsa_ssa_nss.cc
@@ -0,0 +1,144 @@
+// Copyright 2014 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 <cryptohi.h>
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/rsa_key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/scoped_nss_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+class RsaSsaImplementation : public RsaHashedAlgorithm {
+ public:
+ RsaSsaImplementation()
+ : RsaHashedAlgorithm(CKF_SIGN | CKF_VERIFY,
+ blink::WebCryptoKeyUsageVerify,
+ blink::WebCryptoKeyUsageSign) {}
+
+ const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const override {
+ switch (hash) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return "RS1";
+ case blink::WebCryptoAlgorithmIdSha256:
+ return "RS256";
+ case blink::WebCryptoAlgorithmIdSha384:
+ return "RS384";
+ case blink::WebCryptoAlgorithmIdSha512:
+ return "RS512";
+ default:
+ return NULL;
+ }
+ }
+
+ Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return Status::ErrorUnexpectedKeyType();
+
+ SECKEYPrivateKey* private_key = PrivateKeyNss::Cast(key)->key();
+
+ const blink::WebCryptoAlgorithm& hash =
+ key.algorithm().rsaHashedParams()->hash();
+
+ // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
+ // inner hash of the input Web Crypto algorithm.
+ SECOidTag sign_alg_tag;
+ switch (hash.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+ break;
+ case blink::WebCryptoAlgorithmIdSha256:
+ sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+ break;
+ case blink::WebCryptoAlgorithmIdSha384:
+ sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+ break;
+ case blink::WebCryptoAlgorithmIdSha512:
+ sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+ break;
+ default:
+ return Status::ErrorUnsupported();
+ }
+
+ crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
+ if (SEC_SignData(signature_item.get(),
+ data.bytes(),
+ data.byte_length(),
+ private_key,
+ sign_alg_tag) != SECSuccess) {
+ return Status::OperationError();
+ }
+
+ buffer->assign(signature_item->data,
+ signature_item->data + signature_item->len);
+ return Status::Success();
+ }
+
+ Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const override {
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return Status::ErrorUnexpectedKeyType();
+
+ SECKEYPublicKey* public_key = PublicKeyNss::Cast(key)->key();
+
+ const blink::WebCryptoAlgorithm& hash =
+ key.algorithm().rsaHashedParams()->hash();
+
+ const SECItem signature_item = MakeSECItemForBuffer(signature);
+
+ SECOidTag hash_alg_tag;
+ switch (hash.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ hash_alg_tag = SEC_OID_SHA1;
+ break;
+ case blink::WebCryptoAlgorithmIdSha256:
+ hash_alg_tag = SEC_OID_SHA256;
+ break;
+ case blink::WebCryptoAlgorithmIdSha384:
+ hash_alg_tag = SEC_OID_SHA384;
+ break;
+ case blink::WebCryptoAlgorithmIdSha512:
+ hash_alg_tag = SEC_OID_SHA512;
+ break;
+ default:
+ return Status::ErrorUnsupported();
+ }
+
+ *signature_match =
+ SECSuccess == VFY_VerifyDataDirect(data.bytes(),
+ data.byte_length(),
+ public_key,
+ &signature_item,
+ SEC_OID_PKCS1_RSA_ENCRYPTION,
+ hash_alg_tag,
+ NULL,
+ NULL);
+ return Status::Success();
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformRsaSsaImplementation() {
+ return new RsaSsaImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/sha_nss.cc b/chromium/content/child/webcrypto/nss/sha_nss.cc
new file mode 100644
index 00000000000..78a2ea04114
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/sha_nss.cc
@@ -0,0 +1,160 @@
+// Copyright 2014 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 <sechash.h>
+#include <vector>
+
+#include "base/stl_util.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+HASH_HashType WebCryptoAlgorithmToNSSHashType(
+ blink::WebCryptoAlgorithmId algorithm) {
+ switch (algorithm) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return HASH_AlgSHA1;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return HASH_AlgSHA256;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return HASH_AlgSHA384;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return HASH_AlgSHA512;
+ default:
+ // Not a digest algorithm.
+ return HASH_AlgNULL;
+ }
+}
+
+// Implementation of blink::WebCryptoDigester, an internal Blink detail not
+// part of WebCrypto, that allows chunks of data to be streamed in before
+// computing a SHA-* digest (as opposed to ShaImplementation, which computes
+// digests over complete messages)
+class DigestorNSS : public blink::WebCryptoDigestor {
+ public:
+ explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id)
+ : hash_context_(NULL), algorithm_id_(algorithm_id) {}
+
+ ~DigestorNSS() override {
+ if (!hash_context_)
+ return;
+
+ HASH_Destroy(hash_context_);
+ hash_context_ = NULL;
+ }
+
+ bool consume(const unsigned char* data, unsigned int size) override {
+ return ConsumeWithStatus(data, size).IsSuccess();
+ }
+
+ Status ConsumeWithStatus(const unsigned char* data, unsigned int size) {
+ // Initialize everything if the object hasn't been initialized yet.
+ if (!hash_context_) {
+ Status error = Init();
+ if (!error.IsSuccess())
+ return error;
+ }
+
+ HASH_Update(hash_context_, data, size);
+
+ return Status::Success();
+ }
+
+ bool finish(unsigned char*& result_data,
+ unsigned int& result_data_size) override {
+ Status error = FinishInternal(result_, &result_data_size);
+ if (!error.IsSuccess())
+ return false;
+ result_data = result_;
+ return true;
+ }
+
+ Status FinishWithVectorAndStatus(std::vector<uint8_t>* result) {
+ if (!hash_context_)
+ return Status::ErrorUnexpected();
+
+ unsigned int result_length = HASH_ResultLenContext(hash_context_);
+ result->resize(result_length);
+ unsigned char* digest = vector_as_array(result);
+ unsigned int digest_size; // ignored
+ return FinishInternal(digest, &digest_size);
+ }
+
+ private:
+ Status Init() {
+ HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm_id_);
+
+ if (hash_type == HASH_AlgNULL)
+ return Status::ErrorUnsupported();
+
+ hash_context_ = HASH_Create(hash_type);
+ if (!hash_context_)
+ return Status::OperationError();
+
+ HASH_Begin(hash_context_);
+
+ return Status::Success();
+ }
+
+ Status FinishInternal(unsigned char* result, unsigned int* result_size) {
+ if (!hash_context_) {
+ Status error = Init();
+ if (!error.IsSuccess())
+ return error;
+ }
+
+ unsigned int hash_result_length = HASH_ResultLenContext(hash_context_);
+ DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
+
+ HASH_End(hash_context_, result, result_size, hash_result_length);
+
+ if (*result_size != hash_result_length)
+ return Status::ErrorUnexpected();
+ return Status::Success();
+ }
+
+ HASHContext* hash_context_;
+ blink::WebCryptoAlgorithmId algorithm_id_;
+ unsigned char result_[HASH_LENGTH_MAX];
+};
+
+class ShaImplementation : public AlgorithmImplementation {
+ public:
+ Status Digest(const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ DigestorNSS digestor(algorithm.id());
+ Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
+ // http://crbug.com/366427: the spec does not define any other failures for
+ // digest, so none of the subsequent errors are spec compliant.
+ if (!error.IsSuccess())
+ return error;
+ return digestor.FinishWithVectorAndStatus(buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformShaImplementation() {
+ return new ShaImplementation();
+}
+
+scoped_ptr<blink::WebCryptoDigestor> CreatePlatformDigestor(
+ blink::WebCryptoAlgorithmId algorithm) {
+ return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm));
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/sym_key_nss.cc b/chromium/content/child/webcrypto/nss/sym_key_nss.cc
new file mode 100644
index 00000000000..5066d5d91d2
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/sym_key_nss.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 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 "content/child/webcrypto/nss/sym_key_nss.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/generate_key_result.h"
+#include "content/child/webcrypto/nss/key_nss.h"
+#include "content/child/webcrypto/nss/util_nss.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+Status GenerateSecretKeyNss(const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ unsigned keylen_bytes,
+ CK_MECHANISM_TYPE mechanism,
+ GenerateKeyResult* result) {
+ DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
+ if (!slot)
+ return Status::OperationError();
+
+ crypto::ScopedPK11SymKey pk11_key(
+ PK11_KeyGen(slot.get(), mechanism, NULL, keylen_bytes, NULL));
+
+ if (!pk11_key)
+ return Status::OperationError();
+
+ if (PK11_ExtractKeyValue(pk11_key.get()) != SECSuccess)
+ return Status::OperationError();
+
+ const SECItem* key_data = PK11_GetKeyData(pk11_key.get());
+ if (!key_data)
+ return Status::OperationError();
+
+ scoped_ptr<SymKeyNss> handle(new SymKeyNss(
+ pk11_key.Pass(), CryptoData(key_data->data, key_data->len)));
+
+ result->AssignSecretKey(
+ blink::WebCryptoKey::create(handle.release(),
+ blink::WebCryptoKeyTypeSecret,
+ extractable,
+ algorithm,
+ usages));
+
+ return Status::Success();
+}
+
+Status ImportKeyRawNss(const CryptoData& key_data,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ CK_MECHANISM_TYPE mechanism,
+ CK_FLAGS flags,
+ blink::WebCryptoKey* key) {
+ DCHECK(!algorithm.isNull());
+ SECItem key_item = MakeSECItemForBuffer(key_data);
+
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
+ crypto::ScopedPK11SymKey pk11_sym_key(
+ PK11_ImportSymKeyWithFlags(slot.get(),
+ mechanism,
+ PK11_OriginUnwrap,
+ CKA_FLAGS_ONLY,
+ &key_item,
+ flags,
+ false,
+ NULL));
+ if (!pk11_sym_key.get())
+ return Status::OperationError();
+
+ scoped_ptr<SymKeyNss> handle(new SymKeyNss(pk11_sym_key.Pass(), key_data));
+
+ *key = blink::WebCryptoKey::create(handle.release(),
+ blink::WebCryptoKeyTypeSecret,
+ extractable,
+ algorithm,
+ usages);
+ return Status::Success();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/sym_key_nss.h b/chromium/content/child/webcrypto/nss/sym_key_nss.h
new file mode 100644
index 00000000000..7f1e067ac1d
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/sym_key_nss.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_NSS_SYM_KEY_NSS_H_
+#define CONTENT_CHILD_WEBCRYPTO_NSS_SYM_KEY_NSS_H_
+
+#include <pkcs11t.h>
+
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class GenerateKeyResult;
+class Status;
+
+Status GenerateSecretKeyNss(const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ unsigned keylen_bytes,
+ CK_MECHANISM_TYPE mechanism,
+ GenerateKeyResult* result);
+
+Status ImportKeyRawNss(const CryptoData& key_data,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ CK_MECHANISM_TYPE mechanism,
+ CK_FLAGS flags,
+ blink::WebCryptoKey* key);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_NSS_SYM_KEY_NSS_H_
diff --git a/chromium/content/child/webcrypto/nss/util_nss.cc b/chromium/content/child/webcrypto/nss/util_nss.cc
new file mode 100644
index 00000000000..58201cb47dc
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/util_nss.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 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 "content/child/webcrypto/nss/util_nss.h"
+
+#include "base/lazy_instance.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/platform_crypto.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+
+#if defined(USE_NSS)
+#include <dlfcn.h>
+#include <secoid.h>
+#endif
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+base::LazyInstance<NssRuntimeSupport>::Leaky g_nss_runtime_support =
+ LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
+// Creates a SECItem for the data in |buffer|. This does NOT make a copy, so
+// |buffer| should outlive the SECItem.
+SECItem MakeSECItemForBuffer(const CryptoData& buffer) {
+ SECItem item = {
+ siBuffer,
+ // NSS requires non-const data even though it is just for input.
+ const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()};
+ return item;
+}
+
+CryptoData SECItemToCryptoData(const SECItem& item) {
+ return CryptoData(item.data, item.len);
+}
+
+NssRuntimeSupport* NssRuntimeSupport::Get() {
+ return &g_nss_runtime_support.Get();
+}
+
+NssRuntimeSupport::NssRuntimeSupport() : internal_slot_does_oaep_(false) {
+#if !defined(USE_NSS)
+ // Using a bundled version of NSS that is guaranteed to have this symbol.
+ pk11_encrypt_func_ = PK11_Encrypt;
+ pk11_decrypt_func_ = PK11_Decrypt;
+ pk11_pub_encrypt_func_ = PK11_PubEncrypt;
+ pk11_priv_decrypt_func_ = PK11_PrivDecrypt;
+ internal_slot_does_oaep_ = true;
+#else
+ // Using system NSS libraries and PCKS #11 modules, which may not have the
+ // necessary function (PK11_Encrypt) or mechanism support (CKM_AES_GCM).
+
+ // If PK11_Encrypt() was successfully resolved, then NSS will support
+ // AES-GCM directly. This was introduced in NSS 3.15.
+ pk11_encrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
+ dlsym(RTLD_DEFAULT, "PK11_Encrypt"));
+ pk11_decrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
+ dlsym(RTLD_DEFAULT, "PK11_Decrypt"));
+
+ // Even though NSS's pk11wrap layer may support
+ // PK11_PubEncrypt/PK11_PubDecrypt (introduced in NSS 3.16.2), it may have
+ // loaded a softoken that does not include OAEP support.
+ pk11_pub_encrypt_func_ = reinterpret_cast<PK11_PubEncryptFunction>(
+ dlsym(RTLD_DEFAULT, "PK11_PubEncrypt"));
+ pk11_priv_decrypt_func_ = reinterpret_cast<PK11_PrivDecryptFunction>(
+ dlsym(RTLD_DEFAULT, "PK11_PrivDecrypt"));
+ if (pk11_priv_decrypt_func_ && pk11_pub_encrypt_func_) {
+ crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
+ internal_slot_does_oaep_ =
+ !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP);
+ }
+#endif
+}
+
+void PlatformInit() {
+ crypto::EnsureNSSInit();
+}
+
+AlgorithmImplementation* CreatePlatformAesCtrImplementation() {
+ // TODO(eroman): http://crbug.com/399084
+ return NULL;
+}
+
+AlgorithmImplementation* CreatePlatformRsaPssImplementation() {
+ // TODO(eroman): http://crbug.com/399090
+ return NULL;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/nss/util_nss.h b/chromium/content/child/webcrypto/nss/util_nss.h
new file mode 100644
index 00000000000..0b50178be8a
--- /dev/null
+++ b/chromium/content/child/webcrypto/nss/util_nss.h
@@ -0,0 +1,113 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_NSS_UTIL_NSS_H_
+#define CONTENT_CHILD_WEBCRYPTO_NSS_UTIL_NSS_H_
+
+#include <keythi.h>
+#include <pkcs11t.h>
+#include <seccomon.h>
+#include <secmodt.h>
+
+#include "base/lazy_instance.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+
+SECItem MakeSECItemForBuffer(const CryptoData& buffer);
+enum EncryptOrDecrypt { ENCRYPT, DECRYPT };
+
+CryptoData SECItemToCryptoData(const SECItem& item);
+
+// Signature for PK11_Encrypt and PK11_Decrypt.
+typedef SECStatus (*PK11_EncryptDecryptFunction)(PK11SymKey*,
+ CK_MECHANISM_TYPE,
+ SECItem*,
+ unsigned char*,
+ unsigned int*,
+ unsigned int,
+ const unsigned char*,
+ unsigned int);
+
+// Signature for PK11_PubEncrypt
+typedef SECStatus (*PK11_PubEncryptFunction)(SECKEYPublicKey*,
+ CK_MECHANISM_TYPE,
+ SECItem*,
+ unsigned char*,
+ unsigned int*,
+ unsigned int,
+ const unsigned char*,
+ unsigned int,
+ void*);
+
+// Signature for PK11_PrivDecrypt
+typedef SECStatus (*PK11_PrivDecryptFunction)(SECKEYPrivateKey*,
+ CK_MECHANISM_TYPE,
+ SECItem*,
+ unsigned char*,
+ unsigned int*,
+ unsigned int,
+ const unsigned char*,
+ unsigned int);
+
+// Singleton that detects whether or not AES-GCM and
+// RSA-OAEP are supported by the version of NSS being used.
+// On non-Linux platforms, Chromium embedders ship with a
+// fixed version of NSS, and these are always available.
+// However, on Linux (and ChromeOS), NSS is provided by the
+// system, and thus not all algorithms may be available
+// or be safe to use.
+class NssRuntimeSupport {
+ public:
+ bool IsAesGcmSupported() const {
+ return pk11_encrypt_func_ && pk11_decrypt_func_;
+ }
+
+ bool IsRsaOaepSupported() const {
+ return pk11_pub_encrypt_func_ && pk11_priv_decrypt_func_ &&
+ internal_slot_does_oaep_;
+ }
+
+ // Returns NULL if unsupported.
+ PK11_EncryptDecryptFunction pk11_encrypt_func() const {
+ return pk11_encrypt_func_;
+ }
+
+ // Returns NULL if unsupported.
+ PK11_EncryptDecryptFunction pk11_decrypt_func() const {
+ return pk11_decrypt_func_;
+ }
+
+ // Returns NULL if unsupported.
+ PK11_PubEncryptFunction pk11_pub_encrypt_func() const {
+ return pk11_pub_encrypt_func_;
+ }
+
+ // Returns NULL if unsupported.
+ PK11_PrivDecryptFunction pk11_priv_decrypt_func() const {
+ return pk11_priv_decrypt_func_;
+ }
+
+ static NssRuntimeSupport* Get();
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<NssRuntimeSupport>;
+
+ NssRuntimeSupport();
+
+ PK11_EncryptDecryptFunction pk11_encrypt_func_;
+ PK11_EncryptDecryptFunction pk11_decrypt_func_;
+ PK11_PubEncryptFunction pk11_pub_encrypt_func_;
+ PK11_PrivDecryptFunction pk11_priv_decrypt_func_;
+ bool internal_slot_does_oaep_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_NSS_UTIL_NSS_H_
diff --git a/chromium/content/child/webcrypto/openssl/aes_cbc_openssl.cc b/chromium/content/child/webcrypto/openssl/aes_cbc_openssl.cc
new file mode 100644
index 00000000000..860acc45d3b
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/aes_cbc_openssl.cc
@@ -0,0 +1,139 @@
+// Copyright 2014 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 <openssl/aes.h>
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) {
+ // BoringSSL does not support 192-bit AES keys.
+ switch (key_length_bytes) {
+ case 16:
+ return EVP_aes_128_cbc();
+ case 32:
+ return EVP_aes_256_cbc();
+ default:
+ return NULL;
+ }
+}
+
+Status AesCbcEncryptDecrypt(EncryptOrDecrypt cipher_operation,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
+ const std::vector<uint8_t>& raw_key =
+ SymKeyOpenSsl::Cast(key)->raw_key_data();
+
+ if (params->iv().size() != 16)
+ return Status::ErrorIncorrectSizeAesCbcIv();
+
+ // According to the openssl docs, the amount of data written may be as large
+ // as (data_size + cipher_block_size - 1), constrained to a multiple of
+ // cipher_block_size.
+ base::CheckedNumeric<int> output_max_len = data.byte_length();
+ output_max_len += AES_BLOCK_SIZE - 1;
+ if (!output_max_len.IsValid())
+ return Status::ErrorDataTooLarge();
+
+ const unsigned remainder = output_max_len.ValueOrDie() % AES_BLOCK_SIZE;
+ if (remainder != 0)
+ output_max_len += AES_BLOCK_SIZE - remainder;
+ if (!output_max_len.IsValid())
+ return Status::ErrorDataTooLarge();
+
+ // Note: PKCS padding is enabled by default
+ crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>::Type context(
+ EVP_CIPHER_CTX_new());
+
+ if (!context.get())
+ return Status::OperationError();
+
+ const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size());
+ DCHECK(cipher);
+
+ if (!EVP_CipherInit_ex(context.get(),
+ cipher,
+ NULL,
+ &raw_key[0],
+ params->iv().data(),
+ cipher_operation)) {
+ return Status::OperationError();
+ }
+
+ buffer->resize(output_max_len.ValueOrDie());
+
+ unsigned char* const buffer_data = vector_as_array(buffer);
+
+ int output_len = 0;
+ if (!EVP_CipherUpdate(context.get(),
+ buffer_data,
+ &output_len,
+ data.bytes(),
+ data.byte_length()))
+ return Status::OperationError();
+ int final_output_chunk_len = 0;
+ if (!EVP_CipherFinal_ex(
+ context.get(), buffer_data + output_len, &final_output_chunk_len)) {
+ return Status::OperationError();
+ }
+
+ const unsigned int final_output_len =
+ static_cast<unsigned int>(output_len) +
+ static_cast<unsigned int>(final_output_chunk_len);
+
+ buffer->resize(final_output_len);
+
+ return Status::Success();
+}
+
+class AesCbcImplementation : public AesAlgorithm {
+ public:
+ AesCbcImplementation() : AesAlgorithm("CBC") {}
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesCbcEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesCbcEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesCbcImplementation() {
+ return new AesCbcImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/aes_ctr_openssl.cc b/chromium/content/child/webcrypto/openssl/aes_ctr_openssl.cc
new file mode 100644
index 00000000000..82408b2559a
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/aes_ctr_openssl.cc
@@ -0,0 +1,288 @@
+// Copyright 2014 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 <openssl/aes.h>
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) {
+ // BoringSSL does not support 192-bit AES keys.
+ switch (key_length_bytes) {
+ case 16:
+ return EVP_aes_128_ctr();
+ case 32:
+ return EVP_aes_256_ctr();
+ default:
+ return NULL;
+ }
+}
+
+// Encrypts/decrypts given a 128-bit counter.
+//
+// |output| must be a pointer to a buffer which has a length of at least
+// |input.byte_length()|.
+Status AesCtrEncrypt128BitCounter(const EVP_CIPHER* cipher,
+ const CryptoData& raw_key,
+ const CryptoData& input,
+ const CryptoData& counter,
+ uint8_t* output) {
+ DCHECK(cipher);
+ DCHECK_EQ(16u, counter.byte_length());
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>::Type context(
+ EVP_CIPHER_CTX_new());
+
+ if (!context.get())
+ return Status::OperationError();
+
+ if (!EVP_CipherInit_ex(context.get(),
+ cipher,
+ NULL,
+ raw_key.bytes(),
+ counter.bytes(),
+ ENCRYPT)) {
+ return Status::OperationError();
+ }
+
+ int output_len = 0;
+ if (!EVP_CipherUpdate(context.get(),
+ output,
+ &output_len,
+ input.bytes(),
+ input.byte_length())) {
+ return Status::OperationError();
+ }
+ int final_output_chunk_len = 0;
+ if (!EVP_CipherFinal_ex(
+ context.get(), output + output_len, &final_output_chunk_len)) {
+ return Status::OperationError();
+ }
+
+ output_len += final_output_chunk_len;
+ if (static_cast<unsigned int>(output_len) != input.byte_length())
+ return Status::ErrorUnexpected();
+
+ return Status::Success();
+}
+
+// Returns ceil(a/b), where a and b are integers.
+template <typename T>
+T CeilDiv(T a, T b) {
+ return a == 0 ? 0 : 1 + (a - 1) / b;
+}
+
+// Extracts the counter as a BIGNUM. The counter is the rightmost
+// "counter_length_bits" of the block, interpreted as a big-endian number.
+crypto::ScopedBIGNUM GetCounter(const CryptoData& counter_block,
+ unsigned int counter_length_bits) {
+ unsigned int counter_length_remainder_bits = (counter_length_bits % 8);
+
+ // If the counter is a multiple of 8 bits then can call BN_bin2bn() directly.
+ if (counter_length_remainder_bits == 0) {
+ unsigned int byte_length = counter_length_bits / 8;
+ return crypto::ScopedBIGNUM(BN_bin2bn(
+ counter_block.bytes() + counter_block.byte_length() - byte_length,
+ byte_length,
+ NULL));
+ }
+
+ // Otherwise make a copy of the counter and zero out the topmost bits so
+ // BN_bin2bn() can be called with a byte stream.
+ unsigned int byte_length = CeilDiv(counter_length_bits, 8u);
+ std::vector<uint8_t> counter(
+ counter_block.bytes() + counter_block.byte_length() - byte_length,
+ counter_block.bytes() + counter_block.byte_length());
+ counter[0] &= ~(0xFF << counter_length_remainder_bits);
+
+ return crypto::ScopedBIGNUM(
+ BN_bin2bn(&counter.front(), counter.size(), NULL));
+}
+
+// Returns a counter block with the counter bits all set all zero.
+std::vector<uint8_t> BlockWithZeroedCounter(const CryptoData& counter_block,
+ unsigned int counter_length_bits) {
+ unsigned int counter_length_bytes = counter_length_bits / 8;
+ unsigned int counter_length_bits_remainder = counter_length_bits % 8;
+
+ std::vector<uint8_t> new_counter_block(
+ counter_block.bytes(),
+ counter_block.bytes() + counter_block.byte_length());
+
+ unsigned int index = new_counter_block.size() - counter_length_bytes;
+ memset(&new_counter_block.front() + index, 0, counter_length_bytes);
+
+ if (counter_length_bits_remainder) {
+ new_counter_block[index - 1] &= 0xFF << counter_length_bits_remainder;
+ }
+
+ return new_counter_block;
+}
+
+// This function does encryption/decryption for AES-CTR (encryption and
+// decryption are the same).
+//
+// BoringSSL's interface for AES-CTR differs from that of WebCrypto. In
+// WebCrypto the caller specifies a 16-byte counter block and designates how
+// many of the right-most X bits to use as a big-endian counter. Whereas in
+// BoringSSL the entire counter block is interpreted as a 128-bit counter.
+//
+// In AES-CTR, the counter block MUST be unique across all messages that are
+// encrypted/decrypted. WebCrypto expects that the counter can start at any
+// value, and is therefore permitted to wrap around to zero on overflow.
+//
+// Some care is taken to fail if the counter wraps back to an earlier value.
+// However this protection is only enforced during a *single* call to
+// encrypt/decrypt.
+Status AesCtrEncryptDecrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ const blink::WebCryptoAesCtrParams* params = algorithm.aesCtrParams();
+ const std::vector<uint8_t>& raw_key =
+ SymKeyOpenSsl::Cast(key)->raw_key_data();
+
+ if (params->counter().size() != 16)
+ return Status::ErrorIncorrectSizeAesCtrCounter();
+
+ unsigned int counter_length_bits = params->lengthBits();
+ if (counter_length_bits < 1 || counter_length_bits > 128)
+ return Status::ErrorInvalidAesCtrCounterLength();
+
+ // The output of AES-CTR is the same size as the input. However BoringSSL
+ // expects buffer sizes as an "int".
+ base::CheckedNumeric<int> output_max_len = data.byte_length();
+ if (!output_max_len.IsValid())
+ return Status::ErrorDataTooLarge();
+
+ const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size());
+ if (!cipher)
+ return Status::ErrorUnexpected();
+
+ const CryptoData counter_block(params->counter());
+ buffer->resize(output_max_len.ValueOrDie());
+
+ // The total number of possible counter values is pow(2, counter_length_bits)
+ crypto::ScopedBIGNUM num_counter_values(BN_new());
+ if (!BN_lshift(num_counter_values.get(), BN_value_one(), counter_length_bits))
+ return Status::ErrorUnexpected();
+
+ crypto::ScopedBIGNUM current_counter =
+ GetCounter(counter_block, counter_length_bits);
+
+ // The number of AES blocks needed for encryption/decryption. The counter is
+ // incremented this many times.
+ crypto::ScopedBIGNUM num_output_blocks(BN_new());
+ if (!BN_set_word(
+ num_output_blocks.get(),
+ CeilDiv(buffer->size(), static_cast<size_t>(AES_BLOCK_SIZE)))) {
+ return Status::ErrorUnexpected();
+ }
+
+ // If the counter is going to be incremented more times than there are counter
+ // values, fail. (Repeating values of the counter block is bad).
+ if (BN_cmp(num_output_blocks.get(), num_counter_values.get()) > 0)
+ return Status::ErrorAesCtrInputTooLongCounterRepeated();
+
+ // This is the number of blocks that can be successfully encrypted without
+ // overflowing the counter. Encrypting the subsequent block will need to
+ // reset the counter to zero.
+ crypto::ScopedBIGNUM num_blocks_until_reset(BN_new());
+
+ if (!BN_sub(num_blocks_until_reset.get(),
+ num_counter_values.get(),
+ current_counter.get())) {
+ return Status::ErrorUnexpected();
+ }
+
+ // If the counter can be incremented for the entire input without
+ // wrapping-around, do it as a single call into BoringSSL.
+ if (BN_cmp(num_blocks_until_reset.get(), num_output_blocks.get()) >= 0) {
+ return AesCtrEncrypt128BitCounter(cipher,
+ CryptoData(raw_key),
+ data,
+ counter_block,
+ vector_as_array(buffer));
+ }
+
+ // Otherwise the encryption needs to be done in 2 parts. The first part using
+ // the current counter_block, and the next part resetting the counter portion
+ // of the block to zero.
+
+ // This is guaranteed to fit in an "unsigned int" because input size in bytes
+ // fits in an "unsigned int".
+ BN_ULONG num_blocks_part1 = BN_get_word(num_blocks_until_reset.get());
+ BN_ULONG input_size_part1 = num_blocks_part1 * AES_BLOCK_SIZE;
+ DCHECK_LT(input_size_part1, data.byte_length());
+
+ // Encrypt the first part (before wrap-around).
+ Status status =
+ AesCtrEncrypt128BitCounter(cipher,
+ CryptoData(raw_key),
+ CryptoData(data.bytes(), input_size_part1),
+ counter_block,
+ vector_as_array(buffer));
+ if (status.IsError())
+ return status;
+
+ // Encrypt the second part (after wrap-around).
+ std::vector<uint8_t> counter_block_part2 =
+ BlockWithZeroedCounter(counter_block, counter_length_bits);
+
+ return AesCtrEncrypt128BitCounter(
+ cipher,
+ CryptoData(raw_key),
+ CryptoData(data.bytes() + input_size_part1,
+ data.byte_length() - input_size_part1),
+ CryptoData(counter_block_part2),
+ vector_as_array(buffer) + input_size_part1);
+}
+
+class AesCtrImplementation : public AesAlgorithm {
+ public:
+ AesCtrImplementation() : AesAlgorithm("CTR") {}
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesCtrEncryptDecrypt(algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesCtrEncryptDecrypt(algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesCtrImplementation() {
+ return new AesCtrImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/aes_gcm_openssl.cc b/chromium/content/child/webcrypto/openssl/aes_gcm_openssl.cc
new file mode 100644
index 00000000000..7c783c9bdcf
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/aes_gcm_openssl.cc
@@ -0,0 +1,88 @@
+// Copyright 2014 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 <vector>
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const EVP_AEAD* GetAesGcmAlgorithmFromKeySize(unsigned int key_size_bytes) {
+ switch (key_size_bytes) {
+ case 16:
+ return EVP_aead_aes_128_gcm();
+ case 32:
+ return EVP_aead_aes_256_gcm();
+ default:
+ return NULL;
+ }
+}
+
+Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ const std::vector<uint8_t>& raw_key =
+ SymKeyOpenSsl::Cast(key)->raw_key_data();
+ const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
+
+ unsigned int tag_length_bits;
+ Status status = GetAesGcmTagLengthInBits(params, &tag_length_bits);
+ if (status.IsError())
+ return status;
+
+ return AeadEncryptDecrypt(mode,
+ raw_key,
+ data,
+ tag_length_bits / 8,
+ CryptoData(params->iv()),
+ CryptoData(params->optionalAdditionalData()),
+ GetAesGcmAlgorithmFromKeySize(raw_key.size()),
+ buffer);
+}
+
+class AesGcmImplementation : public AesAlgorithm {
+ public:
+ AesGcmImplementation() : AesAlgorithm("GCM") {}
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesGcmEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesGcmEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesGcmImplementation() {
+ return new AesGcmImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/aes_key_openssl.cc b/chromium/content/child/webcrypto/openssl/aes_key_openssl.cc
new file mode 100644
index 00000000000..14fa24e35c2
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/aes_key_openssl.cc
@@ -0,0 +1,124 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/aes_key_openssl.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/sym_key_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+AesAlgorithm::AesAlgorithm(blink::WebCryptoKeyUsageMask all_key_usages,
+ const std::string& jwk_suffix)
+ : all_key_usages_(all_key_usages), jwk_suffix_(jwk_suffix) {
+}
+
+AesAlgorithm::AesAlgorithm(const std::string& jwk_suffix)
+ : all_key_usages_(blink::WebCryptoKeyUsageEncrypt |
+ blink::WebCryptoKeyUsageDecrypt |
+ blink::WebCryptoKeyUsageWrapKey |
+ blink::WebCryptoKeyUsageUnwrapKey),
+ jwk_suffix_(jwk_suffix) {
+}
+
+Status AesAlgorithm::GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const {
+ Status status = CheckKeyCreationUsages(all_key_usages_, usages);
+ if (status.IsError())
+ return status;
+
+ unsigned int keylen_bits;
+ status = GetAesKeyGenLengthInBits(algorithm.aesKeyGenParams(), &keylen_bits);
+ if (status.IsError())
+ return status;
+
+ return GenerateSecretKeyOpenSsl(
+ blink::WebCryptoKeyAlgorithm::createAes(algorithm.id(), keylen_bits),
+ extractable,
+ usages,
+ keylen_bits / 8,
+ result);
+}
+
+Status AesAlgorithm::VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ case blink::WebCryptoKeyFormatJwk:
+ return CheckKeyCreationUsages(all_key_usages_, usages);
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+}
+
+Status AesAlgorithm::ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ const unsigned int keylen_bytes = key_data.byte_length();
+ Status status = VerifyAesKeyLengthForImport(keylen_bytes);
+ if (status.IsError())
+ return status;
+
+ // No possibility of overflow.
+ unsigned int keylen_bits = keylen_bytes * 8;
+
+ return ImportKeyRawOpenSsl(
+ key_data,
+ blink::WebCryptoKeyAlgorithm::createAes(algorithm.id(), keylen_bits),
+ extractable,
+ usages,
+ key);
+}
+
+Status AesAlgorithm::ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ std::vector<uint8_t> raw_data;
+ Status status = ReadAesSecretKeyJwk(
+ key_data, jwk_suffix_, extractable, usages, &raw_data);
+ if (status.IsError())
+ return status;
+
+ return ImportKeyRaw(
+ CryptoData(raw_data), algorithm, extractable, usages, key);
+}
+
+Status AesAlgorithm::ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
+ return Status::Success();
+}
+
+Status AesAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ const std::vector<uint8_t>& raw_data =
+ SymKeyOpenSsl::Cast(key)->raw_key_data();
+
+ WriteSecretKeyJwk(CryptoData(raw_data),
+ MakeJwkAesAlgorithmName(jwk_suffix_, raw_data.size()),
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/aes_key_openssl.h b/chromium/content/child/webcrypto/openssl/aes_key_openssl.h
new file mode 100644
index 00000000000..206a1e2bcfc
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/aes_key_openssl.h
@@ -0,0 +1,67 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_OPENSSL_AES_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_AES_OPENSSL_H_
+
+#include "content/child/webcrypto/algorithm_implementation.h"
+
+namespace content {
+
+namespace webcrypto {
+
+// Base class for AES algorithms that provides the implementation for key
+// creation and export.
+class AesAlgorithm : public AlgorithmImplementation {
+ public:
+ // |all_key_usages| is the set of all WebCrypto key usages that are
+ // allowed for imported or generated keys. |jwk_suffix| is the suffix
+ // used when constructing JWK names for the algorithm. For instance A128CBC
+ // is the JWK name for 128-bit AES-CBC. The |jwk_suffix| in this case would
+ // be "CBC".
+ AesAlgorithm(blink::WebCryptoKeyUsageMask all_key_usages,
+ const std::string& jwk_suffix);
+
+ // This is the same as the other AesAlgorithm constructor where
+ // |all_key_usages| is pre-filled to values for encryption/decryption
+ // algorithms (supports usages for: encrypt, decrypt, wrap, unwrap).
+ explicit AesAlgorithm(const std::string& jwk_suffix);
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override;
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override;
+
+ Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ private:
+ const blink::WebCryptoKeyUsageMask all_key_usages_;
+ const std::string jwk_suffix_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_AES_OPENSSL_H_
diff --git a/chromium/content/child/webcrypto/openssl/aes_kw_openssl.cc b/chromium/content/child/webcrypto/openssl/aes_kw_openssl.cc
new file mode 100644
index 00000000000..c612d53dc96
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/aes_kw_openssl.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 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 <vector>
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/aes_key_openssl.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const EVP_AEAD* GetAesKwAlgorithmFromKeySize(unsigned int key_size_bytes) {
+ switch (key_size_bytes) {
+ case 16:
+ return EVP_aead_aes_128_key_wrap();
+ case 32:
+ return EVP_aead_aes_256_key_wrap();
+ default:
+ return NULL;
+ }
+}
+
+Status AesKwEncryptDecrypt(EncryptOrDecrypt mode,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ // These length checks are done so the returned error matches that of NSS
+ // implementation. Other than giving a more specific error, these are not
+ // required.
+ if ((mode == ENCRYPT && data.byte_length() < 16) ||
+ (mode == DECRYPT && data.byte_length() < 24)) {
+ return Status::ErrorDataTooSmall();
+ }
+ if (data.byte_length() % 8)
+ return Status::ErrorInvalidAesKwDataLength();
+
+ const std::vector<uint8_t>& raw_key =
+ SymKeyOpenSsl::Cast(key)->raw_key_data();
+
+ return AeadEncryptDecrypt(mode,
+ raw_key,
+ data,
+ 8, // tag_length_bytes
+ CryptoData(), // iv
+ CryptoData(), // additional_data
+ GetAesKwAlgorithmFromKeySize(raw_key.size()),
+ buffer);
+}
+
+class AesKwImplementation : public AesAlgorithm {
+ public:
+ AesKwImplementation()
+ : AesAlgorithm(
+ blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
+ "KW") {}
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesKwEncryptDecrypt(ENCRYPT, algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return AesKwEncryptDecrypt(DECRYPT, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformAesKwImplementation() {
+ return new AesKwImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/hmac_openssl.cc b/chromium/content/child/webcrypto/openssl/hmac_openssl.cc
new file mode 100644
index 00000000000..77b5ccfcf93
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/hmac_openssl.cc
@@ -0,0 +1,216 @@
+// Copyright 2014 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 <openssl/hmac.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_math.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/sym_key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/secure_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+const blink::WebCryptoKeyUsageMask kAllKeyUsages =
+ blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
+
+Status SignHmac(const std::vector<uint8_t>& raw_key,
+ const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ const EVP_MD* digest_algorithm = GetDigest(hash.id());
+ if (!digest_algorithm)
+ return Status::ErrorUnsupported();
+ unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm);
+
+ // OpenSSL wierdness here.
+ // First, HMAC() needs a void* for the key data, so make one up front as a
+ // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
+ // which will result if the raw_key vector is empty; an entirely valid
+ // case. Handle this specific case by pointing to a fresh array.
+ const unsigned char null_key[] = {0};
+ const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
+
+ buffer->resize(hmac_expected_length);
+ crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
+ vector_as_array(buffer), hmac_expected_length);
+
+ unsigned int hmac_actual_length;
+ unsigned char* const success = HMAC(digest_algorithm,
+ raw_key_voidp,
+ raw_key.size(),
+ data.bytes(),
+ data.byte_length(),
+ hmac_result.safe_buffer(),
+ &hmac_actual_length);
+ if (!success || hmac_actual_length != hmac_expected_length)
+ return Status::OperationError();
+
+ return Status::Success();
+}
+
+class HmacImplementation : public AlgorithmImplementation {
+ public:
+ HmacImplementation() {}
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override {
+ Status status = CheckKeyCreationUsages(kAllKeyUsages, usages);
+ if (status.IsError())
+ return status;
+
+ const blink::WebCryptoHmacKeyGenParams* params =
+ algorithm.hmacKeyGenParams();
+
+ unsigned int keylen_bits = 0;
+ status = GetHmacKeyGenLengthInBits(params, &keylen_bits);
+ if (status.IsError())
+ return status;
+
+ return GenerateSecretKeyOpenSsl(blink::WebCryptoKeyAlgorithm::createHmac(
+ params->hash().id(), keylen_bits),
+ extractable,
+ usages,
+ keylen_bits / 8,
+ result);
+ }
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override {
+ switch (format) {
+ case blink::WebCryptoKeyFormatRaw:
+ case blink::WebCryptoKeyFormatJwk:
+ return CheckKeyCreationUsages(kAllKeyUsages, usages);
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+ }
+
+ Status ImportKeyRaw(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override {
+ const blink::WebCryptoAlgorithm& hash =
+ algorithm.hmacImportParams()->hash();
+
+ base::CheckedNumeric<unsigned int> keylen_bits(key_data.byte_length());
+ keylen_bits *= 8;
+
+ if (!keylen_bits.IsValid())
+ return Status::ErrorDataTooLarge();
+
+ return ImportKeyRawOpenSsl(key_data,
+ blink::WebCryptoKeyAlgorithm::createHmac(
+ hash.id(), keylen_bits.ValueOrDie()),
+ extractable,
+ usages,
+ key);
+ }
+
+ Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override {
+ const char* algorithm_name =
+ GetJwkHmacAlgorithmName(algorithm.hmacImportParams()->hash().id());
+ if (!algorithm_name)
+ return Status::ErrorUnexpected();
+
+ std::vector<uint8_t> raw_data;
+ Status status = ReadSecretKeyJwk(
+ key_data, algorithm_name, extractable, usages, &raw_data);
+ if (status.IsError())
+ return status;
+
+ return ImportKeyRaw(
+ CryptoData(raw_data), algorithm, extractable, usages, key);
+ }
+
+ Status ExportKeyRaw(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override {
+ *buffer = SymKeyOpenSsl::Cast(key)->raw_key_data();
+ return Status::Success();
+ }
+
+ Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override {
+ SymKeyOpenSsl* sym_key = SymKeyOpenSsl::Cast(key);
+ const std::vector<uint8_t>& raw_data = sym_key->raw_key_data();
+
+ const char* algorithm_name =
+ GetJwkHmacAlgorithmName(key.algorithm().hmacParams()->hash().id());
+ if (!algorithm_name)
+ return Status::ErrorUnexpected();
+
+ WriteSecretKeyJwk(CryptoData(raw_data),
+ algorithm_name,
+ key.extractable(),
+ key.usages(),
+ buffer);
+
+ return Status::Success();
+ }
+
+ Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ const blink::WebCryptoAlgorithm& hash =
+ key.algorithm().hmacParams()->hash();
+
+ return SignHmac(
+ SymKeyOpenSsl::Cast(key)->raw_key_data(), hash, data, buffer);
+ }
+
+ Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const override {
+ std::vector<uint8_t> result;
+ Status status = Sign(algorithm, key, data, &result);
+
+ if (status.IsError())
+ return status;
+
+ // Do not allow verification of truncated MACs.
+ *signature_match = result.size() == signature.byte_length() &&
+ crypto::SecureMemEqual(vector_as_array(&result),
+ signature.bytes(),
+ signature.byte_length());
+
+ return Status::Success();
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformHmacImplementation() {
+ return new HmacImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/key_openssl.cc b/chromium/content/child/webcrypto/openssl/key_openssl.cc
new file mode 100644
index 00000000000..9ea1f20428c
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/key_openssl.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/key_openssl.h"
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+
+namespace content {
+
+namespace webcrypto {
+
+KeyOpenSsl::KeyOpenSsl(const CryptoData& serialized_key_data)
+ : serialized_key_data_(
+ serialized_key_data.bytes(),
+ serialized_key_data.bytes() + serialized_key_data.byte_length()) {
+}
+
+KeyOpenSsl::~KeyOpenSsl() {
+}
+
+SymKeyOpenSsl* KeyOpenSsl::AsSymKey() {
+ return NULL;
+}
+
+AsymKeyOpenSsl* KeyOpenSsl::AsAsymKey() {
+ return NULL;
+}
+
+SymKeyOpenSsl::~SymKeyOpenSsl() {
+}
+
+SymKeyOpenSsl* SymKeyOpenSsl::Cast(const blink::WebCryptoKey& key) {
+ KeyOpenSsl* platform_key = reinterpret_cast<KeyOpenSsl*>(key.handle());
+ return platform_key->AsSymKey();
+}
+
+SymKeyOpenSsl* SymKeyOpenSsl::AsSymKey() {
+ return this;
+}
+
+SymKeyOpenSsl::SymKeyOpenSsl(const CryptoData& raw_key_data)
+ : KeyOpenSsl(raw_key_data) {
+}
+
+AsymKeyOpenSsl::~AsymKeyOpenSsl() {
+}
+
+AsymKeyOpenSsl* AsymKeyOpenSsl::Cast(const blink::WebCryptoKey& key) {
+ return reinterpret_cast<KeyOpenSsl*>(key.handle())->AsAsymKey();
+}
+
+AsymKeyOpenSsl* AsymKeyOpenSsl::AsAsymKey() {
+ return this;
+}
+
+AsymKeyOpenSsl::AsymKeyOpenSsl(crypto::ScopedEVP_PKEY key,
+ const CryptoData& serialized_key_data)
+ : KeyOpenSsl(serialized_key_data), key_(key.Pass()) {
+}
+
+bool PlatformSerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8_t>* key_data) {
+ const KeyOpenSsl* openssl_key = static_cast<KeyOpenSsl*>(key.handle());
+ *key_data = openssl_key->serialized_key_data();
+ return true;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/key_openssl.h b/chromium/content/child/webcrypto/openssl/key_openssl.h
new file mode 100644
index 00000000000..48163c18ac0
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/key_openssl.h
@@ -0,0 +1,83 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_OPENSSL_KEY_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_KEY_OPENSSL_H_
+
+#include <openssl/ossl_typ.h>
+#include <stdint.h>
+#include <vector>
+
+#include "base/macros.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoKey.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class AsymKeyOpenSsl;
+class SymKeyOpenSsl;
+
+// Base key class for all OpenSSL keys, used to safely cast between types. Each
+// key maintains a copy of its serialized form in either 'raw', 'pkcs8', or
+// 'spki' format. This is to allow structured cloning of keys synchronously from
+// the target Blink thread without having to lock access to the key.
+class KeyOpenSsl : public blink::WebCryptoKeyHandle {
+ public:
+ explicit KeyOpenSsl(const CryptoData& serialized_key_data);
+ ~KeyOpenSsl() override;
+
+ virtual SymKeyOpenSsl* AsSymKey();
+ virtual AsymKeyOpenSsl* AsAsymKey();
+
+ const std::vector<uint8_t>& serialized_key_data() const {
+ return serialized_key_data_;
+ }
+
+ private:
+ const std::vector<uint8_t> serialized_key_data_;
+};
+
+class SymKeyOpenSsl : public KeyOpenSsl {
+ public:
+ ~SymKeyOpenSsl() override;
+ explicit SymKeyOpenSsl(const CryptoData& raw_key_data);
+
+ static SymKeyOpenSsl* Cast(const blink::WebCryptoKey& key);
+
+ SymKeyOpenSsl* AsSymKey() override;
+
+ const std::vector<uint8_t>& raw_key_data() const {
+ return serialized_key_data();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SymKeyOpenSsl);
+};
+
+class AsymKeyOpenSsl : public KeyOpenSsl {
+ public:
+ ~AsymKeyOpenSsl() override;
+ AsymKeyOpenSsl(crypto::ScopedEVP_PKEY key,
+ const CryptoData& serialized_key_data);
+
+ static AsymKeyOpenSsl* Cast(const blink::WebCryptoKey& key);
+
+ AsymKeyOpenSsl* AsAsymKey() override;
+
+ EVP_PKEY* key() { return key_.get(); }
+
+ private:
+ crypto::ScopedEVP_PKEY key_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsymKeyOpenSsl);
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_KEY_OPENSSL_H_
diff --git a/chromium/content/child/webcrypto/openssl/rsa_key_openssl.cc b/chromium/content/child/webcrypto/openssl/rsa_key_openssl.cc
new file mode 100644
index 00000000000..6710c31b0ca
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_key_openssl.cc
@@ -0,0 +1,389 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/rsa_key_openssl.h"
+
+#include <openssl/evp.h>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/generate_key_result.h"
+#include "content/child/webcrypto/jwk.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// Creates a blink::WebCryptoAlgorithm having the modulus length and public
+// exponent of |key|.
+Status CreateRsaHashedKeyAlgorithm(
+ blink::WebCryptoAlgorithmId rsa_algorithm,
+ blink::WebCryptoAlgorithmId hash_algorithm,
+ EVP_PKEY* key,
+ blink::WebCryptoKeyAlgorithm* key_algorithm) {
+ DCHECK_EQ(EVP_PKEY_RSA, EVP_PKEY_id(key));
+
+ crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(key));
+ if (!rsa.get())
+ return Status::ErrorUnexpected();
+
+ unsigned int modulus_length_bits = BN_num_bits(rsa.get()->n);
+
+ // Convert the public exponent to big-endian representation.
+ std::vector<uint8_t> e(BN_num_bytes(rsa.get()->e));
+ if (e.size() == 0)
+ return Status::ErrorUnexpected();
+ if (e.size() != BN_bn2bin(rsa.get()->e, &e[0]))
+ return Status::ErrorUnexpected();
+
+ *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(
+ rsa_algorithm, modulus_length_bits, &e[0], e.size(), hash_algorithm);
+
+ return Status::Success();
+}
+
+// Creates a WebCryptoKey that wraps |private_key|.
+Status CreateWebCryptoRsaPrivateKey(
+ crypto::ScopedEVP_PKEY private_key,
+ const blink::WebCryptoAlgorithmId rsa_algorithm_id,
+ const blink::WebCryptoAlgorithm& hash,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ Status status = CreateRsaHashedKeyAlgorithm(
+ rsa_algorithm_id, hash.id(), private_key.get(), &key_algorithm);
+ if (status.IsError())
+ return status;
+
+ return CreateWebCryptoPrivateKey(private_key.Pass(), key_algorithm,
+ extractable, usages, key);
+}
+
+// Creates a WebCryptoKey that wraps |public_key|.
+Status CreateWebCryptoRsaPublicKey(
+ crypto::ScopedEVP_PKEY public_key,
+ const blink::WebCryptoAlgorithmId rsa_algorithm_id,
+ const blink::WebCryptoAlgorithm& hash,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ blink::WebCryptoKeyAlgorithm key_algorithm;
+ Status status = CreateRsaHashedKeyAlgorithm(
+ rsa_algorithm_id, hash.id(), public_key.get(), &key_algorithm);
+ if (status.IsError())
+ return status;
+
+ return CreateWebCryptoPublicKey(public_key.Pass(), key_algorithm, extractable,
+ usages, key);
+}
+
+Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const JwkRsaInfo& params,
+ blink::WebCryptoKey* key) {
+ crypto::ScopedRSA rsa(RSA_new());
+
+ rsa->n = CreateBIGNUM(params.n);
+ rsa->e = CreateBIGNUM(params.e);
+ rsa->d = CreateBIGNUM(params.d);
+ rsa->p = CreateBIGNUM(params.p);
+ rsa->q = CreateBIGNUM(params.q);
+ rsa->dmp1 = CreateBIGNUM(params.dp);
+ rsa->dmq1 = CreateBIGNUM(params.dq);
+ rsa->iqmp = CreateBIGNUM(params.qi);
+
+ if (!rsa->n || !rsa->e || !rsa->d || !rsa->p || !rsa->q || !rsa->dmp1 ||
+ !rsa->dmq1 || !rsa->iqmp) {
+ return Status::OperationError();
+ }
+
+ // TODO(eroman): This should really be a DataError, however for compatibility
+ // with NSS it is an OperationError.
+ if (!RSA_check_key(rsa.get()))
+ return Status::OperationError();
+
+ // Create a corresponding EVP_PKEY.
+ crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
+ if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
+ return Status::OperationError();
+
+ return CreateWebCryptoRsaPrivateKey(pkey.Pass(), algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash(),
+ extractable, usages, key);
+}
+
+Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const CryptoData& n,
+ const CryptoData& e,
+ blink::WebCryptoKey* key) {
+ crypto::ScopedRSA rsa(RSA_new());
+
+ rsa->n = BN_bin2bn(n.bytes(), n.byte_length(), NULL);
+ rsa->e = BN_bin2bn(e.bytes(), e.byte_length(), NULL);
+
+ if (!rsa->n || !rsa->e)
+ return Status::OperationError();
+
+ // Create a corresponding EVP_PKEY.
+ crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
+ if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
+ return Status::OperationError();
+
+ return CreateWebCryptoRsaPublicKey(pkey.Pass(), algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash(),
+ extractable, usages, key);
+}
+
+} // namespace
+
+Status RsaHashedAlgorithm::GenerateKey(
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask combined_usages,
+ GenerateKeyResult* result) const {
+ Status status = CheckKeyCreationUsages(
+ all_public_key_usages_ | all_private_key_usages_, combined_usages);
+ if (status.IsError())
+ return status;
+
+ const blink::WebCryptoKeyUsageMask public_usages =
+ combined_usages & all_public_key_usages_;
+ const blink::WebCryptoKeyUsageMask private_usages =
+ combined_usages & all_private_key_usages_;
+
+ const blink::WebCryptoRsaHashedKeyGenParams* params =
+ algorithm.rsaHashedKeyGenParams();
+
+ unsigned int public_exponent = 0;
+ unsigned int modulus_length_bits = 0;
+ status =
+ GetRsaKeyGenParameters(params, &public_exponent, &modulus_length_bits);
+ if (status.IsError())
+ return status;
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ // Generate an RSA key pair.
+ crypto::ScopedRSA rsa_private_key(RSA_new());
+ crypto::ScopedBIGNUM bn(BN_new());
+ if (!rsa_private_key.get() || !bn.get() ||
+ !BN_set_word(bn.get(), public_exponent)) {
+ return Status::OperationError();
+ }
+
+ if (!RSA_generate_key_ex(
+ rsa_private_key.get(), modulus_length_bits, bn.get(), NULL)) {
+ return Status::OperationError();
+ }
+
+ // Construct an EVP_PKEY for the private key.
+ crypto::ScopedEVP_PKEY private_pkey(EVP_PKEY_new());
+ if (!private_pkey ||
+ !EVP_PKEY_set1_RSA(private_pkey.get(), rsa_private_key.get())) {
+ return Status::OperationError();
+ }
+
+ // Construct an EVP_PKEY for the public key.
+ crypto::ScopedRSA rsa_public_key(RSAPublicKey_dup(rsa_private_key.get()));
+ crypto::ScopedEVP_PKEY public_pkey(EVP_PKEY_new());
+ if (!public_pkey ||
+ !EVP_PKEY_set1_RSA(public_pkey.get(), rsa_public_key.get())) {
+ return Status::OperationError();
+ }
+
+ blink::WebCryptoKey public_key;
+ blink::WebCryptoKey private_key;
+
+ // Note that extractable is unconditionally set to true. This is because per
+ // the WebCrypto spec generated public keys are always public.
+ status = CreateWebCryptoRsaPublicKey(public_pkey.Pass(), algorithm.id(),
+ params->hash(), true, public_usages,
+ &public_key);
+ if (status.IsError())
+ return status;
+
+ status = CreateWebCryptoRsaPrivateKey(private_pkey.Pass(), algorithm.id(),
+ params->hash(), extractable,
+ private_usages, &private_key);
+ if (status.IsError())
+ return status;
+
+ result->AssignKeyPair(public_key, private_key);
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const {
+ switch (format) {
+ case blink::WebCryptoKeyFormatSpki:
+ return CheckKeyCreationUsages(all_public_key_usages_, usages);
+ case blink::WebCryptoKeyFormatPkcs8:
+ return CheckKeyCreationUsages(all_private_key_usages_, usages);
+ case blink::WebCryptoKeyFormatJwk:
+ // The JWK could represent either a public key or private key. The usages
+ // must make sense for one of the two. The usages will be checked again by
+ // ImportKeyJwk() once the key type has been determined.
+ if (CheckKeyCreationUsages(all_private_key_usages_, usages).IsSuccess() ||
+ CheckKeyCreationUsages(all_public_key_usages_, usages).IsSuccess()) {
+ return Status::Success();
+ }
+ return Status::ErrorCreateKeyBadUsages();
+ default:
+ return Status::ErrorUnsupportedImportKeyFormat();
+ }
+}
+
+Status RsaHashedAlgorithm::ImportKeyPkcs8(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ crypto::ScopedEVP_PKEY private_key;
+ Status status =
+ ImportUnverifiedPkeyFromPkcs8(key_data, EVP_PKEY_RSA, &private_key);
+ if (status.IsError())
+ return status;
+
+ // Verify the parameters of the key.
+ crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(private_key.get()));
+ if (!rsa.get())
+ return Status::ErrorUnexpected();
+ if (!RSA_check_key(rsa.get()))
+ return Status::DataError();
+
+ // TODO(eroman): Validate the algorithm OID against the webcrypto provided
+ // hash. http://crbug.com/389400
+
+ return CreateWebCryptoRsaPrivateKey(private_key.Pass(), algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash(),
+ extractable, usages, key);
+}
+
+Status RsaHashedAlgorithm::ImportKeySpki(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ crypto::ScopedEVP_PKEY public_key;
+ Status status =
+ ImportUnverifiedPkeyFromSpki(key_data, EVP_PKEY_RSA, &public_key);
+ if (status.IsError())
+ return status;
+
+ // TODO(eroman): Validate the algorithm OID against the webcrypto provided
+ // hash. http://crbug.com/389400
+
+ return CreateWebCryptoRsaPublicKey(public_key.Pass(), algorithm.id(),
+ algorithm.rsaHashedImportParams()->hash(),
+ extractable, usages, key);
+}
+
+Status RsaHashedAlgorithm::ImportKeyJwk(
+ const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ const char* jwk_algorithm =
+ GetJwkAlgorithm(algorithm.rsaHashedImportParams()->hash().id());
+
+ if (!jwk_algorithm)
+ return Status::ErrorUnexpected();
+
+ JwkRsaInfo jwk;
+ Status status =
+ ReadRsaKeyJwk(key_data, jwk_algorithm, extractable, usages, &jwk);
+ if (status.IsError())
+ return status;
+
+ // Once the key type is known, verify the usages.
+ status = CheckKeyCreationUsages(
+ jwk.is_private_key ? all_private_key_usages_ : all_public_key_usages_,
+ usages);
+ if (status.IsError())
+ return status;
+
+ return jwk.is_private_key
+ ? ImportRsaPrivateKey(algorithm, extractable, usages, jwk, key)
+ : ImportRsaPublicKey(algorithm, extractable, usages,
+ CryptoData(jwk.n), CryptoData(jwk.e), key);
+}
+
+Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return Status::ErrorUnexpectedKeyType();
+ *buffer = AsymKeyOpenSsl::Cast(key)->serialized_key_data();
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return Status::ErrorUnexpectedKeyType();
+ *buffer = AsymKeyOpenSsl::Cast(key)->serialized_key_data();
+ return Status::Success();
+}
+
+Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ EVP_PKEY* pkey = AsymKeyOpenSsl::Cast(key)->key();
+ crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey));
+ if (!rsa.get())
+ return Status::ErrorUnexpected();
+
+ const char* jwk_algorithm =
+ GetJwkAlgorithm(key.algorithm().rsaHashedParams()->hash().id());
+ if (!jwk_algorithm)
+ return Status::ErrorUnexpected();
+
+ switch (key.type()) {
+ case blink::WebCryptoKeyTypePublic:
+ WriteRsaPublicKeyJwk(CryptoData(BIGNUMToVector(rsa->n)),
+ CryptoData(BIGNUMToVector(rsa->e)), jwk_algorithm,
+ key.extractable(), key.usages(), buffer);
+ return Status::Success();
+ case blink::WebCryptoKeyTypePrivate:
+ WriteRsaPrivateKeyJwk(CryptoData(BIGNUMToVector(rsa->n)),
+ CryptoData(BIGNUMToVector(rsa->e)),
+ CryptoData(BIGNUMToVector(rsa->d)),
+ CryptoData(BIGNUMToVector(rsa->p)),
+ CryptoData(BIGNUMToVector(rsa->q)),
+ CryptoData(BIGNUMToVector(rsa->dmp1)),
+ CryptoData(BIGNUMToVector(rsa->dmq1)),
+ CryptoData(BIGNUMToVector(rsa->iqmp)),
+ jwk_algorithm, key.extractable(), key.usages(),
+ buffer);
+ return Status::Success();
+
+ default:
+ return Status::ErrorUnexpected();
+ }
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/rsa_key_openssl.h b/chromium/content/child/webcrypto/openssl/rsa_key_openssl.h
new file mode 100644
index 00000000000..d7935052dc7
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_key_openssl.h
@@ -0,0 +1,83 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_OPENSSL_RSA_KEY_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_RSA_KEY_OPENSSL_H_
+
+#include "content/child/webcrypto/algorithm_implementation.h"
+
+namespace content {
+
+namespace webcrypto {
+
+// Base class for an RSA algorithm whose keys additionaly have a hash parameter
+// bound to them. Provides functionality for generating, importing, and
+// exporting keys.
+class RsaHashedAlgorithm : public AlgorithmImplementation {
+ public:
+ // |all_public_key_usages| and |all_private_key_usages| are the set of
+ // WebCrypto key usages that are valid for created keys (public and private
+ // respectively).
+ //
+ // For instance if public keys support encryption and wrapping, and private
+ // keys support decryption and unwrapping callers should set:
+ // all_public_key_usages = UsageEncrypt | UsageWrap
+ // all_private_key_usages = UsageDecrypt | UsageUnwrap
+ // This information is used when importing or generating keys, to enforce
+ // that valid key usages are allowed.
+ RsaHashedAlgorithm(blink::WebCryptoKeyUsageMask all_public_key_usages,
+ blink::WebCryptoKeyUsageMask all_private_key_usages)
+ : all_public_key_usages_(all_public_key_usages),
+ all_private_key_usages_(all_private_key_usages) {}
+
+ // For instance "RSA-OAEP-256".
+ virtual const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const = 0;
+
+ Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ GenerateKeyResult* result) const override;
+
+ Status VerifyKeyUsagesBeforeImportKey(
+ blink::WebCryptoKeyFormat format,
+ blink::WebCryptoKeyUsageMask usages) const override;
+
+ Status ImportKeyPkcs8(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ImportKeySpki(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ImportKeyJwk(const CryptoData& key_data,
+ const blink::WebCryptoAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) const override;
+
+ Status ExportKeyPkcs8(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ Status ExportKeySpki(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ Status ExportKeyJwk(const blink::WebCryptoKey& key,
+ std::vector<uint8_t>* buffer) const override;
+
+ private:
+ blink::WebCryptoKeyUsageMask all_public_key_usages_;
+ blink::WebCryptoKeyUsageMask all_private_key_usages_;
+};
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_RSA_KEY_OPENSSL_H_
diff --git a/chromium/content/child/webcrypto/openssl/rsa_oaep_openssl.cc b/chromium/content/child/webcrypto/openssl/rsa_oaep_openssl.cc
new file mode 100644
index 00000000000..b1e40174fa5
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_oaep_openssl.cc
@@ -0,0 +1,153 @@
+// Copyright 2014 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 <openssl/evp.h>
+
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/rsa_key_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+typedef int (*InitFunc)(EVP_PKEY_CTX* ctx);
+typedef int (*EncryptDecryptFunc)(EVP_PKEY_CTX* ctx,
+ unsigned char* out,
+ size_t* outlen,
+ const unsigned char* in,
+ size_t inlen);
+
+// Helper for doing either RSA-OAEP encryption or decryption.
+//
+// To encrypt call with:
+// init_func=EVP_PKEY_encrypt_init, encrypt_decrypt_func=EVP_PKEY_encrypt
+//
+// To decrypt call with:
+// init_func=EVP_PKEY_decrypt_init, encrypt_decrypt_func=EVP_PKEY_decrypt
+Status CommonEncryptDecrypt(InitFunc init_func,
+ EncryptDecryptFunc encrypt_decrypt_func,
+ const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ EVP_PKEY* pkey = AsymKeyOpenSsl::Cast(key)->key();
+ const EVP_MD* digest =
+ GetDigest(key.algorithm().rsaHashedParams()->hash().id());
+ if (!digest)
+ return Status::ErrorUnsupported();
+
+ crypto::ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(pkey, NULL));
+
+ if (!init_func(ctx.get()) ||
+ 1 != EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING) ||
+ 1 != EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), digest) ||
+ 1 != EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), digest)) {
+ return Status::OperationError();
+ }
+
+ const blink::WebVector<uint8_t>& label =
+ algorithm.rsaOaepParams()->optionalLabel();
+
+ if (label.size()) {
+ // Make a copy of the label, since the ctx takes ownership of it when
+ // calling set0_rsa_oaep_label().
+ crypto::ScopedOpenSSLBytes label_copy;
+ label_copy.reset(static_cast<uint8_t*>(OPENSSL_malloc(label.size())));
+ memcpy(label_copy.get(), label.data(), label.size());
+
+ if (1 != EVP_PKEY_CTX_set0_rsa_oaep_label(
+ ctx.get(), label_copy.release(), label.size())) {
+ return Status::OperationError();
+ }
+ }
+
+ // Determine the maximum length of the output.
+ size_t outlen = 0;
+ if (!encrypt_decrypt_func(
+ ctx.get(), NULL, &outlen, data.bytes(), data.byte_length())) {
+ return Status::OperationError();
+ }
+ buffer->resize(outlen);
+
+ // Do the actual encryption/decryption.
+ if (!encrypt_decrypt_func(ctx.get(),
+ vector_as_array(buffer),
+ &outlen,
+ data.bytes(),
+ data.byte_length())) {
+ return Status::OperationError();
+ }
+ buffer->resize(outlen);
+
+ return Status::Success();
+}
+
+class RsaOaepImplementation : public RsaHashedAlgorithm {
+ public:
+ RsaOaepImplementation()
+ : RsaHashedAlgorithm(
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
+ blink::WebCryptoKeyUsageDecrypt |
+ blink::WebCryptoKeyUsageUnwrapKey) {}
+
+ const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const override {
+ switch (hash) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return "RSA-OAEP";
+ case blink::WebCryptoAlgorithmIdSha256:
+ return "RSA-OAEP-256";
+ case blink::WebCryptoAlgorithmIdSha384:
+ return "RSA-OAEP-384";
+ case blink::WebCryptoAlgorithmIdSha512:
+ return "RSA-OAEP-512";
+ default:
+ return NULL;
+ }
+ }
+
+ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return Status::ErrorUnexpectedKeyType();
+
+ return CommonEncryptDecrypt(
+ EVP_PKEY_encrypt_init, EVP_PKEY_encrypt, algorithm, key, data, buffer);
+ }
+
+ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return Status::ErrorUnexpectedKeyType();
+
+ return CommonEncryptDecrypt(
+ EVP_PKEY_decrypt_init, EVP_PKEY_decrypt, algorithm, key, data, buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformRsaOaepImplementation() {
+ return new RsaOaepImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/rsa_pss_openssl.cc b/chromium/content/child/webcrypto/openssl/rsa_pss_openssl.cc
new file mode 100644
index 00000000000..a6bf4d55a69
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_pss_openssl.cc
@@ -0,0 +1,67 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/rsa_key_openssl.h"
+#include "content/child/webcrypto/openssl/rsa_sign_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+class RsaPssImplementation : public RsaHashedAlgorithm {
+ public:
+ RsaPssImplementation()
+ : RsaHashedAlgorithm(blink::WebCryptoKeyUsageVerify,
+ blink::WebCryptoKeyUsageSign) {}
+
+ const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const override {
+ switch (hash) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return "PS1";
+ case blink::WebCryptoAlgorithmIdSha256:
+ return "PS256";
+ case blink::WebCryptoAlgorithmIdSha384:
+ return "PS384";
+ case blink::WebCryptoAlgorithmIdSha512:
+ return "PS512";
+ default:
+ return NULL;
+ }
+ }
+
+ Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return RsaSign(
+ key, algorithm.rsaPssParams()->saltLengthBytes(), data, buffer);
+ }
+
+ Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const override {
+ return RsaVerify(key,
+ algorithm.rsaPssParams()->saltLengthBytes(),
+ signature,
+ data,
+ signature_match);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformRsaPssImplementation() {
+ return new RsaPssImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/rsa_sign_openssl.cc b/chromium/content/child/webcrypto/openssl/rsa_sign_openssl.cc
new file mode 100644
index 00000000000..1410aabb25b
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_sign_openssl.cc
@@ -0,0 +1,155 @@
+// Copyright 2014 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/numerics/safe_math.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/openssl/rsa_key_openssl.h"
+#include "content/child/webcrypto/openssl/rsa_sign_openssl.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// Extracts the OpenSSL key and digest from a WebCrypto key. The returned
+// pointers will remain valid as long as |key| is alive.
+Status GetPKeyAndDigest(const blink::WebCryptoKey& key,
+ EVP_PKEY** pkey,
+ const EVP_MD** digest) {
+ *pkey = AsymKeyOpenSsl::Cast(key)->key();
+
+ *digest = GetDigest(key.algorithm().rsaHashedParams()->hash().id());
+ if (!*digest)
+ return Status::ErrorUnsupported();
+
+ return Status::Success();
+}
+
+// Sets the PSS parameters on |pctx| if the key is for RSA-PSS.
+//
+// Otherwise returns Success without doing anything.
+Status ApplyRsaPssOptions(const blink::WebCryptoKey& key,
+ const EVP_MD* const mgf_digest,
+ unsigned int salt_length_bytes,
+ EVP_PKEY_CTX* pctx) {
+ // Only apply RSA-PSS options if the key is for RSA-PSS.
+ if (key.algorithm().id() != blink::WebCryptoAlgorithmIdRsaPss) {
+ DCHECK_EQ(0u, salt_length_bytes);
+ DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, key.algorithm().id());
+ return Status::Success();
+ }
+
+ // BoringSSL takes a signed int for the salt length, and interprets
+ // negative values in a special manner. Make sure not to silently underflow.
+ base::CheckedNumeric<int> salt_length_bytes_int(salt_length_bytes);
+ if (!salt_length_bytes_int.IsValid()) {
+ // TODO(eroman): Give a better error message.
+ return Status::OperationError();
+ }
+
+ if (1 != EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
+ 1 != EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf_digest) ||
+ 1 != EVP_PKEY_CTX_set_rsa_pss_saltlen(
+ pctx, salt_length_bytes_int.ValueOrDie())) {
+ return Status::OperationError();
+ }
+
+ return Status::Success();
+}
+
+} // namespace
+
+Status RsaSign(const blink::WebCryptoKey& key,
+ unsigned int pss_salt_length_bytes,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) {
+ if (key.type() != blink::WebCryptoKeyTypePrivate)
+ return Status::ErrorUnexpectedKeyType();
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ EVP_PKEY_CTX* pctx = NULL; // Owned by |ctx|.
+
+ EVP_PKEY* private_key = NULL;
+ const EVP_MD* digest = NULL;
+ Status status = GetPKeyAndDigest(key, &private_key, &digest);
+ if (status.IsError())
+ return status;
+
+ // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter
+ // returns a maximum allocation size, while the call without a NULL returns
+ // the real one, which may be smaller.
+ size_t sig_len = 0;
+ if (!ctx.get() ||
+ !EVP_DigestSignInit(ctx.get(), &pctx, digest, NULL, private_key)) {
+ return Status::OperationError();
+ }
+
+ // Set PSS-specific options (if applicable).
+ status = ApplyRsaPssOptions(key, digest, pss_salt_length_bytes, pctx);
+ if (status.IsError())
+ return status;
+
+ if (!EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) ||
+ !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) {
+ return Status::OperationError();
+ }
+
+ buffer->resize(sig_len);
+ if (!EVP_DigestSignFinal(ctx.get(), &buffer->front(), &sig_len))
+ return Status::OperationError();
+
+ buffer->resize(sig_len);
+ return Status::Success();
+}
+
+Status RsaVerify(const blink::WebCryptoKey& key,
+ unsigned int pss_salt_length_bytes,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) {
+ if (key.type() != blink::WebCryptoKeyTypePublic)
+ return Status::ErrorUnexpectedKeyType();
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
+ EVP_PKEY_CTX* pctx = NULL; // Owned by |ctx|.
+
+ EVP_PKEY* public_key = NULL;
+ const EVP_MD* digest = NULL;
+ Status status = GetPKeyAndDigest(key, &public_key, &digest);
+ if (status.IsError())
+ return status;
+
+ if (!EVP_DigestVerifyInit(ctx.get(), &pctx, digest, NULL, public_key))
+ return Status::OperationError();
+
+ // Set PSS-specific options (if applicable).
+ status = ApplyRsaPssOptions(key, digest, pss_salt_length_bytes, pctx);
+ if (status.IsError())
+ return status;
+
+ if (!EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length()))
+ return Status::OperationError();
+
+ // Note that the return value can be:
+ // 1 --> Success
+ // 0 --> Verification failed
+ // <0 --> Operation error
+ int rv = EVP_DigestVerifyFinal(
+ ctx.get(), signature.bytes(), signature.byte_length());
+ *signature_match = rv == 1;
+ return rv >= 0 ? Status::Success() : Status::OperationError();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/rsa_sign_openssl.h b/chromium/content/child/webcrypto/openssl/rsa_sign_openssl.h
new file mode 100644
index 00000000000..c750ee2e57c
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_sign_openssl.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_OPENSSL_RSA_SIGN_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_RSA_SIGN_OPENSSL_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+namespace blink {
+class WebCryptoKey;
+}
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class Status;
+
+// Helper functions for doing RSA-SSA signing and verification
+// (both PKCS1-v1_5 and PSS flavor).
+//
+// The salt length parameter is only relevant when the key is for RSA-PSS. In
+// other cases it should be set to zero.
+
+Status RsaSign(const blink::WebCryptoKey& key,
+ unsigned int pss_salt_length_bytes,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer);
+
+Status RsaVerify(const blink::WebCryptoKey& key,
+ unsigned int pss_salt_length_bytes,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_RSA_SIGN_OPENSSL_H_
diff --git a/chromium/content/child/webcrypto/openssl/rsa_ssa_openssl.cc b/chromium/content/child/webcrypto/openssl/rsa_ssa_openssl.cc
new file mode 100644
index 00000000000..1d3b834fc79
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/rsa_ssa_openssl.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/rsa_key_openssl.h"
+#include "content/child/webcrypto/openssl/rsa_sign_openssl.h"
+#include "content/child/webcrypto/status.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+class RsaSsaImplementation : public RsaHashedAlgorithm {
+ public:
+ RsaSsaImplementation()
+ : RsaHashedAlgorithm(blink::WebCryptoKeyUsageVerify,
+ blink::WebCryptoKeyUsageSign) {}
+
+ const char* GetJwkAlgorithm(
+ const blink::WebCryptoAlgorithmId hash) const override {
+ switch (hash) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return "RS1";
+ case blink::WebCryptoAlgorithmIdSha256:
+ return "RS256";
+ case blink::WebCryptoAlgorithmIdSha384:
+ return "RS384";
+ case blink::WebCryptoAlgorithmIdSha512:
+ return "RS512";
+ default:
+ return NULL;
+ }
+ }
+
+ Status Sign(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ return RsaSign(key, 0, data, buffer);
+ }
+
+ Status Verify(const blink::WebCryptoAlgorithm& algorithm,
+ const blink::WebCryptoKey& key,
+ const CryptoData& signature,
+ const CryptoData& data,
+ bool* signature_match) const override {
+ return RsaVerify(key, 0, signature, data, signature_match);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformRsaSsaImplementation() {
+ return new RsaSsaImplementation;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/sha_openssl.cc b/chromium/content/child/webcrypto/openssl/sha_openssl.cc
new file mode 100644
index 00000000000..e7ee049fefd
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/sha_openssl.cc
@@ -0,0 +1,140 @@
+// Copyright 2014 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 <vector>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "content/child/webcrypto/algorithm_implementation.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/util_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "crypto/openssl_util.h"
+#include "crypto/scoped_openssl_types.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// Implementation of blink::WebCryptoDigester, an internal Blink detail not
+// part of WebCrypto, that allows chunks of data to be streamed in before
+// computing a SHA-* digest (as opposed to ShaImplementation, which computes
+// digests over complete messages)
+class DigestorOpenSsl : public blink::WebCryptoDigestor {
+ public:
+ explicit DigestorOpenSsl(blink::WebCryptoAlgorithmId algorithm_id)
+ : initialized_(false),
+ digest_context_(EVP_MD_CTX_create()),
+ algorithm_id_(algorithm_id) {}
+
+ bool consume(const unsigned char* data, unsigned int size) override {
+ return ConsumeWithStatus(data, size).IsSuccess();
+ }
+
+ Status ConsumeWithStatus(const unsigned char* data, unsigned int size) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ Status error = Init();
+ if (!error.IsSuccess())
+ return error;
+
+ if (!EVP_DigestUpdate(digest_context_.get(), data, size))
+ return Status::OperationError();
+
+ return Status::Success();
+ }
+
+ bool finish(unsigned char*& result_data,
+ unsigned int& result_data_size) override {
+ Status error = FinishInternal(result_, &result_data_size);
+ if (!error.IsSuccess())
+ return false;
+ result_data = result_;
+ return true;
+ }
+
+ Status FinishWithVectorAndStatus(std::vector<uint8_t>* result) {
+ const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get());
+ result->resize(hash_expected_size);
+ unsigned char* const hash_buffer = vector_as_array(result);
+ unsigned int hash_buffer_size; // ignored
+ return FinishInternal(hash_buffer, &hash_buffer_size);
+ }
+
+ private:
+ Status Init() {
+ if (initialized_)
+ return Status::Success();
+
+ const EVP_MD* digest_algorithm = GetDigest(algorithm_id_);
+ if (!digest_algorithm)
+ return Status::ErrorUnexpected();
+
+ if (!digest_context_.get())
+ return Status::OperationError();
+
+ if (!EVP_DigestInit_ex(digest_context_.get(), digest_algorithm, NULL))
+ return Status::OperationError();
+
+ initialized_ = true;
+ return Status::Success();
+ }
+
+ Status FinishInternal(unsigned char* result, unsigned int* result_size) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ Status error = Init();
+ if (!error.IsSuccess())
+ return error;
+
+ const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get());
+ if (hash_expected_size <= 0)
+ return Status::ErrorUnexpected();
+ DCHECK_LE(hash_expected_size, EVP_MAX_MD_SIZE);
+
+ if (!EVP_DigestFinal_ex(digest_context_.get(), result, result_size) ||
+ static_cast<int>(*result_size) != hash_expected_size)
+ return Status::OperationError();
+
+ return Status::Success();
+ }
+
+ bool initialized_;
+ crypto::ScopedEVP_MD_CTX digest_context_;
+ blink::WebCryptoAlgorithmId algorithm_id_;
+ unsigned char result_[EVP_MAX_MD_SIZE];
+};
+
+class ShaImplementation : public AlgorithmImplementation {
+ public:
+ Status Digest(const blink::WebCryptoAlgorithm& algorithm,
+ const CryptoData& data,
+ std::vector<uint8_t>* buffer) const override {
+ DigestorOpenSsl digestor(algorithm.id());
+ Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
+ // http://crbug.com/366427: the spec does not define any other failures for
+ // digest, so none of the subsequent errors are spec compliant.
+ if (!error.IsSuccess())
+ return error;
+ return digestor.FinishWithVectorAndStatus(buffer);
+ }
+};
+
+} // namespace
+
+AlgorithmImplementation* CreatePlatformShaImplementation() {
+ return new ShaImplementation();
+}
+
+scoped_ptr<blink::WebCryptoDigestor> CreatePlatformDigestor(
+ blink::WebCryptoAlgorithmId algorithm) {
+ return scoped_ptr<blink::WebCryptoDigestor>(new DigestorOpenSsl(algorithm));
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/sym_key_openssl.cc b/chromium/content/child/webcrypto/openssl/sym_key_openssl.cc
new file mode 100644
index 00000000000..39238335a26
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/sym_key_openssl.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/sym_key_openssl.h"
+
+#include <vector>
+#include <openssl/rand.h>
+
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/generate_key_result.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/openssl_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+Status GenerateSecretKeyOpenSsl(const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ unsigned keylen_bytes,
+ GenerateKeyResult* result) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ std::vector<unsigned char> random_bytes(keylen_bytes, 0);
+
+ if (keylen_bytes > 0) {
+ if (!(RAND_bytes(&random_bytes[0], keylen_bytes)))
+ return Status::OperationError();
+ }
+
+ result->AssignSecretKey(
+ blink::WebCryptoKey::create(new SymKeyOpenSsl(CryptoData(random_bytes)),
+ blink::WebCryptoKeyTypeSecret,
+ extractable,
+ algorithm,
+ usages));
+
+ return Status::Success();
+}
+
+Status ImportKeyRawOpenSsl(const CryptoData& key_data,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ *key = blink::WebCryptoKey::create(new SymKeyOpenSsl(key_data),
+ blink::WebCryptoKeyTypeSecret,
+ extractable,
+ algorithm,
+ usages);
+ return Status::Success();
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/sym_key_openssl.h b/chromium/content/child/webcrypto/openssl/sym_key_openssl.h
new file mode 100644
index 00000000000..bb5def4704f
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/sym_key_openssl.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_OPENSSL_SYM_KEY_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_SYM_KEY_OPENSSL_H_
+
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class GenerateKeyResult;
+class Status;
+
+Status GenerateSecretKeyOpenSsl(const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ unsigned keylen_bytes,
+ GenerateKeyResult* result);
+
+Status ImportKeyRawOpenSsl(const CryptoData& key_data,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_SYM_KEY_OPENSSL_H_
diff --git a/chromium/content/child/webcrypto/openssl/util_openssl.cc b/chromium/content/child/webcrypto/openssl/util_openssl.cc
new file mode 100644
index 00000000000..4abf04278bf
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/util_openssl.cc
@@ -0,0 +1,249 @@
+// Copyright 2014 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 "content/child/webcrypto/openssl/util_openssl.h"
+
+#include <openssl/evp.h>
+#include <openssl/pkcs12.h>
+
+#include "base/stl_util.h"
+#include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/openssl/key_openssl.h"
+#include "content/child/webcrypto/platform_crypto.h"
+#include "content/child/webcrypto/status.h"
+#include "crypto/openssl_util.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// Exports an EVP_PKEY public key to the SPKI format.
+Status ExportPKeySpki(EVP_PKEY* key, std::vector<uint8_t>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ crypto::ScopedBIO bio(BIO_new(BIO_s_mem()));
+
+ // TODO(eroman): Use the OID specified by webcrypto spec.
+ // http://crbug.com/373545
+ if (!i2d_PUBKEY_bio(bio.get(), key))
+ return Status::ErrorUnexpected();
+
+ char* data = NULL;
+ long len = BIO_get_mem_data(bio.get(), &data);
+ if (!data || len < 0)
+ return Status::ErrorUnexpected();
+
+ buffer->assign(data, data + len);
+ return Status::Success();
+}
+
+// Exports an EVP_PKEY private key to the PKCS8 format.
+Status ExportPKeyPkcs8(EVP_PKEY* key, std::vector<uint8_t>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ crypto::ScopedBIO bio(BIO_new(BIO_s_mem()));
+
+ // TODO(eroman): Use the OID specified by webcrypto spec.
+ // http://crbug.com/373545
+ if (!i2d_PKCS8PrivateKeyInfo_bio(bio.get(), key))
+ return Status::ErrorUnexpected();
+
+ char* data = NULL;
+ long len = BIO_get_mem_data(bio.get(), &data);
+ if (!data || len < 0)
+ return Status::ErrorUnexpected();
+
+ buffer->assign(data, data + len);
+ return Status::Success();
+}
+
+} // namespace
+
+void PlatformInit() {
+ crypto::EnsureOpenSSLInit();
+}
+
+const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) {
+ switch (id) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return EVP_sha1();
+ case blink::WebCryptoAlgorithmIdSha256:
+ return EVP_sha256();
+ case blink::WebCryptoAlgorithmIdSha384:
+ return EVP_sha384();
+ case blink::WebCryptoAlgorithmIdSha512:
+ return EVP_sha512();
+ default:
+ return NULL;
+ }
+}
+
+Status AeadEncryptDecrypt(EncryptOrDecrypt mode,
+ const std::vector<uint8_t>& raw_key,
+ const CryptoData& data,
+ unsigned int tag_length_bytes,
+ const CryptoData& iv,
+ const CryptoData& additional_data,
+ const EVP_AEAD* aead_alg,
+ std::vector<uint8_t>* buffer) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ EVP_AEAD_CTX ctx;
+
+ if (!aead_alg)
+ return Status::ErrorUnexpected();
+
+ if (!EVP_AEAD_CTX_init(&ctx,
+ aead_alg,
+ vector_as_array(&raw_key),
+ raw_key.size(),
+ tag_length_bytes,
+ NULL)) {
+ return Status::OperationError();
+ }
+
+ crypto::ScopedOpenSSL<EVP_AEAD_CTX, EVP_AEAD_CTX_cleanup>::Type ctx_cleanup(
+ &ctx);
+
+ size_t len;
+ int ok;
+
+ if (mode == DECRYPT) {
+ if (data.byte_length() < tag_length_bytes)
+ return Status::ErrorDataTooSmall();
+
+ buffer->resize(data.byte_length() - tag_length_bytes);
+
+ ok = EVP_AEAD_CTX_open(&ctx,
+ vector_as_array(buffer),
+ &len,
+ buffer->size(),
+ iv.bytes(),
+ iv.byte_length(),
+ data.bytes(),
+ data.byte_length(),
+ additional_data.bytes(),
+ additional_data.byte_length());
+ } else {
+ // No need to check for unsigned integer overflow here (seal fails if
+ // the output buffer is too small).
+ buffer->resize(data.byte_length() + EVP_AEAD_max_overhead(aead_alg));
+
+ ok = EVP_AEAD_CTX_seal(&ctx,
+ vector_as_array(buffer),
+ &len,
+ buffer->size(),
+ iv.bytes(),
+ iv.byte_length(),
+ data.bytes(),
+ data.byte_length(),
+ additional_data.bytes(),
+ additional_data.byte_length());
+ }
+
+ if (!ok)
+ return Status::OperationError();
+ buffer->resize(len);
+ return Status::Success();
+}
+
+Status CreateWebCryptoPublicKey(crypto::ScopedEVP_PKEY public_key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ // Serialize the key at creation time so that if structured cloning is
+ // requested it can be done synchronously from the Blink thread.
+ std::vector<uint8_t> spki_data;
+ Status status = ExportPKeySpki(public_key.get(), &spki_data);
+ if (status.IsError())
+ return status;
+
+ *key = blink::WebCryptoKey::create(
+ new AsymKeyOpenSsl(public_key.Pass(), CryptoData(spki_data)),
+ blink::WebCryptoKeyTypePublic, extractable, algorithm, usages);
+ return Status::Success();
+}
+
+Status CreateWebCryptoPrivateKey(crypto::ScopedEVP_PKEY private_key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key) {
+ // Serialize the key at creation time so that if structured cloning is
+ // requested it can be done synchronously from the Blink thread.
+ std::vector<uint8_t> pkcs8_data;
+ Status status = ExportPKeyPkcs8(private_key.get(), &pkcs8_data);
+ if (status.IsError())
+ return status;
+
+ *key = blink::WebCryptoKey::create(
+ new AsymKeyOpenSsl(private_key.Pass(), CryptoData(pkcs8_data)),
+ blink::WebCryptoKeyTypePrivate, extractable, algorithm, usages);
+ return Status::Success();
+}
+
+Status ImportUnverifiedPkeyFromSpki(const CryptoData& key_data,
+ int expected_pkey_id,
+ crypto::ScopedEVP_PKEY* pkey) {
+ if (!key_data.byte_length())
+ return Status::ErrorImportEmptyKeyData();
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ crypto::ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(key_data.bytes()),
+ key_data.byte_length()));
+ if (!bio.get())
+ return Status::ErrorUnexpected();
+
+ pkey->reset(d2i_PUBKEY_bio(bio.get(), NULL));
+ if (!pkey->get())
+ return Status::DataError();
+
+ if (EVP_PKEY_id(pkey->get()) != expected_pkey_id)
+ return Status::DataError(); // Data did not define expected key type.
+
+ return Status::Success();
+}
+
+Status ImportUnverifiedPkeyFromPkcs8(const CryptoData& key_data,
+ int expected_pkey_id,
+ crypto::ScopedEVP_PKEY* pkey) {
+ if (!key_data.byte_length())
+ return Status::ErrorImportEmptyKeyData();
+
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ crypto::ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(key_data.bytes()),
+ key_data.byte_length()));
+ if (!bio.get())
+ return Status::ErrorUnexpected();
+
+ crypto::ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>::Type
+ p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
+ if (!p8inf.get())
+ return Status::DataError();
+
+ pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
+ if (!pkey->get())
+ return Status::DataError();
+
+ if (EVP_PKEY_id(pkey->get()) != expected_pkey_id)
+ return Status::DataError(); // Data did not define expected key type.
+
+ return Status::Success();
+}
+
+BIGNUM* CreateBIGNUM(const std::string& n) {
+ return BN_bin2bn(reinterpret_cast<const uint8_t*>(n.data()), n.size(), NULL);
+}
+
+std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n) {
+ std::vector<uint8_t> v(BN_num_bytes(n));
+ BN_bn2bin(n, vector_as_array(&v));
+ return v;
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/openssl/util_openssl.h b/chromium/content/child/webcrypto/openssl/util_openssl.h
new file mode 100644
index 00000000000..5031cf27e9b
--- /dev/null
+++ b/chromium/content/child/webcrypto/openssl/util_openssl.h
@@ -0,0 +1,87 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_OPENSSL_UTIL_OPENSSL_H_
+#define CONTENT_CHILD_WEBCRYPTO_OPENSSL_UTIL_OPENSSL_H_
+
+#include <string>
+#include <vector>
+
+#include <openssl/ossl_typ.h>
+
+#include "crypto/scoped_openssl_types.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebCryptoKey.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class Status;
+
+// The values of these constants correspond with the "enc" parameter of
+// EVP_CipherInit_ex(), do not change.
+enum EncryptOrDecrypt { DECRYPT=0, ENCRYPT=1 };
+
+const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id);
+
+// Does either encryption or decryption for an AEAD algorithm.
+// * |mode| controls whether encryption or decryption is done
+// * |aead_alg| the algorithm (for instance AES-GCM)
+// * |buffer| where the ciphertext or plaintext is written to.
+Status AeadEncryptDecrypt(EncryptOrDecrypt mode,
+ const std::vector<uint8_t>& raw_key,
+ const CryptoData& data,
+ unsigned int tag_length_bytes,
+ const CryptoData& iv,
+ const CryptoData& additional_data,
+ const EVP_AEAD* aead_alg,
+ std::vector<uint8_t>* buffer);
+
+// Creates a WebCrypto public key given an EVP_PKEY. This step includes
+// exporting the key to SPKI format, for use by serialization later.
+Status CreateWebCryptoPublicKey(
+ crypto::ScopedEVP_PKEY public_key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key);
+
+// Creates a WebCrypto private key given an EVP_PKEY. This step includes
+// exporting the key to PKCS8 format, for use by serialization later.
+Status CreateWebCryptoPrivateKey(
+ crypto::ScopedEVP_PKEY private_key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ blink::WebCryptoKey* key);
+
+// Imports SPKI bytes to an EVP_PKEY for a public key. The resulting asymmetric
+// key may be invalid, and should be verified using something like
+// RSA_check_key(). The only validation performed by this function is to ensure
+// the key type matched |expected_pkey_id|.
+Status ImportUnverifiedPkeyFromSpki(const CryptoData& key_data,
+ int expected_pkey_id,
+ crypto::ScopedEVP_PKEY* pkey);
+
+// Imports PKCS8 bytes to an EVP_PKEY for a private key. The resulting
+// asymmetric key may be invalid, and should be verified using something like
+// RSA_check_key(). The only validation performed by this function is to ensure
+// the key type matched |expected_pkey_id|.
+Status ImportUnverifiedPkeyFromPkcs8(const CryptoData& key_data,
+ int expected_pkey_id,
+ crypto::ScopedEVP_PKEY* pkey);
+
+// Allocates a new BIGNUM given a std::string big-endian representation.
+BIGNUM* CreateBIGNUM(const std::string& n);
+
+// Converts a BIGNUM to a big endian byte array.
+std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_OPENSSL_UTIL_OPENSSL_H_
diff --git a/chromium/content/child/webcrypto/platform_crypto.h b/chromium/content/child/webcrypto/platform_crypto.h
index 9e957301c01..2977b9c97f5 100644
--- a/chromium/content/child/webcrypto/platform_crypto.h
+++ b/chromium/content/child/webcrypto/platform_crypto.h
@@ -5,285 +5,36 @@
#ifndef CONTENT_CHILD_WEBCRYPTO_PLATFORM_CRYPTO_H_
#define CONTENT_CHILD_WEBCRYPTO_PLATFORM_CRYPTO_H_
+#include <stdint.h>
#include <vector>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/WebKit/public/platform/WebCrypto.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-
-namespace blink {
-template <typename T>
-class WebVector;
-}
+// The definitions for these methods lives in either nss/ or openssl/
namespace content {
-enum EncryptOrDecrypt { ENCRYPT, DECRYPT };
-
namespace webcrypto {
-class CryptoData;
-class Status;
-
-// Functions in the webcrypto::platform namespace are intended to be those
-// which are OpenSSL/NSS specific.
-//
-// The general purpose code which applies to both OpenSSL and NSS
-// implementations of webcrypto should live in the outter webcrypto namespace,
-// and the crypto library specific bits in the "platform" namespace.
-//
-// -----------------
-// Threading:
-// -----------------
-//
-// Unless otherwise noted, functions in webcrypto::platform are called
-// exclusively from a sequenced worker pool.
-//
-// This means that operations using a given key cannot occur in
-// parallel and it is not necessary to guard against concurrent usage.
-//
-// The exceptions are:
-//
-// * Key::ThreadSafeSerializeForClone(), which is called from the
-// target Blink thread during structured clone.
-//
-// * ImportKeyRaw(), ImportKeySpki(), ImportKeyPkcs8(), which can be
-// called from the target Blink thread during structured clone
-// deserialization, as well as from the webcrypto worker pool.
-//
-// TODO(eroman): Change it so import happens in worker pool too.
-// http://crbug.com/366834
-namespace platform {
-
-class SymKey;
-class PublicKey;
-class PrivateKey;
-
-// Base key class for all platform keys, used to safely cast between types.
-class Key : public blink::WebCryptoKeyHandle {
- public:
- virtual SymKey* AsSymKey() = 0;
- virtual PublicKey* AsPublicKey() = 0;
- virtual PrivateKey* AsPrivateKey() = 0;
-
- virtual bool ThreadSafeSerializeForClone(
- blink::WebVector<uint8>* key_data) = 0;
-};
-
-// Do any one-time initialization. Note that this can be called MULTIPLE times
-// (once per instantiation of WebCryptoImpl).
-void Init();
+class AlgorithmImplementation;
-// Preconditions:
-// * |key| is a non-null AES-CBC key.
-// * |iv| is exactly 16 bytes long
-Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- std::vector<uint8>* buffer);
+void PlatformInit();
-// Preconditions:
-// * |key| is a non-null AES-GCM key.
-// * |tag_length_bits| is one of {32, 64, 96, 104, 112, 120, 128}
-Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- const CryptoData& additional_data,
- unsigned int tag_length_bits,
- std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |key| is non-null
-// * |hash| is a digest algorithm
-// * |label| MAY be empty (e.g. 0 bytes long).
-Status EncryptRsaOaep(PublicKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |key| is non-null
-// * |hash| is a digest algorithm
-// * |label| MAY be empty (e.g. 0 bytes long).
-Status DecryptRsaOaep(PrivateKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |key| is a non-null HMAC key.
-// * |hash| is a digest algorithm.
-Status SignHmac(SymKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |algorithm| is a SHA function.
-Status DigestSha(blink::WebCryptoAlgorithmId algorithm,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |algorithm| is a SHA function.
-scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
+scoped_ptr<blink::WebCryptoDigestor> CreatePlatformDigestor(
blink::WebCryptoAlgorithmId algorithm);
-// Preconditions:
-// * |key| is non-null.
-// * |hash| is a digest algorithm.
-Status SignRsaSsaPkcs1v1_5(PrivateKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |key| is non-null.
-// * |hash| is a digest algorithm.
-Status VerifyRsaSsaPkcs1v1_5(PublicKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match);
-
-// |keylen_bytes| is the desired length of the key in bits.
-//
-// Preconditions:
-// * algorithm.id() is for a symmetric key algorithm.
-// * keylen_bytes is non-zero (TODO(eroman): revisit this).
-// * For AES algorithms |keylen_bytes| is either 16, 24, or 32 bytes long.
-// * usage_mask makes sense for the algorithm.
-Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- unsigned keylen_bytes,
- blink::WebCryptoKey* key);
-
-// Preconditions:
-// * algorithm.id() is for an RSA algorithm.
-// * public_exponent, modulus_length_bits and hash_or_null are the same as what
-// is in algorithm. They are split out for convenience.
-// * modulus_length_bits is not 0
-// * public_exponent is not empty.
-// * {public|private}_key_usage_mask make sense for the algorithm.
-Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask public_key_usage_mask,
- blink::WebCryptoKeyUsageMask private_key_usage_mask,
- unsigned int modulus_length_bits,
- unsigned long public_exponent,
- blink::WebCryptoKey* public_key,
- blink::WebCryptoKey* private_key);
-
-// Preconditions:
-// * |key| is non-null.
-// * |algorithm.id()| is for a symmetric key algorithm.
-// * For AES algorithms |key_data| is either 16, 24, or 32 bytes long.
-// * usage_mask makes sense for the algorithm.
-// Note that this may be called from target Blink thread.
-Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
-
-// Preconditions:
-// * algorithm.id() is for an RSA algorithm.
-// * usage_mask makes sense for the algorithm.
-Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& modulus_data,
- const CryptoData& exponent_data,
- blink::WebCryptoKey* key);
-
-// Preconditions:
-// * algorithm.id() is for an RSA algorithm.
-// * modulus, public_exponent, and private_exponent will be non-empty. The
-// others will either all be specified (non-empty), or all be unspecified
-// (empty).
-// * usage_mask makes sense for the algorithm.
-Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& modulus,
- const CryptoData& public_exponent,
- const CryptoData& private_exponent,
- const CryptoData& prime1,
- const CryptoData& prime2,
- const CryptoData& exponent1,
- const CryptoData& exponent2,
- const CryptoData& coefficient,
- blink::WebCryptoKey* key);
-
-// Note that this may be called from target Blink thread.
-// Preconditions:
-// * usage_mask makes sense for the algorithm.
-Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
-
-// Note that this may be called from target Blink thread.
-// Preconditions:
-// * usage_mask makes sense for the algorithm.
-Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
-
-// Preconditions:
-// * |key| is non-null.
-Status ExportKeyRaw(SymKey* key, std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |key| is non-null.
-Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer);
-
-// Preconditions:
-// * |key| is non-null.
-Status ExportRsaPublicKey(PublicKey* key,
- std::vector<uint8>* modulus,
- std::vector<uint8>* public_exponent);
-
-// Preconditions:
-// * |key| is non-null.
-Status ExportRsaPrivateKey(PrivateKey* key,
- std::vector<uint8>* modulus,
- std::vector<uint8>* public_exponent,
- std::vector<uint8>* private_exponent,
- std::vector<uint8>* prime1,
- std::vector<uint8>* prime2,
- std::vector<uint8>* exponent1,
- std::vector<uint8>* exponent2,
- std::vector<uint8>* coefficient);
-
-// Preconditions:
-// * |key| is non-null.
-Status ExportKeyPkcs8(PrivateKey* key,
- const blink::WebCryptoKeyAlgorithm& key_algorithm,
- std::vector<uint8>* buffer);
-
-// Performs AES-KW encryption/decryption on the input |data|.
-// Preconditions:
-// * |key| is non-null
-// * |data| is multiple of 8 bytes. If encrypting it is at least 16 bytes, and
-// if decrypting at least 24 bytes.
-// * |buffer| is non-null.
-Status EncryptDecryptAesKw(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-} // namespace platform
+AlgorithmImplementation* CreatePlatformShaImplementation();
+AlgorithmImplementation* CreatePlatformAesCbcImplementation();
+AlgorithmImplementation* CreatePlatformAesCtrImplementation();
+AlgorithmImplementation* CreatePlatformAesGcmImplementation();
+AlgorithmImplementation* CreatePlatformAesKwImplementation();
+AlgorithmImplementation* CreatePlatformHmacImplementation();
+AlgorithmImplementation* CreatePlatformRsaOaepImplementation();
+AlgorithmImplementation* CreatePlatformRsaSsaImplementation();
+AlgorithmImplementation* CreatePlatformRsaPssImplementation();
+
+bool PlatformSerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8_t>* key_data);
} // namespace webcrypto
diff --git a/chromium/content/child/webcrypto/platform_crypto_nss.cc b/chromium/content/child/webcrypto/platform_crypto_nss.cc
deleted file mode 100644
index c5c18afc3d4..00000000000
--- a/chromium/content/child/webcrypto/platform_crypto_nss.cc
+++ /dev/null
@@ -1,1934 +0,0 @@
-// Copyright 2014 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 "content/child/webcrypto/platform_crypto.h"
-
-#include <cryptohi.h>
-#include <pk11pub.h>
-#include <secerr.h>
-#include <sechash.h>
-
-#include <vector>
-
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/child/webcrypto/crypto_data.h"
-#include "content/child/webcrypto/status.h"
-#include "content/child/webcrypto/webcrypto_util.h"
-#include "crypto/nss_util.h"
-#include "crypto/scoped_nss_types.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
-
-#if defined(USE_NSS)
-#include <dlfcn.h>
-#include <secoid.h>
-#endif
-
-// At the time of this writing:
-// * Windows and Mac builds ship with their own copy of NSS (3.15+)
-// * Linux builds use the system's libnss, which is 3.14 on Debian (but 3.15+
-// on other distros).
-//
-// Since NSS provides AES-GCM support starting in version 3.15, it may be
-// unavailable for Linux Chrome users.
-//
-// * !defined(CKM_AES_GCM)
-//
-// This means that at build time, the NSS header pkcs11t.h is older than
-// 3.15. However at runtime support may be present.
-//
-// * !defined(USE_NSS)
-//
-// This means that Chrome is being built with an embedded copy of NSS,
-// which can be assumed to be >= 3.15. On the other hand if USE_NSS is
-// defined, it also implies running on Linux.
-//
-// TODO(eroman): Simplify this once 3.15+ is required by Linux builds.
-#if !defined(CKM_AES_GCM)
-#define CKM_AES_GCM 0x00001087
-
-struct CK_GCM_PARAMS {
- CK_BYTE_PTR pIv;
- CK_ULONG ulIvLen;
- CK_BYTE_PTR pAAD;
- CK_ULONG ulAADLen;
- CK_ULONG ulTagBits;
-};
-#endif // !defined(CKM_AES_GCM)
-
-namespace {
-
-// Signature for PK11_Encrypt and PK11_Decrypt.
-typedef SECStatus (*PK11_EncryptDecryptFunction)(PK11SymKey*,
- CK_MECHANISM_TYPE,
- SECItem*,
- unsigned char*,
- unsigned int*,
- unsigned int,
- const unsigned char*,
- unsigned int);
-
-// Signature for PK11_PubEncrypt
-typedef SECStatus (*PK11_PubEncryptFunction)(SECKEYPublicKey*,
- CK_MECHANISM_TYPE,
- SECItem*,
- unsigned char*,
- unsigned int*,
- unsigned int,
- const unsigned char*,
- unsigned int,
- void*);
-
-// Signature for PK11_PrivDecrypt
-typedef SECStatus (*PK11_PrivDecryptFunction)(SECKEYPrivateKey*,
- CK_MECHANISM_TYPE,
- SECItem*,
- unsigned char*,
- unsigned int*,
- unsigned int,
- const unsigned char*,
- unsigned int);
-
-// Singleton to abstract away dynamically loading libnss3.so
-class NssRuntimeSupport {
- public:
- bool IsAesGcmSupported() const {
- return pk11_encrypt_func_ && pk11_decrypt_func_;
- }
-
- bool IsRsaOaepSupported() const {
- return pk11_pub_encrypt_func_ && pk11_priv_decrypt_func_ &&
- internal_slot_does_oaep_;
- }
-
- // Returns NULL if unsupported.
- PK11_EncryptDecryptFunction pk11_encrypt_func() const {
- return pk11_encrypt_func_;
- }
-
- // Returns NULL if unsupported.
- PK11_EncryptDecryptFunction pk11_decrypt_func() const {
- return pk11_decrypt_func_;
- }
-
- // Returns NULL if unsupported.
- PK11_PubEncryptFunction pk11_pub_encrypt_func() const {
- return pk11_pub_encrypt_func_;
- }
-
- // Returns NULL if unsupported.
- PK11_PrivDecryptFunction pk11_priv_decrypt_func() const {
- return pk11_priv_decrypt_func_;
- }
-
- private:
- friend struct base::DefaultLazyInstanceTraits<NssRuntimeSupport>;
-
- NssRuntimeSupport() : internal_slot_does_oaep_(false) {
-#if !defined(USE_NSS)
- // Using a bundled version of NSS that is guaranteed to have this symbol.
- pk11_encrypt_func_ = PK11_Encrypt;
- pk11_decrypt_func_ = PK11_Decrypt;
- pk11_pub_encrypt_func_ = PK11_PubEncrypt;
- pk11_priv_decrypt_func_ = PK11_PrivDecrypt;
- internal_slot_does_oaep_ = true;
-#else
- // Using system NSS libraries and PCKS #11 modules, which may not have the
- // necessary function (PK11_Encrypt) or mechanism support (CKM_AES_GCM).
-
- // If PK11_Encrypt() was successfully resolved, then NSS will support
- // AES-GCM directly. This was introduced in NSS 3.15.
- pk11_encrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
- dlsym(RTLD_DEFAULT, "PK11_Encrypt"));
- pk11_decrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
- dlsym(RTLD_DEFAULT, "PK11_Decrypt"));
-
- // Even though NSS's pk11wrap layer may support
- // PK11_PubEncrypt/PK11_PubDecrypt (introduced in NSS 3.16.2), it may have
- // loaded a softoken that does not include OAEP support.
- pk11_pub_encrypt_func_ = reinterpret_cast<PK11_PubEncryptFunction>(
- dlsym(RTLD_DEFAULT, "PK11_PubEncrypt"));
- pk11_priv_decrypt_func_ = reinterpret_cast<PK11_PrivDecryptFunction>(
- dlsym(RTLD_DEFAULT, "PK11_PrivDecrypt"));
- if (pk11_priv_decrypt_func_ && pk11_pub_encrypt_func_) {
- crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
- internal_slot_does_oaep_ =
- !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP);
- }
-#endif
- }
-
- PK11_EncryptDecryptFunction pk11_encrypt_func_;
- PK11_EncryptDecryptFunction pk11_decrypt_func_;
- PK11_PubEncryptFunction pk11_pub_encrypt_func_;
- PK11_PrivDecryptFunction pk11_priv_decrypt_func_;
- bool internal_slot_does_oaep_;
-};
-
-base::LazyInstance<NssRuntimeSupport>::Leaky g_nss_runtime_support =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-namespace content {
-
-namespace webcrypto {
-
-namespace platform {
-
-// Each key maintains a copy of its serialized form
-// in either 'raw', 'pkcs8', or 'spki' format. This is to allow
-// structured cloning of keys synchronously from the target Blink
-// thread without having to lock access to the key.
-//
-// TODO(eroman): Take advantage of this for implementing exportKey(): no need
-// to call into NSS if the serialized form already exists.
-// http://crubg.com/366836
-class SymKey : public Key {
- public:
- static Status Create(crypto::ScopedPK11SymKey key, scoped_ptr<SymKey>* out) {
- out->reset(new SymKey(key.Pass()));
- return ExportKeyRaw(out->get(), &(*out)->serialized_key_);
- }
-
- PK11SymKey* key() { return key_.get(); }
-
- virtual SymKey* AsSymKey() OVERRIDE { return this; }
- virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
- virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
-
- virtual bool ThreadSafeSerializeForClone(
- blink::WebVector<uint8>* key_data) OVERRIDE {
- key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size());
- return true;
- }
-
- private:
- explicit SymKey(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {}
-
- crypto::ScopedPK11SymKey key_;
- std::vector<uint8> serialized_key_;
-
- DISALLOW_COPY_AND_ASSIGN(SymKey);
-};
-
-class PublicKey : public Key {
- public:
- static Status Create(crypto::ScopedSECKEYPublicKey key,
- scoped_ptr<PublicKey>* out) {
- out->reset(new PublicKey(key.Pass()));
- return ExportKeySpki(out->get(), &(*out)->serialized_key_);
- }
-
- SECKEYPublicKey* key() { return key_.get(); }
-
- virtual SymKey* AsSymKey() OVERRIDE { return NULL; }
- virtual PublicKey* AsPublicKey() OVERRIDE { return this; }
- virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
-
- virtual bool ThreadSafeSerializeForClone(
- blink::WebVector<uint8>* key_data) OVERRIDE {
- key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size());
- return true;
- }
-
- private:
- explicit PublicKey(crypto::ScopedSECKEYPublicKey key) : key_(key.Pass()) {}
-
- crypto::ScopedSECKEYPublicKey key_;
- std::vector<uint8> serialized_key_;
-
- DISALLOW_COPY_AND_ASSIGN(PublicKey);
-};
-
-class PrivateKey : public Key {
- public:
- static Status Create(crypto::ScopedSECKEYPrivateKey key,
- const blink::WebCryptoKeyAlgorithm& algorithm,
- scoped_ptr<PrivateKey>* out) {
- out->reset(new PrivateKey(key.Pass()));
- return ExportKeyPkcs8(out->get(), algorithm, &(*out)->serialized_key_);
- }
-
- SECKEYPrivateKey* key() { return key_.get(); }
-
- virtual SymKey* AsSymKey() OVERRIDE { return NULL; }
- virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
- virtual PrivateKey* AsPrivateKey() OVERRIDE { return this; }
-
- virtual bool ThreadSafeSerializeForClone(
- blink::WebVector<uint8>* key_data) OVERRIDE {
- key_data->assign(Uint8VectorStart(serialized_key_), serialized_key_.size());
- return true;
- }
-
- private:
- explicit PrivateKey(crypto::ScopedSECKEYPrivateKey key) : key_(key.Pass()) {}
-
- crypto::ScopedSECKEYPrivateKey key_;
- std::vector<uint8> serialized_key_;
-
- DISALLOW_COPY_AND_ASSIGN(PrivateKey);
-};
-
-namespace {
-
-Status NssSupportsAesGcm() {
- if (g_nss_runtime_support.Get().IsAesGcmSupported())
- return Status::Success();
- return Status::ErrorUnsupported(
- "NSS version doesn't support AES-GCM. Try using version 3.15 or later");
-}
-
-Status NssSupportsRsaOaep() {
- if (g_nss_runtime_support.Get().IsRsaOaepSupported())
- return Status::Success();
- return Status::ErrorUnsupported(
- "NSS version doesn't support RSA-OAEP. Try using version 3.16.2 or "
- "later");
-}
-
-#if defined(USE_NSS) && !defined(OS_CHROMEOS)
-Status ErrorRsaKeyImportNotSupported() {
- return Status::ErrorUnsupported(
- "NSS version must be at least 3.16.2 for RSA key import. See "
- "http://crbug.com/380424");
-}
-
-Status NssSupportsKeyImport(blink::WebCryptoAlgorithmId algorithm) {
- // Prior to NSS 3.16.2 RSA key parameters were not validated. This is
- // a security problem for RSA private key import from JWK which uses a
- // CKA_ID based on the public modulus to retrieve the private key.
-
- if (!IsAlgorithmRsa(algorithm))
- return Status::Success();
-
- if (!NSS_VersionCheck("3.16.2"))
- return ErrorRsaKeyImportNotSupported();
-
- // Also ensure that the version of Softoken is 3.16.2 or later.
- crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
- CK_SLOT_INFO info = {};
- if (PK11_GetSlotInfo(slot.get(), &info) != SECSuccess)
- return ErrorRsaKeyImportNotSupported();
-
- // CK_SLOT_INFO.hardwareVersion contains the major.minor
- // version info for Softoken in the corresponding .major/.minor
- // fields, and .firmwareVersion contains the patch.build
- // version info (in the .major/.minor fields)
- if ((info.hardwareVersion.major > 3) ||
- (info.hardwareVersion.major == 3 &&
- (info.hardwareVersion.minor > 16 ||
- (info.hardwareVersion.minor == 16 &&
- info.firmwareVersion.major >= 2)))) {
- return Status::Success();
- }
-
- return ErrorRsaKeyImportNotSupported();
-}
-#else
-Status NssSupportsKeyImport(blink::WebCryptoAlgorithmId) {
- return Status::Success();
-}
-#endif
-
-// Creates a SECItem for the data in |buffer|. This does NOT make a copy, so
-// |buffer| should outlive the SECItem.
-SECItem MakeSECItemForBuffer(const CryptoData& buffer) {
- SECItem item = {
- siBuffer,
- // NSS requires non-const data even though it is just for input.
- const_cast<unsigned char*>(buffer.bytes()), buffer.byte_length()};
- return item;
-}
-
-HASH_HashType WebCryptoAlgorithmToNSSHashType(
- blink::WebCryptoAlgorithmId algorithm) {
- switch (algorithm) {
- case blink::WebCryptoAlgorithmIdSha1:
- return HASH_AlgSHA1;
- case blink::WebCryptoAlgorithmIdSha256:
- return HASH_AlgSHA256;
- case blink::WebCryptoAlgorithmIdSha384:
- return HASH_AlgSHA384;
- case blink::WebCryptoAlgorithmIdSha512:
- return HASH_AlgSHA512;
- default:
- // Not a digest algorithm.
- return HASH_AlgNULL;
- }
-}
-
-CK_MECHANISM_TYPE WebCryptoHashToHMACMechanism(
- const blink::WebCryptoAlgorithm& algorithm) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- return CKM_SHA_1_HMAC;
- case blink::WebCryptoAlgorithmIdSha256:
- return CKM_SHA256_HMAC;
- case blink::WebCryptoAlgorithmIdSha384:
- return CKM_SHA384_HMAC;
- case blink::WebCryptoAlgorithmIdSha512:
- return CKM_SHA512_HMAC;
- default:
- // Not a supported algorithm.
- return CKM_INVALID_MECHANISM;
- }
-}
-
-CK_MECHANISM_TYPE WebCryptoHashToDigestMechanism(
- const blink::WebCryptoAlgorithm& algorithm) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- return CKM_SHA_1;
- case blink::WebCryptoAlgorithmIdSha256:
- return CKM_SHA256;
- case blink::WebCryptoAlgorithmIdSha384:
- return CKM_SHA384;
- case blink::WebCryptoAlgorithmIdSha512:
- return CKM_SHA512;
- default:
- // Not a supported algorithm.
- return CKM_INVALID_MECHANISM;
- }
-}
-
-CK_MECHANISM_TYPE WebCryptoHashToMGFMechanism(
- const blink::WebCryptoAlgorithm& algorithm) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- return CKG_MGF1_SHA1;
- case blink::WebCryptoAlgorithmIdSha256:
- return CKG_MGF1_SHA256;
- case blink::WebCryptoAlgorithmIdSha384:
- return CKG_MGF1_SHA384;
- case blink::WebCryptoAlgorithmIdSha512:
- return CKG_MGF1_SHA512;
- default:
- return CKM_INVALID_MECHANISM;
- }
-}
-
-bool InitializeRsaOaepParams(const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- CK_RSA_PKCS_OAEP_PARAMS* oaep_params) {
- oaep_params->source = CKZ_DATA_SPECIFIED;
- oaep_params->pSourceData = const_cast<unsigned char*>(label.bytes());
- oaep_params->ulSourceDataLen = label.byte_length();
- oaep_params->mgf = WebCryptoHashToMGFMechanism(hash);
- oaep_params->hashAlg = WebCryptoHashToDigestMechanism(hash);
-
- if (oaep_params->mgf == CKM_INVALID_MECHANISM ||
- oaep_params->hashAlg == CKM_INVALID_MECHANISM) {
- return false;
- }
-
- return true;
-}
-
-Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& iv,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- CK_ATTRIBUTE_TYPE operation = (mode == ENCRYPT) ? CKA_ENCRYPT : CKA_DECRYPT;
-
- SECItem iv_item = MakeSECItemForBuffer(iv);
-
- crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
- if (!param)
- return Status::OperationError();
-
- crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
- CKM_AES_CBC_PAD, operation, key->key(), param.get()));
-
- if (!context.get())
- return Status::OperationError();
-
- // Oddly PK11_CipherOp takes input and output lengths as "int" rather than
- // "unsigned int". Do some checks now to avoid integer overflowing.
- if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
- // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
- // it doesn't make much difference since the one-shot API would end up
- // blowing out the memory and crashing anyway.
- return Status::ErrorDataTooLarge();
- }
-
- // PK11_CipherOp does an invalid memory access when given empty decryption
- // input, or input which is not a multiple of the block size. See also
- // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
- if (operation == CKA_DECRYPT &&
- (data.byte_length() == 0 || (data.byte_length() % AES_BLOCK_SIZE != 0))) {
- return Status::OperationError();
- }
-
- // TODO(eroman): Refine the output buffer size. It can be computed exactly for
- // encryption, and can be smaller for decryption.
- unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE;
- CHECK_GT(output_max_len, data.byte_length());
-
- buffer->resize(output_max_len);
-
- unsigned char* buffer_data = Uint8VectorStart(buffer);
-
- int output_len;
- if (SECSuccess != PK11_CipherOp(context.get(),
- buffer_data,
- &output_len,
- buffer->size(),
- data.bytes(),
- data.byte_length())) {
- return Status::OperationError();
- }
-
- unsigned int final_output_chunk_len;
- if (SECSuccess != PK11_DigestFinal(context.get(),
- buffer_data + output_len,
- &final_output_chunk_len,
- output_max_len - output_len)) {
- return Status::OperationError();
- }
-
- buffer->resize(final_output_chunk_len + output_len);
- return Status::Success();
-}
-
-// Helper to either encrypt or decrypt for AES-GCM. The result of encryption is
-// the concatenation of the ciphertext and the authentication tag. Similarly,
-// this is the expectation for the input to decryption.
-Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- const CryptoData& additional_data,
- unsigned int tag_length_bits,
- std::vector<uint8>* buffer) {
- Status status = NssSupportsAesGcm();
- if (status.IsError())
- return status;
-
- unsigned int tag_length_bytes = tag_length_bits / 8;
-
- CK_GCM_PARAMS gcm_params = {0};
- gcm_params.pIv = const_cast<unsigned char*>(iv.bytes());
- gcm_params.ulIvLen = iv.byte_length();
-
- gcm_params.pAAD = const_cast<unsigned char*>(additional_data.bytes());
- gcm_params.ulAADLen = additional_data.byte_length();
-
- gcm_params.ulTagBits = tag_length_bits;
-
- SECItem param;
- param.type = siBuffer;
- param.data = reinterpret_cast<unsigned char*>(&gcm_params);
- param.len = sizeof(gcm_params);
-
- unsigned int buffer_size = 0;
-
- // Calculate the output buffer size.
- if (mode == ENCRYPT) {
- // TODO(eroman): This is ugly, abstract away the safe integer arithmetic.
- if (data.byte_length() > (UINT_MAX - tag_length_bytes))
- return Status::ErrorDataTooLarge();
- buffer_size = data.byte_length() + tag_length_bytes;
- } else {
- // TODO(eroman): In theory the buffer allocated for the plain text should be
- // sized as |data.byte_length() - tag_length_bytes|.
- //
- // However NSS has a bug whereby it will fail if the output buffer size is
- // not at least as large as the ciphertext:
- //
- // https://bugzilla.mozilla.org/show_bug.cgi?id=%20853674
- //
- // From the analysis of that bug it looks like it might be safe to pass a
- // correctly sized buffer but lie about its size. Since resizing the
- // WebCryptoArrayBuffer is expensive that hack may be worth looking into.
- buffer_size = data.byte_length();
- }
-
- buffer->resize(buffer_size);
- unsigned char* buffer_data = Uint8VectorStart(buffer);
-
- PK11_EncryptDecryptFunction func =
- (mode == ENCRYPT) ? g_nss_runtime_support.Get().pk11_encrypt_func()
- : g_nss_runtime_support.Get().pk11_decrypt_func();
-
- unsigned int output_len = 0;
- SECStatus result = func(key->key(),
- CKM_AES_GCM,
- &param,
- buffer_data,
- &output_len,
- buffer->size(),
- data.bytes(),
- data.byte_length());
-
- if (result != SECSuccess)
- return Status::OperationError();
-
- // Unfortunately the buffer needs to be shrunk for decryption (see the NSS bug
- // above).
- buffer->resize(output_len);
-
- return Status::Success();
-}
-
-CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism(
- const blink::WebCryptoAlgorithm& algorithm) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- case blink::WebCryptoAlgorithmIdAesGcm:
- case blink::WebCryptoAlgorithmIdAesKw:
- return CKM_AES_KEY_GEN;
- case blink::WebCryptoAlgorithmIdHmac:
- return WebCryptoHashToHMACMechanism(algorithm.hmacKeyGenParams()->hash());
- default:
- return CKM_INVALID_MECHANISM;
- }
-}
-
-bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
- SECKEYPublicKey* key,
- blink::WebCryptoKeyAlgorithm* key_algorithm) {
- // TODO(eroman): What about other key types rsaPss, rsaOaep.
- if (!key || key->keyType != rsaKey)
- return false;
-
- unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8;
- CryptoData public_exponent(key->u.rsa.publicExponent.data,
- key->u.rsa.publicExponent.len);
-
- switch (algorithm.paramsType()) {
- case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
- case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
- *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(
- algorithm.id(),
- modulus_length_bits,
- public_exponent.bytes(),
- public_exponent.byte_length(),
- GetInnerHashAlgorithm(algorithm).id());
- return true;
- default:
- return false;
- }
-}
-
-bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
- SECKEYPrivateKey* key,
- blink::WebCryptoKeyAlgorithm* key_algorithm) {
- crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key));
- return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm);
-}
-
-// The Default IV for AES-KW. See http://www.ietf.org/rfc/rfc3394.txt
-// Section 2.2.3.1.
-// TODO(padolph): Move to common place to be shared with OpenSSL implementation.
-const unsigned char kAesIv[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6};
-
-// Sets NSS CK_MECHANISM_TYPE and CK_FLAGS corresponding to the input Web Crypto
-// algorithm ID.
-Status WebCryptoAlgorithmToNssMechFlags(
- const blink::WebCryptoAlgorithm& algorithm,
- CK_MECHANISM_TYPE* mechanism,
- CK_FLAGS* flags) {
- // Flags are verified at the Blink layer; here the flags are set to all
- // possible operations of a key for the input algorithm type.
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdHmac: {
- const blink::WebCryptoAlgorithm hash = GetInnerHashAlgorithm(algorithm);
- *mechanism = WebCryptoHashToHMACMechanism(hash);
- if (*mechanism == CKM_INVALID_MECHANISM)
- return Status::ErrorUnsupported();
- *flags = CKF_SIGN | CKF_VERIFY;
- return Status::Success();
- }
- case blink::WebCryptoAlgorithmIdAesCbc: {
- *mechanism = CKM_AES_CBC;
- *flags = CKF_ENCRYPT | CKF_DECRYPT;
- return Status::Success();
- }
- case blink::WebCryptoAlgorithmIdAesKw: {
- *mechanism = CKM_NSS_AES_KEY_WRAP;
- *flags = CKF_WRAP | CKF_WRAP;
- return Status::Success();
- }
- case blink::WebCryptoAlgorithmIdAesGcm: {
- Status status = NssSupportsAesGcm();
- if (status.IsError())
- return status;
- *mechanism = CKM_AES_GCM;
- *flags = CKF_ENCRYPT | CKF_DECRYPT;
- return Status::Success();
- }
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-Status DoUnwrapSymKeyAesKw(const CryptoData& wrapped_key_data,
- SymKey* wrapping_key,
- CK_MECHANISM_TYPE mechanism,
- CK_FLAGS flags,
- crypto::ScopedPK11SymKey* unwrapped_key) {
- DCHECK_GE(wrapped_key_data.byte_length(), 24u);
- DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u);
-
- SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
- crypto::ScopedSECItem param_item(
- PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
- if (!param_item)
- return Status::ErrorUnexpected();
-
- SECItem cipher_text = MakeSECItemForBuffer(wrapped_key_data);
-
- // The plaintext length is always 64 bits less than the data size.
- const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8;
-
-#if defined(USE_NSS)
- // Part of workaround for
- // https://bugzilla.mozilla.org/show_bug.cgi?id=981170. See the explanation
- // later in this function.
- PORT_SetError(0);
-#endif
-
- crypto::ScopedPK11SymKey new_key(
- PK11_UnwrapSymKeyWithFlags(wrapping_key->key(),
- CKM_NSS_AES_KEY_WRAP,
- param_item.get(),
- &cipher_text,
- mechanism,
- CKA_FLAGS_ONLY,
- plaintext_length,
- flags));
-
- // TODO(padolph): Use NSS PORT_GetError() and friends to report a more
- // accurate error, providing if doesn't leak any information to web pages
- // about other web crypto users, key details, etc.
- if (!new_key)
- return Status::OperationError();
-
-#if defined(USE_NSS)
- // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=981170
- // which was fixed in NSS 3.16.0.
- // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey,
- // with a reasonable length but with key data pointing to uninitialized
- // memory.
- // To understand this workaround see the fix for 981170:
- // https://hg.mozilla.org/projects/nss/rev/753bb69e543c
- if (!NSS_VersionCheck("3.16") && PORT_GetError() == SEC_ERROR_BAD_DATA)
- return Status::OperationError();
-#endif
-
- *unwrapped_key = new_key.Pass();
- return Status::Success();
-}
-
-void CopySECItemToVector(const SECItem& item, std::vector<uint8>* out) {
- out->assign(item.data, item.data + item.len);
-}
-
-// From PKCS#1 [http://tools.ietf.org/html/rfc3447]:
-//
-// RSAPrivateKey ::= SEQUENCE {
-// version Version,
-// modulus INTEGER, -- n
-// publicExponent INTEGER, -- e
-// privateExponent INTEGER, -- d
-// prime1 INTEGER, -- p
-// prime2 INTEGER, -- q
-// exponent1 INTEGER, -- d mod (p-1)
-// exponent2 INTEGER, -- d mod (q-1)
-// coefficient INTEGER, -- (inverse of q) mod p
-// otherPrimeInfos OtherPrimeInfos OPTIONAL
-// }
-//
-// Note that otherPrimeInfos is only applicable for version=1. Since NSS
-// doesn't use multi-prime can safely use version=0.
-struct RSAPrivateKey {
- SECItem version;
- SECItem modulus;
- SECItem public_exponent;
- SECItem private_exponent;
- SECItem prime1;
- SECItem prime2;
- SECItem exponent1;
- SECItem exponent2;
- SECItem coefficient;
-};
-
-// The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo
-// function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we
-// provide a fallback implementation.
-#if defined(USE_NSS)
-const SEC_ASN1Template RSAPrivateKeyTemplate[] = {
- {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)},
- {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)},
- {0}};
-#endif // defined(USE_NSS)
-
-// On success |value| will be filled with data which must be freed by
-// SECITEM_FreeItem(value, PR_FALSE);
-bool ReadUint(SECKEYPrivateKey* key,
- CK_ATTRIBUTE_TYPE attribute,
- SECItem* value) {
- SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value);
-
- // PK11_ReadRawAttribute() returns items of type siBuffer. However in order
- // for the ASN.1 encoding to be correct, the items must be of type
- // siUnsignedInteger.
- value->type = siUnsignedInteger;
-
- return rv == SECSuccess;
-}
-
-// Fills |out| with the RSA private key properties. Returns true on success.
-// Regardless of the return value, the caller must invoke FreeRSAPrivateKey()
-// to free up any allocated memory.
-//
-// The passed in RSAPrivateKey must be zero-initialized.
-bool InitRSAPrivateKey(SECKEYPrivateKey* key, RSAPrivateKey* out) {
- if (key->keyType != rsaKey)
- return false;
-
- // Everything should be zero-ed out. These are just some spot checks.
- DCHECK(!out->version.data);
- DCHECK(!out->version.len);
- DCHECK(!out->modulus.data);
- DCHECK(!out->modulus.len);
-
- // Always use version=0 since not using multi-prime.
- if (!SEC_ASN1EncodeInteger(NULL, &out->version, 0))
- return false;
-
- if (!ReadUint(key, CKA_MODULUS, &out->modulus))
- return false;
- if (!ReadUint(key, CKA_PUBLIC_EXPONENT, &out->public_exponent))
- return false;
- if (!ReadUint(key, CKA_PRIVATE_EXPONENT, &out->private_exponent))
- return false;
- if (!ReadUint(key, CKA_PRIME_1, &out->prime1))
- return false;
- if (!ReadUint(key, CKA_PRIME_2, &out->prime2))
- return false;
- if (!ReadUint(key, CKA_EXPONENT_1, &out->exponent1))
- return false;
- if (!ReadUint(key, CKA_EXPONENT_2, &out->exponent2))
- return false;
- if (!ReadUint(key, CKA_COEFFICIENT, &out->coefficient))
- return false;
-
- return true;
-}
-
-struct FreeRsaPrivateKey {
- void operator()(RSAPrivateKey* out) {
- SECITEM_FreeItem(&out->version, PR_FALSE);
- SECITEM_FreeItem(&out->modulus, PR_FALSE);
- SECITEM_FreeItem(&out->public_exponent, PR_FALSE);
- SECITEM_FreeItem(&out->private_exponent, PR_FALSE);
- SECITEM_FreeItem(&out->prime1, PR_FALSE);
- SECITEM_FreeItem(&out->prime2, PR_FALSE);
- SECITEM_FreeItem(&out->exponent1, PR_FALSE);
- SECITEM_FreeItem(&out->exponent2, PR_FALSE);
- SECITEM_FreeItem(&out->coefficient, PR_FALSE);
- }
-};
-
-} // namespace
-
-class DigestorNSS : public blink::WebCryptoDigestor {
- public:
- explicit DigestorNSS(blink::WebCryptoAlgorithmId algorithm_id)
- : hash_context_(NULL), algorithm_id_(algorithm_id) {}
-
- virtual ~DigestorNSS() {
- if (!hash_context_)
- return;
-
- HASH_Destroy(hash_context_);
- hash_context_ = NULL;
- }
-
- virtual bool consume(const unsigned char* data, unsigned int size) {
- return ConsumeWithStatus(data, size).IsSuccess();
- }
-
- Status ConsumeWithStatus(const unsigned char* data, unsigned int size) {
- // Initialize everything if the object hasn't been initialized yet.
- if (!hash_context_) {
- Status error = Init();
- if (!error.IsSuccess())
- return error;
- }
-
- HASH_Update(hash_context_, data, size);
-
- return Status::Success();
- }
-
- virtual bool finish(unsigned char*& result_data,
- unsigned int& result_data_size) {
- Status error = FinishInternal(result_, &result_data_size);
- if (!error.IsSuccess())
- return false;
- result_data = result_;
- return true;
- }
-
- Status FinishWithVectorAndStatus(std::vector<uint8>* result) {
- if (!hash_context_)
- return Status::ErrorUnexpected();
-
- unsigned int result_length = HASH_ResultLenContext(hash_context_);
- result->resize(result_length);
- unsigned char* digest = Uint8VectorStart(result);
- unsigned int digest_size; // ignored
- return FinishInternal(digest, &digest_size);
- }
-
- private:
- Status Init() {
- HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm_id_);
-
- if (hash_type == HASH_AlgNULL)
- return Status::ErrorUnsupported();
-
- hash_context_ = HASH_Create(hash_type);
- if (!hash_context_)
- return Status::OperationError();
-
- HASH_Begin(hash_context_);
-
- return Status::Success();
- }
-
- Status FinishInternal(unsigned char* result, unsigned int* result_size) {
- if (!hash_context_) {
- Status error = Init();
- if (!error.IsSuccess())
- return error;
- }
-
- unsigned int hash_result_length = HASH_ResultLenContext(hash_context_);
- DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
-
- HASH_End(hash_context_, result, result_size, hash_result_length);
-
- if (*result_size != hash_result_length)
- return Status::ErrorUnexpected();
- return Status::Success();
- }
-
- HASHContext* hash_context_;
- blink::WebCryptoAlgorithmId algorithm_id_;
- unsigned char result_[HASH_LENGTH_MAX];
-};
-
-Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- DCHECK(!algorithm.isNull());
-
- CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
- CK_FLAGS flags = 0;
- Status status =
- WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags);
- if (status.IsError())
- return status;
-
- SECItem key_item = MakeSECItemForBuffer(key_data);
-
- crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
- crypto::ScopedPK11SymKey pk11_sym_key(
- PK11_ImportSymKeyWithFlags(slot.get(),
- mechanism,
- PK11_OriginUnwrap,
- CKA_FLAGS_ONLY,
- &key_item,
- flags,
- false,
- NULL));
- if (!pk11_sym_key.get())
- return Status::OperationError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreateSecretKeyAlgorithm(
- algorithm, key_data.byte_length(), &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<SymKey> key_handle;
- status = SymKey::Create(pk11_sym_key.Pass(), &key_handle);
- if (status.IsError())
- return status;
-
- *key = blink::WebCryptoKey::create(key_handle.release(),
- blink::WebCryptoKeyTypeSecret,
- extractable,
- key_algorithm,
- usage_mask);
- return Status::Success();
-}
-
-Status ExportKeyRaw(SymKey* key, std::vector<uint8>* buffer) {
- if (PK11_ExtractKeyValue(key->key()) != SECSuccess)
- return Status::OperationError();
-
- // http://crbug.com/366427: the spec does not define any other failures for
- // exporting, so none of the subsequent errors are spec compliant.
- const SECItem* key_data = PK11_GetKeyData(key->key());
- if (!key_data)
- return Status::OperationError();
-
- buffer->assign(key_data->data, key_data->data + key_data->len);
-
- return Status::Success();
-}
-
-namespace {
-
-typedef scoped_ptr<CERTSubjectPublicKeyInfo,
- crypto::NSSDestroyer<CERTSubjectPublicKeyInfo,
- SECKEY_DestroySubjectPublicKeyInfo> >
- ScopedCERTSubjectPublicKeyInfo;
-
-// Validates an NSS KeyType against a WebCrypto import algorithm.
-bool ValidateNssKeyTypeAgainstInputAlgorithm(
- KeyType key_type,
- const blink::WebCryptoAlgorithm& algorithm) {
- switch (key_type) {
- case rsaKey:
- return IsAlgorithmRsa(algorithm.id());
- case dsaKey:
- case ecKey:
- case rsaPssKey:
- case rsaOaepKey:
- // TODO(padolph): Handle other key types.
- break;
- default:
- break;
- }
- return false;
-}
-
-} // namespace
-
-Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- Status status = NssSupportsKeyImport(algorithm.id());
- if (status.IsError())
- return status;
-
- DCHECK(key);
-
- if (!key_data.byte_length())
- return Status::ErrorImportEmptyKeyData();
- DCHECK(key_data.bytes());
-
- // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 Subject
- // Public Key Info. Decode this to a CERTSubjectPublicKeyInfo.
- SECItem spki_item = MakeSECItemForBuffer(key_data);
- const ScopedCERTSubjectPublicKeyInfo spki(
- SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item));
- if (!spki)
- return Status::DataError();
-
- crypto::ScopedSECKEYPublicKey sec_public_key(
- SECKEY_ExtractPublicKey(spki.get()));
- if (!sec_public_key)
- return Status::DataError();
-
- const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get());
- if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm))
- return Status::DataError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreatePublicKeyAlgorithm(
- algorithm, sec_public_key.get(), &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<PublicKey> key_handle;
- status = PublicKey::Create(sec_public_key.Pass(), &key_handle);
- if (status.IsError())
- return status;
-
- *key = blink::WebCryptoKey::create(key_handle.release(),
- blink::WebCryptoKeyTypePublic,
- extractable,
- key_algorithm,
- usage_mask);
-
- return Status::Success();
-}
-
-Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer) {
- const crypto::ScopedSECItem spki_der(
- SECKEY_EncodeDERSubjectPublicKeyInfo(key->key()));
- // http://crbug.com/366427: the spec does not define any other failures for
- // exporting, so none of the subsequent errors are spec compliant.
- if (!spki_der)
- return Status::OperationError();
-
- DCHECK(spki_der->data);
- DCHECK(spki_der->len);
-
- buffer->assign(spki_der->data, spki_der->data + spki_der->len);
-
- return Status::Success();
-}
-
-Status ExportRsaPublicKey(PublicKey* key,
- std::vector<uint8>* modulus,
- std::vector<uint8>* public_exponent) {
- DCHECK(key);
- DCHECK(key->key());
- if (key->key()->keyType != rsaKey)
- return Status::ErrorUnsupported();
- CopySECItemToVector(key->key()->u.rsa.modulus, modulus);
- CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent);
- if (modulus->empty() || public_exponent->empty())
- return Status::ErrorUnexpected();
- return Status::Success();
-}
-
-void AssignVectorFromSecItem(const SECItem& item, std::vector<uint8>* output) {
- output->assign(item.data, item.data + item.len);
-}
-
-Status ExportRsaPrivateKey(PrivateKey* key,
- std::vector<uint8>* modulus,
- std::vector<uint8>* public_exponent,
- std::vector<uint8>* private_exponent,
- std::vector<uint8>* prime1,
- std::vector<uint8>* prime2,
- std::vector<uint8>* exponent1,
- std::vector<uint8>* exponent2,
- std::vector<uint8>* coefficient) {
- RSAPrivateKey key_props = {};
- scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(&key_props);
-
- if (!InitRSAPrivateKey(key->key(), &key_props))
- return Status::OperationError();
-
- AssignVectorFromSecItem(key_props.modulus, modulus);
- AssignVectorFromSecItem(key_props.public_exponent, public_exponent);
- AssignVectorFromSecItem(key_props.private_exponent, private_exponent);
- AssignVectorFromSecItem(key_props.prime1, prime1);
- AssignVectorFromSecItem(key_props.prime2, prime2);
- AssignVectorFromSecItem(key_props.exponent1, exponent1);
- AssignVectorFromSecItem(key_props.exponent2, exponent2);
- AssignVectorFromSecItem(key_props.coefficient, coefficient);
-
- return Status::Success();
-}
-
-Status ExportKeyPkcs8(PrivateKey* key,
- const blink::WebCryptoKeyAlgorithm& key_algorithm,
- std::vector<uint8>* buffer) {
- // TODO(eroman): Support other RSA key types as they are added to Blink.
- if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 &&
- key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaOaep)
- return Status::ErrorUnsupported();
-
-// TODO(rsleevi): Implement OAEP support according to the spec.
-
-#if defined(USE_NSS)
- // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code.
- const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
- const int kPrivateKeyInfoVersion = 0;
-
- SECKEYPrivateKeyInfo private_key_info = {};
- RSAPrivateKey rsa_private_key = {};
- scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(
- &rsa_private_key);
-
- // http://crbug.com/366427: the spec does not define any other failures for
- // exporting, so none of the subsequent errors are spec compliant.
- if (!InitRSAPrivateKey(key->key(), &rsa_private_key))
- return Status::OperationError();
-
- crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
- if (!arena.get())
- return Status::OperationError();
-
- if (!SEC_ASN1EncodeItem(arena.get(),
- &private_key_info.privateKey,
- &rsa_private_key,
- RSAPrivateKeyTemplate))
- return Status::OperationError();
-
- if (SECSuccess !=
- SECOID_SetAlgorithmID(
- arena.get(), &private_key_info.algorithm, algorithm, NULL))
- return Status::OperationError();
-
- if (!SEC_ASN1EncodeInteger(
- arena.get(), &private_key_info.version, kPrivateKeyInfoVersion))
- return Status::OperationError();
-
- crypto::ScopedSECItem encoded_key(
- SEC_ASN1EncodeItem(NULL,
- NULL,
- &private_key_info,
- SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate)));
-#else // defined(USE_NSS)
- crypto::ScopedSECItem encoded_key(
- PK11_ExportDERPrivateKeyInfo(key->key(), NULL));
-#endif // defined(USE_NSS)
-
- if (!encoded_key.get())
- return Status::OperationError();
-
- buffer->assign(encoded_key->data, encoded_key->data + encoded_key->len);
- return Status::Success();
-}
-
-Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- Status status = NssSupportsKeyImport(algorithm.id());
- if (status.IsError())
- return status;
-
- DCHECK(key);
-
- if (!key_data.byte_length())
- return Status::ErrorImportEmptyKeyData();
- DCHECK(key_data.bytes());
-
- // The binary blob 'key_data' is expected to be a DER-encoded ASN.1 PKCS#8
- // private key info object.
- SECItem pki_der = MakeSECItemForBuffer(key_data);
-
- SECKEYPrivateKey* seckey_private_key = NULL;
- crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
- if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot.get(),
- &pki_der,
- NULL, // nickname
- NULL, // publicValue
- false, // isPerm
- false, // isPrivate
- KU_ALL, // usage
- &seckey_private_key,
- NULL) != SECSuccess) {
- return Status::DataError();
- }
- DCHECK(seckey_private_key);
- crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key);
-
- const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get());
- if (!ValidateNssKeyTypeAgainstInputAlgorithm(sec_key_type, algorithm))
- return Status::DataError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<PrivateKey> key_handle;
- status = PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle);
- if (status.IsError())
- return status;
-
- *key = blink::WebCryptoKey::create(key_handle.release(),
- blink::WebCryptoKeyTypePrivate,
- extractable,
- key_algorithm,
- usage_mask);
-
- return Status::Success();
-}
-
-// -----------------------------------
-// Hmac
-// -----------------------------------
-
-Status SignHmac(SymKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- DCHECK_EQ(PK11_GetMechanism(key->key()), WebCryptoHashToHMACMechanism(hash));
-
- SECItem param_item = {siBuffer, NULL, 0};
- SECItem data_item = MakeSECItemForBuffer(data);
- // First call is to figure out the length.
- SECItem signature_item = {siBuffer, NULL, 0};
-
- if (PK11_SignWithSymKey(key->key(),
- PK11_GetMechanism(key->key()),
- &param_item,
- &signature_item,
- &data_item) != SECSuccess) {
- return Status::OperationError();
- }
-
- DCHECK_NE(0u, signature_item.len);
-
- buffer->resize(signature_item.len);
- signature_item.data = Uint8VectorStart(buffer);
-
- if (PK11_SignWithSymKey(key->key(),
- PK11_GetMechanism(key->key()),
- &param_item,
- &signature_item,
- &data_item) != SECSuccess) {
- return Status::OperationError();
- }
-
- DCHECK_EQ(buffer->size(), signature_item.len);
- return Status::Success();
-}
-
-// -----------------------------------
-// RsaOaep
-// -----------------------------------
-
-Status EncryptRsaOaep(PublicKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- Status status = NssSupportsRsaOaep();
- if (status.IsError())
- return status;
-
- CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
- if (!InitializeRsaOaepParams(hash, label, &oaep_params))
- return Status::ErrorUnsupported();
-
- SECItem param;
- param.type = siBuffer;
- param.data = reinterpret_cast<unsigned char*>(&oaep_params);
- param.len = sizeof(oaep_params);
-
- buffer->resize(SECKEY_PublicKeyStrength(key->key()));
- unsigned char* buffer_data = Uint8VectorStart(buffer);
- unsigned int output_len;
- if (g_nss_runtime_support.Get().pk11_pub_encrypt_func()(key->key(),
- CKM_RSA_PKCS_OAEP,
- &param,
- buffer_data,
- &output_len,
- buffer->size(),
- data.bytes(),
- data.byte_length(),
- NULL) != SECSuccess) {
- return Status::OperationError();
- }
-
- DCHECK_LE(output_len, buffer->size());
- buffer->resize(output_len);
- return Status::Success();
-}
-
-Status DecryptRsaOaep(PrivateKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- Status status = NssSupportsRsaOaep();
- if (status.IsError())
- return status;
-
- CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
- if (!InitializeRsaOaepParams(hash, label, &oaep_params))
- return Status::ErrorUnsupported();
-
- SECItem param;
- param.type = siBuffer;
- param.data = reinterpret_cast<unsigned char*>(&oaep_params);
- param.len = sizeof(oaep_params);
-
- const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key());
- if (modulus_length_bytes <= 0)
- return Status::ErrorUnexpected();
-
- buffer->resize(modulus_length_bytes);
-
- unsigned char* buffer_data = Uint8VectorStart(buffer);
- unsigned int output_len;
- if (g_nss_runtime_support.Get().pk11_priv_decrypt_func()(
- key->key(),
- CKM_RSA_PKCS_OAEP,
- &param,
- buffer_data,
- &output_len,
- buffer->size(),
- data.bytes(),
- data.byte_length()) != SECSuccess) {
- return Status::OperationError();
- }
-
- DCHECK_LE(output_len, buffer->size());
- buffer->resize(output_len);
- return Status::Success();
-}
-
-// -----------------------------------
-// RsaSsaPkcs1v1_5
-// -----------------------------------
-
-Status SignRsaSsaPkcs1v1_5(PrivateKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // Pick the NSS signing algorithm by combining RSA-SSA (RSA PKCS1) and the
- // inner hash of the input Web Crypto algorithm.
- SECOidTag sign_alg_tag;
- switch (hash.id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- sign_alg_tag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
- break;
- case blink::WebCryptoAlgorithmIdSha256:
- sign_alg_tag = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
- break;
- case blink::WebCryptoAlgorithmIdSha384:
- sign_alg_tag = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
- break;
- case blink::WebCryptoAlgorithmIdSha512:
- sign_alg_tag = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
- break;
- default:
- return Status::ErrorUnsupported();
- }
-
- crypto::ScopedSECItem signature_item(SECITEM_AllocItem(NULL, NULL, 0));
- if (SEC_SignData(signature_item.get(),
- data.bytes(),
- data.byte_length(),
- key->key(),
- sign_alg_tag) != SECSuccess) {
- return Status::OperationError();
- }
-
- buffer->assign(signature_item->data,
- signature_item->data + signature_item->len);
- return Status::Success();
-}
-
-Status VerifyRsaSsaPkcs1v1_5(PublicKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match) {
- const SECItem signature_item = MakeSECItemForBuffer(signature);
-
- SECOidTag hash_alg_tag;
- switch (hash.id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- hash_alg_tag = SEC_OID_SHA1;
- break;
- case blink::WebCryptoAlgorithmIdSha256:
- hash_alg_tag = SEC_OID_SHA256;
- break;
- case blink::WebCryptoAlgorithmIdSha384:
- hash_alg_tag = SEC_OID_SHA384;
- break;
- case blink::WebCryptoAlgorithmIdSha512:
- hash_alg_tag = SEC_OID_SHA512;
- break;
- default:
- return Status::ErrorUnsupported();
- }
-
- *signature_match =
- SECSuccess == VFY_VerifyDataDirect(data.bytes(),
- data.byte_length(),
- key->key(),
- &signature_item,
- SEC_OID_PKCS1_RSA_ENCRYPTION,
- hash_alg_tag,
- NULL,
- NULL);
- return Status::Success();
-}
-
-Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- std::vector<uint8>* buffer) {
- // TODO(eroman): Inline.
- return AesCbcEncryptDecrypt(mode, key, iv, data, buffer);
-}
-
-Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- const CryptoData& additional_data,
- unsigned int tag_length_bits,
- std::vector<uint8>* buffer) {
- // TODO(eroman): Inline.
- return AesGcmEncryptDecrypt(
- mode, key, data, iv, additional_data, tag_length_bits, buffer);
-}
-
-// -----------------------------------
-// Key generation
-// -----------------------------------
-
-Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask public_key_usage_mask,
- blink::WebCryptoKeyUsageMask private_key_usage_mask,
- unsigned int modulus_length_bits,
- unsigned long public_exponent,
- blink::WebCryptoKey* public_key,
- blink::WebCryptoKey* private_key) {
- if (algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep) {
- Status status = NssSupportsRsaOaep();
- if (status.IsError())
- return status;
- }
-
- crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
- if (!slot)
- return Status::OperationError();
-
- PK11RSAGenParams rsa_gen_params;
- // keySizeInBits is a signed type, don't pass in a negative value.
- if (modulus_length_bits > INT_MAX)
- return Status::OperationError();
- rsa_gen_params.keySizeInBits = modulus_length_bits;
- rsa_gen_params.pe = public_exponent;
-
- // Flags are verified at the Blink layer; here the flags are set to all
- // possible operations for the given key type.
- CK_FLAGS operation_flags;
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdRsaOaep:
- operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
- break;
- case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
- operation_flags = CKF_SIGN | CKF_VERIFY;
- break;
- default:
- NOTREACHED();
- return Status::ErrorUnexpected();
- }
- const CK_FLAGS operation_flags_mask =
- CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_WRAP | CKF_UNWRAP;
-
- // The private key must be marked as insensitive and extractable, otherwise it
- // cannot later be exported in unencrypted form or structured-cloned.
- const PK11AttrFlags attribute_flags =
- PK11_ATTR_INSENSITIVE | PK11_ATTR_EXTRACTABLE;
-
- // Note: NSS does not generate an sec_public_key if the call below fails,
- // so there is no danger of a leaked sec_public_key.
- SECKEYPublicKey* sec_public_key = NULL;
- crypto::ScopedSECKEYPrivateKey scoped_sec_private_key(
- PK11_GenerateKeyPairWithOpFlags(slot.get(),
- CKM_RSA_PKCS_KEY_PAIR_GEN,
- &rsa_gen_params,
- &sec_public_key,
- attribute_flags,
- operation_flags,
- operation_flags_mask,
- NULL));
- if (!scoped_sec_private_key)
- return Status::OperationError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<PublicKey> public_key_handle;
- Status status = PublicKey::Create(
- crypto::ScopedSECKEYPublicKey(sec_public_key), &public_key_handle);
- if (status.IsError())
- return status;
-
- scoped_ptr<PrivateKey> private_key_handle;
- status = PrivateKey::Create(
- scoped_sec_private_key.Pass(), key_algorithm, &private_key_handle);
- if (status.IsError())
- return status;
-
- *public_key = blink::WebCryptoKey::create(public_key_handle.release(),
- blink::WebCryptoKeyTypePublic,
- true,
- key_algorithm,
- public_key_usage_mask);
- *private_key = blink::WebCryptoKey::create(private_key_handle.release(),
- blink::WebCryptoKeyTypePrivate,
- extractable,
- key_algorithm,
- private_key_usage_mask);
-
- return Status::Success();
-}
-
-void Init() {
- crypto::EnsureNSSInit();
-}
-
-Status DigestSha(blink::WebCryptoAlgorithmId algorithm,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- DigestorNSS digestor(algorithm);
- Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
- // http://crbug.com/366427: the spec does not define any other failures for
- // digest, so none of the subsequent errors are spec compliant.
- if (!error.IsSuccess())
- return error;
- return digestor.FinishWithVectorAndStatus(buffer);
-}
-
-scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
- blink::WebCryptoAlgorithmId algorithm_id) {
- return scoped_ptr<blink::WebCryptoDigestor>(new DigestorNSS(algorithm_id));
-}
-
-Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- unsigned keylen_bytes,
- blink::WebCryptoKey* key) {
- CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm);
- blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret;
-
- if (mech == CKM_INVALID_MECHANISM)
- return Status::ErrorUnsupported();
-
- crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
- if (!slot)
- return Status::OperationError();
-
- crypto::ScopedPK11SymKey pk11_key(
- PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL));
-
- if (!pk11_key)
- return Status::OperationError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<SymKey> key_handle;
- Status status = SymKey::Create(pk11_key.Pass(), &key_handle);
- if (status.IsError())
- return status;
-
- *key = blink::WebCryptoKey::create(
- key_handle.release(), key_type, extractable, key_algorithm, usage_mask);
- return Status::Success();
-}
-
-Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& modulus_data,
- const CryptoData& exponent_data,
- blink::WebCryptoKey* key) {
- if (!modulus_data.byte_length())
- return Status::ErrorImportRsaEmptyModulus();
-
- if (!exponent_data.byte_length())
- return Status::ErrorImportRsaEmptyExponent();
-
- DCHECK(modulus_data.bytes());
- DCHECK(exponent_data.bytes());
-
- // NSS does not provide a way to create an RSA public key directly from the
- // modulus and exponent values, but it can import an DER-encoded ASN.1 blob
- // with these values and create the public key from that. The code below
- // follows the recommendation described in
- // https://developer.mozilla.org/en-US/docs/NSS/NSS_Tech_Notes/nss_tech_note7
-
- // Pack the input values into a struct compatible with NSS ASN.1 encoding, and
- // set up an ASN.1 encoder template for it.
- struct RsaPublicKeyData {
- SECItem modulus;
- SECItem exponent;
- };
- const RsaPublicKeyData pubkey_in = {
- {siUnsignedInteger, const_cast<unsigned char*>(modulus_data.bytes()),
- modulus_data.byte_length()},
- {siUnsignedInteger, const_cast<unsigned char*>(exponent_data.bytes()),
- exponent_data.byte_length()}};
- const SEC_ASN1Template rsa_public_key_template[] = {
- {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RsaPublicKeyData)},
- {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, modulus), },
- {SEC_ASN1_INTEGER, offsetof(RsaPublicKeyData, exponent), },
- {0, }};
-
- // DER-encode the public key.
- crypto::ScopedSECItem pubkey_der(
- SEC_ASN1EncodeItem(NULL, NULL, &pubkey_in, rsa_public_key_template));
- if (!pubkey_der)
- return Status::OperationError();
-
- // Import the DER-encoded public key to create an RSA SECKEYPublicKey.
- crypto::ScopedSECKEYPublicKey pubkey(
- SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA));
- if (!pubkey)
- return Status::OperationError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<PublicKey> key_handle;
- Status status = PublicKey::Create(pubkey.Pass(), &key_handle);
- if (status.IsError())
- return status;
-
- *key = blink::WebCryptoKey::create(key_handle.release(),
- blink::WebCryptoKeyTypePublic,
- extractable,
- key_algorithm,
- usage_mask);
- return Status::Success();
-}
-
-struct DestroyGenericObject {
- void operator()(PK11GenericObject* o) const {
- if (o)
- PK11_DestroyGenericObject(o);
- }
-};
-
-typedef scoped_ptr<PK11GenericObject, DestroyGenericObject>
- ScopedPK11GenericObject;
-
-// Helper to add an attribute to a template.
-void AddAttribute(CK_ATTRIBUTE_TYPE type,
- void* value,
- unsigned long length,
- std::vector<CK_ATTRIBUTE>* templ) {
- CK_ATTRIBUTE attribute = {type, value, length};
- templ->push_back(attribute);
-}
-
-// Helper to optionally add an attribute to a template, if the provided data is
-// non-empty.
-void AddOptionalAttribute(CK_ATTRIBUTE_TYPE type,
- const CryptoData& data,
- std::vector<CK_ATTRIBUTE>* templ) {
- if (!data.byte_length())
- return;
- CK_ATTRIBUTE attribute = {type, const_cast<unsigned char*>(data.bytes()),
- data.byte_length()};
- templ->push_back(attribute);
-}
-
-Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& modulus,
- const CryptoData& public_exponent,
- const CryptoData& private_exponent,
- const CryptoData& prime1,
- const CryptoData& prime2,
- const CryptoData& exponent1,
- const CryptoData& exponent2,
- const CryptoData& coefficient,
- blink::WebCryptoKey* key) {
- Status status = NssSupportsKeyImport(algorithm.id());
- if (status.IsError())
- return status;
-
- CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
- CK_KEY_TYPE key_type = CKK_RSA;
- CK_BBOOL ck_false = CK_FALSE;
-
- std::vector<CK_ATTRIBUTE> key_template;
-
- AddAttribute(CKA_CLASS, &obj_class, sizeof(obj_class), &key_template);
- AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template);
- AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template);
- AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template);
- AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template);
-
- // Required properties.
- AddOptionalAttribute(CKA_MODULUS, modulus, &key_template);
- AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template);
- AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template);
-
- // Manufacture a CKA_ID so the created key can be retrieved later as a
- // SECKEYPrivateKey using FindKeyByKeyID(). Unfortunately there isn't a more
- // direct way to do this in NSS.
- //
- // For consistency with other NSS key creation methods, set the CKA_ID to
- // PK11_MakeIDFromPubKey(). There are some problems with
- // this approach:
- //
- // (1) Prior to NSS 3.16.2, there is no parameter validation when creating
- // private keys. It is therefore possible to construct a key using the
- // known public modulus, and where all the other parameters are bogus.
- // FindKeyByKeyID() returns the first key matching the ID. So this would
- // effectively allow an attacker to retrieve a private key of their
- // choice.
- // TODO(eroman): Once NSS rolls and this is fixed, disallow RSA key
- // import on older versions of NSS.
- // http://crbug.com/378315
- //
- // (2) The ID space is shared by different key types. So theoretically
- // possible to retrieve a key of the wrong type which has a matching
- // CKA_ID. In practice I am told this is not likely except for small key
- // sizes, since would require constructing keys with the same public
- // data.
- //
- // (3) FindKeyByKeyID() doesn't necessarily return the object that was just
- // created by CreateGenericObject. If the pre-existing key was
- // provisioned with flags incompatible with WebCrypto (for instance
- // marked sensitive) then this will break things.
- SECItem modulus_item = MakeSECItemForBuffer(CryptoData(modulus));
- crypto::ScopedSECItem object_id(PK11_MakeIDFromPubKey(&modulus_item));
- AddOptionalAttribute(
- CKA_ID, CryptoData(object_id->data, object_id->len), &key_template);
-
- // Optional properties (all of these will have been specified or none).
- AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template);
- AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template);
- AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template);
- AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template);
- AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template);
-
- crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
-
- ScopedPK11GenericObject key_object(PK11_CreateGenericObject(
- slot.get(), &key_template[0], key_template.size(), PR_FALSE));
-
- if (!key_object)
- return Status::OperationError();
-
- crypto::ScopedSECKEYPrivateKey private_key_tmp(
- PK11_FindKeyByKeyID(slot.get(), object_id.get(), NULL));
-
- // PK11_FindKeyByKeyID() may return a handle to an existing key, rather than
- // the object created by PK11_CreateGenericObject().
- crypto::ScopedSECKEYPrivateKey private_key(
- SECKEY_CopyPrivateKey(private_key_tmp.get()));
-
- if (!private_key)
- return Status::OperationError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm))
- return Status::ErrorUnexpected();
-
- scoped_ptr<PrivateKey> key_handle;
- status = PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle);
- if (status.IsError())
- return status;
-
- *key = blink::WebCryptoKey::create(key_handle.release(),
- blink::WebCryptoKeyTypePrivate,
- extractable,
- key_algorithm,
- usage_mask);
- return Status::Success();
-}
-
-Status WrapSymKeyAesKw(PK11SymKey* key,
- SymKey* wrapping_key,
- std::vector<uint8>* buffer) {
- // The data size must be at least 16 bytes and a multiple of 8 bytes.
- // RFC 3394 does not specify a maximum allowed data length, but since only
- // keys are being wrapped in this application (which are small), a reasonable
- // max limit is whatever will fit into an unsigned. For the max size test,
- // note that AES Key Wrap always adds 8 bytes to the input data size.
- const unsigned int input_length = PK11_GetKeyLength(key);
- DCHECK_GE(input_length, 16u);
- DCHECK((input_length % 8) == 0);
- if (input_length > UINT_MAX - 8)
- return Status::ErrorDataTooLarge();
-
- SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
- crypto::ScopedSECItem param_item(
- PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
- if (!param_item)
- return Status::ErrorUnexpected();
-
- const unsigned int output_length = input_length + 8;
- buffer->resize(output_length);
- SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer));
-
- if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP,
- param_item.get(),
- wrapping_key->key(),
- key,
- &wrapped_key_item)) {
- return Status::OperationError();
- }
- if (output_length != wrapped_key_item.len)
- return Status::ErrorUnexpected();
-
- return Status::Success();
-}
-
-Status DecryptAesKw(SymKey* wrapping_key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be
- // temporarily viewed as a symmetric key to be unwrapped (decrypted).
- crypto::ScopedPK11SymKey decrypted;
- Status status = DoUnwrapSymKeyAesKw(
- data, wrapping_key, CKK_GENERIC_SECRET, 0, &decrypted);
- if (status.IsError())
- return status;
-
- // Once the decrypt is complete, extract the resultant raw bytes from NSS and
- // return them to the caller.
- if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess)
- return Status::OperationError();
- const SECItem* const key_data = PK11_GetKeyData(decrypted.get());
- if (!key_data)
- return Status::OperationError();
- buffer->assign(key_data->data, key_data->data + key_data->len);
-
- return Status::Success();
-}
-
-Status EncryptAesKw(SymKey* wrapping_key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be
- // temporarily viewed as a symmetric key to be wrapped (encrypted).
- SECItem data_item = MakeSECItemForBuffer(data);
- crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
- crypto::ScopedPK11SymKey data_as_sym_key(PK11_ImportSymKey(slot.get(),
- CKK_GENERIC_SECRET,
- PK11_OriginUnwrap,
- CKA_SIGN,
- &data_item,
- NULL));
- if (!data_as_sym_key)
- return Status::OperationError();
-
- return WrapSymKeyAesKw(data_as_sym_key.get(), wrapping_key, buffer);
-}
-
-Status EncryptDecryptAesKw(EncryptOrDecrypt mode,
- SymKey* wrapping_key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- return mode == ENCRYPT ? EncryptAesKw(wrapping_key, data, buffer)
- : DecryptAesKw(wrapping_key, data, buffer);
-}
-
-} // namespace platform
-
-} // namespace webcrypto
-
-} // namespace content
diff --git a/chromium/content/child/webcrypto/platform_crypto_openssl.cc b/chromium/content/child/webcrypto/platform_crypto_openssl.cc
deleted file mode 100644
index 1235e51f2cc..00000000000
--- a/chromium/content/child/webcrypto/platform_crypto_openssl.cc
+++ /dev/null
@@ -1,520 +0,0 @@
-// Copyright 2014 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 "content/child/webcrypto/platform_crypto.h"
-
-#include <vector>
-#include <openssl/aes.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/child/webcrypto/crypto_data.h"
-#include "content/child/webcrypto/status.h"
-#include "content/child/webcrypto/webcrypto_util.h"
-#include "crypto/openssl_util.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
-
-namespace content {
-
-namespace webcrypto {
-
-namespace platform {
-
-class SymKey : public Key {
- public:
- explicit SymKey(const CryptoData& key_data)
- : key_(key_data.bytes(), key_data.bytes() + key_data.byte_length()) {}
-
- virtual SymKey* AsSymKey() OVERRIDE { return this; }
- virtual PublicKey* AsPublicKey() OVERRIDE { return NULL; }
- virtual PrivateKey* AsPrivateKey() OVERRIDE { return NULL; }
- virtual bool ThreadSafeSerializeForClone(
- blink::WebVector<uint8>* key_data) OVERRIDE {
- key_data->assign(Uint8VectorStart(key_), key_.size());
- return true;
- }
-
- const std::vector<unsigned char>& key() const { return key_; }
-
- private:
- const std::vector<unsigned char> key_;
-
- DISALLOW_COPY_AND_ASSIGN(SymKey);
-};
-
-namespace {
-
-const EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) {
- // OpenSSL supports AES CBC ciphers for only 3 key lengths: 128, 192, 256 bits
- switch (key_length_bytes) {
- case 16:
- return EVP_aes_128_cbc();
- case 24:
- return EVP_aes_192_cbc();
- case 32:
- return EVP_aes_256_cbc();
- default:
- return NULL;
- }
-}
-
-const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) {
- switch (id) {
- case blink::WebCryptoAlgorithmIdSha1:
- return EVP_sha1();
- case blink::WebCryptoAlgorithmIdSha256:
- return EVP_sha256();
- case blink::WebCryptoAlgorithmIdSha384:
- return EVP_sha384();
- case blink::WebCryptoAlgorithmIdSha512:
- return EVP_sha512();
- default:
- return NULL;
- }
-}
-
-// OpenSSL constants for EVP_CipherInit_ex(), do not change
-enum CipherOperation { kDoDecrypt = 0, kDoEncrypt = 1 };
-
-Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& iv,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- CipherOperation cipher_operation =
- (mode == ENCRYPT) ? kDoEncrypt : kDoDecrypt;
-
- if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
- // TODO(padolph): Handle this by chunking the input fed into OpenSSL. Right
- // now it doesn't make much difference since the one-shot API would end up
- // blowing out the memory and crashing anyway.
- return Status::ErrorDataTooLarge();
- }
-
- // Note: PKCS padding is enabled by default
- crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> context(
- EVP_CIPHER_CTX_new());
-
- if (!context.get())
- return Status::OperationError();
-
- const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(key->key().size());
- DCHECK(cipher);
-
- if (!EVP_CipherInit_ex(context.get(),
- cipher,
- NULL,
- &key->key()[0],
- iv.bytes(),
- cipher_operation)) {
- return Status::OperationError();
- }
-
- // According to the openssl docs, the amount of data written may be as large
- // as (data_size + cipher_block_size - 1), constrained to a multiple of
- // cipher_block_size.
- unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE - 1;
- const unsigned remainder = output_max_len % AES_BLOCK_SIZE;
- if (remainder != 0)
- output_max_len += AES_BLOCK_SIZE - remainder;
- DCHECK_GT(output_max_len, data.byte_length());
-
- buffer->resize(output_max_len);
-
- unsigned char* const buffer_data = Uint8VectorStart(buffer);
-
- int output_len = 0;
- if (!EVP_CipherUpdate(context.get(),
- buffer_data,
- &output_len,
- data.bytes(),
- data.byte_length()))
- return Status::OperationError();
- int final_output_chunk_len = 0;
- if (!EVP_CipherFinal_ex(
- context.get(), buffer_data + output_len, &final_output_chunk_len)) {
- return Status::OperationError();
- }
-
- const unsigned int final_output_len =
- static_cast<unsigned int>(output_len) +
- static_cast<unsigned int>(final_output_chunk_len);
- DCHECK_LE(final_output_len, output_max_len);
-
- buffer->resize(final_output_len);
-
- return Status::Success();
-}
-
-} // namespace
-
-class DigestorOpenSSL : public blink::WebCryptoDigestor {
- public:
- explicit DigestorOpenSSL(blink::WebCryptoAlgorithmId algorithm_id)
- : initialized_(false),
- digest_context_(EVP_MD_CTX_create()),
- algorithm_id_(algorithm_id) {}
-
- virtual bool consume(const unsigned char* data, unsigned int size) {
- return ConsumeWithStatus(data, size).IsSuccess();
- }
-
- Status ConsumeWithStatus(const unsigned char* data, unsigned int size) {
- crypto::OpenSSLErrStackTracer(FROM_HERE);
- Status error = Init();
- if (!error.IsSuccess())
- return error;
-
- if (!EVP_DigestUpdate(digest_context_.get(), data, size))
- return Status::OperationError();
-
- return Status::Success();
- }
-
- virtual bool finish(unsigned char*& result_data,
- unsigned int& result_data_size) {
- Status error = FinishInternal(result_, &result_data_size);
- if (!error.IsSuccess())
- return false;
- result_data = result_;
- return true;
- }
-
- Status FinishWithVectorAndStatus(std::vector<uint8>* result) {
- const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get());
- result->resize(hash_expected_size);
- unsigned char* const hash_buffer = Uint8VectorStart(result);
- unsigned int hash_buffer_size; // ignored
- return FinishInternal(hash_buffer, &hash_buffer_size);
- }
-
- private:
- Status Init() {
- if (initialized_)
- return Status::Success();
-
- const EVP_MD* digest_algorithm = GetDigest(algorithm_id_);
- if (!digest_algorithm)
- return Status::ErrorUnexpected();
-
- if (!digest_context_.get())
- return Status::OperationError();
-
- if (!EVP_DigestInit_ex(digest_context_.get(), digest_algorithm, NULL))
- return Status::OperationError();
-
- initialized_ = true;
- return Status::Success();
- }
-
- Status FinishInternal(unsigned char* result, unsigned int* result_size) {
- crypto::OpenSSLErrStackTracer(FROM_HERE);
- Status error = Init();
- if (!error.IsSuccess())
- return error;
-
- const int hash_expected_size = EVP_MD_CTX_size(digest_context_.get());
- if (hash_expected_size <= 0)
- return Status::ErrorUnexpected();
- DCHECK_LE(hash_expected_size, EVP_MAX_MD_SIZE);
-
- if (!EVP_DigestFinal_ex(digest_context_.get(), result, result_size) ||
- static_cast<int>(*result_size) != hash_expected_size)
- return Status::OperationError();
-
- return Status::Success();
- }
-
- bool initialized_;
- crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context_;
- blink::WebCryptoAlgorithmId algorithm_id_;
- unsigned char result_[EVP_MAX_MD_SIZE];
-};
-
-Status ExportKeyRaw(SymKey* key, std::vector<uint8>* buffer) {
- *buffer = key->key();
- return Status::Success();
-}
-
-void Init() { crypto::EnsureOpenSSLInit(); }
-
-Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- std::vector<uint8>* buffer) {
- // TODO(eroman): inline the function here.
- return AesCbcEncryptDecrypt(mode, key, iv, data, buffer);
-}
-
-Status DigestSha(blink::WebCryptoAlgorithmId algorithm,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- DigestorOpenSSL digestor(algorithm);
- Status error = digestor.ConsumeWithStatus(data.bytes(), data.byte_length());
- if (!error.IsSuccess())
- return error;
- return digestor.FinishWithVectorAndStatus(buffer);
-}
-
-scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
- blink::WebCryptoAlgorithmId algorithm_id) {
- return scoped_ptr<blink::WebCryptoDigestor>(
- new DigestorOpenSSL(algorithm_id));
-}
-
-Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- unsigned keylen_bytes,
- blink::WebCryptoKey* key) {
- // TODO(eroman): Is this right?
- if (keylen_bytes == 0)
- return Status::ErrorGenerateKeyLength();
-
- crypto::OpenSSLErrStackTracer(FROM_HERE);
-
- std::vector<unsigned char> random_bytes(keylen_bytes, 0);
- if (!(RAND_bytes(&random_bytes[0], keylen_bytes)))
- return Status::OperationError();
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreateSecretKeyAlgorithm(algorithm, keylen_bytes, &key_algorithm))
- return Status::ErrorUnexpected();
-
- *key = blink::WebCryptoKey::create(new SymKey(CryptoData(random_bytes)),
- blink::WebCryptoKeyTypeSecret,
- extractable,
- key_algorithm,
- usage_mask);
-
- return Status::Success();
-}
-
-Status GenerateRsaKeyPair(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask public_key_usage_mask,
- blink::WebCryptoKeyUsageMask private_key_usage_mask,
- unsigned int modulus_length_bits,
- unsigned long public_exponent,
- blink::WebCryptoKey* public_key,
- blink::WebCryptoKey* private_key) {
- // TODO(padolph): Placeholder for OpenSSL implementation.
- // Issue http://crbug.com/267888.
- return Status::ErrorUnsupported();
-}
-
-Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
-
- blink::WebCryptoKeyAlgorithm key_algorithm;
- if (!CreateSecretKeyAlgorithm(
- algorithm, key_data.byte_length(), &key_algorithm))
- return Status::ErrorUnexpected();
-
- *key = blink::WebCryptoKey::create(new SymKey(key_data),
- blink::WebCryptoKeyTypeSecret,
- extractable,
- key_algorithm,
- usage_mask);
-
- return Status::Success();
-}
-
-Status SignHmac(SymKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- const EVP_MD* digest_algorithm = GetDigest(hash.id());
- if (!digest_algorithm)
- return Status::ErrorUnsupported();
- unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm);
-
- const std::vector<unsigned char>& raw_key = key->key();
-
- // OpenSSL wierdness here.
- // First, HMAC() needs a void* for the key data, so make one up front as a
- // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key,
- // which will result if the raw_key vector is empty; an entirely valid
- // case. Handle this specific case by pointing to an empty array.
- const unsigned char null_key[] = {};
- const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key;
-
- buffer->resize(hmac_expected_length);
- crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result(
- Uint8VectorStart(buffer), hmac_expected_length);
-
- crypto::OpenSSLErrStackTracer(FROM_HERE);
-
- unsigned int hmac_actual_length;
- unsigned char* const success = HMAC(digest_algorithm,
- raw_key_voidp,
- raw_key.size(),
- data.bytes(),
- data.byte_length(),
- hmac_result.safe_buffer(),
- &hmac_actual_length);
- if (!success || hmac_actual_length != hmac_expected_length)
- return Status::OperationError();
-
- return Status::Success();
-}
-
-Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& modulus_data,
- const CryptoData& exponent_data,
- blink::WebCryptoKey* key) {
- // TODO(padolph): Placeholder for OpenSSL implementation.
- // Issue
- return Status::ErrorUnsupported();
-}
-
-Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& modulus,
- const CryptoData& public_exponent,
- const CryptoData& private_exponent,
- const CryptoData& prime1,
- const CryptoData& prime2,
- const CryptoData& exponent1,
- const CryptoData& exponent2,
- const CryptoData& coefficient,
- blink::WebCryptoKey* key) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- const CryptoData& iv,
- const CryptoData& additional_data,
- unsigned int tag_length_bits,
- std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status EncryptRsaOaep(PublicKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status DecryptRsaOaep(PrivateKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& label,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status SignRsaSsaPkcs1v1_5(PrivateKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-// Key is guaranteed to be an RSA SSA key.
-Status VerifyRsaSsaPkcs1v1_5(PublicKey* key,
- const blink::WebCryptoAlgorithm& hash,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status ImportKeySpki(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& key_data,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status ExportKeySpki(PublicKey* key, std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status ExportKeyPkcs8(PrivateKey* key,
- const blink::WebCryptoKeyAlgorithm& key_algorithm,
- std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status ExportRsaPublicKey(PublicKey* key,
- std::vector<uint8>* modulus,
- std::vector<uint8>* public_exponent) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status ExportRsaPrivateKey(PrivateKey* key,
- std::vector<uint8>* modulus,
- std::vector<uint8>* public_exponent,
- std::vector<uint8>* private_exponent,
- std::vector<uint8>* prime1,
- std::vector<uint8>* prime2,
- std::vector<uint8>* exponent1,
- std::vector<uint8>* exponent2,
- std::vector<uint8>* coefficient) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-Status EncryptDecryptAesKw(EncryptOrDecrypt mode,
- SymKey* key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- // TODO(eroman): http://crbug.com/267888
- return Status::ErrorUnsupported();
-}
-
-bool ThreadSafeDeserializeKeyForClone(
- const blink::WebCryptoKeyAlgorithm& algorithm,
- blink::WebCryptoKeyType type,
- bool extractable,
- blink::WebCryptoKeyUsageMask usages,
- const CryptoData& key_data,
- blink::WebCryptoKey* key) {
- // TODO(eroman): http://crbug.com/267888
- return false;
-}
-
-} // namespace platform
-
-} // namespace webcrypto
-
-} // namespace content
diff --git a/chromium/content/child/webcrypto/shared_crypto.cc b/chromium/content/child/webcrypto/shared_crypto.cc
deleted file mode 100644
index 65559b04c82..00000000000
--- a/chromium/content/child/webcrypto/shared_crypto.cc
+++ /dev/null
@@ -1,955 +0,0 @@
-// Copyright 2014 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 "content/child/webcrypto/shared_crypto.h"
-
-#include "base/logging.h"
-#include "content/child/webcrypto/crypto_data.h"
-#include "content/child/webcrypto/jwk.h"
-#include "content/child/webcrypto/platform_crypto.h"
-#include "content/child/webcrypto/status.h"
-#include "content/child/webcrypto/webcrypto_util.h"
-#include "crypto/secure_util.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-#include "third_party/WebKit/public/platform/WebCryptoKey.h"
-#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
-
-namespace content {
-
-namespace webcrypto {
-
-// ------------
-// Threading:
-// ------------
-//
-// All functions in this file are called from the webcrypto worker pool except
-// for:
-//
-// * SerializeKeyForClone()
-// * DeserializeKeyForClone()
-// * ImportKey() // TODO(eroman): Change this.
-
-namespace {
-
-// TODO(eroman): Move this helper to WebCryptoKey.
-bool KeyUsageAllows(const blink::WebCryptoKey& key,
- const blink::WebCryptoKeyUsage usage) {
- return ((key.usages() & usage) != 0);
-}
-
-bool IsValidAesKeyLengthBits(unsigned int length_bits) {
- // 192-bit AES is disallowed.
- return length_bits == 128 || length_bits == 256;
-}
-
-bool IsValidAesKeyLengthBytes(unsigned int length_bytes) {
- // 192-bit AES is disallowed.
- return length_bytes == 16 || length_bytes == 32;
-}
-
-const size_t kAesBlockSizeBytes = 16;
-
-Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
- const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::SymKey* sym_key;
- Status status = ToPlatformSymKey(key, &sym_key);
- if (status.IsError())
- return status;
-
- const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
- if (!params)
- return Status::ErrorUnexpected();
-
- CryptoData iv(params->iv().data(), params->iv().size());
- if (iv.byte_length() != kAesBlockSizeBytes)
- return Status::ErrorIncorrectSizeAesCbcIv();
-
- return platform::EncryptDecryptAesCbc(mode, sym_key, data, iv, buffer);
-}
-
-Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
- const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::SymKey* sym_key;
- Status status = ToPlatformSymKey(key, &sym_key);
- if (status.IsError())
- return status;
-
- const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
- if (!params)
- return Status::ErrorUnexpected();
-
- unsigned int tag_length_bits = 128;
- if (params->hasTagLengthBits())
- tag_length_bits = params->optionalTagLengthBits();
-
- if (tag_length_bits != 32 && tag_length_bits != 64 && tag_length_bits != 96 &&
- tag_length_bits != 104 && tag_length_bits != 112 &&
- tag_length_bits != 120 && tag_length_bits != 128)
- return Status::ErrorInvalidAesGcmTagLength();
-
- return platform::EncryptDecryptAesGcm(
- mode,
- sym_key,
- data,
- CryptoData(params->iv()),
- CryptoData(params->optionalAdditionalData()),
- tag_length_bits,
- buffer);
-}
-
-Status EncryptRsaOaep(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::PublicKey* public_key;
- Status status = ToPlatformPublicKey(key, &public_key);
- if (status.IsError())
- return status;
-
- const blink::WebCryptoRsaOaepParams* params = algorithm.rsaOaepParams();
- if (!params)
- return Status::ErrorUnexpected();
-
- return platform::EncryptRsaOaep(public_key,
- key.algorithm().rsaHashedParams()->hash(),
- CryptoData(params->optionalLabel()),
- data,
- buffer);
-}
-
-Status DecryptRsaOaep(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::PrivateKey* private_key;
- Status status = ToPlatformPrivateKey(key, &private_key);
- if (status.IsError())
- return status;
-
- const blink::WebCryptoRsaOaepParams* params = algorithm.rsaOaepParams();
- if (!params)
- return Status::ErrorUnexpected();
-
- return platform::DecryptRsaOaep(private_key,
- key.algorithm().rsaHashedParams()->hash(),
- CryptoData(params->optionalLabel()),
- data,
- buffer);
-}
-
-Status SignHmac(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::SymKey* sym_key;
- Status status = ToPlatformSymKey(key, &sym_key);
- if (status.IsError())
- return status;
-
- return platform::SignHmac(
- sym_key, key.algorithm().hmacParams()->hash(), data, buffer);
-}
-
-Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match) {
- std::vector<uint8> result;
- Status status = SignHmac(algorithm, key, data, &result);
- if (status.IsError())
- return status;
-
- // Do not allow verification of truncated MACs.
- *signature_match =
- result.size() == signature.byte_length() &&
- crypto::SecureMemEqual(
- Uint8VectorStart(result), signature.bytes(), signature.byte_length());
-
- return Status::Success();
-}
-
-Status SignRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::PrivateKey* private_key;
- Status status = ToPlatformPrivateKey(key, &private_key);
- if (status.IsError())
- return status;
-
- return platform::SignRsaSsaPkcs1v1_5(
- private_key, key.algorithm().rsaHashedParams()->hash(), data, buffer);
-}
-
-Status VerifyRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match) {
- platform::PublicKey* public_key;
- Status status = ToPlatformPublicKey(key, &public_key);
- if (status.IsError())
- return status;
-
- return platform::VerifyRsaSsaPkcs1v1_5(
- public_key,
- key.algorithm().rsaHashedParams()->hash(),
- signature,
- data,
- signature_match);
-}
-
-// Note that this function may be called from the target Blink thread.
-Status ImportKeyRaw(const CryptoData& key_data,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCtr:
- case blink::WebCryptoAlgorithmIdAesCbc:
- case blink::WebCryptoAlgorithmIdAesGcm:
- case blink::WebCryptoAlgorithmIdAesKw:
- if (!IsValidAesKeyLengthBytes(key_data.byte_length())) {
- return key_data.byte_length() == 24
- ? Status::ErrorAes192BitUnsupported()
- : Status::ErrorImportAesKeyLength();
- }
- // Fallthrough intentional!
- case blink::WebCryptoAlgorithmIdHmac:
- return platform::ImportKeyRaw(
- algorithm, key_data, extractable, usage_mask, key);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-// Returns the key format to use for structured cloning.
-blink::WebCryptoKeyFormat GetCloneFormatForKeyType(
- blink::WebCryptoKeyType type) {
- switch (type) {
- case blink::WebCryptoKeyTypeSecret:
- return blink::WebCryptoKeyFormatRaw;
- case blink::WebCryptoKeyTypePublic:
- return blink::WebCryptoKeyFormatSpki;
- case blink::WebCryptoKeyTypePrivate:
- return blink::WebCryptoKeyFormatPkcs8;
- }
-
- NOTREACHED();
- return blink::WebCryptoKeyFormatRaw;
-}
-
-// Converts a KeyAlgorithm into an equivalent Algorithm for import.
-blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm(
- const blink::WebCryptoKeyAlgorithm& algorithm) {
- switch (algorithm.paramsType()) {
- case blink::WebCryptoKeyAlgorithmParamsTypeAes:
- return CreateAlgorithm(algorithm.id());
- case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
- return CreateHmacImportAlgorithm(algorithm.hmacParams()->hash().id());
- case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
- return CreateRsaHashedImportAlgorithm(
- algorithm.id(), algorithm.rsaHashedParams()->hash().id());
- case blink::WebCryptoKeyAlgorithmParamsTypeNone:
- break;
- default:
- break;
- }
- return blink::WebCryptoAlgorithm::createNull();
-}
-
-// There is some duplicated information in the serialized format used by
-// structured clone (since the KeyAlgorithm is serialized separately from the
-// key data). Use this extra information to further validate what was
-// deserialized from the key data.
-//
-// A failure here implies either a bug in the code, or that the serialized data
-// was corrupted.
-bool ValidateDeserializedKey(const blink::WebCryptoKey& key,
- const blink::WebCryptoKeyAlgorithm& algorithm,
- blink::WebCryptoKeyType type) {
- if (algorithm.id() != key.algorithm().id())
- return false;
-
- if (key.type() != type)
- return false;
-
- switch (algorithm.paramsType()) {
- case blink::WebCryptoKeyAlgorithmParamsTypeAes:
- if (algorithm.aesParams()->lengthBits() !=
- key.algorithm().aesParams()->lengthBits())
- return false;
- break;
- case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
- if (algorithm.rsaHashedParams()->modulusLengthBits() !=
- key.algorithm().rsaHashedParams()->modulusLengthBits())
- return false;
- if (algorithm.rsaHashedParams()->publicExponent().size() !=
- key.algorithm().rsaHashedParams()->publicExponent().size())
- return false;
- if (memcmp(algorithm.rsaHashedParams()->publicExponent().data(),
- key.algorithm().rsaHashedParams()->publicExponent().data(),
- key.algorithm().rsaHashedParams()->publicExponent().size()) !=
- 0)
- return false;
- break;
- case blink::WebCryptoKeyAlgorithmParamsTypeNone:
- case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-Status EncryptDecryptAesKw(EncryptOrDecrypt mode,
- const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- platform::SymKey* sym_key;
- Status status = ToPlatformSymKey(key, &sym_key);
- if (status.IsError())
- return status;
-
- unsigned int min_length = mode == ENCRYPT ? 16 : 24;
-
- if (data.byte_length() < min_length)
- return Status::ErrorDataTooSmall();
- if (data.byte_length() % 8)
- return Status::ErrorInvalidAesKwDataLength();
-
- if (status.IsError())
- return status;
- return platform::EncryptDecryptAesKw(mode, sym_key, data, buffer);
-}
-
-Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- if (algorithm.id() != key.algorithm().id())
- return Status::ErrorUnexpected();
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdAesGcm:
- return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdRsaOaep:
- return DecryptRsaOaep(algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdAesKw:
- return EncryptDecryptAesKw(DECRYPT, algorithm, key, data, buffer);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- if (algorithm.id() != key.algorithm().id())
- return Status::ErrorUnexpected();
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdAesGcm:
- return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdAesKw:
- return EncryptDecryptAesKw(ENCRYPT, algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdRsaOaep:
- return EncryptRsaOaep(algorithm, key, data, buffer);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-Status UnwrapKeyDecryptAndImport(
- blink::WebCryptoKeyFormat format,
- const CryptoData& wrapped_key_data,
- const blink::WebCryptoKey& wrapping_key,
- const blink::WebCryptoAlgorithm& wrapping_algorithm,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- std::vector<uint8> buffer;
- Status status = DecryptDontCheckKeyUsage(
- wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
- if (status.IsError())
- return status;
- // NOTE that returning the details of ImportKey() failures may leak
- // information about the plaintext of the encrypted key (for instance the JWK
- // key_ops). As long as the ImportKey error messages don't describe actual
- // key bytes however this should be OK. For more discussion see
- // http://crubg.com/372040
- return ImportKey(
- format, CryptoData(buffer), algorithm, extractable, usage_mask, key);
-}
-
-Status WrapKeyExportAndEncrypt(
- blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key_to_wrap,
- const blink::WebCryptoKey& wrapping_key,
- const blink::WebCryptoAlgorithm& wrapping_algorithm,
- std::vector<uint8>* buffer) {
- std::vector<uint8> exported_data;
- Status status = ExportKey(format, key_to_wrap, &exported_data);
- if (status.IsError())
- return status;
- return EncryptDontCheckUsage(
- wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer);
-}
-
-// Returns the internal block size for SHA-*
-unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) {
- switch (hash_id) {
- case blink::WebCryptoAlgorithmIdSha1:
- case blink::WebCryptoAlgorithmIdSha256:
- return 64;
- case blink::WebCryptoAlgorithmIdSha384:
- case blink::WebCryptoAlgorithmIdSha512:
- return 128;
- default:
- NOTREACHED();
- return 0;
- }
-}
-
-// Returns the mask of all key usages that are possible for |algorithm| and
-// |key_type|. If the combination of |algorithm| and |key_type| doesn't make
-// sense, then returns 0 (no usages).
-blink::WebCryptoKeyUsageMask GetValidKeyUsagesForKeyType(
- blink::WebCryptoAlgorithmId algorithm,
- blink::WebCryptoKeyType key_type) {
- if (IsAlgorithmAsymmetric(algorithm) ==
- (key_type == blink::WebCryptoKeyTypeSecret))
- return 0;
-
- switch (algorithm) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- case blink::WebCryptoAlgorithmIdAesGcm:
- case blink::WebCryptoAlgorithmIdAesCtr:
- return blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
- blink::WebCryptoKeyUsageWrapKey |
- blink::WebCryptoKeyUsageUnwrapKey;
- case blink::WebCryptoAlgorithmIdAesKw:
- return blink::WebCryptoKeyUsageWrapKey |
- blink::WebCryptoKeyUsageUnwrapKey;
- case blink::WebCryptoAlgorithmIdHmac:
- return blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
- case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
- switch (key_type) {
- case blink::WebCryptoKeyTypePublic:
- return blink::WebCryptoKeyUsageVerify;
- case blink::WebCryptoKeyTypePrivate:
- return blink::WebCryptoKeyUsageSign;
- default:
- return 0;
- }
- case blink::WebCryptoAlgorithmIdRsaOaep:
- switch (key_type) {
- case blink::WebCryptoKeyTypePublic:
- return blink::WebCryptoKeyUsageEncrypt |
- blink::WebCryptoKeyUsageWrapKey;
- case blink::WebCryptoKeyTypePrivate:
- return blink::WebCryptoKeyUsageDecrypt |
- blink::WebCryptoKeyUsageUnwrapKey;
- default:
- return 0;
- }
- default:
- return 0;
- }
-}
-
-// Returns Status::Success() if |usages| is a valid set of key usages for
-// |algorithm| and |key_type|. Otherwise returns an error.
-// In the case of JWK format the check is incomplete for asymmetric algorithms.
-Status BestEffortCheckKeyUsagesForImport(blink::WebCryptoAlgorithmId algorithm,
- blink::WebCryptoKeyFormat format,
- blink::WebCryptoKeyUsageMask usages) {
- if (!IsAlgorithmAsymmetric(algorithm))
- return CheckKeyUsages(algorithm, blink::WebCryptoKeyTypeSecret, usages);
-
- // Try to infer the key type given the import format.
- blink::WebCryptoKeyType key_type;
- bool key_type_known = false;
-
- switch (format) {
- case blink::WebCryptoKeyFormatRaw:
- // TODO(eroman): The spec defines Diffie-Hellman raw import for public
- // keys, so this will need to be updated in the future when DH is
- // implemented.
- return Status::ErrorUnexpected();
- case blink::WebCryptoKeyFormatSpki:
- key_type = blink::WebCryptoKeyTypePublic;
- key_type_known = true;
- break;
- case blink::WebCryptoKeyFormatPkcs8:
- key_type = blink::WebCryptoKeyTypePrivate;
- key_type_known = true;
- break;
- case blink::WebCryptoKeyFormatJwk:
- key_type_known = false;
- break;
- default:
- return Status::ErrorUnexpected();
- }
-
- if (key_type_known)
- return CheckKeyUsages(algorithm, key_type, usages);
-
- // If the key type is not known, then the algorithm is asymmetric. Whether the
- // key data describes a public or private key isn't known yet. But it must at
- // least be ONE of those two.
- DCHECK(IsAlgorithmAsymmetric(algorithm));
-
- if (CheckKeyUsages(algorithm, blink::WebCryptoKeyTypePublic, usages)
- .IsError() &&
- CheckKeyUsages(algorithm, blink::WebCryptoKeyTypePrivate, usages)
- .IsError()) {
- return Status::ErrorCreateKeyBadUsages();
- }
-
- return Status::Success();
-}
-
-// Returns an error if |combined_usage_mask| is invalid for generating a key
-// pair for |algorithm|. Otherwise returns Status::Success(), and fills
-// |public_key_usages| with the usages for the public key, and
-// |private_key_usages| with those for the private key.
-Status CheckKeyUsagesForGenerateKeyPair(
- blink::WebCryptoAlgorithmId algorithm,
- blink::WebCryptoKeyUsageMask combined_usage_mask,
- blink::WebCryptoKeyUsageMask* public_key_usages,
- blink::WebCryptoKeyUsageMask* private_key_usages) {
- DCHECK(IsAlgorithmAsymmetric(algorithm));
-
- blink::WebCryptoKeyUsageMask all_public_key_usages =
- GetValidKeyUsagesForKeyType(algorithm, blink::WebCryptoKeyTypePublic);
- blink::WebCryptoKeyUsageMask all_private_key_usages =
- GetValidKeyUsagesForKeyType(algorithm, blink::WebCryptoKeyTypePrivate);
-
- if (!ContainsKeyUsages(all_public_key_usages | all_private_key_usages,
- combined_usage_mask))
- return Status::ErrorCreateKeyBadUsages();
-
- *public_key_usages = combined_usage_mask & all_public_key_usages;
- *private_key_usages = combined_usage_mask & all_private_key_usages;
-
- return Status::Success();
-}
-
-// Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros,
-// to unsigned long.
-bool BigIntegerToLong(const uint8* data,
- unsigned int data_size,
- unsigned long* result) {
- // TODO(padolph): Is it correct to say that empty data is an error, or does it
- // mean value 0? See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23655
- if (data_size == 0)
- return false;
-
- *result = 0;
- for (size_t i = 0; i < data_size; ++i) {
- size_t reverse_i = data_size - i - 1;
-
- if (reverse_i >= sizeof(unsigned long) && data[i])
- return false; // Too large for a long.
-
- *result |= data[i] << 8 * reverse_i;
- }
- return true;
-}
-
-
-} // namespace
-
-void Init() { platform::Init(); }
-
-Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
- return Status::ErrorUnexpected();
- return EncryptDontCheckUsage(algorithm, key, data, buffer);
-}
-
-Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
- return Status::ErrorUnexpected();
- return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
-}
-
-Status Digest(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdSha1:
- case blink::WebCryptoAlgorithmIdSha256:
- case blink::WebCryptoAlgorithmIdSha384:
- case blink::WebCryptoAlgorithmIdSha512:
- return platform::DigestSha(algorithm.id(), data, buffer);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
- blink::WebCryptoAlgorithmId algorithm) {
- return platform::CreateDigestor(algorithm);
-}
-
-Status GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- Status status =
- CheckKeyUsages(algorithm.id(), blink::WebCryptoKeyTypeSecret, usage_mask);
- if (status.IsError())
- return status;
-
- unsigned int keylen_bytes = 0;
-
- // Get the secret key length in bytes from generation parameters.
- // This resolves any defaults.
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdAesCbc:
- case blink::WebCryptoAlgorithmIdAesGcm:
- case blink::WebCryptoAlgorithmIdAesKw: {
- if (!IsValidAesKeyLengthBits(algorithm.aesKeyGenParams()->lengthBits())) {
- return algorithm.aesKeyGenParams()->lengthBits() == 192
- ? Status::ErrorAes192BitUnsupported()
- : Status::ErrorGenerateKeyLength();
- }
- keylen_bytes = algorithm.aesKeyGenParams()->lengthBits() / 8;
- break;
- }
- case blink::WebCryptoAlgorithmIdHmac: {
- const blink::WebCryptoHmacKeyGenParams* params =
- algorithm.hmacKeyGenParams();
- DCHECK(params);
- if (params->hasLengthBits()) {
- if (params->optionalLengthBits() % 8)
- return Status::ErrorGenerateKeyLength();
- keylen_bytes = params->optionalLengthBits() / 8;
- } else {
- keylen_bytes = ShaBlockSizeBytes(params->hash().id());
- if (keylen_bytes == 0)
- return Status::ErrorUnsupported();
- }
- break;
- }
-
- default:
- return Status::ErrorUnsupported();
- }
-
- // TODO(eroman): Is this correct? HMAC can import zero-length keys, so should
- // probably be able to allowed to generate them too.
- if (keylen_bytes == 0)
- return Status::ErrorGenerateKeyLength();
-
- return platform::GenerateSecretKey(
- algorithm, extractable, usage_mask, keylen_bytes, key);
-}
-
-Status GenerateKeyPair(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask combined_usage_mask,
- blink::WebCryptoKey* public_key,
- blink::WebCryptoKey* private_key) {
- blink::WebCryptoKeyUsageMask public_key_usage_mask = 0;
- blink::WebCryptoKeyUsageMask private_key_usage_mask = 0;
-
- Status status = CheckKeyUsagesForGenerateKeyPair(algorithm.id(),
- combined_usage_mask,
- &public_key_usage_mask,
- &private_key_usage_mask);
- if (status.IsError())
- return status;
-
- // TODO(padolph): Handle other asymmetric algorithm key generation.
- switch (algorithm.paramsType()) {
- case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: {
- const blink::WebCryptoRsaHashedKeyGenParams* params =
- algorithm.rsaHashedKeyGenParams();
-
- if (!params->modulusLengthBits())
- return Status::ErrorGenerateRsaZeroModulus();
-
- unsigned long public_exponent = 0;
- if (!BigIntegerToLong(params->publicExponent().data(),
- params->publicExponent().size(),
- &public_exponent) ||
- (public_exponent != 3 && public_exponent != 65537)) {
- return Status::ErrorGenerateKeyPublicExponent();
- }
-
- return platform::GenerateRsaKeyPair(algorithm,
- extractable,
- public_key_usage_mask,
- private_key_usage_mask,
- params->modulusLengthBits(),
- public_exponent,
- public_key,
- private_key);
- }
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-// Note that this function may be called from the target Blink thread.
-Status ImportKey(blink::WebCryptoKeyFormat format,
- const CryptoData& key_data,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- // This is "best effort" because it is incomplete for JWK (for which the key
- // type is not yet known). ImportKeyJwk() does extra checks on key usage once
- // the key type has been determined.
- Status status =
- BestEffortCheckKeyUsagesForImport(algorithm.id(), format, usage_mask);
- if (status.IsError())
- return status;
-
- switch (format) {
- case blink::WebCryptoKeyFormatRaw:
- return ImportKeyRaw(key_data, algorithm, extractable, usage_mask, key);
- case blink::WebCryptoKeyFormatSpki:
- return platform::ImportKeySpki(
- algorithm, key_data, extractable, usage_mask, key);
- case blink::WebCryptoKeyFormatPkcs8:
- return platform::ImportKeyPkcs8(
- algorithm, key_data, extractable, usage_mask, key);
- case blink::WebCryptoKeyFormatJwk:
- return ImportKeyJwk(key_data, algorithm, extractable, usage_mask, key);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-// TODO(eroman): Move this to anonymous namespace.
-Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key,
- std::vector<uint8>* buffer) {
- switch (format) {
- case blink::WebCryptoKeyFormatRaw: {
- platform::SymKey* sym_key;
- Status status = ToPlatformSymKey(key, &sym_key);
- if (status.IsError())
- return status;
- return platform::ExportKeyRaw(sym_key, buffer);
- }
- case blink::WebCryptoKeyFormatSpki: {
- platform::PublicKey* public_key;
- Status status = ToPlatformPublicKey(key, &public_key);
- if (status.IsError())
- return status;
- return platform::ExportKeySpki(public_key, buffer);
- }
- case blink::WebCryptoKeyFormatPkcs8: {
- platform::PrivateKey* private_key;
- Status status = ToPlatformPrivateKey(key, &private_key);
- if (status.IsError())
- return status;
- return platform::ExportKeyPkcs8(private_key, key.algorithm(), buffer);
- }
- case blink::WebCryptoKeyFormatJwk:
- return ExportKeyJwk(key, buffer);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-Status ExportKey(blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key,
- std::vector<uint8>* buffer) {
- if (!key.extractable())
- return Status::ErrorKeyNotExtractable();
- return ExportKeyDontCheckExtractability(format, key, buffer);
-}
-
-Status Sign(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer) {
- if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign))
- return Status::ErrorUnexpected();
- if (algorithm.id() != key.algorithm().id())
- return Status::ErrorUnexpected();
-
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdHmac:
- return SignHmac(algorithm, key, data, buffer);
- case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
- return SignRsaSsaPkcs1v1_5(algorithm, key, data, buffer);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-Status VerifySignature(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match) {
- if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageVerify))
- return Status::ErrorUnexpected();
- if (algorithm.id() != key.algorithm().id())
- return Status::ErrorUnexpected();
-
- if (!signature.byte_length()) {
- // None of the algorithms generate valid zero-length signatures so this
- // will necessarily fail verification. Early return to protect
- // implementations from dealing with a NULL signature pointer.
- *signature_match = false;
- return Status::Success();
- }
-
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdHmac:
- return VerifyHmac(algorithm, key, signature, data, signature_match);
- case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
- return VerifyRsaSsaPkcs1v1_5(
- algorithm, key, signature, data, signature_match);
- default:
- return Status::ErrorUnsupported();
- }
-}
-
-Status WrapKey(blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key_to_wrap,
- const blink::WebCryptoKey& wrapping_key,
- const blink::WebCryptoAlgorithm& wrapping_algorithm,
- std::vector<uint8>* buffer) {
- if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey))
- return Status::ErrorUnexpected();
- if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
- return Status::ErrorUnexpected();
-
- return WrapKeyExportAndEncrypt(
- format, key_to_wrap, wrapping_key, wrapping_algorithm, buffer);
-}
-
-Status UnwrapKey(blink::WebCryptoKeyFormat format,
- const CryptoData& wrapped_key_data,
- const blink::WebCryptoKey& wrapping_key,
- const blink::WebCryptoAlgorithm& wrapping_algorithm,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
- return Status::ErrorUnexpected();
- if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
- return Status::ErrorUnexpected();
-
- // Fail-fast if the key usages don't make sense. This avoids decrypting the
- // key only to then have import fail. It is "best effort" because when
- // unwrapping JWK for asymmetric algorithms the key type isn't known yet.
- Status status =
- BestEffortCheckKeyUsagesForImport(algorithm.id(), format, usage_mask);
- if (status.IsError())
- return status;
-
- return UnwrapKeyDecryptAndImport(format,
- wrapped_key_data,
- wrapping_key,
- wrapping_algorithm,
- algorithm,
- extractable,
- usage_mask,
- key);
-}
-
-// Note that this function is called from the target Blink thread.
-bool SerializeKeyForClone(const blink::WebCryptoKey& key,
- blink::WebVector<uint8>* key_data) {
- return static_cast<webcrypto::platform::Key*>(key.handle())
- ->ThreadSafeSerializeForClone(key_data);
-}
-
-// Note that this function is called from the target Blink thread.
-bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
- blink::WebCryptoKeyType type,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& key_data,
- blink::WebCryptoKey* key) {
- // TODO(eroman): This should not call into the platform crypto layer.
- // Otherwise it runs the risk of stalling while the NSS/OpenSSL global locks
- // are held.
- //
- // An alternate approach is to defer the key import until the key is used.
- // However this means that any deserialization errors would have to be
- // surfaced as WebCrypto errors, leading to slightly different behaviors. For
- // instance you could clone a key which fails to be deserialized.
- Status status = ImportKey(GetCloneFormatForKeyType(type),
- key_data,
- KeyAlgorithmToImportAlgorithm(algorithm),
- extractable,
- usage_mask,
- key);
- if (status.IsError())
- return false;
- return ValidateDeserializedKey(*key, algorithm, type);
-}
-
-Status ToPlatformSymKey(const blink::WebCryptoKey& key,
- platform::SymKey** out) {
- *out = static_cast<platform::Key*>(key.handle())->AsSymKey();
- if (!*out)
- return Status::ErrorUnexpectedKeyType();
- return Status::Success();
-}
-
-Status ToPlatformPublicKey(const blink::WebCryptoKey& key,
- platform::PublicKey** out) {
- *out = static_cast<platform::Key*>(key.handle())->AsPublicKey();
- if (!*out)
- return Status::ErrorUnexpectedKeyType();
- return Status::Success();
-}
-
-Status ToPlatformPrivateKey(const blink::WebCryptoKey& key,
- platform::PrivateKey** out) {
- *out = static_cast<platform::Key*>(key.handle())->AsPrivateKey();
- if (!*out)
- return Status::ErrorUnexpectedKeyType();
- return Status::Success();
-}
-
-// Returns Status::Success() if |usages| is a valid set of key usages for
-// |algorithm| and |key_type|. Otherwise returns an error.
-Status CheckKeyUsages(blink::WebCryptoAlgorithmId algorithm,
- blink::WebCryptoKeyType key_type,
- blink::WebCryptoKeyUsageMask usages) {
- if (!ContainsKeyUsages(GetValidKeyUsagesForKeyType(algorithm, key_type),
- usages))
- return Status::ErrorCreateKeyBadUsages();
-
- return Status::Success();
-}
-
-} // namespace webcrypto
-
-} // namespace content
diff --git a/chromium/content/child/webcrypto/shared_crypto.h b/chromium/content/child/webcrypto/shared_crypto.h
deleted file mode 100644
index d9e5a959db7..00000000000
--- a/chromium/content/child/webcrypto/shared_crypto.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_SHARED_CRYPTO_H_
-#define CONTENT_CHILD_WEBCRYPTO_SHARED_CRYPTO_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebCrypto.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-
-namespace content {
-
-namespace webcrypto {
-
-class CryptoData;
-class Status;
-
-// Do one-time initialization. It is safe to call this multiple times.
-// May be called concurrently from multiple threads.
-CONTENT_EXPORT void Init();
-
-// The functions exported by shared_crypto.h provide a common entry point for
-// synchronous crypto operations.
-//
-// Here is how the layer cake looks.
-//
-// Blink
-// |
-// ==============|==========================
-// |
-// content
-// |
-// |
-// v
-// WebCryptoImpl (Implements the blink::WebCrypto interface for
-// | asynchronous completions; posts tasks to
-// | the webcrypto worker pool to fulfill the request
-// using the synchronous methods of shared_crypto.h)
-// |
-// | [shared_crypto_unittest.cc]
-// | /
-// | / (The blink::WebCrypto interface is not
-// | / testable from the chromium side because
-// | / the result object is not mockable.
-// | / Tests are done on shared_crypto instead.
-// V v
-// [shared_crypto.h] (Exposes synchronous functions in the
-// | webcrypto:: namespace. This does
-// | common validations, infers default
-// | parameters, and casts the algorithm
-// | parameters to the right types)
-// |
-// V
-// [platform_crypto.h] (Exposes functions in the webcrypto::platform
-// | namespace)
-// |
-// |
-// V
-// [platform_crypto_{nss|openssl}.cc] (Implements using the platform crypto
-// library)
-//
-// The shared_crypto.h functions are responsible for:
-//
-// * Validating the key usages
-// * Inferring default parameters when not specified
-// * Validating key exportability
-// * Validating algorithm with key.algorithm
-// * Converting the Blink key to a more specific platform::{PublicKey,
-// PrivateKey, SymKey} and making sure it was the right type.
-// * Validating alogorithm specific parameters (for instance, was the iv for
-// AES-CBC 16 bytes).
-// * Parse a JWK
-
-CONTENT_EXPORT Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-CONTENT_EXPORT Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-CONTENT_EXPORT Status Digest(const blink::WebCryptoAlgorithm& algorithm,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-CONTENT_EXPORT scoped_ptr<blink::WebCryptoDigestor> CreateDigestor(
- blink::WebCryptoAlgorithmId algorithm);
-
-CONTENT_EXPORT Status
- GenerateSecretKey(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
-
-CONTENT_EXPORT Status
- GenerateKeyPair(const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* public_key,
- blink::WebCryptoKey* private_key);
-
-CONTENT_EXPORT Status ImportKey(blink::WebCryptoKeyFormat format,
- const CryptoData& key_data,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
-
-CONTENT_EXPORT Status ExportKey(blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key,
- std::vector<uint8>* buffer);
-
-CONTENT_EXPORT Status Sign(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& data,
- std::vector<uint8>* buffer);
-
-CONTENT_EXPORT Status
- VerifySignature(const blink::WebCryptoAlgorithm& algorithm,
- const blink::WebCryptoKey& key,
- const CryptoData& signature,
- const CryptoData& data,
- bool* signature_match);
-
-CONTENT_EXPORT Status
- WrapKey(blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key_to_wrap,
- const blink::WebCryptoKey& wrapping_key,
- const blink::WebCryptoAlgorithm& wrapping_algorithm,
- std::vector<uint8>* buffer);
-
-CONTENT_EXPORT Status
- UnwrapKey(blink::WebCryptoKeyFormat format,
- const CryptoData& wrapped_key_data,
- const blink::WebCryptoKey& wrapping_key,
- const blink::WebCryptoAlgorithm& wrapping_algorithm,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key);
-
-// Called on the target Blink thread.
-CONTENT_EXPORT bool SerializeKeyForClone(const blink::WebCryptoKey& key,
- blink::WebVector<uint8>* key_data);
-
-// Called on the target Blink thread.
-CONTENT_EXPORT bool DeserializeKeyForClone(
- const blink::WebCryptoKeyAlgorithm& algorithm,
- blink::WebCryptoKeyType type,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& key_data,
- blink::WebCryptoKey* key);
-
-namespace platform {
-class SymKey;
-class PublicKey;
-class PrivateKey;
-}
-
-Status ToPlatformSymKey(const blink::WebCryptoKey& key, platform::SymKey** out);
-
-Status ToPlatformPublicKey(const blink::WebCryptoKey& key,
- platform::PublicKey** out);
-
-Status ToPlatformPrivateKey(const blink::WebCryptoKey& key,
- platform::PrivateKey** out);
-
-// Returns Staus::Success() if |usages| is valid for |key_type| and |algorithm|.
-// Otherwise returns a failure
-Status CheckKeyUsages(blink::WebCryptoAlgorithmId algorithm,
- blink::WebCryptoKeyType key_type,
- blink::WebCryptoKeyUsageMask usages);
-
-} // namespace webcrypto
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEBCRYPTO_SHARED_CRYPTO_H_
diff --git a/chromium/content/child/webcrypto/shared_crypto_unittest.cc b/chromium/content/child/webcrypto/shared_crypto_unittest.cc
deleted file mode 100644
index f4afaf70f61..00000000000
--- a/chromium/content/child/webcrypto/shared_crypto_unittest.cc
+++ /dev/null
@@ -1,4399 +0,0 @@
-// Copyright 2014 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 "content/child/webcrypto/shared_crypto.h"
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/file_util.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "content/child/webcrypto/crypto_data.h"
-#include "content/child/webcrypto/status.h"
-#include "content/child/webcrypto/webcrypto_util.h"
-#include "content/public/common/content_paths.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
-#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
-#include "third_party/WebKit/public/platform/WebCryptoKey.h"
-#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
-#include "third_party/re2/re2/re2.h"
-
-#if !defined(USE_OPENSSL)
-#include <nss.h>
-#include <pk11pub.h>
-
-#include "crypto/scoped_nss_types.h"
-#endif
-
-// The OpenSSL implementation of WebCrypto is less complete, so don't run all of
-// the tests: http://crbug.com/267888
-#if defined(USE_OPENSSL)
-#define MAYBE(test_name) DISABLED_##test_name
-#else
-#define MAYBE(test_name) test_name
-#endif
-
-#define EXPECT_BYTES_EQ(expected, actual) \
- EXPECT_EQ(CryptoData(expected), CryptoData(actual))
-
-#define EXPECT_BYTES_EQ_HEX(expected_hex, actual_bytes) \
- EXPECT_BYTES_EQ(HexStringToBytes(expected_hex), actual_bytes)
-
-namespace content {
-
-namespace webcrypto {
-
-// These functions are used by GTEST to support EXPECT_EQ() for
-// webcrypto::Status and webcrypto::CryptoData
-
-void PrintTo(const Status& status, ::std::ostream* os) {
- if (status.IsSuccess())
- *os << "Success";
- else
- *os << "Error type: " << status.error_type()
- << " Error details: " << status.error_details();
-}
-
-bool operator==(const content::webcrypto::Status& a,
- const content::webcrypto::Status& b) {
- if (a.IsSuccess() != b.IsSuccess())
- return false;
- if (a.IsSuccess())
- return true;
- return a.error_type() == b.error_type() &&
- a.error_details() == b.error_details();
-}
-
-bool operator!=(const content::webcrypto::Status& a,
- const content::webcrypto::Status& b) {
- return !(a == b);
-}
-
-void PrintTo(const CryptoData& data, ::std::ostream* os) {
- *os << "[" << base::HexEncode(data.bytes(), data.byte_length()) << "]";
-}
-
-bool operator==(const content::webcrypto::CryptoData& a,
- const content::webcrypto::CryptoData& b) {
- return a.byte_length() == b.byte_length() &&
- memcmp(a.bytes(), b.bytes(), a.byte_length()) == 0;
-}
-
-bool operator!=(const content::webcrypto::CryptoData& a,
- const content::webcrypto::CryptoData& b) {
- return !(a == b);
-}
-
-namespace {
-
-// -----------------------------------------------------------------------------
-
-// TODO(eroman): For Linux builds using system NSS, AES-GCM support is a
-// runtime dependency. Test it by trying to import a key.
-// TODO(padolph): Consider caching the result of the import key test.
-bool SupportsAesGcm() {
- std::vector<uint8> key_raw(16, 0);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- Status status = ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(key_raw),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &key);
-
- if (status.IsError())
- EXPECT_EQ(blink::WebCryptoErrorTypeNotSupported, status.error_type());
- return status.IsSuccess();
-}
-
-bool SupportsRsaOaep() {
-#if defined(USE_OPENSSL)
- return false;
-#else
- // TODO(eroman): Exclude version test for OS_CHROMEOS
-#if defined(USE_NSS)
- if (!NSS_VersionCheck("3.16.2"))
- return false;
-#endif
- crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
- return !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP);
-#endif
-}
-
-bool SupportsRsaKeyImport() {
-// TODO(eroman): Exclude version test for OS_CHROMEOS
-#if defined(USE_NSS)
- if (!NSS_VersionCheck("3.16.2")) {
- LOG(WARNING) << "RSA key import is not supported by this version of NSS. "
- "Skipping some tests";
- return false;
- }
-#endif
- return true;
-}
-
-blink::WebCryptoAlgorithm CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmId algorithm_id,
- const blink::WebCryptoAlgorithmId hash_id,
- unsigned int modulus_length,
- const std::vector<uint8>& public_exponent) {
- DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
- algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
- DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- algorithm_id,
- new blink::WebCryptoRsaHashedKeyGenParams(
- CreateAlgorithm(hash_id),
- modulus_length,
- webcrypto::Uint8VectorStart(public_exponent),
- public_exponent.size()));
-}
-
-// Creates an RSA-OAEP algorithm
-blink::WebCryptoAlgorithm CreateRsaOaepAlgorithm(
- const std::vector<uint8>& label) {
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- blink::WebCryptoAlgorithmIdRsaOaep,
- new blink::WebCryptoRsaOaepParams(
- !label.empty(), Uint8VectorStart(label), label.size()));
-}
-
-// Creates an AES-CBC algorithm.
-blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(const std::vector<uint8>& iv) {
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- blink::WebCryptoAlgorithmIdAesCbc,
- new blink::WebCryptoAesCbcParams(Uint8VectorStart(iv), iv.size()));
-}
-
-// Creates an AES-GCM algorithm.
-blink::WebCryptoAlgorithm CreateAesGcmAlgorithm(
- const std::vector<uint8>& iv,
- const std::vector<uint8>& additional_data,
- unsigned int tag_length_bits) {
- EXPECT_TRUE(SupportsAesGcm());
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- blink::WebCryptoAlgorithmIdAesGcm,
- new blink::WebCryptoAesGcmParams(Uint8VectorStart(iv),
- iv.size(),
- true,
- Uint8VectorStart(additional_data),
- additional_data.size(),
- true,
- tag_length_bits));
-}
-
-// Creates an HMAC algorithm whose parameters struct is compatible with key
-// generation. It is an error to call this with a hash_id that is not a SHA*.
-// The key_length_bits parameter is optional, with zero meaning unspecified.
-blink::WebCryptoAlgorithm CreateHmacKeyGenAlgorithm(
- blink::WebCryptoAlgorithmId hash_id,
- unsigned int key_length_bits) {
- DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
- // key_length_bytes == 0 means unspecified
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- blink::WebCryptoAlgorithmIdHmac,
- new blink::WebCryptoHmacKeyGenParams(
- CreateAlgorithm(hash_id), (key_length_bits != 0), key_length_bits));
-}
-
-// Returns a slightly modified version of the input vector.
-//
-// - For non-empty inputs a single bit is inverted.
-// - For empty inputs, a byte is added.
-std::vector<uint8> Corrupted(const std::vector<uint8>& input) {
- std::vector<uint8> corrupted_data(input);
- if (corrupted_data.empty())
- corrupted_data.push_back(0);
- corrupted_data[corrupted_data.size() / 2] ^= 0x01;
- return corrupted_data;
-}
-
-std::vector<uint8> HexStringToBytes(const std::string& hex) {
- std::vector<uint8> bytes;
- base::HexStringToBytes(hex, &bytes);
- return bytes;
-}
-
-std::vector<uint8> MakeJsonVector(const std::string& json_string) {
- return std::vector<uint8>(json_string.begin(), json_string.end());
-}
-
-std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) {
- std::string json;
- base::JSONWriter::Write(&dict, &json);
- return MakeJsonVector(json);
-}
-
-// ----------------------------------------------------------------
-// Helpers for working with JSON data files for test expectations.
-// ----------------------------------------------------------------
-
-// Reads a file in "src/content/test/data/webcrypto" to a base::Value.
-// The file must be JSON, however it can also include C++ style comments.
-::testing::AssertionResult ReadJsonTestFile(const char* test_file_name,
- scoped_ptr<base::Value>* value) {
- base::FilePath test_data_dir;
- if (!PathService::Get(DIR_TEST_DATA, &test_data_dir))
- return ::testing::AssertionFailure() << "Couldn't retrieve test dir";
-
- base::FilePath file_path =
- test_data_dir.AppendASCII("webcrypto").AppendASCII(test_file_name);
-
- std::string file_contents;
- if (!base::ReadFileToString(file_path, &file_contents)) {
- return ::testing::AssertionFailure()
- << "Couldn't read test file: " << file_path.value();
- }
-
- // Strip C++ style comments out of the "json" file, otherwise it cannot be
- // parsed.
- re2::RE2::GlobalReplace(&file_contents, re2::RE2("\\s*//.*"), "");
-
- // Parse the JSON to a dictionary.
- value->reset(base::JSONReader::Read(file_contents));
- if (!value->get()) {
- return ::testing::AssertionFailure()
- << "Couldn't parse test file JSON: " << file_path.value();
- }
-
- return ::testing::AssertionSuccess();
-}
-
-// Same as ReadJsonTestFile(), but return the value as a List.
-::testing::AssertionResult ReadJsonTestFileToList(
- const char* test_file_name,
- scoped_ptr<base::ListValue>* list) {
- // Read the JSON.
- scoped_ptr<base::Value> json;
- ::testing::AssertionResult result = ReadJsonTestFile(test_file_name, &json);
- if (!result)
- return result;
-
- // Cast to an ListValue.
- base::ListValue* list_value = NULL;
- if (!json->GetAsList(&list_value) || !list_value)
- return ::testing::AssertionFailure() << "The JSON was not a list";
-
- list->reset(list_value);
- ignore_result(json.release());
-
- return ::testing::AssertionSuccess();
-}
-
-// Read a string property from the dictionary with path |property_name|
-// (which can include periods for nested dictionaries). Interprets the
-// string as a hex encoded string and converts it to a bytes list.
-//
-// Returns empty vector on failure.
-std::vector<uint8> GetBytesFromHexString(base::DictionaryValue* dict,
- const char* property_name) {
- std::string hex_string;
- if (!dict->GetString(property_name, &hex_string)) {
- EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
- return std::vector<uint8>();
- }
-
- return HexStringToBytes(hex_string);
-}
-
-// Reads a string property with path "property_name" and converts it to a
-// WebCryptoAlgorith. Returns null algorithm on failure.
-blink::WebCryptoAlgorithm GetDigestAlgorithm(base::DictionaryValue* dict,
- const char* property_name) {
- std::string algorithm_name;
- if (!dict->GetString(property_name, &algorithm_name)) {
- EXPECT_TRUE(false) << "Couldn't get string property: " << property_name;
- return blink::WebCryptoAlgorithm::createNull();
- }
-
- struct {
- const char* name;
- blink::WebCryptoAlgorithmId id;
- } kDigestNameToId[] = {
- {"sha-1", blink::WebCryptoAlgorithmIdSha1},
- {"sha-256", blink::WebCryptoAlgorithmIdSha256},
- {"sha-384", blink::WebCryptoAlgorithmIdSha384},
- {"sha-512", blink::WebCryptoAlgorithmIdSha512},
- };
-
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDigestNameToId); ++i) {
- if (kDigestNameToId[i].name == algorithm_name)
- return CreateAlgorithm(kDigestNameToId[i].id);
- }
-
- return blink::WebCryptoAlgorithm::createNull();
-}
-
-// Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
-// dictionary to a good state
-void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
- dict->Clear();
- dict->SetString("kty", "oct");
- dict->SetString("alg", "A128CBC");
- dict->SetString("use", "enc");
- dict->SetBoolean("ext", false);
- dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
-}
-
-// Helper for ImportJwkRsaFailures. Restores the JWK JSON
-// dictionary to a good state
-void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
- dict->Clear();
- dict->SetString("kty", "RSA");
- dict->SetString("alg", "RS256");
- dict->SetString("use", "sig");
- dict->SetBoolean("ext", false);
- dict->SetString(
- "n",
- "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
- "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
- "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
- dict->SetString("e", "AQAB");
-}
-
-// Returns true if any of the vectors in the input list have identical content.
-// Dumb O(n^2) implementation but should be fast enough for the input sizes that
-// are used.
-bool CopiesExist(const std::vector<std::vector<uint8> >& bufs) {
- for (size_t i = 0; i < bufs.size(); ++i) {
- for (size_t j = i + 1; j < bufs.size(); ++j) {
- if (CryptoData(bufs[i]) == CryptoData(bufs[j]))
- return true;
- }
- }
- return false;
-}
-
-blink::WebCryptoAlgorithm CreateAesKeyGenAlgorithm(
- blink::WebCryptoAlgorithmId aes_alg_id,
- unsigned short length) {
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- aes_alg_id, new blink::WebCryptoAesKeyGenParams(length));
-}
-
-blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
- unsigned short key_length_bits) {
- return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
- key_length_bits);
-}
-
-blink::WebCryptoAlgorithm CreateAesGcmKeyGenAlgorithm(
- unsigned short key_length_bits) {
- EXPECT_TRUE(SupportsAesGcm());
- return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesGcm,
- key_length_bits);
-}
-
-blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(
- unsigned short key_length_bits) {
- return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw,
- key_length_bits);
-}
-
-// The following key pair is comprised of the SPKI (public key) and PKCS#8
-// (private key) representations of the key pair provided in Example 1 of the
-// NIST test vectors at
-// ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt
-const unsigned int kModulusLengthBits = 1024;
-const char* const kPublicKeySpkiDerHex =
- "30819f300d06092a864886f70d010101050003818d0030818902818100a5"
- "6e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad9"
- "91d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfc"
- "e0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e"
- "6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cf"
- "fb2249bd9a21370203010001";
-const char* const kPrivateKeyPkcs8DerHex =
- "30820275020100300d06092a864886f70d01010105000482025f3082025b"
- "02010002818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52"
- "a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab"
- "7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921c"
- "b23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef"
- "22e1e1f20d0ce8cffb2249bd9a2137020301000102818033a5042a90b27d"
- "4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c"
- "568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee"
- "896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31"
- "b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b3"
- "25024100e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e8629"
- "6b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b"
- "3b6dcd3eda8e6443024100b69dca1cf7d4d7ec81e75b90fcca874abcde12"
- "3fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc72"
- "3e6963364a1f9425452b269a6799fd024028fa13938655be1f8a159cbaca"
- "5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8d"
- "d3ede2448328f385d81b30e8e43b2fffa02786197902401a8b38f398fa71"
- "2049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd"
- "48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729024027"
- "156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319"
- "584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24"
- "a79f4d";
-// The modulus and exponent (in hex) of kPublicKeySpkiDerHex
-const char* const kPublicKeyModulusHex =
- "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
- "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
- "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
- "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
-const char* const kPublicKeyExponentHex = "010001";
-
-class SharedCryptoTest : public testing::Test {
- protected:
- virtual void SetUp() OVERRIDE { Init(); }
-};
-
-blink::WebCryptoKey ImportSecretKeyFromRaw(
- const std::vector<uint8>& key_raw,
- const blink::WebCryptoAlgorithm& algorithm,
- blink::WebCryptoKeyUsageMask usage) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- bool extractable = true;
- EXPECT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(key_raw),
- algorithm,
- extractable,
- usage,
- &key));
-
- EXPECT_FALSE(key.isNull());
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(algorithm.id(), key.algorithm().id());
- EXPECT_EQ(extractable, key.extractable());
- EXPECT_EQ(usage, key.usages());
- return key;
-}
-
-void ImportRsaKeyPair(const std::vector<uint8>& spki_der,
- const std::vector<uint8>& pkcs8_der,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask public_key_usage_mask,
- blink::WebCryptoKeyUsageMask private_key_usage_mask,
- blink::WebCryptoKey* public_key,
- blink::WebCryptoKey* private_key) {
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(spki_der),
- algorithm,
- true,
- public_key_usage_mask,
- public_key));
- EXPECT_FALSE(public_key->isNull());
- EXPECT_TRUE(public_key->handle());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key->type());
- EXPECT_EQ(algorithm.id(), public_key->algorithm().id());
- EXPECT_TRUE(public_key->extractable());
- EXPECT_EQ(public_key_usage_mask, public_key->usages());
-
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(pkcs8_der),
- algorithm,
- extractable,
- private_key_usage_mask,
- private_key));
- EXPECT_FALSE(private_key->isNull());
- EXPECT_TRUE(private_key->handle());
- EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key->type());
- EXPECT_EQ(algorithm.id(), private_key->algorithm().id());
- EXPECT_EQ(extractable, private_key->extractable());
- EXPECT_EQ(private_key_usage_mask, private_key->usages());
-}
-
-Status AesGcmEncrypt(const blink::WebCryptoKey& key,
- const std::vector<uint8>& iv,
- const std::vector<uint8>& additional_data,
- unsigned int tag_length_bits,
- const std::vector<uint8>& plain_text,
- std::vector<uint8>* cipher_text,
- std::vector<uint8>* authentication_tag) {
- EXPECT_TRUE(SupportsAesGcm());
- blink::WebCryptoAlgorithm algorithm =
- CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
-
- std::vector<uint8> output;
- Status status = Encrypt(algorithm, key, CryptoData(plain_text), &output);
- if (status.IsError())
- return status;
-
- if ((tag_length_bits % 8) != 0) {
- EXPECT_TRUE(false) << "Encrypt should have failed.";
- return Status::OperationError();
- }
-
- size_t tag_length_bytes = tag_length_bits / 8;
-
- if (tag_length_bytes > output.size()) {
- EXPECT_TRUE(false) << "tag length is larger than output";
- return Status::OperationError();
- }
-
- // The encryption result is cipher text with authentication tag appended.
- cipher_text->assign(output.begin(),
- output.begin() + (output.size() - tag_length_bytes));
- authentication_tag->assign(output.begin() + cipher_text->size(),
- output.end());
-
- return Status::Success();
-}
-
-Status AesGcmDecrypt(const blink::WebCryptoKey& key,
- const std::vector<uint8>& iv,
- const std::vector<uint8>& additional_data,
- unsigned int tag_length_bits,
- const std::vector<uint8>& cipher_text,
- const std::vector<uint8>& authentication_tag,
- std::vector<uint8>* plain_text) {
- EXPECT_TRUE(SupportsAesGcm());
- blink::WebCryptoAlgorithm algorithm =
- CreateAesGcmAlgorithm(iv, additional_data, tag_length_bits);
-
- // Join cipher text and authentication tag.
- std::vector<uint8> cipher_text_with_tag;
- cipher_text_with_tag.reserve(cipher_text.size() + authentication_tag.size());
- cipher_text_with_tag.insert(
- cipher_text_with_tag.end(), cipher_text.begin(), cipher_text.end());
- cipher_text_with_tag.insert(cipher_text_with_tag.end(),
- authentication_tag.begin(),
- authentication_tag.end());
-
- return Decrypt(algorithm, key, CryptoData(cipher_text_with_tag), plain_text);
-}
-
-Status ImportKeyJwk(const CryptoData& key_data,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- return ImportKey(blink::WebCryptoKeyFormatJwk,
- key_data,
- algorithm,
- extractable,
- usage_mask,
- key);
-}
-
-Status ImportKeyJwkFromDict(const base::DictionaryValue& dict,
- const blink::WebCryptoAlgorithm& algorithm,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- blink::WebCryptoKey* key) {
- return ImportKeyJwk(CryptoData(MakeJsonVector(dict)),
- algorithm,
- extractable,
- usage_mask,
- key);
-}
-
-// Parses a vector of JSON into a dictionary.
-scoped_ptr<base::DictionaryValue> GetJwkDictionary(
- const std::vector<uint8>& json) {
- base::StringPiece json_string(
- reinterpret_cast<const char*>(Uint8VectorStart(json)), json.size());
- base::Value* value = base::JSONReader::Read(json_string);
- EXPECT_TRUE(value);
- base::DictionaryValue* dict_value = NULL;
- value->GetAsDictionary(&dict_value);
- return scoped_ptr<base::DictionaryValue>(dict_value);
-}
-
-// Verifies the input dictionary contains the expected values. Exact matches are
-// required on the fields examined.
-::testing::AssertionResult VerifyJwk(
- const scoped_ptr<base::DictionaryValue>& dict,
- const std::string& kty_expected,
- const std::string& alg_expected,
- blink::WebCryptoKeyUsageMask use_mask_expected) {
- // ---- kty
- std::string value_string;
- if (!dict->GetString("kty", &value_string))
- return ::testing::AssertionFailure() << "Missing 'kty'";
- if (value_string != kty_expected)
- return ::testing::AssertionFailure() << "Expected 'kty' to be "
- << kty_expected << "but found "
- << value_string;
-
- // ---- alg
- if (!dict->GetString("alg", &value_string))
- return ::testing::AssertionFailure() << "Missing 'alg'";
- if (value_string != alg_expected)
- return ::testing::AssertionFailure() << "Expected 'alg' to be "
- << alg_expected << " but found "
- << value_string;
-
- // ---- ext
- // always expect ext == true in this case
- bool ext_value;
- if (!dict->GetBoolean("ext", &ext_value))
- return ::testing::AssertionFailure() << "Missing 'ext'";
- if (!ext_value)
- return ::testing::AssertionFailure()
- << "Expected 'ext' to be true but found false";
-
- // ---- key_ops
- base::ListValue* key_ops;
- if (!dict->GetList("key_ops", &key_ops))
- return ::testing::AssertionFailure() << "Missing 'key_ops'";
- blink::WebCryptoKeyUsageMask key_ops_mask = 0;
- Status status = GetWebCryptoUsagesFromJwkKeyOps(key_ops, &key_ops_mask);
- if (status.IsError())
- return ::testing::AssertionFailure() << "Failure extracting 'key_ops'";
- if (key_ops_mask != use_mask_expected)
- return ::testing::AssertionFailure()
- << "Expected 'key_ops' mask to be " << use_mask_expected
- << " but found " << key_ops_mask << " (" << value_string << ")";
-
- return ::testing::AssertionSuccess();
-}
-
-// Verifies that the JSON in the input vector contains the provided
-// expected values. Exact matches are required on the fields examined.
-::testing::AssertionResult VerifySecretJwk(
- const std::vector<uint8>& json,
- const std::string& alg_expected,
- const std::string& k_expected_hex,
- blink::WebCryptoKeyUsageMask use_mask_expected) {
- scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
- if (!dict.get() || dict->empty())
- return ::testing::AssertionFailure() << "JSON parsing failed";
-
- // ---- k
- std::string value_string;
- if (!dict->GetString("k", &value_string))
- return ::testing::AssertionFailure() << "Missing 'k'";
- std::string k_value;
- if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
- return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
- if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
- k_expected_hex.c_str())) {
- return ::testing::AssertionFailure() << "Expected 'k' to be "
- << k_expected_hex
- << " but found something different";
- }
-
- return VerifyJwk(dict, "oct", alg_expected, use_mask_expected);
-}
-
-// Verifies that the JSON in the input vector contains the provided
-// expected values. Exact matches are required on the fields examined.
-::testing::AssertionResult VerifyPublicJwk(
- const std::vector<uint8>& json,
- const std::string& alg_expected,
- const std::string& n_expected_hex,
- const std::string& e_expected_hex,
- blink::WebCryptoKeyUsageMask use_mask_expected) {
- scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
- if (!dict.get() || dict->empty())
- return ::testing::AssertionFailure() << "JSON parsing failed";
-
- // ---- n
- std::string value_string;
- if (!dict->GetString("n", &value_string))
- return ::testing::AssertionFailure() << "Missing 'n'";
- std::string n_value;
- if (!webcrypto::Base64DecodeUrlSafe(value_string, &n_value))
- return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(n) failed";
- if (base::HexEncode(n_value.data(), n_value.size()) != n_expected_hex) {
- return ::testing::AssertionFailure() << "'n' does not match the expected "
- "value";
- }
- // TODO(padolph): LowerCaseEqualsASCII() does not work for above!
-
- // ---- e
- if (!dict->GetString("e", &value_string))
- return ::testing::AssertionFailure() << "Missing 'e'";
- std::string e_value;
- if (!webcrypto::Base64DecodeUrlSafe(value_string, &e_value))
- return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(e) failed";
- if (!LowerCaseEqualsASCII(base::HexEncode(e_value.data(), e_value.size()),
- e_expected_hex.c_str())) {
- return ::testing::AssertionFailure() << "Expected 'e' to be "
- << e_expected_hex
- << " but found something different";
- }
-
- return VerifyJwk(dict, "RSA", alg_expected, use_mask_expected);
-}
-
-} // namespace
-
-TEST_F(SharedCryptoTest, CheckAesGcm) {
- if (!SupportsAesGcm()) {
- LOG(WARNING) << "AES GCM not supported on this platform, so some tests "
- "will be skipped. Consider upgrading local NSS libraries";
- return;
- }
-}
-
-// Tests several Status objects against their expected hard coded values, as
-// well as ensuring that comparison of Status objects works.
-// Comparison should take into account both the error details, as well as the
-// error type.
-TEST_F(SharedCryptoTest, Status) {
- // Even though the error message is the same, these should not be considered
- // the same by the tests because the error type is different.
- EXPECT_NE(Status::DataError(), Status::OperationError());
- EXPECT_NE(Status::Success(), Status::OperationError());
-
- EXPECT_EQ(Status::Success(), Status::Success());
- EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
- Status::ErrorJwkPropertyWrongType("kty", "string"));
-
- Status status = Status::Success();
-
- EXPECT_FALSE(status.IsError());
- EXPECT_EQ("", status.error_details());
-
- status = Status::OperationError();
- EXPECT_TRUE(status.IsError());
- EXPECT_EQ("", status.error_details());
- EXPECT_EQ(blink::WebCryptoErrorTypeOperation, status.error_type());
-
- status = Status::DataError();
- EXPECT_TRUE(status.IsError());
- EXPECT_EQ("", status.error_details());
- EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
-
- status = Status::ErrorUnsupported();
- EXPECT_TRUE(status.IsError());
- EXPECT_EQ("The requested operation is unsupported", status.error_details());
- EXPECT_EQ(blink::WebCryptoErrorTypeNotSupported, status.error_type());
-
- status = Status::ErrorJwkPropertyMissing("kty");
- EXPECT_TRUE(status.IsError());
- EXPECT_EQ("The required JWK property \"kty\" was missing",
- status.error_details());
- EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
-
- status = Status::ErrorJwkPropertyWrongType("kty", "string");
- EXPECT_TRUE(status.IsError());
- EXPECT_EQ("The JWK property \"kty\" must be a string",
- status.error_details());
- EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
-
- status = Status::ErrorJwkBase64Decode("n");
- EXPECT_TRUE(status.IsError());
- EXPECT_EQ("The JWK property \"n\" could not be base64 decoded",
- status.error_details());
- EXPECT_EQ(blink::WebCryptoErrorTypeData, status.error_type());
-}
-
-TEST_F(SharedCryptoTest, DigestSampleSets) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
-
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- blink::WebCryptoAlgorithm test_algorithm =
- GetDigestAlgorithm(test, "algorithm");
- std::vector<uint8> test_input = GetBytesFromHexString(test, "input");
- std::vector<uint8> test_output = GetBytesFromHexString(test, "output");
-
- std::vector<uint8> output;
- ASSERT_EQ(Status::Success(),
- Digest(test_algorithm, CryptoData(test_input), &output));
- EXPECT_BYTES_EQ(test_output, output);
- }
-}
-
-TEST_F(SharedCryptoTest, DigestSampleSetsInChunks) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("digest.json", &tests));
-
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- blink::WebCryptoAlgorithm test_algorithm =
- GetDigestAlgorithm(test, "algorithm");
- std::vector<uint8> test_input = GetBytesFromHexString(test, "input");
- std::vector<uint8> test_output = GetBytesFromHexString(test, "output");
-
- // Test the chunk version of the digest functions. Test with 129 byte chunks
- // because the SHA-512 chunk size is 128 bytes.
- unsigned char* output;
- unsigned int output_length;
- static const size_t kChunkSizeBytes = 129;
- size_t length = test_input.size();
- scoped_ptr<blink::WebCryptoDigestor> digestor(
- CreateDigestor(test_algorithm.id()));
- std::vector<uint8>::iterator begin = test_input.begin();
- size_t chunk_index = 0;
- while (begin != test_input.end()) {
- size_t chunk_length = std::min(kChunkSizeBytes, length - chunk_index);
- std::vector<uint8> chunk(begin, begin + chunk_length);
- ASSERT_TRUE(chunk.size() > 0);
- EXPECT_TRUE(digestor->consume(&chunk.front(), chunk.size()));
- chunk_index = chunk_index + chunk_length;
- begin = begin + chunk_length;
- }
- EXPECT_TRUE(digestor->finish(output, output_length));
- EXPECT_BYTES_EQ(test_output, CryptoData(output, output_length));
- }
-}
-
-TEST_F(SharedCryptoTest, HMACSampleSets) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("hmac.json", &tests));
- // TODO(padolph): Missing known answer tests for HMAC SHA384, and SHA512.
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- blink::WebCryptoAlgorithm test_hash = GetDigestAlgorithm(test, "hash");
- const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
- const std::vector<uint8> test_message =
- GetBytesFromHexString(test, "message");
- const std::vector<uint8> test_mac = GetBytesFromHexString(test, "mac");
-
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac);
-
- blink::WebCryptoAlgorithm import_algorithm =
- CreateHmacImportAlgorithm(test_hash.id());
-
- blink::WebCryptoKey key = ImportSecretKeyFromRaw(
- test_key,
- import_algorithm,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify);
-
- EXPECT_EQ(test_hash.id(), key.algorithm().hmacParams()->hash().id());
- EXPECT_EQ(test_key.size() * 8, key.algorithm().hmacParams()->lengthBits());
-
- // Verify exported raw key is identical to the imported data
- std::vector<uint8> raw_key;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
- EXPECT_BYTES_EQ(test_key, raw_key);
-
- std::vector<uint8> output;
-
- ASSERT_EQ(Status::Success(),
- Sign(algorithm, key, CryptoData(test_message), &output));
-
- EXPECT_BYTES_EQ(test_mac, output);
-
- bool signature_match = false;
- EXPECT_EQ(Status::Success(),
- VerifySignature(algorithm,
- key,
- CryptoData(output),
- CryptoData(test_message),
- &signature_match));
- EXPECT_TRUE(signature_match);
-
- // Ensure truncated signature does not verify by passing one less byte.
- EXPECT_EQ(
- Status::Success(),
- VerifySignature(algorithm,
- key,
- CryptoData(Uint8VectorStart(output), output.size() - 1),
- CryptoData(test_message),
- &signature_match));
- EXPECT_FALSE(signature_match);
-
- // Ensure truncated signature does not verify by passing no bytes.
- EXPECT_EQ(Status::Success(),
- VerifySignature(algorithm,
- key,
- CryptoData(),
- CryptoData(test_message),
- &signature_match));
- EXPECT_FALSE(signature_match);
-
- // Ensure extra long signature does not cause issues and fails.
- const unsigned char kLongSignature[1024] = {0};
- EXPECT_EQ(
- Status::Success(),
- VerifySignature(algorithm,
- key,
- CryptoData(kLongSignature, sizeof(kLongSignature)),
- CryptoData(test_message),
- &signature_match));
- EXPECT_FALSE(signature_match);
- }
-}
-
-TEST_F(SharedCryptoTest, AesCbcFailures) {
- const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
- blink::WebCryptoKey key = ImportSecretKeyFromRaw(
- HexStringToBytes(key_hex),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
-
- // Verify exported raw key is identical to the imported data
- std::vector<uint8> raw_key;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
- EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
-
- std::vector<uint8> output;
-
- // Use an invalid |iv| (fewer than 16 bytes)
- {
- std::vector<uint8> input(32);
- std::vector<uint8> iv;
- EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
- Encrypt(webcrypto::CreateAesCbcAlgorithm(iv),
- key,
- CryptoData(input),
- &output));
- EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
- Decrypt(webcrypto::CreateAesCbcAlgorithm(iv),
- key,
- CryptoData(input),
- &output));
- }
-
- // Use an invalid |iv| (more than 16 bytes)
- {
- std::vector<uint8> input(32);
- std::vector<uint8> iv(17);
- EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
- Encrypt(webcrypto::CreateAesCbcAlgorithm(iv),
- key,
- CryptoData(input),
- &output));
- EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
- Decrypt(webcrypto::CreateAesCbcAlgorithm(iv),
- key,
- CryptoData(input),
- &output));
- }
-
- // Give an input that is too large (would cause integer overflow when
- // narrowing to an int).
- {
- std::vector<uint8> iv(16);
-
- // Pretend the input is large. Don't pass data pointer as NULL in case that
- // is special cased; the implementation shouldn't actually dereference the
- // data.
- CryptoData input(&iv[0], INT_MAX - 3);
-
- EXPECT_EQ(Status::ErrorDataTooLarge(),
- Encrypt(CreateAesCbcAlgorithm(iv), key, input, &output));
- EXPECT_EQ(Status::ErrorDataTooLarge(),
- Decrypt(CreateAesCbcAlgorithm(iv), key, input, &output));
- }
-
- // Fail importing the key (too few bytes specified)
- {
- std::vector<uint8> key_raw(1);
- std::vector<uint8> iv(16);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- EXPECT_EQ(Status::ErrorImportAesKeyLength(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(key_raw),
- CreateAesCbcAlgorithm(iv),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &key));
- }
-
- // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
- // keys).
- EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
- ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
- EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
- ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &output));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(AesCbcSampleSets)) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
-
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
- std::vector<uint8> test_iv = GetBytesFromHexString(test, "iv");
- std::vector<uint8> test_plain_text =
- GetBytesFromHexString(test, "plain_text");
- std::vector<uint8> test_cipher_text =
- GetBytesFromHexString(test, "cipher_text");
-
- blink::WebCryptoKey key = ImportSecretKeyFromRaw(
- test_key,
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
-
- EXPECT_EQ(test_key.size() * 8, key.algorithm().aesParams()->lengthBits());
-
- // Verify exported raw key is identical to the imported data
- std::vector<uint8> raw_key;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
- EXPECT_BYTES_EQ(test_key, raw_key);
-
- std::vector<uint8> output;
-
- // Test encryption.
- EXPECT_EQ(Status::Success(),
- Encrypt(webcrypto::CreateAesCbcAlgorithm(test_iv),
- key,
- CryptoData(test_plain_text),
- &output));
- EXPECT_BYTES_EQ(test_cipher_text, output);
-
- // Test decryption.
- EXPECT_EQ(Status::Success(),
- Decrypt(webcrypto::CreateAesCbcAlgorithm(test_iv),
- key,
- CryptoData(test_cipher_text),
- &output));
- EXPECT_BYTES_EQ(test_plain_text, output);
-
- const unsigned int kAesCbcBlockSize = 16;
-
- // Decrypt with a padding error by stripping the last block. This also ends
- // up testing decryption over empty cipher text.
- if (test_cipher_text.size() >= kAesCbcBlockSize) {
- EXPECT_EQ(Status::OperationError(),
- Decrypt(CreateAesCbcAlgorithm(test_iv),
- key,
- CryptoData(&test_cipher_text[0],
- test_cipher_text.size() - kAesCbcBlockSize),
- &output));
- }
-
- // Decrypt cipher text which is not a multiple of block size by stripping
- // a few bytes off the cipher text.
- if (test_cipher_text.size() > 3) {
- EXPECT_EQ(
- Status::OperationError(),
- Decrypt(CreateAesCbcAlgorithm(test_iv),
- key,
- CryptoData(&test_cipher_text[0], test_cipher_text.size() - 3),
- &output));
- }
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyAes)) {
- // Check key generation for each of AES-CBC, AES-GCM, and AES-KW, and for each
- // allowed key length.
- std::vector<blink::WebCryptoAlgorithm> algorithm;
- const unsigned short kKeyLength[] = {128, 256};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLength); ++i) {
- algorithm.push_back(CreateAesCbcKeyGenAlgorithm(kKeyLength[i]));
- algorithm.push_back(CreateAesKwKeyGenAlgorithm(kKeyLength[i]));
- if (SupportsAesGcm())
- algorithm.push_back(CreateAesGcmKeyGenAlgorithm(kKeyLength[i]));
- }
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- std::vector<std::vector<uint8> > keys;
- std::vector<uint8> key_bytes;
- for (size_t i = 0; i < algorithm.size(); ++i) {
- SCOPED_TRACE(i);
- // Generate a small sample of keys.
- keys.clear();
- for (int j = 0; j < 16; ++j) {
- ASSERT_EQ(Status::Success(),
- GenerateSecretKey(algorithm[i], true, 0, &key));
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
- EXPECT_EQ(key_bytes.size() * 8,
- key.algorithm().aesParams()->lengthBits());
- keys.push_back(key_bytes);
- }
- // Ensure all entries in the key sample set are unique. This is a simplistic
- // estimate of whether the generated keys appear random.
- EXPECT_FALSE(CopiesExist(keys));
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyAesBadLength)) {
- const unsigned short kKeyLen[] = {0, 127, 257};
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLen); ++i) {
- SCOPED_TRACE(i);
- EXPECT_EQ(Status::ErrorGenerateKeyLength(),
- GenerateSecretKey(
- CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
- EXPECT_EQ(Status::ErrorGenerateKeyLength(),
- GenerateSecretKey(
- CreateAesKwKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
- if (SupportsAesGcm()) {
- EXPECT_EQ(Status::ErrorGenerateKeyLength(),
- GenerateSecretKey(
- CreateAesGcmKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
- }
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyHmac)) {
- // Generate a small sample of HMAC keys.
- std::vector<std::vector<uint8> > keys;
- for (int i = 0; i < 16; ++i) {
- std::vector<uint8> key_bytes;
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- blink::WebCryptoAlgorithm algorithm =
- CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 512);
- ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
- EXPECT_FALSE(key.isNull());
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
- key.algorithm().hmacParams()->hash().id());
- EXPECT_EQ(512u, key.algorithm().hmacParams()->lengthBits());
-
- std::vector<uint8> raw_key;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
- EXPECT_EQ(64U, raw_key.size());
- keys.push_back(raw_key);
- }
- // Ensure all entries in the key sample set are unique. This is a simplistic
- // estimate of whether the generated keys appear random.
- EXPECT_FALSE(CopiesExist(keys));
-}
-
-// If the key length is not provided, then the block size is used.
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyHmacNoLength)) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- blink::WebCryptoAlgorithm algorithm =
- CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
- ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
- key.algorithm().hmacParams()->hash().id());
- EXPECT_EQ(512u, key.algorithm().hmacParams()->lengthBits());
- std::vector<uint8> raw_key;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
- EXPECT_EQ(64U, raw_key.size());
-
- // The block size for HMAC SHA-512 is larger.
- algorithm = CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha512, 0);
- ASSERT_EQ(Status::Success(), GenerateSecretKey(algorithm, true, 0, &key));
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha512,
- key.algorithm().hmacParams()->hash().id());
- EXPECT_EQ(1024u, key.algorithm().hmacParams()->lengthBits());
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
- EXPECT_EQ(128U, raw_key.size());
-}
-
-TEST_F(SharedCryptoTest, ImportJwkKeyUsage) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- base::DictionaryValue dict;
- dict.SetString("kty", "oct");
- dict.SetBoolean("ext", false);
- dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
- const blink::WebCryptoAlgorithm aes_cbc_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- const blink::WebCryptoAlgorithm hmac_algorithm =
- webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
- const blink::WebCryptoAlgorithm aes_kw_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- // Test null usage.
- base::ListValue* key_ops = new base::ListValue;
- // Note: the following call makes dict assume ownership of key_ops.
- dict.Set("key_ops", key_ops);
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, aes_cbc_algorithm, false, 0, &key));
- EXPECT_EQ(0, key.usages());
-
- // Test each key_ops value translates to the correct Web Crypto value.
- struct TestCase {
- const char* jwk_key_op;
- const char* jwk_alg;
- const blink::WebCryptoAlgorithm algorithm;
- const blink::WebCryptoKeyUsage usage;
- };
- // TODO(padolph): Add 'deriveBits' key_ops value once it is supported.
- const TestCase test_case[] = {
- {"encrypt", "A128CBC", aes_cbc_algorithm,
- blink::WebCryptoKeyUsageEncrypt},
- {"decrypt", "A128CBC", aes_cbc_algorithm,
- blink::WebCryptoKeyUsageDecrypt},
- {"sign", "HS256", hmac_algorithm, blink::WebCryptoKeyUsageSign},
- {"verify", "HS256", hmac_algorithm, blink::WebCryptoKeyUsageVerify},
- {"wrapKey", "A128KW", aes_kw_algorithm, blink::WebCryptoKeyUsageWrapKey},
- {"unwrapKey", "A128KW", aes_kw_algorithm,
- blink::WebCryptoKeyUsageUnwrapKey}};
- for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(test_case);
- ++test_index) {
- SCOPED_TRACE(test_index);
- dict.SetString("alg", test_case[test_index].jwk_alg);
- key_ops->Clear();
- key_ops->AppendString(test_case[test_index].jwk_key_op);
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict,
- test_case[test_index].algorithm,
- false,
- test_case[test_index].usage,
- &key));
- EXPECT_EQ(test_case[test_index].usage, key.usages());
- }
-
- // Test discrete multiple usages.
- dict.SetString("alg", "A128CBC");
- key_ops->Clear();
- key_ops->AppendString("encrypt");
- key_ops->AppendString("decrypt");
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict,
- aes_cbc_algorithm,
- false,
- blink::WebCryptoKeyUsageDecrypt |
- blink::WebCryptoKeyUsageEncrypt,
- &key));
- EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt,
- key.usages());
-
- // Test constrained key usage (input usage is a subset of JWK usage).
- key_ops->Clear();
- key_ops->AppendString("encrypt");
- key_ops->AppendString("decrypt");
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict,
- aes_cbc_algorithm,
- false,
- blink::WebCryptoKeyUsageDecrypt,
- &key));
- EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages());
-
- // Test failure if input usage is NOT a strict subset of the JWK usage.
- key_ops->Clear();
- key_ops->AppendString("encrypt");
- EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
- ImportKeyJwkFromDict(dict,
- aes_cbc_algorithm,
- false,
- blink::WebCryptoKeyUsageEncrypt |
- blink::WebCryptoKeyUsageDecrypt,
- &key));
-
- // Test 'use' inconsistent with 'key_ops'.
- dict.SetString("alg", "HS256");
- dict.SetString("use", "sig");
- key_ops->AppendString("sign");
- key_ops->AppendString("verify");
- key_ops->AppendString("encrypt");
- EXPECT_EQ(Status::ErrorJwkUseAndKeyopsInconsistent(),
- ImportKeyJwkFromDict(
- dict,
- hmac_algorithm,
- false,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- &key));
-
- // Test JWK composite 'sig' use
- dict.Remove("key_ops", NULL);
- dict.SetString("use", "sig");
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(
- dict,
- hmac_algorithm,
- false,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- &key));
- EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- key.usages());
-
- // Test JWK composite use 'enc' usage
- dict.SetString("alg", "A128CBC");
- dict.SetString("use", "enc");
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict,
- aes_cbc_algorithm,
- false,
- blink::WebCryptoKeyUsageDecrypt |
- blink::WebCryptoKeyUsageEncrypt |
- blink::WebCryptoKeyUsageWrapKey |
- blink::WebCryptoKeyUsageUnwrapKey,
- &key));
- EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt |
- blink::WebCryptoKeyUsageWrapKey |
- blink::WebCryptoKeyUsageUnwrapKey,
- key.usages());
-}
-
-TEST_F(SharedCryptoTest, ImportJwkFailures) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
-
- // Baseline pass: each test below breaks a single item, so we start with a
- // passing case to make sure each failure is caused by the isolated break.
- // Each breaking subtest below resets the dictionary to this passing case when
- // complete.
- base::DictionaryValue dict;
- RestoreJwkOctDictionary(&dict);
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
-
- // Fail on empty JSON.
- EXPECT_EQ(
- Status::ErrorImportEmptyKeyData(),
- ImportKeyJwk(
- CryptoData(MakeJsonVector("")), algorithm, false, usage_mask, &key));
-
- // Fail on invalid JSON.
- const std::vector<uint8> bad_json_vec = MakeJsonVector(
- "{"
- "\"kty\" : \"oct\","
- "\"alg\" : \"HS256\","
- "\"use\" : ");
- EXPECT_EQ(Status::ErrorJwkNotDictionary(),
- ImportKeyJwk(
- CryptoData(bad_json_vec), algorithm, false, usage_mask, &key));
-
- // Fail on JWK alg present but unrecognized.
- dict.SetString("alg", "A127CBC");
- EXPECT_EQ(Status::ErrorJwkUnrecognizedAlgorithm(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on invalid kty.
- dict.SetString("kty", "foo");
- EXPECT_EQ(Status::ErrorJwkUnrecognizedKty(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on missing kty.
- dict.Remove("kty", NULL);
- EXPECT_EQ(Status::ErrorJwkPropertyMissing("kty"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on kty wrong type.
- dict.SetDouble("kty", 0.1);
- EXPECT_EQ(Status::ErrorJwkPropertyWrongType("kty", "string"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on invalid use.
- dict.SetString("use", "foo");
- EXPECT_EQ(Status::ErrorJwkUnrecognizedUse(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on invalid use (wrong type).
- dict.SetBoolean("use", true);
- EXPECT_EQ(Status::ErrorJwkPropertyWrongType("use", "string"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on invalid extractable (wrong type).
- dict.SetInteger("ext", 0);
- EXPECT_EQ(Status::ErrorJwkPropertyWrongType("ext", "boolean"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on invalid key_ops (wrong type).
- dict.SetBoolean("key_ops", true);
- EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops", "list"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
- // only "foo".
- base::ListValue* key_ops = new base::ListValue;
- // Note: the following call makes dict assume ownership of key_ops.
- dict.Set("key_ops", key_ops);
- key_ops->AppendString("foo");
- EXPECT_EQ(Status::ErrorJwkKeyopsInconsistent(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-}
-
-// Import a JWK with unrecognized values for "key_ops".
-TEST_F(SharedCryptoTest, ImportJwkUnrecognizedKeyOps) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
-
- base::DictionaryValue dict;
- RestoreJwkOctDictionary(&dict);
-
- base::ListValue* key_ops = new base::ListValue;
- dict.Set("key_ops", key_ops);
- key_ops->AppendString("foo");
- key_ops->AppendString("bar");
- key_ops->AppendString("baz");
- key_ops->AppendString("encrypt");
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
-}
-
-// Import a JWK with a value in key_ops array that is not a string.
-TEST_F(SharedCryptoTest, ImportJwkNonStringKeyOp) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
-
- base::DictionaryValue dict;
- RestoreJwkOctDictionary(&dict);
-
- base::ListValue* key_ops = new base::ListValue;
- dict.Set("key_ops", key_ops);
- key_ops->AppendString("encrypt");
- key_ops->AppendInteger(3);
- EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops[1]", "string"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
-}
-
-TEST_F(SharedCryptoTest, ImportJwkOctFailures) {
- base::DictionaryValue dict;
- RestoreJwkOctDictionary(&dict);
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- // Baseline pass.
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- EXPECT_EQ(algorithm.id(), key.algorithm().id());
- EXPECT_FALSE(key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
-
- // The following are specific failure cases for when kty = "oct".
-
- // Fail on missing k.
- dict.Remove("k", NULL);
- EXPECT_EQ(Status::ErrorJwkPropertyMissing("k"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on bad b64 encoding for k.
- dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
- EXPECT_EQ(Status::ErrorJwkBase64Decode("k"),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on empty k.
- dict.SetString("k", "");
- EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
- // value (128) for an AES key.
- dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
- EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-
- // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
- // value (128) for an AES key.
- dict.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
- EXPECT_EQ(Status::ErrorJwkIncorrectKeyLength(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkOctDictionary(&dict);
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkRsaPublicKey)) {
- if (!SupportsRsaKeyImport())
- return;
-
- const bool supports_rsa_oaep = SupportsRsaOaep();
- if (!supports_rsa_oaep) {
- LOG(WARNING) << "RSA-OAEP not supported on this platform. Skipping some"
- << "tests.";
- }
-
- struct TestCase {
- const blink::WebCryptoAlgorithm algorithm;
- const blink::WebCryptoKeyUsageMask usage;
- const char* const jwk_alg;
- };
- const TestCase kTests[] = {
- // RSASSA-PKCS1-v1_5 SHA-1
- {CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- blink::WebCryptoKeyUsageVerify, "RS1"},
- // RSASSA-PKCS1-v1_5 SHA-256
- {CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- blink::WebCryptoKeyUsageVerify, "RS256"},
- // RSASSA-PKCS1-v1_5 SHA-384
- {CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha384),
- blink::WebCryptoKeyUsageVerify, "RS384"},
- // RSASSA-PKCS1-v1_5 SHA-512
- {CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha512),
- blink::WebCryptoKeyUsageVerify, "RS512"},
- // RSA-OAEP with SHA-1 and MGF-1 / SHA-1
- {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP"},
- // RSA-OAEP with SHA-256 and MGF-1 / SHA-256
- {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha256),
- blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-256"},
- // RSA-OAEP with SHA-384 and MGF-1 / SHA-384
- {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha384),
- blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-384"},
- // RSA-OAEP with SHA-512 and MGF-1 / SHA-512
- {CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha512),
- blink::WebCryptoKeyUsageEncrypt, "RSA-OAEP-512"}};
-
- for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
- ++test_index) {
- SCOPED_TRACE(test_index);
- const TestCase& test = kTests[test_index];
- if (!supports_rsa_oaep &&
- test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep) {
- continue;
- }
-
- // Import the spki to create a public key
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
- test.algorithm,
- true,
- test.usage,
- &public_key));
-
- // Export the public key as JWK and verify its contents
- std::vector<uint8> jwk;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
- EXPECT_TRUE(VerifyPublicJwk(jwk,
- test.jwk_alg,
- kPublicKeyModulusHex,
- kPublicKeyExponentHex,
- test.usage));
-
- // Import the JWK back in to create a new key
- blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
- ASSERT_EQ(
- Status::Success(),
- ImportKeyJwk(
- CryptoData(jwk), test.algorithm, true, test.usage, &public_key2));
- ASSERT_TRUE(public_key2.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
- EXPECT_TRUE(public_key2.extractable());
- EXPECT_EQ(test.algorithm.id(), public_key2.algorithm().id());
-
- // Only perform SPKI consistency test for RSA-SSA as its
- // export format is the same as kPublicKeySpkiDerHex
- if (test.algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5) {
- // Export the new key as spki and compare to the original.
- std::vector<uint8> spki;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
- EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, CryptoData(spki));
- }
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportJwkRsaFailures)) {
- base::DictionaryValue dict;
- RestoreJwkRsaDictionary(&dict);
- blink::WebCryptoAlgorithm algorithm =
- CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
- // entry, while an RSA private key must have those plus at least a "d"
- // (private exponent) entry.
- // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
- // section 6.3.
-
- // Baseline pass.
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- EXPECT_EQ(algorithm.id(), key.algorithm().id());
- EXPECT_FALSE(key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
-
- // The following are specific failure cases for when kty = "RSA".
-
- // Fail if either "n" or "e" is not present or malformed.
- const std::string kKtyParmName[] = {"n", "e"};
- for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
- // Fail on missing parameter.
- dict.Remove(kKtyParmName[idx], NULL);
- EXPECT_NE(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkRsaDictionary(&dict);
-
- // Fail on bad b64 parameter encoding.
- dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
- EXPECT_NE(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkRsaDictionary(&dict);
-
- // Fail on empty parameter.
- dict.SetString(kKtyParmName[idx], "");
- EXPECT_NE(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- RestoreJwkRsaDictionary(&dict);
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportJwkInputConsistency)) {
- // The Web Crypto spec says that if a JWK value is present, but is
- // inconsistent with the input value, the operation must fail.
-
- // Consistency rules when JWK value is not present: Inputs should be used.
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- bool extractable = false;
- blink::WebCryptoAlgorithm algorithm =
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageVerify;
- base::DictionaryValue dict;
- dict.SetString("kty", "oct");
- dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
- std::vector<uint8> json_vec = MakeJsonVector(dict);
- EXPECT_EQ(
- Status::Success(),
- ImportKeyJwk(
- CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(extractable, key.extractable());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
- key.algorithm().hmacParams()->hash().id());
- EXPECT_EQ(320u, key.algorithm().hmacParams()->lengthBits());
- EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
- key = blink::WebCryptoKey::createNull();
-
- // Consistency rules when JWK value exists: Fail if inconsistency is found.
-
- // Pass: All input values are consistent with the JWK values.
- dict.Clear();
- dict.SetString("kty", "oct");
- dict.SetString("alg", "HS256");
- dict.SetString("use", "sig");
- dict.SetBoolean("ext", false);
- dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
- json_vec = MakeJsonVector(dict);
- EXPECT_EQ(
- Status::Success(),
- ImportKeyJwk(
- CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
-
- // Extractable cases:
- // 1. input=T, JWK=F ==> fail (inconsistent)
- // 4. input=F, JWK=F ==> pass, result extractable is F
- // 2. input=T, JWK=T ==> pass, result extractable is T
- // 3. input=F, JWK=T ==> pass, result extractable is F
- EXPECT_EQ(
- Status::ErrorJwkExtInconsistent(),
- ImportKeyJwk(CryptoData(json_vec), algorithm, true, usage_mask, &key));
- EXPECT_EQ(
- Status::Success(),
- ImportKeyJwk(CryptoData(json_vec), algorithm, false, usage_mask, &key));
- EXPECT_FALSE(key.extractable());
- dict.SetBoolean("ext", true);
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, true, usage_mask, &key));
- EXPECT_TRUE(key.extractable());
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, false, usage_mask, &key));
- EXPECT_FALSE(key.extractable());
- dict.SetBoolean("ext", true); // restore previous value
-
- // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value
- // (HMAC SHA256).
- EXPECT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
- ImportKeyJwk(CryptoData(json_vec),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- extractable,
- blink::WebCryptoKeyUsageEncrypt,
- &key));
-
- // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value
- // (HMAC SHA256).
- EXPECT_EQ(
- Status::ErrorJwkAlgorithmInconsistent(),
- ImportKeyJwk(CryptoData(json_vec),
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
- extractable,
- usage_mask,
- &key));
-
- // Pass: JWK alg missing but input algorithm specified: use input value
- dict.Remove("alg", NULL);
- EXPECT_EQ(Status::Success(),
- ImportKeyJwkFromDict(
- dict,
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
- extractable,
- usage_mask,
- &key));
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, algorithm.id());
- dict.SetString("alg", "HS256");
-
- // Fail: Input usage_mask (encrypt) is not a subset of the JWK value
- // (sign|verify). Moreover "encrypt" is not a valid usage for HMAC.
- EXPECT_EQ(Status::ErrorCreateKeyBadUsages(),
- ImportKeyJwk(CryptoData(json_vec),
- algorithm,
- extractable,
- blink::WebCryptoKeyUsageEncrypt,
- &key));
-
- // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK
- // value (sign|verify). Moreover "encrypt" is not a valid usage for HMAC.
- usage_mask = blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageSign |
- blink::WebCryptoKeyUsageVerify;
- EXPECT_EQ(
- Status::ErrorCreateKeyBadUsages(),
- ImportKeyJwk(
- CryptoData(json_vec), algorithm, extractable, usage_mask, &key));
-
- // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
- // only certain alg values are permitted. For example, when kty = "RSA" alg
- // must be of the RSA family, or when kty = "oct" alg must be symmetric
- // algorithm.
-
- // TODO(padolph): key_ops consistency tests
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportJwkHappy)) {
- // This test verifies the happy path of JWK import, including the application
- // of the imported key material.
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- bool extractable = false;
- blink::WebCryptoAlgorithm algorithm =
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
- blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageSign;
-
- // Import a symmetric key JWK and HMAC-SHA256 sign()
- // Uses the first SHA256 test vector from the HMAC sample set above.
-
- base::DictionaryValue dict;
- dict.SetString("kty", "oct");
- dict.SetString("alg", "HS256");
- dict.SetString("use", "sig");
- dict.SetBoolean("ext", false);
- dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
-
- ASSERT_EQ(
- Status::Success(),
- ImportKeyJwkFromDict(dict, algorithm, extractable, usage_mask, &key));
-
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
- key.algorithm().hmacParams()->hash().id());
-
- const std::vector<uint8> message_raw = HexStringToBytes(
- "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
- "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
- "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
- "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
-
- std::vector<uint8> output;
-
- ASSERT_EQ(Status::Success(),
- Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
- key,
- CryptoData(message_raw),
- &output));
-
- const std::string mac_raw =
- "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
-
- EXPECT_BYTES_EQ_HEX(mac_raw, output);
-
- // TODO(padolph): Import an RSA public key JWK and use it
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkSymmetricKey)) {
- // Raw keys are generated by openssl:
- // % openssl rand -hex <key length bytes>
- const char* const key_hex_128 = "3f1e7cd4f6f8543f6b1e16002e688623";
- const char* const key_hex_256 =
- "bd08286b81a74783fd1ccf46b7e05af84ee25ae021210074159e0c4d9d907692";
- const char* const key_hex_384 =
- "a22c5441c8b185602283d64c7221de1d0951e706bfc09539435ec0e0ed614e1d406623f2"
- "b31d31819fec30993380dd82";
- const char* const key_hex_512 =
- "5834f639000d4cf82de124fbfd26fb88d463e99f839a76ba41ac88967c80a3f61e1239a4"
- "52e573dba0750e988152988576efd75b8d0229b7aca2ada2afd392ee";
- const blink::WebCryptoAlgorithm aes_cbc_alg =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- const blink::WebCryptoAlgorithm aes_gcm_alg =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm);
- const blink::WebCryptoAlgorithm aes_kw_alg =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
- const blink::WebCryptoAlgorithm hmac_sha_1_alg =
- webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1);
- const blink::WebCryptoAlgorithm hmac_sha_256_alg =
- webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256);
- const blink::WebCryptoAlgorithm hmac_sha_384_alg =
- webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha384);
- const blink::WebCryptoAlgorithm hmac_sha_512_alg =
- webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha512);
-
- struct TestCase {
- const char* const key_hex;
- const blink::WebCryptoAlgorithm algorithm;
- const blink::WebCryptoKeyUsageMask usage;
- const char* const jwk_alg;
- };
-
- // TODO(padolph): Test AES-CTR JWK export, once AES-CTR import works.
- const TestCase kTests[] = {
- // AES-CBC 128
- {key_hex_128, aes_cbc_alg,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
- "A128CBC"},
- // AES-CBC 256
- {key_hex_256, aes_cbc_alg, blink::WebCryptoKeyUsageDecrypt, "A256CBC"},
- // AES-GCM 128
- {key_hex_128, aes_gcm_alg,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
- "A128GCM"},
- // AES-GCM 256
- {key_hex_256, aes_gcm_alg, blink::WebCryptoKeyUsageDecrypt, "A256GCM"},
- // AES-KW 128
- {key_hex_128, aes_kw_alg,
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
- "A128KW"},
- // AES-KW 256
- {key_hex_256, aes_kw_alg,
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
- "A256KW"},
- // HMAC SHA-1
- {key_hex_256, hmac_sha_1_alg,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, "HS1"},
- // HMAC SHA-384
- {key_hex_384, hmac_sha_384_alg, blink::WebCryptoKeyUsageSign, "HS384"},
- // HMAC SHA-512
- {key_hex_512, hmac_sha_512_alg, blink::WebCryptoKeyUsageVerify, "HS512"},
- // Large usage value
- {key_hex_256, aes_cbc_alg,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
- "A256CBC"},
- // Zero usage value
- {key_hex_512, hmac_sha_512_alg, 0, "HS512"},
- };
-
- // Round-trip import/export each key.
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- std::vector<uint8> json;
- for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
- ++test_index) {
- SCOPED_TRACE(test_index);
- const TestCase& test = kTests[test_index];
-
- // Skip AES-GCM tests where not supported.
- if (test.algorithm.id() == blink::WebCryptoAlgorithmIdAesGcm &&
- !SupportsAesGcm()) {
- continue;
- }
-
- // Import a raw key.
- key = ImportSecretKeyFromRaw(
- HexStringToBytes(test.key_hex), test.algorithm, test.usage);
-
- // Export the key in JWK format and validate.
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
- EXPECT_TRUE(VerifySecretJwk(json, test.jwk_alg, test.key_hex, test.usage));
-
- // Import the JWK-formatted key.
- ASSERT_EQ(
- Status::Success(),
- ImportKeyJwk(CryptoData(json), test.algorithm, true, test.usage, &key));
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(test.algorithm.id(), key.algorithm().id());
- EXPECT_EQ(true, key.extractable());
- EXPECT_EQ(test.usage, key.usages());
-
- // Export the key in raw format and compare to the original.
- std::vector<uint8> key_raw_out;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
- EXPECT_BYTES_EQ_HEX(test.key_hex, key_raw_out);
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ExportJwkEmptySymmetricKey)) {
- const blink::WebCryptoAlgorithm import_algorithm =
- webcrypto::CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1);
-
- blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageSign;
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- // Import a zero-byte HMAC key.
- const char key_data_hex[] = "";
- key = ImportSecretKeyFromRaw(
- HexStringToBytes(key_data_hex), import_algorithm, usages);
- EXPECT_EQ(0u, key.algorithm().hmacParams()->lengthBits());
-
- // Export the key in JWK format and validate.
- std::vector<uint8> json;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
- EXPECT_TRUE(VerifySecretJwk(json, "HS1", key_data_hex, usages));
-
- // Now try re-importing the JWK key.
- key = blink::WebCryptoKey::createNull();
- EXPECT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatJwk,
- CryptoData(json),
- import_algorithm,
- true,
- usages,
- &key));
-
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(0u, key.algorithm().hmacParams()->lengthBits());
-
- std::vector<uint8> exported_key_data;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key_data));
-
- EXPECT_EQ(0u, exported_key_data.size());
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportExportSpki)) {
- if (!SupportsRsaKeyImport())
- return;
-
- // Passing case: Import a valid RSA key in SPKI format.
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- blink::WebCryptoKeyUsageVerify,
- &key));
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
- EXPECT_TRUE(key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageVerify, key.usages());
- EXPECT_EQ(kModulusLengthBits,
- key.algorithm().rsaHashedParams()->modulusLengthBits());
- EXPECT_BYTES_EQ_HEX(
- "010001",
- CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
-
- // Failing case: Empty SPKI data
- EXPECT_EQ(
- Status::ErrorImportEmptyKeyData(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(std::vector<uint8>()),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
- true,
- blink::WebCryptoKeyUsageVerify,
- &key));
-
- // Failing case: Bad DER encoding.
- EXPECT_EQ(
- Status::DataError(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes("618333c4cb")),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
- true,
- blink::WebCryptoKeyUsageVerify,
- &key));
-
- // Failing case: Import RSA key but provide an inconsistent input algorithm.
- EXPECT_EQ(Status::DataError(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &key));
-
- // Passing case: Export a previously imported RSA public key in SPKI format
- // and compare to original data.
- std::vector<uint8> output;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
- EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
-
- // Failing case: Try to export a previously imported RSA public key in raw
- // format (not allowed for a public key).
- EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &output));
-
- // Failing case: Try to export a non-extractable key
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- false,
- blink::WebCryptoKeyUsageVerify,
- &key));
- EXPECT_TRUE(key.handle());
- EXPECT_FALSE(key.extractable());
- EXPECT_EQ(Status::ErrorKeyNotExtractable(),
- ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
-
- // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
- // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
- // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
- // (e.g. SHA-1 in OID, SHA-256 in params)
- // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
- // as OAEP/PSS
-}
-
-TEST_F(SharedCryptoTest, MAYBE(ImportExportPkcs8)) {
- if (!SupportsRsaKeyImport())
- return;
-
- // Passing case: Import a valid RSA key in PKCS#8 format.
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypePrivate, key.type());
- EXPECT_TRUE(key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
- key.algorithm().rsaHashedParams()->hash().id());
- EXPECT_EQ(kModulusLengthBits,
- key.algorithm().rsaHashedParams()->modulusLengthBits());
- EXPECT_BYTES_EQ_HEX(
- "010001",
- CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
-
- std::vector<uint8> exported_key;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
- EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
-
- // Failing case: Empty PKCS#8 data
- EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(std::vector<uint8>()),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-
- // Failing case: Bad DER encoding.
- EXPECT_EQ(
- Status::DataError(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(HexStringToBytes("618333c4cb")),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-
- // Failing case: Import RSA key but provide an inconsistent input algorithm
- // and usage. Several issues here:
- // * AES-CBC doesn't support PKCS8 key format
- // * AES-CBC doesn't support "sign" usage
- EXPECT_EQ(Status::ErrorCreateKeyBadUsages(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-}
-
-// Tests JWK import and export by doing a roundtrip key conversion and ensuring
-// it was lossless:
-//
-// PKCS8 --> JWK --> PKCS8
-TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkToPkcs8RoundTrip)) {
- if (!SupportsRsaKeyImport())
- return;
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-
- std::vector<uint8> exported_key_jwk;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatJwk, key, &exported_key_jwk));
-
- // All of the optional parameters (p, q, dp, dq, qi) should be present in the
- // output.
- const char* expected_jwk =
- "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
- "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
- "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
- "\"KPoTk4ZVvh-"
- "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
- "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
- "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
- "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
- "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
- "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
- "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
- "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
- "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
- "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
- "\"JxVqukEm0kqB86Uoy_sn9WiG-"
- "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
-
- ASSERT_EQ(CryptoData(std::string(expected_jwk)),
- CryptoData(exported_key_jwk));
-
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatJwk,
- CryptoData(exported_key_jwk),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-
- std::vector<uint8> exported_key_pkcs8;
- ASSERT_EQ(
- Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key_pkcs8));
-
- ASSERT_EQ(CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
- CryptoData(exported_key_pkcs8));
-}
-
-// Tests importing multiple RSA private keys from JWK, and then exporting to
-// PKCS8.
-//
-// This is a regression test for http://crbug.com/378315, for which importing
-// a sequence of keys from JWK could yield the wrong key. The first key would
-// be imported correctly, however every key after that would actually import
-// the first key.
-TEST_F(SharedCryptoTest, MAYBE(ImportMultipleRSAPrivateKeysJwk)) {
- if (!SupportsRsaKeyImport())
- return;
-
- scoped_ptr<base::ListValue> key_list;
- ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
-
- // For this test to be meaningful the keys MUST be kept alive before importing
- // new keys.
- std::vector<blink::WebCryptoKey> live_keys;
-
- for (size_t key_index = 0; key_index < key_list->GetSize(); ++key_index) {
- SCOPED_TRACE(key_index);
-
- base::DictionaryValue* key_values;
- ASSERT_TRUE(key_list->GetDictionary(key_index, &key_values));
-
- // Get the JWK representation of the key.
- base::DictionaryValue* key_jwk;
- ASSERT_TRUE(key_values->GetDictionary("jwk", &key_jwk));
-
- // Get the PKCS8 representation of the key.
- std::string pkcs8_hex_string;
- ASSERT_TRUE(key_values->GetString("pkcs8", &pkcs8_hex_string));
- std::vector<uint8> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
-
- // Get the modulus length for the key.
- int modulus_length_bits = 0;
- ASSERT_TRUE(key_values->GetInteger("modulusLength", &modulus_length_bits));
-
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- // Import the key from JWK.
- ASSERT_EQ(
- Status::Success(),
- ImportKeyJwkFromDict(*key_jwk,
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- blink::WebCryptoKeyUsageSign,
- &private_key));
-
- live_keys.push_back(private_key);
-
- EXPECT_EQ(
- modulus_length_bits,
- static_cast<int>(
- private_key.algorithm().rsaHashedParams()->modulusLengthBits()));
-
- // Export to PKCS8 and verify that it matches expectation.
- std::vector<uint8> exported_key_pkcs8;
- ASSERT_EQ(
- Status::Success(),
- ExportKey(
- blink::WebCryptoKeyFormatPkcs8, private_key, &exported_key_pkcs8));
-
- EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
- }
-}
-
-// Import an RSA private key using JWK. Next import a JWK containing the same
-// modulus, but mismatched parameters for the rest. It should NOT be possible
-// that the second import retrieves the first key. See http://crbug.com/378315
-// for how that could happen.
-TEST_F(SharedCryptoTest, MAYBE(ImportJwkExistingModulusAndInvalid)) {
-#if defined(USE_NSS)
- if (!NSS_VersionCheck("3.16.2")) {
- LOG(WARNING) << "Skipping test because lacks NSS support";
- return;
- }
-#endif
-
- scoped_ptr<base::ListValue> key_list;
- ASSERT_TRUE(ReadJsonTestFileToList("rsa_private_keys.json", &key_list));
-
- // Import a 1024-bit private key.
- base::DictionaryValue* key1_props;
- ASSERT_TRUE(key_list->GetDictionary(1, &key1_props));
- base::DictionaryValue* key1_jwk;
- ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
-
- blink::WebCryptoKey key1 = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKeyJwkFromDict(*key1_jwk,
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- blink::WebCryptoKeyUsageSign,
- &key1));
-
- ASSERT_EQ(1024u, key1.algorithm().rsaHashedParams()->modulusLengthBits());
-
- // Construct a JWK using the modulus of key1, but all the other fields from
- // another key (also a 1024-bit private key).
- base::DictionaryValue* key2_props;
- ASSERT_TRUE(key_list->GetDictionary(5, &key2_props));
- base::DictionaryValue* key2_jwk;
- ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
- std::string modulus;
- key1_jwk->GetString("n", &modulus);
- key2_jwk->SetString("n", modulus);
-
- // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
- // somehow return the key created earlier.
- blink::WebCryptoKey key2 = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::OperationError(),
- ImportKeyJwkFromDict(*key2_jwk,
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- blink::WebCryptoKeyUsageSign,
- &key2));
-}
-
-// Import a JWK RSA private key with some optional parameters missing (q, dp,
-// dq, qi).
-//
-// The only optional parameter included is "p".
-//
-// This fails because JWA says that producers must include either ALL optional
-// parameters or NONE.
-TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkMissingOptionalParams)) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- base::DictionaryValue dict;
- dict.SetString("kty", "RSA");
- dict.SetString("alg", "RS1");
-
- dict.SetString(
- "n",
- "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
- "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
- "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
- dict.SetString("e", "AQAB");
- dict.SetString(
- "d",
- "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
- "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
- "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
-
- dict.SetString("p",
- "5-"
- "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31W"
- "hU1vZs8w0Fgs7bc0-2o5kQw");
-
- ASSERT_EQ(Status::ErrorJwkIncompleteOptionalRsaPrivateKey(),
- ImportKeyJwkFromDict(dict,
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-}
-
-// Import a JWK RSA private key, without any of the optional parameters.
-//
-// This is expected to work, however based on the current NSS implementation it
-// does not.
-//
-// TODO(eroman): http://crbug/com/374927
-TEST_F(SharedCryptoTest, MAYBE(ImportRsaPrivateKeyJwkIncorrectOptionalEmpty)) {
- if (!SupportsRsaKeyImport())
- return;
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- base::DictionaryValue dict;
- dict.SetString("kty", "RSA");
- dict.SetString("alg", "RS1");
-
- dict.SetString(
- "n",
- "pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
- "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
- "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc");
- dict.SetString("e", "AQAB");
- dict.SetString(
- "d",
- "M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
- "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
- "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU");
-
- // TODO(eroman): This should pass, see: http://crbug/com/374927
- //
- // Technically it is OK to fail since JWA says that consumer are not required
- // to support lack of the optional parameters.
- ASSERT_EQ(Status::OperationError(),
- ImportKeyJwkFromDict(dict,
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &key));
-
-}
-
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyPairRsa)) {
- // Note: using unrealistic short key lengths here to avoid bogging down tests.
-
- // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
- const unsigned int modulus_length = 256;
- const std::vector<uint8> public_exponent = HexStringToBytes("010001");
- blink::WebCryptoAlgorithm algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- public_exponent);
- bool extractable = true;
- const blink::WebCryptoKeyUsageMask usage_mask = 0;
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- EXPECT_EQ(Status::Success(),
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key));
- EXPECT_FALSE(public_key.isNull());
- EXPECT_FALSE(private_key.isNull());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
- EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
- EXPECT_EQ(modulus_length,
- public_key.algorithm().rsaHashedParams()->modulusLengthBits());
- EXPECT_EQ(modulus_length,
- private_key.algorithm().rsaHashedParams()->modulusLengthBits());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
- public_key.algorithm().rsaHashedParams()->hash().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
- private_key.algorithm().rsaHashedParams()->hash().id());
- EXPECT_TRUE(public_key.extractable());
- EXPECT_EQ(extractable, private_key.extractable());
- EXPECT_EQ(usage_mask, public_key.usages());
- EXPECT_EQ(usage_mask, private_key.usages());
-
- // Try exporting the generated key pair, and then re-importing to verify that
- // the exported data was valid.
- std::vector<uint8> public_key_spki;
- EXPECT_EQ(
- Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
-
- if (SupportsRsaKeyImport()) {
- public_key = blink::WebCryptoKey::createNull();
- EXPECT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(public_key_spki),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- usage_mask,
- &public_key));
- EXPECT_EQ(modulus_length,
- public_key.algorithm().rsaHashedParams()->modulusLengthBits());
-
- std::vector<uint8> private_key_pkcs8;
- EXPECT_EQ(
- Status::Success(),
- ExportKey(
- blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
- private_key = blink::WebCryptoKey::createNull();
- EXPECT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(private_key_pkcs8),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- usage_mask,
- &private_key));
- EXPECT_EQ(modulus_length,
- private_key.algorithm().rsaHashedParams()->modulusLengthBits());
- }
-
- // Fail with bad modulus.
- algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- 0,
- public_exponent);
- EXPECT_EQ(Status::ErrorGenerateRsaZeroModulus(),
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key));
-
- // Fail with bad exponent: larger than unsigned long.
- unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT
- const std::vector<uint8> long_exponent(exponent_length, 0x01);
- algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- long_exponent);
- EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key));
-
- // Fail with bad exponent: empty.
- const std::vector<uint8> empty_exponent;
- algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- empty_exponent);
- EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key));
-
- // Fail with bad exponent: all zeros.
- std::vector<uint8> exponent_with_leading_zeros(15, 0x00);
- algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- exponent_with_leading_zeros);
- EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key));
-
- // Key generation success using exponent with leading zeros.
- exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
- public_exponent.begin(),
- public_exponent.end());
- algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- exponent_with_leading_zeros);
- EXPECT_EQ(Status::Success(),
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key));
- EXPECT_FALSE(public_key.isNull());
- EXPECT_FALSE(private_key.isNull());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
- EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
- EXPECT_TRUE(public_key.extractable());
- EXPECT_EQ(extractable, private_key.extractable());
- EXPECT_EQ(usage_mask, public_key.usages());
- EXPECT_EQ(usage_mask, private_key.usages());
-
- // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
- algorithm =
- CreateRsaHashedKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1,
- modulus_length,
- public_exponent);
- EXPECT_EQ(
- Status::Success(),
- GenerateKeyPair(algorithm, false, usage_mask, &public_key, &private_key));
- EXPECT_FALSE(public_key.isNull());
- EXPECT_FALSE(private_key.isNull());
- EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key.type());
- EXPECT_EQ(blink::WebCryptoKeyTypePrivate, private_key.type());
- EXPECT_EQ(modulus_length,
- public_key.algorithm().rsaHashedParams()->modulusLengthBits());
- EXPECT_EQ(modulus_length,
- private_key.algorithm().rsaHashedParams()->modulusLengthBits());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
- public_key.algorithm().rsaHashedParams()->hash().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
- private_key.algorithm().rsaHashedParams()->hash().id());
- // Even though "extractable" was set to false, the public key remains
- // extractable.
- EXPECT_TRUE(public_key.extractable());
- EXPECT_FALSE(private_key.extractable());
- EXPECT_EQ(usage_mask, public_key.usages());
- EXPECT_EQ(usage_mask, private_key.usages());
-
- // Exporting a private key as SPKI format doesn't make sense. However this
- // will first fail because the key is not extractable.
- std::vector<uint8> output;
- EXPECT_EQ(Status::ErrorKeyNotExtractable(),
- ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
-
- // Re-generate an extractable private_key and try to export it as SPKI format.
- // This should fail since spki is for public keys.
- EXPECT_EQ(
- Status::Success(),
- GenerateKeyPair(algorithm, true, usage_mask, &public_key, &private_key));
- EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
- ExportKey(blink::WebCryptoKeyFormatSpki, private_key, &output));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyPairRsaBadModulusLength)) {
- const unsigned int kBadModulus[] = {
- 0,
- 255, // Not a multiple of 8.
- 1023, // Not a multiple of 8.
- 0xFFFFFFFF, // Cannot fit in a signed int.
- 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
- };
-
- const std::vector<uint8> public_exponent = HexStringToBytes("010001");
-
- for (size_t i = 0; i < arraysize(kBadModulus); ++i) {
- const unsigned int modulus_length = kBadModulus[i];
- blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- public_exponent);
- bool extractable = true;
- const blink::WebCryptoKeyUsageMask usage_mask = 0;
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- EXPECT_FALSE(
- GenerateKeyPair(
- algorithm, extractable, usage_mask, &public_key, &private_key)
- .IsSuccess());
- }
-}
-
-// Try generating RSA key pairs using unsupported public exponents. Only
-// exponents of 3 and 65537 are supported. While both OpenSSL and NSS can
-// support other values, OpenSSL hangs when given invalid exponents, so use a
-// whitelist to validate the parameters.
-TEST_F(SharedCryptoTest, MAYBE(GenerateKeyPairRsaBadExponent)) {
- const unsigned int modulus_length = 1024;
-
- const char* const kPublicExponents[] = {
- "11", // 17 - This is a valid public exponent, but currently disallowed.
- "00",
- "01",
- "02",
- "010000", // 65536
- };
-
- for (size_t i = 0; i < arraysize(kPublicExponents); ++i) {
- SCOPED_TRACE(i);
- blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- HexStringToBytes(kPublicExponents[i]));
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
- GenerateKeyPair(
- algorithm, true, 0, &public_key, &private_key));
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(RsaSsaSignVerifyFailures)) {
- if (!SupportsRsaKeyImport())
- return;
-
- // Import a key pair.
- blink::WebCryptoAlgorithm import_algorithm =
- CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1);
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
- ASSERT_NO_FATAL_FAILURE(
- ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
- HexStringToBytes(kPrivateKeyPkcs8DerHex),
- import_algorithm,
- false,
- blink::WebCryptoKeyUsageVerify,
- blink::WebCryptoKeyUsageSign,
- &public_key,
- &private_key));
-
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
-
- std::vector<uint8> signature;
- bool signature_match;
-
- // Compute a signature.
- const std::vector<uint8> data = HexStringToBytes("010203040506070809");
- ASSERT_EQ(Status::Success(),
- Sign(algorithm, private_key, CryptoData(data), &signature));
-
- // Ensure truncated signature does not verify by passing one less byte.
- EXPECT_EQ(Status::Success(),
- VerifySignature(
- algorithm,
- public_key,
- CryptoData(Uint8VectorStart(signature), signature.size() - 1),
- CryptoData(data),
- &signature_match));
- EXPECT_FALSE(signature_match);
-
- // Ensure truncated signature does not verify by passing no bytes.
- EXPECT_EQ(Status::Success(),
- VerifySignature(algorithm,
- public_key,
- CryptoData(),
- CryptoData(data),
- &signature_match));
- EXPECT_FALSE(signature_match);
-
- // Ensure corrupted signature does not verify.
- std::vector<uint8> corrupt_sig = signature;
- corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
- EXPECT_EQ(Status::Success(),
- VerifySignature(algorithm,
- public_key,
- CryptoData(corrupt_sig),
- CryptoData(data),
- &signature_match));
- EXPECT_FALSE(signature_match);
-
- // Ensure signatures that are greater than the modulus size fail.
- const unsigned int long_message_size_bytes = 1024;
- DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
- const unsigned char kLongSignature[long_message_size_bytes] = {0};
- EXPECT_EQ(Status::Success(),
- VerifySignature(algorithm,
- public_key,
- CryptoData(kLongSignature, sizeof(kLongSignature)),
- CryptoData(data),
- &signature_match));
- EXPECT_FALSE(signature_match);
-
- // Ensure that signing and verifying with an incompatible algorithm fails.
- algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep);
-
- EXPECT_EQ(Status::ErrorUnexpected(),
- Sign(algorithm, private_key, CryptoData(data), &signature));
- EXPECT_EQ(Status::ErrorUnexpected(),
- VerifySignature(algorithm,
- public_key,
- CryptoData(signature),
- CryptoData(data),
- &signature_match));
-
- // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
- // based solely on the contents of the input signature data. In the Web Crypto
- // implementation, the inner hash should be specified uniquely by the key
- // algorithm parameter. To validate this behavior, call Verify with a computed
- // signature that used one hash type (SHA-1), but pass in a key with a
- // different inner hash type (SHA-256). If the hash type is determined by the
- // signature itself (undesired), the verify will pass, while if the hash type
- // is specified by the key algorithm (desired), the verify will fail.
-
- // Compute a signature using SHA-1 as the inner hash.
- EXPECT_EQ(Status::Success(),
- Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
- private_key,
- CryptoData(data),
- &signature));
-
- blink::WebCryptoKey public_key_256 = blink::WebCryptoKey::createNull();
- EXPECT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- blink::WebCryptoKeyUsageVerify,
- &public_key_256));
-
- // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
- // signature should not verify.
- // NOTE: public_key was produced by generateKey, and so its associated
- // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
- // it has no inner hash to conflict with the input algorithm.
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha1,
- private_key.algorithm().rsaHashedParams()->hash().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
- public_key_256.algorithm().rsaHashedParams()->hash().id());
-
- bool is_match;
- EXPECT_EQ(Status::Success(),
- VerifySignature(
- CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
- public_key_256,
- CryptoData(signature),
- CryptoData(data),
- &is_match));
- EXPECT_FALSE(is_match);
-}
-
-TEST_F(SharedCryptoTest, MAYBE(RsaSignVerifyKnownAnswer)) {
- if (!SupportsRsaKeyImport())
- return;
-
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("pkcs1v15_sign.json", &tests));
-
- // Import the key pair.
- blink::WebCryptoAlgorithm import_algorithm =
- CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha1);
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
- ASSERT_NO_FATAL_FAILURE(
- ImportRsaKeyPair(HexStringToBytes(kPublicKeySpkiDerHex),
- HexStringToBytes(kPrivateKeyPkcs8DerHex),
- import_algorithm,
- false,
- blink::WebCryptoKeyUsageVerify,
- blink::WebCryptoKeyUsageSign,
- &public_key,
- &private_key));
-
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
-
- // Validate the signatures are computed and verified as expected.
- std::vector<uint8> signature;
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
-
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- std::vector<uint8> test_message =
- GetBytesFromHexString(test, "message_hex");
- std::vector<uint8> test_signature =
- GetBytesFromHexString(test, "signature_hex");
-
- signature.clear();
- ASSERT_EQ(
- Status::Success(),
- Sign(algorithm, private_key, CryptoData(test_message), &signature));
- EXPECT_BYTES_EQ(test_signature, signature);
-
- bool is_match = false;
- ASSERT_EQ(Status::Success(),
- VerifySignature(algorithm,
- public_key,
- CryptoData(test_signature),
- CryptoData(test_message),
- &is_match));
- EXPECT_TRUE(is_match);
- }
-}
-
-TEST_F(SharedCryptoTest, MAYBE(AesKwKeyImport)) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- // Import a 128-bit Key Encryption Key (KEK)
- std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes(key_raw_hex_in)),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
- std::vector<uint8> key_raw_out;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
- EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
-
- // Import a 192-bit KEK
- key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
- ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes(key_raw_hex_in)),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
-
- // Import a 256-bit Key Encryption Key (KEK)
- key_raw_hex_in =
- "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes(key_raw_hex_in)),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
- EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
-
- // Fail import of 0 length key
- EXPECT_EQ(Status::ErrorImportAesKeyLength(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes("")),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
-
- // Fail import of 124-bit KEK
- key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb";
- EXPECT_EQ(Status::ErrorImportAesKeyLength(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes(key_raw_hex_in)),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
-
- // Fail import of 200-bit KEK
- key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
- EXPECT_EQ(Status::ErrorImportAesKeyLength(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes(key_raw_hex_in)),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
-
- // Fail import of 260-bit KEK
- key_raw_hex_in =
- "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
- EXPECT_EQ(Status::ErrorImportAesKeyLength(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(HexStringToBytes(key_raw_hex_in)),
- algorithm,
- true,
- blink::WebCryptoKeyUsageWrapKey,
- &key));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(UnwrapFailures)) {
- // This test exercises the code path common to all unwrap operations.
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(0, &test));
- const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
- const std::vector<uint8> test_ciphertext =
- GetBytesFromHexString(test, "ciphertext");
-
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
-
- // Using a wrapping algorithm that does not match the wrapping key algorithm
- // should fail.
- blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
- test_kek,
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
- blink::WebCryptoKeyUsageUnwrapKey);
- EXPECT_EQ(
- Status::ErrorUnexpected(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(test_ciphertext),
- wrapping_key,
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
-
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
- const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
- const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
- const std::vector<uint8> test_ciphertext =
- GetBytesFromHexString(test, "ciphertext");
- const blink::WebCryptoAlgorithm wrapping_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
- test_kek,
- wrapping_algorithm,
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
-
- // Import the key to be wrapped.
- blink::WebCryptoKey key = ImportSecretKeyFromRaw(
- test_key,
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
- blink::WebCryptoKeyUsageSign);
-
- // Wrap the key and verify the ciphertext result against the known answer.
- std::vector<uint8> wrapped_key;
- ASSERT_EQ(Status::Success(),
- WrapKey(blink::WebCryptoKeyFormatRaw,
- key,
- wrapping_key,
- wrapping_algorithm,
- &wrapped_key));
- EXPECT_BYTES_EQ(test_ciphertext, wrapped_key);
-
- // Unwrap the known ciphertext to get a new test_key.
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(
- Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(test_ciphertext),
- wrapping_key,
- wrapping_algorithm,
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageSign,
- &unwrapped_key));
- EXPECT_FALSE(key.isNull());
- EXPECT_TRUE(key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
- EXPECT_EQ(true, key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
-
- // Export the new key and compare its raw bytes with the original known key.
- std::vector<uint8> raw_key;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
- EXPECT_BYTES_EQ(test_key, raw_key);
- }
-}
-
-// Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the
-// unwrapped key
-TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyUnwrapSignVerifyHmac)) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
-
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(0, &test));
- const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
- const std::vector<uint8> test_ciphertext =
- GetBytesFromHexString(test, "ciphertext");
- const blink::WebCryptoAlgorithm wrapping_algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
- test_kek, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
-
- // Unwrap the known ciphertext.
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(
- Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(test_ciphertext),
- wrapping_key,
- wrapping_algorithm,
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
- false,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- &key));
-
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
- EXPECT_FALSE(key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- key.usages());
-
- // Sign an empty message and ensure it is verified.
- std::vector<uint8> test_message;
- std::vector<uint8> signature;
-
- ASSERT_EQ(Status::Success(),
- Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
- key,
- CryptoData(test_message),
- &signature));
-
- EXPECT_GT(signature.size(), 0u);
-
- bool verify_result;
- ASSERT_EQ(Status::Success(),
- VerifySignature(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
- key,
- CryptoData(signature),
- CryptoData(test_message),
- &verify_result));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapErrors)) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
- base::DictionaryValue* test;
- // Use 256 bits of data with a 256-bit KEK
- ASSERT_TRUE(tests->GetDictionary(3, &test));
- const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
- const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
- const std::vector<uint8> test_ciphertext =
- GetBytesFromHexString(test, "ciphertext");
- const blink::WebCryptoAlgorithm wrapping_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
- const blink::WebCryptoAlgorithm key_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
- test_kek,
- wrapping_algorithm,
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
- // Import the key to be wrapped.
- blink::WebCryptoKey key = ImportSecretKeyFromRaw(
- test_key,
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- blink::WebCryptoKeyUsageEncrypt);
-
- // Unwrap with wrapped data too small must fail.
- const std::vector<uint8> small_data(test_ciphertext.begin(),
- test_ciphertext.begin() + 23);
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- EXPECT_EQ(Status::ErrorDataTooSmall(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(small_data),
- wrapping_key,
- wrapping_algorithm,
- key_algorithm,
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
-
- // Unwrap with wrapped data size not a multiple of 8 bytes must fail.
- const std::vector<uint8> unaligned_data(test_ciphertext.begin(),
- test_ciphertext.end() - 2);
- EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(unaligned_data),
- wrapping_key,
- wrapping_algorithm,
- key_algorithm,
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyUnwrapCorruptData)) {
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
- base::DictionaryValue* test;
- // Use 256 bits of data with a 256-bit KEK
- ASSERT_TRUE(tests->GetDictionary(3, &test));
- const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
- const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
- const std::vector<uint8> test_ciphertext =
- GetBytesFromHexString(test, "ciphertext");
- const blink::WebCryptoAlgorithm wrapping_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
- test_kek,
- wrapping_algorithm,
- blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
-
- // Unwrap of a corrupted version of the known ciphertext should fail, due to
- // AES-KW's built-in integrity check.
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- EXPECT_EQ(
- Status::OperationError(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(Corrupted(test_ciphertext)),
- wrapping_key,
- wrapping_algorithm,
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
-}
-
-TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapKnownData)) {
- // The following data lists a known HMAC SHA-256 key, then a JWK
- // representation of this key which was encrypted ("wrapped") using AES-KW and
- // the following wrapping key.
- // For reference, the intermediate clear JWK is
- // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
- // (Not shown is space padding to ensure the cleartext meets the size
- // requirements of the AES-KW algorithm.)
- const std::vector<uint8> key_data = HexStringToBytes(
- "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
- const std::vector<uint8> wrapped_key_data = HexStringToBytes(
- "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
- "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
- "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
- "97938C5CFE5B10B4254D0C399F39D0");
- const std::vector<uint8> wrapping_key_data =
- HexStringToBytes("000102030405060708090A0B0C0D0E0F");
- const blink::WebCryptoAlgorithm wrapping_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
- wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
-
- // Unwrap the known wrapped key data to produce a new key
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(
- Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatJwk,
- CryptoData(wrapped_key_data),
- wrapping_key,
- wrapping_algorithm,
- CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
- true,
- blink::WebCryptoKeyUsageVerify,
- &unwrapped_key));
-
- // Validate the new key's attributes.
- EXPECT_FALSE(unwrapped_key.isNull());
- EXPECT_TRUE(unwrapped_key.handle());
- EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id());
- EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
- unwrapped_key.algorithm().hmacParams()->hash().id());
- EXPECT_EQ(256u, unwrapped_key.algorithm().hmacParams()->lengthBits());
- EXPECT_EQ(true, unwrapped_key.extractable());
- EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages());
-
- // Export the new key's raw data and compare to the known original.
- std::vector<uint8> raw_key;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
- EXPECT_BYTES_EQ(key_data, raw_key);
-}
-
-// TODO(eroman):
-// * Test decryption when the tag length exceeds input size
-// * Test decryption with empty input
-// * Test decryption with tag length of 0.
-TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) {
- // Some Linux test runners may not have a new enough version of NSS.
- if (!SupportsAesGcm()) {
- LOG(WARNING) << "AES GCM not supported, skipping tests";
- return;
- }
-
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("aes_gcm.json", &tests));
-
- // Note that WebCrypto appends the authentication tag to the ciphertext.
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
- base::DictionaryValue* test;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- const std::vector<uint8> test_key = GetBytesFromHexString(test, "key");
- const std::vector<uint8> test_iv = GetBytesFromHexString(test, "iv");
- const std::vector<uint8> test_additional_data =
- GetBytesFromHexString(test, "additional_data");
- const std::vector<uint8> test_plain_text =
- GetBytesFromHexString(test, "plain_text");
- const std::vector<uint8> test_authentication_tag =
- GetBytesFromHexString(test, "authentication_tag");
- const unsigned int test_tag_size_bits = test_authentication_tag.size() * 8;
- const std::vector<uint8> test_cipher_text =
- GetBytesFromHexString(test, "cipher_text");
-
- blink::WebCryptoKey key = ImportSecretKeyFromRaw(
- test_key,
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesGcm),
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
-
- // Verify exported raw key is identical to the imported data
- std::vector<uint8> raw_key;
- EXPECT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
-
- EXPECT_BYTES_EQ(test_key, raw_key);
-
- // Test encryption.
- std::vector<uint8> cipher_text;
- std::vector<uint8> authentication_tag;
- EXPECT_EQ(Status::Success(),
- AesGcmEncrypt(key,
- test_iv,
- test_additional_data,
- test_tag_size_bits,
- test_plain_text,
- &cipher_text,
- &authentication_tag));
-
- EXPECT_BYTES_EQ(test_cipher_text, cipher_text);
- EXPECT_BYTES_EQ(test_authentication_tag, authentication_tag);
-
- // Test decryption.
- std::vector<uint8> plain_text;
- EXPECT_EQ(Status::Success(),
- AesGcmDecrypt(key,
- test_iv,
- test_additional_data,
- test_tag_size_bits,
- test_cipher_text,
- test_authentication_tag,
- &plain_text));
- EXPECT_BYTES_EQ(test_plain_text, plain_text);
-
- // Decryption should fail if any of the inputs are tampered with.
- EXPECT_EQ(Status::OperationError(),
- AesGcmDecrypt(key,
- Corrupted(test_iv),
- test_additional_data,
- test_tag_size_bits,
- test_cipher_text,
- test_authentication_tag,
- &plain_text));
- EXPECT_EQ(Status::OperationError(),
- AesGcmDecrypt(key,
- test_iv,
- Corrupted(test_additional_data),
- test_tag_size_bits,
- test_cipher_text,
- test_authentication_tag,
- &plain_text));
- EXPECT_EQ(Status::OperationError(),
- AesGcmDecrypt(key,
- test_iv,
- test_additional_data,
- test_tag_size_bits,
- Corrupted(test_cipher_text),
- test_authentication_tag,
- &plain_text));
- EXPECT_EQ(Status::OperationError(),
- AesGcmDecrypt(key,
- test_iv,
- test_additional_data,
- test_tag_size_bits,
- test_cipher_text,
- Corrupted(test_authentication_tag),
- &plain_text));
-
- // Try different incorrect tag lengths
- uint8 kAlternateTagLengths[] = {0, 8, 96, 120, 128, 160, 255};
- for (size_t tag_i = 0; tag_i < arraysize(kAlternateTagLengths); ++tag_i) {
- unsigned int wrong_tag_size_bits = kAlternateTagLengths[tag_i];
- if (test_tag_size_bits == wrong_tag_size_bits)
- continue;
- EXPECT_NE(Status::Success(),
- AesGcmDecrypt(key,
- test_iv,
- test_additional_data,
- wrong_tag_size_bits,
- test_cipher_text,
- test_authentication_tag,
- &plain_text));
- }
- }
-}
-
-// AES 192-bit is not allowed: http://crbug.com/381829
-TEST_F(SharedCryptoTest, MAYBE(ImportAesCbc192Raw)) {
- std::vector<uint8> key_raw(24, 0);
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- Status status = ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(key_raw),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &key);
- ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
-}
-
-// AES 192-bit is not allowed: http://crbug.com/381829
-TEST_F(SharedCryptoTest, MAYBE(ImportAesCbc192Jwk)) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- base::DictionaryValue dict;
- dict.SetString("kty", "oct");
- dict.SetString("alg", "A192CBC");
- dict.SetString("k", "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh");
-
- EXPECT_EQ(
- Status::ErrorAes192BitUnsupported(),
- ImportKeyJwkFromDict(dict,
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- false,
- blink::WebCryptoKeyUsageEncrypt,
- &key));
-}
-
-// AES 192-bit is not allowed: http://crbug.com/381829
-TEST_F(SharedCryptoTest, MAYBE(GenerateAesCbc192)) {
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- Status status = GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(192),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &key);
- ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
-}
-
-// AES 192-bit is not allowed: http://crbug.com/381829
-TEST_F(SharedCryptoTest, MAYBE(UnwrapAesCbc192)) {
- std::vector<uint8> wrapping_key_data(16, 0);
- std::vector<uint8> wrapped_key = HexStringToBytes(
- "1A07ACAB6C906E50883173C29441DB1DE91D34F45C435B5F99C822867FB3956F");
-
- blink::WebCryptoKey wrapping_key =
- ImportSecretKeyFromRaw(wrapping_key_data,
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
- blink::WebCryptoKeyUsageUnwrapKey);
-
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(wrapped_key),
- wrapping_key,
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
-}
-
-class SharedCryptoRsaOaepTest : public ::testing::Test {
- public:
- SharedCryptoRsaOaepTest() { Init(); }
-
- scoped_ptr<base::DictionaryValue> CreatePublicKeyJwkDict() {
- scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue());
- jwk->SetString("kty", "RSA");
- jwk->SetString("n",
- Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyModulusHex)));
- jwk->SetString(
- "e", Base64EncodeUrlSafe(HexStringToBytes(kPublicKeyExponentHex)));
- return jwk.Pass();
- }
-};
-
-// Import a PKCS#8 private key that uses RSAPrivateKey with the
-// id-rsaEncryption OID.
-TEST_F(SharedCryptoRsaOaepTest, ImportPkcs8WithRsaEncryption) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageDecrypt,
- &private_key));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithNoAlg) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKeyJwkFromDict(*jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMatchingAlg) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
- jwk->SetString("alg", "RSA-OAEP");
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKeyJwkFromDict(*jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMismatchedAlgFails) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
- jwk->SetString("alg", "RSA-OAEP-512");
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorJwkAlgorithmInconsistent(),
- ImportKeyJwkFromDict(*jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, ImportPublicJwkWithMismatchedTypeFails) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
- jwk->SetString("kty", "oct");
- jwk->SetString("alg", "RSA-OAEP");
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorJwkPropertyMissing("k"),
- ImportKeyJwkFromDict(*jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, ExportPublicJwk) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- struct TestData {
- blink::WebCryptoAlgorithmId hash_alg;
- const char* expected_jwk_alg;
- } kTestData[] = {{blink::WebCryptoAlgorithmIdSha1, "RSA-OAEP"},
- {blink::WebCryptoAlgorithmIdSha256, "RSA-OAEP-256"},
- {blink::WebCryptoAlgorithmIdSha384, "RSA-OAEP-384"},
- {blink::WebCryptoAlgorithmIdSha512, "RSA-OAEP-512"}};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) {
- const TestData& test_data = kTestData[i];
- SCOPED_TRACE(test_data.expected_jwk_alg);
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
- jwk->SetString("alg", test_data.expected_jwk_alg);
-
- // Import the key in a known-good format
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKeyJwkFromDict(
- *jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep, test_data.hash_alg),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-
- // Now export the key as JWK and verify its contents
- std::vector<uint8> jwk_data;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk_data));
- EXPECT_TRUE(VerifyPublicJwk(jwk_data,
- test_data.expected_jwk_alg,
- kPublicKeyModulusHex,
- kPublicKeyExponentHex,
- blink::WebCryptoKeyUsageEncrypt));
- }
-}
-
-TEST_F(SharedCryptoRsaOaepTest, EncryptDecryptKnownAnswerTest) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- scoped_ptr<base::ListValue> tests;
- ASSERT_TRUE(ReadJsonTestFileToList("rsa_oaep.json", &tests));
-
- for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
- SCOPED_TRACE(test_index);
-
- base::DictionaryValue* test = NULL;
- ASSERT_TRUE(tests->GetDictionary(test_index, &test));
-
- blink::WebCryptoAlgorithm digest_algorithm =
- GetDigestAlgorithm(test, "hash");
- ASSERT_FALSE(digest_algorithm.isNull());
- std::vector<uint8> public_key_der =
- GetBytesFromHexString(test, "public_key");
- std::vector<uint8> private_key_der =
- GetBytesFromHexString(test, "private_key");
- std::vector<uint8> ciphertext = GetBytesFromHexString(test, "ciphertext");
- std::vector<uint8> plaintext = GetBytesFromHexString(test, "plaintext");
- std::vector<uint8> label = GetBytesFromHexString(test, "label");
-
- blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep, digest_algorithm.id());
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(public_key_der,
- private_key_der,
- import_algorithm,
- false,
- blink::WebCryptoKeyUsageEncrypt,
- blink::WebCryptoKeyUsageDecrypt,
- &public_key,
- &private_key));
-
- blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
- std::vector<uint8> decrypted_data;
- ASSERT_EQ(Status::Success(),
- Decrypt(op_algorithm,
- private_key,
- CryptoData(ciphertext),
- &decrypted_data));
- EXPECT_BYTES_EQ(plaintext, decrypted_data);
- std::vector<uint8> encrypted_data;
- ASSERT_EQ(
- Status::Success(),
- Encrypt(
- op_algorithm, public_key, CryptoData(plaintext), &encrypted_data));
- std::vector<uint8> redecrypted_data;
- ASSERT_EQ(Status::Success(),
- Decrypt(op_algorithm,
- private_key,
- CryptoData(encrypted_data),
- &redecrypted_data));
- EXPECT_BYTES_EQ(plaintext, redecrypted_data);
- }
-}
-
-TEST_F(SharedCryptoRsaOaepTest, EncryptWithLargeMessageFails) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha1;
- const size_t kHashSize = 20;
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKeyJwkFromDict(*jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep, kHash),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-
- // The maximum size of an encrypted message is:
- // modulus length
- // - 1 (leading octet)
- // - hash size (maskedSeed)
- // - hash size (lHash portion of maskedDB)
- // - 1 (at least one octet for the padding string)
- size_t kMaxMessageSize = (kModulusLengthBits / 8) - 2 - (2 * kHashSize);
-
- // The label has no influence on the maximum message size. For simplicity,
- // use the empty string.
- std::vector<uint8> label;
- blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
-
- // Test that a message just before the boundary succeeds.
- std::string large_message;
- large_message.resize(kMaxMessageSize - 1, 'A');
-
- std::vector<uint8> ciphertext;
- ASSERT_EQ(
- Status::Success(),
- Encrypt(
- op_algorithm, public_key, CryptoData(large_message), &ciphertext));
-
- // Test that a message at the boundary succeeds.
- large_message.resize(kMaxMessageSize, 'A');
- ciphertext.clear();
-
- ASSERT_EQ(
- Status::Success(),
- Encrypt(
- op_algorithm, public_key, CryptoData(large_message), &ciphertext));
-
- // Test that a message greater than the largest size fails.
- large_message.resize(kMaxMessageSize + 1, 'A');
- ciphertext.clear();
-
- ASSERT_EQ(
- Status::OperationError(),
- Encrypt(
- op_algorithm, public_key, CryptoData(large_message), &ciphertext));
-}
-
-// Ensures that if the selected hash algorithm for the RSA-OAEP message is too
-// large, then it is rejected, independent of the actual message to be
-// encrypted.
-// For example, a 1024-bit RSA key is too small to accomodate a message that
-// uses OAEP with SHA-512, since it requires 1040 bits to encode
-// (2 * hash size + 2 padding bytes).
-TEST_F(SharedCryptoRsaOaepTest, EncryptWithLargeDigestFails) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- const blink::WebCryptoAlgorithmId kHash = blink::WebCryptoAlgorithmIdSha512;
-
- scoped_ptr<base::DictionaryValue> jwk(CreatePublicKeyJwkDict());
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKeyJwkFromDict(*jwk.get(),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep, kHash),
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &public_key));
-
- // The label has no influence on the maximum message size. For simplicity,
- // use the empty string.
- std::vector<uint8> label;
- blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
-
- std::string small_message("A");
- std::vector<uint8> ciphertext;
- // This is an operation error, as the internal consistency checking of the
- // algorithm parameters is up to the implementation.
- ASSERT_EQ(
- Status::OperationError(),
- Encrypt(
- op_algorithm, public_key, CryptoData(small_message), &ciphertext));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, DecryptWithLargeMessageFails) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)),
- CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep,
- blink::WebCryptoAlgorithmIdSha1),
- true,
- blink::WebCryptoKeyUsageDecrypt,
- &private_key));
-
- // The label has no influence on the maximum message size. For simplicity,
- // use the empty string.
- std::vector<uint8> label;
- blink::WebCryptoAlgorithm op_algorithm = CreateRsaOaepAlgorithm(label);
-
- std::string large_dummy_message(kModulusLengthBits / 8, 'A');
- std::vector<uint8> plaintext;
-
- ASSERT_EQ(Status::OperationError(),
- Decrypt(op_algorithm,
- private_key,
- CryptoData(large_dummy_message),
- &plaintext));
-}
-
-TEST_F(SharedCryptoRsaOaepTest, WrapUnwrapRawKey) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
- HexStringToBytes(kPublicKeySpkiDerHex),
- HexStringToBytes(kPrivateKeyPkcs8DerHex),
- import_algorithm,
- false,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
- blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
- &public_key,
- &private_key));
-
- std::vector<uint8> label;
- blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
-
- const std::string key_hex = "000102030405060708090A0B0C0D0E0F";
- const blink::WebCryptoAlgorithm key_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
-
- blink::WebCryptoKey key =
- ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
- key_algorithm,
- blink::WebCryptoKeyUsageEncrypt);
- ASSERT_FALSE(key.isNull());
-
- std::vector<uint8> wrapped_key;
- ASSERT_EQ(Status::Success(),
- WrapKey(blink::WebCryptoKeyFormatRaw,
- key,
- public_key,
- wrapping_algorithm,
- &wrapped_key));
-
- // Verify that |wrapped_key| can be decrypted and yields the key data.
- // Because |private_key| supports both decrypt and unwrap, this is valid.
- std::vector<uint8> decrypted_key;
- ASSERT_EQ(Status::Success(),
- Decrypt(wrapping_algorithm,
- private_key,
- CryptoData(wrapped_key),
- &decrypted_key));
- EXPECT_BYTES_EQ_HEX(key_hex, decrypted_key);
-
- // Now attempt to unwrap the key, which should also decrypt the data.
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(wrapped_key),
- private_key,
- wrapping_algorithm,
- key_algorithm,
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
- ASSERT_FALSE(unwrapped_key.isNull());
-
- std::vector<uint8> raw_key;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
- EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
-}
-
-TEST_F(SharedCryptoRsaOaepTest, WrapUnwrapJwkSymKey) {
- if (!SupportsRsaOaep()) {
- LOG(WARNING) << "RSA-OAEP support not present; skipping.";
- return;
- }
-
- // The public and private portions of a 2048-bit RSA key with the
- // id-rsaEncryption OID
- const char kPublicKey2048SpkiDerHex[] =
- "30820122300d06092a864886f70d01010105000382010f003082010a0282010100c5d8ce"
- "137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b300c6a6c9764"
- "f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448e7183a3a68"
- "e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872458d1b1e2f"
- "7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34ba17bc5d08"
- "a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea9893652d02fc606"
- "36f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d733711c89ca"
- "749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b557c16615d"
- "5d0203010001";
- const char kPrivateKey2048Pkcs8DerHex[] =
- "308204bd020100300d06092a864886f70d0101010500048204a7308204a3020100028201"
- "0100c5d8ce137a38168c8ab70229cfa5accc640567159750a312ce2e7d54b6e2fdd59b30"
- "0c6a6c9764f8de6f00519cdb90111453d273a967462786480621f9e7cee5b73d63358448"
- "e7183a3a68e991186359f26aa88fbca5f53e673e502e4c5a2ba5068aeba60c9d0c44d872"
- "458d1b1e2f7f339f986076d516e93dc750f0b7680b6f5f02bc0d5590495be04c4ae59d34"
- "ba17bc5d08a93c75cfda2828f4a55b153af912038438276cb4a14f8116ca94db0ea98936"
- "52d02fc60636f19975e3d79a4d8ea8bfed6f8e0a24b63d243b08ea70a086ad56dd6341d7"
- "33711c89ca749d4a80b3e6ecd2f8e53731eadeac2ea77788ee55d7b4b47c0f2523fbd61b"
- "557c16615d5d02030100010282010074b70feb41a0b0fcbc207670400556c9450042ede3"
- "d4383fb1ce8f3558a6d4641d26dd4c333fa4db842d2b9cf9d2354d3e16ad027a9f682d8c"
- "f4145a1ad97b9edcd8a41c402bd9d8db10f62f43df854cdccbbb2100834f083f53ed6d42"
- "b1b729a59072b004a4e945fc027db15e9c121d1251464d320d4774d5732df6b3dbf751f4"
- "9b19c9db201e19989c883bbaad5333db47f64f6f7a95b8d4936b10d945aa3f794cfaab62"
- "e7d47686129358914f3b8085f03698a650ab5b8c7e45813f2b0515ec05b6e5195b6a7c2a"
- "0d36969745f431ded4fd059f6aa361a4649541016d356297362b778e90f077d48815b339"
- "ec6f43aba345df93e67fcb6c2cb5b4544e9be902818100e9c90abe5f9f32468c5b6d630c"
- "54a4d7d75e29a72cf792f21e242aac78fd7995c42dfd4ae871d2619ff7096cb05baa78e3"
- "23ecab338401a8059adf7a0d8be3b21edc9a9c82c5605634a2ec81ec053271721351868a"
- "4c2e50c689d7cef94e31ff23658af5843366e2b289c5bf81d72756a7b93487dd8770d69c"
- "1f4e089d6d89f302818100d8a58a727c4e209132afd9933b98c89aca862a01cc0be74133"
- "bee517909e5c379e526895ac4af11780c1fe91194c777c9670b6423f0f5a32fd7691a622"
- "113eef4bed2ef863363a335fd55b0e75088c582437237d7f3ed3f0a643950237bc6e6277"
- "ccd0d0a1b4170aa1047aa7ffa7c8c54be10e8c7327ae2e0885663963817f6f02818100e5"
- "aed9ba4d71b7502e6748a1ce247ecb7bd10c352d6d9256031cdf3c11a65e44b0b7ca2945"
- "134671195af84c6b3bb3d10ebf65ae916f38bd5dbc59a0ad1c69b8beaf57cb3a8335f19b"
- "c7117b576987b48331cd9fd3d1a293436b7bb5e1a35c6560de4b5688ea834367cb0997eb"
- "b578f59ed4cb724c47dba94d3b484c1876dcd70281807f15bc7d2406007cac2b138a96af"
- "2d1e00276b84da593132c253fcb73212732dfd25824c2a615bc3d9b7f2c8d2fa542d3562"
- "b0c7738e61eeff580a6056239fb367ea9e5efe73d4f846033602e90c36a78db6fa8ea792"
- "0769675ec58e237bd994d189c8045a96f5dd3a4f12547257ce224e3c9af830a4da3c0eab"
- "9227a0035ae9028180067caea877e0b23090fc689322b71fbcce63d6596e66ab5fcdbaa0"
- "0d49e93aba8effb4518c2da637f209028401a68f344865b4956b032c69acde51d29177ca"
- "3db99fdbf5e74848ed4fa7bdfc2ebb60e2aaa5354770a763e1399ab7a2099762d525fea0"
- "37f3e1972c45a477e66db95c9609bb27f862700ef93379930786cf751b";
- blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaOaep, blink::WebCryptoAlgorithmIdSha1);
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
- HexStringToBytes(kPublicKey2048SpkiDerHex),
- HexStringToBytes(kPrivateKey2048Pkcs8DerHex),
- import_algorithm,
- false,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey,
- blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey,
- &public_key,
- &private_key));
-
- std::vector<uint8> label;
- blink::WebCryptoAlgorithm wrapping_algorithm = CreateRsaOaepAlgorithm(label);
-
- const std::string key_hex = "000102030405060708090a0b0c0d0e0f";
- const blink::WebCryptoAlgorithm key_algorithm =
- webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
-
- blink::WebCryptoKey key =
- ImportSecretKeyFromRaw(HexStringToBytes(key_hex),
- key_algorithm,
- blink::WebCryptoKeyUsageEncrypt);
- ASSERT_FALSE(key.isNull());
-
- std::vector<uint8> wrapped_key;
- ASSERT_EQ(Status::Success(),
- WrapKey(blink::WebCryptoKeyFormatJwk,
- key,
- public_key,
- wrapping_algorithm,
- &wrapped_key));
-
- // Verify that |wrapped_key| can be decrypted and yields a valid JWK object.
- // Because |private_key| supports both decrypt and unwrap, this is valid.
- std::vector<uint8> decrypted_jwk;
- ASSERT_EQ(Status::Success(),
- Decrypt(wrapping_algorithm,
- private_key,
- CryptoData(wrapped_key),
- &decrypted_jwk));
- EXPECT_TRUE(VerifySecretJwk(
- decrypted_jwk, "A128CBC", key_hex, blink::WebCryptoKeyUsageEncrypt));
-
- // Now attempt to unwrap the key, which should also decrypt the data.
- blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatJwk,
- CryptoData(wrapped_key),
- private_key,
- wrapping_algorithm,
- key_algorithm,
- true,
- blink::WebCryptoKeyUsageEncrypt,
- &unwrapped_key));
- ASSERT_FALSE(unwrapped_key.isNull());
-
- std::vector<uint8> raw_key;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
- EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
-}
-
-// Try importing an RSA-SSA public key with unsupported key usages using SPKI
-// format. RSA-SSA public keys only support the 'verify' usage.
-TEST_F(SharedCryptoTest, MAYBE(ImportRsaSsaPublicKeyBadUsage_SPKI)) {
- const blink::WebCryptoAlgorithm algorithm =
- CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256);
-
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageSign,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- blink::WebCryptoKeyUsageEncrypt,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
- };
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- ImportKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
- algorithm,
- false,
- bad_usages[i],
- &public_key));
- }
-}
-
-// Try importing an RSA-SSA public key with unsupported key usages using JWK
-// format. RSA-SSA public keys only support the 'verify' usage.
-TEST_F(SharedCryptoTest, MAYBE(ImportRsaSsaPublicKeyBadUsage_JWK)) {
- const blink::WebCryptoAlgorithm algorithm =
- CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256);
-
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageSign,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- blink::WebCryptoKeyUsageEncrypt,
- blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
- };
-
- base::DictionaryValue dict;
- RestoreJwkRsaDictionary(&dict);
- dict.Remove("use", NULL);
- dict.SetString("alg", "RS256");
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- ImportKeyJwkFromDict(
- dict, algorithm, false, bad_usages[i], &public_key));
- }
-}
-
-// Try importing an AES-CBC key with unsupported key usages using raw
-// format. AES-CBC keys support the following usages:
-// 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
-TEST_F(SharedCryptoTest, MAYBE(ImportAesCbcKeyBadUsage_Raw)) {
- const blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
-
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageSign,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageDecrypt,
- blink::WebCryptoKeyUsageDeriveBits,
- blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
- };
-
- std::vector<uint8> key_bytes(16);
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(key_bytes),
- algorithm,
- true,
- bad_usages[i],
- &key));
- }
-}
-
-// Try importing an AES-KW key with unsupported key usages using raw
-// format. AES-KW keys support the following usages:
-// 'wrapKey', 'unwrapKey'
-TEST_F(SharedCryptoTest, MAYBE(ImportAesKwKeyBadUsage_Raw)) {
- const blink::WebCryptoAlgorithm algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageEncrypt,
- blink::WebCryptoKeyUsageDecrypt,
- blink::WebCryptoKeyUsageSign,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageUnwrapKey,
- blink::WebCryptoKeyUsageDeriveBits,
- blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
- };
-
- std::vector<uint8> key_bytes(16);
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(key_bytes),
- algorithm,
- true,
- bad_usages[i],
- &key));
- }
-}
-
-// Try unwrapping an HMAC key with unsupported usages using JWK format and
-// AES-KW. HMAC keys support the following usages:
-// 'sign', 'verify'
-TEST_F(SharedCryptoTest, MAYBE(UnwrapHmacKeyBadUsage_JWK)) {
- const blink::WebCryptoAlgorithm unwrap_algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageEncrypt,
- blink::WebCryptoKeyUsageDecrypt,
- blink::WebCryptoKeyUsageWrapKey,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey,
- blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDeriveKey,
- };
-
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(std::vector<uint8>(16)),
- unwrap_algorithm,
- true,
- blink::WebCryptoKeyUsageUnwrapKey,
- &wrapping_key));
-
- // The JWK plain text is:
- // { "kty": "oct","alg": "HS256","k": "GADWrMRHwQfoNaXU5fZvTg=="}
- const char* kWrappedJwk =
- "0AA245F17064FFB2A7A094436A39BEBFC962C627303D1327EA750CE9F917688C2782A943"
- "7AE7586547AC490E8AE7D5B02D63868D5C3BB57D36C4C8C5BF3962ACEC6F42E767E5706"
- "4";
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- UnwrapKey(blink::WebCryptoKeyFormatJwk,
- CryptoData(HexStringToBytes(kWrappedJwk)),
- wrapping_key,
- unwrap_algorithm,
- webcrypto::CreateHmacImportAlgorithm(
- blink::WebCryptoAlgorithmIdSha256),
- true,
- bad_usages[i],
- &key));
- }
-}
-
-// Try unwrapping an RSA-SSA public key with unsupported usages using JWK format
-// and AES-KW. RSA-SSA public keys support the following usages:
-// 'verify'
-TEST_F(SharedCryptoTest, MAYBE(UnwrapRsaSsaPublicKeyBadUsage_JWK)) {
- const blink::WebCryptoAlgorithm unwrap_algorithm =
- CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
-
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageEncrypt,
- blink::WebCryptoKeyUsageSign,
- blink::WebCryptoKeyUsageDecrypt,
- blink::WebCryptoKeyUsageWrapKey,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey,
- };
-
- // Import the wrapping key.
- blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- ImportKey(blink::WebCryptoKeyFormatRaw,
- CryptoData(std::vector<uint8>(16)),
- unwrap_algorithm,
- true,
- blink::WebCryptoKeyUsageUnwrapKey,
- &wrapping_key));
-
- // The JWK plaintext is:
- // { "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"}
-
- const char* kWrappedJwk =
- "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152"
- "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D"
- "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D"
- "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B"
- "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2"
- "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B"
- "30F2EE83CEDFD51136852C8A5939B768";
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- UnwrapKey(blink::WebCryptoKeyFormatJwk,
- CryptoData(HexStringToBytes(kWrappedJwk)),
- wrapping_key,
- unwrap_algorithm,
- webcrypto::CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256),
- true,
- bad_usages[i],
- &key));
- }
-}
-
-// Generate an AES-CBC key with invalid usages. AES-CBC supports:
-// 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
-TEST_F(SharedCryptoTest, MAYBE(GenerateAesKeyBadUsages)) {
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageSign, blink::WebCryptoKeyUsageVerify,
- blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageVerify,
- };
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- GenerateSecretKey(
- CreateAesCbcKeyGenAlgorithm(128), true, bad_usages[i], &key));
- }
-}
-
-// Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
-// 'sign', 'verify'
-TEST_F(SharedCryptoTest, MAYBE(GenerateRsaSsaBadUsages)) {
- blink::WebCryptoKeyUsageMask bad_usages[] = {
- blink::WebCryptoKeyUsageDecrypt,
- blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDecrypt,
- blink::WebCryptoKeyUsageWrapKey,
- };
-
- const unsigned int modulus_length = 256;
- const std::vector<uint8> public_exponent = HexStringToBytes("010001");
-
- for (size_t i = 0; i < arraysize(bad_usages); ++i) {
- SCOPED_TRACE(i);
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
- GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- public_exponent),
- true,
- bad_usages[i],
- &public_key,
- &private_key));
- }
-}
-
-// Generate an RSA-SSA key pair. The public and private keys should select the
-// key usages which are applicable, and not have the exact same usages as was
-// specified to GenerateKey
-TEST_F(SharedCryptoTest, MAYBE(GenerateRsaSsaKeyPairIntersectUsages)) {
- const unsigned int modulus_length = 256;
- const std::vector<uint8> public_exponent = HexStringToBytes("010001");
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::Success(),
- GenerateKeyPair(
- CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- public_exponent),
- true,
- blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
- &public_key,
- &private_key));
-
- EXPECT_EQ(blink::WebCryptoKeyUsageVerify, public_key.usages());
- EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
-
- // Try again but this time without the Verify usages.
- ASSERT_EQ(Status::Success(),
- GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- public_exponent),
- true,
- blink::WebCryptoKeyUsageSign,
- &public_key,
- &private_key));
-
- EXPECT_EQ(0, public_key.usages());
- EXPECT_EQ(blink::WebCryptoKeyUsageSign, private_key.usages());
-}
-
-// Generate an AES-CBC key and an RSA key pair. Use the AES-CBC key to wrap the
-// key pair (using SPKI format for public key, PKCS8 format for private key).
-// Then unwrap the wrapped key pair and verify that the key data is the same.
-TEST_F(SharedCryptoTest, MAYBE(WrapUnwrapRoundtripSpkiPkcs8UsingAesCbc)) {
- if (!SupportsRsaKeyImport())
- return;
-
- // Generate the wrapping key.
- blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
- true,
- blink::WebCryptoKeyUsageWrapKey |
- blink::WebCryptoKeyUsageUnwrapKey,
- &wrapping_key));
-
- // Generate an RSA key pair to be wrapped.
- const unsigned int modulus_length = 256;
- const std::vector<uint8> public_exponent = HexStringToBytes("010001");
-
- blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
- blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
- ASSERT_EQ(Status::Success(),
- GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256,
- modulus_length,
- public_exponent),
- true,
- 0,
- &public_key,
- &private_key));
-
- // Export key pair as SPKI + PKCS8
- std::vector<uint8> public_key_spki;
- ASSERT_EQ(
- Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
-
- std::vector<uint8> private_key_pkcs8;
- ASSERT_EQ(
- Status::Success(),
- ExportKey(
- blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
-
- // Wrap the key pair.
- blink::WebCryptoAlgorithm wrap_algorithm =
- CreateAesCbcAlgorithm(std::vector<uint8>(16, 0));
-
- std::vector<uint8> wrapped_public_key;
- ASSERT_EQ(Status::Success(),
- WrapKey(blink::WebCryptoKeyFormatSpki,
- public_key,
- wrapping_key,
- wrap_algorithm,
- &wrapped_public_key));
-
- std::vector<uint8> wrapped_private_key;
- ASSERT_EQ(Status::Success(),
- WrapKey(blink::WebCryptoKeyFormatPkcs8,
- private_key,
- wrapping_key,
- wrap_algorithm,
- &wrapped_private_key));
-
- // Unwrap the key pair.
- blink::WebCryptoAlgorithm rsa_import_algorithm =
- CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- blink::WebCryptoAlgorithmIdSha256);
-
- blink::WebCryptoKey unwrapped_public_key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatSpki,
- CryptoData(wrapped_public_key),
- wrapping_key,
- wrap_algorithm,
- rsa_import_algorithm,
- true,
- 0,
- &unwrapped_public_key));
-
- blink::WebCryptoKey unwrapped_private_key = blink::WebCryptoKey::createNull();
-
- ASSERT_EQ(Status::Success(),
- UnwrapKey(blink::WebCryptoKeyFormatPkcs8,
- CryptoData(wrapped_private_key),
- wrapping_key,
- wrap_algorithm,
- rsa_import_algorithm,
- true,
- 0,
- &unwrapped_private_key));
-
- // Export unwrapped key pair as SPKI + PKCS8
- std::vector<uint8> unwrapped_public_key_spki;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatSpki,
- unwrapped_public_key,
- &unwrapped_public_key_spki));
-
- std::vector<uint8> unwrapped_private_key_pkcs8;
- ASSERT_EQ(Status::Success(),
- ExportKey(blink::WebCryptoKeyFormatPkcs8,
- unwrapped_private_key,
- &unwrapped_private_key_pkcs8));
-
- EXPECT_EQ(public_key_spki, unwrapped_public_key_spki);
- EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8);
-
- EXPECT_NE(public_key_spki, wrapped_public_key);
- EXPECT_NE(private_key_pkcs8, wrapped_private_key);
-}
-
-} // namespace webcrypto
-
-} // namespace content
diff --git a/chromium/content/child/webcrypto/status.cc b/chromium/content/child/webcrypto/status.cc
index fc01c2c290a..a7afdb3c063 100644
--- a/chromium/content/child/webcrypto/status.cc
+++ b/chromium/content/child/webcrypto/status.cc
@@ -58,11 +58,6 @@ Status Status::ErrorJwkExtInconsistent() {
"specified by the Web Crypto call");
}
-Status Status::ErrorJwkUnrecognizedAlgorithm() {
- return Status(blink::WebCryptoErrorTypeData,
- "The JWK \"alg\" property was not recognized");
-}
-
Status Status::ErrorJwkAlgorithmInconsistent() {
return Status(blink::WebCryptoErrorTypeData,
"The JWK \"alg\" property was inconsistent with that specified "
@@ -99,9 +94,9 @@ Status Status::ErrorJwkUseAndKeyopsInconsistent() {
"but are inconsistent with each other.");
}
-Status Status::ErrorJwkUnrecognizedKty() {
+Status Status::ErrorJwkUnexpectedKty(const std::string& expected) {
return Status(blink::WebCryptoErrorTypeData,
- "The JWK \"kty\" property was unrecognized");
+ "The JWK \"kty\" property was not \"" + expected + "\"");
}
Status Status::ErrorJwkIncorrectKeyLength() {
@@ -110,16 +105,37 @@ Status Status::ErrorJwkIncorrectKeyLength() {
"of key data for the given algorithm.");
}
-Status Status::ErrorJwkIncompleteOptionalRsaPrivateKey() {
+Status Status::ErrorJwkEmptyBigInteger(const std::string& property) {
+ return Status(blink::WebCryptoErrorTypeData,
+ "The JWK \"" + property + "\" property was empty.");
+}
+
+Status Status::ErrorJwkBigIntegerHasLeadingZero(const std::string& property) {
+ return Status(
+ blink::WebCryptoErrorTypeData,
+ "The JWK \"" + property + "\" property contained a leading zero.");
+}
+
+Status Status::ErrorJwkDuplicateKeyOps() {
return Status(blink::WebCryptoErrorTypeData,
- "The optional JWK properties p, q, dp, dq, qi must either all "
- "be provided, or none provided");
+ "The \"key_ops\" property of the JWK dictionary contains "
+ "duplicate usages.");
}
Status Status::ErrorImportEmptyKeyData() {
return Status(blink::WebCryptoErrorTypeData, "No key data was provided");
}
+Status Status::ErrorUnsupportedImportKeyFormat() {
+ return Status(blink::WebCryptoErrorTypeNotSupported,
+ "Unsupported import key format for algorithm");
+}
+
+Status Status::ErrorUnsupportedExportKeyFormat() {
+ return Status(blink::WebCryptoErrorTypeNotSupported,
+ "Unsupported export key format for algorithm");
+}
+
Status Status::ErrorImportAesKeyLength() {
return Status(blink::WebCryptoErrorTypeData,
"AES key data must be 128, 192 or 256 bits");
@@ -140,6 +156,21 @@ Status Status::ErrorIncorrectSizeAesCbcIv() {
"The \"iv\" has an unexpected length -- must be 16 bytes");
}
+Status Status::ErrorIncorrectSizeAesCtrCounter() {
+ return Status(blink::WebCryptoErrorTypeData,
+ "The \"counter\" has an unexpected length -- must be 16 bytes");
+}
+
+Status Status::ErrorInvalidAesCtrCounterLength() {
+ return Status(blink::WebCryptoErrorTypeData,
+ "The \"length\" property must be >= 1 and <= 128");
+}
+
+Status Status::ErrorAesCtrInputTooLongCounterRepeated() {
+ return Status(blink::WebCryptoErrorTypeData,
+ "The input is too large for the counter length.");
+}
+
Status Status::ErrorDataTooLarge() {
return Status(blink::WebCryptoErrorTypeData,
"The provided data is too large");
@@ -185,9 +216,10 @@ Status Status::ErrorImportRsaEmptyModulus() {
return Status(blink::WebCryptoErrorTypeData, "The modulus is empty");
}
-Status Status::ErrorGenerateRsaZeroModulus() {
- return Status(blink::WebCryptoErrorTypeData,
- "The modulus bit length cannot be zero");
+Status Status::ErrorGenerateRsaUnsupportedModulus() {
+ return Status(blink::WebCryptoErrorTypeNotSupported,
+ "The modulus length must be a multiple of 8 bits and >= 256 "
+ "and <= 16384");
}
Status Status::ErrorImportRsaEmptyExponent() {
@@ -207,7 +239,7 @@ Status Status::ErrorGenerateKeyLength() {
}
Status Status::ErrorCreateKeyBadUsages() {
- return Status(blink::WebCryptoErrorTypeData,
+ return Status(blink::WebCryptoErrorTypeSyntax,
"Cannot create a key using the specified key usages.");
}
diff --git a/chromium/content/child/webcrypto/status.h b/chromium/content/child/webcrypto/status.h
index 103c4edf6b5..4c1aae6e185 100644
--- a/chromium/content/child/webcrypto/status.h
+++ b/chromium/content/child/webcrypto/status.h
@@ -69,10 +69,6 @@ class CONTENT_EXPORT Status {
// incompatible with the value requested by the Web Crypto call.
static Status ErrorJwkExtInconsistent();
- // The "alg" parameter could not be converted to an equivalent
- // WebCryptoAlgorithm. Either it was malformed or unrecognized.
- static Status ErrorJwkUnrecognizedAlgorithm();
-
// The "alg" parameter is incompatible with the (optional) Algorithm
// specified by the Web Crypto import operation.
static Status ErrorJwkAlgorithmInconsistent();
@@ -97,9 +93,9 @@ class CONTENT_EXPORT Status {
// are incompatible with each other.
static Status ErrorJwkUseAndKeyopsInconsistent();
- // The "kty" parameter was given and was a string, however it was
- // unrecognized.
- static Status ErrorJwkUnrecognizedKty();
+ // The "kty" parameter was given and was a string, however it was not the
+ // expected value.
+ static Status ErrorJwkUnexpectedKty(const std::string& expected);
// The amount of key data provided was incompatible with the selected
// algorithm. For instance if the algorith name was A128CBC then EXACTLY
@@ -107,9 +103,16 @@ class CONTENT_EXPORT Status {
// given that is an error.
static Status ErrorJwkIncorrectKeyLength();
- // The JWK was for an RSA private key but only partially provided the optional
- // parameters (p, q, dq, dq, qi).
- static Status ErrorJwkIncompleteOptionalRsaPrivateKey();
+ // The JWK property |property| is supposed to represent a big-endian unsigned
+ // integer, however was the empty string.
+ static Status ErrorJwkEmptyBigInteger(const std::string& property);
+
+ // The big-endian unsigned integer |property| contained leading zeros. This
+ // violates the JWA requirement that such octet strings be minimal.
+ static Status ErrorJwkBigIntegerHasLeadingZero(const std::string& property);
+
+ // The key_ops lists a usage more than once.
+ static Status ErrorJwkDuplicateKeyOps();
// ------------------------------------
// Other errors
@@ -120,6 +123,14 @@ class CONTENT_EXPORT Status {
// key data there.
static Status ErrorImportEmptyKeyData();
+ // Tried importing a key using an unsupported format for the key type (for
+ // instance importing an HMAC key using format=spki).
+ static Status ErrorUnsupportedImportKeyFormat();
+
+ // Tried exporting a key using an unsupported format for the key type (for
+ // instance exporting an HMAC key using format=spki).
+ static Status ErrorUnsupportedExportKeyFormat();
+
// The key data buffer provided for importKey() is an incorrect length for
// AES.
static Status ErrorImportAesKeyLength();
@@ -136,6 +147,18 @@ class CONTENT_EXPORT Status {
// bytes.
static Status ErrorIncorrectSizeAesCbcIv();
+ // When doing AES-CTR encryption/decryption, the "counter" parameter was not
+ // 16 bytes.
+ static Status ErrorIncorrectSizeAesCtrCounter();
+
+ // When doing AES-CTR encryption/decryption, the "length" parameter for the
+ // counter was out of range.
+ static Status ErrorInvalidAesCtrCounterLength();
+
+ // The input to encrypt/decrypt was too large. Based on the counter size, it
+ // would cause the counter to wraparound and repeat earlier values.
+ static Status ErrorAesCtrInputTooLongCounterRepeated();
+
// The data provided to an encrypt/decrypt/sign/verify operation was too
// large. This can either represent an internal limitation (for instance
// representing buffer lengths as uints).
@@ -172,8 +195,8 @@ class CONTENT_EXPORT Status {
// The modulus bytes were empty when importing an RSA public key.
static Status ErrorImportRsaEmptyModulus();
- // The the modulus length was zero bits when generating an RSA public key.
- static Status ErrorGenerateRsaZeroModulus();
+ // The modulus length was unsupported when generating an RSA key pair.
+ static Status ErrorGenerateRsaUnsupportedModulus();
// The exponent bytes were empty when importing an RSA public key.
static Status ErrorImportRsaEmptyExponent();
diff --git a/chromium/content/child/webcrypto/structured_clone.cc b/chromium/content/child/webcrypto/structured_clone.cc
new file mode 100644
index 00000000000..68d449a065e
--- /dev/null
+++ b/chromium/content/child/webcrypto/structured_clone.cc
@@ -0,0 +1,136 @@
+// Copyright 2014 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 "content/child/webcrypto/structured_clone.h"
+
+#include "base/logging.h"
+#include "content/child/webcrypto/algorithm_dispatch.h"
+#include "content/child/webcrypto/platform_crypto.h"
+#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/webcrypto_util.h"
+#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
+
+namespace content {
+
+namespace webcrypto {
+
+namespace {
+
+// Returns the key format to use for structured cloning.
+blink::WebCryptoKeyFormat GetCloneFormatForKeyType(
+ blink::WebCryptoKeyType type) {
+ switch (type) {
+ case blink::WebCryptoKeyTypeSecret:
+ return blink::WebCryptoKeyFormatRaw;
+ case blink::WebCryptoKeyTypePublic:
+ return blink::WebCryptoKeyFormatSpki;
+ case blink::WebCryptoKeyTypePrivate:
+ return blink::WebCryptoKeyFormatPkcs8;
+ }
+
+ NOTREACHED();
+ return blink::WebCryptoKeyFormatRaw;
+}
+
+// Converts a KeyAlgorithm into an equivalent Algorithm for import.
+blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm(
+ const blink::WebCryptoKeyAlgorithm& algorithm) {
+ switch (algorithm.paramsType()) {
+ case blink::WebCryptoKeyAlgorithmParamsTypeAes:
+ return CreateAlgorithm(algorithm.id());
+ case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
+ return CreateHmacImportAlgorithm(algorithm.hmacParams()->hash().id());
+ case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
+ return CreateRsaHashedImportAlgorithm(
+ algorithm.id(), algorithm.rsaHashedParams()->hash().id());
+ case blink::WebCryptoKeyAlgorithmParamsTypeNone:
+ break;
+ default:
+ break;
+ }
+ return blink::WebCryptoAlgorithm::createNull();
+}
+
+// There is some duplicated information in the serialized format used by
+// structured clone (since the KeyAlgorithm is serialized separately from the
+// key data). Use this extra information to further validate what was
+// deserialized from the key data.
+//
+// A failure here implies either a bug in the code, or that the serialized data
+// was corrupted.
+bool ValidateDeserializedKey(const blink::WebCryptoKey& key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type) {
+ if (algorithm.id() != key.algorithm().id())
+ return false;
+
+ if (key.type() != type)
+ return false;
+
+ switch (algorithm.paramsType()) {
+ case blink::WebCryptoKeyAlgorithmParamsTypeAes:
+ if (algorithm.aesParams()->lengthBits() !=
+ key.algorithm().aesParams()->lengthBits())
+ return false;
+ break;
+ case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
+ if (algorithm.rsaHashedParams()->modulusLengthBits() !=
+ key.algorithm().rsaHashedParams()->modulusLengthBits())
+ return false;
+ if (algorithm.rsaHashedParams()->publicExponent().size() !=
+ key.algorithm().rsaHashedParams()->publicExponent().size())
+ return false;
+ if (memcmp(algorithm.rsaHashedParams()->publicExponent().data(),
+ key.algorithm().rsaHashedParams()->publicExponent().data(),
+ key.algorithm().rsaHashedParams()->publicExponent().size()) !=
+ 0)
+ return false;
+ break;
+ case blink::WebCryptoKeyAlgorithmParamsTypeNone:
+ case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+// Note that this function is called from the target Blink thread.
+bool SerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8_t>* key_data) {
+ return PlatformSerializeKeyForClone(key, key_data);
+}
+
+// Note that this function is called from the target Blink thread.
+bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const CryptoData& key_data,
+ blink::WebCryptoKey* key) {
+ // TODO(eroman): This should not call into the platform crypto layer.
+ // Otherwise it runs the risk of stalling while the NSS/OpenSSL global locks
+ // are held.
+ //
+ // An alternate approach is to defer the key import until the key is used.
+ // However this means that any deserialization errors would have to be
+ // surfaced as WebCrypto errors, leading to slightly different behaviors. For
+ // instance you could clone a key which fails to be deserialized.
+ Status status = ImportKey(GetCloneFormatForKeyType(type),
+ key_data,
+ KeyAlgorithmToImportAlgorithm(algorithm),
+ extractable,
+ usages,
+ key);
+ if (status.IsError())
+ return false;
+ return ValidateDeserializedKey(*key, algorithm, type);
+}
+
+} // namespace webcrypto
+
+} // namespace content
diff --git a/chromium/content/child/webcrypto/structured_clone.h b/chromium/content/child/webcrypto/structured_clone.h
new file mode 100644
index 00000000000..3e218c85a80
--- /dev/null
+++ b/chromium/content/child/webcrypto/structured_clone.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBCRYPTO_STRUCTURED_CLONE_H_
+#define CONTENT_CHILD_WEBCRYPTO_STRUCTURED_CLONE_H_
+
+#include <stdint.h>
+
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+
+// Called on the target Blink thread.
+bool SerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8_t>* key_data);
+
+// Called on the target Blink thread.
+bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const CryptoData& key_data,
+ blink::WebCryptoKey* key);
+
+} // namespace webcrypto
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBCRYPTO_STRUCTURED_CLONE_H_
diff --git a/chromium/content/child/webcrypto/webcrypto_impl.cc b/chromium/content/child/webcrypto/webcrypto_impl.cc
index 43b108bb0c6..2099a901073 100644
--- a/chromium/content/child/webcrypto/webcrypto_impl.cc
+++ b/chromium/content/child/webcrypto/webcrypto_impl.cc
@@ -10,13 +10,16 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
+#include "content/child/webcrypto/algorithm_dispatch.h"
#include "content/child/webcrypto/crypto_data.h"
-#include "content/child/webcrypto/shared_crypto.h"
+#include "content/child/webcrypto/generate_key_result.h"
#include "content/child/webcrypto/status.h"
+#include "content/child/webcrypto/structured_clone.h"
#include "content/child/webcrypto/webcrypto_util.h"
#include "content/child/worker_thread_task_runner.h"
#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
@@ -108,7 +111,7 @@ void CompleteWithError(const Status& status, blink::WebCryptoResult* result) {
}
void CompleteWithBufferOrError(const Status& status,
- const std::vector<uint8>& buffer,
+ const std::vector<uint8_t>& buffer,
blink::WebCryptoResult* result) {
if (status.IsError()) {
CompleteWithError(status, result);
@@ -118,8 +121,7 @@ void CompleteWithBufferOrError(const Status& status,
// theoretically this could overflow.
CompleteWithError(Status::ErrorUnexpected(), result);
} else {
- result->completeWithBuffer(webcrypto::Uint8VectorStart(buffer),
- buffer.size());
+ result->completeWithBuffer(vector_as_array(&buffer), buffer.size());
}
}
}
@@ -198,9 +200,9 @@ struct EncryptState : public BaseState {
const blink::WebCryptoAlgorithm algorithm;
const blink::WebCryptoKey key;
- const std::vector<uint8> data;
+ const std::vector<uint8_t> data;
- std::vector<uint8> buffer;
+ std::vector<uint8_t> buffer;
};
typedef EncryptState DecryptState;
@@ -209,25 +211,18 @@ typedef EncryptState DigestState;
struct GenerateKeyState : public BaseState {
GenerateKeyState(const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKeyUsageMask usages,
const blink::WebCryptoResult& result)
: BaseState(result),
algorithm(algorithm),
extractable(extractable),
- usage_mask(usage_mask),
- public_key(blink::WebCryptoKey::createNull()),
- private_key(blink::WebCryptoKey::createNull()),
- is_asymmetric(false) {}
+ usages(usages) {}
const blink::WebCryptoAlgorithm algorithm;
const bool extractable;
- const blink::WebCryptoKeyUsageMask usage_mask;
+ const blink::WebCryptoKeyUsageMask usages;
- // If |is_asymmetric| is false, then |public_key| is understood to mean the
- // symmetric key, and |private_key| is unused.
- blink::WebCryptoKey public_key;
- blink::WebCryptoKey private_key;
- bool is_asymmetric;
+ webcrypto::GenerateKeyResult generate_key_result;
};
struct ImportKeyState : public BaseState {
@@ -236,21 +231,20 @@ struct ImportKeyState : public BaseState {
unsigned int key_data_size,
const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKeyUsageMask usages,
const blink::WebCryptoResult& result)
: BaseState(result),
format(format),
key_data(key_data, key_data + key_data_size),
algorithm(algorithm),
extractable(extractable),
- usage_mask(usage_mask),
- key(blink::WebCryptoKey::createNull()) {}
+ usages(usages) {}
const blink::WebCryptoKeyFormat format;
- const std::vector<uint8> key_data;
+ const std::vector<uint8_t> key_data;
const blink::WebCryptoAlgorithm algorithm;
const bool extractable;
- const blink::WebCryptoKeyUsageMask usage_mask;
+ const blink::WebCryptoKeyUsageMask usages;
blink::WebCryptoKey key;
};
@@ -264,7 +258,7 @@ struct ExportKeyState : public BaseState {
const blink::WebCryptoKeyFormat format;
const blink::WebCryptoKey key;
- std::vector<uint8> buffer;
+ std::vector<uint8_t> buffer;
};
typedef EncryptState SignState;
@@ -286,8 +280,8 @@ struct VerifySignatureState : public BaseState {
const blink::WebCryptoAlgorithm algorithm;
const blink::WebCryptoKey key;
- const std::vector<uint8> signature;
- const std::vector<uint8> data;
+ const std::vector<uint8_t> signature;
+ const std::vector<uint8_t> data;
bool verify_result;
};
@@ -309,7 +303,7 @@ struct WrapKeyState : public BaseState {
const blink::WebCryptoKey wrapping_key;
const blink::WebCryptoAlgorithm wrap_algorithm;
- std::vector<uint8> buffer;
+ std::vector<uint8_t> buffer;
};
struct UnwrapKeyState : public BaseState {
@@ -329,11 +323,10 @@ struct UnwrapKeyState : public BaseState {
unwrap_algorithm(unwrap_algorithm),
unwrapped_key_algorithm(unwrapped_key_algorithm),
extractable(extractable),
- usages(usages),
- unwrapped_key(blink::WebCryptoKey::createNull()) {}
+ usages(usages) {}
const blink::WebCryptoKeyFormat format;
- const std::vector<uint8> wrapped_key;
+ const std::vector<uint8_t> wrapped_key;
const blink::WebCryptoKey wrapping_key;
const blink::WebCryptoAlgorithm unwrap_algorithm;
const blink::WebCryptoAlgorithm unwrapped_key_algorithm;
@@ -400,10 +393,7 @@ void DoGenerateKeyReply(scoped_ptr<GenerateKeyState> state) {
if (state->status.IsError()) {
CompleteWithError(state->status, &state->result);
} else {
- if (state->is_asymmetric)
- state->result.completeWithKeyPair(state->public_key, state->private_key);
- else
- state->result.completeWithKey(state->public_key);
+ state->generate_key_result.Complete(&state->result);
}
}
@@ -411,37 +401,10 @@ void DoGenerateKey(scoped_ptr<GenerateKeyState> passed_state) {
GenerateKeyState* state = passed_state.get();
if (state->cancelled())
return;
- state->is_asymmetric =
- webcrypto::IsAlgorithmAsymmetric(state->algorithm.id());
- if (state->is_asymmetric) {
- state->status = webcrypto::GenerateKeyPair(state->algorithm,
- state->extractable,
- state->usage_mask,
- &state->public_key,
- &state->private_key);
-
- if (state->status.IsSuccess()) {
- DCHECK(state->public_key.handle());
- DCHECK(state->private_key.handle());
- DCHECK_EQ(state->algorithm.id(), state->public_key.algorithm().id());
- DCHECK_EQ(state->algorithm.id(), state->private_key.algorithm().id());
- DCHECK_EQ(true, state->public_key.extractable());
- DCHECK_EQ(state->extractable, state->private_key.extractable());
- }
- } else {
- blink::WebCryptoKey* key = &state->public_key;
-
- state->status = webcrypto::GenerateSecretKey(
- state->algorithm, state->extractable, state->usage_mask, key);
-
- if (state->status.IsSuccess()) {
- DCHECK(key->handle());
- DCHECK_EQ(state->algorithm.id(), key->algorithm().id());
- DCHECK_EQ(state->extractable, key->extractable());
- DCHECK_EQ(state->usage_mask, key->usages());
- }
- }
-
+ state->status = webcrypto::GenerateKey(state->algorithm,
+ state->extractable,
+ state->usages,
+ &state->generate_key_result);
state->origin_thread->PostTask(
FROM_HERE, base::Bind(DoGenerateKeyReply, Passed(&passed_state)));
}
@@ -458,7 +421,7 @@ void DoImportKey(scoped_ptr<ImportKeyState> passed_state) {
webcrypto::CryptoData(state->key_data),
state->algorithm,
state->extractable,
- state->usage_mask,
+ state->usages,
&state->key);
if (state->status.IsSuccess()) {
DCHECK(state->key.handle());
@@ -480,8 +443,7 @@ void DoExportKeyReply(scoped_ptr<ExportKeyState> state) {
CompleteWithError(state->status, &state->result);
} else {
state->result.completeWithJson(
- reinterpret_cast<const char*>(
- webcrypto::Uint8VectorStart(&state->buffer)),
+ reinterpret_cast<const char*>(vector_as_array(&state->buffer)),
state->buffer.size());
}
}
@@ -525,12 +487,11 @@ void DoVerify(scoped_ptr<VerifySignatureState> passed_state) {
VerifySignatureState* state = passed_state.get();
if (state->cancelled())
return;
- state->status =
- webcrypto::VerifySignature(state->algorithm,
- state->key,
- webcrypto::CryptoData(state->signature),
- webcrypto::CryptoData(state->data),
- &state->verify_result);
+ state->status = webcrypto::Verify(state->algorithm,
+ state->key,
+ webcrypto::CryptoData(state->signature),
+ webcrypto::CryptoData(state->data),
+ &state->verify_result);
state->origin_thread->PostTask(
FROM_HERE, base::Bind(DoVerifyReply, Passed(&passed_state)));
@@ -584,10 +545,6 @@ WebCryptoImpl::WebCryptoImpl() {
WebCryptoImpl::~WebCryptoImpl() {
}
-void WebCryptoImpl::EnsureInit() {
- webcrypto::Init();
-}
-
void WebCryptoImpl::encrypt(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const unsigned char* data,
@@ -634,12 +591,12 @@ void WebCryptoImpl::digest(const blink::WebCryptoAlgorithm& algorithm,
void WebCryptoImpl::generateKey(const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKeyUsageMask usages,
blink::WebCryptoResult result) {
DCHECK(!algorithm.isNull());
scoped_ptr<GenerateKeyState> state(
- new GenerateKeyState(algorithm, extractable, usage_mask, result));
+ new GenerateKeyState(algorithm, extractable, usages, result));
if (!CryptoThreadPool::PostTask(FROM_HERE,
base::Bind(DoGenerateKey, Passed(&state)))) {
CompleteWithThreadPoolError(&result);
@@ -651,15 +608,10 @@ void WebCryptoImpl::importKey(blink::WebCryptoKeyFormat format,
unsigned int key_data_size,
const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKeyUsageMask usages,
blink::WebCryptoResult result) {
- scoped_ptr<ImportKeyState> state(new ImportKeyState(format,
- key_data,
- key_data_size,
- algorithm,
- extractable,
- usage_mask,
- result));
+ scoped_ptr<ImportKeyState> state(new ImportKeyState(
+ format, key_data, key_data_size, algorithm, extractable, usages, result));
if (!CryptoThreadPool::PostTask(FROM_HERE,
base::Bind(DoImportKey, Passed(&state)))) {
CompleteWithThreadPoolError(&result);
diff --git a/chromium/content/child/webcrypto/webcrypto_impl.h b/chromium/content/child/webcrypto/webcrypto_impl.h
index 485beb9698d..9263f6eefa1 100644
--- a/chromium/content/child/webcrypto/webcrypto_impl.h
+++ b/chromium/content/child/webcrypto/webcrypto_impl.h
@@ -23,9 +23,10 @@ class WebCryptoImpl : public blink::WebCrypto {
public:
WebCryptoImpl();
- virtual ~WebCryptoImpl();
+ // TODO(eroman): Once Blink and Chromium repositories are merged, use
+ // "override" in place of virtual.
- static void EnsureInit();
+ virtual ~WebCryptoImpl();
virtual void encrypt(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
@@ -43,14 +44,14 @@ class WebCryptoImpl : public blink::WebCrypto {
blink::WebCryptoResult result);
virtual void generateKey(const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKeyUsageMask usages,
blink::WebCryptoResult result);
virtual void importKey(blink::WebCryptoKeyFormat format,
const unsigned char* key_data,
unsigned int key_data_size,
const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
+ blink::WebCryptoKeyUsageMask usages,
blink::WebCryptoResult result);
virtual void exportKey(blink::WebCryptoKeyFormat format,
const blink::WebCryptoKey& key,
diff --git a/chromium/content/child/webcrypto/webcrypto_util.cc b/chromium/content/child/webcrypto/webcrypto_util.cc
index 87ac17465e8..410acdda738 100644
--- a/chromium/content/child/webcrypto/webcrypto_util.cc
+++ b/chromium/content/child/webcrypto/webcrypto_util.cc
@@ -4,7 +4,8 @@
#include "content/child/webcrypto/webcrypto_util.h"
-#include "base/base64.h"
+#include <set>
+
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "content/child/webcrypto/status.h"
@@ -16,48 +17,30 @@ namespace content {
namespace webcrypto {
-const uint8* Uint8VectorStart(const std::vector<uint8>& data) {
- if (data.empty())
- return NULL;
- return &data[0];
-}
+namespace {
-uint8* Uint8VectorStart(std::vector<uint8>* data) {
- if (data->empty())
- return NULL;
- return &(*data)[0];
-}
+// Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros,
+// to unsigned int.
+bool BigIntegerToUint(const uint8_t* data,
+ unsigned int data_size,
+ unsigned int* result) {
+ if (data_size == 0)
+ return false;
-// This function decodes unpadded 'base64url' encoded data, as described in
-// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5. To do this, first
-// change the incoming data to 'base64' encoding by applying the appropriate
-// transformation including adding padding if required, and then call a base64
-// decoder.
-bool Base64DecodeUrlSafe(const std::string& input, std::string* output) {
- std::string base64EncodedText(input);
- std::replace(base64EncodedText.begin(), base64EncodedText.end(), '-', '+');
- std::replace(base64EncodedText.begin(), base64EncodedText.end(), '_', '/');
- base64EncodedText.append((4 - base64EncodedText.size() % 4) % 4, '=');
- return base::Base64Decode(base64EncodedText, output);
-}
+ *result = 0;
+ for (size_t i = 0; i < data_size; ++i) {
+ size_t reverse_i = data_size - i - 1;
-// Returns an unpadded 'base64url' encoding of the input data, using the
-// inverse of the process above.
-std::string Base64EncodeUrlSafe(const base::StringPiece& input) {
- std::string output;
- base::Base64Encode(input, &output);
- std::replace(output.begin(), output.end(), '+', '-');
- std::replace(output.begin(), output.end(), '/', '_');
- output.erase(std::remove(output.begin(), output.end(), '='), output.end());
- return output;
-}
+ if (reverse_i >= sizeof(*result) && data[i])
+ return false; // Too large for a uint.
-std::string Base64EncodeUrlSafe(const std::vector<uint8>& input) {
- const base::StringPiece string_piece(
- reinterpret_cast<const char*>(Uint8VectorStart(input)), input.size());
- return Base64EncodeUrlSafe(string_piece);
+ *result |= data[i] << 8 * reverse_i;
+ }
+ return true;
}
+} // namespace
+
struct JwkToWebCryptoUsage {
const char* const jwk_key_op;
const blink::WebCryptoKeyUsage webcrypto_usage;
@@ -80,12 +63,11 @@ const JwkToWebCryptoUsage kJwkWebCryptoUsageMap[] = {
{"wrapKey", blink::WebCryptoKeyUsageWrapKey},
{"unwrapKey", blink::WebCryptoKeyUsageUnwrapKey}};
-// Modifies the input usage_mask by according to the key_op value.
bool JwkKeyOpToWebCryptoUsage(const std::string& key_op,
- blink::WebCryptoKeyUsageMask* usage_mask) {
+ blink::WebCryptoKeyUsage* usage) {
for (size_t i = 0; i < arraysize(kJwkWebCryptoUsageMap); ++i) {
if (kJwkWebCryptoUsageMap[i].jwk_key_op == key_op) {
- *usage_mask |= kJwkWebCryptoUsageMap[i].webcrypto_usage;
+ *usage = kJwkWebCryptoUsageMap[i].webcrypto_usage;
return true;
}
}
@@ -93,18 +75,32 @@ bool JwkKeyOpToWebCryptoUsage(const std::string& key_op,
}
// Composes a Web Crypto usage mask from an array of JWK key_ops values.
-Status GetWebCryptoUsagesFromJwkKeyOps(
- const base::ListValue* jwk_key_ops_value,
- blink::WebCryptoKeyUsageMask* usage_mask) {
- *usage_mask = 0;
- for (size_t i = 0; i < jwk_key_ops_value->GetSize(); ++i) {
+Status GetWebCryptoUsagesFromJwkKeyOps(const base::ListValue* key_ops,
+ blink::WebCryptoKeyUsageMask* usages) {
+ // This set keeps track of all unrecognized key_ops values.
+ std::set<std::string> unrecognized_usages;
+
+ *usages = 0;
+ for (size_t i = 0; i < key_ops->GetSize(); ++i) {
std::string key_op;
- if (!jwk_key_ops_value->GetString(i, &key_op)) {
+ if (!key_ops->GetString(i, &key_op)) {
return Status::ErrorJwkPropertyWrongType(
base::StringPrintf("key_ops[%d]", static_cast<int>(i)), "string");
}
- // Unrecognized key_ops are silently skipped.
- ignore_result(JwkKeyOpToWebCryptoUsage(key_op, usage_mask));
+
+ blink::WebCryptoKeyUsage usage;
+ if (JwkKeyOpToWebCryptoUsage(key_op, &usage)) {
+ // Ensure there are no duplicate usages.
+ if (*usages & usage)
+ return Status::ErrorJwkDuplicateKeyOps();
+ *usages |= usage;
+ }
+
+ // Reaching here means the usage was unrecognized. Such usages are skipped
+ // over, however they are kept track of in a set to ensure there were no
+ // duplicates.
+ if (!unrecognized_usages.insert(key_op).second)
+ return Status::ErrorJwkDuplicateKeyOps();
}
return Status::Success();
}
@@ -112,32 +108,15 @@ Status GetWebCryptoUsagesFromJwkKeyOps(
// Composes a JWK key_ops List from a Web Crypto usage mask.
// Note: Caller must assume ownership of returned instance.
base::ListValue* CreateJwkKeyOpsFromWebCryptoUsages(
- blink::WebCryptoKeyUsageMask usage_mask) {
+ blink::WebCryptoKeyUsageMask usages) {
base::ListValue* jwk_key_ops = new base::ListValue();
for (size_t i = 0; i < arraysize(kJwkWebCryptoUsageMap); ++i) {
- if (usage_mask & kJwkWebCryptoUsageMap[i].webcrypto_usage)
+ if (usages & kJwkWebCryptoUsageMap[i].webcrypto_usage)
jwk_key_ops->AppendString(kJwkWebCryptoUsageMap[i].jwk_key_op);
}
return jwk_key_ops;
}
-blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
- const blink::WebCryptoAlgorithm& algorithm) {
- DCHECK(!algorithm.isNull());
- switch (algorithm.paramsType()) {
- case blink::WebCryptoAlgorithmParamsTypeHmacImportParams:
- return algorithm.hmacImportParams()->hash();
- case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams:
- return algorithm.hmacKeyGenParams()->hash();
- case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
- return algorithm.rsaHashedImportParams()->hash();
- case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
- return algorithm.rsaHashedKeyGenParams()->hash();
- default:
- return blink::WebCryptoAlgorithm::createNull();
- }
-}
-
blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) {
return blink::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL);
}
@@ -154,52 +133,125 @@ blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
blink::WebCryptoAlgorithmId id,
blink::WebCryptoAlgorithmId hash_id) {
DCHECK(blink::WebCryptoAlgorithm::isHash(hash_id));
- DCHECK(id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
- id == blink::WebCryptoAlgorithmIdRsaOaep);
return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
}
-bool CreateSecretKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
- unsigned int keylen_bytes,
- blink::WebCryptoKeyAlgorithm* key_algorithm) {
- switch (algorithm.id()) {
- case blink::WebCryptoAlgorithmIdHmac: {
- blink::WebCryptoAlgorithm hash = GetInnerHashAlgorithm(algorithm);
- if (hash.isNull())
- return false;
- if (keylen_bytes > UINT_MAX / 8)
- return false;
- *key_algorithm =
- blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bytes * 8);
- return true;
+bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a,
+ blink::WebCryptoKeyUsageMask b) {
+ return (a & b) == b;
+}
+
+// TODO(eroman): Move this helper to WebCryptoKey.
+bool KeyUsageAllows(const blink::WebCryptoKey& key,
+ const blink::WebCryptoKeyUsage usage) {
+ return ((key.usages() & usage) != 0);
+}
+
+// The WebCrypto spec defines the default value for the tag length, as well as
+// the allowed values for tag length.
+Status GetAesGcmTagLengthInBits(const blink::WebCryptoAesGcmParams* params,
+ unsigned int* tag_length_bits) {
+ *tag_length_bits = 128;
+ if (params->hasTagLengthBits())
+ *tag_length_bits = params->optionalTagLengthBits();
+
+ if (*tag_length_bits != 32 && *tag_length_bits != 64 &&
+ *tag_length_bits != 96 && *tag_length_bits != 104 &&
+ *tag_length_bits != 112 && *tag_length_bits != 120 &&
+ *tag_length_bits != 128)
+ return Status::ErrorInvalidAesGcmTagLength();
+
+ return Status::Success();
+}
+
+Status GetAesKeyGenLengthInBits(const blink::WebCryptoAesKeyGenParams* params,
+ unsigned int* keylen_bits) {
+ *keylen_bits = params->lengthBits();
+
+ if (*keylen_bits == 128 || *keylen_bits == 256)
+ return Status::Success();
+
+ // BoringSSL does not support 192-bit AES.
+ if (*keylen_bits == 192)
+ return Status::ErrorAes192BitUnsupported();
+
+ return Status::ErrorGenerateKeyLength();
+}
+
+Status GetHmacKeyGenLengthInBits(const blink::WebCryptoHmacKeyGenParams* params,
+ unsigned int* keylen_bits) {
+ if (!params->hasLengthBits()) {
+ switch (params->hash().id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ case blink::WebCryptoAlgorithmIdSha256:
+ *keylen_bits = 512;
+ return Status::Success();
+ case blink::WebCryptoAlgorithmIdSha384:
+ case blink::WebCryptoAlgorithmIdSha512:
+ *keylen_bits = 1024;
+ return Status::Success();
+ default:
+ return Status::ErrorUnsupported();
}
- case blink::WebCryptoAlgorithmIdAesKw:
- case blink::WebCryptoAlgorithmIdAesCbc:
- case blink::WebCryptoAlgorithmIdAesCtr:
- case blink::WebCryptoAlgorithmIdAesGcm:
- *key_algorithm = blink::WebCryptoKeyAlgorithm::createAes(
- algorithm.id(), keylen_bytes * 8);
- return true;
- default:
- return false;
}
+
+ if (params->optionalLengthBits() % 8)
+ return Status::ErrorGenerateKeyLength();
+
+ *keylen_bits = params->optionalLengthBits();
+
+ // TODO(eroman): NSS fails when generating a zero-length secret key.
+ if (*keylen_bits == 0)
+ return Status::ErrorGenerateKeyLength();
+
+ return Status::Success();
}
-bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a,
- blink::WebCryptoKeyUsageMask b) {
- return (a & b) == b;
+Status VerifyAesKeyLengthForImport(unsigned int keylen_bytes) {
+ if (keylen_bytes == 16 || keylen_bytes == 32)
+ return Status::Success();
+
+ // BoringSSL does not support 192-bit AES.
+ if (keylen_bytes == 24)
+ return Status::ErrorAes192BitUnsupported();
+
+ return Status::ErrorImportAesKeyLength();
}
-bool IsAlgorithmRsa(blink::WebCryptoAlgorithmId alg_id) {
- return alg_id == blink::WebCryptoAlgorithmIdRsaOaep ||
- alg_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
+Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages,
+ blink::WebCryptoKeyUsageMask actual_usages) {
+ if (!ContainsKeyUsages(all_possible_usages, actual_usages))
+ return Status::ErrorCreateKeyBadUsages();
+ return Status::Success();
}
-bool IsAlgorithmAsymmetric(blink::WebCryptoAlgorithmId alg_id) {
- // TODO(padolph): include all other asymmetric algorithms once they are
- // defined, e.g. EC and DH.
- return IsAlgorithmRsa(alg_id);
+Status GetRsaKeyGenParameters(
+ const blink::WebCryptoRsaHashedKeyGenParams* params,
+ unsigned int* public_exponent,
+ unsigned int* modulus_length_bits) {
+ *modulus_length_bits = params->modulusLengthBits();
+
+ // Limit key sizes to those supported by NSS:
+ // * Multiple of 8 bits
+ // * 256 bits to 16K bits
+ if (*modulus_length_bits < 256 || *modulus_length_bits > 16384 ||
+ (*modulus_length_bits % 8) != 0) {
+ return Status::ErrorGenerateRsaUnsupportedModulus();
+ }
+
+ if (!BigIntegerToUint(params->publicExponent().data(),
+ params->publicExponent().size(),
+ public_exponent)) {
+ return Status::ErrorGenerateKeyPublicExponent();
+ }
+
+ // OpenSSL hangs when given bad public exponents, whereas NSS simply fails. To
+ // avoid feeding OpenSSL data that will hang use a whitelist.
+ if (*public_exponent != 3 && *public_exponent != 65537)
+ return Status::ErrorGenerateKeyPublicExponent();
+
+ return Status::Success();
}
} // namespace webcrypto
diff --git a/chromium/content/child/webcrypto/webcrypto_util.h b/chromium/content/child/webcrypto/webcrypto_util.h
index f4a2a6f6528..26b4675f059 100644
--- a/chromium/content/child/webcrypto/webcrypto_util.h
+++ b/chromium/content/child/webcrypto/webcrypto_util.h
@@ -5,10 +5,9 @@
#ifndef CONTENT_CHILD_WEBCRYPTO_WEBCRYPTO_UTIL_H_
#define CONTENT_CHILD_WEBCRYPTO_WEBCRYPTO_UTIL_H_
+#include <stdint.h>
#include <string>
-#include <vector>
-#include "base/basictypes.h"
-#include "base/strings/string_piece.h"
+
#include "base/values.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
@@ -20,36 +19,14 @@ namespace webcrypto {
class Status;
-// Returns a pointer to the start of |data|, or NULL if it is empty. This is a
-// convenience function for getting the pointer, and should not be used beyond
-// the expected lifetime of |data|.
-CONTENT_EXPORT const uint8* Uint8VectorStart(const std::vector<uint8>& data);
-CONTENT_EXPORT uint8* Uint8VectorStart(std::vector<uint8>* data);
-
-// This function decodes unpadded 'base64url' encoded data, as described in
-// RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5.
-// In Web Crypto, this type of encoding is only used inside JWK.
-CONTENT_EXPORT bool Base64DecodeUrlSafe(const std::string& input,
- std::string* output);
-
-// Returns an unpadded 'base64url' encoding of the input data, the opposite of
-// Base64DecodeUrlSafe() above.
-CONTENT_EXPORT std::string Base64EncodeUrlSafe(const base::StringPiece& input);
-CONTENT_EXPORT std::string Base64EncodeUrlSafe(const std::vector<uint8>& input);
-
-// Composes a Web Crypto usage mask from an array of JWK key_ops values.
-CONTENT_EXPORT Status GetWebCryptoUsagesFromJwkKeyOps(
- const base::ListValue* jwk_key_ops_value,
- blink::WebCryptoKeyUsageMask* jwk_key_ops_mask);
+// Converts a JWK "key_ops" array to the corresponding WebCrypto usages.
+CONTENT_EXPORT Status
+ GetWebCryptoUsagesFromJwkKeyOps(const base::ListValue* key_ops,
+ blink::WebCryptoKeyUsageMask* usages);
// Composes a JWK key_ops array from a Web Crypto usage mask.
base::ListValue* CreateJwkKeyOpsFromWebCryptoUsages(
- blink::WebCryptoKeyUsageMask usage_mask);
-
-// Returns the "hash" param for an algorithm if it exists, otherwise returns
-// a null algorithm.
-blink::WebCryptoAlgorithm GetInnerHashAlgorithm(
- const blink::WebCryptoAlgorithm& algorithm);
+ blink::WebCryptoKeyUsageMask usages);
// Creates a WebCryptoAlgorithm without any parameters.
CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAlgorithm(
@@ -67,16 +44,37 @@ CONTENT_EXPORT blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
blink::WebCryptoAlgorithmId id,
blink::WebCryptoAlgorithmId hash_id);
-bool CreateSecretKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
- unsigned int keylen_bytes,
- blink::WebCryptoKeyAlgorithm* key_algorithm);
-
// Returns true if the set bits in b make up a subset of the set bits in a.
bool ContainsKeyUsages(blink::WebCryptoKeyUsageMask a,
blink::WebCryptoKeyUsageMask b);
-bool IsAlgorithmRsa(blink::WebCryptoAlgorithmId alg_id);
-bool IsAlgorithmAsymmetric(blink::WebCryptoAlgorithmId alg_id);
+bool KeyUsageAllows(const blink::WebCryptoKey& key,
+ const blink::WebCryptoKeyUsage usage);
+
+Status GetAesGcmTagLengthInBits(const blink::WebCryptoAesGcmParams* params,
+ unsigned int* tag_length_bits);
+
+Status GetAesKeyGenLengthInBits(const blink::WebCryptoAesKeyGenParams* params,
+ unsigned int* keylen_bits);
+
+Status GetHmacKeyGenLengthInBits(const blink::WebCryptoHmacKeyGenParams* params,
+ unsigned int* keylen_bits);
+
+Status VerifyAesKeyLengthForImport(unsigned int keylen_bytes);
+
+Status CheckKeyCreationUsages(blink::WebCryptoKeyUsageMask all_possible_usages,
+ blink::WebCryptoKeyUsageMask actual_usages);
+
+// Extracts the public exponent and modulus length from the Blink parameters.
+// On success it is guaranteed that:
+// * public_exponent is either 3 or 65537
+// * modulus_length_bits is a multiple of 8
+// * modulus_length is >= 256
+// * modulus_length is <= 16K
+Status GetRsaKeyGenParameters(
+ const blink::WebCryptoRsaHashedKeyGenParams* params,
+ unsigned int* public_exponent,
+ unsigned int* modulus_length_bits);
} // namespace webcrypto
diff --git a/chromium/content/child/webfileutilities_impl.cc b/chromium/content/child/webfileutilities_impl.cc
index e2f3e331104..72ddc73d9d6 100644
--- a/chromium/content/child/webfileutilities_impl.cc
+++ b/chromium/content/child/webfileutilities_impl.cc
@@ -4,10 +4,10 @@
#include "content/child/webfileutilities_impl.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
-#include "content/child/blink_glue.h"
+#include "content/child/file_info_util.h"
#include "net/base/file_stream.h"
#include "net/base/filename_util.h"
#include "third_party/WebKit/public/platform/WebFileInfo.h"
diff --git a/chromium/content/child/webmessageportchannel_impl.cc b/chromium/content/child/webmessageportchannel_impl.cc
index b32dde9bdbe..dbdc2f38eb6 100644
--- a/chromium/content/child/webmessageportchannel_impl.cc
+++ b/chromium/content/child/webmessageportchannel_impl.cc
@@ -20,7 +20,7 @@ using blink::WebString;
namespace content {
WebMessagePortChannelImpl::WebMessagePortChannelImpl(
- base::MessageLoopProxy* child_thread_loop)
+ const scoped_refptr<base::MessageLoopProxy>& child_thread_loop)
: client_(NULL),
route_id_(MSG_ROUTING_NONE),
message_port_id_(MSG_ROUTING_NONE),
@@ -32,7 +32,7 @@ WebMessagePortChannelImpl::WebMessagePortChannelImpl(
WebMessagePortChannelImpl::WebMessagePortChannelImpl(
int route_id,
int message_port_id,
- base::MessageLoopProxy* child_thread_loop)
+ const scoped_refptr<base::MessageLoopProxy>& child_thread_loop)
: client_(NULL),
route_id_(route_id),
message_port_id_(message_port_id),
@@ -61,7 +61,7 @@ WebMessagePortChannelImpl::~WebMessagePortChannelImpl() {
// static
void WebMessagePortChannelImpl::CreatePair(
- base::MessageLoopProxy* child_thread_loop,
+ const scoped_refptr<base::MessageLoopProxy>& child_thread_loop,
blink::WebMessagePortChannel** channel1,
blink::WebMessagePortChannel** channel2) {
WebMessagePortChannelImpl* impl1 =
@@ -119,7 +119,8 @@ void WebMessagePortChannelImpl::postMessage(
child_thread_loop_->PostTask(
FROM_HERE,
base::Bind(
- &WebMessagePortChannelImpl::PostMessage, this, message, channels));
+ &WebMessagePortChannelImpl::PostMessage, this,
+ static_cast<base::string16>(message), channels));
} else {
PostMessage(message, channels);
}
diff --git a/chromium/content/child/webmessageportchannel_impl.h b/chromium/content/child/webmessageportchannel_impl.h
index 01cd9276fd5..e33ccc4d94c 100644
--- a/chromium/content/child/webmessageportchannel_impl.h
+++ b/chromium/content/child/webmessageportchannel_impl.h
@@ -28,14 +28,17 @@ class WebMessagePortChannelImpl
public IPC::Listener,
public base::RefCountedThreadSafe<WebMessagePortChannelImpl> {
public:
- explicit WebMessagePortChannelImpl(base::MessageLoopProxy* child_thread_loop);
- WebMessagePortChannelImpl(int route_id,
- int message_port_id,
- base::MessageLoopProxy* child_thread_loop);
-
- static void CreatePair(base::MessageLoopProxy* child_thread_loop,
- blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2);
+ explicit WebMessagePortChannelImpl(
+ const scoped_refptr<base::MessageLoopProxy>& child_thread_loop);
+ WebMessagePortChannelImpl(
+ int route_id,
+ int message_port_id,
+ const scoped_refptr<base::MessageLoopProxy>& child_thread_loop);
+
+ static void CreatePair(
+ const scoped_refptr<base::MessageLoopProxy>& child_thread_loop,
+ blink::WebMessagePortChannel** channel1,
+ blink::WebMessagePortChannel** channel2);
// Extracts port IDs for passing on to the browser process, and queues any
// received messages. Takes ownership of the passed array (and deletes it).
@@ -49,7 +52,7 @@ class WebMessagePortChannelImpl
private:
friend class base::RefCountedThreadSafe<WebMessagePortChannelImpl>;
- virtual ~WebMessagePortChannelImpl();
+ ~WebMessagePortChannelImpl() override;
// WebMessagePortChannel implementation.
virtual void setClient(blink::WebMessagePortChannelClient* client);
@@ -66,7 +69,7 @@ class WebMessagePortChannelImpl
blink::WebMessagePortChannelArray* channels);
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnMessage(const base::string16& message,
const std::vector<int>& sent_message_port_ids,
diff --git a/chromium/content/child/websocket_bridge.h b/chromium/content/child/websocket_bridge.h
index b606a74dd15..0fe5ae29466 100644
--- a/chromium/content/child/websocket_bridge.h
+++ b/chromium/content/child/websocket_bridge.h
@@ -34,14 +34,14 @@ class WebSocketBridge : public blink::WebSocketHandle {
virtual void connect(const blink::WebURL& url,
const blink::WebVector<blink::WebString>& protocols,
const blink::WebSerializedOrigin& origin,
- blink::WebSocketHandleClient* client) OVERRIDE;
+ blink::WebSocketHandleClient* client) override;
virtual void send(bool fin,
WebSocketHandle::MessageType type,
const char* data,
- size_t size) OVERRIDE;
- virtual void flowControl(int64_t quota) OVERRIDE;
+ size_t size) override;
+ virtual void flowControl(int64_t quota) override;
virtual void close(unsigned short code,
- const blink::WebString& reason) OVERRIDE;
+ const blink::WebString& reason) override;
virtual void Disconnect();
diff --git a/chromium/content/child/websocket_dispatcher.h b/chromium/content/child/websocket_dispatcher.h
index 5356c3b5daa..ac864481595 100644
--- a/chromium/content/child/websocket_dispatcher.h
+++ b/chromium/content/child/websocket_dispatcher.h
@@ -25,14 +25,14 @@ class WebSocketBridge;
class WebSocketDispatcher : public IPC::Listener {
public:
WebSocketDispatcher();
- virtual ~WebSocketDispatcher();
+ ~WebSocketDispatcher() override;
// Returns a unique channel id
int AddBridge(WebSocketBridge* bridge);
void RemoveBridge(int channel_id);
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
private:
WebSocketBridge* GetBridge(int channel_id, uint32 type);
diff --git a/chromium/content/child/webthemeengine_impl_mac.cc b/chromium/content/child/webthemeengine_impl_mac.cc
deleted file mode 100644
index 62a5da11ef3..00000000000
--- a/chromium/content/child/webthemeengine_impl_mac.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 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 "content/child/webthemeengine_impl_mac.h"
-
-#include <Carbon/Carbon.h>
-
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/WebKit/public/platform/WebCanvas.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-
-using blink::WebCanvas;
-using blink::WebRect;
-using blink::WebThemeEngine;
-
-namespace content {
-
-static ThemeTrackEnableState stateToHIEnableState(WebThemeEngine::State state) {
- switch (state) {
- case WebThemeEngine::StateDisabled:
- return kThemeTrackDisabled;
- case WebThemeEngine::StateInactive:
- return kThemeTrackInactive;
- default:
- return kThemeTrackActive;
- }
-}
-
-void WebThemeEngineImpl::paintScrollbarThumb(
- WebCanvas* canvas,
- WebThemeEngine::State state,
- WebThemeEngine::Size size,
- const WebRect& rect,
- const WebThemeEngine::ScrollbarInfo& scrollbarInfo) {
- HIThemeTrackDrawInfo trackInfo;
- trackInfo.version = 0;
- trackInfo.kind = size == WebThemeEngine::SizeRegular ?
- kThemeMediumScrollBar : kThemeSmallScrollBar;
- trackInfo.bounds = CGRectMake(rect.x, rect.y, rect.width, rect.height);
- trackInfo.min = 0;
- trackInfo.max = scrollbarInfo.maxValue;
- trackInfo.value = scrollbarInfo.currentValue;
- trackInfo.trackInfo.scrollbar.viewsize = scrollbarInfo.visibleSize;
- trackInfo.attributes = 0;
- if (scrollbarInfo.orientation ==
- WebThemeEngine::ScrollbarOrientationHorizontal) {
- trackInfo.attributes |= kThemeTrackHorizontal;
- }
-
- trackInfo.enableState = stateToHIEnableState(state);
-
- trackInfo.trackInfo.scrollbar.pressState =
- state == WebThemeEngine::StatePressed ? kThemeThumbPressed : 0;
- trackInfo.attributes |= (kThemeTrackShowThumb | kThemeTrackHideTrack);
- gfx::SkiaBitLocker bitLocker(canvas);
- CGContextRef cgContext = bitLocker.cgContext();
- HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
-}
-
-} // namespace content
diff --git a/chromium/content/child/webthemeengine_impl_mac.h b/chromium/content/child/webthemeengine_impl_mac.h
index 7f7a6915948..f937361a26e 100644
--- a/chromium/content/child/webthemeengine_impl_mac.h
+++ b/chromium/content/child/webthemeengine_impl_mac.h
@@ -10,14 +10,6 @@
namespace content {
class WebThemeEngineImpl : public blink::WebThemeEngine {
- public:
- // blink::WebThemeEngine implementation.
- virtual void paintScrollbarThumb(
- blink::WebCanvas* canvas,
- blink::WebThemeEngine::State part,
- blink::WebThemeEngine::Size state,
- const blink::WebRect& rect,
- const blink::WebThemeEngine::ScrollbarInfo& extra_params);
};
} // namespace content
diff --git a/chromium/content/child/webthread_impl.cc b/chromium/content/child/webthread_impl.cc
index d53d06e0610..ec80b70e86e 100644
--- a/chromium/content/child/webthread_impl.cc
+++ b/chromium/content/child/webthread_impl.cc
@@ -24,11 +24,11 @@ class WebThreadBase::TaskObserverAdapter
TaskObserverAdapter(WebThread::TaskObserver* observer)
: observer_(observer) {}
- virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
+ void WillProcessTask(const base::PendingTask& pending_task) override {
observer_->willProcessTask();
}
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
+ void DidProcessTask(const base::PendingTask& pending_task) override {
observer_->didProcessTask();
}
@@ -88,13 +88,18 @@ bool WebThreadImpl::isCurrentThread() const {
return thread_->thread_id() == base::PlatformThread::CurrentId();
}
+blink::PlatformThreadId WebThreadImpl::threadId() const {
+ return thread_->thread_id();
+}
+
WebThreadImpl::~WebThreadImpl() {
thread_->Stop();
}
WebThreadImplForMessageLoop::WebThreadImplForMessageLoop(
base::MessageLoopProxy* message_loop)
- : message_loop_(message_loop) {}
+ : message_loop_(message_loop),
+ thread_id_(base::PlatformThread::CurrentId()) {}
void WebThreadImplForMessageLoop::postTask(Task* task) {
message_loop_->PostTask(
@@ -126,6 +131,10 @@ bool WebThreadImplForMessageLoop::isCurrentThread() const {
return message_loop_->BelongsToCurrentThread();
}
+blink::PlatformThreadId WebThreadImplForMessageLoop::threadId() const {
+ return thread_id_;
+}
+
WebThreadImplForMessageLoop::~WebThreadImplForMessageLoop() {}
} // namespace content
diff --git a/chromium/content/child/webthread_impl.h b/chromium/content/child/webthread_impl.h
index 4c81b2579d6..8ebbd97d02c 100644
--- a/chromium/content/child/webthread_impl.h
+++ b/chromium/content/child/webthread_impl.h
@@ -22,6 +22,7 @@ class CONTENT_EXPORT WebThreadBase : public blink::WebThread {
virtual void removeTaskObserver(TaskObserver* observer);
virtual bool isCurrentThread() const = 0;
+ virtual blink::PlatformThreadId threadId() const = 0;
protected:
WebThreadBase();
@@ -46,7 +47,8 @@ class CONTENT_EXPORT WebThreadImpl : public WebThreadBase {
base::MessageLoop* message_loop() const { return thread_->message_loop(); }
- virtual bool isCurrentThread() const OVERRIDE;
+ virtual bool isCurrentThread() const override;
+ virtual blink::PlatformThreadId threadId() const override;
private:
scoped_ptr<base::Thread> thread_;
@@ -58,15 +60,18 @@ class WebThreadImplForMessageLoop : public WebThreadBase {
base::MessageLoopProxy* message_loop);
CONTENT_EXPORT virtual ~WebThreadImplForMessageLoop();
- virtual void postTask(Task* task) OVERRIDE;
- virtual void postDelayedTask(Task* task, long long delay_ms) OVERRIDE;
+ virtual void postTask(Task* task) override;
+ virtual void postDelayedTask(Task* task, long long delay_ms) override;
- virtual void enterRunLoop() OVERRIDE;
- virtual void exitRunLoop() OVERRIDE;
+ virtual void enterRunLoop() override;
+ virtual void exitRunLoop() override;
private:
- virtual bool isCurrentThread() const OVERRIDE;
+ virtual bool isCurrentThread() const override;
+ virtual blink::PlatformThreadId threadId() const override;
+
scoped_refptr<base::MessageLoopProxy> message_loop_;
+ blink::PlatformThreadId thread_id_;
};
} // namespace content
diff --git a/chromium/content/child/weburlresponse_extradata_impl.cc b/chromium/content/child/weburlresponse_extradata_impl.cc
new file mode 100644
index 00000000000..3eee8bcd320
--- /dev/null
+++ b/chromium/content/child/weburlresponse_extradata_impl.cc
@@ -0,0 +1,19 @@
+// Copyright 2014 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 "content/child/weburlresponse_extradata_impl.h"
+
+namespace content {
+
+WebURLResponseExtraDataImpl::WebURLResponseExtraDataImpl(
+ const std::string& npn_negotiated_protocol)
+ : npn_negotiated_protocol_(npn_negotiated_protocol),
+ is_ftp_directory_listing_(false),
+ connection_info_(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN) {
+}
+
+WebURLResponseExtraDataImpl::~WebURLResponseExtraDataImpl() {
+}
+
+} // namespace content
diff --git a/chromium/content/child/weburlresponse_extradata_impl.h b/chromium/content/child/weburlresponse_extradata_impl.h
new file mode 100644
index 00000000000..719b0693c4c
--- /dev/null
+++ b/chromium/content/child/weburlresponse_extradata_impl.h
@@ -0,0 +1,105 @@
+// Copyright 2014 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 CONTENT_CHILD_WEBURLRESPONSE_EXTRADATA_IMPL_H_
+#define CONTENT_CHILD_WEBURLRESPONSE_EXTRADATA_IMPL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "net/http/http_response_info.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+
+namespace content {
+
+class CONTENT_EXPORT WebURLResponseExtraDataImpl :
+ public NON_EXPORTED_BASE(blink::WebURLResponse::ExtraData) {
+ public:
+ explicit WebURLResponseExtraDataImpl(
+ const std::string& npn_negotiated_protocol);
+ virtual ~WebURLResponseExtraDataImpl();
+
+ const std::string& npn_negotiated_protocol() const {
+ return npn_negotiated_protocol_;
+ }
+
+ // Flag whether this request was loaded via an explicit proxy
+ // (HTTP, SOCKS, etc).
+ bool was_fetched_via_proxy() const {
+ return was_fetched_via_proxy_;
+ }
+ void set_was_fetched_via_proxy(bool was_fetched_via_proxy) {
+ was_fetched_via_proxy_ = was_fetched_via_proxy;
+ }
+
+ // The proxy server used if this request was loaded via an explicit proxy
+ // (HTTP, SOCKS, etc).
+ net::HostPortPair proxy_server() const {
+ return proxy_server_;
+ }
+ void set_proxy_server(net::HostPortPair proxy_server) {
+ proxy_server_ = proxy_server;
+ }
+
+ /// Flag whether this request was loaded via the SPDY protocol or not.
+ // SPDY is an experimental web protocol, see http://dev.chromium.org/spdy
+ bool was_fetched_via_spdy() const {
+ return was_fetched_via_spdy_;
+ }
+ void set_was_fetched_via_spdy(bool was_fetched_via_spdy) {
+ was_fetched_via_spdy_ = was_fetched_via_spdy;
+ }
+
+ // Information about the type of connection used to fetch this response.
+ net::HttpResponseInfo::ConnectionInfo connection_info() const {
+ return connection_info_;
+ }
+ void set_connection_info(
+ net::HttpResponseInfo::ConnectionInfo connection_info) {
+ connection_info_ = connection_info;
+ }
+
+ // Flag whether this request was loaded after the
+ // TLS/Next-Protocol-Negotiation was used.
+ // This is related to SPDY.
+ bool was_npn_negotiated() const {
+ return was_npn_negotiated_;
+ }
+ void set_was_npn_negotiated(bool was_npn_negotiated) {
+ was_npn_negotiated_ = was_npn_negotiated;
+ }
+
+ // Flag whether this request was made when "Alternate-Protocol: xxx"
+ // is present in server's response.
+ bool was_alternate_protocol_available() const {
+ return was_alternate_protocol_available_;
+ }
+ void set_was_alternate_protocol_available(
+ bool was_alternate_protocol_available) {
+ was_alternate_protocol_available_ = was_alternate_protocol_available;
+ }
+
+ bool is_ftp_directory_listing() const { return is_ftp_directory_listing_; }
+ void set_is_ftp_directory_listing(bool is_ftp_directory_listing) {
+ is_ftp_directory_listing_ = is_ftp_directory_listing;
+ }
+
+ private:
+ std::string npn_negotiated_protocol_;
+ bool is_ftp_directory_listing_;
+ bool was_fetched_via_proxy_;
+ net::HostPortPair proxy_server_;
+ bool was_fetched_via_spdy_;
+ bool was_npn_negotiated_;
+ net::HttpResponseInfo::ConnectionInfo connection_info_;
+ bool was_alternate_protocol_available_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebURLResponseExtraDataImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_WEBURLRESPONSE_EXTRADATA_IMPL_H_
diff --git a/chromium/content/child/worker_thread_task_runner.h b/chromium/content/child/worker_thread_task_runner.h
index 54b9ea0bc98..5acafbd81e5 100644
--- a/chromium/content/child/worker_thread_task_runner.h
+++ b/chromium/content/child/worker_thread_task_runner.h
@@ -22,13 +22,13 @@ class WorkerThreadTaskRunner : public base::TaskRunner {
static scoped_refptr<WorkerThreadTaskRunner> current();
// TaskRunner overrides.
- virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
- const base::Closure& task,
- base::TimeDelta delay) OVERRIDE;
- virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
+ bool RunsTasksOnCurrentThread() const override;
protected:
- virtual ~WorkerThreadTaskRunner();
+ ~WorkerThreadTaskRunner() override;
private:
const int worker_thread_id_;
diff --git a/chromium/content/common/BUILD.gn b/chromium/content/common/BUILD.gn
index 511027e3091..cfe291b724f 100644
--- a/chromium/content/common/BUILD.gn
+++ b/chromium/content/common/BUILD.gn
@@ -7,65 +7,93 @@ import("//build/config/ui.gni")
import("//content/common/common.gni")
import("//mojo/public/tools/bindings/mojom.gni")
+if (is_chromeos && use_x11 && cpu_arch != "arm") {
+ action("libva_generate_stubs") {
+ extra_header = "gpu/media/va_stub_header.fragment"
+
+ script = "../../tools/generate_stubs/generate_stubs.py"
+ sources = [ "gpu/media/va.sigs" ]
+ source_prereqs = [ extra_header ]
+ stubs_filename_root = "va_stubs"
+
+ outputs = [
+ "$target_gen_dir/gpu/media/$stubs_filename_root.cc",
+ "$target_gen_dir/gpu/media/$stubs_filename_root.h",
+ ]
+ args = [
+ "-i", rebase_path("$target_gen_dir/gpu/media", root_build_dir),
+ "-o", rebase_path("$target_gen_dir/gpu/media", root_build_dir),
+ "-t", "posix_stubs",
+ "-e", rebase_path(extra_header, root_build_dir),
+ "-s", stubs_filename_root,
+ "-p", "content/common/gpu/media",
+ ]
+
+ args += rebase_path(sources, root_build_dir)
+ }
+}
+
source_set("common") {
- # Only targets in the content tree can depend directly on this target.
- visibility = [ "//content/*" ]
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/common:common_sources" ]
sources = rebase_path(content_common_gypi_values.private_common_sources,
".", "//content")
- forward_dependent_configs_from = [
- "//gpu/command_buffer/common",
- "//third_party/WebKit/public:blink_headers",
- ]
-
configs += [
"//content:content_implementation",
- "//content:libjingle_stub_config",
]
+ public_deps = [
+ "//gpu/command_buffer/common",
+ "//third_party/WebKit/public:blink_headers",
+ ]
deps = [
"//base",
"//build/util:webkit_version",
"//components/tracing",
- "//gpu/command_buffer/common",
+ "//gpu/command_buffer/client:gles2_interface",
+ "//gpu/command_buffer/client:gpu_memory_buffer_manager",
"//net",
"//skia",
"//third_party/icu",
"//ui/accessibility",
"//ui/base",
+ "//ui/events/ipc",
"//ui/gfx",
"//ui/gfx/geometry",
+ "//ui/gfx/ipc",
+ "//ui/shell_dialogs",
"//url",
- "//third_party/WebKit/public:blink_headers",
- # TODO(GYP) convert these dependencies.
- #'../third_party/libjingle/libjingle.gyp:libjingle',
- #'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
+ "//third_party/libjingle",
]
if (!is_ios) {
deps += [
"//cc",
"//ipc",
- "//mojo/environment:chromium",
- "//mojo/system",
+ "//ipc/mojo",
# TODO: the dependency on gl_in_process_context should be decoupled from
# content and moved to android_webview. See crbug.com/365797.
"//gpu/command_buffer/client:gl_in_process_context",
"//gpu/command_buffer/client:gles2_c_lib",
+ "//gpu/command_buffer/client:gles2_cmd_helper",
"//gpu/command_buffer/client:gles2_implementation",
"//gpu/command_buffer/service",
"//gpu/ipc",
+ "//gpu/skia_bindings",
+ "//media",
+ "//media:shared_memory_support",
+ "//mojo/edk/system",
+ "//mojo/environment:chromium",
+ "//mojo/public/interfaces/application",
+ "//sandbox",
+ "//storage/browser",
+ "//storage/common",
+ "//third_party/WebKit/public:blink",
"//ui/gl",
- "//webkit/browser:storage",
- "//webkit/common",
- "//webkit/common:storage",
"//webkit/common/gpu",
- #'../gpu/gpu.gyp:gl_in_process_context',
- #'../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings',
- #'../media/media.gyp:media',
- #'../media/media.gyp:shared_memory_support',
- #'../third_party/WebKit/public/blink.gyp:blink',
]
}
@@ -92,10 +120,11 @@ source_set("common") {
"plugin_list_posix.cc",
]
- # TODO(GYP) enable when converted to GN.
- #deps += [
- # "//webkit:webkit_resources",
- #]
+ deps += [
+ "//content/app/resources",
+ "//content:resources",
+ "//third_party/WebKit/public:resources",
+ ]
libs += [ "QuartzCore.framework" ]
}
@@ -103,13 +132,14 @@ source_set("common") {
sources += [
"gpu/client/gpu_memory_buffer_impl_surface_texture.cc",
"gpu/client/gpu_memory_buffer_impl_surface_texture.h",
+ "gpu/gpu_memory_buffer_factory_surface_texture.cc",
+ "gpu/gpu_memory_buffer_factory_surface_texture.h",
]
- # TODO(GYP) enable when these targets are converted.
- #deps += [
- # "//content:content_jni_headers",
- # "//content:common_aidl",
- #]
+ deps += [
+ "//content/public/android:jni",
+ "//content/public/android:common_aidl",
+ ]
libs += [ "android" ]
}
@@ -123,9 +153,21 @@ source_set("common") {
sources -= [
"cursors/webcursor_ozone.cc",
"font_list_ozone.cc",
+ "gpu/gpu_memory_buffer_factory_ozone.cc",
+ ]
+ } else {
+ sources -= [
+ "gpu/gpu_memory_buffer_factory_linux.cc",
+ ]
+ deps += [
+ "//ui/ozone/gpu",
]
}
+ if (!use_aura) {
+ sources -= [ "cursors/webcursor_aura.cc" ]
+ }
+
if (!use_aura || !use_x11) {
sources -= [ "cursors/webcursor_aurax11.cc" ]
}
@@ -161,8 +203,16 @@ source_set("common") {
]
} else {
sources -= [
+ "pepper_file_util.cc",
+ "pepper_file_util.h",
+ "pepper_messages.h",
"pepper_plugin_list.cc",
"pepper_plugin_list.h",
+ "pepper_renderer_instance_data.cc",
+ "pepper_renderer_instance_data.h",
+ "plugin_list.cc",
+ "plugin_list.h",
+ "plugin_list_posix.cc",
"sandbox_util.cc",
]
}
@@ -172,10 +222,6 @@ source_set("common") {
"gpu/media/android_video_decode_accelerator.cc",
"gpu/media/android_video_decode_accelerator.h",
]
- deps += [
- # TODO(GYP) enable once supported in the GN build.
- #"//media",
- ]
if (enable_webrtc) {
deps += [ "//third_party/libyuv" ]
@@ -198,8 +244,6 @@ source_set("common") {
"gpu/media/v4l2_video_encode_accelerator.cc",
"gpu/media/v4l2_video_encode_accelerator.h",
]
- # TODO(GYP) enable once supported in the GN build.
- #deps += [ "//media" ]
libs = [ "EGL", "GLESv2" ]
} else { # !arm
sources += [
@@ -210,10 +254,20 @@ source_set("common") {
"gpu/media/vaapi_h264_decoder.h",
"gpu/media/vaapi_video_decode_accelerator.cc",
"gpu/media/vaapi_video_decode_accelerator.h",
+ "gpu/media/vaapi_video_encode_accelerator.cc",
+ "gpu/media/vaapi_video_encode_accelerator.h",
"gpu/media/vaapi_wrapper.cc",
"gpu/media/vaapi_wrapper.h",
+ ] + get_target_outputs(":libva_generate_stubs")
+ configs += [
+ "//third_party/libva:libva_config",
+ "//third_party/libyuv:libyuv_config",
+ ]
+ deps += [
+ ":libva_generate_stubs",
+ "//media",
+ "//third_party/libyuv",
]
- assert(false, "Implement generate_stubs for libva")
}
}
@@ -224,8 +278,6 @@ source_set("common") {
]
include_dirs += [ "//third_party/khronos" ]
deps += [
- # TODO(GYP) enable once supported in the GN build.
- #"//media",
"//ui/gl",
]
@@ -249,6 +301,8 @@ source_set("common") {
"sandbox_linux/bpf_ppapi_policy_linux.h",
"sandbox_linux/bpf_renderer_policy_linux.cc",
"sandbox_linux/bpf_renderer_policy_linux.h",
+ "sandbox_linux/bpf_utility_policy_linux.cc",
+ "sandbox_linux/bpf_utility_policy_linux.h",
"sandbox_linux/sandbox_bpf_base_policy_linux.cc",
"sandbox_linux/sandbox_bpf_base_policy_linux.h",
]
@@ -264,6 +318,12 @@ source_set("common") {
mojom("mojo_bindings") {
sources = [
- "web_ui_setup.mojom",
+ "geolocation_service.mojom",
+ "render_frame_setup.mojom",
+ ]
+
+ deps = [
+ "//content/public/common:mojo_bindings",
+ "//mojo/public/interfaces/application:application",
]
}
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index 388e1dbe70f..3a9551d0265 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -1,14 +1,14 @@
include_rules = [
"+media/audio",
"+media/base",
- "-webkit/browser",
- "-webkit/child",
+ "-storage/browser",
"-webkit/renderer",
# No inclusion of WebKit from the browser, other than strictly enum/POD,
# header-only types, and some selected common code.
"-third_party/WebKit",
"+third_party/WebKit/public/platform/WebBatteryStatus.h",
+ "+third_party/WebKit/public/platform/WebCircularGeofencingRegion.h",
"+third_party/WebKit/public/platform/WebCString.h",
"+third_party/WebKit/public/platform/WebDeviceMotionData.h",
"+third_party/WebKit/public/platform/WebDeviceOrientationData.h",
@@ -16,18 +16,23 @@ include_rules = [
"+third_party/WebKit/public/platform/WebFloatRect.h",
"+third_party/WebKit/public/platform/WebGamepad.h",
"+third_party/WebKit/public/platform/WebGamepads.h",
+ "+third_party/WebKit/public/platform/WebGeofencingEventType.h",
"+third_party/WebKit/public/platform/WebGraphicsContext3D.h",
"+third_party/WebKit/public/platform/WebHTTPBody.h",
"+third_party/WebKit/public/platform/WebIDBCursor.h",
"+third_party/WebKit/public/platform/WebIDBDatabase.h",
"+third_party/WebKit/public/platform/WebIDBTypes.h",
- "+third_party/WebKit/public/platform/WebLockOrientationCallback.h",
+ "+third_party/WebKit/public/platform/WebLockOrientationError.h",
+ "+third_party/WebKit/public/platform/WebNotificationPermission.h",
+ "+third_party/WebKit/public/platform/WebPushPermissionStatus.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenOrientationLockType.h",
"+third_party/WebKit/public/platform/WebScreenOrientationType.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
"+third_party/WebKit/public/platform/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/WebServiceWorkerEventResult.h",
+ "+third_party/WebKit/public/platform/WebServiceWorkerCacheError.h",
+ "+third_party/WebKit/public/platform/WebServiceWorkerResponseType.h",
"+third_party/WebKit/public/platform/WebServiceWorkerState.h",
"+third_party/WebKit/public/platform/WebStorageArea.h",
"+third_party/WebKit/public/platform/WebString.h",
diff --git a/chromium/content/common/OWNERS b/chromium/content/common/OWNERS
index a211f76d449..4bc5132b1a4 100644
--- a/chromium/content/common/OWNERS
+++ b/chromium/content/common/OWNERS
@@ -1,5 +1,4 @@
# For Linux sandboxing
-cevans@chromium.org
jln@chromium.org
# For security review of sandboxes
@@ -21,26 +20,45 @@ per-file plugin*=bauerb@chromium.org
# Changes to IPC messages require a security review to avoid introducing
# new sandbox escapes.
per-file *_message*.h=set noparent
-per-file *_message*.h=cevans@chromium.org
per-file *_message*.h=dcheng@chromium.org
per-file *_message*.h=inferno@chromium.org
per-file *_message*.h=jln@chromium.org
per-file *_message*.h=jschuh@chromium.org
per-file *_message*.h=kenrb@chromium.org
+per-file *_message*.h=mkwst@chromium.org
per-file *_message*.h=nasko@chromium.org
per-file *_message*.h=palmer@chromium.org
per-file *_message*.h=tsepez@chromium.org
+per-file *_message*.h=wfh@chromium.org
+
+per-file *_messages.cc=set noparent
+per-file *_messages.cc=dcheng@chromium.org
+per-file *_messages.cc=inferno@chromium.org
+per-file *_messages.cc=jln@chromium.org
+per-file *_messages.cc=jschuh@chromium.org
+per-file *_messages.cc=kenrb@chromium.org
+per-file *_messages.cc=mkwst@chromium.org
+per-file *_messages.cc=nasko@chromium.org
+per-file *_messages.cc=palmer@chromium.org
+per-file *_messages.cc=tsepez@chromium.org
+per-file *_messages.cc=wfh@chromium.org
per-file *param_traits*.h=set noparent
-per-file *param_traits*.h=cevans@chromium.org
per-file *param_traits*.h=dcheng@chromium.org
per-file *param_traits*.h=inferno@chromium.org
per-file *param_traits*.h=jln@chromium.org
per-file *param_traits*.h=jschuh@chromium.org
per-file *param_traits*.h=kenrb@chromium.org
+per-file *param_traits*.h=mkwst@chromium.org
per-file *param_traits*.h=nasko@chromium.org
per-file *param_traits*.h=palmer@chromium.org
per-file *param_traits*.h=tsepez@chromium.org
+per-file *param_traits*.h=wfh@chromium.org
+
+# Changes to Mojo interfaces require a security review to avoid
+# introducing new sandbox escapes.
+per-file *.mojom=set noparent
+per-file *.mojom=tsepez@chromium.org
# Accessibility
per-file accessibility_node_data.*=dmazzoni@chromium.org
@@ -53,3 +71,4 @@ per-file websocket.*=yhirano@chromium.org
# Compositor
per-file cc_messages_unittest.cc=danakj@chromium.org
+per-file cc_messages_perftest.cc=danakj@chromium.org
diff --git a/chromium/content/common/accessibility_messages.h b/chromium/content/common/accessibility_messages.h
index 3a9ccb7ee3a..69dfb51d3ae 100644
--- a/chromium/content/common/accessibility_messages.h
+++ b/chromium/content/common/accessibility_messages.h
@@ -17,6 +17,14 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_update.h"
+// Singly-included section for custom types.
+#ifndef CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
+#define CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
+
+typedef std::map<int32, int> FrameIDMap;
+
+#endif // CONTENT_COMMON_ACCESSIBILITY_MESSAGES_H_
+
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -55,6 +63,15 @@ IPC_STRUCT_BEGIN(AccessibilityHostMsg_EventParams)
// The tree update.
IPC_STRUCT_MEMBER(ui::AXTreeUpdate, update)
+ // Mapping from node id to routing id of its child frame - either the
+ // routing id of a RenderFrame or a RenderFrameProxy for an out-of-process
+ // iframe.
+ IPC_STRUCT_MEMBER(FrameIDMap, node_to_frame_routing_id_map)
+
+ // Mapping from node id to the browser plugin instance id of a child
+ // browser plugin.
+ IPC_STRUCT_MEMBER(FrameIDMap, node_to_browser_plugin_instance_id_map)
+
// Type of event.
IPC_STRUCT_MEMBER(ui::AXEvent, event_type)
@@ -71,6 +88,26 @@ IPC_STRUCT_BEGIN(AccessibilityHostMsg_LocationChangeParams)
IPC_STRUCT_MEMBER(gfx::Rect, new_location)
IPC_STRUCT_END()
+IPC_STRUCT_BEGIN(AccessibilityHostMsg_FindInPageResultParams)
+ // The find in page request id.
+ IPC_STRUCT_MEMBER(int, request_id)
+
+ // The index of the result match.
+ IPC_STRUCT_MEMBER(int, match_index)
+
+ // The id of the accessibility object for the start of the match range.
+ IPC_STRUCT_MEMBER(int, start_id)
+
+ // The character offset into the text of the start object.
+ IPC_STRUCT_MEMBER(int, start_offset)
+
+ // The id of the accessibility object for the end of the match range.
+ IPC_STRUCT_MEMBER(int, end_id)
+
+ // The character offset into the text of the end object.
+ IPC_STRUCT_MEMBER(int, end_offset)
+IPC_STRUCT_END()
+
// Messages sent from the browser to the renderer.
// Relay a request from assistive technology to set focus to a given node.
@@ -105,27 +142,61 @@ IPC_MESSAGE_ROUTED3(AccessibilityMsg_SetTextSelection,
int /* New start offset */,
int /* New end offset */)
+// Relay a request from assistive technology to set the value of an
+// editable text element.
+IPC_MESSAGE_ROUTED2(AccessibilityMsg_SetValue,
+ int /* object id */,
+ base::string16 /* Value */)
+
// Determine the accessibility object under a given point and reply with
// a AccessibilityHostMsg_HitTestResult with the same id.
IPC_MESSAGE_ROUTED1(AccessibilityMsg_HitTest,
- gfx::Point /* location to test */);
+ gfx::Point /* location to test */)
+
+// Relay a request from assistive technology to set accessibility focus
+// to a given node. On platforms where this is used (currently Android),
+// inline text boxes are only computed for the node with accessibility focus,
+// rather than for the whole tree.
+IPC_MESSAGE_ROUTED1(AccessibilityMsg_SetAccessibilityFocus,
+ int /* object id */)
// Tells the render view that a AccessibilityHostMsg_Events
// message was processed and it can send addition events.
IPC_MESSAGE_ROUTED0(AccessibilityMsg_Events_ACK)
-// Kill the renderer because we got a fatal error in the accessibility tree.
+// Tell the renderer to reset and send a new accessibility tree from
+// scratch because the browser is out of sync. It passes a sequential
+// reset token. This should be rare, and if we need reset the same renderer
+// too many times we just kill it. After sending a reset, the browser ignores
+// incoming accessibility IPCs until it receives one with the matching reset
+// token. Conversely, it ignores IPCs with a reset token if it was not
+// expecting a reset.
+IPC_MESSAGE_ROUTED1(AccessibilityMsg_Reset,
+ int /* reset token */)
+
+// Kill the renderer because we got a fatal error in the accessibility tree
+// and we've already reset too many times.
IPC_MESSAGE_ROUTED0(AccessibilityMsg_FatalError)
// Messages sent from the renderer to the browser.
// Sent to notify the browser about renderer accessibility events.
// The browser responds with a AccessibilityMsg_Events_ACK.
-IPC_MESSAGE_ROUTED1(
+// The second parameter, reset_token, is set if this IPC was sent in response
+// to a reset request from the browser. When the browser requests a reset,
+// it ignores incoming IPCs until it sees one with the correct reset token.
+// Any other time, it ignores IPCs with a reset token.
+IPC_MESSAGE_ROUTED2(
AccessibilityHostMsg_Events,
- std::vector<AccessibilityHostMsg_EventParams>)
+ std::vector<AccessibilityHostMsg_EventParams> /* events */,
+ int /* reset_token */)
// Sent to update the browser of the location of accessibility objects.
IPC_MESSAGE_ROUTED1(
AccessibilityHostMsg_LocationChanges,
std::vector<AccessibilityHostMsg_LocationChangeParams>)
+
+// Sent to update the browser of the location of accessibility objects.
+IPC_MESSAGE_ROUTED1(
+ AccessibilityHostMsg_FindInPageResult,
+ AccessibilityHostMsg_FindInPageResultParams)
diff --git a/chromium/content/common/accessibility_mode_enums.h b/chromium/content/common/accessibility_mode_enums.h
new file mode 100644
index 00000000000..ae059f26414
--- /dev/null
+++ b/chromium/content/common/accessibility_mode_enums.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 CONTENT_COMMON_ACCESSIBILITY_MODE_ENUMS_H_
+#define CONTENT_COMMON_ACCESSIBILITY_MODE_ENUMS_H_
+
+// Note: keep enums in content/browser/resources/accessibility/accessibility.js
+// in sync with these two enums.
+enum AccessibilityModeFlag {
+ // Accessibility updates are processed to create platform trees and events are
+ // passed to platform APIs in the browser.
+ AccessibilityModeFlagPlatform = 1 << 0,
+
+ // Accessibility is on, and the full tree is computed. If this flag is off,
+ // only limited information about editable text nodes is sent to the browser
+ // process. Useful for implementing limited UIA on tablets.
+ AccessibilityModeFlagFullTree = 1 << 1,
+};
+
+enum AccessibilityMode {
+ // All accessibility is off.
+ AccessibilityModeOff = 0,
+
+ // Renderer accessibility is on, and platform APIs are called.
+ AccessibilityModeComplete =
+ AccessibilityModeFlagPlatform | AccessibilityModeFlagFullTree,
+
+ // Renderer accessibility is on, and events are passed to any extensions
+ // requesting automation, but not to platform accessibility.
+ AccessibilityModeTreeOnly = AccessibilityModeFlagFullTree,
+};
+
+#endif // CONTENT_COMMON_ACCESSIBILITY_MODE_ENUMS_H_
diff --git a/chromium/content/common/android/OWNERS b/chromium/content/common/android/OWNERS
index 11d36ee9570..ac52ad02bfc 100644
--- a/chromium/content/common/android/OWNERS
+++ b/chromium/content/common/android/OWNERS
@@ -1,4 +1,3 @@
benm@chromium.org
-bulach@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/common/android/address_parser_internal.cc b/chromium/content/common/android/address_parser_internal.cc
index b1a440d3c8b..cc71b241ba4 100644
--- a/chromium/content/common/android/address_parser_internal.cc
+++ b/chromium/content/common/android/address_parser_internal.cc
@@ -340,7 +340,7 @@ bool FindStateStartingInWord(WordList* words,
};
DCHECK_EQ(state_names_accumulative[arraysize(state_names_accumulative) - 1],
- static_cast<int>(ARRAYSIZE_UNSAFE(state_names)));
+ static_cast<int>(arraysize(state_names)));
const Word& first_word = words->at(state_first_word);
int length = first_word.end - first_word.begin;
@@ -590,7 +590,7 @@ bool IsValidLocationName(const Word& word) {
DCHECK_EQ(
location_names_accumulative[arraysize(location_names_accumulative) - 1],
- static_cast<int>(ARRAYSIZE_UNSAFE(location_names)));
+ static_cast<int>(arraysize(location_names)));
if (!IsAsciiAlpha(*word.begin))
return false;
diff --git a/chromium/content/common/android/gin_java_bridge_errors.cc b/chromium/content/common/android/gin_java_bridge_errors.cc
new file mode 100644
index 00000000000..b2458cd0354
--- /dev/null
+++ b/chromium/content/common/android/gin_java_bridge_errors.cc
@@ -0,0 +1,35 @@
+// Copyright 2014 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 "content/common/android/gin_java_bridge_errors.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+const char* GinJavaBridgeErrorToString(GinJavaBridgeError error) {
+ switch (error) {
+ case kGinJavaBridgeNoError:
+ return "No error";
+ case kGinJavaBridgeUnknownObjectId:
+ return "Unknown Java object ID";
+ case kGinJavaBridgeObjectIsGone:
+ return "Java object is gone";
+ case kGinJavaBridgeMethodNotFound:
+ return "Method not found";
+ case kGinJavaBridgeAccessToObjectGetClassIsBlocked:
+ return "Access to java.lang.Object.getClass is blocked";
+ case kGinJavaBridgeJavaExceptionRaised:
+ return "Java exception was raised during method invocation";
+ case kGinJavaBridgeNonAssignableTypes:
+ return "The type of the object passed to the method is incompatible "
+ "with the type of method's argument";
+ case kGinJavaBridgeRenderFrameDeleted:
+ return "RenderFrame has been deleted";
+ }
+ NOTREACHED();
+ return "Unknown error";
+}
+
+} // namespace content
diff --git a/chromium/content/common/android/gin_java_bridge_errors.h b/chromium/content/common/android/gin_java_bridge_errors.h
new file mode 100644
index 00000000000..05ed8023786
--- /dev/null
+++ b/chromium/content/common/android/gin_java_bridge_errors.h
@@ -0,0 +1,28 @@
+// Copyright 2014 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 CONTENT_COMMON_ANDROID_GIN_JAVA_BRIDGE_ERRORS_H_
+#define CONTENT_COMMON_ANDROID_GIN_JAVA_BRIDGE_ERRORS_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+enum GinJavaBridgeError {
+ kGinJavaBridgeNoError = 0,
+ kGinJavaBridgeUnknownObjectId,
+ kGinJavaBridgeObjectIsGone,
+ kGinJavaBridgeMethodNotFound,
+ kGinJavaBridgeAccessToObjectGetClassIsBlocked,
+ kGinJavaBridgeJavaExceptionRaised,
+ kGinJavaBridgeNonAssignableTypes,
+ kGinJavaBridgeRenderFrameDeleted,
+ kGinJavaBridgeErrorLast = kGinJavaBridgeRenderFrameDeleted
+};
+
+CONTENT_EXPORT const char* GinJavaBridgeErrorToString(GinJavaBridgeError error);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ANDROID_GIN_JAVA_BRIDGE_ERRORS_H_
diff --git a/chromium/content/common/android/surface_texture_lookup.cc b/chromium/content/common/android/surface_texture_lookup.cc
deleted file mode 100644
index ee6715d3d8d..00000000000
--- a/chromium/content/common/android/surface_texture_lookup.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2014 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 "content/common/android/surface_texture_lookup.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-namespace {
-SurfaceTextureLookup* g_instance = NULL;
-} // namespace
-
-// static
-SurfaceTextureLookup* SurfaceTextureLookup::GetInstance() {
- DCHECK(g_instance);
- return g_instance;
-}
-
-// static
-void SurfaceTextureLookup::InitInstance(SurfaceTextureLookup* instance) {
- DCHECK(!g_instance || !instance);
- g_instance = instance;
-}
-
-} // namespace content
diff --git a/chromium/content/common/android/surface_texture_lookup.h b/chromium/content/common/android/surface_texture_lookup.h
deleted file mode 100644
index a1ad0fb29e5..00000000000
--- a/chromium/content/common/android/surface_texture_lookup.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 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 CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_LOOKUP_H_
-#define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_LOOKUP_H_
-
-#include "ui/gfx/native_widget_types.h"
-
-namespace content {
-
-class SurfaceTextureLookup {
- public:
- static SurfaceTextureLookup* GetInstance();
- static void InitInstance(SurfaceTextureLookup* instance);
-
- virtual gfx::AcceleratedWidget AcquireNativeWidget(int primary_id,
- int secondary_id) = 0;
-
- protected:
- virtual ~SurfaceTextureLookup() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_LOOKUP_H_
diff --git a/chromium/content/common/android/surface_texture_manager.cc b/chromium/content/common/android/surface_texture_manager.cc
new file mode 100644
index 00000000000..8062964e057
--- /dev/null
+++ b/chromium/content/common/android/surface_texture_manager.cc
@@ -0,0 +1,28 @@
+// Copyright 2014 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 "content/common/android/surface_texture_manager.h"
+
+#include "base/logging.h"
+
+namespace content {
+namespace {
+
+SurfaceTextureManager* g_instance = NULL;
+
+} // namespace
+
+// static
+SurfaceTextureManager* SurfaceTextureManager::GetInstance() {
+ DCHECK(g_instance);
+ return g_instance;
+}
+
+// static
+void SurfaceTextureManager::InitInstance(SurfaceTextureManager* instance) {
+ DCHECK(!g_instance || !instance);
+ g_instance = instance;
+}
+
+} // namespace content
diff --git a/chromium/content/common/android/surface_texture_manager.h b/chromium/content/common/android/surface_texture_manager.h
new file mode 100644
index 00000000000..3227f019599
--- /dev/null
+++ b/chromium/content/common/android/surface_texture_manager.h
@@ -0,0 +1,41 @@
+// Copyright 2014 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 CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_MANAGER_H_
+#define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_MANAGER_H_
+
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class SurfaceTexture;
+}
+
+namespace content {
+
+class SurfaceTextureManager {
+ public:
+ static SurfaceTextureManager* GetInstance();
+ static void InitInstance(SurfaceTextureManager* instance);
+
+ // Register a surface texture for use in another process.
+ virtual void RegisterSurfaceTexture(int surface_texture_id,
+ int client_id,
+ gfx::SurfaceTexture* surface_texture) = 0;
+
+ // Unregister a surface texture previously registered for use in another
+ // process.
+ virtual void UnregisterSurfaceTexture(int surface_texture_id,
+ int client_id) = 0;
+
+ // Acquire native widget for a registered surface texture.
+ virtual gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture(
+ int surface_texture_id) = 0;
+
+ protected:
+ virtual ~SurfaceTextureManager() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_MANAGER_H_
diff --git a/chromium/content/common/appcache_interfaces.cc b/chromium/content/common/appcache_interfaces.cc
new file mode 100644
index 00000000000..f9f9a05b3a7
--- /dev/null
+++ b/chromium/content/common/appcache_interfaces.cc
@@ -0,0 +1,139 @@
+// Copyright (c) 2012 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 "content/common/appcache_interfaces.h"
+
+#include <set>
+
+#include "base/strings/string_util.h"
+#include "net/url_request/url_request.h"
+#include "url/gurl.h"
+
+namespace content {
+
+const char kHttpScheme[] = "http";
+const char kHttpsScheme[] = "https";
+const char kDevToolsScheme[] = "chrome-devtools";
+const char kHttpGETMethod[] = "GET";
+const char kHttpHEADMethod[] = "HEAD";
+
+const char kEnableExecutableHandlers[] = "enable-appcache-executable-handlers";
+
+const base::FilePath::CharType kAppCacheDatabaseName[] =
+ FILE_PATH_LITERAL("Index");
+
+AppCacheInfo::AppCacheInfo()
+ : cache_id(kAppCacheNoCacheId),
+ group_id(0),
+ status(APPCACHE_STATUS_UNCACHED),
+ size(0),
+ is_complete(false) {
+}
+
+AppCacheInfo::~AppCacheInfo() {
+}
+
+AppCacheResourceInfo::AppCacheResourceInfo()
+ : url(),
+ size(0),
+ is_master(false),
+ is_manifest(false),
+ is_intercept(false),
+ is_fallback(false),
+ is_foreign(false),
+ is_explicit(false),
+ response_id(kAppCacheNoResponseId) {
+}
+
+AppCacheResourceInfo::~AppCacheResourceInfo() {
+}
+
+AppCacheErrorDetails::AppCacheErrorDetails()
+ : message(),
+ reason(APPCACHE_UNKNOWN_ERROR),
+ url(),
+ status(0),
+ is_cross_origin(false) {}
+
+AppCacheErrorDetails::AppCacheErrorDetails(
+ std::string in_message,
+ AppCacheErrorReason in_reason,
+ GURL in_url,
+ int in_status,
+ bool in_is_cross_origin)
+ : message(in_message),
+ reason(in_reason),
+ url(in_url),
+ status(in_status),
+ is_cross_origin(in_is_cross_origin) {}
+
+AppCacheErrorDetails::~AppCacheErrorDetails() {}
+
+AppCacheNamespace::AppCacheNamespace()
+ : type(APPCACHE_FALLBACK_NAMESPACE),
+ is_pattern(false),
+ is_executable(false) {
+}
+
+AppCacheNamespace::AppCacheNamespace(
+ AppCacheNamespaceType type, const GURL& url, const GURL& target,
+ bool is_pattern)
+ : type(type),
+ namespace_url(url),
+ target_url(target),
+ is_pattern(is_pattern),
+ is_executable(false) {
+}
+
+AppCacheNamespace::AppCacheNamespace(
+ AppCacheNamespaceType type, const GURL& url, const GURL& target,
+ bool is_pattern, bool is_executable)
+ : type(type),
+ namespace_url(url),
+ target_url(target),
+ is_pattern(is_pattern),
+ is_executable(is_executable) {
+}
+
+AppCacheNamespace::~AppCacheNamespace() {
+}
+
+bool AppCacheNamespace::IsMatch(const GURL& url) const {
+ if (is_pattern) {
+ // We have to escape '?' characters since MatchPattern also treats those
+ // as wildcards which we don't want here, we only do '*'s.
+ std::string pattern = namespace_url.spec();
+ if (namespace_url.has_query())
+ ReplaceSubstringsAfterOffset(&pattern, 0, "?", "\\?");
+ return MatchPattern(url.spec(), pattern);
+ }
+ return StartsWithASCII(url.spec(), namespace_url.spec(), true);
+}
+
+bool IsSchemeSupportedForAppCache(const GURL& url) {
+ bool supported = url.SchemeIs(kHttpScheme) || url.SchemeIs(kHttpsScheme) ||
+ url.SchemeIs(kDevToolsScheme);
+
+#ifndef NDEBUG
+ // TODO(michaeln): It would be really nice if this could optionally work for
+ // file and filesystem urls too to help web developers experiment and test
+ // their apps, perhaps enabled via a cmd line flag or some other developer
+ // tool setting. Unfortunately file scheme net::URLRequests don't produce the
+ // same signalling (200 response codes, headers) as http URLRequests, so this
+ // doesn't work just yet.
+ // supported |= url.SchemeIsFile();
+#endif
+ return supported;
+}
+
+bool IsMethodSupportedForAppCache(const std::string& method) {
+ return (method == kHttpGETMethod) || (method == kHttpHEADMethod);
+}
+
+bool IsSchemeAndMethodSupportedForAppCache(const net::URLRequest* request) {
+ return IsSchemeSupportedForAppCache(request->url()) &&
+ IsMethodSupportedForAppCache(request->method());
+}
+
+} // namespace content
diff --git a/chromium/content/common/appcache_interfaces.h b/chromium/content/common/appcache_interfaces.h
new file mode 100644
index 00000000000..7199fbb1330
--- /dev/null
+++ b/chromium/content/common/appcache_interfaces.h
@@ -0,0 +1,188 @@
+// Copyright (c) 2012 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 CONTENT_COMMON_APPCACHE_APPCACHE_INTERFACES_H_
+#define CONTENT_COMMON_APPCACHE_APPCACHE_INTERFACES_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "content/public/common/appcache_info.h"
+
+namespace net {
+class URLRequest;
+}
+
+namespace content {
+
+// Defines constants, types, and abstract classes used in the main
+// process and in child processes.
+
+enum AppCacheEventID {
+ APPCACHE_CHECKING_EVENT,
+ APPCACHE_ERROR_EVENT,
+ APPCACHE_NO_UPDATE_EVENT,
+ APPCACHE_DOWNLOADING_EVENT,
+ APPCACHE_PROGRESS_EVENT,
+ APPCACHE_UPDATE_READY_EVENT,
+ APPCACHE_CACHED_EVENT,
+ APPCACHE_OBSOLETE_EVENT,
+ APPCACHE_EVENT_ID_LAST = APPCACHE_OBSOLETE_EVENT
+};
+
+// Temporarily renumber them in wierd way, to help remove LOG_TIP from WebKit
+enum AppCacheLogLevel {
+ APPCACHE_LOG_DEBUG = 4,
+ APPCACHE_LOG_INFO = 1,
+ APPCACHE_LOG_WARNING = 2,
+ APPCACHE_LOG_ERROR = 3,
+};
+
+enum AppCacheNamespaceType {
+ APPCACHE_FALLBACK_NAMESPACE,
+ APPCACHE_INTERCEPT_NAMESPACE,
+ APPCACHE_NETWORK_NAMESPACE
+};
+
+enum AppCacheErrorReason {
+ APPCACHE_MANIFEST_ERROR,
+ APPCACHE_SIGNATURE_ERROR,
+ APPCACHE_RESOURCE_ERROR,
+ APPCACHE_CHANGED_ERROR,
+ APPCACHE_ABORT_ERROR,
+ APPCACHE_QUOTA_ERROR,
+ APPCACHE_POLICY_ERROR,
+ APPCACHE_UNKNOWN_ERROR,
+ APPCACHE_ERROR_REASON_LAST = APPCACHE_UNKNOWN_ERROR
+};
+
+// Type to hold information about a single appcache resource.
+struct CONTENT_EXPORT AppCacheResourceInfo {
+ AppCacheResourceInfo();
+ ~AppCacheResourceInfo();
+
+ GURL url;
+ int64 size;
+ bool is_master;
+ bool is_manifest;
+ bool is_intercept;
+ bool is_fallback;
+ bool is_foreign;
+ bool is_explicit;
+ int64 response_id;
+};
+
+struct CONTENT_EXPORT AppCacheErrorDetails {
+ AppCacheErrorDetails();
+ AppCacheErrorDetails(std::string message,
+ AppCacheErrorReason reason,
+ GURL url,
+ int status,
+ bool is_cross_origin);
+ ~AppCacheErrorDetails();
+
+ std::string message;
+ AppCacheErrorReason reason;
+ GURL url;
+ int status;
+ bool is_cross_origin;
+};
+
+typedef std::vector<AppCacheResourceInfo> AppCacheResourceInfoVector;
+
+struct CONTENT_EXPORT AppCacheNamespace {
+ AppCacheNamespace(); // Type is APPCACHE_FALLBACK_NAMESPACE by default.
+ AppCacheNamespace(AppCacheNamespaceType type, const GURL& url,
+ const GURL& target, bool is_pattern);
+ AppCacheNamespace(AppCacheNamespaceType type, const GURL& url,
+ const GURL& target, bool is_pattern, bool is_executable);
+ ~AppCacheNamespace();
+
+ bool IsMatch(const GURL& url) const;
+
+ AppCacheNamespaceType type;
+ GURL namespace_url;
+ GURL target_url;
+ bool is_pattern;
+ bool is_executable;
+};
+
+typedef std::vector<AppCacheNamespace> AppCacheNamespaceVector;
+
+// Interface used by backend (browser-process) to talk to frontend (renderer).
+class CONTENT_EXPORT AppCacheFrontend {
+ public:
+ virtual void OnCacheSelected(
+ int host_id, const AppCacheInfo& info) = 0;
+ virtual void OnStatusChanged(const std::vector<int>& host_ids,
+ AppCacheStatus status) = 0;
+ virtual void OnEventRaised(const std::vector<int>& host_ids,
+ AppCacheEventID event_id) = 0;
+ virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
+ const GURL& url,
+ int num_total, int num_complete) = 0;
+ virtual void OnErrorEventRaised(
+ const std::vector<int>& host_ids,
+ const AppCacheErrorDetails& details) = 0;
+ virtual void OnContentBlocked(int host_id,
+ const GURL& manifest_url) = 0;
+ virtual void OnLogMessage(int host_id, AppCacheLogLevel log_level,
+ const std::string& message) = 0;
+ virtual ~AppCacheFrontend() {}
+};
+
+// Interface used by frontend (renderer) to talk to backend (browser-process).
+class CONTENT_EXPORT AppCacheBackend {
+ public:
+ virtual void RegisterHost(int host_id) = 0;
+ virtual void UnregisterHost(int host_id) = 0;
+ virtual void SetSpawningHostId(int host_id, int spawning_host_id) = 0;
+ virtual void SelectCache(int host_id,
+ const GURL& document_url,
+ const int64 cache_document_was_loaded_from,
+ const GURL& manifest_url) = 0;
+ virtual void SelectCacheForWorker(
+ int host_id,
+ int parent_process_id,
+ int parent_host_id) = 0;
+ virtual void SelectCacheForSharedWorker(
+ int host_id,
+ int64 appcache_id) = 0;
+ virtual void MarkAsForeignEntry(int host_id, const GURL& document_url,
+ int64 cache_document_was_loaded_from) = 0;
+ virtual AppCacheStatus GetStatus(int host_id) = 0;
+ virtual bool StartUpdate(int host_id) = 0;
+ virtual bool SwapCache(int host_id) = 0;
+ virtual void GetResourceList(
+ int host_id, std::vector<AppCacheResourceInfo>* resource_infos) = 0;
+
+ protected:
+ virtual ~AppCacheBackend() {}
+};
+
+// Useful string constants.
+// Note: These are also defined elsewhere in the chrome code base in
+// url_contants.h .cc, however the content library can not have
+// any dependencies on the chrome library, so we can't use them in here.
+CONTENT_EXPORT extern const char kHttpScheme[];
+CONTENT_EXPORT extern const char kHttpsScheme[];
+CONTENT_EXPORT extern const char kHttpGETMethod[];
+CONTENT_EXPORT extern const char kHttpHEADMethod[];
+
+// CommandLine flag to turn this experimental feature on.
+CONTENT_EXPORT extern const char kEnableExecutableHandlers[];
+
+CONTENT_EXPORT bool IsSchemeSupportedForAppCache(const GURL& url);
+CONTENT_EXPORT bool IsMethodSupportedForAppCache(
+ const std::string& method);
+CONTENT_EXPORT bool IsSchemeAndMethodSupportedForAppCache(
+ const net::URLRequest* request);
+
+CONTENT_EXPORT extern const base::FilePath::CharType
+ kAppCacheDatabaseName[];
+
+} // namespace
+
+#endif // CONTENT_COMMON_APPCACHE_APPCACHE_INTERFACES_H_
diff --git a/chromium/content/common/appcache_messages.h b/chromium/content/common/appcache_messages.h
index 8ad8fd5a5d7..15d37582d51 100644
--- a/chromium/content/common/appcache_messages.h
+++ b/chromium/content/common/appcache_messages.h
@@ -5,18 +5,18 @@
// Multiply-included message file, hence no include guard.
#include "ipc/ipc_message_macros.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
+#include "content/common/appcache_interfaces.h"
#define IPC_MESSAGE_START AppCacheMsgStart
-IPC_ENUM_TRAITS_MAX_VALUE(appcache::AppCacheEventID,
- appcache::APPCACHE_EVENT_ID_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(appcache::AppCacheStatus,
- appcache::APPCACHE_STATUS_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(appcache::AppCacheErrorReason,
- appcache::APPCACHE_ERROR_REASON_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::AppCacheEventID,
+ content::APPCACHE_EVENT_ID_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::AppCacheStatus,
+ content::APPCACHE_STATUS_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::AppCacheErrorReason,
+ content::APPCACHE_ERROR_REASON_LAST)
-IPC_STRUCT_TRAITS_BEGIN(appcache::AppCacheInfo)
+IPC_STRUCT_TRAITS_BEGIN(content::AppCacheInfo)
IPC_STRUCT_TRAITS_MEMBER(manifest_url)
IPC_STRUCT_TRAITS_MEMBER(creation_time)
IPC_STRUCT_TRAITS_MEMBER(last_update_time)
@@ -28,7 +28,7 @@ IPC_STRUCT_TRAITS_BEGIN(appcache::AppCacheInfo)
IPC_STRUCT_TRAITS_MEMBER(is_complete)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(appcache::AppCacheResourceInfo)
+IPC_STRUCT_TRAITS_BEGIN(content::AppCacheResourceInfo)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(size)
IPC_STRUCT_TRAITS_MEMBER(is_master)
@@ -38,7 +38,7 @@ IPC_STRUCT_TRAITS_BEGIN(appcache::AppCacheResourceInfo)
IPC_STRUCT_TRAITS_MEMBER(is_explicit)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(appcache::AppCacheErrorDetails)
+IPC_STRUCT_TRAITS_BEGIN(content::AppCacheErrorDetails)
IPC_STRUCT_TRAITS_MEMBER(message)
IPC_STRUCT_TRAITS_MEMBER(reason)
IPC_STRUCT_TRAITS_MEMBER(url)
@@ -96,7 +96,7 @@ IPC_MESSAGE_CONTROL3(AppCacheHostMsg_MarkAsForeignEntry,
// Returns the status of the appcache associated with host_id.
IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheHostMsg_GetStatus,
int /* host_id */,
- appcache::AppCacheStatus)
+ content::AppCacheStatus)
// Initiates an update of the appcache associated with host_id.
IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheHostMsg_StartUpdate,
@@ -111,7 +111,7 @@ IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheHostMsg_SwapCache,
// Gets resource list from appcache synchronously.
IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheHostMsg_GetResourceList,
int /* host_id in*/,
- std::vector<appcache::AppCacheResourceInfo>
+ std::vector<content::AppCacheResourceInfo>
/* resources out */)
@@ -121,18 +121,18 @@ IPC_SYNC_MESSAGE_CONTROL1_1(AppCacheHostMsg_GetResourceList,
// a particular host. This is sent in reply to AppCacheHostMsg_SelectCache.
IPC_MESSAGE_CONTROL2(AppCacheMsg_CacheSelected,
int /* host_id */,
- appcache::AppCacheInfo)
+ content::AppCacheInfo)
// Notifies the renderer of an AppCache status change.
IPC_MESSAGE_CONTROL2(AppCacheMsg_StatusChanged,
std::vector<int> /* host_ids */,
- appcache::AppCacheStatus)
+ content::AppCacheStatus)
// Notifies the renderer of an AppCache event other than the
// progress event which has a seperate message.
IPC_MESSAGE_CONTROL2(AppCacheMsg_EventRaised,
std::vector<int> /* host_ids */,
- appcache::AppCacheEventID)
+ content::AppCacheEventID)
// Notifies the renderer of an AppCache progress event.
IPC_MESSAGE_CONTROL4(AppCacheMsg_ProgressEventRaised,
@@ -144,7 +144,7 @@ IPC_MESSAGE_CONTROL4(AppCacheMsg_ProgressEventRaised,
// Notifies the renderer of an AppCache error event.
IPC_MESSAGE_CONTROL2(AppCacheMsg_ErrorEventRaised,
std::vector<int> /* host_ids */,
- appcache::AppCacheErrorDetails)
+ content::AppCacheErrorDetails)
// Notifies the renderer of an AppCache logging message.
IPC_MESSAGE_CONTROL3(AppCacheMsg_LogMessage,
diff --git a/chromium/content/common/battery_status_messages.h b/chromium/content/common/battery_status_messages.h
deleted file mode 100644
index dd09ed0ca24..00000000000
--- a/chromium/content/common/battery_status_messages.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 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.
-
-// IPC messages for Battery Status API.
-// Multiply-included message file, hence no include guard.
-
-#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatus.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START BatteryStatusMsgStart
-
-IPC_STRUCT_TRAITS_BEGIN(blink::WebBatteryStatus)
- IPC_STRUCT_TRAITS_MEMBER(charging)
- IPC_STRUCT_TRAITS_MEMBER(chargingTime)
- IPC_STRUCT_TRAITS_MEMBER(dischargingTime)
- IPC_STRUCT_TRAITS_MEMBER(level)
-IPC_STRUCT_TRAITS_END()
-
-// Notifies the browser process that the renderer process wants
-// to listen to battery status updates.
-IPC_MESSAGE_CONTROL0(BatteryStatusHostMsg_Start)
-
-// Notifies the render process with new battery status data.
-IPC_MESSAGE_CONTROL1(BatteryStatusMsg_DidChange,
- blink::WebBatteryStatus /* new status */)
-
-// Notifies the browser process that the renderer process is not using the
-// battery status data anymore.
-IPC_MESSAGE_CONTROL0(BatteryStatusHostMsg_Stop)
diff --git a/chromium/content/common/browser_plugin/OWNERS b/chromium/content/common/browser_plugin/OWNERS
index ee4b51e55d9..bba0da48bd2 100644
--- a/chromium/content/common/browser_plugin/OWNERS
+++ b/chromium/content/common/browser_plugin/OWNERS
@@ -3,12 +3,13 @@ lazyboy@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/browser_plugin/browser_plugin_constants.cc b/chromium/content/common/browser_plugin/browser_plugin_constants.cc
index 96b4a5f879e..93fa6623b50 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_constants.cc
+++ b/chromium/content/common/browser_plugin/browser_plugin_constants.cc
@@ -8,31 +8,8 @@ namespace content {
namespace browser_plugin {
-// Internal method bindings.
-const char kMethodInternalAttach[] = "-internal-attach";
-
-// Attributes.
-const char kAttributeAllowTransparency[] = "allowtransparency";
-const char kAttributeAutoSize[] = "autosize";
-const char kAttributeContentWindow[] = "contentWindow";
-const char kAttributeMaxHeight[] = "maxheight";
-const char kAttributeMaxWidth[] = "maxwidth";
-const char kAttributeMinHeight[] = "minheight";
-const char kAttributeMinWidth[] = "minwidth";
-const char kAttributeName[] = "name";
-const char kAttributePartition[] = "partition";
-const char kAttributeSrc[] = "src";
-
-// Parameters/properties on events.
-const char kWindowID[] = "windowId";
-
-// Error messages.
-const char kErrorCannotRemovePartition[] =
- "Cannot remove partition attribute after navigating.";
-
// Other.
const int kInstanceIDNone = 0;
-const int kInvalidPermissionRequestID = 0;
} // namespace browser_plugin
diff --git a/chromium/content/common/browser_plugin/browser_plugin_constants.h b/chromium/content/common/browser_plugin/browser_plugin_constants.h
index 7c408d3c413..812d07f8a4a 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_constants.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_constants.h
@@ -9,30 +9,8 @@ namespace content {
namespace browser_plugin {
-// Internal method bindings.
-extern const char kMethodInternalAttach[];
-
-// Attributes.
-extern const char kAttributeAllowTransparency[];
-extern const char kAttributeAutoSize[];
-extern const char kAttributeContentWindow[];
-extern const char kAttributeMaxHeight[];
-extern const char kAttributeMaxWidth[];
-extern const char kAttributeMinHeight[];
-extern const char kAttributeMinWidth[];
-extern const char kAttributeName[];
-extern const char kAttributePartition[];
-extern const char kAttributeSrc[];
-
-// Parameters/properties on events.
-extern const char kWindowID[];
-
-// Error messages.
-extern const char kErrorCannotRemovePartition[];
-
// Other.
extern const int kInstanceIDNone;
-extern const int kInvalidPermissionRequestID;
} // namespace browser_plugin
diff --git a/chromium/content/common/browser_plugin/browser_plugin_messages.h b/chromium/content/common/browser_plugin/browser_plugin_messages.h
index 74cb01d40c2..61fbdefaf71 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_messages.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_messages.h
@@ -8,7 +8,6 @@
#include "base/basictypes.h"
#include "base/process/process.h"
-#include "base/values.h"
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/cursors/webcursor.h"
@@ -23,6 +22,7 @@
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -36,15 +36,7 @@
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebDragStatus, blink::WebDragStatusLast)
-IPC_STRUCT_BEGIN(BrowserPluginHostMsg_AutoSize_Params)
- IPC_STRUCT_MEMBER(bool, enable)
- IPC_STRUCT_MEMBER(gfx::Size, max_size)
- IPC_STRUCT_MEMBER(gfx::Size, min_size)
-IPC_STRUCT_END()
-
IPC_STRUCT_BEGIN(BrowserPluginHostMsg_ResizeGuest_Params)
- // Indicates whether the parameters have been populated or not.
- IPC_STRUCT_MEMBER(bool, size_changed)
// The new size of guest view.
IPC_STRUCT_MEMBER(gfx::Size, view_size)
// Indicates the scale factor of the embedder WebView.
@@ -58,28 +50,11 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(BrowserPluginHostMsg_Attach_Params)
IPC_STRUCT_MEMBER(bool, focused)
IPC_STRUCT_MEMBER(bool, visible)
- IPC_STRUCT_MEMBER(bool, opaque)
- IPC_STRUCT_MEMBER(GURL, embedder_frame_url)
- IPC_STRUCT_MEMBER(BrowserPluginHostMsg_AutoSize_Params, auto_size_params)
IPC_STRUCT_MEMBER(BrowserPluginHostMsg_ResizeGuest_Params,
resize_guest_params)
IPC_STRUCT_MEMBER(gfx::Point, origin)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(BrowserPluginMsg_UpdateRect_Params)
- // The size of the RenderView when this message was generated. This is
- // included so the host knows how large the view is from the perspective of
- // the renderer process. This is necessary in case a resize operation is in
- // progress. If auto-resize is enabled, this should update the corresponding
- // view size.
- IPC_STRUCT_MEMBER(gfx::Size, view_size)
-
- // All the above coordinates are in DIP. This is the scale factor needed
- // to convert them to pixels.
- IPC_STRUCT_MEMBER(float, scale_factor)
-
- // Is this UpdateRect an ACK to a resize request?
- IPC_STRUCT_MEMBER(bool, is_resize_ack)
+ // Whether the browser plugin is a full page plugin document.
+ IPC_STRUCT_MEMBER(bool, is_full_page_plugin)
IPC_STRUCT_END()
// Browser plugin messages
@@ -90,19 +65,19 @@ IPC_STRUCT_END()
// This message is sent from BrowserPlugin to BrowserPluginGuest to issue an
// edit command.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ExecuteEditCommand,
- int /* instance_id */,
- std::string /* command */)
+ int /* browser_plugin_instance_id */,
+ std::string /* command */)
// This message must be sent just before sending a key event.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
std::vector<content::EditCommand> /* edit_commands */)
// This message is sent from BrowserPlugin to BrowserPluginGuest whenever IME
// composition state is updated.
IPC_MESSAGE_ROUTED5(
BrowserPluginHostMsg_ImeSetComposition,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
std::string /* text */,
std::vector<blink::WebCompositionUnderline> /* underlines */,
int /* selectiont_start */,
@@ -111,75 +86,50 @@ IPC_MESSAGE_ROUTED5(
// This message is sent from BrowserPlugin to BrowserPluginGuest to notify that
// confirming the current composition is requested.
IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_ImeConfirmComposition,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
std::string /* text */,
bool /* keep selection */)
// Deletes the current selection plus the specified number of characters before
// and after the selection or caret.
IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_ExtendSelectionAndDelete,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
int /* before */,
int /* after */)
-// This message is sent to the browser process to enable or disable autosize
-// mode.
-IPC_MESSAGE_ROUTED3(
- BrowserPluginHostMsg_SetAutoSize,
- int /* instance_id */,
- BrowserPluginHostMsg_AutoSize_Params /* auto_size_params */,
- BrowserPluginHostMsg_ResizeGuest_Params /* resize_guest_params */)
-
// This message is sent to the browser process to indicate that a BrowserPlugin
-// has taken ownership of the lifetime of the guest of the given |instance_id|.
-// |params| is the state of the BrowserPlugin taking ownership of
-// the guest. If a guest doesn't already exist with the given |instance_id|,
-// a new one will be created.
-IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_Attach,
- int /* instance_id */,
- BrowserPluginHostMsg_Attach_Params /* params */,
- base::DictionaryValue /* extra_params */)
+// has taken ownership of the lifetime of the guest of the given
+// |browser_plugin_instance_id|. |params| is the state of the BrowserPlugin
+// taking ownership of the guest.
+IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_Attach,
+ int /* browser_plugin_instance_id */,
+ BrowserPluginHostMsg_Attach_Params /* params */)
// Tells the guest to focus or defocus itself.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetFocus,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
bool /* enable */)
// Sends an input event to the guest.
IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_HandleInputEvent,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
gfx::Rect /* guest_window_rect */,
IPC::WebInputEventPointer /* event */)
-IPC_MESSAGE_ROUTED3(BrowserPluginHostMsg_CopyFromCompositingSurfaceAck,
- int /* instance_id */,
- int /* request_id */,
- SkBitmap);
-
// Notify the guest renderer that some resources given to the embededer
// are not used any more.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ReclaimCompositorResources,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
FrameHostMsg_ReclaimCompositorResources_Params /* params */)
-// When a BrowserPlugin has been removed from the embedder's DOM, it informs
-// the browser process to cleanup the guest.
-IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_PluginDestroyed,
- int /* instance_id */)
-
// Tells the guest it has been shown or hidden.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetVisibility,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
bool /* visible */)
-// Tells the guest to change its background opacity.
-IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_SetContentsOpaque,
- int /* instance_id */,
- bool /* opaque */)
-
// Tells the guest that a drag event happened on the plugin.
IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_DragStatusUpdate,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
blink::WebDragStatus /* drag_status */,
content::DropData /* drop_data */,
blink::WebDragOperationsMask /* operation_mask */,
@@ -187,15 +137,16 @@ IPC_MESSAGE_ROUTED5(BrowserPluginHostMsg_DragStatusUpdate,
// Sends a PointerLock Lock ACK to the BrowserPluginGuest.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_LockMouse_ACK,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
bool /* succeeded */)
// Sends a PointerLock Unlock ACK to the BrowserPluginGuest.
-IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_UnlockMouse_ACK, int /* instance_id */)
+IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_UnlockMouse_ACK,
+ int /* browser_plugin_instance_id */)
-// Sent when plugin's position has changed without UpdateRect.
+// Sent when plugin's position has changed.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_UpdateGeometry,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
gfx::Rect /* view_rect */)
// -----------------------------------------------------------------------------
@@ -205,7 +156,7 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_UpdateGeometry,
// to resize a guest plugin container so that the guest is relaid out
// according to the new size.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ResizeGuest,
- int /* instance_id*/,
+ int /* browser_plugin_instance_id*/,
BrowserPluginHostMsg_ResizeGuest_Params)
// -----------------------------------------------------------------------------
@@ -213,73 +164,51 @@ IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_ResizeGuest,
// This message is sent in response to a completed attachment of a guest
// to a BrowserPlugin.
-IPC_MESSAGE_CONTROL1(BrowserPluginMsg_Attach_ACK, int /* instance_id */);
-
-// Once the swapped out guest RenderView has been created in the embedder render
-// process, the browser process informs the embedder of its routing ID.
-IPC_MESSAGE_CONTROL2(BrowserPluginMsg_GuestContentWindowReady,
- int /* instance_id */,
- int /* source_routing_id */)
+IPC_MESSAGE_CONTROL1(BrowserPluginMsg_Attach_ACK,
+ int /* browser_plugin_instance_id */)
// When the guest crashes, the browser process informs the embedder through this
// message.
IPC_MESSAGE_CONTROL1(BrowserPluginMsg_GuestGone,
- int /* instance_id */)
+ int /* browser_plugin_instance_id */)
// When the user tabs to the end of the tab stops of a guest, the browser
// process informs the embedder to tab out of the browser plugin.
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_AdvanceFocus,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
bool /* reverse */)
// When the guest starts/stops listening to touch events, it needs to notify the
// plugin in the embedder about it.
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_ShouldAcceptTouchEvents,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
bool /* accept */)
+// Tells the guest to change its background opacity.
+IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetContentsOpaque,
+ int /* browser_plugin_instance_id */,
+ bool /* opaque */)
+
// Inform the embedder of the cursor the guest wishes to display.
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetCursor,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
content::WebCursor /* cursor */)
-// The guest has damage it wants to convey to the embedder so that it can
-// update its backing store.
-IPC_MESSAGE_CONTROL2(BrowserPluginMsg_UpdateRect,
- int /* instance_id */,
- BrowserPluginMsg_UpdateRect_Params)
-
-IPC_MESSAGE_CONTROL4(BrowserPluginMsg_CopyFromCompositingSurface,
- int /* instance_id */,
- int /* request_id */,
- gfx::Rect /* source_rect */,
- gfx::Size /* dest_size */)
-
-// Guest renders into an FBO with textures provided by the embedder.
-// BrowserPlugin shares mostly the same logic as out-of-process RenderFrames but
-// because BrowserPlugins implement custom a second level of routing logic,
-// the IPCs need to be annotated with an extra instance_id. These messages
-// provide that extra id.
-IPC_MESSAGE_CONTROL2(BrowserPluginMsg_BuffersSwapped,
- int /* instance_id */,
- FrameMsg_BuffersSwapped_Params /* params */)
-
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_CompositorFrameSwapped,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
FrameMsg_CompositorFrameSwapped_Params /* params */)
// Forwards a PointerLock Unlock request to the BrowserPlugin.
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetMouseLock,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
bool /* enable */)
-// See comment about BrowserPluginMsg_BuffersSwapped and
-// BrowserPluginMsg_CompositorFrameSwapped for how these related
-// to the FrameHostMsg variants.
-IPC_MESSAGE_ROUTED1(BrowserPluginHostMsg_BuffersSwappedACK,
- FrameHostMsg_BuffersSwappedACK_Params /* params */)
+// Sends text to be displayed in tooltip.
+IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetTooltipText,
+ int /* browser_plugin_instance_id */,
+ base::string16 /* tooltip_text */)
// Acknowledge that we presented an ubercomp frame.
IPC_MESSAGE_ROUTED2(BrowserPluginHostMsg_CompositorFrameSwappedACK,
- int /* instance_id */,
+ int /* browser_plugin_instance_id */,
FrameHostMsg_CompositorFrameSwappedACK_Params /* params */)
diff --git a/chromium/content/common/cc_messages.cc b/chromium/content/common/cc_messages.cc
index 8946d70027b..426cee21be4 100644
--- a/chromium/content/common/cc_messages.cc
+++ b/chromium/content/common/cc_messages.cc
@@ -6,8 +6,8 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/filter_operations.h"
+#include "cc/quads/largest_draw_quad.h"
#include "content/public/common/common_param_traits.h"
-#include "content/public/common/content_switches.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkFlattenableSerialization.h"
#include "ui/gfx/transform.h"
@@ -294,13 +294,13 @@ void ParamTraits<cc::RenderPass>::Write(
WriteParam(m, p.damage_rect);
WriteParam(m, p.transform_to_root_target);
WriteParam(m, p.has_transparent_background);
- WriteParam(m, p.shared_quad_state_list.size());
WriteParam(m, p.quad_list.size());
- size_t shared_quad_state_index = 0;
- size_t last_shared_quad_state_index = kuint32max;
- for (size_t i = 0; i < p.quad_list.size(); ++i) {
- const cc::DrawQuad* quad = p.quad_list[i];
+ cc::SharedQuadStateList::ConstIterator shared_quad_state_iter =
+ p.shared_quad_state_list.begin();
+ cc::SharedQuadStateList::ConstIterator last_shared_quad_state_iter =
+ p.shared_quad_state_list.end();
+ for (const auto& quad : p.quad_list) {
DCHECK(quad->rect.Contains(quad->visible_rect))
<< quad->material << " rect: " << quad->rect.ToString()
<< " visible_rect: " << quad->visible_rect.ToString();
@@ -347,35 +347,23 @@ void ParamTraits<cc::RenderPass>::Write(
break;
}
- const cc::ScopedPtrVector<cc::SharedQuadState>& sqs_list =
- p.shared_quad_state_list;
-
- // This is an invalid index.
- size_t bad_index = sqs_list.size();
-
// Null shared quad states should not occur.
DCHECK(quad->shared_quad_state);
- if (!quad->shared_quad_state) {
- WriteParam(m, bad_index);
- continue;
- }
// SharedQuadStates should appear in the order they are used by DrawQuads.
// Find the SharedQuadState for this DrawQuad.
- while (shared_quad_state_index < sqs_list.size() &&
- quad->shared_quad_state != sqs_list[shared_quad_state_index])
- ++shared_quad_state_index;
-
- DCHECK_LT(shared_quad_state_index, sqs_list.size());
- if (shared_quad_state_index >= sqs_list.size()) {
- WriteParam(m, bad_index);
- continue;
- }
-
- WriteParam(m, shared_quad_state_index);
- if (shared_quad_state_index != last_shared_quad_state_index) {
- WriteParam(m, *sqs_list[shared_quad_state_index]);
- last_shared_quad_state_index = shared_quad_state_index;
+ while (shared_quad_state_iter != p.shared_quad_state_list.end() &&
+ quad->shared_quad_state != *shared_quad_state_iter)
+ ++shared_quad_state_iter;
+
+ DCHECK(shared_quad_state_iter != p.shared_quad_state_list.end());
+
+ if (shared_quad_state_iter != last_shared_quad_state_iter) {
+ WriteParam(m, true);
+ WriteParam(m, **shared_quad_state_iter);
+ last_shared_quad_state_iter = shared_quad_state_iter;
+ } else {
+ WriteParam(m, false);
}
}
}
@@ -383,33 +371,35 @@ void ParamTraits<cc::RenderPass>::Write(
static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
size_t to_reserve = sizeof(cc::RenderPass);
- to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
+ // Whether the quad points to a new shared quad state for each quad.
+ to_reserve += p.quad_list.size() * sizeof(bool);
- // The shared_quad_state_index for each quad.
- to_reserve += p.quad_list.size() * sizeof(size_t);
+ // Shared quad state is only written when a quad contains a shared quad state
+ // that has not been written.
+ to_reserve += p.shared_quad_state_list.size() * sizeof(cc::SharedQuadState);
// The largest quad type, verified by a unit test.
- to_reserve += p.quad_list.size() * sizeof(cc::RenderPassDrawQuad);
+ to_reserve += p.quad_list.size() * cc::LargestDrawQuadSize();
return to_reserve;
}
-template<typename QuadType>
-static scoped_ptr<cc::DrawQuad> ReadDrawQuad(const Message* m,
- PickleIterator* iter) {
- scoped_ptr<QuadType> quad = QuadType::Create();
- if (!ReadParam(m, iter, quad.get()))
- return scoped_ptr<QuadType>().template PassAs<cc::DrawQuad>();
- return quad.template PassAs<cc::DrawQuad>();
+template <typename QuadType>
+static cc::DrawQuad* ReadDrawQuad(const Message* m,
+ PickleIterator* iter,
+ cc::RenderPass* render_pass) {
+ QuadType* quad = render_pass->CreateAndAppendDrawQuad<QuadType>();
+ if (!ReadParam(m, iter, quad))
+ return NULL;
+ return quad;
}
bool ParamTraits<cc::RenderPass>::Read(
const Message* m, PickleIterator* iter, param_type* p) {
- cc::RenderPass::Id id(-1, -1);
+ cc::RenderPassId id(-1, -1);
gfx::Rect output_rect;
gfx::Rect damage_rect;
gfx::Transform transform_to_root_target;
bool has_transparent_background;
- size_t shared_quad_state_list_size;
size_t quad_list_size;
if (!ReadParam(m, iter, &id) ||
@@ -417,7 +407,6 @@ bool ParamTraits<cc::RenderPass>::Read(
!ReadParam(m, iter, &damage_rect) ||
!ReadParam(m, iter, &transform_to_root_target) ||
!ReadParam(m, iter, &has_transparent_background) ||
- !ReadParam(m, iter, &shared_quad_state_list_size) ||
!ReadParam(m, iter, &quad_list_size))
return false;
@@ -427,47 +416,46 @@ bool ParamTraits<cc::RenderPass>::Read(
transform_to_root_target,
has_transparent_background);
- size_t last_shared_quad_state_index = kuint32max;
for (size_t i = 0; i < quad_list_size; ++i) {
cc::DrawQuad::Material material;
PickleIterator temp_iter = *iter;
if (!ReadParam(m, &temp_iter, &material))
return false;
- scoped_ptr<cc::DrawQuad> draw_quad;
+ cc::DrawQuad* draw_quad = NULL;
switch (material) {
case cc::DrawQuad::CHECKERBOARD:
- draw_quad = ReadDrawQuad<cc::CheckerboardDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::CheckerboardDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::DEBUG_BORDER:
- draw_quad = ReadDrawQuad<cc::DebugBorderDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::DebugBorderDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::IO_SURFACE_CONTENT:
- draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::IOSurfaceDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::PICTURE_CONTENT:
NOTREACHED();
return false;
case cc::DrawQuad::SURFACE_CONTENT:
- draw_quad = ReadDrawQuad<cc::SurfaceDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::SurfaceDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::TEXTURE_CONTENT:
- draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::TextureDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::RENDER_PASS:
- draw_quad = ReadDrawQuad<cc::RenderPassDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::RenderPassDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::SOLID_COLOR:
- draw_quad = ReadDrawQuad<cc::SolidColorDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::SolidColorDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::TILED_CONTENT:
- draw_quad = ReadDrawQuad<cc::TileDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::TileDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::STREAM_VIDEO_CONTENT:
- draw_quad = ReadDrawQuad<cc::StreamVideoDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::StreamVideoDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::YUV_VIDEO_CONTENT:
- draw_quad = ReadDrawQuad<cc::YUVVideoDrawQuad>(m, iter);
+ draw_quad = ReadDrawQuad<cc::YUVVideoDrawQuad>(m, iter, p);
break;
case cc::DrawQuad::INVALID:
break;
@@ -488,26 +476,18 @@ bool ParamTraits<cc::RenderPass>::Read(
return false;
}
- size_t shared_quad_state_index;
- if (!ReadParam(m, iter, &shared_quad_state_index))
- return false;
- if (shared_quad_state_index >= shared_quad_state_list_size)
- return false;
- // SharedQuadState indexes should be in ascending order.
- if (last_shared_quad_state_index != kuint32max &&
- shared_quad_state_index < last_shared_quad_state_index)
+ bool has_new_shared_quad_state;
+ if (!ReadParam(m, iter, &has_new_shared_quad_state))
return false;
// If the quad has a new shared quad state, read it in.
- if (last_shared_quad_state_index != shared_quad_state_index) {
+ if (has_new_shared_quad_state) {
cc::SharedQuadState* state = p->CreateAndAppendSharedQuadState();
if (!ReadParam(m, iter, state))
return false;
- last_shared_quad_state_index = shared_quad_state_index;
}
draw_quad->shared_quad_state = p->shared_quad_state_list.back();
- p->quad_list.push_back(draw_quad.Pass());
}
return true;
@@ -528,16 +508,15 @@ void ParamTraits<cc::RenderPass>::Log(
l->append(", ");
l->append("[");
- for (size_t i = 0; i < p.shared_quad_state_list.size(); ++i) {
- if (i)
+ for (const auto& shared_quad_state : p.shared_quad_state_list) {
+ if (shared_quad_state != p.shared_quad_state_list.front())
l->append(", ");
- LogParam(*p.shared_quad_state_list[i], l);
+ LogParam(*shared_quad_state, l);
}
l->append("], [");
- for (size_t i = 0; i < p.quad_list.size(); ++i) {
- if (i)
+ for (const auto& quad : p.quad_list) {
+ if (quad != p.quad_list.front())
l->append(", ");
- const cc::DrawQuad* quad = p.quad_list[i];
switch (quad->material) {
case cc::DrawQuad::CHECKERBOARD:
LogParam(*cc::CheckerboardDrawQuad::MaterialCast(quad), l);
@@ -715,6 +694,7 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
to_reserve += p.resource_list.size() * sizeof(cc::TransferableResource);
for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
const cc::RenderPass* pass = p.render_pass_list[i];
+ to_reserve += sizeof(size_t) * 2;
to_reserve += ReserveSizeForRenderPassWrite(*pass);
}
m->Reserve(to_reserve);
@@ -722,8 +702,11 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
WriteParam(m, p.device_scale_factor);
WriteParam(m, p.resource_list);
WriteParam(m, p.render_pass_list.size());
- for (size_t i = 0; i < p.render_pass_list.size(); ++i)
+ for (size_t i = 0; i < p.render_pass_list.size(); ++i) {
+ WriteParam(m, p.render_pass_list[i]->quad_list.size());
+ WriteParam(m, p.render_pass_list[i]->shared_quad_state_list.size());
WriteParam(m, *p.render_pass_list[i]);
+ }
}
bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
@@ -733,6 +716,8 @@ bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
return false;
const static size_t kMaxRenderPasses = 10000;
+ const static size_t kMaxSharedQuadStateListSize = 100000;
+ const static size_t kMaxQuadListSize = 1000000;
size_t num_render_passes;
if (!ReadParam(m, iter, &p->resource_list) ||
@@ -740,7 +725,15 @@ bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
num_render_passes > kMaxRenderPasses || num_render_passes == 0)
return false;
for (size_t i = 0; i < num_render_passes; ++i) {
- scoped_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
+ size_t quad_list_size;
+ size_t shared_quad_state_list_size;
+ if (!ReadParam(m, iter, &quad_list_size) ||
+ !ReadParam(m, iter, &shared_quad_state_list_size) ||
+ quad_list_size > kMaxQuadListSize ||
+ shared_quad_state_list_size > kMaxSharedQuadStateListSize)
+ return false;
+ scoped_ptr<cc::RenderPass> render_pass =
+ cc::RenderPass::Create(shared_quad_state_list_size, quad_list_size);
if (!ReadParam(m, iter, render_pass.get()))
return false;
p->render_pass_list.push_back(render_pass.Pass());
diff --git a/chromium/content/common/cc_messages.h b/chromium/content/common/cc_messages.h
index da416eb3f7c..0c14ddf5ef5 100644
--- a/chromium/content/common/cc_messages.h
+++ b/chromium/content/common/cc_messages.h
@@ -8,6 +8,7 @@
#include "cc/output/compositor_frame.h"
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/filter_operation.h"
+#include "cc/output/viewport_selection_bound.h"
#include "cc/quads/checkerboard_draw_quad.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/draw_quad.h"
@@ -29,6 +30,7 @@
#include "content/common/content_export.h"
#include "gpu/ipc/gpu_command_buffer_traits.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#ifndef CONTENT_COMMON_CC_MESSAGES_H_
#define CONTENT_COMMON_CC_MESSAGES_H_
@@ -131,11 +133,12 @@ IPC_ENUM_TRAITS_MAX_VALUE(cc::IOSurfaceDrawQuad::Orientation,
IPC_ENUM_TRAITS_MAX_VALUE(cc::FilterOperation::FilterType,
cc::FilterOperation::FILTER_TYPE_LAST )
IPC_ENUM_TRAITS_MAX_VALUE(cc::ResourceFormat, cc::RESOURCE_FORMAT_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(cc::SelectionBoundType, cc::SELECTION_BOUND_TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(SkXfermode::Mode, SkXfermode::kLastMode)
IPC_ENUM_TRAITS_MAX_VALUE(cc::YUVVideoDrawQuad::ColorSpace,
cc::YUVVideoDrawQuad::COLOR_SPACE_LAST)
-IPC_STRUCT_TRAITS_BEGIN(cc::RenderPass::Id)
+IPC_STRUCT_TRAITS_BEGIN(cc::RenderPassId)
IPC_STRUCT_TRAITS_MEMBER(layer_id)
IPC_STRUCT_TRAITS_MEMBER(index)
IPC_STRUCT_TRAITS_END()
@@ -173,11 +176,11 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::RenderPassDrawQuad)
IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
IPC_STRUCT_TRAITS_MEMBER(render_pass_id)
- IPC_STRUCT_TRAITS_MEMBER(is_replica)
IPC_STRUCT_TRAITS_MEMBER(mask_resource_id)
- IPC_STRUCT_TRAITS_MEMBER(contents_changed_since_last_frame)
- IPC_STRUCT_TRAITS_MEMBER(mask_uv_rect)
+ IPC_STRUCT_TRAITS_MEMBER(mask_uv_scale)
+ IPC_STRUCT_TRAITS_MEMBER(mask_texture_size)
IPC_STRUCT_TRAITS_MEMBER(filters)
+ IPC_STRUCT_TRAITS_MEMBER(filters_scale)
IPC_STRUCT_TRAITS_MEMBER(background_filters)
IPC_STRUCT_TRAITS_END()
@@ -249,6 +252,7 @@ IPC_STRUCT_TRAITS_BEGIN(cc::TransferableResource)
IPC_STRUCT_TRAITS_MEMBER(mailbox_holder)
IPC_STRUCT_TRAITS_MEMBER(is_repeated)
IPC_STRUCT_TRAITS_MEMBER(is_software)
+ IPC_STRUCT_TRAITS_MEMBER(allow_overlay)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::ReturnedResource)
@@ -258,6 +262,13 @@ IPC_STRUCT_TRAITS_BEGIN(cc::ReturnedResource)
IPC_STRUCT_TRAITS_MEMBER(lost)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(cc::ViewportSelectionBound)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(edge_top)
+ IPC_STRUCT_TRAITS_MEMBER(edge_bottom)
+ IPC_STRUCT_TRAITS_MEMBER(visible)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(cc::BeginFrameArgs)
IPC_STRUCT_TRAITS_MEMBER(frame_time)
IPC_STRUCT_TRAITS_MEMBER(deadline)
@@ -268,14 +279,16 @@ IPC_STRUCT_TRAITS_BEGIN(cc::CompositorFrameMetadata)
IPC_STRUCT_TRAITS_MEMBER(device_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset)
IPC_STRUCT_TRAITS_MEMBER(page_scale_factor)
- IPC_STRUCT_TRAITS_MEMBER(viewport_size)
+ IPC_STRUCT_TRAITS_MEMBER(scrollable_viewport_size)
IPC_STRUCT_TRAITS_MEMBER(root_layer_size)
IPC_STRUCT_TRAITS_MEMBER(min_page_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(location_bar_offset)
IPC_STRUCT_TRAITS_MEMBER(location_bar_content_translation)
- IPC_STRUCT_TRAITS_MEMBER(overdraw_bottom_height)
+ IPC_STRUCT_TRAITS_MEMBER(selection_start)
+ IPC_STRUCT_TRAITS_MEMBER(selection_end)
IPC_STRUCT_TRAITS_MEMBER(latency_info)
+ IPC_STRUCT_TRAITS_MEMBER(satisfies_sequences)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::GLFrameData)
diff --git a/chromium/content/common/cc_messages_perftest.cc b/chromium/content/common/cc_messages_perftest.cc
index 7589128c23b..1aa09e875d5 100644
--- a/chromium/content/common/cc_messages_perftest.cc
+++ b/chromium/content/common/cc_messages_perftest.cc
@@ -67,10 +67,9 @@ TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_1_4000) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
render_pass->CreateAndAppendSharedQuadState();
for (int i = 0; i < 4000; ++i) {
- render_pass->quad_list.push_back(
- PictureDrawQuad::Create().PassAs<DrawQuad>());
- render_pass->quad_list.back()->shared_quad_state =
- render_pass->shared_quad_state_list.back();
+ PictureDrawQuad* quad =
+ render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
+ quad->shared_quad_state = render_pass->shared_quad_state_list.back();
}
frame->delegated_frame_data.reset(new DelegatedFrameData);
@@ -85,10 +84,9 @@ TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_1_100000) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
render_pass->CreateAndAppendSharedQuadState();
for (int i = 0; i < 100000; ++i) {
- render_pass->quad_list.push_back(
- PictureDrawQuad::Create().PassAs<DrawQuad>());
- render_pass->quad_list.back()->shared_quad_state =
- render_pass->shared_quad_state_list.back();
+ PictureDrawQuad* quad =
+ render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
+ quad->shared_quad_state = render_pass->shared_quad_state_list.back();
}
frame->delegated_frame_data.reset(new DelegatedFrameData);
@@ -103,10 +101,9 @@ TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_4000_4000) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
for (int i = 0; i < 4000; ++i) {
render_pass->CreateAndAppendSharedQuadState();
- render_pass->quad_list.push_back(
- PictureDrawQuad::Create().PassAs<DrawQuad>());
- render_pass->quad_list.back()->shared_quad_state =
- render_pass->shared_quad_state_list.back();
+ PictureDrawQuad* quad =
+ render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
+ quad->shared_quad_state = render_pass->shared_quad_state_list.back();
}
frame->delegated_frame_data.reset(new DelegatedFrameData);
@@ -121,10 +118,9 @@ TEST_F(CCMessagesPerfTest, DelegatedFrame_ManyQuads_100000_100000) {
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
for (int i = 0; i < 100000; ++i) {
render_pass->CreateAndAppendSharedQuadState();
- render_pass->quad_list.push_back(
- PictureDrawQuad::Create().PassAs<DrawQuad>());
- render_pass->quad_list.back()->shared_quad_state =
- render_pass->shared_quad_state_list.back();
+ PictureDrawQuad* quad =
+ render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
+ quad->shared_quad_state = render_pass->shared_quad_state_list.back();
}
frame->delegated_frame_data.reset(new DelegatedFrameData);
@@ -142,10 +138,9 @@ TEST_F(CCMessagesPerfTest,
scoped_ptr<RenderPass> render_pass = RenderPass::Create();
for (int j = 0; j < 100; ++j) {
render_pass->CreateAndAppendSharedQuadState();
- render_pass->quad_list.push_back(
- PictureDrawQuad::Create().PassAs<DrawQuad>());
- render_pass->quad_list.back()->shared_quad_state =
- render_pass->shared_quad_state_list.back();
+ PictureDrawQuad* quad =
+ render_pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
+ quad->shared_quad_state = render_pass->shared_quad_state_list.back();
}
frame->delegated_frame_data->render_pass_list.push_back(render_pass.Pass());
}
diff --git a/chromium/content/common/cc_messages_unittest.cc b/chromium/content/common/cc_messages_unittest.cc
index d0ceb691820..cc1fdf0c84c 100644
--- a/chromium/content/common/cc_messages_unittest.cc
+++ b/chromium/content/common/cc_messages_unittest.cc
@@ -28,6 +28,7 @@ using cc::FilterOperations;
using cc::IOSurfaceDrawQuad;
using cc::PictureDrawQuad;
using cc::RenderPass;
+using cc::RenderPassId;
using cc::RenderPassDrawQuad;
using cc::ResourceProvider;
using cc::SharedQuadState;
@@ -143,11 +144,9 @@ class CCMessagesTest : public testing::Test {
void Compare(const RenderPassDrawQuad* a, const RenderPassDrawQuad* b) {
EXPECT_EQ(a->render_pass_id, b->render_pass_id);
- EXPECT_EQ(a->is_replica, b->is_replica);
EXPECT_EQ(a->mask_resource_id, b->mask_resource_id);
- EXPECT_EQ(a->contents_changed_since_last_frame,
- b->contents_changed_since_last_frame);
- EXPECT_EQ(a->mask_uv_rect.ToString(), b->mask_uv_rect.ToString());
+ EXPECT_EQ(a->mask_uv_scale.ToString(), b->mask_uv_scale.ToString());
+ EXPECT_EQ(a->mask_texture_size.ToString(), b->mask_texture_size.ToString());
EXPECT_EQ(a->filters.size(), b->filters.size());
for (size_t i = 0; i < a->filters.size(); ++i) {
if (a->filters.at(i).type() != cc::FilterOperation::REFERENCE) {
@@ -158,6 +157,7 @@ class CCMessagesTest : public testing::Test {
b->filters.at(i).image_filter()->countInputs());
}
}
+ EXPECT_EQ(a->filters_scale, b->filters_scale);
EXPECT_EQ(a->background_filters, b->background_filters);
}
@@ -215,6 +215,7 @@ class CCMessagesTest : public testing::Test {
}
EXPECT_EQ(a.mailbox_holder.texture_target, b.mailbox_holder.texture_target);
EXPECT_EQ(a.mailbox_holder.sync_point, b.mailbox_holder.sync_point);
+ EXPECT_EQ(a.allow_overlay, b.allow_overlay);
}
};
@@ -241,6 +242,8 @@ TEST_F(CCMessagesTest, AllQuads) {
gfx::SizeF arbitrary_sizef1(15.2f, 104.6f);
gfx::PointF arbitrary_pointf1(31.4f, 15.9f);
gfx::PointF arbitrary_pointf2(26.5f, -35.8f);
+ gfx::Vector2dF arbitrary_vector2df1(16.2f, -85.1f);
+ gfx::Vector2dF arbitrary_vector2df2(-8.3f, 0.47f);
float arbitrary_float1 = 0.7f;
float arbitrary_float2 = 0.3f;
float arbitrary_float3 = 0.9f;
@@ -258,7 +261,7 @@ TEST_F(CCMessagesTest, AllQuads) {
SkXfermode::Mode arbitrary_blend_mode3 = SkXfermode::kOverlay_Mode;
IOSurfaceDrawQuad::Orientation arbitrary_orientation =
IOSurfaceDrawQuad::UNFLIPPED;
- RenderPass::Id arbitrary_id(10, 14);
+ RenderPassId arbitrary_id(10, 14);
ResourceProvider::ResourceId arbitrary_resourceid1 = 55;
ResourceProvider::ResourceId arbitrary_resourceid2 = 47;
ResourceProvider::ResourceId arbitrary_resourceid3 = 23;
@@ -307,19 +310,19 @@ TEST_F(CCMessagesTest, AllQuads) {
pass_cmp->CreateAndAppendSharedQuadState();
shared_state1_cmp->CopyFrom(shared_state1_in);
- scoped_ptr<CheckerboardDrawQuad> checkerboard_in =
- CheckerboardDrawQuad::Create();
+ CheckerboardDrawQuad* checkerboard_in =
+ pass_in->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
checkerboard_in->SetAll(shared_state1_in,
arbitrary_rect1,
arbitrary_rect2_inside_rect1,
arbitrary_rect1_inside_rect1,
arbitrary_bool1,
arbitrary_color);
- scoped_ptr<DrawQuad> checkerboard_cmp = checkerboard_in->Copy(
- checkerboard_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(checkerboard_in,
+ checkerboard_in->shared_quad_state);
- scoped_ptr<DebugBorderDrawQuad> debugborder_in =
- DebugBorderDrawQuad::Create();
+ DebugBorderDrawQuad* debugborder_in =
+ pass_in->CreateAndAppendDrawQuad<DebugBorderDrawQuad>();
debugborder_in->SetAll(shared_state1_in,
arbitrary_rect3,
arbitrary_rect1_inside_rect3,
@@ -327,11 +330,11 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_bool1,
arbitrary_color,
arbitrary_int);
- scoped_ptr<DrawQuad> debugborder_cmp = debugborder_in->Copy(
- debugborder_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(debugborder_in,
+ debugborder_in->shared_quad_state);
- scoped_ptr<IOSurfaceDrawQuad> iosurface_in =
- IOSurfaceDrawQuad::Create();
+ IOSurfaceDrawQuad* iosurface_in =
+ pass_in->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>();
iosurface_in->SetAll(shared_state1_in,
arbitrary_rect2,
arbitrary_rect2_inside_rect2,
@@ -340,8 +343,8 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_size1,
arbitrary_resourceid3,
arbitrary_orientation);
- scoped_ptr<DrawQuad> iosurface_cmp = iosurface_in->Copy(
- iosurface_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(iosurface_in,
+ iosurface_in->shared_quad_state);
SharedQuadState* shared_state2_in = pass_in->CreateAndAppendSharedQuadState();
shared_state2_in->SetAll(arbitrary_matrix,
@@ -356,22 +359,24 @@ TEST_F(CCMessagesTest, AllQuads) {
pass_cmp->CreateAndAppendSharedQuadState();
shared_state2_cmp->CopyFrom(shared_state2_in);
- scoped_ptr<RenderPassDrawQuad> renderpass_in =
- RenderPassDrawQuad::Create();
+ RenderPassDrawQuad* renderpass_in =
+ pass_in->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
renderpass_in->SetAll(shared_state2_in,
arbitrary_rect1,
arbitrary_rect2_inside_rect1,
arbitrary_rect1_inside_rect1,
arbitrary_bool1,
arbitrary_id,
- arbitrary_bool2,
arbitrary_resourceid2,
- arbitrary_rect1,
- arbitrary_rectf1,
+ arbitrary_vector2df1,
+ arbitrary_size1,
arbitrary_filters1,
+ arbitrary_vector2df2,
arbitrary_filters2);
- scoped_ptr<RenderPassDrawQuad> renderpass_cmp = renderpass_in->Copy(
- renderpass_in->shared_quad_state, renderpass_in->render_pass_id);
+ pass_cmp->CopyFromAndAppendRenderPassDrawQuad(
+ renderpass_in,
+ renderpass_in->shared_quad_state,
+ renderpass_in->render_pass_id);
SharedQuadState* shared_state3_in = pass_in->CreateAndAppendSharedQuadState();
shared_state3_in->SetAll(arbitrary_matrix,
@@ -386,8 +391,8 @@ TEST_F(CCMessagesTest, AllQuads) {
pass_cmp->CreateAndAppendSharedQuadState();
shared_state3_cmp->CopyFrom(shared_state3_in);
- scoped_ptr<SolidColorDrawQuad> solidcolor_in =
- SolidColorDrawQuad::Create();
+ SolidColorDrawQuad* solidcolor_in =
+ pass_in->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
solidcolor_in->SetAll(shared_state3_in,
arbitrary_rect3,
arbitrary_rect1_inside_rect3,
@@ -395,11 +400,11 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_bool1,
arbitrary_color,
arbitrary_bool2);
- scoped_ptr<DrawQuad> solidcolor_cmp = solidcolor_in->Copy(
- solidcolor_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(solidcolor_in,
+ solidcolor_in->shared_quad_state);
- scoped_ptr<StreamVideoDrawQuad> streamvideo_in =
- StreamVideoDrawQuad::Create();
+ StreamVideoDrawQuad* streamvideo_in =
+ pass_in->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
streamvideo_in->SetAll(shared_state3_in,
arbitrary_rect2,
arbitrary_rect2_inside_rect2,
@@ -407,21 +412,23 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_bool1,
arbitrary_resourceid2,
arbitrary_matrix);
- scoped_ptr<DrawQuad> streamvideo_cmp = streamvideo_in->Copy(
- streamvideo_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(streamvideo_in,
+ streamvideo_in->shared_quad_state);
cc::SurfaceId arbitrary_surface_id(3);
- scoped_ptr<SurfaceDrawQuad> surface_in = SurfaceDrawQuad::Create();
+ SurfaceDrawQuad* surface_in =
+ pass_in->CreateAndAppendDrawQuad<SurfaceDrawQuad>();
surface_in->SetAll(shared_state3_in,
arbitrary_rect2,
arbitrary_rect2_inside_rect2,
arbitrary_rect1_inside_rect2,
arbitrary_bool1,
arbitrary_surface_id);
- scoped_ptr<DrawQuad> surface_cmp = surface_in->Copy(
- surface_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(surface_in,
+ surface_in->shared_quad_state);
- scoped_ptr<TextureDrawQuad> texture_in = TextureDrawQuad::Create();
+ TextureDrawQuad* texture_in =
+ pass_in->CreateAndAppendDrawQuad<TextureDrawQuad>();
texture_in->SetAll(shared_state3_in,
arbitrary_rect2,
arbitrary_rect2_inside_rect2,
@@ -434,10 +441,10 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_color,
arbitrary_float_array,
arbitrary_bool3);
- scoped_ptr<DrawQuad> texture_cmp = texture_in->Copy(
- texture_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(texture_in,
+ texture_in->shared_quad_state);
- scoped_ptr<TileDrawQuad> tile_in = TileDrawQuad::Create();
+ TileDrawQuad* tile_in = pass_in->CreateAndAppendDrawQuad<TileDrawQuad>();
tile_in->SetAll(shared_state3_in,
arbitrary_rect2,
arbitrary_rect2_inside_rect2,
@@ -447,11 +454,10 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rectf1,
arbitrary_size1,
arbitrary_bool2);
- scoped_ptr<DrawQuad> tile_cmp = tile_in->Copy(
- tile_in->shared_quad_state);
+ pass_cmp->CopyFromAndAppendDrawQuad(tile_in, tile_in->shared_quad_state);
- scoped_ptr<YUVVideoDrawQuad> yuvvideo_in =
- YUVVideoDrawQuad::Create();
+ YUVVideoDrawQuad* yuvvideo_in =
+ pass_in->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
yuvvideo_in->SetAll(shared_state3_in,
arbitrary_rect1,
arbitrary_rect2_inside_rect1,
@@ -463,49 +469,33 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_resourceid3,
arbitrary_resourceid4,
arbitrary_color_space);
- scoped_ptr<DrawQuad> yuvvideo_cmp = yuvvideo_in->Copy(
- yuvvideo_in->shared_quad_state);
-
- pass_in->quad_list.push_back(checkerboard_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(debugborder_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(iosurface_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(renderpass_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(solidcolor_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(streamvideo_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(surface_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(texture_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(tile_in.PassAs<DrawQuad>());
- pass_in->quad_list.push_back(yuvvideo_in.PassAs<DrawQuad>());
-
-
- pass_cmp->quad_list.push_back(checkerboard_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(debugborder_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(iosurface_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(renderpass_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(solidcolor_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(streamvideo_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(surface_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(texture_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(tile_cmp.PassAs<DrawQuad>());
- pass_cmp->quad_list.push_back(yuvvideo_cmp.PassAs<DrawQuad>());
+ pass_cmp->CopyFromAndAppendDrawQuad(yuvvideo_in,
+ yuvvideo_in->shared_quad_state);
// Make sure the in and cmp RenderPasses match.
Compare(pass_cmp.get(), pass_in.get());
ASSERT_EQ(3u, pass_in->shared_quad_state_list.size());
ASSERT_EQ(10u, pass_in->quad_list.size());
- for (size_t i = 0; i < 3; ++i) {
- Compare(pass_cmp->shared_quad_state_list[i],
- pass_in->shared_quad_state_list[i]);
+ for (cc::SharedQuadStateList::ConstIterator
+ cmp_iterator = pass_cmp->shared_quad_state_list.begin(),
+ in_iterator = pass_in->shared_quad_state_list.begin();
+ in_iterator != pass_in->shared_quad_state_list.end();
+ ++cmp_iterator, ++in_iterator) {
+ Compare(*cmp_iterator, *in_iterator);
}
- for (size_t i = 0; i < pass_in->quad_list.size(); ++i)
- Compare(pass_cmp->quad_list[i], pass_in->quad_list[i]);
+ for (auto in_iter = pass_in->quad_list.cbegin(),
+ cmp_iter = pass_cmp->quad_list.cbegin();
+ in_iter != pass_in->quad_list.cend();
+ ++in_iter, ++cmp_iter)
+ Compare(*cmp_iter, *in_iter);
+
for (size_t i = 1; i < pass_in->quad_list.size(); ++i) {
bool same_shared_quad_state_cmp =
- pass_cmp->quad_list[i]->shared_quad_state ==
- pass_cmp->quad_list[i - 1]->shared_quad_state;
+ pass_cmp->quad_list.ElementAt(i)->shared_quad_state ==
+ pass_cmp->quad_list.ElementAt(i - 1)->shared_quad_state;
bool same_shared_quad_state_in =
- pass_in->quad_list[i]->shared_quad_state ==
- pass_in->quad_list[i - 1]->shared_quad_state;
+ pass_in->quad_list.ElementAt(i)->shared_quad_state ==
+ pass_in->quad_list.ElementAt(i - 1)->shared_quad_state;
EXPECT_EQ(same_shared_quad_state_cmp, same_shared_quad_state_in);
}
@@ -525,28 +515,33 @@ TEST_F(CCMessagesTest, AllQuads) {
Compare(pass_cmp.get(), pass_out.get());
ASSERT_EQ(3u, pass_out->shared_quad_state_list.size());
ASSERT_EQ(10u, pass_out->quad_list.size());
- for (size_t i = 0; i < 3; ++i) {
- Compare(pass_cmp->shared_quad_state_list[i],
- pass_out->shared_quad_state_list[i]);
+ for (cc::SharedQuadStateList::ConstIterator
+ cmp_iterator = pass_cmp->shared_quad_state_list.begin(),
+ out_iterator = pass_out->shared_quad_state_list.begin();
+ out_iterator != pass_out->shared_quad_state_list.end();
+ ++cmp_iterator, ++out_iterator) {
+ Compare(*cmp_iterator, *out_iterator);
}
- for (size_t i = 0; i < pass_out->quad_list.size(); ++i)
- Compare(pass_cmp->quad_list[i], pass_out->quad_list[i]);
+ for (auto out_iter = pass_out->quad_list.cbegin(),
+ cmp_iter = pass_cmp->quad_list.cbegin();
+ out_iter != pass_out->quad_list.cend();
+ ++out_iter, ++cmp_iter)
+ Compare(*cmp_iter, *out_iter);
+
for (size_t i = 1; i < pass_out->quad_list.size(); ++i) {
bool same_shared_quad_state_cmp =
- pass_cmp->quad_list[i]->shared_quad_state ==
- pass_cmp->quad_list[i - 1]->shared_quad_state;
+ pass_cmp->quad_list.ElementAt(i)->shared_quad_state ==
+ pass_cmp->quad_list.ElementAt(i - 1)->shared_quad_state;
bool same_shared_quad_state_out =
- pass_out->quad_list[i]->shared_quad_state ==
- pass_out->quad_list[i - 1]->shared_quad_state;
+ pass_out->quad_list.ElementAt(i)->shared_quad_state ==
+ pass_out->quad_list.ElementAt(i - 1)->shared_quad_state;
EXPECT_EQ(same_shared_quad_state_cmp, same_shared_quad_state_out);
}
}
TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
- scoped_ptr<CheckerboardDrawQuad> quad;
-
scoped_ptr<RenderPass> pass_in = RenderPass::Create();
- pass_in->SetAll(RenderPass::Id(1, 1),
+ pass_in->SetAll(RenderPassId(1, 1),
gfx::Rect(100, 100),
gfx::Rect(),
gfx::Transform(),
@@ -563,14 +558,14 @@ TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
SkXfermode::kSrcOver_Mode,
0);
- quad = CheckerboardDrawQuad::Create();
- quad->SetAll(shared_state1_in,
- gfx::Rect(10, 10),
- gfx::Rect(10, 10),
- gfx::Rect(10, 10),
- false,
- SK_ColorRED);
- pass_in->quad_list.push_back(quad.PassAs<DrawQuad>());
+ CheckerboardDrawQuad* quad1 =
+ pass_in->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+ quad1->SetAll(shared_state1_in,
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ false,
+ SK_ColorRED);
// The second and third SharedQuadStates are not used.
SharedQuadState* shared_state2_in = pass_in->CreateAndAppendSharedQuadState();
@@ -604,14 +599,14 @@ TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
SkXfermode::kSrcOver_Mode,
0);
- quad = CheckerboardDrawQuad::Create();
- quad->SetAll(shared_state4_in,
- gfx::Rect(10, 10),
- gfx::Rect(10, 10),
- gfx::Rect(10, 10),
- false,
- SK_ColorRED);
- pass_in->quad_list.push_back(quad.PassAs<DrawQuad>());
+ CheckerboardDrawQuad* quad2 =
+ pass_in->CreateAndAppendDrawQuad<CheckerboardDrawQuad>();
+ quad2->SetAll(shared_state4_in,
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ gfx::Rect(10, 10),
+ false,
+ SK_ColorRED);
// The fifth is not used again.
SharedQuadState* shared_state5_in = pass_in->CreateAndAppendSharedQuadState();
@@ -647,10 +642,12 @@ TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
ASSERT_EQ(2u, pass_out->shared_quad_state_list.size());
ASSERT_EQ(2u, pass_out->quad_list.size());
- EXPECT_EQ(gfx::Size(1, 1).ToString(),
- pass_out->shared_quad_state_list[0]->content_bounds.ToString());
- EXPECT_EQ(gfx::Size(4, 4).ToString(),
- pass_out->shared_quad_state_list[1]->content_bounds.ToString());
+ EXPECT_EQ(
+ gfx::Size(1, 1).ToString(),
+ pass_out->shared_quad_state_list.ElementAt(0)->content_bounds.ToString());
+ EXPECT_EQ(
+ gfx::Size(4, 4).ToString(),
+ pass_out->shared_quad_state_list.ElementAt(1)->content_bounds.ToString());
}
TEST_F(CCMessagesTest, Resources) {
@@ -677,6 +674,7 @@ TEST_F(CCMessagesTest, Resources) {
arbitrary_resource1.mailbox_holder.mailbox.SetName(arbitrary_mailbox1);
arbitrary_resource1.mailbox_holder.texture_target = GL_TEXTURE_2D;
arbitrary_resource1.mailbox_holder.sync_point = arbitrary_uint1;
+ arbitrary_resource1.allow_overlay = true;
TransferableResource arbitrary_resource2;
arbitrary_resource2.id = 789132;
@@ -686,10 +684,11 @@ TEST_F(CCMessagesTest, Resources) {
arbitrary_resource2.mailbox_holder.mailbox.SetName(arbitrary_mailbox2);
arbitrary_resource2.mailbox_holder.texture_target = GL_TEXTURE_EXTERNAL_OES;
arbitrary_resource2.mailbox_holder.sync_point = arbitrary_uint2;
+ arbitrary_resource2.allow_overlay = false;
scoped_ptr<RenderPass> renderpass_in = RenderPass::Create();
renderpass_in->SetNew(
- RenderPass::Id(1, 1), gfx::Rect(), gfx::Rect(), gfx::Transform());
+ RenderPassId(1, 1), gfx::Rect(), gfx::Rect(), gfx::Transform());
DelegatedFrameData frame_in;
frame_in.resource_list.push_back(arbitrary_resource1);
@@ -708,58 +707,6 @@ TEST_F(CCMessagesTest, Resources) {
Compare(arbitrary_resource2, frame_out.resource_list[1]);
}
-TEST_F(CCMessagesTest, LargestQuadType) {
- size_t largest = 0;
-
- bool done = false;
- for (int i = 0; !done; ++i) {
- switch (static_cast<DrawQuad::Material>(i)) {
- case cc::DrawQuad::CHECKERBOARD:
- largest = std::max(largest, sizeof(cc::CheckerboardDrawQuad));
- break;
- case cc::DrawQuad::DEBUG_BORDER:
- largest = std::max(largest, sizeof(cc::DebugBorderDrawQuad));
- break;
- case cc::DrawQuad::IO_SURFACE_CONTENT:
- largest = std::max(largest, sizeof(cc::IOSurfaceDrawQuad));
- break;
- case cc::DrawQuad::PICTURE_CONTENT:
- largest = std::max(largest, sizeof(cc::PictureDrawQuad));
- break;
- case cc::DrawQuad::TEXTURE_CONTENT:
- largest = std::max(largest, sizeof(cc::TextureDrawQuad));
- break;
- case cc::DrawQuad::RENDER_PASS:
- largest = std::max(largest, sizeof(cc::RenderPassDrawQuad));
- break;
- case cc::DrawQuad::SOLID_COLOR:
- largest = std::max(largest, sizeof(cc::SolidColorDrawQuad));
- break;
- case cc::DrawQuad::SURFACE_CONTENT:
- largest = std::max(largest, sizeof(cc::SurfaceDrawQuad));
- break;
- case cc::DrawQuad::TILED_CONTENT:
- largest = std::max(largest, sizeof(cc::TileDrawQuad));
- break;
- case cc::DrawQuad::STREAM_VIDEO_CONTENT:
- largest = std::max(largest, sizeof(cc::StreamVideoDrawQuad));
- break;
- case cc::DrawQuad::YUV_VIDEO_CONTENT:
- largest = std::max(largest, sizeof(cc::YUVVideoDrawQuad));
- break;
- case cc::DrawQuad::INVALID:
- break;
- default:
- done = true;
- }
- }
-
- // Verify the largest DrawQuad type is RenderPassDrawQuad. If this ever
- // changes, then the ReserveSizeForRenderPassWrite() method needs to be
- // updated as well to use the new largest quad.
- EXPECT_EQ(sizeof(RenderPassDrawQuad), largest);
-}
-
TEST_F(CCMessagesTest, SoftwareFrameData) {
cc::SoftwareFrameData frame_in;
frame_in.id = 3;
diff --git a/chromium/content/common/child_process_host_impl.cc b/chromium/content/common/child_process_host_impl.cc
index 1dccab08385..8e1f56f694f 100644
--- a/chromium/content/common/child_process_host_impl.cc
+++ b/chromium/content/common/child_process_host_impl.cc
@@ -11,13 +11,14 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/numerics/safe_math.h"
#include "base/path_service.h"
#include "base/process/process_metrics.h"
#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "content/common/child_process_messages.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
#include "content/public/common/child_process_host_delegate.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
@@ -78,6 +79,9 @@ base::FilePath TransformPathForFeature(const base::FilePath& path,
// Global atomic to generate child process unique IDs.
base::StaticAtomicSequenceNumber g_unique_id;
+// Global atomic to generate gpu memory buffer unique IDs.
+base::StaticAtomicSequenceNumber g_next_gpu_memory_buffer_id;
+
} // namespace
namespace content {
@@ -93,7 +97,7 @@ ChildProcessHost* ChildProcessHost::Create(ChildProcessHostDelegate* delegate) {
base::FilePath ChildProcessHost::GetChildPath(int flags) {
base::FilePath child_path;
- child_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
+ child_path = base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
switches::kBrowserSubprocessPath);
#if defined(OS_LINUX)
@@ -187,7 +191,7 @@ bool ChildProcessHostImpl::IsChannelOpening() {
}
#if defined(OS_POSIX)
-int ChildProcessHostImpl::TakeClientFileDescriptor() {
+base::ScopedFD ChildProcessHostImpl::TakeClientFileDescriptor() {
return channel_->TakeClientFileDescriptor();
}
#endif
@@ -253,8 +257,11 @@ bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
OnShutdownRequest)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateSharedMemory,
OnAllocateSharedMemory)
- IPC_MESSAGE_HANDLER(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
- OnAllocateGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(
+ ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
+ OnAllocateGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedGpuMemoryBuffer,
+ OnDeletedGpuMemoryBuffer)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -271,9 +278,9 @@ bool ChildProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
void ChildProcessHostImpl::OnChannelConnected(int32 peer_pid) {
if (!peer_handle_ &&
- !base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_) &&
- !(peer_handle_ = delegate_->GetHandle())) {
- NOTREACHED();
+ !base::OpenPrivilegedProcessHandle(peer_pid, &peer_handle_)) {
+ peer_handle_ = delegate_->GetHandle();
+ DCHECK(peer_handle_);
}
opening_channel_ = false;
delegate_->OnChannelConnected(peer_pid);
@@ -310,14 +317,48 @@ void ChildProcessHostImpl::OnShutdownRequest() {
void ChildProcessHostImpl::OnAllocateGpuMemoryBuffer(
uint32 width,
uint32 height,
- uint32 internalformat,
- uint32 usage,
- gfx::GpuMemoryBufferHandle* handle) {
- handle->type = gfx::SHARED_MEMORY_BUFFER;
- AllocateSharedMemory(
- width * height * GpuMemoryBufferImpl::BytesPerPixel(internalformat),
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ IPC::Message* reply) {
+ base::CheckedNumeric<int> size = width;
+ size *= height;
+ if (!size.IsValid()) {
+ GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
+ return;
+ }
+
+ // TODO(reveman): Add support for other types of GpuMemoryBuffers.
+ if (!GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ gfx::Size(width, height), format, usage)) {
+ GpuMemoryBufferAllocated(reply, gfx::GpuMemoryBufferHandle());
+ return;
+ }
+
+ // Note: It is safe to use base::Unretained here as the shared memory
+ // implementation of AllocateForChildProcess() calls this synchronously.
+ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ g_next_gpu_memory_buffer_id.GetNext(),
+ gfx::Size(width, height),
+ format,
peer_handle_,
- &handle->handle);
+ base::Bind(&ChildProcessHostImpl::GpuMemoryBufferAllocated,
+ base::Unretained(this),
+ reply));
+}
+
+void ChildProcessHostImpl::OnDeletedGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ uint32 sync_point) {
+ // Note: Nothing to do here as ownership of shared memory backed
+ // GpuMemoryBuffers is passed with IPC.
+}
+
+void ChildProcessHostImpl::GpuMemoryBufferAllocated(
+ IPC::Message* reply,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer::WriteReplyParams(reply,
+ handle);
+ Send(reply);
}
} // namespace content
diff --git a/chromium/content/common/child_process_host_impl.h b/chromium/content/common/child_process_host_impl.h
index d8a20323500..88c7cf25e83 100644
--- a/chromium/content/common/child_process_host_impl.h
+++ b/chromium/content/common/child_process_host_impl.h
@@ -17,15 +17,12 @@
#include "base/strings/string16.h"
#include "content/public/common/child_process_host.h"
#include "ipc/ipc_listener.h"
+#include "ui/gfx/gpu_memory_buffer.h"
namespace base {
class FilePath;
}
-namespace gfx {
-struct GpuMemoryBufferHandle;
-}
-
namespace IPC {
class MessageFilter;
}
@@ -39,7 +36,7 @@ class ChildProcessHostDelegate;
class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
public IPC::Listener {
public:
- virtual ~ChildProcessHostImpl();
+ ~ChildProcessHostImpl() override;
// Public and static for reuse by RenderMessageFilter.
static void AllocateSharedMemory(
@@ -58,13 +55,13 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
static int GenerateChildProcessUniqueId();
// ChildProcessHost implementation
- virtual bool Send(IPC::Message* message) OVERRIDE;
- virtual void ForceShutdown() OVERRIDE;
- virtual std::string CreateChannel() OVERRIDE;
- virtual bool IsChannelOpening() OVERRIDE;
- virtual void AddFilter(IPC::MessageFilter* filter) OVERRIDE;
+ bool Send(IPC::Message* message) override;
+ void ForceShutdown() override;
+ std::string CreateChannel() override;
+ bool IsChannelOpening() override;
+ void AddFilter(IPC::MessageFilter* filter) override;
#if defined(OS_POSIX)
- virtual int TakeClientFileDescriptor() OVERRIDE;
+ base::ScopedFD TakeClientFileDescriptor() override;
#endif
private:
@@ -73,10 +70,10 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
explicit ChildProcessHostImpl(ChildProcessHostDelegate* delegate);
// IPC::Listener methods:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
- virtual void OnBadMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
+ void OnChannelError() override;
+ void OnBadMessageReceived(const IPC::Message& message) override;
// Message handlers:
void OnShutdownRequest();
@@ -84,9 +81,14 @@ class CONTENT_EXPORT ChildProcessHostImpl : public ChildProcessHost,
base::SharedMemoryHandle* handle);
void OnAllocateGpuMemoryBuffer(uint32 width,
uint32 height,
- uint32 internalformat,
- uint32 usage,
- gfx::GpuMemoryBufferHandle* handle);
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ IPC::Message* reply);
+ void OnDeletedGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
+ uint32 sync_point);
+
+ void GpuMemoryBufferAllocated(IPC::Message* reply,
+ const gfx::GpuMemoryBufferHandle& handle);
ChildProcessHostDelegate* delegate_;
base::ProcessHandle peer_handle_;
diff --git a/chromium/content/common/child_process_messages.h b/chromium/content/common/child_process_messages.h
index 9b44b93537a..948b60ed49a 100644
--- a/chromium/content/common/child_process_messages.h
+++ b/chromium/content/common/child_process_messages.h
@@ -60,30 +60,21 @@ IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuMemoryBufferType,
gfx::GPU_MEMORY_BUFFER_TYPE_LAST)
-#if defined(OS_ANDROID)
-IPC_STRUCT_TRAITS_BEGIN(gfx::SurfaceTextureId)
- IPC_STRUCT_TRAITS_MEMBER(primary_id)
- IPC_STRUCT_TRAITS_MEMBER(secondary_id)
-IPC_STRUCT_TRAITS_END()
-#endif
-
-IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferId)
- IPC_STRUCT_TRAITS_MEMBER(primary_id)
- IPC_STRUCT_TRAITS_MEMBER(secondary_id)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle)
+ IPC_STRUCT_TRAITS_MEMBER(id)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(handle)
- IPC_STRUCT_TRAITS_MEMBER(global_id)
#if defined(OS_MACOSX)
IPC_STRUCT_TRAITS_MEMBER(io_surface_id)
#endif
-#if defined(OS_ANDROID)
- IPC_STRUCT_TRAITS_MEMBER(surface_texture_id)
-#endif
IPC_STRUCT_TRAITS_END()
+IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuMemoryBuffer::Format,
+ gfx::GpuMemoryBuffer::FORMAT_LAST)
+
+IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuMemoryBuffer::Usage,
+ gfx::GpuMemoryBuffer::USAGE_LAST)
+
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -194,6 +185,18 @@ IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TcmallocStats,
IPC_SYNC_MESSAGE_CONTROL4_1(ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
uint32 /* width */,
uint32 /* height */,
- uint32 /* internalformat */,
- uint32 /* usage */,
+ gfx::GpuMemoryBuffer::Format,
+ gfx::GpuMemoryBuffer::Usage,
gfx::GpuMemoryBufferHandle)
+
+// Informs the browser that the child deleted a gpu memory buffer.
+IPC_MESSAGE_CONTROL2(ChildProcessHostMsg_DeletedGpuMemoryBuffer,
+ gfx::GpuMemoryBufferId,
+ uint32 /* sync_point */)
+
+// Asks the browser to create a block of discardable shared memory for the
+// child process.
+IPC_SYNC_MESSAGE_CONTROL1_1(
+ ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory,
+ uint32 /* size */,
+ base::SharedMemoryHandle)
diff --git a/chromium/content/common/child_process_sandbox_support_impl_linux.cc b/chromium/content/common/child_process_sandbox_support_impl_linux.cc
index 8c3c259f54e..5cc8144e5ec 100644
--- a/chromium/content/common/child_process_sandbox_support_impl_linux.cc
+++ b/chromium/content/common/child_process_sandbox_support_impl_linux.cc
@@ -6,6 +6,9 @@
#include <sys/stat.h>
+#include <limits>
+
+#include "base/basictypes.h"
#include "base/debug/trace_event.h"
#include "base/memory/scoped_ptr.h"
#include "base/numerics/safe_conversions.h"
@@ -36,6 +39,7 @@ void GetFallbackFontForCharacter(int32_t character,
std::string family_name;
std::string filename;
+ int fontconfigInterfaceId = 0;
int ttcIndex = 0;
bool isBold = false;
bool isItalic = false;
@@ -44,11 +48,13 @@ void GetFallbackFontForCharacter(int32_t character,
PickleIterator pickle_iter(reply);
if (reply.ReadString(&pickle_iter, &family_name) &&
reply.ReadString(&pickle_iter, &filename) &&
+ reply.ReadInt(&pickle_iter, &fontconfigInterfaceId) &&
reply.ReadInt(&pickle_iter, &ttcIndex) &&
reply.ReadBool(&pickle_iter, &isBold) &&
reply.ReadBool(&pickle_iter, &isItalic)) {
fallbackFont->name = family_name;
fallbackFont->filename = filename;
+ fallbackFont->fontconfigInterfaceId = fontconfigInterfaceId;
fallbackFont->ttcIndex = ttcIndex;
fallbackFont->isBold = isBold;
fallbackFont->isItalic = isItalic;
@@ -56,42 +62,53 @@ void GetFallbackFontForCharacter(int32_t character,
}
}
-void GetRenderStyleForStrike(const char* family, int sizeAndStyle,
+void GetRenderStyleForStrike(const char* family,
+ int size_and_style,
blink::WebFontRenderStyle* out) {
TRACE_EVENT0("sandbox_ipc", "GetRenderStyleForStrike");
+ out->setDefaults();
+
+ if (size_and_style < 0)
+ return;
+
+ const bool bold = size_and_style & 1;
+ const bool italic = size_and_style & 2;
+ const int pixel_size = size_and_style >> 2;
+ if (pixel_size > std::numeric_limits<uint16>::max())
+ return;
+
Pickle request;
request.WriteInt(LinuxSandbox::METHOD_GET_STYLE_FOR_STRIKE);
request.WriteString(family);
- request.WriteInt(sizeAndStyle);
+ request.WriteBool(bold);
+ request.WriteBool(italic);
+ request.WriteUInt16(pixel_size);
uint8_t buf[512];
const ssize_t n = UnixDomainSocket::SendRecvMsg(GetSandboxFD(), buf,
sizeof(buf), NULL, request);
-
- out->setDefaults();
- if (n == -1) {
+ if (n == -1)
return;
- }
Pickle reply(reinterpret_cast<char*>(buf), n);
PickleIterator pickle_iter(reply);
- int useBitmaps, useAutoHint, useHinting, hintStyle, useAntiAlias;
- int useSubpixelRendering, useSubpixelPositioning;
- if (reply.ReadInt(&pickle_iter, &useBitmaps) &&
- reply.ReadInt(&pickle_iter, &useAutoHint) &&
- reply.ReadInt(&pickle_iter, &useHinting) &&
- reply.ReadInt(&pickle_iter, &hintStyle) &&
- reply.ReadInt(&pickle_iter, &useAntiAlias) &&
- reply.ReadInt(&pickle_iter, &useSubpixelRendering) &&
- reply.ReadInt(&pickle_iter, &useSubpixelPositioning)) {
- out->useBitmaps = useBitmaps;
- out->useAutoHint = useAutoHint;
- out->useHinting = useHinting;
- out->hintStyle = hintStyle;
- out->useAntiAlias = useAntiAlias;
- out->useSubpixelRendering = useSubpixelRendering;
- out->useSubpixelPositioning = useSubpixelPositioning;
+ int use_bitmaps, use_autohint, use_hinting, hint_style, use_antialias;
+ int use_subpixel_rendering, use_subpixel_positioning;
+ if (reply.ReadInt(&pickle_iter, &use_bitmaps) &&
+ reply.ReadInt(&pickle_iter, &use_autohint) &&
+ reply.ReadInt(&pickle_iter, &use_hinting) &&
+ reply.ReadInt(&pickle_iter, &hint_style) &&
+ reply.ReadInt(&pickle_iter, &use_antialias) &&
+ reply.ReadInt(&pickle_iter, &use_subpixel_rendering) &&
+ reply.ReadInt(&pickle_iter, &use_subpixel_positioning)) {
+ out->useBitmaps = use_bitmaps;
+ out->useAutoHint = use_autohint;
+ out->useHinting = use_hinting;
+ out->hintStyle = hint_style;
+ out->useAntiAlias = use_antialias;
+ out->useSubpixelRendering = use_subpixel_rendering;
+ out->useSubpixelPositioning = use_subpixel_positioning;
}
}
diff --git a/chromium/content/common/child_process_sandbox_support_impl_linux.h b/chromium/content/common/child_process_sandbox_support_impl_linux.h
index 2bbf76ef84a..50f3c3d3c3b 100644
--- a/chromium/content/common/child_process_sandbox_support_impl_linux.h
+++ b/chromium/content/common/child_process_sandbox_support_impl_linux.h
@@ -16,18 +16,22 @@ struct WebFontRenderStyle;
namespace content {
-// Return a font family which provides glyphs for the Unicode code point
-// specified by |character|
-// character: a UTF32 character
-// preferred_locale: preferred locale identifier for the |character|
-//
-// Returns: a font family instance.
-// The instance has an empty font name if the request could not be satisfied.
+// Returns a font family which provides glyphs for the Unicode code point
+// specified by |character|, a UTF-32 character. |preferred_locale| contains the
+// preferred locale identifier for |character|. The instance has an empty font
+// name if the request could not be satisfied.
void GetFallbackFontForCharacter(const int32_t character,
- const char* preferred_locale,
- blink::WebFallbackFont* family);
-
-void GetRenderStyleForStrike(const char* family, int sizeAndStyle,
+ const char* preferred_locale,
+ blink::WebFallbackFont* family);
+
+// Returns rendering settings for a provided font family, size, and style.
+// |size_and_style| stores the bold setting in its least-significant bit, the
+// italic setting in its second-least-significant bit, and holds the requested
+// size in pixels into its remaining bits.
+// TODO(derat): Update WebSandboxSupport's getRenderStyleForStrike() method to
+// pass the style and size separately instead of packing them into an int.
+void GetRenderStyleForStrike(const char* family,
+ int size_and_style,
blink::WebFontRenderStyle* out);
inline int GetSandboxFD() {
diff --git a/chromium/content/common/common_param_traits_unittest.cc b/chromium/content/common/common_param_traits_unittest.cc
index 95669507179..c1f763af4e2 100644
--- a/chromium/content/common/common_param_traits_unittest.cc
+++ b/chromium/content/common/common_param_traits_unittest.cc
@@ -15,6 +15,7 @@
#include "printing/page_range.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/rect.h"
#include "url/gurl.h"
@@ -84,8 +85,7 @@ TEST(IPCMessageTest, Pair) {
TEST(IPCMessageTest, Bitmap) {
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 5);
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(10, 5);
memset(bitmap.getPixels(), 'A', bitmap.getSize());
IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
@@ -95,7 +95,7 @@ TEST(IPCMessageTest, Bitmap) {
PickleIterator iter(msg);
EXPECT_TRUE(IPC::ParamTraits<SkBitmap>::Read(&msg, &iter, &output));
- EXPECT_EQ(bitmap.config(), output.config());
+ EXPECT_EQ(bitmap.colorType(), output.colorType());
EXPECT_EQ(bitmap.width(), output.width());
EXPECT_EQ(bitmap.height(), output.height());
EXPECT_EQ(bitmap.rowBytes(), output.rowBytes());
diff --git a/chromium/content/common/content_constants_internal.cc b/chromium/content/common/content_constants_internal.cc
index f5da70e3eef..afd5a1734f7 100644
--- a/chromium/content/common/content_constants_internal.cc
+++ b/chromium/content/common/content_constants_internal.cc
@@ -6,12 +6,15 @@
namespace content {
-const int kHungRendererDelayMs = 30000;
+const int64 kHungRendererDelayMs = 30000;
const uint16 kMaxPluginSideLength = 1 << 15;
// 8m pixels.
const uint32 kMaxPluginSize = 8 << 20;
+// 10MiB
+const size_t kMaxLengthOfDataURLString = 1024 * 1024 * 10;
+
const int kTraceEventBrowserProcessSortIndex = -6;
const int kTraceEventRendererProcessSortIndex = -5;
const int kTraceEventPluginProcessSortIndex = -4;
diff --git a/chromium/content/common/content_constants_internal.h b/chromium/content/common/content_constants_internal.h
index 55a2ade3533..a5ce925324a 100644
--- a/chromium/content/common/content_constants_internal.h
+++ b/chromium/content/common/content_constants_internal.h
@@ -11,7 +11,7 @@
namespace content {
// How long to wait before we consider a renderer hung.
-CONTENT_EXPORT extern const int kHungRendererDelayMs;
+CONTENT_EXPORT extern const int64 kHungRendererDelayMs;
// The maximum plugin width and height.
extern const uint16 kMaxPluginSideLength;
@@ -19,6 +19,9 @@ extern const uint16 kMaxPluginSideLength;
// plugin.
extern const uint32 kMaxPluginSize;
+// The maximum length of string as data url.
+extern const size_t kMaxLengthOfDataURLString;
+
// Constants used to organize content processes in about:tracing.
CONTENT_EXPORT extern const int kTraceEventBrowserProcessSortIndex;
CONTENT_EXPORT extern const int kTraceEventRendererProcessSortIndex;
diff --git a/chromium/content/common/content_message_generator.h b/chromium/content/common/content_message_generator.h
index e18ddfe8fed..c8ec407e650 100644
--- a/chromium/content/common/content_message_generator.h
+++ b/chromium/content/common/content_message_generator.h
@@ -8,12 +8,12 @@
#include "content/common/accessibility_messages.h"
#include "content/common/appcache_messages.h"
-#include "content/common/battery_status_messages.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/cc_messages.h"
#include "content/common/clipboard_messages.h"
#include "content/common/database_messages.h"
#include "content/common/desktop_notification_messages.h"
+#include "content/common/device_sensors/device_light_messages.h"
#include "content/common/device_sensors/device_motion_messages.h"
#include "content/common/device_sensors/device_orientation_messages.h"
#include "content/common/devtools_messages.h"
@@ -25,12 +25,13 @@
#include "content/common/fileapi/webblob_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gamepad_messages.h"
+#include "content/common/geofencing_messages.h"
#include "content/common/geolocation_messages.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/image_messages.h"
#include "content/common/indexed_db/indexed_db_messages.h"
#include "content/common/input_messages.h"
-#include "content/common/java_bridge_messages.h"
+#include "content/common/manifest_manager_messages.h"
#include "content/common/media/aec_dump_messages.h"
#include "content/common/media/audio_messages.h"
// TODO(xhwang): Move this to a new ifdef block.
@@ -45,8 +46,8 @@
#include "content/common/message_port_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/mojo/mojo_messages.h"
-#include "content/common/p2p_messages.h"
#include "content/common/pepper_messages.h"
+#include "content/common/platform_notification_messages.h"
#include "content/common/plugin_process_messages.h"
#include "content/common/power_monitor_messages.h"
#include "content/common/push_messaging_messages.h"
@@ -55,7 +56,6 @@
#include "content/common/screen_orientation_messages.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
-#include "content/common/socket_stream_messages.h"
#include "content/common/speech_recognition_messages.h"
#include "content/common/text_input_client_messages.h"
#include "content/common/utility_messages.h"
@@ -63,6 +63,10 @@
#include "content/common/websocket_messages.h"
#include "content/common/worker_messages.h"
+#if defined(ENABLE_WEBRTC)
+#include "content/common/p2p_messages.h"
+#endif
+
#if defined(OS_ANDROID)
#include "content/common/gin_java_bridge_messages.h"
#include "content/common/media/media_player_messages_android.h"
diff --git a/chromium/content/common/content_param_traits.cc b/chromium/content/common/content_param_traits.cc
index 7a1e2aaea8c..0f1ba055121 100644
--- a/chromium/content/common/content_param_traits.cc
+++ b/chromium/content/common/content_param_traits.cc
@@ -12,15 +12,15 @@
namespace IPC {
void ParamTraits<gfx::Range>::Write(Message* m, const gfx::Range& r) {
- m->WriteUInt64(r.start());
- m->WriteUInt64(r.end());
+ m->WriteSizeT(r.start());
+ m->WriteSizeT(r.end());
}
bool ParamTraits<gfx::Range>::Read(const Message* m,
PickleIterator* iter,
gfx::Range* r) {
- uint64 start, end;
- if (!m->ReadUInt64(iter, &start) || !m->ReadUInt64(iter, &end))
+ size_t start, end;
+ if (!m->ReadSizeT(iter, &start) || !m->ReadSizeT(iter, &end))
return false;
r->set_start(start);
r->set_end(end);
diff --git a/chromium/content/common/content_param_traits_macros.h b/chromium/content/common/content_param_traits_macros.h
index 42ce5b155de..1442a86dcf2 100644
--- a/chromium/content/common/content_param_traits_macros.h
+++ b/chromium/content/common/content_param_traits_macros.h
@@ -9,17 +9,24 @@
#define CONTENT_COMMON_CONTENT_PARAM_TRAITS_MACROS_H_
#include "content/common/content_export.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "content/public/common/resource_type.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
-#include "webkit/common/resource_type.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-IPC_ENUM_TRAITS_MAX_VALUE(ResourceType::Type, ResourceType::LAST_TYPE - 1)
+IPC_ENUM_TRAITS_MAX_VALUE(content::ResourceType,
+ content::RESOURCE_TYPE_LAST_TYPE - 1)
+IPC_ENUM_TRAITS_MAX_VALUE(content::RequestContextType,
+ content::REQUEST_CONTEXT_TYPE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::RequestContextFrameType,
+ content::REQUEST_CONTEXT_FRAME_TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebContentSecurityPolicyType,
blink::WebContentSecurityPolicyTypeLast)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebInputEvent::Type,
diff --git a/chromium/content/common/content_paths.cc b/chromium/content/common/content_paths.cc
index b17b4fa2a55..0c705011348 100644
--- a/chromium/content/common/content_paths.cc
+++ b/chromium/content/common/content_paths.cc
@@ -4,7 +4,7 @@
#include "content/public/common/content_paths.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/mac/bundle_locations.h"
#include "base/path_service.h"
diff --git a/chromium/content/common/content_switches_internal.cc b/chromium/content/common/content_switches_internal.cc
index 2f0638fbfba..76d877224a4 100644
--- a/chromium/content/common/content_switches_internal.cc
+++ b/chromium/content/common/content_switches_internal.cc
@@ -14,7 +14,8 @@
namespace content {
bool IsPinchToZoomEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
// --disable-pinch should always disable pinch
if (command_line.HasSwitch(switches::kDisablePinch))
diff --git a/chromium/content/common/cursors/DEPS b/chromium/content/common/cursors/DEPS
index 6fcf9c8c38e..cda6df7c7aa 100644
--- a/chromium/content/common/cursors/DEPS
+++ b/chromium/content/common/cursors/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+grit/ui_unscaled_resources.h",
"+third_party/WebKit/public/platform",
]
diff --git a/chromium/content/common/cursors/webcursor.cc b/chromium/content/common/cursors/webcursor.cc
index e2b0442f955..85721fdd0e2 100644
--- a/chromium/content/common/cursors/webcursor.cc
+++ b/chromium/content/common/cursors/webcursor.cc
@@ -243,10 +243,7 @@ void WebCursor::ImageFromCustomData(SkBitmap* image) const {
if (custom_data_.empty())
return;
- image->setConfig(SkBitmap::kARGB_8888_Config,
- custom_size_.width(),
- custom_size_.height());
- if (!image->allocPixels())
+ if (!image->tryAllocN32Pixels(custom_size_.width(), custom_size_.height()))
return;
memcpy(image->getPixels(), &custom_data_[0], custom_data_.size());
}
diff --git a/chromium/content/common/cursors/webcursor.h b/chromium/content/common/cursors/webcursor.h
index a5e2aedb174..d53fbd0514a 100644
--- a/chromium/content/common/cursors/webcursor.h
+++ b/chromium/content/common/cursors/webcursor.h
@@ -104,7 +104,7 @@ class CONTENT_EXPORT WebCursor {
#endif
#if defined(USE_AURA)
- const ui::PlatformCursor GetPlatformCursor();
+ ui::PlatformCursor GetPlatformCursor();
// Updates |device_scale_factor_| and |rotation_| based on |display|.
void SetDisplayInfo(const gfx::Display& display);
@@ -172,11 +172,14 @@ class CONTENT_EXPORT WebCursor {
// Only used for custom cursors.
ui::PlatformCursor platform_cursor_;
float device_scale_factor_;
- gfx::Display::Rotation rotation_;
#elif defined(OS_WIN)
// A custom cursor created from custom bitmap data by Webkit.
HCURSOR custom_cursor_;
#endif
+
+#if defined(USE_OZONE)
+ gfx::Display::Rotation rotation_;
+#endif
};
} // namespace content
diff --git a/chromium/content/common/cursors/webcursor_aurawin.cc b/chromium/content/common/cursors/webcursor_aurawin.cc
index 5f61ed7e579..15ae5b46c3f 100644
--- a/chromium/content/common/cursors/webcursor_aurawin.cc
+++ b/chromium/content/common/cursors/webcursor_aurawin.cc
@@ -11,7 +11,7 @@
namespace content {
-const ui::PlatformCursor WebCursor::GetPlatformCursor() {
+ui::PlatformCursor WebCursor::GetPlatformCursor() {
if (!IsCustom())
return LoadCursor(NULL, IDC_ARROW);
diff --git a/chromium/content/common/cursors/webcursor_aurax11.cc b/chromium/content/common/cursors/webcursor_aurax11.cc
index 793fe239533..dbd2b213448 100644
--- a/chromium/content/common/cursors/webcursor_aurax11.cc
+++ b/chromium/content/common/cursors/webcursor_aurax11.cc
@@ -17,7 +17,7 @@
namespace content {
-const ui::PlatformCursor WebCursor::GetPlatformCursor() {
+ui::PlatformCursor WebCursor::GetPlatformCursor() {
if (platform_cursor_)
return platform_cursor_;
@@ -25,13 +25,11 @@ const ui::PlatformCursor WebCursor::GetPlatformCursor() {
return 0;
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- custom_size_.width(), custom_size_.height());
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(custom_size_.width(), custom_size_.height());
memcpy(bitmap.getAddr32(0, 0), custom_data_.data(), custom_data_.size());
gfx::Point hotspot = hotspot_;
ui::ScaleAndRotateCursorBitmapAndHotpoint(
- device_scale_factor_, rotation_, &bitmap, &hotspot);
+ device_scale_factor_, gfx::Display::ROTATE_0, &bitmap, &hotspot);
XcursorImage* image = ui::SkBitmapToXcursorImage(&bitmap, hotspot);
platform_cursor_ = ui::CreateReffedCustomXCursor(image);
@@ -39,12 +37,10 @@ const ui::PlatformCursor WebCursor::GetPlatformCursor() {
}
void WebCursor::SetDisplayInfo(const gfx::Display& display) {
- if (rotation_ == display.rotation() &&
- device_scale_factor_ == display.device_scale_factor())
+ if (device_scale_factor_ == display.device_scale_factor())
return;
device_scale_factor_ = display.device_scale_factor();
- rotation_ = display.rotation();
if (platform_cursor_)
ui::UnrefCustomXCursor(platform_cursor_);
platform_cursor_ = 0;
@@ -55,7 +51,6 @@ void WebCursor::SetDisplayInfo(const gfx::Display& display) {
void WebCursor::InitPlatformData() {
platform_cursor_ = 0;
device_scale_factor_ = 1.f;
- rotation_ = gfx::Display::ROTATE_0;
}
bool WebCursor::SerializePlatformData(Pickle* pickle) const {
diff --git a/chromium/content/common/cursors/webcursor_mac.mm b/chromium/content/common/cursors/webcursor_mac.mm
index 6a401321b38..2c0c2aa87ef 100644
--- a/chromium/content/common/cursors/webcursor_mac.mm
+++ b/chromium/content/common/cursors/webcursor_mac.mm
@@ -10,8 +10,8 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/sdk_forward_declarations.h"
+#include "content/app/resources/grit/content_resources.h"
#include "content/public/common/content_client.h"
-#include "grit/webkit_resources.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -19,7 +19,6 @@
#include "ui/gfx/point_conversions.h"
#include "ui/gfx/size_conversions.h"
-
using blink::WebCursorInfo;
using blink::WebSize;
@@ -152,9 +151,7 @@ NSCursor* CreateCustomCursor(const std::vector<char>& custom_data,
}
SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- bitmap.allocPixels();
- if (data)
+ if (bitmap.tryAllocN32Pixels(size.width(), size.height()) && data)
memcpy(bitmap.getAddr32(0, 0), data, data_size);
else
bitmap.eraseARGB(0, 0, 0, 0);
diff --git a/chromium/content/common/cursors/webcursor_ozone.cc b/chromium/content/common/cursors/webcursor_ozone.cc
index fe3dbd9d273..39a356d2834 100644
--- a/chromium/content/common/cursors/webcursor_ozone.cc
+++ b/chromium/content/common/cursors/webcursor_ozone.cc
@@ -11,7 +11,7 @@
namespace content {
-const ui::PlatformCursor WebCursor::GetPlatformCursor() {
+ui::PlatformCursor WebCursor::GetPlatformCursor() {
if (platform_cursor_)
return platform_cursor_;
diff --git a/chromium/content/common/database_connections_unittest.cc b/chromium/content/common/database_connections_unittest.cc
index 8d460888640..7f9a9b27cb5 100644
--- a/chromium/content/common/database_connections_unittest.cc
+++ b/chromium/content/common/database_connections_unittest.cc
@@ -6,12 +6,12 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
+#include "storage/common/database/database_connections.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/common/database/database_connections.h"
using base::ASCIIToUTF16;
-using webkit_database::DatabaseConnections;
-using webkit_database::DatabaseConnectionsWrapper;
+using storage::DatabaseConnections;
+using storage::DatabaseConnectionsWrapper;
namespace content {
diff --git a/chromium/content/common/database_identifier_unittest.cc b/chromium/content/common/database_identifier_unittest.cc
index 2bd2e78c7b5..c2cc9fe72b9 100644
--- a/chromium/content/common/database_identifier_unittest.cc
+++ b/chromium/content/common/database_identifier_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/common/database/database_identifier.h"
+#include "storage/common/database/database_identifier.h"
#include "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-using webkit_database::DatabaseIdentifier;
+using storage::DatabaseIdentifier;
namespace content {
namespace {
@@ -35,7 +35,7 @@ TEST(DatabaseIdentifierTest, CreateIdentifierFromOrigin) {
{"non-standard://foobar.com", "__0"},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ for (size_t i = 0; i < arraysize(cases); ++i) {
GURL origin(cases[i].origin);
DatabaseIdentifier identifier =
DatabaseIdentifier::CreateFromOrigin(origin);
@@ -152,7 +152,7 @@ TEST(DatabaseIdentifierTest, CreateIdentifierAllHostChars) {
{"x\x80x", "__0", false},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ for (size_t i = 0; i < arraysize(cases); ++i) {
GURL origin("http://" + cases[i].hostname);
DatabaseIdentifier identifier =
DatabaseIdentifier::CreateFromOrigin(origin);
@@ -203,7 +203,7 @@ TEST(DatabaseIdentifierTest, ExtractOriginDataFromIdentifier) {
GURL("http://escaped%3dfun.com"), false},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(valid_cases); ++i) {
+ for (size_t i = 0; i < arraysize(valid_cases); ++i) {
DatabaseIdentifier identifier =
DatabaseIdentifier::Parse(valid_cases[i].str);
EXPECT_EQ(valid_cases[i].expected_scheme, identifier.scheme())
@@ -231,7 +231,7 @@ TEST(DatabaseIdentifierTest, ExtractOriginDataFromIdentifier) {
"http_bytes_after_port_0abcd",
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(bogus_components); ++i) {
+ for (size_t i = 0; i < arraysize(bogus_components); ++i) {
DatabaseIdentifier identifier =
DatabaseIdentifier::Parse(bogus_components[i]);
EXPECT_EQ("__0", identifier.ToString())
diff --git a/chromium/content/common/desktop_notification_messages.h b/chromium/content/common/desktop_notification_messages.h
index 48506dd8cf8..3b2215d0bda 100644
--- a/chromium/content/common/desktop_notification_messages.h
+++ b/chromium/content/common/desktop_notification_messages.h
@@ -12,7 +12,7 @@
IPC_STRUCT_TRAITS_BEGIN(content::ShowDesktopNotificationHostMsgParams)
IPC_STRUCT_TRAITS_MEMBER(origin)
- IPC_STRUCT_TRAITS_MEMBER(icon_url)
+ IPC_STRUCT_TRAITS_MEMBER(icon)
IPC_STRUCT_TRAITS_MEMBER(title)
IPC_STRUCT_TRAITS_MEMBER(body)
IPC_STRUCT_TRAITS_MEMBER(direction)
@@ -26,11 +26,6 @@ IPC_STRUCT_TRAITS_END()
IPC_MESSAGE_ROUTED1(DesktopNotificationMsg_PostDisplay,
int /* notification_id */)
-// Used to inform the renderer that the browser has encountered an error
-// trying to display a notification.
-IPC_MESSAGE_ROUTED1(DesktopNotificationMsg_PostError,
- int /* notification_id */)
-
// Informs the renderer that the one if its notifications has closed.
IPC_MESSAGE_ROUTED2(DesktopNotificationMsg_PostClose,
int /* notification_id */,
@@ -40,10 +35,6 @@ IPC_MESSAGE_ROUTED2(DesktopNotificationMsg_PostClose,
IPC_MESSAGE_ROUTED1(DesktopNotificationMsg_PostClick,
int /* notification_id */)
-// Informs the renderer that the one if its notifications has closed.
-IPC_MESSAGE_ROUTED1(DesktopNotificationMsg_PermissionRequestDone,
- int /* request_id */)
-
// Messages sent from the renderer to the browser.
IPC_MESSAGE_ROUTED2(DesktopNotificationHostMsg_Show,
@@ -53,10 +44,6 @@ IPC_MESSAGE_ROUTED2(DesktopNotificationHostMsg_Show,
IPC_MESSAGE_ROUTED1(DesktopNotificationHostMsg_Cancel,
int /* notification_id */)
-IPC_MESSAGE_ROUTED2(DesktopNotificationHostMsg_RequestPermission,
- GURL /* origin */,
- int /* callback_context */)
-
IPC_SYNC_MESSAGE_ROUTED1_1(DesktopNotificationHostMsg_CheckPermission,
GURL /* origin */,
int /* permission_result */)
diff --git a/chromium/content/common/device_sensors/device_light_data.h b/chromium/content/common/device_sensors/device_light_data.h
new file mode 100644
index 00000000000..08140566826
--- /dev/null
+++ b/chromium/content/common/device_sensors/device_light_data.h
@@ -0,0 +1,23 @@
+// Copyright 2014 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 CONTENT_COMMON_DEVICE_SENSORS_DEVICE_LIGHT_DATA_H_
+#define CONTENT_COMMON_DEVICE_SENSORS_DEVICE_LIGHT_DATA_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// This struct is intentionally POD and fixed size so that it can be stored
+// in shared memory between the browser and the renderer processes.
+// POD class should be a struct, should have an inline cstor that uses
+// initializer lists and no dstor.
+struct DeviceLightData {
+ DeviceLightData() : value(-1) {}
+ double value;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_DEVICE_SENSORS_DEVICE_LIGHT_DATA_H_
diff --git a/chromium/content/common/device_sensors/device_light_hardware_buffer.h b/chromium/content/common/device_sensors/device_light_hardware_buffer.h
new file mode 100644
index 00000000000..dcd0f1b57f7
--- /dev/null
+++ b/chromium/content/common/device_sensors/device_light_hardware_buffer.h
@@ -0,0 +1,17 @@
+// Copyright 2014 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 CONTENT_COMMON_DEVICE_SENSORS_DEVICE_LIGHT_HARDWARE_BUFFER_H_
+#define CONTENT_COMMON_DEVICE_SENSORS_DEVICE_LIGHT_HARDWARE_BUFFER_H_
+
+#include "content/common/device_sensors/device_light_data.h"
+#include "content/common/shared_memory_seqlock_buffer.h"
+
+namespace content {
+
+typedef SharedMemorySeqLockBuffer<DeviceLightData> DeviceLightHardwareBuffer;
+
+} // namespace content
+
+#endif // CONTENT_COMMON_DEVICE_SENSORS_DEVICE_LIGHT_HARDWARE_BUFFER_H_
diff --git a/chromium/content/common/device_sensors/device_light_messages.h b/chromium/content/common/device_sensors/device_light_messages.h
new file mode 100644
index 00000000000..4fad255468b
--- /dev/null
+++ b/chromium/content/common/device_sensors/device_light_messages.h
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+// IPC messages for device light.
+// Multiply-included message file, hence no include guard.
+
+#include "base/memory/shared_memory.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_platform_file.h"
+
+#define IPC_MESSAGE_START DeviceLightMsgStart
+
+// Asks the browser process to activate Device Light sensors if necessary.
+IPC_MESSAGE_CONTROL0(DeviceLightHostMsg_StartPolling)
+
+// The browser process asynchronously returns the shared memory handle that
+// will hold the data from the hardware sensors.
+IPC_MESSAGE_CONTROL1(DeviceLightMsg_DidStartPolling,
+ base::SharedMemoryHandle /* handle */)
+
+// Notifies the browser process that the renderer process is not using the
+// Device Light data anymore. The number of Starts should match the number
+// of Stops.
+IPC_MESSAGE_CONTROL0(DeviceLightHostMsg_StopPolling)
diff --git a/chromium/content/common/devtools_messages.h b/chromium/content/common/devtools_messages.h
index 3e148640d45..276a82f9678 100644
--- a/chromium/content/common/devtools_messages.h
+++ b/chromium/content/common/devtools_messages.h
@@ -55,8 +55,13 @@
// These are messages sent from DevToolsAgent to DevToolsClient through the
// browser.
// WebKit-level transport.
-IPC_MESSAGE_ROUTED1(DevToolsClientMsg_DispatchOnInspectorFrontend,
- std::string /* message */)
+
+// Sends response from the agent to the client. Supports chunked encoding.
+// First (the only) chunk arrives with the |total_size| != 0,
+// remaining chunks arrive with |total_size| == 0.
+IPC_MESSAGE_ROUTED2(DevToolsClientMsg_DispatchOnInspectorFrontend,
+ std::string /* message */,
+ uint32 /* total_size */)
//-----------------------------------------------------------------------------
// These are messages sent from DevToolsClient to DevToolsAgent through the
@@ -89,9 +94,6 @@ IPC_MESSAGE_ROUTED2(DevToolsAgentMsg_AddMessageToConsole,
content::ConsoleMessageLevel /* level */,
std::string /* message */)
-// Worker DevTools agent should resume worker execution.
-IPC_MESSAGE_ROUTED0(DevToolsAgentMsg_ResumeWorkerContext)
-
//-----------------------------------------------------------------------------
// These are messages sent from the browser to the renderer.
diff --git a/chromium/content/common/dom_storage/OWNERS b/chromium/content/common/dom_storage/OWNERS
index 8f41e3d626c..043f130dc03 100644
--- a/chromium/content/common/dom_storage/OWNERS
+++ b/chromium/content/common/dom_storage/OWNERS
@@ -4,12 +4,13 @@ michaeln@chromium.org
# Changes to IPC messages require a security review to avoid introducing
# new sandbox escapes.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/fileapi/OWNERS b/chromium/content/common/fileapi/OWNERS
index 2c20f1191f1..334a61ec4c5 100644
--- a/chromium/content/common/fileapi/OWNERS
+++ b/chromium/content/common/fileapi/OWNERS
@@ -1,16 +1,18 @@
-ericu@chromium.org
kinuko@chromium.org
michaeln@chromium.org
jianli@chromium.org
+tzik@chromium.org
+nhiroki@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/fileapi/file_system_messages.h b/chromium/content/common/fileapi/file_system_messages.h
index 933423aa002..5b620b881f9 100644
--- a/chromium/content/common/fileapi/file_system_messages.h
+++ b/chromium/content/common/fileapi/file_system_messages.h
@@ -7,29 +7,29 @@
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
+#include "storage/common/fileapi/directory_entry.h"
+#include "storage/common/fileapi/file_system_info.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "storage/common/quota/quota_types.h"
#include "url/gurl.h"
-#include "webkit/common/fileapi/directory_entry.h"
-#include "webkit/common/fileapi/file_system_info.h"
-#include "webkit/common/fileapi/file_system_types.h"
-#include "webkit/common/quota/quota_types.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START FileSystemMsgStart
-IPC_STRUCT_TRAITS_BEGIN(fileapi::DirectoryEntry)
+IPC_STRUCT_TRAITS_BEGIN(storage::DirectoryEntry)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(is_directory)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(fileapi::FileSystemInfo)
+IPC_STRUCT_TRAITS_BEGIN(storage::FileSystemInfo)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(root_url)
IPC_STRUCT_TRAITS_MEMBER(mount_type)
IPC_STRUCT_TRAITS_END()
-IPC_ENUM_TRAITS(fileapi::FileSystemType)
-IPC_ENUM_TRAITS(quota::QuotaLimitType)
+IPC_ENUM_TRAITS(storage::FileSystemType)
+IPC_ENUM_TRAITS_MAX_VALUE(storage::QuotaLimitType, storage::kQuotaLimitTypeLast)
// File system messages sent from the browser to the child process.
@@ -42,7 +42,7 @@ IPC_MESSAGE_CONTROL3(FileSystemMsg_DidOpenFileSystem,
// WebFileSystem response messages.
IPC_MESSAGE_CONTROL4(FileSystemMsg_DidResolveURL,
int /* request_id */,
- fileapi::FileSystemInfo /* filesystem_info */,
+ storage::FileSystemInfo /* filesystem_info */,
base::FilePath /* file_path */,
bool /* is_directory */)
IPC_MESSAGE_CONTROL1(FileSystemMsg_DidSucceed,
@@ -56,17 +56,12 @@ IPC_MESSAGE_CONTROL3(FileSystemMsg_DidCreateSnapshotFile,
base::FilePath /* true platform path */)
IPC_MESSAGE_CONTROL3(FileSystemMsg_DidReadDirectory,
int /* request_id */,
- std::vector<fileapi::DirectoryEntry> /* entries */,
+ std::vector<storage::DirectoryEntry> /* entries */,
bool /* has_more */)
IPC_MESSAGE_CONTROL3(FileSystemMsg_DidWrite,
int /* request_id */,
int64 /* byte count */,
bool /* complete */)
-IPC_MESSAGE_CONTROL4(FileSystemMsg_DidOpenFile,
- int /* request_id */,
- IPC::PlatformFileForTransit,
- int /* file_open_id */,
- quota::QuotaLimitType /* quota_policy */)
IPC_MESSAGE_CONTROL2(FileSystemMsg_DidFail,
int /* request_id */,
base::File::Error /* error_code */)
@@ -77,7 +72,7 @@ IPC_MESSAGE_CONTROL2(FileSystemMsg_DidFail,
IPC_MESSAGE_CONTROL3(FileSystemHostMsg_OpenFileSystem,
int /* request_id */,
GURL /* origin_url */,
- fileapi::FileSystemType /* type */)
+ storage::FileSystemType /* type */)
// WevFrameClient::resolveURL() message.
IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ResolveURL,
@@ -88,7 +83,7 @@ IPC_MESSAGE_CONTROL2(FileSystemHostMsg_ResolveURL,
IPC_MESSAGE_CONTROL3(FileSystemHostMsg_DeleteFileSystem,
int /* request_id */,
GURL /* origin_url */,
- fileapi::FileSystemType /* type */)
+ storage::FileSystemType /* type */)
// WebFileSystem::move() message.
IPC_MESSAGE_CONTROL3(FileSystemHostMsg_Move,
diff --git a/chromium/content/common/fileapi/file_system_util_unittest.cc b/chromium/content/common/fileapi/file_system_util_unittest.cc
index 0e8f6f8f1e1..9dc47ddf8f7 100644
--- a/chromium/content/common/fileapi/file_system_util_unittest.cc
+++ b/chromium/content/common/fileapi/file_system_util_unittest.cc
@@ -2,18 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/common/fileapi/file_system_util.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "base/files/file_path.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-using fileapi::CrackIsolatedFileSystemName;
-using fileapi::GetExternalFileSystemRootURIString;
-using fileapi::GetIsolatedFileSystemName;
-using fileapi::GetIsolatedFileSystemRootURIString;
-using fileapi::ValidateIsolatedFileSystemId;
-using fileapi::VirtualPath;
+using storage::CrackIsolatedFileSystemName;
+using storage::GetExternalFileSystemRootURIString;
+using storage::GetIsolatedFileSystemName;
+using storage::GetIsolatedFileSystemRootURIString;
+using storage::ValidateIsolatedFileSystemId;
+using storage::VirtualPath;
namespace content {
namespace {
@@ -23,11 +23,11 @@ class FileSystemUtilTest : public testing::Test {};
TEST_F(FileSystemUtilTest, ParseFileSystemSchemeURL) {
GURL uri("filesystem:http://chromium.org/temporary/foo/bar");
GURL origin_url;
- fileapi::FileSystemType type;
+ storage::FileSystemType type;
base::FilePath virtual_path;
ParseFileSystemSchemeURL(uri, &origin_url, &type, &virtual_path);
EXPECT_EQ(GURL("http://chromium.org"), origin_url);
- EXPECT_EQ(fileapi::kFileSystemTypeTemporary, type);
+ EXPECT_EQ(storage::kFileSystemTypeTemporary, type);
#if defined(FILE_PATH_USES_WIN_SEPARATORS)
base::FilePath expected_path(FILE_PATH_LITERAL("foo\\bar"));
#else
@@ -38,14 +38,14 @@ TEST_F(FileSystemUtilTest, ParseFileSystemSchemeURL) {
TEST_F(FileSystemUtilTest, GetTempFileSystemRootURI) {
GURL origin_url("http://chromium.org");
- fileapi::FileSystemType type = fileapi::kFileSystemTypeTemporary;
+ storage::FileSystemType type = storage::kFileSystemTypeTemporary;
GURL uri = GURL("filesystem:http://chromium.org/temporary/");
EXPECT_EQ(uri, GetFileSystemRootURI(origin_url, type));
}
TEST_F(FileSystemUtilTest, GetPersistentFileSystemRootURI) {
GURL origin_url("http://chromium.org");
- fileapi::FileSystemType type = fileapi::kFileSystemTypePersistent;
+ storage::FileSystemType type = storage::kFileSystemTypePersistent;
GURL uri = GURL("filesystem:http://chromium.org/persistent/");
EXPECT_EQ(uri, GetFileSystemRootURI(origin_url, type));
}
@@ -69,7 +69,7 @@ TEST_F(FileSystemUtilTest, VirtualPathBaseName) {
{ FILE_PATH_LITERAL("////bar"), FILE_PATH_LITERAL("bar") },
{ FILE_PATH_LITERAL("bar"), FILE_PATH_LITERAL("bar") }
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
base::FilePath input = base::FilePath(test_cases[i].path);
base::FilePath base_name = VirtualPath::BaseName(input);
EXPECT_EQ(test_cases[i].base_name, base_name.value());
@@ -109,7 +109,7 @@ TEST_F(FileSystemUtilTest, VirtualPathDirName) {
{ FILE_PATH_LITERAL("\\\\\\\\bar"), FILE_PATH_LITERAL("\\") },
#endif
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
base::FilePath input = base::FilePath(test_cases[i].path);
base::FilePath dir_name = VirtualPath::DirName(input);
EXPECT_EQ(test_cases[i].dir_name, dir_name.value());
@@ -129,7 +129,7 @@ TEST_F(FileSystemUtilTest, GetNormalizedFilePath) {
{ FILE_PATH_LITERAL("\\foo"), FILE_PATH_LITERAL("/foo") },
#endif
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
base::FilePath input = base::FilePath(test_cases[i].path);
base::FilePath::StringType normalized_path_string =
VirtualPath::GetNormalizedFilePath(input);
@@ -194,7 +194,7 @@ TEST_F(FileSystemUtilTest, VirtualPathGetComponents) {
{ FILE_PATH_LITERAL("c:"), FILE_PATH_LITERAL("bar") } },
#endif
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
base::FilePath input = base::FilePath(test_cases[i].path);
std::vector<base::FilePath::StringType> components;
VirtualPath::GetComponents(input, &components);
@@ -202,7 +202,7 @@ TEST_F(FileSystemUtilTest, VirtualPathGetComponents) {
for (size_t j = 0; j < components.size(); ++j)
EXPECT_EQ(test_cases[i].components[j], components[j]);
}
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); ++i) {
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
base::FilePath input = base::FilePath(test_cases[i].path);
std::vector<std::string> components;
VirtualPath::GetComponentsUTF8Unsafe(input, &components);
diff --git a/chromium/content/common/fileapi/webblob_messages.h b/chromium/content/common/fileapi/webblob_messages.h
index b4399e7f472..f1dcea67a57 100644
--- a/chromium/content/common/fileapi/webblob_messages.h
+++ b/chromium/content/common/fileapi/webblob_messages.h
@@ -8,7 +8,7 @@
#include "content/common/content_export.h"
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
-#include "webkit/common/blob/blob_data.h"
+#include "storage/common/blob/blob_data.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -20,7 +20,7 @@ IPC_MESSAGE_CONTROL1(BlobHostMsg_StartBuilding,
std::string /*uuid */)
IPC_MESSAGE_CONTROL2(BlobHostMsg_AppendBlobDataItem,
std::string /* uuid */,
- webkit_blob::BlobData::Item)
+ storage::BlobData::Item)
IPC_SYNC_MESSAGE_CONTROL3_0(BlobHostMsg_SyncAppendSharedMemory,
std::string /*uuid*/,
base::SharedMemoryHandle,
@@ -49,7 +49,7 @@ IPC_MESSAGE_CONTROL2(StreamHostMsg_StartBuilding,
// Appends data to a stream being built.
IPC_MESSAGE_CONTROL2(StreamHostMsg_AppendBlobDataItem,
GURL /* url */,
- webkit_blob::BlobData::Item)
+ storage::BlobData::Item)
// Appends data to a stream being built.
IPC_SYNC_MESSAGE_CONTROL3_0(StreamHostMsg_SyncAppendSharedMemory,
diff --git a/chromium/content/common/font_cache_dispatcher_win.h b/chromium/content/common/font_cache_dispatcher_win.h
index 913f857649f..357aed6b491 100644
--- a/chromium/content/common/font_cache_dispatcher_win.h
+++ b/chromium/content/common/font_cache_dispatcher_win.h
@@ -23,13 +23,13 @@ class FontCacheDispatcher : public IPC::MessageFilter, public IPC::Sender {
virtual ~FontCacheDispatcher();
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ virtual bool Send(IPC::Message* message) override;
private:
// IPC::MessageFilter implementation:
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ virtual void OnFilterAdded(IPC::Sender* sender) override;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
+ virtual void OnChannelClosing() override;
// Message handlers.
void OnPreCacheFont(const LOGFONT& font);
diff --git a/chromium/content/common/font_config_ipc_linux.cc b/chromium/content/common/font_config_ipc_linux.cc
index 2d976c48b09..fcb06ebac0d 100644
--- a/chromium/content/common/font_config_ipc_linux.cc
+++ b/chromium/content/common/font_config_ipc_linux.cc
@@ -13,7 +13,7 @@
#include <unistd.h>
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/pickle.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "skia/ext/refptr.h"
diff --git a/chromium/content/common/font_config_ipc_linux.h b/chromium/content/common/font_config_ipc_linux.h
index 0325dc48280..c5cf80f7274 100644
--- a/chromium/content/common/font_config_ipc_linux.h
+++ b/chromium/content/common/font_config_ipc_linux.h
@@ -17,15 +17,15 @@ namespace content {
class FontConfigIPC : public SkFontConfigInterface {
public:
explicit FontConfigIPC(int fd);
- virtual ~FontConfigIPC();
+ ~FontConfigIPC() override;
- virtual bool matchFamilyName(const char familyName[],
- SkTypeface::Style requested,
- FontIdentity* outFontIdentifier,
- SkString* outFamilyName,
- SkTypeface::Style* outStyle) OVERRIDE;
+ bool matchFamilyName(const char familyName[],
+ SkTypeface::Style requested,
+ FontIdentity* outFontIdentifier,
+ SkString* outFamilyName,
+ SkTypeface::Style* outStyle) override;
- virtual SkStream* openStream(const FontIdentity&) OVERRIDE;
+ SkStream* openStream(const FontIdentity&) override;
enum Method {
METHOD_MATCH = 0,
diff --git a/chromium/content/common/frame_message_enums.h b/chromium/content/common/frame_message_enums.h
index d2f9d8af14f..c45989645f7 100644
--- a/chromium/content/common/frame_message_enums.h
+++ b/chromium/content/common/frame_message_enums.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_COMMON_FRAME_MESSAGES_ENUMS_H_
#define CONTENT_COMMON_FRAME_MESSAGES_ENUMS_H_
-#include "ipc/ipc_message_macros.h"
+#include "content/common/accessibility_mode_enums.h"
struct FrameMsg_Navigate_Type {
public:
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
index ee1326c45c6..7d03f8c508c 100644
--- a/chromium/content/common/frame_messages.h
+++ b/chromium/content/common/frame_messages.h
@@ -10,13 +10,18 @@
#include "content/common/frame_message_enums.h"
#include "content/common/frame_param.h"
#include "content/common/navigation_gesture.h"
+#include "content/common/navigation_params.h"
+#include "content/common/resource_request_body.h"
#include "content/public/common/color_suggestion.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/frame_navigate_params.h"
#include "content/public/common/javascript_message_type.h"
#include "content/public/common/page_state.h"
+#include "content/public/common/resource_response.h"
+#include "content/public/common/transition_element.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "url/gurl.h"
#undef IPC_MESSAGE_EXPORT
@@ -24,6 +29,9 @@
#define IPC_MESSAGE_START FrameMsgStart
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(AccessibilityMode,
+ AccessibilityModeOff,
+ AccessibilityModeComplete)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::JavaScriptMessageType,
content::JAVASCRIPT_MESSAGE_TYPE_ALERT,
content::JAVASCRIPT_MESSAGE_TYPE_PROMPT)
@@ -53,6 +61,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::ContextMenuParams)
IPC_STRUCT_TRAITS_MEMBER(frame_page_state)
IPC_STRUCT_TRAITS_MEMBER(media_flags)
IPC_STRUCT_TRAITS_MEMBER(selection_text)
+ IPC_STRUCT_TRAITS_MEMBER(suggested_filename)
IPC_STRUCT_TRAITS_MEMBER(misspelled_word)
IPC_STRUCT_TRAITS_MEMBER(misspelling_hash)
IPC_STRUCT_TRAITS_MEMBER(dictionary_suggestions)
@@ -78,11 +87,23 @@ IPC_STRUCT_TRAITS_BEGIN(content::CustomContextMenuContext)
IPC_STRUCT_TRAITS_MEMBER(is_pepper_menu)
IPC_STRUCT_TRAITS_MEMBER(request_id)
IPC_STRUCT_TRAITS_MEMBER(render_widget_id)
+ IPC_STRUCT_TRAITS_MEMBER(link_followed)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::TransitionElement)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(rect)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_BEGIN(FrameHostMsg_AddNavigationTransitionData_Params)
+ IPC_STRUCT_MEMBER(int, render_frame_id)
+ IPC_STRUCT_MEMBER(std::string, allowed_destination_host_pattern)
+ IPC_STRUCT_MEMBER(std::string, selector)
+ IPC_STRUCT_MEMBER(std::string, markup)
+ IPC_STRUCT_MEMBER(std::vector<content::TransitionElement>, elements)
+IPC_STRUCT_END()
+
IPC_STRUCT_BEGIN(FrameHostMsg_DidFailProvisionalLoadWithError_Params)
- // The WebFrame's uniqueName().
- IPC_STRUCT_MEMBER(base::string16, frame_unique_name)
// Error code as reported in the DidFailProvisionalLoad callback.
IPC_STRUCT_MEMBER(int, error_code)
// An error message generated from the error_code. This can be an empty
@@ -114,8 +135,6 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
content::FrameNavigateParams)
IPC_STRUCT_TRAITS_PARENT(content::FrameNavigateParams)
- // The WebFrame's uniqueName().
- IPC_STRUCT_MEMBER(base::string16, frame_unique_name)
// Information regarding the security of the connection (empty if the
// connection was not secure).
@@ -138,6 +157,10 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
// The status code of the HTTP request.
IPC_STRUCT_MEMBER(int, http_status_code)
+ // This flag is used to warn if the renderer is displaying an error page,
+ // so that we can set the appropriate page type.
+ IPC_STRUCT_MEMBER(bool, url_is_unreachable)
+
// True if the connection was proxied. In this case, socket_address
// will represent the address of the proxy, rather than the remote host.
IPC_STRUCT_MEMBER(bool, was_fetched_via_proxy)
@@ -154,9 +177,47 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
// Notifies the browser that for this navigation, the session history was
// successfully cleared.
IPC_STRUCT_MEMBER(bool, history_list_was_cleared)
+
+ // The routing_id of the render view associated with the navigation.
+ // We need to track the RenderViewHost routing_id because of downstream
+ // dependencies (crbug.com/392171 DownloadRequestHandle, SaveFileManager,
+ // ResourceDispatcherHostImpl, MediaStreamUIProxy,
+ // SpeechRecognitionDispatcherHost and possibly others). They look up the view
+ // based on the ID stored in the resource requests. Once those dependencies
+ // are unwound or moved to RenderFrameHost (crbug.com/304341) we can move the
+ // client to be based on the routing_id of the RenderFrameHost.
+ IPC_STRUCT_MEMBER(int, render_view_routing_id)
IPC_STRUCT_END()
+IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
+ IPC_STRUCT_TRAITS_MEMBER(url)
+ IPC_STRUCT_TRAITS_MEMBER(referrer)
+ IPC_STRUCT_TRAITS_MEMBER(transition)
+ IPC_STRUCT_TRAITS_MEMBER(navigation_type)
+ IPC_STRUCT_TRAITS_MEMBER(allow_download)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::RequestNavigationParams)
+ IPC_STRUCT_TRAITS_MEMBER(is_post)
+ IPC_STRUCT_TRAITS_MEMBER(extra_headers)
+ IPC_STRUCT_TRAITS_MEMBER(browser_initiated_post_data)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::CommitNavigationParams)
+ IPC_STRUCT_TRAITS_MEMBER(page_state)
+ IPC_STRUCT_TRAITS_MEMBER(is_overriding_user_agent)
+ IPC_STRUCT_TRAITS_MEMBER(browser_navigation_start)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_BEGIN(FrameMsg_Navigate_Params)
+ // TODO(clamy): investigate which parameters are also needed in PlzNavigate
+ // and move them to the appropriate NavigationParams struct.
+
+ // These structs contain parameters shared by other navigation IPCs.
+ IPC_STRUCT_MEMBER(content::CommonNavigationParams, common_params)
+ IPC_STRUCT_MEMBER(content::RequestNavigationParams, request_params)
+ IPC_STRUCT_MEMBER(content::CommitNavigationParams, commit_params)
+
// The page_id for this navigation, or -1 if it is a new navigation. Back,
// Forward, and Reload navigations should have a valid page_id. If the load
// succeeds, then this page_id will be reflected in the resultant
@@ -178,9 +239,6 @@ IPC_STRUCT_BEGIN(FrameMsg_Navigate_Params)
// succesful when the navigation commits.
IPC_STRUCT_MEMBER(bool, should_clear_history_list)
- // The URL to load.
- IPC_STRUCT_MEMBER(GURL, url)
-
// Base URL for use in WebKit's SubstituteData.
// Is only used with data: URLs.
IPC_STRUCT_MEMBER(GURL, base_url_for_data_url)
@@ -189,34 +247,20 @@ IPC_STRUCT_BEGIN(FrameMsg_Navigate_Params)
// Is only used with data: URLs.
IPC_STRUCT_MEMBER(GURL, history_url_for_data_url)
- // The URL to send in the "Referer" header field. Can be empty if there is
- // no referrer.
- IPC_STRUCT_MEMBER(content::Referrer, referrer)
-
// Any redirect URLs that occurred before |url|. Useful for cross-process
// navigations; defaults to empty.
IPC_STRUCT_MEMBER(std::vector<GURL>, redirects)
- // The type of transition.
- IPC_STRUCT_MEMBER(content::PageTransition, transition)
-
// Informs the RenderView the pending navigation should replace the current
// history entry when it commits. This is used for cross-process redirects so
// the transferred navigation can recover the navigation state.
IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
- // Opaque history state (received by ViewHostMsg_UpdateState).
- IPC_STRUCT_MEMBER(content::PageState, page_state)
-
- // Type of navigation.
- IPC_STRUCT_MEMBER(FrameMsg_Navigate_Type::Value, navigation_type)
-
- // The time the request was created
+ // The time the request was created. This is used by the old performance
+ // infrastructure to set up DocumentState associated with the RenderView.
+ // TODO(ppi): make it go away.
IPC_STRUCT_MEMBER(base::Time, request_time)
- // Extra headers (separated by \n) to send during the request.
- IPC_STRUCT_MEMBER(std::string, extra_headers)
-
// The following two members identify a previous request that has been
// created before this navigation is being transferred to a new render view.
// This serves the purpose of recycling the old request.
@@ -224,28 +268,12 @@ IPC_STRUCT_BEGIN(FrameMsg_Navigate_Params)
IPC_STRUCT_MEMBER(int, transferred_request_child_id)
IPC_STRUCT_MEMBER(int, transferred_request_request_id)
- // Whether or not we should allow the url to download.
- IPC_STRUCT_MEMBER(bool, allow_download)
-
- // Whether or not the user agent override string should be used.
- IPC_STRUCT_MEMBER(bool, is_overriding_user_agent)
-
- // True if this was a post request.
- IPC_STRUCT_MEMBER(bool, is_post)
-
- // If is_post is true, holds the post_data information from browser. Empty
- // otherwise.
- IPC_STRUCT_MEMBER(std::vector<unsigned char>, browser_initiated_post_data)
-
// Whether or not this url should be allowed to access local file://
// resources.
IPC_STRUCT_MEMBER(bool, can_load_local_resources)
// If not empty, which frame to navigate.
IPC_STRUCT_MEMBER(std::string, frame_to_navigate)
-
- // The navigationStart time to expose to JS for this navigation.
- IPC_STRUCT_MEMBER(base::TimeTicks, browser_navigation_start)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params)
@@ -256,19 +284,58 @@ IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params)
IPC_STRUCT_MEMBER(bool, user_gesture)
IPC_STRUCT_END()
+// PlzNavigate
+IPC_STRUCT_BEGIN(FrameHostMsg_BeginNavigation_Params)
+ // TODO(clamy): See if it is possible to define a common struct between this
+ // IPC and ResourceMsg_Request_Params.
+
+ // The request method: GET, POST, etc.
+ IPC_STRUCT_MEMBER(std::string, method)
+
+ // Additional HTTP request headers.
+ IPC_STRUCT_MEMBER(std::string, headers)
+
+ // net::URLRequest load flags (net::LOAD_NORMAL) by default).
+ IPC_STRUCT_MEMBER(int, load_flags)
+
+ // Optional resource request body (may be null).
+ IPC_STRUCT_MEMBER(scoped_refptr<content::ResourceRequestBody>,
+ request_body)
+
+ // True if the request was user initiated.
+ IPC_STRUCT_MEMBER(bool, has_user_gesture)
+IPC_STRUCT_END()
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// This message is used for supporting popup menus on Mac OS X and Android using
+// native controls. See the FrameHostMsg_ShowPopup message.
+IPC_STRUCT_BEGIN(FrameHostMsg_ShowPopup_Params)
+ // Position on the screen.
+ IPC_STRUCT_MEMBER(gfx::Rect, bounds)
+
+ // The height of each item in the menu.
+ IPC_STRUCT_MEMBER(int, item_height)
+
+ // The size of the font to use for those items.
+ IPC_STRUCT_MEMBER(double, item_font_size)
+
+ // The currently selected (displayed) item in the menu.
+ IPC_STRUCT_MEMBER(int, selected_item)
+
+ // The entire list of items in the popup menu.
+ IPC_STRUCT_MEMBER(std::vector<content::MenuItem>, popup_items)
+
+ // Whether items should be right-aligned.
+ IPC_STRUCT_MEMBER(bool, right_aligned)
+
+ // Whether this is a multi-select popup.
+ IPC_STRUCT_MEMBER(bool, allow_multiple_selection)
+IPC_STRUCT_END()
+#endif
+
// -----------------------------------------------------------------------------
// Messages sent from the browser to the renderer.
-// When HW accelerated buffers are swapped in an out-of-process child frame
-// renderer, the message is forwarded to the embedding frame to notify it of
-// a new texture available for compositing. When the buffer has finished
-// presenting, a FrameHostMsg_BuffersSwappedACK should be sent back to
-// gpu host that produced this buffer.
-//
-// This is used in the non-ubercomp HW accelerated compositing path.
-IPC_MESSAGE_ROUTED1(FrameMsg_BuffersSwapped,
- FrameMsg_BuffersSwapped_Params /* params */)
-
// Notifies the embedding frame that a new CompositorFrame is ready to be
// presented. When the frame finishes presenting, a matching
// FrameHostMsg_CompositorFrameSwappedACK should be sent back to the
@@ -292,6 +359,28 @@ IPC_MESSAGE_ROUTED2(FrameMsg_CustomContextMenuAction,
content::CustomContextMenuContext /* custom_context */,
unsigned /* action */)
+// Requests that the RenderFrame or RenderFrameProxy sets its opener to null.
+IPC_MESSAGE_ROUTED0(FrameMsg_DisownOpener)
+
+// Instructs the renderer to create a new RenderFrame object with |routing_id|.
+// The new frame should be created as a child of the object identified by
+// |parent_routing_id| or as top level if that is MSG_ROUTING_NONE.
+// If a valid |proxy_routing_id| is provided, the new frame will be configured
+// to replace the proxy on commit.
+IPC_MESSAGE_CONTROL3(FrameMsg_NewFrame,
+ int /* routing_id */,
+ int /* parent_routing_id */,
+ int /* proxy_routing_id */)
+
+// Instructs the renderer to create a new RenderFrameProxy object with
+// |routing_id|. The new proxy should be created as a child of the object
+// identified by |parent_routing_id| or as top level if that is
+// MSG_ROUTING_NONE.
+IPC_MESSAGE_CONTROL3(FrameMsg_NewFrameProxy,
+ int /* routing_id */,
+ int /* parent_routing_id */,
+ int /* render_view_routing_id */)
+
// Tells the renderer to perform the specified navigation, interrupting any
// existing navigation.
IPC_MESSAGE_ROUTED1(FrameMsg_Navigate, FrameMsg_Navigate_Params)
@@ -306,6 +395,9 @@ IPC_MESSAGE_ROUTED0(FrameMsg_BeforeUnload)
IPC_MESSAGE_ROUTED1(FrameMsg_SwapOut,
int /* proxy_routing_id */)
+// Instructs the frame to stop the load in progress, if any.
+IPC_MESSAGE_ROUTED0(FrameMsg_Stop)
+
// Request for the renderer to insert CSS into the frame.
IPC_MESSAGE_ROUTED1(FrameMsg_CSSInsertRequest,
std::string /* css */)
@@ -324,24 +416,28 @@ IPC_MESSAGE_ROUTED3(FrameMsg_JavaScriptExecuteRequest,
int, /* ID */
bool /* if true, a reply is requested */)
+// ONLY FOR TESTS: Same as above but adds a fake UserGestureindicator around
+// execution. (crbug.com/408426)
+IPC_MESSAGE_ROUTED3(FrameMsg_JavaScriptExecuteRequestForTests,
+ base::string16, /* javascript */
+ int, /* ID */
+ bool /* if true, a reply is requested */)
+
// Selects between the given start and end offsets in the currently focused
// editable field.
IPC_MESSAGE_ROUTED2(FrameMsg_SetEditableSelectionOffsets,
int /* start */,
int /* end */)
-// Sets the text composition to be between the given start and end offsets in
-// the currently focused editable field.
-IPC_MESSAGE_ROUTED3(FrameMsg_SetCompositionFromExistingText,
- int /* start */,
- int /* end */,
- std::vector<blink::WebCompositionUnderline> /* underlines */)
+// Requests a navigation to the supplied markup, in an iframe with sandbox
+// attributes.
+IPC_MESSAGE_ROUTED1(FrameMsg_SetupTransitionView,
+ std::string /* markup */)
-// Deletes the current selection plus the specified number of characters before
-// and after the selection or caret.
-IPC_MESSAGE_ROUTED2(FrameMsg_ExtendSelectionAndDelete,
- int /* before */,
- int /* after */)
+// Tells the renderer to hide the elements specified by the supplied CSS
+// selector, and activates any exiting-transition stylesheets.
+IPC_MESSAGE_ROUTED1(FrameMsg_BeginExitTransition,
+ std::string /* css_selector */)
// Tells the renderer to reload the frame, optionally ignoring the cache while
// doing so.
@@ -367,6 +463,47 @@ IPC_MESSAGE_ROUTED1(FrameMsg_TextSurroundingSelectionRequest,
// needed to support navigation transitions.
IPC_MESSAGE_ROUTED1(FrameMsg_AddStyleSheetByURL, std::string)
+// Change the accessibility mode in the renderer process.
+IPC_MESSAGE_ROUTED1(FrameMsg_SetAccessibilityMode,
+ AccessibilityMode)
+
+#if defined(OS_ANDROID)
+
+// External popup menus.
+IPC_MESSAGE_ROUTED2(FrameMsg_SelectPopupMenuItems,
+ bool /* user canceled the popup */,
+ std::vector<int> /* selected indices */)
+
+#elif defined(OS_MACOSX)
+
+// External popup menus.
+IPC_MESSAGE_ROUTED1(FrameMsg_SelectPopupMenuItem,
+ int /* selected index, -1 means no selection */)
+
+#endif
+
+// PlzNavigate
+// Tells the renderer that a navigation has been requested.
+IPC_MESSAGE_ROUTED2(FrameMsg_RequestNavigation,
+ content::CommonNavigationParams, /* common_params */
+ content::RequestNavigationParams /* request_params */)
+
+// PlzNavigate
+// Tells the renderer that a navigation is ready to commit. The renderer should
+// request |stream_url| to get access to the stream containing the body of the
+// response.
+IPC_MESSAGE_ROUTED4(FrameMsg_CommitNavigation,
+ content::ResourceResponseHead, /* response */
+ GURL, /* stream_url */
+ content::CommonNavigationParams, /* common_params */
+ content::CommitNavigationParams /* commit_params */)
+
+#if defined(ENABLE_PLUGINS)
+// Notifies the renderer of updates to the Plugin Power Saver origin whitelist.
+IPC_MESSAGE_ROUTED1(FrameMsg_UpdatePluginContentOriginWhitelist,
+ std::set<GURL> /* origin_whitelist */)
+#endif // defined(ENABLE_PLUGINS)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
@@ -395,20 +532,17 @@ IPC_MESSAGE_ROUTED0(FrameHostMsg_Detach)
IPC_MESSAGE_ROUTED0(FrameHostMsg_FrameFocused)
// Sent when the renderer starts a provisional load for a frame.
+// |is_transition_navigation| signals that the frame has defined transition
+// elements which can be animated by the navigation destination to provide
+// a transition effect during load.
IPC_MESSAGE_ROUTED2(FrameHostMsg_DidStartProvisionalLoadForFrame,
- int32 /* parent_routing_id */,
- GURL /* url */)
+ GURL /* url */,
+ bool /* is_transition_navigation */)
// Sent when the renderer fails a provisional load with an error.
IPC_MESSAGE_ROUTED1(FrameHostMsg_DidFailProvisionalLoadWithError,
FrameHostMsg_DidFailProvisionalLoadWithError_Params)
-// Sent when a provisional load on the main frame redirects.
-IPC_MESSAGE_ROUTED3(FrameHostMsg_DidRedirectProvisionalLoad,
- int /* page_id */,
- GURL /* source_url*/,
- GURL /* target_url */)
-
// Notifies the browser that a frame in the view has changed. This message
// has a lot of parameters and is packed/unpacked by functions defined in
// render_messages.h.
@@ -456,10 +590,13 @@ IPC_MESSAGE_ROUTED0(FrameHostMsg_DidAccessInitialDocument)
// the window. Sent for top-level frames.
IPC_MESSAGE_ROUTED0(FrameHostMsg_DidDisownOpener)
+// Notifies the browser that a page id was assigned.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_DidAssignPageId,
+ int32 /* page_id */)
+
// Changes the title for the page in the UI when the page is navigated or the
// title changes. Sent for top-level frames.
-IPC_MESSAGE_ROUTED3(FrameHostMsg_UpdateTitle,
- int32 /* page_id */,
+IPC_MESSAGE_ROUTED2(FrameHostMsg_UpdateTitle,
base::string16 /* title */,
blink::WebTextDirection /* title direction */)
@@ -477,6 +614,7 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_DomOperationResponse,
std::string /* json_string */,
int /* automation_id */)
+#if defined(ENABLE_PLUGINS)
// Sent to the browser when the renderer detects it is blocked on a pepper
// plugin message for too long. This is also sent when it becomes unhung
// (according to the value of is_hung). The browser can give the user the
@@ -508,6 +646,14 @@ IPC_SYNC_MESSAGE_CONTROL4_3(FrameHostMsg_GetPluginInfo,
content::WebPluginInfo /* plugin info */,
std::string /* actual_mime_type */)
+// A renderer sends this to the browser process when it wants to temporarily
+// whitelist an origin's plugin content as essential. This temporary whitelist
+// is specific to a top level frame, and is cleared when the whitelisting
+// RenderFrame is destroyed.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_PluginContentOriginAllowed,
+ GURL /* content_origin */)
+#endif // defined(ENABLE_PLUGINS)
+
// A renderer sends this to the browser process when it wants to
// create a plugin. The browser will create the plugin process if
// necessary, and will return a handle to the channel on success.
@@ -520,14 +666,6 @@ IPC_SYNC_MESSAGE_CONTROL4_2(FrameHostMsg_OpenChannelToPlugin,
IPC::ChannelHandle /* channel_handle */,
content::WebPluginInfo /* info */)
-// Acknowledge that we presented a HW buffer and provide a sync point
-// to specify the location in the command stream when the compositor
-// is no longer using it.
-//
-// See FrameMsg_BuffersSwapped.
-IPC_MESSAGE_ROUTED1(FrameHostMsg_BuffersSwappedACK,
- FrameHostMsg_BuffersSwappedACK_Params /* params */)
-
// Acknowledge that we presented an ubercomp frame.
//
// See FrameMsg_CompositorFrameSwapped
@@ -609,10 +747,11 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_SetSelectedColorInColorChooser,
SkColor /* color */)
// Notifies the browser that media has started/stopped playing.
-IPC_MESSAGE_ROUTED3(FrameHostMsg_MediaPlayingNotification,
+IPC_MESSAGE_ROUTED4(FrameHostMsg_MediaPlayingNotification,
int64 /* player_cookie, distinguishes instances */,
bool /* has_video */,
- bool /* has_audio */)
+ bool /* has_audio */,
+ bool /* is_remote */)
IPC_MESSAGE_ROUTED1(FrameHostMsg_MediaPausedNotification,
int64 /* player_cookie, distinguishes instances */)
@@ -627,3 +766,27 @@ IPC_MESSAGE_ROUTED3(FrameHostMsg_TextSurroundingSelectionResponse,
base::string16, /* content */
size_t, /* startOffset */
size_t /* endOffset */)
+
+// Notifies the browser that the renderer has a pending navigation transition.
+// The string parameters are all UTF8.
+IPC_MESSAGE_CONTROL1(FrameHostMsg_AddNavigationTransitionData,
+ FrameHostMsg_AddNavigationTransitionData_Params)
+
+// PlzNavigate
+// Tells the browser to perform a navigation.
+IPC_MESSAGE_ROUTED2(FrameHostMsg_BeginNavigation,
+ FrameHostMsg_BeginNavigation_Params,
+ content::CommonNavigationParams)
+
+// Sent once a paint happens after the first non empty layout. In other words
+// after the frame has painted something.
+IPC_MESSAGE_ROUTED0(FrameHostMsg_DidFirstVisuallyNonEmptyPaint)
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+
+// Message to show/hide a popup menu using native controls.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_ShowPopup,
+ FrameHostMsg_ShowPopup_Params)
+IPC_MESSAGE_ROUTED0(FrameHostMsg_HidePopup)
+
+#endif
diff --git a/chromium/content/common/frame_param_macros.h b/chromium/content/common/frame_param_macros.h
index 023cfd68ab4..32be0ad2e25 100644
--- a/chromium/content/common/frame_param_macros.h
+++ b/chromium/content/common/frame_param_macros.h
@@ -13,10 +13,11 @@
#ifndef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
#define CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#include "cc/output/compositor_frame_ack.h"
#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
diff --git a/chromium/content/common/gamepad_seqlock_unittest.cc b/chromium/content/common/gamepad_seqlock_unittest.cc
deleted file mode 100644
index 7e5da3f8146..00000000000
--- a/chromium/content/common/gamepad_seqlock_unittest.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2011 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 "content/common/gamepad_seqlock.h"
-
-#include <stdlib.h>
-
-#include "base/atomic_ref_count.h"
-#include "base/threading/platform_thread.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// Basic test to make sure that basic operation works correctly.
-
-struct TestData {
- unsigned a, b, c;
-};
-
-class BasicSeqLockTestThread : public PlatformThread::Delegate {
- public:
- BasicSeqLockTestThread() {}
-
- void Init(
- content::GamepadSeqLock* seqlock,
- TestData* data,
- base::subtle::Atomic32* ready) {
- seqlock_ = seqlock;
- data_ = data;
- ready_ = ready;
- }
- virtual void ThreadMain() {
- while (AtomicRefCountIsZero(ready_)) {
- PlatformThread::YieldCurrentThread();
- }
-
- for (unsigned i = 0; i < 1000; ++i) {
- TestData copy;
- base::subtle::Atomic32 version;
- do {
- version = seqlock_->ReadBegin();
- copy = *data_;
- } while (seqlock_->ReadRetry(version));
-
- EXPECT_EQ(copy.a + 100, copy.b);
- EXPECT_EQ(copy.c, copy.b + copy.a);
- }
-
- AtomicRefCountDec(ready_);
- }
-
- private:
- content::GamepadSeqLock* seqlock_;
- TestData* data_;
- base::AtomicRefCount* ready_;
-
- DISALLOW_COPY_AND_ASSIGN(BasicSeqLockTestThread);
-};
-
-TEST(GamepadSeqLockTest, ManyThreads) {
- content::GamepadSeqLock seqlock;
- TestData data = { 0, 0, 0 };
- base::AtomicRefCount ready = 0;
-
- ANNOTATE_BENIGN_RACE_SIZED(&data, sizeof(data), "Racey reads are discarded");
-
- static const unsigned kNumReaderThreads = 10;
- BasicSeqLockTestThread threads[kNumReaderThreads];
- PlatformThreadHandle handles[kNumReaderThreads];
-
- for (unsigned i = 0; i < kNumReaderThreads; ++i)
- threads[i].Init(&seqlock, &data, &ready);
- for (unsigned i = 0; i < kNumReaderThreads; ++i)
- ASSERT_TRUE(PlatformThread::Create(0, &threads[i], &handles[i]));
-
- // The main thread is the writer, and the spawned are readers.
- unsigned counter = 0;
- for (;;) {
- seqlock.WriteBegin();
- data.a = counter++;
- data.b = data.a + 100;
- data.c = data.b + data.a;
- seqlock.WriteEnd();
-
- if (counter == 1)
- base::AtomicRefCountIncN(&ready, kNumReaderThreads);
-
- if (AtomicRefCountIsZero(&ready))
- break;
- }
-
- for (unsigned i = 0; i < kNumReaderThreads; ++i)
- PlatformThread::Join(handles[i]);
-}
-
-} // namespace base
diff --git a/chromium/content/common/geofencing_messages.h b/chromium/content/common/geofencing_messages.h
new file mode 100644
index 00000000000..152b108e0dc
--- /dev/null
+++ b/chromium/content/common/geofencing_messages.h
@@ -0,0 +1,70 @@
+// Copyright 2014 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.
+
+// IPC message for geofencing
+
+#include "content/common/geofencing_status.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+
+// Singly-included section for typedefs.
+#ifndef CONTENT_COMMON_GEOFENCING_MESSAGES_H_
+#define CONTENT_COMMON_GEOFENCING_MESSAGES_H_
+
+typedef std::map<std::string, blink::WebCircularGeofencingRegion>
+ GeofencingRegistrations;
+
+#endif // CONTENT_COMMON_GEOFENCING_MESSAGES_H_
+
+// Multiply-included message file, hence no include guard.
+#define IPC_MESSAGE_START GeofencingMsgStart
+
+IPC_ENUM_TRAITS_MAX_VALUE(content::GeofencingStatus,
+ content::GEOFENCING_STATUS_LAST)
+
+IPC_STRUCT_TRAITS_BEGIN(blink::WebCircularGeofencingRegion)
+ IPC_STRUCT_TRAITS_MEMBER(latitude)
+ IPC_STRUCT_TRAITS_MEMBER(longitude)
+ IPC_STRUCT_TRAITS_MEMBER(radius)
+IPC_STRUCT_TRAITS_END()
+
+// Messages sent from the child process to the browser.
+IPC_MESSAGE_CONTROL5(GeofencingHostMsg_RegisterRegion,
+ int /* thread_id */,
+ int /* request_id */,
+ std::string /* region_id */,
+ blink::WebCircularGeofencingRegion /* region */,
+ int64 /* serviceworker_registration_id */)
+
+IPC_MESSAGE_CONTROL4(GeofencingHostMsg_UnregisterRegion,
+ int /* thread_id */,
+ int /* request_id */,
+ std::string /* region_id */,
+ int64 /* serviceworker_registration_id */)
+
+IPC_MESSAGE_CONTROL3(GeofencingHostMsg_GetRegisteredRegions,
+ int /* thread_id */,
+ int /* request_id */,
+ int64 /* serviceworker_registration_id */)
+
+// Messages sent from the browser to the child process.
+
+// Reply in response to GeofencingHostMsg_RegisterRegion
+IPC_MESSAGE_CONTROL3(GeofencingMsg_RegisterRegionComplete,
+ int /* thread_id */,
+ int /* request_id */,
+ content::GeofencingStatus /* status */)
+
+// Reply in response to GeofencingHostMsg_UnregisterRegion
+IPC_MESSAGE_CONTROL3(GeofencingMsg_UnregisterRegionComplete,
+ int /* thread_id */,
+ int /* request_id */,
+ content::GeofencingStatus /* status */)
+
+// Reply in response to GeofencingHostMsg_GetRegisteredRegions
+IPC_MESSAGE_CONTROL4(GeofencingMsg_GetRegisteredRegionsComplete,
+ int /* thread_id */,
+ int /* request_id */,
+ content::GeofencingStatus /* status */,
+ GeofencingRegistrations /* regions */)
diff --git a/chromium/content/common/geofencing_status.cc b/chromium/content/common/geofencing_status.cc
new file mode 100644
index 00000000000..ffca197bc85
--- /dev/null
+++ b/chromium/content/common/geofencing_status.cc
@@ -0,0 +1,32 @@
+// Copyright 2014 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 "content/common/geofencing_status.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+const char* GeofencingStatusToString(GeofencingStatus status) {
+ switch (status) {
+ case GEOFENCING_STATUS_OK:
+ return "Operation has succeeded";
+
+ case GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER:
+ return "Operation failed - no Service Worker";
+
+ case GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE:
+ return "Operation failed - geofencing not available";
+
+ case GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED:
+ return "Unregistration failed - no region registered with given ID";
+
+ case GEOFENCING_STATUS_ERROR:
+ return "Operation has failed (unspecified reason)";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace content
diff --git a/chromium/content/common/geofencing_status.h b/chromium/content/common/geofencing_status.h
new file mode 100644
index 00000000000..13a1de8a2f4
--- /dev/null
+++ b/chromium/content/common/geofencing_status.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 CONTENT_COMMON_GEOFENCING_STATUS_H_
+#define CONTENT_COMMON_GEOFENCING_STATUS_H_
+
+namespace content {
+
+enum GeofencingStatus {
+ // Everything is ok.
+ GEOFENCING_STATUS_OK,
+
+ // Operation failed because there is no Service Worker.
+ GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER,
+
+ // Operation failed because geofencing is not available.
+ GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE,
+
+ // Unregistering failed because region was not registered.
+ GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED,
+
+ // Generic error.
+ GEOFENCING_STATUS_ERROR,
+
+ // Used for IPC message range checks.
+ GEOFENCING_STATUS_LAST = GEOFENCING_STATUS_ERROR
+};
+
+const char* GeofencingStatusToString(GeofencingStatus status);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GEOFENCING_STATUS_H_
diff --git a/chromium/content/common/geolocation_messages.h b/chromium/content/common/geolocation_messages.h
index 55b4bd77368..b66a1919b79 100644
--- a/chromium/content/common/geolocation_messages.h
+++ b/chromium/content/common/geolocation_messages.h
@@ -34,36 +34,13 @@ IPC_MESSAGE_ROUTED2(GeolocationMsg_PermissionSet,
int /* bridge_id */,
bool /* is_allowed */)
-// Sent after GeolocationHostMsg_StartUpdating iff the user has granted
-// permission and we have a position available or an error occurs (such as
-// permission denied, position unavailable, etc.)
-IPC_MESSAGE_ROUTED1(GeolocationMsg_PositionUpdated,
- content::Geoposition /* geoposition */)
-
// Messages sent from the renderer to the browser.
// The |bridge_id| representing |host| is requesting permission to access
// geolocation position. This will be replied by GeolocationMsg_PermissionSet.
+// TODO(mlamouri): |origin| should be a security origin to guarantee that a
+// proper origin is passed.
IPC_MESSAGE_ROUTED3(GeolocationHostMsg_RequestPermission,
int /* bridge_id */,
- GURL /* GURL of the frame requesting geolocation */,
+ GURL /* origin in the frame requesting geolocation */,
bool /* user_gesture */)
-
-// The |bridge_id| representing |GURL| is cancelling its previous permission
-// request to access geolocation position.
-IPC_MESSAGE_ROUTED2(GeolocationHostMsg_CancelPermissionRequest,
- int /* bridge_id */,
- GURL /* GURL of the frame */)
-
-// The render view requests the Geolocation service to start updating.
-// This is an asynchronous call, and the browser process may eventually reply
-// with the updated geoposition, or an error (access denied, location
-// unavailable, etc.)
-IPC_MESSAGE_ROUTED2(GeolocationHostMsg_StartUpdating,
- GURL /* GURL of the frame requesting geolocation */,
- bool /* enable_high_accuracy */)
-
-// The render view requests Geolocation service to stop updating.
-// Note that the geolocation service may continue to fetch geolocation data
-// for other origins.
-IPC_MESSAGE_ROUTED0(GeolocationHostMsg_StopUpdating)
diff --git a/chromium/content/common/geolocation_service.mojom b/chromium/content/common/geolocation_service.mojom
new file mode 100644
index 00000000000..00d56400ba4
--- /dev/null
+++ b/chromium/content/common/geolocation_service.mojom
@@ -0,0 +1,19 @@
+// Copyright 2014 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.
+
+module content;
+
+import "content/public/common/mojo_geoposition.mojom";
+
+// The Geolocation service provides updates on the device's location to its
+// client. By default, it provides updates with low accuracy, but
+// |SetHighAccuracy()| can be called to change this.
+[Client=GeolocationServiceClient]
+interface GeolocationService {
+ SetHighAccuracy(bool high_accuracy);
+};
+
+interface GeolocationServiceClient {
+ OnLocationUpdate(MojoGeoposition geoposition);
+};
diff --git a/chromium/content/common/gin_java_bridge_messages.h b/chromium/content/common/gin_java_bridge_messages.h
index f9525b1e5a5..51f90e6ba17 100644
--- a/chromium/content/common/gin_java_bridge_messages.h
+++ b/chromium/content/common/gin_java_bridge_messages.h
@@ -7,6 +7,7 @@
// Multiply-included message file, hence no include guard.
#include "base/basictypes.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
@@ -16,6 +17,9 @@
// Messages for handling Java objects injected into JavaScript -----------------
+IPC_ENUM_TRAITS_MAX_VALUE(content::GinJavaBridgeError,
+ content::kGinJavaBridgeErrorLast)
+
// Sent from browser to renderer to add a Java object with the given name.
// Object IDs are generated on the browser side.
IPC_MESSAGE_ROUTED2(GinJavaBridgeMsg_AddNamedObject,
@@ -45,14 +49,16 @@ IPC_SYNC_MESSAGE_ROUTED2_1(GinJavaBridgeHostMsg_HasMethod,
// a container to work around immutability of base::Value.
// Empty result list indicates that an error has happened on the Java side
// (either bridge-induced error or an unhandled Java exception) and an exception
-// must be thrown into JavaScript.
+// must be thrown into JavaScript. |error_code| indicates the cause of
+// the error.
// Some special value types that are not supported by base::Value are encoded
// as BinaryValues via GinJavaBridgeValue.
-IPC_SYNC_MESSAGE_ROUTED3_1(GinJavaBridgeHostMsg_InvokeMethod,
+IPC_SYNC_MESSAGE_ROUTED3_2(GinJavaBridgeHostMsg_InvokeMethod,
int32 /* object_id */,
std::string /* method_name */,
base::ListValue /* arguments */,
- base::ListValue /* result */)
+ base::ListValue /* result */,
+ content::GinJavaBridgeError /* error_code */)
// Sent from renderer to browser in two cases:
//
diff --git a/chromium/content/common/gpu/OWNERS b/chromium/content/common/gpu/OWNERS
index 61645385063..558fb4cd836 100644
--- a/chromium/content/common/gpu/OWNERS
+++ b/chromium/content/common/gpu/OWNERS
@@ -1,6 +1,6 @@
+ccameron@chromium.org
+jbauman@chromium.org
kbr@chromium.org
-piman@chromium.org
-sievers@chromium.org
# GPU memory buffer implementations.
per-file *gpu_memory_buffer*=reveman@chromium.org
@@ -10,12 +10,12 @@ per-file *gpu_memory_manager*=ccameron@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
-per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc b/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
index 4dd189c1ff5..33648837349 100644
--- a/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -15,10 +15,13 @@
#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/common/cmd_buffer_common.h"
#include "gpu/command_buffer/common/command_buffer_shared.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
+#include "gpu/command_buffer/service/image_factory.h"
#include "ui/gfx/size.h"
+#include "ui/gl/gl_bindings.h"
namespace content {
@@ -42,12 +45,13 @@ bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CommandBufferProxyImpl, message)
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Destroyed, OnDestroyed);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_EchoAck, OnEchoAck);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetMemoryAllocation,
OnSetMemoryAllocation);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncPointAck,
OnSignalSyncPointAck);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SwapBuffersCompleted,
+ OnSwapBuffersCompleted);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -75,13 +79,6 @@ void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason) {
}
}
-void CommandBufferProxyImpl::OnEchoAck() {
- DCHECK(!echo_tasks_.empty());
- base::Closure callback = echo_tasks_.front();
- echo_tasks_.pop();
- callback.Run();
-}
-
void CommandBufferProxyImpl::OnConsoleMessage(
const GPUCommandBufferConsoleMessage& message) {
if (!console_message_callback_.is_null()) {
@@ -147,7 +144,7 @@ bool CommandBufferProxyImpl::Initialize() {
if (!base::SharedMemory::IsHandleValid(handle))
return false;
- bool result;
+ bool result = false;
if (!Send(new GpuCommandBufferMsg_Initialize(
route_id_, handle, &result, &capabilities_))) {
LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize.";
@@ -159,7 +156,7 @@ bool CommandBufferProxyImpl::Initialize() {
return false;
}
- capabilities_.map_image = true;
+ capabilities_.image = true;
return true;
}
@@ -189,14 +186,20 @@ void CommandBufferProxyImpl::Flush(int32 put_offset) {
Send(new GpuCommandBufferMsg_AsyncFlush(route_id_,
put_offset,
- ++flush_count_));
+ ++flush_count_,
+ latency_info_));
+ latency_info_.clear();
}
void CommandBufferProxyImpl::SetLatencyInfo(
const std::vector<ui::LatencyInfo>& latency_info) {
- if (last_state_.error != gpu::error::kNoError)
- return;
- Send(new GpuCommandBufferMsg_SetLatencyInfo(route_id_, latency_info));
+ for (size_t i = 0; i < latency_info.size(); i++)
+ latency_info_.push_back(latency_info[i]);
+}
+
+void CommandBufferProxyImpl::SetSwapBuffersCompletionCallback(
+ const SwapBuffersCompletionCallback& callback) {
+ swap_buffers_completion_callback_ = callback;
}
void CommandBufferProxyImpl::WaitForTokenInRange(int32 start, int32 end) {
@@ -296,88 +299,81 @@ gpu::Capabilities CommandBufferProxyImpl::GetCapabilities() {
return capabilities_;
}
-gfx::GpuMemoryBuffer* CommandBufferProxyImpl::CreateGpuMemoryBuffer(
- size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage,
- int32* id) {
- *id = -1;
-
+int32_t CommandBufferProxyImpl::CreateImage(ClientBuffer buffer,
+ size_t width,
+ size_t height,
+ unsigned internalformat) {
if (last_state_.error != gpu::error::kNoError)
- return NULL;
-
- int32 new_id = channel_->ReserveGpuMemoryBufferId();
- DCHECK(gpu_memory_buffers_.find(new_id) == gpu_memory_buffers_.end());
+ return -1;
- scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer(
- channel_->factory()->AllocateGpuMemoryBuffer(
- width, height, internalformat, usage));
- if (!gpu_memory_buffer)
- return NULL;
+ int32 new_id = channel_->ReserveImageId();
- DCHECK(GpuChannelHost::IsValidGpuMemoryBuffer(
- gpu_memory_buffer->GetHandle()));
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
+ channel_->gpu_memory_buffer_manager();
+ gfx::GpuMemoryBuffer* gpu_memory_buffer =
+ gpu_memory_buffer_manager->GpuMemoryBufferFromClientBuffer(buffer);
+ DCHECK(gpu_memory_buffer);
// This handle is owned by the GPU process and must be passed to it or it
// will leak. In otherwords, do not early out on error between here and the
- // sending of the RegisterGpuMemoryBuffer IPC below.
+ // sending of the CreateImage IPC below.
+ bool requires_sync_point = false;
gfx::GpuMemoryBufferHandle handle =
- channel_->ShareGpuMemoryBufferToGpuProcess(
- gpu_memory_buffer->GetHandle());
-
- if (!Send(new GpuCommandBufferMsg_RegisterGpuMemoryBuffer(
- route_id_,
- new_id,
- handle,
- width,
- height,
- internalformat))) {
- return NULL;
+ channel_->ShareGpuMemoryBufferToGpuProcess(gpu_memory_buffer->GetHandle(),
+ &requires_sync_point);
+
+ DCHECK(gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat(
+ internalformat, gpu_memory_buffer->GetFormat()));
+ if (!Send(new GpuCommandBufferMsg_CreateImage(route_id_,
+ new_id,
+ handle,
+ gfx::Size(width, height),
+ gpu_memory_buffer->GetFormat(),
+ internalformat))) {
+ return -1;
}
- *id = new_id;
- gpu_memory_buffers_[new_id] = gpu_memory_buffer.release();
- return gpu_memory_buffers_[new_id];
+ if (requires_sync_point) {
+ gpu_memory_buffer_manager->SetDestructionSyncPoint(gpu_memory_buffer,
+ InsertSyncPoint());
+ }
+
+ return new_id;
}
-void CommandBufferProxyImpl::DestroyGpuMemoryBuffer(int32 id) {
+void CommandBufferProxyImpl::DestroyImage(int32 id) {
if (last_state_.error != gpu::error::kNoError)
return;
- // Remove the gpu memory buffer from the client side cache.
- GpuMemoryBufferMap::iterator it = gpu_memory_buffers_.find(id);
- if (it != gpu_memory_buffers_.end()) {
- delete it->second;
- gpu_memory_buffers_.erase(it);
- }
+ Send(new GpuCommandBufferMsg_DestroyImage(route_id_, id));
+}
+
+int32_t CommandBufferProxyImpl::CreateGpuMemoryBufferImage(
+ size_t width,
+ size_t height,
+ unsigned internalformat,
+ unsigned usage) {
+ scoped_ptr<gfx::GpuMemoryBuffer> buffer(
+ channel_->gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
+ gfx::Size(width, height),
+ gpu::ImageFactory::ImageFormatToGpuMemoryBufferFormat(internalformat),
+ gpu::ImageFactory::ImageUsageToGpuMemoryBufferUsage(usage)));
+ if (!buffer)
+ return -1;
- Send(new GpuCommandBufferMsg_DestroyGpuMemoryBuffer(route_id_, id));
+ return CreateImage(buffer->AsClientBuffer(), width, height, internalformat);
}
int CommandBufferProxyImpl::GetRouteID() const {
return route_id_;
}
-void CommandBufferProxyImpl::Echo(const base::Closure& callback) {
- if (last_state_.error != gpu::error::kNoError) {
- return;
- }
-
- if (!Send(new GpuCommandBufferMsg_Echo(
- route_id_, GpuCommandBufferMsg_EchoAck(route_id_)))) {
- return;
- }
-
- echo_tasks_.push(callback);
-}
-
uint32 CommandBufferProxyImpl::CreateStreamTexture(uint32 texture_id) {
if (last_state_.error != gpu::error::kNoError)
return 0;
int32 stream_id = channel_->GenerateRouteID();
- bool succeeded;
+ bool succeeded = false;
Send(new GpuCommandBufferMsg_CreateStreamTexture(
route_id_, texture_id, stream_id, &succeeded));
if (!succeeded) {
@@ -392,10 +388,26 @@ uint32 CommandBufferProxyImpl::InsertSyncPoint() {
return 0;
uint32 sync_point = 0;
- Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, &sync_point));
+ Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, true, &sync_point));
return sync_point;
}
+uint32_t CommandBufferProxyImpl::InsertFutureSyncPoint() {
+ if (last_state_.error != gpu::error::kNoError)
+ return 0;
+
+ uint32 sync_point = 0;
+ Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, false, &sync_point));
+ return sync_point;
+}
+
+void CommandBufferProxyImpl::RetireSyncPoint(uint32_t sync_point) {
+ if (last_state_.error != gpu::error::kNoError)
+ return;
+
+ Send(new GpuCommandBufferMsg_RetireSyncPoint(route_id_, sync_point));
+}
+
void CommandBufferProxyImpl::SignalSyncPoint(uint32 sync_point,
const base::Closure& callback) {
if (last_state_.error != gpu::error::kNoError)
@@ -514,4 +526,16 @@ gpu::CommandBufferSharedState* CommandBufferProxyImpl::shared_state() const {
shared_state_shm_->memory());
}
+void CommandBufferProxyImpl::OnSwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ if (!swap_buffers_completion_callback_.is_null()) {
+ if (!ui::LatencyInfo::Verify(
+ latency_info, "CommandBufferProxyImpl::OnSwapBuffersCompleted")) {
+ swap_buffers_completion_callback_.Run(std::vector<ui::LatencyInfo>());
+ return;
+ }
+ swap_buffers_completion_callback_.Run(latency_info);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/client/command_buffer_proxy_impl.h b/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
index ca262b1db60..ea3974029cd 100644
--- a/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
+#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
@@ -28,10 +29,6 @@ namespace base {
class SharedMemory;
}
-namespace gfx {
-class GpuMemoryBuffer;
-}
-
namespace gpu {
struct Mailbox;
}
@@ -65,7 +62,7 @@ class CommandBufferProxyImpl
const std::string& msg, int id)> GpuConsoleMessageCallback;
CommandBufferProxyImpl(GpuChannelHost* channel, int route_id);
- virtual ~CommandBufferProxyImpl();
+ ~CommandBufferProxyImpl() override;
// Sends an IPC message to create a GpuVideoDecodeAccelerator. Creates and
// returns it as an owned pointer to a media::VideoDecodeAccelerator. Returns
@@ -84,37 +81,40 @@ class CommandBufferProxyImpl
scoped_ptr<media::VideoEncodeAccelerator> CreateVideoEncoder();
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelError() override;
// CommandBuffer implementation:
- virtual bool Initialize() OVERRIDE;
- virtual State GetLastState() OVERRIDE;
- virtual int32 GetLastToken() OVERRIDE;
- virtual void Flush(int32 put_offset) OVERRIDE;
- virtual void WaitForTokenInRange(int32 start, int32 end) OVERRIDE;
- virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
- virtual void SetGetBuffer(int32 shm_id) OVERRIDE;
- virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
- int32* id) OVERRIDE;
- virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
+ bool Initialize() override;
+ State GetLastState() override;
+ int32 GetLastToken() override;
+ void Flush(int32 put_offset) override;
+ void WaitForTokenInRange(int32 start, int32 end) override;
+ void WaitForGetOffsetInRange(int32 start, int32 end) override;
+ void SetGetBuffer(int32 shm_id) override;
+ scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+ int32* id) override;
+ void DestroyTransferBuffer(int32 id) override;
// gpu::GpuControl implementation:
- virtual gpu::Capabilities GetCapabilities() OVERRIDE;
- virtual gfx::GpuMemoryBuffer* CreateGpuMemoryBuffer(size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage,
- int32* id) OVERRIDE;
- virtual void DestroyGpuMemoryBuffer(int32 id) OVERRIDE;
- virtual uint32 InsertSyncPoint() OVERRIDE;
- virtual void SignalSyncPoint(uint32 sync_point,
- const base::Closure& callback) OVERRIDE;
- virtual void SignalQuery(uint32 query,
- const base::Closure& callback) OVERRIDE;
- virtual void SetSurfaceVisible(bool visible) OVERRIDE;
- virtual void Echo(const base::Closure& callback) OVERRIDE;
- virtual uint32 CreateStreamTexture(uint32 texture_id) OVERRIDE;
+ gpu::Capabilities GetCapabilities() override;
+ int32 CreateImage(ClientBuffer buffer,
+ size_t width,
+ size_t height,
+ unsigned internalformat) override;
+ void DestroyImage(int32 id) override;
+ int32 CreateGpuMemoryBufferImage(size_t width,
+ size_t height,
+ unsigned internalformat,
+ unsigned usage) override;
+ uint32 InsertSyncPoint() override;
+ uint32_t InsertFutureSyncPoint() override;
+ void RetireSyncPoint(uint32_t sync_point) override;
+ void SignalSyncPoint(uint32 sync_point,
+ const base::Closure& callback) override;
+ void SignalQuery(uint32 query, const base::Closure& callback) override;
+ void SetSurfaceVisible(bool visible) override;
+ uint32 CreateStreamTexture(uint32 texture_id) override;
int GetRouteID() const;
bool ProduceFrontBuffer(const gpu::Mailbox& mailbox);
@@ -133,19 +133,28 @@ class CommandBufferProxyImpl
const GpuConsoleMessageCallback& callback);
void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
+ typedef base::Callback<void(const std::vector<ui::LatencyInfo>& latency_info)>
+ SwapBuffersCompletionCallback;
+ void SetSwapBuffersCompletionCallback(
+ const SwapBuffersCompletionCallback& callback);
// TODO(apatrick): this is a temporary optimization while skia is calling
// ContentGLContext::MakeCurrent prior to every GL call. It saves returning 6
// ints redundantly when only the error is needed for the
// CommandBufferProxyImpl implementation.
- virtual gpu::error::Error GetLastError() OVERRIDE;
+ gpu::error::Error GetLastError() override;
GpuChannelHost* channel() const { return channel_; }
+ base::SharedMemoryHandle GetSharedStateHandle() const {
+ return shared_state_shm_->handle();
+ }
+
private:
typedef std::map<int32, scoped_refptr<gpu::Buffer> > TransferBufferMap;
typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
- typedef std::map<int32, gfx::GpuMemoryBuffer*> GpuMemoryBufferMap;
+ typedef base::ScopedPtrHashMap<int32, gfx::GpuMemoryBuffer>
+ GpuMemoryBufferMap;
// Send an IPC message over the GPU channel. This is private to fully
// encapsulate the channel; all callers of this function must explicitly
@@ -155,10 +164,10 @@ class CommandBufferProxyImpl
// Message handlers:
void OnUpdateState(const gpu::CommandBuffer::State& state);
void OnDestroyed(gpu::error::ContextLostReason reason);
- void OnEchoAck();
void OnConsoleMessage(const GPUCommandBufferConsoleMessage& message);
void OnSetMemoryAllocation(const gpu::MemoryAllocation& allocation);
void OnSignalSyncPointAck(uint32 id);
+ void OnSwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info);
// Try to read an updated copy of the state from shared memory.
void TryUpdateState();
@@ -182,9 +191,6 @@ class CommandBufferProxyImpl
unsigned int flush_count_;
int32 last_put_offset_;
- // Tasks to be invoked in echo responses.
- std::queue<base::Closure> echo_tasks_;
-
base::Closure channel_error_callback_;
MemoryAllocationChangedCallback memory_allocation_changed_callback_;
@@ -200,6 +206,10 @@ class CommandBufferProxyImpl
gpu::Capabilities capabilities_;
+ std::vector<ui::LatencyInfo> latency_info_;
+
+ SwapBuffersCompletionCallback swap_buffers_completion_callback_;
+
DISALLOW_COPY_AND_ASSIGN(CommandBufferProxyImpl);
};
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer.cc b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
index f23283ed55d..a4c3111c0ce 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.cc
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
@@ -91,7 +91,7 @@ bool ContextProviderCommandBuffer::BindToCurrentThread() {
if (lost_context_callback_proxy_)
return true;
- if (!context3d_->makeContextCurrent())
+ if (!context3d_->InitializeOnCurrentThread())
return false;
InitializeCapabilities();
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer.h b/chromium/content/common/gpu/client/context_provider_command_buffer.h
index aa8613a7007..39c7fefc083 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.h
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.h
@@ -34,29 +34,29 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
CommandBufferProxyImpl* GetCommandBufferProxy();
// ContextProviderWebContext implementation.
- virtual WebGraphicsContext3DCommandBufferImpl* WebContext3D() OVERRIDE;
+ WebGraphicsContext3DCommandBufferImpl* WebContext3D() override;
// cc::ContextProvider implementation.
- virtual bool BindToCurrentThread() OVERRIDE;
- virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE;
- virtual gpu::ContextSupport* ContextSupport() OVERRIDE;
- virtual class GrContext* GrContext() OVERRIDE;
- virtual Capabilities ContextCapabilities() OVERRIDE;
- virtual bool IsContextLost() OVERRIDE;
- virtual void VerifyContexts() OVERRIDE;
- virtual void DeleteCachedResources() OVERRIDE;
- virtual bool DestroyedOnMainThread() OVERRIDE;
- virtual void SetLostContextCallback(
- const LostContextCallback& lost_context_callback) OVERRIDE;
- virtual void SetMemoryPolicyChangedCallback(
+ bool BindToCurrentThread() override;
+ gpu::gles2::GLES2Interface* ContextGL() override;
+ gpu::ContextSupport* ContextSupport() override;
+ class GrContext* GrContext() override;
+ Capabilities ContextCapabilities() override;
+ bool IsContextLost() override;
+ void VerifyContexts() override;
+ void DeleteCachedResources() override;
+ bool DestroyedOnMainThread() override;
+ void SetLostContextCallback(
+ const LostContextCallback& lost_context_callback) override;
+ void SetMemoryPolicyChangedCallback(
const MemoryPolicyChangedCallback& memory_policy_changed_callback)
- OVERRIDE;
+ override;
protected:
ContextProviderCommandBuffer(
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
const std::string& debug_name);
- virtual ~ContextProviderCommandBuffer();
+ ~ContextProviderCommandBuffer() override;
void OnLostContext();
void OnMemoryAllocationChanged(const gpu::MemoryAllocation& allocation);
diff --git a/chromium/content/common/gpu/client/gl_helper.cc b/chromium/content/common/gpu/client/gl_helper.cc
index c61737bce38..0ba9193c874 100644
--- a/chromium/content/common/gpu/client/gl_helper.cc
+++ b/chromium/content/common/gpu/client/gl_helper.cc
@@ -105,6 +105,7 @@ class ScalerHolder {
} // namespace
namespace content {
+typedef GLHelperReadbackSupport::FormatSupport FormatSupport;
// Implements GLHelper::CropScaleReadbackAndCleanTexture and encapsulates
// the data needed for it.
@@ -141,19 +142,19 @@ class GLHelper::CopyTextureToImpl
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
unsigned char* out,
- const SkBitmap::Config config,
+ const SkColorType out_color_type,
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality);
void ReadbackTextureSync(GLuint texture,
const gfx::Rect& src_rect,
unsigned char* out,
- SkBitmap::Config format);
+ SkColorType format);
void ReadbackTextureAsync(GLuint texture,
const gfx::Size& dst_size,
unsigned char* out,
- SkBitmap::Config config,
+ SkColorType color_type,
const base::Callback<void(bool)>& callback);
// Reads back bytes from the currently bound frame buffer.
@@ -162,8 +163,9 @@ class GLHelper::CopyTextureToImpl
int32 bytes_per_row, // generally dst_size.width() * 4
int32 row_stride_bytes, // generally dst_size.width() * 4
unsigned char* out,
- const SkBitmap::Config config,
- ReadbackSwizzle swizzle,
+ GLenum format,
+ GLenum type,
+ size_t bytes_per_pixel,
const base::Callback<void(bool)>& callback);
void ReadbackPlane(TextureFrameBufferPair* source,
@@ -193,7 +195,11 @@ class GLHelper::CopyTextureToImpl
// 0 if GL_EXT_draw_buffers is not available.
GLint MaxDrawBuffers() const { return max_draw_buffers_; }
- bool IsReadbackConfigSupported(SkBitmap::Config bitmap_config);
+ FormatSupport GetReadbackConfig(SkColorType color_type,
+ bool can_swizzle,
+ GLenum* format,
+ GLenum* type,
+ size_t* bytes_per_pixel);
private:
// A single request to CropScaleReadbackAndCleanTexture.
@@ -243,13 +249,12 @@ class GLHelper::CopyTextureToImpl
bool flip_vertically,
ReadbackSwizzle swizzle);
- virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
- uint32 sync_point,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback)
- OVERRIDE;
+ void ReadbackYUV(const gpu::Mailbox& mailbox,
+ uint32 sync_point,
+ const scoped_refptr<media::VideoFrame>& target,
+ const base::Callback<void(bool)>& callback) override;
- virtual ScalerInterface* scaler() OVERRIDE { return scaler_.scaler(); }
+ ScalerInterface* scaler() override { return scaler_.scaler(); }
private:
GLES2Interface* gl_;
@@ -281,13 +286,12 @@ class GLHelper::CopyTextureToImpl
bool flip_vertically,
ReadbackSwizzle swizzle);
- virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
- uint32 sync_point,
- const scoped_refptr<media::VideoFrame>& target,
- const base::Callback<void(bool)>& callback)
- OVERRIDE;
+ void ReadbackYUV(const gpu::Mailbox& mailbox,
+ uint32 sync_point,
+ const scoped_refptr<media::VideoFrame>& target,
+ const base::Callback<void(bool)>& callback) override;
- virtual ScalerInterface* scaler() OVERRIDE { return scaler_.scaler(); }
+ ScalerInterface* scaler() override { return scaler_.scaler(); }
private:
GLES2Interface* gl_;
@@ -316,9 +320,28 @@ class GLHelper::CopyTextureToImpl
const gfx::Size& dst_size,
bool vertically_flip_texture,
bool swizzle,
- SkBitmap::Config config,
+ SkColorType color_type,
GLHelper::ScalerQuality quality);
+ // Converts each four consecutive pixels of the source texture into one pixel
+ // in the result texture with each pixel channel representing the grayscale
+ // color of one of the four original pixels:
+ // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X1X2X3X4
+ // The resulting texture is still an RGBA texture (which is ~4 times narrower
+ // than the original). If rendered directly, it wouldn't show anything useful,
+ // but the data in it can be used to construct a grayscale image.
+ // |encoded_texture_size| is the exact size of the resulting RGBA texture. It
+ // is equal to src_size.width()/4 rounded upwards. Some channels in the last
+ // pixel ((-src_size.width()) % 4) to be exact) are padding and don't contain
+ // useful data.
+ // If swizzle is set to true, the transformed pixels are reordered:
+ // R1G1B1A1 R2G2B2A2 R3G3B3A3 R4G4B4A4 -> X3X2X1X4.
+ GLuint EncodeTextureAsGrayscale(GLuint src_texture,
+ const gfx::Size& src_size,
+ gfx::Size* const encoded_texture_size,
+ bool vertically_flip_texture,
+ bool swizzle);
+
static void nullcallback(bool success) {}
void ReadbackDone(Request *request, int bytes_per_pixel);
void FinishRequest(Request* request, bool result);
@@ -327,6 +350,7 @@ class GLHelper::CopyTextureToImpl
static const float kRGBtoYColorWeights[];
static const float kRGBtoUColorWeights[];
static const float kRGBtoVColorWeights[];
+ static const float kRGBtoGrayscaleColorWeights[];
GLES2Interface* gl_;
gpu::ContextSupport* context_support_;
@@ -362,11 +386,31 @@ GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
const gfx::Size& dst_size,
bool vertically_flip_texture,
bool swizzle,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
GLHelper::ScalerQuality quality) {
- if (!IsReadbackConfigSupported(bitmap_config))
- return 0;
+ GLuint dst_texture = 0u;
+ gl_->GenTextures(1, &dst_texture);
+ {
+ GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
+ ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
+ // Use GL_RGBA for destination/temporary texture unless we're working with
+ // 16-bit data
+ if (color_type == kRGB_565_SkColorType) {
+ format = GL_RGB;
+ type = GL_UNSIGNED_SHORT_5_6_5;
+ }
+
+ gl_->TexImage2D(GL_TEXTURE_2D,
+ 0,
+ format,
+ dst_size.width(),
+ dst_size.height(),
+ 0,
+ format,
+ type,
+ NULL);
+ }
scoped_ptr<ScalerInterface> scaler(
helper_->CreateScaler(quality,
src_size,
@@ -374,36 +418,44 @@ GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
dst_size,
vertically_flip_texture,
swizzle));
+ scaler->Scale(src_texture, dst_texture);
+ return dst_texture;
+}
+
+GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale(
+ GLuint src_texture,
+ const gfx::Size& src_size,
+ gfx::Size* const encoded_texture_size,
+ bool vertically_flip_texture,
+ bool swizzle) {
GLuint dst_texture = 0u;
- // Start with ARGB8888 params as any other format which is not
- // supported is already asserted above.
- GLenum format = GL_RGBA , type = GL_UNSIGNED_BYTE;
gl_->GenTextures(1, &dst_texture);
+ // The size of the encoded texture.
+ *encoded_texture_size =
+ gfx::Size((src_size.width() + 3) / 4, src_size.height());
{
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
- switch (bitmap_config) {
- case SkBitmap::kARGB_8888_Config:
- // Do nothing params already set.
- break;
- case SkBitmap::kRGB_565_Config:
- format = GL_RGB;
- type = GL_UNSIGNED_SHORT_5_6_5;
- break;
- default:
- NOTREACHED();
- break;
- }
gl_->TexImage2D(GL_TEXTURE_2D,
0,
- format,
- dst_size.width(),
- dst_size.height(),
+ GL_RGBA,
+ encoded_texture_size->width(),
+ encoded_texture_size->height(),
0,
- format,
- type,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
NULL);
}
- scaler->Scale(src_texture, dst_texture);
+
+ helper_->InitScalerImpl();
+ scoped_ptr<ScalerInterface> grayscale_scaler(
+ helper_->scaler_impl_.get()->CreatePlanarScaler(
+ src_size,
+ gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()),
+ *encoded_texture_size,
+ vertically_flip_texture,
+ swizzle,
+ kRGBtoGrayscaleColorWeights));
+ grayscale_scaler->Scale(src_texture, dst_texture);
return dst_texture;
}
@@ -412,36 +464,16 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
int32 bytes_per_row,
int32 row_stride_bytes,
unsigned char* out,
- const SkBitmap::Config bitmap_config,
- ReadbackSwizzle swizzle,
+ GLenum format,
+ GLenum type,
+ size_t bytes_per_pixel,
const base::Callback<void(bool)>& callback) {
- if (!IsReadbackConfigSupported(bitmap_config)) {
- callback.Run(false);
- return;
- }
+ TRACE_EVENT0("mirror", "GLHelper::CopyTextureToImpl::ReadbackAsync");
Request* request =
new Request(dst_size, bytes_per_row, row_stride_bytes, out, callback);
request_queue_.push(request);
request->buffer = 0u;
- // Start with ARGB8888 params as any other format which is not
- // supported is already asserted above.
- GLenum format = GL_RGBA, type = GL_UNSIGNED_BYTE;
- int bytes_per_pixel = 4;
-
- switch (bitmap_config) {
- case SkBitmap::kARGB_8888_Config:
- if (swizzle == kSwizzleBGRA)
- format = GL_BGRA_EXT;
- break;
- case SkBitmap::kRGB_565_Config:
- format = GL_RGB;
- type = GL_UNSIGNED_SHORT_5_6_5;
- bytes_per_pixel = 2;
- break;
- default:
- NOTREACHED();
- break;
- }
+
gl_->GenBuffers(1, &request->buffer);
gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
@@ -466,32 +498,86 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
request, bytes_per_pixel));
}
+
void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
GLuint src_texture,
const gfx::Size& src_size,
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
unsigned char* out,
- const SkBitmap::Config bitmap_config,
+ const SkColorType out_color_type,
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality) {
- if (!IsReadbackConfigSupported(bitmap_config)) {
+ GLenum format, type;
+ size_t bytes_per_pixel;
+ SkColorType readback_color_type = out_color_type;
+ // Single-component textures are not supported by all GPUs, so we implement
+ // kAlpha_8_SkColorType support here via a special encoding (see below) using
+ // a 32-bit texture to represent an 8-bit image.
+ // Thus we use generic 32-bit readback in this case.
+ if (out_color_type == kAlpha_8_SkColorType) {
+ readback_color_type = kRGBA_8888_SkColorType;
+ }
+
+ FormatSupport supported = GetReadbackConfig(
+ readback_color_type, true, &format, &type, &bytes_per_pixel);
+
+ if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
callback.Run(false);
return;
}
- GLuint texture = ScaleTexture(src_texture,
- src_size,
- src_subrect,
- dst_size,
- true,
-#if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
- true,
-#else
- false,
-#endif
- bitmap_config,
- quality);
- DCHECK(texture);
+
+ GLuint texture = src_texture;
+
+ // Scale texture if needed
+ // Optimization: SCALER_QUALITY_FAST is just a single bilinear pass, which we
+ // can do just as well in EncodeTextureAsGrayscale, which we will do if
+ // out_color_type is kAlpha_8_SkColorType, so let's skip the scaling step
+ // in that case.
+ bool scale_texture = out_color_type != kAlpha_8_SkColorType ||
+ quality != GLHelper::SCALER_QUALITY_FAST;
+ if (scale_texture) {
+ // Don't swizzle during the scale step for kAlpha_8_SkColorType.
+ // We will swizzle in the encode step below if needed.
+ bool scale_swizzle = out_color_type == kAlpha_8_SkColorType
+ ? false
+ : supported == GLHelperReadbackSupport::SWIZZLE;
+ texture =
+ ScaleTexture(src_texture,
+ src_size,
+ src_subrect,
+ dst_size,
+ true,
+ scale_swizzle,
+ out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType
+ : out_color_type,
+ quality);
+ DCHECK(texture);
+ }
+
+ gfx::Size readback_texture_size = dst_size;
+ // Encode texture to grayscale if needed.
+ if (out_color_type == kAlpha_8_SkColorType) {
+ // Do the vertical flip here if we haven't already done it when we scaled
+ // the texture.
+ bool encode_as_grayscale_vertical_flip = !scale_texture;
+ // EncodeTextureAsGrayscale by default creates a texture which should be
+ // read back as RGBA, so need to swizzle if the readback format is BGRA.
+ bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT;
+ GLuint tmp_texture =
+ EncodeTextureAsGrayscale(texture,
+ dst_size,
+ &readback_texture_size,
+ encode_as_grayscale_vertical_flip,
+ encode_as_grayscale_swizzle);
+ // If the scaled texture was created - delete it
+ if (scale_texture)
+ gl_->DeleteTextures(1, &texture);
+ texture = tmp_texture;
+ DCHECK(texture);
+ }
+
+ // Readback the pixels of the resulting texture
ScopedFramebuffer dst_framebuffer(gl_);
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
dst_framebuffer);
@@ -501,24 +587,18 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
GL_TEXTURE_2D,
texture,
0);
- int bytes_per_pixel = 4;
- switch (bitmap_config) {
- case SkBitmap::kARGB_8888_Config:
- // Do nothing params already set.
- break;
- case SkBitmap::kRGB_565_Config:
- bytes_per_pixel = 2;
- break;
- default:
- NOTREACHED();
- break;
- }
- ReadbackAsync(dst_size,
- dst_size.width() * bytes_per_pixel,
- dst_size.width() * bytes_per_pixel,
+
+ int32 bytes_per_row = out_color_type == kAlpha_8_SkColorType
+ ? dst_size.width()
+ : dst_size.width() * bytes_per_pixel;
+
+ ReadbackAsync(readback_texture_size,
+ bytes_per_row,
+ bytes_per_row,
out,
- bitmap_config,
- kSwizzleNone,
+ format,
+ type,
+ bytes_per_pixel,
callback);
gl_->DeleteTextures(1, &texture);
}
@@ -527,9 +607,14 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
GLuint texture,
const gfx::Rect& src_rect,
unsigned char* out,
- SkBitmap::Config bitmap_config) {
- if (!IsReadbackConfigSupported(bitmap_config))
+ SkColorType color_type) {
+ GLenum format, type;
+ size_t bytes_per_pixel;
+ FormatSupport supported =
+ GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
+ if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
return;
+ }
ScopedFramebuffer dst_framebuffer(gl_);
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
@@ -537,11 +622,6 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
gl_->FramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
- GLenum format =
- (bitmap_config == SkBitmap::kRGB_565_Config) ? GL_RGB : GL_RGBA;
- GLenum type = (bitmap_config == SkBitmap::kRGB_565_Config)
- ? GL_UNSIGNED_SHORT_5_6_5
- : GL_UNSIGNED_BYTE;
gl_->ReadPixels(src_rect.x(),
src_rect.y(),
src_rect.width(),
@@ -555,10 +635,16 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
GLuint texture,
const gfx::Size& dst_size,
unsigned char* out,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
const base::Callback<void(bool)>& callback) {
- if (!IsReadbackConfigSupported(bitmap_config))
+ GLenum format, type;
+ size_t bytes_per_pixel;
+ FormatSupport supported =
+ GetReadbackConfig(color_type, false, &format, &type, &bytes_per_pixel);
+ if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
+ callback.Run(false);
return;
+ }
ScopedFramebuffer dst_framebuffer(gl_);
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
@@ -569,13 +655,13 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
GL_TEXTURE_2D,
texture,
0);
- int bytes_per_pixel = (bitmap_config == SkBitmap::kRGB_565_Config) ? 2 : 4;
ReadbackAsync(dst_size,
dst_size.width() * bytes_per_pixel,
dst_size.width() * bytes_per_pixel,
out,
- bitmap_config,
- kSwizzleNone,
+ format,
+ type,
+ bytes_per_pixel,
callback);
}
@@ -591,19 +677,10 @@ GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
dst_size,
vertically_flip_texture,
false,
- SkBitmap::kARGB_8888_Config,
+ kRGBA_8888_SkColorType, // GL_RGBA
quality);
}
-bool GLHelper::CopyTextureToImpl::IsReadbackConfigSupported(
- SkBitmap::Config bitmap_config) {
- if (!helper_) {
- DCHECK(helper_);
- return false;
- }
- return helper_->IsReadbackConfigSupported(bitmap_config);
-}
-
void GLHelper::CopyTextureToImpl::ReadbackDone(Request* finished_request,
int bytes_per_pixel) {
TRACE_EVENT0("mirror",
@@ -669,6 +746,16 @@ void GLHelper::CopyTextureToImpl::CancelRequests() {
}
}
+FormatSupport GLHelper::CopyTextureToImpl::GetReadbackConfig(
+ SkColorType color_type,
+ bool can_swizzle,
+ GLenum* format,
+ GLenum* type,
+ size_t* bytes_per_pixel) {
+ return helper_->readback_support_->GetReadbackConfig(
+ color_type, can_swizzle, format, type, bytes_per_pixel);
+}
+
GLHelper::GLHelper(GLES2Interface* gl, gpu::ContextSupport* context_support)
: gl_(gl),
context_support_(context_support),
@@ -682,19 +769,18 @@ void GLHelper::CropScaleReadbackAndCleanTexture(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
unsigned char* out,
- const SkBitmap::Config config,
+ const SkColorType out_color_type,
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality) {
InitCopyTextToImpl();
- copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(
- src_texture,
- src_size,
- src_subrect,
- dst_size,
- out,
- config,
- callback,
- quality);
+ copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture,
+ src_size,
+ src_subrect,
+ dst_size,
+ out,
+ out_color_type,
+ callback,
+ quality);
}
void GLHelper::CropScaleReadbackAndCleanMailbox(
@@ -704,22 +790,25 @@ void GLHelper::CropScaleReadbackAndCleanMailbox(
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
unsigned char* out,
- const SkBitmap::Config bitmap_config,
+ const SkColorType out_color_type,
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality) {
GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_point);
- CropScaleReadbackAndCleanTexture(
- mailbox_texture, src_size, src_subrect, dst_size, out,
- bitmap_config,
- callback,
- quality);
+ CropScaleReadbackAndCleanTexture(mailbox_texture,
+ src_size,
+ src_subrect,
+ dst_size,
+ out,
+ out_color_type,
+ callback,
+ quality);
gl_->DeleteTextures(1, &mailbox_texture);
}
void GLHelper::ReadbackTextureSync(GLuint texture,
const gfx::Rect& src_rect,
unsigned char* out,
- SkBitmap::Config format) {
+ SkColorType format) {
InitCopyTextToImpl();
copy_texture_to_impl_->ReadbackTextureSync(texture, src_rect, out, format);
}
@@ -728,13 +817,13 @@ void GLHelper::ReadbackTextureAsync(
GLuint texture,
const gfx::Size& dst_size,
unsigned char* out,
- SkBitmap::Config config,
+ SkColorType color_type,
const base::Callback<void(bool)>& callback) {
InitCopyTextToImpl();
copy_texture_to_impl_->ReadbackTextureAsync(texture,
dst_size,
out,
- config,
+ color_type,
callback);
}
@@ -850,8 +939,7 @@ gpu::MailboxHolder GLHelper::ProduceMailboxHolderFromTexture(
GLuint texture_id) {
gpu::Mailbox mailbox;
gl_->GenMailboxCHROMIUM(mailbox.name);
- content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture_id);
- gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+ gl_->ProduceTextureDirectCHROMIUM(texture_id, GL_TEXTURE_2D, mailbox.name);
return gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, InsertSyncPoint());
}
@@ -861,9 +949,8 @@ GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
return 0;
if (sync_point)
WaitSyncPoint(sync_point);
- GLuint texture = CreateTexture();
- content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+ GLuint texture =
+ gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
return texture;
}
@@ -917,8 +1004,9 @@ void GLHelper::CopyTextureToImpl::ReadbackPlane(
dst_subrect.width() >> size_shift,
target->stride(plane),
target->data(plane) + offset,
- SkBitmap::kARGB_8888_Config,
- swizzle,
+ (swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ 4,
callback);
}
@@ -928,6 +1016,8 @@ const float GLHelper::CopyTextureToImpl::kRGBtoUColorWeights[] = {
-0.148f, -0.291f, 0.439f, 0.5f};
const float GLHelper::CopyTextureToImpl::kRGBtoVColorWeights[] = {
0.439f, -0.368f, -0.071f, 0.5f};
+const float GLHelper::CopyTextureToImpl::kRGBtoGrayscaleColorWeights[] = {
+ 0.213f, 0.715f, 0.072f, 0.0f};
// YUV readback constructors. Initiates the main scaler pipeline and
// one planar scaler for each of the Y, U and V planes.
@@ -1053,7 +1143,7 @@ void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
swizzle_,
base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
- media::LetterboxYUV(target, dst_subrect_);
+ media::LetterboxYUV(target.get(), dst_subrect_);
}
// YUV readback constructors. Initiates the main scaler pipeline and
@@ -1191,12 +1281,17 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
swizzle_,
base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
- media::LetterboxYUV(target, dst_subrect_);
+ media::LetterboxYUV(target.get(), dst_subrect_);
}
-bool GLHelper::IsReadbackConfigSupported(SkBitmap::Config texture_format) {
+bool GLHelper::IsReadbackConfigSupported(SkColorType color_type) {
DCHECK(readback_support_.get());
- return readback_support_.get()->IsReadbackConfigSupported(texture_format);
+ GLenum format, type;
+ size_t bytes_per_pixel;
+ FormatSupport support = readback_support_->GetReadbackConfig(
+ color_type, false, &format, &type, &bytes_per_pixel);
+
+ return (support == GLHelperReadbackSupport::SUPPORTED);
}
ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
@@ -1208,15 +1303,19 @@ ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
bool flip_vertically,
bool use_mrt) {
helper_->InitScalerImpl();
- // Query preferred format for glReadPixels, if is is GL_BGRA then use that
- // and trigger the appropriate swizzle in the YUV shaders.
- GLint format = 0, type = 0;
+ // Just query if the best readback configuration needs a swizzle In
+ // ReadbackPlane() we will choose GL_RGBA/GL_BGRA_EXT based on swizzle
+ GLenum format, type;
+ size_t bytes_per_pixel;
+ FormatSupport supported = GetReadbackConfig(
+ kRGBA_8888_SkColorType, true, &format, &type, &bytes_per_pixel);
+ DCHECK((format == GL_RGBA || format == GL_BGRA_EXT) &&
+ type == GL_UNSIGNED_BYTE);
+
ReadbackSwizzle swizzle = kSwizzleNone;
- helper_->readback_support_.get()->GetAdditionalFormat(GL_RGBA,
- GL_UNSIGNED_BYTE,
- &format, &type);
- if (format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
+ if (supported == GLHelperReadbackSupport::SWIZZLE)
swizzle = kSwizzleBGRA;
+
if (max_draw_buffers_ >= 2 && use_mrt) {
return new ReadbackYUV_MRT(gl_,
this,
diff --git a/chromium/content/common/gpu/client/gl_helper.h b/chromium/content/common/gpu/client/gl_helper.h
index 4169c8b6da4..dc90ddeb1c4 100644
--- a/chromium/content/common/gpu/client/gl_helper.h
+++ b/chromium/content/common/gpu/client/gl_helper.h
@@ -160,8 +160,8 @@ class CONTENT_EXPORT GLHelper {
// Copies the block of pixels specified with |src_subrect| from |src_texture|,
// scales it to |dst_size|, and writes it into |out|.
- // |src_size| is the size of |src_texture|. The result is of format GL_BGRA
- // and is potentially flipped vertically to make it a correct image
+ // |src_size| is the size of |src_texture|. The result is in |out_color_type|
+ // format and is potentially flipped vertically to make it a correct image
// representation. |callback| is invoked with the copy result when the copy
// operation has completed.
// Note that the src_texture will have the min/mag filter set to GL_LINEAR
@@ -172,14 +172,14 @@ class CONTENT_EXPORT GLHelper {
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
unsigned char* out,
- const SkBitmap::Config config,
+ const SkColorType out_color_type,
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality);
// Copies the block of pixels specified with |src_subrect| from |src_mailbox|,
// scales it to |dst_size|, and writes it into |out|.
- // |src_size| is the size of |src_mailbox|. The result is of format GL_BGRA
- // and is potentially flipped vertically to make it a correct image
+ // |src_size| is the size of |src_mailbox|. The result is in |out_color_type|
+ // format and is potentially flipped vertically to make it a correct image
// representation. |callback| is invoked with the copy result when the copy
// operation has completed.
// Note that the texture bound to src_mailbox will have the min/mag filter set
@@ -192,7 +192,7 @@ class CONTENT_EXPORT GLHelper {
const gfx::Rect& src_subrect,
const gfx::Size& dst_size,
unsigned char* out,
- const SkBitmap::Config config,
+ const SkColorType out_color_type,
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality);
@@ -204,12 +204,12 @@ class CONTENT_EXPORT GLHelper {
void ReadbackTextureSync(GLuint texture,
const gfx::Rect& src_rect,
unsigned char* out,
- SkBitmap::Config format);
+ SkColorType format);
void ReadbackTextureAsync(GLuint texture,
const gfx::Size& dst_size,
unsigned char* out,
- SkBitmap::Config config,
+ SkColorType color_type,
const base::Callback<void(bool)>& callback);
// Creates a copy of the specified texture. |size| is the size of the texture.
@@ -322,7 +322,7 @@ class CONTENT_EXPORT GLHelper {
// Checks whether the readbback is supported for texture with the
// matching config. This doesnt check for cross format readbacks.
- bool IsReadbackConfigSupported(SkBitmap::Config texture_format);
+ bool IsReadbackConfigSupported(SkColorType texture_format);
protected:
class CopyTextureToImpl;
diff --git a/chromium/content/common/gpu/client/gl_helper_benchmark.cc b/chromium/content/common/gpu/client/gl_helper_benchmark.cc
index b930bb0af00..a394fcfa474 100644
--- a/chromium/content/common/gpu/client/gl_helper_benchmark.cc
+++ b/chromium/content/common/gpu/client/gl_helper_benchmark.cc
@@ -19,7 +19,7 @@
#include "base/at_exit.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "content/common/gpu/client/gl_helper.h"
@@ -56,12 +56,12 @@ const char *kQualityNames[] = {
class GLHelperTest : public testing::Test {
protected:
- virtual void SetUp() {
+ void SetUp() override {
WebGraphicsContext3D::Attributes attributes;
bool lose_context_when_out_of_memory = false;
context_ = webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl::
CreateOffscreenContext(attributes, lose_context_when_out_of_memory);
- context_->makeContextCurrent();
+ context_->InitializeOnCurrentThread();
helper_.reset(
new content::GLHelper(context_->GetGLInterface(),
@@ -71,7 +71,7 @@ class GLHelperTest : public testing::Test {
helper_.get()));
}
- virtual void TearDown() {
+ void TearDown() override {
helper_scaling_.reset(NULL);
helper_.reset(NULL);
context_.reset(NULL);
@@ -141,18 +141,10 @@ TEST_F(GLHelperTest, ScaleBenchmark) {
const gfx::Size dst_size(output_sizes[outsize],
output_sizes[outsize + 1]);
SkBitmap input;
- input.setConfig(SkBitmap::kARGB_8888_Config,
- src_size.width(),
- src_size.height());
- input.allocPixels();
- SkAutoLockPixels lock(input);
+ input.allocN32Pixels(src_size.width(), src_size.height());
SkBitmap output_pixels;
- input.setConfig(SkBitmap::kARGB_8888_Config,
- dst_size.width(),
- dst_size.height());
- output_pixels.allocPixels();
- SkAutoLockPixels output_lock(output_pixels);
+ output_pixels.allocN32Pixels(dst_size.width(), dst_size.height());
context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
context_->bindTexture(GL_TEXTURE_2D, dst_texture);
@@ -278,11 +270,7 @@ TEST_F(GLHelperTest, DISABLED_ScaleTestImage) {
kQualities[q]);
SkBitmap output_pixels;
- input.setConfig(SkBitmap::kARGB_8888_Config,
- dst_size.width(),
- dst_size.height());
- output_pixels.allocPixels();
- SkAutoLockPixels lock(output_pixels);
+ output_pixels.allocN32Pixels(dst_size.width(), dst_size.height());
helper_->ReadbackTextureSync(
dst_texture,
@@ -290,7 +278,7 @@ TEST_F(GLHelperTest, DISABLED_ScaleTestImage) {
dst_size.width(),
dst_size.height()),
static_cast<unsigned char *>(output_pixels.getPixels()),
- SkBitmap::kARGB_8888_Config);
+ kN32_SkColorType);
context_->deleteTexture(dst_texture);
std::string filename = base::StringPrintf("testoutput_%s_%d.ppm",
kQualityNames[q],
@@ -308,7 +296,7 @@ TEST_F(GLHelperTest, DISABLED_ScaleTestImage) {
// These tests needs to run against a proper GL environment, so we
// need to set it up before we can run the tests.
int main(int argc, char** argv) {
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
base::TestSuite* suite = new content::ContentTestSuite(argc, argv);
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool pool;
diff --git a/chromium/content/common/gpu/client/gl_helper_readback_support.cc b/chromium/content/common/gpu/client/gl_helper_readback_support.cc
index 643b8ab5cdd..e773ca90782 100644
--- a/chromium/content/common/gpu/client/gl_helper_readback_support.cc
+++ b/chromium/content/common/gpu/client/gl_helper_readback_support.cc
@@ -4,6 +4,8 @@
#include "content/common/gpu/client/gl_helper_readback_support.h"
#include "base/logging.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
namespace content {
@@ -15,32 +17,38 @@ GLHelperReadbackSupport::GLHelperReadbackSupport(gpu::gles2::GLES2Interface* gl)
GLHelperReadbackSupport::~GLHelperReadbackSupport() {}
void GLHelperReadbackSupport::InitializeReadbackSupport() {
- // We are concerned about 16, 32-bit formats only.
- // The below are the most used 16, 32-bit formats.
- // In future if any new format support is needed that should be added here.
- // Initialize the array with FORMAT_NOT_SUPPORTED as we dont know the
- // supported formats yet.
- for (int i = 0; i < SkBitmap::kConfigCount; ++i) {
- format_support_table_[i] = FORMAT_NOT_SUPPORTED;
+ // We are concerned about 16, 32-bit formats only. The below are the most
+ // used 16, 32-bit formats. In future if any new format support is needed
+ // that should be added here. Initialize the array with
+ // GLHelperReadbackSupport::NOT_SUPPORTED as we dont know the supported
+ // formats yet.
+ for (int i = 0; i <= kLastEnum_SkColorType; ++i) {
+ format_support_table_[i] = GLHelperReadbackSupport::NOT_SUPPORTED;
}
- CheckForReadbackSupport(SkBitmap::kRGB_565_Config);
- CheckForReadbackSupport(SkBitmap::kARGB_4444_Config);
- CheckForReadbackSupport(SkBitmap::kARGB_8888_Config);
+ // TODO(sikugu): kAlpha_8_SkColorType support check is failing on mesa.
+ // See crbug.com/415667.
+ CheckForReadbackSupport(kRGB_565_SkColorType);
+ CheckForReadbackSupport(kARGB_4444_SkColorType);
+ CheckForReadbackSupport(kRGBA_8888_SkColorType);
+ CheckForReadbackSupport(kBGRA_8888_SkColorType);
// Further any formats, support should be checked here.
}
void GLHelperReadbackSupport::CheckForReadbackSupport(
- SkBitmap::Config texture_format) {
+ SkColorType texture_format) {
bool supports_format = false;
switch (texture_format) {
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
supports_format = SupportsFormat(GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
break;
- case SkBitmap::kARGB_8888_Config:
+ case kRGBA_8888_SkColorType:
// This is the baseline, assume always true.
supports_format = true;
break;
- case SkBitmap::kARGB_4444_Config:
+ case kBGRA_8888_SkColorType:
+ supports_format = SupportsFormat(GL_BGRA_EXT, GL_UNSIGNED_BYTE);
+ break;
+ case kARGB_4444_SkColorType:
supports_format = false;
break;
default:
@@ -48,14 +56,16 @@ void GLHelperReadbackSupport::CheckForReadbackSupport(
supports_format = false;
break;
}
- DCHECK((int)texture_format < (int)SkBitmap::kConfigCount);
+ DCHECK((int)texture_format <= (int)kLastEnum_SkColorType);
format_support_table_[texture_format] =
- supports_format ? FORMAT_SUPPORTED : FORMAT_NOT_SUPPORTED;
+ supports_format ? GLHelperReadbackSupport::SUPPORTED
+ : GLHelperReadbackSupport::NOT_SUPPORTED;
}
-void GLHelperReadbackSupport::GetAdditionalFormat(GLint format, GLint type,
- GLint *format_out,
- GLint *type_out) {
+void GLHelperReadbackSupport::GetAdditionalFormat(GLenum format,
+ GLenum type,
+ GLenum* format_out,
+ GLenum* type_out) {
for (unsigned int i = 0; i < format_cache_.size(); i++) {
if (format_cache_[i].format == format && format_cache_[i].type == type) {
*format_out = format_cache_[i].read_format;
@@ -78,20 +88,35 @@ void GLHelperReadbackSupport::GetAdditionalFormat(GLint format, GLint type,
dst_framebuffer);
gl_->FramebufferTexture2D(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_texture, 0);
- gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, format_out);
- gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, type_out);
+ GLint format_tmp = 0, type_tmp = 0;
+ gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format_tmp);
+ gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type_tmp);
+ *format_out = format_tmp;
+ *type_out = type_tmp;
struct FormatCacheEntry entry = { format, type, *format_out, *type_out };
format_cache_.push_back(entry);
}
-bool GLHelperReadbackSupport::SupportsFormat(GLint format, GLint type) {
+bool GLHelperReadbackSupport::SupportsFormat(GLenum format, GLenum type) {
// GLES2.0 Specification says this pairing is always supported
// with additional format from GL_IMPLEMENTATION_COLOR_READ_FORMAT/TYPE
if (format == GL_RGBA && type == GL_UNSIGNED_BYTE)
return true;
+
+ if (format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE) {
+ const GLubyte* tmp = gl_->GetString(GL_EXTENSIONS);
+ if (tmp) {
+ std::string extensions =
+ " " + std::string(reinterpret_cast<const char*>(tmp)) + " ";
+ if (extensions.find(" GL_EXT_read_format_bgra ") != std::string::npos) {
+ return true;
+ }
+ }
+ }
+
bool supports_format = false;
- GLint ext_format = 0, ext_type = 0;
+ GLenum ext_format = 0, ext_type = 0;
GetAdditionalFormat(format, type, &ext_format, &ext_type);
if ((ext_format == format) && (ext_type == type)) {
supports_format = true;
@@ -99,17 +124,60 @@ bool GLHelperReadbackSupport::SupportsFormat(GLint format, GLint type) {
return supports_format;
}
-bool GLHelperReadbackSupport::IsReadbackConfigSupported(
- SkBitmap::Config texture_format) {
- switch (format_support_table_[texture_format]) {
- case FORMAT_SUPPORTED:
- return true;
- case FORMAT_NOT_SUPPORTED:
- return false;
+GLHelperReadbackSupport::FormatSupport
+GLHelperReadbackSupport::GetReadbackConfig(SkColorType color_type,
+ bool can_swizzle,
+ GLenum* format,
+ GLenum* type,
+ size_t* bytes_per_pixel) {
+ DCHECK(format && type && bytes_per_pixel);
+ *bytes_per_pixel = 4;
+ *type = GL_UNSIGNED_BYTE;
+ GLenum new_format = 0, new_type = 0;
+ switch (color_type) {
+ case kRGB_565_SkColorType:
+ if (format_support_table_[color_type] ==
+ GLHelperReadbackSupport::SUPPORTED) {
+ *format = GL_RGB;
+ *type = GL_UNSIGNED_SHORT_5_6_5;
+ *bytes_per_pixel = 2;
+ return GLHelperReadbackSupport::SUPPORTED;
+ }
+ break;
+ case kRGBA_8888_SkColorType:
+ *format = GL_RGBA;
+ if (can_swizzle) {
+ // If GL_BGRA_EXT is advertised as the readback format through
+ // GL_IMPLEMENTATION_COLOR_READ_FORMAT then assume it is preferred by
+ // the implementation for performance.
+ GetAdditionalFormat(*format, *type, &new_format, &new_type);
+
+ if (new_format == GL_BGRA_EXT && new_type == GL_UNSIGNED_BYTE) {
+ *format = GL_BGRA_EXT;
+ return GLHelperReadbackSupport::SWIZZLE;
+ }
+ }
+ return GLHelperReadbackSupport::SUPPORTED;
+ case kBGRA_8888_SkColorType:
+ *format = GL_BGRA_EXT;
+ if (format_support_table_[color_type] ==
+ GLHelperReadbackSupport::SUPPORTED)
+ return GLHelperReadbackSupport::SUPPORTED;
+
+ if (can_swizzle) {
+ *format = GL_RGBA;
+ return GLHelperReadbackSupport::SWIZZLE;
+ }
+
+ break;
+ case kARGB_4444_SkColorType:
+ return GLHelperReadbackSupport::NOT_SUPPORTED;
default:
NOTREACHED();
- return false;
+ break;
}
+
+ return GLHelperReadbackSupport::NOT_SUPPORTED;
}
} // namespace content
diff --git a/chromium/content/common/gpu/client/gl_helper_readback_support.h b/chromium/content/common/gpu/client/gl_helper_readback_support.h
index e163c761fdf..f60438f3ae9 100644
--- a/chromium/content/common/gpu/client/gl_helper_readback_support.h
+++ b/chromium/content/common/gpu/client/gl_helper_readback_support.h
@@ -13,29 +13,35 @@ namespace content {
class CONTENT_EXPORT GLHelperReadbackSupport {
public:
+ enum FormatSupport { SUPPORTED, SWIZZLE, NOT_SUPPORTED };
+
GLHelperReadbackSupport(gpu::gles2::GLES2Interface* gl);
~GLHelperReadbackSupport();
- // Checks whether the readback (Color read format and type) is supported
- // for the requested texture format by the hardware or not.
- // For ex: some hardwares have rgb565 readback
- // support when binded with the frame buffer for others it may fail.
- // Here we pass the internal textureformat as skia config.
- bool IsReadbackConfigSupported(SkBitmap::Config texture_format);
-
+ // For a given color type retrieve whether readback is supported and if so
+ // how it should be performed. The |format|, |type| and |bytes_per_pixel| are
+ // the values that should be used with glReadPixels to facilitate the
+ // readback. If |can_swizzle| is true then this method will return SWIZZLE if
+ // the data needs to be swizzled before using the returned |format| otherwise
+ // the method will return SUPPORTED to indicate that readback is permitted of
+ // this color othewise NOT_SUPPORTED will be returned. This method always
+ // overwrites the out values irrespective of the return value.
+ FormatSupport GetReadbackConfig(SkColorType color_type,
+ bool can_swizzle,
+ GLenum* format,
+ GLenum* type,
+ size_t* bytes_per_pixel);
// Provides the additional readback format/type pairing for a render target
// of a given format/type pairing
- void GetAdditionalFormat(GLint format, GLint type, GLint *format_out,
- GLint *type_out);
+ void GetAdditionalFormat(GLenum format, GLenum type, GLenum *format_out,
+ GLenum *type_out);
private:
- enum FormatSupport { FORMAT_NOT_SUPPORTED = 0, FORMAT_SUPPORTED, };
-
struct FormatCacheEntry {
- GLint format;
- GLint type;
- GLint read_format;
- GLint read_type;
+ GLenum format;
+ GLenum type;
+ GLenum read_format;
+ GLenum read_type;
};
// This populates the format_support_table with the list of supported
@@ -46,14 +52,14 @@ class CONTENT_EXPORT GLHelperReadbackSupport {
// InitializeReadbackSupport. We should not use this any where
// except the InitializeReadbackSupport.Calling this at other places
// can distrub the state of normal gl operations.
- void CheckForReadbackSupport(SkBitmap::Config texture_format);
+ void CheckForReadbackSupport(SkColorType texture_format);
// Helper functions for checking the supported texture formats.
// Avoid using this API in between texture operations, as this does some
// teture opertions (bind, attach) internally.
- bool SupportsFormat(GLint format, GLint type);
+ bool SupportsFormat(GLenum format, GLenum type);
- FormatSupport format_support_table_[SkBitmap::kConfigCount];
+ FormatSupport format_support_table_[kLastEnum_SkColorType + 1];
gpu::gles2::GLES2Interface* gl_;
std::vector<struct FormatCacheEntry> format_cache_;
diff --git a/chromium/content/common/gpu/client/gl_helper_scaling.cc b/chromium/content/common/gpu/client/gl_helper_scaling.cc
index 219f46b6a4c..be857b4b33f 100644
--- a/chromium/content/common/gpu/client/gl_helper_scaling.cc
+++ b/chromium/content/common/gpu/client/gl_helper_scaling.cc
@@ -155,15 +155,15 @@ class ScalerImpl : public GLHelper::ScalerInterface,
}
}
- virtual ~ScalerImpl() {
+ ~ScalerImpl() override {
if (intermediate_texture_) {
gl_->DeleteTextures(1, &intermediate_texture_);
}
}
// GLHelperShader::ShaderInterface implementation.
- virtual void Execute(GLuint source_texture,
- const std::vector<GLuint>& dest_textures) OVERRIDE {
+ void Execute(GLuint source_texture,
+ const std::vector<GLuint>& dest_textures) override {
if (subscaler_) {
subscaler_->Scale(source_texture, intermediate_texture_);
source_texture = intermediate_texture_;
@@ -214,25 +214,25 @@ class ScalerImpl : public GLHelper::ScalerInterface,
}
// GLHelper::ScalerInterface implementation.
- virtual void Scale(GLuint source_texture, GLuint dest_texture) OVERRIDE {
+ void Scale(GLuint source_texture, GLuint dest_texture) override {
std::vector<GLuint> tmp(1);
tmp[0] = dest_texture;
Execute(source_texture, tmp);
}
- virtual const gfx::Size& SrcSize() OVERRIDE {
+ const gfx::Size& SrcSize() override {
if (subscaler_) {
return subscaler_->SrcSize();
}
return spec_.src_size;
}
- virtual const gfx::Rect& SrcSubrect() OVERRIDE {
+ const gfx::Rect& SrcSubrect() override {
if (subscaler_) {
return subscaler_->SrcSubrect();
}
return spec_.src_subrect;
}
- virtual const gfx::Size& DstSize() OVERRIDE { return spec_.dst_size; }
+ const gfx::Size& DstSize() override { return spec_.dst_size; }
private:
GLES2Interface* gl_;
diff --git a/chromium/content/common/gpu/client/gl_helper_unittest.cc b/chromium/content/common/gpu/client/gl_helper_unittest.cc
index 5e5b555f963..47e2edf3956 100644
--- a/chromium/content/common/gpu/client/gl_helper_unittest.cc
+++ b/chromium/content/common/gpu/client/gl_helper_unittest.cc
@@ -15,7 +15,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
@@ -53,13 +53,13 @@ const char* kQualityNames[] = {"best", "good", "fast", };
class GLHelperTest : public testing::Test {
protected:
- virtual void SetUp() {
+ void SetUp() override {
WebGraphicsContext3D::Attributes attributes;
bool lose_context_when_out_of_memory = false;
context_ =
WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
attributes, lose_context_when_out_of_memory);
- context_->makeContextCurrent();
+ context_->InitializeOnCurrentThread();
context_support_ = context_->GetContextSupport();
helper_.reset(
new content::GLHelper(context_->GetGLInterface(), context_support_));
@@ -67,7 +67,7 @@ class GLHelperTest : public testing::Test {
context_->GetGLInterface(), helper_.get()));
}
- virtual void TearDown() {
+ void TearDown() override {
helper_scaling_.reset(NULL);
helper_.reset(NULL);
context_.reset(NULL);
@@ -77,7 +77,8 @@ class GLHelperTest : public testing::Test {
base::debug::TraceLog::GetInstance()->SetEnabled(
base::debug::CategoryFilter(filter),
base::debug::TraceLog::RECORDING_MODE,
- base::debug::TraceLog::RECORD_UNTIL_FULL);
+ base::debug::TraceOptions(
+ base::debug::RECORD_UNTIL_FULL));
}
static void TraceDataCB(
@@ -117,7 +118,11 @@ class GLHelperTest : public testing::Test {
CHECK(item->GetAsDictionary(&dict));
std::string name;
CHECK(dict->GetString("name", &name));
- (*event_counts)[name]++;
+ std::string trace_type;
+ CHECK(dict->GetString("ph", &trace_type));
+ // Count all except END traces, as they come in BEGIN/END pairs.
+ if (trace_type != "E")
+ (*event_counts)[name]++;
VLOG(1) << "trace name: " << name;
}
}
@@ -138,24 +143,40 @@ class GLHelperTest : public testing::Test {
}
}
- // Look up a single R/G/B/A value.
- // Clamp x/y.
+ // Look up a single channel value. Works for 4-channel and single channel
+ // bitmaps. Clamp x/y.
int Channel(SkBitmap* pixels, int x, int y, int c) {
- uint32* data =
- pixels->getAddr32(std::max(0, std::min(x, pixels->width() - 1)),
- std::max(0, std::min(y, pixels->height() - 1)));
- return (*data) >> (c * 8) & 0xff;
+ if (pixels->bytesPerPixel() == 4) {
+ uint32* data =
+ pixels->getAddr32(std::max(0, std::min(x, pixels->width() - 1)),
+ std::max(0, std::min(y, pixels->height() - 1)));
+ return (*data) >> (c * 8) & 0xff;
+ } else {
+ DCHECK_EQ(pixels->bytesPerPixel(), 1);
+ DCHECK_EQ(c, 0);
+ return *pixels->getAddr8(std::max(0, std::min(x, pixels->width() - 1)),
+ std::max(0, std::min(y, pixels->height() - 1)));
+ }
}
- // Set a single R/G/B/A value.
+ // Set a single channel value. Works for 4-channel and single channel
+ // bitmaps. Clamp x/y.
void SetChannel(SkBitmap* pixels, int x, int y, int c, int v) {
DCHECK_GE(x, 0);
DCHECK_GE(y, 0);
DCHECK_LT(x, pixels->width());
DCHECK_LT(y, pixels->height());
- uint32* data = pixels->getAddr32(x, y);
- v = std::max(0, std::min(v, 255));
- *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8));
+ if (pixels->bytesPerPixel() == 4) {
+ uint32* data = pixels->getAddr32(x, y);
+ v = std::max(0, std::min(v, 255));
+ *data = (*data & ~(0xffu << (c * 8))) | (v << (c * 8));
+ } else {
+ DCHECK_EQ(pixels->bytesPerPixel(), 1);
+ DCHECK_EQ(c, 0);
+ uint8* data = pixels->getAddr8(x, y);
+ v = std::max(0, std::min(v, 255));
+ *data = v;
+ }
}
// Print all the R, G, B or A values from an SkBitmap in a
@@ -258,6 +279,7 @@ class GLHelperTest : public testing::Test {
void ValidateScalerStages(
content::GLHelper::ScalerQuality quality,
const std::vector<GLHelperScaling::ScalerStage>& scaler_stages,
+ const gfx::Size& dst_size,
const std::string& message) {
bool previous_error = HasFailure();
// First, check that the input size for each stage is equal to
@@ -275,6 +297,12 @@ class GLHelperTest : public testing::Test {
scaler_stages[i].src_size.height());
}
+ // Check the output size matches the destination of the last stage
+ EXPECT_EQ(scaler_stages[scaler_stages.size() - 1].dst_size.width(),
+ dst_size.width());
+ EXPECT_EQ(scaler_stages[scaler_stages.size() - 1].dst_size.height(),
+ dst_size.height());
+
// Used to verify that up-scales are not attempted after some
// other scale.
bool scaled_x = false;
@@ -370,9 +398,10 @@ class GLHelperTest : public testing::Test {
}
}
- // Compare two bitmaps, make sure that each component of each pixel
- // is no more than |maxdiff| apart. If they are not similar enough,
- // prints out |truth|, |other|, |source|, |scaler_stages| and |message|.
+ // Compares two bitmaps taking color types into account. Checks whether each
+ // component of each pixel is no more than |maxdiff| apart. If bitmaps are not
+ // similar enough, prints out |truth|, |other|, |source|, |scaler_stages|
+ // and |message|.
void Compare(SkBitmap* truth,
SkBitmap* other,
int maxdiff,
@@ -381,21 +410,39 @@ class GLHelperTest : public testing::Test {
std::string message) {
EXPECT_EQ(truth->width(), other->width());
EXPECT_EQ(truth->height(), other->height());
+ bool swizzle = (truth->colorType() == kRGBA_8888_SkColorType &&
+ other->colorType() == kBGRA_8888_SkColorType) ||
+ (truth->colorType() == kBGRA_8888_SkColorType &&
+ other->colorType() == kRGBA_8888_SkColorType);
+ EXPECT_TRUE(swizzle || truth->colorType() == other->colorType());
+ int bpp = truth->bytesPerPixel();
for (int x = 0; x < truth->width(); x++) {
for (int y = 0; y < truth->height(); y++) {
- for (int c = 0; c < 4; c++) {
+ for (int c = 0; c < bpp; c++) {
int a = Channel(truth, x, y, c);
- int b = Channel(other, x, y, c);
+ // swizzle when comparing if needed
+ int b = swizzle && (c == 0 || c == 2)
+ ? Channel(other, x, y, (c + 2) & 2)
+ : Channel(other, x, y, c);
EXPECT_NEAR(a, b, maxdiff) << " x=" << x << " y=" << y << " c=" << c
<< " " << message;
if (std::abs(a - b) > maxdiff) {
LOG(ERROR) << "-------expected--------";
- PrintChannel(truth, c);
+ for (int i = 0; i < bpp; i++) {
+ LOG(ERROR) << "Channel " << i << ":";
+ PrintChannel(truth, i);
+ }
LOG(ERROR) << "-------actual--------";
- PrintChannel(other, c);
+ for (int i = 0; i < bpp; i++) {
+ LOG(ERROR) << "Channel " << i << ":";
+ PrintChannel(other, i);
+ }
if (source) {
- LOG(ERROR) << "-------before scaling--------";
- PrintChannel(source, c);
+ LOG(ERROR) << "-------original--------";
+ for (int i = 0; i < source->bytesPerPixel(); i++) {
+ LOG(ERROR) << "Channel " << i << ":";
+ PrintChannel(source, i);
+ }
}
LOG(ERROR) << "-----Scaler stages------";
LOG(ERROR) << PrintStages(scaler_stages);
@@ -425,6 +472,30 @@ class GLHelperTest : public testing::Test {
ChannelAsFloat(pixels, base_x + 1, base_y + 1, c) * x * y);
}
+ // Encodes an RGBA bitmap to grayscale.
+ // Reference implementation for
+ // GLHelper::CopyToTextureImpl::EncodeTextureAsGrayscale.
+ void EncodeToGrayscaleSlow(SkBitmap* input, SkBitmap* output) {
+ const float kRGBtoGrayscaleColorWeights[3] = {0.213f, 0.715f, 0.072f};
+ CHECK_EQ(kAlpha_8_SkColorType, output->colorType());
+ CHECK_EQ(input->width(), output->width());
+ CHECK_EQ(input->height(), output->height());
+ CHECK_EQ(input->colorType(), kRGBA_8888_SkColorType);
+
+ for (int dst_y = 0; dst_y < output->height(); dst_y++) {
+ for (int dst_x = 0; dst_x < output->width(); dst_x++) {
+ float c0 = ChannelAsFloat(input, dst_x, dst_y, 0);
+ float c1 = ChannelAsFloat(input, dst_x, dst_y, 1);
+ float c2 = ChannelAsFloat(input, dst_x, dst_y, 2);
+ float value = c0 * kRGBtoGrayscaleColorWeights[0] +
+ c1 * kRGBtoGrayscaleColorWeights[1] +
+ c2 * kRGBtoGrayscaleColorWeights[2];
+ SetChannel(
+ output, dst_x, dst_y, 0, static_cast<int>(value * 255.0f + 0.5f));
+ }
+ }
+ }
+
// Very slow bicubic / bilinear scaler for reference.
void ScaleSlow(SkBitmap* input,
SkBitmap* output,
@@ -507,18 +578,37 @@ class GLHelperTest : public testing::Test {
}
void FlipSKBitmap(SkBitmap* bitmap) {
+ int bpp = bitmap->bytesPerPixel();
+ DCHECK(bpp == 4 || bpp == 1);
int top_line = 0;
int bottom_line = bitmap->height() - 1;
while (top_line < bottom_line) {
for (int x = 0; x < bitmap->width(); x++) {
- std::swap(*bitmap->getAddr32(x, top_line),
- *bitmap->getAddr32(x, bottom_line));
+ bpp == 4 ? std::swap(*bitmap->getAddr32(x, top_line),
+ *bitmap->getAddr32(x, bottom_line))
+ : std::swap(*bitmap->getAddr8(x, top_line),
+ *bitmap->getAddr8(x, bottom_line));
}
top_line++;
bottom_line--;
}
}
+ // Swaps red and blue channels in each pixel in a 32-bit bitmap.
+ void SwizzleSKBitmap(SkBitmap* bitmap) {
+ int bpp = bitmap->bytesPerPixel();
+ DCHECK(bpp == 4);
+ for (int y = 0; y < bitmap->height(); y++) {
+ for (int x = 0; x < bitmap->width(); x++) {
+ // Swap channels 0 and 2 (red and blue)
+ int c0 = Channel(bitmap, x, y, 0);
+ int c2 = Channel(bitmap, x, y, 2);
+ SetChannel(bitmap, x, y, 2, c0);
+ SetChannel(bitmap, x, y, 0, c2);
+ }
+ }
+ }
+
// gl_helper scales recursively, so we'll need to do that
// in the reference implementation too.
void ScaleSlowRecursive(SkBitmap* input,
@@ -561,66 +651,181 @@ class GLHelperTest : public testing::Test {
}
SkBitmap tmp;
- tmp.setConfig(SkBitmap::kARGB_8888_Config, xtmp, ytmp);
- tmp.allocPixels();
- SkAutoLockPixels lock(tmp);
+ tmp.allocN32Pixels(xtmp, ytmp);
ScaleSlowRecursive(input, &tmp, quality);
ScaleSlowRecursive(&tmp, output, quality);
}
- // Scaling test: Create a test image, scale it using GLHelperScaling
- // and a reference implementation and compare the results.
- void TestScale(int xsize,
- int ysize,
- int scaled_xsize,
- int scaled_ysize,
- int test_pattern,
- size_t quality,
- bool flip) {
- WebGLId src_texture = context_->createTexture();
- WebGLId framebuffer = context_->createFramebuffer();
- SkBitmap input_pixels;
- input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize);
- input_pixels.allocPixels();
- SkAutoLockPixels lock(input_pixels);
+ // Creates an RGBA SkBitmap
+ scoped_ptr<SkBitmap> CreateTestBitmap(int width,
+ int height,
+ int test_pattern) {
+ scoped_ptr<SkBitmap> bitmap(new SkBitmap);
+ bitmap->allocPixels(SkImageInfo::Make(
+ width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
- for (int x = 0; x < xsize; ++x) {
- for (int y = 0; y < ysize; ++y) {
+ for (int x = 0; x < width; ++x) {
+ for (int y = 0; y < height; ++y) {
switch (test_pattern) {
case 0: // Smooth test pattern
- SetChannel(&input_pixels, x, y, 0, x * 10);
- SetChannel(&input_pixels, x, y, 1, y * 10);
- SetChannel(&input_pixels, x, y, 2, (x + y) * 10);
- SetChannel(&input_pixels, x, y, 3, 255);
+ SetChannel(bitmap.get(), x, y, 0, x * 10);
+ SetChannel(bitmap.get(), x, y, 0, y == 0 ? x * 50 : x * 10);
+ SetChannel(bitmap.get(), x, y, 1, y * 10);
+ SetChannel(bitmap.get(), x, y, 2, (x + y) * 10);
+ SetChannel(bitmap.get(), x, y, 3, 255);
break;
case 1: // Small blocks
- SetChannel(&input_pixels, x, y, 0, x & 1 ? 255 : 0);
- SetChannel(&input_pixels, x, y, 1, y & 1 ? 255 : 0);
- SetChannel(&input_pixels, x, y, 2, (x + y) & 1 ? 255 : 0);
- SetChannel(&input_pixels, x, y, 3, 255);
+ SetChannel(bitmap.get(), x, y, 0, x & 1 ? 255 : 0);
+ SetChannel(bitmap.get(), x, y, 1, y & 1 ? 255 : 0);
+ SetChannel(bitmap.get(), x, y, 2, (x + y) & 1 ? 255 : 0);
+ SetChannel(bitmap.get(), x, y, 3, 255);
break;
case 2: // Medium blocks
- SetChannel(&input_pixels, x, y, 0, 10 + x / 2 * 50);
- SetChannel(&input_pixels, x, y, 1, 10 + y / 3 * 50);
- SetChannel(&input_pixels, x, y, 2, (x + y) / 5 * 50 + 5);
- SetChannel(&input_pixels, x, y, 3, 255);
+ SetChannel(bitmap.get(), x, y, 0, 10 + x / 2 * 50);
+ SetChannel(bitmap.get(), x, y, 1, 10 + y / 3 * 50);
+ SetChannel(bitmap.get(), x, y, 2, (x + y) / 5 * 50 + 5);
+ SetChannel(bitmap.get(), x, y, 3, 255);
break;
}
}
}
+ return bitmap.Pass();
+ }
+ // Binds texture and framebuffer and loads the bitmap pixels into the texture.
+ void BindTextureAndFrameBuffer(WebGLId texture,
+ WebGLId framebuffer,
+ SkBitmap* bitmap,
+ int width,
+ int height) {
context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- context_->bindTexture(GL_TEXTURE_2D, src_texture);
+ context_->bindTexture(GL_TEXTURE_2D, texture);
context_->texImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
- xsize,
- ysize,
+ width,
+ height,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
- input_pixels.getPixels());
+ bitmap->getPixels());
+ }
+
+ // Create a test image, transform it using
+ // GLHelper::CropScaleReadbackAndCleanTexture and a reference implementation
+ // and compare the results.
+ void TestCropScaleReadbackAndCleanTexture(int xsize,
+ int ysize,
+ int scaled_xsize,
+ int scaled_ysize,
+ int test_pattern,
+ SkColorType out_color_type,
+ bool swizzle,
+ size_t quality_index) {
+ DCHECK(out_color_type == kAlpha_8_SkColorType ||
+ out_color_type == kRGBA_8888_SkColorType ||
+ out_color_type == kBGRA_8888_SkColorType);
+ WebGLId src_texture = context_->createTexture();
+ WebGLId framebuffer = context_->createFramebuffer();
+ scoped_ptr<SkBitmap> input_pixels =
+ CreateTestBitmap(xsize, ysize, test_pattern).Pass();
+ BindTextureAndFrameBuffer(
+ src_texture, framebuffer, input_pixels.get(), xsize, ysize);
+
+ std::string message = base::StringPrintf(
+ "input size: %dx%d "
+ "output size: %dx%d "
+ "pattern: %d , quality: %s, "
+ "out_color_type: %d",
+ xsize,
+ ysize,
+ scaled_xsize,
+ scaled_ysize,
+ test_pattern,
+ kQualityNames[quality_index],
+ out_color_type);
+
+ // Transform the bitmap using GLHelper::CropScaleReadbackAndCleanTexture.
+ SkBitmap output_pixels;
+ output_pixels.allocPixels(SkImageInfo::Make(
+ scaled_xsize, scaled_ysize, out_color_type, kPremul_SkAlphaType));
+ base::RunLoop run_loop;
+ gfx::Size encoded_texture_size;
+ helper_->CropScaleReadbackAndCleanTexture(
+ src_texture,
+ gfx::Size(xsize, ysize),
+ gfx::Rect(xsize, ysize),
+ gfx::Size(scaled_xsize, scaled_ysize),
+ static_cast<unsigned char*>(output_pixels.getPixels()),
+ out_color_type,
+ base::Bind(&callcallback, run_loop.QuitClosure()),
+ kQualities[quality_index]);
+ run_loop.Run();
+ // CropScaleReadbackAndCleanTexture flips the pixels. Flip them back.
+ FlipSKBitmap(&output_pixels);
+
+ // If the bitmap shouldn't have changed - compare against input.
+ if (xsize == scaled_xsize && ysize == scaled_ysize &&
+ out_color_type != kAlpha_8_SkColorType) {
+ const std::vector<GLHelperScaling::ScalerStage> dummy_stages;
+ Compare(input_pixels.get(),
+ &output_pixels,
+ 0,
+ NULL,
+ dummy_stages,
+ message + " comparing against input");
+ return;
+ }
+
+ // Now transform the bitmap using the reference implementation.
+ SkBitmap scaled_pixels;
+ scaled_pixels.allocPixels(SkImageInfo::Make(scaled_xsize,
+ scaled_ysize,
+ kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType));
+ SkBitmap truth_pixels;
+ // Step 1: Scale
+ ScaleSlowRecursive(
+ input_pixels.get(), &scaled_pixels, kQualities[quality_index]);
+ // Step 2: Encode to grayscale if needed.
+ if (out_color_type == kAlpha_8_SkColorType) {
+ truth_pixels.allocPixels(SkImageInfo::Make(
+ scaled_xsize, scaled_ysize, out_color_type, kPremul_SkAlphaType));
+ EncodeToGrayscaleSlow(&scaled_pixels, &truth_pixels);
+ } else {
+ truth_pixels = scaled_pixels;
+ }
+
+ // Now compare the results.
+ SkAutoLockPixels lock_input(truth_pixels);
+ const std::vector<GLHelperScaling::ScalerStage> dummy_stages;
+ Compare(&truth_pixels,
+ &output_pixels,
+ 2,
+ input_pixels.get(),
+ dummy_stages,
+ message + " comparing against transformed/scaled");
+
+ context_->deleteTexture(src_texture);
+ context_->deleteFramebuffer(framebuffer);
+ }
+
+ // Scaling test: Create a test image, scale it using GLHelperScaling
+ // and a reference implementation and compare the results.
+ void TestScale(int xsize,
+ int ysize,
+ int scaled_xsize,
+ int scaled_ysize,
+ int test_pattern,
+ size_t quality_index,
+ bool flip) {
+ WebGLId src_texture = context_->createTexture();
+ WebGLId framebuffer = context_->createFramebuffer();
+ scoped_ptr<SkBitmap> input_pixels =
+ CreateTestBitmap(xsize, ysize, test_pattern).Pass();
+ BindTextureAndFrameBuffer(
+ src_texture, framebuffer, input_pixels.get(), xsize, ysize);
std::string message = base::StringPrintf(
"input size: %dx%d "
@@ -631,59 +836,67 @@ class GLHelperTest : public testing::Test {
scaled_xsize,
scaled_ysize,
test_pattern,
- kQualityNames[quality]);
+ kQualityNames[quality_index]);
std::vector<GLHelperScaling::ScalerStage> stages;
- helper_scaling_->ComputeScalerStages(kQualities[quality],
+ helper_scaling_->ComputeScalerStages(kQualities[quality_index],
gfx::Size(xsize, ysize),
gfx::Rect(0, 0, xsize, ysize),
gfx::Size(scaled_xsize, scaled_ysize),
flip,
false,
&stages);
- ValidateScalerStages(kQualities[quality], stages, message);
+ ValidateScalerStages(kQualities[quality_index],
+ stages,
+ gfx::Size(scaled_xsize, scaled_ysize),
+ message);
WebGLId dst_texture =
helper_->CopyAndScaleTexture(src_texture,
gfx::Size(xsize, ysize),
gfx::Size(scaled_xsize, scaled_ysize),
flip,
- kQualities[quality]);
+ kQualities[quality_index]);
SkBitmap output_pixels;
- output_pixels.setConfig(
- SkBitmap::kARGB_8888_Config, scaled_xsize, scaled_ysize);
- output_pixels.allocPixels();
- SkAutoLockPixels output_lock(output_pixels);
+ output_pixels.allocPixels(SkImageInfo::Make(scaled_xsize,
+ scaled_ysize,
+ kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType));
helper_->ReadbackTextureSync(
dst_texture,
gfx::Rect(0, 0, scaled_xsize, scaled_ysize),
static_cast<unsigned char*>(output_pixels.getPixels()),
- SkBitmap::kARGB_8888_Config);
+ kRGBA_8888_SkColorType);
if (flip) {
// Flip the pixels back.
FlipSKBitmap(&output_pixels);
}
+
+ // If the bitmap shouldn't have changed - compare against input.
if (xsize == scaled_xsize && ysize == scaled_ysize) {
- Compare(&input_pixels,
+ Compare(input_pixels.get(),
&output_pixels,
- 2,
+ 0,
NULL,
stages,
message + " comparing against input");
+ return;
}
- SkBitmap truth_pixels;
- truth_pixels.setConfig(
- SkBitmap::kARGB_8888_Config, scaled_xsize, scaled_ysize);
- truth_pixels.allocPixels();
- SkAutoLockPixels truth_lock(truth_pixels);
- ScaleSlowRecursive(&input_pixels, &truth_pixels, kQualities[quality]);
+ // Now scale the bitmap using the reference implementation.
+ SkBitmap truth_pixels;
+ truth_pixels.allocPixels(SkImageInfo::Make(scaled_xsize,
+ scaled_ysize,
+ kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType));
+ ScaleSlowRecursive(
+ input_pixels.get(), &truth_pixels, kQualities[quality_index]);
Compare(&truth_pixels,
&output_pixels,
2,
- &input_pixels,
+ input_pixels.get(),
stages,
message + " comparing against scaled");
@@ -709,6 +922,7 @@ class GLHelperTest : public testing::Test {
&stages);
ValidateScalerStages(kQualities[quality],
stages,
+ gfx::Size(dst_xsize, dst_ysize),
base::StringPrintf(
"input size: %dx%d "
"output size: %dx%d "
@@ -736,7 +950,10 @@ class GLHelperTest : public testing::Test {
false,
false,
&stages);
- ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD, stages, "");
+ ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD,
+ stages,
+ gfx::Size(dst_xsize, dst_ysize),
+ "");
EXPECT_EQ(PrintStages(stages), description);
}
@@ -855,9 +1072,10 @@ class GLHelperTest : public testing::Test {
for (int x = 0; x < w; ++x) {
bool on_grid = (y_on_grid || ((x % grid_pitch) < grid_width));
- if (bmp.config() == SkBitmap::kARGB_8888_Config) {
+ if (bmp.colorType() == kRGBA_8888_SkColorType ||
+ bmp.colorType() == kBGRA_8888_SkColorType) {
*bmp.getAddr32(x, y) = (on_grid ? grid_color : background_color);
- } else if (bmp.config() == SkBitmap::kRGB_565_Config) {
+ } else if (bmp.colorType() == kRGB_565_SkColorType) {
*bmp.getAddr16(x, y) = (on_grid ? grid_color : background_color);
}
}
@@ -879,9 +1097,10 @@ class GLHelperTest : public testing::Test {
bool x_bit = (((x / rect_w) & 0x1) == 0);
bool use_color2 = (x_bit != y_bit); // xor
- if (bmp.config() == SkBitmap::kARGB_8888_Config) {
+ if (bmp.colorType() == kRGBA_8888_SkColorType ||
+ bmp.colorType() == kBGRA_8888_SkColorType) {
*bmp.getAddr32(x, y) = (use_color2 ? color2 : color1);
- } else if (bmp.config() == SkBitmap::kRGB_565_Config) {
+ } else if (bmp.colorType() == kRGB_565_SkColorType) {
*bmp.getAddr16(x, y) = (use_color2 ? color2 : color1);
}
}
@@ -890,15 +1109,16 @@ class GLHelperTest : public testing::Test {
bool ColorComponentsClose(SkColor component1,
SkColor component2,
- SkBitmap::Config config) {
+ SkColorType color_type) {
int c1 = static_cast<int>(component1);
int c2 = static_cast<int>(component2);
bool result = false;
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
+ switch (color_type) {
+ case kRGBA_8888_SkColorType:
+ case kBGRA_8888_SkColorType:
result = (std::abs(c1 - c2) == 0);
break;
- case SkBitmap::kRGB_565_Config:
+ case kRGB_565_SkColorType:
result = (std::abs(c1 - c2) <= 7);
break;
default:
@@ -907,16 +1127,16 @@ class GLHelperTest : public testing::Test {
return result;
}
- bool ColorsClose(SkColor color1, SkColor color2, SkBitmap::Config config) {
+ bool ColorsClose(SkColor color1, SkColor color2, SkColorType color_type) {
bool red = ColorComponentsClose(SkColorGetR(color1),
- SkColorGetR(color2), config);
+ SkColorGetR(color2), color_type);
bool green = ColorComponentsClose(SkColorGetG(color1),
- SkColorGetG(color2), config);
+ SkColorGetG(color2), color_type);
bool blue = ColorComponentsClose(SkColorGetB(color1),
- SkColorGetB(color2), config);
+ SkColorGetB(color2), color_type);
bool alpha = ColorComponentsClose(SkColorGetA(color1),
- SkColorGetA(color2), config);
- if (config == SkBitmap::kRGB_565_Config) {
+ SkColorGetA(color2), color_type);
+ if (color_type == kRGB_565_SkColorType) {
return red && blue && green;
}
return red && blue && green && alpha;
@@ -930,7 +1150,7 @@ class GLHelperTest : public testing::Test {
LOG(ERROR) << "Bitmap geometry check failure";
return false;
}
- if (bmp1.config() != bmp2.config())
+ if (bmp1.colorType() != bmp2.colorType())
return false;
SkAutoLockPixels lock1(bmp1);
@@ -943,7 +1163,7 @@ class GLHelperTest : public testing::Test {
for (int x = 0; x < bmp1.width(); ++x) {
if (!ColorsClose(bmp1.getColor(x,y),
bmp2.getColor(x,y),
- bmp1.config())) {
+ bmp1.colorType())) {
LOG(ERROR) << "Bitmap color comparision failure";
return false;
}
@@ -953,13 +1173,25 @@ class GLHelperTest : public testing::Test {
}
void BindAndAttachTextureWithPixels(GLuint src_texture,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
const gfx::Size& src_size,
const SkBitmap& input_pixels) {
context_->bindTexture(GL_TEXTURE_2D, src_texture);
- GLenum format = (bitmap_config == SkBitmap::kRGB_565_Config) ?
- GL_RGB : GL_RGBA;
- GLenum type = (bitmap_config == SkBitmap::kRGB_565_Config) ?
+ GLenum format = 0;
+ switch (color_type) {
+ case kBGRA_8888_SkColorType:
+ format = GL_BGRA_EXT;
+ break;
+ case kRGBA_8888_SkColorType:
+ format = GL_RGBA;
+ break;
+ case kRGB_565_SkColorType:
+ format = GL_RGB;
+ break;
+ default:
+ NOTREACHED();
+ }
+ GLenum type = (color_type == kRGB_565_SkColorType) ?
GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE;
context_->texImage2D(GL_TEXTURE_2D,
0,
@@ -975,14 +1207,14 @@ class GLHelperTest : public testing::Test {
void ReadBackTexture(GLuint src_texture,
const gfx::Size& src_size,
unsigned char* pixels,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
bool async) {
if (async) {
base::RunLoop run_loop;
helper_->ReadbackTextureAsync(src_texture,
src_size,
pixels,
- bitmap_config,
+ color_type,
base::Bind(&callcallback,
run_loop.QuitClosure()));
run_loop.Run();
@@ -990,41 +1222,39 @@ class GLHelperTest : public testing::Test {
helper_->ReadbackTextureSync(src_texture,
gfx::Rect(src_size),
pixels,
- bitmap_config);
+ color_type);
}
}
-
// Test basic format readback.
bool TestTextureFormatReadback(const gfx::Size& src_size,
- SkBitmap::Config bitmap_config,
+ SkColorType color_type,
bool async) {
- if (!helper_->IsReadbackConfigSupported(bitmap_config)) {
- LOG(INFO) << "Skipping test format not supported" << bitmap_config;
+ SkImageInfo info =
+ SkImageInfo::Make(src_size.width(),
+ src_size.height(),
+ color_type,
+ kPremul_SkAlphaType);
+ if (!helper_->IsReadbackConfigSupported(color_type)) {
+ LOG(INFO) << "Skipping test format not supported" << color_type;
return true;
}
WebGLId src_texture = context_->createTexture();
SkBitmap input_pixels;
- input_pixels.setConfig(bitmap_config, src_size.width(),
- src_size.height());
- input_pixels.allocPixels();
- SkAutoLockPixels lock1(input_pixels);
+ input_pixels.allocPixels(info);
// Test Pattern-1, Fill with Plain color pattern.
// Erase the input bitmap with red color.
input_pixels.eraseColor(SK_ColorRED);
BindAndAttachTextureWithPixels(src_texture,
- bitmap_config,
+ color_type,
src_size,
input_pixels);
SkBitmap output_pixels;
- output_pixels.setConfig(bitmap_config, src_size.width(),
- src_size.height());
- output_pixels.allocPixels();
- SkAutoLockPixels lock2(output_pixels);
+ output_pixels.allocPixels(info);
// Initialize the output bitmap with Green color.
// When the readback is over output bitmap should have the red color.
output_pixels.eraseColor(SK_ColorGREEN);
uint8* pixels = static_cast<uint8*>(output_pixels.getPixels());
- ReadBackTexture(src_texture, src_size, pixels, bitmap_config, async);
+ ReadBackTexture(src_texture, src_size, pixels, color_type, async);
bool result = IsEqual(input_pixels, output_pixels);
if (!result) {
LOG(ERROR) << "Bitmap comparision failure Pattern-1";
@@ -1038,10 +1268,10 @@ class GLHelperTest : public testing::Test {
src_grid_pitch, src_grid_width,
input_pixels);
BindAndAttachTextureWithPixels(src_texture,
- bitmap_config,
+ color_type,
src_size,
input_pixels);
- ReadBackTexture(src_texture, src_size, pixels, bitmap_config, async);
+ ReadBackTexture(src_texture, src_size, pixels, color_type, async);
result = IsEqual(input_pixels, output_pixels);
if (!result) {
LOG(ERROR) << "Bitmap comparision failure Pattern-2";
@@ -1053,10 +1283,10 @@ class GLHelperTest : public testing::Test {
color1,
color2, rect_w, rect_h, input_pixels);
BindAndAttachTextureWithPixels(src_texture,
- bitmap_config,
+ color_type,
src_size,
input_pixels);
- ReadBackTexture(src_texture, src_size, pixels, bitmap_config, async);
+ ReadBackTexture(src_texture, src_size, pixels, color_type, async);
result = IsEqual(input_pixels, output_pixels);
if (!result) {
LOG(ERROR) << "Bitmap comparision failure Pattern-3";
@@ -1084,9 +1314,7 @@ class GLHelperTest : public testing::Test {
content::GLHelper::ScalerQuality quality) {
WebGLId src_texture = context_->createTexture();
SkBitmap input_pixels;
- input_pixels.setConfig(SkBitmap::kARGB_8888_Config, xsize, ysize);
- input_pixels.allocPixels();
- SkAutoLockPixels lock(input_pixels);
+ input_pixels.allocN32Pixels(xsize, ysize);
for (int x = 0; x < xsize; ++x) {
for (int y = 0; y < ysize; ++y) {
@@ -1190,26 +1418,38 @@ class GLHelperTest : public testing::Test {
memset(U, 0x80, u_stride * output_ysize / 2);
memset(V, 0x80, v_stride * output_ysize / 2);
+ const float kRGBtoYColorWeights[] = {0.257f, 0.504f, 0.098f, 0.0625f};
+ const float kRGBtoUColorWeights[] = {-0.148f, -0.291f, 0.439f, 0.5f};
+ const float kRGBtoVColorWeights[] = {0.439f, -0.368f, -0.071f, 0.5f};
+
for (int y = 0; y < ysize; y++) {
for (int x = 0; x < xsize; x++) {
Y[(y + ymargin) * y_stride + x + xmargin] = float_to_byte(
- ChannelAsFloat(&input_pixels, x, y, 0) * 0.257 +
- ChannelAsFloat(&input_pixels, x, y, 1) * 0.504 +
- ChannelAsFloat(&input_pixels, x, y, 2) * 0.098 + 0.0625);
+ ChannelAsFloat(&input_pixels, x, y, 0) * kRGBtoYColorWeights[0] +
+ ChannelAsFloat(&input_pixels, x, y, 1) * kRGBtoYColorWeights[1] +
+ ChannelAsFloat(&input_pixels, x, y, 2) * kRGBtoYColorWeights[2] +
+ kRGBtoYColorWeights[3]);
}
}
for (int y = 0; y < ysize / 2; y++) {
for (int x = 0; x < xsize / 2; x++) {
- U[(y + ymargin / 2) * u_stride + x + xmargin / 2] = float_to_byte(
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * -0.148 +
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.291 +
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * 0.439 + 0.5);
- V[(y + ymargin / 2) * v_stride + x + xmargin / 2] = float_to_byte(
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) * 0.439 +
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) * -0.368 +
- Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) * -0.071 +
- 0.5);
+ U[(y + ymargin / 2) * u_stride + x + xmargin / 2] =
+ float_to_byte(Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) *
+ kRGBtoUColorWeights[0] +
+ Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) *
+ kRGBtoUColorWeights[1] +
+ Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) *
+ kRGBtoUColorWeights[2] +
+ kRGBtoUColorWeights[3]);
+ V[(y + ymargin / 2) * v_stride + x + xmargin / 2] =
+ float_to_byte(Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 0) *
+ kRGBtoVColorWeights[0] +
+ Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 1) *
+ kRGBtoVColorWeights[1] +
+ Bilinear(&input_pixels, x * 2 + 1.0, y * 2 + 1.0, 2) *
+ kRGBtoVColorWeights[2] +
+ kRGBtoVColorWeights[3]);
}
}
@@ -1298,7 +1538,10 @@ class GLHelperTest : public testing::Test {
&stages);
EXPECT_EQ(x_ops_.size(), 0U);
EXPECT_EQ(y_ops_.size(), 0U);
- ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD, stages, "");
+ ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD,
+ stages,
+ gfx::Size(dst_xsize, dst_ysize),
+ "");
EXPECT_EQ(PrintStages(stages), description);
}
@@ -1321,7 +1564,7 @@ class GLHelperTest : public testing::Test {
// X scaled 1/2, Y scaled 1/2, one bilinear pass
x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 512));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 384));
- CheckPipeline2(1024, 768, 2000, 384, "1024x768 -> 512x384 bilinear\n");
+ CheckPipeline2(1024, 768, 512, 384, "1024x768 -> 512x384 bilinear\n");
// X scaled 1/2, Y scaled to 60%, one bilinear2 pass.
x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 50));
@@ -1333,7 +1576,7 @@ class GLHelperTest : public testing::Test {
x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120));
x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 50));
- CheckPipeline2(100, 100, 50, 60, "100x100 -> 60x50 bilinear2 X\n");
+ CheckPipeline2(100, 100, 60, 50, "100x100 -> 60x50 bilinear2 X\n");
// X scaled to 60%, Y scaled 60%, one bilinear2x2 pass.
x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120));
@@ -1428,8 +1671,8 @@ class GLHelperTest : public testing::Test {
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 1));
CheckPipeline2(100,
100,
- 30,
- 30,
+ 1,
+ 1,
"100x100 -> 100x32 bilinear4 Y\n"
"100x32 -> 100x4 bilinear4 Y\n"
"100x4 -> 64x1 bilinear2x2\n"
@@ -1449,10 +1692,19 @@ class GLHelperPixelTest : public GLHelperTest {
gfx::DisableNullDrawGLBindings enable_pixel_output_;
};
-TEST_F(GLHelperTest, ARGBSyncReadbackTest) {
+TEST_F(GLHelperTest, RGBASyncReadbackTest) {
const int kTestSize = 64;
bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- SkBitmap::kARGB_8888_Config,
+ kRGBA_8888_SkColorType,
+ false);
+ EXPECT_EQ(result, true);
+}
+
+
+TEST_F(GLHelperTest, BGRASyncReadbackTest) {
+ const int kTestSize = 64;
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
+ kBGRA_8888_SkColorType,
false);
EXPECT_EQ(result, true);
}
@@ -1460,15 +1712,23 @@ TEST_F(GLHelperTest, ARGBSyncReadbackTest) {
TEST_F(GLHelperTest, RGB565SyncReadbackTest) {
const int kTestSize = 64;
bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- SkBitmap::kRGB_565_Config,
+ kRGB_565_SkColorType,
false);
EXPECT_EQ(result, true);
}
-TEST_F(GLHelperTest, ARGBASyncReadbackTest) {
+TEST_F(GLHelperTest, RGBAASyncReadbackTest) {
const int kTestSize = 64;
bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- SkBitmap::kARGB_8888_Config,
+ kRGBA_8888_SkColorType,
+ true);
+ EXPECT_EQ(result, true);
+}
+
+TEST_F(GLHelperTest, BGRAASyncReadbackTest) {
+ const int kTestSize = 64;
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
+ kBGRA_8888_SkColorType,
true);
EXPECT_EQ(result, true);
}
@@ -1476,7 +1736,7 @@ TEST_F(GLHelperTest, ARGBASyncReadbackTest) {
TEST_F(GLHelperTest, RGB565ASyncReadbackTest) {
const int kTestSize = 64;
bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- SkBitmap::kRGB_565_Config,
+ kRGB_565_SkColorType,
true);
EXPECT_EQ(result, true);
}
@@ -1563,7 +1823,7 @@ TEST_F(GLHelperPixelTest, YUVReadbackTest) {
TEST_F(GLHelperPixelTest, ScaleTest) {
int sizes[] = {3, 6, 16};
for (int flip = 0; flip <= 1; flip++) {
- for (size_t q = 0; q < arraysize(kQualities); q++) {
+ for (size_t q_index = 0; q_index < arraysize(kQualities); q_index++) {
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
for (int dst_x = 0; dst_x < 3; dst_x++) {
@@ -1574,7 +1834,7 @@ TEST_F(GLHelperPixelTest, ScaleTest) {
sizes[dst_x],
sizes[dst_y],
pattern,
- q,
+ q_index,
flip == 1);
if (HasFailure()) {
return;
@@ -1588,6 +1848,40 @@ TEST_F(GLHelperPixelTest, ScaleTest) {
}
}
+// Per pixel tests, all sizes are small so that we can print
+// out the generated bitmaps.
+TEST_F(GLHelperPixelTest, CropScaleReadbackAndCleanTextureTest) {
+ const int kSizes[] = {3, 6, 16};
+ const SkColorType kColorTypes[] = {
+ kAlpha_8_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType};
+ for (size_t color_type = 0; color_type < arraysize(kColorTypes);
+ color_type++) {
+ // Test BEST and FAST qualities, skip GOOD
+ for (size_t q_index = 0; q_index < arraysize(kQualities); q_index += 2) {
+ for (size_t x = 0; x < arraysize(kSizes); x++) {
+ for (size_t y = 0; y < arraysize(kSizes); y++) {
+ for (size_t dst_x = 0; dst_x < arraysize(kSizes); dst_x++) {
+ for (size_t dst_y = 0; dst_y < arraysize(kSizes); dst_y++) {
+ for (int pattern = 0; pattern < 3; pattern++) {
+ TestCropScaleReadbackAndCleanTexture(kSizes[x],
+ kSizes[y],
+ kSizes[dst_x],
+ kSizes[dst_y],
+ pattern,
+ kColorTypes[color_type],
+ false,
+ q_index);
+ if (HasFailure())
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
// Validate that all scaling generates valid pipelines.
TEST_F(GLHelperTest, ValidateScalerPipelines) {
int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096};
@@ -1661,7 +1955,7 @@ TEST_F(GLHelperTest, CheckOptimizations) {
// These tests needs to run against a proper GL environment, so we
// need to set it up before we can run the tests.
int main(int argc, char** argv) {
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
base::TestSuite* suite = new content::ContentTestSuite(argc, argv);
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool pool;
diff --git a/chromium/content/common/gpu/client/gpu_channel_host.cc b/chromium/content/common/gpu/client/gpu_channel_host.cc
index 6312dee080c..77ef8752afc 100644
--- a/chromium/content/common/gpu/client/gpu_channel_host.cc
+++ b/chromium/content/common/gpu/client/gpu_channel_host.cc
@@ -35,36 +35,24 @@ scoped_refptr<GpuChannelHost> GpuChannelHost::Create(
GpuChannelHostFactory* factory,
const gpu::GPUInfo& gpu_info,
const IPC::ChannelHandle& channel_handle,
- base::WaitableEvent* shutdown_event) {
+ base::WaitableEvent* shutdown_event,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) {
DCHECK(factory->IsMainThread());
- scoped_refptr<GpuChannelHost> host = new GpuChannelHost(factory, gpu_info);
+ scoped_refptr<GpuChannelHost> host =
+ new GpuChannelHost(factory, gpu_info, gpu_memory_buffer_manager);
host->Connect(channel_handle, shutdown_event);
return host;
}
-// static
-bool GpuChannelHost::IsValidGpuMemoryBuffer(
- gfx::GpuMemoryBufferHandle handle) {
- switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER:
-#if defined(OS_MACOSX)
- case gfx::IO_SURFACE_BUFFER:
-#endif
-#if defined(OS_ANDROID)
- case gfx::SURFACE_TEXTURE_BUFFER:
-#endif
- return true;
- default:
- return false;
- }
-}
-
-GpuChannelHost::GpuChannelHost(GpuChannelHostFactory* factory,
- const gpu::GPUInfo& gpu_info)
+GpuChannelHost::GpuChannelHost(
+ GpuChannelHostFactory* factory,
+ const gpu::GPUInfo& gpu_info,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
: factory_(factory),
- gpu_info_(gpu_info) {
+ gpu_info_(gpu_info),
+ gpu_memory_buffer_manager_(gpu_memory_buffer_manager) {
next_transfer_buffer_id_.GetNext();
- next_gpu_memory_buffer_id_.GetNext();
+ next_image_id_.GetNext();
next_route_id_.GetNext();
}
@@ -293,30 +281,29 @@ int32 GpuChannelHost::ReserveTransferBufferId() {
}
gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess(
- gfx::GpuMemoryBufferHandle source_handle) {
+ const gfx::GpuMemoryBufferHandle& source_handle,
+ bool* requires_sync_point) {
switch (source_handle.type) {
case gfx::SHARED_MEMORY_BUFFER: {
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SHARED_MEMORY_BUFFER;
handle.handle = ShareToGpuProcess(source_handle.handle);
+ *requires_sync_point = false;
return handle;
}
-#if defined(OS_MACOSX)
case gfx::IO_SURFACE_BUFFER:
- return source_handle;
-#endif
-#if defined(OS_ANDROID)
case gfx::SURFACE_TEXTURE_BUFFER:
+ case gfx::OZONE_NATIVE_BUFFER:
+ *requires_sync_point = true;
return source_handle;
-#endif
default:
NOTREACHED();
return gfx::GpuMemoryBufferHandle();
}
}
-int32 GpuChannelHost::ReserveGpuMemoryBufferId() {
- return next_gpu_memory_buffer_id_.GetNext();
+int32 GpuChannelHost::ReserveImageId() {
+ return next_image_id_.GetNext();
}
int32 GpuChannelHost::GenerateRouteID() {
diff --git a/chromium/content/common/gpu/client/gpu_channel_host.h b/chromium/content/common/gpu/client/gpu_channel_host.h
index 07d5a612ef9..ebbbdac3f66 100644
--- a/chromium/content/common/gpu/client/gpu_channel_host.h
+++ b/chromium/content/common/gpu/client/gpu_channel_host.h
@@ -47,6 +47,10 @@ class VideoDecodeAccelerator;
class VideoEncodeAccelerator;
}
+namespace gpu {
+class GpuMemoryBufferManager;
+}
+
namespace content {
class CommandBufferProxyImpl;
class GpuChannelHost;
@@ -61,8 +65,6 @@ struct GpuListenerInfo {
class CONTENT_EXPORT GpuChannelHostFactory {
public:
- typedef base::Callback<void(const gfx::Size)> CreateImageCallback;
-
virtual ~GpuChannelHostFactory() {}
virtual bool IsMainThread() = 0;
@@ -73,16 +75,6 @@ class CONTENT_EXPORT GpuChannelHostFactory {
int32 surface_id,
const GPUCreateCommandBufferConfig& init_params,
int32 route_id) = 0;
- virtual void CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback) = 0;
- virtual void DeleteImage(int32 image_id, int32 sync_point) = 0;
- virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
- size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage) = 0;
};
// Encapsulates an IPC channel between the client and one GPU process.
@@ -97,11 +89,8 @@ class GpuChannelHost : public IPC::Sender,
GpuChannelHostFactory* factory,
const gpu::GPUInfo& gpu_info,
const IPC::ChannelHandle& channel_handle,
- base::WaitableEvent* shutdown_event);
-
- // Returns true if |handle| is a valid GpuMemoryBuffer handle that
- // can be shared to the GPU process.
- static bool IsValidGpuMemoryBuffer(gfx::GpuMemoryBufferHandle handle);
+ base::WaitableEvent* shutdown_event,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
bool IsLost() const {
DCHECK(channel_filter_.get());
@@ -112,7 +101,7 @@ class GpuChannelHost : public IPC::Sender,
const gpu::GPUInfo& gpu_info() const { return gpu_info_; }
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// Create and connect to a command buffer in the GPU process.
CommandBufferProxyImpl* CreateViewCommandBuffer(
@@ -147,6 +136,10 @@ class GpuChannelHost : public IPC::Sender,
GpuChannelHostFactory* factory() const { return factory_; }
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() const {
+ return gpu_memory_buffer_manager_;
+ }
+
// Returns a handle to the shared memory that can be sent via IPC to the
// GPU process. The caller is responsible for ensuring it is closed. Returns
// an invalid handle on failure.
@@ -160,10 +153,11 @@ class GpuChannelHost : public IPC::Sender,
// IPC to the GPU process. The caller is responsible for ensuring it is
// closed. Returns an invalid handle on failure.
gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuProcess(
- gfx::GpuMemoryBufferHandle source_handle);
+ const gfx::GpuMemoryBufferHandle& source_handle,
+ bool* requires_sync_point);
- // Reserve one unused gpu memory buffer ID.
- int32 ReserveGpuMemoryBufferId();
+ // Reserve one unused image ID.
+ int32 ReserveImageId();
// Generate a route ID guaranteed to be unique for this channel.
int32 GenerateRouteID();
@@ -171,8 +165,9 @@ class GpuChannelHost : public IPC::Sender,
private:
friend class base::RefCountedThreadSafe<GpuChannelHost>;
GpuChannelHost(GpuChannelHostFactory* factory,
- const gpu::GPUInfo& gpu_info);
- virtual ~GpuChannelHost();
+ const gpu::GPUInfo& gpu_info,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+ ~GpuChannelHost() override;
void Connect(const IPC::ChannelHandle& channel_handle,
base::WaitableEvent* shutdown_event);
@@ -192,8 +187,8 @@ class GpuChannelHost : public IPC::Sender,
// IPC::MessageFilter implementation
// (called on the IO thread):
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelError() override;
// The following methods can be called on any thread.
@@ -201,7 +196,7 @@ class GpuChannelHost : public IPC::Sender,
bool IsLost() const;
private:
- virtual ~MessageFilter();
+ ~MessageFilter() override;
// Threading notes: |listeners_| is only accessed on the IO thread. Every
// other field is protected by |lock_|.
@@ -218,7 +213,7 @@ class GpuChannelHost : public IPC::Sender,
// Threading notes: all fields are constant during the lifetime of |this|
// except:
// - |next_transfer_buffer_id_|, atomic type
- // - |next_gpu_memory_buffer_id_|, atomic type
+ // - |next_image_id_|, atomic type
// - |next_route_id_|, atomic type
// - |proxies_|, protected by |context_lock_|
GpuChannelHostFactory* const factory_;
@@ -228,14 +223,16 @@ class GpuChannelHost : public IPC::Sender,
scoped_ptr<IPC::SyncChannel> channel_;
scoped_refptr<MessageFilter> channel_filter_;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
+
// A filter for sending messages from thread other than the main thread.
scoped_refptr<IPC::SyncMessageFilter> sync_filter_;
// Transfer buffer IDs are allocated in sequence.
base::AtomicSequenceNumber next_transfer_buffer_id_;
- // Gpu memory buffer IDs are allocated in sequence.
- base::AtomicSequenceNumber next_gpu_memory_buffer_id_;
+ // Image IDs are allocated in sequence.
+ base::AtomicSequenceNumber next_image_id_;
// Route IDs are allocated in sequence.
base::AtomicSequenceNumber next_route_id_;
diff --git a/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc b/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
index 82882373497..3e134f5adf7 100644
--- a/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
+++ b/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
@@ -18,19 +18,17 @@ using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
class ContextTestBase : public testing::Test {
public:
- virtual void SetUp() {
+ void SetUp() override {
blink::WebGraphicsContext3D::Attributes attributes;
bool lose_context_when_out_of_memory = false;
typedef WebGraphicsContext3DInProcessCommandBufferImpl WGC3DIPCBI;
context_ = WGC3DIPCBI::CreateOffscreenContext(
attributes, lose_context_when_out_of_memory);
- context_->makeContextCurrent();
+ context_->InitializeOnCurrentThread();
context_support_ = context_->GetContextSupport();
}
- virtual void TearDown() {
- context_.reset(NULL);
- }
+ void TearDown() override { context_.reset(NULL); }
protected:
scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_;
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.cc
new file mode 100644
index 00000000000..ea7a321d1c5
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.cc
@@ -0,0 +1,27 @@
+// Copyright 2014 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 "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
+
+#include "base/logging.h"
+
+namespace content {
+namespace {
+GpuMemoryBufferFactoryHost* instance = NULL;
+}
+
+// static
+GpuMemoryBufferFactoryHost* GpuMemoryBufferFactoryHost::GetInstance() {
+ return instance;
+}
+
+GpuMemoryBufferFactoryHost::GpuMemoryBufferFactoryHost() {
+ DCHECK(instance == NULL);
+ instance = this;
+}
+
+GpuMemoryBufferFactoryHost::~GpuMemoryBufferFactoryHost() {
+ instance = NULL;
+}
+}
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.h b/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.h
index 6dfd58beaba..827308ed79e 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.h
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_factory_host.h
@@ -6,10 +6,11 @@
#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_FACTORY_HOST_H_
#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/gpu_memory_buffer.h"
namespace gfx {
class Size;
-struct GpuMemoryBufferHandle;
}
namespace content {
@@ -19,17 +20,24 @@ class CONTENT_EXPORT GpuMemoryBufferFactoryHost {
typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)>
CreateGpuMemoryBufferCallback;
+ static GpuMemoryBufferFactoryHost* GetInstance();
+
virtual void CreateGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id,
const CreateGpuMemoryBufferCallback& callback) = 0;
- virtual void DestroyGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
+ virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
int32 sync_point) = 0;
protected:
- virtual ~GpuMemoryBufferFactoryHost() {}
+ GpuMemoryBufferFactoryHost();
+ virtual ~GpuMemoryBufferFactoryHost();
};
} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
index b3cd98332b4..65edde33f12 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
@@ -8,48 +8,51 @@
namespace content {
-GpuMemoryBufferImpl::GpuMemoryBufferImpl(const gfx::Size& size,
- unsigned internalformat)
- : size_(size), internalformat_(internalformat), mapped_(false) {
- DCHECK(IsFormatValid(internalformat));
+GpuMemoryBufferImpl::GpuMemoryBufferImpl(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback)
+ : id_(id),
+ size_(size),
+ format_(format),
+ callback_(callback),
+ mapped_(false),
+ destruction_sync_point_(0) {
}
-GpuMemoryBufferImpl::~GpuMemoryBufferImpl() {}
-
-// static
-bool GpuMemoryBufferImpl::IsFormatValid(unsigned internalformat) {
- switch (internalformat) {
- case GL_BGRA8_EXT:
- case GL_RGBA8_OES:
- return true;
- default:
- return false;
- }
+GpuMemoryBufferImpl::~GpuMemoryBufferImpl() {
+ callback_.Run(destruction_sync_point_);
}
// static
-bool GpuMemoryBufferImpl::IsUsageValid(unsigned usage) {
- switch (usage) {
- case GL_IMAGE_MAP_CHROMIUM:
- case GL_IMAGE_SCANOUT_CHROMIUM:
- return true;
- default:
- return false;
- }
+GpuMemoryBufferImpl* GpuMemoryBufferImpl::FromClientBuffer(
+ ClientBuffer buffer) {
+ return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
}
// static
-size_t GpuMemoryBufferImpl::BytesPerPixel(unsigned internalformat) {
- switch (internalformat) {
- case GL_BGRA8_EXT:
- case GL_RGBA8_OES:
+size_t GpuMemoryBufferImpl::BytesPerPixel(Format format) {
+ switch (format) {
+ case RGBA_8888:
+ case RGBX_8888:
+ case BGRA_8888:
return 4;
- default:
- NOTREACHED();
- return 0;
}
+
+ NOTREACHED();
+ return 0;
}
-bool GpuMemoryBufferImpl::IsMapped() const { return mapped_; }
+gfx::GpuMemoryBuffer::Format GpuMemoryBufferImpl::GetFormat() const {
+ return format_;
+}
+
+bool GpuMemoryBufferImpl::IsMapped() const {
+ return mapped_;
+}
+
+ClientBuffer GpuMemoryBufferImpl::AsClientBuffer() {
+ return reinterpret_cast<ClientBuffer>(this);
+}
} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
index 95bddccff2e..52d5aef1095 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
@@ -15,52 +15,79 @@ namespace content {
// Provides common implementation of a GPU memory buffer.
class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
public:
+ typedef base::Callback<void(scoped_ptr<GpuMemoryBufferImpl> buffer)>
+ CreationCallback;
typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)>
AllocationCallback;
+ typedef base::Callback<void(uint32 sync_point)> DestructionCallback;
- virtual ~GpuMemoryBufferImpl();
+ ~GpuMemoryBufferImpl() override;
- // Creates a GPU memory buffer instance with |size| and |internalformat| for
- // |usage|.
- static scoped_ptr<GpuMemoryBufferImpl> Create(const gfx::Size& size,
- unsigned internalformat,
- unsigned usage);
+ // Creates a GPU memory buffer instance with |size| and |format| for |usage|
+ // by the current process and |client_id|.
+ static void Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ int client_id,
+ const CreationCallback& callback);
// Allocates a GPU memory buffer with |size| and |internalformat| for |usage|
- // by |child_process|. The |handle| returned can be used by the
- // |child_process| to create an instance of this class.
- static void AllocateForChildProcess(const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ // by |child_process| and |child_client_id|. The |handle| returned can be
+ // used by the |child_process| to create an instance of this class.
+ static void AllocateForChildProcess(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
base::ProcessHandle child_process,
+ int child_client_id,
const AllocationCallback& callback);
+ // Notify that GPU memory buffer has been deleted by |child_process|.
+ static void DeletedByChildProcess(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ uint32 sync_point);
+
// Creates an instance from the given |handle|. |size| and |internalformat|
- // should match what was used to allocate the |handle|.
+ // should match what was used to allocate the |handle|. |callback| is
+ // called when instance is deleted, which is not necessarily on the same
+ // thread as this function was called on and instance was created on.
static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
- gfx::GpuMemoryBufferHandle handle,
+ const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
- unsigned internalformat);
-
- // Returns true if |internalformat| is a format recognized by this base class.
- static bool IsFormatValid(unsigned internalformat);
+ Format format,
+ const DestructionCallback& callback);
- // Returns true if |usage| is recognized by this base class.
- static bool IsUsageValid(unsigned usage);
+ // Type-checking upcast routine. Returns an NULL on failure.
+ static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer);
// Returns the number of bytes per pixel that must be used by an
- // implementation when using |internalformat|.
- static size_t BytesPerPixel(unsigned internalformat);
+ // implementation when using |format|.
+ static size_t BytesPerPixel(Format format);
// Overridden from gfx::GpuMemoryBuffer:
- virtual bool IsMapped() const OVERRIDE;
+ bool IsMapped() const override;
+ Format GetFormat() const override;
+ ClientBuffer AsClientBuffer() override;
+
+ void set_destruction_sync_point(uint32 sync_point) {
+ destruction_sync_point_ = sync_point;
+ }
protected:
- GpuMemoryBufferImpl(const gfx::Size& size, unsigned internalformat);
+ GpuMemoryBufferImpl(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback);
+ const gfx::GpuMemoryBufferId id_;
const gfx::Size size_;
- const unsigned internalformat_;
+ const Format format_;
+ const DestructionCallback callback_;
bool mapped_;
+ uint32 destruction_sync_point_;
DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImpl);
};
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc
index 5af28171f90..9c0fdb368c6 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_android.cc
@@ -4,40 +4,54 @@
#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h"
namespace content {
// static
-scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->Initialize())
- return scoped_ptr<GpuMemoryBufferImpl>();
+void GpuMemoryBufferImpl::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ int client_id,
+ const CreationCallback& callback) {
+ if (GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(format,
+ usage)) {
+ GpuMemoryBufferImplSurfaceTexture::Create(
+ id, size, format, client_id, callback);
+ return;
+ }
- return buffer.PassAs<GpuMemoryBufferImpl>();
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::Create(id, size, format, callback);
+ return;
}
- return scoped_ptr<GpuMemoryBufferImpl>();
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
}
// static
void GpuMemoryBufferImpl::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ Format format,
+ Usage usage,
base::ProcessHandle child_process,
+ int child_client_id,
const AllocationCallback& callback) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- GpuMemoryBufferImplShm::AllocateSharedMemoryForChildProcess(
- size, internalformat, child_process, callback);
+ if (GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(format,
+ usage)) {
+ GpuMemoryBufferImplSurfaceTexture::AllocateForChildProcess(
+ id, size, format, child_client_id, callback);
+ return;
+ }
+
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ id, size, format, child_process, callback);
return;
}
@@ -45,27 +59,38 @@ void GpuMemoryBufferImpl::AllocateForChildProcess(
}
// static
+void GpuMemoryBufferImpl::DeletedByChildProcess(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ uint32 sync_point) {
+ switch (type) {
+ case gfx::SHARED_MEMORY_BUFFER:
+ break;
+ case gfx::SURFACE_TEXTURE_BUFFER:
+ GpuMemoryBufferImplSurfaceTexture::DeletedByChildProcess(
+ id, child_client_id, sync_point);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+// static
scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle(
- gfx::GpuMemoryBufferHandle handle,
+ const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
- unsigned internalformat) {
+ Format format,
+ const DestructionCallback& callback) {
switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER: {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->InitializeFromHandle(handle))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
- }
- case gfx::SURFACE_TEXTURE_BUFFER: {
- scoped_ptr<GpuMemoryBufferImplSurfaceTexture> buffer(
- new GpuMemoryBufferImplSurfaceTexture(size, internalformat));
- if (!buffer->InitializeFromHandle(handle))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
- }
+ case gfx::SHARED_MEMORY_BUFFER:
+ return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ handle, size, format, callback);
+ case gfx::SURFACE_TEXTURE_BUFFER:
+ return GpuMemoryBufferImplSurfaceTexture::CreateFromHandle(
+ handle, size, format, callback);
default:
return scoped_ptr<GpuMemoryBufferImpl>();
}
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
index 06cb7ed9bdc..088795c974a 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
@@ -4,66 +4,167 @@
#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
+#include "base/bind.h"
#include "base/logging.h"
+#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
#include "ui/gl/gl_bindings.h"
namespace content {
+namespace {
+
+void GpuMemoryBufferDeleted(gfx::GpuMemoryBufferId id,
+ int client_id,
+ uint32 sync_point) {
+ GpuMemoryBufferFactoryHost::GetInstance()->DestroyGpuMemoryBuffer(
+ gfx::IO_SURFACE_BUFFER, id, client_id, sync_point);
+}
+
+void GpuMemoryBufferCreated(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id,
+ const GpuMemoryBufferImpl::CreationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ if (handle.is_null()) {
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
+ return;
+ }
+
+ DCHECK_EQ(gfx::IO_SURFACE_BUFFER, handle.type);
+ callback.Run(GpuMemoryBufferImplIOSurface::CreateFromHandle(
+ handle,
+ size,
+ format,
+ base::Bind(&GpuMemoryBufferDeleted, handle.id, client_id)));
+}
+
+void GpuMemoryBufferCreatedForChildProcess(
+ const GpuMemoryBufferImpl::AllocationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ DCHECK_IMPLIES(!handle.is_null(), gfx::IO_SURFACE_BUFFER == handle.type);
+
+ callback.Run(handle);
+}
+
+} // namespace
GpuMemoryBufferImplIOSurface::GpuMemoryBufferImplIOSurface(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback,
+ IOSurfaceRef io_surface)
+ : GpuMemoryBufferImpl(id, size, format, callback), io_surface_(io_surface) {
+}
+
+GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() {
+}
+
+// static
+void GpuMemoryBufferImplIOSurface::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int client_id,
+ const CreationCallback& callback) {
+ GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
+ gfx::IO_SURFACE_BUFFER,
+ id,
+ size,
+ format,
+ MAP,
+ client_id,
+ base::Bind(&GpuMemoryBufferCreated, size, format, client_id, callback));
+}
+
+// static
+void GpuMemoryBufferImplIOSurface::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat)
- : GpuMemoryBufferImpl(size, internalformat) {}
+ Format format,
+ int child_client_id,
+ const AllocationCallback& callback) {
+ GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
+ gfx::IO_SURFACE_BUFFER,
+ id,
+ size,
+ format,
+ MAP,
+ child_client_id,
+ base::Bind(&GpuMemoryBufferCreatedForChildProcess, callback));
+}
-GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() {}
+// static
+scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImplIOSurface::CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback) {
+ DCHECK(IsFormatSupported(format));
+
+ base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
+ IOSurfaceLookup(handle.io_surface_id));
+ if (!io_surface)
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return make_scoped_ptr<GpuMemoryBufferImpl>(new GpuMemoryBufferImplIOSurface(
+ handle.id, size, format, callback, io_surface.get()));
+}
// static
-bool GpuMemoryBufferImplIOSurface::IsFormatSupported(unsigned internalformat) {
- switch (internalformat) {
- case GL_BGRA8_EXT:
+void GpuMemoryBufferImplIOSurface::DeletedByChildProcess(
+ gfx::GpuMemoryBufferId id,
+ int child_client_id,
+ uint32_t sync_point) {
+ GpuMemoryBufferFactoryHost::GetInstance()->DestroyGpuMemoryBuffer(
+ gfx::IO_SURFACE_BUFFER, id, child_client_id, sync_point);
+}
+
+// static
+bool GpuMemoryBufferImplIOSurface::IsFormatSupported(Format format) {
+ switch (format) {
+ case BGRA_8888:
return true;
- default:
+ case RGBA_8888:
+ case RGBX_8888:
return false;
}
+
+ NOTREACHED();
+ return false;
}
// static
-bool GpuMemoryBufferImplIOSurface::IsUsageSupported(unsigned usage) {
+bool GpuMemoryBufferImplIOSurface::IsUsageSupported(Usage usage) {
switch (usage) {
- case GL_IMAGE_MAP_CHROMIUM:
+ case MAP:
return true;
- default:
+ case SCANOUT:
return false;
}
+
+ NOTREACHED();
+ return false;
}
// static
-bool GpuMemoryBufferImplIOSurface::IsConfigurationSupported(
- unsigned internalformat,
- unsigned usage) {
- return IsFormatSupported(internalformat) && IsUsageSupported(usage);
+bool GpuMemoryBufferImplIOSurface::IsConfigurationSupported(Format format,
+ Usage usage) {
+ return IsFormatSupported(format) && IsUsageSupported(usage);
}
// static
-uint32 GpuMemoryBufferImplIOSurface::PixelFormat(unsigned internalformat) {
- switch (internalformat) {
- case GL_BGRA8_EXT:
+uint32 GpuMemoryBufferImplIOSurface::PixelFormat(Format format) {
+ switch (format) {
+ case BGRA_8888:
return 'BGRA';
- default:
+ case RGBA_8888:
+ case RGBX_8888:
NOTREACHED();
return 0;
}
-}
-
-bool GpuMemoryBufferImplIOSurface::InitializeFromHandle(
- gfx::GpuMemoryBufferHandle handle) {
- DCHECK(IsFormatSupported(internalformat_));
- io_surface_.reset(IOSurfaceLookup(handle.io_surface_id));
- if (!io_surface_) {
- VLOG(1) << "IOSurface lookup failed";
- return false;
- }
- return true;
+ NOTREACHED();
+ return 0;
}
void* GpuMemoryBufferImplIOSurface::Map() {
@@ -86,6 +187,7 @@ uint32 GpuMemoryBufferImplIOSurface::GetStride() const {
gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const {
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::IO_SURFACE_BUFFER;
+ handle.id = id_;
handle.io_surface_id = IOSurfaceGetID(io_surface_);
return handle;
}
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
index 24bdcf7e3b2..4cd1903377a 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
@@ -15,23 +15,47 @@ namespace content {
// Implementation of GPU memory buffer based on IO surfaces.
class GpuMemoryBufferImplIOSurface : public GpuMemoryBufferImpl {
public:
- GpuMemoryBufferImplIOSurface(const gfx::Size& size, unsigned internalformat);
- virtual ~GpuMemoryBufferImplIOSurface();
+ static void Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int client_id,
+ const CreationCallback& callback);
- static bool IsFormatSupported(unsigned internalformat);
- static bool IsUsageSupported(unsigned usage);
- static bool IsConfigurationSupported(unsigned internalformat, unsigned usage);
- static uint32 PixelFormat(unsigned internalformat);
+ static void AllocateForChildProcess(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int child_client_id,
+ const AllocationCallback& callback);
- bool InitializeFromHandle(gfx::GpuMemoryBufferHandle handle);
+ static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback);
+
+ static void DeletedByChildProcess(gfx::GpuMemoryBufferId id,
+ int child_client_id,
+ uint32_t sync_point);
+
+ static bool IsFormatSupported(Format format);
+ static bool IsUsageSupported(Usage usage);
+ static bool IsConfigurationSupported(Format format, Usage usage);
+ static uint32 PixelFormat(Format format);
// Overridden from gfx::GpuMemoryBuffer:
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual uint32 GetStride() const OVERRIDE;
- virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE;
+ void* Map() override;
+ void Unmap() override;
+ uint32 GetStride() const override;
+ gfx::GpuMemoryBufferHandle GetHandle() const override;
private:
+ GpuMemoryBufferImplIOSurface(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback,
+ IOSurfaceRef io_surface);
+ ~GpuMemoryBufferImplIOSurface() override;
+
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplIOSurface);
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc
index d885f3f8676..3c144f37ccf 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_linux.cc
@@ -4,39 +4,39 @@
#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
namespace content {
// static
-scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->Initialize())
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
+void GpuMemoryBufferImpl::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ int client_id,
+ const CreationCallback& callback) {
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::Create(id, size, format, callback);
+ return;
}
- return scoped_ptr<GpuMemoryBufferImpl>();
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
}
// static
void GpuMemoryBufferImpl::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ Format format,
+ Usage usage,
base::ProcessHandle child_process,
+ int child_client_id,
const AllocationCallback& callback) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- GpuMemoryBufferImplShm::AllocateSharedMemoryForChildProcess(
- size, internalformat, child_process, callback);
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ id, size, format, child_process, callback);
return;
}
@@ -44,19 +44,24 @@ void GpuMemoryBufferImpl::AllocateForChildProcess(
}
// static
+void GpuMemoryBufferImpl::DeletedByChildProcess(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ uint32 sync_point) {
+}
+
+// static
scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle(
- gfx::GpuMemoryBufferHandle handle,
+ const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
- unsigned internalformat) {
+ Format format,
+ const DestructionCallback& callback) {
switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER: {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->InitializeFromHandle(handle))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
- }
+ case gfx::SHARED_MEMORY_BUFFER:
+ return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ handle, size, format, callback);
default:
return scoped_ptr<GpuMemoryBufferImpl>();
}
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc
index 0e77f468d22..c4e9a03fe77 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_mac.cc
@@ -5,39 +5,50 @@
#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
namespace content {
// static
-scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->Initialize())
- return scoped_ptr<GpuMemoryBufferImpl>();
+void GpuMemoryBufferImpl::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ int client_id,
+ const CreationCallback& callback) {
+ if (GpuMemoryBufferImplIOSurface::IsConfigurationSupported(format, usage)) {
+ GpuMemoryBufferImplIOSurface::Create(id, size, format, client_id, callback);
+ return;
+ }
- return buffer.PassAs<GpuMemoryBufferImpl>();
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::Create(id, size, format, callback);
+ return;
}
- return scoped_ptr<GpuMemoryBufferImpl>();
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
}
// static
void GpuMemoryBufferImpl::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ Format format,
+ Usage usage,
base::ProcessHandle child_process,
+ int child_client_id,
const AllocationCallback& callback) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- GpuMemoryBufferImplShm::AllocateSharedMemoryForChildProcess(
- size, internalformat, child_process, callback);
+ if (GpuMemoryBufferImplIOSurface::IsConfigurationSupported(format, usage)) {
+ GpuMemoryBufferImplIOSurface::AllocateForChildProcess(
+ id, size, format, child_client_id, callback);
+ return;
+ }
+
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ id, size, format, child_process, callback);
return;
}
@@ -45,27 +56,38 @@ void GpuMemoryBufferImpl::AllocateForChildProcess(
}
// static
+void GpuMemoryBufferImpl::DeletedByChildProcess(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ uint32 sync_point) {
+ switch (type) {
+ case gfx::SHARED_MEMORY_BUFFER:
+ break;
+ case gfx::IO_SURFACE_BUFFER:
+ GpuMemoryBufferImplIOSurface::DeletedByChildProcess(
+ id, child_client_id, sync_point);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+// static
scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle(
- gfx::GpuMemoryBufferHandle handle,
+ const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
- unsigned internalformat) {
+ Format format,
+ const DestructionCallback& callback) {
switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER: {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->InitializeFromHandle(handle))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
- }
- case gfx::IO_SURFACE_BUFFER: {
- scoped_ptr<GpuMemoryBufferImplIOSurface> buffer(
- new GpuMemoryBufferImplIOSurface(size, internalformat));
- if (!buffer->InitializeFromHandle(handle))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
- }
+ case gfx::SHARED_MEMORY_BUFFER:
+ return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ handle, size, format, callback);
+ case gfx::IO_SURFACE_BUFFER:
+ return GpuMemoryBufferImplIOSurface::CreateFromHandle(
+ handle, size, format, callback);
default:
return scoped_ptr<GpuMemoryBufferImpl>();
}
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc
new file mode 100644
index 00000000000..236d2bd5860
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone.cc
@@ -0,0 +1,99 @@
+// Copyright 2014 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 "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
+
+namespace content {
+
+// static
+void GpuMemoryBufferImpl::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ int client_id,
+ const CreationCallback& callback) {
+ if (GpuMemoryBufferImplOzoneNativeBuffer::IsConfigurationSupported(format,
+ usage)) {
+ GpuMemoryBufferImplOzoneNativeBuffer::Create(
+ id, size, format, client_id, callback);
+ return;
+ }
+
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::Create(id, size, format, callback);
+ return;
+ }
+
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
+}
+
+// static
+void GpuMemoryBufferImpl::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ const AllocationCallback& callback) {
+ if (GpuMemoryBufferImplOzoneNativeBuffer::IsConfigurationSupported(format,
+ usage)) {
+ GpuMemoryBufferImplOzoneNativeBuffer::AllocateForChildProcess(
+ id, size, format, child_client_id, callback);
+ return;
+ }
+
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ id, size, format, child_process, callback);
+ return;
+ }
+
+ callback.Run(gfx::GpuMemoryBufferHandle());
+}
+
+// static
+void GpuMemoryBufferImpl::DeletedByChildProcess(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ uint32_t sync_point) {
+ switch (type) {
+ case gfx::SHARED_MEMORY_BUFFER:
+ break;
+ case gfx::OZONE_NATIVE_BUFFER:
+ GpuMemoryBufferImplOzoneNativeBuffer::DeletedByChildProcess(
+ id, child_client_id, sync_point);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+// static
+scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback) {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER:
+ return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ handle, size, format, callback);
+ case gfx::OZONE_NATIVE_BUFFER:
+ return GpuMemoryBufferImplOzoneNativeBuffer::CreateFromHandle(
+ handle, size, format, callback);
+ default:
+ return scoped_ptr<GpuMemoryBufferImpl>();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc
new file mode 100644
index 00000000000..2fd143894b2
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc
@@ -0,0 +1,174 @@
+// Copyright 2014 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 "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h"
+
+#include "base/bind.h"
+#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace content {
+namespace {
+
+void GpuMemoryBufferDeleted(gfx::GpuMemoryBufferId id,
+ int client_id,
+ uint32 sync_point) {
+ GpuMemoryBufferFactoryHost::GetInstance()->DestroyGpuMemoryBuffer(
+ gfx::OZONE_NATIVE_BUFFER, id, client_id, sync_point);
+}
+
+void GpuMemoryBufferCreated(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id,
+ const GpuMemoryBufferImpl::CreationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ if (handle.is_null()) {
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
+ return;
+ }
+
+ DCHECK_EQ(gfx::OZONE_NATIVE_BUFFER, handle.type);
+ callback.Run(GpuMemoryBufferImplOzoneNativeBuffer::CreateFromHandle(
+ handle,
+ size,
+ format,
+ base::Bind(&GpuMemoryBufferDeleted, handle.id, client_id)));
+}
+
+void GpuMemoryBufferCreatedForChildProcess(
+ const GpuMemoryBufferImpl::AllocationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ DCHECK_IMPLIES(!handle.is_null(), gfx::OZONE_NATIVE_BUFFER == handle.type);
+
+ callback.Run(handle);
+}
+
+} // namespace
+
+GpuMemoryBufferImplOzoneNativeBuffer::GpuMemoryBufferImplOzoneNativeBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback)
+ : GpuMemoryBufferImpl(id, size, format, callback) {
+}
+
+GpuMemoryBufferImplOzoneNativeBuffer::~GpuMemoryBufferImplOzoneNativeBuffer() {
+}
+
+// static
+void GpuMemoryBufferImplOzoneNativeBuffer::Create(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int client_id,
+ const CreationCallback& callback) {
+ GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
+ gfx::OZONE_NATIVE_BUFFER,
+ id,
+ size,
+ format,
+ SCANOUT,
+ client_id,
+ base::Bind(&GpuMemoryBufferCreated, size, format, client_id, callback));
+}
+
+// static
+void GpuMemoryBufferImplOzoneNativeBuffer::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int child_client_id,
+ const AllocationCallback& callback) {
+ GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
+ gfx::OZONE_NATIVE_BUFFER,
+ id,
+ size,
+ format,
+ SCANOUT,
+ child_client_id,
+ base::Bind(&GpuMemoryBufferCreatedForChildProcess, callback));
+}
+
+// static
+scoped_ptr<GpuMemoryBufferImpl>
+GpuMemoryBufferImplOzoneNativeBuffer::CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback) {
+ DCHECK(IsFormatSupported(format));
+
+ return make_scoped_ptr<GpuMemoryBufferImpl>(
+ new GpuMemoryBufferImplOzoneNativeBuffer(
+ handle.id, size, format, callback));
+}
+
+// static
+void GpuMemoryBufferImplOzoneNativeBuffer::DeletedByChildProcess(
+ gfx::GpuMemoryBufferId id,
+ int child_client_id,
+ uint32_t sync_point) {
+ GpuMemoryBufferFactoryHost::GetInstance()->DestroyGpuMemoryBuffer(
+ gfx::OZONE_NATIVE_BUFFER, id, child_client_id, sync_point);
+}
+
+// static
+bool GpuMemoryBufferImplOzoneNativeBuffer::IsFormatSupported(Format format) {
+ switch (format) {
+ case RGBA_8888:
+ case RGBX_8888:
+ return true;
+ case BGRA_8888:
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// static
+bool GpuMemoryBufferImplOzoneNativeBuffer::IsUsageSupported(Usage usage) {
+ switch (usage) {
+ case MAP:
+ return false;
+ case SCANOUT:
+ return true;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// static
+bool GpuMemoryBufferImplOzoneNativeBuffer::IsConfigurationSupported(
+ Format format,
+ Usage usage) {
+ return IsFormatSupported(format) && IsUsageSupported(usage);
+}
+
+void* GpuMemoryBufferImplOzoneNativeBuffer::Map() {
+ NOTREACHED();
+ return NULL;
+}
+
+void GpuMemoryBufferImplOzoneNativeBuffer::Unmap() {
+ NOTREACHED();
+}
+
+uint32 GpuMemoryBufferImplOzoneNativeBuffer::GetStride() const {
+ NOTREACHED();
+ return 0;
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImplOzoneNativeBuffer::GetHandle()
+ const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::OZONE_NATIVE_BUFFER;
+ handle.id = id_;
+ return handle;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h
new file mode 100644
index 00000000000..2da30b4e3fc
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h
@@ -0,0 +1,59 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_H_
+#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_H_
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+namespace content {
+
+// Implementation of GPU memory buffer based on Ozone native buffers.
+class GpuMemoryBufferImplOzoneNativeBuffer : public GpuMemoryBufferImpl {
+ public:
+ static void Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int client_id,
+ const CreationCallback& callback);
+
+ static void AllocateForChildProcess(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int child_client_id,
+ const AllocationCallback& callback);
+
+ static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback);
+
+ static void DeletedByChildProcess(gfx::GpuMemoryBufferId id,
+ int child_client_id,
+ uint32_t sync_point);
+
+ static bool IsFormatSupported(Format format);
+ static bool IsUsageSupported(Usage usage);
+ static bool IsConfigurationSupported(Format format, Usage usage);
+
+ // Overridden from gfx::GpuMemoryBuffer:
+ void* Map() override;
+ void Unmap() override;
+ uint32 GetStride() const override;
+ gfx::GpuMemoryBufferHandle GetHandle() const override;
+
+ private:
+ GpuMemoryBufferImplOzoneNativeBuffer(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback);
+ ~GpuMemoryBufferImplOzoneNativeBuffer() override;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplOzoneNativeBuffer);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
new file mode 100644
index 00000000000..9a2ae220c3a
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
@@ -0,0 +1,165 @@
+// Copyright 2014 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 "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
+
+#include "base/bind.h"
+#include "base/numerics/safe_math.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace content {
+namespace {
+
+void Noop(uint32 sync_point) {
+}
+
+} // namespace
+
+GpuMemoryBufferImplSharedMemory::GpuMemoryBufferImplSharedMemory(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback,
+ scoped_ptr<base::SharedMemory> shared_memory)
+ : GpuMemoryBufferImpl(id, size, format, callback),
+ shared_memory_(shared_memory.Pass()) {
+}
+
+GpuMemoryBufferImplSharedMemory::~GpuMemoryBufferImplSharedMemory() {
+}
+
+// static
+void GpuMemoryBufferImplSharedMemory::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const CreationCallback& callback) {
+ DCHECK(IsLayoutSupported(size, format));
+
+ scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+ if (!shared_memory->CreateAnonymous(size.GetArea() * BytesPerPixel(format))) {
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
+ return;
+ }
+
+ callback.Run(
+ make_scoped_ptr<GpuMemoryBufferImpl>(new GpuMemoryBufferImplSharedMemory(
+ id, size, format, base::Bind(&Noop), shared_memory.Pass())));
+}
+
+// static
+void GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ base::ProcessHandle child_process,
+ const AllocationCallback& callback) {
+ DCHECK(IsLayoutSupported(size, format));
+
+ base::SharedMemory shared_memory;
+ if (!shared_memory.CreateAnonymous(size.GetArea() * BytesPerPixel(format))) {
+ callback.Run(gfx::GpuMemoryBufferHandle());
+ return;
+ }
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SHARED_MEMORY_BUFFER;
+ handle.id = id;
+ shared_memory.GiveToProcess(child_process, &handle.handle);
+ callback.Run(handle);
+}
+
+// static
+scoped_ptr<GpuMemoryBufferImpl>
+GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback) {
+ DCHECK(IsLayoutSupported(size, format));
+
+ if (!base::SharedMemory::IsHandleValid(handle.handle))
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ return make_scoped_ptr<GpuMemoryBufferImpl>(
+ new GpuMemoryBufferImplSharedMemory(
+ handle.id,
+ size,
+ format,
+ callback,
+ make_scoped_ptr(new base::SharedMemory(handle.handle, false))));
+}
+
+// static
+bool GpuMemoryBufferImplSharedMemory::IsFormatSupported(Format format) {
+ switch (format) {
+ case RGBA_8888:
+ case BGRA_8888:
+ return true;
+ case RGBX_8888:
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// static
+bool GpuMemoryBufferImplSharedMemory::IsUsageSupported(Usage usage) {
+ switch (usage) {
+ case MAP:
+ return true;
+ case SCANOUT:
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+// static
+bool GpuMemoryBufferImplSharedMemory::IsLayoutSupported(const gfx::Size& size,
+ Format format) {
+ if (!IsFormatSupported(format))
+ return false;
+
+ base::CheckedNumeric<int> buffer_size = size.width();
+ buffer_size *= size.height();
+ buffer_size *= BytesPerPixel(format);
+ return buffer_size.IsValid();
+}
+
+// static
+bool GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ const gfx::Size& size,
+ Format format,
+ Usage usage) {
+ return IsLayoutSupported(size, format) && IsUsageSupported(usage);
+}
+
+void* GpuMemoryBufferImplSharedMemory::Map() {
+ DCHECK(!mapped_);
+ if (!shared_memory_->Map(size_.GetArea() * BytesPerPixel(format_)))
+ return NULL;
+ mapped_ = true;
+ return shared_memory_->memory();
+}
+
+void GpuMemoryBufferImplSharedMemory::Unmap() {
+ DCHECK(mapped_);
+ shared_memory_->Unmap();
+ mapped_ = false;
+}
+
+uint32 GpuMemoryBufferImplSharedMemory::GetStride() const {
+ return size_.width() * BytesPerPixel(format_);
+}
+
+gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSharedMemory::GetHandle() const {
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SHARED_MEMORY_BUFFER;
+ handle.id = id_;
+ handle.handle = shared_memory_->handle();
+ return handle;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
new file mode 100644
index 00000000000..d84d031b871
--- /dev/null
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
@@ -0,0 +1,60 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHARED_MEMORY_H_
+#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHARED_MEMORY_H_
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+
+namespace content {
+
+// Implementation of GPU memory buffer based on shared memory.
+class GpuMemoryBufferImplSharedMemory : public GpuMemoryBufferImpl {
+ public:
+ static void Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const CreationCallback& callback);
+
+ static void AllocateForChildProcess(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ base::ProcessHandle child_process,
+ const AllocationCallback& callback);
+
+ static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback);
+
+ static bool IsFormatSupported(Format format);
+ static bool IsUsageSupported(Usage usage);
+ static bool IsLayoutSupported(const gfx::Size& size, Format format);
+ static bool IsConfigurationSupported(const gfx::Size& size,
+ Format format,
+ Usage usage);
+
+ // Overridden from gfx::GpuMemoryBuffer:
+ void* Map() override;
+ void Unmap() override;
+ uint32 GetStride() const override;
+ gfx::GpuMemoryBufferHandle GetHandle() const override;
+
+ private:
+ GpuMemoryBufferImplSharedMemory(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback,
+ scoped_ptr<base::SharedMemory> shared_memory);
+ ~GpuMemoryBufferImplSharedMemory() override;
+
+ scoped_ptr<base::SharedMemory> shared_memory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplSharedMemory);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHARED_MEMORY_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc
deleted file mode 100644
index 84209314206..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2013 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 "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
-
-#include "base/numerics/safe_math.h"
-#include "ui/gl/gl_bindings.h"
-
-namespace content {
-
-GpuMemoryBufferImplShm::GpuMemoryBufferImplShm(const gfx::Size& size,
- unsigned internalformat)
- : GpuMemoryBufferImpl(size, internalformat) {}
-
-GpuMemoryBufferImplShm::~GpuMemoryBufferImplShm() {}
-
-// static
-void GpuMemoryBufferImplShm::AllocateSharedMemoryForChildProcess(
- const gfx::Size& size,
- unsigned internalformat,
- base::ProcessHandle child_process,
- const AllocationCallback& callback) {
- DCHECK(IsLayoutSupported(size, internalformat));
- gfx::GpuMemoryBufferHandle handle;
- base::SharedMemory shared_memory;
- if (!shared_memory.CreateAnonymous(size.GetArea() *
- BytesPerPixel(internalformat))) {
- handle.type = gfx::EMPTY_BUFFER;
- return;
- }
- handle.type = gfx::SHARED_MEMORY_BUFFER;
- shared_memory.GiveToProcess(child_process, &handle.handle);
- callback.Run(handle);
-}
-
-// static
-bool GpuMemoryBufferImplShm::IsLayoutSupported(const gfx::Size& size,
- unsigned internalformat) {
- base::CheckedNumeric<int> buffer_size = size.width();
- buffer_size *= size.height();
- buffer_size *= BytesPerPixel(internalformat);
- return buffer_size.IsValid();
-}
-
-// static
-bool GpuMemoryBufferImplShm::IsUsageSupported(unsigned usage) {
- switch (usage) {
- case GL_IMAGE_MAP_CHROMIUM:
- return true;
- default:
- return false;
- }
-}
-
-// static
-bool GpuMemoryBufferImplShm::IsConfigurationSupported(const gfx::Size& size,
- unsigned internalformat,
- unsigned usage) {
- return IsLayoutSupported(size, internalformat) && IsUsageSupported(usage);
-}
-
-bool GpuMemoryBufferImplShm::Initialize() {
- DCHECK(IsLayoutSupported(size_, internalformat_));
- scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
- if (!shared_memory->CreateAnonymous(size_.GetArea() *
- BytesPerPixel(internalformat_)))
- return false;
- shared_memory_ = shared_memory.Pass();
- DCHECK(!shared_memory_->memory());
- return true;
-}
-
-bool GpuMemoryBufferImplShm::InitializeFromHandle(
- gfx::GpuMemoryBufferHandle handle) {
- DCHECK(IsLayoutSupported(size_, internalformat_));
- if (!base::SharedMemory::IsHandleValid(handle.handle))
- return false;
- shared_memory_.reset(new base::SharedMemory(handle.handle, false));
- DCHECK(!shared_memory_->memory());
- return true;
-}
-
-void* GpuMemoryBufferImplShm::Map() {
- DCHECK(!mapped_);
- if (!shared_memory_->Map(size_.GetArea() * BytesPerPixel(internalformat_)))
- return NULL;
- mapped_ = true;
- return shared_memory_->memory();
-}
-
-void GpuMemoryBufferImplShm::Unmap() {
- DCHECK(mapped_);
- shared_memory_->Unmap();
- mapped_ = false;
-}
-
-uint32 GpuMemoryBufferImplShm::GetStride() const {
- return size_.width() * BytesPerPixel(internalformat_);
-}
-
-gfx::GpuMemoryBufferHandle GpuMemoryBufferImplShm::GetHandle() const {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SHARED_MEMORY_BUFFER;
- handle.handle = shared_memory_->handle();
- return handle;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h
deleted file mode 100644
index 2ba552c50a2..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shm.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 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 CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-
-namespace content {
-
-// Implementation of GPU memory buffer based on shared memory.
-class GpuMemoryBufferImplShm : public GpuMemoryBufferImpl {
- public:
- GpuMemoryBufferImplShm(const gfx::Size& size, unsigned internalformat);
- virtual ~GpuMemoryBufferImplShm();
-
- // Allocates a shared memory backed GPU memory buffer with |size| and
- // |internalformat| for use by |child_process|.
- static void AllocateSharedMemoryForChildProcess(
- const gfx::Size& size,
- unsigned internalformat,
- base::ProcessHandle child_process,
- const AllocationCallback& callback);
-
- static bool IsLayoutSupported(const gfx::Size& size, unsigned internalformat);
- static bool IsUsageSupported(unsigned usage);
- static bool IsConfigurationSupported(const gfx::Size& size,
- unsigned internalformat,
- unsigned usage);
-
- bool Initialize();
- bool InitializeFromHandle(gfx::GpuMemoryBufferHandle handle);
-
- // Overridden from gfx::GpuMemoryBuffer:
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual uint32 GetStride() const OVERRIDE;
- virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE;
-
- private:
- scoped_ptr<base::SharedMemory> shared_memory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplShm);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHM_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
index f6080506caa..28282729215 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
@@ -4,84 +4,178 @@
#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h"
+#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
-#include "content/common/android/surface_texture_lookup.h"
+#include "content/common/android/surface_texture_manager.h"
+#include "content/common/gpu/client/gpu_memory_buffer_factory_host.h"
#include "ui/gl/gl_bindings.h"
namespace content {
+namespace {
+
+void GpuMemoryBufferDeleted(gfx::GpuMemoryBufferId id,
+ int client_id,
+ uint32 sync_point) {
+ GpuMemoryBufferFactoryHost::GetInstance()->DestroyGpuMemoryBuffer(
+ gfx::SURFACE_TEXTURE_BUFFER, id, client_id, sync_point);
+}
+
+void GpuMemoryBufferCreated(
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id,
+ const GpuMemoryBufferImpl::CreationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ if (handle.is_null()) {
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
+ return;
+ }
+
+ DCHECK_EQ(gfx::SURFACE_TEXTURE_BUFFER, handle.type);
+ callback.Run(GpuMemoryBufferImplSurfaceTexture::CreateFromHandle(
+ handle,
+ size,
+ format,
+ base::Bind(&GpuMemoryBufferDeleted, handle.id, client_id)));
+}
+
+void GpuMemoryBufferCreatedForChildProcess(
+ const GpuMemoryBufferImpl::AllocationCallback& callback,
+ const gfx::GpuMemoryBufferHandle& handle) {
+ DCHECK_IMPLIES(!handle.is_null(), gfx::SURFACE_TEXTURE_BUFFER == handle.type);
+
+ callback.Run(handle);
+}
+
+} // namespace
GpuMemoryBufferImplSurfaceTexture::GpuMemoryBufferImplSurfaceTexture(
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat)
- : GpuMemoryBufferImpl(size, internalformat),
- native_window_(NULL),
- stride_(0u) {}
+ Format format,
+ const DestructionCallback& callback,
+ ANativeWindow* native_window)
+ : GpuMemoryBufferImpl(id, size, format, callback),
+ native_window_(native_window),
+ stride_(0) {
+}
GpuMemoryBufferImplSurfaceTexture::~GpuMemoryBufferImplSurfaceTexture() {
- if (native_window_)
- ANativeWindow_release(native_window_);
+ ANativeWindow_release(native_window_);
}
// static
-bool GpuMemoryBufferImplSurfaceTexture::IsFormatSupported(
- unsigned internalformat) {
- switch (internalformat) {
- case GL_RGBA8_OES:
+void GpuMemoryBufferImplSurfaceTexture::Create(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int client_id,
+ const CreationCallback& callback) {
+ GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
+ gfx::SURFACE_TEXTURE_BUFFER,
+ id,
+ size,
+ format,
+ MAP,
+ client_id,
+ base::Bind(&GpuMemoryBufferCreated, size, format, client_id, callback));
+}
+
+// static
+void GpuMemoryBufferImplSurfaceTexture::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int child_client_id,
+ const AllocationCallback& callback) {
+ GpuMemoryBufferFactoryHost::GetInstance()->CreateGpuMemoryBuffer(
+ gfx::SURFACE_TEXTURE_BUFFER,
+ id,
+ size,
+ format,
+ MAP,
+ child_client_id,
+ base::Bind(&GpuMemoryBufferCreatedForChildProcess, callback));
+}
+
+// static
+scoped_ptr<GpuMemoryBufferImpl>
+GpuMemoryBufferImplSurfaceTexture::CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback) {
+ DCHECK(IsFormatSupported(format));
+
+ ANativeWindow* native_window = SurfaceTextureManager::GetInstance()->
+ AcquireNativeWidgetForSurfaceTexture(handle.id);
+ if (!native_window)
+ return scoped_ptr<GpuMemoryBufferImpl>();
+
+ ANativeWindow_setBuffersGeometry(
+ native_window, size.width(), size.height(), WindowFormat(format));
+
+ return make_scoped_ptr<GpuMemoryBufferImpl>(
+ new GpuMemoryBufferImplSurfaceTexture(
+ handle.id, size, format, callback, native_window));
+}
+
+// static
+void GpuMemoryBufferImplSurfaceTexture::DeletedByChildProcess(
+ gfx::GpuMemoryBufferId id,
+ int child_client_id,
+ uint32_t sync_point) {
+ GpuMemoryBufferFactoryHost::GetInstance()->DestroyGpuMemoryBuffer(
+ gfx::SURFACE_TEXTURE_BUFFER, id, child_client_id, sync_point);
+}
+
+// static
+bool GpuMemoryBufferImplSurfaceTexture::IsFormatSupported(Format format) {
+ switch (format) {
+ case RGBA_8888:
return true;
- default:
+ case RGBX_8888:
+ case BGRA_8888:
return false;
}
+
+ NOTREACHED();
+ return false;
}
// static
-bool GpuMemoryBufferImplSurfaceTexture::IsUsageSupported(unsigned usage) {
+bool GpuMemoryBufferImplSurfaceTexture::IsUsageSupported(Usage usage) {
switch (usage) {
- case GL_IMAGE_MAP_CHROMIUM:
+ case MAP:
return true;
- default:
+ case SCANOUT:
return false;
}
+
+ NOTREACHED();
+ return false;
}
// static
-bool GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(
- unsigned internalformat,
- unsigned usage) {
- return IsFormatSupported(internalformat) && IsUsageSupported(usage);
+bool GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(Format format,
+ Usage usage) {
+ return IsFormatSupported(format) && IsUsageSupported(usage);
}
// static
-int GpuMemoryBufferImplSurfaceTexture::WindowFormat(unsigned internalformat) {
- switch (internalformat) {
- case GL_RGBA8_OES:
+int GpuMemoryBufferImplSurfaceTexture::WindowFormat(Format format) {
+ switch (format) {
+ case RGBA_8888:
return WINDOW_FORMAT_RGBA_8888;
- default:
+ case RGBX_8888:
+ case BGRA_8888:
NOTREACHED();
return 0;
}
-}
-bool GpuMemoryBufferImplSurfaceTexture::InitializeFromHandle(
- gfx::GpuMemoryBufferHandle handle) {
- TRACE_EVENT0("gpu",
- "GpuMemoryBufferImplSurfaceTexture::InitializeFromHandle");
-
- DCHECK(IsFormatSupported(internalformat_));
- DCHECK(!native_window_);
- native_window_ = SurfaceTextureLookup::GetInstance()->AcquireNativeWidget(
- handle.surface_texture_id.primary_id,
- handle.surface_texture_id.secondary_id);
- if (!native_window_)
- return false;
-
- ANativeWindow_setBuffersGeometry(native_window_,
- size_.width(),
- size_.height(),
- WindowFormat(internalformat_));
-
- surface_texture_id_ = handle.surface_texture_id;
- return true;
+ NOTREACHED();
+ return 0;
}
void* GpuMemoryBufferImplSurfaceTexture::Map() {
@@ -97,7 +191,7 @@ void* GpuMemoryBufferImplSurfaceTexture::Map() {
}
DCHECK_LE(size_.width(), buffer.stride);
- stride_ = buffer.stride * BytesPerPixel(internalformat_);
+ stride_ = buffer.stride * BytesPerPixel(format_);
mapped_ = true;
return buffer.bits;
}
@@ -110,13 +204,15 @@ void GpuMemoryBufferImplSurfaceTexture::Unmap() {
mapped_ = false;
}
-uint32 GpuMemoryBufferImplSurfaceTexture::GetStride() const { return stride_; }
+uint32 GpuMemoryBufferImplSurfaceTexture::GetStride() const {
+ return stride_;
+}
gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSurfaceTexture::GetHandle()
const {
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::SURFACE_TEXTURE_BUFFER;
- handle.surface_texture_id = surface_texture_id_;
+ handle.id = id_;
return handle;
}
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h
index c1cbfc3c319..57256347ca8 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h
@@ -14,25 +14,47 @@ namespace content {
// Implementation of GPU memory buffer based on SurfaceTextures.
class GpuMemoryBufferImplSurfaceTexture : public GpuMemoryBufferImpl {
public:
- GpuMemoryBufferImplSurfaceTexture(const gfx::Size& size,
- unsigned internalformat);
- virtual ~GpuMemoryBufferImplSurfaceTexture();
+ static void Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int client_id,
+ const CreationCallback& callback);
+
+ static void AllocateForChildProcess(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ int child_client_id,
+ const AllocationCallback& callback);
+
+ static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback);
- static bool IsFormatSupported(unsigned internalformat);
- static bool IsUsageSupported(unsigned usage);
- static bool IsConfigurationSupported(unsigned internalformat, unsigned usage);
- static int WindowFormat(unsigned internalformat);
+ static void DeletedByChildProcess(gfx::GpuMemoryBufferId id,
+ int child_client_id,
+ uint32_t sync_point);
- bool InitializeFromHandle(gfx::GpuMemoryBufferHandle handle);
+ static bool IsFormatSupported(Format format);
+ static bool IsUsageSupported(Usage usage);
+ static bool IsConfigurationSupported(Format format, Usage usage);
+ static int WindowFormat(Format format);
// Overridden from gfx::GpuMemoryBuffer:
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE;
- virtual uint32 GetStride() const OVERRIDE;
+ virtual void* Map() override;
+ virtual void Unmap() override;
+ virtual gfx::GpuMemoryBufferHandle GetHandle() const override;
+ virtual uint32 GetStride() const override;
private:
- gfx::SurfaceTextureId surface_texture_id_;
+ GpuMemoryBufferImplSurfaceTexture(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ const DestructionCallback& callback,
+ ANativeWindow* native_window);
+ virtual ~GpuMemoryBufferImplSurfaceTexture();
+
ANativeWindow* native_window_;
size_t stride_;
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc
index d885f3f8676..3c144f37ccf 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_win.cc
@@ -4,39 +4,39 @@
#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shm.h"
+#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
namespace content {
// static
-scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::Create(
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->Initialize())
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
+void GpuMemoryBufferImpl::Create(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ Format format,
+ Usage usage,
+ int client_id,
+ const CreationCallback& callback) {
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::Create(id, size, format, callback);
+ return;
}
- return scoped_ptr<GpuMemoryBufferImpl>();
+ callback.Run(scoped_ptr<GpuMemoryBufferImpl>());
}
// static
void GpuMemoryBufferImpl::AllocateForChildProcess(
+ gfx::GpuMemoryBufferId id,
const gfx::Size& size,
- unsigned internalformat,
- unsigned usage,
+ Format format,
+ Usage usage,
base::ProcessHandle child_process,
+ int child_client_id,
const AllocationCallback& callback) {
- if (GpuMemoryBufferImplShm::IsConfigurationSupported(
- size, internalformat, usage)) {
- GpuMemoryBufferImplShm::AllocateSharedMemoryForChildProcess(
- size, internalformat, child_process, callback);
+ if (GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
+ size, format, usage)) {
+ GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ id, size, format, child_process, callback);
return;
}
@@ -44,19 +44,24 @@ void GpuMemoryBufferImpl::AllocateForChildProcess(
}
// static
+void GpuMemoryBufferImpl::DeletedByChildProcess(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ base::ProcessHandle child_process,
+ int child_client_id,
+ uint32 sync_point) {
+}
+
+// static
scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle(
- gfx::GpuMemoryBufferHandle handle,
+ const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
- unsigned internalformat) {
+ Format format,
+ const DestructionCallback& callback) {
switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER: {
- scoped_ptr<GpuMemoryBufferImplShm> buffer(
- new GpuMemoryBufferImplShm(size, internalformat));
- if (!buffer->InitializeFromHandle(handle))
- return scoped_ptr<GpuMemoryBufferImpl>();
-
- return buffer.PassAs<GpuMemoryBufferImpl>();
- }
+ case gfx::SHARED_MEMORY_BUFFER:
+ return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ handle, size, format, callback);
default:
return scoped_ptr<GpuMemoryBufferImpl>();
}
diff --git a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
index 8b714b9e19d..a7844678001 100644
--- a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
+++ b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
@@ -231,11 +231,13 @@ void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
}
void GpuVideoDecodeAcceleratorHost::OnPictureReady(
- int32 picture_buffer_id, int32 bitstream_buffer_id) {
+ int32 picture_buffer_id,
+ int32 bitstream_buffer_id,
+ const gfx::Rect& visible_rect) {
DCHECK(CalledOnValidThread());
if (!client_)
return;
- media::Picture picture(picture_buffer_id, bitstream_buffer_id);
+ media::Picture picture(picture_buffer_id, bitstream_buffer_id, visible_rect);
client_->PictureReady(picture);
}
diff --git a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
index 571bd0c94bf..4cbeeb1272d 100644
--- a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
+++ b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
@@ -31,26 +31,25 @@ class GpuVideoDecodeAcceleratorHost
CommandBufferProxyImpl* impl);
// IPC::Listener implementation.
- virtual void OnChannelError() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnChannelError() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// media::VideoDecodeAccelerator implementation.
- virtual bool Initialize(media::VideoCodecProfile profile,
- Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
- virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
+ bool Initialize(media::VideoCodecProfile profile, Client* client) override;
+ void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
+ void AssignPictureBuffers(
+ const std::vector<media::PictureBuffer>& buffers) override;
+ void ReusePictureBuffer(int32 picture_buffer_id) override;
+ void Flush() override;
+ void Reset() override;
+ void Destroy() override;
// CommandBufferProxyImpl::DeletionObserver implemetnation.
- virtual void OnWillDeleteImpl() OVERRIDE;
+ void OnWillDeleteImpl() override;
private:
// Only Destroy() should be deleting |this|.
- virtual ~GpuVideoDecodeAcceleratorHost();
+ ~GpuVideoDecodeAcceleratorHost() override;
// Notify |client_| of an error. Posts a task to avoid re-entrancy.
void PostNotifyError(Error);
@@ -64,7 +63,9 @@ class GpuVideoDecodeAcceleratorHost
const gfx::Size& dimensions,
uint32 texture_target);
void OnDismissPictureBuffer(int32 picture_buffer_id);
- void OnPictureReady(int32 picture_buffer_id, int32 bitstream_buffer_id);
+ void OnPictureReady(int32 picture_buffer_id,
+ int32 bitstream_buffer_id,
+ const gfx::Rect& visible_rect);
void OnFlushDone();
void OnResetDone();
void OnNotifyError(uint32 error);
diff --git a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
index fafa7eb00da..026040f455e 100644
--- a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
+++ b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
@@ -39,12 +39,6 @@ GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
impl_->RemoveDeletionObserver(this);
}
-// static
-std::vector<media::VideoEncodeAccelerator::SupportedProfile>
-GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
- return GpuVideoEncodeAccelerator::GetSupportedProfiles();
-}
-
bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
@@ -75,6 +69,56 @@ void GpuVideoEncodeAcceleratorHost::OnChannelError() {
NOTIFY_ERROR(kPlatformFailureError) << "OnChannelError()";
}
+std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
+ DCHECK(CalledOnValidThread());
+ if (!channel_)
+ return std::vector<media::VideoEncodeAccelerator::SupportedProfile>();
+ return ConvertGpuToMediaProfiles(
+ channel_->gpu_info().video_encode_accelerator_supported_profiles);
+}
+
+// Make sure the enum values of media::VideoCodecProfile and
+// gpu::VideoCodecProfile match.
+#define STATIC_ASSERT_ENUM_MATCH(name) \
+ static_assert( \
+ media::name == static_cast<media::VideoCodecProfile>(gpu::name), \
+ #name " value must match in media and gpu.")
+
+STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_UNKNOWN);
+STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_MIN);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_BASELINE);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_MAIN);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_EXTENDED);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH10PROFILE);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH422PROFILE);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH444PREDICTIVEPROFILE);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_SCALABLEBASELINE);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_SCALABLEHIGH);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_STEREOHIGH);
+STATIC_ASSERT_ENUM_MATCH(H264PROFILE_MULTIVIEWHIGH);
+STATIC_ASSERT_ENUM_MATCH(VP8PROFILE_ANY);
+STATIC_ASSERT_ENUM_MATCH(VP9PROFILE_ANY);
+STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_MAX);
+
+std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+GpuVideoEncodeAcceleratorHost::ConvertGpuToMediaProfiles(const std::vector<
+ gpu::VideoEncodeAcceleratorSupportedProfile>& gpu_profiles) {
+ std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
+ for (size_t i = 0; i < gpu_profiles.size(); i++) {
+ media::VideoEncodeAccelerator::SupportedProfile profile;
+ profile.profile =
+ static_cast<media::VideoCodecProfile>(gpu_profiles[i].profile);
+ profile.max_resolution = gpu_profiles[i].max_resolution;
+ profile.max_framerate_numerator = gpu_profiles[i].max_framerate_numerator;
+ profile.max_framerate_denominator =
+ gpu_profiles[i].max_framerate_denominator;
+ profiles.push_back(profile);
+ }
+ return profiles;
+}
+
bool GpuVideoEncodeAcceleratorHost::Initialize(
media::VideoFrame::Format input_format,
const gfx::Size& input_visible_size,
diff --git a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h
index 14c2d817b64..021eff46ec1 100644
--- a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h
+++ b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h
@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
+#include "gpu/config/gpu_info.h"
#include "ipc/ipc_listener.h"
#include "media/video/video_encode_accelerator.h"
@@ -44,34 +45,34 @@ class GpuVideoEncodeAcceleratorHost
GpuVideoEncodeAcceleratorHost(GpuChannelHost* channel,
CommandBufferProxyImpl* impl);
- // Static query for the supported profiles. This query proxies to
- // GpuVideoEncodeAccelerator::GetSupportedProfiles().
- static std::vector<SupportedProfile> GetSupportedProfiles();
+ static std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+ ConvertGpuToMediaProfiles(const std::vector<
+ gpu::VideoEncodeAcceleratorSupportedProfile>& gpu_profiles);
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelError() override;
// media::VideoEncodeAccelerator implementation.
- virtual bool Initialize(media::VideoFrame::Format input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32 initial_bitrate,
- Client* client) OVERRIDE;
- virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe) OVERRIDE;
- virtual void UseOutputBitstreamBuffer(
- const media::BitstreamBuffer& buffer) OVERRIDE;
- virtual void RequestEncodingParametersChange(uint32 bitrate,
- uint32 framerate_num) OVERRIDE;
- virtual void Destroy() OVERRIDE;
+ std::vector<SupportedProfile> GetSupportedProfiles() override;
+ bool Initialize(media::VideoFrame::Format input_format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32 initial_bitrate,
+ Client* client) override;
+ void Encode(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) override;
+ void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer) override;
+ void RequestEncodingParametersChange(uint32 bitrate,
+ uint32 framerate_num) override;
+ void Destroy() override;
// CommandBufferProxyImpl::DeletionObserver implemetnation.
- virtual void OnWillDeleteImpl() OVERRIDE;
+ void OnWillDeleteImpl() override;
private:
// Only Destroy() should be deleting |this|.
- virtual ~GpuVideoEncodeAcceleratorHost();
+ ~GpuVideoEncodeAcceleratorHost() override;
// Notify |client_| of an error. Posts a task to avoid re-entrancy.
void PostNotifyError(Error);
diff --git a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
index e7c945f3cea..a5ba1807fe9 100644
--- a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
+++ b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -22,13 +22,13 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
+#include "base/tracked_objects.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
-#include "gpu/command_buffer/client/gles2_lib.h"
#include "gpu/command_buffer/client/gles2_trace_implementation.h"
#include "gpu/command_buffer/client/transfer_buffer.h"
#include "gpu/command_buffer/common/constants.h"
@@ -65,28 +65,6 @@ scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup>
return it->second;
}
-// Singleton used to initialize and terminate the gles2 library.
-class GLES2Initializer {
- public:
- GLES2Initializer() {
- gles2::Initialize();
- }
-
- ~GLES2Initializer() {
- gles2::Terminate();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-
-base::LazyInstance<GLES2Initializer> g_gles2_initializer =
- LAZY_INSTANCE_INITIALIZER;
-
-////////////////////////////////////////////////////////////////////////////////
-
} // namespace anonymous
WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits::SharedMemoryLimits()
@@ -119,8 +97,8 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl(
active_url_(active_url),
gpu_preference_(attributes.preferDiscreteGPU ? gfx::PreferDiscreteGpu
: gfx::PreferIntegratedGpu),
- weak_ptr_factory_(this),
- mem_limits_(limits) {
+ mem_limits_(limits),
+ weak_ptr_factory_(this) {
if (share_context) {
DCHECK(!attributes_.shareResources);
share_group_ = share_context->share_group_;
@@ -150,15 +128,23 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::MaybeInitializeGL");
+ // Below, we perform an expensive one-time initialization that is required to
+ // get first pixels to the screen. This can't be called "jank" since there is
+ // nothing on the screen. Using TaskStopwatch to exclude the operation from
+ // jank calculations.
+ tracked_objects::TaskStopwatch stopwatch;
+ stopwatch.Start();
+
if (!CreateContext(surface_id_ != 0)) {
Destroy();
+
+ stopwatch.Stop();
+
initialize_failed_ = true;
return false;
}
- // TODO(twiz): This code is too fragile in that it assumes that only WebGL
- // contexts will request noExtensions.
- if (gl_ && attributes_.noExtensions)
+ if (gl_ && attributes_.webGL)
gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation");
command_buffer_->SetChannelErrorCallback(
@@ -171,6 +157,8 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
real_gl_->SetErrorMessageCallback(getErrorMessageCallback());
+ stopwatch.Stop();
+
visible_ = true;
initialized_ = true;
return true;
@@ -187,24 +175,13 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
share_group_command_buffer = share_context->command_buffer_.get();
}
+ ::gpu::gles2::ContextCreationAttribHelper attribs_for_gles2;
+ ConvertAttributes(attributes_, &attribs_for_gles2);
+ attribs_for_gles2.lose_context_when_out_of_memory =
+ lose_context_when_out_of_memory_;
+ DCHECK(attribs_for_gles2.buffer_preserved);
std::vector<int32> attribs;
- attribs.push_back(ALPHA_SIZE);
- attribs.push_back(attributes_.alpha ? 8 : 0);
- attribs.push_back(DEPTH_SIZE);
- attribs.push_back(attributes_.depth ? 24 : 0);
- attribs.push_back(STENCIL_SIZE);
- attribs.push_back(attributes_.stencil ? 8 : 0);
- attribs.push_back(SAMPLES);
- attribs.push_back(attributes_.antialias ? 4 : 0);
- attribs.push_back(SAMPLE_BUFFERS);
- attribs.push_back(attributes_.antialias ? 1 : 0);
- attribs.push_back(FAIL_IF_MAJOR_PERF_CAVEAT);
- attribs.push_back(attributes_.failIfMajorPerformanceCaveat ? 1 : 0);
- attribs.push_back(LOSE_CONTEXT_WHEN_OUT_OF_MEMORY);
- attribs.push_back(lose_context_when_out_of_memory_ ? 1 : 0);
- attribs.push_back(BIND_GENERATES_RESOURCES);
- attribs.push_back(0);
- attribs.push_back(NONE);
+ attribs_for_gles2.Serialize(&attribs);
// Create a proxy to a command buffer in the GPU process.
if (onscreen) {
@@ -239,9 +216,6 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::CreateContext");
- // Ensure the gles2 library is initialized first in a thread safe way.
- g_gles2_initializer.Get();
-
scoped_refptr<gpu::gles2::ShareGroup> gles2_share_group;
scoped_ptr<base::AutoLock> share_group_lock;
@@ -279,13 +253,16 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
DCHECK(host_.get());
// Create the object exposing the OpenGL API.
- bool bind_generates_resources = false;
+ const bool bind_generates_resources = false;
+ const bool support_client_side_arrays = false;
+
real_gl_.reset(
new gpu::gles2::GLES2Implementation(gles2_helper_.get(),
- gles2_share_group,
+ gles2_share_group.get(),
transfer_buffer_.get(),
bind_generates_resources,
lose_context_when_out_of_memory_,
+ support_client_side_arrays,
command_buffer_.get()));
setGLInterface(real_gl_.get());
@@ -309,12 +286,11 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
return true;
}
-bool WebGraphicsContext3DCommandBufferImpl::makeContextCurrent() {
+bool WebGraphicsContext3DCommandBufferImpl::InitializeOnCurrentThread() {
if (!MaybeInitializeGL()) {
DLOG(ERROR) << "Failed to initialize context.";
return false;
}
- gles2::SetGLContext(GetGLInterface());
if (gpu::error::IsError(command_buffer_->GetLastError())) {
LOG(ERROR) << "Context dead on arrival. Last error: "
<< command_buffer_->GetLastError();
diff --git a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
index 67a4fa2718b..9b4c7b6157b 100644
--- a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
+++ b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -142,14 +142,10 @@ class WebGraphicsContext3DCommandBufferImpl
return mem_limits_.mapped_memory_reclaim_limit;
}
+ CONTENT_EXPORT bool InitializeOnCurrentThread();
+
//----------------------------------------------------------------------
// WebGraphicsContext3D methods
-
- // Must be called after initialize() and before any of the following methods.
- // Permanently binds to the first calling thread. Returns false if the
- // graphics context fails to create. Do not call from more than one thread.
- virtual bool makeContextCurrent();
-
virtual bool isContextLost();
virtual WGC3Denum getGraphicsResetStatusARB();
@@ -161,30 +157,6 @@ class WebGraphicsContext3DCommandBufferImpl
BAD_ATTRIBUTE = 0x3004,
CONTEXT_LOST = 0x300E
};
- // WebGraphicsContext3DCommandBufferImpl configuration attributes. Those in
- // the 16-bit range are the same as used by EGL. Those outside the 16-bit
- // range are unique to Chromium. Attributes are matched using a closest fit
- // algorithm.
- // Changes to this enum should also be copied to
- // gpu/command_buffer/common/gles2_cmd_utils.cc and to
- // gpu/command_buffer/client/gl_in_process_context.cc
- enum Attribute {
- ALPHA_SIZE = 0x3021,
- BLUE_SIZE = 0x3022,
- GREEN_SIZE = 0x3023,
- RED_SIZE = 0x3024,
- DEPTH_SIZE = 0x3025,
- STENCIL_SIZE = 0x3026,
- SAMPLES = 0x3031,
- SAMPLE_BUFFERS = 0x3032,
- HEIGHT = 0x3056,
- WIDTH = 0x3057,
- NONE = 0x3038, // Attrib list = terminator
- SHARE_RESOURCES = 0x10000,
- BIND_GENERATES_RESOURCES = 0x10001,
- FAIL_IF_MAJOR_PERF_CAVEAT = 0x10002,
- LOSE_CONTEXT_WHEN_OUT_OF_MEMORY = 0x10003,
- };
// Initialize the underlying GL context. May be called multiple times; second
// and subsequent calls are ignored. Must be called from the thread that is
@@ -226,8 +198,6 @@ class WebGraphicsContext3DCommandBufferImpl
gfx::GpuPreference gpu_preference_;
- base::WeakPtrFactory<WebGraphicsContext3DCommandBufferImpl> weak_ptr_factory_;
-
scoped_ptr<CommandBufferProxyImpl> command_buffer_;
scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_;
scoped_ptr<gpu::TransferBuffer> transfer_buffer_;
@@ -236,6 +206,11 @@ class WebGraphicsContext3DCommandBufferImpl
Error last_error_;
SharedMemoryLimits mem_limits_;
scoped_refptr<ShareGroup> share_group_;
+
+ // Member variables should appear before the WeakPtrFactory, to ensure
+ // that any WeakPtrs to Controller are invalidated before its members
+ // variable's destructors are executed, rendering them invalid.
+ base::WeakPtrFactory<WebGraphicsContext3DCommandBufferImpl> weak_ptr_factory_;
};
} // namespace content
diff --git a/chromium/content/common/gpu/gpu_channel.cc b/chromium/content/common/gpu/gpu_channel.cc
index 005a4aa4093..369d514d061 100644
--- a/chromium/content/common/gpu/gpu_channel.cc
+++ b/chromium/content/common/gpu/gpu_channel.cc
@@ -25,12 +25,10 @@
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
-#include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "ipc/ipc_channel.h"
#include "ipc/message_filter.h"
#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_image.h"
#include "ui/gl/gl_surface.h"
#if defined(OS_POSIX)
@@ -74,57 +72,73 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
public:
GpuChannelMessageFilter(base::WeakPtr<GpuChannel> gpu_channel,
scoped_refptr<SyncPointManager> sync_point_manager,
- scoped_refptr<base::MessageLoopProxy> message_loop)
+ scoped_refptr<base::MessageLoopProxy> message_loop,
+ bool future_sync_points)
: preemption_state_(IDLE),
gpu_channel_(gpu_channel),
sender_(NULL),
sync_point_manager_(sync_point_manager),
message_loop_(message_loop),
messages_forwarded_to_channel_(0),
- a_stub_is_descheduled_(false) {}
+ a_stub_is_descheduled_(false),
+ future_sync_points_(future_sync_points) {}
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
+ void OnFilterAdded(IPC::Sender* sender) override {
DCHECK(!sender_);
sender_ = sender;
}
- virtual void OnFilterRemoved() OVERRIDE {
+ void OnFilterRemoved() override {
DCHECK(sender_);
sender_ = NULL;
}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
DCHECK(sender_);
bool handled = false;
- if (message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) {
- // This message should not be sent explicitly by the renderer.
- DLOG(ERROR) << "Client should not send "
+ if ((message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) &&
+ !future_sync_points_) {
+ DLOG(ERROR) << "Untrusted client should not send "
"GpuCommandBufferMsg_RetireSyncPoint message";
- handled = true;
- }
-
- // All other messages get processed by the GpuChannel.
- if (!handled) {
- messages_forwarded_to_channel_++;
- if (preempting_flag_.get())
- pending_messages_.push(PendingMessage(messages_forwarded_to_channel_));
- UpdatePreemptionState();
+ return true;
}
if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) {
- uint32 sync_point = sync_point_manager_->GenerateSyncPoint();
+ Tuple1<bool> retire;
IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
+ if (!GpuCommandBufferMsg_InsertSyncPoint::ReadSendParam(&message,
+ &retire)) {
+ reply->set_reply_error();
+ Send(reply);
+ return true;
+ }
+ if (!future_sync_points_ && !retire.a) {
+ LOG(ERROR) << "Untrusted contexts can't create future sync points";
+ reply->set_reply_error();
+ Send(reply);
+ return true;
+ }
+ uint32 sync_point = sync_point_manager_->GenerateSyncPoint();
GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point);
Send(reply);
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &GpuChannelMessageFilter::InsertSyncPointOnMainThread,
- gpu_channel_,
- sync_point_manager_,
- message.routing_id(),
- sync_point));
+ message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&GpuChannelMessageFilter::InsertSyncPointOnMainThread,
+ gpu_channel_,
+ sync_point_manager_,
+ message.routing_id(),
+ retire.a,
+ sync_point));
handled = true;
}
+
+ // All other messages get processed by the GpuChannel.
+ messages_forwarded_to_channel_++;
+ if (preempting_flag_.get())
+ pending_messages_.push(PendingMessage(messages_forwarded_to_channel_));
+ UpdatePreemptionState();
+
return handled;
}
@@ -152,7 +166,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
}
protected:
- virtual ~GpuChannelMessageFilter() {}
+ ~GpuChannelMessageFilter() override {}
private:
enum PreemptionState {
@@ -336,6 +350,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
base::WeakPtr<GpuChannel> gpu_channel,
scoped_refptr<SyncPointManager> manager,
int32 routing_id,
+ bool retire,
uint32 sync_point) {
// This function must ensure that the sync point will be retired. Normally
// we'll find the stub based on the routing ID, and associate the sync point
@@ -346,8 +361,10 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
GpuCommandBufferStub* stub = gpu_channel->LookupCommandBuffer(routing_id);
if (stub) {
stub->AddSyncPoint(sync_point);
- GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point);
- gpu_channel->OnMessageReceived(message);
+ if (retire) {
+ GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point);
+ gpu_channel->OnMessageReceived(message);
+ }
return;
} else {
gpu_channel->MessageProcessed();
@@ -372,6 +389,9 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
base::OneShotTimer<GpuChannelMessageFilter> timer_;
bool a_stub_is_descheduled_;
+
+ // True if this channel can create future sync points.
+ bool future_sync_points_;
};
GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
@@ -379,24 +399,26 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
gfx::GLShareGroup* share_group,
gpu::gles2::MailboxManager* mailbox,
int client_id,
- bool software)
+ bool software,
+ bool allow_future_sync_points)
: gpu_channel_manager_(gpu_channel_manager),
messages_processed_(0),
client_id_(client_id),
share_group_(share_group ? share_group : new gfx::GLShareGroup),
- mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManager),
- image_manager_(new gpu::gles2::ImageManager),
+ mailbox_manager_(mailbox ? mailbox : new gpu::gles2::MailboxManagerImpl),
watchdog_(watchdog),
software_(software),
handle_messages_scheduled_(false),
currently_processing_message_(NULL),
- weak_factory_(this),
- num_stubs_descheduled_(0) {
+ num_stubs_descheduled_(0),
+ allow_future_sync_points_(allow_future_sync_points),
+ weak_factory_(this) {
DCHECK(gpu_channel_manager);
DCHECK(client_id);
channel_id_ = IPC::Channel::GenerateVerifiedChannelID("gpu");
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
}
@@ -421,7 +443,8 @@ void GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
filter_ =
new GpuChannelMessageFilter(weak_factory_.GetWeakPtr(),
gpu_channel_manager_->sync_point_manager(),
- base::MessageLoopProxy::current());
+ base::MessageLoopProxy::current(),
+ allow_future_sync_points_);
io_message_loop_ = io_message_loop;
channel_->AddFilter(filter_.get());
@@ -433,10 +456,10 @@ std::string GpuChannel::GetChannelName() {
}
#if defined(OS_POSIX)
-int GpuChannel::TakeRendererFileDescriptor() {
+base::ScopedFD GpuChannel::TakeRendererFileDescriptor() {
if (!channel_) {
NOTREACHED();
- return -1;
+ return base::ScopedFD();
}
return channel_->TakeClientFileDescriptor();
}
@@ -552,7 +575,6 @@ CreateCommandBufferResult GpuChannel::CreateViewCommandBuffer(
share_group,
window,
mailbox_manager_.get(),
- image_manager_.get(),
gfx::Size(),
disallowed_features_,
init_params.attribs,
@@ -578,39 +600,6 @@ GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32 route_id) {
return stubs_.Lookup(route_id);
}
-void GpuChannel::CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- gfx::Size* size) {
- TRACE_EVENT1("gpu",
- "GpuChannel::CreateImage",
- "image_id",
- image_id);
-
- *size = gfx::Size();
-
- if (image_manager_->LookupImage(image_id)) {
- LOG(ERROR) << "CreateImage failed, image_id already in use.";
- return;
- }
-
- scoped_refptr<gfx::GLImage> image = gfx::GLImage::CreateGLImage(window);
- if (!image.get())
- return;
-
- image_manager_->AddImage(image.get(), image_id);
- *size = image->GetSize();
-}
-
-void GpuChannel::DeleteImage(int32 image_id) {
- TRACE_EVENT1("gpu",
- "GpuChannel::DeleteImage",
- "image_id",
- image_id);
-
- image_manager_->RemoveImage(image_id);
-}
-
void GpuChannel::LoseAllContexts() {
gpu_channel_manager_->LoseAllContexts();
}
@@ -678,65 +667,53 @@ void GpuChannel::HandleMessage() {
if (deferred_messages_.empty())
return;
- bool should_fast_track_ack = false;
- IPC::Message* m = deferred_messages_.front();
- GpuCommandBufferStub* stub = stubs_.Lookup(m->routing_id());
-
- do {
- if (stub) {
- if (!stub->IsScheduled())
- return;
- if (stub->IsPreempted()) {
- OnScheduled();
- return;
- }
+ IPC::Message* m = NULL;
+ GpuCommandBufferStub* stub = NULL;
+
+ m = deferred_messages_.front();
+ stub = stubs_.Lookup(m->routing_id());
+ if (stub) {
+ if (!stub->IsScheduled())
+ return;
+ if (stub->IsPreempted()) {
+ OnScheduled();
+ return;
}
+ }
- scoped_ptr<IPC::Message> message(m);
- deferred_messages_.pop_front();
- bool message_processed = true;
-
- currently_processing_message_ = message.get();
- bool result;
- if (message->routing_id() == MSG_ROUTING_CONTROL)
- result = OnControlMessageReceived(*message);
- else
- result = router_.RouteMessage(*message);
- currently_processing_message_ = NULL;
-
- if (!result) {
- // Respond to sync messages even if router failed to route.
- if (message->is_sync()) {
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message);
- reply->set_reply_error();
- Send(reply);
- }
- } else {
- // If the command buffer becomes unscheduled as a result of handling the
- // message but still has more commands to process, synthesize an IPC
- // message to flush that command buffer.
- if (stub) {
- if (stub->HasUnprocessedCommands()) {
- deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled(
- stub->route_id()));
- message_processed = false;
- }
- }
+ scoped_ptr<IPC::Message> message(m);
+ deferred_messages_.pop_front();
+ bool message_processed = true;
+
+ currently_processing_message_ = message.get();
+ bool result;
+ if (message->routing_id() == MSG_ROUTING_CONTROL)
+ result = OnControlMessageReceived(*message);
+ else
+ result = router_.RouteMessage(*message);
+ currently_processing_message_ = NULL;
+
+ if (!result) {
+ // Respond to sync messages even if router failed to route.
+ if (message->is_sync()) {
+ IPC::Message* reply = IPC::SyncMessage::GenerateReply(&*message);
+ reply->set_reply_error();
+ Send(reply);
}
- if (message_processed)
- MessageProcessed();
-
- // We want the EchoACK following the SwapBuffers to be sent as close as
- // possible, avoiding scheduling other channels in the meantime.
- should_fast_track_ack = false;
- if (!deferred_messages_.empty()) {
- m = deferred_messages_.front();
- stub = stubs_.Lookup(m->routing_id());
- should_fast_track_ack =
- (m->type() == GpuCommandBufferMsg_Echo::ID) &&
- stub && stub->IsScheduled();
+ } else {
+ // If the command buffer becomes unscheduled as a result of handling the
+ // message but still has more commands to process, synthesize an IPC
+ // message to flush that command buffer.
+ if (stub) {
+ if (stub->HasUnprocessedCommands()) {
+ deferred_messages_.push_front(new GpuCommandBufferMsg_Rescheduled(
+ stub->route_id()));
+ message_processed = false;
+ }
}
- } while (should_fast_track_ack);
+ }
+ if (message_processed)
+ MessageProcessed();
if (!deferred_messages_.empty()) {
OnScheduled();
@@ -756,7 +733,6 @@ void GpuChannel::OnCreateOffscreenCommandBuffer(
share_group,
gfx::GLSurfaceHandle(),
mailbox_manager_.get(),
- image_manager_.get(),
size,
disallowed_features_,
init_params.attribs,
diff --git a/chromium/content/common/gpu/gpu_channel.h b/chromium/content/common/gpu/gpu_channel.h
index 7ad270f0ebf..0d8538f4889 100644
--- a/chromium/content/common/gpu/gpu_channel.h
+++ b/chromium/content/common/gpu/gpu_channel.h
@@ -34,9 +34,6 @@ class WaitableEvent;
namespace gpu {
class PreemptionFlag;
-namespace gles2 {
-class ImageManager;
-}
}
namespace IPC {
@@ -59,8 +56,9 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
gfx::GLShareGroup* share_group,
gpu::gles2::MailboxManager* mailbox_manager,
int client_id,
- bool software);
- virtual ~GpuChannel();
+ bool software,
+ bool allow_future_sync_points);
+ ~GpuChannel() override;
void Init(base::MessageLoopProxy* io_message_loop,
base::WaitableEvent* shutdown_event);
@@ -74,7 +72,7 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
std::string GetChannelName();
#if defined(OS_POSIX)
- int TakeRendererFileDescriptor();
+ base::ScopedFD TakeRendererFileDescriptor();
#endif // defined(OS_POSIX)
base::ProcessId renderer_pid() const { return channel_->GetPeerPID(); }
@@ -86,11 +84,11 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
}
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelError() override;
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// Requeue the message that is currently being processed to the beginning of
// the queue. Used when the processing of a message gets aborted because of
@@ -114,12 +112,6 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
const GPUCreateCommandBufferConfig& init_params,
int32 route_id);
- void CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- gfx::Size* size);
- void DeleteImage(int32 image_id);
-
gfx::GLShareGroup* share_group() const { return share_group_.get(); }
GpuCommandBufferStub* LookupCommandBuffer(int32 route_id);
@@ -151,6 +143,8 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
uint64 GetMemoryUsage();
+ bool allow_future_sync_points() const { return allow_future_sync_points_; }
+
private:
friend class GpuChannelMessageFilter;
@@ -206,7 +200,6 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
scoped_refptr<gfx::GLShareGroup> share_group_;
scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
- scoped_refptr<gpu::gles2::ImageManager> image_manager_;
typedef IDMap<GpuCommandBufferStub, IDMapOwnPointer> StubMap;
StubMap stubs_;
@@ -218,14 +211,19 @@ class GpuChannel : public IPC::Listener, public IPC::Sender {
bool handle_messages_scheduled_;
IPC::Message* currently_processing_message_;
- base::WeakPtrFactory<GpuChannel> weak_factory_;
-
scoped_refptr<GpuChannelMessageFilter> filter_;
scoped_refptr<base::MessageLoopProxy> io_message_loop_;
scoped_ptr<DevToolsGpuAgent> devtools_gpu_agent_;
size_t num_stubs_descheduled_;
+ bool allow_future_sync_points_;
+
+ // Member variables should appear before the WeakPtrFactory, to ensure
+ // that any WeakPtrs to Controller are invalidated before its members
+ // variable's destructors are executed, rendering them invalid.
+ base::WeakPtrFactory<GpuChannel> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GpuChannel);
};
diff --git a/chromium/content/common/gpu/gpu_channel_manager.cc b/chromium/content/common/gpu/gpu_channel_manager.cc
index 7c96d79672f..a073e20151e 100644
--- a/chromium/content/common/gpu/gpu_channel_manager.cc
+++ b/chromium/content/common/gpu/gpu_channel_manager.cc
@@ -7,45 +7,98 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/gpu_memory_buffer_factory.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/sync_point_manager.h"
#include "content/common/message_router.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/mailbox_manager_impl.h"
#include "gpu/command_buffer/service/memory_program_cache.h"
#include "gpu/command_buffer/service/shader_translator_cache.h"
+#include "ipc/message_filter.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_share_group.h"
namespace content {
-GpuChannelManager::ImageOperation::ImageOperation(
- int32 sync_point, base::Closure callback)
- : sync_point(sync_point),
- callback(callback) {
-}
+namespace {
-GpuChannelManager::ImageOperation::~ImageOperation() {
-}
+class GpuChannelManagerMessageFilter : public IPC::MessageFilter {
+ public:
+ GpuChannelManagerMessageFilter(
+ GpuMemoryBufferFactory* gpu_memory_buffer_factory)
+ : sender_(NULL), gpu_memory_buffer_factory_(gpu_memory_buffer_factory) {}
+
+ void OnFilterAdded(IPC::Sender* sender) override {
+ DCHECK(!sender_);
+ sender_ = sender;
+ }
+
+ void OnFilterRemoved() override {
+ DCHECK(sender_);
+ sender_ = NULL;
+ }
+
+ bool OnMessageReceived(const IPC::Message& message) override {
+ DCHECK(sender_);
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GpuChannelManagerMessageFilter, message)
+ IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+ }
+
+ protected:
+ ~GpuChannelManagerMessageFilter() override {}
+
+ void OnCreateGpuMemoryBuffer(
+ const GpuMsg_CreateGpuMemoryBuffer_Params& params) {
+ TRACE_EVENT2("gpu",
+ "GpuChannelManagerMessageFilter::OnCreateGpuMemoryBuffer",
+ "id",
+ params.id,
+ "client_id",
+ params.client_id);
+ sender_->Send(new GpuHostMsg_GpuMemoryBufferCreated(
+ gpu_memory_buffer_factory_->CreateGpuMemoryBuffer(params.type,
+ params.id,
+ params.size,
+ params.format,
+ params.usage,
+ params.client_id)));
+ }
+
+ IPC::Sender* sender_;
+ GpuMemoryBufferFactory* gpu_memory_buffer_factory_;
+};
+
+} // namespace
GpuChannelManager::GpuChannelManager(MessageRouter* router,
GpuWatchdog* watchdog,
base::MessageLoopProxy* io_message_loop,
- base::WaitableEvent* shutdown_event)
- : weak_factory_(this),
- io_message_loop_(io_message_loop),
+ base::WaitableEvent* shutdown_event,
+ IPC::SyncChannel* channel)
+ : io_message_loop_(io_message_loop),
shutdown_event_(shutdown_event),
router_(router),
gpu_memory_manager_(
this,
GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit),
watchdog_(watchdog),
- sync_point_manager_(new SyncPointManager) {
+ sync_point_manager_(new SyncPointManager),
+ gpu_memory_buffer_factory_(GpuMemoryBufferFactory::Create()),
+ channel_(channel),
+ filter_(new GpuChannelManagerMessageFilter(
+ gpu_memory_buffer_factory_.get())),
+ weak_factory_(this) {
DCHECK(router_);
DCHECK(io_message_loop);
DCHECK(shutdown_event);
+ channel_->AddFilter(filter_.get());
}
GpuChannelManager::~GpuChannelManager() {
@@ -54,7 +107,6 @@ GpuChannelManager::~GpuChannelManager() {
default_offscreen_surface_->Destroy();
default_offscreen_surface_ = NULL;
}
- DCHECK(image_operations_.empty());
}
gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
@@ -108,9 +160,6 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
OnCreateViewCommandBuffer)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateImage, OnCreateImage)
- IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage, OnDeleteImage)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -120,7 +169,9 @@ bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
bool GpuChannelManager::Send(IPC::Message* msg) { return router_->Send(msg); }
-void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
+void GpuChannelManager::OnEstablishChannel(int client_id,
+ bool share_context,
+ bool allow_future_sync_points) {
IPC::ChannelHandle channel_handle;
gfx::GLShareGroup* share_group = NULL;
@@ -129,23 +180,28 @@ void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
if (!share_group_.get()) {
share_group_ = new gfx::GLShareGroup;
DCHECK(!mailbox_manager_.get());
- mailbox_manager_ = new gpu::gles2::MailboxManager;
+ mailbox_manager_ = new gpu::gles2::MailboxManagerImpl;
}
share_group = share_group_.get();
mailbox_manager = mailbox_manager_.get();
}
- scoped_ptr<GpuChannel> channel(new GpuChannel(
- this, watchdog_, share_group, mailbox_manager, client_id, false));
+ scoped_ptr<GpuChannel> channel(new GpuChannel(this,
+ watchdog_,
+ share_group,
+ mailbox_manager,
+ client_id,
+ false,
+ allow_future_sync_points));
channel->Init(io_message_loop_.get(), shutdown_event_);
channel_handle.name = channel->GetChannelName();
#if defined(OS_POSIX)
// On POSIX, pass the renderer-side FD. Also mark it as auto-close so
// that it gets closed after it has been sent.
- int renderer_fd = channel->TakeRendererFileDescriptor();
- DCHECK_NE(-1, renderer_fd);
- channel_handle.socket = base::FileDescriptor(renderer_fd, true);
+ base::ScopedFD renderer_fd = channel->TakeRendererFileDescriptor();
+ DCHECK(renderer_fd.is_valid());
+ channel_handle.socket = base::FileDescriptor(renderer_fd.Pass());
#endif
gpu_channels_.set(client_id, channel.Pass());
@@ -182,92 +238,42 @@ void GpuChannelManager::OnCreateViewCommandBuffer(
Send(new GpuHostMsg_CommandBufferCreated(result));
}
-void GpuChannelManager::CreateImage(
- gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
- gfx::Size size;
-
- GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
- if (iter != gpu_channels_.end()) {
- iter->second->CreateImage(window, image_id, &size);
- }
-
- Send(new GpuHostMsg_ImageCreated(size));
-}
-
-void GpuChannelManager::OnCreateImage(
- gfx::PluginWindowHandle window, int32 client_id, int32 image_id) {
- DCHECK(image_id);
-
- if (image_operations_.empty()) {
- CreateImage(window, client_id, image_id);
- } else {
- image_operations_.push_back(
- new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage,
- base::Unretained(this),
- window,
- client_id,
- image_id)));
- }
-}
-
-void GpuChannelManager::DeleteImage(int32 client_id, int32 image_id) {
- GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
- if (iter != gpu_channels_.end()) {
- iter->second->DeleteImage(image_id);
- }
-}
-
-void GpuChannelManager::OnDeleteImage(
- int32 client_id, int32 image_id, int32 sync_point) {
- DCHECK(image_id);
-
- if (!sync_point && image_operations_.empty()) {
- DeleteImage(client_id, image_id);
- } else {
- image_operations_.push_back(
- new ImageOperation(sync_point,
- base::Bind(&GpuChannelManager::DeleteImage,
- base::Unretained(this),
- client_id,
- image_id)));
- if (sync_point) {
- sync_point_manager()->AddSyncPointCallback(
- sync_point,
- base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired,
- base::Unretained(this),
- image_operations_.back()));
- }
- }
-}
-
-void GpuChannelManager::OnDeleteImageSyncPointRetired(
- ImageOperation* image_operation) {
- // Mark operation as no longer having a pending sync point.
- image_operation->sync_point = 0;
-
- // De-queue operations until we reach a pending sync point.
- while (!image_operations_.empty()) {
- // Check if operation has a pending sync point.
- if (image_operations_.front()->sync_point)
- return;
-
- image_operations_.front()->callback.Run();
- delete image_operations_.front();
- image_operations_.pop_front();
- }
+void GpuChannelManager::DestroyGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) {
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&GpuChannelManager::DestroyGpuMemoryBufferOnIO,
+ base::Unretained(this),
+ type,
+ id,
+ client_id));
}
-void GpuChannelManager::OnCreateGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage) {
- Send(new GpuHostMsg_GpuMemoryBufferCreated(gfx::GpuMemoryBufferHandle()));
+void GpuChannelManager::DestroyGpuMemoryBufferOnIO(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) {
+ gpu_memory_buffer_factory_->DestroyGpuMemoryBuffer(type, id, client_id);
}
void GpuChannelManager::OnDestroyGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
int32 sync_point) {
+ if (!sync_point) {
+ DestroyGpuMemoryBuffer(type, id, client_id);
+ } else {
+ sync_point_manager()->AddSyncPointCallback(
+ sync_point,
+ base::Bind(&GpuChannelManager::DestroyGpuMemoryBuffer,
+ base::Unretained(this),
+ type,
+ id,
+ client_id));
+ }
}
void GpuChannelManager::OnLoadedShader(std::string program_proto) {
diff --git a/chromium/content/common/gpu/gpu_channel_manager.h b/chromium/content/common/gpu/gpu_channel_manager.h
index 73b4e59ea57..fd9844f6420 100644
--- a/chromium/content/common/gpu/gpu_channel_manager.h
+++ b/chromium/content/common/gpu/gpu_channel_manager.h
@@ -19,6 +19,7 @@
#include "content/common/gpu/gpu_memory_manager.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/gl_surface.h"
@@ -41,12 +42,15 @@ class ShaderTranslatorCache;
namespace IPC {
struct ChannelHandle;
+class SyncChannel;
+class MessageFilter;
}
struct GPUCreateCommandBufferConfig;
namespace content {
class GpuChannel;
+class GpuMemoryBufferFactory;
class GpuWatchdog;
class MessageRouter;
class SyncPointManager;
@@ -60,25 +64,24 @@ class GpuChannelManager : public IPC::Listener,
GpuChannelManager(MessageRouter* router,
GpuWatchdog* watchdog,
base::MessageLoopProxy* io_message_loop,
- base::WaitableEvent* shutdown_event);
- virtual ~GpuChannelManager();
+ base::WaitableEvent* shutdown_event,
+ IPC::SyncChannel* channel);
+ ~GpuChannelManager() override;
// Remove the channel for a particular renderer.
void RemoveChannel(int client_id);
// Listener overrides.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// Sender overrides.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
bool HandleMessagesScheduled();
uint64 MessagesProcessed();
void LoseAllContexts();
- base::WeakPtrFactory<GpuChannelManager> weak_factory_;
-
int GenerateRouteID();
void AddRoute(int32 routing_id, IPC::Listener* listener);
void RemoveRoute(int32 routing_id);
@@ -98,19 +101,17 @@ class GpuChannelManager : public IPC::Listener,
gfx::GLSurface* GetDefaultOffscreenSurface();
- private:
- struct ImageOperation {
- ImageOperation(int32 sync_point, base::Closure callback);
- ~ImageOperation();
+ GpuMemoryBufferFactory* gpu_memory_buffer_factory() {
+ return gpu_memory_buffer_factory_.get();
+ }
- int32 sync_point;
- base::Closure callback;
- };
+ private:
typedef base::ScopedPtrHashMap<int, GpuChannel> GpuChannelMap;
- typedef std::deque<ImageOperation*> ImageOperationQueue;
// Message handlers.
- void OnEstablishChannel(int client_id, bool share_context);
+ void OnEstablishChannel(int client_id,
+ bool share_context,
+ bool allow_future_sync_points);
void OnCloseChannel(const IPC::ChannelHandle& channel_handle);
void OnVisibilityChanged(
int32 render_view_id, int32 client_id, bool visible);
@@ -120,19 +121,16 @@ class GpuChannelManager : public IPC::Listener,
int32 client_id,
const GPUCreateCommandBufferConfig& init_params,
int32 route_id);
- void CreateImage(
- gfx::PluginWindowHandle window, int32 client_id, int32 image_id);
- void OnCreateImage(
- gfx::PluginWindowHandle window, int32 client_id, int32 image_id);
- void DeleteImage(int32 client_id, int32 image_id);
- void OnDeleteImage(int32 client_id, int32 image_id, int32 sync_point);
- void OnDeleteImageSyncPointRetired(ImageOperation*);
void OnLoadedShader(std::string shader);
- void OnCreateGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- unsigned internalformat,
- unsigned usage);
- void OnDestroyGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id);
+ void DestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id);
+ void OnDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id,
int32 sync_point);
void OnLoseAllContexts();
@@ -156,7 +154,14 @@ class GpuChannelManager : public IPC::Listener,
scoped_ptr<gpu::gles2::ProgramCache> program_cache_;
scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_;
scoped_refptr<gfx::GLSurface> default_offscreen_surface_;
- ImageOperationQueue image_operations_;
+ scoped_ptr<GpuMemoryBufferFactory> gpu_memory_buffer_factory_;
+ IPC::SyncChannel* channel_;
+ scoped_refptr<IPC::MessageFilter> filter_;
+
+ // Member variables should appear before the WeakPtrFactory, to ensure
+ // that any WeakPtrs to Controller are invalidated before its members
+ // variable's destructors are executed, rendering them invalid.
+ base::WeakPtrFactory<GpuChannelManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GpuChannelManager);
};
diff --git a/chromium/content/common/gpu/gpu_command_buffer_stub.cc b/chromium/content/common/gpu/gpu_command_buffer_stub.cc
index 37f50a8cdf4..18a666dcd9f 100644
--- a/chromium/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/chromium/content/common/gpu/gpu_command_buffer_stub.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/hash.h"
+#include "base/json/json_writer.h"
#include "base/memory/shared_memory.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -14,6 +15,7 @@
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
+#include "content/common/gpu/gpu_memory_buffer_factory.h"
#include "content/common/gpu/gpu_memory_manager.h"
#include "content/common/gpu/gpu_memory_tracking.h"
#include "content/common/gpu/gpu_messages.h"
@@ -28,7 +30,7 @@
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/service/gl_context_virtual.h"
#include "gpu/command_buffer/service/gl_state_restorer_impl.h"
-#include "gpu/command_buffer/service/gpu_control_service.h"
+#include "gpu/command_buffer/service/image_factory.h"
#include "gpu/command_buffer/service/image_manager.h"
#include "gpu/command_buffer/service/logger.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
@@ -66,21 +68,20 @@ class GpuCommandBufferMemoryTracker : public gpu::gles2::MemoryTracker {
CreateTrackingGroup(channel->renderer_pid(), this)) {
}
- virtual void TrackMemoryAllocatedChange(
+ void TrackMemoryAllocatedChange(
size_t old_size,
size_t new_size,
- gpu::gles2::MemoryTracker::Pool pool) OVERRIDE {
+ gpu::gles2::MemoryTracker::Pool pool) override {
tracking_group_->TrackMemoryAllocatedChange(
old_size, new_size, pool);
}
- virtual bool EnsureGPUMemoryAvailable(size_t size_needed) OVERRIDE {
+ bool EnsureGPUMemoryAvailable(size_t size_needed) override {
return tracking_group_->EnsureGPUMemoryAvailable(size_needed);
};
private:
- virtual ~GpuCommandBufferMemoryTracker() {
- }
+ ~GpuCommandBufferMemoryTracker() override {}
scoped_ptr<GpuMemoryTrackingGroup> tracking_group_;
DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferMemoryTracker);
@@ -90,7 +91,7 @@ class GpuCommandBufferMemoryTracker : public gpu::gles2::MemoryTracker {
// url_hash matches.
void FastSetActiveURL(const GURL& url, size_t url_hash) {
// Leave the previously set URL in the empty case -- empty URLs are given by
- // WebKitPlatformSupportImpl::createOffscreenGraphicsContext3D. Hopefully the
+ // BlinkPlatformImpl::createOffscreenGraphicsContext3D. Hopefully the
// onscreen context URL was set previously and will show up even when a crash
// occurs during offscreen command processing.
if (url.is_empty())
@@ -111,6 +112,36 @@ const int64 kHandleMoreWorkPeriodBusyMs = 1;
// Prevents idle work from being starved.
const int64 kMaxTimeSinceIdleMs = 10;
+class DevToolsChannelData : public base::debug::ConvertableToTraceFormat {
+ public:
+ static scoped_refptr<base::debug::ConvertableToTraceFormat> CreateForChannel(
+ GpuChannel* channel);
+
+ void AppendAsTraceFormat(std::string* out) const override {
+ std::string tmp;
+ base::JSONWriter::Write(value_.get(), &tmp);
+ *out += tmp;
+ }
+
+ private:
+ explicit DevToolsChannelData(base::Value* value) : value_(value) {}
+ ~DevToolsChannelData() override {}
+ scoped_ptr<base::Value> value_;
+ DISALLOW_COPY_AND_ASSIGN(DevToolsChannelData);
+};
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+DevToolsChannelData::CreateForChannel(GpuChannel* channel) {
+ scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue);
+ res->SetInteger("renderer_pid", channel->renderer_pid());
+ res->SetDouble("used_bytes", channel->GetMemoryUsage());
+ res->SetDouble("limit_bytes",
+ channel->gpu_channel_manager()
+ ->gpu_memory_manager()
+ ->GetMaximumClientAllocation());
+ return new DevToolsChannelData(res.release());
+}
+
} // namespace
GpuCommandBufferStub::GpuCommandBufferStub(
@@ -118,7 +149,6 @@ GpuCommandBufferStub::GpuCommandBufferStub(
GpuCommandBufferStub* share_group,
const gfx::GLSurfaceHandle& handle,
gpu::gles2::MailboxManager* mailbox_manager,
- gpu::gles2::ImageManager* image_manager,
const gfx::Size& size,
const gpu::gles2::DisallowedFeatures& disallowed_features,
const std::vector<int32>& attribs,
@@ -156,15 +186,14 @@ GpuCommandBufferStub::GpuCommandBufferStub(
if (share_group) {
context_group_ = share_group->context_group_;
DCHECK(context_group_->bind_generates_resource() ==
- attrib_parser.bind_generates_resource_);
+ attrib_parser.bind_generates_resource);
} else {
context_group_ = new gpu::gles2::ContextGroup(
mailbox_manager,
- image_manager,
new GpuCommandBufferMemoryTracker(channel),
channel_->gpu_channel_manager()->shader_translator_cache(),
NULL,
- attrib_parser.bind_generates_resource_);
+ attrib_parser.bind_generates_resource);
}
use_virtualized_gl_context_ |=
@@ -183,6 +212,12 @@ GpuMemoryManager* GpuCommandBufferStub::GetMemoryManager() const {
}
bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
+ "GPUTask",
+ "data",
+ DevToolsChannelData::CreateForChannel(channel()));
+ // TODO(yurys): remove devtools_gpu_instrumentation call once DevTools
+ // Timeline migrates to tracing crbug.com/361045.
devtools_gpu_instrumentation::ScopedGpuTask task(channel());
FastSetActiveURL(active_url_, active_url_hash_);
@@ -190,12 +225,12 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
// Ensure the appropriate GL context is current before handling any IPC
// messages directed at the command buffer. This ensures that the message
// handler can assume that the context is current (not necessary for
- // Echo, RetireSyncPoint, or WaitSyncPoint).
- if (decoder_.get() && message.type() != GpuCommandBufferMsg_Echo::ID &&
+ // RetireSyncPoint or WaitSyncPoint).
+ if (decoder_.get() &&
message.type() != GpuCommandBufferMsg_WaitForTokenInRange::ID &&
message.type() != GpuCommandBufferMsg_WaitForGetOffsetInRange::ID &&
message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID &&
- message.type() != GpuCommandBufferMsg_SetLatencyInfo::ID) {
+ message.type() != GpuCommandBufferMsg_SignalSyncPoint::ID) {
if (!MakeCurrent())
return false;
have_context = true;
@@ -211,13 +246,11 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
OnSetGetBuffer);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ProduceFrontBuffer,
OnProduceFrontBuffer);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Echo, OnEcho);
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_WaitForTokenInRange,
OnWaitForTokenInRange);
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_WaitForGetOffsetInRange,
OnWaitForGetOffsetInRange);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SetLatencyInfo, OnSetLatencyInfo);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Rescheduled, OnRescheduled);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer,
OnRegisterTransferBuffer);
@@ -238,10 +271,8 @@ bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(
GpuCommandBufferMsg_SetClientHasMemoryAllocationChangedCallback,
OnSetClientHasMemoryAllocationChangedCallback)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
- OnRegisterGpuMemoryBuffer);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyGpuMemoryBuffer,
- OnDestroyGpuMemoryBuffer);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateImage, OnCreateImage);
+ IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyImage, OnDestroyImage);
IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture,
OnCreateStreamTexture)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -310,7 +341,7 @@ void GpuCommandBufferStub::PollWork() {
bool GpuCommandBufferStub::HasUnprocessedCommands() {
if (command_buffer_) {
gpu::CommandBuffer::State state = command_buffer_->GetLastState();
- return state.put_offset != state.get_offset &&
+ return command_buffer_->GetPutOffset() != state.get_offset &&
!gpu::error::IsError(state.error);
}
return false;
@@ -351,11 +382,6 @@ void GpuCommandBufferStub::ScheduleDelayedWork(int64 delay) {
base::TimeDelta::FromMilliseconds(delay));
}
-void GpuCommandBufferStub::OnEcho(const IPC::Message& message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnEcho");
- Send(new IPC::Message(message));
-}
-
bool GpuCommandBufferStub::MakeCurrent() {
if (decoder_->MakeCurrent())
return true;
@@ -540,9 +566,6 @@ void GpuCommandBufferStub::OnInitialize(
return;
}
- gpu_control_service_.reset(
- new gpu::GpuControlService(context_group_->image_manager(), NULL));
-
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableGPUServiceLogging)) {
decoder_->set_log_commands(true);
@@ -584,8 +607,11 @@ void GpuCommandBufferStub::OnInitialize(
command_buffer_->SetSharedStateBuffer(gpu::MakeBackingFromSharedMemory(
shared_state_shm.Pass(), kSharedStateSize));
+ gpu::Capabilities capabilities = decoder_->GetCapabilities();
+ capabilities.future_sync_points = channel_->allow_future_sync_points();
+
GpuCommandBufferMsg_Initialize::WriteReplyParams(
- reply_message, true, decoder_->GetCapabilities());
+ reply_message, true, capabilities);
Send(reply_message);
if (handle_.is_null() && !active_url_.is_empty()) {
@@ -595,15 +621,6 @@ void GpuCommandBufferStub::OnInitialize(
}
}
-void GpuCommandBufferStub::OnSetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- if (!ui::LatencyInfo::Verify(latency_info,
- "GpuCommandBufferStub::OnSetLatencyInfo"))
- return;
- if (!latency_info_callback_.is_null())
- latency_info_callback_.Run(latency_info);
-}
-
void GpuCommandBufferStub::OnCreateStreamTexture(
uint32 texture_id, int32 stream_id, bool* succeeded) {
#if defined(OS_ANDROID)
@@ -723,9 +740,18 @@ void GpuCommandBufferStub::CheckCompleteWaits() {
}
}
-void GpuCommandBufferStub::OnAsyncFlush(int32 put_offset, uint32 flush_count) {
+void GpuCommandBufferStub::OnAsyncFlush(
+ int32 put_offset,
+ uint32 flush_count,
+ const std::vector<ui::LatencyInfo>& latency_info) {
TRACE_EVENT1(
"gpu", "GpuCommandBufferStub::OnAsyncFlush", "put_offset", put_offset);
+
+ if (ui::LatencyInfo::Verify(latency_info,
+ "GpuCommandBufferStub::OnAsyncFlush") &&
+ !latency_info_callback_.is_null()) {
+ latency_info_callback_.Run(latency_info);
+ }
DCHECK(command_buffer_.get());
if (flush_count - last_flush_count_ < 0x8000000U) {
last_flush_count_ = flush_count;
@@ -741,7 +767,7 @@ void GpuCommandBufferStub::OnAsyncFlush(int32 put_offset, uint32 flush_count) {
void GpuCommandBufferStub::OnRescheduled() {
gpu::CommandBuffer::State pre_state = command_buffer_->GetLastState();
- command_buffer_->Flush(pre_state.put_offset);
+ command_buffer_->Flush(command_buffer_->GetPutOffset());
gpu::CommandBuffer::State post_state = command_buffer_->GetLastState();
if (pre_state.get_offset != post_state.get_offset)
@@ -832,8 +858,6 @@ void GpuCommandBufferStub::AddSyncPoint(uint32 sync_point) {
void GpuCommandBufferStub::OnRetireSyncPoint(uint32 sync_point) {
DCHECK(!sync_points_.empty() && sync_points_.front() == sync_point);
sync_points_.pop_front();
- if (context_group_->mailbox_manager()->UsesSync() && MakeCurrent())
- context_group_->mailbox_manager()->PushTextureUpdates();
GpuChannelManager* manager = channel_->gpu_channel_manager();
manager->sync_point_manager()->RetireSyncPoint(sync_point);
}
@@ -915,32 +939,49 @@ void GpuCommandBufferStub::OnSetClientHasMemoryAllocationChangedCallback(
}
}
-void GpuCommandBufferStub::OnRegisterGpuMemoryBuffer(
- int32 id,
- gfx::GpuMemoryBufferHandle gpu_memory_buffer,
- uint32 width,
- uint32 height,
- uint32 internalformat) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterGpuMemoryBuffer");
-#if defined(OS_ANDROID)
- // Verify that renderer is not trying to use a surface texture it doesn't own.
- if (gpu_memory_buffer.type == gfx::SURFACE_TEXTURE_BUFFER &&
- gpu_memory_buffer.surface_texture_id.secondary_id !=
- channel()->client_id()) {
- LOG(ERROR) << "Illegal surface texture ID for renderer.";
+void GpuCommandBufferStub::OnCreateImage(int32 id,
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ gfx::GpuMemoryBuffer::Format format,
+ uint32 internalformat) {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateImage");
+
+ if (!decoder_)
+ return;
+
+ gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
+ DCHECK(image_manager);
+ if (image_manager->LookupImage(id)) {
+ LOG(ERROR) << "Image already exists with same ID.";
return;
}
-#endif
- if (gpu_control_service_) {
- gpu_control_service_->RegisterGpuMemoryBuffer(
- id, gpu_memory_buffer, width, height, internalformat);
- }
+
+ GpuChannelManager* manager = channel_->gpu_channel_manager();
+ scoped_refptr<gfx::GLImage> image =
+ manager->gpu_memory_buffer_factory()
+ ->AsImageFactory()
+ ->CreateImageForGpuMemoryBuffer(
+ handle, size, format, internalformat, channel()->client_id());
+ if (!image.get())
+ return;
+
+ image_manager->AddImage(image.get(), id);
}
-void GpuCommandBufferStub::OnDestroyGpuMemoryBuffer(int32 id) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyGpuMemoryBuffer");
- if (gpu_control_service_)
- gpu_control_service_->UnregisterGpuMemoryBuffer(id);
+void GpuCommandBufferStub::OnDestroyImage(int32 id) {
+ TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyImage");
+
+ if (!decoder_)
+ return;
+
+ gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
+ DCHECK(image_manager);
+ if (!image_manager->LookupImage(id)) {
+ LOG(ERROR) << "Image with ID doesn't exist.";
+ return;
+ }
+
+ image_manager->RemoveImage(id);
}
void GpuCommandBufferStub::SendConsoleMessage(
@@ -1041,4 +1082,9 @@ uint64 GpuCommandBufferStub::GetMemoryUsage() const {
return GetMemoryManager()->GetClientMemoryUsage(this);
}
+void GpuCommandBufferStub::SwapBuffersCompleted(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ Send(new GpuCommandBufferMsg_SwapBuffersCompleted(route_id_, latency_info));
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/gpu_command_buffer_stub.h b/chromium/content/common/gpu/gpu_command_buffer_stub.h
index f660f1df3e8..6f69a2a3d86 100644
--- a/chromium/content/common/gpu/gpu_command_buffer_stub.h
+++ b/chromium/content/common/gpu/gpu_command_buffer_stub.h
@@ -32,10 +32,8 @@
#include "url/gurl.h"
namespace gpu {
-class GpuControlService;
struct Mailbox;
namespace gles2 {
-class ImageManager;
class MailboxManager;
}
}
@@ -71,7 +69,6 @@ class GpuCommandBufferStub
GpuCommandBufferStub* share_group,
const gfx::GLSurfaceHandle& handle,
gpu::gles2::MailboxManager* mailbox_manager,
- gpu::gles2::ImageManager* image_manager,
const gfx::Size& size,
const gpu::gles2::DisallowedFeatures& disallowed_features,
const std::vector<int32>& attribs,
@@ -83,21 +80,20 @@ class GpuCommandBufferStub
bool software,
const GURL& active_url);
- virtual ~GpuCommandBufferStub();
+ ~GpuCommandBufferStub() override;
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// GpuMemoryManagerClient implementation:
- virtual gfx::Size GetSurfaceSize() const OVERRIDE;
- virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const OVERRIDE;
- virtual void SetMemoryAllocation(
- const gpu::MemoryAllocation& allocation) OVERRIDE;
- virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) OVERRIDE;
- virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE;
+ gfx::Size GetSurfaceSize() const override;
+ gpu::gles2::MemoryTracker* GetMemoryTracker() const override;
+ void SetMemoryAllocation(const gpu::MemoryAllocation& allocation) override;
+ void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) override;
+ bool GetTotalGpuMemory(uint64* bytes) override;
// Whether this command buffer can currently handle IPC messages.
bool IsScheduled();
@@ -147,6 +143,8 @@ class GpuCommandBufferStub
uint64 GetMemoryUsage() const;
+ void SwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info);
+
private:
GpuMemoryManager* GetMemoryManager() const;
bool MakeCurrent();
@@ -167,8 +165,8 @@ class GpuCommandBufferStub
void OnWaitForGetOffsetInRange(int32 start,
int32 end,
IPC::Message* reply_message);
- void OnAsyncFlush(int32 put_offset, uint32 flush_count);
- void OnEcho(const IPC::Message& message);
+ void OnAsyncFlush(int32 put_offset, uint32 flush_count,
+ const std::vector<ui::LatencyInfo>& latency_info);
void OnRescheduled();
void OnRegisterTransferBuffer(int32 id,
base::SharedMemoryHandle transfer_buffer,
@@ -199,16 +197,15 @@ class GpuCommandBufferStub
void OnSetClientHasMemoryAllocationChangedCallback(bool has_callback);
- void OnRegisterGpuMemoryBuffer(int32 id,
- gfx::GpuMemoryBufferHandle gpu_memory_buffer,
- uint32 width,
- uint32 height,
- uint32 internalformat);
- void OnDestroyGpuMemoryBuffer(int32 id);
+ void OnCreateImage(int32 id,
+ gfx::GpuMemoryBufferHandle handle,
+ gfx::Size size,
+ gfx::GpuMemoryBuffer::Format format,
+ uint32 internalformat);
+ void OnDestroyImage(int32 id);
void OnCommandProcessed();
void OnParseError();
- void OnSetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
void OnCreateStreamTexture(
uint32 texture_id, int32 stream_id, bool* succeeded);
@@ -251,7 +248,6 @@ class GpuCommandBufferStub
scoped_ptr<gpu::gles2::GLES2Decoder> decoder_;
scoped_ptr<gpu::GpuScheduler> scheduler_;
scoped_refptr<gfx::GLSurface> surface_;
- scoped_ptr<gpu::GpuControlService> gpu_control_service_;
scoped_ptr<GpuMemoryManagerClientState> memory_manager_client_state_;
// The last memory allocation received from the GpuMemoryManager (used to
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory.h b/chromium/content/common/gpu/gpu_memory_buffer_factory.h
new file mode 100644
index 00000000000..5dd2203f268
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory.h
@@ -0,0 +1,55 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_H_
+#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+namespace gfx {
+class GLImage;
+}
+
+namespace gpu {
+class ImageFactory;
+}
+
+namespace content {
+
+class GpuMemoryBufferFactory {
+ public:
+ GpuMemoryBufferFactory() {}
+ virtual ~GpuMemoryBufferFactory() {}
+
+ // Creates a new platform specific factory instance.
+ static scoped_ptr<GpuMemoryBufferFactory> Create();
+
+ // Creates a GPU memory buffer instance of |type|. A valid handle is
+ // returned on success.
+ virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id) = 0;
+
+ // Destroys GPU memory buffer identified by |id|.
+ virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) = 0;
+
+ // Type-checking downcast routine.
+ virtual gpu::ImageFactory* AsImageFactory() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_android.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_android.cc
new file mode 100644
index 00000000000..1fce6b67615
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_android.cc
@@ -0,0 +1,88 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory.h"
+
+#include "base/logging.h"
+#include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
+#include "gpu/command_buffer/service/image_factory.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_shared_memory.h"
+
+namespace content {
+namespace {
+
+class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory,
+ public gpu::ImageFactory {
+ public:
+ // Overridden from GpuMemoryBufferFactory:
+ virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id) override {
+ switch (type) {
+ case gfx::SURFACE_TEXTURE_BUFFER:
+ return surface_texture_factory_.CreateGpuMemoryBuffer(
+ id, size, format, client_id);
+ default:
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+ }
+ virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) override {
+ switch (type) {
+ case gfx::SURFACE_TEXTURE_BUFFER:
+ surface_texture_factory_.DestroyGpuMemoryBuffer(id, client_id);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ virtual gpu::ImageFactory* AsImageFactory() override { return this; }
+
+ // Overridden from gpu::ImageFactory:
+ virtual scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ unsigned internalformat,
+ int client_id) override {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_refptr<gfx::GLImageSharedMemory> image(
+ new gfx::GLImageSharedMemory(size, internalformat));
+ if (!image->Initialize(handle, format))
+ return NULL;
+
+ return image;
+ }
+ case gfx::SURFACE_TEXTURE_BUFFER: {
+ return surface_texture_factory_.CreateImageForGpuMemoryBuffer(
+ handle.id, size, internalformat, client_id);
+ }
+ default:
+ NOTREACHED();
+ return scoped_refptr<gfx::GLImage>();
+ }
+ }
+
+ private:
+ GpuMemoryBufferFactorySurfaceTexture surface_texture_factory_;
+};
+
+} // namespace
+
+// static
+scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::Create() {
+ return make_scoped_ptr<GpuMemoryBufferFactory>(
+ new GpuMemoryBufferFactoryImpl);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
new file mode 100644
index 00000000000..182f82655d9
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
@@ -0,0 +1,103 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
+#include "ui/gl/gl_image_io_surface.h"
+
+namespace content {
+namespace {
+
+void AddBooleanValue(CFMutableDictionaryRef dictionary,
+ const CFStringRef key,
+ bool value) {
+ CFDictionaryAddValue(
+ dictionary, key, value ? kCFBooleanTrue : kCFBooleanFalse);
+}
+
+void AddIntegerValue(CFMutableDictionaryRef dictionary,
+ const CFStringRef key,
+ int32 value) {
+ base::ScopedCFTypeRef<CFNumberRef> number(
+ CFNumberCreate(NULL, kCFNumberSInt32Type, &value));
+ CFDictionaryAddValue(dictionary, key, number.get());
+}
+
+} // namespace
+
+GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() {
+}
+
+GpuMemoryBufferFactoryIOSurface::~GpuMemoryBufferFactoryIOSurface() {
+}
+
+gfx::GpuMemoryBufferHandle
+GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id) {
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
+ properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+ AddIntegerValue(properties, kIOSurfaceWidth, size.width());
+ AddIntegerValue(properties, kIOSurfaceHeight, size.height());
+ AddIntegerValue(properties,
+ kIOSurfaceBytesPerElement,
+ GpuMemoryBufferImpl::BytesPerPixel(format));
+ AddIntegerValue(properties,
+ kIOSurfacePixelFormat,
+ GpuMemoryBufferImplIOSurface::PixelFormat(format));
+ // TODO(reveman): Remove this when using a mach_port_t to transfer
+ // IOSurface to browser and renderer process. crbug.com/323304
+ AddBooleanValue(properties, kIOSurfaceIsGlobal, true);
+
+ base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceCreate(properties));
+ if (!io_surface)
+ return gfx::GpuMemoryBufferHandle();
+
+ IOSurfaceMapKey key(id, client_id);
+ DCHECK(io_surfaces_.find(key) == io_surfaces_.end());
+ io_surfaces_[key] = io_surface;
+
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::IO_SURFACE_BUFFER;
+ handle.id = id;
+ handle.io_surface_id = IOSurfaceGetID(io_surface);
+ return handle;
+}
+
+void GpuMemoryBufferFactoryIOSurface::DestroyGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ int client_id) {
+ IOSurfaceMapKey key(id, client_id);
+ IOSurfaceMap::iterator it = io_surfaces_.find(key);
+ if (it != io_surfaces_.end())
+ io_surfaces_.erase(it);
+}
+
+scoped_refptr<gfx::GLImage>
+GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id) {
+ IOSurfaceMapKey key(id, client_id);
+ IOSurfaceMap::iterator it = io_surfaces_.find(key);
+ if (it == io_surfaces_.end())
+ return scoped_refptr<gfx::GLImage>();
+
+ scoped_refptr<gfx::GLImageIOSurface> image(new gfx::GLImageIOSurface(size));
+ if (!image->Initialize(it->second.get()))
+ return scoped_refptr<gfx::GLImage>();
+
+ return image;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h
new file mode 100644
index 00000000000..1ee16ef582f
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_IO_SURFACE_H_
+#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_IO_SURFACE_H_
+
+#include <IOSurface/IOSurfaceAPI.h>
+
+#include "base/containers/hash_tables.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+namespace gfx {
+class GLImage;
+}
+
+namespace content {
+
+class GpuMemoryBufferFactoryIOSurface {
+ public:
+ GpuMemoryBufferFactoryIOSurface();
+ ~GpuMemoryBufferFactoryIOSurface();
+
+ // Creates a IOSurface backed GPU memory buffer with |size| and
+ // |internalformat|. A valid handle is returned on success.
+ gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id);
+
+ // Destroy a previously created GPU memory buffer.
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id);
+
+ // Creates a GLImage instance for a GPU memory buffer.
+ scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ int client_id);
+
+ private:
+ typedef std::pair<int, int> IOSurfaceMapKey;
+ typedef base::hash_map<IOSurfaceMapKey, base::ScopedCFTypeRef<IOSurfaceRef>>
+ IOSurfaceMap;
+ IOSurfaceMap io_surfaces_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_IO_SURFACE_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_linux.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_linux.cc
new file mode 100644
index 00000000000..67465514533
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_linux.cc
@@ -0,0 +1,67 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory.h"
+
+#include "base/logging.h"
+#include "gpu/command_buffer/service/image_factory.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_shared_memory.h"
+
+namespace content {
+namespace {
+
+class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory,
+ public gpu::ImageFactory {
+ public:
+ // Overridden from GpuMemoryBufferFactory:
+ gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id) override {
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) override {
+ NOTREACHED();
+ }
+ gpu::ImageFactory* AsImageFactory() override { return this; }
+
+ // Overridden from gpu::ImageFactory:
+ scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ unsigned internalformat,
+ int client_id) override {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_refptr<gfx::GLImageSharedMemory> image(
+ new gfx::GLImageSharedMemory(size, internalformat));
+ if (!image->Initialize(handle, format))
+ return NULL;
+
+ return image;
+ }
+ default:
+ NOTREACHED();
+ return scoped_refptr<gfx::GLImage>();
+ }
+ }
+};
+
+} // namespace
+
+// static
+scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::Create() {
+ return make_scoped_ptr<GpuMemoryBufferFactory>(
+ new GpuMemoryBufferFactoryImpl);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_mac.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_mac.cc
new file mode 100644
index 00000000000..aa04b274b69
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_mac.cc
@@ -0,0 +1,88 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory.h"
+
+#include "base/logging.h"
+#include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
+#include "gpu/command_buffer/service/image_factory.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_shared_memory.h"
+
+namespace content {
+namespace {
+
+class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory,
+ public gpu::ImageFactory {
+ public:
+ // Overridden from GpuMemoryBufferFactory:
+ gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id) override {
+ switch (type) {
+ case gfx::IO_SURFACE_BUFFER:
+ return io_surface_factory_.CreateGpuMemoryBuffer(
+ id, size, format, client_id);
+ default:
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+ }
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) override {
+ switch (type) {
+ case gfx::IO_SURFACE_BUFFER:
+ io_surface_factory_.DestroyGpuMemoryBuffer(id, client_id);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ gpu::ImageFactory* AsImageFactory() override { return this; }
+
+ // Overridden from gpu::ImageFactory:
+ scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ unsigned internalformat,
+ int client_id) override {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_refptr<gfx::GLImageSharedMemory> image(
+ new gfx::GLImageSharedMemory(size, internalformat));
+ if (!image->Initialize(handle, format))
+ return NULL;
+
+ return image;
+ }
+ case gfx::IO_SURFACE_BUFFER: {
+ return io_surface_factory_.CreateImageForGpuMemoryBuffer(
+ handle.id, size, format, client_id);
+ }
+ default:
+ NOTREACHED();
+ return scoped_refptr<gfx::GLImage>();
+ }
+ }
+
+ private:
+ GpuMemoryBufferFactoryIOSurface io_surface_factory_;
+};
+
+} // namespace
+
+// static
+scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::Create() {
+ return make_scoped_ptr<GpuMemoryBufferFactory>(
+ new GpuMemoryBufferFactoryImpl);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone.cc
new file mode 100644
index 00000000000..f2a296e72b6
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory.h"
+
+#include "base/logging.h"
+#include "gpu/command_buffer/service/image_factory.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_shared_memory.h"
+#include "ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h"
+
+namespace content {
+namespace {
+
+class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory,
+ public gpu::ImageFactory {
+ public:
+ // Overridden from GpuMemoryBufferFactory:
+ virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id) override {
+ switch (type) {
+ case gfx::OZONE_NATIVE_BUFFER: {
+ if (!ozone_buffer_factory_.CreateGpuMemoryBuffer(
+ id, size, format, usage, client_id)) {
+ return gfx::GpuMemoryBufferHandle();
+ }
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::OZONE_NATIVE_BUFFER;
+ handle.id = id;
+ return handle;
+ }
+ default:
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+ }
+ virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) override {
+ switch (type) {
+ case gfx::OZONE_NATIVE_BUFFER:
+ ozone_buffer_factory_.DestroyGpuMemoryBuffer(id, client_id);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+ virtual gpu::ImageFactory* AsImageFactory() override { return this; }
+
+ // Overridden from gpu::ImageFactory:
+ virtual scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ unsigned internalformat,
+ int client_id) override {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_refptr<gfx::GLImageSharedMemory> image(
+ new gfx::GLImageSharedMemory(size, internalformat));
+ if (!image->Initialize(handle, format))
+ return NULL;
+
+ return image;
+ }
+ case gfx::OZONE_NATIVE_BUFFER:
+ return ozone_buffer_factory_.CreateImageForGpuMemoryBuffer(
+ handle.id, size, format, internalformat, client_id);
+ default:
+ NOTREACHED();
+ return scoped_refptr<gfx::GLImage>();
+ }
+ }
+
+ private:
+ ui::GpuMemoryBufferFactoryOzoneNativeBuffer ozone_buffer_factory_;
+};
+
+} // namespace
+
+// static
+scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::Create() {
+ return make_scoped_ptr<GpuMemoryBufferFactory>(
+ new GpuMemoryBufferFactoryImpl);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc
new file mode 100644
index 00000000000..91b81cbd651
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc
@@ -0,0 +1,78 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
+
+#include "content/common/android/surface_texture_manager.h"
+#include "ui/gl/android/surface_texture.h"
+#include "ui/gl/gl_image_surface_texture.h"
+
+namespace content {
+
+GpuMemoryBufferFactorySurfaceTexture::GpuMemoryBufferFactorySurfaceTexture() {
+}
+
+GpuMemoryBufferFactorySurfaceTexture::~GpuMemoryBufferFactorySurfaceTexture() {
+}
+
+gfx::GpuMemoryBufferHandle
+GpuMemoryBufferFactorySurfaceTexture::CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ unsigned internalformat,
+ int client_id) {
+ // Note: this needs to be 0 as the surface texture implemenation will take
+ // ownership of the texture and call glDeleteTextures when the GPU service
+ // attaches the surface texture to a real texture id. glDeleteTextures
+ // silently ignores 0.
+ const int kDummyTextureId = 0;
+ scoped_refptr<gfx::SurfaceTexture> surface_texture =
+ gfx::SurfaceTexture::Create(kDummyTextureId);
+ if (!surface_texture.get())
+ return gfx::GpuMemoryBufferHandle();
+
+ SurfaceTextureManager::GetInstance()->RegisterSurfaceTexture(
+ id, client_id, surface_texture.get());
+
+ SurfaceTextureMapKey key(id, client_id);
+ DCHECK(surface_textures_.find(key) == surface_textures_.end());
+ surface_textures_[key] = surface_texture;
+
+ gfx::GpuMemoryBufferHandle handle;
+ handle.type = gfx::SURFACE_TEXTURE_BUFFER;
+ handle.id = id;
+ return handle;
+}
+
+void GpuMemoryBufferFactorySurfaceTexture::DestroyGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ int client_id) {
+ SurfaceTextureMapKey key(id, client_id);
+ SurfaceTextureMap::iterator it = surface_textures_.find(key);
+ if (it != surface_textures_.end())
+ surface_textures_.erase(it);
+
+ SurfaceTextureManager::GetInstance()->UnregisterSurfaceTexture(id, client_id);
+}
+
+scoped_refptr<gfx::GLImage>
+GpuMemoryBufferFactorySurfaceTexture::CreateImageForGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ unsigned internalformat,
+ int client_id) {
+ SurfaceTextureMapKey key(id, client_id);
+ SurfaceTextureMap::iterator it = surface_textures_.find(key);
+ if (it == surface_textures_.end())
+ return scoped_refptr<gfx::GLImage>();
+
+ scoped_refptr<gfx::GLImageSurfaceTexture> image(
+ new gfx::GLImageSurfaceTexture(size));
+ if (!image->Initialize(it->second.get()))
+ return scoped_refptr<gfx::GLImage>();
+
+ return image;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h
new file mode 100644
index 00000000000..c9103eda4fd
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h
@@ -0,0 +1,51 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_SURFACE_TEXTURE_H_
+#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_SURFACE_TEXTURE_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+namespace gfx {
+class GLImage;
+class SurfaceTexture;
+}
+
+namespace content {
+
+class GpuMemoryBufferFactorySurfaceTexture {
+ public:
+ GpuMemoryBufferFactorySurfaceTexture();
+ ~GpuMemoryBufferFactorySurfaceTexture();
+
+ // Creates a SurfaceTexture backed GPU memory buffer with |size| and
+ // |internalformat|. A valid handle is returned on success.
+ gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ unsigned internalformat,
+ int client_id);
+
+ // Destroy a previously created GPU memory buffer.
+ void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id);
+
+ // Creates a GLImage instance for a GPU memory buffer.
+ scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ unsigned internalformat,
+ int client_id);
+
+ private:
+ typedef std::pair<int, int> SurfaceTextureMapKey;
+ typedef base::hash_map<SurfaceTextureMapKey,
+ scoped_refptr<gfx::SurfaceTexture>> SurfaceTextureMap;
+ SurfaceTextureMap surface_textures_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_SURFACE_TEXTURE_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_win.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_win.cc
new file mode 100644
index 00000000000..618ecc5ed24
--- /dev/null
+++ b/chromium/content/common/gpu/gpu_memory_buffer_factory_win.cc
@@ -0,0 +1,67 @@
+// Copyright 2014 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 "content/common/gpu/gpu_memory_buffer_factory.h"
+
+#include "base/logging.h"
+#include "gpu/command_buffer/service/image_factory.h"
+#include "ui/gl/gl_image.h"
+#include "ui/gl/gl_image_shared_memory.h"
+
+namespace content {
+namespace {
+
+class GpuMemoryBufferFactoryImpl : public GpuMemoryBufferFactory,
+ public gpu::ImageFactory {
+ public:
+ // Overridden from GpuMemoryBufferFactory:
+ virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
+ gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ gfx::GpuMemoryBuffer::Usage usage,
+ int client_id) override {
+ NOTREACHED();
+ return gfx::GpuMemoryBufferHandle();
+ }
+ virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferType type,
+ gfx::GpuMemoryBufferId id,
+ int client_id) override {
+ NOTREACHED();
+ }
+ virtual gpu::ImageFactory* AsImageFactory() override { return this; }
+
+ // Overridden from gpu::ImageFactory:
+ virtual scoped_refptr<gfx::GLImage> CreateImageForGpuMemoryBuffer(
+ const gfx::GpuMemoryBufferHandle& handle,
+ const gfx::Size& size,
+ gfx::GpuMemoryBuffer::Format format,
+ unsigned internalformat,
+ int client_id) override {
+ switch (handle.type) {
+ case gfx::SHARED_MEMORY_BUFFER: {
+ scoped_refptr<gfx::GLImageSharedMemory> image(
+ new gfx::GLImageSharedMemory(size, internalformat));
+ if (!image->Initialize(handle, format))
+ return NULL;
+
+ return image;
+ }
+ default:
+ NOTREACHED();
+ return scoped_refptr<gfx::GLImage>();
+ }
+ }
+};
+
+} // namespace
+
+// static
+scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::Create() {
+ return make_scoped_ptr<GpuMemoryBufferFactory>(
+ new GpuMemoryBufferFactoryImpl);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_manager.cc b/chromium/content/common/gpu/gpu_memory_manager.cc
index 9a233758f07..b3c98c02168 100644
--- a/chromium/content/common/gpu/gpu_memory_manager.cc
+++ b/chromium/content/common/gpu/gpu_memory_manager.cc
@@ -62,11 +62,11 @@ GpuMemoryManager::~GpuMemoryManager() {
void GpuMemoryManager::UpdateAvailableGpuMemory() {
// If the value was overridden on the command line, use the specified value.
static bool client_hard_limit_bytes_overridden =
- CommandLine::ForCurrentProcess()->HasSwitch(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kForceGpuMemAvailableMb);
if (client_hard_limit_bytes_overridden) {
base::StringToUint64(
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kForceGpuMemAvailableMb),
&client_hard_limit_bytes_);
client_hard_limit_bytes_ *= 1024 * 1024;
@@ -106,7 +106,7 @@ void GpuMemoryManager::UpdateAvailableGpuMemory() {
#else
// Ignore what the system said and give all clients the same maximum
// allocation on desktop platforms.
- client_hard_limit_bytes_ = 256 * 1024 * 1024;
+ client_hard_limit_bytes_ = 512 * 1024 * 1024;
#endif
}
diff --git a/chromium/content/common/gpu/gpu_memory_manager_unittest.cc b/chromium/content/common/gpu/gpu_memory_manager_unittest.cc
index cf9e7cfffe9..18ebce20786 100644
--- a/chromium/content/common/gpu/gpu_memory_manager_unittest.cc
+++ b/chromium/content/common/gpu/gpu_memory_manager_unittest.cc
@@ -12,30 +12,17 @@
using gpu::MemoryAllocation;
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
-template<>
-struct hash<content::GpuMemoryManagerClient*> {
- uint64 operator()(content::GpuMemoryManagerClient* ptr) const {
- return hash<uint64>()(reinterpret_cast<uint64>(ptr));
- }
-};
-} // namespace BASE_HASH_NAMESPACE
-#endif // COMPILER
-
class FakeMemoryTracker : public gpu::gles2::MemoryTracker {
public:
- virtual void TrackMemoryAllocatedChange(
+ void TrackMemoryAllocatedChange(
size_t /* old_size */,
size_t /* new_size */,
- gpu::gles2::MemoryTracker::Pool /* pool */) OVERRIDE {
- }
- virtual bool EnsureGPUMemoryAvailable(size_t /* size_needed */) OVERRIDE {
+ gpu::gles2::MemoryTracker::Pool /* pool */) override {}
+ bool EnsureGPUMemoryAvailable(size_t /* size_needed */) override {
return true;
}
private:
- virtual ~FakeMemoryTracker() {
- }
+ ~FakeMemoryTracker() override {}
};
namespace content {
@@ -110,22 +97,22 @@ class FakeClient : public GpuMemoryManagerClient {
memmgr_->CreateClientState(this, surface_id != 0, visible));
}
- virtual ~FakeClient() {
+ ~FakeClient() override {
client_state_.reset();
tracking_group_.reset();
memory_tracker_ = NULL;
}
- virtual void SetMemoryAllocation(const MemoryAllocation& alloc) OVERRIDE {
+ void SetMemoryAllocation(const MemoryAllocation& alloc) override {
allocation_ = alloc;
ClientAssignmentCollector::AddClientStat(this, alloc);
}
- virtual void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) OVERRIDE {
+ void SuggestHaveFrontBuffer(bool suggest_have_frontbuffer) override {
suggest_have_frontbuffer_ = suggest_have_frontbuffer;
}
- virtual bool GetTotalGpuMemory(uint64* bytes) OVERRIDE {
+ bool GetTotalGpuMemory(uint64* bytes) override {
if (total_gpu_memory_) {
*bytes = total_gpu_memory_;
return true;
@@ -134,15 +121,13 @@ class FakeClient : public GpuMemoryManagerClient {
}
void SetTotalGpuMemory(uint64 bytes) { total_gpu_memory_ = bytes; }
- virtual gpu::gles2::MemoryTracker* GetMemoryTracker() const OVERRIDE {
+ gpu::gles2::MemoryTracker* GetMemoryTracker() const override {
if (share_group_)
return share_group_->GetMemoryTracker();
return memory_tracker_.get();
}
- virtual gfx::Size GetSurfaceSize() const OVERRIDE {
- return surface_size_;
- }
+ gfx::Size GetSurfaceSize() const override { return surface_size_; }
void SetSurfaceSize(gfx::Size size) { surface_size_ = size; }
void SetVisible(bool visible) {
@@ -163,8 +148,7 @@ class GpuMemoryManagerTest : public testing::Test {
memmgr_.TestingDisableScheduleManage();
}
- virtual void SetUp() {
- }
+ void SetUp() override {}
static int32 GenerateUniqueSurfaceId() {
static int32 surface_id_ = 1;
diff --git a/chromium/content/common/gpu/gpu_messages.h b/chromium/content/common/gpu/gpu_messages.h
index 02c3c389ab6..839de2d55a9 100644
--- a/chromium/content/common/gpu/gpu_messages.h
+++ b/chromium/content/common/gpu/gpu_messages.h
@@ -45,7 +45,7 @@
IPC_ENUM_TRAITS_MAX_VALUE(content::CauseForGpuLaunch,
content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM - 1)
IPC_ENUM_TRAITS_MAX_VALUE(content::CreateCommandBufferResult,
- content::CREATE_COMMAND_BUFFER_RESULT_LAST);
+ content::CREATE_COMMAND_BUFFER_RESULT_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuPreference,
gfx::GpuPreferenceLast)
IPC_ENUM_TRAITS_MAX_VALUE(gfx::SurfaceType,
@@ -61,6 +61,12 @@ IPC_ENUM_TRAITS_MAX_VALUE(media::VideoFrame::Format,
IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::VideoCodecProfile,
media::VIDEO_CODEC_PROFILE_MIN,
media::VIDEO_CODEC_PROFILE_MAX)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(gpu::CollectInfoResult,
+ gpu::kCollectInfoNone,
+ gpu::kCollectInfoFatalFailure)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(gpu::VideoCodecProfile,
+ gpu::VIDEO_CODEC_PROFILE_MIN,
+ gpu::VIDEO_CODEC_PROFILE_MAX)
IPC_STRUCT_BEGIN(GPUCreateCommandBufferConfig)
IPC_STRUCT_MEMBER(int32, share_group_id)
@@ -69,45 +75,35 @@ IPC_STRUCT_BEGIN(GPUCreateCommandBufferConfig)
IPC_STRUCT_MEMBER(gfx::GpuPreference, gpu_preference)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
- IPC_STRUCT_MEMBER(int32, surface_id)
- IPC_STRUCT_MEMBER(uint64, surface_handle)
- IPC_STRUCT_MEMBER(int32, route_id)
- IPC_STRUCT_MEMBER(gpu::Mailbox, mailbox)
+IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBuffer_Params)
+ IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferType, type)
+ IPC_STRUCT_MEMBER(int32, id)
IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(float, scale_factor)
- IPC_STRUCT_MEMBER(std::vector<ui::LatencyInfo>, latency_info)
+ IPC_STRUCT_MEMBER(gfx::GpuMemoryBuffer::Format, format)
+ IPC_STRUCT_MEMBER(gfx::GpuMemoryBuffer::Usage, usage)
+ IPC_STRUCT_MEMBER(int32, client_id)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params)
+IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
IPC_STRUCT_MEMBER(int32, surface_id)
IPC_STRUCT_MEMBER(uint64, surface_handle)
IPC_STRUCT_MEMBER(int32, route_id)
- IPC_STRUCT_MEMBER(int, x)
- IPC_STRUCT_MEMBER(int, y)
- IPC_STRUCT_MEMBER(int, width)
- IPC_STRUCT_MEMBER(int, height)
- IPC_STRUCT_MEMBER(gpu::Mailbox, mailbox)
- IPC_STRUCT_MEMBER(gfx::Size, surface_size)
- IPC_STRUCT_MEMBER(float, surface_scale_factor)
+ IPC_STRUCT_MEMBER(gfx::Size, size)
+ IPC_STRUCT_MEMBER(float, scale_factor)
IPC_STRUCT_MEMBER(std::vector<ui::LatencyInfo>, latency_info)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceRelease_Params)
- IPC_STRUCT_MEMBER(int32, surface_id)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(AcceleratedSurfaceMsg_BufferPresented_Params)
- IPC_STRUCT_MEMBER(gpu::Mailbox, mailbox)
- IPC_STRUCT_MEMBER(uint32, sync_point)
#if defined(OS_MACOSX)
+IPC_STRUCT_BEGIN(AcceleratedSurfaceMsg_BufferPresented_Params)
+ // If the browser needs framerate throttling based on GPU back-pressure to be
+ // disabled (e.g, because the NSView isn't visible but tab capture is active),
+ // then this is set to true.
+ IPC_STRUCT_MEMBER(bool, disable_throttling)
+ // If the browser is drawing to the screen, this is the CGL renderer ID of
+ // the GL context that the brower is using.
IPC_STRUCT_MEMBER(int32, renderer_id)
-#endif
-#if defined(OS_WIN)
- IPC_STRUCT_MEMBER(base::TimeTicks, vsync_timebase)
- IPC_STRUCT_MEMBER(base::TimeDelta, vsync_interval)
-#endif
IPC_STRUCT_END()
+#endif
IPC_STRUCT_BEGIN(GPUCommandBufferConsoleMessage)
IPC_STRUCT_MEMBER(int32, id)
@@ -154,8 +150,14 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo::GPUDevice)
IPC_STRUCT_TRAITS_MEMBER(device_string)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(gpu::VideoEncodeAcceleratorSupportedProfile)
+ IPC_STRUCT_TRAITS_MEMBER(profile)
+ IPC_STRUCT_TRAITS_MEMBER(max_resolution)
+ IPC_STRUCT_TRAITS_MEMBER(max_framerate_numerator)
+ IPC_STRUCT_TRAITS_MEMBER(max_framerate_denominator)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo)
- IPC_STRUCT_TRAITS_MEMBER(finalized)
IPC_STRUCT_TRAITS_MEMBER(initialization_time)
IPC_STRUCT_TRAITS_MEMBER(optimus)
IPC_STRUCT_TRAITS_MEMBER(amd_switchable)
@@ -183,24 +185,14 @@ IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo)
IPC_STRUCT_TRAITS_MEMBER(software_rendering)
IPC_STRUCT_TRAITS_MEMBER(direct_rendering)
IPC_STRUCT_TRAITS_MEMBER(sandboxed)
+ IPC_STRUCT_TRAITS_MEMBER(process_crash_count)
+ IPC_STRUCT_TRAITS_MEMBER(basic_info_state)
+ IPC_STRUCT_TRAITS_MEMBER(context_info_state)
#if defined(OS_WIN)
+ IPC_STRUCT_TRAITS_MEMBER(dx_diagnostics_info_state)
IPC_STRUCT_TRAITS_MEMBER(dx_diagnostics)
#endif
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::Capabilities)
- IPC_STRUCT_TRAITS_MEMBER(post_sub_buffer)
- IPC_STRUCT_TRAITS_MEMBER(fast_npot_mo8_textures)
- IPC_STRUCT_TRAITS_MEMBER(egl_image_external)
- IPC_STRUCT_TRAITS_MEMBER(texture_format_bgra8888)
- IPC_STRUCT_TRAITS_MEMBER(texture_format_etc1)
- IPC_STRUCT_TRAITS_MEMBER(texture_rectangle)
- IPC_STRUCT_TRAITS_MEMBER(iosurface)
- IPC_STRUCT_TRAITS_MEMBER(texture_usage)
- IPC_STRUCT_TRAITS_MEMBER(texture_storage)
- IPC_STRUCT_TRAITS_MEMBER(discard_framebuffer)
- IPC_STRUCT_TRAITS_MEMBER(sync_query)
- IPC_STRUCT_TRAITS_MEMBER(map_image)
+ IPC_STRUCT_TRAITS_MEMBER(video_encode_accelerator_supported_profiles)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::GPUVideoMemoryUsageStats::ProcessStats)
@@ -247,9 +239,10 @@ IPC_MESSAGE_CONTROL0(GpuMsg_Initialize)
// GpuHostMsg_ChannelEstablished message. The client ID is passed so that
// the GPU process reuses an existing channel to that process if it exists.
// This ID is a unique opaque identifier generated by the browser process.
-IPC_MESSAGE_CONTROL2(GpuMsg_EstablishChannel,
+IPC_MESSAGE_CONTROL3(GpuMsg_EstablishChannel,
int /* client_id */,
- bool /* share_context */)
+ bool /* share_context */,
+ bool /* allow_future_sync_points */)
// Tells the GPU process to close the channel identified by IPC channel
// handle. If no channel can be identified, do nothing.
@@ -265,29 +258,15 @@ IPC_MESSAGE_CONTROL5(GpuMsg_CreateViewCommandBuffer,
GPUCreateCommandBufferConfig, /* init_params */
int32 /* route_id */)
-// Tells the GPU process to create a new image from a window. Images
-// can be bound to textures using CHROMIUM_texture_from_image.
-IPC_MESSAGE_CONTROL3(GpuMsg_CreateImage,
- gfx::PluginWindowHandle, /* window */
- int32, /* client_id */
- int32 /* image_id */)
-
-// Tells the GPU process to delete image.
-IPC_MESSAGE_CONTROL3(GpuMsg_DeleteImage,
- int32, /* client_id */
- int32, /* image_id */
- int32 /* sync_point */)
-
-// Tells the GPU process to create a new gpu memory buffer for |handle|.
-IPC_MESSAGE_CONTROL4(GpuMsg_CreateGpuMemoryBuffer,
- gfx::GpuMemoryBufferHandle, /* handle */
- gfx::Size, /* size */
- unsigned, /* internalformat */
- unsigned /* usage */)
+// Tells the GPU process to create a new gpu memory buffer.
+IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBuffer,
+ GpuMsg_CreateGpuMemoryBuffer_Params)
// Tells the GPU process to destroy buffer.
-IPC_MESSAGE_CONTROL2(GpuMsg_DestroyGpuMemoryBuffer,
- gfx::GpuMemoryBufferHandle, /* handle */
+IPC_MESSAGE_CONTROL4(GpuMsg_DestroyGpuMemoryBuffer,
+ gfx::GpuMemoryBufferType, /* type */
+ gfx::GpuMemoryBufferId, /* id */
+ int32, /* client_id */
int32 /* sync_point */)
// Tells the GPU process to create a context for collecting graphics card
@@ -297,12 +276,12 @@ IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo)
// Tells the GPU process to report video_memory information for the task manager
IPC_MESSAGE_CONTROL0(GpuMsg_GetVideoMemoryUsageStats)
+#if defined(OS_MACOSX)
// Tells the GPU process that the browser process has handled the swap
-// buffers or post sub-buffer request. A non-zero sync point means
-// that we should wait for the sync point. The surface_handle identifies
-// that buffer that has finished presented, i.e. the buffer being returned.
+// buffers or post sub-buffer request.
IPC_MESSAGE_ROUTED1(AcceleratedSurfaceMsg_BufferPresented,
AcceleratedSurfaceMsg_BufferPresented_Params)
+#endif
// Tells the GPU process to wake up the GPU because we're about to draw.
IPC_MESSAGE_ROUTED0(AcceleratedSurfaceMsg_WakeUpGpu)
@@ -319,6 +298,9 @@ IPC_MESSAGE_CONTROL0(GpuMsg_Hang)
// Tells the GPU process to disable the watchdog thread.
IPC_MESSAGE_CONTROL0(GpuMsg_DisableWatchdog)
+// Tells the GPU process that the browser has seen a GPU switch.
+IPC_MESSAGE_CONTROL0(GpuMsg_GpuSwitched)
+
//------------------------------------------------------------------------------
// GPU Host Messages
// These are messages to the browser.
@@ -372,10 +354,6 @@ IPC_MESSAGE_CONTROL1(GpuHostMsg_CommandBufferCreated,
IPC_MESSAGE_CONTROL1(GpuHostMsg_DestroyCommandBuffer,
int32 /* surface_id */)
-// Response from GPU to a GpuMsg_CreateImage message.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_ImageCreated,
- gfx::Size /* size */)
-
// Response from GPU to a GpuMsg_CreateGpuMemoryBuffer message.
IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryBufferCreated,
gfx::GpuMemoryBufferHandle /* handle */)
@@ -399,32 +377,10 @@ IPC_MESSAGE_CONTROL2(GpuHostMsg_AcceleratedSurfaceInitialized,
int32 /* surface_id */,
int32 /* route_id */)
-// Tells the browser that a frame with the specific latency info was drawn to
-// the screen
-IPC_MESSAGE_CONTROL1(GpuHostMsg_FrameDrawn,
- std::vector<ui::LatencyInfo> /* latency_info */)
-
// Same as above with a rect of the part of the surface that changed.
IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
-// This message notifies the browser process that the renderer
-// swapped a portion of the buffers associated with the given "window", which
-// should cause the browser to redraw the compositor's contents.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfacePostSubBuffer,
- GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params)
-
-// Tells the browser to release whatever resources are associated with
-// the given surface. The browser must send an ACK once this operation
-// is complete.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceRelease,
- GpuHostMsg_AcceleratedSurfaceRelease_Params)
-
-// Tells the browser to release resources for the given surface until the next
-// time swap buffers or post sub buffer is sent.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceSuspend,
- int32 /* surface_id */)
-
// Tells the browser about updated parameters for vsync alignment.
IPC_MESSAGE_CONTROL3(GpuHostMsg_UpdateVSyncParameters,
int32 /* surface_id */,
@@ -534,14 +490,11 @@ IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_WaitForGetOffsetInRange,
// Asynchronously synchronize the put and get offsets of both processes.
// Caller passes its current put offset. Current state (including get offset)
-// is returned in shared memory.
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_AsyncFlush,
+// is returned in shared memory. The input latency info for the current
+// frame is also sent to the GPU process.
+IPC_MESSAGE_ROUTED3(GpuCommandBufferMsg_AsyncFlush,
int32 /* put_offset */,
- uint32 /* flush_count */)
-
-// Sends information about the latency of the current frame to the GPU
-// process.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetLatencyInfo,
+ uint32 /* flush_count */,
std::vector<ui::LatencyInfo> /* latency_info */)
// Asynchronously process any commands known to the GPU process. This is only
@@ -589,13 +542,9 @@ IPC_SYNC_MESSAGE_ROUTED5_1(GpuCommandBufferMsg_CreateVideoEncoder,
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_Destroyed,
gpu::error::ContextLostReason /* reason */)
-// Request that the GPU process reply with the given message. Reply may be
-// delayed.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_Echo,
- IPC::Message /* reply */)
-
-// Response to a GpuChannelMsg_Echo message.
-IPC_MESSAGE_ROUTED0(GpuCommandBufferMsg_EchoAck)
+// Tells the browser that SwapBuffers returned and passes latency info
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SwapBuffersCompleted,
+ std::vector<ui::LatencyInfo> /* latency_info */)
// Send to stub on surface visibility change.
IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SetSurfaceVisible, bool /* visible */)
@@ -613,7 +562,8 @@ IPC_MESSAGE_ROUTED1(
// can be expected to be reasonably fast, but the sync point is actually
// retired in order with respect to the other calls. The sync point is shared
// across channels.
-IPC_SYNC_MESSAGE_ROUTED0_1(GpuCommandBufferMsg_InsertSyncPoint,
+IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_InsertSyncPoint,
+ bool /* retire */,
uint32 /* sync_point */)
// Retires the sync point. Note: this message is not sent explicitly by the
@@ -639,17 +589,17 @@ IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SignalQuery,
uint32 /* query */,
uint32 /* signal_id */)
-// Register an existing gpu memory buffer. The id that can be
-// used to identify the gpu memory buffer from a command buffer.
-IPC_MESSAGE_ROUTED5(GpuCommandBufferMsg_RegisterGpuMemoryBuffer,
+// Create an image from an existing gpu memory buffer. The id that can be
+// used to identify the image from a command buffer.
+IPC_MESSAGE_ROUTED5(GpuCommandBufferMsg_CreateImage,
int32 /* id */,
gfx::GpuMemoryBufferHandle /* gpu_memory_buffer */,
- uint32 /* width */,
- uint32 /* height */,
+ gfx::Size /* size */,
+ gfx::GpuMemoryBuffer::Format /* format */,
uint32 /* internalformat */)
-// Destroy a previously created gpu memory buffer.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyGpuMemoryBuffer,
+// Destroy a previously created image.
+IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyImage,
int32 /* id */)
// Attaches an external image stream to the client texture.
@@ -711,9 +661,10 @@ IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
int32) /* Picture buffer ID */
// Decoder reports that a picture is ready.
-IPC_MESSAGE_ROUTED2(AcceleratedVideoDecoderHostMsg_PictureReady,
- int32, /* Picture buffer ID */
- int32) /* Bitstream buffer ID */
+IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderHostMsg_PictureReady,
+ int32, /* Picture buffer ID */
+ int32, /* Bitstream buffer ID */
+ gfx::Rect) /* Visible rectangle */
// Confirm decoder has been flushed.
IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_FlushDone)
diff --git a/chromium/content/common/gpu/image_transport_surface.cc b/chromium/content/common/gpu/image_transport_surface.cc
index 19b672b9784..c08477225d8 100644
--- a/chromium/content/common/gpu/image_transport_surface.cc
+++ b/chromium/content/common/gpu/image_transport_surface.cc
@@ -12,17 +12,13 @@
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/null_transport_surface.h"
#include "content/common/gpu/sync_point_manager.h"
-#include "content/common/gpu/texture_image_transport_surface.h"
#include "gpu/command_buffer/service/gpu_scheduler.h"
#include "ui/gfx/vsync_provider.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
-#if defined(OS_WIN)
-#include "ui/base/win/shell.h"
-#endif
-
namespace content {
ImageTransportSurface::ImageTransportSurface() {}
@@ -34,10 +30,15 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
GpuCommandBufferStub* stub,
const gfx::GLSurfaceHandle& handle) {
scoped_refptr<gfx::GLSurface> surface;
- if (handle.transport_type == gfx::TEXTURE_TRANSPORT)
- surface = new TextureImageTransportSurface(manager, stub, handle);
- else
+ if (handle.transport_type == gfx::NULL_TRANSPORT) {
+#if defined(OS_ANDROID)
+ surface = CreateTransportSurface(manager, stub, handle);
+#else
+ surface = new NullTransportSurface(manager, stub, handle);
+#endif
+ } else {
surface = CreateNativeSurface(manager, stub, handle);
+ }
if (!surface.get() || !surface->Initialize())
return NULL;
@@ -83,13 +84,13 @@ bool ImageTransportHelper::Initialize() {
return true;
}
-void ImageTransportHelper::Destroy() {}
-
bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
+#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
OnBufferPresented)
+#endif
IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_WakeUpGpu, OnWakeUpGpu);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -108,19 +109,6 @@ void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
}
-void ImageTransportHelper::SendAcceleratedSurfacePostSubBuffer(
- GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params) {
- params.surface_id = stub_->surface_id();
- params.route_id = route_id_;
- manager_->Send(new GpuHostMsg_AcceleratedSurfacePostSubBuffer(params));
-}
-
-void ImageTransportHelper::SendAcceleratedSurfaceRelease() {
- GpuHostMsg_AcceleratedSurfaceRelease_Params params;
- params.surface_id = stub_->surface_id();
- manager_->Send(new GpuHostMsg_AcceleratedSurfaceRelease(params));
-}
-
void ImageTransportHelper::SendUpdateVSyncParameters(
base::TimeTicks timebase, base::TimeDelta interval) {
manager_->Send(new GpuHostMsg_UpdateVSyncParameters(stub_->surface_id(),
@@ -128,9 +116,9 @@ void ImageTransportHelper::SendUpdateVSyncParameters(
interval));
}
-void ImageTransportHelper::SendLatencyInfo(
+void ImageTransportHelper::SwapBuffersCompleted(
const std::vector<ui::LatencyInfo>& latency_info) {
- manager_->Send(new GpuHostMsg_FrameDrawn(latency_info));
+ stub_->SwapBuffersCompleted(latency_info);
}
void ImageTransportHelper::SetScheduled(bool is_scheduled) {
@@ -161,24 +149,12 @@ bool ImageTransportHelper::MakeCurrent() {
}
void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
-#if defined(OS_WIN)
- // If Aero Glass is enabled, then the renderer will handle ratelimiting and
- // there's no tearing, so waiting for vsync is unnecessary.
- if (ui::win::IsAeroGlassEnabled()) {
- context->SetSwapInterval(0);
- return;
- }
-#endif
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync))
context->SetSwapInterval(0);
else
context->SetSwapInterval(1);
}
-void ImageTransportHelper::Suspend() {
- manager_->Send(new GpuHostMsg_AcceleratedSurfaceSuspend(stub_->surface_id()));
-}
-
gpu::GpuScheduler* ImageTransportHelper::Scheduler() {
if (!stub_.get())
return NULL;
@@ -191,10 +167,12 @@ gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
return stub_->decoder();
}
+#if defined(OS_MACOSX)
void ImageTransportHelper::OnBufferPresented(
const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
surface_->OnBufferPresented(params);
}
+#endif
void ImageTransportHelper::OnWakeUpGpu() {
surface_->WakeUpGpu();
@@ -232,7 +210,6 @@ bool PassThroughImageTransportSurface::Initialize() {
}
void PassThroughImageTransportSurface::Destroy() {
- helper_->Destroy();
GLSurfaceAdapter::Destroy();
}
@@ -246,13 +223,17 @@ bool PassThroughImageTransportSurface::SwapBuffers() {
// GetVsyncValues before SwapBuffers to work around Mali driver bug:
// crbug.com/223558.
SendVSyncUpdateIfAvailable();
+ for (size_t i = 0; i < latency_info_.size(); ++i) {
+ latency_info_[i].AddLatencyNumber(
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0);
+ }
bool result = gfx::GLSurfaceAdapter::SwapBuffers();
for (size_t i = 0; i < latency_info_.size(); i++) {
latency_info_[i].AddLatencyNumber(
ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
}
- helper_->SendLatencyInfo(latency_info_);
+ helper_->SwapBuffersCompleted(latency_info_);
latency_info_.clear();
return result;
}
@@ -266,7 +247,7 @@ bool PassThroughImageTransportSurface::PostSubBuffer(
ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0);
}
- helper_->SendLatencyInfo(latency_info_);
+ helper_->SwapBuffersCompleted(latency_info_);
latency_info_.clear();
return result;
}
@@ -279,10 +260,12 @@ bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
return true;
}
+#if defined(OS_MACOSX)
void PassThroughImageTransportSurface::OnBufferPresented(
const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
NOTREACHED();
}
+#endif
void PassThroughImageTransportSurface::OnResize(gfx::Size size,
float scale_factor) {
@@ -294,7 +277,7 @@ gfx::Size PassThroughImageTransportSurface::GetSize() {
}
void PassThroughImageTransportSurface::WakeUpGpu() {
- NOTIMPLEMENTED();
+ NOTREACHED();
}
PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
diff --git a/chromium/content/common/gpu/image_transport_surface.h b/chromium/content/common/gpu/image_transport_surface.h
index 16dfa9603a9..fea2d4f0980 100644
--- a/chromium/content/common/gpu/image_transport_surface.h
+++ b/chromium/content/common/gpu/image_transport_surface.h
@@ -23,7 +23,6 @@
struct AcceleratedSurfaceMsg_BufferPresented_Params;
struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-struct GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params;
namespace gfx {
class GLSurface;
@@ -58,8 +57,10 @@ class ImageTransportSurface {
public:
ImageTransportSurface();
+#if defined(OS_MACOSX)
virtual void OnBufferPresented(
const AcceleratedSurfaceMsg_BufferPresented_Params& params) = 0;
+#endif
virtual void OnResize(gfx::Size size, float scale_factor) = 0;
virtual void SetLatencyInfo(
const std::vector<ui::LatencyInfo>& latency_info) = 0;
@@ -93,6 +94,13 @@ class ImageTransportSurface {
GpuCommandBufferStub* stub,
const gfx::GLSurfaceHandle& handle);
+#if defined(OS_ANDROID)
+ static scoped_refptr<gfx::GLSurface> CreateTransportSurface(
+ GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ const gfx::GLSurfaceHandle& handle);
+#endif
+
DISALLOW_COPY_AND_ASSIGN(ImageTransportSurface);
};
@@ -105,25 +113,21 @@ class ImageTransportHelper
GpuChannelManager* manager,
GpuCommandBufferStub* stub,
gfx::PluginWindowHandle handle);
- virtual ~ImageTransportHelper();
+ ~ImageTransportHelper() override;
bool Initialize();
- void Destroy();
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Helper send functions. Caller fills in the surface specific params
// like size and surface id. The helper fills in the rest.
void SendAcceleratedSurfaceBuffersSwapped(
GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params);
- void SendAcceleratedSurfacePostSubBuffer(
- GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params);
- void SendAcceleratedSurfaceRelease();
void SendUpdateVSyncParameters(
base::TimeTicks timebase, base::TimeDelta interval);
- void SendLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
+ void SwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info);
// Whether or not we should execute more commands.
void SetScheduled(bool is_scheduled);
@@ -139,8 +143,6 @@ class ImageTransportHelper
// Set the default swap interval on the surface.
static void SetSwapInterval(gfx::GLContext* context);
- void Suspend();
-
GpuChannelManager* manager() const { return manager_; }
GpuCommandBufferStub* stub() const { return stub_.get(); }
@@ -149,8 +151,10 @@ class ImageTransportHelper
gpu::gles2::GLES2Decoder* Decoder();
// IPC::Message handlers.
+#if defined(OS_MACOSX)
void OnBufferPresented(
const AcceleratedSurfaceMsg_BufferPresented_Params& params);
+#endif
void OnWakeUpGpu();
// Backbuffer resize callback.
@@ -180,23 +184,25 @@ class PassThroughImageTransportSurface
gfx::GLSurface* surface);
// GLSurface implementation.
- virtual bool Initialize() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool SwapBuffers() OVERRIDE;
- virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
- virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
+ bool Initialize() override;
+ void Destroy() override;
+ bool SwapBuffers() override;
+ bool PostSubBuffer(int x, int y, int width, int height) override;
+ bool OnMakeCurrent(gfx::GLContext* context) override;
// ImageTransportSurface implementation.
- virtual void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
- virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
- virtual gfx::Size GetSize() OVERRIDE;
- virtual void SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) OVERRIDE;
- virtual void WakeUpGpu() OVERRIDE;
+#if defined(OS_MACOSX)
+ void OnBufferPresented(
+ const AcceleratedSurfaceMsg_BufferPresented_Params& params) override;
+#endif
+ void OnResize(gfx::Size size, float scale_factor) override;
+ gfx::Size GetSize() override;
+ void SetLatencyInfo(
+ const std::vector<ui::LatencyInfo>& latency_info) override;
+ void WakeUpGpu() override;
protected:
- virtual ~PassThroughImageTransportSurface();
+ ~PassThroughImageTransportSurface() override;
// If updated vsync parameters can be determined, send this information to
// the browser.
diff --git a/chromium/content/common/gpu/image_transport_surface_android.cc b/chromium/content/common/gpu/image_transport_surface_android.cc
index 5fc9e51605f..a2cadd065ac 100644
--- a/chromium/content/common/gpu/image_transport_surface_android.cc
+++ b/chromium/content/common/gpu/image_transport_surface_android.cc
@@ -10,7 +10,7 @@
#include "content/common/gpu/gpu_channel_manager.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "content/common/gpu/gpu_surface_lookup.h"
-#include "content/common/gpu/image_transport_surface.h"
+#include "content/common/gpu/null_transport_surface.h"
#include "content/public/common/content_switches.h"
#include "ui/gl/gl_surface_egl.h"
@@ -31,19 +31,16 @@ void DidAccessGpu() {
}
class ImageTransportSurfaceAndroid
- : public PassThroughImageTransportSurface,
+ : public NullTransportSurface,
public base::SupportsWeakPtr<ImageTransportSurfaceAndroid> {
public:
ImageTransportSurfaceAndroid(GpuChannelManager* manager,
GpuCommandBufferStub* stub,
- gfx::GLSurface* surface,
- uint32 parent_client_id);
+ const gfx::GLSurfaceHandle& handle);
// gfx::GLSurface implementation.
- virtual bool Initialize() OVERRIDE;
- virtual bool SwapBuffers() OVERRIDE;
- virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
- virtual void WakeUpGpu() OVERRIDE;
+ virtual bool OnMakeCurrent(gfx::GLContext* context) override;
+ virtual void WakeUpGpu() override;
protected:
virtual ~ImageTransportSurfaceAndroid();
@@ -52,7 +49,6 @@ class ImageTransportSurfaceAndroid
void ScheduleWakeUp();
void DoWakeUpGpu();
- uint32 parent_client_id_;
base::TimeTicks begin_wake_up_time_;
};
@@ -63,7 +59,7 @@ class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
gfx::GLSurface* surface);
// gfx::GLSurface implementation.
- virtual bool SwapBuffers() OVERRIDE;
+ virtual bool SwapBuffers() override;
protected:
virtual ~DirectSurfaceAndroid();
@@ -75,41 +71,16 @@ class DirectSurfaceAndroid : public PassThroughImageTransportSurface {
ImageTransportSurfaceAndroid::ImageTransportSurfaceAndroid(
GpuChannelManager* manager,
GpuCommandBufferStub* stub,
- gfx::GLSurface* surface,
- uint32 parent_client_id)
- : PassThroughImageTransportSurface(manager, stub, surface),
- parent_client_id_(parent_client_id) {}
+ const gfx::GLSurfaceHandle& handle)
+ : NullTransportSurface(manager, stub, handle) {}
ImageTransportSurfaceAndroid::~ImageTransportSurfaceAndroid() {}
-bool ImageTransportSurfaceAndroid::Initialize() {
- if (!surface())
- return false;
-
- if (!PassThroughImageTransportSurface::Initialize())
- return false;
-
- GpuChannel* parent_channel =
- GetHelper()->manager()->LookupChannel(parent_client_id_);
- if (parent_channel) {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
- GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
- }
-
- return true;
-}
-
bool ImageTransportSurfaceAndroid::OnMakeCurrent(gfx::GLContext* context) {
DidAccessGpu();
return true;
}
-bool ImageTransportSurfaceAndroid::SwapBuffers() {
- NOTREACHED();
- return false;
-}
-
void ImageTransportSurfaceAndroid::WakeUpGpu() {
begin_wake_up_time_ = base::TimeTicks::Now();
ScheduleWakeUp();
@@ -160,18 +131,20 @@ bool DirectSurfaceAndroid::SwapBuffers() {
} // anonymous namespace
// static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateTransportSurface(
GpuChannelManager* manager,
GpuCommandBufferStub* stub,
const gfx::GLSurfaceHandle& handle) {
- if (handle.transport_type == gfx::NATIVE_TRANSPORT) {
- return scoped_refptr<gfx::GLSurface>(
- new ImageTransportSurfaceAndroid(manager,
- stub,
- manager->GetDefaultOffscreenSurface(),
- handle.parent_client_id));
- }
+ DCHECK_EQ(gfx::NULL_TRANSPORT, handle.transport_type);
+ return scoped_refptr<gfx::GLSurface>(
+ new ImageTransportSurfaceAndroid(manager, stub, handle));
+}
+// static
+scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
+ GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ const gfx::GLSurfaceHandle& handle) {
DCHECK(GpuSurfaceLookup::GetInstance());
DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
ANativeWindow* window =
diff --git a/chromium/content/common/gpu/image_transport_surface_calayer_mac.h b/chromium/content/common/gpu/image_transport_surface_calayer_mac.h
new file mode 100644
index 00000000000..1a7c3a211d6
--- /dev/null
+++ b/chromium/content/common/gpu/image_transport_surface_calayer_mac.h
@@ -0,0 +1,102 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_CALAYER_MAC_H_
+#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_CALAYER_MAC_H_
+
+#include "base/mac/scoped_nsobject.h"
+#include "content/common/gpu/image_transport_surface_fbo_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gpu_switching_observer.h"
+#include "ui/gl/scoped_cgl.h"
+
+@class ImageTransportLayer;
+
+namespace content {
+
+// Allocate CAOpenGLLayer-backed storage for an FBO image transport surface.
+class CALayerStorageProvider
+ : public ImageTransportSurfaceFBO::StorageProvider,
+ public ui::GpuSwitchingObserver {
+ public:
+ CALayerStorageProvider(ImageTransportSurfaceFBO* transport_surface);
+ ~CALayerStorageProvider() override;
+
+ // ImageTransportSurfaceFBO::StorageProvider implementation:
+ gfx::Size GetRoundedSize(gfx::Size size) override;
+ bool AllocateColorBufferStorage(CGLContextObj context,
+ GLuint texture,
+ gfx::Size pixel_size,
+ float scale_factor) override;
+ void FreeColorBufferStorage() override;
+ void SwapBuffers(const gfx::Size& size, float scale_factor) override;
+ void WillWriteToBackbuffer() override;
+ void DiscardBackbuffer() override;
+ void SwapBuffersAckedByBrowser(bool disable_throttling) override;
+
+ // Interface to ImageTransportLayer:
+ CGLContextObj LayerShareGroupContext();
+ bool LayerCanDraw();
+ void LayerDoDraw();
+ void LayerResetStorageProvider();
+
+ // ui::GpuSwitchingObserver implementation.
+ void OnGpuSwitched() override;
+
+ private:
+ void DrawImmediatelyAndUnblockBrowser();
+
+ // The browser will be blocked while there is a frame that was sent to it but
+ // hasn't drawn yet. This call will un-block the browser.
+ void UnblockBrowserIfNeeded();
+
+ ImageTransportSurfaceFBO* transport_surface_;
+
+ // Used to determine if we should use setNeedsDisplay or setAsynchronous to
+ // animate.
+ const bool gpu_vsync_disabled_;
+
+ // Used also to determine if we should wait for CoreAnimation to call our
+ // drawInCGLContext, or if we should force it with displayIfNeeded.
+ bool throttling_disabled_;
+
+ // Set when a new swap occurs, and un-set when |layer_| draws that frame.
+ bool has_pending_draw_;
+
+ // A counter that is incremented whenever LayerCanDraw returns false. If this
+ // reaches a threshold, then |layer_| is switched to synchronous drawing to
+ // save CPU work.
+ uint32 can_draw_returned_false_count_;
+
+ // The texture with the pixels to draw, and the share group it is allocated
+ // in.
+ base::ScopedTypeRef<CGLContextObj> share_group_context_;
+ GLuint fbo_texture_;
+ gfx::Size fbo_pixel_size_;
+ float fbo_scale_factor_;
+
+ // The CALayer that the current frame is being drawn into.
+ base::scoped_nsobject<CAContext> context_;
+ base::scoped_nsobject<ImageTransportLayer> layer_;
+
+ // When a CAContext is destroyed in the GPU process, it will become a blank
+ // CALayer in the browser process. Put retains on these contexts in this queue
+ // when they are discarded, and remove one item from the queue as each frame
+ // is acked.
+ std::list<base::scoped_nsobject<CAContext> > previously_discarded_contexts_;
+
+ // Indicates that the CALayer should be recreated at the next swap. This is
+ // to ensure that the CGLContext created for the CALayer be on the right GPU.
+ bool recreate_layer_after_gpu_switch_;
+
+ // Weak factory against which a timeout task for forcing a draw is created.
+ base::WeakPtrFactory<CALayerStorageProvider> pending_draw_weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CALayerStorageProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_IMAGE_TRANSPORT_CALAYER_MAC_H_
diff --git a/chromium/content/common/gpu/image_transport_surface_calayer_mac.mm b/chromium/content/common/gpu/image_transport_surface_calayer_mac.mm
new file mode 100644
index 00000000000..0147b3c686a
--- /dev/null
+++ b/chromium/content/common/gpu/image_transport_surface_calayer_mac.mm
@@ -0,0 +1,371 @@
+// Copyright 2014 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 "content/common/gpu/image_transport_surface_calayer_mac.h"
+
+#include <OpenGL/CGLRenderers.h>
+
+#include "base/command_line.h"
+#include "base/mac/sdk_forward_declarations.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
+#include "ui/base/cocoa/animation_utils.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gl/gl_gl_api_implementation.h"
+#include "ui/gl/gl_switches.h"
+#include "ui/gl/gpu_switching_manager.h"
+
+namespace {
+const size_t kFramesToKeepCAContextAfterDiscard = 2;
+}
+
+@interface ImageTransportLayer : CAOpenGLLayer {
+ content::CALayerStorageProvider* storageProvider_;
+}
+- (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider;
+- (void)resetStorageProvider;
+@end
+
+@implementation ImageTransportLayer
+
+- (id)initWithStorageProvider:
+ (content::CALayerStorageProvider*)storageProvider {
+ if (self = [super init])
+ storageProvider_ = storageProvider;
+ return self;
+}
+
+- (void)resetStorageProvider {
+ if (storageProvider_)
+ storageProvider_->LayerResetStorageProvider();
+ storageProvider_ = NULL;
+}
+
+- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
+ if (!storageProvider_)
+ return NULL;
+ return CGLRetainPixelFormat(CGLGetPixelFormat(
+ storageProvider_->LayerShareGroupContext()));
+}
+
+- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
+ if (!storageProvider_)
+ return NULL;
+ CGLContextObj context = NULL;
+ CGLError error = CGLCreateContext(
+ pixelFormat, storageProvider_->LayerShareGroupContext(), &context);
+ if (error != kCGLNoError)
+ DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error;
+ return context;
+}
+
+- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ if (!storageProvider_)
+ return NO;
+ return storageProvider_->LayerCanDraw();
+}
+
+- (void)drawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ // While in this callback, CoreAnimation has set |glContext| to be current.
+ // Ensure that the GL calls that we make are made against the native GL API.
+ gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
+
+ if (storageProvider_) {
+ storageProvider_->LayerDoDraw();
+ } else {
+ glClearColor(1, 1, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
+}
+
+@end
+
+namespace content {
+
+CALayerStorageProvider::CALayerStorageProvider(
+ ImageTransportSurfaceFBO* transport_surface)
+ : transport_surface_(transport_surface),
+ gpu_vsync_disabled_(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuVsync)),
+ throttling_disabled_(false),
+ has_pending_draw_(false),
+ can_draw_returned_false_count_(0),
+ fbo_texture_(0),
+ fbo_scale_factor_(1),
+ recreate_layer_after_gpu_switch_(false),
+ pending_draw_weak_factory_(this) {
+ ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
+}
+
+CALayerStorageProvider::~CALayerStorageProvider() {
+ ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
+}
+
+gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) {
+ return size;
+}
+
+bool CALayerStorageProvider::AllocateColorBufferStorage(
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) {
+ // Allocate an ordinary OpenGL texture to back the FBO.
+ GLenum error;
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ DLOG(ERROR) << "Error found (and ignored) before allocating buffer "
+ << "storage: " << error;
+ }
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
+ 0,
+ GL_RGBA,
+ pixel_size.width(),
+ pixel_size.height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+ error = glGetError();
+ if (error != GL_NO_ERROR) {
+ DLOG(ERROR) << "glTexImage failed with GL error: " << error;
+ return false;
+ }
+ glFlush();
+
+ // Set the parameters that will be used to allocate the CALayer to draw the
+ // texture into.
+ share_group_context_.reset(CGLRetainContext(context));
+ fbo_texture_ = texture;
+ fbo_pixel_size_ = pixel_size;
+ fbo_scale_factor_ = scale_factor;
+ return true;
+}
+
+void CALayerStorageProvider::FreeColorBufferStorage() {
+ // Note that |context_| still holds a reference to |layer_|, and will until
+ // a new frame is swapped in.
+ [layer_ resetStorageProvider];
+ layer_.reset();
+
+ share_group_context_.reset();
+ fbo_texture_ = 0;
+ fbo_pixel_size_ = gfx::Size();
+ can_draw_returned_false_count_ = 0;
+}
+
+void CALayerStorageProvider::SwapBuffers(
+ const gfx::Size& size, float scale_factor) {
+ DCHECK(!has_pending_draw_);
+
+ // Recreate the CALayer on the new GPU if a GPU switch has occurred. Note
+ // that the CAContext will retain a reference to the old CALayer until the
+ // call to -[CAContext setLayer:] replaces the old CALayer with the new one.
+ if (recreate_layer_after_gpu_switch_) {
+ [layer_ resetStorageProvider];
+ layer_.reset();
+ recreate_layer_after_gpu_switch_ = false;
+ }
+
+ // Set the pending draw flag only after destroying the old layer (otherwise
+ // destroying it will un-set the flag).
+ has_pending_draw_ = true;
+
+ // Allocate a CAContext to use to transport the CALayer to the browser
+ // process, if needed.
+ if (!context_) {
+ base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
+ CGSConnectionID connection_id = CGSMainConnectionID();
+ context_.reset([CAContext contextWithCGSConnection:connection_id
+ options:dict]);
+ [context_ retain];
+ }
+
+ // Allocate a CALayer to use to draw the content, if needed.
+ if (!layer_) {
+ layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
+ gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
+ fbo_pixel_size_, 1.0f / fbo_scale_factor_)));
+ [layer_ setContentsScale:fbo_scale_factor_];
+ [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
+
+ // Make the CALayer current to the CAContext and display its contents
+ // immediately.
+ [context_ setLayer:layer_];
+ }
+
+ // Replacing the CAContext's CALayer will sometimes results in an immediate
+ // draw. If that happens, early-out.
+ if (!has_pending_draw_)
+ return;
+
+ // Tell CoreAnimation to draw our frame.
+ if (gpu_vsync_disabled_ || throttling_disabled_) {
+ DrawImmediatelyAndUnblockBrowser();
+ } else {
+ if (![layer_ isAsynchronous])
+ [layer_ setAsynchronous:YES];
+
+ // If CoreAnimation doesn't end up drawing our frame, un-block the browser
+ // after a timeout of 1/6th of a second has passed.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CALayerStorageProvider::DrawImmediatelyAndUnblockBrowser,
+ pending_draw_weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(1) / 6);
+ }
+}
+
+void CALayerStorageProvider::DrawImmediatelyAndUnblockBrowser() {
+ CHECK(has_pending_draw_);
+ if ([layer_ isAsynchronous])
+ [layer_ setAsynchronous:NO];
+ [layer_ setNeedsDisplay];
+ [layer_ displayIfNeeded];
+
+ // Sometimes, the setNeedsDisplay+displayIfNeeded pairs have no effect. This
+ // can happen if the NSView that this layer is attached to isn't in the
+ // window hierarchy (e.g, tab capture of a backgrounded tab). In this case,
+ // the frame will never be seen, so drop it.
+ UnblockBrowserIfNeeded();
+}
+
+void CALayerStorageProvider::WillWriteToBackbuffer() {
+ // The browser should always throttle itself so that there are no pending
+ // draws when the output surface is written to, but in the event of things
+ // like context lost, or changing context, this will not be true. If there
+ // exists a pending draw, flush it immediately to maintain a consistent
+ // state.
+ if (has_pending_draw_)
+ DrawImmediatelyAndUnblockBrowser();
+}
+
+void CALayerStorageProvider::DiscardBackbuffer() {
+ // If this surface's backbuffer is discarded, it is because this surface has
+ // been made non-visible. Ensure that the previous contents are not briefly
+ // flashed when this is made visible by creating a new CALayer and CAContext
+ // at the next swap.
+ [layer_ resetStorageProvider];
+ layer_.reset();
+
+ // If we remove all references to the CAContext in this process, it will be
+ // blanked-out in the browser process (even if the browser process is inside
+ // a NSDisableScreenUpdates block). Ensure that the context is kept around
+ // until a fixed number of frames (determined empirically) have been acked.
+ // http://crbug.com/425819
+ while (previously_discarded_contexts_.size() <
+ kFramesToKeepCAContextAfterDiscard) {
+ previously_discarded_contexts_.push_back(
+ base::scoped_nsobject<CAContext>());
+ }
+ previously_discarded_contexts_.push_back(context_);
+
+ context_.reset();
+}
+
+void CALayerStorageProvider::SwapBuffersAckedByBrowser(
+ bool disable_throttling) {
+ throttling_disabled_ = disable_throttling;
+ if (!previously_discarded_contexts_.empty())
+ previously_discarded_contexts_.pop_front();
+}
+
+CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
+ return share_group_context_;
+}
+
+bool CALayerStorageProvider::LayerCanDraw() {
+ if (has_pending_draw_) {
+ can_draw_returned_false_count_ = 0;
+ return true;
+ } else {
+ if ([layer_ isAsynchronous]) {
+ DCHECK(!gpu_vsync_disabled_);
+ // If we are in asynchronous mode, we will be getting callbacks at every
+ // vsync, asking us if we have anything to draw. If we get 30 of these in
+ // a row, ask that we stop getting these callback for now, so that we
+ // don't waste CPU cycles.
+ if (can_draw_returned_false_count_ == 30)
+ [layer_ setAsynchronous:NO];
+ else
+ can_draw_returned_false_count_ += 1;
+ }
+ return false;
+ }
+}
+
+void CALayerStorageProvider::LayerDoDraw() {
+ GLint viewport[4] = {0, 0, 0, 0};
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ gfx::Size viewport_size(viewport[2], viewport[3]);
+
+ // Set the coordinate system to be one-to-one with pixels.
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // Draw a fullscreen quad.
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fbo_texture_);
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0, 0);
+ glVertex2f(0, 0);
+
+ glTexCoord2f(0, fbo_pixel_size_.height());
+ glVertex2f(0, fbo_pixel_size_.height());
+
+ glTexCoord2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
+ glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
+
+ glTexCoord2f(fbo_pixel_size_.width(), 0);
+ glVertex2f(fbo_pixel_size_.width(), 0);
+ }
+ glEnd();
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ GLint current_renderer_id = 0;
+ if (CGLGetParameter(CGLGetCurrentContext(),
+ kCGLCPCurrentRendererID,
+ &current_renderer_id) == kCGLNoError) {
+ current_renderer_id &= kCGLRendererIDMatchingMask;
+ transport_surface_->SetRendererID(current_renderer_id);
+ }
+
+ // Allow forward progress in the context now that the swap is complete.
+ UnblockBrowserIfNeeded();
+}
+
+void CALayerStorageProvider::LayerResetStorageProvider() {
+ // If we are providing back-pressure by waiting for a draw, that draw will
+ // now never come, so release the pressure now.
+ UnblockBrowserIfNeeded();
+}
+
+void CALayerStorageProvider::OnGpuSwitched() {
+ recreate_layer_after_gpu_switch_ = true;
+}
+
+void CALayerStorageProvider::UnblockBrowserIfNeeded() {
+ if (!has_pending_draw_)
+ return;
+ pending_draw_weak_factory_.InvalidateWeakPtrs();
+ has_pending_draw_ = false;
+ transport_surface_->SendSwapBuffers(
+ SurfaceHandleFromCAContextID([context_ contextId]),
+ fbo_pixel_size_,
+ fbo_scale_factor_);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_fbo_mac.cc b/chromium/content/common/gpu/image_transport_surface_fbo_mac.cc
deleted file mode 100644
index 79ec8db8dd1..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_fbo_mac.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2014 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 "content/common/gpu/image_transport_surface_fbo_mac.h"
-
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_surface_osmesa.h"
-
-namespace content {
-
-ImageTransportSurfaceFBO::ImageTransportSurfaceFBO(
- StorageProvider* storage_provider,
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle)
- : storage_provider_(storage_provider),
- backbuffer_suggested_allocation_(true),
- frontbuffer_suggested_allocation_(true),
- fbo_id_(0),
- texture_id_(0),
- depth_stencil_renderbuffer_id_(0),
- has_complete_framebuffer_(false),
- context_(NULL),
- scale_factor_(1.f),
- made_current_(false),
- is_swap_buffers_pending_(false),
- did_unschedule_(false) {
- helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
-}
-
-ImageTransportSurfaceFBO::~ImageTransportSurfaceFBO() {
-}
-
-bool ImageTransportSurfaceFBO::Initialize() {
- // Only support IOSurfaces if the GL implementation is the native desktop GL.
- // IO surfaces will not work with, for example, OSMesa software renderer
- // GL contexts.
- if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
- gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
- return false;
-
- if (!helper_->Initialize())
- return false;
-
- helper_->stub()->AddDestructionObserver(this);
- return true;
-}
-
-void ImageTransportSurfaceFBO::Destroy() {
- DestroyFramebuffer();
-
- helper_->Destroy();
-}
-
-bool ImageTransportSurfaceFBO::DeferDraws() {
- // The command buffer hit a draw/clear command that could clobber the
- // IOSurface in use by an earlier SwapBuffers. If a Swap is pending, abort
- // processing of the command by returning true and unschedule until the Swap
- // Ack arrives.
- if(did_unschedule_)
- return true; // Still unscheduled, so just return true.
- if (is_swap_buffers_pending_) {
- did_unschedule_ = true;
- helper_->SetScheduled(false);
- return true;
- }
- return false;
-}
-
-bool ImageTransportSurfaceFBO::IsOffscreen() {
- return false;
-}
-
-bool ImageTransportSurfaceFBO::OnMakeCurrent(gfx::GLContext* context) {
- context_ = context;
-
- if (made_current_)
- return true;
-
- OnResize(gfx::Size(1, 1), 1.f);
-
- made_current_ = true;
- return true;
-}
-
-unsigned int ImageTransportSurfaceFBO::GetBackingFrameBufferObject() {
- return fbo_id_;
-}
-
-bool ImageTransportSurfaceFBO::SetBackbufferAllocation(bool allocation) {
- if (backbuffer_suggested_allocation_ == allocation)
- return true;
- backbuffer_suggested_allocation_ = allocation;
- AdjustBufferAllocation();
- return true;
-}
-
-void ImageTransportSurfaceFBO::SetFrontbufferAllocation(bool allocation) {
- if (frontbuffer_suggested_allocation_ == allocation)
- return;
- frontbuffer_suggested_allocation_ = allocation;
- AdjustBufferAllocation();
-}
-
-void ImageTransportSurfaceFBO::AdjustBufferAllocation() {
- // On mac, the frontbuffer and backbuffer are the same buffer. The buffer is
- // free'd when both the browser and gpu processes have Unref'd the IOSurface.
- if (!backbuffer_suggested_allocation_ &&
- !frontbuffer_suggested_allocation_ &&
- has_complete_framebuffer_) {
- DestroyFramebuffer();
- helper_->Suspend();
- } else if (backbuffer_suggested_allocation_ && !has_complete_framebuffer_) {
- CreateFramebuffer();
- }
-}
-
-bool ImageTransportSurfaceFBO::SwapBuffers() {
- DCHECK(backbuffer_suggested_allocation_);
- if (!frontbuffer_suggested_allocation_)
- return true;
- glFlush();
-
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
- params.surface_handle = storage_provider_->GetSurfaceHandle();
- params.size = GetSize();
- params.scale_factor = scale_factor_;
- params.latency_info.swap(latency_info_);
- helper_->SendAcceleratedSurfaceBuffersSwapped(params);
-
- DCHECK(!is_swap_buffers_pending_);
- is_swap_buffers_pending_ = true;
- return true;
-}
-
-bool ImageTransportSurfaceFBO::PostSubBuffer(
- int x, int y, int width, int height) {
- DCHECK(backbuffer_suggested_allocation_);
- if (!frontbuffer_suggested_allocation_)
- return true;
- glFlush();
-
- GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
- params.surface_handle = storage_provider_->GetSurfaceHandle();
- params.x = x;
- params.y = y;
- params.width = width;
- params.height = height;
- params.surface_size = GetSize();
- params.surface_scale_factor = scale_factor_;
- params.latency_info.swap(latency_info_);
- helper_->SendAcceleratedSurfacePostSubBuffer(params);
-
- DCHECK(!is_swap_buffers_pending_);
- is_swap_buffers_pending_ = true;
- return true;
-}
-
-bool ImageTransportSurfaceFBO::SupportsPostSubBuffer() {
- return true;
-}
-
-gfx::Size ImageTransportSurfaceFBO::GetSize() {
- return size_;
-}
-
-void* ImageTransportSurfaceFBO::GetHandle() {
- return NULL;
-}
-
-void* ImageTransportSurfaceFBO::GetDisplay() {
- return NULL;
-}
-
-void ImageTransportSurfaceFBO::OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
- DCHECK(is_swap_buffers_pending_);
-
- context_->share_group()->SetRendererID(params.renderer_id);
- is_swap_buffers_pending_ = false;
- if (did_unschedule_) {
- did_unschedule_ = false;
- helper_->SetScheduled(true);
- }
-}
-
-void ImageTransportSurfaceFBO::OnResize(gfx::Size size,
- float scale_factor) {
- // This trace event is used in gpu_feature_browsertest.cc - the test will need
- // to be updated if this event is changed or moved.
- TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::OnResize",
- "old_width", size_.width(), "new_width", size.width());
- // Caching |context_| from OnMakeCurrent. It should still be current.
- DCHECK(context_->IsCurrent(this));
-
- size_ = size;
- scale_factor_ = scale_factor;
-
- CreateFramebuffer();
-}
-
-void ImageTransportSurfaceFBO::SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- for (size_t i = 0; i < latency_info.size(); i++)
- latency_info_.push_back(latency_info[i]);
-}
-
-void ImageTransportSurfaceFBO::WakeUpGpu() {
- NOTIMPLEMENTED();
-}
-
-void ImageTransportSurfaceFBO::OnWillDestroyStub() {
- helper_->stub()->RemoveDestructionObserver(this);
- Destroy();
-}
-
-void ImageTransportSurfaceFBO::DestroyFramebuffer() {
- // If we have resources to destroy, then make sure that we have a current
- // context which we can use to delete the resources.
- if (context_ || fbo_id_ || texture_id_ || depth_stencil_renderbuffer_id_) {
- DCHECK(gfx::GLContext::GetCurrent() == context_);
- DCHECK(context_->IsCurrent(this));
- DCHECK(CGLGetCurrentContext());
- }
-
- if (fbo_id_) {
- glDeleteFramebuffersEXT(1, &fbo_id_);
- fbo_id_ = 0;
- }
-
- if (texture_id_) {
- glDeleteTextures(1, &texture_id_);
- texture_id_ = 0;
- }
-
- if (depth_stencil_renderbuffer_id_) {
- glDeleteRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
- depth_stencil_renderbuffer_id_ = 0;
- }
-
- storage_provider_->FreeColorBufferStorage();
-
- has_complete_framebuffer_ = false;
-}
-
-void ImageTransportSurfaceFBO::CreateFramebuffer() {
- gfx::Size new_rounded_size = storage_provider_->GetRoundedSize(size_);
-
- // Only recreate surface when the rounded up size has changed.
- if (has_complete_framebuffer_ && new_rounded_size == rounded_size_)
- return;
-
- // This trace event is used in gpu_feature_browsertest.cc - the test will need
- // to be updated if this event is changed or moved.
- TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::CreateFramebuffer",
- "width", new_rounded_size.width(),
- "height", new_rounded_size.height());
-
- rounded_size_ = new_rounded_size;
-
- // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
- // Mac OS X and is required for IOSurface interoperability.
- GLint previous_texture_id = 0;
- glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id);
-
- // Free the old IO Surface first to reduce memory fragmentation.
- DestroyFramebuffer();
-
- glGenFramebuffersEXT(1, &fbo_id_);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
-
- glGenTextures(1, &texture_id_);
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id_);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_RECTANGLE_ARB,
- texture_id_,
- 0);
-
- // Search through the provided attributes; if the caller has
- // requested a stencil buffer, try to get one.
-
- int32 stencil_bits =
- helper_->stub()->GetRequestedAttribute(EGL_STENCIL_SIZE);
- if (stencil_bits > 0) {
- // Create and bind the stencil buffer
- bool has_packed_depth_stencil =
- GLSurface::ExtensionsContain(
- reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
- "GL_EXT_packed_depth_stencil");
-
- if (has_packed_depth_stencil) {
- glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
- depth_stencil_renderbuffer_id_);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
- rounded_size_.width(), rounded_size_.height());
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
- GL_STENCIL_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT,
- depth_stencil_renderbuffer_id_);
- }
-
- // If we asked for stencil but the extension isn't present,
- // it's OK to silently fail; subsequent code will/must check
- // for the presence of a stencil buffer before attempting to
- // do stencil-based operations.
- }
-
- bool allocated_color_buffer = storage_provider_->AllocateColorBufferStorage(
- static_cast<CGLContextObj>(context_->GetHandle()),
- rounded_size_);
- if (!allocated_color_buffer) {
- DLOG(ERROR) << "Failed to allocate color buffer storage.";
- DestroyFramebuffer();
- return;
- }
-
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- DLOG(ERROR) << "Framebuffer was incomplete: " << status;
- DestroyFramebuffer();
- return;
- }
-
- has_complete_framebuffer_ = true;
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, previous_texture_id);
- // The FBO remains bound for this GL context.
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_fbo_mac.h b/chromium/content/common/gpu/image_transport_surface_fbo_mac.h
index 1302cfe51bc..dbcdc83f7a3 100644
--- a/chromium/content/common/gpu/image_transport_surface_fbo_mac.h
+++ b/chromium/content/common/gpu/image_transport_surface_fbo_mac.h
@@ -34,56 +34,74 @@ class ImageTransportSurfaceFBO
// Allocate the storage for the color buffer. The specified context is
// current, and there is a texture bound to GL_TEXTURE_RECTANGLE_ARB.
virtual bool AllocateColorBufferStorage(
- CGLContextObj context, gfx::Size size) = 0;
+ CGLContextObj context, GLuint texture,
+ gfx::Size size, float scale_factor) = 0;
// Free the storage allocated in the AllocateColorBufferStorage call. The
// GL texture that was bound has already been deleted by the caller.
virtual void FreeColorBufferStorage() = 0;
- // Retrieve the handle for the surface to send to the browser process to
- // display.
- virtual uint64 GetSurfaceHandle() const = 0;
+ // Swap buffers and return the handle for the surface to send to the browser
+ // process to display.
+ virtual void SwapBuffers(const gfx::Size& size, float scale_factor) = 0;
+
+ // Indicate that the backbuffer will be written to.
+ virtual void WillWriteToBackbuffer() = 0;
+
+ // Indicate that the backbuffer has been discarded and should not be seen
+ // again.
+ virtual void DiscardBackbuffer() = 0;
+
+ // Called once for every SwapBuffers call when the IPC for the present has
+ // been processed by the browser. |disable_throttling| is set if the
+ // browser suspects that GPU back-pressure should be disabled.
+ virtual void SwapBuffersAckedByBrowser(bool disable_throttling) = 0;
};
- ImageTransportSurfaceFBO(StorageProvider* storage_provider,
- GpuChannelManager* manager,
+ ImageTransportSurfaceFBO(GpuChannelManager* manager,
GpuCommandBufferStub* stub,
gfx::PluginWindowHandle handle);
// GLSurface implementation
- virtual bool Initialize() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool DeferDraws() OVERRIDE;
- virtual bool IsOffscreen() OVERRIDE;
- virtual bool SwapBuffers() OVERRIDE;
- virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
- virtual bool SupportsPostSubBuffer() OVERRIDE;
- virtual gfx::Size GetSize() OVERRIDE;
- virtual void* GetHandle() OVERRIDE;
- virtual void* GetDisplay() OVERRIDE;
- virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
- virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
- virtual bool SetBackbufferAllocation(bool allocated) OVERRIDE;
- virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
+ bool Initialize() override;
+ void Destroy() override;
+ bool DeferDraws() override;
+ bool IsOffscreen() override;
+ bool SwapBuffers() override;
+ bool PostSubBuffer(int x, int y, int width, int height) override;
+ bool SupportsPostSubBuffer() override;
+ gfx::Size GetSize() override;
+ void* GetHandle() override;
+ void* GetDisplay() override;
+ bool OnMakeCurrent(gfx::GLContext* context) override;
+ unsigned int GetBackingFrameBufferObject() override;
+ bool SetBackbufferAllocation(bool allocated) override;
+ void SetFrontbufferAllocation(bool allocated) override;
+
+ // Called when the context may continue to make forward progress after a swap.
+ void SendSwapBuffers(uint64 surface_handle,
+ const gfx::Size pixel_size,
+ float scale_factor);
+ void SetRendererID(int renderer_id);
protected:
// ImageTransportSurface implementation
- virtual void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
- virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
- virtual void SetLatencyInfo(
- const std::vector<ui::LatencyInfo>&) OVERRIDE;
- virtual void WakeUpGpu() OVERRIDE;
+ void OnBufferPresented(
+ const AcceleratedSurfaceMsg_BufferPresented_Params& params) override;
+ void OnResize(gfx::Size pixel_size, float scale_factor) override;
+ void SetLatencyInfo(const std::vector<ui::LatencyInfo>&) override;
+ void WakeUpGpu() override;
// GpuCommandBufferStub::DestructionObserver implementation.
- virtual void OnWillDestroyStub() OVERRIDE;
+ void OnWillDestroyStub() override;
private:
- virtual ~ImageTransportSurfaceFBO() OVERRIDE;
+ ~ImageTransportSurfaceFBO() override;
void AdjustBufferAllocation();
void DestroyFramebuffer();
- void CreateFramebuffer();
+ void AllocateOrResizeFramebuffer(
+ const gfx::Size& pixel_size, float scale_factor);
scoped_ptr<StorageProvider> storage_provider_;
@@ -99,19 +117,15 @@ class ImageTransportSurfaceFBO
// Weak pointer to the context that this was last made current to.
gfx::GLContext* context_;
- gfx::Size size_;
- gfx::Size rounded_size_;
+ gfx::Size pixel_size_;
+ gfx::Size rounded_pixel_size_;
float scale_factor_;
// Whether or not we've successfully made the surface current once.
bool made_current_;
- // Whether a SwapBuffers is pending.
- bool is_swap_buffers_pending_;
-
- // Whether we unscheduled command buffer because of pending SwapBuffers.
- bool did_unschedule_;
-
+ // Whether a SwapBuffers IPC needs to be sent to the browser.
+ bool is_swap_buffers_send_pending_;
std::vector<ui::LatencyInfo> latency_info_;
scoped_ptr<ImageTransportHelper> helper_;
diff --git a/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm b/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm
new file mode 100644
index 00000000000..6af794d552e
--- /dev/null
+++ b/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm
@@ -0,0 +1,334 @@
+// Copyright 2014 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 "content/common/gpu/image_transport_surface_fbo_mac.h"
+
+#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/image_transport_surface_calayer_mac.h"
+#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_osmesa.h"
+
+namespace content {
+
+ImageTransportSurfaceFBO::ImageTransportSurfaceFBO(
+ GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ gfx::PluginWindowHandle handle)
+ : backbuffer_suggested_allocation_(true),
+ frontbuffer_suggested_allocation_(true),
+ fbo_id_(0),
+ texture_id_(0),
+ depth_stencil_renderbuffer_id_(0),
+ has_complete_framebuffer_(false),
+ context_(NULL),
+ scale_factor_(1.f),
+ made_current_(false),
+ is_swap_buffers_send_pending_(false) {
+ if (ui::RemoteLayerAPISupported())
+ storage_provider_.reset(new CALayerStorageProvider(this));
+ else
+ storage_provider_.reset(new IOSurfaceStorageProvider(this));
+ helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
+}
+
+ImageTransportSurfaceFBO::~ImageTransportSurfaceFBO() {
+}
+
+bool ImageTransportSurfaceFBO::Initialize() {
+ // Only support IOSurfaces if the GL implementation is the native desktop GL.
+ // IO surfaces will not work with, for example, OSMesa software renderer
+ // GL contexts.
+ if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
+ gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
+ return false;
+
+ if (!helper_->Initialize())
+ return false;
+
+ helper_->stub()->AddDestructionObserver(this);
+ return true;
+}
+
+void ImageTransportSurfaceFBO::Destroy() {
+ DestroyFramebuffer();
+}
+
+bool ImageTransportSurfaceFBO::DeferDraws() {
+ storage_provider_->WillWriteToBackbuffer();
+ // We should not have a pending send when we are drawing the next frame.
+ DCHECK(!is_swap_buffers_send_pending_);
+ return false;
+}
+
+bool ImageTransportSurfaceFBO::IsOffscreen() {
+ return false;
+}
+
+bool ImageTransportSurfaceFBO::OnMakeCurrent(gfx::GLContext* context) {
+ context_ = context;
+
+ if (made_current_)
+ return true;
+
+ AllocateOrResizeFramebuffer(gfx::Size(1, 1), 1.f);
+
+ made_current_ = true;
+ return true;
+}
+
+unsigned int ImageTransportSurfaceFBO::GetBackingFrameBufferObject() {
+ return fbo_id_;
+}
+
+bool ImageTransportSurfaceFBO::SetBackbufferAllocation(bool allocation) {
+ if (backbuffer_suggested_allocation_ == allocation)
+ return true;
+ backbuffer_suggested_allocation_ = allocation;
+ AdjustBufferAllocation();
+ if (!allocation)
+ storage_provider_->DiscardBackbuffer();
+ return true;
+}
+
+void ImageTransportSurfaceFBO::SetFrontbufferAllocation(bool allocation) {
+ if (frontbuffer_suggested_allocation_ == allocation)
+ return;
+ frontbuffer_suggested_allocation_ = allocation;
+ AdjustBufferAllocation();
+}
+
+void ImageTransportSurfaceFBO::AdjustBufferAllocation() {
+ // On mac, the frontbuffer and backbuffer are the same buffer. The buffer is
+ // free'd when both the browser and gpu processes have Unref'd the IOSurface.
+ if (!backbuffer_suggested_allocation_ &&
+ !frontbuffer_suggested_allocation_ &&
+ has_complete_framebuffer_) {
+ DestroyFramebuffer();
+ } else if (backbuffer_suggested_allocation_ && !has_complete_framebuffer_) {
+ AllocateOrResizeFramebuffer(pixel_size_, scale_factor_);
+ }
+}
+
+bool ImageTransportSurfaceFBO::SwapBuffers() {
+ DCHECK(backbuffer_suggested_allocation_);
+ if (!frontbuffer_suggested_allocation_)
+ return true;
+ glFlush();
+
+ // It is the responsibility of the storage provider to send the swap IPC.
+ is_swap_buffers_send_pending_ = true;
+ storage_provider_->SwapBuffers(pixel_size_, scale_factor_);
+ return true;
+}
+
+void ImageTransportSurfaceFBO::SendSwapBuffers(uint64 surface_handle,
+ const gfx::Size pixel_size,
+ float scale_factor) {
+ GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
+ params.surface_handle = surface_handle;
+ params.size = pixel_size;
+ params.scale_factor = scale_factor;
+ params.latency_info.swap(latency_info_);
+ helper_->SendAcceleratedSurfaceBuffersSwapped(params);
+ is_swap_buffers_send_pending_ = false;
+}
+
+void ImageTransportSurfaceFBO::SetRendererID(int renderer_id) {
+ if (renderer_id)
+ context_->share_group()->SetRendererID(renderer_id);
+}
+
+bool ImageTransportSurfaceFBO::PostSubBuffer(
+ int x, int y, int width, int height) {
+ // Mac does not support sub-buffer swaps.
+ NOTREACHED();
+ return false;
+}
+
+bool ImageTransportSurfaceFBO::SupportsPostSubBuffer() {
+ return true;
+}
+
+gfx::Size ImageTransportSurfaceFBO::GetSize() {
+ return pixel_size_;
+}
+
+void* ImageTransportSurfaceFBO::GetHandle() {
+ return NULL;
+}
+
+void* ImageTransportSurfaceFBO::GetDisplay() {
+ return NULL;
+}
+
+void ImageTransportSurfaceFBO::OnBufferPresented(
+ const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
+ SetRendererID(params.renderer_id);
+ storage_provider_->SwapBuffersAckedByBrowser(params.disable_throttling);
+}
+
+void ImageTransportSurfaceFBO::OnResize(gfx::Size pixel_size,
+ float scale_factor) {
+ TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::OnResize",
+ "old_size", pixel_size_.ToString(),
+ "new_size", pixel_size.ToString());
+ // Caching |context_| from OnMakeCurrent. It should still be current.
+ DCHECK(context_->IsCurrent(this));
+
+ AllocateOrResizeFramebuffer(pixel_size, scale_factor);
+}
+
+void ImageTransportSurfaceFBO::SetLatencyInfo(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ for (size_t i = 0; i < latency_info.size(); i++)
+ latency_info_.push_back(latency_info[i]);
+}
+
+void ImageTransportSurfaceFBO::WakeUpGpu() {
+ NOTIMPLEMENTED();
+}
+
+void ImageTransportSurfaceFBO::OnWillDestroyStub() {
+ helper_->stub()->RemoveDestructionObserver(this);
+ Destroy();
+}
+
+void ImageTransportSurfaceFBO::DestroyFramebuffer() {
+ // If we have resources to destroy, then make sure that we have a current
+ // context which we can use to delete the resources.
+ if (context_ || fbo_id_ || texture_id_ || depth_stencil_renderbuffer_id_) {
+ DCHECK(gfx::GLContext::GetCurrent() == context_);
+ DCHECK(context_->IsCurrent(this));
+ DCHECK(CGLGetCurrentContext());
+ }
+
+ if (fbo_id_) {
+ glDeleteFramebuffersEXT(1, &fbo_id_);
+ fbo_id_ = 0;
+ }
+
+ if (texture_id_) {
+ glDeleteTextures(1, &texture_id_);
+ texture_id_ = 0;
+ }
+
+ if (depth_stencil_renderbuffer_id_) {
+ glDeleteRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
+ depth_stencil_renderbuffer_id_ = 0;
+ }
+
+ storage_provider_->FreeColorBufferStorage();
+
+ has_complete_framebuffer_ = false;
+}
+
+void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
+ const gfx::Size& new_pixel_size, float new_scale_factor) {
+ gfx::Size new_rounded_pixel_size =
+ storage_provider_->GetRoundedSize(new_pixel_size);
+
+ // Only recreate the surface's storage when the rounded up size has changed,
+ // or the scale factor has changed.
+ bool needs_new_storage =
+ !has_complete_framebuffer_ ||
+ new_rounded_pixel_size != rounded_pixel_size_ ||
+ new_scale_factor != scale_factor_;
+
+ // Save the new storage parameters.
+ pixel_size_ = new_pixel_size;
+ rounded_pixel_size_ = new_rounded_pixel_size;
+ scale_factor_ = new_scale_factor;
+
+ if (!needs_new_storage)
+ return;
+
+ TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer",
+ "width", new_rounded_pixel_size.width(),
+ "height", new_rounded_pixel_size.height());
+
+ // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
+ // Mac OS X and is required for IOSurface interoperability.
+ GLint previous_texture_id = 0;
+ glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id);
+
+ // Free the old IO Surface first to reduce memory fragmentation.
+ DestroyFramebuffer();
+
+ glGenFramebuffersEXT(1, &fbo_id_);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
+
+ glGenTextures(1, &texture_id_);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id_);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
+ GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
+ GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_RECTANGLE_ARB,
+ texture_id_,
+ 0);
+
+ // Search through the provided attributes; if the caller has
+ // requested a stencil buffer, try to get one.
+
+ int32 stencil_bits =
+ helper_->stub()->GetRequestedAttribute(EGL_STENCIL_SIZE);
+ if (stencil_bits > 0) {
+ // Create and bind the stencil buffer
+ bool has_packed_depth_stencil =
+ GLSurface::ExtensionsContain(
+ reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
+ "GL_EXT_packed_depth_stencil");
+
+ if (has_packed_depth_stencil) {
+ glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
+ depth_stencil_renderbuffer_id_);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+ rounded_pixel_size_.width(),
+ rounded_pixel_size_.height());
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
+ GL_STENCIL_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ depth_stencil_renderbuffer_id_);
+ }
+
+ // If we asked for stencil but the extension isn't present,
+ // it's OK to silently fail; subsequent code will/must check
+ // for the presence of a stencil buffer before attempting to
+ // do stencil-based operations.
+ }
+
+ bool allocated_color_buffer = storage_provider_->AllocateColorBufferStorage(
+ static_cast<CGLContextObj>(context_->GetHandle()), texture_id_,
+ rounded_pixel_size_, scale_factor_);
+ if (!allocated_color_buffer) {
+ DLOG(ERROR) << "Failed to allocate color buffer storage.";
+ DestroyFramebuffer();
+ return;
+ }
+
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ DLOG(ERROR) << "Framebuffer was incomplete: " << status;
+ DestroyFramebuffer();
+ return;
+ }
+
+ has_complete_framebuffer_ = true;
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, previous_texture_id);
+ // The FBO remains bound for this GL context.
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_iosurface_mac.cc b/chromium/content/common/gpu/image_transport_surface_iosurface_mac.cc
index 5d0dded9287..121a3a2f2ba 100644
--- a/chromium/content/common/gpu/image_transport_surface_iosurface_mac.cc
+++ b/chromium/content/common/gpu/image_transport_surface_iosurface_mac.cc
@@ -5,6 +5,7 @@
#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
namespace content {
namespace {
@@ -39,7 +40,9 @@ void AddIntegerValue(CFMutableDictionaryRef dictionary,
} // namespace
-IOSurfaceStorageProvider::IOSurfaceStorageProvider() {}
+IOSurfaceStorageProvider::IOSurfaceStorageProvider(
+ ImageTransportSurfaceFBO* transport_surface)
+ : transport_surface_(transport_surface) {}
IOSurfaceStorageProvider::~IOSurfaceStorageProvider() {
DCHECK(!io_surface_);
@@ -51,8 +54,8 @@ gfx::Size IOSurfaceStorageProvider::GetRoundedSize(gfx::Size size) {
}
bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
- CGLContextObj context,
- gfx::Size size) {
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) {
// Allocate a new IOSurface, which is the GPU resource that can be
// shared across processes.
base::ScopedCFTypeRef<CFMutableDictionaryRef> properties;
@@ -62,10 +65,10 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
&kCFTypeDictionaryValueCallBacks));
AddIntegerValue(properties,
kIOSurfaceWidth,
- size.width());
+ pixel_size.width());
AddIntegerValue(properties,
kIOSurfaceHeight,
- size.height());
+ pixel_size.height());
AddIntegerValue(properties,
kIOSurfaceBytesPerElement, 4);
AddBooleanValue(properties,
@@ -74,7 +77,7 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
// synchronizing with the browser process because they are
// ultimately reference counted by the operating system.
io_surface_.reset(IOSurfaceCreate(properties));
- io_surface_handle_ = IOSurfaceGetID(io_surface_);
+ io_surface_id_ = IOSurfaceGetID(io_surface_);
// Don't think we need to identify a plane.
GLuint plane = 0;
@@ -82,8 +85,8 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
context,
GL_TEXTURE_RECTANGLE_ARB,
GL_RGBA,
- size.width(),
- size.height(),
+ pixel_size.width(),
+ pixel_size.height(),
GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV,
io_surface_.get(),
@@ -99,11 +102,32 @@ bool IOSurfaceStorageProvider::AllocateColorBufferStorage(
void IOSurfaceStorageProvider::FreeColorBufferStorage() {
io_surface_.reset();
- io_surface_handle_ = 0;
+ io_surface_id_ = 0;
}
-uint64 IOSurfaceStorageProvider::GetSurfaceHandle() const {
- return io_surface_handle_;
+void IOSurfaceStorageProvider::SwapBuffers(
+ const gfx::Size& size, float scale_factor) {
+ // The browser compositor will throttle itself, so we are free to unblock the
+ // context immediately. Make sure that the browser is doing its throttling
+ // appropriately by ensuring that the previous swap was acknowledged before
+ // we get another swap.
+ DCHECK(pending_swapped_surfaces_.empty());
+ pending_swapped_surfaces_.push_back(io_surface_);
+
+ transport_surface_->SendSwapBuffers(
+ SurfaceHandleFromIOSurfaceID(io_surface_id_), size, scale_factor);
+}
+
+void IOSurfaceStorageProvider::WillWriteToBackbuffer() {
+}
+
+void IOSurfaceStorageProvider::DiscardBackbuffer() {
+}
+
+void IOSurfaceStorageProvider::SwapBuffersAckedByBrowser(
+ bool disable_throttling) {
+ DCHECK(!pending_swapped_surfaces_.empty());
+ pending_swapped_surfaces_.pop_front();
}
} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_iosurface_mac.h b/chromium/content/common/gpu/image_transport_surface_iosurface_mac.h
index ccd0a4cb89c..4d49018e4f1 100644
--- a/chromium/content/common/gpu/image_transport_surface_iosurface_mac.h
+++ b/chromium/content/common/gpu/image_transport_surface_iosurface_mac.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_IOSURFACE_MAC_H_
#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_IOSURFACE_MAC_H_
+#include <list>
+
#include "content/common/gpu/image_transport_surface_fbo_mac.h"
#include "ui/gl/gl_bindings.h"
@@ -17,21 +19,33 @@ namespace content {
class IOSurfaceStorageProvider
: public ImageTransportSurfaceFBO::StorageProvider {
public:
- IOSurfaceStorageProvider();
- virtual ~IOSurfaceStorageProvider();
+ IOSurfaceStorageProvider(ImageTransportSurfaceFBO* transport_surface);
+ ~IOSurfaceStorageProvider() override;
// ImageTransportSurfaceFBO::StorageProvider implementation:
- virtual gfx::Size GetRoundedSize(gfx::Size size) OVERRIDE;
- virtual bool AllocateColorBufferStorage(
- CGLContextObj context, gfx::Size size) OVERRIDE;
- virtual void FreeColorBufferStorage() OVERRIDE;
- virtual uint64 GetSurfaceHandle() const OVERRIDE;
+ gfx::Size GetRoundedSize(gfx::Size size) override;
+ bool AllocateColorBufferStorage(CGLContextObj context,
+ GLuint texture,
+ gfx::Size pixel_size,
+ float scale_factor) override;
+ void FreeColorBufferStorage() override;
+ void SwapBuffers(const gfx::Size& size, float scale_factor) override;
+ void WillWriteToBackbuffer() override;
+ void DiscardBackbuffer() override;
+ void SwapBuffersAckedByBrowser(bool disable_throttling) override;
private:
+ ImageTransportSurfaceFBO* transport_surface_;
+
base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
+ // The list of IOSurfaces that have been sent to the browser process but have
+ // not been opened in the browser process yet. This list should never have
+ // more than one entry.
+ std::list<base::ScopedCFTypeRef<IOSurfaceRef>> pending_swapped_surfaces_;
+
// The id of |io_surface_| or 0 if that's NULL.
- IOSurfaceID io_surface_handle_;
+ IOSurfaceID io_surface_id_;
DISALLOW_COPY_AND_ASSIGN(IOSurfaceStorageProvider);
};
diff --git a/chromium/content/common/gpu/image_transport_surface_mac.mm b/chromium/content/common/gpu/image_transport_surface_mac.mm
index 9ab22728e07..0f40f23f1a3 100644
--- a/chromium/content/common/gpu/image_transport_surface_mac.mm
+++ b/chromium/content/common/gpu/image_transport_surface_mac.mm
@@ -5,7 +5,6 @@
#include "content/common/gpu/image_transport_surface_fbo_mac.h"
#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
@@ -19,13 +18,14 @@ namespace {
class DRTSurfaceOSMesa : public gfx::GLSurfaceOSMesa {
public:
// Size doesn't matter, the surface is resized to the right size later.
- DRTSurfaceOSMesa() : GLSurfaceOSMesa(GL_RGBA, gfx::Size(1, 1)) {}
+ DRTSurfaceOSMesa()
+ : GLSurfaceOSMesa(gfx::OSMesaSurfaceFormatRGBA, gfx::Size(1, 1)) {}
// Implement a subset of GLSurface.
- virtual bool SwapBuffers() OVERRIDE;
+ bool SwapBuffers() override;
private:
- virtual ~DRTSurfaceOSMesa() {}
+ ~DRTSurfaceOSMesa() override {}
DISALLOW_COPY_AND_ASSIGN(DRTSurfaceOSMesa);
};
@@ -43,13 +43,13 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
GpuCommandBufferStub* stub,
const gfx::GLSurfaceHandle& surface_handle) {
DCHECK(surface_handle.transport_type == gfx::NATIVE_DIRECT ||
- surface_handle.transport_type == gfx::NATIVE_TRANSPORT);
+ surface_handle.transport_type == gfx::NULL_TRANSPORT);
switch (gfx::GetGLImplementation()) {
case gfx::kGLImplementationDesktopGL:
case gfx::kGLImplementationAppleGL:
return scoped_refptr<gfx::GLSurface>(new ImageTransportSurfaceFBO(
- new IOSurfaceStorageProvider, manager, stub, surface_handle.handle));
+ manager, stub, surface_handle.handle));
default:
// Content shell in DRT mode spins up a gpu process which needs an
// image transport surface, but that surface isn't used to read pixel
diff --git a/chromium/content/common/gpu/media/OWNERS b/chromium/content/common/gpu/media/OWNERS
index 76f86d18902..7f528c0ab51 100644
--- a/chromium/content/common/gpu/media/OWNERS
+++ b/chromium/content/common/gpu/media/OWNERS
@@ -1,7 +1,6 @@
-acolwell@chromium.org
dalecurtis@chromium.org
ddorwin@chromium.org
+posciak@chromium.org
scherkus@chromium.org
-shadi@chromium.org
vrk@chromium.org
xhwang@chromium.org
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator.cc b/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
index f72e1b257d7..0eee64152f5 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
@@ -89,7 +89,7 @@ bool AndroidVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
client_ = client;
- if (profile == media::VP8PROFILE_MAIN) {
+ if (profile == media::VP8PROFILE_ANY) {
codec_ = media::kCodecVP8;
} else {
// TODO(dwkang): enable H264 once b/8125974 is fixed.
@@ -357,16 +357,30 @@ void AndroidVideoDecodeAccelerator::SendCurrentSurfaceToClient(
// attached.
// 2. SurfaceTexture requires us to apply a transform matrix when we show
// the texture.
- copier_->DoCopyTexture(gl_decoder_.get(), GL_TEXTURE_EXTERNAL_OES,
- GL_TEXTURE_2D, surface_texture_id_,
- picture_buffer_texture_id, 0, size_.width(),
- size_.height(), false, false, false);
+ // TODO(hkuang): get the StreamTexture transform matrix in GPU process
+ // instead of using default matrix crbug.com/226218.
+ const static GLfloat default_matrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ copier_->DoCopyTextureWithTransform(gl_decoder_.get(),
+ GL_TEXTURE_EXTERNAL_OES,
+ surface_texture_id_,
+ picture_buffer_texture_id,
+ 0,
+ size_.width(),
+ size_.height(),
+ false,
+ false,
+ false,
+ default_matrix);
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady,
- weak_this_factory_.GetWeakPtr(),
- media::Picture(picture_buffer_id, bitstream_id)));
+ base::Bind(
+ &AndroidVideoDecodeAccelerator::NotifyPictureReady,
+ weak_this_factory_.GetWeakPtr(),
+ media::Picture(picture_buffer_id, bitstream_id, gfx::Rect(size_))));
}
void AndroidVideoDecodeAccelerator::Decode(
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator.h b/chromium/content/common/gpu/media/android_video_decode_accelerator.h
index 0e02ce4c1a8..2b41925af47 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator.h
@@ -38,15 +38,15 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// media::VideoDecodeAccelerator implementation.
virtual bool Initialize(media::VideoCodecProfile profile,
- Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
+ Client* client) override;
+ virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool CanDecodeOnIOThread() OVERRIDE;
+ const std::vector<media::PictureBuffer>& buffers) override;
+ virtual void ReusePictureBuffer(int32 picture_buffer_id) override;
+ virtual void Flush() override;
+ virtual void Reset() override;
+ virtual void Destroy() override;
+ virtual bool CanDecodeOnIOThread() override;
private:
enum State {
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc b/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
index 30b314e1371..e391d11ed4e 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
@@ -39,15 +39,15 @@ class MockVideoDecodeAcceleratorClient
// VideoDecodeAccelerator::Client implementation.
virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
const gfx::Size& dimensions,
- uint32 texture_target) OVERRIDE {};
- virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE {};
- virtual void PictureReady(const media::Picture& picture) OVERRIDE {};
+ uint32 texture_target) override {};
+ virtual void DismissPictureBuffer(int32 picture_buffer_id) override {};
+ virtual void PictureReady(const media::Picture& picture) override {};
virtual void NotifyEndOfBitstreamBuffer(
- int32 bitstream_buffer_id) OVERRIDE {};
- virtual void NotifyFlushDone() OVERRIDE {};
- virtual void NotifyResetDone() OVERRIDE {};
+ int32 bitstream_buffer_id) override {};
+ virtual void NotifyFlushDone() override {};
+ virtual void NotifyResetDone() override {};
virtual void NotifyError(
- media::VideoDecodeAccelerator::Error error) OVERRIDE {};
+ media::VideoDecodeAccelerator::Error error) override {};
};
class AndroidVideoDecodeAcceleratorTest : public testing::Test {
@@ -55,7 +55,7 @@ class AndroidVideoDecodeAcceleratorTest : public testing::Test {
virtual ~AndroidVideoDecodeAcceleratorTest() {}
protected:
- virtual void SetUp() OVERRIDE {
+ virtual void SetUp() override {
JNIEnv* env = base::android::AttachCurrentThread();
media::RegisterJni(env);
// TODO(felipeg): fix GL bindings, so that the decoder can perform GL
diff --git a/chromium/content/common/gpu/media/android_video_encode_accelerator.cc b/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
index 83593fa5901..9b703d70f97 100644
--- a/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -4,6 +4,8 @@
#include "content/common/gpu/media/android_video_encode_accelerator.h"
+#include <set>
+
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
@@ -26,8 +28,9 @@ using media::VideoFrame;
namespace content {
-enum {
+enum PixelFormat {
// Subset of MediaCodecInfo.CodecCapabilities.
+ COLOR_FORMAT_YUV420_PLANAR = 19,
COLOR_FORMAT_YUV420_SEMIPLANAR = 21,
};
@@ -67,6 +70,19 @@ static inline const base::TimeDelta NoWaitTimeOut() {
return base::TimeDelta::FromMicroseconds(0);
}
+static bool GetSupportedColorFormatForMime(const std::string& mime,
+ PixelFormat* pixel_format) {
+ std::set<int> formats = MediaCodecBridge::GetEncoderColorFormats(mime);
+ if (formats.count(COLOR_FORMAT_YUV420_SEMIPLANAR) > 0)
+ *pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
+ else if (formats.count(COLOR_FORMAT_YUV420_PLANAR) > 0)
+ *pixel_format = COLOR_FORMAT_YUV420_PLANAR;
+ else
+ return false;
+
+ return true;
+}
+
AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator()
: num_buffers_at_codec_(0),
num_output_buffers_(-1),
@@ -77,7 +93,6 @@ AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() {
DCHECK(thread_checker_.CalledOnValidThread());
}
-// static
std::vector<media::VideoEncodeAccelerator::SupportedProfile>
AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
std::vector<MediaCodecBridge::CodecsInfo> codecs_info =
@@ -86,7 +101,7 @@ AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
std::vector<SupportedProfile> profiles;
#if defined(ENABLE_WEBRTC)
- const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
return profiles;
#endif
@@ -100,13 +115,13 @@ AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
continue;
}
SupportedProfile profile;
- profile.profile = media::VP8PROFILE_MAIN;
+ profile.profile = media::VP8PROFILE_ANY;
// Wouldn't it be nice if MediaCodec exposed the maximum capabilities of the
// encoder? Sure would be. Too bad it doesn't. So we hard-code some
// reasonable defaults.
profile.max_resolution.SetSize(1920, 1088);
- profile.max_framerate.numerator = 30;
- profile.max_framerate.denominator = 1;
+ profile.max_framerate_numerator = 30;
+ profile.max_framerate_denominator = 1;
profiles.push_back(profile);
}
return profiles;
@@ -129,7 +144,7 @@ bool AndroidVideoEncodeAccelerator::Initialize(
if (!(media::MediaCodecBridge::SupportsSetParameters() &&
format == VideoFrame::I420 &&
- output_profile == media::VP8PROFILE_MAIN)) {
+ output_profile == media::VP8PROFILE_ANY)) {
DLOG(ERROR) << "Unexpected combo: " << format << ", " << output_profile;
return false;
}
@@ -143,17 +158,17 @@ bool AndroidVideoEncodeAccelerator::Initialize(
return false;
}
- // TODO(fischman): when there is more HW out there with different color-space
- // support, this should turn into a negotiation with the codec for supported
- // formats. For now we use the only format supported by the only available
- // HW.
- media_codec_.reset(
- media::VideoCodecBridge::CreateEncoder(media::kCodecVP8,
- input_visible_size,
- initial_bitrate,
- INITIAL_FRAMERATE,
- IFRAME_INTERVAL,
- COLOR_FORMAT_YUV420_SEMIPLANAR));
+ PixelFormat pixel_format = COLOR_FORMAT_YUV420_SEMIPLANAR;
+ if (!GetSupportedColorFormatForMime("video/x-vnd.on2.vp8", &pixel_format)) {
+ DLOG(ERROR) << "No color format support.";
+ return false;
+ }
+ media_codec_.reset(media::VideoCodecBridge::CreateEncoder(media::kCodecVP8,
+ input_visible_size,
+ initial_bitrate,
+ INITIAL_FRAMERATE,
+ IFRAME_INTERVAL,
+ pixel_format));
if (!media_codec_) {
DLOG(ERROR) << "Failed to create/start the codec: "
diff --git a/chromium/content/common/gpu/media/android_video_encode_accelerator.h b/chromium/content/common/gpu/media/android_video_encode_accelerator.h
index 0de1e1cfba5..f7f6eab374b 100644
--- a/chromium/content/common/gpu/media/android_video_encode_accelerator.h
+++ b/chromium/content/common/gpu/media/android_video_encode_accelerator.h
@@ -34,22 +34,21 @@ class CONTENT_EXPORT AndroidVideoEncodeAccelerator
AndroidVideoEncodeAccelerator();
virtual ~AndroidVideoEncodeAccelerator();
- static std::vector<media::VideoEncodeAccelerator::SupportedProfile>
- GetSupportedProfiles();
-
// media::VideoEncodeAccelerator implementation.
+ virtual std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+ GetSupportedProfiles() override;
virtual bool Initialize(media::VideoFrame::Format format,
const gfx::Size& input_visible_size,
media::VideoCodecProfile output_profile,
uint32 initial_bitrate,
- Client* client) OVERRIDE;
+ Client* client) override;
virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe) OVERRIDE;
+ bool force_keyframe) override;
virtual void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer)
- OVERRIDE;
+ override;
virtual void RequestEncodingParametersChange(uint32 bitrate,
- uint32 framerate) OVERRIDE;
- virtual void Destroy() OVERRIDE;
+ uint32 framerate) override;
+ virtual void Destroy() override;
private:
enum {
diff --git a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc
index 2e667d0bd1a..530358e155f 100644
--- a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -18,6 +18,7 @@
#include "base/callback.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
+#include "base/file_version_info.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
@@ -322,7 +323,7 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id());
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
base::win::ScopedComPtr<IDirect3DSurface9> d3d_surface;
hr = decoding_texture_->GetSurfaceLevel(0, d3d_surface.Receive());
@@ -361,7 +362,7 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
egl_display,
decoding_surface_,
EGL_BACK_BUFFER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, current_texture);
return true;
}
@@ -455,10 +456,9 @@ bool DXVAVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
// TODO(ananta)
// H264PROFILE_HIGH video decoding is janky at times. Needs more
- // investigation.
+ // investigation. http://crbug.com/426707
if (profile != media::H264PROFILE_BASELINE &&
- profile != media::H264PROFILE_MAIN &&
- profile != media::H264PROFILE_HIGH) {
+ profile != media::H264PROFILE_MAIN) {
RETURN_AND_NOTIFY_ON_FAILURE(false,
"Unsupported h264 profile", PLATFORM_FAILURE, false);
}
@@ -557,12 +557,25 @@ void DXVAVideoDecodeAccelerator::ReusePictureBuffer(
RETURN_AND_NOTIFY_ON_FAILURE((state_ != kUninitialized),
"Invalid state: " << state_, ILLEGAL_STATE,);
- if (output_picture_buffers_.empty())
+ if (output_picture_buffers_.empty() && stale_output_picture_buffers_.empty())
return;
OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
- RETURN_AND_NOTIFY_ON_FAILURE(it != output_picture_buffers_.end(),
- "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
+ // If we didn't find the picture id in the |output_picture_buffers_| map we
+ // try the |stale_output_picture_buffers_| map, as this may have been an
+ // output picture buffer from before a resolution change, that at resolution
+ // change time had yet to be displayed. The client is calling us back to tell
+ // us that we can now recycle this picture buffer, so if we were waiting to
+ // dispose of it we now can.
+ if (it == output_picture_buffers_.end()) {
+ it = stale_output_picture_buffers_.find(picture_buffer_id);
+ RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
+ "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
+ weak_this_factory_.GetWeakPtr(), picture_buffer_id));
+ return;
+ }
it->second->ReusePictureBuffer();
ProcessPendingSamples();
@@ -638,6 +651,19 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) {
"msmpeg2vdec.dll required for decoding is not loaded",
false);
+ // Check version of DLL, version 6.7.7140 is blacklisted due to high crash
+ // rates in browsers loading that DLL. If that is the version installed we
+ // fall back to software decoding. See crbug/403440.
+ FileVersionInfo* version_info =
+ FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll);
+ RETURN_ON_FAILURE(version_info,
+ "unable to get version of msmpeg2vdec.dll",
+ false);
+ base::string16 file_version = version_info->file_version();
+ RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos,
+ "blacklisted version of msmpeg2vdec.dll 6.7.7140",
+ false);
+
typedef HRESULT(WINAPI * GetClassObject)(
const CLSID & clsid, const IID & iid, void * *object);
@@ -943,7 +969,8 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
PLATFORM_FAILURE, );
media::Picture output_picture(index->second->id(),
- sample_info.input_buffer_id);
+ sample_info.input_buffer_id,
+ gfx::Rect(index->second->size()));
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::NotifyPictureReady,
@@ -981,6 +1008,7 @@ void DXVAVideoDecodeAccelerator::Invalidate() {
return;
weak_this_factory_.InvalidateWeakPtrs();
output_picture_buffers_.clear();
+ stale_output_picture_buffers_.clear();
pending_output_samples_.clear();
pending_input_buffers_.clear();
decoder_.Release();
@@ -1157,8 +1185,7 @@ void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers,
- weak_this_factory_.GetWeakPtr(),
- output_picture_buffers_));
+ weak_this_factory_.GetWeakPtr()));
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -1166,20 +1193,35 @@ void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
weak_this_factory_.GetWeakPtr(),
width,
height));
-
- output_picture_buffers_.clear();
}
-void DXVAVideoDecodeAccelerator::DismissStaleBuffers(
- const OutputBuffers& picture_buffers) {
- OutputBuffers::const_iterator index;
+void DXVAVideoDecodeAccelerator::DismissStaleBuffers() {
+ OutputBuffers::iterator index;
- for (index = picture_buffers.begin();
- index != picture_buffers.end();
+ for (index = output_picture_buffers_.begin();
+ index != output_picture_buffers_.end();
++index) {
- DVLOG(1) << "Dismissing picture id: " << index->second->id();
- client_->DismissPictureBuffer(index->second->id());
+ if (index->second->available()) {
+ DVLOG(1) << "Dismissing picture id: " << index->second->id();
+ client_->DismissPictureBuffer(index->second->id());
+ } else {
+ // Move to |stale_output_picture_buffers_| for deferred deletion.
+ stale_output_picture_buffers_.insert(
+ std::make_pair(index->first, index->second));
+ }
}
+
+ output_picture_buffers_.clear();
+}
+
+void DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer(
+ int32 picture_buffer_id) {
+ OutputBuffers::iterator it = stale_output_picture_buffers_.find(
+ picture_buffer_id);
+ DCHECK(it != stale_output_picture_buffers_.end());
+ DVLOG(1) << "Dismissing picture id: " << it->second->id();
+ client_->DismissPictureBuffer(it->second->id());
+ stale_output_picture_buffers_.erase(it);
}
} // namespace content
diff --git a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h
index 74ca5990b47..f53f4a12bc1 100644
--- a/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/dxva_video_decode_accelerator.h
@@ -6,7 +6,12 @@
#define CONTENT_COMMON_GPU_MEDIA_DXVA_VIDEO_DECODE_ACCELERATOR_H_
#include <d3d9.h>
+// Work around bug in this header by disabling the relevant warning for it.
+// https://connect.microsoft.com/VisualStudio/feedback/details/911260/dxva2api-h-in-win8-sdk-triggers-c4201-with-w4
+#pragma warning(push)
+#pragma warning(disable:4201)
#include <dxva2api.h>
+#pragma warning(pop)
#include <list>
#include <map>
#include <mfidl.h>
@@ -48,15 +53,15 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
// media::VideoDecodeAccelerator implementation.
virtual bool Initialize(media::VideoCodecProfile profile,
- Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
+ Client* client) override;
+ virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool CanDecodeOnIOThread() OVERRIDE;
+ const std::vector<media::PictureBuffer>& buffers) override;
+ virtual void ReusePictureBuffer(int32 picture_buffer_id) override;
+ virtual void Flush() override;
+ virtual void Reset() override;
+ virtual void Destroy() override;
+ virtual bool CanDecodeOnIOThread() override;
private:
typedef void* EGLConfig;
@@ -146,7 +151,10 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
typedef std::map<int32, linked_ptr<DXVAPictureBuffer> > OutputBuffers;
// Tells the client to dismiss the stale picture buffers passed in.
- void DismissStaleBuffers(const OutputBuffers& picture_buffers);
+ void DismissStaleBuffers();
+
+ // Called after the client indicates we can recycle a stale picture buffer.
+ void DeferredDismissStaleBuffer(int32 picture_buffer_id);
// To expose client callbacks from VideoDecodeAccelerator.
media::VideoDecodeAccelerator::Client* client_;
@@ -191,6 +199,12 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
// The key is the picture buffer id.
OutputBuffers output_picture_buffers_;
+ // After a resolution change there may be a few output buffers which have yet
+ // to be displayed so they cannot be dismissed immediately. We move them from
+ // |output_picture_buffers_| to this map so they may be dismissed once they
+ // become available.
+ OutputBuffers stale_output_picture_buffers_;
+
// Set to true if we requested picture slots from the client.
bool pictures_requested_;
diff --git a/chromium/content/common/gpu/media/exynos_v4l2_video_device.h b/chromium/content/common/gpu/media/exynos_v4l2_video_device.h
index 3745cbef7f7..d1498a66e18 100644
--- a/chromium/content/common/gpu/media/exynos_v4l2_video_device.h
+++ b/chromium/content/common/gpu/media/exynos_v4l2_video_device.h
@@ -18,28 +18,28 @@ class ExynosV4L2Device : public V4L2Device {
virtual ~ExynosV4L2Device();
// V4L2Device implementation.
- virtual int Ioctl(int request, void* arg) OVERRIDE;
- virtual bool Poll(bool poll_device, bool* event_pending) OVERRIDE;
- virtual bool SetDevicePollInterrupt() OVERRIDE;
- virtual bool ClearDevicePollInterrupt() OVERRIDE;
+ virtual int Ioctl(int request, void* arg) override;
+ virtual bool Poll(bool poll_device, bool* event_pending) override;
+ virtual bool SetDevicePollInterrupt() override;
+ virtual bool ClearDevicePollInterrupt() override;
virtual void* Mmap(void* addr,
unsigned int len,
int prot,
int flags,
- unsigned int offset) OVERRIDE;
- virtual void Munmap(void* addr, unsigned int len) OVERRIDE;
- virtual bool Initialize() OVERRIDE;
+ unsigned int offset) override;
+ virtual void Munmap(void* addr, unsigned int len) override;
+ virtual bool Initialize() override;
virtual EGLImageKHR CreateEGLImage(EGLDisplay egl_display,
EGLContext egl_context,
GLuint texture_id,
gfx::Size frame_buffer_size,
unsigned int buffer_index,
- size_t planes_count) OVERRIDE;
+ size_t planes_count) override;
virtual EGLBoolean DestroyEGLImage(EGLDisplay egl_display,
- EGLImageKHR egl_image) OVERRIDE;
- virtual GLenum GetTextureTarget() OVERRIDE;
- virtual uint32 PreferredInputFormat() OVERRIDE;
- virtual uint32 PreferredOutputFormat() OVERRIDE;
+ EGLImageKHR egl_image) override;
+ virtual GLenum GetTextureTarget() override;
+ virtual uint32 PreferredInputFormat() override;
+ virtual uint32 PreferredOutputFormat() override;
private:
const Type type_;
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
index 0d315dae4e8..2f71b827f66 100644
--- a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -76,20 +76,18 @@ class GpuVideoDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
MessageFilter(GpuVideoDecodeAccelerator* owner, int32 host_route_id)
: owner_(owner), host_route_id_(host_route_id) {}
- virtual void OnChannelError() OVERRIDE { sender_ = NULL; }
+ void OnChannelError() override { sender_ = NULL; }
- virtual void OnChannelClosing() OVERRIDE { sender_ = NULL; }
+ void OnChannelClosing() override { sender_ = NULL; }
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
- sender_ = sender;
- }
+ void OnFilterAdded(IPC::Sender* sender) override { sender_ = sender; }
- virtual void OnFilterRemoved() OVERRIDE {
+ void OnFilterRemoved() override {
// This will delete |owner_| and |this|.
owner_->OnFilterRemoved();
}
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& msg) override {
if (msg.routing_id() != host_route_id_)
return false;
@@ -111,7 +109,7 @@ class GpuVideoDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
}
protected:
- virtual ~MessageFilter() {}
+ ~MessageFilter() override {}
private:
GpuVideoDecodeAccelerator* owner_;
@@ -212,7 +210,8 @@ void GpuVideoDecodeAccelerator::PictureReady(
if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
host_route_id_,
picture.picture_buffer_id(),
- picture.bitstream_buffer_id()))) {
+ picture.bitstream_buffer_id(),
+ picture.visible_rect()))) {
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed";
}
}
@@ -258,7 +257,8 @@ void GpuVideoDecodeAccelerator::Initialize(
#elif defined(OS_MACOSX)
video_decode_accelerator_.reset(new VTVideoDecodeAccelerator(
static_cast<CGLContextObj>(
- stub_->decoder()->GetGLContext()->GetHandle())));
+ stub_->decoder()->GetGLContext()->GetHandle()),
+ make_context_current_));
#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
if (!device.get()) {
@@ -370,11 +370,12 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
- if (texture_target_ == GL_TEXTURE_EXTERNAL_OES) {
- // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the
- // underlying EGLImage. Use |texture_dimensions_| for this size.
+ if (texture_target_ == GL_TEXTURE_EXTERNAL_OES ||
+ texture_target_ == GL_TEXTURE_RECTANGLE) {
+ // These textures have their dimensions defined by the underlying storage.
+ // Use |texture_dimensions_| for this size.
texture_manager->SetLevelInfo(texture_ref,
- GL_TEXTURE_EXTERNAL_OES,
+ texture_target_,
0,
0,
texture_dimensions_.width(),
@@ -494,7 +495,7 @@ void GpuVideoDecodeAccelerator::SetTextureCleared(
gpu::gles2::TextureManager* texture_manager =
stub_->decoder()->GetContextGroup()->texture_manager();
DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0));
- texture_manager->SetLevelCleared(texture_ref, target, 0, true);
+ texture_manager->SetLevelCleared(texture_ref.get(), target, 0, true);
uncleared_textures_.erase(it);
}
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
index 05d9fb0a1b9..e59a76fb5c3 100644
--- a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
@@ -40,24 +40,24 @@ class GpuVideoDecodeAccelerator
const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// media::VideoDecodeAccelerator::Client implementation.
- virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
- const gfx::Size& dimensions,
- uint32 texture_target) OVERRIDE;
- virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void PictureReady(const media::Picture& picture) OVERRIDE;
- virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE;
- virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE;
- virtual void NotifyFlushDone() OVERRIDE;
- virtual void NotifyResetDone() OVERRIDE;
+ void ProvidePictureBuffers(uint32 requested_num_of_buffers,
+ const gfx::Size& dimensions,
+ uint32 texture_target) override;
+ void DismissPictureBuffer(int32 picture_buffer_id) override;
+ void PictureReady(const media::Picture& picture) override;
+ void NotifyError(media::VideoDecodeAccelerator::Error error) override;
+ void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) override;
+ void NotifyFlushDone() override;
+ void NotifyResetDone() override;
// GpuCommandBufferStub::DestructionObserver implementation.
- virtual void OnWillDestroyStub() OVERRIDE;
+ void OnWillDestroyStub() override;
// Function to delegate sending to actual sender.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// Initialize the accelerator with the given profile and send the
// |init_done_msg| when done.
@@ -68,7 +68,7 @@ class GpuVideoDecodeAccelerator
class MessageFilter;
// We only allow self-delete, from OnWillDestroyStub(), after cleanup there.
- virtual ~GpuVideoDecodeAccelerator();
+ ~GpuVideoDecodeAccelerator() override;
// Handlers for IPC messages.
void OnDecode(base::SharedMemoryHandle handle, int32 id, uint32 size);
diff --git a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
index 12c7b10b325..12b473fcce2 100644
--- a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
@@ -5,18 +5,27 @@
#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
#include "base/callback.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop_proxy.h"
#include "build/build_config.h"
#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/public/common/content_switches.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h"
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
+#if defined(OS_CHROMEOS) && defined(USE_X11)
+
+#if defined(ARCH_CPU_ARMEL)
#include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
+#elif defined(ARCH_CPU_X86_FAMILY)
+#include "content/common/gpu/media/vaapi_video_encode_accelerator.h"
+#include "ui/gfx/x/x11_types.h"
+#endif
+
#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
#include "content/common/gpu/media/android_video_encode_accelerator.h"
#endif
@@ -86,7 +95,7 @@ void GpuVideoEncodeAccelerator::Initialize(
return;
}
- CreateEncoder();
+ encoder_ = CreateEncoder();
if (!encoder_) {
DLOG(ERROR)
<< "GpuVideoEncodeAccelerator::Initialize(): VEA creation failed";
@@ -154,31 +163,48 @@ void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
}
// static
-std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+std::vector<gpu::VideoEncodeAcceleratorSupportedProfile>
GpuVideoEncodeAccelerator::GetSupportedProfiles() {
- std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles;
-
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
- profiles = V4L2VideoEncodeAccelerator::GetSupportedProfiles();
-#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
- profiles = AndroidVideoEncodeAccelerator::GetSupportedProfiles();
-#endif
+ scoped_ptr<media::VideoEncodeAccelerator> encoder = CreateEncoder();
+ if (!encoder)
+ return std::vector<gpu::VideoEncodeAcceleratorSupportedProfile>();
+ return ConvertMediaToGpuProfiles(encoder->GetSupportedProfiles());
+}
- // TODO(sheu): return platform-specific profiles.
+std::vector<gpu::VideoEncodeAcceleratorSupportedProfile>
+GpuVideoEncodeAccelerator::ConvertMediaToGpuProfiles(const std::vector<
+ media::VideoEncodeAccelerator::SupportedProfile>& media_profiles) {
+ std::vector<gpu::VideoEncodeAcceleratorSupportedProfile> profiles;
+ for (size_t i = 0; i < media_profiles.size(); i++) {
+ gpu::VideoEncodeAcceleratorSupportedProfile profile;
+ profile.profile =
+ static_cast<gpu::VideoCodecProfile>(media_profiles[i].profile);
+ profile.max_resolution = media_profiles[i].max_resolution;
+ profile.max_framerate_numerator = media_profiles[i].max_framerate_numerator;
+ profile.max_framerate_denominator =
+ media_profiles[i].max_framerate_denominator;
+ profiles.push_back(profile);
+ }
return profiles;
}
-void GpuVideoEncodeAccelerator::CreateEncoder() {
- DCHECK(!encoder_);
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) && defined(USE_X11)
+scoped_ptr<media::VideoEncodeAccelerator>
+GpuVideoEncodeAccelerator::CreateEncoder() {
+ scoped_ptr<media::VideoEncodeAccelerator> encoder;
+#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(ARCH_CPU_ARMEL)
scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder);
- if (!device.get())
- return;
-
- encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass()));
+ if (device)
+ encoder.reset(new V4L2VideoEncodeAccelerator(device.Pass()));
+#elif defined(ARCH_CPU_X86_FAMILY)
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ if (!cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
+ encoder.reset(new VaapiVideoEncodeAccelerator(gfx::GetXDisplay()));
+#endif
#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
- encoder_.reset(new AndroidVideoEncodeAccelerator());
+ encoder.reset(new AndroidVideoEncodeAccelerator());
#endif
+ return encoder.Pass();
}
void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id,
@@ -226,7 +252,7 @@ void GpuVideoEncodeAccelerator::OnEncode(int32 frame_id,
frame_id,
base::Passed(&shm))));
- if (!frame) {
+ if (!frame.get()) {
DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode(): "
"could not create VideoFrame for frame_id=" << frame_id;
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
diff --git a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h
index 7b1da6b2fe5..ca60f6f1c8d 100644
--- a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h
+++ b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/gpu/gpu_command_buffer_stub.h"
+#include "gpu/config/gpu_info.h"
#include "ipc/ipc_listener.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/gfx/size.h"
@@ -31,7 +32,7 @@ class GpuVideoEncodeAccelerator
public GpuCommandBufferStub::DestructionObserver {
public:
GpuVideoEncodeAccelerator(int32 host_route_id, GpuCommandBufferStub* stub);
- virtual ~GpuVideoEncodeAccelerator();
+ ~GpuVideoEncodeAccelerator() override;
// Initialize this accelerator with the given parameters and send
// |init_done_msg| when complete.
@@ -42,28 +43,31 @@ class GpuVideoEncodeAccelerator
IPC::Message* init_done_msg);
// IPC::Listener implementation
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// media::VideoEncodeAccelerator::Client implementation.
- virtual void RequireBitstreamBuffers(unsigned int input_count,
- const gfx::Size& input_coded_size,
- size_t output_buffer_size) OVERRIDE;
- virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
- size_t payload_size,
- bool key_frame) OVERRIDE;
- virtual void NotifyError(media::VideoEncodeAccelerator::Error error) OVERRIDE;
+ void RequireBitstreamBuffers(unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) override;
+ void BitstreamBufferReady(int32 bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame) override;
+ void NotifyError(media::VideoEncodeAccelerator::Error error) override;
// GpuCommandBufferStub::DestructionObserver implementation.
- virtual void OnWillDestroyStub() OVERRIDE;
+ void OnWillDestroyStub() override;
// Static query for supported profiles. This query calls the appropriate
// platform-specific version.
- static std::vector<media::VideoEncodeAccelerator::SupportedProfile>
- GetSupportedProfiles();
+ static std::vector<gpu::VideoEncodeAcceleratorSupportedProfile>
+ GetSupportedProfiles();
+ static std::vector<gpu::VideoEncodeAcceleratorSupportedProfile>
+ ConvertMediaToGpuProfiles(const std::vector<
+ media::VideoEncodeAccelerator::SupportedProfile>& media_profiles);
private:
// Create the appropriate platform-specific VEA.
- void CreateEncoder();
+ static scoped_ptr<media::VideoEncodeAccelerator> CreateEncoder();
// IPC handlers, proxying media::VideoEncodeAccelerator for the renderer
// process.
diff --git a/chromium/content/common/gpu/media/h264_dpb.h b/chromium/content/common/gpu/media/h264_dpb.h
index 29be0bcfeda..366c47a78cd 100644
--- a/chromium/content/common/gpu/media/h264_dpb.h
+++ b/chromium/content/common/gpu/media/h264_dpb.h
@@ -41,6 +41,7 @@ struct H264Picture {
int frame_num_wrap;
int long_term_frame_idx;
+ media::H264SliceHeader::Type type;
bool idr; // IDR picture?
bool ref; // reference picture?
bool long_term; // long term reference picture?
diff --git a/chromium/content/common/gpu/media/rendering_helper.cc b/chromium/content/common/gpu/media/rendering_helper.cc
index 4b7bb192b26..5870ceef564 100644
--- a/chromium/content/common/gpu/media/rendering_helper.cc
+++ b/chromium/content/common/gpu/media/rendering_helper.cc
@@ -9,14 +9,18 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringize_macros.h"
#include "base/synchronization/waitable_event.h"
+#include "base/time/time.h"
#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_glx.h"
#if defined(OS_WIN)
#include <windows.h>
@@ -26,10 +30,10 @@
#include "ui/gfx/x/x11_types.h"
#endif
-#ifdef GL_VARIANT_GLX
-struct XFreeDeleter {
- void operator()(void* x) const { ::XFree(x); }
-};
+#if !defined(OS_WIN) && defined(ARCH_CPU_X86_FAMILY)
+#define GL_VARIANT_GLX 1
+#else
+#define GL_VARIANT_EGL 1
#endif
// Helper for Shader creation.
@@ -54,137 +58,77 @@ static void CreateShader(GLuint program,
namespace content {
-RenderingHelperParams::RenderingHelperParams() {}
+RenderingHelperParams::RenderingHelperParams()
+ : rendering_fps(0), warm_up_iterations(0), render_as_thumbnails(false) {
+}
RenderingHelperParams::~RenderingHelperParams() {}
-static const gfx::GLImplementation kGLImplementation =
-#if defined(GL_VARIANT_GLX)
- gfx::kGLImplementationDesktopGL;
-#elif defined(GL_VARIANT_EGL)
- gfx::kGLImplementationEGLGLES2;
-#else
- -1;
-#error "Unknown GL implementation."
-#endif
+VideoFrameTexture::VideoFrameTexture(uint32 texture_target,
+ uint32 texture_id,
+ const base::Closure& no_longer_needed_cb)
+ : texture_target_(texture_target),
+ texture_id_(texture_id),
+ no_longer_needed_cb_(no_longer_needed_cb) {
+ DCHECK(!no_longer_needed_cb_.is_null());
+}
-RenderingHelper::RenderingHelper() {
-#if defined(GL_VARIANT_EGL)
- gl_surface_ = EGL_NO_SURFACE;
-#endif
+VideoFrameTexture::~VideoFrameTexture() {
+ base::ResetAndReturn(&no_longer_needed_cb_).Run();
+}
-#if defined(OS_WIN)
- window_ = NULL;
+RenderingHelper::RenderedVideo::RenderedVideo()
+ : is_flushing(false), frames_to_drop(0) {
+}
+
+RenderingHelper::RenderedVideo::~RenderedVideo() {
+}
+
+// static
+bool RenderingHelper::InitializeOneOff() {
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+#if GL_VARIANT_GLX
+ cmd_line->AppendSwitchASCII(switches::kUseGL,
+ gfx::kGLImplementationDesktopName);
#else
- x_window_ = (Window)0;
+ cmd_line->AppendSwitchASCII(switches::kUseGL, gfx::kGLImplementationEGLName);
#endif
+ return gfx::GLSurface::InitializeOneOff();
+}
+RenderingHelper::RenderingHelper() {
+ window_ = gfx::kNullAcceleratedWidget;
Clear();
}
RenderingHelper::~RenderingHelper() {
- CHECK_EQ(clients_.size(), 0U) << "Must call UnInitialize before dtor.";
+ CHECK_EQ(videos_.size(), 0U) << "Must call UnInitialize before dtor.";
Clear();
}
void RenderingHelper::Initialize(const RenderingHelperParams& params,
base::WaitableEvent* done) {
- // Use cients_.size() != 0 as a proxy for the class having already been
+ // Use videos_.size() != 0 as a proxy for the class having already been
// Initialize()'d, and UnInitialize() before continuing.
- if (clients_.size()) {
+ if (videos_.size()) {
base::WaitableEvent done(false, false);
UnInitialize(&done);
done.Wait();
}
+ render_task_.Reset(
+ base::Bind(&RenderingHelper::RenderContent, base::Unretained(this)));
+
frame_duration_ = params.rendering_fps > 0
? base::TimeDelta::FromSeconds(1) / params.rendering_fps
: base::TimeDelta();
- gfx::InitializeStaticGLBindings(kGLImplementation);
- scoped_refptr<gfx::GLContextStubWithExtensions> stub_context(
- new gfx::GLContextStubWithExtensions());
-
render_as_thumbnails_ = params.render_as_thumbnails;
message_loop_ = base::MessageLoop::current();
-#if GL_VARIANT_GLX
- x_display_ = gfx::GetXDisplay();
- CHECK(x_display_);
- CHECK(glXQueryVersion(x_display_, NULL, NULL));
- const int fbconfig_attr[] = {
- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
- GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE,
- GLX_DOUBLEBUFFER, True,
- GL_NONE,
- };
- int num_fbconfigs;
- scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs(
- glXChooseFBConfig(x_display_, DefaultScreen(x_display_), fbconfig_attr,
- &num_fbconfigs));
- CHECK(glx_fb_configs.get());
- CHECK_GT(num_fbconfigs, 0);
- x_visual_ = glXGetVisualFromFBConfig(x_display_, glx_fb_configs.get()[0]);
- CHECK(x_visual_);
- gl_context_ = glXCreateContext(x_display_, x_visual_, 0, true);
- CHECK(gl_context_);
- stub_context->AddExtensionsString(
- reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
- stub_context->SetGLVersionString(
- reinterpret_cast<const char*>(glGetString(GL_VERSION)));
-
- Screen* screen = DefaultScreenOfDisplay(x_display_);
- screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen));
-#else // EGL
- EGLNativeDisplayType native_display;
-
#if defined(OS_WIN)
- native_display = EGL_DEFAULT_DISPLAY;
screen_size_ =
gfx::Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
-#else
- x_display_ = gfx::GetXDisplay();
- CHECK(x_display_);
- native_display = x_display_;
-
- Screen* screen = DefaultScreenOfDisplay(x_display_);
- screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen));
-#endif
- gl_display_ = eglGetDisplay(native_display);
- CHECK(gl_display_);
- CHECK(eglInitialize(gl_display_, NULL, NULL)) << eglGetError();
-
- static EGLint rgba8888[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_NONE,
- };
- EGLConfig egl_config;
- int num_configs;
- CHECK(eglChooseConfig(gl_display_, rgba8888, &egl_config, 1, &num_configs))
- << eglGetError();
- CHECK_GE(num_configs, 1);
- static EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
- gl_context_ = eglCreateContext(
- gl_display_, egl_config, EGL_NO_CONTEXT, context_attribs);
- CHECK_NE(gl_context_, EGL_NO_CONTEXT) << eglGetError();
- stub_context->AddExtensionsString(
- reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
- stub_context->AddExtensionsString(
- eglQueryString(gl_display_, EGL_EXTENSIONS));
- stub_context->SetGLVersionString(
- reinterpret_cast<const char*>(glGetString(GL_VERSION)));
-#endif
- clients_ = params.clients;
- CHECK_GT(clients_.size(), 0U);
- LayoutRenderingAreas();
-
-#if defined(OS_WIN)
window_ = CreateWindowEx(0,
L"Static",
L"VideoDecodeAcceleratorTest",
@@ -197,59 +141,51 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
NULL,
NULL,
NULL);
- CHECK(window_ != NULL);
-#else
- int depth = DefaultDepth(x_display_, DefaultScreen(x_display_));
+#elif defined(USE_X11)
+ Display* display = gfx::GetXDisplay();
+ Screen* screen = DefaultScreenOfDisplay(display);
+ screen_size_ = gfx::Size(XWidthOfScreen(screen), XHeightOfScreen(screen));
-#if defined(GL_VARIANT_GLX)
- CHECK_EQ(depth, x_visual_->depth);
-#endif
+ CHECK(display);
XSetWindowAttributes window_attributes;
+ memset(&window_attributes, 0, sizeof(window_attributes));
window_attributes.background_pixel =
- BlackPixel(x_display_, DefaultScreen(x_display_));
+ BlackPixel(display, DefaultScreen(display));
window_attributes.override_redirect = true;
-
- x_window_ = XCreateWindow(x_display_,
- DefaultRootWindow(x_display_),
- 0,
- 0,
- screen_size_.width(),
- screen_size_.height(),
- 0 /* border width */,
- depth,
- CopyFromParent /* class */,
- CopyFromParent /* visual */,
- (CWBackPixel | CWOverrideRedirect),
- &window_attributes);
- XStoreName(x_display_, x_window_, "VideoDecodeAcceleratorTest");
- XSelectInput(x_display_, x_window_, ExposureMask);
- XMapWindow(x_display_, x_window_);
-#endif
-
-#if GL_VARIANT_EGL
-#if defined(OS_WIN)
- gl_surface_ =
- eglCreateWindowSurface(gl_display_, egl_config, window_, NULL);
+ int depth = DefaultDepth(display, DefaultScreen(display));
+
+ window_ = XCreateWindow(display,
+ DefaultRootWindow(display),
+ 0,
+ 0,
+ screen_size_.width(),
+ screen_size_.height(),
+ 0 /* border width */,
+ depth,
+ CopyFromParent /* class */,
+ CopyFromParent /* visual */,
+ (CWBackPixel | CWOverrideRedirect),
+ &window_attributes);
+ XStoreName(display, window_, "VideoDecodeAcceleratorTest");
+ XSelectInput(display, window_, ExposureMask);
+ XMapWindow(display, window_);
#else
- gl_surface_ =
- eglCreateWindowSurface(gl_display_, egl_config, x_window_, NULL);
-#endif
- CHECK_NE(gl_surface_, EGL_NO_SURFACE);
+#error unknown platform
#endif
+ CHECK(window_ != gfx::kNullAcceleratedWidget);
-#if GL_VARIANT_GLX
- CHECK(glXMakeContextCurrent(x_display_, x_window_, x_window_, gl_context_));
-#else // EGL
- CHECK(eglMakeCurrent(gl_display_, gl_surface_, gl_surface_, gl_context_))
- << eglGetError();
-#endif
+ gl_surface_ = gfx::GLSurface::CreateViewGLSurface(window_);
+ gl_context_ = gfx::GLContext::CreateGLContext(
+ NULL, gl_surface_.get(), gfx::PreferIntegratedGpu);
+ gl_context_->MakeCurrent(gl_surface_.get());
- // Must be done after a context is made current.
- gfx::InitializeDynamicGLBindings(kGLImplementation, stub_context.get());
+ CHECK_GT(params.window_sizes.size(), 0U);
+ videos_.resize(params.window_sizes.size());
+ LayoutRenderingAreas(params.window_sizes);
if (render_as_thumbnails_) {
- CHECK_EQ(clients_.size(), 1U);
+ CHECK_EQ(videos_.size(), 1U);
GLint max_texture_size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
@@ -275,6 +211,7 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER, thumbnails_fbo_id_);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
@@ -367,32 +304,54 @@ void RenderingHelper::Initialize(const RenderingHelperParams& params,
glEnableVertexAttribArray(tc_location);
glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, kTextureCoords);
- if (frame_duration_ != base::TimeDelta()) {
- render_timer_.Start(
- FROM_HERE, frame_duration_, this, &RenderingHelper::RenderContent);
+ if (frame_duration_ != base::TimeDelta())
+ WarmUpRendering(params.warm_up_iterations);
+
+ // It's safe to use Unretained here since |rendering_thread_| will be stopped
+ // in VideoDecodeAcceleratorTest.TearDown(), while the |rendering_helper_| is
+ // a member of that class. (See video_decode_accelerator_unittest.cc.)
+ gl_surface_->GetVSyncProvider()->GetVSyncParameters(base::Bind(
+ &RenderingHelper::UpdateVSyncParameters, base::Unretained(this), done));
+}
+
+// The rendering for the first few frames is slow (e.g., 100ms on Peach Pit).
+// This affects the numbers measured in the performance test. We try to render
+// several frames here to warm up the rendering.
+void RenderingHelper::WarmUpRendering(int warm_up_iterations) {
+ unsigned int texture_id;
+ scoped_ptr<GLubyte[]> emptyData(new GLubyte[screen_size_.GetArea() * 2]);
+ glGenTextures(1, &texture_id);
+ glBindTexture(GL_TEXTURE_2D, texture_id);
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ GL_RGB,
+ screen_size_.width(),
+ screen_size_.height(),
+ 0,
+ GL_RGB,
+ GL_UNSIGNED_SHORT_5_6_5,
+ emptyData.get());
+ for (int i = 0; i < warm_up_iterations; ++i) {
+ RenderTexture(GL_TEXTURE_2D, texture_id);
+ gl_surface_->SwapBuffers();
}
- done->Signal();
+ glDeleteTextures(1, &texture_id);
}
void RenderingHelper::UnInitialize(base::WaitableEvent* done) {
CHECK_EQ(base::MessageLoop::current(), message_loop_);
- render_timer_.Stop();
+
+ render_task_.Cancel();
+
if (render_as_thumbnails_) {
glDeleteTextures(1, &thumbnails_texture_id_);
glDeleteFramebuffersEXT(1, &thumbnails_fbo_id_);
}
-#if GL_VARIANT_GLX
- glXDestroyContext(x_display_, gl_context_);
-#else // EGL
- CHECK(eglMakeCurrent(
- gl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT))
- << eglGetError();
- CHECK(eglDestroyContext(gl_display_, gl_context_));
- CHECK(eglDestroySurface(gl_display_, gl_surface_));
- CHECK(eglTerminate(gl_display_));
-#endif
- gfx::ClearGLBindings();
+ gl_context_->ReleaseCurrent(gl_surface_.get());
+ gl_context_ = NULL;
+ gl_surface_ = NULL;
+
Clear();
done->Signal();
}
@@ -456,9 +415,34 @@ void RenderingHelper::RenderThumbnail(uint32 texture_target,
GLSetViewPort(area);
RenderTexture(texture_target, texture_id);
glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
+
+ // Need to flush the GL commands before we return the tnumbnail texture to
+ // the decoder.
+ glFlush();
++frame_count_;
}
+void RenderingHelper::QueueVideoFrame(
+ size_t window_id,
+ scoped_refptr<VideoFrameTexture> video_frame) {
+ CHECK_EQ(base::MessageLoop::current(), message_loop_);
+ RenderedVideo* video = &videos_[window_id];
+ DCHECK(!video->is_flushing);
+
+ video->pending_frames.push(video_frame);
+
+ if (video->frames_to_drop > 0 && video->pending_frames.size() > 1) {
+ --video->frames_to_drop;
+ video->pending_frames.pop();
+ }
+
+ // Schedules the first RenderContent() if need.
+ if (scheduled_render_time_.is_null()) {
+ scheduled_render_time_ = base::TimeTicks::Now();
+ message_loop_->PostTask(FROM_HERE, render_task_.callback());
+ }
+}
+
void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
// The ExternalOES sampler is bound to GL_TEXTURE1 and the Texture2D sampler
// is bound to GL_TEXTURE0.
@@ -474,48 +458,41 @@ void RenderingHelper::RenderTexture(uint32 texture_target, uint32 texture_id) {
}
void RenderingHelper::DeleteTexture(uint32 texture_id) {
+ CHECK_EQ(base::MessageLoop::current(), message_loop_);
glDeleteTextures(1, &texture_id);
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}
-NativeContextType RenderingHelper::GetGLContext() { return gl_context_; }
+void* RenderingHelper::GetGLContext() {
+ return gl_context_->GetHandle();
+}
void* RenderingHelper::GetGLDisplay() {
-#if GL_VARIANT_GLX
- return x_display_;
-#else // EGL
- return gl_display_;
-#endif
+ return gl_surface_->GetDisplay();
}
void RenderingHelper::Clear() {
- clients_.clear();
+ videos_.clear();
message_loop_ = NULL;
gl_context_ = NULL;
-#if GL_VARIANT_EGL
- gl_display_ = EGL_NO_DISPLAY;
- gl_surface_ = EGL_NO_SURFACE;
-#endif
+ gl_surface_ = NULL;
+
render_as_thumbnails_ = false;
frame_count_ = 0;
thumbnails_fbo_id_ = 0;
thumbnails_texture_id_ = 0;
#if defined(OS_WIN)
- if (window_) {
+ if (window_)
DestroyWindow(window_);
- window_ = NULL;
- }
#else
// Destroy resources acquired in Initialize, in reverse-acquisition order.
- if (x_window_) {
- CHECK(XUnmapWindow(x_display_, x_window_));
- CHECK(XDestroyWindow(x_display_, x_window_));
- x_window_ = (Window)0;
+ if (window_) {
+ CHECK(XUnmapWindow(gfx::GetXDisplay(), window_));
+ CHECK(XDestroyWindow(gfx::GetXDisplay(), window_));
}
- // Mimic newly created object.
- x_display_ = NULL;
#endif
+ window_ = gfx::kNullAcceleratedWidget;
}
void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
@@ -554,29 +531,58 @@ void RenderingHelper::GetThumbnailsAsRGB(std::vector<unsigned char>* rgb,
done->Signal();
}
+void RenderingHelper::Flush(size_t window_id) {
+ videos_[window_id].is_flushing = true;
+}
+
void RenderingHelper::RenderContent() {
+ CHECK_EQ(base::MessageLoop::current(), message_loop_);
+
+ // Update the VSync params.
+ //
+ // It's safe to use Unretained here since |rendering_thread_| will be stopped
+ // in VideoDecodeAcceleratorTest.TearDown(), while the |rendering_helper_| is
+ // a member of that class. (See video_decode_accelerator_unittest.cc.)
+ gl_surface_->GetVSyncProvider()->GetVSyncParameters(
+ base::Bind(&RenderingHelper::UpdateVSyncParameters,
+ base::Unretained(this),
+ static_cast<base::WaitableEvent*>(NULL)));
+
glUniform1i(glGetUniformLocation(program_, "tex_flip"), 1);
+ // Frames that will be returned to the client (via the no_longer_needed_cb)
+ // after this vector falls out of scope at the end of this method. We need
+ // to keep references to them until after SwapBuffers() call below.
+ std::vector<scoped_refptr<VideoFrameTexture> > frames_to_be_returned;
+ bool need_swap_buffer = false;
if (render_as_thumbnails_) {
// In render_as_thumbnails_ mode, we render the FBO content on the
// screen instead of the decoded textures.
- GLSetViewPort(render_areas_[0]);
+ GLSetViewPort(videos_[0].render_area);
RenderTexture(GL_TEXTURE_2D, thumbnails_texture_id_);
+ need_swap_buffer = true;
} else {
- for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i]) {
- GLSetViewPort(render_areas_[i]);
- clients_[i]->RenderContent(this);
+ for (RenderedVideo& video : videos_) {
+ if (video.pending_frames.empty())
+ continue;
+ need_swap_buffer = true;
+ scoped_refptr<VideoFrameTexture> frame = video.pending_frames.front();
+ GLSetViewPort(video.render_area);
+ RenderTexture(frame->texture_target(), frame->texture_id());
+
+ if (video.pending_frames.size() > 1 || video.is_flushing) {
+ frames_to_be_returned.push_back(video.pending_frames.front());
+ video.pending_frames.pop();
+ } else {
+ ++video.frames_to_drop;
}
}
}
-#if GL_VARIANT_GLX
- glXSwapBuffers(x_display_, x_window_);
-#else // EGL
- eglSwapBuffers(gl_display_, gl_surface_);
- CHECK_EQ(static_cast<int>(eglGetError()), EGL_SUCCESS);
-#endif
+ if (need_swap_buffer)
+ gl_surface_->SwapBuffers();
+
+ ScheduleNextRenderContent();
}
// Helper function for the LayoutRenderingAreas(). The |lengths| are the
@@ -593,11 +599,12 @@ static void ScaleAndCalculateOffsets(std::vector<int>* lengths,
}
}
-void RenderingHelper::LayoutRenderingAreas() {
+void RenderingHelper::LayoutRenderingAreas(
+ const std::vector<gfx::Size>& window_sizes) {
// Find the number of colums and rows.
- // The smallest n * n or n * (n + 1) > number of clients.
- size_t cols = sqrt(clients_.size() - 1) + 1;
- size_t rows = (clients_.size() + cols - 1) / cols;
+ // The smallest n * n or n * (n + 1) > number of windows.
+ size_t cols = sqrt(videos_.size() - 1) + 1;
+ size_t rows = (videos_.size() + cols - 1) / cols;
// Find the widths and heights of the grid.
std::vector<int> widths(cols);
@@ -605,31 +612,75 @@ void RenderingHelper::LayoutRenderingAreas() {
std::vector<int> offset_x(cols);
std::vector<int> offset_y(rows);
- for (size_t i = 0; i < clients_.size(); ++i) {
- const gfx::Size& window_size = clients_[i]->GetWindowSize();
- widths[i % cols] = std::max(widths[i % cols], window_size.width());
- heights[i / cols] = std::max(heights[i / cols], window_size.height());
+ for (size_t i = 0; i < window_sizes.size(); ++i) {
+ const gfx::Size& size = window_sizes[i];
+ widths[i % cols] = std::max(widths[i % cols], size.width());
+ heights[i / cols] = std::max(heights[i / cols], size.height());
}
ScaleAndCalculateOffsets(&widths, &offset_x, screen_size_.width());
ScaleAndCalculateOffsets(&heights, &offset_y, screen_size_.height());
// Put each render_area_ in the center of each cell.
- render_areas_.clear();
- for (size_t i = 0; i < clients_.size(); ++i) {
- const gfx::Size& window_size = clients_[i]->GetWindowSize();
+ for (size_t i = 0; i < window_sizes.size(); ++i) {
+ const gfx::Size& size = window_sizes[i];
float scale =
- std::min(static_cast<float>(widths[i % cols]) / window_size.width(),
- static_cast<float>(heights[i / cols]) / window_size.height());
+ std::min(static_cast<float>(widths[i % cols]) / size.width(),
+ static_cast<float>(heights[i / cols]) / size.height());
// Don't scale up the texture.
scale = std::min(1.0f, scale);
- size_t w = scale * window_size.width();
- size_t h = scale * window_size.height();
+ size_t w = scale * size.width();
+ size_t h = scale * size.height();
size_t x = offset_x[i % cols] + (widths[i % cols] - w) / 2;
size_t y = offset_y[i / cols] + (heights[i / cols] - h) / 2;
- render_areas_.push_back(gfx::Rect(x, y, w, h));
+ videos_[i].render_area = gfx::Rect(x, y, w, h);
}
}
+
+void RenderingHelper::UpdateVSyncParameters(base::WaitableEvent* done,
+ const base::TimeTicks timebase,
+ const base::TimeDelta interval) {
+ vsync_timebase_ = timebase;
+ vsync_interval_ = interval;
+
+ if (done)
+ done->Signal();
+}
+
+void RenderingHelper::DropOneFrameForAllVideos() {
+ for (RenderedVideo& video : videos_) {
+ if (video.pending_frames.empty())
+ continue;
+
+ if (video.pending_frames.size() > 1 || video.is_flushing) {
+ video.pending_frames.pop();
+ } else {
+ ++video.frames_to_drop;
+ }
+ }
+}
+
+void RenderingHelper::ScheduleNextRenderContent() {
+ scheduled_render_time_ += frame_duration_;
+
+ // Schedules the next RenderContent() at latest VSYNC before the
+ // |scheduled_render_time_|.
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks target =
+ std::max(now + vsync_interval_, scheduled_render_time_);
+
+ int64 intervals = (target - vsync_timebase_) / vsync_interval_;
+ target = vsync_timebase_ + intervals * vsync_interval_;
+
+ // When the rendering falls behind, drops frames.
+ while (scheduled_render_time_ < target) {
+ scheduled_render_time_ += frame_duration_;
+ DropOneFrameForAllVideos();
+ }
+
+ message_loop_->PostDelayedTask(
+ FROM_HERE, render_task_.callback(), target - now);
+}
} // namespace content
diff --git a/chromium/content/common/gpu/media/rendering_helper.h b/chromium/content/common/gpu/media/rendering_helper.h
index 597184cc0ff..e66c8d5964f 100644
--- a/chromium/content/common/gpu/media/rendering_helper.h
+++ b/chromium/content/common/gpu/media/rendering_helper.h
@@ -6,53 +6,82 @@
#define CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
#include <map>
+#include <queue>
#include <vector>
#include "base/basictypes.h"
+#include "base/cancelable_callback.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
namespace base {
class MessageLoop;
class WaitableEvent;
}
-#if !defined(OS_WIN) && defined(ARCH_CPU_X86_FAMILY)
-#define GL_VARIANT_GLX 1
-typedef GLXContext NativeContextType;
-#else
-#define GL_VARIANT_EGL 1
-typedef EGLContext NativeContextType;
-#endif
-
namespace content {
-struct RenderingHelperParams;
+class VideoFrameTexture : public base::RefCounted<VideoFrameTexture> {
+ public:
+ uint32 texture_id() const { return texture_id_; }
+ uint32 texture_target() const { return texture_target_; }
+
+ VideoFrameTexture(uint32 texture_target,
+ uint32 texture_id,
+ const base::Closure& no_longer_needed_cb);
+
+ private:
+ friend class base::RefCounted<VideoFrameTexture>;
+
+ uint32 texture_target_;
+ uint32 texture_id_;
+ base::Closure no_longer_needed_cb_;
+
+ ~VideoFrameTexture();
+};
+
+struct RenderingHelperParams {
+ RenderingHelperParams();
+ ~RenderingHelperParams();
+
+ // The rendering FPS.
+ int rendering_fps;
+
+ // The number of empty frames rendered when the rendering helper is
+ // initialized.
+ int warm_up_iterations;
+
+ // The desired size of each window. We play each stream in its own window
+ // on the screen.
+ std::vector<gfx::Size> window_sizes;
+
+ // The members below are only used for the thumbnail mode where all frames
+ // are rendered in sequence onto one FBO for comparison/verification purposes.
+
+ // Whether the frames are rendered as scaled thumbnails within a
+ // larger FBO that is in turn rendered to the window.
+ bool render_as_thumbnails;
+ // The size of the FBO containing all visible thumbnails.
+ gfx::Size thumbnails_page_size;
+ // The size of each thumbnail within the FBO.
+ gfx::Size thumbnail_size;
+};
// Creates and draws textures used by the video decoder.
// This class is not thread safe and thus all the methods of this class
// (except for ctor/dtor) ensure they're being run on a single thread.
class RenderingHelper {
public:
- // Interface for the content provider of the RenderingHelper.
- class Client {
- public:
- // Callback to tell client to render the content.
- virtual void RenderContent(RenderingHelper* helper) = 0;
-
- // Callback to get the desired window size of the client.
- virtual const gfx::Size& GetWindowSize() = 0;
-
- protected:
- virtual ~Client() {}
- };
RenderingHelper();
~RenderingHelper();
+ static bool InitializeOneOff();
+
// Create the render context and windows by the specified dimensions.
void Initialize(const RenderingHelperParams& params,
base::WaitableEvent* done);
@@ -71,9 +100,13 @@ class RenderingHelper {
// |texture_target|.
void RenderThumbnail(uint32 texture_target, uint32 texture_id);
- // Render |texture_id| to the current view port of the screen using target
- // |texture_target|.
- void RenderTexture(uint32 texture_target, uint32 texture_id);
+ // Queues the |video_frame| for rendering.
+ void QueueVideoFrame(size_t window_id,
+ scoped_refptr<VideoFrameTexture> video_frame);
+
+ // Flushes the pending frames. Notify the rendering_helper there won't be
+ // more video frames.
+ void Flush(size_t window_id);
// Delete |texture_id|.
void DeleteTexture(uint32 texture_id);
@@ -82,7 +115,7 @@ class RenderingHelper {
void* GetGLDisplay();
// Get the platform specific handle to the OpenGL context.
- NativeContextType GetGLContext();
+ void* GetGLContext();
// Get rendered thumbnails as RGB.
// Sets alpha_solid to true if the alpha channel is entirely 0xff.
@@ -91,38 +124,56 @@ class RenderingHelper {
base::WaitableEvent* done);
private:
+ struct RenderedVideo {
+ // The rect on the screen where the video will be rendered.
+ gfx::Rect render_area;
+
+ // True if there won't be any new video frames comming.
+ bool is_flushing;
+
+ // The number of frames need to be dropped to catch up the rendering. We
+ // always keep the last remaining frame in pending_frames even after it
+ // has been rendered, so that we have something to display if the client
+ // is falling behind on providing us with new frames during timer-driven
+ // playback.
+ int frames_to_drop;
+
+ // The video frames pending for rendering.
+ std::queue<scoped_refptr<VideoFrameTexture> > pending_frames;
+
+ RenderedVideo();
+ ~RenderedVideo();
+ };
+
void Clear();
void RenderContent();
- void LayoutRenderingAreas();
+ void WarmUpRendering(int warm_up_iterations);
- // Timer to trigger the RenderContent() repeatly.
- base::RepeatingTimer<RenderingHelper> render_timer_;
- base::MessageLoop* message_loop_;
+ void LayoutRenderingAreas(const std::vector<gfx::Size>& window_sizes);
- NativeContextType gl_context_;
+ void UpdateVSyncParameters(base::WaitableEvent* done,
+ const base::TimeTicks timebase,
+ const base::TimeDelta interval);
-#if defined(GL_VARIANT_EGL)
- EGLDisplay gl_display_;
- EGLSurface gl_surface_;
-#else
- XVisualInfo* x_visual_;
-#endif
+ void DropOneFrameForAllVideos();
+ void ScheduleNextRenderContent();
-#if defined(OS_WIN)
- HWND window_;
-#else
- Display* x_display_;
- Window x_window_;
-#endif
+ // Render |texture_id| to the current view port of the screen using target
+ // |texture_target|.
+ void RenderTexture(uint32 texture_target, uint32 texture_id);
- gfx::Size screen_size_;
+ base::MessageLoop* message_loop_;
+
+ scoped_refptr<gfx::GLContext> gl_context_;
+ scoped_refptr<gfx::GLSurface> gl_surface_;
- // The rendering area of each window on the screen.
- std::vector<gfx::Rect> render_areas_;
+ gfx::AcceleratedWidget window_;
+
+ gfx::Size screen_size_;
- std::vector<base::WeakPtr<Client> > clients_;
+ std::vector<RenderedVideo> videos_;
bool render_as_thumbnails_;
int frame_count_;
@@ -132,28 +183,14 @@ class RenderingHelper {
gfx::Size thumbnail_size_;
GLuint program_;
base::TimeDelta frame_duration_;
+ base::TimeTicks scheduled_render_time_;
+ base::CancelableClosure render_task_;
+ base::TimeTicks vsync_timebase_;
+ base::TimeDelta vsync_interval_;
DISALLOW_COPY_AND_ASSIGN(RenderingHelper);
};
-struct RenderingHelperParams {
- RenderingHelperParams();
- ~RenderingHelperParams();
-
- // The rendering FPS.
- int rendering_fps;
-
- // The clients who provide the content for rendering.
- std::vector<base::WeakPtr<RenderingHelper::Client> > clients;
-
- // Whether the frames are rendered as scaled thumbnails within a
- // larger FBO that is in turn rendered to the window.
- bool render_as_thumbnails;
- // The size of the FBO containing all visible thumbnails.
- gfx::Size thumbnails_page_size;
- // The size of each thumbnail within the FBO.
- gfx::Size thumbnail_size;
-};
} // namespace content
#endif // CONTENT_COMMON_GPU_MEDIA_RENDERING_HELPER_H_
diff --git a/chromium/content/common/gpu/media/tegra_v4l2_video_device.cc b/chromium/content/common/gpu/media/tegra_v4l2_video_device.cc
index 43c34017d60..991f54a76d3 100644
--- a/chromium/content/common/gpu/media/tegra_v4l2_video_device.cc
+++ b/chromium/content/common/gpu/media/tegra_v4l2_video_device.cc
@@ -55,7 +55,7 @@ class TegraFunctionSymbolFinder {
TegraFunctionSymbolFinder() : initialized_(false) {
if (!dlopen("/usr/lib/libtegrav4l2.so",
RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) {
- DLOG(ERROR) << "Failed to load libtegrav4l2.so ";
+ DLOG(ERROR) << "Failed to load libtegrav4l2.so";
return;
}
#define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \
@@ -109,7 +109,7 @@ int TegraV4L2Device::Ioctl(int flags, void* arg) {
bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) {
if (HANDLE_EINTR(TegraV4L2_Poll(device_fd_, poll_device, event_pending)) ==
-1) {
- DLOG(ERROR) << "TegraV4L2Poll returned -1 ";
+ LOG(ERROR) << "TegraV4L2Poll returned -1 ";
return false;
}
return true;
@@ -129,7 +129,7 @@ void TegraV4L2Device::Munmap(void* addr, unsigned int len) {
bool TegraV4L2Device::SetDevicePollInterrupt() {
if (HANDLE_EINTR(TegraV4L2_SetDevicePollInterrupt(device_fd_)) == -1) {
- DLOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt";
+ LOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt";
return false;
}
return true;
@@ -137,7 +137,7 @@ bool TegraV4L2Device::SetDevicePollInterrupt() {
bool TegraV4L2Device::ClearDevicePollInterrupt() {
if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) {
- DLOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt";
+ LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt";
return false;
}
return true;
@@ -158,7 +158,7 @@ bool TegraV4L2Device::Initialize() {
}
if (!g_tegra_function_symbol_finder_.Get().initialized()) {
- DLOG(ERROR) << "Unable to initialize functions ";
+ DLOG(ERROR) << "Unable to initialize functions";
return false;
}
device_fd_ = HANDLE_EINTR(
@@ -185,9 +185,11 @@ EGLImageKHR TegraV4L2Device::CreateEGLImage(EGLDisplay egl_display,
reinterpret_cast<EGLClientBuffer>(texture_id),
&attr);
if (egl_image == EGL_NO_IMAGE_KHR) {
+ LOG(ERROR) << "Unable to create EGL image";
return egl_image;
}
if (TegraV4L2_UseEglImage(device_fd_, buffer_index, egl_image) != 0) {
+ LOG(ERROR) << "Unable to use EGL image";
eglDestroyImageKHR(egl_display, egl_image);
egl_image = EGL_NO_IMAGE_KHR;
}
diff --git a/chromium/content/common/gpu/media/tegra_v4l2_video_device.h b/chromium/content/common/gpu/media/tegra_v4l2_video_device.h
index e588951450a..f9e38caa487 100644
--- a/chromium/content/common/gpu/media/tegra_v4l2_video_device.h
+++ b/chromium/content/common/gpu/media/tegra_v4l2_video_device.h
@@ -21,28 +21,28 @@ class TegraV4L2Device : public V4L2Device {
explicit TegraV4L2Device(Type type);
virtual ~TegraV4L2Device();
- virtual int Ioctl(int flags, void* arg) OVERRIDE;
- virtual bool Poll(bool poll_device, bool* event_pending) OVERRIDE;
- virtual bool SetDevicePollInterrupt() OVERRIDE;
- virtual bool ClearDevicePollInterrupt() OVERRIDE;
+ virtual int Ioctl(int flags, void* arg) override;
+ virtual bool Poll(bool poll_device, bool* event_pending) override;
+ virtual bool SetDevicePollInterrupt() override;
+ virtual bool ClearDevicePollInterrupt() override;
virtual void* Mmap(void* addr,
unsigned int len,
int prot,
int flags,
- unsigned int offset) OVERRIDE;
- virtual void Munmap(void* addr, unsigned int len) OVERRIDE;
- virtual bool Initialize() OVERRIDE;
+ unsigned int offset) override;
+ virtual void Munmap(void* addr, unsigned int len) override;
+ virtual bool Initialize() override;
virtual EGLImageKHR CreateEGLImage(EGLDisplay egl_display,
EGLContext egl_context,
GLuint texture_id,
gfx::Size frame_buffer_size,
unsigned int buffer_index,
- size_t planes_count) OVERRIDE;
+ size_t planes_count) override;
virtual EGLBoolean DestroyEGLImage(EGLDisplay egl_display,
- EGLImageKHR egl_image) OVERRIDE;
- virtual GLenum GetTextureTarget() OVERRIDE;
- virtual uint32 PreferredInputFormat() OVERRIDE;
- virtual uint32 PreferredOutputFormat() OVERRIDE;
+ EGLImageKHR egl_image) override;
+ virtual GLenum GetTextureTarget() override;
+ virtual uint32 PreferredInputFormat() override;
+ virtual uint32 PreferredOutputFormat() override;
private:
const Type type_;
diff --git a/chromium/content/common/gpu/media/v4l2_image_processor.cc b/chromium/content/common/gpu/media/v4l2_image_processor.cc
index 1a9dd292180..20d91f02e15 100644
--- a/chromium/content/common/gpu/media/v4l2_image_processor.cc
+++ b/chromium/content/common/gpu/media/v4l2_image_processor.cc
@@ -19,14 +19,14 @@
#define NOTIFY_ERROR() \
do { \
- DLOG(ERROR) << "calling NotifyError()"; \
+ LOG(ERROR) << "calling NotifyError()"; \
NotifyError(); \
} while (0)
#define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \
do { \
if (device_->Ioctl(type, arg) != 0) { \
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
return value; \
} \
} while (0)
@@ -40,7 +40,7 @@
#define IOCTL_OR_LOG_ERROR(type, arg) \
do { \
if (device_->Ioctl(type, arg) != 0) \
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
} while (0)
namespace content {
@@ -110,7 +110,7 @@ bool V4L2ImageProcessor::Initialize(media::VideoFrame::Format input_format,
V4L2Device::VideoFrameFormatToV4L2PixFmt(output_format);
if (!input_format_fourcc_ || !output_format_fourcc_) {
- DLOG(ERROR) << "Unrecognized format(s)";
+ LOG(ERROR) << "Unrecognized format(s)";
return false;
}
@@ -130,8 +130,8 @@ bool V4L2ImageProcessor::Initialize(media::VideoFrame::Format input_format,
V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
- "caps check failed: 0x" << std::hex << caps.capabilities;
+ LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
+ "caps check failed: 0x" << std::hex << caps.capabilities;
return false;
}
@@ -139,7 +139,7 @@ bool V4L2ImageProcessor::Initialize(media::VideoFrame::Format input_format,
return false;
if (!device_thread_.Start()) {
- DLOG(ERROR) << "Initialize(): encoder thread failed to start";
+ LOG(ERROR) << "Initialize(): encoder thread failed to start";
return false;
}
@@ -214,6 +214,7 @@ void V4L2ImageProcessor::DestroyTask() {
}
bool V4L2ImageProcessor::CreateInputBuffers() {
+ DVLOG(3) << __func__;
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
DCHECK(!input_streamon_);
@@ -284,6 +285,7 @@ bool V4L2ImageProcessor::CreateInputBuffers() {
}
bool V4L2ImageProcessor::CreateOutputBuffers() {
+ DVLOG(3) << __func__;
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
DCHECK(!output_streamon_);
@@ -501,7 +503,7 @@ void V4L2ImageProcessor::Dequeue() {
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- DPLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
+ PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR();
return;
}
@@ -528,7 +530,7 @@ void V4L2ImageProcessor::Dequeue() {
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- DPLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
+ PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR();
return;
}
@@ -646,7 +648,7 @@ bool V4L2ImageProcessor::StartDevicePoll() {
// Start up the device poll thread and schedule its first DevicePollTask().
if (!device_poll_thread_.Start()) {
- DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
+ LOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
NOTIFY_ERROR();
return false;
}
diff --git a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc
index 1b47516c0e7..243fee58d2e 100644
--- a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc
@@ -26,14 +26,14 @@
#define NOTIFY_ERROR(x) \
do { \
SetDecoderState(kError); \
- DLOG(ERROR) << "calling NotifyError(): " << x; \
+ LOG(ERROR) << "calling NotifyError(): " << x; \
NotifyError(x); \
} while (0)
#define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \
do { \
if (device_->Ioctl(type, arg) != 0) { \
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
NOTIFY_ERROR(PLATFORM_FAILURE); \
return value; \
} \
@@ -48,7 +48,7 @@
#define IOCTL_OR_LOG_ERROR(type, arg) \
do { \
if (device_->Ioctl(type, arg) != 0) \
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
} while (0)
namespace content {
@@ -224,8 +224,8 @@ bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
case media::H264PROFILE_HIGH:
DVLOG(2) << "Initialize(): profile H264PROFILE_HIGH";
break;
- case media::VP8PROFILE_MAIN:
- DVLOG(2) << "Initialize(): profile VP8PROFILE_MAIN";
+ case media::VP8PROFILE_ANY:
+ DVLOG(2) << "Initialize(): profile VP8PROFILE_ANY";
break;
default:
DLOG(ERROR) << "Initialize(): unsupported profile=" << profile;
@@ -234,20 +234,20 @@ bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
video_profile_ = profile;
if (egl_display_ == EGL_NO_DISPLAY) {
- DLOG(ERROR) << "Initialize(): could not get EGLDisplay";
+ LOG(ERROR) << "Initialize(): could not get EGLDisplay";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
// We need the context to be initialized to query extensions.
if (!make_context_current_.Run()) {
- DLOG(ERROR) << "Initialize(): could not make context current";
+ LOG(ERROR) << "Initialize(): could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
if (!gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync) {
- DLOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync";
+ LOG(ERROR) << "Initialize(): context does not have EGL_KHR_fence_sync";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -260,7 +260,7 @@ bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
+ LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
", caps check failed: 0x" << std::hex << caps.capabilities;
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
@@ -295,7 +295,7 @@ bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
}
if (!decoder_thread_.Start()) {
- DLOG(ERROR) << "Initialize(): decoder thread failed to start";
+ LOG(ERROR) << "Initialize(): decoder thread failed to start";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -329,15 +329,15 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers(
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
if (buffers.size() != output_buffer_map_.size()) {
- DLOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture"
- " buffers. (Got " << buffers.size()
- << ", requested " << output_buffer_map_.size() << ")";
+ LOG(ERROR) << "AssignPictureBuffers(): Failed to provide requested picture"
+ " buffers. (Got " << buffers.size()
+ << ", requested " << output_buffer_map_.size() << ")";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
if (!make_context_current_.Run()) {
- DLOG(ERROR) << "AssignPictureBuffers(): could not make context current";
+ LOG(ERROR) << "AssignPictureBuffers(): could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -365,7 +365,7 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers(
i,
output_planes_count_);
if (egl_image == EGL_NO_IMAGE_KHR) {
- DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
+ LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
// Ownership of EGLImages allocated in previous iterations of this loop
// has been transferred to output_buffer_map_. After we error-out here
// the destructor will handle their cleanup.
@@ -389,7 +389,7 @@ void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
if (!make_context_current_.Run()) {
- DLOG(ERROR) << "ReusePictureBuffer(): could not make context current";
+ LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -397,7 +397,7 @@ void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
EGLSyncKHR egl_sync =
eglCreateSyncKHR(egl_display_, EGL_SYNC_FENCE_KHR, NULL);
if (egl_sync == EGL_NO_SYNC_KHR) {
- DLOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed";
+ LOG(ERROR) << "ReusePictureBuffer(): eglCreateSyncKHR() failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -464,7 +464,7 @@ void V4L2VideoDecodeAccelerator::DecodeTask(
new base::SharedMemory(bitstream_buffer.handle(), true),
bitstream_buffer.size(), bitstream_buffer.id()));
if (!bitstream_record->shm->Map(bitstream_buffer.size())) {
- DLOG(ERROR) << "Decode(): could not map bitstream_buffer";
+ LOG(ERROR) << "Decode(): could not map bitstream_buffer";
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
}
@@ -964,7 +964,7 @@ void V4L2VideoDecodeAccelerator::Enqueue() {
// We just started up a previously empty queue.
// Queue state changed; signal interrupt.
if (!device_->SetDevicePollInterrupt()) {
- DPLOG(ERROR) << "SetDevicePollInterrupt(): failed";
+ PLOG(ERROR) << "SetDevicePollInterrupt(): failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -986,7 +986,7 @@ void V4L2VideoDecodeAccelerator::Enqueue() {
// We just started up a previously empty queue.
// Queue state changed; signal interrupt.
if (!device_->SetDevicePollInterrupt()) {
- DPLOG(ERROR) << "SetDevicePollInterrupt(): failed";
+ PLOG(ERROR) << "SetDevicePollInterrupt(): failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1013,7 +1013,7 @@ void V4L2VideoDecodeAccelerator::DequeueEvents() {
DCHECK(!resolution_change_pending_);
resolution_change_pending_ = IsResolutionChangeNecessary();
} else {
- DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type
+ LOG(ERROR) << "DequeueEvents(): got an event (" << ev.type
<< ") we haven't subscribed to.";
}
}
@@ -1042,7 +1042,7 @@ void V4L2VideoDecodeAccelerator::Dequeue() {
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
+ PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1073,7 +1073,7 @@ void V4L2VideoDecodeAccelerator::Dequeue() {
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
+ PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1092,7 +1092,9 @@ void V4L2VideoDecodeAccelerator::Dequeue() {
DVLOG(3) << "Dequeue(): returning input_id=" << dqbuf.timestamp.tv_sec
<< " as picture_id=" << output_record.picture_id;
const media::Picture& picture =
- media::Picture(output_record.picture_id, dqbuf.timestamp.tv_sec);
+ media::Picture(output_record.picture_id,
+ dqbuf.timestamp.tv_sec,
+ gfx::Rect(frame_buffer_size_));
pending_picture_ready_.push(
PictureRecord(output_record.cleared, picture));
SendPictureReady();
@@ -1156,7 +1158,7 @@ bool V4L2VideoDecodeAccelerator::EnqueueOutputRecord() {
DVLOG(1) << __func__ << " eglClientWaitSyncKHR failed!";
}
if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) {
- DLOG(FATAL) << __func__ << " eglDestroySyncKHR failed!";
+ LOG(ERROR) << __func__ << " eglDestroySyncKHR failed!";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1216,7 +1218,7 @@ void V4L2VideoDecodeAccelerator::ReusePictureBufferTask(
OutputRecord& output_record = output_buffer_map_[index];
if (output_record.at_device || !output_record.at_client) {
- DLOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable";
+ LOG(ERROR) << "ReusePictureBufferTask(): picture_buffer_id not reusable";
NOTIFY_ERROR(INVALID_ARGUMENT);
return;
}
@@ -1422,7 +1424,7 @@ bool V4L2VideoDecodeAccelerator::StartDevicePoll() {
// Start up the device poll thread and schedule its first DevicePollTask().
if (!device_poll_thread_.Start()) {
- DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
+ LOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1441,7 +1443,7 @@ bool V4L2VideoDecodeAccelerator::StopDevicePoll(bool keep_input_state) {
// Signal the DevicePollTask() to stop, and stop the device poll thread.
if (!device_->SetDevicePollInterrupt()) {
- DPLOG(ERROR) << "SetDevicePollInterrupt(): failed";
+ PLOG(ERROR) << "SetDevicePollInterrupt(): failed";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1542,13 +1544,13 @@ void V4L2VideoDecodeAccelerator::FinishResolutionChange() {
bool again;
bool ret = GetFormatInfo(&format, &again);
if (!ret || again) {
- DVLOG(3) << "Couldn't get format information after resolution change";
+ LOG(ERROR) << "Couldn't get format information after resolution change";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
if (!CreateBuffersForFormat(format)) {
- DVLOG(3) << "Couldn't reallocate buffers after resolution change";
+ LOG(ERROR) << "Couldn't reallocate buffers after resolution change";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1630,7 +1632,7 @@ bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format,
*again = true;
return true;
} else {
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT";
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: VIDIOC_G_FMT";
NOTIFY_ERROR(PLATFORM_FAILURE);
return false;
}
@@ -1706,7 +1708,7 @@ bool V4L2VideoDecodeAccelerator::CreateInputBuffers() {
MAP_SHARED,
buffer.m.planes[0].m.mem_offset);
if (address == MAP_FAILED) {
- DPLOG(ERROR) << "CreateInputBuffers(): mmap() failed";
+ PLOG(ERROR) << "CreateInputBuffers(): mmap() failed";
return false;
}
input_buffer_map_[i].address = address;
@@ -1833,7 +1835,7 @@ bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() {
reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
reqbufs.memory = V4L2_MEMORY_MMAP;
if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) {
- DPLOG(ERROR) << "DestroyOutputBuffers() ioctl() failed: VIDIOC_REQBUFS";
+ PLOG(ERROR) << "DestroyOutputBuffers() ioctl() failed: VIDIOC_REQBUFS";
success = false;
}
@@ -1849,7 +1851,7 @@ void V4L2VideoDecodeAccelerator::ResolutionChangeDestroyBuffers() {
DVLOG(3) << "ResolutionChangeDestroyBuffers()";
if (!DestroyOutputBuffers()) {
- DLOG(FATAL) << __func__ << " Failed destroying output buffers.";
+ LOG(ERROR) << __func__ << " Failed destroying output buffers.";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
diff --git a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h
index e3d553d7641..9b973105f3b 100644
--- a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h
@@ -87,15 +87,15 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator
// media::VideoDecodeAccelerator implementation.
// Note: Initialize() and Destroy() are synchronous.
virtual bool Initialize(media::VideoCodecProfile profile,
- Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
+ Client* client) override;
+ virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool CanDecodeOnIOThread() OVERRIDE;
+ const std::vector<media::PictureBuffer>& buffers) override;
+ virtual void ReusePictureBuffer(int32 picture_buffer_id) override;
+ virtual void Flush() override;
+ virtual void Reset() override;
+ virtual void Destroy() override;
+ virtual bool CanDecodeOnIOThread() override;
private:
// These are rather subjectively tuned.
diff --git a/chromium/content/common/gpu/media/v4l2_video_device.cc b/chromium/content/common/gpu/media/v4l2_video_device.cc
index e9c54229c78..58b935a4008 100644
--- a/chromium/content/common/gpu/media/v4l2_video_device.cc
+++ b/chromium/content/common/gpu/media/v4l2_video_device.cc
@@ -18,13 +18,13 @@ scoped_ptr<V4L2Device> V4L2Device::Create(Type type) {
scoped_ptr<ExynosV4L2Device> exynos_device(new ExynosV4L2Device(type));
if (exynos_device->Initialize())
- return exynos_device.PassAs<V4L2Device>();
+ return exynos_device.Pass();
scoped_ptr<TegraV4L2Device> tegra_device(new TegraV4L2Device(type));
if (tegra_device->Initialize())
- return tegra_device.PassAs<V4L2Device>();
+ return tegra_device.Pass();
- DLOG(ERROR) << "Failed to create V4L2Device";
+ LOG(ERROR) << "Failed to create V4L2Device";
return scoped_ptr<V4L2Device>();
}
@@ -106,9 +106,14 @@ gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) {
int horiz_bpp =
media::VideoFrame::PlaneHorizontalBitsPerPixel(frame_format, 0);
+ DVLOG(3) << __func__ << ": bytesperline=" << bytesperline
+ << ", sizeimage=" << sizeimage
+ << ", visible_size=" << visible_size.ToString() << ", frame_format="
+ << media::VideoFrame::FormatToString(frame_format)
+ << ", horiz_bpp=" << horiz_bpp;
if (sizeimage == 0 || bytesperline == 0 || horiz_bpp == 0 ||
(bytesperline * 8) % horiz_bpp != 0) {
- DLOG(ERROR) << "Invalid format provided";
+ LOG(ERROR) << "Invalid format provided";
return coded_size;
}
@@ -118,6 +123,7 @@ gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) {
sizeimage = ((sizeimage + bytesperline - 1) / bytesperline) * bytesperline;
coded_size.SetSize(bytesperline * 8 / horiz_bpp, sizeimage / bytesperline);
+ DVLOG(3) << "coded_size=" << coded_size.ToString();
// Sanity checks. Calculated coded size has to contain given visible size
// and fulfill buffer byte size requirements for each plane.
@@ -125,11 +131,9 @@ gfx::Size V4L2Device::CodedSizeFromV4L2Format(struct v4l2_format format) {
if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) {
- DCHECK_LE(
- format.fmt.pix_mp.plane_fmt[i].sizeimage,
- media::VideoFrame::PlaneAllocationSize(frame_format, i, coded_size));
- DCHECK_LE(format.fmt.pix_mp.plane_fmt[i].bytesperline,
- base::checked_cast<__u32>(coded_size.width()));
+ DCHECK_EQ(format.fmt.pix_mp.plane_fmt[i].bytesperline,
+ base::checked_cast<__u32>(media::VideoFrame::RowBytes(
+ i, frame_format, coded_size.width())));
}
}
diff --git a/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc b/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc
index 95d5079c325..d69c97da551 100644
--- a/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc
@@ -21,14 +21,14 @@
#define NOTIFY_ERROR(x) \
do { \
SetEncoderState(kError); \
- DLOG(ERROR) << "calling NotifyError(): " << x; \
+ LOG(ERROR) << "calling NotifyError(): " << x; \
NotifyError(x); \
} while (0)
#define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \
do { \
if (device_->Ioctl(type, arg) != 0) { \
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
NOTIFY_ERROR(kPlatformFailureError); \
return value; \
} \
@@ -43,7 +43,7 @@
#define IOCTL_OR_LOG_ERROR(type, arg) \
do { \
if (device_->Ioctl(type, arg) != 0) \
- DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
+ PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
} while (0)
namespace content {
@@ -66,13 +66,10 @@ V4L2VideoEncodeAccelerator::OutputRecord::OutputRecord()
V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator(
scoped_ptr<V4L2Device> device)
: child_message_loop_proxy_(base::MessageLoopProxy::current()),
- weak_this_ptr_factory_(this),
- weak_this_(weak_this_ptr_factory_.GetWeakPtr()),
output_buffer_byte_size_(0),
device_input_format_(media::VideoFrame::UNKNOWN),
input_planes_count_(0),
output_format_fourcc_(0),
- encoder_thread_("V4L2EncoderThread"),
encoder_state_(kUninitialized),
stream_header_size_(0),
device_(device.Pass()),
@@ -81,7 +78,10 @@ V4L2VideoEncodeAccelerator::V4L2VideoEncodeAccelerator(
input_memory_type_(V4L2_MEMORY_USERPTR),
output_streamon_(false),
output_buffer_queued_count_(0),
- device_poll_thread_("V4L2EncoderDevicePollThread") {
+ encoder_thread_("V4L2EncoderThread"),
+ device_poll_thread_("V4L2EncoderDevicePollThread"),
+ weak_this_ptr_factory_(this) {
+ weak_this_ = weak_this_ptr_factory_.GetWeakPtr();
}
V4L2VideoEncodeAccelerator::~V4L2VideoEncodeAccelerator() {
@@ -119,13 +119,13 @@ bool V4L2VideoEncodeAccelerator::Initialize(
V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
- "caps check failed: 0x" << std::hex << caps.capabilities;
+ LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
+ "caps check failed: 0x" << std::hex << caps.capabilities;
return false;
}
if (!SetFormats(input_format, output_profile)) {
- DLOG(ERROR) << "Failed setting up formats";
+ LOG(ERROR) << "Failed setting up formats";
return false;
}
@@ -148,7 +148,7 @@ bool V4L2VideoEncodeAccelerator::Initialize(
input_allocated_size_,
base::Bind(&V4L2VideoEncodeAccelerator::ImageProcessorError,
weak_this_))) {
- DLOG(ERROR) << "Failed initializing image processor";
+ LOG(ERROR) << "Failed initializing image processor";
return false;
}
}
@@ -160,7 +160,7 @@ bool V4L2VideoEncodeAccelerator::Initialize(
return false;
if (!encoder_thread_.Start()) {
- DLOG(ERROR) << "Initialize(): encoder thread failed to start";
+ LOG(ERROR) << "Initialize(): encoder thread failed to start";
return false;
}
@@ -181,7 +181,7 @@ bool V4L2VideoEncodeAccelerator::Initialize(
}
void V4L2VideoEncodeAccelerator::ImageProcessorError() {
- DVLOG(1) << "Image processor error";
+ LOG(ERROR) << "Image processor error";
NOTIFY_ERROR(kPlatformFailureError);
}
@@ -255,6 +255,7 @@ void V4L2VideoEncodeAccelerator::Destroy() {
// We're destroying; cancel all callbacks.
client_ptr_factory_.reset();
+ weak_this_ptr_factory_.InvalidateWeakPtrs();
if (image_processor_.get())
image_processor_.release()->Destroy();
@@ -279,27 +280,26 @@ void V4L2VideoEncodeAccelerator::Destroy() {
delete this;
}
-// static
std::vector<media::VideoEncodeAccelerator::SupportedProfile>
V4L2VideoEncodeAccelerator::GetSupportedProfiles() {
std::vector<SupportedProfile> profiles;
SupportedProfile profile;
- const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (cmd_line->HasSwitch(switches::kEnableWebRtcHWVp8Encoding)) {
- profile.profile = media::VP8PROFILE_MAIN;
- profile.max_resolution.SetSize(1920, 1088);
- profile.max_framerate.numerator = 30;
- profile.max_framerate.denominator = 1;
- profiles.push_back(profile);
- } else {
- profile.profile = media::H264PROFILE_MAIN;
+ profile.profile = media::VP8PROFILE_ANY;
profile.max_resolution.SetSize(1920, 1088);
- profile.max_framerate.numerator = 30;
- profile.max_framerate.denominator = 1;
+ profile.max_framerate_numerator = 30;
+ profile.max_framerate_denominator = 1;
profiles.push_back(profile);
}
+ profile.profile = media::H264PROFILE_MAIN;
+ profile.max_resolution.SetSize(1920, 1088);
+ profile.max_framerate_numerator = 30;
+ profile.max_framerate_denominator = 1;
+ profiles.push_back(profile);
+
return profiles;
}
@@ -499,7 +499,7 @@ void V4L2VideoEncodeAccelerator::Dequeue() {
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
+ PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(kPlatformFailureError);
return;
}
@@ -527,7 +527,7 @@ void V4L2VideoEncodeAccelerator::Dequeue() {
// EAGAIN if we're just out of buffers to dequeue.
break;
}
- DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
+ PLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
NOTIFY_ERROR(kPlatformFailureError);
return;
}
@@ -608,6 +608,7 @@ bool V4L2VideoEncodeAccelerator::EnqueueInputRecord() {
switch (input_memory_type_) {
case V4L2_MEMORY_USERPTR:
+ qbuf.m.planes[i].length = qbuf.m.planes[i].bytesused;
qbuf.m.planes[i].m.userptr =
reinterpret_cast<unsigned long>(frame->data(i));
DCHECK(qbuf.m.planes[i].m.userptr);
@@ -672,7 +673,7 @@ bool V4L2VideoEncodeAccelerator::StartDevicePoll() {
// Start up the device poll thread and schedule its first DevicePollTask().
if (!device_poll_thread_.Start()) {
- DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
+ LOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
NOTIFY_ERROR(kPlatformFailureError);
return false;
}
@@ -830,7 +831,7 @@ bool V4L2VideoEncodeAccelerator::SetOutputFormat(
output_format_fourcc_ =
V4L2Device::VideoCodecProfileToV4L2PixFmt(output_profile);
if (!output_format_fourcc_) {
- DLOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile;
+ LOG(ERROR) << "Initialize(): invalid output_profile=" << output_profile;
return false;
}
@@ -858,6 +859,7 @@ bool V4L2VideoEncodeAccelerator::SetOutputFormat(
bool V4L2VideoEncodeAccelerator::NegotiateInputFormat(
media::VideoFrame::Format input_format) {
+ DVLOG(3) << "NegotiateInputFormat()";
DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
DCHECK(!input_streamon_);
DCHECK(!output_streamon_);
@@ -868,7 +870,7 @@ bool V4L2VideoEncodeAccelerator::NegotiateInputFormat(
uint32 input_format_fourcc =
V4L2Device::VideoFrameFormatToV4L2PixFmt(input_format);
if (!input_format_fourcc) {
- DVLOG(1) << "Unsupported input format";
+ LOG(ERROR) << "Unsupported input format";
return false;
}
@@ -1044,7 +1046,7 @@ bool V4L2VideoEncodeAccelerator::CreateOutputBuffers() {
MAP_SHARED,
buffer.m.planes[0].m.mem_offset);
if (address == MAP_FAILED) {
- DPLOG(ERROR) << "CreateOutputBuffers(): mmap() failed";
+ PLOG(ERROR) << "CreateOutputBuffers(): mmap() failed";
return false;
}
output_buffer_map_[i].address = address;
diff --git a/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.h b/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.h
index 15f580dfc75..267d0d010a6 100644
--- a/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.h
+++ b/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.h
@@ -46,21 +46,20 @@ class CONTENT_EXPORT V4L2VideoEncodeAccelerator
virtual ~V4L2VideoEncodeAccelerator();
// media::VideoEncodeAccelerator implementation.
+ virtual std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+ GetSupportedProfiles() override;
virtual bool Initialize(media::VideoFrame::Format format,
const gfx::Size& input_visible_size,
media::VideoCodecProfile output_profile,
uint32 initial_bitrate,
- Client* client) OVERRIDE;
+ Client* client) override;
virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe) OVERRIDE;
+ bool force_keyframe) override;
virtual void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer)
- OVERRIDE;
+ override;
virtual void RequestEncodingParametersChange(uint32 bitrate,
- uint32 framerate) OVERRIDE;
- virtual void Destroy() OVERRIDE;
-
- static std::vector<media::VideoEncodeAccelerator::SupportedProfile>
- GetSupportedProfiles();
+ uint32 framerate) override;
+ virtual void Destroy() override;
private:
// Auto-destroy reference for BitstreamBuffer, for tracking buffers passed to
@@ -192,21 +191,6 @@ class CONTENT_EXPORT V4L2VideoEncodeAccelerator
// Our original calling message loop for the child thread.
const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
- // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or
- // device worker threads back to the child thread. Because the worker threads
- // are members of this class, any task running on those threads is guaranteed
- // that this object is still alive. As a result, tasks posted from the child
- // thread to the encoder or device thread should use base::Unretained(this),
- // and tasks posted the other way should use |weak_this_|.
- base::WeakPtrFactory<V4L2VideoEncodeAccelerator> weak_this_ptr_factory_;
- base::WeakPtr<V4L2VideoEncodeAccelerator> weak_this_;
-
- // To expose client callbacks from VideoEncodeAccelerator.
- // NOTE: all calls to these objects *MUST* be executed on
- // child_message_loop_proxy_.
- scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
- base::WeakPtr<Client> client_;
-
gfx::Size visible_size_;
// Input allocated size required by the device.
gfx::Size input_allocated_size_;
@@ -224,9 +208,6 @@ class CONTENT_EXPORT V4L2VideoEncodeAccelerator
// thread should be the only one managing these.
//
- // This thread services tasks posted from the VEA API entry points by the
- // child thread and device service callbacks posted from the device thread.
- base::Thread encoder_thread_;
// Encoder state.
State encoder_state_;
@@ -264,16 +245,29 @@ class CONTENT_EXPORT V4L2VideoEncodeAccelerator
// since we don't care about ordering.
std::vector<linked_ptr<BitstreamBufferRef> > encoder_output_queue_;
- //
+ // Image processor, if one is in use.
+ scoped_ptr<V4L2ImageProcessor> image_processor_;
+
+ // This thread services tasks posted from the VEA API entry points by the
+ // child thread and device service callbacks posted from the device thread.
+ base::Thread encoder_thread_;
+
// The device polling thread handles notifications of V4L2 device changes.
// TODO(sheu): replace this thread with an TYPE_IO encoder_thread_.
- //
-
- // The thread.
base::Thread device_poll_thread_;
- // Image processor, if one is in use.
- scoped_ptr<V4L2ImageProcessor> image_processor_;
+ // To expose client callbacks from VideoEncodeAccelerator.
+ // NOTE: all calls to these objects *MUST* be executed on
+ // child_message_loop_proxy_.
+ base::WeakPtr<Client> client_;
+ scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
+
+ // WeakPtr<> pointing to |this| for use in posting tasks from the
+ // image_processor_ back to the child thread.
+ // Tasks posted onto encoder and poll threads can use base::Unretained(this),
+ // as both threads will not outlive this object.
+ base::WeakPtr<V4L2VideoEncodeAccelerator> weak_this_;
+ base::WeakPtrFactory<V4L2VideoEncodeAccelerator> weak_this_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(V4L2VideoEncodeAccelerator);
};
diff --git a/chromium/content/common/gpu/media/va.sigs b/chromium/content/common/gpu/media/va.sigs
index b3cea38713c..9906f9f8cbb 100644
--- a/chromium/content/common/gpu/media/va.sigs
+++ b/chromium/content/common/gpu/media/va.sigs
@@ -22,7 +22,9 @@ const char *vaErrorStr(VAStatus error_status);
VAStatus vaGetConfigAttributes(VADisplay dpy, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs);
VAStatus vaInitialize(VADisplay dpy, int *major_version, int *minor_version);
VAStatus vaMapBuffer(VADisplay dpy, VABufferID buf_id, void **pbuf);
+int vaMaxNumEntrypoints (VADisplay dpy);
int vaMaxNumProfiles(VADisplay dpy);
+VAStatus vaQueryConfigEntrypoints (VADisplay dpy, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints);
VAStatus vaQueryConfigProfiles(VADisplay dpy, VAProfile *profile_list, int *num_profiles);
VAStatus vaRenderPicture(VADisplay dpy, VAContextID context, VABufferID *buffers, int num_buffers);
VAStatus vaSetDisplayAttributes(VADisplay dpy, VADisplayAttribute *attr_list, int num_attributes);
diff --git a/chromium/content/common/gpu/media/vaapi_h264_decoder.cc b/chromium/content/common/gpu/media/vaapi_h264_decoder.cc
index 9654a3c246a..56918caf5d7 100644
--- a/chromium/content/common/gpu/media/vaapi_h264_decoder.cc
+++ b/chromium/content/common/gpu/media/vaapi_h264_decoder.cc
@@ -488,8 +488,8 @@ bool VaapiH264Decoder::DecodePicture() {
return false;
}
- if (!vaapi_wrapper_->DecodeAndDestroyPendingBuffers(
- dec_surface->va_surface()->id())) {
+ if (!vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
+ dec_surface->va_surface()->id())) {
DVLOG(1) << "Failed decoding picture";
return false;
}
@@ -1676,6 +1676,16 @@ VaapiH264Decoder::DecResult VaapiH264Decoder::Decode() {
break;
}
+ case media::H264NALU::kAUD:
+ case media::H264NALU::kEOSeq:
+ case media::H264NALU::kEOStream:
+ if (state_ != kDecoding)
+ break;
+ if (!FinishPrevFrameIfPresent())
+ SET_ERROR_AND_RETURN();
+
+ break;
+
default:
DVLOG(4) << "Skipping NALU type: " << nalu.nal_unit_type;
break;
diff --git a/chromium/content/common/gpu/media/vaapi_h264_decoder_unittest.cc b/chromium/content/common/gpu/media/vaapi_h264_decoder_unittest.cc
index 6bd873e88ea..70d8220ddbe 100644
--- a/chromium/content/common/gpu/media/vaapi_h264_decoder_unittest.cc
+++ b/chromium/content/common/gpu/media/vaapi_h264_decoder_unittest.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "content/common/gpu/media/vaapi_h264_decoder.h"
#include "media/base/video_decoder_config.h"
@@ -127,7 +127,8 @@ bool VaapiH264DecoderLoop::Initialize(base::FilePath input_file,
media::VideoCodecProfile profile = media::H264PROFILE_BASELINE;
base::Closure report_error_cb =
base::Bind(&LogOnError, VaapiH264Decoder::VAAPI_ERROR);
- wrapper_ = VaapiWrapper::Create(profile, x_display_, report_error_cb);
+ wrapper_ = VaapiWrapper::Create(
+ VaapiWrapper::kDecode, profile, x_display_, report_error_cb);
if (!wrapper_.get()) {
LOG(ERROR) << "Can't create vaapi wrapper";
return false;
@@ -248,8 +249,7 @@ bool VaapiH264DecoderLoop::ProcessVideoFrame(
int to_write = media::VideoFrame::PlaneAllocationSize(
frame->format(), i, frame->coded_size());
const char* buf = reinterpret_cast<const char*>(frame->data(i));
- int written = base::AppendToFile(output_file_, buf, to_write);
- if (written != to_write)
+ if (!base::AppendToFile(output_file_, buf, to_write))
return false;
}
return true;
@@ -349,7 +349,7 @@ TEST(VaapiH264DecoderTest, TestDecode) {
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args.
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
// Needed to enable DVLOG through --vmodule.
logging::LoggingSettings settings;
@@ -357,11 +357,11 @@ int main(int argc, char** argv) {
CHECK(logging::InitLogging(settings));
// Process command line.
- CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
CHECK(cmd_line);
- CommandLine::SwitchMap switches = cmd_line->GetSwitches();
- for (CommandLine::SwitchMap::const_iterator it = switches.begin();
+ base::CommandLine::SwitchMap switches = cmd_line->GetSwitches();
+ for (base::CommandLine::SwitchMap::const_iterator it = switches.begin();
it != switches.end();
++it) {
if (it->first == "input_file") {
diff --git a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index b68f5d46da4..df1f6443421 100644
--- a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -30,7 +30,7 @@ namespace content {
#define RETURN_AND_NOTIFY_ON_FAILURE(result, log, error_code, ret) \
do { \
if (!(result)) { \
- DVLOG(1) << log; \
+ LOG(ERROR) << log; \
NotifyError(error_code); \
return ret; \
} \
@@ -54,7 +54,7 @@ void VaapiVideoDecodeAccelerator::NotifyError(Error error) {
message_loop_->PostTask(FROM_HERE, base::Bind(
&VaapiVideoDecodeAccelerator::Cleanup, weak_this_));
- DVLOG(1) << "Notifying of error " << error;
+ LOG(ERROR) << "Notifying of error " << error;
if (client_) {
client_->NotifyError(error);
client_ptr_factory_.reset();
@@ -169,7 +169,7 @@ bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
x_pixmap_ = XCreatePixmap(x_display_, RootWindow(x_display_, screen),
size_.width(), size_.height(), win_attr.depth);
if (!x_pixmap_) {
- DVLOG(1) << "Failed creating an X Pixmap for TFP";
+ LOG(ERROR) << "Failed creating an X Pixmap for TFP";
return false;
}
@@ -182,7 +182,7 @@ bool VaapiVideoDecodeAccelerator::TFPPicture::Initialize(
glx_pixmap_ = glXCreatePixmap(x_display_, fb_config, x_pixmap_, pixmap_attr);
if (!glx_pixmap_) {
// x_pixmap_ will be freed in the destructor.
- DVLOG(1) << "Failed creating a GLX Pixmap for TFP";
+ LOG(ERROR) << "Failed creating a GLX Pixmap for TFP";
return false;
}
@@ -219,7 +219,7 @@ VaapiVideoDecodeAccelerator::TFPPicture*
VaapiVideoDecodeAccelerator::TFPPictureById(int32 picture_buffer_id) {
TFPPictures::iterator it = tfp_pictures_.find(picture_buffer_id);
if (it == tfp_pictures_.end()) {
- DVLOG(1) << "Picture id " << picture_buffer_id << " does not exist";
+ LOG(ERROR) << "Picture id " << picture_buffer_id << " does not exist";
return NULL;
}
@@ -295,16 +295,18 @@ bool VaapiVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
return false;
if (!InitializeFBConfig()) {
- DVLOG(1) << "Could not get a usable FBConfig";
+ LOG(ERROR) << "Could not get a usable FBConfig";
return false;
}
vaapi_wrapper_ = VaapiWrapper::Create(
- profile, x_display_,
+ VaapiWrapper::kDecode,
+ profile,
+ x_display_,
base::Bind(&ReportToUMA, content::VaapiH264Decoder::VAAPI_ERROR));
if (!vaapi_wrapper_.get()) {
- DVLOG(1) << "Failed initializing VAAPI";
+ LOG(ERROR) << "Failed initializing VAAPI";
return false;
}
@@ -369,8 +371,11 @@ void VaapiVideoDecodeAccelerator::OutputPicture(
TRACE_COUNTER1("Video Decoder", "Textures at client", num_frames_at_client_);
DVLOG(4) << "Notifying output picture id " << output_id
<< " for input "<< input_id << " is ready";
+ // TODO(posciak): Use visible size from decoder here instead
+ // (crbug.com/402760).
if (client_)
- client_->PictureReady(media::Picture(output_id, input_id));
+ client_->PictureReady(
+ media::Picture(output_id, input_id, gfx::Rect(tfp_picture->size())));
}
void VaapiVideoDecodeAccelerator::TryOutputSurface() {
diff --git a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
index 2bde3e0cef7..5d65da7a4ae 100644
--- a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
@@ -50,15 +50,15 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
// media::VideoDecodeAccelerator implementation.
virtual bool Initialize(media::VideoCodecProfile profile,
- Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
+ Client* client) override;
+ virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool CanDecodeOnIOThread() OVERRIDE;
+ const std::vector<media::PictureBuffer>& buffers) override;
+ virtual void ReusePictureBuffer(int32 picture_buffer_id) override;
+ virtual void Flush() override;
+ virtual void Reset() override;
+ virtual void Destroy() override;
+ virtual bool CanDecodeOnIOThread() override;
private:
// Notify the client that an error has occurred and decoding cannot continue.
diff --git a/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc b/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc
new file mode 100644
index 00000000000..19e1c0820dd
--- /dev/null
+++ b/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc
@@ -0,0 +1,1067 @@
+// Copyright 2014 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 "content/common/gpu/media/vaapi_video_encode_accelerator.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
+#include "base/numerics/safe_conversions.h"
+#include "content/common/gpu/media/h264_dpb.h"
+#include "content/public/common/content_switches.h"
+#include "media/base/bind_to_current_loop.h"
+#include "third_party/libva/va/va_enc_h264.h"
+
+#define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): "
+
+#define NOTIFY_ERROR(error, msg) \
+ do { \
+ SetState(kError); \
+ LOG(ERROR) << msg; \
+ LOG(ERROR) << "Calling NotifyError(" << error << ")";\
+ NotifyError(error); \
+ } while (0)
+
+namespace content {
+
+namespace {
+// Need 2 surfaces for each frame: one for input data and one for
+// reconstructed picture, which is later used for reference.
+const size_t kMinSurfacesToEncode = 2;
+
+// Subjectively chosen.
+const size_t kNumInputBuffers = 4;
+const size_t kMaxNumReferenceFrames = 4;
+
+// We need up to kMaxNumReferenceFrames surfaces for reference, plus one
+// for input and one for encode (which will be added to the set of reference
+// frames for subsequent frames). Actual execution of HW encode is done
+// in parallel, and we want to process more frames in the meantime.
+// To have kNumInputBuffers in flight, we need a full set of reference +
+// encode surfaces (i.e. kMaxNumReferenceFrames + kMinSurfacesToEncode), and
+// (kNumInputBuffers - 1) of kMinSurfacesToEncode for the remaining frames
+// in flight.
+const size_t kNumSurfaces = kMaxNumReferenceFrames + kMinSurfacesToEncode +
+ kMinSurfacesToEncode * (kNumInputBuffers - 1);
+
+// An IDR every 128 frames, an I frame every 30 and no B frames.
+const int kIDRPeriod = 128;
+const int kIPeriod = 30;
+const int kIPPeriod = 1;
+
+const int kDefaultFramerate = 30;
+
+// HRD parameters (ch. E.2.2 in spec).
+const int kBitRateScale = 0; // bit_rate_scale for SPS HRD parameters.
+const int kCPBSizeScale = 0; // cpb_size_scale for SPS HRD parameters.
+
+const int kDefaultQP = 26;
+// All Intel codecs can do at least 4.1.
+const int kDefaultLevelIDC = 41;
+const int kChromaFormatIDC = 1; // 4:2:0
+
+// Arbitrarily chosen bitrate window size for rate control, in ms.
+const int kCPBWindowSizeMs = 1500;
+
+// UMA errors that the VaapiVideoEncodeAccelerator class reports.
+enum VAVEAEncoderFailure {
+ VAAPI_ERROR = 0,
+ VAVEA_ENCODER_FAILURES_MAX,
+};
+
+}
+
+// Round |value| up to |alignment|, which must be a power of 2.
+static inline size_t RoundUpToPowerOf2(size_t value, size_t alignment) {
+ // Check that |alignment| is a power of 2.
+ DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
+ return ((value + (alignment - 1)) & ~(alignment - 1));
+}
+
+static void ReportToUMA(VAVEAEncoderFailure failure) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Media.VAVEA.EncoderFailure",
+ failure,
+ VAVEA_ENCODER_FAILURES_MAX);
+}
+
+struct VaapiVideoEncodeAccelerator::InputFrameRef {
+ InputFrameRef(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe)
+ : frame(frame), force_keyframe(force_keyframe) {}
+ const scoped_refptr<media::VideoFrame> frame;
+ const bool force_keyframe;
+};
+
+struct VaapiVideoEncodeAccelerator::BitstreamBufferRef {
+ BitstreamBufferRef(int32 id, scoped_ptr<base::SharedMemory> shm, size_t size)
+ : id(id), shm(shm.Pass()), size(size) {}
+ const int32 id;
+ const scoped_ptr<base::SharedMemory> shm;
+ const size_t size;
+};
+
+std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+VaapiVideoEncodeAccelerator::GetSupportedProfiles() {
+ std::vector<SupportedProfile> profiles;
+
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
+ return profiles;
+
+ std::vector<media::VideoCodecProfile> hw_profiles =
+ VaapiWrapper::GetSupportedEncodeProfiles(
+ x_display_, base::Bind(&base::DoNothing));
+
+ media::VideoEncodeAccelerator::SupportedProfile profile;
+ profile.max_resolution.SetSize(1920, 1088);
+ profile.max_framerate_numerator = kDefaultFramerate;
+ profile.max_framerate_denominator = 1;
+ for (size_t i = 0; i < hw_profiles.size(); i++) {
+ profile.profile = hw_profiles[i];
+ profiles.push_back(profile);
+ }
+ return profiles;
+}
+
+static unsigned int Log2OfPowerOf2(unsigned int x) {
+ CHECK_GT(x, 0u);
+ DCHECK_EQ(x & (x - 1), 0u);
+
+ int log = 0;
+ while (x) {
+ x >>= 1;
+ ++log;
+ }
+ return log;
+}
+
+VaapiVideoEncodeAccelerator::VaapiVideoEncodeAccelerator(Display* x_display)
+ : profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN),
+ mb_width_(0),
+ mb_height_(0),
+ output_buffer_byte_size_(0),
+ x_display_(x_display),
+ state_(kUninitialized),
+ frame_num_(0),
+ last_idr_frame_num_(0),
+ bitrate_(0),
+ framerate_(0),
+ cpb_size_(0),
+ encoding_parameters_changed_(false),
+ encoder_thread_("VAVEAEncoderThread"),
+ child_message_loop_proxy_(base::MessageLoopProxy::current()),
+ weak_this_ptr_factory_(this) {
+ DVLOGF(4);
+ weak_this_ = weak_this_ptr_factory_.GetWeakPtr();
+
+ max_ref_idx_l0_size_ = kMaxNumReferenceFrames;
+ qp_ = kDefaultQP;
+ idr_period_ = kIDRPeriod;
+ i_period_ = kIPeriod;
+ ip_period_ = kIPPeriod;
+}
+
+VaapiVideoEncodeAccelerator::~VaapiVideoEncodeAccelerator() {
+ DVLOGF(4);
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+ DCHECK(!encoder_thread_.IsRunning());
+}
+
+bool VaapiVideoEncodeAccelerator::Initialize(
+ media::VideoFrame::Format format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32 initial_bitrate,
+ Client* client) {
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+ DCHECK(!encoder_thread_.IsRunning());
+ DCHECK_EQ(state_, kUninitialized);
+
+ DVLOGF(1) << "Initializing VAVEA, input_format: "
+ << media::VideoFrame::FormatToString(format)
+ << ", input_visible_size: " << input_visible_size.ToString()
+ << ", output_profile: " << output_profile
+ << ", initial_bitrate: " << initial_bitrate;
+
+ client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
+ client_ = client_ptr_factory_->GetWeakPtr();
+
+ if (output_profile < media::H264PROFILE_BASELINE ||
+ output_profile > media::H264PROFILE_MAIN) {
+ DVLOGF(1) << "Unsupported output profile: " << output_profile;
+ return false;
+ }
+
+ if (format != media::VideoFrame::I420) {
+ DVLOGF(1) << "Unsupported input format: "
+ << media::VideoFrame::FormatToString(format);
+ return false;
+ }
+
+ profile_ = output_profile;
+ visible_size_ = input_visible_size;
+ // 4:2:0 format has to be 2-aligned.
+ DCHECK_EQ(visible_size_.width() % 2, 0);
+ DCHECK_EQ(visible_size_.height() % 2, 0);
+ coded_size_ = gfx::Size(RoundUpToPowerOf2(visible_size_.width(), 16),
+ RoundUpToPowerOf2(visible_size_.height(), 16));
+ mb_width_ = coded_size_.width() / 16;
+ mb_height_ = coded_size_.height() / 16;
+ output_buffer_byte_size_ = coded_size_.GetArea();
+
+ UpdateRates(initial_bitrate, kDefaultFramerate);
+
+ vaapi_wrapper_ = VaapiWrapper::Create(VaapiWrapper::kEncode,
+ output_profile,
+ x_display_,
+ base::Bind(&ReportToUMA, VAAPI_ERROR));
+ if (!vaapi_wrapper_) {
+ LOG(ERROR) << "Failed initializing VAAPI";
+ return false;
+ }
+
+ if (!encoder_thread_.Start()) {
+ LOG(ERROR) << "Failed to start encoder thread";
+ return false;
+ }
+ encoder_thread_proxy_ = encoder_thread_.message_loop_proxy();
+
+ // Finish the remaining initialization on the encoder thread.
+ encoder_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&VaapiVideoEncodeAccelerator::InitializeTask,
+ base::Unretained(this)));
+
+ return true;
+}
+
+void VaapiVideoEncodeAccelerator::InitializeTask() {
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, kUninitialized);
+ DVLOGF(4);
+
+ va_surface_release_cb_ = media::BindToCurrentLoop(
+ base::Bind(&VaapiVideoEncodeAccelerator::RecycleVASurfaceID,
+ base::Unretained(this)));
+
+ if (!vaapi_wrapper_->CreateSurfaces(
+ coded_size_, kNumSurfaces, &available_va_surface_ids_)) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed creating VASurfaces");
+ return;
+ }
+
+ UpdateSPS();
+ GeneratePackedSPS();
+
+ UpdatePPS();
+ GeneratePackedPPS();
+
+ child_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&Client::RequireBitstreamBuffers,
+ client_,
+ kNumInputBuffers,
+ coded_size_,
+ output_buffer_byte_size_));
+
+ SetState(kEncoding);
+}
+
+void VaapiVideoEncodeAccelerator::RecycleVASurfaceID(
+ VASurfaceID va_surface_id) {
+ DVLOGF(4) << "va_surface_id: " << va_surface_id;
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+
+ available_va_surface_ids_.push_back(va_surface_id);
+ EncodeFrameTask();
+}
+
+void VaapiVideoEncodeAccelerator::BeginFrame(bool force_keyframe) {
+ memset(&current_pic_, 0, sizeof(current_pic_));
+
+ current_pic_.frame_num = frame_num_++;
+ frame_num_ %= idr_period_;
+
+ if (current_pic_.frame_num % i_period_ == 0 || force_keyframe)
+ current_pic_.type = media::H264SliceHeader::kISlice;
+ else
+ current_pic_.type = media::H264SliceHeader::kPSlice;
+
+ if (current_pic_.frame_num % idr_period_ == 0 || force_keyframe) {
+ current_pic_.idr = true;
+ last_idr_frame_num_ = current_pic_.frame_num;
+ ref_pic_list0_.clear();
+ }
+
+ if (current_pic_.type != media::H264SliceHeader::kBSlice)
+ current_pic_.ref = true;
+
+ current_pic_.pic_order_cnt = current_pic_.frame_num * 2;
+ current_pic_.top_field_order_cnt = current_pic_.pic_order_cnt;
+ current_pic_.pic_order_cnt_lsb = current_pic_.pic_order_cnt;
+
+ current_encode_job_->keyframe = current_pic_.idr;
+
+ DVLOGF(4) << "Starting a new frame, type: " << current_pic_.type
+ << (force_keyframe ? " (forced keyframe)" : "")
+ << " frame_num: " << current_pic_.frame_num
+ << " POC: " << current_pic_.pic_order_cnt;
+}
+
+void VaapiVideoEncodeAccelerator::EndFrame() {
+ // Store the picture on the list of reference pictures and keep the list
+ // below maximum size, dropping oldest references.
+ if (current_pic_.ref)
+ ref_pic_list0_.push_front(current_encode_job_->recon_surface);
+ size_t max_num_ref_frames =
+ base::checked_cast<size_t>(current_sps_.max_num_ref_frames);
+ while (ref_pic_list0_.size() > max_num_ref_frames)
+ ref_pic_list0_.pop_back();
+
+ submitted_encode_jobs_.push(make_linked_ptr(current_encode_job_.release()));
+}
+
+static void InitVAPicture(VAPictureH264* va_pic) {
+ memset(va_pic, 0, sizeof(*va_pic));
+ va_pic->picture_id = VA_INVALID_ID;
+ va_pic->flags = VA_PICTURE_H264_INVALID;
+}
+
+bool VaapiVideoEncodeAccelerator::SubmitFrameParameters() {
+ VAEncSequenceParameterBufferH264 seq_param;
+ memset(&seq_param, 0, sizeof(seq_param));
+
+#define SPS_TO_SP(a) seq_param.a = current_sps_.a;
+ SPS_TO_SP(seq_parameter_set_id);
+ SPS_TO_SP(level_idc);
+
+ seq_param.intra_period = i_period_;
+ seq_param.intra_idr_period = idr_period_;
+ seq_param.ip_period = ip_period_;
+ seq_param.bits_per_second = bitrate_;
+
+ SPS_TO_SP(max_num_ref_frames);
+ seq_param.picture_width_in_mbs = mb_width_;
+ seq_param.picture_height_in_mbs = mb_height_;
+
+#define SPS_TO_SP_FS(a) seq_param.seq_fields.bits.a = current_sps_.a;
+ SPS_TO_SP_FS(chroma_format_idc);
+ SPS_TO_SP_FS(frame_mbs_only_flag);
+ SPS_TO_SP_FS(log2_max_frame_num_minus4);
+ SPS_TO_SP_FS(pic_order_cnt_type);
+ SPS_TO_SP_FS(log2_max_pic_order_cnt_lsb_minus4);
+#undef SPS_TO_SP_FS
+
+ SPS_TO_SP(bit_depth_luma_minus8);
+ SPS_TO_SP(bit_depth_chroma_minus8);
+
+ SPS_TO_SP(frame_cropping_flag);
+ if (current_sps_.frame_cropping_flag) {
+ SPS_TO_SP(frame_crop_left_offset);
+ SPS_TO_SP(frame_crop_right_offset);
+ SPS_TO_SP(frame_crop_top_offset);
+ SPS_TO_SP(frame_crop_bottom_offset);
+ }
+
+ SPS_TO_SP(vui_parameters_present_flag);
+#define SPS_TO_SP_VF(a) seq_param.vui_fields.bits.a = current_sps_.a;
+ SPS_TO_SP_VF(timing_info_present_flag);
+#undef SPS_TO_SP_VF
+ SPS_TO_SP(num_units_in_tick);
+ SPS_TO_SP(time_scale);
+#undef SPS_TO_SP
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncSequenceParameterBufferType,
+ sizeof(seq_param),
+ &seq_param))
+ return false;
+
+ VAEncPictureParameterBufferH264 pic_param;
+ memset(&pic_param, 0, sizeof(pic_param));
+
+ pic_param.CurrPic.picture_id = current_encode_job_->recon_surface->id();
+ pic_param.CurrPic.TopFieldOrderCnt = current_pic_.top_field_order_cnt;
+ pic_param.CurrPic.BottomFieldOrderCnt = current_pic_.bottom_field_order_cnt;
+ pic_param.CurrPic.flags = 0;
+
+ for (size_t i = 0; i < arraysize(pic_param.ReferenceFrames); ++i)
+ InitVAPicture(&pic_param.ReferenceFrames[i]);
+
+ DCHECK_LE(ref_pic_list0_.size(), arraysize(pic_param.ReferenceFrames));
+ RefPicList::const_iterator iter = ref_pic_list0_.begin();
+ for (size_t i = 0;
+ i < arraysize(pic_param.ReferenceFrames) && iter != ref_pic_list0_.end();
+ ++iter, ++i) {
+ pic_param.ReferenceFrames[i].picture_id = (*iter)->id();
+ pic_param.ReferenceFrames[i].flags = 0;
+ }
+
+ pic_param.coded_buf = current_encode_job_->coded_buffer;
+ pic_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id;
+ pic_param.seq_parameter_set_id = current_pps_.seq_parameter_set_id;
+ pic_param.frame_num = current_pic_.frame_num;
+ pic_param.pic_init_qp = qp_;
+ pic_param.num_ref_idx_l0_active_minus1 = max_ref_idx_l0_size_ - 1;
+ pic_param.pic_fields.bits.idr_pic_flag = current_pic_.idr;
+ pic_param.pic_fields.bits.reference_pic_flag = current_pic_.ref;
+#define PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = current_pps_.a;
+ PPS_TO_PP_PF(entropy_coding_mode_flag);
+ PPS_TO_PP_PF(transform_8x8_mode_flag);
+ PPS_TO_PP_PF(deblocking_filter_control_present_flag);
+#undef PPS_TO_PP_PF
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncPictureParameterBufferType,
+ sizeof(pic_param),
+ &pic_param))
+ return false;
+
+ VAEncSliceParameterBufferH264 slice_param;
+ memset(&slice_param, 0, sizeof(slice_param));
+
+ slice_param.num_macroblocks = mb_width_ * mb_height_;
+ slice_param.macroblock_info = VA_INVALID_ID;
+ slice_param.slice_type = current_pic_.type;
+ slice_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id;
+ slice_param.idr_pic_id = last_idr_frame_num_;
+ slice_param.pic_order_cnt_lsb = current_pic_.pic_order_cnt_lsb;
+ slice_param.num_ref_idx_active_override_flag = true;
+
+ for (size_t i = 0; i < arraysize(slice_param.RefPicList0); ++i)
+ InitVAPicture(&slice_param.RefPicList0[i]);
+
+ for (size_t i = 0; i < arraysize(slice_param.RefPicList1); ++i)
+ InitVAPicture(&slice_param.RefPicList1[i]);
+
+ DCHECK_LE(ref_pic_list0_.size(), arraysize(slice_param.RefPicList0));
+ iter = ref_pic_list0_.begin();
+ for (size_t i = 0;
+ i < arraysize(slice_param.RefPicList0) && iter != ref_pic_list0_.end();
+ ++iter, ++i) {
+ InitVAPicture(&slice_param.RefPicList0[i]);
+ slice_param.RefPicList0[i].picture_id = (*iter)->id();
+ slice_param.RefPicList0[i].flags = 0;
+ }
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncSliceParameterBufferType,
+ sizeof(slice_param),
+ &slice_param))
+ return false;
+
+ VAEncMiscParameterRateControl rate_control_param;
+ memset(&rate_control_param, 0, sizeof(rate_control_param));
+ rate_control_param.bits_per_second = bitrate_;
+ rate_control_param.target_percentage = 90;
+ rate_control_param.window_size = kCPBWindowSizeMs;
+ rate_control_param.initial_qp = qp_;
+ rate_control_param.rc_flags.bits.disable_frame_skip = true;
+
+ if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer(
+ VAEncMiscParameterTypeRateControl,
+ sizeof(rate_control_param),
+ &rate_control_param))
+ return false;
+
+ VAEncMiscParameterFrameRate framerate_param;
+ memset(&framerate_param, 0, sizeof(framerate_param));
+ framerate_param.framerate = framerate_;
+ if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer(
+ VAEncMiscParameterTypeFrameRate,
+ sizeof(framerate_param),
+ &framerate_param))
+ return false;
+
+ VAEncMiscParameterHRD hrd_param;
+ memset(&hrd_param, 0, sizeof(hrd_param));
+ hrd_param.buffer_size = cpb_size_;
+ hrd_param.initial_buffer_fullness = cpb_size_ / 2;
+ if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer(VAEncMiscParameterTypeHRD,
+ sizeof(hrd_param),
+ &hrd_param))
+ return false;
+
+ return true;
+}
+
+bool VaapiVideoEncodeAccelerator::SubmitHeadersIfNeeded() {
+ if (current_pic_.type != media::H264SliceHeader::kISlice)
+ return true;
+
+ // Submit PPS.
+ VAEncPackedHeaderParameterBuffer par_buffer;
+ memset(&par_buffer, 0, sizeof(par_buffer));
+ par_buffer.type = VAEncPackedHeaderSequence;
+ par_buffer.bit_length = packed_sps_.BytesInBuffer() * 8;
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderParameterBufferType,
+ sizeof(par_buffer),
+ &par_buffer))
+ return false;
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType,
+ packed_sps_.BytesInBuffer(),
+ packed_sps_.data()))
+ return false;
+
+ // Submit PPS.
+ memset(&par_buffer, 0, sizeof(par_buffer));
+ par_buffer.type = VAEncPackedHeaderPicture;
+ par_buffer.bit_length = packed_pps_.BytesInBuffer() * 8;
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderParameterBufferType,
+ sizeof(par_buffer),
+ &par_buffer))
+ return false;
+
+ if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType,
+ packed_pps_.BytesInBuffer(),
+ packed_pps_.data()))
+ return false;
+
+ return true;
+}
+
+bool VaapiVideoEncodeAccelerator::ExecuteEncode() {
+ DVLOGF(3) << "Encoding frame_num: " << current_pic_.frame_num;
+ return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers(
+ current_encode_job_->input_surface->id());
+}
+
+bool VaapiVideoEncodeAccelerator::UploadFrame(
+ const scoped_refptr<media::VideoFrame>& frame) {
+ return vaapi_wrapper_->UploadVideoFrameToSurface(
+ frame, current_encode_job_->input_surface->id());
+}
+
+void VaapiVideoEncodeAccelerator::TryToReturnBitstreamBuffer() {
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+
+ if (state_ != kEncoding)
+ return;
+
+ if (submitted_encode_jobs_.empty() || available_bitstream_buffers_.empty())
+ return;
+
+ linked_ptr<BitstreamBufferRef> buffer = available_bitstream_buffers_.front();
+ available_bitstream_buffers_.pop();
+
+ uint8* target_data = reinterpret_cast<uint8*>(buffer->shm->memory());
+
+ linked_ptr<EncodeJob> encode_job = submitted_encode_jobs_.front();
+ submitted_encode_jobs_.pop();
+
+ size_t data_size = 0;
+ if (!vaapi_wrapper_->DownloadAndDestroyCodedBuffer(
+ encode_job->coded_buffer,
+ encode_job->input_surface->id(),
+ target_data,
+ buffer->size,
+ &data_size)) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer");
+ return;
+ }
+
+ DVLOGF(3) << "Returning bitstream buffer "
+ << (encode_job->keyframe ? "(keyframe)" : "")
+ << " id: " << buffer->id << " size: " << data_size;
+
+ child_message_loop_proxy_->PostTask(FROM_HERE,
+ base::Bind(&Client::BitstreamBufferReady,
+ client_,
+ buffer->id,
+ data_size,
+ encode_job->keyframe));
+}
+
+void VaapiVideoEncodeAccelerator::Encode(
+ const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) {
+ DVLOGF(3) << "Frame timestamp: " << frame->timestamp().InMilliseconds()
+ << " force_keyframe: " << force_keyframe;
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+
+ encoder_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&VaapiVideoEncodeAccelerator::EncodeTask,
+ base::Unretained(this),
+ frame,
+ force_keyframe));
+}
+
+bool VaapiVideoEncodeAccelerator::PrepareNextJob() {
+ if (available_va_surface_ids_.size() < kMinSurfacesToEncode)
+ return false;
+
+ DCHECK(!current_encode_job_);
+ current_encode_job_.reset(new EncodeJob());
+
+ if (!vaapi_wrapper_->CreateCodedBuffer(output_buffer_byte_size_,
+ &current_encode_job_->coded_buffer)) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed creating coded buffer");
+ return false;
+ }
+
+ current_encode_job_->input_surface =
+ new VASurface(available_va_surface_ids_.back(), va_surface_release_cb_);
+ available_va_surface_ids_.pop_back();
+
+ current_encode_job_->recon_surface =
+ new VASurface(available_va_surface_ids_.back(), va_surface_release_cb_);
+ available_va_surface_ids_.pop_back();
+
+ // Reference surfaces are needed until the job is done, but they get
+ // removed from ref_pic_list0_ when it's full at the end of job submission.
+ // Keep refs to them along with the job and only release after sync.
+ current_encode_job_->reference_surfaces = ref_pic_list0_;
+
+ return true;
+}
+
+void VaapiVideoEncodeAccelerator::EncodeTask(
+ const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) {
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+ DCHECK_NE(state_, kUninitialized);
+
+ encoder_input_queue_.push(
+ make_linked_ptr(new InputFrameRef(frame, force_keyframe)));
+ EncodeFrameTask();
+}
+
+void VaapiVideoEncodeAccelerator::EncodeFrameTask() {
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+
+ if (state_ != kEncoding || encoder_input_queue_.empty())
+ return;
+
+ if (!PrepareNextJob()) {
+ DVLOGF(4) << "Not ready for next frame yet";
+ return;
+ }
+
+ linked_ptr<InputFrameRef> frame_ref = encoder_input_queue_.front();
+ encoder_input_queue_.pop();
+
+ if (!UploadFrame(frame_ref->frame)) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed uploading source frame to HW.");
+ return;
+ }
+
+ BeginFrame(frame_ref->force_keyframe || encoding_parameters_changed_);
+ encoding_parameters_changed_ = false;
+
+ if (!SubmitFrameParameters()) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed submitting frame parameters.");
+ return;
+ }
+
+ if (!SubmitHeadersIfNeeded()) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed submitting frame headers.");
+ return;
+ }
+
+ if (!ExecuteEncode()) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed submitting encode job to HW.");
+ return;
+ }
+
+ EndFrame();
+ TryToReturnBitstreamBuffer();
+}
+
+void VaapiVideoEncodeAccelerator::UseOutputBitstreamBuffer(
+ const media::BitstreamBuffer& buffer) {
+ DVLOGF(4) << "id: " << buffer.id();
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+
+ if (buffer.size() < output_buffer_byte_size_) {
+ NOTIFY_ERROR(kInvalidArgumentError, "Provided bitstream buffer too small");
+ return;
+ }
+
+ scoped_ptr<base::SharedMemory> shm(
+ new base::SharedMemory(buffer.handle(), false));
+ if (!shm->Map(buffer.size())) {
+ NOTIFY_ERROR(kPlatformFailureError, "Failed mapping shared memory.");
+ return;
+ }
+
+ scoped_ptr<BitstreamBufferRef> buffer_ref(
+ new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size()));
+
+ encoder_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask,
+ base::Unretained(this),
+ base::Passed(&buffer_ref)));
+}
+
+void VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask(
+ scoped_ptr<BitstreamBufferRef> buffer_ref) {
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+ DCHECK_NE(state_, kUninitialized);
+
+ available_bitstream_buffers_.push(make_linked_ptr(buffer_ref.release()));
+ TryToReturnBitstreamBuffer();
+}
+
+void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange(
+ uint32 bitrate,
+ uint32 framerate) {
+ DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate;
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+
+ encoder_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask,
+ base::Unretained(this),
+ bitrate,
+ framerate));
+}
+
+void VaapiVideoEncodeAccelerator::UpdateRates(uint32 bitrate,
+ uint32 framerate) {
+ if (encoder_thread_.IsRunning())
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+ DCHECK_NE(bitrate, 0u);
+ DCHECK_NE(framerate, 0u);
+ bitrate_ = bitrate;
+ framerate_ = framerate;
+ cpb_size_ = bitrate_ * kCPBWindowSizeMs / 1000;
+}
+
+void VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
+ uint32 bitrate,
+ uint32 framerate) {
+ DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate;
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+ DCHECK_NE(state_, kUninitialized);
+
+ // This is a workaround to zero being temporarily, as part of the initial
+ // setup, provided by the webrtc video encode and a zero bitrate and
+ // framerate not being accepted by VAAPI
+ // TODO: This code is common with v4l2_video_encode_accelerator.cc, perhaps
+ // it could be pulled up to RTCVideoEncoder
+ if (bitrate < 1)
+ bitrate = 1;
+ if (framerate < 1)
+ framerate = 1;
+
+ UpdateRates(bitrate, framerate);
+
+ UpdateSPS();
+ GeneratePackedSPS();
+
+ // Submit new parameters along with next frame that will be processed.
+ encoding_parameters_changed_ = true;
+}
+
+void VaapiVideoEncodeAccelerator::Destroy() {
+ DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
+
+ // Can't call client anymore after Destroy() returns.
+ client_ptr_factory_.reset();
+ weak_this_ptr_factory_.InvalidateWeakPtrs();
+
+ // Early-exit encoder tasks if they are running and join the thread.
+ if (encoder_thread_.IsRunning()) {
+ encoder_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&VaapiVideoEncodeAccelerator::DestroyTask,
+ base::Unretained(this)));
+ encoder_thread_.Stop();
+ }
+
+ delete this;
+}
+
+void VaapiVideoEncodeAccelerator::DestroyTask() {
+ DVLOGF(2);
+ DCHECK(encoder_thread_proxy_->BelongsToCurrentThread());
+ SetState(kError);
+}
+
+void VaapiVideoEncodeAccelerator::UpdateSPS() {
+ memset(&current_sps_, 0, sizeof(media::H264SPS));
+
+ // Spec A.2 and A.3.
+ switch (profile_) {
+ case media::H264PROFILE_BASELINE:
+ // Due to crbug.com/345569, we don't distinguish between constrained
+ // and non-constrained baseline profiles. Since many codecs can't do
+ // non-constrained, and constrained is usually what we mean (and it's a
+ // subset of non-constrained), default to it.
+ current_sps_.profile_idc = media::H264SPS::kProfileIDCBaseline;
+ current_sps_.constraint_set0_flag = true;
+ break;
+ case media::H264PROFILE_MAIN:
+ current_sps_.profile_idc = media::H264SPS::kProfileIDCMain;
+ current_sps_.constraint_set1_flag = true;
+ break;
+ case media::H264PROFILE_HIGH:
+ current_sps_.profile_idc = media::H264SPS::kProfileIDCHigh;
+ break;
+ default:
+ NOTIMPLEMENTED();
+ return;
+ }
+
+ current_sps_.level_idc = kDefaultLevelIDC;
+ current_sps_.seq_parameter_set_id = 0;
+ current_sps_.chroma_format_idc = kChromaFormatIDC;
+
+ DCHECK_GE(idr_period_, 1u << 4);
+ current_sps_.log2_max_frame_num_minus4 = Log2OfPowerOf2(idr_period_) - 4;
+ current_sps_.pic_order_cnt_type = 0;
+ current_sps_.log2_max_pic_order_cnt_lsb_minus4 =
+ Log2OfPowerOf2(idr_period_ * 2) - 4;
+ current_sps_.max_num_ref_frames = max_ref_idx_l0_size_;
+
+ current_sps_.frame_mbs_only_flag = true;
+
+ DCHECK_GT(mb_width_, 0u);
+ DCHECK_GT(mb_height_, 0u);
+ current_sps_.pic_width_in_mbs_minus1 = mb_width_ - 1;
+ DCHECK(current_sps_.frame_mbs_only_flag);
+ current_sps_.pic_height_in_map_units_minus1 = mb_height_ - 1;
+
+ if (visible_size_ != coded_size_) {
+ // Visible size differs from coded size, fill crop information.
+ current_sps_.frame_cropping_flag = true;
+ DCHECK(!current_sps_.separate_colour_plane_flag);
+ // Spec table 6-1. Only 4:2:0 for now.
+ DCHECK_EQ(current_sps_.chroma_format_idc, 1);
+ // Spec 7.4.2.1.1. Crop is in crop units, which is 2 pixels for 4:2:0.
+ const unsigned int crop_unit_x = 2;
+ const unsigned int crop_unit_y = 2 * (2 - current_sps_.frame_mbs_only_flag);
+ current_sps_.frame_crop_left_offset = 0;
+ current_sps_.frame_crop_right_offset =
+ (coded_size_.width() - visible_size_.width()) / crop_unit_x;
+ current_sps_.frame_crop_top_offset = 0;
+ current_sps_.frame_crop_bottom_offset =
+ (coded_size_.height() - visible_size_.height()) / crop_unit_y;
+ }
+
+ current_sps_.vui_parameters_present_flag = true;
+ current_sps_.timing_info_present_flag = true;
+ current_sps_.num_units_in_tick = 1;
+ current_sps_.time_scale = framerate_ * 2; // See equation D-2 in spec.
+ current_sps_.fixed_frame_rate_flag = true;
+
+ current_sps_.nal_hrd_parameters_present_flag = true;
+ // H.264 spec ch. E.2.2.
+ current_sps_.cpb_cnt_minus1 = 0;
+ current_sps_.bit_rate_scale = kBitRateScale;
+ current_sps_.cpb_size_scale = kCPBSizeScale;
+ current_sps_.bit_rate_value_minus1[0] =
+ (bitrate_ >>
+ (kBitRateScale + media::H264SPS::kBitRateScaleConstantTerm)) - 1;
+ current_sps_.cpb_size_value_minus1[0] =
+ (cpb_size_ >>
+ (kCPBSizeScale + media::H264SPS::kCPBSizeScaleConstantTerm)) - 1;
+ current_sps_.cbr_flag[0] = true;
+ current_sps_.initial_cpb_removal_delay_length_minus_1 =
+ media::H264SPS::kDefaultInitialCPBRemovalDelayLength - 1;
+ current_sps_.cpb_removal_delay_length_minus1 =
+ media::H264SPS::kDefaultInitialCPBRemovalDelayLength - 1;
+ current_sps_.dpb_output_delay_length_minus1 =
+ media::H264SPS::kDefaultDPBOutputDelayLength - 1;
+ current_sps_.time_offset_length = media::H264SPS::kDefaultTimeOffsetLength;
+ current_sps_.low_delay_hrd_flag = false;
+}
+
+void VaapiVideoEncodeAccelerator::GeneratePackedSPS() {
+ packed_sps_.Reset();
+
+ packed_sps_.BeginNALU(media::H264NALU::kSPS, 3);
+
+ packed_sps_.AppendBits(8, current_sps_.profile_idc);
+ packed_sps_.AppendBool(current_sps_.constraint_set0_flag);
+ packed_sps_.AppendBool(current_sps_.constraint_set1_flag);
+ packed_sps_.AppendBool(current_sps_.constraint_set2_flag);
+ packed_sps_.AppendBool(current_sps_.constraint_set3_flag);
+ packed_sps_.AppendBool(current_sps_.constraint_set4_flag);
+ packed_sps_.AppendBool(current_sps_.constraint_set5_flag);
+ packed_sps_.AppendBits(2, 0); // reserved_zero_2bits
+ packed_sps_.AppendBits(8, current_sps_.level_idc);
+ packed_sps_.AppendUE(current_sps_.seq_parameter_set_id);
+
+ if (current_sps_.profile_idc == media::H264SPS::kProfileIDCHigh) {
+ packed_sps_.AppendUE(current_sps_.chroma_format_idc);
+ if (current_sps_.chroma_format_idc == 3)
+ packed_sps_.AppendBool(current_sps_.separate_colour_plane_flag);
+ packed_sps_.AppendUE(current_sps_.bit_depth_luma_minus8);
+ packed_sps_.AppendUE(current_sps_.bit_depth_chroma_minus8);
+ packed_sps_.AppendBool(current_sps_.qpprime_y_zero_transform_bypass_flag);
+ packed_sps_.AppendBool(current_sps_.seq_scaling_matrix_present_flag);
+ CHECK(!current_sps_.seq_scaling_matrix_present_flag);
+ }
+
+ packed_sps_.AppendUE(current_sps_.log2_max_frame_num_minus4);
+ packed_sps_.AppendUE(current_sps_.pic_order_cnt_type);
+ if (current_sps_.pic_order_cnt_type == 0)
+ packed_sps_.AppendUE(current_sps_.log2_max_pic_order_cnt_lsb_minus4);
+ else if (current_sps_.pic_order_cnt_type == 1) {
+ CHECK(1);
+ }
+
+ packed_sps_.AppendUE(current_sps_.max_num_ref_frames);
+ packed_sps_.AppendBool(current_sps_.gaps_in_frame_num_value_allowed_flag);
+ packed_sps_.AppendUE(current_sps_.pic_width_in_mbs_minus1);
+ packed_sps_.AppendUE(current_sps_.pic_height_in_map_units_minus1);
+
+ packed_sps_.AppendBool(current_sps_.frame_mbs_only_flag);
+ if (!current_sps_.frame_mbs_only_flag)
+ packed_sps_.AppendBool(current_sps_.mb_adaptive_frame_field_flag);
+
+ packed_sps_.AppendBool(current_sps_.direct_8x8_inference_flag);
+
+ packed_sps_.AppendBool(current_sps_.frame_cropping_flag);
+ if (current_sps_.frame_cropping_flag) {
+ packed_sps_.AppendUE(current_sps_.frame_crop_left_offset);
+ packed_sps_.AppendUE(current_sps_.frame_crop_right_offset);
+ packed_sps_.AppendUE(current_sps_.frame_crop_top_offset);
+ packed_sps_.AppendUE(current_sps_.frame_crop_bottom_offset);
+ }
+
+ packed_sps_.AppendBool(current_sps_.vui_parameters_present_flag);
+ if (current_sps_.vui_parameters_present_flag) {
+ packed_sps_.AppendBool(false); // aspect_ratio_info_present_flag
+ packed_sps_.AppendBool(false); // overscan_info_present_flag
+ packed_sps_.AppendBool(false); // video_signal_type_present_flag
+ packed_sps_.AppendBool(false); // chroma_loc_info_present_flag
+
+ packed_sps_.AppendBool(current_sps_.timing_info_present_flag);
+ if (current_sps_.timing_info_present_flag) {
+ packed_sps_.AppendBits(32, current_sps_.num_units_in_tick);
+ packed_sps_.AppendBits(32, current_sps_.time_scale);
+ packed_sps_.AppendBool(current_sps_.fixed_frame_rate_flag);
+ }
+
+ packed_sps_.AppendBool(current_sps_.nal_hrd_parameters_present_flag);
+ if (current_sps_.nal_hrd_parameters_present_flag) {
+ packed_sps_.AppendUE(current_sps_.cpb_cnt_minus1);
+ packed_sps_.AppendBits(4, current_sps_.bit_rate_scale);
+ packed_sps_.AppendBits(4, current_sps_.cpb_size_scale);
+ CHECK_LT(base::checked_cast<size_t>(current_sps_.cpb_cnt_minus1),
+ arraysize(current_sps_.bit_rate_value_minus1));
+ for (int i = 0; i <= current_sps_.cpb_cnt_minus1; ++i) {
+ packed_sps_.AppendUE(current_sps_.bit_rate_value_minus1[i]);
+ packed_sps_.AppendUE(current_sps_.cpb_size_value_minus1[i]);
+ packed_sps_.AppendBool(current_sps_.cbr_flag[i]);
+ }
+ packed_sps_.AppendBits(
+ 5, current_sps_.initial_cpb_removal_delay_length_minus_1);
+ packed_sps_.AppendBits(5, current_sps_.cpb_removal_delay_length_minus1);
+ packed_sps_.AppendBits(5, current_sps_.dpb_output_delay_length_minus1);
+ packed_sps_.AppendBits(5, current_sps_.time_offset_length);
+ }
+
+ packed_sps_.AppendBool(false); // vcl_hrd_parameters_flag
+ if (current_sps_.nal_hrd_parameters_present_flag)
+ packed_sps_.AppendBool(current_sps_.low_delay_hrd_flag);
+
+ packed_sps_.AppendBool(false); // pic_struct_present_flag
+ packed_sps_.AppendBool(false); // bitstream_restriction_flag
+ }
+
+ packed_sps_.FinishNALU();
+}
+
+void VaapiVideoEncodeAccelerator::UpdatePPS() {
+ memset(&current_pps_, 0, sizeof(media::H264PPS));
+
+ current_pps_.seq_parameter_set_id = current_sps_.seq_parameter_set_id;
+ current_pps_.pic_parameter_set_id = 0;
+
+ current_pps_.entropy_coding_mode_flag =
+ current_sps_.profile_idc >= media::H264SPS::kProfileIDCMain;
+
+ CHECK_GT(max_ref_idx_l0_size_, 0u);
+ current_pps_.num_ref_idx_l0_default_active_minus1 = max_ref_idx_l0_size_ - 1;
+ current_pps_.num_ref_idx_l1_default_active_minus1 = 0;
+ DCHECK_LE(qp_, 51u);
+ current_pps_.pic_init_qp_minus26 = qp_ - 26;
+ current_pps_.deblocking_filter_control_present_flag = true;
+ current_pps_.transform_8x8_mode_flag =
+ (current_sps_.profile_idc == media::H264SPS::kProfileIDCHigh);
+}
+
+void VaapiVideoEncodeAccelerator::GeneratePackedPPS() {
+ packed_pps_.Reset();
+
+ packed_pps_.BeginNALU(media::H264NALU::kPPS, 3);
+
+ packed_pps_.AppendUE(current_pps_.pic_parameter_set_id);
+ packed_pps_.AppendUE(current_pps_.seq_parameter_set_id);
+ packed_pps_.AppendBool(current_pps_.entropy_coding_mode_flag);
+ packed_pps_.AppendBool(
+ current_pps_.bottom_field_pic_order_in_frame_present_flag);
+ CHECK_EQ(current_pps_.num_slice_groups_minus1, 0);
+ packed_pps_.AppendUE(current_pps_.num_slice_groups_minus1);
+
+ packed_pps_.AppendUE(current_pps_.num_ref_idx_l0_default_active_minus1);
+ packed_pps_.AppendUE(current_pps_.num_ref_idx_l1_default_active_minus1);
+
+ packed_pps_.AppendBool(current_pps_.weighted_pred_flag);
+ packed_pps_.AppendBits(2, current_pps_.weighted_bipred_idc);
+
+ packed_pps_.AppendSE(current_pps_.pic_init_qp_minus26);
+ packed_pps_.AppendSE(current_pps_.pic_init_qs_minus26);
+ packed_pps_.AppendSE(current_pps_.chroma_qp_index_offset);
+
+ packed_pps_.AppendBool(current_pps_.deblocking_filter_control_present_flag);
+ packed_pps_.AppendBool(current_pps_.constrained_intra_pred_flag);
+ packed_pps_.AppendBool(current_pps_.redundant_pic_cnt_present_flag);
+
+ packed_pps_.AppendBool(current_pps_.transform_8x8_mode_flag);
+ packed_pps_.AppendBool(current_pps_.pic_scaling_matrix_present_flag);
+ DCHECK(!current_pps_.pic_scaling_matrix_present_flag);
+ packed_pps_.AppendSE(current_pps_.second_chroma_qp_index_offset);
+
+ packed_pps_.FinishNALU();
+}
+
+void VaapiVideoEncodeAccelerator::SetState(State state) {
+ // Only touch state on encoder thread, unless it's not running.
+ if (encoder_thread_.IsRunning() &&
+ !encoder_thread_proxy_->BelongsToCurrentThread()) {
+ encoder_thread_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&VaapiVideoEncodeAccelerator::SetState,
+ base::Unretained(this),
+ state));
+ return;
+ }
+
+ DVLOGF(1) << "setting state to: " << state;
+ state_ = state;
+}
+
+void VaapiVideoEncodeAccelerator::NotifyError(Error error) {
+ if (!child_message_loop_proxy_->BelongsToCurrentThread()) {
+ child_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &VaapiVideoEncodeAccelerator::NotifyError, weak_this_, error));
+ return;
+ }
+
+ if (client_) {
+ client_->NotifyError(error);
+ client_ptr_factory_.reset();
+ }
+}
+
+VaapiVideoEncodeAccelerator::EncodeJob::EncodeJob()
+ : coded_buffer(VA_INVALID_ID), keyframe(false) {
+}
+
+VaapiVideoEncodeAccelerator::EncodeJob::~EncodeJob() {
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.h b/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.h
new file mode 100644
index 00000000000..520228cbc1e
--- /dev/null
+++ b/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.h
@@ -0,0 +1,263 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
+#define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
+
+#include <list>
+#include <queue>
+
+#include "base/memory/linked_ptr.h"
+#include "base/threading/thread.h"
+#include "content/common/content_export.h"
+#include "content/common/gpu/media/h264_dpb.h"
+#include "content/common/gpu/media/va_surface.h"
+#include "content/common/gpu/media/vaapi_wrapper.h"
+#include "media/filters/h264_bitstream_buffer.h"
+#include "media/video/video_encode_accelerator.h"
+
+namespace content {
+
+// A VideoEncodeAccelerator implementation that uses VA-API
+// (http://www.freedesktop.org/wiki/Software/vaapi) for HW-accelerated
+// video encode.
+class CONTENT_EXPORT VaapiVideoEncodeAccelerator
+ : public media::VideoEncodeAccelerator {
+ public:
+ explicit VaapiVideoEncodeAccelerator(Display* x_display);
+ virtual ~VaapiVideoEncodeAccelerator();
+
+ // media::VideoEncodeAccelerator implementation.
+ virtual std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+ GetSupportedProfiles() override;
+ virtual bool Initialize(media::VideoFrame::Format format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32 initial_bitrate,
+ Client* client) override;
+ virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) override;
+ virtual void UseOutputBitstreamBuffer(
+ const media::BitstreamBuffer& buffer) override;
+ virtual void RequestEncodingParametersChange(uint32 bitrate,
+ uint32 framerate) override;
+ virtual void Destroy() override;
+
+ private:
+ // Reference picture list.
+ typedef std::list<scoped_refptr<VASurface> > RefPicList;
+
+ // Encode job for one frame. Created when an input frame is awaiting and
+ // enough resources are available to proceed. Once the job is prepared and
+ // submitted to the hardware, it awaits on the submitted_encode_jobs_ queue
+ // for an output bitstream buffer to become available. Once one is ready,
+ // the encoded bytes are downloaded to it and job resources are released
+ // and become available for reuse.
+ struct EncodeJob {
+ // Input surface for video frame data.
+ scoped_refptr<VASurface> input_surface;
+ // Surface for a reconstructed picture, which is used for reference
+ // for subsequent frames.
+ scoped_refptr<VASurface> recon_surface;
+ // Buffer that will contain output bitstream for this frame.
+ VABufferID coded_buffer;
+ // Reference surfaces required to encode this picture. We keep references
+ // to them here, because we may discard some of them from ref_pic_list*
+ // before the HW job is done.
+ RefPicList reference_surfaces;
+ // True if this job will produce a keyframe. Used to report
+ // to BitstreamBufferReady().
+ bool keyframe;
+
+ EncodeJob();
+ ~EncodeJob();
+ };
+
+ // Encoder state.
+ enum State {
+ kUninitialized,
+ kEncoding,
+ kError,
+ };
+
+ // Holds input frames coming from the client ready to be encoded.
+ struct InputFrameRef;
+ // Holds output buffers coming from the client ready to be filled.
+ struct BitstreamBufferRef;
+
+ // Tasks for each of the VEA interface calls to be executed on the
+ // encoder thread.
+ void InitializeTask();
+ void EncodeTask(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe);
+ void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref);
+ void RequestEncodingParametersChangeTask(uint32 bitrate, uint32 framerate);
+ void DestroyTask();
+
+ // Prepare and schedule an encode job if we have an input to encode
+ // and enough resources to proceed.
+ void EncodeFrameTask();
+
+ // Fill current_sps_/current_pps_ with current values.
+ void UpdateSPS();
+ void UpdatePPS();
+ void UpdateRates(uint32 bitrate, uint32 framerate);
+
+ // Generate packed SPS and PPS in packed_sps_/packed_pps_, using
+ // values in current_sps_/current_pps_.
+ void GeneratePackedSPS();
+ void GeneratePackedPPS();
+
+ // Check if we have sufficient resources for a new encode job, claim them and
+ // fill current_encode_job_ with them.
+ // Return false if we cannot start a new job yet, true otherwise.
+ bool PrepareNextJob();
+
+ // Begin a new frame, making it a keyframe if |force_keyframe| is true,
+ // updating current_pic_.
+ void BeginFrame(bool force_keyframe);
+
+ // End current frame, updating reference picture lists and storing current
+ // job in the jobs awaiting completion on submitted_encode_jobs_.
+ void EndFrame();
+
+ // Submit parameters for the current frame to the hardware.
+ bool SubmitFrameParameters();
+ // Submit keyframe headers to the hardware if the current frame is a keyframe.
+ bool SubmitHeadersIfNeeded();
+
+ // Upload image data from |frame| to the input surface for current job.
+ bool UploadFrame(const scoped_refptr<media::VideoFrame>& frame);
+
+ // Execute encode in hardware. This does not block and will return before
+ // the job is finished.
+ bool ExecuteEncode();
+
+ // Callback that returns a no longer used VASurfaceID to
+ // available_va_surface_ids_ for reuse.
+ void RecycleVASurfaceID(VASurfaceID va_surface_id);
+
+ // Tries to return a bitstream buffer if both a submitted job awaits to
+ // be completed and we have bitstream buffers from the client available
+ // to download the encoded data to.
+ void TryToReturnBitstreamBuffer();
+
+ // Puts the encoder into en error state and notifies client about the error.
+ void NotifyError(Error error);
+
+ // Sets the encoder state on the correct thread.
+ void SetState(State state);
+
+ // VaapiWrapper is the owner of all HW resources (surfaces and buffers)
+ // and will free them on destruction.
+ scoped_ptr<VaapiWrapper> vaapi_wrapper_;
+
+ // Input profile and sizes.
+ media::VideoCodecProfile profile_;
+ gfx::Size visible_size_;
+ gfx::Size coded_size_; // Macroblock-aligned.
+ // Width/height in macroblocks.
+ unsigned int mb_width_;
+ unsigned int mb_height_;
+
+ // Maximum size of the reference list 0.
+ unsigned int max_ref_idx_l0_size_;
+
+ // Initial QP.
+ unsigned int qp_;
+
+ // IDR frame period.
+ unsigned int idr_period_;
+ // I frame period.
+ unsigned int i_period_;
+ // IP period, i.e. how often do we need to have either an I or a P frame in
+ // the stream. Period of 1 means we can have no B frames.
+ unsigned int ip_period_;
+
+ // Size in bytes required for input bitstream buffers.
+ size_t output_buffer_byte_size_;
+
+ Display* x_display_;
+
+ // All of the members below must be accessed on the encoder_thread_,
+ // while it is running.
+
+ // Encoder state. Encode tasks will only run in kEncoding state.
+ State state_;
+
+ // frame_num to be used for the next frame.
+ unsigned int frame_num_;
+ // frame_num of the previous IDR.
+ unsigned int last_idr_frame_num_;
+
+ // Current bitrate in bps.
+ unsigned int bitrate_;
+ // Current fps.
+ unsigned int framerate_;
+ // CPB size in bits, i.e. bitrate in kbps * window size in ms/1000.
+ unsigned int cpb_size_;
+ // True if the parameters have changed and we need to submit a keyframe
+ // with updated parameters.
+ bool encoding_parameters_changed_;
+
+ // Job currently being prepared for encode.
+ scoped_ptr<EncodeJob> current_encode_job_;
+
+ // Current SPS, PPS and their packed versions. Packed versions are their NALUs
+ // in AnnexB format *without* emulation prevention three-byte sequences
+ // (those will be added by the driver).
+ media::H264SPS current_sps_;
+ media::H264BitstreamBuffer packed_sps_;
+ media::H264PPS current_pps_;
+ media::H264BitstreamBuffer packed_pps_;
+
+ // Picture currently being prepared for encode.
+ H264Picture current_pic_;
+
+ // VA surfaces available for reuse.
+ std::vector<VASurfaceID> available_va_surface_ids_;
+
+ // VA buffers for coded frames.
+ std::vector<VABufferID> available_va_buffer_ids_;
+
+ // Currently active reference surfaces.
+ RefPicList ref_pic_list0_;
+
+ // Callback via which finished VA surfaces are returned to us.
+ VASurface::ReleaseCB va_surface_release_cb_;
+
+ // VideoFrames passed from the client, waiting to be encoded.
+ std::queue<linked_ptr<InputFrameRef> > encoder_input_queue_;
+
+ // BitstreamBuffers mapped, ready to be filled.
+ std::queue<linked_ptr<BitstreamBufferRef> > available_bitstream_buffers_;
+
+ // Jobs submitted for encode, awaiting bitstream buffers to become available.
+ std::queue<linked_ptr<EncodeJob> > submitted_encode_jobs_;
+
+ // Encoder thread. All tasks are executed on it.
+ base::Thread encoder_thread_;
+ scoped_refptr<base::MessageLoopProxy> encoder_thread_proxy_;
+
+ const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
+
+ // To expose client callbacks from VideoEncodeAccelerator.
+ // NOTE: all calls to these objects *MUST* be executed on
+ // child_message_loop_proxy_.
+ scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
+ base::WeakPtr<Client> client_;
+
+ // WeakPtr to post from the encoder thread back to the ChildThread, as it may
+ // outlive this. Posting from the ChildThread using base::Unretained(this)
+ // to the encoder thread is safe, because |this| always outlives the encoder
+ // thread (it's a member of this class).
+ base::WeakPtr<VaapiVideoEncodeAccelerator> weak_this_;
+ base::WeakPtrFactory<VaapiVideoEncodeAccelerator> weak_this_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VaapiVideoEncodeAccelerator);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
diff --git a/chromium/content/common/gpu/media/vaapi_wrapper.cc b/chromium/content/common/gpu/media/vaapi_wrapper.cc
index 5250e590eac..2b4b33349aa 100644
--- a/chromium/content/common/gpu/media/vaapi_wrapper.cc
+++ b/chromium/content/common/gpu/media/vaapi_wrapper.cc
@@ -7,10 +7,12 @@
#include <dlfcn.h>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
// Auto-generated for dlopen libva libraries
#include "content/common/gpu/media/va_stubs.h"
+#include "third_party/libyuv/include/libyuv.h"
using content_common_gpu_media::kModuleVa;
using content_common_gpu_media::InitializeStubs;
@@ -22,7 +24,7 @@ static const base::FilePath::CharType kVaLib[] =
#define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
do { \
- DVLOG(1) << err_msg \
+ LOG(ERROR) << err_msg \
<< " VA error: " << vaErrorStr(va_error); \
report_error_to_uma_cb_.Run(); \
} while (0)
@@ -43,27 +45,59 @@ static const base::FilePath::CharType kVaLib[] =
namespace content {
+// Config attributes common for both encode and decode.
+static const VAConfigAttrib kCommonVAConfigAttribs[] = {
+ {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
+};
+
+// Attributes required for encode.
+static const VAConfigAttrib kEncodeVAConfigAttribs[] = {
+ {VAConfigAttribRateControl, VA_RC_CBR},
+ {VAConfigAttribEncPackedHeaders,
+ VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE},
+};
+
+struct ProfileMap {
+ media::VideoCodecProfile profile;
+ VAProfile va_profile;
+};
+
+// A map between VideoCodecProfile and VAProfile.
+static const ProfileMap kProfileMap[] = {
+ {media::H264PROFILE_BASELINE, VAProfileH264Baseline},
+ {media::H264PROFILE_MAIN, VAProfileH264Main},
+ // TODO(posciak): See if we can/want support other variants of
+ // media::H264PROFILE_HIGH*.
+ {media::H264PROFILE_HIGH, VAProfileH264High},
+};
+
+static std::vector<VAConfigAttrib> GetRequiredAttribs(
+ VaapiWrapper::CodecMode mode) {
+ std::vector<VAConfigAttrib> required_attribs;
+ required_attribs.insert(
+ required_attribs.end(),
+ kCommonVAConfigAttribs,
+ kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
+ if (mode == VaapiWrapper::kEncode) {
+ required_attribs.insert(
+ required_attribs.end(),
+ kEncodeVAConfigAttribs,
+ kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
+ }
+ return required_attribs;
+}
+
// Maps Profile enum values to VaProfile values.
static VAProfile ProfileToVAProfile(
media::VideoCodecProfile profile,
const std::vector<VAProfile>& supported_profiles) {
VAProfile va_profile = VAProfileNone;
-
- switch (profile) {
- case media::H264PROFILE_BASELINE:
- va_profile = VAProfileH264Baseline;
- break;
- case media::H264PROFILE_MAIN:
- va_profile = VAProfileH264Main;
- break;
- // TODO(posciak): See if we can/want support other variants
- // of media::H264PROFILE_HIGH*.
- case media::H264PROFILE_HIGH:
- va_profile = VAProfileH264High;
- break;
- default:
+ for (size_t i = 0; i < arraysize(kProfileMap); i++) {
+ if (kProfileMap[i].profile == profile) {
+ va_profile = kProfileMap[i].va_profile;
break;
+ }
}
bool supported = std::find(supported_profiles.begin(),
@@ -106,23 +140,55 @@ VaapiWrapper::VaapiWrapper()
VaapiWrapper::~VaapiWrapper() {
DestroyPendingBuffers();
+ DestroyCodedBuffers();
DestroySurfaces();
Deinitialize();
}
scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
+ CodecMode mode,
media::VideoCodecProfile profile,
Display* x_display,
const base::Closure& report_error_to_uma_cb) {
scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
- if (!vaapi_wrapper->Initialize(profile, x_display, report_error_to_uma_cb))
+ if (!vaapi_wrapper->Initialize(
+ mode, profile, x_display, report_error_to_uma_cb))
vaapi_wrapper.reset();
return vaapi_wrapper.Pass();
}
+std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles(
+ Display* x_display,
+ const base::Closure& report_error_to_uma_cb) {
+ std::vector<media::VideoCodecProfile> supported_profiles;
+
+ scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper());
+ if (!wrapper->VaInitialize(x_display, report_error_to_uma_cb)) {
+ return supported_profiles;
+ }
+
+ std::vector<VAProfile> va_profiles;
+ if (!wrapper->GetSupportedVaProfiles(&va_profiles))
+ return supported_profiles;
+
+ std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode);
+ for (size_t i = 0; i < arraysize(kProfileMap); i++) {
+ VAProfile va_profile =
+ ProfileToVAProfile(kProfileMap[i].profile, va_profiles);
+ if (va_profile != VAProfileNone &&
+ wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) &&
+ wrapper->AreAttribsSupported(
+ va_profile, VAEntrypointEncSlice, required_attribs)) {
+ supported_profiles.push_back(kProfileMap[i].profile);
+ }
+ }
+ return supported_profiles;
+}
+
void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
+ base::AutoLock auto_lock(va_lock_);
VADisplayAttribute item = {VADisplayAttribRenderMode,
1, // At least support '_LOCAL_OVERLAY'.
-1, // The maximum possible support 'ALL'.
@@ -134,12 +200,11 @@ void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
}
-bool VaapiWrapper::Initialize(media::VideoCodecProfile profile,
- Display* x_display,
- const base::Closure& report_error_to_uma_cb) {
+bool VaapiWrapper::VaInitialize(Display* x_display,
+ const base::Closure& report_error_to_uma_cb) {
static bool vaapi_functions_initialized = PostSandboxInitialization();
if (!vaapi_functions_initialized) {
- DVLOG(1) << "Failed to initialize VAAPI libs";
+ LOG(ERROR) << "Failed to initialize VAAPI libs";
return false;
}
@@ -149,7 +214,7 @@ bool VaapiWrapper::Initialize(media::VideoCodecProfile profile,
va_display_ = vaGetDisplay(x_display);
if (!vaDisplayIsValid(va_display_)) {
- DVLOG(1) << "Could not get a valid VA display";
+ LOG(ERROR) << "Could not get a valid VA display";
return false;
}
@@ -158,47 +223,120 @@ bool VaapiWrapper::Initialize(media::VideoCodecProfile profile,
DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
if (VAAPIVersionLessThan(0, 34)) {
- DVLOG(1) << "VAAPI version < 0.34 is not supported.";
+ LOG(ERROR) << "VAAPI version < 0.34 is not supported.";
return false;
}
+ return true;
+}
+bool VaapiWrapper::GetSupportedVaProfiles(std::vector<VAProfile>* profiles) {
+ base::AutoLock auto_lock(va_lock_);
// Query the driver for supported profiles.
int max_profiles = vaMaxNumProfiles(va_display_);
std::vector<VAProfile> supported_profiles(
base::checked_cast<size_t>(max_profiles));
int num_supported_profiles;
- va_res = vaQueryConfigProfiles(
+ VAStatus va_res = vaQueryConfigProfiles(
va_display_, &supported_profiles[0], &num_supported_profiles);
VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false);
if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) {
- DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles;
+ LOG(ERROR) << "vaQueryConfigProfiles returned: " << num_supported_profiles;
return false;
}
supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles));
+ *profiles = supported_profiles;
+ return true;
+}
- VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles);
- if (va_profile == VAProfileNone) {
- DVLOG(1) << "Unsupported profile";
+bool VaapiWrapper::IsEntrypointSupported(VAProfile va_profile,
+ VAEntrypoint entrypoint) {
+ base::AutoLock auto_lock(va_lock_);
+ // Query the driver for supported entrypoints.
+ int max_entrypoints = vaMaxNumEntrypoints(va_display_);
+ std::vector<VAEntrypoint> supported_entrypoints(
+ base::checked_cast<size_t>(max_entrypoints));
+
+ int num_supported_entrypoints;
+ VAStatus va_res = vaQueryConfigEntrypoints(va_display_,
+ va_profile,
+ &supported_entrypoints[0],
+ &num_supported_entrypoints);
+ VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false);
+ if (num_supported_entrypoints < 0 ||
+ num_supported_entrypoints > max_entrypoints) {
+ LOG(ERROR) << "vaQueryConfigEntrypoints returned: "
+ << num_supported_entrypoints;
return false;
}
- VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0};
- const VAEntrypoint kEntrypoint = VAEntrypointVLD;
- va_res = vaGetConfigAttributes(va_display_, va_profile, kEntrypoint,
- &attrib, 1);
+ if (std::find(supported_entrypoints.begin(),
+ supported_entrypoints.end(),
+ entrypoint) == supported_entrypoints.end()) {
+ DVLOG(1) << "Unsupported entrypoint";
+ return false;
+ }
+ return true;
+}
+
+bool VaapiWrapper::AreAttribsSupported(
+ VAProfile va_profile,
+ VAEntrypoint entrypoint,
+ const std::vector<VAConfigAttrib>& required_attribs) {
+ base::AutoLock auto_lock(va_lock_);
+ // Query the driver for required attributes.
+ std::vector<VAConfigAttrib> attribs = required_attribs;
+ for (size_t i = 0; i < required_attribs.size(); ++i)
+ attribs[i].value = 0;
+
+ VAStatus va_res = vaGetConfigAttributes(
+ va_display_, va_profile, entrypoint, &attribs[0], attribs.size());
VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
- if (!(attrib.value & VA_RT_FORMAT_YUV420)) {
- DVLOG(1) << "YUV420 not supported by this VAAPI implementation";
+ for (size_t i = 0; i < required_attribs.size(); ++i) {
+ if (attribs[i].type != required_attribs[i].type ||
+ (attribs[i].value & required_attribs[i].value) !=
+ required_attribs[i].value) {
+ DVLOG(1) << "Unsupported value " << required_attribs[i].value
+ << " for attribute type " << required_attribs[i].type;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool VaapiWrapper::Initialize(CodecMode mode,
+ media::VideoCodecProfile profile,
+ Display* x_display,
+ const base::Closure& report_error_to_uma_cb) {
+ if (!VaInitialize(x_display, report_error_to_uma_cb))
+ return false;
+ std::vector<VAProfile> supported_va_profiles;
+ if (!GetSupportedVaProfiles(&supported_va_profiles))
+ return false;
+ VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles);
+ if (va_profile == VAProfileNone) {
+ DVLOG(1) << "Unsupported profile";
return false;
}
+ VAEntrypoint entrypoint =
+ (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
+ if (!IsEntrypointSupported(va_profile, entrypoint))
+ return false;
+ std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode);
+ if (!AreAttribsSupported(va_profile, entrypoint, required_attribs))
+ return false;
TryToSetVADisplayAttributeToLocalGPU();
- va_res = vaCreateConfig(va_display_, va_profile, kEntrypoint,
- &attrib, 1, &va_config_id_);
+ base::AutoLock auto_lock(va_lock_);
+ VAStatus va_res = vaCreateConfig(va_display_,
+ va_profile,
+ entrypoint,
+ &required_attribs[0],
+ required_attribs.size(),
+ &va_config_id_);
VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
return true;
@@ -299,6 +437,7 @@ bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
switch (va_buffer_type) {
case VASliceParameterBufferType:
case VASliceDataBufferType:
+ case VAEncSliceParameterBufferType:
pending_slice_bufs_.push_back(buffer_id);
break;
@@ -310,6 +449,43 @@ bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type,
return true;
}
+bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
+ VAEncMiscParameterType misc_param_type,
+ size_t size,
+ void* buffer) {
+ base::AutoLock auto_lock(va_lock_);
+
+ VABufferID buffer_id;
+ VAStatus va_res = vaCreateBuffer(va_display_,
+ va_context_id_,
+ VAEncMiscParameterBufferType,
+ sizeof(VAEncMiscParameterBuffer) + size,
+ 1,
+ NULL,
+ &buffer_id);
+ VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
+
+ void* data_ptr = NULL;
+ va_res = vaMapBuffer(va_display_, buffer_id, &data_ptr);
+ VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
+ if (va_res != VA_STATUS_SUCCESS) {
+ vaDestroyBuffer(va_display_, buffer_id);
+ return false;
+ }
+
+ DCHECK(data_ptr);
+
+ VAEncMiscParameterBuffer* misc_param =
+ reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr);
+ misc_param->type = misc_param_type;
+ memcpy(misc_param->data, buffer, size);
+ va_res = vaUnmapBuffer(va_display_, buffer_id);
+ VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
+
+ pending_va_bufs_.push_back(buffer_id);
+ return true;
+}
+
void VaapiWrapper::DestroyPendingBuffers() {
base::AutoLock auto_lock(va_lock_);
@@ -327,38 +503,73 @@ void VaapiWrapper::DestroyPendingBuffers() {
pending_slice_bufs_.clear();
}
-bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_id) {
+bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) {
+ base::AutoLock auto_lock(va_lock_);
+ VAStatus va_res = vaCreateBuffer(va_display_,
+ va_context_id_,
+ VAEncCodedBufferType,
+ size,
+ 1,
+ NULL,
+ buffer_id);
+ VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false);
+
+ DCHECK(coded_buffers_.insert(*buffer_id).second);
+ return true;
+}
+
+void VaapiWrapper::DestroyCodedBuffers() {
+ base::AutoLock auto_lock(va_lock_);
+
+ for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin();
+ iter != coded_buffers_.end();
+ ++iter) {
+ VAStatus va_res = vaDestroyBuffer(va_display_, *iter);
+ VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
+ }
+
+ coded_buffers_.clear();
+}
+
+bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
base::AutoLock auto_lock(va_lock_);
DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
- DVLOG(4) << "Decoding into VA surface " << va_surface_id;
+ DVLOG(4) << "Target VA surface " << va_surface_id;
- // Get ready to decode into surface.
+ // Get ready to execute for given surface.
VAStatus va_res = vaBeginPicture(va_display_, va_context_id_,
va_surface_id);
VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
- // Commit parameter and slice buffers.
- va_res = vaRenderPicture(va_display_, va_context_id_,
- &pending_va_bufs_[0], pending_va_bufs_.size());
- VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
+ if (pending_va_bufs_.size() > 0) {
+ // Commit parameter and slice buffers.
+ va_res = vaRenderPicture(va_display_,
+ va_context_id_,
+ &pending_va_bufs_[0],
+ pending_va_bufs_.size());
+ VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
+ }
- va_res = vaRenderPicture(va_display_, va_context_id_,
- &pending_slice_bufs_[0],
- pending_slice_bufs_.size());
- VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
+ if (pending_slice_bufs_.size() > 0) {
+ va_res = vaRenderPicture(va_display_,
+ va_context_id_,
+ &pending_slice_bufs_[0],
+ pending_slice_bufs_.size());
+ VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
+ }
- // Instruct HW decoder to start processing committed buffers (decode this
- // picture). This does not block until the end of decode.
+ // Instruct HW codec to start processing committed buffers.
+ // Does not block and the job is not finished after this returns.
va_res = vaEndPicture(va_display_, va_context_id_);
VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false);
return true;
}
-bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
- bool result = SubmitDecode(va_surface_id);
+bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
+ bool result = Execute(va_surface_id);
DestroyPendingBuffers();
return result;
}
@@ -378,8 +589,7 @@ bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
0, 0, dest_size.width(), dest_size.height(),
0, 0, dest_size.width(), dest_size.height(),
NULL, 0, 0);
- VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap",
- false);
+ VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false);
return true;
}
@@ -403,15 +613,124 @@ bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
if (va_res == VA_STATUS_SUCCESS)
return true;
- vaDestroyImage(va_display_, image->image_id);
+ va_res = vaDestroyImage(va_display_, image->image_id);
+ VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
+
return false;
}
void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) {
base::AutoLock auto_lock(va_lock_);
- vaUnmapBuffer(va_display_, image->buf);
- vaDestroyImage(va_display_, image->image_id);
+ VAStatus va_res = vaUnmapBuffer(va_display_, image->buf);
+ VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
+
+ va_res = vaDestroyImage(va_display_, image->image_id);
+ VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
+}
+
+static void DestroyVAImage(VADisplay va_display, VAImage image) {
+ if (image.image_id != VA_INVALID_ID)
+ vaDestroyImage(va_display, image.image_id);
+}
+
+bool VaapiWrapper::UploadVideoFrameToSurface(
+ const scoped_refptr<media::VideoFrame>& frame,
+ VASurfaceID va_surface_id) {
+ base::AutoLock auto_lock(va_lock_);
+
+ VAImage image;
+ VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image);
+ VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false);
+ base::ScopedClosureRunner vaimage_deleter(
+ base::Bind(&DestroyVAImage, va_display_, image));
+
+ if (image.format.fourcc != VA_FOURCC_NV12) {
+ LOG(ERROR) << "Unsupported image format: " << image.format.fourcc;
+ return false;
+ }
+
+ if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) {
+ LOG(ERROR) << "Buffer too small to fit the frame.";
+ return false;
+ }
+
+ void* image_ptr = NULL;
+ va_res = vaMapBuffer(va_display_, image.buf, &image_ptr);
+ VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
+ DCHECK(image_ptr);
+
+ int ret = 0;
+ {
+ base::AutoUnlock auto_unlock(va_lock_);
+ ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane),
+ frame->stride(media::VideoFrame::kYPlane),
+ frame->data(media::VideoFrame::kUPlane),
+ frame->stride(media::VideoFrame::kUPlane),
+ frame->data(media::VideoFrame::kVPlane),
+ frame->stride(media::VideoFrame::kVPlane),
+ static_cast<uint8*>(image_ptr) + image.offsets[0],
+ image.pitches[0],
+ static_cast<uint8*>(image_ptr) + image.offsets[1],
+ image.pitches[1],
+ image.width,
+ image.height);
+ }
+
+ va_res = vaUnmapBuffer(va_display_, image.buf);
+ VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
+
+ return ret == 0;
+}
+
+bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
+ VASurfaceID sync_surface_id,
+ uint8* target_ptr,
+ size_t target_size,
+ size_t* coded_data_size) {
+ base::AutoLock auto_lock(va_lock_);
+
+ VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id);
+ VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
+
+ VACodedBufferSegment* buffer_segment = NULL;
+ va_res = vaMapBuffer(
+ va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment));
+ VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
+ DCHECK(target_ptr);
+
+ {
+ base::AutoUnlock auto_unlock(va_lock_);
+ *coded_data_size = 0;
+
+ while (buffer_segment) {
+ DCHECK(buffer_segment->buf);
+
+ if (buffer_segment->size > target_size) {
+ LOG(ERROR) << "Insufficient output buffer size";
+ break;
+ }
+
+ memcpy(target_ptr, buffer_segment->buf, buffer_segment->size);
+
+ target_ptr += buffer_segment->size;
+ *coded_data_size += buffer_segment->size;
+ target_size -= buffer_segment->size;
+
+ buffer_segment =
+ reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next);
+ }
+ }
+
+ va_res = vaUnmapBuffer(va_display_, buffer_id);
+ VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
+
+ va_res = vaDestroyBuffer(va_display_, buffer_id);
+ VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
+
+ DCHECK(coded_buffers_.erase(buffer_id));
+
+ return buffer_segment == NULL;
}
// static
diff --git a/chromium/content/common/gpu/media/vaapi_wrapper.h b/chromium/content/common/gpu/media/vaapi_wrapper.h
index 5570360ecd1..39906a0f405 100644
--- a/chromium/content/common/gpu/media/vaapi_wrapper.h
+++ b/chromium/content/common/gpu/media/vaapi_wrapper.h
@@ -3,12 +3,16 @@
// found in the LICENSE file.
//
// This file contains an implementation of VaapiWrapper, used by
-// VaapiVideoDecodeAccelerator and VaapiH264Decoder to interface
-// with libva (VA-API library for hardware video decode).
+// VaapiVideoDecodeAccelerator and VaapiH264Decoder for decode,
+// and VaapiVideoEncodeAccelerator for encode, to interface
+// with libva (VA-API library for hardware video codec).
#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_
#define CONTENT_COMMON_GPU_MEDIA_VAAPI_WRAPPER_H_
+#include <set>
+#include <vector>
+
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
@@ -22,24 +26,35 @@
namespace content {
// This class handles VA-API calls and ensures proper locking of VA-API calls
-// to libva, the userspace shim to the HW decoder driver. libva is not
+// to libva, the userspace shim to the HW codec driver. libva is not
// thread-safe, so we have to perform locking ourselves. This class is fully
// synchronous and its methods can be called from any thread and may wait on
// the va_lock_ while other, concurrent calls run.
//
// This class is responsible for managing VAAPI connection, contexts and state.
// It is also responsible for managing and freeing VABuffers (not VASurfaces),
-// which are used to queue decode parameters and slice data to the HW decoder,
+// which are used to queue parameters and slice data to the HW codec,
// as well as underlying memory for VASurfaces themselves.
class CONTENT_EXPORT VaapiWrapper {
public:
+ enum CodecMode {
+ kDecode,
+ kEncode,
+ };
+
// |report_error_to_uma_cb| will be called independently from reporting
// errors to clients via method return values.
static scoped_ptr<VaapiWrapper> Create(
+ CodecMode mode,
media::VideoCodecProfile profile,
Display* x_display,
const base::Closure& report_error_to_uma_cb);
+ // Return the supported encode profiles.
+ static std::vector<media::VideoCodecProfile> GetSupportedEncodeProfiles(
+ Display* x_display,
+ const base::Closure& report_error_to_uma_cb);
+
~VaapiWrapper();
// Create |num_surfaces| backing surfaces in driver for VASurfaces, each
@@ -57,20 +72,30 @@ class CONTENT_EXPORT VaapiWrapper {
void DestroySurfaces();
// Submit parameters or slice data of |va_buffer_type|, copying them from
- // |buffer| of size |size|, into HW decoder. The data in |buffer| is no
+ // |buffer| of size |size|, into HW codec. The data in |buffer| is no
// longer needed and can be freed after this method returns.
- // Data submitted via this method awaits in the HW decoder until
- // DecodeAndDestroyPendingBuffers is called to execute or
- // DestroyPendingBuffers is used to cancel a pending decode.
+ // Data submitted via this method awaits in the HW codec until
+ // ExecuteAndDestroyPendingBuffers() is called to execute or
+ // DestroyPendingBuffers() is used to cancel a pending job.
bool SubmitBuffer(VABufferType va_buffer_type, size_t size, void* buffer);
- // Cancel and destroy all buffers queued to the HW decoder via SubmitBuffer.
- // Useful when a pending decode is to be cancelled (on reset or error).
+ // Submit a VAEncMiscParameterBuffer of given |misc_param_type|, copying its
+ // data from |buffer| of size |size|, into HW codec. The data in |buffer| is
+ // no longer needed and can be freed after this method returns.
+ // Data submitted via this method awaits in the HW codec until
+ // ExecuteAndDestroyPendingBuffers() is called to execute or
+ // DestroyPendingBuffers() is used to cancel a pending job.
+ bool SubmitVAEncMiscParamBuffer(VAEncMiscParameterType misc_param_type,
+ size_t size,
+ void* buffer);
+
+ // Cancel and destroy all buffers queued to the HW codec via SubmitBuffer().
+ // Useful when a pending job is to be cancelled (on reset or error).
void DestroyPendingBuffers();
- // Execute decode in hardware into |va_surface_id} and destroy pending
- // buffers. Return false if SubmitDecode() fails.
- bool DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id);
+ // Execute job in hardware on target |va_surface_id| and destroy pending
+ // buffers. Return false if Execute() fails.
+ bool ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id);
// Put data from |va_surface_id| into |x_pixmap| of size |size|,
// converting/scaling to it.
@@ -92,18 +117,48 @@ class CONTENT_EXPORT VaapiWrapper {
// GetVaImage(). This is intended for testing only.
void ReturnVaImageForTesting(VAImage* image);
+ // Upload contents of |frame| into |va_surface_id| for encode.
+ bool UploadVideoFrameToSurface(const scoped_refptr<media::VideoFrame>& frame,
+ VASurfaceID va_surface_id);
+
+ // Create a buffer of |size| bytes to be used as encode output.
+ bool CreateCodedBuffer(size_t size, VABufferID* buffer_id);
+
+ // Download the contents of the buffer with given |buffer_id| into a buffer of
+ // size |target_size|, pointed to by |target_ptr|. The number of bytes
+ // downloaded will be returned in |coded_data_size|. |sync_surface_id| will
+ // be used as a sync point, i.e. it will have to become idle before starting
+ // the download. |sync_surface_id| should be the source surface passed
+ // to the encode job.
+ bool DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
+ VASurfaceID sync_surface_id,
+ uint8* target_ptr,
+ size_t target_size,
+ size_t* coded_data_size);
+
+ // Destroy all previously-allocated (and not yet destroyed) coded buffers.
+ void DestroyCodedBuffers();
+
private:
VaapiWrapper();
- bool Initialize(media::VideoCodecProfile profile,
+ bool Initialize(CodecMode mode,
+ media::VideoCodecProfile profile,
Display* x_display,
- const base::Closure& report_error__to_uma_cb);
+ const base::Closure& report_error_to_uma_cb);
void Deinitialize();
-
- // Execute decode in hardware and destroy pending buffers. Return false if
- // vaapi driver refuses to accept parameter or slice buffers submitted
- // by client or if decode fails in hardware.
- bool SubmitDecode(VASurfaceID va_surface_id);
+ bool VaInitialize(Display* x_display,
+ const base::Closure& report_error_to_uma_cb);
+ bool GetSupportedVaProfiles(std::vector<VAProfile>* profiles);
+ bool IsEntrypointSupported(VAProfile va_profile, VAEntrypoint entrypoint);
+ bool AreAttribsSupported(VAProfile va_profile,
+ VAEntrypoint entrypoint,
+ const std::vector<VAConfigAttrib>& required_attribs);
+
+ // Execute pending job in hardware and destroy pending buffers. Return false
+ // if vaapi driver refuses to accept parameter or slice buffers submitted
+ // by client, or if execution fails in hardware.
+ bool Execute(VASurfaceID va_surface_id);
// Attempt to set render mode to "render to texture.". Failure is non-fatal.
void TryToSetVADisplayAttributeToLocalGPU();
@@ -114,7 +169,7 @@ class CONTENT_EXPORT VaapiWrapper {
// Libva is not thread safe, so we have to do locking for it ourselves.
// This lock is to be taken for the duration of all VA-API calls and for
- // the entire decode execution sequence in DecodeAndDestroyPendingBuffers().
+ // the entire job submission sequence in ExecuteAndDestroyPendingBuffers().
base::Lock va_lock_;
// Allocated ids for VASurfaces.
@@ -131,11 +186,14 @@ class CONTENT_EXPORT VaapiWrapper {
// valid until DestroySurfaces().
VAContextID va_context_id_;
- // Data queued up for HW decoder, to be committed on next HW decode.
+ // Data queued up for HW codec, to be committed on next execution.
std::vector<VABufferID> pending_slice_bufs_;
std::vector<VABufferID> pending_va_bufs_;
- // Called to report decoding errors to UMA. Errors to clients are reported via
+ // Bitstream buffers for encode.
+ std::set<VABufferID> coded_buffers_;
+
+ // Called to report codec errors to UMA. Errors to clients are reported via
// return values from public methods.
base::Closure report_error_to_uma_cb_;
diff --git a/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc b/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 58e0e99a980..8b89d049b93 100644
--- a/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -30,12 +30,12 @@
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file.h"
+#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/md5.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -101,6 +101,9 @@ const base::FilePath::CharType* g_output_log = NULL;
// The value is set by the switch "--rendering_fps".
double g_rendering_fps = 60;
+// The value is set by the switch "--rendering_warm_up".
+int g_rendering_warm_up = 0;
+
// Magic constants for differentiating the reasons for NotifyResetDone being
// called.
enum ResetPoint {
@@ -193,9 +196,10 @@ enum ClientState {
// the TESTs below.
class GLRenderingVDAClient
: public VideoDecodeAccelerator::Client,
- public RenderingHelper::Client,
public base::SupportsWeakPtr<GLRenderingVDAClient> {
public:
+ // |window_id| the window_id of the client, which is used to identify the
+ // rendering area in the |rendering_helper|.
// Doesn't take ownership of |rendering_helper| or |note|, which must outlive
// |*this|.
// |num_play_throughs| indicates how many times to play through the video.
@@ -212,7 +216,8 @@ class GLRenderingVDAClient
// will start delaying the call to ReusePictureBuffer() for kReuseDelay.
// |decode_calls_per_second| is the number of VDA::Decode calls per second.
// If |decode_calls_per_second| > 0, |num_in_flight_decodes| must be 1.
- GLRenderingVDAClient(RenderingHelper* rendering_helper,
+ GLRenderingVDAClient(size_t window_id,
+ RenderingHelper* rendering_helper,
ClientStateNotification<ClientState>* note,
const std::string& encoded_data,
int num_in_flight_decodes,
@@ -233,23 +238,17 @@ class GLRenderingVDAClient
// The heart of the Client.
virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
const gfx::Size& dimensions,
- uint32 texture_target) OVERRIDE;
- virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void PictureReady(const media::Picture& picture) OVERRIDE;
+ uint32 texture_target) override;
+ virtual void DismissPictureBuffer(int32 picture_buffer_id) override;
+ virtual void PictureReady(const media::Picture& picture) override;
// Simple state changes.
- virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE;
- virtual void NotifyFlushDone() OVERRIDE;
- virtual void NotifyResetDone() OVERRIDE;
- virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE;
-
- // RenderingHelper::Client implementation.
- virtual void RenderContent(RenderingHelper*) OVERRIDE;
- virtual const gfx::Size& GetWindowSize() OVERRIDE;
+ virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) override;
+ virtual void NotifyFlushDone() override;
+ virtual void NotifyResetDone() override;
+ virtual void NotifyError(VideoDecodeAccelerator::Error error) override;
void OutputFrameDeliveryTimes(base::File* output);
- void NotifyFrameDropped(int32 picture_buffer_id);
-
// Simple getters for inspecting the state of the Client.
int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; }
int num_skipped_fragments() { return num_skipped_fragments_; }
@@ -285,6 +284,7 @@ class GLRenderingVDAClient
// Request decode of the next fragment in the encoded data.
void DecodeNextFragment();
+ size_t window_id_;
RenderingHelper* rendering_helper_;
gfx::Size frame_size_;
std::string encoded_data_;
@@ -319,13 +319,16 @@ class GLRenderingVDAClient
// The number of VDA::Decode calls per second. This is to simulate webrtc.
int decode_calls_per_second_;
bool render_as_thumbnails_;
- bool pending_picture_updated_;
- std::deque<int32> pending_picture_buffer_ids_;
+ // The number of frames that are not returned from rendering_helper_. We
+ // checks this count to ensure all frames are rendered before entering the
+ // CS_RESET state.
+ int frames_at_render_;
DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient);
};
GLRenderingVDAClient::GLRenderingVDAClient(
+ size_t window_id,
RenderingHelper* rendering_helper,
ClientStateNotification<ClientState>* note,
const std::string& encoded_data,
@@ -340,7 +343,8 @@ GLRenderingVDAClient::GLRenderingVDAClient(
int delay_reuse_after_frame_num,
int decode_calls_per_second,
bool render_as_thumbnails)
- : rendering_helper_(rendering_helper),
+ : window_id_(window_id),
+ rendering_helper_(rendering_helper),
frame_size_(frame_width, frame_height),
encoded_data_(encoded_data),
num_in_flight_decodes_(num_in_flight_decodes),
@@ -361,7 +365,7 @@ GLRenderingVDAClient::GLRenderingVDAClient(
delay_reuse_after_frame_num_(delay_reuse_after_frame_num),
decode_calls_per_second_(decode_calls_per_second),
render_as_thumbnails_(render_as_thumbnails),
- pending_picture_updated_(true) {
+ frames_at_render_(0) {
CHECK_GT(num_in_flight_decodes, 0);
CHECK_GT(num_play_throughs, 0);
// |num_in_flight_decodes_| is unsupported if |decode_calls_per_second_| > 0.
@@ -459,42 +463,6 @@ void GLRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) {
picture_buffers_by_id_.erase(it);
}
-void GLRenderingVDAClient::RenderContent(RenderingHelper*) {
- CHECK(!render_as_thumbnails_);
-
- // No decoded texture for rendering yet, just skip.
- if (pending_picture_buffer_ids_.size() == 0)
- return;
-
- int32 buffer_id = pending_picture_buffer_ids_.front();
- media::PictureBuffer* picture_buffer = picture_buffers_by_id_[buffer_id];
-
- CHECK(picture_buffer);
- if (!pending_picture_updated_) {
- // Frame dropped, just redraw the last texture.
- rendering_helper_->RenderTexture(texture_target_,
- picture_buffer->texture_id());
- return;
- }
-
- base::TimeTicks now = base::TimeTicks::Now();
- frame_delivery_times_.push_back(now);
-
- rendering_helper_->RenderTexture(texture_target_,
- picture_buffer->texture_id());
-
- if (pending_picture_buffer_ids_.size() == 1) {
- pending_picture_updated_ = false;
- } else {
- pending_picture_buffer_ids_.pop_front();
- ReturnPicture(buffer_id);
- }
-}
-
-const gfx::Size& GLRenderingVDAClient::GetWindowSize() {
- return render_as_thumbnails_ ? kThumbnailsPageSize : frame_size_;
-}
-
void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
// We shouldn't be getting pictures delivered after Reset has completed.
CHECK_LT(state_, CS_RESET);
@@ -503,6 +471,9 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
return;
base::TimeTicks now = base::TimeTicks::Now();
+
+ frame_delivery_times_.push_back(now);
+
// Save the decode time of this picture.
std::map<int, base::TimeTicks>::iterator it =
decode_start_time_.find(picture.bitstream_buffer_id());
@@ -524,31 +495,37 @@ void GLRenderingVDAClient::PictureReady(const media::Picture& picture) {
encoded_data_next_pos_to_decode_ = 0;
}
+ media::PictureBuffer* picture_buffer =
+ picture_buffers_by_id_[picture.picture_buffer_id()];
+ CHECK(picture_buffer);
+
+ scoped_refptr<VideoFrameTexture> video_frame =
+ new VideoFrameTexture(texture_target_,
+ picture_buffer->texture_id(),
+ base::Bind(&GLRenderingVDAClient::ReturnPicture,
+ AsWeakPtr(),
+ picture.picture_buffer_id()));
+ ++frames_at_render_;
+
if (render_as_thumbnails_) {
- frame_delivery_times_.push_back(now);
- media::PictureBuffer* picture_buffer =
- picture_buffers_by_id_[picture.picture_buffer_id()];
- CHECK(picture_buffer);
- rendering_helper_->RenderThumbnail(texture_target_,
- picture_buffer->texture_id());
- ReturnPicture(picture.picture_buffer_id());
+ rendering_helper_->RenderThumbnail(video_frame->texture_target(),
+ video_frame->texture_id());
} else if (!suppress_rendering_) {
- // Keep the picture for rendering.
- pending_picture_buffer_ids_.push_back(picture.picture_buffer_id());
- if (pending_picture_buffer_ids_.size() > 1 && !pending_picture_updated_) {
- ReturnPicture(pending_picture_buffer_ids_.front());
- pending_picture_buffer_ids_.pop_front();
- pending_picture_updated_ = true;
- }
- } else {
- frame_delivery_times_.push_back(now);
- ReturnPicture(picture.picture_buffer_id());
+ rendering_helper_->QueueVideoFrame(window_id_, video_frame);
}
}
void GLRenderingVDAClient::ReturnPicture(int32 picture_buffer_id) {
if (decoder_deleted())
return;
+
+ --frames_at_render_;
+ if (frames_at_render_ == 0 && state_ == CS_RESETTING) {
+ SetState(CS_RESET);
+ DeleteDecoder();
+ return;
+ }
+
if (num_decoded_frames_ > delay_reuse_after_frame_num_) {
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
@@ -590,13 +567,6 @@ void GLRenderingVDAClient::NotifyResetDone() {
if (decoder_deleted())
return;
- // Clear pending_pictures and reuse them.
- while (!pending_picture_buffer_ids_.empty()) {
- decoder_->ReusePictureBuffer(pending_picture_buffer_ids_.front());
- pending_picture_buffer_ids_.pop_front();
- }
- pending_picture_updated_ = true;
-
if (reset_after_frame_num_ == MID_STREAM_RESET) {
reset_after_frame_num_ = END_OF_STREAM_RESET;
DecodeNextFragment();
@@ -614,9 +584,12 @@ void GLRenderingVDAClient::NotifyResetDone() {
return;
}
- SetState(CS_RESET);
- if (!decoder_deleted())
+ rendering_helper_->Flush(window_id_);
+
+ if (frames_at_render_ == 0) {
+ SetState(CS_RESET);
DeleteDecoder();
+ }
}
void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) {
@@ -637,10 +610,6 @@ void GLRenderingVDAClient::OutputFrameDeliveryTimes(base::File* output) {
}
}
-void GLRenderingVDAClient::NotifyFrameDropped(int32 picture_buffer_id) {
- decoder_->ReusePictureBuffer(picture_buffer_id);
-}
-
static bool LookingAtNAL(const std::string& encoded, size_t pos) {
return encoded[pos] == 0 && encoded[pos + 1] == 0 &&
encoded[pos + 2] == 0 && encoded[pos + 3] == 1;
@@ -809,7 +778,7 @@ void GLRenderingVDAClient::DecodeNextFragment() {
CHECK(shm.CreateAndMapAnonymous(next_fragment_size));
memcpy(shm.memory(), next_fragment_bytes.data(), next_fragment_size);
base::SharedMemoryHandle dup_handle;
- CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle));
+ CHECK(shm.ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle));
media::BitstreamBuffer bitstream_buffer(
next_bitstream_buffer_id_, dup_handle, next_fragment_size);
decode_start_time_[next_bitstream_buffer_id_] = base::TimeTicks::Now();
@@ -1104,6 +1073,7 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
RenderingHelperParams helper_params;
helper_params.rendering_fps = g_rendering_fps;
+ helper_params.warm_up_iterations = g_rendering_warm_up;
helper_params.render_as_thumbnails = render_as_thumbnails;
if (render_as_thumbnails) {
// Only one decoder is supported with thumbnail rendering
@@ -1127,7 +1097,8 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
}
GLRenderingVDAClient* client =
- new GLRenderingVDAClient(&rendering_helper_,
+ new GLRenderingVDAClient(index,
+ &rendering_helper_,
note,
video_file->data_str,
num_in_flight_decodes,
@@ -1143,7 +1114,10 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) {
render_as_thumbnails);
clients[index] = client;
- helper_params.clients.push_back(client->AsWeakPtr());
+ helper_params.window_sizes.push_back(
+ render_as_thumbnails
+ ? kThumbnailsPageSize
+ : gfx::Size(video_file->width, video_file->height));
}
InitializeRenderingHelper(helper_params);
@@ -1371,12 +1345,14 @@ TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) {
// Disable rendering by setting the rendering_fps = 0.
helper_params.rendering_fps = 0;
+ helper_params.warm_up_iterations = 0;
helper_params.render_as_thumbnails = false;
ClientStateNotification<ClientState>* note =
new ClientStateNotification<ClientState>();
GLRenderingVDAClient* client =
- new GLRenderingVDAClient(&rendering_helper_,
+ new GLRenderingVDAClient(0,
+ &rendering_helper_,
note,
test_video_files_[0]->data_str,
1,
@@ -1390,7 +1366,8 @@ TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) {
std::numeric_limits<int>::max(),
kWebRtcDecodeCallsPerSecond,
false /* render_as_thumbnail */);
- helper_params.clients.push_back(client->AsWeakPtr());
+ helper_params.window_sizes.push_back(
+ gfx::Size(test_video_files_[0]->width, test_video_files_[0]->height));
InitializeRenderingHelper(helper_params);
CreateAndStartDecoder(client, note);
WaitUntilDecodeFinish(note);
@@ -1420,17 +1397,17 @@ TEST_F(VideoDecodeAcceleratorTest, TestDecodeTimeMedian) {
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args.
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
// Needed to enable DVLOG through --vmodule.
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
CHECK(logging::InitLogging(settings));
- CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
DCHECK(cmd_line);
- CommandLine::SwitchMap switches = cmd_line->GetSwitches();
+ base::CommandLine::SwitchMap switches = cmd_line->GetSwitches();
for (CommandLine::SwitchMap::const_iterator it = switches.begin();
it != switches.end(); ++it) {
if (it->first == "test_video_data") {
@@ -1449,6 +1426,11 @@ int main(int argc, char **argv) {
CHECK(base::StringToDouble(input, &content::g_rendering_fps));
continue;
}
+ if (it->first == "rendering_warm_up") {
+ std::string input(it->second.begin(), it->second.end());
+ CHECK(base::StringToInt(input, &content::g_rendering_warm_up));
+ continue;
+ }
// TODO(owenlin): Remove this flag once it is not used in autotest.
if (it->first == "disable_rendering") {
content::g_rendering_fps = 0;
@@ -1460,6 +1442,7 @@ int main(int argc, char **argv) {
}
base::ShadowingAtExitManager at_exit_manager;
+ content::RenderingHelper::InitializeOneOff();
return RUN_ALL_TESTS();
}
diff --git a/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc b/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc
index 5f606343dd4..b1fb5922666 100644
--- a/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -5,15 +5,14 @@
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/scoped_vector.h"
#include "base/numerics/safe_conversions.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/time/time.h"
-#include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
#include "content/common/gpu/media/video_accelerator_unittest_helpers.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/bitstream_buffer.h"
@@ -22,6 +21,18 @@
#include "media/video/video_encode_accelerator.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(USE_X11)
+#include "ui/gfx/x/x11_types.h"
+#endif
+
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
+#include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
+#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
+#include "content/common/gpu/media/vaapi_video_encode_accelerator.h"
+#else
+#error The VideoEncodeAcceleratorUnittest is not supported on this platform.
+#endif
+
using media::VideoEncodeAccelerator;
namespace content {
@@ -81,26 +92,171 @@ const unsigned int kMinFramesForBitrateTests = 300;
// Bitrate is only forced for tests that test bitrate.
const char* g_default_in_filename = "bear_320x192_40frames.yuv";
const char* g_default_in_parameters = ":320:192:1:out.h264:200000";
-base::FilePath::StringType* g_test_stream_data;
+// Environment to store test stream data for all test cases.
+class VideoEncodeAcceleratorTestEnvironment;
+VideoEncodeAcceleratorTestEnvironment* g_env;
struct TestStream {
TestStream()
- : requested_bitrate(0),
+ : num_frames(0),
+ aligned_buffer_size(0),
+ requested_bitrate(0),
requested_framerate(0),
requested_subsequent_bitrate(0),
requested_subsequent_framerate(0) {}
~TestStream() {}
- gfx::Size size;
- base::MemoryMappedFile input_file;
- media::VideoCodecProfile requested_profile;
+ gfx::Size visible_size;
+ gfx::Size coded_size;
+ unsigned int num_frames;
+
+ // Original unaligned input file name provided as an argument to the test.
+ // And the file must be an I420 (YUV planar) raw stream.
+ std::string in_filename;
+
+ // A temporary file used to prepare aligned input buffers of |in_filename|.
+ // The file makes sure starting address of YUV planes are 64 byte-aligned.
+ base::FilePath aligned_in_file;
+
+ // The memory mapping of |aligned_in_file|
+ base::MemoryMappedFile mapped_aligned_in_file;
+
+ // Byte size of a frame of |aligned_in_file|.
+ size_t aligned_buffer_size;
+
+ // Byte size for each aligned plane of a frame
+ std::vector<size_t> aligned_plane_size;
+
std::string out_filename;
+ media::VideoCodecProfile requested_profile;
unsigned int requested_bitrate;
unsigned int requested_framerate;
unsigned int requested_subsequent_bitrate;
unsigned int requested_subsequent_framerate;
};
+inline static size_t Align64Bytes(size_t value) {
+ return (value + 63) & ~63;
+}
+
+// Write |data| of |size| bytes at |offset| bytes into |file|.
+static bool WriteFile(base::File* file,
+ const off_t offset,
+ const uint8* data,
+ size_t size) {
+ size_t written_bytes = 0;
+ while (written_bytes < size) {
+ int bytes = file->Write(offset + written_bytes,
+ reinterpret_cast<const char*>(data + written_bytes),
+ size - written_bytes);
+ if (bytes <= 0)
+ return false;
+ written_bytes += bytes;
+ }
+ return true;
+}
+
+// ARM performs CPU cache management with CPU cache line granularity. We thus
+// need to ensure our buffers are CPU cache line-aligned (64 byte-aligned).
+// Otherwise newer kernels will refuse to accept them, and on older kernels
+// we'll be treating ourselves to random corruption.
+// Since we are just mapping and passing chunks of the input file directly to
+// the VEA as input frames to avoid copying large chunks of raw data on each
+// frame and thus affecting performance measurements, we have to prepare a
+// temporary file with all planes aligned to 64-byte boundaries beforehand.
+static void CreateAlignedInputStreamFile(const gfx::Size& coded_size,
+ TestStream* test_stream) {
+ // Test case may have many encoders and memory should be prepared once.
+ if (test_stream->coded_size == coded_size &&
+ test_stream->mapped_aligned_in_file.IsValid())
+ return;
+
+ // All encoders in multiple encoder test reuse the same test_stream, make
+ // sure they requested the same coded_size
+ ASSERT_TRUE(!test_stream->mapped_aligned_in_file.IsValid() ||
+ coded_size == test_stream->coded_size);
+ test_stream->coded_size = coded_size;
+
+ size_t num_planes = media::VideoFrame::NumPlanes(kInputFormat);
+ std::vector<size_t> padding_sizes(num_planes);
+ std::vector<size_t> coded_bpl(num_planes);
+ std::vector<size_t> visible_bpl(num_planes);
+ std::vector<size_t> visible_plane_rows(num_planes);
+
+ // Calculate padding in bytes to be added after each plane required to keep
+ // starting addresses of all planes at a 64 byte boudnary. This padding will
+ // be added after each plane when copying to the temporary file.
+ // At the same time we also need to take into account coded_size requested by
+ // the VEA; each row of visible_bpl bytes in the original file needs to be
+ // copied into a row of coded_bpl bytes in the aligned file.
+ for (size_t i = 0; i < num_planes; i++) {
+ size_t size =
+ media::VideoFrame::PlaneAllocationSize(kInputFormat, i, coded_size);
+ test_stream->aligned_plane_size.push_back(Align64Bytes(size));
+ test_stream->aligned_buffer_size += test_stream->aligned_plane_size.back();
+
+ coded_bpl[i] =
+ media::VideoFrame::RowBytes(i, kInputFormat, coded_size.width());
+ visible_bpl[i] = media::VideoFrame::RowBytes(
+ i, kInputFormat, test_stream->visible_size.width());
+ visible_plane_rows[i] = media::VideoFrame::Rows(
+ i, kInputFormat, test_stream->visible_size.height());
+ size_t padding_rows =
+ media::VideoFrame::Rows(i, kInputFormat, coded_size.height()) -
+ visible_plane_rows[i];
+ padding_sizes[i] = padding_rows * coded_bpl[i] + Align64Bytes(size) - size;
+ }
+
+ base::MemoryMappedFile src_file;
+ CHECK(src_file.Initialize(base::FilePath(test_stream->in_filename)));
+ CHECK(base::CreateTemporaryFile(&test_stream->aligned_in_file));
+
+ size_t visible_buffer_size = media::VideoFrame::AllocationSize(
+ kInputFormat, test_stream->visible_size);
+ CHECK_EQ(src_file.length() % visible_buffer_size, 0U)
+ << "Stream byte size is not a product of calculated frame byte size";
+
+ test_stream->num_frames = src_file.length() / visible_buffer_size;
+ uint32 flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
+ base::File::FLAG_READ;
+
+ // Create a temporary file with coded_size length.
+ base::File dest_file(test_stream->aligned_in_file, flags);
+ CHECK_GT(test_stream->aligned_buffer_size, 0UL);
+ dest_file.SetLength(test_stream->aligned_buffer_size *
+ test_stream->num_frames);
+
+ const uint8* src = src_file.data();
+ off_t dest_offset = 0;
+ for (size_t frame = 0; frame < test_stream->num_frames; frame++) {
+ for (size_t i = 0; i < num_planes; i++) {
+ // Assert that each plane of frame starts at 64 byte boundary.
+ ASSERT_EQ(dest_offset & 63, 0)
+ << "Planes of frame should be mapped at a 64 byte boundary";
+ for (size_t j = 0; j < visible_plane_rows[i]; j++) {
+ CHECK(WriteFile(&dest_file, dest_offset, src, visible_bpl[i]));
+ src += visible_bpl[i];
+ dest_offset += coded_bpl[i];
+ }
+ dest_offset += padding_sizes[i];
+ }
+ }
+ CHECK(test_stream->mapped_aligned_in_file.Initialize(dest_file.Pass()));
+ // Assert that memory mapped of file starts at 64 byte boundary. So each
+ // plane of frames also start at 64 byte boundary.
+ ASSERT_EQ(
+ reinterpret_cast<off_t>(test_stream->mapped_aligned_in_file.data()) & 63,
+ 0)
+ << "File should be mapped at a 64 byte boundary";
+
+ CHECK_EQ(test_stream->mapped_aligned_in_file.length() %
+ test_stream->aligned_buffer_size,
+ 0U)
+ << "Stream byte size is not a product of calculated frame byte size";
+ CHECK_GT(test_stream->num_frames, 0UL);
+ CHECK_LE(test_stream->num_frames, kMaxFrameNum);
+}
+
// Parse |data| into its constituent parts, set the various output fields
// accordingly, read in video stream, and store them to |test_streams|.
static void ParseAndReadTestStreamData(const base::FilePath::StringType& data,
@@ -118,12 +274,12 @@ static void ParseAndReadTestStreamData(const base::FilePath::StringType& data,
CHECK_LE(fields.size(), 9U) << data;
TestStream* test_stream = new TestStream();
- base::FilePath::StringType filename = fields[0];
+ test_stream->in_filename = fields[0];
int width, height;
CHECK(base::StringToInt(fields[1], &width));
CHECK(base::StringToInt(fields[2], &height));
- test_stream->size = gfx::Size(width, height);
- CHECK(!test_stream->size.IsEmpty());
+ test_stream->visible_size = gfx::Size(width, height);
+ CHECK(!test_stream->visible_size.IsEmpty());
int profile;
CHECK(base::StringToInt(fields[3], &profile));
CHECK_GT(profile, media::VIDEO_CODEC_PROFILE_UNKNOWN);
@@ -149,56 +305,10 @@ static void ParseAndReadTestStreamData(const base::FilePath::StringType& data,
CHECK(base::StringToUint(fields[8],
&test_stream->requested_subsequent_framerate));
}
-
- CHECK(test_stream->input_file.Initialize(base::FilePath(filename)));
test_streams->push_back(test_stream);
}
}
-// Set default parameters of |test_streams| and update the parameters according
-// to |mid_stream_bitrate_switch| and |mid_stream_framerate_switch|.
-static void UpdateTestStreamData(bool mid_stream_bitrate_switch,
- bool mid_stream_framerate_switch,
- ScopedVector<TestStream>* test_streams) {
- for (size_t i = 0; i < test_streams->size(); i++) {
- TestStream* test_stream = (*test_streams)[i];
- // Use defaults for bitrate/framerate if they are not provided.
- if (test_stream->requested_bitrate == 0)
- test_stream->requested_bitrate = kDefaultBitrate;
-
- if (test_stream->requested_framerate == 0)
- test_stream->requested_framerate = kDefaultFramerate;
-
- // If bitrate/framerate switch is requested, use the subsequent values if
- // provided, or, if not, calculate them from their initial values using
- // the default ratios.
- // Otherwise, if a switch is not requested, keep the initial values.
- if (mid_stream_bitrate_switch) {
- if (test_stream->requested_subsequent_bitrate == 0) {
- test_stream->requested_subsequent_bitrate =
- test_stream->requested_bitrate * kDefaultSubsequentBitrateRatio;
- }
- } else {
- test_stream->requested_subsequent_bitrate =
- test_stream->requested_bitrate;
- }
- if (test_stream->requested_subsequent_bitrate == 0)
- test_stream->requested_subsequent_bitrate = 1;
-
- if (mid_stream_framerate_switch) {
- if (test_stream->requested_subsequent_framerate == 0) {
- test_stream->requested_subsequent_framerate =
- test_stream->requested_framerate * kDefaultSubsequentFramerateRatio;
- }
- } else {
- test_stream->requested_subsequent_framerate =
- test_stream->requested_framerate;
- }
- if (test_stream->requested_subsequent_framerate == 0)
- test_stream->requested_subsequent_framerate = 1;
- }
-}
-
enum ClientState {
CS_CREATED,
CS_ENCODER_SET,
@@ -244,28 +354,29 @@ class H264Validator : public StreamValidator {
seen_pps_(false),
seen_idr_(false) {}
- void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE;
+ virtual void ProcessStreamBuffer(const uint8* stream, size_t size) override;
private:
// Set to true when encoder provides us with the corresponding NALU type.
bool seen_sps_;
bool seen_pps_;
bool seen_idr_;
+
+ media::H264Parser h264_parser_;
};
void H264Validator::ProcessStreamBuffer(const uint8* stream, size_t size) {
- media::H264Parser h264_parser;
- h264_parser.SetStream(stream, size);
+ h264_parser_.SetStream(stream, size);
while (1) {
media::H264NALU nalu;
media::H264Parser::Result result;
- result = h264_parser.AdvanceToNextNALU(&nalu);
+ result = h264_parser_.AdvanceToNextNALU(&nalu);
if (result == media::H264Parser::kEOStream)
break;
- ASSERT_EQ(result, media::H264Parser::kOk);
+ ASSERT_EQ(media::H264Parser::kOk, result);
bool keyframe = false;
@@ -273,22 +384,30 @@ void H264Validator::ProcessStreamBuffer(const uint8* stream, size_t size) {
case media::H264NALU::kIDRSlice:
ASSERT_TRUE(seen_sps_);
ASSERT_TRUE(seen_pps_);
- seen_idr_ = keyframe = true;
+ seen_idr_ = true;
+ keyframe = true;
// fallthrough
- case media::H264NALU::kNonIDRSlice:
+ case media::H264NALU::kNonIDRSlice: {
ASSERT_TRUE(seen_idr_);
if (!frame_cb_.Run(keyframe))
return;
break;
+ }
- case media::H264NALU::kSPS:
+ case media::H264NALU::kSPS: {
+ int sps_id;
+ ASSERT_EQ(media::H264Parser::kOk, h264_parser_.ParseSPS(&sps_id));
seen_sps_ = true;
break;
+ }
- case media::H264NALU::kPPS:
+ case media::H264NALU::kPPS: {
ASSERT_TRUE(seen_sps_);
+ int pps_id;
+ ASSERT_EQ(media::H264Parser::kOk, h264_parser_.ParsePPS(&pps_id));
seen_pps_ = true;
break;
+ }
default:
break;
@@ -302,7 +421,7 @@ class VP8Validator : public StreamValidator {
: StreamValidator(frame_cb),
seen_keyframe_(false) {}
- void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE;
+ virtual void ProcessStreamBuffer(const uint8* stream, size_t size) override;
private:
// Have we already got a keyframe in the stream?
@@ -343,12 +462,14 @@ scoped_ptr<StreamValidator> StreamValidator::Create(
class VEAClient : public VideoEncodeAccelerator::Client {
public:
- VEAClient(const TestStream& test_stream,
+ VEAClient(TestStream* test_stream,
ClientStateNotification<ClientState>* note,
bool save_to_file,
unsigned int keyframe_period,
bool force_bitrate,
- bool test_perf);
+ bool test_perf,
+ bool mid_stream_bitrate_switch,
+ bool mid_stream_framerate_switch);
virtual ~VEAClient();
void CreateEncoder();
void DestroyEncoder();
@@ -357,13 +478,13 @@ class VEAClient : public VideoEncodeAccelerator::Client {
double frames_per_second();
// VideoDecodeAccelerator::Client implementation.
- void RequireBitstreamBuffers(unsigned int input_count,
- const gfx::Size& input_coded_size,
- size_t output_buffer_size) OVERRIDE;
- void BitstreamBufferReady(int32 bitstream_buffer_id,
- size_t payload_size,
- bool key_frame) OVERRIDE;
- void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE;
+ virtual void RequireBitstreamBuffers(unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) override;
+ virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame) override;
+ virtual void NotifyError(VideoEncodeAccelerator::Error error) override;
private:
bool has_encoder() { return encoder_.get(); }
@@ -402,10 +523,15 @@ class VEAClient : public VideoEncodeAccelerator::Client {
// the input stream, ready to be sent to encoder.
scoped_refptr<media::VideoFrame> PrepareInputFrame(off_t position);
+ // Update the parameters according to |mid_stream_bitrate_switch| and
+ // |mid_stream_framerate_switch|.
+ void UpdateTestStreamData(bool mid_stream_bitrate_switch,
+ bool mid_stream_framerate_switch);
+
ClientState state_;
scoped_ptr<VideoEncodeAccelerator> encoder_;
- const TestStream& test_stream_;
+ TestStream* test_stream_;
// Used to notify another thread about the state. VEAClient does not own this.
ClientStateNotification<ClientState>* note_;
@@ -422,18 +548,13 @@ class VEAClient : public VideoEncodeAccelerator::Client {
// Current offset into input stream.
off_t pos_in_input_stream_;
- // Byte size of an input frame.
- size_t input_buffer_size_;
gfx::Size input_coded_size_;
// Requested by encoder.
unsigned int num_required_input_buffers_;
size_t output_buffer_size_;
- // Precalculated number of frames in the stream.
- unsigned int num_frames_in_stream_;
-
- // Number of frames to encode. This may differ from num_frames_in_stream_ if
- // we need more frames for bitrate tests.
+ // Number of frames to encode. This may differ from the number of frames in
+ // stream if we need more frames for bitrate tests.
unsigned int num_frames_to_encode_;
// Number of encoded frames we've got from the encoder thus far.
@@ -480,24 +601,36 @@ class VEAClient : public VideoEncodeAccelerator::Client {
// All methods of this class should be run on the same thread.
base::ThreadChecker thread_checker_;
+
+ // Requested bitrate in bits per second.
+ unsigned int requested_bitrate_;
+
+ // Requested initial framerate.
+ unsigned int requested_framerate_;
+
+ // Bitrate to switch to in the middle of the stream.
+ unsigned int requested_subsequent_bitrate_;
+
+ // Framerate to switch to in the middle of the stream.
+ unsigned int requested_subsequent_framerate_;
};
-VEAClient::VEAClient(const TestStream& test_stream,
+VEAClient::VEAClient(TestStream* test_stream,
ClientStateNotification<ClientState>* note,
bool save_to_file,
unsigned int keyframe_period,
bool force_bitrate,
- bool test_perf)
+ bool test_perf,
+ bool mid_stream_bitrate_switch,
+ bool mid_stream_framerate_switch)
: state_(CS_CREATED),
test_stream_(test_stream),
note_(note),
next_input_id_(1),
next_output_buffer_id_(0),
pos_in_input_stream_(0),
- input_buffer_size_(0),
num_required_input_buffers_(0),
output_buffer_size_(0),
- num_frames_in_stream_(0),
num_frames_to_encode_(0),
num_encoded_frames_(0),
num_frames_since_last_check_(0),
@@ -509,46 +642,30 @@ VEAClient::VEAClient(const TestStream& test_stream,
current_requested_bitrate_(0),
current_framerate_(0),
encoded_stream_size_since_last_check_(0),
- test_perf_(test_perf) {
+ test_perf_(test_perf),
+ requested_bitrate_(0),
+ requested_framerate_(0),
+ requested_subsequent_bitrate_(0),
+ requested_subsequent_framerate_(0) {
if (keyframe_period_)
CHECK_LT(kMaxKeyframeDelay, keyframe_period_);
validator_ = StreamValidator::Create(
- test_stream_.requested_profile,
+ test_stream_->requested_profile,
base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this)));
CHECK(validator_.get());
if (save_to_file_) {
- CHECK(!test_stream_.out_filename.empty());
- base::FilePath out_filename(test_stream_.out_filename);
+ CHECK(!test_stream_->out_filename.empty());
+ base::FilePath out_filename(test_stream_->out_filename);
// This creates or truncates out_filename.
// Without it, AppendToFile() will not work.
EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0));
}
- input_buffer_size_ =
- media::VideoFrame::AllocationSize(kInputFormat, test_stream.size);
- CHECK_GT(input_buffer_size_, 0UL);
-
- // Calculate the number of frames in the input stream by dividing its length
- // in bytes by frame size in bytes.
- CHECK_EQ(test_stream_.input_file.length() % input_buffer_size_, 0U)
- << "Stream byte size is not a product of calculated frame byte size";
- num_frames_in_stream_ = test_stream_.input_file.length() / input_buffer_size_;
- CHECK_GT(num_frames_in_stream_, 0UL);
- CHECK_LE(num_frames_in_stream_, kMaxFrameNum);
-
- // We may need to loop over the stream more than once if more frames than
- // provided is required for bitrate tests.
- if (force_bitrate_ && num_frames_in_stream_ < kMinFramesForBitrateTests) {
- DVLOG(1) << "Stream too short for bitrate test (" << num_frames_in_stream_
- << " frames), will loop it to reach " << kMinFramesForBitrateTests
- << " frames";
- num_frames_to_encode_ = kMinFramesForBitrateTests;
- } else {
- num_frames_to_encode_ = num_frames_in_stream_;
- }
+ // Initialize the parameters of the test streams.
+ UpdateTestStreamData(mid_stream_bitrate_switch, mid_stream_framerate_switch);
thread_checker_.DetachFromThread();
}
@@ -559,24 +676,28 @@ void VEAClient::CreateEncoder() {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK(!has_encoder());
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder);
encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass()));
+#elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11)
+ encoder_.reset(new VaapiVideoEncodeAccelerator(gfx::GetXDisplay()));
+#endif
+
SetState(CS_ENCODER_SET);
- DVLOG(1) << "Profile: " << test_stream_.requested_profile
- << ", initial bitrate: " << test_stream_.requested_bitrate;
+ DVLOG(1) << "Profile: " << test_stream_->requested_profile
+ << ", initial bitrate: " << requested_bitrate_;
if (!encoder_->Initialize(kInputFormat,
- test_stream_.size,
- test_stream_.requested_profile,
- test_stream_.requested_bitrate,
+ test_stream_->visible_size,
+ test_stream_->requested_profile,
+ requested_bitrate_,
this)) {
- DLOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed";
+ LOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed";
SetState(CS_ERROR);
return;
}
- SetStreamParameters(test_stream_.requested_bitrate,
- test_stream_.requested_framerate);
+ SetStreamParameters(requested_bitrate_, requested_framerate_);
SetState(CS_INITIALIZED);
}
@@ -587,6 +708,50 @@ void VEAClient::DestroyEncoder() {
encoder_.reset();
}
+void VEAClient::UpdateTestStreamData(bool mid_stream_bitrate_switch,
+ bool mid_stream_framerate_switch) {
+ // Use defaults for bitrate/framerate if they are not provided.
+ if (test_stream_->requested_bitrate == 0)
+ requested_bitrate_ = kDefaultBitrate;
+ else
+ requested_bitrate_ = test_stream_->requested_bitrate;
+
+ if (test_stream_->requested_framerate == 0)
+ requested_framerate_ = kDefaultFramerate;
+ else
+ requested_framerate_ = test_stream_->requested_framerate;
+
+ // If bitrate/framerate switch is requested, use the subsequent values if
+ // provided, or, if not, calculate them from their initial values using
+ // the default ratios.
+ // Otherwise, if a switch is not requested, keep the initial values.
+ if (mid_stream_bitrate_switch) {
+ if (test_stream_->requested_subsequent_bitrate == 0)
+ requested_subsequent_bitrate_ =
+ requested_bitrate_ * kDefaultSubsequentBitrateRatio;
+ else
+ requested_subsequent_bitrate_ =
+ test_stream_->requested_subsequent_bitrate;
+ } else {
+ requested_subsequent_bitrate_ = requested_bitrate_;
+ }
+ if (requested_subsequent_bitrate_ == 0)
+ requested_subsequent_bitrate_ = 1;
+
+ if (mid_stream_framerate_switch) {
+ if (test_stream_->requested_subsequent_framerate == 0)
+ requested_subsequent_framerate_ =
+ requested_framerate_ * kDefaultSubsequentFramerateRatio;
+ else
+ requested_subsequent_framerate_ =
+ test_stream_->requested_subsequent_framerate;
+ } else {
+ requested_subsequent_framerate_ = requested_framerate_;
+ }
+ if (requested_subsequent_framerate_ == 0)
+ requested_subsequent_framerate_ = 1;
+}
+
double VEAClient::frames_per_second() {
base::TimeDelta duration = last_frame_ready_time_ - encode_start_time_;
return num_encoded_frames_ / duration.InSecondsF();
@@ -599,35 +764,20 @@ void VEAClient::RequireBitstreamBuffers(unsigned int input_count,
ASSERT_EQ(state_, CS_INITIALIZED);
SetState(CS_ENCODING);
- // TODO(posciak): For now we only support input streams that meet encoder
- // size requirements exactly (i.e. coded size == visible size), so that we
- // can simply mmap the stream file and feed the encoder directly with chunks
- // of that, instead of memcpying from mmapped file into a separate set of
- // input buffers that would meet the coded size and alignment requirements.
- // If/when this is changed, the ARM-specific alignment check below should be
- // redone as well.
- input_coded_size_ = input_coded_size;
- ASSERT_EQ(input_coded_size_, test_stream_.size);
-#if defined(ARCH_CPU_ARMEL)
- // ARM performs CPU cache management with CPU cache line granularity. We thus
- // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned).
- // Otherwise newer kernels will refuse to accept them, and on older kernels
- // we'll be treating ourselves to random corruption.
- // Since we are just mmapping and passing chunks of the input file, to ensure
- // alignment, if the starting virtual addresses of the frames in it were not
- // 64 byte-aligned, we'd have to use a separate set of input buffers and copy
- // the frames into them before sending to the encoder. It would have been an
- // overkill here though, because, for now at least, we only test resolutions
- // that result in proper alignment, and it would have also interfered with
- // performance testing. So just assert that the frame size is a multiple of
- // 64 bytes. This ensures all frames start at 64-byte boundary, because
- // MemoryMappedFile should be mmapp()ed at virtual page start as well.
- ASSERT_EQ(input_buffer_size_ & 63, 0u)
- << "Frame size has to be a multiple of 64 bytes";
- ASSERT_EQ(reinterpret_cast<off_t>(test_stream_.input_file.data()) & 63, 0)
- << "Mapped file should be mapped at a 64 byte boundary";
-#endif
+ CreateAlignedInputStreamFile(input_coded_size, test_stream_);
+ // We may need to loop over the stream more than once if more frames than
+ // provided is required for bitrate tests.
+ if (force_bitrate_ && test_stream_->num_frames < kMinFramesForBitrateTests) {
+ DVLOG(1) << "Stream too short for bitrate test ("
+ << test_stream_->num_frames << " frames), will loop it to reach "
+ << kMinFramesForBitrateTests << " frames";
+ num_frames_to_encode_ = kMinFramesForBitrateTests;
+ } else {
+ num_frames_to_encode_ = test_stream_->num_frames;
+ }
+
+ input_coded_size_ = input_coded_size;
num_required_input_buffers_ = input_count;
ASSERT_GT(num_required_input_buffers_, 0UL);
@@ -670,11 +820,10 @@ void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id,
if (save_to_file_) {
int size = base::checked_cast<int>(payload_size);
- EXPECT_EQ(base::AppendToFile(
- base::FilePath::FromUTF8Unsafe(test_stream_.out_filename),
- static_cast<char*>(shm->memory()),
- size),
- size);
+ EXPECT_TRUE(base::AppendToFile(
+ base::FilePath::FromUTF8Unsafe(test_stream_->out_filename),
+ static_cast<char*>(shm->memory()),
+ size));
}
FeedEncoderWithOutput(shm);
@@ -711,24 +860,27 @@ void VEAClient::InputNoLongerNeededCallback(int32 input_id) {
}
scoped_refptr<media::VideoFrame> VEAClient::PrepareInputFrame(off_t position) {
- CHECK_LE(position + input_buffer_size_, test_stream_.input_file.length());
+ CHECK_LE(position + test_stream_->aligned_buffer_size,
+ test_stream_->mapped_aligned_in_file.length());
- uint8* frame_data =
- const_cast<uint8*>(test_stream_.input_file.data() + position);
+ uint8* frame_data_y = const_cast<uint8*>(
+ test_stream_->mapped_aligned_in_file.data() + position);
+ uint8* frame_data_u = frame_data_y + test_stream_->aligned_plane_size[0];
+ uint8* frame_data_v = frame_data_u + test_stream_->aligned_plane_size[1];
CHECK_GT(current_framerate_, 0U);
scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::WrapExternalYuvData(
kInputFormat,
input_coded_size_,
- gfx::Rect(test_stream_.size),
- test_stream_.size,
+ gfx::Rect(test_stream_->visible_size),
+ test_stream_->visible_size,
input_coded_size_.width(),
input_coded_size_.width() / 2,
input_coded_size_.width() / 2,
- frame_data,
- frame_data + input_coded_size_.GetArea(),
- frame_data + (input_coded_size_.GetArea() * 5 / 4),
+ frame_data_y,
+ frame_data_u,
+ frame_data_v,
base::TimeDelta().FromMilliseconds(
next_input_id_ * base::Time::kMillisecondsPerSecond /
current_framerate_),
@@ -752,8 +904,9 @@ void VEAClient::FeedEncoderWithInputs() {
while (inputs_at_client_.size() <
num_required_input_buffers_ + kNumExtraInputFrames) {
- size_t bytes_left = test_stream_.input_file.length() - pos_in_input_stream_;
- if (bytes_left < input_buffer_size_) {
+ size_t bytes_left =
+ test_stream_->mapped_aligned_in_file.length() - pos_in_input_stream_;
+ if (bytes_left < test_stream_->aligned_buffer_size) {
DCHECK_EQ(bytes_left, 0UL);
// Rewind if at the end of stream and we are still encoding.
// This is to flush the encoder with additional frames from the beginning
@@ -771,7 +924,7 @@ void VEAClient::FeedEncoderWithInputs() {
scoped_refptr<media::VideoFrame> video_frame =
PrepareInputFrame(pos_in_input_stream_);
- pos_in_input_stream_ += input_buffer_size_;
+ pos_in_input_stream_ += test_stream_->aligned_buffer_size;
encoder_->Encode(video_frame, force_keyframe);
}
@@ -785,7 +938,7 @@ void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) {
return;
base::SharedMemoryHandle dup_handle;
- CHECK(shm->ShareToProcess(base::Process::Current().handle(), &dup_handle));
+ CHECK(shm->ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle));
media::BitstreamBuffer bitstream_buffer(
next_output_buffer_id_++, dup_handle, output_buffer_size_);
@@ -824,11 +977,10 @@ bool VEAClient::HandleEncodedFrame(bool keyframe) {
if (num_encoded_frames_ == num_frames_to_encode_ / 2) {
VerifyStreamProperties();
- if (test_stream_.requested_subsequent_bitrate !=
- current_requested_bitrate_ ||
- test_stream_.requested_subsequent_framerate != current_framerate_) {
- SetStreamParameters(test_stream_.requested_subsequent_bitrate,
- test_stream_.requested_subsequent_framerate);
+ if (requested_subsequent_bitrate_ != current_requested_bitrate_ ||
+ requested_subsequent_framerate_ != current_framerate_) {
+ SetStreamParameters(requested_subsequent_bitrate_,
+ requested_subsequent_framerate_);
}
} else if (num_encoded_frames_ == num_frames_to_encode_) {
VerifyPerf();
@@ -867,6 +1019,31 @@ void VEAClient::VerifyStreamProperties() {
}
}
+// Setup test stream data and delete temporary aligned files at the beginning
+// and end of unittest. We only need to setup once for all test cases.
+class VideoEncodeAcceleratorTestEnvironment : public ::testing::Environment {
+ public:
+ VideoEncodeAcceleratorTestEnvironment(
+ scoped_ptr<base::FilePath::StringType> data) {
+ test_stream_data_ = data.Pass();
+ }
+
+ virtual void SetUp() {
+ ParseAndReadTestStreamData(*test_stream_data_, &test_streams_);
+ }
+
+ virtual void TearDown() {
+ for (size_t i = 0; i < test_streams_.size(); i++) {
+ base::DeleteFile(test_streams_[i]->aligned_in_file, false);
+ }
+ }
+
+ ScopedVector<TestStream> test_streams_;
+
+ private:
+ scoped_ptr<base::FilePath::StringType> test_stream_data_;
+};
+
// Test parameters:
// - Number of concurrent encoders.
// - If true, save output to file (provided an output filename was supplied).
@@ -889,12 +1066,6 @@ TEST_P(VideoEncodeAcceleratorTest, TestSimpleEncode) {
const bool mid_stream_bitrate_switch = GetParam().f;
const bool mid_stream_framerate_switch = GetParam().g;
- // Initialize the test streams.
- ScopedVector<TestStream> test_streams;
- ParseAndReadTestStreamData(*g_test_stream_data, &test_streams);
- UpdateTestStreamData(
- mid_stream_bitrate_switch, mid_stream_framerate_switch, &test_streams);
-
ScopedVector<ClientStateNotification<ClientState> > notes;
ScopedVector<VEAClient> clients;
base::Thread encoder_thread("EncoderThread");
@@ -902,19 +1073,21 @@ TEST_P(VideoEncodeAcceleratorTest, TestSimpleEncode) {
// Create all encoders.
for (size_t i = 0; i < num_concurrent_encoders; i++) {
- size_t test_stream_index = i % test_streams.size();
+ size_t test_stream_index = i % g_env->test_streams_.size();
// Disregard save_to_file if we didn't get an output filename.
bool encoder_save_to_file =
(save_to_file &&
- !test_streams[test_stream_index]->out_filename.empty());
+ !g_env->test_streams_[test_stream_index]->out_filename.empty());
notes.push_back(new ClientStateNotification<ClientState>());
- clients.push_back(new VEAClient(*test_streams[test_stream_index],
+ clients.push_back(new VEAClient(g_env->test_streams_[test_stream_index],
notes.back(),
encoder_save_to_file,
keyframe_period,
force_bitrate,
- test_perf));
+ test_perf,
+ mid_stream_bitrate_switch,
+ mid_stream_framerate_switch));
encoder_thread.message_loop()->PostTask(
FROM_HERE,
@@ -978,15 +1151,11 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(MakeTuple(1, false, 0, true, false, false, true)));
INSTANTIATE_TEST_CASE_P(
- MidStreamParamSwitchBitrateAndFPS,
- VideoEncodeAcceleratorTest,
- ::testing::Values(MakeTuple(1, false, 0, true, false, true, true)));
-
-INSTANTIATE_TEST_CASE_P(
MultipleEncoders,
VideoEncodeAcceleratorTest,
::testing::Values(MakeTuple(3, false, 0, false, false, false, false),
- MakeTuple(3, false, 0, true, false, true, true)));
+ MakeTuple(3, false, 0, true, false, false, true),
+ MakeTuple(3, false, 0, true, false, true, false)));
// TODO(posciak): more tests:
// - async FeedEncoderWithOutput
@@ -999,25 +1168,24 @@ INSTANTIATE_TEST_CASE_P(
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args.
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
base::ShadowingAtExitManager at_exit_manager;
scoped_ptr<base::FilePath::StringType> test_stream_data(
new base::FilePath::StringType(
media::GetTestDataFilePath(content::g_default_in_filename).value() +
content::g_default_in_parameters));
- content::g_test_stream_data = test_stream_data.get();
// Needed to enable DVLOG through --vmodule.
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
CHECK(logging::InitLogging(settings));
- CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
DCHECK(cmd_line);
- CommandLine::SwitchMap switches = cmd_line->GetSwitches();
- for (CommandLine::SwitchMap::const_iterator it = switches.begin();
+ base::CommandLine::SwitchMap switches = cmd_line->GetSwitches();
+ for (base::CommandLine::SwitchMap::const_iterator it = switches.begin();
it != switches.end();
++it) {
if (it->first == "test_stream_data") {
@@ -1029,5 +1197,11 @@ int main(int argc, char** argv) {
LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
}
+ content::g_env =
+ reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>(
+ testing::AddGlobalTestEnvironment(
+ new content::VideoEncodeAcceleratorTestEnvironment(
+ test_stream_data.Pass())));
+
return RUN_ALL_TESTS();
}
diff --git a/chromium/content/common/gpu/media/vt.h b/chromium/content/common/gpu/media/vt.h
new file mode 100644
index 00000000000..fcb7d21f769
--- /dev/null
+++ b/chromium/content/common/gpu/media/vt.h
@@ -0,0 +1,19 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_MEDIA_VT_H_
+#define CONTENT_COMMON_GPU_MEDIA_VT_H_
+
+// Dynamic library loader.
+#include "content/common/gpu/media/vt_stubs.h"
+
+// CoreMedia and VideoToolbox types.
+#include "content/common/gpu/media/vt_stubs_header.fragment"
+
+// CoreMedia and VideoToolbox functions.
+extern "C" {
+#include "content/common/gpu/media/vt.sig"
+} // extern "C"
+
+#endif // CONTENT_COMMON_GPU_MEDIA_VT_H_
diff --git a/chromium/content/common/gpu/media/vt.sig b/chromium/content/common/gpu/media/vt.sig
new file mode 100644
index 00000000000..236a52a4801
--- /dev/null
+++ b/chromium/content/common/gpu/media/vt.sig
@@ -0,0 +1,16 @@
+//------------------------------------------------
+// Functions from CoreMedia.framework used in VTVideoDecodeAccelerator.
+//------------------------------------------------
+OSStatus CMBlockBufferCreateWithMemoryBlock(CFAllocatorRef structureAllocator, void *memoryBlock, size_t blockLength, CFAllocatorRef blockAllocator, const CMBlockBufferCustomBlockSource *customBlockSource, size_t offsetToData, size_t dataLength, CMBlockBufferFlags flags, CMBlockBufferRef *newBBufOut);
+OSStatus CMBlockBufferReplaceDataBytes(const void *sourceBytes, CMBlockBufferRef destinationBuffer, size_t offsetIntoDestination, size_t dataLength);
+OSStatus CMSampleBufferCreate(CFAllocatorRef allocator, CMBlockBufferRef dataBuffer, Boolean dataReady, CMSampleBufferMakeDataReadyCallback makeDataReadyCallback, void *makeDataReadyRefcon, CMFormatDescriptionRef formatDescription, CMItemCount numSamples, CMItemCount numSampleTimingEntries, const CMSampleTimingInfo *sampleTimingArray, CMItemCount numSampleSizeEntries, const size_t *sampleSizeArray, CMSampleBufferRef *sBufOut);
+OSStatus CMVideoFormatDescriptionCreateFromH264ParameterSets(CFAllocatorRef allocator, size_t parameterSetCount, const uint8_t *const *parameterSetPointers, const size_t *parameterSetSizes, int NALUnitHeaderLength, CMFormatDescriptionRef *formatDescriptionOut);
+CMVideoDimensions CMVideoFormatDescriptionGetDimensions(CMVideoFormatDescriptionRef videoDesc);
+
+//------------------------------------------------
+// Functions from VideoToolbox.framework used in VTVideoDecodeAccelerator.
+//------------------------------------------------
+Boolean VTDecompressionSessionCanAcceptFormatDescription(VTDecompressionSessionRef session, CMFormatDescriptionRef newFormatDesc);
+OSStatus VTDecompressionSessionCreate(CFAllocatorRef allocator, CMVideoFormatDescriptionRef videoFormatDescription, CFDictionaryRef videoDecoderSpecification, CFDictionaryRef destinationImageBufferAttributes, const VTDecompressionOutputCallbackRecord *outputCallback, VTDecompressionSessionRef *decompressionSessionOut);
+OSStatus VTDecompressionSessionDecodeFrame(VTDecompressionSessionRef session, CMSampleBufferRef sampleBuffer, VTDecodeFrameFlags decodeFlags, void *sourceFrameRefCon, VTDecodeInfoFlags *infoFlagsOut);
+OSStatus VTDecompressionSessionFinishDelayedFrames(VTDecompressionSessionRef session);
diff --git a/chromium/content/common/gpu/media/vt_stubs_header.fragment b/chromium/content/common/gpu/media/vt_stubs_header.fragment
new file mode 100644
index 00000000000..f8f7ded55a6
--- /dev/null
+++ b/chromium/content/common/gpu/media/vt_stubs_header.fragment
@@ -0,0 +1,84 @@
+// Copyright 2014 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 <CoreFoundation/CoreFoundation.h>
+
+extern "C" {
+
+//
+// Declare CoreMedia types.
+//
+
+typedef signed long CMItemCount;
+typedef uint32_t CMBlockBufferFlags;
+typedef struct OpaqueCMBlockBuffer *CMBlockBufferRef;
+typedef const struct opaqueCMFormatDescription *CMFormatDescriptionRef;
+typedef CMFormatDescriptionRef CMVideoFormatDescriptionRef;
+typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
+
+typedef int64_t CMTimeValue;
+typedef int32_t CMTimeScale;
+typedef int64_t CMTimeEpoch;
+typedef uint32_t CMTimeFlags;
+
+typedef struct {
+ CMTimeValue value;
+ CMTimeScale timescale;
+ CMTimeFlags flags;
+ CMTimeEpoch epoch;
+} CMTime;
+
+typedef struct {
+ CMTime duration;
+ CMTime presentationTimeStamp;
+ CMTime decodeTimeStamp;
+} CMSampleTimingInfo;
+
+typedef struct {
+ int32_t width;
+ int32_t height;
+} CMVideoDimensions;
+
+typedef struct {
+ uint32_t version;
+ void *(*AllocateBlock)(void *refCon, size_t sizeInBytes);
+ void (*FreeBlock)(void *refCon, void *doomedMemoryBlock, size_t sizeInBytes);
+ void *refCon;
+} CMBlockBufferCustomBlockSource;
+
+typedef OSStatus (*CMSampleBufferMakeDataReadyCallback)(
+ CMSampleBufferRef sbuf,
+ void *makeDataReadyRefcon);
+
+//
+// Declare VideoToolbox types.
+//
+
+typedef struct __CVBuffer *CVBufferRef;
+typedef CVBufferRef CVImageBufferRef;
+typedef uint32_t VTDecodeFrameFlags;
+enum {
+ kVTDecodeFrame_EnableAsynchronousDecompression = 1 << 0,
+ kVTDecodeFrame_DoNotOutputFrame = 1 << 1,
+ kVTDecodeFrame_1xRealTimePlayback = 1 << 2,
+ kVTDecodeFrame_EnableTemporalProcessing = 1 << 3,
+};
+typedef UInt32 VTDecodeInfoFlags;
+typedef struct OpaqueVTDecompressionSession* VTDecompressionSessionRef;
+
+typedef void (*VTDecompressionOutputCallback)(
+ void *decompressionOutputRefCon,
+ void *sourceFrameRefCon,
+ OSStatus status,
+ VTDecodeInfoFlags infoFlags,
+ CVImageBufferRef imageBuffer,
+ CMTime presentationTimeStamp,
+ CMTime presentationDuration);
+
+typedef struct {
+ VTDecompressionOutputCallback decompressionOutputCallback;
+ void *decompressionOutputRefCon;
+} VTDecompressionOutputCallbackRecord;
+
+} // extern "C"
diff --git a/chromium/content/common/gpu/media/vt_video_decode_accelerator.cc b/chromium/content/common/gpu/media/vt_video_decode_accelerator.cc
index 59251d20465..b09a5e3e0c3 100644
--- a/chromium/content/common/gpu/media/vt_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/vt_video_decode_accelerator.cc
@@ -2,15 +2,91 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <CoreVideo/CoreVideo.h>
+#include <OpenGL/CGLIOSurface.h>
+#include <OpenGL/gl.h>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/sys_byteorder.h"
+#include "base/thread_task_runner_handle.h"
#include "content/common/gpu/media/vt_video_decode_accelerator.h"
+#include "content/public/common/content_switches.h"
+#include "media/filters/h264_parser.h"
+#include "ui/gl/scoped_binders.h"
+
+using content_common_gpu_media::kModuleVt;
+using content_common_gpu_media::InitializeStubs;
+using content_common_gpu_media::IsVtInitialized;
+using content_common_gpu_media::StubPathMap;
+
+#define NOTIFY_STATUS(name, status) \
+ do { \
+ LOG(ERROR) << name << " failed with status " << status; \
+ NotifyError(PLATFORM_FAILURE); \
+ } while (0)
namespace content {
-VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(CGLContextObj cgl_context)
- : loop_proxy_(base::MessageLoopProxy::current()),
- cgl_context_(cgl_context),
+// Size of NALU length headers in AVCC/MPEG-4 format (can be 1, 2, or 4).
+static const int kNALUHeaderLength = 4;
+
+// We only request 5 picture buffers from the client which are used to hold the
+// decoded samples. These buffers are then reused when the client tells us that
+// it is done with the buffer.
+static const int kNumPictureBuffers = 5;
+
+// Route decoded frame callbacks back into the VTVideoDecodeAccelerator.
+static void OutputThunk(
+ void* decompression_output_refcon,
+ void* source_frame_refcon,
+ OSStatus status,
+ VTDecodeInfoFlags info_flags,
+ CVImageBufferRef image_buffer,
+ CMTime presentation_time_stamp,
+ CMTime presentation_duration) {
+ VTVideoDecodeAccelerator* vda =
+ reinterpret_cast<VTVideoDecodeAccelerator*>(decompression_output_refcon);
+ int32_t bitstream_id = reinterpret_cast<intptr_t>(source_frame_refcon);
+ vda->Output(bitstream_id, status, image_buffer);
+}
+
+VTVideoDecodeAccelerator::DecodedFrame::DecodedFrame(
+ int32_t bitstream_id,
+ CVImageBufferRef image_buffer)
+ : bitstream_id(bitstream_id),
+ image_buffer(image_buffer) {
+}
+
+VTVideoDecodeAccelerator::DecodedFrame::~DecodedFrame() {
+}
+
+VTVideoDecodeAccelerator::PendingAction::PendingAction(
+ Action action,
+ int32_t bitstream_id)
+ : action(action),
+ bitstream_id(bitstream_id) {
+}
+
+VTVideoDecodeAccelerator::PendingAction::~PendingAction() {
+}
+
+VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
+ CGLContextObj cgl_context,
+ const base::Callback<bool(void)>& make_context_current)
+ : cgl_context_(cgl_context),
+ make_context_current_(make_context_current),
client_(NULL),
- weak_this_factory_(this) {
+ has_error_(false),
+ format_(NULL),
+ session_(NULL),
+ gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ weak_this_factory_(this),
+ decoder_thread_("VTDecoderThread") {
+ DCHECK(!make_context_current_.is_null());
+ callback_.decompressionOutputCallback = OutputThunk;
+ callback_.decompressionOutputRefCon = this;
}
VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() {
@@ -20,40 +96,651 @@ bool VTVideoDecodeAccelerator::Initialize(
media::VideoCodecProfile profile,
Client* client) {
DCHECK(CalledOnValidThread());
- DVLOG(2) << __FUNCTION__;
client_ = client;
// Only H.264 is supported.
if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
return false;
- // Prevent anyone from using VTVideoDecoder for now. http://crbug.com/133828
- return false;
+ // Require --no-sandbox until VideoToolbox library loading is part of sandbox
+ // startup (and this VDA is ready for regular users).
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox))
+ return false;
+
+ if (!IsVtInitialized()) {
+ // CoreVideo is also required, but the loader stops after the first
+ // path is loaded. Instead we rely on the transitive dependency from
+ // VideoToolbox to CoreVideo.
+ // TODO(sandersd): Fallback to PrivateFrameworks for VideoToolbox.
+ StubPathMap paths;
+ paths[kModuleVt].push_back(FILE_PATH_LITERAL(
+ "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox"));
+ if (!InitializeStubs(paths))
+ return false;
+ }
+
+ // Spawn a thread to handle parsing and calling VideoToolbox.
+ if (!decoder_thread_.Start())
+ return false;
+
+ return true;
+}
+
+bool VTVideoDecodeAccelerator::ConfigureDecoder(
+ const std::vector<const uint8_t*>& nalu_data_ptrs,
+ const std::vector<size_t>& nalu_data_sizes) {
+ DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
+
+ // Construct a new format description from the parameter sets.
+ // TODO(sandersd): Replace this with custom code to support OS X < 10.9.
+ format_.reset();
+ OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(
+ kCFAllocatorDefault,
+ nalu_data_ptrs.size(), // parameter_set_count
+ &nalu_data_ptrs.front(), // &parameter_set_pointers
+ &nalu_data_sizes.front(), // &parameter_set_sizes
+ kNALUHeaderLength, // nal_unit_header_length
+ format_.InitializeInto());
+ if (status) {
+ NOTIFY_STATUS("CMVideoFormatDescriptionCreateFromH264ParameterSets()",
+ status);
+ return false;
+ }
+
+ // If the session is compatible, there's nothing to do.
+ if (session_ &&
+ VTDecompressionSessionCanAcceptFormatDescription(session_, format_)) {
+ return true;
+ }
+
+ // Prepare VideoToolbox configuration dictionaries.
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> decoder_config(
+ CFDictionaryCreateMutable(
+ kCFAllocatorDefault,
+ 1, // capacity
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CFDictionarySetValue(
+ decoder_config,
+ // kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
+ CFSTR("EnableHardwareAcceleratedVideoDecoder"),
+ kCFBooleanTrue);
+
+ base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config(
+ CFDictionaryCreateMutable(
+ kCFAllocatorDefault,
+ 4, // capacity
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ CMVideoDimensions coded_dimensions =
+ CMVideoFormatDescriptionGetDimensions(format_);
+#define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
+ // TODO(sandersd): RGBA option for 4:4:4 video.
+ int32_t pixel_format = kCVPixelFormatType_422YpCbCr8;
+ base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
+ base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
+ base::ScopedCFTypeRef<CFNumberRef> cf_height(CFINT(coded_dimensions.height));
+#undef CFINT
+ CFDictionarySetValue(
+ image_config, kCVPixelBufferPixelFormatTypeKey, cf_pixel_format);
+ CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
+ CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
+ CFDictionarySetValue(
+ image_config, kCVPixelBufferOpenGLCompatibilityKey, kCFBooleanTrue);
+
+ // TODO(sandersd): Does the old session need to be flushed first?
+ session_.reset();
+ status = VTDecompressionSessionCreate(
+ kCFAllocatorDefault,
+ format_, // video_format_description
+ decoder_config, // video_decoder_specification
+ image_config, // destination_image_buffer_attributes
+ &callback_, // output_callback
+ session_.InitializeInto());
+ if (status) {
+ NOTIFY_STATUS("VTDecompressionSessionCreate()", status);
+ return false;
+ }
+
+ return true;
}
void VTVideoDecodeAccelerator::Decode(const media::BitstreamBuffer& bitstream) {
DCHECK(CalledOnValidThread());
+ // Not actually a requirement of the VDA API, but we're lazy and use negative
+ // values as flags internally. Revisit that if this actually happens.
+ if (bitstream.id() < 0) {
+ LOG(ERROR) << "Negative bitstream ID";
+ NotifyError(INVALID_ARGUMENT);
+ client_->NotifyEndOfBitstreamBuffer(bitstream.id());
+ return;
+ }
+ pending_bitstream_ids_.push(bitstream.id());
+ decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
+ &VTVideoDecodeAccelerator::DecodeTask, base::Unretained(this),
+ bitstream));
+}
+
+void VTVideoDecodeAccelerator::DecodeTask(
+ const media::BitstreamBuffer& bitstream) {
+ DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
+
+ // Once we have a bitstream buffer, we must either decode it or drop it.
+ // This construct ensures that the buffer is always dropped unless we call
+ // drop_bitstream.Release().
+ base::ScopedClosureRunner drop_bitstream(base::Bind(
+ &VTVideoDecodeAccelerator::DropBitstream, base::Unretained(this),
+ bitstream.id()));
+
+ // Map the bitstream buffer.
+ base::SharedMemory memory(bitstream.handle(), true);
+ size_t size = bitstream.size();
+ if (!memory.Map(size)) {
+ LOG(ERROR) << "Failed to map bitstream buffer";
+ NotifyError(PLATFORM_FAILURE);
+ return;
+ }
+ const uint8_t* buf = static_cast<uint8_t*>(memory.memory());
+
+ // NALUs are stored with Annex B format in the bitstream buffer (start codes),
+ // but VideoToolbox expects AVCC/MPEG-4 format (length headers), so we must
+ // rewrite the data.
+ //
+ // 1. Locate relevant NALUs and compute the size of the translated data.
+ // Also record any parameter sets for VideoToolbox initialization.
+ bool config_changed = false;
+ size_t data_size = 0;
+ std::vector<media::H264NALU> nalus;
+ parser_.SetStream(buf, size);
+ media::H264NALU nalu;
+ while (true) {
+ media::H264Parser::Result result = parser_.AdvanceToNextNALU(&nalu);
+ if (result == media::H264Parser::kEOStream)
+ break;
+ if (result != media::H264Parser::kOk) {
+ LOG(ERROR) << "Failed to find H.264 NALU";
+ NotifyError(PLATFORM_FAILURE);
+ return;
+ }
+ // TODO(sandersd): Strict ordering rules.
+ switch (nalu.nal_unit_type) {
+ case media::H264NALU::kSPS:
+ last_sps_.assign(nalu.data, nalu.data + nalu.size);
+ last_spsext_.clear();
+ config_changed = true;
+ break;
+ case media::H264NALU::kSPSExt:
+ // TODO(sandersd): Check that the previous NALU was an SPS.
+ last_spsext_.assign(nalu.data, nalu.data + nalu.size);
+ config_changed = true;
+ break;
+ case media::H264NALU::kPPS:
+ last_pps_.assign(nalu.data, nalu.data + nalu.size);
+ config_changed = true;
+ break;
+ default:
+ nalus.push_back(nalu);
+ data_size += kNALUHeaderLength + nalu.size;
+ break;
+ }
+ }
+
+ // 2. Initialize VideoToolbox.
+ // TODO(sandersd): Check if the new configuration is identical before
+ // reconfiguring.
+ if (config_changed) {
+ if (last_sps_.size() == 0 || last_pps_.size() == 0) {
+ LOG(ERROR) << "Invalid configuration data";
+ NotifyError(INVALID_ARGUMENT);
+ return;
+ }
+ // TODO(sandersd): Check that the SPS and PPS IDs match.
+ std::vector<const uint8_t*> nalu_data_ptrs;
+ std::vector<size_t> nalu_data_sizes;
+ nalu_data_ptrs.push_back(&last_sps_.front());
+ nalu_data_sizes.push_back(last_sps_.size());
+ if (last_spsext_.size() != 0) {
+ nalu_data_ptrs.push_back(&last_spsext_.front());
+ nalu_data_sizes.push_back(last_spsext_.size());
+ }
+ nalu_data_ptrs.push_back(&last_pps_.front());
+ nalu_data_sizes.push_back(last_pps_.size());
+
+ // If ConfigureDecoder() fails, it already called NotifyError().
+ if (!ConfigureDecoder(nalu_data_ptrs, nalu_data_sizes))
+ return;
+ }
+
+ // If there are no non-configuration units, immediately return an empty
+ // (ie. dropped) frame. It is an error to create a MemoryBlock with zero
+ // size.
+ if (!data_size)
+ return;
+
+ // If the session is not configured, fail.
+ if (!session_) {
+ LOG(ERROR) << "Image slice without configuration data";
+ NotifyError(INVALID_ARGUMENT);
+ return;
+ }
+
+ // 3. Allocate a memory-backed CMBlockBuffer for the translated data.
+ // TODO(sandersd): Check that the slice's PPS matches the current PPS.
+ base::ScopedCFTypeRef<CMBlockBufferRef> data;
+ OSStatus status = CMBlockBufferCreateWithMemoryBlock(
+ kCFAllocatorDefault,
+ NULL, // &memory_block
+ data_size, // block_length
+ kCFAllocatorDefault, // block_allocator
+ NULL, // &custom_block_source
+ 0, // offset_to_data
+ data_size, // data_length
+ 0, // flags
+ data.InitializeInto());
+ if (status) {
+ NOTIFY_STATUS("CMBlockBufferCreateWithMemoryBlock()", status);
+ return;
+ }
+
+ // 4. Copy NALU data, inserting length headers.
+ size_t offset = 0;
+ for (size_t i = 0; i < nalus.size(); i++) {
+ media::H264NALU& nalu = nalus[i];
+ uint32_t header = base::HostToNet32(static_cast<uint32_t>(nalu.size));
+ status = CMBlockBufferReplaceDataBytes(
+ &header, data, offset, kNALUHeaderLength);
+ if (status) {
+ NOTIFY_STATUS("CMBlockBufferReplaceDataBytes()", status);
+ return;
+ }
+ offset += kNALUHeaderLength;
+ status = CMBlockBufferReplaceDataBytes(nalu.data, data, offset, nalu.size);
+ if (status) {
+ NOTIFY_STATUS("CMBlockBufferReplaceDataBytes()", status);
+ return;
+ }
+ offset += nalu.size;
+ }
+
+ // 5. Package the data for VideoToolbox and request decoding.
+ base::ScopedCFTypeRef<CMSampleBufferRef> frame;
+ status = CMSampleBufferCreate(
+ kCFAllocatorDefault,
+ data, // data_buffer
+ true, // data_ready
+ NULL, // make_data_ready_callback
+ NULL, // make_data_ready_refcon
+ format_, // format_description
+ 1, // num_samples
+ 0, // num_sample_timing_entries
+ NULL, // &sample_timing_array
+ 0, // num_sample_size_entries
+ NULL, // &sample_size_array
+ frame.InitializeInto());
+ if (status) {
+ NOTIFY_STATUS("CMSampleBufferCreate()", status);
+ return;
+ }
+
+ // Asynchronous Decompression allows for parallel submission of frames
+ // (without it, DecodeFrame() does not return until the frame has been
+ // decoded). We don't enable Temporal Processing so that frames are always
+ // returned in decode order; this makes it easier to avoid deadlock.
+ VTDecodeFrameFlags decode_flags =
+ kVTDecodeFrame_EnableAsynchronousDecompression;
+
+ intptr_t bitstream_id = bitstream.id();
+ status = VTDecompressionSessionDecodeFrame(
+ session_,
+ frame, // sample_buffer
+ decode_flags, // decode_flags
+ reinterpret_cast<void*>(bitstream_id), // source_frame_refcon
+ NULL); // &info_flags_out
+ if (status) {
+ NOTIFY_STATUS("VTDecompressionSessionDecodeFrame()", status);
+ return;
+ }
+
+ // Now that the bitstream is decoding, don't drop it.
+ (void)drop_bitstream.Release();
+}
+
+// This method may be called on any VideoToolbox thread.
+void VTVideoDecodeAccelerator::Output(
+ int32_t bitstream_id,
+ OSStatus status,
+ CVImageBufferRef image_buffer) {
+ if (status) {
+ // TODO(sandersd): Handle dropped frames.
+ NOTIFY_STATUS("Decoding", status);
+ image_buffer = NULL;
+ } else if (CFGetTypeID(image_buffer) != CVPixelBufferGetTypeID()) {
+ LOG(ERROR) << "Decoded frame is not a CVPixelBuffer";
+ NotifyError(PLATFORM_FAILURE);
+ image_buffer = NULL;
+ } else {
+ CFRetain(image_buffer);
+ }
+ gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &VTVideoDecodeAccelerator::OutputTask,
+ weak_this_factory_.GetWeakPtr(),
+ DecodedFrame(bitstream_id, image_buffer)));
+}
+
+void VTVideoDecodeAccelerator::OutputTask(DecodedFrame frame) {
+ DCHECK(CalledOnValidThread());
+ decoded_frames_.push(frame);
+ ProcessDecodedFrames();
}
void VTVideoDecodeAccelerator::AssignPictureBuffers(
const std::vector<media::PictureBuffer>& pictures) {
DCHECK(CalledOnValidThread());
+
+ for (size_t i = 0; i < pictures.size(); i++) {
+ DCHECK(!texture_ids_.count(pictures[i].id()));
+ assigned_picture_ids_.insert(pictures[i].id());
+ available_picture_ids_.push_back(pictures[i].id());
+ texture_ids_[pictures[i].id()] = pictures[i].texture_id();
+ }
+
+ // Pictures are not marked as uncleared until after this method returns, and
+ // they will be broken if they are used before that happens. So, schedule
+ // future work after that happens.
+ gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &VTVideoDecodeAccelerator::ProcessDecodedFrames,
+ weak_this_factory_.GetWeakPtr()));
}
void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
DCHECK(CalledOnValidThread());
+ DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1);
+ picture_bindings_.erase(picture_id);
+ // Don't put the picture back in the available list if has been dismissed.
+ if (assigned_picture_ids_.count(picture_id) != 0) {
+ available_picture_ids_.push_back(picture_id);
+ ProcessDecodedFrames();
+ }
+}
+
+void VTVideoDecodeAccelerator::CompleteAction(Action action) {
+ DCHECK(CalledOnValidThread());
+
+ switch (action) {
+ case ACTION_FLUSH:
+ client_->NotifyFlushDone();
+ break;
+ case ACTION_RESET:
+ client_->NotifyResetDone();
+ break;
+ case ACTION_DESTROY:
+ delete this;
+ break;
+ }
+}
+
+void VTVideoDecodeAccelerator::CompleteActions(int32_t bitstream_id) {
+ DCHECK(CalledOnValidThread());
+ while (!pending_actions_.empty() &&
+ pending_actions_.front().bitstream_id == bitstream_id) {
+ CompleteAction(pending_actions_.front().action);
+ pending_actions_.pop();
+ }
+}
+
+void VTVideoDecodeAccelerator::ProcessDecodedFrames() {
+ DCHECK(CalledOnValidThread());
+
+ while (!decoded_frames_.empty()) {
+ if (pending_actions_.empty()) {
+ // No pending actions; send frames normally.
+ if (!has_error_)
+ SendPictures(pending_bitstream_ids_.back());
+ return;
+ }
+
+ int32_t next_action_bitstream_id = pending_actions_.front().bitstream_id;
+ int32_t last_sent_bitstream_id = -1;
+ switch (pending_actions_.front().action) {
+ case ACTION_FLUSH:
+ // Send frames normally.
+ if (has_error_)
+ return;
+ last_sent_bitstream_id = SendPictures(next_action_bitstream_id);
+ break;
+
+ case ACTION_RESET:
+ // Drop decoded frames.
+ if (has_error_)
+ return;
+ while (!decoded_frames_.empty() &&
+ last_sent_bitstream_id != next_action_bitstream_id) {
+ last_sent_bitstream_id = decoded_frames_.front().bitstream_id;
+ decoded_frames_.pop();
+ DCHECK_EQ(pending_bitstream_ids_.front(), last_sent_bitstream_id);
+ pending_bitstream_ids_.pop();
+ client_->NotifyEndOfBitstreamBuffer(last_sent_bitstream_id);
+ }
+ break;
+
+ case ACTION_DESTROY:
+ // Drop decoded frames, without bookkeeping.
+ while (!decoded_frames_.empty()) {
+ last_sent_bitstream_id = decoded_frames_.front().bitstream_id;
+ decoded_frames_.pop();
+ }
+
+ // Handle completing the action specially, as it is important not to
+ // access |this| after calling CompleteAction().
+ if (last_sent_bitstream_id == next_action_bitstream_id)
+ CompleteAction(ACTION_DESTROY);
+
+ // Either |this| was deleted or no more progress can be made.
+ return;
+ }
+
+ // If we ran out of buffers (or pictures), no more progress can be made
+ // until more frames are decoded.
+ if (last_sent_bitstream_id != next_action_bitstream_id)
+ return;
+
+ // Complete all actions pending for this |bitstream_id|, then loop to see
+ // if progress can be made on the next action.
+ CompleteActions(next_action_bitstream_id);
+ }
+}
+
+int32_t VTVideoDecodeAccelerator::ProcessDroppedFrames(
+ int32_t last_sent_bitstream_id,
+ int32_t up_to_bitstream_id) {
+ DCHECK(CalledOnValidThread());
+ // Drop frames as long as there is a frame, we have not reached the next
+ // action, and the next frame has no image.
+ while (!decoded_frames_.empty() &&
+ last_sent_bitstream_id != up_to_bitstream_id &&
+ decoded_frames_.front().image_buffer.get() == NULL) {
+ const DecodedFrame& frame = decoded_frames_.front();
+ DCHECK_EQ(pending_bitstream_ids_.front(), frame.bitstream_id);
+ client_->NotifyEndOfBitstreamBuffer(frame.bitstream_id);
+ last_sent_bitstream_id = frame.bitstream_id;
+ decoded_frames_.pop();
+ pending_bitstream_ids_.pop();
+ }
+ return last_sent_bitstream_id;
+}
+
+// TODO(sandersd): If GpuVideoDecoder didn't specifically check the size of
+// textures, this would be unnecessary, as the size is actually a property of
+// the texture binding, not the texture. We rebind every frame, so the size
+// passed to ProvidePictureBuffers() is meaningless.
+void VTVideoDecodeAccelerator::ProcessSizeChangeIfNeeded() {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!decoded_frames_.empty());
+
+ // Find the size of the next image.
+ const DecodedFrame& frame = decoded_frames_.front();
+ CVImageBufferRef image_buffer = frame.image_buffer.get();
+ size_t width = CVPixelBufferGetWidth(image_buffer);
+ size_t height = CVPixelBufferGetHeight(image_buffer);
+ gfx::Size image_size(width, height);
+
+ if (picture_size_ != image_size) {
+ // Dismiss all assigned picture buffers.
+ for (int32_t picture_id : assigned_picture_ids_)
+ client_->DismissPictureBuffer(picture_id);
+ assigned_picture_ids_.clear();
+ available_picture_ids_.clear();
+
+ // Request new pictures.
+ client_->ProvidePictureBuffers(
+ kNumPictureBuffers, image_size, GL_TEXTURE_RECTANGLE_ARB);
+ picture_size_ = image_size;
+ }
+}
+
+int32_t VTVideoDecodeAccelerator::SendPictures(int32_t up_to_bitstream_id) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!decoded_frames_.empty());
+
+ // TODO(sandersd): Store the actual last sent bitstream ID?
+ int32_t last_sent_bitstream_id = -1;
+
+ last_sent_bitstream_id =
+ ProcessDroppedFrames(last_sent_bitstream_id, up_to_bitstream_id);
+ if (last_sent_bitstream_id == up_to_bitstream_id || decoded_frames_.empty())
+ return last_sent_bitstream_id;
+
+ ProcessSizeChangeIfNeeded();
+ if (available_picture_ids_.empty())
+ return last_sent_bitstream_id;
+
+ if (!make_context_current_.Run()) {
+ LOG(ERROR) << "Failed to make GL context current";
+ NotifyError(PLATFORM_FAILURE);
+ return last_sent_bitstream_id;
+ }
+
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ while (!available_picture_ids_.empty() && !has_error_) {
+ DCHECK_NE(last_sent_bitstream_id, up_to_bitstream_id);
+ DCHECK(!decoded_frames_.empty());
+
+ // We don't pop |frame| or |picture_id| until they are consumed, which may
+ // not happen if an error occurs. Conveniently, this also removes some
+ // refcounting.
+ const DecodedFrame& frame = decoded_frames_.front();
+ DCHECK_EQ(pending_bitstream_ids_.front(), frame.bitstream_id);
+ int32_t picture_id = available_picture_ids_.back();
+
+ CVImageBufferRef image_buffer = frame.image_buffer.get();
+ IOSurfaceRef surface = CVPixelBufferGetIOSurface(image_buffer);
+
+ gfx::ScopedTextureBinder
+ texture_binder(GL_TEXTURE_RECTANGLE_ARB, texture_ids_[picture_id]);
+ CGLError status = CGLTexImageIOSurface2D(
+ cgl_context_, // ctx
+ GL_TEXTURE_RECTANGLE_ARB, // target
+ GL_RGB, // internal_format
+ picture_size_.width(), // width
+ picture_size_.height(), // height
+ GL_YCBCR_422_APPLE, // format
+ GL_UNSIGNED_SHORT_8_8_APPLE, // type
+ surface, // io_surface
+ 0); // plane
+ if (status != kCGLNoError) {
+ NOTIFY_STATUS("CGLTexImageIOSurface2D()", status);
+ break;
+ }
+
+ picture_bindings_[picture_id] = frame.image_buffer;
+ client_->PictureReady(media::Picture(
+ picture_id, frame.bitstream_id, gfx::Rect(picture_size_)));
+ available_picture_ids_.pop_back();
+ client_->NotifyEndOfBitstreamBuffer(frame.bitstream_id);
+ last_sent_bitstream_id = frame.bitstream_id;
+ decoded_frames_.pop();
+ pending_bitstream_ids_.pop();
+
+ last_sent_bitstream_id =
+ ProcessDroppedFrames(last_sent_bitstream_id, up_to_bitstream_id);
+ if (last_sent_bitstream_id == up_to_bitstream_id || decoded_frames_.empty())
+ break;
+
+ ProcessSizeChangeIfNeeded();
+ }
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ return last_sent_bitstream_id;
+}
+
+void VTVideoDecodeAccelerator::FlushTask() {
+ DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
+ OSStatus status = VTDecompressionSessionFinishDelayedFrames(session_);
+ if (status)
+ NOTIFY_STATUS("VTDecompressionSessionFinishDelayedFrames()", status);
+}
+
+void VTVideoDecodeAccelerator::QueueAction(Action action) {
+ DCHECK(CalledOnValidThread());
+ if (pending_bitstream_ids_.empty()) {
+ // If there are no pending frames, all actions complete immediately.
+ CompleteAction(action);
+ } else {
+ // Otherwise, queue the action.
+ pending_actions_.push(PendingAction(action, pending_bitstream_ids_.back()));
+
+ // Request a flush to make sure the action will eventually complete.
+ decoder_thread_.message_loop_proxy()->PostTask(FROM_HERE, base::Bind(
+ &VTVideoDecodeAccelerator::FlushTask, base::Unretained(this)));
+
+ // See if we can make progress now that there is a new pending action.
+ ProcessDecodedFrames();
+ }
+}
+
+void VTVideoDecodeAccelerator::NotifyError(Error error) {
+ if (!CalledOnValidThread()) {
+ gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &VTVideoDecodeAccelerator::NotifyError,
+ weak_this_factory_.GetWeakPtr(),
+ error));
+ return;
+ }
+ has_error_ = true;
+ client_->NotifyError(error);
+}
+
+void VTVideoDecodeAccelerator::DropBitstream(int32_t bitstream_id) {
+ DCHECK(decoder_thread_.message_loop_proxy()->BelongsToCurrentThread());
+ gpu_task_runner_->PostTask(FROM_HERE, base::Bind(
+ &VTVideoDecodeAccelerator::OutputTask,
+ weak_this_factory_.GetWeakPtr(),
+ DecodedFrame(bitstream_id, NULL)));
}
void VTVideoDecodeAccelerator::Flush() {
DCHECK(CalledOnValidThread());
+ QueueAction(ACTION_FLUSH);
}
void VTVideoDecodeAccelerator::Reset() {
DCHECK(CalledOnValidThread());
+ QueueAction(ACTION_RESET);
}
void VTVideoDecodeAccelerator::Destroy() {
DCHECK(CalledOnValidThread());
+ // Drop any other pending actions.
+ while (!pending_actions_.empty())
+ pending_actions_.pop();
+ // Return all bitstream buffers.
+ while (!pending_bitstream_ids_.empty()) {
+ client_->NotifyEndOfBitstreamBuffer(pending_bitstream_ids_.front());
+ pending_bitstream_ids_.pop();
+ }
+ QueueAction(ACTION_DESTROY);
}
bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() {
diff --git a/chromium/content/common/gpu/media/vt_video_decode_accelerator.h b/chromium/content/common/gpu/media/vt_video_decode_accelerator.h
index 5b5d8be070c..5aa4f7051c7 100644
--- a/chromium/content/common/gpu/media/vt_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/vt_video_decode_accelerator.h
@@ -7,47 +7,194 @@
#include <stdint.h>
+#include <map>
+#include <queue>
+
+#include "base/mac/scoped_cftyperef.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
+#include "base/threading/thread.h"
+#include "content/common/gpu/media/vt.h"
+#include "media/filters/h264_parser.h"
#include "media/video/video_decode_accelerator.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_context_cgl.h"
+namespace base {
+class SingleThreadTaskRunner;
+} // namespace base
+
namespace content {
-// (Stub of a) VideoToolbox.framework implementation of the
-// VideoDecodeAccelerator interface for Mac OS X.
+// VideoToolbox.framework implementation of the VideoDecodeAccelerator
+// interface for Mac OS X (currently limited to 10.9+).
class VTVideoDecodeAccelerator
: public media::VideoDecodeAccelerator,
public base::NonThreadSafe {
public:
- explicit VTVideoDecodeAccelerator(CGLContextObj cgl_context);
- virtual ~VTVideoDecodeAccelerator();
+ explicit VTVideoDecodeAccelerator(
+ CGLContextObj cgl_context,
+ const base::Callback<bool(void)>& make_context_current);
+ ~VTVideoDecodeAccelerator() override;
// VideoDecodeAccelerator implementation.
- virtual bool Initialize(
- media::VideoCodecProfile profile,
- Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream) OVERRIDE;
- virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& pictures) OVERRIDE;
- virtual void ReusePictureBuffer(int32_t picture_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool CanDecodeOnIOThread() OVERRIDE;
+ bool Initialize(media::VideoCodecProfile profile, Client* client) override;
+ void Decode(const media::BitstreamBuffer& bitstream) override;
+ void AssignPictureBuffers(
+ const std::vector<media::PictureBuffer>& pictures) override;
+ void ReusePictureBuffer(int32_t picture_id) override;
+ void Flush() override;
+ void Reset() override;
+ void Destroy() override;
+ bool CanDecodeOnIOThread() override;
+
+ // Called by OutputThunk() when VideoToolbox finishes decoding a frame.
+ void Output(
+ int32_t bitstream_id,
+ OSStatus status,
+ CVImageBufferRef image_buffer);
private:
- scoped_refptr<base::MessageLoopProxy> loop_proxy_;
+ struct DecodedFrame {
+ DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer);
+ ~DecodedFrame();
+
+ int32_t bitstream_id;
+ base::ScopedCFTypeRef<CVImageBufferRef> image_buffer;
+ };
+
+ // Actions are the possible types of pending operations, which are queued
+ // by Flush(), Reset(), and Destroy().
+ enum Action {
+ ACTION_FLUSH,
+ ACTION_RESET,
+ ACTION_DESTROY
+ };
+
+ // PendingActions contain the |bitstream_id| of a frame that, once decoded and
+ // sent, a particular |action| should be completed at.
+ struct PendingAction {
+ PendingAction(Action action, int32_t bitstream_id);
+ ~PendingAction();
+
+ Action action;
+ int32_t bitstream_id;
+ };
+
+ // Methods for interacting with VideoToolbox. Run on |decoder_thread_|.
+ bool ConfigureDecoder(
+ const std::vector<const uint8_t*>& nalu_data_ptrs,
+ const std::vector<size_t>& nalu_data_sizes);
+ void DecodeTask(const media::BitstreamBuffer&);
+ void FlushTask();
+ void DropBitstream(int32_t bitstream_id);
+
+ // Methods for interacting with |client_|. Run on |gpu_task_runner_|.
+ void OutputTask(DecodedFrame frame);
+ void NotifyError(Error error);
+
+ // Send decoded frames up to and including |up_to_bitstream_id|, and return
+ // the last sent |bitstream_id|.
+ int32_t SendPictures(int32_t up_to_bitstream_id);
+
+ // Internal helper for SendPictures(): Drop frames with no image data up to
+ // a particular bitstream ID, so that if there is still a frame in the queue
+ // when this function returns, it is guaranteed to have image data, and thus
+ // it is time to set up the GPU context. Returns the last bitstream ID that
+ // was dropped, or |last_sent_bitstream_id| if no frames were dropped.
+ int32_t ProcessDroppedFrames(
+ int32_t last_sent_bitstream_id,
+ int32_t up_to_bitstream_id);
+
+ // Internal helper for SendPictures(): Check if the next frame has a size
+ // different from the current picture buffers, and request new ones if so.
+ void ProcessSizeChangeIfNeeded();
+
+ // Since VideoToolbox has no reset feature (only flush), and the VDA API
+ // allows Decode() and Flush() calls during a reset operation, it's possible
+ // to have multiple pending actions at once. We handle the fully general case
+ // of an arbitrary sequence of pending actions (in reality, there should
+ // probably be at most one reset and one flush at a time).
+ void QueueAction(Action action);
+
+ // Process queued decoded frames, usually by sending them (unless there
+ // is a pending ACTION_RESET or ACTION_DESTROY, in which case they are
+ // dropped), completing queued actions along the way.
+ void ProcessDecodedFrames();
+
+ // Complete a particular action, by eg. calling NotifyFlushDone().
+ // Warning: Deletes |this| if |action| is ACTION_DESTROY.
+ void CompleteAction(Action action);
+
+ // Complete all actions pending for a particular |bitstream_id|.
+ // Warning: Do not call if there is a pending ACTION_DESTROY.
+ void CompleteActions(int32_t bitstream_id);
+
+ //
+ // GPU thread state.
+ //
CGLContextObj cgl_context_;
+ base::Callback<bool(void)> make_context_current_;
media::VideoDecodeAccelerator::Client* client_;
- // Member variables should appear before the WeakPtrFactory, to ensure
- // that any WeakPtrs to Controller are invalidated before its members
- // variable's destructors are executed, rendering them invalid.
+ // client_->NotifyError() called.
+ bool has_error_;
+
+ // Size of assigned picture buffers.
+ gfx::Size picture_size_;
+
+ // Queue of actions so that we can quickly discover what the next action will
+ // be; this is useful because we are dropping all frames when the next action
+ // is ACTION_RESET or ACTION_DESTROY.
+ std::queue<PendingAction> pending_actions_;
+
+ // Queue of bitstreams that have not yet been decoded. This is mostly needed
+ // to be sure we free them all in Destroy().
+ std::queue<int32_t> pending_bitstream_ids_;
+
+ // All picture buffers assigned to us. Used to check if reused picture buffers
+ // should be added back to the available list or released. (They are not
+ // released immediately because we need the reuse event to free the binding.)
+ std::set<int32_t> assigned_picture_ids_;
+
+ // Texture IDs of assigned pictures.
+ std::map<int32_t, uint32_t> texture_ids_;
+
+ // Pictures ready to be rendered to.
+ std::vector<int32_t> available_picture_ids_;
+
+ // Decoded frames ready to render.
+ std::queue<DecodedFrame> decoded_frames_;
+
+ // Image buffers kept alive while they are bound to pictures.
+ std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_;
+
+ //
+ // Decoder thread state.
+ //
+ VTDecompressionOutputCallbackRecord callback_;
+ base::ScopedCFTypeRef<CMFormatDescriptionRef> format_;
+ base::ScopedCFTypeRef<VTDecompressionSessionRef> session_;
+ media::H264Parser parser_;
+
+ std::vector<uint8_t> last_sps_;
+ std::vector<uint8_t> last_spsext_;
+ std::vector<uint8_t> last_pps_;
+
+ //
+ // Shared state (set up and torn down on GPU thread).
+ //
+ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
+
+ // This WeakPtrFactory does not need to be last as its pointers are bound to
+ // the same thread it is destructed on (the GPU thread).
base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_;
+ // Declared last to ensure that all decoder thread tasks complete before any
+ // state is destructed.
+ base::Thread decoder_thread_;
+
DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator);
};
diff --git a/chromium/content/common/gpu/null_transport_surface.cc b/chromium/content/common/gpu/null_transport_surface.cc
new file mode 100644
index 00000000000..ebcea853a67
--- /dev/null
+++ b/chromium/content/common/gpu/null_transport_surface.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2014 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 "content/common/gpu/null_transport_surface.h"
+
+#include "base/command_line.h"
+#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/gpu_channel_manager.h"
+#include "content/common/gpu/gpu_command_buffer_stub.h"
+#include "content/public/common/content_switches.h"
+#include "gpu/command_buffer/service/context_group.h"
+
+namespace content {
+
+NullTransportSurface::NullTransportSurface(
+ GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ const gfx::GLSurfaceHandle& handle)
+ : PassThroughImageTransportSurface(manager,
+ stub,
+ manager->GetDefaultOffscreenSurface()),
+ parent_client_id_(handle.parent_client_id) {
+}
+
+NullTransportSurface::~NullTransportSurface() {
+}
+
+bool NullTransportSurface::Initialize() {
+ if (!surface())
+ return false;
+
+ if (!PassThroughImageTransportSurface::Initialize())
+ return false;
+
+ GpuChannel* parent_channel =
+ GetHelper()->manager()->LookupChannel(parent_client_id_);
+ if (parent_channel) {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
+ GetHelper()->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
+ }
+
+ return true;
+}
+
+void NullTransportSurface::Destroy() {
+ // Do not destroy |surface_| since we use the shared offscreen surface.
+}
+
+bool NullTransportSurface::SwapBuffers() {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool NullTransportSurface::PostSubBuffer(
+ int x, int y, int width, int height) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void NullTransportSurface::SendVSyncUpdateIfAvailable() {
+ NOTREACHED();
+}
+
+bool NullTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
+ // Override PassThroughImageTransportSurface default behavior which
+ // sets the swap interval.
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/null_transport_surface.h b/chromium/content/common/gpu/null_transport_surface.h
new file mode 100644
index 00000000000..53f86fcc06e
--- /dev/null
+++ b/chromium/content/common/gpu/null_transport_surface.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2014 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 CONTENT_COMMON_GPU_NULL_TRANSPORT_SURFACE_H_
+#define CONTENT_COMMON_GPU_NULL_TRANSPORT_SURFACE_H_
+
+#include "base/basictypes.h"
+#include "content/common/gpu/image_transport_surface.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace content {
+
+// Used when the GPU process is not involved in frame transport, but frame
+// resources are exchanged between client and target directly (such as in
+// delegated rendering).
+class NullTransportSurface : public PassThroughImageTransportSurface {
+ public:
+ NullTransportSurface(GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ const gfx::GLSurfaceHandle& handle);
+
+ // gfx::GLSurfaceAdapter implementation.
+ bool Initialize() override;
+ void Destroy() override;
+ bool SwapBuffers() override;
+ bool PostSubBuffer(int x, int y, int width, int height) override;
+ bool OnMakeCurrent(gfx::GLContext* context) override;
+
+ protected:
+ ~NullTransportSurface() override;
+
+ void SendVSyncUpdateIfAvailable() override;
+
+ private:
+ uint32 parent_client_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullTransportSurface);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_NULL_TRANSPORT_SURFACE_H_
diff --git a/chromium/content/common/gpu/stream_texture_android.cc b/chromium/content/common/gpu/stream_texture_android.cc
index 83b471b583c..eb7f3bbe32b 100644
--- a/chromium/content/common/gpu/stream_texture_android.cc
+++ b/chromium/content/common/gpu/stream_texture_android.cc
@@ -53,7 +53,7 @@ bool StreamTexture::Create(
GL_UNSIGNED_BYTE,
true);
texture_manager->SetLevelImage(
- texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image);
+ texture, GL_TEXTURE_EXTERNAL_OES, 0, gl_image.get());
return true;
}
@@ -95,7 +95,7 @@ void StreamTexture::OnWillDestroyStub() {
surface_texture_ = NULL;
}
-void StreamTexture::Destroy() {
+void StreamTexture::Destroy(bool have_context) {
NOTREACHED();
}
@@ -131,7 +131,7 @@ void StreamTexture::WillUseTexImage() {
const gpu::gles2::TextureUnit& active_unit =
state->texture_units[state->active_texture_unit];
glBindTexture(GL_TEXTURE_EXTERNAL_OES,
- active_unit.bound_texture_external_oes
+ active_unit.bound_texture_external_oes.get()
? active_unit.bound_texture_external_oes->service_id()
: 0);
}
@@ -202,4 +202,17 @@ void StreamTexture::ReleaseTexImage(unsigned target) {
NOTREACHED();
}
+bool StreamTexture::CopyTexImage(unsigned target) {
+ return false;
+}
+
+bool StreamTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+ int z_order,
+ gfx::OverlayTransform transform,
+ const gfx::Rect& bounds_rect,
+ const gfx::RectF& crop_rect) {
+ NOTREACHED();
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/stream_texture_android.h b/chromium/content/common/gpu/stream_texture_android.h
index ce8f405a036..066d4faa727 100644
--- a/chromium/content/common/gpu/stream_texture_android.h
+++ b/chromium/content/common/gpu/stream_texture_android.h
@@ -33,23 +33,29 @@ class StreamTexture : public gfx::GLImage,
virtual ~StreamTexture();
// gfx::GLImage implementation:
- virtual void Destroy() OVERRIDE;
- virtual gfx::Size GetSize() OVERRIDE;
- virtual bool BindTexImage(unsigned target) OVERRIDE;
- virtual void ReleaseTexImage(unsigned target) OVERRIDE;
- virtual void WillUseTexImage() OVERRIDE;
- virtual void DidUseTexImage() OVERRIDE {}
- virtual void WillModifyTexImage() OVERRIDE {}
- virtual void DidModifyTexImage() OVERRIDE {}
+ virtual void Destroy(bool have_context) override;
+ virtual gfx::Size GetSize() override;
+ virtual bool BindTexImage(unsigned target) override;
+ virtual void ReleaseTexImage(unsigned target) override;
+ virtual bool CopyTexImage(unsigned target) override;
+ virtual void WillUseTexImage() override;
+ virtual void DidUseTexImage() override {}
+ virtual void WillModifyTexImage() override {}
+ virtual void DidModifyTexImage() override {}
+ virtual bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
+ int z_order,
+ gfx::OverlayTransform transform,
+ const gfx::Rect& bounds_rect,
+ const gfx::RectF& crop_rect) override;
// GpuCommandBufferStub::DestructionObserver implementation.
- virtual void OnWillDestroyStub() OVERRIDE;
+ virtual void OnWillDestroyStub() override;
// Called when a new frame is available for the SurfaceTexture.
void OnFrameAvailable();
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
// IPC message handlers:
void OnStartListening();
diff --git a/chromium/content/common/gpu/surface_handle_types_mac.cc b/chromium/content/common/gpu/surface_handle_types_mac.cc
new file mode 100644
index 00000000000..ef7254241da
--- /dev/null
+++ b/chromium/content/common/gpu/surface_handle_types_mac.cc
@@ -0,0 +1,53 @@
+// Copyright 2014 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 "content/common/gpu/surface_handle_types_mac.h"
+
+#include "base/logging.h"
+
+namespace content {
+namespace {
+
+// The type of the handle is stored in the upper 64 bits.
+const uint64 kTypeMask = 0xFFFFFFFFull << 32;
+
+const uint64 kTypeIOSurface = 0x01010101ull << 32;
+const uint64 kTypeCAContext = 0x02020202ull << 32;
+
+// To make it a bit less likely that we'll just cast off the top bits of the
+// handle to get the ID, XOR lower bits with a type-specific mask.
+const uint32 kXORMaskIOSurface = 0x01010101;
+const uint32 kXORMaskCAContext = 0x02020202;
+
+} // namespace
+
+SurfaceHandleType GetSurfaceHandleType(uint64 surface_handle) {
+ switch(surface_handle & kTypeMask) {
+ case kTypeIOSurface:
+ return kSurfaceHandleTypeIOSurface;
+ case kTypeCAContext:
+ return kSurfaceHandleTypeCAContext;
+ }
+ return kSurfaceHandleTypeInvalid;
+}
+
+IOSurfaceID IOSurfaceIDFromSurfaceHandle(uint64 surface_handle) {
+ DCHECK_EQ(kSurfaceHandleTypeIOSurface, GetSurfaceHandleType(surface_handle));
+ return static_cast<uint32>(surface_handle) ^ kXORMaskIOSurface;
+}
+
+CAContextID CAContextIDFromSurfaceHandle(uint64 surface_handle) {
+ DCHECK_EQ(kSurfaceHandleTypeCAContext, GetSurfaceHandleType(surface_handle));
+ return static_cast<uint32>(surface_handle) ^ kXORMaskCAContext;
+}
+
+uint64 SurfaceHandleFromIOSurfaceID(IOSurfaceID io_surface_id) {
+ return kTypeIOSurface | (io_surface_id ^ kXORMaskIOSurface);
+}
+
+uint64 SurfaceHandleFromCAContextID(CAContextID ca_context_id) {
+ return kTypeCAContext | (ca_context_id ^ kXORMaskCAContext);
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/surface_handle_types_mac.h b/chromium/content/common/gpu/surface_handle_types_mac.h
new file mode 100644
index 00000000000..8432017377a
--- /dev/null
+++ b/chromium/content/common/gpu/surface_handle_types_mac.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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 CONTENT_COMMON_GPU_SURFACE_HANDLE_TYPES_MAC_H_
+#define CONTENT_COMMON_GPU_SURFACE_HANDLE_TYPES_MAC_H_
+
+#include <IOSurface/IOSurface.h>
+#include <OpenGL/CGLIOSurface.h>
+
+#include "base/basictypes.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+
+namespace content {
+
+// The surface handle passed between the GPU and browser process may refer to
+// an IOSurface or a CAContext. These helper functions must be used to identify
+// and translate between the types.
+enum SurfaceHandleType {
+ kSurfaceHandleTypeInvalid,
+ kSurfaceHandleTypeIOSurface,
+ kSurfaceHandleTypeCAContext,
+};
+
+SurfaceHandleType GetSurfaceHandleType(uint64 surface_handle);
+
+CAContextID CAContextIDFromSurfaceHandle(uint64 surface_handle);
+IOSurfaceID IOSurfaceIDFromSurfaceHandle(uint64 surface_handle);
+
+uint64 SurfaceHandleFromIOSurfaceID(IOSurfaceID io_surface_id);
+uint64 SurfaceHandleFromCAContextID(CAContextID ca_context_id);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_HANDLE_TYPES_MAC_H_
diff --git a/chromium/content/common/gpu/sync_point_manager.cc b/chromium/content/common/gpu/sync_point_manager.cc
index 5aa4b7e8e8c..fd5fa6a02f0 100644
--- a/chromium/content/common/gpu/sync_point_manager.cc
+++ b/chromium/content/common/gpu/sync_point_manager.cc
@@ -46,7 +46,11 @@ void SyncPointManager::RetireSyncPoint(uint32 sync_point) {
{
base::AutoLock lock(lock_);
SyncPointMap::iterator it = sync_point_map_.find(sync_point);
- DCHECK(it != sync_point_map_.end());
+ if (it == sync_point_map_.end()) {
+ LOG(ERROR) << "Attempted to retire sync point that"
+ " didn't exist or was already retired.";
+ return;
+ }
list.swap(it->second);
sync_point_map_.erase(it);
}
diff --git a/chromium/content/common/gpu/texture_image_transport_surface.cc b/chromium/content/common/gpu/texture_image_transport_surface.cc
deleted file mode 100644
index 0ab94e3ed75..00000000000
--- a/chromium/content/common/gpu/texture_image_transport_surface.cc
+++ /dev/null
@@ -1,459 +0,0 @@
-// Copyright (c) 2012 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 "content/common/gpu/texture_image_transport_surface.h"
-
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/sync_point_manager.h"
-#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/service/context_group.h"
-#include "gpu/command_buffer/service/gpu_scheduler.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "ui/gl/scoped_binders.h"
-
-using gpu::gles2::ContextGroup;
-using gpu::gles2::GLES2Decoder;
-using gpu::gles2::MailboxManager;
-using gpu::gles2::Texture;
-using gpu::gles2::TextureManager;
-using gpu::gles2::TextureRef;
-using gpu::Mailbox;
-
-namespace content {
-namespace {
-
-bool IsContextValid(ImageTransportHelper* helper) {
- return helper->stub()->decoder()->GetGLContext()->IsCurrent(NULL);
-}
-
-} // namespace
-
-TextureImageTransportSurface::TextureImageTransportSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle)
- : fbo_id_(0),
- current_size_(1, 1),
- scale_factor_(1.f),
- stub_destroyed_(false),
- backbuffer_suggested_allocation_(true),
- frontbuffer_suggested_allocation_(true),
- handle_(handle),
- is_swap_buffers_pending_(false),
- did_unschedule_(false) {
- helper_.reset(new ImageTransportHelper(this,
- manager,
- stub,
- gfx::kNullPluginWindow));
-}
-
-TextureImageTransportSurface::~TextureImageTransportSurface() {
- DCHECK(stub_destroyed_);
- Destroy();
-}
-
-bool TextureImageTransportSurface::Initialize() {
- mailbox_manager_ =
- helper_->stub()->decoder()->GetContextGroup()->mailbox_manager();
-
- GpuChannelManager* manager = helper_->manager();
- surface_ = manager->GetDefaultOffscreenSurface();
- if (!surface_.get())
- return false;
-
- if (!helper_->Initialize())
- return false;
-
- GpuChannel* parent_channel = manager->LookupChannel(handle_.parent_client_id);
- if (parent_channel) {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
- helper_->SetPreemptByFlag(parent_channel->GetPreemptionFlag());
- }
-
- return true;
-}
-
-void TextureImageTransportSurface::Destroy() {
- if (surface_.get())
- surface_ = NULL;
-
- helper_->Destroy();
-}
-
-bool TextureImageTransportSurface::DeferDraws() {
- // The command buffer hit a draw/clear command that could clobber the
- // texture in use by the UI compositor. If a Swap is pending, abort
- // processing of the command by returning true and unschedule until the Swap
- // Ack arrives.
- DCHECK(!did_unschedule_);
- if (is_swap_buffers_pending_) {
- did_unschedule_ = true;
- helper_->SetScheduled(false);
- return true;
- }
- return false;
-}
-
-bool TextureImageTransportSurface::IsOffscreen() {
- return true;
-}
-
-unsigned int TextureImageTransportSurface::GetBackingFrameBufferObject() {
- DCHECK(IsContextValid(helper_.get()));
- if (!fbo_id_) {
- glGenFramebuffersEXT(1, &fbo_id_);
- glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_id_);
- helper_->stub()->AddDestructionObserver(this);
- CreateBackTexture();
- }
-
- return fbo_id_;
-}
-
-bool TextureImageTransportSurface::SetBackbufferAllocation(bool allocation) {
- DCHECK(!is_swap_buffers_pending_);
- if (backbuffer_suggested_allocation_ == allocation)
- return true;
- backbuffer_suggested_allocation_ = allocation;
-
- if (backbuffer_suggested_allocation_) {
- DCHECK(!backbuffer_.get());
- CreateBackTexture();
- } else {
- ReleaseBackTexture();
- }
-
- return true;
-}
-
-void TextureImageTransportSurface::SetFrontbufferAllocation(bool allocation) {
- if (frontbuffer_suggested_allocation_ == allocation)
- return;
- frontbuffer_suggested_allocation_ = allocation;
-
- // If a swapbuffers is in flight, wait for the ack before releasing the front
- // buffer:
- // - we don't know yet which texture the browser will want to keep
- // - we want to ensure we don't destroy a texture that is in flight before the
- // browser got a reference on it.
- if (!frontbuffer_suggested_allocation_ &&
- !is_swap_buffers_pending_ &&
- helper_->MakeCurrent()) {
- ReleaseFrontTexture();
- }
-}
-
-void* TextureImageTransportSurface::GetShareHandle() {
- return GetHandle();
-}
-
-void* TextureImageTransportSurface::GetDisplay() {
- return surface_.get() ? surface_->GetDisplay() : NULL;
-}
-
-void* TextureImageTransportSurface::GetConfig() {
- return surface_.get() ? surface_->GetConfig() : NULL;
-}
-
-void TextureImageTransportSurface::OnResize(gfx::Size size,
- float scale_factor) {
- DCHECK_GE(size.width(), 1);
- DCHECK_GE(size.height(), 1);
- current_size_ = size;
- scale_factor_ = scale_factor;
- if (backbuffer_suggested_allocation_)
- CreateBackTexture();
-}
-
-void TextureImageTransportSurface::OnWillDestroyStub() {
- bool have_context = IsContextValid(helper_.get());
- helper_->stub()->RemoveDestructionObserver(this);
-
- // We are losing the stub owning us, this is our last chance to clean up the
- // resources we allocated in the stub's context.
- if (have_context) {
- ReleaseBackTexture();
- ReleaseFrontTexture();
- } else {
- backbuffer_ = NULL;
- back_mailbox_ = Mailbox();
- frontbuffer_ = NULL;
- front_mailbox_ = Mailbox();
- }
-
- if (fbo_id_ && have_context) {
- glDeleteFramebuffersEXT(1, &fbo_id_);
- CHECK_GL_ERROR();
- }
- fbo_id_ = 0;
-
- stub_destroyed_ = true;
-}
-
-void TextureImageTransportSurface::SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- for (size_t i = 0; i < latency_info.size(); i++)
- latency_info_.push_back(latency_info[i]);
-}
-
-void TextureImageTransportSurface::WakeUpGpu() {
- NOTIMPLEMENTED();
-}
-
-bool TextureImageTransportSurface::SwapBuffers() {
- DCHECK(IsContextValid(helper_.get()));
- DCHECK(backbuffer_suggested_allocation_);
-
- if (!frontbuffer_suggested_allocation_)
- return true;
-
- if (!backbuffer_.get()) {
- LOG(ERROR) << "Swap without valid backing.";
- return true;
- }
-
- DCHECK(backbuffer_size() == current_size_);
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
- params.size = backbuffer_size();
- params.scale_factor = scale_factor_;
- params.mailbox = back_mailbox_;
-
- glFlush();
-
- params.latency_info.swap(latency_info_);
- helper_->SendAcceleratedSurfaceBuffersSwapped(params);
-
- DCHECK(!is_swap_buffers_pending_);
- is_swap_buffers_pending_ = true;
- return true;
-}
-
-bool TextureImageTransportSurface::PostSubBuffer(
- int x, int y, int width, int height) {
- DCHECK(IsContextValid(helper_.get()));
- DCHECK(backbuffer_suggested_allocation_);
- if (!frontbuffer_suggested_allocation_)
- return true;
- const gfx::Rect new_damage_rect(x, y, width, height);
- DCHECK(gfx::Rect(gfx::Point(), current_size_).Contains(new_damage_rect));
-
- // An empty damage rect is a successful no-op.
- if (new_damage_rect.IsEmpty())
- return true;
-
- if (!backbuffer_.get()) {
- LOG(ERROR) << "Swap without valid backing.";
- return true;
- }
-
- DCHECK(current_size_ == backbuffer_size());
- GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params;
- params.surface_size = backbuffer_size();
- params.surface_scale_factor = scale_factor_;
- params.x = x;
- params.y = y;
- params.width = width;
- params.height = height;
- params.mailbox = back_mailbox_;
-
- glFlush();
-
- params.latency_info.swap(latency_info_);
- helper_->SendAcceleratedSurfacePostSubBuffer(params);
-
- DCHECK(!is_swap_buffers_pending_);
- is_swap_buffers_pending_ = true;
- return true;
-}
-
-bool TextureImageTransportSurface::SupportsPostSubBuffer() {
- return true;
-}
-
-gfx::Size TextureImageTransportSurface::GetSize() {
- return current_size_;
-}
-
-void* TextureImageTransportSurface::GetHandle() {
- return surface_.get() ? surface_->GetHandle() : NULL;
-}
-
-unsigned TextureImageTransportSurface::GetFormat() {
- return surface_.get() ? surface_->GetFormat() : 0;
-}
-
-void TextureImageTransportSurface::OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
- if (params.sync_point == 0) {
- BufferPresentedImpl(params.mailbox);
- } else {
- helper_->manager()->sync_point_manager()->AddSyncPointCallback(
- params.sync_point,
- base::Bind(&TextureImageTransportSurface::BufferPresentedImpl,
- this,
- params.mailbox));
- }
-}
-
-void TextureImageTransportSurface::BufferPresentedImpl(const Mailbox& mailbox) {
- DCHECK(is_swap_buffers_pending_);
- is_swap_buffers_pending_ = false;
-
- // When we wait for a sync point, we may get called back after the stub is
- // destroyed. In that case there's no need to do anything with the returned
- // mailbox.
- if (stub_destroyed_)
- return;
-
- // We should not have allowed the backbuffer to be discarded while the ack
- // was pending.
- DCHECK(backbuffer_suggested_allocation_);
- DCHECK(backbuffer_.get());
-
- bool swap = true;
- if (!mailbox.IsZero()) {
- if (mailbox == back_mailbox_) {
- // The browser has skipped the frame to unblock the GPU process, waiting
- // for one of the right size, and returned the back buffer, so don't swap.
- swap = false;
- }
- }
- if (swap) {
- std::swap(backbuffer_, frontbuffer_);
- std::swap(back_mailbox_, front_mailbox_);
- }
-
- // We're relying on the fact that the parent context is
- // finished with its context when it inserts the sync point that
- // triggers this callback.
- if (helper_->MakeCurrent()) {
- if (frontbuffer_.get() && !frontbuffer_suggested_allocation_)
- ReleaseFrontTexture();
- if (!backbuffer_.get() || backbuffer_size() != current_size_)
- CreateBackTexture();
- else
- AttachBackTextureToFBO();
- }
-
- // Even if MakeCurrent fails, schedule anyway, to trigger the lost context
- // logic.
- if (did_unschedule_) {
- did_unschedule_ = false;
- helper_->SetScheduled(true);
- }
-}
-
-void TextureImageTransportSurface::ReleaseBackTexture() {
- DCHECK(IsContextValid(helper_.get()));
- backbuffer_ = NULL;
- back_mailbox_ = Mailbox();
- glFlush();
- CHECK_GL_ERROR();
-}
-
-void TextureImageTransportSurface::ReleaseFrontTexture() {
- DCHECK(IsContextValid(helper_.get()));
- frontbuffer_ = NULL;
- front_mailbox_ = Mailbox();
- glFlush();
- CHECK_GL_ERROR();
- helper_->SendAcceleratedSurfaceRelease();
-}
-
-void TextureImageTransportSurface::CreateBackTexture() {
- DCHECK(IsContextValid(helper_.get()));
- // If |is_swap_buffers_pending| we are waiting for our backbuffer
- // in the mailbox, so we shouldn't be reallocating it now.
- DCHECK(!is_swap_buffers_pending_);
-
- if (backbuffer_.get() && backbuffer_size() == current_size_)
- return;
-
- VLOG(1) << "Allocating new backbuffer texture";
-
- GLES2Decoder* decoder = helper_->stub()->decoder();
- TextureManager* texture_manager =
- decoder->GetContextGroup()->texture_manager();
- if (!backbuffer_.get()) {
- back_mailbox_ = gpu::Mailbox::Generate();
- GLuint service_id;
- glGenTextures(1, &service_id);
- backbuffer_ = TextureRef::Create(texture_manager, 0, service_id);
- texture_manager->SetTarget(backbuffer_.get(), GL_TEXTURE_2D);
- Texture* texture = texture_manager->Produce(backbuffer_.get());
- mailbox_manager_->ProduceTexture(GL_TEXTURE_2D, back_mailbox_, texture);
- }
-
- {
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D,
- backbuffer_->service_id());
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
- current_size_.width(), current_size_.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- gpu::gles2::ErrorState* error_state = decoder->GetErrorState();
- texture_manager->SetParameteri("Backbuffer",
- error_state,
- backbuffer_.get(),
- GL_TEXTURE_MIN_FILTER,
- GL_LINEAR);
- texture_manager->SetParameteri("Backbuffer",
- error_state,
- backbuffer_.get(),
- GL_TEXTURE_MAG_FILTER,
- GL_LINEAR);
- texture_manager->SetParameteri("Backbuffer",
- error_state,
- backbuffer_.get(),
- GL_TEXTURE_WRAP_S,
- GL_CLAMP_TO_EDGE);
- texture_manager->SetParameteri("Backbuffer",
- error_state,
- backbuffer_.get(),
- GL_TEXTURE_WRAP_T,
- GL_CLAMP_TO_EDGE);
- texture_manager->SetLevelInfo(backbuffer_.get(),
- GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- current_size_.width(),
- current_size_.height(),
- 1,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- true);
- DCHECK(texture_manager->CanRender(backbuffer_.get()));
- CHECK_GL_ERROR();
- }
-
- AttachBackTextureToFBO();
-}
-
-void TextureImageTransportSurface::AttachBackTextureToFBO() {
- DCHECK(IsContextValid(helper_.get()));
- DCHECK(backbuffer_.get());
- gfx::ScopedFrameBufferBinder fbo_binder(fbo_id_);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- backbuffer_->service_id(),
- 0);
- CHECK_GL_ERROR();
-
-#ifndef NDEBUG
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- DLOG(FATAL) << "Framebuffer incomplete: " << status;
- }
-#endif
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/texture_image_transport_surface.h b/chromium/content/common/gpu/texture_image_transport_surface.h
deleted file mode 100644
index dec6b35e982..00000000000
--- a/chromium/content/common/gpu/texture_image_transport_surface.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_COMMON_GPU_TEXTURE_IMAGE_TRANSPORT_SURFACE_H_
-#define CONTENT_COMMON_GPU_TEXTURE_IMAGE_TRANSPORT_SURFACE_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/image_transport_surface.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/service/texture_manager.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface.h"
-
-namespace content {
-class GpuChannelManager;
-
-class TextureImageTransportSurface
- : public ImageTransportSurface,
- public GpuCommandBufferStub::DestructionObserver,
- public gfx::GLSurface {
- public:
- TextureImageTransportSurface(GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle);
-
- // gfx::GLSurface implementation.
- virtual bool Initialize() OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual bool DeferDraws() OVERRIDE;
- virtual bool IsOffscreen() OVERRIDE;
- virtual bool SwapBuffers() OVERRIDE;
- virtual gfx::Size GetSize() OVERRIDE;
- virtual void* GetHandle() OVERRIDE;
- virtual unsigned GetFormat() OVERRIDE;
- virtual bool SupportsPostSubBuffer() OVERRIDE;
- virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
- virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
- virtual bool SetBackbufferAllocation(bool allocated) OVERRIDE;
- virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
- virtual void* GetShareHandle() OVERRIDE;
- virtual void* GetDisplay() OVERRIDE;
- virtual void* GetConfig() OVERRIDE;
-
- protected:
- // ImageTransportSurface implementation.
- virtual void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
- virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
- virtual void SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) OVERRIDE;
- virtual void WakeUpGpu() OVERRIDE;
-
- // GpuCommandBufferStub::DestructionObserver implementation.
- virtual void OnWillDestroyStub() OVERRIDE;
-
- private:
-
- gfx::Size backbuffer_size() const {
- DCHECK(backbuffer_.get());
- GLsizei width = 0;
- GLsizei height = 0;
- backbuffer_->texture()->GetLevelSize(GL_TEXTURE_2D, 0, &width, &height);
- return gfx::Size(width, height);
- }
-
- virtual ~TextureImageTransportSurface();
- void CreateBackTexture();
- void AttachBackTextureToFBO();
- void ReleaseBackTexture();
- void ReleaseFrontTexture();
- void BufferPresentedImpl(const gpu::Mailbox& mailbox_name);
-
- // The framebuffer that represents this surface (service id). Allocated lazily
- // in OnMakeCurrent.
- uint32 fbo_id_;
-
- // The current backbuffer.
- scoped_refptr<gpu::gles2::TextureRef> backbuffer_;
- scoped_refptr<gpu::gles2::TextureRef> frontbuffer_;
-
- // The mailbox name for the current backbuffer texture. Needs to be unique per
- // GL texture and is invalid while service_id is zero.
- gpu::Mailbox back_mailbox_;
- gpu::Mailbox front_mailbox_;
-
- // The current size of the GLSurface. Used to disambiguate from the current
- // texture size which might be outdated (since we use two buffers).
- gfx::Size current_size_;
- float scale_factor_;
-
- // Whether or not the command buffer stub has been destroyed.
- bool stub_destroyed_;
-
- bool backbuffer_suggested_allocation_;
- bool frontbuffer_suggested_allocation_;
-
- scoped_ptr<ImageTransportHelper> helper_;
- gfx::GLSurfaceHandle handle_;
-
- // The offscreen surface used to make the context current. However note that
- // the actual rendering is always redirected to an FBO.
- scoped_refptr<gfx::GLSurface> surface_;
-
- // Whether a SwapBuffers is pending.
- bool is_swap_buffers_pending_;
-
- // Whether we unscheduled command buffer because of pending SwapBuffers.
- bool did_unschedule_;
-
- // Holds a reference to the mailbox manager for cleanup.
- scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
-
- std::vector<ui::LatencyInfo> latency_info_;
- DISALLOW_COPY_AND_ASSIGN(TextureImageTransportSurface);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_TEXTURE_IMAGE_TRANSPORT_SURFACE_H_
diff --git a/chromium/content/common/handle_enumerator_win.cc b/chromium/content/common/handle_enumerator_win.cc
index 0b8cbe5fd42..981655065d9 100644
--- a/chromium/content/common/handle_enumerator_win.cc
+++ b/chromium/content/common/handle_enumerator_win.cc
@@ -52,7 +52,7 @@ const size_t kMaxHandleNameLength = 1024;
void HandleEnumerator::EnumerateHandles() {
sandbox::HandleTable handles;
std::string process_type =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
base::string16 output = ASCIIToUTF16(process_type);
output.append(ASCIIToUTF16(" process - Handles at shutdown:\n"));
diff --git a/chromium/content/common/host_discardable_shared_memory_manager.cc b/chromium/content/common/host_discardable_shared_memory_manager.cc
new file mode 100644
index 00000000000..c56fd113f59
--- /dev/null
+++ b/chromium/content/common/host_discardable_shared_memory_manager.cc
@@ -0,0 +1,255 @@
+// Copyright 2014 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 "content/common/host_discardable_shared_memory_manager.h"
+
+#include <algorithm>
+
+#include "base/callback.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/trace_event.h"
+#include "base/lazy_instance.h"
+#include "base/numerics/safe_math.h"
+#include "base/strings/string_number_conversions.h"
+
+namespace content {
+namespace {
+
+base::LazyInstance<HostDiscardableSharedMemoryManager>
+ g_discardable_shared_memory_manager = LAZY_INSTANCE_INITIALIZER;
+
+const size_t kDefaultMemoryLimit = 512 * 1024 * 1024;
+
+const int kEnforceMemoryPolicyDelayMs = 1000;
+
+} // namespace
+
+HostDiscardableSharedMemoryManager::MemorySegment::MemorySegment(
+ linked_ptr<base::DiscardableSharedMemory> memory,
+ base::ProcessHandle process_handle)
+ : memory(memory), process_handle(process_handle) {
+}
+
+HostDiscardableSharedMemoryManager::MemorySegment::~MemorySegment() {
+}
+
+HostDiscardableSharedMemoryManager::HostDiscardableSharedMemoryManager()
+ : memory_limit_(kDefaultMemoryLimit),
+ bytes_allocated_(0),
+ memory_pressure_listener_(new base::MemoryPressureListener(
+ base::Bind(&HostDiscardableSharedMemoryManager::OnMemoryPressure,
+ base::Unretained(this)))),
+ enforce_memory_policy_pending_(false),
+ weak_ptr_factory_(this) {
+}
+
+HostDiscardableSharedMemoryManager::~HostDiscardableSharedMemoryManager() {
+}
+
+HostDiscardableSharedMemoryManager*
+HostDiscardableSharedMemoryManager::current() {
+ return g_discardable_shared_memory_manager.Pointer();
+}
+
+scoped_ptr<base::DiscardableSharedMemory>
+HostDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
+ size_t size) {
+ // TODO(reveman): Need to implement this for discardable memory support in
+ // the browser process.
+ NOTIMPLEMENTED();
+ return scoped_ptr<base::DiscardableSharedMemory>();
+}
+
+void HostDiscardableSharedMemoryManager::
+ AllocateLockedDiscardableSharedMemoryForChild(
+ base::ProcessHandle process_handle,
+ size_t size,
+ base::SharedMemoryHandle* shared_memory_handle) {
+ base::AutoLock lock(lock_);
+
+ // Memory usage must be reduced to prevent the addition of |size| from
+ // taking usage above the limit. Usage should be reduced to 0 in cases
+ // where |size| is greater than the limit.
+ size_t limit = 0;
+ // Note: the actual mapped size can be larger than requested and cause
+ // |bytes_allocated_| to temporarily be larger than |memory_limit_|. The
+ // error is minimized by incrementing |bytes_allocated_| with the actual
+ // mapped size rather than |size| below.
+ if (size < memory_limit_)
+ limit = memory_limit_ - size;
+
+ if (bytes_allocated_ > limit)
+ ReduceMemoryUsageUntilWithinLimit(limit);
+
+ linked_ptr<base::DiscardableSharedMemory> memory(
+ new base::DiscardableSharedMemory);
+ if (!memory->CreateAndMap(size)) {
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+
+ if (!memory->ShareToProcess(process_handle, shared_memory_handle)) {
+ LOG(ERROR) << "Cannot share discardable memory segment";
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+
+ base::CheckedNumeric<size_t> checked_bytes_allocated = bytes_allocated_;
+ checked_bytes_allocated += memory->mapped_size();
+ if (!checked_bytes_allocated.IsValid()) {
+ *shared_memory_handle = base::SharedMemory::NULLHandle();
+ return;
+ }
+
+ bytes_allocated_ = checked_bytes_allocated.ValueOrDie();
+ BytesAllocatedChanged(bytes_allocated_);
+
+ segments_.push_back(MemorySegment(memory, process_handle));
+ std::push_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
+
+ if (bytes_allocated_ > memory_limit_)
+ ScheduleEnforceMemoryPolicy();
+}
+
+void HostDiscardableSharedMemoryManager::ProcessRemoved(
+ base::ProcessHandle process_handle) {
+ base::AutoLock lock(lock_);
+
+ size_t bytes_allocated_before_purging = bytes_allocated_;
+ for (auto& segment : segments_) {
+ // Skip segments that belong to a different process.
+ if (segment.process_handle != process_handle)
+ continue;
+
+ size_t size = segment.memory->mapped_size();
+ DCHECK_GE(bytes_allocated_, size);
+
+ // This will unmap the memory segment and drop our reference. The result
+ // is that the memory will be released to the OS if the child process is
+ // no longer referencing it.
+ // Note: We intentionally leave the segment in the vector to avoid
+ // reconstructing the heap. The element will be removed from the heap
+ // when its last usage time is older than all other segments.
+ segment.memory->Close();
+ bytes_allocated_ -= size;
+ }
+
+ if (bytes_allocated_ != bytes_allocated_before_purging)
+ BytesAllocatedChanged(bytes_allocated_);
+}
+
+void HostDiscardableSharedMemoryManager::SetMemoryLimit(size_t limit) {
+ base::AutoLock lock(lock_);
+
+ memory_limit_ = limit;
+ ReduceMemoryUsageUntilWithinMemoryLimit();
+}
+
+void HostDiscardableSharedMemoryManager::EnforceMemoryPolicy() {
+ base::AutoLock lock(lock_);
+
+ enforce_memory_policy_pending_ = false;
+ ReduceMemoryUsageUntilWithinMemoryLimit();
+}
+
+void HostDiscardableSharedMemoryManager::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
+ base::AutoLock lock(lock_);
+
+ switch (memory_pressure_level) {
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+ // Purge everything possible when pressure is critical.
+ ReduceMemoryUsageUntilWithinLimit(0);
+ break;
+ }
+}
+
+void
+HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinMemoryLimit() {
+ if (bytes_allocated_ <= memory_limit_)
+ return;
+
+ ReduceMemoryUsageUntilWithinLimit(memory_limit_);
+ if (bytes_allocated_ > memory_limit_)
+ ScheduleEnforceMemoryPolicy();
+}
+
+void HostDiscardableSharedMemoryManager::ReduceMemoryUsageUntilWithinLimit(
+ size_t limit) {
+ TRACE_EVENT1("renderer_host",
+ "HostDiscardableSharedMemoryManager::"
+ "ReduceMemoryUsageUntilWithinLimit",
+ "bytes_allocated",
+ bytes_allocated_);
+
+ // Usage time of currently locked segments are updated to this time and
+ // we stop eviction attempts as soon as we come across a segment that we've
+ // previously tried to evict but was locked.
+ base::Time current_time = Now();
+
+ lock_.AssertAcquired();
+ size_t bytes_allocated_before_purging = bytes_allocated_;
+ while (!segments_.empty()) {
+ if (bytes_allocated_ <= limit)
+ break;
+
+ // Stop eviction attempts when the LRU segment is currently in use.
+ if (segments_.front().memory->last_known_usage() >= current_time)
+ break;
+
+ std::pop_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
+ MemorySegment segment = segments_.back();
+ segments_.pop_back();
+
+ // Attempt to purge and truncate LRU segment. When successful, as much
+ // memory as possible will be released to the OS. How much memory is
+ // released depends on the platform. The child process should perform
+ // periodic cleanup to ensure that all memory is release within a
+ // reasonable amount of time.
+ if (segment.memory->PurgeAndTruncate(current_time)) {
+ size_t size = segment.memory->mapped_size();
+ DCHECK_GE(bytes_allocated_, size);
+ bytes_allocated_ -= size;
+ continue;
+ }
+
+ // Add memory segment (with updated usage timestamp) back on heap after
+ // failed attempt to purge it.
+ segments_.push_back(segment);
+ std::push_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
+ }
+
+ if (bytes_allocated_ != bytes_allocated_before_purging)
+ BytesAllocatedChanged(bytes_allocated_);
+}
+
+void HostDiscardableSharedMemoryManager::BytesAllocatedChanged(
+ size_t new_bytes_allocated) const {
+ TRACE_COUNTER_ID1(
+ "base", "TotalDiscardableMemoryUsage", this, new_bytes_allocated);
+
+ static const char kTotalDiscardableMemoryUsageKey[] = "total-dm-usage";
+ base::debug::SetCrashKeyValue(kTotalDiscardableMemoryUsageKey,
+ base::Uint64ToString(new_bytes_allocated));
+}
+
+base::Time HostDiscardableSharedMemoryManager::Now() const {
+ return base::Time::Now();
+}
+
+void HostDiscardableSharedMemoryManager::ScheduleEnforceMemoryPolicy() {
+ if (enforce_memory_policy_pending_)
+ return;
+
+ enforce_memory_policy_pending_ = true;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&HostDiscardableSharedMemoryManager::EnforceMemoryPolicy,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(kEnforceMemoryPolicyDelayMs));
+}
+
+} // namespace content
diff --git a/chromium/content/common/host_discardable_shared_memory_manager.h b/chromium/content/common/host_discardable_shared_memory_manager.h
new file mode 100644
index 00000000000..148c4fc3f80
--- /dev/null
+++ b/chromium/content/common/host_discardable_shared_memory_manager.h
@@ -0,0 +1,100 @@
+// Copyright 2014 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 CONTENT_COMMON_HOST_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
+#define CONTENT_COMMON_HOST_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
+
+#include <vector>
+
+#include "base/memory/discardable_memory_shmem_allocator.h"
+#include "base/memory/discardable_shared_memory.h"
+#include "base/memory/linked_ptr.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/memory/shared_memory.h"
+#include "base/memory/weak_ptr.h"
+#include "base/process/process_handle.h"
+#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Implementation of DiscardableMemoryShmemAllocator that allocates and
+// manages discardable memory segments for the browser process and child
+// processes. This class is thread-safe and instances can safely be used
+// on any thread.
+class CONTENT_EXPORT HostDiscardableSharedMemoryManager
+ : public base::DiscardableMemoryShmemAllocator {
+ public:
+ HostDiscardableSharedMemoryManager();
+ ~HostDiscardableSharedMemoryManager() override;
+
+ // Returns a singleton instance.
+ static HostDiscardableSharedMemoryManager* current();
+
+ // Overridden from base::DiscardableMemoryShmemAllocator:
+ scoped_ptr<base::DiscardableSharedMemory>
+ AllocateLockedDiscardableSharedMemory(size_t size) override;
+
+ // This allocates a discardable memory segment for |process_handle|.
+ // A valid shared memory handle is returned on success.
+ void AllocateLockedDiscardableSharedMemoryForChild(
+ base::ProcessHandle process_handle,
+ size_t size,
+ base::SharedMemoryHandle* shared_memory_handle);
+
+ // Call this to notify the manager that child process associated with
+ // |process_handle| has been removed. The manager will use this to release
+ // memory segments allocated for child process to the OS.
+ void ProcessRemoved(base::ProcessHandle process_handle);
+
+ // The maximum number of bytes of memory that may be allocated. This will
+ // cause memory usage to be reduced if currently above |limit|.
+ void SetMemoryLimit(size_t limit);
+
+ // Reduce memory usage if above current memory limit.
+ void EnforceMemoryPolicy();
+
+ private:
+ struct MemorySegment {
+ MemorySegment(linked_ptr<base::DiscardableSharedMemory> memory,
+ base::ProcessHandle process_handle);
+ ~MemorySegment();
+
+ linked_ptr<base::DiscardableSharedMemory> memory;
+ base::ProcessHandle process_handle;
+ };
+
+ static bool CompareMemoryUsageTime(const MemorySegment& a,
+ const MemorySegment& b) {
+ // In this system, LRU memory segment is evicted first.
+ return a.memory->last_known_usage() > b.memory->last_known_usage();
+ }
+
+ void OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
+ void ReduceMemoryUsageUntilWithinMemoryLimit();
+ void ReduceMemoryUsageUntilWithinLimit(size_t limit);
+ void BytesAllocatedChanged(size_t new_bytes_allocated) const;
+
+ // Virtual for tests.
+ virtual base::Time Now() const;
+ virtual void ScheduleEnforceMemoryPolicy();
+
+ base::Lock lock_;
+ // Note: The elements in |segments_| are arranged in such a way that they form
+ // a heap. The LRU memory segment always first.
+ typedef std::vector<MemorySegment> MemorySegmentVector;
+ MemorySegmentVector segments_;
+ size_t memory_limit_;
+ size_t bytes_allocated_;
+ scoped_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+ bool enforce_memory_policy_pending_;
+ base::WeakPtrFactory<HostDiscardableSharedMemoryManager> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(HostDiscardableSharedMemoryManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_HOST_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
diff --git a/chromium/content/common/host_discardable_shared_memory_manager_unittest.cc b/chromium/content/common/host_discardable_shared_memory_manager_unittest.cc
new file mode 100644
index 00000000000..d4c5e0054d6
--- /dev/null
+++ b/chromium/content/common/host_discardable_shared_memory_manager_unittest.cc
@@ -0,0 +1,188 @@
+// Copyright 2014 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 "content/common/host_discardable_shared_memory_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class TestDiscardableSharedMemory : public base::DiscardableSharedMemory {
+ public:
+ TestDiscardableSharedMemory() {}
+
+ explicit TestDiscardableSharedMemory(base::SharedMemoryHandle handle)
+ : DiscardableSharedMemory(handle) {}
+
+ void SetNow(base::Time now) { now_ = now; }
+
+ private:
+ // Overriden from base::DiscardableSharedMemory:
+ base::Time Now() const override { return now_; }
+
+ base::Time now_;
+};
+
+class TestHostDiscardableSharedMemoryManager
+ : public HostDiscardableSharedMemoryManager {
+ public:
+ TestHostDiscardableSharedMemoryManager()
+ : enforce_memory_policy_pending_(false) {}
+
+ void SetNow(base::Time now) { now_ = now; }
+
+ void set_enforce_memory_policy_pending(bool enforce_memory_policy_pending) {
+ enforce_memory_policy_pending_ = enforce_memory_policy_pending;
+ }
+ bool enforce_memory_policy_pending() const {
+ return enforce_memory_policy_pending_;
+ }
+
+ private:
+ // Overriden from HostDiscardableSharedMemoryManager:
+ base::Time Now() const override { return now_; }
+ void ScheduleEnforceMemoryPolicy() override {
+ enforce_memory_policy_pending_ = true;
+ }
+
+ base::Time now_;
+ bool enforce_memory_policy_pending_;
+};
+
+class HostDiscardableSharedMemoryManagerTest : public testing::Test {
+ protected:
+ // Overridden from testing::Test:
+ void SetUp() override {
+ manager_.reset(new TestHostDiscardableSharedMemoryManager);
+ }
+
+ scoped_ptr<TestHostDiscardableSharedMemoryManager> manager_;
+};
+
+TEST_F(HostDiscardableSharedMemoryManagerTest, AllocateForChild) {
+ const int kDataSize = 1024;
+ uint8 data[kDataSize];
+ memset(data, 0x80, kDataSize);
+
+ base::SharedMemoryHandle shared_handle;
+ manager_->AllocateLockedDiscardableSharedMemoryForChild(
+ base::GetCurrentProcessHandle(), kDataSize, &shared_handle);
+ ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle));
+
+ TestDiscardableSharedMemory memory(shared_handle);
+ bool rv = memory.Map(kDataSize);
+ ASSERT_TRUE(rv);
+
+ memcpy(memory.memory(), data, kDataSize);
+ memory.SetNow(base::Time::FromDoubleT(1));
+ memory.Unlock();
+
+ ASSERT_TRUE(memory.Lock());
+ EXPECT_EQ(memcmp(data, memory.memory(), kDataSize), 0);
+ memory.Unlock();
+}
+
+TEST_F(HostDiscardableSharedMemoryManagerTest, Purge) {
+ const int kDataSize = 1024;
+
+ base::SharedMemoryHandle shared_handle1;
+ manager_->AllocateLockedDiscardableSharedMemoryForChild(
+ base::GetCurrentProcessHandle(), kDataSize, &shared_handle1);
+ ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle1));
+
+ TestDiscardableSharedMemory memory1(shared_handle1);
+ bool rv = memory1.Map(kDataSize);
+ ASSERT_TRUE(rv);
+
+ base::SharedMemoryHandle shared_handle2;
+ manager_->AllocateLockedDiscardableSharedMemoryForChild(
+ base::GetCurrentProcessHandle(), kDataSize, &shared_handle2);
+ ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle2));
+
+ TestDiscardableSharedMemory memory2(shared_handle2);
+ rv = memory2.Map(kDataSize);
+ ASSERT_TRUE(rv);
+
+ // Enough memory for both allocations.
+ manager_->SetNow(base::Time::FromDoubleT(1));
+ manager_->SetMemoryLimit(memory1.mapped_size() + memory2.mapped_size());
+
+ memory1.SetNow(base::Time::FromDoubleT(2));
+ memory1.Unlock();
+ memory2.SetNow(base::Time::FromDoubleT(2));
+ memory2.Unlock();
+
+ // Manager should not have to schedule another call to EnforceMemoryPolicy().
+ manager_->SetNow(base::Time::FromDoubleT(3));
+ manager_->EnforceMemoryPolicy();
+ EXPECT_FALSE(manager_->enforce_memory_policy_pending());
+
+ // Memory should still be resident.
+ EXPECT_TRUE(memory1.IsMemoryResident());
+ EXPECT_TRUE(memory2.IsMemoryResident());
+
+ rv = memory1.Lock();
+ EXPECT_TRUE(rv);
+ rv = memory2.Lock();
+ EXPECT_TRUE(rv);
+
+ memory1.SetNow(base::Time::FromDoubleT(4));
+ memory1.Unlock();
+ memory2.SetNow(base::Time::FromDoubleT(5));
+ memory2.Unlock();
+
+ // Just enough memory for one allocation.
+ manager_->SetNow(base::Time::FromDoubleT(6));
+ manager_->SetMemoryLimit(memory2.mapped_size());
+ EXPECT_FALSE(manager_->enforce_memory_policy_pending());
+
+ // LRU allocation should still be resident.
+ EXPECT_FALSE(memory1.IsMemoryResident());
+ EXPECT_TRUE(memory2.IsMemoryResident());
+
+ rv = memory1.Lock();
+ EXPECT_FALSE(rv);
+ rv = memory2.Lock();
+ EXPECT_TRUE(rv);
+}
+
+TEST_F(HostDiscardableSharedMemoryManagerTest, EnforceMemoryPolicy) {
+ const int kDataSize = 1024;
+
+ base::SharedMemoryHandle shared_handle;
+ manager_->AllocateLockedDiscardableSharedMemoryForChild(
+ base::GetCurrentProcessHandle(), kDataSize, &shared_handle);
+ ASSERT_TRUE(base::SharedMemory::IsHandleValid(shared_handle));
+
+ TestDiscardableSharedMemory memory(shared_handle);
+ bool rv = memory.Map(kDataSize);
+ ASSERT_TRUE(rv);
+
+ // Not enough memory for one allocation.
+ manager_->SetNow(base::Time::FromDoubleT(1));
+ manager_->SetMemoryLimit(memory.mapped_size() - 1);
+ // We need to enforce memory policy as our memory usage is currently above
+ // the limit.
+ EXPECT_TRUE(manager_->enforce_memory_policy_pending());
+
+ manager_->set_enforce_memory_policy_pending(false);
+ manager_->SetNow(base::Time::FromDoubleT(2));
+ manager_->EnforceMemoryPolicy();
+ // Still need to enforce memory policy as nothing can be purged.
+ EXPECT_TRUE(manager_->enforce_memory_policy_pending());
+
+ memory.SetNow(base::Time::FromDoubleT(3));
+ memory.Unlock();
+
+ manager_->set_enforce_memory_policy_pending(false);
+ manager_->SetNow(base::Time::FromDoubleT(4));
+ manager_->EnforceMemoryPolicy();
+ // Memory policy should have successfully been enforced.
+ EXPECT_FALSE(manager_->enforce_memory_policy_pending());
+
+ EXPECT_FALSE(memory.Lock());
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/common/host_shared_bitmap_manager.cc b/chromium/content/common/host_shared_bitmap_manager.cc
index ac1478fe5ea..66f721552f9 100644
--- a/chromium/content/common/host_shared_bitmap_manager.cc
+++ b/chromium/content/common/host_shared_bitmap_manager.cc
@@ -187,6 +187,11 @@ void HostSharedBitmapManager::ProcessRemoved(
process_map_.erase(proc_it);
}
+size_t HostSharedBitmapManager::AllocatedBitmapCount() const {
+ base::AutoLock lock(lock_);
+ return handle_map_.size();
+}
+
void HostSharedBitmapManager::FreeSharedMemoryFromMap(
cc::SharedBitmap* bitmap) {
base::AutoLock lock(lock_);
diff --git a/chromium/content/common/host_shared_bitmap_manager.h b/chromium/content/common/host_shared_bitmap_manager.h
index 08245b368b5..71af0e36ec6 100644
--- a/chromium/content/common/host_shared_bitmap_manager.h
+++ b/chromium/content/common/host_shared_bitmap_manager.h
@@ -9,7 +9,6 @@
#include <set>
#include "base/basictypes.h"
-#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/hash.h"
#include "base/memory/ref_counted.h"
@@ -20,18 +19,12 @@
#include "content/common/content_export.h"
namespace BASE_HASH_NAMESPACE {
-#if defined(COMPILER_GCC)
template <>
struct hash<cc::SharedBitmapId> {
size_t operator()(const cc::SharedBitmapId& id) const {
return base::Hash(reinterpret_cast<const char*>(id.name), sizeof(id.name));
}
};
-#elif defined(COMPILER_MSVC)
-inline std::size_t hash_value(const cc::SharedBitmapId& id) {
- return base::Hash(reinterpret_cast<const char*>(id.name), sizeof(id.name));
-}
-#endif // COMPILER
} // namespace BASE_HASH_NAMESPACE
namespace content {
@@ -40,18 +33,18 @@ class BitmapData;
class CONTENT_EXPORT HostSharedBitmapManager : public cc::SharedBitmapManager {
public:
HostSharedBitmapManager();
- virtual ~HostSharedBitmapManager();
+ ~HostSharedBitmapManager() override;
static HostSharedBitmapManager* current();
// cc::SharedBitmapManager implementation.
- virtual scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
- const gfx::Size& size) OVERRIDE;
- virtual scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
+ scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
+ const gfx::Size& size) override;
+ scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
const gfx::Size& size,
- const cc::SharedBitmapId&) OVERRIDE;
- virtual scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
- base::SharedMemory*) OVERRIDE;
+ const cc::SharedBitmapId&) override;
+ scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
+ base::SharedMemory*) override;
void AllocateSharedBitmapForChild(
base::ProcessHandle process_handle,
@@ -65,12 +58,12 @@ class CONTENT_EXPORT HostSharedBitmapManager : public cc::SharedBitmapManager {
void ChildDeletedSharedBitmap(const cc::SharedBitmapId& id);
void ProcessRemoved(base::ProcessHandle process_handle);
- size_t AllocatedBitmapCount() const { return handle_map_.size(); }
+ size_t AllocatedBitmapCount() const;
private:
void FreeSharedMemoryFromMap(cc::SharedBitmap* bitmap);
- base::Lock lock_;
+ mutable base::Lock lock_;
typedef base::hash_map<cc::SharedBitmapId, scoped_refptr<BitmapData> >
BitmapMap;
diff --git a/chromium/content/common/host_shared_bitmap_manager_unittest.cc b/chromium/content/common/host_shared_bitmap_manager_unittest.cc
index ed0ddbab2ae..68456a8f7ba 100644
--- a/chromium/content/common/host_shared_bitmap_manager_unittest.cc
+++ b/chromium/content/common/host_shared_bitmap_manager_unittest.cc
@@ -10,7 +10,7 @@ namespace {
class HostSharedBitmapManagerTest : public testing::Test {
protected:
- virtual void SetUp() { manager_.reset(new HostSharedBitmapManager()); }
+ void SetUp() override { manager_.reset(new HostSharedBitmapManager()); }
scoped_ptr<HostSharedBitmapManager> manager_;
};
diff --git a/chromium/content/common/indexed_db/OWNERS b/chromium/content/common/indexed_db/OWNERS
index c7ad25e64c2..1f0a278156e 100644
--- a/chromium/content/common/indexed_db/OWNERS
+++ b/chromium/content/common/indexed_db/OWNERS
@@ -1,17 +1,17 @@
dgrogan@chromium.org
michaeln@chromium.org
jsbell@chromium.org
-ericu@chromium.org
cmumford@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/indexed_db/indexed_db_key.cc b/chromium/content/common/indexed_db/indexed_db_key.cc
index 12e0730604c..4c553ca4bdf 100644
--- a/chromium/content/common/indexed_db/indexed_db_key.cc
+++ b/chromium/content/common/indexed_db/indexed_db_key.cc
@@ -94,29 +94,6 @@ IndexedDBKey::IndexedDBKey(const base::string16& string)
IndexedDBKey::~IndexedDBKey() {}
-IndexedDBKey::IndexedDBKey(const IndexedDBKey& other)
- : type_(other.type_),
- array_(other.array_),
- binary_(other.binary_),
- string_(other.string_),
- date_(other.date_),
- number_(other.number_),
- size_estimate_(other.size_estimate_) {
- DCHECK((!IsValid() && !other.IsValid()) || CompareTo(other) == 0);
-}
-
-IndexedDBKey& IndexedDBKey::operator=(const IndexedDBKey& other) {
- type_ = other.type_;
- array_ = other.array_;
- binary_ = other.binary_;
- string_ = other.string_;
- date_ = other.date_;
- number_ = other.number_;
- size_estimate_ = other.size_estimate_;
- DCHECK((!IsValid() && !other.IsValid()) || CompareTo(other) == 0);
- return *this;
-}
-
bool IndexedDBKey::IsValid() const {
if (type_ == WebIDBKeyTypeInvalid || type_ == WebIDBKeyTypeNull)
return false;
diff --git a/chromium/content/common/indexed_db/indexed_db_key.h b/chromium/content/common/indexed_db/indexed_db_key.h
index 848a930daea..bb027700e89 100644
--- a/chromium/content/common/indexed_db/indexed_db_key.h
+++ b/chromium/content/common/indexed_db/indexed_db_key.h
@@ -33,9 +33,6 @@ class CONTENT_EXPORT IndexedDBKey {
blink::WebIDBKeyType type); // must be date or number
~IndexedDBKey();
- IndexedDBKey(const IndexedDBKey& other);
- IndexedDBKey& operator=(const IndexedDBKey& other);
-
bool IsValid() const;
bool IsLessThan(const IndexedDBKey& other) const;
diff --git a/chromium/content/common/indexed_db/indexed_db_messages.h b/chromium/content/common/indexed_db/indexed_db_messages.h
index 558d09af504..85c354c1264 100644
--- a/chromium/content/common/indexed_db/indexed_db_messages.h
+++ b/chromium/content/common/indexed_db/indexed_db_messages.h
@@ -14,8 +14,16 @@
#include "content/common/indexed_db/indexed_db_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
-#include "third_party/WebKit/public/platform/WebIDBCursor.h"
-#include "third_party/WebKit/public/platform/WebIDBDatabase.h"
+#include "third_party/WebKit/public/platform/WebIDBTypes.h"
+
+// Singly-included section for typedefs in multiply-included file.
+#ifndef CONTENT_COMMON_INDEXED_DB_INDEXED_DB_MESSAGES_H_
+#define CONTENT_COMMON_INDEXED_DB_INDEXED_DB_MESSAGES_H_
+
+// An index id, and corresponding set of keys to insert.
+typedef std::pair<int64, std::vector<content::IndexedDBKey> > IndexKeys;
+
+#endif // CONTENT_COMMON_INDEXED_DB_INDEXED_DB_MESSAGES_H_
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -23,19 +31,15 @@
// Argument structures used in messages
-IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBCursor::Direction,
- blink::WebIDBCursor::DirectionLast)
-IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBDatabase::PutMode,
- blink::WebIDBDatabase::PutModeLast)
-IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBDatabase::TaskType,
- blink::WebIDBDatabase::TaskTypeLast)
-IPC_ENUM_TRAITS(blink::WebIDBDatabase::TransactionMode)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBCursorDirection,
+ blink::WebIDBCursorDirectionLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBPutMode, blink::WebIDBPutModeLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBTaskType, blink::WebIDBTaskTypeLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBTransactionMode,
+ blink::WebIDBTransactionModeLast)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebIDBDataLoss, blink::WebIDBDataLossTotal)
-// An index id, and corresponding set of keys to insert.
-typedef std::pair<int64, std::vector<content::IndexedDBKey> > IndexKeys;
-
// Used to enumerate indexed databases.
IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryGetDatabaseNames_Params)
// The response should have these ids.
@@ -85,7 +89,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseCreateTransaction_Params)
// The scope of the transaction.
IPC_STRUCT_MEMBER(std::vector<int64>, object_store_ids)
// The transaction mode.
- IPC_STRUCT_MEMBER(blink::WebIDBDatabase::TransactionMode, mode)
+ IPC_STRUCT_MEMBER(blink::WebIDBTransactionMode, mode)
IPC_STRUCT_END()
// Used to create an object store.
@@ -150,7 +154,7 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabasePut_Params)
// The key to set it on (may not be "valid"/set in some cases).
IPC_STRUCT_MEMBER(content::IndexedDBKey, key)
// Whether this is an add or a put.
- IPC_STRUCT_MEMBER(blink::WebIDBDatabase::PutMode, put_mode)
+ IPC_STRUCT_MEMBER(blink::WebIDBPutMode, put_mode)
// The index ids and the list of keys for each index.
IPC_STRUCT_MEMBER(std::vector<IndexKeys>, index_keys)
// Sideband data for any blob or file encoded in value.
@@ -173,11 +177,11 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_DatabaseOpenCursor_Params)
// The serialized key range.
IPC_STRUCT_MEMBER(content::IndexedDBKeyRange, key_range)
// The direction of this cursor.
- IPC_STRUCT_MEMBER(blink::WebIDBCursor::Direction, direction)
+ IPC_STRUCT_MEMBER(blink::WebIDBCursorDirection, direction)
// If this is just retrieving the key
IPC_STRUCT_MEMBER(bool, key_only)
// The priority of this cursor.
- IPC_STRUCT_MEMBER(blink::WebIDBDatabase::TaskType, task_type)
+ IPC_STRUCT_MEMBER(blink::WebIDBTaskType, task_type)
IPC_STRUCT_END()
// Used to open both cursors and object cursors in IndexedDB.
@@ -476,7 +480,11 @@ IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseCreateTransaction,
// WebIDBDatabase::close() message.
IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseClose,
- int32 /* ipc_database_callbacks_id */)
+ int32 /* ipc_database_id */)
+
+// WebIDBDatabase::versionChangeIgnored() message.
+IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseVersionChangeIgnored,
+ int32 /* ipc_database_id */)
// WebIDBDatabase::~WebIDBDatabase() message.
IPC_MESSAGE_CONTROL1(IndexedDBHostMsg_DatabaseDestroyed,
diff --git a/chromium/content/common/input/did_overscroll_params.cc b/chromium/content/common/input/did_overscroll_params.cc
new file mode 100644
index 00000000000..2b69d8600e7
--- /dev/null
+++ b/chromium/content/common/input/did_overscroll_params.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 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 "content/common/input/did_overscroll_params.h"
+
+namespace content {
+
+DidOverscrollParams::DidOverscrollParams() {
+}
+
+DidOverscrollParams::~DidOverscrollParams() {
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/did_overscroll_params.h b/chromium/content/common/input/did_overscroll_params.h
index 4f6a7f1f226..7db3ac43009 100644
--- a/chromium/content/common/input/did_overscroll_params.h
+++ b/chromium/content/common/input/did_overscroll_params.h
@@ -5,14 +5,19 @@
#ifndef CONTENT_COMMON_INPUT_DID_OVERSCROLL_PARAMS_H_
#define CONTENT_COMMON_INPUT_DID_OVERSCROLL_PARAMS_H_
+#include "content/common/content_export.h"
+#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace content {
-struct DidOverscrollParams {
+struct CONTENT_EXPORT DidOverscrollParams {
+ DidOverscrollParams();
+ ~DidOverscrollParams();
gfx::Vector2dF accumulated_overscroll;
gfx::Vector2dF latest_overscroll_delta;
gfx::Vector2dF current_fling_velocity;
+ gfx::PointF causal_event_viewport_point;
};
} // namespace content
diff --git a/chromium/content/common/input/gesture_event_stream_validator.cc b/chromium/content/common/input/gesture_event_stream_validator.cc
index a6229f98b69..eccdbe0079f 100644
--- a/chromium/content/common/input/gesture_event_stream_validator.cc
+++ b/chromium/content/common/input/gesture_event_stream_validator.cc
@@ -24,8 +24,10 @@ bool GestureEventStreamValidator::Validate(const blink::WebGestureEvent& event,
error_msg->clear();
switch (event.type) {
case WebInputEvent::GestureScrollBegin:
- if (scrolling_ || pinching_)
+ if (scrolling_)
error_msg->append("Scroll begin during scroll\n");
+ if (pinching_)
+ error_msg->append("Scroll begin during pinch\n");
scrolling_ = true;
break;
case WebInputEvent::GestureScrollUpdate:
@@ -42,18 +44,16 @@ bool GestureEventStreamValidator::Validate(const blink::WebGestureEvent& event,
scrolling_ = false;
break;
case WebInputEvent::GesturePinchBegin:
- if (!scrolling_)
- error_msg->append("Pinch begin outside of scroll\n");
if (pinching_)
error_msg->append("Pinch begin during pinch\n");
pinching_ = true;
break;
case WebInputEvent::GesturePinchUpdate:
- if (!pinching_ || !scrolling_)
+ if (!pinching_)
error_msg->append("Pinch update outside of pinch\n");
break;
case WebInputEvent::GesturePinchEnd:
- if (!pinching_ || !scrolling_)
+ if (!pinching_)
error_msg->append("Pinch end outside of pinch\n");
pinching_ = false;
break;
@@ -62,11 +62,19 @@ bool GestureEventStreamValidator::Validate(const blink::WebGestureEvent& event,
error_msg->append("Missing tap end event\n");
waiting_for_tap_end_ = true;
break;
- case WebInputEvent::GestureTap:
+ case WebInputEvent::GestureTapUnconfirmed:
+ if (!waiting_for_tap_end_)
+ error_msg->append("Missing TapDown event before TapUnconfirmed\n");
+ break;
case WebInputEvent::GestureTapCancel:
- case WebInputEvent::GestureDoubleTap:
if (!waiting_for_tap_end_)
- error_msg->append("Missing GestureTapDown event\n");
+ error_msg->append("Missing TapDown event before TapCancel\n");
+ waiting_for_tap_end_ = false;
+ break;
+ case WebInputEvent::GestureTap:
+ case WebInputEvent::GestureDoubleTap:
+ // Both Tap and DoubleTap gestures may be synthetically inserted, and do
+ // not require a preceding TapDown.
waiting_for_tap_end_ = false;
break;
default:
diff --git a/chromium/content/common/input/gesture_event_stream_validator.h b/chromium/content/common/input/gesture_event_stream_validator.h
index 3c417f5d425..8a2bf86a000 100644
--- a/chromium/content/common/input/gesture_event_stream_validator.h
+++ b/chromium/content/common/input/gesture_event_stream_validator.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "content/common/content_export.h"
namespace blink {
class WebGestureEvent;
@@ -16,7 +17,7 @@ class WebGestureEvent;
namespace content {
// Utility class for validating a stream of WebGestureEvents.
-class GestureEventStreamValidator {
+class CONTENT_EXPORT GestureEventStreamValidator {
public:
GestureEventStreamValidator();
~GestureEventStreamValidator();
diff --git a/chromium/content/common/input/gesture_event_stream_validator_unittest.cc b/chromium/content/common/input/gesture_event_stream_validator_unittest.cc
new file mode 100644
index 00000000000..857dcfe9375
--- /dev/null
+++ b/chromium/content/common/input/gesture_event_stream_validator_unittest.cc
@@ -0,0 +1,236 @@
+// Copyright 2014 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 "content/common/input/gesture_event_stream_validator.h"
+
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using blink::WebInputEvent;
+using blink::WebGestureEvent;
+
+namespace content {
+namespace {
+
+const blink::WebGestureDevice kDefaultGestureDevice =
+ blink::WebGestureDeviceTouchscreen;
+
+blink::WebGestureEvent Build(WebInputEvent::Type type) {
+ return SyntheticWebGestureEventBuilder::Build(type, kDefaultGestureDevice);
+}
+
+} // namespace
+
+TEST(GestureEventStreamValidator, ValidScroll) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ event = Build(WebInputEvent::GestureScrollBegin);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureScrollUpdate);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureScrollEnd);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, InvalidScroll) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ // No preceding ScrollBegin.
+ event = Build(WebInputEvent::GestureScrollUpdate);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ // No preceding ScrollBegin.
+ event = Build(WebInputEvent::GestureScrollEnd);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureScrollBegin);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ // Already scrolling.
+ event = Build(WebInputEvent::GestureScrollBegin);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureScrollEnd);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ // Scroll already ended.
+ event = Build(WebInputEvent::GestureScrollEnd);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, ValidFling) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ event = Build(WebInputEvent::GestureScrollBegin);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureFlingStart);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, InvalidFling) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ // No preceding ScrollBegin.
+ event = Build(WebInputEvent::GestureFlingStart);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, ValidPinch) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ event = Build(WebInputEvent::GesturePinchBegin);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GesturePinchUpdate);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GesturePinchEnd);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, InvalidPinch) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ // No preceding PinchBegin.
+ event = Build(WebInputEvent::GesturePinchUpdate);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ event = Build(WebInputEvent::GesturePinchBegin);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ // ScrollBegin while pinching.
+ event = Build(WebInputEvent::GestureScrollBegin);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ // ScrollEnd while pinching.
+ event = Build(WebInputEvent::GestureScrollEnd);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ // Pinch already begun.
+ event = Build(WebInputEvent::GesturePinchBegin);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ event = Build(WebInputEvent::GesturePinchEnd);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ // Pinch already ended.
+ event = Build(WebInputEvent::GesturePinchEnd);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, ValidTap) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ event = Build(WebInputEvent::GestureTapDown);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapCancel);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapDown);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapUnconfirmed);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapCancel);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ // Tap and DoubleTap do not require a TapDown (unlike TapUnconfirmed and
+ // TapCancel).
+ event = Build(WebInputEvent::GestureTap);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureDoubleTap);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(GestureEventStreamValidator, InvalidTap) {
+ GestureEventStreamValidator validator;
+ std::string error_msg;
+ WebGestureEvent event;
+
+ // No preceding TapDown.
+ event = Build(WebInputEvent::GestureTapUnconfirmed);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapCancel);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ // TapDown already terminated.
+ event = Build(WebInputEvent::GestureTapDown);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureDoubleTap);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapCancel);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+
+ // TapDown already terminated.
+ event = Build(WebInputEvent::GestureTapDown);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTap);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event = Build(WebInputEvent::GestureTapCancel);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/input_param_traits.cc b/chromium/content/common/input/input_param_traits.cc
index 2a5297c8a1c..e9aba992a82 100644
--- a/chromium/content/common/input/input_param_traits.cc
+++ b/chromium/content/common/input/input_param_traits.cc
@@ -21,7 +21,7 @@ scoped_ptr<content::SyntheticGestureParams> ReadGestureParams(
if (!ReadParam(m, iter, gesture_params.get()))
return scoped_ptr<content::SyntheticGestureParams>();
- return gesture_params.template PassAs<content::SyntheticGestureParams>();
+ return gesture_params.Pass();
}
} // namespace
diff --git a/chromium/content/common/input/input_param_traits_unittest.cc b/chromium/content/common/input/input_param_traits_unittest.cc
index db07d29dc5c..cbfd9aa2bcc 100644
--- a/chromium/content/common/input/input_param_traits_unittest.cc
+++ b/chromium/content/common/input/input_param_traits_unittest.cc
@@ -199,7 +199,7 @@ TEST_F(InputParamTraitsTest, SyntheticSmoothScrollGestureParams) {
ASSERT_EQ(SyntheticGestureParams::SMOOTH_SCROLL_GESTURE,
gesture_params->GetGestureType());
SyntheticGesturePacket packet_in;
- packet_in.set_gesture_params(gesture_params.PassAs<SyntheticGestureParams>());
+ packet_in.set_gesture_params(gesture_params.Pass());
Verify(packet_in);
}
@@ -214,7 +214,7 @@ TEST_F(InputParamTraitsTest, SyntheticPinchGestureParams) {
ASSERT_EQ(SyntheticGestureParams::PINCH_GESTURE,
gesture_params->GetGestureType());
SyntheticGesturePacket packet_in;
- packet_in.set_gesture_params(gesture_params.PassAs<SyntheticGestureParams>());
+ packet_in.set_gesture_params(gesture_params.Pass());
Verify(packet_in);
}
@@ -228,7 +228,7 @@ TEST_F(InputParamTraitsTest, SyntheticTapGestureParams) {
ASSERT_EQ(SyntheticGestureParams::TAP_GESTURE,
gesture_params->GetGestureType());
SyntheticGesturePacket packet_in;
- packet_in.set_gesture_params(gesture_params.PassAs<SyntheticGestureParams>());
+ packet_in.set_gesture_params(gesture_params.Pass());
Verify(packet_in);
}
diff --git a/chromium/content/common/input/synthetic_pinch_gesture_params.h b/chromium/content/common/input/synthetic_pinch_gesture_params.h
index 393b0cc1c68..ba15cafbf98 100644
--- a/chromium/content/common/input/synthetic_pinch_gesture_params.h
+++ b/chromium/content/common/input/synthetic_pinch_gesture_params.h
@@ -17,9 +17,9 @@ struct CONTENT_EXPORT SyntheticPinchGestureParams
SyntheticPinchGestureParams();
SyntheticPinchGestureParams(
const SyntheticPinchGestureParams& other);
- virtual ~SyntheticPinchGestureParams();
+ ~SyntheticPinchGestureParams() override;
- virtual GestureType GetGestureType() const OVERRIDE;
+ GestureType GetGestureType() const override;
float scale_factor;
gfx::Point anchor;
diff --git a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
index 4fe027edc8b..05f7357c6e5 100644
--- a/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
+++ b/chromium/content/common/input/synthetic_smooth_scroll_gesture_params.h
@@ -20,9 +20,9 @@ struct CONTENT_EXPORT SyntheticSmoothScrollGestureParams
SyntheticSmoothScrollGestureParams();
SyntheticSmoothScrollGestureParams(
const SyntheticSmoothScrollGestureParams& other);
- virtual ~SyntheticSmoothScrollGestureParams();
+ ~SyntheticSmoothScrollGestureParams() override;
- virtual GestureType GetGestureType() const OVERRIDE;
+ GestureType GetGestureType() const override;
gfx::Point anchor;
std::vector<gfx::Vector2d> distances; // Positive X/Y to scroll left/up.
diff --git a/chromium/content/common/input/synthetic_tap_gesture_params.h b/chromium/content/common/input/synthetic_tap_gesture_params.h
index dde22c6b1d8..c4ca5766ed4 100644
--- a/chromium/content/common/input/synthetic_tap_gesture_params.h
+++ b/chromium/content/common/input/synthetic_tap_gesture_params.h
@@ -16,9 +16,9 @@ struct CONTENT_EXPORT SyntheticTapGestureParams
public:
SyntheticTapGestureParams();
SyntheticTapGestureParams(const SyntheticTapGestureParams& other);
- virtual ~SyntheticTapGestureParams();
+ ~SyntheticTapGestureParams() override;
- virtual GestureType GetGestureType() const OVERRIDE;
+ GestureType GetGestureType() const override;
gfx::Point position;
int duration_ms;
diff --git a/chromium/content/common/input/touch_event_stream_validator.cc b/chromium/content/common/input/touch_event_stream_validator.cc
index 85bc4694433..3310036c5b4 100644
--- a/chromium/content/common/input/touch_event_stream_validator.cc
+++ b/chromium/content/common/input/touch_event_stream_validator.cc
@@ -38,6 +38,14 @@ bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
WebTouchEvent previous_event = previous_event_;
previous_event_ = event;
+ if (!event.touchesLength) {
+ error_msg->append("Touch event is empty.\n");
+ return false;
+ }
+
+ if (!WebInputEvent::isTouchEventType(event.type))
+ error_msg->append("Touch event has invalid type.\n");
+
// Allow "hard" restarting of touch stream validation. This is necessary
// in cases where touch event forwarding ceases in response to the event ack
// or removal of touch handlers.
@@ -56,6 +64,7 @@ bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
error_msg->append("Previously active touch point not in new event.\n");
}
+ bool found_valid_state_for_type = false;
for (unsigned i = 0; i < event.touchesLength; ++i) {
const WebTouchPoint& point = event.touches[i];
const WebTouchPoint* previous_point =
@@ -81,16 +90,22 @@ bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
case WebTouchPoint::StateReleased:
if (event.type != WebInputEvent::TouchEnd)
error_msg->append("Released touch point outside touchend.\n");
+ else
+ found_valid_state_for_type = true;
break;
case WebTouchPoint::StatePressed:
if (event.type != WebInputEvent::TouchStart)
error_msg->append("Pressed touch point outside touchstart.\n");
+ else
+ found_valid_state_for_type = true;
break;
case WebTouchPoint::StateMoved:
if (event.type != WebInputEvent::TouchMove)
error_msg->append("Moved touch point outside touchmove.\n");
+ else
+ found_valid_state_for_type = true;
break;
case WebTouchPoint::StateStationary:
@@ -99,9 +114,15 @@ bool TouchEventStreamValidator::Validate(const WebTouchEvent& event,
case WebTouchPoint::StateCancelled:
if (event.type != WebInputEvent::TouchCancel)
error_msg->append("Cancelled touch point outside touchcancel.\n");
+ else
+ found_valid_state_for_type = true;
break;
}
}
+
+ if (!found_valid_state_for_type)
+ error_msg->append("No valid touch point corresponding to event type.");
+
return error_msg->empty();
}
diff --git a/chromium/content/common/input/touch_event_stream_validator.h b/chromium/content/common/input/touch_event_stream_validator.h
index 0c9732cedfd..ec112fd8e97 100644
--- a/chromium/content/common/input/touch_event_stream_validator.h
+++ b/chromium/content/common/input/touch_event_stream_validator.h
@@ -8,12 +8,13 @@
#include <string>
#include "base/basictypes.h"
+#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
// Utility class for validating a stream of WebTouchEvents.
-class TouchEventStreamValidator {
+class CONTENT_EXPORT TouchEventStreamValidator {
public:
TouchEventStreamValidator();
~TouchEventStreamValidator();
diff --git a/chromium/content/common/input/touch_event_stream_validator_unittest.cc b/chromium/content/common/input/touch_event_stream_validator_unittest.cc
new file mode 100644
index 00000000000..5e3b767fb1d
--- /dev/null
+++ b/chromium/content/common/input/touch_event_stream_validator_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2014 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 "content/common/input/touch_event_stream_validator.h"
+
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input/web_touch_event_traits.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using blink::WebInputEvent;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+
+namespace content {
+
+TEST(TouchEventStreamValidator, ValidTouchStream) {
+ TouchEventStreamValidator validator;
+ SyntheticWebTouchEvent event;
+ std::string error_msg;
+
+ event.PressPoint(0, 1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.PressPoint(1, 0);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.MovePoint(1, 1, 1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.ReleasePoint(1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.MovePoint(0, -1, 0);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.CancelPoint(0);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.PressPoint(-1, -1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(TouchEventStreamValidator, ResetOnNewTouchStream) {
+ TouchEventStreamValidator validator;
+ SyntheticWebTouchEvent event;
+ std::string error_msg;
+
+ event.PressPoint(0, 1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.CancelPoint(0);
+ event.ResetPoints();
+ event.PressPoint(1, 0);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+}
+
+TEST(TouchEventStreamValidator, MissedTouchStart) {
+ TouchEventStreamValidator validator;
+ SyntheticWebTouchEvent event;
+ std::string error_msg;
+
+ event.PressPoint(0, 1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ event.PressPoint(1, 0);
+ event.ResetPoints();
+ event.PressPoint(1, 1);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(TouchEventStreamValidator, MissedTouchEnd) {
+ TouchEventStreamValidator validator;
+ SyntheticWebTouchEvent event;
+ std::string error_msg;
+
+ event.PressPoint(0, 1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.PressPoint(0, 1);
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ event.ResetPoints();
+
+ event.ReleasePoint(1);
+ event.ResetPoints();
+ event.PressPoint(1, 1);
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(TouchEventStreamValidator, EmptyEvent) {
+ TouchEventStreamValidator validator;
+ WebTouchEvent event;
+ std::string error_msg;
+
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(TouchEventStreamValidator, InvalidEventType) {
+ TouchEventStreamValidator validator;
+ WebTouchEvent event;
+ std::string error_msg;
+
+ event.type = WebInputEvent::GestureScrollBegin;
+ event.touchesLength = 1;
+ event.touches[0].state = WebTouchPoint::StatePressed;
+
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+}
+
+TEST(TouchEventStreamValidator, InvalidPointStates) {
+ TouchEventStreamValidator validator;
+ std::string error_msg;
+
+ WebInputEvent::Type kTouchTypes[4] = {
+ WebInputEvent::TouchStart, WebInputEvent::TouchMove,
+ WebInputEvent::TouchEnd, WebInputEvent::TouchCancel,
+ };
+
+ WebTouchPoint::State kValidTouchPointStatesForType[4] = {
+ WebTouchPoint::StatePressed, WebTouchPoint::StateMoved,
+ WebTouchPoint::StateReleased, WebTouchPoint::StateCancelled,
+ };
+
+ SyntheticWebTouchEvent start;
+ start.PressPoint(0, 0);
+ for (size_t i = 0; i < 4; ++i) {
+ // Always start with a touchstart to reset the stream validation.
+ EXPECT_TRUE(validator.Validate(start, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+
+ WebTouchEvent event;
+ event.touchesLength = 1;
+ event.type = kTouchTypes[i];
+ for (size_t j = WebTouchPoint::StateUndefined;
+ j <= WebTouchPoint::StateCancelled;
+ ++j) {
+ event.touches[0].state = static_cast<WebTouchPoint::State>(j);
+ if (event.touches[0].state == kValidTouchPointStatesForType[i]) {
+ EXPECT_TRUE(validator.Validate(event, &error_msg));
+ EXPECT_TRUE(error_msg.empty());
+ } else {
+ EXPECT_FALSE(validator.Validate(event, &error_msg));
+ EXPECT_FALSE(error_msg.empty());
+ }
+ }
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/web_input_event_traits.cc b/chromium/content/common/input/web_input_event_traits.cc
index fa9f433a1d7..4de53c70ebc 100644
--- a/chromium/content/common/input/web_input_event_traits.cc
+++ b/chromium/content/common/input/web_input_event_traits.cc
@@ -8,13 +8,17 @@
#include <limits>
#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+using base::StringAppendF;
+using base::SStringPrintf;
using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebKeyboardEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebTouchEvent;
+using blink::WebTouchPoint;
using std::numeric_limits;
namespace content {
@@ -22,6 +26,94 @@ namespace {
const int kInvalidTouchIndex = -1;
+void ApppendEventDetails(const WebKeyboardEvent& event, std::string* result) {
+ StringAppendF(result,
+ "{\n WinCode: %d\n NativeCode: %d\n IsSystem: %d\n"
+ " Text: %s\n UnmodifiedText: %s\n KeyIdentifier: %s\n}",
+ event.windowsKeyCode,
+ event.nativeKeyCode,
+ event.isSystemKey,
+ reinterpret_cast<const char*>(event.text),
+ reinterpret_cast<const char*>(event.unmodifiedText),
+ reinterpret_cast<const char*>(event.keyIdentifier));
+}
+
+void ApppendEventDetails(const WebMouseEvent& event, std::string* result) {
+ StringAppendF(result,
+ "{\n Button: %d\n Pos: (%d, %d)\n WindowPos: (%d, %d)\n"
+ " GlobalPos: (%d, %d)\n Movement: (%d, %d)\n Clicks: %d\n}",
+ event.button,
+ event.x,
+ event.y,
+ event.windowX,
+ event.windowY,
+ event.globalX,
+ event.globalY,
+ event.movementX,
+ event.movementY,
+ event.clickCount);
+}
+
+void ApppendEventDetails(const WebMouseWheelEvent& event, std::string* result) {
+ StringAppendF(result,
+ "{\n Delta: (%f, %f)\n WheelTicks: (%f, %f)\n Accel: (%f, %f)\n"
+ " ScrollByPage: %d\n HasPreciseScrollingDeltas: %d\n"
+ " Phase: (%d, %d)\n CanRubberband: (%d, %d)\n}",
+ event.deltaX,
+ event.deltaY,
+ event.wheelTicksX,
+ event.wheelTicksY,
+ event.accelerationRatioX,
+ event.accelerationRatioY,
+ event.scrollByPage,
+ event.hasPreciseScrollingDeltas,
+ event.phase,
+ event.momentumPhase,
+ event.canRubberbandLeft,
+ event.canRubberbandRight);
+}
+
+void ApppendEventDetails(const WebGestureEvent& event, std::string* result) {
+ StringAppendF(result,
+ "{\n Pos: (%d, %d)\n GlobalPos: (%d, %d)\n SourceDevice: %d\n"
+ " RawData: (%f, %f, %f, %f)\n}",
+ event.x,
+ event.y,
+ event.globalX,
+ event.globalY,
+ event.sourceDevice,
+ event.data.scrollUpdate.deltaX,
+ event.data.scrollUpdate.deltaY,
+ event.data.scrollUpdate.velocityX,
+ event.data.scrollUpdate.velocityY);
+}
+
+void ApppendTouchPointDetails(const WebTouchPoint& point, std::string* result) {
+ StringAppendF(result,
+ " (ID: %d, State: %d, ScreenPos: (%f, %f), Pos: (%f, %f),"
+ " Radius: (%f, %f), Rot: %f, Force: %f),\n",
+ point.id,
+ point.state,
+ point.screenPosition.x,
+ point.screenPosition.y,
+ point.position.x,
+ point.position.y,
+ point.radiusX,
+ point.radiusY,
+ point.rotationAngle,
+ point.force);
+}
+
+void ApppendEventDetails(const WebTouchEvent& event, std::string* result) {
+ StringAppendF(result,
+ "{\n Touches: %u, Cancelable: %d,\n[\n",
+ event.touchesLength,
+ event.cancelable);
+ for (unsigned i = 0; i < event.touchesLength; ++i)
+ ApppendTouchPointDetails(event.touches[i], result);
+ result->append(" ]\n}");
+}
+
bool CanCoalesce(const WebKeyboardEvent& event_to_coalesce,
const WebKeyboardEvent& event) {
return false;
@@ -184,6 +276,19 @@ void Coalesce(const WebGestureEvent& event_to_coalesce,
}
}
+struct WebInputEventToString {
+ template <class EventType>
+ bool Execute(const WebInputEvent& event, std::string* result) const {
+ SStringPrintf(result, "%s (Time: %lf, Modifiers: %d)\n",
+ WebInputEventTraits::GetName(event.type),
+ event.timeStampSeconds,
+ event.modifiers);
+ const EventType& typed_event = static_cast<const EventType&>(event);
+ ApppendEventDetails(typed_event, result);
+ return true;
+ }
+};
+
struct WebInputEventSize {
template <class EventType>
bool Execute(WebInputEvent::Type /* type */, size_t* type_size) const {
@@ -306,6 +411,12 @@ const char* WebInputEventTraits::GetName(WebInputEvent::Type type) {
return "";
}
+std::string WebInputEventTraits::ToString(const WebInputEvent& event) {
+ std::string result;
+ Apply(WebInputEventToString(), event.type, event, &result);
+ return result;
+}
+
size_t WebInputEventTraits::GetSize(WebInputEvent::Type type) {
size_t size = 0;
Apply(WebInputEventSize(), type, type, &size);
diff --git a/chromium/content/common/input/web_input_event_traits.h b/chromium/content/common/input/web_input_event_traits.h
index 47cd69fef60..2e5a20edf43 100644
--- a/chromium/content/common/input/web_input_event_traits.h
+++ b/chromium/content/common/input/web_input_event_traits.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_TRAITS_H_
#define CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_TRAITS_H_
+#include <string>
+
#include "base/basictypes.h"
#include "content/common/input/scoped_web_input_event.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -15,6 +17,7 @@ namespace content {
class CONTENT_EXPORT WebInputEventTraits {
public:
static const char* GetName(blink::WebInputEvent::Type type);
+ static std::string ToString(const blink::WebInputEvent& event);
static size_t GetSize(blink::WebInputEvent::Type type);
static ScopedWebInputEvent Clone(const blink::WebInputEvent& event);
static void Delete(blink::WebInputEvent* event);
diff --git a/chromium/content/common/input/web_input_event_traits_unittest.cc b/chromium/content/common/input/web_input_event_traits_unittest.cc
index 6eafb0fabb6..7a7cb7ff8b3 100644
--- a/chromium/content/common/input/web_input_event_traits_unittest.cc
+++ b/chromium/content/common/input/web_input_event_traits_unittest.cc
@@ -11,6 +11,9 @@
using blink::WebGestureEvent;
using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
using std::numeric_limits;
@@ -159,5 +162,27 @@ TEST_F(WebInputEventTraitsTest, PinchEventCoalescing) {
EXPECT_EQ(numeric_limits<float>::max(), pinch1.data.pinchUpdate.scale);
}
+// Very basic smoke test to ensure stringification doesn't explode.
+TEST_F(WebInputEventTraitsTest, ToString) {
+ WebKeyboardEvent key;
+ key.type = WebInputEvent::RawKeyDown;
+ EXPECT_FALSE(WebInputEventTraits::ToString(key).empty());
+
+ WebMouseEvent mouse;
+ mouse.type = WebInputEvent::MouseMove;
+ EXPECT_FALSE(WebInputEventTraits::ToString(mouse).empty());
+
+ WebMouseWheelEvent mouse_wheel;
+ mouse_wheel.type = WebInputEvent::MouseWheel;
+ EXPECT_FALSE(WebInputEventTraits::ToString(mouse_wheel).empty());
+
+ WebGestureEvent gesture =
+ CreateGesture(WebInputEvent::GesturePinchBegin, 1, 1);
+ EXPECT_FALSE(WebInputEventTraits::ToString(gesture).empty());
+
+ WebTouchEvent touch = CreateTouch(WebInputEvent::TouchStart);
+ EXPECT_FALSE(WebInputEventTraits::ToString(touch).empty());
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/input/web_touch_event_traits.cc b/chromium/content/common/input/web_touch_event_traits.cc
index d1003bacce4..1a161060630 100644
--- a/chromium/content/common/input/web_touch_event_traits.cc
+++ b/chromium/content/common/input/web_touch_event_traits.cc
@@ -31,6 +31,20 @@ bool WebTouchEventTraits::IsTouchSequenceStart(const WebTouchEvent& event) {
return AllTouchPointsHaveState(event, blink::WebTouchPoint::StatePressed);
}
+bool WebTouchEventTraits::IsTouchSequenceEnd(const WebTouchEvent& event) {
+ if (event.type != WebInputEvent::TouchEnd &&
+ event.type != WebInputEvent::TouchCancel)
+ return false;
+ if (!event.touchesLength)
+ return true;
+ for (size_t i = 0; i < event.touchesLength; ++i) {
+ if (event.touches[i].state != blink::WebTouchPoint::StateReleased &&
+ event.touches[i].state != blink::WebTouchPoint::StateCancelled)
+ return false;
+ }
+ return true;
+}
+
void WebTouchEventTraits::ResetType(WebInputEvent::Type type,
double timestamp_sec,
WebTouchEvent* event) {
diff --git a/chromium/content/common/input/web_touch_event_traits.h b/chromium/content/common/input/web_touch_event_traits.h
index 74e9d6eb7de..a29c0709af6 100644
--- a/chromium/content/common/input/web_touch_event_traits.h
+++ b/chromium/content/common/input/web_touch_event_traits.h
@@ -22,6 +22,10 @@ class CONTENT_EXPORT WebTouchEventTraits {
// touches to some active touches (the start of a new "touch sequence").
static bool IsTouchSequenceStart(const blink::WebTouchEvent& event);
+ // Returns whether this event represents a transition from active
+ // touches to no active touches (the end of a "touch sequence").
+ static bool IsTouchSequenceEnd(const blink::WebTouchEvent& event);
+
// Sets the type of |event| to |type|, resetting any other type-specific
// properties and updating the timestamp.
static void ResetType(blink::WebInputEvent::Type type,
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index 6b36bec4d15..95663f75a34 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -19,12 +19,14 @@
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
-#include "content/public/common/common_param_traits.h"
#include "content/common/input/touch_action.h"
+#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/ipc/latency_info_param_traits.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/point.h"
+#include "ui/gfx/range/range.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/vector2d_f.h"
@@ -57,6 +59,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::DidOverscrollParams)
IPC_STRUCT_TRAITS_MEMBER(accumulated_overscroll)
IPC_STRUCT_TRAITS_MEMBER(latest_overscroll_delta)
IPC_STRUCT_TRAITS_MEMBER(current_fling_velocity)
+ IPC_STRUCT_TRAITS_MEMBER(causal_event_viewport_point)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
@@ -113,6 +116,33 @@ IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent,
IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange,
bool /* is_visible */)
+// Sets the text composition to be between the given start and end offsets in
+// the currently focused editable field.
+IPC_MESSAGE_ROUTED3(InputMsg_SetCompositionFromExistingText,
+ int /* start */,
+ int /* end */,
+ std::vector<blink::WebCompositionUnderline> /* underlines */)
+
+// Deletes the current selection plus the specified number of characters before
+// and after the selection or caret.
+IPC_MESSAGE_ROUTED2(InputMsg_ExtendSelectionAndDelete,
+ int /* before */,
+ int /* after */)
+
+// This message sends a string being composed with an input method.
+IPC_MESSAGE_ROUTED4(
+ InputMsg_ImeSetComposition,
+ base::string16, /* text */
+ std::vector<blink::WebCompositionUnderline>, /* underlines */
+ int, /* selectiont_start */
+ int /* selection_end */)
+
+// This message confirms an ongoing composition.
+IPC_MESSAGE_ROUTED3(InputMsg_ImeConfirmComposition,
+ base::string16 /* text */,
+ gfx::Range /* replacement_range */,
+ bool /* keep_selection */)
+
// This message notifies the renderer that the next key event is bound to one
// or more pre-defined edit commands. If the next key event is not handled
// by webkit, the specified edit commands shall be executed against current
@@ -169,8 +199,13 @@ IPC_MESSAGE_ROUTED0(InputMsg_Unselect)
// Requests the renderer to select the region between two points.
// Expects a SelectRange_ACK message when finished.
IPC_MESSAGE_ROUTED2(InputMsg_SelectRange,
- gfx::Point /* start */,
- gfx::Point /* end */)
+ gfx::Point /* base */,
+ gfx::Point /* extent */)
+
+// Requests the renderer to move the selection extent point to a new position.
+// Expects a MoveRangeSelectionExtent_ACK message when finished.
+IPC_MESSAGE_ROUTED1(InputMsg_MoveRangeSelectionExtent,
+ gfx::Point /* extent */)
// Requests the renderer to move the caret selection toward the point.
// Expects a MoveCaret_ACK message when finished.
@@ -186,7 +221,7 @@ IPC_MESSAGE_ROUTED3(InputMsg_ActivateNearestFindResult,
float /* y */)
#endif
-IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted);
+IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted)
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
@@ -207,6 +242,28 @@ IPC_MESSAGE_ROUTED1(InputHostMsg_SetTouchAction,
IPC_MESSAGE_ROUTED1(InputHostMsg_DidOverscroll,
content::DidOverscrollParams /* params */)
+// Acknowledges receipt of a InputMsg_MoveCaret message.
+IPC_MESSAGE_ROUTED0(InputHostMsg_MoveCaret_ACK)
+
+// Acknowledges receipt of a InputMsg_MoveRangeSelectionExtent message.
+IPC_MESSAGE_ROUTED0(InputHostMsg_MoveRangeSelectionExtent_ACK)
+
+// Acknowledges receipt of a InputMsg_SelectRange message.
+IPC_MESSAGE_ROUTED0(InputHostMsg_SelectRange_ACK)
+
+// Required for cancelling an ongoing input method composition.
+IPC_MESSAGE_ROUTED0(InputHostMsg_ImeCancelComposition)
+
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
+// On Mac and Aura IME can request composition character bounds
+// synchronously (see crbug.com/120597). This IPC message sends the character
+// bounds after every composition change to always have correct bound info.
+// This IPC message is also used on Android 5.0 and above.
+IPC_MESSAGE_ROUTED2(InputHostMsg_ImeCompositionRangeChanged,
+ gfx::Range /* composition range */,
+ std::vector<gfx::Rect> /* character bounds */)
+#endif
+
// Adding a new message? Stick to the sort order above: first platform
// independent InputMsg, then ifdefs for platform specific InputMsg, then
// platform independent InputHostMsg, then ifdefs for platform specific
diff --git a/chromium/content/common/inter_process_time_ticks_converter.cc b/chromium/content/common/inter_process_time_ticks_converter.cc
index de3fb13d991..e0c12e2bba3 100644
--- a/chromium/content/common/inter_process_time_ticks_converter.cc
+++ b/chromium/content/common/inter_process_time_ticks_converter.cc
@@ -72,4 +72,13 @@ int64 InterProcessTimeTicksConverter::Convert(int64 value) const {
return numerator_ * value / denominator_;
}
+bool InterProcessTimeTicksConverter::IsSkewAdditiveForMetrics() const {
+ return numerator_ == 1 && denominator_ == 1;
+}
+
+base::TimeDelta InterProcessTimeTicksConverter::GetSkewForMetrics() const {
+ return base::TimeTicks::FromInternalValue(remote_lower_bound_) -
+ base::TimeTicks::FromInternalValue(local_base_time_);
+}
+
} // namespace content
diff --git a/chromium/content/common/inter_process_time_ticks_converter.h b/chromium/content/common/inter_process_time_ticks_converter.h
index 01c6124288d..8b005408d58 100644
--- a/chromium/content/common/inter_process_time_ticks_converter.h
+++ b/chromium/content/common/inter_process_time_ticks_converter.h
@@ -61,6 +61,16 @@ class CONTENT_EXPORT InterProcessTimeTicksConverter {
// |remote_delta|.
LocalTimeDelta ToLocalTimeDelta(const RemoteTimeDelta& remote_delta) const;
+ // Returns true iff the TimeTicks are converted by adding a constant, without
+ // scaling. This is the case whenever the remote timespan is smaller than the
+ // local timespan, which should be the majority of cases due to IPC overhead.
+ bool IsSkewAdditiveForMetrics() const;
+
+ // Returns the (remote time) - (local time) difference estimated by the
+ // converter. This is the constant that is subtracted from remote TimeTicks to
+ // get local TimeTicks when no scaling is applied.
+ base::TimeDelta GetSkewForMetrics() const;
+
private:
int64 Convert(int64 value) const;
diff --git a/chromium/content/common/inter_process_time_ticks_converter_unittest.cc b/chromium/content/common/inter_process_time_ticks_converter_unittest.cc
index a651bfb9625..ed2791b302d 100644
--- a/chromium/content/common/inter_process_time_ticks_converter_unittest.cc
+++ b/chromium/content/common/inter_process_time_ticks_converter_unittest.cc
@@ -25,6 +25,8 @@ struct TestParams {
struct TestResults {
int64 result_time;
int32 result_delta;
+ bool is_skew_additive;
+ int64 skew;
};
TestResults RunTest(const TestParams& params) {
@@ -50,6 +52,8 @@ TestResults RunTest(const TestParams& params) {
test_time)).ToTimeTicks().ToInternalValue();
results.result_delta = converter.ToLocalTimeDelta(
RemoteTimeDelta::FromRawDelta(params.test_delta)).ToInt32();
+ results.is_skew_additive = converter.IsSkewAdditiveForMetrics();
+ results.skew = converter.GetSkewForMetrics().ToInternalValue();
return results;
}
@@ -79,6 +83,8 @@ TEST(InterProcessTimeTicksConverterTest, NoSkew) {
TestResults results = RunTest(p);
EXPECT_EQ(3, results.result_time);
EXPECT_EQ(1, results.result_delta);
+ EXPECT_TRUE(results.is_skew_additive);
+ EXPECT_EQ(0, results.skew);
}
TEST(InterProcessTimeTicksConverterTest, OffsetMidpoints) {
@@ -94,6 +100,8 @@ TEST(InterProcessTimeTicksConverterTest, OffsetMidpoints) {
TestResults results = RunTest(p);
EXPECT_EQ(3, results.result_time);
EXPECT_EQ(1, results.result_delta);
+ EXPECT_TRUE(results.is_skew_additive);
+ EXPECT_EQ(1, results.skew);
}
TEST(InterProcessTimeTicksConverterTest, DoubleEndedSkew) {
@@ -112,6 +120,7 @@ TEST(InterProcessTimeTicksConverterTest, DoubleEndedSkew) {
TestResults results = RunTest(p);
EXPECT_EQ(5, results.result_time);
EXPECT_EQ(1, results.result_delta);
+ EXPECT_FALSE(results.is_skew_additive);
}
TEST(InterProcessTimeTicksConverterTest, FrontEndSkew) {
@@ -129,6 +138,7 @@ TEST(InterProcessTimeTicksConverterTest, FrontEndSkew) {
TestResults results = RunTest(p);
EXPECT_EQ(4, results.result_time);
EXPECT_EQ(1, results.result_delta);
+ EXPECT_FALSE(results.is_skew_additive);
}
TEST(InterProcessTimeTicksConverterTest, BackEndSkew) {
@@ -144,6 +154,7 @@ TEST(InterProcessTimeTicksConverterTest, BackEndSkew) {
TestResults results = RunTest(p);
EXPECT_EQ(2, results.result_time);
EXPECT_EQ(1, results.result_delta);
+ EXPECT_FALSE(results.is_skew_additive);
}
TEST(InterProcessTimeTicksConverterTest, Instantaneous) {
diff --git a/chromium/content/common/java_bridge_messages.h b/chromium/content/common/java_bridge_messages.h
deleted file mode 100644
index 6bb811631e0..00000000000
--- a/chromium/content/common/java_bridge_messages.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2011 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.
-
-// IPC messages for injected Java objects. See JavaBridgeDispatcher for details.
-
-// Multiply-included message file, hence no include guard.
-
-#if defined(OS_ANDROID)
-
-#include "content/child/plugin_param_traits.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_message_macros.h"
-
-#define IPC_MESSAGE_START JavaBridgeMsgStart
-
-// Messages for handling Java objects injected into JavaScript -----------------
-
-// Sent from browser to renderer to add a Java object with the given name.
-IPC_MESSAGE_ROUTED2(JavaBridgeMsg_AddNamedObject,
- base::string16 /* name */,
- content::NPVariant_Param) /* object */
-
-// Sent from browser to renderer to remove a Java object with the given name.
-IPC_MESSAGE_ROUTED1(JavaBridgeMsg_RemoveNamedObject,
- base::string16 /* name */)
-
-// Sent from renderer to browser to request a route ID for a renderer-side (ie
-// JavaScript) object.
-IPC_SYNC_MESSAGE_CONTROL0_1(JavaBridgeMsg_GenerateRouteID,
- int /* route_id */)
-
-// Sent from renderer to browser to get the channel handle for NP channel.
-IPC_SYNC_MESSAGE_ROUTED0_1(JavaBridgeHostMsg_GetChannelHandle,
- IPC::ChannelHandle) /* channel handle */
-
-#endif // defined(OS_ANDROID)
diff --git a/chromium/content/common/mac/font_loader.mm b/chromium/content/common/mac/font_loader.mm
index 66b143f0a38..37dedf4dbe6 100644
--- a/chromium/content/common/mac/font_loader.mm
+++ b/chromium/content/common/mac/font_loader.mm
@@ -7,8 +7,8 @@
#import <Cocoa/Cocoa.h>
#include "base/basictypes.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
diff --git a/chromium/content/common/manifest_manager_messages.h b/chromium/content/common/manifest_manager_messages.h
new file mode 100644
index 00000000000..881ff6b6435
--- /dev/null
+++ b/chromium/content/common/manifest_manager_messages.h
@@ -0,0 +1,49 @@
+// Copyright 2014 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.
+
+// IPC messages for the web manifest manager.
+// Multiply-included message file, hence no include guard.
+
+#include "content/common/content_export.h"
+#include "content/public/common/manifest.h"
+#include "ipc/ipc_message_macros.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+
+#define IPC_MESSAGE_START ManifestManagerMsgStart
+
+IPC_ENUM_TRAITS_MAX_VALUE(content::Manifest::DisplayMode,
+ content::Manifest::DISPLAY_MODE_BROWSER)
+
+IPC_STRUCT_TRAITS_BEGIN(content::Manifest::Icon)
+ IPC_STRUCT_TRAITS_MEMBER(src)
+ IPC_STRUCT_TRAITS_MEMBER(type)
+ IPC_STRUCT_TRAITS_MEMBER(density)
+ IPC_STRUCT_TRAITS_MEMBER(sizes)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::Manifest)
+ IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(short_name)
+ IPC_STRUCT_TRAITS_MEMBER(start_url)
+ IPC_STRUCT_TRAITS_MEMBER(display)
+ IPC_STRUCT_TRAITS_MEMBER(orientation)
+ IPC_STRUCT_TRAITS_MEMBER(icons)
+ IPC_STRUCT_TRAITS_MEMBER(gcm_sender_id)
+IPC_STRUCT_TRAITS_END()
+
+// The browser process requests for the manifest linked with the associated
+// render frame. The renderer process will respond via a RequestManifestResponse
+// IPC message with a Manifest object attached to it and the associated
+// |request_id| that was initially given.
+IPC_MESSAGE_ROUTED1(ManifestManagerMsg_RequestManifest,
+ int /* request_id */)
+
+// The renderer process' response to a RequestManifest. The |request_id| will
+// match the one that was initially received. The |manifest| object will be an
+// empty manifest in case of any failure.
+IPC_MESSAGE_ROUTED2(ManifestManagerHostMsg_RequestManifestResponse,
+ int, /* request_id */
+ content::Manifest /* manifest */)
diff --git a/chromium/content/common/media/OWNERS b/chromium/content/common/media/OWNERS
index 9314814ce29..594b5ee5dd5 100644
--- a/chromium/content/common/media/OWNERS
+++ b/chromium/content/common/media/OWNERS
@@ -1,8 +1,6 @@
-acolwell@chromium.org
dalecurtis@chromium.org
ddorwin@chromium.org
scherkus@chromium.org
-shadi@chromium.org
tommi@chromium.org
vrk@chromium.org
wjia@chromium.org
@@ -10,23 +8,25 @@ xhwang@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
per-file *_param_traits.*=set noparent
-per-file *_param_traits.*=cevans@chromium.org
per-file *_param_traits.*=dcheng@chromium.org
per-file *_param_traits.*=inferno@chromium.org
per-file *_param_traits.*=jln@chromium.org
per-file *_param_traits.*=jschuh@chromium.org
per-file *_param_traits.*=kenrb@chromium.org
+per-file *_param_traits.*=mkwst@chromium.org
per-file *_param_traits.*=nasko@chromium.org
per-file *_param_traits.*=palmer@chromium.org
per-file *_param_traits.*=tsepez@chromium.org
+per-file *_param_traits.*=wfh@chromium.org
diff --git a/chromium/content/common/media/audio_messages.h b/chromium/content/common/media/audio_messages.h
index 3b9bc36ce6e..cdc35211288 100644
--- a/chromium/content/common/media/audio_messages.h
+++ b/chromium/content/common/media/audio_messages.h
@@ -11,7 +11,6 @@
#include "content/common/content_export.h"
#include "content/common/media/media_param_traits.h"
#include "ipc/ipc_message_macros.h"
-#include "media/audio/audio_buffers_state.h"
#include "media/audio/audio_input_ipc.h"
#include "media/audio/audio_output_ipc.h"
#include "media/audio/audio_parameters.h"
@@ -39,38 +38,23 @@ IPC_STRUCT_END()
// buffer it shares with the browser process. It is also given a SyncSocket that
// it uses to communicate with the browser process about the state of the
// buffered audio data.
-#if defined(OS_WIN)
-IPC_MESSAGE_CONTROL4(AudioMsg_NotifyStreamCreated,
- int /* stream id */,
- base::SharedMemoryHandle /* handle */,
- base::SyncSocket::Handle /* socket handle */,
- uint32 /* length */)
-#else
-IPC_MESSAGE_CONTROL4(AudioMsg_NotifyStreamCreated,
- int /* stream id */,
- base::SharedMemoryHandle /* handle */,
- base::FileDescriptor /* socket handle */,
- uint32 /* length */)
-#endif
+IPC_MESSAGE_CONTROL4(
+ AudioMsg_NotifyStreamCreated,
+ int /* stream id */,
+ base::SharedMemoryHandle /* handle */,
+ base::SyncSocket::TransitDescriptor /* socket descriptor */,
+ uint32 /* length */)
// Tell the renderer process that an audio input stream has been created.
// The renderer process would be given a SyncSocket that it should read
// from from then on. It is also given number of segments in shared memory.
-#if defined(OS_WIN)
-IPC_MESSAGE_CONTROL5(AudioInputMsg_NotifyStreamCreated,
- int /* stream id */,
- base::SharedMemoryHandle /* handle */,
- base::SyncSocket::Handle /* socket handle */,
- uint32 /* length */,
- uint32 /* segment count */)
-#else
-IPC_MESSAGE_CONTROL5(AudioInputMsg_NotifyStreamCreated,
- int /* stream id */,
- base::SharedMemoryHandle /* handle */,
- base::FileDescriptor /* socket handle */,
- uint32 /* length */,
- uint32 /* segment count */)
-#endif
+IPC_MESSAGE_CONTROL5(
+ AudioInputMsg_NotifyStreamCreated,
+ int /* stream id */,
+ base::SharedMemoryHandle /* handle */,
+ base::SyncSocket::TransitDescriptor /* socket descriptor */,
+ uint32 /* length */,
+ uint32 /* segment count */)
// Notification message sent from AudioRendererHost to renderer after an output
// device change has occurred.
diff --git a/chromium/content/common/media/cdm_messages.h b/chromium/content/common/media/cdm_messages.h
index 11b0eefdfd6..68c7bd184df 100644
--- a/chromium/content/common/media/cdm_messages.h
+++ b/chromium/content/common/media/cdm_messages.h
@@ -20,29 +20,40 @@
#define IPC_MESSAGE_START CdmMsgStart
IPC_ENUM_TRAITS(media::MediaKeys::KeyError)
-IPC_ENUM_TRAITS(CdmHostMsg_CreateSession_ContentType)
+IPC_ENUM_TRAITS_MAX_VALUE(CdmHostMsg_CreateSession_ContentType,
+ CREATE_SESSION_TYPE_LAST)
-IPC_MESSAGE_ROUTED3(CdmHostMsg_InitializeCdm,
- int /* cdm_id */,
- std::string /* key_system */,
- GURL /* security_origin */)
+// Messages from render to browser.
-IPC_MESSAGE_ROUTED4(CdmHostMsg_CreateSession,
- int /* cdm_id */,
- uint32_t /* session_id */,
- CdmHostMsg_CreateSession_ContentType /* content_type */,
- std::vector<uint8> /* init_data */)
+IPC_MESSAGE_CONTROL4(CdmHostMsg_InitializeCdm,
+ int /* render_frame_id */,
+ int /* cdm_id */,
+ std::string /* key_system */,
+ GURL /* security_origin */)
-IPC_MESSAGE_ROUTED3(CdmHostMsg_UpdateSession,
- int /* cdm_id */,
- uint32_t /* session_id */,
- std::vector<uint8> /* response */)
+IPC_MESSAGE_CONTROL5(CdmHostMsg_CreateSession,
+ int /* render_frame_id */,
+ int /* cdm_id */,
+ uint32_t /* session_id */,
+ CdmHostMsg_CreateSession_ContentType /* content_type */,
+ std::vector<uint8> /* init_data */)
-IPC_MESSAGE_ROUTED2(CdmHostMsg_ReleaseSession,
- int /* cdm_id */,
- uint32_t /* session_id */)
+IPC_MESSAGE_CONTROL4(CdmHostMsg_UpdateSession,
+ int /* render_frame_id */,
+ int /* cdm_id */,
+ uint32_t /* session_id */,
+ std::vector<uint8> /* response */)
+
+IPC_MESSAGE_CONTROL3(CdmHostMsg_ReleaseSession,
+ int /* render_frame_id */,
+ int /* cdm_id */,
+ uint32_t /* session_id */)
+
+IPC_MESSAGE_CONTROL2(CdmHostMsg_DestroyCdm,
+ int /* render_frame_id */,
+ int /* cdm_id */)
-IPC_MESSAGE_ROUTED1(CdmHostMsg_DestroyCdm, int /* cdm_id */)
+// Messages from browser to render.
IPC_MESSAGE_ROUTED3(CdmMsg_SessionCreated,
int /* cdm_id */,
diff --git a/chromium/content/common/media/cdm_messages_enums.h b/chromium/content/common/media/cdm_messages_enums.h
index 3e6aeae7d58..5357b512570 100644
--- a/chromium/content/common/media/cdm_messages_enums.h
+++ b/chromium/content/common/media/cdm_messages_enums.h
@@ -8,7 +8,8 @@
// Dictates the session type when an EME session is created.
enum CdmHostMsg_CreateSession_ContentType {
CREATE_SESSION_TYPE_WEBM,
- CREATE_SESSION_TYPE_MP4
+ CREATE_SESSION_TYPE_MP4,
+ CREATE_SESSION_TYPE_LAST = CREATE_SESSION_TYPE_MP4
};
#endif // CONTENT_COMMON_MEDIA_CDM_MESSAGES_ENUMS_H_
diff --git a/chromium/content/common/media/media_param_traits.cc b/chromium/content/common/media/media_param_traits.cc
index 345f838119b..405e89de17e 100644
--- a/chromium/content/common/media/media_param_traits.cc
+++ b/chromium/content/common/media/media_param_traits.cc
@@ -24,7 +24,6 @@ void ParamTraits<AudioParameters>::Write(Message* m,
m->WriteInt(p.bits_per_sample());
m->WriteInt(p.frames_per_buffer());
m->WriteInt(p.channels());
- m->WriteInt(p.input_channels());
m->WriteInt(p.effects());
}
@@ -32,7 +31,7 @@ bool ParamTraits<AudioParameters>::Read(const Message* m,
PickleIterator* iter,
AudioParameters* r) {
int format, channel_layout, sample_rate, bits_per_sample,
- frames_per_buffer, channels, input_channels, effects;
+ frames_per_buffer, channels, effects;
if (!m->ReadInt(iter, &format) ||
!m->ReadInt(iter, &channel_layout) ||
@@ -40,13 +39,12 @@ bool ParamTraits<AudioParameters>::Read(const Message* m,
!m->ReadInt(iter, &bits_per_sample) ||
!m->ReadInt(iter, &frames_per_buffer) ||
!m->ReadInt(iter, &channels) ||
- !m->ReadInt(iter, &input_channels) ||
!m->ReadInt(iter, &effects))
return false;
+
AudioParameters params(static_cast<AudioParameters::Format>(format),
static_cast<ChannelLayout>(channel_layout), channels,
- input_channels, sample_rate, bits_per_sample, frames_per_buffer,
- effects);
+ sample_rate, bits_per_sample, frames_per_buffer, effects);
*r = params;
if (!r->IsValid())
return false;
diff --git a/chromium/content/common/media/media_player_messages_android.h b/chromium/content/common/media/media_player_messages_android.h
index 4548f0b849b..999ab0f95a6 100644
--- a/chromium/content/common/media/media_player_messages_android.h
+++ b/chromium/content/common/media/media_player_messages_android.h
@@ -60,7 +60,8 @@ IPC_STRUCT_TRAITS_BEGIN(media::SubsampleEntry)
IPC_STRUCT_TRAITS_MEMBER(cypher_bytes)
IPC_STRUCT_TRAITS_END()
-IPC_ENUM_TRAITS(MediaPlayerHostMsg_Initialize_Type)
+IPC_ENUM_TRAITS_MAX_VALUE(MediaPlayerHostMsg_Initialize_Type,
+ MEDIA_PLAYER_TYPE_LAST)
// Parameters to describe a media player
IPC_STRUCT_BEGIN(MediaPlayerHostMsg_Initialize_Params)
@@ -71,6 +72,7 @@ IPC_STRUCT_BEGIN(MediaPlayerHostMsg_Initialize_Params)
IPC_STRUCT_MEMBER(GURL, url)
IPC_STRUCT_MEMBER(GURL, first_party_for_cookies)
IPC_STRUCT_MEMBER(GURL, frame_url)
+ IPC_STRUCT_MEMBER(bool, allow_credentials)
IPC_STRUCT_END()
// Chrome for Android seek message sequence is:
@@ -152,9 +154,10 @@ IPC_MESSAGE_ROUTED3(MediaPlayerMsg_MediaVideoSizeChanged,
int /* height */)
// The current play time has updated.
-IPC_MESSAGE_ROUTED2(MediaPlayerMsg_MediaTimeUpdate,
+IPC_MESSAGE_ROUTED3(MediaPlayerMsg_MediaTimeUpdate,
int /* player_id */,
- base::TimeDelta /* current_time */)
+ base::TimeDelta /* current_timestamp */,
+ base::TimeTicks /* current_time_ticks */)
// The player has been released.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_MediaPlayerReleased,
@@ -196,13 +199,15 @@ IPC_MESSAGE_ROUTED2(MediaPlayerMsg_ConnectedToRemoteDevice,
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DisconnectedFromRemoteDevice,
int /* player_id */)
+// The availability of remote devices has changed
+IPC_MESSAGE_ROUTED2(MediaPlayerMsg_RemoteRouteAvailabilityChanged,
+ int /* player_id */,
+ bool /* routes_available */)
+
// Instructs the video element to enter fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_RequestFullscreen,
int /*player_id */)
-// Pauses all video playback.
-IPC_MESSAGE_ROUTED0(MediaPlayerMsg_PauseVideo)
-
// Messages for controlling the media playback in browser process ----------
// Destroy the media player object.
@@ -246,6 +251,14 @@ IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_EnterFullscreen, int /* player_id */)
// Requests the player to exit fullscreen.
IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_ExitFullscreen, int /* player_id */)
+// Play the media on a remote device, if possible.
+IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_RequestRemotePlayback,
+ int /* demuxer_client_id */)
+
+// Control media playing on a remote device.
+IPC_MESSAGE_ROUTED1(MediaPlayerHostMsg_RequestRemotePlaybackControl,
+ int /* demuxer_client_id */)
+
// Requests the player with |player_id| to use the CDM with |cdm_id|.
IPC_MESSAGE_ROUTED2(MediaPlayerHostMsg_SetCdm,
int /* player_id */,
diff --git a/chromium/content/common/media/media_player_messages_enums_android.h b/chromium/content/common/media/media_player_messages_enums_android.h
index 97818ffe57a..50dec95a52f 100644
--- a/chromium/content/common/media/media_player_messages_enums_android.h
+++ b/chromium/content/common/media/media_player_messages_enums_android.h
@@ -9,6 +9,7 @@
enum MediaPlayerHostMsg_Initialize_Type {
MEDIA_PLAYER_TYPE_URL,
MEDIA_PLAYER_TYPE_MEDIA_SOURCE,
+ MEDIA_PLAYER_TYPE_LAST = MEDIA_PLAYER_TYPE_MEDIA_SOURCE
};
#endif // CONTENT_COMMON_MEDIA_MEDIA_PLAYER_MESSAGES_ENUMS_ANDROID_H_
diff --git a/chromium/content/common/media/media_stream_messages.h b/chromium/content/common/media/media_stream_messages.h
index 0d331709a1d..b66d052a301 100644
--- a/chromium/content/common/media/media_stream_messages.h
+++ b/chromium/content/common/media/media_stream_messages.h
@@ -78,8 +78,7 @@ IPC_MESSAGE_ROUTED2(MediaStreamMsg_DeviceStopped,
// The browser has enumerated devices. If no devices are found
// |device_list| is empty.
-// Used by Pepper.
-// TODO(vrk,wjia): Move this to pepper code.
+// Used by Pepper and WebRTC.
IPC_MESSAGE_ROUTED2(MediaStreamMsg_DevicesEnumerated,
int /* request id */,
content::StreamDeviceInfoArray /* device_list */)
@@ -96,16 +95,11 @@ IPC_MESSAGE_ROUTED3(MediaStreamMsg_DeviceOpened,
IPC_MESSAGE_ROUTED1(MediaStreamMsg_DeviceOpenFailed,
int /* request id */)
-// Response to enumerate devices request.
-IPC_MESSAGE_CONTROL2(MediaStreamMsg_GetSourcesACK,
- int /* request id */,
- content::StreamDeviceInfoArray /* device_list */)
-
// Messages sent from the renderer to the browser.
// Request a new media stream.
IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_GenerateStream,
- int /* render view id */,
+ int /* render frame id */,
int /* request id */,
content::StreamOptions /* components */,
GURL /* security origin */,
@@ -113,36 +107,30 @@ IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_GenerateStream,
// Request to cancel the request for a new media stream.
IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelGenerateStream,
- int /* render view id */,
+ int /* render frame id */,
int /* request id */)
// Request to close a device that has been opened by GenerateStream.
IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_StopStreamDevice,
- int /* render view id */,
+ int /* render frame id */,
std::string /*device_id*/)
// Request to enumerate devices.
-IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_GetSources,
- int /* request id */,
- GURL /* origin */)
-
-// Request to enumerate devices.
// Used by Pepper and WebRTC.
-IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_EnumerateDevices,
- int /* render view id */,
+IPC_MESSAGE_CONTROL4(MediaStreamHostMsg_EnumerateDevices,
+ int /* render frame id */,
int /* request id */,
content::MediaStreamType /* type */,
- GURL /* security origin */,
- bool /* hide_labels_if_no_access */)
+ GURL /* security origin */)
// Request to stop enumerating devices.
IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelEnumerateDevices,
- int /* render view id */,
+ int /* render frame id */,
int /* request id */)
// Request to open the device.
IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_OpenDevice,
- int /* render view id */,
+ int /* render frame id */,
int /* request id */,
std::string /* device_id */,
content::MediaStreamType /* type */,
@@ -150,5 +138,5 @@ IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_OpenDevice,
// Request to close a device.
IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CloseDevice,
- int /* render view id */,
+ int /* render frame id */,
std::string /*label*/)
diff --git a/chromium/content/common/media/media_stream_options.cc b/chromium/content/common/media/media_stream_options.cc
index c727b63718c..83add2a42de 100644
--- a/chromium/content/common/media/media_stream_options.cc
+++ b/chromium/content/common/media/media_stream_options.cc
@@ -42,13 +42,13 @@ bool GetFirstConstraintByName(const StreamOptions::Constraints& mandatory,
std::string* value,
bool* is_mandatory) {
if (GetFirstConstraintByName(mandatory, name, value)) {
- if (is_mandatory)
- *is_mandatory = true;
- return true;
- }
if (is_mandatory)
- *is_mandatory = false;
- return GetFirstConstraintByName(optional, name, value);
+ *is_mandatory = true;
+ return true;
+ }
+ if (is_mandatory)
+ *is_mandatory = false;
+ return GetFirstConstraintByName(optional, name, value);
}
} // namespace
diff --git a/chromium/content/common/media/midi_messages.h b/chromium/content/common/media/midi_messages.h
index 599f42c8ab9..388d518e5c8 100644
--- a/chromium/content/common/media/midi_messages.h
+++ b/chromium/content/common/media/midi_messages.h
@@ -34,11 +34,6 @@ IPC_MESSAGE_ROUTED3(MidiHostMsg_RequestSysExPermission,
GURL /* origin */,
bool /* user_gesture */)
-// Renderer request to browser for canceling a previous permission request.
-IPC_MESSAGE_ROUTED2(MidiHostMsg_CancelSysExPermissionRequest,
- int /* bridge_id */,
- GURL /* GURL of the frame */)
-
// Messages sent from the browser to the renderer.
IPC_MESSAGE_ROUTED2(MidiMsg_SysExPermissionApproved,
@@ -48,21 +43,25 @@ IPC_MESSAGE_ROUTED2(MidiMsg_SysExPermissionApproved,
// Messages for IPC between MidiMessageFilter and MidiHost.
// Renderer request to browser for access to MIDI services.
-IPC_MESSAGE_CONTROL1(MidiHostMsg_StartSession,
- int /* client id */)
+IPC_MESSAGE_CONTROL0(MidiHostMsg_StartSession)
IPC_MESSAGE_CONTROL3(MidiHostMsg_SendData,
uint32 /* port */,
std::vector<uint8> /* data */,
double /* timestamp */)
+IPC_MESSAGE_CONTROL0(MidiHostMsg_EndSession)
+
// Messages sent from the browser to the renderer.
-IPC_MESSAGE_CONTROL4(MidiMsg_SessionStarted,
- int /* client id */,
- media::MidiResult /* result */,
- media::MidiPortInfoList /* input ports */,
- media::MidiPortInfoList /* output ports */)
+IPC_MESSAGE_CONTROL1(MidiMsg_AddInputPort,
+ media::MidiPortInfo /* input port */)
+
+IPC_MESSAGE_CONTROL1(MidiMsg_AddOutputPort,
+ media::MidiPortInfo /* output port */)
+
+IPC_MESSAGE_CONTROL1(MidiMsg_SessionStarted,
+ media::MidiResult /* result */)
IPC_MESSAGE_CONTROL3(MidiMsg_DataReceived,
uint32 /* port */,
diff --git a/chromium/content/common/media/peer_connection_tracker_messages.h b/chromium/content/common/media/peer_connection_tracker_messages.h
index c5ed72fd0dd..cd774bea3fc 100644
--- a/chromium/content/common/media/peer_connection_tracker_messages.h
+++ b/chromium/content/common/media/peer_connection_tracker_messages.h
@@ -12,7 +12,7 @@
IPC_STRUCT_BEGIN(PeerConnectionInfo)
IPC_STRUCT_MEMBER(int, lid)
- IPC_STRUCT_MEMBER(std::string, servers)
+ IPC_STRUCT_MEMBER(std::string, rtc_configuration)
IPC_STRUCT_MEMBER(std::string, constraints)
IPC_STRUCT_MEMBER(std::string, url)
IPC_STRUCT_END()
@@ -40,3 +40,4 @@ IPC_MESSAGE_CONTROL5(PeerConnectionTrackerHost_GetUserMedia,
// Messages sent to PeerConnectionTracker.
IPC_MESSAGE_CONTROL0(PeerConnectionTracker_GetAllStats)
+IPC_MESSAGE_CONTROL0(PeerConnectionTracker_OnSuspend)
diff --git a/chromium/content/common/media/video_capture_messages.h b/chromium/content/common/media/video_capture_messages.h
index c3970df76f8..b7a2ee17ff3 100644
--- a/chromium/content/common/media/video_capture_messages.h
+++ b/chromium/content/common/media/video_capture_messages.h
@@ -17,9 +17,12 @@
IPC_ENUM_TRAITS_MAX_VALUE(content::VideoCaptureState,
content::VIDEO_CAPTURE_STATE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(media::ResolutionChangePolicy,
+ media::RESOLUTION_POLICY_LAST)
+
IPC_STRUCT_TRAITS_BEGIN(media::VideoCaptureParams)
IPC_STRUCT_TRAITS_MEMBER(requested_format)
- IPC_STRUCT_TRAITS_MEMBER(allow_resolution_change)
+ IPC_STRUCT_TRAITS_MEMBER(resolution_change_policy)
IPC_STRUCT_TRAITS_END()
// TODO(nick): device_id in these messages is basically just a route_id. We
@@ -45,10 +48,11 @@ IPC_MESSAGE_CONTROL2(VideoCaptureMsg_FreeBuffer,
int /* buffer_id */)
// Tell the renderer process that a buffer is available from video capture.
-IPC_MESSAGE_CONTROL4(VideoCaptureMsg_BufferReady,
+IPC_MESSAGE_CONTROL5(VideoCaptureMsg_BufferReady,
int /* device id */,
int /* buffer_id */,
media::VideoCaptureFormat /* format */,
+ gfx::Rect /* visible_rect */,
base::TimeTicks /* timestamp */)
// Tell the renderer process that a texture mailbox buffer is available from
@@ -83,6 +87,13 @@ IPC_MESSAGE_CONTROL3(VideoCaptureHostMsg_Start,
IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Pause,
int /* device_id */)
+// Resume the video capture specified by |device_id|, |session_id| and
+// |params|.
+IPC_MESSAGE_CONTROL3(VideoCaptureHostMsg_Resume,
+ int, /* device_id */
+ media::VideoCaptureSessionId, /* session_id */
+ media::VideoCaptureParams /* params */)
+
// Close the video capture specified by |device_id|.
IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Stop,
int /* device_id */)
@@ -92,7 +103,7 @@ IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Stop,
IPC_MESSAGE_CONTROL3(VideoCaptureHostMsg_BufferReady,
int /* device_id */,
int /* buffer_id */,
- std::vector<uint32> /* syncpoints */)
+ uint32 /* syncpoint */)
// Get the formats supported by a device referenced by |capture_session_id|.
IPC_MESSAGE_CONTROL2(VideoCaptureHostMsg_GetDeviceSupportedFormats,
diff --git a/chromium/content/common/message_router.h b/chromium/content/common/message_router.h
index 9c77d06bca6..a842f8eb899 100644
--- a/chromium/content/common/message_router.h
+++ b/chromium/content/common/message_router.h
@@ -32,13 +32,13 @@ namespace content {
class MessageRouter : public IPC::Listener, public IPC::Sender {
public:
MessageRouter();
- virtual ~MessageRouter();
+ ~MessageRouter() override;
// Implemented by subclasses to handle control messages
virtual bool OnControlMessageReceived(const IPC::Message& msg);
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// Like OnMessageReceived, except it only handles routed messages. Returns
// true if the message was dispatched, or false if there was no listener for
@@ -46,7 +46,7 @@ class MessageRouter : public IPC::Listener, public IPC::Sender {
virtual bool RouteMessage(const IPC::Message& msg);
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// Called to add a listener for a particular message routing ID.
// Returns true if succeeded.
diff --git a/chromium/content/common/mojo/OWNERS b/chromium/content/common/mojo/OWNERS
index 988215d97ca..c5d7458faca 100644
--- a/chromium/content/common/mojo/OWNERS
+++ b/chromium/content/common/mojo/OWNERS
@@ -1,7 +1,6 @@
# Changes to IPC messages require a security review to avoid introducing
# new sandbox escapes.
per-file *_message*.h=set noparent
-per-file *_message*.h=cevans@chromium.org
per-file *_message*.h=dcheng@chromium.org
per-file *_message*.h=inferno@chromium.org
per-file *_message*.h=jln@chromium.org
@@ -12,7 +11,6 @@ per-file *_message*.h=palmer@chromium.org
per-file *_message*.h=tsepez@chromium.org
per-file *param_traits*.h=set noparent
-per-file *param_traits*.h=cevans@chromium.org
per-file *param_traits*.h=dcheng@chromium.org
per-file *param_traits*.h=inferno@chromium.org
per-file *param_traits*.h=jln@chromium.org
diff --git a/chromium/content/common/mojo/mojo_messages.h b/chromium/content/common/mojo/mojo_messages.h
index e9657dae66e..45133d73154 100644
--- a/chromium/content/common/mojo/mojo_messages.h
+++ b/chromium/content/common/mojo/mojo_messages.h
@@ -16,9 +16,8 @@
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
#define IPC_MESSAGE_START MojoMsgStart
// Mojo IPC is bootstrapped over Chrome IPC via this message.
IPC_MESSAGE_CONTROL1(MojoMsg_Activate,
- IPC::PlatformFileForTransit /* handle */);
+ IPC::PlatformFileForTransit /* handle */)
diff --git a/chromium/content/common/mojo/mojo_service_names.cc b/chromium/content/common/mojo/mojo_service_names.cc
deleted file mode 100644
index 26ff68ffe4c..00000000000
--- a/chromium/content/common/mojo/mojo_service_names.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 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 "content/common/mojo/mojo_service_names.h"
-
-namespace content {
-
-// Renderer-provided services:
-
-const char kRendererService_WebUISetup[] = "content:web_ui_setup";
-
-} // namespace content
diff --git a/chromium/content/common/mojo/mojo_service_names.h b/chromium/content/common/mojo/mojo_service_names.h
deleted file mode 100644
index 787b67dd0a8..00000000000
--- a/chromium/content/common/mojo/mojo_service_names.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 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 CONTENT_COMMON_SERVICE_CONSTANTS_H_
-#define CONTENT_COMMON_SERVICE_CONSTANTS_H_
-
-namespace content {
-
-// ----------------------------------------------------------------------------
-// Renderer-provided services:
-
-// WebUISetup <-> WebUISetupClient
-extern const char kRendererService_WebUISetup[];
-
-} // namespace content
-
-#endif // CONTENT_COMMON_SERVICE_CONSTANTS_H_
diff --git a/chromium/content/common/mojo/service_registry_impl.cc b/chromium/content/common/mojo/service_registry_impl.cc
new file mode 100644
index 00000000000..348d1d45c81
--- /dev/null
+++ b/chromium/content/common/mojo/service_registry_impl.cc
@@ -0,0 +1,81 @@
+// Copyright 2014 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 "content/common/mojo/service_registry_impl.h"
+
+#include "mojo/common/common_type_converters.h"
+
+namespace content {
+
+ServiceRegistryImpl::ServiceRegistryImpl()
+ : bound_(false), weak_factory_(this) {
+}
+
+ServiceRegistryImpl::ServiceRegistryImpl(mojo::ScopedMessagePipeHandle handle)
+ : bound_(false), weak_factory_(this) {
+ BindRemoteServiceProvider(handle.Pass());
+}
+
+ServiceRegistryImpl::~ServiceRegistryImpl() {
+ while (!pending_connects_.empty()) {
+ mojo::CloseRaw(pending_connects_.front().second);
+ pending_connects_.pop();
+ }
+}
+
+void ServiceRegistryImpl::BindRemoteServiceProvider(
+ mojo::ScopedMessagePipeHandle handle) {
+ CHECK(!bound_);
+ bound_ = true;
+ mojo::WeakBindToPipe(this, handle.Pass());
+ while (!pending_connects_.empty()) {
+ client()->ConnectToService(
+ mojo::String::From(pending_connects_.front().first),
+ mojo::ScopedMessagePipeHandle(pending_connects_.front().second));
+ pending_connects_.pop();
+ }
+}
+
+void ServiceRegistryImpl::OnConnectionError() {
+ // TODO(sammc): Support reporting this to our owner.
+}
+
+void ServiceRegistryImpl::AddService(
+ const std::string& service_name,
+ const base::Callback<void(mojo::ScopedMessagePipeHandle)> service_factory) {
+ service_factories_[service_name] = service_factory;
+}
+
+void ServiceRegistryImpl::RemoveService(const std::string& service_name) {
+ service_factories_.erase(service_name);
+}
+
+void ServiceRegistryImpl::ConnectToRemoteService(
+ const base::StringPiece& service_name,
+ mojo::ScopedMessagePipeHandle handle) {
+ if (!bound_) {
+ pending_connects_.push(
+ std::make_pair(service_name.as_string(), handle.release()));
+ return;
+ }
+ client()->ConnectToService(mojo::String::From(service_name), handle.Pass());
+}
+
+base::WeakPtr<ServiceRegistry> ServiceRegistryImpl::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+void ServiceRegistryImpl::ConnectToService(
+ const mojo::String& name,
+ mojo::ScopedMessagePipeHandle client_handle) {
+ std::map<std::string,
+ base::Callback<void(mojo::ScopedMessagePipeHandle)> >::iterator it =
+ service_factories_.find(name);
+ if (it == service_factories_.end())
+ return;
+
+ it->second.Run(client_handle.Pass());
+}
+
+} // namespace content
diff --git a/chromium/content/common/mojo/service_registry_impl.h b/chromium/content/common/mojo/service_registry_impl.h
new file mode 100644
index 00000000000..b3a6576b27a
--- /dev/null
+++ b/chromium/content/common/mojo/service_registry_impl.h
@@ -0,0 +1,64 @@
+// Copyright 2014 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 CONTENT_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_
+#define CONTENT_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_
+
+#include <map>
+#include <queue>
+#include <string>
+#include <utility>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/common/service_registry.h"
+#include "mojo/public/cpp/bindings/interface_impl.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/interfaces/application/service_provider.mojom.h"
+
+namespace content {
+
+class CONTENT_EXPORT ServiceRegistryImpl
+ : public ServiceRegistry,
+ public NON_EXPORTED_BASE(mojo::InterfaceImpl<mojo::ServiceProvider>) {
+ public:
+ ServiceRegistryImpl();
+ explicit ServiceRegistryImpl(mojo::ScopedMessagePipeHandle handle);
+ ~ServiceRegistryImpl() override;
+
+ // Binds to a remote ServiceProvider. This will expose added services to the
+ // remote ServiceProvider with the corresponding handle and enable
+ // ConnectToRemoteService to provide access to services exposed by the remote
+ // ServiceProvider.
+ void BindRemoteServiceProvider(mojo::ScopedMessagePipeHandle handle);
+
+ // ServiceRegistry overrides.
+ void AddService(const std::string& service_name,
+ const base::Callback<void(mojo::ScopedMessagePipeHandle)>
+ service_factory) override;
+ void RemoveService(const std::string& service_name) override;
+ void ConnectToRemoteService(const base::StringPiece& service_name,
+ mojo::ScopedMessagePipeHandle handle) override;
+
+ base::WeakPtr<ServiceRegistry> GetWeakPtr();
+
+ private:
+ // mojo::InterfaceImpl<mojo::ServiceProvider> overrides.
+ void ConnectToService(const mojo::String& name,
+ mojo::ScopedMessagePipeHandle client_handle) override;
+ void OnConnectionError() override;
+
+ std::map<std::string, base::Callback<void(mojo::ScopedMessagePipeHandle)> >
+ service_factories_;
+ std::queue<std::pair<std::string, mojo::MessagePipeHandle> >
+ pending_connects_;
+ bool bound_;
+
+ base::WeakPtrFactory<ServiceRegistry> weak_factory_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MOJO_SERVICE_REGISTRY_IMPL_H_
diff --git a/chromium/content/common/navigation_gesture.h b/chromium/content/common/navigation_gesture.h
index 5040d715fc2..380cd51fff7 100644
--- a/chromium/content/common/navigation_gesture.h
+++ b/chromium/content/common/navigation_gesture.h
@@ -16,6 +16,7 @@ enum NavigationGesture {
NavigationGestureAuto,
// Initial state.
NavigationGestureUnknown,
+ NavigationGestureLast = NavigationGestureUnknown
};
} // namespace content
diff --git a/chromium/content/common/navigation_params.cc b/chromium/content/common/navigation_params.cc
new file mode 100644
index 00000000000..31787acb975
--- /dev/null
+++ b/chromium/content/common/navigation_params.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 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 "content/common/navigation_params.h"
+
+#include "base/memory/ref_counted_memory.h"
+
+namespace content {
+CommonNavigationParams::CommonNavigationParams()
+ : transition(ui::PAGE_TRANSITION_LINK),
+ navigation_type(FrameMsg_Navigate_Type::NORMAL),
+ allow_download(true) {
+}
+
+CommonNavigationParams::~CommonNavigationParams() {}
+
+CommonNavigationParams::CommonNavigationParams(
+ const GURL& url,
+ const Referrer& referrer,
+ ui::PageTransition transition,
+ FrameMsg_Navigate_Type::Value navigation_type,
+ bool allow_download)
+ : url(url),
+ referrer(referrer),
+ transition(transition),
+ navigation_type(navigation_type),
+ allow_download(allow_download) {
+}
+
+RequestNavigationParams::RequestNavigationParams() : is_post(false) {}
+
+RequestNavigationParams::RequestNavigationParams(
+ bool is_post,
+ const std::string& extra_headers,
+ const base::RefCountedMemory* post_data)
+ : is_post(is_post),
+ extra_headers(extra_headers) {
+ if (post_data) {
+ browser_initiated_post_data.assign(
+ post_data->front(), post_data->front() + post_data->size());
+ }
+}
+
+RequestNavigationParams::~RequestNavigationParams() {}
+
+CommitNavigationParams::CommitNavigationParams()
+ : is_overriding_user_agent(false) {
+}
+
+CommitNavigationParams::CommitNavigationParams(const PageState& page_state,
+ bool is_overriding_user_agent,
+ base::TimeTicks navigation_start)
+ : page_state(page_state),
+ is_overriding_user_agent(is_overriding_user_agent),
+ browser_navigation_start(navigation_start) {
+}
+
+CommitNavigationParams::~CommitNavigationParams() {}
+
+} // namespace content
diff --git a/chromium/content/common/navigation_params.h b/chromium/content/common/navigation_params.h
new file mode 100644
index 00000000000..d30d382322d
--- /dev/null
+++ b/chromium/content/common/navigation_params.h
@@ -0,0 +1,104 @@
+// Copyright 2014 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 CONTENT_COMMON_NAVIGATION_PARAMS_H_
+#define CONTENT_COMMON_NAVIGATION_PARAMS_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "content/common/frame_message_enums.h"
+#include "content/public/common/page_state.h"
+#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
+#include "url/gurl.h"
+
+namespace base {
+class RefCountedMemory;
+}
+
+namespace content {
+class NavigationEntry;
+
+// The following structures hold parameters used during a navigation. In
+// particular they are used by FrameMsg_Navigate, FrameMsg_CommitNavigation and
+// FrameHostMsg_BeginNavigation.
+// TODO(clamy): Depending on the avancement of the history refactoring move the
+// history parameters from FrameMsg_Navigate into one of the structs.
+
+// Used by all navigation IPCs.
+struct CONTENT_EXPORT CommonNavigationParams {
+ CommonNavigationParams();
+ CommonNavigationParams(const GURL& url,
+ const Referrer& referrer,
+ ui::PageTransition transition,
+ FrameMsg_Navigate_Type::Value navigation_type,
+ bool allow_download);
+ ~CommonNavigationParams();
+
+ // The URL to navigate to.
+ // PlzNavigate: May be modified when the navigation is ready to commit.
+ GURL url;
+
+ // The URL to send in the "Referer" header field. Can be empty if there is
+ // no referrer.
+ Referrer referrer;
+
+ // The type of transition.
+ ui::PageTransition transition;
+
+ // Type of navigation.
+ FrameMsg_Navigate_Type::Value navigation_type;
+
+ // Allows the URL to be downloaded (true by default).
+ // Avoid downloading when in view-source mode.
+ bool allow_download;
+};
+
+// Used by FrameMsg_Navigate.
+// PlzNavigate: sent to the renderer when requesting a navigation.
+struct CONTENT_EXPORT RequestNavigationParams {
+ RequestNavigationParams();
+ RequestNavigationParams(bool is_post,
+ const std::string& extra_headers,
+ const base::RefCountedMemory* post_data);
+ ~RequestNavigationParams();
+
+ // Whether the navigation is a POST request (as opposed to a GET).
+ bool is_post;
+
+ // Extra headers (separated by \n) to send during the request.
+ std::string extra_headers;
+
+ // If is_post is true, holds the post_data information from browser. Empty
+ // otherwise.
+ std::vector<unsigned char> browser_initiated_post_data;
+};
+
+// Used by FrameMsg_Navigate.
+// PlzNavigate: sent to the renderer when the navigation is ready to commit.
+struct CONTENT_EXPORT CommitNavigationParams {
+ CommitNavigationParams();
+ CommitNavigationParams(const PageState& page_state,
+ bool is_overriding_user_agent,
+ base::TimeTicks navigation_start);
+ ~CommitNavigationParams();
+
+ // Opaque history state (received by ViewHostMsg_UpdateState).
+ PageState page_state;
+
+ // Whether or not the user agent override string should be used.
+ bool is_overriding_user_agent;
+
+ // The navigationStart time to expose through the Navigation Timing API to JS.
+ base::TimeTicks browser_navigation_start;
+
+ // TODO(clamy): Move the redirect chain here.
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_NAVIGATION_PARAMS_H_
diff --git a/chromium/content/common/net/url_request_user_data.h b/chromium/content/common/net/url_request_user_data.h
index f540becab87..58d97b7f32a 100644
--- a/chromium/content/common/net/url_request_user_data.h
+++ b/chromium/content/common/net/url_request_user_data.h
@@ -15,7 +15,7 @@ class URLRequestUserData : public base::SupportsUserData::Data {
public:
URLRequestUserData(int render_process_id,
int render_frame_id);
- virtual ~URLRequestUserData();
+ ~URLRequestUserData() override;
int render_process_id() const { return render_process_id_; }
int render_frame_id() const { return render_frame_id_; }
diff --git a/chromium/content/common/one_writer_seqlock_unittest.cc b/chromium/content/common/one_writer_seqlock_unittest.cc
new file mode 100644
index 00000000000..a72ab5d3b7b
--- /dev/null
+++ b/chromium/content/common/one_writer_seqlock_unittest.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2011 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 "content/common/one_writer_seqlock.h"
+
+#include <stdlib.h>
+
+#include "base/atomic_ref_count.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+#include "base/threading/platform_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+// Basic test to make sure that basic operation works correctly.
+
+struct TestData {
+ unsigned a, b, c;
+};
+
+class BasicSeqLockTestThread : public PlatformThread::Delegate {
+ public:
+ BasicSeqLockTestThread() {}
+
+ void Init(
+ content::OneWriterSeqLock* seqlock,
+ TestData* data,
+ base::subtle::Atomic32* ready) {
+ seqlock_ = seqlock;
+ data_ = data;
+ ready_ = ready;
+ }
+ void ThreadMain() override {
+ while (AtomicRefCountIsZero(ready_)) {
+ PlatformThread::YieldCurrentThread();
+ }
+
+ for (unsigned i = 0; i < 1000; ++i) {
+ TestData copy;
+ base::subtle::Atomic32 version;
+ do {
+ version = seqlock_->ReadBegin();
+ copy = *data_;
+ } while (seqlock_->ReadRetry(version));
+
+ EXPECT_EQ(copy.a + 100, copy.b);
+ EXPECT_EQ(copy.c, copy.b + copy.a);
+ }
+
+ AtomicRefCountDec(ready_);
+ }
+
+ private:
+ content::OneWriterSeqLock* seqlock_;
+ TestData* data_;
+ base::AtomicRefCount* ready_;
+
+ DISALLOW_COPY_AND_ASSIGN(BasicSeqLockTestThread);
+};
+
+TEST(OneWriterSeqLockTest, ManyThreads) {
+ content::OneWriterSeqLock seqlock;
+ TestData data = { 0, 0, 0 };
+ base::AtomicRefCount ready = 0;
+
+ ANNOTATE_BENIGN_RACE_SIZED(&data, sizeof(data), "Racey reads are discarded");
+
+ static const unsigned kNumReaderThreads = 10;
+ BasicSeqLockTestThread threads[kNumReaderThreads];
+ PlatformThreadHandle handles[kNumReaderThreads];
+
+ for (unsigned i = 0; i < kNumReaderThreads; ++i)
+ threads[i].Init(&seqlock, &data, &ready);
+ for (unsigned i = 0; i < kNumReaderThreads; ++i)
+ ASSERT_TRUE(PlatformThread::Create(0, &threads[i], &handles[i]));
+
+ // The main thread is the writer, and the spawned are readers.
+ unsigned counter = 0;
+ for (;;) {
+ seqlock.WriteBegin();
+ data.a = counter++;
+ data.b = data.a + 100;
+ data.c = data.b + data.a;
+ seqlock.WriteEnd();
+
+ if (counter == 1)
+ base::AtomicRefCountIncN(&ready, kNumReaderThreads);
+
+ if (AtomicRefCountIsZero(&ready))
+ break;
+ }
+
+ for (unsigned i = 0; i < kNumReaderThreads; ++i)
+ PlatformThread::Join(handles[i]);
+}
+
+} // namespace base
diff --git a/chromium/content/common/p2p_messages.h b/chromium/content/common/p2p_messages.h
index 9f8c201b80e..e1237947743 100644
--- a/chromium/content/common/p2p_messages.h
+++ b/chromium/content/common/p2p_messages.h
@@ -10,7 +10,7 @@
#include "content/common/p2p_socket_type.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/net_util.h"
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
+#include "third_party/webrtc/base/asyncpacketsocket.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -20,24 +20,26 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::P2PSocketType,
content::P2P_SOCKET_TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(content::P2PSocketOption,
content::P2P_SOCKET_OPT_MAX - 1)
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(talk_base::DiffServCodePoint,
- talk_base::DSCP_NO_CHANGE,
- talk_base::DSCP_CS7)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(rtc::DiffServCodePoint,
+ rtc::DSCP_NO_CHANGE,
+ rtc::DSCP_CS7)
IPC_STRUCT_TRAITS_BEGIN(net::NetworkInterface)
IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(address)
+ IPC_STRUCT_TRAITS_MEMBER(network_prefix)
+ IPC_STRUCT_TRAITS_MEMBER(ip_address_attributes)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(talk_base::PacketTimeUpdateParams)
+IPC_STRUCT_TRAITS_BEGIN(rtc::PacketTimeUpdateParams)
IPC_STRUCT_TRAITS_MEMBER(rtp_sendtime_extension_id)
IPC_STRUCT_TRAITS_MEMBER(srtp_auth_key)
IPC_STRUCT_TRAITS_MEMBER(srtp_auth_tag_len)
IPC_STRUCT_TRAITS_MEMBER(srtp_packet_index)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(talk_base::PacketOptions)
+IPC_STRUCT_TRAITS_BEGIN(rtc::PacketOptions)
IPC_STRUCT_TRAITS_MEMBER(dscp)
IPC_STRUCT_TRAITS_MEMBER(packet_time_params)
IPC_STRUCT_TRAITS_END()
@@ -56,9 +58,10 @@ IPC_MESSAGE_CONTROL2(P2PMsg_GetHostAddressResult,
int32 /* request_id */,
net::IPAddressList /* address list*/)
-IPC_MESSAGE_CONTROL2(P2PMsg_OnSocketCreated,
+IPC_MESSAGE_CONTROL3(P2PMsg_OnSocketCreated,
int /* socket_id */,
- net::IPEndPoint /* socket_address */)
+ net::IPEndPoint /* local_address */,
+ net::IPEndPoint /* remote_address */)
IPC_MESSAGE_CONTROL1(P2PMsg_OnSendComplete,
int /* socket_id */)
@@ -103,7 +106,7 @@ IPC_MESSAGE_CONTROL5(P2PHostMsg_Send,
int /* socket_id */,
net::IPEndPoint /* socket_address */,
std::vector<char> /* data */,
- talk_base::PacketOptions /* packet options */,
+ rtc::PacketOptions /* packet options */,
uint64 /* packet_id */)
IPC_MESSAGE_CONTROL1(P2PHostMsg_DestroySocket,
diff --git a/chromium/content/common/page_state_serialization.cc b/chromium/content/common/page_state_serialization.cc
index 9239d030ccb..d99830a2ce2 100644
--- a/chromium/content/common/page_state_serialization.cc
+++ b/chromium/content/common/page_state_serialization.cc
@@ -193,12 +193,13 @@ struct SerializeObject {
// which is no longer used.
// 20: Add pinch viewport scroll offset, the offset of the pinched zoomed
// viewport within the unzoomed main frame.
+// 21: Add frame sequence number
//
// NOTE: If the version is -1, then the pickle contains only a URL string.
// See ReadPageState.
//
const int kMinVersion = 11;
-const int kCurrentVersion = 20;
+const int kCurrentVersion = 21;
// A bunch of convenience functions to read/write to SerializeObjects. The
// de-serializers assume the input data will be in the correct format and fall
@@ -231,10 +232,6 @@ int ReadInteger(SerializeObject* obj) {
return 0;
}
-void ConsumeInteger(SerializeObject* obj) {
- int unused ALLOW_UNUSED = ReadInteger(obj);
-}
-
void WriteInteger64(int64 data, SerializeObject* obj) {
obj->pickle.WriteInt64(data);
}
@@ -247,10 +244,6 @@ int64 ReadInteger64(SerializeObject* obj) {
return 0;
}
-void ConsumeInteger64(SerializeObject* obj) {
- int64 unused ALLOW_UNUSED = ReadInteger64(obj);
-}
-
void WriteReal(double data, SerializeObject* obj) {
WriteData(&data, sizeof(double), obj);
}
@@ -269,10 +262,6 @@ double ReadReal(SerializeObject* obj) {
return value;
}
-void ConsumeReal(SerializeObject* obj) {
- double unused ALLOW_UNUSED = ReadReal(obj);
-}
-
void WriteBoolean(bool data, SerializeObject* obj) {
obj->pickle.WriteInt(data ? 1 : 0);
}
@@ -285,10 +274,6 @@ bool ReadBoolean(SerializeObject* obj) {
return false;
}
-void ConsumeBoolean(SerializeObject* obj) {
- bool unused ALLOW_UNUSED = ReadBoolean(obj);
-}
-
void WriteGURL(const GURL& url, SerializeObject* obj) {
obj->pickle.WriteString(url.possibly_invalid_spec());
}
@@ -361,10 +346,6 @@ base::NullableString16 ReadString(SerializeObject* obj) {
base::NullableString16();
}
-void ConsumeString(SerializeObject* obj) {
- const base::char16* unused ALLOW_UNUSED = ReadStringNoCopy(obj, NULL);
-}
-
template <typename T>
void WriteAndValidateVectorSize(const std::vector<T>& v, SerializeObject* obj) {
CHECK_LT(v.size(), std::numeric_limits<int>::max() / sizeof(T));
@@ -511,6 +492,7 @@ void WriteFrameState(
WriteReal(state.page_scale_factor, obj);
WriteInteger64(state.item_sequence_number, obj);
WriteInteger64(state.document_sequence_number, obj);
+ WriteInteger64(state.frame_sequence_number, obj);
WriteInteger(state.referrer_policy, obj);
WriteReal(state.pinch_viewport_scroll_offset.x(), obj);
WriteReal(state.pinch_viewport_scroll_offset.y(), obj);
@@ -537,19 +519,19 @@ void WriteFrameState(
void ReadFrameState(SerializeObject* obj, bool is_top,
ExplodedFrameState* state) {
if (obj->version < 14 && !is_top)
- ConsumeInteger(obj); // Skip over redundant version field.
+ ReadInteger(obj); // Skip over redundant version field.
state->url_string = ReadString(obj);
if (obj->version < 19)
- ConsumeString(obj); // Skip obsolete original url string field.
+ ReadString(obj); // Skip obsolete original url string field.
state->target = ReadString(obj);
if (obj->version < 15) {
- ConsumeString(obj); // Skip obsolete parent field.
- ConsumeString(obj); // Skip obsolete title field.
- ConsumeString(obj); // Skip obsolete alternate title field.
- ConsumeReal(obj); // Skip obsolete visited time field.
+ ReadString(obj); // Skip obsolete parent field.
+ ReadString(obj); // Skip obsolete title field.
+ ReadString(obj); // Skip obsolete alternate title field.
+ ReadReal(obj); // Skip obsolete visited time field.
}
int x = ReadInteger(obj);
@@ -557,8 +539,8 @@ void ReadFrameState(SerializeObject* obj, bool is_top,
state->scroll_offset = gfx::Point(x, y);
if (obj->version < 15) {
- ConsumeBoolean(obj); // Skip obsolete target item flag.
- ConsumeInteger(obj); // Skip obsolete visit count field.
+ ReadBoolean(obj); // Skip obsolete target item flag.
+ ReadInteger(obj); // Skip obsolete visit count field.
}
state->referrer = ReadString(obj);
@@ -567,9 +549,11 @@ void ReadFrameState(SerializeObject* obj, bool is_top,
state->page_scale_factor = ReadReal(obj);
state->item_sequence_number = ReadInteger64(obj);
state->document_sequence_number = ReadInteger64(obj);
+ if (obj->version >= 21)
+ state->frame_sequence_number = ReadInteger64(obj);
if (obj->version >= 17 && obj->version < 19)
- ConsumeInteger64(obj); // Skip obsolete target frame id number.
+ ReadInteger64(obj); // Skip obsolete target frame id number.
if (obj->version >= 18) {
state->referrer_policy =
@@ -596,7 +580,7 @@ void ReadFrameState(SerializeObject* obj, bool is_top,
state->http_body.http_content_type = ReadString(obj);
if (obj->version < 14)
- ConsumeString(obj); // Skip unused referrer string.
+ ReadString(obj); // Skip unused referrer string.
#if defined(OS_ANDROID)
if (obj->version == 11) {
@@ -692,13 +676,40 @@ ExplodedHttpBody::~ExplodedHttpBody() {
ExplodedFrameState::ExplodedFrameState()
: item_sequence_number(0),
document_sequence_number(0),
+ frame_sequence_number(0),
page_scale_factor(0.0),
referrer_policy(blink::WebReferrerPolicyDefault) {
}
+ExplodedFrameState::ExplodedFrameState(const ExplodedFrameState& other) {
+ assign(other);
+}
+
ExplodedFrameState::~ExplodedFrameState() {
}
+void ExplodedFrameState::operator=(const ExplodedFrameState& other) {
+ if (&other != this)
+ assign(other);
+}
+
+void ExplodedFrameState::assign(const ExplodedFrameState& other) {
+ url_string = other.url_string;
+ referrer = other.referrer;
+ target = other.target;
+ state_object = other.state_object;
+ document_state = other.document_state;
+ pinch_viewport_scroll_offset = other.pinch_viewport_scroll_offset;
+ scroll_offset = other.scroll_offset;
+ item_sequence_number = other.item_sequence_number;
+ document_sequence_number = other.document_sequence_number;
+ frame_sequence_number = other.frame_sequence_number;
+ page_scale_factor = other.page_scale_factor;
+ referrer_policy = other.referrer_policy;
+ http_body = other.http_body;
+ children = other.children;
+}
+
ExplodedPageState::ExplodedPageState() {
}
diff --git a/chromium/content/common/page_state_serialization.h b/chromium/content/common/page_state_serialization.h
index d3d3b029739..e31780fd3c3 100644
--- a/chromium/content/common/page_state_serialization.h
+++ b/chromium/content/common/page_state_serialization.h
@@ -52,13 +52,19 @@ struct CONTENT_EXPORT ExplodedFrameState {
gfx::Point scroll_offset;
int64 item_sequence_number;
int64 document_sequence_number;
+ int64 frame_sequence_number;
double page_scale_factor;
blink::WebReferrerPolicy referrer_policy;
ExplodedHttpBody http_body;
std::vector<ExplodedFrameState> children;
ExplodedFrameState();
+ ExplodedFrameState(const ExplodedFrameState& other);
~ExplodedFrameState();
+ void operator=(const ExplodedFrameState& other);
+
+private:
+ void assign(const ExplodedFrameState& other);
};
struct CONTENT_EXPORT ExplodedPageState {
diff --git a/chromium/content/common/page_state_serialization_unittest.cc b/chromium/content/common/page_state_serialization_unittest.cc
index 39ff3f2c8bf..3c25bccd565 100644
--- a/chromium/content/common/page_state_serialization_unittest.cc
+++ b/chromium/content/common/page_state_serialization_unittest.cc
@@ -5,7 +5,7 @@
#include <math.h>
#include "base/base64.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/pickle.h"
#include "base/strings/string_util.h"
@@ -105,6 +105,7 @@ class PageStateSerializationTest : public testing::Test {
frame_state->scroll_offset = gfx::Point(0, 100);
frame_state->item_sequence_number = 1;
frame_state->document_sequence_number = 2;
+ frame_state->frame_sequence_number = 3;
frame_state->page_scale_factor = 2.0;
}
@@ -143,6 +144,7 @@ class PageStateSerializationTest : public testing::Test {
frame_state->scroll_offset = gfx::Point(42, -42);
frame_state->item_sequence_number = 123;
frame_state->document_sequence_number = 456;
+ frame_state->frame_sequence_number = 789;
frame_state->page_scale_factor = 2.0f;
frame_state->document_state.push_back(
@@ -424,5 +426,9 @@ TEST_F(PageStateSerializationTest, BackwardsCompat_v18) {
TestBackwardsCompat(18);
}
+TEST_F(PageStateSerializationTest, BackwardsCompat_v20) {
+ TestBackwardsCompat(20);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/pepper_file_util.cc b/chromium/content/common/pepper_file_util.cc
new file mode 100644
index 00000000000..fea5ef24cf3
--- /dev/null
+++ b/chromium/content/common/pepper_file_util.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 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 "content/common/pepper_file_util.h"
+
+namespace content {
+
+storage::FileSystemType PepperFileSystemTypeToFileSystemType(
+ PP_FileSystemType type) {
+ switch (type) {
+ case PP_FILESYSTEMTYPE_LOCALTEMPORARY:
+ return storage::kFileSystemTypeTemporary;
+ case PP_FILESYSTEMTYPE_LOCALPERSISTENT:
+ return storage::kFileSystemTypePersistent;
+ case PP_FILESYSTEMTYPE_EXTERNAL:
+ return storage::kFileSystemTypeExternal;
+ default:
+ return storage::kFileSystemTypeUnknown;
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/pepper_file_util.h b/chromium/content/common/pepper_file_util.h
new file mode 100644
index 00000000000..aab9c1d63fc
--- /dev/null
+++ b/chromium/content/common/pepper_file_util.h
@@ -0,0 +1,22 @@
+// Copyright 2014 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 CONTENT_COMMON_PEPPER_FILE_UTIL_H_
+#define CONTENT_COMMON_PEPPER_FILE_UTIL_H_
+
+#include "ppapi/c/pp_file_info.h"
+#include "storage/common/fileapi/file_system_types.h"
+
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
+namespace content {
+
+storage::FileSystemType PepperFileSystemTypeToFileSystemType(
+ PP_FileSystemType type);
+
+} // namespace content
+
+#endif // CONTENT_COMMON_PEPPER_FILE_UTIL_H_
diff --git a/chromium/content/common/pepper_plugin_list.cc b/chromium/content/common/pepper_plugin_list.cc
index fac77f6f2e4..81eda1aeac5 100644
--- a/chromium/content/common/pepper_plugin_list.cc
+++ b/chromium/content/common/pepper_plugin_list.cc
@@ -6,7 +6,7 @@
#include "base/basictypes.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -36,11 +36,12 @@ void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
max_plugins_to_register_from_command_line_exceeds_limit);
bool out_of_process = true;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiInProcess))
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kPpapiInProcess))
out_of_process = false;
const std::string value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kRegisterPepperPlugins);
if (value.empty())
return;
diff --git a/chromium/content/common/pepper_plugin_list.h b/chromium/content/common/pepper_plugin_list.h
index d460e084778..1d06419b5f1 100644
--- a/chromium/content/common/pepper_plugin_list.h
+++ b/chromium/content/common/pepper_plugin_list.h
@@ -7,7 +7,12 @@
#include <vector>
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
namespace content {
+
struct PepperPluginInfo;
struct WebPluginInfo;
diff --git a/chromium/content/common/pepper_renderer_instance_data.h b/chromium/content/common/pepper_renderer_instance_data.h
index e39017dcb1b..6b3baa40059 100644
--- a/chromium/content/common/pepper_renderer_instance_data.h
+++ b/chromium/content/common/pepper_renderer_instance_data.h
@@ -7,6 +7,10 @@
#include "url/gurl.h"
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
namespace content {
// This struct contains data which is associated with a particular plugin
diff --git a/chromium/content/common/platform_notification_messages.h b/chromium/content/common/platform_notification_messages.h
new file mode 100644
index 00000000000..1585165af7f
--- /dev/null
+++ b/chromium/content/common/platform_notification_messages.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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.
+
+// Messages for platform-native notifications using the Web Notification API.
+// Multiply-included message file, hence no include guard.
+
+#include "content/public/common/show_desktop_notification_params.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebNotificationPermission.h"
+#include "url/gurl.h"
+
+#define IPC_MESSAGE_START PlatformNotificationMsgStart
+
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebNotificationPermission,
+ blink::WebNotificationPermissionLast)
+
+// Messages sent from the browser to the renderer.
+
+// Informs the renderer that the permission request for |request_id| is done,
+// and has been settled with |result|.
+IPC_MESSAGE_ROUTED2(PlatformNotificationMsg_PermissionRequestComplete,
+ int /* request_id */,
+ blink::WebNotificationPermission /* result */)
+
+// Informs the renderer that the browser has displayed the notification.
+IPC_MESSAGE_CONTROL1(PlatformNotificationMsg_DidShow,
+ int /* notification_id */)
+
+// Informs the renderer that the notification has been closed.
+IPC_MESSAGE_CONTROL1(PlatformNotificationMsg_DidClose,
+ int /* notification_id */)
+
+// Informs the renderer that the notification has been clicked on.
+IPC_MESSAGE_CONTROL1(PlatformNotificationMsg_DidClick,
+ int /* notification_id */)
+
+// Messages sent from the renderer to the browser.
+
+// Requests permission to display platform notifications for |origin|.
+IPC_MESSAGE_ROUTED2(PlatformNotificationHostMsg_RequestPermission,
+ GURL /* origin */,
+ int /* request_id */)
+
+IPC_MESSAGE_CONTROL2(PlatformNotificationHostMsg_Show,
+ int /* notification_id */,
+ content::ShowDesktopNotificationHostMsgParams /* params */)
+
+IPC_MESSAGE_CONTROL1(PlatformNotificationHostMsg_Close,
+ int /* notification_id */)
+
+IPC_SYNC_MESSAGE_CONTROL1_1(PlatformNotificationHostMsg_CheckPermission,
+ GURL /* origin */,
+ blink::WebNotificationPermission /* result */)
diff --git a/chromium/content/common/plugin_carbon_interpose_constants_mac.cc b/chromium/content/common/plugin_carbon_interpose_constants_mac.cc
deleted file mode 100644
index e187e984583..00000000000
--- a/chromium/content/common/plugin_carbon_interpose_constants_mac.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011 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.
-
-#if !defined(__LP64__)
-
-#include "content/common/plugin_carbon_interpose_constants_mac.h"
-
-namespace content {
-
-const char kDYLDInsertLibrariesKey[] = "DYLD_INSERT_LIBRARIES";
-
-} // namespace content
-
-#endif // !__LP64__
diff --git a/chromium/content/common/plugin_carbon_interpose_constants_mac.h b/chromium/content/common/plugin_carbon_interpose_constants_mac.h
deleted file mode 100644
index 1ac9ee5fae2..00000000000
--- a/chromium/content/common/plugin_carbon_interpose_constants_mac.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_
-#define CONTENT_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_
-
-#if !defined(__LP64__)
-
-// Strings used in setting up Carbon interposing for the plugin process.
-namespace content {
-
-extern const char kDYLDInsertLibrariesKey[];
-
-} // namespace content
-
-#endif // !__LP64__
-
-#endif // CONTENT_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_
diff --git a/chromium/content/common/plugin_constants_win.cc b/chromium/content/common/plugin_constants_win.cc
index edaeffd6b2e..026885677e2 100644
--- a/chromium/content/common/plugin_constants_win.cc
+++ b/chromium/content/common/plugin_constants_win.cc
@@ -9,8 +9,6 @@ namespace content {
const base::char16 kNativeWindowClassName[] = L"NativeWindowClass";
const base::char16 kWrapperNativeWindowClassName[] =
L"WrapperNativeWindowClass";
-const base::char16 kPluginNameAtomProperty[] = L"PluginNameAtom";
-const base::char16 kPluginVersionAtomProperty[] = L"PluginVersionAtom";
const base::char16 kDummyActivationWindowName[] = L"DummyWindowForActivation";
const base::char16 kPaintMessageName[] = L"Chrome_CustomPaintil";
const base::char16 kRegistryMozillaPlugins[] = L"SOFTWARE\\MozillaPlugins";
diff --git a/chromium/content/common/plugin_constants_win.h b/chromium/content/common/plugin_constants_win.h
index d796730a697..49920f48254 100644
--- a/chromium/content/common/plugin_constants_win.h
+++ b/chromium/content/common/plugin_constants_win.h
@@ -21,8 +21,6 @@ extern const base::char16 kNativeWindowClassName[];
// is created on the browser UI thread.
extern const base::char16 kWrapperNativeWindowClassName[];
-extern const base::char16 kPluginNameAtomProperty[];
-extern const base::char16 kPluginVersionAtomProperty[];
extern const base::char16 kDummyActivationWindowName[];
// The name of the custom window message that the browser uses to tell the
diff --git a/chromium/content/common/plugin_list.cc b/chromium/content/common/plugin_list.cc
index ea74a706fe4..a0f9507ea9d 100644
--- a/chromium/content/common/plugin_list.cc
+++ b/chromium/content/common/plugin_list.cc
@@ -36,7 +36,7 @@ PluginList* PluginList::Singleton() {
// static
bool PluginList::DebugPluginLoading() {
- return CommandLine::ForCurrentProcess()->HasSwitch(
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDebugPluginLoading);
}
@@ -143,7 +143,7 @@ bool PluginList::ParseMimeTypes(
for (size_t i = 0; i < mime_types.size(); ++i) {
WebPluginMimeType mime_type;
- mime_type.mime_type = StringToLowerASCII(mime_types[i]);
+ mime_type.mime_type = base::StringToLowerASCII(mime_types[i]);
if (file_extensions.size() > i)
base::SplitString(file_extensions[i], ',', &mime_type.file_extensions);
@@ -313,7 +313,7 @@ void PluginList::GetPluginInfoArray(
bool include_npapi,
std::vector<WebPluginInfo>* info,
std::vector<std::string>* actual_mime_types) {
- DCHECK(mime_type == StringToLowerASCII(mime_type));
+ DCHECK(mime_type == base::StringToLowerASCII(mime_type));
DCHECK(info);
if (!use_stale)
@@ -348,7 +348,8 @@ void PluginList::GetPluginInfoArray(
std::string path = url.path();
std::string::size_type last_dot = path.rfind('.');
if (last_dot != std::string::npos && mime_type.empty()) {
- std::string extension = StringToLowerASCII(std::string(path, last_dot+1));
+ std::string extension =
+ base::StringToLowerASCII(std::string(path, last_dot+1));
std::string actual_mime_type;
for (size_t i = 0; i < plugins_list_.size(); ++i) {
if (SupportsExtension(plugins_list_[i], extension, &actual_mime_type)) {
diff --git a/chromium/content/common/plugin_list.h b/chromium/content/common/plugin_list.h
index 2f775d20b4c..9ad67fc8634 100644
--- a/chromium/content/common/plugin_list.h
+++ b/chromium/content/common/plugin_list.h
@@ -14,12 +14,14 @@
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_vector.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/public/common/webplugininfo.h"
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
class GURL;
namespace content {
diff --git a/chromium/content/common/plugin_list_mac.mm b/chromium/content/common/plugin_list_mac.mm
index 8ac4a65e605..8400dceb36a 100644
--- a/chromium/content/common/plugin_list_mac.mm
+++ b/chromium/content/common/plugin_list_mac.mm
@@ -7,8 +7,8 @@
#import <Carbon/Carbon.h>
#import <Foundation/Foundation.h>
-#include "base/file_util.h"
#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
diff --git a/chromium/content/common/plugin_list_win.cc b/chromium/content/common/plugin_list_win.cc
index e7d4b4b904b..ccc994b8f55 100644
--- a/chromium/content/common/plugin_list_win.cc
+++ b/chromium/content/common/plugin_list_win.cc
@@ -7,9 +7,9 @@
#include <set>
#include "base/basictypes.h"
-#include "base/file_util.h"
#include "base/file_version_info.h"
#include "base/file_version_info_win.h"
+#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
@@ -93,17 +93,19 @@ bool GetInstalledPath(const base::char16* app, base::FilePath* out) {
}
// Search the registry at the given path and detect plugin directories.
-void GetPluginsInRegistryDirectory(
- HKEY root_key,
- const base::string16& registry_folder,
- std::set<base::FilePath>* plugin_dirs) {
- for (base::win::RegistryKeyIterator iter(root_key, registry_folder.c_str());
- iter.Valid(); ++iter) {
+void GetPluginsInRegistryDirectory(HKEY root_key,
+ const base::string16& registry_folder,
+ REGSAM wow64_access,
+ std::set<base::FilePath>* plugin_dirs) {
+ for (base::win::RegistryKeyIterator iter(
+ root_key, registry_folder.c_str(), wow64_access);
+ iter.Valid();
+ ++iter) {
// Use the registry to gather plugin across the file system.
base::string16 reg_path = registry_folder;
reg_path.append(L"\\");
reg_path.append(iter.Name());
- base::win::RegKey key(root_key, reg_path.c_str(), KEY_READ);
+ base::win::RegKey key(root_key, reg_path.c_str(), KEY_READ | wow64_access);
base::string16 path;
if (key.ReadValue(kRegistryPath, &path) == ERROR_SUCCESS)
@@ -115,7 +117,8 @@ void GetPluginsInRegistryDirectory(
// FireFox 3 beta and version 2 can coexist. See bug: 1025003
void GetFirefoxInstalledPaths(std::vector<base::FilePath>* out) {
base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE,
- kRegistryFirefoxInstalled);
+ kRegistryFirefoxInstalled,
+ KEY_WOW64_32KEY);
for (; it.Valid(); ++it) {
base::string16 full_path = base::string16(kRegistryFirefoxInstalled) +
L"\\" + it.Name() + L"\\Main";
@@ -359,10 +362,16 @@ void PluginList::GetPluginPathsFromRegistry(
std::set<base::FilePath> plugin_dirs;
- GetPluginsInRegistryDirectory(
- HKEY_CURRENT_USER, kRegistryMozillaPlugins, &plugin_dirs);
- GetPluginsInRegistryDirectory(
- HKEY_LOCAL_MACHINE, kRegistryMozillaPlugins, &plugin_dirs);
+ // Search for plugins from HKCU and HKLM. THis will only find plugins that
+ // are correctly registered in the correct WOW64 registry hive.
+ GetPluginsInRegistryDirectory(HKEY_CURRENT_USER,
+ kRegistryMozillaPlugins,
+ 0,
+ &plugin_dirs);
+ GetPluginsInRegistryDirectory(HKEY_LOCAL_MACHINE,
+ kRegistryMozillaPlugins,
+ 0,
+ &plugin_dirs);
for (std::set<base::FilePath>::iterator i = plugin_dirs.begin();
i != plugin_dirs.end(); ++i) {
@@ -384,9 +393,9 @@ bool PluginList::ShouldLoadPluginUsingPluginList(
if (should_check_version) {
for (size_t j = 0; j < plugins->size(); ++j) {
base::FilePath::StringType plugin1 =
- StringToLowerASCII((*plugins)[j].path.BaseName().value());
+ base::StringToLowerASCII((*plugins)[j].path.BaseName().value());
base::FilePath::StringType plugin2 =
- StringToLowerASCII(info.path.BaseName().value());
+ base::StringToLowerASCII(info.path.BaseName().value());
if ((plugin1 == plugin2 && HaveSharedMimeType((*plugins)[j], info)) ||
(plugin1 == kJavaDeploy1 && plugin2 == kJavaDeploy2) ||
(plugin1 == kJavaDeploy2 && plugin2 == kJavaDeploy1)) {
@@ -413,7 +422,7 @@ bool PluginList::ShouldLoadPluginUsingPluginList(
// Troublemakers.
base::FilePath::StringType filename =
- StringToLowerASCII(info.path.BaseName().value());
+ base::StringToLowerASCII(info.path.BaseName().value());
// Depends on XPCOM.
if (filename == kMozillaActiveXPlugin)
return false;
diff --git a/chromium/content/common/plugin_process_messages.h b/chromium/content/common/plugin_process_messages.h
index 5eb75449921..c520dcc025e 100644
--- a/chromium/content/common/plugin_process_messages.h
+++ b/chromium/content/common/plugin_process_messages.h
@@ -10,6 +10,7 @@
#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
@@ -67,13 +68,6 @@ IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed,
// menu bar, etc. We pass the window rect for convenience so that the
// browser can easily tell if the window is fullscreen.
-// Notifies the browser that the plugin has selected a window (i.e., brought
-// it to the front and wants it to have keyboard focus).
-IPC_MESSAGE_CONTROL3(PluginProcessHostMsg_PluginSelectWindow,
- uint32 /* window ID */,
- gfx::Rect /* window rect */,
- bool /* modal */)
-
// Notifies the browser that the plugin has shown a window.
IPC_MESSAGE_CONTROL3(PluginProcessHostMsg_PluginShowWindow,
uint32 /* window ID */,
diff --git a/chromium/content/common/process_type.cc b/chromium/content/common/process_type.cc
index c4e293b0c7b..d3c6894242f 100644
--- a/chromium/content/common/process_type.cc
+++ b/chromium/content/common/process_type.cc
@@ -17,8 +17,6 @@ std::string GetProcessTypeNameInEnglish(int type) {
return "Tab";
case PROCESS_TYPE_PLUGIN:
return "Plug-in";
- case PROCESS_TYPE_WORKER:
- return "Web Worker";
case PROCESS_TYPE_UTILITY:
return "Utility";
case PROCESS_TYPE_ZYGOTE:
diff --git a/chromium/content/common/push_messaging_messages.h b/chromium/content/common/push_messaging_messages.h
index 75b2b68472a..40a1a4b0400 100644
--- a/chromium/content/common/push_messaging_messages.h
+++ b/chromium/content/common/push_messaging_messages.h
@@ -5,24 +5,54 @@
// IPC messages for push messaging.
// Multiply-included message file, hence no include guard.
+#include "content/public/common/push_messaging_status.h"
#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebPushPermissionStatus.h"
#include "url/gurl.h"
#define IPC_MESSAGE_START PushMessagingMsgStart
+IPC_ENUM_TRAITS_MAX_VALUE(content::PushRegistrationStatus,
+ content::PUSH_REGISTRATION_STATUS_LAST)
+
+IPC_ENUM_TRAITS_MAX_VALUE(
+ blink::WebPushPermissionStatus,
+ blink::WebPushPermissionStatus::WebPushPermissionStatusLast)
// Messages sent from the browser to the renderer.
IPC_MESSAGE_ROUTED3(PushMessagingMsg_RegisterSuccess,
int32 /* callbacks_id */,
- GURL /* endpoint */,
- std::string /* registration_id */)
+ GURL /* push_endpoint */,
+ std::string /* push_registration_id */)
+
+IPC_MESSAGE_ROUTED2(PushMessagingMsg_RegisterError,
+ int32 /* callbacks_id */,
+ content::PushRegistrationStatus /* status */)
+
+IPC_MESSAGE_ROUTED2(PushMessagingMsg_PermissionStatusResult,
+ int32 /* callback_id */,
+ blink::WebPushPermissionStatus /* status */)
+
+IPC_MESSAGE_ROUTED1(PushMessagingMsg_PermissionStatusFailure,
+ int32 /* callback_id */)
-IPC_MESSAGE_ROUTED1(PushMessagingMsg_RegisterError,
- int32 /* callbacks_id */)
+IPC_MESSAGE_ROUTED1(PushMessagingMsg_RequestPermissionResponse,
+ int32 /* request_id */)
// Messages sent from the renderer to the browser.
-IPC_MESSAGE_CONTROL3(PushMessagingHostMsg_Register,
- int32 /* routing_id */,
+IPC_MESSAGE_CONTROL5(PushMessagingHostMsg_Register,
+ int32 /* render_frame_id */,
int32 /* callbacks_id */,
- std::string /* sender_id */)
+ std::string /* sender_id */,
+ bool /* user_gesture */,
+ int32 /* service_worker_provider_id */)
+
+IPC_MESSAGE_CONTROL3(PushMessagingHostMsg_PermissionStatus,
+ int32 /* render_frame_id */,
+ int32 /* service_worker_provider_id */,
+ int32 /* permission_callback_id */)
+
+IPC_MESSAGE_ROUTED2(PushMessagingHostMsg_RequestPermission,
+ int32 /* request_id */,
+ bool /* user_gesture */)
diff --git a/chromium/content/common/quota_messages.h b/chromium/content/common/quota_messages.h
index bbfd6e684f2..5551210f4ee 100644
--- a/chromium/content/common/quota_messages.h
+++ b/chromium/content/common/quota_messages.h
@@ -7,13 +7,13 @@
#include "base/basictypes.h"
#include "content/public/common/storage_quota_params.h"
#include "ipc/ipc_message_macros.h"
+#include "storage/common/quota/quota_types.h"
#include "url/gurl.h"
-#include "webkit/common/quota/quota_types.h"
#define IPC_MESSAGE_START QuotaMsgStart
-IPC_ENUM_TRAITS_MAX_VALUE(quota::StorageType, quota::kStorageTypeLast)
-IPC_ENUM_TRAITS(quota::QuotaStatusCode)
+IPC_ENUM_TRAITS_MAX_VALUE(storage::StorageType, storage::kStorageTypeLast)
+IPC_ENUM_TRAITS(storage::QuotaStatusCode)
IPC_STRUCT_TRAITS_BEGIN(content::StorageQuotaParams)
IPC_STRUCT_TRAITS_MEMBER(render_view_id)
@@ -38,14 +38,14 @@ IPC_MESSAGE_CONTROL3(QuotaMsg_DidQueryStorageUsageAndQuota,
IPC_MESSAGE_CONTROL2(QuotaMsg_DidFail,
int /* request_id */,
- quota::QuotaStatusCode /* error */)
+ storage::QuotaStatusCode /* error */)
// Quota messages sent from the child process to the browser.
IPC_MESSAGE_CONTROL3(QuotaHostMsg_QueryStorageUsageAndQuota,
int /* request_id */,
GURL /* origin_url */,
- quota::StorageType /* type */)
+ storage::StorageType /* type */)
IPC_MESSAGE_CONTROL1(QuotaHostMsg_RequestStorageQuota,
content::StorageQuotaParams)
diff --git a/chromium/content/common/render_frame_setup.mojom b/chromium/content/common/render_frame_setup.mojom
new file mode 100644
index 00000000000..0a1d433447d
--- /dev/null
+++ b/chromium/content/common/render_frame_setup.mojom
@@ -0,0 +1,12 @@
+// Copyright 2014 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.
+
+module content;
+
+import "mojo/public/interfaces/application/service_provider.mojom";
+
+interface RenderFrameSetup {
+ GetServiceProviderForFrame(int32 frame_routing_id,
+ mojo.ServiceProvider& service_provider);
+};
diff --git a/chromium/content/common/resource_messages.cc b/chromium/content/common/resource_messages.cc
index bdae2e2dd08..1e7632db9ea 100644
--- a/chromium/content/common/resource_messages.cc
+++ b/chromium/content/common/resource_messages.cc
@@ -33,23 +33,21 @@ void ParamTraits<scoped_refptr<net::HttpResponseHeaders> >::Log(
l->append("<HttpResponseHeaders>");
}
-
-void ParamTraits<webkit_common::DataElement>::Write(
- Message* m, const param_type& p) {
+void ParamTraits<storage::DataElement>::Write(Message* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.type()));
switch (p.type()) {
- case webkit_common::DataElement::TYPE_BYTES: {
+ case storage::DataElement::TYPE_BYTES: {
m->WriteData(p.bytes(), static_cast<int>(p.length()));
break;
}
- case webkit_common::DataElement::TYPE_FILE: {
+ case storage::DataElement::TYPE_FILE: {
WriteParam(m, p.path());
WriteParam(m, p.offset());
WriteParam(m, p.length());
WriteParam(m, p.expected_modification_time());
break;
}
- case webkit_common::DataElement::TYPE_FILE_FILESYSTEM: {
+ case storage::DataElement::TYPE_FILE_FILESYSTEM: {
WriteParam(m, p.filesystem_url());
WriteParam(m, p.offset());
WriteParam(m, p.length());
@@ -57,7 +55,7 @@ void ParamTraits<webkit_common::DataElement>::Write(
break;
}
default: {
- DCHECK(p.type() == webkit_common::DataElement::TYPE_BLOB);
+ DCHECK(p.type() == storage::DataElement::TYPE_BLOB);
WriteParam(m, p.blob_uuid());
WriteParam(m, p.offset());
WriteParam(m, p.length());
@@ -66,13 +64,14 @@ void ParamTraits<webkit_common::DataElement>::Write(
}
}
-bool ParamTraits<webkit_common::DataElement>::Read(
- const Message* m, PickleIterator* iter, param_type* r) {
+bool ParamTraits<storage::DataElement>::Read(const Message* m,
+ PickleIterator* iter,
+ param_type* r) {
int type;
if (!ReadParam(m, iter, &type))
return false;
switch (type) {
- case webkit_common::DataElement::TYPE_BYTES: {
+ case storage::DataElement::TYPE_BYTES: {
const char* data;
int len;
if (!m->ReadData(iter, &data, &len))
@@ -80,7 +79,7 @@ bool ParamTraits<webkit_common::DataElement>::Read(
r->SetToBytes(data, len);
break;
}
- case webkit_common::DataElement::TYPE_FILE: {
+ case storage::DataElement::TYPE_FILE: {
base::FilePath file_path;
uint64 offset, length;
base::Time expected_modification_time;
@@ -96,7 +95,7 @@ bool ParamTraits<webkit_common::DataElement>::Read(
expected_modification_time);
break;
}
- case webkit_common::DataElement::TYPE_FILE_FILESYSTEM: {
+ case storage::DataElement::TYPE_FILE_FILESYSTEM: {
GURL file_system_url;
uint64 offset, length;
base::Time expected_modification_time;
@@ -113,7 +112,7 @@ bool ParamTraits<webkit_common::DataElement>::Read(
break;
}
default: {
- DCHECK(type == webkit_common::DataElement::TYPE_BLOB);
+ DCHECK(type == storage::DataElement::TYPE_BLOB);
std::string blob_uuid;
uint64 offset, length;
if (!ReadParam(m, iter, &blob_uuid))
@@ -129,9 +128,9 @@ bool ParamTraits<webkit_common::DataElement>::Read(
return true;
}
-void ParamTraits<webkit_common::DataElement>::Log(
- const param_type& p, std::string* l) {
- l->append("<webkit_common::DataElement>");
+void ParamTraits<storage::DataElement>::Log(const param_type& p,
+ std::string* l) {
+ l->append("<storage::DataElement>");
}
void ParamTraits<scoped_refptr<content::ResourceDevToolsInfo> >::Write(
@@ -278,7 +277,7 @@ bool ParamTraits<scoped_refptr<content::ResourceRequestBody> >::Read(
return false;
if (!has_object)
return true;
- std::vector<webkit_common::DataElement> elements;
+ std::vector<storage::DataElement> elements;
if (!ReadParam(m, iter, &elements))
return false;
int64 identifier;
diff --git a/chromium/content/common/resource_messages.h b/chromium/content/common/resource_messages.h
index dc83e5a9321..e35a88e06ca 100644
--- a/chromium/content/common/resource_messages.h
+++ b/chromium/content/common/resource_messages.h
@@ -11,11 +11,13 @@
#include "base/process/process.h"
#include "content/common/content_param_traits_macros.h"
#include "content/common/resource_request_body.h"
+#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/resource_response.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_info.h"
+#include "net/url_request/redirect_info.h"
#ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_
#define CONTENT_COMMON_RESOURCE_MESSAGES_H_
@@ -39,8 +41,8 @@ struct ParamTraits<scoped_refptr<net::HttpResponseHeaders> > {
};
template <>
-struct CONTENT_EXPORT ParamTraits<webkit_common::DataElement> {
- typedef webkit_common::DataElement param_type;
+struct CONTENT_EXPORT ParamTraits<storage::DataElement> {
+ typedef storage::DataElement param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
@@ -83,15 +85,21 @@ IPC_ENUM_TRAITS_MAX_VALUE( \
net::HttpResponseInfo::ConnectionInfo, \
net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS - 1)
+IPC_ENUM_TRAITS_MAX_VALUE(content::FetchRequestMode,
+ content::FETCH_REQUEST_MODE_LAST)
+
+IPC_ENUM_TRAITS_MAX_VALUE(content::FetchCredentialsMode,
+ content::FETCH_CREDENTIALS_MODE_LAST)
+
IPC_STRUCT_TRAITS_BEGIN(content::ResourceResponseHead)
IPC_STRUCT_TRAITS_PARENT(content::ResourceResponseInfo)
- IPC_STRUCT_TRAITS_MEMBER(error_code)
IPC_STRUCT_TRAITS_MEMBER(request_start)
IPC_STRUCT_TRAITS_MEMBER(response_start)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::SyncLoadResult)
IPC_STRUCT_TRAITS_PARENT(content::ResourceResponseHead)
+ IPC_STRUCT_TRAITS_MEMBER(error_code)
IPC_STRUCT_TRAITS_MEMBER(final_url)
IPC_STRUCT_TRAITS_MEMBER(data)
IPC_STRUCT_TRAITS_END()
@@ -117,6 +125,22 @@ IPC_STRUCT_TRAITS_BEGIN(content::ResourceResponseInfo)
IPC_STRUCT_TRAITS_MEMBER(was_fetched_via_proxy)
IPC_STRUCT_TRAITS_MEMBER(npn_negotiated_protocol)
IPC_STRUCT_TRAITS_MEMBER(socket_address)
+ IPC_STRUCT_TRAITS_MEMBER(was_fetched_via_service_worker)
+ IPC_STRUCT_TRAITS_MEMBER(was_fallback_required_by_service_worker)
+ IPC_STRUCT_TRAITS_MEMBER(original_url_via_service_worker)
+ IPC_STRUCT_TRAITS_MEMBER(response_type_via_service_worker)
+ IPC_STRUCT_TRAITS_MEMBER(service_worker_fetch_start)
+ IPC_STRUCT_TRAITS_MEMBER(service_worker_fetch_ready)
+ IPC_STRUCT_TRAITS_MEMBER(service_worker_fetch_end)
+ IPC_STRUCT_TRAITS_MEMBER(proxy_server)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(net::RedirectInfo)
+ IPC_STRUCT_TRAITS_MEMBER(status_code)
+ IPC_STRUCT_TRAITS_MEMBER(new_method)
+ IPC_STRUCT_TRAITS_MEMBER(new_url)
+ IPC_STRUCT_TRAITS_MEMBER(new_first_party_for_cookies)
+ IPC_STRUCT_TRAITS_MEMBER(new_referrer)
IPC_STRUCT_TRAITS_END()
// Parameters for a resource request.
@@ -158,7 +182,7 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// What this resource load is for (main frame, sub-frame, sub-resource,
// object).
- IPC_STRUCT_MEMBER(ResourceType::Type, resource_type)
+ IPC_STRUCT_MEMBER(content::ResourceType, resource_type)
// The priority of this request.
IPC_STRUCT_MEMBER(net::RequestPriority, priority)
@@ -174,6 +198,21 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// or kInvalidServiceWorkerProviderId.
IPC_STRUCT_MEMBER(int, service_worker_provider_id)
+ // True if the request should not be handled by the ServiceWorker.
+ IPC_STRUCT_MEMBER(bool, skip_service_worker)
+
+ // The request mode passed to the ServiceWorker.
+ IPC_STRUCT_MEMBER(content::FetchRequestMode, fetch_request_mode)
+
+ // The credentials mode passed to the ServiceWorker.
+ IPC_STRUCT_MEMBER(content::FetchCredentialsMode, fetch_credentials_mode)
+
+ // The request context passed to the ServiceWorker.
+ IPC_STRUCT_MEMBER(content::RequestContextType, fetch_request_context_type)
+
+ // The frame type passed to the ServiceWorker.
+ IPC_STRUCT_MEMBER(content::RequestContextFrameType, fetch_frame_type)
+
// Optional resource request body (may be null).
IPC_STRUCT_MEMBER(scoped_refptr<content::ResourceRequestBody>,
request_body)
@@ -183,6 +222,12 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// True if the request was user initiated.
IPC_STRUCT_MEMBER(bool, has_user_gesture)
+ // True if load timing data should be collected for request.
+ IPC_STRUCT_MEMBER(bool, enable_load_timing)
+
+ // True if upload progress should be available for request.
+ IPC_STRUCT_MEMBER(bool, enable_upload_progress)
+
// The routing id of the RenderFrame.
IPC_STRUCT_MEMBER(int, render_frame_id)
@@ -196,7 +241,7 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// -1 if unknown / invalid.
IPC_STRUCT_MEMBER(int, parent_render_frame_id)
- IPC_STRUCT_MEMBER(content::PageTransition, transition_type)
+ IPC_STRUCT_MEMBER(ui::PageTransition, transition_type)
// For navigations, whether this navigation should replace the current session
// history entry on commit.
@@ -255,10 +300,9 @@ IPC_MESSAGE_CONTROL3(ResourceMsg_UploadProgress,
// Sent when the request has been redirected. The receiver is expected to
// respond with either a FollowRedirect message (if the redirect is to be
// followed) or a CancelRequest message (if it should not be followed).
-IPC_MESSAGE_CONTROL4(ResourceMsg_ReceivedRedirect,
+IPC_MESSAGE_CONTROL3(ResourceMsg_ReceivedRedirect,
int /* request_id */,
- GURL /* new_url */,
- GURL /* new_first_party_for_cookies */,
+ net::RedirectInfo /* redirect_info */,
content::ResourceResponseHead)
// Sent to set the shared memory buffer to be used to transmit response data to
diff --git a/chromium/content/common/resource_request_body.h b/chromium/content/common/resource_request_body.h
index c060c7234e8..60dcb2913bb 100644
--- a/chromium/content/common/resource_request_body.h
+++ b/chromium/content/common/resource_request_body.h
@@ -11,8 +11,8 @@
#include "base/memory/ref_counted.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
+#include "storage/common/data_element.h"
#include "url/gurl.h"
-#include "webkit/common/data_element.h"
namespace base {
class FilePath;
@@ -23,10 +23,10 @@ namespace content {
// A struct used to represent upload data. The data field is populated by
// WebURLLoader from the data given as WebHTTPBody.
class CONTENT_EXPORT ResourceRequestBody
- : public base::RefCounted<ResourceRequestBody>,
+ : public base::RefCountedThreadSafe<ResourceRequestBody>,
public base::SupportsUserData {
public:
- typedef webkit_common::DataElement Element;
+ typedef storage::DataElement Element;
ResourceRequestBody();
@@ -51,8 +51,8 @@ class CONTENT_EXPORT ResourceRequestBody
int64 identifier() const { return identifier_; }
private:
- friend class base::RefCounted<ResourceRequestBody>;
- virtual ~ResourceRequestBody();
+ friend class base::RefCountedThreadSafe<ResourceRequestBody>;
+ ~ResourceRequestBody() override;
std::vector<Element> elements_;
int64 identifier_;
diff --git a/chromium/content/common/sandbox_init_mac.cc b/chromium/content/common/sandbox_init_mac.cc
index d6f2112dac6..609517932c2 100644
--- a/chromium/content/common/sandbox_init_mac.cc
+++ b/chromium/content/common/sandbox_init_mac.cc
@@ -31,7 +31,8 @@ bool GetSandboxTypeFromCommandLine(int* sandbox_type,
*sandbox_type = -1;
*allowed_dir = base::FilePath(); // Empty by default.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kNoSandbox))
return false;
@@ -47,9 +48,6 @@ bool GetSandboxTypeFromCommandLine(int* sandbox_type,
*sandbox_type = SANDBOX_TYPE_UTILITY;
*allowed_dir =
command_line.GetSwitchValuePath(switches::kUtilityProcessAllowedDir);
- } else if (process_type == switches::kWorkerProcess) {
- // Worker process sandbox.
- *sandbox_type = SANDBOX_TYPE_WORKER;
} else if (process_type == switches::kGpuProcess) {
if (command_line.HasSwitch(switches::kDisableGpuSandbox))
return false;
diff --git a/chromium/content/common/sandbox_init_win.cc b/chromium/content/common/sandbox_init_win.cc
index 7d9d920d9db..fe67bda7e31 100644
--- a/chromium/content/common/sandbox_init_win.cc
+++ b/chromium/content/common/sandbox_init_win.cc
@@ -14,7 +14,8 @@
namespace content {
bool InitializeSandbox(sandbox::SandboxInterfaceInfo* sandbox_info) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
sandbox::BrokerServices* broker_services = sandbox_info->broker_services;
if (broker_services) {
if (!InitBrokerServices(broker_services))
@@ -25,6 +26,11 @@ bool InitializeSandbox(sandbox::SandboxInterfaceInfo* sandbox_info) {
// process to swap its window station. During this time all the UI will be
// broken. This has to run before threads and windows are created.
if (!command_line.HasSwitch(switches::kNoSandbox)) {
+#if defined(ADDRESS_SANITIZER) && defined(OS_WIN)
+ LOG(FATAL) << "AddressSanitizer for Windows doesn't support sandboxing "
+ "yet (http://crbug.com/382867). "
+ "Please rerun with sandbox disabled.";
+#endif
// Precreate the desktop and window station used by the renderers.
sandbox::TargetPolicy* policy = broker_services->CreatePolicy();
sandbox::ResultCode result = policy->CreateAlternateDesktop(true);
diff --git a/chromium/content/common/sandbox_linux/OWNERS b/chromium/content/common/sandbox_linux/OWNERS
index b05bb35fbb1..db0893eca57 100644
--- a/chromium/content/common/sandbox_linux/OWNERS
+++ b/chromium/content/common/sandbox_linux/OWNERS
@@ -1,4 +1,3 @@
-cevans@chromium.org
jln@chromium.org
jorgelo@chromium.org
rsesek@chromium.org
diff --git a/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc b/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
index b7bd3fa195e..8ce5f868da4 100644
--- a/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
+++ b/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
@@ -4,9 +4,13 @@
#include "content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h"
+#include <sys/syscall.h>
#include <sys/types.h>
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::ResultExpr;
namespace content {
@@ -15,9 +19,7 @@ SandboxBPFBasePolicyAndroid::SandboxBPFBasePolicyAndroid()
SandboxBPFBasePolicyAndroid::~SandboxBPFBasePolicyAndroid() {}
-sandbox::ErrorCode SandboxBPFBasePolicyAndroid::EvaluateSyscall(
- sandbox::SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr SandboxBPFBasePolicyAndroid::EvaluateSyscall(int sysno) const {
bool override_and_allow = false;
switch (sysno) {
@@ -52,9 +54,9 @@ sandbox::ErrorCode SandboxBPFBasePolicyAndroid::EvaluateSyscall(
}
if (override_and_allow)
- return sandbox::ErrorCode(sandbox::ErrorCode::ERR_ALLOWED);
+ return Allow();
- return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
}
} // namespace content
diff --git a/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h b/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h
index 0eaa6b56d74..4a0e6c5e953 100644
--- a/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h
+++ b/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h
@@ -6,7 +6,6 @@
#define CONTENT_COMMON_SANDBOX_LINUX_ANDROID_SANDBOX_BPF_BASE_POLICY_ANDROID_H_
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
-#include "sandbox/linux/seccomp-bpf/errorcode.h"
namespace content {
@@ -19,9 +18,8 @@ class SandboxBPFBasePolicyAndroid : public SandboxBPFBasePolicy {
virtual ~SandboxBPFBasePolicyAndroid();
// sandbox::SandboxBPFPolicy:
- virtual sandbox::ErrorCode EvaluateSyscall(
- sandbox::SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ virtual sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
private:
DISALLOW_COPY_AND_ASSIGN(SandboxBPFBasePolicyAndroid);
diff --git a/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
index a189a5d6b8f..20b8f94ea54 100644
--- a/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
@@ -22,13 +22,16 @@
#include "build/build_config.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/services/linux_syscalls.h"
-using sandbox::ErrorCode;
-using sandbox::SandboxBPF;
using sandbox::SyscallSets;
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::Arg;
+using sandbox::bpf_dsl::Error;
+using sandbox::bpf_dsl::If;
+using sandbox::bpf_dsl::ResultExpr;
namespace content {
@@ -94,13 +97,12 @@ void AddArmGpuWhitelist(std::vector<std::string>* read_whitelist,
class CrosArmGpuBrokerProcessPolicy : public CrosArmGpuProcessPolicy {
public:
- static sandbox::SandboxBPFPolicy* Create() {
+ static sandbox::bpf_dsl::Policy* Create() {
return new CrosArmGpuBrokerProcessPolicy();
}
- virtual ~CrosArmGpuBrokerProcessPolicy() {}
+ ~CrosArmGpuBrokerProcessPolicy() override {}
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ ResultExpr EvaluateSyscall(int system_call_number) const override;
private:
CrosArmGpuBrokerProcessPolicy() : CrosArmGpuProcessPolicy(false) {}
@@ -109,15 +111,14 @@ class CrosArmGpuBrokerProcessPolicy : public CrosArmGpuProcessPolicy {
// A GPU broker policy is the same as a GPU policy with open and
// openat allowed.
-ErrorCode CrosArmGpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr CrosArmGpuBrokerProcessPolicy::EvaluateSyscall(int sysno) const {
switch (sysno) {
case __NR_access:
case __NR_open:
case __NR_openat:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
default:
- return CrosArmGpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
+ return CrosArmGpuProcessPolicy::EvaluateSyscall(sysno);
}
}
@@ -128,11 +129,10 @@ CrosArmGpuProcessPolicy::CrosArmGpuProcessPolicy(bool allow_shmat)
CrosArmGpuProcessPolicy::~CrosArmGpuProcessPolicy() {}
-ErrorCode CrosArmGpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr CrosArmGpuProcessPolicy::EvaluateSyscall(int sysno) const {
#if defined(__arm__)
if (allow_shmat_ && sysno == __NR_shmat)
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
#endif // defined(__arm__)
switch (sysno) {
@@ -144,21 +144,17 @@ ErrorCode CrosArmGpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
case __NR_getsockname:
case __NR_sysinfo:
case __NR_uname:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
// Allow only AF_UNIX for |domain|.
case __NR_socket:
- case __NR_socketpair:
- return sandbox->Cond(0, ErrorCode::TP_32BIT,
- ErrorCode::OP_EQUAL, AF_UNIX,
- ErrorCode(ErrorCode::ERR_ALLOWED),
- ErrorCode(EPERM));
+ case __NR_socketpair: {
+ const Arg<int> domain(0);
+ return If(domain == AF_UNIX, Allow()).Else(Error(EPERM));
+ }
#endif // defined(__arm__)
default:
- if (SyscallSets::IsAdvancedScheduler(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
-
// Default to the generic GPU policy.
- return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
+ return GpuProcessPolicy::EvaluateSyscall(sysno);
}
}
diff --git a/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h
index 0ccc93ce270..179ac81f127 100644
--- a/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h
+++ b/chromium/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.h
@@ -13,11 +13,11 @@ namespace content {
class CrosArmGpuProcessPolicy : public GpuProcessPolicy {
public:
explicit CrosArmGpuProcessPolicy(bool allow_shmat);
- virtual ~CrosArmGpuProcessPolicy();
+ ~CrosArmGpuProcessPolicy() override;
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
- virtual bool PreSandboxHook() OVERRIDE;
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
+ bool PreSandboxHook() override;
private:
const bool allow_shmat_; // Allow shmat(2).
diff --git a/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
index d6b54f8ef55..e1a33d02a9b 100644
--- a/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
@@ -25,16 +25,18 @@
#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
#include "content/common/set_process_title.h"
#include "content/public/common/content_switches.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/services/broker_process.h"
#include "sandbox/linux/services/linux_syscalls.h"
+#include "sandbox/linux/syscall_broker/broker_process.h"
using sandbox::BrokerProcess;
-using sandbox::ErrorCode;
-using sandbox::SandboxBPF;
using sandbox::SyscallSets;
using sandbox::arch_seccomp_data;
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::ResultExpr;
+using sandbox::bpf_dsl::Trap;
namespace content {
@@ -72,9 +74,16 @@ inline bool IsArchitectureArm() {
#endif
}
-bool IsAcceleratedVideoDecodeEnabled() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- return !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode);
+bool IsAcceleratedVideoEnabled() {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ bool accelerated_encode_enabled = false;
+#if defined(OS_CHROMEOS)
+ accelerated_encode_enabled =
+ !command_line.HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode);
+#endif
+ return !command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode) ||
+ accelerated_encode_enabled;
}
intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args,
@@ -110,13 +119,12 @@ intptr_t GpuSIGSYS_Handler(const struct arch_seccomp_data& args,
class GpuBrokerProcessPolicy : public GpuProcessPolicy {
public:
- static sandbox::SandboxBPFPolicy* Create() {
+ static sandbox::bpf_dsl::Policy* Create() {
return new GpuBrokerProcessPolicy();
}
- virtual ~GpuBrokerProcessPolicy() {}
+ ~GpuBrokerProcessPolicy() override {}
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ ResultExpr EvaluateSyscall(int system_call_number) const override;
private:
GpuBrokerProcessPolicy() {}
@@ -126,25 +134,25 @@ class GpuBrokerProcessPolicy : public GpuProcessPolicy {
// x86_64/i386 or desktop ARM.
// A GPU broker policy is the same as a GPU policy with open and
// openat allowed.
-ErrorCode GpuBrokerProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr GpuBrokerProcessPolicy::EvaluateSyscall(int sysno) const {
switch (sysno) {
case __NR_access:
case __NR_open:
case __NR_openat:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
default:
- return GpuProcessPolicy::EvaluateSyscall(sandbox, sysno);
+ return GpuProcessPolicy::EvaluateSyscall(sysno);
}
}
void UpdateProcessTypeToGpuBroker() {
- CommandLine::StringVector exec = CommandLine::ForCurrentProcess()->GetArgs();
- CommandLine::Reset();
- CommandLine::Init(0, NULL);
- CommandLine::ForCurrentProcess()->InitFromArgv(exec);
- CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kProcessType,
- "gpu-broker");
+ base::CommandLine::StringVector exec =
+ base::CommandLine::ForCurrentProcess()->GetArgs();
+ base::CommandLine::Reset();
+ base::CommandLine::Init(0, NULL);
+ base::CommandLine::ForCurrentProcess()->InitFromArgv(exec);
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kProcessType, "gpu-broker");
// Update the process title. The argv was already cached by the call to
// SetProcessTitleFromCommandLine in content_main_runner.cc, so we can pass
@@ -153,7 +161,7 @@ void UpdateProcessTypeToGpuBroker() {
}
bool UpdateProcessTypeAndEnableSandbox(
- sandbox::SandboxBPFPolicy* (*broker_sandboxer_allocator)(void)) {
+ sandbox::bpf_dsl::Policy* (*broker_sandboxer_allocator)(void)) {
DCHECK(broker_sandboxer_allocator);
UpdateProcessTypeToGpuBroker();
return SandboxSeccompBPF::StartSandboxWithExternalPolicy(
@@ -162,16 +170,27 @@ bool UpdateProcessTypeAndEnableSandbox(
} // namespace
-GpuProcessPolicy::GpuProcessPolicy() : broker_process_(NULL) {}
+GpuProcessPolicy::GpuProcessPolicy() : GpuProcessPolicy(false) {
+}
+
+GpuProcessPolicy::GpuProcessPolicy(bool allow_mincore)
+ : broker_process_(NULL), allow_mincore_(allow_mincore) {
+}
GpuProcessPolicy::~GpuProcessPolicy() {}
// Main policy for x86_64/i386. Extended by CrosArmGpuProcessPolicy.
-ErrorCode GpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr GpuProcessPolicy::EvaluateSyscall(int sysno) const {
switch (sysno) {
case __NR_ioctl:
-#if defined(__i386__) || defined(__x86_64__)
+ return Allow();
+ case __NR_mincore:
+ if (allow_mincore_) {
+ return Allow();
+ } else {
+ return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
+ }
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
// The Nvidia driver uses flags not in the baseline policy
// (MAP_LOCKED | MAP_EXECUTABLE | MAP_32BIT)
case __NR_mmap:
@@ -181,21 +200,23 @@ ErrorCode GpuProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
case __NR_mprotect:
// TODO(jln): restrict prctl.
case __NR_prctl:
- case __NR_sched_getaffinity:
- case __NR_sched_setaffinity:
- case __NR_setpriority:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
case __NR_access:
case __NR_open:
case __NR_openat:
DCHECK(broker_process_);
- return sandbox->Trap(GpuSIGSYS_Handler, broker_process_);
+ return Trap(GpuSIGSYS_Handler, broker_process_);
+ case __NR_setpriority:
+ return sandbox::RestrictGetSetpriority(GetPolicyPid());
+ case __NR_sched_getaffinity:
+ case __NR_sched_setaffinity:
+ return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
default:
if (SyscallSets::IsEventFd(sysno))
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
// Default on the baseline policy.
- return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
}
}
@@ -214,9 +235,9 @@ bool GpuProcessPolicy::PreSandboxHook() {
std::vector<std::string>());
if (IsArchitectureX86_64() || IsArchitectureI386()) {
- // Accelerated video decode dlopen()'s some shared objects
+ // Accelerated video dlopen()'s some shared objects
// inside the sandbox, so preload them now.
- if (IsAcceleratedVideoDecodeEnabled()) {
+ if (IsAcceleratedVideoEnabled()) {
const char* I965DrvVideoPath = NULL;
if (IsArchitectureX86_64()) {
@@ -235,7 +256,7 @@ bool GpuProcessPolicy::PreSandboxHook() {
}
void GpuProcessPolicy::InitGpuBrokerProcess(
- sandbox::SandboxBPFPolicy* (*broker_sandboxer_allocator)(void),
+ sandbox::bpf_dsl::Policy* (*broker_sandboxer_allocator)(void),
const std::vector<std::string>& read_whitelist_extra,
const std::vector<std::string>& write_whitelist_extra) {
static const char kDriRcPath[] = "/etc/drirc";
diff --git a/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h
index 6da4d04d30f..aae79c1381e 100644
--- a/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h
+++ b/chromium/content/common/sandbox_linux/bpf_gpu_policy_linux.h
@@ -20,12 +20,13 @@ namespace content {
class GpuProcessPolicy : public SandboxBPFBasePolicy {
public:
GpuProcessPolicy();
- virtual ~GpuProcessPolicy();
+ explicit GpuProcessPolicy(bool allow_mincore);
+ ~GpuProcessPolicy() override;
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
- virtual bool PreSandboxHook() OVERRIDE;
+ bool PreSandboxHook() override;
protected:
// Start a broker process to handle open() inside the sandbox.
@@ -35,7 +36,7 @@ class GpuProcessPolicy : public SandboxBPFBasePolicy {
// names that should be whitelisted by the broker process, in addition to
// the basic ones.
void InitGpuBrokerProcess(
- sandbox::SandboxBPFPolicy* (*broker_sandboxer_allocator)(void),
+ sandbox::bpf_dsl::Policy* (*broker_sandboxer_allocator)(void),
const std::vector<std::string>& read_whitelist_extra,
const std::vector<std::string>& write_whitelist_extra);
@@ -50,6 +51,10 @@ class GpuProcessPolicy : public SandboxBPFBasePolicy {
// This is allocated by InitGpuBrokerProcess, called from PreSandboxHook(),
// which executes iff the sandbox is going to be enabled afterwards.
sandbox::BrokerProcess* broker_process_;
+
+ // eglCreateWindowSurface() needs mincore().
+ bool allow_mincore_;
+
DISALLOW_COPY_AND_ASSIGN(GpuProcessPolicy);
};
diff --git a/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
index ec5739cbdc1..c8fcb45de0c 100644
--- a/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.cc
@@ -9,20 +9,22 @@
#include "base/basictypes.h"
#include "build/build_config.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#include "sandbox/linux/services/linux_syscalls.h"
using sandbox::SyscallSets;
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::Error;
+using sandbox::bpf_dsl::ResultExpr;
namespace content {
PpapiProcessPolicy::PpapiProcessPolicy() {}
PpapiProcessPolicy::~PpapiProcessPolicy() {}
-ErrorCode PpapiProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr PpapiProcessPolicy::EvaluateSyscall(int sysno) const {
switch (sysno) {
// TODO(jln): restrict prctl.
case __NR_prctl:
@@ -30,17 +32,18 @@ ErrorCode PpapiProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
case __NR_pwrite64:
case __NR_sched_get_priority_max:
case __NR_sched_get_priority_min:
+ case __NR_times:
+ return Allow();
case __NR_sched_getaffinity:
case __NR_sched_getparam:
case __NR_sched_getscheduler:
case __NR_sched_setscheduler:
- case __NR_times:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
case __NR_ioctl:
- return ErrorCode(ENOTTY); // Flash Access.
+ return Error(ENOTTY); // Flash Access.
default:
// Default on the baseline policy.
- return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
}
}
diff --git a/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h
index 1e9038ff129..172ceefa568 100644
--- a/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h
+++ b/chromium/content/common/sandbox_linux/bpf_ppapi_policy_linux.h
@@ -13,10 +13,10 @@ namespace content {
class PpapiProcessPolicy : public SandboxBPFBasePolicy {
public:
PpapiProcessPolicy();
- virtual ~PpapiProcessPolicy();
+ ~PpapiProcessPolicy() override;
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
private:
DISALLOW_COPY_AND_ASSIGN(PpapiProcessPolicy);
diff --git a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
index db520101807..408a3801bed 100644
--- a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
@@ -9,31 +9,33 @@
#include "base/basictypes.h"
#include "build/build_config.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
#include "sandbox/linux/services/linux_syscalls.h"
using sandbox::SyscallSets;
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::Error;
+using sandbox::bpf_dsl::ResultExpr;
namespace content {
RendererProcessPolicy::RendererProcessPolicy() {}
RendererProcessPolicy::~RendererProcessPolicy() {}
-ErrorCode RendererProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
+ResultExpr RendererProcessPolicy::EvaluateSyscall(int sysno) const {
switch (sysno) {
- case __NR_ioctl:
- return sandbox::RestrictIoctl(sandbox);
- // Allow the system calls below.
// The baseline policy allows __NR_clock_gettime. Allow
// clock_getres() for V8. crbug.com/329053.
case __NR_clock_getres:
+ return sandbox::RestrictClockID();
+ case __NR_ioctl:
+ return sandbox::RestrictIoctl();
+ // Allow the system calls below.
case __NR_fdatasync:
case __NR_fsync:
- case __NR_getpriority:
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
case __NR_getrlimit:
#endif
#if defined(__i386__) || defined(__arm__)
@@ -42,22 +44,22 @@ ErrorCode RendererProcessPolicy::EvaluateSyscall(SandboxBPF* sandbox,
case __NR_mremap: // See crbug.com/149834.
case __NR_pread64:
case __NR_pwrite64:
- case __NR_sched_getaffinity:
case __NR_sched_get_priority_max:
case __NR_sched_get_priority_min:
- case __NR_sched_getparam:
- case __NR_sched_getscheduler:
- case __NR_sched_setscheduler:
- case __NR_setpriority:
case __NR_sysinfo:
case __NR_times:
case __NR_uname:
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
+ case __NR_sched_getaffinity:
+ case __NR_sched_getparam:
+ case __NR_sched_getscheduler:
+ case __NR_sched_setscheduler:
+ return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
case __NR_prlimit64:
- return ErrorCode(EPERM); // See crbug.com/160157.
+ return Error(EPERM); // See crbug.com/160157.
default:
// Default on the content baseline policy.
- return SandboxBPFBasePolicy::EvaluateSyscall(sandbox, sysno);
+ return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
}
}
diff --git a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h
index ce00cd78c0f..0dffa00a577 100644
--- a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h
+++ b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.h
@@ -13,10 +13,10 @@ namespace content {
class RendererProcessPolicy : public SandboxBPFBasePolicy {
public:
RendererProcessPolicy();
- virtual ~RendererProcessPolicy();
+ ~RendererProcessPolicy() override;
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
private:
DISALLOW_COPY_AND_ASSIGN(RendererProcessPolicy);
diff --git a/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc
new file mode 100644
index 00000000000..401a5f718cd
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 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 "content/common/sandbox_linux/bpf_utility_policy_linux.h"
+
+#include <errno.h>
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+#include "content/common/sandbox_linux/sandbox_linux.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
+#include "sandbox/linux/services/linux_syscalls.h"
+
+using sandbox::SyscallSets;
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::Error;
+using sandbox::bpf_dsl::ResultExpr;
+
+namespace content {
+
+UtilityProcessPolicy::UtilityProcessPolicy() {
+}
+UtilityProcessPolicy::~UtilityProcessPolicy() {
+}
+
+ResultExpr UtilityProcessPolicy::EvaluateSyscall(int sysno) const {
+ // TODO(mdempsky): For now, this is just a copy of the renderer
+ // policy, which happens to work well for utility processes too. It
+ // should be possible to limit further though. In particular, the
+ // entries below annotated with bug references are most likely
+ // unnecessary.
+
+ switch (sysno) {
+ case __NR_ioctl:
+ return sandbox::RestrictIoctl();
+ // Allow the system calls below.
+ case __NR_fdatasync:
+ case __NR_fsync:
+#if defined(__i386__) || defined(__x86_64__)
+ case __NR_getrlimit:
+#endif
+#if defined(__i386__) || defined(__arm__)
+ case __NR_ugetrlimit:
+#endif
+ case __NR_pread64:
+ case __NR_pwrite64:
+ case __NR_sysinfo:
+ case __NR_times:
+ case __NR_uname:
+ return Allow();
+ default:
+ // Default on the content baseline policy.
+ return SandboxBPFBasePolicy::EvaluateSyscall(sysno);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.h b/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.h
new file mode 100644
index 00000000000..bf65f335eef
--- /dev/null
+++ b/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.h
@@ -0,0 +1,27 @@
+// Copyright 2014 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 CONTENT_COMMON_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
+#define CONTENT_COMMON_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
+
+#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
+
+namespace content {
+
+// This policy can be used by utility processes.
+class UtilityProcessPolicy : public SandboxBPFBasePolicy {
+ public:
+ UtilityProcessPolicy();
+ ~UtilityProcessPolicy() override;
+
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(UtilityProcessPolicy);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
diff --git a/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc
index d1e5af30563..75bfe22c56e 100644
--- a/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.cc
@@ -7,8 +7,11 @@
#include <errno.h>
#include "base/logging.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
+using sandbox::bpf_dsl::ResultExpr;
+
namespace content {
namespace {
@@ -22,11 +25,14 @@ SandboxBPFBasePolicy::SandboxBPFBasePolicy()
: baseline_policy_(new sandbox::BaselinePolicy(kFSDeniedErrno)) {}
SandboxBPFBasePolicy::~SandboxBPFBasePolicy() {}
-ErrorCode SandboxBPFBasePolicy::EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const {
+ResultExpr SandboxBPFBasePolicy::EvaluateSyscall(int system_call_number) const {
+ DCHECK(baseline_policy_);
+ return baseline_policy_->EvaluateSyscall(system_call_number);
+}
+
+ResultExpr SandboxBPFBasePolicy::InvalidSyscall() const {
DCHECK(baseline_policy_);
- return baseline_policy_->EvaluateSyscall(sandbox_compiler,
- system_call_number);
+ return baseline_policy_->InvalidSyscall();
}
bool SandboxBPFBasePolicy::PreSandboxHook() {
diff --git a/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h
index 6d9d83f4fa1..86c203d98ec 100644
--- a/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h
+++ b/chromium/content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h
@@ -7,28 +7,27 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
+#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
-
-using sandbox::ErrorCode;
-using sandbox::SandboxBPF;
namespace content {
// The "baseline" BPF policy for content/. Any content/ seccomp-bpf policy
// should inherit from it.
-// It implements the main SandboxBPFPolicy interface. Due to its nature
+// It implements the main Policy interface. Due to its nature
// as a "kernel attack surface reduction" layer, it's implementation-defined.
-class SandboxBPFBasePolicy : public sandbox::SandboxBPFPolicy {
+class SandboxBPFBasePolicy : public sandbox::bpf_dsl::Policy {
public:
SandboxBPFBasePolicy();
- virtual ~SandboxBPFBasePolicy();
+ ~SandboxBPFBasePolicy() override;
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
+ int system_call_number) const override;
+ sandbox::bpf_dsl::ResultExpr InvalidSyscall() const override;
// A policy can implement this hook to run code right before the policy
- // is passed to the SandboxBPF class and the sandbox is engaged.
+ // is passed to the BPF compiler and the sandbox is engaged.
// If PreSandboxHook() returns true, the sandbox is guaranteed to be
// engaged afterwards.
// This will be used when enabling the sandbox though
@@ -38,6 +37,8 @@ class SandboxBPFBasePolicy : public sandbox::SandboxBPFPolicy {
// Get the errno(3) to return for filesystem errors.
static int GetFSDeniedErrno();
+ pid_t GetPolicyPid() const { return baseline_policy_->policy_pid(); }
+
private:
// Compose the BaselinePolicy from sandbox/.
scoped_ptr<sandbox::BaselinePolicy> baseline_policy_;
diff --git a/chromium/content/common/sandbox_linux/sandbox_init_linux.cc b/chromium/content/common/sandbox_linux/sandbox_init_linux.cc
index 516c611d2eb..0585d5421dd 100644
--- a/chromium/content/common/sandbox_linux/sandbox_init_linux.cc
+++ b/chromium/content/common/sandbox_linux/sandbox_init_linux.cc
@@ -6,15 +6,15 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/bpf_dsl/policy.h"
namespace content {
-bool InitializeSandbox(scoped_ptr<sandbox::SandboxBPFPolicy> policy) {
+bool InitializeSandbox(scoped_ptr<sandbox::bpf_dsl::Policy> policy) {
return SandboxSeccompBPF::StartSandboxWithExternalPolicy(policy.Pass());
}
-scoped_ptr<sandbox::SandboxBPFPolicy> GetBPFSandboxBaselinePolicy() {
+scoped_ptr<sandbox::bpf_dsl::Policy> GetBPFSandboxBaselinePolicy() {
return SandboxSeccompBPF::GetBaselinePolicy().Pass();
}
diff --git a/chromium/content/common/sandbox_linux/sandbox_linux.cc b/chromium/content/common/sandbox_linux/sandbox_linux.cc
index 37ebae7c8f7..12e11d8e131 100644
--- a/chromium/content/common/sandbox_linux/sandbox_linux.cc
+++ b/chromium/content/common/sandbox_linux/sandbox_linux.cc
@@ -18,6 +18,7 @@
#include "base/debug/stack_trace.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/posix/eintr_wrapper.h"
@@ -34,8 +35,7 @@
#include "sandbox/linux/services/yama.h"
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(LEAK_SANITIZER)
+#if defined(ANY_OF_AMTLU_SANITIZER)
#include <sanitizer/common_interface_defs.h>
#endif
@@ -52,20 +52,16 @@ struct FDCloser {
};
void LogSandboxStarted(const std::string& sandbox_name) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
const std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
const std::string activated_sandbox =
"Activated " + sandbox_name + " sandbox for process type: " +
process_type + ".";
-#if defined(OS_CHROMEOS)
- LOG(WARNING) << activated_sandbox;
-#else
VLOG(1) << activated_sandbox;
-#endif
}
-#if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER)
bool AddResourceLimit(int resource, rlim_t limit) {
struct rlimit old_rlimit;
if (getrlimit(resource, &old_rlimit))
@@ -78,7 +74,6 @@ bool AddResourceLimit(int resource, rlim_t limit) {
int rc = setrlimit(resource, &new_rlimit);
return rc == 0;
}
-#endif
bool IsRunningTSAN() {
#if defined(THREAD_SANITIZER)
@@ -119,8 +114,7 @@ LinuxSandbox::LinuxSandbox()
if (setuid_sandbox_client_ == NULL) {
LOG(FATAL) << "Failed to instantiate the setuid sandbox client.";
}
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(LEAK_SANITIZER)
+#if defined(ANY_OF_AMTLU_SANITIZER)
sanitizer_args_ = make_scoped_ptr(new __sanitizer_sandbox_arguments);
*sanitizer_args_ = {0};
#endif
@@ -138,8 +132,7 @@ LinuxSandbox* LinuxSandbox::GetInstance() {
void LinuxSandbox::PreinitializeSandbox() {
CHECK(!pre_initialized_);
seccomp_bpf_supported_ = false;
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(LEAK_SANITIZER)
+#if defined(ANY_OF_AMTLU_SANITIZER)
// Sanitizers need to open some resources before the sandbox is enabled.
// This should not fork, not launch threads, not open a directory.
__sanitizer_sandbox_on_notify(sanitizer_args());
@@ -264,7 +257,7 @@ bool LinuxSandbox::StartSeccompBPF(const std::string& process_type) {
}
bool LinuxSandbox::InitializeSandboxImpl() {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
const std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType);
@@ -338,8 +331,9 @@ bool LinuxSandbox::seccomp_bpf_supported() const {
bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) {
(void) process_type;
-#if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER)
- CommandLine* command_line = CommandLine::ForCurrentProcess();
+#if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
+ !defined(THREAD_SANITIZER)
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kNoSandbox)) {
return false;
}
@@ -358,7 +352,6 @@ bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) {
// For now, increase limit to 16GB for renderer and worker and gpu processes
// to accomodate.
if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess ||
process_type == switches::kGpuProcess) {
address_space_limit = 1L << 34;
}
@@ -376,9 +369,13 @@ bool LinuxSandbox::LimitAddressSpace(const std::string& process_type) {
return limited_as && limited_data;
#else
+ // Silence the compiler warning about unused function. This doesn't actually
+ // call AddResourceLimit().
+ ignore_result(AddResourceLimit);
base::SysInfo::AmountOfVirtualMemory();
return false;
-#endif // !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER)
+#endif // !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) &&
+ // !defined(THREAD_SANITIZER)
}
bool LinuxSandbox::HasOpenDirectories() const {
@@ -397,7 +394,6 @@ void LinuxSandbox::CheckForBrokenPromises(const std::string& process_type) {
// Make sure that any promise made with GetStatus() wasn't broken.
bool promised_seccomp_bpf_would_start = false;
if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess ||
process_type == switches::kPpapiPluginProcess) {
promised_seccomp_bpf_would_start =
(sandbox_status_flags_ != kSandboxLinuxInvalid) &&
diff --git a/chromium/content/common/sandbox_linux/sandbox_linux.h b/chromium/content/common/sandbox_linux/sandbox_linux.h
index 6e4f8b33736..a5a232277e9 100644
--- a/chromium/content/common/sandbox_linux/sandbox_linux.h
+++ b/chromium/content/common/sandbox_linux/sandbox_linux.h
@@ -12,8 +12,10 @@
#include "content/public/common/sandbox_linux.h"
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(LEAK_SANITIZER)
+ defined(THREAD_SANITIZER) || defined(LEAK_SANITIZER) || \
+ defined(UNDEFINED_SANITIZER)
#include <sanitizer/common_interface_defs.h>
+#define ANY_OF_AMTLU_SANITIZER 1
#endif
template <typename T> struct DefaultSingletonTraits;
@@ -87,8 +89,7 @@ class LinuxSandbox {
// to make some vulnerabilities harder to exploit.
bool LimitAddressSpace(const std::string& process_type);
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(LEAK_SANITIZER)
+#if defined(ANY_OF_AMTLU_SANITIZER)
__sanitizer_sandbox_arguments* sanitizer_args() const {
return sanitizer_args_.get();
};
@@ -132,8 +133,7 @@ class LinuxSandbox {
bool seccomp_bpf_supported_; // Accurate if pre_initialized_.
bool yama_is_enforcing_; // Accurate if pre_initialized_.
scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_;
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(LEAK_SANITIZER)
+#if defined(ANY_OF_AMTLU_SANITIZER)
scoped_ptr<__sanitizer_sandbox_arguments> sanitizer_args_;
#endif
diff --git a/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
index 820b18b8419..54daf90eb98 100644
--- a/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
+++ b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc
@@ -8,8 +8,6 @@
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <sys/types.h>
#include "base/basictypes.h"
@@ -17,7 +15,7 @@
#include "base/logging.h"
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h"
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
#if defined(USE_SECCOMP_BPF)
@@ -26,6 +24,7 @@
#include "content/common/sandbox_linux/bpf_gpu_policy_linux.h"
#include "content/common/sandbox_linux/bpf_ppapi_policy_linux.h"
#include "content/common/sandbox_linux/bpf_renderer_policy_linux.h"
+#include "content/common/sandbox_linux/bpf_utility_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
@@ -35,16 +34,23 @@
#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
#include "sandbox/linux/services/linux_syscalls.h"
+#if !defined(IN_NACL_HELPER)
+#include "ui/gl/gl_switches.h"
+#endif
+
using sandbox::BaselinePolicy;
+using sandbox::SandboxBPF;
using sandbox::SyscallSets;
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::ResultExpr;
#else
// Make sure that seccomp-bpf does not get disabled by mistake. Also make sure
// that we think twice about this when adding a new architecture.
-#if !defined(ARCH_CPU_MIPS_FAMILY) && !defined(ARCH_CPU_ARM64)
+#if !defined(ARCH_CPU_ARM64)
#error "Seccomp-bpf disabled on supported architecture!"
-#endif // !defined(ARCH_CPU_MIPS_FAMILY) && !defined(ARCH_CPU_ARM64)
+#endif // !defined(ARCH_CPU_ARM64)
#endif //
@@ -53,7 +59,7 @@ namespace content {
#if defined(USE_SECCOMP_BPF)
namespace {
-void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy);
+void StartSandboxWithPolicy(sandbox::bpf_dsl::Policy* policy);
inline bool IsChromeOS() {
#if defined(OS_CHROMEOS)
@@ -74,34 +80,27 @@ inline bool IsArchitectureArm() {
class BlacklistDebugAndNumaPolicy : public SandboxBPFBasePolicy {
public:
BlacklistDebugAndNumaPolicy() {}
- virtual ~BlacklistDebugAndNumaPolicy() {}
+ ~BlacklistDebugAndNumaPolicy() override {}
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ ResultExpr EvaluateSyscall(int system_call_number) const override;
private:
DISALLOW_COPY_AND_ASSIGN(BlacklistDebugAndNumaPolicy);
};
-ErrorCode BlacklistDebugAndNumaPolicy::EvaluateSyscall(SandboxBPF* sandbox,
- int sysno) const {
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
- // TODO(jln) we should not have to do that in a trivial policy.
- return ErrorCode(ENOSYS);
- }
+ResultExpr BlacklistDebugAndNumaPolicy::EvaluateSyscall(int sysno) const {
if (SyscallSets::IsDebug(sysno) || SyscallSets::IsNuma(sysno))
- return sandbox->Trap(sandbox::CrashSIGSYS_Handler, NULL);
+ return sandbox::CrashSIGSYS();
- return ErrorCode(ErrorCode::ERR_ALLOWED);
+ return Allow();
}
class AllowAllPolicy : public SandboxBPFBasePolicy {
public:
AllowAllPolicy() {}
- virtual ~AllowAllPolicy() {}
+ ~AllowAllPolicy() override {}
- virtual ErrorCode EvaluateSyscall(SandboxBPF* sandbox_compiler,
- int system_call_number) const OVERRIDE;
+ ResultExpr EvaluateSyscall(int system_call_number) const override;
private:
DISALLOW_COPY_AND_ASSIGN(AllowAllPolicy);
@@ -110,19 +109,13 @@ class AllowAllPolicy : public SandboxBPFBasePolicy {
// Allow all syscalls.
// This will still deny x32 or IA32 calls in 64 bits mode or
// 64 bits system calls in compatibility mode.
-ErrorCode AllowAllPolicy::EvaluateSyscall(SandboxBPF*, int sysno) const {
- if (!SandboxBPF::IsValidSyscallNumber(sysno)) {
- // TODO(jln) we should not have to do that in a trivial policy.
- return ErrorCode(ENOSYS);
- } else {
- return ErrorCode(ErrorCode::ERR_ALLOWED);
- }
+ResultExpr AllowAllPolicy::EvaluateSyscall(int sysno) const {
+ return Allow();
}
// If a BPF policy is engaged for |process_type|, run a few sanity checks.
void RunSandboxSanityChecks(const std::string& process_type) {
if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess ||
process_type == switches::kGpuProcess ||
process_type == switches::kPpapiPluginProcess) {
int syscall_ret;
@@ -151,7 +144,7 @@ void RunSandboxSanityChecks(const std::string& process_type) {
// This function takes ownership of |policy|.
-void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy) {
+void StartSandboxWithPolicy(sandbox::bpf_dsl::Policy* policy) {
// Starting the sandbox is a one-way operation. The kernel doesn't allow
// us to unload a sandbox policy after it has been started. Nonetheless,
// in order to make the use of the "Sandbox" object easier, we allow for
@@ -166,7 +159,8 @@ void StartSandboxWithPolicy(sandbox::SandboxBPFPolicy* policy) {
// in its dependencies. Make sure to not link things that are not needed.
#if !defined(IN_NACL_HELPER)
scoped_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
bool allow_sysv_shm = false;
if (command_line.HasSwitch(switches::kGpuSandboxAllowSysVShm)) {
DCHECK(IsArchitectureArm());
@@ -177,24 +171,27 @@ scoped_ptr<SandboxBPFBasePolicy> GetGpuProcessSandbox() {
return scoped_ptr<SandboxBPFBasePolicy>(
new CrosArmGpuProcessPolicy(allow_sysv_shm));
} else {
- return scoped_ptr<SandboxBPFBasePolicy>(new GpuProcessPolicy);
+ bool allow_mincore = command_line.HasSwitch(switches::kUseGL) &&
+ command_line.GetSwitchValueASCII(switches::kUseGL) ==
+ gfx::kGLImplementationEGLName;
+ return scoped_ptr<SandboxBPFBasePolicy>(
+ new GpuProcessPolicy(allow_mincore));
}
}
// Initialize the seccomp-bpf sandbox.
-bool StartBPFSandbox(const CommandLine& command_line,
+bool StartBPFSandbox(const base::CommandLine& command_line,
const std::string& process_type) {
scoped_ptr<SandboxBPFBasePolicy> policy;
if (process_type == switches::kGpuProcess) {
policy.reset(GetGpuProcessSandbox().release());
- } else if (process_type == switches::kRendererProcess ||
- process_type == switches::kWorkerProcess) {
+ } else if (process_type == switches::kRendererProcess) {
policy.reset(new RendererProcessPolicy);
} else if (process_type == switches::kPpapiPluginProcess) {
policy.reset(new PpapiProcessPolicy);
} else if (process_type == switches::kUtilityProcess) {
- policy.reset(new BlacklistDebugAndNumaPolicy);
+ policy.reset(new UtilityProcessPolicy);
} else {
NOTREACHED();
policy.reset(new AllowAllPolicy);
@@ -207,7 +204,7 @@ bool StartBPFSandbox(const CommandLine& command_line,
return true;
}
#else // defined(IN_NACL_HELPER)
-bool StartBPFSandbox(const CommandLine& command_line,
+bool StartBPFSandbox(const base::CommandLine& command_line,
const std::string& process_type) {
NOTREACHED();
// Avoid -Wunused-function with no-op code.
@@ -224,7 +221,8 @@ bool StartBPFSandbox(const CommandLine& command_line,
// Is seccomp BPF globally enabled?
bool SandboxSeccompBPF::IsSeccompBPFDesired() {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (!command_line.HasSwitch(switches::kNoSandbox) &&
!command_line.HasSwitch(switches::kDisableSeccompFilterSandbox)) {
return true;
@@ -236,7 +234,8 @@ bool SandboxSeccompBPF::IsSeccompBPFDesired() {
bool SandboxSeccompBPF::ShouldEnableSeccompBPF(
const std::string& process_type) {
#if defined(USE_SECCOMP_BPF)
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (process_type == switches::kGpuProcess)
return !command_line.HasSwitch(switches::kDisableGpuSandbox);
@@ -264,7 +263,8 @@ bool SandboxSeccompBPF::SupportsSandbox() {
bool SandboxSeccompBPF::StartSandbox(const std::string& process_type) {
#if defined(USE_SECCOMP_BPF)
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
if (IsSeccompBPFDesired() && // Global switches policy.
ShouldEnableSeccompBPF(process_type) && // Process-specific policy.
@@ -280,7 +280,7 @@ bool SandboxSeccompBPF::StartSandbox(const std::string& process_type) {
}
bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
- scoped_ptr<sandbox::SandboxBPFPolicy> policy) {
+ scoped_ptr<sandbox::bpf_dsl::Policy> policy) {
#if defined(USE_SECCOMP_BPF)
if (IsSeccompBPFDesired() && SupportsSandbox()) {
CHECK(policy);
@@ -291,12 +291,11 @@ bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
return false;
}
-scoped_ptr<sandbox::SandboxBPFPolicy>
-SandboxSeccompBPF::GetBaselinePolicy() {
+scoped_ptr<sandbox::bpf_dsl::Policy> SandboxSeccompBPF::GetBaselinePolicy() {
#if defined(USE_SECCOMP_BPF)
- return scoped_ptr<sandbox::SandboxBPFPolicy>(new BaselinePolicy);
+ return scoped_ptr<sandbox::bpf_dsl::Policy>(new BaselinePolicy);
#else
- return scoped_ptr<sandbox::SandboxBPFPolicy>();
+ return scoped_ptr<sandbox::bpf_dsl::Policy>();
#endif // defined(USE_SECCOMP_BPF)
}
diff --git a/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h
index cbf6daf8167..91702fc443d 100644
--- a/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h
+++ b/chromium/content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h
@@ -11,7 +11,9 @@
#include "base/memory/scoped_ptr.h"
namespace sandbox {
-class SandboxBPFPolicy;
+namespace bpf_dsl {
+class Policy;
+}
}
namespace content {
@@ -39,9 +41,9 @@ class SandboxSeccompBPF {
// This is the API to enable a seccomp-bpf sandbox by using an
// external policy.
static bool StartSandboxWithExternalPolicy(
- scoped_ptr<sandbox::SandboxBPFPolicy> policy);
+ scoped_ptr<sandbox::bpf_dsl::Policy> policy);
// The "baseline" policy can be a useful base to build a sandbox policy.
- static scoped_ptr<sandbox::SandboxBPFPolicy> GetBaselinePolicy();
+ static scoped_ptr<sandbox::bpf_dsl::Policy> GetBaselinePolicy();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxSeccompBPF);
@@ -50,4 +52,3 @@ class SandboxSeccompBPF {
} // namespace content
#endif // CONTENT_COMMON_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
-
diff --git a/chromium/content/common/sandbox_mac.mm b/chromium/content/common/sandbox_mac.mm
index f4ea8d57583..118919f20a3 100644
--- a/chromium/content/common/sandbox_mac.mm
+++ b/chromium/content/common/sandbox_mac.mm
@@ -16,7 +16,7 @@ extern "C" {
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/mac_util.h"
@@ -31,13 +31,18 @@ extern "C" {
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "content/grit/content_resources.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "grit/content_resources.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "ui/base/layout.h"
#include "ui/gl/gl_surface.h"
+extern "C" {
+void CGSSetDenyWindowServerConnections(bool);
+void CGSShutdownServerConnections();
+};
+
namespace content {
namespace {
@@ -53,7 +58,6 @@ struct SandboxTypeToResourceIDMapping {
// profile for all process types known to content.
SandboxTypeToResourceIDMapping kDefaultSandboxTypeToResourceIDMapping[] = {
{ SANDBOX_TYPE_RENDERER, IDR_RENDERER_SANDBOX_PROFILE },
- { SANDBOX_TYPE_WORKER, IDR_WORKER_SANDBOX_PROFILE },
{ SANDBOX_TYPE_UTILITY, IDR_UTILITY_SANDBOX_PROFILE },
{ SANDBOX_TYPE_GPU, IDR_GPU_SANDBOX_PROFILE },
{ SANDBOX_TYPE_PPAPI, IDR_PPAPI_SANDBOX_PROFILE },
@@ -269,8 +273,8 @@ void Sandbox::SandboxWarmup(int sandbox_type) {
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
// Load in the color profiles we'll need (as a side effect).
- (void) base::mac::GetSRGBColorSpace();
- (void) base::mac::GetSystemColorSpace();
+ ignore_result(base::mac::GetSRGBColorSpace());
+ ignore_result(base::mac::GetSystemColorSpace());
// CGColorSpaceCreateSystemDefaultCMYK - 10.6
base::ScopedCFTypeRef<CGColorSpaceRef> cmyk_colorspace(
@@ -326,6 +330,18 @@ void Sandbox::SandboxWarmup(int sandbox_type) {
NSColor* color = [NSColor controlTextColor];
[color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
}
+
+ if (sandbox_type == SANDBOX_TYPE_RENDERER &&
+ base::mac::IsOSMountainLionOrLater()) {
+ // Now disconnect from WindowServer, after all objects have been warmed up.
+ // Shutting down the connection requires connecting to WindowServer,
+ // so do this before actually engaging the sandbox. This is only done on
+ // 10.8 and higher because doing it on earlier OSes causes layout tests to
+ // fail <http://crbug.com/397642#c48>. This may cause two log messages to
+ // be printed to the system logger on certain OS versions.
+ CGSSetDenyWindowServerConnections(true);
+ CGSShutdownServerConnections();
+ }
}
// static
@@ -526,7 +542,8 @@ bool Sandbox::EnableSandbox(int sandbox_type,
// Enable verbose logging if enabled on the command line. (See common.sb
// for details).
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
bool enable_logging =
command_line->HasSwitch(switches::kEnableSandboxLogging);;
if (enable_logging) {
diff --git a/chromium/content/common/sandbox_mac_diraccess_unittest.mm b/chromium/content/common/sandbox_mac_diraccess_unittest.mm
index 06a5442b255..7a3fed8dfbc 100644
--- a/chromium/content/common/sandbox_mac_diraccess_unittest.mm
+++ b/chromium/content/common/sandbox_mac_diraccess_unittest.mm
@@ -9,8 +9,8 @@ extern "C" {
#include <sandbox.h>
}
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/process/kill.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -61,7 +61,7 @@ TEST_F(MacDirAccessSandboxTest, StringEscape) {
{"^\u2135.\u2136$", "^\\u2135.\\u2136$"},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(string_escape_cases); ++i) {
+ for (size_t i = 0; i < arraysize(string_escape_cases); ++i) {
std::string out;
std::string in(string_escape_cases[i].to_escape);
EXPECT_TRUE(Sandbox::QuotePlainString(in, &out));
@@ -103,7 +103,7 @@ TEST_F(MacDirAccessSandboxTest, RegexEscape) {
}
{
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(regex_cases); ++i) {
+ for (size_t i = 0; i < arraysize(regex_cases); ++i) {
std::string out;
std::string in = base::WideToUTF8(regex_cases[i].to_escape);
EXPECT_TRUE(Sandbox::QuoteStringForRegex(in, &out));
@@ -159,7 +159,7 @@ TEST_F(MacDirAccessSandboxTest, SandboxAccess) {
"\\^.$|()[]*+?{}", // All regex characters.
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(sandbox_dir_cases); ++i) {
+ for (size_t i = 0; i < arraysize(sandbox_dir_cases); ++i) {
const char* sandbox_dir_name = sandbox_dir_cases[i];
base::FilePath sandbox_dir = tmp_dir.Append(sandbox_dir_name);
ASSERT_TRUE(CreateDirectory(sandbox_dir));
diff --git a/chromium/content/common/sandbox_mac_fontloading_unittest.mm b/chromium/content/common/sandbox_mac_fontloading_unittest.mm
index da033b7645b..645a7f6d909 100644
--- a/chromium/content/common/sandbox_mac_fontloading_unittest.mm
+++ b/chromium/content/common/sandbox_mac_fontloading_unittest.mm
@@ -4,7 +4,7 @@
#import <Cocoa/Cocoa.h>
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
@@ -20,8 +20,9 @@ namespace content {
class FontLoadingTestCase : public MacSandboxTestCase {
public:
FontLoadingTestCase() : font_data_length_(-1) {}
- virtual bool BeforeSandboxInit() OVERRIDE;
- virtual bool SandboxedTest() OVERRIDE;
+ bool BeforeSandboxInit() override;
+ bool SandboxedTest() override;
+
private:
scoped_ptr<base::SharedMemory> font_shmem_;
size_t font_data_length_;
diff --git a/chromium/content/common/sandbox_mac_system_access_unittest.mm b/chromium/content/common/sandbox_mac_system_access_unittest.mm
index c527ea5be29..1d5f1d48d53 100644
--- a/chromium/content/common/sandbox_mac_system_access_unittest.mm
+++ b/chromium/content/common/sandbox_mac_system_access_unittest.mm
@@ -4,15 +4,21 @@
#import <Cocoa/Cocoa.h>
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "content/common/sandbox_mac.h"
#include "content/common/sandbox_mac_unittest_helper.h"
-#include "crypto/nss_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(USE_OPENSSL)
+#include <openssl/rand.h>
+#include "crypto/openssl_util.h"
+#else
+#include "crypto/nss_util.h"
+#endif
+
namespace content {
//--------------------- Clipboard Sandboxing ----------------------
@@ -20,11 +26,12 @@ namespace content {
class MacSandboxedClipboardTestCase : public MacSandboxTestCase {
public:
MacSandboxedClipboardTestCase();
- virtual ~MacSandboxedClipboardTestCase();
+ ~MacSandboxedClipboardTestCase() override;
+
+ bool SandboxedTest() override;
- virtual bool SandboxedTest() OVERRIDE;
+ void SetTestData(const char* test_data) override;
- virtual void SetTestData(const char* test_data) OVERRIDE;
private:
NSString* clipboard_name_;
};
@@ -81,7 +88,7 @@ TEST_F(MacSandboxTest, ClipboardAccess) {
// Test case for checking sandboxing of filesystem apis.
class MacSandboxedFileAccessTestCase : public MacSandboxTestCase {
public:
- virtual bool SandboxedTest() OVERRIDE;
+ bool SandboxedTest() override;
};
REGISTER_SANDBOX_TEST_CASE(MacSandboxedFileAccessTestCase);
@@ -99,7 +106,7 @@ TEST_F(MacSandboxTest, FileAccess) {
// /dev/urandom is available to any sandboxed process.
class MacSandboxedUrandomTestCase : public MacSandboxTestCase {
public:
- virtual bool SandboxedTest() OVERRIDE;
+ bool SandboxedTest() override;
};
REGISTER_SANDBOX_TEST_CASE(MacSandboxedUrandomTestCase);
@@ -120,11 +127,36 @@ TEST_F(MacSandboxTest, UrandomAccess) {
EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedUrandomTestCase", NULL));
}
+#if defined(USE_OPENSSL)
+
+//--------------------- OpenSSL Sandboxing ----------------------
+// Test case for checking sandboxing of OpenSSL initialization.
+class MacSandboxedOpenSSLTestCase : public MacSandboxTestCase {
+ public:
+ bool SandboxedTest() override;
+};
+
+REGISTER_SANDBOX_TEST_CASE(MacSandboxedOpenSSLTestCase);
+
+bool MacSandboxedOpenSSLTestCase::SandboxedTest() {
+ crypto::EnsureOpenSSLInit();
+
+ // Ensure that RAND_bytes is functional within the sandbox.
+ uint8_t byte;
+ return RAND_bytes(&byte, 1) == 1;
+}
+
+TEST_F(MacSandboxTest, OpenSSLAccess) {
+ EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedOpenSSLTestCase", NULL));
+}
+
+#else // !defined(USE_OPENSSL)
+
//--------------------- NSS Sandboxing ----------------------
// Test case for checking sandboxing of NSS initialization.
class MacSandboxedNSSTestCase : public MacSandboxTestCase {
public:
- virtual bool SandboxedTest() OVERRIDE;
+ virtual bool SandboxedTest() override;
};
REGISTER_SANDBOX_TEST_CASE(MacSandboxedNSSTestCase);
@@ -141,4 +173,6 @@ TEST_F(MacSandboxTest, NSSAccess) {
EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedNSSTestCase", NULL));
}
+#endif // defined(USE_OPENSSL)
+
} // namespace content
diff --git a/chromium/content/common/sandbox_win.cc b/chromium/content/common/sandbox_win.cc
index d733213f020..1a5a66c0831 100644
--- a/chromium/content/common/sandbox_win.cc
+++ b/chromium/content/common/sandbox_win.cc
@@ -10,9 +10,8 @@
#include "base/command_line.h"
#include "base/debug/profiler.h"
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/hash.h"
-#include "base/metrics/field_trial.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
@@ -29,7 +28,7 @@
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/win_utils.h"
-#include "ui/gfx/win/dpi.h"
+#include "ui/gfx/win/direct_write.h"
static sandbox::BrokerServices* g_broker_services = NULL;
static sandbox::TargetServices* g_target_services = NULL;
@@ -43,10 +42,10 @@ namespace {
// For more information about how this list is generated, and how to get off
// of it, see:
// https://sites.google.com/a/chromium.org/dev/Home/third-party-developers
-// If the size of this list exceeds 64, change kTroublesomeDllsMaxCount.
const wchar_t* const kTroublesomeDlls[] = {
L"adialhk.dll", // Kaspersky Internet Security.
L"acpiz.dll", // Unknown.
+ L"airfoilinject3.dll", // Airfoil.
L"akinsofthook32.dll", // Akinsoft Software Engineering.
L"assistant_x64.dll", // Unknown.
L"avcuf64.dll", // Bit Defender Internet Security x64.
@@ -83,6 +82,8 @@ const wchar_t* const kTroublesomeDlls[] = {
L"pavshookwow.dll", // Panda Antivirus.
L"pctavhook.dll", // PC Tools Antivirus.
L"pctgmhk.dll", // PC Tools Spyware Doctor.
+ L"picrmi32.dll", // PicRec.
+ L"picrmi64.dll", // PicRec.
L"prntrack.dll", // Pharos Systems.
L"protector.dll", // Unknown (suspected malware).
L"radhslib.dll", // Radiant Naomi Internet Filter.
@@ -192,8 +193,8 @@ void BlacklistAddOneDll(const wchar_t* module_name,
DCHECK_LE(3U, (name.size() - period));
if (period <= 8)
return;
- for (int ix = 0; ix < 3; ++ix) {
- const wchar_t suffix[] = {'~', ('1' + ix), 0};
+ for (wchar_t ix = '1'; ix <= '3'; ++ix) {
+ const wchar_t suffix[] = {'~', ix, 0};
std::wstring alt_name = name.substr(0, 6) + suffix;
alt_name += name.substr(period, name.size());
if (check_in_browser) {
@@ -243,7 +244,7 @@ base::string16 PrependWindowsSessionPath(const base::char16* object) {
}
// Checks if the sandbox should be let to run without a job object assigned.
-bool ShouldSetJobLevel(const CommandLine& cmd_line) {
+bool ShouldSetJobLevel(const base::CommandLine& cmd_line) {
if (!cmd_line.HasSwitch(switches::kAllowNoSandboxJob))
return true;
@@ -349,7 +350,18 @@ bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) {
// Win8+ adds a device DeviceApi that we don't need.
if (base::win::GetVersion() > base::win::VERSION_WIN7)
- policy->AddKernelObjectToClose(L"File", L"\\Device\\DeviceApi");
+ result = policy->AddKernelObjectToClose(L"File", L"\\Device\\DeviceApi");
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
+ // Close the proxy settings on XP.
+ if (base::win::GetVersion() <= base::win::VERSION_SERVER_2003)
+ result = policy->AddKernelObjectToClose(L"Key",
+ L"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\" \
+ L"CurrentVersion\\Internet Settings");
+ if (result != sandbox::SBOX_ALL_OK)
+ return false;
+
sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
if (base::win::GetVersion() > base::win::VERSION_XP) {
@@ -361,6 +373,7 @@ bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) {
policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN);
// Prevents the renderers from manipulating low-integrity processes.
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
+ policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
if (sandbox::SBOX_ALL_OK != policy->SetAlternateDesktop(true)) {
DLOG(WARNING) << "Failed to apply desktop security to the renderer";
@@ -372,8 +385,9 @@ bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) {
// Updates the command line arguments with debug-related flags. If debug flags
// have been used with this process, they will be filtered and added to
// command_line as needed.
-void ProcessDebugFlags(CommandLine* command_line) {
- const CommandLine& current_cmd_line = *CommandLine::ForCurrentProcess();
+void ProcessDebugFlags(base::CommandLine* command_line) {
+ const base::CommandLine& current_cmd_line =
+ *base::CommandLine::ForCurrentProcess();
std::string type = command_line->GetSwitchValueASCII(switches::kProcessType);
if (current_cmd_line.HasSwitch(switches::kWaitForDebuggerChildren)) {
// Look to pass-on the kWaitForDebugger flag.
@@ -430,8 +444,8 @@ void CheckDuplicateHandle(HANDLE handle) {
kDuplicateHandleWarning;
if (0 == _wcsicmp(type_info->Name.Buffer, L"Process")) {
- const ACCESS_MASK kDangerousMask = ~(PROCESS_QUERY_LIMITED_INFORMATION |
- SYNCHRONIZE);
+ const ACCESS_MASK kDangerousMask =
+ ~static_cast<DWORD>(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE);
CHECK(!(basic_info.GrantedAccess & kDangerousMask)) <<
kDuplicateHandleWarning;
}
@@ -468,7 +482,7 @@ BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle,
PROCESS_QUERY_INFORMATION,
FALSE, 0));
base::win::ScopedHandle process(temp_handle);
- CHECK(::IsProcessInJob(process, NULL, &is_in_job));
+ CHECK(::IsProcessInJob(process.Get(), NULL, &is_in_job));
}
}
@@ -484,7 +498,7 @@ BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle,
base::win::ScopedHandle handle(temp_handle);
// Callers use CHECK macro to make sure we get the right stack.
- CheckDuplicateHandle(handle);
+ CheckDuplicateHandle(handle.Get());
}
return TRUE;
@@ -493,7 +507,7 @@ BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle,
} // namespace
-void SetJobLevel(const CommandLine& cmd_line,
+void SetJobLevel(const base::CommandLine& cmd_line,
sandbox::JobLevel job_level,
uint32 ui_exceptions,
sandbox::TargetPolicy* policy) {
@@ -563,42 +577,11 @@ bool InitTargetServices(sandbox::TargetServices* target_services) {
return sandbox::SBOX_ALL_OK == result;
}
-bool ShouldUseDirectWrite() {
- // If the flag is currently on, and we're on Win7 or above, we enable
- // DirectWrite. Skia does not require the additions to DirectWrite in QFE
- // 2670838, but a simple 'better than XP' check is not enough.
- if (base::win::GetVersion() < base::win::VERSION_WIN7)
- return false;
-
- base::win::OSInfo::VersionNumber os_version =
- base::win::OSInfo::GetInstance()->version_number();
- if ((os_version.major == 6) && (os_version.minor == 1)) {
- // We can't use DirectWrite for pre-release versions of Windows 7.
- if (os_version.build < 7600)
- return false;
- }
-
- // If forced off, don't use it.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kDisableDirectWrite))
- return false;
-
-#if !defined(NACL_WIN64)
- // Can't use GDI on HiDPI.
- if (gfx::GetDPIScale() > 1.0f)
- return true;
-#endif
-
- // Otherwise, check the field trial.
- const std::string group_name =
- base::FieldTrialList::FindFullName("DirectWrite");
- return group_name != "Disabled";
-}
-
base::ProcessHandle StartSandboxedProcess(
SandboxedProcessLauncherDelegate* delegate,
- CommandLine* cmd_line) {
- const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ base::CommandLine* cmd_line) {
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
std::string type_str = cmd_line->GetSwitchValueASCII(switches::kProcessType);
TRACE_EVENT_BEGIN_ETW("StartProcessWithAccess", 0, type_str);
@@ -665,13 +648,15 @@ base::ProcessHandle StartSandboxedProcess(
return 0;
if (type_str == switches::kRendererProcess) {
- if (ShouldUseDirectWrite()) {
+#if !defined(NACL_WIN64)
+ if (gfx::win::ShouldUseDirectWrite()) {
AddDirectory(base::DIR_WINDOWS_FONTS,
NULL,
true,
sandbox::TargetPolicy::FILES_ALLOW_READONLY,
policy);
}
+#endif
} else {
// Hack for Google Desktop crash. Trick GD into not injecting its DLL into
// this subprocess. See
@@ -737,7 +722,8 @@ base::ProcessHandle StartSandboxedProcess(
if (delegate)
delegate->PostSpawnTarget(target.process_handle());
- ResumeThread(target.thread_handle());
+ CHECK(ResumeThread(target.thread_handle()) != -1);
+ TRACE_EVENT_END_ETW("StartProcessWithAccess", 0, type_str);
return target.TakeProcessHandle();
}
@@ -768,7 +754,7 @@ bool BrokerDuplicateHandle(HANDLE source_handle,
target_process_id));
if (target_process.IsValid()) {
return !!::DuplicateHandle(::GetCurrentProcess(), source_handle,
- target_process, target_handle,
+ target_process.Get(), target_handle,
desired_access, FALSE, options);
}
diff --git a/chromium/content/common/sandbox_win.h b/chromium/content/common/sandbox_win.h
index 1703d7a9ec7..7fe52a85aaa 100644
--- a/chromium/content/common/sandbox_win.h
+++ b/chromium/content/common/sandbox_win.h
@@ -34,9 +34,6 @@ bool InitBrokerServices(sandbox::BrokerServices* broker_services);
bool InitTargetServices(sandbox::TargetServices* target_services);
-// Returns whether DirectWrite font rendering should be used.
-CONTENT_EXPORT bool ShouldUseDirectWrite();
-
} // namespace content
#endif // CONTENT_COMMON_SANDBOX_WIN_H_
diff --git a/chromium/content/common/screen_orientation_messages.h b/chromium/content/common/screen_orientation_messages.h
index b7336d6b657..2defcc71fa5 100644
--- a/chromium/content/common/screen_orientation_messages.h
+++ b/chromium/content/common/screen_orientation_messages.h
@@ -7,7 +7,7 @@
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/WebLockOrientationCallback.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationError.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
@@ -21,11 +21,11 @@ IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScreenOrientationType,
blink::WebScreenOrientationLandscapeSecondary)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebScreenOrientationLockType,
blink::WebScreenOrientationLockDefault,
- blink::WebScreenOrientationLockPortrait)
+ blink::WebScreenOrientationLockNatural)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(
- blink::WebLockOrientationCallback::ErrorType,
- blink::WebLockOrientationCallback::ErrorTypeNotAvailable,
- blink::WebLockOrientationCallback::ErrorTypeCanceled)
+ blink::WebLockOrientationError,
+ blink::WebLockOrientationErrorNotAvailable,
+ blink::WebLockOrientationErrorCanceled)
// The browser process informs the renderer process that the screen orientation
// has changed. |orientation| contains the new screen orientation in degrees.
@@ -34,13 +34,11 @@ IPC_MESSAGE_CONTROL1(ScreenOrientationMsg_OrientationChange,
blink::WebScreenOrientationType /* orientation */ )
// The browser process' response to a ScreenOrientationHostMsg_LockRequest when
-// the lock actually succeeded. The message includes the new |angle| and |type|
-// of orientation. The |request_id| passed when receiving the request is passed
-// back so the renderer process can associate the response to the right request.
-IPC_MESSAGE_ROUTED3(ScreenOrientationMsg_LockSuccess,
- int, /* request_id */
- unsigned, /* angle */
- blink::WebScreenOrientationType /* type */)
+// the lock actually succeeded. The |request_id| passed when receiving the
+// request is passed back so the renderer process can associate the response to
+// the right request.
+IPC_MESSAGE_ROUTED1(ScreenOrientationMsg_LockSuccess,
+ int /* request_id */)
// The browser process' response to a ScreenOrientationHostMsg_LockRequest when
// the lock actually failed. The message includes the |error| type. The
@@ -48,7 +46,7 @@ IPC_MESSAGE_ROUTED3(ScreenOrientationMsg_LockSuccess,
// process can associate the response to the right request.
IPC_MESSAGE_ROUTED2(ScreenOrientationMsg_LockError,
int, /* request_id */
- blink::WebLockOrientationCallback::ErrorType /* error */);
+ blink::WebLockOrientationError /* error */)
// The renderer process requests the browser process to lock the screen
// orientation to the specified |orientations|. The request contains a
@@ -62,3 +60,17 @@ IPC_MESSAGE_ROUTED2(ScreenOrientationHostMsg_LockRequest,
// The renderer process requests the browser process to unlock the screen
// orientation.
IPC_MESSAGE_ROUTED0(ScreenOrientationHostMsg_Unlock)
+
+// The renderer process is now using the Screen Orientation API and informs the
+// browser process that it should start accurately listening to the screen
+// orientation if it wasn't already.
+// This is only expected to be acted upon when the underlying platform requires
+// heavy work in order to accurately know the screen orientation.
+IPC_MESSAGE_CONTROL0(ScreenOrientationHostMsg_StartListening)
+
+// The renderer process is no longer using the Screen Orientation API and
+// informs the browser process that it can stop accurately listening to the
+// screen orientation if no other process cares about it.
+// This is only expected to be acted upon when the underlying platform requires
+// heavy work in order to accurately know the screen orientation.
+IPC_MESSAGE_CONTROL0(ScreenOrientationHostMsg_StopListening)
diff --git a/chromium/content/common/service_worker/OWNERS b/chromium/content/common/service_worker/OWNERS
index 98927dc929d..5f81c8940ad 100644
--- a/chromium/content/common/service_worker/OWNERS
+++ b/chromium/content/common/service_worker/OWNERS
@@ -1,5 +1,7 @@
michaeln@chromium.org
falken@chromium.org
+horo@chromium.org
+nhiroki@chromium.org
# may not be available
kinuko@chromium.org
@@ -7,12 +9,13 @@ kinuko@chromium.org
# Changes to IPC messages require a security review to avoid introducing
# new sandbox escapes.
per-file *_messages*.h=set noparent
-per-file *_messages*.h=cevans@chromium.org
per-file *_messages*.h=dcheng@chromium.org
per-file *_messages*.h=inferno@chromium.org
per-file *_messages*.h=jln@chromium.org
per-file *_messages*.h=jschuh@chromium.org
per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
per-file *_messages*.h=nasko@chromium.org
per-file *_messages*.h=palmer@chromium.org
per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/service_worker/embedded_worker_messages.h b/chromium/content/common/service_worker/embedded_worker_messages.h
index df5cf6914a3..438cf6cc19d 100644
--- a/chromium/content/common/service_worker/embedded_worker_messages.h
+++ b/chromium/content/common/service_worker/embedded_worker_messages.h
@@ -23,7 +23,8 @@ IPC_STRUCT_BEGIN(EmbeddedWorkerMsg_StartWorker_Params)
IPC_STRUCT_MEMBER(GURL, scope)
IPC_STRUCT_MEMBER(GURL, script_url)
IPC_STRUCT_MEMBER(int, worker_devtools_agent_route_id)
- IPC_STRUCT_MEMBER(bool, pause_on_start)
+ IPC_STRUCT_MEMBER(bool, pause_after_download)
+ IPC_STRUCT_MEMBER(bool, wait_for_debugger)
IPC_STRUCT_END()
// Parameters structure for EmbeddedWorkerHostMsg_ReportConsoleMessage.
@@ -41,23 +42,44 @@ IPC_STRUCT_END()
IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_StartWorker,
EmbeddedWorkerMsg_StartWorker_Params /* params */)
+// Browser -> Renderer message to resume a worker that has been started
+// with the pause_after_download option.
+IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_ResumeAfterDownload,
+ int /* embedded_worker_id */)
+
// Browser -> Renderer message to stop (terminate) the embedded worker.
IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_StopWorker,
int /* embedded_worker_id */)
+// Renderer -> Browser message to indicate that the worker script has been
+// downloaded and the embedded worker is in paused state.
+IPC_MESSAGE_CONTROL1(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
+ int /* embedded_worker_id */)
+
+// Renderer -> Browser message to indicate that the worker is ready for
+// inspection.
+IPC_MESSAGE_CONTROL1(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
+ int /* embedded_worker_id */)
+
// Renderer -> Browser message to indicate that the worker has loadedd the
// script.
-IPC_MESSAGE_CONTROL1(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
- int /* embedded_worker_id */)
+IPC_MESSAGE_CONTROL2(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
+ int /* embedded_worker_id */,
+ int /* thread_id */)
// Renderer -> Browser message to indicate that the worker has failed to load
// the script.
IPC_MESSAGE_CONTROL1(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
int /* embedded_worker_id */)
+// Renderer -> Browser message to indicate that the worker has evaluated the
+// script.
+IPC_MESSAGE_CONTROL2(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
+ int /* embedded_worker_id */,
+ bool /* success */)
+
// Renderer -> Browser message to indicate that the worker is started.
-IPC_MESSAGE_CONTROL2(EmbeddedWorkerHostMsg_WorkerStarted,
- int /* thread_id */,
+IPC_MESSAGE_CONTROL1(EmbeddedWorkerHostMsg_WorkerStarted,
int /* embedded_worker_id */)
// Renderer -> Browser message to indicate that the worker is stopped.
diff --git a/chromium/content/common/service_worker/service_worker_messages.h b/chromium/content/common/service_worker/service_worker_messages.h
index 0b0cb4ea821..f645c5699fb 100644
--- a/chromium/content/common/service_worker/service_worker_messages.h
+++ b/chromium/content/common/service_worker/service_worker_messages.h
@@ -4,11 +4,17 @@
// Message definition file, included multiple times, hence no include guard.
+#include <string>
+#include <vector>
+
#include "base/strings/string16.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
+#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
+#include "third_party/WebKit/public/platform/WebGeofencingEventType.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
#include "url/gurl.h"
@@ -27,20 +33,51 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerEventResult,
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerState,
blink::WebServiceWorkerStateLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerResponseType,
+ blink::WebServiceWorkerResponseTypeLast)
+
IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerFetchRequest)
+ IPC_STRUCT_TRAITS_MEMBER(mode)
+ IPC_STRUCT_TRAITS_MEMBER(request_context_type)
+ IPC_STRUCT_TRAITS_MEMBER(frame_type)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(method)
IPC_STRUCT_TRAITS_MEMBER(headers)
+ IPC_STRUCT_TRAITS_MEMBER(blob_uuid)
+ IPC_STRUCT_TRAITS_MEMBER(blob_size)
+ IPC_STRUCT_TRAITS_MEMBER(referrer)
+ IPC_STRUCT_TRAITS_MEMBER(credentials_mode)
+ IPC_STRUCT_TRAITS_MEMBER(is_reload)
IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS_MAX_VALUE(content::ServiceWorkerFetchEventResult,
content::SERVICE_WORKER_FETCH_EVENT_LAST)
IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerResponse)
+ IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(status_code)
IPC_STRUCT_TRAITS_MEMBER(status_text)
+ IPC_STRUCT_TRAITS_MEMBER(response_type)
IPC_STRUCT_TRAITS_MEMBER(headers)
IPC_STRUCT_TRAITS_MEMBER(blob_uuid)
+ IPC_STRUCT_TRAITS_MEMBER(blob_size)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerCacheQueryParams)
+ IPC_STRUCT_TRAITS_MEMBER(ignore_search)
+ IPC_STRUCT_TRAITS_MEMBER(ignore_method)
+ IPC_STRUCT_TRAITS_MEMBER(ignore_vary)
+ IPC_STRUCT_TRAITS_MEMBER(prefix_match)
+IPC_STRUCT_TRAITS_END()
+
+IPC_ENUM_TRAITS_MAX_VALUE(content::ServiceWorkerCacheOperationType,
+ content::SERVICE_WORKER_CACHE_OPERATION_TYPE_LAST)
+
+IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerBatchOperation)
+ IPC_STRUCT_TRAITS_MEMBER(operation_type)
+ IPC_STRUCT_TRAITS_MEMBER(request)
+ IPC_STRUCT_TRAITS_MEMBER(response)
+ IPC_STRUCT_TRAITS_MEMBER(match_params)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerObjectInfo)
@@ -48,8 +85,28 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerObjectInfo)
IPC_STRUCT_TRAITS_MEMBER(scope)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(state)
+ IPC_STRUCT_TRAITS_MEMBER(version_id)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerRegistrationObjectInfo)
+ IPC_STRUCT_TRAITS_MEMBER(handle_id)
+ IPC_STRUCT_TRAITS_MEMBER(scope)
+ IPC_STRUCT_TRAITS_MEMBER(registration_id)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerVersionAttributes)
+ IPC_STRUCT_TRAITS_MEMBER(installing)
+ IPC_STRUCT_TRAITS_MEMBER(waiting)
+ IPC_STRUCT_TRAITS_MEMBER(active)
+IPC_STRUCT_TRAITS_END()
+
+IPC_ENUM_TRAITS_MAX_VALUE(
+ blink::WebServiceWorkerCacheError,
+ blink::WebServiceWorkerCacheErrorLast)
+
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGeofencingEventType,
+ blink::WebGeofencingEventTypeLast)
+
//---------------------------------------------------------------------------
// Messages sent from the child process to the browser.
@@ -66,6 +123,12 @@ IPC_MESSAGE_CONTROL4(ServiceWorkerHostMsg_UnregisterServiceWorker,
int /* provider_id */,
GURL /* scope (url pattern) */)
+IPC_MESSAGE_CONTROL4(ServiceWorkerHostMsg_GetRegistration,
+ int /* thread_id */,
+ int /* request_id */,
+ int /* provider_id */,
+ GURL /* document_url */)
+
// Sends a 'message' event to a service worker (renderer->browser).
IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_PostMessageToWorker,
int /* handle_id */,
@@ -89,9 +152,17 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
int /* handle_id */)
+// Increments and decrements the ServiceWorkerRegistration object's reference
+// counting in the browser side. The registration object is created with
+// ref-count==1 initially.
+IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
+ int /* registration_handle_id */)
+IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
+ int /* registration_handle_id */)
+
// Informs the browser that |provider_id| is associated
// with a service worker script running context and
-// |version_id| identifies which ServcieWorkerVersion.
+// |version_id| identifies which ServiceWorkerVersion.
IPC_MESSAGE_CONTROL2(ServiceWorkerHostMsg_SetVersionId,
int /* provider_id */,
int64 /* version_id */)
@@ -103,7 +174,7 @@ IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_InstallEventFinished,
blink::WebServiceWorkerEventResult)
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_ActivateEventFinished,
int /* request_id */,
- blink::WebServiceWorkerEventResult);
+ blink::WebServiceWorkerEventResult)
IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_FetchEventFinished,
int /* request_id */,
content::ServiceWorkerFetchEventResult,
@@ -112,6 +183,8 @@ IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_SyncEventFinished,
int /* request_id */)
IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_PushEventFinished,
int /* request_id */)
+IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_GeofencingEventFinished,
+ int /* request_id */)
// Asks the browser to retrieve documents controlled by the sender
// ServiceWorker.
@@ -124,6 +197,52 @@ IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_PostMessageToDocument,
base::string16 /* message */,
std::vector<int> /* sent_message_port_ids */)
+// CacheStorage operations in the browser.
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_CacheStorageHas,
+ int /* request_id */,
+ base::string16 /* fetch_store_name */)
+
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_CacheStorageOpen,
+ int /* request_id */,
+ base::string16 /* fetch_store_name */)
+
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_CacheStorageDelete,
+ int /* request_id */,
+ base::string16 /* fetch_store_name */)
+
+IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_CacheStorageKeys,
+ int /* request_id */)
+
+// Cache operations in the browser.
+IPC_MESSAGE_ROUTED4(ServiceWorkerHostMsg_CacheMatch,
+ int /* request_id */,
+ int /* cache_id */,
+ content::ServiceWorkerFetchRequest,
+ content::ServiceWorkerCacheQueryParams)
+
+IPC_MESSAGE_ROUTED4(ServiceWorkerHostMsg_CacheMatchAll,
+ int /* request_id */,
+ int /* cache_id */,
+ content::ServiceWorkerFetchRequest,
+ content::ServiceWorkerCacheQueryParams)
+
+IPC_MESSAGE_ROUTED4(ServiceWorkerHostMsg_CacheKeys,
+ int /* request_id */,
+ int /* cache_id */,
+ content::ServiceWorkerFetchRequest,
+ content::ServiceWorkerCacheQueryParams)
+
+IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_CacheBatch,
+ int /* request_id */,
+ int /* cache_id */,
+ std::vector<content::ServiceWorkerBatchOperation>)
+
+IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_CacheClosed,
+ int /* cache_id */)
+
+IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_BlobDataHandled,
+ std::string /* uuid */)
+
//---------------------------------------------------------------------------
// Messages sent from the browser to the child process.
//
@@ -132,41 +251,84 @@ IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_PostMessageToDocument,
// extract it and dispatch the message to the correct ServiceWorkerDispatcher
// on the correct thread.
-// Response to ServiceWorkerMsg_RegisterServiceWorker.
-IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerRegistered,
+// Informs the child process that the given provider gets associated or
+// disassociated with the registration.
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_AssociateRegistration,
+ int /* thread_id */,
+ int /* provider_id */,
+ content::ServiceWorkerRegistrationObjectInfo,
+ content::ServiceWorkerVersionAttributes)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_DisassociateRegistration,
+ int /* thread_id */,
+ int /* provider_id */)
+
+// Response to ServiceWorkerHostMsg_RegisterServiceWorker.
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerRegistered,
int /* thread_id */,
int /* request_id */,
- content::ServiceWorkerObjectInfo)
+ content::ServiceWorkerRegistrationObjectInfo,
+ content::ServiceWorkerVersionAttributes)
-// Response to ServiceWorkerMsg_UnregisterServiceWorker.
-IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_ServiceWorkerUnregistered,
+// Response to ServiceWorkerHostMsg_UnregisterServiceWorker.
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerUnregistered,
int /* thread_id */,
- int /* request_id */)
+ int /* request_id */,
+ bool /* is_success */)
+
+// Response to ServiceWorkerHostMsg_GetRegistration.
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_DidGetRegistration,
+ int /* thread_id */,
+ int /* request_id */,
+ content::ServiceWorkerRegistrationObjectInfo,
+ content::ServiceWorkerVersionAttributes)
// Sent when any kind of registration error occurs during a
-// RegisterServiceWorker / UnregisterServiceWorker handler above.
+// RegisterServiceWorker handler above.
IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerRegistrationError,
int /* thread_id */,
int /* request_id */,
blink::WebServiceWorkerError::ErrorType /* code */,
base::string16 /* message */)
+// Sent when any kind of registration error occurs during a
+// UnregisterServiceWorker handler above.
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerUnregistrationError,
+ int /* thread_id */,
+ int /* request_id */,
+ blink::WebServiceWorkerError::ErrorType /* code */,
+ base::string16 /* message */)
+
+// Sent when any kind of registration error occurs during a
+// GetRegistration handler above.
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerGetRegistrationError,
+ int /* thread_id */,
+ int /* request_id */,
+ blink::WebServiceWorkerError::ErrorType /* code */,
+ base::string16 /* message */)
+
// Informs the child process that the ServiceWorker's state has changed.
IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerStateChanged,
int /* thread_id */,
int /* handle_id */,
blink::WebServiceWorkerState)
-// Tells the child process to set the waiting ServiceWorker for the given
-// provider.
-IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_SetWaitingServiceWorker,
+// Tells the child process to set service workers for the given provider.
+IPC_MESSAGE_CONTROL5(ServiceWorkerMsg_SetVersionAttributes,
int /* thread_id */,
int /* provider_id */,
- content::ServiceWorkerObjectInfo)
+ int /* registration_handle_id */,
+ int /* changed_mask */,
+ content::ServiceWorkerVersionAttributes)
-// Tells the child process to set the current ServiceWorker for the given
+// Informs the child process that new ServiceWorker enters the installation
+// phase.
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_UpdateFound,
+ int /* thread_id */,
+ content::ServiceWorkerRegistrationObjectInfo)
+
+// Tells the child process to set the controller ServiceWorker for the given
// provider.
-IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_SetCurrentServiceWorker,
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_SetControllerServiceWorker,
int /* thread_id */,
int /* provider_id */,
content::ServiceWorkerObjectInfo)
@@ -193,6 +355,11 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_SyncEvent,
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_PushEvent,
int /* request_id */,
std::string /* data */)
+IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_GeofencingEvent,
+ int /* request_id */,
+ blink::WebGeofencingEventType /* event_type */,
+ std::string /* region_id */,
+ blink::WebCircularGeofencingRegion /* region */)
IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_MessageToWorker,
base::string16 /* message */,
std::vector<int> /* sent_message_port_ids */,
@@ -202,3 +369,57 @@ IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_MessageToWorker,
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_DidGetClientDocuments,
int /* request_id */,
std::vector<int> /* client_ids */)
+
+// Sent via EmbeddedWorker at successful completion of CacheStorage operations.
+IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_CacheStorageHasSuccess,
+ int /* request_id */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheStorageOpenSuccess,
+ int /* request_id */,
+ int /* fetch_store_id */)
+IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_CacheStorageDeleteSuccess,
+ int /* request_id */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheStorageKeysSuccess,
+ int /* request_id */,
+ std::vector<base::string16> /* keys */)
+
+// Sent via EmbeddedWorker at erroneous completion of CacheStorage operations.
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheStorageHasError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError /* reason */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheStorageOpenError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError /* reason */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheStorageDeleteError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError /* reason */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheStorageKeysError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError /* reason */)
+
+// Sent via EmbeddedWorker at successful completion of Cache operations.
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheMatchSuccess,
+ int /* request_id */,
+ content::ServiceWorkerResponse)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheMatchAllSuccess,
+ int /* request_id */,
+ std::vector<content::ServiceWorkerResponse>)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheKeysSuccess,
+ int /* request_id */,
+ std::vector<content::ServiceWorkerFetchRequest>)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheBatchSuccess,
+ int /* request_id */,
+ std::vector<content::ServiceWorkerResponse>)
+
+// Sent via EmbeddedWorker at erroneous completion of CacheStorage operations.
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheMatchError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheMatchAllError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheKeysError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_CacheBatchError,
+ int /* request_id */,
+ blink::WebServiceWorkerCacheError)
diff --git a/chromium/content/common/service_worker/service_worker_status_code.cc b/chromium/content/common/service_worker/service_worker_status_code.cc
index bdf28a94f67..a402a8a73ef 100644
--- a/chromium/content/common/service_worker/service_worker_status_code.cc
+++ b/chromium/content/common/service_worker/service_worker_status_code.cc
@@ -30,6 +30,10 @@ const char* ServiceWorkerStatusToString(ServiceWorkerStatusCode status) {
return "ServiceWorker failed to activate";
case SERVICE_WORKER_ERROR_IPC_FAILED:
return "IPC connection was closed or IPC error has occured";
+ case SERVICE_WORKER_ERROR_NETWORK:
+ return "Operation failed by network issue";
+ case SERVICE_WORKER_ERROR_SECURITY:
+ return "Operation failed by security issue";
}
NOTREACHED();
return "";
diff --git a/chromium/content/common/service_worker/service_worker_status_code.h b/chromium/content/common/service_worker/service_worker_status_code.h
index a0245e48e10..953d533fc3c 100644
--- a/chromium/content/common/service_worker/service_worker_status_code.h
+++ b/chromium/content/common/service_worker/service_worker_status_code.h
@@ -42,6 +42,12 @@ enum ServiceWorkerStatusCode {
// Sending an IPC to the worker failed (often due to child process is
// terminated).
SERVICE_WORKER_ERROR_IPC_FAILED,
+
+ // Operation is failed by network issue.
+ SERVICE_WORKER_ERROR_NETWORK,
+
+ // Operation is failed by security issue.
+ SERVICE_WORKER_ERROR_SECURITY,
};
CONTENT_EXPORT const char* ServiceWorkerStatusToString(
diff --git a/chromium/content/common/service_worker/service_worker_types.cc b/chromium/content/common/service_worker/service_worker_types.cc
index ce5cd7aee07..dec264e6414 100644
--- a/chromium/content/common/service_worker/service_worker_types.cc
+++ b/chromium/content/common/service_worker/service_worker_types.cc
@@ -6,36 +6,76 @@
namespace content {
-ServiceWorkerFetchRequest::ServiceWorkerFetchRequest() {}
+ServiceWorkerFetchRequest::ServiceWorkerFetchRequest()
+ : mode(FETCH_REQUEST_MODE_NO_CORS),
+ request_context_type(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
+ frame_type(REQUEST_CONTEXT_FRAME_TYPE_NONE),
+ blob_size(0),
+ credentials_mode(FETCH_CREDENTIALS_MODE_OMIT),
+ is_reload(false) {
+}
ServiceWorkerFetchRequest::ServiceWorkerFetchRequest(
const GURL& url,
const std::string& method,
- const std::map<std::string, std::string>& headers)
- : url(url),
+ const ServiceWorkerHeaderMap& headers,
+ const GURL& referrer,
+ bool is_reload)
+ : mode(FETCH_REQUEST_MODE_NO_CORS),
+ request_context_type(REQUEST_CONTEXT_TYPE_UNSPECIFIED),
+ frame_type(REQUEST_CONTEXT_FRAME_TYPE_NONE),
+ url(url),
method(method),
- headers(headers) {
+ headers(headers),
+ blob_size(0),
+ referrer(referrer),
+ credentials_mode(FETCH_CREDENTIALS_MODE_OMIT),
+ is_reload(is_reload) {
}
ServiceWorkerFetchRequest::~ServiceWorkerFetchRequest() {}
-ServiceWorkerResponse::ServiceWorkerResponse() : status_code(0) {}
+ServiceWorkerResponse::ServiceWorkerResponse()
+ : status_code(0),
+ response_type(blink::WebServiceWorkerResponseTypeOpaque),
+ blob_size(0) {
+}
ServiceWorkerResponse::ServiceWorkerResponse(
+ const GURL& url,
int status_code,
const std::string& status_text,
- const std::map<std::string, std::string>& headers,
- const std::string& blob_uuid)
- : status_code(status_code),
+ blink::WebServiceWorkerResponseType response_type,
+ const ServiceWorkerHeaderMap& headers,
+ const std::string& blob_uuid,
+ uint64 blob_size)
+ : url(url),
+ status_code(status_code),
status_text(status_text),
+ response_type(response_type),
headers(headers),
- blob_uuid(blob_uuid) {
+ blob_uuid(blob_uuid),
+ blob_size(blob_size) {
}
ServiceWorkerResponse::~ServiceWorkerResponse() {}
+ServiceWorkerCacheQueryParams::ServiceWorkerCacheQueryParams()
+ : ignore_search(false),
+ ignore_method(false),
+ ignore_vary(false),
+ prefix_match(false) {}
+
+ServiceWorkerBatchOperation::ServiceWorkerBatchOperation() {}
+
ServiceWorkerObjectInfo::ServiceWorkerObjectInfo()
: handle_id(kInvalidServiceWorkerHandleId),
- state(blink::WebServiceWorkerStateUnknown) {}
+ state(blink::WebServiceWorkerStateUnknown),
+ version_id(kInvalidServiceWorkerVersionId) {}
+
+ServiceWorkerRegistrationObjectInfo::ServiceWorkerRegistrationObjectInfo()
+ : handle_id(kInvalidServiceWorkerRegistrationHandleId),
+ registration_id(kInvalidServiceWorkerRegistrationId) {
+}
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_types.h b/chromium/content/common/service_worker/service_worker_types.h
index 8f49f9a5635..d0ef45cbc0c 100644
--- a/chromium/content/common/service_worker/service_worker_types.h
+++ b/chromium/content/common/service_worker/service_worker_types.h
@@ -9,7 +9,11 @@
#include <string>
#include "base/basictypes.h"
+#include "base/strings/string_util.h"
#include "content/common/content_export.h"
+#include "content/public/common/request_context_frame_type.h"
+#include "content/public/common/request_context_type.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerState.h"
#include "url/gurl.h"
@@ -21,30 +25,31 @@ namespace content {
// Indicates invalid request ID (i.e. the sender does not expect it gets
// response for the message) for messaging between browser process
// and embedded worker.
-const static int kInvalidServiceWorkerRequestId = -1;
+static const int kInvalidServiceWorkerRequestId = -1;
// Constants for invalid identifiers.
-const static int kInvalidServiceWorkerHandleId = -1;
-const static int kInvalidServiceWorkerProviderId = -1;
-const static int64 kInvalidServiceWorkerRegistrationId = -1;
-const static int64 kInvalidServiceWorkerVersionId = -1;
-const static int64 kInvalidServiceWorkerResourceId = -1;
-const static int64 kInvalidServiceWorkerResponseId = -1;
+static const int kInvalidServiceWorkerHandleId = -1;
+static const int kInvalidServiceWorkerRegistrationHandleId = -1;
+static const int kInvalidServiceWorkerProviderId = -1;
+static const int64 kInvalidServiceWorkerRegistrationId = -1;
+static const int64 kInvalidServiceWorkerVersionId = -1;
+static const int64 kInvalidServiceWorkerResourceId = -1;
+static const int64 kInvalidServiceWorkerResponseId = -1;
+static const int kInvalidEmbeddedWorkerThreadId = -1;
-// To dispatch fetch request from browser to child process.
-// TODO(kinuko): This struct will definitely need more fields and
-// we'll probably want to have response struct/class too.
-struct CONTENT_EXPORT ServiceWorkerFetchRequest {
- ServiceWorkerFetchRequest();
- ServiceWorkerFetchRequest(
- const GURL& url,
- const std::string& method,
- const std::map<std::string, std::string>& headers);
- ~ServiceWorkerFetchRequest();
+enum FetchRequestMode {
+ FETCH_REQUEST_MODE_SAME_ORIGIN,
+ FETCH_REQUEST_MODE_NO_CORS,
+ FETCH_REQUEST_MODE_CORS,
+ FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT,
+ FETCH_REQUEST_MODE_LAST = FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT
+};
- GURL url;
- std::string method;
- std::map<std::string, std::string> headers;
+enum FetchCredentialsMode {
+ FETCH_CREDENTIALS_MODE_OMIT,
+ FETCH_CREDENTIALS_MODE_SAME_ORIGIN,
+ FETCH_CREDENTIALS_MODE_INCLUDE,
+ FETCH_CREDENTIALS_MODE_LAST = FETCH_CREDENTIALS_MODE_INCLUDE
};
// Indicates how the service worker handled a fetch event.
@@ -56,19 +61,86 @@ enum ServiceWorkerFetchEventResult {
SERVICE_WORKER_FETCH_EVENT_LAST = SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
};
+struct ServiceWorkerCaseInsensitiveCompare {
+ bool operator()(const std::string& lhs, const std::string& rhs) const {
+ return base::strcasecmp(lhs.c_str(), rhs.c_str()) < 0;
+ }
+};
+
+typedef std::map<std::string, std::string, ServiceWorkerCaseInsensitiveCompare>
+ ServiceWorkerHeaderMap;
+
+// To dispatch fetch request from browser to child process.
+struct CONTENT_EXPORT ServiceWorkerFetchRequest {
+ ServiceWorkerFetchRequest();
+ ServiceWorkerFetchRequest(const GURL& url,
+ const std::string& method,
+ const ServiceWorkerHeaderMap& headers,
+ const GURL& referrer,
+ bool is_reload);
+ ~ServiceWorkerFetchRequest();
+
+ FetchRequestMode mode;
+ RequestContextType request_context_type;
+ RequestContextFrameType frame_type;
+ GURL url;
+ std::string method;
+ ServiceWorkerHeaderMap headers;
+ std::string blob_uuid;
+ uint64 blob_size;
+ GURL referrer;
+ FetchCredentialsMode credentials_mode;
+ bool is_reload;
+};
+
// Represents a response to a fetch.
struct CONTENT_EXPORT ServiceWorkerResponse {
ServiceWorkerResponse();
- ServiceWorkerResponse(int status_code,
+ ServiceWorkerResponse(const GURL& url,
+ int status_code,
const std::string& status_text,
- const std::map<std::string, std::string>& headers,
- const std::string& blob_uuid);
+ blink::WebServiceWorkerResponseType response_type,
+ const ServiceWorkerHeaderMap& headers,
+ const std::string& blob_uuid,
+ uint64 blob_size);
~ServiceWorkerResponse();
+ GURL url;
int status_code;
std::string status_text;
- std::map<std::string, std::string> headers;
+ blink::WebServiceWorkerResponseType response_type;
+ ServiceWorkerHeaderMap headers;
std::string blob_uuid;
+ uint64 blob_size;
+};
+
+// Controls how requests are matched in the Cache API.
+struct CONTENT_EXPORT ServiceWorkerCacheQueryParams {
+ ServiceWorkerCacheQueryParams();
+
+ bool ignore_search;
+ bool ignore_method;
+ bool ignore_vary;
+ bool prefix_match;
+};
+
+// The type of a single batch operation in the Cache API.
+enum ServiceWorkerCacheOperationType {
+ SERVICE_WORKER_CACHE_OPERATION_TYPE_UNDEFINED,
+ SERVICE_WORKER_CACHE_OPERATION_TYPE_PUT,
+ SERVICE_WORKER_CACHE_OPERATION_TYPE_DELETE,
+ SERVICE_WORKER_CACHE_OPERATION_TYPE_LAST =
+ SERVICE_WORKER_CACHE_OPERATION_TYPE_DELETE
+};
+
+// A single batch operation for the Cache API.
+struct CONTENT_EXPORT ServiceWorkerBatchOperation {
+ ServiceWorkerBatchOperation();
+
+ ServiceWorkerCacheOperationType operation_type;
+ ServiceWorkerFetchRequest request;
+ ServiceWorkerResponse response;
+ ServiceWorkerCacheQueryParams match_params;
};
// Represents initialization info for a WebServiceWorker object.
@@ -78,6 +150,44 @@ struct CONTENT_EXPORT ServiceWorkerObjectInfo {
GURL scope;
GURL url;
blink::WebServiceWorkerState state;
+ int64 version_id;
+};
+
+struct ServiceWorkerRegistrationObjectInfo {
+ ServiceWorkerRegistrationObjectInfo();
+ int handle_id;
+ GURL scope;
+ int64 registration_id;
+};
+
+struct ServiceWorkerVersionAttributes {
+ ServiceWorkerObjectInfo installing;
+ ServiceWorkerObjectInfo waiting;
+ ServiceWorkerObjectInfo active;
+};
+
+class ChangedVersionAttributesMask {
+ public:
+ enum {
+ INSTALLING_VERSION = 1 << 0,
+ WAITING_VERSION = 1 << 1,
+ ACTIVE_VERSION = 1 << 2,
+ CONTROLLING_VERSION = 1 << 3,
+ };
+
+ ChangedVersionAttributesMask() : changed_(0) {}
+ explicit ChangedVersionAttributesMask(int changed) : changed_(changed) {}
+
+ int changed() const { return changed_; }
+
+ void add(int changed_versions) { changed_ |= changed_versions; }
+ bool installing_changed() const { return !!(changed_ & INSTALLING_VERSION); }
+ bool waiting_changed() const { return !!(changed_ & WAITING_VERSION); }
+ bool active_changed() const { return !!(changed_ & ACTIVE_VERSION); }
+ bool controller_changed() const { return !!(changed_ & CONTROLLING_VERSION); }
+
+ private:
+ int changed_;
};
} // namespace content
diff --git a/chromium/content/common/set_process_title.cc b/chromium/content/common/set_process_title.cc
index 99eb243bba1..fdbf06cd0d8 100644
--- a/chromium/content/common/set_process_title.cc
+++ b/chromium/content/common/set_process_title.cc
@@ -19,8 +19,8 @@
#if defined(OS_LINUX)
#include <sys/prctl.h>
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/process/process_metrics.h"
#include "base/strings/string_util.h"
#include "base/threading/platform_thread.h"
diff --git a/chromium/content/common/shareable_file_reference_unittest.cc b/chromium/content/common/shareable_file_reference_unittest.cc
index ca6218a8d1d..5e697b9eb24 100644
--- a/chromium/content/common/shareable_file_reference_unittest.cc
+++ b/chromium/content/common/shareable_file_reference_unittest.cc
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "webkit/common/blob/shareable_file_reference.h"
+#include "storage/common/blob/shareable_file_reference.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
-using webkit_blob::ShareableFileReference;
+using storage::ShareableFileReference;
namespace content {
diff --git a/chromium/content/common/socket_stream.h b/chromium/content/common/socket_stream.h
deleted file mode 100644
index 3bce134558f..00000000000
--- a/chromium/content/common/socket_stream.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_COMMON_SOCKET_STREAM_H_
-#define CONTENT_COMMON_SOCKET_STREAM_H_
-
-namespace content {
-
-const int kNoSocketId = 0;
-
-} // namespace content
-
-#endif // CONTENT_COMMON_SOCKET_STREAM_H_
diff --git a/chromium/content/common/socket_stream_handle_data.h b/chromium/content/common/socket_stream_handle_data.h
deleted file mode 100644
index 3ce79ca47b0..00000000000
--- a/chromium/content/common/socket_stream_handle_data.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_SOCKET_STREAM_HANDLE_DATA_H_
-#define CONTENT_RENDERER_SOCKET_STREAM_HANDLE_DATA_H_
-
-#include "base/supports_user_data.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// User data stored in each WebSocketStreamHandleImpl.
-class SocketStreamHandleData : public base::SupportsUserData::Data {
- public:
- explicit SocketStreamHandleData(int render_frame_id)
- : render_frame_id_(render_frame_id) {}
- virtual ~SocketStreamHandleData() {}
-
- int render_frame_id() const { return render_frame_id_; }
-
- private:
- int render_frame_id_;
-
- DISALLOW_COPY_AND_ASSIGN(SocketStreamHandleData);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SOCKET_STREAM_HANDLE_DATA_H_
diff --git a/chromium/content/common/socket_stream_messages.h b/chromium/content/common/socket_stream_messages.h
deleted file mode 100644
index 6e24a157850..00000000000
--- a/chromium/content/common/socket_stream_messages.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Multiply-included message file, hence no include guard.
-#include <vector>
-
-#include "content/common/content_export.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_param_traits.h"
-#include "url/gurl.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START SocketStreamMsgStart
-
-// Web Sockets messages sent from the renderer to the browser.
-
-// Open new Socket Stream for the |socket_url| identified by |socket_id|
-// in the renderer process.
-// The browser starts connecting asynchronously.
-// Once Socket Stream connection is established, the browser will send
-// SocketStreamMsg_Connected back.
-// |render_frame_id| must be the routing id of RenderFrameImpl to which the
-// Socket Stream belongs.
-IPC_MESSAGE_CONTROL3(SocketStreamHostMsg_Connect,
- int /* render_frame_id */,
- GURL /* socket_url */,
- int /* socket_id */)
-
-// Request to send data on the Socket Stream.
-// SocketStreamHandle can send data at most |max_pending_send_allowed| bytes,
-// which is given by ViewMsg_SocketStream_Connected at any time.
-// The number of pending bytes can be tracked by size of |data| sent
-// and |amount_sent| parameter of ViewMsg_SocketStream_DataSent.
-// That is, the following constraints is applied:
-// (accumulated total of |data|) - (accumulated total of |amount_sent|)
-// <= |max_pending_send_allowed|
-// If the SocketStreamHandle ever tries to exceed the
-// |max_pending_send_allowed|, the connection will be closed.
-IPC_MESSAGE_CONTROL2(SocketStreamHostMsg_SendData,
- int /* socket_id */,
- std::vector<char> /* data */)
-
-// Request to close the Socket Stream.
-// The browser will send ViewMsg_SocketStream_Closed back when the Socket
-// Stream is completely closed.
-IPC_MESSAGE_CONTROL1(SocketStreamHostMsg_Close,
- int /* socket_id */)
-
-
-// Speech input messages sent from the browser to the renderer.
-
-// A |socket_id| is assigned by SocketStreamHostMsg_Connect.
-// The Socket Stream is connected. The SocketStreamHandle should keep track
-// of how much it has pending (how much it has requested to be sent) and
-// shouldn't go over |max_pending_send_allowed| bytes.
-IPC_MESSAGE_CONTROL2(SocketStreamMsg_Connected,
- int /* socket_id */,
- int /* max_pending_send_allowed */)
-
-// |data| is received on the Socket Stream.
-IPC_MESSAGE_CONTROL2(SocketStreamMsg_ReceivedData,
- int /* socket_id */,
- std::vector<char> /* data */)
-
-// |amount_sent| bytes of data requested by
-// SocketStreamHostMsg_SendData has been sent on the Socket Stream.
-IPC_MESSAGE_CONTROL2(SocketStreamMsg_SentData,
- int /* socket_id */,
- int /* amount_sent */)
-
-// The Socket Stream is closed.
-IPC_MESSAGE_CONTROL1(SocketStreamMsg_Closed,
- int /* socket_id */)
-
-// The Socket Stream is failed.
-IPC_MESSAGE_CONTROL2(SocketStreamMsg_Failed,
- int /* socket_id */,
- int /* error_code */)
diff --git a/chromium/content/common/speech_recognition_messages.h b/chromium/content/common/speech_recognition_messages.h
index 5e4fcf56db4..80eb7f74d2d 100644
--- a/chromium/content/common/speech_recognition_messages.h
+++ b/chromium/content/common/speech_recognition_messages.h
@@ -6,11 +6,14 @@
#include <string>
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
#include "content/public/common/speech_recognition_error.h"
#include "content/public/common/speech_recognition_grammar.h"
#include "content/public/common/speech_recognition_result.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
+#include "media/audio/audio_parameters.h"
#include "ui/gfx/rect.h"
#define IPC_MESSAGE_START SpeechRecognitionMsgStart
@@ -62,6 +65,8 @@ IPC_STRUCT_BEGIN(SpeechRecognitionHostMsg_StartRequest_Params)
IPC_STRUCT_MEMBER(bool, continuous)
// Whether the user requested interim results or not.
IPC_STRUCT_MEMBER(bool, interim_results)
+ // Wheter the user has set an audio track as input or not.
+ IPC_STRUCT_MEMBER(bool, using_audio_track)
IPC_STRUCT_END()
@@ -114,3 +119,9 @@ IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_SoundEnded, int /* request_id */)
IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_AudioEnded, int /* request_id */)
IPC_MESSAGE_ROUTED1(SpeechRecognitionMsg_Ended, int /* request_id */)
+
+IPC_MESSAGE_ROUTED4(SpeechRecognitionMsg_AudioReceiverReady,
+ int /* request_id */,
+ media::AudioParameters /* params */,
+ base::SharedMemoryHandle /* memory */,
+ base::SyncSocket::TransitDescriptor /* socket */)
diff --git a/chromium/content/common/ssl_status_serialization.cc b/chromium/content/common/ssl_status_serialization.cc
index 5543c35d4e3..d10b1b8a7e4 100644
--- a/chromium/content/common/ssl_status_serialization.cc
+++ b/chromium/content/common/ssl_status_serialization.cc
@@ -53,29 +53,27 @@ bool DeserializeSecurityInfo(
Pickle pickle(state.data(), static_cast<int>(state.size()));
PickleIterator iter(pickle);
- bool pickle_read_ok = pickle.ReadInt(&iter, cert_id) &&
- pickle.ReadUInt32(&iter, cert_status) &&
- pickle.ReadInt(&iter, security_bits) &&
- pickle.ReadInt(&iter, ssl_connection_status);
- if (!pickle_read_ok)
- return pickle_read_ok;
-
int num_scts_to_read;
- pickle_read_ok = pickle.ReadInt(&iter, &num_scts_to_read);
- int id;
- uint16 status;
- for (; pickle_read_ok && num_scts_to_read > 0; --num_scts_to_read) {
- pickle_read_ok = pickle.ReadInt(&iter, &id) &&
- pickle.ReadUInt16(&iter, &status);
- if (pickle_read_ok) {
- signed_certificate_timestamp_ids->push_back(
- SignedCertificateTimestampIDAndStatus(
- id,
- static_cast<net::ct::SCTVerifyStatus>(status)));
- }
+ if (!pickle.ReadInt(&iter, cert_id) ||
+ !pickle.ReadUInt32(&iter, cert_status) ||
+ !pickle.ReadInt(&iter, security_bits) ||
+ !pickle.ReadInt(&iter, ssl_connection_status) ||
+ !pickle.ReadInt(&iter, &num_scts_to_read))
+ return false;
+
+ for (; num_scts_to_read > 0; --num_scts_to_read) {
+ int id;
+ uint16 status;
+ if (!pickle.ReadInt(&iter, &id) ||
+ !pickle.ReadUInt16(&iter, &status))
+ return false;
+ signed_certificate_timestamp_ids->push_back(
+ SignedCertificateTimestampIDAndStatus(
+ id,
+ static_cast<net::ct::SCTVerifyStatus>(status)));
}
- return pickle_read_ok;
+ return true;
}
} // namespace content
diff --git a/chromium/content/common/swapped_out_messages.cc b/chromium/content/common/swapped_out_messages.cc
index 72bf66b5055..6c872d43f1a 100644
--- a/chromium/content/common/swapped_out_messages.cc
+++ b/chromium/content/common/swapped_out_messages.cc
@@ -40,11 +40,13 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
case FrameHostMsg_Detach::ID:
case FrameHostMsg_DomOperationResponse::ID:
case FrameHostMsg_CompositorFrameSwappedACK::ID:
- case FrameHostMsg_BuffersSwappedACK::ID:
case FrameHostMsg_ReclaimCompositorResources::ID:
// Input events propagate from parent to child.
case FrameHostMsg_ForwardInputEvent::ID:
case FrameHostMsg_InitializeChildFrame::ID:
+ // The browser should always have an accurate mirror of the renderer's
+ // notion of the current page id.
+ case FrameHostMsg_DidAssignPageId::ID:
return true;
default:
break;
diff --git a/chromium/content/common/user_agent.cc b/chromium/content/common/user_agent.cc
index 2255badd0b4..1176c488d3d 100644
--- a/chromium/content/common/user_agent.cc
+++ b/chromium/content/common/user_agent.cc
@@ -162,7 +162,7 @@ std::string BuildUserAgentFromProduct(const std::string& product) {
"";
#elif defined(OS_MACOSX)
"Macintosh; ";
-#elif defined(USE_X11)
+#elif defined(USE_X11) || defined(USE_OZONE)
"X11; "; // strange, but that's what Firefox uses
#elif defined(OS_ANDROID)
"Linux; ";
diff --git a/chromium/content/common/user_agent_ios.mm b/chromium/content/common/user_agent_ios.mm
deleted file mode 100644
index ca897c171b5..00000000000
--- a/chromium/content/common/user_agent_ios.mm
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2014 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 "content/public/common/user_agent.h"
-
-#import <UIKit/UIKit.h>
-
-#include <sys/sysctl.h>
-#include <string>
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/sys_info.h"
-
-namespace {
-
-struct UAVersions {
- const char* safari_version_string;
- const char* webkit_version_string;
-};
-
-struct OSVersionMap {
- int32 major_os_version;
- int32 minor_os_version;
- UAVersions ua_versions;
-};
-
-const UAVersions& GetUAVersionsForCurrentOS() {
- // The WebKit version can be extracted dynamically from UIWebView, but the
- // Safari version can't be, so a lookup table is used instead (for both, since
- // the reported versions should stay in sync).
- static const OSVersionMap version_map[] = {
- { 7, 1, { "9537.53", "537.51.2" } },
- { 7, 0, { "9537.53", "537.51.1" } },
- // 6.1 has the same values as 6.0.
- { 6, 0, { "8536.25", "536.26" } },
- };
-
- int32 os_major_version = 0;
- int32 os_minor_version = 0;
- int32 os_bugfix_version = 0;
- base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
- &os_minor_version,
- &os_bugfix_version);
-
- // Return the versions corresponding to the first (and thus highest) OS
- // version less than or equal to the given OS version.
- for (unsigned int i = 0; i < arraysize(version_map); ++i) {
- if (os_major_version > version_map[i].major_os_version ||
- (os_major_version == version_map[i].major_os_version &&
- os_minor_version >= version_map[i].minor_os_version))
- return version_map[i].ua_versions;
- }
- NOTREACHED();
- return version_map[arraysize(version_map) - 1].ua_versions;
-}
-
-} // namespace
-
-namespace content {
-
-std::string BuildOSCpuInfo() {
- int32 os_major_version = 0;
- int32 os_minor_version = 0;
- int32 os_bugfix_version = 0;
- base::SysInfo::OperatingSystemVersionNumbers(&os_major_version,
- &os_minor_version,
- &os_bugfix_version);
- std::string os_version;
- if (os_bugfix_version == 0) {
- base::StringAppendF(&os_version,
- "%d_%d",
- os_major_version,
- os_minor_version);
- } else {
- base::StringAppendF(&os_version,
- "%d_%d_%d",
- os_major_version,
- os_minor_version,
- os_bugfix_version);
- }
-
- // Remove the end of the platform name. For example "iPod touch" becomes
- // "iPod".
- std::string platform = base::SysNSStringToUTF8(
- [[UIDevice currentDevice] model]);
- size_t position = platform.find_first_of(" ");
- if (position != std::string::npos)
- platform = platform.substr(0, position);
-
- std::string os_cpu;
- base::StringAppendF(
- &os_cpu,
- "%s; CPU %s %s like Mac OS X",
- platform.c_str(),
- (platform == "iPad") ? "OS" : "iPhone OS",
- os_version.c_str());
-
- return os_cpu;
-}
-
-std::string BuildUserAgentFromProduct(const std::string& product) {
- // Retrieve the kernel build number.
- int mib[2] = {CTL_KERN, KERN_OSVERSION};
- unsigned int namelen = sizeof(mib) / sizeof(mib[0]);
- size_t bufferSize = 0;
- sysctl(mib, namelen, NULL, &bufferSize, NULL, 0);
- char kernel_version[bufferSize];
- int result = sysctl(mib, namelen, kernel_version, &bufferSize, NULL, 0);
- DCHECK(result == 0);
-
- UAVersions ua_versions = GetUAVersionsForCurrentOS();
-
- std::string user_agent;
- base::StringAppendF(&user_agent,
- "Mozilla/5.0 (%s) AppleWebKit/%s"
- " (KHTML, like Gecko) %s Mobile/%s Safari/%s",
- BuildOSCpuInfo().c_str(),
- ua_versions.webkit_version_string,
- product.c_str(),
- kernel_version,
- ua_versions.safari_version_string);
-
- return user_agent;
-}
-
-} // namespace content
diff --git a/chromium/content/common/utility_messages.h b/chromium/content/common/utility_messages.h
index 1e5c68bfea3..c12032b6d93 100644
--- a/chromium/content/common/utility_messages.h
+++ b/chromium/content/common/utility_messages.h
@@ -27,7 +27,7 @@ IPC_MESSAGE_CONTROL0(UtilityMsg_BatchMode_Started)
// Tells the utility process that it can shutdown.
IPC_MESSAGE_CONTROL0(UtilityMsg_BatchMode_Finished)
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
// Tells the utility process to load each plugin in the order specified by the
// vector. It will respond after each load with the WebPluginInfo.
IPC_MESSAGE_CONTROL1(UtilityMsg_LoadPlugins,
@@ -38,7 +38,7 @@ IPC_MESSAGE_CONTROL1(UtilityMsg_LoadPlugins,
// Utility process host messages:
// These are messages from the utility process to the browser.
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
// Notifies the browser when a plugin failed to load so the two processes can
// keep the canonical list in sync.
IPC_SYNC_MESSAGE_CONTROL2_0(UtilityHostMsg_LoadPluginFailed,
@@ -49,4 +49,4 @@ IPC_SYNC_MESSAGE_CONTROL2_0(UtilityHostMsg_LoadPluginFailed,
IPC_SYNC_MESSAGE_CONTROL2_0(UtilityHostMsg_LoadedPlugin,
uint32_t /* index in the vector */,
content::WebPluginInfo /* plugin info */)
-#endif // OS_POSIX
+#endif
diff --git a/chromium/content/common/view_message_enums.h b/chromium/content/common/view_message_enums.h
index 37179e82631..4d3d193ebcf 100644
--- a/chromium/content/common/view_message_enums.h
+++ b/chromium/content/common/view_message_enums.h
@@ -22,34 +22,4 @@ struct ViewHostMsg_UpdateRect_Flags {
}
};
-// Note: keep enums in content/browser/resources/accessibility/accessibility.js
-// in sync with these two enums.
-enum AccessibilityModeFlag {
- // Accessibility updates are processed to create platform trees and events are
- // passed to platform APIs in the browser.
- AccessibilityModeFlagPlatform = 1 << 0,
-
- // Accessibility is on, and the full tree is computed. If this flag is off,
- // only limited information about editable text nodes is sent to the browser
- // process. Useful for implementing limited UIA on tablets.
- AccessibilityModeFlagFullTree = 1 << 1,
-};
-
-enum AccessibilityMode {
- // All accessibility is off.
- AccessibilityModeOff = 0,
-
- // Renderer accessibility is on, platform APIs are called, but only limited
- // information is available (see AccessibilityModeFlagEditableTextOnly).
- AccessibilityModeEditableTextOnly = AccessibilityModeFlagPlatform,
-
- // Renderer accessibility is on, and platform APIs are called.
- AccessibilityModeComplete =
- AccessibilityModeFlagPlatform | AccessibilityModeFlagFullTree,
-
- // Renderer accessibility is on, and events are passed to any extensions
- // requesting automation, but not to platform accessibility.
- AccessibilityModeTreeOnly = AccessibilityModeFlagFullTree,
-};
-
#endif // CONTENT_COMMON_VIEW_MESSAGES_ENUMS_H_
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index 3815910e727..426ac1faa12 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -14,12 +14,13 @@
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/cookie_data.h"
+#include "content/common/date_time_suggestion.h"
#include "content/common/navigation_gesture.h"
-#include "content/common/pepper_renderer_instance_data.h"
#include "content/common/view_message_enums.h"
#include "content/common/webplugin_geometry.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/favicon_url.h"
+#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/common/menu_item.h"
#include "content/public/common/page_state.h"
@@ -29,7 +30,6 @@
#include "content/public/common/stop_find_action.h"
#include "content/public/common/three_d_api_types.h"
#include "content/public/common/window_container_type.h"
-#include "content/common/date_time_suggestion.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
@@ -49,43 +49,56 @@
#include "ui/base/ime/text_input_mode.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_types.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
#include "ui/gfx/point.h"
#include "ui/gfx/range/range.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_f.h"
#include "ui/gfx/vector2d.h"
#include "ui/gfx/vector2d_f.h"
-#include "ui/shell_dialogs/selected_file_info.h"
#if defined(OS_MACOSX)
#include "content/common/mac/font_descriptor.h"
#include "third_party/WebKit/public/web/mac/WebScrollbarTheme.h"
#endif
+#if defined(ENABLE_PLUGINS)
+#include "content/common/pepper_renderer_instance_data.h"
+#endif
+
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START ViewMsgStart
-IPC_ENUM_TRAITS(AccessibilityMode)
-IPC_ENUM_TRAITS(blink::WebMediaPlayerAction::Type)
-IPC_ENUM_TRAITS(blink::WebPluginAction::Type)
-IPC_ENUM_TRAITS(blink::WebPopupType)
-IPC_ENUM_TRAITS(blink::WebTextDirection)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebMediaPlayerAction::Type,
+ blink::WebMediaPlayerAction::Type::TypeLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebPluginAction::Type,
+ blink::WebPluginAction::Type::TypeLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebPopupType,
+ blink::WebPopupType::WebPopupTypeLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebTextDirection,
+ blink::WebTextDirection::WebTextDirectionLast)
IPC_ENUM_TRAITS(WindowContainerType)
IPC_ENUM_TRAITS(content::FaviconURL::IconType)
IPC_ENUM_TRAITS(content::FileChooserParams::Mode)
IPC_ENUM_TRAITS(content::MenuItem::Type)
-IPC_ENUM_TRAITS(content::NavigationGesture)
-IPC_ENUM_TRAITS(content::PageZoom)
-IPC_ENUM_TRAITS(content::RendererPreferencesHintingEnum)
-IPC_ENUM_TRAITS(content::RendererPreferencesSubpixelRenderingEnum)
+IPC_ENUM_TRAITS_MAX_VALUE(content::NavigationGesture,
+ content::NavigationGestureLast)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::PageZoom,
+ content::PageZoom::PAGE_ZOOM_OUT,
+ content::PageZoom::PAGE_ZOOM_IN)
+IPC_ENUM_TRAITS(gfx::FontRenderParams::Hinting)
+IPC_ENUM_TRAITS(gfx::FontRenderParams::SubpixelRendering)
IPC_ENUM_TRAITS_MAX_VALUE(content::TapMultipleTargetsStrategy,
content::TAP_MULTIPLE_TARGETS_STRATEGY_MAX)
-IPC_ENUM_TRAITS(content::StopFindAction)
-IPC_ENUM_TRAITS(content::ThreeDAPIType)
-IPC_ENUM_TRAITS(media::ChannelLayout)
-IPC_ENUM_TRAITS(media::MediaLogEvent::Type)
+IPC_ENUM_TRAITS_MAX_VALUE(content::StopFindAction,
+ content::STOP_FIND_ACTION_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::ThreeDAPIType,
+ content::THREE_D_API_TYPE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(media::ChannelLayout, media::CHANNEL_LAYOUT_MAX - 1)
+IPC_ENUM_TRAITS_MAX_VALUE(media::MediaLogEvent::Type,
+ media::MediaLogEvent::TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(ui::TextInputMode, ui::TEXT_INPUT_MODE_MAX)
IPC_ENUM_TRAITS(ui::TextInputType)
@@ -159,22 +172,34 @@ IPC_STRUCT_TRAITS_BEGIN(content::FaviconURL)
IPC_STRUCT_TRAITS_MEMBER(icon_sizes)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::FileChooserFileInfo)
+ IPC_STRUCT_TRAITS_MEMBER(file_path)
+ IPC_STRUCT_TRAITS_MEMBER(display_name)
+ IPC_STRUCT_TRAITS_MEMBER(file_system_url)
+ IPC_STRUCT_TRAITS_MEMBER(modification_time)
+ IPC_STRUCT_TRAITS_MEMBER(length)
+ IPC_STRUCT_TRAITS_MEMBER(is_directory)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::FileChooserParams)
IPC_STRUCT_TRAITS_MEMBER(mode)
IPC_STRUCT_TRAITS_MEMBER(title)
IPC_STRUCT_TRAITS_MEMBER(default_file_name)
IPC_STRUCT_TRAITS_MEMBER(accept_types)
+ IPC_STRUCT_TRAITS_MEMBER(need_local_path)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(capture)
#endif
IPC_STRUCT_TRAITS_END()
+#if defined(ENABLE_PLUGINS)
IPC_STRUCT_TRAITS_BEGIN(content::PepperRendererInstanceData)
IPC_STRUCT_TRAITS_MEMBER(render_process_id)
IPC_STRUCT_TRAITS_MEMBER(render_frame_id)
IPC_STRUCT_TRAITS_MEMBER(document_url)
IPC_STRUCT_TRAITS_MEMBER(plugin_url)
IPC_STRUCT_TRAITS_END()
+#endif
IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
IPC_STRUCT_TRAITS_MEMBER(can_accept_load_drops)
@@ -202,8 +227,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
IPC_STRUCT_TRAITS_MEMBER(user_agent_override)
IPC_STRUCT_TRAITS_MEMBER(accept_languages)
IPC_STRUCT_TRAITS_MEMBER(report_frame_name_changes)
- IPC_STRUCT_TRAITS_MEMBER(touchpad_fling_profile)
- IPC_STRUCT_TRAITS_MEMBER(touchscreen_fling_profile)
IPC_STRUCT_TRAITS_MEMBER(tap_multiple_targets_strategy)
IPC_STRUCT_TRAITS_MEMBER(disable_client_blocked_error_page)
IPC_STRUCT_TRAITS_MEMBER(plugin_fullscreen_allowed)
@@ -237,12 +260,6 @@ IPC_STRUCT_TRAITS_BEGIN(media::MediaLogEvent)
IPC_STRUCT_TRAITS_MEMBER(time)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(ui::SelectedFileInfo)
- IPC_STRUCT_TRAITS_MEMBER(file_path)
- IPC_STRUCT_TRAITS_MEMBER(local_path)
- IPC_STRUCT_TRAITS_MEMBER(display_name)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_BEGIN(ViewHostMsg_CreateWindow_Params)
// Routing ID of the view initiating the open.
IPC_STRUCT_MEMBER(int, opener_id)
@@ -333,38 +350,12 @@ IPC_STRUCT_BEGIN(ViewHostMsg_SelectionBounds_Params)
IPC_STRUCT_MEMBER(bool, is_anchor_first)
IPC_STRUCT_END()
-// This message is used for supporting popup menus on Mac OS X using native
-// Cocoa controls. The renderer sends us this message which we use to populate
-// the popup menu.
-IPC_STRUCT_BEGIN(ViewHostMsg_ShowPopup_Params)
- // Position on the screen.
- IPC_STRUCT_MEMBER(gfx::Rect, bounds)
-
- // The height of each item in the menu.
- IPC_STRUCT_MEMBER(int, item_height)
-
- // The size of the font to use for those items.
- IPC_STRUCT_MEMBER(double, item_font_size)
-
- // The currently selected (displayed) item in the menu.
- IPC_STRUCT_MEMBER(int, selected_item)
-
- // The entire list of items in the popup menu.
- IPC_STRUCT_MEMBER(std::vector<content::MenuItem>, popup_items)
-
- // Whether items should be right-aligned.
- IPC_STRUCT_MEMBER(bool, right_aligned)
-
- // Whether this is a multi-select popup.
- IPC_STRUCT_MEMBER(bool, allow_multiple_selection)
-IPC_STRUCT_END()
-
IPC_STRUCT_BEGIN(ViewHostMsg_TextInputState_Params)
// The type of input field
IPC_STRUCT_MEMBER(ui::TextInputType, type)
- // The mode of input field
- IPC_STRUCT_MEMBER(ui::TextInputMode, mode)
+ // The flags of the input field (autocorrect, autocomplete, etc.)
+ IPC_STRUCT_MEMBER(int, flags)
// The value of the input field
IPC_STRUCT_MEMBER(std::string, value)
@@ -396,9 +387,6 @@ IPC_STRUCT_BEGIN(ViewHostMsg_TextInputState_Params)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewHostMsg_UpdateRect_Params)
- // The scroll offset of the render view.
- IPC_STRUCT_MEMBER(gfx::Vector2d, scroll_offset)
-
// The size of the RenderView when this message was generated. This is
// included so the host knows how large the view is from the perspective of
// the renderer process. This is necessary in case a resize operation is in
@@ -423,10 +411,6 @@ IPC_STRUCT_BEGIN(ViewHostMsg_UpdateRect_Params)
// which would indicate that this paint message is an ACK for multiple
// request messages.
IPC_STRUCT_MEMBER(int, flags)
-
- // All the above coordinates are in DIP. This is the scale factor needed
- // to convert them to pixels.
- IPC_STRUCT_MEMBER(float, scale_factor)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewMsg_New_Params)
@@ -434,7 +418,7 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
IPC_STRUCT_MEMBER(content::RendererPreferences, renderer_preferences)
// Preferences for this view.
- IPC_STRUCT_MEMBER(WebPreferences, web_preferences)
+ IPC_STRUCT_MEMBER(content::WebPreferences, web_preferences)
// The ID of the view to be created.
IPC_STRUCT_MEMBER(int32, view_id)
@@ -478,15 +462,15 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
// The properties of the screen associated with the view.
IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
-
- // The accessibility mode of the renderer.
- IPC_STRUCT_MEMBER(AccessibilityMode, accessibility_mode)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewMsg_PostMessage_Params)
+ // Whether the data format is supplied as serialized script value, or as
+ // a simple string. If it is a raw string, must be converted from string to a
+ // WebSerializedScriptValue in renderer.
+ IPC_STRUCT_MEMBER(bool, is_data_raw_string)
// The serialized script value.
IPC_STRUCT_MEMBER(base::string16, data)
-
// When sent to the browser, this is the routing ID of the source frame in
// the source process. The browser replaces it with the routing ID of the
// equivalent (swapped out) frame in the destination process.
@@ -505,9 +489,16 @@ IPC_STRUCT_END()
// Messages sent from the browser to the renderer.
+#if defined(OS_ANDROID)
// Tells the renderer to cancel an opened date/time dialog.
IPC_MESSAGE_ROUTED0(ViewMsg_CancelDateTimeDialog)
+// Replaces a date time input field.
+IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceDateTime,
+ double /* dialog_value */)
+
+#endif
+
// Get all savable resource links from current webpage, include main
// frame and sub-frame.
IPC_MESSAGE_ROUTED1(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
@@ -564,7 +555,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetRendererPrefs,
// This passes a set of webkit preferences down to the renderer.
IPC_MESSAGE_ROUTED1(ViewMsg_UpdateWebPreferences,
- WebPreferences)
+ content::WebPreferences)
// Informs the renderer that the timezone has changed.
IPC_MESSAGE_CONTROL0(ViewMsg_TimezoneChange)
@@ -577,7 +568,7 @@ IPC_STRUCT_BEGIN(ViewMsg_Resize_Params)
IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
IPC_STRUCT_MEMBER(gfx::Size, new_size)
IPC_STRUCT_MEMBER(gfx::Size, physical_backing_size)
- IPC_STRUCT_MEMBER(float, overdraw_bottom_height)
+ IPC_STRUCT_MEMBER(float, top_controls_layout_height)
IPC_STRUCT_MEMBER(gfx::Size, visible_viewport_size)
IPC_STRUCT_MEMBER(gfx::Rect, resizer_rect)
IPC_STRUCT_MEMBER(bool, is_fullscreen)
@@ -591,6 +582,11 @@ IPC_STRUCT_END()
IPC_MESSAGE_ROUTED1(ViewMsg_Resize,
ViewMsg_Resize_Params /* params */)
+// Sent to inform the renderer of its screen device color profile. An empty
+// profile tells the renderer use the default sRGB color profile.
+IPC_MESSAGE_ROUTED1(ViewMsg_ColorProfile,
+ std::vector<char> /* color profile */)
+
// Tells the render view that the resize rect has changed.
IPC_MESSAGE_ROUTED1(ViewMsg_ChangeResizeRect,
gfx::Rect /* resizer_rect */)
@@ -603,12 +599,9 @@ IPC_MESSAGE_ROUTED0(ViewMsg_WasHidden)
// render view is expected to respond with a full repaint if needs_repainting
// is true. If needs_repainting is false, then this message does not trigger a
// message in response.
-IPC_MESSAGE_ROUTED1(ViewMsg_WasShown,
- bool /* needs_repainting */)
-
-// Sent to inform the view that it was swapped out. This allows the process to
-// exit if no other views are using it.
-IPC_MESSAGE_ROUTED0(ViewMsg_WasSwappedOut)
+IPC_MESSAGE_ROUTED2(ViewMsg_WasShown,
+ bool /* needs_repainting */,
+ ui::LatencyInfo /* latency_info */)
// Tells the renderer to focus the first (last if reverse is true) focusable
// node.
@@ -617,11 +610,10 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetInitialFocus,
// Sent to inform the renderer to invoke a context menu.
// The parameter specifies the location in the render view's coordinates.
-IPC_MESSAGE_ROUTED1(ViewMsg_ShowContextMenu,
+IPC_MESSAGE_ROUTED2(ViewMsg_ShowContextMenu,
+ ui::MenuSourceType,
gfx::Point /* location where menu should be shown */)
-IPC_MESSAGE_ROUTED0(ViewMsg_Stop)
-
// Sent when the user wants to search for a word on the page (find in page).
IPC_MESSAGE_ROUTED3(ViewMsg_Find,
int /* request_id */,
@@ -633,10 +625,6 @@ IPC_MESSAGE_ROUTED3(ViewMsg_Find,
IPC_MESSAGE_ROUTED1(ViewMsg_StopFinding,
content::StopFindAction /* action */)
-// Replaces a date time input field.
-IPC_MESSAGE_ROUTED1(ViewMsg_ReplaceDateTime,
- double /* dialog_value */)
-
// Copies the image at location x, y to the clipboard (if there indeed is an
// image at that location).
IPC_MESSAGE_ROUTED2(ViewMsg_CopyImageAt,
@@ -665,9 +653,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_PluginActionAt,
IPC_MESSAGE_ROUTED1(ViewMsg_PostMessageEvent,
ViewMsg_PostMessage_Params)
-// Requests that the RenderView's main frame sets its opener to null.
-IPC_MESSAGE_ROUTED0(ViewMsg_DisownOpener)
-
// Change the zoom level for the current main frame. If the level actually
// changes, a ViewHostMsg_DidZoomURL message will be sent back to the browser
// telling it what url got zoomed and what its current zoom level is.
@@ -732,26 +717,12 @@ IPC_MESSAGE_ROUTED0(ViewMsg_CandidateWindowShown)
IPC_MESSAGE_ROUTED0(ViewMsg_CandidateWindowUpdated)
IPC_MESSAGE_ROUTED0(ViewMsg_CandidateWindowHidden)
-// This message sends a string being composed with an input method.
-IPC_MESSAGE_ROUTED4(
- ViewMsg_ImeSetComposition,
- base::string16, /* text */
- std::vector<blink::WebCompositionUnderline>, /* underlines */
- int, /* selectiont_start */
- int /* selection_end */)
-
-// This message confirms an ongoing composition.
-IPC_MESSAGE_ROUTED3(ViewMsg_ImeConfirmComposition,
- base::string16 /* text */,
- gfx::Range /* replacement_range */,
- bool /* keep_selection */)
-
// Used to notify the render-view that we have received a target URL. Used
// to prevent target URLs spamming the browser.
IPC_MESSAGE_ROUTED0(ViewMsg_UpdateTargetURL_ACK)
IPC_MESSAGE_ROUTED1(ViewMsg_RunFileChooserResponse,
- std::vector<ui::SelectedFileInfo>)
+ std::vector<content::FileChooserFileInfo>)
// Provides the results of directory enumeration.
IPC_MESSAGE_ROUTED2(ViewMsg_EnumerateDirectoryResponse,
@@ -850,6 +821,7 @@ IPC_MESSAGE_ROUTED0(ViewMsg_WorkerConnected)
IPC_MESSAGE_CONTROL1(ViewMsg_NetworkTypeChanged,
net::NetworkChangeNotifier::ConnectionType /* type */)
+#if defined(ENABLE_PLUGINS)
// Reply to ViewHostMsg_OpenChannelToPpapiBroker
// Tells the renderer that the channel to the broker has been created.
IPC_MESSAGE_ROUTED2(ViewMsg_PpapiBrokerChannelCreated,
@@ -866,6 +838,7 @@ IPC_MESSAGE_ROUTED1(ViewMsg_PpapiBrokerPermissionResult,
// pages containing plugins.
IPC_MESSAGE_CONTROL1(ViewMsg_PurgePluginListCache,
bool /* reload_pages */)
+#endif
// Used to instruct the RenderView to go into "view source" mode.
IPC_MESSAGE_ROUTED0(ViewMsg_EnableViewSourceMode)
@@ -879,10 +852,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_SavePageAsMHTML,
IPC_MESSAGE_CONTROL1(ViewMsg_TempCrashWithData,
GURL /* data */)
-// Change the accessibility mode in the renderer process.
-IPC_MESSAGE_ROUTED1(ViewMsg_SetAccessibilityMode,
- AccessibilityMode)
-
// An acknowledge to ViewHostMsg_MultipleTargetsTouched to notify the renderer
// process to release the magnified image.
IPC_MESSAGE_ROUTED1(ViewMsg_ReleaseDisambiguationPopupBitmap,
@@ -894,8 +863,11 @@ IPC_MESSAGE_ROUTED3(ViewMsg_WindowSnapshotCompleted,
gfx::Size /* size */,
std::vector<unsigned char> /* png */)
+// Fetches complete rendered content of a web page as plain text.
+IPC_MESSAGE_ROUTED0(ViewMsg_GetRenderedText)
+
#if defined(OS_MACOSX)
-IPC_ENUM_TRAITS_MAX_VALUE(blink::ScrollerStyle, blink::ScrollerStyleOverlay);
+IPC_ENUM_TRAITS_MAX_VALUE(blink::ScrollerStyle, blink::ScrollerStyleOverlay)
// Notification of a change in scrollbar appearance and/or behavior.
IPC_MESSAGE_CONTROL5(ViewMsg_UpdateScrollbarTheme,
@@ -924,11 +896,6 @@ IPC_MESSAGE_CONTROL1(ViewMsg_SetWebKitSharedTimersSuspended,
IPC_MESSAGE_ROUTED1(ViewMsg_FindMatchRects,
int /* current_version */)
-// External popup menus.
-IPC_MESSAGE_ROUTED2(ViewMsg_SelectPopupMenuItems,
- bool /* user canceled the popup */,
- std::vector<int> /* selected indices */)
-
// Notifies the renderer whether hiding/showing the top controls is enabled
// and whether or not to animate to the proper state.
IPC_MESSAGE_ROUTED3(ViewMsg_UpdateTopControlsState,
@@ -970,10 +937,6 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetInLiveResize,
IPC_MESSAGE_ROUTED2(ViewMsg_PluginImeCompositionCompleted,
base::string16 /* text */,
int /* plugin_id */)
-
-// External popup menus.
-IPC_MESSAGE_ROUTED1(ViewMsg_SelectPopupMenuItem,
- int /* selected index, -1 means no selection */)
#endif
// Sent by the browser as a reply to ViewHostMsg_SwapCompositorFrame.
@@ -989,6 +952,12 @@ IPC_MESSAGE_ROUTED2(ViewMsg_ReclaimCompositorResources,
IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret)
+// Sent by the browser to ask the renderer to redraw.
+// If |request_id| is not zero, it is added to the forced frame's latency info
+// as ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT.
+IPC_MESSAGE_ROUTED1(ViewMsg_ForceRedraw,
+ int /* request_id */)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
@@ -1027,10 +996,6 @@ IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_GetAudioHardwareConfig,
media::AudioParameters /* input parameters */,
media::AudioParameters /* output parameters */)
-// Asks the browser for CPU usage of the renderer process in percents.
-IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetCPUUsage,
- int /* CPU usage in percents */)
-
// Asks the browser for the renderer process memory size stats.
IPC_SYNC_MESSAGE_CONTROL0_2(ViewHostMsg_GetProcessMemorySizes,
size_t /* private_bytes */,
@@ -1089,13 +1054,6 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_UpdateScreenRects_ACK)
IPC_MESSAGE_ROUTED1(ViewHostMsg_RequestMove,
gfx::Rect /* position */)
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
-// Message to show/hide a popup menu using native controls.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup,
- ViewHostMsg_ShowPopup_Params)
-IPC_MESSAGE_ROUTED0(ViewHostMsg_HidePopup)
-#endif
-
// Result of string search in the page.
// Response to ViewMsg_Find with the results of the requested find-in-page
// search, the number of matches found and the selection rect (in screen
@@ -1112,7 +1070,7 @@ IPC_MESSAGE_ROUTED5(ViewHostMsg_Find_Reply,
// Indicates that the render view has been closed in respose to a
// Close message.
IPC_MESSAGE_CONTROL1(ViewHostMsg_Close_ACK,
- int /* old_route_id */);
+ int /* old_route_id */)
// Indicates that the current page has been closed, after a ClosePage
// message.
@@ -1126,8 +1084,7 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateState,
// Notifies the browser that we want to show a destination url for a potential
// action (e.g. when the user is hovering over a link).
-IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateTargetURL,
- int32,
+IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateTargetURL,
GURL)
// Sent when the document element is available for the top-level frame. This
@@ -1145,7 +1102,7 @@ IPC_MESSAGE_ROUTED5(ViewHostMsg_DidLoadResourceFromMemoryCache,
std::string /* security info */,
std::string /* http method */,
std::string /* mime type */,
- ResourceType::Type /* resource type */)
+ content::ResourceType /* resource type */)
// Sent when the renderer displays insecure content in a secure page.
IPC_MESSAGE_ROUTED0(ViewHostMsg_DidDisplayInsecureContent)
@@ -1171,12 +1128,6 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_FocusedNodeChanged,
IPC_MESSAGE_ROUTED1(ViewHostMsg_SetCursor, content::WebCursor)
-// Message sent from renderer requesting touch emulation using mouse.
-// Shift-scrolling should be converted to pinch, if |allow_pinch| is true.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_SetTouchEventEmulationEnabled,
- bool /* enabled */,
- bool /* allow_pinch */)
-
// Used to set a cookie. The cookie is set asynchronously, but will be
// available to a subsequent ViewHostMsg_GetCookies request.
IPC_MESSAGE_CONTROL4(ViewHostMsg_SetCookie,
@@ -1264,12 +1215,11 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_AppCacheAccessed,
bool /* blocked by policy */)
// Initiates a download based on user actions like 'ALT+click'.
-IPC_MESSAGE_CONTROL5(ViewHostMsg_DownloadUrl,
+IPC_MESSAGE_CONTROL4(ViewHostMsg_DownloadUrl,
int /* render_view_id */,
GURL /* url */,
content::Referrer /* referrer */,
- base::string16 /* suggested_name */,
- bool /* use prompt for save location */)
+ base::string16 /* suggested_name */)
// Used to go to the session history entry at the given offset (ie, -1 will
// return the "back" item).
@@ -1289,12 +1239,6 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_RouteMessageEvent,
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredSizeChange,
gfx::Size /* pref_size */)
-// Notifies that the scroll offset changed.
-// This is different from ViewHostMsg_UpdateRect in that ViewHostMsg_UpdateRect
-// is not sent at all when threaded compositing is enabled while
-// ViewHostMsg_DidChangeScrollOffset works properly in this case.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_DidChangeScrollOffset)
-
// Notifies whether there are JavaScript touch event handlers or not.
IPC_MESSAGE_ROUTED1(ViewHostMsg_HasTouchEventHandlers,
bool /* has_handlers */)
@@ -1306,6 +1250,7 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_WebUISend,
std::string /* message */,
base::ListValue /* args */)
+#if defined(ENABLE_PLUGINS)
// A renderer sends this to the browser process when it wants to create a ppapi
// plugin. The browser will create the plugin process if necessary, and will
// return a handle to the channel on success.
@@ -1378,15 +1323,13 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_RequestPpapiBrokerPermission,
int /* routing_id */,
GURL /* document_url */,
base::FilePath /* plugin_path */)
+#endif // defined(ENABLE_PLUGINS)
// Send the tooltip text for the current mouse position to the browser.
IPC_MESSAGE_ROUTED2(ViewHostMsg_SetTooltipText,
base::string16 /* tooltip text string */,
blink::WebTextDirection /* text direction hint */)
-IPC_MESSAGE_ROUTED0(ViewHostMsg_SelectRange_ACK)
-IPC_MESSAGE_ROUTED0(ViewHostMsg_MoveCaret_ACK)
-
// Notification that the text selection has changed.
// Note: The secound parameter is the character based offset of the
// base::string16
@@ -1413,6 +1356,13 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_EnumerateDirectory,
int /* request_id */,
base::FilePath /* file_path */)
+// Asks the browser to save a image (for <canvas> or <img>) from a data URL.
+// Note: |data_url| is the contents of a data:URL, and that it's represented as
+// a string only to work around size limitations for GURLs in IPC messages.
+IPC_MESSAGE_CONTROL2(ViewHostMsg_SaveImageFromDataURL,
+ int /* render_view_id */,
+ std::string /* data_url */)
+
// Tells the browser to move the focus to the next (previous if reverse is
// true) focusable element.
IPC_MESSAGE_ROUTED1(ViewHostMsg_TakeFocus,
@@ -1422,13 +1372,16 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_TakeFocus,
IPC_MESSAGE_ROUTED1(ViewHostMsg_OpenDateTimeDialog,
ViewHostMsg_DateTimeDialogValue_Params /* value */)
+IPC_MESSAGE_ROUTED4(ViewHostMsg_TextInputTypeChanged,
+ ui::TextInputType /* TextInputType of the focused node */,
+ ui::TextInputMode /* TextInputMode of the focused node */,
+ bool /* can_compose_inline in the focused node */,
+ int /* flags in the focused node */)
+
// Required for updating text input state.
IPC_MESSAGE_ROUTED1(ViewHostMsg_TextInputStateChanged,
ViewHostMsg_TextInputState_Params /* input state params */)
-// Required for cancelling an ongoing input method composition.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_ImeCancelComposition)
-
// Sent when the renderer changes the zoom level for a particular url, so the
// browser can update its records. If the view is a plugin doc, then url is
// used to update the zoom level for all pages in that site. Otherwise, the
@@ -1450,26 +1403,11 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateZoomLimits,
IPC_MESSAGE_CONTROL1(ViewHostMsg_SuddenTerminationChanged,
bool /* enabled */)
-IPC_STRUCT_BEGIN(ViewHostMsg_CompositorSurfaceBuffersSwapped_Params)
- IPC_STRUCT_MEMBER(int32, surface_id)
- IPC_STRUCT_MEMBER(uint64, surface_handle)
- IPC_STRUCT_MEMBER(int32, route_id)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(float, scale_factor)
- IPC_STRUCT_MEMBER(int32, gpu_process_host_id)
- IPC_STRUCT_MEMBER(std::vector<ui::LatencyInfo>, latency_info)
-IPC_STRUCT_END()
-
-// This message is synthesized by GpuProcessHost to pass through a swap message
-// to the RenderWidgetHelper. This allows GetBackingStore to block for either a
-// software or GPU frame.
-IPC_MESSAGE_ROUTED1(
- ViewHostMsg_CompositorSurfaceBuffersSwapped,
- ViewHostMsg_CompositorSurfaceBuffersSwapped_Params /* params */)
-
-IPC_MESSAGE_ROUTED2(ViewHostMsg_SwapCompositorFrame,
- uint32 /* output_surface_id */,
- cc::CompositorFrame /* frame */)
+IPC_MESSAGE_ROUTED3(
+ ViewHostMsg_SwapCompositorFrame,
+ uint32 /* output_surface_id */,
+ cc::CompositorFrame /* frame */,
+ std::vector<IPC::Message> /* messages_to_deliver_with_frame */)
// Sent by the compositor when a flinging animation is stopped.
IPC_MESSAGE_ROUTED0(ViewHostMsg_DidStopFlinging)
@@ -1502,11 +1440,11 @@ IPC_MESSAGE_ROUTED4(ViewHostMsg_RegisterProtocolHandler,
base::string16 /* title */,
bool /* user_gesture */)
-// Stores new inspector setting in the profile.
-// TODO(jam): this should be in the chrome module
-IPC_MESSAGE_ROUTED2(ViewHostMsg_UpdateInspectorSetting,
- std::string, /* key */
- std::string /* value */)
+// Unregister the registered handler for URL requests with the given scheme.
+IPC_MESSAGE_ROUTED3(ViewHostMsg_UnregisterProtocolHandler,
+ std::string /* scheme */,
+ GURL /* url */,
+ bool /* user_gesture */)
// Puts the browser into "tab fullscreen" mode for the sending renderer.
// See the comment in chrome/browser/ui/browser.h for more details.
@@ -1583,10 +1521,6 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_WillInsertBody)
IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateFaviconURL,
std::vector<content::FaviconURL> /* candidates */)
-// Sent once a paint happens after the first non empty layout. In other words
-// after the page has painted something.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_DidFirstVisuallyNonEmptyPaint)
-
// Sent by the renderer to the browser to start a vibration with the given
// duration.
IPC_MESSAGE_CONTROL1(ViewHostMsg_Vibrate,
@@ -1660,11 +1594,10 @@ IPC_MESSAGE_ROUTED1(ViewHostMsg_SetNeedsBeginFrame,
bool /* enabled */)
// Reply to the ViewMsg_ExtractSmartClipData message.
-// TODO(juhui24.lee@samsung.com): this should be changed to a vector of structs
-// instead of encoding the data as a string which is not allowed normally. Since
-// ths is only used in Android WebView, it's allowed temporarily.
-// http://crbug.com/330872
-IPC_MESSAGE_ROUTED1(ViewHostMsg_SmartClipDataExtracted, base::string16)
+IPC_MESSAGE_ROUTED3(ViewHostMsg_SmartClipDataExtracted,
+ base::string16 /* text */,
+ base::string16 /* html */,
+ gfx::Rect /* rect */)
#elif defined(OS_MACOSX)
// Request that the browser load a font into shared memory for us.
@@ -1682,6 +1615,9 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_PluginFocusChanged,
// Instructs the browser to start plugin IME.
IPC_MESSAGE_ROUTED0(ViewHostMsg_StartPluginIme)
+// Receives content of a web page as plain text.
+IPC_MESSAGE_ROUTED1(ViewMsg_GetRenderedTextCompleted, std::string);
+
#elif defined(OS_WIN)
// Request that the given font characters be loaded by the browser so it's
// cached by the OS. Please see RenderMessageFilter::OnPreCacheFontCharacters
@@ -1712,15 +1648,6 @@ IPC_MESSAGE_CONTROL1(ViewHostMsg_FreeTransportDIB,
TransportDIB::Id /* DIB id */)
#endif
-#if defined(OS_MACOSX) || defined(USE_AURA)
-// On Mac and Aura IME can request composition character bounds
-// synchronously (see crbug.com/120597). This IPC message sends the character
-// bounds after every composition change to always have correct bound info.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_ImeCompositionRangeChanged,
- gfx::Range /* composition range */,
- std::vector<gfx::Rect> /* character bounds */)
-#endif
-
// Adding a new message? Stick to the sort order above: first platform
// independent ViewMsg, then ifdefs for platform specific ViewMsg, then platform
// independent ViewHostMsg, then ifdefs for platform specific ViewHostMsg.
diff --git a/chromium/content/common/web_ui_setup.mojom b/chromium/content/common/web_ui_setup.mojom
deleted file mode 100644
index d61d96ceddf..00000000000
--- a/chromium/content/common/web_ui_setup.mojom
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2014 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.
-
-module content {
-
-[Peer=WebUISetup]
-interface WebUISetupClient {
-};
-
-[Peer=WebUISetupClient]
-interface WebUISetup {
- SetWebUIHandle(int32 view_routing_id, handle<message_pipe> web_ui_handle);
-};
-
-}
diff --git a/chromium/content/common/websocket.h b/chromium/content/common/websocket.h
index 10813187772..e79fc988c05 100644
--- a/chromium/content/common/websocket.h
+++ b/chromium/content/common/websocket.h
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "base/strings/string_split.h"
#include "base/time/time.h"
#include "url/gurl.h"
@@ -31,7 +32,7 @@ struct WebSocketHandshakeRequest {
// The request URL
GURL url;
// Additional HTTP request headers
- std::vector<std::pair<std::string, std::string> > headers;
+ base::StringPairs headers;
// HTTP request headers raw string
std::string headers_text;
// The time that this request is sent
diff --git a/chromium/content/common/websocket_messages.h b/chromium/content/common/websocket_messages.h
index d42b38bbf17..394c9698c6c 100644
--- a/chromium/content/common/websocket_messages.h
+++ b/chromium/content/common/websocket_messages.h
@@ -5,10 +5,7 @@
// Multiply-included message file, hence no include guard.
// This file defines the IPCs for the browser-side implementation of
-// WebSockets. For the legacy renderer-side implementation, see
-// socket_stream_messages.h.
-// TODO(ricea): Fix this comment when the legacy implementation has been
-// removed.
+// WebSockets.
//
// This IPC interface is based on the WebSocket multiplexing draft spec,
// http://tools.ietf.org/html/draft-ietf-hybi-websocket-multiplexing-09
diff --git a/chromium/content/common/worker_messages.h b/chromium/content/common/worker_messages.h
index 94b3997a4c1..9f57b201fc6 100644
--- a/chromium/content/common/worker_messages.h
+++ b/chromium/content/common/worker_messages.h
@@ -97,14 +97,19 @@ IPC_MESSAGE_ROUTED0(WorkerMsg_WorkerObjectDestroyed)
//-----------------------------------------------------------------------------
// WorkerHost messages
-// These are messages sent from the worker process to the renderer process.
-// WorkerMsg_PostMessage is also sent here.
+// These are messages sent from the worker (renderer process) to the worker
+// host (browser process).
IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerContextClosed,
int /* worker_route_id */)
IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerContextDestroyed,
int /* worker_route_id */)
+// Renderer -> Browser message to indicate that the worker is ready for
+// inspection.
+IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerReadyForInspection,
+ int /* worker_route_id */)
+
IPC_MESSAGE_CONTROL1(WorkerHostMsg_WorkerScriptLoaded,
int /* worker_route_id */)
diff --git a/chromium/content/content.gyp b/chromium/content/content.gyp
index fbd3b7d332d..5a7355f7ff3 100644
--- a/chromium/content/content.gyp
+++ b/chromium/content/content.gyp
@@ -25,9 +25,30 @@
['OS != "ios"', {
'includes': [
'content_common_mojo_bindings.gypi',
+ 'content_resources.gypi',
'../build/win_precompile.gypi',
],
}],
+ ['OS == "win"', {
+ 'targets': [
+ {
+ 'target_name': 'content_startup_helper_win',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../base/base.gyp:base_i18n',
+ '../sandbox/sandbox.gyp:sandbox',
+ ],
+ 'sources': [
+ 'app/startup_helper_win.cc',
+ 'public/app/startup_helper_win.h',
+ ],
+ }
+ ],
+ }],
# In component mode, we build all of content as a single DLL.
# However, in the static mode, we need to build content as multiple
# targets in order to prevent dependencies from getting introduced
@@ -40,12 +61,16 @@
],
'targets': [
{
+ # GN version: //content
'target_name': 'content',
'type': 'none',
'dependencies': [
'content_browser',
'content_common',
],
+ 'export_dependent_settings': [
+ 'content_common',
+ ],
'conditions': [
['OS != "ios"', {
'dependencies': [
@@ -55,12 +80,12 @@
'content_ppapi_plugin',
'content_renderer',
'content_utility',
- 'content_worker',
],
}],
],
},
{
+ # GN version: //content/app:browser
'target_name': 'content_app_browser',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -70,6 +95,9 @@
'dependencies': [
'content_common',
],
+ 'export_dependent_settings': [
+ 'content_common',
+ ],
'conditions': [
['chrome_multiple_dll', {
'defines': [
@@ -79,6 +107,7 @@
],
},
{
+ # GN version: //content/app:child
'target_name': 'content_app_child',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -88,6 +117,9 @@
'dependencies': [
'content_common',
],
+ 'export_dependent_settings': [
+ 'content_common',
+ ],
'conditions': [
['chrome_multiple_dll', {
'defines': [
@@ -97,6 +129,7 @@
],
},
{
+ # GN version: //content/app:both
'target_name': 'content_app_both',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -111,15 +144,21 @@
],
},
{
+ # GN version: //content/browser and //content/public/browser
'target_name': 'content_browser',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
'includes': [
'content_browser.gypi',
+ # Disable LTO due to ELF section name out of range
+ # crbug.com/422251
+ '../build/android/disable_lto.gypi',
],
'dependencies': [
'content_common',
- 'content_resources.gyp:content_resources',
+ ],
+ 'export_dependent_settings': [
+ 'content_common',
],
'conditions': [
['java_bridge==1', {
@@ -133,9 +172,15 @@
'content_utility',
],
}],
+ ['OS != "ios"', {
+ 'dependencies': [
+ 'content_resources',
+ ],
+ }],
],
},
{
+ # GN version: //content/common and //content/public/common
'target_name': 'content_common',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -145,7 +190,7 @@
'conditions': [
['OS != "ios"', {
'dependencies': [
- 'content_resources.gyp:content_resources',
+ 'content_resources',
],
}],
],
@@ -157,6 +202,7 @@
['OS != "ios"', {
'targets': [
{
+ # GN version: //content/child and //content/public/child
'target_name': 'content_child',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -164,12 +210,13 @@
'content_child.gypi',
],
'dependencies': [
- 'content_resources.gyp:content_resources',
+ 'content_resources',
],
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
},
{
+ # GN version: //content/gpu
'target_name': 'content_gpu',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -182,6 +229,7 @@
],
},
{
+ # GN version: //content/plugin and //content/public/plugin
'target_name': 'content_plugin',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -194,6 +242,7 @@
],
},
{
+ # GN version: //content/ppapi_plugin
'target_name': 'content_ppapi_plugin',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -204,6 +253,7 @@
'msvs_disabled_warnings': [ 4267, ],
},
{
+ # GN version: //content/renderer and //content/public/renderer
'target_name': 'content_renderer',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -213,7 +263,7 @@
'dependencies': [
'content_child',
'content_common',
- 'content_resources.gyp:content_resources',
+ 'content_resources',
],
'conditions': [
['chromium_enable_vtune_jit_for_v8==1', {
@@ -224,6 +274,7 @@
],
},
{
+ # GN version: //content/utility and //content/public/utility
'target_name': 'content_utility',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
@@ -235,18 +286,6 @@
'content_common',
],
},
- {
- 'target_name': 'content_worker',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_worker.gypi',
- ],
- 'dependencies': [
- 'content_child',
- 'content_common',
- ],
- },
],
}],
],
@@ -254,11 +293,12 @@
{ # component != static_library
'targets': [
{
+ # GN version: //content
'target_name': 'content',
'type': 'shared_library',
'variables': { 'enable_wexit_time_destructors': 1, },
'dependencies': [
- 'content_resources.gyp:content_resources',
+ 'content_resources',
],
'conditions': [
['chromium_enable_vtune_jit_for_v8==1', {
@@ -277,7 +317,6 @@
'content_ppapi_plugin.gypi',
'content_renderer.gypi',
'content_utility.gypi',
- 'content_worker.gypi',
],
'msvs_settings': {
'VCLinkerTool': {
@@ -290,51 +329,60 @@
},
},
{
+ # GN version: //content/app:browser
'target_name': 'content_app_browser',
'type': 'none',
'dependencies': ['content', 'content_browser'],
},
{
+ # GN version: //content/app:child
'target_name': 'content_app_child',
'type': 'none',
'dependencies': ['content', 'content_child'],
},
{
+ # GN version: //content/app:both
'target_name': 'content_app_both',
'type': 'none',
'dependencies': ['content'],
'export_dependent_settings': ['content'],
},
{
+ # GN version: //content/browser and //content/public/browser
'target_name': 'content_browser',
'type': 'none',
'dependencies': ['content'],
'export_dependent_settings': ['content'],
},
{
+ # GN version: //content/common and //content/public/common
'target_name': 'content_common',
'type': 'none',
- 'dependencies': ['content', 'content_resources.gyp:content_resources'],
+ 'dependencies': ['content', 'content_resources'],
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
'export_dependent_settings': ['content'],
},
{
+ # GN Version: //content/child
'target_name': 'content_child',
'type': 'none',
'dependencies': ['content'],
},
{
+ # GN version: //content/gpu
'target_name': 'content_gpu',
'type': 'none',
'dependencies': ['content'],
},
{
+ # GN version: //content/plugin
'target_name': 'content_plugin',
'type': 'none',
'dependencies': ['content'],
},
{
+ # GN version: //content/ppapi_plugin
'target_name': 'content_ppapi_plugin',
'type': 'none',
'dependencies': ['content'],
@@ -342,21 +390,18 @@
'msvs_disabled_warnings': [ 4267, ],
},
{
+ # GN version: //content/renderer and //content/public/renderer
'target_name': 'content_renderer',
'type': 'none',
'dependencies': ['content'],
},
{
+ # GN version: //content/utility
'target_name': 'content_utility',
'type': 'none',
'dependencies': ['content'],
'export_dependent_settings': ['content'],
},
- {
- 'target_name': 'content_worker',
- 'type': 'none',
- 'dependencies': ['content'],
- },
],
}],
['OS == "android"', {
@@ -379,7 +424,10 @@
'type': 'none',
'dependencies': [
'../base/base.gyp:base',
+ '../device/battery/battery.gyp:device_battery_java',
'../media/media.gyp:media_java',
+ '../mojo/mojo_base.gyp:mojo_system_java',
+ '../mojo/public/mojo_public.gyp:mojo_bindings_java',
'../net/net.gyp:net',
'../ui/android/ui_android.gyp:ui_java',
'common_aidl',
@@ -387,9 +435,9 @@
'content_strings_grd',
'content_gamepad_mapping',
'gesture_event_type_java',
- 'page_transition_types_java',
'popup_item_type_java',
'result_codes_java',
+ 'selection_event_type_java',
'speech_recognition_error_java',
'top_controls_state_java',
'screen_orientation_values_java',
@@ -404,7 +452,6 @@
['android_webview_build == 0', {
'dependencies': [
'../third_party/eyesfree/eyesfree.gyp:eyesfree_java',
- '../third_party/guava/guava.gyp:guava_javalib',
],
}],
],
@@ -423,88 +470,68 @@
],
},
{
- 'target_name': 'gesture_event_type_java',
+ 'target_name': 'content_gamepad_mapping',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/browser/GestureEventType.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/browser',
- 'template_deps': ['browser/android/gesture_event_type_list.h'],
+ 'source_file': 'browser/gamepad/gamepad_standard_mappings.h',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
- 'target_name': 'page_transition_types_java',
+ 'target_name': 'gesture_event_type_java',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/browser',
- 'template_deps': ['public/common/page_transition_types_list.h'],
+ 'source_file': 'browser/android/gesture_event_type.h',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
'target_name': 'popup_item_type_java',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/browser/input/PopupItemType.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/browser/input',
- 'template_deps': ['browser/android/popup_item_type_list.h'],
+ 'source_file': 'browser/android/content_view_core_impl.cc',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
'target_name': 'result_codes_java',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/common/ResultCodes.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/common',
- 'template_deps': ['public/common/result_codes_list.h'],
+ 'source_file': 'public/common/result_codes.h',
+ },
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
+ },
+ {
+ 'target_name': 'selection_event_type_java',
+ 'type': 'none',
+ 'variables': {
+ 'source_file': 'browser/renderer_host/input/selection_event_type.h',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
'target_name': 'speech_recognition_error_java',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/browser',
- 'template_deps': ['public/common/speech_recognition_error_list.h'],
+ 'source_file': 'public/common/speech_recognition_error.h',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
'target_name': 'top_controls_state_java',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/common/TopControlsState.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/common',
- 'template_deps': ['public/common/top_controls_state_list.h'],
+ 'source_file': 'public/common/top_controls_state.h',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
'target_name': 'screen_orientation_values_java',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template',
- ],
'variables': {
- 'package_name': 'org/chromium/content/common',
- 'template_deps': ['public/common/screen_orientation_values_list.h'],
+ 'source_file': 'public/common/screen_orientation_values.h',
},
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
+ 'includes': [ '../build/android/java_cpp_enum.gypi' ],
},
{
'target_name': 'java_set_jni_headers',
@@ -550,20 +577,21 @@
],
},
{
- 'target_name': 'content_gamepad_mapping',
+ 'target_name': 'content_v8_external_data',
'type': 'none',
- 'sources': [
- 'public/android/java/src/org/chromium/content/browser/input/CanonicalButtonIndex.template',
- 'public/android/java/src/org/chromium/content/browser/input/CanonicalAxisIndex.template',
+ 'conditions': [
+ ['v8_use_external_startup_data==1', {
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/content_shell/assets',
+ 'files': [
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ },
+ ],
+ }],
],
- 'variables': {
- 'package_name': 'org/chromium/content/browser/input',
- 'template_deps': [
- 'browser/gamepad/canonical_axis_index_list.h',
- 'browser/gamepad/canonical_button_index_list.h',
- ],
- },
- 'includes': [ '../build/android/java_cpp_template.gypi' ],
},
],
}], # OS == "android"
diff --git a/chromium/content/content_app.gypi b/chromium/content/content_app.gypi
index fcb98e989d6..12c217798b3 100644
--- a/chromium/content/content_app.gypi
+++ b/chromium/content/content_app.gypi
@@ -26,13 +26,11 @@
'app/content_main_runner.cc',
'app/mojo/mojo_init.cc',
'app/mojo/mojo_init.h',
- 'app/startup_helper_win.cc',
'public/app/android_library_loader_hooks.h',
'public/app/content_main.h',
'public/app/content_main_delegate.cc',
'public/app/content_main_delegate.h',
'public/app/content_main_runner.h',
- 'public/app/startup_helper_win.h',
],
'conditions': [
['((OS=="linux" and os_posix==1 and use_aura==1) or OS=="android") and use_allocator!="none"', {
@@ -41,11 +39,6 @@
'../base/allocator/allocator.gyp:allocator',
],
}],
- ['OS=="win"', {
- 'dependencies': [
- '../sandbox/sandbox.gyp:sandbox',
- ],
- }],
['OS=="android"', {
'sources!': [
'app/content_main.cc',
@@ -58,6 +51,11 @@
'../build/android/cpufeatures.gypi',
],
}],
+ ['OS=="win"', {
+ 'dependencies': [
+ 'content_startup_helper_win',
+ ],
+ }],
['OS=="ios"', {
'sources!': [
'app/content_main.cc',
@@ -66,10 +64,9 @@
],
}, { # OS!="ios"
'dependencies': [
- '../mojo/mojo.gyp:mojo_environment_chromium',
- '../mojo/mojo.gyp:mojo_service_manager',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
- '../mojo/mojo.gyp:mojo_system_impl',
+ '../mojo/edk/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
],
}],
],
diff --git a/chromium/content/content_browser.gypi b/chromium/content/content_browser.gypi
index 33f796fc4f0..2cf449d3fe8 100644
--- a/chromium/content/content_browser.gypi
+++ b/chromium/content/content_browser.gypi
@@ -6,6 +6,8 @@
'dependencies': [
'../base/base.gyp:base_static',
'../crypto/crypto.gyp:crypto',
+ '../device/battery/battery.gyp:device_battery',
+ '../device/battery/battery.gyp:device_battery_mojo_bindings',
'../google_apis/google_apis.gyp:google_apis',
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
@@ -23,7 +25,7 @@
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/resources/ui_resources.gyp:ui_resources',
'../ui/snapshot/snapshot.gyp:snapshot',
- 'browser/service_worker/service_worker_proto.gyp:database_proto',
+ 'browser/service_worker/service_worker_proto.gyp:proto',
'browser/speech/proto/speech_proto.gyp:speech_proto',
],
'export_dependent_settings': [
@@ -51,10 +53,10 @@
'public/browser/android/external_video_surface_container.h',
'public/browser/android/layer_tree_build_helper.h',
'public/browser/android/synchronous_compositor_client.h',
- 'public/browser/android/synchronous_compositor.cc',
'public/browser/android/synchronous_compositor.h',
'public/browser/android/ui_resource_client_android.h',
'public/browser/android/ui_resource_provider.h',
+ 'public/browser/appcache_service.h',
'public/browser/ax_event_notification_details.cc',
'public/browser/ax_event_notification_details.h',
'public/browser/blob_handle.h',
@@ -73,6 +75,7 @@
'public/browser/browser_main_runner.h',
'public/browser/browser_message_filter.cc',
'public/browser/browser_message_filter.h',
+ 'public/browser/browser_plugin_guest_delegate.cc',
'public/browser/browser_plugin_guest_delegate.h',
'public/browser/browser_plugin_guest_manager.cc',
'public/browser/browser_plugin_guest_manager.h',
@@ -94,14 +97,13 @@
'public/browser/desktop_media_id.h',
'public/browser/desktop_notification_delegate.h',
'public/browser/devtools_agent_host.h',
- 'public/browser/devtools_client_host.h',
+ 'public/browser/devtools_agent_host_client.h',
'public/browser/devtools_external_agent_proxy.h',
'public/browser/devtools_external_agent_proxy_delegate.h',
'public/browser/download_danger_type.h',
- 'public/browser/devtools_frontend_host_delegate.h',
+ 'public/browser/devtools_frontend_host.h',
'public/browser/devtools_http_handler.h',
'public/browser/devtools_http_handler_delegate.h',
- 'public/browser/devtools_manager.h',
'public/browser/devtools_manager_delegate.h',
'public/browser/devtools_target.h',
'public/browser/dom_operation_notification_details.h',
@@ -161,12 +163,14 @@
'public/browser/page_navigator.cc',
'public/browser/page_navigator.h',
'public/browser/pepper_flash_settings_helper.h',
+ 'public/browser/permission_type.h',
'public/browser/plugin_data_remover.h',
'public/browser/plugin_service.h',
'public/browser/plugin_service_filter.h',
'public/browser/power_save_blocker.h',
'public/browser/profiler_controller.h',
'public/browser/profiler_subscriber.h',
+ 'public/browser/push_messaging_service.h',
'public/browser/quota_permission_context.h',
'public/browser/render_frame_host.h',
'public/browser/render_process_host.h',
@@ -188,7 +192,13 @@
'public/browser/resource_request_info.h',
'public/browser/resource_throttle.h',
'public/browser/save_page_type.h',
+ 'public/browser/screen_orientation_dispatcher_host.h',
+ 'public/browser/screen_orientation_delegate.h',
+ 'public/browser/screen_orientation_provider.cc',
+ 'public/browser/screen_orientation_provider.h',
'public/browser/service_worker_context.h',
+ 'public/browser/service_worker_usage_info.cc',
+ 'public/browser/service_worker_usage_info.h',
'public/browser/session_storage_namespace.h',
'public/browser/session_storage_usage_info.h',
'public/browser/signed_certificate_timestamp_store.h',
@@ -200,8 +210,11 @@
'public/browser/speech_recognition_session_config.h',
'public/browser/speech_recognition_session_context.cc',
'public/browser/speech_recognition_session_context.h',
+ 'public/browser/ssl_host_state_delegate.h',
'public/browser/storage_partition.h',
'public/browser/stream_handle.h',
+ 'public/browser/stream_info.cc',
+ 'public/browser/stream_info.h',
'public/browser/tracing_controller.h',
'public/browser/user_metrics.h',
'public/browser/utility_process_host.h',
@@ -213,6 +226,7 @@
'public/browser/web_contents_observer.cc',
'public/browser/web_contents_observer.h',
'public/browser/web_contents_user_data.h',
+ 'public/browser/web_contents_view_delegate.cc',
'public/browser/web_contents_view_delegate.h',
'public/browser/web_drag_dest_delegate.h',
'public/browser/web_ui.h',
@@ -264,8 +278,12 @@
'browser/android/browser_jni_registrar.h',
'browser/android/browser_startup_controller.cc',
'browser/android/browser_startup_controller.h',
+ 'browser/android/browser_surface_texture_manager.cc',
+ 'browser/android/browser_surface_texture_manager.h',
'browser/android/child_process_launcher_android.cc',
'browser/android/child_process_launcher_android.h',
+ 'browser/android/composited_touch_handle_drawable.cc',
+ 'browser/android/composited_touch_handle_drawable.h',
'browser/android/content_readback_handler.cc',
'browser/android/content_readback_handler.h',
'browser/android/content_settings.cc',
@@ -285,8 +303,10 @@
'browser/android/download_controller_android_impl.cc',
'browser/android/download_controller_android_impl.h',
'browser/android/devtools_auth.cc',
- 'browser/android/edge_effect.h',
'browser/android/edge_effect.cc',
+ 'browser/android/edge_effect.h',
+ 'browser/android/edge_effect_l.cc',
+ 'browser/android/edge_effect_l.h',
'browser/android/gesture_event_type_list.h',
'browser/android/in_process/synchronous_compositor_factory_impl.cc',
'browser/android/in_process/synchronous_compositor_factory_impl.h',
@@ -300,34 +320,66 @@
'browser/android/interstitial_page_delegate_android.h',
'browser/android/load_url_params.cc',
'browser/android/load_url_params.h',
- 'browser/android/overscroll_glow.h',
'browser/android/overscroll_glow.cc',
+ 'browser/android/overscroll_glow.h',
'browser/android/popup_item_type_list.h',
- 'browser/android/surface_texture_peer_browser_impl.cc',
- 'browser/android/surface_texture_peer_browser_impl.h',
+ 'browser/android/popup_touch_handle_drawable.cc',
+ 'browser/android/popup_touch_handle_drawable.h',
+ 'browser/android/system_ui_resource_manager_impl.cc',
+ 'browser/android/system_ui_resource_manager_impl.h',
'browser/android/tracing_controller_android.cc',
'browser/android/tracing_controller_android.h',
'browser/android/web_contents_observer_android.cc',
'browser/android/web_contents_observer_android.h',
'browser/android/ui_resource_provider_impl.cc',
'browser/android/ui_resource_provider_impl.h',
+ 'browser/appcache/appcache.cc',
+ 'browser/appcache/appcache.h',
+ 'browser/appcache/appcache_backend_impl.cc',
+ 'browser/appcache/appcache_backend_impl.h',
+ 'browser/appcache/appcache_database.cc',
+ 'browser/appcache/appcache_database.h',
+ 'browser/appcache/appcache_disk_cache.cc',
+ 'browser/appcache/appcache_disk_cache.h',
'browser/appcache/appcache_dispatcher_host.cc',
'browser/appcache/appcache_dispatcher_host.h',
+ 'browser/appcache/appcache_entry.h',
+ 'browser/appcache/appcache_executable_handler.h',
'browser/appcache/appcache_frontend_proxy.cc',
'browser/appcache/appcache_frontend_proxy.h',
+ 'browser/appcache/appcache_group.cc',
+ 'browser/appcache/appcache_group.h',
+ 'browser/appcache/appcache_histograms.cc',
+ 'browser/appcache/appcache_histograms.h',
+ 'browser/appcache/appcache_host.cc',
+ 'browser/appcache/appcache_host.h',
'browser/appcache/appcache_interceptor.cc',
'browser/appcache/appcache_interceptor.h',
+ 'browser/appcache/appcache_policy.h',
+ 'browser/appcache/appcache_quota_client.cc',
+ 'browser/appcache/appcache_quota_client.h',
+ 'browser/appcache/appcache_request_handler.cc',
+ 'browser/appcache/appcache_request_handler.h',
+ 'browser/appcache/appcache_response.cc',
+ 'browser/appcache/appcache_response.h',
+ 'browser/appcache/appcache_service_impl.cc',
+ 'browser/appcache/appcache_service_impl.h',
+ 'browser/appcache/appcache_storage.cc',
+ 'browser/appcache/appcache_storage.h',
+ 'browser/appcache/appcache_storage_impl.cc',
+ 'browser/appcache/appcache_storage_impl.h',
+ 'browser/appcache/appcache_update_job.cc',
+ 'browser/appcache/appcache_update_job.h',
+ 'browser/appcache/appcache_url_request_job.cc',
+ 'browser/appcache/appcache_url_request_job.h',
+ 'browser/appcache/appcache_working_set.cc',
+ 'browser/appcache/appcache_working_set.h',
'browser/appcache/chrome_appcache_service.cc',
'browser/appcache/chrome_appcache_service.h',
- 'browser/appcache/view_appcache_internals_job.h',
+ 'browser/appcache/appcache_manifest_parser.cc',
+ 'browser/appcache/appcache_manifest_parser.h',
'browser/appcache/view_appcache_internals_job.cc',
- 'browser/battery_status/battery_status_manager_android.cc',
- 'browser/battery_status/battery_status_manager_default.cc',
- 'browser/battery_status/battery_status_manager.h',
- 'browser/battery_status/battery_status_message_filter.cc',
- 'browser/battery_status/battery_status_message_filter.h',
- 'browser/battery_status/battery_status_service.cc',
- 'browser/battery_status/battery_status_service.h',
+ 'browser/appcache/view_appcache_internals_job.h',
'browser/bootstrap_sandbox_mac.cc',
'browser/bootstrap_sandbox_mac.h',
'browser/browser_child_process_host_impl.cc',
@@ -365,44 +417,58 @@
'browser/child_process_launcher.h',
'browser/child_process_security_policy_impl.cc',
'browser/child_process_security_policy_impl.h',
- 'browser/cross_site_request_manager.cc',
- 'browser/cross_site_request_manager.h',
+ 'browser/cocoa/system_hotkey_helper_mac.h',
+ 'browser/cocoa/system_hotkey_helper_mac.mm',
+ 'browser/cocoa/system_hotkey_map.h',
+ 'browser/cocoa/system_hotkey_map.mm',
'browser/devtools/devtools_agent_host_impl.cc',
'browser/devtools/devtools_agent_host_impl.h',
- 'browser/devtools/devtools_browser_target.cc',
- 'browser/devtools/devtools_browser_target.h',
- 'browser/devtools/devtools_frontend_host.cc',
- 'browser/devtools/devtools_frontend_host.h',
+ 'browser/devtools/devtools_frontend_host_impl.cc',
+ 'browser/devtools/devtools_frontend_host_impl.h',
'browser/devtools/devtools_http_handler_impl.cc',
'browser/devtools/devtools_http_handler_impl.h',
- 'browser/devtools/devtools_manager_impl.cc',
- 'browser/devtools/devtools_manager_impl.h',
+ 'browser/devtools/devtools_manager.cc',
+ 'browser/devtools/devtools_manager.h',
'browser/devtools/devtools_netlog_observer.cc',
'browser/devtools/devtools_netlog_observer.h',
- 'browser/devtools/devtools_power_handler.cc',
- 'browser/devtools/devtools_power_handler.h',
'browser/devtools/devtools_protocol.cc',
'browser/devtools/devtools_protocol.h',
'browser/devtools/devtools_system_info_handler.cc',
'browser/devtools/devtools_system_info_handler.h',
- 'browser/devtools/devtools_tracing_handler.h',
- 'browser/devtools/devtools_tracing_handler.cc',
'browser/devtools/forwarding_agent_host.cc',
'browser/devtools/forwarding_agent_host.h',
'browser/devtools/ipc_devtools_agent_host.cc',
'browser/devtools/ipc_devtools_agent_host.h',
+ 'browser/devtools/embedded_worker_devtools_agent_host.cc',
+ 'browser/devtools/embedded_worker_devtools_agent_host.h',
'browser/devtools/embedded_worker_devtools_manager.cc',
'browser/devtools/embedded_worker_devtools_manager.h',
+ 'browser/devtools/protocol/color_picker.cc',
+ 'browser/devtools/protocol/color_picker.h',
+ 'browser/devtools/protocol/devtools_protocol_client.cc',
+ 'browser/devtools/protocol/devtools_protocol_client.h',
+ 'browser/devtools/protocol/dom_handler.cc',
+ 'browser/devtools/protocol/dom_handler.h',
+ 'browser/devtools/protocol/input_handler.cc',
+ 'browser/devtools/protocol/input_handler.h',
+ 'browser/devtools/protocol/inspector_handler.cc',
+ 'browser/devtools/protocol/inspector_handler.h',
+ 'browser/devtools/protocol/network_handler.cc',
+ 'browser/devtools/protocol/network_handler.h',
+ 'browser/devtools/protocol/page_handler.cc',
+ 'browser/devtools/protocol/page_handler.h',
+ 'browser/devtools/protocol/power_handler.cc',
+ 'browser/devtools/protocol/power_handler.h',
+ 'browser/devtools/protocol/tracing_handler.cc',
+ 'browser/devtools/protocol/tracing_handler.h',
+ 'browser/devtools/protocol/usage_and_quota_query.cc',
+ 'browser/devtools/protocol/usage_and_quota_query.h',
+ 'browser/devtools/protocol/worker_handler.cc',
+ 'browser/devtools/protocol/worker_handler.h',
'browser/devtools/render_view_devtools_agent_host.cc',
'browser/devtools/render_view_devtools_agent_host.h',
- 'browser/devtools/renderer_overrides_handler.cc',
- 'browser/devtools/renderer_overrides_handler.h',
'browser/devtools/tethering_handler.h',
'browser/devtools/tethering_handler.cc',
- 'browser/devtools/worker_devtools_manager.cc',
- 'browser/devtools/worker_devtools_manager.h',
- 'browser/devtools/worker_devtools_message_filter.cc',
- 'browser/devtools/worker_devtools_message_filter.h',
'browser/device_monitor_mac.h',
'browser/device_monitor_mac.mm',
'browser/device_monitor_udev.cc',
@@ -416,6 +482,8 @@
'browser/device_sensors/data_fetcher_shared_memory_win.cc',
'browser/device_sensors/device_inertial_sensor_service.cc',
'browser/device_sensors/device_inertial_sensor_service.h',
+ 'browser/device_sensors/device_light_message_filter.cc',
+ 'browser/device_sensors/device_light_message_filter.h',
'browser/device_sensors/device_motion_message_filter.cc',
'browser/device_sensors/device_motion_message_filter.h',
'browser/device_sensors/device_orientation_message_filter.cc',
@@ -515,8 +583,14 @@
'browser/fileapi/upload_file_system_file_element_reader.cc',
'browser/fileapi/upload_file_system_file_element_reader.h',
'browser/font_list_async.cc',
+ 'browser/frame_host/cross_process_frame_connector.cc',
+ 'browser/frame_host/cross_process_frame_connector.h',
+ 'browser/frame_host/cross_site_transferring_request.cc',
+ 'browser/frame_host/cross_site_transferring_request.h',
'browser/frame_host/debug_urls.cc',
'browser/frame_host/debug_urls.h',
+ 'browser/frame_host/frame_accessibility.cc',
+ 'browser/frame_host/frame_accessibility.h',
'browser/frame_host/frame_tree.cc',
'browser/frame_host/frame_tree.h',
'browser/frame_host/frame_tree_node.cc',
@@ -534,16 +608,18 @@
'browser/frame_host/navigation_entry_impl.h',
'browser/frame_host/navigation_entry_screenshot_manager.cc',
'browser/frame_host/navigation_entry_screenshot_manager.h',
+ 'browser/frame_host/navigation_request.cc',
+ 'browser/frame_host/navigation_request.h',
+ 'browser/frame_host/navigation_request_info.cc',
+ 'browser/frame_host/navigation_request_info.h',
'browser/frame_host/navigator.cc',
'browser/frame_host/navigator.h',
'browser/frame_host/navigator_impl.cc',
'browser/frame_host/navigator_impl.h',
'browser/frame_host/navigator_delegate.cc',
'browser/frame_host/navigator_delegate.h',
- 'browser/frame_host/cross_process_frame_connector.cc',
- 'browser/frame_host/cross_process_frame_connector.h',
- 'browser/frame_host/cross_site_transferring_request.cc',
- 'browser/frame_host/cross_site_transferring_request.h',
+ 'browser/frame_host/popup_menu_helper_mac.h',
+ 'browser/frame_host/popup_menu_helper_mac.mm',
'browser/frame_host/render_frame_host_delegate.cc',
'browser/frame_host/render_frame_host_delegate.h',
'browser/frame_host/render_frame_host_factory.cc',
@@ -584,12 +660,24 @@
'browser/gamepad/raw_input_data_fetcher_win.h',
'browser/gamepad/xbox_data_fetcher_mac.cc',
'browser/gamepad/xbox_data_fetcher_mac.h',
+ 'browser/geofencing/geofencing_dispatcher_host.cc',
+ 'browser/geofencing/geofencing_dispatcher_host.h',
+ 'browser/geofencing/geofencing_manager.cc',
+ 'browser/geofencing/geofencing_manager.h',
+ 'browser/geofencing/geofencing_provider.h',
+ 'browser/geofencing/geofencing_registration_delegate.h',
+ 'browser/geofencing/geofencing_service.cc',
+ 'browser/geofencing/geofencing_service.h',
'browser/geolocation/empty_wifi_data_provider.cc',
'browser/geolocation/empty_wifi_data_provider.h',
'browser/geolocation/geolocation_dispatcher_host.cc',
'browser/geolocation/geolocation_dispatcher_host.h',
'browser/geolocation/geolocation_provider_impl.cc',
'browser/geolocation/geolocation_provider_impl.h',
+ 'browser/geolocation/geolocation_service_context.cc',
+ 'browser/geolocation/geolocation_service_context.h',
+ 'browser/geolocation/geolocation_service_impl.cc',
+ 'browser/geolocation/geolocation_service_impl.h',
'browser/geolocation/location_api_adapter_android.cc',
'browser/geolocation/location_api_adapter_android.h',
'browser/geolocation/location_arbitrator.h',
@@ -619,11 +707,15 @@
'browser/geolocation/wifi_data_provider_linux.h',
'browser/geolocation/wifi_data_provider_mac.cc',
'browser/geolocation/wifi_data_provider_mac.h',
+ 'browser/geolocation/wifi_data_provider_manager.cc',
+ 'browser/geolocation/wifi_data_provider_manager.h',
'browser/geolocation/wifi_data_provider_win.cc',
'browser/geolocation/wifi_data_provider_win.h',
'browser/geolocation/wifi_polling_policy.h',
'browser/gpu/browser_gpu_channel_host_factory.cc',
'browser/gpu/browser_gpu_channel_host_factory.h',
+ 'browser/gpu/browser_gpu_memory_buffer_manager.cc',
+ 'browser/gpu/browser_gpu_memory_buffer_manager.h',
'browser/gpu/compositor_util.cc',
'browser/gpu/compositor_util.h',
'browser/gpu/gpu_data_manager_impl.cc',
@@ -632,6 +724,8 @@
'browser/gpu/gpu_data_manager_impl_private.h',
'browser/gpu/gpu_internals_ui.cc',
'browser/gpu/gpu_internals_ui.h',
+ 'browser/gpu/gpu_memory_buffer_factory_host_impl.cc',
+ 'browser/gpu/gpu_memory_buffer_factory_host_impl.h',
'browser/gpu/gpu_process_host.cc',
'browser/gpu/gpu_process_host.h',
'browser/gpu/gpu_process_host_ui_shim.cc',
@@ -675,8 +769,9 @@
'browser/indexed_db/indexed_db_database_error.h',
'browser/indexed_db/indexed_db_dispatcher_host.cc',
'browser/indexed_db/indexed_db_dispatcher_host.h',
- 'browser/indexed_db/indexed_db_factory.cc',
'browser/indexed_db/indexed_db_factory.h',
+ 'browser/indexed_db/indexed_db_factory_impl.cc',
+ 'browser/indexed_db/indexed_db_factory_impl.h',
'browser/indexed_db/indexed_db_index_writer.cc',
'browser/indexed_db/indexed_db_index_writer.h',
'browser/indexed_db/indexed_db_internals_ui.cc',
@@ -698,7 +793,10 @@
'browser/indexed_db/leveldb/leveldb_comparator.h',
'browser/indexed_db/leveldb/leveldb_database.cc',
'browser/indexed_db/leveldb/leveldb_database.h',
+ 'browser/indexed_db/leveldb/leveldb_factory.h',
'browser/indexed_db/leveldb/leveldb_iterator.h',
+ 'browser/indexed_db/leveldb/leveldb_iterator_impl.cc',
+ 'browser/indexed_db/leveldb/leveldb_iterator_impl.h',
'browser/indexed_db/leveldb/leveldb_transaction.cc',
'browser/indexed_db/leveldb/leveldb_transaction.h',
'browser/indexed_db/leveldb/leveldb_write_batch.cc',
@@ -716,6 +814,16 @@
'browser/loader/global_routing_id.h',
'browser/loader/layered_resource_handler.cc',
'browser/loader/layered_resource_handler.h',
+ 'browser/loader/navigation_resource_handler.cc',
+ 'browser/loader/navigation_resource_handler.h',
+ 'browser/loader/navigation_url_loader.cc',
+ 'browser/loader/navigation_url_loader.h',
+ 'browser/loader/navigation_url_loader_delegate.h',
+ 'browser/loader/navigation_url_loader_factory.h',
+ 'browser/loader/navigation_url_loader_impl.cc',
+ 'browser/loader/navigation_url_loader_impl.h',
+ 'browser/loader/navigation_url_loader_impl_core.cc',
+ 'browser/loader/navigation_url_loader_impl_core.h',
'browser/loader/power_save_block_resource_throttle.cc',
'browser/loader/power_save_block_resource_throttle.h',
'browser/loader/redirect_to_file_resource_handler.cc',
@@ -741,6 +849,8 @@
'browser/loader/resource_scheduler_filter.h',
'browser/loader/stream_resource_handler.cc',
'browser/loader/stream_resource_handler.h',
+ 'browser/loader/stream_writer.cc',
+ 'browser/loader/stream_writer.h',
'browser/loader/sync_resource_handler.cc',
'browser/loader/sync_resource_handler.h',
'browser/loader/temporary_file_stream.cc',
@@ -759,6 +869,8 @@
'browser/media/android/media_drm_credential_manager.h',
'browser/media/android/media_resource_getter_impl.cc',
'browser/media/android/media_resource_getter_impl.h',
+ 'browser/media/audio_stream_monitor.cc',
+ 'browser/media/audio_stream_monitor.h',
'browser/media/capture/audio_mirroring_manager.cc',
'browser/media/capture/audio_mirroring_manager.h',
'browser/media/capture/content_video_capture_device_core.cc',
@@ -767,6 +879,8 @@
'browser/media/capture/video_capture_oracle.h',
'browser/media/capture/web_contents_audio_input_stream.cc',
'browser/media/capture/web_contents_audio_input_stream.h',
+ 'browser/media/capture/web_contents_audio_muter.cc',
+ 'browser/media/capture/web_contents_audio_muter.h',
'browser/media/capture/web_contents_capture_util.cc',
'browser/media/capture/web_contents_capture_util.h',
'browser/media/capture/web_contents_tracker.cc',
@@ -789,6 +903,8 @@
'browser/media/webrtc_identity_store.h',
'browser/media/webrtc_identity_store_backend.cc',
'browser/media/webrtc_identity_store_backend.h',
+ 'browser/manifest/manifest_manager_host.cc',
+ 'browser/manifest/manifest_manager_host.h',
'browser/message_port_message_filter.cc',
'browser/message_port_message_filter.h',
'browser/message_port_service.cc',
@@ -797,6 +913,8 @@
'browser/mime_registry_message_filter.h',
'browser/mojo/mojo_application_host.cc',
'browser/mojo/mojo_application_host.h',
+ 'browser/mojo/service_registry_android.cc',
+ 'browser/mojo/service_registry_android.h',
'browser/net/browser_online_state_observer.cc',
'browser/net/browser_online_state_observer.h',
'browser/net/sqlite_persistent_cookie_store.cc',
@@ -805,6 +923,10 @@
'browser/net/view_blob_internals_job_factory.h',
'browser/net/view_http_cache_job_factory.cc',
'browser/net/view_http_cache_job_factory.h',
+ 'browser/notifications/notification_message_filter.cc',
+ 'browser/notifications/notification_message_filter.h',
+ 'browser/notifications/page_notification_delegate.cc',
+ 'browser/notifications/page_notification_delegate.h',
'browser/notification_service_impl.cc',
'browser/notification_service_impl.h',
'browser/power_monitor_message_broadcaster.cc',
@@ -828,24 +950,16 @@
'browser/profiler_controller_impl.h',
'browser/profiler_message_filter.cc',
'browser/profiler_message_filter.h',
- 'browser/push_messaging_message_filter.cc',
- 'browser/push_messaging_message_filter.h',
+ 'browser/push_messaging/push_messaging_message_filter.cc',
+ 'browser/push_messaging/push_messaging_message_filter.h',
+ 'browser/push_messaging/push_messaging_router.cc',
+ 'browser/push_messaging/push_messaging_router.h',
'browser/quota_dispatcher_host.cc',
'browser/quota_dispatcher_host.h',
'browser/renderer_data_memoizing_store.h',
'browser/renderer_host/clipboard_message_filter.cc',
'browser/renderer_host/clipboard_message_filter.h',
'browser/renderer_host/clipboard_message_filter_mac.mm',
- 'browser/renderer_host/compositing_iosurface_context_mac.h',
- 'browser/renderer_host/compositing_iosurface_context_mac.mm',
- 'browser/renderer_host/compositing_iosurface_layer_mac.h',
- 'browser/renderer_host/compositing_iosurface_layer_mac.mm',
- 'browser/renderer_host/compositing_iosurface_mac.h',
- 'browser/renderer_host/compositing_iosurface_mac.mm',
- 'browser/renderer_host/compositing_iosurface_shader_programs_mac.cc',
- 'browser/renderer_host/compositing_iosurface_shader_programs_mac.h',
- 'browser/renderer_host/compositing_iosurface_transformer_mac.cc',
- 'browser/renderer_host/compositing_iosurface_transformer_mac.h',
'browser/renderer_host/compositor_impl_android.cc',
'browser/renderer_host/compositor_impl_android.h',
'browser/renderer_host/compositor_resize_lock_aura.cc',
@@ -861,6 +975,8 @@
'browser/renderer_host/event_with_latency_info.h',
'browser/renderer_host/file_utilities_message_filter.cc',
'browser/renderer_host/file_utilities_message_filter.h',
+ 'browser/renderer_host/font_utils_linux.cc',
+ 'browser/renderer_host/font_utils_linux.h',
'browser/renderer_host/gamepad_browser_message_filter.cc',
'browser/renderer_host/gamepad_browser_message_filter.h',
'browser/renderer_host/gpu_message_filter.cc',
@@ -871,6 +987,8 @@
'browser/renderer_host/ime_adapter_android.h',
'browser/renderer_host/input/gesture_event_queue.cc',
'browser/renderer_host/input/gesture_event_queue.h',
+ 'browser/renderer_host/input/gesture_text_selector.cc',
+ 'browser/renderer_host/input/gesture_text_selector.h',
'browser/renderer_host/input/input_ack_handler.h',
'browser/renderer_host/input/input_router.h',
'browser/renderer_host/input/input_router_client.h',
@@ -882,6 +1000,8 @@
'browser/renderer_host/input/motion_event_android.h',
'browser/renderer_host/input/motion_event_web.cc',
'browser/renderer_host/input/motion_event_web.h',
+ 'browser/renderer_host/input/selection_event_type.h',
+ 'browser/renderer_host/input/selection_event_type_list.h',
'browser/renderer_host/input/synthetic_gesture.cc',
'browser/renderer_host/input/synthetic_gesture.h',
'browser/renderer_host/input/synthetic_gesture_controller.cc',
@@ -911,6 +1031,10 @@
'browser/renderer_host/input/touch_event_queue.h',
'browser/renderer_host/input/touch_action_filter.cc',
'browser/renderer_host/input/touch_action_filter.h',
+ 'browser/renderer_host/input/touch_handle.cc',
+ 'browser/renderer_host/input/touch_handle.h',
+ 'browser/renderer_host/input/touch_selection_controller.cc',
+ 'browser/renderer_host/input/touch_selection_controller.h',
'browser/renderer_host/input/touchpad_tap_suppression_controller.cc',
'browser/renderer_host/input/touchpad_tap_suppression_controller.h',
'browser/renderer_host/input/touchscreen_tap_suppression_controller.cc',
@@ -935,8 +1059,6 @@
'browser/renderer_host/media/audio_renderer_host.h',
'browser/renderer_host/media/audio_sync_reader.cc',
'browser/renderer_host/media/audio_sync_reader.h',
- 'browser/renderer_host/media/device_request_message_filter.cc',
- 'browser/renderer_host/media/device_request_message_filter.h',
'browser/renderer_host/media/media_capture_devices_impl.cc',
'browser/renderer_host/media/media_capture_devices_impl.h',
'browser/renderer_host/media/media_stream_dispatcher_host.cc',
@@ -969,15 +1091,12 @@
'browser/renderer_host/overscroll_controller.cc',
'browser/renderer_host/overscroll_controller.h',
'browser/renderer_host/overscroll_controller_delegate.h',
- 'browser/renderer_host/popup_menu_helper_mac.h',
- 'browser/renderer_host/popup_menu_helper_mac.mm',
'browser/renderer_host/render_message_filter.cc',
'browser/renderer_host/render_message_filter.h',
'browser/renderer_host/render_process_host_impl.cc',
'browser/renderer_host/render_process_host_impl.h',
'browser/renderer_host/render_sandbox_host_linux.cc',
'browser/renderer_host/render_sandbox_host_linux.h',
- 'browser/renderer_host/render_process_host_impl.h',
'browser/renderer_host/render_view_host_delegate.cc',
'browser/renderer_host/render_view_host_delegate.h',
'browser/renderer_host/render_view_host_delegate_view.h',
@@ -987,7 +1106,6 @@
'browser/renderer_host/render_view_host_impl.h',
'browser/renderer_host/render_widget_helper.cc',
'browser/renderer_host/render_widget_helper.h',
- 'browser/renderer_host/render_widget_helper_mac.mm',
'browser/renderer_host/render_widget_host_delegate.cc',
'browser/renderer_host/render_widget_host_delegate.h',
'browser/renderer_host/render_widget_host_impl.cc',
@@ -1004,18 +1122,14 @@
'browser/renderer_host/render_widget_host_view_mac_editcommand_helper.mm',
'browser/renderer_host/render_widget_host_view_mac.h',
'browser/renderer_host/render_widget_host_view_mac.mm',
+ 'browser/renderer_host/render_widget_resize_helper.cc',
+ 'browser/renderer_host/render_widget_resize_helper.h',
'browser/renderer_host/renderer_frame_manager.cc',
'browser/renderer_host/renderer_frame_manager.h',
'browser/renderer_host/sandbox_ipc_linux.cc',
'browser/renderer_host/sandbox_ipc_linux.h',
'browser/renderer_host/software_frame_manager.cc',
'browser/renderer_host/software_frame_manager.h',
- 'browser/renderer_host/software_layer_mac.mm',
- 'browser/renderer_host/software_layer_mac.h',
- 'browser/renderer_host/socket_stream_dispatcher_host.cc',
- 'browser/renderer_host/socket_stream_dispatcher_host.h',
- 'browser/renderer_host/socket_stream_host.cc',
- 'browser/renderer_host/socket_stream_host.h',
'browser/renderer_host/text_input_client_mac.h',
'browser/renderer_host/text_input_client_mac.mm',
'browser/renderer_host/text_input_client_message_filter.h',
@@ -1025,7 +1139,6 @@
'browser/renderer_host/web_input_event_aura.cc',
'browser/renderer_host/web_input_event_aura.h',
'browser/renderer_host/web_input_event_aurawin.cc',
- 'browser/renderer_host/web_input_event_aurax11.cc',
'browser/renderer_host/webmenurunner_mac.h',
'browser/renderer_host/webmenurunner_mac.mm',
'browser/renderer_host/websocket_dispatcher_host.cc',
@@ -1038,15 +1151,26 @@
'browser/resource_context_impl.h',
'browser/safe_util_win.cc',
'browser/safe_util_win.h',
- 'browser/screen_orientation/screen_orientation_dispatcher_host.cc',
- 'browser/screen_orientation/screen_orientation_dispatcher_host.h',
- 'browser/screen_orientation/screen_orientation_provider.h',
- 'browser/screen_orientation/screen_orientation_provider_android.h',
- 'browser/screen_orientation/screen_orientation_provider_android.cc',
+ 'browser/screen_orientation/screen_orientation_delegate_android.cc',
+ 'browser/screen_orientation/screen_orientation_delegate_android.h',
+ 'browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc',
+ 'browser/screen_orientation/screen_orientation_dispatcher_host_impl.h',
+ 'browser/screen_orientation/screen_orientation_message_filter_android.h',
+ 'browser/screen_orientation/screen_orientation_message_filter_android.cc',
'browser/service_worker/embedded_worker_instance.cc',
'browser/service_worker/embedded_worker_instance.h',
'browser/service_worker/embedded_worker_registry.cc',
'browser/service_worker/embedded_worker_registry.h',
+ 'browser/service_worker/service_worker_cache.cc',
+ 'browser/service_worker/service_worker_cache.h',
+ 'browser/service_worker/service_worker_cache_listener.cc',
+ 'browser/service_worker/service_worker_cache_listener.h',
+ 'browser/service_worker/service_worker_cache_quota_client.cc',
+ 'browser/service_worker/service_worker_cache_quota_client.h',
+ 'browser/service_worker/service_worker_cache_storage.cc',
+ 'browser/service_worker/service_worker_cache_storage.h',
+ 'browser/service_worker/service_worker_cache_storage_manager.cc',
+ 'browser/service_worker/service_worker_cache_storage_manager.h',
'browser/service_worker/service_worker_context_core.cc',
'browser/service_worker/service_worker_context_core.h',
'browser/service_worker/service_worker_context_observer.h',
@@ -1058,6 +1182,8 @@
'browser/service_worker/service_worker_controllee_request_handler.h',
'browser/service_worker/service_worker_database.cc',
'browser/service_worker/service_worker_database.h',
+ 'browser/service_worker/service_worker_database_task_manager.cc',
+ 'browser/service_worker/service_worker_database_task_manager.h',
'browser/service_worker/service_worker_disk_cache.cc',
'browser/service_worker/service_worker_disk_cache.h',
'browser/service_worker/service_worker_dispatcher_host.cc',
@@ -1066,18 +1192,20 @@
'browser/service_worker/service_worker_fetch_dispatcher.h',
'browser/service_worker/service_worker_handle.cc',
'browser/service_worker/service_worker_handle.h',
- 'browser/service_worker/service_worker_histograms.cc',
- 'browser/service_worker/service_worker_histograms.h',
'browser/service_worker/service_worker_info.cc',
'browser/service_worker/service_worker_info.h',
'browser/service_worker/service_worker_internals_ui.cc',
'browser/service_worker/service_worker_internals_ui.h',
'browser/service_worker/service_worker_job_coordinator.cc',
'browser/service_worker/service_worker_job_coordinator.h',
+ 'browser/service_worker/service_worker_metrics.cc',
+ 'browser/service_worker/service_worker_metrics.h',
'browser/service_worker/service_worker_process_manager.cc',
'browser/service_worker/service_worker_process_manager.h',
'browser/service_worker/service_worker_provider_host.cc',
'browser/service_worker/service_worker_provider_host.h',
+ 'browser/service_worker/service_worker_quota_client.cc',
+ 'browser/service_worker/service_worker_quota_client.h',
'browser/service_worker/service_worker_read_from_cache_job.cc',
'browser/service_worker/service_worker_read_from_cache_job.h',
'browser/service_worker/service_worker_register_job_base.h',
@@ -1085,6 +1213,8 @@
'browser/service_worker/service_worker_register_job.h',
'browser/service_worker/service_worker_registration.cc',
'browser/service_worker/service_worker_registration.h',
+ 'browser/service_worker/service_worker_registration_handle.cc',
+ 'browser/service_worker/service_worker_registration_handle.h',
'browser/service_worker/service_worker_registration_status.cc',
'browser/service_worker/service_worker_registration_status.h',
'browser/service_worker/service_worker_request_handler.cc',
@@ -1111,6 +1241,10 @@
'browser/shared_worker/shared_worker_message_filter.h',
'browser/shared_worker/shared_worker_service_impl.cc',
'browser/shared_worker/shared_worker_service_impl.h',
+ 'browser/shared_worker/worker_document_set.cc',
+ 'browser/shared_worker/worker_document_set.h',
+ 'browser/shared_worker/worker_storage_partition.cc',
+ 'browser/shared_worker/worker_storage_partition.h',
'browser/signed_certificate_timestamp_store_impl.cc',
'browser/signed_certificate_timestamp_store_impl.h',
'browser/site_instance_impl.cc',
@@ -1148,8 +1282,6 @@
'browser/ssl/ssl_client_auth_handler.h',
'browser/ssl/ssl_error_handler.cc',
'browser/ssl/ssl_error_handler.h',
- 'browser/ssl/ssl_host_state.cc',
- 'browser/ssl/ssl_host_state.h',
'browser/ssl/ssl_manager.cc',
'browser/ssl/ssl_manager.h',
'browser/ssl/ssl_policy_backend.cc',
@@ -1194,10 +1326,14 @@
'browser/tracing/trace_message_filter.h',
'browser/tracing/etw_system_event_consumer_win.cc',
'browser/tracing/etw_system_event_consumer_win.h',
+ 'browser/tracing/trace_uploader.cc',
+ 'browser/tracing/trace_uploader.h',
'browser/tracing/tracing_controller_impl.cc',
'browser/tracing/tracing_controller_impl.h',
'browser/tracing/tracing_ui.cc',
'browser/tracing/tracing_ui.h',
+ 'browser/transition_request_manager.cc',
+ 'browser/transition_request_manager.h',
'browser/udev_linux.cc',
'browser/udev_linux.h',
'browser/user_metrics.cc',
@@ -1257,16 +1393,6 @@
'browser/webui/web_ui_impl.cc',
'browser/webui/web_ui_impl.h',
'browser/webui/web_ui_message_handler.cc',
- 'browser/worker_host/worker_document_set.cc',
- 'browser/worker_host/worker_document_set.h',
- 'browser/worker_host/worker_message_filter.cc',
- 'browser/worker_host/worker_message_filter.h',
- 'browser/worker_host/worker_process_host.cc',
- 'browser/worker_host/worker_process_host.h',
- 'browser/worker_host/worker_service_impl.cc',
- 'browser/worker_host/worker_service_impl.h',
- 'browser/worker_host/worker_storage_partition.cc',
- 'browser/worker_host/worker_storage_partition.h',
'browser/zygote_host/zygote_host_impl_linux.cc',
'browser/zygote_host/zygote_host_impl_linux.h',
'zygote/zygote_linux.cc',
@@ -1277,34 +1403,31 @@
'<(SHARED_INTERMEDIATE_DIR)/webkit/grit/devtools_resources_map.cc',
'<(SHARED_INTERMEDIATE_DIR)/webkit/grit/devtools_resources_map.h',
'<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/grit/tracing_resources.h',
- '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/grit/webui_resources_map.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/resources/grit/webui_resources_map.cc',
# These files are generated by devtools_protocol_constants_generator.py.
'<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/devtools_protocol_constants.cc',
'<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/devtools_protocol_constants.h',
+ # These files are generated by devtools_protocol_handler_generator.py.
+ '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_handler_impl.cc',
+ '<(SHARED_INTERMEDIATE_DIR)/content/browser/devtools/protocol/devtools_protocol_handler_impl.h',
],
'android_browser_sources': [
- 'browser/renderer_host/java/gin_java_bound_object.cc',
- 'browser/renderer_host/java/gin_java_bound_object.h',
- 'browser/renderer_host/java/gin_java_bound_object_delegate.cc',
- 'browser/renderer_host/java/gin_java_bound_object_delegate.h',
- 'browser/renderer_host/java/gin_java_method_invocation_helper.cc',
- 'browser/renderer_host/java/gin_java_method_invocation_helper.h',
- 'browser/renderer_host/java/gin_java_script_to_java_types_coercion.cc',
- 'browser/renderer_host/java/gin_java_script_to_java_types_coercion.h',
- 'browser/renderer_host/java/java_bound_object.cc',
- 'browser/renderer_host/java/java_bound_object.h',
- 'browser/renderer_host/java/java_bridge_channel_host.cc',
- 'browser/renderer_host/java/java_bridge_channel_host.h',
- 'browser/renderer_host/java/java_bridge_dispatcher_host.cc',
- 'browser/renderer_host/java/java_bridge_dispatcher_host.h',
- 'browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc',
- 'browser/renderer_host/java/java_bridge_dispatcher_host_manager.h',
- 'browser/renderer_host/java/java_method.cc',
- 'browser/renderer_host/java/java_method.h',
- 'browser/renderer_host/java/java_type.cc',
- 'browser/renderer_host/java/java_type.h',
- 'browser/renderer_host/java/jni_helper.cc',
- 'browser/renderer_host/java/jni_helper.h',
+ 'browser/android/java/gin_java_bound_object.cc',
+ 'browser/android/java/gin_java_bound_object.h',
+ 'browser/android/java/gin_java_bound_object_delegate.cc',
+ 'browser/android/java/gin_java_bound_object_delegate.h',
+ 'browser/android/java/gin_java_bridge_dispatcher_host.cc',
+ 'browser/android/java/gin_java_bridge_dispatcher_host.h',
+ 'browser/android/java/gin_java_method_invocation_helper.cc',
+ 'browser/android/java/gin_java_method_invocation_helper.h',
+ 'browser/android/java/gin_java_script_to_java_types_coercion.cc',
+ 'browser/android/java/gin_java_script_to_java_types_coercion.h',
+ 'browser/android/java/java_method.cc',
+ 'browser/android/java/java_method.h',
+ 'browser/android/java/java_type.cc',
+ 'browser/android/java/java_type.h',
+ 'browser/android/java/jni_helper.cc',
+ 'browser/android/java/jni_helper.h',
],
'webrtc_browser_sources': [
'browser/media/webrtc_internals.cc',
@@ -1332,20 +1455,28 @@
'browser/renderer_host/p2p/socket_dispatcher_host.h',
],
'compositor_browser_sources': [
+ 'browser/compositor/browser_compositor_ca_layer_tree_mac.mm',
+ 'browser/compositor/browser_compositor_ca_layer_tree_mac.h',
'browser/compositor/browser_compositor_output_surface.cc',
'browser/compositor/browser_compositor_output_surface.h',
'browser/compositor/browser_compositor_output_surface_proxy.cc',
'browser/compositor/browser_compositor_output_surface_proxy.h',
'browser/compositor/browser_compositor_view_mac.mm',
'browser/compositor/browser_compositor_view_mac.h',
+ 'browser/compositor/buffer_queue.cc',
+ 'browser/compositor/buffer_queue.h',
'browser/compositor/delegated_frame_host.cc',
'browser/compositor/delegated_frame_host.h',
'browser/compositor/gpu_process_transport_factory.cc',
'browser/compositor/gpu_process_transport_factory.h',
'browser/compositor/image_transport_factory.cc',
'browser/compositor/image_transport_factory.h',
- 'browser/compositor/no_transport_image_transport_factory.cc',
- 'browser/compositor/no_transport_image_transport_factory.h',
+ 'browser/compositor/io_surface_context_mac.h',
+ 'browser/compositor/io_surface_context_mac.mm',
+ 'browser/compositor/io_surface_layer_mac.h',
+ 'browser/compositor/io_surface_layer_mac.mm',
+ 'browser/compositor/io_surface_texture_mac.h',
+ 'browser/compositor/io_surface_texture_mac.mm',
'browser/compositor/onscreen_display_client.cc',
'browser/compositor/onscreen_display_client.h',
'browser/compositor/overlay_candidate_validator_ozone.cc',
@@ -1356,8 +1487,12 @@
'browser/compositor/reflector_impl.h',
'browser/compositor/resize_lock.cc',
'browser/compositor/resize_lock.h',
+ 'browser/compositor/software_layer_mac.mm',
+ 'browser/compositor/software_layer_mac.h',
'browser/compositor/gpu_browser_compositor_output_surface.cc',
'browser/compositor/gpu_browser_compositor_output_surface.h',
+ 'browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc',
+ 'browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h',
'browser/compositor/software_browser_compositor_output_surface.cc',
'browser/compositor/software_browser_compositor_output_surface.h',
'browser/compositor/software_output_device_mac.mm',
@@ -1375,6 +1510,8 @@
'plugin_browser_sources': [
'browser/pepper_flash_settings_helper_impl.cc',
'browser/pepper_flash_settings_helper_impl.h',
+ 'browser/plugin_content_origin_whitelist.cc',
+ 'browser/plugin_content_origin_whitelist.h',
'browser/plugin_data_remover_impl.cc',
'browser/plugin_data_remover_impl.h',
'browser/plugin_loader_posix.cc',
@@ -1429,6 +1566,11 @@
'browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h',
'browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc',
'browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h',
+ 'browser/renderer_host/pepper/pepper_truetype_font.h',
+ 'browser/renderer_host/pepper/pepper_truetype_font_android.cc',
+ 'browser/renderer_host/pepper/pepper_truetype_font_host.cc',
+ 'browser/renderer_host/pepper/pepper_truetype_font_host.h',
+ 'browser/renderer_host/pepper/pepper_truetype_font_linux.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list_android.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list.h',
'browser/renderer_host/pepper/pepper_truetype_font_list_host.cc',
@@ -1437,6 +1579,8 @@
'browser/renderer_host/pepper/pepper_truetype_font_list_ozone.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list_pango.cc',
'browser/renderer_host/pepper/pepper_truetype_font_list_win.cc',
+ 'browser/renderer_host/pepper/pepper_truetype_font_mac.mm',
+ 'browser/renderer_host/pepper/pepper_truetype_font_win.cc',
'browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc',
'browser/renderer_host/pepper/pepper_udp_socket_message_filter.h',
'browser/renderer_host/pepper/quota_reservation.cc',
@@ -1466,7 +1610,9 @@
]
}, { # os != "win"
'sources': [
- 'browser/power_profiler/power_data_provider_dummy.cc'
+ 'browser/power_profiler/power_data_provider_dummy.cc',
+ 'browser/file_descriptor_info_impl.h',
+ 'browser/file_descriptor_info_impl.cc',
]
}],
['OS!="win" and OS!="mac" and OS!="android" and (OS!="linux" or use_udev==0)', {
@@ -1502,25 +1648,25 @@
],
}, { # OS!="ios"
'dependencies': [
+ 'app/resources/content_resources.gyp:content_resources',
+ 'app/strings/content_strings.gyp:content_strings',
'browser/devtools/devtools_resources.gyp:devtools_resources',
+ 'browser/devtools/devtools.gyp:devtools_protocol_handler',
'content_common_mojo_bindings',
'../cc/cc.gyp:cc',
'../cc/cc.gyp:cc_surfaces',
- '../mojo/mojo.gyp:mojo_cpp_bindings',
- '../mojo/mojo.gyp:mojo_js_bindings',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_js_bindings',
'../net/net.gyp:http_server',
+ '../storage/storage_browser.gyp:storage',
+ '../storage/storage_common.gyp:storage_common',
+ '../third_party/angle/src/angle.gyp:commit_id',
'../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
'../ui/surface/surface.gyp:surface',
- '../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/storage_browser.gyp:webkit_storage_browser',
- '../webkit/storage_common.gyp:webkit_storage_common',
- '../webkit/webkit_resources.gyp:webkit_resources',
- '../webkit/webkit_resources.gyp:webkit_strings',
- '../third_party/angle/src/build_angle.gyp:commit_id',
],
}],
- ['enable_printing!=0', {
+ ['enable_basic_printing==1 or enable_print_preview==1', {
'dependencies': [
'../printing/printing.gyp:printing',
],
@@ -1538,7 +1684,13 @@
['OS!="android" and OS!="ios"', {
'dependencies': [
'browser/tracing/tracing_resources.gyp:tracing_resources',
+ '../ui/compositor/compositor.gyp:compositor',
],
+ 'sources': [ '<@(compositor_browser_sources)' ],
+ }, {
+ 'sources/': [
+ ['exclude', '^public/browser/context_factory.h'],
+ ]
}],
['OS!="ios"', {
'dependencies': [
@@ -1647,24 +1799,24 @@
['OS=="android"', {
'dependencies': [
'../media/media.gyp:media',
+ '../mojo/mojo_base.gyp:libmojo_system_java',
'content.gyp:content_jni_headers',
],
+ 'defines': ['APPCACHE_USE_SIMPLE_CACHE'],
+ 'direct_dependent_settings': {
+ 'defines': ['APPCACHE_USE_SIMPLE_CACHE'],
+ },
'link_settings': {
'libraries': [
'-ljnigraphics',
],
},
'sources/': [
- ['exclude', '^browser/battery_status/battery_status_manager_default\\.cc$'],
['exclude', '^browser/device_sensors/data_fetcher_shared_memory_default\\.cc$'],
['exclude', '^browser/geolocation/network_location_provider\\.(cc|h)$'],
['exclude', '^browser/geolocation/network_location_request\\.(cc|h)$'],
+ ['exclude', '^browser/tracing/trace_uploader\\.(cc|h)$'],
['exclude', '^browser/tracing/tracing_ui\\.(cc|h)$'],
- ['exclude', '^browser/speech/'],
- ['include', '^browser/speech/speech_recognition_dispatcher_host\\.(cc|h)$'],
- ['include', '^browser/speech/speech_recognition_manager_impl\\.(cc|h)$'],
- ['include', '^browser/speech/speech_recognizer\\.h$'],
- ['include', '^browser/speech/speech_recognizer_impl_android\\.(cc|h)$'],
],
'sources': [
'<@(android_browser_sources)',
@@ -1726,16 +1878,6 @@
['exclude', '^browser/renderer_host/ui_events_helper.h'],
],
}],
- ['use_aura==1 or OS=="mac"', {
- 'dependencies': [
- '../ui/compositor/compositor.gyp:compositor',
- ],
- 'sources': [ '<@(compositor_browser_sources)' ],
- }, {
- 'sources/': [
- ['exclude', '^public/browser/context_factory.h'],
- ]
- }],
['enable_plugins==1', {
'dependencies': [
'../ppapi/ppapi_internal.gyp:ppapi_ipc',
@@ -1745,12 +1887,21 @@
'<@(plugin_browser_sources)',
],
}],
- ['input_speech==1', {
+ ['enable_web_speech==1', {
'dependencies': [
'../third_party/flac/flac.gyp:libflac',
'../third_party/speex/speex.gyp:libspeex',
],
}],
+ ['enable_web_speech==0 and OS=="android"', {
+ 'sources/': [
+ ['exclude', '^browser/speech/'],
+ ['include', '^browser/speech/speech_recognition_dispatcher_host\\.(cc|h)$'],
+ ['include', '^browser/speech/speech_recognition_manager_impl\\.(cc|h)$'],
+ ['include', '^browser/speech/speech_recognizer\\.h$'],
+ ['include', '^browser/speech/speech_recognizer_impl_android\\.(cc|h)$'],
+ ],
+ }],
['OS == "win"', {
'sources!': [
'browser/geolocation/empty_wifi_data_provider.cc',
diff --git a/chromium/content/content_browsertests.isolate b/chromium/content/content_browsertests.isolate
index 87c8da4c87a..53a53fc317a 100644
--- a/chromium/content/content_browsertests.isolate
+++ b/chromium/content/content_browsertests.isolate
@@ -5,14 +5,29 @@
'conditions': [
['OS=="android"', {
'variables': {
- 'isolate_dependency_tracked': [
+ 'files': [
'<(PRODUCT_DIR)/content_shell/assets/content_shell.pak',
],
},
}],
+ ['chromeos==1', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/content_shell.pak',
+ ],
+ },
+ }],
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/content_shell.pak',
+ ],
+ },
+ }],
['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
- 'isolate_dependency_untracked': [
+ 'files': [
+ '../media/test/data/',
'../net/data/',
'test/data/',
],
@@ -25,45 +40,47 @@
'<(PRODUCT_DIR)',
'<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
'--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
],
- 'isolate_dependency_tracked': [
+ 'files': [
'../testing/xvfb.py',
'<(PRODUCT_DIR)/content_shell.pak',
- '<(PRODUCT_DIR)/fonts.conf',
- '<(PRODUCT_DIR)/libclearkeycdm.so',
- '<(PRODUCT_DIR)/libclearkeycdmadapter.so',
'<(PRODUCT_DIR)/libffmpegsumo.so',
- '<(PRODUCT_DIR)/plugins/libtest_netscape_plugin.so',
+ '<(PRODUCT_DIR)/libosmesa.so',
+ '<(PRODUCT_DIR)/libppapi_tests.so',
],
},
}],
- ['OS=="linux" or OS=="mac" or OS=="win"', {
+ ['OS=="linux" and use_ozone==0', {
'variables': {
- 'isolate_dependency_tracked': [
- '../testing/test_env.py',
- '<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
+ 'files': [
+ '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
],
- 'isolate_dependency_untracked': [
+ },
+ }],
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'files': [
'../net/tools/testserver/',
- '../third_party/WebKit/Tools/Scripts/',
- '../third_party/lighttpd/',
+ '../ppapi/tests/test_case.html',
+ '../ppapi/tests/test_page.css',
+ '../testing/test_env.py',
'../third_party/pyftpdlib/',
'../third_party/pywebsocket/',
'../third_party/tlslite/',
+ '<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
],
},
}],
['OS=="mac"', {
'variables': {
- 'isolate_dependency_tracked': [
- '<(PRODUCT_DIR)/clearkeycdmadapter.plugin',
- '<(PRODUCT_DIR)/content_resources.pak',
- '<(PRODUCT_DIR)/ffmpegsumo.so',
- '<(PRODUCT_DIR)/plugins/TestNestscapePlugin.plugin',
- '<(PRODUCT_DIR)/plugins/npapi_test_plugin.plugin',
- ],
- 'isolate_dependency_untracked': [
+ 'files': [
'<(PRODUCT_DIR)/Content Shell.app/',
+ '<(PRODUCT_DIR)/ffmpegsumo.so',
+ '<(PRODUCT_DIR)/plugins/npapi_test_plugin.plugin/',
+ '<(PRODUCT_DIR)/plugins/test_netscape_plugin.plugin/',
+ '<(PRODUCT_DIR)/ppapi_tests.plugin/Contents/MacOS/ppapi_tests',
],
},
}],
@@ -73,21 +90,40 @@
'../testing/test_env.py',
'<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
'--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
],
},
}],
['OS=="win"', {
'variables': {
- 'isolate_dependency_tracked': [
- '<(PRODUCT_DIR)/ffmpegsumo.dll',
- '<(PRODUCT_DIR)/chrome_100_percent.pak',
- '<(PRODUCT_DIR)/clearkeycdm.dll',
- '<(PRODUCT_DIR)/clearkeycdmadapter.dll',
+ 'files': [
'<(PRODUCT_DIR)/content_shell.pak',
+ '<(PRODUCT_DIR)/ffmpegsumo.dll',
+ '<(PRODUCT_DIR)/osmesa.dll',
'<(PRODUCT_DIR)/plugins/np_test_netscape_plugin.dll',
'<(PRODUCT_DIR)/plugins/npapi_test_plugin.dll',
+ '<(PRODUCT_DIR)/ppapi_tests.dll',
],
},
}],
+ ['OS=="win" and target_arch=="ia32"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/wow_helper.exe',
+ ],
+ },
+ }],
+ ['OS=="win" and (fastbuild==0 or fastbuild==1)', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/content_browsertests.exe.pdb',
+ ],
+ },
+ }],
+ ],
+ 'includes': [
+ '../base/base.isolate',
+ '../gin/v8.isolate',
],
}
diff --git a/chromium/content/content_child.gypi b/chromium/content/content_child.gypi
index 3e45b0c9099..c51317f3c76 100644
--- a/chromium/content/content_child.gypi
+++ b/chromium/content/content_child.gypi
@@ -6,8 +6,9 @@
'dependencies': [
'../base/base.gyp:base',
'../components/tracing.gyp:tracing',
- '../mojo/mojo.gyp:mojo_environment_chromium',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/mojo_base.gyp:mojo_common_lib',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
'../skia/skia.gyp:skia',
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
@@ -36,12 +37,16 @@
'child/appcache/web_application_cache_host_impl.cc',
'child/appcache/web_application_cache_host_impl.h',
'child/assert_matching_enums.cc',
- 'child/blink_glue.cc',
- 'child/blink_glue.h',
'child/blink_platform_impl.cc',
'child/blink_platform_impl.h',
+ 'child/bluetooth/web_bluetooth_impl.cc',
+ 'child/bluetooth/web_bluetooth_impl.h',
'child/browser_font_resource_trusted.cc',
'child/browser_font_resource_trusted.h',
+ 'child/child_discardable_shared_memory_manager.cc',
+ 'child/child_discardable_shared_memory_manager.h',
+ 'child/child_gpu_memory_buffer_manager.cc',
+ 'child/child_gpu_memory_buffer_manager.h',
'child/child_histogram_message_filter.cc',
'child/child_histogram_message_filter.h',
'child/child_message_filter.cc',
@@ -60,6 +65,8 @@
'child/database_util.h',
'child/db_message_filter.cc',
'child/db_message_filter.h',
+ 'child/file_info_util.cc',
+ 'child/file_info_util.h',
'child/fileapi/file_system_dispatcher.cc',
'child/fileapi/file_system_dispatcher.h',
'child/fileapi/webfilesystem_impl.cc',
@@ -68,12 +75,14 @@
'child/fileapi/webfilewriter_base.h',
'child/fileapi/webfilewriter_impl.cc',
'child/fileapi/webfilewriter_impl.h',
- 'child/fling_animator_impl_android.cc',
- 'child/fling_animator_impl_android.h',
- 'child/fling_curve_configuration.cc',
- 'child/fling_curve_configuration.h',
'child/ftp_directory_listing_response_delegate.cc',
'child/ftp_directory_listing_response_delegate.h',
+ 'child/geofencing/geofencing_dispatcher.cc',
+ 'child/geofencing/geofencing_dispatcher.h',
+ 'child/geofencing/geofencing_message_filter.cc',
+ 'child/geofencing/geofencing_message_filter.h',
+ 'child/geofencing/web_geofencing_provider_impl.cc',
+ 'child/geofencing/web_geofencing_provider_impl.h',
'child/image_decoder.cc',
'child/image_decoder.h',
'child/indexed_db/indexed_db_dispatcher.cc',
@@ -90,6 +99,12 @@
'child/indexed_db/webidbfactory_impl.h',
'child/mojo/mojo_application.cc',
'child/mojo/mojo_application.h',
+ 'child/multipart_response_delegate.cc',
+ 'child/multipart_response_delegate.h',
+ 'child/notifications/notification_dispatcher.cc',
+ 'child/notifications/notification_dispatcher.h',
+ 'child/notifications/notification_manager.cc',
+ 'child/notifications/notification_manager.h',
'child/npapi/np_channel_base.cc',
'child/npapi/np_channel_base.h',
'child/npapi/npobject_base.h',
@@ -149,61 +164,73 @@
'child/request_info.h',
'child/resource_dispatcher.cc',
'child/resource_dispatcher.h',
+ 'child/resource_loader_bridge.cc',
+ 'child/resource_loader_bridge.h',
'child/runtime_features.cc',
'child/runtime_features.h',
'child/scoped_child_process_reference.cc',
'child/scoped_child_process_reference.h',
- 'child/service_worker/service_worker_handle_reference.cc',
- 'child/service_worker/service_worker_handle_reference.h',
'child/service_worker/service_worker_dispatcher.cc',
'child/service_worker/service_worker_dispatcher.h',
+ 'child/service_worker/service_worker_handle_reference.cc',
+ 'child/service_worker/service_worker_handle_reference.h',
'child/service_worker/service_worker_message_filter.cc',
'child/service_worker/service_worker_message_filter.h',
'child/service_worker/service_worker_network_provider.cc',
'child/service_worker/service_worker_network_provider.h',
'child/service_worker/service_worker_provider_context.cc',
'child/service_worker/service_worker_provider_context.h',
+ 'child/service_worker/service_worker_registration_handle_reference.cc',
+ 'child/service_worker/service_worker_registration_handle_reference.h',
'child/service_worker/web_service_worker_impl.cc',
'child/service_worker/web_service_worker_impl.h',
'child/service_worker/web_service_worker_provider_impl.cc',
'child/service_worker/web_service_worker_provider_impl.h',
+ 'child/service_worker/web_service_worker_registration_impl.cc',
+ 'child/service_worker/web_service_worker_registration_impl.h',
'child/shared_worker_devtools_agent.cc',
'child/shared_worker_devtools_agent.h',
'child/simple_webmimeregistry_impl.cc',
'child/simple_webmimeregistry_impl.h',
'child/site_isolation_policy.cc',
'child/site_isolation_policy.h',
- 'child/socket_stream_dispatcher.cc',
- 'child/socket_stream_dispatcher.h',
'child/sync_load_response.cc',
'child/sync_load_response.h',
'child/thread_safe_sender.cc',
'child/thread_safe_sender.h',
- 'child/touch_fling_gesture_curve.cc',
- 'child/touch_fling_gesture_curve.h',
+ 'child/threaded_data_provider.cc',
+ 'child/threaded_data_provider.h',
+ 'child/web_data_consumer_handle_impl.cc',
+ 'child/web_data_consumer_handle_impl.h',
'child/web_database_observer_impl.cc',
'child/web_database_observer_impl.h',
'child/web_discardable_memory_impl.cc',
'child/web_discardable_memory_impl.h',
- 'child/web_socket_stream_handle_bridge.h',
- 'child/web_socket_stream_handle_delegate.h',
- 'child/web_socket_stream_handle_impl.cc',
- 'child/web_socket_stream_handle_impl.h',
+ 'child/web_gesture_curve_impl.cc',
+ 'child/web_gesture_curve_impl.h',
'child/web_url_loader_impl.cc',
'child/web_url_loader_impl.h',
+ 'child/web_url_request_util.cc',
+ 'child/web_url_request_util.h',
'child/webblobregistry_impl.cc',
'child/webblobregistry_impl.h',
+ 'child/webcrypto/algorithm_dispatch.cc',
+ 'child/webcrypto/algorithm_dispatch.h',
+ 'child/webcrypto/algorithm_implementation.cc',
+ 'child/webcrypto/algorithm_implementation.h',
+ 'child/webcrypto/algorithm_registry.cc',
+ 'child/webcrypto/algorithm_registry.h',
'child/webcrypto/crypto_data.cc',
'child/webcrypto/crypto_data.h',
+ 'child/webcrypto/generate_key_result.cc',
+ 'child/webcrypto/generate_key_result.h',
'child/webcrypto/jwk.cc',
'child/webcrypto/jwk.h',
'child/webcrypto/platform_crypto.h',
- 'child/webcrypto/platform_crypto_nss.cc',
- 'child/webcrypto/platform_crypto_openssl.cc',
- 'child/webcrypto/shared_crypto.cc',
- 'child/webcrypto/shared_crypto.h',
'child/webcrypto/status.cc',
'child/webcrypto/status.h',
+ 'child/webcrypto/structured_clone.cc',
+ 'child/webcrypto/structured_clone.h',
'child/webcrypto/webcrypto_impl.cc',
'child/webcrypto/webcrypto_impl.h',
'child/webcrypto/webcrypto_util.cc',
@@ -214,8 +241,6 @@
'child/webfileutilities_impl.h',
'child/webmessageportchannel_impl.cc',
'child/webmessageportchannel_impl.h',
- 'child/threaded_data_provider.cc',
- 'child/threaded_data_provider.h',
'child/websocket_bridge.cc',
'child/websocket_bridge.h',
'child/websocket_dispatcher.cc',
@@ -224,15 +249,58 @@
'child/webthemeengine_impl_android.h',
'child/webthemeengine_impl_default.cc',
'child/webthemeengine_impl_default.h',
- 'child/webthemeengine_impl_mac.cc',
'child/webthemeengine_impl_mac.h',
'child/webthread_impl.cc',
'child/webthread_impl.h',
+ 'child/weburlresponse_extradata_impl.cc',
+ 'child/weburlresponse_extradata_impl.h',
'child/worker_task_runner.cc',
'child/worker_task_runner.h',
'child/worker_thread_task_runner.cc',
'child/worker_thread_task_runner.h',
],
+ 'webcrypto_nss_sources': [
+ 'child/webcrypto/nss/aes_cbc_nss.cc',
+ 'child/webcrypto/nss/aes_gcm_nss.cc',
+ 'child/webcrypto/nss/aes_key_nss.cc',
+ 'child/webcrypto/nss/aes_key_nss.h',
+ 'child/webcrypto/nss/aes_kw_nss.cc',
+ 'child/webcrypto/nss/hmac_nss.cc',
+ 'child/webcrypto/nss/key_nss.cc',
+ 'child/webcrypto/nss/key_nss.h',
+ 'child/webcrypto/nss/rsa_key_nss.cc',
+ 'child/webcrypto/nss/rsa_key_nss.h',
+ 'child/webcrypto/nss/rsa_oaep_nss.cc',
+ 'child/webcrypto/nss/rsa_ssa_nss.cc',
+ 'child/webcrypto/nss/sha_nss.cc',
+ 'child/webcrypto/nss/sym_key_nss.cc',
+ 'child/webcrypto/nss/sym_key_nss.h',
+ 'child/webcrypto/nss/util_nss.cc',
+ 'child/webcrypto/nss/util_nss.h',
+ ],
+ 'webcrypto_openssl_sources': [
+ 'child/webcrypto/openssl/aes_cbc_openssl.cc',
+ 'child/webcrypto/openssl/aes_ctr_openssl.cc',
+ 'child/webcrypto/openssl/aes_gcm_openssl.cc',
+ 'child/webcrypto/openssl/aes_key_openssl.cc',
+ 'child/webcrypto/openssl/aes_key_openssl.h',
+ 'child/webcrypto/openssl/aes_kw_openssl.cc',
+ 'child/webcrypto/openssl/hmac_openssl.cc',
+ 'child/webcrypto/openssl/key_openssl.cc',
+ 'child/webcrypto/openssl/key_openssl.h',
+ 'child/webcrypto/openssl/rsa_key_openssl.cc',
+ 'child/webcrypto/openssl/rsa_key_openssl.h',
+ 'child/webcrypto/openssl/rsa_oaep_openssl.cc',
+ 'child/webcrypto/openssl/rsa_pss_openssl.cc',
+ 'child/webcrypto/openssl/rsa_sign_openssl.cc',
+ 'child/webcrypto/openssl/rsa_sign_openssl.h',
+ 'child/webcrypto/openssl/rsa_ssa_openssl.cc',
+ 'child/webcrypto/openssl/sha_openssl.cc',
+ 'child/webcrypto/openssl/sym_key_openssl.cc',
+ 'child/webcrypto/openssl/sym_key_openssl.h',
+ 'child/webcrypto/openssl/util_openssl.cc',
+ 'child/webcrypto/openssl/util_openssl.h',
+ ],
},
'sources': [
'<@(public_child_sources)',
@@ -269,11 +337,12 @@
],
}, { # OS!="ios"
'dependencies': [
+ 'app/resources/content_resources.gyp:content_resources',
+ 'app/strings/content_strings.gyp:content_strings',
+ '../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
+ '../third_party/WebKit/public/blink_resources.gyp:blink_resources',
'../third_party/npapi/npapi.gyp:npapi',
- '../webkit/child/webkit_child.gyp:webkit_child',
- '../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/webkit_resources.gyp:webkit_resources',
],
}],
['use_aura==1', {
@@ -287,15 +356,15 @@
],
}],
['use_openssl==1', {
- 'sources!': [
- 'child/webcrypto/platform_crypto_nss.cc',
+ 'sources': [
+ '<@(webcrypto_openssl_sources)',
],
'dependencies': [
- '../third_party/openssl/openssl.gyp:openssl',
+ '../third_party/boringssl/boringssl.gyp:boringssl',
],
}, {
- 'sources!': [
- 'child/webcrypto/platform_crypto_openssl.cc',
+ 'sources': [
+ '<@(webcrypto_nss_sources)',
],
'conditions': [
['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
diff --git a/chromium/content/content_common.gypi b/chromium/content/content_common.gypi
index e4f4921d1c5..6d9a28d1493 100644
--- a/chromium/content/content_common.gypi
+++ b/chromium/content/content_common.gypi
@@ -11,12 +11,12 @@
'../skia/skia.gyp:skia',
'../third_party/WebKit/public/blink_headers.gyp:blink_headers',
'../third_party/icu/icu.gyp:icuuc',
- '../third_party/libjingle/libjingle.gyp:libjingle',
'../ui/accessibility/accessibility.gyp:accessibility',
'../ui/base/ui_base.gyp:ui_base',
'../ui/events/ipc/events_ipc.gyp:events_ipc',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'../url/url.gyp:url_lib',
],
@@ -32,6 +32,7 @@
],
'variables': {
'public_common_sources': [
+ 'public/common/appcache_info.h',
'public/common/bindings_policy.h',
'public/common/child_process_host.h',
'public/common/child_process_host_delegate.cc',
@@ -56,9 +57,10 @@
'public/common/context_menu_params.h',
'public/common/drop_data.cc',
'public/common/drop_data.h',
- 'public/common/eme_codec.h',
'public/common/favicon_url.cc',
'public/common/favicon_url.h',
+ 'public/common/file_chooser_file_info.cc',
+ 'public/common/file_chooser_file_info.h',
'public/common/file_chooser_params.cc',
'public/common/file_chooser_params.h',
'public/common/frame_navigate_params.cc',
@@ -70,6 +72,8 @@
'public/common/injection_test_mac.h',
'public/common/injection_test_win.h',
'public/common/javascript_message_type.h',
+ 'public/common/manifest.cc',
+ 'public/common/manifest.h',
'public/common/main_function_params.h',
'public/common/media_stream_request.cc',
'public/common/media_stream_request.h',
@@ -77,22 +81,26 @@
'public/common/menu_item.h',
'public/common/page_state.cc',
'public/common/page_state.h',
- 'public/common/page_transition_types.cc',
- 'public/common/page_transition_types.h',
- 'public/common/page_transition_types_list.h',
'public/common/page_type.h',
'public/common/page_zoom.h',
'public/common/pepper_plugin_info.cc',
'public/common/pepper_plugin_info.h',
'public/common/process_type.h',
+ 'public/common/push_messaging_status.cc',
+ 'public/common/push_messaging_status.h',
'public/common/referrer.h',
'public/common/renderer_preferences.cc',
'public/common/renderer_preferences.h',
+ 'public/common/request_context_frame_type.h',
+ 'public/common/request_context_type.h',
'public/common/resource_devtools_info.cc',
'public/common/resource_devtools_info.h',
+ 'public/common/resource_response.cc',
'public/common/resource_response.h',
'public/common/resource_response_info.cc',
'public/common/resource_response_info.h',
+ 'public/common/resource_type.cc',
+ 'public/common/resource_type.h',
'public/common/result_codes.h',
'public/common/result_codes_list.h',
'public/common/sandbox_init.h',
@@ -101,6 +109,7 @@
'public/common/sandboxed_process_launcher_delegate.cc',
'public/common/sandboxed_process_launcher_delegate.h',
'public/common/security_style.h',
+ 'public/common/service_registry.h',
'public/common/show_desktop_notification_params.cc',
'public/common/show_desktop_notification_params.h',
'public/common/signed_certificate_timestamp_id_and_status.cc',
@@ -116,12 +125,15 @@
'public/common/three_d_api_types.h',
'public/common/top_controls_state.h',
'public/common/top_controls_state_list.h',
+ 'public/common/transition_element.h',
'public/common/url_constants.cc',
'public/common/url_constants.h',
'public/common/url_fetcher.h',
'public/common/url_utils.cc',
'public/common/url_utils.h',
'public/common/user_agent.h',
+ 'public/common/web_preferences.cc',
+ 'public/common/web_preferences.h',
'public/common/webplugininfo.cc',
'public/common/webplugininfo.h',
'public/common/window_container_type.cc',
@@ -137,16 +149,19 @@
'common/android/address_parser_internal.h',
'common/android/common_jni_registrar.cc',
'common/android/common_jni_registrar.h',
+ 'common/android/gin_java_bridge_errors.cc',
+ 'common/android/gin_java_bridge_errors.h',
'common/android/gin_java_bridge_value.cc',
'common/android/gin_java_bridge_value.h',
'common/android/hash_set.cc',
'common/android/hash_set.h',
- 'common/android/surface_texture_lookup.cc',
- 'common/android/surface_texture_lookup.h',
+ 'common/android/surface_texture_manager.cc',
+ 'common/android/surface_texture_manager.h',
'common/android/surface_texture_peer.cc',
'common/android/surface_texture_peer.h',
+ 'common/appcache_interfaces.cc',
+ 'common/appcache_interfaces.h',
'common/appcache_messages.h',
- 'common/battery_status_messages.h',
'common/browser_plugin/browser_plugin_constants.cc',
'common/browser_plugin/browser_plugin_constants.h',
'common/browser_plugin/browser_plugin_messages.h',
@@ -185,6 +200,9 @@
'common/database_messages.h',
'common/date_time_suggestion.h',
'common/desktop_notification_messages.h',
+ 'common/device_sensors/device_light_data.h',
+ 'common/device_sensors/device_light_hardware_buffer.h',
+ 'common/device_sensors/device_light_messages.h',
'common/device_sensors/device_motion_hardware_buffer.h',
'common/device_sensors/device_motion_messages.h',
'common/device_sensors/device_orientation_hardware_buffer.h',
@@ -222,6 +240,9 @@
'common/gamepad_param_traits.h',
'common/gamepad_user_gesture.cc',
'common/gamepad_user_gesture.h',
+ 'common/geofencing_messages.h',
+ 'common/geofencing_status.cc',
+ 'common/geofencing_status.h',
'common/geolocation_messages.h',
'common/gin_java_bridge_messages.h',
'common/gpu/client/command_buffer_proxy_impl.cc',
@@ -236,14 +257,17 @@
'common/gpu/client/gl_helper_scaling.h',
'common/gpu/client/gpu_channel_host.cc',
'common/gpu/client/gpu_channel_host.h',
+ 'common/gpu/client/gpu_memory_buffer_factory_host.cc',
'common/gpu/client/gpu_memory_buffer_factory_host.h',
'common/gpu/client/gpu_memory_buffer_impl.cc',
'common/gpu/client/gpu_memory_buffer_impl.h',
'common/gpu/client/gpu_memory_buffer_impl_android.cc',
'common/gpu/client/gpu_memory_buffer_impl_linux.cc',
'common/gpu/client/gpu_memory_buffer_impl_mac.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_shm.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_shm.h',
+ 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_buffer.h',
+ 'common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc',
+ 'common/gpu/client/gpu_memory_buffer_impl_shared_memory.h',
'common/gpu/client/gpu_memory_buffer_impl_win.cc',
'common/gpu/client/gpu_video_decode_accelerator_host.cc',
'common/gpu/client/gpu_video_decode_accelerator_host.h',
@@ -262,6 +286,12 @@
'common/gpu/gpu_command_buffer_stub.cc',
'common/gpu/gpu_command_buffer_stub.h',
'common/gpu/gpu_config.h',
+ 'common/gpu/gpu_memory_buffer_factory.h',
+ 'common/gpu/gpu_memory_buffer_factory_android.cc',
+ 'common/gpu/gpu_memory_buffer_factory_linux.cc',
+ 'common/gpu/gpu_memory_buffer_factory_mac.cc',
+ 'common/gpu/gpu_memory_buffer_factory_ozone.cc',
+ 'common/gpu/gpu_memory_buffer_factory_win.cc',
'common/gpu/gpu_memory_manager.cc',
'common/gpu/gpu_memory_manager.h',
'common/gpu/gpu_memory_manager_client.cc',
@@ -278,7 +308,9 @@
'common/gpu/image_transport_surface.cc',
'common/gpu/image_transport_surface.h',
'common/gpu/image_transport_surface_android.cc',
- 'common/gpu/image_transport_surface_fbo_mac.cc',
+ 'common/gpu/image_transport_surface_calayer_mac.mm',
+ 'common/gpu/image_transport_surface_calayer_mac.h',
+ 'common/gpu/image_transport_surface_fbo_mac.mm',
'common/gpu/image_transport_surface_fbo_mac.h',
'common/gpu/image_transport_surface_linux.cc',
'common/gpu/image_transport_surface_mac.mm',
@@ -289,14 +321,18 @@
'common/gpu/media/gpu_video_decode_accelerator.h',
'common/gpu/media/gpu_video_encode_accelerator.cc',
'common/gpu/media/gpu_video_encode_accelerator.h',
+ 'common/gpu/null_transport_surface.cc',
+ 'common/gpu/null_transport_surface.h',
'common/gpu/stream_texture_android.cc',
'common/gpu/stream_texture_android.h',
+ 'common/gpu/surface_handle_types_mac.cc',
+ 'common/gpu/surface_handle_types_mac.h',
'common/gpu/sync_point_manager.cc',
'common/gpu/sync_point_manager.h',
- 'common/gpu/texture_image_transport_surface.cc',
- 'common/gpu/texture_image_transport_surface.h',
'common/handle_enumerator_win.cc',
'common/handle_enumerator_win.h',
+ 'common/host_discardable_shared_memory_manager.cc',
+ 'common/host_discardable_shared_memory_manager.h',
'common/host_shared_bitmap_manager.cc',
'common/host_shared_bitmap_manager.h',
'common/image_messages.h',
@@ -310,6 +346,7 @@
'common/indexed_db/indexed_db_messages.h',
'common/indexed_db/indexed_db_param_traits.cc',
'common/indexed_db/indexed_db_param_traits.h',
+ 'common/input/did_overscroll_params.cc',
'common/input/did_overscroll_params.h',
'common/input/gesture_event_stream_validator.cc',
'common/input/gesture_event_stream_validator.h',
@@ -342,13 +379,13 @@
'common/input_messages.h',
'common/inter_process_time_ticks_converter.cc',
'common/inter_process_time_ticks_converter.h',
- 'common/java_bridge_messages.h',
'common/mac/attributed_string_coder.h',
'common/mac/attributed_string_coder.mm',
'common/mac/font_descriptor.h',
'common/mac/font_descriptor.mm',
'common/mac/font_loader.h',
'common/mac/font_loader.mm',
+ 'common/manifest_manager_messages.h',
'common/media/aec_dump_messages.h',
'common/media/audio_messages.h',
'common/media/cdm_messages.h',
@@ -371,9 +408,11 @@
'common/message_router.h',
'common/mime_registry_messages.h',
'common/mojo/mojo_messages.h',
- 'common/mojo/mojo_service_names.cc',
- 'common/mojo/mojo_service_names.h',
+ 'common/mojo/service_registry_impl.cc',
+ 'common/mojo/service_registry_impl.h',
'common/navigation_gesture.h',
+ 'common/navigation_params.cc',
+ 'common/navigation_params.h',
'common/net/url_fetcher.cc',
'common/net/url_request_user_data.cc',
'common/net/url_request_user_data.h',
@@ -383,13 +422,14 @@
'common/page_state_serialization.cc',
'common/page_state_serialization.h',
'common/page_zoom.cc',
+ 'common/pepper_file_util.cc',
+ 'common/pepper_file_util.h',
'common/pepper_messages.h',
'common/pepper_plugin_list.cc',
'common/pepper_plugin_list.h',
'common/pepper_renderer_instance_data.cc',
'common/pepper_renderer_instance_data.h',
- 'common/plugin_carbon_interpose_constants_mac.cc',
- 'common/plugin_carbon_interpose_constants_mac.h',
+ 'common/platform_notification_messages.h',
'common/plugin_constants_win.cc',
'common/plugin_constants_win.h',
'common/plugin_list.cc',
@@ -419,6 +459,8 @@
'common/sandbox_linux/bpf_ppapi_policy_linux.h',
'common/sandbox_linux/bpf_renderer_policy_linux.cc',
'common/sandbox_linux/bpf_renderer_policy_linux.h',
+ 'common/sandbox_linux/bpf_utility_policy_linux.cc',
+ 'common/sandbox_linux/bpf_utility_policy_linux.h',
'common/sandbox_linux/sandbox_bpf_base_policy_linux.cc',
'common/sandbox_linux/sandbox_bpf_base_policy_linux.h',
'common/sandbox_linux/sandbox_init_linux.cc',
@@ -445,9 +487,6 @@
'common/set_process_title.h',
'common/set_process_title_linux.cc',
'common/set_process_title_linux.h',
- 'common/socket_stream.h',
- 'common/socket_stream_handle_data.h',
- 'common/socket_stream_messages.h',
'common/speech_recognition_messages.h',
'common/ssl_status_serialization.cc',
'common/ssl_status_serialization.h',
@@ -457,7 +496,6 @@
'common/url_schemes.cc',
'common/url_schemes.h',
'common/user_agent.cc',
- 'common/user_agent_ios.mm',
'common/utility_messages.h',
'common/view_message_enums.h',
'common/view_messages.h',
@@ -501,7 +539,6 @@
['include', '^public/common/frame_navigate_params\\.cc$'],
['include', '^public/common/media_stream_request\\.cc$'],
['include', '^public/common/page_state\\.cc$'],
- ['include', '^public/common/page_transition_types\\.cc$'],
['include', '^public/common/password_form\\.cc$'],
['include', '^public/common/signed_certificate_timestamp_id_and_status\\.cc$'],
['include', '^public/common/speech_recognition_result\\.cc$'],
@@ -527,16 +564,18 @@
'../gpu/gpu.gyp:gpu_ipc',
'../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings',
'../ipc/ipc.gyp:ipc',
+ '../ipc/mojo/ipc_mojo.gyp:ipc_mojo',
'../media/media.gyp:media',
'../media/media.gyp:shared_memory_support',
- '../mojo/mojo.gyp:mojo_environment_chromium',
- '../mojo/mojo.gyp:mojo_system_impl',
+ '../mojo/edk/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
+ '../storage/storage_browser.gyp:storage',
+ '../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
'../ui/gl/gl.gyp:gl',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
- '../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/storage_browser.gyp:webkit_storage_browser',
- '../webkit/storage_common.gyp:webkit_storage_common',
],
'actions': [
{
@@ -565,11 +604,14 @@
}],
['OS=="mac"', {
'dependencies': [
- '../webkit/webkit_resources.gyp:webkit_resources',
+ 'app/resources/content_resources.gyp:content_resources',
],
'sources': [
'common/gpu/client/gpu_memory_buffer_impl_io_surface.cc',
'common/gpu/client/gpu_memory_buffer_impl_io_surface.h',
+ 'common/gpu/gpu_memory_buffer_factory_io_surface.cc',
+ 'common/gpu/gpu_memory_buffer_factory_io_surface.h',
+ 'common/gpu/media/vt.h',
'common/gpu/media/vt_video_decode_accelerator.cc',
'common/gpu/media/vt_video_decode_accelerator.h',
],
@@ -582,11 +624,52 @@
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
],
},
+ 'variables': {
+ 'generate_stubs_script': '../tools/generate_stubs/generate_stubs.py',
+ 'extra_header': 'common/gpu/media/vt_stubs_header.fragment',
+ 'sig_files': ['common/gpu/media/vt.sig'],
+ 'outfile_type': 'posix_stubs',
+ 'stubs_filename_root': 'vt_stubs',
+ 'project_path': 'content/common/gpu/media',
+ 'intermediate_dir': '<(INTERMEDIATE_DIR)',
+ 'output_root': '<(SHARED_INTERMEDIATE_DIR)/vt_stubs',
+ },
+ 'include_dirs': [
+ '<(output_root)',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate_stubs',
+ 'inputs': [
+ '<(generate_stubs_script)',
+ '<(extra_header)',
+ '<@(sig_files)',
+ ],
+ 'outputs': [
+ '<(intermediate_dir)/<(stubs_filename_root).cc',
+ '<(output_root)/<(project_path)/<(stubs_filename_root).h',
+ ],
+ 'action': ['python',
+ '<(generate_stubs_script)',
+ '-i', '<(intermediate_dir)',
+ '-o', '<(output_root)/<(project_path)',
+ '-t', '<(outfile_type)',
+ '-e', '<(extra_header)',
+ '-s', '<(stubs_filename_root)',
+ '-p', '<(project_path)',
+ '<@(_inputs)',
+ ],
+ 'process_outputs_as_sources': 1,
+ 'message': 'Generating VideoToolbox stubs for dynamic loading',
+ },
+ ],
}],
['OS=="android"',{
'sources': [
'common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc',
'common/gpu/client/gpu_memory_buffer_impl_surface_texture.h',
+ 'common/gpu/gpu_memory_buffer_factory_surface_texture.cc',
+ 'common/gpu/gpu_memory_buffer_factory_surface_texture.h',
],
'link_settings': {
'libraries': [
@@ -626,9 +709,19 @@
],
}, { # enable_plugins == 0
'sources!': [
+ 'common/pepper_file_util.cc',
+ 'common/pepper_file_util.h',
+ 'common/pepper_messages.h',
'common/pepper_plugin_list.cc',
'common/pepper_plugin_list.h',
+ 'common/pepper_renderer_instance_data.cc',
+ 'common/pepper_renderer_instance_data.h',
+ 'common/plugin_list.cc',
+ 'common/plugin_list.h',
+ 'common/plugin_list_posix.cc',
'common/sandbox_util.cc',
+ 'public/common/pepper_plugin_info.cc',
+ 'public/common/pepper_plugin_info.h',
],
}],
['OS=="android"', {
@@ -649,6 +742,11 @@
'common/gpu/media/android_video_encode_accelerator.h',
],
}],
+ ['enable_webrtc==1', {
+ 'dependencies': [
+ '../third_party/libjingle/libjingle.gyp:libjingle',
+ ],
+ }],
['target_arch=="arm" and chromeos == 1 and use_x11 == 1', {
'dependencies': [
'../media/media.gyp:media',
@@ -672,6 +770,10 @@
],
}],
['target_arch != "arm" and chromeos == 1 and use_x11 == 1', {
+ 'dependencies': [
+ '../media/media.gyp:media',
+ '../third_party/libyuv/libyuv.gyp:libyuv',
+ ],
'sources': [
'common/gpu/media/h264_dpb.cc',
'common/gpu/media/h264_dpb.h',
@@ -680,6 +782,8 @@
'common/gpu/media/vaapi_h264_decoder.h',
'common/gpu/media/vaapi_video_decode_accelerator.cc',
'common/gpu/media/vaapi_video_decode_accelerator.h',
+ 'common/gpu/media/vaapi_video_encode_accelerator.cc',
+ 'common/gpu/media/vaapi_video_encode_accelerator.h',
'common/gpu/media/vaapi_wrapper.cc',
'common/gpu/media/vaapi_wrapper.h',
],
@@ -695,6 +799,7 @@
},
'include_dirs': [
'<(DEPTH)/third_party/libva',
+ '<(DEPTH)/third_party/libyuv',
'<(output_root)',
],
'actions': [
@@ -793,6 +898,8 @@
'common/sandbox_linux/bpf_ppapi_policy_linux.h',
'common/sandbox_linux/bpf_renderer_policy_linux.cc',
'common/sandbox_linux/bpf_renderer_policy_linux.h',
+ 'common/sandbox_linux/bpf_utility_policy_linux.cc',
+ 'common/sandbox_linux/bpf_utility_policy_linux.h',
'common/sandbox_linux/sandbox_bpf_base_policy_linux.cc',
'common/sandbox_linux/sandbox_bpf_base_policy_linux.h',
],
@@ -802,6 +909,14 @@
['use_ozone==1', {
'dependencies': [
'../ui/ozone/ozone.gyp:ozone',
+ '../ui/ozone/gpu/ozone_gpu.gyp:ozone_gpu',
+ ],
+ 'sources': [
+ 'common/gpu/client/gpu_memory_buffer_impl_ozone.cc',
+ ],
+ 'sources!': [
+ 'common/gpu/client/gpu_memory_buffer_impl_linux.cc',
+ 'common/gpu/gpu_memory_buffer_factory_linux.cc',
],
}],
],
diff --git a/chromium/content/content_common_mojo_bindings.gypi b/chromium/content/content_common_mojo_bindings.gypi
index 7f35e67fdf7..da5c00a4d3d 100644
--- a/chromium/content/content_common_mojo_bindings.gypi
+++ b/chromium/content/content_common_mojo_bindings.gypi
@@ -8,16 +8,24 @@
'target_name': 'content_common_mojo_bindings',
'type': 'static_library',
'dependencies': [
- '../mojo/mojo.gyp:mojo_cpp_bindings',
- '../mojo/mojo.gyp:mojo_environment_chromium',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
],
'sources': [
- 'common/web_ui_setup.mojom',
+ # NOTE: Sources duplicated in //content/common/BUILD.gn:mojo_bindings.
+ 'common/geolocation_service.mojom',
+ 'common/render_frame_setup.mojom',
+
+ # NOTE: Sources duplicated in
+ # //content/public/common/BUILD.gn:mojo_bindings.
+ 'public/common/mojo_geoposition.mojom',
],
'includes': [ '../mojo/public/tools/bindings/mojom_bindings_generator.gypi' ],
'export_dependent_settings': [
- '../mojo/mojo.gyp:mojo_cpp_bindings',
- '../mojo/mojo.gyp:mojo_environment_chromium',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
],
},
],
diff --git a/chromium/content/content_gl_tests.isolate b/chromium/content/content_gl_tests.isolate
new file mode 100644
index 00000000000..a9ca4e3deae
--- /dev/null
+++ b/chromium/content/content_gl_tests.isolate
@@ -0,0 +1,57 @@
+# Copyright 2013 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.
+{
+ 'conditions': [
+ ['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'command': [
+ '<(PRODUCT_DIR)/content_gl_tests<(EXECUTABLE_SUFFIX)',
+ ],
+ 'files': [
+ '<(PRODUCT_DIR)/content_gl_tests<(EXECUTABLE_SUFFIX)',
+ ],
+ },
+ }],
+ # TODO(kbr): these two dependencies seem to be necessary when
+ # running the component build to avoid "Failed to mmap datapack"
+ # errors. Should investigate further.
+ ['OS=="linux" or OS=="win"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/content_resources.pak',
+ '<(PRODUCT_DIR)/ui_test.pak',
+ ],
+ },
+ }],
+ ['OS=="linux"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/libffmpegsumo.so',
+ ],
+ },
+ }],
+ ['OS=="mac"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/ffmpegsumo.so',
+ ],
+ },
+ }],
+ ['OS=="win"', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/d3dcompiler_46.dll',
+ '<(PRODUCT_DIR)/libEGL.dll',
+ '<(PRODUCT_DIR)/libGLESv2.dll',
+ '<(PRODUCT_DIR)/ffmpegsumo.dll',
+ '<(PRODUCT_DIR)/osmesa.dll',
+ ],
+ },
+ }],
+ ],
+ 'includes': [
+ '../base/base.isolate',
+ '../gin/v8.isolate',
+ ],
+}
diff --git a/chromium/content/content_gpu.gypi b/chromium/content/content_gpu.gypi
index 48274936106..396106ce1a4 100644
--- a/chromium/content/content_gpu.gypi
+++ b/chromium/content/content_gpu.gypi
@@ -5,7 +5,7 @@
{
'dependencies': [
'../base/base.gyp:base',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
'../skia/skia.gyp:skia',
'../ui/gl/gl.gyp:gl',
],
@@ -31,8 +31,8 @@
'<(DEPTH)/third_party/wtl/include',
],
'dependencies': [
- '<(angle_path)/src/build_angle.gyp:libEGL',
- '<(angle_path)/src/build_angle.gyp:libGLESv2',
+ '<(angle_path)/src/angle.gyp:libEGL',
+ '<(angle_path)/src/angle.gyp:libGLESv2',
],
'link_settings': {
'libraries': [
@@ -40,32 +40,6 @@
],
},
}],
- ['OS=="win" and target_arch=="ia32" and directxsdk_exists=="True"', {
- # We don't support x64 prior to Win7 and D3DCompiler_43.dll is
- # not needed on Vista+.
- 'actions': [
- {
- 'action_name': 'extract_d3dcompiler',
- 'variables': {
- 'input': 'Jun2010_D3DCompiler_43_x86.cab',
- 'output': 'D3DCompiler_43.dll',
- },
- 'inputs': [
- '../third_party/directxsdk/files/Redist/<(input)',
- ],
- 'outputs': [
- '<(PRODUCT_DIR)/<(output)',
- ],
- 'action': [
- 'python',
- '../build/extract_from_cab.py',
- '..\\third_party\\directxsdk\\files\\Redist\\<(input)',
- '<(output)',
- '<(PRODUCT_DIR)',
- ],
- },
- ],
- }],
['target_arch!="arm" and chromeos == 1', {
'include_dirs': [
'<(DEPTH)/third_party/libva',
diff --git a/chromium/content/content_jni.gypi b/chromium/content/content_jni.gypi
index 42699aa6e08..202f5580fa3 100644
--- a/chromium/content/content_jni.gypi
+++ b/chromium/content/content_jni.gypi
@@ -11,7 +11,6 @@
'public/android/java/src/org/chromium/content/app/ChildProcessService.java',
'public/android/java/src/org/chromium/content/app/ContentMain.java',
'public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java',
- 'public/android/java/src/org/chromium/content/browser/BatteryStatusManager.java',
'public/android/java/src/org/chromium/content/browser/BrowserStartupController.java',
'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java',
'public/android/java/src/org/chromium/content/browser/ContentSettings.java',
@@ -23,23 +22,26 @@
'public/android/java/src/org/chromium/content/browser/DeviceSensors.java',
'public/android/java/src/org/chromium/content/browser/DownloadController.java',
'public/android/java/src/org/chromium/content/browser/input/GamepadList.java',
+ 'public/android/java/src/org/chromium/content/browser/input/HandleViewResources.java',
'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java',
'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java',
+ 'public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java',
'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java',
- 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java',
'public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java',
'public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java',
'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java',
'public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java',
+ 'public/android/java/src/org/chromium/content/browser/ServiceRegistry.java',
'public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java',
'public/android/java/src/org/chromium/content/browser/SpeechRecognition.java',
'public/android/java/src/org/chromium/content/browser/TimeZoneMonitor.java',
'public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java',
'public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java',
'public/android/java/src/org/chromium/content/browser/VibrationProvider.java',
- 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java',
+ 'public/android/java/src/org/chromium/content/browser/WebContentsObserver.java',
'public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java',
'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java',
+ 'public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java',
],
'variables': {
'jni_gen_package': 'content',
diff --git a/chromium/content/content_plugin.gypi b/chromium/content/content_plugin.gypi
index c6baab9a999..30336a0ed12 100644
--- a/chromium/content/content_plugin.gypi
+++ b/chromium/content/content_plugin.gypi
@@ -6,7 +6,7 @@
'conditions': [
['enable_plugins==1 and OS!="linux"', {
'dependencies': [
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
'../skia/skia.gyp:skia',
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/npapi/npapi.gyp:npapi',
diff --git a/chromium/content/content_ppapi_plugin.gypi b/chromium/content/content_ppapi_plugin.gypi
index f79e1bfa349..c02e053d3f1 100644
--- a/chromium/content/content_ppapi_plugin.gypi
+++ b/chromium/content/content_ppapi_plugin.gypi
@@ -7,7 +7,7 @@
['enable_plugins==1', {
'dependencies': [
'../base/base.gyp:base',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
'../ppapi/ppapi_internal.gyp:ppapi_ipc',
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
@@ -19,12 +19,12 @@
'ppapi_plugin/broker_process_dispatcher.h',
'ppapi_plugin/plugin_process_dispatcher.cc',
'ppapi_plugin/plugin_process_dispatcher.h',
+ 'ppapi_plugin/ppapi_blink_platform_impl.cc',
+ 'ppapi_plugin/ppapi_blink_platform_impl.h',
'ppapi_plugin/ppapi_broker_main.cc',
'ppapi_plugin/ppapi_plugin_main.cc',
'ppapi_plugin/ppapi_thread.cc',
'ppapi_plugin/ppapi_thread.h',
- 'ppapi_plugin/ppapi_webkitplatformsupport_impl.cc',
- 'ppapi_plugin/ppapi_webkitplatformsupport_impl.h',
],
'include_dirs': [
'..',
diff --git a/chromium/content/content_renderer.gypi b/chromium/content/content_renderer.gypi
index 444a6650113..144f8de37ef 100644
--- a/chromium/content/content_renderer.gypi
+++ b/chromium/content/content_renderer.gypi
@@ -8,15 +8,20 @@
'../base/base.gyp:base',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../cc/cc.gyp:cc',
+ '../cc/blink/cc_blink.gyp:cc_blink',
+ '../device/battery/battery.gyp:device_battery',
+ '../device/battery/battery.gyp:device_battery_mojo_bindings',
'../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
'../jingle/jingle.gyp:jingle_glue',
+ '../media/blink/media_blink.gyp:media_blink',
'../media/media.gyp:media',
- '../mojo/mojo.gyp:mojo_environment_chromium',
- '../mojo/mojo.gyp:mojo_js_bindings_lib',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/edk/mojo_edk.gyp:mojo_js_lib',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
+ '../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/icu/icu.gyp:icui18n',
'../third_party/icu/icu.gyp:icuuc',
@@ -30,10 +35,7 @@
'../ui/native_theme/native_theme.gyp:native_theme',
'../ui/surface/surface.gyp:surface',
'../v8/tools/gyp/v8.gyp:v8',
- '../webkit/child/webkit_child.gyp:webkit_child',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
- '../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/storage_common.gyp:webkit_storage_common',
],
'include_dirs': [
'..',
@@ -43,22 +45,21 @@
'public_renderer_sources': [
'public/renderer/android_content_detection_prefixes.cc',
'public/renderer/android_content_detection_prefixes.h',
+ 'public/renderer/browser_plugin_delegate.h',
'public/renderer/content_renderer_client.cc',
'public/renderer/content_renderer_client.h',
'public/renderer/context_menu_client.h',
'public/renderer/document_state.cc',
'public/renderer/document_state.h',
- 'public/renderer/key_system_info.cc',
- 'public/renderer/key_system_info.h',
'public/renderer/navigation_state.cc',
'public/renderer/navigation_state.h',
'public/renderer/pepper_plugin_instance.h',
+ 'public/renderer/platform_event_observer.h',
'public/renderer/renderer_ppapi_host.h',
'public/renderer/render_frame.h',
'public/renderer/render_frame_observer.cc',
'public/renderer/render_frame_observer.h',
'public/renderer/render_frame_observer_tracker.h',
- 'public/renderer/render_font_warmup_win.cc',
'public/renderer/render_font_warmup_win.h',
'public/renderer/render_process_observer.cc',
'public/renderer/render_process_observer.h',
@@ -73,7 +74,6 @@
'public/renderer/v8_value_converter.h',
'public/renderer/video_encode_accelerator.cc',
'public/renderer/video_encode_accelerator.h',
- 'public/renderer/web_preferences.h',
],
'private_renderer_sources': [
'renderer/accessibility/blink_ax_enum_conversion.cc',
@@ -82,10 +82,6 @@
'renderer/accessibility/blink_ax_tree_source.h',
'renderer/accessibility/renderer_accessibility.cc',
'renderer/accessibility/renderer_accessibility.h',
- 'renderer/accessibility/renderer_accessibility_complete.cc',
- 'renderer/accessibility/renderer_accessibility_complete.h',
- 'renderer/accessibility/renderer_accessibility_focus_only.cc',
- 'renderer/accessibility/renderer_accessibility_focus_only.h',
'renderer/active_notification_tracker.cc',
'renderer/active_notification_tracker.h',
'renderer/android/address_detector.cc',
@@ -96,76 +92,34 @@
'renderer/android/email_detector.h',
'renderer/android/phone_number_detector.cc',
'renderer/android/phone_number_detector.h',
+ 'renderer/android/renderer_date_time_picker.cc',
+ 'renderer/android/renderer_date_time_picker.h',
'renderer/android/synchronous_compositor_factory.cc',
'renderer/android/synchronous_compositor_factory.h',
'renderer/battery_status/battery_status_dispatcher.cc',
'renderer/battery_status/battery_status_dispatcher.h',
- 'renderer/battery_status/fake_battery_status_dispatcher.cc',
- 'renderer/battery_status/fake_battery_status_dispatcher.h',
'renderer/browser_plugin/browser_plugin.cc',
'renderer/browser_plugin/browser_plugin.h',
- 'renderer/browser_plugin/browser_plugin_bindings.cc',
- 'renderer/browser_plugin/browser_plugin_bindings.h',
- 'renderer/browser_plugin/browser_plugin_manager_factory.h',
- 'renderer/browser_plugin/browser_plugin_manager_impl.cc',
- 'renderer/browser_plugin/browser_plugin_manager_impl.h',
'renderer/browser_plugin/browser_plugin_manager.cc',
'renderer/browser_plugin/browser_plugin_manager.h',
'renderer/clipboard_utils.cc',
'renderer/clipboard_utils.h',
'renderer/child_frame_compositing_helper.cc',
'renderer/child_frame_compositing_helper.h',
- 'renderer/compositor_bindings/scrollbar_impl.cc',
- 'renderer/compositor_bindings/scrollbar_impl.h',
- 'renderer/compositor_bindings/web_animation_curve_common.cc',
- 'renderer/compositor_bindings/web_animation_curve_common.h',
- 'renderer/compositor_bindings/web_animation_impl.cc',
- 'renderer/compositor_bindings/web_animation_impl.h',
- 'renderer/compositor_bindings/web_compositor_support_impl.cc',
- 'renderer/compositor_bindings/web_compositor_support_impl.h',
- 'renderer/compositor_bindings/web_content_layer_impl.cc',
- 'renderer/compositor_bindings/web_content_layer_impl.h',
- 'renderer/compositor_bindings/web_external_bitmap_impl.cc',
- 'renderer/compositor_bindings/web_external_bitmap_impl.h',
- 'renderer/compositor_bindings/web_external_texture_layer_impl.cc',
- 'renderer/compositor_bindings/web_external_texture_layer_impl.h',
- 'renderer/compositor_bindings/web_filter_animation_curve_impl.cc',
- 'renderer/compositor_bindings/web_filter_animation_curve_impl.h',
- 'renderer/compositor_bindings/web_filter_operations_impl.cc',
- 'renderer/compositor_bindings/web_filter_operations_impl.h',
- 'renderer/compositor_bindings/web_float_animation_curve_impl.cc',
- 'renderer/compositor_bindings/web_float_animation_curve_impl.h',
- 'renderer/compositor_bindings/web_image_layer_impl.cc',
- 'renderer/compositor_bindings/web_image_layer_impl.h',
- 'renderer/compositor_bindings/web_layer_impl.cc',
- 'renderer/compositor_bindings/web_layer_impl.h',
- 'renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc',
- 'renderer/compositor_bindings/web_layer_impl_fixed_bounds.h',
- 'renderer/compositor_bindings/web_nine_patch_layer_impl.cc',
- 'renderer/compositor_bindings/web_nine_patch_layer_impl.h',
- 'renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc',
- 'renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h',
- 'renderer/compositor_bindings/web_scrollbar_layer_impl.cc',
- 'renderer/compositor_bindings/web_scrollbar_layer_impl.h',
- 'renderer/compositor_bindings/web_solid_color_layer_impl.cc',
- 'renderer/compositor_bindings/web_solid_color_layer_impl.h',
- 'renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc',
- 'renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h',
- 'renderer/compositor_bindings/web_transform_animation_curve_impl.cc',
- 'renderer/compositor_bindings/web_transform_animation_curve_impl.h',
- 'renderer/compositor_bindings/web_transform_operations_impl.cc',
- 'renderer/compositor_bindings/web_transform_operations_impl.h',
+ 'renderer/chrome_object_extensions_utils.cc',
+ 'renderer/chrome_object_extensions_utils.h',
'renderer/context_menu_params_builder.cc',
'renderer/context_menu_params_builder.h',
'renderer/cursor_utils.cc',
'renderer/cursor_utils.h',
'renderer/date_time_suggestion_builder.cc',
'renderer/date_time_suggestion_builder.h',
+ 'renderer/device_sensors/device_light_event_pump.cc',
+ 'renderer/device_sensors/device_light_event_pump.h',
'renderer/device_sensors/device_motion_event_pump.cc',
'renderer/device_sensors/device_motion_event_pump.h',
'renderer/device_sensors/device_orientation_event_pump.cc',
'renderer/device_sensors/device_orientation_event_pump.h',
- 'renderer/device_sensors/device_sensor_event_pump.cc',
'renderer/device_sensors/device_sensor_event_pump.h',
'renderer/devtools/devtools_agent.cc',
'renderer/devtools/devtools_agent.h',
@@ -186,14 +140,20 @@
'renderer/dom_storage/webstoragearea_impl.h',
'renderer/dom_storage/webstoragenamespace_impl.cc',
'renderer/dom_storage/webstoragenamespace_impl.h',
+ 'renderer/dom_utils.cc',
+ 'renderer/dom_utils.h',
'renderer/drop_data_builder.cc',
'renderer/drop_data_builder.h',
'renderer/fetchers/image_resource_fetcher.cc',
'renderer/fetchers/image_resource_fetcher.h',
+ 'renderer/fetchers/manifest_fetcher.cc',
+ 'renderer/fetchers/manifest_fetcher.h',
'renderer/fetchers/multi_resolution_image_resource_fetcher.cc',
'renderer/fetchers/multi_resolution_image_resource_fetcher.h',
'renderer/fetchers/resource_fetcher_impl.cc',
'renderer/fetchers/resource_fetcher_impl.h',
+ 'renderer/fetchers/web_url_loader_client_impl.cc',
+ 'renderer/fetchers/web_url_loader_client_impl.h',
'renderer/gamepad_shared_memory_reader.cc',
'renderer/gamepad_shared_memory_reader.h',
'renderer/geolocation_dispatcher.cc',
@@ -204,10 +164,14 @@
'renderer/gpu/compositor_software_output_device.h',
'renderer/gpu/delegated_compositor_output_surface.cc',
'renderer/gpu/delegated_compositor_output_surface.h',
+ 'renderer/gpu/frame_swap_message_queue.cc',
+ 'renderer/gpu/frame_swap_message_queue.h',
'renderer/gpu/gpu_benchmarking_extension.cc',
'renderer/gpu/gpu_benchmarking_extension.h',
'renderer/gpu/mailbox_output_surface.cc',
'renderer/gpu/mailbox_output_surface.h',
+ 'renderer/gpu/queue_message_swap_promise.cc',
+ 'renderer/gpu/queue_message_swap_promise.h',
'renderer/gpu/render_widget_compositor.cc',
'renderer/gpu/render_widget_compositor.h',
'renderer/gpu/stream_texture_host_android.cc',
@@ -235,6 +199,8 @@
'renderer/input/input_handler_proxy.h',
'renderer/input/input_handler_wrapper.cc',
'renderer/input/input_handler_wrapper.h',
+ 'renderer/input/input_scroll_elasticity_controller.cc',
+ 'renderer/input/input_scroll_elasticity_controller.h',
'renderer/internal_document_state_data.cc',
'renderer/internal_document_state_data.h',
'renderer/java/gin_java_bridge_dispatcher.cc',
@@ -243,12 +209,12 @@
'renderer/java/gin_java_bridge_object.h',
'renderer/java/gin_java_bridge_value_converter.cc',
'renderer/java/gin_java_bridge_value_converter.h',
- 'renderer/java/java_bridge_channel.cc',
- 'renderer/java/java_bridge_channel.h',
- 'renderer/java/java_bridge_dispatcher.cc',
- 'renderer/java/java_bridge_dispatcher.h',
- 'renderer/media/active_loader.cc',
- 'renderer/media/active_loader.h',
+ 'renderer/manifest/manifest_manager.cc',
+ 'renderer/manifest/manifest_manager.h',
+ 'renderer/manifest/manifest_parser.cc',
+ 'renderer/manifest/manifest_parser.h',
+ 'renderer/manifest/manifest_uma_util.cc',
+ 'renderer/manifest/manifest_uma_util.h',
'renderer/media/aec_dump_message_filter.cc',
'renderer/media/aec_dump_message_filter.h',
'renderer/media/android/audio_decoder_android.cc',
@@ -278,18 +244,10 @@
'renderer/media/audio_message_filter.h',
'renderer/media/audio_renderer_mixer_manager.cc',
'renderer/media/audio_renderer_mixer_manager.h',
- 'renderer/media/buffered_data_source.cc',
- 'renderer/media/buffered_data_source.h',
- 'renderer/media/buffered_data_source_host_impl.h',
- 'renderer/media/buffered_data_source_host_impl.cc',
- 'renderer/media/buffered_resource_loader.cc',
- 'renderer/media/buffered_resource_loader.h',
- 'renderer/media/cache_util.cc',
- 'renderer/media/cache_util.h',
'renderer/media/cdm_session_adapter.cc',
'renderer/media/cdm_session_adapter.h',
- 'renderer/media/crypto/content_decryption_module_factory.cc',
- 'renderer/media/crypto/content_decryption_module_factory.h',
+ 'renderer/media/crypto/encrypted_media_player_support_impl.cc',
+ 'renderer/media/crypto/encrypted_media_player_support_impl.h',
'renderer/media/crypto/key_systems.cc',
'renderer/media/crypto/key_systems.h',
'renderer/media/crypto/key_systems_support_uma.cc',
@@ -301,6 +259,8 @@
'renderer/media/crypto/ppapi_decryptor.h',
'renderer/media/crypto/proxy_decryptor.cc',
'renderer/media/crypto/proxy_decryptor.h',
+ 'renderer/media/crypto/render_cdm_factory.cc',
+ 'renderer/media/crypto/render_cdm_factory.h',
'renderer/media/media_stream_audio_level_calculator.cc',
'renderer/media/media_stream_audio_level_calculator.h',
'renderer/media/media_stream_audio_renderer.cc',
@@ -310,14 +270,12 @@
'renderer/media/media_stream_constraints_util.h',
'renderer/media/media_stream_dispatcher.h',
'renderer/media/media_stream_dispatcher_eventhandler.h',
- 'renderer/media/media_stream_impl.h',
'renderer/media/media_stream_track.cc',
'renderer/media/media_stream_track.h',
'renderer/media/midi_dispatcher.cc',
'renderer/media/midi_dispatcher.h',
'renderer/media/midi_message_filter.cc',
'renderer/media/midi_message_filter.h',
- 'renderer/media/preload.h',
'renderer/media/render_media_log.cc',
'renderer/media/render_media_log.h',
'renderer/media/renderer_gpu_video_accelerator_factories.cc',
@@ -326,53 +284,43 @@
'renderer/media/renderer_webaudiodevice_impl.h',
'renderer/media/renderer_webmidiaccessor_impl.cc',
'renderer/media/renderer_webmidiaccessor_impl.h',
- 'renderer/media/texttrack_impl.cc',
- 'renderer/media/texttrack_impl.h',
'renderer/media/video_capture_impl.cc',
'renderer/media/video_capture_impl.h',
'renderer/media/video_capture_impl_manager.cc',
'renderer/media/video_capture_impl_manager.h',
'renderer/media/video_capture_message_filter.cc',
'renderer/media/video_capture_message_filter.h',
- 'renderer/media/video_frame_compositor.cc',
- 'renderer/media/video_frame_compositor.h',
'renderer/media/video_frame_provider.cc',
'renderer/media/video_frame_provider.h',
- 'renderer/media/webaudiosourceprovider_impl.cc',
- 'renderer/media/webaudiosourceprovider_impl.h',
'renderer/media/webcontentdecryptionmodule_impl.cc',
'renderer/media/webcontentdecryptionmodule_impl.h',
'renderer/media/webcontentdecryptionmodulesession_impl.cc',
'renderer/media/webcontentdecryptionmodulesession_impl.h',
- 'renderer/media/webinbandtexttrack_impl.cc',
- 'renderer/media/webinbandtexttrack_impl.h',
- 'renderer/media/webmediaplayer_delegate.h',
- 'renderer/media/webmediaplayer_impl.cc',
- 'renderer/media/webmediaplayer_impl.h',
'renderer/media/webmediaplayer_ms.cc',
'renderer/media/webmediaplayer_ms.h',
- 'renderer/media/webmediaplayer_params.cc',
- 'renderer/media/webmediaplayer_params.h',
- 'renderer/media/webmediaplayer_util.cc',
- 'renderer/media/webmediaplayer_util.h',
- 'renderer/media/webmediasource_impl.cc',
- 'renderer/media/webmediasource_impl.h',
- 'renderer/media/websourcebuffer_impl.cc',
- 'renderer/media/websourcebuffer_impl.h',
'renderer/memory_benchmarking_extension.cc',
'renderer/memory_benchmarking_extension.h',
'renderer/menu_item_builder.cc',
'renderer/menu_item_builder.h',
'renderer/mhtml_generator.cc',
'renderer/mhtml_generator.h',
+ 'renderer/mojo/service_registry_js_wrapper.cc',
+ 'renderer/mojo/service_registry_js_wrapper.h',
'renderer/mouse_lock_dispatcher.cc',
'renderer/mouse_lock_dispatcher.h',
'renderer/net_info_helper.cc',
'renderer/net_info_helper.h',
+ 'renderer/notification_icon_loader.cc',
+ 'renderer/notification_icon_loader.h',
+ 'renderer/notification_permission_dispatcher.cc',
+ 'renderer/notification_permission_dispatcher.h',
'renderer/notification_provider.cc',
'renderer/notification_provider.h',
'renderer/push_messaging_dispatcher.cc',
'renderer/push_messaging_dispatcher.h',
+ 'renderer/push_permission_dispatcher.cc',
+ 'renderer/push_permission_dispatcher.h',
+ 'renderer/render_font_warmup_win.cc',
'renderer/render_frame_impl.cc',
'renderer/render_frame_impl.h',
'renderer/render_frame_proxy.cc',
@@ -394,10 +342,12 @@
'renderer/render_widget.h',
'renderer/render_widget_fullscreen.cc',
'renderer/render_widget_fullscreen.h',
+ 'renderer/renderer_blink_platform_impl.cc',
+ 'renderer/renderer_blink_platform_impl.h',
'renderer/renderer_clipboard_client.cc',
'renderer/renderer_clipboard_client.h',
- 'renderer/renderer_date_time_picker.cc',
- 'renderer/renderer_date_time_picker.h',
+ 'renderer/renderer_font_platform_win.cc',
+ 'renderer/renderer_font_platform_win.h',
'renderer/renderer_main.cc',
'renderer/renderer_main_platform_delegate.h',
'renderer/renderer_main_platform_delegate_android.cc',
@@ -410,18 +360,31 @@
'renderer/renderer_webcolorchooser_impl.h',
'renderer/renderer_webcookiejar_impl.cc',
'renderer/renderer_webcookiejar_impl.h',
- 'renderer/renderer_webkitplatformsupport_impl.cc',
- 'renderer/renderer_webkitplatformsupport_impl.h',
'renderer/resizing_mode_selector.cc',
'renderer/resizing_mode_selector.h',
'renderer/sad_plugin.cc',
'renderer/sad_plugin.h',
'renderer/savable_resources.cc',
'renderer/savable_resources.h',
- 'renderer/screen_orientation/mock_screen_orientation_controller.cc',
- 'renderer/screen_orientation/mock_screen_orientation_controller.h',
+ 'renderer/scheduler/null_renderer_scheduler.cc',
+ 'renderer/scheduler/null_renderer_scheduler.h',
+ 'renderer/scheduler/renderer_scheduler.cc',
+ 'renderer/scheduler/renderer_scheduler.h',
+ 'renderer/scheduler/renderer_scheduler_impl.cc',
+ 'renderer/scheduler/renderer_scheduler_impl.h',
+ 'renderer/scheduler/renderer_task_queue_selector.cc',
+ 'renderer/scheduler/renderer_task_queue_selector.h',
+ 'renderer/scheduler/single_thread_idle_task_runner.cc',
+ 'renderer/scheduler/single_thread_idle_task_runner.h',
+ 'renderer/scheduler/task_queue_manager.cc',
+ 'renderer/scheduler/task_queue_manager.h',
+ 'renderer/scheduler/task_queue_selector.h',
+ 'renderer/scheduler/web_scheduler_impl.cc',
+ 'renderer/scheduler/web_scheduler_impl.h',
'renderer/screen_orientation/screen_orientation_dispatcher.cc',
'renderer/screen_orientation/screen_orientation_dispatcher.h',
+ 'renderer/screen_orientation/screen_orientation_observer.cc',
+ 'renderer/screen_orientation/screen_orientation_observer.h',
'renderer/scoped_clipboard_writer_glue.cc',
'renderer/scoped_clipboard_writer_glue.h',
'renderer/service_worker/embedded_worker_context_client.cc',
@@ -432,6 +395,8 @@
'renderer/service_worker/embedded_worker_devtools_agent.h',
'renderer/service_worker/embedded_worker_dispatcher.cc',
'renderer/service_worker/embedded_worker_dispatcher.h',
+ 'renderer/service_worker/service_worker_cache_storage_dispatcher.cc',
+ 'renderer/service_worker/service_worker_cache_storage_dispatcher.h',
'renderer/service_worker/service_worker_script_context.cc',
'renderer/service_worker/service_worker_script_context.h',
'renderer/shared_memory_seqlock_reader.cc',
@@ -454,7 +419,6 @@
'renderer/text_input_client_observer.h',
'renderer/v8_value_converter_impl.cc',
'renderer/v8_value_converter_impl.h',
- 'renderer/web_preferences.cc',
'renderer/web_ui_extension.cc',
'renderer/web_ui_extension.h',
'renderer/web_ui_extension_data.cc',
@@ -465,8 +429,6 @@
'renderer/web_ui_mojo_context_state.h',
'renderer/web_ui_runner.cc',
'renderer/web_ui_runner.h',
- 'renderer/web_ui_setup_impl.cc',
- 'renderer/web_ui_setup_impl.h',
'renderer/webclipboard_impl.cc',
'renderer/webclipboard_impl.h',
'renderer/webgraphicscontext3d_provider_impl.cc',
@@ -490,7 +452,6 @@
'renderer/npapi/webplugin_impl.h',
'renderer/pepper/audio_helper.cc',
'renderer/pepper/audio_helper.h',
- 'renderer/pepper/common.h',
'renderer/pepper/content_decryptor_delegate.cc',
'renderer/pepper/content_decryptor_delegate.h',
'renderer/pepper/content_renderer_pepper_host_factory.cc',
@@ -511,10 +472,6 @@
'renderer/pepper/host_var_tracker.h',
'renderer/pepper/message_channel.cc',
'renderer/pepper/message_channel.h',
- 'renderer/pepper/npapi_glue.cc',
- 'renderer/pepper/npapi_glue.h',
- 'renderer/pepper/npobject_var.cc',
- 'renderer/pepper/npobject_var.h',
'renderer/pepper/pepper_audio_input_host.cc',
'renderer/pepper/pepper_audio_input_host.h',
'renderer/pepper/pepper_broker.cc',
@@ -549,17 +506,14 @@
'renderer/pepper/pepper_platform_video_capture.h',
'renderer/pepper/pepper_plugin_instance_impl.cc',
'renderer/pepper/pepper_plugin_instance_impl.h',
+ 'renderer/pepper/pepper_plugin_instance_throttler.cc',
+ 'renderer/pepper/pepper_plugin_instance_throttler.h',
'renderer/pepper/pepper_plugin_registry.cc',
'renderer/pepper/pepper_plugin_registry.h',
'renderer/pepper/pepper_proxy_channel_delegate_impl.cc',
'renderer/pepper/pepper_proxy_channel_delegate_impl.h',
- 'renderer/pepper/pepper_truetype_font.h',
- 'renderer/pepper/pepper_truetype_font_android.cc',
- 'renderer/pepper/pepper_truetype_font_host.cc',
- 'renderer/pepper/pepper_truetype_font_host.h',
- 'renderer/pepper/pepper_truetype_font_linux.cc',
- 'renderer/pepper/pepper_truetype_font_mac.mm',
- 'renderer/pepper/pepper_truetype_font_win.cc',
+ 'renderer/pepper/pepper_try_catch.cc',
+ 'renderer/pepper/pepper_try_catch.h',
'renderer/pepper/pepper_url_loader_host.cc',
'renderer/pepper/pepper_url_loader_host.h',
'renderer/pepper/pepper_video_capture_host.cc',
@@ -574,6 +528,10 @@
'renderer/pepper/plugin_module.h',
'renderer/pepper/plugin_object.cc',
'renderer/pepper/plugin_object.h',
+ 'renderer/pepper/plugin_power_saver_helper.cc',
+ 'renderer/pepper/plugin_power_saver_helper.h',
+ 'renderer/pepper/ppapi_preferences_builder.cc',
+ 'renderer/pepper/ppapi_preferences_builder.h',
'renderer/pepper/ppb_audio_impl.cc',
'renderer/pepper/ppb_audio_impl.h',
'renderer/pepper/ppb_broker_impl.cc',
@@ -607,11 +565,13 @@
'renderer/pepper/url_request_info_util.h',
'renderer/pepper/url_response_info_util.cc',
'renderer/pepper/url_response_info_util.h',
- 'renderer/pepper/usb_key_code_conversion.h',
'renderer/pepper/usb_key_code_conversion.cc',
+ 'renderer/pepper/usb_key_code_conversion.h',
'renderer/pepper/usb_key_code_conversion_linux.cc',
'renderer/pepper/usb_key_code_conversion_mac.cc',
'renderer/pepper/usb_key_code_conversion_win.cc',
+ 'renderer/pepper/v8object_var.cc',
+ 'renderer/pepper/v8object_var.h',
'renderer/pepper/v8_var_converter.cc',
'renderer/pepper/v8_var_converter.h',
'renderer/pepper/video_decoder_shim.cc',
@@ -641,7 +601,6 @@
'renderer/media/media_stream_audio_track_sink.h',
'renderer/media/media_stream_center.cc',
'renderer/media/media_stream_dispatcher.cc',
- 'renderer/media/media_stream_impl.cc',
'renderer/media/media_stream_registry_interface.h',
'renderer/media/media_stream_audio_source.cc',
'renderer/media/media_stream_audio_source.h',
@@ -683,8 +642,9 @@
'renderer/media/rtc_video_encoder_factory.h',
'renderer/media/rtc_video_renderer.cc',
'renderer/media/rtc_video_renderer.h',
- 'renderer/media/video_frame_deliverer.cc',
- 'renderer/media/video_frame_deliverer.h',
+ 'renderer/media/speech_recognition_audio_sink.cc',
+ 'renderer/media/speech_recognition_audio_sink.h',
+ 'renderer/media/user_media_client_impl.cc',
'renderer/media/video_source_handler.cc',
'renderer/media/video_source_handler.h',
'renderer/media/video_track_adapter.cc',
@@ -791,10 +751,8 @@
}],
['OS=="android"', {
'sources!': [
- 'renderer/accessibility/renderer_accessibility_focus_only.cc',
'renderer/media/audio_decoder.cc',
- 'renderer/media/filter_helpers.cc',
- 'renderer/media/webmediaplayer_impl.cc',
+ 'renderer/media/crypto/encrypted_media_player_support_impl.cc',
],
'sources': [
'renderer/external_popup_menu.cc',
@@ -851,10 +809,20 @@
'sources': [
'<@(private_renderer_plugin_sources)',
],
+ 'conditions': [
+ ['OS=="android"', {
+ 'sources!': [
+ # Android does not build FFmpeg, which these depend on.
+ 'renderer/pepper/video_decoder_shim.cc',
+ 'renderer/pepper/video_decoder_shim.h',
+ ],
+ }],
+ ],
'dependencies': [
'../ppapi/ppapi_internal.gyp:ppapi_host',
'../ppapi/ppapi_internal.gyp:ppapi_proxy',
'../ppapi/ppapi_internal.gyp:ppapi_shared',
+ '../third_party/libyuv/libyuv.gyp:libyuv',
],
}, { # enable_plugins==0
'sources!': [
@@ -870,6 +838,9 @@
}],
['enable_pepper_cdms != 1', {
'sources!': [
+ 'renderer/media/crypto/pepper_cdm_wrapper.h',
+ 'renderer/media/crypto/pepper_cdm_wrapper_impl.cc',
+ 'renderer/media/crypto/pepper_cdm_wrapper_impl.h',
'renderer/media/crypto/ppapi_decryptor.cc',
'renderer/media/crypto/ppapi_decryptor.h',
],
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index cdb7855b101..445cc8d98d8 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -32,18 +32,19 @@
<include name="IDR_WEBRTC_INTERNALS_JS" file="browser/resources/media/webrtc_internals.js" flattenhtml="true" type="BINDATA" />
<if expr="is_macosx">
<include name="IDR_GPU_SANDBOX_PROFILE" file="browser/gpu.sb" type="BINDATA" />
- <include name="IDR_WORKER_SANDBOX_PROFILE" file="browser/worker.sb" type="BINDATA" />
<include name="IDR_COMMON_SANDBOX_PROFILE" file="common/common.sb" type="BINDATA" />
<include name="IDR_PPAPI_SANDBOX_PROFILE" file="ppapi_plugin/ppapi.sb" type="BINDATA" />
<include name="IDR_RENDERER_SANDBOX_PROFILE" file="renderer/renderer.sb" type="BINDATA" />
<include name="IDR_UTILITY_SANDBOX_PROFILE" file="utility/utility.sb" type="BINDATA" />
</if>
<if expr="not is_ios">
- <include name="IDR_MOJO_CODEC_JS" file="../mojo/public/js/bindings/codec.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_MOJO_CONNECTION_JS" file="../mojo/public/js/bindings/connection.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_MOJO_CONNECTOR_JS" file="../mojo/public/js/bindings/connector.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_MOJO_ROUTER_JS" file="../mojo/public/js/bindings/router.js" flattenhtml="true" type="BINDATA" />
- <include name="IDR_MOJO_UNICODE_JS" file="../mojo/public/js/bindings/unicode.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_BUFFER_JS" file="../mojo/public/js/buffer.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_CODEC_JS" file="../mojo/public/js/codec.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_CONNECTION_JS" file="../mojo/public/js/connection.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_CONNECTOR_JS" file="../mojo/public/js/connector.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_ROUTER_JS" file="../mojo/public/js/router.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_UNICODE_JS" file="../mojo/public/js/unicode.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_VALIDATOR_JS" file="../mojo/public/js/validator.js" flattenhtml="true" type="BINDATA" />
</if>
</includes>
</release>
diff --git a/chromium/content/content_resources.gyp b/chromium/content/content_resources.gyp
deleted file mode 100644
index 65fdb9a2907..00000000000
--- a/chromium/content/content_resources.gyp
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2012 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(jochen): make this a .gypi file and include it in content.gyp, once
-# content.gyp doesn't depend on gyp files from chrome/ anymore:
-# http://crbug.com/10394
-{
- 'targets': [
- {
- 'target_name': 'content_resources',
- 'type': 'none',
- 'variables': {
- 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/content',
- },
- 'actions': [
- {
- 'action_name': 'generate_content_resources',
- 'variables': {
- 'grit_grd_file': 'content_resources.grd',
- },
- 'includes': [ '../build/grit_action.gypi' ],
- },
- ],
- 'includes': [ '../build/grit_target.gypi' ],
- 'copies': [
- {
- 'destination': '<(PRODUCT_DIR)',
- 'files': [
- '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak'
- ],
- },
- ],
- },
- ],
-}
diff --git a/chromium/content/content_resources.gypi b/chromium/content/content_resources.gypi
new file mode 100644
index 00000000000..d61642f7d1e
--- /dev/null
+++ b/chromium/content/content_resources.gypi
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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.
+
+{
+ 'targets': [
+ {
+ # GN version: //content:resources
+ 'target_name': 'content_resources',
+ 'type': 'none',
+ 'variables': {
+ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/content',
+ },
+ 'actions': [
+ {
+ 'action_name': 'generate_content_resources',
+ 'variables': {
+ 'grit_grd_file': 'content_resources.grd',
+ },
+ 'includes': [ '../build/grit_action.gypi' ],
+ },
+ ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)',
+ 'files': [
+ '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak'
+ ],
+ },
+ ],
+ },
+ ],
+}
diff --git a/chromium/content/content_shell.gypi b/chromium/content/content_shell.gypi
index e9f641d09ab..0ba38e16ba8 100644
--- a/chromium/content/content_shell.gypi
+++ b/chromium/content/content_shell.gypi
@@ -19,6 +19,7 @@
},
'targets': [
{
+ # GN version: //content/shell:content_shell_lib
'target_name': 'content_shell_lib',
'type': 'static_library',
'defines': ['CONTENT_SHELL_VERSION="<(content_shell_version)"'],
@@ -26,6 +27,8 @@
'chromium_code': 1,
},
'dependencies': [
+ 'app/resources/content_resources.gyp:content_resources',
+ 'app/strings/content_strings.gyp:content_strings',
'content.gyp:content_app_both',
'content.gyp:content_browser',
'content.gyp:content_common',
@@ -33,60 +36,92 @@
'content.gyp:content_plugin',
'content.gyp:content_ppapi_plugin',
'content.gyp:content_renderer',
+ 'content.gyp:content_resources',
'content.gyp:content_utility',
- 'content.gyp:content_worker',
- 'content_resources.gyp:content_resources',
'content_shell_resources',
'copy_test_netscape_plugin',
'layouttest_support_content',
'../base/base.gyp:base',
'../base/base.gyp:base_static',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../cc/blink/cc_blink.gyp:cc_blink',
'../cc/cc.gyp:cc',
- '../components/components.gyp:breakpad_component',
+ '../components/components.gyp:crash_component',
+ '../components/components.gyp:web_cache_renderer',
'../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
'../ipc/ipc.gyp:ipc',
+ '../media/blink/media_blink.gyp:media_blink',
'../media/media.gyp:media',
'../net/net.gyp:net',
'../net/net.gyp:net_resources',
'../skia/skia.gyp:skia',
+ '../storage/storage_browser.gyp:storage',
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/WebKit/public/blink.gyp:blink_test_support',
'../ui/base/ui_base.gyp:ui_base',
'../ui/events/events.gyp:events_base',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
'../ui/gl/gl.gyp:gl',
'../url/url.gyp:url_lib',
'../v8/tools/gyp/v8.gyp:v8',
- '../webkit/common/webkit_common.gyp:webkit_common',
- '../webkit/storage_browser.gyp:webkit_storage_browser',
- '../webkit/webkit_resources.gyp:webkit_resources',
],
'include_dirs': [
'..',
],
'sources': [
+ # Note: sources list duplicated in GN build.
'shell/android/shell_jni_registrar.cc',
'shell/android/shell_jni_registrar.h',
'shell/android/shell_manager.cc',
'shell/android/shell_manager.h',
+ 'shell/app/blink_test_platform_support.h',
+ 'shell/app/blink_test_platform_support_android.cc',
+ 'shell/app/blink_test_platform_support_linux.cc',
+ 'shell/app/blink_test_platform_support_mac.mm',
+ 'shell/app/blink_test_platform_support_win.cc',
'shell/app/paths_mac.h',
'shell/app/paths_mac.mm',
- 'shell/app/shell_breakpad_client.cc',
- 'shell/app/shell_breakpad_client.h',
+ 'shell/app/shell_crash_reporter_client.cc',
+ 'shell/app/shell_crash_reporter_client.h',
'shell/app/shell_main_delegate.cc',
'shell/app/shell_main_delegate.h',
'shell/app/shell_main_delegate_mac.h',
'shell/app/shell_main_delegate_mac.mm',
- 'shell/app/webkit_test_platform_support_android.cc',
- 'shell/app/webkit_test_platform_support.h',
- 'shell/app/webkit_test_platform_support_linux.cc',
- 'shell/app/webkit_test_platform_support_mac.mm',
- 'shell/app/webkit_test_platform_support_win.cc',
+ 'shell/browser/ipc_echo_message_filter.cc',
+ 'shell/browser/ipc_echo_message_filter.h',
+ 'shell/browser/layout_test/layout_test_android.cc',
+ 'shell/browser/layout_test/layout_test_android.h',
+ 'shell/browser/layout_test/layout_test_browser_context.cc',
+ 'shell/browser/layout_test/layout_test_browser_context.h',
+ 'shell/browser/layout_test/layout_test_browser_main.cc',
+ 'shell/browser/layout_test/layout_test_browser_main.h',
+ 'shell/browser/layout_test/layout_test_browser_main_parts.cc',
+ 'shell/browser/layout_test/layout_test_browser_main_parts.h',
+ 'shell/browser/layout_test/layout_test_content_browser_client.cc',
+ 'shell/browser/layout_test/layout_test_content_browser_client.h',
+ 'shell/browser/layout_test/layout_test_download_manager_delegate.cc',
+ 'shell/browser/layout_test/layout_test_download_manager_delegate.h',
+ 'shell/browser/layout_test/layout_test_devtools_frontend.cc',
+ 'shell/browser/layout_test/layout_test_devtools_frontend.h',
+ 'shell/browser/layout_test/layout_test_javascript_dialog_manager.cc',
+ 'shell/browser/layout_test/layout_test_javascript_dialog_manager.h',
+ 'shell/browser/layout_test/layout_test_message_filter.cc',
+ 'shell/browser/layout_test/layout_test_message_filter.h',
+ 'shell/browser/layout_test/layout_test_notification_manager.cc',
+ 'shell/browser/layout_test/layout_test_notification_manager.h',
+ 'shell/browser/layout_test/layout_test_resource_dispatcher_host_delegate.cc',
+ 'shell/browser/layout_test/layout_test_resource_dispatcher_host_delegate.h',
+ 'shell/browser/layout_test/layout_test_url_request_context_getter.cc',
+ 'shell/browser/layout_test/layout_test_url_request_context_getter.h',
'shell/browser/notify_done_forwarder.cc',
'shell/browser/notify_done_forwarder.h',
+ 'shell/browser/shell.cc',
+ 'shell/browser/shell.h',
+ 'shell/browser/shell_access_token_store.cc',
+ 'shell/browser/shell_access_token_store.h',
'shell/browser/shell_android.cc',
'shell/browser/shell_application_mac.h',
'shell/browser/shell_application_mac.mm',
@@ -98,29 +133,25 @@
'shell/browser/shell_browser_main_parts.cc',
'shell/browser/shell_browser_main_parts.h',
'shell/browser/shell_browser_main_parts_mac.mm',
- 'shell/browser/shell.cc',
'shell/browser/shell_content_browser_client.cc',
'shell/browser/shell_content_browser_client.h',
- 'shell/browser/shell_devtools_delegate.cc',
- 'shell/browser/shell_devtools_delegate.h',
+ 'shell/browser/shell_devtools_manager_delegate.cc',
+ 'shell/browser/shell_devtools_manager_delegate.h',
'shell/browser/shell_devtools_frontend.cc',
'shell/browser/shell_devtools_frontend.h',
'shell/browser/shell_download_manager_delegate.cc',
'shell/browser/shell_download_manager_delegate.h',
- 'shell/browser/shell.h',
'shell/browser/shell_javascript_dialog.h',
'shell/browser/shell_javascript_dialog_mac.mm',
'shell/browser/shell_javascript_dialog_manager.cc',
'shell/browser/shell_javascript_dialog_manager.h',
'shell/browser/shell_javascript_dialog_win.cc',
- 'shell/browser/shell_layout_tests_android.cc',
- 'shell/browser/shell_layout_tests_android.h',
+ 'shell/browser/shell_mojo_test_utils_android.cc',
+ 'shell/browser/shell_mojo_test_utils_android.h',
'shell/browser/shell_login_dialog.cc',
'shell/browser/shell_login_dialog.h',
'shell/browser/shell_login_dialog_mac.mm',
'shell/browser/shell_mac.mm',
- 'shell/browser/shell_message_filter.cc',
- 'shell/browser/shell_message_filter.h',
'shell/browser/shell_net_log.cc',
'shell/browser/shell_net_log.h',
'shell/browser/shell_network_delegate.cc',
@@ -145,6 +176,8 @@
'shell/browser/shell_web_contents_view_delegate_win.cc',
'shell/browser/webkit_test_controller.cc',
'shell/browser/webkit_test_controller.h',
+ 'shell/common/layout_test/layout_test_messages.cc',
+ 'shell/common/layout_test/layout_test_messages.h',
'shell/common/leak_detection_result.h',
'shell/common/shell_content_client.cc',
'shell/common/shell_content_client.h',
@@ -156,63 +189,58 @@
'shell/common/shell_test_configuration.h',
'shell/common/test_runner/test_preferences.cc',
'shell/common/test_runner/test_preferences.h',
+ 'shell/common/v8_breakpad_support_win.cc',
+ 'shell/common/v8_breakpad_support_win.h',
'shell/common/webkit_test_helpers.cc',
'shell/common/webkit_test_helpers.h',
- 'shell/geolocation/shell_access_token_store.cc',
- 'shell/geolocation/shell_access_token_store.h',
- 'shell/renderer/gc_controller.cc',
- 'shell/renderer/gc_controller.h',
- 'shell/renderer/leak_detector.cc',
- 'shell/renderer/leak_detector.h',
+ 'shell/renderer/ipc_echo.cc',
+ 'shell/renderer/ipc_echo.h',
+ 'shell/renderer/layout_test/gc_controller.cc',
+ 'shell/renderer/layout_test/gc_controller.h',
+ 'shell/renderer/layout_test/layout_test_content_renderer_client.cc',
+ 'shell/renderer/layout_test/layout_test_content_renderer_client.h',
+ 'shell/renderer/layout_test/layout_test_render_frame_observer.cc',
+ 'shell/renderer/layout_test/layout_test_render_frame_observer.h',
+ 'shell/renderer/layout_test/layout_test_render_process_observer.cc',
+ 'shell/renderer/layout_test/layout_test_render_process_observer.h',
+ 'shell/renderer/layout_test/leak_detector.cc',
+ 'shell/renderer/layout_test/leak_detector.h',
+ 'shell/renderer/layout_test/webkit_test_runner.cc',
+ 'shell/renderer/layout_test/webkit_test_runner.h',
'shell/renderer/shell_content_renderer_client.cc',
'shell/renderer/shell_content_renderer_client.h',
- 'shell/renderer/shell_render_frame_observer.cc',
- 'shell/renderer/shell_render_frame_observer.h',
- 'shell/renderer/shell_render_process_observer.cc',
- 'shell/renderer/shell_render_process_observer.h',
'shell/renderer/shell_render_view_observer.cc',
'shell/renderer/shell_render_view_observer.h',
- 'shell/renderer/test_runner/MockColorChooser.cpp',
- 'shell/renderer/test_runner/MockColorChooser.h',
- 'shell/renderer/test_runner/MockSpellCheck.cpp',
- 'shell/renderer/test_runner/MockSpellCheck.h',
- 'shell/renderer/test_runner/MockWebMIDIAccessor.cpp',
- 'shell/renderer/test_runner/MockWebMIDIAccessor.h',
- 'shell/renderer/test_runner/MockWebMediaStreamCenter.cpp',
- 'shell/renderer/test_runner/MockWebMediaStreamCenter.h',
- 'shell/renderer/test_runner/MockWebSpeechRecognizer.cpp',
- 'shell/renderer/test_runner/MockWebSpeechRecognizer.h',
- 'shell/renderer/test_runner/SpellCheckClient.cpp',
- 'shell/renderer/test_runner/SpellCheckClient.h',
- 'shell/renderer/test_runner/TestCommon.cpp',
- 'shell/renderer/test_runner/TestCommon.h',
- 'shell/renderer/test_runner/TestInterfaces.cpp',
- 'shell/renderer/test_runner/TestInterfaces.h',
- 'shell/renderer/test_runner/TestPlugin.cpp',
- 'shell/renderer/test_runner/TestPlugin.h',
- 'shell/renderer/test_runner/WebTask.cpp',
- 'shell/renderer/test_runner/WebTask.h',
- 'shell/renderer/test_runner/WebTestDelegate.h',
- 'shell/renderer/test_runner/WebTestInterfaces.cpp',
- 'shell/renderer/test_runner/WebTestInterfaces.h',
- 'shell/renderer/test_runner/WebTestThemeEngineMac.h',
- 'shell/renderer/test_runner/WebTestThemeEngineMac.mm',
- 'shell/renderer/test_runner/WebTestThemeEngineMock.cpp',
- 'shell/renderer/test_runner/WebTestThemeEngineMock.h',
'shell/renderer/test_runner/accessibility_controller.cc',
'shell/renderer/test_runner/accessibility_controller.h',
'shell/renderer/test_runner/event_sender.cc',
'shell/renderer/test_runner/event_sender.h',
'shell/renderer/test_runner/gamepad_controller.cc',
'shell/renderer/test_runner/gamepad_controller.h',
+ 'shell/renderer/test_runner/mock_color_chooser.cc',
+ 'shell/renderer/test_runner/mock_color_chooser.h',
'shell/renderer/test_runner/mock_constraints.cc',
'shell/renderer/test_runner/mock_constraints.h',
+ 'shell/renderer/test_runner/mock_credential_manager_client.cc',
+ 'shell/renderer/test_runner/mock_credential_manager_client.h',
'shell/renderer/test_runner/mock_grammar_check.cc',
'shell/renderer/test_runner/mock_grammar_check.h',
+ 'shell/renderer/test_runner/mock_screen_orientation_client.cc',
+ 'shell/renderer/test_runner/mock_screen_orientation_client.h',
+ 'shell/renderer/test_runner/mock_spell_check.cc',
+ 'shell/renderer/test_runner/mock_spell_check.h',
'shell/renderer/test_runner/mock_web_audio_device.cc',
'shell/renderer/test_runner/mock_web_audio_device.h',
+ 'shell/renderer/test_runner/mock_web_media_stream_center.cc',
+ 'shell/renderer/test_runner/mock_web_media_stream_center.h',
+ 'shell/renderer/test_runner/mock_web_midi_accessor.cc',
+ 'shell/renderer/test_runner/mock_web_midi_accessor.h',
'shell/renderer/test_runner/mock_web_push_client.cc',
'shell/renderer/test_runner/mock_web_push_client.h',
+ 'shell/renderer/test_runner/mock_web_speech_recognizer.cc',
+ 'shell/renderer/test_runner/mock_web_speech_recognizer.h',
+ 'shell/renderer/test_runner/mock_web_theme_engine.cc',
+ 'shell/renderer/test_runner/mock_web_theme_engine.h',
'shell/renderer/test_runner/mock_web_user_media_client.cc',
'shell/renderer/test_runner/mock_web_user_media_client.h',
'shell/renderer/test_runner/mock_webrtc_data_channel_handler.cc',
@@ -223,6 +251,14 @@
'shell/renderer/test_runner/mock_webrtc_peer_connection_handler.h',
'shell/renderer/test_runner/notification_presenter.cc',
'shell/renderer/test_runner/notification_presenter.h',
+ 'shell/renderer/test_runner/spell_check_client.cc',
+ 'shell/renderer/test_runner/spell_check_client.h',
+ 'shell/renderer/test_runner/test_common.cc',
+ 'shell/renderer/test_runner/test_common.h',
+ 'shell/renderer/test_runner/test_interfaces.cc',
+ 'shell/renderer/test_runner/test_interfaces.h',
+ 'shell/renderer/test_runner/test_plugin.cc',
+ 'shell/renderer/test_runner/test_plugin.h',
'shell/renderer/test_runner/test_runner.cc',
'shell/renderer/test_runner/test_runner.h',
'shell/renderer/test_runner/text_input_controller.cc',
@@ -232,11 +268,14 @@
'shell/renderer/test_runner/web_frame_test_proxy.h',
'shell/renderer/test_runner/web_permissions.cc',
'shell/renderer/test_runner/web_permissions.h',
+ 'shell/renderer/test_runner/web_task.cc',
+ 'shell/renderer/test_runner/web_task.h',
+ 'shell/renderer/test_runner/web_test_delegate.h',
+ 'shell/renderer/test_runner/web_test_interfaces.cc',
+ 'shell/renderer/test_runner/web_test_interfaces.h',
'shell/renderer/test_runner/web_test_proxy.cc',
'shell/renderer/test_runner/web_test_proxy.h',
'shell/renderer/test_runner/web_test_runner.h',
- 'shell/renderer/webkit_test_runner.cc',
- 'shell/renderer/webkit_test_runner.h',
],
'msvs_settings': {
'VCLinkerTool': {
@@ -244,11 +283,6 @@
},
},
'conditions': [
- ['OS=="mac"', {
- 'sources/': [
- ['exclude', 'WebTestThemeEngineMock.cpp'],
- ],
- }],
['OS=="win" and win_use_allocator_shim==1', {
'dependencies': [
'../base/allocator/allocator.gyp:allocator',
@@ -256,10 +290,10 @@
}],
['OS=="win"', {
'resource_include_dirs': [
- '<(SHARED_INTERMEDIATE_DIR)/webkit',
+ '<(SHARED_INTERMEDIATE_DIR)/content/app/strings',
],
'dependencies': [
- '<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings',
+ '<(DEPTH)/content/app/strings/content_strings.gyp:content_strings',
],
'configurations': {
'Debug_Base': {
@@ -272,10 +306,6 @@
},
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
- }, { # OS!="win"
- 'sources/': [
- ['exclude', 'Win\\.cpp$'],
- ],
}], # OS=="win"
['OS=="linux"', {
'dependencies': [
@@ -284,11 +314,13 @@
}],
['use_x11 == 1', {
'dependencies': [
+ '../ui/events/devices/events_devices.gyp:events_devices',
'../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
],
}],
['OS=="android"', {
'dependencies': [
+ '../mojo/mojo_base.gyp:libmojo_system_java',
'content_shell_jni_headers',
],
'dependencies!': [
@@ -355,14 +387,15 @@
],
}],
['enable_plugins==0', {
- 'sources/': [
- ['exclude', 'shell/browser/shell_plugin_service_filter.cc'],
- ['exclude', 'shell/browser/shell_plugin_service_filter.h'],
+ 'sources!': [
+ 'shell/browser/shell_plugin_service_filter.cc',
+ 'shell/browser/shell_plugin_service_filter.h',
],
}]
],
},
{
+ # GN version: //content/shell:resources
'target_name': 'content_shell_resources',
'type': 'none',
'variables': {
@@ -409,6 +442,8 @@
'files': [
'shell/renderer/test_runner/resources/fonts/AHEM____.TTF',
'shell/renderer/test_runner/resources/fonts/fonts.conf',
+ '../third_party/gardiner_mod/GardinerModBug.ttf',
+ '../third_party/gardiner_mod/GardinerModCat.ttf',
]
}],
}],
@@ -427,45 +462,53 @@
{
# We build a minimal set of resources so WebKit in content_shell has
# access to necessary resources.
+ # GN version: //content/shell:pak
'target_name': 'content_shell_pak',
'type': 'none',
'dependencies': [
- 'content_resources.gyp:content_resources',
+ 'app/resources/content_resources.gyp:content_resources',
+ 'app/strings/content_strings.gyp:content_strings',
+ 'browser/tracing/tracing_resources.gyp:tracing_resources',
+ 'content.gyp:content_resources',
'content_shell_resources',
'<(DEPTH)/net/net.gyp:net_resources',
+ '<(DEPTH)/third_party/WebKit/public/blink_resources.gyp:blink_resources',
'<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
'<(DEPTH)/ui/strings/ui_strings.gyp:ui_strings',
- '<(DEPTH)/webkit/webkit_resources.gyp:webkit_resources',
- '<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings',
],
'conditions': [
- ['OS!="android" and OS!="ios"', {
- 'dependencies': [
- 'browser/tracing/tracing_resources.gyp:tracing_resources',
- ],
- }],
['OS!="android"', {
'dependencies': [
'browser/devtools/devtools_resources.gyp:devtools_resources',
],
}],
+ ['OS=="android"', {
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)',
+ 'files': [
+ '<(PRODUCT_DIR)/content_shell/assets/content_shell.pak'
+ ],
+ },
+ ],
+ }],
],
'actions': [
{
'action_name': 'repack_content_shell_pack',
'variables': {
'pak_inputs': [
- '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_100_percent.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/content/app/strings/content_strings_en-US.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/browser/tracing/tracing_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/shell_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.pak',
- '<(SHARED_INTERMEDIATE_DIR)/ui/app_locale_settings/app_locale_settings_en-US.pak',
- '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources_100_percent.pak',
- '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/webui_resources.pak',
- '<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings/ui_strings_en-US.pak',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.pak',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources_100_percent.pak',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_100_percent.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/resources/webui_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/strings/app_locale_settings_en-US.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/ui/strings/ui_strings_en-US.pak',
],
'conditions': [
['OS!="android"', {
@@ -481,6 +524,7 @@
],
},
{
+ # GN version: //content/shell:content_shell
'target_name': 'content_shell',
'type': 'executable',
'mac_bundle': 1,
@@ -497,7 +541,6 @@
'..',
],
'sources': [
- 'app/startup_helper_win.cc',
'shell/app/shell_main.cc',
],
'mac_bundle_resources': [
@@ -514,9 +557,6 @@
'INFOPLIST_FILE': 'shell/app/app-Info.plist',
},
'msvs_settings': {
- 'VCLinkerTool': {
- 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
- },
'VCManifestTool': {
'AdditionalManifestFiles': [
'shell/app/shell.exe.manifest',
@@ -548,6 +588,13 @@
'../sandbox/sandbox.gyp:sandbox',
],
}], # OS=="win"
+ ['OS=="win" and asan==0', {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ }], # OS=="win" and asan==0
['OS=="mac"', {
'product_name': '<(content_shell_product_name)',
'dependencies!': [
@@ -938,6 +985,7 @@
'sources': [
'shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java',
'shell/android/java/src/org/chromium/content_shell/ShellLayoutTestUtils.java',
+ 'shell/android/java/src/org/chromium/content_shell/ShellMojoTestUtils.java',
'shell/android/java/src/org/chromium/content_shell/ShellManager.java',
'shell/android/java/src/org/chromium/content_shell/Shell.java',
],
@@ -1003,6 +1051,7 @@
'dependencies': [
'content.gyp:content_icudata',
'content.gyp:content_java',
+ 'content.gyp:content_v8_external_data',
'content_java_test_support',
'content_shell_java',
'libcontent_shell_content_view',
@@ -1028,6 +1077,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
+ ['v8_use_external_startup_data==1', {
+ 'additional_input_paths': [
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ }],
],
},
'conditions': [
diff --git a/chromium/content/content_tests.gypi b/chromium/content/content_tests.gypi
index d17648d9b60..ceb8a35b7c2 100644
--- a/chromium/content/content_tests.gypi
+++ b/chromium/content/content_tests.gypi
@@ -3,8 +3,164 @@
# found in the LICENSE file.
{
+ 'variables': {
+ 'layouttest_support_content_sources': [
+ 'public/test/layouttest_support.h',
+ 'public/test/nested_message_pump_android.cc',
+ 'public/test/nested_message_pump_android.h',
+ 'test/layouttest_support.cc',
+ 'test/test_media_stream_renderer_factory.cc',
+ 'test/test_media_stream_renderer_factory.h',
+ 'test/test_video_frame_provider.cc',
+ 'test/test_video_frame_provider.h',
+ ],
+ 'test_support_content_sources': [
+ 'public/test/async_file_test_helper.cc',
+ 'public/test/async_file_test_helper.h',
+ 'public/test/browser_test_base.cc',
+ 'public/test/browser_test_base.h',
+ 'public/test/browser_test.h',
+ 'public/test/browser_test_utils.cc',
+ 'public/test/browser_test_utils.h',
+ 'public/test/content_test_suite_base.cc',
+ 'public/test/content_test_suite_base.h',
+ 'public/test/download_test_observer.cc',
+ 'public/test/download_test_observer.h',
+ 'public/test/fake_speech_recognition_manager.cc',
+ 'public/test/fake_speech_recognition_manager.h',
+ 'public/test/frame_load_waiter.cc',
+ 'public/test/frame_load_waiter.h',
+ 'public/test/javascript_test_observer.cc',
+ 'public/test/javascript_test_observer.h',
+ 'public/test/mock_blob_url_request_context.cc',
+ 'public/test/mock_blob_url_request_context.h',
+ 'public/test/mock_download_item.cc',
+ 'public/test/mock_download_item.h',
+ 'public/test/mock_download_manager.cc',
+ 'public/test/mock_download_manager.h',
+ 'public/test/mock_notification_observer.cc',
+ 'public/test/mock_notification_observer.h',
+ 'public/test/mock_render_process_host.cc',
+ 'public/test/mock_render_process_host.h',
+ 'public/test/mock_render_thread.cc',
+ 'public/test/mock_render_thread.h',
+ 'public/test/mock_resource_context.cc',
+ 'public/test/mock_resource_context.h',
+ 'public/test/mock_special_storage_policy.cc',
+ 'public/test/mock_special_storage_policy.h',
+ 'public/test/mock_storage_client.cc',
+ 'public/test/mock_storage_client.h',
+ 'public/test/render_view_test.cc',
+ 'public/test/render_view_test.h',
+ 'public/test/render_widget_test.cc',
+ 'public/test/render_widget_test.h',
+ 'public/test/sandbox_file_system_test_helper.cc',
+ 'public/test/sandbox_file_system_test_helper.h',
+ 'public/test/test_browser_context.cc',
+ 'public/test/test_browser_context.h',
+ 'public/test/test_browser_thread.cc',
+ 'public/test/test_browser_thread.h',
+ 'public/test/test_browser_thread_bundle.cc',
+ 'public/test/test_browser_thread_bundle.h',
+ 'public/test/test_content_client_initializer.cc',
+ 'public/test/test_content_client_initializer.h',
+ 'public/test/test_file_error_injector.cc',
+ 'public/test/test_file_error_injector.h',
+ 'public/test/test_file_system_backend.cc',
+ 'public/test/test_file_system_backend.h',
+ 'public/test/test_file_system_context.cc',
+ 'public/test/test_file_system_context.h',
+ 'public/test/test_file_system_options.cc',
+ 'public/test/test_file_system_options.h',
+ 'public/test/test_launcher.cc',
+ 'public/test/test_launcher.h',
+ 'public/test/test_navigation_observer.cc',
+ 'public/test/test_navigation_observer.h',
+ 'public/test/test_notification_tracker.cc',
+ 'public/test/test_notification_tracker.h',
+ 'public/test/test_renderer_host.cc',
+ 'public/test/test_renderer_host.h',
+ 'public/test/test_utils.cc',
+ 'public/test/test_utils.h',
+ 'public/test/unittest_test_suite.cc',
+ 'public/test/unittest_test_suite.h',
+ 'public/test/web_contents_tester.cc',
+ 'public/test/web_contents_tester.h',
+ # TODO(phajdan.jr): All of those files should live in content/test (if
+ # they're only used by content) or content/public/test (if they're used
+ # by other embedders).
+ 'browser/download/mock_download_file.cc',
+ 'browser/download/mock_download_file.h',
+ 'browser/geolocation/fake_access_token_store.cc',
+ 'browser/geolocation/fake_access_token_store.h',
+ 'browser/geolocation/mock_location_arbitrator.cc',
+ 'browser/geolocation/mock_location_arbitrator.h',
+ 'browser/geolocation/mock_location_provider.cc',
+ 'browser/geolocation/mock_location_provider.h',
+ 'browser/renderer_host/media/mock_media_observer.cc',
+ 'browser/renderer_host/media/mock_media_observer.h',
+ 'browser/renderer_host/test/no_transport_image_transport_factory_android.cc',
+ 'browser/renderer_host/test/no_transport_image_transport_factory_android.h',
+ 'test/appcache_test_helper.cc',
+ 'test/appcache_test_helper.h',
+ 'test/blink_test_environment.cc',
+ 'test/blink_test_environment.h',
+ 'test/content_browser_test_utils_internal.cc',
+ 'test/content_browser_test_utils_internal.h',
+ 'test/content_test_suite.cc',
+ 'test/content_test_suite.h',
+ 'test/mock_google_streaming_server.cc',
+ 'test/mock_google_streaming_server.h',
+ 'test/mock_keyboard.cc',
+ 'test/mock_keyboard.h',
+ 'test/mock_keyboard_driver_win.cc',
+ 'test/mock_keyboard_driver_win.h',
+ 'test/mock_render_process.cc',
+ 'test/mock_render_process.h',
+ 'test/mock_webblob_registry_impl.cc',
+ 'test/mock_webblob_registry_impl.h',
+ 'test/mock_webclipboard_impl.cc',
+ 'test/mock_webclipboard_impl.h',
+ 'test/mock_webframeclient.h',
+ 'test/mock_weburlloader.cc',
+ 'test/mock_weburlloader.h',
+ 'test/net/url_request_abort_on_end_job.cc',
+ 'test/net/url_request_abort_on_end_job.h',
+ 'test/net/url_request_slow_download_job.cc',
+ 'test/net/url_request_slow_download_job.h',
+ 'test/ppapi_unittest.cc',
+ 'test/ppapi_unittest.h',
+ 'test/test_blink_web_unit_test_support.cc',
+ 'test/test_blink_web_unit_test_support.h',
+ 'test/test_content_browser_client.cc',
+ 'test/test_content_browser_client.h',
+ 'test/test_content_client.cc',
+ 'test/test_content_client.h',
+ 'test/test_frame_navigation_observer.cc',
+ 'test/test_frame_navigation_observer.h',
+ 'test/test_render_frame_host.cc',
+ 'test/test_render_frame_host.h',
+ 'test/test_render_frame_host_factory.cc',
+ 'test/test_render_frame_host_factory.h',
+ 'test/test_render_view_host.cc',
+ 'test/test_render_view_host.h',
+ 'test/test_render_view_host_factory.cc',
+ 'test/test_render_view_host_factory.h',
+ 'test/test_web_contents.cc',
+ 'test/test_web_contents.h',
+ 'test/web_gesture_curve_mock.cc',
+ 'test/web_gesture_curve_mock.h',
+ 'test/web_layer_tree_view_impl_for_testing.cc',
+ 'test/web_layer_tree_view_impl_for_testing.h',
+ 'test/weburl_loader_mock.cc',
+ 'test/weburl_loader_mock.h',
+ 'test/weburl_loader_mock_factory.cc',
+ 'test/weburl_loader_mock_factory.h',
+ ]
+ },
'targets': [
{
+ # GN version: //content/test:layouttest_support
'target_name': 'layouttest_support_content',
'type': 'static_library',
'conditions': [
@@ -25,25 +181,18 @@
'..',
'<(SHARED_INTERMEDIATE_DIR)',
],
- 'sources': [
- 'public/test/layouttest_support.h',
- 'public/test/nested_message_pump_android.cc',
- 'public/test/nested_message_pump_android.h',
- 'test/layouttest_support.cc',
- 'test/test_media_stream_renderer_factory.cc',
- 'test/test_media_stream_renderer_factory.h',
- 'test/test_video_frame_provider.cc',
- 'test/test_video_frame_provider.h',
- ],
+ 'sources': [ '<@(layouttest_support_content_sources)' ]
}],
],
},
{
+ # GN version: //content/test:test_support
'target_name': 'test_support_content',
'type': 'static_library',
'dependencies': [
'../net/net.gyp:net_test_support',
'../skia/skia.gyp:skia',
+ '../storage/storage_common.gyp:storage_common',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'../ui/accessibility/accessibility.gyp:ax_gen',
@@ -56,7 +205,6 @@
'../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/resources/ui_resources.gyp:ui_resources',
'../url/url.gyp:url_lib',
- '../webkit/common/webkit_common.gyp:webkit_common',
'browser/speech/proto/speech_proto.gyp:speech_proto',
'content.gyp:content_app_both',
'content.gyp:content_browser',
@@ -65,165 +213,14 @@
'include_dirs': [
'..',
],
- 'sources': [
- 'public/test/async_file_test_helper.cc',
- 'public/test/async_file_test_helper.h',
- 'public/test/browser_test_base.cc',
- 'public/test/browser_test_base.h',
- 'public/test/browser_test.h',
- 'public/test/browser_test_utils.cc',
- 'public/test/browser_test_utils.h',
- 'public/test/content_test_suite_base.cc',
- 'public/test/content_test_suite_base.h',
- 'public/test/download_test_observer.cc',
- 'public/test/download_test_observer.h',
- 'public/test/fake_speech_recognition_manager.cc',
- 'public/test/fake_speech_recognition_manager.h',
- 'public/test/javascript_test_observer.cc',
- 'public/test/javascript_test_observer.h',
- 'public/test/mock_blob_url_request_context.cc',
- 'public/test/mock_blob_url_request_context.h',
- 'public/test/mock_download_item.cc',
- 'public/test/mock_download_item.h',
- 'public/test/mock_download_manager.cc',
- 'public/test/mock_download_manager.h',
- 'public/test/mock_notification_observer.cc',
- 'public/test/mock_notification_observer.h',
- 'public/test/mock_render_process_host.cc',
- 'public/test/mock_render_process_host.h',
- 'public/test/mock_render_thread.cc',
- 'public/test/mock_render_thread.h',
- 'public/test/mock_resource_context.cc',
- 'public/test/mock_resource_context.h',
- 'public/test/mock_special_storage_policy.cc',
- 'public/test/mock_special_storage_policy.h',
- 'public/test/mock_storage_client.cc',
- 'public/test/mock_storage_client.h',
- 'public/test/render_view_test.cc',
- 'public/test/render_view_test.h',
- 'public/test/render_widget_test.cc',
- 'public/test/render_widget_test.h',
- 'public/test/sandbox_file_system_test_helper.cc',
- 'public/test/sandbox_file_system_test_helper.h',
- 'public/test/test_browser_context.cc',
- 'public/test/test_browser_context.h',
- 'public/test/test_browser_thread.cc',
- 'public/test/test_browser_thread.h',
- 'public/test/test_browser_thread_bundle.cc',
- 'public/test/test_browser_thread_bundle.h',
- 'public/test/test_content_client_initializer.cc',
- 'public/test/test_content_client_initializer.h',
- 'public/test/test_file_error_injector.cc',
- 'public/test/test_file_error_injector.h',
- 'public/test/test_file_system_backend.cc',
- 'public/test/test_file_system_backend.h',
- 'public/test/test_file_system_context.cc',
- 'public/test/test_file_system_context.h',
- 'public/test/test_file_system_options.cc',
- 'public/test/test_file_system_options.h',
- 'public/test/test_launcher.cc',
- 'public/test/test_launcher.h',
- 'public/test/test_navigation_observer.cc',
- 'public/test/test_navigation_observer.h',
- 'public/test/test_notification_tracker.cc',
- 'public/test/test_notification_tracker.h',
- 'public/test/test_renderer_host.cc',
- 'public/test/test_renderer_host.h',
- 'public/test/test_utils.cc',
- 'public/test/test_utils.h',
- 'public/test/unittest_test_suite.cc',
- 'public/test/unittest_test_suite.h',
- 'public/test/web_contents_tester.cc',
- 'public/test/web_contents_tester.h',
- 'app/startup_helper_win.cc',
- # TODO(phajdan.jr): All of those files should live in content/test (if
- # they're only used by content) or content/public/test (if they're used
- # by other embedders).
- 'browser/download/mock_download_file.cc',
- 'browser/download/mock_download_file.h',
- 'browser/geolocation/fake_access_token_store.cc',
- 'browser/geolocation/fake_access_token_store.h',
- 'browser/geolocation/mock_location_arbitrator.cc',
- 'browser/geolocation/mock_location_arbitrator.h',
- 'browser/geolocation/mock_location_provider.cc',
- 'browser/geolocation/mock_location_provider.h',
- 'browser/renderer_host/compositing_iosurface_shader_programs_mac.cc',
- 'browser/renderer_host/compositing_iosurface_shader_programs_mac.h',
- 'browser/renderer_host/compositing_iosurface_transformer_mac.cc',
- 'browser/renderer_host/compositing_iosurface_transformer_mac.h',
- 'browser/renderer_host/media/mock_media_observer.cc',
- 'browser/renderer_host/media/mock_media_observer.h',
- 'test/appcache_test_helper.cc',
- 'test/appcache_test_helper.h',
- 'test/content_browser_test_utils_internal.cc',
- 'test/content_browser_test_utils_internal.h',
- 'test/content_test_suite.cc',
- 'test/content_test_suite.h',
- 'test/frame_load_waiter.cc',
- 'test/frame_load_waiter.h',
- 'test/mock_google_streaming_server.cc',
- 'test/mock_google_streaming_server.h',
- 'test/mock_keyboard.cc',
- 'test/mock_keyboard.h',
- 'test/mock_keyboard_driver_win.cc',
- 'test/mock_keyboard_driver_win.h',
- 'test/mock_render_process.cc',
- 'test/mock_render_process.h',
- 'test/mock_webclipboard_impl.cc',
- 'test/mock_webclipboard_impl.h',
- 'test/mock_webframeclient.h',
- 'test/mock_weburlloader.cc',
- 'test/mock_weburlloader.h',
- 'test/net/url_request_abort_on_end_job.cc',
- 'test/net/url_request_abort_on_end_job.h',
- 'test/net/url_request_failed_job.cc',
- 'test/net/url_request_failed_job.h',
- 'test/net/url_request_mock_http_job.cc',
- 'test/net/url_request_mock_http_job.h',
- 'test/net/url_request_prepackaged_interceptor.cc',
- 'test/net/url_request_prepackaged_interceptor.h',
- 'test/net/url_request_slow_download_job.cc',
- 'test/net/url_request_slow_download_job.h',
- 'test/ppapi_unittest.cc',
- 'test/ppapi_unittest.h',
- 'test/test_content_browser_client.cc',
- 'test/test_content_browser_client.h',
- 'test/test_content_client.cc',
- 'test/test_content_client.h',
- 'test/test_frame_navigation_observer.cc',
- 'test/test_frame_navigation_observer.h',
- 'test/test_render_frame_host.cc',
- 'test/test_render_frame_host.h',
- 'test/test_render_frame_host_factory.cc',
- 'test/test_render_frame_host_factory.h',
- 'test/test_render_view_host.cc',
- 'test/test_render_view_host.h',
- 'test/test_render_view_host_factory.cc',
- 'test/test_render_view_host_factory.h',
- 'test/test_web_contents.cc',
- 'test/test_web_contents.h',
- 'test/test_webkit_platform_support.cc',
- 'test/test_webkit_platform_support.h',
- 'test/web_gesture_curve_mock.cc',
- 'test/web_gesture_curve_mock.h',
- 'test/webkit_support.cc',
- 'test/webkit_support.h',
- 'test/webkit_unit_test_support.cc',
- 'test/webkit_unit_test_support.h',
- 'test/web_layer_tree_view_impl_for_testing.cc',
- 'test/web_layer_tree_view_impl_for_testing.h',
- 'test/weburl_loader_mock.cc',
- 'test/weburl_loader_mock.h',
- 'test/weburl_loader_mock_factory.cc',
- 'test/weburl_loader_mock_factory.h',
- ],
+ 'sources': [ '<@(test_support_content_sources)' ],
'conditions': [
['enable_plugins==0', {
'sources!': [
'test/ppapi_unittest.cc',
],
}],
- ['input_speech==0', {
+ ['enable_web_speech==0', {
'sources!': [
'test/mock_google_streaming_server.cc',
],
@@ -262,24 +259,27 @@
'content.gyp:content_child',
'content.gyp:content_common',
'content.gyp:content_gpu',
+ 'content.gyp:content_plugin',
'content.gyp:content_ppapi_plugin',
'content.gyp:content_renderer',
'content.gyp:content_utility',
- 'content.gyp:content_worker',
+ 'content_shell_and_tests.gyp:content_shell_pak',
+ '../cc/blink/cc_blink.gyp:cc_blink',
'../cc/cc.gyp:cc',
'../cc/cc_tests.gyp:cc_test_support',
+ '../media/blink/media_blink.gyp:media_blink',
'../media/media.gyp:media',
'../ppapi/ppapi_internal.gyp:ppapi_host',
'../ppapi/ppapi_internal.gyp:ppapi_proxy',
'../ppapi/ppapi_internal.gyp:ppapi_shared',
'../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
+ '../storage/storage_browser.gyp:storage',
+ '../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
+ '../ui/compositor/compositor.gyp:compositor_test_support',
'../ui/surface/surface.gyp:surface',
'../v8/tools/gyp/v8.gyp:v8',
- '../webkit/child/webkit_child.gyp:webkit_child',
'../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu',
- '../webkit/storage_browser.gyp:webkit_storage_browser',
- '../webkit/storage_common.gyp:webkit_storage_common',
],
'export_dependent_settings': [
'../third_party/WebKit/public/blink.gyp:blink',
@@ -288,6 +288,7 @@
['OS == "win"', {
'dependencies': [
'../sandbox/sandbox.gyp:sandbox',
+ 'content.gyp:content_startup_helper_win',
],
}],
['enable_webrtc==1', {
@@ -319,24 +320,26 @@
'../ui/wm/wm.gyp:wm',
],
}],
- ['use_aura==1 or OS=="mac"', {
- 'dependencies': [
- '../ui/compositor/compositor.gyp:compositor',
- ],
- }],
['OS=="win"', {
'dependencies': [
'../third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
],
}],
['OS!="android" and OS!="ios"', {
+ 'sources': [
+ 'browser/compositor/test/no_transport_image_transport_factory.cc',
+ 'browser/compositor/test/no_transport_image_transport_factory.h',
+ ],
'dependencies': [
+ '../ui/compositor/compositor.gyp:compositor',
'../third_party/libvpx/libvpx.gyp:libvpx',
],
}],
['OS=="android"', {
'dependencies': [
+ '../gin/gin.gyp:gin',
'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
+ 'content.gyp:content_v8_external_data',
],
}],
],
@@ -345,13 +348,14 @@
'target_name': 'content_unittests',
'type': '<(gtest_target_type)',
'dependencies': [
- 'browser/service_worker/service_worker_proto.gyp:database_proto',
+ 'browser/service_worker/service_worker_proto.gyp:proto',
'browser/speech/proto/speech_proto.gyp:speech_proto',
'content.gyp:content_browser',
'content.gyp:content_common',
'test_support_content',
'../base/base.gyp:test_support_base',
'../crypto/crypto.gyp:crypto',
+ '../mojo/edk/mojo_edk.gyp:mojo_common_test_support',
'../net/net.gyp:net_test_support',
'../skia/skia.gyp:skia',
'../sql/sql.gyp:sql',
@@ -363,6 +367,7 @@
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
],
'include_dirs': [
'..',
@@ -377,6 +382,7 @@
'browser/appcache/appcache_disk_cache_unittest.cc',
'browser/appcache/appcache_group_unittest.cc',
'browser/appcache/appcache_host_unittest.cc',
+ 'browser/appcache/appcache_manifest_parser_unittest.cc',
'browser/appcache/appcache_quota_client_unittest.cc',
'browser/appcache/appcache_request_handler_unittest.cc',
'browser/appcache/appcache_response_unittest.cc',
@@ -387,7 +393,6 @@
'browser/appcache/appcache_update_job_unittest.cc',
'browser/appcache/appcache_url_request_job_unittest.cc',
'browser/appcache/chrome_appcache_service_unittest.cc',
- 'browser/appcache/manifest_parser_unittest.cc',
'browser/appcache/mock_appcache_policy.cc',
'browser/appcache/mock_appcache_policy.h',
'browser/appcache/mock_appcache_service.cc',
@@ -395,11 +400,12 @@
'browser/appcache/mock_appcache_storage.cc',
'browser/appcache/mock_appcache_storage.h',
'browser/appcache/mock_appcache_storage_unittest.cc',
- 'browser/battery_status/battery_status_service_unittest.cc',
'browser/browser_thread_unittest.cc',
'browser/browser_url_handler_impl_unittest.cc',
'browser/byte_stream_unittest.cc',
'browser/child_process_security_policy_unittest.cc',
+ 'browser/cocoa/system_hotkey_map_unittest.mm',
+ 'browser/compositor/buffer_queue_unittest.cc',
'browser/compositor/software_browser_compositor_output_surface_unittest.cc',
'browser/compositor/software_output_device_ozone_unittest.cc',
'browser/databases_table_unittest.cc',
@@ -446,6 +452,8 @@
'browser/fileapi/local_file_util_unittest.cc',
'browser/fileapi/mock_file_change_observer.cc',
'browser/fileapi/mock_file_change_observer.h',
+ 'browser/fileapi/mock_file_update_observer.cc',
+ 'browser/fileapi/mock_file_update_observer.h',
'browser/fileapi/mock_url_request_delegate.cc',
'browser/fileapi/mock_url_request_delegate.h',
'browser/fileapi/native_file_util_unittest.cc',
@@ -466,19 +474,23 @@
'browser/frame_host/frame_tree_unittest.cc',
'browser/frame_host/navigation_controller_impl_unittest.cc',
'browser/frame_host/navigation_entry_impl_unittest.cc',
+ 'browser/frame_host/navigator_impl_unittest.cc',
'browser/frame_host/render_frame_host_manager_unittest.cc',
'browser/frame_host/render_widget_host_view_child_frame_unittest.cc',
'browser/frame_host/render_widget_host_view_guest_unittest.cc',
'browser/gamepad/gamepad_provider_unittest.cc',
+ 'browser/gamepad/gamepad_service_unittest.cc',
'browser/gamepad/gamepad_test_helpers.cc',
'browser/gamepad/gamepad_test_helpers.h',
- 'browser/geolocation/geolocation_provider_unittest.cc',
+ 'browser/geofencing/geofencing_manager_unittest.cc',
+ 'browser/geofencing/geofencing_service_unittest.cc',
+ 'browser/geolocation/geolocation_provider_impl_unittest.cc',
'browser/geolocation/location_arbitrator_impl_unittest.cc',
'browser/geolocation/network_location_provider_unittest.cc',
'browser/geolocation/wifi_data_provider_chromeos_unittest.cc',
'browser/geolocation/wifi_data_provider_common_unittest.cc',
'browser/geolocation/wifi_data_provider_linux_unittest.cc',
- 'browser/geolocation/wifi_data_provider_unittest_win.cc',
+ 'browser/geolocation/wifi_data_provider_win_unittest.cc',
'browser/gpu/gpu_data_manager_impl_private_unittest.cc',
'browser/gpu/shader_disk_cache_unittest.cc',
'browser/host_zoom_map_impl_unittest.cc',
@@ -493,12 +505,17 @@
'browser/indexed_db/indexed_db_quota_client_unittest.cc',
'browser/indexed_db/indexed_db_transaction_unittest.cc',
'browser/indexed_db/indexed_db_unittest.cc',
+ 'browser/indexed_db/leveldb/mock_leveldb_factory.cc',
+ 'browser/indexed_db/leveldb/mock_leveldb_factory.h',
'browser/indexed_db/mock_indexed_db_callbacks.cc',
'browser/indexed_db/mock_indexed_db_callbacks.h',
'browser/indexed_db/mock_indexed_db_database_callbacks.cc',
'browser/indexed_db/mock_indexed_db_database_callbacks.h',
+ 'browser/indexed_db/mock_indexed_db_factory.cc',
+ 'browser/indexed_db/mock_indexed_db_factory.h',
'browser/indexed_db/leveldb/leveldb_unittest.cc',
'browser/indexed_db/list_set_unittest.cc',
+ 'browser/loader/navigation_url_loader_unittest.cc',
'browser/loader/resource_buffer_unittest.cc',
'browser/loader/resource_dispatcher_host_unittest.cc',
'browser/loader/resource_loader_unittest.cc',
@@ -506,6 +523,7 @@
'browser/loader/temporary_file_stream_unittest.cc',
'browser/loader/upload_data_stream_builder_unittest.cc',
'browser/mach_broker_mac_unittest.cc',
+ 'browser/media/audio_stream_monitor_unittest.cc',
'browser/media/capture/audio_mirroring_manager_unittest.cc',
'browser/media/capture/video_capture_oracle_unittest.cc',
'browser/media/capture/web_contents_audio_input_stream_unittest.cc',
@@ -530,8 +548,8 @@
'browser/quota/quota_temporary_storage_evictor_unittest.cc',
'browser/quota/storage_monitor_unittest.cc',
'browser/quota/usage_tracker_unittest.cc',
- 'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc',
'browser/renderer_host/input/gesture_event_queue_unittest.cc',
+ 'browser/renderer_host/input/gesture_text_selector_unittest.cc',
'browser/renderer_host/input/input_router_impl_unittest.cc',
'browser/renderer_host/input/mock_input_ack_handler.cc',
'browser/renderer_host/input/mock_input_ack_handler.h',
@@ -542,9 +560,11 @@
'browser/renderer_host/input/touch_action_filter_unittest.cc',
'browser/renderer_host/input/touch_emulator_unittest.cc',
'browser/renderer_host/input/touch_event_queue_unittest.cc',
+ 'browser/renderer_host/input/touch_handle_unittest.cc',
+ 'browser/renderer_host/input/touch_selection_controller_unittest.cc',
+ 'browser/renderer_host/input/web_input_event_util_unittest.cc',
'browser/renderer_host/media/audio_input_device_manager_unittest.cc',
'browser/renderer_host/media/audio_renderer_host_unittest.cc',
- 'browser/renderer_host/media/device_request_message_filter_unittest.cc',
'browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc',
'browser/renderer_host/media/media_stream_manager_unittest.cc',
'browser/renderer_host/media/media_stream_ui_proxy_unittest.cc',
@@ -562,6 +582,7 @@
'browser/renderer_host/render_view_host_unittest.cc',
'browser/renderer_host/render_widget_host_unittest.cc',
'browser/renderer_host/render_widget_host_view_aura_unittest.cc',
+ 'browser/renderer_host/render_widget_host_view_base_unittest.cc',
'browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm',
'browser/renderer_host/render_widget_host_view_mac_unittest.mm',
'browser/renderer_host/software_frame_manager_unittest.cc',
@@ -572,18 +593,24 @@
'browser/service_worker/embedded_worker_instance_unittest.cc',
'browser/service_worker/embedded_worker_test_helper.cc',
'browser/service_worker/embedded_worker_test_helper.h',
+ 'browser/service_worker/service_worker_cache_unittest.cc',
+ 'browser/service_worker/service_worker_cache_storage_manager_unittest.cc',
'browser/service_worker/service_worker_context_unittest.cc',
+ 'browser/service_worker/service_worker_controllee_request_handler_unittest.cc',
+ 'browser/service_worker/service_worker_context_request_handler_unittest.cc',
'browser/service_worker/service_worker_database_unittest.cc',
'browser/service_worker/service_worker_dispatcher_host_unittest.cc',
- 'browser/service_worker/service_worker_dispatcher_host_unittest.cc',
'browser/service_worker/service_worker_handle_unittest.cc',
'browser/service_worker/service_worker_job_unittest.cc',
+ 'browser/service_worker/service_worker_process_manager_unittest.cc',
'browser/service_worker/service_worker_provider_host_unittest.cc',
'browser/service_worker/service_worker_registration_unittest.cc',
+ 'browser/service_worker/service_worker_request_handler_unittest.cc',
'browser/service_worker/service_worker_storage_unittest.cc',
'browser/service_worker/service_worker_url_request_job_unittest.cc',
'browser/service_worker/service_worker_utils_unittest.cc',
'browser/service_worker/service_worker_version_unittest.cc',
+ 'browser/service_worker/service_worker_write_to_cache_job_unittest.cc',
'browser/shared_worker/shared_worker_instance_unittest.cc',
'browser/shared_worker/shared_worker_service_impl_unittest.cc',
'browser/site_instance_impl_unittest.cc',
@@ -592,13 +619,13 @@
'browser/speech/google_one_shot_remote_engine_unittest.cc',
'browser/speech/google_streaming_remote_engine_unittest.cc',
'browser/speech/speech_recognizer_impl_unittest.cc',
- 'browser/ssl/ssl_host_state_unittest.cc',
'browser/startup_task_runner_unittest.cc',
'browser/storage_partition_impl_map_unittest.cc',
'browser/storage_partition_impl_unittest.cc',
'browser/streams/stream_unittest.cc',
'browser/streams/stream_url_request_job_unittest.cc',
'browser/system_message_window_win_unittest.cc',
+ 'browser/transition_request_manager_unittest.cc',
'browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc',
'browser/web_contents/aura/window_slider_unittest.cc',
'browser/web_contents/web_contents_delegate_unittest.cc',
@@ -609,7 +636,7 @@
'browser/web_contents/web_drag_source_mac_unittest.mm',
'browser/webui/web_ui_data_source_unittest.cc',
'browser/webui/web_ui_message_handler_unittest.cc',
- 'child/blink_platform_unittest.cc',
+ 'child/blink_platform_impl_unittest.cc',
'child/fileapi/webfilewriter_base_unittest.cc',
'child/indexed_db/indexed_db_dispatcher_unittest.cc',
'child/indexed_db/webidbcursor_impl_unittest.cc',
@@ -617,9 +644,23 @@
'child/npapi/plugin_lib_unittest.cc',
'child/power_monitor_broadcast_source_unittest.cc',
'child/resource_dispatcher_unittest.cc',
+ 'child/simple_webmimeregistry_impl_unittest.cc',
'child/site_isolation_policy_unittest.cc',
- 'child/touch_fling_gesture_curve_unittest.cc',
- 'child/webcrypto/shared_crypto_unittest.cc',
+ 'child/web_data_consumer_handle_impl_unittest.cc',
+ 'child/web_gesture_curve_impl_unittest.cc',
+ 'child/web_url_loader_impl_unittest.cc',
+ 'child/webcrypto/test/aes_cbc_unittest.cc',
+ 'child/webcrypto/test/aes_ctr_unittest.cc',
+ 'child/webcrypto/test/aes_gcm_unittest.cc',
+ 'child/webcrypto/test/aes_kw_unittest.cc',
+ 'child/webcrypto/test/hmac_unittest.cc',
+ 'child/webcrypto/test/rsa_oaep_unittest.cc',
+ 'child/webcrypto/test/rsa_pss_unittest.cc',
+ 'child/webcrypto/test/rsa_ssa_unittest.cc',
+ 'child/webcrypto/test/sha_unittest.cc',
+ 'child/webcrypto/test/status_unittest.cc',
+ 'child/webcrypto/test/test_helpers.cc',
+ 'child/webcrypto/test/test_helpers.h',
'child/worker_task_runner_unittest.cc',
'common/android/address_parser_unittest.cc',
'common/android/gin_java_bridge_value_unittest.cc',
@@ -631,13 +672,17 @@
'common/dom_storage/dom_storage_map_unittest.cc',
'common/fileapi/file_system_util_unittest.cc',
'common/gpu/gpu_memory_manager_unittest.cc',
+ 'common/host_discardable_shared_memory_manager_unittest.cc',
'common/host_shared_bitmap_manager_unittest.cc',
'common/indexed_db/indexed_db_key_unittest.cc',
+ 'common/input/gesture_event_stream_validator_unittest.cc',
'common/input/input_param_traits_unittest.cc',
+ 'common/input/touch_event_stream_validator_unittest.cc',
'common/input/web_input_event_traits_unittest.cc',
'common/inter_process_time_ticks_converter_unittest.cc',
'common/mac/attributed_string_coder_unittest.mm',
'common/mac/font_descriptor_unittest.mm',
+ 'common/one_writer_seqlock_unittest.cc',
'common/page_state_serialization_unittest.cc',
'common/page_zoom_unittest.cc',
'common/plugin_list_unittest.cc',
@@ -651,43 +696,39 @@
'renderer/active_notification_tracker_unittest.cc',
'renderer/android/email_detector_unittest.cc',
'renderer/android/phone_number_detector_unittest.cc',
- 'renderer/battery_status/battery_status_dispatcher_unittest.cc',
'renderer/bmp_image_decoder_unittest.cc',
- 'renderer/compositor_bindings/web_animation_unittest.cc',
- 'renderer/compositor_bindings/web_float_animation_curve_unittest.cc',
- 'renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc',
+ 'renderer/device_sensors/device_light_event_pump_unittest.cc',
'renderer/device_sensors/device_motion_event_pump_unittest.cc',
'renderer/device_sensors/device_orientation_event_pump_unittest.cc',
'renderer/disambiguation_popup_helper_unittest.cc',
'renderer/dom_storage/dom_storage_cached_area_unittest.cc',
+ 'renderer/gpu/frame_swap_message_queue_unittest.cc',
+ 'renderer/gpu/queue_message_swap_promise_unittest.cc',
+ 'renderer/gpu/render_widget_compositor_unittest.cc',
'renderer/ico_image_decoder_unittest.cc',
'renderer/input/input_event_filter_unittest.cc',
'renderer/input/input_handler_proxy_unittest.cc',
+ 'renderer/manifest/manifest_parser_unittest.cc',
'renderer/media/android/media_info_loader_unittest.cc',
'renderer/media/audio_message_filter_unittest.cc',
'renderer/media/audio_renderer_mixer_manager_unittest.cc',
- 'renderer/media/buffered_data_source_unittest.cc',
- 'renderer/media/buffered_data_source_host_impl_unittest.cc',
- 'renderer/media/buffered_resource_loader_unittest.cc',
- 'renderer/media/cache_util_unittest.cc',
'renderer/media/crypto/key_systems_unittest.cc',
'renderer/media/render_media_log_unittest.cc',
- 'renderer/media/test_response_generator.cc',
- 'renderer/media/test_response_generator.h',
'renderer/media/video_capture_impl_manager_unittest.cc',
'renderer/media/video_capture_impl_unittest.cc',
'renderer/media/video_capture_message_filter_unittest.cc',
- 'renderer/media/video_frame_compositor_unittest.cc',
- 'renderer/media/webaudiosourceprovider_impl_unittest.cc',
'renderer/media/webrtc/video_destination_handler_unittest.cc',
'renderer/npapi/webplugin_impl_unittest.cc',
+ 'renderer/pepper/event_conversion_unittest.cc',
'renderer/pepper/host_var_tracker_unittest.cc',
'renderer/pepper/mock_resource.h',
'renderer/pepper/pepper_broker_unittest.cc',
'renderer/pepper/v8_var_converter_unittest.cc',
- 'renderer/render_frame_impl_unittest.cc',
'renderer/render_thread_impl_unittest.cc',
'renderer/render_widget_unittest.cc',
+ 'renderer/scheduler/renderer_scheduler_impl_unittest.cc',
+ 'renderer/scheduler/renderer_task_queue_selector_unittest.cc',
+ 'renderer/scheduler/task_queue_manager_unittest.cc',
'renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc',
'renderer/skia_benchmarking_extension_unittest.cc',
'renderer/v8_value_converter_impl_unittest.cc',
@@ -715,26 +756,30 @@
'content.gyp:content_gpu',
'content.gyp:content_plugin',
'content.gyp:content_renderer',
- 'content_resources.gyp:content_resources',
+ 'content.gyp:content_resources',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
'../cc/cc.gyp:cc',
+ '../cc/cc.gyp:cc_surfaces',
'../cc/cc_tests.gyp:cc_test_support',
+ '../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
'../gpu/gpu.gyp:gpu_unittest_utils',
'../ipc/ipc.gyp:test_support_ipc',
- '../jingle/jingle.gyp:jingle_glue_test_util',
'../media/media.gyp:media_test_support',
'../media/media.gyp:shared_memory_support',
+ '../storage/storage_browser.gyp:storage',
+ '../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
'../third_party/icu/icu.gyp:icui18n',
'../third_party/icu/icu.gyp:icuuc',
'../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
'../third_party/libjingle/libjingle.gyp:libjingle',
- '../ui/compositor/compositor.gyp:compositor_test_support',
'../ui/gl/gl.gyp:gl',
- '../webkit/child/webkit_child.gyp:webkit_child',
- '../webkit/storage_browser.gyp:webkit_storage_browser',
- '../webkit/storage_common.gyp:webkit_storage_common',
+ ],
+ }],
+ ['OS != "win"', {
+ 'sources': [
+ 'browser/file_descriptor_info_impl_unittest.cc',
],
}],
['enable_plugins==0', {
@@ -762,7 +807,6 @@
'renderer/media/media_stream_audio_processor_unittest.cc',
'renderer/media/media_stream_constraints_util_unittest.cc',
'renderer/media/media_stream_dispatcher_unittest.cc',
- 'renderer/media/media_stream_impl_unittest.cc',
'renderer/media/media_stream_video_capture_source_unittest.cc',
'renderer/media/media_stream_video_source_unittest.cc',
'renderer/media/media_stream_video_track_unittest.cc',
@@ -775,6 +819,8 @@
'renderer/media/mock_media_constraint_factory.cc',
'renderer/media/rtc_peer_connection_handler_unittest.cc',
'renderer/media/rtc_video_decoder_unittest.cc',
+ 'renderer/media/speech_recognition_audio_sink_unittest.cc',
+ 'renderer/media/user_media_client_impl_unittest.cc',
'renderer/media/video_source_handler_unittest.cc',
'renderer/media/webrtc/media_stream_remote_video_source_unittest.cc',
'renderer/media/webrtc/media_stream_track_metrics_unittest.cc',
@@ -788,6 +834,7 @@
'renderer/media/webrtc_local_audio_source_provider_unittest.cc',
'renderer/media/webrtc_local_audio_track_unittest.cc',
'renderer/media/webrtc_uma_histograms_unittest.cc',
+ 'renderer/p2p/ipc_network_manager_unittest.cc',
],
'dependencies': [
'../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
@@ -820,7 +867,7 @@
['exclude', '^renderer/media/media_stream_'],
],
}],
- ['input_speech==0', {
+ ['enable_web_speech==0', {
'sources/': [
['exclude', '^browser/speech/'],
]
@@ -877,8 +924,11 @@
}],
['OS == "android"', {
'sources': [
- 'browser/renderer_host/java/gin_java_method_invocation_helper_unittest.cc',
- 'browser/renderer_host/java/jni_helper_unittest.cc',
+ 'browser/android/java/gin_java_method_invocation_helper_unittest.cc',
+ 'browser/android/java/java_type_unittest.cc',
+ 'browser/android/java/jni_helper_unittest.cc',
+ 'browser/android/system_ui_resource_manager_impl_unittest.cc',
+ 'browser/renderer_host/input/motion_event_android_unittest.cc',
'renderer/java/gin_java_bridge_value_converter_unittest.cc',
],
'sources!': [
@@ -925,6 +975,19 @@
['test_isolation_mode != "noop"', {
'targets': [
{
+ 'target_name': 'content_browsertests_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'content_browsertests',
+ ],
+ 'includes': [
+ '../build/isolate.gypi',
+ ],
+ 'sources': [
+ 'content_browsertests.isolate',
+ ],
+ },
+ {
'target_name': 'content_unittests_run',
'type': 'none',
'dependencies': [
@@ -932,12 +995,37 @@
],
'includes': [
'../build/isolate.gypi',
- 'content_unittests.isolate',
],
'sources': [
'content_unittests.isolate',
],
- },
+ 'conditions': [
+ ['use_x11==1', {
+ 'dependencies': [
+ '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
+ ],
+ }],
+ ],
+ },
+ ],
+ 'conditions': [
+ ['archive_gpu_tests==1', {
+ 'targets': [
+ {
+ 'target_name': 'content_gl_tests_run',
+ 'type': 'none',
+ 'dependencies': [
+ 'content_shell_and_tests.gyp:content_gl_tests',
+ ],
+ 'includes': [
+ '../build/isolate.gypi',
+ ],
+ 'sources': [
+ 'content_gl_tests.isolate',
+ ],
+ },
+ ],
+ }],
],
}],
['OS!="ios"', {
@@ -972,6 +1060,11 @@
'../testing/android/native_test.gyp:native_test_native_code',
],
}],
+ ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
+ 'dependencies': [
+ '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ ],
+ }],
],
},
{
@@ -981,6 +1074,7 @@
'content_shell_lib',
'../skia/skia.gyp:skia',
'../testing/gtest.gyp:gtest',
+ '../ui/accessibility/accessibility.gyp:ax_gen',
],
'sources': [
'test/content_test_launcher.cc',
@@ -990,6 +1084,9 @@
'public/test/content_browser_test_utils.h',
'public/test/content_browser_test_utils_mac.mm',
],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
'conditions': [
['OS=="android"', {
'dependencies': [
@@ -1006,14 +1103,14 @@
'target_name': 'web_ui_test_mojo_bindings',
'type': 'static_library',
'dependencies': [
- '../mojo/mojo.gyp:mojo_cpp_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
],
'sources': [
'test/data/web_ui_test_mojo_bindings.mojom',
],
'includes': [ '../mojo/public/tools/bindings/mojom_bindings_generator.gypi' ],
'export_dependent_settings': [
- '../mojo/mojo.gyp:mojo_cpp_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
],
},
{
@@ -1024,24 +1121,25 @@
'content.gyp:content_gpu',
'content.gyp:content_plugin',
'content.gyp:content_renderer',
+ 'content.gyp:content_resources',
'content_browser_test_support',
- 'content_resources.gyp:content_resources',
'content_shell_lib',
'content_shell_pak',
'test_support_content',
'web_ui_test_mojo_bindings',
'../base/base.gyp:test_support_base',
+ '../device/battery/battery.gyp:device_battery',
+ '../device/battery/battery.gyp:device_battery_mojo_bindings',
'../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
'../ipc/ipc.gyp:test_support_ipc',
'../media/media.gyp:media_test_support',
'../media/media.gyp:shared_memory_support',
- '../mojo/mojo.gyp:mojo_common_test_support',
- '../mojo/mojo.gyp:mojo_cpp_bindings',
- '../mojo/mojo.gyp:mojo_environment_chromium',
- '../mojo/mojo.gyp:mojo_js_bindings',
- '../mojo/mojo.gyp:mojo_service_manager',
- '../mojo/mojo.gyp:mojo_system_impl',
+ '../mojo/edk/mojo_edk.gyp:mojo_common_test_support',
+ '../mojo/edk/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/public/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_js_bindings',
'../net/net.gyp:net_test_support',
'../ppapi/ppapi_internal.gyp:ppapi_host',
'../ppapi/ppapi_internal.gyp:ppapi_ipc',
@@ -1062,7 +1160,6 @@
'../ui/resources/ui_resources.gyp:ui_resources',
'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'../ui/snapshot/snapshot.gyp:snapshot',
- '../webkit/child/webkit_child.gyp:webkit_child',
'../ui/accessibility/accessibility.gyp:ax_gen',
],
'include_dirs': [
@@ -1077,14 +1174,18 @@
],
'sources': [
'app/mojo/mojo_browsertest.cc',
+ 'browser/accessibility/accessibility_ipc_error_browsertest.cc',
'browser/accessibility/accessibility_mode_browsertest.cc',
'browser/accessibility/accessibility_win_browsertest.cc',
+ 'browser/accessibility/android_granularity_movement_browsertest.cc',
'browser/accessibility/android_hit_testing_browsertest.cc',
'browser/accessibility/cross_platform_accessibility_browsertest.cc',
'browser/accessibility/dump_accessibility_tree_browsertest.cc',
+ 'browser/accessibility/site_per_process_accessibility_browsertest.cc',
'browser/battery_status/battery_status_browsertest.cc',
'browser/compositor/image_transport_factory_browsertest.cc',
'browser/bookmarklet_browsertest.cc',
+ 'browser/child_process_launcher_browsertest.cc',
'browser/child_process_security_policy_browsertest.cc',
'browser/cross_site_transfer_browsertest.cc',
'browser/database_browsertest.cc',
@@ -1105,11 +1206,13 @@
'browser/indexed_db/mock_browsertest_indexed_db_class_factory.cc',
'browser/indexed_db/mock_browsertest_indexed_db_class_factory.h',
'browser/loader/resource_dispatcher_host_browsertest.cc',
+ 'browser/manifest/manifest_browsertest.cc',
'browser/media/encrypted_media_browsertest.cc',
'browser/media/media_browsertest.cc',
'browser/media/media_browsertest.h',
'browser/media/media_canplaytype_browsertest.cc',
'browser/media/media_source_browsertest.cc',
+ 'browser/net_info_browsertest.cc',
'browser/plugin_data_remover_impl_browsertest.cc',
'browser/plugin_browsertest.cc',
'browser/plugin_service_impl_browsertest.cc',
@@ -1119,27 +1222,24 @@
'browser/renderer_host/render_view_host_browsertest.cc',
'browser/renderer_host/render_widget_host_browsertest.cc',
'browser/renderer_host/render_widget_host_view_browsertest.cc',
+ 'browser/screen_orientation/screen_orientation_browsertest.cc',
'browser/security_exploit_browsertest.cc',
'browser/service_worker/service_worker_browsertest.cc',
'browser/session_history_browsertest.cc',
+ 'browser/shared_worker/worker_browsertest.cc',
+ 'browser/site_per_process_browsertest.h',
'browser/site_per_process_browsertest.cc',
'browser/speech/speech_recognition_browsertest.cc',
'browser/tracing/tracing_controller_browsertest.cc',
+ 'browser/transition_browsertest.cc',
'browser/web_contents/opened_by_dom_browsertest.cc',
'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
'browser/web_contents/web_contents_impl_browsertest.cc',
'browser/web_contents/web_contents_view_aura_browsertest.cc',
'browser/webkit_browsertest.cc',
'browser/webui/web_ui_mojo_browsertest.cc',
- 'browser/worker_host/test/worker_browsertest.cc',
'child/site_isolation_policy_browsertest.cc',
'renderer/accessibility/renderer_accessibility_browsertest.cc',
- 'renderer/browser_plugin/browser_plugin_browsertest.cc',
- 'renderer/browser_plugin/browser_plugin_browsertest.h',
- 'renderer/browser_plugin/mock_browser_plugin.cc',
- 'renderer/browser_plugin/mock_browser_plugin.h',
- 'renderer/browser_plugin/mock_browser_plugin_manager.cc',
- 'renderer/browser_plugin/mock_browser_plugin_manager.h',
'renderer/browser_render_view_browsertest.cc',
'renderer/dom_serializer_browsertest.cc',
'renderer/gin_browsertest.cc',
@@ -1150,6 +1250,7 @@
'renderer/pepper/pepper_file_chooser_host_unittest.cc',
'renderer/pepper/pepper_graphics_2d_host_unittest.cc',
'renderer/pepper/pepper_url_request_unittest.cc',
+ 'renderer/pepper/plugin_power_saver_helper_browsertest.cc',
'renderer/render_thread_impl_browsertest.cc',
'renderer/render_view_browsertest.cc',
'renderer/render_view_browsertest_mac.mm',
@@ -1158,6 +1259,7 @@
'renderer/savable_resources_browsertest.cc',
'test/accessibility_browser_test_utils.cc',
'test/accessibility_browser_test_utils.h',
+ 'test/browser_test_utils_browsertest.cc',
'test/content_browser_test_test.cc',
'test/ppapi/ppapi_browsertest.cc',
'test/ppapi/ppapi_test.cc',
@@ -1182,16 +1284,16 @@
# their various targets (net.gyp:net_resources, etc.),
# but that causes errors in other targets when
# resulting .res files get referenced multiple times.
+ '<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.rc',
+ '<(SHARED_INTERMEDIATE_DIR)/content/app/strings/content_strings_en-US.rc',
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.rc',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.rc',
- '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.rc',
],
'dependencies': [
+ '<(DEPTH)/content/app/strings/content_strings.gyp:content_strings',
'<(DEPTH)/net/net.gyp:net_resources',
+ '<(DEPTH)/third_party/WebKit/public/blink_resources.gyp:blink_resources',
'<(DEPTH)/third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
'<(DEPTH)/third_party/isimpledom/isimpledom.gyp:isimpledom',
- '<(DEPTH)/webkit/webkit_resources.gyp:webkit_strings',
- '<(DEPTH)/webkit/webkit_resources.gyp:webkit_resources',
],
'configurations': {
'Debug_Base': {
@@ -1217,6 +1319,7 @@
}],
['OS!="android"', {
'sources!': [
+ 'browser/accessibility/android_granularity_movement_browsertest.cc',
'browser/accessibility/android_hit_testing_browsertest.cc',
]
}],
@@ -1262,9 +1365,11 @@
}],
['enable_webrtc==1', {
'sources': [
+ 'browser/media/webrtc_aecdump_browsertest.cc',
'browser/media/webrtc_browsertest.cc',
'browser/media/webrtc_getusermedia_browsertest.cc',
'browser/media/webrtc_internals_browsertest.cc',
+ 'browser/media/webrtc_webcam_browsertest.cc',
'test/webrtc_content_browsertest_base.cc',
'test/webrtc_content_browsertest_base.h',
],
@@ -1287,7 +1392,7 @@
'../ppapi/ppapi_internal.gyp:ppapi_tests',
]
}],
- ['input_speech==0', {
+ ['enable_web_speech==0', {
'sources/': [
['exclude', '^browser/speech/'],
]
@@ -1296,7 +1401,7 @@
'sources!': [
# These tests depend on single process mode, which is disabled
# in official builds.
- 'renderer/browser_render_view_browsertest.cc',
+ 'renderer/browser_render_view_browsertest.cc',
'renderer/dom_serializer_browsertest.cc',
'renderer/resource_fetcher_browsertest.cc',
'renderer/savable_resources_browsertest.cc',
@@ -1315,13 +1420,11 @@
'../testing/gtest.gyp:gtest',
'../third_party/WebKit/public/blink.gyp:blink',
'../ui/base/ui_base.gyp:ui_base',
- '../v8/tools/gyp/v8.gyp:v8',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/gl/gl.gyp:gl',
- # The following dependency provides the missing symbol
- # HeapProfilerStart in Linux component builds.
- '../webkit/child/webkit_child.gyp:webkit_child',
+ '../v8/tools/gyp/v8.gyp:v8',
],
'include_dirs': [
'..',
@@ -1335,6 +1438,17 @@
'dependencies': [
'../testing/android/native_test.gyp:native_test_native_code',
],
+ }, {
+ 'dependencies': [
+ # Runtime dependencis.
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ '../third_party/mesa/mesa.gyp:osmesa',
+ ],
+ }],
+ ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
+ 'dependencies': [
+ '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ ],
}],
],
},
@@ -1351,9 +1465,6 @@
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gl/gl.gyp:gl',
- # The following two dependencies provide the missing
- # symbol HeapProfilerStart in Linux component builds.
- '../webkit/child/webkit_child.gyp:webkit_child',
],
'include_dirs': [
'..',
@@ -1361,10 +1472,17 @@
'sources': [
'common/gpu/client/gl_helper_benchmark.cc',
],
+ 'conditions': [
+ ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
+ 'dependencies': [
+ '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ ],
+ }],
+ ],
},
],
}],
- ['chromeos==1 or OS=="win" or OS=="android"', {
+ ['(chromeos==1 or OS=="win" or OS=="android") and use_ozone==0', {
'targets': [
{
'target_name': 'video_decode_accelerator_unittest',
@@ -1375,6 +1493,7 @@
'../testing/gtest.gyp:gtest',
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gl/gl.gyp:gl',
'content.gyp:content',
@@ -1409,8 +1528,8 @@
}],
['OS=="win"', {
'dependencies': [
- '<(angle_path)/src/build_angle.gyp:libEGL',
- '<(angle_path)/src/build_angle.gyp:libGLESv2',
+ '<(angle_path)/src/angle.gyp:libEGL',
+ '<(angle_path)/src/angle.gyp:libGLESv2',
],
}],
['(OS=="win" and win_use_allocator_shim==1) or '
@@ -1460,7 +1579,7 @@
},
]
}],
- ['chromeos==1 and target_arch == "arm"', {
+ ['chromeos==1 and (target_arch == "arm" or use_x11 == 1)', {
'targets': [
{
'target_name': 'video_encode_accelerator_unittest',
@@ -1473,6 +1592,7 @@
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/gl/gl.gyp:gl',
'content.gyp:content',
],
@@ -1480,12 +1600,24 @@
'common/gpu/media/video_accelerator_unittest_helpers.h',
'common/gpu/media/video_encode_accelerator_unittest.cc',
],
+ 'include_dirs': [
+ '<(DEPTH)/third_party/libva',
+ '<(DEPTH)/third_party/libyuv',
+ ],
+ 'conditions': [
+ ['use_x11==1', {
+ 'dependencies': [
+ '../ui/gfx/x/gfx_x11.gyp:gfx_x11',
+ ],
+ }],
+ ],
},
]
}],
['OS == "android"', {
'targets': [
{
+ # TODO(GN)
'target_name': 'content_gl_tests_apk',
'type': 'none',
'dependencies': [
@@ -1500,6 +1632,7 @@
],
},
{
+ # TODO(GN)
'target_name': 'content_unittests_apk',
'type': 'none',
'dependencies': [
@@ -1508,15 +1641,34 @@
],
'variables': {
'test_suite_name': 'content_unittests',
+ 'conditions': [
+ ['v8_use_external_startup_data==1', {
+ 'additional_input_paths': [
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ 'copies': [
+ {
+ 'destination': '<(PRODUCT_DIR)/content_unittests_apk/assets',
+ 'files': [
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ },
+ ],
+ }],
+ ],
},
'includes': [ '../build/apk_test.gypi' ],
},
{
+ # TODO(GN)
'target_name': 'content_browsertests_apk',
'type': 'none',
'dependencies': [
'content.gyp:content_icudata',
'content.gyp:content_java',
+ 'content.gyp:content_v8_external_data',
'content_browsertests',
'content_java_test_support',
'content_shell_java',
@@ -1534,11 +1686,18 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
+ ['v8_use_external_startup_data==1', {
+ 'additional_input_paths': [
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ }],
],
},
'includes': [ '../build/java_apk.gypi' ],
},
{
+ # TODO(GN)
'target_name': 'content_perftests_apk',
'type': 'none',
'dependencies': [
@@ -1551,6 +1710,7 @@
'includes': [ '../build/apk_test.gypi' ],
},
{
+ # GN: //content/shell/android:chromium_linker_test_apk
'target_name': 'chromium_linker_test_apk',
'type': 'none',
'conditions': [
@@ -1559,6 +1719,7 @@
'chromium_android_linker_test',
'content.gyp:content_icudata',
'content.gyp:content_java',
+ 'content.gyp:content_v8_external_data',
'content_shell_java',
],
'variables': {
@@ -1576,6 +1737,12 @@
'<(PRODUCT_DIR)/icudtl.dat',
],
}],
+ ['v8_use_external_startup_data==1', {
+ 'additional_input_paths': [
+ '<(PRODUCT_DIR)/natives_blob.bin',
+ '<(PRODUCT_DIR)/snapshot_blob.bin',
+ ],
+ }],
],
},
'includes': [ '../build/java_apk.gypi' ],
@@ -1584,6 +1751,7 @@
],
},
{
+ # GN: //content/shell/android:linker_test
'target_name': 'chromium_android_linker_test',
'type': 'shared_library',
'defines!': ['CONTENT_IMPLEMENTATION'],
@@ -1600,6 +1768,7 @@
],
},
{
+ # GN: //content/shell/android:linker_test_jni_headers
'target_name': 'chromium_android_linker_test_jni_headers',
'type': 'none',
'sources': [
@@ -1611,6 +1780,7 @@
'includes': [ '../build/jni_generator.gypi' ],
},
{
+ # TODO(GN)
'target_name': 'video_decode_accelerator_unittest_apk',
'type': 'none',
'dependencies': [
@@ -1621,11 +1791,8 @@
},
'includes': [ '../build/apk_test.gypi' ],
},
- ],
- }],
- ['OS == "android"', {
- 'targets': [
{
+ # GN: //content/public/test/android:test_support_content_jni_headers
'target_name': 'test_support_content_jni_headers',
'type': 'none',
'sources': [
@@ -1637,6 +1804,7 @@
'includes': [ '../build/jni_generator.gypi' ],
},
{
+ # GN: //content/public/test/android:content_java_test_support
'target_name': 'content_java_test_support',
'type': 'none',
'dependencies': [
@@ -1651,6 +1819,8 @@
'includes': [ '../build/java.gypi' ],
},
{
+ # GN: //content/shell/android:content_shell_test_apk
+ # and //content/public/android:content_javatests
'target_name': 'content_shell_test_apk',
'type': 'none',
'dependencies': [
@@ -1660,10 +1830,13 @@
'../base/base.gyp:base_java',
'../base/base.gyp:base_javatests',
'../base/base.gyp:base_java_test_support',
+ '../device/battery/battery.gyp:device_battery_javatests',
'../media/media.gyp:media_java',
'../media/media.gyp:media_test_support',
+ '../mojo/public/mojo_public.gyp:mojo_public_test_interfaces',
'../net/net.gyp:net_java',
'../net/net.gyp:net_javatests',
+ '../net/net.gyp:net_java_test_support',
],
'variables': {
'apk_name': 'ContentShellTest',
diff --git a/chromium/content/content_unittests.isolate b/chromium/content/content_unittests.isolate
index e3867e642cc..bc982e2c3dd 100644
--- a/chromium/content/content_unittests.isolate
+++ b/chromium/content/content_unittests.isolate
@@ -5,23 +5,29 @@
'conditions': [
['OS=="android" or OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
- 'isolate_dependency_untracked': [
+ 'files': [
'../media/test/data/',
- '../webkit/data/',
'test/data/',
],
},
}],
- ['OS=="android" or OS=="mac" or OS=="win"', {
+ ['OS=="android"', {
'variables': {
- 'isolate_dependency_tracked': [
- '<(PRODUCT_DIR)/content_resources.pak',
+ 'files': [
+ '<(PRODUCT_DIR)/content_shell/assets/content_shell.pak',
],
},
}],
['OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
- 'isolate_dependency_tracked': [
+ 'files': [
+ '<(PRODUCT_DIR)/content_shell.pak',
+ ],
+ },
+ }],
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
+ 'variables': {
+ 'files': [
'../testing/test_env.py',
'<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
],
@@ -35,10 +41,19 @@
'<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
'--brave-new-test-launcher',
'--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
],
- 'isolate_dependency_tracked': [
+ 'files': [
'../testing/xvfb.py',
'<(PRODUCT_DIR)/libffmpegsumo.so',
+ '<(PRODUCT_DIR)/libosmesa.so',
+ ],
+ },
+ }],
+ ['OS=="linux" and use_ozone==0', {
+ 'variables': {
+ 'files': [
'<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
],
},
@@ -50,9 +65,12 @@
'<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
'--brave-new-test-launcher',
'--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
],
- 'isolate_dependency_tracked': [
+ 'files': [
'<(PRODUCT_DIR)/ffmpegsumo.so',
+ '<(PRODUCT_DIR)/osmesa.so',
],
},
}],
@@ -63,15 +81,25 @@
'<(PRODUCT_DIR)/content_unittests<(EXECUTABLE_SUFFIX)',
'--brave-new-test-launcher',
'--test-launcher-bot-mode',
+ '--asan=<(asan)',
+ '--lsan=<(lsan)',
],
- 'isolate_dependency_tracked': [
+ 'files': [
'<(PRODUCT_DIR)/ffmpegsumo.dll',
- '<(PRODUCT_DIR)/ui_test.pak',
+ '<(PRODUCT_DIR)/osmesa.dll',
+ ],
+ },
+ }],
+ ['OS=="win" and (fastbuild==0 or fastbuild==1)', {
+ 'variables': {
+ 'files': [
+ '<(PRODUCT_DIR)/content_unittests.exe.pdb',
],
},
}],
],
'includes': [
- '../third_party/icu/icu.isolate',
+ '../base/base.isolate',
+ '../gin/v8.isolate',
],
}
diff --git a/chromium/content/content_utility.gypi b/chromium/content/content_utility.gypi
index 2b46f7d6659..dee05e44676 100644
--- a/chromium/content/content_utility.gypi
+++ b/chromium/content/content_utility.gypi
@@ -6,7 +6,7 @@
'dependencies': [
'../base/base.gyp:base',
'../courgette/courgette.gyp:courgette_lib',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
+ '../mojo/public/mojo_public.gyp:mojo_application_bindings',
],
'sources': [
'public/utility/content_utility_client.cc',
diff --git a/chromium/content/content_worker.gypi b/chromium/content/content_worker.gypi
deleted file mode 100644
index a04b662ec34..00000000000
--- a/chromium/content/content_worker.gypi
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright (c) 2011 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.
-
-{
- 'dependencies': [
- '../base/base.gyp:base',
- '../mojo/mojo.gyp:mojo_service_provider_bindings',
- '../skia/skia.gyp:skia',
- '../third_party/WebKit/public/blink.gyp:blink',
- ],
- 'sources': [
- 'worker/websharedworker_stub.cc',
- 'worker/websharedworker_stub.h',
- 'worker/websharedworkerclient_proxy.cc',
- 'worker/websharedworkerclient_proxy.h',
- 'worker/worker_main.cc',
- 'worker/shared_worker_permission_client_proxy.cc',
- 'worker/shared_worker_permission_client_proxy.h',
- 'worker/worker_thread.cc',
- 'worker/worker_thread.h',
- 'worker/worker_webapplicationcachehost_impl.cc',
- 'worker/worker_webapplicationcachehost_impl.h',
- 'worker/worker_webkitplatformsupport_impl.cc',
- 'worker/worker_webkitplatformsupport_impl.h',
- ],
- 'include_dirs': [
- '..',
- ],
-}
diff --git a/chromium/content/gpu/BUILD.gn b/chromium/content/gpu/BUILD.gn
index 6a47b73d7bf..d1f844897d8 100644
--- a/chromium/content/gpu/BUILD.gn
+++ b/chromium/content/gpu/BUILD.gn
@@ -2,14 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/ui.gni")
import("//content/content.gni")
-# We don't support x64 prior to Win7 and D3DCompiler_43.dll is not needed on
-# Vista+.
-need_d3dcompiler = (is_win && cpu_arch == "x86" && directxsdk_exists)
-
source_set("gpu") {
- visibility = "//content/*"
+ visibility = [ "//content/*" ]
+
sources = [
"gpu_main.cc",
"gpu_process.cc",
@@ -27,7 +25,7 @@ source_set("gpu") {
deps = [
"//base",
"//content:export",
- "//mojo/public/interfaces/service_provider",
+ "//mojo/public/interfaces/application",
"//skia",
"//ui/gl",
]
@@ -44,30 +42,11 @@ source_set("gpu") {
]
}
- if (need_d3dcompiler) {
- deps += [ ":extract_d3dcompiler" ]
- }
-
if (is_chromeos && cpu_arch != "arm") {
- configs += [ "//third_party/libva/libva_config" ]
+ configs += [ "//third_party/libva:libva_config" ]
}
-}
-if (need_d3dcompiler) {
- action("extract_d3dcompiler") {
- visibility = ":*"
- script = "//build/extract_from_cab.py"
-
- cabfile = "//third_party/directxsdk/files/Redist/Jun2010_D3DCompiler_43_x86.cab"
- dllfile = "D3DCompiler_43.dll"
-
- source_prereqs = [ cabfile ]
- outputs = [ "$root_out_dir/$dllfile" ]
-
- args = [
- rebase_path(cabfile, root_build_dir),
- dllfile,
- rebase_path(root_out_dir, root_build_dir),
- ]
+ if (use_x11) {
+ deps += [ "//ui/events/platform/x11" ]
}
}
diff --git a/chromium/content/gpu/OWNERS b/chromium/content/gpu/OWNERS
index e8d07a9e149..4cd2b20015b 100644
--- a/chromium/content/gpu/OWNERS
+++ b/chromium/content/gpu/OWNERS
@@ -1,2 +1,3 @@
-kbr@chromium.org
-piman@chromium.org
+jbauman@chromium.org
+kbr@chromium.org
+piman@chromium.org
diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc
index ab0636da76f..f47294b9d66 100644
--- a/chromium/content/gpu/gpu_child_thread.cc
+++ b/chromium/content/gpu/gpu_child_thread.cc
@@ -18,10 +18,11 @@
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gpu_switching_manager.h"
#if defined(USE_OZONE)
-#include "ui/ozone/ozone_platform.h"
#include "ui/ozone/public/gpu_platform_support.h"
+#include "ui/ozone/public/ozone_platform.h"
#endif
namespace content {
@@ -61,7 +62,7 @@ GpuChildThread::GpuChildThread(GpuWatchdogThread* watchdog_thread,
}
GpuChildThread::GpuChildThread(const std::string& channel_id)
- : ChildThread(channel_id),
+ : ChildThread(Options(channel_id, false)),
dead_on_arrival_(false),
in_browser_process_(true) {
#if defined(OS_WIN)
@@ -112,6 +113,7 @@ bool GpuChildThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(GpuMsg_Crash, OnCrash)
IPC_MESSAGE_HANDLER(GpuMsg_Hang, OnHang)
IPC_MESSAGE_HANDLER(GpuMsg_DisableWatchdog, OnDisableWatchdog)
+ IPC_MESSAGE_HANDLER(GpuMsg_GpuSwitched, OnGpuSwitched)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -163,7 +165,8 @@ void GpuChildThread::OnInitialize() {
new GpuChannelManager(GetRouter(),
watchdog_thread_.get(),
ChildProcess::current()->io_message_loop_proxy(),
- ChildProcess::current()->GetShutDownEvent()));
+ ChildProcess::current()->GetShutDownEvent(),
+ channel()));
#if defined(USE_OZONE)
ui::OzonePlatform::GetInstance()
@@ -197,6 +200,9 @@ void GpuChildThread::OnCollectGraphicsInfo() {
case gpu::kCollectInfoNonFatalFailure:
VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
break;
+ case gpu::kCollectInfoNone:
+ NOTREACHED();
+ break;
case gpu::kCollectInfoSuccess:
break;
}
@@ -207,7 +213,7 @@ void GpuChildThread::OnCollectGraphicsInfo() {
// and GpuDataManager prevents us from sending multiple collecting requests,
// so it's OK to be blocking.
gpu::GetDxDiagnostics(&gpu_info_.dx_diagnostics);
- gpu_info_.finalized = true;
+ gpu_info_.dx_diagnostics_info_state = gpu::kCollectInfoSuccess;
#endif // OS_WIN
Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
@@ -261,5 +267,11 @@ void GpuChildThread::OnDisableWatchdog() {
}
}
+void GpuChildThread::OnGpuSwitched() {
+ VLOG(1) << "GPU: GPU has switched";
+ // Notify observers in the GPU process.
+ ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
+}
+
} // namespace content
diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h
index ff0c9258cd1..b5c312db935 100644
--- a/chromium/content/gpu/gpu_child_thread.h
+++ b/chromium/content/gpu/gpu_child_thread.h
@@ -45,16 +45,16 @@ class GpuChildThread : public ChildThread {
// For single-process mode.
explicit GpuChildThread(const std::string& channel_id);
- virtual ~GpuChildThread();
+ ~GpuChildThread() override;
- virtual void Shutdown() OVERRIDE;
+ void Shutdown() override;
void Init(const base::Time& process_start_time);
void StopWatchdog();
// ChildThread overrides.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+ bool OnControlMessageReceived(const IPC::Message& msg) override;
private:
// Message handlers.
@@ -67,6 +67,7 @@ class GpuChildThread : public ChildThread {
void OnCrash();
void OnHang();
void OnDisableWatchdog();
+ void OnGpuSwitched();
#if defined(USE_TCMALLOC)
void OnGetGpuTcmalloc();
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index 1f68ee508ae..37606e2b3d8 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -10,6 +10,7 @@
#endif
#include "base/debug/trace_event.h"
+#include "base/environment.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
@@ -22,6 +23,7 @@
#include "content/common/content_constants_internal.h"
#include "content/common/gpu/gpu_config.h"
#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
@@ -54,6 +56,7 @@
#if defined(OS_MACOSX)
#include "base/message_loop/message_pump_mac.h"
+#include "content/common/sandbox_mac.h"
#endif
#if defined(ADDRESS_SANITIZER)
@@ -205,9 +208,21 @@ int GpuMain(const MainFunctionParams& parameters) {
// consuming has completed, otherwise the process is liable to be aborted.
if (enable_watchdog && !delayed_watchdog_enable) {
watchdog_thread = new GpuWatchdogThread(kGpuTimeout);
- watchdog_thread->Start();
+ base::Thread::Options options;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ watchdog_thread->StartWithOptions(options);
}
+ // Temporarily disable DRI3 on desktop Linux.
+ // The GPU process is crashing on DRI3-enabled desktop Linux systems.
+ // TODO(jorgelo): remove this when crbug.com/415681 is fixed.
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ {
+ scoped_ptr<base::Environment> env(base::Environment::Create());
+ env->SetVar("LIBGL_DRI3_DISABLE", "1");
+ }
+#endif
+
gpu::GPUInfo gpu_info;
// Get vendor_id, device_id, driver_version from browser process through
// commandline switches.
@@ -222,16 +237,13 @@ int GpuMain(const MainFunctionParams& parameters) {
bool initialized_sandbox = false;
bool initialized_gl_context = false;
bool should_initialize_gl_context = false;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
// On Chrome OS ARM Mali, GPU driver userspace creates threads when
// initializing a GL context, so start the sandbox early.
- if (!command_line.HasSwitch(
- switches::kGpuSandboxStartAfterInitialization)) {
- gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(),
- should_initialize_gl_context);
+ if (command_line.HasSwitch(switches::kGpuSandboxStartEarly)) {
+ gpu_info.sandboxed = StartSandboxLinux(
+ gpu_info, watchdog_thread.get(), should_initialize_gl_context);
initialized_sandbox = true;
}
-#endif
#endif // defined(OS_LINUX)
base::TimeTicks before_initialize_one_off = base::TimeTicks::Now();
@@ -302,7 +314,9 @@ int GpuMain(const MainFunctionParams& parameters) {
if (enable_watchdog && delayed_watchdog_enable) {
watchdog_thread = new GpuWatchdogThread(kGpuTimeout);
- watchdog_thread->Start();
+ base::Thread::Options options;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ watchdog_thread->StartWithOptions(options);
}
// OSMesa is expected to run very slowly, so disable the watchdog in that
@@ -323,7 +337,12 @@ int GpuMain(const MainFunctionParams& parameters) {
}
#elif defined(OS_WIN)
gpu_info.sandboxed = StartSandboxWindows(parameters.sandbox_info);
+#elif defined(OS_MACOSX)
+ gpu_info.sandboxed = Sandbox::SandboxIsCurrentlyActive();
#endif
+
+ gpu_info.video_encode_accelerator_supported_profiles =
+ content::GpuVideoEncodeAccelerator::GetSupportedProfiles();
} else {
dead_on_arrival = true;
}
@@ -348,7 +367,7 @@ int GpuMain(const MainFunctionParams& parameters) {
gpu_process.set_main_thread(child_thread);
- if (watchdog_thread)
+ if (watchdog_thread.get())
watchdog_thread->AddPowerObserver();
{
@@ -405,6 +424,9 @@ bool CollectGraphicsInfo(gpu::GPUInfo& gpu_info) {
case gpu::kCollectInfoNonFatalFailure:
VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
break;
+ case gpu::kCollectInfoNone:
+ NOTREACHED();
+ break;
case gpu::kCollectInfoSuccess:
break;
}
@@ -492,7 +514,9 @@ bool StartSandboxLinux(const gpu::GPUInfo& gpu_info,
// with only one thread.
res = LinuxSandbox::InitializeSandbox();
if (watchdog_thread) {
- watchdog_thread->Start();
+ base::Thread::Options options;
+ options.timer_slack = base::TIMER_SLACK_MAXIMUM;
+ watchdog_thread->StartWithOptions(options);
}
return res;
diff --git a/chromium/content/gpu/gpu_process.h b/chromium/content/gpu/gpu_process.h
index f4db71e18e0..0511fa8d44a 100644
--- a/chromium/content/gpu/gpu_process.h
+++ b/chromium/content/gpu/gpu_process.h
@@ -12,7 +12,7 @@ namespace content {
class GpuProcess : public ChildProcess {
public:
GpuProcess();
- virtual ~GpuProcess();
+ ~GpuProcess() override;
private:
DISALLOW_COPY_AND_ASSIGN(GpuProcess);
diff --git a/chromium/content/gpu/gpu_watchdog_thread.cc b/chromium/content/gpu/gpu_watchdog_thread.cc
index 940d07e72ac..02b6bff8040 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.cc
+++ b/chromium/content/gpu/gpu_watchdog_thread.cc
@@ -12,7 +12,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/power_monitor/power_monitor.h"
#include "base/process/process.h"
#include "build/build_config.h"
@@ -38,8 +38,8 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
arm_cpu_time_(),
#endif
task_observer_(this),
- weak_factory_(this),
- suspended_(false) {
+ suspended_(false),
+ weak_factory_(this) {
DCHECK(timeout >= 0);
#if defined(OS_WIN)
diff --git a/chromium/content/gpu/gpu_watchdog_thread.h b/chromium/content/gpu/gpu_watchdog_thread.h
index db7978baa57..c766ca34937 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.h
+++ b/chromium/content/gpu/gpu_watchdog_thread.h
@@ -29,15 +29,15 @@ class GpuWatchdogThread : public base::Thread,
void PostAcknowledge();
// Implement GpuWatchdog.
- virtual void CheckArmed() OVERRIDE;
+ void CheckArmed() override;
// Must be called after a PowerMonitor has been created. Can be called from
// any thread.
void AddPowerObserver();
protected:
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void CleanUp() override;
private:
friend class base::RefCountedThreadSafe<GpuWatchdogThread>;
@@ -47,18 +47,17 @@ class GpuWatchdogThread : public base::Thread,
class GpuWatchdogTaskObserver : public base::MessageLoop::TaskObserver {
public:
explicit GpuWatchdogTaskObserver(GpuWatchdogThread* watchdog);
- virtual ~GpuWatchdogTaskObserver();
+ ~GpuWatchdogTaskObserver() override;
// Implements MessageLoop::TaskObserver.
- virtual void WillProcessTask(
- const base::PendingTask& pending_task) OVERRIDE;
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE;
+ void WillProcessTask(const base::PendingTask& pending_task) override;
+ void DidProcessTask(const base::PendingTask& pending_task) override;
private:
GpuWatchdogThread* watchdog_;
};
- virtual ~GpuWatchdogThread();
+ ~GpuWatchdogThread() override;
void OnAcknowledge();
void OnCheck(bool after_suspend);
@@ -67,8 +66,8 @@ class GpuWatchdogThread : public base::Thread,
void OnAddPowerObserver();
// Implement PowerObserver.
- virtual void OnSuspend() OVERRIDE;
- virtual void OnResume() OVERRIDE;
+ void OnSuspend() override;
+ void OnResume() override;
#if defined(OS_WIN)
base::TimeDelta GetWatchedThreadTime();
@@ -88,14 +87,14 @@ class GpuWatchdogThread : public base::Thread,
// the task was posted.
base::Time suspension_timeout_;
- base::WeakPtrFactory<GpuWatchdogThread> weak_factory_;
-
bool suspended_;
#if defined(OS_CHROMEOS)
FILE* tty_file_;
#endif
+ base::WeakPtrFactory<GpuWatchdogThread> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(GpuWatchdogThread);
};
diff --git a/chromium/content/gpu/in_process_gpu_thread.h b/chromium/content/gpu/in_process_gpu_thread.h
index ef6b4e17a65..e8e0140dc28 100644
--- a/chromium/content/gpu/in_process_gpu_thread.h
+++ b/chromium/content/gpu/in_process_gpu_thread.h
@@ -17,11 +17,11 @@ class GpuProcess;
class InProcessGpuThread : public base::Thread {
public:
explicit InProcessGpuThread(const std::string& channel_id);
- virtual ~InProcessGpuThread();
+ ~InProcessGpuThread() override;
protected:
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void CleanUp() override;
private:
std::string channel_id_;
diff --git a/chromium/content/plugin/BUILD.gn b/chromium/content/plugin/BUILD.gn
index 6235dbf6650..03171deaa90 100644
--- a/chromium/content/plugin/BUILD.gn
+++ b/chromium/content/plugin/BUILD.gn
@@ -7,7 +7,10 @@ import("//build/config/features.gni")
# This is the NPAPI plugin process. It isn't used on Linux.
if (enable_plugins && !is_linux) {
source_set("plugin") {
- visibility = "//content/*"
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/plugin:plugin_sources" ]
+
sources = [
"plugin_channel.cc",
"plugin_channel.h",
@@ -29,12 +32,10 @@ if (enable_plugins && !is_linux) {
deps = [
"//content:export",
- "//mojo/public/interfaces/service_provider",
+ "//mojo/public/interfaces/application",
"//skia",
"//third_party/npapi",
- #"//third_party/WebKit/public:blink", TODO(GYP)
- # TODO(GYP) remove this when blink is enabled:
- "//third_party/WebKit/public:blink_headers",
+ "//third_party/WebKit/public:blink",
]
}
} else {
diff --git a/chromium/content/plugin/plugin_carbon_interpose_mac.cc b/chromium/content/plugin/plugin_carbon_interpose_mac.cc
deleted file mode 100644
index fd9f138253b..00000000000
--- a/chromium/content/plugin/plugin_carbon_interpose_mac.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2012 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.
-
-#if !defined(__LP64__)
-
-#include <Carbon/Carbon.h>
-
-#include "content/plugin/plugin_interpose_util_mac.h"
-#include "ui/gfx/rect.h"
-
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
-// Returns true if the given window is modal.
-static bool IsModalWindow(WindowRef window) {
- WindowModality modality = kWindowModalityNone;
- WindowRef modal_target = NULL;
- OSStatus status = GetWindowModality(window, &modality, &modal_target);
- return (status == noErr) && (modality != kWindowModalityNone);
-}
-
-static CGRect CGRectForWindow(WindowRef window) {
- CGRect bounds = { { 0, 0 }, { 0, 0 } };
- HIWindowGetBounds(window, kWindowContentRgn, kHICoordSpace72DPIGlobal,
- &bounds);
- return bounds;
-}
-
-struct WindowInfo {
- uint32 window_id;
- CGRect bounds;
- WindowInfo(WindowRef window) {
- window_id = HIWindowGetCGWindowID(window);
- bounds = CGRectForWindow(window);
- }
-};
-
-static void OnPluginWindowClosed(const WindowInfo& window_info) {
- mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id,
- window_info.bounds);
-}
-
-static void OnPluginWindowShown(WindowRef window) {
- mac_plugin_interposing::NotifyBrowserOfPluginShowWindow(
- HIWindowGetCGWindowID(window), CGRectForWindow(window),
- IsModalWindow(window));
-}
-
-static void OnPluginWindowSelected(WindowRef window) {
- mac_plugin_interposing::NotifyBrowserOfPluginSelectWindow(
- HIWindowGetCGWindowID(window), CGRectForWindow(window),
- IsModalWindow(window));
-}
-
-#pragma mark -
-
-static void ChromePluginSelectWindow(WindowRef window) {
- mac_plugin_interposing::SwitchToPluginProcess();
- SelectWindow(window);
- OnPluginWindowSelected(window);
-}
-
-static void ChromePluginShowWindow(WindowRef window) {
- mac_plugin_interposing::SwitchToPluginProcess();
- ShowWindow(window);
- OnPluginWindowShown(window);
-}
-
-static void ChromePluginDisposeWindow(WindowRef window) {
- WindowInfo window_info(window);
- DisposeWindow(window);
- OnPluginWindowClosed(window_info);
-}
-
-static void ChromePluginHideWindow(WindowRef window) {
- WindowInfo window_info(window);
- HideWindow(window);
- OnPluginWindowClosed(window_info);
-}
-
-static void ChromePluginShowHide(WindowRef window, Boolean show) {
- if (show) {
- mac_plugin_interposing::SwitchToPluginProcess();
- ShowHide(window, show);
- OnPluginWindowShown(window);
- } else {
- WindowInfo window_info(window);
- ShowHide(window, show);
- OnPluginWindowClosed(window_info);
- }
-}
-
-static void ChromePluginReleaseWindow(WindowRef window) {
- WindowInfo window_info(window);
- ReleaseWindow(window);
- OnPluginWindowClosed(window_info);
-}
-
-static void ChromePluginDisposeDialog(DialogRef dialog) {
- WindowRef window = GetDialogWindow(dialog);
- WindowInfo window_info(window);
- DisposeDialog(dialog);
- OnPluginWindowClosed(window_info);
-}
-
-#pragma mark -
-
-struct interpose_substitution {
- const void* replacement;
- const void* original;
-};
-
-#define INTERPOSE_FUNCTION(function) \
- { reinterpret_cast<const void*>(ChromePlugin##function), \
- reinterpret_cast<const void*>(function) }
-
-__attribute__((used)) static const interpose_substitution substitutions[]
- __attribute__((section("__DATA, __interpose"))) = {
- INTERPOSE_FUNCTION(SelectWindow),
- INTERPOSE_FUNCTION(ShowWindow),
- INTERPOSE_FUNCTION(ShowHide),
- INTERPOSE_FUNCTION(DisposeWindow),
- INTERPOSE_FUNCTION(HideWindow),
- INTERPOSE_FUNCTION(ReleaseWindow),
- INTERPOSE_FUNCTION(DisposeDialog),
-};
-
-#endif // !__LP64__
diff --git a/chromium/content/plugin/plugin_channel.cc b/chromium/content/plugin/plugin_channel.cc
index 0f960442ae5..0b7ed4f40bf 100644
--- a/chromium/content/plugin/plugin_channel.cc
+++ b/chromium/content/plugin/plugin_channel.cc
@@ -79,11 +79,9 @@ class PluginChannel::MessageFilter : public IPC::MessageFilter {
}
// IPC::MessageFilter:
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
- sender_ = sender;
- }
+ void OnFilterAdded(IPC::Sender* sender) override { sender_ = sender; }
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
IPC_BEGIN_MESSAGE_MAP(PluginChannel::MessageFilter, message)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_Init, OnInit)
IPC_MESSAGE_HANDLER(PluginMsg_SignalModalDialogEvent,
@@ -96,7 +94,7 @@ class PluginChannel::MessageFilter : public IPC::MessageFilter {
}
protected:
- virtual ~MessageFilter() {
+ ~MessageFilter() override {
// Clean up in case of renderer crash.
for (ModalDialogEventMap::iterator i = modal_dialog_event_map_.begin();
i != modal_dialog_event_map_.end(); ++i) {
diff --git a/chromium/content/plugin/plugin_channel.h b/chromium/content/plugin/plugin_channel.h
index ffe5c79cc9b..d3106b347c5 100644
--- a/chromium/content/plugin/plugin_channel.h
+++ b/chromium/content/plugin/plugin_channel.h
@@ -33,17 +33,17 @@ class PluginChannel : public NPChannelBase {
static void NotifyRenderersOfPendingShutdown();
// IPC::Listener:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelError() override;
int renderer_id() { return renderer_id_; }
- virtual int GenerateRouteID() OVERRIDE;
+ int GenerateRouteID() override;
// Returns the event that's set when a call to the renderer causes a modal
// dialog to come up.
- virtual base::WaitableEvent* GetModalDialogEvent(int render_view_id) OVERRIDE;
+ base::WaitableEvent* GetModalDialogEvent(int render_view_id) override;
bool in_send() { return in_send_ != 0; }
@@ -51,19 +51,19 @@ class PluginChannel : public NPChannelBase {
void set_incognito(bool value) { incognito_ = value; }
#if defined(OS_POSIX)
- int TakeRendererFileDescriptor() {
+ base::ScopedFD TakeRendererFileDescriptor() {
return channel_->TakeClientFileDescriptor();
}
#endif
protected:
- virtual ~PluginChannel();
+ ~PluginChannel() override;
// NPChannelBase::
- virtual void CleanUp() OVERRIDE;
- virtual bool Init(base::MessageLoopProxy* ipc_message_loop,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) OVERRIDE;
+ void CleanUp() override;
+ bool Init(base::MessageLoopProxy* ipc_message_loop,
+ bool create_pipe_now,
+ base::WaitableEvent* shutdown_event) override;
private:
class MessageFilter;
@@ -71,7 +71,7 @@ class PluginChannel : public NPChannelBase {
// Called on the plugin thread
PluginChannel();
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& msg) override;
static NPChannelBase* ClassFactory() { return new PluginChannel(); }
diff --git a/chromium/content/plugin/plugin_interpose_util_mac.h b/chromium/content/plugin/plugin_interpose_util_mac.h
index fc812802fcb..1a6eb9ffd58 100644
--- a/chromium/content/plugin/plugin_interpose_util_mac.h
+++ b/chromium/content/plugin/plugin_interpose_util_mac.h
@@ -5,41 +5,14 @@
#ifndef CONTENT_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_
#define CONTENT_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_
-#include <Carbon/Carbon.h>
-
#import "base/basictypes.h"
-// This is really a WebPluginDelegateImpl, but that class is private to the
-// framework, and these functions are called from a dylib.
-typedef void* OpaquePluginRef;
-
namespace mac_plugin_interposing {
// Swizzles methods we need to watch in order to manage process and window
// focus correctly.
void SetUpCocoaInterposing();
-// Brings the plugin process to the front so that the user can see its windows.
-void SwitchToPluginProcess();
-
-// Returns the delegate currently processing events.
-OpaquePluginRef GetActiveDelegate();
-
-// Sends a message to the browser process to inform it that the given window
-// has been brought forward.
-void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds,
- bool modal);
-
-// Sends a message to the browser process to inform it that the given window
-// has been shown.
-void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds,
- bool modal);
-
-// Sends a message to the browser process to inform it that the given window
-// has been hidden, and switches focus back to the browser process if there are
-// no remaining plugin windows.
-void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds);
-
} // namespace MacPluginInterpose
#endif // CONTENT_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_
diff --git a/chromium/content/plugin/plugin_interpose_util_mac.mm b/chromium/content/plugin/plugin_interpose_util_mac.mm
index 62cef3a968f..b9265c3567f 100644
--- a/chromium/content/plugin/plugin_interpose_util_mac.mm
+++ b/chromium/content/plugin/plugin_interpose_util_mac.mm
@@ -13,11 +13,9 @@
using content::PluginThread;
-namespace mac_plugin_interposing {
+namespace {
-// TODO(stuartmorgan): Make this an IPC to order the plugin process above the
-// browser process only if the browser is current frontmost.
-__attribute__((visibility("default")))
+// Brings the plugin process to the front so that the user can see its windows.
void SwitchToPluginProcess() {
ProcessSerialNumber this_process, front_process;
if ((GetCurrentProcess(&this_process) != noErr) ||
@@ -32,24 +30,8 @@ void SwitchToPluginProcess() {
}
}
-__attribute__((visibility("default")))
-OpaquePluginRef GetActiveDelegate() {
- return content::WebPluginDelegateImpl::GetActiveDelegate();
-}
-
-__attribute__((visibility("default")))
-void NotifyBrowserOfPluginSelectWindow(uint32 window_id, CGRect bounds,
- bool modal) {
- PluginThread* plugin_thread = PluginThread::current();
- if (plugin_thread) {
- gfx::Rect window_bounds(bounds);
- plugin_thread->Send(
- new PluginProcessHostMsg_PluginSelectWindow(window_id, window_bounds,
- modal));
- }
-}
-
-__attribute__((visibility("default")))
+// Sends a message to the browser process to inform it that the given window
+// has been shown.
void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds,
bool modal) {
PluginThread* plugin_thread = PluginThread::current();
@@ -61,7 +43,9 @@ void NotifyBrowserOfPluginShowWindow(uint32 window_id, CGRect bounds,
}
}
-__attribute__((visibility("default")))
+// Sends a message to the browser process to inform it that the given window
+// has been hidden, and switches focus back to the browser process if there are
+// no remaining plugin windows.
void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds) {
PluginThread* plugin_thread = PluginThread::current();
if (plugin_thread) {
@@ -71,6 +55,7 @@ void NotifyBrowserOfPluginHideWindow(uint32 window_id, CGRect bounds) {
}
}
+// Informs the host that the plugin has changed the cursor visibility.
void NotifyPluginOfSetCursorVisibility(bool visibility) {
PluginThread* plugin_thread = PluginThread::current();
if (plugin_thread) {
@@ -79,10 +64,6 @@ void NotifyPluginOfSetCursorVisibility(bool visibility) {
}
}
-} // namespace mac_plugin_interposing
-
-#pragma mark -
-
struct WindowInfo {
uint32 window_id;
CGRect bounds;
@@ -93,16 +74,15 @@ struct WindowInfo {
}
};
-static void OnPluginWindowClosed(const WindowInfo& window_info) {
+void OnPluginWindowClosed(const WindowInfo& window_info) {
if (window_info.window_id == 0)
return;
- mac_plugin_interposing::NotifyBrowserOfPluginHideWindow(window_info.window_id,
- window_info.bounds);
+ NotifyBrowserOfPluginHideWindow(window_info.window_id, window_info.bounds);
}
-static BOOL g_waiting_for_window_number = NO;
+BOOL g_waiting_for_window_number = NO;
-static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
+void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
// The window id is 0 if it has never been shown (including while it is the
// process of being shown for the first time); when that happens, we'll catch
// it in _setWindowNumber instead.
@@ -118,10 +98,12 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
is_modal = YES;
s_pending_display_is_modal = NO;
}
- mac_plugin_interposing::NotifyBrowserOfPluginShowWindow(
- window_info.window_id, window_info.bounds, is_modal);
+ NotifyBrowserOfPluginShowWindow(window_info.window_id, window_info.bounds,
+ is_modal);
}
+} // namespace
+
@interface NSWindow (ChromePluginUtilities)
// Returns YES if the window is visible and actually on the screen.
- (BOOL)chromePlugin_isWindowOnScreen;
@@ -160,14 +142,14 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
- (void)chromePlugin_orderFront:(id)sender {
[self chromePlugin_orderFront:sender];
if ([self chromePlugin_isWindowOnScreen])
- mac_plugin_interposing::SwitchToPluginProcess();
+ SwitchToPluginProcess();
OnPluginWindowShown(WindowInfo(self), NO);
}
- (void)chromePlugin_makeKeyAndOrderFront:(id)sender {
[self chromePlugin_makeKeyAndOrderFront:sender];
if ([self chromePlugin_isWindowOnScreen])
- mac_plugin_interposing::SwitchToPluginProcess();
+ SwitchToPluginProcess();
OnPluginWindowShown(WindowInfo(self), NO);
}
@@ -176,7 +158,7 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
[self chromePlugin_setWindowNumber:num];
return;
}
- mac_plugin_interposing::SwitchToPluginProcess();
+ SwitchToPluginProcess();
[self chromePlugin_setWindowNumber:num];
OnPluginWindowShown(WindowInfo(self), NO);
}
@@ -190,7 +172,7 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
@implementation NSApplication (ChromePluginInterposing)
- (NSInteger)chromePlugin_runModalForWindow:(NSWindow*)window {
- mac_plugin_interposing::SwitchToPluginProcess();
+ SwitchToPluginProcess();
// This is out-of-order relative to the other calls, but runModalForWindow:
// won't return until the window closes, and the order only matters for
// full-screen windows.
@@ -209,20 +191,21 @@ static void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
@implementation NSCursor (ChromePluginInterposing)
- (void)chromePlugin_set {
- OpaquePluginRef delegate = mac_plugin_interposing::GetActiveDelegate();
+ content::WebPluginDelegateImpl* delegate =
+ content::WebPluginDelegateImpl::GetActiveDelegate();
if (delegate) {
- static_cast<content::WebPluginDelegateImpl*>(delegate)->SetNSCursor(self);
+ delegate->SetNSCursor(self);
return;
}
[self chromePlugin_set];
}
+ (void)chromePlugin_hide {
- mac_plugin_interposing::NotifyPluginOfSetCursorVisibility(false);
+ NotifyPluginOfSetCursorVisibility(false);
}
+ (void)chromePlugin_unhide {
- mac_plugin_interposing::NotifyPluginOfSetCursorVisibility(true);
+ NotifyPluginOfSetCursorVisibility(true);
}
@end
diff --git a/chromium/content/plugin/plugin_main.cc b/chromium/content/plugin/plugin_main.cc
index bcf8856561e..a793831a4fa 100644
--- a/chromium/content/plugin/plugin_main.cc
+++ b/chromium/content/plugin/plugin_main.cc
@@ -32,10 +32,6 @@
namespace content {
#if defined(OS_MACOSX)
-// Removes our Carbon library interposing from the environment so that it
-// doesn't carry into any processes that plugins might start.
-void TrimInterposeEnvironment();
-
// Initializes the global Cocoa application object.
void InitializeChromeApplication();
#endif
@@ -44,9 +40,6 @@ void InitializeChromeApplication();
int PluginMain(const MainFunctionParams& parameters) {
// The main thread of the plugin services UI.
#if defined(OS_MACOSX)
-#if !defined(__LP64__)
- TrimInterposeEnvironment();
-#endif
InitializeChromeApplication();
#endif
base::MessageLoopForUI main_message_loop;
diff --git a/chromium/content/plugin/plugin_main_mac.mm b/chromium/content/plugin/plugin_main_mac.mm
index 91deed83dab..fddaa59ba13 100644
--- a/chromium/content/plugin/plugin_main_mac.mm
+++ b/chromium/content/plugin/plugin_main_mac.mm
@@ -4,47 +4,10 @@
#import <AppKit/AppKit.h>
-#include "base/environment.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "content/common/plugin_carbon_interpose_constants_mac.h"
#include "content/plugin/plugin_interpose_util_mac.h"
-#include "content/public/common/content_client.h"
namespace content {
-#if !defined(__LP64__)
-void TrimInterposeEnvironment() {
- scoped_ptr<base::Environment> env(base::Environment::Create());
-
- std::string interpose_list;
- if (!env->GetVar(kDYLDInsertLibrariesKey, &interpose_list)) {
- VLOG(0) << "No Carbon Interpose library found.";
- return;
- }
-
- // The list is a :-separated list of paths. Because we append our interpose
- // library just before forking in plugin_process_host.cc, the only cases we
- // need to handle are:
- // 1) The whole string is "<kInterposeLibraryPath>", so just clear it, or
- // 2) ":<kInterposeLibraryPath>" is the end of the string, so trim and re-set.
- std::string interpose_library_path =
- GetContentClient()->GetCarbonInterposePath();
- DCHECK_GE(interpose_list.size(), interpose_library_path.size());
- size_t suffix_offset = interpose_list.size() - interpose_library_path.size();
- if (suffix_offset == 0 &&
- interpose_list == interpose_library_path) {
- env->UnSetVar(kDYLDInsertLibrariesKey);
- } else if (suffix_offset > 0 && interpose_list[suffix_offset - 1] == ':' &&
- interpose_list.substr(suffix_offset) == interpose_library_path) {
- std::string trimmed_list = interpose_list.substr(0, suffix_offset - 1);
- env->SetVar(kDYLDInsertLibrariesKey, trimmed_list.c_str());
- } else {
- NOTREACHED() << "Missing Carbon interposing library";
- }
-}
-#endif
-
void InitializeChromeApplication() {
[NSApplication sharedApplication];
mac_plugin_interposing::SetUpCocoaInterposing();
diff --git a/chromium/content/plugin/plugin_thread.cc b/chromium/content/plugin/plugin_thread.cc
index bec0f98d887..e51e39b9a63 100644
--- a/chromium/content/plugin/plugin_thread.cc
+++ b/chromium/content/plugin/plugin_thread.cc
@@ -39,10 +39,10 @@ class EnsureTerminateMessageFilter : public IPC::MessageFilter {
EnsureTerminateMessageFilter() {}
protected:
- virtual ~EnsureTerminateMessageFilter() {}
+ ~EnsureTerminateMessageFilter() override {}
// IPC::MessageFilter:
- virtual void OnChannelError() OVERRIDE {
+ void OnChannelError() override {
// How long we wait before forcibly shutting down the process.
const base::TimeDelta kPluginProcessTerminateTimeout =
base::TimeDelta::FromSeconds(3);
@@ -93,9 +93,9 @@ PluginThread::PluginThread()
channel()->AddFilter(new EnsureTerminateMessageFilter());
- // This is needed because we call some code which uses WebKit strings.
- webkit_platform_support_.reset(new BlinkPlatformImpl);
- blink::initialize(webkit_platform_support_.get());
+ // This is needed because we call some code which uses Blink strings.
+ blink_platform_impl_.reset(new BlinkPlatformImpl);
+ blink::initialize(blink_platform_impl_.get());
}
PluginThread::~PluginThread() {
@@ -146,7 +146,7 @@ void PluginThread::OnCreateChannel(int renderer_id,
#if defined(OS_POSIX)
// On POSIX, pass the renderer-side FD.
channel_handle.socket =
- base::FileDescriptor(channel->TakeRendererFileDescriptor(), true);
+ base::FileDescriptor(channel->TakeRendererFileDescriptor());
#endif
channel->set_incognito(incognito);
}
diff --git a/chromium/content/plugin/plugin_thread.h b/chromium/content/plugin/plugin_thread.h
index f76cfa1b3a1..11acafc79c1 100644
--- a/chromium/content/plugin/plugin_thread.h
+++ b/chromium/content/plugin/plugin_thread.h
@@ -25,8 +25,8 @@ class BlinkPlatformImpl;
class PluginThread : public ChildThread {
public:
PluginThread();
- virtual ~PluginThread();
- virtual void Shutdown() OVERRIDE;
+ ~PluginThread() override;
+ void Shutdown() override;
// Returns the one plugin thread.
static PluginThread* current();
@@ -36,7 +36,7 @@ class PluginThread : public ChildThread {
void SetForcefullyTerminatePluginProcess();
private:
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& msg) override;
// Callback for when a channel has been created.
void OnCreateChannel(int renderer_id, bool incognito);
@@ -52,7 +52,7 @@ class PluginThread : public ChildThread {
bool forcefully_terminate_plugin_process_;
- scoped_ptr<BlinkPlatformImpl> webkit_platform_support_;
+ scoped_ptr<BlinkPlatformImpl> blink_platform_impl_;
DISALLOW_COPY_AND_ASSIGN(PluginThread);
};
diff --git a/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h b/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h
index d3b115a6e5d..2374ba3ef18 100644
--- a/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h
+++ b/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h
@@ -25,13 +25,13 @@ class WebPluginAcceleratedSurfaceProxy : public WebPluginAcceleratedSurface {
WebPluginProxy* plugin_proxy,
gfx::GpuPreference gpu_preference);
- virtual ~WebPluginAcceleratedSurfaceProxy();
+ ~WebPluginAcceleratedSurfaceProxy() override;
// WebPluginAcceleratedSurface implementation.
- virtual void SetSize(const gfx::Size& size) OVERRIDE;
- virtual CGLContextObj context() OVERRIDE;
- virtual void StartDrawing() OVERRIDE;
- virtual void EndDrawing() OVERRIDE;
+ void SetSize(const gfx::Size& size) override;
+ CGLContextObj context() override;
+ void StartDrawing() override;
+ void EndDrawing() override;
private:
WebPluginAcceleratedSurfaceProxy(WebPluginProxy* plugin_proxy,
diff --git a/chromium/content/plugin/webplugin_delegate_stub.h b/chromium/content/plugin/webplugin_delegate_stub.h
index e0f6526f8b0..d6f6323db1e 100644
--- a/chromium/content/plugin/webplugin_delegate_stub.h
+++ b/chromium/content/plugin/webplugin_delegate_stub.h
@@ -42,10 +42,10 @@ class WebPluginDelegateStub : public IPC::Listener,
PluginChannel* channel);
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
int instance_id() { return instance_id_; }
WebPluginDelegateImpl* delegate() { return delegate_; }
@@ -54,7 +54,7 @@ class WebPluginDelegateStub : public IPC::Listener,
private:
friend class base::RefCounted<WebPluginDelegateStub>;
- virtual ~WebPluginDelegateStub();
+ ~WebPluginDelegateStub() override;
// Message handlers for the WebPluginDelegate calls that are proxied from the
// renderer over the IPC channel.
diff --git a/chromium/content/plugin/webplugin_proxy.h b/chromium/content/plugin/webplugin_proxy.h
index 5cece13893e..e1fb45dc8e8 100644
--- a/chromium/content/plugin/webplugin_proxy.h
+++ b/chromium/content/plugin/webplugin_proxy.h
@@ -15,7 +15,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
#include "content/child/npapi/webplugin.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
@@ -46,69 +45,67 @@ class WebPluginProxy : public WebPlugin,
int route_id,
const GURL& page_url,
int host_render_view_routing_id);
- virtual ~WebPluginProxy();
+ ~WebPluginProxy() override;
void set_delegate(WebPluginDelegateImpl* d) { delegate_ = d; }
// WebPlugin overrides
- virtual void SetWindow(gfx::PluginWindowHandle window) OVERRIDE;
- virtual void SetAcceptsInputEvents(bool accepts) OVERRIDE;
- virtual void WillDestroyWindow(gfx::PluginWindowHandle window) OVERRIDE;
- virtual void CancelResource(unsigned long id) OVERRIDE;
- virtual void Invalidate() OVERRIDE;
- virtual void InvalidateRect(const gfx::Rect& rect) OVERRIDE;
- virtual NPObject* GetWindowScriptNPObject() OVERRIDE;
- virtual NPObject* GetPluginElement() OVERRIDE;
- virtual bool FindProxyForUrl(const GURL& url,
- std::string* proxy_list) OVERRIDE;
- virtual void SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) OVERRIDE;
- virtual std::string GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) OVERRIDE;
- virtual void HandleURLRequest(const char* url,
- const char* method,
- const char* target,
- const char* buf,
- unsigned int len,
- int notify_id,
- bool popups_allowed,
- bool notify_redirects) OVERRIDE;
+ void SetWindow(gfx::PluginWindowHandle window) override;
+ void SetAcceptsInputEvents(bool accepts) override;
+ void WillDestroyWindow(gfx::PluginWindowHandle window) override;
+ void CancelResource(unsigned long id) override;
+ void Invalidate() override;
+ void InvalidateRect(const gfx::Rect& rect) override;
+ NPObject* GetWindowScriptNPObject() override;
+ NPObject* GetPluginElement() override;
+ bool FindProxyForUrl(const GURL& url, std::string* proxy_list) override;
+ void SetCookie(const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& cookie) override;
+ std::string GetCookies(const GURL& url,
+ const GURL& first_party_for_cookies) override;
+ void HandleURLRequest(const char* url,
+ const char* method,
+ const char* target,
+ const char* buf,
+ unsigned int len,
+ int notify_id,
+ bool popups_allowed,
+ bool notify_redirects) override;
void UpdateGeometry(const gfx::Rect& window_rect,
const gfx::Rect& clip_rect,
const TransportDIB::Handle& windowless_buffer0,
const TransportDIB::Handle& windowless_buffer1,
int windowless_buffer_index);
- virtual void CancelDocumentLoad() OVERRIDE;
- virtual void InitiateHTTPRangeRequest(
- const char* url, const char* range_info, int range_request_id) OVERRIDE;
- virtual void DidStartLoading() OVERRIDE;
- virtual void DidStopLoading() OVERRIDE;
- virtual void SetDeferResourceLoading(unsigned long resource_id,
- bool defer) OVERRIDE;
- virtual bool IsOffTheRecord() OVERRIDE;
- virtual void ResourceClientDeleted(
- WebPluginResourceClient* resource_client) OVERRIDE;
- virtual void URLRedirectResponse(bool allow, int resource_id) OVERRIDE;
- virtual bool CheckIfRunInsecureContent(const GURL& url) OVERRIDE;
+ void CancelDocumentLoad() override;
+ void InitiateHTTPRangeRequest(const char* url,
+ const char* range_info,
+ int range_request_id) override;
+ void DidStartLoading() override;
+ void DidStopLoading() override;
+ void SetDeferResourceLoading(unsigned long resource_id, bool defer) override;
+ bool IsOffTheRecord() override;
+ void ResourceClientDeleted(WebPluginResourceClient* resource_client) override;
+ void URLRedirectResponse(bool allow, int resource_id) override;
+ bool CheckIfRunInsecureContent(const GURL& url) override;
#if defined(OS_WIN)
void SetWindowlessData(HANDLE pump_messages_event,
gfx::NativeViewId dummy_activation_window);
#endif
#if defined(OS_MACOSX)
- virtual void FocusChanged(bool focused) OVERRIDE;
- virtual void StartIme() OVERRIDE;
- virtual WebPluginAcceleratedSurface*
- GetAcceleratedSurface(gfx::GpuPreference gpu_preference) OVERRIDE;
- virtual void AcceleratedPluginEnabledRendering() OVERRIDE;
- virtual void AcceleratedPluginAllocatedIOSurface(int32 width,
- int32 height,
- uint32 surface_id) OVERRIDE;
- virtual void AcceleratedPluginSwappedIOSurface() OVERRIDE;
+ void FocusChanged(bool focused) override;
+ void StartIme() override;
+ WebPluginAcceleratedSurface* GetAcceleratedSurface(
+ gfx::GpuPreference gpu_preference) override;
+ void AcceleratedPluginEnabledRendering() override;
+ void AcceleratedPluginAllocatedIOSurface(int32 width,
+ int32 height,
+ uint32 surface_id) override;
+ void AcceleratedPluginSwappedIOSurface() override;
#endif
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// class-specific methods
diff --git a/chromium/content/ppapi_plugin/BUILD.gn b/chromium/content/ppapi_plugin/BUILD.gn
index fae7d1af851..eff00a52cba 100644
--- a/chromium/content/ppapi_plugin/BUILD.gn
+++ b/chromium/content/ppapi_plugin/BUILD.gn
@@ -3,17 +3,19 @@
# found in the LICENSE file.
source_set("ppapi_plugin") {
+ visibility = [ "//content/*" ]
+
sources = [
"broker_process_dispatcher.cc",
"broker_process_dispatcher.h",
"plugin_process_dispatcher.cc",
"plugin_process_dispatcher.h",
+ "ppapi_blink_platform_impl.cc",
+ "ppapi_blink_platform_impl.h",
"ppapi_broker_main.cc",
"ppapi_plugin_main.cc",
"ppapi_thread.cc",
"ppapi_thread.h",
- "ppapi_webkitplatformsupport_impl.cc",
- "ppapi_webkitplatformsupport_impl.h",
]
configs += [ "//content:content_implementation" ]
@@ -21,13 +23,13 @@ source_set("ppapi_plugin") {
deps = [
"//base",
"//content:export",
- "//mojo/public/interfaces/service_provider",
+ "//content/public/child:child_sources",
+ "//content/public/common:common_sources",
+ "//mojo/public/interfaces/application",
"//ppapi:ppapi_ipc",
"//skia",
"//third_party/icu",
- #"//third_party/WebKit/public:blink", TODO(GYP)
- # TODO(GYP) remove this when blink is enabled:
- "//third_party/WebKit/public:blink_headers",
+ "//third_party/WebKit/public:blink",
"//ui/base",
"//ui/gfx",
"//ui/gfx/geometry",
diff --git a/chromium/content/ppapi_plugin/broker_process_dispatcher.h b/chromium/content/ppapi_plugin/broker_process_dispatcher.h
index 7b6471765f1..bbdbfdcc323 100644
--- a/chromium/content/ppapi_plugin/broker_process_dispatcher.h
+++ b/chromium/content/ppapi_plugin/broker_process_dispatcher.h
@@ -23,10 +23,10 @@ class BrokerProcessDispatcher
public:
BrokerProcessDispatcher(PP_GetInterface_Func get_plugin_interface,
PP_ConnectInstance_Func connect_instance);
- virtual ~BrokerProcessDispatcher();
+ ~BrokerProcessDispatcher() override;
// IPC::Listener overrides.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
void OnGetPermissionSettingsCompleted(
uint32 request_id,
diff --git a/chromium/content/ppapi_plugin/plugin_process_dispatcher.h b/chromium/content/ppapi_plugin/plugin_process_dispatcher.h
index 2d80e0f02ec..548bdc2a70e 100644
--- a/chromium/content/ppapi_plugin/plugin_process_dispatcher.h
+++ b/chromium/content/ppapi_plugin/plugin_process_dispatcher.h
@@ -19,7 +19,7 @@ class PluginProcessDispatcher : public ppapi::proxy::PluginDispatcher {
PluginProcessDispatcher(PP_GetInterface_Func get_interface,
const ppapi::PpapiPermissions& permissions,
bool incognito);
- virtual ~PluginProcessDispatcher();
+ ~PluginProcessDispatcher() override;
private:
ScopedChildProcessReference process_ref_;
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
new file mode 100644
index 00000000000..ad84196ac3f
--- /dev/null
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
@@ -0,0 +1,257 @@
+// Copyright (c) 2012 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 "content/ppapi_plugin/ppapi_blink_platform_impl.h"
+
+#include <map>
+
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
+#include "content/child/child_thread.h"
+#include "content/common/child_process_messages.h"
+#include "ppapi/proxy/plugin_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+
+#if defined(OS_WIN)
+#include "third_party/WebKit/public/platform/win/WebSandboxSupport.h"
+#elif defined(OS_MACOSX)
+#include "third_party/WebKit/public/platform/mac/WebSandboxSupport.h"
+#elif defined(OS_ANDROID)
+#include "third_party/WebKit/public/platform/android/WebSandboxSupport.h"
+#elif defined(OS_POSIX)
+#include "content/common/child_process_sandbox_support_impl_linux.h"
+#include "third_party/WebKit/public/platform/linux/WebFallbackFont.h"
+#include "third_party/WebKit/public/platform/linux/WebSandboxSupport.h"
+#include "third_party/icu/source/common/unicode/utf16.h"
+#endif
+
+using blink::WebSandboxSupport;
+using blink::WebString;
+using blink::WebUChar;
+using blink::WebUChar32;
+
+typedef struct CGFont* CGFontRef;
+
+namespace content {
+
+class PpapiBlinkPlatformImpl::SandboxSupport : public WebSandboxSupport {
+ public:
+ virtual ~SandboxSupport() {}
+
+#if defined(OS_WIN)
+ virtual bool ensureFontLoaded(HFONT);
+#elif defined(OS_MACOSX)
+ virtual bool loadFont(NSFont* srcFont, CGFontRef* out, uint32_t* fontID);
+#elif defined(OS_ANDROID)
+ // Empty class.
+#elif defined(OS_POSIX)
+ SandboxSupport();
+ virtual void getFallbackFontForCharacter(
+ WebUChar32 character,
+ const char* preferred_locale,
+ blink::WebFallbackFont* fallbackFont);
+ virtual void getRenderStyleForStrike(const char* family,
+ int sizeAndStyle,
+ blink::WebFontRenderStyle* out);
+
+ private:
+ // WebKit likes to ask us for the correct font family to use for a set of
+ // unicode code points. It needs this information frequently so we cache it
+ // here.
+ std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
+ // For debugging crbug.com/312965
+ base::PlatformThreadId creation_thread_;
+#endif
+};
+
+#if defined(OS_WIN)
+
+bool PpapiBlinkPlatformImpl::SandboxSupport::ensureFontLoaded(HFONT font) {
+ LOGFONT logfont;
+ GetObject(font, sizeof(LOGFONT), &logfont);
+
+ // Use the proxy sender rather than going directly to the ChildThread since
+ // the proxy browser sender will properly unlock during sync messages.
+ return ppapi::proxy::PluginGlobals::Get()->GetBrowserSender()->Send(
+ new ChildProcessHostMsg_PreCacheFont(logfont));
+}
+
+#elif defined(OS_MACOSX)
+
+bool PpapiBlinkPlatformImpl::SandboxSupport::loadFont(NSFont* src_font,
+ CGFontRef* out,
+ uint32_t* font_id) {
+ // TODO(brettw) this should do the something similar to what
+ // RendererBlinkPlatformImpl does and request that the browser load the font.
+ // Note: need to unlock the proxy lock like ensureFontLoaded does.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+#elif defined(OS_ANDROID)
+
+// Empty class.
+
+#elif defined(OS_POSIX)
+
+PpapiBlinkPlatformImpl::SandboxSupport::SandboxSupport()
+ : creation_thread_(base::PlatformThread::CurrentId()) {
+}
+
+void PpapiBlinkPlatformImpl::SandboxSupport::getFallbackFontForCharacter(
+ WebUChar32 character,
+ const char* preferred_locale,
+ blink::WebFallbackFont* fallbackFont) {
+ ppapi::ProxyLock::AssertAcquired();
+ // For debugging crbug.com/312965
+ CHECK_EQ(creation_thread_, base::PlatformThread::CurrentId());
+ const std::map<int32_t, blink::WebFallbackFont>::const_iterator iter =
+ unicode_font_families_.find(character);
+ if (iter != unicode_font_families_.end()) {
+ fallbackFont->name = iter->second.name;
+ fallbackFont->filename = iter->second.filename;
+ fallbackFont->fontconfigInterfaceId = iter->second.fontconfigInterfaceId;
+ fallbackFont->ttcIndex = iter->second.ttcIndex;
+ fallbackFont->isBold = iter->second.isBold;
+ fallbackFont->isItalic = iter->second.isItalic;
+ return;
+ }
+
+ GetFallbackFontForCharacter(character, preferred_locale, fallbackFont);
+ unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
+}
+
+void PpapiBlinkPlatformImpl::SandboxSupport::getRenderStyleForStrike(
+ const char* family,
+ int sizeAndStyle,
+ blink::WebFontRenderStyle* out) {
+ GetRenderStyleForStrike(family, sizeAndStyle, out);
+}
+
+#endif
+
+PpapiBlinkPlatformImpl::PpapiBlinkPlatformImpl()
+ : sandbox_support_(new PpapiBlinkPlatformImpl::SandboxSupport()) {
+}
+
+PpapiBlinkPlatformImpl::~PpapiBlinkPlatformImpl() {
+}
+
+void PpapiBlinkPlatformImpl::Shutdown() {
+ // SandboxSupport contains a map of WebFontFamily objects, which hold
+ // WebCStrings, which become invalidated when blink is shut down. Hence, we
+ // need to clear that map now, just before blink::shutdown() is called.
+ sandbox_support_.reset();
+}
+
+blink::WebClipboard* PpapiBlinkPlatformImpl::clipboard() {
+ NOTREACHED();
+ return NULL;
+}
+
+blink::WebMimeRegistry* PpapiBlinkPlatformImpl::mimeRegistry() {
+ NOTREACHED();
+ return NULL;
+}
+
+blink::WebFileUtilities* PpapiBlinkPlatformImpl::fileUtilities() {
+ NOTREACHED();
+ return NULL;
+}
+
+blink::WebSandboxSupport* PpapiBlinkPlatformImpl::sandboxSupport() {
+ return sandbox_support_.get();
+}
+
+bool PpapiBlinkPlatformImpl::sandboxEnabled() {
+ return true; // Assume PPAPI is always sandboxed.
+}
+
+unsigned long long PpapiBlinkPlatformImpl::visitedLinkHash(
+ const char* canonical_url,
+ size_t length) {
+ NOTREACHED();
+ return 0;
+}
+
+bool PpapiBlinkPlatformImpl::isLinkVisited(unsigned long long link_hash) {
+ NOTREACHED();
+ return false;
+}
+
+void PpapiBlinkPlatformImpl::createMessageChannel(
+ blink::WebMessagePortChannel** channel1,
+ blink::WebMessagePortChannel** channel2) {
+ NOTREACHED();
+ *channel1 = NULL;
+ *channel2 = NULL;
+}
+
+void PpapiBlinkPlatformImpl::setCookies(
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& value) {
+ NOTREACHED();
+}
+
+blink::WebString PpapiBlinkPlatformImpl::cookies(
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies) {
+ NOTREACHED();
+ return blink::WebString();
+}
+
+blink::WebString PpapiBlinkPlatformImpl::defaultLocale() {
+ NOTREACHED();
+ return blink::WebString();
+}
+
+blink::WebThemeEngine* PpapiBlinkPlatformImpl::themeEngine() {
+ NOTREACHED();
+ return NULL;
+}
+
+blink::WebURLLoader* PpapiBlinkPlatformImpl::createURLLoader() {
+ NOTREACHED();
+ return NULL;
+}
+
+void PpapiBlinkPlatformImpl::getPluginList(
+ bool refresh,
+ blink::WebPluginListBuilder* builder) {
+ NOTREACHED();
+}
+
+blink::WebData PpapiBlinkPlatformImpl::loadResource(const char* name) {
+ NOTREACHED();
+ return blink::WebData();
+}
+
+blink::WebStorageNamespace*
+PpapiBlinkPlatformImpl::createLocalStorageNamespace() {
+ NOTREACHED();
+ return 0;
+}
+
+void PpapiBlinkPlatformImpl::dispatchStorageEvent(
+ const blink::WebString& key,
+ const blink::WebString& old_value,
+ const blink::WebString& new_value,
+ const blink::WebString& origin,
+ const blink::WebURL& url,
+ bool is_local_storage) {
+ NOTREACHED();
+}
+
+int PpapiBlinkPlatformImpl::databaseDeleteFile(
+ const blink::WebString& vfs_file_name,
+ bool sync_dir) {
+ NOTREACHED();
+ return 0;
+}
+
+} // namespace content
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
new file mode 100644
index 00000000000..25076d8fd30
--- /dev/null
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 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 CONTENT_PPAPI_PLUGIN_PPAPI_BLINK_PLATFORM_IMPL_H_
+#define CONTENT_PPAPI_PLUGIN_PPAPI_BLINK_PLATFORM_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/child/blink_platform_impl.h"
+
+namespace content {
+
+class PpapiBlinkPlatformImpl : public BlinkPlatformImpl {
+ public:
+ PpapiBlinkPlatformImpl();
+ virtual ~PpapiBlinkPlatformImpl();
+
+ // Shutdown must be called just prior to shutting down blink.
+ void Shutdown();
+
+ // BlinkPlatformImpl methods:
+ virtual blink::WebClipboard* clipboard();
+ virtual blink::WebMimeRegistry* mimeRegistry();
+ virtual blink::WebFileUtilities* fileUtilities();
+ virtual blink::WebSandboxSupport* sandboxSupport();
+ virtual bool sandboxEnabled();
+ virtual unsigned long long visitedLinkHash(const char* canonicalURL,
+ size_t length);
+ virtual bool isLinkVisited(unsigned long long linkHash);
+ virtual void createMessageChannel(blink::WebMessagePortChannel** channel1,
+ blink::WebMessagePortChannel** channel2);
+ virtual void setCookies(const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies,
+ const blink::WebString& value);
+ virtual blink::WebString cookies(
+ const blink::WebURL& url,
+ const blink::WebURL& first_party_for_cookies);
+ virtual blink::WebString defaultLocale();
+ virtual blink::WebThemeEngine* themeEngine();
+ virtual blink::WebURLLoader* createURLLoader();
+ virtual void getPluginList(bool refresh, blink::WebPluginListBuilder*);
+ virtual blink::WebData loadResource(const char* name);
+ virtual blink::WebStorageNamespace* createLocalStorageNamespace();
+ virtual void dispatchStorageEvent(const blink::WebString& key,
+ const blink::WebString& oldValue, const blink::WebString& newValue,
+ const blink::WebString& origin, const blink::WebURL& url,
+ bool isLocalStorage);
+ virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
+ bool sync_dir);
+
+ private:
+ class SandboxSupport;
+ scoped_ptr<SandboxSupport> sandbox_support_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiBlinkPlatformImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_PPAPI_PLUGIN_PPAPI_BLINK_PLATFORM_IMPL_H_
diff --git a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
index 81ca51edeb7..fb0beda4ab3 100644
--- a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
+++ b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -30,7 +30,7 @@
#endif
#if defined(OS_CHROMEOS)
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#endif
#if defined(OS_LINUX)
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.cc b/chromium/content/ppapi_plugin/ppapi_thread.cc
index 62cf021b007..45d8951fe67 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.cc
+++ b/chromium/content/ppapi_plugin/ppapi_thread.cc
@@ -9,7 +9,7 @@
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/debug/crash_logging.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
@@ -24,7 +24,7 @@
#include "content/common/sandbox_util.h"
#include "content/ppapi_plugin/broker_process_dispatcher.h"
#include "content/ppapi_plugin/plugin_process_dispatcher.h"
-#include "content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h"
+#include "content/ppapi_plugin/ppapi_blink_platform_impl.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
@@ -107,12 +107,12 @@ PpapiThread::PpapiThread(const CommandLine& command_line, bool is_broker)
base::RandInt(0, std::numeric_limits<PP_Module>::max())),
next_plugin_dispatcher_id_(1) {
ppapi::proxy::PluginGlobals* globals = ppapi::proxy::PluginGlobals::Get();
- globals->set_plugin_proxy_delegate(this);
+ globals->SetPluginProxyDelegate(this);
globals->set_command_line(
command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs));
- webkit_platform_support_.reset(new PpapiWebKitPlatformSupportImpl);
- blink::initialize(webkit_platform_support_.get());
+ blink_platform_impl_.reset(new PpapiBlinkPlatformImpl);
+ blink::initialize(blink_platform_impl_.get());
if (!is_broker_) {
channel()->AddFilter(
@@ -125,10 +125,12 @@ PpapiThread::~PpapiThread() {
}
void PpapiThread::Shutdown() {
- ppapi::proxy::PluginGlobals::Get()->set_plugin_proxy_delegate(NULL);
+ ChildThread::Shutdown();
+
+ ppapi::proxy::PluginGlobals::Get()->ResetPluginProxyDelegate();
if (plugin_entry_points_.shutdown_module)
plugin_entry_points_.shutdown_module();
- webkit_platform_support_->Shutdown();
+ blink_platform_impl_->Shutdown();
blink::shutdown();
}
@@ -179,7 +181,7 @@ IPC::PlatformFileForTransit PpapiThread::ShareHandleWithRemote(
#if defined(OS_WIN)
if (peer_handle_.IsValid()) {
DCHECK(is_broker_);
- return IPC::GetFileHandleForProcess(handle, peer_handle_,
+ return IPC::GetFileHandleForProcess(handle, peer_handle_.Get(),
should_close_source);
}
#endif
@@ -490,7 +492,7 @@ bool PpapiThread::SetupRendererChannel(base::ProcessId renderer_pid,
// On POSIX, transfer ownership of the renderer-side (client) FD.
// This ensures this process will be notified when it is closed even if a
// connection is not established.
- handle->socket = base::FileDescriptor(dispatcher->TakeRendererFD(), true);
+ handle->socket = base::FileDescriptor(dispatcher->TakeRendererFD());
if (handle->socket.fd == -1)
return false;
#endif
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.h b/chromium/content/ppapi_plugin/ppapi_thread.h
index 87ac2cca15c..3d80e490c9f 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.h
+++ b/chromium/content/ppapi_plugin/ppapi_thread.h
@@ -38,15 +38,15 @@ struct ChannelHandle;
namespace content {
-class PpapiWebKitPlatformSupportImpl;
+class PpapiBlinkPlatformImpl;
class PpapiThread : public ChildThread,
public ppapi::proxy::PluginDispatcher::PluginDelegate,
public ppapi::proxy::PluginProxyDelegate {
public:
PpapiThread(const base::CommandLine& command_line, bool is_broker);
- virtual ~PpapiThread();
- virtual void Shutdown() OVERRIDE;
+ ~PpapiThread() override;
+ void Shutdown() override;
private:
// Make sure the enum list in tools/histogram/histograms.xml is updated with
@@ -62,34 +62,32 @@ class PpapiThread : public ChildThread,
};
// ChildThread overrides.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+ bool OnControlMessageReceived(const IPC::Message& msg) override;
+ void OnChannelConnected(int32 peer_pid) override;
// PluginDispatcher::PluginDelegate implementation.
- virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() OVERRIDE;
- virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE;
- virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE;
- virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override;
+ base::MessageLoopProxy* GetIPCMessageLoop() override;
+ base::WaitableEvent* GetShutdownEvent() override;
+ IPC::PlatformFileForTransit ShareHandleWithRemote(
base::PlatformFile handle,
base::ProcessId peer_pid,
- bool should_close_source) OVERRIDE;
- virtual uint32 Register(
- ppapi::proxy::PluginDispatcher* plugin_dispatcher) OVERRIDE;
- virtual void Unregister(uint32 plugin_dispatcher_id) OVERRIDE;
+ bool should_close_source) override;
+ uint32 Register(ppapi::proxy::PluginDispatcher* plugin_dispatcher) override;
+ void Unregister(uint32 plugin_dispatcher_id) override;
// PluginProxyDelegate.
// SendToBrowser() is intended to be safe to use on another thread so
// long as the main PpapiThread outlives it.
- virtual IPC::Sender* GetBrowserSender() OVERRIDE;
- virtual std::string GetUILanguage() OVERRIDE;
- virtual void PreCacheFont(const void* logfontw) OVERRIDE;
- virtual void SetActiveURL(const std::string& url) OVERRIDE;
- virtual PP_Resource CreateBrowserFont(
- ppapi::proxy::Connection connection,
- PP_Instance instance,
- const PP_BrowserFont_Trusted_Description& desc,
- const ppapi::Preferences& prefs) OVERRIDE;
+ IPC::Sender* GetBrowserSender() override;
+ std::string GetUILanguage() override;
+ void PreCacheFont(const void* logfontw) override;
+ void SetActiveURL(const std::string& url) override;
+ PP_Resource CreateBrowserFont(ppapi::proxy::Connection connection,
+ PP_Instance instance,
+ const PP_BrowserFont_Trusted_Description& desc,
+ const ppapi::Preferences& prefs) override;
// Message handlers.
void OnLoadPlugin(const base::FilePath& path,
@@ -149,8 +147,8 @@ class PpapiThread : public ChildThread,
std::map<uint32, ppapi::proxy::PluginDispatcher*> plugin_dispatchers_;
uint32 next_plugin_dispatcher_id_;
- // The WebKitPlatformSupport implementation.
- scoped_ptr<PpapiWebKitPlatformSupportImpl> webkit_platform_support_;
+ // The BlinkPlatformImpl implementation.
+ scoped_ptr<PpapiBlinkPlatformImpl> blink_platform_impl_;
#if defined(OS_WIN)
// Caches the handle to the peer process if this is a broker.
diff --git a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc b/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc
deleted file mode 100644
index cfbed442068..00000000000
--- a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (c) 2012 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 "content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h"
-
-#include <map>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/threading/platform_thread.h"
-#include "build/build_config.h"
-#include "content/child/child_thread.h"
-#include "content/common/child_process_messages.h"
-#include "ppapi/proxy/plugin_globals.h"
-#include "ppapi/shared_impl/proxy_lock.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-
-#if defined(OS_WIN)
-#include "third_party/WebKit/public/platform/win/WebSandboxSupport.h"
-#elif defined(OS_MACOSX)
-#include "third_party/WebKit/public/platform/mac/WebSandboxSupport.h"
-#elif defined(OS_ANDROID)
-#include "third_party/WebKit/public/platform/android/WebSandboxSupport.h"
-#elif defined(OS_POSIX)
-#include "content/common/child_process_sandbox_support_impl_linux.h"
-#include "third_party/WebKit/public/platform/linux/WebFallbackFont.h"
-#include "third_party/WebKit/public/platform/linux/WebSandboxSupport.h"
-#include "third_party/icu/source/common/unicode/utf16.h"
-#endif
-
-using blink::WebSandboxSupport;
-using blink::WebString;
-using blink::WebUChar;
-using blink::WebUChar32;
-
-typedef struct CGFont* CGFontRef;
-
-namespace content {
-
-class PpapiWebKitPlatformSupportImpl::SandboxSupport
- : public WebSandboxSupport {
- public:
- virtual ~SandboxSupport() {}
-
-#if defined(OS_WIN)
- virtual bool ensureFontLoaded(HFONT);
-#elif defined(OS_MACOSX)
- virtual bool loadFont(
- NSFont* srcFont, CGFontRef* out, uint32_t* fontID);
-#elif defined(OS_ANDROID)
- // Empty class.
-#elif defined(OS_POSIX)
- SandboxSupport();
- virtual void getFallbackFontForCharacter(
- WebUChar32 character,
- const char* preferred_locale,
- blink::WebFallbackFont* fallbackFont);
- virtual void getRenderStyleForStrike(
- const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out);
-
- private:
- // WebKit likes to ask us for the correct font family to use for a set of
- // unicode code points. It needs this information frequently so we cache it
- // here.
- std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
- // For debugging crbug.com/312965
- base::PlatformThreadId creation_thread_;
-#endif
-};
-
-#if defined(OS_WIN)
-
-bool PpapiWebKitPlatformSupportImpl::SandboxSupport::ensureFontLoaded(
- HFONT font) {
- LOGFONT logfont;
- GetObject(font, sizeof(LOGFONT), &logfont);
-
- // Use the proxy sender rather than going directly to the ChildThread since
- // the proxy browser sender will properly unlock during sync messages.
- return ppapi::proxy::PluginGlobals::Get()->GetBrowserSender()->Send(
- new ChildProcessHostMsg_PreCacheFont(logfont));
-}
-
-#elif defined(OS_MACOSX)
-
-bool PpapiWebKitPlatformSupportImpl::SandboxSupport::loadFont(
- NSFont* src_font,
- CGFontRef* out,
- uint32_t* font_id) {
- // TODO(brettw) this should do the something similar to what
- // RendererWebKitClientImpl does and request that the browser load the font.
- // Note: need to unlock the proxy lock like ensureFontLoaded does.
- NOTIMPLEMENTED();
- return false;
-}
-
-#elif defined(OS_ANDROID)
-
-// Empty class.
-
-#elif defined(OS_POSIX)
-
-PpapiWebKitPlatformSupportImpl::SandboxSupport::SandboxSupport()
- : creation_thread_(base::PlatformThread::CurrentId()) {
-}
-
-void
-PpapiWebKitPlatformSupportImpl::SandboxSupport::getFallbackFontForCharacter(
- WebUChar32 character,
- const char* preferred_locale,
- blink::WebFallbackFont* fallbackFont) {
- ppapi::ProxyLock::AssertAcquired();
- // For debugging crbug.com/312965
- CHECK_EQ(creation_thread_, base::PlatformThread::CurrentId());
- const std::map<int32_t, blink::WebFallbackFont>::const_iterator iter =
- unicode_font_families_.find(character);
- if (iter != unicode_font_families_.end()) {
- fallbackFont->name = iter->second.name;
- fallbackFont->filename = iter->second.filename;
- fallbackFont->ttcIndex = iter->second.ttcIndex;
- fallbackFont->isBold = iter->second.isBold;
- fallbackFont->isItalic = iter->second.isItalic;
- return;
- }
-
- GetFallbackFontForCharacter(character, preferred_locale, fallbackFont);
- unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
-}
-
-void PpapiWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike(
- const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out) {
- GetRenderStyleForStrike(family, sizeAndStyle, out);
-}
-
-#endif
-
-PpapiWebKitPlatformSupportImpl::PpapiWebKitPlatformSupportImpl()
- : sandbox_support_(new PpapiWebKitPlatformSupportImpl::SandboxSupport()) {
-}
-
-PpapiWebKitPlatformSupportImpl::~PpapiWebKitPlatformSupportImpl() {
-}
-
-void PpapiWebKitPlatformSupportImpl::Shutdown() {
- // SandboxSupport contains a map of WebFontFamily objects, which hold
- // WebCStrings, which become invalidated when blink is shut down. Hence, we
- // need to clear that map now, just before blink::shutdown() is called.
- sandbox_support_.reset();
-}
-
-blink::WebClipboard* PpapiWebKitPlatformSupportImpl::clipboard() {
- NOTREACHED();
- return NULL;
-}
-
-blink::WebMimeRegistry* PpapiWebKitPlatformSupportImpl::mimeRegistry() {
- NOTREACHED();
- return NULL;
-}
-
-blink::WebFileUtilities* PpapiWebKitPlatformSupportImpl::fileUtilities() {
- NOTREACHED();
- return NULL;
-}
-
-blink::WebSandboxSupport* PpapiWebKitPlatformSupportImpl::sandboxSupport() {
- return sandbox_support_.get();
-}
-
-bool PpapiWebKitPlatformSupportImpl::sandboxEnabled() {
- return true; // Assume PPAPI is always sandboxed.
-}
-
-unsigned long long PpapiWebKitPlatformSupportImpl::visitedLinkHash(
- const char* canonical_url,
- size_t length) {
- NOTREACHED();
- return 0;
-}
-
-bool PpapiWebKitPlatformSupportImpl::isLinkVisited(
- unsigned long long link_hash) {
- NOTREACHED();
- return false;
-}
-
-void PpapiWebKitPlatformSupportImpl::createMessageChannel(
- blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2) {
- NOTREACHED();
- *channel1 = NULL;
- *channel2 = NULL;
-}
-
-void PpapiWebKitPlatformSupportImpl::setCookies(
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
- const blink::WebString& value) {
- NOTREACHED();
-}
-
-blink::WebString PpapiWebKitPlatformSupportImpl::cookies(
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies) {
- NOTREACHED();
- return blink::WebString();
-}
-
-blink::WebString PpapiWebKitPlatformSupportImpl::defaultLocale() {
- NOTREACHED();
- return blink::WebString();
-}
-
-blink::WebThemeEngine* PpapiWebKitPlatformSupportImpl::themeEngine() {
- NOTREACHED();
- return NULL;
-}
-
-blink::WebURLLoader* PpapiWebKitPlatformSupportImpl::createURLLoader() {
- NOTREACHED();
- return NULL;
-}
-
-blink::WebSocketStreamHandle*
- PpapiWebKitPlatformSupportImpl::createSocketStreamHandle() {
- NOTREACHED();
- return NULL;
-}
-
-void PpapiWebKitPlatformSupportImpl::getPluginList(bool refresh,
- blink::WebPluginListBuilder* builder) {
- NOTREACHED();
-}
-
-blink::WebData PpapiWebKitPlatformSupportImpl::loadResource(const char* name) {
- NOTREACHED();
- return blink::WebData();
-}
-
-blink::WebStorageNamespace*
-PpapiWebKitPlatformSupportImpl::createLocalStorageNamespace() {
- NOTREACHED();
- return 0;
-}
-
-void PpapiWebKitPlatformSupportImpl::dispatchStorageEvent(
- const blink::WebString& key, const blink::WebString& old_value,
- const blink::WebString& new_value, const blink::WebString& origin,
- const blink::WebURL& url, bool is_local_storage) {
- NOTREACHED();
-}
-
-int PpapiWebKitPlatformSupportImpl::databaseDeleteFile(
- const blink::WebString& vfs_file_name, bool sync_dir) {
- NOTREACHED();
- return 0;
-}
-
-} // namespace content
diff --git a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h b/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
deleted file mode 100644
index 3361304024c..00000000000
--- a/chromium/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_PPAPI_PLUGIN_PPAPI_WEBKITPLATFORMSUPPORT_IMPL_H_
-#define CONTENT_PPAPI_PLUGIN_PPAPI_WEBKITPLATFORMSUPPORT_IMPL_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/child/blink_platform_impl.h"
-
-namespace content {
-
-class PpapiWebKitPlatformSupportImpl : public BlinkPlatformImpl {
- public:
- PpapiWebKitPlatformSupportImpl();
- virtual ~PpapiWebKitPlatformSupportImpl();
-
- // Shutdown must be called just prior to shutting down blink.
- void Shutdown();
-
- // WebKitPlatformSupport methods:
- virtual blink::WebClipboard* clipboard();
- virtual blink::WebMimeRegistry* mimeRegistry();
- virtual blink::WebFileUtilities* fileUtilities();
- virtual blink::WebSandboxSupport* sandboxSupport();
- virtual bool sandboxEnabled();
- virtual unsigned long long visitedLinkHash(const char* canonicalURL,
- size_t length);
- virtual bool isLinkVisited(unsigned long long linkHash);
- virtual void createMessageChannel(blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2);
- virtual void setCookies(const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
- const blink::WebString& value);
- virtual blink::WebString cookies(
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies);
- virtual blink::WebString defaultLocale();
- virtual blink::WebThemeEngine* themeEngine();
- virtual blink::WebURLLoader* createURLLoader();
- virtual blink::WebSocketStreamHandle* createSocketStreamHandle();
- virtual void getPluginList(bool refresh, blink::WebPluginListBuilder*);
- virtual blink::WebData loadResource(const char* name);
- virtual blink::WebStorageNamespace* createLocalStorageNamespace();
- virtual void dispatchStorageEvent(const blink::WebString& key,
- const blink::WebString& oldValue, const blink::WebString& newValue,
- const blink::WebString& origin, const blink::WebURL& url,
- bool isLocalStorage);
- virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
- bool sync_dir);
-
- private:
- class SandboxSupport;
- scoped_ptr<SandboxSupport> sandbox_support_;
-
- DISALLOW_COPY_AND_ASSIGN(PpapiWebKitPlatformSupportImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_PPAPI_PLUGIN_PPAPI_WEBKITPLATFORMSUPPORT_IMPL_H_
diff --git a/chromium/content/public/OWNERS b/chromium/content/public/OWNERS
new file mode 100644
index 00000000000..cac71c15af4
--- /dev/null
+++ b/chromium/content/public/OWNERS
@@ -0,0 +1,2 @@
+# DWrite specific changes
+per-file render_font_warmup_win.h=scottmg@chromium.org
diff --git a/chromium/content/public/README b/chromium/content/public/README
new file mode 100644
index 00000000000..ab094d04280
--- /dev/null
+++ b/chromium/content/public/README
@@ -0,0 +1,3 @@
+Content API design:
+http://www.chromium.org/developers/content-module/content-api
+
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
new file mode 100644
index 00000000000..94bb8780b17
--- /dev/null
+++ b/chromium/content/public/android/BUILD.gn
@@ -0,0 +1,178 @@
+# Copyright 2014 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.
+
+import("//build/config/android/config.gni")
+import("//build/config/android/rules.gni")
+
+content_jni_gypi_values = exec_script("//build/gypi_to_gn.py",
+ [ rebase_path("../../content_jni.gypi") ],
+ "scope",
+ [ "../../content_jni.gypi" ])
+
+android_aidl("common_aidl") {
+ interface_file = "java/src/org/chromium/content/common/common.aidl"
+ import_include = "java/src"
+ sources = [
+ "java/src/org/chromium/content/common/IChildProcessCallback.aidl",
+ "java/src/org/chromium/content/common/IChildProcessService.aidl",
+ ]
+}
+
+android_resources("content_java_resources") {
+ deps = [
+ ":content_strings_grd",
+ "//ui/android:ui_java_resources",
+ ]
+ custom_package = "org.chromium.content"
+ resource_dirs = [ "java/res" ]
+}
+
+android_library("content_java") {
+ deps = [
+ ":content_java_resources",
+ "//base:base_java",
+ "//media/base/android:media_java",
+ "//mojo/android:system_java",
+ "//mojo/public/java:bindings",
+ "//mojo/public/java:system",
+ "//net/android:net_java",
+ "//ui/android:ui_java",
+ "//third_party/jsr-305:jsr_305_javalib",
+
+#"//content:content_common",
+ ]
+
+ srcjar_deps = [
+ ":common_aidl",
+ ":content_public_android_java_enums_srcjar",
+ ]
+
+ DEPRECATED_java_in_dir = "java/src"
+ if (!is_android_webview_build) {
+ deps += [
+ "//third_party/eyesfree:eyesfree_java",
+ ]
+ }
+}
+
+java_strings_grd("content_strings_grd") {
+ grd_file = "java/strings/android_content_strings.grd"
+ outputs = [
+ "values-am/android_content_strings.xml",
+ "values-ar/android_content_strings.xml",
+ "values-bg/android_content_strings.xml",
+ "values-ca/android_content_strings.xml",
+ "values-cs/android_content_strings.xml",
+ "values-da/android_content_strings.xml",
+ "values-de/android_content_strings.xml",
+ "values-el/android_content_strings.xml",
+ "values/android_content_strings.xml",
+ "values-en-rGB/android_content_strings.xml",
+ "values-es/android_content_strings.xml",
+ "values-es-rUS/android_content_strings.xml",
+ "values-fa/android_content_strings.xml",
+ "values-fi/android_content_strings.xml",
+ "values-tl/android_content_strings.xml",
+ "values-fr/android_content_strings.xml",
+ "values-hi/android_content_strings.xml",
+ "values-hr/android_content_strings.xml",
+ "values-hu/android_content_strings.xml",
+ "values-in/android_content_strings.xml",
+ "values-it/android_content_strings.xml",
+ "values-iw/android_content_strings.xml",
+ "values-ja/android_content_strings.xml",
+ "values-ko/android_content_strings.xml",
+ "values-lt/android_content_strings.xml",
+ "values-lv/android_content_strings.xml",
+ "values-nl/android_content_strings.xml",
+ "values-nb/android_content_strings.xml",
+ "values-pl/android_content_strings.xml",
+ "values-pt-rBR/android_content_strings.xml",
+ "values-pt-rPT/android_content_strings.xml",
+ "values-ro/android_content_strings.xml",
+ "values-ru/android_content_strings.xml",
+ "values-sk/android_content_strings.xml",
+ "values-sl/android_content_strings.xml",
+ "values-sr/android_content_strings.xml",
+ "values-sv/android_content_strings.xml",
+ "values-sw/android_content_strings.xml",
+ "values-th/android_content_strings.xml",
+ "values-tr/android_content_strings.xml",
+ "values-uk/android_content_strings.xml",
+ "values-vi/android_content_strings.xml",
+ "values-zh-rCN/android_content_strings.xml",
+ "values-zh-rTW/android_content_strings.xml",
+ ]
+}
+
+java_cpp_enum("content_public_android_java_enums_srcjar") {
+ sources = [
+ "//content/browser/android/content_view_core_impl.cc",
+ "//content/browser/android/gesture_event_type.h",
+ "//content/browser/renderer_host/input/selection_event_type.h",
+ "//content/browser/gamepad/gamepad_standard_mappings.h",
+ "//content/public/common/result_codes.h",
+ "//content/public/common/screen_orientation_values.h",
+ "//content/public/common/speech_recognition_error.h",
+ "//content/public/common/top_controls_state.h",
+ ]
+ outputs = [
+ "org/chromium/content/browser/GestureEventType.java",
+ "org/chromium/content/browser/input/CanonicalAxisIndex.java",
+ "org/chromium/content/browser/input/CanonicalButtonIndex.java",
+ "org/chromium/content/browser/input/PopupItemType.java",
+ "org/chromium/content/browser/input/SelectionEventType.java",
+ "org/chromium/content_public/common/ResultCode.java",
+ "org/chromium/content_public/common/ScreenOrientationValues.java",
+ "org/chromium/content_public/common/SpeechRecognitionErrorCode.java",
+ "org/chromium/content_public/common/TopControlsState.java",
+ ]
+}
+
+generate_jar_jni("jar_jni") {
+ jni_package = "content"
+ classes = [
+ "java/util/HashSet.class",
+ "android/view/MotionEvent.class",
+ ]
+}
+
+generate_jni("content_jni_headers") {
+ sources = rebase_path(content_jni_gypi_values.sources, "", "../..")
+ jni_package = "content"
+}
+
+group("jni") {
+ deps = [
+ ":content_jni_headers",
+ ":jar_jni",
+ ]
+}
+
+android_library("content_javatests") {
+ testonly = true
+ deps = [
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//content/public/test/android:content_java_test_support",
+ "//content/shell/android:content_shell_java",
+ "//content/shell/android:content_shell_java_resources",
+ "//content/shell/android:content_shell_apk_java",
+ "//content/shell/android:content_shell_test_java",
+ "//media/base/android:media_java",
+ "//mojo/android:system_java",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces_java",
+ "//mojo/public/java:bindings",
+ "//mojo/public/java:system",
+ "//net/android:net_java",
+ "//net/android:net_java_test_support",
+ "//ui/android:ui_java",
+ ":content_java",
+ ]
+
+ DEPRECATED_java_in_dir = "javatests/src"
+}
+
+
+# TODO(GYP): content_icudata
diff --git a/chromium/content/public/android/DEPS b/chromium/content/public/android/DEPS
index 7ff666f8f82..01d0156151a 100644
--- a/chromium/content/public/android/DEPS
+++ b/chromium/content/public/android/DEPS
@@ -5,4 +5,6 @@ include_rules = [
"+content/public/test/android",
# ContentShellActivity is needed for running ContentView.
"+content/shell/android",
+ # Mojo is needed for Mojo service registry kept in the browser.
+ "+mojo/android",
]
diff --git a/chromium/content/public/android/OWNERS b/chromium/content/public/android/OWNERS
index 6d043f42934..1f0649b1740 100644
--- a/chromium/content/public/android/OWNERS
+++ b/chromium/content/public/android/OWNERS
@@ -1,5 +1,4 @@
benm@chromium.org
-bulach@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/public/app/BUILD.gn b/chromium/content/public/app/BUILD.gn
index 37d2847278c..ccb31698574 100644
--- a/chromium/content/public/app/BUILD.gn
+++ b/chromium/content/public/app/BUILD.gn
@@ -2,24 +2,133 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("app") {
- sources = [
- "android_library_loader_hooks.h",
- "content_main.h",
- "content_main_delegate.cc",
- "content_main_delegate.h",
- "content_main_runner.h",
- "startup_helper_win.h",
- ]
-
- configs += [ "//content:content_implementation" ]
-
- deps = [
- "//base",
- "//base:i18n",
- "//content:export",
- "//content/public/plugin",
- "//content/public/renderer",
- "//content/public/utility",
- ]
+# App different than the regular content subcomponents (see comments in
+# //content/BUILD.gn) because it has to support the browser/child process split
+# (the "both" target include both browser and child process files and is used
+# for testing).
+#
+# In non-component mode, browser, child, and both all follow the same structure:
+# foo ->
+# //content/public/app:child (group) ->
+# //content/public/app:child_sources (source set) ->
+# //content/app:child (source set)
+
+# In component mode, content is linked as one big turd so there is only one
+# app target containing sources ("both") and the other ones forward to it:
+# foo ->
+# //content/public/app:child (group; "browser" and "both" ones look the same)
+# //content (shared library) ->
+# //content/public/app:both_sources (source set)
+
+public_app_shared_sources = [
+ "android_library_loader_hooks.h",
+ "content_main.h",
+ "content_main_delegate.cc",
+ "content_main_delegate.h",
+ "content_main_runner.h",
+ "startup_helper_win.h",
+]
+
+public_app_shared_deps = [
+ "//base",
+ "//base:i18n",
+ "//content:export",
+ "//content/public/common:common_sources",
+]
+
+if (is_component_build) {
+
+ source_set("both_sources") {
+ # Only the main content shared library can pull this in.
+ visibility = [ "//content:content" ]
+
+ sources = public_app_shared_sources
+
+ configs += [ "//content:content_implementation" ]
+
+ deps = public_app_shared_deps + [
+ "//content/app:both",
+ "//content/public/browser:browser_sources",
+ ]
+ }
+
+ # These all just forward to content, which in turn depends on "both_sources".
+ group("browser") {
+ deps = [ "//content" ]
+ }
+ group("child") {
+ deps = [ "//content" ]
+ }
+ group("both") {
+ deps = [ "//content" ]
+ }
+
+} else {
+
+ # content_main_delegate.cc conditionally includes content_browser_client.h
+ # from //content/public/browser when it's not the child build. However,
+ # the header checker doesn't know this doesn't apply and throws an error.
+ # So all of these targets set check_includes = false.
+ #
+ # TODO(brettw) either teach the header checker to understand simple
+ # ifdefs or split the file apart so we can enable header checking here.
+ # Furthermore, since this file exists in more than one target, they all
+ # have to opt-out of header checking (a file is checked once for all
+ # targets using a source file).
+
+ source_set("both") {
+ check_includes = false # See comment above.
+
+ sources = public_app_shared_sources
+ configs += [ "//content:content_implementation" ]
+ deps = public_app_shared_deps + [
+ "//content/app:both",
+ "//content/public/browser",
+ "//content/public/common",
+ ]
+ }
+
+ # TODO(GYP) enable chrome_multiple_dll support
+ is_chrome_multiple_dll = false
+
+ if (is_chrome_multiple_dll) {
+ source_set("browser") {
+ check_includes = false # See comment above.
+
+ sources = public_app_shared_sources
+
+ defines = [ "CHROME_MULTIPLE_DLL_BROWSER" ]
+ configs += [ "//content:content_implementation" ]
+
+ deps = public_app_shared_deps + [
+ "//content/app:browser",
+ "//content/public/browser",
+ "//content/public/common",
+ ]
+ }
+
+ source_set("child") {
+ check_includes = false # See comment above.
+
+ sources = public_app_shared_sources
+
+ defines = [ "CHROME_MULTIPLE_DLL_CHILD" ]
+ configs += [ "//content:content_implementation" ]
+
+ deps = public_app_shared_deps + [
+ "//content/app:child",
+ "//content/public/common",
+ ]
+ }
+ } else {
+ # When the multi-DLL build is disabled, there is only one type of the
+ # "app" target, and "browser" and "child" are the same as "both".
+ group("browser") {
+ deps = [ ":both" ]
+ }
+ group("child") {
+ deps = [ ":both" ]
+ }
+ }
+
}
diff --git a/chromium/content/public/app/android_library_loader_hooks.h b/chromium/content/public/app/android_library_loader_hooks.h
index b815f080705..f6779c6a149 100644
--- a/chromium/content/public/app/android_library_loader_hooks.h
+++ b/chromium/content/public/app/android_library_loader_hooks.h
@@ -21,8 +21,7 @@ CONTENT_EXPORT bool EnsureJniRegistered(JNIEnv* env);
// This is designed to be used as a hook function to be passed to
// base::android::SetLibraryLoadedHook
CONTENT_EXPORT bool LibraryLoaded(JNIEnv* env,
- jclass clazz,
- jobjectArray init_command_line);
+ jclass clazz);
} // namespace content
diff --git a/chromium/content/public/app/content_main_delegate.cc b/chromium/content/public/app/content_main_delegate.cc
index 433300cfd8b..e86f6c8c3e1 100644
--- a/chromium/content/public/app/content_main_delegate.cc
+++ b/chromium/content/public/app/content_main_delegate.cc
@@ -4,7 +4,9 @@
#include "content/public/app/content_main_delegate.h"
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
#include "content/public/browser/content_browser_client.h"
+#endif
#if !defined(OS_IOS)
#include "content/public/plugin/content_plugin_client.h"
@@ -48,6 +50,10 @@ void ContentMainDelegate::ZygoteStarting(
#endif
+bool ContentMainDelegate::ShouldEnableTerminationOnHeapCorruption() {
+ return true;
+}
+
ContentBrowserClient* ContentMainDelegate::CreateContentBrowserClient() {
#if defined(CHROME_MULTIPLE_DLL_CHILD)
return NULL;
diff --git a/chromium/content/public/app/content_main_delegate.h b/chromium/content/public/app/content_main_delegate.h
index 6191d7815e6..6273950f2ab 100644
--- a/chromium/content/public/app/content_main_delegate.h
+++ b/chromium/content/public/app/content_main_delegate.h
@@ -76,6 +76,13 @@ class CONTENT_EXPORT ContentMainDelegate {
virtual void ZygoteForked() {}
#endif // OS_MACOSX
+ // Allows the embedder to disable termination on heap corruption.
+ // This is being used to measure the impact of this feature on crash reports.
+ // Termination on heap corruption is enabled by default.
+ // TODO(erikwright): Remove this by September 2014 when experimentation is
+ // complete.
+ virtual bool ShouldEnableTerminationOnHeapCorruption();
+
protected:
friend class ContentClientInitializer;
diff --git a/chromium/content/public/browser/BUILD.gn b/chromium/content/public/browser/BUILD.gn
index 05cb6f19096..39bddc485ca 100644
--- a/chromium/content/public/browser/BUILD.gn
+++ b/chromium/content/public/browser/BUILD.gn
@@ -5,7 +5,18 @@
import("//content/browser/browser.gni")
import("//build/config/ui.gni")
-source_set("browser") {
+# See //content/BUILD.gn for how this works.
+group("browser") {
+ if (is_component_build) {
+ public_deps = [ "//content" ]
+ } else {
+ public_deps = [ ":browser_sources" ]
+ }
+}
+
+source_set("browser_sources") {
+ visibility = [ "//content/*" ]
+
if (is_ios) {
# iOS doesn't get the normal file list and only takes these whitelisted
# files.
@@ -29,11 +40,22 @@ source_set("browser") {
configs += [ "//content:content_implementation" ]
+ public_deps = [
+ # We expose skia headers in the public API.
+ "//skia",
+ ]
deps = [
"//content/browser",
- "//skia",
+ "//content/public/common:common_sources",
+ "//net",
+ "//ui/accessibility",
+ "//ui/base",
+ "//ui/events",
]
- # We expose skia headers in the public API.
- forward_dependent_configs_from = [ "//skia" ]
+ allow_circular_includes_from = [
+ # This target is a pair with content/browser. They always go together and
+ # include headers from each other.
+ "//content/browser",
+ ]
}
diff --git a/chromium/content/public/browser/android/OWNERS b/chromium/content/public/browser/android/OWNERS
index 1df84db9b51..ade1eb825b7 100644
--- a/chromium/content/public/browser/android/OWNERS
+++ b/chromium/content/public/browser/android/OWNERS
@@ -1,4 +1,3 @@
-bulach@chromium.org
mkosiba@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/public/browser/android/compositor.h b/chromium/content/public/browser/android/compositor.h
index a8f734cf7d5..25a61c88aec 100644
--- a/chromium/content/public/browser/android/compositor.h
+++ b/chromium/content/public/browser/android/compositor.h
@@ -55,10 +55,6 @@ class CONTENT_EXPORT Compositor {
// having been made visible again.
virtual void SetVisible(bool visible) = 0;
- // Set the output surface handle which the compositor renders into.
- // DEPRECATED: Use SetSurface() which takes a Java Surface object.
- virtual void SetWindowSurface(ANativeWindow* window) = 0;
-
// Set the output surface which the compositor renders into.
virtual void SetSurface(jobject surface) = 0;
diff --git a/chromium/content/public/browser/android/content_view_core.h b/chromium/content/public/browser/android/content_view_core.h
index cf620c0136e..2afd50efe8b 100644
--- a/chromium/content/public/browser/android/content_view_core.h
+++ b/chromium/content/public/browser/android/content_view_core.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_controller.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/gfx/rect.h"
class SkBitmap;
@@ -47,7 +48,6 @@ class CONTENT_EXPORT ContentViewCore {
virtual ui::ViewAndroid* GetViewAndroid() const = 0;
virtual ui::WindowAndroid* GetWindowAndroid() const = 0;
virtual scoped_refptr<cc::Layer> GetLayer() const = 0;
- virtual void LoadUrl(NavigationController::LoadURLParams& params) = 0;
virtual void ShowPastePopup(int x, int y) = 0;
// Request a scaled content readback. The result is passed through the
@@ -55,11 +55,10 @@ class CONTENT_EXPORT ContentViewCore {
// success or not. The content is passed through the SkBitmap parameter.
virtual void GetScaledContentBitmap(
float scale,
- jobject bitmap_config,
+ SkColorType color_type,
gfx::Rect src_rect,
const base::Callback<void(bool, const SkBitmap&)>& result_callback) = 0;
virtual float GetDpiScale() const = 0;
- virtual void PauseVideo() = 0;
virtual void PauseOrResumeGeolocation(bool should_pause) = 0;
// Observer callback for frame metadata updates.
diff --git a/chromium/content/public/browser/android/devtools_auth.h b/chromium/content/public/browser/android/devtools_auth.h
index 700892c034a..857a1a14137 100644
--- a/chromium/content/public/browser/android/devtools_auth.h
+++ b/chromium/content/public/browser/android/devtools_auth.h
@@ -6,14 +6,14 @@
#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_AUTH_ANDROID_H_
#include "content/common/content_export.h"
-
-#include <pwd.h>
+#include "net/socket/unix_domain_server_socket_posix.h"
namespace content {
-// Returns true if the given user/group pair is authorized to connect to the
-// devtools server, false if not.
-CONTENT_EXPORT bool CanUserConnectToDevTools(uid_t uid, gid_t gid);
+// Returns true if the given peer identified by the credentials is authorized
+// to connect to the devtools server, false if not.
+CONTENT_EXPORT bool CanUserConnectToDevTools(
+ const net::UnixDomainServerSocket::Credentials& credentials);
} // namespace content
diff --git a/chromium/content/public/browser/android/synchronous_compositor.cc b/chromium/content/public/browser/android/synchronous_compositor.cc
deleted file mode 100644
index 25c4dc4cf3c..00000000000
--- a/chromium/content/public/browser/android/synchronous_compositor.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 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 "content/public/browser/android/synchronous_compositor.h"
-
-namespace content {
-
-SynchronousCompositorMemoryPolicy::SynchronousCompositorMemoryPolicy()
- : bytes_limit(0), num_resources_limit(0) {}
-
-bool SynchronousCompositorMemoryPolicy::operator==(
- const SynchronousCompositorMemoryPolicy& other) const {
- return bytes_limit == other.bytes_limit &&
- num_resources_limit == other.num_resources_limit;
-}
-
-bool SynchronousCompositorMemoryPolicy::operator!=(
- const SynchronousCompositorMemoryPolicy& other) const {
- return !(*this == other);
-}
-
-} // namespace content
diff --git a/chromium/content/public/browser/android/synchronous_compositor.h b/chromium/content/public/browser/android/synchronous_compositor.h
index 62485f155f8..69000e56639 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.h
+++ b/chromium/content/public/browser/android/synchronous_compositor.h
@@ -31,19 +31,6 @@ namespace content {
class SynchronousCompositorClient;
class WebContents;
-struct CONTENT_EXPORT SynchronousCompositorMemoryPolicy {
- // Memory limit for rendering and pre-rendering.
- size_t bytes_limit;
-
- // Limit of number of GL resources used for rendering and pre-rendering.
- size_t num_resources_limit;
-
- SynchronousCompositorMemoryPolicy();
-
- bool operator==(const SynchronousCompositorMemoryPolicy& other) const;
- bool operator!=(const SynchronousCompositorMemoryPolicy& other) const;
-};
-
// Interface for embedders that wish to direct compositing operations
// synchronously under their own control. Only meaningful when the
// kEnableSyncrhonousRendererCompositor flag is specified.
@@ -80,18 +67,15 @@ class CONTENT_EXPORT SynchronousCompositor {
// releases all hardware resources.
virtual void ReleaseHwDraw() = 0;
- // Get the share context of the compositor. The returned context is owned
- // by the compositor and is only valid between InitializeHwDraw and
- // ReleaseHwDraw.
- virtual gpu::GLInProcessContext* GetShareContext() = 0;
-
// "On demand" hardware draw. The content is first clipped to |damage_area|,
// then transformed through |transform|, and finally clipped to |view_size|.
virtual scoped_ptr<cc::CompositorFrame> DemandDrawHw(
gfx::Size surface_size,
const gfx::Transform& transform,
gfx::Rect viewport,
- gfx::Rect clip) = 0;
+ gfx::Rect clip,
+ gfx::Rect viewport_rect_for_tile_priority,
+ const gfx::Transform& transform_for_tile_priority) = 0;
// For delegated rendering, return resources from parent compositor to this.
// Note that all resources must be returned before ReleaseHwDraw.
@@ -102,8 +86,7 @@ class CONTENT_EXPORT SynchronousCompositor {
virtual bool DemandDrawSw(SkCanvas* canvas) = 0;
// Set the memory limit policy of this compositor.
- virtual void SetMemoryPolicy(
- const SynchronousCompositorMemoryPolicy& policy) = 0;
+ virtual void SetMemoryPolicy(size_t bytes_limit) = 0;
// Should be called by the embedder after the embedder had modified the
// scroll offset of the root layer (as returned by
diff --git a/chromium/content/public/browser/android/ui_resource_provider.h b/chromium/content/public/browser/android/ui_resource_provider.h
index 38511e13436..c764d1e6360 100644
--- a/chromium/content/public/browser/android/ui_resource_provider.h
+++ b/chromium/content/public/browser/android/ui_resource_provider.h
@@ -20,6 +20,8 @@ class CONTENT_EXPORT UIResourceProvider {
UIResourceClientAndroid* client) = 0;
virtual void DeleteUIResource(cc::UIResourceId resource_id) = 0;
+
+ virtual bool SupportsETC1NonPowerOfTwo() const = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/appcache_service.h b/chromium/content/public/browser/appcache_service.h
new file mode 100644
index 00000000000..7742abd3f3f
--- /dev/null
+++ b/chromium/content/public/browser/appcache_service.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2012 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 CONTENT_PUBLIC_BROWSER_APPCACHE_SERVICE_H_
+#define CONTENT_PUBLIC_BROWSER_APPCACHE_SERVICE_H_
+
+#include <map>
+#include <set>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/common/appcache_info.h"
+#include "net/base/completion_callback.h"
+
+namespace content {
+
+class AppCacheStorage;
+
+// Refcounted container to avoid copying the collection in callbacks.
+struct CONTENT_EXPORT AppCacheInfoCollection
+ : public base::RefCountedThreadSafe<AppCacheInfoCollection> {
+ AppCacheInfoCollection();
+
+ std::map<GURL, AppCacheInfoVector> infos_by_origin;
+
+ private:
+ friend class base::RefCountedThreadSafe<AppCacheInfoCollection>;
+ virtual ~AppCacheInfoCollection();
+};
+
+// Exposes a limited interface to the AppCacheService.
+// Call these methods only on the IO thread.
+class CONTENT_EXPORT AppCacheService {
+ public:
+ // Determines if a request for 'url' can be satisfied while offline.
+ // This method always completes asynchronously.
+ virtual void CanHandleMainResourceOffline(const GURL& url,
+ const GURL& first_party,
+ const net::CompletionCallback&
+ callback) = 0;
+
+ // Populates 'collection' with info about all of the appcaches stored
+ // within the service, 'callback' is invoked upon completion. The service
+ // acquires a reference to the 'collection' until until completion.
+ // This method always completes asynchronously.
+ virtual void GetAllAppCacheInfo(AppCacheInfoCollection* collection,
+ const net::CompletionCallback& callback) = 0;
+
+ // Deletes the group identified by 'manifest_url', 'callback' is
+ // invoked upon completion. Upon completion, the cache group and
+ // any resources within the group are no longer loadable and all
+ // subresource loads for pages associated with a deleted group
+ // will fail. This method always completes asynchronously.
+ virtual void DeleteAppCacheGroup(const GURL& manifest_url,
+ const net::CompletionCallback& callback) = 0;
+
+ protected:
+ virtual ~AppCacheService() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_APPCACHE_SERVICE_H_
diff --git a/chromium/content/public/browser/ax_event_notification_details.cc b/chromium/content/public/browser/ax_event_notification_details.cc
index 87ff4df41ee..dfebb87c759 100644
--- a/chromium/content/public/browser/ax_event_notification_details.cc
+++ b/chromium/content/public/browser/ax_event_notification_details.cc
@@ -7,16 +7,19 @@
namespace content {
AXEventNotificationDetails::AXEventNotificationDetails(
+ int node_id_to_clear,
const std::vector<ui::AXNodeData>& nodes,
ui::AXEvent event_type,
int id,
int process_id,
int routing_id)
- : nodes(nodes),
+ : node_id_to_clear(node_id_to_clear),
+ nodes(nodes),
event_type(event_type),
id(id),
process_id(process_id),
- routing_id(routing_id) {}
+ routing_id(routing_id) {
+}
AXEventNotificationDetails::~AXEventNotificationDetails() {}
diff --git a/chromium/content/public/browser/ax_event_notification_details.h b/chromium/content/public/browser/ax_event_notification_details.h
index 3065e59d52f..0f4d8dc2515 100644
--- a/chromium/content/public/browser/ax_event_notification_details.h
+++ b/chromium/content/public/browser/ax_event_notification_details.h
@@ -17,7 +17,8 @@ namespace content {
// |WebContentsObserver::AccessibilityEventReceived| method.
struct CONTENT_EXPORT AXEventNotificationDetails {
public:
- AXEventNotificationDetails(const std::vector<ui::AXNodeData>& nodes,
+ AXEventNotificationDetails(int node_id_to_clear,
+ const std::vector<ui::AXNodeData>& nodes,
ui::AXEvent event_type,
int id,
int process_id,
@@ -25,6 +26,7 @@ struct CONTENT_EXPORT AXEventNotificationDetails {
~AXEventNotificationDetails();
+ int node_id_to_clear;
std::vector<ui::AXNodeData> nodes;
ui::AXEvent event_type;
int id;
diff --git a/chromium/content/public/browser/browser_child_process_host.h b/chromium/content/public/browser/browser_child_process_host.h
index 078eb860cf0..b243678ce54 100644
--- a/chromium/content/public/browser/browser_child_process_host.h
+++ b/chromium/content/public/browser/browser_child_process_host.h
@@ -38,7 +38,7 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
int process_type,
BrowserChildProcessHostDelegate* delegate);
- virtual ~BrowserChildProcessHost() {}
+ ~BrowserChildProcessHost() override {}
// Derived classes call this to launch the child process asynchronously.
// Takes ownership of |cmd_line| and |delegate|.
diff --git a/chromium/content/public/browser/browser_child_process_host_delegate.h b/chromium/content/public/browser/browser_child_process_host_delegate.h
index 25ff00a4cb4..b6568af1f20 100644
--- a/chromium/content/public/browser/browser_child_process_host_delegate.h
+++ b/chromium/content/public/browser/browser_child_process_host_delegate.h
@@ -13,7 +13,7 @@ namespace content {
// Interface that all users of BrowserChildProcessHost need to provide.
class CONTENT_EXPORT BrowserChildProcessHostDelegate : public IPC::Listener {
public:
- virtual ~BrowserChildProcessHostDelegate() {}
+ ~BrowserChildProcessHostDelegate() override {}
// Delegates return true if it's ok to shut down the child process (which is
// the default return value). The exception is if the host is in the middle of
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index 1c09777f42b..fec68dc320f 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
+#include "content/public/common/push_messaging_status.h"
class GURL;
@@ -17,7 +18,7 @@ namespace base {
class FilePath;
}
-namespace fileapi {
+namespace storage {
class ExternalMountPoints;
}
@@ -25,7 +26,7 @@ namespace net {
class URLRequestContextGetter;
}
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
}
@@ -40,6 +41,7 @@ class PushMessagingService;
class ResourceContext;
class SiteInstance;
class StoragePartition;
+class SSLHostStateDelegate;
// This class holds the context needed for a browsing session.
// It lives on the UI thread. All these methods must only be called on the UI
@@ -51,7 +53,7 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// Returns BrowserContext specific external mount points. It may return NULL
// if the context doesn't have any BrowserContext specific external mount
// points. Currenty, non-NULL value is returned only on ChromeOS.
- static fileapi::ExternalMountPoints* GetMountPoints(BrowserContext* context);
+ static storage::ExternalMountPoints* GetMountPoints(BrowserContext* context);
static content::StoragePartition* GetStoragePartition(
BrowserContext* browser_context, SiteInstance* site_instance);
@@ -85,6 +87,17 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
const char* data, size_t length,
const BlobCallback& callback);
+ // Delivers a push message with |data| to the Service Worker identified by
+ // |origin| and |service_worker_registration_id|.
+ static void DeliverPushMessage(
+ BrowserContext* browser_context,
+ const GURL& origin,
+ int64 service_worker_registration_id,
+ const std::string& data,
+ const base::Callback<void(PushDeliveryStatus)>& callback);
+
+ static void NotifyWillBeDestroyed(BrowserContext* browser_context);
+
// Ensures that the corresponding ResourceContext is initialized. Normally the
// BrowserContext initializs the corresponding getters when its objects are
// created, but if the embedder wants to pass the ResourceContext to another
@@ -96,7 +109,7 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// across the next restart.
static void SaveSessionState(BrowserContext* browser_context);
- virtual ~BrowserContext();
+ ~BrowserContext() override;
// Returns the path of the directory where this context's data is stored.
virtual base::FilePath GetPath() const = 0;
@@ -143,27 +156,18 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
virtual BrowserPluginGuestManager* GetGuestManager() = 0;
// Returns a special storage policy implementation, or NULL.
- virtual quota::SpecialStoragePolicy* GetSpecialStoragePolicy() = 0;
+ virtual storage::SpecialStoragePolicy* GetSpecialStoragePolicy() = 0;
// Returns a push messaging service. The embedder owns the service, and is
// responsible for ensuring that it outlives RenderProcessHost. It's valid to
// return NULL.
virtual PushMessagingService* GetPushMessagingService() = 0;
-};
-} // namespace content
-
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
-
-template<>
-struct hash<content::BrowserContext*> {
- std::size_t operator()(content::BrowserContext* const& p) const {
- return reinterpret_cast<std::size_t>(p);
- }
+ // Returns the SSL host state decisions for this context. The context may
+ // return NULL, implementing the default exception storage strategy.
+ virtual SSLHostStateDelegate* GetSSLHostStateDelegate() = 0;
};
-} // namespace BASE_HASH_NAMESPACE
-#endif
+} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_BROWSER_CONTEXT_H_
diff --git a/chromium/content/public/browser/browser_message_filter.cc b/chromium/content/public/browser/browser_message_filter.cc
index 6b3432204b9..e4cf09407c7 100644
--- a/chromium/content/public/browser/browser_message_filter.cc
+++ b/chromium/content/public/browser/browser_message_filter.cc
@@ -27,29 +27,27 @@ class BrowserMessageFilter::Internal : public IPC::MessageFilter {
explicit Internal(BrowserMessageFilter* filter) : filter_(filter) {}
private:
- virtual ~Internal() {}
+ ~Internal() override {}
// IPC::MessageFilter implementation:
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
+ void OnFilterAdded(IPC::Sender* sender) override {
filter_->sender_ = sender;
filter_->OnFilterAdded(sender);
}
- virtual void OnFilterRemoved() OVERRIDE {
- filter_->OnFilterRemoved();
- }
+ void OnFilterRemoved() override { filter_->OnFilterRemoved(); }
- virtual void OnChannelClosing() OVERRIDE {
+ void OnChannelClosing() override {
filter_->sender_ = NULL;
filter_->OnChannelClosing();
}
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
+ void OnChannelConnected(int32 peer_pid) override {
filter_->peer_pid_ = peer_pid;
filter_->OnChannelConnected(peer_pid);
}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
BrowserThread::ID thread = BrowserThread::IO;
filter_->OverrideThreadForMessage(message, &thread);
@@ -67,7 +65,7 @@ class BrowserMessageFilter::Internal : public IPC::MessageFilter {
}
if (thread == BrowserThread::UI &&
- !BrowserMessageFilter::CheckCanDispatchOnUI(message, filter_)) {
+ !BrowserMessageFilter::CheckCanDispatchOnUI(message, filter_.get())) {
return true;
}
@@ -78,8 +76,8 @@ class BrowserMessageFilter::Internal : public IPC::MessageFilter {
return true;
}
- virtual bool GetSupportedMessageClasses(
- std::vector<uint32>* supported_message_classes) const OVERRIDE {
+ bool GetSupportedMessageClasses(
+ std::vector<uint32>* supported_message_classes) const override {
supported_message_classes->assign(
filter_->message_classes_to_filter().begin(),
filter_->message_classes_to_filter().end());
diff --git a/chromium/content/public/browser/browser_message_filter.h b/chromium/content/public/browser/browser_message_filter.h
index 81f06a90343..5ff787de788 100644
--- a/chromium/content/public/browser/browser_message_filter.h
+++ b/chromium/content/public/browser/browser_message_filter.h
@@ -51,7 +51,7 @@ class CONTENT_EXPORT BrowserMessageFilter
// IPC::Sender implementation. Can be called on any thread. Can't send sync
// messages (since we don't want to block the browser on any other process).
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
// If you want the given message to be dispatched to your OnMessageReceived on
// a different thread, there are two options, either
@@ -101,7 +101,7 @@ class CONTENT_EXPORT BrowserMessageFilter
}
protected:
- virtual ~BrowserMessageFilter();
+ ~BrowserMessageFilter() override;
private:
friend class base::RefCountedThreadSafe<BrowserMessageFilter,
diff --git a/chromium/content/public/browser/browser_plugin_guest_delegate.cc b/chromium/content/public/browser/browser_plugin_guest_delegate.cc
new file mode 100644
index 00000000000..d9a61ea24a3
--- /dev/null
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 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 "content/public/browser/browser_plugin_guest_delegate.h"
+
+namespace content {
+
+WebContents* BrowserPluginGuestDelegate::CreateNewGuestWindow(
+ const WebContents::CreateParams& create_params) {
+ return NULL;
+}
+
+bool BrowserPluginGuestDelegate::Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options,
+ bool is_full_page_plugin) {
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/browser_plugin_guest_delegate.h b/chromium/content/public/browser/browser_plugin_guest_delegate.h
index 7abd7371a25..90abc5ddfda 100644
--- a/chromium/content/public/browser/browser_plugin_guest_delegate.h
+++ b/chromium/content/public/browser/browser_plugin_guest_delegate.h
@@ -8,6 +8,7 @@
#include "base/callback_forward.h"
#include "base/process/kill.h"
#include "content/common/content_export.h"
+#include "content/public/browser/web_contents.h"
namespace base {
class DictionaryValue;
@@ -19,8 +20,6 @@ class Size;
namespace content {
-class WebContents;
-
// Objects implement this interface to get notified about changes in the guest
// WebContents and to provide necessary functionality.
class CONTENT_EXPORT BrowserPluginGuestDelegate {
@@ -28,16 +27,28 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
virtual ~BrowserPluginGuestDelegate() {}
// Notification that the embedder will begin attachment. This is called
- // prior to resuming resource loads.
+ // prior to resuming resource loads. |element_instance_id| uniquely identifies
+ // the element that will serve as a container for the guest.
virtual void WillAttach(content::WebContents* embedder_web_contents,
- const base::DictionaryValue& extra_params) {}
+ int element_instance_id) {}
+
+ virtual WebContents* CreateNewGuestWindow(
+ const WebContents::CreateParams& create_params);
+
+ // Notification that the embedder has completed attachment. The
+ // |guest_proxy_routing_id| is the routing ID for the RenderView in the
+ // embedder that will serve as a contentWindow proxy for the guest.
+ virtual void DidAttach(int guest_proxy_routing_id) {}
- // Notification that the embedder has completed attachment.
- virtual void DidAttach() {}
+ // Notification that the BrowserPlugin has resized.
+ virtual void ElementSizeChanged(const gfx::Size& old_size,
+ const gfx::Size& new_size) {}
- // Notifies that the content size of the guest has changed in autosize mode.
- virtual void SizeChanged(const gfx::Size& old_size,
- const gfx::Size& new_size) {}
+ // Notifies that the content size of the guest has changed.
+ // Note: In autosize mode, it si possible that the guest size may not match
+ // the element size.
+ virtual void GuestSizeChanged(const gfx::Size& old_size,
+ const gfx::Size& new_size) {}
// Asks the delegate if the given guest can lock the pointer.
// Invoking the |callback| synchronously is OK.
@@ -46,15 +57,18 @@ class CONTENT_EXPORT BrowserPluginGuestDelegate {
bool last_unlocked_by_target,
const base::Callback<void(bool)>& callback) {}
- // Requests that the delegate destroy itself along with its associated
- // WebContents.
- virtual void Destroy() {}
-
// Registers a |callback| with the delegate that the delegate would call when
// it is about to be destroyed.
typedef base::Callback<void()> DestructionCallback;
virtual void RegisterDestructionCallback(
const DestructionCallback& callback) {}
+
+ // Find the given |search_text| in the page. Returns true if the find request
+ // is handled by this browser plugin guest delegate.
+ virtual bool Find(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options,
+ bool is_full_page_plugin);
};
} // namespace content
diff --git a/chromium/content/public/browser/browser_plugin_guest_manager.cc b/chromium/content/public/browser/browser_plugin_guest_manager.cc
index abb0bb06e16..4ea181739c9 100644
--- a/chromium/content/public/browser/browser_plugin_guest_manager.cc
+++ b/chromium/content/public/browser/browser_plugin_guest_manager.cc
@@ -4,21 +4,14 @@
#include "content/public/browser/browser_plugin_guest_manager.h"
-#include "base/values.h"
-
namespace content {
-content::WebContents* BrowserPluginGuestManager::CreateGuest(
- SiteInstance* embedder_site_instance,
- int instance_id,
- scoped_ptr<base::DictionaryValue> extra_params) {
+WebContents* BrowserPluginGuestManager::GetGuestByInstanceID(
+ WebContents* embedder_web_contents,
+ int browser_plugin_instance_id) {
return NULL;
}
-int BrowserPluginGuestManager::GetNextInstanceID() {
- return 0;
-}
-
bool BrowserPluginGuestManager::ForEachGuest(
WebContents* embedder_web_contents,
const GuestCallback& callback) {
diff --git a/chromium/content/public/browser/browser_plugin_guest_manager.h b/chromium/content/public/browser/browser_plugin_guest_manager.h
index 3e7dd26fb57..481a8ab6517 100644
--- a/chromium/content/public/browser/browser_plugin_guest_manager.h
+++ b/chromium/content/public/browser/browser_plugin_guest_manager.h
@@ -5,20 +5,11 @@
#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_PLUGIN_GUEST_MANAGER_H_
#define CONTENT_PUBLIC_BROWSER_BROWSER_PLUGIN_GUEST_MANAGER_H_
-#include <string>
-
#include "base/callback.h"
#include "content/common/content_export.h"
-class GURL;
-
-namespace base {
-class DictionaryValue;
-} // namespace base
-
namespace content {
-class SiteInstance;
class WebContents;
// A BrowserPluginGuestManager offloads guest management and routing
@@ -27,28 +18,11 @@ class CONTENT_EXPORT BrowserPluginGuestManager {
public:
virtual ~BrowserPluginGuestManager() {}
- // Requests the allocation of a new guest WebContents.
- virtual content::WebContents* CreateGuest(
- content::SiteInstance* embedder_site_instance,
- int instance_id,
- scoped_ptr<base::DictionaryValue> extra_params);
-
- // Return a new instance ID.
- // TODO(fsamuel): Remove this. Once the instance ID concept is moved
- // entirely out of content and into chrome, this API will be unnecessary.
- virtual int GetNextInstanceID();
-
- typedef base::Callback<void(WebContents*)> GuestByInstanceIDCallback;
// Requests a guest WebContents associated with the provided
- // |guest_instance_id|. If a guest associated with the provided ID
- // does not exist, then the |callback| will be called with a NULL
- // WebContents. If the provided |embedder_render_process_id| does
- // not own the requested guest, then the embedder will be killed,
- // and the |callback| will not be called.
- virtual void MaybeGetGuestByInstanceIDOrKill(
- int guest_instance_id,
- int embedder_render_process_id,
- const GuestByInstanceIDCallback& callback) {}
+ // |browser_plugin_instance_id|.
+ // Returns the guest associated with the provided ID if one exists.
+ virtual WebContents* GetGuestByInstanceID(WebContents* embedder_web_contents,
+ int browser_plugin_instance_id);
// Iterates over all WebContents belonging to a given |embedder_web_contents|,
// calling |callback| for each. If one of the callbacks returns true, then
diff --git a/chromium/content/public/browser/browser_thread.h b/chromium/content/public/browser/browser_thread.h
index 6c83633e1f5..a9591e9516a 100644
--- a/chromium/content/public/browser/browser_thread.h
+++ b/chromium/content/public/browser/browser_thread.h
@@ -229,13 +229,14 @@ class CONTENT_EXPORT BrowserThread {
// not deleted while unregistering.
static void SetDelegate(ID identifier, BrowserThreadDelegate* delegate);
- // Use these templates in conjuction with RefCountedThreadSafe when you want
- // to ensure that an object is deleted on a specific thread. This is needed
- // when an object can hop between threads (i.e. IO -> FILE -> IO), and thread
- // switching delays can mean that the final IO tasks executes before the FILE
- // task's stack unwinds. This would lead to the object destructing on the
- // FILE thread, which often is not what you want (i.e. to unregister from
- // NotificationService, to notify other objects on the creating thread etc).
+ // Use these templates in conjunction with RefCountedThreadSafe or scoped_ptr
+ // when you want to ensure that an object is deleted on a specific thread.
+ // This is needed when an object can hop between threads
+ // (i.e. IO -> FILE -> IO), and thread switching delays can mean that the
+ // final IO tasks executes before the FILE task's stack unwinds.
+ // This would lead to the object destructing on the FILE thread, which often
+ // is not what you want (i.e. to unregister from NotificationService, to
+ // notify other objects on the creating thread etc).
template<ID thread>
struct DeleteOnThread {
template<typename T>
@@ -252,9 +253,14 @@ class CONTENT_EXPORT BrowserThread {
}
}
}
+ template <typename T>
+ inline void operator()(T* ptr) const {
+ enum { type_must_be_complete = sizeof(T) };
+ Destruct(ptr);
+ }
};
- // Sample usage:
+ // Sample usage with RefCountedThreadSafe:
// class Foo
// : public base::RefCountedThreadSafe<
// Foo, BrowserThread::DeleteOnIOThread> {
@@ -265,6 +271,9 @@ class CONTENT_EXPORT BrowserThread {
// friend class base::DeleteHelper<Foo>;
//
// ~Foo();
+ //
+ // Sample usage with scoped_ptr:
+ // scoped_ptr<Foo, BrowserThread::DeleteOnIOThread> ptr;
struct DeleteOnUIThread : public DeleteOnThread<UI> { };
struct DeleteOnIOThread : public DeleteOnThread<IO> { };
struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
diff --git a/chromium/content/public/browser/child_process_security_policy.h b/chromium/content/public/browser/child_process_security_policy.h
index 261bf58f181..7048d91cf52 100644
--- a/chromium/content/public/browser/child_process_security_policy.h
+++ b/chromium/content/public/browser/child_process_security_policy.h
@@ -70,7 +70,7 @@ class ChildProcessSecurityPolicy {
// Grants read access permission to the given isolated file system
// identified by |filesystem_id|. An isolated file system can be
// created for a set of native files/directories (like dropped files)
- // using fileapi::IsolatedContext. A child process needs to be granted
+ // using storage::IsolatedContext. A child process needs to be granted
// permission to the file system to access the files in it using
// file system URL. You do NOT need to give direct permission to
// individual file paths.
@@ -145,6 +145,11 @@ class ChildProcessSecurityPolicy {
// Returns true if delete-from access has been granted to |filesystem_id|.
virtual bool CanDeleteFromFileSystem(int child_id,
const std::string& filesystem_id) = 0;
+
+ // Returns true if the specified child_id has been granted WebUI bindings.
+ // The browser should check this property before assuming the child process
+ // is allowed to use WebUI bindings.
+ virtual bool HasWebUIBindings(int child_id) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index e8da55e8aff..728d8226fa5 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -116,6 +116,13 @@ bool ContentBrowserClient::AllowAppCache(const GURL& manifest_url,
return true;
}
+bool ContentBrowserClient::AllowServiceWorker(
+ const GURL& scope,
+ const GURL& document_url,
+ content::ResourceContext* context) {
+ return true;
+}
+
bool ContentBrowserClient::AllowGetCookie(const GURL& url,
const GURL& first_party,
const net::CookieList& cookie_list,
@@ -149,11 +156,12 @@ bool ContentBrowserClient::AllowWorkerDatabase(
return true;
}
-bool ContentBrowserClient::AllowWorkerFileSystem(
+void ContentBrowserClient::AllowWorkerFileSystem(
const GURL& url,
ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames) {
- return true;
+ const std::vector<std::pair<int, int> >& render_frames,
+ base::Callback<void(bool)> callback) {
+ callback.Run(true);
}
bool ContentBrowserClient::AllowWorkerIndexedDB(
@@ -168,6 +176,14 @@ QuotaPermissionContext* ContentBrowserClient::CreateQuotaPermissionContext() {
return NULL;
}
+void ContentBrowserClient::SelectClientCertificate(
+ int render_process_id,
+ int render_frame_id,
+ net::SSLCertRequestInfo* cert_request_info,
+ const base::Callback<void(net::X509Certificate*)>& callback) {
+ callback.Run(NULL);
+}
+
net::URLRequestContext* ContentBrowserClient::OverrideRequestContextForURL(
const GURL& url, ResourceContext* context) {
return NULL;
@@ -203,39 +219,21 @@ MediaObserver* ContentBrowserClient::GetMediaObserver() {
return NULL;
}
-blink::WebNotificationPresenter::Permission
- ContentBrowserClient::CheckDesktopNotificationPermission(
- const GURL& source_origin,
- ResourceContext* context,
- int render_process_id) {
- return blink::WebNotificationPresenter::PermissionAllowed;
-}
-
-void ContentBrowserClient::RequestGeolocationPermission(
- WebContents* web_contents,
- int bridge_id,
- const GURL& requesting_frame,
- bool user_gesture,
- base::Callback<void(bool)> result_callback,
- base::Closure* cancel_callback) {
- result_callback.Run(true);
+blink::WebNotificationPermission
+ContentBrowserClient::CheckDesktopNotificationPermission(
+ const GURL& source_origin,
+ ResourceContext* context,
+ int render_process_id) {
+ return blink::WebNotificationPermissionAllowed;
}
-void ContentBrowserClient::RequestMidiSysExPermission(
+void ContentBrowserClient::RequestPermission(
+ PermissionType permission,
WebContents* web_contents,
int bridge_id,
const GURL& requesting_frame,
bool user_gesture,
- base::Callback<void(bool)> result_callback,
- base::Closure* cancel_callback) {
- result_callback.Run(true);
-}
-
-void ContentBrowserClient::RequestProtectedMediaIdentifierPermission(
- WebContents* web_contents,
- const GURL& origin,
- base::Callback<void(bool)> result_callback,
- base::Closure* cancel_callback) {
+ const base::Callback<void(bool)>& result_callback) {
result_callback.Run(true);
}
@@ -258,11 +256,6 @@ bool ContentBrowserClient::CanCreateWindow(
return true;
}
-std::string ContentBrowserClient::GetWorkerProcessTitle(
- const GURL& url, ResourceContext* context) {
- return std::string();
-}
-
SpeechRecognitionManagerDelegate*
ContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
return NULL;
@@ -349,4 +342,11 @@ ContentBrowserClient::OverrideCreateExternalVideoSurfaceContainer(
}
#endif
+bool ContentBrowserClient::CheckMediaAccessPermission(
+ BrowserContext* browser_context,
+ const GURL& security_origin,
+ MediaStreamType type) {
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index d355596d8f7..5a27d9822c5 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -16,17 +16,20 @@
#include "base/memory/scoped_vector.h"
#include "base/values.h"
#include "content/public/browser/certificate_request_result_type.h"
+#include "content/public/browser/desktop_notification_delegate.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/media_stream_request.h"
+#include "content/public/common/resource_type.h"
#include "content/public/common/socket_permission_request.h"
#include "content/public/common/window_container_type.h"
#include "net/base/mime_util.h"
#include "net/cookies/canonical_cookie.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job_factory.h"
-#include "third_party/WebKit/public/web/WebNotificationPresenter.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "third_party/WebKit/public/platform/WebNotificationPermission.h"
#include "ui/base/window_open_disposition.h"
-#include "webkit/browser/fileapi/file_system_context.h"
-#include "webkit/common/resource_type.h"
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "base/posix/global_descriptors.h"
@@ -37,7 +40,6 @@
#endif
class GURL;
-struct WebPreferences;
namespace base {
class CommandLine;
@@ -56,7 +58,6 @@ class ImageSkia;
namespace net {
class CookieOptions;
class CookieStore;
-class HttpNetworkSession;
class NetLog;
class SSLCertRequestInfo;
class SSLInfo;
@@ -74,7 +75,7 @@ namespace ui {
class SelectFilePolicy;
}
-namespace fileapi {
+namespace storage {
class ExternalMountPoints;
class FileSystemBackend;
}
@@ -106,6 +107,7 @@ class WebContentsViewDelegate;
struct MainFunctionParams;
struct Referrer;
struct ShowDesktopNotificationHostMsgParams;
+struct WebPreferences;
// A mapping from the scheme name to the protocol handler that services its
// content.
@@ -141,24 +143,6 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual WebContentsViewDelegate* GetWebContentsViewDelegate(
WebContents* web_contents);
- // Notifies that a guest WebContents has been created. A guest WebContents
- // represents a renderer that's hosted within a BrowserPlugin. Creation can
- // occur an arbitrary length of time before attachment. If the new guest has
- // an |opener_web_contents|, then it's a new window created by that opener.
- // If the guest was created via navigation, then |extra_params| will be
- // non-NULL. |extra_params| are parameters passed to the BrowserPlugin object
- // element by the content embedder. These parameters may include the API to
- // enable for the given guest. |guest_delegate| is a return parameter of
- // the delegate in the content embedder that will service the guest in the
- // content layer. The content layer takes ownership of the |guest_delegate|.
- virtual void GuestWebContentsCreated(
- int guest_instance_id,
- SiteInstance* guest_site_instance,
- WebContents* guest_web_contents,
- WebContents* opener_web_contents,
- BrowserPluginGuestDelegate** guest_delegate,
- scoped_ptr<base::DictionaryValue> extra_params) {}
-
// Notifies that a render process will be created. This is called before
// the content layer adds its own BrowserMessageFilters, so that the
// embedder's IPC filters have priority.
@@ -243,14 +227,6 @@ class CONTENT_EXPORT ContentBrowserClient {
// Called from a site instance's destructor.
virtual void SiteInstanceDeleting(SiteInstance* site_instance) {}
- // Called when a worker process is created.
- virtual void WorkerProcessCreated(SiteInstance* site_instance,
- int worker_process_id) {}
-
- // Called when a worker process is terminated.
- virtual void WorkerProcessTerminated(SiteInstance* site_instance,
- int worker_process_id) {}
-
// Returns true if for the navigation from |current_url| to |new_url|
// in |site_instance|, a new SiteInstance and BrowsingInstance should be
// created (even if we are in a process model that doesn't usually swap.)
@@ -298,6 +274,13 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& first_party,
ResourceContext* context);
+ // Allow the embedder to control if a Service Worker can be associated
+ // with the given scope.
+ // This is called on the IO thread.
+ virtual bool AllowServiceWorker(const GURL& scope,
+ const GURL& first_party,
+ content::ResourceContext* context);
+
// Allow the embedder to control if the given cookie can be read.
// This is called on the IO thread.
virtual bool AllowGetCookie(const GURL& url,
@@ -335,10 +318,11 @@ class CONTENT_EXPORT ContentBrowserClient {
// Allow the embedder to control if access to file system by a shared worker
// is allowed.
// This is called on the IO thread.
- virtual bool AllowWorkerFileSystem(
+ virtual void AllowWorkerFileSystem(
const GURL& url,
ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames);
+ const std::vector<std::pair<int, int> >& render_frames,
+ base::Callback<void(bool)> callback);
// Allow the embedder to control if access to IndexedDB by a shared worker
// is allowed.
@@ -400,26 +384,25 @@ class CONTENT_EXPORT ContentBrowserClient {
// asynchronously. If |result| is not set to
// CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE, the request will be cancelled
// or denied immediately, and the callback won't be run.
- virtual void AllowCertificateError(
- int render_process_id,
- int render_frame_id,
- int cert_error,
- const net::SSLInfo& ssl_info,
- const GURL& request_url,
- ResourceType::Type resource_type,
- bool overridable,
- bool strict_enforcement,
- const base::Callback<void(bool)>& callback,
- CertificateRequestResultType* result) {}
+ virtual void AllowCertificateError(int render_process_id,
+ int render_frame_id,
+ int cert_error,
+ const net::SSLInfo& ssl_info,
+ const GURL& request_url,
+ ResourceType resource_type,
+ bool overridable,
+ bool strict_enforcement,
+ bool expired_previous_decision,
+ const base::Callback<void(bool)>& callback,
+ CertificateRequestResultType* result) {}
// Selects a SSL client certificate and returns it to the |callback|. If no
// certificate was selected NULL is returned to the |callback|.
virtual void SelectClientCertificate(
int render_process_id,
int render_frame_id,
- const net::HttpNetworkSession* network_session,
net::SSLCertRequestInfo* cert_request_info,
- const base::Callback<void(net::X509Certificate*)>& callback) {}
+ const base::Callback<void(net::X509Certificate*)>& callback);
// Adds a new installable certificate or private key.
// Typically used to install an X.509 user certificate.
@@ -435,16 +418,9 @@ class CONTENT_EXPORT ContentBrowserClient {
// return NULL if they're not interested.
virtual MediaObserver* GetMediaObserver();
- // Asks permission to show desktop notifications. |callback| needs to be run
- // when the user approves the request.
- virtual void RequestDesktopNotificationPermission(
- const GURL& source_origin,
- RenderFrameHost* render_frame_host,
- const base::Closure& callback) {}
-
// Checks if the given page has permission to show desktop notifications.
// This is called on the IO thread.
- virtual blink::WebNotificationPresenter::Permission
+ virtual blink::WebNotificationPermission
CheckDesktopNotificationPermission(
const GURL& source_url,
ResourceContext* context,
@@ -454,42 +430,28 @@ class CONTENT_EXPORT ContentBrowserClient {
// a callback which can be used to cancel the notification.
virtual void ShowDesktopNotification(
const ShowDesktopNotificationHostMsgParams& params,
- RenderFrameHost* render_frame_host,
- DesktopNotificationDelegate* delegate,
+ BrowserContext* browser_context,
+ int render_process_id,
+ scoped_ptr<DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) {}
- // The renderer is requesting permission to use Geolocation. When the answer
- // to a permission request has been determined, |result_callback| should be
- // called with the result. If |cancel_callback| is non-null, it's set to a
- // callback which can be used to cancel the permission request.
- virtual void RequestGeolocationPermission(
- WebContents* web_contents,
- int bridge_id,
- const GURL& requesting_frame,
- bool user_gesture,
- base::Callback<void(bool)> result_callback,
- base::Closure* cancel_callback);
-
- // Requests a permission to use system exclusive messages in MIDI events.
- // |result_callback| will be invoked when the request is resolved. If
- // |cancel_callback| is non-null, it's set to a callback which can be used to
- // cancel the permission request.
- virtual void RequestMidiSysExPermission(
+ virtual void RequestPermission(
+ PermissionType permission,
WebContents* web_contents,
int bridge_id,
const GURL& requesting_frame,
bool user_gesture,
- base::Callback<void(bool)> result_callback,
- base::Closure* cancel_callback);
+ const base::Callback<void(bool)>& result_callback);
- // Request permission to access protected media identifier. |result_callback
- // will tell whether it's permitted. If |cancel_callback| is non-null, it's
- // set to a callback which can be used to cancel the permission request.
- virtual void RequestProtectedMediaIdentifierPermission(
- WebContents* web_contents,
- const GURL& origin,
- base::Callback<void(bool)> result_callback,
- base::Closure* cancel_callback);
+ virtual void CancelPermissionRequest(PermissionType permission,
+ WebContents* web_contents,
+ int bridge_id,
+ const GURL& requesting_frame) {}
+
+ virtual void RegisterPermissionUsage(PermissionType permission,
+ WebContents* web_contents,
+ const GURL& frame_url,
+ const GURL& main_frame_url) {}
// Returns true if the given page is allowed to open a window of the given
// type. If true is returned, |no_javascript_access| will indicate whether
@@ -510,12 +472,6 @@ class CONTENT_EXPORT ContentBrowserClient {
int opener_id,
bool* no_javascript_access);
- // Returns a title string to use in the task manager for a process host with
- // the given URL, or the empty string to fall back to the default logic.
- // This is called on the IO thread.
- virtual std::string GetWorkerProcessTitle(const GURL& url,
- ResourceContext* context);
-
// Notifies the embedder that the ResourceDispatcherHost has been created.
// This is when it can optionally add a delegate.
virtual void ResourceDispatcherHostCreated() {}
@@ -541,11 +497,6 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& url,
WebPreferences* prefs) {}
- // Inspector setting was changed and should be persisted.
- virtual void UpdateInspectorSetting(RenderViewHost* rvh,
- const std::string& key,
- const std::string& value) {}
-
// Notifies that BrowserURLHandler has been created, so that the embedder can
// optionally add their own handlers.
virtual void BrowserURLHandlerCreated(BrowserURLHandler* handler) {}
@@ -595,7 +546,7 @@ class CONTENT_EXPORT ContentBrowserClient {
// Returns auto mount handlers for URL requests for FileSystem APIs.
virtual void GetURLRequestAutoMountHandlers(
- std::vector<fileapi::URLRequestAutoMountHandler>* handlers) {}
+ std::vector<storage::URLRequestAutoMountHandler>* handlers) {}
// Returns additional file system backends for FileSystem API.
// |browser_context| is needed in the additional FileSystemBackends.
@@ -604,7 +555,7 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual void GetAdditionalFileSystemBackends(
BrowserContext* browser_context,
const base::FilePath& storage_partition_path,
- ScopedVector<fileapi::FileSystemBackend>* additional_backends) {}
+ ScopedVector<storage::FileSystemBackend>* additional_backends) {}
// Allows an embedder to return its own LocationProvider implementation.
// Return NULL to use the default one for the platform to be created.
@@ -647,7 +598,7 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual void GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line,
int child_process_id,
- std::vector<FileDescriptorInfo>* mappings) {}
+ FileDescriptorInfo* mappings) {}
#endif
#if defined(OS_WIN)
@@ -667,6 +618,13 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual ExternalVideoSurfaceContainer*
OverrideCreateExternalVideoSurfaceContainer(WebContents* web_contents);
#endif
+
+// Checks if |security_origin| has permission to access the microphone or
+// camera. Note that this does not query the user. |type| must be
+// MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE.
+virtual bool CheckMediaAccessPermission(BrowserContext* browser_context,
+ const GURL& security_origin,
+ MediaStreamType type);
};
} // namespace content
diff --git a/chromium/content/public/browser/cookie_store_factory.h b/chromium/content/public/browser/cookie_store_factory.h
index ec2243fcb10..03834bfb420 100644
--- a/chromium/content/public/browser/cookie_store_factory.h
+++ b/chromium/content/public/browser/cookie_store_factory.h
@@ -18,7 +18,7 @@ class CookieMonsterDelegate;
class CookieStore;
}
-namespace quota {
+namespace storage {
class SpecialStoragePolicy;
}
@@ -56,13 +56,13 @@ struct CONTENT_EXPORT CookieStoreConfig {
// created using this config.
CookieStoreConfig(const base::FilePath& path,
SessionCookieMode session_cookie_mode,
- quota::SpecialStoragePolicy* storage_policy,
+ storage::SpecialStoragePolicy* storage_policy,
net::CookieMonsterDelegate* cookie_delegate);
~CookieStoreConfig();
const base::FilePath path;
const SessionCookieMode session_cookie_mode;
- const scoped_refptr<quota::SpecialStoragePolicy> storage_policy;
+ const scoped_refptr<storage::SpecialStoragePolicy> storage_policy;
const scoped_refptr<net::CookieMonsterDelegate> cookie_delegate;
// The following are infrequently used cookie store parameters.
diff --git a/chromium/content/public/browser/desktop_media_id.cc b/chromium/content/public/browser/desktop_media_id.cc
index a2adfdab5e6..9f5d4bb1e9e 100644
--- a/chromium/content/public/browser/desktop_media_id.cc
+++ b/chromium/content/public/browser/desktop_media_id.cc
@@ -32,7 +32,12 @@ class AuraWindowRegistry : public aura::WindowObserver {
}
// If the windows doesn't have an Id yet assign it.
- int id = next_id_++;
+ int id;
+ do {
+ id = next_id_;
+ next_id_ = (next_id_ == INT_MAX) ? 1 : (next_id_ + 1);
+ } while (id_to_window_map_.find(id) != id_to_window_map_.end());
+
window_to_id_map_[window] = id;
id_to_window_map_[id] = window;
window->AddObserver(this);
@@ -48,12 +53,12 @@ class AuraWindowRegistry : public aura::WindowObserver {
friend struct DefaultSingletonTraits<AuraWindowRegistry>;
AuraWindowRegistry()
- : next_id_(0) {
+ : next_id_(1) {
}
- virtual ~AuraWindowRegistry() {}
+ ~AuraWindowRegistry() override {}
// WindowObserver overrides.
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
+ void OnWindowDestroying(aura::Window* window) override {
std::map<aura::Window*, int>::iterator it = window_to_id_map_.find(window);
DCHECK(it != window_to_id_map_.end());
id_to_window_map_.erase(it->second);
diff --git a/chromium/content/public/browser/desktop_notification_delegate.h b/chromium/content/public/browser/desktop_notification_delegate.h
index 27c5fd7f28c..aaf2c9d98d7 100644
--- a/chromium/content/public/browser/desktop_notification_delegate.h
+++ b/chromium/content/public/browser/desktop_notification_delegate.h
@@ -16,9 +16,6 @@ class DesktopNotificationDelegate {
// The notification was shown.
virtual void NotificationDisplayed() = 0;
- // The notification couldn't be shown due to an error.
- virtual void NotificationError() = 0;
-
// The notification was closed.
virtual void NotificationClosed(bool by_user) = 0;
diff --git a/chromium/content/public/browser/devtools_agent_host.h b/chromium/content/public/browser/devtools_agent_host.h
index dd18a53886b..cc5d69caa57 100644
--- a/chromium/content/public/browser/devtools_agent_host.h
+++ b/chromium/content/public/browser/devtools_agent_host.h
@@ -9,19 +9,35 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "content/public/browser/devtools_agent_host_client.h"
+#include "url/gurl.h"
namespace content {
class DevToolsExternalAgentProxyDelegate;
-class RenderViewHost;
class WebContents;
// Describes interface for managing devtools agents from browser process.
class CONTENT_EXPORT DevToolsAgentHost
: public base::RefCounted<DevToolsAgentHost> {
public:
+ enum Type {
+ // Agent host associated with WebContents.
+ TYPE_WEB_CONTENTS,
+
+ // Agent host associated with shared worker.
+ TYPE_SHARED_WORKER,
+
+ // Agent host associated with service worker.
+ TYPE_SERVICE_WORKER,
+
+ // Agent host associated with DevToolsExternalAgentProxyDelegate.
+ TYPE_EXTERNAL,
+ };
+
// Returns DevToolsAgentHost with a given |id| or NULL of it does not exist.
static scoped_refptr<DevToolsAgentHost> GetForId(const std::string& id);
@@ -30,13 +46,9 @@ class CONTENT_EXPORT DevToolsAgentHost
static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(
WebContents* web_contents);
- // Returns DevToolsAgentHost that can be used for inspecting |rvh|.
- // New DevToolsAgentHost will be created if it does not exist.
- static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(RenderViewHost* rvh);
-
- // Returns true iff an instance of DevToolsAgentHost for the |rvh|
+ // Returns true iff an instance of DevToolsAgentHost for the |web_contents|
// does exist.
- static bool HasFor(RenderViewHost* rvh);
+ static bool HasFor(WebContents* web_contents);
// Returns DevToolsAgentHost that can be used for inspecting shared worker
// with given worker process host id and routing id.
@@ -51,31 +63,66 @@ class CONTENT_EXPORT DevToolsAgentHost
static bool IsDebuggerAttached(WebContents* web_contents);
- // Returns a list of all existing RenderViewHost's that can be debugged.
- static std::vector<RenderViewHost*> GetValidRenderViewHosts();
+ typedef std::vector<scoped_refptr<DevToolsAgentHost> > List;
+
+ // Returns all possible DevToolsAgentHosts.
+ static List GetOrCreateAll();
+
+ // Client attaches to this agent host to start debugging it.
+ virtual void AttachClient(DevToolsAgentHostClient* client) = 0;
+
+ // Already attached client detaches from this agent host to stop debugging it.
+ virtual void DetachClient() = 0;
// Returns true if there is a client attached.
virtual bool IsAttached() = 0;
+ // Sends a message to the agent.
+ virtual void DispatchProtocolMessage(const std::string& message) = 0;
+
// Starts inspecting element at position (|x|, |y|) in the specified page.
virtual void InspectElement(int x, int y) = 0;
// Returns the unique id of the agent.
virtual std::string GetId() = 0;
- // Returns render view host instance for this host if any.
- virtual RenderViewHost* GetRenderViewHost() = 0;
+ // Returns web contents instance for this host if any.
+ virtual WebContents* GetWebContents() = 0;
// Temporarily detaches render view host from this host. Must be followed by
- // a call to ConnectRenderViewHost (may leak the host instance otherwise).
- virtual void DisconnectRenderViewHost() = 0;
+ // a call to ConnectWebContents (may leak the host instance otherwise).
+ virtual void DisconnectWebContents() = 0;
// Attaches render view host to this host.
- virtual void ConnectRenderViewHost(RenderViewHost* rvh) = 0;
+ virtual void ConnectWebContents(WebContents* web_contents) = 0;
// Returns true if DevToolsAgentHost is for worker.
virtual bool IsWorker() const = 0;
+ // Returns agent host type.
+ virtual Type GetType() = 0;
+
+ // Returns agent host title.
+ virtual std::string GetTitle() = 0;
+
+ // Returns url associated with agent host.
+ virtual GURL GetURL() = 0;
+
+ // Activates agent host. Returns false if the operation failed.
+ virtual bool Activate() = 0;
+
+ // Closes agent host. Returns false if the operation failed.
+ virtual bool Close() = 0;
+
+ // Terminates all debugging sessions and detaches all clients.
+ static void DetachAllClients();
+
+ typedef base::Callback<void(DevToolsAgentHost*, bool attached)>
+ AgentStateCallback;
+
+ static void AddAgentStateCallback(const AgentStateCallback& callback);
+ static void RemoveAgentStateCallback(const AgentStateCallback& callback);
+
protected:
friend class base::RefCounted<DevToolsAgentHost>;
virtual ~DevToolsAgentHost() {}
diff --git a/chromium/content/public/browser/devtools_agent_host_client.h b/chromium/content/public/browser/devtools_agent_host_client.h
new file mode 100644
index 00000000000..90d7a735952
--- /dev/null
+++ b/chromium/content/public/browser/devtools_agent_host_client.h
@@ -0,0 +1,34 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_DEVTOOLS_AGENT_HOST_CLIENT_H_
+#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_AGENT_HOST_CLIENT_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class DevToolsAgentHost;
+
+// DevToolsAgentHostClient can attach to a DevToolsAgentHost and start
+// debugging it.
+class CONTENT_EXPORT DevToolsAgentHostClient {
+ public:
+ virtual ~DevToolsAgentHostClient() {}
+
+ // Dispatches given protocol message on the client.
+ virtual void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+ const std::string& message) = 0;
+
+ // This method is called when attached agent host is closed.
+ virtual void AgentHostClosed(DevToolsAgentHost* agent_host,
+ bool replaced_with_another_client) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_AGENT_HOST_CLIENT_H_
diff --git a/chromium/content/public/browser/devtools_client_host.h b/chromium/content/public/browser/devtools_client_host.h
deleted file mode 100644
index fe76d3cdf91..00000000000
--- a/chromium/content/public/browser/devtools_client_host.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_PUBLIC_BROWSER_DEVTOOLS_CLIENT_HOST_H_
-#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_CLIENT_HOST_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "content/common/content_export.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-
-class RenderViewHost;
-class WebContents;
-
-class DevToolsFrontendHostDelegate;
-
-// Describes interface for managing devtools clients from browser process. There
-// are currently two types of clients: devtools windows and TCP socket
-// debuggers.
-class CONTENT_EXPORT DevToolsClientHost {
- public:
- virtual ~DevToolsClientHost() {}
-
- // Dispatches given message on the front-end.
- virtual void DispatchOnInspectorFrontend(const std::string& message) = 0;
-
- // This method is called when the contents inspected by this devtools client
- // is closing.
- virtual void InspectedContentsClosing() = 0;
-
- // Called to notify client that it has been kicked out by some other client
- // with greater priority.
- virtual void ReplacedWithAnotherClient() = 0;
-
- // Creates a DevToolsClientHost for a WebContents containing the default
- // DevTools frontend implementation.
- static DevToolsClientHost* CreateDevToolsFrontendHost(
- WebContents* client_web_contents,
- DevToolsFrontendHostDelegate* delegate);
-
- // Sets up DevToolsClient on the corresponding RenderView.
- static void SetupDevToolsFrontendClient(RenderViewHost* frontend_rvh);
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_CLIENT_HOST_H_
diff --git a/chromium/content/public/browser/devtools_frontend_host.h b/chromium/content/public/browser/devtools_frontend_host.h
new file mode 100644
index 00000000000..24c50f51e07
--- /dev/null
+++ b/chromium/content/public/browser/devtools_frontend_host.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_DEVTOOLS_FRONTEND_HOST_H_
+#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_FRONTEND_HOST_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+class RenderViewHost;
+
+// This class dispatches messages between DevTools frontend and Delegate
+// which is implemented by the embedder.
+// This allows us to avoid exposing DevTools frontend messages through
+// the content public API.
+class DevToolsFrontendHost {
+ public:
+ // Delegate actually handles messages from frontend.
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // Message is coming from frontend to the embedder.
+ virtual void HandleMessageFromDevToolsFrontend(
+ const std::string& message) = 0;
+
+ // Message is coming from frontend to the backend.
+ // TODO(dgozman): remove this by making one of the possible messages
+ // passed via the method above.
+ virtual void HandleMessageFromDevToolsFrontendToBackend(
+ const std::string& message) = 0;
+ };
+
+ // Creates a new DevToolsFrontendHost for RenderViewHost where DevTools
+ // frontend is loaded.
+ CONTENT_EXPORT static DevToolsFrontendHost* Create(
+ RenderViewHost* frontend_rvh, Delegate* delegate);
+
+ CONTENT_EXPORT virtual ~DevToolsFrontendHost() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_FRONTEND_HOST_H_
diff --git a/chromium/content/public/browser/devtools_frontend_host_delegate.h b/chromium/content/public/browser/devtools_frontend_host_delegate.h
deleted file mode 100644
index 1d41befdcf6..00000000000
--- a/chromium/content/public/browser/devtools_frontend_host_delegate.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_PUBLIC_BROWSER_DEVTOOLS_FRONTEND_HOST_DELEGATE_H_
-#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_FRONTEND_HOST_DELEGATE_H_
-
-#include <string>
-
-namespace content {
-
-// Clients that want to use default DevTools front-end implementation should
-// implement this interface to provide access to the embedding browser from
-// the front-end.
-class DevToolsFrontendHostDelegate {
- public:
- virtual ~DevToolsFrontendHostDelegate() {}
-
- // Dispatch the message from the frontend to the frontend host.
- virtual void DispatchOnEmbedder(const std::string& message) = 0;
-
- // This method is called when the contents inspected by this devtools frontend
- // is closing.
- virtual void InspectedContentsClosing() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_FRONTEND_HOST_DELEGATE_H_
diff --git a/chromium/content/public/browser/devtools_http_handler.h b/chromium/content/public/browser/devtools_http_handler.h
index cdceff8dfd4..2b656b64958 100644
--- a/chromium/content/public/browser/devtools_http_handler.h
+++ b/chromium/content/public/browser/devtools_http_handler.h
@@ -8,12 +8,13 @@
#include <string>
#include "base/files/file_path.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
class GURL;
namespace net {
-class StreamListenSocketFactory;
+class ServerSocket;
class URLRequestContextGetter;
}
@@ -26,6 +27,32 @@ class DevToolsHttpHandlerDelegate;
// this browser.
class DevToolsHttpHandler {
public:
+
+ // Factory of net::ServerSocket. This is to separate instantiating dev tools
+ // and instantiating server socket.
+ class CONTENT_EXPORT ServerSocketFactory {
+ public:
+ ServerSocketFactory(const std::string& address, int port, int backlog);
+ virtual ~ServerSocketFactory();
+
+ // Returns a new instance of ServerSocket or NULL if an error occurred.
+ // It calls ServerSocket::ListenWithAddressAndPort() with address, port and
+ // backlog passed to constructor.
+ virtual scoped_ptr<net::ServerSocket> CreateAndListen() const;
+
+ protected:
+ // Creates a server socket. ServerSocket::Listen() will be called soon
+ // unless it returns NULL.
+ virtual scoped_ptr<net::ServerSocket> Create() const = 0;
+
+ const std::string address_;
+ const int port_;
+ const int backlog_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServerSocketFactory);
+ };
+
// Returns true if the given protocol version is supported.
CONTENT_EXPORT static bool IsSupportedProtocolVersion(
const std::string& version);
@@ -40,7 +67,7 @@ class DevToolsHttpHandler {
// port selected by the OS will be written to a well-known file in
// the output directory.
CONTENT_EXPORT static DevToolsHttpHandler* Start(
- const net::StreamListenSocketFactory* socket_factory,
+ scoped_ptr<ServerSocketFactory> server_socket_factory,
const std::string& frontend_url,
DevToolsHttpHandlerDelegate* delegate,
const base::FilePath& active_port_output_directory);
diff --git a/chromium/content/public/browser/devtools_http_handler_delegate.h b/chromium/content/public/browser/devtools_http_handler_delegate.h
index 2b64a7dd40a..514b273f5ae 100644
--- a/chromium/content/public/browser/devtools_http_handler_delegate.h
+++ b/chromium/content/public/browser/devtools_http_handler_delegate.h
@@ -12,8 +12,6 @@
#include "base/memory/scoped_ptr.h"
#include "net/socket/stream_listen_socket.h"
-class GURL;
-
namespace content {
class DevToolsTarget;
@@ -32,20 +30,6 @@ class DevToolsHttpHandlerDelegate {
// Returns path to the front-end files on the local filesystem for debugging.
virtual base::FilePath GetDebugFrontendDir() = 0;
- // Get a thumbnail for a given page. Returns non-empty string iff we have the
- // thumbnail.
- virtual std::string GetPageThumbnailData(const GURL& url) = 0;
-
- // Creates new inspectable target.
- virtual scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) = 0;
-
- typedef std::vector<DevToolsTarget*> TargetList;
- typedef base::Callback<void(const TargetList&)> TargetCallback;
-
- // Requests the list of all inspectable targets.
- // The caller gets the ownership of the returned targets.
- virtual void EnumerateTargets(TargetCallback callback) = 0;
-
// Creates named socket for reversed tethering implementation (used with
// remote debugging, primarily for mobile).
virtual scoped_ptr<net::StreamListenSocket> CreateSocketForTethering(
diff --git a/chromium/content/public/browser/devtools_manager.h b/chromium/content/public/browser/devtools_manager.h
deleted file mode 100644
index 32082ea8bc5..00000000000
--- a/chromium/content/public/browser/devtools_manager.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_PUBLIC_BROWSER_DEVTOOLS_MANAGER_H_
-#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_MANAGER_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "content/common/content_export.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-
-class DevToolsAgentHost;
-class DevToolsClientHost;
-
-// DevToolsManager connects a devtools client to inspected agent and routes
-// devtools messages between the inspected instance represented by the agent
-// and devtools front-end represented by the client. If inspected agent
-// gets terminated DevToolsManager will notify corresponding client and
-// remove it from the map.
-class CONTENT_EXPORT DevToolsManager {
- public:
- static DevToolsManager* GetInstance();
-
- virtual ~DevToolsManager() {}
-
- // Routes devtools message from |from| client to corresponding
- // DevToolsAgentHost.
- virtual bool DispatchOnInspectorBackend(DevToolsClientHost* from,
- const std::string& message) = 0;
-
- // Disconnects all client hostst.
- virtual void CloseAllClientHosts() = 0;
-
- // Returns agent that has |client_host| attached to it if there is one.
- virtual DevToolsAgentHost* GetDevToolsAgentHostFor(
- DevToolsClientHost* client_host) = 0;
-
- // Registers new DevToolsClientHost for inspected |agent_host|. If there is
- // another DevToolsClientHost registered for the |agent_host| at the moment
- // it is disconnected.
- virtual void RegisterDevToolsClientHostFor(
- DevToolsAgentHost* agent_host,
- DevToolsClientHost* client_host) = 0;
-
- // This method will remove all references from the manager to the
- // DevToolsClientHost and unregister all listeners related to the
- // DevToolsClientHost. Called by closing client.
- virtual void ClientHostClosing(DevToolsClientHost* client_host) = 0;
-
- typedef base::Callback<void(DevToolsAgentHost*, bool attached)> Callback;
-
- virtual void AddAgentStateCallback(const Callback& callback) = 0;
- virtual void RemoveAgentStateCallback(const Callback& callback) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_DEVTOOLS_MANAGER_H_
diff --git a/chromium/content/public/browser/devtools_manager_delegate.h b/chromium/content/public/browser/devtools_manager_delegate.h
index d34e7af3957..5ebd854b108 100644
--- a/chromium/content/public/browser/devtools_manager_delegate.h
+++ b/chromium/content/public/browser/devtools_manager_delegate.h
@@ -5,14 +5,22 @@
#ifndef CONTENT_PUBLIC_BROWSER_DEVTOOLS_MANAGER_DELEGATE_H_
#define CONTENT_PUBLIC_BROWSER_DEVTOOLS_MANAGER_DELEGATE_H_
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+
namespace base {
class DictionaryValue;
}
+class GURL;
+
namespace content {
class BrowserContext;
class DevToolsAgentHost;
+class DevToolsTarget;
class DevToolsManagerDelegate {
public:
@@ -29,6 +37,20 @@ class DevToolsManagerDelegate {
virtual base::DictionaryValue* HandleCommand(
DevToolsAgentHost* agent_host,
base::DictionaryValue* command) = 0;
+
+ // Creates new inspectable target.
+ virtual scoped_ptr<DevToolsTarget> CreateNewTarget(const GURL& url) = 0;
+
+ typedef std::vector<DevToolsTarget*> TargetList;
+ typedef base::Callback<void(const TargetList&)> TargetCallback;
+
+ // Requests the list of all inspectable targets.
+ // The caller gets the ownership of the returned targets.
+ virtual void EnumerateTargets(TargetCallback callback) = 0;
+
+ // Get a thumbnail for a given page. Returns non-empty string iff we have the
+ // thumbnail.
+ virtual std::string GetPageThumbnailData(const GURL& url) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/download_interrupt_reason_values.h b/chromium/content/public/browser/download_interrupt_reason_values.h
index b05207a5fb9..bcb21b388c2 100644
--- a/chromium/content/public/browser/download_interrupt_reason_values.h
+++ b/chromium/content/public/browser/download_interrupt_reason_values.h
@@ -14,7 +14,6 @@
INTERRUPT_REASON(FILE_FAILED, 1)
// The file cannot be accessed due to security restrictions.
-// The file cannot be accessed.
// "Access Denied".
INTERRUPT_REASON(FILE_ACCESS_DENIED, 2)
@@ -95,6 +94,11 @@ INTERRUPT_REASON(SERVER_PRECONDITION, 32)
// "Unable to get file".
INTERRUPT_REASON(SERVER_BAD_CONTENT, 33)
+// Server didn't authorize access to resource.
+INTERRUPT_REASON(SERVER_UNAUTHORIZED, 34)
+
+// Server certificate problem.
+INTERRUPT_REASON(SERVER_CERT_PROBLEM, 35)
// User input.
diff --git a/chromium/content/public/browser/download_item.h b/chromium/content/public/browser/download_item.h
index 1e66f8b8a0d..ed6cd3eea4b 100644
--- a/chromium/content/public/browser/download_item.h
+++ b/chromium/content/public/browser/download_item.h
@@ -27,7 +27,7 @@
#include "base/supports_user_data.h"
#include "content/public/browser/download_danger_type.h"
#include "content/public/browser/download_interrupt_reasons.h"
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
class GURL;
@@ -99,7 +99,7 @@ class CONTENT_EXPORT DownloadItem : public base::SupportsUserData {
virtual ~Observer() {}
};
- virtual ~DownloadItem() {}
+ ~DownloadItem() override {}
// Observation ---------------------------------------------------------------
@@ -189,7 +189,7 @@ class CONTENT_EXPORT DownloadItem : public base::SupportsUserData {
virtual std::string GetOriginalMimeType() const = 0;
virtual std::string GetRemoteAddress() const = 0;
virtual bool HasUserGesture() const = 0;
- virtual PageTransition GetTransitionType() const = 0;
+ virtual ui::PageTransition GetTransitionType() const = 0;
virtual const std::string& GetLastModifiedTime() const = 0;
virtual const std::string& GetETag() const = 0;
virtual bool IsSavePackageDownload() const = 0;
diff --git a/chromium/content/public/browser/download_manager.h b/chromium/content/public/browser/download_manager.h
index 0c9bbacaa47..d51ebe9b294 100644
--- a/chromium/content/public/browser/download_manager.h
+++ b/chromium/content/public/browser/download_manager.h
@@ -56,7 +56,7 @@ struct DownloadCreateInfo;
// Browser's download manager: manages all downloads and destination view.
class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
public:
- virtual ~DownloadManager() {}
+ ~DownloadManager() override {}
// Sets/Gets the delegate for this DownloadManager. The delegate has to live
// past its Shutdown method being called (by the DownloadManager).
diff --git a/chromium/content/public/browser/file_descriptor_info.h b/chromium/content/public/browser/file_descriptor_info.h
index 2248eb690f1..b0b2bdad7dc 100644
--- a/chromium/content/public/browser/file_descriptor_info.h
+++ b/chromium/content/public/browser/file_descriptor_info.h
@@ -5,23 +5,42 @@
#ifndef CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_H_
#define CONTENT_PUBLIC_BROWSER_FILE_DESCRIPTOR_INFO_H_
-#include "base/file_descriptor_posix.h"
+#include "base/files/file.h"
+#include "base/process/launch.h"
namespace content {
-// This struct is used when passing files that should be mapped in a process
-// that is been created and allows to associate that file with a specific ID.
-// It also provides a way to know if the actual file descriptor should be
-// closed with the FileDescriptor.auto_close field.
-
-struct FileDescriptorInfo {
- FileDescriptorInfo(int id, const base::FileDescriptor& file_descriptor)
- : id(id),
- fd(file_descriptor) {
- }
-
- int id;
- base::FileDescriptor fd;
+// FileDescriptorInfo is a collection of file descriptors which is
+// needed to launch a process. You should tell FileDescriptorInfo
+// which FD should be closed and which shouldn't so that it can take care
+// of the lifetime of FDs.
+//
+// See base/process/launcher.h for more details about launching a
+// process.
+class FileDescriptorInfo {
+ public:
+ virtual ~FileDescriptorInfo() {}
+
+ // Add an FD associated with an ID, without delegating the ownerhip
+ // of ID.
+ virtual void Share(int id, base::PlatformFile fd) = 0;
+
+ // Add an FD associated with an ID, passing the FD ownership to
+ // FileDescriptorInfo.
+ virtual void Transfer(int id, base::ScopedFD fd) = 0;
+
+ // A vecotr backed map of registered ID-FD pairs.
+ virtual const base::FileHandleMappingVector& GetMapping() const = 0;
+
+ // A GetMapping() variant what adjusts the ID value by |delta|.
+ // Some environments need this trick.
+ virtual base::FileHandleMappingVector GetMappingWithIDAdjustment(
+ int delta) const = 0;
+
+ // API for iterating registered ID-FD pairs.
+ virtual base::PlatformFile GetFDAt(size_t i) const = 0;
+ virtual int GetIDAt(size_t i) const = 0;
+ virtual size_t GetMappingSize() const = 0;
};
}
diff --git a/chromium/content/public/browser/gpu_data_manager.h b/chromium/content/public/browser/gpu_data_manager.h
index 7ffc9f18402..a29575f762c 100644
--- a/chromium/content/public/browser/gpu_data_manager.h
+++ b/chromium/content/public/browser/gpu_data_manager.h
@@ -57,9 +57,15 @@ class GpuDataManager {
// contains a description of the reason why GPU access is blocked.
virtual bool GpuAccessAllowed(std::string* reason) const = 0;
- // Requests complete GPUinfo if it has not already been requested
+ // Requests complete GPU info if it has not already been requested
virtual void RequestCompleteGpuInfoIfNeeded() = 0;
+ // Check if basic and context GPU info have been collected.
+ virtual bool IsEssentialGpuInfoAvailable() const = 0;
+
+ // On Windows, besides basic and context GPU info, it also checks if
+ // DxDiagnostics have been collected.
+ // On other platforms, it's the same as IsEsentialGpuInfoAvailable().
virtual bool IsCompleteGpuInfoAvailable() const = 0;
// Requests that the GPU process report its current video memory usage stats,
@@ -72,6 +78,10 @@ class GpuDataManager {
// Register a path to SwiftShader.
virtual void RegisterSwiftShaderPath(const base::FilePath& path) = 0;
+ // Returns current state about WARP, which may be due to command-line
+ // arguments or saved state.
+ virtual bool ShouldUseWarp() const = 0;
+
// Registers/unregister |observer|.
virtual void AddObserver(GpuDataManagerObserver* observer) = 0;
virtual void RemoveObserver(GpuDataManagerObserver* observer) = 0;
diff --git a/chromium/content/public/browser/gpu_data_manager_observer.h b/chromium/content/public/browser/gpu_data_manager_observer.h
index d52e668fa22..e45ed44082a 100644
--- a/chromium/content/public/browser/gpu_data_manager_observer.h
+++ b/chromium/content/public/browser/gpu_data_manager_observer.h
@@ -35,9 +35,6 @@ class CONTENT_EXPORT GpuDataManagerObserver {
// Called for any observer when the GPU process crashed.
virtual void OnGpuProcessCrashed(base::TerminationStatus exit_code) {}
- // Called for any observer when the system switches to a different GPU.
- virtual void OnGpuSwitching() {}
-
protected:
virtual ~GpuDataManagerObserver() {}
};
diff --git a/chromium/content/public/browser/host_zoom_map.h b/chromium/content/public/browser/host_zoom_map.h
index e65b443d2b4..e9e523e29f4 100644
--- a/chromium/content/public/browser/host_zoom_map.h
+++ b/chromium/content/public/browser/host_zoom_map.h
@@ -13,9 +13,11 @@
#include "base/callback.h"
#include "base/callback_list.h"
#include "content/common/content_export.h"
+#include "url/gurl.h"
namespace content {
+class NavigationEntry;
class BrowserContext;
class ResourceContext;
class WebContents;
@@ -52,7 +54,11 @@ class HostZoomMap {
typedef std::vector<ZoomLevelChange> ZoomLevelVector;
- CONTENT_EXPORT static HostZoomMap* GetForBrowserContext(
+ // Extracts the URL from NavigationEntry, substituting the error page
+ // URL in the event that the error page is showing.
+ CONTENT_EXPORT static GURL GetURLFromEntry(const NavigationEntry* entry);
+
+ CONTENT_EXPORT static HostZoomMap* GetDefaultForBrowserContext(
BrowserContext* browser_context);
// Returns the current zoom level for the specified WebContents. May be
@@ -64,6 +70,11 @@ class HostZoomMap {
CONTENT_EXPORT static void SetZoomLevel(const WebContents* web_contents,
double level);
+ // Send an IPC to refresh any displayed error page's zoom levels. Needs to
+ // be called since error pages don't get loaded via the normal channel.
+ CONTENT_EXPORT static void SendErrorPageZoomLevelRefresh(
+ const WebContents* web_contents);
+
// Copy the zoom levels from the given map. Can only be called on the UI
// thread.
virtual void CopyFrom(HostZoomMap* copy) = 0;
diff --git a/chromium/content/public/browser/indexed_db_context.h b/chromium/content/public/browser/indexed_db_context.h
index 27c254caf7a..af469e33027 100644
--- a/chromium/content/public/browser/indexed_db_context.h
+++ b/chromium/content/public/browser/indexed_db_context.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_INDEXED_DB_CONTEXT_H_
#define CONTENT_PUBLIC_BROWSER_INDEXED_DB_CONTEXT_H_
+#include <string>
#include <vector>
#include "base/basictypes.h"
@@ -15,7 +16,6 @@
namespace base {
class SequencedTaskRunner;
-class TaskRunner;
}
namespace content {
@@ -25,7 +25,7 @@ namespace content {
class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> {
public:
// Only call the below methods by posting to this TaskRunner.
- virtual base::TaskRunner* TaskRunner() const = 0;
+ virtual base::SequencedTaskRunner* TaskRunner() const = 0;
// Methods used in response to QuotaManager requests.
virtual std::vector<IndexedDBInfo> GetAllOriginsInfo() = 0;
diff --git a/chromium/content/public/browser/invalidate_type.h b/chromium/content/public/browser/invalidate_type.h
index e352e013969..975bb304cf1 100644
--- a/chromium/content/public/browser/invalidate_type.h
+++ b/chromium/content/public/browser/invalidate_type.h
@@ -14,8 +14,9 @@ enum InvalidateTypes {
INVALIDATE_TYPE_TAB = 1 << 1, // The favicon, app icon, or crashed
// state changed.
INVALIDATE_TYPE_LOAD = 1 << 2, // The loading state has changed.
- INVALIDATE_TYPE_PAGE_ACTIONS = 1 << 3, // Page action icons have changed.
- INVALIDATE_TYPE_TITLE = 1 << 4, // The title changed.
+ INVALIDATE_TYPE_TITLE = 1 << 3, // The title changed.
+
+ INVALIDATE_TYPE_ALL = (1 << 4) - 1,
};
}
diff --git a/chromium/content/public/browser/load_from_memory_cache_details.cc b/chromium/content/public/browser/load_from_memory_cache_details.cc
index a6ce4e52aac..547d5468b60 100644
--- a/chromium/content/public/browser/load_from_memory_cache_details.cc
+++ b/chromium/content/public/browser/load_from_memory_cache_details.cc
@@ -13,7 +13,7 @@ LoadFromMemoryCacheDetails::LoadFromMemoryCacheDetails(
net::CertStatus cert_status,
const std::string& http_method,
const std::string& mime_type,
- ResourceType::Type resource_type)
+ ResourceType resource_type)
: url(url),
pid(pid),
cert_id(cert_id),
diff --git a/chromium/content/public/browser/load_from_memory_cache_details.h b/chromium/content/public/browser/load_from_memory_cache_details.h
index ac9b734a1a3..dfd1740149e 100644
--- a/chromium/content/public/browser/load_from_memory_cache_details.h
+++ b/chromium/content/public/browser/load_from_memory_cache_details.h
@@ -7,9 +7,9 @@
#include <string>
#include "base/basictypes.h"
+#include "content/public/common/resource_type.h"
#include "net/cert/cert_status_flags.h"
#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
namespace content {
@@ -20,7 +20,7 @@ struct LoadFromMemoryCacheDetails {
net::CertStatus cert_status,
const std::string& http_method,
const std::string& mime_type,
- ResourceType::Type resource_type);
+ ResourceType resource_type);
~LoadFromMemoryCacheDetails();
GURL url;
@@ -29,7 +29,7 @@ struct LoadFromMemoryCacheDetails {
net::CertStatus cert_status;
std::string http_method;
std::string mime_type;
- ResourceType::Type resource_type;
+ ResourceType resource_type;
};
} // namespace content
diff --git a/chromium/content/public/browser/load_notification_details.h b/chromium/content/public/browser/load_notification_details.h
index 70efdd8b226..22af84cab69 100644
--- a/chromium/content/public/browser/load_notification_details.h
+++ b/chromium/content/public/browser/load_notification_details.h
@@ -7,7 +7,7 @@
#include "base/time/time.h"
#include "content/public/browser/navigation_controller.h"
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace content {
@@ -17,7 +17,7 @@ namespace content {
// log page load metrics.
struct LoadNotificationDetails {
LoadNotificationDetails(const GURL& url,
- PageTransition origin,
+ ui::PageTransition origin,
base::TimeDelta load_time,
NavigationController* controller,
int session_index)
@@ -37,7 +37,7 @@ struct LoadNotificationDetails {
int session_index;
// The type of action that caused the load.
- PageTransition origin;
+ ui::PageTransition origin;
// The NavigationController for the load.
NavigationController* controller;
diff --git a/chromium/content/public/browser/media_device_id.cc b/chromium/content/public/browser/media_device_id.cc
index 2e405dd2183..c8e5f235999 100644
--- a/chromium/content/public/browser/media_device_id.cc
+++ b/chromium/content/public/browser/media_device_id.cc
@@ -24,7 +24,7 @@ std::string GetHMACForMediaDeviceID(const ResourceContext::SaltCallback& sc,
bool result = hmac.Init(security_origin.spec()) &&
hmac.Sign(raw_unique_id + salt, &digest[0], digest.size());
DCHECK(result);
- return StringToLowerASCII(base::HexEncode(&digest[0], digest.size()));
+ return base::StringToLowerASCII(base::HexEncode(&digest[0], digest.size()));
}
bool DoesMediaDeviceIDMatchHMAC(const ResourceContext::SaltCallback& sc,
diff --git a/chromium/content/public/browser/media_observer.h b/chromium/content/public/browser/media_observer.h
index dca5b85564f..6e7088b1c18 100644
--- a/chromium/content/public/browser/media_observer.h
+++ b/chromium/content/public/browser/media_observer.h
@@ -24,37 +24,16 @@ class MediaObserver {
// Called when a media request changes state.
virtual void OnMediaRequestStateChanged(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const GURL& security_origin,
- const MediaStreamDevice& device,
+ MediaStreamType stream_type,
MediaRequestState state) = 0;
// Called when an audio stream is being created.
virtual void OnCreatingAudioStream(int render_process_id,
int render_frame_id) = 0;
- // Called when an audio stream transitions into a playing state.
- // |power_read_callback| is a thread-safe callback, provided for polling the
- // current audio signal power level, and any copies/references to it must be
- // destroyed when OnAudioStreamStopped() is called.
- //
- // The callback returns the current power level (in dBFS units) and the clip
- // status (true if any part of the audio signal has clipped since the last
- // callback run). See media/audio/audio_power_monitor.h for more info.
- typedef base::Callback<std::pair<float, bool>()> ReadPowerAndClipCallback;
- virtual void OnAudioStreamPlaying(
- int render_process_id,
- int render_frame_id,
- int stream_id,
- const ReadPowerAndClipCallback& power_read_callback) = 0;
-
- // Called when an audio stream has stopped.
- virtual void OnAudioStreamStopped(
- int render_process_id,
- int render_frame_id,
- int stream_id) = 0;
-
protected:
virtual ~MediaObserver() {}
};
diff --git a/chromium/content/public/browser/navigation_controller.cc b/chromium/content/public/browser/navigation_controller.cc
index f0b3f46cc50..6a1e87f602a 100644
--- a/chromium/content/public/browser/navigation_controller.cc
+++ b/chromium/content/public/browser/navigation_controller.cc
@@ -11,7 +11,7 @@ namespace content {
NavigationController::LoadURLParams::LoadURLParams(const GURL& url)
: url(url),
load_type(LOAD_TYPE_DEFAULT),
- transition_type(PAGE_TRANSITION_LINK),
+ transition_type(ui::PAGE_TRANSITION_LINK),
frame_tree_node_id(-1),
is_renderer_initiated(false),
override_user_agent(UA_OVERRIDE_INHERIT),
diff --git a/chromium/content/public/browser/navigation_controller.h b/chromium/content/public/browser/navigation_controller.h
index 08ea0b9985d..abc6c7e6988 100644
--- a/chromium/content/public/browser/navigation_controller.h
+++ b/chromium/content/public/browser/navigation_controller.h
@@ -14,8 +14,8 @@
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/session_storage_namespace.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace base {
@@ -94,7 +94,7 @@ class NavigationController {
CONTENT_EXPORT static NavigationEntry* CreateNavigationEntry(
const GURL& url,
const Referrer& referrer,
- PageTransition transition,
+ ui::PageTransition transition,
bool is_renderer_initiated,
const std::string& extra_headers,
BrowserContext* browser_context);
@@ -109,7 +109,7 @@ class NavigationController {
// PageTransition for this load. See PageTransition for details.
// Note the default value in constructor below.
- PageTransition transition_type;
+ ui::PageTransition transition_type;
// The FrameTreeNode ID for the frame to navigate, or -1 for the main frame.
int64 frame_tree_node_id;
@@ -296,7 +296,7 @@ class NavigationController {
// request. Extra headers are separated by \n.
virtual void LoadURL(const GURL& url,
const Referrer& referrer,
- PageTransition type,
+ ui::PageTransition type,
const std::string& extra_headers) = 0;
// More general version of LoadURL. See comments in LoadURLParams for
@@ -340,9 +340,9 @@ class NavigationController {
// Removing of entries -------------------------------------------------------
- // Removes the entry at the specified |index|. This call discards any
- // transient entries. If the index is the last committed index or the pending
- // entry, this does nothing and returns false.
+ // Removes the entry at the specified |index|. If the index is the last
+ // committed index or the pending entry, this does nothing and returns false.
+ // Otherwise this call discards any transient or pending entries.
virtual bool RemoveEntryAtIndex(int index) = 0;
// Random --------------------------------------------------------------------
diff --git a/chromium/content/public/browser/navigation_entry.h b/chromium/content/public/browser/navigation_entry.h
index 6d69b0de4bc..de8ee49b7ad 100644
--- a/chromium/content/public/browser/navigation_entry.h
+++ b/chromium/content/public/browser/navigation_entry.h
@@ -11,9 +11,9 @@
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/page_type.h"
#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
class GURL;
@@ -110,8 +110,8 @@ class NavigationEntry {
// The transition type indicates what the user did to move to this page from
// the previous page.
- virtual void SetTransitionType(content::PageTransition transition_type) = 0;
- virtual content::PageTransition GetTransitionType() const = 0;
+ virtual void SetTransitionType(ui::PageTransition transition_type) = 0;
+ virtual ui::PageTransition GetTransitionType() const = 0;
// The user typed URL was the URL that the user initiated the navigation
// with, regardless of any redirects. This is used to generate keywords, for
diff --git a/chromium/content/public/browser/page_navigator.cc b/chromium/content/public/browser/page_navigator.cc
index dc9b3c53aaa..f585501e9e4 100644
--- a/chromium/content/public/browser/page_navigator.cc
+++ b/chromium/content/public/browser/page_navigator.cc
@@ -10,7 +10,7 @@ OpenURLParams::OpenURLParams(
const GURL& url,
const Referrer& referrer,
WindowOpenDisposition disposition,
- PageTransition transition,
+ ui::PageTransition transition,
bool is_renderer_initiated)
: url(url),
referrer(referrer),
@@ -28,7 +28,7 @@ OpenURLParams::OpenURLParams(
const Referrer& referrer,
int64 frame_tree_node_id,
WindowOpenDisposition disposition,
- PageTransition transition,
+ ui::PageTransition transition,
bool is_renderer_initiated)
: url(url),
referrer(referrer),
@@ -45,7 +45,7 @@ OpenURLParams::OpenURLParams()
: uses_post(false),
frame_tree_node_id(-1),
disposition(UNKNOWN),
- transition(PageTransitionFromInt(0)),
+ transition(ui::PAGE_TRANSITION_LINK),
is_renderer_initiated(false),
should_replace_current_entry(false),
user_gesture(true) {
diff --git a/chromium/content/public/browser/page_navigator.h b/chromium/content/public/browser/page_navigator.h
index 849d4ca68b1..0cdba29607c 100644
--- a/chromium/content/public/browser/page_navigator.h
+++ b/chromium/content/public/browser/page_navigator.h
@@ -15,8 +15,8 @@
#include "base/memory/ref_counted_memory.h"
#include "content/common/content_export.h"
#include "content/public/browser/global_request_id.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
+#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
@@ -28,13 +28,13 @@ struct CONTENT_EXPORT OpenURLParams {
OpenURLParams(const GURL& url,
const Referrer& referrer,
WindowOpenDisposition disposition,
- PageTransition transition,
+ ui::PageTransition transition,
bool is_renderer_initiated);
OpenURLParams(const GURL& url,
const Referrer& referrer,
int64 frame_tree_node_id,
WindowOpenDisposition disposition,
- PageTransition transition,
+ ui::PageTransition transition,
bool is_renderer_initiated);
~OpenURLParams();
@@ -66,7 +66,7 @@ struct CONTENT_EXPORT OpenURLParams {
WindowOpenDisposition disposition;
// The transition type of navigation.
- PageTransition transition;
+ ui::PageTransition transition;
// Whether this navigation is initiated by the renderer process.
bool is_renderer_initiated;
diff --git a/chromium/content/public/browser/permission_type.h b/chromium/content/public/browser/permission_type.h
new file mode 100644
index 00000000000..1a3b2617232
--- /dev/null
+++ b/chromium/content/public/browser/permission_type.h
@@ -0,0 +1,28 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_PERMISSION_TYPE_H_
+#define CONTENT_PUBLIC_BROWSER_PERMISSION_TYPE_H_
+
+namespace content {
+
+// This enum is also used for UMA purposes, so it needs to adhere to
+// the UMA guidelines.
+// Make sure you update histograms.xml if you add new permission types.
+// Never delete or reorder an entry; only add new entries
+// immediately before PERMISSION_NUM
+enum PermissionType {
+ PERMISSION_MIDI_SYSEX = 1,
+ PERMISSION_PUSH_MESSAGING = 2,
+ PERMISSION_NOTIFICATIONS = 3,
+ PERMISSION_GEOLOCATION = 4,
+ PERMISSION_PROTECTED_MEDIA = 5,
+
+ // Always keep this at the end.
+ PERMISSION_NUM,
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_PERMISSION_TYPE_H_
diff --git a/chromium/content/public/browser/push_messaging_service.h b/chromium/content/public/browser/push_messaging_service.h
index 37150db783b..d0cd124a823 100644
--- a/chromium/content/public/browser/push_messaging_service.h
+++ b/chromium/content/public/browser/push_messaging_service.h
@@ -9,6 +9,8 @@
#include "base/callback.h"
#include "content/common/content_export.h"
+#include "content/public/common/push_messaging_status.h"
+#include "third_party/WebKit/public/platform/WebPushPermissionStatus.h"
#include "url/gurl.h"
namespace content {
@@ -19,13 +21,26 @@ class CONTENT_EXPORT PushMessagingService {
public:
typedef base::Callback<void(const GURL& /* endpoint */,
const std::string& /* registration_id */,
- bool /* success */)>
+ PushRegistrationStatus /* status */)>
RegisterCallback;
virtual ~PushMessagingService() {}
- virtual void Register(const std::string& app_id,
+
+ // Register the given |sender_id| with GCM.
+ virtual void Register(const GURL& origin,
+ int64 service_worker_registration_id,
const std::string& sender_id,
+ int renderer_id,
+ int render_frame_id,
+ bool user_gesture,
const RegisterCallback& callback) = 0;
+
+ // Check whether the requester has permission to register for Push
+ // Messages
+ virtual blink::WebPushPermissionStatus GetPermissionStatus(
+ const GURL& requesting_origin,
+ int renderer_id,
+ int render_frame_id) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/quota_permission_context.h b/chromium/content/public/browser/quota_permission_context.h
index 5950f233ff5..e8d648983de 100644
--- a/chromium/content/public/browser/quota_permission_context.h
+++ b/chromium/content/public/browser/quota_permission_context.h
@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "content/public/common/storage_quota_params.h"
-#include "webkit/common/quota/quota_types.h"
+#include "storage/common/quota/quota_types.h"
class GURL;
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index ac6ba5aa8d7..53032b4ccf6 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -12,6 +12,7 @@
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/rect.h"
#include "url/gurl.h"
namespace base {
@@ -21,6 +22,7 @@ class Value;
namespace content {
class RenderProcessHost;
class RenderViewHost;
+class ServiceRegistry;
class SiteInstance;
// The interface provides a communication conduit with a frame in the renderer.
@@ -31,7 +33,7 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// Returns NULL if the IDs do not correspond to a live RenderFrameHost.
static RenderFrameHost* FromID(int render_process_id, int render_frame_id);
- virtual ~RenderFrameHost() {}
+ ~RenderFrameHost() override {}
// Returns the route id for this frame.
virtual int GetRoutingID() = 0;
@@ -71,9 +73,32 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
virtual void ExecuteJavaScript(const base::string16& javascript,
const JavaScriptResultCallback& callback) = 0;
+ // ONLY FOR TESTS: Same as above but adds a fake UserGestureIndicator around
+ // execution. (crbug.com/408426)
+ virtual void ExecuteJavaScriptForTests(const base::string16& javascript) = 0;
+
+ // Accessibility actions - these send a message to the RenderFrame
+ // to trigger an action on an accessibility object.
+ virtual void AccessibilitySetFocus(int acc_obj_id) = 0;
+ virtual void AccessibilityDoDefaultAction(int acc_obj_id) = 0;
+ virtual void AccessibilityScrollToMakeVisible(
+ int acc_obj_id, const gfx::Rect& subfocus) = 0;
+ virtual void AccessibilitySetTextSelection(
+ int acc_obj_id, int start_offset, int end_offset) = 0;
+
+ // This is called when the user has committed to the given find in page
+ // request (e.g. by pressing enter or by clicking on the next / previous
+ // result buttons). It triggers sending a native accessibility event on
+ // the result object on the page, navigating assistive technology to that
+ // result.
+ virtual void ActivateFindInPageResultForAccessibility(int request_id) = 0;
+
// Temporary until we get rid of RenderViewHost.
virtual RenderViewHost* GetRenderViewHost() = 0;
+ // Returns the ServiceRegistry for this frame.
+ virtual ServiceRegistry* GetServiceRegistry() = 0;
+
private:
// This interface should only be implemented inside content.
friend class RenderFrameHostImpl;
diff --git a/chromium/content/public/browser/render_process_host.h b/chromium/content/public/browser/render_process_host.h
index ee650367fcc..4ae7f3a282a 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -27,6 +27,7 @@ class BrowserContext;
class BrowserMessageFilter;
class RenderProcessHostObserver;
class RenderWidgetHost;
+class ServiceRegistry;
class StoragePartition;
struct GlobalRequestID;
@@ -55,7 +56,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// General functions ---------------------------------------------------------
- virtual ~RenderProcessHost() {}
+ ~RenderProcessHost() override {}
// Initialize the new renderer process, returning true on success. This must
// be called once before the object can be used, but can be called after
@@ -79,13 +80,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual void AddObserver(RenderProcessHostObserver* observer) = 0;
virtual void RemoveObserver(RenderProcessHostObserver* observer) = 0;
- // Called to wait for the next UpdateRect message for the specified render
- // widget. Returns true if successful, and the msg out-param will contain a
- // copy of the received UpdateRect message.
- virtual bool WaitForBackingStoreMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) = 0;
-
// Called when a received message cannot be decoded.
virtual void ReceivedBadMessage() = 0;
@@ -232,6 +226,16 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// have changed.
virtual void NotifyTimezoneChange() = 0;
+ // Returns the ServiceRegistry for this process.
+ virtual ServiceRegistry* GetServiceRegistry() = 0;
+
+ // PlzNavigate
+ // Returns the time the first call to Init completed successfully (after a new
+ // renderer process was created); further calls to Init won't change this
+ // value.
+ // Note: Do not use! Will disappear after PlzNavitate is completed.
+ virtual const base::TimeTicks& GetInitTimeForNavigationMetrics() const = 0;
+
// Static management functions -----------------------------------------------
// Flag to run the renderer in process. This is primarily
@@ -282,8 +286,8 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// A value of zero means to use the default heuristic.
static void SetMaxRendererProcessCount(size_t count);
- // Returns the current max number of renderer processes used by the content
- // module.
+ // Returns the current maximum number of renderer process hosts kept by the
+ // content module.
static size_t GetMaxRendererProcessCount();
};
diff --git a/chromium/content/public/browser/render_process_host_observer.h b/chromium/content/public/browser/render_process_host_observer.h
index 867bc7cc3a0..926b66d1dd3 100644
--- a/chromium/content/public/browser/render_process_host_observer.h
+++ b/chromium/content/public/browser/render_process_host_observer.h
@@ -23,7 +23,6 @@ class CONTENT_EXPORT RenderProcessHostObserver {
//
// Note that this is equivalent to WebContentsObserver::RenderProcessGone().
virtual void RenderProcessExited(RenderProcessHost* host,
- base::ProcessHandle handle,
base::TerminationStatus status,
int exit_code) {}
diff --git a/chromium/content/public/browser/render_view_host.h b/chromium/content/public/browser/render_view_host.h
index 559c0ef4c69..b3308d18aae 100644
--- a/chromium/content/public/browser/render_view_host.h
+++ b/chromium/content/public/browser/render_view_host.h
@@ -16,28 +16,23 @@
#include "third_party/WebKit/public/web/WebDragOperation.h"
class GURL;
-struct WebPreferences;
-
-namespace gfx {
-class Point;
-}
namespace base {
class FilePath;
class Value;
}
-namespace media {
-class AudioOutputController;
+namespace blink {
+struct WebMediaPlayerAction;
+struct WebPluginAction;
}
-namespace ui {
-struct SelectedFileInfo;
+namespace gfx {
+class Point;
}
-namespace blink {
-struct WebMediaPlayerAction;
-struct WebPluginAction;
+namespace media {
+class AudioOutputController;
}
namespace content {
@@ -48,6 +43,8 @@ class RenderViewHostDelegate;
class SessionStorageNamespace;
class SiteInstance;
struct DropData;
+struct FileChooserFileInfo;
+struct WebPreferences;
// A RenderViewHost is responsible for creating and talking to a RenderView
// object in a child process. It exposes a high level API to users, for things
@@ -70,7 +67,7 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// because RenderWidgetHost is a virtual base class.
static RenderViewHost* From(RenderWidgetHost* rwh);
- virtual ~RenderViewHost() {}
+ ~RenderViewHost() override {}
// Returns the main frame for this render view.
virtual RenderFrameHost* GetMainFrame() = 0;
@@ -163,7 +160,7 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// from a file chooser dialog for the form. |permissions| is the file
// selection mode in which the chooser dialog was created.
virtual void FilesSelectedInChooser(
- const std::vector<ui::SelectedFileInfo>& files,
+ const std::vector<content::FileChooserFileInfo>& files,
FileChooserParams::Mode permissions) = 0;
virtual RenderViewHostDelegate* GetDelegate() const = 0;
@@ -194,9 +191,14 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
// RenderViewHostDelegate.
virtual void SyncRendererPrefs() = 0;
- // Returns the current WebKit preferences.
+ // Returns the current WebKit preferences. Note: WebPreferences is cached, so
+ // this lookup will be fast
virtual WebPreferences GetWebkitPreferences() = 0;
+ // If any state that affects the webkit preferences changed, this method must
+ // be called. This triggers recomputing preferences.
+ virtual void OnWebkitPreferencesChanged() = 0;
+
// Passes a list of Webkit preferences to the renderer.
virtual void UpdateWebkitPreferences(const WebPreferences& prefs) = 0;
@@ -210,9 +212,6 @@ class CONTENT_EXPORT RenderViewHost : virtual public RenderWidgetHost {
virtual void GetAudioOutputControllers(
const GetAudioOutputControllersCallback& callback) const = 0;
- // Sets the mojo handle for WebUI pages.
- virtual void SetWebUIHandle(mojo::ScopedMessagePipeHandle handle) = 0;
-
// Notify the render view host to select the word around the caret.
virtual void SelectWordAroundCaret() = 0;
diff --git a/chromium/content/public/browser/render_widget_host.h b/chromium/content/public/browser/render_widget_host.h
index 30308736a76..e37c3cdce5e 100644
--- a/chromium/content/public/browser/render_widget_host.h
+++ b/chromium/content/public/browser/render_widget_host.h
@@ -114,7 +114,7 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// hosts.
static scoped_ptr<RenderWidgetHostIterator> GetRenderWidgetHosts();
- virtual ~RenderWidgetHost() {}
+ ~RenderWidgetHost() override {}
// Update the text direction of the focused input element and notify it to a
// renderer process.
@@ -181,7 +181,7 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
const gfx::Rect& src_rect,
const gfx::Size& accelerated_dst_size,
const base::Callback<void(bool, const SkBitmap&)>& callback,
- const SkBitmap::Config& bitmap_config) = 0;
+ const SkColorType color_type) = 0;
// Ensures that the view does not drop the backing store even when hidden.
virtual bool CanCopyFromBackingStore() = 0;
#if defined(OS_ANDROID)
@@ -189,42 +189,6 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
virtual void UnlockBackingStore() = 0;
#endif
- // Send a command to the renderer to turn on full accessibility.
- virtual void EnableFullAccessibilityMode() = 0;
-
- // Check whether this RenderWidget has full accessibility mode.
- virtual bool IsFullAccessibilityModeForTesting() = 0;
-
- // Send a command to the renderer to turn on tree only accessibility.
- virtual void EnableTreeOnlyAccessibilityMode() = 0;
-
- // Check whether this RenderWidget has tree-only accessibility mode.
- virtual bool IsTreeOnlyAccessibilityModeForTesting() = 0;
-
- // Relay a request from assistive technology to perform the default action
- // on a given node.
- virtual void AccessibilityDoDefaultAction(int object_id) = 0;
-
- // Relay a request from assistive technology to set focus to a given node.
- virtual void AccessibilitySetFocus(int object_id) = 0;
-
- // Relay a request from assistive technology to make a given object
- // visible by scrolling as many scrollable containers as necessary.
- // In addition, if it's not possible to make the entire object visible,
- // scroll so that the |subfocus| rect is visible at least. The subfocus
- // rect is in local coordinates of the object itself.
- virtual void AccessibilityScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) = 0;
-
- // Relay a request from assistive technology to move a given object
- // to a specific location, in the WebContents area coordinate space, i.e.
- // (0, 0) is the top-left corner of the WebContents.
- virtual void AccessibilityScrollToPoint(int acc_obj_id, gfx::Point point) = 0;
-
- // Relay a request from assistive technology to set text selection.
- virtual void AccessibilitySetTextSelection(
- int acc_obj_id, int start_offset, int end_offset) = 0;
-
// Forwards the given message to the renderer. These are called by
// the view when it has received a message.
virtual void ForwardMouseEvent(
@@ -234,8 +198,6 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
virtual void ForwardKeyboardEvent(
const NativeWebKeyboardEvent& key_event) = 0;
- virtual const gfx::Vector2d& GetLastScrollOffset() const = 0;
-
virtual RenderProcessHost* GetProcess() const = 0;
virtual int GetRoutingID() const = 0;
@@ -265,9 +227,6 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
virtual void SetIgnoreInputEvents(bool ignore_input_events) = 0;
- // Stops loading the page.
- virtual void Stop() = 0;
-
// Called to notify the RenderWidget that it has been resized.
virtual void WasResized() = 0;
@@ -290,7 +249,7 @@ class CONTENT_EXPORT RenderWidgetHost : public IPC::Sender {
// Get the screen info corresponding to this render widget.
virtual void GetWebScreenInfo(blink::WebScreenInfo* result) = 0;
- virtual SkBitmap::Config PreferredReadbackFormat() = 0;
+ virtual SkColorType PreferredReadbackFormat() = 0;
protected:
friend class RenderWidgetHostImpl;
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index fff83a76f75..6d97fd898ef 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -10,6 +10,7 @@
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/native_widget_types.h"
@@ -61,6 +62,9 @@ class CONTENT_EXPORT RenderWidgetHostView {
// screen space.
virtual void SetBounds(const gfx::Rect& rect) = 0;
+ // Retrieves the last known scroll position.
+ virtual gfx::Vector2dF GetLastScrollOffset() const = 0;
+
// Retrieves the native view used to contain plugins and identify the
// renderer in IPC messages.
virtual gfx::NativeView GetNativeView() const = 0;
@@ -101,9 +105,12 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Returns the currently selected text.
virtual base::string16 GetSelectedText() const = 0;
- // Subclasses should override this method to do what is appropriate to set
- // the background to be transparent or opaque.
- virtual void SetBackgroundOpaque(bool opaque) = 0;
+ // Subclasses should override this method to set the background color. |color|
+ // could be transparent or opaque.
+ virtual void SetBackgroundColor(SkColor color) = 0;
+ // Convenience method to fill the background layer with the default color by
+ // calling |SetBackgroundColor|.
+ virtual void SetBackgroundColorToDefault() = 0;
virtual bool GetBackgroundOpaque() = 0;
// Return value indicates whether the mouse is locked successfully or not.
@@ -135,12 +142,6 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Set the view's active state (i.e., tint state of controls).
virtual void SetActive(bool active) = 0;
- // Tells the view whether or not to accept first responder status. If |flag|
- // is true, the view does not accept first responder status and instead
- // manually becomes first responder when it receives a mouse down event. If
- // |flag| is false, the view participates in the key-view chain as normal.
- virtual void SetTakesFocusOnlyOnMouseDown(bool flag) = 0;
-
// Notifies the view that its enclosing window has changed visibility
// (minimized/unminimized, app hidden/unhidden, etc).
// TODO(stuartmorgan): This is a temporary plugin-specific workaround for
diff --git a/chromium/content/public/browser/render_widget_host_view_frame_subscriber.h b/chromium/content/public/browser/render_widget_host_view_frame_subscriber.h
index 0b658595caf..0b24ea1a9be 100644
--- a/chromium/content/public/browser/render_widget_host_view_frame_subscriber.h
+++ b/chromium/content/public/browser/render_widget_host_view_frame_subscriber.h
@@ -44,13 +44,14 @@ class RenderWidgetHostViewFrameSubscriber {
bool /* frame_captured */)> DeliverFrameCallback;
// Called when a new frame is going to be presented at time
- // |present_time|. Implementation can decide whether the current frame should
- // be captured or not.
+ // |present_time| with |damage_rect| being the region of the frame that has
+ // changed since the last frame. The implementation decides whether the
+ // current frame should be captured or not.
//
// Return true if the current frame should be captured. If so, |storage|
- // should will be set to hold an appropriately sized and allocated buffer
- // into which to copy the frame. The platform presenter will perform scaling
- // and color space conversion to fit into the output frame.
+ // will be set to hold an appropriately sized and allocated buffer into which
+ // to copy the frame. The platform presenter will perform scaling and color
+ // space conversion to fit into the output frame.
//
// Destination format is determined by |storage|, currently only
// media::VideoFrame::YV12 is supported. Platform layer will perform color
@@ -60,7 +61,8 @@ class RenderWidgetHostViewFrameSubscriber {
// platform layer to decide when to deliver a captured frame.
//
// Return false if the current frame should not be captured.
- virtual bool ShouldCaptureFrame(base::TimeTicks present_time,
+ virtual bool ShouldCaptureFrame(const gfx::Rect& damage_rect,
+ base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* callback) = 0;
};
diff --git a/chromium/content/public/browser/resource_context.h b/chromium/content/public/browser/resource_context.h
index 58eb298987b..27183f8ae68 100644
--- a/chromium/content/public/browser/resource_context.h
+++ b/chromium/content/public/browser/resource_context.h
@@ -16,10 +16,6 @@
class GURL;
-namespace appcache {
-class AppCacheService;
-}
-
namespace net {
class ClientCertStore;
class HostResolver;
@@ -29,6 +25,8 @@ class URLRequestContext;
namespace content {
+class AppCacheService;
+
// ResourceContext contains the relevant context information required for
// resource loading. It lives on the IO thread, although it is constructed on
// the UI thread. It must be destructed on the IO thread.
@@ -38,7 +36,7 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
virtual ~ResourceContext() {}
#else
ResourceContext();
- virtual ~ResourceContext();
+ ~ResourceContext() override;
#endif
virtual net::HostResolver* GetHostResolver() = 0;
@@ -58,16 +56,6 @@ class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
const GURL& url,
const base::Callback<void(scoped_ptr<net::KeygenHandler>)>& callback);
- // Returns true if microphone access is allowed for |origin|. Used to
- // determine what level of authorization is given to |origin| to access
- // resource metadata.
- virtual bool AllowMicAccess(const GURL& origin) = 0;
-
- // Returns true if web camera access is allowed for |origin|. Used to
- // determine what level of authorization is given to |origin| to access
- // resource metadata.
- virtual bool AllowCameraAccess(const GURL& origin) = 0;
-
// Returns a callback that can be invoked to get a random salt
// string that is used for creating media device IDs. The salt
// should be stored in the current user profile and should be reset
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
index 607b1af81d2..49eece0e0e9 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -4,16 +4,14 @@
#include "content/public/browser/resource_dispatcher_host_delegate.h"
-#include "content/public/browser/stream_handle.h"
+#include "content/public/browser/stream_info.h"
namespace content {
bool ResourceDispatcherHostDelegate::ShouldBeginRequest(
- int child_id,
- int route_id,
const std::string& method,
const GURL& url,
- ResourceType::Type resource_type,
+ ResourceType resource_type,
ResourceContext* resource_context) {
return true;
}
@@ -21,10 +19,8 @@ bool ResourceDispatcherHostDelegate::ShouldBeginRequest(
void ResourceDispatcherHostDelegate::RequestBeginning(
net::URLRequest* request,
ResourceContext* resource_context,
- appcache::AppCacheService* appcache_service,
- ResourceType::Type resource_type,
- int child_id,
- int route_id,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
ScopedVector<ResourceThrottle>* throttles) {
}
@@ -68,7 +64,7 @@ bool ResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
void ResourceDispatcherHostDelegate::OnStreamCreated(
net::URLRequest* request,
- scoped_ptr<content::StreamHandle> stream) {
+ scoped_ptr<content::StreamInfo> stream) {
}
void ResourceDispatcherHostDelegate::OnResponseStarted(
diff --git a/chromium/content/public/browser/resource_dispatcher_host_delegate.h b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
index cb8b683cfa4..7942df56898 100644
--- a/chromium/content/public/browser/resource_dispatcher_host_delegate.h
+++ b/chromium/content/public/browser/resource_dispatcher_host_delegate.h
@@ -10,23 +10,11 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
-#include "webkit/common/resource_type.h"
+#include "content/public/common/resource_type.h"
class GURL;
template <class T> class ScopedVector;
-namespace appcache {
-class AppCacheService;
-}
-
-namespace content {
-class ResourceContext;
-class ResourceThrottle;
-class StreamHandle;
-struct Referrer;
-struct ResourceResponse;
-}
-
namespace IPC {
class Sender;
}
@@ -38,48 +26,48 @@ class URLRequest;
namespace content {
+class AppCacheService;
+class ResourceContext;
class ResourceDispatcherHostLoginDelegate;
+class ResourceThrottle;
+struct Referrer;
+struct ResourceResponse;
+struct StreamInfo;
// Interface that the embedder provides to ResourceDispatcherHost to allow
// observing and modifying requests.
class CONTENT_EXPORT ResourceDispatcherHostDelegate {
public:
// Called when a request begins. Return false to abort the request.
- virtual bool ShouldBeginRequest(
- int child_id,
- int route_id,
- const std::string& method,
- const GURL& url,
- ResourceType::Type resource_type,
- ResourceContext* resource_context);
+ virtual bool ShouldBeginRequest(const std::string& method,
+ const GURL& url,
+ ResourceType resource_type,
+ ResourceContext* resource_context);
// Called after ShouldBeginRequest to allow the embedder to add resource
// throttles.
- virtual void RequestBeginning(
- net::URLRequest* request,
- ResourceContext* resource_context,
- appcache::AppCacheService* appcache_service,
- ResourceType::Type resource_type,
- int child_id,
- int route_id,
- ScopedVector<ResourceThrottle>* throttles);
+ virtual void RequestBeginning(net::URLRequest* request,
+ ResourceContext* resource_context,
+ AppCacheService* appcache_service,
+ ResourceType resource_type,
+ ScopedVector<ResourceThrottle>* throttles);
// Allows an embedder to add additional resource handlers for a download.
// |must_download| is set if the request must be handled as a download.
- virtual void DownloadStarting(
- net::URLRequest* request,
- ResourceContext* resource_context,
- int child_id,
- int route_id,
- int request_id,
- bool is_content_initiated,
- bool must_download,
- ScopedVector<ResourceThrottle>* throttles);
+ virtual void DownloadStarting(net::URLRequest* request,
+ ResourceContext* resource_context,
+ int child_id,
+ int route_id,
+ int request_id,
+ bool is_content_initiated,
+ bool must_download,
+ ScopedVector<ResourceThrottle>* throttles);
// Creates a ResourceDispatcherHostLoginDelegate that asks the user for a
// username and password.
virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
- net::AuthChallengeInfo* auth_info, net::URLRequest* request);
+ net::AuthChallengeInfo* auth_info,
+ net::URLRequest* request);
// Launches the url for the given tab. Returns true if an attempt to handle
// the url was made, e.g. by launching an app. Note that this does not
@@ -90,8 +78,8 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
// Returns true if we should force the given resource to be downloaded.
// Otherwise, the content layer decides.
- virtual bool ShouldForceDownloadResource(
- const GURL& url, const std::string& mime_type);
+ virtual bool ShouldForceDownloadResource(const GURL& url,
+ const std::string& mime_type);
// Returns true and sets |origin| if a Stream should be created for the
// resource.
@@ -104,31 +92,27 @@ class CONTENT_EXPORT ResourceDispatcherHostDelegate {
// If the stream will be rendered in a BrowserPlugin, |payload| will contain
// the data that should be given to the old ResourceHandler to forward to the
// renderer process.
- virtual bool ShouldInterceptResourceAsStream(
- net::URLRequest* request,
- const std::string& mime_type,
- GURL* origin,
- std::string* payload);
+ virtual bool ShouldInterceptResourceAsStream(net::URLRequest* request,
+ const std::string& mime_type,
+ GURL* origin,
+ std::string* payload);
// Informs the delegate that a Stream was created. The Stream can be read from
// the blob URL of the Stream, but can only be read once.
- virtual void OnStreamCreated(
- net::URLRequest* request,
- scoped_ptr<content::StreamHandle> stream);
+ virtual void OnStreamCreated(net::URLRequest* request,
+ scoped_ptr<content::StreamInfo> stream);
// Informs the delegate that a response has started.
- virtual void OnResponseStarted(
- net::URLRequest* request,
- ResourceContext* resource_context,
- ResourceResponse* response,
- IPC::Sender* sender);
+ virtual void OnResponseStarted(net::URLRequest* request,
+ ResourceContext* resource_context,
+ ResourceResponse* response,
+ IPC::Sender* sender);
// Informs the delegate that a request has been redirected.
- virtual void OnRequestRedirected(
- const GURL& redirect_url,
- net::URLRequest* request,
- ResourceContext* resource_context,
- ResourceResponse* response);
+ virtual void OnRequestRedirected(const GURL& redirect_url,
+ net::URLRequest* request,
+ ResourceContext* resource_context,
+ ResourceResponse* response);
// Notification that a request has completed.
virtual void RequestComplete(net::URLRequest* url_request);
diff --git a/chromium/content/public/browser/resource_request_details.cc b/chromium/content/public/browser/resource_request_details.cc
index a5b91b90d05..ad5f47e1734 100644
--- a/chromium/content/public/browser/resource_request_details.cc
+++ b/chromium/content/public/browser/resource_request_details.cc
@@ -4,7 +4,6 @@
#include "content/public/browser/resource_request_details.h"
-#include "content/browser/worker_host/worker_service_impl.h"
#include "content/public/browser/resource_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
@@ -29,19 +28,7 @@ ResourceRequestDetails::ResourceRequestDetails(const net::URLRequest* request,
http_response_code =
request->response_info().headers.get() ?
request->response_info().headers.get()->response_code() : -1;
-
- // If request is from the worker process on behalf of a renderer, use
- // the renderer process id, since it consumes the notification response
- // such as ssl state etc.
- // TODO(atwilson): need to notify all associated renderers in the case
- // of ssl state change (http://crbug.com/25357). For now, just notify
- // the first one (works for dedicated workers and shared workers with
- // a single process).
- int worker_render_frame_id;
- if (!WorkerServiceImpl::GetInstance()->GetRendererForWorker(
- info->GetChildID(), &origin_child_id, &worker_render_frame_id)) {
- origin_child_id = info->GetChildID();
- }
+ origin_child_id = info->GetChildID();
}
ResourceRequestDetails::~ResourceRequestDetails() {}
diff --git a/chromium/content/public/browser/resource_request_details.h b/chromium/content/public/browser/resource_request_details.h
index 0127fefef22..f776f4da766 100644
--- a/chromium/content/public/browser/resource_request_details.h
+++ b/chromium/content/public/browser/resource_request_details.h
@@ -7,11 +7,11 @@
#include <string>
+#include "content/public/common/resource_type.h"
#include "net/base/host_port_pair.h"
#include "net/cert/cert_status_flags.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
-#include "webkit/common/resource_type.h"
namespace net {
class URLRequest;
@@ -37,7 +37,7 @@ struct ResourceRequestDetails {
net::URLRequestStatus status;
int ssl_cert_id;
net::CertStatus ssl_cert_status;
- ResourceType::Type resource_type;
+ ResourceType resource_type;
net::HostPortPair socket_address;
int render_frame_id;
// HTTP response code. See HttpResponseHeaders::response_code().
@@ -50,7 +50,7 @@ struct ResourceRedirectDetails : public ResourceRequestDetails {
ResourceRedirectDetails(const net::URLRequest* request,
int cert_id,
const GURL& new_url);
- virtual ~ResourceRedirectDetails();
+ ~ResourceRedirectDetails() override;
// The URL to which we are being redirected.
GURL new_url;
diff --git a/chromium/content/public/browser/resource_request_info.h b/chromium/content/public/browser/resource_request_info.h
index f0badee0f7c..00be9c7ceb9 100644
--- a/chromium/content/public/browser/resource_request_info.h
+++ b/chromium/content/public/browser/resource_request_info.h
@@ -7,10 +7,10 @@
#include "base/basictypes.h"
#include "content/common/content_export.h"
-#include "content/public/common/page_transition_types.h"
+#include "content/public/common/resource_type.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
-#include "webkit/common/resource_type.h"
+#include "ui/base/page_transition_types.h"
namespace net {
class URLRequest;
@@ -30,14 +30,13 @@ class ResourceRequestInfo {
// Allocates a new, dummy ResourceRequestInfo and associates it with the
// given URLRequest.
// NOTE: Add more parameters if you need to initialize other fields.
- CONTENT_EXPORT static void AllocateForTesting(
- net::URLRequest* request,
- ResourceType::Type resource_type,
- ResourceContext* context,
- int render_process_id,
- int render_view_id,
- int render_frame_id,
- bool is_async);
+ CONTENT_EXPORT static void AllocateForTesting(net::URLRequest* request,
+ ResourceType resource_type,
+ ResourceContext* context,
+ int render_process_id,
+ int render_view_id,
+ int render_frame_id,
+ bool is_async);
// Returns the associated RenderFrame for a given process. Returns false, if
// there is no associated RenderFrame. This method does not rely on the
@@ -82,7 +81,7 @@ class ResourceRequestInfo {
virtual int GetParentRenderFrameID() const = 0;
// Returns the associated resource type.
- virtual ResourceType::Type GetResourceType() const = 0;
+ virtual ResourceType GetResourceType() const = 0;
// Returns the process type that initiated this request.
virtual int GetProcessType() const = 0;
@@ -95,10 +94,17 @@ class ResourceRequestInfo {
virtual blink::WebPageVisibilityState GetVisibilityState() const = 0;
// Returns the associated page transition type.
- virtual PageTransition GetPageTransition() const = 0;
+ virtual ui::PageTransition GetPageTransition() const = 0;
// True if the request was initiated by a user action (like a tap to follow
// a link).
+ //
+ // Note that a false value does not mean the request was not initiated by a
+ // user gesture. Also note that the fact that a user gesture was active
+ // while the request was created does not imply that the user consciously
+ // wanted this request to happen nor is aware of it.
+ //
+ // DO NOT BASE SECURITY DECISIONS ON THIS FLAG!
virtual bool HasUserGesture() const = 0;
// True if ResourceController::CancelAndIgnore() was called. For example,
diff --git a/chromium/content/public/browser/resource_throttle.h b/chromium/content/public/browser/resource_throttle.h
index 469782d9dfd..ec176bc907b 100644
--- a/chromium/content/public/browser/resource_throttle.h
+++ b/chromium/content/public/browser/resource_throttle.h
@@ -23,9 +23,9 @@ class ResourceThrottle {
virtual ~ResourceThrottle() {}
virtual void WillStartRequest(bool* defer) {}
+ virtual void WillStartUsingNetwork(bool* defer) {}
virtual void WillRedirectRequest(const GURL& new_url, bool* defer) {}
virtual void WillProcessResponse(bool* defer) {}
- virtual void OnBeforeNetworkStart(bool* defer) {}
// Returns the name of the throttle, as a UTF-8 C-string, for logging
// purposes. NULL is not allowed. Caller does *not* take ownership of the
diff --git a/chromium/content/public/browser/screen_orientation_delegate.h b/chromium/content/public/browser/screen_orientation_delegate.h
new file mode 100644
index 00000000000..243d2c3659b
--- /dev/null
+++ b/chromium/content/public/browser/screen_orientation_delegate.h
@@ -0,0 +1,43 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_DELEGATE_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+
+namespace content {
+
+class WebContents;
+
+// Can be implemented to provide platform specific functionality for
+// ScreenOrientationProvider.
+class CONTENT_EXPORT ScreenOrientationDelegate {
+ public:
+ ScreenOrientationDelegate() {};
+ virtual ~ScreenOrientationDelegate() {}
+
+ // Returns true if the tab must be fullscreen in order for
+ // ScreenOrientationProvider to respond to requests.
+ virtual bool FullScreenRequired(WebContents* web_contents) = 0;
+
+ // Lock display to the given orientation.
+ virtual void Lock(blink::WebScreenOrientationLockType lock_orientation) = 0;
+
+ // Are ScreenOrientationProvider requests currently supported by the platform.
+ virtual bool ScreenOrientationProviderSupported() = 0;
+
+ // Unlocks the display, allowing hardware rotation to resume.
+ virtual void Unlock() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegate);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_DELEGATE_H_
+
diff --git a/chromium/content/public/browser/screen_orientation_dispatcher_host.h b/chromium/content/public/browser/screen_orientation_dispatcher_host.h
new file mode 100644
index 00000000000..c0f8bc0268f
--- /dev/null
+++ b/chromium/content/public/browser/screen_orientation_dispatcher_host.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_DISPATCHER_HOST_H_
+#define CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_DISPATCHER_HOST_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationError.h"
+
+namespace content {
+
+// ScreenOrientationDispatcherHost receives lock and unlock requests from the
+// RenderFrames and dispatch them to the ScreenOrientationProvider. It also
+// make sure that the right RenderFrame get replied for each lock request.
+class CONTENT_EXPORT ScreenOrientationDispatcherHost {
+ public:
+ virtual ~ScreenOrientationDispatcherHost() {}
+
+ // Notifies that the lock with the given |request_id| has succeeded.
+ // The renderer process will be notified that the lock succeeded only if
+ // |request_id| matches the current lock information.
+ virtual void NotifyLockSuccess(int request_id) = 0;
+
+ // Notifies that the lock with the given |request_id| has failed.
+ // The renderer process will be notified that the lock succeeded only if
+ // |request_id| matches the current lock information.
+ virtual void NotifyLockError(int request_id,
+ blink::WebLockOrientationError error) = 0;
+
+ virtual void OnOrientationChange() = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_DISPATCHER_HOST_H_
diff --git a/chromium/content/public/browser/screen_orientation_provider.cc b/chromium/content/public/browser/screen_orientation_provider.cc
new file mode 100644
index 00000000000..35a07eeffde
--- /dev/null
+++ b/chromium/content/public/browser/screen_orientation_provider.cc
@@ -0,0 +1,209 @@
+// Copyright 2014 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 "content/public/browser/screen_orientation_provider.h"
+
+#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/screen_orientation_delegate.h"
+#include "content/public/browser/screen_orientation_dispatcher_host.h"
+#include "content/public/browser/web_contents.h"
+#include "third_party/WebKit/public/platform/WebLockOrientationError.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+
+namespace content {
+
+ScreenOrientationDelegate* ScreenOrientationProvider::delegate_ = NULL;
+
+ScreenOrientationProvider::LockInformation::LockInformation(int request_id,
+ blink::WebScreenOrientationLockType lock)
+ : request_id(request_id),
+ lock(lock) {
+}
+
+ScreenOrientationProvider::ScreenOrientationProvider(
+ ScreenOrientationDispatcherHost* dispatcher_host,
+ WebContents* web_contents)
+ : WebContentsObserver(web_contents),
+ dispatcher_(dispatcher_host),
+ lock_applied_(false) {
+}
+
+ScreenOrientationProvider::~ScreenOrientationProvider() {
+}
+
+void ScreenOrientationProvider::LockOrientation(int request_id,
+ blink::WebScreenOrientationLockType lock_orientation) {
+
+ if (!delegate_ || !delegate_->ScreenOrientationProviderSupported()) {
+ dispatcher_->NotifyLockError(request_id,
+ blink::WebLockOrientationErrorNotAvailable);
+ return;
+ }
+
+ if (delegate_->FullScreenRequired(web_contents())) {
+ RenderViewHost* rvh = web_contents()->GetRenderViewHost();
+ if (!rvh) {
+ dispatcher_->NotifyLockError(request_id,
+ blink::WebLockOrientationErrorCanceled);
+ return;
+ }
+ RenderViewHostDelegate* rvhd = rvh->GetDelegate();
+ if (!rvhd) {
+ dispatcher_->NotifyLockError(request_id,
+ blink::WebLockOrientationErrorCanceled);
+ return;
+ }
+ if (!rvhd->IsFullscreenForCurrentTab()) {
+ dispatcher_->NotifyLockError(request_id,
+ blink::WebLockOrientationErrorFullScreenRequired);
+ return;
+ }
+ }
+
+ if (lock_orientation == blink::WebScreenOrientationLockNatural) {
+ lock_orientation = GetNaturalLockType();
+ if (lock_orientation == blink::WebScreenOrientationLockDefault) {
+ // We are in a broken state, let's pretend we got canceled.
+ dispatcher_->NotifyLockError(request_id,
+ blink::WebLockOrientationErrorCanceled);
+ return;
+ }
+ }
+
+ lock_applied_ = true;
+ delegate_->Lock(lock_orientation);
+
+ // If two calls happen close to each other some platforms will ignore the
+ // first. A successful lock will be once orientation matches the latest
+ // request.
+ pending_lock_.reset();
+
+ // If the orientation we are locking to matches the current orientation, we
+ // should succeed immediately.
+ if (LockMatchesCurrentOrientation(lock_orientation)) {
+ dispatcher_->NotifyLockSuccess(request_id);
+ return;
+ }
+
+ pending_lock_.reset(new LockInformation(request_id, lock_orientation));
+}
+
+void ScreenOrientationProvider::UnlockOrientation() {
+ if (!lock_applied_ || !delegate_)
+ return;
+
+ delegate_->Unlock();
+
+ lock_applied_ = false;
+ pending_lock_.reset();
+}
+
+void ScreenOrientationProvider::OnOrientationChange() {
+ if (!pending_lock_.get())
+ return;
+
+ if (LockMatchesCurrentOrientation(pending_lock_->lock)) {
+ dispatcher_->NotifyLockSuccess(pending_lock_->request_id);
+ pending_lock_.reset();
+ }
+}
+
+void ScreenOrientationProvider::SetDelegate(
+ ScreenOrientationDelegate* delegate) {
+ delegate_ = delegate;
+}
+
+void ScreenOrientationProvider::DidToggleFullscreenModeForTab(
+ bool entered_fullscreen) {
+ if (!lock_applied_ || !delegate_)
+ return;
+
+ // If fullscreen is not required in order to lock orientation, don't unlock
+ // when fullscreen state changes.
+ if (!delegate_->FullScreenRequired(web_contents()))
+ return;
+
+ DCHECK(!entered_fullscreen);
+ UnlockOrientation();
+}
+
+blink::WebScreenOrientationLockType
+ ScreenOrientationProvider::GetNaturalLockType() const {
+ RenderWidgetHost* rwh = web_contents()->GetRenderViewHost();
+ if (!rwh)
+ return blink::WebScreenOrientationLockDefault;
+
+ blink::WebScreenInfo screen_info;
+ rwh->GetWebScreenInfo(&screen_info);
+
+ switch (screen_info.orientationType) {
+ case blink::WebScreenOrientationPortraitPrimary:
+ case blink::WebScreenOrientationPortraitSecondary:
+ if (screen_info.orientationAngle == 0 ||
+ screen_info.orientationAngle == 180) {
+ return blink::WebScreenOrientationLockPortraitPrimary;
+ }
+ return blink::WebScreenOrientationLockLandscapePrimary;
+ case blink::WebScreenOrientationLandscapePrimary:
+ case blink::WebScreenOrientationLandscapeSecondary:
+ if (screen_info.orientationAngle == 0 ||
+ screen_info.orientationAngle == 180) {
+ return blink::WebScreenOrientationLockLandscapePrimary;
+ }
+ return blink::WebScreenOrientationLockPortraitPrimary;
+ case blink::WebScreenOrientationUndefined:
+ NOTREACHED();
+ return blink::WebScreenOrientationLockDefault;
+ }
+
+ NOTREACHED();
+ return blink::WebScreenOrientationLockDefault;
+}
+
+bool ScreenOrientationProvider::LockMatchesCurrentOrientation(
+ blink::WebScreenOrientationLockType lock) {
+ RenderWidgetHost* rwh = web_contents()->GetRenderViewHost();
+ if (!rwh)
+ return false;
+
+ blink::WebScreenInfo screen_info;
+ rwh->GetWebScreenInfo(&screen_info);
+
+ switch (lock) {
+ case blink::WebScreenOrientationLockPortraitPrimary:
+ return screen_info.orientationType ==
+ blink::WebScreenOrientationPortraitPrimary;
+ case blink::WebScreenOrientationLockPortraitSecondary:
+ return screen_info.orientationType ==
+ blink::WebScreenOrientationPortraitSecondary;
+ case blink::WebScreenOrientationLockLandscapePrimary:
+ return screen_info.orientationType ==
+ blink::WebScreenOrientationLandscapePrimary;
+ case blink::WebScreenOrientationLockLandscapeSecondary:
+ return screen_info.orientationType ==
+ blink::WebScreenOrientationLandscapeSecondary;
+ case blink::WebScreenOrientationLockLandscape:
+ return screen_info.orientationType ==
+ blink::WebScreenOrientationLandscapePrimary ||
+ screen_info.orientationType ==
+ blink::WebScreenOrientationLandscapeSecondary;
+ case blink::WebScreenOrientationLockPortrait:
+ return screen_info.orientationType ==
+ blink::WebScreenOrientationPortraitPrimary ||
+ screen_info.orientationType ==
+ blink::WebScreenOrientationPortraitSecondary;
+ case blink::WebScreenOrientationLockAny:
+ return true;
+ case blink::WebScreenOrientationLockNatural:
+ case blink::WebScreenOrientationLockDefault:
+ NOTREACHED();
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/screen_orientation_provider.h b/chromium/content/public/browser/screen_orientation_provider.h
new file mode 100644
index 00000000000..7879d3455d7
--- /dev/null
+++ b/chromium/content/public/browser/screen_orientation_provider.h
@@ -0,0 +1,80 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_PROVIDER_H_
+#define CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+
+namespace content {
+
+class ScreenOrientationDelegate;
+class ScreenOrientationDispatcherHost;
+class WebContents;
+
+// Handles screen orientation lock/unlock. Platforms which wish to provide
+// custom implementations can provide a factory for ScreenOrientationDelegate.
+class CONTENT_EXPORT ScreenOrientationProvider : public WebContentsObserver {
+ public:
+ ScreenOrientationProvider(ScreenOrientationDispatcherHost* dispatcher_host,
+ WebContents* web_contents);
+ ~ScreenOrientationProvider() override;
+
+ // Lock the screen orientation to |orientations|.
+ void LockOrientation(int request_id,
+ blink::WebScreenOrientationLockType lock_orientation);
+
+ // Unlock the screen orientation.
+ void UnlockOrientation();
+
+ // Inform about a screen orientation update. It is called to let the provider
+ // know if a lock has been resolved.
+ void OnOrientationChange();
+
+ // Provide a delegate which creates delegates for platform implementations.
+ // The delegate is not owned by ScreenOrientationProvider.
+ static void SetDelegate(ScreenOrientationDelegate* delegate_);
+
+ // WebContentsObserver
+ void DidToggleFullscreenModeForTab(bool entered_fullscreen) override;
+
+ private:
+ struct LockInformation {
+ LockInformation(int request_id, blink::WebScreenOrientationLockType lock);
+ int request_id;
+ blink::WebScreenOrientationLockType lock;
+ };
+
+ // Returns the lock type that should be associated with 'natural' lock.
+ // Returns WebScreenOrientationLockDefault if the natural lock type can't be
+ // found.
+ blink::WebScreenOrientationLockType GetNaturalLockType() const;
+
+ // Whether the passed |lock| matches the current orientation. In other words,
+ // whether the orientation will need to change to match the |lock|.
+ bool LockMatchesCurrentOrientation(blink::WebScreenOrientationLockType lock);
+
+ // Not owned, responsible for platform implementations.
+ static ScreenOrientationDelegate* delegate_;
+
+ // ScreenOrientationDispatcherHost owns ScreenOrientationProvider.
+ ScreenOrientationDispatcherHost* dispatcher_;
+
+ // Whether the ScreenOrientationProvider currently has a lock applied.
+ bool lock_applied_;
+
+ // Locks that require orientation changes are not completed until
+ // OnOrientationChange.
+ scoped_ptr<LockInformation> pending_lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SCREEN_ORIENTATION_PROVIDER_H_
diff --git a/chromium/content/public/browser/service_worker_context.h b/chromium/content/public/browser/service_worker_context.h
index 2d0805e9b99..94ab73f67e2 100644
--- a/chromium/content/public/browser/service_worker_context.h
+++ b/chromium/content/public/browser/service_worker_context.h
@@ -5,14 +5,17 @@
#ifndef CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CONTEXT_H_
#define CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CONTEXT_H_
+#include <set>
+#include <string>
+
#include "base/basictypes.h"
#include "base/callback_forward.h"
+#include "content/public/browser/service_worker_usage_info.h"
#include "url/gurl.h"
namespace content {
-// Represents the per-StoragePartition ServiceWorker data. Must be used from
-// the UI thread.
+// Represents the per-StoragePartition ServiceWorker data.
class ServiceWorkerContext {
public:
// https://rawgithub.com/slightlyoff/ServiceWorker/master/spec/service_worker/index.html#url-scope:
@@ -21,6 +24,18 @@ class ServiceWorkerContext {
typedef base::Callback<void(bool success)> ResultCallback;
+ typedef base::Callback<void(const std::vector<ServiceWorkerUsageInfo>&
+ usage_info)> GetUsageInfoCallback;
+
+ // Registers the header name which should not be passed to the ServiceWorker.
+ // Must be called from the IO thread.
+ CONTENT_EXPORT static void AddExcludedHeadersForFetchEvent(
+ const std::set<std::string>& header_names);
+
+ // Returns true if the header name should not be passed to the ServiceWorker.
+ // Must be called from the IO thread.
+ static bool IsExcludedHeaderNameForFetchEvent(const std::string& header_name);
+
// Equivalent to calling navigator.serviceWorker.register(script_url, {scope:
// pattern}) from a renderer, except that |pattern| is an absolute URL instead
// of relative to some current origin. |callback| is passed true when the JS
@@ -49,10 +64,9 @@ class ServiceWorkerContext {
// TODO(jyasskin): Provide a way to SendMessage to a Scope.
- // Synchronously releases all of the RenderProcessHosts that have Service
- // Workers running inside them, and prevents any new Service Worker instances
- // from starting up.
- virtual void Terminate() = 0;
+ // Methods used in response to browsing data and quota manager requests.
+ virtual void GetAllOriginsInfo(const GetUsageInfoCallback& callback) = 0;
+ virtual void DeleteForOrigin(const GURL& origin_url) = 0;
protected:
ServiceWorkerContext() {}
diff --git a/chromium/content/public/browser/service_worker_usage_info.cc b/chromium/content/public/browser/service_worker_usage_info.cc
new file mode 100644
index 00000000000..7ed49860d1e
--- /dev/null
+++ b/chromium/content/public/browser/service_worker_usage_info.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 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 "content/public/browser/service_worker_usage_info.h"
+
+namespace content {
+
+ServiceWorkerUsageInfo::ServiceWorkerUsageInfo(const GURL& origin,
+ const std::vector<GURL>& scopes)
+ : origin(origin), scopes(scopes), total_size_bytes(0) {
+}
+
+ServiceWorkerUsageInfo::ServiceWorkerUsageInfo(const GURL& origin)
+ : origin(origin), total_size_bytes(0) {
+}
+
+ServiceWorkerUsageInfo::ServiceWorkerUsageInfo() : total_size_bytes(0) {
+}
+
+ServiceWorkerUsageInfo::~ServiceWorkerUsageInfo() {
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/service_worker_usage_info.h b/chromium/content/public/browser/service_worker_usage_info.h
new file mode 100644
index 00000000000..9cc883a62b2
--- /dev/null
+++ b/chromium/content/public/browser/service_worker_usage_info.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_USAGE_INFO_H_
+#define CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_USAGE_INFO_H_
+
+#include <vector>
+
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Used to report per-origin storage info for registered Service Workers.
+class CONTENT_EXPORT ServiceWorkerUsageInfo {
+ public:
+ ServiceWorkerUsageInfo(const GURL& origin, const std::vector<GURL>& scopes);
+ ServiceWorkerUsageInfo(const GURL& origin);
+ ServiceWorkerUsageInfo();
+ ~ServiceWorkerUsageInfo();
+
+ // The origin this object is describing.
+ GURL origin;
+
+ // The set of all Service Worker registrations within this origin;
+ // a registration is a 'scope' - a URL with optional wildcard.
+ std::vector<GURL> scopes;
+
+ // The total size, including resources.
+ int64_t total_size_bytes;
+
+ // TODO(jsbell): Add last modified time.
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_USAGE_INFO_H_
diff --git a/chromium/content/public/browser/site_instance.h b/chromium/content/public/browser/site_instance.h
index 9c9e6633864..61d593da3e0 100644
--- a/chromium/content/public/browser/site_instance.h
+++ b/chromium/content/public/browser/site_instance.h
@@ -135,8 +135,11 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// the same process if they can communicate with other via JavaScript.
// (e.g., docs.google.com and mail.google.com have DOM access to each other
// if they both set their document.domain properties to google.com.)
+ // Note that if the destination is a blank page, we consider that to be part
+ // of the same web site for the purposes for process assignment.
static bool IsSameWebSite(content::BrowserContext* browser_context,
- const GURL& url1, const GURL& url2);
+ const GURL& src_url,
+ const GURL& dest_url);
// Returns the site for the given URL, which includes only the scheme and
// registered domain. Returns an empty GURL if the URL has no host.
diff --git a/chromium/content/public/browser/speech_recognition_session_context.cc b/chromium/content/public/browser/speech_recognition_session_context.cc
index 9b6575b4f0e..b185be8f6c3 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.cc
+++ b/chromium/content/public/browser/speech_recognition_session_context.cc
@@ -11,6 +11,7 @@ namespace content {
SpeechRecognitionSessionContext::SpeechRecognitionSessionContext()
: render_process_id(0),
render_view_id(0),
+ render_frame_id(0),
guest_render_view_id(MSG_ROUTING_NONE),
embedder_render_process_id(0),
embedder_render_view_id(MSG_ROUTING_NONE),
diff --git a/chromium/content/public/browser/speech_recognition_session_context.h b/chromium/content/public/browser/speech_recognition_session_context.h
index d092a5daf04..532a4e47e65 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.h
+++ b/chromium/content/public/browser/speech_recognition_session_context.h
@@ -26,6 +26,7 @@ struct CONTENT_EXPORT SpeechRecognitionSessionContext {
int render_process_id;
int render_view_id;
+ int render_frame_id;
// Browser plugin guest's render view id, if this context represents a speech
// recognition request from an embedder on behalf of the guest. This is used
diff --git a/chromium/content/public/browser/ssl_host_state_delegate.h b/chromium/content/public/browser/ssl_host_state_delegate.h
new file mode 100644
index 00000000000..4666471a148
--- /dev/null
+++ b/chromium/content/public/browser/ssl_host_state_delegate.h
@@ -0,0 +1,63 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_SSL_HOST_STATE_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_SSL_HOST_STATE_DELEGATE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "content/common/content_export.h"
+#include "net/cert/x509_certificate.h"
+
+namespace content {
+
+// The SSLHostStateDelegate encapulates the host-specific state for SSL errors.
+// For example, SSLHostStateDelegate remembers whether the user has whitelisted
+// a particular broken cert for use with particular host. We separate this
+// state from the SSLManager because this state is shared across many navigation
+// controllers.
+//
+// SSLHostStateDelegate may be implemented by the embedder to provide a storage
+// strategy for certificate decisions or it may be left unimplemented to use a
+// default strategy of not remembering decisions at all.
+class SSLHostStateDelegate {
+ public:
+ // The judgements that can be reached by a user for invalid certificates.
+ enum CertJudgment {
+ DENIED,
+ ALLOWED
+ };
+
+ // Records that |cert| is permitted to be used for |host| in the future, for
+ // a specified |error| type.
+ virtual void AllowCert(const std::string&,
+ const net::X509Certificate& cert,
+ net::CertStatus error) = 0;
+
+ // Clear all allow preferences.
+ virtual void Clear() = 0;
+
+ // Queries whether |cert| is allowed for |host| and |error|. Returns true in
+ // |expired_previous_decision| if a previous user decision expired immediately
+ // prior to this query, otherwise false.
+ virtual CertJudgment QueryPolicy(const std::string& host,
+ const net::X509Certificate& cert,
+ net::CertStatus error,
+ bool* expired_previous_decision) = 0;
+
+ // Records that a host has run insecure content.
+ virtual void HostRanInsecureContent(const std::string& host, int pid) = 0;
+
+ // Returns whether the specified host ran insecure content.
+ virtual bool DidHostRunInsecureContent(const std::string& host,
+ int pid) const = 0;
+
+ protected:
+ virtual ~SSLHostStateDelegate() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_SSL_HOST_STATE_DELEGATE_H_
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index 3a4139d633b..c16e5e6a0e6 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -8,15 +8,18 @@
#include <string>
#include "base/basictypes.h"
+#include "base/callback_forward.h"
#include "base/files/file_path.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
class GURL;
-namespace appcache {
-class AppCacheService;
+namespace base {
+class Time;
}
-namespace fileapi {
+namespace storage {
class FileSystemContext;
}
@@ -24,20 +27,22 @@ namespace net {
class URLRequestContextGetter;
}
-namespace quota {
+namespace storage {
class QuotaManager;
class SpecialStoragePolicy;
}
-namespace webkit_database {
+namespace storage {
class DatabaseTracker;
}
namespace content {
+class AppCacheService;
class BrowserContext;
-class IndexedDBContext;
class DOMStorageContext;
+class GeofencingManager;
+class IndexedDBContext;
class ServiceWorkerContext;
// Defines what persistent state a child process can access.
@@ -46,49 +51,46 @@ class ServiceWorkerContext;
// persistent state inside the BrowserContext. This is used to implement
// isolated storage where a renderer with isolated storage cannot see
// the cookies, localStorage, etc., that normal web renderers have access to.
-class StoragePartition {
+class CONTENT_EXPORT StoragePartition {
public:
virtual base::FilePath GetPath() = 0;
virtual net::URLRequestContextGetter* GetURLRequestContext() = 0;
virtual net::URLRequestContextGetter* GetMediaURLRequestContext() = 0;
- virtual quota::QuotaManager* GetQuotaManager() = 0;
- virtual appcache::AppCacheService* GetAppCacheService() = 0;
- virtual fileapi::FileSystemContext* GetFileSystemContext() = 0;
- virtual webkit_database::DatabaseTracker* GetDatabaseTracker() = 0;
+ virtual storage::QuotaManager* GetQuotaManager() = 0;
+ virtual AppCacheService* GetAppCacheService() = 0;
+ virtual storage::FileSystemContext* GetFileSystemContext() = 0;
+ virtual storage::DatabaseTracker* GetDatabaseTracker() = 0;
virtual DOMStorageContext* GetDOMStorageContext() = 0;
virtual IndexedDBContext* GetIndexedDBContext() = 0;
virtual ServiceWorkerContext* GetServiceWorkerContext() = 0;
-
- enum RemoveDataMask {
- REMOVE_DATA_MASK_APPCACHE = 1 << 0,
- REMOVE_DATA_MASK_COOKIES = 1 << 1,
- REMOVE_DATA_MASK_FILE_SYSTEMS = 1 << 2,
- REMOVE_DATA_MASK_INDEXEDDB = 1 << 3,
- REMOVE_DATA_MASK_LOCAL_STORAGE = 1 << 4,
- REMOVE_DATA_MASK_SHADER_CACHE = 1 << 5,
- REMOVE_DATA_MASK_WEBSQL = 1 << 6,
- REMOVE_DATA_MASK_WEBRTC_IDENTITY = 1 << 7,
- REMOVE_DATA_MASK_ALL = -1
- };
-
- enum QuotaManagedStorageMask {
- // Corresponds to quota::kStorageTypeTemporary.
- QUOTA_MANAGED_STORAGE_MASK_TEMPORARY = 1 << 0,
-
- // Corresponds to quota::kStorageTypePersistent.
- QUOTA_MANAGED_STORAGE_MASK_PERSISTENT = 1 << 1,
-
- // Corresponds to quota::kStorageTypeSyncable.
- QUOTA_MANAGED_STORAGE_MASK_SYNCABLE = 1 << 2,
-
- QUOTA_MANAGED_STORAGE_MASK_ALL = -1
- };
+ virtual GeofencingManager* GetGeofencingManager() = 0;
+
+ static const uint32 REMOVE_DATA_MASK_APPCACHE = 1 << 0;
+ static const uint32 REMOVE_DATA_MASK_COOKIES = 1 << 1;
+ static const uint32 REMOVE_DATA_MASK_FILE_SYSTEMS = 1 << 2;
+ static const uint32 REMOVE_DATA_MASK_INDEXEDDB = 1 << 3;
+ static const uint32 REMOVE_DATA_MASK_LOCAL_STORAGE = 1 << 4;
+ static const uint32 REMOVE_DATA_MASK_SHADER_CACHE = 1 << 5;
+ static const uint32 REMOVE_DATA_MASK_WEBSQL = 1 << 6;
+ static const uint32 REMOVE_DATA_MASK_WEBRTC_IDENTITY = 1 << 7;
+ static const uint32 REMOVE_DATA_MASK_SERVICE_WORKERS = 1 << 8;
+ static const uint32 REMOVE_DATA_MASK_ALL = 0xFFFFFFFF;
+
+ // Corresponds to storage::kStorageTypeTemporary.
+ static const uint32 QUOTA_MANAGED_STORAGE_MASK_TEMPORARY = 1 << 0;
+ // Corresponds to storage::kStorageTypePersistent.
+ static const uint32 QUOTA_MANAGED_STORAGE_MASK_PERSISTENT = 1 << 1;
+ // Corresponds to storage::kStorageTypeSyncable.
+ static const uint32 QUOTA_MANAGED_STORAGE_MASK_SYNCABLE = 1 << 2;
+ static const uint32 QUOTA_MANAGED_STORAGE_MASK_ALL = 0xFFFFFFFF;
// Starts an asynchronous task that does a best-effort clear the data
// corresponding to the given |remove_mask| and |quota_storage_remove_mask|
// inside this StoragePartition for the given |storage_origin|.
// Note session dom storage is not cleared even if you specify
// REMOVE_DATA_MASK_LOCAL_STORAGE.
+ // |callback| is called when data deletion is done or at least the deletion is
+ // scheduled.
//
// TODO(ajwong): Right now, the embedder may have some
// URLRequestContextGetter objects that the StoragePartition does not know
@@ -98,13 +100,13 @@ class StoragePartition {
virtual void ClearDataForOrigin(uint32 remove_mask,
uint32 quota_storage_remove_mask,
const GURL& storage_origin,
- net::URLRequestContextGetter* rq_context) = 0;
+ net::URLRequestContextGetter* rq_context,
+ const base::Closure& callback) = 0;
// A callback type to check if a given origin matches a storage policy.
// Can be passed empty/null where used, which means the origin will always
// match.
- typedef base::Callback<bool(const GURL&,
- quota::SpecialStoragePolicy*)>
+ typedef base::Callback<bool(const GURL&, storage::SpecialStoragePolicy*)>
OriginMatcherFunction;
// Similar to ClearDataForOrigin().
diff --git a/chromium/content/public/browser/stream_handle.h b/chromium/content/public/browser/stream_handle.h
index 94591d7d41d..7a8fb3225cd 100644
--- a/chromium/content/public/browser/stream_handle.h
+++ b/chromium/content/public/browser/stream_handle.h
@@ -5,17 +5,14 @@
#ifndef CONTENT_PUBLIC_BROWSER_STREAM_HANDLE_H_
#define CONTENT_PUBLIC_BROWSER_STREAM_HANDLE_H_
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
+#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
-namespace net {
-class HttpResponseHeaders;
-}
-
namespace content {
+// A handle to a Stream. When the handle is destroyed, the stream is released
+// and the URL is invalidated.
class CONTENT_EXPORT StreamHandle {
public:
virtual ~StreamHandle() {}
@@ -23,15 +20,6 @@ class CONTENT_EXPORT StreamHandle {
// Gets the URL the stream can be read from.
virtual const GURL& GetURL() = 0;
- // Gets the original URL being redirected to this Stream.
- virtual const GURL& GetOriginalURL() = 0;
-
- // Get the MIME type associated with this Stream.
- virtual const std::string& GetMimeType() = 0;
-
- // Get the HTTP response headers associated with this Stream.
- virtual scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders() = 0;
-
// Add a callback which will be called when the Stream is closed.
virtual void AddCloseListener(const base::Closure& callback) = 0;
};
diff --git a/chromium/content/public/browser/stream_info.cc b/chromium/content/public/browser/stream_info.cc
new file mode 100644
index 00000000000..5472b98793e
--- /dev/null
+++ b/chromium/content/public/browser/stream_info.cc
@@ -0,0 +1,16 @@
+// Copyright 2014 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 "content/public/browser/stream_info.h"
+
+#include "content/public/browser/stream_handle.h"
+#include "net/http/http_response_headers.h"
+
+namespace content {
+
+StreamInfo::StreamInfo() {}
+
+StreamInfo::~StreamInfo() {}
+
+} // namespace content
diff --git a/chromium/content/public/browser/stream_info.h b/chromium/content/public/browser/stream_info.h
new file mode 100644
index 00000000000..1882371a17e
--- /dev/null
+++ b/chromium/content/public/browser/stream_info.h
@@ -0,0 +1,47 @@
+// Copyright 2014 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 CONTENT_PUBLIC_BROWSER_STREAM_INFO_H_
+#define CONTENT_PUBLIC_BROWSER_STREAM_INFO_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace net {
+class HttpResponseHeaders;
+}
+
+namespace content {
+
+class StreamHandle;
+
+// A convenience structure for passing around both a StreamHandle and associated
+// metadata. The intent is so, when passing the stream's URL to a child process,
+// the handle can be retained as long as it is needed while the rest of the
+// StreamInfo is released.
+struct CONTENT_EXPORT StreamInfo {
+ StreamInfo();
+ ~StreamInfo();
+
+ // The handle to the stream itself.
+ scoped_ptr<StreamHandle> handle;
+
+ // The original URL being redirected to this stream.
+ GURL original_url;
+
+ // The MIME type associated with this stream.
+ std::string mime_type;
+
+ // The HTTP response headers associated with this stream.
+ scoped_refptr<net::HttpResponseHeaders> response_headers;
+
+ DISALLOW_COPY_AND_ASSIGN(StreamInfo);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_STREAM_INFO_H_
diff --git a/chromium/content/public/browser/tracing_controller.h b/chromium/content/public/browser/tracing_controller.h
index 68184a5a844..5b3eb4e4873 100644
--- a/chromium/content/public/browser/tracing_controller.h
+++ b/chromium/content/public/browser/tracing_controller.h
@@ -9,12 +9,10 @@
#include <string>
#include "base/callback.h"
+#include "base/debug/trace_event.h"
+#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-namespace base {
-class FilePath;
-};
-
namespace content {
class TracingController;
@@ -25,15 +23,39 @@ class TracingController;
// the UI thread.
class TracingController {
public:
- enum Options {
- DEFAULT_OPTIONS = 0,
- ENABLE_SYSTRACE = 1 << 0,
- ENABLE_SAMPLING = 1 << 1,
- RECORD_CONTINUOUSLY = 1 << 2, // For EnableRecording() only.
- };
CONTENT_EXPORT static TracingController* GetInstance();
+ // An interface for trace data consumer. An implemnentation of this interface
+ // is passed to either DisableTracing() or CaptureMonitoringSnapshot() and
+ // receives the trace data followed by a notification that all child processes
+ // have completed tracing and the data collection is over.
+ // All methods are called on the UI thread.
+ // Close method will be called exactly once and no methods will be
+ // called after that.
+ class CONTENT_EXPORT TraceDataSink
+ : public base::RefCountedThreadSafe<TraceDataSink> {
+ public:
+ virtual void AddTraceChunk(const std::string& chunk) {}
+ virtual void SetSystemTrace(const std::string& data) {}
+ virtual void Close() {}
+
+ protected:
+ friend class base::RefCountedThreadSafe<TraceDataSink>;
+ virtual ~TraceDataSink() {}
+ };
+
+ // Create a trace sink that may be supplied to DisableRecording or
+ // CaptureMonitoringSnapshot to capture the trace data as a string.
+ CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateStringSink(
+ const base::Callback<void(base::RefCountedString*)>& callback);
+
+ // Create a trace sink that may be supplied to DisableRecording or
+ // CaptureMonitoringSnapshot to dump the trace data to a file.
+ CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateFileSink(
+ const base::FilePath& file_path,
+ const base::Closure& callback);
+
// Get a set of category groups. The category groups can change as
// new code paths are reached.
//
@@ -65,8 +87,8 @@ class TracingController {
// |options| controls what kind of tracing is enabled.
typedef base::Callback<void()> EnableRecordingDoneCallback;
virtual bool EnableRecording(
- const std::string& category_filter,
- TracingController::Options options,
+ const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& trace_options,
const EnableRecordingDoneCallback& callback) = 0;
// Stop recording on all processes.
@@ -81,15 +103,12 @@ class TracingController {
// TracingFileResultCallback will be called back with a file that contains
// the traced data.
//
- // Trace data will be written into |result_file_path| if it is not empty, or
- // into a temporary file. The actual file path will be passed to |callback| if
- // it's not null.
+ // If |trace_data_sink| is not null, it will receive chunks of trace data
+ // as a comma-separated sequences of JSON-stringified events, followed by
+ // a notification that the trace collection is finished.
//
- // If |result_file_path| is empty and |callback| is null, trace data won't be
- // written to any file.
- typedef base::Callback<void(const base::FilePath&)> TracingFileResultCallback;
- virtual bool DisableRecording(const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) = 0;
+ virtual bool DisableRecording(
+ const scoped_refptr<TraceDataSink>& trace_data_sink) = 0;
// Start monitoring on all processes.
//
@@ -105,8 +124,8 @@ class TracingController {
// |options| controls what kind of tracing is enabled.
typedef base::Callback<void()> EnableMonitoringDoneCallback;
virtual bool EnableMonitoring(
- const std::string& category_filter,
- TracingController::Options options,
+ const base::debug::CategoryFilter& category_filter,
+ const base::debug::TraceOptions& trace_options,
const EnableMonitoringDoneCallback& callback) = 0;
// Stop monitoring on all processes.
@@ -118,9 +137,10 @@ class TracingController {
const DisableMonitoringDoneCallback& callback) = 0;
// Get the current monitoring configuration.
- virtual void GetMonitoringStatus(bool* out_enabled,
- std::string* out_category_filter,
- TracingController::Options* out_options) = 0;
+ virtual void GetMonitoringStatus(
+ bool* out_enabled,
+ base::debug::CategoryFilter* out_category_filter,
+ base::debug::TraceOptions* out_trace_options) = 0;
// Get the current monitoring traced data.
//
@@ -134,14 +154,11 @@ class TracingController {
// request, TracingFileResultCallback will be called back with a file that
// contains the traced data.
//
- // Trace data will be written into |result_file_path| if it is not empty, or
- // into a temporary file. The actual file path will be passed to |callback|.
- //
- // If |result_file_path| is empty and |callback| is null, trace data won't be
- // written to any file.
+ // If |trace_data_sink| is not null, it will receive chunks of trace data
+ // as a comma-separated sequences of JSON-stringified events, followed by
+ // a notification that the trace collection is finished.
virtual bool CaptureMonitoringSnapshot(
- const base::FilePath& result_file_path,
- const TracingFileResultCallback& callback) = 0;
+ const scoped_refptr<TraceDataSink>& trace_data_sink) = 0;
// Get the maximum across processes of trace buffer percent full state.
// When the TraceBufferPercentFull value is determined, the callback is
diff --git a/chromium/content/public/browser/url_data_source.cc b/chromium/content/public/browser/url_data_source.cc
index 148e62ab229..0c76c50afd0 100644
--- a/chromium/content/public/browser/url_data_source.cc
+++ b/chromium/content/public/browser/url_data_source.cc
@@ -56,4 +56,9 @@ bool URLDataSource::ShouldServeMimeTypeAsContentTypeHeader() const {
return false;
}
+std::string URLDataSource::GetAccessControlAllowOriginForOrigin(
+ const std::string& origin) const {
+ return std::string();
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/url_data_source.h b/chromium/content/public/browser/url_data_source.h
index 33c185b63b8..9230360721f 100644
--- a/chromium/content/public/browser/url_data_source.h
+++ b/chromium/content/public/browser/url_data_source.h
@@ -119,6 +119,15 @@ class CONTENT_EXPORT URLDataSource {
// is for chrome-devtools.
virtual bool ShouldServeMimeTypeAsContentTypeHeader() const;
+ // This method is called when the request contains "Origin:" header. The value
+ // of the header is passed in |origin| parameter. If the returned value is not
+ // empty, it is used as a value for "Access-Control-Allow-Origin:" response
+ // header, otherwise the header is not set. This method should return either
+ // |origin|, or "*", or "none", or empty string.
+ // Default implementation returns an empty string.
+ virtual std::string GetAccessControlAllowOriginForOrigin(
+ const std::string& origin) const;
+
// Called to inform the source that StartDataRequest() will be called soon.
// Gives the source an opportunity to rewrite |path| to incorporate extra
// information from the URLRequest prior to serving.
diff --git a/chromium/content/public/browser/utility_process_host.h b/chromium/content/public/browser/utility_process_host.h
index 756d50f1d1e..07f46ee0c74 100644
--- a/chromium/content/public/browser/utility_process_host.h
+++ b/chromium/content/public/browser/utility_process_host.h
@@ -34,12 +34,15 @@ struct ChildProcessData;
class UtilityProcessHost : public IPC::Sender,
public base::SupportsWeakPtr<UtilityProcessHost> {
public:
- // Used to create a utility process.
+ // Used to create a utility process. |client| is optional. If supplied it will
+ // be notified of incoming messages from the utility process.
+ // |client_task_runner| is required if |client| is supplied and is the task
+ // runner upon which |client| will be invoked.
CONTENT_EXPORT static UtilityProcessHost* Create(
- UtilityProcessHostClient* client,
- base::SequencedTaskRunner* client_task_runner);
+ const scoped_refptr<UtilityProcessHostClient>& client,
+ const scoped_refptr<base::SequencedTaskRunner>& client_task_runner);
- virtual ~UtilityProcessHost() {}
+ ~UtilityProcessHost() override {}
// Starts utility process in batch mode. Caller must call EndBatchMode()
// to finish the utility process.
diff --git a/chromium/content/public/browser/web_contents.cc b/chromium/content/public/browser/web_contents.cc
index 549e881c748..7afc3385c98 100644
--- a/chromium/content/public/browser/web_contents.cc
+++ b/chromium/content/public/browser/web_contents.cc
@@ -16,7 +16,7 @@ WebContents::CreateParams::CreateParams(BrowserContext* context)
routing_id(MSG_ROUTING_NONE),
main_frame_routing_id(MSG_ROUTING_NONE),
initially_hidden(false),
- guest_instance_id(0),
+ guest_delegate(NULL),
context(NULL) {}
WebContents::CreateParams::CreateParams(
@@ -28,7 +28,7 @@ WebContents::CreateParams::CreateParams(
routing_id(MSG_ROUTING_NONE),
main_frame_routing_id(MSG_ROUTING_NONE),
initially_hidden(false),
- guest_instance_id(0),
+ guest_delegate(NULL),
context(NULL) {}
WebContents::CreateParams::~CreateParams() {
diff --git a/chromium/content/public/browser/web_contents.h b/chromium/content/public/browser/web_contents.h
index 0e388764929..5478a378158 100644
--- a/chromium/content/public/browser/web_contents.h
+++ b/chromium/content/public/browser/web_contents.h
@@ -14,6 +14,7 @@
#include "base/strings/string16.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
+#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/save_page_type.h"
@@ -45,6 +46,7 @@ struct LoadStateWithParam;
namespace content {
class BrowserContext;
+class BrowserPluginGuestDelegate;
class InterstitialPage;
class PageState;
class RenderFrameHost;
@@ -55,6 +57,7 @@ class SiteInstance;
class WebContentsDelegate;
struct CustomContextMenuContext;
struct DropData;
+struct Manifest;
struct RendererPreferences;
// WebContents is the core class in content/. A WebContents renders web content
@@ -109,13 +112,8 @@ class WebContents : public PageNavigator,
// True if the contents should be initially hidden.
bool initially_hidden;
- // If this instance ID is non-zero then it indicates that this WebContents
- // should behave as a guest.
- int guest_instance_id;
-
- // TODO(fsamuel): This is temporary. Remove this once all guests are created
- // from the content embedder.
- scoped_ptr<base::DictionaryValue> guest_extra_params;
+ // If non-null then this WebContents will be hosted by a BrowserPlugin.
+ BrowserPluginGuestDelegate* guest_delegate;
// Used to specify the location context which display the new view should
// belong. This can be NULL if not needed.
@@ -146,7 +144,7 @@ class WebContents : public PageNavigator,
CONTENT_EXPORT static WebContents* FromRenderFrameHost(RenderFrameHost* rfh);
- virtual ~WebContents() {}
+ ~WebContents() override {}
// Intrinsic tab state -------------------------------------------------------
@@ -226,6 +224,18 @@ class WebContents : public PageNavigator,
virtual void SetUserAgentOverride(const std::string& override) = 0;
virtual const std::string& GetUserAgentOverride() const = 0;
+ // Enable the accessibility tree for this WebContents in the renderer,
+ // but don't enable creating a native accessibility tree on the browser
+ // side.
+ virtual void EnableTreeOnlyAccessibilityMode() = 0;
+
+ // Returns true only if "tree only" accessibility mode is on.
+ virtual bool IsTreeOnlyAccessibilityModeForTesting() const = 0;
+
+ // Returns true only if complete accessibility mode is on, meaning there's
+ // both renderer accessibility, and a native browser accessibility tree.
+ virtual bool IsFullAccessibilityModeForTesting() const = 0;
+
#if defined(OS_WIN)
virtual void SetParentNativeViewAccessible(
gfx::NativeViewAccessible accessible_parent) = 0;
@@ -296,6 +306,10 @@ class WebContents : public PageNavigator,
virtual void DecrementCapturerCount() = 0;
virtual int GetCapturerCount() const = 0;
+ // Indicates/Sets whether all audio output from this WebContents is muted.
+ virtual bool IsAudioMuted() const = 0;
+ virtual void SetAudioMuted(bool mute) = 0;
+
// Indicates whether this tab should be considered crashed. The setter will
// also notify the delegate when the flag is changed.
virtual bool IsCrashed() const = 0;
@@ -307,8 +321,8 @@ class WebContents : public PageNavigator,
virtual bool IsBeingDestroyed() const = 0;
// Convenience method for notifying the delegate of a navigation state
- // change. See InvalidateType enum.
- virtual void NotifyNavigationStateChanged(unsigned changed_flags) = 0;
+ // change.
+ virtual void NotifyNavigationStateChanged(InvalidateTypes changed_flags) = 0;
// Get the last time that the WebContents was made active (either when it was
// created or shown with WasShown()).
@@ -492,10 +506,6 @@ class WebContents : public PageNavigator,
virtual void SetClosedByUserGesture(bool value) = 0;
virtual bool GetClosedByUserGesture() const = 0;
- // Gets the zoom percent for this tab.
- virtual int GetZoomPercent(bool* enable_increment,
- bool* enable_decrement) const = 0;
-
// Opens view-source tab for this contents.
virtual void ViewSource() = 0;
@@ -571,28 +581,25 @@ class WebContents : public PageNavigator,
// Requests the renderer to insert CSS into the main frame's document.
virtual void InsertCSS(const std::string& css) = 0;
+ // Returns true if audio has recently been audible from the WebContents.
+ virtual bool WasRecentlyAudible() = 0;
+
+ typedef base::Callback<void(const Manifest&)> GetManifestCallback;
+
+ // Requests the Manifest of the main frame's document.
+ virtual void GetManifest(const GetManifestCallback&) = 0;
+
#if defined(OS_ANDROID)
CONTENT_EXPORT static WebContents* FromJavaWebContents(
jobject jweb_contents_android);
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() = 0;
#elif defined(OS_MACOSX)
- // The web contents view assumes that its view will never be overlapped by
- // another view (either partially or fully). This allows it to perform
- // optimizations. If the view is in a view hierarchy where it might be
- // overlapped by another view, notify the view by calling this with |true|.
- virtual void SetAllowOverlappingViews(bool overlapping) = 0;
-
- // Returns true if overlapping views are allowed, false otherwise.
- virtual bool GetAllowOverlappingViews() = 0;
-
- // To draw two overlapping web contents view, the underlaying one should
- // know about the overlaying one. Caller must ensure that |overlay| exists
- // until |RemoveOverlayView| is called.
- virtual void SetOverlayView(WebContents* overlay,
- const gfx::Point& offset) = 0;
-
- // Removes the previously set overlay view.
- virtual void RemoveOverlayView() = 0;
+ // Allowing other views disables optimizations which assume that only a single
+ // WebContents is present.
+ virtual void SetAllowOtherViews(bool allow) = 0;
+
+ // Returns true if other views are allowed, false otherwise.
+ virtual bool GetAllowOtherViews() = 0;
#endif // OS_ANDROID
private:
diff --git a/chromium/content/public/browser/web_contents_delegate.cc b/chromium/content/public/browser/web_contents_delegate.cc
index 0028339ab63..f264df7f4a0 100644
--- a/chromium/content/public/browser/web_contents_delegate.cc
+++ b/chromium/content/public/browser/web_contents_delegate.cc
@@ -92,7 +92,7 @@ void WebContentsDelegate::ViewSourceForTab(WebContents* source,
GURL url = GURL(kViewSourceScheme + std::string(":") + page_url.spec());
OpenURLFromTab(source, OpenURLParams(url, Referrer(),
NEW_FOREGROUND_TAB,
- PAGE_TRANSITION_LINK, false));
+ ui::PAGE_TRANSITION_LINK, false));
}
void WebContentsDelegate::ViewSourceForFrame(WebContents* source,
@@ -102,7 +102,7 @@ void WebContentsDelegate::ViewSourceForFrame(WebContents* source,
GURL url = GURL(kViewSourceScheme + std::string(":") + frame_url.spec());
OpenURLFromTab(source, OpenURLParams(url, Referrer(),
NEW_FOREGROUND_TAB,
- PAGE_TRANSITION_LINK, false));
+ ui::PAGE_TRANSITION_LINK, false));
}
bool WebContentsDelegate::PreHandleKeyboardEvent(
@@ -164,11 +164,22 @@ void WebContentsDelegate::RequestMediaAccessPermission(
WebContents* web_contents,
const MediaStreamRequest& request,
const MediaResponseCallback& callback) {
+ LOG(ERROR) << "WebContentsDelegate::RequestMediaAccessPermission: "
+ << "Not supported.";
callback.Run(MediaStreamDevices(),
- MEDIA_DEVICE_INVALID_STATE,
+ MEDIA_DEVICE_NOT_SUPPORTED,
scoped_ptr<MediaStreamUI>());
}
+bool WebContentsDelegate::CheckMediaAccessPermission(
+ WebContents* web_contents,
+ const GURL& security_origin,
+ MediaStreamType type) {
+ LOG(ERROR) << "WebContentsDelegate::CheckMediaAccessPermission: "
+ << "Not supported.";
+ return false;
+}
+
bool WebContentsDelegate::RequestPpapiBrokerPermission(
WebContents* web_contents,
const GURL& url,
diff --git a/chromium/content/public/browser/web_contents_delegate.h b/chromium/content/public/browser/web_contents_delegate.h
index 52e4747ca59..bcd5caf609b 100644
--- a/chromium/content/public/browser/web_contents_delegate.h
+++ b/chromium/content/public/browser/web_contents_delegate.h
@@ -12,9 +12,9 @@
#include "base/callback.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
+#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_type.h"
#include "content/public/common/media_stream_request.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/window_container_type.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -84,10 +84,9 @@ class CONTENT_EXPORT WebContentsDelegate {
// Called to inform the delegate that the WebContents's navigation state
// changed. The |changed_flags| indicates the parts of the navigation state
- // that have been updated, and is any combination of the
- // |WebContents::InvalidateTypes| bits.
+ // that have been updated.
virtual void NavigationStateChanged(const WebContents* source,
- unsigned changed_flags) {}
+ InvalidateTypes changed_flags) {}
// Called to inform the delegate that the WebContent's visible SSL state (as
// defined by SSLStatus) changed.
@@ -145,7 +144,6 @@ class CONTENT_EXPORT WebContentsDelegate {
// Notification that the target URL has changed.
virtual void UpdateTargetURL(WebContents* source,
- int32 page_id,
const GURL& url) {}
// Notification that there was a mouse event, along with the absolute
@@ -163,8 +161,11 @@ class CONTENT_EXPORT WebContentsDelegate {
virtual bool CanOverscrollContent() const;
// Callback that allows vertical overscroll activies to be communicated to the
- // delegate.
- virtual void OverscrollUpdate(int delta_y) {}
+ // delegate. |delta_y| is the total amount of overscroll.
+ virtual void OverscrollUpdate(float delta_y) {}
+
+ // Invoked when a vertical overscroll completes.
+ virtual void OverscrollComplete() {}
// Return the rect where to display the resize corner, if any, otherwise
// an empty rect.
@@ -383,6 +384,14 @@ class CONTENT_EXPORT WebContentsDelegate {
const GURL& url,
bool user_gesture) {}
+ // Unregister the registered handler for URL requests with the given scheme.
+ // |user_gesture| is true if the registration is made in the context of a user
+ // gesture.
+ virtual void UnregisterProtocolHandler(WebContents* web_contents,
+ const std::string& protocol,
+ const GURL& url,
+ bool user_gesture) {}
+
// Result of string search in the page. This includes the number of matches
// found and the selection rect (in screen coordinates) for the string found.
// If |final_update| is false, it indicates that more results follow.
@@ -436,6 +445,13 @@ class CONTENT_EXPORT WebContentsDelegate {
const MediaStreamRequest& request,
const MediaResponseCallback& callback);
+ // Checks if we have permission to access the microphone or camera. Note that
+ // this does not query the user. |type| must be MEDIA_DEVICE_AUDIO_CAPTURE
+ // or MEDIA_DEVICE_VIDEO_CAPTURE.
+ virtual bool CheckMediaAccessPermission(WebContents* web_contents,
+ const GURL& security_origin,
+ MediaStreamType type);
+
// Requests permission to access the PPAPI broker. The delegate should return
// true and call the passed in |callback| with the result, or return false
// to indicate that it does not support asking for permission.
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index 72c6ff60680..d792ad22e03 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -10,10 +10,10 @@
#include "content/common/content_export.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/common/frame_navigate_params.h"
-#include "content/public/common/page_transition_types.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
namespace content {
@@ -82,13 +82,24 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// RenderProcessHostObserver::RenderProcessExited().
virtual void RenderProcessGone(base::TerminationStatus status) {}
- // This method is invoked when a WebContents swaps its render view host with
- // another one, possibly changing processes. The RenderViewHost that has
- // been replaced is in |old_render_view_host|, which is NULL if the old RVH
- // was shut down.
+ // This method is invoked when a WebContents swaps its visible RenderViewHost
+ // with another one, possibly changing processes. The RenderViewHost that has
+ // been replaced is in |old_host|, which is NULL if the old RVH was shut down.
virtual void RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host) {}
+ // This method is invoked whenever one of the current frames of a WebContents
+ // swaps its RenderFrameHost with another one; for example because that frame
+ // navigated and the new content is in a different process. The
+ // RenderFrameHost that has been replaced is in |old_host|, which can be NULL
+ // if the old RFH was shut down.
+ //
+ // This method, in combination with RenderFrameDeleted, is appropriate for
+ // observers wishing to track the set of active RenderFrameHosts -- i.e.,
+ // those hosts that would be visited by calling WebContents::ForEachFrame.
+ virtual void RenderFrameHostChanged(RenderFrameHost* old_host,
+ RenderFrameHost* new_host) {}
+
// This method is invoked after the WebContents decided which RenderViewHost
// to use for the next navigation, but before the navigation starts.
virtual void AboutToNavigateRenderView(
@@ -103,11 +114,8 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
const GURL& url,
NavigationController::ReloadType reload_type) {}
- // |render_view_host| is the RenderViewHost for which the provisional load is
- // happening. |frame_id| is a positive, non-zero integer identifying the
- // navigating frame in the given |render_view_host|. |parent_frame_id| is the
- // frame identifier of the frame containing the navigating frame, or -1 if the
- // frame is not contained in another frame.
+ // |render_frame_host| is the RenderFrameHost for which the provisional load
+ // is happening.
//
// Since the URL validation will strip error URLs, or srcdoc URLs, the boolean
// flags |is_error_page| and |is_iframe_srcdoc| will indicate that the not
@@ -116,45 +124,28 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// Note that during a cross-process navigation, several provisional loads
// can be on-going in parallel.
virtual void DidStartProvisionalLoadForFrame(
- int64 frame_id,
- int64 parent_frame_id,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& validated_url,
bool is_error_page,
- bool is_iframe_srcdoc,
- RenderViewHost* render_view_host) {}
-
- // This method is invoked right after the DidStartProvisionalLoadForFrame if
- // the provisional load affects the main frame, or if the provisional load
- // was redirected. The latter use case is DEPRECATED. You should listen to
- // WebContentsObserver::DidGetRedirectForResourceRequest instead.
- virtual void ProvisionalChangeToMainFrameUrl(
- const GURL& url,
- RenderFrameHost* render_frame_host) {}
+ bool is_iframe_srcdoc) {}
// This method is invoked when the provisional load was successfully
- // committed. The |render_view_host| is now the current RenderViewHost of the
- // WebContents.
+ // committed.
//
// If the navigation only changed the reference fragment, or was triggered
// using the history API (e.g. window.history.replaceState), we will receive
// this signal without a prior DidStartProvisionalLoadForFrame signal.
virtual void DidCommitProvisionalLoadForFrame(
- int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
+ RenderFrameHost* render_frame_host,
const GURL& url,
- PageTransition transition_type,
- RenderViewHost* render_view_host) {}
+ ui::PageTransition transition_type) {}
// This method is invoked when the provisional load failed.
- virtual void DidFailProvisionalLoad(int64 frame_id,
- const base::string16& frame_unique_name,
- bool is_main_frame,
- const GURL& validated_url,
- int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) {}
+ virtual void DidFailProvisionalLoad(
+ RenderFrameHost* render_frame_host,
+ const GURL& validated_url,
+ int error_code,
+ const base::string16& error_description) {}
// If the provisional load corresponded to the main frame, this method is
// invoked in addition to DidCommitProvisionalLoadForFrame.
@@ -165,6 +156,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// And regardless of what frame navigated, this method is invoked after
// DidCommitProvisionalLoadForFrame was invoked.
virtual void DidNavigateAnyFrame(
+ RenderFrameHost* render_frame_host,
const LoadCommittedDetails& details,
const FrameNavigateParams& params) {}
@@ -179,8 +171,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// This method is invoked when the document in the given frame finished
// loading. At this point, scripts marked as defer were executed, and
// content scripts marked "document_end" get injected into the frame.
- virtual void DocumentLoadedInFrame(int64 frame_id,
- RenderViewHost* render_view_host) {}
+ virtual void DocumentLoadedInFrame(RenderFrameHost* render_frame_host) {}
// This method is invoked when the navigation is done, i.e. the spinner of
// the tab will stop spinning, and the onload event was dispatched.
@@ -188,19 +179,15 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// If the WebContents is displaying replacement content, e.g. network error
// pages, DidFinishLoad is invoked for frames that were not sending
// navigational events before. It is safe to ignore these events.
- virtual void DidFinishLoad(int64 frame_id,
- const GURL& validated_url,
- bool is_main_frame,
- RenderViewHost* render_view_host) {}
+ virtual void DidFinishLoad(RenderFrameHost* render_frame_host,
+ const GURL& validated_url) {}
// This method is like DidFinishLoad, but when the load failed or was
// cancelled, e.g. window.stop() is invoked.
- virtual void DidFailLoad(int64 frame_id,
+ virtual void DidFailLoad(RenderFrameHost* render_frame_host,
const GURL& validated_url,
- bool is_main_frame,
int error_code,
- const base::string16& error_description,
- RenderViewHost* render_view_host) {}
+ const base::string16& error_description) {}
// This method is invoked when content was loaded from an in-memory cache.
virtual void DidLoadResourceFromMemoryCache(
@@ -232,11 +219,10 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
const GURL& url,
const Referrer& referrer,
WindowOpenDisposition disposition,
- PageTransition transition,
+ ui::PageTransition transition,
int64 source_frame_id) {}
- virtual void FrameDetached(RenderViewHost* render_view_host,
- int64 frame_id) {}
+ virtual void FrameDetached(RenderFrameHost* render_frame_host) {}
// This method is invoked when the renderer has completed its first paint
// after a non-empty layout.
@@ -337,12 +323,14 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
RenderFrameHost* render_frame_host);
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
int routing_id() const;
+ WebContents* web_contents() const;
+
protected:
// Use this constructor when the object is tied to a single WebContents for
// its entire lifetime.
@@ -353,13 +341,11 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// observing.
WebContentsObserver();
- virtual ~WebContentsObserver();
+ ~WebContentsObserver() override;
// Start observing a different WebContents; used with the default constructor.
void Observe(WebContents* web_contents);
- WebContents* web_contents() const;
-
private:
friend class WebContentsImpl;
diff --git a/chromium/content/public/browser/web_contents_view_delegate.cc b/chromium/content/public/browser/web_contents_view_delegate.cc
new file mode 100644
index 00000000000..e582621be3f
--- /dev/null
+++ b/chromium/content/public/browser/web_contents_view_delegate.cc
@@ -0,0 +1,55 @@
+// Copyright 2014 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 "content/public/browser/web_contents_view_delegate.h"
+
+#include <stddef.h>
+
+namespace content {
+
+WebContentsViewDelegate::~WebContentsViewDelegate() {
+}
+
+WebDragDestDelegate* WebContentsViewDelegate::GetDragDestDelegate() {
+ return NULL;
+}
+
+void WebContentsViewDelegate::ShowContextMenu(
+ RenderFrameHost* render_frame_host,
+ const ContextMenuParams& params) {
+}
+
+void WebContentsViewDelegate::StoreFocus() {
+}
+
+void WebContentsViewDelegate::RestoreFocus() {
+}
+
+bool WebContentsViewDelegate::Focus() {
+ return false;
+}
+
+void WebContentsViewDelegate::TakeFocus(bool reverse) {
+}
+
+void WebContentsViewDelegate::ShowDisambiguationPopup(
+ const gfx::Rect& target_rect,
+ const SkBitmap& zoomed_bitmap,
+ const gfx::NativeView content,
+ const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
+ const base::Callback<void(ui::MouseEvent*)>& mouse_cb) {
+}
+
+void WebContentsViewDelegate::HideDisambiguationPopup() {
+}
+
+void WebContentsViewDelegate::SizeChanged(const gfx::Size& size) {
+}
+
+void* WebContentsViewDelegate::CreateRenderWidgetHostViewDelegate(
+ RenderWidgetHost* render_widget_host) {
+ return NULL;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/web_contents_view_delegate.h b/chromium/content/public/browser/web_contents_view_delegate.h
index b0e3f6255b9..ecbd0ff968a 100644
--- a/chromium/content/public/browser/web_contents_view_delegate.h
+++ b/chromium/content/public/browser/web_contents_view_delegate.h
@@ -2,26 +2,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_VIEW_WIN_DELEGATE_H_
-#define CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_VIEW_WIN_DELEGATE_H_
+#ifndef CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_VIEW_DELEGATE_H_
+#define CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_VIEW_DELEGATE_H_
-#if defined(OS_MACOSX)
+#if defined(__OBJC__)
#import <Cocoa/Cocoa.h>
#endif
+#include "base/callback_forward.h"
#include "content/common/content_export.h"
#include "ui/gfx/native_widget_types.h"
-#if defined(OS_MACOSX)
+#if defined(__OBJC__)
@protocol RenderWidgetHostViewMacDelegate;
#endif
namespace gfx {
+class Rect;
class Size;
}
namespace ui {
-class FocusStoreGtk;
+class GestureEvent;
+class MouseEvent;
}
namespace content {
@@ -34,33 +37,54 @@ struct ContextMenuParams;
// WebContentsView implementation.
class CONTENT_EXPORT WebContentsViewDelegate {
public:
- virtual ~WebContentsViewDelegate() {}
+ virtual ~WebContentsViewDelegate();
// Returns a delegate to process drags not handled by content.
- virtual WebDragDestDelegate* GetDragDestDelegate() = 0;
+ virtual WebDragDestDelegate* GetDragDestDelegate();
// Shows a context menu.
virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
- const ContextMenuParams& params) = 0;
-
-#if defined(USE_AURA)
- // These methods allow the embedder to intercept WebContentsViewWin's
- // implementation of these WebContentsView methods. See the WebContentsView
- // interface documentation for more information about these methods.
- virtual void StoreFocus() = 0;
- virtual void RestoreFocus() = 0;
- virtual bool Focus() = 0;
- virtual void TakeFocus(bool reverse) = 0;
- virtual void SizeChanged(const gfx::Size& size) = 0;
-#elif defined(OS_MACOSX)
+ const ContextMenuParams& params);
+
+ // These methods allow the embedder to intercept a WebContentsView's
+ // implementation of these methods. See the WebContentsView interface
+ // documentation for more information about these methods.
+ virtual void StoreFocus();
+ virtual void RestoreFocus();
+ virtual bool Focus();
+ virtual void TakeFocus(bool reverse);
+ virtual void SizeChanged(const gfx::Size& size);
+
+ // Shows a popup window containing the |zoomed_bitmap| of web content with
+ // more than one link, allowing the user to more easily select which link
+ // they were trying to touch. |target_rect| is the rectangle in DIPs in the
+ // coordinate system of |content| that has been scaled up in |zoomed_bitmap|.
+ // Should the popup receive any gesture events they should be translated back
+ // to the coordinate system of |content| and then provided to the |callback|
+ // for forwarding on to the original scale web content.
+ virtual void ShowDisambiguationPopup(
+ const gfx::Rect& target_rect,
+ const SkBitmap& zoomed_bitmap,
+ const gfx::NativeView content,
+ const base::Callback<void(ui::GestureEvent*)>& gesture_cb,
+ const base::Callback<void(ui::MouseEvent*)>& mouse_cb);
+
+ // Hides the link disambiguation popup window if it is showing, otherwise does
+ // nothing.
+ virtual void HideDisambiguationPopup();
+
// Returns a newly-created delegate for the RenderWidgetHostViewMac, to handle
// events on the responder chain.
+#if defined(__OBJC__)
virtual NSObject<RenderWidgetHostViewMacDelegate>*
CreateRenderWidgetHostViewDelegate(
- RenderWidgetHost* render_widget_host) = 0;
+ RenderWidgetHost* render_widget_host);
+#else
+ virtual void* CreateRenderWidgetHostViewDelegate(
+ RenderWidgetHost* render_widget_host);
#endif
};
} // namespace content
-#endif // CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_VIEW_WIN_DELEGATE_H_
+#endif // CONTENT_PUBLIC_BROWSER_WEB_CONTENTS_VIEW_DELEGATE_H_
diff --git a/chromium/content/public/browser/web_ui.h b/chromium/content/public/browser/web_ui.h
index 52ce114dcf3..8568530c7db 100644
--- a/chromium/content/public/browser/web_ui.h
+++ b/chromium/content/public/browser/web_ui.h
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "base/strings/string16.h"
#include "content/common/content_export.h"
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
class GURL;
@@ -64,8 +64,8 @@ class CONTENT_EXPORT WebUI {
// Returns the transition type that should be used for link clicks on this
// Web UI. This will default to LINK but may be overridden.
- virtual PageTransition GetLinkTransitionType() const = 0;
- virtual void SetLinkTransitionType(PageTransition type) = 0;
+ virtual ui::PageTransition GetLinkTransitionType() const = 0;
+ virtual void SetLinkTransitionType(ui::PageTransition type) = 0;
// Allows a controller to override the BindingsPolicy that should be enabled
// for this page.
diff --git a/chromium/content/public/browser/web_ui_data_source.h b/chromium/content/public/browser/web_ui_data_source.h
index 2acb117b2c0..5e0a2deb568 100644
--- a/chromium/content/public/browser/web_ui_data_source.h
+++ b/chromium/content/public/browser/web_ui_data_source.h
@@ -56,10 +56,6 @@ class WebUIDataSource {
// Sets the path which will return the JSON strings.
virtual void SetJsonPath(const std::string& path) = 0;
- // Sets the data source to use a slightly different format for json data. Some
- // day this should become the default.
- virtual void SetUseJsonJSFormatV2() = 0;
-
// Adds a mapping between a path name and a resource to return.
virtual void AddResourcePath(const std::string& path, int resource_id) = 0;
diff --git a/chromium/content/public/browser/worker_service.h b/chromium/content/public/browser/worker_service.h
index 83a8bd83e0c..7ce2bf4ec1f 100644
--- a/chromium/content/public/browser/worker_service.h
+++ b/chromium/content/public/browser/worker_service.h
@@ -26,9 +26,6 @@ class WorkerService {
// Returns the WorkerService singleton.
CONTENT_EXPORT static WorkerService* GetInstance();
- // Determines whether embedded SharedWorker is enabled.
- CONTENT_EXPORT static bool EmbeddedSharedWorkerEnabled();
-
// Terminates the given worker. Returns true if the process was found.
virtual bool TerminateWorker(int process_id, int route_id) = 0;
diff --git a/chromium/content/public/child/BUILD.gn b/chromium/content/public/child/BUILD.gn
index 9dc2c30ad45..fff416aff02 100644
--- a/chromium/content/public/child/BUILD.gn
+++ b/chromium/content/public/child/BUILD.gn
@@ -4,7 +4,18 @@
import("//content/child/child.gni")
-source_set("child") {
+# See //content/BUILD.gn for how this works.
+group("child") {
+ if (is_component_build) {
+ public_deps = [ "//content" ]
+ } else {
+ public_deps = [ ":child_sources" ]
+ }
+}
+
+source_set("child_sources") {
+ visibility = [ "//content/*" ]
+
sources = rebase_path(content_child_gypi_values.public_child_sources,
".", "//content")
@@ -14,5 +25,6 @@ source_set("child") {
deps = [
"//content/child",
+ "//content/public/common:common_sources",
]
}
diff --git a/chromium/content/public/child/request_peer.h b/chromium/content/public/child/request_peer.h
index 93143c5b4a8..dfa7a7417ea 100644
--- a/chromium/content/public/child/request_peer.h
+++ b/chromium/content/public/child/request_peer.h
@@ -16,6 +16,10 @@ namespace base {
class TimeTicks;
}
+namespace net {
+struct RedirectInfo;
+}
+
namespace content {
struct ResourceResponseInfo;
@@ -30,16 +34,14 @@ struct ResourceResponseInfo;
class CONTENT_EXPORT RequestPeer {
public:
// Called as upload progress is made.
- // note: only for requests with LOAD_ENABLE_UPLOAD_PROGRESS set
+ // note: only for requests with upload progress enabled.
virtual void OnUploadProgress(uint64 position, uint64 size) = 0;
// Called when a redirect occurs. The implementation may return false to
- // suppress the redirect. The given ResponseInfo provides complete
- // information about the redirect, and new_url is the URL that will be loaded
- // if this method returns true. new_first_party_for_cookies is the new
- // first-party URL for cookies should that have changed.
- virtual bool OnReceivedRedirect(const GURL& new_url,
- const GURL& new_first_party_for_cookies,
+ // suppress the redirect. The ResourceResponseInfo provides information about
+ // the redirect response and the RedirectInfo includes information about the
+ // request to be made if the method returns true.
+ virtual bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
const ResourceResponseInfo& info) = 0;
// Called when response headers are available (after all redirects have
diff --git a/chromium/content/public/child/resource_dispatcher_delegate.h b/chromium/content/public/child/resource_dispatcher_delegate.h
index 1c6168824fc..6a5da1c0136 100644
--- a/chromium/content/public/child/resource_dispatcher_delegate.h
+++ b/chromium/content/public/child/resource_dispatcher_delegate.h
@@ -8,7 +8,7 @@
#include <string>
#include "content/common/content_export.h"
-#include "webkit/common/resource_type.h"
+#include "content/public/common/resource_type.h"
class GURL;
@@ -22,15 +22,13 @@ class CONTENT_EXPORT ResourceDispatcherDelegate {
public:
virtual ~ResourceDispatcherDelegate() {}
- virtual RequestPeer* OnRequestComplete(
- RequestPeer* current_peer,
- ResourceType::Type resource_type,
- int error_code) = 0;
+ virtual RequestPeer* OnRequestComplete(RequestPeer* current_peer,
+ ResourceType resource_type,
+ int error_code) = 0;
- virtual RequestPeer* OnReceivedResponse(
- RequestPeer* current_peer,
- const std::string& mime_type,
- const GURL& url) = 0;
+ virtual RequestPeer* OnReceivedResponse(RequestPeer* current_peer,
+ const std::string& mime_type,
+ const GURL& url) = 0;
};
} // namespace content
diff --git a/chromium/content/public/common/BUILD.gn b/chromium/content/public/common/BUILD.gn
index 32fd84e09d5..c4d003669dc 100644
--- a/chromium/content/public/common/BUILD.gn
+++ b/chromium/content/public/common/BUILD.gn
@@ -2,9 +2,22 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/features.gni")
import("//content/common/common.gni")
+import("//mojo/public/tools/bindings/mojom.gni")
+
+# See //content/BUILD.gn for how this works.
+group("common") {
+ if (is_component_build) {
+ public_deps = [ "//content" ]
+ } else {
+ public_deps = [ ":common_sources" ]
+ }
+}
+
+source_set("common_sources") {
+ visibility = [ "//content/*" ]
-source_set("common") {
sources = rebase_path(content_common_gypi_values.public_common_sources,
".", "//content")
@@ -12,9 +25,28 @@ source_set("common") {
"//content:content_implementation",
]
- deps = [
+ public_deps = [
"//content/common",
+ ]
+ deps = [
+ "//net",
"//skia",
"//third_party/WebKit/public:blink_headers",
+ "//third_party/icu",
+ "//ui/base",
+ "//ui/gfx",
+ ]
+
+ if (!enable_plugins) {
+ sources -= [
+ "pepper_plugin_info.cc",
+ "pepper_plugin_info.h",
+ ]
+ }
+}
+
+mojom("mojo_bindings") {
+ sources = [
+ "mojo_geoposition.mojom",
]
}
diff --git a/chromium/content/public/common/OWNERS b/chromium/content/public/common/OWNERS
index cbcb62d430c..86e41044421 100644
--- a/chromium/content/public/common/OWNERS
+++ b/chromium/content/public/common/OWNERS
@@ -1,14 +1,19 @@
per-file common_param_traits.cc=set noparent
-per-file common_param_traits.cc=cevans@chromium.org
per-file common_param_traits.cc=tsepez@chromium.org
per-file *param_traits*.h=set noparent
-per-file *param_traits*.h=cevans@chromium.org
per-file *param_traits*.h=dcheng@chromium.org
per-file *param_traits*.h=inferno@chromium.org
per-file *param_traits*.h=jln@chromium.org
per-file *param_traits*.h=jschuh@chromium.org
per-file *param_traits*.h=kenrb@chromium.org
+per-file *param_traits*.h=mkwst@chromium.org
per-file *param_traits*.h=nasko@chromium.org
per-file *param_traits*.h=palmer@chromium.org
per-file *param_traits*.h=tsepez@chromium.org
+per-file *param_traits*.h=wfh@chromium.org
+
+# Changes to Mojo interfaces require a security review to avoid
+# introducing new sandbox escapes.
+per-file *.mojom=set noparent
+per-file *.mojom=tsepez@chromium.org
diff --git a/chromium/content/public/common/appcache_info.h b/chromium/content/public/common/appcache_info.h
new file mode 100644
index 00000000000..436b193a965
--- /dev/null
+++ b/chromium/content/public/common/appcache_info.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2014 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 CONTENT_PUBLIC_COMMON_APPCACHE_INFO_H_
+#define CONTENT_PUBLIC_COMMON_APPCACHE_INFO_H_
+
+#include <vector>
+
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+
+static const int kAppCacheNoHostId = 0;
+static const int64 kAppCacheNoCacheId = 0;
+static const int64 kAppCacheNoResponseId = 0;
+static const int64 kAppCacheUnknownCacheId = -1;
+
+enum AppCacheStatus {
+ APPCACHE_STATUS_UNCACHED,
+ APPCACHE_STATUS_IDLE,
+ APPCACHE_STATUS_CHECKING,
+ APPCACHE_STATUS_DOWNLOADING,
+ APPCACHE_STATUS_UPDATE_READY,
+ APPCACHE_STATUS_OBSOLETE,
+ APPCACHE_STATUS_LAST = APPCACHE_STATUS_OBSOLETE
+};
+
+struct CONTENT_EXPORT AppCacheInfo {
+ AppCacheInfo();
+ ~AppCacheInfo();
+
+ GURL manifest_url;
+ base::Time creation_time;
+ base::Time last_update_time;
+ base::Time last_access_time;
+ int64 cache_id;
+ int64 group_id;
+ AppCacheStatus status;
+ int64 size;
+ bool is_complete;
+};
+
+typedef std::vector<AppCacheInfo> AppCacheInfoVector;
+
+} // namespace
+
+#endif // CONTENT_PUBLIC_COMMON_APPCACHE_INFO_H_
diff --git a/chromium/content/public/common/child_process_host.h b/chromium/content/public/common/child_process_host.h
index c8abedebd8b..cd9ed56ab58 100644
--- a/chromium/content/public/common/child_process_host.h
+++ b/chromium/content/public/common/child_process_host.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PULIC_COMMON_CHILD_PROCESS_HOST_H_
#define CONTENT_PULIC_COMMON_CHILD_PROCESS_HOST_H_
+#include "base/files/scoped_file.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "ipc/ipc_channel_proxy.h"
@@ -26,7 +27,7 @@ class ChildProcessHostDelegate;
// processes that run independent of the browser process.
class CONTENT_EXPORT ChildProcessHost : public IPC::Sender {
public:
- virtual ~ChildProcessHost() {}
+ ~ChildProcessHost() override {}
// This is a value never returned as the unique id of any child processes of
// any kind, including the values returned by RenderProcessHost::GetID().
@@ -98,7 +99,7 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Sender {
#if defined(OS_POSIX)
// See IPC::Channel::TakeClientFileDescriptor.
- virtual int TakeClientFileDescriptor() = 0;
+ virtual base::ScopedFD TakeClientFileDescriptor() = 0;
#endif
};
diff --git a/chromium/content/public/common/child_process_host_delegate.h b/chromium/content/public/common/child_process_host_delegate.h
index 06d30937cb6..9aa23ae8823 100644
--- a/chromium/content/public/common/child_process_host_delegate.h
+++ b/chromium/content/public/common/child_process_host_delegate.h
@@ -16,7 +16,7 @@ namespace content {
// Interface that all users of ChildProcessHost need to provide.
class ChildProcessHostDelegate : public IPC::Listener {
public:
- virtual ~ChildProcessHostDelegate() {}
+ ~ChildProcessHostDelegate() override {}
// Delegates return true if it's ok to shut down the child process (which is
// the default return value). The exception is if the host is in the middle of
diff --git a/chromium/content/public/common/common_param_traits.cc b/chromium/content/public/common/common_param_traits.cc
index 956801a178a..f4f9a0874b5 100644
--- a/chromium/content/public/common/common_param_traits.cc
+++ b/chromium/content/public/common/common_param_traits.cc
@@ -12,44 +12,6 @@
#include "content/public/common/url_utils.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/rect_f.h"
-
-namespace {
-
-struct SkBitmap_Data {
- // The configuration for the bitmap (bits per pixel, etc).
- SkBitmap::Config fConfig;
-
- // The width of the bitmap in pixels.
- uint32 fWidth;
-
- // The height of the bitmap in pixels.
- uint32 fHeight;
-
- void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
- fConfig = bitmap.config();
- fWidth = bitmap.width();
- fHeight = bitmap.height();
- }
-
- // Returns whether |bitmap| successfully initialized.
- bool InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels,
- size_t total_pixels) const {
- if (total_pixels) {
- bitmap->setConfig(fConfig, fWidth, fHeight, 0);
- if (!bitmap->allocPixels())
- return false;
- if (total_pixels != bitmap->getSize())
- return false;
- memcpy(bitmap->getPixels(), pixels, total_pixels);
- }
- return true;
- }
-};
-
-} // namespace
namespace IPC {
@@ -177,220 +139,6 @@ void ParamTraits<content::PageState>::Log(
l->append(")");
}
-void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
- m->WriteInt(p.x());
- m->WriteInt(p.y());
-}
-
-bool ParamTraits<gfx::Point>::Read(const Message* m, PickleIterator* iter,
- gfx::Point* r) {
- int x, y;
- if (!m->ReadInt(iter, &x) ||
- !m->ReadInt(iter, &y))
- return false;
- r->set_x(x);
- r->set_y(y);
- return true;
-}
-
-void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::string* l) {
- l->append(base::StringPrintf("(%d, %d)", p.x(), p.y()));
-}
-
-void ParamTraits<gfx::PointF>::Write(Message* m, const gfx::PointF& v) {
- ParamTraits<float>::Write(m, v.x());
- ParamTraits<float>::Write(m, v.y());
-}
-
-bool ParamTraits<gfx::PointF>::Read(const Message* m,
- PickleIterator* iter,
- gfx::PointF* r) {
- float x, y;
- if (!ParamTraits<float>::Read(m, iter, &x) ||
- !ParamTraits<float>::Read(m, iter, &y))
- return false;
- r->set_x(x);
- r->set_y(y);
- return true;
-}
-
-void ParamTraits<gfx::PointF>::Log(const gfx::PointF& v, std::string* l) {
- l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
-}
-
-void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
- DCHECK_GE(p.width(), 0);
- DCHECK_GE(p.height(), 0);
- int values[2] = { p.width(), p.height() };
- m->WriteBytes(&values, sizeof(int) * 2);
-}
-
-bool ParamTraits<gfx::Size>::Read(const Message* m,
- PickleIterator* iter,
- gfx::Size* r) {
- const char* char_values;
- if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
- return false;
- const int* values = reinterpret_cast<const int*>(char_values);
- if (values[0] < 0 || values[1] < 0)
- return false;
- r->set_width(values[0]);
- r->set_height(values[1]);
- return true;
-}
-
-void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::string* l) {
- l->append(base::StringPrintf("(%d, %d)", p.width(), p.height()));
-}
-
-void ParamTraits<gfx::SizeF>::Write(Message* m, const gfx::SizeF& p) {
- float values[2] = { p.width(), p.height() };
- m->WriteBytes(&values, sizeof(float) * 2);
-}
-
-bool ParamTraits<gfx::SizeF>::Read(const Message* m,
- PickleIterator* iter,
- gfx::SizeF* r) {
- const char* char_values;
- if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
- return false;
- const float* values = reinterpret_cast<const float*>(char_values);
- r->set_width(values[0]);
- r->set_height(values[1]);
- return true;
-}
-
-void ParamTraits<gfx::SizeF>::Log(const gfx::SizeF& p, std::string* l) {
- l->append(base::StringPrintf("(%f, %f)", p.width(), p.height()));
-}
-
-void ParamTraits<gfx::Vector2d>::Write(Message* m, const gfx::Vector2d& p) {
- int values[2] = { p.x(), p.y() };
- m->WriteBytes(&values, sizeof(int) * 2);
-}
-
-bool ParamTraits<gfx::Vector2d>::Read(const Message* m,
- PickleIterator* iter,
- gfx::Vector2d* r) {
- const char* char_values;
- if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
- return false;
- const int* values = reinterpret_cast<const int*>(char_values);
- r->set_x(values[0]);
- r->set_y(values[1]);
- return true;
-}
-
-void ParamTraits<gfx::Vector2d>::Log(const gfx::Vector2d& v, std::string* l) {
- l->append(base::StringPrintf("(%d, %d)", v.x(), v.y()));
-}
-
-void ParamTraits<gfx::Vector2dF>::Write(Message* m, const gfx::Vector2dF& p) {
- float values[2] = { p.x(), p.y() };
- m->WriteBytes(&values, sizeof(float) * 2);
-}
-
-bool ParamTraits<gfx::Vector2dF>::Read(const Message* m,
- PickleIterator* iter,
- gfx::Vector2dF* r) {
- const char* char_values;
- if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
- return false;
- const float* values = reinterpret_cast<const float*>(char_values);
- r->set_x(values[0]);
- r->set_y(values[1]);
- return true;
-}
-
-void ParamTraits<gfx::Vector2dF>::Log(const gfx::Vector2dF& v, std::string* l) {
- l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
-}
-
-void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
- int values[4] = { p.x(), p.y(), p.width(), p.height() };
- m->WriteBytes(&values, sizeof(int) * 4);
-}
-
-bool ParamTraits<gfx::Rect>::Read(const Message* m,
- PickleIterator* iter,
- gfx::Rect* r) {
- const char* char_values;
- if (!m->ReadBytes(iter, &char_values, sizeof(int) * 4))
- return false;
- const int* values = reinterpret_cast<const int*>(char_values);
- if (values[2] < 0 || values[3] < 0)
- return false;
- r->SetRect(values[0], values[1], values[2], values[3]);
- return true;
-}
-
-void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::string* l) {
- l->append(base::StringPrintf("(%d, %d, %d, %d)", p.x(), p.y(),
- p.width(), p.height()));
-}
-
-void ParamTraits<gfx::RectF>::Write(Message* m, const gfx::RectF& p) {
- float values[4] = { p.x(), p.y(), p.width(), p.height() };
- m->WriteBytes(&values, sizeof(float) * 4);
-}
-
-bool ParamTraits<gfx::RectF>::Read(const Message* m,
- PickleIterator* iter,
- gfx::RectF* r) {
- const char* char_values;
- if (!m->ReadBytes(iter, &char_values, sizeof(float) * 4))
- return false;
- const float* values = reinterpret_cast<const float*>(char_values);
- r->SetRect(values[0], values[1], values[2], values[3]);
- return true;
-}
-
-void ParamTraits<gfx::RectF>::Log(const gfx::RectF& p, std::string* l) {
- l->append(base::StringPrintf("(%f, %f, %f, %f)", p.x(), p.y(),
- p.width(), p.height()));
-}
-
-void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
- size_t fixed_size = sizeof(SkBitmap_Data);
- SkBitmap_Data bmp_data;
- bmp_data.InitSkBitmapDataForTransfer(p);
- m->WriteData(reinterpret_cast<const char*>(&bmp_data),
- static_cast<int>(fixed_size));
- size_t pixel_size = p.getSize();
- SkAutoLockPixels p_lock(p);
- m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
- static_cast<int>(pixel_size));
-}
-
-bool ParamTraits<SkBitmap>::Read(const Message* m,
- PickleIterator* iter,
- SkBitmap* r) {
- const char* fixed_data;
- int fixed_data_size = 0;
- if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
- (fixed_data_size <= 0)) {
- NOTREACHED();
- return false;
- }
- if (fixed_data_size != sizeof(SkBitmap_Data))
- return false; // Message is malformed.
-
- const char* variable_data;
- int variable_data_size = 0;
- if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
- (variable_data_size < 0)) {
- NOTREACHED();
- return false;
- }
- const SkBitmap_Data* bmp_data =
- reinterpret_cast<const SkBitmap_Data*>(fixed_data);
- return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
-}
-
-void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::string* l) {
- l->append("<SkBitmap>");
-}
-
} // namespace IPC
// Generate param traits write methods.
diff --git a/chromium/content/public/common/common_param_traits.h b/chromium/content/public/common/common_param_traits.h
index f527f162800..657ef646c71 100644
--- a/chromium/content/public/common/common_param_traits.h
+++ b/chromium/content/public/common/common_param_traits.h
@@ -25,20 +25,10 @@
#include "url/gurl.h"
#include "url/origin.h"
-class SkBitmap;
-
namespace content {
class PageState;
}
-namespace gfx {
-class Point;
-class Rect;
-class RectF;
-class Size;
-class Vector2d;
-} // namespace gfx
-
namespace net {
class HostPortPair;
class IPEndPoint;
@@ -87,70 +77,6 @@ struct CONTENT_EXPORT ParamTraits<content::PageState> {
};
template <>
-struct CONTENT_EXPORT ParamTraits<gfx::Point> {
- typedef gfx::Point param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::PointF> {
- typedef gfx::PointF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::Size> {
- typedef gfx::Size param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::SizeF> {
- typedef gfx::SizeF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::Vector2d> {
- typedef gfx::Vector2d param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::Vector2dF> {
- typedef gfx::Vector2dF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::Rect> {
- typedef gfx::Rect param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct CONTENT_EXPORT ParamTraits<gfx::RectF> {
- typedef gfx::RectF param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
struct ParamTraits<gfx::NativeWindow> {
typedef gfx::NativeWindow param_type;
static void Write(Message* m, const param_type& p) {
@@ -204,18 +130,6 @@ struct ParamTraits<TransportDIB::Id> {
};
#endif
-template <>
-struct CONTENT_EXPORT ParamTraits<SkBitmap> {
- typedef SkBitmap param_type;
- static void Write(Message* m, const param_type& p);
-
- // Note: This function expects parameter |r| to be of type &SkBitmap since
- // r->SetConfig() and r->SetPixels() are called.
- static bool Read(const Message* m, PickleIterator* iter, param_type* r);
-
- static void Log(const param_type& p, std::string* l);
-};
-
} // namespace IPC
#endif // CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_H_
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index 61d8b851434..cb17472ea91 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -9,10 +9,10 @@
#define CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
#include "content/public/common/console_message_level.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
#include "content/public/common/security_style.h"
#include "content/public/common/ssl_status.h"
+#include "content/public/common/web_preferences.h"
#include "content/public/common/webplugininfo.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/network_change_notifier.h"
@@ -22,13 +22,13 @@
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
+#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
-#include "webkit/common/webpreferences.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-IPC_ENUM_TRAITS(content::PageTransition) // Bitmask.
+IPC_ENUM_TRAITS(ui::PageTransition) // Bitmask.
IPC_ENUM_TRAITS_MAX_VALUE(net::NetworkChangeNotifier::ConnectionType,
net::NetworkChangeNotifier::CONNECTION_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(content::ConsoleMessageLevel,
@@ -37,11 +37,15 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::SecurityStyle,
content::SECURITY_STYLE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebReferrerPolicy,
blink::WebReferrerPolicyLast)
-IPC_ENUM_TRAITS_MAX_VALUE(webkit_glue::EditingBehavior,
- webkit_glue::EDITING_BEHAVIOR_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::EditingBehavior,
+ content::EDITING_BEHAVIOR_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(WindowOpenDisposition,
WINDOW_OPEN_DISPOSITION_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(net::RequestPriority, net::MAXIMUM_PRIORITY)
+IPC_ENUM_TRAITS_MAX_VALUE(content::V8CacheOptions,
+ content::V8_CACHE_OPTIONS_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::V8ScriptStreamingMode,
+ content::V8_SCRIPT_STREAMING_MODE_LAST)
IPC_STRUCT_TRAITS_BEGIN(blink::WebPoint)
IPC_STRUCT_TRAITS_MEMBER(x)
@@ -87,7 +91,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPluginInfo)
IPC_STRUCT_TRAITS_MEMBER(pepper_permissions)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
+IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(standard_font_family_map)
IPC_STRUCT_TRAITS_MEMBER(fixed_font_family_map)
IPC_STRUCT_TRAITS_MEMBER(serif_font_family_map)
@@ -106,8 +110,6 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(images_enabled)
IPC_STRUCT_TRAITS_MEMBER(plugins_enabled)
IPC_STRUCT_TRAITS_MEMBER(dom_paste_enabled)
- IPC_STRUCT_TRAITS_MEMBER(inspector_settings)
- IPC_STRUCT_TRAITS_MEMBER(site_specific_quirks_enabled)
IPC_STRUCT_TRAITS_MEMBER(shrinks_standalone_images_to_fit)
IPC_STRUCT_TRAITS_MEMBER(uses_universal_detector)
IPC_STRUCT_TRAITS_MEMBER(text_areas_are_resizable)
@@ -146,12 +148,12 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(accelerated_2d_canvas_enabled)
IPC_STRUCT_TRAITS_MEMBER(minimum_accelerated_2d_canvas_size)
IPC_STRUCT_TRAITS_MEMBER(antialiased_2d_canvas_disabled)
+ IPC_STRUCT_TRAITS_MEMBER(antialiased_clips_2d_canvas_enabled)
IPC_STRUCT_TRAITS_MEMBER(accelerated_2d_canvas_msaa_sample_count)
IPC_STRUCT_TRAITS_MEMBER(accelerated_filters_enabled)
IPC_STRUCT_TRAITS_MEMBER(deferred_filters_enabled)
IPC_STRUCT_TRAITS_MEMBER(container_culling_enabled)
- IPC_STRUCT_TRAITS_MEMBER(gesture_tap_highlight_enabled)
- IPC_STRUCT_TRAITS_MEMBER(accelerated_compositing_for_video_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(text_blobs_enabled)
IPC_STRUCT_TRAITS_MEMBER(allow_displaying_insecure_content)
IPC_STRUCT_TRAITS_MEMBER(allow_running_insecure_content)
IPC_STRUCT_TRAITS_MEMBER(enable_scroll_animator)
@@ -165,6 +167,7 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(pointer_events_max_touch_points)
IPC_STRUCT_TRAITS_MEMBER(sync_xhr_in_documents_enabled)
IPC_STRUCT_TRAITS_MEMBER(deferred_image_decoding_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(image_color_profiles_enabled)
IPC_STRUCT_TRAITS_MEMBER(should_respect_image_orientation)
IPC_STRUCT_TRAITS_MEMBER(number_of_cpu_cores)
IPC_STRUCT_TRAITS_MEMBER(editing_behavior)
@@ -174,16 +177,20 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(main_frame_resizes_are_orientation_changes)
IPC_STRUCT_TRAITS_MEMBER(initialize_at_minimum_page_scale)
IPC_STRUCT_TRAITS_MEMBER(smart_insert_delete_enabled)
- IPC_STRUCT_TRAITS_MEMBER(compositor_touch_hit_testing)
IPC_STRUCT_TRAITS_MEMBER(cookie_enabled)
IPC_STRUCT_TRAITS_MEMBER(navigate_on_drag_drop)
IPC_STRUCT_TRAITS_MEMBER(spatial_navigation_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(v8_cache_options)
+ IPC_STRUCT_TRAITS_MEMBER(v8_script_streaming_enabled)
+ IPC_STRUCT_TRAITS_MEMBER(v8_script_streaming_mode)
+ IPC_STRUCT_TRAITS_MEMBER(slimming_paint_enabled)
IPC_STRUCT_TRAITS_MEMBER(pepper_accelerated_video_decode_enabled)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(text_autosizing_enabled)
IPC_STRUCT_TRAITS_MEMBER(font_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(device_scale_adjustment)
IPC_STRUCT_TRAITS_MEMBER(force_enable_zoom)
+ IPC_STRUCT_TRAITS_MEMBER(fullscreen_supported)
IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_media_playback)
IPC_STRUCT_TRAITS_MEMBER(default_video_poster_url)
@@ -191,6 +198,7 @@ IPC_STRUCT_TRAITS_BEGIN(WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(use_legacy_background_size_shorthand_behavior)
IPC_STRUCT_TRAITS_MEMBER(wide_viewport_quirk)
IPC_STRUCT_TRAITS_MEMBER(use_wide_viewport)
+ IPC_STRUCT_TRAITS_MEMBER(force_zero_layout_height)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_layout_size_quirk)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_merge_content_quirk)
IPC_STRUCT_TRAITS_MEMBER(viewport_meta_non_user_scalable_quirk)
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index 3a9769cbfd1..425c40ff29d 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -109,10 +109,6 @@ bool ContentClient::GetSandboxProfileForSandboxType(
int* sandbox_profile_resource_id) const {
return false;
}
-
-std::string ContentClient::GetCarbonInterposePath() const {
- return std::string();
-}
#endif
} // namespace content
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index ec52600a349..13f0d5c57dc 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -132,10 +132,6 @@ class CONTENT_EXPORT ContentClient {
virtual bool GetSandboxProfileForSandboxType(
int sandbox_type,
int* sandbox_profile_resource_id) const;
-
- // Gets the Carbon interposing path to give to DYLD. Returns an empty string
- // if the embedder doesn't bundle it.
- virtual std::string GetCarbonInterposePath() const;
#endif
private:
diff --git a/chromium/content/public/common/content_constants.cc b/chromium/content/public/common/content_constants.cc
index 251db885e1c..5034cb4d19d 100644
--- a/chromium/content/public/common/content_constants.cc
+++ b/chromium/content/public/common/content_constants.cc
@@ -20,6 +20,7 @@ const char kFlashPluginSwfDescription[] = "Shockwave Flash";
const char kFlashPluginSplMimeType[] = "application/futuresplash";
const char kFlashPluginSplExtension[] = "spl";
const char kFlashPluginSplDescription[] = "FutureSplash Player";
+const char kSilverlightPluginMimeTypePrefix[] = "application/x-silverlight";
// This number used to be limited to 32 in the past (see b/535234).
const size_t kMaxRendererProcessCount = 82;
diff --git a/chromium/content/public/common/content_constants.h b/chromium/content/public/common/content_constants.h
index 9b3b0e38671..df9d557ff76 100644
--- a/chromium/content/public/common/content_constants.h
+++ b/chromium/content/public/common/content_constants.h
@@ -31,6 +31,7 @@ CONTENT_EXPORT extern const char kFlashPluginSwfDescription[];
CONTENT_EXPORT extern const char kFlashPluginSplMimeType[];
CONTENT_EXPORT extern const char kFlashPluginSplExtension[];
CONTENT_EXPORT extern const char kFlashPluginSplDescription[];
+CONTENT_EXPORT extern const char kSilverlightPluginMimeTypePrefix[];
CONTENT_EXPORT extern const size_t kMaxRendererProcessCount;
diff --git a/chromium/content/public/common/content_descriptors.h b/chromium/content/public/common/content_descriptors.h
index 5a6b234e5d9..db972015048 100644
--- a/chromium/content/public/common/content_descriptors.h
+++ b/chromium/content/public/common/content_descriptors.h
@@ -16,6 +16,12 @@ enum {
#if defined(OS_ANDROID)
kAndroidPropertyDescriptor,
kAndroidICUDataDescriptor,
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+ kV8NativesDataDescriptor,
+ kV8SnapshotDataDescriptor,
+#endif
+
#endif
// The first key that embedders can use to register descriptors (see
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index f10bed115cd..03c757801f1 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -81,15 +81,6 @@ const char kDisable3DAPIs[] = "disable-3d-apis";
// Disable gpu-accelerated 2d canvas.
const char kDisableAccelerated2dCanvas[] = "disable-accelerated-2d-canvas";
-// Disables accelerated compositing for backgrounds of root layers with
-// background-attachment: fixed.
-const char kDisableAcceleratedFixedRootBackground[] =
- "disable-accelerated-fixed-root-background";
-
-// Disables accelerated compositing for overflow scroll.
-const char kDisableAcceleratedOverflowScroll[] =
- "disable-accelerated-overflow-scroll";
-
// Disables layer squashing.
const char kDisableLayerSquashing[] =
"disable-layer-squashing";
@@ -105,9 +96,13 @@ const char kDisableApplicationCache[] = "disable-application-cache";
// users with many windows/tabs and lots of memory.
const char kDisableBackingStoreLimit[] = "disable-backing-store-limit";
-// See comment for kEnableCompositingForFixedPosition.
-const char kDisableCompositingForFixedPosition[] =
- "disable-fixed-position-compositing";
+// Disable the Blink Scheduler. Ensures there's no reordering of blink tasks.
+// This switch is intended only for performance tests.
+const char kDisableBlinkScheduler[] = "disable-blink-scheduler";
+
+// Disable the creation of compositing layers when it would prevent LCD text.
+const char kDisablePreferCompositingToLCDText[] =
+ "disable-prefer-compositing-to-lcd-text";
// See comment for kEnableCompositingForTransition.
const char kDisableCompositingForTransition[] =
@@ -119,13 +114,6 @@ const char kDisableDatabases[] = "disable-databases";
// Disables delegated renderer.
const char kDisableDelegatedRenderer[] = "disable-delegated-renderer";
-// Disables desktop notifications (default enabled on windows).
-const char kDisableDesktopNotifications[] = "disable-desktop-notifications";
-
-// Disables experimental navigator content utils implementation.
-const char kDisableNavigatorContentUtils[] =
- "disable-navigator-content-utils";
-
// Handles URL requests by NPAPI plugins through the renderer.
const char kDisableDirectNPAPIRequests[] = "disable-direct-npapi-requests";
@@ -134,15 +122,9 @@ const char kDisableDirectNPAPIRequests[] = "disable-direct-npapi-requests";
extern const char kDisableDomainBlockingFor3DAPIs[] =
"disable-domain-blocking-for-3d-apis";
-// Disable running the SharedWorker inside the renderer process.
-const char kDisableEmbeddedSharedWorker[] = "disable-embedded-shared-worker";
-
// Disable experimental WebGL support.
const char kDisableExperimentalWebGL[] = "disable-webgl";
-// Disable the fast text autosizing implementation.
-const char kDisableFastTextAutosizing[] = "disable-fast-text-autosizing";
-
// Disable FileSystem API.
const char kDisableFileSystem[] = "disable-file-system";
@@ -152,8 +134,6 @@ const char kDisableFlash3d[] = "disable-flash-3d";
// Disable Stage3D inside of flapper.
const char kDisableFlashStage3d[] = "disable-flash-stage3d";
-const char kDisableGestureTapHighlight[] = "disable-gesture-tap-highlight";
-
// Disables GPU hardware acceleration. If software renderer is not in place,
// then the GPU process won't launch.
const char kDisableGpu[] = "disable-gpu";
@@ -225,6 +205,10 @@ const char kDisableLogging[] = "disable-logging";
// Disables Media Source API (i.e., the MediaSource object).
const char kDisableMediaSource[] = "disable-media-source";
+// Disable rasterizer that writes directly to GPU memory.
+// Overrides the kEnableOneCopy flag.
+const char kDisableOneCopy[] = "disable-one-copy";
+
// Disable Pepper3D.
const char kDisablePepper3d[] = "disable-pepper-3d";
@@ -246,9 +230,6 @@ const char kDisableRemoteFonts[] = "disable-remote-fonts";
// Turns off the accessibility in the renderer.
const char kDisableRendererAccessibility[] = "disable-renderer-accessibility";
-// Disables the new layout/paint system which paints after layout is complete.
-const char kDisableRepaintAfterLayout[] = "disable-repaint-after-layout";
-
// Disable the seccomp filter sandbox (seccomp-bpf) (Linux only).
const char kDisableSeccompFilterSandbox[] = "disable-seccomp-filter-sandbox";
@@ -258,11 +239,12 @@ const char kDisableSessionStorage[] = "disable-session-storage";
// Disable the setuid sandbox (Linux only).
const char kDisableSetuidSandbox[] = "disable-setuid-sandbox";
-// Enable shared workers. Functionality not yet complete.
+// Disable shared workers.
const char kDisableSharedWorkers[] = "disable-shared-workers";
-// Disables site-specific tailoring to compatibility issues in WebKit.
-const char kDisableSiteSpecificQuirks[] = "disable-site-specific-quirks";
+// For tests, disable single thread scheduler and only manually composite.
+const char kDisableSingleThreadProxyScheduler[] =
+ "disable-single-thread-proxy-scheduler";
// Disable smooth scrolling for testing.
const char kDisableSmoothScrolling[] = "disable-smooth-scrolling";
@@ -270,12 +252,20 @@ const char kDisableSmoothScrolling[] = "disable-smooth-scrolling";
// Disables the use of a 3D software rasterizer.
const char kDisableSoftwareRasterizer[] = "disable-software-rasterizer";
-// Disable False Start in SSL and TLS connections.
-const char kDisableSSLFalseStart[] = "disable-ssl-false-start";
+// Disables SVG 1.1 DOM.
+const char kDisableSVG1DOM[] = "disable-svg1dom";
// Disable multithreaded GPU compositing of web content.
const char kDisableThreadedCompositing[] = "disable-threaded-compositing";
+// Disable multithreaded, compositor scrolling of web content.
+const char kDisableThreadedScrolling[] = "disable-threaded-scrolling";
+
+// Disable V8 idle notification after commit.
+// Overrides kEnableV8IdleNotificationAfterCommit.
+const char kDisableV8IdleNotificationAfterCommit[] =
+ "disable-v8-idle-notification-after-commit";
+
// Don't enforce the same-origin policy. (Used by people testing their sites.)
const char kDisableWebSecurity[] = "disable-web-security";
@@ -285,35 +275,27 @@ const char kDisableXSLT[] = "disable-xslt";
// Disables Blink's XSSAuditor. The XSSAuditor mitigates reflective XSS.
const char kDisableXSSAuditor[] = "disable-xss-auditor";
-// Disable rasterizer that writes directly to GPU memory associated with tiles.
-// Overrides the kEnableZeroCopy flag.
-const char kDisableZeroCopy[] = "disable-zero-copy";
-
// Specifies if the |DOMAutomationController| needs to be bound in the
// renderer. This binding happens on per-frame basis and hence can potentially
// be a performance bottleneck. One should only enable it when automating dom
// based tests.
const char kDomAutomationController[] = "dom-automation";
+// Enable antialiasing on 2d canvas clips (as opposed to draw operations)
+const char kEnable2dCanvasClipAntialiasing[] = "enable-2d-canvas-clip-aa";
+
+// Enable partially decoding jpeg images using the GPU.
+// At least YUV decoding will be accelerated when using this flag.
+// Has no effect unless GPU rasterization is enabled.
+const char kEnableAcceleratedJpegDecoding[] =
+ "enable-accelerated-jpeg-decoding";
+
// Enable bleeding-edge code to make Chrome draw content faster. The changes
// behind this path are very likely to break lots of content.
// ** DO NOT use this flag unless you know what you are doing. **
const char kEnableBleedingEdgeRenderingFastPaths[] =
"enable-bleeding-edge-rendering-fast-paths";
-// Disable deferred image filters.
-const char kDisableDeferredFilters[] = "disable-deferred-filters";
-
-// Enables accelerated compositing for backgrounds of root layers with
-// background-attachment: fixed.
-const char kEnableAcceleratedFixedRootBackground[] =
- "enable-accelerated-fixed-root-background";
-
-// Enables accelerated compositing for overflow scroll. Promotes eligible
-// overflow:scroll elements to layers to enable accelerated scrolling for them.
-const char kEnableAcceleratedOverflowScroll[] =
- "enable-accelerated-overflow-scroll";
-
// Enables LCD text.
const char kEnableLCDText[] = "enable-lcd-text";
@@ -329,21 +311,18 @@ const char kEnableLayerSquashing[] =
// Enable experimental container node culling.
const char kEnableContainerCulling[] = "enable-container-culling";
+// Enable the experimental Credential Manager JavaScript API.
+const char kEnableCredentialManagerAPI[] = "enable-credential-manager-api";
+
// Use a BeginFrame signal from browser to renderer to schedule rendering.
const char kEnableBeginFrameScheduling[] = "enable-begin-frame-scheduling";
-// Enable the creation of compositing layers for fixed position
-// elements. Three options are needed to support four possible scenarios:
-// 1. Default (disabled)
-// 2. Enabled always (to allow dogfooding)
-// 3. Disabled always (to give safety fallback for users)
-// 4. Enabled only if we detect a highDPI display
-//
-// Option #4 may soon be the default, because the feature is needed soon for
-// high DPI, but cannot be used (yet) for low DPI. Options #2 and #3 will
-// override Option #4.
-const char kEnableCompositingForFixedPosition[] =
- "enable-fixed-position-compositing";
+// Enable the creation of compositing layers when it would prevent LCD text.
+const char kEnablePreferCompositingToLCDText[] =
+ "enable-prefer-compositing-to-lcd-text";
+
+// PlzNavigate: Use the experimental browser-side navigation path.
+const char kEnableBrowserSideNavigation[] = "enable-browser-side-navigation";
// Enable/Disable the creation of compositing layers for RenderLayers with a
// transition on a property that supports accelerated animation (that is,
@@ -361,6 +340,10 @@ const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
// Enables delegated renderer.
const char kEnableDelegatedRenderer[] = "enable-delegated-renderer";
+// Enables display list based 2d canvas implementation.
+const char kEnableDisplayList2dCanvas[] = "enable-display-list-2d-canvas";
+const char kDisableDisplayList2dCanvas[] = "disable-display-list-2d-canvas";
+
// Enables restarting interrupted downloads.
const char kEnableDownloadResumption[] = "enable-download-resumption";
@@ -379,12 +362,6 @@ const char kEnableExperimentalWebPlatformFeatures[] =
// for example page cycler and layout tests. See bug 1157243.
const char kEnableFileCookies[] = "enable-file-cookies";
-// Enable the fast text autosizing implementation.
-const char kEnableFastTextAutosizing[] = "enable-fast-text-autosizing";
-
-// Enable Gesture Tap Highlight
-const char kEnableGestureTapHighlight[] = "enable-gesture-tap-highlight";
-
// Enables TRACE for GL calls in the renderer.
const char kEnableGpuClientTracing[] = "enable-gpu-client-tracing";
@@ -397,16 +374,12 @@ const char kEnableGpuRasterization[] = "enable-gpu-rasterization";
// tiles may be displayed during fast scrolls especially on slower devices.
const char kEnableLowResTiling[] = "enable-low-res-tiling";
-// See comment for kEnableCompositingForFixedPosition.
-const char kEnableHighDpiCompositingForFixedPosition[] =
- "enable-high-dpi-fixed-position-compositing";
+// Dynamically apply color profiles to web content images.
+const char kEnableImageColorProfiles[] = "enable-image-color-profiles";
// Paint content on the compositor thread instead of the main thread.
const char kEnableImplSidePainting[] = "enable-impl-side-painting";
-// Enables support for inband text tracks in media content.
-const char kEnableInbandTextTracks[] = "enable-inband-text-tracks";
-
// Force logging to be enabled. Logging is disabled by default in release
// builds.
const char kEnableLogging[] = "enable-logging";
@@ -414,16 +387,15 @@ const char kEnableLogging[] = "enable-logging";
// Enables the memory benchmarking extension
const char kEnableMemoryBenchmarking[] = "enable-memory-benchmarking";
+// Enables the network information API.
+const char kEnableNetworkInformation[] = "enable-network-information";
+
// Enable rasterizer that writes directly to GPU memory.
const char kEnableOneCopy[] = "enable-one-copy";
// Enables use of hardware overlay for fullscreen video playback. Android only.
const char kEnableOverlayFullscreenVideo[] = "enable-overlay-fullscreen-video";
-// Disables blink subtitle and media control on top of overlay fullscreen video.
-const char kDisableOverlayFullscreenVideoSubtitle[] =
- "disable-overlay-fullscreen-video-subtitle";
-
// Forward overscroll event data from the renderer to the browser.
const char kEnableOverscrollNotifications[] = "enable-overscroll-notifications";
@@ -436,20 +408,16 @@ const char kEnablePinch[] = "enable-pinch";
// also applys to workers.
const char kEnablePreciseMemoryInfo[] = "enable-precise-memory-info";
-// Enable caching of pre-parsed JS script data. See http://crbug.com/32407.
-const char kEnablePreparsedJsCaching[] = "enable-preparsed-js-caching";
+// Set options to cache V8 data. (off, preparse data, or code)
+const char kV8CacheOptions[] = "v8-cache-options";
// Enables the CSS multicol implementation that uses the regions implementation.
const char kEnableRegionBasedColumns[] =
"enable-region-based-columns";
-// Enables the new layout/paint system which paints after layout is complete.
-const char kEnableRepaintAfterLayout[] =
- "enable-repaint-after-layout";
-
-// Enables targeted style recalculation optimizations.
-const char kEnableTargetedStyleRecalc[] =
- "enable-targeted-style-recalc";
+// Replaces renderer-browser IPC channel with ChnanelMojo.
+const char kEnableRendererMojoChannel[] =
+ "enable-renderer-mojo-channel";
// Cause the OS X sandbox write to syslog every time an access to a resource
// is denied by the sandbox.
@@ -463,15 +431,15 @@ const char kEnableSeccompFilterSandbox[] =
// Enables the Skia benchmarking extension
const char kEnableSkiaBenchmarking[] = "enable-skia-benchmarking";
+// Enables slimming paint: http://www.chromium.org/blink/slimming-paint
+const char kEnableSlimmingPaint[] = "enable-slimming-paint";
+
// On platforms that support it, enables smooth scroll animation.
const char kEnableSmoothScrolling[] = "enable-smooth-scrolling";
// Enable spatial navigation
const char kEnableSpatialNavigation[] = "enable-spatial-navigation";
-// Enables the synthesis part of the Web Speech API.
-const char kEnableSpeechSynthesis[] = "enable-speech-synthesis";
-
// Enables StatsTable, logging statistics to a global named shared memory table.
const char kEnableStatsTable[] = "enable-stats-table";
@@ -487,10 +455,6 @@ const char kEnableStatsTable[] = "enable-stats-table";
// cookies on cross-site requests.
const char kEnableStrictSiteIsolation[] = "enable-strict-site-isolation";
-// Enable support for ServiceWorker. See
-// https://github.com/slightlyoff/ServiceWorker for more information.
-const char kEnableServiceWorker[] = "enable-service-worker";
-
// Enable support for sync events in ServiceWorkers.
const char kEnableServiceWorkerSync[] = "enable-service-worker-sync";
@@ -498,13 +462,33 @@ const char kEnableServiceWorkerSync[] = "enable-service-worker-sync";
// SYN packet.
const char kEnableTcpFastOpen[] = "enable-tcp-fastopen";
-// Enable multithreaded GPU compositing of web content.
+// Enable experimental text blob rendering.
+const char kEnableTextBlobs[] = "enable-text-blobs";
+
+// Enabled threaded compositing for layout tests.
const char kEnableThreadedCompositing[] = "enable-threaded-compositing";
+// Enable tracing during the execution of browser tests.
+const char kEnableTracing[] = "enable-tracing";
+
+// The filename to write the output of the test tracing to.
+const char kEnableTracingOutput[] = "enable-tracing-output";
+
// Enable screen capturing support for MediaStream API.
const char kEnableUserMediaScreenCapturing[] =
"enable-usermedia-screen-capturing";
+// Enables streaming scripts to V8 while loading.
+const char kEnableV8ScriptStreaming[] = "enable-v8-script-streaming";
+
+// Send a notification from RenderWidgetCompositor to V8 to do idle work
+// (e.g. garbage collection) after the commit until the beginning of the next
+// frame. This moves the work off the critical path where compositor is waiting
+// for the main thread. The flag is experimental until the implementation of the
+// V8 idle handler is completed.
+const char kEnableV8IdleNotificationAfterCommit[] =
+ "enable-v8-idle-notification-after-commit";
+
// Enables the use of the @viewport CSS rule, which allows
// pages to control aspects of their own layout. This also turns on touch-screen
// pinch gestures.
@@ -522,9 +506,6 @@ const char kMainFrameResizesAreOrientationChanges[] =
// Enable the Vtune profiler support.
const char kEnableVtune[] = "enable-vtune-support";
-// Enable SVG Animations on the Web Animations model.
-const char kEnableWebAnimationsSVG[] = "enable-web-animations-svg";
-
// Enables WebGL extensions not yet approved by the community.
const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
@@ -540,14 +521,14 @@ const char kEnableZeroCopy[] = "enable-zero-copy";
// Load NPAPI plugins from the specified directory.
const char kExtraPluginDir[] = "extra-plugin-dir";
-// Some field trials may be randomized in the browser, and the randomly selected
-// outcome needs to be propagated to the renderer. For instance, this is used
-// to modify histograms recorded in the renderer, or to get the renderer to
-// also set of its state (initialize, or not initialize components) to match the
-// experiment(s). The option is also useful for forcing field trials when
-// testing changes locally. The argument is a list of name and value pairs,
-// separated by slashes. See FieldTrialList::CreateTrialsFromString() in
-// field_trial.h for details.
+// This option can be used to force field trials when testing changes locally.
+// The argument is a list of name and value pairs, separated by slashes. If a
+// trial name is prefixed with an asterisk, that trial will start activated.
+// For example, the following argument defines two trials, with the second one
+// activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/"
+// This option is also used by the browser to send the list of trials to
+// renderers, using the same format. See
+// FieldTrialList::CreateTrialsFromString() in field_trial.h for details.
const char kForceFieldTrials[] = "force-fieldtrials";
// Always use the Skia GPU backend for drawing layer tiles. Only valid with GPU
@@ -576,15 +557,14 @@ const char kGpuLauncher[] = "gpu-launcher";
// Makes this process a GPU sub-process.
const char kGpuProcess[] = "gpu-process";
-// Allow shmat system call in GPU sandbox.
+// Allows shmat() system call in the GPU sandbox.
const char kGpuSandboxAllowSysVShm[] = "gpu-sandbox-allow-sysv-shm";
// Makes GPU sandbox failures fatal.
const char kGpuSandboxFailuresFatal[] = "gpu-sandbox-failures-fatal";
-// Allow GPU sandbox to start later
-const char kGpuSandboxStartAfterInitialization[] =
- "gpu-sandbox-start-after-initialization";
+// Starts the GPU sandbox before creating a GL context.
+const char kGpuSandboxStartEarly[] = "gpu-sandbox-start-early";
// Causes the GPU process to display a dialog on launch.
const char kGpuStartupDialog[] = "gpu-startup-dialog";
@@ -648,9 +628,16 @@ const char kNoSandbox[] = "no-sandbox";
// Number of worker threads used to rasterize content.
const char kNumRasterThreads[] = "num-raster-threads";
-// Enables or disables history navigation in response to horizontal overscroll.
-// Set the value to '1' to enable the feature, and set to '0' to disable.
-// Defaults to enabled.
+// Controls the behavior of history navigation in response to horizontal
+// overscroll.
+// Set the value to '0' to disable.
+// Set the value to '1' to enable the behavior where pages slide in and out in
+// response to the horizontal overscroll gesture and a screenshot of the target
+// page is shown.
+// Set the value to '2' to enable the simplified overscroll UI where a
+// navigation arrow slides in from the side of the screen in response to the
+// horizontal overscroll gesture.
+// Defaults to '1'.
const char kOverscrollHistoryNavigation[] =
"overscroll-history-navigation";
@@ -731,6 +718,9 @@ const char kRendererProcessLimit[] = "renderer-process-limit";
// Causes the renderer process to display a dialog on launch.
const char kRendererStartupDialog[] = "renderer-startup-dialog";
+// Handles frame scrolls via the root RenderLayer instead of the FrameView.
+const char kRootLayerScrolls[] = "root-layer-scrolls";
+
// Causes the process to run as a sandbox IPC subprocess.
const char kSandboxIPCProcess[] = "sandbox-ipc";
@@ -831,6 +821,8 @@ const char kTraceStartupDuration[] = "trace-startup-duration";
// all events since startup.
const char kTraceStartupFile[] = "trace-startup-file";
+// Sets the target URL for uploading tracing data.
+const char kTraceUploadURL[] = "trace-upload-url";
// Prioritizes the UI's command stream in the GPU process
@@ -875,9 +867,6 @@ const char kValidateInputEventStream[] = "validate-input-event-stream";
// kWaitForDebugger flag passed on or not.
const char kWaitForDebuggerChildren[] = "wait-for-debugger-children";
-// Causes the process to run as a worker subprocess.
-const char kWorkerProcess[] = "worker";
-
// The prefix used when starting the zygote process. (i.e. 'gdb --args')
const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
@@ -889,9 +878,6 @@ const char kZygoteProcess[] = "zygote";
// NS and AGC will be done in PeerConnection instead of MediaStreamTrack.
const char kDisableAudioTrackProcessing[] = "disable-audio-track-processing";
-// Disables WebRTC device enumeration.
-const char kDisableDeviceEnumeration[] = "disable-device-enumeration";
-
// Disables HW decode acceleration for WebRTC.
const char kDisableWebRtcHWDecoding[] = "disable-webrtc-hw-decoding";
@@ -904,6 +890,9 @@ const char kDisableWebRtcHWEncoding[] = "disable-webrtc-hw-encoding";
// Enables VP8 HW encode acceleration for WebRTC.
const char kEnableWebRtcHWVp8Encoding[] = "enable-webrtc-hw-vp8-encoding";
+
+// Enables H264 HW encode acceleration for WebRTC.
+const char kEnableWebRtcHWH264Encoding[] = "enable-webrtc-hw-h264-encoding";
#endif
#if defined(OS_ANDROID)
@@ -932,6 +921,10 @@ const char kNetworkCountryIso[] = "network-country-iso";
// Enables remote debug over HTTP on the specified socket name.
const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
+
+// Block ChildProcessMain thread of the renderer's ChildProcessService until a
+// Java debugger is attached.
+const char kRendererWaitForJavaDebugger[] = "renderer-wait-for-java-debugger";
#endif
// Disable web audio API.
@@ -940,30 +933,38 @@ const char kDisableWebAudio[] = "disable-webaudio";
#if defined(OS_CHROMEOS)
// Disables panel fitting (used for mirror mode).
const char kDisablePanelFitting[] = "disable-panel-fitting";
+
+// Enables VA-API accelerated video encode.
+const char kDisableVaapiAcceleratedVideoEncode[] =
+ "disable-vaapi-accelerated-video-encode";
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-const char kEnableCarbonInterposing[] = "enable-carbon-interposing";
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+// Allows sending text-to-speech requests to speech-dispatcher, a common
+// Linux speech service. Because it's buggy, the user must explicitly
+// enable it so that visiting a random webpage can't cause instability.
+const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher";
+#endif
+#if defined(OS_MACOSX) && !defined(OS_IOS)
// Disables support for Core Animation plugins. This is triggered when
-// accelerated compositing is disabled. See http://crbug.com/122430 .
+// accelerated compositing is disabled. See http://crbug.com/122430.
const char kDisableCoreAnimationPlugins[] =
"disable-core-animation-plugins";
+
+// Allows input events to be handed on the compositor thread.
+// This feature is under development, see http://crbug.com/138003.
+extern const char kEnableThreadedEventHandlingMac[] =
+ "enable-threaded-event-handling-mac";
#endif
#if defined(OS_WIN)
// Device scale factor passed to certain processes like renderers, etc.
const char kDeviceScaleFactor[] = "device-scale-factor";
-// Disables the DirectWrite font rendering system on windows.
-const char kDisableDirectWrite[] = "disable-direct-write";
-
// Disable the Legacy Window which corresponds to the size of the WebContents.
const char kDisableLegacyIntermediateWindow[] = "disable-legacy-window";
-// Use high resolution timers for TimeTicks.
-const char kEnableHighResolutionTime[] = "enable-high-resolution-time";
-
// Enable the Win32K process mitigation policy for renderer processes which
// prevents them from invoking user32 and gdi32 system calls which enter
// the kernel. This is only supported on Windows 8 and beyond.
@@ -971,6 +972,11 @@ const char kEnableWin32kRendererLockDown[]
= "enable_win32k_renderer_lockdown";
#endif
+#if defined(ENABLE_PLUGINS)
+// Enables the plugin power saver feature.
+const char kEnablePluginPowerSaver[] = "enable-plugin-power-saver";
+#endif
+
// Don't dump stuff here, follow the same order as the header.
} // namespace switches
diff --git a/chromium/content/public/common/content_switches.h b/chromium/content/public/common/content_switches.h
index 6b7042a2126..360aded3172 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -33,27 +33,23 @@ CONTENT_EXPORT extern const char kDefaultTileHeight[];
CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
CONTENT_EXPORT extern const char kDisable3DAPIs[];
CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
-CONTENT_EXPORT extern const char kDisableAcceleratedFixedRootBackground[];
-CONTENT_EXPORT extern const char kDisableAcceleratedOverflowScroll[];
CONTENT_EXPORT extern const char kDisableLayerSquashing[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
CONTENT_EXPORT extern const char kDisableApplicationCache[];
extern const char kDisableBackingStoreLimit[];
-CONTENT_EXPORT extern const char kDisableCompositingForFixedPosition[];
+CONTENT_EXPORT extern const char kDisableBlinkScheduler[];
+CONTENT_EXPORT extern const char kDisablePreferCompositingToLCDText[];
CONTENT_EXPORT extern const char kDisableCompositingForTransition[];
CONTENT_EXPORT extern const char kDisableDatabases[];
CONTENT_EXPORT extern const char kDisableDelegatedRenderer[];
-extern const char kDisableDesktopNotifications[];
extern const char kDisableDirectNPAPIRequests[];
CONTENT_EXPORT extern const char kDisableDistanceFieldText[];
+CONTENT_EXPORT extern const char kDisableDisplayList2dCanvas[];
extern const char kDisableDomainBlockingFor3DAPIs[];
-CONTENT_EXPORT extern const char kDisableEmbeddedSharedWorker[];
CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
-CONTENT_EXPORT extern const char kDisableFastTextAutosizing[];
CONTENT_EXPORT extern const char kDisableFileSystem[];
CONTENT_EXPORT extern const char kDisableFlash3d[];
CONTENT_EXPORT extern const char kDisableFlashStage3d[];
-CONTENT_EXPORT extern const char kDisableGestureTapHighlight[];
CONTENT_EXPORT extern const char kDisableGpu[];
CONTENT_EXPORT extern const char kDisableGpuCompositing[];
extern const char kDisableGpuProcessCrashLimit[];
@@ -72,84 +68,84 @@ extern const char kDisableKillAfterBadIPC[];
CONTENT_EXPORT extern const char kDisableLocalStorage[];
CONTENT_EXPORT extern const char kDisableLogging[];
CONTENT_EXPORT extern const char kDisableMediaSource[];
-extern const char kDisableNavigatorContentUtils[];
+CONTENT_EXPORT extern const char kDisableOneCopy[];
extern const char kDisablePepper3d[];
CONTENT_EXPORT extern const char kDisablePinch[];
CONTENT_EXPORT extern const char kDisablePlugins[];
CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
extern const char kDisableRemoteFonts[];
extern const char kDisableRendererAccessibility[];
-CONTENT_EXPORT extern const char kDisableRepaintAfterLayout[];
CONTENT_EXPORT extern const char kDisableSeccompFilterSandbox[];
extern const char kDisableSessionStorage[];
CONTENT_EXPORT extern const char kDisableSetuidSandbox[];
CONTENT_EXPORT extern const char kDisableSharedWorkers[];
-extern const char kDisableSiteSpecificQuirks[];
+CONTENT_EXPORT extern const char kDisableSingleThreadProxyScheduler[];
CONTENT_EXPORT extern const char kDisableSmoothScrolling[];
CONTENT_EXPORT extern const char kDisableSoftwareRasterizer[];
-CONTENT_EXPORT extern const char kDisableSSLFalseStart[];
+CONTENT_EXPORT extern const char kDisableSVG1DOM[];
CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
+CONTENT_EXPORT extern const char kDisableThreadedScrolling[];
+extern const char kDisableV8IdleNotificationAfterCommit[];
CONTENT_EXPORT extern const char kDisableWebSecurity[];
extern const char kDisableXSLT[];
extern const char kDisableXSSAuditor[];
-CONTENT_EXPORT extern const char kDisableZeroCopy[];
CONTENT_EXPORT extern const char kDomAutomationController[];
+extern const char kEnable2dCanvasClipAntialiasing[];
+CONTENT_EXPORT extern const char kEnableAcceleratedJpegDecoding[];
CONTENT_EXPORT extern const char kEnableBleedingEdgeRenderingFastPaths[];
-CONTENT_EXPORT extern const char kDisableDeferredFilters[];
-CONTENT_EXPORT extern const char kEnableAcceleratedFixedRootBackground[];
-CONTENT_EXPORT extern const char kEnableAcceleratedOverflowScroll[];
CONTENT_EXPORT extern const char kEnableLayerSquashing[];
CONTENT_EXPORT extern const char kEnableContainerCulling[];
+CONTENT_EXPORT extern const char kEnableCredentialManagerAPI[];
CONTENT_EXPORT extern const char kEnableBeginFrameScheduling[];
-CONTENT_EXPORT extern const char kEnableCompositingForFixedPosition[];
+CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[];
+CONTENT_EXPORT extern const char kEnableBrowserSideNavigation[];
CONTENT_EXPORT extern const char kEnableCompositingForTransition[];
CONTENT_EXPORT extern const char kEnableDeferredImageDecoding[];
CONTENT_EXPORT extern const char kEnableDelegatedRenderer[];
+CONTENT_EXPORT extern const char kEnableDisplayList2dCanvas[];
CONTENT_EXPORT extern const char kEnableDistanceFieldText[];
CONTENT_EXPORT extern const char kEnableDownloadResumption[];
CONTENT_EXPORT extern const char kEnableEncryptedMedia[];
CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
-CONTENT_EXPORT extern const char kEnableFastTextAutosizing[];
CONTENT_EXPORT extern const char kEnableFileCookies[];
-CONTENT_EXPORT extern const char kEnableGestureTapHighlight[];
extern const char kEnableGpuClientTracing[];
CONTENT_EXPORT extern const char kEnableGpuRasterization[];
CONTENT_EXPORT extern const char kEnableLowResTiling[];
-CONTENT_EXPORT extern const char kEnableHighDpiCompositingForFixedPosition[];
+CONTENT_EXPORT extern const char kEnableImageColorProfiles[];
CONTENT_EXPORT extern const char kEnableImplSidePainting[];
-CONTENT_EXPORT extern const char kEnableInbandTextTracks[];
CONTENT_EXPORT extern const char kEnableLCDText[];
CONTENT_EXPORT extern const char kEnableLogging[];
extern const char kEnableMemoryBenchmarking[];
+CONTENT_EXPORT extern const char kEnableNetworkInformation[];
CONTENT_EXPORT extern const char kEnableOneCopy[];
CONTENT_EXPORT extern const char kEnableOverlayFullscreenVideo[];
-CONTENT_EXPORT extern const char kDisableOverlayFullscreenVideoSubtitle[];
CONTENT_EXPORT extern const char kEnableOverscrollNotifications[];
CONTENT_EXPORT extern const char kEnablePinch[];
CONTENT_EXPORT extern const char kEnablePreciseMemoryInfo[];
-extern const char kEnablePreparsedJsCaching[];
CONTENT_EXPORT extern const char kEnableRegionBasedColumns[];
-CONTENT_EXPORT extern const char kEnableRepaintAfterLayout[];
+CONTENT_EXPORT extern const char kEnableRendererMojoChannel[];
CONTENT_EXPORT extern const char kEnableSandboxLogging[];
extern const char kEnableSeccompFilterSandbox[];
extern const char kEnableSkiaBenchmarking[];
+extern const char kEnableSlimmingPaint[];
CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
CONTENT_EXPORT extern const char kEnableSpatialNavigation[];
-CONTENT_EXPORT extern const char kEnableSpeechSynthesis[];
CONTENT_EXPORT extern const char kEnableStatsTable[];
-extern const char kEnableStrictSiteIsolation[];
-CONTENT_EXPORT extern const char kEnableServiceWorker[];
+CONTENT_EXPORT extern const char kEnableStrictSiteIsolation[];
CONTENT_EXPORT extern const char kEnableServiceWorkerSync[];
-CONTENT_EXPORT extern const char kEnableTargetedStyleRecalc[];
CONTENT_EXPORT extern const char kEnableTcpFastOpen[];
+CONTENT_EXPORT extern const char kEnableTextBlobs[];
CONTENT_EXPORT extern const char kEnableThreadedCompositing[];
+CONTENT_EXPORT extern const char kEnableTracing[];
+CONTENT_EXPORT extern const char kEnableTracingOutput[];
CONTENT_EXPORT extern const char kEnableUserMediaScreenCapturing[];
+extern const char kEnableV8ScriptStreaming[];
+extern const char kEnableV8IdleNotificationAfterCommit[];
CONTENT_EXPORT extern const char kEnableViewport[];
CONTENT_EXPORT extern const char kEnableViewportMeta[];
CONTENT_EXPORT extern const char kMainFrameResizesAreOrientationChanges[];
CONTENT_EXPORT extern const char kEnableVtune[];
-extern const char kEnableWebAnimationsSVG[];
CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
CONTENT_EXPORT extern const char kEnableWebGLImageChromium[];
CONTENT_EXPORT extern const char kEnableWebMIDI[];
@@ -165,7 +161,7 @@ extern const char kGpuLauncher[];
CONTENT_EXPORT extern const char kGpuProcess[];
CONTENT_EXPORT extern const char kGpuSandboxAllowSysVShm[];
CONTENT_EXPORT extern const char kGpuSandboxFailuresFatal[];
-CONTENT_EXPORT extern const char kGpuSandboxStartAfterInitialization[];
+CONTENT_EXPORT extern const char kGpuSandboxStartEarly[];
CONTENT_EXPORT extern const char kGpuStartupDialog[];
extern const char kGpuVendorID[];
CONTENT_EXPORT extern const char kHostResolverRules[];
@@ -208,6 +204,7 @@ extern const char kRendererCmdPrefix[];
CONTENT_EXPORT extern const char kRendererProcess[];
CONTENT_EXPORT extern const char kRendererProcessLimit[];
CONTENT_EXPORT extern const char kRendererStartupDialog[];
+CONTENT_EXPORT extern const char kRootLayerScrolls[];
extern const char kSandboxIPCProcess[];
CONTENT_EXPORT extern const char kScrollEndEffect[];
extern const char kShowPaintRects[];
@@ -230,6 +227,7 @@ extern const char kTraceShutdownFile[];
extern const char kTraceStartup[];
extern const char kTraceStartupDuration[];
extern const char kTraceStartupFile[];
+extern const char kTraceUploadURL[];
CONTENT_EXPORT extern const char kUIPrioritizeInGpuProcess[];
CONTENT_EXPORT extern const char kUseDiscardableMemory[];
CONTENT_EXPORT extern const char kUseFakeUIForMediaStream[];
@@ -240,19 +238,19 @@ CONTENT_EXPORT extern const char kUtilityProcess[];
extern const char kUtilityProcessAllowedDir[];
CONTENT_EXPORT extern const char kUtilityProcessEnableMDns[];
CONTENT_EXPORT extern const char kUtilityProcessRunningElevated[];
+extern const char kV8CacheOptions[];
CONTENT_EXPORT extern const char kValidateInputEventStream[];
CONTENT_EXPORT extern const char kWaitForDebuggerChildren[];
-CONTENT_EXPORT extern const char kWorkerProcess[];
CONTENT_EXPORT extern const char kZygoteCmdPrefix[];
CONTENT_EXPORT extern const char kZygoteProcess[];
#if defined(ENABLE_WEBRTC)
CONTENT_EXPORT extern const char kDisableAudioTrackProcessing[];
-CONTENT_EXPORT extern const char kDisableDeviceEnumeration[];
CONTENT_EXPORT extern const char kDisableWebRtcHWDecoding[];
CONTENT_EXPORT extern const char kDisableWebRtcEncryption[];
CONTENT_EXPORT extern const char kDisableWebRtcHWEncoding[];
CONTENT_EXPORT extern const char kEnableWebRtcHWVp8Encoding[];
+CONTENT_EXPORT extern const char kEnableWebRtcHWH264Encoding[];
#endif
#if defined(OS_ANDROID)
@@ -265,31 +263,39 @@ CONTENT_EXPORT extern const char kForceUseOverlayEmbeddedVideo[];
CONTENT_EXPORT extern const char kHideScrollbars[];
extern const char kNetworkCountryIso[];
CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
+CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
#endif
CONTENT_EXPORT extern const char kDisableWebAudio[];
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const char kDisablePanelFitting[];
+CONTENT_EXPORT extern const char kDisableVaapiAcceleratedVideoEncode[];
+#endif
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+CONTENT_EXPORT extern const char kEnableSpeechDispatcher[];
#endif
#if defined(OS_MACOSX) && !defined(OS_IOS)
-extern const char kEnableCarbonInterposing[];
extern const char kDisableCoreAnimationPlugins[];
+extern const char kEnableThreadedEventHandlingMac[];
#endif
#if defined(OS_WIN)
// This switch contains the device scale factor passed to certain processes
// like renderers, etc.
CONTENT_EXPORT extern const char kDeviceScaleFactor[];
-CONTENT_EXPORT extern const char kDisableDirectWrite[];
CONTENT_EXPORT extern const char kDisableLegacyIntermediateWindow[];
-CONTENT_EXPORT extern const char kEnableHighResolutionTime[];
// This switch will be removed when we enable the win32K lockdown process
// mitigation.
CONTENT_EXPORT extern const char kEnableWin32kRendererLockDown[];
#endif
+#if defined(ENABLE_PLUGINS)
+CONTENT_EXPORT extern const char kEnablePluginPowerSaver[];
+#endif
+
// DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
// alphabetical order, or in one of the ifdefs (also in order in each section).
diff --git a/chromium/content/public/common/context_menu_params.h b/chromium/content/public/common/context_menu_params.h
index ccef48ec2ca..8849dae303d 100644
--- a/chromium/content/public/common/context_menu_params.h
+++ b/chromium/content/public/common/context_menu_params.h
@@ -36,6 +36,12 @@ struct CONTENT_EXPORT CustomContextMenuContext {
// It could also be |kCurrentRenderWidget|, which means the render widget that
// the corresponding ViewHostMsg_ContextMenu is sent to.
int32 render_widget_id;
+
+ // If the context menu was created for a link, and we navigated to that url,
+ // this will contain the url that was navigated. This field may not be set
+ // if, for example, we are transitioning to an incognito window, since we
+ // want to sever any connection to the old renderer.
+ GURL link_followed;
};
// FIXME(beng): This would be more useful in the future and more efficient
@@ -98,6 +104,10 @@ struct CONTENT_EXPORT ContextMenuParams {
// This is the text of the selection that the context menu was invoked on.
base::string16 selection_text;
+ // This is the suggested filename to be used when saving file through "Save
+ // Link As" option of context menu.
+ base::string16 suggested_filename;
+
// The misspelled word under the cursor, if any. Used to generate the
// |dictionary_suggestions| list.
base::string16 misspelled_word;
diff --git a/chromium/content/public/common/eme_codec.h b/chromium/content/public/common/eme_codec.h
deleted file mode 100644
index 54ed0e60044..00000000000
--- a/chromium/content/public/common/eme_codec.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 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 CONTENT_PUBLIC_COMMON_EME_CODEC_H_
-#define CONTENT_PUBLIC_COMMON_EME_CODEC_H_
-
-namespace content {
-
-// Defines bitmask values that specify codecs used in Encrypted Media Extension
-// (EME). Each value represents a codec within a specific container.
-// The mask values are stored in a SupportedCodecs.
-enum EmeCodec {
- EME_CODEC_NONE = 0,
- EME_CODEC_WEBM_VORBIS = 1 << 0,
- EME_CODEC_WEBM_AUDIO_ALL = EME_CODEC_WEBM_VORBIS,
- EME_CODEC_WEBM_VP8 = 1 << 1,
- EME_CODEC_WEBM_VP9 = 1 << 2,
- EME_CODEC_WEBM_VIDEO_ALL = (EME_CODEC_WEBM_VP8 | EME_CODEC_WEBM_VP9),
- EME_CODEC_WEBM_ALL = (EME_CODEC_WEBM_AUDIO_ALL | EME_CODEC_WEBM_VIDEO_ALL),
-#if defined(USE_PROPRIETARY_CODECS)
- EME_CODEC_MP4_AAC = 1 << 3,
- EME_CODEC_MP4_AUDIO_ALL = EME_CODEC_MP4_AAC,
- EME_CODEC_MP4_AVC1 = 1 << 4,
- EME_CODEC_MP4_VIDEO_ALL = EME_CODEC_MP4_AVC1,
- EME_CODEC_MP4_ALL = (EME_CODEC_MP4_AUDIO_ALL | EME_CODEC_MP4_VIDEO_ALL),
- EME_CODEC_ALL = (EME_CODEC_WEBM_ALL | EME_CODEC_MP4_ALL),
-#else
- EME_CODEC_ALL = EME_CODEC_WEBM_ALL,
-#endif // defined(USE_PROPRIETARY_CODECS)
-};
-
-typedef uint32 SupportedCodecs;
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_EME_CODEC_H_
diff --git a/chromium/content/public/common/file_chooser_file_info.cc b/chromium/content/public/common/file_chooser_file_info.cc
new file mode 100644
index 00000000000..9f9a02878ff
--- /dev/null
+++ b/chromium/content/public/common/file_chooser_file_info.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 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 "content/public/common/file_chooser_file_info.h"
+
+namespace content {
+
+FileChooserFileInfo::FileChooserFileInfo() : length(0), is_directory(false) {
+}
+
+FileChooserFileInfo::~FileChooserFileInfo() {
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/file_chooser_file_info.h b/chromium/content/public/common/file_chooser_file_info.h
new file mode 100644
index 00000000000..24d116d58c4
--- /dev/null
+++ b/chromium/content/public/common/file_chooser_file_info.h
@@ -0,0 +1,35 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_FILE_CHOOSER_FILE_INFO_H_
+#define CONTENT_PUBLIC_COMMON_FILE_CHOOSER_FILE_INFO_H_
+
+#include "base/files/file_path.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Result of file chooser.
+struct CONTENT_EXPORT FileChooserFileInfo {
+ FileChooserFileInfo();
+ ~FileChooserFileInfo();
+
+ base::FilePath file_path;
+
+ // For native files.
+ base::FilePath::StringType display_name;
+
+ // For non-native files.
+ GURL file_system_url;
+ base::Time modification_time;
+ int64 length;
+
+ bool is_directory;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_FILE_CHOOSER_FILE_INFO_H_
diff --git a/chromium/content/public/common/file_chooser_params.cc b/chromium/content/public/common/file_chooser_params.cc
index c9c95710d84..97de9e3b6ef 100644
--- a/chromium/content/public/common/file_chooser_params.cc
+++ b/chromium/content/public/common/file_chooser_params.cc
@@ -6,7 +6,7 @@
namespace content {
-FileChooserParams::FileChooserParams() : mode(Open) {
+FileChooserParams::FileChooserParams() : mode(Open), need_local_path(true) {
}
FileChooserParams::~FileChooserParams() {
diff --git a/chromium/content/public/common/file_chooser_params.h b/chromium/content/public/common/file_chooser_params.h
index 46043269a57..ad612ab9ce2 100644
--- a/chromium/content/public/common/file_chooser_params.h
+++ b/chromium/content/public/common/file_chooser_params.h
@@ -46,6 +46,9 @@ struct CONTENT_EXPORT FileChooserParams {
// input element. It is used to restrict selectable files to such types.
std::vector<base::string16> accept_types;
+ // Whether the caller needs native file path or not.
+ bool need_local_path;
+
#if defined(OS_ANDROID)
// See http://www.w3.org/TR/html-media-capture for more information.
// If true, the data should be obtained using the device's camera/mic/etc.
diff --git a/chromium/content/public/common/frame_navigate_params.cc b/chromium/content/public/common/frame_navigate_params.cc
index 933edf1d5b5..637cec53e8e 100644
--- a/chromium/content/public/common/frame_navigate_params.cc
+++ b/chromium/content/public/common/frame_navigate_params.cc
@@ -8,7 +8,7 @@ namespace content {
FrameNavigateParams::FrameNavigateParams()
: page_id(0),
- transition(PAGE_TRANSITION_LINK),
+ transition(ui::PAGE_TRANSITION_LINK),
should_update_history(false) {
}
diff --git a/chromium/content/public/common/frame_navigate_params.h b/chromium/content/public/common/frame_navigate_params.h
index 2f9656af694..b704b8e9306 100644
--- a/chromium/content/public/common/frame_navigate_params.h
+++ b/chromium/content/public/common/frame_navigate_params.h
@@ -9,9 +9,9 @@
#include <vector>
#include "content/common/content_export.h"
-#include "content/public/common/page_transition_types.h"
#include "content/public/common/referrer.h"
#include "net/base/host_port_pair.h"
+#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
namespace content {
@@ -42,7 +42,7 @@ struct CONTENT_EXPORT FrameNavigateParams {
content::Referrer referrer;
// The type of transition.
- PageTransition transition;
+ ui::PageTransition transition;
// Lists the redirects that occurred on the way to the current page. This
// vector has the same format as reported by the WebDataSource in the glue,
diff --git a/chromium/content/public/common/main_function_params.h b/chromium/content/public/common/main_function_params.h
index 8a2b826acd8..e2756e7c098 100644
--- a/chromium/content/public/common/main_function_params.h
+++ b/chromium/content/public/common/main_function_params.h
@@ -33,6 +33,8 @@ struct MainFunctionParams {
sandbox_info(NULL),
#elif defined(OS_MACOSX)
autorelease_pool(NULL),
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
+ zygote_child(false),
#endif
ui_task(NULL) {
}
@@ -43,6 +45,8 @@ struct MainFunctionParams {
sandbox::SandboxInterfaceInfo* sandbox_info;
#elif defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool* autorelease_pool;
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
+ bool zygote_child;
#endif
// Used by InProcessBrowserTest. If non-null BrowserMain schedules this
diff --git a/chromium/content/public/common/manifest.cc b/chromium/content/public/common/manifest.cc
new file mode 100644
index 00000000000..292b85b44db
--- /dev/null
+++ b/chromium/content/public/common/manifest.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 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 "content/public/common/manifest.h"
+
+namespace content {
+
+const double Manifest::Icon::kDefaultDensity = 1;
+const size_t Manifest::kMaxIPCStringLength = 4 * 1024;
+
+Manifest::Icon::Icon()
+ : density(kDefaultDensity) {
+}
+
+Manifest::Icon::~Icon() {
+}
+
+Manifest::Manifest()
+ : display(DISPLAY_MODE_UNSPECIFIED),
+ orientation(blink::WebScreenOrientationLockDefault) {
+}
+
+Manifest::~Manifest() {
+}
+
+bool Manifest::IsEmpty() const {
+ return name.is_null() &&
+ short_name.is_null() &&
+ start_url.is_empty() &&
+ display == DISPLAY_MODE_UNSPECIFIED &&
+ orientation == blink::WebScreenOrientationLockDefault &&
+ icons.empty() &&
+ gcm_sender_id.is_null();
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/manifest.h b/chromium/content/public/common/manifest.h
new file mode 100644
index 00000000000..038bd0d9f7c
--- /dev/null
+++ b/chromium/content/public/common/manifest.h
@@ -0,0 +1,98 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_MANIFEST_H_
+#define CONTENT_PUBLIC_COMMON_MANIFEST_H_
+
+#include <vector>
+
+#include "base/strings/nullable_string16.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
+#include "ui/gfx/geometry/size.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// The Manifest structure is an internal representation of the Manifest file
+// described in the "Manifest for Web Application" document:
+// http://w3c.github.io/manifest/
+struct CONTENT_EXPORT Manifest {
+ enum DisplayMode {
+ DISPLAY_MODE_UNSPECIFIED,
+ DISPLAY_MODE_FULLSCREEN,
+ DISPLAY_MODE_STANDALONE,
+ DISPLAY_MODE_MINIMAL_UI,
+ DISPLAY_MODE_BROWSER
+ };
+
+ // Structure representing an icon as per the Manifest specification, see:
+ // http://w3c.github.io/manifest/#dfn-icon-object
+ struct CONTENT_EXPORT Icon {
+ Icon();
+ ~Icon();
+
+ // MUST be a valid url. If an icon doesn't have a valid URL, it will not be
+ // successfully parsed, thus will not be represented in the Manifest.
+ GURL src;
+
+ // Null if the parsing failed or the field was not present. The type can be
+ // any string and doesn't have to be a valid image MIME type at this point.
+ // It is up to the consumer of the object to check if the type matches a
+ // supported type.
+ base::NullableString16 type;
+
+ // Default value is 1.0 if the value is missing or invalid.
+ double density;
+
+ // Empty if the parsing failed, the field was not present or empty.
+ // The special value "any" is represented by gfx::Size(0, 0).
+ std::vector<gfx::Size> sizes;
+
+ // Default density. Set to 1.0.
+ static const double kDefaultDensity;
+ };
+
+ Manifest();
+ ~Manifest();
+
+ // Returns whether this Manifest had no attribute set. A newly created
+ // Manifest is always empty.
+ bool IsEmpty() const;
+
+ // Null if the parsing failed or the field was not present.
+ base::NullableString16 name;
+
+ // Null if the parsing failed or the field was not present.
+ base::NullableString16 short_name;
+
+ // Empty if the parsing failed or the field was not present.
+ GURL start_url;
+
+ // Set to DISPLAY_MODE_UNSPECIFIED if the parsing failed or the field was not
+ // present.
+ DisplayMode display;
+
+ // Set to blink::WebScreenOrientationLockDefault if the parsing failed or the
+ // field was not present.
+ blink::WebScreenOrientationLockType orientation;
+
+ // Empty if the parsing failed, the field was not present, empty or all the
+ // icons inside the JSON array were invalid.
+ std::vector<Icon> icons;
+
+ // This is a proprietary extension of the web Manifest, double-check that it
+ // is okay to use this entry.
+ // Null if parsing failed or the field was not present.
+ base::NullableString16 gcm_sender_id;
+
+ // Maximum length for all the strings inside the Manifest when it is sent over
+ // IPC. The renderer process should truncate the strings before sending the
+ // Manifest and the browser process must do the same when receiving it.
+ static const size_t kMaxIPCStringLength;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_MANIFEST_H_
diff --git a/chromium/content/public/common/media_stream_request.cc b/chromium/content/public/common/media_stream_request.cc
index cb3b8ed86aa..dc5e1569cc8 100644
--- a/chromium/content/public/common/media_stream_request.cc
+++ b/chromium/content/public/common/media_stream_request.cc
@@ -85,7 +85,7 @@ const MediaStreamDevice* MediaStreamDevices::FindById(
MediaStreamRequest::MediaStreamRequest(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const GURL& security_origin,
bool user_gesture,
@@ -95,7 +95,7 @@ MediaStreamRequest::MediaStreamRequest(
MediaStreamType audio_type,
MediaStreamType video_type)
: render_process_id(render_process_id),
- render_view_id(render_view_id),
+ render_frame_id(render_frame_id),
page_request_id(page_request_id),
security_origin(security_origin),
user_gesture(user_gesture),
diff --git a/chromium/content/public/common/media_stream_request.h b/chromium/content/public/common/media_stream_request.h
index 5a91fd10ccc..31ebbead2a9 100644
--- a/chromium/content/public/common/media_stream_request.h
+++ b/chromium/content/public/common/media_stream_request.h
@@ -59,24 +59,26 @@ enum VideoFacingMode {
MEDIA_VIDEO_FACING_NONE = 0,
MEDIA_VIDEO_FACING_USER,
MEDIA_VIDEO_FACING_ENVIRONMENT,
- MEDIA_VIDEO_FACING_LEFT,
- MEDIA_VIDEO_FACING_RIGHT,
NUM_MEDIA_VIDEO_FACING_MODE
};
+// Elements in this enum should not be deleted or rearranged; the only
+// permitted operation is to add new elements before NUM_MEDIA_REQUEST_RESULTS.
enum MediaStreamRequestResult {
MEDIA_DEVICE_OK = 0,
- MEDIA_DEVICE_PERMISSION_DENIED,
- MEDIA_DEVICE_PERMISSION_DISMISSED,
- MEDIA_DEVICE_INVALID_STATE,
- MEDIA_DEVICE_NO_HARDWARE,
- MEDIA_DEVICE_INVALID_SECURITY_ORIGIN,
- MEDIA_DEVICE_TAB_CAPTURE_FAILURE,
- MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE,
- MEDIA_DEVICE_CAPTURE_FAILURE,
- MEDIA_DEVICE_TRACK_START_FAILURE,
-
+ MEDIA_DEVICE_PERMISSION_DENIED = 1,
+ MEDIA_DEVICE_PERMISSION_DISMISSED = 2,
+ MEDIA_DEVICE_INVALID_STATE = 3,
+ MEDIA_DEVICE_NO_HARDWARE = 4,
+ MEDIA_DEVICE_INVALID_SECURITY_ORIGIN = 5,
+ MEDIA_DEVICE_TAB_CAPTURE_FAILURE = 6,
+ MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE = 7,
+ MEDIA_DEVICE_CAPTURE_FAILURE = 8,
+ MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED = 9,
+ MEDIA_DEVICE_TRACK_START_FAILURE = 10,
+ MEDIA_DEVICE_NOT_SUPPORTED = 11,
+ MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN = 12,
NUM_MEDIA_REQUEST_RESULTS
};
@@ -192,7 +194,7 @@ typedef std::map<MediaStreamType, MediaStreamDevices> MediaStreamDeviceMap;
struct CONTENT_EXPORT MediaStreamRequest {
MediaStreamRequest(
int render_process_id,
- int render_view_id,
+ int render_frame_id,
int page_request_id,
const GURL& security_origin,
bool user_gesture,
@@ -209,12 +211,12 @@ struct CONTENT_EXPORT MediaStreamRequest {
// displayed for this renderer.
int render_process_id;
- // This is the render view id for the renderer associated with generating
+ // This is the render frame id for the renderer associated with generating
// frames for a MediaStream. Any indicators associated with a capture will be
// displayed for this renderer.
- int render_view_id;
+ int render_frame_id;
- // The unique id combined with render_process_id and render_view_id for
+ // The unique id combined with render_process_id and render_frame_id for
// identifying this request. This is used for cancelling request.
int page_request_id;
diff --git a/chromium/content/public/common/mojo_geoposition.mojom b/chromium/content/public/common/mojo_geoposition.mojom
new file mode 100644
index 00000000000..852f2a9c44b
--- /dev/null
+++ b/chromium/content/public/common/mojo_geoposition.mojom
@@ -0,0 +1,56 @@
+// Copyright 2014 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 declares the Geoposition structure, used to represent a position
+// fix. It was originally derived from:
+// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation.h
+// TODO(blundell): Investigate killing content::Geoposition in favor of using
+// this struct everywhere (and renaming it to Geoposition).
+
+module content;
+
+struct MojoGeoposition {
+ // These values follow the W3C geolocation specification and can be returned
+ // to JavaScript without the need for a conversion.
+ enum ErrorCode {
+ ERROR_CODE_NONE = 0, // Chrome addition.
+ ERROR_CODE_PERMISSION_DENIED = 1,
+ ERROR_CODE_POSITION_UNAVAILABLE = 2,
+ ERROR_CODE_TIMEOUT = 3,
+ ERROR_CODE_LAST = ERROR_CODE_TIMEOUT
+ };
+
+ // Whether this geoposition is valid.
+ bool valid;
+
+ // These properties correspond to those of the JavaScript Position object
+ // although their types may differ.
+ // Latitude in decimal degrees north (WGS84 coordinate frame).
+ double latitude;
+ // Longitude in decimal degrees west (WGS84 coordinate frame).
+ double longitude;
+ // Altitude in meters (above WGS84 datum).
+ double altitude;
+ // Accuracy of horizontal position in meters.
+ double accuracy;
+ // Accuracy of altitude in meters.
+ double altitude_accuracy;
+ // Heading in decimal degrees clockwise from true north.
+ double heading;
+ // Horizontal component of device velocity in meters per second.
+ double speed;
+ // TODO(blundell): If I need to represent this differently to use this
+ // struct to replace content::Geolocation, I'll need to convert
+ // correctly into seconds-since-epoch when using this in
+ // GeolocationDispatcher::OnLocationUpdate().
+ // Time of position measurement in seconds since Epoch in UTC time. This is
+ // taken from the host computer's system clock (i.e. from Time::Now(), not the
+ // source device's clock).
+ double timestamp;
+
+ // Error code, see enum above.
+ ErrorCode error_code;
+ // Human-readable error message.
+ string error_message;
+};
diff --git a/chromium/content/public/common/page_transition_types.cc b/chromium/content/public/common/page_transition_types.cc
deleted file mode 100644
index bf95ea045c0..00000000000
--- a/chromium/content/public/common/page_transition_types.cc
+++ /dev/null
@@ -1,89 +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 "content/public/common/page_transition_types.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-bool PageTransitionCoreTypeIs(PageTransition lhs,
- PageTransition rhs) {
- // Expect the rhs to be a compile time constant without qualifiers.
- DCHECK(PageTransitionGetQualifier(rhs) == 0 &&
- PageTransitionIsValidType(rhs));
- return implicit_cast<int>(PageTransitionStripQualifier(lhs)) ==
- implicit_cast<int>(PageTransitionStripQualifier(rhs));
-}
-
-PageTransition PageTransitionStripQualifier(PageTransition type) {
- return static_cast<PageTransition>(type & ~PAGE_TRANSITION_QUALIFIER_MASK);
-}
-
-bool PageTransitionIsValidType(int32 type) {
- PageTransition t = PageTransitionStripQualifier(
- static_cast<PageTransition>(type));
- return (t <= PAGE_TRANSITION_LAST_CORE);
-}
-
-PageTransition PageTransitionFromInt(int32 type) {
- if (!PageTransitionIsValidType(type)) {
- NOTREACHED() << "Invalid transition type " << type;
-
- // Return a safe default so we don't have corrupt data in release mode.
- return PAGE_TRANSITION_LINK;
- }
- return static_cast<PageTransition>(type);
-}
-
-bool PageTransitionIsMainFrame(PageTransition type) {
- int32 t = PageTransitionStripQualifier(type);
- return (t != PAGE_TRANSITION_AUTO_SUBFRAME &&
- t != PAGE_TRANSITION_MANUAL_SUBFRAME);
-}
-
-bool PageTransitionIsRedirect(PageTransition type) {
- return (type & PAGE_TRANSITION_IS_REDIRECT_MASK) != 0;
-}
-
-bool PageTransitionIsNewNavigation(PageTransition type) {
- return (type & PAGE_TRANSITION_FORWARD_BACK) == 0 &&
- !PageTransitionCoreTypeIs(type, content::PAGE_TRANSITION_RELOAD);
-}
-
-int32 PageTransitionGetQualifier(PageTransition type) {
- return type & PAGE_TRANSITION_QUALIFIER_MASK;
-}
-
-bool PageTransitionIsWebTriggerable(PageTransition type) {
- int32 t = PageTransitionStripQualifier(type);
- switch (t) {
- case PAGE_TRANSITION_LINK:
- case PAGE_TRANSITION_AUTO_SUBFRAME:
- case PAGE_TRANSITION_MANUAL_SUBFRAME:
- case PAGE_TRANSITION_FORM_SUBMIT:
- return true;
- }
- return false;
-}
-
-const char* PageTransitionGetCoreTransitionString(PageTransition type) {
- int32 t = PageTransitionStripQualifier(type);
- switch (t) {
- case PAGE_TRANSITION_LINK: return "link";
- case PAGE_TRANSITION_TYPED: return "typed";
- case PAGE_TRANSITION_AUTO_BOOKMARK: return "auto_bookmark";
- case PAGE_TRANSITION_AUTO_SUBFRAME: return "auto_subframe";
- case PAGE_TRANSITION_MANUAL_SUBFRAME: return "manual_subframe";
- case PAGE_TRANSITION_GENERATED: return "generated";
- case PAGE_TRANSITION_AUTO_TOPLEVEL: return "auto_toplevel";
- case PAGE_TRANSITION_FORM_SUBMIT: return "form_submit";
- case PAGE_TRANSITION_RELOAD: return "reload";
- case PAGE_TRANSITION_KEYWORD: return "keyword";
- case PAGE_TRANSITION_KEYWORD_GENERATED: return "keyword_generated";
- }
- return NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/page_transition_types.h b/chromium/content/public/common/page_transition_types.h
deleted file mode 100644
index 1b1f8013502..00000000000
--- a/chromium/content/public/common/page_transition_types.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_PUBLIC_COMMON_PAGE_TRANSITION_TYPES_H_
-#define CONTENT_PUBLIC_COMMON_PAGE_TRANSITION_TYPES_H_
-
-#include "base/basictypes.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-enum PageTransition {
-
-#define PAGE_TRANSITION(label, value) PAGE_TRANSITION_ ## label = value,
-#include "content/public/common/page_transition_types_list.h"
-#undef PAGE_TRANSITION
-
-};
-
-// Compares two PageTransition types ignoring qualifiers. |rhs| is taken to
-// be a compile time constant, and hence must not contain any qualifiers.
-CONTENT_EXPORT bool PageTransitionCoreTypeIs(PageTransition lhs,
- PageTransition rhs);
-
-// Simplifies the provided transition by removing any qualifier
-CONTENT_EXPORT PageTransition PageTransitionStripQualifier(
- PageTransition type);
-
-bool PageTransitionIsValidType(int32 type);
-
-CONTENT_EXPORT PageTransition PageTransitionFromInt(int32 type);
-
-// Returns true if the given transition is a top-level frame transition, or
-// false if the transition was for a subframe.
-CONTENT_EXPORT bool PageTransitionIsMainFrame(PageTransition type);
-
-// Returns whether a transition involves a redirection
-CONTENT_EXPORT bool PageTransitionIsRedirect(PageTransition type);
-
-// Returns whether a transition is a new navigation (rather than a return
-// to a previously committed navigation).
-CONTENT_EXPORT bool PageTransitionIsNewNavigation(PageTransition type);
-
-// Return the qualifier
-CONTENT_EXPORT int32 PageTransitionGetQualifier(PageTransition type);
-
-// Returns true if the transition can be triggered by the web instead of
-// through UI or similar.
-CONTENT_EXPORT bool PageTransitionIsWebTriggerable(PageTransition type);
-
-// Return a string version of the core type values.
-CONTENT_EXPORT const char* PageTransitionGetCoreTransitionString(
- PageTransition type);
-
-// TODO(joth): Remove the #if guard here; requires all chrome layer code to
-// be fixed up not to use operator==
-#if defined(CONTENT_IMPLEMENTATION)
-// Declare a dummy class that is intentionally never defined.
-class DontUseOperatorEquals;
-
-// Ban operator== as it's way too easy to forget to strip the qualifiers. Use
-// PageTransitionCoreTypeIs() instead.
-DontUseOperatorEquals operator==(PageTransition, PageTransition);
-DontUseOperatorEquals operator==(PageTransition, int);
-DontUseOperatorEquals operator==(int, PageTransition);
-#endif // defined(CONTENT_IMPLEMENTATION)
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_PAGE_TRANSITION_TYPES_H_
diff --git a/chromium/content/public/common/page_transition_types_list.h b/chromium/content/public/common/page_transition_types_list.h
deleted file mode 100644
index be6733433d2..00000000000
--- a/chromium/content/public/common/page_transition_types_list.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Intentionally no include guards because this file is meant to be included
-// inside a macro to generate enum values.
-
-// Types of transitions between pages. These are stored in the history
-// database to separate visits, and are reported by the renderer for page
-// navigations.
-//
-// WARNING: don't change these numbers. They are written directly into the
-// history database, so future versions will need the same values to match
-// the enums.
-//
-// A type is made of a core value and a set of qualifiers. A type has one
-// core value and 0 or or more qualifiers.
-
-// User got to this page by clicking a link on another page.
-PAGE_TRANSITION(LINK, 0)
-
-// User got this page by typing the URL in the URL bar. This should not be
-// used for cases where the user selected a choice that didn't look at all
-// like a URL; see GENERATED below.
-//
-// We also use this for other "explicit" navigation actions.
-PAGE_TRANSITION(TYPED, 1)
-
-// User got to this page through a suggestion in the UI, for example)
-// through the destinations page.
-PAGE_TRANSITION(AUTO_BOOKMARK, 2)
-
-// This is a subframe navigation. This is any content that is automatically
-// loaded in a non-toplevel frame. For example, if a page consists of
-// several frames containing ads, those ad URLs will have this transition
-// type. The user may not even realize the content in these pages is a
-// separate frame, so may not care about the URL (see MANUAL below).
-PAGE_TRANSITION(AUTO_SUBFRAME, 3)
-
-// For subframe navigations that are explicitly requested by the user and
-// generate new navigation entries in the back/forward list. These are
-// probably more important than frames that were automatically loaded in
-// the background because the user probably cares about the fact that this
-// link was loaded.
-PAGE_TRANSITION(MANUAL_SUBFRAME, 4)
-
-// User got to this page by typing in the URL bar and selecting an entry
-// that did not look like a URL. For example, a match might have the URL
-// of a Google search result page, but appear like "Search Google for ...".
-// These are not quite the same as TYPED navigations because the user
-// didn't type or see the destination URL.
-// See also KEYWORD.
-PAGE_TRANSITION(GENERATED, 5)
-
-// This is a toplevel navigation. This is any content that is automatically
-// loaded in a toplevel frame. For example, opening a tab to show the ASH
-// screen saver, opening the devtools window, opening the NTP after the safe
-// browsing warning, opening web-based dialog boxes are examples of
-// AUTO_TOPLEVEL navigations.
-PAGE_TRANSITION(AUTO_TOPLEVEL, 6)
-
-// The user filled out values in a form and submitted it. NOTE that in
-// some situations submitting a form does not result in this transition
-// type. This can happen if the form uses script to submit the contents.
-PAGE_TRANSITION(FORM_SUBMIT, 7)
-
-// The user "reloaded" the page, either by hitting the reload button or by
-// hitting enter in the address bar. NOTE: This is distinct from the
-// concept of whether a particular load uses "reload semantics" (i.e.
-// bypasses cached data). For this reason, lots of code needs to pass
-// around the concept of whether a load should be treated as a "reload"
-// separately from their tracking of this transition type, which is mainly
-// used for proper scoring for consumers who care about how frequently a
-// user typed/visited a particular URL.
-//
-// SessionRestore and undo tab close use this transition type too.
-PAGE_TRANSITION(RELOAD, 8)
-
-// The url was generated from a replaceable keyword other than the default
-// search provider. If the user types a keyword (which also applies to
-// tab-to-search) in the omnibox this qualifier is applied to the transition
-// type of the generated url. TemplateURLModel then may generate an
-// additional visit with a transition type of KEYWORD_GENERATED against the
-// url 'http://' + keyword. For example, if you do a tab-to-search against
-// wikipedia the generated url has a transition qualifer of KEYWORD, and
-// TemplateURLModel generates a visit for 'wikipedia.org' with a transition
-// type of KEYWORD_GENERATED.
-PAGE_TRANSITION(KEYWORD, 9)
-
-// Corresponds to a visit generated for a keyword. See description of
-// KEYWORD for more details.
-PAGE_TRANSITION(KEYWORD_GENERATED, 10)
-
-// ADDING NEW CORE VALUE? Be sure to update the LAST_CORE and CORE_MASK
-// values below. Also update CoreTransitionString().
-PAGE_TRANSITION(LAST_CORE, PAGE_TRANSITION_KEYWORD_GENERATED)
-PAGE_TRANSITION(CORE_MASK, 0xFF)
-
-// Qualifiers
-// Any of the core values above can be augmented by one or more qualifiers.
-// These qualifiers further define the transition.
-
-// A managed user attempted to visit a URL but was blocked.
-PAGE_TRANSITION(BLOCKED, 0x00800000)
-
-// User used the Forward or Back button to navigate among browsing history.
-PAGE_TRANSITION(FORWARD_BACK, 0x01000000)
-
-// User used the address bar to trigger this navigation.
-PAGE_TRANSITION(FROM_ADDRESS_BAR, 0x02000000)
-
-// User is navigating to the home page.
-PAGE_TRANSITION(HOME_PAGE, 0x04000000)
-
-// The transition originated from an external application; the exact definition
-// of this is embedder dependent.
-PAGE_TRANSITION(FROM_API, 0x08000000)
-
-// The beginning of a navigation chain.
-PAGE_TRANSITION(CHAIN_START, 0x10000000)
-
-// The last transition in a redirect chain.
-PAGE_TRANSITION(CHAIN_END, 0x20000000)
-
-// Redirects caused by JavaScript or a meta refresh tag on the page.
-PAGE_TRANSITION(CLIENT_REDIRECT, 0x40000000)
-
-// Redirects sent from the server by HTTP headers. It might be nice to
-// break this out into 2 types in the future, permanent or temporary, if we
-// can get that information from WebKit.
-PAGE_TRANSITION(SERVER_REDIRECT, 0x80000000)
-
-// Used to test whether a transition involves a redirect.
-PAGE_TRANSITION(IS_REDIRECT_MASK, 0xC0000000)
-
-// General mask defining the bits used for the qualifiers.
-PAGE_TRANSITION(QUALIFIER_MASK, 0xFFFFFF00)
diff --git a/chromium/content/public/common/pepper_plugin_info.h b/chromium/content/public/common/pepper_plugin_info.h
index 3cd54bce914..bb1d9de6127 100644
--- a/chromium/content/public/common/pepper_plugin_info.h
+++ b/chromium/content/public/common/pepper_plugin_info.h
@@ -14,6 +14,10 @@
#include "ppapi/c/pp_module.h"
#include "ppapi/c/ppb.h"
+#if !defined(ENABLE_PLUGINS)
+#error "Plugins should be enabled"
+#endif
+
namespace content {
struct CONTENT_EXPORT PepperPluginInfo {
diff --git a/chromium/content/public/common/process_type.h b/chromium/content/public/common/process_type.h
index 495bef31c64..14696697857 100644
--- a/chromium/content/public/common/process_type.h
+++ b/chromium/content/public/common/process_type.h
@@ -20,7 +20,7 @@ enum ProcessType {
PROCESS_TYPE_BROWSER,
PROCESS_TYPE_RENDERER,
PROCESS_TYPE_PLUGIN,
- PROCESS_TYPE_WORKER,
+ PROCESS_TYPE_WORKER_DEPRECATED,
PROCESS_TYPE_UTILITY,
PROCESS_TYPE_ZYGOTE,
PROCESS_TYPE_SANDBOX_HELPER,
diff --git a/chromium/content/public/common/push_messaging_status.cc b/chromium/content/public/common/push_messaging_status.cc
new file mode 100644
index 00000000000..d3b3d1b9dc5
--- /dev/null
+++ b/chromium/content/public/common/push_messaging_status.cc
@@ -0,0 +1,38 @@
+// Copyright 2014 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 "content/public/common/push_messaging_status.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+const char* PushRegistrationStatusToString(PushRegistrationStatus status) {
+ switch (status) {
+ case PUSH_REGISTRATION_STATUS_SUCCESS:
+ return "Registration successful";
+
+ case PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER:
+ return "Registration failed - no Service Worker";
+
+ case PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE:
+ return "Registration failed - push service not available";
+
+ case PUSH_REGISTRATION_STATUS_LIMIT_REACHED:
+ return "Registration failed - registration limit has been reached";
+
+ case PUSH_REGISTRATION_STATUS_PERMISSION_DENIED:
+ return "Registration failed - permission denied";
+
+ case PUSH_REGISTRATION_STATUS_SERVICE_ERROR:
+ return "Registration failed - push service error";
+
+ case PUSH_REGISTRATION_STATUS_NO_SENDER_ID:
+ return "Registration failed - no sender id provided";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/push_messaging_status.h b/chromium/content/public/common/push_messaging_status.h
new file mode 100644
index 00000000000..22351ca18bf
--- /dev/null
+++ b/chromium/content/public/common/push_messaging_status.h
@@ -0,0 +1,64 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_PUSH_MESSAGING_STATUS_H_
+#define CONTENT_PUBLIC_COMMON_PUSH_MESSAGING_STATUS_H_
+
+namespace content {
+
+// Push registration success / error codes for internal use & reporting in UMA.
+enum PushRegistrationStatus {
+ // Registration was successful.
+ PUSH_REGISTRATION_STATUS_SUCCESS = 0,
+
+ // Registration failed because there is no Service Worker.
+ PUSH_REGISTRATION_STATUS_NO_SERVICE_WORKER = 1,
+
+ // Registration failed because the push service is not available.
+ PUSH_REGISTRATION_STATUS_SERVICE_NOT_AVAILABLE = 2,
+
+ // Registration failed because the maximum number of registratons has been
+ // reached.
+ PUSH_REGISTRATION_STATUS_LIMIT_REACHED = 3,
+
+ // Registration failed because permission was denied.
+ PUSH_REGISTRATION_STATUS_PERMISSION_DENIED = 4,
+
+ // Registration failed in the push service implemented by the embedder.
+ PUSH_REGISTRATION_STATUS_SERVICE_ERROR = 5,
+
+ // Registration failed because no sender id was provided by the page.
+ PUSH_REGISTRATION_STATUS_NO_SENDER_ID = 6,
+
+ // NOTE: Do not renumber these as that would confuse interpretation of
+ // previously logged data. When making changes, also update the enum list
+ // in tools/metrics/histograms/histograms.xml to keep it in sync, and
+ // update PUSH_REGISTRATION_STATUS_LAST below.
+
+ // Used for IPC message range checks.
+ PUSH_REGISTRATION_STATUS_LAST = PUSH_REGISTRATION_STATUS_NO_SENDER_ID
+};
+
+// Push message delivery success / error codes for internal use.
+enum PushDeliveryStatus {
+ // The message was successfully delivered.
+ PUSH_DELIVERY_STATUS_SUCCESS,
+
+ // The message could not be delivered because no service worker was found.
+ PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER,
+
+ // The message could not be delivered because of a service worker error.
+ PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR,
+
+ // When making changes, update PUSH_DELIVERY_STATUS_LAST below.
+
+ // Used for IPC message range checks.
+ PUSH_DELIVERY_STATUS_LAST = PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR
+};
+
+const char* PushRegistrationStatusToString(PushRegistrationStatus status);
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_PUSH_MESSAGING_STATUS_H_
diff --git a/chromium/content/public/common/referrer.h b/chromium/content/public/common/referrer.h
index b10bfd6c28e..122c5ead790 100644
--- a/chromium/content/public/common/referrer.h
+++ b/chromium/content/public/common/referrer.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_COMMON_REFERRER_H_
#define CONTENT_PUBLIC_COMMON_REFERRER_H_
+#include "base/logging.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "url/gurl.h"
@@ -23,6 +24,38 @@ struct CONTENT_EXPORT Referrer {
GURL url;
blink::WebReferrerPolicy policy;
+
+ static Referrer SanitizeForRequest(const GURL& request,
+ const Referrer& referrer) {
+ Referrer sanitized_referrer(referrer.url.GetAsReferrer(), referrer.policy);
+
+ if (!request.SchemeIsHTTPOrHTTPS() ||
+ !sanitized_referrer.url.SchemeIsHTTPOrHTTPS()) {
+ sanitized_referrer.url = GURL();
+ return sanitized_referrer;
+ }
+
+ switch (sanitized_referrer.policy) {
+ case blink::WebReferrerPolicyDefault:
+ if (sanitized_referrer.url.SchemeIsSecure() &&
+ !request.SchemeIsSecure()) {
+ sanitized_referrer.url = GURL();
+ }
+ break;
+ case blink::WebReferrerPolicyAlways:
+ break;
+ case blink::WebReferrerPolicyNever:
+ sanitized_referrer.url = GURL();
+ break;
+ case blink::WebReferrerPolicyOrigin:
+ sanitized_referrer.url = sanitized_referrer.url.GetOrigin();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return sanitized_referrer;
+ }
};
} // namespace content
diff --git a/chromium/content/public/common/renderer_preferences.cc b/chromium/content/public/common/renderer_preferences.cc
index 1e4c6d55ec8..a43b94398bb 100644
--- a/chromium/content/public/common/renderer_preferences.cc
+++ b/chromium/content/public/common/renderer_preferences.cc
@@ -5,27 +5,17 @@
#include "content/public/common/renderer_preferences.h"
#include "third_party/skia/include/core/SkColor.h"
-
-namespace {
-// The touchpad / touchscreen fling profiles are a matched set
-// determined via UX experimentation. Do not modify without
-// first discussing with rjkroege@chromium.org or
-// wjmaclean@chromium.org.
-const float kDefaultAlpha = -5.70762e+03f;
-const float kDefaultBeta = 1.72e+02f;
-const float kDefaultGamma = 3.7e+00f;
-}
+#include "ui/gfx/font_render_params.h"
namespace content {
RendererPreferences::RendererPreferences()
: can_accept_load_drops(true),
should_antialias_text(true),
- hinting(RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT),
+ hinting(gfx::FontRenderParams::HINTING_MEDIUM),
use_autohinter(false),
use_bitmaps(false),
- subpixel_rendering(
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT),
+ subpixel_rendering(gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE),
use_subpixel_positioning(false),
focus_ring_color(SkColorSetARGB(255, 229, 151, 0)),
thumb_active_color(SkColorSetRGB(244, 244, 244)),
@@ -43,16 +33,10 @@ RendererPreferences::RendererPreferences()
enable_do_not_track(false),
default_zoom_level(0),
report_frame_name_changes(false),
- touchpad_fling_profile(3),
- touchscreen_fling_profile(3),
tap_multiple_targets_strategy(TAP_MULTIPLE_TARGETS_STRATEGY_POPUP),
disable_client_blocked_error_page(false),
plugin_fullscreen_allowed(true),
use_video_overlay_for_embedded_encrypted_video(false) {
- touchpad_fling_profile[0] = kDefaultAlpha;
- touchpad_fling_profile[1] = kDefaultBeta;
- touchpad_fling_profile[2] = kDefaultGamma;
- touchscreen_fling_profile = touchpad_fling_profile;
}
RendererPreferences::~RendererPreferences() { }
diff --git a/chromium/content/public/common/renderer_preferences.h b/chromium/content/public/common/renderer_preferences.h
index 43e43c9e589..cb13db7908b 100644
--- a/chromium/content/public/common/renderer_preferences.h
+++ b/chromium/content/public/common/renderer_preferences.h
@@ -17,26 +17,10 @@
#include "content/common/content_export.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/font_render_params.h"
namespace content {
-enum RendererPreferencesHintingEnum {
- RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT = 0,
- RENDERER_PREFERENCES_HINTING_NONE,
- RENDERER_PREFERENCES_HINTING_SLIGHT,
- RENDERER_PREFERENCES_HINTING_MEDIUM,
- RENDERER_PREFERENCES_HINTING_FULL,
-};
-
-enum RendererPreferencesSubpixelRenderingEnum {
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT = 0,
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE,
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB,
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR,
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB,
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR,
-};
-
enum TapMultipleTargetsStrategy {
TAP_MULTIPLE_TARGETS_STRATEGY_ZOOM = 0,
TAP_MULTIPLE_TARGETS_STRATEGY_POPUP,
@@ -59,7 +43,7 @@ struct CONTENT_EXPORT RendererPreferences {
// The level of hinting to use when rendering text.
// Currently only used by Linux.
- RendererPreferencesHintingEnum hinting;
+ gfx::FontRenderParams::Hinting hinting;
// Whether auto hinter should be used. Currently only used by Linux.
bool use_autohinter;
@@ -70,7 +54,7 @@ struct CONTENT_EXPORT RendererPreferences {
// The type of subpixel rendering to use for text.
// Currently only used by Linux.
- RendererPreferencesSubpixelRenderingEnum subpixel_rendering;
+ gfx::FontRenderParams::SubpixelRendering subpixel_rendering;
// Whether subpixel positioning should be used, permitting fractional X
// positions for glyphs. Currently only used by Linux.
@@ -129,12 +113,6 @@ struct CONTENT_EXPORT RendererPreferences {
// information.
bool report_frame_name_changes;
- // Controls deacceleration of touchpad-initiated flings.
- std::vector<float> touchpad_fling_profile;
-
- // Controls deacceleration of touchscreen-initiated flings.
- std::vector<float> touchscreen_fling_profile;
-
// How to handle a tap gesture touching multiple targets
TapMultipleTargetsStrategy tap_multiple_targets_strategy;
diff --git a/chromium/content/public/common/request_context_frame_type.h b/chromium/content/public/common/request_context_frame_type.h
new file mode 100644
index 00000000000..7a8ab30b3e1
--- /dev/null
+++ b/chromium/content/public/common/request_context_frame_type.h
@@ -0,0 +1,20 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_REQUEST_CONTEXT_FRAME_TYPE_H_
+#define CONTENT_PUBLIC_COMMON_REQUEST_CONTEXT_FRAME_TYPE_H_
+
+namespace content {
+
+enum RequestContextFrameType {
+ REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY = 0,
+ REQUEST_CONTEXT_FRAME_TYPE_NESTED,
+ REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ REQUEST_CONTEXT_FRAME_TYPE_LAST = REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_REQUEST_CONTEXT_FRAME_TYPE_H_
diff --git a/chromium/content/public/common/request_context_type.h b/chromium/content/public/common/request_context_type.h
new file mode 100644
index 00000000000..2a5a60ae814
--- /dev/null
+++ b/chromium/content/public/common/request_context_type.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_REQUEST_CONTEXT_TYPE_H_
+#define CONTENT_PUBLIC_COMMON_REQUEST_CONTEXT_TYPE_H_
+
+namespace content {
+
+enum RequestContextType {
+ REQUEST_CONTEXT_TYPE_UNSPECIFIED = 0,
+ REQUEST_CONTEXT_TYPE_AUDIO,
+ REQUEST_CONTEXT_TYPE_BEACON,
+ REQUEST_CONTEXT_TYPE_CSP_REPORT,
+ REQUEST_CONTEXT_TYPE_DOWNLOAD,
+ REQUEST_CONTEXT_TYPE_EMBED,
+ REQUEST_CONTEXT_TYPE_EVENT_SOURCE,
+ REQUEST_CONTEXT_TYPE_FAVICON,
+ REQUEST_CONTEXT_TYPE_FETCH,
+ REQUEST_CONTEXT_TYPE_FONT,
+ REQUEST_CONTEXT_TYPE_FORM,
+ REQUEST_CONTEXT_TYPE_FRAME,
+ REQUEST_CONTEXT_TYPE_HYPERLINK,
+ REQUEST_CONTEXT_TYPE_IFRAME,
+ REQUEST_CONTEXT_TYPE_IMAGE,
+ REQUEST_CONTEXT_TYPE_IMAGE_SET,
+ REQUEST_CONTEXT_TYPE_IMPORT,
+ REQUEST_CONTEXT_TYPE_INTERNAL,
+ REQUEST_CONTEXT_TYPE_LOCATION,
+ REQUEST_CONTEXT_TYPE_MANIFEST,
+ REQUEST_CONTEXT_TYPE_OBJECT,
+ REQUEST_CONTEXT_TYPE_PING,
+ REQUEST_CONTEXT_TYPE_PLUGIN,
+ REQUEST_CONTEXT_TYPE_PREFETCH,
+ REQUEST_CONTEXT_TYPE_SCRIPT,
+ REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ REQUEST_CONTEXT_TYPE_SHARED_WORKER,
+ REQUEST_CONTEXT_TYPE_SUBRESOURCE,
+ REQUEST_CONTEXT_TYPE_STYLE,
+ REQUEST_CONTEXT_TYPE_TRACK,
+ REQUEST_CONTEXT_TYPE_VIDEO,
+ REQUEST_CONTEXT_TYPE_WORKER,
+ REQUEST_CONTEXT_TYPE_XML_HTTP_REQUEST,
+ REQUEST_CONTEXT_TYPE_XSLT,
+ REQUEST_CONTEXT_TYPE_LAST = REQUEST_CONTEXT_TYPE_XSLT
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_REQUEST_CONTEXT_TYPE_H_
diff --git a/chromium/content/public/common/resource_devtools_info.cc b/chromium/content/public/common/resource_devtools_info.cc
index 657ac3af23f..93ea6d14567 100644
--- a/chromium/content/public/common/resource_devtools_info.cc
+++ b/chromium/content/public/common/resource_devtools_info.cc
@@ -13,4 +13,15 @@ ResourceDevToolsInfo::ResourceDevToolsInfo()
ResourceDevToolsInfo::~ResourceDevToolsInfo() {
}
+scoped_refptr<ResourceDevToolsInfo> ResourceDevToolsInfo::DeepCopy() const {
+ scoped_refptr<ResourceDevToolsInfo> new_info = new ResourceDevToolsInfo;
+ new_info->http_status_code = http_status_code;
+ new_info->http_status_text = http_status_text;
+ new_info->request_headers = request_headers;
+ new_info->response_headers = response_headers;
+ new_info->request_headers_text = request_headers_text;
+ new_info->response_headers_text = response_headers_text;
+ return new_info;
+}
+
} // namespace content
diff --git a/chromium/content/public/common/resource_devtools_info.h b/chromium/content/public/common/resource_devtools_info.h
index d9485badfec..8c1e8e3433e 100644
--- a/chromium/content/public/common/resource_devtools_info.h
+++ b/chromium/content/public/common/resource_devtools_info.h
@@ -10,16 +10,20 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
+#include "base/strings/string_split.h"
#include "content/common/content_export.h"
namespace content {
+// Note: when modifying this structure, also update DeepCopy in
+// resource_devtools_info.cc.
struct ResourceDevToolsInfo : base::RefCounted<ResourceDevToolsInfo> {
- typedef std::vector<std::pair<std::string, std::string> >
- HeadersVector;
+ typedef base::StringPairs HeadersVector;
CONTENT_EXPORT ResourceDevToolsInfo();
+ scoped_refptr<ResourceDevToolsInfo> DeepCopy() const;
+
int32 http_status_code;
std::string http_status_text;
HeadersVector request_headers;
diff --git a/chromium/content/public/common/resource_response.cc b/chromium/content/public/common/resource_response.cc
new file mode 100644
index 00000000000..92abfba8e3c
--- /dev/null
+++ b/chromium/content/public/common/resource_response.cc
@@ -0,0 +1,56 @@
+// Copyright 2014 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 "content/public/common/resource_response.h"
+
+#include "net/http/http_response_headers.h"
+
+namespace content {
+
+scoped_refptr<ResourceResponse> ResourceResponse::DeepCopy() const {
+ scoped_refptr<ResourceResponse> new_response(new ResourceResponse);
+ new_response->head.request_time = head.request_time;
+ new_response->head.response_time = head.response_time;
+ if (head.headers.get()) {
+ new_response->head.headers =
+ new net::HttpResponseHeaders(head.headers->raw_headers());
+ }
+ new_response->head.mime_type = head.mime_type;
+ new_response->head.charset = head.charset;
+ new_response->head.security_info = head.security_info;
+ new_response->head.content_length = head.content_length;
+ new_response->head.encoded_data_length = head.encoded_data_length;
+ new_response->head.appcache_id = head.appcache_id;
+ new_response->head.appcache_manifest_url = head.appcache_manifest_url;
+ new_response->head.load_timing = head.load_timing;
+ if (head.devtools_info.get()) {
+ new_response->head.devtools_info = head.devtools_info->DeepCopy();
+ }
+ new_response->head.download_file_path = head.download_file_path;
+ new_response->head.was_fetched_via_spdy = head.was_fetched_via_spdy;
+ new_response->head.was_npn_negotiated = head.was_npn_negotiated;
+ new_response->head.was_alternate_protocol_available =
+ new_response->head.was_alternate_protocol_available;
+ new_response->head.connection_info = head.connection_info;
+ new_response->head.was_fetched_via_proxy = head.was_fetched_via_proxy;
+ new_response->head.proxy_server = head.proxy_server;
+ new_response->head.npn_negotiated_protocol = head.npn_negotiated_protocol;
+ new_response->head.socket_address = head.socket_address;
+ new_response->head.was_fetched_via_service_worker =
+ head.was_fetched_via_service_worker;
+ new_response->head.was_fallback_required_by_service_worker =
+ head.was_fallback_required_by_service_worker;
+ new_response->head.original_url_via_service_worker =
+ head.original_url_via_service_worker;
+ new_response->head.response_type_via_service_worker =
+ head.response_type_via_service_worker;
+ new_response->head.service_worker_fetch_start =
+ head.service_worker_fetch_start;
+ new_response->head.service_worker_fetch_ready =
+ head.service_worker_fetch_ready;
+ new_response->head.service_worker_fetch_end = head.service_worker_fetch_end;
+ return new_response;
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/resource_response.h b/chromium/content/public/common/resource_response.h
index a9a6addaaca..2c64d6195c3 100644
--- a/chromium/content/public/common/resource_response.h
+++ b/chromium/content/public/common/resource_response.h
@@ -20,8 +20,6 @@ namespace content {
// Parameters for a resource response header.
struct ResourceResponseHead : ResourceResponseInfo {
- // The response error_code.
- int error_code;
// TimeTicks::Now() when the browser received the request from the renderer.
base::TimeTicks request_start;
// TimeTicks::Now() when the browser sent the response to the renderer.
@@ -30,6 +28,8 @@ struct ResourceResponseHead : ResourceResponseInfo {
// Parameters for a synchronous resource response.
struct SyncLoadResult : ResourceResponseHead {
+ // The response error_code.
+ int error_code;
// The final URL after any redirects.
GURL final_url;
@@ -40,12 +40,20 @@ struct SyncLoadResult : ResourceResponseHead {
// Simple wrapper that refcounts ResourceResponseHead.
// Inherited, rather than typedef'd, to allow forward declarations.
struct CONTENT_EXPORT ResourceResponse
- : public base::RefCounted<ResourceResponse> {
+ : public base::RefCountedThreadSafe<ResourceResponse> {
public:
ResourceResponseHead head;
+ // Performs a deep copy of the ResourceResponse and all fields in it, safe to
+ // pass across threads.
+ //
+ // TODO(davidben): This structure should be passed along in a scoped_ptr. It's
+ // currently reference-counted to avoid copies, but may be
+ // modified. https://crbug.com/416050
+ scoped_refptr<ResourceResponse> DeepCopy() const;
+
private:
- friend class base::RefCounted<ResourceResponse>;
+ friend class base::RefCountedThreadSafe<ResourceResponse>;
~ResourceResponse() {}
};
diff --git a/chromium/content/public/common/resource_response_info.cc b/chromium/content/public/common/resource_response_info.cc
index 70dbc508d34..d5e81e91b35 100644
--- a/chromium/content/public/common/resource_response_info.cc
+++ b/chromium/content/public/common/resource_response_info.cc
@@ -4,20 +4,24 @@
#include "content/public/common/resource_response_info.h"
+#include "content/public/common/appcache_info.h"
#include "net/http/http_response_headers.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
namespace content {
ResourceResponseInfo::ResourceResponseInfo()
: content_length(-1),
encoded_data_length(-1),
- appcache_id(appcache::kAppCacheNoCacheId),
+ appcache_id(kAppCacheNoCacheId),
was_fetched_via_spdy(false),
was_npn_negotiated(false),
was_alternate_protocol_available(false),
connection_info(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
- was_fetched_via_proxy(false) {
+ was_fetched_via_proxy(false),
+ was_fetched_via_service_worker(false),
+ was_fallback_required_by_service_worker(false),
+ response_type_via_service_worker(
+ blink::WebServiceWorkerResponseTypeDefault) {
}
ResourceResponseInfo::~ResourceResponseInfo() {
diff --git a/chromium/content/public/common/resource_response_info.h b/chromium/content/public/common/resource_response_info.h
index 31fa4b905b9..42c2a8c8aec 100644
--- a/chromium/content/public/common/resource_response_info.h
+++ b/chromium/content/public/common/resource_response_info.h
@@ -15,11 +15,15 @@
#include "content/public/common/resource_devtools_info.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_timing_info.h"
+#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponseType.h"
#include "url/gurl.h"
namespace content {
+// Note: when modifying this structure, also update ResourceResponse::DeepCopy
+// in resource_response.cc.
struct ResourceResponseInfo {
CONTENT_EXPORT ResourceResponseInfo();
CONTENT_EXPORT ~ResourceResponseInfo();
@@ -89,14 +93,38 @@ struct ResourceResponseInfo {
// True if the response was fetched via an explicit proxy (as opposed to a
// transparent proxy). The proxy could be any type of proxy, HTTP or SOCKS.
- // Note: we cannot tell if a transparent proxy may have been involved.
+ // Note: we cannot tell if a transparent proxy may have been involved. If
+ // true, |proxy_server| contains the name of the proxy server that was used.
bool was_fetched_via_proxy;
+ net::HostPortPair proxy_server;
// NPN protocol negotiated with the server.
std::string npn_negotiated_protocol;
// Remote address of the socket which fetched this resource.
net::HostPortPair socket_address;
+
+ // True if the response was fetched by a ServiceWorker.
+ bool was_fetched_via_service_worker;
+
+ // True when the request whoes mode is |CORS| or |CORS-with-forced-preflight|
+ // is sent to a ServiceWorker but FetchEvent.respondWith is not called. So the
+ // renderer have to resend the request with skip service worker flag
+ // considering the CORS preflight logic.
+ bool was_fallback_required_by_service_worker;
+
+ // The original URL of the response which was fetched by the ServiceWorker.
+ // This may be empty if the response was created inside the ServiceWorker.
+ GURL original_url_via_service_worker;
+
+ // The type of the response which was fetched by the ServiceWorker.
+ blink::WebServiceWorkerResponseType response_type_via_service_worker;
+
+ // ServiceWorker Timing Information. These will be set if the response is
+ // provided by the ServiceWorker, or kept empty.
+ base::TimeTicks service_worker_fetch_start;
+ base::TimeTicks service_worker_fetch_ready;
+ base::TimeTicks service_worker_fetch_end;
};
} // namespace content
diff --git a/chromium/content/public/common/resource_type.cc b/chromium/content/public/common/resource_type.cc
new file mode 100644
index 00000000000..6ff7fb6746d
--- /dev/null
+++ b/chromium/content/public/common/resource_type.cc
@@ -0,0 +1,13 @@
+// Copyright 2014 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 "content/public/common/resource_type.h"
+
+namespace content {
+
+bool IsResourceTypeFrame(ResourceType type) {
+ return type == RESOURCE_TYPE_MAIN_FRAME || type == RESOURCE_TYPE_SUB_FRAME;
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/resource_type.h b/chromium/content/public/common/resource_type.h
new file mode 100644
index 00000000000..f71d953df4e
--- /dev/null
+++ b/chromium/content/public/common/resource_type.h
@@ -0,0 +1,39 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_RESOURCE_TYPE_H_
+#define CONTENT_PUBLIC_COMMON_RESOURCE_TYPE_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Used in histograms, so please add new types at the end, and rename unused
+// entries to RESOURCETYPE_UNUSED_0, etc...
+enum ResourceType {
+ RESOURCE_TYPE_MAIN_FRAME = 0, // top level page
+ RESOURCE_TYPE_SUB_FRAME, // frame or iframe
+ RESOURCE_TYPE_STYLESHEET, // a CSS stylesheet
+ RESOURCE_TYPE_SCRIPT, // an external script
+ RESOURCE_TYPE_IMAGE, // an image (jpg/gif/png/etc)
+ RESOURCE_TYPE_FONT_RESOURCE, // a font
+ RESOURCE_TYPE_SUB_RESOURCE, // an "other" subresource.
+ RESOURCE_TYPE_OBJECT, // an object (or embed) tag for a plugin,
+ // or a resource that a plugin requested.
+ RESOURCE_TYPE_MEDIA, // a media resource.
+ RESOURCE_TYPE_WORKER, // the main resource of a dedicated worker.
+ RESOURCE_TYPE_SHARED_WORKER, // the main resource of a shared worker.
+ RESOURCE_TYPE_PREFETCH, // an explicitly requested prefetch
+ RESOURCE_TYPE_FAVICON, // a favicon
+ RESOURCE_TYPE_XHR, // a XMLHttpRequest
+ RESOURCE_TYPE_PING, // a ping request for <a ping>
+ RESOURCE_TYPE_SERVICE_WORKER, // the main resource of a service worker.
+ RESOURCE_TYPE_LAST_TYPE
+};
+
+CONTENT_EXPORT bool IsResourceTypeFrame(ResourceType type);
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_RESOURCE_TYPE_H_
diff --git a/chromium/content/public/common/result_codes.h b/chromium/content/public/common/result_codes.h
index 1bf625d0157..d0963a3b14b 100644
--- a/chromium/content/public/common/result_codes.h
+++ b/chromium/content/public/common/result_codes.h
@@ -7,11 +7,30 @@
namespace content {
+// This file consolidates all the return codes for the browser and renderer
+// process. The return code is the value that:
+// a) is returned by main() or winmain(), or
+// b) specified in the call for ExitProcess() or TerminateProcess(), or
+// c) the exception value that causes a process to terminate.
+//
+// It is advisable to not use negative numbers because the Windows API returns
+// it as an unsigned long and the exception values have high numbers. For
+// example EXCEPTION_ACCESS_VIOLATION value is 0xC0000005.
+//
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.common
enum ResultCode {
+ // Process terminated normally.
+ RESULT_CODE_NORMAL_EXIT,
-#define RESULT_CODE(label, value) RESULT_CODE_ ## label = value,
-#include "content/public/common/result_codes_list.h"
-#undef RESULT_CODE
+ // Process was killed by user or system.
+ RESULT_CODE_KILLED,
+
+ // Process hung.
+ RESULT_CODE_HUNG,
+
+ // A bad message caused the process termination.
+ RESULT_CODE_KILLED_BAD_MESSAGE,
// Last return code (keep this last).
RESULT_CODE_LAST_CODE
diff --git a/chromium/content/public/common/result_codes_list.h b/chromium/content/public/common/result_codes_list.h
deleted file mode 100644
index 589fb458eba..00000000000
--- a/chromium/content/public/common/result_codes_list.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 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.
-
-// Intentionally no include guards because this file is meant to be included
-// inside a macro to generate enum values.
-
-// This file consolidates all the return codes for the browser and renderer
-// process. The return code is the value that:
-// a) is returned by main() or winmain(), or
-// b) specified in the call for ExitProcess() or TerminateProcess(), or
-// c) the exception value that causes a process to terminate.
-//
-// It is advisable to not use negative numbers because the Windows API returns
-// it as an unsigned long and the exception values have high numbers. For
-// example EXCEPTION_ACCESS_VIOLATION value is 0xC0000005.
-
-#include "build/build_config.h"
-
-// Process terminated normally.
-RESULT_CODE(NORMAL_EXIT, 0)
-
-// Process was killed by user or system.
-RESULT_CODE(KILLED, 1)
-
-// Process hung.
-RESULT_CODE(HUNG, 2)
-
-// A bad message caused the process termination.
-RESULT_CODE(KILLED_BAD_MESSAGE, 3)
diff --git a/chromium/content/public/common/sandbox_init.h b/chromium/content/public/common/sandbox_init.h
index 313662da0b0..4173d9afe4d 100644
--- a/chromium/content/public/common/sandbox_init.h
+++ b/chromium/content/public/common/sandbox_init.h
@@ -16,7 +16,9 @@ class FilePath;
}
namespace sandbox {
-class SandboxBPFPolicy;
+namespace bpf_dsl {
+class Policy;
+}
struct SandboxInterfaceInfo;
}
@@ -86,11 +88,11 @@ class SandboxInitializerDelegate;
// Initialize a seccomp-bpf sandbox. |policy| may not be NULL.
// Returns true if the sandbox has been properly engaged.
CONTENT_EXPORT bool InitializeSandbox(
- scoped_ptr<sandbox::SandboxBPFPolicy> policy);
+ scoped_ptr<sandbox::bpf_dsl::Policy> policy);
// Return a "baseline" policy. This is used by a SandboxInitializerDelegate to
// implement a policy that is derived from the baseline.
-CONTENT_EXPORT scoped_ptr<sandbox::SandboxBPFPolicy>
+CONTENT_EXPORT scoped_ptr<sandbox::bpf_dsl::Policy>
GetBPFSandboxBaselinePolicy();
#endif // defined(OS_LINUX)
diff --git a/chromium/content/public/common/sandbox_type_mac.h b/chromium/content/public/common/sandbox_type_mac.h
index 4c7faaa756c..6f8a6f0e11f 100644
--- a/chromium/content/public/common/sandbox_type_mac.h
+++ b/chromium/content/public/common/sandbox_type_mac.h
@@ -18,12 +18,6 @@ enum SandboxType {
SANDBOX_TYPE_RENDERER = SANDBOX_TYPE_FIRST_TYPE,
- // The worker process uses the most restrictive sandbox which has almost
- // *everything* locked down. Only a couple of /System/Library/ paths and
- // some other very basic operations (e.g., reading metadata to allow
- // following symlinks) are permitted.
- SANDBOX_TYPE_WORKER,
-
// Utility process is as restrictive as the worker process except full
// access is allowed to one configurable directory.
SANDBOX_TYPE_UTILITY,
diff --git a/chromium/content/public/common/sandboxed_process_launcher_delegate.h b/chromium/content/public/common/sandboxed_process_launcher_delegate.h
index 3f634a159f3..134fc0f58ef 100644
--- a/chromium/content/public/common/sandboxed_process_launcher_delegate.h
+++ b/chromium/content/public/common/sandboxed_process_launcher_delegate.h
@@ -6,8 +6,8 @@
#define CONTENT_PUBLIC_COMMON_SANDBOXED_PROCESS_LAUNCHER_DELEGATE_H_
#include "base/environment.h"
+#include "base/files/scoped_file.h"
#include "base/process/process.h"
-
#include "content/common/content_export.h"
#if defined(OS_MACOSX)
@@ -64,7 +64,7 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate {
virtual base::EnvironmentMap GetEnvironment();
// Return the file descriptor for the IPC channel.
- virtual int GetIpcFd() = 0;
+ virtual base::ScopedFD TakeIpcFd() = 0;
#if defined(OS_MACOSX)
// Gets the Mac SandboxType to enforce on the process. Return
diff --git a/chromium/content/public/common/screen_orientation_values.h b/chromium/content/public/common/screen_orientation_values.h
index fe421a2b793..422344d9c1d 100644
--- a/chromium/content/public/common/screen_orientation_values.h
+++ b/chromium/content/public/common/screen_orientation_values.h
@@ -7,10 +7,18 @@
namespace content {
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.common
enum ScreenOrientationValues {
-#define DEFINE_SCREEN_ORIENTATION_VALUE(name, value) name = value,
-#include "content/public/common/screen_orientation_values_list.h"
-#undef DEFINE_SCREEN_ORIENTATION_VALUE
+ SCREEN_ORIENTATION_VALUES_DEFAULT,
+ SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY,
+ SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY,
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY,
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY,
+ SCREEN_ORIENTATION_VALUES_ANY,
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE,
+ SCREEN_ORIENTATION_VALUES_PORTRAIT,
+ SCREEN_ORIENTATION_VALUES_NATURAL,
};
} // namespace content
diff --git a/chromium/content/public/common/screen_orientation_values_list.h b/chromium/content/public/common/screen_orientation_values_list.h
deleted file mode 100644
index 9cc6f92b171..00000000000
--- a/chromium/content/public/common/screen_orientation_values_list.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 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 CONTENT_PUBLIC_COMMON_SCREEN_ORIENTATION_VALUES_LIST_H_
-#define CONTENT_PUBLIC_COMMON_SCREEN_ORIENTATION_VALUES_LIST_H_
-
-#ifndef DEFINE_SCREEN_ORIENTATION_VALUE
-#error "DEFINE_SCREEN_ORIENTATION_VALUE should be defined before including this"
-#endif
-
-// These values are defined with macros so that a Java class can be generated
-// for them.
-DEFINE_SCREEN_ORIENTATION_VALUE(DEFAULT, 0)
-DEFINE_SCREEN_ORIENTATION_VALUE(PORTRAIT_PRIMARY, 1)
-DEFINE_SCREEN_ORIENTATION_VALUE(PORTRAIT_SECONDARY, 2)
-DEFINE_SCREEN_ORIENTATION_VALUE(LANDSCAPE_PRIMARY, 3)
-DEFINE_SCREEN_ORIENTATION_VALUE(LANDSCAPE_SECONDARY, 4)
-DEFINE_SCREEN_ORIENTATION_VALUE(ANY, 5)
-DEFINE_SCREEN_ORIENTATION_VALUE(LANDSCAPE, 6)
-DEFINE_SCREEN_ORIENTATION_VALUE(PORTRAIT, 7)
-
-#endif // CONTENT_PUBLIC_COMMON_SCREEN_ORIENTATION_VALUES_LIST_H_
diff --git a/chromium/content/public/common/service_registry.h b/chromium/content/public/common/service_registry.h
new file mode 100644
index 00000000000..be2294ee53e
--- /dev/null
+++ b/chromium/content/public/common/service_registry.h
@@ -0,0 +1,76 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_SERVICE_REGISTRY_H_
+#define CONTENT_PUBLIC_COMMON_SERVICE_REGISTRY_H_
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace content {
+
+// A ServiceRegistry exposes local services that have been added using
+// AddService to a paired remote ServiceRegistry and provides local access to
+// services exposed by the remote ServiceRegistry through
+// ConnectToRemoteService.
+class CONTENT_EXPORT ServiceRegistry {
+ public:
+ virtual ~ServiceRegistry() {}
+
+ // Make the service created by |service_factory| available to the remote
+ // ServiceProvider. In response to each request for a service,
+ // |service_factory| will be run with an InterfaceRequest<Interface>
+ // representing that request. Adding a factory for an already registered
+ // service will override the factory. Existing connections to the service are
+ // unaffected.
+ template <typename Interface>
+ void AddService(const base::Callback<void(mojo::InterfaceRequest<Interface>)>
+ service_factory) {
+ AddService(Interface::Name_,
+ base::Bind(&ServiceRegistry::ForwardToServiceFactory<Interface>,
+ service_factory));
+ }
+ virtual void AddService(
+ const std::string& service_name,
+ const base::Callback<void(mojo::ScopedMessagePipeHandle)>
+ service_factory) = 0;
+
+ // Remove future access to the service implementing Interface. Existing
+ // connections to the service are unaffected.
+ template <typename Interface>
+ void RemoveService() {
+ RemoveService(Interface::Name_);
+ }
+ virtual void RemoveService(const std::string& service_name) = 0;
+
+ // Connect to an interface provided by the remote service provider.
+ template <typename Interface>
+ void ConnectToRemoteService(mojo::InterfacePtr<Interface>* ptr) {
+ mojo::MessagePipe pipe;
+ ptr->Bind(pipe.handle0.Pass());
+ ConnectToRemoteService(Interface::Name_, pipe.handle1.Pass());
+ }
+ virtual void ConnectToRemoteService(const base::StringPiece& name,
+ mojo::ScopedMessagePipeHandle handle) = 0;
+
+ private:
+ template <typename Interface>
+ static void ForwardToServiceFactory(
+ const base::Callback<void(mojo::InterfaceRequest<Interface>)>
+ service_factory,
+ mojo::ScopedMessagePipeHandle handle) {
+ service_factory.Run(mojo::MakeRequest<Interface>(handle.Pass()));
+ }
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_SERVICE_REGISTRY_H_
diff --git a/chromium/content/public/common/show_desktop_notification_params.h b/chromium/content/public/common/show_desktop_notification_params.h
index 327f91cb8b6..c601654409a 100644
--- a/chromium/content/public/common/show_desktop_notification_params.h
+++ b/chromium/content/public/common/show_desktop_notification_params.h
@@ -7,6 +7,7 @@
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "url/gurl.h"
namespace content {
@@ -19,8 +20,9 @@ struct CONTENT_EXPORT ShowDesktopNotificationHostMsgParams {
// URL which is the origin that created this notification.
GURL origin;
- // Contents of the notification if is_html is false.
- GURL icon_url;
+ // Image to be displayed as part of the notification.
+ SkBitmap icon;
+
base::string16 title;
base::string16 body;
diff --git a/chromium/content/public/common/speech_recognition_error.h b/chromium/content/public/common/speech_recognition_error.h
index a12bc401cab..bbd73c7494c 100644
--- a/chromium/content/public/common/speech_recognition_error.h
+++ b/chromium/content/public/common/speech_recognition_error.h
@@ -7,10 +7,34 @@
namespace content {
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.common
+// GENERATED_JAVA_PREFIX_TO_STRIP: SPEECH_RECOGNITION_ERROR_
enum SpeechRecognitionErrorCode {
-#define DEFINE_SPEECH_RECOGNITION_ERROR(x, y) SPEECH_RECOGNITION_ERROR_##x = y,
-#include "content/public/common/speech_recognition_error_list.h"
-#undef DEFINE_SPEECH_RECOGNITION_ERROR
+ // There was no error.
+ SPEECH_RECOGNITION_ERROR_NONE,
+
+ // The user or a script aborted speech input.
+ SPEECH_RECOGNITION_ERROR_ABORTED,
+
+ // There was an error with recording audio.
+ SPEECH_RECOGNITION_ERROR_AUDIO,
+
+ // There was a network error.
+ SPEECH_RECOGNITION_ERROR_NETWORK,
+
+ // Not allowed for privacy or security reasons.
+ SPEECH_RECOGNITION_ERROR_NOT_ALLOWED,
+
+ // No speech heard before timeout.
+ SPEECH_RECOGNITION_ERROR_NO_SPEECH,
+
+ // Speech was heard, but could not be interpreted.
+ SPEECH_RECOGNITION_ERROR_NO_MATCH,
+
+ // There was an error in the speech recognition grammar.
+ SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR,
+ SPEECH_RECOGNITION_ERROR_LAST = SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR,
};
// Error details for the SPEECH_RECOGNITION_ERROR_AUDIO error.
diff --git a/chromium/content/public/common/speech_recognition_error_list.h b/chromium/content/public/common/speech_recognition_error_list.h
deleted file mode 100644
index 8a9614ec190..00000000000
--- a/chromium/content/public/common/speech_recognition_error_list.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2013 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 intentionally does not have header guards, it's included
-// inside a macro to generate enum values.
-
-#ifndef DEFINE_SPEECH_RECOGNITION_ERROR
-#error "DEFINE_SPEECH_RECOGNITION_ERROR must be defined before including this."
-#endif
-
-// There was no error.
-DEFINE_SPEECH_RECOGNITION_ERROR(NONE, 0)
-
-// The user or a script aborted speech input.
-DEFINE_SPEECH_RECOGNITION_ERROR(ABORTED, 1)
-
-// There was an error with recording audio.
-DEFINE_SPEECH_RECOGNITION_ERROR(AUDIO, 2)
-
-// There was a network error.
-DEFINE_SPEECH_RECOGNITION_ERROR(NETWORK, 3)
-
-// Not allowed for privacy or security reasons.
-DEFINE_SPEECH_RECOGNITION_ERROR(NOT_ALLOWED, 4)
-
-// No speech heard before timeout.
-DEFINE_SPEECH_RECOGNITION_ERROR(NO_SPEECH, 5)
-
-// Speech was heard, but could not be interpreted.
-DEFINE_SPEECH_RECOGNITION_ERROR(NO_MATCH, 6)
-
-// There was an error in the speech recognition grammar.
-DEFINE_SPEECH_RECOGNITION_ERROR(BAD_GRAMMAR, 7)
-
-// Reports the highest value. Update when adding a new error code.
-DEFINE_SPEECH_RECOGNITION_ERROR(LAST, 7)
-
diff --git a/chromium/content/public/common/stop_find_action.h b/chromium/content/public/common/stop_find_action.h
index 2477097ba36..0088eec3ea6 100644
--- a/chromium/content/public/common/stop_find_action.h
+++ b/chromium/content/public/common/stop_find_action.h
@@ -12,7 +12,8 @@ namespace content {
enum StopFindAction {
STOP_FIND_ACTION_CLEAR_SELECTION,
STOP_FIND_ACTION_KEEP_SELECTION,
- STOP_FIND_ACTION_ACTIVATE_SELECTION
+ STOP_FIND_ACTION_ACTIVATE_SELECTION,
+ STOP_FIND_ACTION_LAST = STOP_FIND_ACTION_ACTIVATE_SELECTION
};
} // namespace content
diff --git a/chromium/content/public/common/storage_quota_params.h b/chromium/content/public/common/storage_quota_params.h
index 6fd5cf82fd0..9ff61c2ffe8 100644
--- a/chromium/content/public/common/storage_quota_params.h
+++ b/chromium/content/public/common/storage_quota_params.h
@@ -7,8 +7,8 @@
#include "content/common/content_export.h"
#include "ipc/ipc_message.h"
+#include "storage/common/quota/quota_types.h"
#include "url/gurl.h"
-#include "webkit/common/quota/quota_types.h"
namespace content {
@@ -18,14 +18,14 @@ struct CONTENT_EXPORT StorageQuotaParams {
StorageQuotaParams()
: render_view_id(MSG_ROUTING_NONE),
request_id(-1),
- storage_type(quota::kStorageTypeTemporary),
+ storage_type(storage::kStorageTypeTemporary),
requested_size(0),
user_gesture(false) {}
int render_view_id;
int request_id;
GURL origin_url;
- quota::StorageType storage_type;
+ storage::StorageType storage_type;
uint64 requested_size;
// Request was made in the context of a user gesture.
diff --git a/chromium/content/public/common/three_d_api_types.h b/chromium/content/public/common/three_d_api_types.h
index e28f5bcb95e..8a29307d5fd 100644
--- a/chromium/content/public/common/three_d_api_types.h
+++ b/chromium/content/public/common/three_d_api_types.h
@@ -13,7 +13,9 @@ namespace content {
enum ThreeDAPIType {
THREE_D_API_TYPE_WEBGL,
- THREE_D_API_TYPE_PEPPER_3D
+ THREE_D_API_TYPE_PEPPER_3D,
+ THREE_D_API_TYPE_LAST = THREE_D_API_TYPE_PEPPER_3D
+
};
} // namespace content
diff --git a/chromium/content/public/common/top_controls_state.h b/chromium/content/public/common/top_controls_state.h
index 31535a0d8fb..7f71e6e451a 100644
--- a/chromium/content/public/common/top_controls_state.h
+++ b/chromium/content/public/common/top_controls_state.h
@@ -7,10 +7,12 @@
namespace content {
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content_public.common
enum TopControlsState {
-#define DEFINE_TOP_CONTROLS_STATE(name, value) name = value,
-#include "content/public/common/top_controls_state_list.h"
-#undef DEFINE_TOP_CONTROLS_STATE
+ TOP_CONTROLS_STATE_SHOWN = 1,
+ TOP_CONTROLS_STATE_HIDDEN = 2,
+ TOP_CONTROLS_STATE_BOTH = 3,
};
} // namespace content
diff --git a/chromium/content/public/common/top_controls_state_list.h b/chromium/content/public/common/top_controls_state_list.h
deleted file mode 100644
index c740304a169..00000000000
--- a/chromium/content/public/common/top_controls_state_list.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_PUBLIC_COMMON_TOP_CONTROLS_STATE_LIST_H_
-#define CONTENT_PUBLIC_COMMON_TOP_CONTROLS_STATE_LIST_H_
-
-#ifndef DEFINE_TOP_CONTROLS_STATE
-#error "DEFINE_TOP_CONTROLS_STATE should be defined before including this file"
-#endif
-
-// These values are defined with macros so that a Java class can be generated
-// for them.
-DEFINE_TOP_CONTROLS_STATE(SHOWN, 1)
-DEFINE_TOP_CONTROLS_STATE(HIDDEN, 2)
-DEFINE_TOP_CONTROLS_STATE(BOTH, 3)
-
-#endif // CONTENT_PUBLIC_COMMON_TOP_CONTROLS_STATE_LIST_H_
-
diff --git a/chromium/content/public/common/transition_element.h b/chromium/content/public/common/transition_element.h
new file mode 100644
index 00000000000..d8168b8ccf5
--- /dev/null
+++ b/chromium/content/public/common/transition_element.h
@@ -0,0 +1,23 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_TRANSITION_ELEMENT_H_
+#define CONTENT_PUBLIC_COMMON_TRANSITION_ELEMENT_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace content {
+
+// This struct stores the information of one transition element.
+struct CONTENT_EXPORT TransitionElement {
+ std::string name;
+ gfx::Rect rect;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_TRANSITION_ELEMENT_H_
diff --git a/chromium/content/public/common/url_constants.cc b/chromium/content/public/common/url_constants.cc
index ac65dedaaf6..fb7d9d64299 100644
--- a/chromium/content/public/common/url_constants.cc
+++ b/chromium/content/public/common/url_constants.cc
@@ -14,6 +14,9 @@ const char kGuestScheme[] = "chrome-guest";
const char kMetadataScheme[] = "metadata";
const char kSwappedOutScheme[] = "swappedout";
const char kViewSourceScheme[] = "view-source";
+#if defined(OS_CHROMEOS)
+const char kExternalFileScheme[] = "externalfile";
+#endif
const char kAboutSrcDocURL[] = "about:srcdoc";
@@ -32,6 +35,7 @@ const char kChromeUITcmallocHost[] = "tcmalloc";
const char kChromeUITracingHost[] = "tracing";
const char kChromeUIWebRTCInternalsHost[] = "webrtc-internals";
+const char kChromeUIBrowserCrashURL[] = "chrome://inducebrowsercrashforrealz";
const char kChromeUICrashURL[] = "chrome://crash";
const char kChromeUIDumpURL[] = "chrome://crashdump";
const char kChromeUIGpuCleanURL[] = "chrome://gpuclean";
diff --git a/chromium/content/public/common/url_constants.h b/chromium/content/public/common/url_constants.h
index 7f125f725a9..d04328d8c49 100644
--- a/chromium/content/public/common/url_constants.h
+++ b/chromium/content/public/common/url_constants.h
@@ -21,6 +21,9 @@ CONTENT_EXPORT extern const char kGuestScheme[];
CONTENT_EXPORT extern const char kMetadataScheme[];
CONTENT_EXPORT extern const char kSwappedOutScheme[];
CONTENT_EXPORT extern const char kViewSourceScheme[];
+#if defined(OS_CHROMEOS)
+CONTENT_EXPORT extern const char kExternalFileScheme[];
+#endif
// Hosts for about URLs.
CONTENT_EXPORT extern const char kAboutSrcDocURL[];
@@ -41,6 +44,7 @@ CONTENT_EXPORT extern const char kChromeUITracingHost[];
CONTENT_EXPORT extern const char kChromeUIWebRTCInternalsHost[];
// Full about URLs (including schemes).
+CONTENT_EXPORT extern const char kChromeUIBrowserCrashURL[];
CONTENT_EXPORT extern const char kChromeUICrashURL[];
CONTENT_EXPORT extern const char kChromeUIDumpURL[];
CONTENT_EXPORT extern const char kChromeUIGpuCleanURL[];
diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc
new file mode 100644
index 00000000000..dbe16297f90
--- /dev/null
+++ b/chromium/content/public/common/web_preferences.cc
@@ -0,0 +1,196 @@
+// Copyright 2014 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 "content/public/common/web_preferences.h"
+
+#include "base/basictypes.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/WebKit/public/web/WebSettings.h"
+#include "third_party/icu/source/common/unicode/uchar.h"
+
+using blink::WebSettings;
+
+namespace content {
+
+// "Zyyy" is the ISO 15924 script code for undetermined script aka Common.
+const char kCommonScript[] = "Zyyy";
+
+#define COMPILE_ASSERT_MATCHING_ENUMS(content_name, blink_name) \
+ COMPILE_ASSERT( \
+ static_cast<int>(content_name) == static_cast<int>(blink_name), \
+ mismatching_enums)
+
+COMPILE_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_MAC,
+ WebSettings::EditingBehaviorMac);
+COMPILE_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_WIN,
+ WebSettings::EditingBehaviorWin);
+COMPILE_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_UNIX,
+ WebSettings::EditingBehaviorUnix);
+COMPILE_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_ANDROID,
+ WebSettings::EditingBehaviorAndroid);
+
+COMPILE_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_OFF,
+ WebSettings::V8CacheOptionsOff);
+COMPILE_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_PARSE,
+ WebSettings::V8CacheOptionsParse);
+COMPILE_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_CODE,
+ WebSettings::V8CacheOptionsCode);
+COMPILE_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_LAST,
+ WebSettings::V8CacheOptionsCode);
+
+COMPILE_ASSERT_MATCHING_ENUMS(V8_SCRIPT_STREAMING_MODE_ALL,
+ WebSettings::V8ScriptStreamingModeAll);
+COMPILE_ASSERT_MATCHING_ENUMS(
+ V8_SCRIPT_STREAMING_MODE_ONLY_ASYNC_AND_DEFER,
+ WebSettings::V8ScriptStreamingModeOnlyAsyncAndDefer);
+COMPILE_ASSERT_MATCHING_ENUMS(
+ V8_SCRIPT_STREAMING_MODE_ALL_PLUS_BLOCK_PARSER_BLOCKING,
+ WebSettings::V8ScriptStreamingModeAllPlusBlockParsingBlocking);
+COMPILE_ASSERT_MATCHING_ENUMS(
+ V8_SCRIPT_STREAMING_MODE_LAST,
+ WebSettings::V8ScriptStreamingModeAllPlusBlockParsingBlocking);
+
+WebPreferences::WebPreferences()
+ : default_font_size(16),
+ default_fixed_font_size(13),
+ minimum_font_size(0),
+ minimum_logical_font_size(6),
+ default_encoding("ISO-8859-1"),
+ javascript_enabled(true),
+ web_security_enabled(true),
+ javascript_can_open_windows_automatically(true),
+ loads_images_automatically(true),
+ images_enabled(true),
+ plugins_enabled(true),
+ dom_paste_enabled(false), // enables execCommand("paste")
+ shrinks_standalone_images_to_fit(true),
+ uses_universal_detector(false), // Disabled: page cycler regression
+ text_areas_are_resizable(true),
+ java_enabled(true),
+ allow_scripts_to_close_windows(false),
+ remote_fonts_enabled(true),
+ javascript_can_access_clipboard(false),
+ xslt_enabled(true),
+ xss_auditor_enabled(true),
+ dns_prefetching_enabled(true),
+ local_storage_enabled(false),
+ databases_enabled(false),
+ application_cache_enabled(false),
+ tabs_to_links(true),
+ caret_browsing_enabled(false),
+ hyperlink_auditing_enabled(true),
+ is_online(true),
+ connection_type(net::NetworkChangeNotifier::CONNECTION_NONE),
+ allow_universal_access_from_file_urls(false),
+ allow_file_access_from_file_urls(false),
+ webaudio_enabled(false),
+ experimental_webgl_enabled(false),
+ pepper_3d_enabled(false),
+ flash_3d_enabled(true),
+ flash_stage3d_enabled(false),
+ flash_stage3d_baseline_enabled(false),
+ gl_multisampling_enabled(true),
+ privileged_webgl_extensions_enabled(false),
+ webgl_errors_to_console_enabled(true),
+ mock_scrollbars_enabled(false),
+ layer_squashing_enabled(true),
+ asynchronous_spell_checking_enabled(true),
+ unified_textchecker_enabled(false),
+ accelerated_2d_canvas_enabled(false),
+ minimum_accelerated_2d_canvas_size(257 * 256),
+ antialiased_2d_canvas_disabled(false),
+ antialiased_clips_2d_canvas_enabled(false),
+ accelerated_2d_canvas_msaa_sample_count(0),
+ accelerated_filters_enabled(false),
+ deferred_filters_enabled(false),
+ container_culling_enabled(false),
+ text_blobs_enabled(false),
+ allow_displaying_insecure_content(true),
+ allow_running_insecure_content(false),
+ password_echo_enabled(false),
+ should_print_backgrounds(false),
+ should_clear_document_background(true),
+ enable_scroll_animator(false),
+ region_based_columns_enabled(false),
+ touch_enabled(false),
+ device_supports_touch(false),
+ device_supports_mouse(true),
+ touch_adjustment_enabled(true),
+ pointer_events_max_touch_points(0),
+ sync_xhr_in_documents_enabled(true),
+ deferred_image_decoding_enabled(false),
+ image_color_profiles_enabled(false),
+ should_respect_image_orientation(false),
+ number_of_cpu_cores(1),
+#if defined(OS_MACOSX)
+ editing_behavior(EDITING_BEHAVIOR_MAC),
+#elif defined(OS_WIN)
+ editing_behavior(EDITING_BEHAVIOR_WIN),
+#elif defined(OS_ANDROID)
+ editing_behavior(EDITING_BEHAVIOR_ANDROID),
+#elif defined(OS_POSIX)
+ editing_behavior(EDITING_BEHAVIOR_UNIX),
+#else
+ editing_behavior(EDITING_BEHAVIOR_MAC),
+#endif
+ supports_multiple_windows(true),
+ viewport_enabled(false),
+ viewport_meta_enabled(false),
+ main_frame_resizes_are_orientation_changes(false),
+ initialize_at_minimum_page_scale(true),
+#if defined(OS_MACOSX)
+ smart_insert_delete_enabled(true),
+#else
+ smart_insert_delete_enabled(false),
+#endif
+ spatial_navigation_enabled(false),
+ pinch_virtual_viewport_enabled(false),
+ pinch_overlay_scrollbar_thickness(0),
+ use_solid_color_scrollbars(false),
+ navigate_on_drag_drop(true),
+ v8_cache_options(V8_CACHE_OPTIONS_OFF),
+ v8_script_streaming_enabled(false),
+ v8_script_streaming_mode(V8_SCRIPT_STREAMING_MODE_ALL),
+ slimming_paint_enabled(false),
+ cookie_enabled(true),
+ pepper_accelerated_video_decode_enabled(false)
+#if defined(OS_ANDROID)
+ ,
+ text_autosizing_enabled(true),
+ font_scale_factor(1.0f),
+ device_scale_adjustment(1.0f),
+ force_enable_zoom(false),
+ fullscreen_supported(true),
+ double_tap_to_zoom_enabled(true),
+ user_gesture_required_for_media_playback(true),
+ support_deprecated_target_density_dpi(false),
+ use_legacy_background_size_shorthand_behavior(false),
+ wide_viewport_quirk(false),
+ use_wide_viewport(true),
+ force_zero_layout_height(false),
+ viewport_meta_layout_size_quirk(false),
+ viewport_meta_merge_content_quirk(false),
+ viewport_meta_non_user_scalable_quirk(false),
+ viewport_meta_zero_values_quirk(false),
+ clobber_user_agent_initial_scale_quirk(false),
+ ignore_main_frame_overflow_hidden_quirk(false),
+ report_screen_size_in_physical_pixels_quirk(false)
+#endif
+{
+ standard_font_family_map[kCommonScript] =
+ base::ASCIIToUTF16("Times New Roman");
+ fixed_font_family_map[kCommonScript] = base::ASCIIToUTF16("Courier New");
+ serif_font_family_map[kCommonScript] = base::ASCIIToUTF16("Times New Roman");
+ sans_serif_font_family_map[kCommonScript] = base::ASCIIToUTF16("Arial");
+ cursive_font_family_map[kCommonScript] = base::ASCIIToUTF16("Script");
+ fantasy_font_family_map[kCommonScript] = base::ASCIIToUTF16("Impact");
+ pictograph_font_family_map[kCommonScript] =
+ base::ASCIIToUTF16("Times New Roman");
+}
+
+WebPreferences::~WebPreferences() {
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h
new file mode 100644
index 00000000000..057174fef62
--- /dev/null
+++ b/chromium/content/public/common/web_preferences.h
@@ -0,0 +1,203 @@
+// Copyright 2014 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 CONTENT_PUBLIC_COMMON_WEB_PREFERENCES_H_
+#define CONTENT_PUBLIC_COMMON_WEB_PREFERENCES_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "net/base/network_change_notifier.h"
+#include "url/gurl.h"
+
+namespace blink {
+class WebView;
+}
+
+namespace content {
+
+// Map of ISO 15924 four-letter script code to font family. For example,
+// "Arab" to "My Arabic Font".
+typedef std::map<std::string, base::string16> ScriptFontFamilyMap;
+
+enum EditingBehavior {
+ EDITING_BEHAVIOR_MAC,
+ EDITING_BEHAVIOR_WIN,
+ EDITING_BEHAVIOR_UNIX,
+ EDITING_BEHAVIOR_ANDROID,
+ EDITING_BEHAVIOR_LAST = EDITING_BEHAVIOR_ANDROID
+};
+
+enum V8CacheOptions {
+ V8_CACHE_OPTIONS_OFF,
+ V8_CACHE_OPTIONS_PARSE,
+ V8_CACHE_OPTIONS_CODE,
+ V8_CACHE_OPTIONS_LAST = V8_CACHE_OPTIONS_CODE
+};
+
+enum V8ScriptStreamingMode {
+ V8_SCRIPT_STREAMING_MODE_ALL,
+ V8_SCRIPT_STREAMING_MODE_ONLY_ASYNC_AND_DEFER,
+ V8_SCRIPT_STREAMING_MODE_ALL_PLUS_BLOCK_PARSER_BLOCKING,
+ V8_SCRIPT_STREAMING_MODE_LAST =
+ V8_SCRIPT_STREAMING_MODE_ALL_PLUS_BLOCK_PARSER_BLOCKING
+};
+
+// The ISO 15924 script code for undetermined script aka Common. It's the
+// default used on WebKit's side to get/set a font setting when no script is
+// specified.
+CONTENT_EXPORT extern const char kCommonScript[];
+
+// A struct for managing blink's settings.
+//
+// Adding new values to this class probably involves updating
+// blink::WebSettings, content/common/view_messages.h, browser/tab_contents/
+// render_view_host_delegate_helper.cc, and browser/profiles/profile.cc.
+struct CONTENT_EXPORT WebPreferences {
+ ScriptFontFamilyMap standard_font_family_map;
+ ScriptFontFamilyMap fixed_font_family_map;
+ ScriptFontFamilyMap serif_font_family_map;
+ ScriptFontFamilyMap sans_serif_font_family_map;
+ ScriptFontFamilyMap cursive_font_family_map;
+ ScriptFontFamilyMap fantasy_font_family_map;
+ ScriptFontFamilyMap pictograph_font_family_map;
+ int default_font_size;
+ int default_fixed_font_size;
+ int minimum_font_size;
+ int minimum_logical_font_size;
+ std::string default_encoding;
+ bool javascript_enabled;
+ bool web_security_enabled;
+ bool javascript_can_open_windows_automatically;
+ bool loads_images_automatically;
+ bool images_enabled;
+ bool plugins_enabled;
+ bool dom_paste_enabled;
+ bool shrinks_standalone_images_to_fit;
+ bool uses_universal_detector;
+ bool text_areas_are_resizable;
+ bool java_enabled;
+ bool allow_scripts_to_close_windows;
+ bool remote_fonts_enabled;
+ bool javascript_can_access_clipboard;
+ bool xslt_enabled;
+ bool xss_auditor_enabled;
+ // We don't use dns_prefetching_enabled to disable DNS prefetching. Instead,
+ // we disable the feature at a lower layer so that we catch non-WebKit uses
+ // of DNS prefetch as well.
+ bool dns_prefetching_enabled;
+ bool local_storage_enabled;
+ bool databases_enabled;
+ bool application_cache_enabled;
+ bool tabs_to_links;
+ bool caret_browsing_enabled;
+ bool hyperlink_auditing_enabled;
+ bool is_online;
+ net::NetworkChangeNotifier::ConnectionType connection_type;
+ bool allow_universal_access_from_file_urls;
+ bool allow_file_access_from_file_urls;
+ bool webaudio_enabled;
+ bool experimental_webgl_enabled;
+ bool pepper_3d_enabled;
+ bool flash_3d_enabled;
+ bool flash_stage3d_enabled;
+ bool flash_stage3d_baseline_enabled;
+ bool gl_multisampling_enabled;
+ bool privileged_webgl_extensions_enabled;
+ bool webgl_errors_to_console_enabled;
+ bool mock_scrollbars_enabled;
+ bool layer_squashing_enabled;
+ bool asynchronous_spell_checking_enabled;
+ bool unified_textchecker_enabled;
+ bool accelerated_2d_canvas_enabled;
+ int minimum_accelerated_2d_canvas_size;
+ bool antialiased_2d_canvas_disabled;
+ bool antialiased_clips_2d_canvas_enabled;
+ int accelerated_2d_canvas_msaa_sample_count;
+ bool accelerated_filters_enabled;
+ bool deferred_filters_enabled;
+ bool container_culling_enabled;
+ bool text_blobs_enabled;
+ bool allow_displaying_insecure_content;
+ bool allow_running_insecure_content;
+ bool password_echo_enabled;
+ bool should_print_backgrounds;
+ bool should_clear_document_background;
+ bool enable_scroll_animator;
+ bool css_variables_enabled;
+ bool region_based_columns_enabled;
+ bool touch_enabled;
+ bool device_supports_touch;
+ bool device_supports_mouse;
+ bool touch_adjustment_enabled;
+ int pointer_events_max_touch_points;
+ bool sync_xhr_in_documents_enabled;
+ bool deferred_image_decoding_enabled;
+ bool image_color_profiles_enabled;
+ bool should_respect_image_orientation;
+ int number_of_cpu_cores;
+ EditingBehavior editing_behavior;
+ bool supports_multiple_windows;
+ bool viewport_enabled;
+ bool viewport_meta_enabled;
+ bool main_frame_resizes_are_orientation_changes;
+ bool initialize_at_minimum_page_scale;
+ bool smart_insert_delete_enabled;
+ bool spatial_navigation_enabled;
+ bool pinch_virtual_viewport_enabled;
+ int pinch_overlay_scrollbar_thickness;
+ bool use_solid_color_scrollbars;
+ bool navigate_on_drag_drop;
+ V8CacheOptions v8_cache_options;
+ bool v8_script_streaming_enabled;
+ V8ScriptStreamingMode v8_script_streaming_mode;
+ bool slimming_paint_enabled;
+
+ // This flags corresponds to a Page's Settings' setCookieEnabled state. It
+ // only controls whether or not the "document.cookie" field is properly
+ // connected to the backing store, for instance if you wanted to be able to
+ // define custom getters and setters from within a unique security content
+ // without raising a DOM security exception.
+ bool cookie_enabled;
+
+ // This flag indicates whether H/W accelerated video decode is enabled for
+ // pepper plugins. Defaults to false.
+ bool pepper_accelerated_video_decode_enabled;
+
+#if defined(OS_ANDROID)
+ bool text_autosizing_enabled;
+ float font_scale_factor;
+ float device_scale_adjustment;
+ bool force_enable_zoom;
+ bool fullscreen_supported;
+ bool double_tap_to_zoom_enabled;
+ bool user_gesture_required_for_media_playback;
+ GURL default_video_poster_url;
+ bool support_deprecated_target_density_dpi;
+ bool use_legacy_background_size_shorthand_behavior;
+ bool wide_viewport_quirk;
+ bool use_wide_viewport;
+ bool force_zero_layout_height;
+ bool viewport_meta_layout_size_quirk;
+ bool viewport_meta_merge_content_quirk;
+ bool viewport_meta_non_user_scalable_quirk;
+ bool viewport_meta_zero_values_quirk;
+ bool clobber_user_agent_initial_scale_quirk;
+ bool ignore_main_frame_overflow_hidden_quirk;
+ bool report_screen_size_in_physical_pixels_quirk;
+#endif
+
+ // We try to keep the default values the same as the default values in
+ // chrome, except for the cases where it would require lots of extra work for
+ // the embedder to use the same default value.
+ WebPreferences();
+ ~WebPreferences();
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_WEB_PREFERENCES_H_
diff --git a/chromium/content/public/plugin/BUILD.gn b/chromium/content/public/plugin/BUILD.gn
index 059aea60ebd..c43de9bd3e8 100644
--- a/chromium/content/public/plugin/BUILD.gn
+++ b/chromium/content/public/plugin/BUILD.gn
@@ -2,8 +2,25 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("plugin") {
+# See //content/BUILD.gn for how this works.
+group("plugin") {
+ if (is_component_build) {
+ public_deps = [ "//content" ]
+ } else {
+ public_deps = [ ":plugin_sources" ]
+ }
+}
+
+source_set("plugin_sources") {
+ visibility = [ "//content/*" ]
+
sources = [
"content_plugin_client.h",
]
+
+ deps = [
+ "//base",
+ "//content/plugin",
+ "//content/public/common:common_sources",
+ ]
}
diff --git a/chromium/content/public/renderer/BUILD.gn b/chromium/content/public/renderer/BUILD.gn
index 414020506ab..3a5070b65b9 100644
--- a/chromium/content/public/renderer/BUILD.gn
+++ b/chromium/content/public/renderer/BUILD.gn
@@ -5,23 +5,42 @@
import("//build/config/features.gni")
import("//content/renderer/renderer.gni")
-source_set("renderer") {
+# See //content/BUILD.gn for how this works.
+group("renderer") {
+ if (is_component_build) {
+ public_deps = [ "//content" ]
+ } else {
+ public_deps = [ ":renderer_sources" ]
+ }
+}
+
+source_set("renderer_sources") {
+ visibility = [ "//content/*" ]
+
sources = rebase_path(content_renderer_gypi_values.public_renderer_sources,
".", "//content")
configs += [
"//content:content_implementation",
- "//content:libjingle_stub_config",
]
deps = [
+ "//content/public/common:common_sources",
"//content/renderer",
"//skia",
+ "//third_party/libjingle",
"//third_party/WebKit/public:blink_headers",
"//third_party/widevine/cdm:version_h",
+ "//ui/gfx",
"//v8",
]
+ allow_circular_includes_from = [
+ # This target is a pair with content/renderer. They always go together and
+ # include headers from each other.
+ "//content/renderer",
+ ]
+
if (enable_webrtc) {
sources += rebase_path(
content_renderer_gypi_values.public_renderer_webrtc_sources,
diff --git a/chromium/content/public/renderer/browser_plugin_delegate.h b/chromium/content/public/renderer/browser_plugin_delegate.h
new file mode 100644
index 00000000000..282adda24a4
--- /dev/null
+++ b/chromium/content/public/renderer/browser_plugin_delegate.h
@@ -0,0 +1,40 @@
+// Copyright 2014 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 CONTENT_PUBLIC_RENDERER_BROWSER_PLUGIN_DELEGATE_H_
+#define CONTENT_PUBLIC_RENDERER_BROWSER_PLUGIN_DELEGATE_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+class RenderFrame;
+
+// A delegate for BrowserPlugin which gets notified about the plugin load.
+// Implementations can provide additional steps necessary to change the load
+// behavior of the plugin.
+class CONTENT_EXPORT BrowserPluginDelegate {
+ public:
+ virtual ~BrowserPluginDelegate() {}
+
+ // Called when the BrowserPlugin's geometry has been computed for the first
+ // time.
+ virtual void Ready() {}
+
+ // Called when plugin document has finished loading.
+ virtual void DidFinishLoading() {}
+
+ // Called when plugin document receives data.
+ virtual void DidReceiveData(const char* data, int data_length) {}
+
+ // Sets the instance ID that idenfies the plugin within current render
+ // process.
+ virtual void SetElementInstanceID(int element_instance_id) {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_BROWSER_PLUGIN_DELEGATE_H_
diff --git a/chromium/content/public/renderer/content_renderer_client.cc b/chromium/content/public/renderer/content_renderer_client.cc
index 800bb55b151..ca1b9fe536f 100644
--- a/chromium/content/public/renderer/content_renderer_client.cc
+++ b/chromium/content/public/renderer/content_renderer_client.cc
@@ -4,18 +4,24 @@
#include "content/public/renderer/content_renderer_client.h"
+#include "third_party/WebKit/public/web/WebPluginPlaceholder.h"
+
namespace content {
SkBitmap* ContentRendererClient::GetSadPluginBitmap() {
- return NULL;
+ return nullptr;
}
SkBitmap* ContentRendererClient::GetSadWebViewBitmap() {
- return NULL;
+ return nullptr;
}
-std::string ContentRendererClient::GetDefaultEncoding() {
- return std::string();
+scoped_ptr<blink::WebPluginPlaceholder>
+ContentRendererClient::CreatePluginPlaceholder(
+ RenderFrame* render_frame,
+ blink::WebLocalFrame* frame,
+ const blink::WebPluginParams& params) {
+ return nullptr;
}
bool ContentRendererClient::OverrideCreatePlugin(
@@ -29,7 +35,7 @@ bool ContentRendererClient::OverrideCreatePlugin(
blink::WebPlugin* ContentRendererClient::CreatePluginReplacement(
RenderFrame* render_frame,
const base::FilePath& plugin_path) {
- return NULL;
+ return nullptr;
}
bool ContentRendererClient::HasErrorPage(int http_status_code,
@@ -50,38 +56,38 @@ void ContentRendererClient::DeferMediaLoad(RenderFrame* render_frame,
blink::WebMediaStreamCenter*
ContentRendererClient::OverrideCreateWebMediaStreamCenter(
blink::WebMediaStreamCenterClient* client) {
- return NULL;
+ return nullptr;
}
blink::WebRTCPeerConnectionHandler*
ContentRendererClient::OverrideCreateWebRTCPeerConnectionHandler(
blink::WebRTCPeerConnectionHandlerClient* client) {
- return NULL;
+ return nullptr;
}
blink::WebMIDIAccessor*
ContentRendererClient::OverrideCreateMIDIAccessor(
blink::WebMIDIAccessorClient* client) {
- return NULL;
+ return nullptr;
}
blink::WebAudioDevice*
ContentRendererClient::OverrideCreateAudioDevice(
double sample_rate) {
- return NULL;
+ return nullptr;
}
blink::WebClipboard* ContentRendererClient::OverrideWebClipboard() {
- return NULL;
+ return nullptr;
}
blink::WebThemeEngine* ContentRendererClient::OverrideThemeEngine() {
- return NULL;
+ return nullptr;
}
blink::WebSpeechSynthesizer* ContentRendererClient::OverrideSpeechSynthesizer(
blink::WebSpeechSynthesizerClient* client) {
- return NULL;
+ return nullptr;
}
bool ContentRendererClient::RunIdleHandlerWhenWidgetsHidden() {
@@ -117,7 +123,7 @@ bool ContentRendererClient::ShouldFork(blink::WebFrame* frame,
bool ContentRendererClient::WillSendRequest(
blink::WebFrame* frame,
- PageTransition transition_type,
+ ui::PageTransition transition_type,
const GURL& url,
const GURL& first_party_for_cookies,
GURL* new_url) {
@@ -135,7 +141,7 @@ bool ContentRendererClient::IsLinkVisited(unsigned long long link_hash) {
blink::WebPrescientNetworking*
ContentRendererClient::GetPrescientNetworking() {
- return NULL;
+ return nullptr;
}
bool ContentRendererClient::ShouldOverridePageVisibilityState(
@@ -146,7 +152,7 @@ bool ContentRendererClient::ShouldOverridePageVisibilityState(
const void* ContentRendererClient::CreatePPAPIInterface(
const std::string& interface_name) {
- return NULL;
+ return nullptr;
}
bool ContentRendererClient::IsExternalPepperPlugin(
@@ -159,7 +165,7 @@ bool ContentRendererClient::AllowPepperMediaStreamAPI(const GURL& url) {
}
void ContentRendererClient::AddKeySystems(
- std::vector<KeySystemInfo>* key_systems) {
+ std::vector<media::KeySystemInfo>* key_systems) {
}
bool ContentRendererClient::ShouldReportDetailedMessageForSource(
@@ -174,7 +180,31 @@ bool ContentRendererClient::ShouldEnableSiteIsolationPolicy() const {
blink::WebWorkerPermissionClientProxy*
ContentRendererClient::CreateWorkerPermissionClientProxy(
RenderFrame* render_frame, blink::WebFrame* frame) {
- return NULL;
+ return nullptr;
+}
+
+bool ContentRendererClient::IsPluginAllowedToUseCompositorAPI(const GURL& url) {
+ return false;
+}
+
+bool ContentRendererClient::IsPluginAllowedToUseVideoDecodeAPI(
+ const GURL& url) {
+ return false;
+}
+
+bool ContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() {
+ return false;
+}
+
+BrowserPluginDelegate* ContentRendererClient::CreateBrowserPluginDelegate(
+ RenderFrame* render_frame,
+ const std::string& mime_type,
+ const GURL& original_url) {
+ return nullptr;
+}
+
+std::string ContentRendererClient::GetUserAgentOverrideForURL(const GURL& url) {
+ return std::string();
}
} // namespace content
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index ca600396daa..7b79a5cb177 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -8,14 +8,15 @@
#include <string>
#include <vector>
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/page_transition_types.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
#include "third_party/WebKit/public/web/WebNavigationType.h"
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
+#include "ui/base/page_transition_types.h"
#include "v8/include/v8.h"
class GURL;
@@ -37,6 +38,7 @@ class WebMediaStreamCenter;
class WebMediaStreamCenterClient;
class WebPlugin;
class WebPluginContainer;
+class WebPluginPlaceholder;
class WebPrescientNetworking;
class WebRTCPeerConnectionHandler;
class WebRTCPeerConnectionHandlerClient;
@@ -49,12 +51,16 @@ struct WebPluginParams;
struct WebURLError;
}
+namespace media {
+struct KeySystemInfo;
+}
+
namespace content {
+class BrowserPluginDelegate;
class DocumentState;
class RenderFrame;
class RenderView;
class SynchronousCompositor;
-struct KeySystemInfo;
struct WebPluginInfo;
// Embedder API for participating in renderer logic.
@@ -83,8 +89,13 @@ class CONTENT_EXPORT ContentRendererClient {
// none.
virtual SkBitmap* GetSadWebViewBitmap();
- // Returns the default text encoding.
- virtual std::string GetDefaultEncoding();
+ // Allows the embedder to create a plugin placeholder instead of a plugin.
+ // Called before OverrideCreatePlugin. May return null to decline to provide
+ // a plugin placeholder.
+ virtual scoped_ptr<blink::WebPluginPlaceholder> CreatePluginPlaceholder(
+ RenderFrame* render_frame,
+ blink::WebLocalFrame* frame,
+ const blink::WebPluginParams& params);
// Allows the embedder to override creating a plugin. If it returns true, then
// |plugin| will contain the created plugin, although it could be NULL. If it
@@ -101,6 +112,12 @@ class CONTENT_EXPORT ContentRendererClient {
RenderFrame* render_frame,
const base::FilePath& plugin_path);
+ // Creates a delegate for browser plugin.
+ virtual BrowserPluginDelegate* CreateBrowserPluginDelegate(
+ RenderFrame* render_frame,
+ const std::string& mime_type,
+ const GURL& original_url);
+
// Returns true if the embedder has an error page to show for the given http
// status code. If so |error_domain| should be set to according to WebURLError
// and the embedder's GetNavigationErrorHtml will be called afterwards to get
@@ -207,7 +224,7 @@ class CONTENT_EXPORT ContentRendererClient {
// Notifies the embedder that the given frame is requesting the resource at
// |url|. If the function returns true, the url is changed to |new_url|.
virtual bool WillSendRequest(blink::WebFrame* frame,
- PageTransition transition_type,
+ ui::PageTransition transition_type,
const GURL& url,
const GURL& first_party_for_cookies,
GURL* new_url);
@@ -240,7 +257,7 @@ class CONTENT_EXPORT ContentRendererClient {
// Gives the embedder a chance to register the key system(s) it supports by
// populating |key_systems|.
- virtual void AddKeySystems(std::vector<KeySystemInfo>* key_systems);
+ virtual void AddKeySystems(std::vector<media::KeySystemInfo>* key_systems);
// Returns true if we should report a detailed message (including a stack
// trace) for console [logs|errors|exceptions]. |source| is the WebKit-
@@ -258,6 +275,19 @@ class CONTENT_EXPORT ContentRendererClient {
virtual blink::WebWorkerPermissionClientProxy*
CreateWorkerPermissionClientProxy(RenderFrame* render_frame,
blink::WebFrame* frame);
+
+ // Returns true if the page at |url| can use Pepper Compositor APIs.
+ virtual bool IsPluginAllowedToUseCompositorAPI(const GURL& url);
+
+ // Returns true if the page at |url| can use Pepper VideoDecoder APIs.
+ virtual bool IsPluginAllowedToUseVideoDecodeAPI(const GURL& url);
+
+ // Returns true if dev channel APIs are available for plugins.
+ virtual bool IsPluginAllowedToUseDevChannelAPIs();
+
+ // Returns a user agent override specific for |url|, or empty string if
+ // default user agent should be used.
+ virtual std::string GetUserAgentOverrideForURL(const GURL& url);
};
} // namespace content
diff --git a/chromium/content/public/renderer/document_state.h b/chromium/content/public/renderer/document_state.h
index 11b7d5e10bf..d388a8a979e 100644
--- a/chromium/content/public/renderer/document_state.h
+++ b/chromium/content/public/renderer/document_state.h
@@ -161,6 +161,11 @@ class CONTENT_EXPORT DocumentState
was_fetched_via_proxy_ = value;
}
+ net::HostPortPair proxy_server() const { return proxy_server_; }
+ void set_proxy_server(net::HostPortPair proxy_server) {
+ proxy_server_ = proxy_server;
+ }
+
void set_was_prefetcher(bool value) { was_prefetcher_ = value; }
bool was_prefetcher() const { return was_prefetcher_; }
@@ -204,6 +209,7 @@ class CONTENT_EXPORT DocumentState
bool was_alternate_protocol_available_;
net::HttpResponseInfo::ConnectionInfo connection_info_;
bool was_fetched_via_proxy_;
+ net::HostPortPair proxy_server_;
// A prefetcher is a page that contains link rel=prefetch elements.
bool was_prefetcher_;
diff --git a/chromium/content/public/renderer/key_system_info.cc b/chromium/content/public/renderer/key_system_info.cc
deleted file mode 100644
index 6a64fdbac00..00000000000
--- a/chromium/content/public/renderer/key_system_info.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 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 "content/public/renderer/key_system_info.h"
-
-namespace content {
-
-KeySystemInfo::KeySystemInfo(const std::string& key_system)
- : key_system(key_system),
- use_aes_decryptor(false) {
-}
-
-KeySystemInfo::~KeySystemInfo() {
-}
-
-} // namespace content
diff --git a/chromium/content/public/renderer/key_system_info.h b/chromium/content/public/renderer/key_system_info.h
deleted file mode 100644
index 8eb2e573c48..00000000000
--- a/chromium/content/public/renderer/key_system_info.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 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 CONTENT_PUBLIC_RENDERER_KEY_SYSTEM_INFO_H_
-#define CONTENT_PUBLIC_RENDERER_KEY_SYSTEM_INFO_H_
-
-#include <map>
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#include "content/common/content_export.h"
-#include "content/public/common/eme_codec.h"
-
-// Definitions:
-// * Key system
-// https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#key-system
-// * Concrete key system
-// A key system string that can be instantiated, such as
-// via the MediaKeys constructor. Examples include "org.w3.clearkey" and
-// "com.widevine.alpha".
-// * Abstract key system
-// A key system string that cannot be instantiated like a concrete key system
-// but is otherwise useful, such as in discovery using isTypeSupported().
-// * Parent key system
-// A key system string that is one level up from the child key system. It may
-// be an abstract key system.
-// As an example, "com.example" is the parent of "com.example.foo".
-
-namespace content {
-
-// Contains information about an EME key system as well as how to instantiate
-// the corresponding CDM.
-struct CONTENT_EXPORT KeySystemInfo {
- explicit KeySystemInfo(const std::string& key_system);
- ~KeySystemInfo();
-
- std::string key_system;
-
- // Specifies codecs supported by |key_system|.
- SupportedCodecs supported_codecs;
-
- // A hierarchical parent for |key_system|. This value can be used to check
- // supported types but cannot be used to instantiate a MediaKeys object.
- // Only one parent key system is currently supported per concrete key system.
- std::string parent_key_system;
-
- // The following indicate how the corresponding CDM should be instantiated.
- bool use_aes_decryptor;
-#if defined(ENABLE_PEPPER_CDMS)
- std::string pepper_type;
-#endif
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_RENDERER_KEY_SYSTEM_INFO_H_
diff --git a/chromium/content/public/renderer/media_stream_audio_sink.cc b/chromium/content/public/renderer/media_stream_audio_sink.cc
index 9d105d9c36f..5b14f95b4f2 100644
--- a/chromium/content/public/renderer/media_stream_audio_sink.cc
+++ b/chromium/content/public/renderer/media_stream_audio_sink.cc
@@ -18,7 +18,11 @@ void MediaStreamAudioSink::AddToAudioTrack(
DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
// TODO(xians): Support remote audio track.
- DCHECK(native_track->is_local_track());
+ if (!native_track->is_local_track()) {
+ LOG(ERROR) << "Can't add the sink to a remote audio track";
+ return;
+ }
+
WebRtcLocalAudioTrack* audio_track =
static_cast<WebRtcLocalAudioTrack*>(native_track);
audio_track->AddSink(sink);
@@ -29,7 +33,11 @@ void MediaStreamAudioSink::RemoveFromAudioTrack(
const blink::WebMediaStreamTrack& track) {
MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
// TODO(xians): Support remote audio track.
- DCHECK(native_track->is_local_track());
+ if (!native_track->is_local_track()) {
+ LOG(ERROR) << "Can't remove the sink from a remote audio track";
+ return;
+ }
+
WebRtcLocalAudioTrack* audio_track =
static_cast<WebRtcLocalAudioTrack*>(native_track);
audio_track->RemoveSink(sink);
diff --git a/chromium/content/public/renderer/media_stream_audio_sink.h b/chromium/content/public/renderer/media_stream_audio_sink.h
index 312d61dc42f..3bd0ff9cf2e 100644
--- a/chromium/content/public/renderer/media_stream_audio_sink.h
+++ b/chromium/content/public/renderer/media_stream_audio_sink.h
@@ -51,7 +51,7 @@ class CONTENT_EXPORT MediaStreamAudioSink : public MediaStreamSink {
virtual void OnSetFormat(const media::AudioParameters& params) = 0;
protected:
- virtual ~MediaStreamAudioSink() {}
+ ~MediaStreamAudioSink() override {}
};
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_video_sink.h b/chromium/content/public/renderer/media_stream_video_sink.h
index 7aa2a5e8850..37f84d1de8e 100644
--- a/chromium/content/public/renderer/media_stream_video_sink.h
+++ b/chromium/content/public/renderer/media_stream_video_sink.h
@@ -63,7 +63,7 @@ class CONTENT_EXPORT MediaStreamVideoSink : public MediaStreamSink {
const blink::WebMediaStreamTrack& track);
protected:
- virtual ~MediaStreamVideoSink() {}
+ ~MediaStreamVideoSink() override {}
};
diff --git a/chromium/content/public/renderer/navigation_state.cc b/chromium/content/public/renderer/navigation_state.cc
index a1fc18349bd..e5f91fa8186 100644
--- a/chromium/content/public/renderer/navigation_state.cc
+++ b/chromium/content/public/renderer/navigation_state.cc
@@ -6,7 +6,7 @@
namespace content {
-NavigationState::NavigationState(content::PageTransition transition_type,
+NavigationState::NavigationState(ui::PageTransition transition_type,
bool is_content_initiated,
int32 pending_page_id,
int pending_history_list_offset,
diff --git a/chromium/content/public/renderer/navigation_state.h b/chromium/content/public/renderer/navigation_state.h
index 64b85113f72..15eac2663e6 100644
--- a/chromium/content/public/renderer/navigation_state.h
+++ b/chromium/content/public/renderer/navigation_state.h
@@ -8,7 +8,7 @@
#include <string>
#include "content/common/content_export.h"
-#include "content/public/common/page_transition_types.h"
+#include "ui/base/page_transition_types.h"
namespace content {
@@ -23,7 +23,7 @@ class CONTENT_EXPORT NavigationState {
int32 pending_page_id,
int pending_history_list_offset,
bool history_list_was_cleared,
- content::PageTransition transition_type) {
+ ui::PageTransition transition_type) {
return new NavigationState(transition_type,
false,
pending_page_id,
@@ -33,7 +33,7 @@ class CONTENT_EXPORT NavigationState {
static NavigationState* CreateContentInitiated() {
return new NavigationState(
- content::PAGE_TRANSITION_LINK, true, -1, -1, false);
+ ui::PAGE_TRANSITION_LINK, true, -1, -1, false);
}
// Contains the page_id for this navigation or -1 if there is none yet.
@@ -70,8 +70,8 @@ class CONTENT_EXPORT NavigationState {
// Contains the transition type that the browser specified when it
// initiated the load.
- content::PageTransition transition_type() const { return transition_type_; }
- void set_transition_type(content::PageTransition type) {
+ ui::PageTransition transition_type() const { return transition_type_; }
+ void set_transition_type(ui::PageTransition type) {
transition_type_ = type;
}
@@ -116,13 +116,13 @@ class CONTENT_EXPORT NavigationState {
const std::string& extra_headers() { return extra_headers_; }
private:
- NavigationState(content::PageTransition transition_type,
+ NavigationState(ui::PageTransition transition_type,
bool is_content_initiated,
int32 pending_page_id,
int pending_history_list_offset,
bool history_list_was_cleared);
- content::PageTransition transition_type_;
+ ui::PageTransition transition_type_;
bool request_committed_;
bool is_content_initiated_;
int32 pending_page_id_;
diff --git a/chromium/content/public/renderer/platform_event_observer.h b/chromium/content/public/renderer/platform_event_observer.h
new file mode 100644
index 00000000000..6d569227af6
--- /dev/null
+++ b/chromium/content/public/renderer/platform_event_observer.h
@@ -0,0 +1,136 @@
+// Copyright 2014 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 CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
+#define CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
+
+#include "base/logging.h"
+#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread.h"
+
+namespace blink {
+class WebPlatformEventListener;
+}
+
+namespace content {
+
+// This class is used as a base class for PlatformEventObserver<ListenerType> to
+// allow storing PlatformEventObserver<> with different typename in the same
+// place.
+class PlatformEventObserverBase {
+ public:
+ virtual ~PlatformEventObserverBase() { }
+
+ // Methods that need to be exposed in PlatformEventObserverBase. Their purpose
+ // is described in PlatformEventObserver<>.
+
+ virtual void Start(blink::WebPlatformEventListener* listener) = 0;
+ virtual void Stop() = 0;
+
+ // Helper method that allows an sub-class to write its own test helper.
+ // The |data| type MUST be known from the caller.
+ virtual void SendFakeDataForTesting(void* data) { }
+};
+
+// PlatformEventObserver<> defines the basic skeleton for an object requesting
+// the browser process to start/stop listening to some platform/hardware events
+// and observe the result.
+// The results are received via IPC, assuming that the object was correctly
+// registered as an observer via the constructor taking a RenderThread.
+template <typename ListenerType>
+class PlatformEventObserver : public PlatformEventObserverBase,
+ public RenderProcessObserver {
+ public:
+ // Creates a PlatformEventObserver that doesn't listen to responses from the
+ // browser process. Can be used for testing purposes or for observers that
+ // have other means to get their results.
+ PlatformEventObserver()
+ : is_observing_(false),
+ listener_(0) {
+ }
+
+ // Creates a PlatformEventObserver that registers to the RenderThread in order
+ // to intercept the received IPC messages (via OnControlMessageReceived). If
+ // |thread| is null, it will not register.
+ explicit PlatformEventObserver(RenderThread* thread)
+ : is_observing_(false),
+ listener_(0) {
+ if (thread)
+ thread->AddObserver(this);
+ }
+
+ // The observer must automatically stop observing when destroyed in case it
+ // did not stop before. Implementations of PlatformEventObserver must do
+ // so by calling StopIfObserving() from their destructors.
+ virtual ~PlatformEventObserver() {
+ // If this assert fails, the derived destructor failed to invoke
+ // StopIfObserving().
+ DCHECK(!is_observing());
+ }
+
+ // Called when a new IPC message is received. Must be used to listen to the
+ // responses from the browser process if any expected.
+ virtual bool OnControlMessageReceived(const IPC::Message& msg) override {
+ return false;
+ }
+
+ // Start observing. Will request the browser process to start listening to the
+ // events. |listener| will receive any response from the browser process.
+ // Note: should not be called if already observing.
+ virtual void Start(blink::WebPlatformEventListener* listener) {
+ DCHECK(!is_observing());
+ listener_ = static_cast<ListenerType*>(listener);
+ is_observing_ = true;
+
+ SendStartMessage();
+ }
+
+ // Stop observing. Will let the browser know that it doesn't need to observe
+ // anymore.
+ virtual void Stop() {
+ DCHECK(is_observing());
+ listener_ = 0;
+ is_observing_ = false;
+
+ SendStopMessage();
+ }
+
+ protected:
+ // This method is expected to send an IPC to the browser process to let it
+ // know that it should start observing.
+ // It is expected for subclasses to override it.
+ virtual void SendStartMessage() = 0;
+
+ // This method is expected to send an IPC to the browser process to let it
+ // know that it should start observing.
+ // It is expected for subclasses to override it.
+ virtual void SendStopMessage() = 0;
+
+ // Implementations of PlatformEventObserver must call StopIfObserving()
+ // from their destructor to shutdown in an orderly manner.
+ // (As Stop() calls a virtual method, it cannot be handled by
+ // ~PlatformEventObserver.)
+ void StopIfObserving() {
+ if (is_observing())
+ Stop();
+ }
+
+ bool is_observing() const {
+ return is_observing_;
+ }
+
+ ListenerType* listener() {
+ return listener_;
+ }
+
+ private:
+ bool is_observing_;
+ ListenerType* listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformEventObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_PLATFORM_EVENT_OBSERVER_H_
diff --git a/chromium/content/public/renderer/render_font_warmup_win.cc b/chromium/content/public/renderer/render_font_warmup_win.cc
deleted file mode 100644
index a7f67b8fbd6..00000000000
--- a/chromium/content/public/renderer/render_font_warmup_win.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2014 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 "content/public/renderer/render_font_warmup_win.h"
-
-#include <dwrite.h>
-
-#include "base/logging.h"
-#include "base/win/iat_patch_function.h"
-#include "base/win/windows_version.h"
-#include "third_party/WebKit/public/web/win/WebFontRendering.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "third_party/skia/include/ports/SkFontMgr.h"
-#include "third_party/skia/include/ports/SkTypeface_win.h"
-
-namespace content {
-
-namespace {
-
-SkFontMgr* g_warmup_fontmgr = NULL;
-
-base::win::IATPatchFunction g_iat_patch_open_sc_manager;
-base::win::IATPatchFunction g_iat_patch_close_service_handle;
-base::win::IATPatchFunction g_iat_patch_open_service;
-base::win::IATPatchFunction g_iat_patch_start_service;
-base::win::IATPatchFunction g_iat_patch_nt_connect_port;
-
-// These are from ntddk.h
-#if !defined(STATUS_ACCESS_DENIED)
-#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
-#endif
-
-typedef LONG NTSTATUS;
-
-SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name,
- const wchar_t* database_name,
- DWORD access_mask) {
- ::SetLastError(0);
- return reinterpret_cast<SC_HANDLE>(0xdeadbeef);
-}
-
-SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager,
- const wchar_t* service_name,
- DWORD access_mask) {
- ::SetLastError(0);
- return reinterpret_cast<SC_HANDLE>(0xdeadbabe);
-}
-
-BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) {
- if (service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbabe) &&
- service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbeef))
- CHECK(false);
- ::SetLastError(0);
- return TRUE;
-}
-
-BOOL WINAPI StartServiceWPatch(SC_HANDLE service,
- DWORD args,
- const wchar_t** arg_vectors) {
- if (service != reinterpret_cast<SC_HANDLE>(0xdeadbabe))
- CHECK(false);
- ::SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
-}
-
-NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle,
- void* port_name,
- void* object_attribs,
- void* port_attribs,
- DWORD flags,
- void* server_sid,
- void* message,
- DWORD* buffer_length,
- void* out_message_attributes,
- void* in_message_attributes,
- void* time_out) {
- return STATUS_ACCESS_DENIED;
-}
-
-// Directwrite connects to the font cache service to retrieve information about
-// fonts installed on the system etc. This works well outside the sandbox and
-// within the sandbox as long as the lpc connection maintained by the current
-// process with the font cache service remains valid. It appears that there
-// are cases when this connection is dropped after which directwrite is unable
-// to connect to the font cache service which causes problems with characters
-// disappearing.
-// Directwrite has fallback code to enumerate fonts if it is unable to connect
-// to the font cache service. We need to intercept the following APIs to
-// ensure that it does not connect to the font cache service.
-// NtALpcConnectPort
-// OpenSCManagerW
-// OpenServiceW
-// StartServiceW
-// CloseServiceHandle.
-// These are all IAT patched.
-void PatchServiceManagerCalls() {
- static bool is_patched = false;
- if (is_patched)
- return;
- const char* service_provider_dll =
- (base::win::GetVersion() >= base::win::VERSION_WIN8 ?
- "api-ms-win-service-management-l1-1-0.dll" : "advapi32.dll");
-
- is_patched = true;
-
- DWORD patched = g_iat_patch_open_sc_manager.Patch(L"dwrite.dll",
- service_provider_dll, "OpenSCManagerW", OpenSCManagerWPatch);
- DCHECK(patched == 0);
-
- patched = g_iat_patch_close_service_handle.Patch(L"dwrite.dll",
- service_provider_dll, "CloseServiceHandle", CloseServiceHandlePatch);
- DCHECK(patched == 0);
-
- patched = g_iat_patch_open_service.Patch(L"dwrite.dll",
- service_provider_dll, "OpenServiceW", OpenServiceWPatch);
- DCHECK(patched == 0);
-
- patched = g_iat_patch_start_service.Patch(L"dwrite.dll",
- service_provider_dll, "StartServiceW", StartServiceWPatch);
- DCHECK(patched == 0);
-
- patched = g_iat_patch_nt_connect_port.Patch(L"dwrite.dll",
- "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch);
- DCHECK(patched == 0);
-}
-
-
-// Windows-only DirectWrite support. These warm up the DirectWrite paths
-// before sandbox lock down to allow Skia access to the Font Manager service.
-void CreateDirectWriteFactory(IDWriteFactory** factory) {
- typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
- PatchServiceManagerCalls();
-
- DWriteCreateFactoryProc dwrite_create_factory_proc =
- reinterpret_cast<DWriteCreateFactoryProc>(
- GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
- CHECK(dwrite_create_factory_proc);
- CHECK(SUCCEEDED(
- dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_ISOLATED,
- __uuidof(IDWriteFactory),
- reinterpret_cast<IUnknown**>(factory))));
-}
-
-} // namespace
-
-void DoPreSandboxWarmupForTypeface(SkTypeface* typeface) {
- SkPaint paint_warmup;
- paint_warmup.setTypeface(typeface);
- wchar_t glyph = L'S';
- paint_warmup.measureText(&glyph, 2);
-}
-
-SkFontMgr* GetPreSandboxWarmupFontMgr() {
- if (!g_warmup_fontmgr) {
- IDWriteFactory* factory;
- CreateDirectWriteFactory(&factory);
- blink::WebFontRendering::setDirectWriteFactory(factory);
- g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory);
- }
- return g_warmup_fontmgr;
-}
-
-} // namespace content
diff --git a/chromium/content/public/renderer/render_frame.h b/chromium/content/public/renderer/render_frame.h
index c48acd80123..223825daeaf 100644
--- a/chromium/content/public/renderer/render_frame.h
+++ b/chromium/content/public/renderer/render_frame.h
@@ -11,22 +11,33 @@
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
-struct WebPreferences;
-
namespace blink {
class WebFrame;
class WebLocalFrame;
class WebNode;
class WebPlugin;
class WebURLRequest;
+class WebURLResponse;
struct WebPluginParams;
}
+namespace gfx {
+class Range;
+}
+
+namespace v8 {
+template <typename T> class Handle;
+class Context;
+class Isolate;
+}
+
namespace content {
class ContextMenuClient;
class RenderView;
+class ServiceRegistry;
struct ContextMenuParams;
struct WebPluginInfo;
+struct WebPreferences;
// This interface wraps functionality, which is specific to frames, such as
// navigation. It provides communication with a corresponding RenderFrameHost
@@ -44,7 +55,7 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
virtual int GetRoutingID() = 0;
// Returns the associated WebFrame.
- virtual blink::WebFrame* GetWebFrame() = 0;
+ virtual blink::WebLocalFrame* GetWebFrame() = 0;
// Gets WebKit related preferences associated with this frame.
virtual WebPreferences& GetWebkitPreferences() = 0;
@@ -88,8 +99,28 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
// Return true if this frame is hidden.
virtual bool IsHidden() = 0;
+ // Returns the ServiceRegistry for this frame.
+ virtual ServiceRegistry* GetServiceRegistry() = 0;
+
+ // Returns true if this frame is a FTP directory listing.
+ virtual bool IsFTPDirectoryListing() = 0;
+
+ // Attaches the browser plugin identified by |element_instance_id| to guest
+ // content created by the embedder.
+ virtual void AttachGuest(int element_instance_id) = 0;
+
+ // Notifies the browser of text selection changes made.
+ virtual void SetSelectedText(const base::string16& selection_text,
+ size_t offset,
+ const gfx::Range& range) = 0;
+
+ // Ensures that builtin mojo bindings modules are available in |context|.
+ virtual void EnsureMojoBuiltinsAreAvailable(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context) = 0;
+
protected:
- virtual ~RenderFrame() {}
+ ~RenderFrame() override {}
private:
// This interface should only be implemented inside content.
diff --git a/chromium/content/public/renderer/render_frame_observer.h b/chromium/content/public/renderer/render_frame_observer.h
index ac836bb809b..7ad46d7d52c 100644
--- a/chromium/content/public/renderer/render_frame_observer.h
+++ b/chromium/content/public/renderer/render_frame_observer.h
@@ -53,6 +53,11 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
int world_id) {}
virtual void DidClearWindowObject() {}
virtual void DidChangeName(const base::string16& name) {}
+ virtual void DidChangeManifest() {}
+
+ // Called when the frame will soon be closed. This is the last opportunity to
+ // send messages to the host (e.g., for clean-up, shutdown, etc.).
+ virtual void FrameWillClose() {}
// Called when we receive a console message from Blink for which we requested
// extra details (like the stack trace). |message| is the error message,
@@ -70,17 +75,17 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
virtual void DidCommitCompositorFrame() {}
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
RenderFrame* render_frame() const;
int routing_id() const { return routing_id_; }
protected:
explicit RenderFrameObserver(RenderFrame* render_frame);
- virtual ~RenderFrameObserver();
+ ~RenderFrameObserver() override;
private:
friend class RenderFrameImpl;
diff --git a/chromium/content/public/renderer/render_thread.h b/chromium/content/public/renderer/render_thread.h
index a545150f9bb..38006d81d43 100644
--- a/chromium/content/public/renderer/render_thread.h
+++ b/chromium/content/public/renderer/render_thread.h
@@ -39,6 +39,7 @@ namespace content {
class RenderProcessObserver;
class ResourceDispatcherDelegate;
+class ServiceRegistry;
class CONTENT_EXPORT RenderThread : public IPC::Sender {
public:
@@ -47,7 +48,7 @@ class CONTENT_EXPORT RenderThread : public IPC::Sender {
static RenderThread* Get();
RenderThread();
- virtual ~RenderThread();
+ ~RenderThread() override;
virtual base::MessageLoop* GetMessageLoop() = 0;
virtual IPC::SyncChannel* GetChannel() = 0;
@@ -136,6 +137,9 @@ class CONTENT_EXPORT RenderThread : public IPC::Sender {
// Release cached font.
virtual void ReleaseCachedFonts() = 0;
#endif
+
+ // Returns the ServiceRegistry for this thread.
+ virtual ServiceRegistry* GetServiceRegistry() = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/render_view.h b/chromium/content/public/renderer/render_view.h
index c4fce50b7bd..6040a6b4ee2 100644
--- a/chromium/content/public/renderer/render_view.h
+++ b/chromium/content/public/renderer/render_view.h
@@ -15,8 +15,6 @@
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
#include "ui/gfx/native_widget_types.h"
-struct WebPreferences;
-
namespace blink {
class WebElement;
class WebFrame;
@@ -29,6 +27,7 @@ struct WebContextMenuData;
}
namespace gfx {
+class Point;
class Size;
}
@@ -37,6 +36,7 @@ namespace content {
class RenderFrame;
class RenderViewVisitor;
struct SSLStatus;
+struct WebPreferences;
class CONTENT_EXPORT RenderView : public IPC::Sender {
public:
@@ -50,20 +50,16 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// been closed but not yet destroyed are excluded).
static void ForEach(RenderViewVisitor* visitor);
+ // Applies WebKit related preferences to this view.
+ static void ApplyWebPreferences(const WebPreferences& preferences,
+ blink::WebView* web_view);
+
// Returns the main RenderFrame.
virtual RenderFrame* GetMainRenderFrame() = 0;
// Get the routing ID of the view.
virtual int GetRoutingID() const = 0;
- // Page IDs allow the browser to identify pages in each renderer process for
- // keeping back/forward history in sync.
- // Note that this is NOT updated for every main frame navigation, only for
- // "regular" navigations that go into session history. In particular, client
- // redirects, like the page cycler uses (document.location.href="foo") do not
- // count as regular navigations and do not increment the page id.
- virtual int GetPageId() const = 0;
-
// Returns the size of the view.
virtual gfx::Size GetSize() const = 0;
@@ -85,6 +81,10 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// editable div, or has an ARIA role of textbox.
virtual bool IsEditableNode(const blink::WebNode& node) const = 0;
+ // Returns true if a hit test for |point| returns a descendant of |node|.
+ virtual bool NodeContainsPoint(const blink::WebNode& node,
+ const gfx::Point& point) const = 0;
+
// Returns true if we should display scrollbars for the given view size and
// false if the scrollbars should be hidden.
virtual bool ShouldDisplayScrollbars(int width, int height) const = 0;
@@ -128,7 +128,7 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
#endif
protected:
- virtual ~RenderView() {}
+ ~RenderView() override {}
private:
// This interface should only be implemented inside content.
diff --git a/chromium/content/public/renderer/render_view_observer.h b/chromium/content/public/renderer/render_view_observer.h
index 2849bdd45d6..4c7aba0529f 100644
--- a/chromium/content/public/renderer/render_view_observer.h
+++ b/chromium/content/public/renderer/render_view_observer.h
@@ -79,7 +79,6 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
blink::WebDataSource* ds) {}
virtual void PrintPage(blink::WebLocalFrame* frame, bool user_initiated) {}
virtual void FocusedNodeChanged(const blink::WebNode& node) {}
- virtual void ZoomLevelChanged() {};
virtual void DidChangeScrollOffset(blink::WebLocalFrame* frame) {}
virtual void DraggableRegionsChanged(blink::WebFrame* frame) {}
virtual void DidCommitCompositorFrame() {}
@@ -88,26 +87,28 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
// These match the RenderView methods.
virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) {}
virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) {}
+ virtual void DidHandleGestureEvent(const blink::WebGestureEvent& event) {}
// These match incoming IPCs.
virtual void Navigate(const GURL& url) {}
virtual void ClosePage() {}
virtual void OrientationChangeEvent() {}
+ virtual void Resized() {}
virtual void OnStop() {}
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// IPC::Sender implementation.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ bool Send(IPC::Message* message) override;
RenderView* render_view() const;
int routing_id() const { return routing_id_; }
protected:
explicit RenderViewObserver(RenderView* render_view);
- virtual ~RenderViewObserver();
+ ~RenderViewObserver() override;
// Sets |render_view_| to track.
// Removes itself of previous (if any) |render_view_| observer list and adds
diff --git a/chromium/content/public/renderer/renderer_gamepad_provider.h b/chromium/content/public/renderer/renderer_gamepad_provider.h
index ba6ec9fae98..6899948bb2c 100644
--- a/chromium/content/public/renderer/renderer_gamepad_provider.h
+++ b/chromium/content/public/renderer/renderer_gamepad_provider.h
@@ -2,8 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_GAMEPAD_RENDERER_PROVIDER_H_
-#define CONTENT_GAMEPAD_RENDERER_PROVIDER_H_
+#ifndef CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_
+#define CONTENT_PUBLIC_RENDERER_RENDERER_GAMEPAD_PROVIDER_H_
+
+#include "content/public/renderer/platform_event_observer.h"
namespace blink {
class WebGamepadListener;
@@ -13,16 +15,19 @@ class WebGamepads;
namespace content {
// Provides gamepad data and events for blink.
-class RendererGamepadProvider {
+class RendererGamepadProvider
+ : public PlatformEventObserver<blink::WebGamepadListener> {
public:
+ explicit RendererGamepadProvider(RenderThread* thread)
+ : PlatformEventObserver<blink::WebGamepadListener>(thread) { }
+
+ ~RendererGamepadProvider() override {}
+
// Provides latest snapshot of gamepads.
virtual void SampleGamepads(blink::WebGamepads& gamepads) = 0;
- // Registers listener for be notified of events.
- virtual void SetGamepadListener(blink::WebGamepadListener* listener) = 0;
-
protected:
- virtual ~RendererGamepadProvider() {}
+ DISALLOW_COPY_AND_ASSIGN(RendererGamepadProvider);
};
} // namespace content
diff --git a/chromium/content/public/renderer/renderer_ppapi_host.h b/chromium/content/public/renderer/renderer_ppapi_host.h
index 6c843dc30f9..e13c31371ca 100644
--- a/chromium/content/public/renderer/renderer_ppapi_host.h
+++ b/chromium/content/public/renderer/renderer_ppapi_host.h
@@ -8,8 +8,8 @@
#include <vector>
#include "base/callback_forward.h"
+#include "base/files/file.h"
#include "base/memory/ref_counted.h"
-#include "base/platform_file.h"
#include "base/process/process.h"
#include "content/common/content_export.h"
#include "ipc/ipc_platform_file.h"
diff --git a/chromium/content/public/renderer/resource_fetcher.h b/chromium/content/public/renderer/resource_fetcher.h
index 05967f189cc..5c010f99965 100644
--- a/chromium/content/public/renderer/resource_fetcher.h
+++ b/chromium/content/public/renderer/resource_fetcher.h
@@ -27,6 +27,11 @@ namespace content {
// Interface to download resources asynchronously.
class CONTENT_EXPORT ResourceFetcher {
public:
+ enum LoaderType {
+ PLATFORM_LOADER, // uses Platform::createURLLoader
+ FRAME_ASSOCIATED_LOADER, // uses WebFrame::createAssociatedURLLoader
+ };
+
virtual ~ResourceFetcher() {}
// This will be called asynchronously after the URL has been fetched,
@@ -51,12 +56,17 @@ class CONTENT_EXPORT ResourceFetcher {
// Starts the request using the specified frame. Calls |callback| when
// done.
virtual void Start(blink::WebFrame* frame,
- blink::WebURLRequest::TargetType target_type,
+ blink::WebURLRequest::RequestContext request_context,
+ blink::WebURLRequest::FrameType frame_type,
+ LoaderType loader_type,
const Callback& callback) = 0;
// Sets how long to wait for the server to reply. By default, there is no
// timeout. Must be called after a request is started.
virtual void SetTimeout(const base::TimeDelta& timeout) = 0;
+
+ // Manually cancel the request.
+ virtual void Cancel() = 0;
};
} // namespace content
diff --git a/chromium/content/public/renderer/video_encode_accelerator.cc b/chromium/content/public/renderer/video_encode_accelerator.cc
index f256f48b522..a8ad12bc847 100644
--- a/chromium/content/public/renderer/video_encode_accelerator.cc
+++ b/chromium/content/public/renderer/video_encode_accelerator.cc
@@ -25,7 +25,7 @@ void CreateVideoEncodeAccelerator(
scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner =
gpu_factories->GetTaskRunner();
base::PostTaskAndReplyWithResult(
- encode_task_runner,
+ encode_task_runner.get(),
FROM_HERE,
base::Bind(
&media::GpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator,
@@ -35,7 +35,11 @@ void CreateVideoEncodeAccelerator(
std::vector<media::VideoEncodeAccelerator::SupportedProfile>
GetSupportedVideoEncodeAcceleratorProfiles() {
- return GpuVideoEncodeAcceleratorHost::GetSupportedProfiles();
+ scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories =
+ RenderThreadImpl::current()->GetGpuFactories();
+ if (!gpu_factories.get())
+ return std::vector<media::VideoEncodeAccelerator::SupportedProfile>();
+ return gpu_factories->GetVideoEncodeAcceleratorSupportedProfiles();
}
} // namespace content
diff --git a/chromium/content/public/renderer/web_preferences.h b/chromium/content/public/renderer/web_preferences.h
deleted file mode 100644
index a61047338ad..00000000000
--- a/chromium/content/public/renderer/web_preferences.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2013 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 CONTENT_PUBLIC_RENDERER_WEB_PREFERENCES_H_
-#define CONTENT_PUBLIC_RENDERER_WEB_PREFERENCES_H_
-
-#include "content/common/content_export.h"
-
-struct WebPreferences;
-
-namespace blink {
-class WebView;
-}
-
-namespace content {
-
-CONTENT_EXPORT void ApplyWebPreferences(const WebPreferences& prefs,
- blink::WebView* web_view);
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_RENDERER_WEB_PREFERENCES_H_
diff --git a/chromium/content/public/utility/BUILD.gn b/chromium/content/public/utility/BUILD.gn
index f61994b2624..7d40a50f230 100644
--- a/chromium/content/public/utility/BUILD.gn
+++ b/chromium/content/public/utility/BUILD.gn
@@ -2,7 +2,18 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-source_set("utility") {
+# See //content/BUILD.gn for how this works.
+group("utility") {
+ if (is_component_build) {
+ public_deps = [ "//content" ]
+ } else {
+ public_deps = [ ":utility_sources" ]
+ }
+}
+
+source_set("utility_sources") {
+ visibility = [ "//content/*" ]
+
sources = [
"content_utility_client.cc",
"content_utility_client.h",
@@ -15,7 +26,15 @@ source_set("utility") {
deps = [
"//base",
"//content:export",
+ "//content/public/common:common_sources",
+ "//content/utility",
"//ipc",
]
+
+ allow_circular_includes_from = [
+ # This target is a pair with content/browser. They always go together and
+ # include headers from each other.
+ "//content/utility",
+ ]
}
diff --git a/chromium/content/public/utility/content_utility_client.h b/chromium/content/public/utility/content_utility_client.h
index 8f1ec4c7059..5a5d0e54e78 100644
--- a/chromium/content/public/utility/content_utility_client.h
+++ b/chromium/content/public/utility/content_utility_client.h
@@ -12,6 +12,8 @@ namespace content {
// Embedder API for participating in renderer logic.
class CONTENT_EXPORT ContentUtilityClient {
public:
+ virtual ~ContentUtilityClient() {}
+
// Notifies us that the UtilityThread has been created.
virtual void UtilityThreadStarted() {}
diff --git a/chromium/content/public/utility/utility_thread.h b/chromium/content/public/utility/utility_thread.h
index cf2fe973930..6e7cbd108d8 100644
--- a/chromium/content/public/utility/utility_thread.h
+++ b/chromium/content/public/utility/utility_thread.h
@@ -22,7 +22,7 @@ class CONTENT_EXPORT UtilityThread : public IPC::Sender {
static UtilityThread* Get();
UtilityThread();
- virtual ~UtilityThread();
+ ~UtilityThread() override;
// Releases the process if we are not (or no longer) in batch mode.
virtual void ReleaseProcessIfNeeded() = 0;
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn
index 4dde197a9d5..22acf49b724 100644
--- a/chromium/content/renderer/BUILD.gn
+++ b/chromium/content/renderer/BUILD.gn
@@ -5,17 +5,18 @@
import("//build/config/features.gni")
import("//build/config/ui.gni")
import("//content/renderer/renderer.gni")
+import("//media/media_options.gni")
source_set("renderer") {
- # Only targets in the content tree can depend directly on this target.
- visibility = [ "//content/*" ]
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/renderer:renderer_sources" ]
sources = rebase_path(content_renderer_gypi_values.private_renderer_sources,
".", "//content")
configs += [
"//content:content_implementation",
- "//content:libjingle_stub_config",
]
deps = [
@@ -24,32 +25,41 @@ source_set("renderer") {
"//crypto:platform",
"//base/allocator",
+ "//cc",
+ "//cc/blink",
"//content:resources",
"//content/common:mojo_bindings",
+ "//content/public/child:child_sources",
+ "//content/public/common:common_sources",
+ "//content/public/common:mojo_bindings",
+ "//device/battery:mojo_bindings",
"//gin",
+ "//gpu",
+ "//gpu/command_buffer/client:gles2_interface",
+ "//jingle:jingle_glue",
+ "//media",
+ "//media/blink",
+ "//mojo/edk/js",
"//mojo/environment:chromium",
- "//mojo/public/js/bindings",
- "//mojo/public/interfaces/service_provider",
+ "//mojo/public/js",
+ "//mojo/public/interfaces/application",
"//net",
"//skia",
+ "//storage/common",
"//third_party/icu",
+ "//third_party/libjingle",
"//third_party/npapi",
- "//third_party/WebKit/public:blink_headers",
+ "//third_party/WebKit/public:blink",
"//third_party/widevine/cdm:version_h",
"//ui/accessibility",
+ "//ui/base",
+ "//ui/events:events_base",
"//ui/events:dom4_keycode_converter",
+ "//ui/gl",
"//ui/native_theme",
"//ui/surface",
"//v8",
- "//webkit/child",
- "//webkit/common",
- "//webkit/common:storage",
"//webkit/common/gpu",
- # TODO(GYP)
- #'../jingle/jingle.gyp:jingle_glue',
- #'../media/media.gyp:media',
- #'../third_party/WebKit/public/blink.gyp:blink',
- #'../third_party/libjingle/libjingle.gyp:libjingle',
]
if (!enable_notifications) {
@@ -72,10 +82,8 @@ source_set("renderer") {
if (is_android) {
sources -= [
- "accessibility/renderer_accessibility_focus_only.cc",
"media/audio_decoder.cc",
- "media/filter_helpers.cc",
- "media/webmediaplayer_impl.cc",
+ "media/crypto/encrypted_media_player_support_impl.cc",
]
sources += [
"external_popup_menu.cc",
@@ -90,15 +98,16 @@ source_set("renderer") {
deps += [
"//third_party/android_tools:cpu_features",
- # TODO(GYP)
- #"//third_party/libphonenumber",
+ "//third_party/libphonenumber",
]
} else {
sources -= [
- "java/java_bridge_channel.cc",
- "java/java_bridge_channel.h",
- "java/java_bridge_dispatcher.cc",
- "java/java_bridge_dispatcher.h",
+ "java/gin_java_bridge_dispatcher.cc",
+ "java/gin_java_bridge_dispatcher.h",
+ "java/gin_java_bridge_object.cc",
+ "java/gin_java_bridge_object.h",
+ "java/gin_java_bridge_value_converter.cc",
+ "java/gin_java_bridge_value_converter.h",
]
}
@@ -112,12 +121,10 @@ source_set("renderer") {
"media/media_stream_audio_renderer.cc",
"media/media_stream_audio_renderer.h",
"media/media_stream_center.h",
- "media/media_stream_client.h",
"media/media_stream_constraints_util.cc",
"media/media_stream_constraints_util.h",
"media/media_stream_dispatcher.h",
"media/media_stream_dispatcher_eventhandler.h",
- "media/media_stream_impl.h",
"media/media_stream_track.cc",
"media/media_stream_track.h",
]
@@ -129,12 +136,11 @@ source_set("renderer") {
".", "//content")
deps += [
"//crypto",
- # TODO(GYP)
- #"../third_party/libjingle/libjingle.gyp:libjingle_webrtc",
- #"../third_party/libjingle/libjingle.gyp:libpeerconnection",
- #"../third_party/webrtc/modules/modules.gyp:audio_device",
- #"../third_party/webrtc/modules/modules.gyp:audio_processing",
- #"//third_party/libyuv",
+ "//third_party/libyuv",
+ "//third_party/webrtc/modules/audio_device",
+ "//third_party/webrtc/modules/audio_processing",
+ "//third_party/libjingle:libjingle_webrtc",
+ "//third_party/libjingle:libpeerconnection",
]
} else {
sources += [
@@ -148,10 +154,10 @@ source_set("renderer") {
content_renderer_gypi_values.private_renderer_plugin_sources,
".", "//content")
deps += [
- # TODO(GYP)
- #"//ppapi/ppapi_internal.gyp:ppapi_host",
- #"//ppapi/ppapi_internal.gyp:ppapi_proxy",
- #"//ppapi/ppapi_internal.gyp:ppapi_shared",
+ "//ppapi:ppapi_host",
+ "//ppapi:ppapi_proxy",
+ "//ppapi:ppapi_shared",
+ "//third_party/libyuv",
]
} else {
# These files are in the WebRTC list, but also require plugins.
@@ -171,8 +177,24 @@ source_set("renderer") {
if (!enable_pepper_cdms) {
sources -= [
- "renderer/media/crypto/ppapi_decryptor.cc",
- "renderer/media/crypto/ppapi_decryptor.h",
+ "media/crypto/pepper_cdm_wrapper.h",
+ "media/crypto/pepper_cdm_wrapper_impl.cc",
+ "media/crypto/pepper_cdm_wrapper_impl.h",
+ "media/crypto/ppapi_decryptor.cc",
+ "media/crypto/ppapi_decryptor.h",
+ ]
+ }
+
+ if (enable_print_preview) {
+ deps += [ "//printing" ]
+ }
+
+ if (enable_browser_cdms) {
+ sources += [
+ "media/crypto/proxy_media_keys.cc",
+ "media/crypto/proxy_media_keys.h",
+ "media/crypto/renderer_cdm_manager.cc",
+ "media/crypto/renderer_cdm_manager.h",
]
}
}
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS
index 27cce1016a4..3ddb64470fc 100644
--- a/chromium/content/renderer/DEPS
+++ b/chromium/content/renderer/DEPS
@@ -1,15 +1,17 @@
include_rules = [
+ "+cc/blink",
"+content/public/renderer",
"+content/child",
+ "+device/battery", # For battery status service.
"+gin",
"+jingle/glue",
"+media", # For audio input/output and audio/video decoding.
+ "-storage/browser",
"+third_party/hyphen/hyphen.h",
"+third_party/libjingle",
"+third_party/tcmalloc",
"+v8/include",
"+v8/src/third_party/vtune",
- "-webkit/browser",
]
specific_include_rules = {
diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS
index b3105d08b3c..b9a7ad47651 100644
--- a/chromium/content/renderer/OWNERS
+++ b/chromium/content/renderer/OWNERS
@@ -3,3 +3,9 @@ jamesr@chromium.org
# Mac Sandbox profiles.
per-file *.sb=set noparent
per-file *.sb=jeremy@chromium.org
+
+# DirectWrite specific changes
+per-file render_font_warmup_win.cc=scottmg@chromium.org
+per-file renderer_font_platform_win.*=shrikant@chromium.org
+per-file renderer_font_platform_win.*=scottmg@chromium.org
+per-file renderer_font_platform_win.*=cpu@chromium.org
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
index 724b1455ac2..02d73fd5319 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -13,8 +13,13 @@ uint32 AXStateFromBlink(const blink::WebAXObject& o) {
if (o.isChecked())
state |= (1 << ui::AX_STATE_CHECKED);
- if (o.isCollapsed())
- state |= (1 << ui::AX_STATE_COLLAPSED);
+ blink::WebAXExpanded expanded = o.isExpanded();
+ if (expanded) {
+ if (expanded == blink::WebAXExpandedCollapsed)
+ state |= (1 << ui::AX_STATE_COLLAPSED);
+ else if (expanded == blink::WebAXExpandedExpanded)
+ state |= (1 << ui::AX_STATE_EXPANDED);
+ }
if (o.canSetFocusAttribute())
state |= (1 << ui::AX_STATE_FOCUSABLE);
@@ -23,11 +28,8 @@ uint32 AXStateFromBlink(const blink::WebAXObject& o) {
state |= (1 << ui::AX_STATE_FOCUSED);
if (o.role() == blink::WebAXRolePopUpButton ||
- o.ariaHasPopup()) {
+ o.ariaHasPopup())
state |= (1 << ui::AX_STATE_HASPOPUP);
- if (!o.isCollapsed())
- state |= (1 << ui::AX_STATE_EXPANDED);
- }
if (o.isHovered())
state |= (1 << ui::AX_STATE_HOVERED);
@@ -94,6 +96,8 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_ARTICLE;
case blink::WebAXRoleBanner:
return ui::AX_ROLE_BANNER;
+ case blink::WebAXRoleBlockquote:
+ return ui::AX_ROLE_BLOCKQUOTE;
case blink::WebAXRoleBrowser:
return ui::AX_ROLE_BROWSER;
case blink::WebAXRoleBusyIndicator:
@@ -118,12 +122,20 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_COMPLEMENTARY;
case blink::WebAXRoleContentInfo:
return ui::AX_ROLE_CONTENT_INFO;
+ case blink::WebAXRoleDate:
+ return ui::AX_ROLE_DATE;
+ case blink::WebAXRoleDateTime:
+ return ui::AX_ROLE_DATE_TIME;
case blink::WebAXRoleDefinition:
return ui::AX_ROLE_DEFINITION;
case blink::WebAXRoleDescriptionListDetail:
return ui::AX_ROLE_DESCRIPTION_LIST_DETAIL;
+ case blink::WebAXRoleDescriptionList:
+ return ui::AX_ROLE_DESCRIPTION_LIST;
case blink::WebAXRoleDescriptionListTerm:
return ui::AX_ROLE_DESCRIPTION_LIST_TERM;
+ case blink::WebAXRoleDetails:
+ return ui::AX_ROLE_DETAILS;
case blink::WebAXRoleDialog:
return ui::AX_ROLE_DIALOG;
case blink::WebAXRoleDirectory:
@@ -140,6 +152,10 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_EDITABLE_TEXT;
case blink::WebAXRoleEmbeddedObject:
return ui::AX_ROLE_EMBEDDED_OBJECT;
+ case blink::WebAXRoleFigcaption:
+ return ui::AX_ROLE_FIGCAPTION;
+ case blink::WebAXRoleFigure:
+ return ui::AX_ROLE_FIGURE;
case blink::WebAXRoleFooter:
return ui::AX_ROLE_FOOTER;
case blink::WebAXRoleForm:
@@ -194,8 +210,6 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_MARQUEE;
case blink::WebAXRoleMath:
return ui::AX_ROLE_MATH;
- case blink::WebAXRoleMathElement:
- return ui::AX_ROLE_MATH_ELEMENT;
case blink::WebAXRoleMatte:
return ui::AX_ROLE_MATTE;
case blink::WebAXRoleMenu:
@@ -206,12 +220,20 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_MENU_BUTTON;
case blink::WebAXRoleMenuItem:
return ui::AX_ROLE_MENU_ITEM;
+ case blink::WebAXRoleMenuItemCheckBox:
+ return ui::AX_ROLE_MENU_ITEM_CHECK_BOX;
+ case blink::WebAXRoleMenuItemRadio:
+ return ui::AX_ROLE_MENU_ITEM_RADIO;
case blink::WebAXRoleMenuListOption:
return ui::AX_ROLE_MENU_LIST_OPTION;
case blink::WebAXRoleMenuListPopup:
return ui::AX_ROLE_MENU_LIST_POPUP;
+ case blink::WebAXRoleMeter:
+ return ui::AX_ROLE_METER;
case blink::WebAXRoleNavigation:
return ui::AX_ROLE_NAVIGATION;
+ case blink::WebAXRoleNone:
+ return ui::AX_ROLE_NONE;
case blink::WebAXRoleNote:
return ui::AX_ROLE_NOTE;
case blink::WebAXRoleOutline:
@@ -220,6 +242,8 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_PARAGRAPH;
case blink::WebAXRolePopUpButton:
return ui::AX_ROLE_POP_UP_BUTTON;
+ case blink::WebAXRolePre:
+ return ui::AX_ROLE_PRE;
case blink::WebAXRolePresentational:
return ui::AX_ROLE_PRESENTATIONAL;
case blink::WebAXRoleProgressIndicator:
@@ -286,6 +310,8 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
return ui::AX_ROLE_TEXT_AREA;
case blink::WebAXRoleTextField:
return ui::AX_ROLE_TEXT_FIELD;
+ case blink::WebAXRoleTime:
+ return ui::AX_ROLE_TIME;
case blink::WebAXRoleTimer:
return ui::AX_ROLE_TIMER;
case blink::WebAXRoleToggleButton:
@@ -311,7 +337,9 @@ ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
default:
// We can't add an assertion here, that prevents us
// from adding new role enums in Blink.
- return static_cast<ui::AXRole>(-1);
+ LOG(WARNING) << "Warning: Blink WebAXRole " << role
+ << " not handled by Chromium yet.";
+ return ui::AX_ROLE_UNKNOWN;
}
}
@@ -325,16 +353,12 @@ ui::AXEvent AXEventFromBlink(blink::WebAXEvent event) {
return ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED;
case blink::WebAXEventAutocorrectionOccured:
return ui::AX_EVENT_AUTOCORRECTION_OCCURED;
- case blink::WebAXEventBlur:
- return ui::AX_EVENT_BLUR;
case blink::WebAXEventCheckedStateChanged:
return ui::AX_EVENT_CHECKED_STATE_CHANGED;
case blink::WebAXEventChildrenChanged:
return ui::AX_EVENT_CHILDREN_CHANGED;
case blink::WebAXEventFocus:
return ui::AX_EVENT_FOCUS;
- case blink::WebAXEventHide:
- return ui::AX_EVENT_HIDE;
case blink::WebAXEventInvalidStatusChanged:
return ui::AX_EVENT_INVALID_STATUS_CHANGED;
case blink::WebAXEventLayoutComplete:
@@ -362,15 +386,9 @@ ui::AXEvent AXEventFromBlink(blink::WebAXEvent event) {
case blink::WebAXEventSelectedChildrenChanged:
return ui::AX_EVENT_SELECTED_CHILDREN_CHANGED;
case blink::WebAXEventSelectedTextChanged:
- return ui::AX_EVENT_SELECTED_TEXT_CHANGED;
- case blink::WebAXEventShow:
- return ui::AX_EVENT_SHOW;
+ return ui::AX_EVENT_TEXT_SELECTION_CHANGED;
case blink::WebAXEventTextChanged:
return ui::AX_EVENT_TEXT_CHANGED;
- case blink::WebAXEventTextInserted:
- return ui::AX_EVENT_TEXT_INSERTED;
- case blink::WebAXEventTextRemoved:
- return ui::AX_EVENT_TEXT_REMOVED;
case blink::WebAXEventValueChanged:
return ui::AX_EVENT_VALUE_CHANGED;
default:
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
index 4b675a37df1..22c66acbdaa 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -10,6 +10,9 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
+#include "content/renderer/browser_plugin/browser_plugin.h"
+#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -21,9 +24,11 @@
#include "third_party/WebKit/public/web/WebDocumentType.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFormControlElement.h"
-#include "third_party/WebKit/public/web/WebInputElement.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebNode.h"
+#include "third_party/WebKit/public/web/WebPlugin.h"
+#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebView.h"
using base::ASCIIToUTF16;
@@ -34,6 +39,8 @@ using blink::WebDocumentType;
using blink::WebElement;
using blink::WebLocalFrame;
using blink::WebNode;
+using blink::WebPlugin;
+using blink::WebPluginContainer;
using blink::WebVector;
using blink::WebView;
@@ -53,27 +60,32 @@ bool IsParentUnignoredOf(WebAXObject ancestor,
return parent.equals(ancestor);
}
-bool IsTrue(std::string html_value) {
- return LowerCaseEqualsASCII(html_value, "true");
-}
-
std::string GetEquivalentAriaRoleString(const ui::AXRole role) {
switch (role) {
case ui::AX_ROLE_ARTICLE:
return "article";
case ui::AX_ROLE_BANNER:
return "banner";
+ case ui::AX_ROLE_BUTTON:
+ return "button";
case ui::AX_ROLE_COMPLEMENTARY:
return "complementary";
- case ui::AX_ROLE_CONTENT_INFO:
case ui::AX_ROLE_FOOTER:
return "contentinfo";
+ case ui::AX_ROLE_HORIZONTAL_RULE:
+ return "separator";
+ case ui::AX_ROLE_IMAGE:
+ return "img";
case ui::AX_ROLE_MAIN:
return "main";
case ui::AX_ROLE_NAVIGATION:
return "navigation";
+ case ui::AX_ROLE_RADIO_BUTTON:
+ return "radio";
case ui::AX_ROLE_REGION:
return "region";
+ case ui::AX_ROLE_SLIDER:
+ return "slider";
default:
break;
}
@@ -93,8 +105,11 @@ void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
} // Anonymous namespace
-BlinkAXTreeSource::BlinkAXTreeSource(RenderViewImpl* render_view)
- : render_view_(render_view) {
+BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame)
+ : render_frame_(render_frame),
+ node_to_frame_routing_id_map_(NULL),
+ node_to_browser_plugin_instance_id_map_(NULL),
+ accessibility_focus_id_(-1) {
}
BlinkAXTreeSource::~BlinkAXTreeSource() {
@@ -110,6 +125,14 @@ bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const {
return false;
}
+void BlinkAXTreeSource::CollectChildFrameIdMapping(
+ std::map<int32, int>* node_to_frame_routing_id_map,
+ std::map<int32, int>* node_to_browser_plugin_instance_id_map) {
+ node_to_frame_routing_id_map_ = node_to_frame_routing_id_map;
+ node_to_browser_plugin_instance_id_map_ =
+ node_to_browser_plugin_instance_id_map;
+}
+
blink::WebAXObject BlinkAXTreeSource::GetRoot() const {
return GetMainDocument().accessibilityObject();
}
@@ -125,6 +148,17 @@ int32 BlinkAXTreeSource::GetId(blink::WebAXObject node) const {
void BlinkAXTreeSource::GetChildren(
blink::WebAXObject parent,
std::vector<blink::WebAXObject>* out_children) const {
+ if (parent.role() == blink::WebAXRoleStaticText) {
+ blink::WebAXObject ancestor = parent;
+ while (!ancestor.isDetached()) {
+ if (ancestor.axID() == accessibility_focus_id_) {
+ parent.loadInlineTextBoxes();
+ break;
+ }
+ ancestor = ancestor.parentObject();
+ }
+ }
+
bool is_iframe = false;
WebNode node = parent.node();
if (!node.isNull() && node.isElementNode()) {
@@ -285,26 +319,19 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
WebNode node = src.node();
bool is_iframe = false;
- std::string live_atomic;
- std::string live_busy;
- std::string live_status;
- std::string live_relevant;
if (!node.isNull() && node.isElementNode()) {
WebElement element = node.to<WebElement>();
is_iframe = (element.tagName() == ASCIIToUTF16("IFRAME"));
- if (LowerCaseEqualsASCII(element.getAttribute("aria-expanded"), "true"))
- dst->state |= (1 << ui::AX_STATE_EXPANDED);
-
// TODO(ctguil): The tagName in WebKit is lower cased but
// HTMLElement::nodeName calls localNameUpper. Consider adding
// a WebElement method that returns the original lower cased tagName.
dst->AddStringAttribute(
ui::AX_ATTR_HTML_TAG,
- StringToLowerASCII(UTF16ToUTF8(element.tagName())));
+ base::StringToLowerASCII(UTF16ToUTF8(element.tagName())));
for (unsigned i = 0; i < element.attributeCount(); ++i) {
- std::string name = StringToLowerASCII(UTF16ToUTF8(
+ std::string name = base::StringToLowerASCII(UTF16ToUTF8(
element.attributeLocalName(i)));
std::string value = UTF16ToUTF8(element.attributeValue(i));
dst->html_attributes.push_back(std::make_pair(name, value));
@@ -325,6 +352,12 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
line_breaks.push_back(src_line_breaks[i]);
dst->AddIntListAttribute(ui::AX_ATTR_LINE_BREAKS, line_breaks);
}
+
+ if (dst->role == ui::AX_ROLE_TEXT_FIELD &&
+ src.textInputType().length()) {
+ dst->AddStringAttribute(ui::AX_ATTR_TEXT_INPUT_TYPE,
+ UTF16ToUTF8(src.textInputType()));
+ }
}
// ARIA role.
@@ -337,71 +370,32 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
dst->AddStringAttribute(ui::AX_ATTR_ROLE, role);
}
- // Live region attributes
- live_atomic = UTF16ToUTF8(element.getAttribute("aria-atomic"));
- live_busy = UTF16ToUTF8(element.getAttribute("aria-busy"));
- live_status = UTF16ToUTF8(element.getAttribute("aria-live"));
- live_relevant = UTF16ToUTF8(element.getAttribute("aria-relevant"));
- }
-
- // Walk up the parent chain to set live region attributes of containers
- std::string container_live_atomic;
- std::string container_live_busy;
- std::string container_live_status;
- std::string container_live_relevant;
- WebAXObject container_accessible = src;
- while (!container_accessible.isDetached()) {
- WebNode container_node = container_accessible.node();
- if (!container_node.isNull() && container_node.isElementNode()) {
- WebElement container_elem = container_node.to<WebElement>();
- if (container_elem.hasAttribute("aria-atomic") &&
- container_live_atomic.empty()) {
- container_live_atomic =
- UTF16ToUTF8(container_elem.getAttribute("aria-atomic"));
- }
- if (container_elem.hasAttribute("aria-busy") &&
- container_live_busy.empty()) {
- container_live_busy =
- UTF16ToUTF8(container_elem.getAttribute("aria-busy"));
- }
- if (container_elem.hasAttribute("aria-live") &&
- container_live_status.empty()) {
- container_live_status =
- UTF16ToUTF8(container_elem.getAttribute("aria-live"));
- }
- if (container_elem.hasAttribute("aria-relevant") &&
- container_live_relevant.empty()) {
- container_live_relevant =
- UTF16ToUTF8(container_elem.getAttribute("aria-relevant"));
+ // Browser plugin (used in a <webview>).
+ if (node_to_browser_plugin_instance_id_map_) {
+ BrowserPlugin* browser_plugin = BrowserPlugin::GetFromNode(element);
+ if (browser_plugin) {
+ (*node_to_browser_plugin_instance_id_map_)[dst->id] =
+ browser_plugin->browser_plugin_instance_id();
+ dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
}
}
- container_accessible = container_accessible.parentObject();
}
- if (!live_atomic.empty())
- dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, IsTrue(live_atomic));
- if (!live_busy.empty())
- dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, IsTrue(live_busy));
- if (!live_status.empty())
- dst->AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, live_status);
- if (!live_relevant.empty())
- dst->AddStringAttribute(ui::AX_ATTR_LIVE_RELEVANT, live_relevant);
-
- if (!container_live_atomic.empty()) {
+ if (src.isInLiveRegion()) {
+ dst->AddBoolAttribute(ui::AX_ATTR_LIVE_ATOMIC, src.liveRegionAtomic());
+ dst->AddBoolAttribute(ui::AX_ATTR_LIVE_BUSY, src.liveRegionBusy());
+ dst->AddStringAttribute(ui::AX_ATTR_LIVE_STATUS,
+ UTF16ToUTF8(src.liveRegionStatus()));
+ dst->AddStringAttribute(ui::AX_ATTR_LIVE_RELEVANT,
+ UTF16ToUTF8(src.liveRegionRelevant()));
dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_ATOMIC,
- IsTrue(container_live_atomic));
- }
- if (!container_live_busy.empty()) {
+ src.containerLiveRegionAtomic());
dst->AddBoolAttribute(ui::AX_ATTR_CONTAINER_LIVE_BUSY,
- IsTrue(container_live_busy));
- }
- if (!container_live_status.empty()) {
+ src.containerLiveRegionBusy());
dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS,
- container_live_status);
- }
- if (!container_live_relevant.empty()) {
+ UTF16ToUTF8(src.containerLiveRegionStatus()));
dst->AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_RELEVANT,
- container_live_relevant);
+ UTF16ToUTF8(src.containerLiveRegionRelevant()));
}
if (dst->role == ui::AX_ROLE_PROGRESS_INDICATOR ||
@@ -437,17 +431,35 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
UTF16ToUTF8(doctype.name()));
}
- const gfx::Size& scroll_offset = document.frame()->scrollOffset();
+ const gfx::Size& scroll_offset = document.scrollOffset();
dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X, scroll_offset.width());
dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y, scroll_offset.height());
- const gfx::Size& min_offset = document.frame()->minimumScrollOffset();
+ const gfx::Size& min_offset = document.minimumScrollOffset();
dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MIN, min_offset.width());
dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN, min_offset.height());
- const gfx::Size& max_offset = document.frame()->maximumScrollOffset();
+ const gfx::Size& max_offset = document.maximumScrollOffset();
dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, max_offset.width());
dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX, max_offset.height());
+
+ if (node_to_frame_routing_id_map_ && !src.equals(GetRoot())) {
+ WebLocalFrame* frame = document.frame();
+ RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame);
+ if (render_frame) {
+ (*node_to_frame_routing_id_map_)[dst->id] =
+ render_frame->GetRoutingID();
+ dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
+ } else {
+ RenderFrameProxy* render_frame_proxy =
+ RenderFrameProxy::FromWebFrame(frame);
+ if (render_frame_proxy) {
+ (*node_to_frame_routing_id_map_)[dst->id] =
+ render_frame_proxy->routing_id();
+ dst->AddBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST, true);
+ }
+ }
+ }
}
if (dst->role == ui::AX_ROLE_TABLE) {
@@ -550,13 +562,8 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
}
blink::WebDocument BlinkAXTreeSource::GetMainDocument() const {
- WebView* view = render_view_->GetWebView();
- WebLocalFrame* main_frame =
- view ? view->mainFrame()->toWebLocalFrame() : NULL;
-
- if (main_frame)
- return main_frame->document();
-
+ if (render_frame_ && render_frame_->GetWebFrame())
+ return render_frame_->GetWebFrame()->document();
return WebDocument();
}
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.h b/chromium/content/renderer/accessibility/blink_ax_tree_source.h
index 52b908250b0..b08108b12e5 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.h
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.h
@@ -11,37 +11,52 @@
namespace content {
-class RenderViewImpl;
+class RenderFrameImpl;
class BlinkAXTreeSource
: public ui::AXTreeSource<blink::WebAXObject> {
public:
- BlinkAXTreeSource(RenderViewImpl* render_view);
- virtual ~BlinkAXTreeSource();
+ BlinkAXTreeSource(RenderFrameImpl* render_frame);
+ ~BlinkAXTreeSource() override;
+
+ // Call this to have BlinkAXTreeSource collect a mapping from
+ // node ids to the frame routing id for an out-of-process iframe during
+ // calls to SerializeNode.
+ void CollectChildFrameIdMapping(
+ std::map<int32, int>* node_to_frame_routing_id_map,
+ std::map<int32, int>* node_to_browser_plugin_instance_id_map);
// Walks up the ancestor chain to see if this is a descendant of the root.
bool IsInTree(blink::WebAXObject node) const;
+ // Set the id of the node with accessibility focus. The node with
+ // accessibility focus will force loading inline text box children,
+ // which aren't always loaded by default on all platforms.
+ int accessibility_focus_id() { return accessibility_focus_id_; }
+ void set_accessiblity_focus_id(int id) { accessibility_focus_id_ = id; }
+
// AXTreeSource implementation.
- virtual blink::WebAXObject GetRoot() const OVERRIDE;
- virtual blink::WebAXObject GetFromId(int32 id) const OVERRIDE;
- virtual int32 GetId(blink::WebAXObject node) const OVERRIDE;
- virtual void GetChildren(
+ blink::WebAXObject GetRoot() const override;
+ blink::WebAXObject GetFromId(int32 id) const override;
+ int32 GetId(blink::WebAXObject node) const override;
+ void GetChildren(
blink::WebAXObject node,
- std::vector<blink::WebAXObject>* out_children) const OVERRIDE;
- virtual blink::WebAXObject GetParent(blink::WebAXObject node) const
- OVERRIDE;
- virtual void SerializeNode(blink::WebAXObject node,
- ui::AXNodeData* out_data) const OVERRIDE;
- virtual bool IsValid(blink::WebAXObject node) const OVERRIDE;
- virtual bool IsEqual(blink::WebAXObject node1,
- blink::WebAXObject node2) const OVERRIDE;
- virtual blink::WebAXObject GetNull() const OVERRIDE;
+ std::vector<blink::WebAXObject>* out_children) const override;
+ blink::WebAXObject GetParent(blink::WebAXObject node) const override;
+ void SerializeNode(blink::WebAXObject node,
+ ui::AXNodeData* out_data) const override;
+ bool IsValid(blink::WebAXObject node) const override;
+ bool IsEqual(blink::WebAXObject node1,
+ blink::WebAXObject node2) const override;
+ blink::WebAXObject GetNull() const override;
blink::WebDocument GetMainDocument() const;
private:
- RenderViewImpl* render_view_;
+ RenderFrameImpl* render_frame_;
+ std::map<int32, int>* node_to_frame_routing_id_map_;
+ std::map<int32, int>* node_to_browser_plugin_instance_id_map_;
+ int accessibility_focus_id_;
};
} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.cc b/chromium/content/renderer/accessibility/renderer_accessibility.cc
index 9a575a14761..ac83a767997 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility.cc
@@ -4,34 +4,491 @@
#include "content/renderer/accessibility/renderer_accessibility.h"
+#include <queue>
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebInputElement.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebSettings.h"
#include "third_party/WebKit/public/web/WebView.h"
+using blink::WebAXObject;
using blink::WebDocument;
-using blink::WebFrame;
+using blink::WebLocalFrame;
+using blink::WebNode;
+using blink::WebPoint;
+using blink::WebRect;
+using blink::WebSettings;
using blink::WebView;
namespace content {
-RendererAccessibility::RendererAccessibility(
- RenderViewImpl* render_view)
- : RenderViewObserver(render_view),
- render_view_(render_view) {
+RendererAccessibility::RendererAccessibility(RenderFrameImpl* render_frame)
+ : RenderFrameObserver(render_frame),
+ render_frame_(render_frame),
+ tree_source_(render_frame),
+ serializer_(&tree_source_),
+ last_scroll_offset_(gfx::Size()),
+ ack_pending_(false),
+ reset_token_(0),
+ weak_factory_(this) {
+ WebView* web_view = render_frame_->GetRenderView()->GetWebView();
+ WebSettings* settings = web_view->settings();
+ settings->setAccessibilityEnabled(true);
+
+#if defined(OS_ANDROID)
+ // Password values are only passed through on Android.
+ settings->setAccessibilityPasswordValuesEnabled(true);
+#endif
+
+#if !defined(OS_ANDROID)
+ // Inline text boxes are enabled for all nodes on all except Android.
+ settings->setInlineTextBoxAccessibilityEnabled(true);
+#endif
+
+ const WebDocument& document = GetMainDocument();
+ if (!document.isNull()) {
+ // It's possible that the webview has already loaded a webpage without
+ // accessibility being enabled. Initialize the browser's cached
+ // accessibility tree by sending it a notification.
+ HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE);
+ }
}
RendererAccessibility::~RendererAccessibility() {
}
-WebDocument RendererAccessibility::GetMainDocument() {
- WebView* view = render_view()->GetWebView();
- WebFrame* main_frame = view ? view->mainFrame() : NULL;
+bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, OnDoDefaultAction)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_Events_ACK, OnEventsAck)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible,
+ OnScrollToMakeVisible)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint, OnScrollToPoint)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection, OnSetTextSelection)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_SetValue, OnSetValue)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_HitTest, OnHitTest)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_SetAccessibilityFocus,
+ OnSetAccessibilityFocus)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_Reset, OnReset)
+ IPC_MESSAGE_HANDLER(AccessibilityMsg_FatalError, OnFatalError)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void RendererAccessibility::HandleWebAccessibilityEvent(
+ const blink::WebAXObject& obj, blink::WebAXEvent event) {
+ HandleAXEvent(obj, AXEventFromBlink(event));
+}
+
+void RendererAccessibility::HandleAccessibilityFindInPageResult(
+ int identifier,
+ int match_index,
+ const blink::WebAXObject& start_object,
+ int start_offset,
+ const blink::WebAXObject& end_object,
+ int end_offset) {
+ AccessibilityHostMsg_FindInPageResultParams params;
+ params.request_id = identifier;
+ params.match_index = match_index;
+ params.start_id = start_object.axID();
+ params.start_offset = start_offset;
+ params.end_id = end_object.axID();
+ params.end_offset = end_offset;
+ Send(new AccessibilityHostMsg_FindInPageResult(routing_id(), params));
+}
+
+void RendererAccessibility::FocusedNodeChanged(const WebNode& node) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ if (node.isNull()) {
+ // When focus is cleared, implicitly focus the document.
+ // TODO(dmazzoni): Make Blink send this notification instead.
+ HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_BLUR);
+ }
+}
+
+void RendererAccessibility::DisableAccessibility() {
+ RenderView* render_view = render_frame_->GetRenderView();
+ if (!render_view)
+ return;
+
+ WebView* web_view = render_view->GetWebView();
+ if (!web_view)
+ return;
+
+ WebSettings* settings = web_view->settings();
+ if (!settings)
+ return;
+
+ settings->setAccessibilityEnabled(false);
+}
- if (main_frame)
- return main_frame->document();
+void RendererAccessibility::HandleAXEvent(
+ const blink::WebAXObject& obj, ui::AXEvent event) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+ gfx::Size scroll_offset = document.frame()->scrollOffset();
+ if (scroll_offset != last_scroll_offset_) {
+ // Make sure the browser is always aware of the scroll position of
+ // the root document element by posting a generic notification that
+ // will update it.
+ // TODO(dmazzoni): remove this as soon as
+ // https://bugs.webkit.org/show_bug.cgi?id=73460 is fixed.
+ last_scroll_offset_ = scroll_offset;
+ if (!obj.equals(document.accessibilityObject())) {
+ HandleAXEvent(document.accessibilityObject(),
+ ui::AX_EVENT_LAYOUT_COMPLETE);
+ }
+ }
+
+ // Add the accessibility object to our cache and ensure it's valid.
+ AccessibilityHostMsg_EventParams acc_event;
+ acc_event.id = obj.axID();
+ acc_event.event_type = event;
+
+ // Discard duplicate accessibility events.
+ for (uint32 i = 0; i < pending_events_.size(); ++i) {
+ if (pending_events_[i].id == acc_event.id &&
+ pending_events_[i].event_type == acc_event.event_type) {
+ return;
+ }
+ }
+ pending_events_.push_back(acc_event);
+
+ if (!ack_pending_ && !weak_factory_.HasWeakPtrs()) {
+ // When no accessibility events are in-flight post a task to send
+ // the events to the browser. We use PostTask so that we can queue
+ // up additional events.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&RendererAccessibility::SendPendingAccessibilityEvents,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+WebDocument RendererAccessibility::GetMainDocument() {
+ if (render_frame_ && render_frame_->GetWebFrame())
+ return render_frame_->GetWebFrame()->document();
return WebDocument();
}
+void RendererAccessibility::SendPendingAccessibilityEvents() {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ if (pending_events_.empty())
+ return;
+
+ if (render_frame_->is_swapped_out())
+ return;
+
+ ack_pending_ = true;
+
+ // Make a copy of the events, because it's possible that
+ // actions inside this loop will cause more events to be
+ // queued up.
+ std::vector<AccessibilityHostMsg_EventParams> src_events = pending_events_;
+ pending_events_.clear();
+
+ // Generate an event message from each Blink event.
+ std::vector<AccessibilityHostMsg_EventParams> event_msgs;
+
+ // If there's a layout complete message, we need to send location changes.
+ bool had_layout_complete_messages = false;
+
+ // Loop over each event and generate an updated event message.
+ for (size_t i = 0; i < src_events.size(); ++i) {
+ AccessibilityHostMsg_EventParams& event = src_events[i];
+ if (event.event_type == ui::AX_EVENT_LAYOUT_COMPLETE)
+ had_layout_complete_messages = true;
+
+ WebAXObject obj = document.accessibilityObjectFromID(event.id);
+
+ // Make sure the object still exists.
+ if (!obj.updateLayoutAndCheckValidity())
+ continue;
+
+ // If it's ignored, find the first ancestor that's not ignored.
+ while (!obj.isDetached() && obj.accessibilityIsIgnored())
+ obj = obj.parentObject();
+
+ // Make sure it's a descendant of our root node - exceptions include the
+ // scroll area that's the parent of the main document (we ignore it), and
+ // possibly nodes attached to a different document.
+ if (!tree_source_.IsInTree(obj))
+ continue;
+
+ // When we get a "selected children changed" event, Blink
+ // doesn't also send us events for each child that changed
+ // selection state, so make sure we re-send that whole subtree.
+ if (event.event_type == ui::AX_EVENT_SELECTED_CHILDREN_CHANGED) {
+ serializer_.DeleteClientSubtree(obj);
+ }
+
+ AccessibilityHostMsg_EventParams event_msg;
+ tree_source_.CollectChildFrameIdMapping(
+ &event_msg.node_to_frame_routing_id_map,
+ &event_msg.node_to_browser_plugin_instance_id_map);
+ event_msg.event_type = event.event_type;
+ event_msg.id = event.id;
+ serializer_.SerializeChanges(obj, &event_msg.update);
+ event_msgs.push_back(event_msg);
+
+ // For each node in the update, set the location in our map from
+ // ids to locations.
+ for (size_t i = 0; i < event_msg.update.nodes.size(); ++i) {
+ locations_[event_msg.update.nodes[i].id] =
+ event_msg.update.nodes[i].location;
+ }
+
+ VLOG(0) << "Accessibility event: " << ui::ToString(event.event_type)
+ << " on node id " << event_msg.id
+ << "\n" << event_msg.update.ToString();
+ }
+
+ Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs, reset_token_));
+ reset_token_ = 0;
+
+ if (had_layout_complete_messages)
+ SendLocationChanges();
+}
+
+void RendererAccessibility::SendLocationChanges() {
+ std::vector<AccessibilityHostMsg_LocationChangeParams> messages;
+
+ // Do a breadth-first explore of the whole blink AX tree.
+ base::hash_map<int, gfx::Rect> new_locations;
+ std::queue<WebAXObject> objs_to_explore;
+ objs_to_explore.push(tree_source_.GetRoot());
+ while (objs_to_explore.size()) {
+ WebAXObject obj = objs_to_explore.front();
+ objs_to_explore.pop();
+
+ // See if we had a previous location. If not, this whole subtree must
+ // be new, so don't continue to explore this branch.
+ int id = obj.axID();
+ base::hash_map<int, gfx::Rect>::iterator iter = locations_.find(id);
+ if (iter == locations_.end())
+ continue;
+
+ // If the location has changed, append it to the IPC message.
+ gfx::Rect new_location = obj.boundingBoxRect();
+ if (iter != locations_.end() && iter->second != new_location) {
+ AccessibilityHostMsg_LocationChangeParams message;
+ message.id = id;
+ message.new_location = new_location;
+ messages.push_back(message);
+ }
+
+ // Save the new location.
+ new_locations[id] = new_location;
+
+ // Explore children of this object.
+ std::vector<blink::WebAXObject> children;
+ tree_source_.GetChildren(obj, &children);
+ for (size_t i = 0; i < children.size(); ++i)
+ objs_to_explore.push(children[i]);
+ }
+ locations_.swap(new_locations);
+
+ Send(new AccessibilityHostMsg_LocationChanges(routing_id(), messages));
+}
+
+void RendererAccessibility::OnDoDefaultAction(int acc_obj_id) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+ if (obj.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "DoDefaultAction on invalid object id " << acc_obj_id;
+#endif
+ return;
+ }
+
+ obj.performDefaultAction();
+}
+
+void RendererAccessibility::OnEventsAck() {
+ DCHECK(ack_pending_);
+ ack_pending_ = false;
+ SendPendingAccessibilityEvents();
+}
+
+void RendererAccessibility::OnFatalError() {
+ CHECK(false) << "Invalid accessibility tree.";
+}
+
+void RendererAccessibility::OnHitTest(gfx::Point point) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+ WebAXObject root_obj = document.accessibilityObject();
+ if (!root_obj.updateLayoutAndCheckValidity())
+ return;
+
+ WebAXObject obj = root_obj.hitTest(point);
+ if (!obj.isDetached())
+ HandleAXEvent(obj, ui::AX_EVENT_HOVER);
+}
+
+void RendererAccessibility::OnSetAccessibilityFocus(int acc_obj_id) {
+ if (tree_source_.accessibility_focus_id() == acc_obj_id)
+ return;
+
+ tree_source_.set_accessiblity_focus_id(acc_obj_id);
+
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+
+ // This object may not be a leaf node. Force the whole subtree to be
+ // re-serialized.
+ serializer_.DeleteClientSubtree(obj);
+
+ // Explicitly send a tree change update event now.
+ HandleAXEvent(obj, ui::AX_EVENT_TREE_CHANGED);
+}
+
+void RendererAccessibility::OnReset(int reset_token) {
+ reset_token_ = reset_token;
+ serializer_.Reset();
+ pending_events_.clear();
+
+ const WebDocument& document = GetMainDocument();
+ if (!document.isNull())
+ HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE);
+}
+
+void RendererAccessibility::OnScrollToMakeVisible(
+ int acc_obj_id, gfx::Rect subfocus) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+ if (obj.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "ScrollToMakeVisible on invalid object id " << acc_obj_id;
+#endif
+ return;
+ }
+
+ obj.scrollToMakeVisibleWithSubFocus(
+ WebRect(subfocus.x(), subfocus.y(), subfocus.width(), subfocus.height()));
+
+ // Make sure the browser gets an event when the scroll
+ // position actually changes.
+ // TODO(dmazzoni): remove this once this bug is fixed:
+ // https://bugs.webkit.org/show_bug.cgi?id=73460
+ HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE);
+}
+
+void RendererAccessibility::OnScrollToPoint(int acc_obj_id, gfx::Point point) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+ if (obj.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "ScrollToPoint on invalid object id " << acc_obj_id;
+#endif
+ return;
+ }
+
+ obj.scrollToGlobalPoint(WebPoint(point.x(), point.y()));
+
+ // Make sure the browser gets an event when the scroll
+ // position actually changes.
+ // TODO(dmazzoni): remove this once this bug is fixed:
+ // https://bugs.webkit.org/show_bug.cgi?id=73460
+ HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_LAYOUT_COMPLETE);
+}
+
+void RendererAccessibility::OnSetFocus(int acc_obj_id) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+ if (obj.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "OnSetAccessibilityFocus on invalid object id "
+ << acc_obj_id;
+#endif
+ return;
+ }
+
+ WebAXObject root = document.accessibilityObject();
+ if (root.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "OnSetAccessibilityFocus but root is invalid";
+#endif
+ return;
+ }
+
+ // By convention, calling SetFocus on the root of the tree should clear the
+ // current focus. Otherwise set the focus to the new node.
+ if (acc_obj_id == root.axID())
+ render_frame_->GetRenderView()->GetWebView()->clearFocusedElement();
+ else
+ obj.setFocused(true);
+}
+
+void RendererAccessibility::OnSetTextSelection(
+ int acc_obj_id, int start_offset, int end_offset) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+ if (obj.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "SetTextSelection on invalid object id " << acc_obj_id;
+#endif
+ return;
+ }
+
+ obj.setSelectedTextRange(start_offset, end_offset);
+}
+
+void RendererAccessibility::OnSetValue(
+ int acc_obj_id,
+ base::string16 value) {
+ const WebDocument& document = GetMainDocument();
+ if (document.isNull())
+ return;
+
+ WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
+ if (obj.isDetached()) {
+#ifndef NDEBUG
+ LOG(WARNING) << "SetTextSelection on invalid object id " << acc_obj_id;
+#endif
+ return;
+ }
+
+ obj.setValue(value);
+ HandleAXEvent(obj, ui::AX_EVENT_VALUE_CHANGED);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.h b/chromium/content/renderer/accessibility/renderer_accessibility.h
index 9ddb6ed4405..2c3d8e846b4 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.h
+++ b/chromium/content/renderer/accessibility/renderer_accessibility.h
@@ -5,79 +5,132 @@
#ifndef CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_H_
#define CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_H_
+#include <vector>
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/accessibility_messages.h"
-#include "content/public/renderer/render_view_observer.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/renderer/accessibility/blink_ax_tree_source.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
+#include "ui/accessibility/ax_tree_serializer.h"
namespace blink {
class WebDocument;
+class WebNode;
};
namespace content {
-class RenderViewImpl;
-
-enum RendererAccessibilityType {
- // Turns on Blink accessibility and provides a full accessibility
- // implementation for when assistive technology is running.
- RendererAccessibilityTypeComplete,
-
- // Does not turn on Blink accessibility. Only sends a minimal accessible tree
- // to the browser whenever focus changes. This mode is currently used to
- // support opening the on-screen keyboard in response to touch events on
- // Windows 8 in Metro mode.
- RendererAccessibilityTypeFocusOnly
-};
+class RenderFrameImpl;
-// The browser process implement native accessibility APIs, allowing
+// The browser process implements native accessibility APIs, allowing
// assistive technology (e.g., screen readers, magnifiers) to access and
// control the web contents with high-level APIs. These APIs are also used
// by automation tools, and Windows 8 uses them to determine when the
// on-screen keyboard should be shown.
//
-// An instance of this class (or rather, a subclass) belongs to RenderViewImpl.
-// Accessibility is initialized based on the AccessibilityMode of
-// RenderViewImpl; it lazily starts as Off or EditableTextOnly depending on
-// the operating system, and switches to Complete if assistive technology is
-// detected or a flag is set.
+// An instance of this class belongs to RenderFrameImpl. Accessibility is
+// initialized based on the AccessibilityMode of RenderFrameImpl; it lazily
+// starts as Off or EditableTextOnly depending on the operating system, and
+// switches to Complete if assistive technology is detected or a flag is set.
//
// A tree of accessible objects is built here and sent to the browser process;
// the browser process maintains this as a tree of platform-native
// accessible objects that can be used to respond to accessibility requests
// from other processes.
//
-// This base class just contains common code and will not do anything by itself.
-// The two subclasses are:
-//
-// RendererAccessibilityComplete - turns on Blink accessibility and
-// provides a full accessibility implementation for when
-// assistive technology is running.
-//
-// RendererAccessibilityFocusOnly - does not turn on Blink
-// accessibility. Only sends a minimal accessible tree to the
-// browser whenever focus changes. This mode is currently used
-// to support opening the on-screen keyboard in response to
-// touch events on Windows 8 in Metro mode.
-//
-class CONTENT_EXPORT RendererAccessibility : public RenderViewObserver {
+// This class implements complete accessibility support for assistive
+// technology. It turns on Blink's accessibility code and sends a serialized
+// representation of that tree whenever it changes. It also handles requests
+// from the browser to perform accessibility actions on nodes in the tree
+// (e.g., change focus, or click on a button).
+class CONTENT_EXPORT RendererAccessibility : public RenderFrameObserver {
public:
- explicit RendererAccessibility(RenderViewImpl* render_view);
- virtual ~RendererAccessibility();
+ explicit RendererAccessibility(RenderFrameImpl* render_frame);
+ ~RendererAccessibility() override;
+
+ // RenderFrameObserver implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
// Called when an accessibility notification occurs in Blink.
- virtual void HandleWebAccessibilityEvent(
- const blink::WebAXObject& obj, blink::WebAXEvent event) = 0;
+ void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
+ blink::WebAXEvent event);
+
+ // Called when a new find in page result is highlighted.
+ void HandleAccessibilityFindInPageResult(
+ int identifier,
+ int match_index,
+ const blink::WebAXObject& start_object,
+ int start_offset,
+ const blink::WebAXObject& end_object,
+ int end_offset);
+
+ void FocusedNodeChanged(const blink::WebNode& node);
- // Gets the type of this RendererAccessibility object. Primarily intended for
- // testing.
- virtual RendererAccessibilityType GetType() = 0;
+ // This can be called before deleting a RendererAccessibility instance due
+ // to the accessibility mode changing, as opposed to during frame destruction
+ // (when there'd be no point).
+ void DisableAccessibility();
+
+ void HandleAXEvent(const blink::WebAXObject& obj, ui::AXEvent event);
protected:
// Returns the main top-level document for this page, or NULL if there's
// no view or frame.
blink::WebDocument GetMainDocument();
- // The RenderViewImpl that owns us.
- RenderViewImpl* render_view_;
+ // Send queued events from the renderer to the browser.
+ void SendPendingAccessibilityEvents();
+
+ // Check the entire accessibility tree to see if any nodes have
+ // changed location, by comparing their locations to the cached
+ // versions. If any have moved, send an IPC with the new locations.
+ void SendLocationChanges();
+
+ // The RenderFrameImpl that owns us.
+ RenderFrameImpl* render_frame_;
+
+ private:
+ // Handlers for messages from the browser to the renderer.
+ void OnDoDefaultAction(int acc_obj_id);
+ void OnEventsAck();
+ void OnFatalError();
+ void OnHitTest(gfx::Point point);
+ void OnSetAccessibilityFocus(int acc_obj_id);
+ void OnReset(int reset_token);
+ void OnScrollToMakeVisible(int acc_obj_id, gfx::Rect subfocus);
+ void OnScrollToPoint(int acc_obj_id, gfx::Point point);
+ void OnSetFocus(int acc_obj_id);
+ void OnSetTextSelection(int acc_obj_id, int start_offset, int end_offset);
+ void OnSetValue(int acc_obj_id, base::string16 value);
+
+ // Events from Blink are collected until they are ready to be
+ // sent to the browser.
+ std::vector<AccessibilityHostMsg_EventParams> pending_events_;
+
+ // The adapter that exposes Blink's accessibility tree to AXTreeSerializer.
+ BlinkAXTreeSource tree_source_;
+
+ // The serializer that sends accessibility messages to the browser process.
+ ui::AXTreeSerializer<blink::WebAXObject> serializer_;
+
+ // Current location of every object, so we can detect when it moves.
+ base::hash_map<int, gfx::Rect> locations_;
+
+ // The most recently observed scroll offset of the root document element.
+ // TODO(dmazzoni): remove once https://bugs.webkit.org/show_bug.cgi?id=73460
+ // is fixed.
+ gfx::Size last_scroll_offset_;
+
+ // Set if we are waiting for an accessibility event ack.
+ bool ack_pending_;
+
+ // Nonzero if the browser requested we reset the accessibility state.
+ // We need to return this token in the next IPC.
+ int reset_token_;
+
+ // So we can queue up tasks to be executed later.
+ base::WeakPtrFactory<RendererAccessibility> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RendererAccessibility);
};
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index 9aa4b28e683..c173c94f9e0 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "content/common/frame_messages.h"
#include "content/common/view_message_enums.h"
#include "content/public/test/render_view_test.h"
-#include "content/renderer/accessibility/renderer_accessibility_complete.h"
+#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -20,14 +22,14 @@ using blink::WebDocument;
namespace content {
-class TestRendererAccessibilityComplete : public RendererAccessibilityComplete {
+class TestRendererAccessibility : public RendererAccessibility {
public:
- explicit TestRendererAccessibilityComplete(RenderViewImpl* render_view)
- : RendererAccessibilityComplete(render_view) {
+ explicit TestRendererAccessibility(RenderFrameImpl* render_frame)
+ : RendererAccessibility(render_frame) {
}
void SendPendingAccessibilityEvents() {
- RendererAccessibilityComplete::SendPendingAccessibilityEvents();
+ RendererAccessibility::SendPendingAccessibilityEvents();
}
};
@@ -43,13 +45,13 @@ class RendererAccessibilityTest : public RenderViewTest {
return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame());
}
- virtual void SetUp() {
+ void SetUp() override {
RenderViewTest::SetUp();
sink_ = &render_thread_->sink();
}
void SetMode(AccessibilityMode mode) {
- view()->OnSetAccessibilityMode(mode);
+ frame()->OnSetAccessibilityMode(mode);
}
void GetLastAccEvent(
@@ -57,7 +59,7 @@ class RendererAccessibilityTest : public RenderViewTest {
const IPC::Message* message =
sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID);
ASSERT_TRUE(message);
- Tuple1<std::vector<AccessibilityHostMsg_EventParams> > param;
+ Tuple2<std::vector<AccessibilityHostMsg_EventParams>, int> param;
AccessibilityHostMsg_Events::Read(message, &param);
ASSERT_GE(param.a.size(), 1U);
*params = param.a[0];
@@ -76,152 +78,8 @@ class RendererAccessibilityTest : public RenderViewTest {
};
-TEST_F(RendererAccessibilityTest, EditableTextModeFocusEvents) {
- // This is not a test of true web accessibility, it's a test of
- // a mode used on Windows 8 in Metro mode where an extremely simplified
- // accessibility tree containing only the current focused node is
- // generated.
- SetMode(AccessibilityModeEditableTextOnly);
-
- // Set a minimum size and give focus so simulated events work.
- view()->webwidget()->resize(blink::WebSize(500, 500));
- view()->webwidget()->setFocus(true);
-
- std::string html =
- "<body>"
- " <input>"
- " <textarea></textarea>"
- " <p contentEditable>Editable</p>"
- " <div tabindex=0 role=textbox>Textbox</div>"
- " <button>Button</button>"
- " <a href=#>Link</a>"
- "</body>";
-
- // Load the test page.
- LoadHTML(html.c_str());
-
- // We should have sent a message to the browser with the initial focus
- // on the document.
- {
- SCOPED_TRACE("Initial focus on document");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.event_type,
- ui::AX_EVENT_LAYOUT_COMPLETE);
- EXPECT_EQ(event.id, 1);
- EXPECT_EQ(event.update.nodes.size(), 2U);
- EXPECT_EQ(event.update.nodes[0].id, 1);
- EXPECT_EQ(event.update.nodes[0].role,
- ui::AX_ROLE_ROOT_WEB_AREA);
- EXPECT_EQ(event.update.nodes[0].state,
- (1U << ui::AX_STATE_READ_ONLY) |
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED));
- EXPECT_EQ(event.update.nodes[0].child_ids.size(), 1U);
- }
-
- // Now focus the input element, and check everything again.
- {
- SCOPED_TRACE("input");
- sink_->ClearMessages();
- ExecuteJavaScript("document.querySelector('input').focus();");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.event_type,
- ui::AX_EVENT_FOCUS);
- EXPECT_EQ(event.id, 3);
- EXPECT_EQ(event.update.nodes[0].id, 1);
- EXPECT_EQ(event.update.nodes[0].role,
- ui::AX_ROLE_ROOT_WEB_AREA);
- EXPECT_EQ(event.update.nodes[0].state,
- (1U << ui::AX_STATE_READ_ONLY) |
- (1U << ui::AX_STATE_FOCUSABLE));
- EXPECT_EQ(event.update.nodes[0].child_ids.size(), 1U);
- EXPECT_EQ(event.update.nodes[1].id, 3);
- EXPECT_EQ(event.update.nodes[1].role,
- ui::AX_ROLE_GROUP);
- EXPECT_EQ(event.update.nodes[1].state,
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED));
- }
-
- // Check other editable text nodes.
- {
- SCOPED_TRACE("textarea");
- sink_->ClearMessages();
- ExecuteJavaScript("document.querySelector('textarea').focus();");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.id, 4);
- EXPECT_EQ(event.update.nodes[1].state,
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED));
- }
-
- {
- SCOPED_TRACE("contentEditable");
- sink_->ClearMessages();
- ExecuteJavaScript("document.querySelector('p').focus();");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.id, 5);
- EXPECT_EQ(event.update.nodes[1].state,
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED));
- }
-
- {
- SCOPED_TRACE("role=textarea");
- sink_->ClearMessages();
- ExecuteJavaScript("document.querySelector('div').focus();");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.id, 6);
- EXPECT_EQ(event.update.nodes[1].state,
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED));
- }
-
- // Try focusing things that aren't editable text.
- {
- SCOPED_TRACE("button");
- sink_->ClearMessages();
- ExecuteJavaScript("document.querySelector('button').focus();");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.id, 7);
- EXPECT_EQ(event.update.nodes[1].state,
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED) |
- (1U << ui::AX_STATE_READ_ONLY));
- }
-
- {
- SCOPED_TRACE("link");
- sink_->ClearMessages();
- ExecuteJavaScript("document.querySelector('a').focus();");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.id, 8);
- EXPECT_EQ(event.update.nodes[1].state,
- (1U << ui::AX_STATE_FOCUSABLE) |
- (1U << ui::AX_STATE_FOCUSED) |
- (1U << ui::AX_STATE_READ_ONLY));
- }
-
- // Clear focus.
- {
- SCOPED_TRACE("Back to document.");
- sink_->ClearMessages();
- ExecuteJavaScript("document.activeElement.blur()");
- AccessibilityHostMsg_EventParams event;
- GetLastAccEvent(&event);
- EXPECT_EQ(event.id, 1);
- }
-}
-
TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
- // The job of RendererAccessibilityComplete is to serialize the
+ // The job of RendererAccessibility is to serialize the
// accessibility tree built by WebKit and send it to the browser.
// When the accessibility tree changes, it tries to send only
// the nodes that actually changed or were reparented. This test
@@ -236,10 +94,9 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
"</body>";
LoadHTML(html.c_str());
- // Creating a RendererAccessibilityComplete should sent the tree
- // to the browser.
- scoped_ptr<TestRendererAccessibilityComplete> accessibility(
- new TestRendererAccessibilityComplete(view()));
+ // Creating a RendererAccessibility should sent the tree to the browser.
+ scoped_ptr<TestRendererAccessibility> accessibility(
+ new TestRendererAccessibility(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
@@ -306,10 +163,9 @@ TEST_F(RendererAccessibilityTest,
LoadHTML(html.c_str());
static const int kProxyRoutingId = 13;
- // Creating a RendererAccessibilityComplete should send the tree
- // to the browser.
- scoped_ptr<TestRendererAccessibilityComplete> accessibility(
- new TestRendererAccessibilityComplete(view()));
+ // Creating a RendererAccessibility should send the tree to the browser.
+ scoped_ptr<TestRendererAccessibility> accessibility(
+ new TestRendererAccessibility(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser());
@@ -322,7 +178,7 @@ TEST_F(RendererAccessibilityTest,
accessibility->HandleAXEvent(
root_obj,
ui::AX_EVENT_VALUE_CHANGED);
- view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
+ view()->GetMainRenderFrame()->OnSwapOut(kProxyRoutingId);
accessibility->SendPendingAccessibilityEvents();
EXPECT_FALSE(sink_->GetUniqueMessageMatching(
AccessibilityHostMsg_Events::ID));
@@ -333,13 +189,15 @@ TEST_F(RendererAccessibilityTest,
// because the element it was referring to no longer exists,
// so the event here is from loading this new page.
FrameMsg_Navigate_Params nav_params;
- nav_params.url = GURL("data:text/html,<p>Hello, again.</p>");
- nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- nav_params.transition = PAGE_TRANSITION_TYPED;
+ nav_params.common_params.url = GURL("data:text/html,<p>Hello, again.</p>");
+ nav_params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ nav_params.common_params.transition = ui::PAGE_TRANSITION_TYPED;
nav_params.current_history_list_length = 1;
nav_params.current_history_list_offset = 0;
nav_params.pending_history_list_offset = 1;
nav_params.page_id = -1;
+ nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(nav_params);
accessibility->SendPendingAccessibilityEvents();
EXPECT_TRUE(sink_->GetUniqueMessageMatching(
@@ -347,7 +205,7 @@ TEST_F(RendererAccessibilityTest,
}
TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
- // Test RendererAccessibilityComplete and make sure it sends the
+ // Test RendererAccessibility and make sure it sends the
// proper event to the browser when an object in the tree
// is hidden, but its children are not.
std::string html =
@@ -361,8 +219,8 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
"</body>";
LoadHTML(html.c_str());
- scoped_ptr<TestRendererAccessibilityComplete> accessibility(
- new TestRendererAccessibilityComplete(view()));
+ scoped_ptr<TestRendererAccessibility> accessibility(
+ new TestRendererAccessibility(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
@@ -389,7 +247,7 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
GetLastAccEvent(&event);
ASSERT_EQ(2U, event.update.nodes.size());
- // RendererAccessibilityComplete notices that 'C' is being reparented,
+ // RendererAccessibility notices that 'C' is being reparented,
// so it clears the subtree rooted at 'A', then updates 'A' and then 'C'.
EXPECT_EQ(node_a.axID(), event.update.node_id_to_clear);
EXPECT_EQ(node_a.axID(), event.update.nodes[0].id);
@@ -398,7 +256,7 @@ TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
}
TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
- // Test RendererAccessibilityComplete and make sure it sends the
+ // Test RendererAccessibility and make sure it sends the
// proper event to the browser when an object in the tree
// is shown, causing its own already-visible children to be
// reparented to it.
@@ -413,8 +271,8 @@ TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
"</body>";
LoadHTML(html.c_str());
- scoped_ptr<TestRendererAccessibilityComplete> accessibility(
- new TestRendererAccessibilityComplete(view()));
+ scoped_ptr<TestRendererAccessibility> accessibility(
+ new TestRendererAccessibility(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
@@ -447,7 +305,7 @@ TEST_F(RendererAccessibilityTest, ShowAccessibilityObject) {
}
TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
- // Test RendererAccessibilityComplete and make sure it sends the
+ // Test RendererAccessibility and make sure it sends the
// proper event to the browser when an object in the tree
// is detached, but its children are not. This can happen when
// a layout occurs and an anonymous render block is no longer needed.
@@ -457,8 +315,8 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
"</body>";
LoadHTML(html.c_str());
- scoped_ptr<TestRendererAccessibilityComplete> accessibility(
- new TestRendererAccessibilityComplete(view()));
+ scoped_ptr<TestRendererAccessibility> accessibility(
+ new TestRendererAccessibility(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(7, CountAccessibilityNodesSentToBrowser());
@@ -518,15 +376,15 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
}
TEST_F(RendererAccessibilityTest, EventOnObjectNotInTree) {
- // Test RendererAccessibilityComplete and make sure it doesn't send anything
+ // Test RendererAccessibility and make sure it doesn't send anything
// if we get a notification from Blink for an object that isn't in the
// tree, like the scroll area that's the parent of the main document,
// which we don't expose.
std::string html = "<body><input></body>";
LoadHTML(html.c_str());
- scoped_ptr<TestRendererAccessibilityComplete> accessibility(
- new TestRendererAccessibilityComplete(view()));
+ scoped_ptr<TestRendererAccessibility> accessibility(
+ new TestRendererAccessibility(frame()));
accessibility->SendPendingAccessibilityEvents();
EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
@@ -546,7 +404,7 @@ TEST_F(RendererAccessibilityTest, EventOnObjectNotInTree) {
const IPC::Message* message =
sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID);
ASSERT_TRUE(message);
- Tuple1<std::vector<AccessibilityHostMsg_EventParams> > param;
+ Tuple2<std::vector<AccessibilityHostMsg_EventParams>, int> param;
AccessibilityHostMsg_Events::Read(message, &param);
ASSERT_EQ(0U, param.a.size());
}
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc b/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc
deleted file mode 100644
index 2e72dde7fb9..00000000000
--- a/chromium/content/renderer/accessibility/renderer_accessibility_complete.cc
+++ /dev/null
@@ -1,399 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/accessibility/renderer_accessibility_complete.h"
-
-#include <queue>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "content/renderer/accessibility/blink_ax_enum_conversion.h"
-#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebAXObject.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebInputElement.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "ui/accessibility/ax_tree.h"
-
-using blink::WebAXObject;
-using blink::WebDocument;
-using blink::WebNode;
-using blink::WebPoint;
-using blink::WebRect;
-using blink::WebView;
-
-namespace content {
-
-RendererAccessibilityComplete::RendererAccessibilityComplete(
- RenderViewImpl* render_view)
- : RendererAccessibility(render_view),
- weak_factory_(this),
- tree_source_(render_view),
- serializer_(&tree_source_),
- last_scroll_offset_(gfx::Size()),
- ack_pending_(false) {
- WebAXObject::enableAccessibility();
-
-#if !defined(OS_ANDROID)
- // Skip inline text boxes on Android - since there are no native Android
- // APIs that compute the bounds of a range of text, it's a waste to
- // include these in the AX tree.
- WebAXObject::enableInlineTextBoxAccessibility();
-#endif
-
- const WebDocument& document = GetMainDocument();
- if (!document.isNull()) {
- // It's possible that the webview has already loaded a webpage without
- // accessibility being enabled. Initialize the browser's cached
- // accessibility tree by sending it a notification.
- HandleAXEvent(document.accessibilityObject(),
- ui::AX_EVENT_LAYOUT_COMPLETE);
- }
-}
-
-RendererAccessibilityComplete::~RendererAccessibilityComplete() {
-}
-
-bool RendererAccessibilityComplete::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RendererAccessibilityComplete, message)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction,
- OnDoDefaultAction)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_Events_ACK,
- OnEventsAck)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible,
- OnScrollToMakeVisible)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint,
- OnScrollToPoint)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection,
- OnSetTextSelection)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_HitTest, OnHitTest)
- IPC_MESSAGE_HANDLER(AccessibilityMsg_FatalError, OnFatalError)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void RendererAccessibilityComplete::FocusedNodeChanged(const WebNode& node) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- if (node.isNull()) {
- // When focus is cleared, implicitly focus the document.
- // TODO(dmazzoni): Make Blink send this notification instead.
- HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_BLUR);
- }
-}
-
-void RendererAccessibilityComplete::DidFinishLoad(blink::WebLocalFrame* frame) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-}
-
-
-void RendererAccessibilityComplete::HandleWebAccessibilityEvent(
- const blink::WebAXObject& obj, blink::WebAXEvent event) {
- HandleAXEvent(obj, AXEventFromBlink(event));
-}
-
-void RendererAccessibilityComplete::HandleAXEvent(
- const blink::WebAXObject& obj, ui::AXEvent event) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- gfx::Size scroll_offset = document.frame()->scrollOffset();
- if (scroll_offset != last_scroll_offset_) {
- // Make sure the browser is always aware of the scroll position of
- // the root document element by posting a generic notification that
- // will update it.
- // TODO(dmazzoni): remove this as soon as
- // https://bugs.webkit.org/show_bug.cgi?id=73460 is fixed.
- last_scroll_offset_ = scroll_offset;
- if (!obj.equals(document.accessibilityObject())) {
- HandleAXEvent(document.accessibilityObject(),
- ui::AX_EVENT_LAYOUT_COMPLETE);
- }
- }
-
- // Add the accessibility object to our cache and ensure it's valid.
- AccessibilityHostMsg_EventParams acc_event;
- acc_event.id = obj.axID();
- acc_event.event_type = event;
-
- // Discard duplicate accessibility events.
- for (uint32 i = 0; i < pending_events_.size(); ++i) {
- if (pending_events_[i].id == acc_event.id &&
- pending_events_[i].event_type ==
- acc_event.event_type) {
- return;
- }
- }
- pending_events_.push_back(acc_event);
-
- if (!ack_pending_ && !weak_factory_.HasWeakPtrs()) {
- // When no accessibility events are in-flight post a task to send
- // the events to the browser. We use PostTask so that we can queue
- // up additional events.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&RendererAccessibilityComplete::
- SendPendingAccessibilityEvents,
- weak_factory_.GetWeakPtr()));
- }
-}
-
-RendererAccessibilityType RendererAccessibilityComplete::GetType() {
- return RendererAccessibilityTypeComplete;
-}
-
-void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- if (pending_events_.empty())
- return;
-
- if (render_view_->is_swapped_out())
- return;
-
- ack_pending_ = true;
-
- // Make a copy of the events, because it's possible that
- // actions inside this loop will cause more events to be
- // queued up.
- std::vector<AccessibilityHostMsg_EventParams> src_events =
- pending_events_;
- pending_events_.clear();
-
- // Generate an event message from each Blink event.
- std::vector<AccessibilityHostMsg_EventParams> event_msgs;
-
- // Loop over each event and generate an updated event message.
- for (size_t i = 0; i < src_events.size(); ++i) {
- AccessibilityHostMsg_EventParams& event =
- src_events[i];
-
- WebAXObject obj = document.accessibilityObjectFromID(
- event.id);
- // Make sure the object still exists.
- if (!obj.updateBackingStoreAndCheckValidity())
- continue;
- // Make sure it's a descendant of our root node - exceptions include the
- // scroll area that's the parent of the main document (we ignore it), and
- // possibly nodes attached to a different document.
- if (!tree_source_.IsInTree(obj))
- continue;
-
- // When we get a "selected children changed" event, Blink
- // doesn't also send us events for each child that changed
- // selection state, so make sure we re-send that whole subtree.
- if (event.event_type ==
- ui::AX_EVENT_SELECTED_CHILDREN_CHANGED) {
- serializer_.DeleteClientSubtree(obj);
- }
-
- AccessibilityHostMsg_EventParams event_msg;
- event_msg.event_type = event.event_type;
- event_msg.id = event.id;
- serializer_.SerializeChanges(obj, &event_msg.update);
- event_msgs.push_back(event_msg);
-
- VLOG(0) << "Accessibility event: " << ui::ToString(event.event_type)
- << " on node id " << event_msg.id
- << "\n" << event_msg.update.ToString();
- }
-
- Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs));
-
- SendLocationChanges();
-}
-
-void RendererAccessibilityComplete::SendLocationChanges() {
- std::vector<AccessibilityHostMsg_LocationChangeParams> messages;
-
- // Do a breadth-first explore of the whole blink AX tree.
- base::hash_map<int, gfx::Rect> new_locations;
- std::queue<WebAXObject> objs_to_explore;
- objs_to_explore.push(tree_source_.GetRoot());
- while (objs_to_explore.size()) {
- WebAXObject obj = objs_to_explore.front();
- objs_to_explore.pop();
-
- // See if we had a previous location. If not, this whole subtree must
- // be new, so don't continue to explore this branch.
- int id = obj.axID();
- base::hash_map<int, gfx::Rect>::iterator iter = locations_.find(id);
- if (iter == locations_.end())
- continue;
-
- // If the location has changed, append it to the IPC message.
- gfx::Rect new_location = obj.boundingBoxRect();
- if (iter != locations_.end() && iter->second != new_location) {
- AccessibilityHostMsg_LocationChangeParams message;
- message.id = id;
- message.new_location = new_location;
- messages.push_back(message);
- }
-
- // Save the new location.
- new_locations[id] = new_location;
- }
- locations_.swap(new_locations);
-
- Send(new AccessibilityHostMsg_LocationChanges(routing_id(), messages));
-}
-
-void RendererAccessibilityComplete::OnDoDefaultAction(int acc_obj_id) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
- if (obj.isDetached()) {
-#ifndef NDEBUG
- LOG(WARNING) << "DoDefaultAction on invalid object id " << acc_obj_id;
-#endif
- return;
- }
-
- obj.performDefaultAction();
-}
-
-void RendererAccessibilityComplete::OnScrollToMakeVisible(
- int acc_obj_id, gfx::Rect subfocus) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
- if (obj.isDetached()) {
-#ifndef NDEBUG
- LOG(WARNING) << "ScrollToMakeVisible on invalid object id " << acc_obj_id;
-#endif
- return;
- }
-
- obj.scrollToMakeVisibleWithSubFocus(
- WebRect(subfocus.x(), subfocus.y(),
- subfocus.width(), subfocus.height()));
-
- // Make sure the browser gets an event when the scroll
- // position actually changes.
- // TODO(dmazzoni): remove this once this bug is fixed:
- // https://bugs.webkit.org/show_bug.cgi?id=73460
- HandleAXEvent(document.accessibilityObject(),
- ui::AX_EVENT_LAYOUT_COMPLETE);
-}
-
-void RendererAccessibilityComplete::OnScrollToPoint(
- int acc_obj_id, gfx::Point point) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
- if (obj.isDetached()) {
-#ifndef NDEBUG
- LOG(WARNING) << "ScrollToPoint on invalid object id " << acc_obj_id;
-#endif
- return;
- }
-
- obj.scrollToGlobalPoint(WebPoint(point.x(), point.y()));
-
- // Make sure the browser gets an event when the scroll
- // position actually changes.
- // TODO(dmazzoni): remove this once this bug is fixed:
- // https://bugs.webkit.org/show_bug.cgi?id=73460
- HandleAXEvent(document.accessibilityObject(),
- ui::AX_EVENT_LAYOUT_COMPLETE);
-}
-
-void RendererAccessibilityComplete::OnSetTextSelection(
- int acc_obj_id, int start_offset, int end_offset) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
- if (obj.isDetached()) {
-#ifndef NDEBUG
- LOG(WARNING) << "SetTextSelection on invalid object id " << acc_obj_id;
-#endif
- return;
- }
-
- // TODO(dmazzoni): support elements other than <input>.
- blink::WebNode node = obj.node();
- if (!node.isNull() && node.isElementNode()) {
- blink::WebElement element = node.to<blink::WebElement>();
- blink::WebInputElement* input_element =
- blink::toWebInputElement(&element);
- if (input_element && input_element->isTextField())
- input_element->setSelectionRange(start_offset, end_offset);
- }
-}
-
-void RendererAccessibilityComplete::OnHitTest(gfx::Point point) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
- WebAXObject root_obj = document.accessibilityObject();
- if (!root_obj.updateBackingStoreAndCheckValidity())
- return;
-
- WebAXObject obj = root_obj.hitTest(point);
- if (!obj.isDetached())
- HandleAXEvent(obj, ui::AX_EVENT_HOVER);
-}
-
-void RendererAccessibilityComplete::OnEventsAck() {
- DCHECK(ack_pending_);
- ack_pending_ = false;
- SendPendingAccessibilityEvents();
-}
-
-void RendererAccessibilityComplete::OnSetFocus(int acc_obj_id) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id);
- if (obj.isDetached()) {
-#ifndef NDEBUG
- LOG(WARNING) << "OnSetAccessibilityFocus on invalid object id "
- << acc_obj_id;
-#endif
- return;
- }
-
- WebAXObject root = document.accessibilityObject();
- if (root.isDetached()) {
-#ifndef NDEBUG
- LOG(WARNING) << "OnSetAccessibilityFocus but root is invalid";
-#endif
- return;
- }
-
- // By convention, calling SetFocus on the root of the tree should clear the
- // current focus. Otherwise set the focus to the new node.
- if (acc_obj_id == root.axID())
- render_view()->GetWebView()->clearFocusedElement();
- else
- obj.setFocused(true);
-}
-
-void RendererAccessibilityComplete::OnFatalError() {
- CHECK(false) << "Invalid accessibility tree.";
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_complete.h b/chromium/content/renderer/accessibility/renderer_accessibility_complete.h
deleted file mode 100644
index 507b734779e..00000000000
--- a/chromium/content/renderer/accessibility/renderer_accessibility_complete.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_COMPLETE_H_
-#define CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_COMPLETE_H_
-
-#include <set>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/memory/weak_ptr.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "content/renderer/accessibility/blink_ax_tree_source.h"
-#include "content/renderer/accessibility/renderer_accessibility.h"
-#include "third_party/WebKit/public/web/WebAXEnums.h"
-#include "third_party/WebKit/public/web/WebAXObject.h"
-#include "ui/accessibility/ax_node_data.h"
-#include "ui/accessibility/ax_tree_serializer.h"
-
-namespace blink {
-class WebDocument;
-class WebNode;
-};
-
-namespace content {
-class RenderViewImpl;
-
-// This is the subclass of RendererAccessibility that implements
-// complete accessibility support for assistive technology (as opposed to
-// partial support - see RendererAccessibilityFocusOnly).
-//
-// This version turns on Blink's accessibility code and sends
-// a serialized representation of that tree whenever it changes. It also
-// handles requests from the browser to perform accessibility actions on
-// nodes in the tree (e.g., change focus, or click on a button).
-class CONTENT_EXPORT RendererAccessibilityComplete
- : public RendererAccessibility {
- public:
- explicit RendererAccessibilityComplete(RenderViewImpl* render_view);
- virtual ~RendererAccessibilityComplete();
-
- // RenderView::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE;
- virtual void DidFinishLoad(blink::WebLocalFrame* frame) OVERRIDE;
-
- // RendererAccessibility.
- virtual void HandleWebAccessibilityEvent(
- const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
- virtual RendererAccessibilityType GetType() OVERRIDE;
-
- void HandleAXEvent(const blink::WebAXObject& obj, ui::AXEvent event);
-
- protected:
- // Send queued events from the renderer to the browser.
- void SendPendingAccessibilityEvents();
-
- // Check the entire accessibility tree to see if any nodes have
- // changed location, by comparing their locations to the cached
- // versions. If any have moved, send an IPC with the new locations.
- void SendLocationChanges();
-
- private:
- // Handlers for messages from the browser to the renderer.
- void OnDoDefaultAction(int acc_obj_id);
- void OnEventsAck();
- void OnChangeScrollPosition(int acc_obj_id, int scroll_x, int scroll_y);
- void OnScrollToMakeVisible(int acc_obj_id, gfx::Rect subfocus);
- void OnScrollToPoint(int acc_obj_id, gfx::Point point);
- void OnSetFocus(int acc_obj_id);
- void OnSetTextSelection(int acc_obj_id, int start_offset, int end_offset);
- void OnHitTest(gfx::Point point);
- void OnFatalError();
-
- // So we can queue up tasks to be executed later.
- base::WeakPtrFactory<RendererAccessibilityComplete> weak_factory_;
-
- // Events from Blink are collected until they are ready to be
- // sent to the browser.
- std::vector<AccessibilityHostMsg_EventParams> pending_events_;
-
- // The adapter that exposes Blink's accessibility tree to AXTreeSerializer.
- BlinkAXTreeSource tree_source_;
-
- // The serializer that sends accessibility messages to the browser process.
- ui::AXTreeSerializer<blink::WebAXObject> serializer_;
-
- // Current location of every object, so we can detect when it moves.
- base::hash_map<int, gfx::Rect> locations_;
-
- // The most recently observed scroll offset of the root document element.
- // TODO(dmazzoni): remove once https://bugs.webkit.org/show_bug.cgi?id=73460
- // is fixed.
- gfx::Size last_scroll_offset_;
-
- // Set if we are waiting for an accessibility event ack.
- bool ack_pending_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererAccessibilityComplete);
-};
-
-#endif // CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_COMPLETE_H_
-
-} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc
deleted file mode 100644
index bda3e8f73a3..00000000000
--- a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/accessibility/renderer_accessibility_focus_only.h"
-
-#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "ui/accessibility/ax_node_data.h"
-
-using blink::WebDocument;
-using blink::WebElement;
-using blink::WebNode;
-using blink::WebView;
-
-namespace {
-// The root node will always have id 1. Let each child node have a new
-// id starting with 2.
-const int kInitialId = 2;
-}
-
-namespace content {
-
-RendererAccessibilityFocusOnly::RendererAccessibilityFocusOnly(
- RenderViewImpl* render_view)
- : RendererAccessibility(render_view),
- next_id_(kInitialId) {
-}
-
-RendererAccessibilityFocusOnly::~RendererAccessibilityFocusOnly() {
-}
-
-void RendererAccessibilityFocusOnly::HandleWebAccessibilityEvent(
- const blink::WebAXObject& obj, blink::WebAXEvent event) {
- // Do nothing.
-}
-
-RendererAccessibilityType RendererAccessibilityFocusOnly::GetType() {
- return RendererAccessibilityTypeFocusOnly;
-}
-
-void RendererAccessibilityFocusOnly::FocusedNodeChanged(const WebNode& node) {
- // Send the new accessible tree and post a native focus event.
- HandleFocusedNodeChanged(node, true);
-}
-
-void RendererAccessibilityFocusOnly::DidFinishLoad(
- blink::WebLocalFrame* frame) {
- WebView* view = render_view()->GetWebView();
- if (view->focusedFrame() != frame)
- return;
-
- WebDocument document = frame->document();
- // Send an accessible tree to the browser, but do not post a native
- // focus event. This is important so that if focus is initially in an
- // editable text field, Windows will know to pop up the keyboard if the
- // user touches it and focus doesn't change.
- HandleFocusedNodeChanged(document.focusedElement(), false);
-}
-
-void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged(
- const WebNode& node,
- bool send_focus_event) {
- const WebDocument& document = GetMainDocument();
- if (document.isNull())
- return;
-
- bool node_has_focus;
- bool node_is_editable_text;
- // Check HasIMETextFocus first, because it will correctly handle
- // focus in a text box inside a ppapi plug-in. Otherwise fall back on
- // checking the focused node in Blink.
- if (render_view_->HasIMETextFocus()) {
- node_has_focus = true;
- node_is_editable_text = true;
- } else {
- node_has_focus = !node.isNull();
- node_is_editable_text =
- node_has_focus && render_view_->IsEditableNode(node);
- }
-
- std::vector<AccessibilityHostMsg_EventParams> events;
- events.push_back(AccessibilityHostMsg_EventParams());
- AccessibilityHostMsg_EventParams& event = events[0];
-
- // If we want to update the browser's accessibility tree but not send a
- // native focus changed event, we can send a LayoutComplete
- // event, which doesn't post a native event on Windows.
- event.event_type =
- send_focus_event ? ui::AX_EVENT_FOCUS : ui::AX_EVENT_LAYOUT_COMPLETE;
-
- // Set the id that the event applies to: the root node if nothing
- // has focus, otherwise the focused node.
- event.id = node_has_focus ? next_id_ : 1;
-
- event.update.nodes.resize(2);
- ui::AXNodeData& root = event.update.nodes[0];
- ui::AXNodeData& child = event.update.nodes[1];
-
- // Always include the root of the tree, the document. It always has id 1.
- root.id = 1;
- root.role = ui::AX_ROLE_ROOT_WEB_AREA;
- root.state =
- (1 << ui::AX_STATE_READ_ONLY) |
- (1 << ui::AX_STATE_FOCUSABLE);
- if (!node_has_focus)
- root.state |= (1 << ui::AX_STATE_FOCUSED);
- root.location = gfx::Rect(render_view_->size());
- root.child_ids.push_back(next_id_);
-
- child.id = next_id_;
- child.role = ui::AX_ROLE_GROUP;
-
- if (!node.isNull() && node.isElementNode()) {
- child.location = gfx::Rect(
- const_cast<WebNode&>(node).to<WebElement>().boundsInViewportSpace());
- } else if (render_view_->HasIMETextFocus()) {
- child.location = root.location;
- } else {
- child.location = gfx::Rect();
- }
-
- if (node_has_focus) {
- child.state =
- (1 << ui::AX_STATE_FOCUSABLE) |
- (1 << ui::AX_STATE_FOCUSED);
- if (!node_is_editable_text)
- child.state |= (1 << ui::AX_STATE_READ_ONLY);
- }
-
-#ifndef NDEBUG
- /**
- if (logging_) {
- VLOG(0) << "Accessibility update: \n"
- << "routing id=" << routing_id()
- << " event="
- << AccessibilityEventToString(event.event_type)
- << "\n" << event.nodes[0].DebugString(true);
- }
- **/
-#endif
-
- Send(new AccessibilityHostMsg_Events(routing_id(), events));
-
- // Increment the id, wrap back when we get past a million.
- next_id_++;
- if (next_id_ > 1000000)
- next_id_ = kInitialId;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h b/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h
deleted file mode 100644
index 806cd4bc94e..00000000000
--- a/chromium/content/renderer/accessibility/renderer_accessibility_focus_only.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_FOCUS_ONLY_H_
-#define CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_FOCUS_ONLY_H_
-
-#include "content/renderer/accessibility/renderer_accessibility.h"
-
-namespace content {
-
-// This is an accsessibility implementation that only handles whatever
-// node has focus, ignoring everything else. It's here because on Windows 8,
-// we need to use accessibility APIs to tell the operating system when a
-// touch should pop up the on-screen keyboard, but it's not worth the
-// performance overhead to enable full accessibility support.
-//
-// Here's how the on-screen keyboard works in Windows 8 "Metro-style" apps:
-//
-// 1. The user touches a control.
-// 2. If the application determines focus moves to an editable text control,
-// it sends a native focus event, pointing to a native accessibility object
-// with information about the control that was just focused.
-// 3. If the operating system sees that a focus event closely follows a
-// touch event, AND the bounding rectangle of the newly-focused control
-// contains the touch point, AND the focused object is a text control,
-// then Windows pops up the on-screen keyboard. In all other cases,
-// changing focus closes the on-screen keyboard.
-//
-// Alternatively:
-// 1. The user touches a text control that already has focus.
-// 2. The operating system uses accessibility APIs to query for the
-// currently focused object. If the touch falls within the bounds of
-// the focused object, the on-screen keyboard opens.
-//
-// In order to implement the accessibility APIs with minimal overhead, this
-// class builds a "fake" accessibility tree consisting of only a single root
-// node and optionally a single child node, representing the current focused
-// element in the page (if any). Every time focus changes, this fake tree is
-// sent from the renderer to the browser, along with a focus event - either
-// on the child, or on the root of the tree if nothing is focused.
-//
-// Sometimes, touching an element other than a text box will result in a
-// text box getting focus. We want the on-screen keyboard to pop up in those
-// cases, so we "cheat" more and always send the dimensions of the whole
-// window as the bounds of the child object. That way, a touch that leads
-// to a text box getting focus will always open the on-screen keyboard,
-// regardless of the relation between the touch location and the text box
-// bounds.
-class RendererAccessibilityFocusOnly : public RendererAccessibility {
- public:
- explicit RendererAccessibilityFocusOnly(RenderViewImpl* render_view);
- virtual ~RendererAccessibilityFocusOnly();
-
- // RendererAccessibility implementation.
- virtual void HandleWebAccessibilityEvent(
- const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
- virtual RendererAccessibilityType GetType() OVERRIDE;
-
- // RenderView::Observer implementation.
- virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE;
- virtual void DidFinishLoad(blink::WebLocalFrame* frame) OVERRIDE;
-
- private:
- void HandleFocusedNodeChanged(const blink::WebNode& node,
- bool send_focus_event);
-
- int next_id_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererAccessibilityFocusOnly);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_ACCESSIBILITY_RENDERER_ACCESSIBILITY_FOCUS_ONLY_H_
diff --git a/chromium/content/renderer/active_notification_tracker.cc b/chromium/content/renderer/active_notification_tracker.cc
index ff2d9cf6561..2a958a5877d 100644
--- a/chromium/content/renderer/active_notification_tracker.cc
+++ b/chromium/content/renderer/active_notification_tracker.cc
@@ -7,10 +7,8 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "third_party/WebKit/public/web/WebNotification.h"
-#include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
using blink::WebNotification;
-using blink::WebNotificationPermissionCallback;
namespace content {
@@ -66,18 +64,4 @@ void ActiveNotificationTracker::Clear() {
}
}
-WebNotificationPermissionCallback* ActiveNotificationTracker::GetCallback(
- int id) {
- return callback_table_.Lookup(id);
-}
-
-int ActiveNotificationTracker::RegisterPermissionRequest(
- WebNotificationPermissionCallback* callback) {
- return callback_table_.Add(callback);
-}
-
-void ActiveNotificationTracker::OnPermissionRequestComplete(int id) {
- callback_table_.Remove(id);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/active_notification_tracker.h b/chromium/content/renderer/active_notification_tracker.h
index b6305a56754..e3f64d16cd6 100644
--- a/chromium/content/renderer/active_notification_tracker.h
+++ b/chromium/content/renderer/active_notification_tracker.h
@@ -13,10 +13,6 @@
#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebNotification.h"
-namespace blink {
-class WebNotificationPermissionCallback;
-}
-
namespace content {
// This class manages the set of active Notification objects in either
@@ -33,22 +29,15 @@ class CONTENT_EXPORT ActiveNotificationTracker {
bool GetId(const blink::WebNotification& notification, int& id);
bool GetNotification(int id, blink::WebNotification* notification);
- // Methods for tracking active permission requests.
- int RegisterPermissionRequest(
- blink::WebNotificationPermissionCallback* callback);
- void OnPermissionRequestComplete(int id);
- blink::WebNotificationPermissionCallback* GetCallback(int id);
-
// Clears out all active notifications. Useful on page navigation.
void Clear();
private:
typedef std::map<blink::WebNotification, int> ReverseTable;
- // Tracking maps for active notifications and permission requests.
+ // Tracking maps for active notifications.
IDMap<blink::WebNotification> notification_table_;
ReverseTable reverse_notification_table_;
- IDMap<blink::WebNotificationPermissionCallback> callback_table_;
DISALLOW_COPY_AND_ASSIGN(ActiveNotificationTracker);
};
diff --git a/chromium/content/renderer/android/OWNERS b/chromium/content/renderer/android/OWNERS
index 29d0acf8c4e..c7eba94949b 100644
--- a/chromium/content/renderer/android/OWNERS
+++ b/chromium/content/renderer/android/OWNERS
@@ -1,3 +1,2 @@
-bulach@chromium.org
tedchoc@chromium.org
yfriedman@chromium.org
diff --git a/chromium/content/renderer/android/address_detector.h b/chromium/content/renderer/android/address_detector.h
index eea777f1329..e612339adf4 100644
--- a/chromium/content/renderer/android/address_detector.h
+++ b/chromium/content/renderer/android/address_detector.h
@@ -23,9 +23,9 @@ class AddressDetector : public ContentDetector {
const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
- std::string* content_text) OVERRIDE;
- virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
- virtual size_t GetMaximumContentLength() OVERRIDE;
+ std::string* content_text) override;
+ virtual GURL GetIntentURL(const std::string& content_text) override;
+ virtual size_t GetMaximumContentLength() override;
std::string GetContentText(const base::string16& text);
diff --git a/chromium/content/renderer/android/email_detector.h b/chromium/content/renderer/android/email_detector.h
index ff469e865cd..97b35c72189 100644
--- a/chromium/content/renderer/android/email_detector.h
+++ b/chromium/content/renderer/android/email_detector.h
@@ -27,9 +27,9 @@ class CONTENT_EXPORT EmailDetector : public ContentDetector {
const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
- std::string* content_text) OVERRIDE;
- virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
- virtual size_t GetMaximumContentLength() OVERRIDE;
+ std::string* content_text) override;
+ virtual GURL GetIntentURL(const std::string& content_text) override;
+ virtual size_t GetMaximumContentLength() override;
DISALLOW_COPY_AND_ASSIGN(EmailDetector);
};
diff --git a/chromium/content/renderer/android/phone_number_detector.h b/chromium/content/renderer/android/phone_number_detector.h
index 081a427628e..37413155df9 100644
--- a/chromium/content/renderer/android/phone_number_detector.h
+++ b/chromium/content/renderer/android/phone_number_detector.h
@@ -28,9 +28,9 @@ class CONTENT_EXPORT PhoneNumberDetector : public ContentDetector {
const base::string16::const_iterator& end,
size_t* start_pos,
size_t* end_pos,
- std::string* content_text) OVERRIDE;
- virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
- virtual size_t GetMaximumContentLength() OVERRIDE;
+ std::string* content_text) override;
+ virtual GURL GetIntentURL(const std::string& content_text) override;
+ virtual size_t GetMaximumContentLength() override;
const std::string region_code_;
diff --git a/chromium/content/renderer/android/renderer_date_time_picker.cc b/chromium/content/renderer/android/renderer_date_time_picker.cc
new file mode 100644
index 00000000000..15b833289d5
--- /dev/null
+++ b/chromium/content/renderer/android/renderer_date_time_picker.cc
@@ -0,0 +1,96 @@
+// Copyright 2014 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 "content/renderer/android/renderer_date_time_picker.h"
+
+#include "base/strings/string_util.h"
+#include "content/common/view_messages.h"
+#include "content/renderer/date_time_suggestion_builder.h"
+#include "content/renderer/render_view_impl.h"
+#include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h"
+#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
+#include "third_party/WebKit/public/web/WebDateTimeInputType.h"
+#include "ui/base/ime/text_input_type.h"
+
+using blink::WebString;
+
+namespace content {
+
+static ui::TextInputType ToTextInputType(int type) {
+ switch (type) {
+ case blink::WebDateTimeInputTypeDate:
+ return ui::TEXT_INPUT_TYPE_DATE;
+ break;
+ case blink::WebDateTimeInputTypeDateTime:
+ return ui::TEXT_INPUT_TYPE_DATE_TIME;
+ break;
+ case blink::WebDateTimeInputTypeDateTimeLocal:
+ return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
+ break;
+ case blink::WebDateTimeInputTypeMonth:
+ return ui::TEXT_INPUT_TYPE_MONTH;
+ break;
+ case blink::WebDateTimeInputTypeTime:
+ return ui::TEXT_INPUT_TYPE_TIME;
+ break;
+ case blink::WebDateTimeInputTypeWeek:
+ return ui::TEXT_INPUT_TYPE_WEEK;
+ break;
+ case blink::WebDateTimeInputTypeNone:
+ default:
+ return ui::TEXT_INPUT_TYPE_NONE;
+ }
+}
+
+RendererDateTimePicker::RendererDateTimePicker(
+ RenderViewImpl* sender,
+ const blink::WebDateTimeChooserParams& params,
+ blink::WebDateTimeChooserCompletion* completion)
+ : RenderViewObserver(sender),
+ chooser_params_(params),
+ chooser_completion_(completion) {
+}
+
+RendererDateTimePicker::~RendererDateTimePicker() {
+}
+
+bool RendererDateTimePicker::Open() {
+ ViewHostMsg_DateTimeDialogValue_Params message;
+ message.dialog_type = ToTextInputType(chooser_params_.type);
+ message.dialog_value = chooser_params_.doubleValue;
+ message.minimum = chooser_params_.minimum;
+ message.maximum = chooser_params_.maximum;
+ message.step = chooser_params_.step;
+ for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) {
+ message.suggestions.push_back(
+ DateTimeSuggestionBuilder::Build(chooser_params_.suggestions[i]));
+ }
+ Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message));
+ return true;
+}
+
+bool RendererDateTimePicker::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RendererDateTimePicker, message)
+ IPC_MESSAGE_HANDLER(ViewMsg_ReplaceDateTime, OnReplaceDateTime)
+ IPC_MESSAGE_HANDLER(ViewMsg_CancelDateTimeDialog, OnCancel)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void RendererDateTimePicker::OnReplaceDateTime(double value) {
+ if (chooser_completion_)
+ chooser_completion_->didChooseValue(value);
+ static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
+}
+
+void RendererDateTimePicker::OnCancel() {
+ if (chooser_completion_)
+ chooser_completion_->didCancelChooser();
+ static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/android/renderer_date_time_picker.h b/chromium/content/renderer/android/renderer_date_time_picker.h
new file mode 100644
index 00000000000..481d288c055
--- /dev/null
+++ b/chromium/content/renderer/android/renderer_date_time_picker.h
@@ -0,0 +1,46 @@
+// Copyright 2014 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 CONTENT_RENDERER_ANDROID_RENDERER_DATE_TIME_PICKER_H_
+#define CONTENT_RENDERER_ANDROID_RENDERER_DATE_TIME_PICKER_H_
+
+#include "base/basictypes.h"
+#include "content/public/renderer/render_view_observer.h"
+#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
+
+struct ViewHostMsg_DateTimeDialogValue_Params;
+
+namespace blink {
+class WebDateTimeChooserCompletion;
+} // namespace blink
+
+namespace content {
+class RenderViewImpl;
+
+class RendererDateTimePicker : public RenderViewObserver {
+ public:
+ RendererDateTimePicker(
+ RenderViewImpl* sender,
+ const blink::WebDateTimeChooserParams& params,
+ blink::WebDateTimeChooserCompletion* completion);
+ virtual ~RendererDateTimePicker();
+
+ bool Open();
+
+ private:
+ void OnReplaceDateTime(double value);
+ void OnCancel();
+
+ // RenderViewObserver
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
+
+ blink::WebDateTimeChooserParams chooser_params_;
+ blink::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us
+
+ DISALLOW_COPY_AND_ASSIGN(RendererDateTimePicker);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_ANDROID_RENDERER_DATE_TIME_PICKER_H_
diff --git a/chromium/content/renderer/android/synchronous_compositor_factory.h b/chromium/content/renderer/android/synchronous_compositor_factory.h
index 88908bafb52..9653bc265fd 100644
--- a/chromium/content/renderer/android/synchronous_compositor_factory.h
+++ b/chromium/content/renderer/android/synchronous_compositor_factory.h
@@ -21,6 +21,7 @@ class OutputSurface;
namespace webkit {
namespace gpu {
class ContextProviderWebContext;
+class WebGraphicsContext3DInProcessCommandBufferImpl;
}
}
@@ -28,6 +29,7 @@ namespace content {
class InputHandlerManagerClient;
class StreamTextureFactory;
+class FrameSwapMessageQueue;
// Decouples creation from usage of the parts needed for the synchonous
// compositor rendering path. In practice this is only used in single
@@ -44,17 +46,21 @@ class SynchronousCompositorFactory {
GetCompositorMessageLoop() = 0;
virtual bool RecordFullLayer() = 0;
virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
- int routing_id) = 0;
+ int routing_id,
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue) = 0;
// The factory maintains ownership of the returned interface.
virtual InputHandlerManagerClient* GetInputHandlerManagerClient() = 0;
virtual scoped_refptr<webkit::gpu::ContextProviderWebContext>
- GetSharedOffscreenContextProviderForMainThread() = 0;
+ CreateOffscreenContextProvider(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ const std::string& debug_name) = 0;
virtual scoped_refptr<StreamTextureFactory> CreateStreamTextureFactory(
int frame_id) = 0;
- virtual blink::WebGraphicsContext3D* CreateOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes) = 0;
+ virtual webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl*
+ CreateOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes) = 0;
protected:
SynchronousCompositorFactory() {}
diff --git a/chromium/content/renderer/battery_status/battery_status_dispatcher.cc b/chromium/content/renderer/battery_status/battery_status_dispatcher.cc
index e6ab56e2b5f..e7496113d7e 100644
--- a/chromium/content/renderer/battery_status/battery_status_dispatcher.cc
+++ b/chromium/content/renderer/battery_status/battery_status_dispatcher.cc
@@ -2,54 +2,35 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "battery_status_dispatcher.h"
+#include "content/renderer/battery_status/battery_status_dispatcher.h"
-#include "base/logging.h"
-#include "content/common/battery_status_messages.h"
-#include "content/renderer/render_thread_impl.h"
+#include "content/public/common/service_registry.h"
+#include "content/public/renderer/render_thread.h"
#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
namespace content {
-BatteryStatusDispatcher::BatteryStatusDispatcher(RenderThread* thread)
- : listener_(0) {
- if (thread)
- thread->AddObserver(this);
-}
+BatteryStatusDispatcher::BatteryStatusDispatcher(
+ blink::WebBatteryStatusListener* listener)
+ : listener_(listener) {
+ DCHECK(listener_);
-BatteryStatusDispatcher::~BatteryStatusDispatcher() {
- if (listener_)
- Stop();
+ RenderThread::Get()->GetServiceRegistry()->ConnectToRemoteService(&monitor_);
+ monitor_.set_client(this);
}
-bool BatteryStatusDispatcher::SetListener(
- blink::WebBatteryStatusListener* listener) {
- listener_ = listener;
- return listener ? Start() : Stop();
-}
-
-bool BatteryStatusDispatcher::OnControlMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(BatteryStatusDispatcher, message)
- IPC_MESSAGE_HANDLER(BatteryStatusMsg_DidChange, OnDidChange)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-bool BatteryStatusDispatcher::Start() {
- return RenderThread::Get()->Send(new BatteryStatusHostMsg_Start());
-}
-
-bool BatteryStatusDispatcher::Stop() {
- return RenderThread::Get()->Send(new BatteryStatusHostMsg_Stop());
+BatteryStatusDispatcher::~BatteryStatusDispatcher() {
}
-void BatteryStatusDispatcher::OnDidChange(
- const blink::WebBatteryStatus& status) {
- if (listener_)
- listener_->updateBatteryStatus(status);
+void BatteryStatusDispatcher::DidChange(
+ device::BatteryStatusPtr battery_status) {
+ DCHECK(battery_status);
+ blink::WebBatteryStatus web_battery_status;
+ web_battery_status.charging = battery_status->charging;
+ web_battery_status.chargingTime = battery_status->charging_time;
+ web_battery_status.dischargingTime = battery_status->discharging_time;
+ web_battery_status.level = battery_status->level;
+ listener_->updateBatteryStatus(web_battery_status);
}
} // namespace content
diff --git a/chromium/content/renderer/battery_status/battery_status_dispatcher.h b/chromium/content/renderer/battery_status/battery_status_dispatcher.h
index 0358fa792d2..9843246874f 100644
--- a/chromium/content/renderer/battery_status/battery_status_dispatcher.h
+++ b/chromium/content/renderer/battery_status/battery_status_dispatcher.h
@@ -5,35 +5,30 @@
#ifndef CONTENT_RENDERER_BATTERY_STATUS_BATTERY_STATUS_DISPATCHER_H_
#define CONTENT_RENDERER_BATTERY_STATUS_BATTERY_STATUS_DISPATCHER_H_
-#include "content/public/renderer/render_process_observer.h"
+#include "base/macros.h"
+#include "content/common/content_export.h"
+#include "device/battery/battery_monitor.mojom.h"
namespace blink {
-class WebBatteryStatus;
class WebBatteryStatusListener;
}
namespace content {
-class RenderThread;
-class CONTENT_EXPORT BatteryStatusDispatcher : public RenderProcessObserver {
+class CONTENT_EXPORT BatteryStatusDispatcher
+ : public NON_EXPORTED_BASE(device::BatteryStatusObserver) {
public:
- explicit BatteryStatusDispatcher(RenderThread* thread);
- virtual ~BatteryStatusDispatcher();
-
- // RenderProcessObserver method.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
-
- // Sets the listener to receive battery status updates. Returns true if the
- // registration was successful.
- bool SetListener(blink::WebBatteryStatusListener* listener);
-
- protected:
- virtual bool Start();
- virtual bool Stop();
+ explicit BatteryStatusDispatcher(blink::WebBatteryStatusListener* listener);
+ ~BatteryStatusDispatcher() override;
private:
- void OnDidChange(const blink::WebBatteryStatus& status);
+ // BatteryStatusObserver method.
+ void DidChange(device::BatteryStatusPtr battery_status) override;
+
+ void Start();
+ void Stop();
+ device::BatteryMonitorPtr monitor_;
blink::WebBatteryStatusListener* listener_;
DISALLOW_COPY_AND_ASSIGN(BatteryStatusDispatcher);
diff --git a/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc b/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc
index ecbcf393f49..31d2c666f0f 100644
--- a/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc
+++ b/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/battery_status_messages.h"
+#include "content/public/test/mock_render_thread.h"
#include "content/public/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
@@ -20,7 +21,7 @@ class MockBatteryStatusListener : public blink::WebBatteryStatusListener {
// blink::WebBatteryStatusListener method.
virtual void updateBatteryStatus(
- const blink::WebBatteryStatus& status) OVERRIDE {
+ const blink::WebBatteryStatus& status) override {
status_ = status;
did_change_battery_status_ = true;
}
@@ -35,53 +36,16 @@ class MockBatteryStatusListener : public blink::WebBatteryStatusListener {
DISALLOW_COPY_AND_ASSIGN(MockBatteryStatusListener);
};
-class BatteryStatusDispatcherForTesting : public BatteryStatusDispatcher {
- public:
- BatteryStatusDispatcherForTesting()
- : BatteryStatusDispatcher(0),
- start_invoked_(false),
- stop_invoked_(false) { }
-
- virtual ~BatteryStatusDispatcherForTesting() { }
-
- bool start_invoked() const { return start_invoked_; }
- bool stop_invoked() const { return stop_invoked_; }
-
- protected:
- virtual bool Start() OVERRIDE {
- start_invoked_ = true;
- return true;
- }
-
- virtual bool Stop() OVERRIDE {
- stop_invoked_ = true;
- return true;
- }
-
+class BatteryStatusDispatcherTest : public testing::Test {
private:
- bool start_invoked_;
- bool stop_invoked_;
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusDispatcherForTesting);
+ // We need to create a MockRenderThread so RenderThread::Get() doesn't return
+ // null.
+ MockRenderThread render_thread_;
};
-TEST(BatteryStatusDispatcherTest, Start) {
- MockBatteryStatusListener listener;
- BatteryStatusDispatcherForTesting dispatcher;
-
- EXPECT_FALSE(dispatcher.start_invoked());
- EXPECT_FALSE(dispatcher.stop_invoked());
-
- dispatcher.SetListener(&listener);
- EXPECT_TRUE(dispatcher.start_invoked());
-
- dispatcher.SetListener(0);
- EXPECT_TRUE(dispatcher.stop_invoked());
-}
-
-TEST(BatteryStatusDispatcherTest, UpdateListener) {
+TEST_F(BatteryStatusDispatcherTest, UpdateListener) {
MockBatteryStatusListener listener;
- BatteryStatusDispatcherForTesting dispatcher;
+ BatteryStatusDispatcher dispatcher(0);
blink::WebBatteryStatus status;
status.charging = true;
@@ -89,8 +53,7 @@ TEST(BatteryStatusDispatcherTest, UpdateListener) {
status.dischargingTime = 200;
status.level = 0.5;
- dispatcher.SetListener(&listener);
- EXPECT_TRUE(dispatcher.start_invoked());
+ dispatcher.Start(&listener);
BatteryStatusMsg_DidChange message(status);
dispatcher.OnControlMessageReceived(message);
@@ -102,17 +65,15 @@ TEST(BatteryStatusDispatcherTest, UpdateListener) {
EXPECT_EQ(status.dischargingTime, received_status.dischargingTime);
EXPECT_EQ(status.level, received_status.level);
- dispatcher.SetListener(0);
- EXPECT_TRUE(dispatcher.stop_invoked());
+ dispatcher.Stop();
}
-TEST(BatteryStatusDispatcherTest, NoUpdateWhenNullListener) {
+TEST_F(BatteryStatusDispatcherTest, NoUpdateWhenNullListener) {
MockBatteryStatusListener listener;
- BatteryStatusDispatcherForTesting dispatcher;
+ BatteryStatusDispatcher dispatcher(0);
- dispatcher.SetListener(0);
- EXPECT_FALSE(dispatcher.start_invoked());
- EXPECT_TRUE(dispatcher.stop_invoked());
+ dispatcher.Start(0);
+ dispatcher.Stop();
blink::WebBatteryStatus status;
BatteryStatusMsg_DidChange message(status);
diff --git a/chromium/content/renderer/battery_status/fake_battery_status_dispatcher.cc b/chromium/content/renderer/battery_status/fake_battery_status_dispatcher.cc
deleted file mode 100644
index 06350949c5b..00000000000
--- a/chromium/content/renderer/battery_status/fake_battery_status_dispatcher.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 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 "fake_battery_status_dispatcher.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
-
-namespace content {
-
-FakeBatteryStatusDispatcher::FakeBatteryStatusDispatcher() : listener_(0) {
-}
-
-void FakeBatteryStatusDispatcher::SetListener(
- blink::WebBatteryStatusListener* listener) {
- listener_ = listener;
-}
-
-void FakeBatteryStatusDispatcher::PostBatteryStatusChange(
- const blink::WebBatteryStatus& status) {
- if (!listener_)
- return;
-
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(&blink::WebBatteryStatusListener::updateBatteryStatus,
- base::Unretained(listener_),
- status));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/battery_status/fake_battery_status_dispatcher.h b/chromium/content/renderer/battery_status/fake_battery_status_dispatcher.h
deleted file mode 100644
index cddd6d8e5c1..00000000000
--- a/chromium/content/renderer/battery_status/fake_battery_status_dispatcher.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_BATTERY_STATUS_FAKE_BATTERY_STATUS_DISPATCHER_H_
-#define CONTENT_RENDERER_BATTERY_STATUS_FAKE_BATTERY_STATUS_DISPATCHER_H_
-
-#include "base/macros.h"
-
-namespace blink {
-class WebBatteryStatus;
-class WebBatteryStatusListener;
-}
-
-namespace content {
-
-class FakeBatteryStatusDispatcher {
- public:
- FakeBatteryStatusDispatcher();
-
- void SetListener(blink::WebBatteryStatusListener* listener);
- void PostBatteryStatusChange(const blink::WebBatteryStatus& status);
-
- private:
- blink::WebBatteryStatusListener* listener_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeBatteryStatusDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BATTERY_STATUS_FAKE_BATTERY_STATUS_DISPATCHER_H_
diff --git a/chromium/content/renderer/bmp_image_decoder_unittest.cc b/chromium/content/renderer/bmp_image_decoder_unittest.cc
index a2491263615..14193cccd2e 100644
--- a/chromium/content/renderer/bmp_image_decoder_unittest.cc
+++ b/chromium/content/renderer/bmp_image_decoder_unittest.cc
@@ -10,7 +10,7 @@ class BMPImageDecoderTest : public ImageDecoderTest {
BMPImageDecoderTest() : ImageDecoderTest("bmp") { }
protected:
- virtual blink::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE {
+ blink::WebImageDecoder* CreateWebKitImageDecoder() const override {
return new blink::WebImageDecoder(blink::WebImageDecoder::TypeBMP);
}
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index 6cb0bfbc93a..39e49d25a33 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -13,8 +13,8 @@
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/browser_plugin/browser_plugin_bindings.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/child_frame_compositing_helper.h"
#include "content/renderer/cursor_utils.h"
@@ -22,276 +22,138 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/sad_plugin.h"
#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/events/keycodes/keyboard_codes.h"
using blink::WebCanvas;
using blink::WebPluginContainer;
-using blink::WebPluginParams;
using blink::WebPoint;
using blink::WebRect;
using blink::WebURL;
using blink::WebVector;
+namespace {
+typedef std::map<blink::WebPluginContainer*, content::BrowserPlugin*>
+ PluginContainerMap;
+static base::LazyInstance<PluginContainerMap> g_plugin_container_map =
+ LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
namespace content {
+// static
+BrowserPlugin* BrowserPlugin::GetFromNode(blink::WebNode& node) {
+ blink::WebPluginContainer* container = node.pluginContainer();
+ if (!container)
+ return NULL;
+
+ PluginContainerMap* browser_plugins = g_plugin_container_map.Pointer();
+ PluginContainerMap::iterator it = browser_plugins->find(container);
+ return it == browser_plugins->end() ? NULL : it->second;
+}
+
BrowserPlugin::BrowserPlugin(RenderViewImpl* render_view,
blink::WebFrame* frame,
- bool auto_navigate)
- : guest_instance_id_(browser_plugin::kInstanceIDNone),
- attached_(false),
+ scoped_ptr<BrowserPluginDelegate> delegate)
+ : attached_(false),
+ attach_pending_(false),
render_view_(render_view->AsWeakPtr()),
render_view_routing_id_(render_view->GetRoutingID()),
container_(NULL),
- paint_ack_received_(true),
last_device_scale_factor_(GetDeviceScaleFactor()),
sad_guest_(NULL),
guest_crashed_(false),
- is_auto_size_state_dirty_(false),
- content_window_routing_id_(MSG_ROUTING_NONE),
plugin_focused_(false),
visible_(true),
- auto_navigate_(auto_navigate),
mouse_locked_(false),
+ ready_(false),
browser_plugin_manager_(render_view->GetBrowserPluginManager()),
- embedder_frame_url_(frame->document().url()),
+ browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
+ contents_opaque_(true),
+ delegate_(delegate.Pass()),
weak_ptr_factory_(this) {
+ browser_plugin_instance_id_ = browser_plugin_manager()->GetNextInstanceID();
+
+ if (delegate_)
+ delegate_->SetElementInstanceID(browser_plugin_instance_id_);
}
BrowserPlugin::~BrowserPlugin() {
- // If the BrowserPlugin has never navigated then the browser process and
- // BrowserPluginManager don't know about it and so there is nothing to do
- // here.
- if (!HasGuestInstanceID())
- return;
- browser_plugin_manager()->RemoveBrowserPlugin(guest_instance_id_);
- browser_plugin_manager()->Send(
- new BrowserPluginHostMsg_PluginDestroyed(render_view_routing_id_,
- guest_instance_id_));
+ if (compositing_helper_.get())
+ compositing_helper_->OnContainerDestroy();
+
+ browser_plugin_manager()->RemoveBrowserPlugin(browser_plugin_instance_id_);
}
bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_Attach_ACK, OnAttachACK)
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_BuffersSwapped, OnBuffersSwapped)
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped,
OnCompositorFrameSwapped(message))
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_CopyFromCompositingSurface,
- OnCopyFromCompositingSurface)
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestContentWindowReady,
- OnGuestContentWindowReady)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetContentsOpaque, OnSetContentsOpaque)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
+ IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetTooltipText, OnSetTooltipText)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents,
OnShouldAcceptTouchEvents)
- IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdateRect, OnUpdateRect)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void BrowserPlugin::UpdateDOMAttribute(const std::string& attribute_name,
- const std::string& attribute_value) {
+ const base::string16& attribute_value) {
if (!container())
return;
blink::WebElement element = container()->element();
blink::WebString web_attribute_name =
blink::WebString::fromUTF8(attribute_name);
- if (!HasDOMAttribute(attribute_name) ||
- (std::string(element.getAttribute(web_attribute_name).utf8()) !=
- attribute_value)) {
- element.setAttribute(web_attribute_name,
- blink::WebString::fromUTF8(attribute_value));
- }
-}
-
-void BrowserPlugin::RemoveDOMAttribute(const std::string& attribute_name) {
- if (!container())
- return;
-
- container()->element().removeAttribute(
- blink::WebString::fromUTF8(attribute_name));
-}
-
-std::string BrowserPlugin::GetDOMAttributeValue(
- const std::string& attribute_name) const {
- if (!container())
- return std::string();
-
- return container()->element().getAttribute(
- blink::WebString::fromUTF8(attribute_name)).utf8();
-}
-
-bool BrowserPlugin::HasDOMAttribute(const std::string& attribute_name) const {
- if (!container())
- return false;
-
- return container()->element().hasAttribute(
- blink::WebString::fromUTF8(attribute_name));
-}
-
-bool BrowserPlugin::GetAllowTransparencyAttribute() const {
- return HasDOMAttribute(browser_plugin::kAttributeAllowTransparency);
-}
-
-bool BrowserPlugin::GetAutoSizeAttribute() const {
- return HasDOMAttribute(browser_plugin::kAttributeAutoSize);
-}
-
-int BrowserPlugin::GetMaxHeightAttribute() const {
- int max_height;
- base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMaxHeight),
- &max_height);
- return max_height;
-}
-
-int BrowserPlugin::GetMaxWidthAttribute() const {
- int max_width;
- base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMaxWidth),
- &max_width);
- return max_width;
-}
-
-int BrowserPlugin::GetMinHeightAttribute() const {
- int min_height;
- base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMinHeight),
- &min_height);
- return min_height;
+ element.setAttribute(web_attribute_name, attribute_value);
}
-int BrowserPlugin::GetMinWidthAttribute() const {
- int min_width;
- base::StringToInt(GetDOMAttributeValue(browser_plugin::kAttributeMinWidth),
- &min_width);
- return min_width;
-}
-
-int BrowserPlugin::GetAdjustedMaxHeight() const {
- int max_height = GetMaxHeightAttribute();
- return max_height ? max_height : height();
-}
-
-int BrowserPlugin::GetAdjustedMaxWidth() const {
- int max_width = GetMaxWidthAttribute();
- return max_width ? max_width : width();
-}
-
-int BrowserPlugin::GetAdjustedMinHeight() const {
- int min_height = GetMinHeightAttribute();
- // FrameView.cpp does not allow this value to be <= 0, so when the value is
- // unset (or set to 0), we set it to the container size.
- min_height = min_height ? min_height : height();
- // For autosize, minHeight should not be bigger than maxHeight.
- return std::min(min_height, GetAdjustedMaxHeight());
-}
-
-int BrowserPlugin::GetAdjustedMinWidth() const {
- int min_width = GetMinWidthAttribute();
- // FrameView.cpp does not allow this value to be <= 0, so when the value is
- // unset (or set to 0), we set it to the container size.
- min_width = min_width ? min_width : width();
- // For autosize, minWidth should not be bigger than maxWidth.
- return std::min(min_width, GetAdjustedMaxWidth());
-}
-
-void BrowserPlugin::ParseAllowTransparencyAttribute() {
- if (!HasGuestInstanceID())
- return;
-
- bool opaque = !GetAllowTransparencyAttribute();
-
- if (compositing_helper_)
- compositing_helper_->SetContentsOpaque(opaque);
-
- browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetContentsOpaque(
- render_view_routing_id_,
- guest_instance_id_,
- opaque));
-}
-
-void BrowserPlugin::ParseAutoSizeAttribute() {
- last_view_size_ = plugin_size();
- is_auto_size_state_dirty_ = true;
- UpdateGuestAutoSizeState(GetAutoSizeAttribute());
-}
-
-void BrowserPlugin::PopulateAutoSizeParameters(
- BrowserPluginHostMsg_AutoSize_Params* params, bool auto_size_enabled) {
- params->enable = auto_size_enabled;
- // No need to populate the params if autosize is off.
- if (auto_size_enabled) {
- params->max_size = gfx::Size(GetAdjustedMaxWidth(), GetAdjustedMaxHeight());
- params->min_size = gfx::Size(GetAdjustedMinWidth(), GetAdjustedMinHeight());
-
- if (max_auto_size_ != params->max_size)
- is_auto_size_state_dirty_ = true;
-
- max_auto_size_ = params->max_size;
- } else {
- max_auto_size_ = gfx::Size();
- }
-}
-
-void BrowserPlugin::UpdateGuestAutoSizeState(bool auto_size_enabled) {
- // If we haven't yet heard back from the guest about the last resize request,
- // then we don't issue another request until we do in
- // BrowserPlugin::OnUpdateRect.
- if (!HasGuestInstanceID() || !paint_ack_received_)
- return;
-
- BrowserPluginHostMsg_AutoSize_Params auto_size_params;
- BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params;
- if (auto_size_enabled) {
- GetSizeParams(&auto_size_params, &resize_guest_params, true);
- } else {
- GetSizeParams(NULL, &resize_guest_params, true);
+void BrowserPlugin::Attach() {
+ if (ready()) {
+ attached_ = false;
+ guest_crashed_ = false;
+ EnableCompositing(false);
+ if (compositing_helper_.get()) {
+ compositing_helper_->OnContainerDestroy();
+ compositing_helper_ = NULL;
+ }
}
- paint_ack_received_ = false;
- browser_plugin_manager()->Send(
- new BrowserPluginHostMsg_SetAutoSize(render_view_routing_id_,
- guest_instance_id_,
- auto_size_params,
- resize_guest_params));
-}
-
-void BrowserPlugin::Attach(int guest_instance_id,
- scoped_ptr<base::DictionaryValue> extra_params) {
- CHECK(guest_instance_id != browser_plugin::kInstanceIDNone);
-
- // If this BrowserPlugin is already attached to a guest, then do nothing.
- if (HasGuestInstanceID())
- return;
-
- // This API may be called directly without setting the src attribute.
- // In that case, we need to make sure we don't allocate another instance ID.
- guest_instance_id_ = guest_instance_id;
- browser_plugin_manager()->AddBrowserPlugin(guest_instance_id, this);
+ // TODO(fsamuel): Add support for reattachment.
BrowserPluginHostMsg_Attach_Params attach_params;
attach_params.focused = ShouldGuestBeFocused();
attach_params.visible = visible_;
- attach_params.opaque = !GetAllowTransparencyAttribute();
- attach_params.embedder_frame_url = embedder_frame_url_;
attach_params.origin = plugin_rect().origin();
- GetSizeParams(&attach_params.auto_size_params,
- &attach_params.resize_guest_params,
- false);
+ attach_params.is_full_page_plugin = false;
+ if (container()) {
+ blink::WebLocalFrame* frame = container()->element().document().frame();
+ attach_params.is_full_page_plugin =
+ frame->view()->mainFrame()->document().isPluginDocument();
+ }
+ gfx::Size view_size(width(), height());
+ if (!view_size.IsEmpty()) {
+ PopulateResizeGuestParameters(view_size,
+ &attach_params.resize_guest_params);
+ }
+ browser_plugin_manager()->Send(new BrowserPluginHostMsg_Attach(
+ render_view_routing_id_,
+ browser_plugin_instance_id_,
+ attach_params));
- browser_plugin_manager()->Send(
- new BrowserPluginHostMsg_Attach(render_view_routing_id_,
- guest_instance_id_, attach_params,
- *extra_params));
+ attach_pending_ = true;
}
void BrowserPlugin::DidCommitCompositorFrame() {
@@ -299,31 +161,26 @@ void BrowserPlugin::DidCommitCompositorFrame() {
compositing_helper_->DidCommitCompositorFrame();
}
-void BrowserPlugin::OnAdvanceFocus(int guest_instance_id, bool reverse) {
- DCHECK(render_view_.get());
+void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
+ bool reverse) {
+ DCHECK(render_view_);
render_view_->GetWebView()->advanceFocus(reverse);
}
-void BrowserPlugin::OnAttachACK(int guest_instance_id) {
+void BrowserPlugin::OnAttachACK(int browser_plugin_instance_id) {
+ DCHECK(!attached());
attached_ = true;
-}
-
-void BrowserPlugin::OnBuffersSwapped(
- int instance_id,
- const FrameMsg_BuffersSwapped_Params& params) {
- EnableCompositing(true);
-
- compositing_helper_->OnBuffersSwapped(params.size,
- params.mailbox,
- params.gpu_route_id,
- params.gpu_host_id,
- GetDeviceScaleFactor());
+ attach_pending_ = false;
}
void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
BrowserPluginMsg_CompositorFrameSwapped::Param param;
if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message, &param))
return;
+ // Note that there is no need to send ACK for this message.
+ // If the guest has updated pixels then it is no longer crashed.
+ guest_crashed_ = false;
+
scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
param.b.frame.AssignTo(frame.get());
@@ -335,30 +192,7 @@ void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
param.b.shared_memory_handle);
}
-void BrowserPlugin::OnCopyFromCompositingSurface(int guest_instance_id,
- int request_id,
- gfx::Rect source_rect,
- gfx::Size dest_size) {
- if (!compositing_helper_) {
- browser_plugin_manager()->Send(
- new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
- render_view_routing_id_,
- guest_instance_id_,
- request_id,
- SkBitmap()));
- return;
- }
- compositing_helper_->CopyFromCompositingSurface(request_id, source_rect,
- dest_size);
-}
-
-void BrowserPlugin::OnGuestContentWindowReady(int guest_instance_id,
- int content_window_routing_id) {
- DCHECK(content_window_routing_id != MSG_ROUTING_NONE);
- content_window_routing_id_ = content_window_routing_id;
-}
-
-void BrowserPlugin::OnGuestGone(int guest_instance_id) {
+void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
guest_crashed_ = true;
// Turn off compositing so we can display the sad graphic. Changes to
@@ -375,12 +209,21 @@ void BrowserPlugin::OnGuestGone(int guest_instance_id) {
weak_ptr_factory_.GetWeakPtr()));
}
-void BrowserPlugin::OnSetCursor(int guest_instance_id,
+void BrowserPlugin::OnSetContentsOpaque(int browser_plugin_instance_id,
+ bool opaque) {
+ if (contents_opaque_ == opaque)
+ return;
+ contents_opaque_ = opaque;
+ if (compositing_helper_.get())
+ compositing_helper_->SetContentsOpaque(opaque);
+}
+
+void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id,
const WebCursor& cursor) {
cursor_ = cursor;
}
-void BrowserPlugin::OnSetMouseLock(int guest_instance_id,
+void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id,
bool enable) {
if (enable) {
if (mouse_locked_)
@@ -395,86 +238,21 @@ void BrowserPlugin::OnSetMouseLock(int guest_instance_id,
}
}
-void BrowserPlugin::OnShouldAcceptTouchEvents(int guest_instance_id,
- bool accept) {
- if (container()) {
- container()->requestTouchEventType(accept ?
- blink::WebPluginContainer::TouchEventRequestTypeRaw :
- blink::WebPluginContainer::TouchEventRequestTypeNone);
- }
-}
-
-void BrowserPlugin::OnUpdateRect(
- int guest_instance_id,
- const BrowserPluginMsg_UpdateRect_Params& params) {
- // Note that there is no need to send ACK for this message.
- // If the guest has updated pixels then it is no longer crashed.
- guest_crashed_ = false;
-
- bool auto_size = GetAutoSizeAttribute();
- // We receive a resize ACK in regular mode, but not in autosize.
- // In Compositing mode, we need to do it here so we can continue sending
- // resize messages when needed.
- if (params.is_resize_ack || (auto_size || is_auto_size_state_dirty_))
- paint_ack_received_ = true;
-
- bool was_auto_size_state_dirty = auto_size && is_auto_size_state_dirty_;
- is_auto_size_state_dirty_ = false;
-
- if ((!auto_size && (width() != params.view_size.width() ||
- height() != params.view_size.height())) ||
- (auto_size && was_auto_size_state_dirty) ||
- GetDeviceScaleFactor() != params.scale_factor) {
- UpdateGuestAutoSizeState(auto_size);
- return;
- }
-
- if (auto_size && (params.view_size != last_view_size_))
- last_view_size_ = params.view_size;
-
- BrowserPluginHostMsg_AutoSize_Params auto_size_params;
- BrowserPluginHostMsg_ResizeGuest_Params resize_guest_params;
-
- // BrowserPluginHostMsg_UpdateRect_ACK is used by both the compositing and
- // software paths to piggyback updated autosize parameters.
- if (auto_size)
- PopulateAutoSizeParameters(&auto_size_params, auto_size);
-
- browser_plugin_manager()->Send(
- new BrowserPluginHostMsg_SetAutoSize(render_view_routing_id_,
- guest_instance_id_,
- auto_size_params,
- resize_guest_params));
+void BrowserPlugin::OnSetTooltipText(int instance_id,
+ const base::string16& tooltip_text) {
+ // Show tooltip text by setting the BrowserPlugin's |title| attribute.
+ UpdateDOMAttribute("title", tooltip_text);
}
-void BrowserPlugin::ParseSizeContraintsChanged() {
- bool auto_size = GetAutoSizeAttribute();
- if (auto_size) {
- is_auto_size_state_dirty_ = true;
- UpdateGuestAutoSizeState(true);
+void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
+ bool accept) {
+ if (container()) {
+ container()->requestTouchEventType(
+ accept ? WebPluginContainer::TouchEventRequestTypeRaw
+ : WebPluginContainer::TouchEventRequestTypeNone);
}
}
-bool BrowserPlugin::InAutoSizeBounds(const gfx::Size& size) const {
- return size.width() <= GetAdjustedMaxWidth() &&
- size.height() <= GetAdjustedMaxHeight();
-}
-
-NPObject* BrowserPlugin::GetContentWindow() const {
- if (content_window_routing_id_ == MSG_ROUTING_NONE)
- return NULL;
- RenderViewImpl* guest_render_view = RenderViewImpl::FromRoutingID(
- content_window_routing_id_);
- if (!guest_render_view)
- return NULL;
- blink::WebFrame* guest_frame = guest_render_view->GetWebView()->mainFrame();
- return guest_frame->windowObject();
-}
-
-bool BrowserPlugin::HasGuestInstanceID() const {
- return guest_instance_id_ != browser_plugin::kInstanceIDNone;
-}
-
void BrowserPlugin::ShowSadGraphic() {
// If the BrowserPlugin is scheduled to be deleted, then container_ will be
// NULL so we shouldn't attempt to access it.
@@ -483,41 +261,41 @@ void BrowserPlugin::ShowSadGraphic() {
}
float BrowserPlugin::GetDeviceScaleFactor() const {
- if (!render_view_.get())
+ if (!render_view_)
return 1.0f;
return render_view_->GetWebView()->deviceScaleFactor();
}
-void BrowserPlugin::UpdateDeviceScaleFactor(float device_scale_factor) {
- if (last_device_scale_factor_ == device_scale_factor || !paint_ack_received_)
+void BrowserPlugin::UpdateDeviceScaleFactor() {
+ if (last_device_scale_factor_ == GetDeviceScaleFactor())
return;
BrowserPluginHostMsg_ResizeGuest_Params params;
- PopulateResizeGuestParameters(&params, plugin_size(), true);
+ PopulateResizeGuestParameters(plugin_size(), &params);
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
params));
}
void BrowserPlugin::UpdateGuestFocusState() {
- if (!HasGuestInstanceID())
+ if (!ready())
return;
bool should_be_focused = ShouldGuestBeFocused();
browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetFocus(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
should_be_focused));
}
bool BrowserPlugin::ShouldGuestBeFocused() const {
bool embedder_focused = false;
- if (render_view_.get())
+ if (render_view_)
embedder_focused = render_view_->has_focus();
return plugin_focused_ && embedder_focused;
}
-blink::WebPluginContainer* BrowserPlugin::container() const {
+WebPluginContainer* BrowserPlugin::container() const {
return container_;
}
@@ -525,35 +303,38 @@ bool BrowserPlugin::initialize(WebPluginContainer* container) {
if (!container)
return false;
- // Tell |container| to allow this plugin to use script objects.
- npp_.reset(new NPP_t);
- container->allowScriptObjects();
-
- bindings_.reset(new BrowserPluginBindings(this));
container_ = container;
container_->setWantsWheelEvents(true);
- // This is a way to notify observers of our attributes that we have the
- // bindings ready. This also means that this plugin is available in render
- // tree.
- UpdateDOMAttribute("internalbindings", "true");
+
+ g_plugin_container_map.Get().insert(std::make_pair(container_, this));
+
+ browser_plugin_manager()->AddBrowserPlugin(browser_plugin_instance_id_, this);
+
+ // This is a way to notify observers of our attributes that this plugin is
+ // available in render tree.
+ // TODO(lazyboy): This should be done through the delegate instead. Perhaps
+ // by firing an event from there.
+ UpdateDOMAttribute(
+ "internalinstanceid",
+ base::UTF8ToUTF16(base::IntToString(browser_plugin_instance_id_)));
+
return true;
}
void BrowserPlugin::EnableCompositing(bool enable) {
- bool enabled = !!compositing_helper_;
+ bool enabled = !!compositing_helper_.get();
if (enabled == enable)
return;
if (enable) {
DCHECK(!compositing_helper_.get());
if (!compositing_helper_.get()) {
- compositing_helper_ =
- ChildFrameCompositingHelper::CreateCompositingHelperForBrowserPlugin(
- weak_ptr_factory_.GetWeakPtr());
+ compositing_helper_ = ChildFrameCompositingHelper::CreateForBrowserPlugin(
+ weak_ptr_factory_.GetWeakPtr());
}
}
compositing_helper_->EnableCompositing(enable);
- compositing_helper_->SetContentsOpaque(!GetAllowTransparencyAttribute());
+ compositing_helper_->SetContentsOpaque(contents_opaque_);
if (!enable) {
DCHECK(compositing_helper_.get());
@@ -563,35 +344,19 @@ void BrowserPlugin::EnableCompositing(bool enable) {
}
void BrowserPlugin::destroy() {
- // If the plugin was initialized then it has a valid |npp_| identifier, and
- // the |container_| must clear references to the plugin's script objects.
- DCHECK(!npp_ || container_);
- if (container_)
- container_->clearScriptObjects();
+ if (container_) {
+ // The BrowserPlugin's WebPluginContainer is deleted immediately after this
+ // call returns, so let's not keep a reference to it around.
+ g_plugin_container_map.Get().erase(container_);
+ }
- if (compositing_helper_.get())
- compositing_helper_->OnContainerDestroy();
container_ = NULL;
// Will be a no-op if the mouse is not currently locked.
- if (render_view_.get())
+ if (render_view_)
render_view_->mouse_lock_dispatcher()->OnLockTargetDestroyed(this);
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-NPObject* BrowserPlugin::scriptableObject() {
- if (!bindings_)
- return NULL;
-
- NPObject* browser_plugin_np_object(bindings_->np_object());
- // The object is expected to be retained before it is returned.
- blink::WebBindings::retainObject(browser_plugin_np_object);
- return browser_plugin_np_object;
-}
-
-NPP BrowserPlugin::pluginNPP() {
- return npp_.get();
-}
-
bool BrowserPlugin::supportsKeyboardFocus() const {
return true;
}
@@ -640,17 +405,15 @@ void BrowserPlugin::paint(WebCanvas* canvas, const WebRect& rect) {
bool BrowserPlugin::ShouldForwardToBrowserPlugin(
const IPC::Message& message) {
switch (message.type()) {
- case BrowserPluginMsg_AdvanceFocus::ID:
case BrowserPluginMsg_Attach_ACK::ID:
- case BrowserPluginMsg_BuffersSwapped::ID:
+ case BrowserPluginMsg_AdvanceFocus::ID:
case BrowserPluginMsg_CompositorFrameSwapped::ID:
- case BrowserPluginMsg_CopyFromCompositingSurface::ID:
- case BrowserPluginMsg_GuestContentWindowReady::ID:
case BrowserPluginMsg_GuestGone::ID:
+ case BrowserPluginMsg_SetContentsOpaque::ID:
case BrowserPluginMsg_SetCursor::ID:
case BrowserPluginMsg_SetMouseLock::ID:
+ case BrowserPluginMsg_SetTooltipText::ID:
case BrowserPluginMsg_ShouldAcceptTouchEvents::ID:
- case BrowserPluginMsg_UpdateRect::ID:
return true;
default:
break;
@@ -666,64 +429,40 @@ void BrowserPlugin::updateGeometry(
int old_width = width();
int old_height = height();
plugin_rect_ = window_rect;
+ if (!ready_) {
+ if (delegate_)
+ delegate_->Ready();
+ ready_ = true;
+ }
if (!attached())
return;
- // In AutoSize mode, guests don't care when the BrowserPlugin container is
- // resized. If |!paint_ack_received_|, then we are still waiting on a
- // previous resize to be ACK'ed and so we don't issue additional resizes
- // until the previous one is ACK'ed.
- // TODO(mthiesse): Assess the performance of calling GetAutoSizeAttribute() on
- // resize.
- if (!paint_ack_received_ ||
- (old_width == window_rect.width && old_height == window_rect.height) ||
- GetAutoSizeAttribute()) {
+ if (old_width == window_rect.width && old_height == window_rect.height) {
// Let the browser know about the updated view rect.
browser_plugin_manager()->Send(new BrowserPluginHostMsg_UpdateGeometry(
- render_view_routing_id_, guest_instance_id_, plugin_rect_));
+ render_view_routing_id_, browser_plugin_instance_id_, plugin_rect_));
return;
}
BrowserPluginHostMsg_ResizeGuest_Params params;
- PopulateResizeGuestParameters(&params, plugin_size(), false);
- paint_ack_received_ = false;
+ PopulateResizeGuestParameters(plugin_size(), &params);
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ResizeGuest(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
params));
}
void BrowserPlugin::PopulateResizeGuestParameters(
- BrowserPluginHostMsg_ResizeGuest_Params* params,
const gfx::Size& view_size,
- bool needs_repaint) {
- params->size_changed = true;
+ BrowserPluginHostMsg_ResizeGuest_Params* params) {
params->view_size = view_size;
- params->repaint = needs_repaint;
params->scale_factor = GetDeviceScaleFactor();
- if (last_device_scale_factor_ != params->scale_factor){
- DCHECK(params->repaint);
+ if (last_device_scale_factor_ != params->scale_factor) {
last_device_scale_factor_ = params->scale_factor;
+ params->repaint = true;
}
}
-void BrowserPlugin::GetSizeParams(
- BrowserPluginHostMsg_AutoSize_Params* auto_size_params,
- BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params,
- bool needs_repaint) {
- if (auto_size_params) {
- PopulateAutoSizeParameters(auto_size_params, GetAutoSizeAttribute());
- } else {
- max_auto_size_ = gfx::Size();
- }
- gfx::Size view_size = (auto_size_params && auto_size_params->enable) ?
- auto_size_params->max_size : gfx::Size(width(), height());
- if (view_size.IsEmpty())
- return;
- paint_ack_received_ = false;
- PopulateResizeGuestParameters(resize_guest_params, view_size, needs_repaint);
-}
-
void BrowserPlugin::updateFocus(bool focused) {
plugin_focused_ = focused;
UpdateGuestFocusState();
@@ -734,7 +473,7 @@ void BrowserPlugin::updateVisibility(bool visible) {
return;
visible_ = visible;
- if (!HasGuestInstanceID())
+ if (!ready())
return;
if (compositing_helper_.get())
@@ -742,7 +481,7 @@ void BrowserPlugin::updateVisibility(bool visible) {
browser_plugin_manager()->Send(new BrowserPluginHostMsg_SetVisibility(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
visible));
}
@@ -752,70 +491,27 @@ bool BrowserPlugin::acceptsInputEvents() {
bool BrowserPlugin::handleInputEvent(const blink::WebInputEvent& event,
blink::WebCursorInfo& cursor_info) {
- if (guest_crashed_ || !HasGuestInstanceID())
+ if (guest_crashed_ || !ready())
return false;
if (event.type == blink::WebInputEvent::ContextMenu)
return true;
- const blink::WebInputEvent* modified_event = &event;
- scoped_ptr<blink::WebTouchEvent> touch_event;
- if (blink::WebInputEvent::isTouchEventType(event.type)) {
- const blink::WebTouchEvent* orig_touch_event =
- static_cast<const blink::WebTouchEvent*>(&event);
-
- touch_event.reset(new blink::WebTouchEvent());
- memcpy(touch_event.get(), orig_touch_event, sizeof(blink::WebTouchEvent));
-
- // TODO(bokan): Blink passes back a WebGestureEvent with a touches,
- // changedTouches, and targetTouches lists; however, it doesn't set
- // the state field on the touches which is what the RenderWidget uses
- // to create a WebCore::TouchEvent. crbug.com/358132 tracks removing
- // these multiple lists from WebTouchEvent since they lead to misuse
- // like this and are functionally unused. In the mean time we'll setup
- // the state field here manually to fix multi-touch BrowserPlugins.
- for (size_t i = 0; i < touch_event->touchesLength; ++i) {
- blink::WebTouchPoint& touch = touch_event->touches[i];
- touch.state = blink::WebTouchPoint::StateStationary;
- for (size_t j = 0; j < touch_event->changedTouchesLength; ++j) {
- blink::WebTouchPoint& changed_touch = touch_event->changedTouches[j];
- if (touch.id == changed_touch.id) {
- touch.state = changed_touch.state;
- break;
- }
- }
- }
-
- // For End and Cancel, Blink gives BrowserPlugin a list of touches that
- // are down, but the browser process expects a list of all touches. We
- // modify these events here to match these expectations.
- if (event.type == blink::WebInputEvent::TouchEnd ||
- event.type == blink::WebInputEvent::TouchCancel) {
- if (touch_event->changedTouchesLength > 0) {
- memcpy(&touch_event->touches[touch_event->touchesLength],
- &touch_event->changedTouches,
- touch_event->changedTouchesLength * sizeof(blink::WebTouchPoint));
- touch_event->touchesLength += touch_event->changedTouchesLength;
- }
- }
- modified_event = touch_event.get();
- }
-
if (blink::WebInputEvent::isKeyboardEventType(event.type) &&
!edit_commands_.empty()) {
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
edit_commands_));
edit_commands_.clear();
}
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
plugin_rect_,
- modified_event));
+ &event));
GetWebKitCursorInfo(cursor_, &cursor_info);
return true;
}
@@ -825,12 +521,12 @@ bool BrowserPlugin::handleDragStatusUpdate(blink::WebDragStatus drag_status,
blink::WebDragOperationsMask mask,
const blink::WebPoint& position,
const blink::WebPoint& screen) {
- if (guest_crashed_ || !HasGuestInstanceID())
+ if (guest_crashed_ || !ready())
return false;
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_DragStatusUpdate(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
drag_status,
DropDataBuilder::Build(drag_data),
mask,
@@ -843,17 +539,13 @@ void BrowserPlugin::didReceiveResponse(
}
void BrowserPlugin::didReceiveData(const char* data, int data_length) {
- if (auto_navigate_) {
- std::string value(data, data_length);
- html_string_ += value;
- }
+ if (delegate_)
+ delegate_->DidReceiveData(data, data_length);
}
void BrowserPlugin::didFinishLoading() {
- if (auto_navigate_) {
- // TODO(lazyboy): Make |auto_navigate_| stuff work.
- UpdateDOMAttribute(content::browser_plugin::kAttributeSrc, html_string_);
- }
+ if (delegate_)
+ delegate_->DidFinishLoading();
}
void BrowserPlugin::didFailLoading(const blink::WebURLError& error) {
@@ -872,7 +564,7 @@ void BrowserPlugin::didFailLoadingFrameRequest(
bool BrowserPlugin::executeEditCommand(const blink::WebString& name) {
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ExecuteEditCommand(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
name.utf8()));
// BrowserPlugin swallows edit commands.
@@ -891,7 +583,7 @@ bool BrowserPlugin::setComposition(
const blink::WebVector<blink::WebCompositionUnderline>& underlines,
int selectionStart,
int selectionEnd) {
- if (!HasGuestInstanceID())
+ if (!ready())
return false;
std::vector<blink::WebCompositionUnderline> std_underlines;
for (size_t i = 0; i < underlines.size(); ++i) {
@@ -899,7 +591,7 @@ bool BrowserPlugin::setComposition(
}
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeSetComposition(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
text.utf8(),
std_underlines,
selectionStart,
@@ -911,12 +603,12 @@ bool BrowserPlugin::setComposition(
bool BrowserPlugin::confirmComposition(
const blink::WebString& text,
blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) {
- if (!HasGuestInstanceID())
+ if (!ready())
return false;
bool keep_selection = (selectionBehavior == blink::WebWidget::KeepSelection);
browser_plugin_manager()->Send(new BrowserPluginHostMsg_ImeConfirmComposition(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
text.utf8(),
keep_selection));
// TODO(kochi): This assumes the IPC handling always succeeds.
@@ -924,12 +616,12 @@ bool BrowserPlugin::confirmComposition(
}
void BrowserPlugin::extendSelectionAndDelete(int before, int after) {
- if (!HasGuestInstanceID())
+ if (!ready())
return;
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_ExtendSelectionAndDelete(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
before,
after));
}
@@ -938,7 +630,7 @@ void BrowserPlugin::OnLockMouseACK(bool succeeded) {
mouse_locked_ = succeeded;
browser_plugin_manager()->Send(new BrowserPluginHostMsg_LockMouse_ACK(
render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
succeeded));
}
@@ -946,14 +638,14 @@ void BrowserPlugin::OnMouseLockLost() {
mouse_locked_ = false;
browser_plugin_manager()->Send(new BrowserPluginHostMsg_UnlockMouse_ACK(
render_view_routing_id_,
- guest_instance_id_));
+ browser_plugin_instance_id_));
}
bool BrowserPlugin::HandleMouseLockedInputEvent(
const blink::WebMouseEvent& event) {
browser_plugin_manager()->Send(
new BrowserPluginHostMsg_HandleInputEvent(render_view_routing_id_,
- guest_instance_id_,
+ browser_plugin_instance_id_,
plugin_rect_,
&event));
return true;
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index 925ee2384b3..d072e7b0d6f 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -10,20 +10,19 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
-#include "content/renderer/browser_plugin/browser_plugin_bindings.h"
#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDragStatus.h"
+#include "third_party/WebKit/public/web/WebNode.h"
#include "third_party/WebKit/public/web/WebWidget.h"
-struct BrowserPluginHostMsg_AutoSize_Params;
struct BrowserPluginHostMsg_ResizeGuest_Params;
-struct BrowserPluginMsg_UpdateRect_Params;
struct FrameMsg_BuffersSwapped_Params;
namespace content {
+class BrowserPluginDelegate;
class ChildFrameCompositingHelper;
class BrowserPluginManager;
class MockBrowserPlugin;
@@ -32,10 +31,13 @@ class CONTENT_EXPORT BrowserPlugin :
NON_EXPORTED_BASE(public blink::WebPlugin),
public MouseLockDispatcher::LockTarget {
public:
+ static BrowserPlugin* GetFromNode(blink::WebNode& node);
+
RenderViewImpl* render_view() const { return render_view_.get(); }
int render_view_routing_id() const { return render_view_routing_id_; }
- int guest_instance_id() const { return guest_instance_id_; }
+ int browser_plugin_instance_id() const { return browser_plugin_instance_id_; }
bool attached() const { return attached_; }
+ bool ready() const { return attached_ || attach_pending_; }
BrowserPluginManager* browser_plugin_manager() const {
return browser_plugin_manager_.get();
}
@@ -45,61 +47,27 @@ class CONTENT_EXPORT BrowserPlugin :
// Update Browser Plugin's DOM Node attribute |attribute_name| with the value
// |attribute_value|.
void UpdateDOMAttribute(const std::string& attribute_name,
- const std::string& attribute_value);
- // Remove the DOM Node attribute with the name |attribute_name|.
- void RemoveDOMAttribute(const std::string& attribute_name);
- // Get Browser Plugin's DOM Node attribute |attribute_name|'s value.
- std::string GetDOMAttributeValue(const std::string& attribute_name) const;
- // Checks if the attribute |attribute_name| exists in the DOM.
- bool HasDOMAttribute(const std::string& attribute_name) const;
-
- // Get the allowtransparency attribute value.
- bool GetAllowTransparencyAttribute() const;
- // Parse the allowtransparency attribute and adjust transparency of
- // BrowserPlugin accordingly.
- void ParseAllowTransparencyAttribute();
- // Get the autosize attribute value.
- bool GetAutoSizeAttribute() const;
- // Parses the autosize attribute value.
- void ParseAutoSizeAttribute();
- // Get the maxheight attribute value.
- int GetMaxHeightAttribute() const;
- // Get the maxwidth attribute value.
- int GetMaxWidthAttribute() const;
- // Get the minheight attribute value.
- int GetMinHeightAttribute() const;
- // Get the minwidth attribute value.
- int GetMinWidthAttribute() const;
- // Parse the minwidth, maxwidth, minheight, and maxheight attribute values.
- void ParseSizeContraintsChanged();
-
- bool InAutoSizeBounds(const gfx::Size& size) const;
-
- // Get the guest's DOMWindow proxy.
- NPObject* GetContentWindow() const;
+ const base::string16& attribute_value);
// Returns whether the guest process has crashed.
bool guest_crashed() const { return guest_crashed_; }
- // Returns whether this BrowserPlugin has allocated an instance ID.
- bool HasGuestInstanceID() const;
// Informs the guest of an updated focus state.
void UpdateGuestFocusState();
+
// Indicates whether the guest should be focused.
bool ShouldGuestBeFocused() const;
// Embedder's device scale factor changed, we need to update the guest
// renderer.
- void UpdateDeviceScaleFactor(float device_scale_factor);
+ void UpdateDeviceScaleFactor();
// A request to enable hardware compositing.
void EnableCompositing(bool enable);
// Provided that a guest instance ID has been allocated, this method attaches
- // this BrowserPlugin instance to that guest. |extra_params| are parameters
- // passed in by the content embedder to the browser process.
- void Attach(int guest_instance_id,
- scoped_ptr<base::DictionaryValue> extra_params);
+ // this BrowserPlugin instance to that guest.
+ void Attach();
// Notify the plugin about a compositor commit so that frame ACKs could be
// sent, if needed.
@@ -109,70 +77,66 @@ class CONTENT_EXPORT BrowserPlugin :
static bool ShouldForwardToBrowserPlugin(const IPC::Message& message);
// blink::WebPlugin implementation.
- virtual blink::WebPluginContainer* container() const OVERRIDE;
- virtual bool initialize(blink::WebPluginContainer* container) OVERRIDE;
- virtual void destroy() OVERRIDE;
- virtual NPObject* scriptableObject() OVERRIDE;
- virtual struct _NPP* pluginNPP() OVERRIDE;
- virtual bool supportsKeyboardFocus() const OVERRIDE;
- virtual bool supportsEditCommands() const OVERRIDE;
- virtual bool supportsInputMethod() const OVERRIDE;
- virtual bool canProcessDrag() const OVERRIDE;
+ virtual blink::WebPluginContainer* container() const override;
+ virtual bool initialize(blink::WebPluginContainer* container) override;
+ virtual void destroy() override;
+ virtual bool supportsKeyboardFocus() const override;
+ virtual bool supportsEditCommands() const override;
+ virtual bool supportsInputMethod() const override;
+ virtual bool canProcessDrag() const override;
virtual void paint(
blink::WebCanvas* canvas,
- const blink::WebRect& rect) OVERRIDE;
+ const blink::WebRect& rect) override;
virtual void updateGeometry(
const blink::WebRect& frame_rect,
const blink::WebRect& clip_rect,
const blink::WebVector<blink::WebRect>& cut_outs_rects,
- bool is_visible) OVERRIDE;
- virtual void updateFocus(bool focused) OVERRIDE;
- virtual void updateVisibility(bool visible) OVERRIDE;
- virtual bool acceptsInputEvents() OVERRIDE;
+ bool is_visible) override;
+ virtual void updateFocus(bool focused) override;
+ virtual void updateVisibility(bool visible) override;
+ virtual bool acceptsInputEvents() override;
virtual bool handleInputEvent(
const blink::WebInputEvent& event,
- blink::WebCursorInfo& cursor_info) OVERRIDE;
+ blink::WebCursorInfo& cursor_info) override;
virtual bool handleDragStatusUpdate(blink::WebDragStatus drag_status,
const blink::WebDragData& drag_data,
blink::WebDragOperationsMask mask,
const blink::WebPoint& position,
- const blink::WebPoint& screen) OVERRIDE;
+ const blink::WebPoint& screen) override;
virtual void didReceiveResponse(
- const blink::WebURLResponse& response) OVERRIDE;
- virtual void didReceiveData(const char* data, int data_length) OVERRIDE;
- virtual void didFinishLoading() OVERRIDE;
- virtual void didFailLoading(const blink::WebURLError& error) OVERRIDE;
+ const blink::WebURLResponse& response) override;
+ virtual void didReceiveData(const char* data, int data_length) override;
+ virtual void didFinishLoading() override;
+ virtual void didFailLoading(const blink::WebURLError& error) override;
virtual void didFinishLoadingFrameRequest(
const blink::WebURL& url,
- void* notify_data) OVERRIDE;
+ void* notify_data) override;
virtual void didFailLoadingFrameRequest(
const blink::WebURL& url,
void* notify_data,
- const blink::WebURLError& error) OVERRIDE;
- virtual bool executeEditCommand(const blink::WebString& name) OVERRIDE;
+ const blink::WebURLError& error) override;
+ virtual bool executeEditCommand(const blink::WebString& name) override;
virtual bool executeEditCommand(const blink::WebString& name,
- const blink::WebString& value) OVERRIDE;
+ const blink::WebString& value) override;
virtual bool setComposition(
const blink::WebString& text,
const blink::WebVector<blink::WebCompositionUnderline>& underlines,
int selectionStart,
- int selectionEnd) OVERRIDE;
+ int selectionEnd) override;
virtual bool confirmComposition(
const blink::WebString& text,
- blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) OVERRIDE;
- virtual void extendSelectionAndDelete(int before, int after) OVERRIDE;
+ blink::WebWidget::ConfirmCompositionBehavior selectionBehavior) override;
+ virtual void extendSelectionAndDelete(int before, int after) override;
// MouseLockDispatcher::LockTarget implementation.
- virtual void OnLockMouseACK(bool succeeded) OVERRIDE;
- virtual void OnMouseLockLost() OVERRIDE;
- virtual bool HandleMouseLockedInputEvent(
- const blink::WebMouseEvent& event) OVERRIDE;
+ void OnLockMouseACK(bool succeeded) override;
+ void OnMouseLockLost() override;
+ bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event) override;
private:
friend class base::DeleteHelper<BrowserPlugin>;
// Only the manager is allowed to create a BrowserPlugin.
- friend class BrowserPluginManagerImpl;
- friend class MockBrowserPluginManager;
+ friend class BrowserPluginManager;
// For unit/integration tests.
friend class MockBrowserPlugin;
@@ -180,114 +144,69 @@ class CONTENT_EXPORT BrowserPlugin :
// A BrowserPlugin object is a controller that represents an instance of a
// browser plugin within the embedder renderer process. Once a BrowserPlugin
// does an initial navigation or is attached to a newly created guest, it
- // acquires a guest_instance_id as well. The guest instance ID uniquely
- // identifies a guest WebContents that's hosted by this BrowserPlugin.
+ // acquires a browser_plugin_instance_id as well. The guest instance ID
+ // uniquely identifies a guest WebContents that's hosted by this
+ // BrowserPlugin.
BrowserPlugin(RenderViewImpl* render_view,
blink::WebFrame* frame,
- bool auto_navigate);
+ scoped_ptr<BrowserPluginDelegate> delegate);
- virtual ~BrowserPlugin();
+ ~BrowserPlugin() override;
int width() const { return plugin_rect_.width(); }
int height() const { return plugin_rect_.height(); }
gfx::Size plugin_size() const { return plugin_rect_.size(); }
gfx::Rect plugin_rect() const { return plugin_rect_; }
- // Gets the Max Height value used for auto size.
- int GetAdjustedMaxHeight() const;
- // Gets the Max Width value used for auto size.
- int GetAdjustedMaxWidth() const;
- // Gets the Min Height value used for auto size.
- int GetAdjustedMinHeight() const;
- // Gets the Min Width value used for auto size.
- int GetAdjustedMinWidth() const;
-
- // Virtual to allow for mocking in tests.
- virtual float GetDeviceScaleFactor() const;
- void ShowSadGraphic();
+ float GetDeviceScaleFactor() const;
- // Triggers the event-listeners for |event_name|. Note that the function
- // frees all the values in |props|.
- void TriggerEvent(const std::string& event_name,
- std::map<std::string, base::Value*>* props);
+ void ShowSadGraphic();
// Populates BrowserPluginHostMsg_ResizeGuest_Params with resize state.
void PopulateResizeGuestParameters(
- BrowserPluginHostMsg_ResizeGuest_Params* params,
const gfx::Size& view_size,
- bool needs_repaint);
-
- // Populates BrowserPluginHostMsg_AutoSize_Params object with autosize state.
- void PopulateAutoSizeParameters(
- BrowserPluginHostMsg_AutoSize_Params* params, bool auto_size_enabled);
-
- // Populates both AutoSize and ResizeGuest parameters based on the current
- // autosize state.
- void GetSizeParams(
- BrowserPluginHostMsg_AutoSize_Params* auto_size_params,
- BrowserPluginHostMsg_ResizeGuest_Params* resize_guest_params,
- bool needs_repaint);
-
- // Informs the guest of an updated autosize state.
- void UpdateGuestAutoSizeState(bool auto_size_enabled);
-
+ BrowserPluginHostMsg_ResizeGuest_Params* params);
// IPC message handlers.
// Please keep in alphabetical order.
void OnAdvanceFocus(int instance_id, bool reverse);
- void OnAttachACK(int instance_id);
- void OnBuffersSwapped(int instance_id,
- const FrameMsg_BuffersSwapped_Params& params);
+ void OnAttachACK(int browser_plugin_instance_id);
void OnCompositorFrameSwapped(const IPC::Message& message);
- void OnCopyFromCompositingSurface(int instance_id,
- int request_id,
- gfx::Rect source_rect,
- gfx::Size dest_size);
- void OnGuestContentWindowReady(int instance_id,
- int content_window_routing_id);
void OnGuestGone(int instance_id);
+ void OnSetContentsOpaque(int instance_id, bool opaque);
void OnSetCursor(int instance_id, const WebCursor& cursor);
void OnSetMouseLock(int instance_id, bool enable);
+ void OnSetTooltipText(int browser_plugin_instance_id,
+ const base::string16& tooltip_text);
void OnShouldAcceptTouchEvents(int instance_id, bool accept);
- void OnUpdateRect(int instance_id,
- const BrowserPluginMsg_UpdateRect_Params& params);
- // This is the browser-process-allocated instance ID that uniquely identifies
- // a guest WebContents.
- int guest_instance_id_;
// This indicates whether this BrowserPlugin has been attached to a
// WebContents.
bool attached_;
+ bool attach_pending_;
const base::WeakPtr<RenderViewImpl> render_view_;
// We cache the |render_view_|'s routing ID because we need it on destruction.
// If the |render_view_| is destroyed before the BrowserPlugin is destroyed
// then we will attempt to access a NULL pointer.
const int render_view_routing_id_;
blink::WebPluginContainer* container_;
- scoped_ptr<BrowserPluginBindings> bindings_;
- bool paint_ack_received_;
gfx::Rect plugin_rect_;
float last_device_scale_factor_;
// Bitmap for crashed plugin. Lazily initialized, non-owning pointer.
SkBitmap* sad_guest_;
bool guest_crashed_;
- bool is_auto_size_state_dirty_;
- // Maximum size constraint for autosize.
- gfx::Size max_auto_size_;
- int content_window_routing_id_;
bool plugin_focused_;
// Tracks the visibility of the browser plugin regardless of the whole
// embedder RenderView's visibility.
bool visible_;
- const bool auto_navigate_;
- std::string html_string_;
-
WebCursor cursor_;
- gfx::Size last_view_size_;
bool mouse_locked_;
+ // This indicates that the BrowserPlugin has a geometry.
+ bool ready_;
+
// BrowserPlugin outlives RenderViewImpl in Chrome Apps and so we need to
// store the BrowserPlugin's BrowserPluginManager in a member variable to
// avoid accessing the RenderViewImpl.
@@ -296,14 +215,16 @@ class CONTENT_EXPORT BrowserPlugin :
// Used for HW compositing.
scoped_refptr<ChildFrameCompositingHelper> compositing_helper_;
- // Used to identify the plugin to WebBindings.
- scoped_ptr<struct _NPP> npp_;
-
// URL for the embedder frame.
- const GURL embedder_frame_url_;
+ int browser_plugin_instance_id_;
+
+ // Indicates whether the guest content is opaque.
+ bool contents_opaque_;
std::vector<EditCommand> edit_commands_;
+ scoped_ptr<BrowserPluginDelegate> delegate_;
+
// Weak factory used in v8 |MakeWeak| callback, since the v8 callback might
// get called after BrowserPlugin has been destroyed.
base::WeakPtrFactory<BrowserPlugin> weak_ptr_factory_;
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc b/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc
deleted file mode 100644
index 6758242b9a8..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.cc
+++ /dev/null
@@ -1,613 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_bindings.h"
-
-#include <cstdlib>
-#include <string>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/common/browser_plugin/browser_plugin_constants.h"
-#include "content/public/renderer/v8_value_converter.h"
-#include "content/renderer/browser_plugin/browser_plugin.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "v8/include/v8.h"
-
-using blink::WebBindings;
-using blink::WebElement;
-using blink::WebDOMEvent;
-using blink::WebDOMMessageEvent;
-using blink::WebPluginContainer;
-using blink::WebString;
-
-namespace content {
-
-namespace {
-
-BrowserPluginBindings* GetBindings(NPObject* object) {
- return static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object)->
- message_channel.get();
-}
-
-std::string StringFromNPVariant(const NPVariant& variant) {
- if (!NPVARIANT_IS_STRING(variant))
- return std::string();
- const NPString& np_string = NPVARIANT_TO_STRING(variant);
- return std::string(np_string.UTF8Characters, np_string.UTF8Length);
-}
-
-// Depending on where the attribute comes from it could be a string, int32,
-// or a double. Javascript tends to produce an int32 or a string, but setting
-// the value from the developer tools console may also produce a double.
-int IntFromNPVariant(const NPVariant& variant) {
- int value = 0;
- switch (variant.type) {
- case NPVariantType_Double:
- value = NPVARIANT_TO_DOUBLE(variant);
- break;
- case NPVariantType_Int32:
- value = NPVARIANT_TO_INT32(variant);
- break;
- case NPVariantType_String:
- base::StringToInt(StringFromNPVariant(variant), &value);
- break;
- default:
- break;
- }
- return value;
-}
-
-//------------------------------------------------------------------------------
-// Implementations of NPClass functions. These are here to:
-// - Implement src attribute.
-//------------------------------------------------------------------------------
-NPObject* BrowserPluginBindingsAllocate(NPP npp, NPClass* the_class) {
- return new BrowserPluginBindings::BrowserPluginNPObject;
-}
-
-void BrowserPluginBindingsDeallocate(NPObject* object) {
- BrowserPluginBindings::BrowserPluginNPObject* instance =
- static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(object);
- delete instance;
-}
-
-bool BrowserPluginBindingsHasMethod(NPObject* np_obj, NPIdentifier name) {
- if (!np_obj)
- return false;
-
- BrowserPluginBindings* bindings = GetBindings(np_obj);
- if (!bindings)
- return false;
-
- return bindings->HasMethod(name);
-}
-
-bool BrowserPluginBindingsInvoke(NPObject* np_obj, NPIdentifier name,
- const NPVariant* args, uint32 arg_count,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- BrowserPluginBindings* bindings = GetBindings(np_obj);
- if (!bindings)
- return false;
-
- return bindings->InvokeMethod(name, args, arg_count, result);
-}
-
-bool BrowserPluginBindingsInvokeDefault(NPObject* np_obj,
- const NPVariant* args,
- uint32 arg_count,
- NPVariant* result) {
- NOTIMPLEMENTED();
- return false;
-}
-
-bool BrowserPluginBindingsHasProperty(NPObject* np_obj, NPIdentifier name) {
- if (!np_obj)
- return false;
-
- BrowserPluginBindings* bindings = GetBindings(np_obj);
- if (!bindings)
- return false;
-
- return bindings->HasProperty(name);
-}
-
-bool BrowserPluginBindingsGetProperty(NPObject* np_obj, NPIdentifier name,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- if (!result)
- return false;
-
- // All attributes from here on rely on the bindings, so retrieve it once and
- // return on failure.
- BrowserPluginBindings* bindings = GetBindings(np_obj);
- if (!bindings)
- return false;
-
- return bindings->GetProperty(name, result);
-}
-
-bool BrowserPluginBindingsSetProperty(NPObject* np_obj, NPIdentifier name,
- const NPVariant* variant) {
- if (!np_obj)
- return false;
- if (!variant)
- return false;
-
- // All attributes from here on rely on the bindings, so retrieve it once and
- // return on failure.
- BrowserPluginBindings* bindings = GetBindings(np_obj);
- if (!bindings)
- return false;
-
- if (variant->type == NPVariantType_Null)
- return bindings->RemoveProperty(np_obj, name);
-
- return bindings->SetProperty(np_obj, name, variant);
-}
-
-bool BrowserPluginBindingsEnumerate(NPObject *np_obj, NPIdentifier **value,
- uint32_t *count) {
- NOTIMPLEMENTED();
- return true;
-}
-
-NPClass browser_plugin_message_class = {
- NP_CLASS_STRUCT_VERSION,
- &BrowserPluginBindingsAllocate,
- &BrowserPluginBindingsDeallocate,
- NULL,
- &BrowserPluginBindingsHasMethod,
- &BrowserPluginBindingsInvoke,
- &BrowserPluginBindingsInvokeDefault,
- &BrowserPluginBindingsHasProperty,
- &BrowserPluginBindingsGetProperty,
- &BrowserPluginBindingsSetProperty,
- NULL,
- &BrowserPluginBindingsEnumerate,
-};
-
-} // namespace
-
-// BrowserPluginMethodBinding --------------------------------------------------
-
-class BrowserPluginMethodBinding {
- public:
- BrowserPluginMethodBinding(const char name[], uint32 arg_count)
- : name_(name),
- arg_count_(arg_count) {
- }
-
- virtual ~BrowserPluginMethodBinding() {}
-
- bool MatchesName(NPIdentifier name) const {
- return WebBindings::getStringIdentifier(name_.c_str()) == name;
- }
-
- uint32 arg_count() const { return arg_count_; }
-
- virtual bool Invoke(BrowserPluginBindings* bindings,
- const NPVariant* args,
- NPVariant* result) = 0;
-
- private:
- std::string name_;
- uint32 arg_count_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginMethodBinding);
-};
-
-class BrowserPluginBindingAttach: public BrowserPluginMethodBinding {
- public:
- BrowserPluginBindingAttach()
- : BrowserPluginMethodBinding(browser_plugin::kMethodInternalAttach, 2) {}
-
- virtual bool Invoke(BrowserPluginBindings* bindings,
- const NPVariant* args,
- NPVariant* result) OVERRIDE {
- bool attached = InvokeHelper(bindings, args);
- BOOLEAN_TO_NPVARIANT(attached, *result);
- return true;
- }
-
- private:
- bool InvokeHelper(BrowserPluginBindings* bindings, const NPVariant* args) {
- if (!bindings->instance()->render_view())
- return false;
-
- int instance_id = IntFromNPVariant(args[0]);
- if (!instance_id)
- return false;
-
- scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
- v8::Handle<v8::Value> obj(blink::WebBindings::toV8Value(&args[1]));
- scoped_ptr<base::Value> value(
- converter->FromV8Value(obj, bindings->instance()->render_view()->
- GetWebView()->mainFrame()->mainWorldScriptContext()));
- if (!value)
- return false;
-
- if (!value->IsType(base::Value::TYPE_DICTIONARY))
- return false;
-
- scoped_ptr<base::DictionaryValue> extra_params(
- static_cast<base::DictionaryValue*>(value.release()));
- bindings->instance()->Attach(instance_id, extra_params.Pass());
- return true;
- }
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindingAttach);
-};
-
-// BrowserPluginPropertyBinding ------------------------------------------------
-
-class BrowserPluginPropertyBinding {
- public:
- explicit BrowserPluginPropertyBinding(const char name[]) : name_(name) {}
- virtual ~BrowserPluginPropertyBinding() {}
- const std::string& name() const { return name_; }
- bool MatchesName(NPIdentifier name) const {
- return WebBindings::getStringIdentifier(name_.c_str()) == name;
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) = 0;
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) = 0;
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) = 0;
- // Updates the DOM Attribute value with the current property value.
- void UpdateDOMAttribute(BrowserPluginBindings* bindings,
- std::string new_value) {
- bindings->instance()->UpdateDOMAttribute(name(), new_value);
- }
- private:
- std::string name_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBinding);
-};
-
-class BrowserPluginPropertyBindingAllowTransparency
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingAllowTransparency()
- : BrowserPluginPropertyBinding(
- browser_plugin::kAttributeAllowTransparency) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- bool allow_transparency =
- bindings->instance()->GetAllowTransparencyAttribute();
- BOOLEAN_TO_NPVARIANT(allow_transparency, *result);
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- std::string value = StringFromNPVariant(*variant);
- if (!bindings->instance()->HasDOMAttribute(name())) {
- UpdateDOMAttribute(bindings, value);
- bindings->instance()->ParseAllowTransparencyAttribute();
- } else {
- UpdateDOMAttribute(bindings, value);
- }
- return true;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {
- bindings->instance()->RemoveDOMAttribute(name());
- bindings->instance()->ParseAllowTransparencyAttribute();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAllowTransparency);
-};
-
-class BrowserPluginPropertyBindingAutoSize
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingAutoSize()
- : BrowserPluginPropertyBinding(browser_plugin::kAttributeAutoSize) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- bool auto_size = bindings->instance()->GetAutoSizeAttribute();
- BOOLEAN_TO_NPVARIANT(auto_size, *result);
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- std::string value = StringFromNPVariant(*variant);
- if (!bindings->instance()->HasDOMAttribute(name())) {
- UpdateDOMAttribute(bindings, value);
- bindings->instance()->ParseAutoSizeAttribute();
- } else {
- UpdateDOMAttribute(bindings, value);
- }
- return true;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {
- bindings->instance()->RemoveDOMAttribute(name());
- bindings->instance()->ParseAutoSizeAttribute();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingAutoSize);
-};
-
-class BrowserPluginPropertyBindingContentWindow
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingContentWindow()
- : BrowserPluginPropertyBinding(browser_plugin::kAttributeContentWindow) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- NPObject* obj = bindings->instance()->GetContentWindow();
- if (obj) {
- result->type = NPVariantType_Object;
- result->value.objectValue = WebBindings::retainObject(obj);
- }
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- return false;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {}
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingContentWindow);
-};
-
-class BrowserPluginPropertyBindingMaxHeight
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingMaxHeight()
- : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxHeight) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- int max_height = bindings->instance()->GetMaxHeightAttribute();
- INT32_TO_NPVARIANT(max_height, *result);
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- int new_value = IntFromNPVariant(*variant);
- if (bindings->instance()->GetMaxHeightAttribute() != new_value) {
- UpdateDOMAttribute(bindings, base::IntToString(new_value));
- bindings->instance()->ParseSizeContraintsChanged();
- }
- return true;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {
- bindings->instance()->RemoveDOMAttribute(name());
- bindings->instance()->ParseSizeContraintsChanged();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxHeight);
-};
-
-class BrowserPluginPropertyBindingMaxWidth
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingMaxWidth()
- : BrowserPluginPropertyBinding(browser_plugin::kAttributeMaxWidth) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- int max_width = bindings->instance()->GetMaxWidthAttribute();
- INT32_TO_NPVARIANT(max_width, *result);
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- int new_value = IntFromNPVariant(*variant);
- if (bindings->instance()->GetMaxWidthAttribute() != new_value) {
- UpdateDOMAttribute(bindings, base::IntToString(new_value));
- bindings->instance()->ParseSizeContraintsChanged();
- }
- return true;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {
- bindings->instance()->RemoveDOMAttribute(name());
- bindings->instance()->ParseSizeContraintsChanged();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMaxWidth);
-};
-
-class BrowserPluginPropertyBindingMinHeight
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingMinHeight()
- : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinHeight) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- int min_height = bindings->instance()->GetMinHeightAttribute();
- INT32_TO_NPVARIANT(min_height, *result);
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- int new_value = IntFromNPVariant(*variant);
- if (bindings->instance()->GetMinHeightAttribute() != new_value) {
- UpdateDOMAttribute(bindings, base::IntToString(new_value));
- bindings->instance()->ParseSizeContraintsChanged();
- }
- return true;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {
- bindings->instance()->RemoveDOMAttribute(name());
- bindings->instance()->ParseSizeContraintsChanged();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinHeight);
-};
-
-class BrowserPluginPropertyBindingMinWidth
- : public BrowserPluginPropertyBinding {
- public:
- BrowserPluginPropertyBindingMinWidth()
- : BrowserPluginPropertyBinding(browser_plugin::kAttributeMinWidth) {
- }
- virtual bool GetProperty(BrowserPluginBindings* bindings,
- NPVariant* result) OVERRIDE {
- int min_width = bindings->instance()->GetMinWidthAttribute();
- INT32_TO_NPVARIANT(min_width, *result);
- return true;
- }
- virtual bool SetProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj,
- const NPVariant* variant) OVERRIDE {
- int new_value = IntFromNPVariant(*variant);
- if (bindings->instance()->GetMinWidthAttribute() != new_value) {
- UpdateDOMAttribute(bindings, base::IntToString(new_value));
- bindings->instance()->ParseSizeContraintsChanged();
- }
- return true;
- }
- virtual void RemoveProperty(BrowserPluginBindings* bindings,
- NPObject* np_obj) OVERRIDE {
- bindings->instance()->RemoveDOMAttribute(name());
- bindings->instance()->ParseSizeContraintsChanged();
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginPropertyBindingMinWidth);
-};
-
-
-// BrowserPluginBindings ------------------------------------------------------
-
-BrowserPluginBindings::BrowserPluginNPObject::BrowserPluginNPObject() {
-}
-
-BrowserPluginBindings::BrowserPluginNPObject::~BrowserPluginNPObject() {
-}
-
-BrowserPluginBindings::BrowserPluginBindings(BrowserPlugin* instance)
- : instance_(instance),
- np_object_(NULL),
- weak_ptr_factory_(this) {
- NPObject* obj =
- WebBindings::createObject(instance->pluginNPP(),
- &browser_plugin_message_class);
- np_object_ = static_cast<BrowserPluginBindings::BrowserPluginNPObject*>(obj);
- np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
-
- method_bindings_.push_back(new BrowserPluginBindingAttach);
-
- property_bindings_.push_back(
- new BrowserPluginPropertyBindingAllowTransparency);
- property_bindings_.push_back(new BrowserPluginPropertyBindingAutoSize);
- property_bindings_.push_back(new BrowserPluginPropertyBindingContentWindow);
- property_bindings_.push_back(new BrowserPluginPropertyBindingMaxHeight);
- property_bindings_.push_back(new BrowserPluginPropertyBindingMaxWidth);
- property_bindings_.push_back(new BrowserPluginPropertyBindingMinHeight);
- property_bindings_.push_back(new BrowserPluginPropertyBindingMinWidth);
-}
-
-BrowserPluginBindings::~BrowserPluginBindings() {
- WebBindings::releaseObject(np_object_);
-}
-
-bool BrowserPluginBindings::HasMethod(NPIdentifier name) const {
- for (BindingList::const_iterator iter = method_bindings_.begin();
- iter != method_bindings_.end();
- ++iter) {
- if ((*iter)->MatchesName(name))
- return true;
- }
- return false;
-}
-
-bool BrowserPluginBindings::InvokeMethod(NPIdentifier name,
- const NPVariant* args,
- uint32 arg_count,
- NPVariant* result) {
- for (BindingList::iterator iter = method_bindings_.begin();
- iter != method_bindings_.end();
- ++iter) {
- if ((*iter)->MatchesName(name) && (*iter)->arg_count() == arg_count)
- return (*iter)->Invoke(this, args, result);
- }
- return false;
-}
-
-bool BrowserPluginBindings::HasProperty(NPIdentifier name) const {
- for (PropertyBindingList::const_iterator iter = property_bindings_.begin();
- iter != property_bindings_.end();
- ++iter) {
- if ((*iter)->MatchesName(name))
- return true;
- }
- return false;
-}
-
-bool BrowserPluginBindings::SetProperty(NPObject* np_obj,
- NPIdentifier name,
- const NPVariant* variant) {
- for (PropertyBindingList::iterator iter = property_bindings_.begin();
- iter != property_bindings_.end();
- ++iter) {
- if ((*iter)->MatchesName(name)) {
- if ((*iter)->SetProperty(this, np_obj, variant)) {
- return true;
- }
- break;
- }
- }
- return false;
-}
-
-bool BrowserPluginBindings::RemoveProperty(NPObject* np_obj,
- NPIdentifier name) {
- for (PropertyBindingList::iterator iter = property_bindings_.begin();
- iter != property_bindings_.end();
- ++iter) {
- if ((*iter)->MatchesName(name)) {
- (*iter)->RemoveProperty(this, np_obj);
- return true;
- }
- }
- return false;
-}
-
-bool BrowserPluginBindings::GetProperty(NPIdentifier name, NPVariant* result) {
- for (PropertyBindingList::iterator iter = property_bindings_.begin();
- iter != property_bindings_.end();
- ++iter) {
- if ((*iter)->MatchesName(name))
- return (*iter)->GetProperty(this, result);
- }
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.h b/chromium/content/renderer/browser_plugin/browser_plugin_bindings.h
deleted file mode 100644
index 91e8ced8439..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_bindings.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_BINDINGS_H__
-#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_BINDINGS_H__
-
-#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
-#include "ppapi/shared_impl/resource.h"
-#include "third_party/npapi/bindings/npruntime.h"
-
-namespace content {
-
-class BrowserPlugin;
-class BrowserPluginMethodBinding;
-class BrowserPluginPropertyBinding;
-
-class BrowserPluginBindings {
- public:
- // BrowserPluginNPObject is a simple struct that adds a pointer back to a
- // BrowserPluginBindings instance. This way, we can use an NPObject to allow
- // JavaScript interactions without forcing BrowserPluginBindings to inherit
- // from NPObject.
- struct BrowserPluginNPObject : public NPObject {
- BrowserPluginNPObject();
- ~BrowserPluginNPObject();
-
- base::WeakPtr<BrowserPluginBindings> message_channel;
- };
-
- explicit BrowserPluginBindings(BrowserPlugin* instance);
- ~BrowserPluginBindings();
-
- NPObject* np_object() const { return np_object_; }
-
- BrowserPlugin* instance() const { return instance_; }
-
- bool HasMethod(NPIdentifier name) const;
-
- bool InvokeMethod(NPIdentifier name,
- const NPVariant* args,
- uint32 arg_count,
- NPVariant* result);
-
- bool HasProperty(NPIdentifier name) const;
- bool SetProperty(NPObject* np_obj,
- NPIdentifier name,
- const NPVariant* variant);
- bool GetProperty(NPIdentifier name, NPVariant* result);
- bool RemoveProperty(NPObject *np_obj, NPIdentifier name);
- private:
- BrowserPlugin* instance_;
- // The NPObject we use to expose postMessage to JavaScript.
- BrowserPluginNPObject* np_object_;
-
- typedef ScopedVector<BrowserPluginMethodBinding> BindingList;
- BindingList method_bindings_;
- typedef ScopedVector<BrowserPluginPropertyBinding> PropertyBindingList;
- PropertyBindingList property_bindings_;
-
- // This is used to ensure pending tasks will not fire after this object is
- // destroyed.
- base::WeakPtrFactory<BrowserPluginBindings> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginBindings);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_BINDINGS_H__
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc b/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc
deleted file mode 100644
index 7f9846a1600..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_browsertest.h"
-
-#include "base/debug/leak_annotations.h"
-#include "base/files/file_path.h"
-#include "base/memory/singleton.h"
-#include "base/path_service.h"
-#include "base/pickle.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/browser_plugin/browser_plugin.h"
-#include "content/renderer/browser_plugin/browser_plugin_manager_factory.h"
-#include "content/renderer/browser_plugin/mock_browser_plugin.h"
-#include "content/renderer/browser_plugin/mock_browser_plugin_manager.h"
-#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/renderer_webkitplatformsupport_impl.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/platform/WebCursorInfo.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebScriptSource.h"
-
-namespace content {
-
-namespace {
-const char kHTMLForBrowserPluginObject[] =
- "<object id='browserplugin' width='640px' height='480px'"
- " src='foo' type='%s'></object>"
- "<script>document.querySelector('object').nonExistentAttribute;</script>";
-
-const char kHTMLForBrowserPluginWithAllAttributes[] =
- "<object id='browserplugin' width='640' height='480' type='%s'"
- " autosize maxheight='600' maxwidth='800' minheight='240'"
- " minwidth='320' name='Jim' partition='someid' src='foo'>";
-
-const char kHTMLForSourcelessPluginObject[] =
- "<object id='browserplugin' width='640px' height='480px' type='%s'>";
-
-std::string GetHTMLForBrowserPluginObject() {
- return base::StringPrintf(kHTMLForBrowserPluginObject,
- kBrowserPluginMimeType);
-}
-
-} // namespace
-
-// Test factory for creating test instances of BrowserPluginManager.
-class TestBrowserPluginManagerFactory : public BrowserPluginManagerFactory {
- public:
- virtual MockBrowserPluginManager* CreateBrowserPluginManager(
- RenderViewImpl* render_view) OVERRIDE {
- return new MockBrowserPluginManager(render_view);
- }
-
- // Singleton getter.
- static TestBrowserPluginManagerFactory* GetInstance() {
- return Singleton<TestBrowserPluginManagerFactory>::get();
- }
-
- protected:
- TestBrowserPluginManagerFactory() {}
- virtual ~TestBrowserPluginManagerFactory() {}
-
- private:
- // For Singleton.
- friend struct DefaultSingletonTraits<TestBrowserPluginManagerFactory>;
-
- DISALLOW_COPY_AND_ASSIGN(TestBrowserPluginManagerFactory);
-};
-
-BrowserPluginTest::BrowserPluginTest() {}
-
-BrowserPluginTest::~BrowserPluginTest() {}
-
-void BrowserPluginTest::SetUp() {
- BrowserPluginManager::set_factory_for_testing(
- TestBrowserPluginManagerFactory::GetInstance());
- content::RenderViewTest::SetUp();
-}
-
-void BrowserPluginTest::TearDown() {
- BrowserPluginManager::set_factory_for_testing(
- TestBrowserPluginManagerFactory::GetInstance());
-#if defined(LEAK_SANITIZER)
- // Do this before shutting down V8 in RenderViewTest::TearDown().
- // http://crbug.com/328552
- __lsan_do_leak_check();
-#endif
- RenderViewTest::TearDown();
-}
-
-std::string BrowserPluginTest::ExecuteScriptAndReturnString(
- const std::string& script) {
- v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
- v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
- blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
- if (value.IsEmpty() || !value->IsString())
- return std::string();
-
- v8::Local<v8::String> v8_str = value->ToString();
- int length = v8_str->Utf8Length() + 1;
- scoped_ptr<char[]> str(new char[length]);
- v8_str->WriteUtf8(str.get(), length);
- return str.get();
-}
-
-int BrowserPluginTest::ExecuteScriptAndReturnInt(
- const std::string& script) {
- v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
- v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
- blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
- if (value.IsEmpty() || !value->IsInt32())
- return 0;
-
- return value->Int32Value();
-}
-
-// A return value of false means that a value was not present. The return value
-// of the script is stored in |result|
-bool BrowserPluginTest::ExecuteScriptAndReturnBool(
- const std::string& script, bool* result) {
- v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
- v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue(
- blink::WebScriptSource(blink::WebString::fromUTF8(script.c_str())));
- if (value.IsEmpty() || !value->IsBoolean())
- return false;
-
- *result = value->BooleanValue();
- return true;
-}
-
-MockBrowserPlugin* BrowserPluginTest::GetCurrentPlugin() {
- BrowserPluginHostMsg_Attach_Params params;
- return GetCurrentPluginWithAttachParams(&params);
-}
-
-MockBrowserPlugin* BrowserPluginTest::GetCurrentPluginWithAttachParams(
- BrowserPluginHostMsg_Attach_Params* params) {
- MockBrowserPlugin* browser_plugin = static_cast<MockBrowserPluginManager*>(
- browser_plugin_manager())->last_plugin();
- if (!browser_plugin)
- return NULL;
- browser_plugin_manager()->AllocateInstanceID(browser_plugin);
-
- int instance_id = 0;
- const IPC::Message* msg =
- browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_Attach::ID);
- if (!msg)
- return NULL;
-
- PickleIterator iter(*msg);
- if (!iter.ReadInt(&instance_id))
- return NULL;
-
- if (!IPC::ParamTraits<BrowserPluginHostMsg_Attach_Params>::Read(
- msg, &iter, params)) {
- return NULL;
- }
-
- browser_plugin->OnAttachACK(instance_id);
- return browser_plugin;
-}
-
-// This test verifies that an initial resize occurs when we instantiate the
-// browser plugin.
-TEST_F(BrowserPluginTest, InitialResize) {
- LoadHTML(GetHTMLForBrowserPluginObject().c_str());
- // Verify that the information in Attach is correct.
- BrowserPluginHostMsg_Attach_Params params;
- MockBrowserPlugin* browser_plugin = GetCurrentPluginWithAttachParams(&params);
-
- EXPECT_EQ(640, params.resize_guest_params.view_size.width());
- EXPECT_EQ(480, params.resize_guest_params.view_size.height());
- ASSERT_TRUE(browser_plugin);
-}
-
-// This test verifies that all attributes (present at the time of writing) are
-// parsed on initialization. However, this test does minimal checking of
-// correct behavior.
-TEST_F(BrowserPluginTest, ParseAllAttributes) {
- std::string html = base::StringPrintf(kHTMLForBrowserPluginWithAllAttributes,
- kBrowserPluginMimeType);
- LoadHTML(html.c_str());
- bool result;
- bool has_value = ExecuteScriptAndReturnBool(
- "document.getElementById('browserplugin').autosize", &result);
- EXPECT_TRUE(has_value);
- EXPECT_TRUE(result);
- int maxHeight = ExecuteScriptAndReturnInt(
- "document.getElementById('browserplugin').maxheight");
- EXPECT_EQ(600, maxHeight);
- int maxWidth = ExecuteScriptAndReturnInt(
- "document.getElementById('browserplugin').maxwidth");
- EXPECT_EQ(800, maxWidth);
- int minHeight = ExecuteScriptAndReturnInt(
- "document.getElementById('browserplugin').minheight");
- EXPECT_EQ(240, minHeight);
- int minWidth = ExecuteScriptAndReturnInt(
- "document.getElementById('browserplugin').minwidth");
- EXPECT_EQ(320, minWidth);
-}
-
-TEST_F(BrowserPluginTest, ResizeFlowControl) {
- LoadHTML(GetHTMLForBrowserPluginObject().c_str());
- MockBrowserPlugin* browser_plugin = GetCurrentPlugin();
- ASSERT_TRUE(browser_plugin);
- int instance_id = browser_plugin->guest_instance_id();
- // Send an UpdateRect to the BrowserPlugin to make sure the browser sees a
- // resize related (SetAutoSize) message.
- {
- // We send a stale UpdateRect to the BrowserPlugin.
- BrowserPluginMsg_UpdateRect_Params update_rect_params;
- update_rect_params.view_size = gfx::Size(640, 480);
- update_rect_params.scale_factor = 1.0f;
- update_rect_params.is_resize_ack = true;
- BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
- browser_plugin->OnMessageReceived(msg);
- }
-
- browser_plugin_manager()->sink().ClearMessages();
-
- // Resize the browser plugin three times.
-
- ExecuteJavaScript("document.getElementById('browserplugin').width = '641px'");
- GetMainFrame()->view()->layout();
- ProcessPendingMessages();
-
- ExecuteJavaScript("document.getElementById('browserplugin').width = '642px'");
- GetMainFrame()->view()->layout();
- ProcessPendingMessages();
-
- ExecuteJavaScript("document.getElementById('browserplugin').width = '643px'");
- GetMainFrame()->view()->layout();
- ProcessPendingMessages();
-
- // Expect to see one resize messsage in the sink. BrowserPlugin will not issue
- // subsequent resize requests until the first request is satisfied by the
- // guest. The rest of the messages could be
- // BrowserPluginHostMsg_UpdateGeometry msgs.
- EXPECT_LE(1u, browser_plugin_manager()->sink().message_count());
- for (size_t i = 0; i < browser_plugin_manager()->sink().message_count();
- ++i) {
- const IPC::Message* msg = browser_plugin_manager()->sink().GetMessageAt(i);
- if (msg->type() != BrowserPluginHostMsg_ResizeGuest::ID)
- EXPECT_EQ(msg->type(), BrowserPluginHostMsg_UpdateGeometry::ID);
- }
- const IPC::Message* msg =
- browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_ResizeGuest::ID);
- ASSERT_TRUE(msg);
- BrowserPluginHostMsg_ResizeGuest::Param param;
- BrowserPluginHostMsg_ResizeGuest::Read(msg, &param);
- instance_id = param.a;
- BrowserPluginHostMsg_ResizeGuest_Params params = param.b;
- EXPECT_EQ(641, params.view_size.width());
- EXPECT_EQ(480, params.view_size.height());
-
- {
- // We send a stale UpdateRect to the BrowserPlugin.
- BrowserPluginMsg_UpdateRect_Params update_rect_params;
- update_rect_params.view_size = gfx::Size(641, 480);
- update_rect_params.scale_factor = 1.0f;
- update_rect_params.is_resize_ack = true;
- BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
- browser_plugin->OnMessageReceived(msg);
- }
- // Send the BrowserPlugin another UpdateRect, but this time with a size
- // that matches the size of the container.
- {
- BrowserPluginMsg_UpdateRect_Params update_rect_params;
- update_rect_params.view_size = gfx::Size(643, 480);
- update_rect_params.scale_factor = 1.0f;
- update_rect_params.is_resize_ack = true;
- BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
- browser_plugin->OnMessageReceived(msg);
- }
-}
-
-TEST_F(BrowserPluginTest, RemovePlugin) {
- LoadHTML(GetHTMLForBrowserPluginObject().c_str());
- MockBrowserPlugin* browser_plugin = GetCurrentPlugin();
- ASSERT_TRUE(browser_plugin);
-
- EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_PluginDestroyed::ID));
- ExecuteJavaScript("x = document.getElementById('browserplugin'); "
- "x.parentNode.removeChild(x);");
- ProcessPendingMessages();
- EXPECT_TRUE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_PluginDestroyed::ID));
-}
-
-// This test verifies that PluginDestroyed messages do not get sent from a
-// BrowserPlugin that has never navigated.
-TEST_F(BrowserPluginTest, RemovePluginBeforeNavigation) {
- std::string html = base::StringPrintf(kHTMLForSourcelessPluginObject,
- kBrowserPluginMimeType);
- LoadHTML(html.c_str());
- EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_PluginDestroyed::ID));
- ExecuteJavaScript("x = document.getElementById('browserplugin'); "
- "x.parentNode.removeChild(x);");
- ProcessPendingMessages();
- EXPECT_FALSE(browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_PluginDestroyed::ID));
-}
-
-// Verify that the 'partition' attribute on the browser plugin is parsed
-// correctly.
-TEST_F(BrowserPluginTest, AutoSizeAttributes) {
- std::string html = base::StringPrintf(kHTMLForSourcelessPluginObject,
- kBrowserPluginMimeType);
- LoadHTML(html.c_str());
- const char* kSetAutoSizeParametersAndNavigate =
- "var browserplugin = document.getElementById('browserplugin');"
- "browserplugin.autosize = true;"
- "browserplugin.minwidth = 42;"
- "browserplugin.minheight = 43;"
- "browserplugin.maxwidth = 1337;"
- "browserplugin.maxheight = 1338;"
- "browserplugin.src = 'foobar';";
- const char* kDisableAutoSize =
- "document.getElementById('browserplugin').removeAttribute('autosize');";
-
- int instance_id = 0;
- // Set some autosize parameters before navigating then navigate.
- // Verify that the BrowserPluginHostMsg_Attach message contains
- // the correct autosize parameters.
- ExecuteJavaScript(kSetAutoSizeParametersAndNavigate);
- ProcessPendingMessages();
-
- BrowserPluginHostMsg_Attach_Params params;
- MockBrowserPlugin* browser_plugin = GetCurrentPluginWithAttachParams(&params);
- ASSERT_TRUE(browser_plugin);
-
- EXPECT_TRUE(params.auto_size_params.enable);
- EXPECT_EQ(42, params.auto_size_params.min_size.width());
- EXPECT_EQ(43, params.auto_size_params.min_size.height());
- EXPECT_EQ(1337, params.auto_size_params.max_size.width());
- EXPECT_EQ(1338, params.auto_size_params.max_size.height());
-
- // Disable autosize. AutoSize state will not be sent to the guest until
- // the guest has responded to the last resize request.
- ExecuteJavaScript(kDisableAutoSize);
- ProcessPendingMessages();
-
- const IPC::Message* auto_size_msg =
- browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_SetAutoSize::ID);
- EXPECT_FALSE(auto_size_msg);
-
- // Send the BrowserPlugin an UpdateRect equal to its |max_size|.
- BrowserPluginMsg_UpdateRect_Params update_rect_params;
- update_rect_params.view_size = gfx::Size(1337, 1338);
- update_rect_params.scale_factor = 1.0f;
- update_rect_params.is_resize_ack = true;
- BrowserPluginMsg_UpdateRect msg(instance_id, update_rect_params);
- browser_plugin->OnMessageReceived(msg);
-
- // Verify that the autosize state has been updated.
- {
- const IPC::Message* auto_size_msg =
- browser_plugin_manager()->sink().GetUniqueMessageMatching(
- BrowserPluginHostMsg_SetAutoSize::ID);
- ASSERT_TRUE(auto_size_msg);
-
- BrowserPluginHostMsg_SetAutoSize::Param param;
- BrowserPluginHostMsg_SetAutoSize::Read(auto_size_msg, &param);
- BrowserPluginHostMsg_AutoSize_Params auto_size_params = param.b;
- BrowserPluginHostMsg_ResizeGuest_Params resize_params = param.c;
- EXPECT_FALSE(auto_size_params.enable);
- // These value are not populated (as an optimization) if autosize is
- // disabled.
- EXPECT_EQ(0, auto_size_params.min_size.width());
- EXPECT_EQ(0, auto_size_params.min_size.height());
- EXPECT_EQ(0, auto_size_params.max_size.width());
- EXPECT_EQ(0, auto_size_params.max_size.height());
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.h b/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.h
deleted file mode 100644
index 434da343f42..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_browsertest.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_BROWSERETEST_H_
-#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_BROWSERETEST_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/public/test/render_view_test.h"
-#include "content/renderer/browser_plugin/mock_browser_plugin_manager.h"
-#include "content/renderer/render_view_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-class RenderThreadImpl;
-
-namespace content {
-
-class MockBrowserPlugin;
-
-class BrowserPluginTest : public RenderViewTest {
- public:
- BrowserPluginTest();
- virtual ~BrowserPluginTest();
-
- virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
-
- MockBrowserPluginManager* browser_plugin_manager() const {
- return static_cast<MockBrowserPluginManager*>(
- static_cast<RenderViewImpl*>(view_)->GetBrowserPluginManager());
- }
- std::string ExecuteScriptAndReturnString(const std::string& script);
- int ExecuteScriptAndReturnInt(const std::string& script);
- bool ExecuteScriptAndReturnBool(const std::string& script, bool* result);
- // Returns NULL if there is no plugin.
- MockBrowserPlugin* GetCurrentPlugin();
- // Returns NULL if there is no plugin.
- MockBrowserPlugin* GetCurrentPluginWithAttachParams(
- BrowserPluginHostMsg_Attach_Params* params);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_BROWSERETEST_H_
-
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc b/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc
index 03120d82f78..16cc98e0009 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc
@@ -4,27 +4,26 @@
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
-#include "base/lazy_instance.h"
-#include "base/threading/thread_local.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/browser_plugin/browser_plugin_constants.h"
+#include "content/common/browser_plugin/browser_plugin_messages.h"
+#include "content/common/frame_messages.h"
+#include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
-#include "content/renderer/browser_plugin/browser_plugin_manager_factory.h"
-#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
+#include "ipc/ipc_message_macros.h"
namespace content {
// static
-BrowserPluginManagerFactory* BrowserPluginManager::factory_ = NULL;
-
BrowserPluginManager* BrowserPluginManager::Create(
RenderViewImpl* render_view) {
- if (factory_)
- return factory_->CreateBrowserPluginManager(render_view);
- return new BrowserPluginManagerImpl(render_view);
+ return new BrowserPluginManager(render_view);
}
BrowserPluginManager::BrowserPluginManager(RenderViewImpl* render_view)
: RenderViewObserver(render_view),
+ current_instance_id_(browser_plugin::kInstanceIDNone),
render_view_(render_view->AsWeakPtr()) {
}
@@ -32,24 +31,28 @@ BrowserPluginManager::~BrowserPluginManager() {
}
void BrowserPluginManager::AddBrowserPlugin(
- int guest_instance_id,
+ int browser_plugin_instance_id,
BrowserPlugin* browser_plugin) {
- instances_.AddWithID(browser_plugin, guest_instance_id);
+ instances_.AddWithID(browser_plugin, browser_plugin_instance_id);
}
-void BrowserPluginManager::RemoveBrowserPlugin(int guest_instance_id) {
- instances_.Remove(guest_instance_id);
+void BrowserPluginManager::RemoveBrowserPlugin(int browser_plugin_instance_id) {
+ instances_.Remove(browser_plugin_instance_id);
}
BrowserPlugin* BrowserPluginManager::GetBrowserPlugin(
- int guest_instance_id) const {
- return instances_.Lookup(guest_instance_id);
+ int browser_plugin_instance_id) const {
+ return instances_.Lookup(browser_plugin_instance_id);
+}
+
+int BrowserPluginManager::GetNextInstanceID() {
+ return ++current_instance_id_;
}
-void BrowserPluginManager::UpdateDeviceScaleFactor(float device_scale_factor) {
+void BrowserPluginManager::UpdateDeviceScaleFactor() {
IDMap<BrowserPlugin>::iterator iter(&instances_);
while (!iter.IsAtEnd()) {
- iter.GetCurrentValue()->UpdateDeviceScaleFactor(device_scale_factor);
+ iter.GetCurrentValue()->UpdateDeviceScaleFactor();
iter.Advance();
}
}
@@ -62,4 +65,68 @@ void BrowserPluginManager::UpdateFocusState() {
}
}
+void BrowserPluginManager::Attach(int browser_plugin_instance_id) {
+ BrowserPlugin* plugin = GetBrowserPlugin(browser_plugin_instance_id);
+ if (plugin)
+ plugin->Attach();
+}
+
+BrowserPlugin* BrowserPluginManager::CreateBrowserPlugin(
+ RenderViewImpl* render_view,
+ blink::WebFrame* frame,
+ scoped_ptr<BrowserPluginDelegate> delegate) {
+ return new BrowserPlugin(render_view, frame, delegate.Pass());
+}
+
+void BrowserPluginManager::DidCommitCompositorFrame() {
+ IDMap<BrowserPlugin>::iterator iter(&instances_);
+ while (!iter.IsAtEnd()) {
+ iter.GetCurrentValue()->DidCommitCompositorFrame();
+ iter.Advance();
+ }
+}
+
+bool BrowserPluginManager::OnMessageReceived(
+ const IPC::Message& message) {
+ if (!BrowserPlugin::ShouldForwardToBrowserPlugin(message))
+ return false;
+
+ int browser_plugin_instance_id = browser_plugin::kInstanceIDNone;
+ // All allowed messages must have |browser_plugin_instance_id| as their
+ // first parameter.
+ PickleIterator iter(message);
+ bool success = iter.ReadInt(&browser_plugin_instance_id);
+ DCHECK(success);
+ BrowserPlugin* plugin = GetBrowserPlugin(browser_plugin_instance_id);
+ if (plugin && plugin->OnMessageReceived(message))
+ return true;
+
+ // TODO(fsamuel): This is probably forcing the compositor to continue working
+ // even on display:none. We should optimize this.
+ if (message.type() == BrowserPluginMsg_CompositorFrameSwapped::ID) {
+ OnCompositorFrameSwappedPluginUnavailable(message);
+ return true;
+ }
+
+ return false;
+}
+
+bool BrowserPluginManager::Send(IPC::Message* msg) {
+ return RenderThread::Get()->Send(msg);
+}
+
+void BrowserPluginManager::OnCompositorFrameSwappedPluginUnavailable(
+ const IPC::Message& message) {
+ BrowserPluginMsg_CompositorFrameSwapped::Param param;
+ if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message, &param))
+ return;
+
+ FrameHostMsg_CompositorFrameSwappedACK_Params params;
+ params.producing_host_id = param.b.producing_host_id;
+ params.producing_route_id = param.b.producing_route_id;
+ params.output_surface_id = param.b.output_surface_id;
+ Send(new BrowserPluginHostMsg_CompositorFrameSwappedACK(
+ routing_id(), param.a, params));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
index 636f6ad2d97..23cde185ed3 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
@@ -8,19 +8,17 @@
#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
#include "content/public/renderer/render_view_observer.h"
#include "ipc/ipc_sender.h"
namespace blink {
class WebFrame;
-struct WebPluginParams;
}
namespace content {
class BrowserPlugin;
-class BrowserPluginManagerFactory;
+class BrowserPluginDelegate;
class RenderViewImpl;
// BrowserPluginManager manages the routing of messages to the appropriate
@@ -32,51 +30,52 @@ class CONTENT_EXPORT BrowserPluginManager
// Returns the one BrowserPluginManager for this process.
static BrowserPluginManager* Create(RenderViewImpl* render_view);
- // Overrides factory for testing. Default (NULL) value indicates regular
- // (non-test) environment.
- static void set_factory_for_testing(BrowserPluginManagerFactory* factory) {
- BrowserPluginManager::factory_ = factory;
- }
-
explicit BrowserPluginManager(RenderViewImpl* render_view);
// Creates a new BrowserPlugin object.
// BrowserPlugin is responsible for associating itself with the
// BrowserPluginManager via AddBrowserPlugin. When it is destroyed, it is
// responsible for removing its association via RemoveBrowserPlugin.
- virtual BrowserPlugin* CreateBrowserPlugin(
+ BrowserPlugin* CreateBrowserPlugin(
RenderViewImpl* render_view,
blink::WebFrame* frame,
- bool auto_navigate) = 0;
+ scoped_ptr<BrowserPluginDelegate> delegate);
+
+ void Attach(int browser_plugin_instance_id);
+
+ void AddBrowserPlugin(int browser_plugin_instance_id,
+ BrowserPlugin* browser_plugin);
+ void RemoveBrowserPlugin(int browser_plugin_instance_id);
+ BrowserPlugin* GetBrowserPlugin(int browser_plugin_instance_id) const;
- void AddBrowserPlugin(int guest_instance_id, BrowserPlugin* browser_plugin);
- void RemoveBrowserPlugin(int guest_instance_id);
- BrowserPlugin* GetBrowserPlugin(int guest_instance_id) const;
- void UpdateDeviceScaleFactor(float device_scale_factor);
+ void UpdateDeviceScaleFactor();
void UpdateFocusState();
RenderViewImpl* render_view() const { return render_view_.get(); }
+ int GetNextInstanceID();
- // RenderViewObserver implementation.
-
- // BrowserPluginManager must override the default Send behavior.
- virtual bool Send(IPC::Message* msg) OVERRIDE = 0;
+ // RenderViewObserver override. Call on render thread.
+ void DidCommitCompositorFrame() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ bool Send(IPC::Message* msg) override;
// Don't destroy the BrowserPluginManager when the RenderViewImpl goes away.
// BrowserPluginManager's lifetime is managed by a reference count. Once
// the host RenderViewImpl and all BrowserPlugins release their references,
// then the BrowserPluginManager will be destroyed.
- virtual void OnDestruct() OVERRIDE {}
+ void OnDestruct() override {}
- protected:
+ private:
// Friend RefCounted so that the dtor can be non-public.
friend class base::RefCounted<BrowserPluginManager>;
- // Static factory instance (always NULL for non-test).
- static BrowserPluginManagerFactory* factory_;
+ ~BrowserPluginManager() override;
+
+ // IPC message handlers.
+ void OnCompositorFrameSwappedPluginUnavailable(const IPC::Message& message);
- virtual ~BrowserPluginManager();
// This map is keyed by guest instance IDs.
IDMap<BrowserPlugin> instances_;
+ int current_instance_id_;
base::WeakPtr<RenderViewImpl> render_view_;
DISALLOW_COPY_AND_ASSIGN(BrowserPluginManager);
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_factory.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager_factory.h
deleted file mode 100644
index 3178fededbd..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_factory.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_MANAGER_FACTORY_H_
-#define CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_MANAGER_FACTORY_H_
-
-namespace content {
-
-class CONTENT_EXPORT BrowserPluginManagerFactory {
- public:
- virtual BrowserPluginManager* CreateBrowserPluginManager(
- RenderViewImpl* render_view) = 0;
-
- protected:
- virtual ~BrowserPluginManagerFactory() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BROWSER_PLUGIN_BROWSER_PLUGIN_MANAGER_FACTORY_H_
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
deleted file mode 100644
index 54f557a6082..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
-
-#include "content/common/browser_plugin/browser_plugin_constants.h"
-#include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/common/cursors/webcursor.h"
-#include "content/renderer/browser_plugin/browser_plugin.h"
-#include "content/renderer/render_thread_impl.h"
-#include "ui/gfx/point.h"
-
-namespace content {
-
-BrowserPluginManagerImpl::BrowserPluginManagerImpl(RenderViewImpl* render_view)
- : BrowserPluginManager(render_view) {
-}
-
-BrowserPluginManagerImpl::~BrowserPluginManagerImpl() {
-}
-
-BrowserPlugin* BrowserPluginManagerImpl::CreateBrowserPlugin(
- RenderViewImpl* render_view,
- blink::WebFrame* frame,
- bool auto_navigate) {
- return new BrowserPlugin(render_view, frame, auto_navigate);
-}
-
-bool BrowserPluginManagerImpl::Send(IPC::Message* msg) {
- return RenderThread::Get()->Send(msg);
-}
-
-bool BrowserPluginManagerImpl::OnMessageReceived(
- const IPC::Message& message) {
- if (BrowserPlugin::ShouldForwardToBrowserPlugin(message)) {
- int guest_instance_id = browser_plugin::kInstanceIDNone;
- // All allowed messages must have |guest_instance_id| as their first
- // parameter.
- PickleIterator iter(message);
- bool success = iter.ReadInt(&guest_instance_id);
- DCHECK(success);
- BrowserPlugin* plugin = GetBrowserPlugin(guest_instance_id);
- if (plugin && plugin->OnMessageReceived(message))
- return true;
- }
-
- return false;
-}
-
-void BrowserPluginManagerImpl::DidCommitCompositorFrame() {
- IDMap<BrowserPlugin>::iterator iter(&instances_);
- while (!iter.IsAtEnd()) {
- iter.GetCurrentValue()->DidCommitCompositorFrame();
- iter.Advance();
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h
deleted file mode 100644
index 219ff30a001..00000000000
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager_impl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_MANAGER_IMPL_H_
-#define CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_MANAGER_IMPL_H_
-
-#include <map>
-
-#include "content/renderer/browser_plugin/browser_plugin_manager.h"
-#include "ui/gfx/size.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace content {
-
-class BrowserPluginManagerImpl : public BrowserPluginManager {
- public:
- explicit BrowserPluginManagerImpl(RenderViewImpl* render_view);
-
- // BrowserPluginManager implementation.
- virtual BrowserPlugin* CreateBrowserPlugin(
- RenderViewImpl* render_view,
- blink::WebFrame* frame,
- bool auto_navigate) OVERRIDE;
-
- // IPC::Sender implementation.
- virtual bool Send(IPC::Message* msg) OVERRIDE;
-
- // RenderViewObserver override. Call on render thread.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void DidCommitCompositorFrame() OVERRIDE;
-
- private:
- virtual ~BrowserPluginManagerImpl();
-
- DISALLOW_COPY_AND_ASSIGN(BrowserPluginManagerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BROWSER_PLUGIN_BROWSER_PLUGIN_MANAGER_IMPL_H_
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc b/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc
deleted file mode 100644
index 1d7df152561..00000000000
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/browser_plugin/mock_browser_plugin.h"
-#include "content/renderer/render_process_impl.h"
-
-namespace content {
-
-MockBrowserPlugin::MockBrowserPlugin(RenderViewImpl* render_view,
- blink::WebFrame* frame,
- bool auto_navigate)
- : BrowserPlugin(render_view, frame, auto_navigate) {
-}
-
-MockBrowserPlugin::~MockBrowserPlugin() {}
-
-} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin.h b/chromium/content/renderer/browser_plugin/mock_browser_plugin.h
deleted file mode 100644
index c1655761653..00000000000
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_MOCK_BROWSER_PLUGIN_H_
-#define CONTENT_RENDERER_BROWSER_PLUGIN_MOCK_BROWSER_PLUGIN_H_
-
-#include "content/renderer/browser_plugin/browser_plugin.h"
-
-namespace content {
-
-class MockBrowserPlugin : public BrowserPlugin {
- public:
- MockBrowserPlugin(RenderViewImpl* render_view,
- blink::WebFrame* frame,
- bool auto_navigate);
-
- virtual ~MockBrowserPlugin();
-
- // Allow poking at a few private members.
- using BrowserPlugin::OnAttachACK;
- using BrowserPlugin::guest_crashed_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BROWSER_PLUGIN_MOCK_BROWSER_PLUGIN_H_
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
deleted file mode 100644
index 36d78b8675b..00000000000
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/browser_plugin/mock_browser_plugin_manager.h"
-
-#include "base/message_loop/message_loop.h"
-#include "content/common/browser_plugin/browser_plugin_messages.h"
-#include "content/renderer/browser_plugin/mock_browser_plugin.h"
-#include "ipc/ipc_message.h"
-
-namespace content {
-
-MockBrowserPluginManager::MockBrowserPluginManager(
- RenderViewImpl* render_view)
- : BrowserPluginManager(render_view),
- guest_instance_id_counter_(0),
- last_plugin_(NULL) {
-}
-
-MockBrowserPluginManager::~MockBrowserPluginManager() {
-}
-
-BrowserPlugin* MockBrowserPluginManager::CreateBrowserPlugin(
- RenderViewImpl* render_view,
- blink::WebFrame* frame,
- bool auto_navigate) {
- last_plugin_ = new MockBrowserPlugin(render_view, frame, auto_navigate);
- return last_plugin_;
-}
-
-void MockBrowserPluginManager::AllocateInstanceID(
- BrowserPlugin* browser_plugin) {
- AllocateInstanceIDACK(browser_plugin, ++guest_instance_id_counter_);
-}
-
-void MockBrowserPluginManager::AllocateInstanceIDACK(
- BrowserPlugin* browser_plugin,
- int guest_instance_id) {
- scoped_ptr<base::DictionaryValue> extra_params(new base::DictionaryValue());
- browser_plugin->Attach(guest_instance_id, extra_params.Pass());
-}
-
-bool MockBrowserPluginManager::Send(IPC::Message* msg) {
- // This is a copy-and-paste from MockRenderThread::Send.
- // We need to simulate a synchronous channel, thus we are going to receive
- // through this function messages, messages with reply and reply messages.
- // We can only handle one synchronous message at a time.
- if (msg->is_reply()) {
- if (reply_deserializer_) {
- reply_deserializer_->SerializeOutputParameters(*msg);
- reply_deserializer_.reset();
- }
- } else {
- if (msg->is_sync()) {
- // We actually need to handle deleting the reply deserializer for sync
- // messages.
- reply_deserializer_.reset(
- static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer());
- }
- OnMessageReceived(*msg);
- }
- delete msg;
- return true;
-}
-
-bool MockBrowserPluginManager::OnMessageReceived(
- const IPC::Message& message) {
- // Save the message in the sink.
- sink_.OnMessageReceived(message);
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h
deleted file mode 100644
index b3614c74c94..00000000000
--- a/chromium/content/renderer/browser_plugin/mock_browser_plugin_manager.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_BROWSER_PLUGIN_MOCK_BROWSER_PLUGIN_MANAGER_H_
-#define CONTENT_RENDERER_BROWSER_PLUGIN_MOCK_BROWSER_PLUGIN_MANAGER_H_
-
-#include "content/renderer/browser_plugin/browser_plugin_manager.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "ipc/ipc_message_utils.h"
-#include "ipc/ipc_test_sink.h"
-
-namespace content {
-
-class MockBrowserPlugin;
-
-class MockBrowserPluginManager : public BrowserPluginManager {
- public:
- MockBrowserPluginManager(RenderViewImpl* render_view);
-
- // BrowserPluginManager implementation.
- virtual BrowserPlugin* CreateBrowserPlugin(
- RenderViewImpl* render_view,
- blink::WebFrame* frame,
- bool auto_navigate) OVERRIDE;
-
- // Provides access to the messages that have been received by this thread.
- IPC::TestSink& sink() { return sink_; }
-
- // Allocates instance ID for the browser plugin.
- void AllocateInstanceID(BrowserPlugin* browser_plugin);
-
- // RenderViewObserver override.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual bool Send(IPC::Message* msg) OVERRIDE;
-
- // Returns the latest browser plugin that was created by this manager.
- MockBrowserPlugin* last_plugin() { return last_plugin_; }
-
- protected:
- virtual ~MockBrowserPluginManager();
- void AllocateInstanceIDACK(BrowserPlugin* browser_plugin,
- int guest_instance_id);
-
- IPC::TestSink sink_;
-
- // The last known good deserializer for sync messages.
- scoped_ptr<IPC::MessageReplyDeserializer> reply_deserializer_;
-
- int guest_instance_id_counter_;
- MockBrowserPlugin* last_plugin_;
-
- DISALLOW_COPY_AND_ASSIGN(MockBrowserPluginManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BROWSER_PLUGIN_MOCK_BROWSER_PLUGIN_MANAGER_H_
diff --git a/chromium/content/renderer/browser_render_view_browsertest.cc b/chromium/content/renderer/browser_render_view_browsertest.cc
index 1172d02285d..2c12bc7a478 100644
--- a/chromium/content/renderer/browser_render_view_browsertest.cc
+++ b/chromium/content/renderer/browser_render_view_browsertest.cc
@@ -49,13 +49,12 @@ class TestShellContentRendererClient : public ShellContentRendererClient {
latest_error_reason_(0),
latest_error_stale_copy_in_cache_(false) {}
- virtual void GetNavigationErrorStrings(
- content::RenderView* render_view,
- blink::WebFrame* frame,
- const blink::WebURLRequest& failed_request,
- const blink::WebURLError& error,
- std::string* error_html,
- base::string16* error_description) OVERRIDE {
+ void GetNavigationErrorStrings(content::RenderView* render_view,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& failed_request,
+ const blink::WebURLError& error,
+ std::string* error_html,
+ base::string16* error_description) override {
if (error_html)
*error_html = "A suffusion of yellow.";
latest_error_valid_ = true;
@@ -88,8 +87,7 @@ void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
new net::FailingHttpTransactionFactory(cache->GetSession(), error));
// Throw away old version; since this is a browser test, there is no
// need to restore the old state.
- cache->SetHttpNetworkTransactionFactoryForTesting(
- factory.PassAs<net::HttpTransactionFactory>());
+ cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
}
void CallOnUIThreadValidatingReturn(const base::Closure& callback,
@@ -139,13 +137,13 @@ class RenderViewBrowserTest : public ContentBrowserTest {
public:
RenderViewBrowserTest() {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
// This method is needed to allow interaction with in-process renderer
// and use of a test ContentRendererClient.
command_line->AppendSwitch(switches::kSingleProcess);
}
- virtual void SetUpOnMainThread() OVERRIDE {
+ void SetUpOnMainThread() override {
// Override setting of renderer client.
renderer_client_ = new TestShellContentRendererClient();
// Explicitly leaks ownership; this object will remain alive
diff --git a/chromium/content/renderer/child_frame_compositing_helper.cc b/chromium/content/renderer/child_frame_compositing_helper.cc
index 8790ae2d8a8..841cfadf704 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.cc
+++ b/chromium/content/renderer/child_frame_compositing_helper.cc
@@ -4,11 +4,11 @@
#include "content/renderer/child_frame_compositing_helper.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/layers/delegated_frame_provider.h"
#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/solid_color_layer.h"
-#include "cc/layers/texture_layer.h"
#include "cc/output/context_provider.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
@@ -18,12 +18,10 @@
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_thread_impl.h"
#include "skia/ext/image_operations.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -32,28 +30,20 @@
namespace content {
-ChildFrameCompositingHelper::SwapBuffersInfo::SwapBuffersInfo()
- : route_id(0),
- output_surface_id(0),
- host_id(0),
- software_frame_id(0),
- shared_memory(NULL) {}
-
ChildFrameCompositingHelper*
-ChildFrameCompositingHelper::CreateCompositingHelperForBrowserPlugin(
+ChildFrameCompositingHelper::CreateForBrowserPlugin(
const base::WeakPtr<BrowserPlugin>& browser_plugin) {
return new ChildFrameCompositingHelper(
browser_plugin, NULL, NULL, browser_plugin->render_view_routing_id());
}
ChildFrameCompositingHelper*
-ChildFrameCompositingHelper::CreateCompositingHelperForRenderFrame(
- blink::WebFrame* frame,
- RenderFrameProxy* render_frame_proxy,
- int host_routing_id) {
- return new ChildFrameCompositingHelper(
- base::WeakPtr<BrowserPlugin>(), frame, render_frame_proxy,
- host_routing_id);
+ChildFrameCompositingHelper::CreateForRenderFrameProxy(
+ RenderFrameProxy* render_frame_proxy) {
+ return new ChildFrameCompositingHelper(base::WeakPtr<BrowserPlugin>(),
+ render_frame_proxy->web_frame(),
+ render_frame_proxy,
+ render_frame_proxy->routing_id());
}
ChildFrameCompositingHelper::ChildFrameCompositingHelper(
@@ -65,9 +55,7 @@ ChildFrameCompositingHelper::ChildFrameCompositingHelper(
last_route_id_(0),
last_output_surface_id_(0),
last_host_id_(0),
- last_mailbox_valid_(false),
ack_pending_(true),
- software_ack_pending_(false),
opaque_(true),
browser_plugin_(browser_plugin),
render_frame_proxy_(render_frame_proxy),
@@ -93,7 +81,7 @@ int ChildFrameCompositingHelper::GetInstanceID() {
if (!browser_plugin_)
return 0;
- return browser_plugin_->guest_instance_id();
+ return browser_plugin_->browser_plugin_instance_id();
}
void ChildFrameCompositingHelper::SendCompositorFrameSwappedACKToBrowser(
@@ -110,19 +98,6 @@ void ChildFrameCompositingHelper::SendCompositorFrameSwappedACKToBrowser(
}
}
-void ChildFrameCompositingHelper::SendBuffersSwappedACKToBrowser(
- FrameHostMsg_BuffersSwappedACK_Params& params) {
- // This function will be removed when BrowserPluginManager is removed and
- // BrowserPlugin is modified to use a RenderFrame.
- if (GetBrowserPluginManager()) {
- GetBrowserPluginManager()->Send(new BrowserPluginHostMsg_BuffersSwappedACK(
- host_routing_id_, params));
- } else if (render_frame_proxy_) {
- render_frame_proxy_->Send(
- new FrameHostMsg_BuffersSwappedACK(host_routing_id_, params));
- }
-}
-
void ChildFrameCompositingHelper::SendReclaimCompositorResourcesToBrowser(
FrameHostMsg_ReclaimCompositorResources_Params& params) {
// This function will be removed when BrowserPluginManager is removed and
@@ -137,36 +112,7 @@ void ChildFrameCompositingHelper::SendReclaimCompositorResourcesToBrowser(
}
}
-void ChildFrameCompositingHelper::CopyFromCompositingSurface(
- int request_id,
- gfx::Rect source_rect,
- gfx::Size dest_size) {
- CHECK(background_layer_);
- scoped_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
- &ChildFrameCompositingHelper::CopyFromCompositingSurfaceHasResult,
- this,
- request_id,
- dest_size));
- request->set_area(source_rect);
- background_layer_->RequestCopyOfOutput(request.Pass());
-}
-
void ChildFrameCompositingHelper::DidCommitCompositorFrame() {
- if (software_ack_pending_) {
- FrameHostMsg_CompositorFrameSwappedACK_Params params;
- params.producing_host_id = last_host_id_;
- params.producing_route_id = last_route_id_;
- params.output_surface_id = last_output_surface_id_;
- if (!unacked_software_frames_.empty()) {
- params.ack.last_software_frame_id = unacked_software_frames_.back();
- unacked_software_frames_.pop_back();
- }
-
- SendCompositorFrameSwappedACKToBrowser(params);
-
- software_ack_pending_ = false;
- }
if (!resource_collection_.get() || !ack_pending_)
return;
@@ -188,7 +134,7 @@ void ChildFrameCompositingHelper::EnableCompositing(bool enable) {
background_layer_->SetMasksToBounds(true);
background_layer_->SetBackgroundColor(
SkColorSetARGBInline(255, 255, 255, 255));
- web_layer_.reset(new WebLayerImpl(background_layer_));
+ web_layer_.reset(new cc_blink::WebLayerImpl(background_layer_));
}
if (GetContainer()) {
@@ -217,74 +163,16 @@ void ChildFrameCompositingHelper::CheckSizeAndAdjustLayerProperties(
background_layer_->SetIsDrawable(false);
}
-void ChildFrameCompositingHelper::MailboxReleased(SwapBuffersInfo mailbox,
- uint32 sync_point,
- bool lost_resource) {
- if (mailbox.type == SOFTWARE_COMPOSITOR_FRAME) {
- delete mailbox.shared_memory;
- mailbox.shared_memory = NULL;
- } else if (lost_resource) {
- // Reset mailbox's name if the resource was lost.
- mailbox.name.SetZero();
- }
-
- // This means the GPU process crashed or guest crashed.
- if (last_host_id_ != mailbox.host_id ||
- last_output_surface_id_ != mailbox.output_surface_id ||
- last_route_id_ != mailbox.route_id)
- return;
-
- if (mailbox.type == SOFTWARE_COMPOSITOR_FRAME)
- unacked_software_frames_.push_back(mailbox.software_frame_id);
-
- // We need to send an ACK to for every buffer sent to us.
- // However, if a buffer is freed up from
- // the compositor in cases like switching back to SW mode without a new
- // buffer arriving, no ACK is needed.
- if (!ack_pending_) {
- last_mailbox_valid_ = false;
- return;
- }
- ack_pending_ = false;
- switch (mailbox.type) {
- case TEXTURE_IMAGE_TRANSPORT: {
- FrameHostMsg_BuffersSwappedACK_Params params;
- params.gpu_host_id = mailbox.host_id;
- params.gpu_route_id = mailbox.route_id;
- params.mailbox = mailbox.name;
- params.sync_point = sync_point;
- SendBuffersSwappedACKToBrowser(params);
- break;
- }
- case GL_COMPOSITOR_FRAME: {
- FrameHostMsg_CompositorFrameSwappedACK_Params params;
- params.producing_host_id = mailbox.host_id;
- params.producing_route_id = mailbox.route_id;
- params.output_surface_id = mailbox.output_surface_id;
- params.ack.gl_frame_data.reset(new cc::GLFrameData());
- params.ack.gl_frame_data->mailbox = mailbox.name;
- params.ack.gl_frame_data->size = mailbox.size;
- params.ack.gl_frame_data->sync_point = sync_point;
- SendCompositorFrameSwappedACKToBrowser(params);
- break;
- }
- case SOFTWARE_COMPOSITOR_FRAME:
- break;
- }
-}
-
void ChildFrameCompositingHelper::OnContainerDestroy() {
if (GetContainer())
GetContainer()->setWebLayer(NULL);
- if (resource_collection_)
+ if (resource_collection_.get())
resource_collection_->SetClient(NULL);
ack_pending_ = false;
- software_ack_pending_ = false;
resource_collection_ = NULL;
frame_provider_ = NULL;
- texture_layer_ = NULL;
delegated_layer_ = NULL;
background_layer_ = NULL;
web_layer_.reset();
@@ -297,159 +185,15 @@ void ChildFrameCompositingHelper::ChildFrameGone() {
background_layer_->SetContentsOpaque(true);
}
-void ChildFrameCompositingHelper::OnBuffersSwappedPrivate(
- const SwapBuffersInfo& mailbox,
- uint32 sync_point,
- float device_scale_factor) {
- DCHECK(!delegated_layer_.get());
- // If these mismatch, we are either just starting up, GPU process crashed or
- // guest renderer crashed.
- // In this case, we are communicating with a new image transport
- // surface and must ACK with the new ID's and an empty mailbox.
- if (last_route_id_ != mailbox.route_id ||
- last_output_surface_id_ != mailbox.output_surface_id ||
- last_host_id_ != mailbox.host_id)
- last_mailbox_valid_ = false;
-
- last_route_id_ = mailbox.route_id;
- last_output_surface_id_ = mailbox.output_surface_id;
- last_host_id_ = mailbox.host_id;
-
- ack_pending_ = true;
- // Browser plugin getting destroyed, do a fast ACK.
- if (!background_layer_.get()) {
- MailboxReleased(mailbox, sync_point, false);
- return;
- }
-
- if (!texture_layer_.get()) {
- texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
- texture_layer_->SetIsDrawable(true);
- SetContentsOpaque(opaque_);
-
- background_layer_->AddChild(texture_layer_);
- }
-
- // The size of browser plugin container is not always equal to the size
- // of the buffer that arrives here. This could be for a number of reasons,
- // including autosize and a resize in progress.
- // During resize, the container size changes first and then some time
- // later, a new buffer with updated size will arrive. During this process,
- // we need to make sure that things are still displayed pixel perfect.
- // We accomplish this by modifying bounds of the texture layer only
- // when a new buffer arrives.
- // Visually, this will either display a smaller part of the buffer
- // or introduce a gutter around it.
- CheckSizeAndAdjustLayerProperties(
- mailbox.size, device_scale_factor, texture_layer_.get());
-
- bool is_software_frame = mailbox.type == SOFTWARE_COMPOSITOR_FRAME;
- bool current_mailbox_valid = is_software_frame ? mailbox.shared_memory != NULL
- : !mailbox.name.IsZero();
- if (!is_software_frame && !last_mailbox_valid_) {
- SwapBuffersInfo empty_info = mailbox;
- empty_info.name.SetZero();
- MailboxReleased(empty_info, 0, false);
- if (!current_mailbox_valid)
- return;
- }
-
- cc::TextureMailbox texture_mailbox;
- scoped_ptr<cc::SingleReleaseCallback> release_callback;
- if (current_mailbox_valid) {
- release_callback =
- cc::SingleReleaseCallback::Create(
- base::Bind(&ChildFrameCompositingHelper::MailboxReleased,
- scoped_refptr<ChildFrameCompositingHelper>(this),
- mailbox)).Pass();
- if (is_software_frame) {
- texture_mailbox = cc::TextureMailbox(mailbox.shared_memory, mailbox.size);
- } else {
- texture_mailbox =
- cc::TextureMailbox(mailbox.name, GL_TEXTURE_2D, sync_point);
- }
- }
-
- texture_layer_->SetFlipped(!is_software_frame);
- texture_layer_->SetTextureMailbox(texture_mailbox, release_callback.Pass());
- texture_layer_->SetNeedsDisplay();
- last_mailbox_valid_ = current_mailbox_valid;
-}
-
-void ChildFrameCompositingHelper::OnBuffersSwapped(
- const gfx::Size& size,
- const gpu::Mailbox& mailbox,
- int gpu_route_id,
- int gpu_host_id,
- float device_scale_factor) {
- SwapBuffersInfo swap_info;
- swap_info.name = mailbox;
- swap_info.type = TEXTURE_IMAGE_TRANSPORT;
- swap_info.size = size;
- swap_info.route_id = gpu_route_id;
- swap_info.output_surface_id = 0;
- swap_info.host_id = gpu_host_id;
- OnBuffersSwappedPrivate(swap_info, 0, device_scale_factor);
-}
-
void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
scoped_ptr<cc::CompositorFrame> frame,
int route_id,
uint32 output_surface_id,
int host_id,
base::SharedMemoryHandle handle) {
-
- if (frame->gl_frame_data) {
- SwapBuffersInfo swap_info;
- swap_info.name = frame->gl_frame_data->mailbox;
- swap_info.type = GL_COMPOSITOR_FRAME;
- swap_info.size = frame->gl_frame_data->size;
- swap_info.route_id = route_id;
- swap_info.output_surface_id = output_surface_id;
- swap_info.host_id = host_id;
- OnBuffersSwappedPrivate(swap_info,
- frame->gl_frame_data->sync_point,
- frame->metadata.device_scale_factor);
- return;
- }
-
- if (frame->software_frame_data) {
- cc::SoftwareFrameData* frame_data = frame->software_frame_data.get();
-
- SwapBuffersInfo swap_info;
- swap_info.type = SOFTWARE_COMPOSITOR_FRAME;
- swap_info.size = frame_data->size;
- swap_info.route_id = route_id;
- swap_info.output_surface_id = output_surface_id;
- swap_info.host_id = host_id;
- swap_info.software_frame_id = frame_data->id;
-
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(handle, true));
- const size_t size_in_bytes = 4 * frame_data->size.GetArea();
- if (!shared_memory->Map(size_in_bytes)) {
- LOG(ERROR) << "Failed to map shared memory of size " << size_in_bytes;
- // Send ACK right away.
- software_ack_pending_ = true;
- MailboxReleased(swap_info, 0, false);
- DidCommitCompositorFrame();
- return;
- }
-
- swap_info.shared_memory = shared_memory.release();
- OnBuffersSwappedPrivate(swap_info, 0, frame->metadata.device_scale_factor);
- software_ack_pending_ = true;
- last_route_id_ = route_id;
- last_output_surface_id_ = output_surface_id;
- last_host_id_ = host_id;
- return;
- }
-
- DCHECK(!texture_layer_.get());
-
cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
// Do nothing if we are getting destroyed or have no frame data.
- if (!frame_data || !background_layer_)
+ if (!frame_data || !background_layer_.get())
return;
DCHECK(!frame_data->render_pass_list.empty());
@@ -469,7 +213,7 @@ void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
// Drop the cc::DelegatedFrameResourceCollection so that we will not return
// any resources from the old output surface with the new output surface id.
- if (resource_collection_) {
+ if (resource_collection_.get()) {
resource_collection_->SetClient(NULL);
if (resource_collection_->LoseAllResources())
@@ -480,7 +224,7 @@ void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
last_route_id_ = route_id;
last_host_id_ = host_id;
}
- if (!resource_collection_) {
+ if (!resource_collection_.get()) {
resource_collection_ = new cc::DelegatedFrameResourceCollection;
resource_collection_->SetClient(this);
}
@@ -492,6 +236,7 @@ void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
delegated_layer_ =
cc::DelegatedRendererLayer::Create(frame_provider_.get());
delegated_layer_->SetIsDrawable(true);
+ buffer_size_ = gfx::Size();
SetContentsOpaque(opaque_);
background_layer_->AddChild(delegated_layer_);
} else {
@@ -507,8 +252,6 @@ void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
}
void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
- if (texture_layer_.get())
- texture_layer_->SetIsDrawable(visible);
if (delegated_layer_.get())
delegated_layer_->SetIsDrawable(visible);
}
@@ -522,7 +265,7 @@ void ChildFrameCompositingHelper::UnusedResourcesAreAvailable() {
void ChildFrameCompositingHelper::SendReturnedDelegatedResources() {
FrameHostMsg_ReclaimCompositorResources_Params params;
- if (resource_collection_)
+ if (resource_collection_.get())
resource_collection_->TakeUnusedResourcesForChildCompositor(
&params.ack.resources);
DCHECK(!params.ack.resources.empty());
@@ -535,34 +278,8 @@ void ChildFrameCompositingHelper::SendReturnedDelegatedResources() {
void ChildFrameCompositingHelper::SetContentsOpaque(bool opaque) {
opaque_ = opaque;
-
- if (texture_layer_.get())
- texture_layer_->SetContentsOpaque(opaque_);
if (delegated_layer_.get())
delegated_layer_->SetContentsOpaque(opaque_);
}
-void ChildFrameCompositingHelper::CopyFromCompositingSurfaceHasResult(
- int request_id,
- gfx::Size dest_size,
- scoped_ptr<cc::CopyOutputResult> result) {
- scoped_ptr<SkBitmap> bitmap;
- if (result && result->HasBitmap() && !result->size().IsEmpty())
- bitmap = result->TakeBitmap();
-
- SkBitmap resized_bitmap;
- if (bitmap) {
- resized_bitmap =
- skia::ImageOperations::Resize(*bitmap,
- skia::ImageOperations::RESIZE_BEST,
- dest_size.width(),
- dest_size.height());
- }
- if (GetBrowserPluginManager()) {
- GetBrowserPluginManager()->Send(
- new BrowserPluginHostMsg_CopyFromCompositingSurfaceAck(
- host_routing_id_, GetInstanceID(), request_id, resized_bitmap));
- }
-}
-
} // namespace content
diff --git a/chromium/content/renderer/child_frame_compositing_helper.h b/chromium/content/renderer/child_frame_compositing_helper.h
index d66ae3f7cd8..b6c4d57f2de 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.h
+++ b/chromium/content/renderer/child_frame_compositing_helper.h
@@ -13,7 +13,6 @@
#include "base/memory/shared_memory.h"
#include "cc/layers/delegated_frame_resource_collection.h"
#include "content/common/content_export.h"
-#include "gpu/command_buffer/common/mailbox.h"
#include "ui/gfx/size.h"
namespace base {
@@ -22,10 +21,8 @@ class SharedMemory;
namespace cc {
class CompositorFrame;
-class CopyOutputResult;
class Layer;
class SolidColorLayer;
-class TextureLayer;
class DelegatedFrameProvider;
class DelegatedFrameResourceCollection;
class DelegatedRendererLayer;
@@ -56,24 +53,14 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
: public base::RefCounted<ChildFrameCompositingHelper>,
public cc::DelegatedFrameResourceCollectionClient {
public:
- static ChildFrameCompositingHelper* CreateCompositingHelperForBrowserPlugin(
+ static ChildFrameCompositingHelper* CreateForBrowserPlugin(
const base::WeakPtr<BrowserPlugin>& browser_plugin);
- static ChildFrameCompositingHelper* CreateCompositingHelperForRenderFrame(
- blink::WebFrame* frame,
- RenderFrameProxy* render_frame_proxy,
- int host_routing_id);
+ static ChildFrameCompositingHelper* CreateForRenderFrameProxy(
+ RenderFrameProxy* render_frame_proxy);
- void CopyFromCompositingSurface(int request_id,
- gfx::Rect source_rect,
- gfx::Size dest_size);
void DidCommitCompositorFrame();
void EnableCompositing(bool);
void OnContainerDestroy();
- void OnBuffersSwapped(const gfx::Size& size,
- const gpu::Mailbox& mailbox,
- int gpu_route_id,
- int gpu_host_id,
- float device_scale_factor);
void OnCompositorFrameSwapped(scoped_ptr<cc::CompositorFrame> frame,
int route_id,
uint32 output_surface_id,
@@ -83,7 +70,7 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
void ChildFrameGone();
// cc::DelegatedFrameProviderClient implementation.
- virtual void UnusedResourcesAreAvailable() OVERRIDE;
+ void UnusedResourcesAreAvailable() override;
void SetContentsOpaque(bool);
protected:
@@ -97,23 +84,6 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
RenderFrameProxy* render_frame_proxy,
int host_routing_id);
- enum SwapBuffersType {
- TEXTURE_IMAGE_TRANSPORT,
- GL_COMPOSITOR_FRAME,
- SOFTWARE_COMPOSITOR_FRAME,
- };
- struct SwapBuffersInfo {
- SwapBuffersInfo();
-
- gpu::Mailbox name;
- SwapBuffersType type;
- gfx::Size size;
- int route_id;
- uint32 output_surface_id;
- int host_id;
- unsigned software_frame_id;
- base::SharedMemory* shared_memory;
- };
virtual ~ChildFrameCompositingHelper();
BrowserPluginManager* GetBrowserPluginManager();
@@ -122,34 +92,19 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
void SendCompositorFrameSwappedACKToBrowser(
FrameHostMsg_CompositorFrameSwappedACK_Params& params);
- void SendBuffersSwappedACKToBrowser(
- FrameHostMsg_BuffersSwappedACK_Params& params);
void SendReclaimCompositorResourcesToBrowser(
FrameHostMsg_ReclaimCompositorResources_Params& params);
void CheckSizeAndAdjustLayerProperties(const gfx::Size& new_size,
float device_scale_factor,
cc::Layer* layer);
- void OnBuffersSwappedPrivate(const SwapBuffersInfo& mailbox,
- unsigned sync_point,
- float device_scale_factor);
- void MailboxReleased(SwapBuffersInfo mailbox,
- unsigned sync_point,
- bool lost_resource);
void SendReturnedDelegatedResources();
- void CopyFromCompositingSurfaceHasResult(
- int request_id,
- gfx::Size dest_size,
- scoped_ptr<cc::CopyOutputResult> result);
int host_routing_id_;
int last_route_id_;
uint32 last_output_surface_id_;
int last_host_id_;
- bool last_mailbox_valid_;
bool ack_pending_;
- bool software_ack_pending_;
bool opaque_;
- std::vector<unsigned> unacked_software_frames_;
gfx::Size buffer_size_;
@@ -163,7 +118,6 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
scoped_refptr<cc::SolidColorLayer> background_layer_;
- scoped_refptr<cc::TextureLayer> texture_layer_;
scoped_refptr<cc::DelegatedRendererLayer> delegated_layer_;
scoped_ptr<blink::WebLayer> web_layer_;
blink::WebFrame* frame_;
diff --git a/chromium/content/renderer/chrome_object_extensions_utils.cc b/chromium/content/renderer/chrome_object_extensions_utils.cc
new file mode 100644
index 00000000000..b9c3cdebba2
--- /dev/null
+++ b/chromium/content/renderer/chrome_object_extensions_utils.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2014 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 "content/renderer/chrome_object_extensions_utils.h"
+
+#include "gin/converter.h"
+#include "v8/include/v8.h"
+
+namespace content {
+
+v8::Handle<v8::Object> GetOrCreateChromeObject(
+ v8::Isolate* isolate, v8::Handle<v8::Object> global) {
+ v8::Handle<v8::Object> chrome;
+ v8::Handle<v8::Value> chrome_value =
+ global->Get(gin::StringToV8(isolate, "chrome"));
+ if (chrome_value.IsEmpty() || !chrome_value->IsObject()) {
+ chrome = v8::Object::New(isolate);
+ global->Set(gin::StringToSymbol(isolate, "chrome"), chrome);
+ } else {
+ chrome = chrome_value->ToObject();
+ }
+ return chrome;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/chrome_object_extensions_utils.h b/chromium/content/renderer/chrome_object_extensions_utils.h
new file mode 100644
index 00000000000..1048616d79c
--- /dev/null
+++ b/chromium/content/renderer/chrome_object_extensions_utils.h
@@ -0,0 +1,17 @@
+// Copyright (c) 2014 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 CONTENT_RENDERER_CHROME_OBJECT_EXTENSIONS_UTILS_H_
+#define CONTENT_RENDERER_CHROME_OBJECT_EXTENSIONS_UTILS_H_
+
+#include "v8/include/v8.h"
+
+namespace content {
+
+v8::Handle<v8::Object> GetOrCreateChromeObject(
+ v8::Isolate* isolate, v8::Handle<v8::Object> global);
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_CHROME_OBJECT_EXTENSIONS_UTILS_H_
diff --git a/chromium/content/renderer/compositor_bindings/OWNERS b/chromium/content/renderer/compositor_bindings/OWNERS
deleted file mode 100644
index d42bb39ccd8..00000000000
--- a/chromium/content/renderer/compositor_bindings/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-enne@chromium.org
-nduca@chromium.org
diff --git a/chromium/content/renderer/compositor_bindings/PRESUBMIT.py b/chromium/content/renderer/compositor_bindings/PRESUBMIT.py
deleted file mode 100644
index 8e4e5718483..00000000000
--- a/chromium/content/renderer/compositor_bindings/PRESUBMIT.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2014 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.
-
-"""
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
-details on the presubmit API built into gcl.
-"""
-
-SOURCE_FILES = (r'^.*\.(cc|h)$')
-
-def CheckChangeLintsClean(input_api, output_api):
- input_api.cpplint._cpplint_state.ResetErrorCounts() # reset global state
- source_filter = lambda x: input_api.FilterSourceFile(
- x, white_list=SOURCE_FILES, black_list=None)
- files = [f.AbsoluteLocalPath() for f in
- input_api.AffectedSourceFiles(source_filter)]
- level = 1 # strict, but just warn
-
- for file_name in files:
- input_api.cpplint.ProcessFile(file_name, level)
-
- if not input_api.cpplint._cpplint_state.error_count:
- return []
-
- return [output_api.PresubmitPromptWarning(
- 'Changelist failed cpplint.py check.')]
-
-
-def CheckChangeOnUpload(input_api, output_api):
- results = []
- results += CheckChangeLintsClean(input_api, output_api)
- return results
diff --git a/chromium/content/renderer/compositor_bindings/scrollbar_impl.cc b/chromium/content/renderer/compositor_bindings/scrollbar_impl.cc
deleted file mode 100644
index 6ee82d42444..00000000000
--- a/chromium/content/renderer/compositor_bindings/scrollbar_impl.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/scrollbar_impl.h"
-
-#include "base/logging.h"
-#include "third_party/WebKit/public/platform/WebScrollbar.h"
-#include "third_party/WebKit/public/platform/WebScrollbarThemeGeometry.h"
-
-using blink::WebScrollbar;
-
-namespace content {
-
-ScrollbarImpl::ScrollbarImpl(
- scoped_ptr<WebScrollbar> scrollbar,
- blink::WebScrollbarThemePainter painter,
- scoped_ptr<blink::WebScrollbarThemeGeometry> geometry)
- : scrollbar_(scrollbar.Pass()),
- painter_(painter),
- geometry_(geometry.Pass()) {
-}
-
-ScrollbarImpl::~ScrollbarImpl() {
-}
-
-cc::ScrollbarOrientation ScrollbarImpl::Orientation() const {
- if (scrollbar_->orientation() == WebScrollbar::Horizontal)
- return cc::HORIZONTAL;
- return cc::VERTICAL;
-}
-
-bool ScrollbarImpl::IsLeftSideVerticalScrollbar() const {
- return scrollbar_->isLeftSideVerticalScrollbar();
-}
-
-bool ScrollbarImpl::HasThumb() const {
- return geometry_->hasThumb(scrollbar_.get());
-}
-
-bool ScrollbarImpl::IsOverlay() const {
- return scrollbar_->isOverlay();
-}
-
-gfx::Point ScrollbarImpl::Location() const {
- return scrollbar_->location();
-}
-
-int ScrollbarImpl::ThumbThickness() const {
- gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_.get());
- if (scrollbar_->orientation() == WebScrollbar::Horizontal)
- return thumb_rect.height();
- return thumb_rect.width();
-}
-
-int ScrollbarImpl::ThumbLength() const {
- gfx::Rect thumb_rect = geometry_->thumbRect(scrollbar_.get());
- if (scrollbar_->orientation() == WebScrollbar::Horizontal)
- return thumb_rect.width();
- return thumb_rect.height();
-}
-
-gfx::Rect ScrollbarImpl::TrackRect() const {
- return geometry_->trackRect(scrollbar_.get());
-}
-
-void ScrollbarImpl::PaintPart(SkCanvas* canvas,
- cc::ScrollbarPart part,
- const gfx::Rect& content_rect) {
- if (part == cc::THUMB) {
- painter_.paintThumb(canvas, content_rect);
- return;
- }
-
- // The following is a simplification of ScrollbarThemeComposite::paint.
- painter_.paintScrollbarBackground(canvas, content_rect);
-
- if (geometry_->hasButtons(scrollbar_.get())) {
- gfx::Rect back_button_start_paint_rect =
- geometry_->backButtonStartRect(scrollbar_.get());
- painter_.paintBackButtonStart(canvas, back_button_start_paint_rect);
-
- gfx::Rect back_button_end_paint_rect =
- geometry_->backButtonEndRect(scrollbar_.get());
- painter_.paintBackButtonEnd(canvas, back_button_end_paint_rect);
-
- gfx::Rect forward_button_start_paint_rect =
- geometry_->forwardButtonStartRect(scrollbar_.get());
- painter_.paintForwardButtonStart(canvas, forward_button_start_paint_rect);
-
- gfx::Rect forward_button_end_paint_rect =
- geometry_->forwardButtonEndRect(scrollbar_.get());
- painter_.paintForwardButtonEnd(canvas, forward_button_end_paint_rect);
- }
-
- gfx::Rect track_paint_rect = geometry_->trackRect(scrollbar_.get());
- painter_.paintTrackBackground(canvas, track_paint_rect);
-
- bool thumb_present = geometry_->hasThumb(scrollbar_.get());
- if (thumb_present) {
- painter_.paintForwardTrackPart(canvas, track_paint_rect);
- painter_.paintBackTrackPart(canvas, track_paint_rect);
- }
-
- painter_.paintTickmarks(canvas, track_paint_rect);
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/scrollbar_impl.h b/chromium/content/renderer/compositor_bindings/scrollbar_impl.h
deleted file mode 100644
index 9159d0a9267..00000000000
--- a/chromium/content/renderer/compositor_bindings/scrollbar_impl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_SCROLLBAR_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_SCROLLBAR_IMPL_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "cc/input/scrollbar.h"
-#include "third_party/WebKit/public/platform/WebScrollbarThemePainter.h"
-
-namespace blink {
-class WebScrollbar;
-class WebScrollbarThemeGeometry;
-}
-
-namespace content {
-
-class ScrollbarImpl : public cc::Scrollbar {
- public:
- ScrollbarImpl(scoped_ptr<blink::WebScrollbar> scrollbar,
- blink::WebScrollbarThemePainter painter,
- scoped_ptr<blink::WebScrollbarThemeGeometry> geometry);
- virtual ~ScrollbarImpl();
-
- // cc::Scrollbar implementation.
- virtual cc::ScrollbarOrientation Orientation() const OVERRIDE;
- virtual bool IsLeftSideVerticalScrollbar() const OVERRIDE;
- virtual bool HasThumb() const OVERRIDE;
- virtual bool IsOverlay() const OVERRIDE;
- virtual gfx::Point Location() const OVERRIDE;
- virtual int ThumbThickness() const OVERRIDE;
- virtual int ThumbLength() const OVERRIDE;
- virtual gfx::Rect TrackRect() const OVERRIDE;
- virtual void PaintPart(SkCanvas* canvas,
- cc::ScrollbarPart part,
- const gfx::Rect& content_rect) OVERRIDE;
-
- private:
- scoped_ptr<blink::WebScrollbar> scrollbar_;
- blink::WebScrollbarThemePainter painter_;
- scoped_ptr<blink::WebScrollbarThemeGeometry> geometry_;
-
- DISALLOW_COPY_AND_ASSIGN(ScrollbarImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_SCROLLBAR_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_animation_curve_common.cc b/chromium/content/renderer/compositor_bindings/web_animation_curve_common.cc
deleted file mode 100644
index c5bb36dacfb..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_animation_curve_common.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_animation_curve_common.h"
-
-#include "cc/animation/timing_function.h"
-
-namespace content {
-
-scoped_ptr<cc::TimingFunction> CreateTimingFunction(
- blink::WebAnimationCurve::TimingFunctionType type) {
- switch (type) {
- case blink::WebAnimationCurve::TimingFunctionTypeEase:
- return cc::EaseTimingFunction::Create();
- case blink::WebAnimationCurve::TimingFunctionTypeEaseIn:
- return cc::EaseInTimingFunction::Create();
- case blink::WebAnimationCurve::TimingFunctionTypeEaseOut:
- return cc::EaseOutTimingFunction::Create();
- case blink::WebAnimationCurve::TimingFunctionTypeEaseInOut:
- return cc::EaseInOutTimingFunction::Create();
- case blink::WebAnimationCurve::TimingFunctionTypeLinear:
- return scoped_ptr<cc::TimingFunction>();
- }
- return scoped_ptr<cc::TimingFunction>();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_animation_curve_common.h b/chromium/content/renderer/compositor_bindings/web_animation_curve_common.h
deleted file mode 100644
index e0fd7c8d028..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_animation_curve_common.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_ANIMATION_CURVE_COMMON_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_ANIMATION_CURVE_COMMON_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "third_party/WebKit/public/platform/WebAnimationCurve.h"
-
-namespace cc {
-class TimingFunction;
-}
-
-namespace content {
-scoped_ptr<cc::TimingFunction> CreateTimingFunction(
- blink::WebAnimationCurve::TimingFunctionType);
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_ANIMATION_CURVE_COMMON_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_animation_impl.cc b/chromium/content/renderer/compositor_bindings/web_animation_impl.cc
deleted file mode 100644
index 832aa6e3d31..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_animation_impl.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_animation_impl.h"
-
-#include "cc/animation/animation.h"
-#include "cc/animation/animation_curve.h"
-#include "cc/animation/animation_id_provider.h"
-#include "content/renderer/compositor_bindings/web_filter_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_float_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_transform_animation_curve_impl.h"
-#include "third_party/WebKit/public/platform/WebAnimation.h"
-#include "third_party/WebKit/public/platform/WebAnimationCurve.h"
-
-using cc::Animation;
-using cc::AnimationIdProvider;
-
-using blink::WebAnimation;
-using blink::WebAnimationCurve;
-
-namespace content {
-
-WebAnimationImpl::WebAnimationImpl(const WebAnimationCurve& web_curve,
- TargetProperty target_property,
- int animation_id,
- int group_id) {
- if (!animation_id)
- animation_id = AnimationIdProvider::NextAnimationId();
- if (!group_id)
- group_id = AnimationIdProvider::NextGroupId();
-
- WebAnimationCurve::AnimationCurveType curve_type = web_curve.type();
- scoped_ptr<cc::AnimationCurve> curve;
- switch (curve_type) {
- case WebAnimationCurve::AnimationCurveTypeFloat: {
- const WebFloatAnimationCurveImpl* float_curve_impl =
- static_cast<const WebFloatAnimationCurveImpl*>(&web_curve);
- curve = float_curve_impl->CloneToAnimationCurve();
- break;
- }
- case WebAnimationCurve::AnimationCurveTypeTransform: {
- const WebTransformAnimationCurveImpl* transform_curve_impl =
- static_cast<const WebTransformAnimationCurveImpl*>(&web_curve);
- curve = transform_curve_impl->CloneToAnimationCurve();
- break;
- }
- case WebAnimationCurve::AnimationCurveTypeFilter: {
- const WebFilterAnimationCurveImpl* filter_curve_impl =
- static_cast<const WebFilterAnimationCurveImpl*>(&web_curve);
- curve = filter_curve_impl->CloneToAnimationCurve();
- break;
- }
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
- case WebAnimationCurve::AnimationCurveTypeScrollOffset: {
- const WebScrollOffsetAnimationCurveImpl* scroll_curve_impl =
- static_cast<const WebScrollOffsetAnimationCurveImpl*>(&web_curve);
- curve = scroll_curve_impl->CloneToAnimationCurve();
- break;
- }
-#endif
- }
- animation_ = Animation::Create(
- curve.Pass(),
- animation_id,
- group_id,
- static_cast<cc::Animation::TargetProperty>(target_property));
-}
-
-WebAnimationImpl::~WebAnimationImpl() {
-}
-
-int WebAnimationImpl::id() {
- return animation_->id();
-}
-
-blink::WebAnimation::TargetProperty WebAnimationImpl::targetProperty() const {
- return static_cast<WebAnimationImpl::TargetProperty>(
- animation_->target_property());
-}
-
-int WebAnimationImpl::iterations() const {
- return animation_->iterations();
-}
-
-void WebAnimationImpl::setIterations(int n) {
- animation_->set_iterations(n);
-}
-
-double WebAnimationImpl::startTime() const {
- return (animation_->start_time() - base::TimeTicks()).InSecondsF();
-}
-
-void WebAnimationImpl::setStartTime(double monotonic_time) {
- animation_->set_start_time(base::TimeTicks::FromInternalValue(
- monotonic_time * base::Time::kMicrosecondsPerSecond));
-}
-
-double WebAnimationImpl::timeOffset() const {
- return animation_->time_offset().InSecondsF();
-}
-
-void WebAnimationImpl::setTimeOffset(double monotonic_time) {
- animation_->set_time_offset(base::TimeDelta::FromSecondsD(monotonic_time));
-}
-
-#if WEB_ANIMATION_SUPPORTS_FULL_DIRECTION
-blink::WebAnimation::Direction WebAnimationImpl::direction() const {
- switch (animation_->direction()) {
- case cc::Animation::Normal:
- return DirectionNormal;
- case cc::Animation::Reverse:
- return DirectionReverse;
- case cc::Animation::Alternate:
- return DirectionAlternate;
- case cc::Animation::AlternateReverse:
- return DirectionAlternateReverse;
- default:
- NOTREACHED();
- }
- return DirectionNormal;
-}
-
-void WebAnimationImpl::setDirection(Direction direction) {
- switch (direction) {
- case DirectionNormal:
- animation_->set_direction(cc::Animation::Normal);
- break;
- case DirectionReverse:
- animation_->set_direction(cc::Animation::Reverse);
- break;
- case DirectionAlternate:
- animation_->set_direction(cc::Animation::Alternate);
- break;
- case DirectionAlternateReverse:
- animation_->set_direction(cc::Animation::AlternateReverse);
- break;
- }
-}
-#else
-bool WebAnimationImpl::alternatesDirection() const {
- return animation_->direction() == cc::Animation::Alternate;
-}
-
-void WebAnimationImpl::setAlternatesDirection(bool alternates) {
- if (alternates)
- animation_->set_direction(cc::Animation::Alternate);
- else
- animation_->set_direction(cc::Animation::Normal);
-}
-#endif
-
-scoped_ptr<cc::Animation> WebAnimationImpl::PassAnimation() {
- animation_->set_needs_synchronized_start_time(true);
- return animation_.Pass();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_animation_impl.h b/chromium/content/renderer/compositor_bindings/web_animation_impl.h
deleted file mode 100644
index a706358ae36..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_animation_impl.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_ANIMATION_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_ANIMATION_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebAnimation.h"
-
-namespace cc {
-class Animation;
-}
-
-namespace blink {
-class WebAnimationCurve;
-}
-
-namespace content {
-
-class WebAnimationImpl : public blink::WebAnimation {
- public:
- CONTENT_EXPORT WebAnimationImpl(
- const blink::WebAnimationCurve& curve,
- TargetProperty target,
- int animation_id,
- int group_id);
- virtual ~WebAnimationImpl();
-
- // blink::WebAnimation implementation
- virtual int id();
- virtual TargetProperty targetProperty() const;
- virtual int iterations() const;
- virtual void setIterations(int iterations);
- virtual double startTime() const;
- virtual void setStartTime(double monotonic_time);
- virtual double timeOffset() const;
- virtual void setTimeOffset(double monotonic_time);
-#if WEB_ANIMATION_SUPPORTS_FULL_DIRECTION
- virtual Direction direction() const;
- virtual void setDirection(Direction);
-#else
- virtual bool alternatesDirection() const;
- virtual void setAlternatesDirection(bool alternates);
-#endif
-
- scoped_ptr<cc::Animation> PassAnimation();
-
- private:
- scoped_ptr<cc::Animation> animation_;
-
- DISALLOW_COPY_AND_ASSIGN(WebAnimationImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_ANIMATION_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_animation_unittest.cc b/chromium/content/renderer/compositor_bindings/web_animation_unittest.cc
deleted file mode 100644
index b529c018c50..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_animation_unittest.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 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/memory/scoped_ptr.h"
-#include "content/renderer/compositor_bindings/web_animation_impl.h"
-#include "content/renderer/compositor_bindings/web_float_animation_curve_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using blink::WebAnimation;
-using blink::WebAnimationCurve;
-using blink::WebFloatAnimationCurve;
-
-namespace content {
-namespace {
-
-TEST(WebAnimationTest, DefaultSettings) {
- scoped_ptr<WebAnimationCurve> curve(new WebFloatAnimationCurveImpl());
- scoped_ptr<WebAnimation> animation(
- new WebAnimationImpl(*curve, WebAnimation::TargetPropertyOpacity, 1, 0));
-
- // Ensure that the defaults are correct.
- EXPECT_EQ(1, animation->iterations());
- EXPECT_EQ(0, animation->startTime());
- EXPECT_EQ(0, animation->timeOffset());
-#if WEB_ANIMATION_SUPPORTS_FULL_DIRECTION
- EXPECT_EQ(WebAnimation::DirectionNormal, animation->direction());
-#else
- EXPECT_FALSE(animation->alternatesDirection());
-#endif
-}
-
-TEST(WebAnimationTest, ModifiedSettings) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl());
- scoped_ptr<WebAnimation> animation(
- new WebAnimationImpl(*curve, WebAnimation::TargetPropertyOpacity, 1, 0));
- animation->setIterations(2);
- animation->setStartTime(2);
- animation->setTimeOffset(2);
-#if WEB_ANIMATION_SUPPORTS_FULL_DIRECTION
- animation->setDirection(WebAnimation::DirectionReverse);
-#else
- animation->setAlternatesDirection(true);
-#endif
-
- EXPECT_EQ(2, animation->iterations());
- EXPECT_EQ(2, animation->startTime());
- EXPECT_EQ(2, animation->timeOffset());
-#if WEB_ANIMATION_SUPPORTS_FULL_DIRECTION
- EXPECT_EQ(WebAnimation::DirectionReverse, animation->direction());
-#else
- EXPECT_TRUE(animation->alternatesDirection());
- animation->setAlternatesDirection(false);
- EXPECT_FALSE(animation->alternatesDirection());
-#endif
-}
-
-} // namespace
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_blend_mode.h b/chromium/content/renderer/compositor_bindings/web_blend_mode.h
deleted file mode 100644
index 6ab6adee98b..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_blend_mode.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_BLEND_MODE_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_BLEND_MODE_H_
-
-#include "third_party/WebKit/public/platform/WebBlendMode.h"
-
-namespace content {
-
-inline SkXfermode::Mode BlendModeToSkia(blink::WebBlendMode blend_mode) {
- switch (blend_mode) {
- case blink::WebBlendModeNormal:
- return SkXfermode::kSrcOver_Mode;
- case blink::WebBlendModeMultiply:
- return SkXfermode::kMultiply_Mode;
- case blink::WebBlendModeScreen:
- return SkXfermode::kScreen_Mode;
- case blink::WebBlendModeOverlay:
- return SkXfermode::kOverlay_Mode;
- case blink::WebBlendModeDarken:
- return SkXfermode::kDarken_Mode;
- case blink::WebBlendModeLighten:
- return SkXfermode::kLighten_Mode;
- case blink::WebBlendModeColorDodge:
- return SkXfermode::kColorDodge_Mode;
- case blink::WebBlendModeColorBurn:
- return SkXfermode::kColorBurn_Mode;
- case blink::WebBlendModeHardLight:
- return SkXfermode::kHardLight_Mode;
- case blink::WebBlendModeSoftLight:
- return SkXfermode::kSoftLight_Mode;
- case blink::WebBlendModeDifference:
- return SkXfermode::kDifference_Mode;
- case blink::WebBlendModeExclusion:
- return SkXfermode::kExclusion_Mode;
- case blink::WebBlendModeHue:
- return SkXfermode::kHue_Mode;
- case blink::WebBlendModeSaturation:
- return SkXfermode::kSaturation_Mode;
- case blink::WebBlendModeColor:
- return SkXfermode::kColor_Mode;
- case blink::WebBlendModeLuminosity:
- return SkXfermode::kLuminosity_Mode;
- }
- return SkXfermode::kSrcOver_Mode;
-}
-
-inline blink::WebBlendMode BlendModeFromSkia(SkXfermode::Mode blend_mode) {
- switch (blend_mode) {
- case SkXfermode::kSrcOver_Mode:
- return blink::WebBlendModeNormal;
- case SkXfermode::kMultiply_Mode:
- return blink::WebBlendModeMultiply;
- case SkXfermode::kScreen_Mode:
- return blink::WebBlendModeScreen;
- case SkXfermode::kOverlay_Mode:
- return blink::WebBlendModeOverlay;
- case SkXfermode::kDarken_Mode:
- return blink::WebBlendModeDarken;
- case SkXfermode::kLighten_Mode:
- return blink::WebBlendModeLighten;
- case SkXfermode::kColorDodge_Mode:
- return blink::WebBlendModeColorDodge;
- case SkXfermode::kColorBurn_Mode:
- return blink::WebBlendModeColorBurn;
- case SkXfermode::kHardLight_Mode:
- return blink::WebBlendModeHardLight;
- case SkXfermode::kSoftLight_Mode:
- return blink::WebBlendModeSoftLight;
- case SkXfermode::kDifference_Mode:
- return blink::WebBlendModeDifference;
- case SkXfermode::kExclusion_Mode:
- return blink::WebBlendModeExclusion;
- case SkXfermode::kHue_Mode:
- return blink::WebBlendModeHue;
- case SkXfermode::kSaturation_Mode:
- return blink::WebBlendModeSaturation;
- case SkXfermode::kColor_Mode:
- return blink::WebBlendModeColor;
- case SkXfermode::kLuminosity_Mode:
- return blink::WebBlendModeLuminosity;
-
- // these value are SkXfermodes, but no blend modes.
- case SkXfermode::kClear_Mode:
- case SkXfermode::kSrc_Mode:
- case SkXfermode::kDst_Mode:
- case SkXfermode::kDstOver_Mode:
- case SkXfermode::kSrcIn_Mode:
- case SkXfermode::kDstIn_Mode:
- case SkXfermode::kSrcOut_Mode:
- case SkXfermode::kDstOut_Mode:
- case SkXfermode::kSrcATop_Mode:
- case SkXfermode::kDstATop_Mode:
- case SkXfermode::kXor_Mode:
- case SkXfermode::kPlus_Mode:
- case SkXfermode::kModulate_Mode:
- NOTREACHED();
- }
- return blink::WebBlendModeNormal;
-}
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_BLEND_MODE_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_compositor_support_impl.cc b/chromium/content/renderer/compositor_bindings/web_compositor_support_impl.cc
deleted file mode 100644
index 0e4e6fa88f5..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_compositor_support_impl.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_compositor_support_impl.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "cc/animation/transform_operations.h"
-#include "cc/output/output_surface.h"
-#include "cc/output/software_output_device.h"
-#include "content/renderer/compositor_bindings/web_animation_impl.h"
-#include "content/renderer/compositor_bindings/web_content_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_external_texture_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_filter_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_filter_operations_impl.h"
-#include "content/renderer/compositor_bindings/web_float_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_image_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_nine_patch_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_scrollbar_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_solid_color_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_transform_animation_curve_impl.h"
-#include "content/renderer/compositor_bindings/web_transform_operations_impl.h"
-
-using blink::WebAnimation;
-using blink::WebAnimationCurve;
-using blink::WebContentLayer;
-using blink::WebContentLayerClient;
-using blink::WebExternalTextureLayer;
-using blink::WebExternalTextureLayerClient;
-using blink::WebFilterAnimationCurve;
-using blink::WebFilterOperations;
-using blink::WebFloatAnimationCurve;
-using blink::WebImageLayer;
-using blink::WebNinePatchLayer;
-using blink::WebLayer;
-using blink::WebScrollbar;
-using blink::WebScrollbarLayer;
-using blink::WebScrollbarThemeGeometry;
-using blink::WebScrollbarThemePainter;
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-using blink::WebScrollOffsetAnimationCurve;
-#endif
-using blink::WebSolidColorLayer;
-using blink::WebTransformAnimationCurve;
-using blink::WebTransformOperations;
-
-namespace content {
-
-WebCompositorSupportImpl::WebCompositorSupportImpl() {
-}
-
-WebCompositorSupportImpl::~WebCompositorSupportImpl() {
-}
-
-WebLayer* WebCompositorSupportImpl::createLayer() {
- return new WebLayerImpl();
-}
-
-WebContentLayer* WebCompositorSupportImpl::createContentLayer(
- WebContentLayerClient* client) {
- return new WebContentLayerImpl(client);
-}
-
-WebExternalTextureLayer* WebCompositorSupportImpl::createExternalTextureLayer(
- WebExternalTextureLayerClient* client) {
- return new WebExternalTextureLayerImpl(client);
-}
-
-blink::WebImageLayer* WebCompositorSupportImpl::createImageLayer() {
- return new WebImageLayerImpl();
-}
-
-blink::WebNinePatchLayer* WebCompositorSupportImpl::createNinePatchLayer() {
- return new WebNinePatchLayerImpl();
-}
-
-WebSolidColorLayer* WebCompositorSupportImpl::createSolidColorLayer() {
- return new WebSolidColorLayerImpl();
-}
-
-WebScrollbarLayer* WebCompositorSupportImpl::createScrollbarLayer(
- WebScrollbar* scrollbar,
- WebScrollbarThemePainter painter,
- WebScrollbarThemeGeometry* geometry) {
- return new WebScrollbarLayerImpl(scrollbar, painter, geometry);
-}
-
-WebScrollbarLayer* WebCompositorSupportImpl::createSolidColorScrollbarLayer(
- WebScrollbar::Orientation orientation,
- int thumb_thickness,
- int track_start,
- bool is_left_side_vertical_scrollbar) {
- return new WebScrollbarLayerImpl(orientation,
- thumb_thickness,
- track_start,
- is_left_side_vertical_scrollbar);
-}
-
-WebAnimation* WebCompositorSupportImpl::createAnimation(
- const blink::WebAnimationCurve& curve,
- blink::WebAnimation::TargetProperty target,
- int animation_id) {
- return new WebAnimationImpl(curve, target, animation_id, 0);
-}
-
-WebFilterAnimationCurve*
-WebCompositorSupportImpl::createFilterAnimationCurve() {
- return new WebFilterAnimationCurveImpl();
-}
-
-WebFloatAnimationCurve* WebCompositorSupportImpl::createFloatAnimationCurve() {
- return new WebFloatAnimationCurveImpl();
-}
-
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-WebScrollOffsetAnimationCurve*
-WebCompositorSupportImpl::createScrollOffsetAnimationCurve(
- blink::WebFloatPoint target_value,
- blink::WebAnimationCurve::TimingFunctionType timing_function) {
- return new WebScrollOffsetAnimationCurveImpl(target_value, timing_function);
-}
-#endif
-
-WebTransformAnimationCurve*
-WebCompositorSupportImpl::createTransformAnimationCurve() {
- return new WebTransformAnimationCurveImpl();
-}
-
-WebTransformOperations* WebCompositorSupportImpl::createTransformOperations() {
- return new WebTransformOperationsImpl();
-}
-
-WebFilterOperations* WebCompositorSupportImpl::createFilterOperations() {
- return new WebFilterOperationsImpl();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_compositor_support_impl.h b/chromium/content/renderer/compositor_bindings/web_compositor_support_impl.h
deleted file mode 100644
index c7d53858745..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_compositor_support_impl.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_COMPOSITOR_SUPPORT_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_COMPOSITOR_SUPPORT_IMPL_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebAnimationCurve.h"
-#include "third_party/WebKit/public/platform/WebCompositorSupport.h"
-#include "third_party/WebKit/public/platform/WebLayer.h"
-#include "third_party/WebKit/public/platform/WebTransformOperations.h"
-
-namespace blink {
-class WebGraphicsContext3D;
-}
-
-namespace content {
-
-class CONTENT_EXPORT WebCompositorSupportImpl
- : public NON_EXPORTED_BASE(blink::WebCompositorSupport) {
- public:
- WebCompositorSupportImpl();
- virtual ~WebCompositorSupportImpl();
-
- virtual blink::WebLayer* createLayer();
- virtual blink::WebContentLayer* createContentLayer(
- blink::WebContentLayerClient* client);
- virtual blink::WebExternalTextureLayer* createExternalTextureLayer(
- blink::WebExternalTextureLayerClient* client);
- virtual blink::WebImageLayer* createImageLayer();
- virtual blink::WebNinePatchLayer* createNinePatchLayer();
- virtual blink::WebSolidColorLayer* createSolidColorLayer();
- virtual blink::WebScrollbarLayer* createScrollbarLayer(
- blink::WebScrollbar* scrollbar,
- blink::WebScrollbarThemePainter painter,
- blink::WebScrollbarThemeGeometry*);
- virtual blink::WebScrollbarLayer* createSolidColorScrollbarLayer(
- blink::WebScrollbar::Orientation orientation,
- int thumb_thickness,
- int track_start,
- bool is_left_side_vertical_scrollbar);
- virtual blink::WebAnimation* createAnimation(
- const blink::WebAnimationCurve& curve,
- blink::WebAnimation::TargetProperty target,
- int animation_id);
- virtual blink::WebFilterAnimationCurve* createFilterAnimationCurve();
- virtual blink::WebFloatAnimationCurve* createFloatAnimationCurve();
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
- virtual blink::WebScrollOffsetAnimationCurve*
- createScrollOffsetAnimationCurve(
- blink::WebFloatPoint target_value,
- blink::WebAnimationCurve::TimingFunctionType timing_function);
-#endif
- virtual blink::WebTransformAnimationCurve* createTransformAnimationCurve();
- virtual blink::WebTransformOperations* createTransformOperations();
- virtual blink::WebFilterOperations* createFilterOperations();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebCompositorSupportImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_COMPOSITOR_SUPPORT_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_content_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_content_layer_impl.cc
deleted file mode 100644
index 1a1eb4331fd..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_content_layer_impl.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_content_layer_impl.h"
-
-#include "cc/layers/content_layer.h"
-#include "cc/layers/picture_layer.h"
-#include "third_party/WebKit/public/platform/WebContentLayerClient.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatRect.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
-
-using cc::ContentLayer;
-using cc::PictureLayer;
-
-namespace content {
-
-WebContentLayerImpl::WebContentLayerImpl(blink::WebContentLayerClient* client)
- : client_(client), ignore_lcd_text_change_(false) {
- if (WebLayerImpl::UsingPictureLayer())
- layer_ = make_scoped_ptr(new WebLayerImpl(PictureLayer::Create(this)));
- else
- layer_ = make_scoped_ptr(new WebLayerImpl(ContentLayer::Create(this)));
- layer_->layer()->SetIsDrawable(true);
- can_use_lcd_text_ = layer_->layer()->can_use_lcd_text();
-}
-
-WebContentLayerImpl::~WebContentLayerImpl() {
- if (WebLayerImpl::UsingPictureLayer())
- static_cast<PictureLayer*>(layer_->layer())->ClearClient();
- else
- static_cast<ContentLayer*>(layer_->layer())->ClearClient();
-}
-
-blink::WebLayer* WebContentLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebContentLayerImpl::setDoubleSided(bool double_sided) {
- layer_->layer()->SetDoubleSided(double_sided);
-}
-
-void WebContentLayerImpl::setDrawCheckerboardForMissingTiles(bool enable) {
- layer_->layer()->SetDrawCheckerboardForMissingTiles(enable);
-}
-
-void WebContentLayerImpl::PaintContents(
- SkCanvas* canvas,
- const gfx::Rect& clip,
- gfx::RectF* opaque,
- ContentLayerClient::GraphicsContextStatus graphics_context_status) {
- if (!client_)
- return;
-
- blink::WebFloatRect web_opaque;
- client_->paintContents(
- canvas,
- clip,
- can_use_lcd_text_,
- web_opaque,
- graphics_context_status == ContentLayerClient::GRAPHICS_CONTEXT_ENABLED
- ? blink::WebContentLayerClient::GraphicsContextEnabled
- : blink::WebContentLayerClient::GraphicsContextDisabled);
- *opaque = web_opaque;
-}
-
-void WebContentLayerImpl::DidChangeLayerCanUseLCDText() {
- // It is important to make this comparison because the LCD text status
- // here can get out of sync with that in the layer.
- if (can_use_lcd_text_ == layer_->layer()->can_use_lcd_text())
- return;
-
- // LCD text cannot be enabled once disabled.
- if (layer_->layer()->can_use_lcd_text() && ignore_lcd_text_change_)
- return;
-
- can_use_lcd_text_ = layer_->layer()->can_use_lcd_text();
- ignore_lcd_text_change_ = true;
- layer_->invalidate();
-}
-
-bool WebContentLayerImpl::FillsBoundsCompletely() const {
- return false;
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_content_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_content_layer_impl.h
deleted file mode 100644
index 435acfd57ab..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_content_layer_impl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_CONTENT_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_CONTENT_LAYER_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cc/layers/content_layer_client.h"
-#include "content/common/content_export.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "third_party/WebKit/public/platform/WebContentLayer.h"
-
-namespace cc {
-class IntRect;
-class FloatRect;
-}
-
-namespace blink {
-class WebContentLayerClient;
-}
-
-namespace content {
-
-class WebContentLayerImpl : public blink::WebContentLayer,
- public cc::ContentLayerClient {
- public:
- CONTENT_EXPORT explicit WebContentLayerImpl(
- blink::WebContentLayerClient*);
-
- // WebContentLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setDoubleSided(bool double_sided);
- virtual void setDrawCheckerboardForMissingTiles(bool checkerboard);
-
- protected:
- virtual ~WebContentLayerImpl();
-
- // ContentLayerClient implementation.
- virtual void PaintContents(SkCanvas* canvas,
- const gfx::Rect& clip,
- gfx::RectF* opaque,
- ContentLayerClient::GraphicsContextStatus
- graphics_context_status) OVERRIDE;
- virtual void DidChangeLayerCanUseLCDText() OVERRIDE;
- virtual bool FillsBoundsCompletely() const OVERRIDE;
-
- scoped_ptr<WebLayerImpl> layer_;
- blink::WebContentLayerClient* client_;
- bool draws_content_;
-
- private:
- bool can_use_lcd_text_;
- bool ignore_lcd_text_change_;
-
- DISALLOW_COPY_AND_ASSIGN(WebContentLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_CONTENT_LAYER_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.cc b/chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.cc
deleted file mode 100644
index bf3d853f606..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_external_bitmap_impl.h"
-
-#include "base/memory/shared_memory.h"
-
-namespace content {
-
-namespace {
-
-SharedMemoryAllocationFunction g_memory_allocator;
-
-} // namespace
-
-void SetSharedMemoryAllocationFunction(
- SharedMemoryAllocationFunction allocator) {
- g_memory_allocator = allocator;
-}
-
-WebExternalBitmapImpl::WebExternalBitmapImpl() {
-}
-
-WebExternalBitmapImpl::~WebExternalBitmapImpl() {
-}
-
-void WebExternalBitmapImpl::setSize(blink::WebSize size) {
- if (size != size_) {
- size_t byte_size = size.width * size.height * 4;
- shared_memory_ = g_memory_allocator(byte_size);
- if (shared_memory_)
- shared_memory_->Map(byte_size);
- size_ = size;
- }
-}
-
-blink::WebSize WebExternalBitmapImpl::size() {
- return size_;
-}
-
-uint8* WebExternalBitmapImpl::pixels() {
- return static_cast<uint8*>(shared_memory_->memory());
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.h b/chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.h
deleted file mode 100644
index 4d7769e3e4d..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_external_bitmap_impl.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_EXTERNAL_BITMAP_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_EXTERNAL_BITMAP_IMPL_H_
-
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebExternalBitmap.h"
-
-namespace base {
-class SharedMemory;
-}
-
-namespace content {
-
-typedef scoped_ptr<base::SharedMemory>(*SharedMemoryAllocationFunction)(size_t);
-
-// Sets the function that this will use to allocate shared memory.
-CONTENT_EXPORT void SetSharedMemoryAllocationFunction(
- SharedMemoryAllocationFunction);
-
-class WebExternalBitmapImpl : public blink::WebExternalBitmap {
- public:
- CONTENT_EXPORT explicit WebExternalBitmapImpl();
- virtual ~WebExternalBitmapImpl();
-
- // blink::WebExternalBitmap implementation.
- virtual blink::WebSize size() OVERRIDE;
- virtual void setSize(blink::WebSize size) OVERRIDE;
- virtual uint8* pixels() OVERRIDE;
-
- base::SharedMemory* shared_memory() { return shared_memory_.get(); }
-
- private:
- scoped_ptr<base::SharedMemory> shared_memory_;
- blink::WebSize size_;
-
- DISALLOW_COPY_AND_ASSIGN(WebExternalBitmapImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_EXTERNAL_BITMAP_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.cc
deleted file mode 100644
index 9709d5951a9..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_external_texture_layer_impl.h"
-
-#include "cc/layers/texture_layer.h"
-#include "cc/resources/resource_update_queue.h"
-#include "cc/resources/single_release_callback.h"
-#include "cc/resources/texture_mailbox.h"
-#include "content/renderer/compositor_bindings/web_external_bitmap_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "third_party/WebKit/public/platform/WebExternalTextureLayerClient.h"
-#include "third_party/WebKit/public/platform/WebExternalTextureMailbox.h"
-#include "third_party/WebKit/public/platform/WebFloatRect.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/khronos/GLES2/gl2.h"
-
-using cc::TextureLayer;
-using cc::ResourceUpdateQueue;
-
-namespace content {
-
-WebExternalTextureLayerImpl::WebExternalTextureLayerImpl(
- blink::WebExternalTextureLayerClient* client)
- : client_(client) {
- cc::TextureLayerClient* cc_client = client_ ? this : NULL;
- scoped_refptr<TextureLayer> layer = TextureLayer::CreateForMailbox(cc_client);
- layer->SetIsDrawable(true);
- layer_.reset(new WebLayerImpl(layer));
-}
-
-WebExternalTextureLayerImpl::~WebExternalTextureLayerImpl() {
- static_cast<TextureLayer*>(layer_->layer())->ClearClient();
-}
-
-blink::WebLayer* WebExternalTextureLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebExternalTextureLayerImpl::clearTexture() {
- TextureLayer* layer = static_cast<TextureLayer*>(layer_->layer());
- layer->ClearTexture();
-}
-
-void WebExternalTextureLayerImpl::setOpaque(bool opaque) {
- static_cast<TextureLayer*>(layer_->layer())->SetContentsOpaque(opaque);
-}
-
-void WebExternalTextureLayerImpl::setPremultipliedAlpha(
- bool premultiplied_alpha) {
- static_cast<TextureLayer*>(layer_->layer())->SetPremultipliedAlpha(
- premultiplied_alpha);
-}
-
-void WebExternalTextureLayerImpl::setBlendBackgroundColor(bool blend) {
- static_cast<TextureLayer*>(layer_->layer())->SetBlendBackgroundColor(blend);
-}
-
-void WebExternalTextureLayerImpl::setRateLimitContext(bool rate_limit) {
- static_cast<TextureLayer*>(layer_->layer())->SetRateLimitContext(rate_limit);
-}
-
-bool WebExternalTextureLayerImpl::PrepareTextureMailbox(
- cc::TextureMailbox* mailbox,
- scoped_ptr<cc::SingleReleaseCallback>* release_callback,
- bool use_shared_memory) {
- blink::WebExternalTextureMailbox client_mailbox;
- WebExternalBitmapImpl* bitmap = NULL;
-
- if (use_shared_memory)
- bitmap = AllocateBitmap();
- if (!client_->prepareMailbox(&client_mailbox, bitmap)) {
- if (bitmap)
- free_bitmaps_.push_back(bitmap);
- return false;
- }
- gpu::Mailbox name;
- name.SetName(client_mailbox.name);
- if (bitmap) {
- *mailbox = cc::TextureMailbox(bitmap->shared_memory(), bitmap->size());
- } else {
- *mailbox =
- cc::TextureMailbox(name, GL_TEXTURE_2D, client_mailbox.syncPoint);
- }
- mailbox->set_allow_overlay(client_mailbox.allowOverlay);
-
- if (mailbox->IsValid()) {
- *release_callback = cc::SingleReleaseCallback::Create(
- base::Bind(&WebExternalTextureLayerImpl::DidReleaseMailbox,
- this->AsWeakPtr(),
- client_mailbox,
- bitmap));
- }
-
- return true;
-}
-
-WebExternalBitmapImpl* WebExternalTextureLayerImpl::AllocateBitmap() {
- if (!free_bitmaps_.empty()) {
- WebExternalBitmapImpl* result = free_bitmaps_.back();
- free_bitmaps_.weak_erase(free_bitmaps_.end() - 1);
- return result;
- }
- return new WebExternalBitmapImpl;
-}
-
-// static
-void WebExternalTextureLayerImpl::DidReleaseMailbox(
- base::WeakPtr<WebExternalTextureLayerImpl> layer,
- const blink::WebExternalTextureMailbox& mailbox,
- WebExternalBitmapImpl* bitmap,
- unsigned sync_point,
- bool lost_resource) {
- if (lost_resource || !layer) {
- delete bitmap;
- return;
- }
-
- blink::WebExternalTextureMailbox available_mailbox;
- memcpy(available_mailbox.name, mailbox.name, sizeof(available_mailbox.name));
- available_mailbox.syncPoint = sync_point;
- if (bitmap)
- layer->free_bitmaps_.push_back(bitmap);
- layer->client_->mailboxReleased(available_mailbox);
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.h
deleted file mode 100644
index bc46b937e8e..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_external_texture_layer_impl.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_
-
-#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "cc/layers/texture_layer_client.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebExternalTextureLayer.h"
-
-namespace cc {
-class SingleReleaseCallback;
-class TextureMailbox;
-}
-
-namespace blink {
-struct WebFloatRect;
-struct WebExternalTextureMailbox;
-}
-
-namespace content {
-
-class WebLayerImpl;
-class WebExternalBitmapImpl;
-
-class WebExternalTextureLayerImpl
- : public blink::WebExternalTextureLayer,
- public cc::TextureLayerClient,
- public base::SupportsWeakPtr<WebExternalTextureLayerImpl> {
- public:
- CONTENT_EXPORT explicit WebExternalTextureLayerImpl(
- blink::WebExternalTextureLayerClient*);
- virtual ~WebExternalTextureLayerImpl();
-
- // blink::WebExternalTextureLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void clearTexture();
- virtual void setOpaque(bool opaque);
- virtual void setPremultipliedAlpha(bool premultiplied);
- virtual void setBlendBackgroundColor(bool blend);
- virtual void setRateLimitContext(bool rate_limit);
-
- // TextureLayerClient implementation.
- virtual bool PrepareTextureMailbox(
- cc::TextureMailbox* mailbox,
- scoped_ptr<cc::SingleReleaseCallback>* release_callback,
- bool use_shared_memory) OVERRIDE;
-
- private:
- static void DidReleaseMailbox(
- base::WeakPtr<WebExternalTextureLayerImpl> layer,
- const blink::WebExternalTextureMailbox& mailbox,
- WebExternalBitmapImpl* bitmap,
- unsigned sync_point,
- bool lost_resource);
-
- WebExternalBitmapImpl* AllocateBitmap();
-
- blink::WebExternalTextureLayerClient* client_;
- scoped_ptr<WebLayerImpl> layer_;
- ScopedVector<WebExternalBitmapImpl> free_bitmaps_;
-
- DISALLOW_COPY_AND_ASSIGN(WebExternalTextureLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_EXTERNAL_TEXTURE_LAYER_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.cc b/chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.cc
deleted file mode 100644
index 944726ecccb..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_filter_animation_curve_impl.h"
-
-#include "cc/animation/keyframed_animation_curve.h"
-#include "cc/animation/timing_function.h"
-#include "cc/output/filter_operations.h"
-#include "content/renderer/compositor_bindings/web_animation_curve_common.h"
-#include "content/renderer/compositor_bindings/web_filter_operations_impl.h"
-
-using blink::WebFilterKeyframe;
-
-namespace content {
-
-WebFilterAnimationCurveImpl::WebFilterAnimationCurveImpl()
- : curve_(cc::KeyframedFilterAnimationCurve::Create()) {
-}
-
-WebFilterAnimationCurveImpl::~WebFilterAnimationCurveImpl() {
-}
-
-blink::WebAnimationCurve::AnimationCurveType WebFilterAnimationCurveImpl::type()
- const {
- return WebAnimationCurve::AnimationCurveTypeFilter;
-}
-
-void WebFilterAnimationCurveImpl::add(const WebFilterKeyframe& keyframe,
- TimingFunctionType type) {
- const cc::FilterOperations& filter_operations =
- static_cast<const WebFilterOperationsImpl&>(keyframe.value())
- .AsFilterOperations();
- curve_->AddKeyframe(cc::FilterKeyframe::Create(
- keyframe.time(), filter_operations, CreateTimingFunction(type)));
-}
-
-void WebFilterAnimationCurveImpl::add(const WebFilterKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2) {
- const cc::FilterOperations& filter_operations =
- static_cast<const WebFilterOperationsImpl&>(keyframe.value())
- .AsFilterOperations();
- curve_->AddKeyframe(cc::FilterKeyframe::Create(
- keyframe.time(),
- filter_operations,
- cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)
- .PassAs<cc::TimingFunction>()));
-}
-
-scoped_ptr<cc::AnimationCurve>
-WebFilterAnimationCurveImpl::CloneToAnimationCurve() const {
- return curve_->Clone();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.h b/chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.h
deleted file mode 100644
index 82e82956e13..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_filter_animation_curve_impl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FILTER_ANIMATION_CURVE_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FILTER_ANIMATION_CURVE_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebFilterAnimationCurve.h"
-
-namespace cc {
-class AnimationCurve;
-class KeyframedFilterAnimationCurve;
-}
-
-namespace blink {
-class WebFilterKeyframe;
-}
-
-namespace content {
-
-class WebFilterAnimationCurveImpl : public blink::WebFilterAnimationCurve {
- public:
- CONTENT_EXPORT WebFilterAnimationCurveImpl();
- virtual ~WebFilterAnimationCurveImpl();
-
- // blink::WebAnimationCurve implementation.
- virtual AnimationCurveType type() const;
-
- // blink::WebFilterAnimationCurve implementation.
- virtual void add(const blink::WebFilterKeyframe& keyframe,
- TimingFunctionType type);
- virtual void add(const blink::WebFilterKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2);
-
- scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
-
- private:
- scoped_ptr<cc::KeyframedFilterAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(WebFilterAnimationCurveImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FILTER_ANIMATION_CURVE_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_filter_operations_impl.cc b/chromium/content/renderer/compositor_bindings/web_filter_operations_impl.cc
deleted file mode 100644
index 2a11ea8a79d..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_filter_operations_impl.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_filter_operations_impl.h"
-
-#include "base/basictypes.h"
-#include "skia/ext/refptr.h"
-#include "third_party/WebKit/public/platform/WebColor.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/skia/include/core/SkScalar.h"
-
-namespace content {
-
-WebFilterOperationsImpl::WebFilterOperationsImpl() {
-}
-
-WebFilterOperationsImpl::~WebFilterOperationsImpl() {
-}
-
-const cc::FilterOperations& WebFilterOperationsImpl::AsFilterOperations()
- const {
- return filter_operations_;
-}
-
-void WebFilterOperationsImpl::appendGrayscaleFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateGrayscaleFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendSepiaFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateSepiaFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendSaturateFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateSaturateFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendHueRotateFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateHueRotateFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendInvertFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateInvertFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendBrightnessFilter(float amount) {
- filter_operations_.Append(
- cc::FilterOperation::CreateBrightnessFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendContrastFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateContrastFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendOpacityFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateOpacityFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendBlurFilter(float amount) {
- filter_operations_.Append(cc::FilterOperation::CreateBlurFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendDropShadowFilter(blink::WebPoint offset,
- float std_deviation,
- blink::WebColor color) {
- filter_operations_.Append(cc::FilterOperation::CreateDropShadowFilter(
- offset, std_deviation, color));
-}
-
-void WebFilterOperationsImpl::appendColorMatrixFilter(SkScalar matrix[20]) {
- filter_operations_.Append(
- cc::FilterOperation::CreateColorMatrixFilter(matrix));
-}
-
-void WebFilterOperationsImpl::appendZoomFilter(float amount, int inset) {
- filter_operations_.Append(
- cc::FilterOperation::CreateZoomFilter(amount, inset));
-}
-
-void WebFilterOperationsImpl::appendSaturatingBrightnessFilter(float amount) {
- filter_operations_.Append(
- cc::FilterOperation::CreateSaturatingBrightnessFilter(amount));
-}
-
-void WebFilterOperationsImpl::appendReferenceFilter(
- SkImageFilter* image_filter) {
- filter_operations_.Append(
- cc::FilterOperation::CreateReferenceFilter(skia::SharePtr(image_filter)));
-}
-
-void WebFilterOperationsImpl::clear() {
- filter_operations_.Clear();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_filter_operations_impl.h b/chromium/content/renderer/compositor_bindings/web_filter_operations_impl.h
deleted file mode 100644
index d3020e6cfcd..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_filter_operations_impl.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FILTER_OPERATIONS_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FILTER_OPERATIONS_IMPL_H_
-
-#include "cc/output/filter_operations.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebFilterOperations.h"
-
-namespace content {
-
-class WebFilterOperationsImpl : public blink::WebFilterOperations {
- public:
- CONTENT_EXPORT WebFilterOperationsImpl();
- virtual ~WebFilterOperationsImpl();
-
- const cc::FilterOperations& AsFilterOperations() const;
-
- // Implementation of blink::WebFilterOperations methods
- virtual void appendGrayscaleFilter(float amount);
- virtual void appendSepiaFilter(float amount);
- virtual void appendSaturateFilter(float amount);
- virtual void appendHueRotateFilter(float amount);
- virtual void appendInvertFilter(float amount);
- virtual void appendBrightnessFilter(float amount);
- virtual void appendContrastFilter(float amount);
- virtual void appendOpacityFilter(float amount);
- virtual void appendBlurFilter(float amount);
- virtual void appendDropShadowFilter(blink::WebPoint offset,
- float std_deviation,
- blink::WebColor color);
- virtual void appendColorMatrixFilter(SkScalar matrix[20]);
- virtual void appendZoomFilter(float amount, int inset);
- virtual void appendSaturatingBrightnessFilter(float amount);
- virtual void appendReferenceFilter(SkImageFilter* image_filter);
-
- virtual void clear();
-
- private:
- cc::FilterOperations filter_operations_;
-
- DISALLOW_COPY_AND_ASSIGN(WebFilterOperationsImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FILTER_OPERATIONS_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.cc b/chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.cc
deleted file mode 100644
index caa1f9ba849..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_float_animation_curve_impl.h"
-
-#include "cc/animation/animation_curve.h"
-#include "cc/animation/keyframed_animation_curve.h"
-#include "cc/animation/timing_function.h"
-#include "content/renderer/compositor_bindings/web_animation_curve_common.h"
-
-using blink::WebFloatKeyframe;
-
-namespace content {
-
-WebFloatAnimationCurveImpl::WebFloatAnimationCurveImpl()
- : curve_(cc::KeyframedFloatAnimationCurve::Create()) {
-}
-
-WebFloatAnimationCurveImpl::~WebFloatAnimationCurveImpl() {
-}
-
-blink::WebAnimationCurve::AnimationCurveType
- WebFloatAnimationCurveImpl::type() const {
- return blink::WebAnimationCurve::AnimationCurveTypeFloat;
-}
-
-void WebFloatAnimationCurveImpl::add(const WebFloatKeyframe& keyframe) {
- add(keyframe, TimingFunctionTypeEase);
-}
-
-void WebFloatAnimationCurveImpl::add(const WebFloatKeyframe& keyframe,
- TimingFunctionType type) {
- curve_->AddKeyframe(cc::FloatKeyframe::Create(
- keyframe.time, keyframe.value, CreateTimingFunction(type)));
-}
-
-void WebFloatAnimationCurveImpl::add(const WebFloatKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2) {
- curve_->AddKeyframe(cc::FloatKeyframe::Create(
- keyframe.time,
- keyframe.value,
- cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)
- .PassAs<cc::TimingFunction>()));
-}
-
-float WebFloatAnimationCurveImpl::getValue(double time) const {
- return curve_->GetValue(time);
-}
-
-scoped_ptr<cc::AnimationCurve>
-WebFloatAnimationCurveImpl::CloneToAnimationCurve() const {
- return curve_->Clone();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.h b/chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.h
deleted file mode 100644
index 4c67b41a81b..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_float_animation_curve_impl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FLOAT_ANIMATION_CURVE_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FLOAT_ANIMATION_CURVE_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebFloatAnimationCurve.h"
-
-namespace cc {
-class AnimationCurve;
-class KeyframedFloatAnimationCurve;
-}
-
-namespace blink {
-struct WebFloatKeyframe;
-}
-
-namespace content {
-
-class WebFloatAnimationCurveImpl : public blink::WebFloatAnimationCurve {
- public:
- CONTENT_EXPORT WebFloatAnimationCurveImpl();
- virtual ~WebFloatAnimationCurveImpl();
-
- // WebAnimationCurve implementation.
- virtual AnimationCurveType type() const;
-
- // WebFloatAnimationCurve implementation.
- virtual void add(const blink::WebFloatKeyframe& keyframe);
- virtual void add(const blink::WebFloatKeyframe& keyframe,
- TimingFunctionType type);
- virtual void add(const blink::WebFloatKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2);
-
- virtual float getValue(double time) const;
-
- scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
-
- private:
- scoped_ptr<cc::KeyframedFloatAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(WebFloatAnimationCurveImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_FLOAT_ANIMATION_CURVE_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_float_animation_curve_unittest.cc b/chromium/content/renderer/compositor_bindings/web_float_animation_curve_unittest.cc
deleted file mode 100644
index bc7c4106426..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_float_animation_curve_unittest.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2014 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/memory/scoped_ptr.h"
-#include "cc/animation/timing_function.h"
-#include "content/renderer/compositor_bindings/web_float_animation_curve_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using blink::WebAnimationCurve;
-using blink::WebFloatAnimationCurve;
-using blink::WebFloatKeyframe;
-
-namespace content {
-namespace {
-
-// Tests that a float animation with one keyframe works as expected.
-TEST(WebFloatAnimationCurveTest, OneFloatKeyframe) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 2),
- WebAnimationCurve::TimingFunctionTypeLinear);
- EXPECT_FLOAT_EQ(2, curve->getValue(-1));
- EXPECT_FLOAT_EQ(2, curve->getValue(0));
- EXPECT_FLOAT_EQ(2, curve->getValue(0.5));
- EXPECT_FLOAT_EQ(2, curve->getValue(1));
- EXPECT_FLOAT_EQ(2, curve->getValue(2));
-}
-
-// Tests that a float animation with two keyframes works as expected.
-TEST(WebFloatAnimationCurveTest, TwoFloatKeyframe) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 2),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(1, 4),
- WebAnimationCurve::TimingFunctionTypeLinear);
- EXPECT_FLOAT_EQ(2, curve->getValue(-1));
- EXPECT_FLOAT_EQ(2, curve->getValue(0));
- EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
- EXPECT_FLOAT_EQ(4, curve->getValue(1));
- EXPECT_FLOAT_EQ(4, curve->getValue(2));
-}
-
-// Tests that a float animation with three keyframes works as expected.
-TEST(WebFloatAnimationCurveTest, ThreeFloatKeyframe) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 2),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(1, 4),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(2, 8),
- WebAnimationCurve::TimingFunctionTypeLinear);
- EXPECT_FLOAT_EQ(2, curve->getValue(-1));
- EXPECT_FLOAT_EQ(2, curve->getValue(0));
- EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
- EXPECT_FLOAT_EQ(4, curve->getValue(1));
- EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
- EXPECT_FLOAT_EQ(8, curve->getValue(2));
- EXPECT_FLOAT_EQ(8, curve->getValue(3));
-}
-
-// Tests that a float animation with multiple keys at a given time works sanely.
-TEST(WebFloatAnimationCurveTest, RepeatedFloatKeyTimes) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 4),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(1, 4),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(1, 6),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(2, 6),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- EXPECT_FLOAT_EQ(4, curve->getValue(-1));
- EXPECT_FLOAT_EQ(4, curve->getValue(0));
- EXPECT_FLOAT_EQ(4, curve->getValue(0.5));
-
- // There is a discontinuity at 1. Any value between 4 and 6 is valid.
- float value = curve->getValue(1);
- EXPECT_TRUE(value >= 4 && value <= 6);
-
- EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
- EXPECT_FLOAT_EQ(6, curve->getValue(2));
- EXPECT_FLOAT_EQ(6, curve->getValue(3));
-}
-
-// Tests that the keyframes may be added out of order.
-TEST(WebFloatAnimationCurveTest, UnsortedKeyframes) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(2, 8),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(0, 2),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(1, 4),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- EXPECT_FLOAT_EQ(2, curve->getValue(-1));
- EXPECT_FLOAT_EQ(2, curve->getValue(0));
- EXPECT_FLOAT_EQ(3, curve->getValue(0.5));
- EXPECT_FLOAT_EQ(4, curve->getValue(1));
- EXPECT_FLOAT_EQ(6, curve->getValue(1.5));
- EXPECT_FLOAT_EQ(8, curve->getValue(2));
- EXPECT_FLOAT_EQ(8, curve->getValue(3));
-}
-
-// Tests that a cubic bezier timing function works as expected.
-TEST(WebFloatAnimationCurveTest, CubicBezierTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0), 0.25, 0, 0.75, 1);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- EXPECT_FLOAT_EQ(0, curve->getValue(0));
- EXPECT_LT(0, curve->getValue(0.25));
- EXPECT_GT(0.25, curve->getValue(0.25));
- EXPECT_NEAR(curve->getValue(0.5), 0.5, 0.00015);
- EXPECT_LT(0.75, curve->getValue(0.75));
- EXPECT_GT(1, curve->getValue(0.75));
- EXPECT_FLOAT_EQ(1, curve->getValue(1));
-}
-
-// Tests that an ease timing function works as expected.
-TEST(WebFloatAnimationCurveTest, EaseTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0), WebAnimationCurve::TimingFunctionTypeEase);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- scoped_ptr<cc::TimingFunction> timing_function(
- cc::EaseTimingFunction::Create());
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(timing_function->GetValue(time), curve->getValue(time));
- }
-}
-
-// Tests using a linear timing function.
-TEST(WebFloatAnimationCurveTest, LinearTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0),
- WebAnimationCurve::TimingFunctionTypeLinear);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(time, curve->getValue(time));
- }
-}
-
-// Tests that an ease in timing function works as expected.
-TEST(WebFloatAnimationCurveTest, EaseInTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0),
- WebAnimationCurve::TimingFunctionTypeEaseIn);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- scoped_ptr<cc::TimingFunction> timing_function(
- cc::EaseInTimingFunction::Create());
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(timing_function->GetValue(time), curve->getValue(time));
- }
-}
-
-// Tests that an ease in timing function works as expected.
-TEST(WebFloatAnimationCurveTest, EaseOutTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0),
- WebAnimationCurve::TimingFunctionTypeEaseOut);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- scoped_ptr<cc::TimingFunction> timing_function(
- cc::EaseOutTimingFunction::Create());
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(timing_function->GetValue(time), curve->getValue(time));
- }
-}
-
-// Tests that an ease in timing function works as expected.
-TEST(WebFloatAnimationCurveTest, EaseInOutTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0),
- WebAnimationCurve::TimingFunctionTypeEaseInOut);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- scoped_ptr<cc::TimingFunction> timing_function(
- cc::EaseInOutTimingFunction::Create());
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(timing_function->GetValue(time), curve->getValue(time));
- }
-}
-
-// Tests that an ease in timing function works as expected.
-TEST(WebFloatAnimationCurveTest, CustomBezierTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- double x1 = 0.3;
- double y1 = 0.2;
- double x2 = 0.8;
- double y2 = 0.7;
- curve->add(WebFloatKeyframe(0, 0), x1, y1, x2, y2);
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- scoped_ptr<cc::TimingFunction> timing_function(
- cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2));
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(timing_function->GetValue(time), curve->getValue(time));
- }
-}
-
-// Tests that the default timing function is indeed ease.
-TEST(WebFloatAnimationCurveTest, DefaultTimingFunction) {
- scoped_ptr<WebFloatAnimationCurve> curve(new WebFloatAnimationCurveImpl);
- curve->add(WebFloatKeyframe(0, 0));
- curve->add(WebFloatKeyframe(1, 1),
- WebAnimationCurve::TimingFunctionTypeLinear);
-
- scoped_ptr<cc::TimingFunction> timing_function(
- cc::EaseTimingFunction::Create());
- for (int i = 0; i <= 4; ++i) {
- const double time = i * 0.25;
- EXPECT_FLOAT_EQ(timing_function->GetValue(time), curve->getValue(time));
- }
-}
-
-} // namespace
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_image_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_image_layer_impl.cc
deleted file mode 100644
index ecbfbd06bf2..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_image_layer_impl.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_image_layer_impl.h"
-
-#include "cc/layers/image_layer.h"
-#include "cc/layers/picture_image_layer.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h"
-
-namespace content {
-
-WebImageLayerImpl::WebImageLayerImpl() {
- if (WebLayerImpl::UsingPictureLayer())
- layer_.reset(new WebLayerImplFixedBounds(cc::PictureImageLayer::Create()));
- else
- layer_.reset(new WebLayerImpl(cc::ImageLayer::Create()));
-}
-
-WebImageLayerImpl::~WebImageLayerImpl() {
-}
-
-blink::WebLayer* WebImageLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebImageLayerImpl::setBitmap(SkBitmap bitmap) {
- if (WebLayerImpl::UsingPictureLayer()) {
- static_cast<cc::PictureImageLayer*>(layer_->layer())->SetBitmap(bitmap);
- static_cast<WebLayerImplFixedBounds*>(layer_.get())->SetFixedBounds(
- gfx::Size(bitmap.width(), bitmap.height()));
- } else {
- static_cast<cc::ImageLayer*>(layer_->layer())->SetBitmap(bitmap);
- }
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_image_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_image_layer_impl.h
deleted file mode 100644
index 359cfa5819d..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_image_layer_impl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_IMAGE_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_IMAGE_LAYER_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebImageLayer.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace content {
-
-class WebLayerImpl;
-
-class WebImageLayerImpl : public blink::WebImageLayer {
- public:
- CONTENT_EXPORT WebImageLayerImpl();
- virtual ~WebImageLayerImpl();
-
- // blink::WebImageLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setBitmap(SkBitmap);
-
- private:
- scoped_ptr<WebLayerImpl> layer_;
-
- DISALLOW_COPY_AND_ASSIGN(WebImageLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_IMAGE_LAYER_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_layer_impl.cc
deleted file mode 100644
index 1dde06b2278..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_layer_impl.cc
+++ /dev/null
@@ -1,489 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_layer_impl.h"
-
-#include "base/bind.h"
-#include "base/debug/trace_event_impl.h"
-#include "base/lazy_instance.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread_checker.h"
-#include "cc/animation/animation.h"
-#include "cc/base/region.h"
-#include "cc/base/switches.h"
-#include "cc/layers/layer.h"
-#include "cc/layers/layer_position_constraint.h"
-#include "cc/trees/layer_tree_host.h"
-#include "content/renderer/compositor_bindings/web_animation_impl.h"
-#include "content/renderer/compositor_bindings/web_blend_mode.h"
-#include "content/renderer/compositor_bindings/web_filter_operations_impl.h"
-#include "content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatRect.h"
-#include "third_party/WebKit/public/platform/WebGraphicsLayerDebugInfo.h"
-#include "third_party/WebKit/public/platform/WebLayerClient.h"
-#include "third_party/WebKit/public/platform/WebLayerPositionConstraint.h"
-#include "third_party/WebKit/public/platform/WebLayerScrollClient.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
-
-using cc::Animation;
-using cc::Layer;
-using blink::WebLayer;
-using blink::WebFloatPoint;
-using blink::WebVector;
-using blink::WebRect;
-using blink::WebSize;
-using blink::WebColor;
-using blink::WebFilterOperations;
-
-namespace content {
-namespace {
-
-bool g_impl_side_painting_enabled = false;
-
-} // namespace
-
-WebLayerImpl::WebLayerImpl() : layer_(Layer::Create()) {
- web_layer_client_ = NULL;
- layer_->SetLayerClient(this);
-}
-
-WebLayerImpl::WebLayerImpl(scoped_refptr<Layer> layer) : layer_(layer) {
- web_layer_client_ = NULL;
- layer_->SetLayerClient(this);
-}
-
-WebLayerImpl::~WebLayerImpl() {
- layer_->ClearRenderSurface();
- layer_->set_layer_animation_delegate(NULL);
- web_layer_client_ = NULL;
-}
-
-// static
-bool WebLayerImpl::UsingPictureLayer() {
- return g_impl_side_painting_enabled;
-}
-
-// static
-void WebLayerImpl::SetImplSidePaintingEnabled(bool enabled) {
- g_impl_side_painting_enabled = enabled;
-}
-
-int WebLayerImpl::id() const {
- return layer_->id();
-}
-
-void WebLayerImpl::invalidateRect(const blink::WebFloatRect& rect) {
- layer_->SetNeedsDisplayRect(rect);
-}
-
-void WebLayerImpl::invalidate() {
- layer_->SetNeedsDisplay();
-}
-
-void WebLayerImpl::addChild(WebLayer* child) {
- layer_->AddChild(static_cast<WebLayerImpl*>(child)->layer());
-}
-
-void WebLayerImpl::insertChild(WebLayer* child, size_t index) {
- layer_->InsertChild(static_cast<WebLayerImpl*>(child)->layer(), index);
-}
-
-void WebLayerImpl::replaceChild(WebLayer* reference, WebLayer* new_layer) {
- layer_->ReplaceChild(static_cast<WebLayerImpl*>(reference)->layer(),
- static_cast<WebLayerImpl*>(new_layer)->layer());
-}
-
-void WebLayerImpl::removeFromParent() {
- layer_->RemoveFromParent();
-}
-
-void WebLayerImpl::removeAllChildren() {
- layer_->RemoveAllChildren();
-}
-
-void WebLayerImpl::setBounds(const WebSize& size) { layer_->SetBounds(size); }
-
-WebSize WebLayerImpl::bounds() const {
- return layer_->bounds();
-}
-
-void WebLayerImpl::setMasksToBounds(bool masks_to_bounds) {
- layer_->SetMasksToBounds(masks_to_bounds);
-}
-
-bool WebLayerImpl::masksToBounds() const {
- return layer_->masks_to_bounds();
-}
-
-void WebLayerImpl::setMaskLayer(WebLayer* maskLayer) {
- layer_->SetMaskLayer(
- maskLayer ? static_cast<WebLayerImpl*>(maskLayer)->layer() : 0);
-}
-
-void WebLayerImpl::setReplicaLayer(WebLayer* replica_layer) {
- layer_->SetReplicaLayer(
- replica_layer ? static_cast<WebLayerImpl*>(replica_layer)->layer() : 0);
-}
-
-void WebLayerImpl::setOpacity(float opacity) {
- layer_->SetOpacity(opacity);
-}
-
-float WebLayerImpl::opacity() const {
- return layer_->opacity();
-}
-
-void WebLayerImpl::setBlendMode(blink::WebBlendMode blend_mode) {
- layer_->SetBlendMode(BlendModeToSkia(blend_mode));
-}
-
-blink::WebBlendMode WebLayerImpl::blendMode() const {
- return BlendModeFromSkia(layer_->blend_mode());
-}
-
-void WebLayerImpl::setIsRootForIsolatedGroup(bool isolate) {
- layer_->SetIsRootForIsolatedGroup(isolate);
-}
-
-bool WebLayerImpl::isRootForIsolatedGroup() {
- return layer_->is_root_for_isolated_group();
-}
-
-void WebLayerImpl::setOpaque(bool opaque) {
- layer_->SetContentsOpaque(opaque);
-}
-
-bool WebLayerImpl::opaque() const {
- return layer_->contents_opaque();
-}
-
-void WebLayerImpl::setPosition(const WebFloatPoint& position) {
- layer_->SetPosition(position);
-}
-
-WebFloatPoint WebLayerImpl::position() const {
- return layer_->position();
-}
-
-void WebLayerImpl::setTransform(const SkMatrix44& matrix) {
- gfx::Transform transform;
- transform.matrix() = matrix;
- layer_->SetTransform(transform);
-}
-
-void WebLayerImpl::setTransformOrigin(const blink::WebFloatPoint3D& point) {
- gfx::Point3F gfx_point = point;
- layer_->SetTransformOrigin(gfx_point);
-}
-
-blink::WebFloatPoint3D WebLayerImpl::transformOrigin() const {
- return layer_->transform_origin();
-}
-
-void WebLayerImpl::setAnchorPoint(const blink::WebFloatPoint&) {}
-
-blink::WebFloatPoint WebLayerImpl::anchorPoint() const {
- return blink::WebFloatPoint();
-}
-
-void WebLayerImpl::setAnchorPointZ(float) {}
-
-float WebLayerImpl::anchorPointZ() const {
- return 0.f;
-};
-
-SkMatrix44 WebLayerImpl::transform() const {
- return layer_->transform().matrix();
-}
-
-void WebLayerImpl::setDrawsContent(bool draws_content) {
- layer_->SetIsDrawable(draws_content);
-}
-
-bool WebLayerImpl::drawsContent() const {
- return layer_->DrawsContent();
-}
-
-void WebLayerImpl::setShouldFlattenTransform(bool flatten) {
- layer_->SetShouldFlattenTransform(flatten);
-}
-
-void WebLayerImpl::setRenderingContext(int context) {
- layer_->Set3dSortingContextId(context);
-}
-
-void WebLayerImpl::setUseParentBackfaceVisibility(
- bool use_parent_backface_visibility) {
- layer_->set_use_parent_backface_visibility(use_parent_backface_visibility);
-}
-
-void WebLayerImpl::setBackgroundColor(WebColor color) {
- layer_->SetBackgroundColor(color);
-}
-
-WebColor WebLayerImpl::backgroundColor() const {
- return layer_->background_color();
-}
-
-void WebLayerImpl::setFilters(const WebFilterOperations& filters) {
- const WebFilterOperationsImpl& filters_impl =
- static_cast<const WebFilterOperationsImpl&>(filters);
- layer_->SetFilters(filters_impl.AsFilterOperations());
-}
-
-void WebLayerImpl::setBackgroundFilters(const WebFilterOperations& filters) {
- const WebFilterOperationsImpl& filters_impl =
- static_cast<const WebFilterOperationsImpl&>(filters);
- layer_->SetBackgroundFilters(filters_impl.AsFilterOperations());
-}
-
-void WebLayerImpl::setAnimationDelegate(blink::WebAnimationDelegate* delegate) {
- animation_delegate_adapter_.reset(
- new WebToCCAnimationDelegateAdapter(delegate));
- layer_->set_layer_animation_delegate(animation_delegate_adapter_.get());
-}
-
-bool WebLayerImpl::addAnimation(blink::WebAnimation* animation) {
- bool result = layer_->AddAnimation(
- static_cast<WebAnimationImpl*>(animation)->PassAnimation());
- delete animation;
- return result;
-}
-
-void WebLayerImpl::removeAnimation(int animation_id) {
- layer_->RemoveAnimation(animation_id);
-}
-
-void WebLayerImpl::removeAnimation(
- int animation_id,
- blink::WebAnimation::TargetProperty target_property) {
- layer_->layer_animation_controller()->RemoveAnimation(
- animation_id, static_cast<Animation::TargetProperty>(target_property));
-}
-
-void WebLayerImpl::pauseAnimation(int animation_id, double time_offset) {
- layer_->PauseAnimation(animation_id, time_offset);
-}
-
-bool WebLayerImpl::hasActiveAnimation() {
- return layer_->HasActiveAnimation();
-}
-
-void WebLayerImpl::setForceRenderSurface(bool force_render_surface) {
- layer_->SetForceRenderSurface(force_render_surface);
-}
-
-void WebLayerImpl::setScrollPosition(blink::WebPoint position) {
- layer_->SetScrollOffset(gfx::Point(position).OffsetFromOrigin());
-}
-
-blink::WebPoint WebLayerImpl::scrollPosition() const {
- return gfx::PointAtOffsetFromOrigin(layer_->scroll_offset());
-}
-
-void WebLayerImpl::setScrollClipLayer(WebLayer* clip_layer) {
- if (!clip_layer) {
- layer_->SetScrollClipLayerId(Layer::INVALID_ID);
- return;
- }
- layer_->SetScrollClipLayerId(clip_layer->id());
-}
-
-bool WebLayerImpl::scrollable() const {
- return layer_->scrollable();
-}
-
-void WebLayerImpl::setUserScrollable(bool horizontal, bool vertical) {
- layer_->SetUserScrollable(horizontal, vertical);
-}
-
-bool WebLayerImpl::userScrollableHorizontal() const {
- return layer_->user_scrollable_horizontal();
-}
-
-bool WebLayerImpl::userScrollableVertical() const {
- return layer_->user_scrollable_vertical();
-}
-
-void WebLayerImpl::setHaveWheelEventHandlers(bool have_wheel_event_handlers) {
- layer_->SetHaveWheelEventHandlers(have_wheel_event_handlers);
-}
-
-bool WebLayerImpl::haveWheelEventHandlers() const {
- return layer_->have_wheel_event_handlers();
-}
-
-void WebLayerImpl::setHaveScrollEventHandlers(bool have_scroll_event_handlers) {
- layer_->SetHaveScrollEventHandlers(have_scroll_event_handlers);
-}
-
-bool WebLayerImpl::haveScrollEventHandlers() const {
- return layer_->have_scroll_event_handlers();
-}
-
-void WebLayerImpl::setShouldScrollOnMainThread(
- bool should_scroll_on_main_thread) {
- layer_->SetShouldScrollOnMainThread(should_scroll_on_main_thread);
-}
-
-bool WebLayerImpl::shouldScrollOnMainThread() const {
- return layer_->should_scroll_on_main_thread();
-}
-
-void WebLayerImpl::setNonFastScrollableRegion(const WebVector<WebRect>& rects) {
- cc::Region region;
- for (size_t i = 0; i < rects.size(); ++i)
- region.Union(rects[i]);
- layer_->SetNonFastScrollableRegion(region);
-}
-
-WebVector<WebRect> WebLayerImpl::nonFastScrollableRegion() const {
- size_t num_rects = 0;
- for (cc::Region::Iterator region_rects(layer_->non_fast_scrollable_region());
- region_rects.has_rect();
- region_rects.next())
- ++num_rects;
-
- WebVector<WebRect> result(num_rects);
- size_t i = 0;
- for (cc::Region::Iterator region_rects(layer_->non_fast_scrollable_region());
- region_rects.has_rect();
- region_rects.next()) {
- result[i] = region_rects.rect();
- ++i;
- }
- return result;
-}
-
-void WebLayerImpl::setTouchEventHandlerRegion(const WebVector<WebRect>& rects) {
- cc::Region region;
- for (size_t i = 0; i < rects.size(); ++i)
- region.Union(rects[i]);
- layer_->SetTouchEventHandlerRegion(region);
-}
-
-WebVector<WebRect> WebLayerImpl::touchEventHandlerRegion() const {
- size_t num_rects = 0;
- for (cc::Region::Iterator region_rects(layer_->touch_event_handler_region());
- region_rects.has_rect();
- region_rects.next())
- ++num_rects;
-
- WebVector<WebRect> result(num_rects);
- size_t i = 0;
- for (cc::Region::Iterator region_rects(layer_->touch_event_handler_region());
- region_rects.has_rect();
- region_rects.next()) {
- result[i] = region_rects.rect();
- ++i;
- }
- return result;
-}
-
-void WebLayerImpl::setIsContainerForFixedPositionLayers(bool enable) {
- layer_->SetIsContainerForFixedPositionLayers(enable);
-}
-
-bool WebLayerImpl::isContainerForFixedPositionLayers() const {
- return layer_->IsContainerForFixedPositionLayers();
-}
-
-static blink::WebLayerPositionConstraint ToWebLayerPositionConstraint(
- const cc::LayerPositionConstraint& constraint) {
- blink::WebLayerPositionConstraint web_constraint;
- web_constraint.isFixedPosition = constraint.is_fixed_position();
- web_constraint.isFixedToRightEdge = constraint.is_fixed_to_right_edge();
- web_constraint.isFixedToBottomEdge = constraint.is_fixed_to_bottom_edge();
- return web_constraint;
-}
-
-static cc::LayerPositionConstraint ToLayerPositionConstraint(
- const blink::WebLayerPositionConstraint& web_constraint) {
- cc::LayerPositionConstraint constraint;
- constraint.set_is_fixed_position(web_constraint.isFixedPosition);
- constraint.set_is_fixed_to_right_edge(web_constraint.isFixedToRightEdge);
- constraint.set_is_fixed_to_bottom_edge(web_constraint.isFixedToBottomEdge);
- return constraint;
-}
-
-void WebLayerImpl::setPositionConstraint(
- const blink::WebLayerPositionConstraint& constraint) {
- layer_->SetPositionConstraint(ToLayerPositionConstraint(constraint));
-}
-
-blink::WebLayerPositionConstraint WebLayerImpl::positionConstraint() const {
- return ToWebLayerPositionConstraint(layer_->position_constraint());
-}
-
-void WebLayerImpl::setScrollClient(blink::WebLayerScrollClient* scroll_client) {
- if (scroll_client) {
- layer_->set_did_scroll_callback(
- base::Bind(&blink::WebLayerScrollClient::didScroll,
- base::Unretained(scroll_client)));
- } else {
- layer_->set_did_scroll_callback(base::Closure());
- }
-}
-
-bool WebLayerImpl::isOrphan() const {
- return !layer_->layer_tree_host();
-}
-
-void WebLayerImpl::setWebLayerClient(blink::WebLayerClient* client) {
- web_layer_client_ = client;
-}
-
-class TracedDebugInfo : public base::debug::ConvertableToTraceFormat {
- public:
- // This object takes ownership of the debug_info object.
- explicit TracedDebugInfo(blink::WebGraphicsLayerDebugInfo* debug_info)
- : debug_info_(debug_info) {}
- virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE {
- DCHECK(thread_checker_.CalledOnValidThread());
- blink::WebString web_string;
- debug_info_->appendAsTraceFormat(&web_string);
- out->append(web_string.utf8());
- }
-
- private:
- virtual ~TracedDebugInfo() {}
- scoped_ptr<blink::WebGraphicsLayerDebugInfo> debug_info_;
- base::ThreadChecker thread_checker_;
-};
-
-scoped_refptr<base::debug::ConvertableToTraceFormat>
-WebLayerImpl::TakeDebugInfo() {
- if (!web_layer_client_)
- return NULL;
- blink::WebGraphicsLayerDebugInfo* debug_info =
- web_layer_client_->takeDebugInfoFor(this);
-
- if (debug_info)
- return new TracedDebugInfo(debug_info);
- else
- return NULL;
-}
-
-void WebLayerImpl::setScrollParent(blink::WebLayer* parent) {
- cc::Layer* scroll_parent = NULL;
- if (parent)
- scroll_parent = static_cast<WebLayerImpl*>(parent)->layer();
- layer_->SetScrollParent(scroll_parent);
-}
-
-void WebLayerImpl::setClipParent(blink::WebLayer* parent) {
- cc::Layer* clip_parent = NULL;
- if (parent)
- clip_parent = static_cast<WebLayerImpl*>(parent)->layer();
- layer_->SetClipParent(clip_parent);
-}
-
-Layer* WebLayerImpl::layer() const {
- return layer_.get();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_layer_impl.h
deleted file mode 100644
index 72f2b347562..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_layer_impl.h
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_LAYER_IMPL_H_
-
-#include <string>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "cc/layers/layer_client.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebAnimation.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebColor.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebLayer.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
-
-namespace cc {
-class Layer;
-}
-
-namespace blink {
-class WebFilterOperations;
-class WebLayerClient;
-struct WebFloatRect;
-}
-
-namespace base {
-namespace debug {
-class ConvertableToTraceFormat;
-}
-}
-
-namespace content {
-
-class WebToCCAnimationDelegateAdapter;
-
-class WebLayerImpl : public blink::WebLayer, public cc::LayerClient {
- public:
- CONTENT_EXPORT WebLayerImpl();
- CONTENT_EXPORT explicit WebLayerImpl(
- scoped_refptr<cc::Layer>);
- virtual ~WebLayerImpl();
-
- static bool UsingPictureLayer();
- CONTENT_EXPORT static void SetImplSidePaintingEnabled(
- bool enabled);
-
- CONTENT_EXPORT cc::Layer* layer() const;
-
- // WebLayer implementation.
- virtual int id() const;
- virtual void invalidateRect(const blink::WebFloatRect&);
- virtual void invalidate();
- virtual void addChild(blink::WebLayer* child);
- virtual void insertChild(blink::WebLayer* child, size_t index);
- virtual void replaceChild(blink::WebLayer* reference,
- blink::WebLayer* new_layer);
- virtual void removeFromParent();
- virtual void removeAllChildren();
- virtual void setBounds(const blink::WebSize& bounds);
- virtual blink::WebSize bounds() const;
- virtual void setMasksToBounds(bool masks_to_bounds);
- virtual bool masksToBounds() const;
- virtual void setMaskLayer(blink::WebLayer* mask);
- virtual void setReplicaLayer(blink::WebLayer* replica);
- virtual void setOpacity(float opacity);
- virtual float opacity() const;
- virtual void setBlendMode(blink::WebBlendMode blend_mode);
- virtual blink::WebBlendMode blendMode() const;
- virtual void setIsRootForIsolatedGroup(bool root);
- virtual bool isRootForIsolatedGroup();
- virtual void setOpaque(bool opaque);
- virtual bool opaque() const;
- virtual void setPosition(const blink::WebFloatPoint& position);
- virtual blink::WebFloatPoint position() const;
- virtual void setTransform(const SkMatrix44& transform);
- virtual void setTransformOrigin(const blink::WebFloatPoint3D& point);
- virtual blink::WebFloatPoint3D transformOrigin() const;
-
- // FIXME: get rid of these once Blink is no longer using them.
- virtual void setAnchorPoint(const blink::WebFloatPoint&);
- virtual blink::WebFloatPoint anchorPoint() const;
- virtual void setAnchorPointZ(float);
- virtual float anchorPointZ() const ;
-
- virtual SkMatrix44 transform() const;
- virtual void setDrawsContent(bool draws_content);
- virtual bool drawsContent() const;
- virtual void setShouldFlattenTransform(bool flatten);
- virtual void setRenderingContext(int context);
- virtual void setUseParentBackfaceVisibility(bool visible);
- virtual void setBackgroundColor(blink::WebColor color);
- virtual blink::WebColor backgroundColor() const;
- virtual void setFilters(const blink::WebFilterOperations& filters);
- virtual void setBackgroundFilters(const blink::WebFilterOperations& filters);
- virtual void setAnimationDelegate(blink::WebAnimationDelegate* delegate);
- virtual bool addAnimation(blink::WebAnimation* animation);
- virtual void removeAnimation(int animation_id);
- virtual void removeAnimation(int animation_id,
- blink::WebAnimation::TargetProperty);
- virtual void pauseAnimation(int animation_id, double time_offset);
- virtual bool hasActiveAnimation();
- virtual void setForceRenderSurface(bool force);
- virtual void setScrollPosition(blink::WebPoint position);
- virtual blink::WebPoint scrollPosition() const;
- virtual void setScrollClipLayer(blink::WebLayer* clip_layer);
- virtual bool scrollable() const;
- virtual void setUserScrollable(bool horizontal, bool vertical);
- virtual bool userScrollableHorizontal() const;
- virtual bool userScrollableVertical() const;
- virtual void setHaveWheelEventHandlers(bool have_wheel_event_handlers);
- virtual bool haveWheelEventHandlers() const;
- virtual void setHaveScrollEventHandlers(bool have_scroll_event_handlers);
- virtual bool haveScrollEventHandlers() const;
- virtual void setShouldScrollOnMainThread(bool scroll_on_main);
- virtual bool shouldScrollOnMainThread() const;
- virtual void setNonFastScrollableRegion(
- const blink::WebVector<blink::WebRect>& region);
- virtual blink::WebVector<blink::WebRect> nonFastScrollableRegion() const;
- virtual void setTouchEventHandlerRegion(
- const blink::WebVector<blink::WebRect>& region);
- virtual blink::WebVector<blink::WebRect> touchEventHandlerRegion() const;
- virtual void setIsContainerForFixedPositionLayers(bool is_container);
- virtual bool isContainerForFixedPositionLayers() const;
- virtual void setPositionConstraint(
- const blink::WebLayerPositionConstraint& constraint);
- virtual blink::WebLayerPositionConstraint positionConstraint() const;
- virtual void setScrollClient(blink::WebLayerScrollClient* client);
- virtual bool isOrphan() const;
- virtual void setWebLayerClient(blink::WebLayerClient* client);
-
- // LayerClient implementation.
- virtual scoped_refptr<base::debug::ConvertableToTraceFormat>
- TakeDebugInfo() OVERRIDE;
-
- virtual void setScrollParent(blink::WebLayer* parent);
- virtual void setClipParent(blink::WebLayer* parent);
-
- protected:
- scoped_refptr<cc::Layer> layer_;
- blink::WebLayerClient* web_layer_client_;
-
- private:
- scoped_ptr<WebToCCAnimationDelegateAdapter> animation_delegate_adapter_;
-
- DISALLOW_COPY_AND_ASSIGN(WebLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_LAYER_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc b/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc
deleted file mode 100644
index b3195f9946c..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h"
-
-#include "cc/layers/layer.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
-
-using cc::Layer;
-
-namespace content {
-
-WebLayerImplFixedBounds::WebLayerImplFixedBounds() {
-}
-
-WebLayerImplFixedBounds::WebLayerImplFixedBounds(scoped_refptr<Layer> layer)
- : WebLayerImpl(layer) {
-}
-
-WebLayerImplFixedBounds::~WebLayerImplFixedBounds() {
-}
-
-void WebLayerImplFixedBounds::invalidateRect(const blink::WebFloatRect& rect) {
- // Partial invalidations seldom occur for such layers.
- // Simply invalidate the whole layer to avoid transformation of coordinates.
- invalidate();
-}
-
-void WebLayerImplFixedBounds::setTransformOrigin(
- const blink::WebFloatPoint3D& transform_origin) {
- if (transform_origin != this->transformOrigin()) {
- layer_->SetTransformOrigin(transform_origin);
- UpdateLayerBoundsAndTransform();
- }
-}
-
-void WebLayerImplFixedBounds::setBounds(const blink::WebSize& bounds) {
- if (original_bounds_ != gfx::Size(bounds)) {
- original_bounds_ = bounds;
- UpdateLayerBoundsAndTransform();
- }
-}
-
-blink::WebSize WebLayerImplFixedBounds::bounds() const {
- return original_bounds_;
-}
-
-void WebLayerImplFixedBounds::setTransform(const SkMatrix44& matrix) {
- gfx::Transform transform;
- transform.matrix() = matrix;
- SetTransformInternal(transform);
-}
-
-SkMatrix44 WebLayerImplFixedBounds::transform() const {
- return original_transform_.matrix();
-}
-
-void WebLayerImplFixedBounds::SetFixedBounds(gfx::Size fixed_bounds) {
- if (fixed_bounds_ != fixed_bounds) {
- fixed_bounds_ = fixed_bounds;
- UpdateLayerBoundsAndTransform();
- }
-}
-
-void WebLayerImplFixedBounds::SetTransformInternal(
- const gfx::Transform& transform) {
- if (original_transform_ != transform) {
- original_transform_ = transform;
- UpdateLayerBoundsAndTransform();
- }
-}
-
-void WebLayerImplFixedBounds::UpdateLayerBoundsAndTransform() {
- if (fixed_bounds_.IsEmpty() || original_bounds_.IsEmpty() ||
- fixed_bounds_ == original_bounds_ ||
- // For now fall back to non-fixed bounds for non-zero transform origin.
- // TODO(wangxianzhu): Support non-zero anchor point for fixed bounds.
- transformOrigin().x ||
- transformOrigin().y) {
- layer_->SetBounds(original_bounds_);
- layer_->SetTransform(original_transform_);
- return;
- }
-
- layer_->SetBounds(fixed_bounds_);
-
- // Apply bounds scale (bounds/fixed_bounds) over original transform.
- gfx::Transform transform_with_bounds_scale(original_transform_);
- float bounds_scale_x =
- static_cast<float>(original_bounds_.width()) / fixed_bounds_.width();
- float bounds_scale_y =
- static_cast<float>(original_bounds_.height()) / fixed_bounds_.height();
- transform_with_bounds_scale.Scale(bounds_scale_x, bounds_scale_y);
- layer_->SetTransform(transform_with_bounds_scale);
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h b/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h
deleted file mode 100644
index 2048666fd18..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_LAYER_IMPL_FIXED_BOUNDS_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_LAYER_IMPL_FIXED_BOUNDS_H_
-
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "ui/gfx/size.h"
-#include "ui/gfx/transform.h"
-
-namespace content {
-
-// A special implementation of WebLayerImpl for layers that its contents
-// need to be automatically scaled when the bounds changes. The compositor
-// can efficiently handle the bounds change of such layers if the bounds
-// is fixed to a given value and the change of bounds are converted to
-// transformation scales.
-class WebLayerImplFixedBounds : public WebLayerImpl {
- public:
- CONTENT_EXPORT WebLayerImplFixedBounds();
- CONTENT_EXPORT explicit WebLayerImplFixedBounds(
- scoped_refptr<cc::Layer>);
- virtual ~WebLayerImplFixedBounds();
-
- // WebLayerImpl overrides.
- virtual void invalidateRect(const blink::WebFloatRect& rect);
- virtual void setTransformOrigin(
- const blink::WebFloatPoint3D& transform_origin);
- virtual void setBounds(const blink::WebSize& bounds);
- virtual blink::WebSize bounds() const;
- virtual void setTransform(const SkMatrix44& transform);
- virtual SkMatrix44 transform() const;
-
- CONTENT_EXPORT void SetFixedBounds(gfx::Size bounds);
-
- protected:
- void SetTransformInternal(const gfx::Transform& transform);
- void UpdateLayerBoundsAndTransform();
-
- gfx::Transform original_transform_;
- gfx::Size original_bounds_;
- gfx::Size fixed_bounds_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebLayerImplFixedBounds);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_LAYER_IMPL_FIXED_BOUNDS_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc b/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc
deleted file mode 100644
index 1ab52f0ddc0..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_layer_impl_fixed_bounds_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2014 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 <vector>
-#include "cc/layers/picture_image_layer.h"
-#include "cc/test/fake_layer_tree_host.h"
-#include "cc/test/geometry_test_utils.h"
-#include "cc/trees/layer_tree_host_common.h"
-#include "content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
-#include "ui/gfx/point3_f.h"
-
-using blink::WebFloatPoint;
-using blink::WebSize;
-
-namespace content {
-namespace {
-
-TEST(WebLayerImplFixedBoundsTest, IdentityBounds) {
- scoped_ptr<WebLayerImplFixedBounds> layer(new WebLayerImplFixedBounds());
- layer->setAnchorPoint(WebFloatPoint(0, 0));
- layer->SetFixedBounds(gfx::Size(100, 100));
- layer->setBounds(WebSize(100, 100));
- EXPECT_EQ(WebSize(100, 100), layer->bounds());
- EXPECT_EQ(gfx::Size(100, 100), layer->layer()->bounds());
- EXPECT_EQ(gfx::Transform(), layer->layer()->transform());
-}
-
-gfx::Point3F TransformPoint(const gfx::Transform& transform,
- const gfx::Point3F& point) {
- gfx::Point3F result = point;
- transform.TransformPoint(&result);
- return result;
-}
-
-void CheckBoundsScaleSimple(WebLayerImplFixedBounds* layer,
- const WebSize& bounds,
- const gfx::Size& fixed_bounds) {
- layer->setBounds(bounds);
- layer->SetFixedBounds(fixed_bounds);
-
- EXPECT_EQ(bounds, layer->bounds());
- EXPECT_EQ(fixed_bounds, layer->layer()->bounds());
- EXPECT_TRUE(layer->transform().isIdentity());
-
- // An arbitrary point to check the scale and transforms.
- gfx::Point3F original_point(10, 20, 1);
- gfx::Point3F scaled_point(
- original_point.x() * bounds.width / fixed_bounds.width(),
- original_point.y() * bounds.height / fixed_bounds.height(),
- original_point.z());
- // Test if the bounds scale is correctly applied in transform.
- EXPECT_POINT3F_EQ(
- scaled_point,
- TransformPoint(layer->layer()->transform(), original_point));
-}
-
-TEST(WebLayerImplFixedBoundsTest, BoundsScaleSimple) {
- scoped_ptr<WebLayerImplFixedBounds> layer(new WebLayerImplFixedBounds());
- layer->setAnchorPoint(WebFloatPoint(0, 0));
- CheckBoundsScaleSimple(layer.get(), WebSize(100, 200), gfx::Size(150, 250));
- // Change fixed_bounds.
- CheckBoundsScaleSimple(layer.get(), WebSize(100, 200), gfx::Size(75, 100));
- // Change bounds.
- CheckBoundsScaleSimple(layer.get(), WebSize(300, 100), gfx::Size(75, 100));
-}
-
-void ExpectEqualLayerRectsInTarget(cc::Layer* layer1, cc::Layer* layer2) {
- gfx::RectF layer1_rect_in_target(layer1->content_bounds());
- layer1->draw_transform().TransformRect(&layer1_rect_in_target);
-
- gfx::RectF layer2_rect_in_target(layer2->content_bounds());
- layer2->draw_transform().TransformRect(&layer2_rect_in_target);
-
- EXPECT_FLOAT_RECT_EQ(layer1_rect_in_target, layer2_rect_in_target);
-}
-
-void CompareFixedBoundsLayerAndNormalLayer(const WebFloatPoint& anchor_point,
- const gfx::Transform& transform) {
- const gfx::Size kDeviceViewportSize(800, 600);
- const float kDeviceScaleFactor = 2.f;
- const float kPageScaleFactor = 1.5f;
-
- WebSize bounds(150, 200);
- WebFloatPoint position(20, 30);
- gfx::Size fixed_bounds(160, 70);
-
- scoped_ptr<WebLayerImplFixedBounds> root_layer(new WebLayerImplFixedBounds());
-
- WebLayerImplFixedBounds* fixed_bounds_layer =
- new WebLayerImplFixedBounds(cc::PictureImageLayer::Create());
- fixed_bounds_layer->setBounds(bounds);
- fixed_bounds_layer->SetFixedBounds(fixed_bounds);
- fixed_bounds_layer->setAnchorPoint(anchor_point);
- fixed_bounds_layer->setTransform(transform.matrix());
- fixed_bounds_layer->setPosition(position);
- root_layer->addChild(fixed_bounds_layer);
-
- WebLayerImpl* normal_layer(new WebLayerImpl(cc::PictureImageLayer::Create()));
-
- normal_layer->setBounds(bounds);
- normal_layer->setAnchorPoint(anchor_point);
- normal_layer->setTransform(transform.matrix());
- normal_layer->setPosition(position);
- root_layer->addChild(normal_layer);
-
- scoped_ptr<cc::FakeLayerTreeHost> host = cc::FakeLayerTreeHost::Create();
- host->SetRootLayer(root_layer->layer());
-
- {
- cc::RenderSurfaceLayerList render_surface_layer_list;
- cc::LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root_layer->layer(), kDeviceViewportSize, &render_surface_layer_list);
- inputs.device_scale_factor = kDeviceScaleFactor;
- inputs.page_scale_factor = kPageScaleFactor;
- inputs.page_scale_application_layer = root_layer->layer(),
- cc::LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
- ExpectEqualLayerRectsInTarget(normal_layer->layer(),
- fixed_bounds_layer->layer());
- }
-
- // Change of fixed bounds should not affect the target geometries.
- fixed_bounds_layer->SetFixedBounds(
- gfx::Size(fixed_bounds.width() / 2, fixed_bounds.height() * 2));
-
- {
- cc::RenderSurfaceLayerList render_surface_layer_list;
- cc::LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
- root_layer->layer(), kDeviceViewportSize, &render_surface_layer_list);
- inputs.device_scale_factor = kDeviceScaleFactor;
- inputs.page_scale_factor = kPageScaleFactor;
- inputs.page_scale_application_layer = root_layer->layer(),
- cc::LayerTreeHostCommon::CalculateDrawProperties(&inputs);
-
- ExpectEqualLayerRectsInTarget(normal_layer->layer(),
- fixed_bounds_layer->layer());
- }
-}
-
-// TODO(perkj): CompareToWebLayerImplSimple disabled on LSAN due to crbug/386080
-#if defined(LEAK_SANITIZER)
-#define MAYBE_CompareToWebLayerImplSimple DISABLED_CompareToWebLayerImplSimple
-#else
-#define MAYBE_CompareToWebLayerImplSimple CompareToWebLayerImplSimple
-#endif
-// A black box test that ensures WebLayerImplFixedBounds won't change target
-// geometries. Simple case: identity transforms and zero anchor point.
-TEST(WebLayerImplFixedBoundsTest, MAYBE_CompareToWebLayerImplSimple) {
- CompareFixedBoundsLayerAndNormalLayer(WebFloatPoint(0, 0), gfx::Transform());
-}
-
-// TODO(perkj): CompareToWebLayerImplComplex disabled on LSAN due to
-// crbug/386080
-#if defined(LEAK_SANITIZER)
-#define MAYBE_CompareToWebLayerImplComplex DISABLED_CompareToWebLayerImplComplex
-#else
-#define MAYBE_CompareToWebLayerImplComplex CompareToWebLayerImplComplex
-#endif
-// A black box test that ensures WebLayerImplFixedBounds won't change target
-// geometries. Complex case: complex transforms and non-zero anchor point.
-TEST(WebLayerImplFixedBoundsTest, MAYBE_CompareToWebLayerImplComplex) {
- gfx::Transform transform;
- // These are arbitrary values that should not affect the results.
- transform.Translate3d(50, 60, 70);
- transform.Scale3d(2, 3, 4);
- transform.RotateAbout(gfx::Vector3dF(33, 44, 55), 99);
-
- CompareFixedBoundsLayerAndNormalLayer(WebFloatPoint(0, 0), transform);
-
- // With non-zero anchor point, WebLayerImplFixedBounds will fall back to
- // WebLayerImpl.
- CompareFixedBoundsLayerAndNormalLayer(WebFloatPoint(0.4f, 0.6f), transform);
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.cc
deleted file mode 100644
index 55a7501b3ad..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_nine_patch_layer_impl.h"
-
-#include "base/command_line.h"
-#include "cc/base/switches.h"
-#include "cc/layers/nine_patch_layer.h"
-#include "cc/layers/picture_image_layer.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl_fixed_bounds.h"
-
-namespace content {
-
-WebNinePatchLayerImpl::WebNinePatchLayerImpl() {
- layer_.reset(new WebLayerImpl(cc::NinePatchLayer::Create()));
-}
-
-WebNinePatchLayerImpl::~WebNinePatchLayerImpl() {
-}
-
-blink::WebLayer* WebNinePatchLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebNinePatchLayerImpl::setBitmap(SkBitmap bitmap,
- const blink::WebRect& aperture) {
- setBitmap(bitmap);
- setAperture(aperture);
- setBorder(blink::WebRect(aperture.x,
- aperture.y,
- bitmap.width() - aperture.width,
- bitmap.height() - aperture.height));
-}
-
-void WebNinePatchLayerImpl::setBitmap(SkBitmap bitmap) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetBitmap(bitmap);
-}
-
-void WebNinePatchLayerImpl::setAperture(const blink::WebRect& aperture) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetAperture(gfx::Rect(aperture));
-}
-
-void WebNinePatchLayerImpl::setBorder(const blink::WebRect& border) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetBorder(gfx::Rect(border));
-}
-
-void WebNinePatchLayerImpl::setFillCenter(bool fill_center) {
- cc::NinePatchLayer* nine_patch =
- static_cast<cc::NinePatchLayer*>(layer_->layer());
- nine_patch->SetFillCenter(fill_center);
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.h
deleted file mode 100644
index cad69d7295e..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_nine_patch_layer_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_NINE_PATCH_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_NINE_PATCH_LAYER_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebNinePatchLayer.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace content {
-
-class WebLayerImpl;
-
-class WebNinePatchLayerImpl : public blink::WebNinePatchLayer {
- public:
- CONTENT_EXPORT WebNinePatchLayerImpl();
- virtual ~WebNinePatchLayerImpl();
-
- // blink::WebNinePatchLayer implementation.
- virtual blink::WebLayer* layer();
-
- // TODO(ccameron): Remove setBitmap(SkBitmap, blink::WebRect) in favor of
- // setBitmap(), setAperture(), and setBorder();
- virtual void setBitmap(SkBitmap bitmap, const blink::WebRect& aperture);
- virtual void setBitmap(SkBitmap bitmap);
- virtual void setAperture(const blink::WebRect& aperture);
- virtual void setBorder(const blink::WebRect& border);
- virtual void setFillCenter(bool fill_center);
-
- private:
- scoped_ptr<WebLayerImpl> layer_;
-
- DISALLOW_COPY_AND_ASSIGN(WebNinePatchLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_NINE_PATCH_LAYER_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc b/chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc
deleted file mode 100644
index 3b752716631..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h"
-
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-
-#include "cc/animation/scroll_offset_animation_curve.h"
-#include "cc/animation/timing_function.h"
-#include "content/renderer/compositor_bindings/web_animation_curve_common.h"
-
-using blink::WebFloatPoint;
-
-namespace content {
-
-WebScrollOffsetAnimationCurveImpl::WebScrollOffsetAnimationCurveImpl(
- WebFloatPoint target_value,
- TimingFunctionType timing_function)
- : curve_(cc::ScrollOffsetAnimationCurve::Create(
- gfx::Vector2dF(target_value.x, target_value.y),
- CreateTimingFunction(timing_function))) {
-}
-
-WebScrollOffsetAnimationCurveImpl::~WebScrollOffsetAnimationCurveImpl() {
-}
-
-blink::WebAnimationCurve::AnimationCurveType
-WebScrollOffsetAnimationCurveImpl::type() const {
- return WebAnimationCurve::AnimationCurveTypeScrollOffset;
-}
-
-void WebScrollOffsetAnimationCurveImpl::setInitialValue(
- WebFloatPoint initial_value) {
- curve_->SetInitialValue(gfx::Vector2dF(initial_value.x, initial_value.y));
-}
-
-WebFloatPoint WebScrollOffsetAnimationCurveImpl::getValue(double time) const {
- gfx::Vector2dF value = curve_->GetValue(time);
- return WebFloatPoint(value.x(), value.y());
-}
-
-double WebScrollOffsetAnimationCurveImpl::duration() const {
- return curve_->Duration();
-}
-
-scoped_ptr<cc::AnimationCurve>
-WebScrollOffsetAnimationCurveImpl::CloneToAnimationCurve() const {
- return curve_->Clone();
-}
-
-} // namespace content
-
-#endif // WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-
diff --git a/chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h b/chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h
deleted file mode 100644
index 4c29f8fdd76..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SCROLL_OFFSET_ANIMATION_CURVE_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SCROLL_OFFSET_ANIMATION_CURVE_IMPL_H_
-
-#include "third_party/WebKit/public/platform/WebAnimationCurve.h"
-
-#if WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebScrollOffsetAnimationCurve.h"
-
-namespace cc {
-class AnimationCurve;
-class ScrollOffsetAnimationCurve;
-}
-
-namespace content {
-
-class WebScrollOffsetAnimationCurveImpl
- : public blink::WebScrollOffsetAnimationCurve {
- public:
- CONTENT_EXPORT WebScrollOffsetAnimationCurveImpl(
- blink::WebFloatPoint target_value,
- TimingFunctionType timing_function);
- virtual ~WebScrollOffsetAnimationCurveImpl();
-
- // blink::WebAnimationCurve implementation.
- virtual AnimationCurveType type() const;
-
- // blink::WebScrollOffsetAnimationCurve implementation.
- virtual void setInitialValue(blink::WebFloatPoint initial_value);
- virtual blink::WebFloatPoint getValue(double time) const;
- virtual double duration() const;
-
- scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
-
- private:
- scoped_ptr<cc::ScrollOffsetAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(WebScrollOffsetAnimationCurveImpl);
-};
-
-} // namespace content
-
-#endif // WEB_SCROLL_OFFSET_ANIMATION_CURVE_IS_DEFINED
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SCROLL_OFFSET_ANIMATION_CURVE_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.cc
deleted file mode 100644
index 0d3be19aeca..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_scrollbar_layer_impl.h"
-
-#include "cc/layers/layer.h"
-#include "cc/layers/painted_scrollbar_layer.h"
-#include "cc/layers/scrollbar_layer_interface.h"
-#include "cc/layers/solid_color_scrollbar_layer.h"
-#include "content/renderer/compositor_bindings/scrollbar_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-
-using cc::PaintedScrollbarLayer;
-using cc::SolidColorScrollbarLayer;
-
-namespace {
-
-cc::ScrollbarOrientation ConvertOrientation(
- blink::WebScrollbar::Orientation orientation) {
- return orientation == blink::WebScrollbar::Horizontal ? cc::HORIZONTAL
- : cc::VERTICAL;
-}
-
-} // namespace
-
-namespace content {
-
-WebScrollbarLayerImpl::WebScrollbarLayerImpl(
- blink::WebScrollbar* scrollbar,
- blink::WebScrollbarThemePainter painter,
- blink::WebScrollbarThemeGeometry* geometry)
- : layer_(new WebLayerImpl(PaintedScrollbarLayer::Create(
- scoped_ptr<cc::Scrollbar>(
- new ScrollbarImpl(make_scoped_ptr(scrollbar),
- painter,
- make_scoped_ptr(geometry))).Pass(),
- 0))) {
-}
-
-WebScrollbarLayerImpl::WebScrollbarLayerImpl(
- blink::WebScrollbar::Orientation orientation,
- int thumb_thickness,
- int track_start,
- bool is_left_side_vertical_scrollbar)
- : layer_(new WebLayerImpl(
- SolidColorScrollbarLayer::Create(ConvertOrientation(orientation),
- thumb_thickness,
- track_start,
- is_left_side_vertical_scrollbar,
- 0))) {
-}
-
-WebScrollbarLayerImpl::~WebScrollbarLayerImpl() {
-}
-
-blink::WebLayer* WebScrollbarLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebScrollbarLayerImpl::setScrollLayer(blink::WebLayer* layer) {
- cc::Layer* scroll_layer =
- layer ? static_cast<WebLayerImpl*>(layer)->layer() : 0;
- layer_->layer()->ToScrollbarLayer()->SetScrollLayer(scroll_layer->id());
-}
-
-void WebScrollbarLayerImpl::setClipLayer(blink::WebLayer* layer) {
- cc::Layer* clip_layer =
- layer ? static_cast<WebLayerImpl*>(layer)->layer() : 0;
- layer_->layer()->ToScrollbarLayer()->SetClipLayer(clip_layer->id());
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.h
deleted file mode 100644
index 47719e1d87c..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_scrollbar_layer_impl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SCROLLBAR_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SCROLLBAR_LAYER_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebScrollbar.h"
-#include "third_party/WebKit/public/platform/WebScrollbarLayer.h"
-
-namespace blink {
-class WebScrollbarThemeGeometry;
-class WebScrollbarThemePainter;
-}
-
-namespace content {
-
-class WebLayerImpl;
-
-class WebScrollbarLayerImpl : public blink::WebScrollbarLayer {
- public:
- CONTENT_EXPORT WebScrollbarLayerImpl(
- blink::WebScrollbar* scrollbar,
- blink::WebScrollbarThemePainter painter,
- blink::WebScrollbarThemeGeometry* geometry);
- CONTENT_EXPORT WebScrollbarLayerImpl(
- blink::WebScrollbar::Orientation orientation,
- int thumb_thickness,
- int track_start,
- bool is_left_side_vertical_scrollbar);
- virtual ~WebScrollbarLayerImpl();
-
- // blink::WebScrollbarLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setScrollLayer(blink::WebLayer* layer);
- virtual void setClipLayer(blink::WebLayer* layer);
-
- private:
- scoped_ptr<WebLayerImpl> layer_;
-
- DISALLOW_COPY_AND_ASSIGN(WebScrollbarLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SCROLLBAR_LAYER_IMPL_H_
diff --git a/chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.cc b/chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.cc
deleted file mode 100644
index 6cd9c192580..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_solid_color_layer_impl.h"
-
-#include "cc/layers/solid_color_layer.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-
-using cc::SolidColorLayer;
-
-namespace content {
-
-WebSolidColorLayerImpl::WebSolidColorLayerImpl()
- : layer_(new WebLayerImpl(SolidColorLayer::Create())) {
- layer_->layer()->SetIsDrawable(true);
-}
-
-WebSolidColorLayerImpl::~WebSolidColorLayerImpl() {
-}
-
-blink::WebLayer* WebSolidColorLayerImpl::layer() {
- return layer_.get();
-}
-
-void WebSolidColorLayerImpl::setBackgroundColor(blink::WebColor color) {
- layer_->setBackgroundColor(color);
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.h b/chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.h
deleted file mode 100644
index fe6eefe6d67..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_solid_color_layer_impl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SOLID_COLOR_LAYER_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SOLID_COLOR_LAYER_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebColor.h"
-#include "third_party/WebKit/public/platform/WebSolidColorLayer.h"
-
-namespace content {
-class WebLayerImpl;
-
-class WebSolidColorLayerImpl : public blink::WebSolidColorLayer {
- public:
- CONTENT_EXPORT WebSolidColorLayerImpl();
- virtual ~WebSolidColorLayerImpl();
-
- // blink::WebSolidColorLayer implementation.
- virtual blink::WebLayer* layer();
- virtual void setBackgroundColor(blink::WebColor);
-
- private:
- scoped_ptr<WebLayerImpl> layer_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSolidColorLayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_SOLID_COLOR_LAYER_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc b/chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc
deleted file mode 100644
index 5a953bdb42c..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h"
-
-#include "third_party/WebKit/public/platform/WebAnimationDelegate.h"
-
-namespace content {
-
-WebToCCAnimationDelegateAdapter::WebToCCAnimationDelegateAdapter(
- blink::WebAnimationDelegate* delegate)
- : delegate_(delegate) {
-}
-
-void WebToCCAnimationDelegateAdapter::NotifyAnimationStarted(
- base::TimeTicks monotonic_time,
- cc::Animation::TargetProperty target_property) {
- delegate_->notifyAnimationStarted(
- (monotonic_time - base::TimeTicks()).InSecondsF(),
- static_cast<blink::WebAnimation::TargetProperty>(target_property));
-}
-
-void WebToCCAnimationDelegateAdapter::NotifyAnimationFinished(
- base::TimeTicks monotonic_time,
- cc::Animation::TargetProperty target_property) {
- delegate_->notifyAnimationFinished(
- (monotonic_time - base::TimeTicks()).InSecondsF(),
- static_cast<blink::WebAnimation::TargetProperty>(target_property));
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h b/chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h
deleted file mode 100644
index b80b627f424..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TO_CC_ANIMATION_DELEGATE_ADAPTER_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TO_CC_ANIMATION_DELEGATE_ADAPTER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "cc/animation/animation_delegate.h"
-
-namespace blink {
-class WebAnimationDelegate;
-}
-
-namespace content {
-
-class WebToCCAnimationDelegateAdapter : public cc::AnimationDelegate {
- public:
- explicit WebToCCAnimationDelegateAdapter(
- blink::WebAnimationDelegate* delegate);
-
- private:
- virtual void NotifyAnimationStarted(
- base::TimeTicks monotonic_time,
- cc::Animation::TargetProperty target_property) OVERRIDE;
- virtual void NotifyAnimationFinished(
- base::TimeTicks monotonic_time,
- cc::Animation::TargetProperty target_property) OVERRIDE;
-
- blink::WebAnimationDelegate* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(WebToCCAnimationDelegateAdapter);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TO_CC_ANIMATION_DELEGATE_ADAPTER_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.cc b/chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.cc
deleted file mode 100644
index 8b03f48a813..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_transform_animation_curve_impl.h"
-
-#include "cc/animation/keyframed_animation_curve.h"
-#include "cc/animation/timing_function.h"
-#include "cc/animation/transform_operations.h"
-#include "content/renderer/compositor_bindings/web_animation_curve_common.h"
-#include "content/renderer/compositor_bindings/web_transform_operations_impl.h"
-
-using blink::WebTransformKeyframe;
-
-namespace content {
-
-WebTransformAnimationCurveImpl::WebTransformAnimationCurveImpl()
- : curve_(cc::KeyframedTransformAnimationCurve::Create()) {
-}
-
-WebTransformAnimationCurveImpl::~WebTransformAnimationCurveImpl() {
-}
-
-blink::WebAnimationCurve::AnimationCurveType
-WebTransformAnimationCurveImpl::type() const {
- return WebAnimationCurve::AnimationCurveTypeTransform;
-}
-
-void WebTransformAnimationCurveImpl::add(const WebTransformKeyframe& keyframe) {
- add(keyframe, TimingFunctionTypeEase);
-}
-
-void WebTransformAnimationCurveImpl::add(const WebTransformKeyframe& keyframe,
- TimingFunctionType type) {
- const cc::TransformOperations& transform_operations =
- static_cast<const WebTransformOperationsImpl&>(keyframe.value())
- .AsTransformOperations();
- curve_->AddKeyframe(cc::TransformKeyframe::Create(
- keyframe.time(), transform_operations, CreateTimingFunction(type)));
-}
-
-void WebTransformAnimationCurveImpl::add(const WebTransformKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2) {
- const cc::TransformOperations& transform_operations =
- static_cast<const WebTransformOperationsImpl&>(keyframe.value())
- .AsTransformOperations();
- curve_->AddKeyframe(cc::TransformKeyframe::Create(
- keyframe.time(),
- transform_operations,
- cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)
- .PassAs<cc::TimingFunction>()));
-}
-
-scoped_ptr<cc::AnimationCurve>
-WebTransformAnimationCurveImpl::CloneToAnimationCurve() const {
- return curve_->Clone();
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.h b/chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.h
deleted file mode 100644
index 5a0576dd7f3..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_transform_animation_curve_impl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TRANSFORM_ANIMATION_CURVE_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TRANSFORM_ANIMATION_CURVE_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebTransformAnimationCurve.h"
-
-namespace cc {
-class AnimationCurve;
-class KeyframedTransformAnimationCurve;
-}
-
-namespace blink {
-class WebTransformKeyframe;
-}
-
-namespace content {
-
-class WebTransformAnimationCurveImpl
- : public blink::WebTransformAnimationCurve {
- public:
- CONTENT_EXPORT WebTransformAnimationCurveImpl();
- virtual ~WebTransformAnimationCurveImpl();
-
- // blink::WebAnimationCurve implementation.
- virtual AnimationCurveType type() const;
-
- // blink::WebTransformAnimationCurve implementation.
- virtual void add(const blink::WebTransformKeyframe& keyframe);
- virtual void add(const blink::WebTransformKeyframe& keyframe,
- TimingFunctionType type);
- virtual void add(const blink::WebTransformKeyframe& keyframe,
- double x1,
- double y1,
- double x2,
- double y2);
-
- scoped_ptr<cc::AnimationCurve> CloneToAnimationCurve() const;
-
- private:
- scoped_ptr<cc::KeyframedTransformAnimationCurve> curve_;
-
- DISALLOW_COPY_AND_ASSIGN(WebTransformAnimationCurveImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TRANSFORM_ANIMATION_CURVE_IMPL_H_
-
diff --git a/chromium/content/renderer/compositor_bindings/web_transform_operations_impl.cc b/chromium/content/renderer/compositor_bindings/web_transform_operations_impl.cc
deleted file mode 100644
index cfec1b48153..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_transform_operations_impl.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 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 "content/renderer/compositor_bindings/web_transform_operations_impl.h"
-
-#include <algorithm>
-
-#include "ui/gfx/transform.h"
-
-namespace content {
-
-WebTransformOperationsImpl::WebTransformOperationsImpl() {
-}
-
-const cc::TransformOperations&
-WebTransformOperationsImpl::AsTransformOperations() const {
- return transform_operations_;
-}
-
-bool WebTransformOperationsImpl::canBlendWith(
- const blink::WebTransformOperations& other) const {
- const WebTransformOperationsImpl& other_impl =
- static_cast<const WebTransformOperationsImpl&>(other);
- return transform_operations_.CanBlendWith(other_impl.transform_operations_);
-}
-
-void WebTransformOperationsImpl::appendTranslate(double x, double y, double z) {
- transform_operations_.AppendTranslate(x, y, z);
-}
-
-void WebTransformOperationsImpl::appendRotate(double x,
- double y,
- double z,
- double degrees) {
- transform_operations_.AppendRotate(x, y, z, degrees);
-}
-
-void WebTransformOperationsImpl::appendScale(double x, double y, double z) {
- transform_operations_.AppendScale(x, y, z);
-}
-
-void WebTransformOperationsImpl::appendSkew(double x, double y) {
- transform_operations_.AppendSkew(x, y);
-}
-
-void WebTransformOperationsImpl::appendPerspective(double depth) {
- transform_operations_.AppendPerspective(depth);
-}
-
-void WebTransformOperationsImpl::appendMatrix(const SkMatrix44& matrix) {
- gfx::Transform transform(gfx::Transform::kSkipInitialization);
- transform.matrix() = matrix;
- transform_operations_.AppendMatrix(transform);
-}
-
-void WebTransformOperationsImpl::appendIdentity() {
- transform_operations_.AppendIdentity();
-}
-
-bool WebTransformOperationsImpl::isIdentity() const {
- return transform_operations_.IsIdentity();
-}
-
-WebTransformOperationsImpl::~WebTransformOperationsImpl() {
-}
-
-} // namespace content
-
diff --git a/chromium/content/renderer/compositor_bindings/web_transform_operations_impl.h b/chromium/content/renderer/compositor_bindings/web_transform_operations_impl.h
deleted file mode 100644
index f0f7b47ba15..00000000000
--- a/chromium/content/renderer/compositor_bindings/web_transform_operations_impl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TRANSFORM_OPERATIONS_IMPL_H_
-#define CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TRANSFORM_OPERATIONS_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cc/animation/transform_operations.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebTransformOperations.h"
-
-namespace content {
-
-class WebTransformOperationsImpl : public blink::WebTransformOperations {
- public:
- CONTENT_EXPORT WebTransformOperationsImpl();
- virtual ~WebTransformOperationsImpl();
-
- const cc::TransformOperations& AsTransformOperations() const;
-
- // Implementation of blink::WebTransformOperations methods
- virtual bool canBlendWith(const blink::WebTransformOperations& other) const;
- virtual void appendTranslate(double x, double y, double z);
- virtual void appendRotate(double x, double y, double z, double degrees);
- virtual void appendScale(double x, double y, double z);
- virtual void appendSkew(double x, double y);
- virtual void appendPerspective(double depth);
- virtual void appendMatrix(const SkMatrix44&);
- virtual void appendIdentity();
- virtual bool isIdentity() const;
-
- private:
- cc::TransformOperations transform_operations_;
-
- DISALLOW_COPY_AND_ASSIGN(WebTransformOperationsImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_COMPOSITOR_BINDINGS_WEB_TRANSFORM_OPERATIONS_IMPL_H_
-
diff --git a/chromium/content/renderer/context_menu_params_builder.cc b/chromium/content/renderer/context_menu_params_builder.cc
index 48355e832bb..63dcd4d1e7b 100644
--- a/chromium/content/renderer/context_menu_params_builder.cc
+++ b/chromium/content/renderer/context_menu_params_builder.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "content/common/ssl_status_serialization.h"
#include "content/public/common/context_menu_params.h"
+#include "content/renderer/dom_utils.h"
#include "content/renderer/history_serialization.h"
#include "content/renderer/menu_item_builder.h"
#include "third_party/WebKit/public/web/WebElement.h"
@@ -40,6 +41,7 @@ ContextMenuParams ContextMenuParamsBuilder::Build(
params.edit_flags = data.editFlags;
params.frame_charset = data.frameEncoding.utf8();
params.referrer_policy = data.referrerPolicy;
+ params.suggested_filename = data.suggestedFilename;
for (size_t i = 0; i < data.dictionarySuggestions.size(); ++i)
params.dictionary_suggestions.push_back(data.dictionarySuggestions[i]);
@@ -54,16 +56,9 @@ ContextMenuParams ContextMenuParamsBuilder::Build(
}
if (!params.link_url.is_empty()) {
- blink::WebNode selectedNode = data.node;
-
- // If there are other embedded tags (like <a ..>Some <b>text</b></a>)
- // we need to extract the parent <a/> node.
- while (!selectedNode.isLink() && !selectedNode.parentNode().isNull()) {
- selectedNode = selectedNode.parentNode();
- }
-
+ blink::WebNode selectedNode = DomUtils::ExtractParentAnchorNode(data.node);
blink::WebElement selectedElement = selectedNode.to<blink::WebElement>();
- if (selectedNode.isLink() && !selectedElement.isNull()) {
+ if (!selectedElement.isNull() && selectedNode.isLink()) {
params.link_text = selectedElement.innerText();
} else {
LOG(ERROR) << "Creating a ContextMenuParams for a node that has a link"
diff --git a/chromium/content/renderer/device_sensors/device_light_event_pump.cc b/chromium/content/renderer/device_sensors/device_light_event_pump.cc
new file mode 100644
index 00000000000..53567441df8
--- /dev/null
+++ b/chromium/content/renderer/device_sensors/device_light_event_pump.cc
@@ -0,0 +1,82 @@
+// Copyright 2014 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 "content/renderer/device_sensors/device_light_event_pump.h"
+
+#include "base/time/time.h"
+#include "content/common/device_sensors/device_light_messages.h"
+#include "content/public/renderer/render_thread.h"
+#include "third_party/WebKit/public/platform/WebDeviceLightListener.h"
+
+namespace {
+// Default rate for firing of DeviceLight events.
+const int kDefaultLightPumpFrequencyHz = 5;
+const int kDefaultLightPumpDelayMicroseconds =
+ base::Time::kMicrosecondsPerSecond / kDefaultLightPumpFrequencyHz;
+} // namespace
+
+namespace content {
+
+DeviceLightEventPump::DeviceLightEventPump(RenderThread* thread)
+ : DeviceSensorEventPump<blink::WebDeviceLightListener>(thread),
+ last_seen_data_(-1) {
+ pump_delay_microseconds_ = kDefaultLightPumpDelayMicroseconds;
+}
+
+DeviceLightEventPump::~DeviceLightEventPump() {
+}
+
+bool DeviceLightEventPump::OnControlMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(DeviceLightEventPump, message)
+ IPC_MESSAGE_HANDLER(DeviceLightMsg_DidStartPolling, OnDidStart)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void DeviceLightEventPump::FireEvent() {
+ DCHECK(listener());
+ DeviceLightData data;
+ if (reader_->GetLatestData(&data) && ShouldFireEvent(data.value)) {
+ last_seen_data_ = data.value;
+ listener()->didChangeDeviceLight(data.value);
+ }
+}
+
+bool DeviceLightEventPump::ShouldFireEvent(double lux) const {
+ if (lux < 0)
+ return false;
+
+ if (lux == std::numeric_limits<double>::infinity()) {
+ // no sensor data can be provided, fire an Infinity event to Blink.
+ return true;
+ }
+
+ return lux != last_seen_data_;
+}
+
+bool DeviceLightEventPump::InitializeReader(base::SharedMemoryHandle handle) {
+ if (!reader_)
+ reader_.reset(new DeviceLightSharedMemoryReader());
+ return reader_->Initialize(handle);
+}
+
+void DeviceLightEventPump::SendStartMessage() {
+ RenderThread::Get()->Send(new DeviceLightHostMsg_StartPolling());
+}
+
+void DeviceLightEventPump::SendStopMessage() {
+ last_seen_data_ = -1;
+ RenderThread::Get()->Send(new DeviceLightHostMsg_StopPolling());
+}
+
+void DeviceLightEventPump::SendFakeDataForTesting(void* fake_data) {
+ double data = *static_cast<double*>(fake_data);
+
+ listener()->didChangeDeviceLight(data);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_light_event_pump.h b/chromium/content/renderer/device_sensors/device_light_event_pump.h
new file mode 100644
index 00000000000..b5dd1f43a86
--- /dev/null
+++ b/chromium/content/renderer/device_sensors/device_light_event_pump.h
@@ -0,0 +1,56 @@
+// Copyright 2014 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 CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_LIGHT_EVENT_PUMP_H_
+#define CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_LIGHT_EVENT_PUMP_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/device_sensors/device_light_data.h"
+#include "content/renderer/device_sensors/device_sensor_event_pump.h"
+#include "content/renderer/shared_memory_seqlock_reader.h"
+
+namespace blink {
+class WebDeviceLightListener;
+}
+
+namespace content {
+
+typedef SharedMemorySeqLockReader<DeviceLightData>
+ DeviceLightSharedMemoryReader;
+
+class CONTENT_EXPORT DeviceLightEventPump
+ : public DeviceSensorEventPump<blink::WebDeviceLightListener> {
+ public:
+ explicit DeviceLightEventPump(RenderThread* thread);
+ ~DeviceLightEventPump() override;
+
+ // Sets the listener to receive updates for device light data at
+ // regular intervals. Returns true if the registration was successful.
+ bool SetListener(blink::WebDeviceLightListener* listener);
+
+ // PlatformEventObserver implementation.
+ bool OnControlMessageReceived(const IPC::Message& message) override;
+ void SendFakeDataForTesting(void* data) override;
+
+ protected:
+ // Methods overriden from base class DeviceSensorEventPump
+ void FireEvent() override;
+ bool InitializeReader(base::SharedMemoryHandle handle) override;
+
+ // PlatformEventObserver implementation.
+ void SendStartMessage() override;
+ void SendStopMessage() override;
+
+ private:
+ bool ShouldFireEvent(double data) const;
+
+ scoped_ptr<DeviceLightSharedMemoryReader> reader_;
+ double last_seen_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceLightEventPump);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_LIGHT_EVENT_PUMP_H_
diff --git a/chromium/content/renderer/device_sensors/device_light_event_pump_unittest.cc b/chromium/content/renderer/device_sensors/device_light_event_pump_unittest.cc
new file mode 100644
index 00000000000..dadc4e3dc67
--- /dev/null
+++ b/chromium/content/renderer/device_sensors/device_light_event_pump_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright 2014 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 "device_light_event_pump.h"
+
+#include "base/message_loop/message_loop.h"
+#include "content/common/device_sensors/device_light_hardware_buffer.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebDeviceLightListener.h"
+
+namespace content {
+
+class MockDeviceLightListener : public blink::WebDeviceLightListener {
+ public:
+ MockDeviceLightListener() : did_change_device_light_(false) {}
+ virtual ~MockDeviceLightListener() {}
+
+ virtual void didChangeDeviceLight(double value) override {
+ data_.value = value;
+ did_change_device_light_ = true;
+ }
+
+ bool did_change_device_light() const { return did_change_device_light_; }
+
+ void set_did_change_device_light(bool value) {
+ did_change_device_light_ = value;
+ }
+
+ const DeviceLightData& data() const { return data_; }
+
+ private:
+ bool did_change_device_light_;
+ DeviceLightData data_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDeviceLightListener);
+};
+
+class DeviceLightEventPumpForTesting : public DeviceLightEventPump {
+ public:
+ DeviceLightEventPumpForTesting()
+ : DeviceLightEventPump(0) {}
+ ~DeviceLightEventPumpForTesting() override {}
+
+ void OnDidStart(base::SharedMemoryHandle renderer_handle) {
+ DeviceLightEventPump::OnDidStart(renderer_handle);
+ }
+ void SendStartMessage() override {}
+ void SendStopMessage() override {}
+ void FireEvent() override {
+ DeviceLightEventPump::FireEvent();
+ Stop();
+ base::MessageLoop::current()->QuitWhenIdle();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeviceLightEventPumpForTesting);
+};
+
+class DeviceLightEventPumpTest : public testing::Test {
+ public:
+ DeviceLightEventPumpTest() {
+ EXPECT_TRUE(shared_memory_.CreateAndMapAnonymous(
+ sizeof(DeviceLightHardwareBuffer)));
+ }
+
+ protected:
+ void SetUp() override {
+ const DeviceLightHardwareBuffer* null_buffer = NULL;
+ listener_.reset(new MockDeviceLightListener);
+ light_pump_.reset(new DeviceLightEventPumpForTesting);
+ buffer_ = static_cast<DeviceLightHardwareBuffer*>(shared_memory_.memory());
+ ASSERT_NE(null_buffer, buffer_);
+ ASSERT_TRUE(shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(),
+ &handle_));
+ }
+
+ void InitBuffer() {
+ DeviceLightData& data = buffer_->data;
+ data.value = 1.0;
+ }
+
+ MockDeviceLightListener* listener() { return listener_.get(); }
+ DeviceLightEventPumpForTesting* light_pump() { return light_pump_.get(); }
+ base::SharedMemoryHandle handle() { return handle_; }
+ DeviceLightHardwareBuffer* buffer() { return buffer_; }
+
+ private:
+ scoped_ptr<MockDeviceLightListener> listener_;
+ scoped_ptr<DeviceLightEventPumpForTesting> light_pump_;
+ base::SharedMemoryHandle handle_;
+ base::SharedMemory shared_memory_;
+ DeviceLightHardwareBuffer* buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceLightEventPumpTest);
+};
+
+TEST_F(DeviceLightEventPumpTest, DidStartPolling) {
+ base::MessageLoopForUI loop;
+
+ InitBuffer();
+
+ light_pump()->Start(listener());
+ light_pump()->OnDidStart(handle());
+
+ base::MessageLoop::current()->Run();
+
+ const DeviceLightData& received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_light());
+ EXPECT_EQ(1, static_cast<double>(received_data.value));
+}
+
+TEST_F(DeviceLightEventPumpTest, FireAllNullEvent) {
+ base::MessageLoopForUI loop;
+
+ light_pump()->Start(listener());
+ light_pump()->OnDidStart(handle());
+
+ base::MessageLoop::current()->Run();
+
+ const DeviceLightData& received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_light());
+ EXPECT_FALSE(received_data.value);
+}
+
+TEST_F(DeviceLightEventPumpTest, DidStartPollingValuesEqual) {
+ base::MessageLoopForUI loop;
+
+ InitBuffer();
+
+ light_pump()->Start(listener());
+ light_pump()->OnDidStart(handle());
+
+ base::MessageLoop::current()->Run();
+
+ const DeviceLightData& received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_light());
+ EXPECT_EQ(1, static_cast<double>(received_data.value));
+
+ double last_seen_data = received_data.value;
+ // Set next value to be same as previous value.
+ buffer()->data.value = 1.0;
+ listener()->set_did_change_device_light(false);
+
+ // Reset the pump's listener.
+ light_pump()->Start(listener());
+
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceLightEventPumpForTesting::FireEvent,
+ base::Unretained(light_pump())));
+ base::MessageLoop::current()->Run();
+
+ // No change in device light as present value is same as previous value.
+ EXPECT_FALSE(listener()->did_change_device_light());
+ EXPECT_EQ(last_seen_data, static_cast<double>(received_data.value));
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump.cc b/chromium/content/renderer/device_sensors/device_motion_event_pump.cc
index 0143d1942cc..aca6df5c005 100644
--- a/chromium/content/renderer/device_sensors/device_motion_event_pump.cc
+++ b/chromium/content/renderer/device_sensors/device_motion_event_pump.cc
@@ -10,23 +10,13 @@
namespace content {
-DeviceMotionEventPump::DeviceMotionEventPump()
- : DeviceSensorEventPump(), listener_(0) {
-}
-
-DeviceMotionEventPump::DeviceMotionEventPump(int pump_delay_millis)
- : DeviceSensorEventPump(pump_delay_millis), listener_(0) {
+DeviceMotionEventPump::DeviceMotionEventPump(RenderThread* thread)
+ : DeviceSensorEventPump<blink::WebDeviceMotionListener>(thread) {
}
DeviceMotionEventPump::~DeviceMotionEventPump() {
}
-bool DeviceMotionEventPump::SetListener(
- blink::WebDeviceMotionListener* listener) {
- listener_ = listener;
- return listener_ ? RequestStart() : Stop();
-}
-
bool DeviceMotionEventPump::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
@@ -38,10 +28,10 @@ bool DeviceMotionEventPump::OnControlMessageReceived(
}
void DeviceMotionEventPump::FireEvent() {
- DCHECK(listener_);
+ DCHECK(listener());
blink::WebDeviceMotionData data;
if (reader_->GetLatestData(&data) && data.allAvailableSensorsAreActive)
- listener_->didChangeDeviceMotion(data);
+ listener()->didChangeDeviceMotion(data);
}
bool DeviceMotionEventPump::InitializeReader(base::SharedMemoryHandle handle) {
@@ -50,13 +40,19 @@ bool DeviceMotionEventPump::InitializeReader(base::SharedMemoryHandle handle) {
return reader_->Initialize(handle);
}
-bool DeviceMotionEventPump::SendStartMessage() {
- return RenderThread::Get()->Send(new DeviceMotionHostMsg_StartPolling());
+void DeviceMotionEventPump::SendStartMessage() {
+ RenderThread::Get()->Send(new DeviceMotionHostMsg_StartPolling());
+}
+
+void DeviceMotionEventPump::SendStopMessage() {
+ RenderThread::Get()->Send(new DeviceMotionHostMsg_StopPolling());
}
+void DeviceMotionEventPump::SendFakeDataForTesting(void* fake_data) {
+ blink::WebDeviceMotionData data =
+ *static_cast<blink::WebDeviceMotionData*>(fake_data);
-bool DeviceMotionEventPump::SendStopMessage() {
- return RenderThread::Get()->Send(new DeviceMotionHostMsg_StopPolling());
+ listener()->didChangeDeviceMotion(data);
}
} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump.h b/chromium/content/renderer/device_sensors/device_motion_event_pump.h
index c02f814142b..af24caa6440 100644
--- a/chromium/content/renderer/device_sensors/device_motion_event_pump.h
+++ b/chromium/content/renderer/device_sensors/device_motion_event_pump.h
@@ -19,27 +19,27 @@ namespace content {
typedef SharedMemorySeqLockReader<blink::WebDeviceMotionData>
DeviceMotionSharedMemoryReader;
-class CONTENT_EXPORT DeviceMotionEventPump : public DeviceSensorEventPump {
+class CONTENT_EXPORT DeviceMotionEventPump
+ : public DeviceSensorEventPump<blink::WebDeviceMotionListener> {
public:
- DeviceMotionEventPump();
- explicit DeviceMotionEventPump(int pump_delay_millis);
- virtual ~DeviceMotionEventPump();
+ explicit DeviceMotionEventPump(RenderThread* thread);
+ ~DeviceMotionEventPump() override;
- // Sets the listener to receive updates for device motion data at
- // regular intervals. Returns true if the registration was successful.
- bool SetListener(blink::WebDeviceMotionListener* listener);
-
- // RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+ // // PlatformEventObserver.
+ bool OnControlMessageReceived(const IPC::Message& message) override;
+ void SendFakeDataForTesting(void* fake_data) override;
protected:
- virtual void FireEvent() OVERRIDE;
- virtual bool InitializeReader(base::SharedMemoryHandle handle) OVERRIDE;
- virtual bool SendStartMessage() OVERRIDE;
- virtual bool SendStopMessage() OVERRIDE;
+ void FireEvent() override;
+ bool InitializeReader(base::SharedMemoryHandle handle) override;
+
+ // PlatformEventObserver.
+ void SendStartMessage() override;
+ void SendStopMessage() override;
- blink::WebDeviceMotionListener* listener_;
scoped_ptr<DeviceMotionSharedMemoryReader> reader_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPump);
};
} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc b/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
index 17636d00b21..13b204f5947 100644
--- a/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
+++ b/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc
@@ -22,7 +22,7 @@ class MockDeviceMotionListener : public blink::WebDeviceMotionListener {
virtual ~MockDeviceMotionListener() { }
virtual void didChangeDeviceMotion(
- const blink::WebDeviceMotionData& data) OVERRIDE {
+ const blink::WebDeviceMotionData& data) override {
memcpy(&data_, &data, sizeof(data));
did_change_device_motion_ = true;
}
@@ -43,15 +43,16 @@ class MockDeviceMotionListener : public blink::WebDeviceMotionListener {
class DeviceMotionEventPumpForTesting : public DeviceMotionEventPump {
public:
- DeviceMotionEventPumpForTesting() { }
- virtual ~DeviceMotionEventPumpForTesting() { }
+ DeviceMotionEventPumpForTesting()
+ : DeviceMotionEventPump(0) { }
+ ~DeviceMotionEventPumpForTesting() override {}
void OnDidStart(base::SharedMemoryHandle renderer_handle) {
DeviceMotionEventPump::OnDidStart(renderer_handle);
}
- virtual bool SendStartMessage() OVERRIDE { return true; }
- virtual bool SendStopMessage() OVERRIDE { return true; }
- virtual void FireEvent() OVERRIDE {
+ void SendStartMessage() override {}
+ void SendStopMessage() override {}
+ void FireEvent() override {
DeviceMotionEventPump::FireEvent();
Stop();
base::MessageLoop::current()->QuitWhenIdle();
@@ -69,7 +70,7 @@ class DeviceMotionEventPumpTest : public testing::Test {
}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
const DeviceMotionHardwareBuffer* null_buffer = NULL;
listener_.reset(new MockDeviceMotionListener);
motion_pump_.reset(new DeviceMotionEventPumpForTesting);
@@ -110,7 +111,7 @@ TEST_F(DeviceMotionEventPumpTest, DidStartPolling) {
InitBuffer(true);
- motion_pump()->SetListener(listener());
+ motion_pump()->Start(listener());
motion_pump()->OnDidStart(handle());
base::MessageLoop::current()->Run();
@@ -137,7 +138,7 @@ TEST_F(DeviceMotionEventPumpTest, DidStartPollingNotAllSensorsActive) {
InitBuffer(false);
- motion_pump()->SetListener(listener());
+ motion_pump()->Start(listener());
motion_pump()->OnDidStart(handle());
base::MessageLoop::current()->Run();
diff --git a/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc b/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc
index ec159b08ead..deea13632f8 100644
--- a/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc
+++ b/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc
@@ -14,23 +14,13 @@ namespace content {
const double DeviceOrientationEventPump::kOrientationThreshold = 0.1;
-DeviceOrientationEventPump::DeviceOrientationEventPump()
- : DeviceSensorEventPump(), listener_(0) {
-}
-
-DeviceOrientationEventPump::DeviceOrientationEventPump(int pump_delay_millis)
- : DeviceSensorEventPump(pump_delay_millis), listener_(0) {
+DeviceOrientationEventPump::DeviceOrientationEventPump(RenderThread* thread)
+ : DeviceSensorEventPump<blink::WebDeviceOrientationListener>(thread) {
}
DeviceOrientationEventPump::~DeviceOrientationEventPump() {
}
-bool DeviceOrientationEventPump::SetListener(
- blink::WebDeviceOrientationListener* listener) {
- listener_ = listener;
- return listener_ ? RequestStart() : Stop();
-}
-
bool DeviceOrientationEventPump::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
@@ -42,11 +32,11 @@ bool DeviceOrientationEventPump::OnControlMessageReceived(
}
void DeviceOrientationEventPump::FireEvent() {
- DCHECK(listener_);
+ DCHECK(listener());
blink::WebDeviceOrientationData data;
if (reader_->GetLatestData(&data) && ShouldFireEvent(data)) {
memcpy(&data_, &data, sizeof(data));
- listener_->didChangeDeviceOrientation(data);
+ listener()->didChangeDeviceOrientation(data);
}
}
@@ -84,12 +74,19 @@ bool DeviceOrientationEventPump::InitializeReader(
return reader_->Initialize(handle);
}
-bool DeviceOrientationEventPump::SendStartMessage() {
- return RenderThread::Get()->Send(new DeviceOrientationHostMsg_StartPolling());
+void DeviceOrientationEventPump::SendStartMessage() {
+ RenderThread::Get()->Send(new DeviceOrientationHostMsg_StartPolling());
}
-bool DeviceOrientationEventPump::SendStopMessage() {
- return RenderThread::Get()->Send(new DeviceOrientationHostMsg_StopPolling());
+void DeviceOrientationEventPump::SendStopMessage() {
+ RenderThread::Get()->Send(new DeviceOrientationHostMsg_StopPolling());
+}
+
+void DeviceOrientationEventPump::SendFakeDataForTesting(void* fake_data) {
+ blink::WebDeviceOrientationData data =
+ *static_cast<blink::WebDeviceOrientationData*>(fake_data);
+
+ listener()->didChangeDeviceOrientation(data);
}
} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_orientation_event_pump.h b/chromium/content/renderer/device_sensors/device_orientation_event_pump.h
index b35ac3314da..d9564e17cd0 100644
--- a/chromium/content/renderer/device_sensors/device_orientation_event_pump.h
+++ b/chromium/content/renderer/device_sensors/device_orientation_event_pump.h
@@ -19,34 +19,34 @@ namespace content {
typedef SharedMemorySeqLockReader<blink::WebDeviceOrientationData>
DeviceOrientationSharedMemoryReader;
-class CONTENT_EXPORT DeviceOrientationEventPump : public DeviceSensorEventPump {
+class CONTENT_EXPORT DeviceOrientationEventPump
+ : public DeviceSensorEventPump<blink::WebDeviceOrientationListener> {
public:
// Angle threshold beyond which two orientation events are considered
// sufficiently different.
static const double kOrientationThreshold;
- DeviceOrientationEventPump();
- explicit DeviceOrientationEventPump(int pump_delay_millis);
- virtual ~DeviceOrientationEventPump();
+ explicit DeviceOrientationEventPump(RenderThread* thread);
+ ~DeviceOrientationEventPump() override;
- // Sets the listener to receive updates for device orientation data at
- // regular intervals. Returns true if the registration was successful.
- bool SetListener(blink::WebDeviceOrientationListener* listener);
-
- // RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+ // PlatformEventObserver.
+ bool OnControlMessageReceived(const IPC::Message& message) override;
+ void SendFakeDataForTesting(void* data) override;
protected:
- virtual void FireEvent() OVERRIDE;
- virtual bool InitializeReader(base::SharedMemoryHandle handle) OVERRIDE;
- virtual bool SendStartMessage() OVERRIDE;
- virtual bool SendStopMessage() OVERRIDE;
+ void FireEvent() override;
+ bool InitializeReader(base::SharedMemoryHandle handle) override;
+
+ // PlatformEventObserver.
+ void SendStartMessage() override;
+ void SendStopMessage() override;
bool ShouldFireEvent(const blink::WebDeviceOrientationData& data) const;
- blink::WebDeviceOrientationListener* listener_;
blink::WebDeviceOrientationData data_;
scoped_ptr<DeviceOrientationSharedMemoryReader> reader_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPump);
};
} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc b/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
index e0c456324c5..35792f9b10d 100644
--- a/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
+++ b/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc
@@ -22,7 +22,7 @@ class MockDeviceOrientationListener
virtual ~MockDeviceOrientationListener() { }
virtual void didChangeDeviceOrientation(
- const blink::WebDeviceOrientationData& data) OVERRIDE {
+ const blink::WebDeviceOrientationData& data) override {
memcpy(&data_, &data, sizeof(data));
did_change_device_orientation_ = true;
}
@@ -46,15 +46,16 @@ class MockDeviceOrientationListener
class DeviceOrientationEventPumpForTesting : public DeviceOrientationEventPump {
public:
- DeviceOrientationEventPumpForTesting() { }
- virtual ~DeviceOrientationEventPumpForTesting() { }
+ DeviceOrientationEventPumpForTesting()
+ : DeviceOrientationEventPump(0) { }
+ ~DeviceOrientationEventPumpForTesting() override {}
void OnDidStart(base::SharedMemoryHandle renderer_handle) {
DeviceOrientationEventPump::OnDidStart(renderer_handle);
}
- virtual bool SendStartMessage() OVERRIDE { return true; }
- virtual bool SendStopMessage() OVERRIDE { return true; }
- virtual void FireEvent() OVERRIDE {
+ void SendStartMessage() override {}
+ void SendStopMessage() override {}
+ void FireEvent() override {
DeviceOrientationEventPump::FireEvent();
Stop();
base::MessageLoop::current()->QuitWhenIdle();
@@ -72,13 +73,16 @@ class DeviceOrientationEventPumpTest : public testing::Test {
}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
+ const DeviceOrientationHardwareBuffer* null_buffer = NULL;
listener_.reset(new MockDeviceOrientationListener);
orientation_pump_.reset(new DeviceOrientationEventPumpForTesting);
buffer_ = static_cast<DeviceOrientationHardwareBuffer*>(
shared_memory_.memory());
+ ASSERT_NE(null_buffer, buffer_);
memset(buffer_, 0, sizeof(DeviceOrientationHardwareBuffer));
- shared_memory_.ShareToProcess(base::kNullProcessHandle, &handle_);
+ ASSERT_TRUE(shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(),
+ &handle_));
}
void InitBuffer() {
@@ -114,17 +118,11 @@ class DeviceOrientationEventPumpTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPumpTest);
};
-// Always failing in the win try bot. See http://crbug.com/256782.
-#if defined(OS_WIN)
-#define MAYBE_DidStartPolling DISABLED_DidStartPolling
-#else
-#define MAYBE_DidStartPolling DidStartPolling
-#endif
-TEST_F(DeviceOrientationEventPumpTest, MAYBE_DidStartPolling) {
+TEST_F(DeviceOrientationEventPumpTest, DidStartPolling) {
base::MessageLoop loop;
InitBuffer();
- orientation_pump()->SetListener(listener());
+ orientation_pump()->Start(listener());
orientation_pump()->OnDidStart(handle());
base::MessageLoop::current()->Run();
@@ -140,17 +138,11 @@ TEST_F(DeviceOrientationEventPumpTest, MAYBE_DidStartPolling) {
EXPECT_TRUE(received_data.hasGamma);
}
-// Always failing in the win try bot. See http://crbug.com/256782.
-#if defined(OS_WIN)
-#define MAYBE_FireAllNullEvent DISABLED_FireAllNullEvent
-#else
-#define MAYBE_FireAllNullEvent FireAllNullEvent
-#endif
-TEST_F(DeviceOrientationEventPumpTest, MAYBE_FireAllNullEvent) {
+TEST_F(DeviceOrientationEventPumpTest, FireAllNullEvent) {
base::MessageLoop loop;
InitBufferNoData();
- orientation_pump()->SetListener(listener());
+ orientation_pump()->Start(listener());
orientation_pump()->OnDidStart(handle());
base::MessageLoop::current()->Run();
@@ -163,20 +155,11 @@ TEST_F(DeviceOrientationEventPumpTest, MAYBE_FireAllNullEvent) {
EXPECT_FALSE(received_data.hasGamma);
}
-// Always failing in the win try bot. See http://crbug.com/256782.
-#if defined(OS_WIN)
-#define MAYBE_UpdateRespectsOrientationThreshold \
- DISABLED_UpdateRespectsOrientationThreshold
-#else
-#define MAYBE_UpdateRespectsOrientationThreshold \
- UpdateRespectsOrientationThreshold
-#endif
-TEST_F(DeviceOrientationEventPumpTest,
- MAYBE_UpdateRespectsOrientationThreshold) {
+TEST_F(DeviceOrientationEventPumpTest, UpdateRespectsOrientationThreshold) {
base::MessageLoop loop;
InitBuffer();
- orientation_pump()->SetListener(listener());
+ orientation_pump()->Start(listener());
orientation_pump()->OnDidStart(handle());
base::MessageLoop::current()->Run();
@@ -195,6 +178,9 @@ TEST_F(DeviceOrientationEventPumpTest,
1 + DeviceOrientationEventPump::kOrientationThreshold / 2.0;
listener()->set_did_change_device_orientation(false);
+ // Reset the pump's listener.
+ orientation_pump()->Start(listener());
+
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&DeviceOrientationEventPumpForTesting::FireEvent,
base::Unretained(orientation_pump())));
@@ -213,6 +199,9 @@ TEST_F(DeviceOrientationEventPumpTest,
1 + DeviceOrientationEventPump::kOrientationThreshold;
listener()->set_did_change_device_orientation(false);
+ // Reset the pump's listener.
+ orientation_pump()->Start(listener());
+
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&DeviceOrientationEventPumpForTesting::FireEvent,
base::Unretained(orientation_pump())));
diff --git a/chromium/content/renderer/device_sensors/device_sensor_event_pump.cc b/chromium/content/renderer/device_sensors/device_sensor_event_pump.cc
deleted file mode 100644
index eed3af27c03..00000000000
--- a/chromium/content/renderer/device_sensors/device_sensor_event_pump.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 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 "device_sensor_event_pump.h"
-
-#include "base/logging.h"
-#include "content/public/renderer/render_thread.h"
-
-namespace content {
-
-// Default interval between successive polls, should take into account the
-// value of |kInertialSensorIntervalMillis| in
-// content/browser/device_sensors/inertial_sensor_consts.h.
-const int DeviceSensorEventPump::kDefaultPumpDelayMillis = 50;
-
-int DeviceSensorEventPump::GetDelayMillis() const {
- return pump_delay_millis_;
-}
-
-DeviceSensorEventPump::DeviceSensorEventPump()
- : pump_delay_millis_(kDefaultPumpDelayMillis),
- state_(STOPPED) {
-}
-
-DeviceSensorEventPump::DeviceSensorEventPump(int pump_delay_millis)
- : pump_delay_millis_(pump_delay_millis),
- state_(STOPPED) {
- DCHECK_GE(pump_delay_millis_, 0);
-}
-
-DeviceSensorEventPump::~DeviceSensorEventPump() {
-}
-
-bool DeviceSensorEventPump::RequestStart() {
- DVLOG(2) << "requested start";
-
- if (state_ != STOPPED)
- return false;
-
- DCHECK(!timer_.IsRunning());
-
- if (SendStartMessage()) {
- state_ = PENDING_START;
- return true;
- }
- return false;
-}
-
-bool DeviceSensorEventPump::Stop() {
- DVLOG(2) << "stop";
-
- if (state_ == STOPPED)
- return true;
-
- DCHECK((state_ == PENDING_START && !timer_.IsRunning()) ||
- (state_ == RUNNING && timer_.IsRunning()));
-
- if (timer_.IsRunning())
- timer_.Stop();
- SendStopMessage();
- state_ = STOPPED;
- return true;
-}
-
-void DeviceSensorEventPump::Attach(RenderThread* thread) {
- if (!thread)
- return;
- thread->AddObserver(this);
-}
-
-void DeviceSensorEventPump::OnDidStart(base::SharedMemoryHandle handle) {
- DVLOG(2) << "did start sensor event pump";
-
- if (state_ != PENDING_START)
- return;
-
- DCHECK(!timer_.IsRunning());
-
- if (InitializeReader(handle)) {
- timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(GetDelayMillis()),
- this, &DeviceSensorEventPump::FireEvent);
- state_ = RUNNING;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/device_sensors/device_sensor_event_pump.h b/chromium/content/renderer/device_sensors/device_sensor_event_pump.h
index 0c66e54035d..43e0f64dca4 100644
--- a/chromium/content/renderer/device_sensors/device_sensor_event_pump.h
+++ b/chromium/content/renderer/device_sensors/device_sensor_event_pump.h
@@ -6,29 +6,58 @@
#define CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_SENSOR_EVENT_PUMP_H_
#include "base/memory/shared_memory.h"
+#include "base/time/time.h"
#include "base/timer/timer.h"
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/platform_event_observer.h"
namespace content {
-class RenderThread;
-class CONTENT_EXPORT DeviceSensorEventPump : public RenderProcessObserver {
+template <typename ListenerType>
+class CONTENT_EXPORT DeviceSensorEventPump
+ : NON_EXPORTED_BASE(public PlatformEventObserver<ListenerType>) {
public:
- // Default delay between subsequent firing of events.
- static const int kDefaultPumpDelayMillis;
+ // Default rate for firing events.
+ static const int kDefaultPumpFrequencyHz = 60;
+ static const int kDefaultPumpDelayMicroseconds =
+ base::Time::kMicrosecondsPerSecond / kDefaultPumpFrequencyHz;
- int GetDelayMillis() const;
+ // PlatformEventObserver
+ virtual void Start(blink::WebPlatformEventListener* listener) override {
+ DVLOG(2) << "requested start";
- void Attach(RenderThread* thread);
- virtual bool OnControlMessageReceived(const IPC::Message& message) = 0;
+ if (state_ != STOPPED)
+ return;
+
+ DCHECK(!timer_.IsRunning());
+
+ PlatformEventObserver<ListenerType>::Start(listener);
+ state_ = PENDING_START;
+ }
+
+ virtual void Stop() override {
+ DVLOG(2) << "stop";
+
+ if (state_ == STOPPED)
+ return;
+
+ DCHECK((state_ == PENDING_START && !timer_.IsRunning()) ||
+ (state_ == RUNNING && timer_.IsRunning()));
+
+ if (timer_.IsRunning())
+ timer_.Stop();
+ PlatformEventObserver<ListenerType>::Stop();
+ state_ = STOPPED;
+ }
protected:
- // Constructor for a pump with default delay.
- DeviceSensorEventPump();
+ explicit DeviceSensorEventPump(RenderThread* thread)
+ : PlatformEventObserver<ListenerType>(thread),
+ pump_delay_microseconds_(kDefaultPumpDelayMicroseconds),
+ state_(STOPPED) {}
- // Constructor for a pump with a given delay.
- explicit DeviceSensorEventPump(int pump_delay_millis);
- virtual ~DeviceSensorEventPump();
+ virtual ~DeviceSensorEventPump() {
+ PlatformEventObserver<ListenerType>::StopIfObserving();
+ }
// The pump is a tri-state automaton with allowed transitions as follows:
// STOPPED -> PENDING_START
@@ -41,18 +70,31 @@ class CONTENT_EXPORT DeviceSensorEventPump : public RenderProcessObserver {
PENDING_START
};
- bool RequestStart();
- void OnDidStart(base::SharedMemoryHandle handle);
- bool Stop();
+ void OnDidStart(base::SharedMemoryHandle handle) {
+ DVLOG(2) << "did start sensor event pump";
+
+ if (state_ != PENDING_START)
+ return;
+
+ DCHECK(!timer_.IsRunning());
+
+ if (InitializeReader(handle)) {
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMicroseconds(pump_delay_microseconds_),
+ this,
+ &DeviceSensorEventPump::FireEvent);
+ state_ = RUNNING;
+ }
+ }
virtual void FireEvent() = 0;
virtual bool InitializeReader(base::SharedMemoryHandle handle) = 0;
- virtual bool SendStartMessage() = 0;
- virtual bool SendStopMessage() = 0;
- int pump_delay_millis_;
+ int pump_delay_microseconds_;
PumpState state_;
base::RepeatingTimer<DeviceSensorEventPump> timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceSensorEventPump);
};
} // namespace content
diff --git a/chromium/content/renderer/devtools/devtools_agent.cc b/chromium/content/renderer/devtools/devtools_agent.cc
index 5ba456b8b14..f03bbb35857 100644
--- a/chromium/content/renderer/devtools/devtools_agent.cc
+++ b/chromium/content/renderer/devtools/devtools_agent.cc
@@ -9,7 +9,7 @@
#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
#include "content/common/devtools_messages.h"
#include "content/common/frame_messages.h"
@@ -44,6 +44,7 @@ using blink::WebVector;
using blink::WebView;
using base::debug::TraceLog;
+using base::debug::TraceOptions;
namespace content {
@@ -51,6 +52,8 @@ base::subtle::AtomicWord DevToolsAgent::event_callback_;
namespace {
+const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
+
class WebKitClientMessageLoopImpl
: public WebDevToolsAgentClient::WebKitClientMessageLoop {
public:
@@ -82,8 +85,6 @@ DevToolsAgent::DevToolsAgent(RenderViewImpl* render_view)
g_agent_for_routing_id.Get()[routing_id()] = this;
render_view->webview()->setDevToolsAgentClient(this);
- render_view->webview()->devToolsAgent()->setProcessId(
- base::Process::Current().pid());
}
DevToolsAgent::~DevToolsAgent() {
@@ -117,8 +118,23 @@ bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) {
void DevToolsAgent::sendMessageToInspectorFrontend(
const blink::WebString& message) {
- Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(routing_id(),
- message.utf8()));
+ std::string msg(message.utf8());
+ if (msg.length() < kMaxMessageChunkSize) {
+ Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
+ routing_id(), msg, msg.size()));
+ return;
+ }
+
+ for (size_t pos = 0; pos < msg.length(); pos += kMaxMessageChunkSize) {
+ Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
+ routing_id(),
+ msg.substr(pos, kMaxMessageChunkSize),
+ pos ? 0 : msg.size()));
+ }
+}
+
+long DevToolsAgent::processId() {
+ return base::GetCurrentProcId();
}
int DevToolsAgent::debuggerId() {
@@ -171,7 +187,7 @@ void DevToolsAgent::enableTracing(const WebString& category_filter) {
TraceLog* trace_log = TraceLog::GetInstance();
trace_log->SetEnabled(base::debug::CategoryFilter(category_filter.utf8()),
TraceLog::RECORDING_MODE,
- TraceLog::RECORD_UNTIL_FULL);
+ TraceOptions());
}
void DevToolsAgent::disableTracing() {
@@ -251,27 +267,6 @@ void DevToolsAgent::disableDeviceEmulation() {
impl->DisableScreenMetricsEmulation();
}
-void DevToolsAgent::setTouchEventEmulationEnabled(
- bool enabled, bool allow_pinch) {
- RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view());
- impl->Send(new ViewHostMsg_SetTouchEventEmulationEnabled(
- impl->routing_id(), enabled, allow_pinch));
-}
-
-#if defined(USE_TCMALLOC) && !defined(OS_WIN)
-static void AllocationVisitor(void* data, const void* ptr) {
- typedef blink::WebDevToolsAgentClient::AllocatedObjectVisitor Visitor;
- Visitor* visitor = reinterpret_cast<Visitor*>(data);
- visitor->visitObject(ptr);
-}
-#endif
-
-void DevToolsAgent::visitAllocatedObjects(AllocatedObjectVisitor* visitor) {
-#if defined(USE_TCMALLOC) && !defined(OS_WIN)
- IterateAllocatedObjects(&AllocationVisitor, visitor);
-#endif
-}
-
// static
DevToolsAgent* DevToolsAgent::FromRoutingId(int routing_id) {
IdToAgentMap::iterator it = g_agent_for_routing_id.Get().find(routing_id);
@@ -355,10 +350,8 @@ void DevToolsAgent::OnAddMessageToConsole(ConsoleMessageLevel level,
void DevToolsAgent::ContinueProgram() {
WebDevToolsAgent* web_agent = GetWebAgent();
- // TODO(pfeldman): rename didNavigate to continueProgram upstream.
- // That is in fact the purpose of the signal.
if (web_agent)
- web_agent->didNavigate();
+ web_agent->continueProgram();
}
void DevToolsAgent::OnSetupDevToolsClient() {
diff --git a/chromium/content/renderer/devtools/devtools_agent.h b/chromium/content/renderer/devtools/devtools_agent.h
index 67c08d803da..dcb70c5f692 100644
--- a/chromium/content/renderer/devtools/devtools_agent.h
+++ b/chromium/content/renderer/devtools/devtools_agent.h
@@ -34,7 +34,7 @@ class DevToolsAgent : public RenderViewObserver,
public blink::WebDevToolsAgentClient {
public:
explicit DevToolsAgent(RenderViewImpl* render_view);
- virtual ~DevToolsAgent();
+ ~DevToolsAgent() override;
// Returns agent instance for its routing id.
static DevToolsAgent* FromRoutingId(int routing_id);
@@ -45,37 +45,35 @@ class DevToolsAgent : public RenderViewObserver,
private:
// RenderView::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// WebDevToolsAgentClient implementation
virtual void sendMessageToInspectorFrontend(const blink::WebString& data);
- virtual int debuggerId() OVERRIDE;
- virtual void saveAgentRuntimeState(const blink::WebString& state) OVERRIDE;
+ virtual long processId() override;
+ virtual int debuggerId() override;
+ virtual void saveAgentRuntimeState(const blink::WebString& state) override;
virtual blink::WebDevToolsAgentClient::WebKitClientMessageLoop*
- createClientMessageLoop() OVERRIDE;
- virtual void willEnterDebugLoop() OVERRIDE;
- virtual void didExitDebugLoop() OVERRIDE;
- virtual void visitAllocatedObjects(AllocatedObjectVisitor* visitor) OVERRIDE;
+ createClientMessageLoop() override;
+ virtual void willEnterDebugLoop() override;
+ virtual void didExitDebugLoop() override;
typedef void (*TraceEventCallback)(
char phase, const unsigned char*, const char* name, unsigned long long id,
int numArgs, const char* const* argNames, const unsigned char* argTypes,
const unsigned long long* argValues,
unsigned char flags, double timestamp);
- virtual void resetTraceEventCallback() OVERRIDE;
+ virtual void resetTraceEventCallback() override;
virtual void setTraceEventCallback(const blink::WebString& category_filter,
- TraceEventCallback cb) OVERRIDE;
- virtual void enableTracing(const blink::WebString& category_filter) OVERRIDE;
- virtual void disableTracing() OVERRIDE;
- virtual void startGPUEventsRecording() OVERRIDE;
- virtual void stopGPUEventsRecording() OVERRIDE;
+ TraceEventCallback cb) override;
+ virtual void enableTracing(const blink::WebString& category_filter) override;
+ virtual void disableTracing() override;
+ virtual void startGPUEventsRecording() override;
+ virtual void stopGPUEventsRecording() override;
virtual void enableDeviceEmulation(
- const blink::WebDeviceEmulationParams& params) OVERRIDE;
- virtual void disableDeviceEmulation() OVERRIDE;
- virtual void setTouchEventEmulationEnabled(bool enabled,
- bool allow_pinch) OVERRIDE;
+ const blink::WebDeviceEmulationParams& params) override;
+ virtual void disableDeviceEmulation() override;
void OnAttach(const std::string& host_id);
void OnReattach(const std::string& host_id,
diff --git a/chromium/content/renderer/devtools/devtools_agent_filter.h b/chromium/content/renderer/devtools/devtools_agent_filter.h
index 5097f423585..48831a30c6d 100644
--- a/chromium/content/renderer/devtools/devtools_agent_filter.h
+++ b/chromium/content/renderer/devtools/devtools_agent_filter.h
@@ -33,14 +33,14 @@ class DevToolsAgentFilter : public IPC::MessageFilter {
static void SendRpcMessage(const DevToolsMessageData& data);
// IPC::MessageFilter override. Called on IO thread.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Called on the main thread.
void AddEmbeddedWorkerRouteOnMainThread(int32 routing_id);
void RemoveEmbeddedWorkerRouteOnMainThread(int32 routing_id);
protected:
- virtual ~DevToolsAgentFilter();
+ ~DevToolsAgentFilter() override;
private:
void OnDispatchOnInspectorBackend(const std::string& message);
diff --git a/chromium/content/renderer/devtools/devtools_client.cc b/chromium/content/renderer/devtools/devtools_client.cc
index 5799fa4b0ed..0d4f7dc520b 100644
--- a/chromium/content/renderer/devtools/devtools_client.cc
+++ b/chromium/content/renderer/devtools/devtools_client.cc
@@ -36,19 +36,6 @@ DevToolsClient::DevToolsClient(RenderViewImpl* render_view)
DevToolsClient::~DevToolsClient() {
}
-bool DevToolsClient::OnMessageReceived(const IPC::Message& message) {
- DCHECK(RenderThreadImpl::current());
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(DevToolsClient, message)
- IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
- OnDispatchOnInspectorFrontend)
- IPC_MESSAGE_UNHANDLED(handled = false);
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
void DevToolsClient::sendMessageToBackend(const WebString& message) {
Send(new DevToolsAgentMsg_DispatchOnInspectorBackend(routing_id(),
message.utf8()));
@@ -63,9 +50,4 @@ bool DevToolsClient::isUnderTest() {
return RenderThreadImpl::current()->layout_test_mode();
}
-void DevToolsClient::OnDispatchOnInspectorFrontend(const std::string& message) {
- web_tools_frontend_->dispatchOnInspectorFrontend(
- WebString::fromUTF8(message));
-}
-
} // namespace content
diff --git a/chromium/content/renderer/devtools/devtools_client.h b/chromium/content/renderer/devtools/devtools_client.h
index be1e902cdff..bf6e077f255 100644
--- a/chromium/content/renderer/devtools/devtools_client.h
+++ b/chromium/content/renderer/devtools/devtools_client.h
@@ -35,16 +35,14 @@ class CONTENT_EXPORT DevToolsClient
virtual ~DevToolsClient();
private:
- // RenderView::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
// WebDevToolsFrontendClient implementation.
- virtual void sendMessageToBackend(const blink::WebString&) OVERRIDE;
- virtual void sendMessageToEmbedder(const blink::WebString&) OVERRIDE;
+ virtual void sendMessageToBackend(const blink::WebString&) override;
+ virtual void sendMessageToEmbedder(const blink::WebString&) override;
- virtual bool isUnderTest() OVERRIDE;
+ virtual bool isUnderTest() override;
- void OnDispatchOnInspectorFrontend(const std::string& message);
+ void OnDispatchOnInspectorFrontend(const std::string& message,
+ uint32 total_size);
scoped_ptr<blink::WebDevToolsFrontend> web_tools_frontend_;
diff --git a/chromium/content/renderer/dom_automation_controller.h b/chromium/content/renderer/dom_automation_controller.h
index 92dc54e5f6f..29b1db37299 100644
--- a/chromium/content/renderer/dom_automation_controller.h
+++ b/chromium/content/renderer/dom_automation_controller.h
@@ -107,14 +107,14 @@ class DomAutomationController : public gin::Wrappable<DomAutomationController>,
private:
explicit DomAutomationController(RenderFrame* render_view);
- virtual ~DomAutomationController();
+ ~DomAutomationController() override;
// gin::WrappableBase
- virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) OVERRIDE;
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
// RenderViewObserver
- virtual void OnDestruct() OVERRIDE;
+ void OnDestruct() override;
int automation_id_; // routing id to be used by the next channel.
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index 5f5ebfed5da..1bcd2bd0ddb 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -6,8 +6,8 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/common/content_switches.h"
@@ -77,7 +77,7 @@ WebFrame* FindSubFrameByURL(WebView* web_view, const GURL& url) {
for (WebElement element = all.firstItem();
!element.isNull(); element = all.nextItem()) {
// Check frame tag and iframe tag
- if (!element.hasTagName("frame") && !element.hasTagName("iframe"))
+ if (!element.hasHTMLTagName("frame") && !element.hasHTMLTagName("iframe"))
continue;
WebFrame* sub_frame = WebLocalFrame::fromFrameOwnerElement(element);
if (sub_frame)
@@ -103,7 +103,7 @@ bool IsMetaElement(const WebNode& node, std::string& charset_info) {
if (!node.isElementNode())
return false;
const WebElement meta = node.toConst<WebElement>();
- if (!meta.hasTagName("meta"))
+ if (!meta.hasHTMLTagName("meta"))
return false;
charset_info.erase(0, charset_info.length());
// Check the META charset declaration.
@@ -154,7 +154,7 @@ class LoadObserver : public RenderViewObserver {
: RenderViewObserver(render_view),
quit_closure_(quit_closure) {}
- virtual void DidFinishLoad(blink::WebLocalFrame* frame) OVERRIDE {
+ void DidFinishLoad(blink::WebLocalFrame* frame) override {
if (frame == render_view()->GetWebView()->mainFrame())
quit_closure_.Run();
}
@@ -170,7 +170,7 @@ class DomSerializerTests : public ContentBrowserTest,
: serialized_(false),
local_directory_name_(FILE_PATH_LITERAL("./dummy_files/")) {}
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kSingleProcess);
#if defined(OS_WIN)
// Don't want to try to create a GPU process.
@@ -615,12 +615,12 @@ class DomSerializerTests : public ContentBrowserTest,
int original_base_tag_count = 0;
for (WebElement element = all.firstItem(); !element.isNull();
element = all.nextItem()) {
- if (element.hasTagName("base")) {
+ if (element.hasHTMLTagName("base")) {
original_base_tag_count++;
} else {
// Get link.
WebString value = GetSubResourceLinkFromElement(element);
- if (value.isNull() && element.hasTagName("a")) {
+ if (value.isNull() && element.hasHTMLTagName("a")) {
value = element.getAttribute("href");
if (value.isEmpty())
value = WebString();
@@ -663,12 +663,12 @@ class DomSerializerTests : public ContentBrowserTest,
if (!node.isElementNode())
continue;
WebElement element = node.to<WebElement>();
- if (element.hasTagName("base")) {
+ if (element.hasHTMLTagName("base")) {
new_base_tag_count++;
} else {
// Get link.
WebString value = GetSubResourceLinkFromElement(element);
- if (value.isNull() && element.hasTagName("a")) {
+ if (value.isNull() && element.hasHTMLTagName("a")) {
value = element.getAttribute("href");
if (value.isEmpty())
value = WebString();
diff --git a/chromium/content/renderer/dom_storage/DEPS b/chromium/content/renderer/dom_storage/DEPS
deleted file mode 100644
index aabd9ff57e6..00000000000
--- a/chromium/content/renderer/dom_storage/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+webkit/dom_storage",
-]
diff --git a/chromium/content/renderer/dom_storage/OWNERS b/chromium/content/renderer/dom_storage/OWNERS
index e1e6b1b4614..1f62afafeb8 100644
--- a/chromium/content/renderer/dom_storage/OWNERS
+++ b/chromium/content/renderer/dom_storage/OWNERS
@@ -1,7 +1,6 @@
michaeln@chromium.org
kinuko@chromium.org
jsbell@chromium.org
-ericu@chromium.org
marja@chromium.org
# Please include michaeln@ or marja@ if you make any functional/runtime changes.
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
index eeec43ee91e..f17f5fed01e 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc
@@ -23,10 +23,10 @@ class MockProxy : public DOMStorageProxy {
// DOMStorageProxy interface for use by DOMStorageCachedArea.
- virtual void LoadArea(int connection_id,
- DOMStorageValuesMap* values,
- bool* send_log_get_messages,
- const CompletionCallback& callback) OVERRIDE {
+ void LoadArea(int connection_id,
+ DOMStorageValuesMap* values,
+ bool* send_log_get_messages,
+ const CompletionCallback& callback) override {
pending_callbacks_.push_back(callback);
observed_load_area_ = true;
observed_connection_id_ = connection_id;
@@ -34,11 +34,11 @@ class MockProxy : public DOMStorageProxy {
*send_log_get_messages = false;
}
- virtual void SetItem(int connection_id,
- const base::string16& key,
- const base::string16& value,
- const GURL& page_url,
- const CompletionCallback& callback) OVERRIDE {
+ void SetItem(int connection_id,
+ const base::string16& key,
+ const base::string16& value,
+ const GURL& page_url,
+ const CompletionCallback& callback) override {
pending_callbacks_.push_back(callback);
observed_set_item_ = true;
observed_connection_id_ = connection_id;
@@ -47,15 +47,14 @@ class MockProxy : public DOMStorageProxy {
observed_page_url_ = page_url;
}
- virtual void LogGetItem(int connection_id,
- const base::string16& key,
- const base::NullableString16& value) OVERRIDE {
- }
+ void LogGetItem(int connection_id,
+ const base::string16& key,
+ const base::NullableString16& value) override {}
- virtual void RemoveItem(int connection_id,
- const base::string16& key,
- const GURL& page_url,
- const CompletionCallback& callback) OVERRIDE {
+ void RemoveItem(int connection_id,
+ const base::string16& key,
+ const GURL& page_url,
+ const CompletionCallback& callback) override {
pending_callbacks_.push_back(callback);
observed_remove_item_ = true;
observed_connection_id_ = connection_id;
@@ -63,9 +62,9 @@ class MockProxy : public DOMStorageProxy {
observed_page_url_ = page_url;
}
- virtual void ClearArea(int connection_id,
- const GURL& page_url,
- const CompletionCallback& callback) OVERRIDE {
+ void ClearArea(int connection_id,
+ const GURL& page_url,
+ const CompletionCallback& callback) override {
pending_callbacks_.push_back(callback);
observed_clear_area_ = true;
observed_connection_id_ = connection_id;
@@ -110,7 +109,7 @@ class MockProxy : public DOMStorageProxy {
GURL observed_page_url_;
private:
- virtual ~MockProxy() {}
+ ~MockProxy() override {}
};
} // namespace
@@ -131,9 +130,7 @@ class DOMStorageCachedAreaTest : public testing::Test {
const base::string16 kValue;
const GURL kPageUrl;
- virtual void SetUp() {
- mock_proxy_ = new MockProxy();
- }
+ void SetUp() override { mock_proxy_ = new MockProxy(); }
bool IsPrimed(DOMStorageCachedArea* cached_area) {
return cached_area->map_.get();
diff --git a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
index 6764a9bc017..94332709d40 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
@@ -39,9 +39,9 @@ class MessageThrottlingFilter : public IPC::MessageFilter {
void Shutdown() { sender_ = NULL; }
private:
- virtual ~MessageThrottlingFilter() {}
+ ~MessageThrottlingFilter() override {}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
int GetPendingCount() { return IncrementPendingCountN(0); }
int IncrementPendingCount() { return IncrementPendingCountN(1); }
@@ -109,20 +109,25 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
void Shutdown();
// DOMStorageProxy interface for use by DOMStorageCachedArea.
- virtual void LoadArea(int connection_id, DOMStorageValuesMap* values,
- bool* send_log_get_messages,
- const CompletionCallback& callback) OVERRIDE;
- virtual void SetItem(int connection_id, const base::string16& key,
- const base::string16& value, const GURL& page_url,
- const CompletionCallback& callback) OVERRIDE;
- virtual void LogGetItem(int connection_id, const base::string16& key,
- const base::NullableString16& value) OVERRIDE;
- virtual void RemoveItem(int connection_id, const base::string16& key,
- const GURL& page_url,
- const CompletionCallback& callback) OVERRIDE;
- virtual void ClearArea(int connection_id,
- const GURL& page_url,
- const CompletionCallback& callback) OVERRIDE;
+ void LoadArea(int connection_id,
+ DOMStorageValuesMap* values,
+ bool* send_log_get_messages,
+ const CompletionCallback& callback) override;
+ void SetItem(int connection_id,
+ const base::string16& key,
+ const base::string16& value,
+ const GURL& page_url,
+ const CompletionCallback& callback) override;
+ void LogGetItem(int connection_id,
+ const base::string16& key,
+ const base::NullableString16& value) override;
+ void RemoveItem(int connection_id,
+ const base::string16& key,
+ const GURL& page_url,
+ const CompletionCallback& callback) override;
+ void ClearArea(int connection_id,
+ const GURL& page_url,
+ const CompletionCallback& callback) override;
private:
// Struct to hold references to our contained areas and
@@ -139,8 +144,7 @@ class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
typedef std::map<std::string, CachedAreaHolder> CachedAreaMap;
typedef std::list<CompletionCallback> CallbackList;
- virtual ~ProxyImpl() {
- }
+ ~ProxyImpl() override {}
// Sudden termination is disabled when there are callbacks pending
// to more reliably commit changes during shutdown.
diff --git a/chromium/content/renderer/dom_utils.cc b/chromium/content/renderer/dom_utils.cc
new file mode 100644
index 00000000000..ecf77b82881
--- /dev/null
+++ b/chromium/content/renderer/dom_utils.cc
@@ -0,0 +1,22 @@
+// Copyright 2014 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 "content/renderer/dom_utils.h"
+
+#include "third_party/WebKit/public/web/WebNode.h"
+
+namespace content {
+
+blink::WebNode DomUtils::ExtractParentAnchorNode(
+ const blink::WebNode& node) {
+ blink::WebNode selected_node = node;
+
+ // If there are other embedded tags (like <a ..>Some <b>text</b></a>)
+ // we need to extract the parent <a/> node.
+ while (!selected_node.isNull() && !selected_node.isLink())
+ selected_node = selected_node.parentNode();
+ return selected_node;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/dom_utils.h b/chromium/content/renderer/dom_utils.h
new file mode 100644
index 00000000000..0b047c383c2
--- /dev/null
+++ b/chromium/content/renderer/dom_utils.h
@@ -0,0 +1,23 @@
+// Copyright 2014 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 CONTENT_RENDERER_DOM_UTILS_H_
+#define CONTENT_RENDERER_DOM_UTILS_H_
+
+namespace blink {
+class WebNode;
+}
+
+namespace content {
+
+class DomUtils {
+ public:
+ // Walks up the DOM, looking for the first parent that represents an <a>.
+ // Returns a null WebNode if no such <a> exists.
+ static blink::WebNode ExtractParentAnchorNode(const blink::WebNode& node);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DOM_UTILS_H_
diff --git a/chromium/content/renderer/external_popup_menu.cc b/chromium/content/renderer/external_popup_menu.cc
index a1bb2475b73..3a635e528d3 100644
--- a/chromium/content/renderer/external_popup_menu.cc
+++ b/chromium/content/renderer/external_popup_menu.cc
@@ -4,19 +4,19 @@
#include "content/renderer/external_popup_menu.h"
-#include "content/common/view_messages.h"
+#include "content/common/frame_messages.h"
#include "content/renderer/menu_item_builder.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/web/WebExternalPopupMenuClient.h"
namespace content {
ExternalPopupMenu::ExternalPopupMenu(
- RenderViewImpl* render_view,
+ RenderFrameImpl* render_frame,
const blink::WebPopupMenuInfo& popup_menu_info,
blink::WebExternalPopupMenuClient* popup_menu_client)
- : render_view_(render_view),
+ : render_frame_(render_frame),
popup_menu_info_(popup_menu_info),
popup_menu_client_(popup_menu_client),
origin_scale_for_emulation_(0) {
@@ -37,7 +37,7 @@ void ExternalPopupMenu::show(const blink::WebRect& bounds) {
rect.x += origin_offset_for_emulation_.x();
rect.y += origin_offset_for_emulation_.y();
- ViewHostMsg_ShowPopup_Params popup_params;
+ FrameHostMsg_ShowPopup_Params popup_params;
popup_params.bounds = rect;
popup_params.item_height = popup_menu_info_.itemHeight;
popup_params.item_font_size = popup_menu_info_.itemFontSize;
@@ -49,13 +49,14 @@ void ExternalPopupMenu::show(const blink::WebRect& bounds) {
popup_params.right_aligned = popup_menu_info_.rightAligned;
popup_params.allow_multiple_selection =
popup_menu_info_.allowMultipleSelection;
- render_view_->Send(
- new ViewHostMsg_ShowPopup(render_view_->routing_id(), popup_params));
+ render_frame_->Send(
+ new FrameHostMsg_ShowPopup(render_frame_->GetRoutingID(), popup_params));
}
void ExternalPopupMenu::close() {
- render_view_->Send(new ViewHostMsg_HidePopup(render_view_->routing_id()));
- render_view_->DidHideExternalPopupMenu();
+ render_frame_->Send(
+ new FrameHostMsg_HidePopup(render_frame_->GetRoutingID()));
+ render_frame_->DidHideExternalPopupMenu();
// |this| was deleted.
}
diff --git a/chromium/content/renderer/external_popup_menu.h b/chromium/content/renderer/external_popup_menu.h
index 32137008416..06e3715d185 100644
--- a/chromium/content/renderer/external_popup_menu.h
+++ b/chromium/content/renderer/external_popup_menu.h
@@ -17,11 +17,11 @@ class WebExternalPopupMenuClient;
}
namespace content {
-class RenderViewImpl;
+class RenderFrameImpl;
class ExternalPopupMenu : public blink::WebExternalPopupMenu {
public:
- ExternalPopupMenu(RenderViewImpl* render_view,
+ ExternalPopupMenu(RenderFrameImpl* render_frame,
const blink::WebPopupMenuInfo& popup_menu_info,
blink::WebExternalPopupMenuClient* popup_menu_client);
@@ -46,7 +46,7 @@ class ExternalPopupMenu : public blink::WebExternalPopupMenu {
virtual void close();
private:
- RenderViewImpl* render_view_;
+ RenderFrameImpl* render_frame_;
blink::WebPopupMenuInfo popup_menu_info_;
blink::WebExternalPopupMenuClient* popup_menu_client_;
diff --git a/chromium/content/renderer/external_popup_menu_browsertest.cc b/chromium/content/renderer/external_popup_menu_browsertest.cc
index a0a6a90c8f3..cadb51ffda6 100644
--- a/chromium/content/renderer/external_popup_menu_browsertest.cc
+++ b/chromium/content/renderer/external_popup_menu_browsertest.cc
@@ -3,8 +3,9 @@
// found in the LICENSE file.
#include "base/strings/utf_string_conversions.h"
-#include "content/common/view_messages.h"
+#include "content/common/frame_messages.h"
#include "content/public/test/render_view_test.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -28,6 +29,10 @@ class ExternalPopupMenuTest : public RenderViewTest {
return static_cast<RenderViewImpl*>(view_);
}
+ RenderFrameImpl* frame() {
+ return view()->GetMainRenderFrame();
+ }
+
virtual void SetUp() {
RenderViewTest::SetUp();
// We need to set this explictly as RenderMain is not run.
@@ -79,28 +84,28 @@ TEST_F(ExternalPopupMenuTest, NormalCase) {
// We should have sent a message to the browser to show the popup menu.
const IPC::Message* message =
- sink.GetUniqueMessageMatching(ViewHostMsg_ShowPopup::ID);
+ sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
- Tuple1<ViewHostMsg_ShowPopup_Params> param;
- ViewHostMsg_ShowPopup::Read(message, &param);
+ Tuple1<FrameHostMsg_ShowPopup_Params> param;
+ FrameHostMsg_ShowPopup::Read(message, &param);
ASSERT_EQ(3U, param.a.popup_items.size());
EXPECT_EQ(1, param.a.selected_item);
- // Simulate the user canceling the popup, the index should not have changed.
- view()->OnSelectPopupMenuItem(-1);
+ // Simulate the user canceling the popup; the index should not have changed.
+ frame()->OnSelectPopupMenuItem(-1);
EXPECT_EQ(1, GetSelectedIndex());
// Show the pop-up again and this time make a selection.
EXPECT_TRUE(SimulateElementClick(kSelectID));
- view()->OnSelectPopupMenuItem(0);
+ frame()->OnSelectPopupMenuItem(0);
EXPECT_EQ(0, GetSelectedIndex());
// Show the pop-up again and make another selection.
sink.ClearMessages();
EXPECT_TRUE(SimulateElementClick(kSelectID));
- message = sink.GetUniqueMessageMatching(ViewHostMsg_ShowPopup::ID);
+ message = sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
ASSERT_TRUE(message != NULL);
- ViewHostMsg_ShowPopup::Read(message, &param);
+ FrameHostMsg_ShowPopup::Read(message, &param);
ASSERT_EQ(3U, param.a.popup_items.size());
EXPECT_EQ(0, param.a.selected_item);
}
@@ -114,7 +119,7 @@ TEST_F(ExternalPopupMenuTest, ShowPopupThenNavigate) {
LoadHTML("<blink>Awesome page!</blink>");
// Now the user selects something, we should not crash.
- view()->OnSelectPopupMenuItem(-1);
+ frame()->OnSelectPopupMenuItem(-1);
}
// An empty select should not cause a crash when clicked.
@@ -128,7 +133,7 @@ class ExternalPopupMenuRemoveTest : public ExternalPopupMenuTest {
ExternalPopupMenuRemoveTest() {}
protected:
- virtual bool ShouldRemoveSelectOnChange() const OVERRIDE { return true; }
+ bool ShouldRemoveSelectOnChange() const override { return true; }
};
// Tests that nothing bad happen when the page removes the select when it
@@ -138,11 +143,63 @@ TEST_F(ExternalPopupMenuRemoveTest, RemoveOnChange) {
EXPECT_TRUE(SimulateElementClick(kSelectID));
// Select something, it causes the select to be removed from the page.
- view()->OnSelectPopupMenuItem(0);
+ frame()->OnSelectPopupMenuItem(0);
// Just to check the soundness of the test, call SimulateElementClick again.
// It should return false as the select has been removed.
EXPECT_FALSE(SimulateElementClick(kSelectID));
}
+class ExternalPopupMenuDisplayNoneTest : public ExternalPopupMenuTest {
+ public:
+ ExternalPopupMenuDisplayNoneTest() {}
+
+ virtual void SetUp() {
+ RenderViewTest::SetUp();
+ // We need to set this explictly as RenderMain is not run.
+ blink::WebView::setUseExternalPopupMenus(true);
+
+ std::string html = "<select id='mySelect'>"
+ " <option value='zero'>zero</option>"
+ " <optgroup label='hide' style='display: none'>"
+ " <option value='one'>one</option>"
+ " </optgroup>"
+ " <option value='two'>two</option>"
+ " <option value='three'>three</option>"
+ " <option value='four'>four</option>"
+ " <option value='five'>five</option>"
+ "</select>";
+ // Load the test page.
+ LoadHTML(html.c_str());
+
+ // Set a minimum size and give focus so simulated events work.
+ view()->webwidget()->resize(blink::WebSize(500, 500));
+ view()->webwidget()->setFocus(true);
+ }
+
+};
+
+TEST_F(ExternalPopupMenuDisplayNoneTest, SelectItem) {
+ IPC::TestSink& sink = render_thread_->sink();
+
+ // Click the text field once to show the popup.
+ EXPECT_TRUE(SimulateElementClick(kSelectID));
+
+ // Read the message sent to browser to show the popup menu.
+ const IPC::Message* message =
+ sink.GetUniqueMessageMatching(FrameHostMsg_ShowPopup::ID);
+ ASSERT_TRUE(message != NULL);
+ Tuple1<FrameHostMsg_ShowPopup_Params> param;
+ FrameHostMsg_ShowPopup::Read(message, &param);
+ // Number of items should match item count minus the number
+ // of "display: none" items.
+ ASSERT_EQ(5U, param.a.popup_items.size());
+
+ // Select index 1 item. This should select item with index 2,
+ // skipping the item with 'display: none'
+ frame()->OnSelectPopupMenuItem(1);
+
+ EXPECT_EQ(2, GetSelectedIndex());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/fetchers/image_resource_fetcher.cc b/chromium/content/renderer/fetchers/image_resource_fetcher.cc
index 9fee6f4c3f2..ec0798ba86d 100644
--- a/chromium/content/renderer/fetchers/image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/image_resource_fetcher.cc
@@ -25,16 +25,19 @@ ImageResourceFetcher::ImageResourceFetcher(
WebFrame* frame,
int id,
int image_size,
- WebURLRequest::TargetType target_type,
+ WebURLRequest::RequestContext request_context,
const Callback& callback)
: callback_(callback),
id_(id),
image_url_(image_url),
image_size_(image_size) {
fetcher_.reset(ResourceFetcher::Create(image_url));
- fetcher_->Start(frame, target_type,
+ fetcher_->Start(frame,
+ request_context,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
base::Bind(&ImageResourceFetcher::OnURLFetchComplete,
- base::Unretained(this)));
+ base::Unretained(this)));
// Set subresource URL for crash reporting.
base::debug::SetCrashKeyValue("subresource_url", image_url.spec());
diff --git a/chromium/content/renderer/fetchers/image_resource_fetcher.h b/chromium/content/renderer/fetchers/image_resource_fetcher.h
index 2edcf3296fc..eca62af3e5e 100644
--- a/chromium/content/renderer/fetchers/image_resource_fetcher.h
+++ b/chromium/content/renderer/fetchers/image_resource_fetcher.h
@@ -29,13 +29,12 @@ class ImageResourceFetcher {
public:
typedef base::Callback<void(ImageResourceFetcher*, const SkBitmap&)> Callback;
- ImageResourceFetcher(
- const GURL& image_url,
- blink::WebFrame* frame,
- int id,
- int image_size,
- blink::WebURLRequest::TargetType target_type,
- const Callback& callback);
+ ImageResourceFetcher(const GURL& image_url,
+ blink::WebFrame* frame,
+ int id,
+ int image_size,
+ blink::WebURLRequest::RequestContext request_context,
+ const Callback& callback);
virtual ~ImageResourceFetcher();
diff --git a/chromium/content/renderer/fetchers/manifest_fetcher.cc b/chromium/content/renderer/fetchers/manifest_fetcher.cc
new file mode 100644
index 00000000000..c6a64c84f87
--- /dev/null
+++ b/chromium/content/renderer/fetchers/manifest_fetcher.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 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 "content/renderer/fetchers/manifest_fetcher.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "content/public/renderer/resource_fetcher.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+
+namespace content {
+
+ManifestFetcher::ManifestFetcher(const GURL& url)
+ : completed_(false) {
+ fetcher_.reset(ResourceFetcher::Create(url));
+}
+
+ManifestFetcher::~ManifestFetcher() {
+ if (!completed_)
+ Cancel();
+}
+
+void ManifestFetcher::Start(blink::WebFrame* frame, const Callback& callback) {
+ callback_ = callback;
+ fetcher_->Start(frame,
+ blink::WebURLRequest::RequestContextManifest,
+ blink::WebURLRequest::FrameTypeNone,
+ ResourceFetcher::FRAME_ASSOCIATED_LOADER,
+ base::Bind(&ManifestFetcher::OnLoadComplete,
+ base::Unretained(this)));
+}
+
+void ManifestFetcher::Cancel() {
+ DCHECK(!completed_);
+ fetcher_->Cancel();
+}
+
+void ManifestFetcher::OnLoadComplete(const blink::WebURLResponse& response,
+ const std::string& data) {
+ DCHECK(!completed_);
+ completed_ = true;
+
+ Callback callback = callback_;
+ callback.Run(response, data);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/fetchers/manifest_fetcher.h b/chromium/content/renderer/fetchers/manifest_fetcher.h
new file mode 100644
index 00000000000..daa8f0a7bac
--- /dev/null
+++ b/chromium/content/renderer/fetchers/manifest_fetcher.h
@@ -0,0 +1,57 @@
+// Copyright 2014 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 CONTENT_RENDERER_FETCHERS_MANIFEST_FETCHER_H_
+#define CONTENT_RENDERER_FETCHERS_MANIFEST_FETCHER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+
+class GURL;
+
+namespace blink {
+class WebFrame;
+}
+
+namespace content {
+
+class ResourceFetcher;
+
+// Helper class to download a Web Manifest. When an instance is created, the
+// caller need to call Start() and wait for the passed callback to be executed.
+// If the fetch fails, the callback will be called with two empty objects.
+class CONTENT_EXPORT ManifestFetcher {
+ public:
+ // This will be called asynchronously after the URL has been fetched,
+ // successfully or not. If there is a failure, response and data will both be
+ // empty. |response| and |data| are both valid until the URLFetcher instance
+ // is destroyed.
+ typedef base::Callback<void(const blink::WebURLResponse& response,
+ const std::string& data)> Callback;
+
+ explicit ManifestFetcher(const GURL& url);
+ virtual ~ManifestFetcher();
+
+ void Start(blink::WebFrame* frame, const Callback& callback);
+ void Cancel();
+
+ private:
+ void OnLoadComplete(const blink::WebURLResponse& response,
+ const std::string& data);
+
+ bool completed_;
+ Callback callback_;
+ scoped_ptr<ResourceFetcher> fetcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ManifestFetcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_FETCHERS_MANIFEST_FETCHER_H_
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
index 2f4b3ff068c..d310f423cfe 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -23,7 +23,7 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher(
const GURL& image_url,
WebFrame* frame,
int id,
- WebURLRequest::TargetType target_type,
+ WebURLRequest::RequestContext request_context,
const Callback& callback)
: callback_(callback),
id_(id),
@@ -31,7 +31,10 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher(
image_url_(image_url) {
fetcher_.reset(ResourceFetcher::Create(image_url));
fetcher_->Start(
- frame, target_type,
+ frame,
+ request_context,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
base::Bind(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
base::Unretained(this)));
}
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
index 1b329500342..c968a87f12e 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
@@ -36,7 +36,7 @@ class MultiResolutionImageResourceFetcher {
const GURL& image_url,
blink::WebFrame* frame,
int id,
- blink::WebURLRequest::TargetType target_type,
+ blink::WebURLRequest::RequestContext request_context,
const Callback& callback);
virtual ~MultiResolutionImageResourceFetcher();
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
index 6462e76cfe0..c175abcd79a 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -35,12 +35,11 @@ ResourceFetcher* ResourceFetcher::Create(const GURL& url) {
}
ResourceFetcherImpl::ResourceFetcherImpl(const GURL& url)
- : request_(url),
- completed_(false) {
+ : request_(url) {
}
ResourceFetcherImpl::~ResourceFetcherImpl() {
- if (!completed_ && loader_)
+ if (!completed() && loader_)
loader_->cancel();
}
@@ -79,21 +78,32 @@ void ResourceFetcherImpl::SetHeader(const std::string& header,
}
void ResourceFetcherImpl::Start(WebFrame* frame,
- WebURLRequest::TargetType target_type,
+ WebURLRequest::RequestContext request_context,
+ WebURLRequest::FrameType frame_type,
+ LoaderType loader_type,
const Callback& callback) {
DCHECK(!loader_);
DCHECK(!request_.isNull());
DCHECK(callback_.is_null());
- DCHECK(!completed_);
+ DCHECK(!completed());
if (!request_.httpBody().isNull())
DCHECK_NE("GET", request_.httpMethod().utf8()) << "GETs can't have bodies.";
callback_ = callback;
- request_.setTargetType(target_type);
+ request_.setRequestContext(request_context);
+ request_.setFrameType(frame_type);
request_.setFirstPartyForCookies(frame->document().firstPartyForCookies());
frame->dispatchWillSendRequest(request_);
- loader_.reset(blink::Platform::current()->createURLLoader());
+
+ switch (loader_type) {
+ case PLATFORM_LOADER:
+ loader_.reset(blink::Platform::current()->createURLLoader());
+ break;
+ case FRAME_ASSOCIATED_LOADER:
+ loader_.reset(frame->createAssociatedURLLoader());
+ break;
+ }
loader_->loadAsynchronously(request_, this);
// No need to hold on to the request.
@@ -102,15 +112,12 @@ void ResourceFetcherImpl::Start(WebFrame* frame,
void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) {
DCHECK(loader_);
- DCHECK(!completed_);
+ DCHECK(!completed());
- timeout_timer_.Start(FROM_HERE, timeout, this,
- &ResourceFetcherImpl::TimeoutFired);
+ timeout_timer_.Start(FROM_HERE, timeout, this, &ResourceFetcherImpl::Cancel);
}
-void ResourceFetcherImpl::RunCallback(const WebURLResponse& response,
- const std::string& data) {
- completed_ = true;
+void ResourceFetcherImpl::OnLoadComplete() {
timeout_timer_.Stop();
if (callback_.is_null())
return;
@@ -118,65 +125,13 @@ void ResourceFetcherImpl::RunCallback(const WebURLResponse& response,
// Take a reference to the callback as running the callback may lead to our
// destruction.
Callback callback = callback_;
- callback.Run(response, data);
+ callback.Run(status() == LOAD_FAILED ? blink::WebURLResponse() : response(),
+ status() == LOAD_FAILED ? std::string() : data());
}
-void ResourceFetcherImpl::TimeoutFired() {
- DCHECK(!completed_);
+void ResourceFetcherImpl::Cancel() {
loader_->cancel();
- RunCallback(WebURLResponse(), std::string());
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// WebURLLoaderClient methods
-
-void ResourceFetcherImpl::willSendRequest(
- WebURLLoader* loader, WebURLRequest& new_request,
- const WebURLResponse& redirect_response) {
-}
-
-void ResourceFetcherImpl::didSendData(
- WebURLLoader* loader, unsigned long long bytes_sent,
- unsigned long long total_bytes_to_be_sent) {
-}
-
-void ResourceFetcherImpl::didReceiveResponse(
- WebURLLoader* loader, const WebURLResponse& response) {
- DCHECK(!completed_);
- response_ = response;
-}
-
-void ResourceFetcherImpl::didReceiveData(
- WebURLLoader* loader, const char* data, int data_length,
- int encoded_data_length) {
- DCHECK(!completed_);
- DCHECK(data_length > 0);
-
- data_.append(data, data_length);
-}
-
-void ResourceFetcherImpl::didReceiveCachedMetadata(
- WebURLLoader* loader, const char* data, int data_length) {
- DCHECK(!completed_);
- DCHECK(data_length > 0);
-
- metadata_.assign(data, data_length);
-}
-
-void ResourceFetcherImpl::didFinishLoading(
- WebURLLoader* loader, double finishTime,
- int64_t total_encoded_data_length) {
- DCHECK(!completed_);
-
- RunCallback(response_, data_);
-}
-
-void ResourceFetcherImpl::didFail(WebURLLoader* loader,
- const WebURLError& error) {
- DCHECK(!completed_);
-
- // Go ahead and tell our delegate that we're done.
- RunCallback(WebURLResponse(), std::string());
+ WebURLLoaderClientImpl::Cancel();
}
} // namespace content
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.h b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
index aed1d79fc98..8064c1a2809 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.h
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
@@ -13,7 +13,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "content/public/renderer/resource_fetcher.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "content/renderer/fetchers/web_url_loader_client_impl.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
@@ -28,17 +28,18 @@ struct WebURLError;
namespace content {
class ResourceFetcherImpl : public ResourceFetcher,
- public blink::WebURLLoaderClient {
+ public WebURLLoaderClientImpl {
public:
// ResourceFetcher implementation:
- virtual void SetMethod(const std::string& method) OVERRIDE;
- virtual void SetBody(const std::string& body) OVERRIDE;
- virtual void SetHeader(const std::string& header,
- const std::string& value) OVERRIDE;
- virtual void Start(blink::WebFrame* frame,
- blink::WebURLRequest::TargetType target_type,
- const Callback& callback) OVERRIDE;
- virtual void SetTimeout(const base::TimeDelta& timeout) OVERRIDE;
+ void SetMethod(const std::string& method) override;
+ void SetBody(const std::string& body) override;
+ void SetHeader(const std::string& header, const std::string& value) override;
+ void Start(blink::WebFrame* frame,
+ blink::WebURLRequest::RequestContext request_context,
+ blink::WebURLRequest::FrameType frame_type,
+ LoaderType loader_type,
+ const Callback& callback) override;
+ void SetTimeout(const base::TimeDelta& timeout) override;
private:
friend class ResourceFetcher;
@@ -47,54 +48,22 @@ class ResourceFetcherImpl : public ResourceFetcher,
virtual ~ResourceFetcherImpl();
- void RunCallback(const blink::WebURLResponse& response,
- const std::string& data);
-
// Callback for timer that limits how long we wait for the server. If this
// timer fires and the request hasn't completed, we kill the request.
void TimeoutFired();
- // WebURLLoaderClient methods:
- virtual void willSendRequest(
- blink::WebURLLoader* loader, blink::WebURLRequest& new_request,
- const blink::WebURLResponse& redirect_response);
- virtual void didSendData(
- blink::WebURLLoader* loader, unsigned long long bytes_sent,
- unsigned long long total_bytes_to_be_sent);
- virtual void didReceiveResponse(
- blink::WebURLLoader* loader, const blink::WebURLResponse& response);
- virtual void didReceiveCachedMetadata(
- blink::WebURLLoader* loader, const char* data, int data_length);
-
- virtual void didReceiveData(
- blink::WebURLLoader* loader, const char* data, int data_length,
- int encoded_data_length);
- virtual void didFinishLoading(
- blink::WebURLLoader* loader, double finishTime,
- int64_t total_encoded_data_length);
- virtual void didFail(
- blink::WebURLLoader* loader, const blink::WebURLError& error);
+ // WebURLLoaderClientImpl methods:
+ void OnLoadComplete() override;
+ void Cancel() override;
scoped_ptr<blink::WebURLLoader> loader_;
// Request to send. Released once Start() is called.
blink::WebURLRequest request_;
- // Set to true once the request is complete.
- bool completed_;
-
- // Buffer to hold the content from the server.
- std::string data_;
-
- // A copy of the original resource response.
- blink::WebURLResponse response_;
-
// Callback when we're done.
Callback callback_;
- // Buffer to hold metadata from the cache.
- std::string metadata_;
-
// Limit how long to wait for the server.
base::OneShotTimer<ResourceFetcherImpl> timeout_timer_;
diff --git a/chromium/content/renderer/fetchers/web_url_loader_client_impl.cc b/chromium/content/renderer/fetchers/web_url_loader_client_impl.cc
new file mode 100644
index 00000000000..847a167928f
--- /dev/null
+++ b/chromium/content/renderer/fetchers/web_url_loader_client_impl.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2012 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 "content/renderer/fetchers/web_url_loader_client_impl.h"
+
+#include "base/logging.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "third_party/WebKit/public/platform/WebURLLoader.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+
+namespace content {
+
+WebURLLoaderClientImpl::WebURLLoaderClientImpl()
+ : completed_(false)
+ , status_(LOADING) {
+}
+
+WebURLLoaderClientImpl::~WebURLLoaderClientImpl() {
+}
+
+void WebURLLoaderClientImpl::didReceiveResponse(
+ blink::WebURLLoader* loader, const blink::WebURLResponse& response) {
+ DCHECK(!completed_);
+ response_ = response;
+}
+
+void WebURLLoaderClientImpl::didReceiveData(
+ blink::WebURLLoader* loader,
+ const char* data,
+ int data_length,
+ int encoded_data_length) {
+ DCHECK(!completed_);
+ DCHECK(data_length > 0);
+
+ data_.append(data, data_length);
+}
+
+void WebURLLoaderClientImpl::didReceiveCachedMetadata(
+ blink::WebURLLoader* loader,
+ const char* data,
+ int data_length) {
+ DCHECK(!completed_);
+ DCHECK(data_length > 0);
+
+ metadata_.assign(data, data_length);
+}
+
+void WebURLLoaderClientImpl::didFinishLoading(
+ blink::WebURLLoader* loader,
+ double finishTime,
+ int64_t total_encoded_data_length) {
+ OnLoadCompleteInternal(LOAD_SUCCEEDED);
+}
+
+void WebURLLoaderClientImpl::didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error) {
+ OnLoadCompleteInternal(LOAD_FAILED);
+}
+
+void WebURLLoaderClientImpl::Cancel() {
+ OnLoadCompleteInternal(LOAD_FAILED);
+}
+
+void WebURLLoaderClientImpl::OnLoadCompleteInternal(LoadStatus status) {
+ DCHECK(!completed_);
+ DCHECK(status_ == LOADING);
+
+ completed_ = true;
+ status_ = status;
+
+ OnLoadComplete();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/fetchers/web_url_loader_client_impl.h b/chromium/content/renderer/fetchers/web_url_loader_client_impl.h
new file mode 100644
index 00000000000..1113862873f
--- /dev/null
+++ b/chromium/content/renderer/fetchers/web_url_loader_client_impl.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2011 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 CONTENT_RENDERER_FETCHERS_WEB_URL_LOADER_CLIENT_IMPL_H_
+#define CONTENT_RENDERER_FETCHERS_WEB_URL_LOADER_CLIENT_IMPL_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+
+namespace blink {
+class WebURLLoader;
+struct WebURLError;
+}
+
+namespace content {
+
+class WebURLLoaderClientImpl : public blink::WebURLLoaderClient {
+ protected:
+ enum LoadStatus {
+ LOADING,
+ LOAD_FAILED,
+ LOAD_SUCCEEDED,
+ };
+
+ WebURLLoaderClientImpl();
+ virtual ~WebURLLoaderClientImpl();
+
+ virtual void Cancel();
+
+ bool completed() const { return completed_; }
+ const std::string& data() const { return data_; }
+ const blink::WebURLResponse& response() const { return response_; }
+ const std::string& metadata() const { return metadata_; }
+ LoadStatus status() const { return status_; }
+
+ virtual void OnLoadComplete() = 0;
+
+ private:
+ void OnLoadCompleteInternal(LoadStatus);
+
+ // WebWebURLLoaderClientImpl methods:
+ virtual void didReceiveResponse(
+ blink::WebURLLoader* loader, const blink::WebURLResponse& response);
+ virtual void didReceiveCachedMetadata(
+ blink::WebURLLoader* loader, const char* data, int data_length);
+ virtual void didReceiveData(
+ blink::WebURLLoader* loader,
+ const char* data,
+ int data_length,
+ int encoded_data_length);
+ virtual void didFinishLoading(
+ blink::WebURLLoader* loader,
+ double finishTime,
+ int64_t total_encoded_data_length);
+ virtual void didFail(
+ blink::WebURLLoader* loader, const blink::WebURLError& error);
+
+ private:
+ // Set to true once the request is complete.
+ bool completed_;
+
+ // Buffer to hold the content from the server.
+ std::string data_;
+
+ // A copy of the original resource response.
+ blink::WebURLResponse response_;
+
+ // Buffer to hold metadata from the cache.
+ std::string metadata_;
+
+ LoadStatus status_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebURLLoaderClientImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_FETCHERS_URL_LOADER_CLIENT_H_
diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.cc b/chromium/content/renderer/gamepad_shared_memory_reader.cc
index e74f0258186..ab75d7eaeb7 100644
--- a/chromium/content/renderer/gamepad_shared_memory_reader.cc
+++ b/chromium/content/renderer/gamepad_shared_memory_reader.cc
@@ -9,27 +9,31 @@
#include "content/common/gamepad_hardware_buffer.h"
#include "content/common/gamepad_user_gesture.h"
#include "content/public/renderer/render_thread.h"
-#include "content/renderer/renderer_webkitplatformsupport_impl.h"
+#include "content/renderer/renderer_blink_platform_impl.h"
#include "ipc/ipc_sync_message_filter.h"
#include "third_party/WebKit/public/platform/WebGamepadListener.h"
+#include "third_party/WebKit/public/platform/WebPlatformEventListener.h"
namespace content {
-GamepadSharedMemoryReader::GamepadSharedMemoryReader(
- RendererWebKitPlatformSupportImpl* webkit_platform_support)
- : gamepad_hardware_buffer_(NULL),
- gamepad_listener_(NULL),
- is_polling_(false),
+GamepadSharedMemoryReader::GamepadSharedMemoryReader(RenderThread* thread)
+ : RendererGamepadProvider(thread),
+ gamepad_hardware_buffer_(NULL),
ever_interacted_with_(false) {
- webkit_platform_support->set_gamepad_provider(this);
}
-void GamepadSharedMemoryReader::StartPollingIfNecessary() {
- if (is_polling_)
- return;
-
+void GamepadSharedMemoryReader::SendStartMessage() {
CHECK(RenderThread::Get()->Send(new GamepadHostMsg_StartPolling(
&renderer_shared_memory_handle_)));
+}
+
+void GamepadSharedMemoryReader::SendStopMessage() {
+ RenderThread::Get()->Send(new GamepadHostMsg_StopPolling());
+}
+
+void GamepadSharedMemoryReader::Start(
+ blink::WebPlatformEventListener* listener) {
+ PlatformEventObserver::Start(listener);
// If we don't get a valid handle from the browser, don't try to Map (we're
// probably out of memory or file handles).
@@ -46,24 +50,11 @@ void GamepadSharedMemoryReader::StartPollingIfNecessary() {
CHECK(memory);
gamepad_hardware_buffer_ =
static_cast<GamepadHardwareBuffer*>(memory);
-
- is_polling_ = true;
-}
-
-void GamepadSharedMemoryReader::StopPollingIfNecessary() {
- if (is_polling_) {
- RenderThread::Get()->Send(new GamepadHostMsg_StopPolling());
- is_polling_ = false;
- }
}
void GamepadSharedMemoryReader::SampleGamepads(blink::WebGamepads& gamepads) {
- // Blink should set the listener before start sampling.
- CHECK(gamepad_listener_);
-
- StartPollingIfNecessary();
- if (!is_polling_)
- return;
+ // Blink should have started observing at that point.
+ CHECK(is_observing());
// ==========
// DANGER
@@ -113,20 +104,8 @@ void GamepadSharedMemoryReader::SampleGamepads(blink::WebGamepads& gamepads) {
}
}
-void GamepadSharedMemoryReader::SetGamepadListener(
- blink::WebGamepadListener* listener) {
- gamepad_listener_ = listener;
- if (gamepad_listener_) {
- // Polling has to be started rigth now and not just on the first sampling
- // because want to get connection events from now.
- StartPollingIfNecessary();
- } else {
- StopPollingIfNecessary();
- }
-}
-
GamepadSharedMemoryReader::~GamepadSharedMemoryReader() {
- StopPollingIfNecessary();
+ StopIfObserving();
}
bool GamepadSharedMemoryReader::OnControlMessageReceived(
@@ -146,15 +125,15 @@ void GamepadSharedMemoryReader::OnGamepadConnected(
// The browser already checks if the user actually interacted with a device.
ever_interacted_with_ = true;
- if (gamepad_listener_)
- gamepad_listener_->didConnectGamepad(index, gamepad);
+ if (listener())
+ listener()->didConnectGamepad(index, gamepad);
}
void GamepadSharedMemoryReader::OnGamepadDisconnected(
int index,
const blink::WebGamepad& gamepad) {
- if (gamepad_listener_)
- gamepad_listener_->didDisconnectGamepad(index, gamepad);
+ if (listener())
+ listener()->didDisconnectGamepad(index, gamepad);
}
} // namespace content
diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.h b/chromium/content/renderer/gamepad_shared_memory_reader.h
index eb63867612c..40af1b8bc69 100644
--- a/chromium/content/renderer/gamepad_shared_memory_reader.h
+++ b/chromium/content/renderer/gamepad_shared_memory_reader.h
@@ -8,46 +8,39 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "content/common/gamepad_messages.h"
-#include "content/public/renderer/render_process_observer.h"
#include "content/public/renderer/renderer_gamepad_provider.h"
#include "third_party/WebKit/public/platform/WebGamepads.h"
namespace content {
struct GamepadHardwareBuffer;
-class RendererWebKitPlatformSupportImpl;
-class GamepadSharedMemoryReader
- : public RenderProcessObserver,
- public RendererGamepadProvider {
+class GamepadSharedMemoryReader : public RendererGamepadProvider {
public:
- GamepadSharedMemoryReader(
- RendererWebKitPlatformSupportImpl* webkit_platform_support);
- virtual ~GamepadSharedMemoryReader();
+ explicit GamepadSharedMemoryReader(RenderThread* thread);
+ ~GamepadSharedMemoryReader() override;
// RendererGamepadProvider implementation.
- virtual void SampleGamepads(
- blink::WebGamepads& gamepads) OVERRIDE;
- virtual void SetGamepadListener(
- blink::WebGamepadListener* listener) OVERRIDE;
+ void SampleGamepads(blink::WebGamepads& gamepads) override;
+ bool OnControlMessageReceived(const IPC::Message& message) override;
+ void Start(blink::WebPlatformEventListener* listener) override;
- // RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+ protected:
+ // PlatformEventObserver protected methods.
+ void SendStartMessage() override;
+ void SendStopMessage() override;
private:
void OnGamepadConnected(int index, const blink::WebGamepad& gamepad);
void OnGamepadDisconnected(int index, const blink::WebGamepad& gamepad);
- void StartPollingIfNecessary();
- void StopPollingIfNecessary();
-
base::SharedMemoryHandle renderer_shared_memory_handle_;
scoped_ptr<base::SharedMemory> renderer_shared_memory_;
GamepadHardwareBuffer* gamepad_hardware_buffer_;
- blink::WebGamepadListener* gamepad_listener_;
- bool is_polling_;
bool ever_interacted_with_;
+
+ DISALLOW_COPY_AND_ASSIGN(GamepadSharedMemoryReader);
};
} // namespace content
diff --git a/chromium/content/renderer/geolocation_dispatcher.cc b/chromium/content/renderer/geolocation_dispatcher.cc
index 620b0578ed0..fde4fc98cba 100644
--- a/chromium/content/renderer/geolocation_dispatcher.cc
+++ b/chromium/content/renderer/geolocation_dispatcher.cc
@@ -25,8 +25,7 @@ namespace content {
GeolocationDispatcher::GeolocationDispatcher(RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
pending_permissions_(new WebGeolocationPermissionRequestManager()),
- enable_high_accuracy_(false),
- updating_(false) {
+ enable_high_accuracy_(false) {
}
GeolocationDispatcher::~GeolocationDispatcher() {}
@@ -35,27 +34,23 @@ bool GeolocationDispatcher::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GeolocationDispatcher, message)
IPC_MESSAGE_HANDLER(GeolocationMsg_PermissionSet, OnPermissionSet)
- IPC_MESSAGE_HANDLER(GeolocationMsg_PositionUpdated, OnPositionUpdated)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void GeolocationDispatcher::geolocationDestroyed() {
- controller_.reset();
- DCHECK(!updating_);
-}
-
void GeolocationDispatcher::startUpdating() {
- GURL url;
- Send(new GeolocationHostMsg_StartUpdating(
- routing_id(), url, enable_high_accuracy_));
- updating_ = true;
+ if (!geolocation_service_.get()) {
+ render_frame()->GetServiceRegistry()->ConnectToRemoteService(
+ &geolocation_service_);
+ geolocation_service_.set_client(this);
+ }
+ if (enable_high_accuracy_)
+ geolocation_service_->SetHighAccuracy(true);
}
void GeolocationDispatcher::stopUpdating() {
- Send(new GeolocationHostMsg_StopUpdating(routing_id()));
- updating_ = false;
+ geolocation_service_.reset();
}
void GeolocationDispatcher::setEnableHighAccuracy(bool enable_high_accuracy) {
@@ -66,8 +61,8 @@ void GeolocationDispatcher::setEnableHighAccuracy(bool enable_high_accuracy) {
bool has_changed = enable_high_accuracy_ != enable_high_accuracy;
enable_high_accuracy_ = enable_high_accuracy;
// We have a different accuracy requirement. Request browser to update.
- if (updating_ && has_changed)
- startUpdating();
+ if (geolocation_service_.get() && has_changed)
+ geolocation_service_->SetHighAccuracy(enable_high_accuracy_);
}
void GeolocationDispatcher::setController(
@@ -94,16 +89,10 @@ void GeolocationDispatcher::requestPermission(
blink::WebUserGestureIndicator::isProcessingUserGesture()));
}
-// TODO(jknotten): Change the messages to use a security origin, so no
-// conversion is necessary.
void GeolocationDispatcher::cancelPermissionRequest(
const WebGeolocationPermissionRequest& permissionRequest) {
int bridge_id;
- if (!pending_permissions_->remove(permissionRequest, bridge_id))
- return;
- base::string16 origin = permissionRequest.securityOrigin().toString();
- Send(new GeolocationHostMsg_CancelPermissionRequest(
- routing_id(), bridge_id, GURL(origin)));
+ pending_permissions_->remove(permissionRequest, bridge_id);
}
// Permission for using geolocation has been set.
@@ -114,32 +103,27 @@ void GeolocationDispatcher::OnPermissionSet(int bridge_id, bool is_allowed) {
permissionRequest.setIsAllowed(is_allowed);
}
-// We have an updated geolocation position or error code.
-void GeolocationDispatcher::OnPositionUpdated(
- const Geoposition& geoposition) {
- // It is possible for the browser process to have queued an update message
- // before receiving the stop updating message.
- if (!updating_)
- return;
-
- if (geoposition.Validate()) {
- controller_->positionChanged(
- WebGeolocationPosition(
- geoposition.timestamp.ToDoubleT(),
- geoposition.latitude, geoposition.longitude,
- geoposition.accuracy,
- // Lowest point on land is at approximately -400 meters.
- geoposition.altitude > -10000.,
- geoposition.altitude,
- geoposition.altitude_accuracy >= 0.,
- geoposition.altitude_accuracy,
- geoposition.heading >= 0. && geoposition.heading <= 360.,
- geoposition.heading,
- geoposition.speed >= 0.,
- geoposition.speed));
+void GeolocationDispatcher::OnLocationUpdate(MojoGeopositionPtr geoposition) {
+ DCHECK(geolocation_service_.get());
+
+ if (geoposition->valid) {
+ controller_->positionChanged(WebGeolocationPosition(
+ geoposition->timestamp,
+ geoposition->latitude,
+ geoposition->longitude,
+ geoposition->accuracy,
+ // Lowest point on land is at approximately -400 meters.
+ geoposition->altitude > -10000.,
+ geoposition->altitude,
+ geoposition->altitude_accuracy >= 0.,
+ geoposition->altitude_accuracy,
+ geoposition->heading >= 0. && geoposition->heading <= 360.,
+ geoposition->heading,
+ geoposition->speed >= 0.,
+ geoposition->speed));
} else {
WebGeolocationError::Error code;
- switch (geoposition.error_code) {
+ switch (geoposition->error_code) {
case Geoposition::ERROR_CODE_PERMISSION_DENIED:
code = WebGeolocationError::ErrorPermissionDenied;
break;
@@ -147,12 +131,11 @@ void GeolocationDispatcher::OnPositionUpdated(
code = WebGeolocationError::ErrorPositionUnavailable;
break;
default:
- NOTREACHED() << geoposition.error_code;
+ NOTREACHED() << geoposition->error_code;
return;
}
- controller_->errorOccurred(
- WebGeolocationError(
- code, blink::WebString::fromUTF8(geoposition.error_message)));
+ controller_->errorOccurred(WebGeolocationError(
+ code, blink::WebString::fromUTF8(geoposition->error_message)));
}
}
diff --git a/chromium/content/renderer/geolocation_dispatcher.h b/chromium/content/renderer/geolocation_dispatcher.h
index bffa50958a3..454859d0525 100644
--- a/chromium/content/renderer/geolocation_dispatcher.h
+++ b/chromium/content/renderer/geolocation_dispatcher.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_GEOLOCATION_DISPATCHER_H_
#include "base/memory/scoped_ptr.h"
+#include "content/common/geolocation_service.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "third_party/WebKit/public/web/WebGeolocationClient.h"
#include "third_party/WebKit/public/web/WebGeolocationController.h"
@@ -23,18 +24,19 @@ struct Geoposition;
// GeolocationDispatcher is a delegate for Geolocation messages used by
// WebKit.
// It's the complement of GeolocationDispatcherHost.
-class GeolocationDispatcher : public RenderFrameObserver,
- public blink::WebGeolocationClient {
+class GeolocationDispatcher
+ : public RenderFrameObserver,
+ public blink::WebGeolocationClient,
+ public mojo::InterfaceImpl<GeolocationServiceClient> {
public:
explicit GeolocationDispatcher(RenderFrame* render_frame);
virtual ~GeolocationDispatcher();
private:
// RenderFrame::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// WebGeolocationClient
- virtual void geolocationDestroyed();
virtual void startUpdating();
virtual void stopUpdating();
virtual void setEnableHighAccuracy(bool enable_high_accuracy);
@@ -45,21 +47,18 @@ class GeolocationDispatcher : public RenderFrameObserver,
virtual void cancelPermissionRequest(
const blink::WebGeolocationPermissionRequest& permissionRequest);
+ // GeolocationServiceClient
+ void OnLocationUpdate(MojoGeopositionPtr geoposition) override;
+
// Permission for using geolocation has been set.
void OnPermissionSet(int bridge_id, bool is_allowed);
- // We have an updated geolocation position or error code.
- void OnPositionUpdated(const content::Geoposition& geoposition);
-
- // The controller_ is valid for the lifetime of the underlying
- // WebCore::GeolocationController. geolocationDestroyed() is
- // invoked when the underlying object is destroyed.
scoped_ptr<blink::WebGeolocationController> controller_;
scoped_ptr<blink::WebGeolocationPermissionRequestManager>
pending_permissions_;
+ GeolocationServicePtr geolocation_service_;
bool enable_high_accuracy_;
- bool updating_;
};
} // namespace content
diff --git a/chromium/content/renderer/gin_browsertest.cc b/chromium/content/renderer/gin_browsertest.cc
index a4e2c10bd30..58fccd9f148 100644
--- a/chromium/content/renderer/gin_browsertest.cc
+++ b/chromium/content/renderer/gin_browsertest.cc
@@ -28,7 +28,7 @@ class TestGinObject : public gin::Wrappable<TestGinObject> {
private:
TestGinObject(bool* alive) : alive_(alive) { *alive_ = true; }
- virtual ~TestGinObject() { *alive_ = false; }
+ ~TestGinObject() override { *alive_ = false; }
bool* alive_;
@@ -40,9 +40,9 @@ gin::WrapperInfo TestGinObject::kWrapperInfo = { gin::kEmbedderNativeGin };
class GinBrowserTest : public RenderViewTest {
public:
GinBrowserTest() {}
- virtual ~GinBrowserTest() {}
+ ~GinBrowserTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kJavaScriptFlags, "--expose_gc");
@@ -75,7 +75,7 @@ TEST_F(GinBrowserTest, GinAndGarbageCollection) {
CHECK(alive);
// Should not crash.
- v8::V8::LowMemoryNotification();
+ blink::mainThreadIsolate()->LowMemoryNotification();
CHECK(!alive);
}
diff --git a/chromium/content/renderer/gpu/OWNERS b/chromium/content/renderer/gpu/OWNERS
index 6f39d70c6bf..4cd2b20015b 100644
--- a/chromium/content/renderer/gpu/OWNERS
+++ b/chromium/content/renderer/gpu/OWNERS
@@ -1,2 +1,3 @@
+jbauman@chromium.org
kbr@chromium.org
piman@chromium.org
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.cc b/chromium/content/renderer/gpu/compositor_output_surface.cc
index a2929643ac1..c579d8c4029 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.cc
+++ b/chromium/content/renderer/gpu/compositor_output_surface.cc
@@ -15,6 +15,7 @@
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -54,12 +55,14 @@ CompositorOutputSurface::CompositorOutputSurface(
uint32 output_surface_id,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
bool use_swap_compositor_frame_message)
: OutputSurface(context_provider, software_device.Pass()),
output_surface_id_(output_surface_id),
use_swap_compositor_frame_message_(use_swap_compositor_frame_message),
output_surface_filter_(
RenderThreadImpl::current()->compositor_output_surface_filter()),
+ frame_swap_message_queue_(swap_frame_message_queue),
routing_id_(routing_id),
prefers_smoothness_(false),
#if defined(OS_WIN)
@@ -71,6 +74,7 @@ CompositorOutputSurface::CompositorOutputSurface(
layout_test_mode_(RenderThreadImpl::current()->layout_test_mode()),
weak_ptrs_(this) {
DCHECK(output_surface_filter_.get());
+ DCHECK(frame_swap_message_queue_.get());
DetachFromThread();
message_sender_ = RenderThreadImpl::current()->sync_message_filter();
DCHECK(message_sender_.get());
@@ -107,7 +111,7 @@ bool CompositorOutputSurface::BindToClient(
client->SetMemoryPolicy(cc::ManagedMemoryPolicy(
128 * 1024 * 1024,
gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE,
- cc::ManagedMemoryPolicy::kDefaultNumResourcesLimit));
+ base::SharedMemory::GetHandleLimit() / 3));
}
return true;
@@ -130,7 +134,8 @@ void CompositorOutputSurface::ShortcutSwapAck(
}
void CompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
- if (layout_test_mode_ && use_swap_compositor_frame_message_) {
+ DCHECK(use_swap_compositor_frame_message_);
+ if (layout_test_mode_) {
// This code path is here to support layout tests that are currently
// doing a readback in the renderer instead of the browser. So they
// are using deprecated code paths in the renderer and don't need to
@@ -149,37 +154,34 @@ void CompositorOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
base::Passed(&frame->gl_frame_data),
base::Passed(&frame->software_frame_data));
- if (context_provider_) {
- gpu::gles2::GLES2Interface* context = context_provider_->ContextGL();
+ if (context_provider()) {
+ gpu::gles2::GLES2Interface* context = context_provider()->ContextGL();
context->Flush();
uint32 sync_point = context->InsertSyncPointCHROMIUM();
- context_provider_->ContextSupport()->SignalSyncPoint(sync_point, closure);
+ context_provider()->ContextSupport()->SignalSyncPoint(sync_point,
+ closure);
} else {
base::MessageLoopProxy::current()->PostTask(FROM_HERE, closure);
}
client_->DidSwapBuffers();
return;
- }
-
- if (use_swap_compositor_frame_message_) {
- Send(new ViewHostMsg_SwapCompositorFrame(routing_id_,
- output_surface_id_,
- *frame));
+ } else {
+ {
+ ScopedVector<IPC::Message> messages;
+ std::vector<IPC::Message> messages_to_deliver_with_frame;
+ scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
+ frame_swap_message_queue_->AcquireSendMessageScope();
+ frame_swap_message_queue_->DrainMessages(&messages);
+ FrameSwapMessageQueue::TransferMessages(messages,
+ &messages_to_deliver_with_frame);
+ Send(new ViewHostMsg_SwapCompositorFrame(routing_id_,
+ output_surface_id_,
+ *frame,
+ messages_to_deliver_with_frame));
+ // ~send_message_scope.
+ }
client_->DidSwapBuffers();
- return;
}
-
- if (frame->gl_frame_data) {
- context_provider_->ContextGL()->ShallowFlushCHROMIUM();
- ContextProviderCommandBuffer* provider_command_buffer =
- static_cast<ContextProviderCommandBuffer*>(context_provider_.get());
- CommandBufferProxyImpl* command_buffer_proxy =
- provider_command_buffer->GetCommandBufferProxy();
- DCHECK(command_buffer_proxy);
- command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info);
- }
-
- OutputSurface::SwapBuffers(frame);
}
void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) {
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.h b/chromium/content/renderer/gpu/compositor_output_surface.h
index df9104769a9..7ee94270245 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.h
+++ b/chromium/content/renderer/gpu/compositor_output_surface.h
@@ -35,6 +35,7 @@ class SoftwareFrameData;
namespace content {
class ContextProviderCommandBuffer;
+class FrameSwapMessageQueue;
// This class can be created only on the main thread, but then becomes pinned
// to a fixed thread when bindToClient is called.
@@ -50,19 +51,20 @@ class CompositorOutputSurface
uint32 output_surface_id,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
scoped_ptr<cc::SoftwareOutputDevice> software,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
bool use_swap_compositor_frame_message);
- virtual ~CompositorOutputSurface();
+ ~CompositorOutputSurface() override;
// cc::OutputSurface implementation.
- virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ bool BindToClient(cc::OutputSurfaceClient* client) override;
+ void SwapBuffers(cc::CompositorFrame* frame) override;
#if defined(OS_ANDROID)
- virtual void SetNeedsBeginFrame(bool enable) OVERRIDE;
+ virtual void SetNeedsBeginFrame(bool enable) override;
#endif
// TODO(epenner): This seems out of place here and would be a better fit
// int CompositorThread after it is fully refactored (http://crbug/170828)
- virtual void UpdateSmoothnessTakesPriority(bool prefer_smoothness) OVERRIDE;
+ void UpdateSmoothnessTakesPriority(bool prefer_smoothness) override;
protected:
void ShortcutSwapAck(uint32 output_surface_id,
@@ -108,6 +110,7 @@ class CompositorOutputSurface
scoped_refptr<IPC::ForwardingMessageFilter> output_surface_filter_;
scoped_refptr<CompositorOutputSurfaceProxy> output_surface_proxy_;
scoped_refptr<IPC::SyncMessageFilter> message_sender_;
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
int routing_id_;
bool prefers_smoothness_;
base::PlatformThreadHandle main_thread_handle_;
diff --git a/chromium/content/renderer/gpu/compositor_software_output_device.cc b/chromium/content/renderer/gpu/compositor_software_output_device.cc
index c656d452715..4b23919203b 100644
--- a/chromium/content/renderer/gpu/compositor_software_output_device.cc
+++ b/chromium/content/renderer/gpu/compositor_software_output_device.cc
@@ -9,12 +9,17 @@
#include "content/child/child_shared_bitmap_manager.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
-#include "third_party/skia/include/core/SkBitmapDevice.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/skia_util.h"
+namespace {
+
+const size_t kInvalidIndex = static_cast<size_t>(-1);
+
+} // namespace
+
namespace content {
CompositorSoftwareOutputDevice::Buffer::Buffer(
@@ -56,7 +61,7 @@ bool CompositorSoftwareOutputDevice::Buffer::FindDamageDifferenceFrom(
}
CompositorSoftwareOutputDevice::CompositorSoftwareOutputDevice()
- : current_index_(-1),
+ : current_index_(kInvalidIndex),
next_buffer_id_(1),
shared_bitmap_manager_(
RenderThreadImpl::current()->shared_bitmap_manager()) {
@@ -113,7 +118,7 @@ void CompositorSoftwareOutputDevice::Resize(
}
buffers_.clear();
- current_index_ = -1;
+ current_index_ = kInvalidIndex;
viewport_pixel_size_ = viewport_pixel_size;
}
@@ -126,7 +131,7 @@ void CompositorSoftwareOutputDevice::DiscardBackbuffer() {
}
}
buffers_.clear();
- current_index_ = -1;
+ current_index_ = kInvalidIndex;
}
void CompositorSoftwareOutputDevice::EnsureBackbuffer() {
@@ -137,7 +142,7 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
DCHECK(CalledOnValidThread());
Buffer* previous = NULL;
- if (current_index_ != size_t(-1))
+ if (current_index_ != kInvalidIndex)
previous = buffers_[current_index_];
current_index_ = FindFreeBuffer(current_index_ + 1);
Buffer* current = buffers_[current_index_];
@@ -166,11 +171,10 @@ SkCanvas* CompositorSoftwareOutputDevice::BeginPaint(
// Copy over the damage region.
if (!region.isEmpty()) {
+ SkImageInfo info = SkImageInfo::MakeN32Premul(
+ viewport_pixel_size_.width(), viewport_pixel_size_.height());
SkBitmap back_bitmap;
- back_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
- viewport_pixel_size_.width(),
- viewport_pixel_size_.height());
- back_bitmap.setPixels(previous->memory());
+ back_bitmap.installPixels(info, previous->memory(), info.minRowBytes());
for (SkRegion::Iterator it(region); !it.done(); it.next()) {
const SkIRect& src_rect = it.rect();
diff --git a/chromium/content/renderer/gpu/compositor_software_output_device.h b/chromium/content/renderer/gpu/compositor_software_output_device.h
index 75bda0ce53e..48fa0507ebe 100644
--- a/chromium/content/renderer/gpu/compositor_software_output_device.h
+++ b/chromium/content/renderer/gpu/compositor_software_output_device.h
@@ -27,20 +27,20 @@ namespace content {
class CompositorSoftwareOutputDevice
: NON_EXPORTED_BASE(public cc::SoftwareOutputDevice),
NON_EXPORTED_BASE(public base::NonThreadSafe) {
-public:
+ public:
CompositorSoftwareOutputDevice();
- virtual ~CompositorSoftwareOutputDevice();
+ ~CompositorSoftwareOutputDevice() override;
- virtual void Resize(const gfx::Size& pixel_size, float scale_factor) OVERRIDE;
+ void Resize(const gfx::Size& pixel_size, float scale_factor) override;
- virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
- virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
- virtual void EnsureBackbuffer() OVERRIDE;
- virtual void DiscardBackbuffer() OVERRIDE;
+ SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
+ void EndPaint(cc::SoftwareFrameData* frame_data) override;
+ void EnsureBackbuffer() override;
+ void DiscardBackbuffer() override;
- virtual void ReclaimSoftwareFrame(unsigned id) OVERRIDE;
+ void ReclaimSoftwareFrame(unsigned id) override;
-private:
+ private:
// Internal buffer class that manages shared memory lifetime and ownership.
// It also tracks buffers' history so we can calculate what's the minimum
// damage rect difference between any two given buffers (see SetParent and
diff --git a/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc b/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
index 263d5f4d65f..d9ed4963f8d 100644
--- a/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
+++ b/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
@@ -3,17 +3,20 @@
// found in the LICENSE file.
#include "content/renderer/gpu/delegated_compositor_output_surface.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
namespace content {
DelegatedCompositorOutputSurface::DelegatedCompositorOutputSurface(
int32 routing_id,
uint32 output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
+ const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
: CompositorOutputSurface(routing_id,
output_surface_id,
context_provider,
scoped_ptr<cc::SoftwareOutputDevice>(),
+ swap_frame_message_queue,
true) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
diff --git a/chromium/content/renderer/gpu/delegated_compositor_output_surface.h b/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
index f971f1c5ce4..6edc2d6b36d 100644
--- a/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
+++ b/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
@@ -5,17 +5,20 @@
#ifndef CONTENT_RENDERER_GPU_DELEGATED_COMPOSITOR_OUTPUT_SURFACE_H_
#define CONTENT_RENDERER_GPU_DELEGATED_COMPOSITOR_OUTPUT_SURFACE_H_
+#include "base/memory/ref_counted.h"
#include "content/renderer/gpu/compositor_output_surface.h"
namespace content {
+class FrameSwapMessageQueue;
class DelegatedCompositorOutputSurface : public CompositorOutputSurface {
public:
DelegatedCompositorOutputSurface(
int32 routing_id,
uint32 output_surface_id,
- const scoped_refptr<ContextProviderCommandBuffer>& context_provider);
- virtual ~DelegatedCompositorOutputSurface() {}
+ const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue);
+ ~DelegatedCompositorOutputSurface() override {}
};
} // namespace content
diff --git a/chromium/content/renderer/gpu/frame_swap_message_queue.cc b/chromium/content/renderer/gpu/frame_swap_message_queue.cc
new file mode 100644
index 00000000000..bf91dd84e0f
--- /dev/null
+++ b/chromium/content/renderer/gpu/frame_swap_message_queue.cc
@@ -0,0 +1,201 @@
+// Copyright 2014 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 "content/renderer/gpu/frame_swap_message_queue.h"
+
+#include <limits>
+
+#include "base/containers/hash_tables.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "ipc/ipc_message.h"
+
+using std::vector;
+
+namespace content {
+
+class FrameSwapMessageSubQueue {
+ public:
+ FrameSwapMessageSubQueue() {}
+ virtual ~FrameSwapMessageSubQueue() {}
+ virtual bool Empty() const = 0;
+ virtual void QueueMessage(int source_frame_number,
+ scoped_ptr<IPC::Message> msg,
+ bool* is_first) = 0;
+ virtual void DrainMessages(int source_frame_number,
+ ScopedVector<IPC::Message>* messages) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FrameSwapMessageSubQueue);
+};
+
+namespace {
+
+// Queue specific to MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE.
+class SendMessageScopeImpl : public FrameSwapMessageQueue::SendMessageScope {
+ public:
+ SendMessageScopeImpl(base::Lock* lock) : auto_lock_(*lock) {}
+ ~SendMessageScopeImpl() override {}
+
+ private:
+ base::AutoLock auto_lock_;
+};
+
+class VisualStateQueue : public FrameSwapMessageSubQueue {
+ public:
+ VisualStateQueue() {}
+
+ ~VisualStateQueue() override {
+ for (VisualStateQueueMap::iterator i = queue_.begin(); i != queue_.end();
+ i++) {
+ STLDeleteElements(&i->second);
+ }
+ }
+
+ bool Empty() const override { return queue_.empty(); }
+
+ void QueueMessage(int source_frame_number,
+ scoped_ptr<IPC::Message> msg,
+ bool* is_first) override {
+ if (is_first)
+ *is_first = (queue_.count(source_frame_number) == 0);
+
+ queue_[source_frame_number].push_back(msg.release());
+ }
+
+ void DrainMessages(int source_frame_number,
+ ScopedVector<IPC::Message>* messages) override {
+ VisualStateQueueMap::iterator end = queue_.upper_bound(source_frame_number);
+ for (VisualStateQueueMap::iterator i = queue_.begin(); i != end; i++) {
+ DCHECK(i->first <= source_frame_number);
+ messages->insert(messages->end(), i->second.begin(), i->second.end());
+ i->second.clear();
+ }
+ queue_.erase(queue_.begin(), end);
+ }
+
+ private:
+ typedef std::map<int, std::vector<IPC::Message*> > VisualStateQueueMap;
+ VisualStateQueueMap queue_;
+
+ DISALLOW_COPY_AND_ASSIGN(VisualStateQueue);
+};
+
+// Queue specific to MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP.
+class SwapQueue : public FrameSwapMessageSubQueue {
+ public:
+ SwapQueue() {}
+ bool Empty() const override { return queue_.empty(); }
+
+ void QueueMessage(int source_frame_number,
+ scoped_ptr<IPC::Message> msg,
+ bool* is_first) override {
+ if (is_first)
+ *is_first = Empty();
+ queue_.push_back(msg.release());
+ }
+
+ void DrainMessages(int source_frame_number,
+ ScopedVector<IPC::Message>* messages) override {
+ messages->insert(messages->end(), queue_.begin(), queue_.end());
+ queue_.weak_clear();
+ }
+
+ private:
+ ScopedVector<IPC::Message> queue_;
+
+ DISALLOW_COPY_AND_ASSIGN(SwapQueue);
+};
+
+} // namespace
+
+FrameSwapMessageQueue::FrameSwapMessageQueue()
+ : visual_state_queue_(new VisualStateQueue()),
+ swap_queue_(new SwapQueue()) {
+}
+
+FrameSwapMessageQueue::~FrameSwapMessageQueue() {
+}
+
+bool FrameSwapMessageQueue::Empty() const {
+ base::AutoLock lock(lock_);
+ return next_drain_messages_.empty() && visual_state_queue_->Empty() &&
+ swap_queue_->Empty();
+}
+
+FrameSwapMessageSubQueue* FrameSwapMessageQueue::GetSubQueue(
+ MessageDeliveryPolicy policy) {
+ switch (policy) {
+ case MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP:
+ return swap_queue_.get();
+ break;
+ case MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE:
+ return visual_state_queue_.get();
+ break;
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+void FrameSwapMessageQueue::QueueMessageForFrame(MessageDeliveryPolicy policy,
+ int source_frame_number,
+ scoped_ptr<IPC::Message> msg,
+ bool* is_first) {
+ base::AutoLock lock(lock_);
+ GetSubQueue(policy)->QueueMessage(source_frame_number, msg.Pass(), is_first);
+}
+
+void FrameSwapMessageQueue::DidSwap(int source_frame_number) {
+ base::AutoLock lock(lock_);
+
+ visual_state_queue_->DrainMessages(source_frame_number,
+ &next_drain_messages_);
+}
+
+void FrameSwapMessageQueue::DidNotSwap(int source_frame_number,
+ cc::SwapPromise::DidNotSwapReason reason,
+ ScopedVector<IPC::Message>* messages) {
+ base::AutoLock lock(lock_);
+ switch (reason) {
+ case cc::SwapPromise::SWAP_FAILS:
+ case cc::SwapPromise::COMMIT_NO_UPDATE:
+ swap_queue_->DrainMessages(source_frame_number, messages);
+ // fallthrough
+ case cc::SwapPromise::COMMIT_FAILS:
+ visual_state_queue_->DrainMessages(source_frame_number, messages);
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+void FrameSwapMessageQueue::DrainMessages(
+ ScopedVector<IPC::Message>* messages) {
+ lock_.AssertAcquired();
+
+ swap_queue_->DrainMessages(0, messages);
+ messages->insert(messages->end(),
+ next_drain_messages_.begin(),
+ next_drain_messages_.end());
+ next_drain_messages_.weak_clear();
+}
+
+scoped_ptr<FrameSwapMessageQueue::SendMessageScope>
+FrameSwapMessageQueue::AcquireSendMessageScope() {
+ return make_scoped_ptr(new SendMessageScopeImpl(&lock_));
+}
+
+// static
+void FrameSwapMessageQueue::TransferMessages(ScopedVector<IPC::Message>& source,
+ vector<IPC::Message>* dest) {
+ for (vector<IPC::Message*>::iterator i = source.begin(); i != source.end();
+ ++i) {
+ IPC::Message* m(*i);
+ dest->push_back(*m);
+ delete m;
+ }
+ source.weak_clear();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/gpu/frame_swap_message_queue.h b/chromium/content/renderer/gpu/frame_swap_message_queue.h
new file mode 100644
index 00000000000..6ebaf164243
--- /dev/null
+++ b/chromium/content/renderer/gpu/frame_swap_message_queue.h
@@ -0,0 +1,108 @@
+// Copyright 2014 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 CONTENT_RENDERER_GPU_FRAME_SWAP_MESSAGE_QUEUE_H_
+#define CONTENT_RENDERER_GPU_FRAME_SWAP_MESSAGE_QUEUE_H_
+
+#include <map>
+#include <vector>
+
+#include "base/auto_reset.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/synchronization/lock.h"
+#include "cc/base/swap_promise.h"
+#include "content/common/content_export.h"
+#include "content/renderer/message_delivery_policy.h"
+
+namespace IPC {
+class Message;
+};
+
+namespace content {
+
+class FrameSwapMessageSubQueue;
+
+// Queue used to keep track of which IPC::Messages should be sent along with a
+// particular compositor frame swap.
+class CONTENT_EXPORT FrameSwapMessageQueue
+ : public base::RefCountedThreadSafe<FrameSwapMessageQueue> {
+ public:
+ class CONTENT_EXPORT SendMessageScope {
+ public:
+ virtual ~SendMessageScope() {}
+ };
+
+ FrameSwapMessageQueue();
+
+ // Queues message to be returned on a matching DrainMessages call.
+ //
+ // |policy| determines how messages are matched with DrainMessages calls.
+ // |source_frame_number| frame number to queue |msg| for.
+ // |msg| - message to queue. The method takes ownership of |msg|.
+ // |is_first| - output parameter. Set to true if this was the first message
+ // enqueued for the given source_frame_number.
+ void QueueMessageForFrame(MessageDeliveryPolicy policy,
+ int source_frame_number,
+ scoped_ptr<IPC::Message> msg,
+ bool* is_first);
+
+ // Returns true if there are no messages in the queue.
+ bool Empty() const;
+
+ // Should be called when a successful swap occurs. The messages for that swap
+ // can be obtained by calling DrainMessages.
+ //
+ // |source_frame_number| frame number for which the swap occurred.
+ void DidSwap(int source_frame_number);
+
+ // Should be called when we know a swap will not occur. This also means we
+ // won't be expecting a DrainMessages call.
+ //
+ // |source_frame_number| frame number for which the swap will not occur.
+ // |reason| reason for the which the swap will not occur.
+ // |messages| depending on |reason| it may make sense to deliver certain
+ // messages asynchronously. This vector will contain those
+ // messages.
+ void DidNotSwap(int source_frame_number,
+ cc::SwapPromise::DidNotSwapReason reason,
+ ScopedVector<IPC::Message>* messages);
+
+ // A SendMessageScope object must be held by the caller when this method is
+ // called.
+ //
+ // |messages| vector to store messages, it's not cleared, only appended to.
+ // The method will append messages queued for frame numbers lower
+ // or equal to |source_frame_number|
+ void DrainMessages(ScopedVector<IPC::Message>* messages);
+
+ // SendMessageScope is used to make sure that messages sent from different
+ // threads (impl/main) are scheduled in the right order on the IO threads.
+ //
+ // Returns an object that must be kept in scope till an IPC message containing
+ // |messages| is sent.
+ scoped_ptr<SendMessageScope> AcquireSendMessageScope();
+
+ static void TransferMessages(ScopedVector<IPC::Message>& source,
+ std::vector<IPC::Message>* dest);
+
+ private:
+ friend class base::RefCountedThreadSafe<FrameSwapMessageQueue>;
+
+ FrameSwapMessageSubQueue* GetSubQueue(MessageDeliveryPolicy policy);
+
+ ~FrameSwapMessageQueue();
+
+ mutable base::Lock lock_;
+ scoped_ptr<FrameSwapMessageSubQueue> visual_state_queue_;
+ scoped_ptr<FrameSwapMessageSubQueue> swap_queue_;
+ ScopedVector<IPC::Message> next_drain_messages_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameSwapMessageQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_GPU_FRAME_SWAP_MESSAGE_QUEUE_H_
diff --git a/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc b/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc
new file mode 100644
index 00000000000..0b0ba8d1469
--- /dev/null
+++ b/chromium/content/renderer/gpu/frame_swap_message_queue_unittest.cc
@@ -0,0 +1,291 @@
+// Copyright 2014 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 "content/renderer/gpu/frame_swap_message_queue.h"
+#include "ipc/ipc_message.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class FrameSwapMessageQueueTest : public testing::Test {
+ public:
+ FrameSwapMessageQueueTest()
+ : first_message_(41, 1, IPC::Message::PRIORITY_NORMAL),
+ second_message_(42, 2, IPC::Message::PRIORITY_NORMAL),
+ third_message_(43, 3, IPC::Message::PRIORITY_NORMAL),
+ queue_(new FrameSwapMessageQueue()) {}
+
+ protected:
+ void QueueNextSwapMessage(scoped_ptr<IPC::Message> msg) {
+ queue_->QueueMessageForFrame(
+ MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 0, msg.Pass(), NULL);
+ }
+
+ void QueueNextSwapMessage(scoped_ptr<IPC::Message> msg, bool* first) {
+ queue_->QueueMessageForFrame(
+ MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, 0, msg.Pass(), first);
+ }
+
+ void QueueVisualStateMessage(int source_frame_number,
+ scoped_ptr<IPC::Message> msg) {
+ queue_->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE,
+ source_frame_number,
+ msg.Pass(),
+ NULL);
+ }
+
+ void QueueVisualStateMessage(int source_frame_number,
+ scoped_ptr<IPC::Message> msg,
+ bool* first) {
+ queue_->QueueMessageForFrame(MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE,
+ source_frame_number,
+ msg.Pass(),
+ first);
+ }
+
+ void DrainMessages(int source_frame_number,
+ ScopedVector<IPC::Message>* messages) {
+ messages->clear();
+ queue_->DidSwap(source_frame_number);
+ scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
+ queue_->AcquireSendMessageScope();
+ queue_->DrainMessages(messages);
+ }
+
+ bool HasMessageForId(const ScopedVector<IPC::Message>& messages,
+ int routing_id) {
+ for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
+ i != messages.end();
+ ++i) {
+ if ((*i)->routing_id() == routing_id)
+ return true;
+ }
+ return false;
+ }
+
+ scoped_ptr<IPC::Message> CloneMessage(const IPC::Message& other) {
+ return make_scoped_ptr(new IPC::Message(other)).Pass();
+ }
+
+ void TestDidNotSwap(cc::SwapPromise::DidNotSwapReason reason);
+
+ IPC::Message first_message_;
+ IPC::Message second_message_;
+ IPC::Message third_message_;
+ scoped_refptr<FrameSwapMessageQueue> queue_;
+};
+
+TEST_F(FrameSwapMessageQueueTest, TestEmptyQueueDrain) {
+ ScopedVector<IPC::Message> messages;
+
+ DrainMessages(0, &messages);
+ ASSERT_TRUE(messages.empty());
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestEmpty) {
+ ScopedVector<IPC::Message> messages;
+ ASSERT_TRUE(queue_->Empty());
+ QueueNextSwapMessage(CloneMessage(first_message_));
+ ASSERT_FALSE(queue_->Empty());
+ DrainMessages(0, &messages);
+ ASSERT_TRUE(queue_->Empty());
+ QueueVisualStateMessage(1, CloneMessage(first_message_));
+ ASSERT_FALSE(queue_->Empty());
+ queue_->DidSwap(1);
+ ASSERT_FALSE(queue_->Empty());
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestQueueMessageFirst) {
+ ScopedVector<IPC::Message> messages;
+ bool visual_state_first = false;
+ bool next_swap_first = false;
+
+ // Queuing the first time should result in true.
+ QueueVisualStateMessage(1, CloneMessage(first_message_), &visual_state_first);
+ ASSERT_TRUE(visual_state_first);
+ // Queuing the second time should result in true.
+ QueueVisualStateMessage(
+ 1, CloneMessage(second_message_), &visual_state_first);
+ ASSERT_FALSE(visual_state_first);
+ // Queuing for a different frame should result in true.
+ QueueVisualStateMessage(2, CloneMessage(first_message_), &visual_state_first);
+ ASSERT_TRUE(visual_state_first);
+
+ // Queuing for a different policy should result in true.
+ QueueNextSwapMessage(CloneMessage(first_message_), &next_swap_first);
+ ASSERT_TRUE(next_swap_first);
+ // Second time for the same policy is still false.
+ QueueNextSwapMessage(CloneMessage(first_message_), &next_swap_first);
+ ASSERT_FALSE(next_swap_first);
+
+ DrainMessages(4, &messages);
+ // Queuing after all messages are drained is a true again.
+ QueueVisualStateMessage(4, CloneMessage(first_message_), &visual_state_first);
+ ASSERT_TRUE(visual_state_first);
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestNextSwapMessageSentWithNextFrame) {
+ ScopedVector<IPC::Message> messages;
+
+ DrainMessages(1, &messages);
+ QueueNextSwapMessage(CloneMessage(first_message_));
+ DrainMessages(2, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_EQ(first_message_.routing_id(), messages.front()->routing_id());
+ messages.clear();
+
+ DrainMessages(2, &messages);
+ ASSERT_TRUE(messages.empty());
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestNextSwapMessageSentWithCurrentFrame) {
+ ScopedVector<IPC::Message> messages;
+
+ DrainMessages(1, &messages);
+ QueueNextSwapMessage(CloneMessage(first_message_));
+ DrainMessages(1, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_EQ(first_message_.routing_id(), messages.front()->routing_id());
+ messages.clear();
+
+ DrainMessages(1, &messages);
+ ASSERT_TRUE(messages.empty());
+}
+
+TEST_F(FrameSwapMessageQueueTest,
+ TestDrainsVisualStateMessagesForCorrespondingFrames) {
+ ScopedVector<IPC::Message> messages;
+
+ QueueVisualStateMessage(1, CloneMessage(first_message_));
+ QueueVisualStateMessage(2, CloneMessage(second_message_));
+ QueueVisualStateMessage(3, CloneMessage(third_message_));
+ DrainMessages(0, &messages);
+ ASSERT_TRUE(messages.empty());
+
+ DrainMessages(2, &messages);
+ ASSERT_EQ(2u, messages.size());
+ ASSERT_TRUE(HasMessageForId(messages, first_message_.routing_id()));
+ ASSERT_TRUE(HasMessageForId(messages, second_message_.routing_id()));
+ messages.clear();
+
+ DrainMessages(2, &messages);
+ ASSERT_TRUE(messages.empty());
+
+ DrainMessages(5, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_EQ(third_message_.routing_id(), messages.front()->routing_id());
+}
+
+TEST_F(FrameSwapMessageQueueTest,
+ TestQueueNextSwapMessagePreservesFifoOrdering) {
+ ScopedVector<IPC::Message> messages;
+
+ QueueNextSwapMessage(CloneMessage(first_message_));
+ QueueNextSwapMessage(CloneMessage(second_message_));
+ DrainMessages(1, &messages);
+ ASSERT_EQ(2u, messages.size());
+ ASSERT_EQ(first_message_.routing_id(), messages[0]->routing_id());
+ ASSERT_EQ(second_message_.routing_id(), messages[1]->routing_id());
+}
+
+TEST_F(FrameSwapMessageQueueTest,
+ TestQueueVisualStateMessagePreservesFifoOrdering) {
+ ScopedVector<IPC::Message> messages;
+
+ QueueVisualStateMessage(1, CloneMessage(first_message_));
+ QueueVisualStateMessage(1, CloneMessage(second_message_));
+ DrainMessages(1, &messages);
+ ASSERT_EQ(2u, messages.size());
+ ASSERT_EQ(first_message_.routing_id(), messages[0]->routing_id());
+ ASSERT_EQ(second_message_.routing_id(), messages[1]->routing_id());
+}
+
+void FrameSwapMessageQueueTest::TestDidNotSwap(
+ cc::SwapPromise::DidNotSwapReason reason) {
+ ScopedVector<IPC::Message> messages;
+
+ QueueNextSwapMessage(CloneMessage(first_message_));
+ QueueVisualStateMessage(2, CloneMessage(second_message_));
+ QueueVisualStateMessage(3, CloneMessage(third_message_));
+
+ queue_->DidNotSwap(2, cc::SwapPromise::COMMIT_NO_UPDATE, &messages);
+ ASSERT_EQ(2u, messages.size());
+ ASSERT_TRUE(HasMessageForId(messages, first_message_.routing_id()));
+ ASSERT_TRUE(HasMessageForId(messages, second_message_.routing_id()));
+ messages.clear();
+
+ queue_->DidNotSwap(3, cc::SwapPromise::COMMIT_NO_UPDATE, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_TRUE(HasMessageForId(messages, third_message_.routing_id()));
+ messages.clear();
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapNoUpdate) {
+ TestDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapSwapFails) {
+ TestDidNotSwap(cc::SwapPromise::SWAP_FAILS);
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapCommitFails) {
+ ScopedVector<IPC::Message> messages;
+
+ QueueNextSwapMessage(CloneMessage(first_message_));
+ QueueVisualStateMessage(2, CloneMessage(second_message_));
+ QueueVisualStateMessage(3, CloneMessage(third_message_));
+
+ queue_->DidNotSwap(2, cc::SwapPromise::COMMIT_FAILS, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_TRUE(HasMessageForId(messages, second_message_.routing_id()));
+ messages.clear();
+
+ queue_->DidNotSwap(3, cc::SwapPromise::COMMIT_FAILS, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_TRUE(HasMessageForId(messages, third_message_.routing_id()));
+ messages.clear();
+
+ DrainMessages(1, &messages);
+ ASSERT_EQ(1u, messages.size());
+ ASSERT_TRUE(HasMessageForId(messages, first_message_.routing_id()));
+}
+
+class NotifiesDeletionMessage : public IPC::Message {
+ public:
+ NotifiesDeletionMessage(bool* deleted, const IPC::Message& other)
+ : IPC::Message(other), deleted_(deleted) {}
+ ~NotifiesDeletionMessage() override { *deleted_ = true; }
+
+ private:
+ bool* deleted_;
+};
+
+TEST_F(FrameSwapMessageQueueTest, TestDeletesNextSwapMessage) {
+ bool message_deleted = false;
+ QueueNextSwapMessage(make_scoped_ptr(
+ new NotifiesDeletionMessage(&message_deleted, first_message_)));
+ queue_ = NULL;
+ ASSERT_TRUE(message_deleted);
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestDeletesVisualStateMessage) {
+ bool message_deleted = false;
+ QueueVisualStateMessage(1,
+ make_scoped_ptr(new NotifiesDeletionMessage(
+ &message_deleted, first_message_)));
+ queue_ = NULL;
+ ASSERT_TRUE(message_deleted);
+}
+
+TEST_F(FrameSwapMessageQueueTest, TestDeletesQueuedVisualStateMessage) {
+ bool message_deleted = false;
+ QueueVisualStateMessage(1,
+ make_scoped_ptr(new NotifiesDeletionMessage(
+ &message_deleted, first_message_)));
+ queue_->DidSwap(1);
+ queue_ = NULL;
+ ASSERT_TRUE(message_deleted);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
index f649db91872..f57a9a781e4 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -7,8 +7,8 @@
#include <string>
#include "base/base64.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string_number_conversions.h"
#include "cc/layers/layer.h"
@@ -18,11 +18,16 @@
#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/v8_value_converter.h"
+#include "content/renderer/chrome_object_extensions_utils.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/skia_benchmarking_extension.h"
+#include "gin/arguments.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
#include "third_party/WebKit/public/web/WebImageCache.h"
+#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/skia/include/core/SkData.h"
@@ -40,26 +45,26 @@ using blink::WebPrivatePtr;
using blink::WebSize;
using blink::WebView;
-const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking";
+namespace content {
+
+namespace {
// offset parameter is deprecated/ignored, and will be remove from the
// signature in a future skia release. <reed@google.com>
-static SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
- SkPixelRef* pr = bm.pixelRef();
- if (pr != NULL) {
- SkData* data = pr->refEncodedData();
- if (data != NULL)
- return data;
- }
- std::vector<unsigned char> vector;
- if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
- return SkData::NewWithCopy(&vector.front() , vector.size());
- }
- return NULL;
+SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
+ SkPixelRef* pr = bm.pixelRef();
+ if (pr != NULL) {
+ SkData* data = pr->refEncodedData();
+ if (data != NULL)
+ return data;
+ }
+ std::vector<unsigned char> vector;
+ if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
+ return SkData::NewWithCopy(&vector.front(), vector.size());
+ }
+ return NULL;
}
-namespace {
-
class SkPictureSerializer {
public:
explicit SkPictureSerializer(const base::FilePath& dirpath)
@@ -67,7 +72,7 @@ class SkPictureSerializer {
layer_id_(0) {
// Let skia register known effect subclasses. This basically enables
// reflection on those subclasses required for picture serialization.
- content::SkiaBenchmarking::Initialize();
+ SkiaBenchmarking::Initialize();
}
// Recursively serializes the layer tree.
@@ -100,11 +105,33 @@ class SkPictureSerializer {
int layer_id_;
};
-} // namespace
+template <typename T>
+bool GetArg(gin::Arguments* args, T* value) {
+ if (!args->GetNext(value)) {
+ args->ThrowError();
+ return false;
+ }
+ return true;
+}
-namespace content {
+template <>
+bool GetArg(gin::Arguments* args, int* value) {
+ float number;
+ bool ret = GetArg(args, &number);
+ *value = number;
+ return ret;
+}
-namespace {
+template <typename T>
+bool GetOptionalArg(gin::Arguments* args, T* value) {
+ if (args->PeekNext().IsEmpty())
+ return true;
+ if (args->PeekNext()->IsUndefined()) {
+ args->Skip();
+ return true;
+ }
+ return GetArg(args, value);
+}
class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
public:
@@ -208,720 +235,576 @@ class GpuBenchmarkingContext {
DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
};
-} // namespace
+void OnMicroBenchmarkCompleted(
+ CallbackAndContext* callback_and_context,
+ scoped_ptr<base::Value> result) {
+ v8::Isolate* isolate = callback_and_context->isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::Context> context = callback_and_context->GetContext();
+ v8::Context::Scope context_scope(context);
+ WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
+ if (frame) {
+ scoped_ptr<V8ValueConverter> converter =
+ make_scoped_ptr(V8ValueConverter::create());
+ v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
+ v8::Handle<v8::Value> argv[] = { value };
+
+ frame->callFunctionEvenIfScriptDisabled(
+ callback_and_context->GetCallback(),
+ v8::Object::New(isolate),
+ 1,
+ argv);
+ }
+}
-class GpuBenchmarkingWrapper : public v8::Extension {
- public:
- GpuBenchmarkingWrapper() :
- v8::Extension(kGpuBenchmarkingExtensionName,
- "if (typeof(chrome) == 'undefined') {"
- " chrome = {};"
- "};"
- "if (typeof(chrome.gpuBenchmarking) == 'undefined') {"
- " chrome.gpuBenchmarking = {};"
- "};"
- "chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers = function() {"
- " native function SetNeedsDisplayOnAllLayers();"
- " return SetNeedsDisplayOnAllLayers();"
- "};"
- "chrome.gpuBenchmarking.setRasterizeOnlyVisibleContent = "
- "function() {"
- " native function SetRasterizeOnlyVisibleContent();"
- " return SetRasterizeOnlyVisibleContent();"
- "};"
- "chrome.gpuBenchmarking.printToSkPicture = function(dirname) {"
- " native function PrintToSkPicture();"
- " return PrintToSkPicture(dirname);"
- "};"
- "chrome.gpuBenchmarking.DEFAULT_INPUT = 0;"
- "chrome.gpuBenchmarking.TOUCH_INPUT = 1;"
- "chrome.gpuBenchmarking.MOUSE_INPUT = 2;"
- "chrome.gpuBenchmarking.gestureSourceTypeSupported = "
- " function(gesture_source_type) {"
- " native function GestureSourceTypeSupported();"
- " return GestureSourceTypeSupported(gesture_source_type);"
- "};"
- "chrome.gpuBenchmarking.smoothScrollBy = "
- " function(pixels_to_scroll, opt_callback, opt_start_x,"
- " opt_start_y, opt_gesture_source_type,"
- " opt_direction, opt_speed_in_pixels_s) {"
- " pixels_to_scroll = pixels_to_scroll || 0;"
- " callback = opt_callback || function() { };"
- " gesture_source_type = opt_gesture_source_type ||"
- " chrome.gpuBenchmarking.DEFAULT_INPUT;"
- " direction = opt_direction || 'down';"
- " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
- " native function BeginSmoothScroll();"
- " return BeginSmoothScroll(pixels_to_scroll, callback,"
- " gesture_source_type, direction,"
- " speed_in_pixels_s, true,"
- " opt_start_x, opt_start_y);"
- "};"
- "chrome.gpuBenchmarking.swipe = "
- " function(direction, distance, opt_callback,"
- " opt_start_x, opt_start_y,"
- " opt_speed_in_pixels_s) {"
- " direction = direction || 'up';"
- " distance = distance || 0;"
- " callback = opt_callback || function() { };"
- " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
- " native function BeginSmoothScroll();"
- " return BeginSmoothScroll(-distance, callback,"
- " chrome.gpuBenchmarking.TOUCH_INPUT,"
- " direction, speed_in_pixels_s, false,"
- " opt_start_x, opt_start_y);"
- "};"
- "chrome.gpuBenchmarking.scrollBounce = "
- " function(direction, distance, overscroll, opt_repeat_count,"
- " opt_callback, opt_start_x, opt_start_y,"
- " opt_speed_in_pixels_s) {"
- " direction = direction || 'down';"
- " distance = distance || 0;"
- " overscroll = overscroll || 0;"
- " repeat_count = opt_repeat_count || 1;"
- " callback = opt_callback || function() { };"
- " speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
- " native function BeginScrollBounce();"
- " return BeginScrollBounce(direction, distance, overscroll,"
- " repeat_count, callback,"
- " speed_in_pixels_s,"
- " opt_start_x, opt_start_y);"
- "};"
- // TODO(dominikg): Remove once JS interface changes have rolled into
- // stable.
- "chrome.gpuBenchmarking.newPinchInterface = true;"
- "chrome.gpuBenchmarking.pinchBy = "
- " function(scale_factor, anchor_x, anchor_y,"
- " opt_callback, "
- "opt_relative_pointer_speed_in_pixels_s) {"
- " callback = opt_callback || function() { };"
- " relative_pointer_speed_in_pixels_s ="
- " opt_relative_pointer_speed_in_pixels_s || 800;"
- " native function BeginPinch();"
- " return BeginPinch(scale_factor, anchor_x, anchor_y, callback,"
- " relative_pointer_speed_in_pixels_s);"
- "};"
- "chrome.gpuBenchmarking.tap = "
- " function(position_x, position_y, opt_callback, "
- "opt_duration_ms,"
- " opt_gesture_source_type) {"
- " callback = opt_callback || function() { };"
- " duration_ms = opt_duration_ms || 50;"
- " gesture_source_type = opt_gesture_source_type ||"
- " chrome.gpuBenchmarking.DEFAULT_INPUT;"
- " native function BeginTap();"
- " return BeginTap(position_x, position_y, callback, duration_ms,"
- " gesture_source_type);"
- "};"
- "chrome.gpuBenchmarking.beginWindowSnapshotPNG = "
- "function(callback) {"
- " native function BeginWindowSnapshotPNG();"
- " BeginWindowSnapshotPNG(callback);"
- "};"
- "chrome.gpuBenchmarking.clearImageCache = function() {"
- " native function ClearImageCache();"
- " ClearImageCache();"
- "};"
- "chrome.gpuBenchmarking.runMicroBenchmark ="
- " function(name, callback, opt_arguments) {"
- " arguments = opt_arguments || {};"
- " native function RunMicroBenchmark();"
- " return RunMicroBenchmark(name, callback, arguments);"
- "};"
- "chrome.gpuBenchmarking.sendMessageToMicroBenchmark ="
- " function(id, arguments) {"
- " native function SendMessageToMicroBenchmark();"
- " return SendMessageToMicroBenchmark(id, arguments);"
- "};"
- "chrome.gpuBenchmarking.hasGpuProcess = function() {"
- " native function HasGpuProcess();"
- " return HasGpuProcess();"
- "};") {}
-
- virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
- v8::Isolate* isolate,
- v8::Handle<v8::String> name) OVERRIDE {
- if (name->Equals(
- v8::String::NewFromUtf8(isolate, "SetNeedsDisplayOnAllLayers")))
- return v8::FunctionTemplate::New(isolate, SetNeedsDisplayOnAllLayers);
- if (name->Equals(
- v8::String::NewFromUtf8(isolate, "SetRasterizeOnlyVisibleContent")))
- return v8::FunctionTemplate::New(isolate, SetRasterizeOnlyVisibleContent);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "PrintToSkPicture")))
- return v8::FunctionTemplate::New(isolate, PrintToSkPicture);
- if (name->Equals(
- v8::String::NewFromUtf8(isolate, "GestureSourceTypeSupported")))
- return v8::FunctionTemplate::New(isolate, GestureSourceTypeSupported);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginSmoothScroll")))
- return v8::FunctionTemplate::New(isolate, BeginSmoothScroll);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginScrollBounce")))
- return v8::FunctionTemplate::New(isolate, BeginScrollBounce);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginPinch")))
- return v8::FunctionTemplate::New(isolate, BeginPinch);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginTap")))
- return v8::FunctionTemplate::New(isolate, BeginTap);
- if (name->Equals(
- v8::String::NewFromUtf8(isolate, "BeginWindowSnapshotPNG")))
- return v8::FunctionTemplate::New(isolate, BeginWindowSnapshotPNG);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "ClearImageCache")))
- return v8::FunctionTemplate::New(isolate, ClearImageCache);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "RunMicroBenchmark")))
- return v8::FunctionTemplate::New(isolate, RunMicroBenchmark);
- if (name->Equals(
- v8::String::NewFromUtf8(isolate, "SendMessageToMicroBenchmark")))
- return v8::FunctionTemplate::New(isolate, SendMessageToMicroBenchmark);
- if (name->Equals(v8::String::NewFromUtf8(isolate, "HasGpuProcess")))
- return v8::FunctionTemplate::New(isolate, HasGpuProcess);
-
- return v8::Handle<v8::FunctionTemplate>();
- }
-
- static void SetNeedsDisplayOnAllLayers(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(true))
- return;
+void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
+ const gfx::Size& size,
+ const std::vector<unsigned char>& png) {
+ v8::Isolate* isolate = callback_and_context->isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::Context> context = callback_and_context->GetContext();
+ v8::Context::Scope context_scope(context);
+ WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
+ if (frame) {
+ v8::Handle<v8::Value> result;
+
+ if (!size.IsEmpty()) {
+ v8::Handle<v8::Object> result_object;
+ result_object = v8::Object::New(isolate);
+
+ result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
+ v8::Number::New(isolate, size.width()));
+ result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
+ v8::Number::New(isolate, size.height()));
+
+ std::string base64_png;
+ base::Base64Encode(
+ base::StringPiece(reinterpret_cast<const char*>(&*png.begin()),
+ png.size()),
+ &base64_png);
+
+ result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
+ v8::String::NewFromUtf8(isolate,
+ base64_png.c_str(),
+ v8::String::kNormalString,
+ base64_png.size()));
+
+ result = result_object;
+ } else {
+ result = v8::Null(isolate);
+ }
- context.compositor()->SetNeedsDisplayOnAllLayers();
+ v8::Handle<v8::Value> argv[] = {result};
+
+ frame->callFunctionEvenIfScriptDisabled(
+ callback_and_context->GetCallback(), v8::Object::New(isolate), 1, argv);
}
+}
- static void SetRasterizeOnlyVisibleContent(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(true))
- return;
+void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
+ v8::Isolate* isolate = callback_and_context->isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::Context> context = callback_and_context->GetContext();
+ v8::Context::Scope context_scope(context);
+ WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
+ if (frame) {
+ frame->callFunctionEvenIfScriptDisabled(
+ callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
+ }
+}
- context.compositor()->SetRasterizeOnlyVisibleContent();
+bool BeginSmoothScroll(v8::Isolate* isolate,
+ int pixels_to_scroll,
+ v8::Handle<v8::Function> callback,
+ int gesture_source_type,
+ const std::string& direction,
+ int speed_in_pixels_s,
+ bool prevent_fling,
+ int start_x,
+ int start_y) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return false;
+
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(
+ isolate, callback, context.web_frame()->mainWorldScriptContext());
+
+ scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
+ new SyntheticSmoothScrollGestureParams);
+
+ // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+ float page_scale_factor = context.web_view()->pageScaleFactor();
+
+ if (gesture_source_type < 0 ||
+ gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+ return false;
+ }
+ gesture_params->gesture_source_type =
+ static_cast<SyntheticGestureParams::GestureSourceType>(
+ gesture_source_type);
+
+ gesture_params->speed_in_pixels_s = speed_in_pixels_s;
+ gesture_params->prevent_fling = prevent_fling;
+
+ gesture_params->anchor.SetPoint(start_x * page_scale_factor,
+ start_y * page_scale_factor);
+
+ int distance_length = pixels_to_scroll * page_scale_factor;
+ gfx::Vector2d distance;
+ if (direction == "down")
+ distance.set_y(-distance_length);
+ else if (direction == "up")
+ distance.set_y(distance_length);
+ else if (direction == "right")
+ distance.set_x(-distance_length);
+ else if (direction == "left")
+ distance.set_x(distance_length);
+ else {
+ return false;
}
+ gesture_params->distances.push_back(distance);
- static void PrintToSkPicture(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 1)
- return;
+ // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+ // progress, we will leak the callback and context. This needs to be fixed,
+ // somehow.
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.Pass(),
+ base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
- v8::String::Utf8Value dirname(args[0]);
- if (dirname.length() == 0)
- return;
+ return true;
+}
- GpuBenchmarkingContext context;
- if (!context.Init(true))
- return;
+} // namespace
- const cc::Layer* root_layer = context.compositor()->GetRootLayer();
- if (!root_layer)
- return;
+gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
- base::FilePath dirpath(
- base::FilePath::StringType(*dirname, *dirname + dirname.length()));
- if (!base::CreateDirectory(dirpath) ||
- !base::PathIsWritable(dirpath)) {
- std::string msg("Path is not writable: ");
- msg.append(dirpath.MaybeAsASCII());
- v8::Isolate* isolate = args.GetIsolate();
- isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
- isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
- return;
- }
+// static
+void GpuBenchmarking::Install(blink::WebFrame* frame) {
+ v8::Isolate* isolate = blink::mainThreadIsolate();
+ v8::HandleScope handle_scope(isolate);
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ if (context.IsEmpty())
+ return;
- SkPictureSerializer serializer(dirpath);
- serializer.Serialize(root_layer);
- }
-
- static void OnSyntheticGestureCompleted(
- CallbackAndContext* callback_and_context) {
- v8::Isolate* isolate = callback_and_context->isolate();
- v8::HandleScope scope(isolate);
- v8::Handle<v8::Context> context = callback_and_context->GetContext();
- v8::Context::Scope context_scope(context);
- WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
- if (frame) {
- frame->callFunctionEvenIfScriptDisabled(
- callback_and_context->GetCallback(),
- v8::Object::New(isolate),
- 0,
- NULL);
- }
- }
+ v8::Context::Scope context_scope(context);
- static void GestureSourceTypeSupported(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- if (args.Length() != 1 || !args[0]->IsNumber()) {
- args.GetReturnValue().Set(false);
- return;
- }
+ gin::Handle<GpuBenchmarking> controller =
+ gin::CreateHandle(isolate, new GpuBenchmarking());
+ if (controller.IsEmpty())
+ return;
- int gesture_source_type = args[0]->IntegerValue();
- if (gesture_source_type < 0 ||
- gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
- args.GetReturnValue().Set(false);
- return;
- }
+ v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
+ context->Global());
+ chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
+}
- bool is_supported = SyntheticGestureParams::IsGestureSourceTypeSupported(
- static_cast<SyntheticGestureParams::GestureSourceType>(
- gesture_source_type));
- args.GetReturnValue().Set(is_supported);
- }
+GpuBenchmarking::GpuBenchmarking() {
+}
- static void BeginSmoothScroll(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(false))
- return;
+GpuBenchmarking::~GpuBenchmarking() {
+}
- // The last two arguments can be undefined. We check their validity later.
- int arglen = args.Length();
- if (arglen < 8 ||
- !args[0]->IsNumber() ||
- !args[1]->IsFunction() ||
- !args[2]->IsNumber() ||
- !args[3]->IsString() ||
- !args[4]->IsNumber() ||
- !args[5]->IsBoolean()) {
- args.GetReturnValue().Set(false);
- return;
- }
+gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
+ v8::Isolate* isolate) {
+ return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
+ .SetMethod("setNeedsDisplayOnAllLayers",
+ &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
+ .SetMethod("setRasterizeOnlyVisibleContent",
+ &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
+ .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
+ .SetValue("DEFAULT_INPUT", 0)
+ .SetValue("TOUCH_INPUT", 1)
+ .SetValue("MOUSE_INPUT", 2)
+ .SetMethod("gestureSourceTypeSupported",
+ &GpuBenchmarking::GestureSourceTypeSupported)
+ .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
+ .SetMethod("swipe", &GpuBenchmarking::Swipe)
+ .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
+ // TODO(dominikg): Remove once JS interface changes have rolled into
+ // stable.
+ .SetValue("newPinchInterface", true)
+ .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
+ .SetMethod("tap", &GpuBenchmarking::Tap)
+ .SetMethod("beginWindowSnapshotPNG",
+ &GpuBenchmarking::BeginWindowSnapshotPNG)
+ .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
+ .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
+ .SetMethod("sendMessageToMicroBenchmark",
+ &GpuBenchmarking::SendMessageToMicroBenchmark)
+ .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
+}
- v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[1]);
+void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return;
- scoped_refptr<CallbackAndContext> callback_and_context =
- new CallbackAndContext(args.GetIsolate(),
- callback_local,
- context.web_frame()->mainWorldScriptContext());
+ context.compositor()->SetNeedsDisplayOnAllLayers();
+}
- scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
- new SyntheticSmoothScrollGestureParams);
+void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return;
- // Convert coordinates from CSS pixels to density independent pixels (DIPs).
- float page_scale_factor = context.web_view()->pageScaleFactor();
+ context.compositor()->SetRasterizeOnlyVisibleContent();
+}
- int gesture_source_type = args[2]->IntegerValue();
- if (gesture_source_type < 0 ||
- gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
- args.GetReturnValue().Set(false);
- return;
- }
- gesture_params->gesture_source_type =
- static_cast<SyntheticGestureParams::GestureSourceType>(
- gesture_source_type);
-
- gesture_params->speed_in_pixels_s = args[4]->IntegerValue();
- gesture_params->prevent_fling = args[5]->BooleanValue();
-
- // Account for the 2 optional arguments, start_x and start_y.
- gfx::Point anchor;
- if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
- blink::WebRect rect = context.render_view_impl()->windowRect();
- anchor.SetPoint(rect.width / 2, rect.height / 2);
- } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
- anchor.SetPoint(args[6]->IntegerValue() * page_scale_factor,
- args[7]->IntegerValue() * page_scale_factor);
- } else {
- args.GetReturnValue().Set(false);
- return;
- }
- gesture_params->anchor = anchor;
-
- int distance_length = args[0]->IntegerValue() * page_scale_factor;
- gfx::Vector2d distance;
- v8::String::Utf8Value direction(args[3]);
- DCHECK(*direction);
- std::string direction_str(*direction);
- if (direction_str == "down")
- distance.set_y(-distance_length);
- else if (direction_str == "up")
- distance.set_y(distance_length);
- else if (direction_str == "right")
- distance.set_x(-distance_length);
- else if (direction_str == "left")
- distance.set_x(distance_length);
- else {
- args.GetReturnValue().Set(false);
- return;
- }
- gesture_params->distances.push_back(distance);
+void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
+ const std::string& dirname) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return;
+
+ const cc::Layer* root_layer = context.compositor()->GetRootLayer();
+ if (!root_layer)
+ return;
+
+ base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
+ if (!base::CreateDirectory(dirpath) ||
+ !base::PathIsWritable(dirpath)) {
+ std::string msg("Path is not writable: ");
+ msg.append(dirpath.MaybeAsASCII());
+ isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
+ isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
+ return;
+ }
- // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
- // progress, we will leak the callback and context. This needs to be fixed,
- // somehow.
- context.render_view_impl()->QueueSyntheticGesture(
- gesture_params.PassAs<SyntheticGestureParams>(),
- base::Bind(&OnSyntheticGestureCompleted,
- callback_and_context));
+ SkPictureSerializer serializer(dirpath);
+ serializer.Serialize(root_layer);
+}
- args.GetReturnValue().Set(true);
+bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
+ if (gesture_source_type < 0 ||
+ gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+ return false;
}
- static void BeginScrollBounce(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(false))
- return;
+ return SyntheticGestureParams::IsGestureSourceTypeSupported(
+ static_cast<SyntheticGestureParams::GestureSourceType>(
+ gesture_source_type));
+}
- // The last two arguments can be undefined. We check their validity later.
- int arglen = args.Length();
- if (arglen < 8 ||
- !args[0]->IsString() ||
- !args[1]->IsNumber() ||
- !args[2]->IsNumber() ||
- !args[3]->IsNumber() ||
- !args[4]->IsFunction() ||
- !args[5]->IsNumber()) {
- args.GetReturnValue().Set(false);
- return;
- }
+bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return false;
+
+ float page_scale_factor = context.web_view()->pageScaleFactor();
+ blink::WebRect rect = context.render_view_impl()->windowRect();
+
+ int pixels_to_scroll = 0;
+ v8::Handle<v8::Function> callback;
+ int start_x = rect.width / (page_scale_factor * 2);
+ int start_y = rect.height / (page_scale_factor * 2);
+ int gesture_source_type = 0; // DEFAULT_INPUT
+ std::string direction = "down";
+ int speed_in_pixels_s = 800;
+
+ if (!GetOptionalArg(args, &pixels_to_scroll) ||
+ !GetOptionalArg(args, &callback) ||
+ !GetOptionalArg(args, &start_x) ||
+ !GetOptionalArg(args, &start_y) ||
+ !GetOptionalArg(args, &gesture_source_type) ||
+ !GetOptionalArg(args, &direction) ||
+ !GetOptionalArg(args, &speed_in_pixels_s)) {
+ return false;
+ }
- v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[4]);
+ return BeginSmoothScroll(args->isolate(),
+ pixels_to_scroll,
+ callback,
+ gesture_source_type,
+ direction,
+ speed_in_pixels_s,
+ true,
+ start_x,
+ start_y);
+}
- scoped_refptr<CallbackAndContext> callback_and_context =
- new CallbackAndContext(args.GetIsolate(),
- callback_local,
- context.web_frame()->mainWorldScriptContext());
+bool GpuBenchmarking::Swipe(gin::Arguments* args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return false;
+
+ float page_scale_factor = context.web_view()->pageScaleFactor();
+ blink::WebRect rect = context.render_view_impl()->windowRect();
+
+ std::string direction = "up";
+ int pixels_to_scroll = 0;
+ v8::Handle<v8::Function> callback;
+ int start_x = rect.width / (page_scale_factor * 2);
+ int start_y = rect.height / (page_scale_factor * 2);
+ int speed_in_pixels_s = 800;
+
+ if (!GetOptionalArg(args, &direction) ||
+ !GetOptionalArg(args, &pixels_to_scroll) ||
+ !GetOptionalArg(args, &callback) ||
+ !GetOptionalArg(args, &start_x) ||
+ !GetOptionalArg(args, &start_y) ||
+ !GetOptionalArg(args, &speed_in_pixels_s)) {
+ return false;
+ }
- scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
- new SyntheticSmoothScrollGestureParams);
+ return BeginSmoothScroll(args->isolate(),
+ -pixels_to_scroll,
+ callback,
+ 1, // TOUCH_INPUT
+ direction,
+ speed_in_pixels_s,
+ false,
+ start_x,
+ start_y);
+}
- // Convert coordinates from CSS pixels to density independent pixels (DIPs).
- float page_scale_factor = context.web_view()->pageScaleFactor();
+bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return false;
+
+ float page_scale_factor = context.web_view()->pageScaleFactor();
+ blink::WebRect rect = context.render_view_impl()->windowRect();
+
+ std::string direction = "down";
+ int distance_length = 0;
+ int overscroll_length = 0;
+ int repeat_count = 1;
+ v8::Handle<v8::Function> callback;
+ int start_x = rect.width / (page_scale_factor * 2);
+ int start_y = rect.height / (page_scale_factor * 2);
+ int speed_in_pixels_s = 800;
+
+ if (!GetOptionalArg(args, &direction) ||
+ !GetOptionalArg(args, &distance_length) ||
+ !GetOptionalArg(args, &overscroll_length) ||
+ !GetOptionalArg(args, &repeat_count) ||
+ !GetOptionalArg(args, &callback) ||
+ !GetOptionalArg(args, &start_x) ||
+ !GetOptionalArg(args, &start_y) ||
+ !GetOptionalArg(args, &speed_in_pixels_s)) {
+ return false;
+ }
- gesture_params->speed_in_pixels_s = args[5]->IntegerValue();
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(args->isolate(),
+ callback,
+ context.web_frame()->mainWorldScriptContext());
+
+ scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
+ new SyntheticSmoothScrollGestureParams);
+
+ gesture_params->speed_in_pixels_s = speed_in_pixels_s;
+
+ gesture_params->anchor.SetPoint(start_x * page_scale_factor,
+ start_y * page_scale_factor);
+
+ distance_length *= page_scale_factor;
+ overscroll_length *= page_scale_factor;
+ gfx::Vector2d distance;
+ gfx::Vector2d overscroll;
+ if (direction == "down") {
+ distance.set_y(-distance_length);
+ overscroll.set_y(overscroll_length);
+ } else if (direction == "up") {
+ distance.set_y(distance_length);
+ overscroll.set_y(-overscroll_length);
+ } else if (direction == "right") {
+ distance.set_x(-distance_length);
+ overscroll.set_x(overscroll_length);
+ } else if (direction == "left") {
+ distance.set_x(distance_length);
+ overscroll.set_x(-overscroll_length);
+ } else {
+ return false;
+ }
- // Account for the 2 optional arguments, start_x and start_y.
- gfx::Point start;
- if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
- blink::WebRect rect = context.render_view_impl()->windowRect();
- start.SetPoint(rect.width / 2, rect.height / 2);
- } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
- start.SetPoint(args[6]->IntegerValue() * page_scale_factor,
- args[7]->IntegerValue() * page_scale_factor);
- } else {
- args.GetReturnValue().Set(false);
- return;
- }
+ for (int i = 0; i < repeat_count; i++) {
+ gesture_params->distances.push_back(distance);
+ gesture_params->distances.push_back(-distance + overscroll);
+ }
- int distance_length = args[1]->IntegerValue() * page_scale_factor;
- int overscroll_length = args[2]->IntegerValue() * page_scale_factor;
- gfx::Vector2d distance;
- gfx::Vector2d overscroll;
- v8::String::Utf8Value direction(args[0]);
- DCHECK(*direction);
- std::string direction_str(*direction);
- if (direction_str == "down") {
- distance.set_y(-distance_length);
- overscroll.set_y(overscroll_length);
- }
- else if (direction_str == "up") {
- distance.set_y(distance_length);
- overscroll.set_y(-overscroll_length);
- }
- else if (direction_str == "right") {
- distance.set_x(-distance_length);
- overscroll.set_x(overscroll_length);
- }
- else if (direction_str == "left") {
- distance.set_x(distance_length);
- overscroll.set_x(-overscroll_length);
- }
- else {
- args.GetReturnValue().Set(false);
- return;
- }
+ // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+ // progress, we will leak the callback and context. This needs to be fixed,
+ // somehow.
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.Pass(),
+ base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
- int repeat_count = args[3]->IntegerValue();
- gesture_params->anchor = start;
- for (int i = 0; i < repeat_count; i++) {
- gesture_params->distances.push_back(distance);
- gesture_params->distances.push_back(-distance + overscroll);
- }
+ return true;
+}
- // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
- // progress, we will leak the callback and context. This needs to be fixed,
- // somehow.
- context.render_view_impl()->QueueSyntheticGesture(
- gesture_params.PassAs<SyntheticGestureParams>(),
- base::Bind(&OnSyntheticGestureCompleted,
- callback_and_context));
+bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return false;
- args.GetReturnValue().Set(true);
- }
+ float scale_factor;
+ int anchor_x;
+ int anchor_y;
+ v8::Handle<v8::Function> callback;
+ int relative_pointer_speed_in_pixels_s = 800;
- static void BeginPinch(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(false))
- return;
- int arglen = args.Length();
- if (arglen < 5 ||
- !args[0]->IsNumber() ||
- !args[1]->IsNumber() ||
- !args[2]->IsNumber() ||
- !args[3]->IsFunction() ||
- !args[4]->IsNumber()) {
- args.GetReturnValue().Set(false);
- return;
- }
+ if (!GetArg(args, &scale_factor) ||
+ !GetArg(args, &anchor_x) ||
+ !GetArg(args, &anchor_y) ||
+ !GetOptionalArg(args, &callback) ||
+ !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
+ return false;
+ }
- scoped_ptr<SyntheticPinchGestureParams> gesture_params(
- new SyntheticPinchGestureParams);
+ scoped_ptr<SyntheticPinchGestureParams> gesture_params(
+ new SyntheticPinchGestureParams);
- // Convert coordinates from CSS pixels to density independent pixels (DIPs).
- float page_scale_factor = context.web_view()->pageScaleFactor();
+ // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+ float page_scale_factor = context.web_view()->pageScaleFactor();
- gesture_params->scale_factor = args[0]->NumberValue();
- gesture_params->anchor.SetPoint(
- args[1]->IntegerValue() * page_scale_factor,
- args[2]->IntegerValue() * page_scale_factor);
- gesture_params->relative_pointer_speed_in_pixels_s =
- args[4]->IntegerValue();
+ gesture_params->scale_factor = scale_factor;
+ gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
+ anchor_y * page_scale_factor);
+ gesture_params->relative_pointer_speed_in_pixels_s =
+ relative_pointer_speed_in_pixels_s;
- v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[3]);
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(args->isolate(),
+ callback,
+ context.web_frame()->mainWorldScriptContext());
- scoped_refptr<CallbackAndContext> callback_and_context =
- new CallbackAndContext(args.GetIsolate(),
- callback_local,
- context.web_frame()->mainWorldScriptContext());
+ // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+ // progress, we will leak the callback and context. This needs to be fixed,
+ // somehow.
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.Pass(),
+ base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
- // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
- // progress, we will leak the callback and context. This needs to be fixed,
- // somehow.
- context.render_view_impl()->QueueSyntheticGesture(
- gesture_params.PassAs<SyntheticGestureParams>(),
- base::Bind(&OnSyntheticGestureCompleted,
- callback_and_context));
+ return true;
+}
- args.GetReturnValue().Set(true);
+bool GpuBenchmarking::Tap(gin::Arguments* args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return false;
+
+ int position_x;
+ int position_y;
+ v8::Handle<v8::Function> callback;
+ int duration_ms = 50;
+ int gesture_source_type = 0; // DEFAULT_INPUT
+
+ if (!GetArg(args, &position_x) ||
+ !GetArg(args, &position_y) ||
+ !GetOptionalArg(args, &callback) ||
+ !GetOptionalArg(args, &duration_ms) ||
+ !GetOptionalArg(args, &gesture_source_type)) {
+ return false;
}
- static void BeginTap(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(false))
- return;
-
- int arglen = args.Length();
- if (arglen < 5 ||
- !args[0]->IsNumber() ||
- !args[1]->IsNumber() ||
- !args[2]->IsFunction() ||
- !args[3]->IsNumber() ||
- !args[4]->IsNumber()) {
- args.GetReturnValue().Set(false);
- return;
- }
-
- scoped_ptr<SyntheticTapGestureParams> gesture_params(
- new SyntheticTapGestureParams);
+ scoped_ptr<SyntheticTapGestureParams> gesture_params(
+ new SyntheticTapGestureParams);
- // Convert coordinates from CSS pixels to density independent pixels (DIPs).
- float page_scale_factor = context.web_view()->pageScaleFactor();
+ // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+ float page_scale_factor = context.web_view()->pageScaleFactor();
- gesture_params->position.SetPoint(
- args[0]->IntegerValue() * page_scale_factor,
- args[1]->IntegerValue() * page_scale_factor);
- gesture_params->duration_ms = args[3]->IntegerValue();
+ gesture_params->position.SetPoint(position_x * page_scale_factor,
+ position_y * page_scale_factor);
+ gesture_params->duration_ms = duration_ms;
- int gesture_source_type = args[4]->IntegerValue();
- if (gesture_source_type < 0 ||
- gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
- args.GetReturnValue().Set(false);
- return;
- }
- gesture_params->gesture_source_type =
- static_cast<SyntheticGestureParams::GestureSourceType>(
- gesture_source_type);
-
- v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[2]);
-
- scoped_refptr<CallbackAndContext> callback_and_context =
- new CallbackAndContext(args.GetIsolate(),
- callback_local,
- context.web_frame()->mainWorldScriptContext());
-
-
- // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
- // progress, we will leak the callback and context. This needs to be fixed,
- // somehow.
- context.render_view_impl()->QueueSyntheticGesture(
- gesture_params.PassAs<SyntheticGestureParams>(),
- base::Bind(&OnSyntheticGestureCompleted,
- callback_and_context));
-
- args.GetReturnValue().Set(true);
- }
-
- static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
- const gfx::Size& size,
- const std::vector<unsigned char>& png) {
- v8::Isolate* isolate = callback_and_context->isolate();
- v8::HandleScope scope(isolate);
- v8::Handle<v8::Context> context = callback_and_context->GetContext();
- v8::Context::Scope context_scope(context);
- WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
- if (frame) {
-
- v8::Handle<v8::Value> result;
-
- if(!size.IsEmpty()) {
- v8::Handle<v8::Object> result_object;
- result_object = v8::Object::New(isolate);
-
- result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
- v8::Number::New(isolate, size.width()));
- result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
- v8::Number::New(isolate, size.height()));
-
- std::string base64_png;
- base::Base64Encode(base::StringPiece(
- reinterpret_cast<const char*>(&*png.begin()), png.size()),
- &base64_png);
-
- result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
- v8::String::NewFromUtf8(isolate,
- base64_png.c_str(),
- v8::String::kNormalString,
- base64_png.size()));
-
- result = result_object;
- } else {
- result = v8::Null(isolate);
- }
-
- v8::Handle<v8::Value> argv[] = { result };
-
- frame->callFunctionEvenIfScriptDisabled(
- callback_and_context->GetCallback(),
- v8::Object::New(isolate),
- 1,
- argv);
- }
+ if (gesture_source_type < 0 ||
+ gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+ return false;
}
+ gesture_params->gesture_source_type =
+ static_cast<SyntheticGestureParams::GestureSourceType>(
+ gesture_source_type);
+
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(args->isolate(),
+ callback,
+ context.web_frame()->mainWorldScriptContext());
+
+ // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+ // progress, we will leak the callback and context. This needs to be fixed,
+ // somehow.
+ context.render_view_impl()->QueueSyntheticGesture(
+ gesture_params.Pass(),
+ base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+
+ return true;
+}
- static void BeginWindowSnapshotPNG(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(false))
- return;
-
- if (!args[0]->IsFunction())
- return;
-
- v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[0]);
-
- scoped_refptr<CallbackAndContext> callback_and_context =
- new CallbackAndContext(args.GetIsolate(),
- callback_local,
- context.web_frame()->mainWorldScriptContext());
-
- context.render_view_impl()->GetWindowSnapshot(
- base::Bind(&OnSnapshotCompleted, callback_and_context));
- }
-
- static void ClearImageCache(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- WebImageCache::clear();
- }
-
- static void OnMicroBenchmarkCompleted(
- CallbackAndContext* callback_and_context,
- scoped_ptr<base::Value> result) {
- v8::Isolate* isolate = callback_and_context->isolate();
- v8::HandleScope scope(isolate);
- v8::Handle<v8::Context> context = callback_and_context->GetContext();
- v8::Context::Scope context_scope(context);
- WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
- if (frame) {
- scoped_ptr<V8ValueConverter> converter =
- make_scoped_ptr(V8ValueConverter::create());
- v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
- v8::Handle<v8::Value> argv[] = { value };
-
- frame->callFunctionEvenIfScriptDisabled(
- callback_and_context->GetCallback(),
- v8::Object::New(isolate),
- 1,
- argv);
- }
- }
+void GpuBenchmarking::BeginWindowSnapshotPNG(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Function> callback) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return;
- static void RunMicroBenchmark(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(true)) {
- args.GetReturnValue().Set(0);
- return;
- }
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(isolate,
+ callback,
+ context.web_frame()->mainWorldScriptContext());
- if (args.Length() != 3 ||
- !args[0]->IsString() ||
- !args[1]->IsFunction() ||
- !args[2]->IsObject()) {
- args.GetReturnValue().Set(0);
- return;
- }
+ context.render_view_impl()->GetWindowSnapshot(
+ base::Bind(&OnSnapshotCompleted, callback_and_context));
+}
- v8::Local<v8::Function> callback_local =
- v8::Local<v8::Function>::Cast(args[1]);
+void GpuBenchmarking::ClearImageCache() {
+ WebImageCache::clear();
+}
- scoped_refptr<CallbackAndContext> callback_and_context =
- new CallbackAndContext(args.GetIsolate(),
- callback_local,
- context.web_frame()->mainWorldScriptContext());
+int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return 0;
- scoped_ptr<V8ValueConverter> converter =
- make_scoped_ptr(V8ValueConverter::create());
- v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
- scoped_ptr<base::Value> value =
- make_scoped_ptr(converter->FromV8Value(args[2], v8_context));
-
- v8::String::Utf8Value benchmark(args[0]);
- DCHECK(*benchmark);
- args.GetReturnValue().Set(context.compositor()->ScheduleMicroBenchmark(
- std::string(*benchmark),
- value.Pass(),
- base::Bind(&OnMicroBenchmarkCompleted, callback_and_context)));
- }
-
- static void SendMessageToMicroBenchmark(
- const v8::FunctionCallbackInfo<v8::Value>& args) {
- GpuBenchmarkingContext context;
- if (!context.Init(true)) {
- args.GetReturnValue().Set(0);
- return;
- }
+ std::string name;
+ v8::Handle<v8::Function> callback;
+ v8::Handle<v8::Object> arguments;
- if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsObject()) {
- args.GetReturnValue().Set(0);
- return;
- }
+ if (!GetArg(args, &name) || !GetArg(args, &callback) ||
+ !GetOptionalArg(args, &arguments)) {
+ return 0;
+ }
- scoped_ptr<V8ValueConverter> converter =
- make_scoped_ptr(V8ValueConverter::create());
- v8::Handle<v8::Context> v8_context =
- context.web_frame()->mainWorldScriptContext();
- scoped_ptr<base::Value> value =
- make_scoped_ptr(converter->FromV8Value(args[1], v8_context));
+ scoped_refptr<CallbackAndContext> callback_and_context =
+ new CallbackAndContext(args->isolate(),
+ callback,
+ context.web_frame()->mainWorldScriptContext());
+
+ scoped_ptr<V8ValueConverter> converter =
+ make_scoped_ptr(V8ValueConverter::create());
+ v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
+ scoped_ptr<base::Value> value =
+ make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
+
+ return context.compositor()->ScheduleMicroBenchmark(
+ name,
+ value.Pass(),
+ base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
+}
- int id = 0;
- converter->FromV8Value(args[0], v8_context)->GetAsInteger(&id);
- args.GetReturnValue().Set(
- context.compositor()->SendMessageToMicroBenchmark(id, value.Pass()));
- }
+bool GpuBenchmarking::SendMessageToMicroBenchmark(
+ int id,
+ v8::Handle<v8::Object> message) {
+ GpuBenchmarkingContext context;
+ if (!context.Init(true))
+ return false;
+
+ scoped_ptr<V8ValueConverter> converter =
+ make_scoped_ptr(V8ValueConverter::create());
+ v8::Handle<v8::Context> v8_context =
+ context.web_frame()->mainWorldScriptContext();
+ scoped_ptr<base::Value> value =
+ make_scoped_ptr(converter->FromV8Value(message, v8_context));
+
+ return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
+}
- static void HasGpuProcess(const v8::FunctionCallbackInfo<v8::Value>& args) {
+bool GpuBenchmarking::HasGpuProcess() {
GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
- args.GetReturnValue().Set(!!gpu_channel);
- }
-};
-
-v8::Extension* GpuBenchmarkingExtension::Get() {
- return new GpuBenchmarkingWrapper();
+ return !!gpu_channel;
}
} // namespace content
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
index d2fe38cc3dc..d4736dd840e 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
@@ -5,16 +5,58 @@
#ifndef CONTENT_RENDERER_GPU_GPU_BENCHMARKING_EXTENSION_H_
#define CONTENT_RENDERER_GPU_GPU_BENCHMARKING_EXTENSION_H_
+#include "base/basictypes.h"
+#include "gin/wrappable.h"
+
+namespace blink {
+class WebFrame;
+}
+
+namespace gin {
+class Arguments;
+}
+
namespace v8 {
-class Extension;
+class Function;
+class Isolate;
+class Object;
+template <typename T> class Handle;
}
namespace content {
-// V8 extension for gpu benchmarking
-class GpuBenchmarkingExtension {
+// gin class for gpu benchmarking
+class GpuBenchmarking : public gin::Wrappable<GpuBenchmarking> {
public:
- static v8::Extension* Get();
+ static gin::WrapperInfo kWrapperInfo;
+ static void Install(blink::WebFrame* frame);
+
+ private:
+ GpuBenchmarking();
+ ~GpuBenchmarking() override;
+
+ // gin::Wrappable.
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
+
+ // JavaScript handlers.
+ void SetNeedsDisplayOnAllLayers();
+ void SetRasterizeOnlyVisibleContent();
+ void PrintToSkPicture(v8::Isolate* isolate, const std::string& dirname);
+ bool GestureSourceTypeSupported(int gesture_source_type);
+ bool SmoothScrollBy(gin::Arguments* args);
+ bool Swipe(gin::Arguments* args);
+ bool ScrollBounce(gin::Arguments* args);
+ bool PinchBy(gin::Arguments* args);
+ bool Tap(gin::Arguments* args);
+ void BeginWindowSnapshotPNG(v8::Isolate* isolate,
+ v8::Handle<v8::Function> callback);
+ void ClearImageCache();
+ int RunMicroBenchmark(gin::Arguments* args);
+ bool SendMessageToMicroBenchmark(int id, v8::Handle<v8::Object> message);
+ bool HasGpuProcess();
+
+ DISALLOW_COPY_AND_ASSIGN(GpuBenchmarking);
};
} // namespace content
diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.cc b/chromium/content/renderer/gpu/mailbox_output_surface.cc
index ec5d00bee44..6389f93856b 100644
--- a/chromium/content/renderer/gpu/mailbox_output_surface.cc
+++ b/chromium/content/renderer/gpu/mailbox_output_surface.cc
@@ -9,6 +9,7 @@
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/gl_frame_data.h"
#include "cc/resources/resource_provider.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
@@ -26,11 +27,13 @@ MailboxOutputSurface::MailboxOutputSurface(
uint32 output_surface_id,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
cc::ResourceFormat format)
: CompositorOutputSurface(routing_id,
output_surface_id,
context_provider,
software_device.Pass(),
+ swap_frame_message_queue,
true),
fbo_(0),
is_backbuffer_discarded_(false),
diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.h b/chromium/content/renderer/gpu/mailbox_output_surface.h
index 2a8e278e90a..fc6ba221c13 100644
--- a/chromium/content/renderer/gpu/mailbox_output_surface.h
+++ b/chromium/content/renderer/gpu/mailbox_output_surface.h
@@ -7,6 +7,7 @@
#include <queue>
+#include "base/memory/ref_counted.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/transferable_resource.h"
#include "content/renderer/gpu/compositor_output_surface.h"
@@ -17,6 +18,7 @@ class CompositorFrameAck;
}
namespace content {
+class FrameSwapMessageQueue;
// Implementation of CompositorOutputSurface that renders to textures which
// are sent to the browser through the mailbox extension.
@@ -29,20 +31,21 @@ class MailboxOutputSurface : public CompositorOutputSurface {
uint32 output_surface_id,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
scoped_ptr<cc::SoftwareOutputDevice> software_device,
+ scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
cc::ResourceFormat format);
- virtual ~MailboxOutputSurface();
+ ~MailboxOutputSurface() override;
// cc::OutputSurface implementation.
- virtual void EnsureBackbuffer() OVERRIDE;
- virtual void DiscardBackbuffer() OVERRIDE;
- virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE;
- virtual void BindFramebuffer() OVERRIDE;
- virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ void EnsureBackbuffer() override;
+ void DiscardBackbuffer() override;
+ void Reshape(const gfx::Size& size, float scale_factor) override;
+ void BindFramebuffer() override;
+ void SwapBuffers(cc::CompositorFrame* frame) override;
private:
// CompositorOutputSurface overrides.
- virtual void OnSwapAck(uint32 output_surface_id,
- const cc::CompositorFrameAck& ack) OVERRIDE;
+ void OnSwapAck(uint32 output_surface_id,
+ const cc::CompositorFrameAck& ack) override;
size_t GetNumAcksPending();
diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise.cc b/chromium/content/renderer/gpu/queue_message_swap_promise.cc
new file mode 100644
index 00000000000..1cb5316e166
--- /dev/null
+++ b/chromium/content/renderer/gpu/queue_message_swap_promise.cc
@@ -0,0 +1,69 @@
+// Copyright 2014 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 "content/renderer/gpu/queue_message_swap_promise.h"
+
+#include "content/renderer/gpu/frame_swap_message_queue.h"
+#include "ipc/ipc_sync_message_filter.h"
+
+namespace content {
+
+QueueMessageSwapPromise::QueueMessageSwapPromise(
+ scoped_refptr<IPC::SyncMessageFilter> message_sender,
+ scoped_refptr<content::FrameSwapMessageQueue> message_queue,
+ int source_frame_number)
+ : message_sender_(message_sender),
+ message_queue_(message_queue),
+ source_frame_number_(source_frame_number)
+#if DCHECK_IS_ON
+ ,
+ completed_(false)
+#endif
+{
+ DCHECK(message_sender_.get());
+ DCHECK(message_queue_.get());
+}
+
+QueueMessageSwapPromise::~QueueMessageSwapPromise() {
+ // The promise should have either been kept or broken before it's deleted.
+#if DCHECK_IS_ON
+ DCHECK(completed_);
+#endif
+}
+
+void QueueMessageSwapPromise::DidSwap(cc::CompositorFrameMetadata* metadata) {
+#if DCHECK_IS_ON
+ DCHECK(!completed_);
+#endif
+ message_queue_->DidSwap(source_frame_number_);
+ // The OutputSurface will take care of the Drain+Send.
+ PromiseCompleted();
+}
+
+void QueueMessageSwapPromise::DidNotSwap(DidNotSwapReason reason) {
+#if DCHECK_IS_ON
+ DCHECK(!completed_);
+#endif
+ ScopedVector<IPC::Message> messages;
+ message_queue_->DidNotSwap(source_frame_number_, reason, &messages);
+ for (ScopedVector<IPC::Message>::iterator i = messages.begin();
+ i != messages.end();
+ ++i) {
+ message_sender_->Send(*i);
+ }
+ messages.weak_clear();
+ PromiseCompleted();
+}
+
+void QueueMessageSwapPromise::PromiseCompleted() {
+#if DCHECK_IS_ON
+ completed_ = true;
+#endif
+}
+
+int64 QueueMessageSwapPromise::TraceId() const {
+ return 0;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise.h b/chromium/content/renderer/gpu/queue_message_swap_promise.h
new file mode 100644
index 00000000000..4094b1b96ec
--- /dev/null
+++ b/chromium/content/renderer/gpu/queue_message_swap_promise.h
@@ -0,0 +1,47 @@
+// Copyright 2014 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 CONTENT_RENDERER_QUEUE_MESSAGE_SWAP_PROMISE_H_
+#define CONTENT_RENDERER_QUEUE_MESSAGE_SWAP_PROMISE_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/base/swap_promise.h"
+
+namespace IPC {
+class SyncMessageFilter;
+}
+
+namespace content {
+
+class FrameSwapMessageQueue;
+
+class QueueMessageSwapPromise : public cc::SwapPromise {
+ public:
+ QueueMessageSwapPromise(scoped_refptr<IPC::SyncMessageFilter> message_sender,
+ scoped_refptr<FrameSwapMessageQueue> message_queue,
+ int source_frame_number);
+
+ ~QueueMessageSwapPromise() override;
+
+ void DidSwap(cc::CompositorFrameMetadata* metadata) override;
+
+ void DidNotSwap(DidNotSwapReason reason) override;
+
+ int64 TraceId() const override;
+
+ private:
+ void PromiseCompleted();
+
+ scoped_refptr<IPC::SyncMessageFilter> message_sender_;
+ scoped_refptr<content::FrameSwapMessageQueue> message_queue_;
+ int source_frame_number_;
+#if DCHECK_IS_ON
+ bool completed_;
+#endif
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_QUEUE_MESSAGE_SWAP_PROMISE_H_
diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc b/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc
new file mode 100644
index 00000000000..101055e8b04
--- /dev/null
+++ b/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc
@@ -0,0 +1,322 @@
+// Copyright 2014 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 "content/renderer/gpu/queue_message_swap_promise.h"
+
+#include <vector>
+
+#include "base/memory/scoped_vector.h"
+#include "cc/base/swap_promise.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
+#include "content/renderer/gpu/render_widget_compositor.h"
+#include "content/renderer/render_widget.h"
+#include "content/test/mock_render_process.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "ipc/ipc_test_sink.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class TestRenderWidget : public RenderWidget {
+ public:
+ using RenderWidget::QueueMessageImpl;
+
+ private:
+ ~TestRenderWidget() override {}
+
+ DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
+};
+
+class TestSyncMessageFilter : public IPC::SyncMessageFilter {
+ public:
+ TestSyncMessageFilter() : IPC::SyncMessageFilter(NULL) {}
+
+ bool Send(IPC::Message* message) override {
+ messages_.push_back(message);
+ return true;
+ }
+
+ ScopedVector<IPC::Message>& messages() { return messages_; }
+
+ private:
+ ~TestSyncMessageFilter() override {}
+
+ ScopedVector<IPC::Message> messages_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSyncMessageFilter);
+};
+
+struct QueueMessageData {
+ MessageDeliveryPolicy policy;
+ bool commit_requested;
+ int source_frame_number;
+};
+
+class QueueMessageSwapPromiseTest : public testing::Test {
+ public:
+ QueueMessageSwapPromiseTest()
+ : frame_swap_message_queue_(new FrameSwapMessageQueue()),
+ sync_message_filter_(new TestSyncMessageFilter()) {}
+
+ ~QueueMessageSwapPromiseTest() override {}
+
+ scoped_ptr<cc::SwapPromise> QueueMessageImpl(IPC::Message* msg,
+ MessageDeliveryPolicy policy,
+ bool commit_requested,
+ int source_frame_number) {
+ return TestRenderWidget::QueueMessageImpl(msg,
+ policy,
+ frame_swap_message_queue_.get(),
+ sync_message_filter_,
+ commit_requested,
+ source_frame_number).Pass();
+ }
+
+ ScopedVector<IPC::Message>& DirectSendMessages() {
+ return sync_message_filter_->messages();
+ }
+
+ ScopedVector<IPC::Message>& NextSwapMessages() {
+ next_swap_messages_.clear();
+ scoped_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
+ frame_swap_message_queue_->AcquireSendMessageScope();
+ frame_swap_message_queue_->DrainMessages(&next_swap_messages_);
+ return next_swap_messages_;
+ }
+
+ bool ContainsMessage(const ScopedVector<IPC::Message>& messages,
+ const IPC::Message& message) {
+ if (messages.empty())
+ return false;
+ for (ScopedVector<IPC::Message>::const_iterator i = messages.begin();
+ i != messages.end();
+ ++i) {
+ if ((*i)->type() == message.type())
+ return true;
+ }
+ return false;
+ }
+
+ bool NextSwapHasMessage(const IPC::Message& message) {
+ return ContainsMessage(NextSwapMessages(), message);
+ }
+
+ void QueueMessages(QueueMessageData data[], size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ messages_.push_back(
+ IPC::Message(0, i + 1, IPC::Message::PRIORITY_NORMAL));
+ promises_.push_back(
+ QueueMessageImpl(new IPC::Message(messages_[i]),
+ data[i].policy,
+ data[i].commit_requested,
+ data[i].source_frame_number).release());
+ }
+ }
+
+ void CleanupPromises() {
+ for (ScopedVector<cc::SwapPromise>::iterator i = promises_.begin();
+ i != promises_.end();
+ ++i) {
+ if (*i)
+ (*i)->DidSwap(NULL);
+ }
+ }
+
+ protected:
+ void VisualStateSwapPromiseDidNotSwap(
+ cc::SwapPromise::DidNotSwapReason reason);
+
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
+ scoped_refptr<TestSyncMessageFilter> sync_message_filter_;
+ std::vector<IPC::Message> messages_;
+ ScopedVector<cc::SwapPromise> promises_;
+
+ private:
+ ScopedVector<IPC::Message> next_swap_messages_;
+
+ DISALLOW_COPY_AND_ASSIGN(QueueMessageSwapPromiseTest);
+};
+
+TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySchedulesMessageForNextSwap) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ ASSERT_TRUE(promises_[0]);
+ EXPECT_TRUE(DirectSendMessages().empty());
+ EXPECT_FALSE(frame_swap_message_queue_->Empty());
+ EXPECT_TRUE(NextSwapHasMessage(messages_[0]));
+
+ CleanupPromises();
+}
+
+TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyNeedsAtMostOnePromise) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
+ {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ ASSERT_TRUE(promises_[0]);
+ ASSERT_FALSE(promises_[1]);
+
+ CleanupPromises();
+}
+
+TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnNoUpdate) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
+ EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
+ EXPECT_TRUE(NextSwapMessages().empty());
+ EXPECT_TRUE(frame_swap_message_queue_->Empty());
+}
+
+TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnSwapFails) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ promises_[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS);
+ EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
+ EXPECT_TRUE(NextSwapMessages().empty());
+ EXPECT_TRUE(frame_swap_message_queue_->Empty());
+}
+
+TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyRetainsMessageOnCommitFails) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP, false, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS);
+ EXPECT_TRUE(DirectSendMessages().empty());
+ EXPECT_FALSE(frame_swap_message_queue_->Empty());
+ EXPECT_TRUE(NextSwapHasMessage(messages_[0]));
+}
+
+TEST_F(QueueMessageSwapPromiseTest, VisualStateDirectSend) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ ASSERT_FALSE(promises_[0]);
+ EXPECT_FALSE(DirectSendMessages().empty());
+ EXPECT_TRUE(frame_swap_message_queue_->Empty());
+ EXPECT_TRUE(NextSwapMessages().empty());
+}
+
+TEST_F(QueueMessageSwapPromiseTest,
+ VisualStateQueuesMessageWhenCommitRequested) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ ASSERT_TRUE(promises_[0]);
+ EXPECT_TRUE(DirectSendMessages().empty());
+ EXPECT_FALSE(frame_swap_message_queue_->Empty());
+ EXPECT_TRUE(NextSwapMessages().empty());
+
+ CleanupPromises();
+}
+
+TEST_F(QueueMessageSwapPromiseTest,
+ VisualStateQueuesMessageWhenOtherMessageAlreadyQueued) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
+ };
+ QueueMessages(data, arraysize(data));
+
+ EXPECT_TRUE(DirectSendMessages().empty());
+ EXPECT_FALSE(frame_swap_message_queue_->Empty());
+ EXPECT_FALSE(NextSwapHasMessage(messages_[1]));
+
+ CleanupPromises();
+}
+
+TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidSwap) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 1},
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 2},
+ };
+ QueueMessages(data, arraysize(data));
+
+ promises_[0]->DidSwap(NULL);
+ ASSERT_FALSE(promises_[1]);
+ ScopedVector<IPC::Message> messages;
+ messages.swap(NextSwapMessages());
+ EXPECT_EQ(2u, messages.size());
+ EXPECT_TRUE(ContainsMessage(messages, messages_[0]));
+ EXPECT_TRUE(ContainsMessage(messages, messages_[1]));
+ EXPECT_FALSE(ContainsMessage(messages, messages_[2]));
+
+ promises_[2]->DidSwap(NULL);
+ messages.swap(NextSwapMessages());
+ EXPECT_EQ(1u, messages.size());
+ EXPECT_TRUE(ContainsMessage(messages, messages_[2]));
+
+ EXPECT_TRUE(DirectSendMessages().empty());
+ EXPECT_TRUE(NextSwapMessages().empty());
+ EXPECT_TRUE(frame_swap_message_queue_->Empty());
+}
+
+void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
+ cc::SwapPromise::DidNotSwapReason reason) {
+ QueueMessageData data[] = {
+ /* { policy, commit_requested, source_frame_number } */
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, true, 1},
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 1},
+ {MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE, false, 2},
+ };
+ QueueMessages(data, arraysize(data));
+
+ promises_[0]->DidNotSwap(reason);
+ ASSERT_FALSE(promises_[1]);
+ EXPECT_TRUE(NextSwapMessages().empty());
+ EXPECT_EQ(2u, DirectSendMessages().size());
+ EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
+ EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[1]));
+ EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_[2]));
+
+ promises_[2]->DidNotSwap(reason);
+ EXPECT_TRUE(NextSwapMessages().empty());
+ EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[2]));
+
+ EXPECT_TRUE(NextSwapMessages().empty());
+ EXPECT_TRUE(frame_swap_message_queue_->Empty());
+}
+
+TEST_F(QueueMessageSwapPromiseTest, VisalStateSwapPromiseDidNotSwapNoUpdate) {
+ VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
+}
+
+TEST_F(QueueMessageSwapPromiseTest,
+ VisalStateSwapPromiseDidNotSwapCommitFails) {
+ VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_FAILS);
+}
+
+TEST_F(QueueMessageSwapPromiseTest, VisalStateSwapPromiseDidNotSwapSwapFails) {
+ VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::SWAP_FAILS);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc
index 159c7cb3350..6d0768bc435 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor.cc
@@ -7,36 +7,39 @@
#include <limits>
#include <string>
-#if defined(OS_ANDROID)
-#include "base/android/sys_utils.h"
-#endif
-
#include "base/command_line.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
+#include "base/sys_info.h"
#include "base/time/time.h"
#include "base/values.h"
#include "cc/base/latency_info_swap_promise.h"
#include "cc/base/latency_info_swap_promise_monitor.h"
+#include "cc/base/swap_promise.h"
#include "cc/base/switches.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/debug/micro_benchmark.h"
+#include "cc/input/layer_selection_bound.h"
#include "cc/layers/layer.h"
+#include "cc/output/begin_frame_args.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
#include "cc/resources/single_release_callback.h"
#include "cc/trees/layer_tree_host.h"
+#include "content/child/child_gpu_memory_buffer_manager.h"
#include "content/child/child_shared_bitmap_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/public/common/content_switches.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h"
+#include "third_party/WebKit/public/platform/WebSelectionBound.h"
#include "third_party/WebKit/public/platform/WebSize.h"
+#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/gfx/frame_time.h"
#include "ui/gl/gl_switches.h"
@@ -44,6 +47,7 @@
#if defined(OS_ANDROID)
#include "content/renderer/android/synchronous_compositor_factory.h"
+#include "ui/gfx/android/device_display_info.h"
#endif
namespace base {
@@ -54,9 +58,11 @@ namespace cc {
class Layer;
}
+using blink::WebBeginFrameArgs;
using blink::WebFloatPoint;
-using blink::WebSize;
using blink::WebRect;
+using blink::WebSelectionBound;
+using blink::WebSize;
namespace content {
namespace {
@@ -80,6 +86,75 @@ bool GetSwitchValueAsInt(
}
}
+cc::LayerSelectionBound ConvertWebSelectionBound(
+ const WebSelectionBound& web_bound) {
+ DCHECK(web_bound.layerId);
+
+ cc::LayerSelectionBound cc_bound;
+ switch (web_bound.type) {
+ case blink::WebSelectionBound::Caret:
+ cc_bound.type = cc::SELECTION_BOUND_CENTER;
+ break;
+ case blink::WebSelectionBound::SelectionLeft:
+ cc_bound.type = cc::SELECTION_BOUND_LEFT;
+ break;
+ case blink::WebSelectionBound::SelectionRight:
+ cc_bound.type = cc::SELECTION_BOUND_RIGHT;
+ break;
+ }
+ cc_bound.layer_id = web_bound.layerId;
+ cc_bound.edge_top = gfx::Point(web_bound.edgeTopInLayer);
+ cc_bound.edge_bottom = gfx::Point(web_bound.edgeBottomInLayer);
+ return cc_bound;
+}
+
+gfx::Size CalculateDefaultTileSize() {
+ int default_tile_size = 256;
+#if defined(OS_ANDROID)
+ // TODO(epenner): unify this for all platforms if it
+ // makes sense (http://crbug.com/159524)
+
+ gfx::DeviceDisplayInfo info;
+ bool real_size_supported = true;
+ int display_width = info.GetPhysicalDisplayWidth();
+ int display_height = info.GetPhysicalDisplayHeight();
+ if (display_width == 0 || display_height == 0) {
+ real_size_supported = false;
+ display_width = info.GetDisplayWidth();
+ display_height = info.GetDisplayHeight();
+ }
+
+ int portrait_width = std::min(display_width, display_height);
+ int landscape_width = std::max(display_width, display_height);
+
+ if (real_size_supported) {
+ // Maximum HD dimensions should be 768x1280
+ // Maximum FHD dimensions should be 1200x1920
+ if (portrait_width > 768 || landscape_width > 1280)
+ default_tile_size = 384;
+ if (portrait_width > 1200 || landscape_width > 1920)
+ default_tile_size = 512;
+
+ // Adjust for some resolutions that barely straddle an extra
+ // tile when in portrait mode. This helps worst case scroll/raster
+ // by not needing a full extra tile for each row.
+ if (default_tile_size == 256 && portrait_width == 768)
+ default_tile_size += 32;
+ if (default_tile_size == 384 && portrait_width == 1200)
+ default_tile_size += 32;
+ } else {
+ // We don't know the exact resolution due to screen controls etc.
+ // So this just estimates the values above using tile counts.
+ int numTiles = (display_width * display_height) / (256 * 256);
+ if (numTiles > 16)
+ default_tile_size = 384;
+ if (numTiles >= 40)
+ default_tile_size = 512;
+ }
+#endif
+ return gfx::Size(default_tile_size, default_tile_size);
+}
+
} // namespace
// static
@@ -104,26 +179,29 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.main_frame_before_activation_enabled =
cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation) &&
!cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeActivation);
- settings.main_frame_before_draw_enabled =
- !cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeDraw);
settings.report_overscroll_only_for_scrollable_axes = true;
settings.accelerated_animation_enabled =
!cmd->HasSwitch(cc::switches::kDisableThreadedAnimation);
- settings.touch_hit_testing =
- !cmd->HasSwitch(cc::switches::kDisableCompositorTouchHitTesting);
- int default_tile_width = settings.default_tile_size.width();
+ settings.default_tile_size = CalculateDefaultTileSize();
if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
- GetSwitchValueAsInt(*cmd, switches::kDefaultTileWidth, 1,
- std::numeric_limits<int>::max(), &default_tile_width);
+ int tile_width = 0;
+ GetSwitchValueAsInt(*cmd,
+ switches::kDefaultTileWidth,
+ 1,
+ std::numeric_limits<int>::max(),
+ &tile_width);
+ settings.default_tile_size.set_width(tile_width);
}
- int default_tile_height = settings.default_tile_size.height();
if (cmd->HasSwitch(switches::kDefaultTileHeight)) {
- GetSwitchValueAsInt(*cmd, switches::kDefaultTileHeight, 1,
- std::numeric_limits<int>::max(), &default_tile_height);
+ int tile_height = 0;
+ GetSwitchValueAsInt(*cmd,
+ switches::kDefaultTileHeight,
+ 1,
+ std::numeric_limits<int>::max(),
+ &tile_height);
+ settings.default_tile_size.set_height(tile_height);
}
- settings.default_tile_size = gfx::Size(default_tile_width,
- default_tile_height);
int max_untiled_layer_width = settings.max_untiled_layer_size.width();
if (cmd->HasSwitch(switches::kMaxUntiledLayerWidth)) {
@@ -150,7 +228,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
render_thread->is_gpu_rasterization_forced();
settings.gpu_rasterization_enabled =
render_thread->is_gpu_rasterization_enabled();
- settings.create_low_res_tiling = render_thread->is_low_res_tiling_enabled();
settings.can_use_lcd_text = render_thread->is_lcd_text_enabled();
settings.use_distance_field_text =
render_thread->is_distance_field_text_enabled();
@@ -158,10 +235,6 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.use_one_copy = render_thread->is_one_copy_enabled();
}
- if (cmd->HasSwitch(switches::kEnableBleedingEdgeRenderingFastPaths)) {
- settings.recording_mode = cc::LayerTreeSettings::RecordWithSkRecord;
- }
-
settings.calculate_top_controls_position =
cmd->HasSwitch(cc::switches::kEnableTopControlsPositionCalculation);
if (cmd->HasSwitch(cc::switches::kTopControlsHeight)) {
@@ -202,6 +275,8 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
cmd->HasSwitch(cc::switches::kEnablePinchVirtualViewport);
settings.allow_antialiasing &=
!cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
+ settings.single_thread_proxy_scheduler =
+ !cmd->HasSwitch(switches::kDisableSingleThreadProxyScheduler);
// These flags should be mirrored by UI versions in ui/compositor/.
settings.initial_debug_state.show_debug_borders =
@@ -282,6 +357,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
} else {
settings.scrollbar_animator = cc::LayerTreeSettings::LinearFade;
settings.scrollbar_fade_delay_ms = 300;
+ settings.scrollbar_fade_resize_delay_ms = 2000;
settings.scrollbar_fade_duration_ms = 300;
settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
}
@@ -292,8 +368,7 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
// Memory policy on Android WebView does not depend on whether device is
// low end, so always use default policy.
bool is_low_end_device =
- base::android::SysUtils::IsLowEndDevice() &&
- !synchronous_compositor_factory;
+ base::SysInfo::IsLowEndDevice() && !synchronous_compositor_factory;
// RGBA_4444 textures are only enabled for low end devices
// and are disabled for Android WebView as it doesn't support the format.
settings.use_rgba_4444_textures = is_low_end_device;
@@ -312,6 +387,9 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.should_clear_root_render_pass =
!synchronous_compositor_factory;
+ // TODO(danakj): Only do this on low end devices.
+ settings.create_low_res_tiling = true;
+
#elif !defined(OS_MACOSX)
if (ui::IsOverlayScrollbarEnabled()) {
settings.scrollbar_animator = cc::LayerTreeSettings::Thinning;
@@ -324,9 +402,15 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128);
}
settings.scrollbar_fade_delay_ms = 500;
+ settings.scrollbar_fade_resize_delay_ms = 500;
settings.scrollbar_fade_duration_ms = 300;
#endif
+ if (cmd->HasSwitch(switches::kEnableLowResTiling))
+ settings.create_low_res_tiling = true;
+ if (cmd->HasSwitch(switches::kDisableLowResTiling))
+ settings.create_low_res_tiling = false;
+
compositor->Initialize(settings);
return compositor.Pass();
@@ -335,8 +419,14 @@ scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
RenderWidgetCompositor::RenderWidgetCompositor(RenderWidget* widget,
bool threaded)
: threaded_(threaded),
- suppress_schedule_composite_(false),
- widget_(widget) {
+ widget_(widget),
+ send_v8_idle_notification_after_commit_(true) {
+ CommandLine* cmd = CommandLine::ForCurrentProcess();
+
+ if (cmd->HasSwitch(switches::kEnableV8IdleNotificationAfterCommit))
+ send_v8_idle_notification_after_commit_ = true;
+ if (cmd->HasSwitch(switches::kDisableV8IdleNotificationAfterCommit))
+ send_v8_idle_notification_after_commit_ = false;
}
RenderWidgetCompositor::~RenderWidgetCompositor() {}
@@ -346,27 +436,10 @@ RenderWidgetCompositor::GetInputHandler() {
return layer_tree_host_->GetInputHandler();
}
-void RenderWidgetCompositor::SetSuppressScheduleComposite(bool suppress) {
- if (suppress_schedule_composite_ == suppress)
- return;
-
- if (suppress)
- TRACE_EVENT_ASYNC_BEGIN0("gpu",
- "RenderWidgetCompositor::SetSuppressScheduleComposite", this);
- else
- TRACE_EVENT_ASYNC_END0("gpu",
- "RenderWidgetCompositor::SetSuppressScheduleComposite", this);
- suppress_schedule_composite_ = suppress;
-}
-
bool RenderWidgetCompositor::BeginMainFrameRequested() const {
return layer_tree_host_->BeginMainFrameRequested();
}
-void RenderWidgetCompositor::UpdateAnimations(base::TimeTicks time) {
- layer_tree_host_->UpdateClientAnimations(time);
-}
-
void RenderWidgetCompositor::SetNeedsDisplayOnAllLayers() {
layer_tree_host_->SetNeedsDisplayOnAllLayers();
}
@@ -386,9 +459,8 @@ void RenderWidgetCompositor::UpdateTopControlsState(
animate);
}
-void RenderWidgetCompositor::SetOverdrawBottomHeight(
- float overdraw_bottom_height) {
- layer_tree_host_->SetOverdrawBottomHeight(overdraw_bottom_height);
+void RenderWidgetCompositor::SetTopControlsLayoutHeight(float height) {
+ layer_tree_host_->SetTopControlsLayoutHeight(height);
}
void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) {
@@ -417,6 +489,14 @@ int RenderWidgetCompositor::GetLayerTreeId() const {
return layer_tree_host_->id();
}
+int RenderWidgetCompositor::GetSourceFrameNumber() const {
+ return layer_tree_host_->source_frame_number();
+}
+
+void RenderWidgetCompositor::SetNeedsCommit() {
+ layer_tree_host_->SetNeedsCommit();
+}
+
void RenderWidgetCompositor::NotifyInputThrottledUntilCommit() {
layer_tree_host_->NotifyInputThrottledUntilCommit();
}
@@ -440,31 +520,50 @@ bool RenderWidgetCompositor::SendMessageToMicroBenchmark(
void RenderWidgetCompositor::Initialize(cc::LayerTreeSettings settings) {
scoped_refptr<base::MessageLoopProxy> compositor_message_loop_proxy;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ main_thread_compositor_task_runner(base::MessageLoopProxy::current());
RenderThreadImpl* render_thread = RenderThreadImpl::current();
cc::SharedBitmapManager* shared_bitmap_manager = NULL;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager = NULL;
// render_thread may be NULL in tests.
if (render_thread) {
compositor_message_loop_proxy =
render_thread->compositor_message_loop_proxy();
shared_bitmap_manager = render_thread->shared_bitmap_manager();
+ gpu_memory_buffer_manager = render_thread->gpu_memory_buffer_manager();
+ main_thread_compositor_task_runner =
+ render_thread->main_thread_compositor_task_runner();
}
if (compositor_message_loop_proxy.get()) {
- layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
- this, shared_bitmap_manager, settings, compositor_message_loop_proxy);
+ layer_tree_host_ =
+ cc::LayerTreeHost::CreateThreaded(this,
+ shared_bitmap_manager,
+ gpu_memory_buffer_manager,
+ settings,
+ main_thread_compositor_task_runner,
+ compositor_message_loop_proxy);
} else {
layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(
- this, this, shared_bitmap_manager, settings);
+ this,
+ this,
+ shared_bitmap_manager,
+ gpu_memory_buffer_manager,
+ settings,
+ main_thread_compositor_task_runner);
}
DCHECK(layer_tree_host_);
}
void RenderWidgetCompositor::setSurfaceReady() {
- layer_tree_host_->SetLayerTreeHostClientReady();
+ // In tests without a RenderThreadImpl, don't set ready as this kicks
+ // off creating output surfaces that the test can't create.
+ if (RenderThreadImpl::current())
+ layer_tree_host_->SetLayerTreeHostClientReady();
}
void RenderWidgetCompositor::setRootLayer(const blink::WebLayer& layer) {
layer_tree_host_->SetRootLayer(
- static_cast<const WebLayerImpl*>(&layer)->layer());
+ static_cast<const cc_blink::WebLayerImpl*>(&layer)->layer());
}
void RenderWidgetCompositor::clearRootLayer() {
@@ -557,7 +656,7 @@ void RenderWidgetCompositor::didStopFlinging() {
}
void RenderWidgetCompositor::registerForAnimations(blink::WebLayer* layer) {
- cc::Layer* cc_layer = static_cast<WebLayerImpl*>(layer)->layer();
+ cc::Layer* cc_layer = static_cast<cc_blink::WebLayerImpl*>(layer)->layer();
cc_layer->layer_animation_controller()->SetAnimationRegistrar(
layer_tree_host_->animation_registrar());
}
@@ -567,13 +666,14 @@ void RenderWidgetCompositor::registerViewportLayers(
const blink::WebLayer* innerViewportScrollLayer,
const blink::WebLayer* outerViewportScrollLayer) {
layer_tree_host_->RegisterViewportLayers(
- static_cast<const WebLayerImpl*>(pageScaleLayer)->layer(),
- static_cast<const WebLayerImpl*>(innerViewportScrollLayer)->layer(),
+ static_cast<const cc_blink::WebLayerImpl*>(pageScaleLayer)->layer(),
+ static_cast<const cc_blink::WebLayerImpl*>(innerViewportScrollLayer)
+ ->layer(),
// The outer viewport layer will only exist when using pinch virtual
// viewports.
- outerViewportScrollLayer
- ? static_cast<const WebLayerImpl*>(outerViewportScrollLayer)->layer()
- : NULL);
+ outerViewportScrollLayer ? static_cast<const cc_blink::WebLayerImpl*>(
+ outerViewportScrollLayer)->layer()
+ : NULL);
}
void RenderWidgetCompositor::clearViewportLayers() {
@@ -582,6 +682,18 @@ void RenderWidgetCompositor::clearViewportLayers() {
scoped_refptr<cc::Layer>());
}
+void RenderWidgetCompositor::registerSelection(
+ const blink::WebSelectionBound& start,
+ const blink::WebSelectionBound& end) {
+ layer_tree_host_->RegisterSelection(ConvertWebSelectionBound(start),
+ ConvertWebSelectionBound(end));
+}
+
+void RenderWidgetCompositor::clearSelection() {
+ cc::LayerSelectionBound empty_selection;
+ layer_tree_host_->RegisterSelection(empty_selection, empty_selection);
+}
+
void CompositeAndReadbackAsyncCallback(
blink::WebCompositeAndReadbackAsyncCallback* callback,
scoped_ptr<cc::CopyOutputResult> result) {
@@ -595,15 +707,18 @@ void CompositeAndReadbackAsyncCallback(
void RenderWidgetCompositor::compositeAndReadbackAsync(
blink::WebCompositeAndReadbackAsyncCallback* callback) {
- DCHECK(layer_tree_host_->root_layer());
- scoped_ptr<cc::CopyOutputRequest> request =
+ DCHECK(!temporary_copy_output_request_);
+ temporary_copy_output_request_ =
cc::CopyOutputRequest::CreateBitmapRequest(
base::Bind(&CompositeAndReadbackAsyncCallback, callback));
- layer_tree_host_->root_layer()->RequestCopyOfOutput(request.Pass());
- if (!threaded_) {
- widget_->webwidget()->animate(0.0);
- widget_->webwidget()->layout();
+ // Force a commit to happen. The temporary copy output request will
+ // be installed after layout which will happen as a part of the commit, when
+ // there is guaranteed to be a root layer.
+ if (!threaded_ &&
+ !layer_tree_host_->settings().single_thread_proxy_scheduler) {
layer_tree_host_->Composite(gfx::FrameTime::Now());
+ } else {
+ layer_tree_host_->SetNeedsCommit();
}
}
@@ -647,6 +762,10 @@ void RenderWidgetCompositor::setShowScrollBottleneckRects(bool show) {
layer_tree_host_->SetDebugState(debug_state);
}
+void RenderWidgetCompositor::setTopControlsContentOffset(float offset) {
+ layer_tree_host_->SetTopControlsContentOffset(offset);
+}
+
void RenderWidgetCompositor::WillBeginMainFrame(int frame_id) {
widget_->InstrumentWillBeginFrame(frame_id);
widget_->willBeginCompositorFrame();
@@ -656,24 +775,51 @@ void RenderWidgetCompositor::DidBeginMainFrame() {
widget_->InstrumentDidBeginFrame();
}
-void RenderWidgetCompositor::Animate(base::TimeTicks frame_begin_time) {
- widget_->webwidget()->animate(
- (frame_begin_time - base::TimeTicks()).InSecondsF());
+void RenderWidgetCompositor::BeginMainFrame(const cc::BeginFrameArgs& args) {
+ begin_main_frame_time_ = args.frame_time;
+ begin_main_frame_interval_ = args.interval;
+ double frame_time_sec = (args.frame_time - base::TimeTicks()).InSecondsF();
+ double deadline_sec = (args.deadline - base::TimeTicks()).InSecondsF();
+ double interval_sec = args.interval.InSecondsF();
+ WebBeginFrameArgs web_begin_frame_args =
+ WebBeginFrameArgs(frame_time_sec, deadline_sec, interval_sec);
+ widget_->webwidget()->beginFrame(web_begin_frame_args);
}
void RenderWidgetCompositor::Layout() {
widget_->webwidget()->layout();
+
+ if (temporary_copy_output_request_) {
+ DCHECK(layer_tree_host_->root_layer());
+ layer_tree_host_->root_layer()->RequestCopyOfOutput(
+ temporary_copy_output_request_.Pass());
+ }
+}
+
+void RenderWidgetCompositor::ApplyViewportDeltas(
+ const gfx::Vector2d& inner_delta,
+ const gfx::Vector2d& outer_delta,
+ float page_scale,
+ float top_controls_delta) {
+ widget_->webwidget()->applyViewportDeltas(
+ inner_delta,
+ outer_delta,
+ page_scale,
+ top_controls_delta);
}
-void RenderWidgetCompositor::ApplyScrollAndScale(
+void RenderWidgetCompositor::ApplyViewportDeltas(
const gfx::Vector2d& scroll_delta,
- float page_scale) {
- widget_->webwidget()->applyScrollAndScale(scroll_delta, page_scale);
+ float page_scale,
+ float top_controls_delta) {
+ widget_->webwidget()->applyViewportDeltas(
+ scroll_delta,
+ page_scale,
+ top_controls_delta);
}
-scoped_ptr<cc::OutputSurface> RenderWidgetCompositor::CreateOutputSurface(
- bool fallback) {
- return widget_->CreateOutputSurface(fallback);
+void RenderWidgetCompositor::RequestNewOutputSurface(bool fallback) {
+ layer_tree_host_->SetOutputSurface(widget_->CreateOutputSurface(fallback));
}
void RenderWidgetCompositor::DidInitializeOutputSurface() {
@@ -684,8 +830,23 @@ void RenderWidgetCompositor::WillCommit() {
}
void RenderWidgetCompositor::DidCommit() {
+ DCHECK(!temporary_copy_output_request_);
+ if (send_v8_idle_notification_after_commit_) {
+ base::TimeDelta idle_time = begin_main_frame_time_ +
+ begin_main_frame_interval_ -
+ gfx::FrameTime::Now();
+ if (idle_time > base::TimeDelta()) {
+ // Convert to 32-bit microseconds first to avoid costly 64-bit division.
+ int32 idle_time_in_us = idle_time.InMicroseconds();
+ int32 idle_time_in_ms = idle_time_in_us / 1000;
+ if (idle_time_in_ms)
+ blink::mainThreadIsolate()->IdleNotification(idle_time_in_ms);
+ }
+ }
+
widget_->DidCommitCompositorFrame();
widget_->didBecomeReadyForAdditionalInput();
+ widget_->webwidget()->didCommitFrameToCompositor();
}
void RenderWidgetCompositor::DidCommitAndDrawFrame() {
@@ -698,11 +859,6 @@ void RenderWidgetCompositor::DidCompleteSwapBuffers() {
widget_->OnSwapBuffersComplete();
}
-void RenderWidgetCompositor::ScheduleComposite() {
- if (!suppress_schedule_composite_)
- widget_->scheduleComposite();
-}
-
void RenderWidgetCompositor::ScheduleAnimation() {
widget_->scheduleAnimation();
}
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/render_widget_compositor.h
index 4160df2de20..e0f369a2f69 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor.h
@@ -15,6 +15,7 @@
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "cc/trees/layer_tree_settings.h"
+#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebLayerTreeView.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/rect.h"
@@ -24,6 +25,7 @@ struct LatencyInfo;
}
namespace cc {
+class CopyOutputRequest;
class InputHandler;
class Layer;
class LayerTreeHost;
@@ -32,9 +34,10 @@ class LayerTreeHost;
namespace content {
class RenderWidget;
-class RenderWidgetCompositor : public blink::WebLayerTreeView,
- public cc::LayerTreeHostClient,
- public cc::LayerTreeHostSingleThreadClient {
+class CONTENT_EXPORT RenderWidgetCompositor
+ : NON_EXPORTED_BASE(public blink::WebLayerTreeView),
+ NON_EXPORTED_BASE(public cc::LayerTreeHostClient),
+ NON_EXPORTED_BASE(public cc::LayerTreeHostSingleThreadClient) {
public:
// Attempt to construct and initialize a compositor instance for the widget
// with the given settings. Returns NULL if initialization fails.
@@ -44,15 +47,13 @@ class RenderWidgetCompositor : public blink::WebLayerTreeView,
virtual ~RenderWidgetCompositor();
const base::WeakPtr<cc::InputHandler>& GetInputHandler();
- void SetSuppressScheduleComposite(bool suppress);
bool BeginMainFrameRequested() const;
- void UpdateAnimations(base::TimeTicks time);
void SetNeedsDisplayOnAllLayers();
void SetRasterizeOnlyVisibleContent();
void UpdateTopControlsState(cc::TopControlsState constraints,
cc::TopControlsState current,
bool animate);
- void SetOverdrawBottomHeight(float overdraw_bottom_height);
+ void SetTopControlsLayoutHeight(float height);
void SetNeedsRedrawRect(gfx::Rect damage_rect);
// Like setNeedsRedraw but forces the frame to be drawn, without early-outs.
// Redraw will be forced after the next commit
@@ -68,6 +69,8 @@ class RenderWidgetCompositor : public blink::WebLayerTreeView,
// LayerTreeHost.
void QueueSwapPromise(scoped_ptr<cc::SwapPromise> swap_promise);
int GetLayerTreeId() const;
+ int GetSourceFrameNumber() const;
+ void SetNeedsCommit();
void NotifyInputThrottledUntilCommit();
const cc::Layer* GetRootLayer() const;
int ScheduleMicroBenchmark(
@@ -113,35 +116,42 @@ class RenderWidgetCompositor : public blink::WebLayerTreeView,
virtual void registerViewportLayers(
const blink::WebLayer* pageScaleLayer,
const blink::WebLayer* innerViewportScrollLayer,
- const blink::WebLayer* outerViewportScrollLayer) OVERRIDE;
- virtual void clearViewportLayers() OVERRIDE;
+ const blink::WebLayer* outerViewportScrollLayer) override;
+ virtual void clearViewportLayers() override;
+ virtual void registerSelection(const blink::WebSelectionBound& start,
+ const blink::WebSelectionBound& end) override;
+ virtual void clearSelection() override;
virtual void setShowFPSCounter(bool show);
virtual void setShowPaintRects(bool show);
virtual void setShowDebugBorders(bool show);
virtual void setContinuousPaintingEnabled(bool enabled);
virtual void setShowScrollBottleneckRects(bool show);
+ virtual void setTopControlsContentOffset(float);
// cc::LayerTreeHostClient implementation.
- virtual void WillBeginMainFrame(int frame_id) OVERRIDE;
- virtual void DidBeginMainFrame() OVERRIDE;
- virtual void Animate(base::TimeTicks frame_begin_time) OVERRIDE;
- virtual void Layout() OVERRIDE;
- virtual void ApplyScrollAndScale(const gfx::Vector2d& scroll_delta,
- float page_scale) OVERRIDE;
- virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback)
- OVERRIDE;
- virtual void DidInitializeOutputSurface() OVERRIDE;
- virtual void WillCommit() OVERRIDE;
- virtual void DidCommit() OVERRIDE;
- virtual void DidCommitAndDrawFrame() OVERRIDE;
- virtual void DidCompleteSwapBuffers() OVERRIDE;
- virtual void RateLimitSharedMainThreadContext() OVERRIDE;
+ void WillBeginMainFrame(int frame_id) override;
+ void DidBeginMainFrame() override;
+ void BeginMainFrame(const cc::BeginFrameArgs& args) override;
+ void Layout() override;
+ void ApplyViewportDeltas(const gfx::Vector2d& inner_delta,
+ const gfx::Vector2d& outer_delta,
+ float page_scale,
+ float top_controls_delta) override;
+ void ApplyViewportDeltas(const gfx::Vector2d& scroll_delta,
+ float page_scale,
+ float top_controls_delta) override;
+ void RequestNewOutputSurface(bool fallback) override;
+ void DidInitializeOutputSurface() override;
+ void WillCommit() override;
+ void DidCommit() override;
+ void DidCommitAndDrawFrame() override;
+ void DidCompleteSwapBuffers() override;
+ void RateLimitSharedMainThreadContext() override;
// cc::LayerTreeHostSingleThreadClient implementation.
- virtual void ScheduleComposite() OVERRIDE;
- virtual void ScheduleAnimation() OVERRIDE;
- virtual void DidPostSwapBuffers() OVERRIDE;
- virtual void DidAbortSwapBuffers() OVERRIDE;
+ void ScheduleAnimation() override;
+ void DidPostSwapBuffers() override;
+ void DidAbortSwapBuffers() override;
private:
RenderWidgetCompositor(RenderWidget* widget, bool threaded);
@@ -149,9 +159,15 @@ class RenderWidgetCompositor : public blink::WebLayerTreeView,
void Initialize(cc::LayerTreeSettings settings);
bool threaded_;
- bool suppress_schedule_composite_;
RenderWidget* widget_;
scoped_ptr<cc::LayerTreeHost> layer_tree_host_;
+
+ scoped_ptr<cc::CopyOutputRequest> temporary_copy_output_request_;
+
+ bool send_v8_idle_notification_after_commit_;
+ base::TimeTicks begin_main_frame_time_;
+ // The time interval between BeginMainFrame calls, provided by the scheduler.
+ base::TimeDelta begin_main_frame_interval_;
};
} // namespace content
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
new file mode 100644
index 00000000000..94c5baf6e63
--- /dev/null
+++ b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 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 "content/renderer/gpu/render_widget_compositor.h"
+
+#include "cc/output/begin_frame_args.h"
+#include "content/public/test/mock_render_thread.h"
+#include "content/renderer/render_widget.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+
+using testing::AllOf;
+using testing::Field;
+
+namespace content {
+
+class MockWebWidget : public blink::WebWidget {
+ public:
+ MOCK_METHOD1(beginFrame, void(const blink::WebBeginFrameArgs& args));
+};
+
+class TestRenderWidget : public RenderWidget {
+ public:
+ TestRenderWidget()
+ : RenderWidget(blink::WebPopupTypeNone,
+ blink::WebScreenInfo(),
+ true,
+ false,
+ false) {
+ webwidget_ = &mock_webwidget_;
+ }
+
+ MockWebWidget mock_webwidget_;
+
+ private:
+ ~TestRenderWidget() override { webwidget_ = NULL; }
+
+ DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
+};
+
+class RenderWidgetCompositorTest : public testing::Test {
+ public:
+ RenderWidgetCompositorTest()
+ : render_widget_(make_scoped_refptr(new TestRenderWidget())),
+ render_widget_compositor_(
+ RenderWidgetCompositor::Create(render_widget_.get(), false)) {}
+ ~RenderWidgetCompositorTest() override {}
+
+ protected:
+ MockRenderThread render_thread_;
+ scoped_refptr<TestRenderWidget> render_widget_;
+ scoped_ptr<RenderWidgetCompositor> render_widget_compositor_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositorTest);
+};
+
+TEST_F(RenderWidgetCompositorTest, BeginMainFrame) {
+ base::TimeTicks frame_time(base::TimeTicks() +
+ base::TimeDelta::FromSeconds(1));
+ base::TimeTicks deadline(base::TimeTicks() + base::TimeDelta::FromSeconds(2));
+ base::TimeDelta interval(base::TimeDelta::FromSeconds(3));
+ cc::BeginFrameArgs args(
+ cc::BeginFrameArgs::Create(frame_time, deadline, interval));
+
+ EXPECT_CALL(render_widget_->mock_webwidget_,
+ beginFrame(AllOf(
+ Field(&blink::WebBeginFrameArgs::lastFrameTimeMonotonic, 1),
+ Field(&blink::WebBeginFrameArgs::deadline, 2),
+ Field(&blink::WebBeginFrameArgs::interval, 3))));
+
+ render_widget_compositor_->BeginMainFrame(args);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/gpu/stream_texture_host_android.h b/chromium/content/renderer/gpu/stream_texture_host_android.h
index 005d49d3009..4bd841381bf 100644
--- a/chromium/content/renderer/gpu/stream_texture_host_android.h
+++ b/chromium/content/renderer/gpu/stream_texture_host_android.h
@@ -38,8 +38,8 @@ class StreamTextureHost : public IPC::Listener {
bool BindToCurrentThread(int32 stream_id, Listener* listener);
// IPC::Channel::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
+ virtual void OnChannelError() override;
private:
// Message handlers:
diff --git a/chromium/content/renderer/history_controller.cc b/chromium/content/renderer/history_controller.cc
index 4c171510fc8..d6f1abdf5e3 100644
--- a/chromium/content/renderer/history_controller.cc
+++ b/chromium/content/renderer/history_controller.cc
@@ -37,7 +37,7 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
using blink::WebFrame;
using blink::WebHistoryCommitType;
@@ -60,7 +60,7 @@ void HistoryController::GoToEntry(scoped_ptr<HistoryEntry> target_entry,
provisional_entry_ = target_entry.Pass();
- WebFrame* main_frame = render_view_->main_render_frame()->GetWebFrame();
+ WebFrame* main_frame = render_view_->GetMainRenderFrame()->GetWebFrame();
if (current_entry_) {
RecursiveGoToEntry(
main_frame, same_document_loads, different_document_loads);
diff --git a/chromium/content/renderer/history_entry.cc b/chromium/content/renderer/history_entry.cc
index 63c1ea0f1d3..d1425165a87 100644
--- a/chromium/content/renderer/history_entry.cc
+++ b/chromium/content/renderer/history_entry.cc
@@ -37,13 +37,23 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
using blink::WebFrame;
using blink::WebHistoryItem;
namespace content {
+// Frame routing ids are not safe to serialize, so instead create a mapping
+// from routing ids to frame sequence numbers. The sequence numbers can be
+// benignly serialized with limited risk of collision in a different process.
+// FrameMap is a singleton per-process.
+typedef base::hash_map<uint64_t, uint64_t> FrameMap;
+static FrameMap& GetFrameMap() {
+ CR_DEFINE_STATIC_LOCAL(FrameMap, routing_ids_to_internal_frame_ids, ());
+ return routing_ids_to_internal_frame_ids;
+}
+
HistoryEntry::HistoryNode* HistoryEntry::HistoryNode::AddChild(
const WebHistoryItem& item,
int64_t frame_id) {
@@ -96,6 +106,7 @@ void HistoryEntry::HistoryNode::set_item(const WebHistoryItem& item) {
// The previous HistoryItem might not have had a target set, or it might be
// different than the current one.
entry_->unique_names_to_items_[item.target().utf8()] = this;
+ entry_->frames_to_items_[item.frameSequenceNumber()] = this;
item_ = item;
}
@@ -103,10 +114,20 @@ HistoryEntry::HistoryNode::HistoryNode(HistoryEntry* entry,
const WebHistoryItem& item,
int64_t frame_id)
: entry_(entry), item_(item) {
- if (frame_id != kInvalidFrameRoutingID)
- entry_->frames_to_items_[frame_id] = this;
- if (!item.isNull())
- entry_->unique_names_to_items_[item.target().utf8()] = this;
+ if (frame_id != kInvalidFrameRoutingID) {
+ // Each history item is given a frame sequence number on creation.
+ // If we've already mapped this frame id to a sequence number, standardize
+ // this item to that sequence number. Otherwise, map the frame id to this
+ // item's existing sequence number.
+ if (GetFrameMap()[frame_id] == 0)
+ GetFrameMap()[frame_id] = item_.frameSequenceNumber();
+ else if (!item_.isNull())
+ item_.setFrameSequenceNumber(GetFrameMap()[frame_id]);
+ entry_->frames_to_items_[GetFrameMap()[frame_id]] = this;
+ }
+
+ if (!item_.isNull())
+ entry_->unique_names_to_items_[item_.target().utf8()] = this;
children_.reset(new ScopedVector<HistoryNode>);
}
@@ -130,7 +151,7 @@ void HistoryEntry::HistoryNode::RemoveChildren() {
it != frames_end;
++it) {
if (it->second == children().at(i))
- frames_to_remove.push_back(it->first);
+ frames_to_remove.push_back(GetFrameMap()[it->first]);
}
for (HistoryEntry::UniqueNamesToItems::iterator it =
entry_->unique_names_to_items_.begin();
@@ -168,13 +189,14 @@ HistoryEntry* HistoryEntry::CloneAndReplace(const WebHistoryItem& new_item,
new_item,
clone_children_of_target,
target_frame,
- render_view->main_render_frame()));
+ render_view->GetMainRenderFrame()));
return new_entry;
}
HistoryEntry::HistoryNode* HistoryEntry::GetHistoryNodeForFrame(
RenderFrameImpl* frame) {
- if (HistoryNode* history_node = frames_to_items_[frame->GetRoutingID()])
+ if (HistoryNode* history_node =
+ frames_to_items_[GetFrameMap()[frame->GetRoutingID()]])
return history_node;
return unique_names_to_items_[frame->GetWebFrame()->uniqueName().utf8()];
}
diff --git a/chromium/content/renderer/history_serialization.cc b/chromium/content/renderer/history_serialization.cc
index 56325a681e0..7a8167bcfa0 100644
--- a/chromium/content/renderer/history_serialization.cc
+++ b/chromium/content/renderer/history_serialization.cc
@@ -94,12 +94,15 @@ void GenerateFrameStateFromItem(const WebHistoryItem& item,
state->item_sequence_number = item.itemSequenceNumber();
state->document_sequence_number =
item.documentSequenceNumber();
+ state->frame_sequence_number =
+ item.frameSequenceNumber();
state->page_scale_factor = item.pageScaleFactor();
ToNullableString16Vector(item.documentState(), &state->document_state);
state->http_body.http_content_type = item.httpContentType();
const WebHTTPBody& http_body = item.httpBody();
- if (!(state->http_body.is_null = http_body.isNull())) {
+ state->http_body.is_null = http_body.isNull();
+ if (!state->http_body.is_null) {
state->http_body.identifier = http_body.identifier();
state->http_body.elements.resize(http_body.elementCount());
for (size_t i = 0; i < http_body.elementCount(); ++i) {
@@ -144,6 +147,8 @@ void RecursivelyGenerateHistoryItem(const ExplodedFrameState& state,
item.setItemSequenceNumber(state.item_sequence_number);
if (state.document_sequence_number)
item.setDocumentSequenceNumber(state.document_sequence_number);
+ if (state.frame_sequence_number)
+ item.setFrameSequenceNumber(state.frame_sequence_number);
item.setHTTPContentType(state.http_body.http_content_type);
if (!state.http_body.is_null) {
diff --git a/chromium/content/renderer/ico_image_decoder_unittest.cc b/chromium/content/renderer/ico_image_decoder_unittest.cc
index b59cfe38251..5d1f235a30c 100644
--- a/chromium/content/renderer/ico_image_decoder_unittest.cc
+++ b/chromium/content/renderer/ico_image_decoder_unittest.cc
@@ -13,7 +13,7 @@ class ICOImageDecoderTest : public ImageDecoderTest {
ICOImageDecoderTest() : ImageDecoderTest("ico") { }
protected:
- virtual blink::WebImageDecoder* CreateWebKitImageDecoder() const OVERRIDE {
+ blink::WebImageDecoder* CreateWebKitImageDecoder() const override {
return new blink::WebImageDecoder(blink::WebImageDecoder::TypeICO);
}
};
diff --git a/chromium/content/renderer/idle_user_detector.h b/chromium/content/renderer/idle_user_detector.h
index a5ee80bdd29..86a7eac6f35 100644
--- a/chromium/content/renderer/idle_user_detector.h
+++ b/chromium/content/renderer/idle_user_detector.h
@@ -23,11 +23,11 @@ namespace content {
class IdleUserDetector : public RenderViewObserver {
public:
IdleUserDetector(RenderView* render_view);
- virtual ~IdleUserDetector();
+ ~IdleUserDetector() override;
private:
// RenderViewObserver implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnHandleInputEvent(const blink::WebInputEvent* event,
const ui::LatencyInfo& latency_info,
diff --git a/chromium/content/renderer/image_loading_helper.cc b/chromium/content/renderer/image_loading_helper.cc
index 1eb98dc57a6..b0099ffce5b 100644
--- a/chromium/content/renderer/image_loading_helper.cc
+++ b/chromium/content/renderer/image_loading_helper.cc
@@ -14,7 +14,7 @@
#include "skia/ext/image_operations.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/size.h"
@@ -141,8 +141,8 @@ bool ImageLoadingHelper::DownloadImage(int id,
image_url,
render_frame()->GetWebFrame(),
id,
- is_favicon ? WebURLRequest::TargetIsFavicon :
- WebURLRequest::TargetIsImage,
+ is_favicon ? WebURLRequest::RequestContextFavicon
+ : WebURLRequest::RequestContextImage,
base::Bind(&ImageLoadingHelper::DidDownloadImage,
base::Unretained(this),
max_image_size)));
diff --git a/chromium/content/renderer/image_loading_helper.h b/chromium/content/renderer/image_loading_helper.h
index a7d24d6f0fc..185f3b7e4f1 100644
--- a/chromium/content/renderer/image_loading_helper.h
+++ b/chromium/content/renderer/image_loading_helper.h
@@ -25,7 +25,7 @@ class ImageLoadingHelper : public RenderFrameObserver {
explicit ImageLoadingHelper(RenderFrame* render_frame);
private:
- virtual ~ImageLoadingHelper();
+ ~ImageLoadingHelper() override;
// Message handler.
void OnDownloadImage(int id,
@@ -60,7 +60,7 @@ class ImageLoadingHelper : public RenderFrameObserver {
SkBitmap ImageFromDataUrl(const GURL&) const;
// RenderFrameObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
typedef ScopedVector<MultiResolutionImageResourceFetcher>
ImageResourceFetcherList;
diff --git a/chromium/content/renderer/in_process_renderer_thread.h b/chromium/content/renderer/in_process_renderer_thread.h
index bc5a5d3d2cf..4b4bc65608f 100644
--- a/chromium/content/renderer/in_process_renderer_thread.h
+++ b/chromium/content/renderer/in_process_renderer_thread.h
@@ -18,11 +18,11 @@ class RenderProcess;
class InProcessRendererThread : public base::Thread {
public:
explicit InProcessRendererThread(const std::string& channel_id);
- virtual ~InProcessRendererThread();
+ ~InProcessRendererThread() override;
protected:
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void CleanUp() override;
private:
std::string channel_id_;
diff --git a/chromium/content/renderer/input/input_event_filter.cc b/chromium/content/renderer/input/input_event_filter.cc
index fa31658a74b..d93836a981e 100644
--- a/chromium/content/renderer/input/input_event_filter.cc
+++ b/chromium/content/renderer/input/input_event_filter.cc
@@ -10,6 +10,7 @@
#include "base/debug/trace_event.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
#include "cc/input/input_handler.h"
#include "content/common/input/did_overscroll_params.h"
#include "content/common/input/web_input_event_traits.h"
@@ -41,8 +42,9 @@ namespace content {
InputEventFilter::InputEventFilter(
IPC::Listener* main_listener,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const scoped_refptr<base::MessageLoopProxy>& target_loop)
- : main_loop_(base::MessageLoopProxy::current()),
+ : main_task_runner_(main_task_runner),
main_listener_(main_listener),
sender_(NULL),
target_loop_(target_loop),
@@ -55,7 +57,7 @@ InputEventFilter::InputEventFilter(
}
void InputEventFilter::SetBoundHandler(const Handler& handler) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
handler_ = handler;
}
@@ -148,10 +150,9 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
"input",
"InputEventFilter::ForwardToHandler::ForwardToMainListener",
TRACE_EVENT_SCOPE_THREAD);
- main_loop_->PostTask(
+ main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&InputEventFilter::ForwardToMainListener,
- this, message));
+ base::Bind(&InputEventFilter::ForwardToMainListener, this, message));
return;
}
@@ -164,12 +165,14 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
bool is_keyboard_shortcut = params.c;
DCHECK(event);
+ const bool send_ack = !WebInputEventTraits::IgnoresAckDisposition(*event);
+
// Intercept |DidOverscroll| notifications, bundling any triggered overscroll
// response with the input event ack.
scoped_ptr<DidOverscrollParams> overscroll_params;
base::AutoReset<scoped_ptr<DidOverscrollParams>*>
- auto_reset_current_overscroll_params(&current_overscroll_params_,
- &overscroll_params);
+ auto_reset_current_overscroll_params(
+ &current_overscroll_params_, send_ack ? &overscroll_params : NULL);
InputEventAckState ack_state = handler_.Run(routing_id, event, &latency_info);
@@ -181,14 +184,13 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
TRACE_EVENT_SCOPE_THREAD);
IPC::Message new_msg = InputMsg_HandleInputEvent(
routing_id, event, latency_info, is_keyboard_shortcut);
- main_loop_->PostTask(
+ main_task_runner_->PostTask(
FROM_HERE,
- base::Bind(&InputEventFilter::ForwardToMainListener,
- this, new_msg));
+ base::Bind(&InputEventFilter::ForwardToMainListener, this, new_msg));
return;
}
- if (WebInputEventTraits::IgnoresAckDisposition(*event))
+ if (!send_ack)
return;
InputHostMsg_HandleInputEvent_ACK_Params ack;
diff --git a/chromium/content/renderer/input/input_event_filter.h b/chromium/content/renderer/input/input_event_filter.h
index a80b9f8c625..e7982f6ffd4 100644
--- a/chromium/content/renderer/input/input_event_filter.h
+++ b/chromium/content/renderer/input/input_event_filter.h
@@ -18,6 +18,7 @@
namespace base {
class MessageLoopProxy;
+class SingleThreadTaskRunner;
}
namespace IPC {
@@ -38,8 +39,10 @@ namespace content {
class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
public IPC::MessageFilter {
public:
- InputEventFilter(IPC::Listener* main_listener,
- const scoped_refptr<base::MessageLoopProxy>& target_loop);
+ InputEventFilter(
+ IPC::Listener* main_listener,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
+ const scoped_refptr<base::MessageLoopProxy>& target_loop);
// The |handler| is invoked on the thread associated with |target_loop| to
// handle input events matching the filtered routes.
@@ -51,29 +54,29 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
// is left to the eventual handler to deliver the corresponding
// InputHostMsg_HandleInputEvent_ACK.
//
- virtual void SetBoundHandler(const Handler& handler) OVERRIDE;
- virtual void DidAddInputHandler(int routing_id,
- cc::InputHandler* input_handler) OVERRIDE;
- virtual void DidRemoveInputHandler(int routing_id) OVERRIDE;
- virtual void DidOverscroll(int routing_id,
- const DidOverscrollParams& params) OVERRIDE;
- virtual void DidStopFlinging(int routing_id) OVERRIDE;
+ void SetBoundHandler(const Handler& handler) override;
+ void DidAddInputHandler(int routing_id,
+ cc::InputHandler* input_handler) override;
+ void DidRemoveInputHandler(int routing_id) override;
+ void DidOverscroll(int routing_id,
+ const DidOverscrollParams& params) override;
+ void DidStopFlinging(int routing_id) override;
// IPC::MessageFilter methods:
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
- virtual ~InputEventFilter();
+ ~InputEventFilter() override;
void ForwardToMainListener(const IPC::Message& message);
void ForwardToHandler(const IPC::Message& message);
void SendMessage(scoped_ptr<IPC::Message> message);
void SendMessageOnIOThread(scoped_ptr<IPC::Message> message);
- scoped_refptr<base::MessageLoopProxy> main_loop_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
IPC::Listener* main_listener_;
// The sender_ only gets invoked on the thread corresponding to io_loop_.
diff --git a/chromium/content/renderer/input/input_event_filter_unittest.cc b/chromium/content/renderer/input/input_event_filter_unittest.cc
index a234e793fdc..b7befdb67cc 100644
--- a/chromium/content/renderer/input/input_event_filter_unittest.cc
+++ b/chromium/content/renderer/input/input_event_filter_unittest.cc
@@ -80,7 +80,7 @@ class InputEventRecorder {
class IPCMessageRecorder : public IPC::Listener {
public:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnMessageReceived(const IPC::Message& message) override {
messages_.push_back(message);
return true;
}
@@ -125,10 +125,10 @@ void AddEventsToFilter(IPC::MessageFilter* message_filter,
class InputEventFilterTest : public testing::Test {
public:
- virtual void SetUp() OVERRIDE {
- filter_ = new InputEventFilter(
- &message_recorder_,
- message_loop_.message_loop_proxy());
+ void SetUp() override {
+ filter_ = new InputEventFilter(&message_recorder_,
+ base::MessageLoopProxy::current(),
+ message_loop_.message_loop_proxy());
filter_->SetBoundHandler(
base::Bind(&InputEventRecorder::HandleInputEvent,
base::Unretained(&event_recorder_)));
diff --git a/chromium/content/renderer/input/input_handler_proxy.cc b/chromium/content/renderer/input/input_handler_proxy.cc
index 951cec10d97..44b613914b3 100644
--- a/chromium/content/renderer/input/input_handler_proxy.cc
+++ b/chromium/content/renderer/input/input_handler_proxy.cc
@@ -5,11 +5,13 @@
#include "content/renderer/input/input_handler_proxy.h"
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "content/common/input/did_overscroll_params.h"
#include "content/common/input/web_input_event_traits.h"
+#include "content/public/common/content_switches.h"
#include "content/renderer/input/input_handler_proxy_client.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -68,7 +70,7 @@ bool ShouldSuppressScrollForFlingBoosting(
gfx::Vector2dF dx(scroll_update_event.data.scrollUpdate.deltaX,
scroll_update_event.data.scrollUpdate.deltaY);
- if (gfx::DotProduct(current_fling_velocity, dx) < 0)
+ if (gfx::DotProduct(current_fling_velocity, dx) <= 0)
return false;
if (time_since_last_boost_event < 0.001)
@@ -92,7 +94,7 @@ bool ShouldBoostFling(const gfx::Vector2dF& current_fling_velocity,
fling_start_event.data.flingStart.velocityX,
fling_start_event.data.flingStart.velocityY);
- if (gfx::DotProduct(current_fling_velocity, new_fling_velocity) < 0)
+ if (gfx::DotProduct(current_fling_velocity, new_fling_velocity) <= 0)
return false;
if (current_fling_velocity.LengthSquared() < kMinBoostFlingSpeedSquare)
@@ -157,6 +159,8 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler,
has_fling_animation_started_(false) {
DCHECK(client);
input_handler_->BindToClient(this);
+ smooth_scroll_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableSmoothScrolling);
}
InputHandlerProxy::~InputHandlerProxy() {}
@@ -174,11 +178,10 @@ InputHandlerProxy::HandleInputEventWithLatencyInfo(
SendScrollLatencyUma(event, *latency_info);
- TRACE_EVENT_FLOW_STEP0(
- "input",
- "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency_info->trace_id),
- "HanldeInputEventImpl");
+ TRACE_EVENT_FLOW_STEP0("input",
+ "LatencyInfo.Flow",
+ TRACE_ID_DONT_MANGLE(latency_info->trace_id),
+ "HandleInputEventImpl");
scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
input_handler_->CreateLatencyInfoSwapPromiseMonitor(latency_info);
@@ -192,6 +195,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
TRACE_EVENT1("input", "InputHandlerProxy::HandleInputEvent",
"type", WebInputEventTraits::GetName(event.type));
+ client_->DidReceiveInputEvent();
if (FilterInputEventForFlingBoosting(event))
return DID_HANDLE;
@@ -208,6 +212,20 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
// event handlers. Forward to the main thread.
return DID_NOT_HANDLE;
}
+ if (smooth_scroll_enabled_) {
+ cc::InputHandler::ScrollStatus scroll_status =
+ input_handler_->ScrollAnimated(
+ gfx::Point(wheel_event.x, wheel_event.y),
+ gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY));
+ switch (scroll_status) {
+ case cc::InputHandler::ScrollStarted:
+ return DID_HANDLE;
+ case cc::InputHandler::ScrollIgnored:
+ return DROP_EVENT;
+ default:
+ return DID_NOT_HANDLE;
+ }
+ }
cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin(
gfx::Point(wheel_event.x, wheel_event.y), cc::InputHandler::Wheel);
switch (scroll_status) {
@@ -220,11 +238,13 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
-wheel_event.deltaX,
"deltaY",
-wheel_event.deltaY);
- bool did_scroll = input_handler_->ScrollBy(
- gfx::Point(wheel_event.x, wheel_event.y),
- gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY));
+ gfx::Point scroll_point(wheel_event.x, wheel_event.y);
+ gfx::Vector2dF scroll_delta(-wheel_event.deltaX, -wheel_event.deltaY);
+ cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy(
+ scroll_point, scroll_delta);
+ HandleOverscroll(scroll_point, scroll_result);
input_handler_->ScrollEnd();
- return did_scroll ? DID_HANDLE : DROP_EVENT;
+ return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
}
case cc::InputHandler::ScrollIgnored:
// TODO(jamesr): This should be DROP_EVENT, but in cases where we fail
@@ -279,11 +299,13 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
const WebGestureEvent& gesture_event =
*static_cast<const WebGestureEvent*>(&event);
- bool did_scroll = input_handler_->ScrollBy(
- gfx::Point(gesture_event.x, gesture_event.y),
- gfx::Vector2dF(-gesture_event.data.scrollUpdate.deltaX,
- -gesture_event.data.scrollUpdate.deltaY));
- return did_scroll ? DID_HANDLE : DROP_EVENT;
+ gfx::Point scroll_point(gesture_event.x, gesture_event.y);
+ gfx::Vector2dF scroll_delta(-gesture_event.data.scrollUpdate.deltaX,
+ -gesture_event.data.scrollUpdate.deltaY);
+ cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy(
+ scroll_point, scroll_delta);
+ HandleOverscroll(scroll_point, scroll_result);
+ return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
} else if (event.type == WebInputEvent::GestureScrollEnd) {
#ifndef NDEBUG
DCHECK(expect_scroll_update_end_);
@@ -319,7 +341,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
*static_cast<const WebGestureEvent*>(&event);
return HandleGestureFling(gesture_event);
} else if (event.type == WebInputEvent::GestureFlingCancel) {
- if (CancelCurrentFling(true))
+ if (CancelCurrentFling())
return DID_HANDLE;
else if (!fling_may_be_active_on_main_thread_)
return DROP_EVENT;
@@ -340,7 +362,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
// Only call |CancelCurrentFling()| if a fling was active, as it will
// otherwise disrupt an in-progress touch scroll.
if (fling_curve_)
- CancelCurrentFling(true);
+ CancelCurrentFling();
} else if (event.type == WebInputEvent::MouseMove) {
const WebMouseEvent& mouse_event =
*static_cast<const WebMouseEvent*>(&event);
@@ -468,7 +490,7 @@ bool InputHandlerProxy::FilterInputEventForFlingBoosting(
// Gestures from a different source should immediately interrupt the fling.
if (gesture_event.sourceDevice != fling_parameters_.sourceDevice) {
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return false;
}
@@ -483,13 +505,13 @@ bool InputHandlerProxy::FilterInputEventForFlingBoosting(
fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchpad
? cc::InputHandler::NonBubblingGesture
: cc::InputHandler::Gesture)) {
- CancelCurrentFling(true);
+ CancelCurrentFling();
return false;
}
// TODO(jdduke): Use |gesture_event.data.scrollBegin.delta{X,Y}Hint| to
// determine if the ScrollBegin should immediately cancel the fling.
- FlingBoostExtend(gesture_event);
+ ExtendBoostedFlingTimeout(gesture_event);
return true;
case WebInputEvent::GestureScrollUpdate: {
@@ -498,16 +520,19 @@ bool InputHandlerProxy::FilterInputEventForFlingBoosting(
if (ShouldSuppressScrollForFlingBoosting(current_fling_velocity_,
gesture_event,
time_since_last_boost_event)) {
- FlingBoostExtend(gesture_event);
+ ExtendBoostedFlingTimeout(gesture_event);
return true;
}
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return false;
}
case WebInputEvent::GestureScrollEnd:
- CancelCurrentFling(true);
+ // Clear the last fling boost event *prior* to fling cancellation,
+ // preventing insertion of a synthetic GestureScrollBegin.
+ last_fling_boost_event_ = WebGestureEvent();
+ CancelCurrentFling();
return true;
case WebInputEvent::GestureFlingStart: {
@@ -529,6 +554,8 @@ bool InputHandlerProxy::FilterInputEventForFlingBoosting(
WebFloatPoint velocity(current_fling_velocity_.x(),
current_fling_velocity_.y());
deferred_fling_cancel_time_seconds_ = 0;
+ disallow_horizontal_fling_scroll_ = !velocity.x;
+ disallow_vertical_fling_scroll_ = !velocity.y;
last_fling_boost_event_ = WebGestureEvent();
fling_curve_.reset(client_->CreateFlingAnimationCurve(
gesture_event.sourceDevice,
@@ -559,36 +586,21 @@ bool InputHandlerProxy::FilterInputEventForFlingBoosting(
default:
// All other types of gestures (taps, presses, etc...) will complete the
// deferred fling cancellation.
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return false;
}
}
-void InputHandlerProxy::FlingBoostExtend(const blink::WebGestureEvent& event) {
- TRACE_EVENT_INSTANT0(
- "input", "InputHandlerProxy::FlingBoostExtend", TRACE_EVENT_SCOPE_THREAD);
+void InputHandlerProxy::ExtendBoostedFlingTimeout(
+ const blink::WebGestureEvent& event) {
+ TRACE_EVENT_INSTANT0("input",
+ "InputHandlerProxy::ExtendBoostedFlingTimeout",
+ TRACE_EVENT_SCOPE_THREAD);
deferred_fling_cancel_time_seconds_ =
event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds;
last_fling_boost_event_ = event;
}
-void InputHandlerProxy::FlingBoostCancelAndResumeScrollingIfNecessary() {
- TRACE_EVENT_INSTANT0(
- "input", "InputHandlerProxy::FlingBoostCancel", TRACE_EVENT_SCOPE_THREAD);
- DCHECK(deferred_fling_cancel_time_seconds_);
-
- // Note: |last_fling_boost_event_| is cleared by |CancelCurrentFling()|.
- WebGestureEvent last_fling_boost_event = last_fling_boost_event_;
-
- CancelCurrentFling(true);
-
- if (last_fling_boost_event.type == WebInputEvent::GestureScrollBegin ||
- last_fling_boost_event.type == WebInputEvent::GestureScrollUpdate) {
- // Synthesize a GestureScrollBegin, as the original was suppressed.
- HandleInputEvent(ObtainGestureScrollBegin(last_fling_boost_event));
- }
-}
-
void InputHandlerProxy::Animate(base::TimeTicks time) {
if (!fling_curve_)
return;
@@ -597,7 +609,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) {
if (deferred_fling_cancel_time_seconds_ &&
monotonic_time_sec > deferred_fling_cancel_time_seconds_) {
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return;
}
@@ -628,7 +640,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) {
TRACE_EVENT_INSTANT0("input",
"InputHandlerProxy::animate::flingOver",
TRACE_EVENT_SCOPE_THREAD);
- CancelCurrentFling(true);
+ CancelCurrentFling();
}
}
@@ -637,23 +649,26 @@ void InputHandlerProxy::MainThreadHasStoppedFlinging() {
client_->DidStopFlinging();
}
-void InputHandlerProxy::DidOverscroll(
- const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta) {
+void InputHandlerProxy::HandleOverscroll(
+ const gfx::Point& causal_event_viewport_point,
+ const cc::InputHandlerScrollResult& scroll_result) {
DCHECK(client_);
+ if (!scroll_result.did_overscroll_root)
+ return;
TRACE_EVENT2("input",
"InputHandlerProxy::DidOverscroll",
"dx",
- latest_overscroll_delta.x(),
+ scroll_result.unused_scroll_delta.x(),
"dy",
- latest_overscroll_delta.y());
+ scroll_result.unused_scroll_delta.y());
DidOverscrollParams params;
- params.accumulated_overscroll = accumulated_overscroll;
- params.latest_overscroll_delta = latest_overscroll_delta;
+ params.accumulated_overscroll = scroll_result.accumulated_root_overscroll;
+ params.latest_overscroll_delta = scroll_result.unused_scroll_delta;
params.current_fling_velocity =
ToClientScrollIncrement(current_fling_velocity_);
+ params.causal_event_viewport_point = causal_event_viewport_point;
if (fling_curve_) {
static const int kFlingOverscrollThreshold = 1;
@@ -668,8 +683,15 @@ void InputHandlerProxy::DidOverscroll(
client_->DidOverscroll(params);
}
-bool InputHandlerProxy::CancelCurrentFling(
- bool send_fling_stopped_notification) {
+bool InputHandlerProxy::CancelCurrentFling() {
+ if (CancelCurrentFlingWithoutNotifyingClient()) {
+ client_->DidStopFlinging();
+ return true;
+ }
+ return false;
+}
+
+bool InputHandlerProxy::CancelCurrentFlingWithoutNotifyingClient() {
bool had_fling_animation = fling_curve_;
if (had_fling_animation &&
fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchscreen) {
@@ -690,10 +712,19 @@ bool InputHandlerProxy::CancelCurrentFling(
gesture_scroll_on_impl_thread_ = false;
current_fling_velocity_ = gfx::Vector2dF();
fling_parameters_ = blink::WebActiveWheelFlingParameters();
- deferred_fling_cancel_time_seconds_ = 0;
- last_fling_boost_event_ = WebGestureEvent();
- if (send_fling_stopped_notification && had_fling_animation)
- client_->DidStopFlinging();
+
+ if (deferred_fling_cancel_time_seconds_) {
+ deferred_fling_cancel_time_seconds_ = 0;
+
+ WebGestureEvent last_fling_boost_event = last_fling_boost_event_;
+ last_fling_boost_event_ = WebGestureEvent();
+ if (last_fling_boost_event.type == WebInputEvent::GestureScrollBegin ||
+ last_fling_boost_event.type == WebInputEvent::GestureScrollUpdate) {
+ // Synthesize a GestureScrollBegin, as the original was suppressed.
+ HandleInputEvent(ObtainGestureScrollBegin(last_fling_boost_event));
+ }
+ }
+
return had_fling_animation;
}
@@ -729,7 +760,7 @@ bool InputHandlerProxy::TouchpadFlingScroll(
// the subarea but then is flung "under" the pointer.
client_->TransferActiveWheelFlingAnimation(fling_parameters_);
fling_may_be_active_on_main_thread_ = true;
- CancelCurrentFling(false);
+ CancelCurrentFlingWithoutNotifyingClient();
break;
}
@@ -769,11 +800,13 @@ bool InputHandlerProxy::scrollBy(const WebFloatSize& increment,
case blink::WebGestureDeviceTouchpad:
did_scroll = TouchpadFlingScroll(clipped_increment);
break;
- case blink::WebGestureDeviceTouchscreen:
+ case blink::WebGestureDeviceTouchscreen: {
clipped_increment = ToClientScrollIncrement(clipped_increment);
- did_scroll = input_handler_->ScrollBy(fling_parameters_.point,
- clipped_increment);
- break;
+ cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy(
+ fling_parameters_.point, clipped_increment);
+ HandleOverscroll(fling_parameters_.point, scroll_result);
+ did_scroll = scroll_result.did_scroll;
+ } break;
}
if (did_scroll) {
diff --git a/chromium/content/renderer/input/input_handler_proxy.h b/chromium/content/renderer/input/input_handler_proxy.h
index de54fa2afe2..39f4346b252 100644
--- a/chromium/content/renderer/input/input_handler_proxy.h
+++ b/chromium/content/renderer/input/input_handler_proxy.h
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/containers/hash_tables.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "cc/input/input_handler.h"
#include "content/common/content_export.h"
@@ -42,12 +43,9 @@ class CONTENT_EXPORT InputHandlerProxy
EventDisposition HandleInputEvent(const blink::WebInputEvent& event);
// cc::InputHandlerClient implementation.
- virtual void WillShutdown() OVERRIDE;
- virtual void Animate(base::TimeTicks time) OVERRIDE;
- virtual void MainThreadHasStoppedFlinging() OVERRIDE;
- virtual void DidOverscroll(const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta)
- OVERRIDE;
+ void WillShutdown() override;
+ void Animate(base::TimeTicks time) override;
+ void MainThreadHasStoppedFlinging() override;
// blink::WebGestureCurveTarget implementation.
virtual bool scrollBy(const blink::WebFloatSize& offset,
@@ -66,16 +64,24 @@ class CONTENT_EXPORT InputHandlerProxy
// Schedule a time in the future after which a boost-enabled fling will
// terminate without further momentum from the user (see |Animate()|).
- void FlingBoostExtend(const blink::WebGestureEvent& event);
-
- // Cancel the current fling and insert a GestureScrollBegin if necessary.
- void FlingBoostCancelAndResumeScrollingIfNecessary();
+ void ExtendBoostedFlingTimeout(const blink::WebGestureEvent& event);
// Returns true if we scrolled by the increment.
bool TouchpadFlingScroll(const blink::WebFloatSize& increment);
+ // Returns true if we actually had an active fling to cancel, also notifying
+ // the client that the fling has ended. Note that if a boosted fling is active
+ // and suppressing an active scroll sequence, a synthetic GestureScrollBegin
+ // will be injected to resume scrolling.
+ bool CancelCurrentFling();
+
// Returns true if we actually had an active fling to cancel.
- bool CancelCurrentFling(bool send_fling_stopped_notification);
+ bool CancelCurrentFlingWithoutNotifyingClient();
+
+ // Used to send overscroll messages to the browser.
+ void HandleOverscroll(
+ const gfx::Point& causal_event_viewport_point,
+ const cc::InputHandlerScrollResult& scroll_result);
scoped_ptr<blink::WebGestureCurve> fling_curve_;
// Parameters for the active fling animation, stored in case we need to
@@ -91,7 +97,7 @@ class CONTENT_EXPORT InputHandlerProxy
// The last event that extended the lifetime of the boosted fling. If the
// event was a scroll gesture, a GestureScrollBegin will be inserted if the
- // fling terminates (via |FlingBoostCancelAndResumeScrollingIfNecessary()|).
+ // fling terminates (via |CancelCurrentFling()|).
blink::WebGestureEvent last_fling_boost_event_;
#ifndef NDEBUG
@@ -116,6 +122,8 @@ class CONTENT_EXPORT InputHandlerProxy
// Non-zero only within the scope of |scrollBy|.
gfx::Vector2dF current_fling_velocity_;
+ bool smooth_scroll_enabled_;
+
DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy);
};
diff --git a/chromium/content/renderer/input/input_handler_proxy_client.h b/chromium/content/renderer/input/input_handler_proxy_client.h
index 70b4186f749..bbb91e842c5 100644
--- a/chromium/content/renderer/input/input_handler_proxy_client.h
+++ b/chromium/content/renderer/input/input_handler_proxy_client.h
@@ -38,6 +38,8 @@ class InputHandlerProxyClient {
virtual void DidStopFlinging() = 0;
+ virtual void DidReceiveInputEvent() = 0;
+
protected:
virtual ~InputHandlerProxyClient() {}
};
diff --git a/chromium/content/renderer/input/input_handler_proxy_unittest.cc b/chromium/content/renderer/input/input_handler_proxy_unittest.cc
index 29c1b0de827..49fa56a72f3 100644
--- a/chromium/content/renderer/input/input_handler_proxy_unittest.cc
+++ b/chromium/content/renderer/input/input_handler_proxy_unittest.cc
@@ -86,9 +86,13 @@ class MockInputHandler : public cc::InputHandler {
MOCK_METHOD2(ScrollBegin,
ScrollStatus(const gfx::Point& viewport_point,
cc::InputHandler::ScrollInputType type));
+ MOCK_METHOD2(ScrollAnimated,
+ ScrollStatus(const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta));
MOCK_METHOD2(ScrollBy,
- bool(const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta));
+ cc::InputHandlerScrollResult(
+ const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta));
MOCK_METHOD2(ScrollVerticallyByPage,
bool(const gfx::Point& viewport_point,
cc::ScrollDirection direction));
@@ -96,18 +100,13 @@ class MockInputHandler : public cc::InputHandler {
MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
virtual scoped_ptr<cc::SwapPromiseMonitor>
- CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) OVERRIDE {
+ CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) override {
return scoped_ptr<cc::SwapPromiseMonitor>();
}
- virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {}
-
- virtual void StartPageScaleAnimation(const gfx::Vector2d& target_offset,
- bool anchor_point,
- float page_scale,
- base::TimeDelta duration) OVERRIDE {}
+ virtual void BindToClient(cc::InputHandlerClient* client) override {}
- virtual void MouseMoveAt(const gfx::Point& mouse_position) OVERRIDE {}
+ virtual void MouseMoveAt(const gfx::Point& mouse_position) override {}
MOCK_METHOD2(IsCurrentlyScrollingLayerAt,
bool(const gfx::Point& point,
@@ -117,9 +116,9 @@ class MockInputHandler : public cc::InputHandler {
virtual void SetRootLayerScrollOffsetDelegate(
cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate)
- OVERRIDE {}
+ override {}
- virtual void OnRootLayerDelegatedScrollOffsetChanged() OVERRIDE {}
+ virtual void OnRootLayerDelegatedScrollOffsetChanged() override {}
DISALLOW_COPY_AND_ASSIGN(MockInputHandler);
};
@@ -160,7 +159,7 @@ class MockInputHandlerProxyClient
MockInputHandlerProxyClient() {}
virtual ~MockInputHandlerProxyClient() {}
- virtual void WillShutdown() OVERRIDE {}
+ virtual void WillShutdown() override {}
MOCK_METHOD1(TransferActiveWheelFlingAnimation,
void(const WebActiveWheelFlingParameters&));
@@ -168,19 +167,32 @@ class MockInputHandlerProxyClient
virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
WebGestureDevice deviceSource,
const WebFloatPoint& velocity,
- const WebSize& cumulative_scroll) OVERRIDE {
+ const WebSize& cumulative_scroll) override {
return new FakeWebGestureCurve(
blink::WebFloatSize(velocity.x, velocity.y),
blink::WebFloatSize(cumulative_scroll.width, cumulative_scroll.height));
}
MOCK_METHOD1(DidOverscroll, void(const DidOverscrollParams&));
- virtual void DidStopFlinging() OVERRIDE {}
+ virtual void DidStopFlinging() override {}
+ virtual void DidReceiveInputEvent() override {}
private:
DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
};
+class MockInputHandlerProxyClientWithDidReceiveInputEvent
+ : public MockInputHandlerProxyClient {
+ public:
+ MockInputHandlerProxyClientWithDidReceiveInputEvent() {}
+ virtual ~MockInputHandlerProxyClientWithDidReceiveInputEvent() {}
+
+ MOCK_METHOD0(DidReceiveInputEvent, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClientWithDidReceiveInputEvent);
+};
+
WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state, float x,
float y) {
WebTouchPoint point;
@@ -196,6 +208,8 @@ class InputHandlerProxyTest : public testing::Test {
: expected_disposition_(InputHandlerProxy::DID_HANDLE) {
input_handler_.reset(
new content::InputHandlerProxy(&mock_input_handler_, &mock_client_));
+ scroll_result_did_scroll_.did_scroll = true;
+ scroll_result_did_not_scroll_.did_scroll = false;
}
~InputHandlerProxyTest() {
@@ -253,8 +267,9 @@ class InputHandlerProxyTest : public testing::Test {
scoped_ptr<content::InputHandlerProxy> input_handler_;
testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
WebGestureEvent gesture_;
-
InputHandlerProxy::EventDisposition expected_disposition_;
+ cc::InputHandlerScrollResult scroll_result_did_scroll_;
+ cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
};
TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) {
@@ -298,7 +313,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollStarted) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(false));
+ .WillOnce(testing::Return(scroll_result_did_not_scroll_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
// Mark the event as handled if scroll happens.
@@ -311,7 +326,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollStarted) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -445,7 +460,7 @@ TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -590,7 +605,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd());
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -693,7 +708,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd());
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -794,7 +809,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd());
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -966,7 +981,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -1020,7 +1035,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
time += dt;
input_handler_->Animate(time);
@@ -1083,7 +1098,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
time += base::TimeDelta::FromMilliseconds(10);
input_handler_->Animate(time);
@@ -1150,7 +1165,7 @@ TEST_F(InputHandlerProxyTest,
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -1176,10 +1191,10 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
WebFloatPoint fling_delta = WebFloatPoint(100, 100);
gesture_.data.flingStart.velocityX = fling_delta.x;
gesture_.data.flingStart.velocityY = fling_delta.y;
- EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
@@ -1190,32 +1205,48 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The second animate starts scrolling in the positive X and Y directions.
- EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
- // Simulate hitting the bottom content edge.
- gfx::Vector2dF accumulated_overscroll(0, 100);
- gfx::Vector2dF latest_overscroll_delta(0, 10);
- EXPECT_CALL(mock_client_,
- DidOverscroll(testing::AllOf(
- testing::Field(&DidOverscrollParams::accumulated_overscroll,
- testing::Eq(accumulated_overscroll)),
- testing::Field(&DidOverscrollParams::latest_overscroll_delta,
- testing::Eq(latest_overscroll_delta)),
- testing::Field(
- &DidOverscrollParams::current_fling_velocity,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))));
- input_handler_->DidOverscroll(accumulated_overscroll,
- latest_overscroll_delta);
+ // The third animate overscrolls in the positive Y direction but scrolls
+ // somewhat.
+ cc::InputHandlerScrollResult overscroll;
+ overscroll.did_scroll = true;
+ overscroll.did_overscroll_root = true;
+ overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100);
+ overscroll.unused_scroll_delta = gfx::Vector2dF(0, 10);
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
+ .WillOnce(testing::Return(overscroll));
+ EXPECT_CALL(
+ mock_client_,
+ DidOverscroll(testing::AllOf(
+ testing::Field(
+ &DidOverscrollParams::accumulated_overscroll,
+ testing::Eq(overscroll.accumulated_root_overscroll)),
+ testing::Field(
+ &DidOverscrollParams::latest_overscroll_delta,
+ testing::Eq(overscroll.unused_scroll_delta)),
+ testing::Field(
+ &DidOverscrollParams::current_fling_velocity,
+ testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ time += base::TimeDelta::FromMilliseconds(100);
+ input_handler_->Animate(time);
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The next call to animate will no longer scroll vertically.
EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
@@ -1224,7 +1255,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_CALL(mock_input_handler_, ScrollEnd());
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -1279,7 +1310,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(false));
+ .WillOnce(testing::Return(scroll_result_did_not_scroll_));
time += base::TimeDelta::FromMicroseconds(5);
input_handler_->Animate(time);
@@ -1300,7 +1331,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(1))))
- .WillOnce(testing::Return(false));
+ .WillOnce(testing::Return(scroll_result_did_not_scroll_));
time += base::TimeDelta::FromMilliseconds(100);
input_handler_->Animate(time);
@@ -1309,6 +1340,10 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) {
}
TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
+ cc::InputHandlerScrollResult overscroll;
+ overscroll.did_scroll = true;
+ overscroll.did_overscroll_root = true;
+
// We shouldn't send any events to the widget for this gesture.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
VERIFY_AND_RESET_MOCKS();
@@ -1343,55 +1378,73 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
time += base::TimeDelta::FromMilliseconds(10);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
- // Simulate hitting the bottom content edge.
- gfx::Vector2dF accumulated_overscroll(0, 100);
- gfx::Vector2dF latest_overscroll_delta(0, 100);
- EXPECT_CALL(mock_client_,
- DidOverscroll(testing::AllOf(
- testing::Field(&DidOverscrollParams::accumulated_overscroll,
- testing::Eq(accumulated_overscroll)),
- testing::Field(&DidOverscrollParams::latest_overscroll_delta,
- testing::Eq(latest_overscroll_delta)),
- testing::Field(
- &DidOverscrollParams::current_fling_velocity,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))));
- input_handler_->DidOverscroll(accumulated_overscroll,
- latest_overscroll_delta);
+ // The third animate hits the bottom content edge.
+ overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100);
+ overscroll.unused_scroll_delta = gfx::Vector2dF(0, 100);
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
+ .WillOnce(testing::Return(overscroll));
+ EXPECT_CALL(
+ mock_client_,
+ DidOverscroll(testing::AllOf(
+ testing::Field(
+ &DidOverscrollParams::accumulated_overscroll,
+ testing::Eq(overscroll.accumulated_root_overscroll)),
+ testing::Field(
+ &DidOverscrollParams::latest_overscroll_delta,
+ testing::Eq(overscroll.unused_scroll_delta)),
+ testing::Field(
+ &DidOverscrollParams::current_fling_velocity,
+ testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))));
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ time += base::TimeDelta::FromMilliseconds(10);
+ input_handler_->Animate(time);
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The next call to animate will no longer scroll vertically.
EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ time += base::TimeDelta::FromMilliseconds(10);
+ input_handler_->Animate(time);
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // The next call will hit the right edge.
+ overscroll.accumulated_root_overscroll = gfx::Vector2dF(100, 100);
+ overscroll.unused_scroll_delta = gfx::Vector2dF(100, 0);
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
+ .WillOnce(testing::Return(overscroll));
+ EXPECT_CALL(
+ mock_client_,
+ DidOverscroll(testing::AllOf(
+ testing::Field(
+ &DidOverscrollParams::accumulated_overscroll,
+ testing::Eq(overscroll.accumulated_root_overscroll)),
+ testing::Field(
+ &DidOverscrollParams::latest_overscroll_delta,
+ testing::Eq(overscroll.unused_scroll_delta)),
+ testing::Field(
+ &DidOverscrollParams::current_fling_velocity,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
time += base::TimeDelta::FromMilliseconds(10);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
- // Simulate hitting the right content edge.
- accumulated_overscroll = gfx::Vector2dF(100, 100);
- latest_overscroll_delta = gfx::Vector2dF(100, 0);
- EXPECT_CALL(mock_client_,
- DidOverscroll(testing::AllOf(
- testing::Field(&DidOverscrollParams::accumulated_overscroll,
- testing::Eq(accumulated_overscroll)),
- testing::Field(&DidOverscrollParams::latest_overscroll_delta,
- testing::Eq(latest_overscroll_delta)),
- testing::Field(
- &DidOverscrollParams::current_fling_velocity,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))));
- input_handler_->DidOverscroll(accumulated_overscroll,
- latest_overscroll_delta);
// The next call to animate will no longer scroll horizontally or vertically,
// and the fling should be cancelled.
EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()).Times(0);
EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
time += base::TimeDelta::FromMilliseconds(10);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
@@ -1555,7 +1608,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) {
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
input_handler_->Animate(time + base::TimeDelta::FromMilliseconds(1));
@@ -1602,7 +1655,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) {
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x,
testing::Eq(expected_delta))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
input_handler_->Animate(time);
last_animate_time = time;
@@ -1626,7 +1679,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) {
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x,
testing::Eq(expected_delta))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
input_handler_->Animate(time);
last_animate_time = time;
@@ -1652,7 +1705,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) {
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x,
testing::Eq(expected_delta))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
input_handler_->Animate(time);
last_animate_time = time;
@@ -1678,7 +1731,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) {
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x,
testing::Eq(expected_delta))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
input_handler_->Animate(time);
last_animate_time = time;
@@ -1768,6 +1821,48 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) {
VERIFY_AND_RESET_MOCKS();
}
+TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // If the new fling is orthogonal to the existing fling, no boosting should
+ // take place, with the new fling replacing the old.
+ WebFloatPoint orthogonal_fling_delta =
+ WebFloatPoint(fling_delta.y, -fling_delta.x);
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ orthogonal_fling_delta,
+ fling_point,
+ fling_point,
+ 0);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Note that the new fling delta uses the orthogonal, unboosted fling
+ // velocity.
+ time += dt;
+ float expected_delta = dt.InSecondsF() * -orthogonal_fling_delta.y;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::y,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) {
base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
base::TimeTicks time = base::TimeTicks() + dt;
@@ -1807,7 +1902,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) {
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x,
testing::Eq(fling_delta.x))))
- .WillOnce(testing::Return(true));
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
@@ -1847,10 +1942,97 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) {
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x,
testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ base::TimeTicks last_animate_time = time;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Now cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // The GestureScrollBegin should be swallowed by the fling.
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ EXPECT_CALL(mock_input_handler_,
+ IsCurrentlyScrollingLayerAt(testing::_, testing::_))
.WillOnce(testing::Return(true));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Now animate the fling to completion (in this case, the fling should
+ // terminate because the input handler reports a failed scroll). As the fling
+ // was cancelled during an active scroll sequence, a synthetic
+ // GestureScrollBegin should be processed, resuming the scroll.
+ time += dt;
+ float expected_delta =
+ (time - last_animate_time).InSecondsF() * -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(scroll_result_did_not_scroll_));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
input_handler_->Animate(time);
VERIFY_AND_RESET_MOCKS();
+
+ // Subsequent GestureScrollUpdates after the cancelled, boosted fling should
+ // cause scrolling as usual.
+ time += dt;
+ expected_delta = 7.3f;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollUpdate;
+ gesture_.data.scrollUpdate.deltaX = -expected_delta;
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // GestureScrollEnd should terminate the resumed scroll properly.
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollEnd;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, DidReceiveInputEvent) {
+ testing::StrictMock<
+ MockInputHandlerProxyClientWithDidReceiveInputEvent> mock_client;
+ input_handler_.reset(
+ new content::InputHandlerProxy(&mock_input_handler_, &mock_client));
+
+ // Note the type of input event isn't important.
+ WebMouseWheelEvent wheel;
+ wheel.type = WebInputEvent::MouseWheel;
+ wheel.scrollByPage = true;
+
+ EXPECT_CALL(mock_client, DidReceiveInputEvent());
+
+ input_handler_->HandleInputEvent(wheel);
+ testing::Mock::VerifyAndClearExpectations(&mock_client);
}
} // namespace
diff --git a/chromium/content/renderer/input/input_handler_wrapper.cc b/chromium/content/renderer/input/input_handler_wrapper.cc
index 6ff0033939a..e53f624a831 100644
--- a/chromium/content/renderer/input/input_handler_wrapper.cc
+++ b/chromium/content/renderer/input/input_handler_wrapper.cc
@@ -57,4 +57,8 @@ void InputHandlerWrapper::DidStopFlinging() {
input_handler_manager_->DidStopFlinging(routing_id_);
}
+void InputHandlerWrapper::DidReceiveInputEvent() {
+ // TODO(skyostil): Hook this up into the renderer scheduler.
+}
+
} // namespace content
diff --git a/chromium/content/renderer/input/input_handler_wrapper.h b/chromium/content/renderer/input/input_handler_wrapper.h
index 9f4ebf0688c..fd997ce2803 100644
--- a/chromium/content/renderer/input/input_handler_wrapper.h
+++ b/chromium/content/renderer/input/input_handler_wrapper.h
@@ -20,21 +20,22 @@ class InputHandlerWrapper : public InputHandlerProxyClient {
const scoped_refptr<base::MessageLoopProxy>& main_loop,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl);
- virtual ~InputHandlerWrapper();
+ ~InputHandlerWrapper() override;
int routing_id() const { return routing_id_; }
InputHandlerProxy* input_handler_proxy() { return &input_handler_proxy_; }
// InputHandlerProxyClient implementation.
- virtual void WillShutdown() OVERRIDE;
- virtual void TransferActiveWheelFlingAnimation(
- const blink::WebActiveWheelFlingParameters& params) OVERRIDE;
- virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
+ void WillShutdown() override;
+ void TransferActiveWheelFlingAnimation(
+ const blink::WebActiveWheelFlingParameters& params) override;
+ blink::WebGestureCurve* CreateFlingAnimationCurve(
blink::WebGestureDevice deviceSource,
const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulativeScroll) OVERRIDE;
- virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
- virtual void DidStopFlinging() OVERRIDE;
+ const blink::WebSize& cumulativeScroll) override;
+ void DidOverscroll(const DidOverscrollParams& params) override;
+ void DidStopFlinging() override;
+ void DidReceiveInputEvent() override;
private:
InputHandlerManager* input_handler_manager_;
diff --git a/chromium/content/renderer/input/input_scroll_elasticity_controller.cc b/chromium/content/renderer/input/input_scroll_elasticity_controller.cc
new file mode 100644
index 00000000000..059bc9d5127
--- /dev/null
+++ b/chromium/content/renderer/input/input_scroll_elasticity_controller.cc
@@ -0,0 +1,473 @@
+// Copyright 2014 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 "content/renderer/input/input_scroll_elasticity_controller.h"
+
+#include <math.h>
+
+// ScrollElasticityController and ScrollElasticityControllerClient are based on
+// WebKit/Source/platform/mac/ScrollElasticityController.mm
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace content {
+
+namespace {
+
+// TODO(ccameron): This is advertised as system uptime, but it used to compute
+// deltas against the event timestamps, which are in seconds since epoch. Find
+// out which is right. Also, avoid querying time, and use frame time instead.
+double SystemUptime() {
+ return base::Time::Now().ToDoubleT();
+}
+
+const float kScrollVelocityZeroingTimeout = 0.10f;
+const float kRubberbandDirectionLockStretchRatio = 1;
+const float kRubberbandMinimumRequiredDeltaBeforeStretch = 10;
+
+const float kRubberbandStiffness = 20;
+const float kRubberbandAmplitude = 0.31f;
+const float kRubberbandPeriod = 1.6f;
+
+float ElasticDeltaForTimeDelta(float initial_position,
+ float initial_velocity,
+ float elapsed_time) {
+ float amplitude = kRubberbandAmplitude;
+ float period = kRubberbandPeriod;
+ float critical_dampening_factor =
+ expf((-elapsed_time * kRubberbandStiffness) / period);
+
+ return (initial_position + (-initial_velocity * elapsed_time * amplitude)) *
+ critical_dampening_factor;
+}
+
+float ElasticDeltaForReboundDelta(float delta) {
+ float stiffness = std::max(kRubberbandStiffness, 1.0f);
+ return delta / stiffness;
+}
+
+float ReboundDeltaForElasticDelta(float delta) {
+ return delta * kRubberbandStiffness;
+}
+
+float ScrollWheelMultiplier() {
+ static float multiplier = -1;
+ if (multiplier < 0) {
+ // TODO(ccameron): Find a place fo this in an Objective C file, or find an
+ // equivalent C call.
+ // multiplier = [[NSUserDefaults standardUserDefaults]
+ // floatForKey:@"NSScrollWheelMultiplier"];
+ if (multiplier <= 0)
+ multiplier = 1;
+ }
+ return multiplier;
+}
+
+} // namespace
+
+ScrollElasticityController::ScrollElasticityController(
+ ScrollElasticityControllerClient* client)
+ : client_(client),
+ in_scroll_gesture_(false),
+ has_scrolled_(false),
+ momentum_scroll_in_progress_(false),
+ ignore_momentum_scrolls_(false),
+ last_momentum_scroll_timestamp_(0),
+ snap_rubberband_timer_is_active_(false) {
+}
+
+bool ScrollElasticityController::HandleWheelEvent(
+ const blink::WebMouseWheelEvent& wheel_event) {
+ if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseMayBegin)
+ return false;
+
+ if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseBegan) {
+ in_scroll_gesture_ = true;
+ has_scrolled_ = false;
+ momentum_scroll_in_progress_ = false;
+ ignore_momentum_scrolls_ = false;
+ last_momentum_scroll_timestamp_ = 0;
+ momentum_velocity_ = gfx::Vector2dF();
+
+ gfx::Vector2dF stretch_amount = client_->StretchAmount();
+ stretch_scroll_force_.set_x(
+ ReboundDeltaForElasticDelta(stretch_amount.x()));
+ stretch_scroll_force_.set_y(
+ ReboundDeltaForElasticDelta(stretch_amount.y()));
+ overflow_scroll_delta_ = gfx::Vector2dF();
+
+ StopSnapRubberbandTimer();
+
+ // TODO(erikchen): Use the commented out line once Chromium uses the
+ // return value correctly.
+ // crbug.com/375512
+ // return ShouldHandleEvent(wheel_event);
+
+ // This logic is incorrect, since diagonal wheel events are not consumed.
+ if (client_->PinnedInDirection(gfx::Vector2dF(-wheel_event.deltaX, 0))) {
+ if (wheel_event.deltaX > 0 && !wheel_event.canRubberbandLeft)
+ return false;
+ if (wheel_event.deltaX < 0 && !wheel_event.canRubberbandRight)
+ return false;
+ }
+
+ return true;
+ }
+
+ if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseEnded ||
+ wheel_event.phase == blink::WebMouseWheelEvent::PhaseCancelled) {
+ SnapRubberband();
+ return has_scrolled_;
+ }
+
+ bool isMomentumScrollEvent =
+ (wheel_event.momentumPhase != blink::WebMouseWheelEvent::PhaseNone);
+ if (ignore_momentum_scrolls_ &&
+ (isMomentumScrollEvent || snap_rubberband_timer_is_active_)) {
+ if (wheel_event.momentumPhase == blink::WebMouseWheelEvent::PhaseEnded) {
+ ignore_momentum_scrolls_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ if (!ShouldHandleEvent(wheel_event))
+ return false;
+
+ float delta_x = overflow_scroll_delta_.x() - wheel_event.deltaX;
+ float delta_y = overflow_scroll_delta_.y() - wheel_event.deltaY;
+ float event_coalesced_delta_x = -wheel_event.deltaX;
+ float event_coalesced_delta_y = -wheel_event.deltaY;
+
+ // Reset overflow values because we may decide to remove delta at various
+ // points and put it into overflow.
+ overflow_scroll_delta_ = gfx::Vector2dF();
+
+ gfx::Vector2dF stretch_amount = client_->StretchAmount();
+ bool is_vertically_stretched = stretch_amount.y() != 0.f;
+ bool is_horizontally_stretched = stretch_amount.x() != 0.f;
+
+ // Slightly prefer scrolling vertically by applying the = case to delta_y
+ if (fabsf(delta_y) >= fabsf(delta_x))
+ delta_x = 0;
+ else
+ delta_y = 0;
+
+ bool should_stretch = false;
+
+ blink::WebMouseWheelEvent::Phase momentum_phase = wheel_event.momentumPhase;
+
+ // If we are starting momentum scrolling then do some setup.
+ if (!momentum_scroll_in_progress_ &&
+ (momentum_phase == blink::WebMouseWheelEvent::PhaseBegan ||
+ momentum_phase == blink::WebMouseWheelEvent::PhaseChanged)) {
+ momentum_scroll_in_progress_ = true;
+ // Start the snap rubber band timer if it's not running. This is needed to
+ // snap back from the over scroll caused by momentum events.
+ if (!snap_rubberband_timer_is_active_ && start_time_ == base::Time())
+ SnapRubberband();
+ }
+
+ double time_delta =
+ wheel_event.timeStampSeconds - last_momentum_scroll_timestamp_;
+ if (in_scroll_gesture_ || momentum_scroll_in_progress_) {
+ if (last_momentum_scroll_timestamp_ && time_delta > 0 &&
+ time_delta < kScrollVelocityZeroingTimeout) {
+ momentum_velocity_.set_x(event_coalesced_delta_x / (float)time_delta);
+ momentum_velocity_.set_y(event_coalesced_delta_y / (float)time_delta);
+ last_momentum_scroll_timestamp_ = wheel_event.timeStampSeconds;
+ } else {
+ last_momentum_scroll_timestamp_ = wheel_event.timeStampSeconds;
+ momentum_velocity_ = gfx::Vector2dF();
+ }
+
+ if (is_vertically_stretched) {
+ if (!is_horizontally_stretched &&
+ client_->PinnedInDirection(gfx::Vector2dF(delta_x, 0))) {
+ // Stretching only in the vertical.
+ if (delta_y != 0 &&
+ (fabsf(delta_x / delta_y) < kRubberbandDirectionLockStretchRatio))
+ delta_x = 0;
+ else if (fabsf(delta_x) <
+ kRubberbandMinimumRequiredDeltaBeforeStretch) {
+ overflow_scroll_delta_.set_x(overflow_scroll_delta_.x() + delta_x);
+ delta_x = 0;
+ } else
+ overflow_scroll_delta_.set_x(overflow_scroll_delta_.x() + delta_x);
+ }
+ } else if (is_horizontally_stretched) {
+ // Stretching only in the horizontal.
+ if (client_->PinnedInDirection(gfx::Vector2dF(0, delta_y))) {
+ if (delta_x != 0 &&
+ (fabsf(delta_y / delta_x) < kRubberbandDirectionLockStretchRatio))
+ delta_y = 0;
+ else if (fabsf(delta_y) <
+ kRubberbandMinimumRequiredDeltaBeforeStretch) {
+ overflow_scroll_delta_.set_y(overflow_scroll_delta_.y() + delta_y);
+ delta_y = 0;
+ } else
+ overflow_scroll_delta_.set_y(overflow_scroll_delta_.y() + delta_y);
+ }
+ } else {
+ // Not stretching at all yet.
+ if (client_->PinnedInDirection(gfx::Vector2dF(delta_x, delta_y))) {
+ if (fabsf(delta_y) >= fabsf(delta_x)) {
+ if (fabsf(delta_x) < kRubberbandMinimumRequiredDeltaBeforeStretch) {
+ overflow_scroll_delta_.set_x(overflow_scroll_delta_.x() + delta_x);
+ delta_x = 0;
+ } else
+ overflow_scroll_delta_.set_x(overflow_scroll_delta_.x() + delta_x);
+ }
+ should_stretch = true;
+ }
+ }
+ }
+
+ if (delta_x != 0 || delta_y != 0) {
+ has_scrolled_ = true;
+ if (!(should_stretch || is_vertically_stretched ||
+ is_horizontally_stretched)) {
+ if (delta_y != 0) {
+ delta_y *= ScrollWheelMultiplier();
+ client_->ImmediateScrollBy(gfx::Vector2dF(0, delta_y));
+ }
+ if (delta_x != 0) {
+ delta_x *= ScrollWheelMultiplier();
+ client_->ImmediateScrollBy(gfx::Vector2dF(delta_x, 0));
+ }
+ } else {
+ if (!client_->AllowsHorizontalStretching()) {
+ delta_x = 0;
+ event_coalesced_delta_x = 0;
+ } else if ((delta_x != 0) && !is_horizontally_stretched &&
+ !client_->PinnedInDirection(gfx::Vector2dF(delta_x, 0))) {
+ delta_x *= ScrollWheelMultiplier();
+
+ client_->ImmediateScrollByWithoutContentEdgeConstraints(
+ gfx::Vector2dF(delta_x, 0));
+ delta_x = 0;
+ }
+
+ if (!client_->AllowsVerticalStretching()) {
+ delta_y = 0;
+ event_coalesced_delta_y = 0;
+ } else if ((delta_y != 0) && !is_vertically_stretched &&
+ !client_->PinnedInDirection(gfx::Vector2dF(0, delta_y))) {
+ delta_y *= ScrollWheelMultiplier();
+
+ client_->ImmediateScrollByWithoutContentEdgeConstraints(
+ gfx::Vector2dF(0, delta_y));
+ delta_y = 0;
+ }
+
+ gfx::Vector2dF stretch_amount = client_->StretchAmount();
+
+ if (momentum_scroll_in_progress_) {
+ if ((client_->PinnedInDirection(gfx::Vector2dF(
+ event_coalesced_delta_x, event_coalesced_delta_y)) ||
+ (fabsf(event_coalesced_delta_x) + fabsf(event_coalesced_delta_y) <=
+ 0)) &&
+ last_momentum_scroll_timestamp_) {
+ ignore_momentum_scrolls_ = true;
+ momentum_scroll_in_progress_ = false;
+ SnapRubberband();
+ }
+ }
+
+ stretch_scroll_force_.set_x(stretch_scroll_force_.x() + delta_x);
+ stretch_scroll_force_.set_y(stretch_scroll_force_.y() + delta_y);
+
+ gfx::Vector2dF damped_delta(
+ ceilf(ElasticDeltaForReboundDelta(stretch_scroll_force_.x())),
+ ceilf(ElasticDeltaForReboundDelta(stretch_scroll_force_.y())));
+
+ client_->ImmediateScrollByWithoutContentEdgeConstraints(damped_delta -
+ stretch_amount);
+ }
+ }
+
+ if (momentum_scroll_in_progress_ &&
+ momentum_phase == blink::WebMouseWheelEvent::PhaseEnded) {
+ momentum_scroll_in_progress_ = false;
+ ignore_momentum_scrolls_ = false;
+ last_momentum_scroll_timestamp_ = 0;
+ }
+
+ return true;
+}
+
+namespace {
+
+float RoundTowardZero(float num) {
+ return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
+}
+
+float RoundToDevicePixelTowardZero(float num) {
+ float rounded_num = roundf(num);
+ if (fabs(num - rounded_num) < 0.125)
+ num = rounded_num;
+
+ return RoundTowardZero(num);
+}
+
+} // namespace
+
+void ScrollElasticityController::SnapRubberbandTimerFired() {
+ if (!momentum_scroll_in_progress_ || ignore_momentum_scrolls_) {
+ float time_delta = (base::Time::Now() - start_time_).InSecondsF();
+
+ if (start_stretch_ == gfx::Vector2dF()) {
+ start_stretch_ = client_->StretchAmount();
+ if (start_stretch_ == gfx::Vector2dF()) {
+ StopSnapRubberbandTimer();
+
+ stretch_scroll_force_ = gfx::Vector2dF();
+ start_time_ = base::Time();
+ orig_origin_ = gfx::Vector2dF();
+ orig_velocity_ = gfx::Vector2dF();
+ return;
+ }
+
+ orig_origin_ = client_->AbsoluteScrollPosition() - start_stretch_;
+ orig_velocity_ = momentum_velocity_;
+
+ // Just like normal scrolling, prefer vertical rubberbanding
+ if (fabsf(orig_velocity_.y()) >= fabsf(orig_velocity_.x()))
+ orig_velocity_.set_x(0);
+
+ // Don't rubber-band horizontally if it's not possible to scroll
+ // horizontally
+ if (!client_->CanScrollHorizontally())
+ orig_velocity_.set_x(0);
+
+ // Don't rubber-band vertically if it's not possible to scroll
+ // vertically
+ if (!client_->CanScrollVertically())
+ orig_velocity_.set_y(0);
+ }
+
+ gfx::Vector2dF delta(
+ RoundToDevicePixelTowardZero(ElasticDeltaForTimeDelta(
+ start_stretch_.x(), -orig_velocity_.x(), time_delta)),
+ RoundToDevicePixelTowardZero(ElasticDeltaForTimeDelta(
+ start_stretch_.y(), -orig_velocity_.y(), time_delta)));
+
+ if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
+ client_->ImmediateScrollByWithoutContentEdgeConstraints(
+ gfx::Vector2dF(delta.x(), delta.y()) - client_->StretchAmount());
+
+ gfx::Vector2dF new_stretch = client_->StretchAmount();
+
+ stretch_scroll_force_.set_x(ReboundDeltaForElasticDelta(new_stretch.x()));
+ stretch_scroll_force_.set_y(ReboundDeltaForElasticDelta(new_stretch.y()));
+ } else {
+ client_->AdjustScrollPositionToBoundsIfNecessary();
+
+ StopSnapRubberbandTimer();
+ stretch_scroll_force_ = gfx::Vector2dF();
+ start_time_ = base::Time();
+ start_stretch_ = gfx::Vector2dF();
+ orig_origin_ = gfx::Vector2dF();
+ orig_velocity_ = gfx::Vector2dF();
+ }
+ } else {
+ start_time_ = base::Time::Now();
+ start_stretch_ = gfx::Vector2dF();
+ }
+}
+
+bool ScrollElasticityController::IsRubberbandInProgress() const {
+ if (!in_scroll_gesture_ && !momentum_scroll_in_progress_ &&
+ !snap_rubberband_timer_is_active_)
+ return false;
+
+ return !client_->StretchAmount().IsZero();
+}
+
+void ScrollElasticityController::StopSnapRubberbandTimer() {
+ client_->StopSnapRubberbandTimer();
+ snap_rubberband_timer_is_active_ = false;
+}
+
+void ScrollElasticityController::SnapRubberband() {
+ double time_delta = SystemUptime() - last_momentum_scroll_timestamp_;
+ if (last_momentum_scroll_timestamp_ &&
+ time_delta >= kScrollVelocityZeroingTimeout)
+ momentum_velocity_ = gfx::Vector2dF();
+
+ in_scroll_gesture_ = false;
+
+ if (snap_rubberband_timer_is_active_)
+ return;
+
+ start_stretch_ = gfx::Vector2dF();
+ orig_origin_ = gfx::Vector2dF();
+ orig_velocity_ = gfx::Vector2dF();
+
+ // If there's no momentum scroll or stretch amount, no need to start the
+ // timer.
+ if (!momentum_scroll_in_progress_ &&
+ client_->StretchAmount() == gfx::Vector2dF()) {
+ start_time_ = base::Time();
+ stretch_scroll_force_ = gfx::Vector2dF();
+ return;
+ }
+
+ start_time_ = base::Time::Now();
+ client_->StartSnapRubberbandTimer();
+ snap_rubberband_timer_is_active_ = true;
+}
+
+bool ScrollElasticityController::ShouldHandleEvent(
+ const blink::WebMouseWheelEvent& wheel_event) {
+ // Once any scrolling has happened, all future events should be handled.
+ if (has_scrolled_)
+ return true;
+
+ // The event can't cause scrolling to start if its delta is 0.
+ if (wheel_event.deltaX == 0 && wheel_event.deltaY == 0)
+ return false;
+
+ // If the client isn't pinned, then the event is guaranteed to cause
+ // scrolling.
+ if (!client_->PinnedInDirection(gfx::Vector2dF(-wheel_event.deltaX, 0)))
+ return true;
+
+ // If the event is pinned, then the client can't scroll, but it might rubber
+ // band.
+ // Check if the event allows rubber banding.
+ if (wheel_event.deltaY == 0) {
+ if (wheel_event.deltaX > 0 && !wheel_event.canRubberbandLeft)
+ return false;
+ if (wheel_event.deltaX < 0 && !wheel_event.canRubberbandRight)
+ return false;
+ }
+
+ // The event is going to either cause scrolling or rubber banding.
+ return true;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/input/input_scroll_elasticity_controller.h b/chromium/content/renderer/input/input_scroll_elasticity_controller.h
new file mode 100644
index 00000000000..79cb4ed4c13
--- /dev/null
+++ b/chromium/content/renderer/input/input_scroll_elasticity_controller.h
@@ -0,0 +1,143 @@
+// Copyright 2014 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 CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
+#define CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+
+// ScrollElasticityController and ScrollElasticityControllerClient are based on
+// WebKit/Source/platform/mac/ScrollElasticityController.h
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace content {
+
+class ScrollElasticityControllerClient {
+ protected:
+ virtual ~ScrollElasticityControllerClient() {}
+
+ public:
+ virtual bool AllowsHorizontalStretching() = 0;
+ virtual bool AllowsVerticalStretching() = 0;
+ // The amount that the view is stretched past the normal allowable bounds.
+ // The "overhang" amount.
+ virtual gfx::Vector2dF StretchAmount() = 0;
+ virtual bool PinnedInDirection(const gfx::Vector2dF& direction) = 0;
+ virtual bool CanScrollHorizontally() = 0;
+ virtual bool CanScrollVertically() = 0;
+
+ // Return the absolute scroll position, not relative to the scroll origin.
+ virtual gfx::Vector2dF AbsoluteScrollPosition() = 0;
+
+ virtual void ImmediateScrollBy(const gfx::Vector2dF& scroll) = 0;
+ virtual void ImmediateScrollByWithoutContentEdgeConstraints(
+ const gfx::Vector2dF& scroll) = 0;
+ virtual void StartSnapRubberbandTimer() = 0;
+ virtual void StopSnapRubberbandTimer() = 0;
+
+ // If the current scroll position is within the overhang area, this function
+ // will cause
+ // the page to scroll to the nearest boundary point.
+ virtual void AdjustScrollPositionToBoundsIfNecessary() = 0;
+};
+
+class ScrollElasticityController {
+ public:
+ explicit ScrollElasticityController(ScrollElasticityControllerClient*);
+
+ // This method is responsible for both scrolling and rubber-banding.
+ //
+ // Events are passed by IPC from the embedder. Events on Mac are grouped
+ // into "gestures". If this method returns 'true', then this object has
+ // handled the event. It expects the embedder to continue to forward events
+ // from the gesture.
+ //
+ // This method makes the assumption that there is only 1 input device being
+ // used at a time. If the user simultaneously uses multiple input devices,
+ // Cocoa does not correctly pass all the gestureBegin/End events. The state
+ // of this class is guaranteed to become eventually consistent, once the
+ // user stops using multiple input devices.
+ bool HandleWheelEvent(const blink::WebMouseWheelEvent& wheel_event);
+ void SnapRubberbandTimerFired();
+
+ bool IsRubberbandInProgress() const;
+
+ private:
+ void StopSnapRubberbandTimer();
+ void SnapRubberband();
+
+ // This method determines whether a given event should be handled. The
+ // logic for control events of gestures (PhaseBegan, PhaseEnded) is handled
+ // elsewhere.
+ //
+ // This class handles almost all wheel events. All of the following
+ // conditions must be met for this class to ignore an event:
+ // + No previous events in this gesture have caused any scrolling or rubber
+ // banding.
+ // + The event contains a horizontal component.
+ // + The client's view is pinned in the horizontal direction of the event.
+ // + The wheel event disallows rubber banding in the horizontal direction
+ // of the event.
+ bool ShouldHandleEvent(const blink::WebMouseWheelEvent& wheel_event);
+
+ ScrollElasticityControllerClient* client_;
+
+ // There is an active scroll gesture event. This parameter only gets set to
+ // false after the rubber band has been snapped, and before a new gesture
+ // has begun. A careful audit of the code may deprecate the need for this
+ // parameter.
+ bool in_scroll_gesture_;
+ // At least one event in the current gesture has been consumed and has
+ // caused the view to scroll or rubber band. All future events in this
+ // gesture will be consumed and overscrolls will cause rubberbanding.
+ bool has_scrolled_;
+ bool momentum_scroll_in_progress_;
+ bool ignore_momentum_scrolls_;
+
+ // Used with blink::WebInputEvent::timeStampSeconds, in seconds since epoch.
+ double last_momentum_scroll_timestamp_;
+ gfx::Vector2dF overflow_scroll_delta_;
+ gfx::Vector2dF stretch_scroll_force_;
+ gfx::Vector2dF momentum_velocity_;
+
+ // Rubber band state.
+ base::Time start_time_;
+ gfx::Vector2dF start_stretch_;
+ gfx::Vector2dF orig_origin_;
+ gfx::Vector2dF orig_velocity_;
+
+ bool snap_rubberband_timer_is_active_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScrollElasticityController);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
diff --git a/chromium/content/renderer/internal_document_state_data.h b/chromium/content/renderer/internal_document_state_data.h
index def89de1810..27567c8fe50 100644
--- a/chromium/content/renderer/internal_document_state_data.h
+++ b/chromium/content/renderer/internal_document_state_data.h
@@ -37,16 +37,6 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
did_first_visually_non_empty_layout_ = value;
}
- // Set to true once RenderViewImpl::DidFlushPaint() is inovked after
- // RenderViewImpl::didFirstVisuallyNonEmptyLayout(). In other words after the
- // page has painted something.
- bool did_first_visually_non_empty_paint() const {
- return did_first_visually_non_empty_paint_;
- }
- void set_did_first_visually_non_empty_paint(bool value) {
- did_first_visually_non_empty_paint_ = value;
- }
-
int http_status_code() const { return http_status_code_; }
void set_http_status_code(int http_status_code) {
http_status_code_ = http_status_code;
@@ -103,7 +93,7 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
}
protected:
- virtual ~InternalDocumentStateData();
+ ~InternalDocumentStateData() override;
private:
bool did_first_visually_non_empty_layout_;
diff --git a/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc b/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc
index 88d502e5ca4..400d58f3dea 100644
--- a/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_dispatcher.cc
@@ -9,7 +9,7 @@
#include "content/common/gin_java_bridge_messages.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/java/gin_java_bridge_object.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
namespace content {
@@ -114,14 +114,16 @@ bool GinJavaBridgeDispatcher::HasJavaMethod(ObjectID object_id,
scoped_ptr<base::Value> GinJavaBridgeDispatcher::InvokeJavaMethod(
ObjectID object_id,
const std::string& method_name,
- const base::ListValue& arguments) {
+ const base::ListValue& arguments,
+ GinJavaBridgeError* error) {
base::ListValue result_wrapper;
render_frame()->Send(
new GinJavaBridgeHostMsg_InvokeMethod(routing_id(),
object_id,
method_name,
arguments,
- &result_wrapper));
+ &result_wrapper,
+ error));
base::Value* result;
if (result_wrapper.Get(0, &result)) {
return scoped_ptr<base::Value>(result->DeepCopy());
diff --git a/chromium/content/renderer/java/gin_java_bridge_dispatcher.h b/chromium/content/renderer/java/gin_java_bridge_dispatcher.h
index 13c67771552..f9d5f5449ad 100644
--- a/chromium/content/renderer/java/gin_java_bridge_dispatcher.h
+++ b/chromium/content/renderer/java/gin_java_bridge_dispatcher.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/public/renderer/render_frame_observer.h"
namespace blink {
@@ -43,14 +44,15 @@ class GinJavaBridgeDispatcher
virtual ~GinJavaBridgeDispatcher();
// RenderFrameObserver override:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void DidClearWindowObject() OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
+ virtual void DidClearWindowObject() override;
void GetJavaMethods(ObjectID object_id, std::set<std::string>* methods);
bool HasJavaMethod(ObjectID object_id, const std::string& method_name);
scoped_ptr<base::Value> InvokeJavaMethod(ObjectID object_id,
const std::string& method_name,
- const base::ListValue& arguments);
+ const base::ListValue& arguments,
+ GinJavaBridgeError* error);
GinJavaBridgeObject* GetObject(ObjectID object_id);
void OnGinJavaBridgeObjectDeleted(ObjectID object_id);
diff --git a/chromium/content/renderer/java/gin_java_bridge_object.cc b/chromium/content/renderer/java/gin_java_bridge_object.cc
index a153f2ae3fc..b4cf3bf669b 100644
--- a/chromium/content/renderer/java/gin_java_bridge_object.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_object.cc
@@ -5,6 +5,7 @@
#include "content/renderer/java/gin_java_bridge_object.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/android/gin_java_bridge_value.h"
#include "content/public/renderer/v8_value_converter.h"
#include "content/renderer/java/gin_java_bridge_value_converter.h"
@@ -82,7 +83,15 @@ gin::ObjectTemplateBuilder GinJavaBridgeObject::GetObjectTemplateBuilder(
v8::Local<v8::Value> GinJavaBridgeObject::GetNamedProperty(
v8::Isolate* isolate,
const std::string& property) {
- if (dispatcher_ && dispatcher_->HasJavaMethod(object_id_, property)) {
+ std::map<std::string, bool>::iterator method_pos =
+ known_methods_.find(property);
+ if (method_pos == known_methods_.end()) {
+ if (!dispatcher_) {
+ return v8::Local<v8::Value>();
+ }
+ known_methods_[property] = dispatcher_->HasJavaMethod(object_id_, property);
+ }
+ if (known_methods_[property]) {
return gin::CreateFunctionTemplate(
isolate,
base::Bind(&GinJavaBridgeObject::InvokeMethod,
@@ -125,11 +134,12 @@ v8::Handle<v8::Value> GinJavaBridgeObject::InvokeMethod(
}
}
- scoped_ptr<base::Value> result =
- dispatcher_->InvokeJavaMethod(object_id_, name, arguments);
+ GinJavaBridgeError error;
+ scoped_ptr<base::Value> result = dispatcher_->InvokeJavaMethod(
+ object_id_, name, arguments, &error);
if (!result.get()) {
args->isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
- args->isolate(), kMethodInvocationErrorMessage)));
+ args->isolate(), GinJavaBridgeErrorToString(error))));
return v8::Undefined(args->isolate());
}
if (!result->IsType(base::Value::TYPE_BINARY)) {
diff --git a/chromium/content/renderer/java/gin_java_bridge_object.h b/chromium/content/renderer/java/gin_java_bridge_object.h
index 97b74c5e4fe..f3a4c7b18f4 100644
--- a/chromium/content/renderer/java/gin_java_bridge_object.h
+++ b/chromium/content/renderer/java/gin_java_bridge_object.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_RENDERER_JAVA_GIN_JAVA_BRIDGE_OBJECT_H_
#define CONTENT_RENDERER_JAVA_GIN_JAVA_BRIDGE_OBJECT_H_
-#include <set>
+#include <map>
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -32,13 +32,13 @@ class GinJavaBridgeObject : public gin::Wrappable<GinJavaBridgeObject>,
// gin::Wrappable.
virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) OVERRIDE;
+ v8::Isolate* isolate) override;
// gin::NamedPropertyInterceptor
virtual v8::Local<v8::Value> GetNamedProperty(
- v8::Isolate* isolate, const std::string& property) OVERRIDE;
+ v8::Isolate* isolate, const std::string& property) override;
virtual std::vector<std::string> EnumerateNamedProperties(
- v8::Isolate* isolate) OVERRIDE;
+ v8::Isolate* isolate) override;
static GinJavaBridgeObject* InjectNamed(
blink::WebFrame* frame,
@@ -61,6 +61,7 @@ class GinJavaBridgeObject : public gin::Wrappable<GinJavaBridgeObject>,
base::WeakPtr<GinJavaBridgeDispatcher> dispatcher_;
GinJavaBridgeDispatcher::ObjectID object_id_;
scoped_ptr<GinJavaBridgeValueConverter> converter_;
+ std::map<std::string, bool> known_methods_;
DISALLOW_COPY_AND_ASSIGN(GinJavaBridgeObject);
};
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter.cc b/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
index ad8fee99bb3..c1727a42bb5 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter.cc
@@ -68,14 +68,13 @@ class TypedArraySerializerImpl : public TypedArraySerializer {
public:
static scoped_ptr<TypedArraySerializer> Create(
v8::Handle<v8::TypedArray> typed_array) {
- scoped_ptr<TypedArraySerializerImpl<ElementType, ListType> > result(
+ return make_scoped_ptr(
new TypedArraySerializerImpl<ElementType, ListType>(typed_array));
- return result.template PassAs<TypedArraySerializer>();
}
virtual void serializeTo(char* data,
size_t data_length,
- base::ListValue* out) OVERRIDE {
+ base::ListValue* out) override {
DCHECK_EQ(data_length, typed_array_->Length() * sizeof(ElementType));
for (ElementType *element = reinterpret_cast<ElementType*>(data),
*end = element + typed_array_->Length();
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter.h b/chromium/content/renderer/java/gin_java_bridge_value_converter.h
index 5b834eaa859..fd343b9fdd5 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter.h
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter.h
@@ -27,13 +27,13 @@ class GinJavaBridgeValueConverter : public content::V8ValueConverter::Strategy {
virtual bool FromV8Object(v8::Handle<v8::Object> value,
base::Value** out,
v8::Isolate* isolate,
- const FromV8ValueCallback& callback) const OVERRIDE;
+ const FromV8ValueCallback& callback) const override;
virtual bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
base::Value** out,
- v8::Isolate* isolate) const OVERRIDE;
+ v8::Isolate* isolate) const override;
virtual bool FromV8Number(v8::Handle<v8::Number> value,
- base::Value** out) const OVERRIDE;
- virtual bool FromV8Undefined(base::Value** out) const OVERRIDE;
+ base::Value** out) const override;
+ virtual bool FromV8Undefined(base::Value** out) const override;
private:
scoped_ptr<V8ValueConverter> converter_;
diff --git a/chromium/content/renderer/java/java_bridge_channel.cc b/chromium/content/renderer/java/java_bridge_channel.cc
deleted file mode 100644
index 0d6d3f6c35f..00000000000
--- a/chromium/content/renderer/java/java_bridge_channel.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/java/java_bridge_channel.h"
-
-#include "content/child/child_process.h"
-#include "content/child/plugin_messages.h"
-#include "content/common/java_bridge_messages.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-namespace content {
-
-JavaBridgeChannel* JavaBridgeChannel::GetJavaBridgeChannel(
- const IPC::ChannelHandle& channel_handle,
- base::MessageLoopProxy* ipc_message_loop) {
- return static_cast<JavaBridgeChannel*>(NPChannelBase::GetChannel(
- channel_handle,
- IPC::Channel::MODE_CLIENT,
- ClassFactory,
- ipc_message_loop,
- true,
- ChildProcess::current()->GetShutDownEvent()));
-}
-
-JavaBridgeChannel::JavaBridgeChannel()
- : peer_owner_id_(new struct _NPP) {
- // Register the dummy owner Id for our peer (the Browser process) as an object
- // owner, and have all objects received from the peer owned by it.
- blink::WebBindings::registerObjectOwner(peer_owner_id_.get());
- SetDefaultNPObjectOwner(peer_owner_id_.get());
-}
-
-JavaBridgeChannel::~JavaBridgeChannel() {
- blink::WebBindings::unregisterObjectOwner(peer_owner_id_.get());
-}
-
-int JavaBridgeChannel::GenerateRouteID() {
- // Use a control message as this going to the JavaBridgeChannelHost, not an
- // injected object.
- int route_id = MSG_ROUTING_NONE;
- Send(new JavaBridgeMsg_GenerateRouteID(&route_id));
- // This should never fail, as the JavaBridgeChannelHost should always outlive
- // us.
- DCHECK_NE(MSG_ROUTING_NONE, route_id);
- return route_id;
-}
-
-bool JavaBridgeChannel::OnControlMessageReceived(const IPC::Message& msg) {
- // We need to intercept these two message types because the default
- // implementation of NPChannelBase::OnControlMessageReceived() is to
- // DCHECK(false). However, we don't need to do anything, as we don't need to
- // worry about the window system hanging when a modal dialog is displayed.
- // This is because, unlike in the case of plugins, the host does not need to
- // pump the message queue to avoid hangs.
- if (msg.type() == PluginMsg_SignalModalDialogEvent::ID ||
- msg.type() == PluginMsg_ResetModalDialogEvent::ID) {
- return true;
- }
- return NPChannelBase::OnControlMessageReceived(msg);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/java/java_bridge_channel.h b/chromium/content/renderer/java/java_bridge_channel.h
deleted file mode 100644
index a947374cefe..00000000000
--- a/chromium/content/renderer/java/java_bridge_channel.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_JAVA_JAVA_BRIDGE_CHANNEL_H_
-#define CONTENT_RENDERER_JAVA_JAVA_BRIDGE_CHANNEL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/child/npapi/np_channel_base.h"
-#include "ipc/ipc_channel_handle.h"
-
-namespace content {
-
-class JavaBridgeChannel : public content::NPChannelBase {
- public:
- // The return value may be null.
- static JavaBridgeChannel* GetJavaBridgeChannel(
- const IPC::ChannelHandle& channel_handle,
- base::MessageLoopProxy* ipc_message_loop);
-
- // NPChannelBase implementation:
- virtual int GenerateRouteID() OVERRIDE;
-
- // NPChannelBase override:
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- private:
- JavaBridgeChannel();
- // This class is ref-counted.
- virtual ~JavaBridgeChannel();
-
- static NPChannelBase* ClassFactory() { return new JavaBridgeChannel(); }
-
- // Dummy NPObject owner Id used to track objects owned by the JavaBridge
- // peer in the Browser process.
- scoped_ptr<struct _NPP> peer_owner_id_;
-
- DISALLOW_COPY_AND_ASSIGN(JavaBridgeChannel);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_JAVA_JAVA_BRIDGE_CHANNEL_H_
diff --git a/chromium/content/renderer/java/java_bridge_dispatcher.cc b/chromium/content/renderer/java/java_bridge_dispatcher.cc
deleted file mode 100644
index 262ea94fbd5..00000000000
--- a/chromium/content/renderer/java/java_bridge_dispatcher.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/java/java_bridge_dispatcher.h"
-
-#include "content/child/child_process.h"
-#include "content/child/npapi/npobject_util.h" // For CreateNPVariant()
-#include "content/common/java_bridge_messages.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/renderer/java/java_bridge_channel.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-namespace content {
-
-JavaBridgeDispatcher::JavaBridgeDispatcher(RenderFrame* render_frame)
- : RenderFrameObserver(render_frame) {
-}
-
-void JavaBridgeDispatcher::EnsureChannelIsSetUp() {
- if (channel_.get()) {
- return;
- }
-
- IPC::ChannelHandle channel_handle;
- Send(new JavaBridgeHostMsg_GetChannelHandle(routing_id(), &channel_handle));
-
- channel_ = JavaBridgeChannel::GetJavaBridgeChannel(
- channel_handle, ChildProcess::current()->io_message_loop_proxy());
-}
-
-JavaBridgeDispatcher::~JavaBridgeDispatcher() {
- for (ObjectMap::const_iterator iter = objects_.begin();
- iter != objects_.end(); ++iter) {
- blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
- }
-}
-
-bool JavaBridgeDispatcher::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(JavaBridgeDispatcher, msg)
- IPC_MESSAGE_HANDLER(JavaBridgeMsg_AddNamedObject, OnAddNamedObject)
- IPC_MESSAGE_HANDLER(JavaBridgeMsg_RemoveNamedObject,
- OnRemoveNamedObject)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void JavaBridgeDispatcher::DidClearWindowObject() {
- // Note that we have to (re)bind all objects, as they will have been unbound
- // when the window object was cleared.
- for (ObjectMap::const_iterator iter = objects_.begin();
- iter != objects_.end();
- ++iter) {
- NPObject* object = NPVARIANT_TO_OBJECT(iter->second);
- // De-associate from the existing V8 wrapper, so we don't pull any
- // of the wrapper's custom properties into the context of the page we
- // have navigated to.
- blink::WebBindings::dropV8WrapperForObject(object);
- // This refs the NPObject. This reference is dropped when either the window
- // object is later cleared, or the object is GC'ed. So the object may be
- // deleted at any time after OnRemoveNamedObject() is called.
- render_frame()->GetWebFrame()->bindToWindowObject(iter->first, object);
- }
-}
-
-void JavaBridgeDispatcher::OnAddNamedObject(
- const base::string16& name,
- const NPVariant_Param& variant_param) {
- DCHECK_EQ(variant_param.type, NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID);
-
- EnsureChannelIsSetUp();
- if (!channel_.get()) {
- // It's possible for |channel_| to be NULL if the RenderView is going away.
- return;
- }
-
- // This creates an NPObject, wrapped as an NPVariant. Pass 0 for the for
- // containing window, as this is only used by plugins to pump the window
- // message queue when a method on a renderer-side object causes a dialog to
- // be displayed, and the Java Bridge does not need this functionality. The
- // page URL is also not required.
- NPVariant variant;
- bool created =
- CreateNPVariant(variant_param, channel_.get(), &variant, 0, GURL());
- DCHECK(created);
- DCHECK_EQ(variant.type, NPVariantType_Object);
-
- // The NPObject is created with a ref count of one, which we remove when
- // OnRemoveNamedObject() is called for that object.
- ObjectMap::iterator iter = objects_.find(name);
- if (iter != objects_.end()) {
- blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
- }
- objects_[name] = variant;
-}
-
-void JavaBridgeDispatcher::OnRemoveNamedObject(const base::string16& name) {
- if (!channel_.get()) {
- DCHECK(objects_.empty());
- return;
- }
-
- // Removing an object does not unbind it from JavaScript until the window
- // object is next cleared. Note that the browser checks that the named object
- // is present.
- ObjectMap::iterator iter = objects_.find(name);
- DCHECK(iter != objects_.end());
- blink::WebBindings::releaseObject(NPVARIANT_TO_OBJECT(iter->second));
- objects_.erase(iter);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/java/java_bridge_dispatcher.h b/chromium/content/renderer/java/java_bridge_dispatcher.h
deleted file mode 100644
index 4858ea7dc2e..00000000000
--- a/chromium/content/renderer/java/java_bridge_dispatcher.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_JAVA_JAVA_BRIDGE_DISPATCHER_H_
-#define CONTENT_RENDERER_JAVA_JAVA_BRIDGE_DISPATCHER_H_
-
-#include <map>
-
-#include "base/memory/ref_counted.h"
-#include "base/strings/string16.h"
-#include "content/public/renderer/render_frame_observer.h"
-#include "ipc/ipc_channel_handle.h"
-#include "third_party/npapi/bindings/npruntime.h"
-
-namespace content {
-class JavaBridgeChannel;
-struct NPVariant_Param;
-
-// This class handles injecting Java objects into the main frame of a
-// RenderView. The 'add' and 'remove' messages received from the browser
-// process modify the entries in a map of 'pending' objects. These objects are
-// bound to the window object of the main frame when that window object is next
-// cleared. These objects remain bound until the window object is cleared
-// again.
-class JavaBridgeDispatcher : public RenderFrameObserver {
- public:
- JavaBridgeDispatcher(RenderFrame* render_frame);
- virtual ~JavaBridgeDispatcher();
-
- private:
- // RenderViewObserver override:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void DidClearWindowObject() OVERRIDE;
-
- // Message handlers
- void OnAddNamedObject(const base::string16& name,
- const NPVariant_Param& variant_param);
- void OnRemoveNamedObject(const base::string16& name);
-
- void EnsureChannelIsSetUp();
-
- // Objects that will be bound to the window when the window object is next
- // cleared. We hold a ref to these.
- typedef std::map<base::string16, NPVariant> ObjectMap;
- ObjectMap objects_;
- scoped_refptr<JavaBridgeChannel> channel_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_JAVA_JAVA_BRIDGE_DISPATCHER_H_
diff --git a/chromium/content/renderer/manifest/OWNERS b/chromium/content/renderer/manifest/OWNERS
new file mode 100644
index 00000000000..2d282460822
--- /dev/null
+++ b/chromium/content/renderer/manifest/OWNERS
@@ -0,0 +1 @@
+mlamouri@chromium.org
diff --git a/chromium/content/renderer/manifest/manifest_manager.cc b/chromium/content/renderer/manifest/manifest_manager.cc
new file mode 100644
index 00000000000..9ccee4cb388
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_manager.cc
@@ -0,0 +1,156 @@
+// Copyright 2014 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 "content/renderer/manifest/manifest_manager.h"
+
+#include "base/bind.h"
+#include "base/strings/nullable_string16.h"
+#include "content/common/manifest_manager_messages.h"
+#include "content/public/renderer/render_frame.h"
+#include "content/renderer/fetchers/manifest_fetcher.h"
+#include "content/renderer/manifest/manifest_parser.h"
+#include "content/renderer/manifest/manifest_uma_util.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+
+namespace content {
+
+ManifestManager::ManifestManager(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame),
+ may_have_manifest_(false),
+ manifest_dirty_(true) {
+}
+
+ManifestManager::~ManifestManager() {
+ if (fetcher_)
+ fetcher_->Cancel();
+
+ // Consumers in the browser process will not receive this message but they
+ // will be aware of the RenderFrame dying and should act on that. Consumers
+ // in the renderer process should be correctly notified.
+ ResolveCallbacks(ResolveStateFailure);
+}
+
+bool ManifestManager::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+
+ IPC_BEGIN_MESSAGE_MAP(ManifestManager, message)
+ IPC_MESSAGE_HANDLER(ManifestManagerMsg_RequestManifest, OnRequestManifest)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void ManifestManager::OnRequestManifest(int request_id) {
+ GetManifest(base::Bind(&ManifestManager::OnRequestManifestComplete,
+ base::Unretained(this), request_id));
+}
+
+void ManifestManager::OnRequestManifestComplete(
+ int request_id, const Manifest& manifest) {
+ // When sent via IPC, the Manifest must follow certain security rules.
+ Manifest ipc_manifest = manifest;
+ ipc_manifest.name = base::NullableString16(
+ ipc_manifest.name.string().substr(0, Manifest::kMaxIPCStringLength),
+ ipc_manifest.name.is_null());
+ ipc_manifest.short_name = base::NullableString16(
+ ipc_manifest.short_name.string().substr(0,
+ Manifest::kMaxIPCStringLength),
+ ipc_manifest.short_name.is_null());
+ for (size_t i = 0; i < ipc_manifest.icons.size(); ++i) {
+ ipc_manifest.icons[i].type = base::NullableString16(
+ ipc_manifest.icons[i].type.string().substr(
+ 0, Manifest::kMaxIPCStringLength),
+ ipc_manifest.icons[i].type.is_null());
+ }
+ ipc_manifest.gcm_sender_id = base::NullableString16(
+ ipc_manifest.gcm_sender_id.string().substr(
+ 0, Manifest::kMaxIPCStringLength),
+ ipc_manifest.gcm_sender_id.is_null());
+
+ Send(new ManifestManagerHostMsg_RequestManifestResponse(
+ routing_id(), request_id, ipc_manifest));
+}
+
+void ManifestManager::GetManifest(const GetManifestCallback& callback) {
+ if (!may_have_manifest_) {
+ callback.Run(Manifest());
+ return;
+ }
+
+ if (!manifest_dirty_) {
+ callback.Run(manifest_);
+ return;
+ }
+
+ pending_callbacks_.push_back(callback);
+
+ // Just wait for the running call to be done if there are other callbacks.
+ if (pending_callbacks_.size() > 1)
+ return;
+
+ FetchManifest();
+}
+
+void ManifestManager::DidChangeManifest() {
+ may_have_manifest_ = true;
+ manifest_dirty_ = true;
+}
+
+void ManifestManager::FetchManifest() {
+ GURL url(render_frame()->GetWebFrame()->document().manifestURL());
+
+ if (url.is_empty()) {
+ ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_EMPTY_URL);
+ ResolveCallbacks(ResolveStateFailure);
+ return;
+ }
+
+ fetcher_.reset(new ManifestFetcher(url));
+
+ // TODO(mlamouri,kenneth): this is not yet taking into account manifest-src
+ // CSP rule, see http://crbug.com/409996.
+ fetcher_->Start(render_frame()->GetWebFrame(),
+ base::Bind(&ManifestManager::OnManifestFetchComplete,
+ base::Unretained(this),
+ render_frame()->GetWebFrame()->document().url()));
+}
+
+void ManifestManager::OnManifestFetchComplete(
+ const GURL& document_url,
+ const blink::WebURLResponse& response,
+ const std::string& data) {
+ if (response.isNull() && data.empty()) {
+ ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_UNSPECIFIED_REASON);
+ ResolveCallbacks(ResolveStateFailure);
+ return;
+ }
+
+ ManifestUmaUtil::FetchSucceeded();
+ manifest_ = ManifestParser::Parse(data, response.url(), document_url);
+
+ fetcher_.reset();
+ ResolveCallbacks(ResolveStateSuccess);
+}
+
+void ManifestManager::ResolveCallbacks(ResolveState state) {
+ if (state == ResolveStateFailure)
+ manifest_ = Manifest();
+
+ manifest_dirty_ = state != ResolveStateSuccess;
+
+ Manifest manifest = manifest_;
+ std::list<GetManifestCallback> callbacks = pending_callbacks_;
+
+ pending_callbacks_.clear();
+
+ for (std::list<GetManifestCallback>::const_iterator it = callbacks.begin();
+ it != callbacks.end(); ++it) {
+ it->Run(manifest);
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_manager.h b/chromium/content/renderer/manifest/manifest_manager.h
new file mode 100644
index 00000000000..5874724e695
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_manager.h
@@ -0,0 +1,84 @@
+// Copyright 2014 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 CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_H_
+#define CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_H_
+
+#include <list>
+
+#include "base/callback_forward.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/common/manifest.h"
+#include "content/public/renderer/render_frame_observer.h"
+
+class GURL;
+
+namespace blink {
+class WebURLResponse;
+}
+
+namespace content {
+
+class ManifestFetcher;
+
+// The ManifestManager is a helper class that takes care of fetching and parsing
+// the Manifest of the associated RenderFrame. It uses the ManifestFetcher and
+// the ManifestParser in order to do so.
+// There are two expected consumers of this helper: ManifestManagerHost, via IPC
+// messages and callers inside the renderer process. The latter should use
+// GetManifest().
+class ManifestManager : public RenderFrameObserver {
+ public:
+ typedef base::Callback<void(const Manifest&)> GetManifestCallback;
+
+ explicit ManifestManager(RenderFrame* render_frame);
+ ~ManifestManager() override;
+
+ // Will call the given |callback| with the Manifest associated with the
+ // RenderFrame if any. Will pass an empty Manifest in case of error.
+ void GetManifest(const GetManifestCallback& callback);
+
+ // RenderFrameObserver implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void DidChangeManifest() override;
+
+ private:
+ enum ResolveState {
+ ResolveStateSuccess,
+ ResolveStateFailure
+ };
+
+ // Called when receiving a ManifestManagerMsg_RequestManifest from the browser
+ // process.
+ void OnRequestManifest(int request_id);
+ void OnRequestManifestComplete(int request_id, const Manifest&);
+
+ void FetchManifest();
+ void OnManifestFetchComplete(const GURL& document_url,
+ const blink::WebURLResponse& response,
+ const std::string& data);
+ void ResolveCallbacks(ResolveState state);
+
+ scoped_ptr<ManifestFetcher> fetcher_;
+
+ // Whether the RenderFrame may have an associated Manifest. If true, the frame
+ // may have a manifest, if false, it can't have one. This boolean is true when
+ // DidChangeManifest() is called, if it is never called, it means that the
+ // associated document has no <link rel='manifest'>.
+ bool may_have_manifest_;
+
+ // Whether the current Manifest is dirty.
+ bool manifest_dirty_;
+
+ // Current Manifest. Might be outdated if manifest_dirty_ is true.
+ Manifest manifest_;
+
+ std::list<GetManifestCallback> pending_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(ManifestManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_MANAGER_H_
diff --git a/chromium/content/renderer/manifest/manifest_parser.cc b/chromium/content/renderer/manifest/manifest_parser.cc
new file mode 100644
index 00000000000..bab85cd75f1
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_parser.cc
@@ -0,0 +1,328 @@
+// Copyright 2014 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 "content/renderer/manifest/manifest_parser.h"
+
+#include "base/json/json_reader.h"
+#include "base/strings/nullable_string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "content/public/common/manifest.h"
+#include "content/renderer/manifest/manifest_uma_util.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+namespace {
+
+enum TrimType {
+ Trim,
+ NoTrim
+};
+
+base::NullableString16 ParseString(const base::DictionaryValue& dictionary,
+ const std::string& key,
+ TrimType trim) {
+ if (!dictionary.HasKey(key))
+ return base::NullableString16();
+
+ base::string16 value;
+ if (!dictionary.GetString(key, &value)) {
+ // TODO(mlamouri): provide a custom message to the developer console about
+ // the property being incorrectly set.
+ return base::NullableString16();
+ }
+
+ if (trim == Trim)
+ base::TrimWhitespace(value, base::TRIM_ALL, &value);
+ return base::NullableString16(value, false);
+}
+
+// Helper function to parse URLs present on a given |dictionary| in a given
+// field identified by its |key|. The URL is first parsed as a string then
+// resolved using |base_url|.
+// Returns a GURL. If the parsing failed, the GURL will not be valid.
+GURL ParseURL(const base::DictionaryValue& dictionary,
+ const std::string& key,
+ const GURL& base_url) {
+ base::NullableString16 url_str = ParseString(dictionary, key, NoTrim);
+ if (url_str.is_null())
+ return GURL();
+
+ return base_url.Resolve(url_str.string());
+}
+
+// Parses the 'name' field of the manifest, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-name-member
+// Returns the parsed string if any, a null string if the parsing failed.
+base::NullableString16 ParseName(const base::DictionaryValue& dictionary) {
+ return ParseString(dictionary, "name", Trim);
+}
+
+// Parses the 'short_name' field of the manifest, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-short-name-member
+// Returns the parsed string if any, a null string if the parsing failed.
+base::NullableString16 ParseShortName(
+ const base::DictionaryValue& dictionary) {
+ return ParseString(dictionary, "short_name", Trim);
+}
+
+// Parses the 'start_url' field of the manifest, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-start_url-member
+// Returns the parsed GURL if any, an empty GURL if the parsing failed.
+GURL ParseStartURL(const base::DictionaryValue& dictionary,
+ const GURL& manifest_url,
+ const GURL& document_url) {
+ GURL start_url = ParseURL(dictionary, "start_url", manifest_url);
+ if (!start_url.is_valid())
+ return GURL();
+
+ if (start_url.GetOrigin() != document_url.GetOrigin()) {
+ // TODO(mlamouri): provide a custom message to the developer console.
+ return GURL();
+ }
+
+ return start_url;
+}
+
+// Parses the 'display' field of the manifest, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-display-member
+// Returns the parsed DisplayMode if any, DISPLAY_MODE_UNSPECIFIED if the
+// parsing failed.
+Manifest::DisplayMode ParseDisplay(const base::DictionaryValue& dictionary) {
+ base::NullableString16 display = ParseString(dictionary, "display", Trim);
+ if (display.is_null())
+ return Manifest::DISPLAY_MODE_UNSPECIFIED;
+
+ if (LowerCaseEqualsASCII(display.string(), "fullscreen"))
+ return Manifest::DISPLAY_MODE_FULLSCREEN;
+ else if (LowerCaseEqualsASCII(display.string(), "standalone"))
+ return Manifest::DISPLAY_MODE_STANDALONE;
+ else if (LowerCaseEqualsASCII(display.string(), "minimal-ui"))
+ return Manifest::DISPLAY_MODE_MINIMAL_UI;
+ else if (LowerCaseEqualsASCII(display.string(), "browser"))
+ return Manifest::DISPLAY_MODE_BROWSER;
+ else
+ return Manifest::DISPLAY_MODE_UNSPECIFIED;
+}
+
+// Parses the 'orientation' field of the manifest, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-orientation-member
+// Returns the parsed WebScreenOrientationLockType if any,
+// WebScreenOrientationLockDefault if the parsing failed.
+blink::WebScreenOrientationLockType ParseOrientation(
+ const base::DictionaryValue& dictionary) {
+ base::NullableString16 orientation =
+ ParseString(dictionary, "orientation", Trim);
+
+ if (orientation.is_null())
+ return blink::WebScreenOrientationLockDefault;
+
+ if (LowerCaseEqualsASCII(orientation.string(), "any"))
+ return blink::WebScreenOrientationLockAny;
+ else if (LowerCaseEqualsASCII(orientation.string(), "natural"))
+ return blink::WebScreenOrientationLockNatural;
+ else if (LowerCaseEqualsASCII(orientation.string(), "landscape"))
+ return blink::WebScreenOrientationLockLandscape;
+ else if (LowerCaseEqualsASCII(orientation.string(), "landscape-primary"))
+ return blink::WebScreenOrientationLockLandscapePrimary;
+ else if (LowerCaseEqualsASCII(orientation.string(), "landscape-secondary"))
+ return blink::WebScreenOrientationLockLandscapeSecondary;
+ else if (LowerCaseEqualsASCII(orientation.string(), "portrait"))
+ return blink::WebScreenOrientationLockPortrait;
+ else if (LowerCaseEqualsASCII(orientation.string(), "portrait-primary"))
+ return blink::WebScreenOrientationLockPortraitPrimary;
+ else if (LowerCaseEqualsASCII(orientation.string(), "portrait-secondary"))
+ return blink::WebScreenOrientationLockPortraitSecondary;
+ else
+ return blink::WebScreenOrientationLockDefault;
+}
+
+// Parses the 'src' field of an icon, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-src-member-of-an-icon
+// Returns the parsed GURL if any, an empty GURL if the parsing failed.
+GURL ParseIconSrc(const base::DictionaryValue& icon,
+ const GURL& manifest_url) {
+ return ParseURL(icon, "src", manifest_url);
+}
+
+// Parses the 'type' field of an icon, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-type-member-of-an-icon
+// Returns the parsed string if any, a null string if the parsing failed.
+base::NullableString16 ParseIconType(const base::DictionaryValue& icon) {
+ return ParseString(icon, "type", Trim);
+}
+
+// Parses the 'density' field of an icon, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-a-density-member-of-an-icon
+// Returns the parsed double if any, Manifest::Icon::kDefaultDensity if the
+// parsing failed.
+double ParseIconDensity(const base::DictionaryValue& icon) {
+ double density;
+ if (!icon.GetDouble("density", &density) || density <= 0)
+ return Manifest::Icon::kDefaultDensity;
+ return density;
+}
+
+// Helper function that returns whether the given |str| is a valid width or
+// height value for an icon sizes per:
+// https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes
+bool IsValidIconWidthOrHeight(const std::string& str) {
+ if (str.empty() || str[0] == '0')
+ return false;
+ for (size_t i = 0; i < str.size(); ++i)
+ if (!IsAsciiDigit(str[i]))
+ return false;
+ return true;
+}
+
+// Parses the 'sizes' attribute of an icon as described in the HTML spec:
+// https://html.spec.whatwg.org/multipage/semantics.html#attr-link-sizes
+// Return a vector of gfx::Size that contains the valid sizes found. "Any" is
+// represented by gfx::Size(0, 0).
+// TODO(mlamouri): this is implemented as a separate function because it should
+// be refactored with the other icon sizes parsing implementations, see
+// http://crbug.com/416477
+std::vector<gfx::Size> ParseIconSizesHTML(const base::string16& sizes_str16) {
+ if (!base::IsStringASCII(sizes_str16))
+ return std::vector<gfx::Size>();
+
+ std::vector<gfx::Size> sizes;
+ std::string sizes_str =
+ base::StringToLowerASCII(base::UTF16ToUTF8(sizes_str16));
+ std::vector<std::string> sizes_str_list;
+ base::SplitStringAlongWhitespace(sizes_str, &sizes_str_list);
+
+ for (size_t i = 0; i < sizes_str_list.size(); ++i) {
+ std::string& size_str = sizes_str_list[i];
+ if (size_str == "any") {
+ sizes.push_back(gfx::Size(0, 0));
+ continue;
+ }
+
+ // It is expected that [0] => width and [1] => height after the split.
+ std::vector<std::string> size_list;
+ base::SplitStringDontTrim(size_str, L'x', &size_list);
+ if (size_list.size() != 2)
+ continue;
+ if (!IsValidIconWidthOrHeight(size_list[0]) ||
+ !IsValidIconWidthOrHeight(size_list[1])) {
+ continue;
+ }
+
+ int width, height;
+ if (!base::StringToInt(size_list[0], &width) ||
+ !base::StringToInt(size_list[1], &height)) {
+ continue;
+ }
+
+ sizes.push_back(gfx::Size(width, height));
+ }
+
+ return sizes;
+}
+
+// Parses the 'sizes' field of an icon, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-a-sizes-member-of-an-icon
+// Returns a vector of gfx::Size with the successfully parsed sizes, if any. An
+// empty vector if the field was not present or empty. "Any" is represented by
+// gfx::Size(0, 0).
+std::vector<gfx::Size> ParseIconSizes(const base::DictionaryValue& icon) {
+ base::NullableString16 sizes_str = ParseString(icon, "sizes", NoTrim);
+
+ return sizes_str.is_null() ? std::vector<gfx::Size>()
+ : ParseIconSizesHTML(sizes_str.string());
+}
+
+// Parses the 'icons' field of a Manifest, as defined in:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-the-icons-member
+// Returns a vector of Manifest::Icon with the successfully parsed icons, if
+// any. An empty vector if the field was not present or empty.
+std::vector<Manifest::Icon> ParseIcons(const base::DictionaryValue& dictionary,
+ const GURL& manifest_url) {
+ std::vector<Manifest::Icon> icons;
+ if (!dictionary.HasKey("icons"))
+ return icons;
+
+ const base::ListValue* icons_list = 0;
+ if (!dictionary.GetList("icons", &icons_list)) {
+ // TODO(mlamouri): provide a custom message to the developer console about
+ // the property being incorrectly set.
+ return icons;
+ }
+
+ for (size_t i = 0; i < icons_list->GetSize(); ++i) {
+ const base::DictionaryValue* icon_dictionary = 0;
+ if (!icons_list->GetDictionary(i, &icon_dictionary))
+ continue;
+
+ Manifest::Icon icon;
+ icon.src = ParseIconSrc(*icon_dictionary, manifest_url);
+ // An icon MUST have a valid src. If it does not, it MUST be ignored.
+ if (!icon.src.is_valid())
+ continue;
+ icon.type = ParseIconType(*icon_dictionary);
+ icon.density = ParseIconDensity(*icon_dictionary);
+ icon.sizes = ParseIconSizes(*icon_dictionary);
+
+ icons.push_back(icon);
+ }
+
+ return icons;
+}
+
+// Parses the 'gcm_sender_id' field of the manifest.
+// This is a proprietary extension of the Web Manifest specification.
+// Returns the parsed string if any, a null string if the parsing failed.
+base::NullableString16 ParseGCMSenderID(
+ const base::DictionaryValue& dictionary) {
+ return ParseString(dictionary, "gcm_sender_id", Trim);
+}
+
+} // anonymous namespace
+
+Manifest ManifestParser::Parse(const base::StringPiece& json,
+ const GURL& manifest_url,
+ const GURL& document_url) {
+ scoped_ptr<base::Value> value(base::JSONReader::Read(json));
+ if (!value) {
+ // TODO(mlamouri): get the JSON parsing error and report it to the developer
+ // console.
+ ManifestUmaUtil::ParseFailed();
+ return Manifest();
+ }
+
+ if (value->GetType() != base::Value::TYPE_DICTIONARY) {
+ // TODO(mlamouri): provide a custom message to the developer console.
+ ManifestUmaUtil::ParseFailed();
+ return Manifest();
+ }
+
+ base::DictionaryValue* dictionary = 0;
+ value->GetAsDictionary(&dictionary);
+ if (!dictionary) {
+ // TODO(mlamouri): provide a custom message to the developer console.
+ ManifestUmaUtil::ParseFailed();
+ return Manifest();
+ }
+
+ Manifest manifest;
+
+ manifest.name = ParseName(*dictionary);
+ manifest.short_name = ParseShortName(*dictionary);
+ manifest.start_url = ParseStartURL(*dictionary, manifest_url, document_url);
+ manifest.display = ParseDisplay(*dictionary);
+ manifest.orientation = ParseOrientation(*dictionary);
+ manifest.icons = ParseIcons(*dictionary, manifest_url);
+ manifest.gcm_sender_id = ParseGCMSenderID(*dictionary);
+
+ ManifestUmaUtil::ParseSucceeded(manifest);
+
+ return manifest;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_parser.h b/chromium/content/renderer/manifest/manifest_parser.h
new file mode 100644
index 00000000000..48812795308
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_parser.h
@@ -0,0 +1,33 @@
+// Copyright 2014 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 CONTENT_RENDERER_MANIFEST_MANIFEST_PARSER_H_
+#define CONTENT_RENDERER_MANIFEST_MANIFEST_PARSER_H_
+
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+
+class GURL;
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace content {
+
+struct Manifest;
+
+// ManifestParser handles the logic of parsing the Web Manifest from a string.
+// It implements:
+// http://w3c.github.io/manifest/#dfn-steps-for-processing-a-manifest
+class CONTENT_EXPORT ManifestParser {
+ public:
+ static Manifest Parse(const base::StringPiece&,
+ const GURL& manifest_url,
+ const GURL& document_url);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_PARSER_H_
diff --git a/chromium/content/renderer/manifest/manifest_parser_unittest.cc b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
new file mode 100644
index 00000000000..1e3770b4e74
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
@@ -0,0 +1,607 @@
+// Copyright 2014 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 "content/renderer/manifest/manifest_parser.h"
+
+#include "base/strings/string_util.h"
+#include "content/public/common/manifest.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class ManifestParserTest : public testing::Test {
+ protected:
+ ManifestParserTest() {}
+ ~ManifestParserTest() override {}
+
+ Manifest ParseManifest(const base::StringPiece& json,
+ const GURL& document_url = default_document_url,
+ const GURL& manifest_url = default_manifest_url) {
+ return ManifestParser::Parse(json, document_url, manifest_url);
+ }
+
+ static const GURL default_document_url;
+ static const GURL default_manifest_url;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ManifestParserTest);
+};
+
+const GURL ManifestParserTest::default_document_url(
+ "http://foo.com/index.html");
+const GURL ManifestParserTest::default_manifest_url(
+ "http://foo.com/manifest.json");
+
+TEST_F(ManifestParserTest, EmptyStringNull) {
+ Manifest manifest = ParseManifest("");
+
+ // A parsing error is equivalent to an empty manifest.
+ ASSERT_TRUE(manifest.IsEmpty());
+ ASSERT_TRUE(manifest.name.is_null());
+ ASSERT_TRUE(manifest.short_name.is_null());
+ ASSERT_TRUE(manifest.start_url.is_empty());
+ ASSERT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
+ ASSERT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
+}
+
+TEST_F(ManifestParserTest, ValidNoContentParses) {
+ Manifest manifest = ParseManifest("{}");
+
+ // Check that all the fields are null in that case.
+ ASSERT_TRUE(manifest.IsEmpty());
+ ASSERT_TRUE(manifest.name.is_null());
+ ASSERT_TRUE(manifest.short_name.is_null());
+ ASSERT_TRUE(manifest.start_url.is_empty());
+ ASSERT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
+ ASSERT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
+}
+
+TEST_F(ManifestParserTest, NameParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"name\": \"foo\" }");
+ ASSERT_TRUE(EqualsASCII(manifest.name.string(), "foo"));
+ ASSERT_FALSE(manifest.IsEmpty());
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"name\": \" foo \" }");
+ ASSERT_TRUE(EqualsASCII(manifest.name.string(), "foo"));
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"name\": {} }");
+ ASSERT_TRUE(manifest.name.is_null());
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"name\": 42 }");
+ ASSERT_TRUE(manifest.name.is_null());
+ }
+}
+
+TEST_F(ManifestParserTest, ShortNameParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"short_name\": \"foo\" }");
+ ASSERT_TRUE(EqualsASCII(manifest.short_name.string(), "foo"));
+ ASSERT_FALSE(manifest.IsEmpty());
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"short_name\": \" foo \" }");
+ ASSERT_TRUE(EqualsASCII(manifest.short_name.string(), "foo"));
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"short_name\": {} }");
+ ASSERT_TRUE(manifest.short_name.is_null());
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"short_name\": 42 }");
+ ASSERT_TRUE(manifest.short_name.is_null());
+ }
+}
+
+TEST_F(ManifestParserTest, StartURLParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"start_url\": \"land.html\" }");
+ ASSERT_EQ(manifest.start_url.spec(),
+ default_document_url.Resolve("land.html").spec());
+ ASSERT_FALSE(manifest.IsEmpty());
+ }
+
+ // Whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"start_url\": \" land.html \" }");
+ ASSERT_EQ(manifest.start_url.spec(),
+ default_document_url.Resolve("land.html").spec());
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"start_url\": {} }");
+ ASSERT_TRUE(manifest.start_url.is_empty());
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"start_url\": 42 }");
+ ASSERT_TRUE(manifest.start_url.is_empty());
+ }
+
+ // Absolute start_url, same origin with document.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"start_url\": \"http://foo.com/land.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_EQ(manifest.start_url.spec(), "http://foo.com/land.html");
+ }
+
+ // Absolute start_url, cross origin with document.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"start_url\": \"http://bar.com/land.html\" }",
+ GURL("http://foo.com/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_TRUE(manifest.start_url.is_empty());
+ }
+
+ // Resolving has to happen based on the manifest_url.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"start_url\": \"land.html\" }",
+ GURL("http://foo.com/landing/manifest.json"),
+ GURL("http://foo.com/index.html"));
+ ASSERT_EQ(manifest.start_url.spec(), "http://foo.com/landing/land.html");
+ }
+}
+
+TEST_F(ManifestParserTest, DisplayParserRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
+ EXPECT_FALSE(manifest.IsEmpty());
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \" browser \" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": {} }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": 42 }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
+ }
+
+ // Parse fails if string isn't known.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"browser_something\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_UNSPECIFIED);
+ }
+
+ // Accept 'fullscreen'.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"fullscreen\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_FULLSCREEN);
+ }
+
+ // Accept 'fullscreen'.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"standalone\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_STANDALONE);
+ }
+
+ // Accept 'minimal-ui'.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"minimal-ui\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_MINIMAL_UI);
+ }
+
+ // Accept 'browser'.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"browser\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
+ }
+
+ // Case insensitive.
+ {
+ Manifest manifest = ParseManifest("{ \"display\": \"BROWSER\" }");
+ EXPECT_EQ(manifest.display, Manifest::DISPLAY_MODE_BROWSER);
+ }
+}
+
+TEST_F(ManifestParserTest, OrientationParserRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockNatural);
+ EXPECT_FALSE(manifest.IsEmpty());
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockNatural);
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": {} }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": 42 }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
+ }
+
+ // Parse fails if string isn't known.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"naturalish\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockDefault);
+ }
+
+ // Accept 'any'.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"any\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockAny);
+ }
+
+ // Accept 'natural'.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"natural\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockNatural);
+ }
+
+ // Accept 'landscape'.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"landscape\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockLandscape);
+ }
+
+ // Accept 'landscape-primary'.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"orientation\": \"landscape-primary\" }");
+ EXPECT_EQ(manifest.orientation,
+ blink::WebScreenOrientationLockLandscapePrimary);
+ }
+
+ // Accept 'landscape-secondary'.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"orientation\": \"landscape-secondary\" }");
+ EXPECT_EQ(manifest.orientation,
+ blink::WebScreenOrientationLockLandscapeSecondary);
+ }
+
+ // Accept 'portrait'.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"portrait\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockPortrait);
+ }
+
+ // Accept 'portrait-primary'.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"orientation\": \"portrait-primary\" }");
+ EXPECT_EQ(manifest.orientation,
+ blink::WebScreenOrientationLockPortraitPrimary);
+ }
+
+ // Accept 'portrait-secondary'.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"orientation\": \"portrait-secondary\" }");
+ EXPECT_EQ(manifest.orientation,
+ blink::WebScreenOrientationLockPortraitSecondary);
+ }
+
+ // Case insensitive.
+ {
+ Manifest manifest = ParseManifest("{ \"orientation\": \"LANDSCAPE\" }");
+ EXPECT_EQ(manifest.orientation, blink::WebScreenOrientationLockLandscape);
+ }
+}
+
+TEST_F(ManifestParserTest, IconsParseRules) {
+ // Smoke test: if no icon, empty list.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [] }");
+ EXPECT_EQ(manifest.icons.size(), 0u);
+ EXPECT_TRUE(manifest.IsEmpty());
+ }
+
+ // Smoke test: if empty icon, empty list.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {} ] }");
+ EXPECT_EQ(manifest.icons.size(), 0u);
+ EXPECT_TRUE(manifest.IsEmpty());
+ }
+
+ // Smoke test: icon with invalid src, empty list.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ { \"icons\": [] } ] }");
+ EXPECT_EQ(manifest.icons.size(), 0u);
+ EXPECT_TRUE(manifest.IsEmpty());
+ }
+
+ // Smoke test: if icon with empty src, it will be present in the list.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ { \"src\": \"\" } ] }");
+ EXPECT_EQ(manifest.icons.size(), 1u);
+ EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/index.html");
+ EXPECT_FALSE(manifest.IsEmpty());
+ }
+
+ // Smoke test: if one icons with valid src, it will be present in the list.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [{ \"src\": \"foo.jpg\" }] }");
+ EXPECT_EQ(manifest.icons.size(), 1u);
+ EXPECT_EQ(manifest.icons[0].src.spec(), "http://foo.com/foo.jpg");
+ EXPECT_FALSE(manifest.IsEmpty());
+ }
+}
+
+TEST_F(ManifestParserTest, IconSrcParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"foo.png\" } ] }");
+ EXPECT_EQ(manifest.icons[0].src.spec(),
+ default_document_url.Resolve("foo.png").spec());
+ }
+
+ // Whitespaces.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \" foo.png \" } ] }");
+ EXPECT_EQ(manifest.icons[0].src.spec(),
+ default_document_url.Resolve("foo.png").spec());
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": {} } ] }");
+ EXPECT_TRUE(manifest.icons.empty());
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": 42 } ] }");
+ EXPECT_TRUE(manifest.icons.empty());
+ }
+
+ // Resolving has to happen based on the document_url.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"icons/foo.png\" } ] }",
+ GURL("http://foo.com/landing/index.html"));
+ EXPECT_EQ(manifest.icons[0].src.spec(),
+ "http://foo.com/landing/icons/foo.png");
+ }
+}
+
+TEST_F(ManifestParserTest, IconTypeParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": \"foo\" } ] }");
+ EXPECT_TRUE(EqualsASCII(manifest.icons[0].type.string(), "foo"));
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ " \"type\": \" foo \" } ] }");
+ EXPECT_TRUE(EqualsASCII(manifest.icons[0].type.string(), "foo"));
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": {} } ] }");
+ EXPECT_TRUE(manifest.icons[0].type.is_null());
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"type\": 42 } ] }");
+ EXPECT_TRUE(manifest.icons[0].type.is_null());
+ }
+}
+
+TEST_F(ManifestParserTest, IconDensityParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 42 } ] }");
+ EXPECT_EQ(manifest.icons[0].density, 42);
+ }
+
+ // Decimal value.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 2.5 } ] }");
+ EXPECT_EQ(manifest.icons[0].density, 2.5);
+ }
+
+ // Parse fail if it isn't a float.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": {} } ] }");
+ EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
+ }
+
+ // Parse fail if it isn't a float.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\":\"2\" } ] }");
+ EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
+ }
+
+ // Edge case: 1.0.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 1.00 } ] }");
+ EXPECT_EQ(manifest.icons[0].density, 1);
+ }
+
+ // Edge case: values between 0.0 and 1.0 are allowed.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 0.42 } ] }");
+ EXPECT_EQ(manifest.icons[0].density, 0.42);
+ }
+
+ // 0 is an invalid value.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": 0.0 } ] }");
+ EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
+ }
+
+ // Negative values are invalid.
+ {
+ Manifest manifest =
+ ParseManifest("{ \"icons\": [ {\"src\": \"\", \"density\": -2.5 } ] }");
+ EXPECT_EQ(manifest.icons[0].density, Manifest::Icon::kDefaultDensity);
+ }
+}
+
+TEST_F(ManifestParserTest, IconSizesParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"42x42\" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 1u);
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \" 42x42 \" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 1u);
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": {} } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
+ }
+
+ // Don't parse if name isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": 42 } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
+ }
+
+ // Smoke test: value correctly parsed.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"42x42 48x48\" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
+ EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(48, 48));
+ }
+
+ // <WIDTH>'x'<HEIGHT> and <WIDTH>'X'<HEIGHT> are equivalent.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"42X42 48X48\" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
+ EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(48, 48));
+ }
+
+ // Twice the same value is parsed twice.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"42X42 42x42\" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes[0], gfx::Size(42, 42));
+ EXPECT_EQ(manifest.icons[0].sizes[1], gfx::Size(42, 42));
+ }
+
+ // Width or height can't start with 0.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"004X007 042x00\" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
+ }
+
+ // Width and height MUST contain digits.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"e4X1.0 55ax1e10\" } ] }");
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
+ }
+
+ // 'any' is correctly parsed and transformed to gfx::Size(0,0).
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"any AnY ANY aNy\" } ] }");
+ gfx::Size any = gfx::Size(0, 0);
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 4u);
+ EXPECT_EQ(manifest.icons[0].sizes[0], any);
+ EXPECT_EQ(manifest.icons[0].sizes[1], any);
+ EXPECT_EQ(manifest.icons[0].sizes[2], any);
+ EXPECT_EQ(manifest.icons[0].sizes[3], any);
+ }
+
+ // Some invalid width/height combinations.
+ {
+ Manifest manifest = ParseManifest("{ \"icons\": [ {\"src\": \"\","
+ "\"sizes\": \"x 40xx 1x2x3 x42 42xx42\" } ] }");
+ gfx::Size any = gfx::Size(0, 0);
+ EXPECT_EQ(manifest.icons[0].sizes.size(), 0u);
+ }
+}
+
+TEST_F(ManifestParserTest, GCMSenderIDParseRules) {
+ // Smoke test.
+ {
+ Manifest manifest = ParseManifest("{ \"gcm_sender_id\": \"foo\" }");
+ EXPECT_TRUE(EqualsASCII(manifest.gcm_sender_id.string(), "foo"));
+ }
+
+ // Trim whitespaces.
+ {
+ Manifest manifest = ParseManifest("{ \"gcm_sender_id\": \" foo \" }");
+ EXPECT_TRUE(EqualsASCII(manifest.gcm_sender_id.string(), "foo"));
+ }
+
+ // Don't parse if property isn't a string.
+ {
+ Manifest manifest = ParseManifest("{ \"gcm_sender_id\": {} }");
+ EXPECT_TRUE(manifest.gcm_sender_id.is_null());
+ }
+ {
+ Manifest manifest = ParseManifest("{ \"gcm_sender_id\": 42 }");
+ EXPECT_TRUE(manifest.gcm_sender_id.is_null());
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_uma_util.cc b/chromium/content/renderer/manifest/manifest_uma_util.cc
new file mode 100644
index 00000000000..513c4d8648b
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_uma_util.cc
@@ -0,0 +1,78 @@
+// Copyright 2014 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 "content/renderer/manifest/manifest_uma_util.h"
+
+#include "base/metrics/histogram.h"
+#include "content/public/common/manifest.h"
+
+namespace content {
+
+namespace {
+
+static const char kUMANameParseSuccess[] = "Manifest.ParseSuccess";
+static const char kUMANameFetchResult[] = "Manifest.FetchResult";
+
+// Enum for UMA purposes, make sure you update histograms.xml if you add new
+// result types. Never delete or reorder an entry; only add new entries
+// immediately before MANIFEST_FETCH_RESULT_TYPE_COUNT.
+enum ManifestFetchResultType {
+ MANIFEST_FETCH_SUCCESS = 0,
+ MANIFEST_FETCH_ERROR_EMPTY_URL = 1,
+ MANIFEST_FETCH_ERROR_UNSPECIFIED = 2,
+
+ // Must stay at the end.
+ MANIFEST_FETCH_RESULT_TYPE_COUNT
+};
+
+} // anonymous namespace
+
+void ManifestUmaUtil::ParseSucceeded(const Manifest& manifest) {
+ UMA_HISTOGRAM_BOOLEAN(kUMANameParseSuccess, true);
+ UMA_HISTOGRAM_BOOLEAN("Manifest.IsEmpty", manifest.IsEmpty());
+ if (manifest.IsEmpty())
+ return;
+
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.name", !manifest.name.is_null());
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.short_name",
+ !manifest.short_name.is_null());
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.start_url",
+ !manifest.start_url.is_empty());
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.display",
+ manifest.display != Manifest::DISPLAY_MODE_UNSPECIFIED);
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.orientation",
+ manifest.orientation != blink::WebScreenOrientationLockDefault);
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.icons", !manifest.icons.empty());
+ UMA_HISTOGRAM_BOOLEAN("Manifest.HasProperty.gcm_sender_id",
+ !manifest.gcm_sender_id.is_null());
+}
+
+void ManifestUmaUtil::ParseFailed() {
+ UMA_HISTOGRAM_BOOLEAN(kUMANameParseSuccess, false);
+}
+
+void ManifestUmaUtil::FetchSucceeded() {
+ UMA_HISTOGRAM_ENUMERATION(kUMANameFetchResult,
+ MANIFEST_FETCH_SUCCESS,
+ MANIFEST_FETCH_RESULT_TYPE_COUNT);
+}
+
+void ManifestUmaUtil::FetchFailed(FetchFailureReason reason) {
+ ManifestFetchResultType fetch_result_type = MANIFEST_FETCH_RESULT_TYPE_COUNT;
+ switch (reason) {
+ case FETCH_EMPTY_URL:
+ fetch_result_type = MANIFEST_FETCH_ERROR_EMPTY_URL;
+ break;
+ case FETCH_UNSPECIFIED_REASON:
+ fetch_result_type = MANIFEST_FETCH_ERROR_UNSPECIFIED;
+ break;
+ }
+ DCHECK_NE(fetch_result_type, MANIFEST_FETCH_RESULT_TYPE_COUNT);
+
+ UMA_HISTOGRAM_ENUMERATION(kUMANameFetchResult,
+ fetch_result_type,
+ MANIFEST_FETCH_RESULT_TYPE_COUNT);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_uma_util.h b/chromium/content/renderer/manifest/manifest_uma_util.h
new file mode 100644
index 00000000000..9498145a1d8
--- /dev/null
+++ b/chromium/content/renderer/manifest/manifest_uma_util.h
@@ -0,0 +1,37 @@
+// Copyright 2014 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 CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
+#define CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
+
+namespace content {
+
+struct Manifest;
+
+class ManifestUmaUtil {
+ public:
+ enum FetchFailureReason {
+ FETCH_EMPTY_URL = 0,
+ FETCH_UNSPECIFIED_REASON
+ };
+
+ // Record that the Manifest was successfully parsed. If it is an empty
+ // Manifest, it will recorded as so and nothing will happen. Otherwise, the
+ // presence of each properties will be recorded.
+ static void ParseSucceeded(const Manifest& manifest);
+
+ // Record that the Manifest parsing failed.
+ static void ParseFailed();
+
+ // Record that the Manifest fetching succeeded.
+ static void FetchSucceeded();
+
+ // Record that the Manifest fetching failed and takes the |reason| why it
+ // failed.
+ static void FetchFailed(FetchFailureReason reason);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MANIFEST_MANIFEST_UMA_UTIL_H_
diff --git a/chromium/content/renderer/media/OWNERS b/chromium/content/renderer/media/OWNERS
index b1afdbbadb8..1aa4b630692 100644
--- a/chromium/content/renderer/media/OWNERS
+++ b/chromium/content/renderer/media/OWNERS
@@ -1,12 +1,10 @@
-acolwell@chromium.org
dalecurtis@chromium.org
ddorwin@chromium.org
perkj@chromium.org
scherkus@chromium.org
-shadi@chromium.org
tommi@chromium.org
vrk@chromium.org
-wjia@chromium.org
+wolenetz@chromium.org
xhwang@chromium.org
xians@chromium.org
@@ -14,3 +12,6 @@ per-file cast_*=hclam@chromium.org
per-file cast_*=hubbe@chromium.org
per-file cast_*=mikhal@chromium.org
per-file cast_*=pwestin@google.com
+
+per-file midi_*=toyoshim@chromium.org
+per-file renderer_webmidi*=toyoshim@chromium.org
diff --git a/chromium/content/renderer/media/active_loader.cc b/chromium/content/renderer/media/active_loader.cc
deleted file mode 100644
index 6951514e5b1..00000000000
--- a/chromium/content/renderer/media/active_loader.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/active_loader.h"
-
-#include "content/renderer/media/buffered_resource_loader.h"
-#include "third_party/WebKit/public/platform/WebURLLoader.h"
-
-namespace content {
-
-ActiveLoader::ActiveLoader(scoped_ptr<blink::WebURLLoader> loader)
- : loader_(loader.Pass()),
- deferred_(false) {
-}
-
-ActiveLoader::~ActiveLoader() {
- loader_->cancel();
-}
-
-void ActiveLoader::SetDeferred(bool deferred) {
- deferred_ = deferred;
- loader_->setDefersLoading(deferred);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/active_loader.h b/chromium/content/renderer/media/active_loader.h
deleted file mode 100644
index 1c30214b92c..00000000000
--- a/chromium/content/renderer/media/active_loader.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_ACTIVE_LOADER_H_
-#define CONTENT_RENDERER_MEDIA_ACTIVE_LOADER_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace blink {
-class WebURLLoader;
-}
-
-namespace content {
-
-// Wraps an active WebURLLoader with some additional state.
-//
-// Handles deferring and deletion of loaders.
-class ActiveLoader {
- public:
- // Creates an ActiveLoader with the given loader. It is assumed that the
- // initial state of |loader| is loading and not deferred.
- explicit ActiveLoader(scoped_ptr<blink::WebURLLoader> loader);
- ~ActiveLoader();
-
- // Starts or stops deferring the resource load.
- void SetDeferred(bool deferred);
- bool deferred() { return deferred_; }
-
- private:
- friend class BufferedDataSourceTest;
-
- scoped_ptr<blink::WebURLLoader> loader_;
- bool deferred_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(ActiveLoader);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_ACTIVE_LOADER_H_
diff --git a/chromium/content/renderer/media/aec_dump_message_filter.h b/chromium/content/renderer/media/aec_dump_message_filter.h
index 7268132d2ef..7d7a3bfca69 100644
--- a/chromium/content/renderer/media/aec_dump_message_filter.h
+++ b/chromium/content/renderer/media/aec_dump_message_filter.h
@@ -49,7 +49,7 @@ class CONTENT_EXPORT AecDumpMessageFilter : public IPC::MessageFilter {
}
protected:
- virtual ~AecDumpMessageFilter();
+ ~AecDumpMessageFilter() override;
private:
// Sends an IPC message using |sender_|.
@@ -64,10 +64,10 @@ class CONTENT_EXPORT AecDumpMessageFilter : public IPC::MessageFilter {
void UnregisterAecDumpConsumer(int id);
// IPC::MessageFilter override. Called on |io_message_loop|.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
// Accessed on |io_message_loop|.
void OnEnableAecDump(int id, IPC::PlatformFileForTransit file_handle);
diff --git a/chromium/content/renderer/media/android/OWNERS b/chromium/content/renderer/media/android/OWNERS
index b896e286436..5abf5a186b9 100644
--- a/chromium/content/renderer/media/android/OWNERS
+++ b/chromium/content/renderer/media/android/OWNERS
@@ -1,2 +1 @@
-bulach@chromium.org
qinmin@chromium.org
diff --git a/chromium/content/renderer/media/android/audio_decoder_android.cc b/chromium/content/renderer/media/android/audio_decoder_android.cc
index 72e25ab2bcc..f3e118ce641 100644
--- a/chromium/content/renderer/media/android/audio_decoder_android.cc
+++ b/chromium/content/renderer/media/android/audio_decoder_android.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/process/process_handle.h"
#include "content/common/view_messages.h"
#include "media/base/android/webaudio_media_codec_info.h"
#include "media/base/audio_bus.h"
@@ -89,9 +90,8 @@ bool AudioDecoderIO::IsValid() const {
}
bool AudioDecoderIO::ShareEncodedToProcess(base::SharedMemoryHandle* handle) {
- return encoded_shared_memory_.ShareToProcess(
- base::Process::Current().handle(),
- handle);
+ return encoded_shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(),
+ handle);
}
static float ConvertSampleToFloat(int16_t sample) {
diff --git a/chromium/content/renderer/media/android/media_info_loader.cc b/chromium/content/renderer/media/android/media_info_loader.cc
index 8a49e04087f..35b79807b3a 100644
--- a/chromium/content/renderer/media/android/media_info_loader.cc
+++ b/chromium/content/renderer/media/android/media_info_loader.cc
@@ -22,6 +22,7 @@ using blink::WebURLResponse;
namespace content {
static const int kHttpOK = 200;
+static const int kHttpPartialContentOK = 206;
MediaInfoLoader::MediaInfoLoader(
const GURL& url,
@@ -29,6 +30,7 @@ MediaInfoLoader::MediaInfoLoader(
const ReadyCB& ready_cb)
: loader_failed_(false),
url_(url),
+ allow_stored_credentials_(false),
cors_mode_(cors_mode),
single_origin_(true),
ready_cb_(ready_cb) {}
@@ -41,12 +43,20 @@ void MediaInfoLoader::Start(blink::WebFrame* frame) {
CHECK(frame);
start_time_ = base::TimeTicks::Now();
+ first_party_url_ = frame->document().firstPartyForCookies();
// Prepare the request.
WebURLRequest request(url_);
- request.setTargetType(WebURLRequest::TargetIsMedia);
+ // TODO(mkwst): Split this into video/audio.
+ request.setRequestContext(WebURLRequest::RequestContextVideo);
frame->setReferrerForRequest(request, blink::WebURL());
+ // Since we don't actually care about the media data at this time, use a two
+ // byte range request to avoid unnecessarily downloading resources. Not all
+ // servers support HEAD unfortunately, so use a range request; which is no
+ // worse than the previous request+cancel code. See http://crbug.com/400788
+ request.addHTTPHeaderField("Range", "bytes=0-1");
+
scoped_ptr<WebURLLoader> loader;
if (test_loader_) {
loader = test_loader_.Pass();
@@ -56,21 +66,24 @@ void MediaInfoLoader::Start(blink::WebFrame* frame) {
options.allowCredentials = true;
options.crossOriginRequestPolicy =
WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
+ allow_stored_credentials_ = true;
} else {
options.exposeAllResponseHeaders = true;
// The author header set is empty, no preflight should go ahead.
options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
options.crossOriginRequestPolicy =
WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
- if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials)
+ if (cors_mode_ == blink::WebMediaPlayer::CORSModeUseCredentials) {
options.allowCredentials = true;
+ allow_stored_credentials_ = true;
+ }
}
loader.reset(frame->createAssociatedURLLoader(options));
}
// Start the resource loading.
loader->loadAsynchronously(request, this);
- active_loader_.reset(new ActiveLoader(loader.Pass()));
+ active_loader_.reset(new media::ActiveLoader(loader.Pass()));
}
/////////////////////////////////////////////////////////////////////////////
@@ -92,6 +105,8 @@ void MediaInfoLoader::willSendRequest(
single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
url_ = newRequest.url();
+ first_party_url_ = newRequest.firstPartyForCookies();
+ allow_stored_credentials_ = newRequest.allowStoredCredentials();
}
void MediaInfoLoader::didSendData(
@@ -111,11 +126,12 @@ void MediaInfoLoader::didReceiveResponse(
"Unknown")
<< " " << response.httpStatusCode();
DCHECK(active_loader_.get());
- if (!url_.SchemeIs("http") && !url_.SchemeIs("https")) {
+ if (!url_.SchemeIs(url::kHttpScheme) && !url_.SchemeIs(url::kHttpsScheme)) {
DidBecomeReady(kOk);
return;
}
- if (response.httpStatusCode() == kHttpOK) {
+ if (response.httpStatusCode() == kHttpOK ||
+ response.httpStatusCode() == kHttpPartialContentOK) {
DidBecomeReady(kOk);
return;
}
@@ -187,7 +203,8 @@ void MediaInfoLoader::DidBecomeReady(Status status) {
base::TimeTicks::Now() - start_time_);
active_loader_.reset();
if (!ready_cb_.is_null())
- base::ResetAndReturn(&ready_cb_).Run(status);
+ base::ResetAndReturn(&ready_cb_).Run(status, url_, first_party_url_,
+ allow_stored_credentials_);
}
} // namespace content
diff --git a/chromium/content/renderer/media/android/media_info_loader.h b/chromium/content/renderer/media/android/media_info_loader.h
index d87b67c30ed..b421fb3796b 100644
--- a/chromium/content/renderer/media/android/media_info_loader.h
+++ b/chromium/content/renderer/media/android/media_info_loader.h
@@ -11,9 +11,10 @@
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
-#include "content/renderer/media/active_loader.h"
+#include "media/blink/active_loader.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
#include "url/gurl.h"
namespace blink {
@@ -44,11 +45,16 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient {
kOk,
};
+ // Callback when MediaInfoLoader finishes loading the url. Args: whether URL
+ // is successfully loaded, the final URL destination following all the
+ // redirect, the first party URL for the final destination, and whether
+ // credentials needs to be sent to the final destination.
+ typedef base::Callback<void(Status, const GURL&, const GURL&, bool)> ReadyCB;
+
// Start loading information about the given media URL.
// |url| - URL for the media resource to be loaded.
// |cors_mode| - HTML media element's crossorigin attribute.
// |ready_cb| - Called when media info has finished or failed loading.
- typedef base::Callback<void(Status)> ReadyCB;
MediaInfoLoader(
const GURL& url,
blink::WebMediaPlayer::CORSMode cors_mode,
@@ -66,10 +72,6 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient {
// Only valid to call after the loader becomes ready.
bool DidPassCORSAccessCheck() const;
- void set_single_origin(bool single_origin) {
- single_origin_ = single_origin;
- }
-
private:
friend class MediaInfoLoaderTest;
@@ -111,10 +113,12 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient {
scoped_ptr<blink::WebURLLoader> test_loader_;
// Keeps track of an active WebURLLoader and associated state.
- scoped_ptr<ActiveLoader> active_loader_;
+ scoped_ptr<media::ActiveLoader> active_loader_;
bool loader_failed_;
GURL url_;
+ GURL first_party_url_;
+ bool allow_stored_credentials_;
blink::WebMediaPlayer::CORSMode cors_mode_;
bool single_origin_;
diff --git a/chromium/content/renderer/media/android/media_info_loader_unittest.cc b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
index ffde7927e1d..41a7b894b77 100644
--- a/chromium/content/renderer/media/android/media_info_loader_unittest.cc
+++ b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
@@ -86,7 +86,7 @@ class MediaInfoLoaderTest : public testing::Test {
void SendResponse(
int http_status, MediaInfoLoader::Status expected_status) {
- EXPECT_CALL(*this, ReadyCallback(expected_status));
+ EXPECT_CALL(*this, ReadyCallback(expected_status, _, _, _));
EXPECT_CALL(*url_loader_, cancel());
WebURLResponse response(gurl_);
@@ -98,11 +98,13 @@ class MediaInfoLoaderTest : public testing::Test {
}
void FailLoad() {
- EXPECT_CALL(*this, ReadyCallback(MediaInfoLoader::kFailed));
+ EXPECT_CALL(*this, ReadyCallback(
+ MediaInfoLoader::kFailed, _, _, _));
loader_->didFail(url_loader_, WebURLError());
}
- MOCK_METHOD1(ReadyCallback, void(MediaInfoLoader::Status));
+ MOCK_METHOD4(ReadyCallback,
+ void(MediaInfoLoader::Status, const GURL&, const GURL&, bool));
protected:
GURL gurl_;
diff --git a/chromium/content/renderer/media/android/media_source_delegate.cc b/chromium/content/renderer/media/android/media_source_delegate.cc
index eeb4c7e662a..504a08f3088 100644
--- a/chromium/content/renderer/media/android/media_source_delegate.cc
+++ b/chromium/content/renderer/media/android/media_source_delegate.cc
@@ -11,12 +11,12 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_number_conversions.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
-#include "content/renderer/media/webmediaplayer_util.h"
-#include "content/renderer/media/webmediasource_impl.h"
#include "media/base/android/demuxer_stream_player_params.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_log.h"
+#include "media/blink/webmediaplayer_util.h"
+#include "media/blink/webmediasource_impl.h"
#include "media/filters/chunk_demuxer.h"
#include "media/filters/decrypting_demuxer_stream.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -48,8 +48,8 @@ static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
MediaSourceDelegate::MediaSourceDelegate(
RendererDemuxerAndroid* demuxer_client,
int demuxer_client_id,
- const scoped_refptr<base::MessageLoopProxy>& media_loop,
- media::MediaLog* media_log)
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
+ const scoped_refptr<media::MediaLog> media_log)
: demuxer_client_(demuxer_client),
demuxer_client_id_(demuxer_client_id),
media_log_(media_log),
@@ -62,16 +62,16 @@ MediaSourceDelegate::MediaSourceDelegate(
browser_seek_time_(media::kNoTimestamp()),
expecting_regular_seek_(false),
access_unit_size_(0),
- main_loop_(base::MessageLoopProxy::current()),
- media_loop_(media_loop),
+ main_task_runner_(base::MessageLoopProxy::current()),
+ media_task_runner_(media_task_runner),
main_weak_factory_(this),
media_weak_factory_(this),
main_weak_this_(main_weak_factory_.GetWeakPtr()) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
}
MediaSourceDelegate::~MediaSourceDelegate() {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
DCHECK(!chunk_demuxer_);
DCHECK(!demuxer_client_);
@@ -81,13 +81,12 @@ MediaSourceDelegate::~MediaSourceDelegate() {
DCHECK(!video_stream_);
}
-void MediaSourceDelegate::Destroy() {
- DCHECK(main_loop_->BelongsToCurrentThread());
+void MediaSourceDelegate::Stop(const base::Closure& stop_cb) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
if (!chunk_demuxer_) {
DCHECK(!demuxer_client_);
- delete this;
return;
}
@@ -100,30 +99,30 @@ void MediaSourceDelegate::Destroy() {
chunk_demuxer_->Shutdown();
- // |this| will be transferred to the callback StopDemuxer() and
- // OnDemuxerStopDone(). They own |this| and OnDemuxerStopDone() will delete
- // it when called, hence using base::Unretained(this) is safe here.
- media_loop_->PostTask(FROM_HERE,
- base::Bind(&MediaSourceDelegate::StopDemuxer,
- base::Unretained(this)));
+ // Continue to stop objects on the media thread.
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &MediaSourceDelegate::StopDemuxer, base::Unretained(this), stop_cb));
}
bool MediaSourceDelegate::IsVideoEncrypted() {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
base::AutoLock auto_lock(is_video_encrypted_lock_);
return is_video_encrypted_;
}
base::Time MediaSourceDelegate::GetTimelineOffset() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
if (!chunk_demuxer_)
return base::Time();
return chunk_demuxer_->GetTimelineOffset();
}
-void MediaSourceDelegate::StopDemuxer() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+void MediaSourceDelegate::StopDemuxer(const base::Closure& stop_cb) {
+ DVLOG(2) << __FUNCTION__;
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DCHECK(chunk_demuxer_);
demuxer_client_->RemoveDelegate(demuxer_client_id_);
@@ -139,10 +138,12 @@ void MediaSourceDelegate::StopDemuxer() {
media_weak_factory_.InvalidateWeakPtrs();
DCHECK(!media_weak_factory_.HasWeakPtrs());
- // The callback OnDemuxerStopDone() owns |this| and will delete it when
- // called. Hence using base::Unretained(this) is safe here.
- chunk_demuxer_->Stop(base::Bind(&MediaSourceDelegate::OnDemuxerStopDone,
- base::Unretained(this)));
+ chunk_demuxer_->Stop();
+ chunk_demuxer_.reset();
+
+ // |this| may be destroyed at this point in time as a result of running
+ // |stop_cb|.
+ stop_cb.Run();
}
void MediaSourceDelegate::InitializeMediaSource(
@@ -151,7 +152,7 @@ void MediaSourceDelegate::InitializeMediaSource(
const media::SetDecryptorReadyCB& set_decryptor_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
const DurationChangeCB& duration_change_cb) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DCHECK(!media_source_opened_cb.is_null());
media_source_opened_cb_ = media_source_opened_cb;
need_key_cb_ = need_key_cb;
@@ -170,13 +171,13 @@ void MediaSourceDelegate::InitializeMediaSource(
// |this| will be retained until StopDemuxer() is posted, so Unretained() is
// safe here.
- media_loop_->PostTask(FROM_HERE,
+ media_task_runner_->PostTask(FROM_HERE,
base::Bind(&MediaSourceDelegate::InitializeDemuxer,
base::Unretained(this)));
}
void MediaSourceDelegate::InitializeDemuxer() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
demuxer_client_->AddDelegate(demuxer_client_id_, this);
chunk_demuxer_->Initialize(this,
base::Bind(&MediaSourceDelegate::OnDemuxerInitDone,
@@ -185,7 +186,7 @@ void MediaSourceDelegate::InitializeDemuxer() {
}
blink::WebTimeRanges MediaSourceDelegate::Buffered() const {
- return ConvertToWebTimeRanges(buffered_time_ranges_);
+ return media::ConvertToWebTimeRanges(buffered_time_ranges_);
}
size_t MediaSourceDelegate::DecodedFrameCount() const {
@@ -205,7 +206,7 @@ size_t MediaSourceDelegate::VideoDecodedByteCount() const {
}
void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
<< demuxer_client_id_;
@@ -229,7 +230,7 @@ void MediaSourceDelegate::CancelPendingSeek(const base::TimeDelta& seek_time) {
void MediaSourceDelegate::StartWaitingForSeek(
const base::TimeDelta& seek_time) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ") : "
<< demuxer_client_id_;
@@ -257,7 +258,7 @@ void MediaSourceDelegate::StartWaitingForSeek(
void MediaSourceDelegate::Seek(
const base::TimeDelta& seek_time, bool is_browser_seek) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ", "
<< (is_browser_seek ? "browser seek" : "regular seek") << ") : "
<< demuxer_client_id_;
@@ -299,7 +300,7 @@ void MediaSourceDelegate::Seek(
}
void MediaSourceDelegate::SeekInternal(const base::TimeDelta& seek_time) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DCHECK(IsSeeking());
chunk_demuxer_->Seek(seek_time, base::Bind(
&MediaSourceDelegate::OnDemuxerSeekDone,
@@ -312,18 +313,18 @@ void MediaSourceDelegate::AddBufferedTimeRange(base::TimeDelta start,
}
void MediaSourceDelegate::SetDuration(base::TimeDelta duration) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << duration.InSecondsF() << ") : "
<< demuxer_client_id_;
// Force duration change notification to be async to avoid reentrancy into
// ChunkDemxuer.
- main_loop_->PostTask(FROM_HERE, base::Bind(
+ main_task_runner_->PostTask(FROM_HERE, base::Bind(
&MediaSourceDelegate::OnDurationChanged, main_weak_this_, duration));
}
void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
if (demuxer_client_)
demuxer_client_->DurationChanged(demuxer_client_id_, duration);
if (!duration_change_cb_.is_null())
@@ -331,7 +332,7 @@ void MediaSourceDelegate::OnDurationChanged(const base::TimeDelta& duration) {
}
void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << type << ") : " << demuxer_client_id_;
if (IsSeeking())
return; // Drop the request during seeking.
@@ -348,7 +349,7 @@ void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type,
scoped_ptr<DemuxerData> data,
size_t index) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
// DemuxerStream::Read() always returns the read callback asynchronously.
DemuxerStream* stream =
(type == DemuxerStream::AUDIO) ? audio_stream_ : video_stream_;
@@ -363,10 +364,11 @@ void MediaSourceDelegate::OnBufferReady(
size_t index,
DemuxerStream::Status status,
const scoped_refptr<media::DecoderBuffer>& buffer) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << index << ", " << status << ", "
- << ((!buffer || buffer->end_of_stream()) ?
- -1 : buffer->timestamp().InMilliseconds())
+ << ((!buffer.get() || buffer->end_of_stream())
+ ? -1
+ : buffer->timestamp().InMilliseconds())
<< ") : " << demuxer_client_id_;
DCHECK(chunk_demuxer_);
@@ -481,7 +483,7 @@ void MediaSourceDelegate::RemoveTextStream(
}
void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
DCHECK(chunk_demuxer_);
@@ -513,12 +515,12 @@ void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
}
void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
DCHECK(!set_decryptor_ready_cb_.is_null());
audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
- media_loop_, set_decryptor_ready_cb_));
+ media_task_runner_, set_decryptor_ready_cb_));
audio_decrypting_demuxer_stream_->Initialize(
audio_stream_,
base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone,
@@ -526,12 +528,12 @@ void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
}
void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
DCHECK(!set_decryptor_ready_cb_.is_null());
video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
- media_loop_, set_decryptor_ready_cb_));
+ media_task_runner_, set_decryptor_ready_cb_));
video_decrypting_demuxer_stream_->Initialize(
video_stream_,
base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone,
@@ -540,7 +542,7 @@ void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
media::PipelineStatus status) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
DCHECK(chunk_demuxer_);
@@ -562,7 +564,7 @@ void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
media::PipelineStatus status) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
DCHECK(chunk_demuxer_);
@@ -577,7 +579,7 @@ void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
}
void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
DCHECK(IsSeeking());
@@ -590,7 +592,7 @@ void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
}
void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
if (audio_decrypting_demuxer_stream_) {
audio_decrypting_demuxer_stream_->Reset(
@@ -603,7 +605,7 @@ void MediaSourceDelegate::ResetAudioDecryptingDemuxerStream() {
}
void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
if (video_decrypting_demuxer_stream_) {
video_decrypting_demuxer_stream_->Reset(base::Bind(
@@ -616,7 +618,7 @@ void MediaSourceDelegate::ResetVideoDecryptingDemuxerStream() {
}
void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
base::AutoLock auto_lock(seeking_lock_);
@@ -626,23 +628,8 @@ void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
}
-void MediaSourceDelegate::OnDemuxerStopDone() {
- DCHECK(media_loop_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- main_loop_->PostTask(
- FROM_HERE,
- base::Bind(&MediaSourceDelegate::DeleteSelf, base::Unretained(this)));
-}
-
-void MediaSourceDelegate::DeleteSelf() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- chunk_demuxer_.reset();
- delete this;
-}
-
void MediaSourceDelegate::NotifyDemuxerReady() {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
DCHECK(is_demuxer_ready_);
@@ -659,7 +646,7 @@ void MediaSourceDelegate::NotifyDemuxerReady() {
}
base::TimeDelta MediaSourceDelegate::GetDuration() const {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
if (!chunk_demuxer_)
return media::kNoTimestamp();
@@ -667,21 +654,21 @@ base::TimeDelta MediaSourceDelegate::GetDuration() const {
if (duration == std::numeric_limits<double>::infinity())
return media::kInfiniteDuration();
- return ConvertSecondsToTimestamp(duration);
+ return media::ConvertSecondsToTimestamp(duration);
}
void MediaSourceDelegate::OnDemuxerOpened() {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
if (media_source_opened_cb_.is_null())
return;
- media_source_opened_cb_.Run(new WebMediaSourceImpl(
+ media_source_opened_cb_.Run(new media::WebMediaSourceImpl(
chunk_demuxer_.get(), base::Bind(&LogMediaSourceError, media_log_)));
}
void MediaSourceDelegate::OnNeedKey(const std::string& type,
const std::vector<uint8>& init_data) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
if (need_key_cb_.is_null())
return;
@@ -736,7 +723,7 @@ base::TimeDelta MediaSourceDelegate::FindBufferedBrowserSeekTime_Locked(
bool MediaSourceDelegate::GetDemuxerConfigFromStream(
media::DemuxerConfigs* configs, bool is_audio) {
- DCHECK(media_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
if (!is_demuxer_ready_)
return false;
if (is_audio && audio_stream_) {
diff --git a/chromium/content/renderer/media/android/media_source_delegate.h b/chromium/content/renderer/media/android/media_source_delegate.h
index 28b18325938..c451e0724ae 100644
--- a/chromium/content/renderer/media/android/media_source_delegate.h
+++ b/chromium/content/renderer/media/android/media_source_delegate.h
@@ -12,7 +12,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "media/base/decryptor.h"
#include "media/base/demuxer.h"
@@ -22,6 +21,10 @@
#include "media/base/text_track.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace media {
class ChunkDemuxer;
class DecoderBuffer;
@@ -44,19 +47,12 @@ class MediaSourceDelegate : public media::DemuxerHost {
UpdateNetworkStateCB;
typedef base::Callback<void(const base::TimeDelta&)> DurationChangeCB;
- // Helper class used by scoped_ptr to destroy an instance of
- // MediaSourceDelegate.
- class Destroyer {
- public:
- inline void operator()(void* media_source_delegate) const {
- static_cast<MediaSourceDelegate*>(media_source_delegate)->Destroy();
- }
- };
-
- MediaSourceDelegate(RendererDemuxerAndroid* demuxer_client,
- int demuxer_client_id,
- const scoped_refptr<base::MessageLoopProxy>& media_loop,
- media::MediaLog* media_log);
+ MediaSourceDelegate(
+ RendererDemuxerAndroid* demuxer_client,
+ int demuxer_client_id,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ const scoped_refptr<media::MediaLog> media_log);
+ virtual ~MediaSourceDelegate();
// Initialize the MediaSourceDelegate. |media_source| will be owned by
// this object after this call.
@@ -97,8 +93,8 @@ class MediaSourceDelegate : public media::DemuxerHost {
// Called when DemuxerStreamPlayer needs to read data from ChunkDemuxer.
void OnReadFromDemuxer(media::DemuxerStream::Type type);
- // Called by the Destroyer to destroy an instance of this object.
- void Destroy();
+ // Must be called explicitly before |this| can be destroyed.
+ void Stop(const base::Closure& stop_cb);
// Called on the main thread to check whether the video stream is encrypted.
bool IsVideoEncrypted();
@@ -107,17 +103,14 @@ class MediaSourceDelegate : public media::DemuxerHost {
base::Time GetTimelineOffset() const;
private:
- // This is private to enforce use of the Destroyer.
- virtual ~MediaSourceDelegate();
-
// Methods inherited from DemuxerHost.
virtual void AddBufferedTimeRange(base::TimeDelta start,
- base::TimeDelta end) OVERRIDE;
- virtual void SetDuration(base::TimeDelta duration) OVERRIDE;
- virtual void OnDemuxerError(media::PipelineStatus status) OVERRIDE;
+ base::TimeDelta end) override;
+ virtual void SetDuration(base::TimeDelta duration) override;
+ virtual void OnDemuxerError(media::PipelineStatus status) override;
virtual void AddTextStream(media::DemuxerStream* text_stream,
- const media::TextTrackConfig& config) OVERRIDE;
- virtual void RemoveTextStream(media::DemuxerStream* text_stream) OVERRIDE;
+ const media::TextTrackConfig& config) override;
+ virtual void RemoveTextStream(media::DemuxerStream* text_stream) override;
// Notifies |demuxer_client_| and fires |duration_changed_cb_|.
void OnDurationChanged(const base::TimeDelta& duration);
@@ -142,17 +135,14 @@ class MediaSourceDelegate : public media::DemuxerHost {
void ResetVideoDecryptingDemuxerStream();
void FinishResettingDecryptingDemuxerStreams();
- // Callback for ChunkDemuxer::Stop() and helper for deleting |this| on the
- // main thread.
- void OnDemuxerStopDone();
- void DeleteSelf();
-
void OnDemuxerOpened();
void OnNeedKey(const std::string& type,
const std::vector<uint8>& init_data);
void NotifyDemuxerReady();
- void StopDemuxer();
+ // Stops and clears objects on the media thread.
+ void StopDemuxer(const base::Closure& stop_cb);
+
void InitializeDemuxer();
void SeekInternal(const base::TimeDelta& seek_time);
// Reads an access unit from the demuxer stream |stream| and stores it in
@@ -231,9 +221,9 @@ class MediaSourceDelegate : public media::DemuxerHost {
size_t access_unit_size_;
- // Message loop for main renderer and media threads.
- const scoped_refptr<base::MessageLoopProxy> main_loop_;
- const scoped_refptr<base::MessageLoopProxy> media_loop_;
+ // Task runner for main renderer and media threads.
+ const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<MediaSourceDelegate> main_weak_factory_;
diff --git a/chromium/content/renderer/media/android/renderer_demuxer_android.cc b/chromium/content/renderer/media/android/renderer_demuxer_android.cc
index 586d7fa44d2..6d40b202480 100644
--- a/chromium/content/renderer/media/android/renderer_demuxer_android.cc
+++ b/chromium/content/renderer/media/android/renderer_demuxer_android.cc
@@ -5,8 +5,7 @@
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
+#include "base/single_thread_task_runner.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/media/media_player_messages_android.h"
#include "content/renderer/media/android/media_source_delegate.h"
@@ -18,8 +17,8 @@ namespace content {
RendererDemuxerAndroid::RendererDemuxerAndroid()
: thread_safe_sender_(RenderThreadImpl::current()->thread_safe_sender()),
- media_message_loop_(
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()) {}
+ media_task_runner_(
+ RenderThreadImpl::current()->GetMediaThreadTaskRunner()) {}
RendererDemuxerAndroid::~RendererDemuxerAndroid() {}
@@ -30,12 +29,12 @@ int RendererDemuxerAndroid::GetNextDemuxerClientID() {
void RendererDemuxerAndroid::AddDelegate(int demuxer_client_id,
MediaSourceDelegate* delegate) {
- DCHECK(media_message_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
delegates_.AddWithID(delegate, demuxer_client_id);
}
void RendererDemuxerAndroid::RemoveDelegate(int demuxer_client_id) {
- DCHECK(media_message_loop_->BelongsToCurrentThread());
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
delegates_.Remove(demuxer_client_id);
}
@@ -43,7 +42,7 @@ bool RendererDemuxerAndroid::OnMessageReceived(const IPC::Message& message) {
switch (message.type()) {
case MediaPlayerMsg_DemuxerSeekRequest::ID:
case MediaPlayerMsg_ReadFromDemuxer::ID:
- media_message_loop_->PostTask(FROM_HERE, base::Bind(
+ media_task_runner_->PostTask(FROM_HERE, base::Bind(
&RendererDemuxerAndroid::DispatchMessage, this, message));
return true;
}
diff --git a/chromium/content/renderer/media/android/renderer_demuxer_android.h b/chromium/content/renderer/media/android/renderer_demuxer_android.h
index 2a92918bb7a..2fddc862048 100644
--- a/chromium/content/renderer/media/android/renderer_demuxer_android.h
+++ b/chromium/content/renderer/media/android/renderer_demuxer_android.h
@@ -11,7 +11,7 @@
#include "media/base/android/demuxer_stream_player_params.h"
namespace base {
-class MessageLoopProxy;
+class SingleThreadTaskRunner;
}
namespace content {
@@ -44,7 +44,7 @@ class RendererDemuxerAndroid : public IPC::MessageFilter {
void RemoveDelegate(int demuxer_client_id);
// IPC::MessageFilter overrides.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& message) override;
// media::DemuxerAndroidClient "implementation".
//
@@ -75,7 +75,7 @@ class RendererDemuxerAndroid : public IPC::MessageFilter {
IDMap<MediaSourceDelegate> delegates_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- scoped_refptr<base::MessageLoopProxy> media_message_loop_;
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
DISALLOW_COPY_AND_ASSIGN(RendererDemuxerAndroid);
};
diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.cc b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
index f3e0bc01cfc..9295b790280 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
@@ -55,20 +55,25 @@ bool RendererMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause)
- IPC_MESSAGE_HANDLER(MediaPlayerMsg_PauseVideo, OnPauseVideo)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_RemoteRouteAvailabilityChanged,
+ OnRemoteRouteAvailabilityChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+void RendererMediaPlayerManager::WasHidden() {
+ ReleaseVideoResources();
+}
+
void RendererMediaPlayerManager::Initialize(
MediaPlayerHostMsg_Initialize_Type type,
int player_id,
const GURL& url,
const GURL& first_party_for_cookies,
int demuxer_client_id,
- const GURL& frame_url) {
-
+ const GURL& frame_url,
+ bool allow_credentials) {
MediaPlayerHostMsg_Initialize_Params media_player_params;
media_player_params.type = type;
media_player_params.player_id = player_id;
@@ -76,6 +81,7 @@ void RendererMediaPlayerManager::Initialize(
media_player_params.url = url;
media_player_params.first_party_for_cookies = first_party_for_cookies;
media_player_params.frame_url = frame_url;
+ media_player_params.allow_credentials = allow_credentials;
Send(new MediaPlayerHostMsg_Initialize(routing_id(), media_player_params));
}
@@ -113,6 +119,15 @@ void RendererMediaPlayerManager::DestroyPlayer(int player_id) {
Send(new MediaPlayerHostMsg_DestroyMediaPlayer(routing_id(), player_id));
}
+void RendererMediaPlayerManager::RequestRemotePlayback(int player_id) {
+ Send(new MediaPlayerHostMsg_RequestRemotePlayback(routing_id(), player_id));
+}
+
+void RendererMediaPlayerManager::RequestRemotePlaybackControl(int player_id) {
+ Send(new MediaPlayerHostMsg_RequestRemotePlaybackControl(routing_id(),
+ player_id));
+}
+
void RendererMediaPlayerManager::OnMediaMetadataChanged(
int player_id,
base::TimeDelta duration,
@@ -167,11 +182,13 @@ void RendererMediaPlayerManager::OnVideoSizeChanged(int player_id,
player->OnVideoSizeChanged(width, height);
}
-void RendererMediaPlayerManager::OnTimeUpdate(int player_id,
- base::TimeDelta current_time) {
+void RendererMediaPlayerManager::OnTimeUpdate(
+ int player_id,
+ base::TimeDelta current_timestamp,
+ base::TimeTicks current_time_ticks) {
WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
if (player)
- player->OnTimeUpdate(current_time);
+ player->OnTimeUpdate(current_timestamp, current_time_ticks);
}
void RendererMediaPlayerManager::OnMediaPlayerReleased(int player_id) {
@@ -223,8 +240,12 @@ void RendererMediaPlayerManager::OnRequestFullscreen(int player_id) {
player->OnRequestFullscreen();
}
-void RendererMediaPlayerManager::OnPauseVideo() {
- ReleaseVideoResources();
+void RendererMediaPlayerManager::OnRemoteRouteAvailabilityChanged(
+ int player_id,
+ bool routes_available) {
+ WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnRemoteRouteAvailabilityChanged(routes_available);
}
void RendererMediaPlayerManager::EnterFullscreen(int player_id,
@@ -240,7 +261,7 @@ void RendererMediaPlayerManager::ExitFullscreen(int player_id) {
}
void RendererMediaPlayerManager::SetCdm(int player_id, int cdm_id) {
- if (cdm_id == RendererCdmManager::kInvalidCdmId) {
+ if (cdm_id == media::MediaKeys::kInvalidCdmId) {
NOTREACHED();
return;
}
diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.h b/chromium/content/renderer/media/android/renderer_media_player_manager.h
index 4bcb2888378..8a9fbb3763b 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.h
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.h
@@ -37,7 +37,8 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
virtual ~RendererMediaPlayerManager();
// RenderFrameObserver overrides.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) override;
+ virtual void WasHidden() override;
// Initializes a MediaPlayerAndroid object in browser process.
void Initialize(MediaPlayerHostMsg_Initialize_Type type,
@@ -45,7 +46,8 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
const GURL& url,
const GURL& first_party_for_cookies,
int demuxer_client_id,
- const GURL& frame_url);
+ const GURL& frame_url,
+ bool allow_credentials);
// Starts the player.
void Start(int player_id);
@@ -72,6 +74,12 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
// Destroys the player in the browser process
void DestroyPlayer(int player_id);
+ // Requests remote playback if possible
+ void RequestRemotePlayback(int player_id);
+
+ // Requests control of remote playback
+ void RequestRemotePlaybackControl(int player_id);
+
// Requests the player to enter fullscreen.
void EnterFullscreen(int player_id, blink::WebFrame* frame);
@@ -88,7 +96,7 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
void RequestExternalSurface(int player_id, const gfx::RectF& geometry);
// RenderFrameObserver overrides.
- virtual void DidCommitCompositorFrame() OVERRIDE;
+ virtual void DidCommitCompositorFrame() override;
// Returns true if a media player should use video-overlay for the embedded
// encrypted video.
@@ -130,10 +138,13 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
void OnMediaPlaybackCompleted(int player_id);
void OnMediaBufferingUpdate(int player_id, int percent);
void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
- void OnSeekCompleted(int player_id, const base::TimeDelta& current_time);
+ void OnSeekCompleted(int player_id,
+ const base::TimeDelta& current_timestamp);
void OnMediaError(int player_id, int error);
void OnVideoSizeChanged(int player_id, int width, int height);
- void OnTimeUpdate(int player_id, base::TimeDelta current_time);
+ void OnTimeUpdate(int player_id,
+ base::TimeDelta current_timestamp,
+ base::TimeTicks current_time_ticks);
void OnMediaPlayerReleased(int player_id);
void OnConnectedToRemoteDevice(int player_id,
const std::string& remote_playback_message);
@@ -143,7 +154,7 @@ class RendererMediaPlayerManager : public RenderFrameObserver {
void OnPlayerPlay(int player_id);
void OnPlayerPause(int player_id);
void OnRequestFullscreen(int player_id);
- void OnPauseVideo();
+ void OnRemoteRouteAvailabilityChanged(int player_id, bool routes_available);
// Release all video player resources.
// If something is in progress the resource will not be freed. It will
diff --git a/chromium/content/renderer/media/android/stream_texture_factory.h b/chromium/content/renderer/media/android/stream_texture_factory.h
index 70d31e9391a..8d048007635 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory.h
@@ -7,6 +7,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "cc/layers/video_frame_provider.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ui/gfx/size.h"
@@ -25,13 +26,12 @@ class StreamTextureProxy {
public:
virtual ~StreamTextureProxy() {}
- // Initialize and bind to the current thread, which becomes the thread that
- // a connected client will receive callbacks on.
- virtual void BindToCurrentThread(int32 stream_id) = 0;
-
- // Setting the target for callback when a frame is available. This function
- // could be called on both the main thread and the compositor thread.
- virtual void SetClient(cc::VideoFrameProvider::Client* client) = 0;
+ // Initialize and bind to the loop, which becomes the thread that
+ // a connected client will receive callbacks on. This can be called
+ // on any thread, but must be called with the same loop every time.
+ virtual void BindToLoop(int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) = 0;
// Causes this instance to be deleted on the thread it is bound to.
virtual void Release() = 0;
@@ -44,6 +44,12 @@ class StreamTextureProxy {
typedef scoped_ptr<StreamTextureProxy, StreamTextureProxy::Deleter>
ScopedStreamTextureProxy;
+class StreamTextureFactoryContextObserver {
+ public:
+ virtual ~StreamTextureFactoryContextObserver() {}
+ virtual void ResetStreamTextureProxy() = 0;
+};
+
// Factory class for managing stream textures.
class StreamTextureFactory : public base::RefCounted<StreamTextureFactory> {
public:
@@ -69,6 +75,9 @@ class StreamTextureFactory : public base::RefCounted<StreamTextureFactory> {
virtual gpu::gles2::GLES2Interface* ContextGL() = 0;
+ virtual void AddObserver(StreamTextureFactoryContextObserver* obs) = 0;
+ virtual void RemoveObserver(StreamTextureFactoryContextObserver* obs) = 0;
+
protected:
friend class base::RefCounted<StreamTextureFactory>;
virtual ~StreamTextureFactory() {}
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_impl.cc
index 58d165b5437..48b5861ddb6 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory_impl.cc
@@ -22,20 +22,24 @@ class StreamTextureProxyImpl : public StreamTextureProxy,
virtual ~StreamTextureProxyImpl();
// StreamTextureProxy implementation:
- virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
- virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
- virtual void Release() OVERRIDE;
+ virtual void BindToLoop(int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) override;
+ virtual void Release() override;
// StreamTextureHost::Listener implementation:
- virtual void OnFrameAvailable() OVERRIDE;
- virtual void OnMatrixChanged(const float matrix[16]) OVERRIDE;
+ virtual void OnFrameAvailable() override;
+ virtual void OnMatrixChanged(const float matrix[16]) override;
private:
- scoped_ptr<StreamTextureHost> host_;
- scoped_refptr<base::MessageLoopProxy> loop_;
+ void BindOnThread(int32 stream_id);
+
+ const scoped_ptr<StreamTextureHost> host_;
- base::Lock client_lock_;
+ // Protects access to |client_| and |loop_|.
+ base::Lock lock_;
cc::VideoFrameProvider::Client* client_;
+ scoped_refptr<base::MessageLoopProxy> loop_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl);
};
@@ -46,31 +50,58 @@ StreamTextureProxyImpl::StreamTextureProxyImpl(StreamTextureHost* host)
StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
void StreamTextureProxyImpl::Release() {
- SetClient(NULL);
- if (loop_.get() && loop_.get() != base::MessageLoopProxy::current())
- loop_->DeleteSoon(FROM_HERE, this);
- else
+ {
+ // Cannot call into |client_| anymore (from any thread) after returning
+ // from here.
+ base::AutoLock lock(lock_);
+ client_ = NULL;
+ }
+ // Release is analogous to the destructor, so there should be no more external
+ // calls to this object in Release. Therefore there is no need to acquire the
+ // lock to access |loop_|.
+ if (!loop_.get() || loop_->BelongsToCurrentThread() ||
+ !loop_->DeleteSoon(FROM_HERE, this)) {
delete this;
+ }
}
-void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
- base::AutoLock lock(client_lock_);
- client_ = client;
+void StreamTextureProxyImpl::BindToLoop(
+ int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) {
+ DCHECK(loop.get());
+
+ {
+ base::AutoLock lock(lock_);
+ DCHECK(!loop_.get() || (loop.get() == loop_.get()));
+ loop_ = loop;
+ client_ = client;
+ }
+
+ if (loop->BelongsToCurrentThread()) {
+ BindOnThread(stream_id);
+ return;
+ }
+ // Unretained is safe here only because the object is deleted on |loop_|
+ // thread.
+ loop->PostTask(FROM_HERE,
+ base::Bind(&StreamTextureProxyImpl::BindOnThread,
+ base::Unretained(this),
+ stream_id));
}
-void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
- loop_ = base::MessageLoopProxy::current();
+void StreamTextureProxyImpl::BindOnThread(int32 stream_id) {
host_->BindToCurrentThread(stream_id, this);
}
void StreamTextureProxyImpl::OnFrameAvailable() {
- base::AutoLock lock(client_lock_);
+ base::AutoLock lock(lock_);
if (client_)
client_->DidReceiveFrame();
}
void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
- base::AutoLock lock(client_lock_);
+ base::AutoLock lock(lock_);
if (client_)
client_->DidUpdateMatrix(matrix);
}
@@ -120,8 +151,8 @@ unsigned StreamTextureFactoryImpl::CreateStreamTexture(
stream_id = gl->CreateStreamTextureCHROMIUM(*texture_id);
gl->GenMailboxCHROMIUM(texture_mailbox->name);
- gl->BindTexture(texture_target, *texture_id);
- gl->ProduceTextureCHROMIUM(texture_target, texture_mailbox->name);
+ gl->ProduceTextureDirectCHROMIUM(
+ *texture_id, texture_target, texture_mailbox->name);
return stream_id;
}
@@ -134,4 +165,12 @@ gpu::gles2::GLES2Interface* StreamTextureFactoryImpl::ContextGL() {
return context_provider_->ContextGL();
}
+void StreamTextureFactoryImpl::AddObserver(
+ StreamTextureFactoryContextObserver* obs) {
+}
+
+void StreamTextureFactoryImpl::RemoveObserver(
+ StreamTextureFactoryContextObserver* obs) {
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_impl.h
index 7721c4812ee..f5ded1c8b05 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_impl.h
@@ -29,14 +29,17 @@ class StreamTextureFactoryImpl : public StreamTextureFactory {
int frame_id);
// StreamTextureFactory implementation.
- virtual StreamTextureProxy* CreateProxy() OVERRIDE;
- virtual void EstablishPeer(int32 stream_id, int player_id) OVERRIDE;
+ virtual StreamTextureProxy* CreateProxy() override;
+ virtual void EstablishPeer(int32 stream_id, int player_id) override;
virtual unsigned CreateStreamTexture(unsigned texture_target,
unsigned* texture_id,
- gpu::Mailbox* texture_mailbox) OVERRIDE;
+ gpu::Mailbox* texture_mailbox) override;
virtual void SetStreamTextureSize(int32 texture_id,
- const gfx::Size& size) OVERRIDE;
- virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE;
+ const gfx::Size& size) override;
+ virtual gpu::gles2::GLES2Interface* ContextGL() override;
+ virtual void AddObserver(StreamTextureFactoryContextObserver* obs) override;
+ virtual void RemoveObserver(
+ StreamTextureFactoryContextObserver* obs) override;
private:
friend class base::RefCounted<StreamTextureFactoryImpl>;
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc
index 75536cbacc9..c6eb63d931d 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc
@@ -11,7 +11,7 @@
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
-#include "base/process/process.h"
+#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
#include "cc/output/context_provider.h"
#include "content/common/android/surface_texture_peer.h"
@@ -34,23 +34,25 @@ class StreamTextureProxyImpl
virtual ~StreamTextureProxyImpl();
// StreamTextureProxy implementation:
- virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
- virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
- virtual void Release() OVERRIDE;
+ virtual void BindToLoop(int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) override;
+ virtual void Release() override;
private:
- void BindOnCompositorThread(int stream_id);
+ void BindOnThread(int32 stream_id);
void OnFrameAvailable();
- scoped_refptr<base::MessageLoopProxy> loop_;
- base::Lock client_lock_;
+ // Protects access to |client_| and |loop_|.
+ base::Lock lock_;
cc::VideoFrameProvider::Client* client_;
- base::Closure callback_;
+ scoped_refptr<base::MessageLoopProxy> loop_;
+ // Accessed on the |loop_| thread only.
+ base::Closure callback_;
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
context_provider_;
scoped_refptr<gfx::SurfaceTexture> surface_texture_;
-
float current_matrix_[16];
bool has_updated_;
@@ -59,43 +61,56 @@ class StreamTextureProxyImpl
StreamTextureProxyImpl::StreamTextureProxyImpl(
StreamTextureFactorySynchronousImpl::ContextProvider* provider)
- : context_provider_(provider), has_updated_(false) {
- DCHECK(RenderThreadImpl::current());
- loop_ = RenderThreadImpl::current()->compositor_message_loop_proxy();
+ : client_(NULL), context_provider_(provider), has_updated_(false) {
std::fill(current_matrix_, current_matrix_ + 16, 0);
}
StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
void StreamTextureProxyImpl::Release() {
- SetClient(NULL);
- if (!loop_->BelongsToCurrentThread())
- loop_->DeleteSoon(FROM_HERE, this);
- else
+ {
+ // Cannot call into |client_| anymore (from any thread) after returning
+ // from here.
+ base::AutoLock lock(lock_);
+ client_ = NULL;
+ }
+ // Release is analogous to the destructor, so there should be no more external
+ // calls to this object in Release. Therefore there is no need to acquire the
+ // lock to access |loop_|.
+ if (!loop_.get() || loop_->BelongsToCurrentThread() ||
+ !loop_->DeleteSoon(FROM_HERE, this)) {
delete this;
+ }
}
-void StreamTextureProxyImpl::SetClient(cc::VideoFrameProvider::Client* client) {
- base::AutoLock lock(client_lock_);
- client_ = client;
-}
+void StreamTextureProxyImpl::BindToLoop(
+ int32 stream_id,
+ cc::VideoFrameProvider::Client* client,
+ scoped_refptr<base::MessageLoopProxy> loop) {
+ DCHECK(loop.get());
+
+ {
+ base::AutoLock lock(lock_);
+ DCHECK(!loop_.get() || (loop.get() == loop_.get()));
+ loop_ = loop;
+ client_ = client;
+ }
-void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
- if (loop_->BelongsToCurrentThread()) {
- BindOnCompositorThread(stream_id);
+ if (loop->BelongsToCurrentThread()) {
+ BindOnThread(stream_id);
return;
}
-
- // Weakptr is only used on compositor thread loop, so this is safe.
- loop_->PostTask(FROM_HERE,
- base::Bind(&StreamTextureProxyImpl::BindOnCompositorThread,
- AsWeakPtr(),
- stream_id));
+ // Unretained is safe here only because the object is deleted on |loop_|
+ // thread.
+ loop->PostTask(FROM_HERE,
+ base::Bind(&StreamTextureProxyImpl::BindOnThread,
+ base::Unretained(this),
+ stream_id));
}
-void StreamTextureProxyImpl::BindOnCompositorThread(int stream_id) {
+void StreamTextureProxyImpl::BindOnThread(int32 stream_id) {
surface_texture_ = context_provider_->GetSurfaceTexture(stream_id);
- if (!surface_texture_) {
+ if (!surface_texture_.get()) {
LOG(ERROR) << "Failed to get SurfaceTexture for stream.";
return;
}
@@ -116,7 +131,7 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) {
memcpy(current_matrix_, matrix, sizeof(matrix));
- base::AutoLock lock(client_lock_);
+ base::AutoLock lock(lock_);
if (client_)
client_->DidUpdateMatrix(current_matrix_);
}
@@ -125,7 +140,7 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
// updateTexImage since after we received the first frame.
has_updated_ = true;
- base::AutoLock lock(client_lock_);
+ base::AutoLock lock(lock_);
if (client_)
client_->DidReceiveFrame();
}
@@ -145,27 +160,32 @@ StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
int frame_id)
: create_context_provider_callback_(try_create_callback),
context_provider_(create_context_provider_callback_.Run()),
- frame_id_(frame_id) {}
+ frame_id_(frame_id),
+ observer_(NULL) {}
StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
- if (!context_provider_)
+ bool had_proxy = !!context_provider_.get();
+ if (!had_proxy)
context_provider_ = create_context_provider_callback_.Run();
- if (!context_provider_)
+ if (!context_provider_.get())
return NULL;
- return new StreamTextureProxyImpl(context_provider_);
+
+ if (observer_ && !had_proxy)
+ context_provider_->AddObserver(observer_);
+ return new StreamTextureProxyImpl(context_provider_.get());
}
void StreamTextureFactorySynchronousImpl::EstablishPeer(int32 stream_id,
int player_id) {
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
scoped_refptr<gfx::SurfaceTexture> surface_texture =
context_provider_->GetSurfaceTexture(stream_id);
- if (surface_texture) {
+ if (surface_texture.get()) {
SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
- base::Process::Current().handle(),
+ base::GetCurrentProcessHandle(),
surface_texture,
frame_id_,
player_id);
@@ -176,15 +196,15 @@ unsigned StreamTextureFactorySynchronousImpl::CreateStreamTexture(
unsigned texture_target,
unsigned* texture_id,
gpu::Mailbox* texture_mailbox) {
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
unsigned stream_id = 0;
GLES2Interface* gl = context_provider_->ContextGL();
gl->GenTextures(1, texture_id);
stream_id = gl->CreateStreamTextureCHROMIUM(*texture_id);
gl->GenMailboxCHROMIUM(texture_mailbox->name);
- gl->BindTexture(texture_target, *texture_id);
- gl->ProduceTextureCHROMIUM(texture_target, texture_mailbox->name);
+ gl->ProduceTextureDirectCHROMIUM(
+ *texture_id, texture_target, texture_mailbox->name);
return stream_id;
}
@@ -193,8 +213,24 @@ void StreamTextureFactorySynchronousImpl::SetStreamTextureSize(
const gfx::Size& size) {}
gpu::gles2::GLES2Interface* StreamTextureFactorySynchronousImpl::ContextGL() {
- DCHECK(context_provider_);
+ DCHECK(context_provider_.get());
return context_provider_->ContextGL();
}
+void StreamTextureFactorySynchronousImpl::AddObserver(
+ StreamTextureFactoryContextObserver* obs) {
+ DCHECK(!observer_);
+ observer_ = obs;
+ if (context_provider_.get())
+ context_provider_->AddObserver(obs);
+}
+
+void StreamTextureFactorySynchronousImpl::RemoveObserver(
+ StreamTextureFactoryContextObserver* obs) {
+ DCHECK_EQ(observer_, obs);
+ observer_ = NULL;
+ if (context_provider_.get())
+ context_provider_->RemoveObserver(obs);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h
index 3466c564c9b..3f33bd39b1a 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
#include "content/renderer/media/android/stream_texture_factory.h"
namespace gfx {
@@ -31,6 +32,9 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
virtual gpu::gles2::GLES2Interface* ContextGL() = 0;
+ virtual void AddObserver(StreamTextureFactoryContextObserver* obs) = 0;
+ virtual void RemoveObserver(StreamTextureFactoryContextObserver* obs) = 0;
+
protected:
friend class base::RefCountedThreadSafe<ContextProvider>;
virtual ~ContextProvider() {}
@@ -43,14 +47,17 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
const CreateContextProviderCallback& try_create_callback,
int frame_id);
- virtual StreamTextureProxy* CreateProxy() OVERRIDE;
- virtual void EstablishPeer(int32 stream_id, int player_id) OVERRIDE;
+ virtual StreamTextureProxy* CreateProxy() override;
+ virtual void EstablishPeer(int32 stream_id, int player_id) override;
virtual unsigned CreateStreamTexture(unsigned texture_target,
unsigned* texture_id,
- gpu::Mailbox* texture_mailbox) OVERRIDE;
+ gpu::Mailbox* texture_mailbox) override;
virtual void SetStreamTextureSize(int32 stream_id,
- const gfx::Size& size) OVERRIDE;
- virtual gpu::gles2::GLES2Interface* ContextGL() OVERRIDE;
+ const gfx::Size& size) override;
+ virtual gpu::gles2::GLES2Interface* ContextGL() override;
+ virtual void AddObserver(StreamTextureFactoryContextObserver* obs) override;
+ virtual void RemoveObserver(
+ StreamTextureFactoryContextObserver* obs) override;
private:
friend class base::RefCounted<StreamTextureFactorySynchronousImpl>;
@@ -62,6 +69,7 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
CreateContextProviderCallback create_context_provider_callback_;
scoped_refptr<ContextProvider> context_provider_;
int frame_id_;
+ StreamTextureFactoryContextObserver* observer_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactorySynchronousImpl);
};
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.cc b/chromium/content/renderer/media/android/webmediaplayer_android.cc
index 98335469166..869bab6d066 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.cc
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.cc
@@ -6,39 +6,45 @@
#include <limits>
+#include "base/android/build_info.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/layers/video_layer.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/crypto/key_systems.h"
+#include "content/renderer/media/crypto/render_cdm_factory.h"
#include "content/renderer/media/crypto/renderer_cdm_manager.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
-#include "content/renderer/media/webmediaplayer_delegate.h"
-#include "content/renderer/media/webmediaplayer_util.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
+#include "media/base/android/media_common_android.h"
#include "media/base/android/media_player_android.h"
#include "media/base/bind_to_current_loop.h"
-// TODO(xhwang): Remove when we remove prefixed EME implementation.
#include "media/base/media_keys.h"
+#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/base/video_frame.h"
+#include "media/blink/webmediaplayer_delegate.h"
+#include "media/blink/webmediaplayer_util.h"
#include "net/base/mime_util.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
+#include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -47,18 +53,17 @@
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/image/image.h"
static const uint32 kGLTextureExternalOES = 0x8D65;
+static const int kSDKVersionToSupportSecurityOriginCheck = 20;
using blink::WebMediaPlayer;
using blink::WebSize;
using blink::WebString;
-using blink::WebTimeRanges;
using blink::WebURL;
using gpu::gles2::GLES2Interface;
using media::MediaPlayerAndroid;
@@ -72,12 +77,33 @@ const char* kMediaEme = "Media.EME.";
void OnReleaseTexture(
const scoped_refptr<content::StreamTextureFactory>& factories,
uint32 texture_id,
- const std::vector<uint32>& release_sync_points) {
+ uint32 release_sync_point) {
GLES2Interface* gl = factories->ContextGL();
- for (size_t i = 0; i < release_sync_points.size(); i++)
- gl->WaitSyncPointCHROMIUM(release_sync_points[i]);
+ gl->WaitSyncPointCHROMIUM(release_sync_point);
gl->DeleteTextures(1, &texture_id);
}
+
+class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
+ public:
+ explicit SyncPointClientImpl(
+ blink::WebGraphicsContext3D* web_graphics_context)
+ : web_graphics_context_(web_graphics_context) {}
+ virtual ~SyncPointClientImpl() {}
+ virtual uint32 InsertSyncPoint() override {
+ return web_graphics_context_->insertSyncPoint();
+ }
+ virtual void WaitSyncPoint(uint32 sync_point) override {
+ web_graphics_context_->waitSyncPoint(sync_point);
+ }
+
+ private:
+ blink::WebGraphicsContext3D* web_graphics_context_;
+};
+
+// Used for calls to decryptor_ready_cb_ where the result can be ignored.
+void DoNothing(bool) {
+}
+
} // namespace
namespace content {
@@ -85,18 +111,19 @@ namespace content {
WebMediaPlayerAndroid::WebMediaPlayerAndroid(
blink::WebFrame* frame,
blink::WebMediaPlayerClient* client,
- base::WeakPtr<WebMediaPlayerDelegate> delegate,
+ base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* player_manager,
RendererCdmManager* cdm_manager,
+ blink::WebContentDecryptionModule* initial_cdm,
scoped_refptr<StreamTextureFactory> factory,
- const scoped_refptr<base::MessageLoopProxy>& media_loop,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
media::MediaLog* media_log)
: RenderFrameObserver(RenderFrame::FromWebFrame(frame)),
frame_(frame),
client_(client),
delegate_(delegate),
buffered_(static_cast<size_t>(1)),
- media_loop_(media_loop),
+ media_task_runner_(task_runner),
ignore_metadata_duration_change_(false),
pending_seek_(false),
seeking_(false),
@@ -108,26 +135,29 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
texture_id_(0),
stream_id_(0),
is_playing_(false),
- playing_started_(false),
needs_establish_peer_(true),
- stream_texture_proxy_initialized_(false),
has_size_info_(false),
- has_media_metadata_(false),
- has_media_info_(false),
+ // Compositor thread does not exist in layout tests.
+ compositor_loop_(
+ RenderThreadImpl::current()->compositor_message_loop_proxy().get()
+ ? RenderThreadImpl::current()->compositor_message_loop_proxy()
+ : base::MessageLoopProxy::current()),
stream_texture_factory_(factory),
needs_external_surface_(false),
video_frame_provider_client_(NULL),
- pending_playback_(false),
player_type_(MEDIA_PLAYER_TYPE_URL),
- current_time_(0),
is_remote_(false),
media_log_(media_log),
web_cdm_(NULL),
+ allow_stored_credentials_(false),
+ is_local_resource_(false),
+ interpolator_(&default_tick_clock_),
weak_factory_(this) {
DCHECK(player_manager_);
DCHECK(cdm_manager_);
DCHECK(main_thread_checker_.CalledOnValidThread());
+ stream_texture_factory_->AddObserver(this);
player_id_ = player_manager_->RegisterMediaPlayer(this);
@@ -142,9 +172,18 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
}
#endif // defined(VIDEO_HOLE)
TryCreateStreamTextureProxyIfNeeded();
+ interpolator_.SetUpperBound(base::TimeDelta());
+
+ // Set the initial CDM, if specified.
+ if (initial_cdm) {
+ web_cdm_ = ToWebContentDecryptionModuleImpl(initial_cdm);
+ if (web_cdm_->GetCdmId() != media::MediaKeys::kInvalidCdmId)
+ player_manager_->SetCdm(player_id_, web_cdm_->GetCdmId());
+ }
}
WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
SetVideoFrameProviderClient(NULL);
client_->setWebLayer(NULL);
@@ -166,14 +205,27 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
current_frame_ = NULL;
}
- if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_)
+ if (delegate_)
delegate_->PlayerGone(this);
+
+ stream_texture_factory_->RemoveObserver(this);
+
+ if (media_source_delegate_) {
+ // Part of |media_source_delegate_| needs to be stopped on the media thread.
+ // Wait until |media_source_delegate_| is fully stopped before tearing
+ // down other objects.
+ base::WaitableEvent waiter(false, false);
+ media_source_delegate_->Stop(
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
+ waiter.Wait();
+ }
}
void WebMediaPlayerAndroid::load(LoadType load_type,
const blink::WebURL& url,
CORSMode cors_mode) {
- ReportMediaSchemeUma(GURL(url));
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ media::ReportMediaSchemeUma(GURL(url));
switch (load_type) {
case LoadTypeURL:
@@ -190,19 +242,16 @@ void WebMediaPlayerAndroid::load(LoadType load_type,
return;
}
- has_media_metadata_ = false;
- has_media_info_ = false;
-
+ url_ = url;
+ is_local_resource_ = IsLocalResource();
int demuxer_client_id = 0;
if (player_type_ != MEDIA_PLAYER_TYPE_URL) {
- has_media_info_ = true;
-
RendererDemuxerAndroid* demuxer =
RenderThreadImpl::current()->renderer_demuxer();
demuxer_client_id = demuxer->GetNextDemuxerClientID();
media_source_delegate_.reset(new MediaSourceDelegate(
- demuxer, demuxer_client_id, media_loop_, media_log_));
+ demuxer, demuxer_client_id, media_task_runner_, media_log_));
if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE) {
media::SetDecryptorReadyCB set_decryptor_ready_cb =
@@ -220,6 +269,8 @@ void WebMediaPlayerAndroid::load(LoadType load_type,
weak_factory_.GetWeakPtr()),
base::Bind(&WebMediaPlayerAndroid::OnDurationChanged,
weak_factory_.GetWeakPtr()));
+ InitializePlayer(url_, frame_->document().firstPartyForCookies(),
+ true, demuxer_client_id);
}
} else {
info_loader_.reset(
@@ -228,51 +279,54 @@ void WebMediaPlayerAndroid::load(LoadType load_type,
cors_mode,
base::Bind(&WebMediaPlayerAndroid::DidLoadMediaInfo,
weak_factory_.GetWeakPtr())));
- // TODO(qinmin): The url might be redirected when android media player
- // requests the stream. As a result, we cannot guarantee there is only
- // a single origin. Remove the following line when b/12573548 is fixed.
- // Check http://crbug.com/334204.
- info_loader_->set_single_origin(false);
info_loader_->Start(frame_);
}
- url_ = url;
- GURL first_party_url = frame_->document().firstPartyForCookies();
- player_manager_->Initialize(
- player_type_, player_id_, url, first_party_url, demuxer_client_id,
- frame_->document().url());
-
- if (player_manager_->ShouldEnterFullscreen(frame_))
- player_manager_->EnterFullscreen(player_id_, frame_);
-
UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing);
+ UMA_HISTOGRAM_BOOLEAN(
+ "Media.MSE.Playback", player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE);
}
-void WebMediaPlayerAndroid::DidLoadMediaInfo(MediaInfoLoader::Status status) {
+void WebMediaPlayerAndroid::DidLoadMediaInfo(
+ MediaInfoLoader::Status status,
+ const GURL& redirected_url,
+ const GURL& first_party_for_cookies,
+ bool allow_stored_credentials) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(!media_source_delegate_);
if (status == MediaInfoLoader::kFailed) {
info_loader_.reset();
UpdateNetworkState(WebMediaPlayer::NetworkStateNetworkError);
return;
}
+ redirected_url_ = redirected_url;
+ InitializePlayer(
+ redirected_url, first_party_for_cookies, allow_stored_credentials, 0);
- has_media_info_ = true;
- if (has_media_metadata_ &&
- ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) {
- UpdateReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
- UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
+ UpdateNetworkState(WebMediaPlayer::NetworkStateIdle);
+}
+
+bool WebMediaPlayerAndroid::IsLocalResource() {
+ if (url_.SchemeIsFile() || url_.SchemeIsBlob())
+ return true;
+
+ std::string host = url_.host();
+ if (!host.compare("localhost") || !host.compare("127.0.0.1") ||
+ !host.compare("[::1]")) {
+ return true;
}
- // Android doesn't start fetching resources until an implementation-defined
- // event (e.g. playback request) occurs. Sets the network state to IDLE
- // if play is not requested yet.
- if (!playing_started_)
- UpdateNetworkState(WebMediaPlayer::NetworkStateIdle);
+
+ return false;
}
void WebMediaPlayerAndroid::play() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
+ // For HLS streams, some devices cannot detect the video size unless a surface
+ // texture is bind to it. See http://crbug.com/400145.
#if defined(VIDEO_HOLE)
- if (hasVideo() && needs_external_surface_ &&
+ if ((hasVideo() || IsHLSStream()) && needs_external_surface_ &&
!player_manager_->IsInFullscreen(frame_)) {
DCHECK(!needs_establish_peer_);
player_manager_->RequestExternalSurface(player_id_, last_computed_rect_);
@@ -282,7 +336,7 @@ void WebMediaPlayerAndroid::play() {
TryCreateStreamTextureProxyIfNeeded();
// There is no need to establish the surface texture peer for fullscreen
// video.
- if (hasVideo() && needs_establish_peer_ &&
+ if ((hasVideo() || IsHLSStream()) && needs_establish_peer_ &&
!player_manager_->IsInFullscreen(frame_)) {
EstablishSurfaceTexturePeer();
}
@@ -291,18 +345,26 @@ void WebMediaPlayerAndroid::play() {
player_manager_->Start(player_id_);
UpdatePlayingState(true);
UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
- playing_started_ = true;
}
void WebMediaPlayerAndroid::pause() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
Pause(true);
}
+void WebMediaPlayerAndroid::requestRemotePlayback() {
+ player_manager_->RequestRemotePlayback(player_id_);
+}
+
+void WebMediaPlayerAndroid::requestRemotePlaybackControl() {
+ player_manager_->RequestRemotePlaybackControl(player_id_);
+}
+
void WebMediaPlayerAndroid::seek(double seconds) {
DCHECK(main_thread_checker_.CalledOnValidThread());
DVLOG(1) << __FUNCTION__ << "(" << seconds << ")";
- base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds);
+ base::TimeDelta new_seek_time = media::ConvertSecondsToTimestamp(seconds);
if (seeking_) {
if (new_seek_time == seek_time_) {
@@ -351,10 +413,12 @@ void WebMediaPlayerAndroid::setRate(double rate) {
}
void WebMediaPlayerAndroid::setVolume(double volume) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
player_manager_->SetVolume(player_id_, volume);
}
bool WebMediaPlayerAndroid::hasVideo() const {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
// If we have obtained video size information before, use it.
if (has_size_info_)
return !natural_size_.isEmpty();
@@ -376,6 +440,7 @@ bool WebMediaPlayerAndroid::hasVideo() const {
}
bool WebMediaPlayerAndroid::hasAudio() const {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
if (!url_.has_path())
return false;
std::string mime;
@@ -390,6 +455,10 @@ bool WebMediaPlayerAndroid::hasAudio() const {
return false;
}
+bool WebMediaPlayerAndroid::isRemote() const {
+ return is_remote_;
+}
+
bool WebMediaPlayerAndroid::paused() const {
return !is_playing_;
}
@@ -399,6 +468,7 @@ bool WebMediaPlayerAndroid::seeking() const {
}
double WebMediaPlayerAndroid::duration() const {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
// HTML5 spec requires duration to be NaN if readyState is HAVE_NOTHING
if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
return std::numeric_limits<double>::quiet_NaN();
@@ -410,6 +480,7 @@ double WebMediaPlayerAndroid::duration() const {
}
double WebMediaPlayerAndroid::timelineOffset() const {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
base::Time timeline_offset;
if (media_source_delegate_)
timeline_offset = media_source_delegate_->GetTimelineOffset();
@@ -421,6 +492,7 @@ double WebMediaPlayerAndroid::timelineOffset() const {
}
double WebMediaPlayerAndroid::currentTime() const {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
// If the player is processing a seek, return the seek time.
// Blink may still query us if updatePlaybackState() occurs while seeking.
if (seeking()) {
@@ -428,7 +500,9 @@ double WebMediaPlayerAndroid::currentTime() const {
pending_seek_time_.InSecondsF() : seek_time_.InSecondsF();
}
- return current_time_;
+ return std::min(
+ (const_cast<media::TimeDeltaInterpolator*>(
+ &interpolator_))->GetInterpolatedTime(), duration_).InSecondsF();
}
WebSize WebMediaPlayerAndroid::naturalSize() const {
@@ -443,19 +517,21 @@ WebMediaPlayer::ReadyState WebMediaPlayerAndroid::readyState() const {
return ready_state_;
}
-WebTimeRanges WebMediaPlayerAndroid::buffered() const {
+blink::WebTimeRanges WebMediaPlayerAndroid::buffered() const {
if (media_source_delegate_)
return media_source_delegate_->Buffered();
return buffered_;
}
-double WebMediaPlayerAndroid::maxTimeSeekable() const {
- // If we haven't even gotten to ReadyStateHaveMetadata yet then just
- // return 0 so that the seekable range is empty.
+blink::WebTimeRanges WebMediaPlayerAndroid::seekable() const {
if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
- return 0.0;
+ return blink::WebTimeRanges();
- return duration();
+ // TODO(dalecurtis): Technically this allows seeking on media which return an
+ // infinite duration. While not expected, disabling this breaks semi-live
+ // players, http://crbug.com/427412.
+ const blink::WebTimeRange seekable_range(0.0, duration());
+ return blink::WebTimeRanges(&seekable_range, 1);
}
bool WebMediaPlayerAndroid::didLoadingProgress() {
@@ -464,10 +540,83 @@ bool WebMediaPlayerAndroid::didLoadingProgress() {
return ret;
}
+bool WebMediaPlayerAndroid::EnsureTextureBackedSkBitmap(GrContext* gr,
+ SkBitmap& bitmap,
+ const WebSize& size,
+ GrSurfaceOrigin origin,
+ GrPixelConfig config) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ if (!bitmap.getTexture() || bitmap.width() != size.width
+ || bitmap.height() != size.height) {
+ if (!gr)
+ return false;
+ GrTextureDesc desc;
+ desc.fConfig = config;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
+ desc.fSampleCnt = 0;
+ desc.fOrigin = origin;
+ desc.fWidth = size.width;
+ desc.fHeight = size.height;
+ skia::RefPtr<GrTexture> texture;
+ texture = skia::AdoptRef(gr->createUncachedTexture(desc, 0, 0));
+ if (!texture.get())
+ return false;
+
+ SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight);
+ SkGrPixelRef* pixelRef = SkNEW_ARGS(SkGrPixelRef, (info, texture.get()));
+ if (!pixelRef)
+ return false;
+ bitmap.setInfo(info);
+ bitmap.setPixelRef(pixelRef)->unref();
+ }
+
+ return true;
+}
+
void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
const blink::WebRect& rect,
- unsigned char alpha) {
- NOTIMPLEMENTED();
+ unsigned char alpha,
+ SkXfermode::Mode mode) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ scoped_ptr<blink::WebGraphicsContext3DProvider> provider =
+ scoped_ptr<blink::WebGraphicsContext3DProvider>(blink::Platform::current(
+ )->createSharedOffscreenGraphicsContext3DProvider());
+ if (!provider)
+ return;
+ blink::WebGraphicsContext3D* context3D = provider->context3d();
+ if (!context3D)
+ return;
+
+ // Copy video texture into a RGBA texture based bitmap first as video texture
+ // on Android is GL_TEXTURE_EXTERNAL_OES which is not supported by Skia yet.
+ // The bitmap's size needs to be the same as the video and use naturalSize()
+ // here. Check if we could reuse existing texture based bitmap.
+ // Otherwise, release existing texture based bitmap and allocate
+ // a new one based on video size.
+ if (!EnsureTextureBackedSkBitmap(provider->grContext(), bitmap_,
+ naturalSize(), kTopLeft_GrSurfaceOrigin, kSkia8888_GrPixelConfig)) {
+ return;
+ }
+
+ unsigned textureId = static_cast<unsigned>(
+ (bitmap_.getTexture())->getTextureHandle());
+ if (!copyVideoTextureToPlatformTexture(context3D, textureId, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, true, false)) {
+ return;
+ }
+
+ // Draw the texture based bitmap onto the Canvas. If the canvas is
+ // hardware based, this will do a GPU-GPU texture copy.
+ // If the canvas is software based, the texture based bitmap will be
+ // readbacked to system memory then draw onto the canvas.
+ SkRect dest;
+ dest.set(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
+ SkPaint paint;
+ paint.setAlpha(alpha);
+ paint.setXfermodeMode(mode);
+ // It is not necessary to pass the dest into the drawBitmap call since all
+ // the context have been set up before calling paintCurrentFrameInContext.
+ canvas->drawBitmapRect(bitmap_, 0, dest, &paint);
}
bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
@@ -478,6 +627,7 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
unsigned int type,
bool premultiply_alpha,
bool flip_y) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
// Don't allow clients to copy an encrypted video frame.
if (needs_external_surface_)
return false;
@@ -488,7 +638,7 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
video_frame = current_frame_;
}
- if (!video_frame ||
+ if (!video_frame.get() ||
video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
return false;
const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
@@ -496,25 +646,12 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) ||
(is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D));
- // For hidden video element (with style "display:none"), ensure the texture
- // size is set.
- if (!is_remote_ &&
- (cached_stream_texture_size_.width != natural_size_.width ||
- cached_stream_texture_size_.height != natural_size_.height)) {
- stream_texture_factory_->SetStreamTextureSize(
- stream_id_, gfx::Size(natural_size_.width, natural_size_.height));
- cached_stream_texture_size_ = natural_size_;
- }
-
- uint32 source_texture = web_graphics_context->createTexture();
web_graphics_context->waitSyncPoint(mailbox_holder->sync_point);
// Ensure the target of texture is set before copyTextureCHROMIUM, otherwise
// an invalid texture target may be used for copy texture.
- web_graphics_context->bindTexture(mailbox_holder->texture_target,
- source_texture);
- web_graphics_context->consumeTextureCHROMIUM(mailbox_holder->texture_target,
- mailbox_holder->mailbox.name);
+ uint32 src_texture = web_graphics_context->createAndConsumeTextureCHROMIUM(
+ mailbox_holder->texture_target, mailbox_holder->mailbox.name);
// The video is stored in an unmultiplied format, so premultiply if
// necessary.
@@ -526,40 +663,51 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
// flip_y==true means to reverse the video orientation while
// flip_y==false means to keep the intrinsic orientation.
web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
- web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D, source_texture,
+ web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D, src_texture,
texture, level, internal_format,
type);
web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
false);
- if (mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES)
- web_graphics_context->bindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
- else
- web_graphics_context->bindTexture(GL_TEXTURE_2D, texture);
- web_graphics_context->deleteTexture(source_texture);
+ web_graphics_context->deleteTexture(src_texture);
web_graphics_context->flush();
- video_frame->AppendReleaseSyncPoint(web_graphics_context->insertSyncPoint());
+
+ SyncPointClientImpl client(web_graphics_context);
+ video_frame->UpdateReleaseSyncPoint(&client);
return true;
}
bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
- if (info_loader_)
- return info_loader_->HasSingleOrigin();
- // The info loader may have failed.
- if (player_type_ == MEDIA_PLAYER_TYPE_URL)
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ if (player_type_ != MEDIA_PLAYER_TYPE_URL)
+ return true;
+
+ if (!info_loader_ || !info_loader_->HasSingleOrigin())
return false;
- return true;
+
+ // TODO(qinmin): The url might be redirected when android media player
+ // requests the stream. As a result, we cannot guarantee there is only
+ // a single origin. Only if the HTTP request was made without credentials,
+ // we will honor the return value from HasSingleSecurityOriginInternal()
+ // in pre-L android versions.
+ // Check http://crbug.com/334204.
+ if (!allow_stored_credentials_)
+ return true;
+
+ return base::android::BuildInfo::GetInstance()->sdk_int() >=
+ kSDKVersionToSupportSecurityOriginCheck;
}
bool WebMediaPlayerAndroid::didPassCORSAccessCheck() const {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
if (info_loader_)
return info_loader_->DidPassCORSAccessCheck();
return false;
}
double WebMediaPlayerAndroid::mediaTimeForTimeValue(double timeValue) const {
- return ConvertSecondsToTimestamp(timeValue).InSecondsF();
+ return media::ConvertSecondsToTimestamp(timeValue).InSecondsF();
}
unsigned WebMediaPlayerAndroid::decodedFrameCount() const {
@@ -592,16 +740,18 @@ unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const {
void WebMediaPlayerAndroid::OnMediaMetadataChanged(
const base::TimeDelta& duration, int width, int height, bool success) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
bool need_to_signal_duration_changed = false;
- if (url_.SchemeIs("file"))
+ if (is_local_resource_)
UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded);
// Update duration, if necessary, prior to ready state updates that may
// cause duration() query.
if (!ignore_metadata_duration_change_ && duration_ != duration) {
duration_ = duration;
-
+ if (is_local_resource_)
+ buffered_[0].end = duration_.InSecondsF();
// Client readyState transition from HAVE_NOTHING to HAVE_METADATA
// already triggers a durationchanged event. If this is a different
// transition, remember to signal durationchanged.
@@ -613,9 +763,7 @@ void WebMediaPlayerAndroid::OnMediaMetadataChanged(
}
}
- has_media_metadata_ = true;
- if (has_media_info_ &&
- ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) {
+ if (ready_state_ != WebMediaPlayer::ReadyStateHaveEnoughData) {
UpdateReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
}
@@ -634,17 +782,14 @@ void WebMediaPlayerAndroid::OnPlaybackComplete() {
// at a time which is smaller than the duration. This makes webkit never
// know that the playback has finished. To solve this, we set the
// current time to media duration when OnPlaybackComplete() get called.
- OnTimeUpdate(duration_);
+ interpolator_.SetBounds(duration_, duration_);
client_->timeChanged();
- // if the loop attribute is set, timeChanged() will update the current time
- // to 0. It will perform a seek to 0. As the requests to the renderer
- // process are sequential, the OnSeekComplete() will only occur
- // once OnPlaybackComplete() is done. As the playback can only be executed
- // upon completion of OnSeekComplete(), the request needs to be saved.
- is_playing_ = false;
+ // If the loop attribute is set, timeChanged() will update the current time
+ // to 0. It will perform a seek to 0. Issue a command to the player to start
+ // playing after seek completes.
if (seeking_ && seek_time_ == base::TimeDelta())
- pending_playback_ = true;
+ player_manager_->Start(player_id_);
}
void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
@@ -666,17 +811,11 @@ void WebMediaPlayerAndroid::OnSeekComplete(
seek(pending_seek_time_.InSecondsF());
return;
}
-
- OnTimeUpdate(current_time);
+ interpolator_.SetBounds(current_time, current_time);
UpdateReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
client_->timeChanged();
-
- if (pending_playback_) {
- play();
- pending_playback_ = false;
- }
}
void WebMediaPlayerAndroid::OnMediaError(int error_type) {
@@ -697,6 +836,7 @@ void WebMediaPlayerAndroid::OnMediaError(int error_type) {
}
void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
has_size_info_ = true;
if (natural_size_.width == width && natural_size_.height == height)
return;
@@ -716,6 +856,9 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
SetNeedsEstablishPeer(true);
}
#endif // defined(VIDEO_HOLE)
+ natural_size_.width = width;
+ natural_size_.height = height;
+
// When play() gets called, |natural_size_| may still be empty and
// EstablishSurfaceTexturePeer() will not get called. As a result, the video
// may play without a surface texture. When we finally get the valid video
@@ -724,13 +867,20 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
if (!paused() && needs_establish_peer_)
EstablishSurfaceTexturePeer();
- natural_size_.width = width;
- natural_size_.height = height;
ReallocateVideoFrame();
+ // For hidden video element (with style "display:none"), ensure the texture
+ // size is set.
+ if (!is_remote_ && cached_stream_texture_size_ != natural_size_) {
+ stream_texture_factory_->SetStreamTextureSize(
+ stream_id_, gfx::Size(natural_size_.width, natural_size_.height));
+ cached_stream_texture_size_ = natural_size_;
+ }
+
// Lazily allocate compositing layer.
if (!video_weblayer_) {
- video_weblayer_.reset(new WebLayerImpl(cc::VideoLayer::Create(this)));
+ video_weblayer_.reset(new cc_blink::WebLayerImpl(
+ cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0)));
client_->setWebLayer(video_weblayer_.get());
}
@@ -740,9 +890,24 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
client_->timeChanged();
}
-void WebMediaPlayerAndroid::OnTimeUpdate(const base::TimeDelta& current_time) {
+void WebMediaPlayerAndroid::OnTimeUpdate(base::TimeDelta current_timestamp,
+ base::TimeTicks current_time_ticks) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- current_time_ = current_time.InSecondsF();
+ // Compensate the current_timestamp with the IPC latency.
+ base::TimeDelta lower_bound =
+ base::TimeTicks::Now() - current_time_ticks + current_timestamp;
+ base::TimeDelta upper_bound = lower_bound;
+ // We should get another time update in about |kTimeUpdateInterval|
+ // milliseconds.
+ if (is_playing_) {
+ upper_bound += base::TimeDelta::FromMilliseconds(
+ media::kTimeUpdateInterval);
+ }
+ // if the lower_bound is smaller than the current time, just use the current
+ // time so that the timer is always progressing.
+ lower_bound =
+ std::min(lower_bound, base::TimeDelta::FromSecondsD(currentTime()));
+ interpolator_.SetBounds(lower_bound, upper_bound);
}
void WebMediaPlayerAndroid::OnConnectedToRemoteDevice(
@@ -752,6 +917,7 @@ void WebMediaPlayerAndroid::OnConnectedToRemoteDevice(
DrawRemotePlaybackText(remote_playback_message);
is_remote_ = true;
SetNeedsEstablishPeer(false);
+ client_->connectedToRemoteDevice();
}
void WebMediaPlayerAndroid::OnDisconnectedFromRemoteDevice() {
@@ -762,14 +928,12 @@ void WebMediaPlayerAndroid::OnDisconnectedFromRemoteDevice() {
EstablishSurfaceTexturePeer();
is_remote_ = false;
ReallocateVideoFrame();
+ client_->disconnectedFromRemoteDevice();
}
void WebMediaPlayerAndroid::OnDidEnterFullscreen() {
- if (!player_manager_->IsInFullscreen(frame_)) {
- frame_->view()->willEnterFullScreen();
- frame_->view()->didEnterFullScreen();
+ if (!player_manager_->IsInFullscreen(frame_))
player_manager_->DidEnterFullscreen(frame_);
- }
}
void WebMediaPlayerAndroid::OnDidExitFullscreen() {
@@ -786,8 +950,6 @@ void WebMediaPlayerAndroid::OnDidExitFullscreen() {
player_manager_->RequestExternalSurface(player_id_, last_computed_rect_);
#endif // defined(VIDEO_HOLE)
- frame_->view()->willExitFullScreen();
- frame_->view()->didExitFullScreen();
player_manager_->DidExitFullscreen();
client_->repaint();
}
@@ -806,6 +968,11 @@ void WebMediaPlayerAndroid::OnRequestFullscreen() {
client_->requestFullscreen();
}
+void WebMediaPlayerAndroid::OnRemoteRouteAvailabilityChanged(
+ bool routes_available) {
+ client_->remoteRouteAvailabilityChanged(routes_available);
+}
+
void WebMediaPlayerAndroid::OnDurationChanged(const base::TimeDelta& duration) {
DCHECK(main_thread_checker_.CalledOnValidThread());
// Only MSE |player_type_| registers this callback.
@@ -875,7 +1042,8 @@ void WebMediaPlayerAndroid::ReleaseMediaResources() {
break;
}
player_manager_->ReleaseResources(player_id_);
- OnPlayerReleased();
+ if (!needs_external_surface_)
+ SetNeedsEstablishPeer(true);
}
void WebMediaPlayerAndroid::OnDestruct() {
@@ -884,6 +1052,23 @@ void WebMediaPlayerAndroid::OnDestruct() {
"the RenderFrame goes away.";
}
+void WebMediaPlayerAndroid::InitializePlayer(
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ bool allow_stored_credentials,
+ int demuxer_client_id) {
+ if (player_type_ == MEDIA_PLAYER_TYPE_URL) {
+ UMA_HISTOGRAM_BOOLEAN("Media.Android.IsHttpLiveStreamingMedia",
+ IsHLSStream());
+ }
+ allow_stored_credentials_ = allow_stored_credentials;
+ player_manager_->Initialize(
+ player_type_, player_id_, url, first_party_for_cookies, demuxer_client_id,
+ frame_->document().url(), allow_stored_credentials);
+ if (player_manager_->ShouldEnterFullscreen(frame_))
+ player_manager_->EnterFullscreen(player_id_, frame_);
+}
+
void WebMediaPlayerAndroid::Pause(bool is_media_related_action) {
player_manager_->Pause(player_id_, is_media_related_action);
UpdatePlayingState(false);
@@ -891,7 +1076,6 @@ void WebMediaPlayerAndroid::Pause(bool is_media_related_action) {
void WebMediaPlayerAndroid::DrawRemotePlaybackText(
const std::string& remote_playback_message) {
-
DCHECK(main_thread_checker_.CalledOnValidThread());
if (!video_weblayer_)
return;
@@ -908,9 +1092,7 @@ void WebMediaPlayerAndroid::DrawRemotePlaybackText(
static_cast<int>(video_size_css_px.height() * device_scale_factor));
SkBitmap bitmap;
- bitmap.setConfig(
- SkBitmap::kARGB_8888_Config, canvas_size.width(), canvas_size.height());
- bitmap.allocPixels();
+ bitmap.allocN32Pixels(canvas_size.width(), canvas_size.height());
// Create the canvas and draw the "Casting to <Chromecast>" text on it.
SkCanvas canvas(bitmap);
@@ -1015,6 +1197,7 @@ void WebMediaPlayerAndroid::DrawRemotePlaybackText(
}
void WebMediaPlayerAndroid::ReallocateVideoFrame() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
if (needs_external_surface_) {
// VideoFrame::CreateHoleFrame is only defined under VIDEO_HOLE.
#if defined(VIDEO_HOLE)
@@ -1030,11 +1213,9 @@ void WebMediaPlayerAndroid::ReallocateVideoFrame() {
#endif // defined(VIDEO_HOLE)
} else if (!is_remote_ && texture_id_) {
GLES2Interface* gl = stream_texture_factory_->ContextGL();
- GLuint texture_id_ref = 0;
- gl->GenTextures(1, &texture_id_ref);
GLuint texture_target = kGLTextureExternalOES;
- gl->BindTexture(texture_target, texture_id_ref);
- gl->ConsumeTextureCHROMIUM(texture_target, texture_mailbox_.name);
+ GLuint texture_id_ref = gl->CreateAndConsumeTextureCHROMIUM(
+ texture_target, texture_mailbox_.name);
gl->Flush();
GLuint texture_mailbox_sync_point = gl->InsertSyncPointCHROMIUM();
@@ -1056,17 +1237,20 @@ void WebMediaPlayerAndroid::SetVideoFrameProviderClient(
cc::VideoFrameProvider::Client* client) {
// This is called from both the main renderer thread and the compositor
// thread (when the main thread is blocked).
- if (video_frame_provider_client_)
- video_frame_provider_client_->StopUsingProvider();
- video_frame_provider_client_ = client;
- // Set the callback target when a frame is produced.
+ // Set the callback target when a frame is produced. Need to do this before
+ // StopUsingProvider to ensure we really stop using the client.
if (stream_texture_proxy_)
- stream_texture_proxy_->SetClient(client);
+ stream_texture_proxy_->BindToLoop(stream_id_, client, compositor_loop_);
+
+ if (video_frame_provider_client_ && video_frame_provider_client_ != client)
+ video_frame_provider_client_->StopUsingProvider();
+ video_frame_provider_client_ = client;
}
void WebMediaPlayerAndroid::SetCurrentFrameInternal(
scoped_refptr<media::VideoFrame>& video_frame) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(current_frame_lock_);
current_frame_ = video_frame;
}
@@ -1078,16 +1262,6 @@ scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() {
video_frame = current_frame_;
}
- if (!stream_texture_proxy_initialized_ && stream_texture_proxy_ &&
- stream_id_ && !needs_external_surface_ && !is_remote_) {
- gfx::Size natural_size = video_frame->natural_size();
- // TODO(sievers): These variables are accessed on the wrong thread here.
- stream_texture_proxy_->BindToCurrentThread(stream_id_);
- stream_texture_factory_->SetStreamTextureSize(stream_id_, natural_size);
- stream_texture_proxy_initialized_ = true;
- cached_stream_texture_size_ = natural_size;
- }
-
return video_frame;
}
@@ -1095,35 +1269,71 @@ void WebMediaPlayerAndroid::PutCurrentFrame(
const scoped_refptr<media::VideoFrame>& frame) {
}
+void WebMediaPlayerAndroid::ResetStreamTextureProxy() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
+ if (stream_id_) {
+ GLES2Interface* gl = stream_texture_factory_->ContextGL();
+ gl->DeleteTextures(1, &texture_id_);
+ texture_id_ = 0;
+ texture_mailbox_ = gpu::Mailbox();
+ stream_id_ = 0;
+ }
+ stream_texture_proxy_.reset();
+ needs_establish_peer_ = !needs_external_surface_ && !is_remote_ &&
+ !player_manager_->IsInFullscreen(frame_) &&
+ (hasVideo() || IsHLSStream());
+
+ TryCreateStreamTextureProxyIfNeeded();
+ if (needs_establish_peer_ && is_playing_)
+ EstablishSurfaceTexturePeer();
+}
+
void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
// Already created.
if (stream_texture_proxy_)
return;
// No factory to create proxy.
- if (!stream_texture_factory_)
+ if (!stream_texture_factory_.get())
+ return;
+
+ // Not needed for hole punching.
+ if (!needs_establish_peer_)
return;
stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy());
- if (needs_establish_peer_ && stream_texture_proxy_) {
+ if (stream_texture_proxy_) {
DoCreateStreamTexture();
ReallocateVideoFrame();
+ if (video_frame_provider_client_) {
+ stream_texture_proxy_->BindToLoop(
+ stream_id_, video_frame_provider_client_, compositor_loop_);
+ }
}
-
- if (stream_texture_proxy_ && video_frame_provider_client_)
- stream_texture_proxy_->SetClient(video_frame_provider_client_);
}
void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
if (!stream_texture_proxy_)
return;
if (stream_texture_factory_.get() && stream_id_)
stream_texture_factory_->EstablishPeer(stream_id_, player_id_);
+
+ // Set the deferred size because the size was changed in remote mode.
+ if (!is_remote_ && cached_stream_texture_size_ != natural_size_) {
+ stream_texture_factory_->SetStreamTextureSize(
+ stream_id_, gfx::Size(natural_size_.width, natural_size_.height));
+ cached_stream_texture_size_ = natural_size_;
+ }
+
needs_establish_peer_ = false;
}
void WebMediaPlayerAndroid::DoCreateStreamTexture() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(!stream_id_);
DCHECK(!texture_id_);
stream_id_ = stream_texture_factory_->CreateStreamTexture(
@@ -1139,13 +1349,22 @@ void WebMediaPlayerAndroid::setPoster(const blink::WebURL& poster) {
}
void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
- is_playing_ = is_playing;
- if (!delegate_)
+ if (is_playing == is_playing_)
return;
+
+ is_playing_ = is_playing;
+
if (is_playing)
- delegate_->DidPlay(this);
+ interpolator_.StartInterpolating();
else
- delegate_->DidPause(this);
+ interpolator_.StopInterpolating();
+
+ if (delegate_) {
+ if (is_playing)
+ delegate_->DidPlay(this);
+ else
+ delegate_->DidPause(this);
+ }
}
#if defined(VIDEO_HOLE)
@@ -1273,11 +1492,11 @@ WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::generateKeyRequest(
// so we keep it as simple as possible without breaking major use cases.
static std::string GuessInitDataType(const unsigned char* init_data,
unsigned init_data_length) {
- // Most WebM files use KeyId of 16 bytes. MP4 init data are always >16 bytes.
+ // Most WebM files use KeyId of 16 bytes. CENC init data is always >16 bytes.
if (init_data_length == 16)
- return "video/webm";
+ return "webm";
- return "video/mp4";
+ return "cenc";
}
// TODO(xhwang): Report an error when there is encrypted stream but EME is
@@ -1295,7 +1514,6 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal(
if (current_key_system_.empty()) {
if (!proxy_decryptor_) {
proxy_decryptor_.reset(new ProxyDecryptor(
- cdm_manager_,
base::Bind(&WebMediaPlayerAndroid::OnKeyAdded,
weak_factory_.GetWeakPtr()),
base::Bind(&WebMediaPlayerAndroid::OnKeyError,
@@ -1305,17 +1523,20 @@ WebMediaPlayerAndroid::GenerateKeyRequestInternal(
}
GURL security_origin(frame_->document().securityOrigin().toString());
- if (!proxy_decryptor_->InitializeCDM(key_system, security_origin))
+ RenderCdmFactory cdm_factory(cdm_manager_);
+ if (!proxy_decryptor_->InitializeCDM(&cdm_factory, key_system,
+ security_origin)) {
return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
+ }
if (!decryptor_ready_cb_.is_null()) {
base::ResetAndReturn(&decryptor_ready_cb_)
- .Run(proxy_decryptor_->GetDecryptor());
+ .Run(proxy_decryptor_->GetDecryptor(), base::Bind(DoNothing));
}
// Only browser CDMs have CDM ID. Render side CDMs (e.g. ClearKey CDM) do
// not have a CDM ID and there is no need to call player_manager_->SetCdm().
- if (proxy_decryptor_->GetCdmId() != RendererCdmManager::kInvalidCdmId)
+ if (proxy_decryptor_->GetCdmId() != media::MediaKeys::kInvalidCdmId)
player_manager_->SetCdm(player_id_, proxy_decryptor_->GetCdmId());
current_key_system_ = key_system;
@@ -1429,13 +1650,63 @@ void WebMediaPlayerAndroid::setContentDecryptionModule(
if (!web_cdm_)
return;
- if (!decryptor_ready_cb_.is_null())
- base::ResetAndReturn(&decryptor_ready_cb_).Run(web_cdm_->GetDecryptor());
+ if (!decryptor_ready_cb_.is_null()) {
+ base::ResetAndReturn(&decryptor_ready_cb_)
+ .Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing));
+ }
- if (web_cdm_->GetCdmId() != RendererCdmManager::kInvalidCdmId)
+ if (web_cdm_->GetCdmId() != media::MediaKeys::kInvalidCdmId)
player_manager_->SetCdm(player_id_, web_cdm_->GetCdmId());
}
+void WebMediaPlayerAndroid::setContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm,
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+
+ // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
+ if (!cdm) {
+ result.completeWithError(
+ blink::WebContentDecryptionModuleExceptionNotSupportedError,
+ 0,
+ "Null MediaKeys object is not supported.");
+ return;
+ }
+
+ web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
+ DCHECK(web_cdm_);
+
+ if (!decryptor_ready_cb_.is_null()) {
+ base::ResetAndReturn(&decryptor_ready_cb_).Run(
+ web_cdm_->GetDecryptor(),
+ media::BindToCurrentLoop(
+ base::Bind(&WebMediaPlayerAndroid::ContentDecryptionModuleAttached,
+ weak_factory_.GetWeakPtr(),
+ result)));
+ } else {
+ // No pipeline/decoder connected, so resolve the promise. When something
+ // is connected, setting the CDM will happen in SetDecryptorReadyCB().
+ ContentDecryptionModuleAttached(result, true);
+ }
+
+ if (web_cdm_->GetCdmId() != media::MediaKeys::kInvalidCdmId)
+ player_manager_->SetCdm(player_id_, web_cdm_->GetCdmId());
+}
+
+void WebMediaPlayerAndroid::ContentDecryptionModuleAttached(
+ blink::WebContentDecryptionModuleResult result,
+ bool success) {
+ if (success) {
+ result.complete();
+ return;
+ }
+
+ result.completeWithError(
+ blink::WebContentDecryptionModuleExceptionNotSupportedError,
+ 0,
+ "Unable to set MediaKeys object");
+}
+
void WebMediaPlayerAndroid::OnKeyAdded(const std::string& session_id) {
EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
@@ -1500,7 +1771,7 @@ void WebMediaPlayerAndroid::OnNeedKey(const std::string& type,
init_data_type_ = type;
const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
- client_->keyNeeded(
+ client_->encrypted(
WebString::fromUTF8(type), init_data_ptr, init_data.size());
}
@@ -1510,8 +1781,10 @@ void WebMediaPlayerAndroid::SetDecryptorReadyCB(
// Cancels the previous decryptor request.
if (decryptor_ready_cb.is_null()) {
- if (!decryptor_ready_cb_.is_null())
- base::ResetAndReturn(&decryptor_ready_cb_).Run(NULL);
+ if (!decryptor_ready_cb_.is_null()) {
+ base::ResetAndReturn(&decryptor_ready_cb_)
+ .Run(NULL, base::Bind(DoNothing));
+ }
return;
}
@@ -1526,12 +1799,13 @@ void WebMediaPlayerAndroid::SetDecryptorReadyCB(
DCHECK(!proxy_decryptor_ || !web_cdm_);
if (proxy_decryptor_) {
- decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor());
+ decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor(),
+ base::Bind(DoNothing));
return;
}
if (web_cdm_) {
- decryptor_ready_cb.Run(web_cdm_->GetDecryptor());
+ decryptor_ready_cb.Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing));
return;
}
@@ -1545,12 +1819,16 @@ void WebMediaPlayerAndroid::enterFullscreen() {
}
}
-void WebMediaPlayerAndroid::exitFullscreen() {
- player_manager_->ExitFullscreen(player_id_);
-}
-
bool WebMediaPlayerAndroid::canEnterFullscreen() const {
return player_manager_->CanEnterFullscreen(frame_);
}
+bool WebMediaPlayerAndroid::IsHLSStream() const {
+ std::string mime;
+ GURL url = redirected_url_.is_empty() ? url_ : redirected_url_;
+ if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime))
+ return false;
+ return !mime.compare("application/x-mpegurl");
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.h b/chromium/content/renderer/media/android/webmediaplayer_android.h
index 67d09e06708..83db690471d 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.h
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.h
@@ -13,6 +13,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/layers/video_frame_provider.h"
#include "content/common/media/media_player_messages_enums_android.h"
@@ -25,36 +27,44 @@
#include "media/base/android/media_player_android.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_keys.h"
+#include "media/base/time_delta_interpolator.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/SkGrPixelRef.h"
#include "ui/gfx/rect_f.h"
namespace base {
-class MessageLoopProxy;
+class SingleThreadTaskRunner;
}
namespace blink {
class WebContentDecryptionModule;
+class WebContentDecryptionModuleResult;
class WebFrame;
class WebURL;
}
+namespace cc_blink {
+class WebLayerImpl;
+}
+
namespace gpu {
struct MailboxHolder;
}
namespace media {
class MediaLog;
+class WebMediaPlayerDelegate;
}
namespace content {
class RendererCdmManager;
class RendererMediaPlayerManager;
class WebContentDecryptionModuleImpl;
-class WebLayerImpl;
-class WebMediaPlayerDelegate;
// This class implements blink::WebMediaPlayer by keeping the android
// media player in the browser process. It listens to all the status changes
@@ -62,7 +72,8 @@ class WebMediaPlayerDelegate;
// player.
class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
public cc::VideoFrameProvider,
- public RenderFrameObserver {
+ public RenderFrameObserver,
+ public StreamTextureFactoryContextObserver {
public:
// Construct a WebMediaPlayerAndroid object. This class communicates with the
// MediaPlayerAndroid object in the browser process through |proxy|.
@@ -70,19 +81,20 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// player can enter fullscreen. This logic should probably be moved into
// blink, so that enterFullscreen() will not be called if another video is
// already in fullscreen.
- WebMediaPlayerAndroid(blink::WebFrame* frame,
- blink::WebMediaPlayerClient* client,
- base::WeakPtr<WebMediaPlayerDelegate> delegate,
- RendererMediaPlayerManager* player_manager,
- RendererCdmManager* cdm_manager,
- scoped_refptr<StreamTextureFactory> factory,
- const scoped_refptr<base::MessageLoopProxy>& media_loop,
- media::MediaLog* media_log);
+ WebMediaPlayerAndroid(
+ blink::WebFrame* frame,
+ blink::WebMediaPlayerClient* client,
+ base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
+ RendererMediaPlayerManager* player_manager,
+ RendererCdmManager* cdm_manager,
+ blink::WebContentDecryptionModule* initial_cdm,
+ scoped_refptr<StreamTextureFactory> factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ media::MediaLog* media_log);
virtual ~WebMediaPlayerAndroid();
// blink::WebMediaPlayer implementation.
virtual void enterFullscreen();
- virtual void exitFullscreen();
virtual bool canEnterFullscreen() const;
// Resource loading.
@@ -97,16 +109,23 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
virtual bool supportsSave() const;
virtual void setRate(double rate);
virtual void setVolume(double volume);
+ virtual void requestRemotePlayback();
+ virtual void requestRemotePlaybackControl();
virtual blink::WebTimeRanges buffered() const;
- virtual double maxTimeSeekable() const;
+ virtual blink::WebTimeRanges seekable() const;
// Poster image, as defined in the <video> element.
- virtual void setPoster(const blink::WebURL& poster) OVERRIDE;
+ virtual void setPoster(const blink::WebURL& poster) override;
// Methods for painting.
+ // FIXME: This path "only works" on Android. It is a workaround for the
+ // issue that Skia could not handle Android's GL_TEXTURE_EXTERNAL_OES texture
+ // internally. It should be removed and replaced by the normal paint path.
+ // https://code.google.com/p/skia/issues/detail?id=1189
virtual void paint(blink::WebCanvas* canvas,
const blink::WebRect& rect,
- unsigned char alpha);
+ unsigned char alpha,
+ SkXfermode::Mode mode);
virtual bool copyVideoTextureToPlatformTexture(
blink::WebGraphicsContext3D* web_graphics_context,
@@ -121,6 +140,8 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
virtual bool hasVideo() const;
virtual bool hasAudio() const;
+ virtual bool isRemote() const;
+
// Dimensions of the video.
virtual blink::WebSize naturalSize() const;
@@ -151,10 +172,10 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// cc::VideoFrameProvider implementation. These methods are running on the
// compositor thread.
virtual void SetVideoFrameProviderClient(
- cc::VideoFrameProvider::Client* client) OVERRIDE;
- virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
+ cc::VideoFrameProvider::Client* client) override;
+ virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() override;
virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
- OVERRIDE;
+ override;
// Media player callback handlers.
void OnMediaMetadataChanged(const base::TimeDelta& duration, int width,
@@ -168,7 +189,8 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
void OnDurationChanged(const base::TimeDelta& duration);
// Called to update the current time.
- void OnTimeUpdate(const base::TimeDelta& current_time);
+ void OnTimeUpdate(base::TimeDelta current_timestamp,
+ base::TimeTicks current_time_ticks);
// Functions called when media player status changes.
void OnConnectedToRemoteDevice(const std::string& remote_playback_message);
@@ -178,6 +200,10 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
void OnMediaPlayerPlay();
void OnMediaPlayerPause();
void OnRequestFullscreen();
+ void OnRemoteRouteAvailabilityChanged(bool routes_available);
+
+ // StreamTextureFactoryContextObserver implementation.
+ virtual void ResetStreamTextureProxy() override;
// Called when the player is released.
virtual void OnPlayerReleased();
@@ -188,7 +214,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
virtual void ReleaseMediaResources();
// RenderFrameObserver implementation.
- virtual void OnDestruct() OVERRIDE;
+ virtual void OnDestruct() override;
#if defined(VIDEO_HOLE)
// Calculate the boundary rectangle of the media player (i.e. location and
@@ -213,8 +239,13 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
virtual MediaKeyException cancelKeyRequest(
const blink::WebString& key_system,
const blink::WebString& session_id);
+ // TODO(jrummell): Remove this method once Blink updated to use the other
+ // two methods.
virtual void setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm);
+ virtual void setContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm,
+ blink::WebContentDecryptionModuleResult result);
void OnKeyAdded(const std::string& session_id);
void OnKeyError(const std::string& session_id,
@@ -250,12 +281,20 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
void SetNeedsEstablishPeer(bool needs_establish_peer);
private:
+ void InitializePlayer(const GURL& url,
+ const GURL& first_party_for_cookies,
+ bool allowed_stored_credentials,
+ int demuxer_client_id);
void Pause(bool is_media_related_action);
void DrawRemotePlaybackText(const std::string& remote_playback_message);
void ReallocateVideoFrame();
void SetCurrentFrameInternal(scoped_refptr<media::VideoFrame>& frame);
- void DidLoadMediaInfo(MediaInfoLoader::Status status);
+ void DidLoadMediaInfo(MediaInfoLoader::Status status,
+ const GURL& redirected_url,
+ const GURL& first_party_for_cookies,
+ bool allow_stored_credentials);
bool IsKeySystemSupported(const std::string& key_system);
+ bool IsLocalResource();
// Actually do the work for generateKeyRequest/addKey so they can easily
// report results to UMA.
@@ -277,6 +316,19 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// NULL immediately and reset.
void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb);
+ // Called when the ContentDecryptionModule has been attached to the
+ // pipeline/decoders.
+ void ContentDecryptionModuleAttached(
+ blink::WebContentDecryptionModuleResult result,
+ bool success);
+
+ bool EnsureTextureBackedSkBitmap(GrContext* gr, SkBitmap& bitmap,
+ const blink::WebSize& size,
+ GrSurfaceOrigin origin,
+ GrPixelConfig config);
+
+ bool IsHLSStream() const;
+
blink::WebFrame* const frame_;
blink::WebMediaPlayerClient* const client_;
@@ -286,7 +338,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// TODO(qinmin): Currently android mediaplayer takes care of the screen
// lock. So this is only used for media source. Will apply this to regular
// media tag once http://crbug.com/247892 is fixed.
- base::WeakPtr<WebMediaPlayerDelegate> delegate_;
+ base::WeakPtr<media::WebMediaPlayerDelegate> delegate_;
// Save the list of buffered time ranges.
blink::WebTimeRanges buffered_;
@@ -304,11 +356,15 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
base::ThreadChecker main_thread_checker_;
// Message loop for media thread.
- const scoped_refptr<base::MessageLoopProxy> media_loop_;
+ const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
// URL of the media file to be fetched.
GURL url_;
+ // URL of the media file after |media_info_loader_| resolves all the
+ // redirections.
+ GURL redirected_url_;
+
// Media duration.
base::TimeDelta duration_;
@@ -358,27 +414,21 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Whether the mediaplayer is playing.
bool is_playing_;
- // Whether the mediaplayer has already started playing.
- bool playing_started_;
-
// Whether media player needs to re-establish the surface texture peer.
bool needs_establish_peer_;
- // Whether |stream_texture_proxy_| is initialized.
- bool stream_texture_proxy_initialized_;
-
// Whether the video size info is available.
bool has_size_info_;
- // Whether the video metadata and info are available.
- bool has_media_metadata_;
- bool has_media_info_;
+ const scoped_refptr<base::MessageLoopProxy> compositor_loop_;
// Object for allocating stream textures.
scoped_refptr<StreamTextureFactory> stream_texture_factory_;
// Object for calling back the compositor thread to repaint the video when a
// frame available. It should be initialized on the compositor thread.
+ // Accessed on main thread and on compositor thread when main thread is
+ // blocked.
ScopedStreamTextureProxy stream_texture_proxy_;
// Whether media player needs external surface.
@@ -387,9 +437,11 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// A pointer back to the compositor to inform it about state changes. This is
// not NULL while the compositor is actively using this webmediaplayer.
+ // Accessed on main thread and on compositor thread when main thread is
+ // blocked.
cc::VideoFrameProvider::Client* video_frame_provider_client_;
- scoped_ptr<WebLayerImpl> video_weblayer_;
+ scoped_ptr<cc_blink::WebLayerImpl> video_weblayer_;
#if defined(VIDEO_HOLE)
// A rectangle represents the geometry of video frame, when computed last
@@ -401,24 +453,12 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
bool force_use_overlay_embedded_video_;
#endif // defined(VIDEO_HOLE)
- scoped_ptr<MediaSourceDelegate,
- MediaSourceDelegate::Destroyer> media_source_delegate_;
-
- // Internal pending playback state.
- // Store a playback request that cannot be started immediately.
- bool pending_playback_;
-
MediaPlayerHostMsg_Initialize_Type player_type_;
- // The current playing time. Because the media player is in the browser
- // process, it will regularly update the |current_time_| by calling
- // OnTimeUpdate().
- double current_time_;
-
// Whether the browser is currently connected to a remote media player.
bool is_remote_;
- media::MediaLog* media_log_;
+ scoped_refptr<media::MediaLog> media_log_;
scoped_ptr<MediaInfoLoader> info_loader_;
@@ -443,6 +483,23 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// player_manager_->SetCdm() directly.
media::DecryptorReadyCB decryptor_ready_cb_;
+ SkBitmap bitmap_;
+
+ // Whether stored credentials are allowed to be passed to the server.
+ bool allow_stored_credentials_;
+
+ // Whether the resource is local.
+ bool is_local_resource_;
+
+ // base::TickClock used by |interpolator_|.
+ base::DefaultTickClock default_tick_clock_;
+
+ // Tracks the most recent media time update and provides interpolated values
+ // as playback progresses.
+ media::TimeDeltaInterpolator interpolator_;
+
+ scoped_ptr<MediaSourceDelegate> media_source_delegate_;
+
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<WebMediaPlayerAndroid> weak_factory_;
diff --git a/chromium/content/renderer/media/audio_input_message_filter.cc b/chromium/content/renderer/media/audio_input_message_filter.cc
index 412196cb3c1..ac987afd360 100644
--- a/chromium/content/renderer/media/audio_input_message_filter.cc
+++ b/chromium/content/renderer/media/audio_input_message_filter.cc
@@ -12,28 +12,37 @@
#include "ipc/ipc_logging.h"
#include "ipc/ipc_sender.h"
-namespace content {
-
namespace {
+
const int kStreamIDNotSet = -1;
+
+void LogMessage(int stream_id, const std::string& msg) {
+ std::ostringstream oss;
+ oss << "[stream_id=" << stream_id << "] AIMF::" << msg;
+ content::WebRtcLogMessage(oss.str());
+ DVLOG(1) << oss.str();
}
+} // namespace
+
+namespace content {
+
class AudioInputMessageFilter::AudioInputIPCImpl
: public NON_EXPORTED_BASE(media::AudioInputIPC) {
public:
AudioInputIPCImpl(const scoped_refptr<AudioInputMessageFilter>& filter,
int render_view_id);
- virtual ~AudioInputIPCImpl();
+ ~AudioInputIPCImpl() override;
// media::AudioInputIPC implementation.
- virtual void CreateStream(media::AudioInputIPCDelegate* delegate,
- int session_id,
- const media::AudioParameters& params,
- bool automatic_gain_control,
- uint32 total_segments) OVERRIDE;
- virtual void RecordStream() OVERRIDE;
- virtual void SetVolume(double volume) OVERRIDE;
- virtual void CloseStream() OVERRIDE;
+ void CreateStream(media::AudioInputIPCDelegate* delegate,
+ int session_id,
+ const media::AudioParameters& params,
+ bool automatic_gain_control,
+ uint32 total_segments) override;
+ void RecordStream() override;
+ void SetVolume(double volume) override;
+ void CloseStream() override;
private:
const scoped_refptr<AudioInputMessageFilter> filter_;
@@ -117,22 +126,14 @@ void AudioInputMessageFilter::OnChannelClosing() {
void AudioInputMessageFilter::OnStreamCreated(
int stream_id,
base::SharedMemoryHandle handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle socket_handle,
-#else
- base::FileDescriptor socket_descriptor,
-#endif
+ base::SyncSocket::TransitDescriptor socket_descriptor,
uint32 length,
uint32 total_segments) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
+ LogMessage(stream_id, "OnStreamCreated");
- WebRtcLogMessage(base::StringPrintf(
- "AIMF::OnStreamCreated. stream_id=%d",
- stream_id));
-
-#if !defined(OS_WIN)
- base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
-#endif
+ base::SyncSocket::Handle socket_handle =
+ base::SyncSocket::UnwrapHandle(socket_descriptor);
media::AudioInputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) {
DLOG(WARNING) << "Got audio stream event for a non-existent or removed"
@@ -193,6 +194,9 @@ void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream(
DCHECK(delegate);
stream_id_ = filter_->delegates_.Add(delegate);
+ // TODO(henrika): remove all LogMessage calls when we have sorted out the
+ // existing "no input audio" issues.
+ LogMessage(stream_id_, "CreateStream");
AudioInputHostMsg_CreateStream_Config config;
config.params = params;
@@ -204,6 +208,7 @@ void AudioInputMessageFilter::AudioInputIPCImpl::CreateStream(
void AudioInputMessageFilter::AudioInputIPCImpl::RecordStream() {
DCHECK_NE(stream_id_, kStreamIDNotSet);
+ LogMessage(stream_id_, "RecordStream");
filter_->Send(new AudioInputHostMsg_RecordStream(stream_id_));
}
@@ -215,6 +220,7 @@ void AudioInputMessageFilter::AudioInputIPCImpl::SetVolume(double volume) {
void AudioInputMessageFilter::AudioInputIPCImpl::CloseStream() {
DCHECK(filter_->io_message_loop_->BelongsToCurrentThread());
DCHECK_NE(stream_id_, kStreamIDNotSet);
+ LogMessage(stream_id_, "CloseStream");
filter_->Send(new AudioInputHostMsg_CloseStream(stream_id_));
filter_->delegates_.Remove(stream_id_);
stream_id_ = kStreamIDNotSet;
diff --git a/chromium/content/renderer/media/audio_input_message_filter.h b/chromium/content/renderer/media/audio_input_message_filter.h
index 1107463eb96..c1b4ba8a5a1 100644
--- a/chromium/content/renderer/media/audio_input_message_filter.h
+++ b/chromium/content/renderer/media/audio_input_message_filter.h
@@ -47,16 +47,16 @@ class CONTENT_EXPORT AudioInputMessageFilter : public IPC::MessageFilter {
// stream_id and the destination render_view_id.
class AudioInputIPCImpl;
- virtual ~AudioInputMessageFilter();
+ ~AudioInputMessageFilter() override;
// Sends an IPC message using |channel_|.
void Send(IPC::Message* message);
// IPC::MessageFilter override. Called on |io_message_loop_|.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
// Received when browser process has created an audio input stream.
void OnStreamCreated(int stream_id,
diff --git a/chromium/content/renderer/media/audio_message_filter.cc b/chromium/content/renderer/media/audio_message_filter.cc
index fde42fb18e2..b03cdd61271 100644
--- a/chromium/content/renderer/media/audio_message_filter.cc
+++ b/chromium/content/renderer/media/audio_message_filter.cc
@@ -24,16 +24,16 @@ class AudioMessageFilter::AudioOutputIPCImpl
AudioOutputIPCImpl(const scoped_refptr<AudioMessageFilter>& filter,
int render_view_id,
int render_frame_id);
- virtual ~AudioOutputIPCImpl();
+ ~AudioOutputIPCImpl() override;
// media::AudioOutputIPC implementation.
- virtual void CreateStream(media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params,
- int session_id) OVERRIDE;
- virtual void PlayStream() OVERRIDE;
- virtual void PauseStream() OVERRIDE;
- virtual void CloseStream() OVERRIDE;
- virtual void SetVolume(double volume) OVERRIDE;
+ void CreateStream(media::AudioOutputIPCDelegate* delegate,
+ const media::AudioParameters& params,
+ int session_id) override;
+ void PlayStream() override;
+ void PauseStream() override;
+ void CloseStream() override;
+ void SetVolume(double volume) override;
private:
const scoped_refptr<AudioMessageFilter> filter_;
@@ -168,11 +168,7 @@ void AudioMessageFilter::OnChannelClosing() {
void AudioMessageFilter::OnStreamCreated(
int stream_id,
base::SharedMemoryHandle handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle socket_handle,
-#else
- base::FileDescriptor socket_descriptor,
-#endif
+ base::SyncSocket::TransitDescriptor socket_descriptor,
uint32 length) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
@@ -180,9 +176,8 @@ void AudioMessageFilter::OnStreamCreated(
"AMF::OnStreamCreated. stream_id=%d",
stream_id));
-#if !defined(OS_WIN)
- base::SyncSocket::Handle socket_handle = socket_descriptor.fd;
-#endif
+ base::SyncSocket::Handle socket_handle =
+ base::SyncSocket::UnwrapHandle(socket_descriptor);
media::AudioOutputIPCDelegate* delegate = delegates_.Lookup(stream_id);
if (!delegate) {
@@ -234,7 +229,6 @@ void AudioMessageFilter::OnOutputDeviceChanged(int stream_id,
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
channel_layout,
channels,
- 0,
new_sample_rate,
16,
new_buffer_size);
diff --git a/chromium/content/renderer/media/audio_message_filter.h b/chromium/content/renderer/media/audio_message_filter.h
index ed4d5b261de..db973d04fe7 100644
--- a/chromium/content/renderer/media/audio_message_filter.h
+++ b/chromium/content/renderer/media/audio_message_filter.h
@@ -55,7 +55,7 @@ class CONTENT_EXPORT AudioMessageFilter : public IPC::MessageFilter {
}
protected:
- virtual ~AudioMessageFilter();
+ ~AudioMessageFilter() override;
private:
FRIEND_TEST_ALL_PREFIXES(AudioMessageFilterTest, Basic);
@@ -69,18 +69,14 @@ class CONTENT_EXPORT AudioMessageFilter : public IPC::MessageFilter {
void Send(IPC::Message* message);
// IPC::MessageFilter override. Called on |io_message_loop|.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
// Received when browser process has created an audio output stream.
void OnStreamCreated(int stream_id, base::SharedMemoryHandle handle,
-#if defined(OS_WIN)
- base::SyncSocket::Handle socket_handle,
-#else
- base::FileDescriptor socket_descriptor,
-#endif
+ base::SyncSocket::TransitDescriptor socket_descriptor,
uint32 length);
// Received when internal state of browser process' audio output device has
diff --git a/chromium/content/renderer/media/audio_message_filter_unittest.cc b/chromium/content/renderer/media/audio_message_filter_unittest.cc
index cdd82888506..2626f4e52f9 100644
--- a/chromium/content/renderer/media/audio_message_filter_unittest.cc
+++ b/chromium/content/renderer/media/audio_message_filter_unittest.cc
@@ -20,21 +20,20 @@ class MockAudioDelegate : public media::AudioOutputIPCDelegate {
Reset();
}
- virtual void OnStateChanged(
- media::AudioOutputIPCDelegate::State state) OVERRIDE {
+ void OnStateChanged(media::AudioOutputIPCDelegate::State state) override {
state_changed_received_ = true;
state_ = state;
}
- virtual void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle,
- int length) OVERRIDE {
+ void OnStreamCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle,
+ int length) override {
created_received_ = true;
handle_ = handle;
length_ = length;
}
- virtual void OnIPCClosed() OVERRIDE {}
+ void OnIPCClosed() override {}
void Reset() {
state_changed_received_ = false;
@@ -86,17 +85,11 @@ TEST(AudioMessageFilterTest, Basic) {
EXPECT_EQ(&delegate, filter->delegates_.Lookup(kStreamId));
// AudioMsg_NotifyStreamCreated
-#if defined(OS_WIN)
- base::SyncSocket::Handle socket_handle;
-#else
- base::FileDescriptor socket_handle;
-#endif
+ base::SyncSocket::TransitDescriptor socket_descriptor;
const uint32 kLength = 1024;
EXPECT_FALSE(delegate.created_received());
- filter->OnMessageReceived(
- AudioMsg_NotifyStreamCreated(
- kStreamId, base::SharedMemory::NULLHandle(),
- socket_handle, kLength));
+ filter->OnMessageReceived(AudioMsg_NotifyStreamCreated(
+ kStreamId, base::SharedMemory::NULLHandle(), socket_descriptor, kLength));
EXPECT_TRUE(delegate.created_received());
EXPECT_FALSE(base::SharedMemory::IsHandleValid(delegate.handle()));
EXPECT_EQ(kLength, delegate.length());
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
index 935fe766f58..4a62d1a1583 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
@@ -21,7 +21,9 @@ AudioRendererMixerManager::AudioRendererMixerManager(
}
AudioRendererMixerManager::~AudioRendererMixerManager() {
- DCHECK(mixers_.empty());
+ // References to AudioRendererMixers may be owned by garbage collected
+ // objects. During process shutdown they may be leaked, so, transitively,
+ // |mixers_| may leak (i.e., may be non-empty at this time) as well.
}
media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput(
@@ -45,6 +47,9 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
int source_render_view_id,
int source_render_frame_id,
const media::AudioParameters& params) {
+ // Effects are not passed through to output creation, so ensure none are set.
+ DCHECK_EQ(params.effects(), media::AudioParameters::NO_EFFECTS);
+
const MixerKey key(source_render_view_id, params);
base::AutoLock auto_lock(mixers_lock_);
@@ -54,9 +59,9 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
return it->second.mixer;
}
- // On ChromeOS and Linux we can rely on the playback device to handle
- // resampling, so don't waste cycles on it here.
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
+ // On ChromeOS we can rely on the playback device to handle resampling, so
+ // don't waste cycles on it here.
+#if defined(OS_CHROMEOS)
int sample_rate = params.sample_rate();
#else
int sample_rate = hardware_config_->GetOutputSampleRate();
@@ -64,7 +69,7 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
// Create output parameters based on the audio hardware configuration for
// passing on to the output sink. Force to 16-bit output for now since we
- // know that works well for WebAudio and WebRTC.
+ // know that works everywhere; ChromeOS does not support other bit depths.
media::AudioParameters output_params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(),
sample_rate, 16, hardware_config_->GetHighLatencyBufferSize());
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.h b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
index 0a76b5dc394..f3d35fcc53f 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.h
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
@@ -68,9 +68,28 @@ class CONTENT_EXPORT AudioRendererMixerManager {
friend class AudioRendererMixerManagerTest;
// Define a key so that only those AudioRendererMixerInputs from the same
- // RenderView and with the same AudioParameters can be mixed together.
+ // RenderView and with the same AudioParameters can be mixed together. The
+ // first value is the RenderViewId.
typedef std::pair<int, media::AudioParameters> MixerKey;
+ // Custom compare operator for the AudioRendererMixerMap. Allows reuse of
+ // mixers where only irrelevant keys mismatch; e.g., effects, bits per sample.
+ struct MixerKeyCompare {
+ bool operator()(const MixerKey& a, const MixerKey& b) const {
+ if (a.first != b.first)
+ return a.first < b.first;
+ if (a.second.sample_rate() != b.second.sample_rate())
+ return a.second.sample_rate() < b.second.sample_rate();
+ if (a.second.channels() != b.second.channels())
+ return a.second.channels() < b.second.channels();
+
+ // Ignore effects(), bits_per_sample(), format(), and frames_per_buffer(),
+ // these parameters do not affect mixer reuse. All AudioRendererMixer
+ // units disable FIFO, so frames_per_buffer() can be safely ignored.
+ return a.second.channel_layout() < b.second.channel_layout();
+ }
+ };
+
// Map of MixerKey to <AudioRendererMixer, Count>. Count allows
// AudioRendererMixerManager to keep track explicitly (v.s. RefCounted which
// is implicit) of the number of outstanding AudioRendererMixers.
@@ -78,7 +97,8 @@ class CONTENT_EXPORT AudioRendererMixerManager {
media::AudioRendererMixer* mixer;
int ref_count;
};
- typedef std::map<MixerKey, AudioRendererMixerReference> AudioRendererMixerMap;
+ typedef std::map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>
+ AudioRendererMixerMap;
// Overrides the AudioRendererSink implementation for unit testing.
void SetAudioRendererSinkForTesting(media::AudioRendererSink* sink);
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
index cb7293e6c97..f1915edf1a1 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
@@ -35,7 +35,7 @@ class AudioRendererMixerManagerTest : public testing::Test {
AudioRendererMixerManagerTest()
: fake_config_(AudioParameters(), AudioParameters()) {
AudioParameters output_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
kSampleRate,
16,
@@ -85,7 +85,7 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
EXPECT_EQ(mixer_count(), 0);
media::AudioParameters params1(
- media::AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
+ AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
kBitsPerChannel, kBufferSize);
media::AudioRendererMixer* mixer1 = GetMixer(kRenderViewId, params1);
@@ -101,7 +101,7 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
EXPECT_EQ(mixer_count(), 1);
media::AudioParameters params2(
- media::AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate * 2,
+ AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate * 2,
kBitsPerChannel, kBufferSize * 2);
media::AudioRendererMixer* mixer2 = GetMixer(kRenderViewId, params2);
ASSERT_TRUE(mixer2);
@@ -117,6 +117,54 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
EXPECT_EQ(mixer_count(), 0);
}
+// Verify GetMixer() correctly deduplicates mixer with irrelevant AudioParameter
+// differences.
+TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
+ EXPECT_CALL(*mock_sink_.get(), Start()).Times(2);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
+ EXPECT_EQ(mixer_count(), 0);
+
+ media::AudioParameters params1(AudioParameters::AUDIO_PCM_LINEAR,
+ kChannelLayout,
+ kSampleRate,
+ kBitsPerChannel,
+ kBufferSize);
+ media::AudioRendererMixer* mixer1 = GetMixer(kRenderViewId, params1);
+ ASSERT_TRUE(mixer1);
+ EXPECT_EQ(mixer_count(), 1);
+
+ // Different formats, bit depths, and buffer sizes should not result in a
+ // different mixer.
+ media::AudioParameters params2(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ kChannelLayout,
+ kSampleRate,
+ kBitsPerChannel * 2,
+ kBufferSize * 2,
+ AudioParameters::NO_EFFECTS);
+ EXPECT_EQ(mixer1, GetMixer(kRenderViewId, params2));
+ EXPECT_EQ(mixer_count(), 1);
+ RemoveMixer(kRenderViewId, params2);
+ EXPECT_EQ(mixer_count(), 1);
+
+ // Modify some parameters that do matter.
+ media::AudioParameters params3(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_MONO,
+ kSampleRate * 2,
+ kBitsPerChannel,
+ kBufferSize,
+ AudioParameters::NO_EFFECTS);
+ ASSERT_NE(params3.channel_layout(), params1.channel_layout());
+
+ EXPECT_NE(mixer1, GetMixer(kRenderViewId, params3));
+ EXPECT_EQ(mixer_count(), 2);
+ RemoveMixer(kRenderViewId, params3);
+ EXPECT_EQ(mixer_count(), 1);
+
+ // Remove final mixer.
+ RemoveMixer(kRenderViewId, params1);
+ EXPECT_EQ(mixer_count(), 0);
+}
+
// Verify CreateInput() provides AudioRendererMixerInput with the appropriate
// callbacks and they are working as expected. Also, verify that separate
// mixers are created for separate render views, even though the AudioParameters
@@ -128,7 +176,7 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
media::AudioParameters params(
- media::AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
+ AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
kBitsPerChannel, kBufferSize);
// Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
diff --git a/chromium/content/renderer/media/buffered_data_source.cc b/chromium/content/renderer/media/buffered_data_source.cc
deleted file mode 100644
index f4a3094684a..00000000000
--- a/chromium/content/renderer/media/buffered_data_source.cc
+++ /dev/null
@@ -1,537 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/buffered_data_source.h"
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "content/public/common/url_constants.h"
-#include "media/base/media_log.h"
-#include "net/base/net_errors.h"
-
-using blink::WebFrame;
-
-namespace {
-
-// BufferedDataSource has an intermediate buffer, this value governs the initial
-// size of that buffer. It is set to 32KB because this is a typical read size
-// of FFmpeg.
-const int kInitialReadBufferSize = 32768;
-
-// Number of cache misses we allow for a single Read() before signaling an
-// error.
-const int kNumCacheMissRetries = 3;
-
-} // namespace
-
-namespace content {
-
-class BufferedDataSource::ReadOperation {
- public:
- ReadOperation(int64 position, int size, uint8* data,
- const media::DataSource::ReadCB& callback);
- ~ReadOperation();
-
- // Runs |callback_| with the given |result|, deleting the operation
- // afterwards.
- static void Run(scoped_ptr<ReadOperation> read_op, int result);
-
- // State for the number of times this read operation has been retried.
- int retries() { return retries_; }
- void IncrementRetries() { ++retries_; }
-
- int64 position() { return position_; }
- int size() { return size_; }
- uint8* data() { return data_; }
-
- private:
- int retries_;
-
- const int64 position_;
- const int size_;
- uint8* data_;
- media::DataSource::ReadCB callback_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(ReadOperation);
-};
-
-BufferedDataSource::ReadOperation::ReadOperation(
- int64 position, int size, uint8* data,
- const media::DataSource::ReadCB& callback)
- : retries_(0),
- position_(position),
- size_(size),
- data_(data),
- callback_(callback) {
- DCHECK(!callback_.is_null());
-}
-
-BufferedDataSource::ReadOperation::~ReadOperation() {
- DCHECK(callback_.is_null());
-}
-
-// static
-void BufferedDataSource::ReadOperation::Run(
- scoped_ptr<ReadOperation> read_op, int result) {
- base::ResetAndReturn(&read_op->callback_).Run(result);
-}
-
-BufferedDataSource::BufferedDataSource(
- const GURL& url,
- BufferedResourceLoader::CORSMode cors_mode,
- const scoped_refptr<base::MessageLoopProxy>& render_loop,
- WebFrame* frame,
- media::MediaLog* media_log,
- BufferedDataSourceHost* host,
- const DownloadingCB& downloading_cb)
- : url_(url),
- cors_mode_(cors_mode),
- total_bytes_(kPositionNotSpecified),
- streaming_(false),
- frame_(frame),
- intermediate_read_buffer_(new uint8[kInitialReadBufferSize]),
- intermediate_read_buffer_size_(kInitialReadBufferSize),
- render_loop_(render_loop),
- stop_signal_received_(false),
- media_has_played_(false),
- preload_(AUTO),
- bitrate_(0),
- playback_rate_(0.0),
- media_log_(media_log),
- host_(host),
- downloading_cb_(downloading_cb),
- weak_factory_(this) {
- DCHECK(host_);
- DCHECK(!downloading_cb_.is_null());
-}
-
-BufferedDataSource::~BufferedDataSource() {}
-
-// A factory method to create BufferedResourceLoader using the read parameters.
-// This method can be overridden to inject mock BufferedResourceLoader object
-// for testing purpose.
-BufferedResourceLoader* BufferedDataSource::CreateResourceLoader(
- int64 first_byte_position, int64 last_byte_position) {
- DCHECK(render_loop_->BelongsToCurrentThread());
-
- BufferedResourceLoader::DeferStrategy strategy = preload_ == METADATA ?
- BufferedResourceLoader::kReadThenDefer :
- BufferedResourceLoader::kCapacityDefer;
-
- return new BufferedResourceLoader(url_,
- cors_mode_,
- first_byte_position,
- last_byte_position,
- strategy,
- bitrate_,
- playback_rate_,
- media_log_.get());
-}
-
-void BufferedDataSource::Initialize(const InitializeCB& init_cb) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(!init_cb.is_null());
- DCHECK(!loader_.get());
-
- init_cb_ = init_cb;
-
- if (url_.SchemeIsHTTPOrHTTPS()) {
- // Do an unbounded range request starting at the beginning. If the server
- // responds with 200 instead of 206 we'll fall back into a streaming mode.
- loader_.reset(CreateResourceLoader(0, kPositionNotSpecified));
- } else {
- // For all other protocols, assume they support range request. We fetch
- // the full range of the resource to obtain the instance size because
- // we won't be served HTTP headers.
- loader_.reset(CreateResourceLoader(kPositionNotSpecified,
- kPositionNotSpecified));
- }
-
- base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr();
- loader_->Start(
- base::Bind(&BufferedDataSource::StartCallback, weak_this),
- base::Bind(&BufferedDataSource::LoadingStateChangedCallback, weak_this),
- base::Bind(&BufferedDataSource::ProgressCallback, weak_this),
- frame_);
-}
-
-void BufferedDataSource::SetPreload(Preload preload) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- preload_ = preload;
-}
-
-bool BufferedDataSource::HasSingleOrigin() {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(init_cb_.is_null() && loader_.get())
- << "Initialize() must complete before calling HasSingleOrigin()";
- return loader_->HasSingleOrigin();
-}
-
-bool BufferedDataSource::DidPassCORSAccessCheck() const {
- return loader_.get() && loader_->DidPassCORSAccessCheck();
-}
-
-void BufferedDataSource::Abort() {
- DCHECK(render_loop_->BelongsToCurrentThread());
- {
- base::AutoLock auto_lock(lock_);
- StopInternal_Locked();
- }
- StopLoader();
- frame_ = NULL;
-}
-
-void BufferedDataSource::MediaPlaybackRateChanged(float playback_rate) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(loader_.get());
-
- if (playback_rate < 0.0f)
- return;
-
- playback_rate_ = playback_rate;
- loader_->SetPlaybackRate(playback_rate);
-}
-
-void BufferedDataSource::MediaIsPlaying() {
- DCHECK(render_loop_->BelongsToCurrentThread());
- media_has_played_ = true;
- UpdateDeferStrategy(false);
-}
-
-void BufferedDataSource::MediaIsPaused() {
- DCHECK(render_loop_->BelongsToCurrentThread());
- UpdateDeferStrategy(true);
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// media::DataSource implementation.
-void BufferedDataSource::Stop(const base::Closure& closure) {
- {
- base::AutoLock auto_lock(lock_);
- StopInternal_Locked();
- }
- closure.Run();
-
- render_loop_->PostTask(
- FROM_HERE,
- base::Bind(&BufferedDataSource::StopLoader, weak_factory_.GetWeakPtr()));
-}
-
-void BufferedDataSource::SetBitrate(int bitrate) {
- render_loop_->PostTask(FROM_HERE,
- base::Bind(&BufferedDataSource::SetBitrateTask,
- weak_factory_.GetWeakPtr(),
- bitrate));
-}
-
-void BufferedDataSource::Read(
- int64 position, int size, uint8* data,
- const media::DataSource::ReadCB& read_cb) {
- DVLOG(1) << "Read: " << position << " offset, " << size << " bytes";
- DCHECK(!read_cb.is_null());
-
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(!read_op_);
-
- if (stop_signal_received_) {
- read_cb.Run(kReadError);
- return;
- }
-
- read_op_.reset(new ReadOperation(position, size, data, read_cb));
- }
-
- render_loop_->PostTask(
- FROM_HERE,
- base::Bind(&BufferedDataSource::ReadTask, weak_factory_.GetWeakPtr()));
-}
-
-bool BufferedDataSource::GetSize(int64* size_out) {
- if (total_bytes_ != kPositionNotSpecified) {
- *size_out = total_bytes_;
- return true;
- }
- *size_out = 0;
- return false;
-}
-
-bool BufferedDataSource::IsStreaming() {
- return streaming_;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Render thread tasks.
-void BufferedDataSource::ReadTask() {
- DCHECK(render_loop_->BelongsToCurrentThread());
- ReadInternal();
-}
-
-void BufferedDataSource::StopInternal_Locked() {
- lock_.AssertAcquired();
- if (stop_signal_received_)
- return;
-
- stop_signal_received_ = true;
-
- // Initialize() isn't part of the DataSource interface so don't call it in
- // response to Stop().
- init_cb_.Reset();
-
- if (read_op_)
- ReadOperation::Run(read_op_.Pass(), kReadError);
-}
-
-void BufferedDataSource::StopLoader() {
- DCHECK(render_loop_->BelongsToCurrentThread());
-
- if (loader_)
- loader_->Stop();
-}
-
-void BufferedDataSource::SetBitrateTask(int bitrate) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(loader_.get());
-
- bitrate_ = bitrate;
- loader_->SetBitrate(bitrate);
-}
-
-// This method is the place where actual read happens, |loader_| must be valid
-// prior to make this method call.
-void BufferedDataSource::ReadInternal() {
- DCHECK(render_loop_->BelongsToCurrentThread());
- int64 position = 0;
- int size = 0;
- {
- base::AutoLock auto_lock(lock_);
- if (stop_signal_received_)
- return;
-
- position = read_op_->position();
- size = read_op_->size();
- }
-
- // First we prepare the intermediate read buffer for BufferedResourceLoader
- // to write to.
- if (size > intermediate_read_buffer_size_) {
- intermediate_read_buffer_.reset(new uint8[size]);
- }
-
- // Perform the actual read with BufferedResourceLoader.
- loader_->Read(position,
- size,
- intermediate_read_buffer_.get(),
- base::Bind(&BufferedDataSource::ReadCallback,
- weak_factory_.GetWeakPtr()));
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-// BufferedResourceLoader callback methods.
-void BufferedDataSource::StartCallback(
- BufferedResourceLoader::Status status) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(loader_.get());
-
- bool init_cb_is_null = false;
- {
- base::AutoLock auto_lock(lock_);
- init_cb_is_null = init_cb_.is_null();
- }
- if (init_cb_is_null) {
- loader_->Stop();
- return;
- }
-
- // All responses must be successful. Resources that are assumed to be fully
- // buffered must have a known content length.
- bool success = status == BufferedResourceLoader::kOk &&
- (!assume_fully_buffered() ||
- loader_->instance_size() != kPositionNotSpecified);
-
- if (success) {
- total_bytes_ = loader_->instance_size();
- streaming_ =
- !assume_fully_buffered() &&
- (total_bytes_ == kPositionNotSpecified || !loader_->range_supported());
-
- media_log_->SetDoubleProperty("total_bytes",
- static_cast<double>(total_bytes_));
- media_log_->SetBooleanProperty("streaming", streaming_);
- } else {
- loader_->Stop();
- }
-
- // TODO(scherkus): we shouldn't have to lock to signal host(), see
- // http://crbug.com/113712 for details.
- base::AutoLock auto_lock(lock_);
- if (stop_signal_received_)
- return;
-
- if (success) {
- if (total_bytes_ != kPositionNotSpecified) {
- host_->SetTotalBytes(total_bytes_);
- if (assume_fully_buffered())
- host_->AddBufferedByteRange(0, total_bytes_);
- }
-
- media_log_->SetBooleanProperty("single_origin", loader_->HasSingleOrigin());
- media_log_->SetBooleanProperty("passed_cors_access_check",
- loader_->DidPassCORSAccessCheck());
- media_log_->SetBooleanProperty("range_header_supported",
- loader_->range_supported());
- }
-
- base::ResetAndReturn(&init_cb_).Run(success);
-}
-
-void BufferedDataSource::PartialReadStartCallback(
- BufferedResourceLoader::Status status) {
- DCHECK(render_loop_->BelongsToCurrentThread());
- DCHECK(loader_.get());
-
- if (status == BufferedResourceLoader::kOk) {
- // Once the request has started successfully, we can proceed with
- // reading from it.
- ReadInternal();
- return;
- }
-
- // Stop the resource loader since we have received an error.
- loader_->Stop();
-
- // TODO(scherkus): we shouldn't have to lock to signal host(), see
- // http://crbug.com/113712 for details.
- base::AutoLock auto_lock(lock_);
- if (stop_signal_received_)
- return;
- ReadOperation::Run(read_op_.Pass(), kReadError);
-}
-
-void BufferedDataSource::ReadCallback(
- BufferedResourceLoader::Status status,
- int bytes_read) {
- DCHECK(render_loop_->BelongsToCurrentThread());
-
- // TODO(scherkus): we shouldn't have to lock to signal host(), see
- // http://crbug.com/113712 for details.
- base::AutoLock auto_lock(lock_);
- if (stop_signal_received_)
- return;
-
- if (status != BufferedResourceLoader::kOk) {
- // Stop the resource load if it failed.
- loader_->Stop();
-
- if (status == BufferedResourceLoader::kCacheMiss &&
- read_op_->retries() < kNumCacheMissRetries) {
- read_op_->IncrementRetries();
-
- // Recreate a loader starting from where we last left off until the
- // end of the resource.
- loader_.reset(CreateResourceLoader(
- read_op_->position(), kPositionNotSpecified));
-
- base::WeakPtr<BufferedDataSource> weak_this = weak_factory_.GetWeakPtr();
- loader_->Start(
- base::Bind(&BufferedDataSource::PartialReadStartCallback, weak_this),
- base::Bind(&BufferedDataSource::LoadingStateChangedCallback,
- weak_this),
- base::Bind(&BufferedDataSource::ProgressCallback, weak_this),
- frame_);
- return;
- }
-
- ReadOperation::Run(read_op_.Pass(), kReadError);
- return;
- }
-
- if (bytes_read > 0) {
- memcpy(read_op_->data(), intermediate_read_buffer_.get(), bytes_read);
- } else if (bytes_read == 0 && total_bytes_ == kPositionNotSpecified) {
- // We've reached the end of the file and we didn't know the total size
- // before. Update the total size so Read()s past the end of the file will
- // fail like they would if we had known the file size at the beginning.
- total_bytes_ = loader_->instance_size();
-
- if (total_bytes_ != kPositionNotSpecified) {
- host_->SetTotalBytes(total_bytes_);
- host_->AddBufferedByteRange(loader_->first_byte_position(),
- total_bytes_);
- }
- }
- ReadOperation::Run(read_op_.Pass(), bytes_read);
-}
-
-void BufferedDataSource::LoadingStateChangedCallback(
- BufferedResourceLoader::LoadingState state) {
- DCHECK(render_loop_->BelongsToCurrentThread());
-
- if (assume_fully_buffered())
- return;
-
- bool is_downloading_data;
- switch (state) {
- case BufferedResourceLoader::kLoading:
- is_downloading_data = true;
- break;
- case BufferedResourceLoader::kLoadingDeferred:
- case BufferedResourceLoader::kLoadingFinished:
- is_downloading_data = false;
- break;
-
- // TODO(scherkus): we don't signal network activity changes when loads
- // fail to preserve existing behaviour when deferring is toggled, however
- // we should consider changing DownloadingCB to also propagate loading
- // state. For example there isn't any signal today to notify the client that
- // loading has failed (we only get errors on subsequent reads).
- case BufferedResourceLoader::kLoadingFailed:
- return;
- }
-
- downloading_cb_.Run(is_downloading_data);
-}
-
-void BufferedDataSource::ProgressCallback(int64 position) {
- DCHECK(render_loop_->BelongsToCurrentThread());
-
- if (assume_fully_buffered())
- return;
-
- // TODO(scherkus): we shouldn't have to lock to signal host(), see
- // http://crbug.com/113712 for details.
- base::AutoLock auto_lock(lock_);
- if (stop_signal_received_)
- return;
-
- host_->AddBufferedByteRange(loader_->first_byte_position(), position);
-}
-
-void BufferedDataSource::UpdateDeferStrategy(bool paused) {
- // No need to aggressively buffer when we are assuming the resource is fully
- // buffered.
- if (assume_fully_buffered()) {
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
- return;
- }
-
- // If the playback has started (at which point the preload value is ignored)
- // and we're paused, then try to load as much as possible (the loader will
- // fall back to kCapacityDefer if it knows the current response won't be
- // useful from the cache in the future).
- if (media_has_played_ && paused && loader_->range_supported()) {
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
- return;
- }
-
- // If media is currently playing or the page indicated preload=auto or the
- // the server does not support the byte range request or we do not want to go
- // too far ahead of the read head, use threshold strategy to enable/disable
- // deferring when the buffer is full/depleted.
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/buffered_data_source.h b/chromium/content/renderer/media/buffered_data_source.h
deleted file mode 100644
index de44e3c9db2..00000000000
--- a/chromium/content/renderer/media/buffered_data_source.h
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_H_
-#define CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "content/renderer/media/buffered_resource_loader.h"
-#include "content/renderer/media/preload.h"
-#include "media/base/data_source.h"
-#include "media/base/ranges.h"
-#include "url/gurl.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace media {
-class MediaLog;
-}
-
-namespace content {
-
-class CONTENT_EXPORT BufferedDataSourceHost {
- public:
- // Notify the host of the total size of the media file.
- virtual void SetTotalBytes(int64 total_bytes) = 0;
-
- // Notify the host that byte range [start,end] has been buffered.
- // TODO(fischman): remove this method when demuxing is push-based instead of
- // pull-based. http://crbug.com/131444
- virtual void AddBufferedByteRange(int64 start, int64 end) = 0;
-
- protected:
- virtual ~BufferedDataSourceHost() {};
-};
-
-// A data source capable of loading URLs and buffering the data using an
-// in-memory sliding window.
-//
-// BufferedDataSource must be created and initialized on the render thread
-// before being passed to other threads. It may be deleted on any thread.
-class CONTENT_EXPORT BufferedDataSource : public media::DataSource {
- public:
- typedef base::Callback<void(bool)> DownloadingCB;
-
- // |url| and |cors_mode| are passed to the object. Buffered byte range changes
- // will be reported to |host|. |downloading_cb| will be called whenever the
- // downloading/paused state of the source changes.
- BufferedDataSource(const GURL& url,
- BufferedResourceLoader::CORSMode cors_mode,
- const scoped_refptr<base::MessageLoopProxy>& render_loop,
- blink::WebFrame* frame,
- media::MediaLog* media_log,
- BufferedDataSourceHost* host,
- const DownloadingCB& downloading_cb);
- virtual ~BufferedDataSource();
-
- // Executes |init_cb| with the result of initialization when it has completed.
- //
- // Method called on the render thread.
- typedef base::Callback<void(bool)> InitializeCB;
- void Initialize(const InitializeCB& init_cb);
-
- // Adjusts the buffering algorithm based on the given preload value.
- void SetPreload(Preload preload);
-
- // Returns true if the media resource has a single origin, false otherwise.
- // Only valid to call after Initialize() has completed.
- //
- // Method called on the render thread.
- bool HasSingleOrigin();
-
- // Returns true if the media resource passed a CORS access control check.
- bool DidPassCORSAccessCheck() const;
-
- // Cancels initialization, any pending loaders, and any pending read calls
- // from the demuxer. The caller is expected to release its reference to this
- // object and never call it again.
- //
- // Method called on the render thread.
- void Abort();
-
- // Notifies changes in playback state for controlling media buffering
- // behavior.
- void MediaPlaybackRateChanged(float playback_rate);
- void MediaIsPlaying();
- void MediaIsPaused();
-
- // Returns true if the resource is local.
- bool assume_fully_buffered() { return !url_.SchemeIsHTTPOrHTTPS(); }
-
- // media::DataSource implementation.
- // Called from demuxer thread.
- virtual void Stop(const base::Closure& closure) OVERRIDE;
-
- virtual void Read(int64 position, int size, uint8* data,
- const media::DataSource::ReadCB& read_cb) OVERRIDE;
- virtual bool GetSize(int64* size_out) OVERRIDE;
- virtual bool IsStreaming() OVERRIDE;
- virtual void SetBitrate(int bitrate) OVERRIDE;
-
- protected:
- // A factory method to create a BufferedResourceLoader based on the read
- // parameters. We can override this file to object a mock
- // BufferedResourceLoader for testing.
- virtual BufferedResourceLoader* CreateResourceLoader(
- int64 first_byte_position, int64 last_byte_position);
-
- private:
- friend class BufferedDataSourceTest;
-
- // Task posted to perform actual reading on the render thread.
- void ReadTask();
-
- // Cancels oustanding callbacks and sets |stop_signal_received_|. Safe to call
- // from any thread.
- void StopInternal_Locked();
-
- // Stops |loader_| if present. Used by Abort() and Stop().
- void StopLoader();
-
- // Tells |loader_| the bitrate of the media.
- void SetBitrateTask(int bitrate);
-
- // The method that performs actual read. This method can only be executed on
- // the render thread.
- void ReadInternal();
-
- // BufferedResourceLoader::Start() callback for initial load.
- void StartCallback(BufferedResourceLoader::Status status);
-
- // BufferedResourceLoader::Start() callback for subsequent loads (i.e.,
- // when accessing ranges that are outside initial buffered region).
- void PartialReadStartCallback(BufferedResourceLoader::Status status);
-
- // BufferedResourceLoader callbacks.
- void ReadCallback(BufferedResourceLoader::Status status, int bytes_read);
- void LoadingStateChangedCallback(BufferedResourceLoader::LoadingState state);
- void ProgressCallback(int64 position);
-
- // Update |loader_|'s deferring strategy in response to a play/pause, or
- // change in playback rate.
- void UpdateDeferStrategy(bool paused);
-
- // URL of the resource requested.
- GURL url_;
- // crossorigin attribute on the corresponding HTML media element, if any.
- BufferedResourceLoader::CORSMode cors_mode_;
-
- // The total size of the resource. Set during StartCallback() if the size is
- // known, otherwise it will remain kPositionNotSpecified until the size is
- // determined by reaching EOF.
- int64 total_bytes_;
-
- // This value will be true if this data source can only support streaming.
- // i.e. range request is not supported.
- bool streaming_;
-
- // A webframe for loading.
- blink::WebFrame* frame_;
-
- // A resource loader for the media resource.
- scoped_ptr<BufferedResourceLoader> loader_;
-
- // Callback method from the pipeline for initialization.
- InitializeCB init_cb_;
-
- // Read parameters received from the Read() method call. Must be accessed
- // under |lock_|.
- class ReadOperation;
- scoped_ptr<ReadOperation> read_op_;
-
- // This buffer is intermediate, we use it for BufferedResourceLoader to write
- // to. And when read in BufferedResourceLoader is done, we copy data from
- // this buffer to |read_buffer_|. The reason for an additional copy is that
- // we don't own |read_buffer_|. But since the read operation is asynchronous,
- // |read_buffer| can be destroyed at any time, so we only copy into
- // |read_buffer| in the final step when it is safe.
- // Memory is allocated for this member during initialization of this object
- // because we want buffer to be passed into BufferedResourceLoader to be
- // always non-null. And by initializing this member with a default size we can
- // avoid creating zero-sized buffered if the first read has zero size.
- scoped_ptr<uint8[]> intermediate_read_buffer_;
- int intermediate_read_buffer_size_;
-
- // The message loop of the render thread.
- const scoped_refptr<base::MessageLoopProxy> render_loop_;
-
- // Protects |stop_signal_received_| and |read_op_|.
- base::Lock lock_;
-
- // Whether we've been told to stop via Abort() or Stop().
- bool stop_signal_received_;
-
- // This variable is true when the user has requested the video to play at
- // least once.
- bool media_has_played_;
-
- // This variable holds the value of the preload attribute for the video
- // element.
- Preload preload_;
-
- // Bitrate of the content, 0 if unknown.
- int bitrate_;
-
- // Current playback rate.
- float playback_rate_;
-
- scoped_refptr<media::MediaLog> media_log_;
-
- // Host object to report buffered byte range changes to.
- BufferedDataSourceHost* host_;
-
- DownloadingCB downloading_cb_;
-
- // NOTE: Weak pointers must be invalidated before all other member variables.
- base::WeakPtrFactory<BufferedDataSource> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedDataSource);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_H_
diff --git a/chromium/content/renderer/media/buffered_data_source_host_impl.cc b/chromium/content/renderer/media/buffered_data_source_host_impl.cc
deleted file mode 100644
index 45c97e63587..00000000000
--- a/chromium/content/renderer/media/buffered_data_source_host_impl.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 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 "content/renderer/media/buffered_data_source_host_impl.h"
-
-namespace content {
-
-BufferedDataSourceHostImpl::BufferedDataSourceHostImpl()
- : total_bytes_(0),
- did_loading_progress_(false) { }
-
-BufferedDataSourceHostImpl::~BufferedDataSourceHostImpl() { }
-
-void BufferedDataSourceHostImpl::SetTotalBytes(int64 total_bytes) {
- total_bytes_ = total_bytes;
-}
-
-void BufferedDataSourceHostImpl::AddBufferedByteRange(int64 start, int64 end) {
- buffered_byte_ranges_.Add(start, end);
- did_loading_progress_ = true;
-}
-
-static base::TimeDelta TimeForByteOffset(
- int64 byte_offset, int64 total_bytes, base::TimeDelta duration) {
- double position = static_cast<double>(byte_offset) / total_bytes;
- // Snap to the beginning/end where the approximation can look especially bad.
- if (position < 0.01)
- return base::TimeDelta();
- if (position > 0.99)
- return duration;
- return base::TimeDelta::FromMilliseconds(
- static_cast<int64>(position * duration.InMilliseconds()));
-}
-
-void BufferedDataSourceHostImpl::AddBufferedTimeRanges(
- media::Ranges<base::TimeDelta>* buffered_time_ranges,
- base::TimeDelta media_duration) const {
- if (total_bytes_ && buffered_byte_ranges_.size()) {
- for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) {
- int64 start = buffered_byte_ranges_.start(i);
- int64 end = buffered_byte_ranges_.end(i);
- buffered_time_ranges->Add(
- TimeForByteOffset(start, total_bytes_, media_duration),
- TimeForByteOffset(end, total_bytes_, media_duration));
- }
- }
-}
-
-bool BufferedDataSourceHostImpl::DidLoadingProgress() {
- bool ret = did_loading_progress_;
- did_loading_progress_ = false;
- return ret;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/buffered_data_source_host_impl.h b/chromium/content/renderer/media/buffered_data_source_host_impl.h
deleted file mode 100644
index d04d4671cc5..00000000000
--- a/chromium/content/renderer/media/buffered_data_source_host_impl.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
-
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "content/renderer/media/buffered_data_source.h"
-#include "media/base/ranges.h"
-
-namespace content {
-
-// Provides an implementation of BufferedDataSourceHost that translates the
-// buffered byte ranges into estimated time ranges.
-class CONTENT_EXPORT BufferedDataSourceHostImpl
- : public BufferedDataSourceHost {
- public:
- BufferedDataSourceHostImpl();
- virtual ~BufferedDataSourceHostImpl();
-
- // BufferedDataSourceHost implementation.
- virtual void SetTotalBytes(int64 total_bytes) OVERRIDE;
- virtual void AddBufferedByteRange(int64 start, int64 end) OVERRIDE;
-
- // Translate the byte ranges to time ranges and append them to the list.
- // TODO(sandersd): This is a confusing name, find something better.
- void AddBufferedTimeRanges(
- media::Ranges<base::TimeDelta>* buffered_time_ranges,
- base::TimeDelta media_duration) const;
-
- bool DidLoadingProgress();
-
- private:
- // Total size of the data source.
- int64 total_bytes_;
-
- // List of buffered byte ranges for estimating buffered time.
- media::Ranges<int64> buffered_byte_ranges_;
-
- // True when AddBufferedByteRange() has been called more recently than
- // DidLoadingProgress().
- bool did_loading_progress_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceHostImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_BUFFERED_DATA_SOURCE_HOST_IMPL_H_
diff --git a/chromium/content/renderer/media/buffered_data_source_host_impl_unittest.cc b/chromium/content/renderer/media/buffered_data_source_host_impl_unittest.cc
deleted file mode 100644
index 6b5a5ecf14a..00000000000
--- a/chromium/content/renderer/media/buffered_data_source_host_impl_unittest.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 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 "content/renderer/media/buffered_data_source_host_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class BufferedDataSourceHostImplTest : public testing::Test {
- public:
- BufferedDataSourceHostImplTest() {}
-
- void Add() {
- host_.AddBufferedTimeRanges(&ranges_, base::TimeDelta::FromSeconds(10));
- }
-
- protected:
- BufferedDataSourceHostImpl host_;
- media::Ranges<base::TimeDelta> ranges_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceHostImplTest);
-};
-
-TEST_F(BufferedDataSourceHostImplTest, Empty) {
- EXPECT_FALSE(host_.DidLoadingProgress());
- Add();
- EXPECT_EQ(0u, ranges_.size());
-}
-
-TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges) {
- host_.AddBufferedByteRange(10, 20);
- host_.SetTotalBytes(100);
- Add();
- EXPECT_EQ(1u, ranges_.size());
- EXPECT_EQ(base::TimeDelta::FromSeconds(1), ranges_.start(0));
- EXPECT_EQ(base::TimeDelta::FromSeconds(2), ranges_.end(0));
-}
-
-TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges_Merges) {
- ranges_.Add(base::TimeDelta::FromSeconds(0), base::TimeDelta::FromSeconds(1));
- host_.AddBufferedByteRange(10, 20);
- host_.SetTotalBytes(100);
- Add();
- EXPECT_EQ(1u, ranges_.size());
- EXPECT_EQ(base::TimeDelta::FromSeconds(0), ranges_.start(0));
- EXPECT_EQ(base::TimeDelta::FromSeconds(2), ranges_.end(0));
-}
-
-TEST_F(BufferedDataSourceHostImplTest, AddBufferedTimeRanges_Snaps) {
- host_.AddBufferedByteRange(5, 995);
- host_.SetTotalBytes(1000);
- Add();
- EXPECT_EQ(1u, ranges_.size());
- EXPECT_EQ(base::TimeDelta::FromSeconds(0), ranges_.start(0));
- EXPECT_EQ(base::TimeDelta::FromSeconds(10), ranges_.end(0));
-}
-
-TEST_F(BufferedDataSourceHostImplTest, SetTotalBytes) {
- host_.AddBufferedByteRange(10, 20);
- Add();
- EXPECT_EQ(0u, ranges_.size());
-
- host_.SetTotalBytes(100);
- Add();
- EXPECT_EQ(1u, ranges_.size());
-}
-
-TEST_F(BufferedDataSourceHostImplTest, DidLoadingProgress) {
- host_.AddBufferedByteRange(10, 20);
- EXPECT_TRUE(host_.DidLoadingProgress());
- EXPECT_FALSE(host_.DidLoadingProgress());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/buffered_data_source_unittest.cc b/chromium/content/renderer/media/buffered_data_source_unittest.cc
deleted file mode 100644
index 403a93b8308..00000000000
--- a/chromium/content/renderer/media/buffered_data_source_unittest.cc
+++ /dev/null
@@ -1,805 +0,0 @@
-// Copyright 2013 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/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "content/public/common/url_constants.h"
-#include "content/renderer/media/buffered_data_source.h"
-#include "content/renderer/media/test_response_generator.h"
-#include "content/test/mock_webframeclient.h"
-#include "content/test/mock_weburlloader.h"
-#include "media/base/media_log.h"
-#include "media/base/mock_filters.h"
-#include "media/base/test_helpers.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-using ::testing::_;
-using ::testing::Assign;
-using ::testing::Invoke;
-using ::testing::InSequence;
-using ::testing::NiceMock;
-using ::testing::StrictMock;
-
-using blink::WebLocalFrame;
-using blink::WebString;
-using blink::WebURLLoader;
-using blink::WebURLResponse;
-using blink::WebView;
-
-namespace content {
-
-class MockBufferedDataSourceHost : public BufferedDataSourceHost {
- public:
- MockBufferedDataSourceHost() {}
- virtual ~MockBufferedDataSourceHost() {}
-
- MOCK_METHOD1(SetTotalBytes, void(int64 total_bytes));
- MOCK_METHOD2(AddBufferedByteRange, void(int64 start, int64 end));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSourceHost);
-};
-
-// Overrides CreateResourceLoader() to permit injecting a MockWebURLLoader.
-// Also keeps track of whether said MockWebURLLoader is actively loading.
-class MockBufferedDataSource : public BufferedDataSource {
- public:
- MockBufferedDataSource(
- const GURL& url,
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
- WebLocalFrame* frame,
- BufferedDataSourceHost* host)
- : BufferedDataSource(url,
- BufferedResourceLoader::kUnspecified,
- message_loop,
- frame,
- new media::MediaLog(),
- host,
- base::Bind(&MockBufferedDataSource::set_downloading,
- base::Unretained(this))),
- downloading_(false),
- loading_(false) {}
- virtual ~MockBufferedDataSource() {}
-
- MOCK_METHOD2(CreateResourceLoader, BufferedResourceLoader*(int64, int64));
- BufferedResourceLoader* CreateMockResourceLoader(int64 first_byte_position,
- int64 last_byte_position) {
- CHECK(!loading_) << "Previous resource load wasn't cancelled";
-
- BufferedResourceLoader* loader =
- BufferedDataSource::CreateResourceLoader(first_byte_position,
- last_byte_position);
-
- // Keep track of active loading state via loadAsynchronously() and cancel().
- NiceMock<MockWebURLLoader>* url_loader = new NiceMock<MockWebURLLoader>();
- ON_CALL(*url_loader, loadAsynchronously(_, _))
- .WillByDefault(Assign(&loading_, true));
- ON_CALL(*url_loader, cancel())
- .WillByDefault(Assign(&loading_, false));
-
- // |test_loader_| will be used when Start() is called.
- loader->test_loader_ = scoped_ptr<WebURLLoader>(url_loader);
- return loader;
- }
-
- bool loading() { return loading_; }
- void set_loading(bool loading) { loading_ = loading; }
- bool downloading() { return downloading_; }
- void set_downloading(bool downloading) { downloading_ = downloading; }
-
- private:
- // Whether the resource is downloading or deferred.
- bool downloading_;
-
- // Whether the resource load has starting loading but yet to been cancelled.
- bool loading_;
-
- DISALLOW_COPY_AND_ASSIGN(MockBufferedDataSource);
-};
-
-static const int64 kFileSize = 5000000;
-static const int64 kFarReadPosition = 4000000;
-static const int kDataSize = 1024;
-
-static const char kHttpUrl[] = "http://localhost/foo.webm";
-static const char kFileUrl[] = "file:///tmp/bar.webm";
-
-class BufferedDataSourceTest : public testing::Test {
- public:
- BufferedDataSourceTest()
- : view_(WebView::create(NULL)),
- frame_(WebLocalFrame::create(&client_)),
- preload_(AUTO) {
- view_->setMainFrame(frame_);
- }
-
- virtual ~BufferedDataSourceTest() {
- view_->close();
- frame_->close();
- }
-
- MOCK_METHOD1(OnInitialize, void(bool));
-
- void Initialize(const char* url, bool expected) {
- GURL gurl(url);
- data_source_.reset(
- new MockBufferedDataSource(gurl,
- message_loop_.message_loop_proxy(),
- view_->mainFrame()->toWebLocalFrame(),
- &host_));
- data_source_->SetPreload(preload_);
-
- response_generator_.reset(new TestResponseGenerator(gurl, kFileSize));
- ExpectCreateResourceLoader();
- EXPECT_CALL(*this, OnInitialize(expected));
- data_source_->Initialize(base::Bind(&BufferedDataSourceTest::OnInitialize,
- base::Unretained(this)));
- message_loop_.RunUntilIdle();
-
- bool is_http = gurl.SchemeIsHTTPOrHTTPS();
- EXPECT_EQ(data_source_->downloading(), is_http);
- }
-
- // Helper to initialize tests with a valid 200 response.
- void InitializeWith200Response() {
- Initialize(kHttpUrl, true);
-
- EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
- Respond(response_generator_->Generate200());
- }
-
- // Helper to initialize tests with a valid 206 response.
- void InitializeWith206Response() {
- Initialize(kHttpUrl, true);
-
- EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
- Respond(response_generator_->Generate206(0));
- }
-
- // Helper to initialize tests with a valid file:// response.
- void InitializeWithFileResponse() {
- Initialize(kFileUrl, true);
-
- EXPECT_CALL(host_, SetTotalBytes(kFileSize));
- EXPECT_CALL(host_, AddBufferedByteRange(0, kFileSize));
- Respond(response_generator_->GenerateFileResponse(0));
- }
-
- // Stops any active loaders and shuts down the data source.
- //
- // This typically happens when the page is closed and for our purposes is
- // appropriate to do when tearing down a test.
- void Stop() {
- if (data_source_->loading()) {
- loader()->didFail(url_loader(), response_generator_->GenerateError());
- message_loop_.RunUntilIdle();
- }
-
- data_source_->Stop(media::NewExpectedClosure());
- message_loop_.RunUntilIdle();
- }
-
- void ExpectCreateResourceLoader() {
- EXPECT_CALL(*data_source_, CreateResourceLoader(_, _))
- .WillOnce(Invoke(data_source_.get(),
- &MockBufferedDataSource::CreateMockResourceLoader));
- message_loop_.RunUntilIdle();
- }
-
- void Respond(const WebURLResponse& response) {
- loader()->didReceiveResponse(url_loader(), response);
- message_loop_.RunUntilIdle();
- }
-
- void ReceiveData(int size) {
- scoped_ptr<char[]> data(new char[size]);
- memset(data.get(), 0xA5, size); // Arbitrary non-zero value.
-
- loader()->didReceiveData(url_loader(), data.get(), size, size);
- message_loop_.RunUntilIdle();
- }
-
- void FinishLoading() {
- data_source_->set_loading(false);
- loader()->didFinishLoading(url_loader(), 0, -1);
- message_loop_.RunUntilIdle();
- }
-
- MOCK_METHOD1(ReadCallback, void(int size));
-
- void ReadAt(int64 position) {
- data_source_->Read(position, kDataSize, buffer_,
- base::Bind(&BufferedDataSourceTest::ReadCallback,
- base::Unretained(this)));
- message_loop_.RunUntilIdle();
- }
-
- // Accessors for private variables on |data_source_|.
- BufferedResourceLoader* loader() {
- return data_source_->loader_.get();
- }
- WebURLLoader* url_loader() {
- return loader()->active_loader_->loader_.get();
- }
-
- Preload preload() { return data_source_->preload_; }
- void set_preload(Preload preload) { preload_ = preload; }
- BufferedResourceLoader::DeferStrategy defer_strategy() {
- return loader()->defer_strategy_;
- }
- int data_source_bitrate() { return data_source_->bitrate_; }
- int data_source_playback_rate() { return data_source_->playback_rate_; }
- int loader_bitrate() { return loader()->bitrate_; }
- int loader_playback_rate() { return loader()->playback_rate_; }
- bool is_local_source() { return data_source_->assume_fully_buffered(); }
- void set_might_be_reused_from_cache_in_future(bool value) {
- loader()->might_be_reused_from_cache_in_future_ = value;
- }
-
- scoped_ptr<MockBufferedDataSource> data_source_;
-
- scoped_ptr<TestResponseGenerator> response_generator_;
- MockWebFrameClient client_;
- WebView* view_;
- WebLocalFrame* frame_;
-
- StrictMock<MockBufferedDataSourceHost> host_;
- base::MessageLoop message_loop_;
-
- private:
- // Used for calling BufferedDataSource::Read().
- uint8 buffer_[kDataSize];
-
- Preload preload_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedDataSourceTest);
-};
-
-TEST_F(BufferedDataSourceTest, Range_Supported) {
- InitializeWith206Response();
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_FALSE(data_source_->IsStreaming());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Range_InstanceSizeUnknown) {
- Initialize(kHttpUrl, true);
-
- Respond(response_generator_->Generate206(
- 0, TestResponseGenerator::kNoContentRangeInstanceSize));
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_TRUE(data_source_->IsStreaming());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Range_NotFound) {
- Initialize(kHttpUrl, false);
- Respond(response_generator_->Generate404());
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Range_NotSupported) {
- InitializeWith200Response();
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_TRUE(data_source_->IsStreaming());
- Stop();
-}
-
-// Special carve-out for Apache versions that choose to return a 200 for
-// Range:0- ("because it's more efficient" than a 206)
-TEST_F(BufferedDataSourceTest, Range_SupportedButReturned200) {
- Initialize(kHttpUrl, true);
- EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
- WebURLResponse response = response_generator_->Generate200();
- response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
- WebString::fromUTF8("bytes"));
- Respond(response);
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_FALSE(data_source_->IsStreaming());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Range_MissingContentRange) {
- Initialize(kHttpUrl, false);
- Respond(response_generator_->Generate206(
- 0, TestResponseGenerator::kNoContentRange));
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Range_MissingContentLength) {
- Initialize(kHttpUrl, true);
-
- // It'll manage without a Content-Length response.
- EXPECT_CALL(host_, SetTotalBytes(response_generator_->content_length()));
- Respond(response_generator_->Generate206(
- 0, TestResponseGenerator::kNoContentLength));
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_FALSE(data_source_->IsStreaming());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Range_WrongContentRange) {
- Initialize(kHttpUrl, false);
-
- // Now it's done and will fail.
- Respond(response_generator_->Generate206(1337));
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-// Test the case where the initial response from the server indicates that
-// Range requests are supported, but a later request prove otherwise.
-TEST_F(BufferedDataSourceTest, Range_ServerLied) {
- InitializeWith206Response();
-
- // Read causing a new request to be made -- we'll expect it to error.
- ExpectCreateResourceLoader();
- ReadAt(kFarReadPosition);
-
- // Return a 200 in response to a range request.
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- Respond(response_generator_->Generate200());
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Http_AbortWhileReading) {
- InitializeWith206Response();
-
- // Make sure there's a pending read -- we'll expect it to error.
- ReadAt(0);
-
- // Abort!!!
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- data_source_->Abort();
- message_loop_.RunUntilIdle();
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_AbortWhileReading) {
- InitializeWithFileResponse();
-
- // Make sure there's a pending read -- we'll expect it to error.
- ReadAt(0);
-
- // Abort!!!
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- data_source_->Abort();
- message_loop_.RunUntilIdle();
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Http_Retry) {
- InitializeWith206Response();
-
- // Read to advance our position.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
- ReadAt(0);
- ReceiveData(kDataSize);
-
- // Issue a pending read but terminate the connection to force a retry.
- ReadAt(kDataSize);
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->Generate206(kDataSize));
-
- // Complete the read.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- EXPECT_CALL(host_, AddBufferedByteRange(kDataSize, (kDataSize * 2) - 1));
- ReceiveData(kDataSize);
-
- EXPECT_TRUE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_Retry) {
- InitializeWithFileResponse();
-
- // Read to advance our position.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- ReadAt(0);
- ReceiveData(kDataSize);
-
- // Issue a pending read but terminate the connection to force a retry.
- ReadAt(kDataSize);
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->GenerateFileResponse(kDataSize));
-
- // Complete the read.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- ReceiveData(kDataSize);
-
- EXPECT_TRUE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Http_TooManyRetries) {
- InitializeWith206Response();
-
- // Make sure there's a pending read -- we'll expect it to error.
- ReadAt(0);
-
- // It'll try three times.
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->Generate206(0));
-
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->Generate206(0));
-
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->Generate206(0));
-
- // It'll error after this.
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- FinishLoading();
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_TooManyRetries) {
- InitializeWithFileResponse();
-
- // Make sure there's a pending read -- we'll expect it to error.
- ReadAt(0);
-
- // It'll try three times.
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->GenerateFileResponse(0));
-
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->GenerateFileResponse(0));
-
- ExpectCreateResourceLoader();
- FinishLoading();
- Respond(response_generator_->GenerateFileResponse(0));
-
- // It'll error after this.
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- FinishLoading();
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_InstanceSizeUnknown) {
- Initialize(kFileUrl, false);
- EXPECT_FALSE(data_source_->downloading());
-
- Respond(response_generator_->GenerateFileResponse(-1));
-
- EXPECT_FALSE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_Successful) {
- InitializeWithFileResponse();
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_FALSE(data_source_->IsStreaming());
- Stop();
-}
-
-static void SetTrue(bool* value) {
- *value = true;
-}
-
-// This test makes sure that Stop() does not require a task to run on
-// |message_loop_| before it calls its callback. This prevents accidental
-// introduction of a pipeline teardown deadlock. The pipeline owner blocks
-// the render message loop while waiting for Stop() to complete. Since this
-// object runs on the render message loop, Stop() will not complete if it
-// requires a task to run on the the message loop that is being blocked.
-TEST_F(BufferedDataSourceTest, StopDoesNotUseMessageLoopForCallback) {
- InitializeWith206Response();
-
- // Stop() the data source, using a callback that lets us verify that it was
- // called before Stop() returns. This is to make sure that the callback does
- // not require |message_loop_| to execute tasks before being called.
- bool stop_done_called = false;
- EXPECT_TRUE(data_source_->loading());
- data_source_->Stop(base::Bind(&SetTrue, &stop_done_called));
-
- // Verify that the callback was called inside the Stop() call.
- EXPECT_TRUE(stop_done_called);
- message_loop_.RunUntilIdle();
-}
-
-TEST_F(BufferedDataSourceTest, StopDuringRead) {
- InitializeWith206Response();
-
- uint8 buffer[256];
- data_source_->Read(0, arraysize(buffer), buffer, base::Bind(
- &BufferedDataSourceTest::ReadCallback, base::Unretained(this)));
-
- // The outstanding read should fail before the stop callback runs.
- {
- InSequence s;
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- data_source_->Stop(media::NewExpectedClosure());
- }
- message_loop_.RunUntilIdle();
-}
-
-TEST_F(BufferedDataSourceTest, DefaultValues) {
- InitializeWith206Response();
-
- // Ensure we have sane values for default loading scenario.
- EXPECT_EQ(AUTO, preload());
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- EXPECT_EQ(0, data_source_bitrate());
- EXPECT_EQ(0.0f, data_source_playback_rate());
- EXPECT_EQ(0, loader_bitrate());
- EXPECT_EQ(0.0f, loader_playback_rate());
-
- EXPECT_TRUE(data_source_->loading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, SetBitrate) {
- InitializeWith206Response();
-
- data_source_->SetBitrate(1234);
- message_loop_.RunUntilIdle();
- EXPECT_EQ(1234, data_source_bitrate());
- EXPECT_EQ(1234, loader_bitrate());
-
- // Read so far ahead to cause the loader to get recreated.
- BufferedResourceLoader* old_loader = loader();
- ExpectCreateResourceLoader();
- ReadAt(kFarReadPosition);
- Respond(response_generator_->Generate206(kFarReadPosition));
-
- // Verify loader changed but still has same bitrate.
- EXPECT_NE(old_loader, loader());
- EXPECT_EQ(1234, loader_bitrate());
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, MediaPlaybackRateChanged) {
- InitializeWith206Response();
-
- data_source_->MediaPlaybackRateChanged(2.0f);
- message_loop_.RunUntilIdle();
- EXPECT_EQ(2.0f, data_source_playback_rate());
- EXPECT_EQ(2.0f, loader_playback_rate());
-
- // Read so far ahead to cause the loader to get recreated.
- BufferedResourceLoader* old_loader = loader();
- ExpectCreateResourceLoader();
- ReadAt(kFarReadPosition);
- Respond(response_generator_->Generate206(kFarReadPosition));
-
- // Verify loader changed but still has same playback rate.
- EXPECT_NE(old_loader, loader());
-
- EXPECT_TRUE(data_source_->loading());
- EXPECT_CALL(*this, ReadCallback(media::DataSource::kReadError));
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Http_Read) {
- InitializeWith206Response();
-
- ReadAt(0);
-
- // Receive first half of the read.
- EXPECT_CALL(host_, AddBufferedByteRange(0, (kDataSize / 2) - 1));
- ReceiveData(kDataSize / 2);
-
- // Receive last half of the read.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
- ReceiveData(kDataSize / 2);
-
- EXPECT_TRUE(data_source_->downloading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Http_Read_Seek) {
- InitializeWith206Response();
-
- // Read a bit from the beginning.
- ReadAt(0);
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize - 1));
- ReceiveData(kDataSize);
-
- // Simulate a seek by reading a bit beyond kDataSize.
- ReadAt(kDataSize * 2);
-
- // We receive data leading up to but not including our read.
- EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2 - 1));
- ReceiveData(kDataSize);
-
- // We now receive the rest of the data for our read.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 3 - 1));
- ReceiveData(kDataSize);
-
- EXPECT_TRUE(data_source_->downloading());
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_Read) {
- InitializeWithFileResponse();
-
- ReadAt(0);
-
- // Receive first half of the read but no buffering update.
- ReceiveData(kDataSize / 2);
-
- // Receive last half of the read but no buffering update.
- EXPECT_CALL(*this, ReadCallback(kDataSize));
- ReceiveData(kDataSize / 2);
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, Http_FinishLoading) {
- InitializeWith206Response();
-
- EXPECT_TRUE(data_source_->downloading());
- FinishLoading();
- EXPECT_FALSE(data_source_->downloading());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, File_FinishLoading) {
- InitializeWithFileResponse();
-
- EXPECT_FALSE(data_source_->downloading());
- FinishLoading();
- EXPECT_FALSE(data_source_->downloading());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, LocalResource_DeferStrategy) {
- InitializeWithFileResponse();
-
- EXPECT_EQ(AUTO, preload());
- EXPECT_TRUE(is_local_source());
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, LocalResource_PreloadMetadata_DeferStrategy) {
- set_preload(METADATA);
- InitializeWithFileResponse();
-
- EXPECT_EQ(METADATA, preload());
- EXPECT_TRUE(is_local_source());
- EXPECT_EQ(BufferedResourceLoader::kReadThenDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, ExternalResource_Reponse200_DeferStrategy) {
- InitializeWith200Response();
-
- EXPECT_EQ(AUTO, preload());
- EXPECT_FALSE(is_local_source());
- EXPECT_FALSE(loader()->range_supported());
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest,
- ExternalResource_Response200_PreloadMetadata_DeferStrategy) {
- set_preload(METADATA);
- InitializeWith200Response();
-
- EXPECT_EQ(METADATA, preload());
- EXPECT_FALSE(is_local_source());
- EXPECT_FALSE(loader()->range_supported());
- EXPECT_EQ(BufferedResourceLoader::kReadThenDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest, ExternalResource_Reponse206_DeferStrategy) {
- InitializeWith206Response();
-
- EXPECT_EQ(AUTO, preload());
- EXPECT_FALSE(is_local_source());
- EXPECT_TRUE(loader()->range_supported());
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
- set_might_be_reused_from_cache_in_future(true);
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kNeverDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
- set_might_be_reused_from_cache_in_future(false);
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- Stop();
-}
-
-TEST_F(BufferedDataSourceTest,
- ExternalResource_Response206_PreloadMetadata_DeferStrategy) {
- set_preload(METADATA);
- InitializeWith206Response();
-
- EXPECT_EQ(METADATA, preload());
- EXPECT_FALSE(is_local_source());
- EXPECT_TRUE(loader()->range_supported());
- EXPECT_EQ(BufferedResourceLoader::kReadThenDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
- set_might_be_reused_from_cache_in_future(true);
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kNeverDefer, defer_strategy());
-
- data_source_->MediaIsPlaying();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
- set_might_be_reused_from_cache_in_future(false);
- data_source_->MediaIsPaused();
- EXPECT_EQ(BufferedResourceLoader::kCapacityDefer, defer_strategy());
-
- Stop();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/buffered_resource_loader.cc b/chromium/content/renderer/media/buffered_resource_loader.cc
deleted file mode 100644
index 24b1213a08c..00000000000
--- a/chromium/content/renderer/media/buffered_resource_loader.cc
+++ /dev/null
@@ -1,786 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/buffered_resource_loader.h"
-
-#include "base/bits.h"
-#include "base/callback_helpers.h"
-#include "base/metrics/histogram.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "content/public/common/url_constants.h"
-#include "content/renderer/media/cache_util.h"
-#include "media/base/media_log.h"
-#include "net/http/http_byte_range.h"
-#include "net/http/http_request_headers.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
-
-using blink::WebFrame;
-using blink::WebString;
-using blink::WebURLError;
-using blink::WebURLLoader;
-using blink::WebURLLoaderOptions;
-using blink::WebURLRequest;
-using blink::WebURLResponse;
-
-namespace content {
-
-static const int kHttpOK = 200;
-static const int kHttpPartialContent = 206;
-
-// Define the number of bytes in a megabyte.
-static const int kMegabyte = 1024 * 1024;
-
-// Minimum capacity of the buffer in forward or backward direction.
-//
-// 2MB is an arbitrary limit; it just seems to be "good enough" in practice.
-static const int kMinBufferCapacity = 2 * kMegabyte;
-
-// Maximum capacity of the buffer in forward or backward direction. This is
-// effectively the largest single read the code path can handle.
-// 20MB is an arbitrary limit; it just seems to be "good enough" in practice.
-static const int kMaxBufferCapacity = 20 * kMegabyte;
-
-// Maximum number of bytes outside the buffer we will wait for in order to
-// fulfill a read. If a read starts more than 2MB away from the data we
-// currently have in the buffer, we will not wait for buffer to reach the read's
-// location and will instead reset the request.
-static const int kForwardWaitThreshold = 2 * kMegabyte;
-
-// Computes the suggested backward and forward capacity for the buffer
-// if one wants to play at |playback_rate| * the natural playback speed.
-// Use a value of 0 for |bitrate| if it is unknown.
-static void ComputeTargetBufferWindow(float playback_rate, int bitrate,
- int* out_backward_capacity,
- int* out_forward_capacity) {
- static const int kDefaultBitrate = 200 * 1024 * 8; // 200 Kbps.
- static const int kMaxBitrate = 20 * kMegabyte * 8; // 20 Mbps.
- static const float kMaxPlaybackRate = 25.0;
- static const int kTargetSecondsBufferedAhead = 10;
- static const int kTargetSecondsBufferedBehind = 2;
-
- // Use a default bit rate if unknown and clamp to prevent overflow.
- if (bitrate <= 0)
- bitrate = kDefaultBitrate;
- bitrate = std::min(bitrate, kMaxBitrate);
-
- // Only scale the buffer window for playback rates greater than 1.0 in
- // magnitude and clamp to prevent overflow.
- bool backward_playback = false;
- if (playback_rate < 0.0f) {
- backward_playback = true;
- playback_rate *= -1.0f;
- }
-
- playback_rate = std::max(playback_rate, 1.0f);
- playback_rate = std::min(playback_rate, kMaxPlaybackRate);
-
- int bytes_per_second = (bitrate / 8.0) * playback_rate;
-
- // Clamp between kMinBufferCapacity and kMaxBufferCapacity.
- *out_forward_capacity = std::max(
- kTargetSecondsBufferedAhead * bytes_per_second, kMinBufferCapacity);
- *out_backward_capacity = std::max(
- kTargetSecondsBufferedBehind * bytes_per_second, kMinBufferCapacity);
-
- *out_forward_capacity = std::min(*out_forward_capacity, kMaxBufferCapacity);
- *out_backward_capacity = std::min(*out_backward_capacity, kMaxBufferCapacity);
-
- if (backward_playback)
- std::swap(*out_forward_capacity, *out_backward_capacity);
-}
-
-BufferedResourceLoader::BufferedResourceLoader(
- const GURL& url,
- CORSMode cors_mode,
- int64 first_byte_position,
- int64 last_byte_position,
- DeferStrategy strategy,
- int bitrate,
- float playback_rate,
- media::MediaLog* media_log)
- : buffer_(kMinBufferCapacity, kMinBufferCapacity),
- loader_failed_(false),
- defer_strategy_(strategy),
- might_be_reused_from_cache_in_future_(true),
- range_supported_(false),
- saved_forward_capacity_(0),
- url_(url),
- cors_mode_(cors_mode),
- first_byte_position_(first_byte_position),
- last_byte_position_(last_byte_position),
- single_origin_(true),
- offset_(0),
- content_length_(kPositionNotSpecified),
- instance_size_(kPositionNotSpecified),
- read_position_(0),
- read_size_(0),
- read_buffer_(NULL),
- first_offset_(0),
- last_offset_(0),
- bitrate_(bitrate),
- playback_rate_(playback_rate),
- media_log_(media_log) {
-
- // Set the initial capacity of |buffer_| based on |bitrate_| and
- // |playback_rate_|.
- UpdateBufferWindow();
-}
-
-BufferedResourceLoader::~BufferedResourceLoader() {}
-
-void BufferedResourceLoader::Start(
- const StartCB& start_cb,
- const LoadingStateChangedCB& loading_cb,
- const ProgressCB& progress_cb,
- WebFrame* frame) {
- // Make sure we have not started.
- DCHECK(start_cb_.is_null());
- DCHECK(loading_cb_.is_null());
- DCHECK(progress_cb_.is_null());
- DCHECK(!start_cb.is_null());
- DCHECK(!loading_cb.is_null());
- DCHECK(!progress_cb.is_null());
- CHECK(frame);
-
- start_cb_ = start_cb;
- loading_cb_ = loading_cb;
- progress_cb_ = progress_cb;
-
- if (first_byte_position_ != kPositionNotSpecified) {
- // TODO(hclam): server may not support range request so |offset_| may not
- // equal to |first_byte_position_|.
- offset_ = first_byte_position_;
- }
-
- // Prepare the request.
- WebURLRequest request(url_);
- request.setTargetType(WebURLRequest::TargetIsMedia);
-
- if (IsRangeRequest()) {
- request.setHTTPHeaderField(
- WebString::fromUTF8(net::HttpRequestHeaders::kRange),
- WebString::fromUTF8(net::HttpByteRange::Bounded(
- first_byte_position_, last_byte_position_).GetHeaderValue()));
- }
-
- frame->setReferrerForRequest(request, blink::WebURL());
-
- // Disable compression, compression for audio/video doesn't make sense...
- request.setHTTPHeaderField(
- WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding),
- WebString::fromUTF8("identity;q=1, *;q=0"));
-
- // Check for our test WebURLLoader.
- scoped_ptr<WebURLLoader> loader;
- if (test_loader_) {
- loader = test_loader_.Pass();
- } else {
- WebURLLoaderOptions options;
- if (cors_mode_ == kUnspecified) {
- options.allowCredentials = true;
- options.crossOriginRequestPolicy =
- WebURLLoaderOptions::CrossOriginRequestPolicyAllow;
- } else {
- options.exposeAllResponseHeaders = true;
- // The author header set is empty, no preflight should go ahead.
- options.preflightPolicy = WebURLLoaderOptions::PreventPreflight;
- options.crossOriginRequestPolicy =
- WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
- if (cors_mode_ == kUseCredentials)
- options.allowCredentials = true;
- }
- loader.reset(frame->createAssociatedURLLoader(options));
- }
-
- // Start the resource loading.
- loader->loadAsynchronously(request, this);
- active_loader_.reset(new ActiveLoader(loader.Pass()));
- loading_cb_.Run(kLoading);
-}
-
-void BufferedResourceLoader::Stop() {
- // Reset callbacks.
- start_cb_.Reset();
- loading_cb_.Reset();
- progress_cb_.Reset();
- read_cb_.Reset();
-
- // Cancel and reset any active loaders.
- active_loader_.reset();
-}
-
-void BufferedResourceLoader::Read(
- int64 position,
- int read_size,
- uint8* buffer,
- const ReadCB& read_cb) {
- DCHECK(start_cb_.is_null());
- DCHECK(read_cb_.is_null());
- DCHECK(!read_cb.is_null());
- DCHECK(buffer);
- DCHECK_GT(read_size, 0);
-
- // Save the parameter of reading.
- read_cb_ = read_cb;
- read_position_ = position;
- read_size_ = read_size;
- read_buffer_ = buffer;
-
- // Reads should immediately fail if the loader also failed.
- if (loader_failed_) {
- DoneRead(kFailed, 0);
- return;
- }
-
- // If we're attempting to read past the end of the file, return a zero
- // indicating EOF.
- //
- // This can happen with callees that read in fixed-sized amounts for parsing
- // or at the end of chunked 200 responses when we discover the actual length
- // of the file.
- if (instance_size_ != kPositionNotSpecified &&
- instance_size_ <= read_position_) {
- DVLOG(1) << "Appear to have seeked beyond EOS; returning 0.";
- DoneRead(kOk, 0);
- return;
- }
-
- // Make sure |offset_| and |read_position_| does not differ by a large
- // amount.
- if (read_position_ > offset_ + kint32max ||
- read_position_ < offset_ + kint32min) {
- DoneRead(kCacheMiss, 0);
- return;
- }
-
- // Make sure |read_size_| is not too large for the buffer to ever be able to
- // fulfill the read request.
- if (read_size_ > kMaxBufferCapacity) {
- DoneRead(kFailed, 0);
- return;
- }
-
- // Prepare the parameters.
- first_offset_ = read_position_ - offset_;
- last_offset_ = first_offset_ + read_size_;
-
- // If we can serve the request now, do the actual read.
- if (CanFulfillRead()) {
- ReadInternal();
- UpdateDeferBehavior();
- return;
- }
-
- // If we expect the read request to be fulfilled later, expand capacity as
- // necessary and disable deferring.
- if (WillFulfillRead()) {
- // Advance offset as much as possible to create additional capacity.
- int advance = std::min(first_offset_, buffer_.forward_bytes());
- bool ret = buffer_.Seek(advance);
- DCHECK(ret);
-
- offset_ += advance;
- first_offset_ -= advance;
- last_offset_ -= advance;
-
- // Expand capacity to accomodate a read that extends past the normal
- // capacity.
- //
- // This can happen when reading in a large seek index or when the
- // first byte of a read request falls within kForwardWaitThreshold.
- if (last_offset_ > buffer_.forward_capacity()) {
- saved_forward_capacity_ = buffer_.forward_capacity();
- buffer_.set_forward_capacity(last_offset_);
- }
-
- // Make sure we stop deferring now that there's additional capacity.
- DCHECK(!ShouldDefer())
- << "Capacity was not adjusted properly to prevent deferring.";
- UpdateDeferBehavior();
-
- return;
- }
-
- // Make a callback to report failure.
- DoneRead(kCacheMiss, 0);
-}
-
-int64 BufferedResourceLoader::content_length() {
- return content_length_;
-}
-
-int64 BufferedResourceLoader::instance_size() {
- return instance_size_;
-}
-
-bool BufferedResourceLoader::range_supported() {
- return range_supported_;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// blink::WebURLLoaderClient implementation.
-void BufferedResourceLoader::willSendRequest(
- WebURLLoader* loader,
- WebURLRequest& newRequest,
- const WebURLResponse& redirectResponse) {
-
- // The load may have been stopped and |start_cb| is destroyed.
- // In this case we shouldn't do anything.
- if (start_cb_.is_null()) {
- // Set the url in the request to an invalid value (empty url).
- newRequest.setURL(blink::WebURL());
- return;
- }
-
- // Only allow |single_origin_| if we haven't seen a different origin yet.
- if (single_origin_)
- single_origin_ = url_.GetOrigin() == GURL(newRequest.url()).GetOrigin();
-
- url_ = newRequest.url();
-}
-
-void BufferedResourceLoader::didSendData(
- WebURLLoader* loader,
- unsigned long long bytes_sent,
- unsigned long long total_bytes_to_be_sent) {
- NOTIMPLEMENTED();
-}
-
-void BufferedResourceLoader::didReceiveResponse(
- WebURLLoader* loader,
- const WebURLResponse& response) {
- DVLOG(1) << "didReceiveResponse: HTTP/"
- << (response.httpVersion() == WebURLResponse::HTTP_0_9 ? "0.9" :
- response.httpVersion() == WebURLResponse::HTTP_1_0 ? "1.0" :
- response.httpVersion() == WebURLResponse::HTTP_1_1 ? "1.1" :
- "Unknown")
- << " " << response.httpStatusCode();
- DCHECK(active_loader_.get());
-
- // The loader may have been stopped and |start_cb| is destroyed.
- // In this case we shouldn't do anything.
- if (start_cb_.is_null())
- return;
-
- uint32 reasons = GetReasonsForUncacheability(response);
- might_be_reused_from_cache_in_future_ = reasons == 0;
- UMA_HISTOGRAM_BOOLEAN("Media.CacheUseful", reasons == 0);
- int shift = 0;
- int max_enum = base::bits::Log2Ceiling(kMaxReason);
- while (reasons) {
- DCHECK_LT(shift, max_enum); // Sanity check.
- if (reasons & 0x1)
- UMA_HISTOGRAM_ENUMERATION("Media.UncacheableReason", shift, max_enum);
- reasons >>= 1;
- ++shift;
- }
-
- // Expected content length can be |kPositionNotSpecified|, in that case
- // |content_length_| is not specified and this is a streaming response.
- content_length_ = response.expectedContentLength();
-
- // We make a strong assumption that when we reach here we have either
- // received a response from HTTP/HTTPS protocol or the request was
- // successful (in particular range request). So we only verify the partial
- // response for HTTP and HTTPS protocol.
- if (url_.SchemeIsHTTPOrHTTPS()) {
- bool partial_response = (response.httpStatusCode() == kHttpPartialContent);
- bool ok_response = (response.httpStatusCode() == kHttpOK);
-
- if (IsRangeRequest()) {
- // Check to see whether the server supports byte ranges.
- std::string accept_ranges =
- response.httpHeaderField("Accept-Ranges").utf8();
- range_supported_ = (accept_ranges.find("bytes") != std::string::npos);
-
- // If we have verified the partial response and it is correct, we will
- // return kOk. It's also possible for a server to support range requests
- // without advertising "Accept-Ranges: bytes".
- if (partial_response && VerifyPartialResponse(response)) {
- range_supported_ = true;
- } else if (ok_response && first_byte_position_ == 0 &&
- last_byte_position_ == kPositionNotSpecified) {
- // We accept a 200 response for a Range:0- request, trusting the
- // Accept-Ranges header, because Apache thinks that's a reasonable thing
- // to return.
- instance_size_ = content_length_;
- } else {
- DoneStart(kFailed);
- return;
- }
- } else {
- instance_size_ = content_length_;
- if (response.httpStatusCode() != kHttpOK) {
- // We didn't request a range but server didn't reply with "200 OK".
- DoneStart(kFailed);
- return;
- }
- }
-
- } else {
- CHECK_EQ(instance_size_, kPositionNotSpecified);
- if (content_length_ != kPositionNotSpecified) {
- if (first_byte_position_ == kPositionNotSpecified)
- instance_size_ = content_length_;
- else if (last_byte_position_ == kPositionNotSpecified)
- instance_size_ = content_length_ + first_byte_position_;
- }
- }
-
- // Calls with a successful response.
- DoneStart(kOk);
-}
-
-void BufferedResourceLoader::didReceiveData(
- WebURLLoader* loader,
- const char* data,
- int data_length,
- int encoded_data_length) {
- DVLOG(1) << "didReceiveData: " << data_length << " bytes";
- DCHECK(active_loader_.get());
- DCHECK_GT(data_length, 0);
-
- buffer_.Append(reinterpret_cast<const uint8*>(data), data_length);
-
- // If there is an active read request, try to fulfill the request.
- if (HasPendingRead() && CanFulfillRead())
- ReadInternal();
-
- // At last see if the buffer is full and we need to defer the downloading.
- UpdateDeferBehavior();
-
- // Consume excess bytes from our in-memory buffer if necessary.
- if (buffer_.forward_bytes() > buffer_.forward_capacity()) {
- int excess = buffer_.forward_bytes() - buffer_.forward_capacity();
- bool success = buffer_.Seek(excess);
- DCHECK(success);
- offset_ += first_offset_ + excess;
- }
-
- // Notify latest progress and buffered offset.
- progress_cb_.Run(offset_ + buffer_.forward_bytes() - 1);
- Log();
-}
-
-void BufferedResourceLoader::didDownloadData(
- blink::WebURLLoader* loader,
- int dataLength,
- int encoded_data_length) {
- NOTIMPLEMENTED();
-}
-
-void BufferedResourceLoader::didReceiveCachedMetadata(
- WebURLLoader* loader,
- const char* data,
- int data_length) {
- NOTIMPLEMENTED();
-}
-
-void BufferedResourceLoader::didFinishLoading(
- WebURLLoader* loader,
- double finishTime,
- int64_t total_encoded_data_length) {
- DVLOG(1) << "didFinishLoading";
- DCHECK(active_loader_.get());
-
- // We're done with the loader.
- active_loader_.reset();
- loading_cb_.Run(kLoadingFinished);
-
- // If we didn't know the |instance_size_| we do now.
- if (instance_size_ == kPositionNotSpecified) {
- instance_size_ = offset_ + buffer_.forward_bytes();
- }
-
- // If there is a start callback, run it.
- if (!start_cb_.is_null()) {
- DCHECK(read_cb_.is_null())
- << "Shouldn't have a read callback during start";
- DoneStart(kOk);
- return;
- }
-
- // Don't leave read callbacks hanging around.
- if (HasPendingRead()) {
- // Try to fulfill with what is in the buffer.
- if (CanFulfillRead())
- ReadInternal();
- else
- DoneRead(kCacheMiss, 0);
- }
-}
-
-void BufferedResourceLoader::didFail(
- WebURLLoader* loader,
- const WebURLError& error) {
- DVLOG(1) << "didFail: reason=" << error.reason
- << ", isCancellation=" << error.isCancellation
- << ", domain=" << error.domain.utf8().data()
- << ", localizedDescription="
- << error.localizedDescription.utf8().data();
- DCHECK(active_loader_.get());
-
- // We don't need to continue loading after failure.
- //
- // Keep it alive until we exit this method so that |error| remains valid.
- scoped_ptr<ActiveLoader> active_loader = active_loader_.Pass();
- loader_failed_ = true;
- loading_cb_.Run(kLoadingFailed);
-
- // Don't leave start callbacks hanging around.
- if (!start_cb_.is_null()) {
- DCHECK(read_cb_.is_null())
- << "Shouldn't have a read callback during start";
- DoneStart(kFailed);
- return;
- }
-
- // Don't leave read callbacks hanging around.
- if (HasPendingRead()) {
- DoneRead(kFailed, 0);
- }
-}
-
-bool BufferedResourceLoader::HasSingleOrigin() const {
- DCHECK(start_cb_.is_null())
- << "Start() must complete before calling HasSingleOrigin()";
- return single_origin_;
-}
-
-bool BufferedResourceLoader::DidPassCORSAccessCheck() const {
- DCHECK(start_cb_.is_null())
- << "Start() must complete before calling DidPassCORSAccessCheck()";
- return !loader_failed_ && cors_mode_ != kUnspecified;
-}
-
-void BufferedResourceLoader::UpdateDeferStrategy(DeferStrategy strategy) {
- if (!might_be_reused_from_cache_in_future_ && strategy == kNeverDefer)
- strategy = kCapacityDefer;
- defer_strategy_ = strategy;
- UpdateDeferBehavior();
-}
-
-void BufferedResourceLoader::SetPlaybackRate(float playback_rate) {
- playback_rate_ = playback_rate;
-
- // This is a pause so don't bother updating the buffer window as we'll likely
- // get unpaused in the future.
- if (playback_rate_ == 0.0)
- return;
-
- UpdateBufferWindow();
-}
-
-void BufferedResourceLoader::SetBitrate(int bitrate) {
- DCHECK(bitrate >= 0);
- bitrate_ = bitrate;
- UpdateBufferWindow();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// Helper methods.
-
-void BufferedResourceLoader::UpdateBufferWindow() {
- int backward_capacity;
- int forward_capacity;
- ComputeTargetBufferWindow(
- playback_rate_, bitrate_, &backward_capacity, &forward_capacity);
-
- // This does not evict data from the buffer if the new capacities are less
- // than the current capacities; the new limits will be enforced after the
- // existing excess buffered data is consumed.
- buffer_.set_backward_capacity(backward_capacity);
- buffer_.set_forward_capacity(forward_capacity);
-}
-
-void BufferedResourceLoader::UpdateDeferBehavior() {
- if (!active_loader_)
- return;
-
- SetDeferred(ShouldDefer());
-}
-
-void BufferedResourceLoader::SetDeferred(bool deferred) {
- if (active_loader_->deferred() == deferred)
- return;
-
- active_loader_->SetDeferred(deferred);
- loading_cb_.Run(deferred ? kLoadingDeferred : kLoading);
-}
-
-bool BufferedResourceLoader::ShouldDefer() const {
- switch(defer_strategy_) {
- case kNeverDefer:
- return false;
-
- case kReadThenDefer:
- DCHECK(read_cb_.is_null() || last_offset_ > buffer_.forward_bytes())
- << "We shouldn't stop deferring if we can fulfill the read";
- return read_cb_.is_null();
-
- case kCapacityDefer:
- return buffer_.forward_bytes() >= buffer_.forward_capacity();
- }
- NOTREACHED();
- return false;
-}
-
-bool BufferedResourceLoader::CanFulfillRead() const {
- // If we are reading too far in the backward direction.
- if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0)
- return false;
-
- // If the start offset is too far ahead.
- if (first_offset_ >= buffer_.forward_bytes())
- return false;
-
- // At the point, we verified that first byte requested is within the buffer.
- // If the request has completed, then just returns with what we have now.
- if (!active_loader_)
- return true;
-
- // If the resource request is still active, make sure the whole requested
- // range is covered.
- if (last_offset_ > buffer_.forward_bytes())
- return false;
-
- return true;
-}
-
-bool BufferedResourceLoader::WillFulfillRead() const {
- // Trying to read too far behind.
- if (first_offset_ < 0 && (first_offset_ + buffer_.backward_bytes()) < 0)
- return false;
-
- // Trying to read too far ahead.
- if ((first_offset_ - buffer_.forward_bytes()) >= kForwardWaitThreshold)
- return false;
-
- // The resource request has completed, there's no way we can fulfill the
- // read request.
- if (!active_loader_)
- return false;
-
- return true;
-}
-
-void BufferedResourceLoader::ReadInternal() {
- // Seek to the first byte requested.
- bool ret = buffer_.Seek(first_offset_);
- DCHECK(ret);
-
- // Then do the read.
- int read = buffer_.Read(read_buffer_, read_size_);
- offset_ += first_offset_ + read;
-
- // And report with what we have read.
- DoneRead(kOk, read);
-}
-
-int64 BufferedResourceLoader::first_byte_position() const {
- return first_byte_position_;
-}
-
-// static
-bool BufferedResourceLoader::ParseContentRange(
- const std::string& content_range_str, int64* first_byte_position,
- int64* last_byte_position, int64* instance_size) {
- const std::string kUpThroughBytesUnit = "bytes ";
- if (content_range_str.find(kUpThroughBytesUnit) != 0)
- return false;
- std::string range_spec =
- content_range_str.substr(kUpThroughBytesUnit.length());
- size_t dash_offset = range_spec.find("-");
- size_t slash_offset = range_spec.find("/");
-
- if (dash_offset == std::string::npos || slash_offset == std::string::npos ||
- slash_offset < dash_offset || slash_offset + 1 == range_spec.length()) {
- return false;
- }
- if (!base::StringToInt64(range_spec.substr(0, dash_offset),
- first_byte_position) ||
- !base::StringToInt64(range_spec.substr(dash_offset + 1,
- slash_offset - dash_offset - 1),
- last_byte_position)) {
- return false;
- }
- if (slash_offset == range_spec.length() - 2 &&
- range_spec[slash_offset + 1] == '*') {
- *instance_size = kPositionNotSpecified;
- } else {
- if (!base::StringToInt64(range_spec.substr(slash_offset + 1),
- instance_size)) {
- return false;
- }
- }
- if (*last_byte_position < *first_byte_position ||
- (*instance_size != kPositionNotSpecified &&
- *last_byte_position >= *instance_size)) {
- return false;
- }
-
- return true;
-}
-
-bool BufferedResourceLoader::VerifyPartialResponse(
- const WebURLResponse& response) {
- int64 first_byte_position, last_byte_position, instance_size;
- if (!ParseContentRange(response.httpHeaderField("Content-Range").utf8(),
- &first_byte_position, &last_byte_position,
- &instance_size)) {
- return false;
- }
-
- if (instance_size != kPositionNotSpecified) {
- instance_size_ = instance_size;
- }
-
- if (first_byte_position_ != kPositionNotSpecified &&
- first_byte_position_ != first_byte_position) {
- return false;
- }
-
- // TODO(hclam): I should also check |last_byte_position|, but since
- // we will never make such a request that it is ok to leave it unimplemented.
- return true;
-}
-
-void BufferedResourceLoader::DoneRead(Status status, int bytes_read) {
- if (saved_forward_capacity_) {
- buffer_.set_forward_capacity(saved_forward_capacity_);
- saved_forward_capacity_ = 0;
- }
- read_position_ = 0;
- read_size_ = 0;
- read_buffer_ = NULL;
- first_offset_ = 0;
- last_offset_ = 0;
- Log();
-
- base::ResetAndReturn(&read_cb_).Run(status, bytes_read);
-}
-
-
-void BufferedResourceLoader::DoneStart(Status status) {
- base::ResetAndReturn(&start_cb_).Run(status);
-}
-
-bool BufferedResourceLoader::IsRangeRequest() const {
- return first_byte_position_ != kPositionNotSpecified;
-}
-
-void BufferedResourceLoader::Log() {
- media_log_->AddEvent(
- media_log_->CreateBufferedExtentsChangedEvent(
- offset_ - buffer_.backward_bytes(),
- offset_,
- offset_ + buffer_.forward_bytes()));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/buffered_resource_loader.h b/chromium/content/renderer/media/buffered_resource_loader.h
deleted file mode 100644
index 3bdf1388c7f..00000000000
--- a/chromium/content/renderer/media/buffered_resource_loader.h
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_BUFFERED_RESOURCE_LOADER_H_
-#define CONTENT_RENDERER_MEDIA_BUFFERED_RESOURCE_LOADER_H_
-
-#include <string>
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/timer/timer.h"
-#include "content/common/content_export.h"
-#include "content/renderer/media/active_loader.h"
-#include "media/base/seekable_buffer.h"
-#include "third_party/WebKit/public/platform/WebURLLoader.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "url/gurl.h"
-
-namespace media {
-class MediaLog;
-class SeekableBuffer;
-}
-
-namespace content {
-
-const int64 kPositionNotSpecified = -1;
-
-// BufferedResourceLoader is single threaded and must be accessed on the
-// render thread. It wraps a WebURLLoader and does in-memory buffering,
-// pausing resource loading when the in-memory buffer is full and resuming
-// resource loading when there is available capacity.
-class CONTENT_EXPORT BufferedResourceLoader
- : NON_EXPORTED_BASE(public blink::WebURLLoaderClient) {
- public:
- // kNeverDefer - Aggresively buffer; never defer loading while paused.
- // kReadThenDefer - Request only enough data to fulfill read requests.
- // kCapacityDefer - Try to keep amount of buffered data at capacity.
- enum DeferStrategy {
- kNeverDefer,
- kReadThenDefer,
- kCapacityDefer,
- };
-
- // Status codes for start/read operations on BufferedResourceLoader.
- enum Status {
- // Everything went as planned.
- kOk,
-
- // The operation failed, which may have been due to:
- // - Page navigation
- // - Server replied 4xx/5xx
- // - The response was invalid
- // - Connection was terminated
- //
- // At this point you should delete the loader.
- kFailed,
-
- // The loader will never be able to satisfy the read request. Please stop,
- // delete, create a new loader, and try again.
- kCacheMiss,
- };
-
- // Keep in sync with WebMediaPlayer::CORSMode.
- enum CORSMode { kUnspecified, kAnonymous, kUseCredentials };
-
- enum LoadingState {
- kLoading, // Actively attempting to download data.
- kLoadingDeferred, // Loading intentionally deferred.
- kLoadingFinished, // Loading finished normally; no more data will arrive.
- kLoadingFailed, // Loading finished abnormally; no more data will arrive.
- };
-
- // |url| - URL for the resource to be loaded.
- // |cors_mode| - HTML media element's crossorigin attribute.
- // |first_byte_position| - First byte to start loading from,
- // |kPositionNotSpecified| for not specified.
- // |last_byte_position| - Last byte to be loaded,
- // |kPositionNotSpecified| for not specified.
- // |strategy| is the initial loading strategy to use.
- // |bitrate| is the bitrate of the media, 0 if unknown.
- // |playback_rate| is the current playback rate of the media.
- BufferedResourceLoader(
- const GURL& url,
- CORSMode cors_mode,
- int64 first_byte_position,
- int64 last_byte_position,
- DeferStrategy strategy,
- int bitrate,
- float playback_rate,
- media::MediaLog* media_log);
- virtual ~BufferedResourceLoader();
-
- // Start the resource loading with the specified URL and range.
- //
- // |loading_cb| is executed when the loading state has changed.
- // |progress_cb| is executed when additional data has arrived.
- typedef base::Callback<void(Status)> StartCB;
- typedef base::Callback<void(LoadingState)> LoadingStateChangedCB;
- typedef base::Callback<void(int64)> ProgressCB;
- void Start(const StartCB& start_cb,
- const LoadingStateChangedCB& loading_cb,
- const ProgressCB& progress_cb,
- blink::WebFrame* frame);
-
- // Stops everything associated with this loader, including active URL loads
- // and pending callbacks.
- //
- // It is safe to delete a BufferedResourceLoader after calling Stop().
- void Stop();
-
- // Copies |read_size| bytes from |position| into |buffer|, executing |read_cb|
- // when the operation has completed.
- //
- // The callback will contain the number of bytes read iff the status is kOk,
- // zero otherwise.
- //
- // If necessary will temporarily increase forward capacity of buffer to
- // accomodate an unusually large read.
- typedef base::Callback<void(Status, int)> ReadCB;
- void Read(int64 position, int read_size,
- uint8* buffer, const ReadCB& read_cb);
-
- // Gets the content length in bytes of the instance after this loader has been
- // started. If this value is |kPositionNotSpecified|, then content length is
- // unknown.
- int64 content_length();
-
- // Gets the original size of the file requested. If this value is
- // |kPositionNotSpecified|, then the size is unknown.
- int64 instance_size();
-
- // Returns true if the server supports byte range requests.
- bool range_supported();
-
- // blink::WebURLLoaderClient implementation.
- virtual void willSendRequest(
- blink::WebURLLoader* loader,
- blink::WebURLRequest& newRequest,
- const blink::WebURLResponse& redirectResponse);
- virtual void didSendData(
- blink::WebURLLoader* loader,
- unsigned long long bytesSent,
- unsigned long long totalBytesToBeSent);
- virtual void didReceiveResponse(
- blink::WebURLLoader* loader,
- const blink::WebURLResponse& response);
- virtual void didDownloadData(
- blink::WebURLLoader* loader,
- int data_length,
- int encoded_data_length);
- virtual void didReceiveData(
- blink::WebURLLoader* loader,
- const char* data,
- int data_length,
- int encoded_data_length);
- virtual void didReceiveCachedMetadata(
- blink::WebURLLoader* loader,
- const char* data, int dataLength);
- virtual void didFinishLoading(
- blink::WebURLLoader* loader,
- double finishTime,
- int64_t total_encoded_data_length);
- virtual void didFail(
- blink::WebURLLoader* loader,
- const blink::WebURLError&);
-
- // Returns true if the media resource has a single origin, false otherwise.
- // Only valid to call after Start() has completed.
- bool HasSingleOrigin() const;
-
- // Returns true if the media resource passed a CORS access control check.
- // Only valid to call after Start() has completed.
- bool DidPassCORSAccessCheck() const;
-
- // Sets the defer strategy to the given value unless it seems unwise.
- // Specifically downgrade kNeverDefer to kCapacityDefer if we know the
- // current response will not be used to satisfy future requests (the cache
- // won't help us).
- void UpdateDeferStrategy(DeferStrategy strategy);
-
- // Sets the playback rate to the given value and updates buffer window
- // accordingly.
- void SetPlaybackRate(float playback_rate);
-
- // Sets the bitrate to the given value and updates buffer window
- // accordingly.
- void SetBitrate(int bitrate);
-
- // Return the |first_byte_position| passed into the ctor.
- int64 first_byte_position() const;
-
- // Parse a Content-Range header into its component pieces and return true if
- // each of the expected elements was found & parsed correctly.
- // |*instance_size| may be set to kPositionNotSpecified if the range ends in
- // "/*".
- // NOTE: only public for testing! This is an implementation detail of
- // VerifyPartialResponse (a private method).
- static bool ParseContentRange(
- const std::string& content_range_str, int64* first_byte_position,
- int64* last_byte_position, int64* instance_size);
-
- private:
- friend class BufferedDataSourceTest;
- friend class BufferedResourceLoaderTest;
- friend class MockBufferedDataSource;
-
- // Updates the |buffer_|'s forward and backward capacities.
- void UpdateBufferWindow();
-
- // Updates deferring behavior based on current buffering scheme.
- void UpdateDeferBehavior();
-
- // Sets |active_loader_|'s defer state and fires |loading_cb_| if the state
- // changed.
- void SetDeferred(bool deferred);
-
- // Returns true if we should defer resource loading based on the current
- // buffering scheme.
- bool ShouldDefer() const;
-
- // Returns true if the current read request can be fulfilled by what is in
- // the buffer.
- bool CanFulfillRead() const;
-
- // Returns true if the current read request will be fulfilled in the future.
- bool WillFulfillRead() const;
-
- // Method that does the actual read and calls the |read_cb_|, assuming the
- // request range is in |buffer_|.
- void ReadInternal();
-
- // If we have made a range request, verify the response from the server.
- bool VerifyPartialResponse(const blink::WebURLResponse& response);
-
- // Done with read. Invokes the read callback and reset parameters for the
- // read request.
- void DoneRead(Status status, int bytes_read);
-
- // Done with start. Invokes the start callback and reset it.
- void DoneStart(Status status);
-
- bool HasPendingRead() { return !read_cb_.is_null(); }
-
- // Helper function that returns true if a range request was specified.
- bool IsRangeRequest() const;
-
- // Log everything interesting to |media_log_|.
- void Log();
-
- // A sliding window of buffer.
- media::SeekableBuffer buffer_;
-
- // Keeps track of an active WebURLLoader and associated state.
- scoped_ptr<ActiveLoader> active_loader_;
-
- // Tracks if |active_loader_| failed. If so, then all calls to Read() will
- // fail.
- bool loader_failed_;
-
- // Current buffering algorithm in place for resource loading.
- DeferStrategy defer_strategy_;
-
- // True if the currently-reading response might be used to satisfy a future
- // request from the cache.
- bool might_be_reused_from_cache_in_future_;
-
- // True if Range header is supported.
- bool range_supported_;
-
- // Forward capacity to reset to after an extension.
- size_t saved_forward_capacity_;
-
- GURL url_;
- CORSMode cors_mode_;
- const int64 first_byte_position_;
- const int64 last_byte_position_;
- bool single_origin_;
-
- // Executed whenever the state of resource loading has changed.
- LoadingStateChangedCB loading_cb_;
-
- // Executed whenever additional data has been downloaded and reports the
- // zero-indexed file offset of the furthest buffered byte.
- ProgressCB progress_cb_;
-
- // Members used during request start.
- StartCB start_cb_;
- int64 offset_;
- int64 content_length_;
- int64 instance_size_;
-
- // Members used during a read operation. They should be reset after each
- // read has completed or failed.
- ReadCB read_cb_;
- int64 read_position_;
- int read_size_;
- uint8* read_buffer_;
-
- // Offsets of the requested first byte and last byte in |buffer_|. They are
- // written by Read().
- int first_offset_;
- int last_offset_;
-
- // Injected WebURLLoader instance for testing purposes.
- scoped_ptr<blink::WebURLLoader> test_loader_;
-
- // Bitrate of the media. Set to 0 if unknown.
- int bitrate_;
-
- // Playback rate of the media.
- float playback_rate_;
-
- scoped_refptr<media::MediaLog> media_log_;
-
- DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoader);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_BUFFERED_RESOURCE_LOADER_H_
diff --git a/chromium/content/renderer/media/buffered_resource_loader_unittest.cc b/chromium/content/renderer/media/buffered_resource_loader_unittest.cc
deleted file mode 100644
index 7bd23de9e25..00000000000
--- a/chromium/content/renderer/media/buffered_resource_loader_unittest.cc
+++ /dev/null
@@ -1,1131 +0,0 @@
-// Copyright 2013 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 <algorithm>
-#include <string>
-
-#include "base/bind.h"
-#include "base/format_macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/stringprintf.h"
-#include "content/renderer/media/buffered_resource_loader.h"
-#include "content/test/mock_webframeclient.h"
-#include "content/test/mock_weburlloader.h"
-#include "media/base/media_log.h"
-#include "media/base/seekable_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_util.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::Truly;
-using ::testing::NiceMock;
-
-using blink::WebLocalFrame;
-using blink::WebString;
-using blink::WebURLError;
-using blink::WebURLResponse;
-using blink::WebView;
-
-namespace content {
-
-static const char* kHttpUrl = "http://test";
-static const char kHttpRedirectToSameDomainUrl1[] = "http://test/ing";
-static const char kHttpRedirectToSameDomainUrl2[] = "http://test/ing2";
-static const char kHttpRedirectToDifferentDomainUrl1[] = "http://test2";
-
-static const int kDataSize = 1024;
-static const int kHttpOK = 200;
-static const int kHttpPartialContent = 206;
-
-enum NetworkState {
- NONE,
- LOADED,
- LOADING
-};
-
-// Predicate that tests that request disallows compressed data.
-static bool CorrectAcceptEncoding(const blink::WebURLRequest &request) {
- std::string value = request.httpHeaderField(
- WebString::fromUTF8(net::HttpRequestHeaders::kAcceptEncoding)).utf8();
- return (value.find("identity;q=1") != std::string::npos) &&
- (value.find("*;q=0") != std::string::npos);
-}
-
-class BufferedResourceLoaderTest : public testing::Test {
- public:
- BufferedResourceLoaderTest()
- : view_(WebView::create(NULL)), frame_(WebLocalFrame::create(&client_)) {
- view_->setMainFrame(frame_);
-
- for (int i = 0; i < kDataSize; ++i) {
- data_[i] = i;
- }
- }
-
- virtual ~BufferedResourceLoaderTest() {
- view_->close();
- frame_->close();
- }
-
- void Initialize(const char* url, int first_position, int last_position) {
- gurl_ = GURL(url);
- first_position_ = first_position;
- last_position_ = last_position;
-
- loader_.reset(new BufferedResourceLoader(
- gurl_, BufferedResourceLoader::kUnspecified,
- first_position_, last_position_,
- BufferedResourceLoader::kCapacityDefer, 0, 0,
- new media::MediaLog()));
-
- // |test_loader_| will be used when Start() is called.
- url_loader_ = new NiceMock<MockWebURLLoader>();
- loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_);
- }
-
- void SetLoaderBuffer(int forward_capacity, int backward_capacity) {
- loader_->buffer_.set_forward_capacity(forward_capacity);
- loader_->buffer_.set_backward_capacity(backward_capacity);
- loader_->buffer_.Clear();
- }
-
- void Start() {
- InSequence s;
- EXPECT_CALL(*url_loader_, loadAsynchronously(Truly(CorrectAcceptEncoding),
- loader_.get()));
-
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- loader_->Start(
- base::Bind(&BufferedResourceLoaderTest::StartCallback,
- base::Unretained(this)),
- base::Bind(&BufferedResourceLoaderTest::LoadingCallback,
- base::Unretained(this)),
- base::Bind(&BufferedResourceLoaderTest::ProgressCallback,
- base::Unretained(this)),
- view_->mainFrame());
- }
-
- void FullResponse(int64 instance_size) {
- FullResponse(instance_size, BufferedResourceLoader::kOk);
- }
-
- void FullResponse(int64 instance_size,
- BufferedResourceLoader::Status status) {
- EXPECT_CALL(*this, StartCallback(status));
-
- WebURLResponse response(gurl_);
- response.setHTTPHeaderField(WebString::fromUTF8("Content-Length"),
- WebString::fromUTF8(base::StringPrintf("%"
- PRId64, instance_size)));
- response.setExpectedContentLength(instance_size);
- response.setHTTPStatusCode(kHttpOK);
- loader_->didReceiveResponse(url_loader_, response);
-
- if (status == BufferedResourceLoader::kOk) {
- EXPECT_EQ(instance_size, loader_->content_length());
- EXPECT_EQ(instance_size, loader_->instance_size());
- }
-
- EXPECT_FALSE(loader_->range_supported());
- }
-
- void PartialResponse(int64 first_position, int64 last_position,
- int64 instance_size) {
- PartialResponse(first_position, last_position, instance_size, false, true);
- }
-
- void PartialResponse(int64 first_position, int64 last_position,
- int64 instance_size, bool chunked, bool accept_ranges) {
- EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kOk));
-
- WebURLResponse response(gurl_);
- response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
- WebString::fromUTF8(base::StringPrintf("bytes "
- "%" PRId64 "-%" PRId64 "/%" PRId64,
- first_position,
- last_position,
- instance_size)));
-
- // HTTP 1.1 doesn't permit Content-Length with Transfer-Encoding: chunked.
- int64 content_length = -1;
- if (chunked) {
- response.setHTTPHeaderField(WebString::fromUTF8("Transfer-Encoding"),
- WebString::fromUTF8("chunked"));
- } else {
- content_length = last_position - first_position + 1;
- }
- response.setExpectedContentLength(content_length);
-
- // A server isn't required to return Accept-Ranges even though it might.
- if (accept_ranges) {
- response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
- WebString::fromUTF8("bytes"));
- }
-
- response.setHTTPStatusCode(kHttpPartialContent);
- loader_->didReceiveResponse(url_loader_, response);
-
- // XXX: what's the difference between these two? For example in the chunked
- // range request case, Content-Length is unspecified (because it's chunked)
- // but Content-Range: a-b/c can be returned, where c == Content-Length
- //
- // Can we eliminate one?
- EXPECT_EQ(content_length, loader_->content_length());
- EXPECT_EQ(instance_size, loader_->instance_size());
-
- // A valid partial response should always result in this being true.
- EXPECT_TRUE(loader_->range_supported());
- }
-
- void Redirect(const char* url) {
- GURL redirectUrl(url);
- blink::WebURLRequest newRequest(redirectUrl);
- blink::WebURLResponse redirectResponse(gurl_);
-
- loader_->willSendRequest(url_loader_, newRequest, redirectResponse);
-
- base::MessageLoop::current()->RunUntilIdle();
- }
-
- void StopWhenLoad() {
- InSequence s;
- EXPECT_CALL(*url_loader_, cancel());
- loader_->Stop();
- loader_.reset();
- }
-
- // Helper method to write to |loader_| from |data_|.
- void WriteLoader(int position, int size) {
- EXPECT_CALL(*this, ProgressCallback(position + size - 1));
- loader_->didReceiveData(url_loader_,
- reinterpret_cast<char*>(data_ + position),
- size,
- size);
- }
-
- void WriteData(int size) {
- EXPECT_CALL(*this, ProgressCallback(_));
-
- scoped_ptr<char[]> data(new char[size]);
- loader_->didReceiveData(url_loader_, data.get(), size, size);
- }
-
- void WriteUntilThreshold() {
- int buffered = loader_->buffer_.forward_bytes();
- int capacity = loader_->buffer_.forward_capacity();
- CHECK_LT(buffered, capacity);
-
- EXPECT_CALL(*this, LoadingCallback(
- BufferedResourceLoader::kLoadingDeferred));
- WriteData(capacity - buffered);
- }
-
- // Helper method to read from |loader_|.
- void ReadLoader(int64 position, int size, uint8* buffer) {
- loader_->Read(position, size, buffer,
- base::Bind(&BufferedResourceLoaderTest::ReadCallback,
- base::Unretained(this)));
- }
-
- // Verifies that data in buffer[0...size] is equal to data_[pos...pos+size].
- void VerifyBuffer(uint8* buffer, int pos, int size) {
- EXPECT_EQ(0, memcmp(buffer, data_ + pos, size));
- }
-
- void ConfirmLoaderOffsets(int64 expected_offset,
- int expected_first_offset,
- int expected_last_offset) {
- EXPECT_EQ(loader_->offset_, expected_offset);
- EXPECT_EQ(loader_->first_offset_, expected_first_offset);
- EXPECT_EQ(loader_->last_offset_, expected_last_offset);
- }
-
- void ConfirmBufferState(int backward_bytes,
- int backward_capacity,
- int forward_bytes,
- int forward_capacity) {
- EXPECT_EQ(backward_bytes, loader_->buffer_.backward_bytes());
- EXPECT_EQ(backward_capacity, loader_->buffer_.backward_capacity());
- EXPECT_EQ(forward_bytes, loader_->buffer_.forward_bytes());
- EXPECT_EQ(forward_capacity, loader_->buffer_.forward_capacity());
- }
-
- void ConfirmLoaderBufferBackwardCapacity(int expected_backward_capacity) {
- EXPECT_EQ(loader_->buffer_.backward_capacity(),
- expected_backward_capacity);
- }
-
- void ConfirmLoaderBufferForwardCapacity(int expected_forward_capacity) {
- EXPECT_EQ(loader_->buffer_.forward_capacity(), expected_forward_capacity);
- }
-
- // Makes sure the |loader_| buffer window is in a reasonable range.
- void CheckBufferWindowBounds() {
- // Corresponds to value defined in buffered_resource_loader.cc.
- static const int kMinBufferCapacity = 2 * 1024 * 1024;
- EXPECT_GE(loader_->buffer_.forward_capacity(), kMinBufferCapacity);
- EXPECT_GE(loader_->buffer_.backward_capacity(), kMinBufferCapacity);
-
- // Corresponds to value defined in buffered_resource_loader.cc.
- static const int kMaxBufferCapacity = 20 * 1024 * 1024;
- EXPECT_LE(loader_->buffer_.forward_capacity(), kMaxBufferCapacity);
- EXPECT_LE(loader_->buffer_.backward_capacity(), kMaxBufferCapacity);
- }
-
- MOCK_METHOD1(StartCallback, void(BufferedResourceLoader::Status));
- MOCK_METHOD2(ReadCallback, void(BufferedResourceLoader::Status, int));
- MOCK_METHOD1(LoadingCallback, void(BufferedResourceLoader::LoadingState));
- MOCK_METHOD1(ProgressCallback, void(int64));
-
- protected:
- GURL gurl_;
- int64 first_position_;
- int64 last_position_;
-
- scoped_ptr<BufferedResourceLoader> loader_;
- NiceMock<MockWebURLLoader>* url_loader_;
-
- MockWebFrameClient client_;
- WebView* view_;
- WebLocalFrame* frame_;
-
- base::MessageLoop message_loop_;
-
- uint8 data_[kDataSize];
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoaderTest);
-};
-
-TEST_F(BufferedResourceLoaderTest, StartStop) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- StopWhenLoad();
-}
-
-// Tests that a bad HTTP response is recived, e.g. file not found.
-TEST_F(BufferedResourceLoaderTest, BadHttpResponse) {
- Initialize(kHttpUrl, -1, -1);
- Start();
-
- EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
-
- WebURLResponse response(gurl_);
- response.setHTTPStatusCode(404);
- response.setHTTPStatusText("Not Found\n");
- loader_->didReceiveResponse(url_loader_, response);
- StopWhenLoad();
-}
-
-// Tests that partial content is requested but not fulfilled.
-TEST_F(BufferedResourceLoaderTest, NotPartialResponse) {
- Initialize(kHttpUrl, 100, -1);
- Start();
- FullResponse(1024, BufferedResourceLoader::kFailed);
- StopWhenLoad();
-}
-
-// Tests that a 200 response is received.
-TEST_F(BufferedResourceLoaderTest, FullResponse) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- FullResponse(1024);
- StopWhenLoad();
-}
-
-// Tests that a partial content response is received.
-TEST_F(BufferedResourceLoaderTest, PartialResponse) {
- Initialize(kHttpUrl, 100, 200);
- Start();
- PartialResponse(100, 200, 1024);
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, PartialResponse_Chunked) {
- Initialize(kHttpUrl, 100, 200);
- Start();
- PartialResponse(100, 200, 1024, true, true);
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, PartialResponse_NoAcceptRanges) {
- Initialize(kHttpUrl, 100, 200);
- Start();
- PartialResponse(100, 200, 1024, false, false);
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, PartialResponse_ChunkedNoAcceptRanges) {
- Initialize(kHttpUrl, 100, 200);
- Start();
- PartialResponse(100, 200, 1024, true, false);
- StopWhenLoad();
-}
-
-// Tests that an invalid partial response is received.
-TEST_F(BufferedResourceLoaderTest, InvalidPartialResponse) {
- Initialize(kHttpUrl, 0, 10);
- Start();
-
- EXPECT_CALL(*this, StartCallback(BufferedResourceLoader::kFailed));
-
- WebURLResponse response(gurl_);
- response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
- WebString::fromUTF8(base::StringPrintf("bytes "
- "%d-%d/%d", 1, 10, 1024)));
- response.setExpectedContentLength(10);
- response.setHTTPStatusCode(kHttpPartialContent);
- loader_->didReceiveResponse(url_loader_, response);
- StopWhenLoad();
-}
-
-// Tests the logic of sliding window for data buffering and reading.
-TEST_F(BufferedResourceLoaderTest, BufferAndRead) {
- Initialize(kHttpUrl, 10, 29);
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kCapacityDefer);
- Start();
- PartialResponse(10, 29, 30);
-
- uint8 buffer[10];
- InSequence s;
-
- // Writes 10 bytes and read them back.
- WriteLoader(10, 10);
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- ReadLoader(10, 10, buffer);
- VerifyBuffer(buffer, 10, 10);
-
- // Writes 10 bytes and read 2 times.
- WriteLoader(20, 10);
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
- ReadLoader(20, 5, buffer);
- VerifyBuffer(buffer, 20, 5);
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
- ReadLoader(25, 5, buffer);
- VerifyBuffer(buffer, 25, 5);
-
- // Read backward within buffer.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- ReadLoader(10, 10, buffer);
- VerifyBuffer(buffer, 10, 10);
-
- // Read backward outside buffer.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(9, 10, buffer);
-
- // Response has completed.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
- loader_->didFinishLoading(url_loader_, 0, -1);
-
- // Try to read 10 from position 25 will just return with 5 bytes.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
- ReadLoader(25, 10, buffer);
- VerifyBuffer(buffer, 25, 5);
-
- // Try to read outside buffered range after request has completed.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(5, 10, buffer);
-
- // Try to read beyond the instance size.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 0));
- ReadLoader(30, 10, buffer);
-}
-
-// Tests the logic of expanding the data buffer for large reads.
-TEST_F(BufferedResourceLoaderTest, ReadExtendBuffer) {
- Initialize(kHttpUrl, 10, 0x014FFFFFF);
- SetLoaderBuffer(10, 20);
- Start();
- PartialResponse(10, 0x014FFFFFF, 0x015000000);
-
- uint8 buffer[20];
- InSequence s;
-
- // Write more than forward capacity and read it back. Ensure forward capacity
- // gets reset after reading.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
- WriteLoader(10, 20);
-
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(10, 20, buffer);
-
- VerifyBuffer(buffer, 10, 20);
- ConfirmLoaderBufferForwardCapacity(10);
-
- // Make and outstanding read request larger than forward capacity. Ensure
- // forward capacity gets extended.
- ReadLoader(30, 20, buffer);
- ConfirmLoaderBufferForwardCapacity(20);
-
- // Fulfill outstanding request. Ensure forward capacity gets reset.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 20));
- WriteLoader(30, 20);
-
- VerifyBuffer(buffer, 30, 20);
- ConfirmLoaderBufferForwardCapacity(10);
-
- // Try to read further ahead than kForwardWaitThreshold allows. Ensure
- // forward capacity is not changed.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(0x00300000, 1, buffer);
-
- ConfirmLoaderBufferForwardCapacity(10);
-
- // Try to read more than maximum forward capacity. Ensure forward capacity is
- // not changed.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
- ReadLoader(30, 0x01400001, buffer);
-
- ConfirmLoaderBufferForwardCapacity(10);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, ReadOutsideBuffer) {
- Initialize(kHttpUrl, 10, 0x00FFFFFF);
- Start();
- PartialResponse(10, 0x00FFFFFF, 0x01000000);
-
- uint8 buffer[10];
- InSequence s;
-
- // Read very far ahead will get a cache miss.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(0x00FFFFFF, 1, buffer);
-
- // The following call will not call ReadCallback() because it is waiting for
- // data to arrive.
- ReadLoader(10, 10, buffer);
-
- // Writing to loader will fulfill the read request.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- WriteLoader(10, 20);
- VerifyBuffer(buffer, 10, 10);
-
- // The following call cannot be fulfilled now.
- ReadLoader(25, 10, buffer);
-
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFinished));
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 5));
- loader_->didFinishLoading(url_loader_, 0, -1);
-}
-
-TEST_F(BufferedResourceLoaderTest, RequestFailedWhenRead) {
- Initialize(kHttpUrl, 10, 29);
- Start();
- PartialResponse(10, 29, 30);
-
- uint8 buffer[10];
- InSequence s;
-
- // We should convert any error we receive to BufferedResourceLoader::kFailed.
- ReadLoader(10, 10, buffer);
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
- WebURLError error;
- error.reason = net::ERR_TIMED_OUT;
- error.isCancellation = false;
- loader_->didFail(url_loader_, error);
-}
-
-TEST_F(BufferedResourceLoaderTest, RequestFailedWithNoPendingReads) {
- Initialize(kHttpUrl, 10, 29);
- Start();
- PartialResponse(10, 29, 30);
-
- uint8 buffer[10];
- InSequence s;
-
- // Write enough data so that a read would technically complete had the request
- // not failed.
- WriteLoader(10, 20);
-
- // Fail without a pending read.
- WebURLError error;
- error.reason = net::ERR_TIMED_OUT;
- error.isCancellation = false;
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
- loader_->didFail(url_loader_, error);
-
- // Now we should immediately fail any read even if we have data buffered.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
- ReadLoader(10, 10, buffer);
-}
-
-TEST_F(BufferedResourceLoaderTest, RequestCancelledWhenRead) {
- Initialize(kHttpUrl, 10, 29);
- Start();
- PartialResponse(10, 29, 30);
-
- uint8 buffer[10];
- InSequence s;
-
- // We should convert any error we receive to BufferedResourceLoader::kFailed.
- ReadLoader(10, 10, buffer);
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingFailed));
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kFailed, 0));
- WebURLError error;
- error.reason = 0;
- error.isCancellation = true;
- loader_->didFail(url_loader_, error);
-}
-
-// Tests the data buffering logic of NeverDefer strategy.
-TEST_F(BufferedResourceLoaderTest, NeverDeferStrategy) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 20);
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kNeverDefer);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[10];
-
- // Read past the buffer size; should not defer regardless.
- WriteLoader(10, 10);
- WriteLoader(20, 50);
-
- // Should move past window.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(10, 10, buffer);
-
- StopWhenLoad();
-}
-
-// Tests the data buffering logic of ReadThenDefer strategy.
-TEST_F(BufferedResourceLoaderTest, ReadThenDeferStrategy) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 20);
- loader_->UpdateDeferStrategy(BufferedResourceLoader::kReadThenDefer);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[10];
-
- // Make an outstanding read request.
- ReadLoader(10, 10, buffer);
-
- // Receive almost enough data to cover, shouldn't defer.
- WriteLoader(10, 9);
-
- // As soon as we have received enough data to fulfill the read, defer.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- WriteLoader(19, 1);
-
- VerifyBuffer(buffer, 10, 10);
-
- // Read again which should disable deferring since there should be nothing
- // left in our internal buffer.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(20, 10, buffer);
-
- // Over-fulfill requested bytes, then deferring should be enabled again.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- WriteLoader(20, 40);
-
- VerifyBuffer(buffer, 20, 10);
-
- // Read far ahead, which should disable deferring. In this case we still have
- // bytes in our internal buffer.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(80, 10, buffer);
-
- // Fulfill requested bytes, then deferring should be enabled again.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- WriteLoader(60, 40);
-
- VerifyBuffer(buffer, 80, 10);
-
- StopWhenLoad();
-}
-
-// Tests the data buffering logic of kCapacityDefer strategy.
-TEST_F(BufferedResourceLoaderTest, ThresholdDeferStrategy) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 20);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[10];
- InSequence s;
-
- // Write half of capacity: keep not deferring.
- WriteData(5);
-
- // Write rest of space until capacity: start deferring.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
- WriteData(5);
-
- // Read a byte from the buffer: stop deferring.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1));
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(10, 1, buffer);
-
- // Write a byte to hit capacity: start deferring.
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoadingDeferred));
- WriteData(6);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, Tricky_ReadForwardsPastBuffered) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 10);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[256];
- InSequence s;
-
- // PRECONDITION
- WriteUntilThreshold();
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 1));
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(10, 1, buffer);
- ConfirmBufferState(1, 10, 9, 10);
- ConfirmLoaderOffsets(11, 0, 0);
-
- // *** TRICKY BUSINESS, PT. I ***
- // Read past buffered: stop deferring.
- //
- // In order for the read to complete we must:
- // 1) Stop deferring to receive more data.
- //
- // BEFORE
- // offset=11 [xxxxxxxxx_]
- // ^ ^^^ requested 4 bytes @ offset 20
- // AFTER
- // offset=24 [__________]
- //
- ReadLoader(20, 4, buffer);
-
- // Write a little, make sure we didn't start deferring.
- WriteData(2);
-
- // Write the rest, read should complete.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
- WriteData(2);
-
- // POSTCONDITION
- ConfirmBufferState(4, 10, 0, 10);
- ConfirmLoaderOffsets(24, 0, 0);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, Tricky_ReadBackwardsPastBuffered) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 10);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[256];
- InSequence s;
-
- // PRECONDITION
- WriteUntilThreshold();
- ConfirmBufferState(0, 10, 10, 10);
- ConfirmLoaderOffsets(10, 0, 0);
-
- // *** TRICKY BUSINESS, PT. II ***
- // Read backwards a little too much: cache miss.
- //
- // BEFORE
- // offset=10 [__________|xxxxxxxxxx]
- // ^ ^^^ requested 10 bytes @ offset 9
- // AFTER
- // offset=10 [__________|xxxxxxxxxx] !!! cache miss !!!
- //
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(9, 4, buffer);
-
- // POSTCONDITION
- ConfirmBufferState(0, 10, 10, 10);
- ConfirmLoaderOffsets(10, 0, 0);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, Tricky_SmallReadWithinThreshold) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 10);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[256];
- InSequence s;
-
- // PRECONDITION
- WriteUntilThreshold();
- ConfirmBufferState(0, 10, 10, 10);
- ConfirmLoaderOffsets(10, 0, 0);
-
- // *** TRICKY BUSINESS, PT. III ***
- // Read past forward capacity but within capacity: stop deferring.
- //
- // In order for the read to complete we must:
- // 1) Adjust offset forward to create capacity.
- // 2) Stop deferring to receive more data.
- //
- // BEFORE
- // offset=10 [xxxxxxxxxx]
- // ^^^^ requested 4 bytes @ offset 24
- // ADJUSTED OFFSET
- // offset=20 [__________]
- // ^^^^ requested 4 bytes @ offset 24
- // AFTER
- // offset=28 [__________]
- //
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(24, 4, buffer);
- ConfirmLoaderOffsets(20, 4, 8);
-
- // Write a little, make sure we didn't start deferring.
- WriteData(4);
-
- // Write the rest, read should complete.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 4));
- WriteData(4);
-
- // POSTCONDITION
- ConfirmBufferState(8, 10, 0, 10);
- ConfirmLoaderOffsets(28, 0, 0);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadWithinThreshold) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 10);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[256];
- InSequence s;
-
- // PRECONDITION
- WriteUntilThreshold();
- ConfirmBufferState(0, 10, 10, 10);
- ConfirmLoaderOffsets(10, 0, 0);
-
- // *** TRICKY BUSINESS, PT. IV ***
- // Read a large amount past forward capacity but within
- // capacity: stop deferring.
- //
- // In order for the read to complete we must:
- // 1) Adjust offset forward to create capacity.
- // 2) Expand capacity to make sure we don't defer as data arrives.
- // 3) Stop deferring to receive more data.
- //
- // BEFORE
- // offset=10 [xxxxxxxxxx]
- // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
- // ADJUSTED OFFSET
- // offset=20 [__________]
- // ^^^^^^ ^^^^^^ requested 12 bytes @ offset 24
- // ADJUSTED CAPACITY
- // offset=20 [________________]
- // ^^^^^^^^^^^^ requested 12 bytes @ offset 24
- // AFTER
- // offset=36 [__________]
- //
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(24, 12, buffer);
- ConfirmLoaderOffsets(20, 4, 16);
- ConfirmBufferState(10, 10, 0, 16);
-
- // Write a little, make sure we didn't start deferring.
- WriteData(10);
-
- // Write the rest, read should complete and capacity should go back to normal.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 12));
- WriteData(6);
- ConfirmLoaderBufferForwardCapacity(10);
-
- // POSTCONDITION
- ConfirmBufferState(6, 10, 0, 10);
- ConfirmLoaderOffsets(36, 0, 0);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, Tricky_LargeReadBackwards) {
- Initialize(kHttpUrl, 10, 99);
- SetLoaderBuffer(10, 10);
- Start();
- PartialResponse(10, 99, 100);
-
- uint8 buffer[256];
- InSequence s;
-
- // PRECONDITION
- WriteUntilThreshold();
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 10));
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(10, 10, buffer);
- WriteUntilThreshold();
- ConfirmBufferState(10, 10, 10, 10);
- ConfirmLoaderOffsets(20, 0, 0);
-
- // *** TRICKY BUSINESS, PT. V ***
- // Read a large amount that involves backwards data: stop deferring.
- //
- // In order for the read to complete we must:
- // 1) Adjust offset *backwards* to create capacity.
- // 2) Expand capacity to make sure we don't defer as data arrives.
- // 3) Stop deferring to receive more data.
- //
- // BEFORE
- // offset=20 [xxxxxxxxxx|xxxxxxxxxx]
- // ^^^^ ^^^^^^^^^^ ^^^^ requested 18 bytes @ offset 16
- // ADJUSTED OFFSET
- // offset=16 [____xxxxxx|xxxxxxxxxx]xxxx
- // ^^^^^^^^^^ ^^^^^^^^ requested 18 bytes @ offset 16
- // ADJUSTED CAPACITY
- // offset=16 [____xxxxxx|xxxxxxxxxxxxxx____]
- // ^^^^^^^^^^^^^^^^^^ requested 18 bytes @ offset 16
- // AFTER
- // offset=34 [xxxxxxxxxx|__________]
- //
- EXPECT_CALL(*this, LoadingCallback(BufferedResourceLoader::kLoading));
- ReadLoader(16, 18, buffer);
- ConfirmLoaderOffsets(16, 0, 18);
- ConfirmBufferState(6, 10, 14, 18);
-
- // Write a little, make sure we didn't start deferring.
- WriteData(2);
-
- // Write the rest, read should complete and capacity should go back to normal.
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kOk, 18));
- WriteData(2);
- ConfirmLoaderBufferForwardCapacity(10);
-
- // POSTCONDITION
- ConfirmBufferState(4, 10, 0, 10);
- ConfirmLoaderOffsets(34, 0, 0);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, Tricky_ReadPastThreshold) {
- const int kSize = 5 * 1024 * 1024;
- const int kThreshold = 2 * 1024 * 1024;
-
- Initialize(kHttpUrl, 10, kSize);
- SetLoaderBuffer(10, 10);
- Start();
- PartialResponse(10, kSize - 1, kSize);
-
- uint8 buffer[256];
- InSequence s;
-
- // PRECONDITION
- WriteUntilThreshold();
- ConfirmBufferState(0, 10, 10, 10);
- ConfirmLoaderOffsets(10, 0, 0);
-
- // *** TRICKY BUSINESS, PT. VI ***
- // Read past the forward wait threshold: cache miss.
- //
- // BEFORE
- // offset=10 [xxxxxxxxxx] ...
- // ^^^^ requested 10 bytes @ threshold
- // AFTER
- // offset=10 [xxxxxxxxxx] !!! cache miss !!!
- //
- EXPECT_CALL(*this, ReadCallback(BufferedResourceLoader::kCacheMiss, 0));
- ReadLoader(kThreshold + 20, 10, buffer);
-
- // POSTCONDITION
- ConfirmBufferState(0, 10, 10, 10);
- ConfirmLoaderOffsets(10, 0, 0);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, HasSingleOrigin) {
- // Make sure no redirect case works as expected.
- Initialize(kHttpUrl, -1, -1);
- Start();
- FullResponse(1024);
- EXPECT_TRUE(loader_->HasSingleOrigin());
- StopWhenLoad();
-
- // Test redirect to the same domain.
- Initialize(kHttpUrl, -1, -1);
- Start();
- Redirect(kHttpRedirectToSameDomainUrl1);
- FullResponse(1024);
- EXPECT_TRUE(loader_->HasSingleOrigin());
- StopWhenLoad();
-
- // Test redirect twice to the same domain.
- Initialize(kHttpUrl, -1, -1);
- Start();
- Redirect(kHttpRedirectToSameDomainUrl1);
- Redirect(kHttpRedirectToSameDomainUrl2);
- FullResponse(1024);
- EXPECT_TRUE(loader_->HasSingleOrigin());
- StopWhenLoad();
-
- // Test redirect to a different domain.
- Initialize(kHttpUrl, -1, -1);
- Start();
- Redirect(kHttpRedirectToDifferentDomainUrl1);
- FullResponse(1024);
- EXPECT_FALSE(loader_->HasSingleOrigin());
- StopWhenLoad();
-
- // Test redirect to the same domain and then to a different domain.
- Initialize(kHttpUrl, -1, -1);
- Start();
- Redirect(kHttpRedirectToSameDomainUrl1);
- Redirect(kHttpRedirectToDifferentDomainUrl1);
- FullResponse(1024);
- EXPECT_FALSE(loader_->HasSingleOrigin());
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_Default) {
- Initialize(kHttpUrl, -1, -1);
- Start();
-
- // Test ensures that default construction of a BufferedResourceLoader has sane
- // values.
- //
- // Please do not change these values in order to make a test pass! Instead,
- // start a conversation on what the default buffer window capacities should
- // be.
- ConfirmLoaderBufferBackwardCapacity(2 * 1024 * 1024);
- ConfirmLoaderBufferForwardCapacity(2 * 1024 * 1024);
-
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_Unknown) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetBitrate(0);
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_BelowLowerBound) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetBitrate(1024 * 8); // 1 Kbps.
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_WithinBounds) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetBitrate(2 * 1024 * 1024 * 8); // 2 Mbps.
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_Bitrate_AboveUpperBound) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetBitrate(100 * 1024 * 1024 * 8); // 100 Mbps.
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Negative) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetPlaybackRate(-10);
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_Zero) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetPlaybackRate(0);
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_BelowLowerBound) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetPlaybackRate(0.1f);
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_WithinBounds) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetPlaybackRate(10);
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-TEST_F(BufferedResourceLoaderTest, BufferWindow_PlaybackRate_AboveUpperBound) {
- Initialize(kHttpUrl, -1, -1);
- Start();
- loader_->SetPlaybackRate(100);
- CheckBufferWindowBounds();
- StopWhenLoad();
-}
-
-static void ExpectContentRange(
- const std::string& str, bool expect_success,
- int64 expected_first, int64 expected_last, int64 expected_size) {
- int64 first, last, size;
- ASSERT_EQ(expect_success, BufferedResourceLoader::ParseContentRange(
- str, &first, &last, &size)) << str;
- if (!expect_success)
- return;
- EXPECT_EQ(first, expected_first);
- EXPECT_EQ(last, expected_last);
- EXPECT_EQ(size, expected_size);
-}
-
-static void ExpectContentRangeFailure(const std::string& str) {
- ExpectContentRange(str, false, 0, 0, 0);
-}
-
-static void ExpectContentRangeSuccess(
- const std::string& str,
- int64 expected_first, int64 expected_last, int64 expected_size) {
- ExpectContentRange(str, true, expected_first, expected_last, expected_size);
-}
-
-TEST(BufferedResourceLoaderStandaloneTest, ParseContentRange) {
- ExpectContentRangeFailure("cytes 0-499/500");
- ExpectContentRangeFailure("bytes 0499/500");
- ExpectContentRangeFailure("bytes 0-499500");
- ExpectContentRangeFailure("bytes 0-499/500-blorg");
- ExpectContentRangeFailure("bytes 0-499/500-1");
- ExpectContentRangeFailure("bytes 0-499/400");
- ExpectContentRangeFailure("bytes 0-/400");
- ExpectContentRangeFailure("bytes -300/400");
- ExpectContentRangeFailure("bytes 20-10/400");
-
- ExpectContentRangeSuccess("bytes 0-499/500", 0, 499, 500);
- ExpectContentRangeSuccess("bytes 0-0/500", 0, 0, 500);
- ExpectContentRangeSuccess("bytes 10-11/50", 10, 11, 50);
- ExpectContentRangeSuccess("bytes 10-11/*", 10, 11,
- kPositionNotSpecified);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/cache_util.cc b/chromium/content/renderer/media/cache_util.cc
deleted file mode 100644
index 2114ddd5189..00000000000
--- a/chromium/content/renderer/media/cache_util.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/cache_util.h"
-
-#include <string>
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/time/time.h"
-#include "net/http/http_util.h"
-#include "net/http/http_version.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-
-using base::Time;
-using base::TimeDelta;
-using net::HttpVersion;
-using blink::WebURLResponse;
-
-namespace content {
-
-enum { kHttpOK = 200, kHttpPartialContent = 206 };
-
-uint32 GetReasonsForUncacheability(const WebURLResponse& response) {
- uint32 reasons = 0;
- const int code = response.httpStatusCode();
- const int version = response.httpVersion();
- const HttpVersion http_version =
- version == WebURLResponse::HTTP_1_1 ? HttpVersion(1, 1) :
- version == WebURLResponse::HTTP_1_0 ? HttpVersion(1, 0) :
- version == WebURLResponse::HTTP_0_9 ? HttpVersion(0, 9) :
- HttpVersion();
- if (code != kHttpOK && code != kHttpPartialContent)
- reasons |= kNoData;
- if (http_version < HttpVersion(1, 1) && code == kHttpPartialContent)
- reasons |= kPre11PartialResponse;
- if (code == kHttpPartialContent &&
- !net::HttpUtil::HasStrongValidators(
- http_version,
- response.httpHeaderField("etag").utf8(),
- response.httpHeaderField("Last-Modified").utf8(),
- response.httpHeaderField("Date").utf8())) {
- reasons |= kNoStrongValidatorOnPartialResponse;
- }
-
- std::string cache_control_header =
- response.httpHeaderField("cache-control").utf8();
- StringToLowerASCII(&cache_control_header);
- if (cache_control_header.find("no-cache") != std::string::npos)
- reasons |= kNoCache;
- if (cache_control_header.find("no-store") != std::string::npos)
- reasons |= kNoStore;
- if (cache_control_header.find("must-revalidate") != std::string::npos)
- reasons |= kHasMustRevalidate;
-
- const TimeDelta kMinimumAgeForUsefulness =
- TimeDelta::FromSeconds(3600); // Arbitrary value.
-
- const char kMaxAgePrefix[] = "max-age=";
- const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1;
- if (cache_control_header.substr(0, kMaxAgePrefixLen) == kMaxAgePrefix) {
- int64 max_age_seconds;
- base::StringToInt64(
- base::StringPiece(cache_control_header.begin() + kMaxAgePrefixLen,
- cache_control_header.end()),
- &max_age_seconds);
- if (TimeDelta::FromSeconds(max_age_seconds) < kMinimumAgeForUsefulness)
- reasons |= kShortMaxAge;
- }
-
- Time date;
- Time expires;
- if (Time::FromString(response.httpHeaderField("Date").utf8().data(), &date) &&
- Time::FromString(response.httpHeaderField("Expires").utf8().data(),
- &expires) &&
- date > Time() && expires > Time() &&
- (expires - date) < kMinimumAgeForUsefulness) {
- reasons |= kExpiresTooSoon;
- }
-
- return reasons;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/cache_util.h b/chromium/content/renderer/media/cache_util.h
deleted file mode 100644
index aca8d8a9081..00000000000
--- a/chromium/content/renderer/media/cache_util.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_CACHE_UTIL_H_
-#define CONTENT_RENDERER_MEDIA_CACHE_UTIL_H_
-
-#include <vector>
-
-#include "base/basictypes.h"
-#include "content/common/content_export.h"
-
-namespace blink {
-class WebURLResponse;
-}
-
-namespace content {
-
-// Reasons that a cached WebURLResponse will *not* prevent a future request to
-// the server. Reported via UMA, so don't change/reuse previously-existing
-// values.
-enum UncacheableReason {
- kNoData = 1 << 0, // Not 200 or 206.
- kPre11PartialResponse = 1 << 1, // 206 but HTTP version < 1.1.
- kNoStrongValidatorOnPartialResponse = 1 << 2, // 206, no strong validator.
- kShortMaxAge = 1 << 3, // Max age less than 1h (arbitrary value).
- kExpiresTooSoon = 1 << 4, // Expires in less than 1h (arbitrary value).
- kHasMustRevalidate = 1 << 5, // Response asks for revalidation.
- kNoCache = 1 << 6, // Response included a no-cache header.
- kNoStore = 1 << 7, // Response included a no-store header.
- kMaxReason // Needs to be one more than max legitimate reason.
-};
-
-// Return the logical OR of the reasons "response" cannot be used for a future
-// request (using the disk cache), or 0 if it might be useful.
-uint32 CONTENT_EXPORT GetReasonsForUncacheability(
- const blink::WebURLResponse& response);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_CACHE_UTIL_H_
diff --git a/chromium/content/renderer/media/cache_util_unittest.cc b/chromium/content/renderer/media/cache_util_unittest.cc
deleted file mode 100644
index 2db66b94baa..00000000000
--- a/chromium/content/renderer/media/cache_util_unittest.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/cache_util.h"
-
-#include <string>
-
-#include "base/format_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-
-using blink::WebString;
-using blink::WebURLResponse;
-
-namespace content {
-
-// Inputs & expected output for GetReasonsForUncacheability.
-struct GRFUTestCase {
- WebURLResponse::HTTPVersion version;
- int status_code;
- const char* headers;
- uint32 expected_reasons;
-};
-
-// Create a new WebURLResponse object.
-static WebURLResponse CreateResponse(const GRFUTestCase& test) {
- WebURLResponse response;
- response.initialize();
- response.setHTTPVersion(test.version);
- response.setHTTPStatusCode(test.status_code);
- std::vector<std::string> lines;
- Tokenize(test.headers, "\n", &lines);
- for (size_t i = 0; i < lines.size(); ++i) {
- size_t colon = lines[i].find(": ");
- response.addHTTPHeaderField(
- WebString::fromUTF8(lines[i].substr(0, colon)),
- WebString::fromUTF8(lines[i].substr(colon + 2)));
- }
- return response;
-}
-
-TEST(CacheUtilTest, GetReasonsForUncacheability) {
- enum { kNoReasons = 0 };
-
- const GRFUTestCase tests[] = {
- {
- WebURLResponse::HTTP_1_1, 206, "ETag: 'fooblort'", kNoReasons
- },
- {
- WebURLResponse::HTTP_1_1, 206, "", kNoStrongValidatorOnPartialResponse
- },
- {
- WebURLResponse::HTTP_1_0, 206, "",
- kPre11PartialResponse | kNoStrongValidatorOnPartialResponse
- },
- {
- WebURLResponse::HTTP_1_1, 200, "cache-control: max-Age=42", kShortMaxAge
- },
- {
- WebURLResponse::HTTP_1_1, 200, "cache-control: max-Age=4200", kNoReasons
- },
- {
- WebURLResponse::HTTP_1_1, 200,
- "Date: Tue, 22 May 2012 23:46:08 GMT\n"
- "Expires: Tue, 22 May 2012 23:56:08 GMT", kExpiresTooSoon
- },
- {
- WebURLResponse::HTTP_1_1, 200, "cache-control: must-revalidate",
- kHasMustRevalidate
- },
- {
- WebURLResponse::HTTP_1_1, 200, "cache-control: no-cache", kNoCache
- },
- {
- WebURLResponse::HTTP_1_1, 200, "cache-control: no-store", kNoStore
- },
- {
- WebURLResponse::HTTP_1_1, 200,
- "cache-control: no-cache\ncache-control: no-store", kNoCache | kNoStore
- },
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- SCOPED_TRACE(base::StringPrintf("case: %" PRIuS
- ", version: %d, code: %d, headers: %s",
- i, tests[i].version, tests[i].status_code,
- tests[i].headers));
- EXPECT_EQ(GetReasonsForUncacheability(CreateResponse(tests[i])),
- tests[i].expected_reasons);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/cdm_session_adapter.cc b/chromium/content/renderer/media/cdm_session_adapter.cc
index 5550c4470b7..276bb3e3f2d 100644
--- a/chromium/content/renderer/media/cdm_session_adapter.cc
+++ b/chromium/content/renderer/media/cdm_session_adapter.cc
@@ -8,62 +8,70 @@
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/stl_util.h"
-#include "content/renderer/media/crypto/content_decryption_module_factory.h"
+#include "content/renderer/media/crypto/key_systems.h"
#include "content/renderer/media/webcontentdecryptionmodulesession_impl.h"
+#include "media/base/cdm_factory.h"
#include "media/base/cdm_promise.h"
#include "media/base/media_keys.h"
#include "url/gurl.h"
namespace content {
-CdmSessionAdapter::CdmSessionAdapter() :
-#if defined(ENABLE_BROWSER_CDMS)
- cdm_id_(0),
-#endif
- weak_ptr_factory_(this) {}
+const char kMediaEME[] = "Media.EME.";
+const char kDot[] = ".";
+
+CdmSessionAdapter::CdmSessionAdapter() : weak_ptr_factory_(this) {
+}
CdmSessionAdapter::~CdmSessionAdapter() {}
-bool CdmSessionAdapter::Initialize(
-#if defined(ENABLE_PEPPER_CDMS)
- const CreatePepperCdmCB& create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
-#endif // defined(ENABLE_PEPPER_CDMS)
- const std::string& key_system,
- const GURL& security_origin) {
+bool CdmSessionAdapter::Initialize(media::CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const GURL& security_origin) {
+ // TODO(xhwang): This is why we need to include "key_systems.h". Move
+ // KeySystemNameForUMA out of src/content so we can move CdmSessionAdapter to
+ // src/media.
+ key_system_uma_prefix_ = kMediaEME + KeySystemNameForUMA(key_system) + kDot;
+
base::WeakPtr<CdmSessionAdapter> weak_this = weak_ptr_factory_.GetWeakPtr();
- media_keys_ = ContentDecryptionModuleFactory::Create(
+ media_keys_ = cdm_factory->Create(
key_system,
security_origin,
-#if defined(ENABLE_PEPPER_CDMS)
- create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- manager,
- &cdm_id_,
-#endif // defined(ENABLE_PEPPER_CDMS)
base::Bind(&CdmSessionAdapter::OnSessionMessage, weak_this),
base::Bind(&CdmSessionAdapter::OnSessionReady, weak_this),
base::Bind(&CdmSessionAdapter::OnSessionClosed, weak_this),
- base::Bind(&CdmSessionAdapter::OnSessionError, weak_this));
+ base::Bind(&CdmSessionAdapter::OnSessionError, weak_this),
+ base::Bind(&CdmSessionAdapter::OnSessionKeysChange, weak_this),
+ base::Bind(&CdmSessionAdapter::OnSessionExpirationUpdate, weak_this));
// Success if |media_keys_| created.
return media_keys_;
}
-WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::CreateSession(
- blink::WebContentDecryptionModuleSession::Client* client) {
- return new WebContentDecryptionModuleSessionImpl(client, this);
+void CdmSessionAdapter::SetServerCertificate(
+ const uint8* server_certificate,
+ int server_certificate_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ media_keys_->SetServerCertificate(
+ server_certificate, server_certificate_length, promise.Pass());
}
-void CdmSessionAdapter::RegisterSession(
+WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::CreateSession() {
+ return new WebContentDecryptionModuleSessionImpl(this);
+}
+
+bool CdmSessionAdapter::RegisterSession(
const std::string& web_session_id,
base::WeakPtr<WebContentDecryptionModuleSessionImpl> session) {
- DCHECK(!ContainsKey(sessions_, web_session_id));
+ // If this session ID is already registered, don't register it again.
+ if (ContainsKey(sessions_, web_session_id))
+ return false;
+
sessions_[web_session_id] = session;
+ return true;
}
-void CdmSessionAdapter::RemoveSession(const std::string& web_session_id) {
+void CdmSessionAdapter::UnregisterSession(const std::string& web_session_id) {
DCHECK(ContainsKey(sessions_, web_session_id));
sessions_.erase(web_session_id);
}
@@ -81,6 +89,12 @@ void CdmSessionAdapter::InitializeNewSession(
promise.Pass());
}
+void CdmSessionAdapter::LoadSession(
+ const std::string& web_session_id,
+ scoped_ptr<media::NewSessionCdmPromise> promise) {
+ media_keys_->LoadSession(web_session_id, promise.Pass());
+}
+
void CdmSessionAdapter::UpdateSession(
const std::string& web_session_id,
const uint8* response,
@@ -90,19 +104,35 @@ void CdmSessionAdapter::UpdateSession(
web_session_id, response, response_length, promise.Pass());
}
-void CdmSessionAdapter::ReleaseSession(
+void CdmSessionAdapter::CloseSession(
const std::string& web_session_id,
scoped_ptr<media::SimpleCdmPromise> promise) {
- media_keys_->ReleaseSession(web_session_id, promise.Pass());
+ media_keys_->CloseSession(web_session_id, promise.Pass());
+}
+
+void CdmSessionAdapter::RemoveSession(
+ const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ media_keys_->RemoveSession(web_session_id, promise.Pass());
+}
+
+void CdmSessionAdapter::GetUsableKeyIds(
+ const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise) {
+ media_keys_->GetUsableKeyIds(web_session_id, promise.Pass());
}
media::Decryptor* CdmSessionAdapter::GetDecryptor() {
return media_keys_->GetDecryptor();
}
+const std::string& CdmSessionAdapter::GetKeySystemUMAPrefix() const {
+ return key_system_uma_prefix_;
+}
+
#if defined(ENABLE_BROWSER_CDMS)
int CdmSessionAdapter::GetCdmId() const {
- return cdm_id_;
+ return media_keys_->GetCdmId();
}
#endif // defined(ENABLE_BROWSER_CDMS)
@@ -116,12 +146,28 @@ void CdmSessionAdapter::OnSessionMessage(const std::string& web_session_id,
session->OnSessionMessage(message, destination_url);
}
-void CdmSessionAdapter::OnSessionReady(const std::string& web_session_id) {
+void CdmSessionAdapter::OnSessionKeysChange(const std::string& web_session_id,
+ bool has_additional_usable_key) {
+ WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
+ DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
+ << web_session_id;
+ if (session)
+ session->OnSessionKeysChange(has_additional_usable_key);
+}
+
+void CdmSessionAdapter::OnSessionExpirationUpdate(
+ const std::string& web_session_id,
+ const base::Time& new_expiry_time) {
WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
<< web_session_id;
if (session)
- session->OnSessionReady();
+ session->OnSessionExpirationUpdate(new_expiry_time);
+}
+
+void CdmSessionAdapter::OnSessionReady(const std::string& web_session_id) {
+ // Ready events not used by unprefixed EME.
+ // TODO(jrummell): Remove when prefixed EME removed.
}
void CdmSessionAdapter::OnSessionClosed(const std::string& web_session_id) {
@@ -137,11 +183,8 @@ void CdmSessionAdapter::OnSessionError(
media::MediaKeys::Exception exception_code,
uint32 system_code,
const std::string& error_message) {
- WebContentDecryptionModuleSessionImpl* session = GetSession(web_session_id);
- DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session "
- << web_session_id;
- if (session)
- session->OnSessionError(exception_code, system_code, error_message);
+ // Error events not used by unprefixed EME.
+ // TODO(jrummell): Remove when prefixed EME removed.
}
WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::GetSession(
diff --git a/chromium/content/renderer/media/cdm_session_adapter.h b/chromium/content/renderer/media/cdm_session_adapter.h
index de27125db15..264067e98fc 100644
--- a/chromium/content/renderer/media/cdm_session_adapter.h
+++ b/chromium/content/renderer/media/cdm_session_adapter.h
@@ -15,17 +15,13 @@
#include "media/base/media_keys.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModuleSession.h"
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/pepper_cdm_wrapper.h"
-#endif
-
class GURL;
-namespace content {
+namespace media {
+class CdmFactory;
+}
-#if defined(ENABLE_BROWSER_CDMS)
-class RendererCdmManager;
-#endif
+namespace content {
class WebContentDecryptionModuleSessionImpl;
@@ -38,49 +34,62 @@ class CdmSessionAdapter : public base::RefCounted<CdmSessionAdapter> {
CdmSessionAdapter();
// Returns true on success.
- bool Initialize(
-#if defined(ENABLE_PEPPER_CDMS)
- const CreatePepperCdmCB& create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
-#endif
- const std::string& key_system,
- const GURL& security_origin);
+ bool Initialize(media::CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const GURL& security_origin);
+
+ // Provides a server certificate to be used to encrypt messages to the
+ // license server.
+ void SetServerCertificate(const uint8* server_certificate,
+ int server_certificate_length,
+ scoped_ptr<media::SimpleCdmPromise> promise);
// Creates a new session and adds it to the internal map. The caller owns the
// created session. RemoveSession() must be called when destroying it, if
// RegisterSession() was called.
- WebContentDecryptionModuleSessionImpl* CreateSession(
- blink::WebContentDecryptionModuleSession::Client* client);
+ WebContentDecryptionModuleSessionImpl* CreateSession();
// Adds a session to the internal map. Called once the session is successfully
- // initialized.
- void RegisterSession(
+ // initialized. Returns true if the session was registered, false if there is
+ // already an existing session with the same |web_session_id|.
+ bool RegisterSession(
const std::string& web_session_id,
base::WeakPtr<WebContentDecryptionModuleSessionImpl> session);
// Removes a session from the internal map.
- void RemoveSession(const std::string& web_session_id);
+ void UnregisterSession(const std::string& web_session_id);
// Initializes a session with the |init_data_type|, |init_data| and
- // |session_type| provided. Takes ownership of |promise|.
+ // |session_type| provided.
void InitializeNewSession(const std::string& init_data_type,
const uint8* init_data,
int init_data_length,
media::MediaKeys::SessionType session_type,
scoped_ptr<media::NewSessionCdmPromise> promise);
+ // Loads the session specified by |web_session_id|.
+ void LoadSession(const std::string& web_session_id,
+ scoped_ptr<media::NewSessionCdmPromise> promise);
+
// Updates the session specified by |web_session_id| with |response|.
- // Takes ownership of |promise|.
void UpdateSession(const std::string& web_session_id,
const uint8* response,
int response_length,
scoped_ptr<media::SimpleCdmPromise> promise);
- // Releases the session specified by |web_session_id|.
- // Takes ownership of |promise|.
- void ReleaseSession(const std::string& web_session_id,
- scoped_ptr<media::SimpleCdmPromise> promise);
+ // Closes the session specified by |web_session_id|.
+ void CloseSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise);
+
+ // Removes stored session data associated with the session specified by
+ // |web_session_id|.
+ void RemoveSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise);
+
+ // Retrieves the key IDs for keys in the session that the CDM knows are
+ // currently usable to decrypt media data.
+ void GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise);
// Returns the Decryptor associated with this CDM. May be NULL if no
// Decryptor is associated with the MediaKeys object.
@@ -88,6 +97,9 @@ class CdmSessionAdapter : public base::RefCounted<CdmSessionAdapter> {
// after WebContentDecryptionModule is freed. http://crbug.com/330324
media::Decryptor* GetDecryptor();
+ // Returns a prefix to use for UMAs.
+ const std::string& GetKeySystemUMAPrefix() const;
+
#if defined(ENABLE_BROWSER_CDMS)
// Returns the CDM ID associated with the |media_keys_|. May be kInvalidCdmId
// if no CDM ID is associated.
@@ -106,6 +118,10 @@ class CdmSessionAdapter : public base::RefCounted<CdmSessionAdapter> {
void OnSessionMessage(const std::string& web_session_id,
const std::vector<uint8>& message,
const GURL& destination_url);
+ void OnSessionKeysChange(const std::string& web_session_id,
+ bool has_additional_usable_key);
+ void OnSessionExpirationUpdate(const std::string& web_session_id,
+ const base::Time& new_expiry_time);
void OnSessionReady(const std::string& web_session_id);
void OnSessionClosed(const std::string& web_session_id);
void OnSessionError(const std::string& web_session_id,
@@ -121,9 +137,7 @@ class CdmSessionAdapter : public base::RefCounted<CdmSessionAdapter> {
SessionMap sessions_;
-#if defined(ENABLE_BROWSER_CDMS)
- int cdm_id_;
-#endif
+ std::string key_system_uma_prefix_;
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<CdmSessionAdapter> weak_ptr_factory_;
diff --git a/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc b/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc
deleted file mode 100644
index e56962f6811..00000000000
--- a/chromium/content/renderer/media/crypto/content_decryption_module_factory.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/crypto/content_decryption_module_factory.h"
-
-#include "base/logging.h"
-#include "content/renderer/media/crypto/key_systems.h"
-#include "media/cdm/aes_decryptor.h"
-#include "url/gurl.h"
-
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/ppapi_decryptor.h"
-#elif defined(ENABLE_BROWSER_CDMS)
-#include "content/renderer/media/crypto/proxy_media_keys.h"
-#include "content/renderer/media/crypto/renderer_cdm_manager.h"
-#endif // defined(ENABLE_PEPPER_CDMS)
-
-namespace content {
-
-scoped_ptr<media::MediaKeys> ContentDecryptionModuleFactory::Create(
- const std::string& key_system,
- const GURL& security_origin,
-#if defined(ENABLE_PEPPER_CDMS)
- const CreatePepperCdmCB& create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
- int* cdm_id,
-#endif // defined(ENABLE_PEPPER_CDMS)
- const media::SessionMessageCB& session_message_cb,
- const media::SessionReadyCB& session_ready_cb,
- const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb) {
- // TODO(jrummell): Pass |security_origin| to all constructors.
- // TODO(jrummell): Enable the following line once blink code updated to
- // check the security origin before calling.
- // DCHECK(security_origin.is_valid());
-
-#if defined(ENABLE_BROWSER_CDMS)
- *cdm_id = RendererCdmManager::kInvalidCdmId;
-#endif
-
- if (CanUseAesDecryptor(key_system)) {
- return scoped_ptr<media::MediaKeys>(
- new media::AesDecryptor(session_message_cb, session_closed_cb));
- }
-#if defined(ENABLE_PEPPER_CDMS)
- return scoped_ptr<media::MediaKeys>(
- PpapiDecryptor::Create(key_system,
- security_origin,
- create_pepper_cdm_cb,
- session_message_cb,
- session_ready_cb,
- session_closed_cb,
- session_error_cb));
-#elif defined(ENABLE_BROWSER_CDMS)
- scoped_ptr<ProxyMediaKeys> proxy_media_keys =
- ProxyMediaKeys::Create(key_system,
- security_origin,
- manager,
- session_message_cb,
- session_ready_cb,
- session_closed_cb,
- session_error_cb);
- if (proxy_media_keys)
- *cdm_id = proxy_media_keys->GetCdmId();
- return proxy_media_keys.PassAs<media::MediaKeys>();
-#else
- return scoped_ptr<media::MediaKeys>();
-#endif // defined(ENABLE_PEPPER_CDMS)
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/crypto/content_decryption_module_factory.h b/chromium/content/renderer/media/crypto/content_decryption_module_factory.h
deleted file mode 100644
index c18bf9d9b21..00000000000
--- a/chromium/content/renderer/media/crypto/content_decryption_module_factory.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_CRYPTO_CONTENT_DECRYPTION_MODULE_FACTORY_H_
-#define CONTENT_RENDERER_MEDIA_CRYPTO_CONTENT_DECRYPTION_MODULE_FACTORY_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "media/base/media_keys.h"
-
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/pepper_cdm_wrapper.h"
-#endif
-
-class GURL;
-
-namespace content {
-
-#if defined(ENABLE_BROWSER_CDMS)
-class RendererCdmManager;
-#endif
-
-class ContentDecryptionModuleFactory {
- public:
- // |create_pepper_cdm_cb| will be called synchronously if necessary. The other
- // callbacks can be called asynchronously.
- static scoped_ptr<media::MediaKeys> Create(
- const std::string& key_system,
- const GURL& security_origin,
-#if defined(ENABLE_PEPPER_CDMS)
- const CreatePepperCdmCB& create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
- int* cdm_id, // Output parameter indicating the CDM ID of the MediaKeys.
-#endif // defined(ENABLE_PEPPER_CDMS)
- const media::SessionMessageCB& session_message_cb,
- const media::SessionReadyCB& session_ready_cb,
- const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_CRYPTO_CONTENT_DECRYPTION_MODULE_FACTORY_H_
diff --git a/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc b/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc
new file mode 100644
index 00000000000..cf24056f14f
--- /dev/null
+++ b/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.cc
@@ -0,0 +1,475 @@
+// Copyright 2014 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 "content/renderer/media/crypto/encrypted_media_player_support_impl.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/metrics/histogram.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/media/crypto/key_systems.h"
+#include "content/renderer/media/crypto/render_cdm_factory.h"
+#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/blink/encrypted_media_player_support.h"
+#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h"
+#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
+
+#if defined(ENABLE_PEPPER_CDMS)
+#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
+#elif defined(ENABLE_BROWSER_CDMS)
+#error Browser side CDM in WMPI for prefixed EME API not supported yet.
+#endif
+
+using blink::WebMediaPlayer;
+using blink::WebMediaPlayerClient;
+using blink::WebString;
+
+namespace content {
+
+#define BIND_TO_RENDER_LOOP(function) \
+ (media::BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
+
+#define BIND_TO_RENDER_LOOP1(function, arg1) \
+ (media::BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
+
+// Prefix for histograms related to Encrypted Media Extensions.
+static const char* kMediaEme = "Media.EME.";
+
+// Used for calls to decryptor_ready_cb where the result can be ignored.
+static void DoNothing(bool success) {
+}
+
+// Convert a WebString to ASCII, falling back on an empty string in the case
+// of a non-ASCII string.
+static std::string ToASCIIOrEmpty(const WebString& string) {
+ return base::IsStringASCII(string) ? base::UTF16ToASCII(string)
+ : std::string();
+}
+
+// Helper functions to report media EME related stats to UMA. They follow the
+// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and
+// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
+// that UMA_* macros require the names to be constant throughout the process'
+// lifetime.
+static void EmeUMAHistogramEnumeration(const std::string& key_system,
+ const std::string& method,
+ int sample,
+ int boundary_value) {
+ base::LinearHistogram::FactoryGet(
+ kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
+ 1, boundary_value, boundary_value + 1,
+ base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
+}
+
+static void EmeUMAHistogramCounts(const std::string& key_system,
+ const std::string& method,
+ int sample) {
+ // Use the same parameters as UMA_HISTOGRAM_COUNTS.
+ base::Histogram::FactoryGet(
+ kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
+ 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
+}
+
+// Helper enum for reporting generateKeyRequest/addKey histograms.
+enum MediaKeyException {
+ kUnknownResultId,
+ kSuccess,
+ kKeySystemNotSupported,
+ kInvalidPlayerState,
+ kMaxMediaKeyException
+};
+
+static MediaKeyException MediaKeyExceptionForUMA(
+ WebMediaPlayer::MediaKeyException e) {
+ switch (e) {
+ case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
+ return kKeySystemNotSupported;
+ case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
+ return kInvalidPlayerState;
+ case WebMediaPlayer::MediaKeyExceptionNoError:
+ return kSuccess;
+ default:
+ return kUnknownResultId;
+ }
+}
+
+// Helper for converting |key_system| name and exception |e| to a pair of enum
+// values from above, for reporting to UMA.
+static void ReportMediaKeyExceptionToUMA(const std::string& method,
+ const std::string& key_system,
+ WebMediaPlayer::MediaKeyException e) {
+ MediaKeyException result_id = MediaKeyExceptionForUMA(e);
+ DCHECK_NE(result_id, kUnknownResultId) << e;
+ EmeUMAHistogramEnumeration(
+ key_system, method, result_id, kMaxMediaKeyException);
+}
+
+// Guess the type of |init_data|. This is only used to handle some corner cases
+// so we keep it as simple as possible without breaking major use cases.
+static std::string GuessInitDataType(const unsigned char* init_data,
+ unsigned init_data_length) {
+ // Most WebM files use KeyId of 16 bytes. CENC init data is always >16 bytes.
+ if (init_data_length == 16)
+ return "webm";
+
+ return "cenc";
+}
+
+scoped_ptr<media::EncryptedMediaPlayerSupport>
+EncryptedMediaPlayerSupportImpl::Create(blink::WebMediaPlayerClient* client) {
+ return scoped_ptr<EncryptedMediaPlayerSupport>(
+ new EncryptedMediaPlayerSupportImpl(client));
+}
+
+EncryptedMediaPlayerSupportImpl::EncryptedMediaPlayerSupportImpl(
+ blink::WebMediaPlayerClient* client)
+ : client_(client),
+ web_cdm_(NULL) {
+}
+
+EncryptedMediaPlayerSupportImpl::~EncryptedMediaPlayerSupportImpl() {
+}
+
+WebMediaPlayer::MediaKeyException
+EncryptedMediaPlayerSupportImpl::GenerateKeyRequest(
+ blink::WebLocalFrame* frame,
+ const WebString& key_system,
+ const unsigned char* init_data,
+ unsigned init_data_length) {
+ DVLOG(1) << "generateKeyRequest: " << base::string16(key_system) << ": "
+ << std::string(reinterpret_cast<const char*>(init_data),
+ static_cast<size_t>(init_data_length));
+
+ std::string ascii_key_system =
+ GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
+
+ WebMediaPlayer::MediaKeyException e =
+ GenerateKeyRequestInternal(frame, ascii_key_system, init_data,
+ init_data_length);
+ ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e);
+ return e;
+}
+
+WebMediaPlayer::MediaKeyException
+EncryptedMediaPlayerSupportImpl::GenerateKeyRequestInternal(
+ blink::WebLocalFrame* frame,
+ const std::string& key_system,
+ const unsigned char* init_data,
+ unsigned init_data_length) {
+ if (!IsConcreteSupportedKeySystem(key_system))
+ return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
+
+ // We do not support run-time switching between key systems for now.
+ if (current_key_system_.empty()) {
+ if (!proxy_decryptor_) {
+ proxy_decryptor_.reset(new ProxyDecryptor(
+ BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyAdded),
+ BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyError),
+ BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnKeyMessage)));
+ }
+
+ GURL security_origin(frame->document().securityOrigin().toString());
+
+#if defined(ENABLE_PEPPER_CDMS)
+ RenderCdmFactory cdm_factory(
+ base::Bind(&PepperCdmWrapperImpl::Create, frame));
+#else
+ RenderCdmFactory cdm_factory;
+#endif
+
+ if (!proxy_decryptor_->InitializeCDM(&cdm_factory, key_system,
+ security_origin)) {
+ return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
+ }
+
+ if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) {
+ base::ResetAndReturn(&decryptor_ready_cb_)
+ .Run(proxy_decryptor_->GetDecryptor(), base::Bind(DoNothing));
+ }
+
+ current_key_system_ = key_system;
+ } else if (key_system != current_key_system_) {
+ return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
+ }
+
+ std::string init_data_type = init_data_type_;
+ if (init_data_type.empty())
+ init_data_type = GuessInitDataType(init_data, init_data_length);
+
+ // TODO(xhwang): We assume all streams are from the same container (thus have
+ // the same "type") for now. In the future, the "type" should be passed down
+ // from the application.
+ if (!proxy_decryptor_->GenerateKeyRequest(
+ init_data_type, init_data, init_data_length)) {
+ current_key_system_.clear();
+ return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
+ }
+
+ return WebMediaPlayer::MediaKeyExceptionNoError;
+}
+
+WebMediaPlayer::MediaKeyException EncryptedMediaPlayerSupportImpl::AddKey(
+ const WebString& key_system,
+ const unsigned char* key,
+ unsigned key_length,
+ const unsigned char* init_data,
+ unsigned init_data_length,
+ const WebString& session_id) {
+ DVLOG(1) << "addKey: " << base::string16(key_system) << ": "
+ << std::string(reinterpret_cast<const char*>(key),
+ static_cast<size_t>(key_length)) << ", "
+ << std::string(reinterpret_cast<const char*>(init_data),
+ static_cast<size_t>(init_data_length)) << " ["
+ << base::string16(session_id) << "]";
+
+ std::string ascii_key_system =
+ GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
+ std::string ascii_session_id = ToASCIIOrEmpty(session_id);
+
+ WebMediaPlayer::MediaKeyException e = AddKeyInternal(ascii_key_system,
+ key,
+ key_length,
+ init_data,
+ init_data_length,
+ ascii_session_id);
+ ReportMediaKeyExceptionToUMA("addKey", ascii_key_system, e);
+ return e;
+}
+
+WebMediaPlayer::MediaKeyException
+EncryptedMediaPlayerSupportImpl::AddKeyInternal(
+ const std::string& key_system,
+ const unsigned char* key,
+ unsigned key_length,
+ const unsigned char* init_data,
+ unsigned init_data_length,
+ const std::string& session_id) {
+ DCHECK(key);
+ DCHECK_GT(key_length, 0u);
+
+ if (!IsConcreteSupportedKeySystem(key_system))
+ return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
+
+ if (current_key_system_.empty() || key_system != current_key_system_)
+ return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
+
+ proxy_decryptor_->AddKey(
+ key, key_length, init_data, init_data_length, session_id);
+ return WebMediaPlayer::MediaKeyExceptionNoError;
+}
+
+WebMediaPlayer::MediaKeyException
+EncryptedMediaPlayerSupportImpl::CancelKeyRequest(
+ const WebString& key_system,
+ const WebString& session_id) {
+ DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": "
+ << " [" << base::string16(session_id) << "]";
+
+ std::string ascii_key_system =
+ GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
+ std::string ascii_session_id = ToASCIIOrEmpty(session_id);
+
+ WebMediaPlayer::MediaKeyException e =
+ CancelKeyRequestInternal(ascii_key_system, ascii_session_id);
+ ReportMediaKeyExceptionToUMA("cancelKeyRequest", ascii_key_system, e);
+ return e;
+}
+
+WebMediaPlayer::MediaKeyException
+EncryptedMediaPlayerSupportImpl::CancelKeyRequestInternal(
+ const std::string& key_system,
+ const std::string& session_id) {
+ if (!IsConcreteSupportedKeySystem(key_system))
+ return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
+
+ if (current_key_system_.empty() || key_system != current_key_system_)
+ return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
+
+ proxy_decryptor_->CancelKeyRequest(session_id);
+ return WebMediaPlayer::MediaKeyExceptionNoError;
+}
+
+void EncryptedMediaPlayerSupportImpl::SetInitialContentDecryptionModule(
+ blink::WebContentDecryptionModule* initial_cdm) {
+ // Used when loading media and no pipeline/decoder attached yet.
+ DCHECK(decryptor_ready_cb_.is_null());
+
+ web_cdm_ = ToWebContentDecryptionModuleImpl(initial_cdm);
+}
+
+void EncryptedMediaPlayerSupportImpl::SetContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm) {
+ // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
+ if (!cdm)
+ return;
+
+ web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
+
+ if (web_cdm_ && !decryptor_ready_cb_.is_null())
+ base::ResetAndReturn(&decryptor_ready_cb_)
+ .Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing));
+}
+
+void EncryptedMediaPlayerSupportImpl::SetContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm,
+ blink::WebContentDecryptionModuleResult result) {
+ // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
+ if (!cdm) {
+ result.completeWithError(
+ blink::WebContentDecryptionModuleExceptionNotSupportedError,
+ 0,
+ "Null MediaKeys object is not supported.");
+ return;
+ }
+
+ web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
+
+ if (web_cdm_ && !decryptor_ready_cb_.is_null()) {
+ base::ResetAndReturn(&decryptor_ready_cb_)
+ .Run(web_cdm_->GetDecryptor(), BIND_TO_RENDER_LOOP1(
+ &EncryptedMediaPlayerSupportImpl::ContentDecryptionModuleAttached,
+ result));
+ } else {
+ // No pipeline/decoder connected, so resolve the promise. When something
+ // is connected, setting the CDM will happen in SetDecryptorReadyCB().
+ ContentDecryptionModuleAttached(result, true);
+ }
+}
+
+void EncryptedMediaPlayerSupportImpl::ContentDecryptionModuleAttached(
+ blink::WebContentDecryptionModuleResult result,
+ bool success) {
+ if (success) {
+ result.complete();
+ return;
+ }
+
+ result.completeWithError(
+ blink::WebContentDecryptionModuleExceptionNotSupportedError,
+ 0,
+ "Unable to set MediaKeys object");
+}
+
+media::SetDecryptorReadyCB
+EncryptedMediaPlayerSupportImpl::CreateSetDecryptorReadyCB() {
+ return BIND_TO_RENDER_LOOP(
+ &EncryptedMediaPlayerSupportImpl::SetDecryptorReadyCB);
+}
+
+media::Demuxer::NeedKeyCB
+EncryptedMediaPlayerSupportImpl::CreateNeedKeyCB() {
+ return BIND_TO_RENDER_LOOP(&EncryptedMediaPlayerSupportImpl::OnNeedKey);
+}
+
+void EncryptedMediaPlayerSupportImpl::OnPipelineDecryptError() {
+ EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1);
+}
+
+void EncryptedMediaPlayerSupportImpl::OnNeedKey(const std::string& type,
+ const std::vector<uint8>& init_data) {
+ // Do not fire NeedKey event if encrypted media is not enabled.
+ if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() &&
+ !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) {
+ return;
+ }
+
+ UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);
+
+ DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_);
+ if (init_data_type_.empty())
+ init_data_type_ = type;
+
+ const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
+ client_->encrypted(
+ WebString::fromUTF8(type), init_data_ptr, init_data.size());
+}
+
+void EncryptedMediaPlayerSupportImpl::OnKeyAdded(
+ const std::string& session_id) {
+ EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
+ client_->keyAdded(
+ WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
+ WebString::fromUTF8(session_id));
+}
+
+void EncryptedMediaPlayerSupportImpl::OnKeyError(const std::string& session_id,
+ media::MediaKeys::KeyError error_code,
+ uint32 system_code) {
+ EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
+ error_code, media::MediaKeys::kMaxKeyError);
+
+ uint16 short_system_code = 0;
+ if (system_code > std::numeric_limits<uint16>::max()) {
+ LOG(WARNING) << "system_code exceeds unsigned short limit.";
+ short_system_code = std::numeric_limits<uint16>::max();
+ } else {
+ short_system_code = static_cast<uint16>(system_code);
+ }
+
+ client_->keyError(
+ WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
+ WebString::fromUTF8(session_id),
+ static_cast<WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
+ short_system_code);
+}
+
+void EncryptedMediaPlayerSupportImpl::OnKeyMessage(
+ const std::string& session_id,
+ const std::vector<uint8>& message,
+ const GURL& destination_url) {
+ DCHECK(destination_url.is_empty() || destination_url.is_valid());
+
+ client_->keyMessage(
+ WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
+ WebString::fromUTF8(session_id),
+ message.empty() ? NULL : &message[0],
+ message.size(),
+ destination_url);
+}
+
+void EncryptedMediaPlayerSupportImpl::SetDecryptorReadyCB(
+ const media::DecryptorReadyCB& decryptor_ready_cb) {
+ // Cancels the previous decryptor request.
+ if (decryptor_ready_cb.is_null()) {
+ if (!decryptor_ready_cb_.is_null()) {
+ base::ResetAndReturn(&decryptor_ready_cb_)
+ .Run(NULL, base::Bind(DoNothing));
+ }
+ return;
+ }
+
+ // TODO(xhwang): Support multiple decryptor notification request (e.g. from
+ // video and audio). The current implementation is okay for the current
+ // media pipeline since we initialize audio and video decoders in sequence.
+ // But WebMediaPlayerImpl should not depend on media pipeline's implementation
+ // detail.
+ DCHECK(decryptor_ready_cb_.is_null());
+
+ // Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink.
+ DCHECK(!proxy_decryptor_ || !web_cdm_);
+
+ if (proxy_decryptor_) {
+ decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor(),
+ base::Bind(DoNothing));
+ return;
+ }
+
+ if (web_cdm_) {
+ decryptor_ready_cb.Run(web_cdm_->GetDecryptor(), base::Bind(DoNothing));
+ return;
+ }
+
+ decryptor_ready_cb_ = decryptor_ready_cb;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h b/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h
new file mode 100644
index 00000000000..d68d40b7d5a
--- /dev/null
+++ b/chromium/content/renderer/media/crypto/encrypted_media_player_support_impl.h
@@ -0,0 +1,130 @@
+// Copyright 2014 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 CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/weak_ptr.h"
+#include "content/renderer/media/crypto/proxy_decryptor.h"
+#include "media/blink/encrypted_media_player_support.h"
+
+namespace blink {
+class WebMediaPlayerClient;
+}
+
+namespace content {
+
+class WebContentDecryptionModuleImpl;
+
+class EncryptedMediaPlayerSupportImpl
+ : public media::EncryptedMediaPlayerSupport,
+ public base::SupportsWeakPtr<EncryptedMediaPlayerSupportImpl> {
+ public:
+ static scoped_ptr<EncryptedMediaPlayerSupport> Create(
+ blink::WebMediaPlayerClient* client);
+
+ ~EncryptedMediaPlayerSupportImpl() override;
+
+ // EncryptedMediaPlayerSupport implementation.
+ blink::WebMediaPlayer::MediaKeyException GenerateKeyRequest(
+ blink::WebLocalFrame* frame,
+ const blink::WebString& key_system,
+ const unsigned char* init_data,
+ unsigned init_data_length) override;
+
+ blink::WebMediaPlayer::MediaKeyException AddKey(
+ const blink::WebString& key_system,
+ const unsigned char* key,
+ unsigned key_length,
+ const unsigned char* init_data,
+ unsigned init_data_length,
+ const blink::WebString& session_id) override;
+
+ blink::WebMediaPlayer::MediaKeyException CancelKeyRequest(
+ const blink::WebString& key_system,
+ const blink::WebString& session_id) override;
+
+ void SetInitialContentDecryptionModule(
+ blink::WebContentDecryptionModule* initial_cdm) override;
+
+ void SetContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm) override;
+ void SetContentDecryptionModule(
+ blink::WebContentDecryptionModule* cdm,
+ blink::WebContentDecryptionModuleResult result) override;
+
+ media::SetDecryptorReadyCB CreateSetDecryptorReadyCB() override;
+ media::Demuxer::NeedKeyCB CreateNeedKeyCB() override;
+
+ void OnPipelineDecryptError() override;
+
+ private:
+ explicit EncryptedMediaPlayerSupportImpl(blink::WebMediaPlayerClient* client);
+
+ // Requests that this object notifies when a decryptor is ready through the
+ // |decryptor_ready_cb| provided.
+ // If |decryptor_ready_cb| is null, the existing callback will be fired with
+ // NULL immediately and reset.
+ void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb);
+
+ blink::WebMediaPlayer::MediaKeyException GenerateKeyRequestInternal(
+ blink::WebLocalFrame* frame,
+ const std::string& key_system,
+ const unsigned char* init_data,
+ unsigned init_data_length);
+
+ blink::WebMediaPlayer::MediaKeyException AddKeyInternal(
+ const std::string& key_system,
+ const unsigned char* key,
+ unsigned key_length,
+ const unsigned char* init_data,
+ unsigned init_data_length,
+ const std::string& session_id);
+
+ blink::WebMediaPlayer::MediaKeyException CancelKeyRequestInternal(
+ const std::string& key_system,
+ const std::string& session_id);
+
+ void OnNeedKey(const std::string& type,
+ const std::vector<uint8>& init_data);
+
+ void OnKeyAdded(const std::string& session_id);
+ void OnKeyError(const std::string& session_id,
+ media::MediaKeys::KeyError error_code,
+ uint32 system_code);
+ void OnKeyMessage(const std::string& session_id,
+ const std::vector<uint8>& message,
+ const GURL& destination_url);
+
+ void ContentDecryptionModuleAttached(
+ blink::WebContentDecryptionModuleResult result,
+ bool success);
+
+ blink::WebMediaPlayerClient* client_;
+
+ // The currently selected key system. Empty string means that no key system
+ // has been selected.
+ std::string current_key_system_;
+
+ // Temporary for EME v0.1. In the future the init data type should be passed
+ // through GenerateKeyRequest() directly from WebKit.
+ std::string init_data_type_;
+
+ // Manages decryption keys and decrypts encrypted frames.
+ scoped_ptr<ProxyDecryptor> proxy_decryptor_;
+
+ // Non-owned pointer to the CDM. Updated via calls to
+ // setContentDecryptionModule().
+ WebContentDecryptionModuleImpl* web_cdm_;
+
+ media::DecryptorReadyCB decryptor_ready_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(EncryptedMediaPlayerSupportImpl);
+};
+}
+
+#endif // CONTENT_RENDERER_MEDIA_CRYPTO_ENCRYPTED_MEDIA_PLAYER_SUPPORT_IMPL_H_
diff --git a/chromium/content/renderer/media/crypto/key_systems.cc b/chromium/content/renderer/media/crypto/key_systems.cc
index dace75167b1..9c3ce046ab6 100644
--- a/chromium/content/renderer/media/crypto/key_systems.cc
+++ b/chromium/content/renderer/media/crypto/key_systems.cc
@@ -13,10 +13,10 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "content/public/common/content_client.h"
-#include "content/public/common/eme_codec.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/public/renderer/key_system_info.h"
#include "content/renderer/media/crypto/key_systems_support_uma.h"
+#include "media/base/eme_constants.h"
+#include "media/base/key_system_info.h"
#if defined(OS_ANDROID)
#include "media/base/android/media_codec_bridge.h"
@@ -26,38 +26,58 @@
namespace content {
+using media::EmeCodec;
+using media::EmeInitDataType;
+using media::KeySystemInfo;
+using media::SupportedInitDataTypes;
+using media::SupportedCodecs;
+
const char kClearKeyKeySystem[] = "org.w3.clearkey";
const char kPrefixedClearKeyKeySystem[] = "webkit-org.w3.clearkey";
const char kUnsupportedClearKeyKeySystem[] = "unsupported-org.w3.clearkey";
-struct CodecMask {
- const char* type;
- EmeCodec mask;
+struct NamedInitDataType {
+ const char* name;
+ EmeInitDataType type;
+};
+
+// Mapping between initialization data types names and enum values. When adding
+// entries, make sure to update IsSaneInitDataTypeWithContainer().
+static NamedInitDataType kInitDataTypeNames[] = {
+ {"webm", media::EME_INIT_DATA_TYPE_WEBM},
+#if defined(USE_PROPRIETARY_CODECS)
+ {"cenc", media::EME_INIT_DATA_TYPE_CENC}
+#endif // defined(USE_PROPRIETARY_CODECS)
+};
+
+struct NamedCodec {
+ const char* name;
+ EmeCodec type;
};
-// Mapping between container types and the masks of associated codecs.
+// Mapping between containers and their codecs.
// Only audio codec can belong to a "audio/*" container. Both audio and video
// codecs can belong to a "video/*" container.
-CodecMask kContainerCodecMasks[] = {
- {"audio/webm", EME_CODEC_WEBM_AUDIO_ALL},
- {"video/webm", EME_CODEC_WEBM_ALL},
+static NamedCodec kContainerToCodecMasks[] = {
+ {"audio/webm", media::EME_CODEC_WEBM_AUDIO_ALL},
+ {"video/webm", media::EME_CODEC_WEBM_ALL},
#if defined(USE_PROPRIETARY_CODECS)
- {"audio/mp4", EME_CODEC_MP4_AUDIO_ALL},
- {"video/mp4", EME_CODEC_MP4_ALL}
+ {"audio/mp4", media::EME_CODEC_MP4_AUDIO_ALL},
+ {"video/mp4", media::EME_CODEC_MP4_ALL}
#endif // defined(USE_PROPRIETARY_CODECS)
};
-// Mapping between codec types and their masks.
-CodecMask kCodecMasks[] = {
- {"vorbis", EME_CODEC_WEBM_VORBIS},
- {"vp8", EME_CODEC_WEBM_VP8},
- {"vp8.0", EME_CODEC_WEBM_VP8},
- {"vp9", EME_CODEC_WEBM_VP9},
- {"vp9.0", EME_CODEC_WEBM_VP9},
+// Mapping between codec names and enum values.
+static NamedCodec kCodecStrings[] = {
+ {"vorbis", media::EME_CODEC_WEBM_VORBIS},
+ {"vp8", media::EME_CODEC_WEBM_VP8},
+ {"vp8.0", media::EME_CODEC_WEBM_VP8},
+ {"vp9", media::EME_CODEC_WEBM_VP9},
+ {"vp9.0", media::EME_CODEC_WEBM_VP9},
#if defined(USE_PROPRIETARY_CODECS)
- {"mp4a", EME_CODEC_MP4_AAC},
- {"avc1", EME_CODEC_MP4_AVC1},
- {"avc3", EME_CODEC_MP4_AVC1}
+ {"mp4a", media::EME_CODEC_MP4_AAC},
+ {"avc1", media::EME_CODEC_MP4_AVC1},
+ {"avc3", media::EME_CODEC_MP4_AVC1}
#endif // defined(USE_PROPRIETARY_CODECS)
};
@@ -68,16 +88,18 @@ static void AddClearKey(std::vector<KeySystemInfo>* concrete_key_systems) {
// http://developer.android.com/guide/appendix/media-formats.html
// VP9 support is device dependent.
- info.supported_codecs = EME_CODEC_WEBM_ALL;
+ info.supported_init_data_types = media::EME_INIT_DATA_TYPE_WEBM;
+ info.supported_codecs = media::EME_CODEC_WEBM_ALL;
#if defined(OS_ANDROID)
// Temporarily disable VP9 support for Android.
// TODO(xhwang): Use mime_util.h to query VP9 support on Android.
- info.supported_codecs &= ~EME_CODEC_WEBM_VP9;
+ info.supported_codecs &= ~media::EME_CODEC_WEBM_VP9;
#endif // defined(OS_ANDROID)
#if defined(USE_PROPRIETARY_CODECS)
- info.supported_codecs |= EME_CODEC_MP4_ALL;
+ info.supported_init_data_types |= media::EME_INIT_DATA_TYPE_CENC;
+ info.supported_codecs |= media::EME_CODEC_MP4_ALL;
#endif // defined(USE_PROPRIETARY_CODECS)
info.use_aes_decryptor = true;
@@ -93,6 +115,12 @@ class KeySystems {
bool IsConcreteSupportedKeySystem(const std::string& key_system);
+ bool IsSupportedKeySystem(const std::string& key_system);
+
+ bool IsSupportedKeySystemWithInitDataType(
+ const std::string& key_system,
+ const std::string& init_data_type);
+
bool IsSupportedKeySystemWithMediaMimeType(
const std::string& mime_type,
const std::vector<std::string>& codecs,
@@ -119,29 +147,45 @@ class KeySystems {
#if defined(ENABLE_PEPPER_CDMS)
const std::string& pepper_type,
#endif
+ SupportedInitDataTypes supported_init_data_types,
SupportedCodecs supported_codecs,
const std::string& parent_key_system);
friend struct base::DefaultLazyInstanceTraits<KeySystems>;
struct KeySystemProperties {
- KeySystemProperties() : use_aes_decryptor(false) {}
+ KeySystemProperties()
+ : use_aes_decryptor(false), supported_codecs(media::EME_CODEC_NONE) {}
bool use_aes_decryptor;
#if defined(ENABLE_PEPPER_CDMS)
std::string pepper_type;
#endif
+ SupportedInitDataTypes supported_init_data_types;
SupportedCodecs supported_codecs;
};
typedef base::hash_map<std::string, KeySystemProperties>
KeySystemPropertiesMap;
typedef base::hash_map<std::string, std::string> ParentKeySystemMap;
- typedef base::hash_map<std::string, EmeCodec> CodecMaskMap;
+ typedef base::hash_map<std::string, SupportedCodecs> ContainerCodecsMap;
+ typedef base::hash_map<std::string, EmeCodec> CodecsMap;
+ typedef base::hash_map<std::string, media::EmeInitDataType> InitDataTypesMap;
KeySystems();
~KeySystems() {}
+ EmeInitDataType GetInitDataTypeForName(
+ const std::string& init_data_type) const;
+ // TODO(sandersd): Separate container enum from codec mask value.
+ // http://crbug.com/417440
+ SupportedCodecs GetCodecMaskForContainer(
+ const std::string& container) const;
+ EmeCodec GetCodecForString(const std::string& codec) const;
+
+ const std::string& GetConcreteKeySystemName(
+ const std::string& key_system) const;
+
// Returns whether a |container| type is supported by checking
// |key_system_supported_codecs|.
// TODO(xhwang): Update this to actually check initDataType support.
@@ -164,8 +208,9 @@ class KeySystems {
KeySystemsSupportUMA key_systems_support_uma_;
- CodecMaskMap container_codec_masks_;
- CodecMaskMap codec_masks_;
+ InitDataTypesMap init_data_type_name_map_;
+ ContainerCodecsMap container_to_codec_mask_map_;
+ CodecsMap codec_string_map_;
bool needs_update_;
base::Time last_update_time_;
@@ -187,18 +232,20 @@ KeySystems& KeySystems::GetInstance() {
// Because we use a LazyInstance, the key systems info must be populated when
// the instance is lazily initiated.
KeySystems::KeySystems() : needs_update_(true) {
- // Build container and codec masks for quick look up.
- for (size_t i = 0; i < arraysize(kContainerCodecMasks); ++i) {
- const CodecMask& container_codec_mask = kContainerCodecMasks[i];
- DCHECK(container_codec_masks_.find(container_codec_mask.type) ==
- container_codec_masks_.end());
- container_codec_masks_[container_codec_mask.type] =
- container_codec_mask.mask;
+ for (size_t i = 0; i < arraysize(kInitDataTypeNames); ++i) {
+ const std::string& name = kInitDataTypeNames[i].name;
+ DCHECK(!init_data_type_name_map_.count(name));
+ init_data_type_name_map_[name] = kInitDataTypeNames[i].type;
+ }
+ for (size_t i = 0; i < arraysize(kContainerToCodecMasks); ++i) {
+ const std::string& name = kContainerToCodecMasks[i].name;
+ DCHECK(!container_to_codec_mask_map_.count(name));
+ container_to_codec_mask_map_[name] = kContainerToCodecMasks[i].type;
}
- for (size_t i = 0; i < arraysize(kCodecMasks); ++i) {
- const CodecMask& codec_mask = kCodecMasks[i];
- DCHECK(codec_masks_.find(codec_mask.type) == codec_masks_.end());
- codec_masks_[codec_mask.type] = codec_mask.mask;
+ for (size_t i = 0; i < arraysize(kCodecStrings); ++i) {
+ const std::string& name = kCodecStrings[i].name;
+ DCHECK(!codec_string_map_.count(name));
+ codec_string_map_[name] = kCodecStrings[i].type;
}
UpdateSupportedKeySystems();
@@ -208,15 +255,49 @@ KeySystems::KeySystems() : needs_update_(true) {
#endif // defined(WIDEVINE_CDM_AVAILABLE)
}
+EmeInitDataType KeySystems::GetInitDataTypeForName(
+ const std::string& init_data_type) const {
+ InitDataTypesMap::const_iterator iter =
+ init_data_type_name_map_.find(init_data_type);
+ if (iter != init_data_type_name_map_.end())
+ return iter->second;
+ return media::EME_INIT_DATA_TYPE_NONE;
+}
+
+SupportedCodecs KeySystems::GetCodecMaskForContainer(
+ const std::string& container) const {
+ ContainerCodecsMap::const_iterator iter =
+ container_to_codec_mask_map_.find(container);
+ if (iter != container_to_codec_mask_map_.end())
+ return iter->second;
+ return media::EME_CODEC_NONE;
+}
+
+EmeCodec KeySystems::GetCodecForString(const std::string& codec) const {
+ CodecsMap::const_iterator iter = codec_string_map_.find(codec);
+ if (iter != codec_string_map_.end())
+ return iter->second;
+ return media::EME_CODEC_NONE;
+}
+
+const std::string& KeySystems::GetConcreteKeySystemName(
+ const std::string& key_system) const {
+ ParentKeySystemMap::const_iterator iter =
+ parent_key_system_map_.find(key_system);
+ if (iter != parent_key_system_map_.end())
+ return iter->second;
+ return key_system;
+}
+
void KeySystems::UpdateIfNeeded() {
-#if defined(WIDEVINE_CDM_AVAILABLE) && defined(WIDEVINE_CDM_IS_COMPONENT)
+#if defined(WIDEVINE_CDM_AVAILABLE)
DCHECK(thread_checker_.CalledOnValidThread());
if (!needs_update_)
return;
// The update could involve a sync IPC to the browser process. Use a minimum
// update interval to avoid unnecessary frequent IPC to the browser.
- static const int kMinUpdateIntervalInSeconds = 5;
+ static const int kMinUpdateIntervalInSeconds = 1;
base::Time now = base::Time::Now();
if (now - last_update_time_ <
base::TimeDelta::FromSeconds(kMinUpdateIntervalInSeconds)) {
@@ -262,6 +343,7 @@ void KeySystems::AddConcreteSupportedKeySystems(
#if defined(ENABLE_PEPPER_CDMS)
key_system_info.pepper_type,
#endif
+ key_system_info.supported_init_data_types,
key_system_info.supported_codecs,
key_system_info.parent_key_system);
}
@@ -273,13 +355,13 @@ void KeySystems::AddConcreteSupportedKeySystem(
#if defined(ENABLE_PEPPER_CDMS)
const std::string& pepper_type,
#endif
+ SupportedInitDataTypes supported_init_data_types,
SupportedCodecs supported_codecs,
const std::string& parent_key_system) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!IsConcreteSupportedKeySystem(concrete_key_system))
<< "Key system '" << concrete_key_system << "' already registered";
- DCHECK(parent_key_system_map_.find(concrete_key_system) ==
- parent_key_system_map_.end())
+ DCHECK(!parent_key_system_map_.count(concrete_key_system))
<< "'" << concrete_key_system << " is already registered as a parent";
KeySystemProperties properties;
@@ -289,6 +371,7 @@ void KeySystems::AddConcreteSupportedKeySystem(
properties.pepper_type = pepper_type;
#endif
+ properties.supported_init_data_types = supported_init_data_types;
properties.supported_codecs = supported_codecs;
concrete_key_system_map_[concrete_key_system] = properties;
@@ -296,8 +379,7 @@ void KeySystems::AddConcreteSupportedKeySystem(
if (!parent_key_system.empty()) {
DCHECK(!IsConcreteSupportedKeySystem(parent_key_system))
<< "Parent '" << parent_key_system << "' already registered concrete";
- DCHECK(parent_key_system_map_.find(parent_key_system) ==
- parent_key_system_map_.end())
+ DCHECK(!parent_key_system_map_.count(parent_key_system))
<< "Parent '" << parent_key_system << "' already registered";
parent_key_system_map_[parent_key_system] = concrete_key_system;
}
@@ -305,8 +387,7 @@ void KeySystems::AddConcreteSupportedKeySystem(
bool KeySystems::IsConcreteSupportedKeySystem(const std::string& key_system) {
DCHECK(thread_checker_.CalledOnValidThread());
- return concrete_key_system_map_.find(key_system) !=
- concrete_key_system_map_.end();
+ return concrete_key_system_map_.count(key_system) != 0;
}
bool KeySystems::IsSupportedContainer(
@@ -323,16 +404,11 @@ bool KeySystems::IsSupportedContainer(
if (container.find("audio/") == 0)
canonical_container.replace(0, 6, "video/");
- CodecMaskMap::const_iterator container_iter =
- container_codec_masks_.find(canonical_container);
- // Unrecognized container.
- if (container_iter == container_codec_masks_.end())
- return false;
-
- EmeCodec container_codec_mask = container_iter->second;
// A container is supported iif at least one codec in that container is
// supported.
- return (container_codec_mask & key_system_supported_codecs) != 0;
+ SupportedCodecs supported_codecs =
+ GetCodecMaskForContainer(canonical_container);
+ return (supported_codecs & key_system_supported_codecs) != 0;
}
bool KeySystems::IsSupportedContainerAndCodecs(
@@ -344,45 +420,66 @@ bool KeySystems::IsSupportedContainerAndCodecs(
DCHECK(!codecs.empty());
DCHECK(IsSupportedContainer(container, key_system_supported_codecs));
- CodecMaskMap::const_iterator container_iter =
- container_codec_masks_.find(container);
- EmeCodec container_codec_mask = container_iter->second;
+ SupportedCodecs container_supported_codecs =
+ GetCodecMaskForContainer(container);
for (size_t i = 0; i < codecs.size(); ++i) {
- const std::string& codec = codecs[i];
- if (codec.empty())
+ // TODO(sandersd): This should fail for isTypeSupported().
+ // http://crbug.com/417461
+ if (codecs[i].empty())
continue;
- CodecMaskMap::const_iterator codec_iter = codec_masks_.find(codec);
- if (codec_iter == codec_masks_.end()) // Unrecognized codec.
- return false;
- EmeCodec codec_mask = codec_iter->second;
- if (!(codec_mask & key_system_supported_codecs)) // Unsupported codec.
+ EmeCodec codec = GetCodecForString(codecs[i]);
+
+ // Unsupported codec.
+ if (!(codec & key_system_supported_codecs))
return false;
// Unsupported codec/container combination, e.g. "video/webm" and "avc1".
- if (!(codec_mask & container_codec_mask))
+ if (!(codec & container_supported_codecs))
return false;
}
return true;
}
+bool KeySystems::IsSupportedKeySystem(const std::string& key_system) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return (concrete_key_system_map_.count(key_system) ||
+ parent_key_system_map_.count(key_system));
+}
+
+bool KeySystems::IsSupportedKeySystemWithInitDataType(
+ const std::string& key_system,
+ const std::string& init_data_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // If |key_system| is a parent key system, use its concrete child.
+ const std::string& concrete_key_system = GetConcreteKeySystemName(key_system);
+
+ // Locate |concrete_key_system|.
+ KeySystemPropertiesMap::const_iterator key_system_iter =
+ concrete_key_system_map_.find(concrete_key_system);
+ if (key_system_iter == concrete_key_system_map_.end())
+ return false;
+
+ // Check |init_data_type| and |key_system| x |init_data_type|.
+ const KeySystemProperties& properties = key_system_iter->second;
+ EmeInitDataType eme_init_data_type = GetInitDataTypeForName(init_data_type);
+ return (properties.supported_init_data_types & eme_init_data_type) != 0;
+}
+
+// TODO(sandersd): Reorganize to be more similar to
+// IsKeySystemSupportedWithInitDataType(). Note that a fork may still be
+// required; http://crbug.com/417461.
bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
const std::string& mime_type,
const std::vector<std::string>& codecs,
const std::string& key_system) {
DCHECK(thread_checker_.CalledOnValidThread());
- // If |key_system| is a parent key_system, use its concrete child.
- // Otherwise, use |key_system|.
- std::string concrete_key_system;
- ParentKeySystemMap::iterator parent_key_system_iter =
- parent_key_system_map_.find(key_system);
- if (parent_key_system_iter != parent_key_system_map_.end())
- concrete_key_system = parent_key_system_iter->second;
- else
- concrete_key_system = key_system;
+ // If |key_system| is a parent key system, use its concrete child.
+ const std::string& concrete_key_system = GetConcreteKeySystemName(key_system);
bool has_type = !mime_type.empty();
@@ -420,7 +517,7 @@ bool KeySystems::IsSupportedKeySystemWithMediaMimeType(
bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
DCHECK(thread_checker_.CalledOnValidThread());
- KeySystemPropertiesMap::iterator key_system_iter =
+ KeySystemPropertiesMap::const_iterator key_system_iter =
concrete_key_system_map_.find(concrete_key_system);
if (key_system_iter == concrete_key_system_map_.end()) {
DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
@@ -434,7 +531,7 @@ bool KeySystems::UseAesDecryptor(const std::string& concrete_key_system) {
std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
DCHECK(thread_checker_.CalledOnValidThread());
- KeySystemPropertiesMap::iterator key_system_iter =
+ KeySystemPropertiesMap::const_iterator key_system_iter =
concrete_key_system_map_.find(concrete_key_system);
if (key_system_iter == concrete_key_system_map_.end()) {
DLOG(FATAL) << concrete_key_system << " is not a known concrete system";
@@ -449,17 +546,14 @@ std::string KeySystems::GetPepperType(const std::string& concrete_key_system) {
void KeySystems::AddContainerMask(const std::string& container, uint32 mask) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(container_codec_masks_.find(container) ==
- container_codec_masks_.end());
-
- container_codec_masks_[container] = static_cast<EmeCodec>(mask);
+ DCHECK(!container_to_codec_mask_map_.count(container));
+ container_to_codec_mask_map_[container] = static_cast<EmeCodec>(mask);
}
void KeySystems::AddCodecMask(const std::string& codec, uint32 mask) {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(codec_masks_.find(codec) == codec_masks_.end());
-
- codec_masks_[codec] = static_cast<EmeCodec>(mask);
+ DCHECK(!codec_string_map_.count(codec));
+ codec_string_map_[codec] = static_cast<EmeCodec>(mask);
}
//------------------------------------------------------------------------------
@@ -483,10 +577,33 @@ std::string GetPrefixedKeySystemName(const std::string& key_system) {
return key_system;
}
+bool IsSaneInitDataTypeWithContainer(
+ const std::string& init_data_type,
+ const std::string& container) {
+ if (init_data_type == "cenc") {
+ return container == "audio/mp4" || container == "video/mp4";
+ } else if (init_data_type == "webm") {
+ return container == "audio/webm" || container == "video/webm";
+ } else {
+ return true;
+ }
+}
+
bool IsConcreteSupportedKeySystem(const std::string& key_system) {
return KeySystems::GetInstance().IsConcreteSupportedKeySystem(key_system);
}
+bool IsSupportedKeySystem(const std::string& key_system) {
+ return KeySystems::GetInstance().IsSupportedKeySystem(key_system);
+}
+
+bool IsSupportedKeySystemWithInitDataType(
+ const std::string& key_system,
+ const std::string& init_data_type) {
+ return KeySystems::GetInstance().IsSupportedKeySystemWithInitDataType(
+ key_system, init_data_type);
+}
+
bool IsSupportedKeySystemWithMediaMimeType(
const std::string& mime_type,
const std::vector<std::string>& codecs,
diff --git a/chromium/content/renderer/media/crypto/key_systems.h b/chromium/content/renderer/media/crypto/key_systems.h
index 99825d1997a..03d40024579 100644
--- a/chromium/content/renderer/media/crypto/key_systems.h
+++ b/chromium/content/renderer/media/crypto/key_systems.h
@@ -24,6 +24,24 @@ std::string GetUnprefixedKeySystemName(const std::string& key_system);
// Gets the prefixed key system name for |key_system|.
std::string GetPrefixedKeySystemName(const std::string& key_system);
+// Returns false if a container-specific |init_data_type| is specified with an
+// inappropriate container.
+// TODO(sandersd): Remove this essentially internal detail if the spec is
+// updated to not convolve the two in a single method call.
+// TODO(sandersd): Use enum values instead of strings. http://crbug.com/417440
+bool IsSaneInitDataTypeWithContainer(
+ const std::string& init_data_type,
+ const std::string& container);
+
+// Note: Shouldn't be used for prefixed API as the original
+// IsSupportedKeySystemWithMediaMimeType() path reports UMAs, but this path does
+// not.
+bool IsSupportedKeySystem(const std::string& key_system);
+
+bool IsSupportedKeySystemWithInitDataType(
+ const std::string& key_system,
+ const std::string& init_data_type);
+
// Returns whether |key_system| is a real supported key system that can be
// instantiated.
// Abstract parent |key_system| strings will return false.
diff --git a/chromium/content/renderer/media/crypto/key_systems_support_uma.cc b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc
index f1d77bd677b..bd90aeb8bc9 100644
--- a/chromium/content/renderer/media/crypto/key_systems_support_uma.cc
+++ b/chromium/content/renderer/media/crypto/key_systems_support_uma.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/metrics/histogram.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/crypto/key_systems.h"
@@ -13,31 +14,34 @@ namespace content {
namespace {
-const char kKeySystemSupportActionPrefix[] = "KeySystemSupport.";
+const char kKeySystemSupportUMAPrefix[] = "Media.EME.KeySystemSupport.";
+
+// These values are reported to UMA. Do not change the existing values!
+enum KeySystemSupportStatus {
+ KEY_SYSTEM_QUERIED = 0,
+ KEY_SYSTEM_SUPPORTED = 1,
+ KEY_SYSTEM_WITH_TYPE_QUERIED = 2,
+ KEY_SYSTEM_WITH_TYPE_SUPPORTED = 3,
+ KEY_SYSTEM_SUPPORT_STATUS_COUNT
+};
// Reports an event only once.
class OneTimeReporter {
public:
- OneTimeReporter(const std::string& key_system,
- bool has_type,
- const std::string& event);
+ OneTimeReporter(const std::string& key_system, KeySystemSupportStatus status);
~OneTimeReporter();
void Report();
private:
bool is_reported_;
- std::string action_;
+ const std::string key_system_;
+ const KeySystemSupportStatus status_;
};
OneTimeReporter::OneTimeReporter(const std::string& key_system,
- bool has_type,
- const std::string& event)
- : is_reported_(false) {
- action_ = kKeySystemSupportActionPrefix + KeySystemNameForUMA(key_system);
- if (has_type)
- action_ += "WithType";
- action_ += '.' + event;
+ KeySystemSupportStatus status)
+ : is_reported_(false), key_system_(key_system), status_(status) {
}
OneTimeReporter::~OneTimeReporter() {}
@@ -45,7 +49,14 @@ OneTimeReporter::~OneTimeReporter() {}
void OneTimeReporter::Report() {
if (is_reported_)
return;
- RenderThread::Get()->RecordComputedAction(action_);
+
+ // Not using UMA_HISTOGRAM_ENUMERATION directly because UMA_* macros require
+ // the names to be constant throughout the process' lifetime.
+ base::LinearHistogram::FactoryGet(
+ kKeySystemSupportUMAPrefix + KeySystemNameForUMA(key_system_), 1,
+ KEY_SYSTEM_SUPPORT_STATUS_COUNT, KEY_SYSTEM_SUPPORT_STATUS_COUNT + 1,
+ base::Histogram::kUmaTargetedHistogramFlag)->Add(status_);
+
is_reported_ = true;
}
@@ -69,10 +80,10 @@ class KeySystemsSupportUMA::Reporter {
KeySystemsSupportUMA::Reporter::Reporter(const std::string& key_system)
: key_system_(key_system),
- call_reporter_(key_system, false, "Queried"),
- call_with_type_reporter_(key_system, true, "Queried"),
- support_reporter_(key_system, false, "Supported"),
- support_with_type_reporter_(key_system, true, "Supported") {}
+ call_reporter_(key_system, KEY_SYSTEM_QUERIED),
+ call_with_type_reporter_(key_system, KEY_SYSTEM_WITH_TYPE_QUERIED),
+ support_reporter_(key_system, KEY_SYSTEM_SUPPORTED),
+ support_with_type_reporter_(key_system, KEY_SYSTEM_WITH_TYPE_SUPPORTED) {}
KeySystemsSupportUMA::Reporter::~Reporter() {}
diff --git a/chromium/content/renderer/media/crypto/key_systems_unittest.cc b/chromium/content/renderer/media/crypto/key_systems_unittest.cc
index e52d361322a..d7c980dd17f 100644
--- a/chromium/content/renderer/media/crypto/key_systems_unittest.cc
+++ b/chromium/content/renderer/media/crypto/key_systems_unittest.cc
@@ -7,9 +7,10 @@
#include "content/public/common/content_client.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/public/renderer/key_system_info.h"
#include "content/renderer/media/crypto/key_systems.h"
#include "content/test/test_content_client.h"
+#include "media/base/eme_constants.h"
+#include "media/base/key_system_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -36,6 +37,7 @@
namespace content {
using blink::WebString;
+using media::KeySystemInfo;
// These are the (fake) key systems that are registered for these tests.
// kUsesAes uses the AesDecryptor like Clear Key.
@@ -64,8 +66,9 @@ enum TestCodec {
TEST_CODEC_FOO_ALL = TEST_CODEC_FOO_AUDIO_ALL | TEST_CODEC_FOO_VIDEO_ALL
};
-COMPILE_ASSERT((TEST_CODEC_FOO_ALL & EME_CODEC_ALL) == EME_CODEC_NONE,
- test_codec_masks_should_only_use_invalid_codec_masks);
+COMPILE_ASSERT((TEST_CODEC_FOO_ALL & media::EME_CODEC_ALL) ==
+ media::EME_CODEC_NONE,
+ test_codec_masks_should_only_use_invalid_codec_masks);
// Adds test container and codec masks.
// This function must be called after SetContentClient() is called.
@@ -91,21 +94,22 @@ static void AddContainerAndCodecMasksForTest() {
}
class TestContentRendererClient : public ContentRendererClient {
- virtual void AddKeySystems(
- std::vector<content::KeySystemInfo>* key_systems) OVERRIDE;
+ void AddKeySystems(std::vector<media::KeySystemInfo>* key_systems) override;
};
void TestContentRendererClient::AddKeySystems(
- std::vector<content::KeySystemInfo>* key_systems) {
+ std::vector<media::KeySystemInfo>* key_systems) {
KeySystemInfo aes(kUsesAes);
- aes.supported_codecs = EME_CODEC_WEBM_ALL;
+ aes.supported_codecs = media::EME_CODEC_WEBM_ALL;
aes.supported_codecs |= TEST_CODEC_FOO_ALL;
+ aes.supported_init_data_types = media::EME_INIT_DATA_TYPE_WEBM;
aes.use_aes_decryptor = true;
key_systems->push_back(aes);
KeySystemInfo ext(kExternal);
- ext.supported_codecs = EME_CODEC_WEBM_ALL;
+ ext.supported_codecs = media::EME_CODEC_WEBM_ALL;
ext.supported_codecs |= TEST_CODEC_FOO_ALL;
+ ext.supported_init_data_types = media::EME_INIT_DATA_TYPE_WEBM;
ext.parent_key_system = kExternalParent;
#if defined(ENABLE_PEPPER_CDMS)
ext.pepper_type = "application/x-ppapi-external-cdm";
@@ -113,6 +117,7 @@ void TestContentRendererClient::AddKeySystems(
key_systems->push_back(ext);
}
+// TODO(sandersd): Refactor. http://crbug.com/417444
class KeySystemsTest : public testing::Test {
protected:
KeySystemsTest() {
@@ -159,11 +164,9 @@ class KeySystemsTest : public testing::Test {
SetRendererClientForTesting(&content_renderer_client_);
}
- virtual void SetUp() OVERRIDE {
- AddContainerAndCodecMasksForTest();
- }
+ void SetUp() override { AddContainerAndCodecMasksForTest(); }
- virtual ~KeySystemsTest() {
+ ~KeySystemsTest() override {
// Clear the use of content_client_, which was set in SetUp().
SetContentClient(NULL);
}
diff --git a/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc b/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc
index c443e031fc6..3fc884aca28 100644
--- a/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc
+++ b/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc
@@ -39,7 +39,7 @@ scoped_ptr<PepperCdmWrapper> PepperCdmWrapperImpl::Create(
PepperWebPluginImpl* ppapi_plugin = static_cast<PepperWebPluginImpl*>(plugin);
scoped_refptr<PepperPluginInstanceImpl> plugin_instance =
ppapi_plugin->instance();
- if (!plugin_instance)
+ if (!plugin_instance.get())
return scoped_ptr<PepperCdmWrapper>();
GURL url(plugin_instance->container()->element().document().url());
@@ -59,7 +59,7 @@ PepperCdmWrapperImpl::PepperCdmWrapperImpl(
: helper_plugin_(helper_plugin.Pass()),
plugin_instance_(plugin_instance) {
DCHECK(helper_plugin_);
- DCHECK(plugin_instance_);
+ DCHECK(plugin_instance_.get());
// Plugin must be a CDM.
DCHECK(plugin_instance_->GetContentDecryptorDelegate());
}
diff --git a/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.h b/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.h
index 7f54f0c74dc..ea4f31c249b 100644
--- a/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.h
+++ b/chromium/content/renderer/media/crypto/pepper_cdm_wrapper_impl.h
@@ -44,10 +44,10 @@ class PepperCdmWrapperImpl : public PepperCdmWrapper {
const std::string& pluginType,
const GURL& security_origin);
- virtual ~PepperCdmWrapperImpl();
+ ~PepperCdmWrapperImpl() override;
// Returns the ContentDecryptorDelegate* associated with this plugin.
- virtual ContentDecryptorDelegate* GetCdmDelegate() OVERRIDE;
+ ContentDecryptorDelegate* GetCdmDelegate() override;
private:
typedef scoped_ptr<blink::WebHelperPlugin, WebHelperPluginDeleter>
diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc
index dd07aaacc69..1af098c1fbe 100644
--- a/chromium/content/renderer/media/crypto/ppapi_decryptor.cc
+++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.cc
@@ -7,9 +7,6 @@
#include <string>
#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
@@ -17,7 +14,6 @@
#include "content/renderer/pepper/content_decryptor_delegate.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "media/base/audio_decoder_config.h"
-#include "media/base/cdm_promise.h"
#include "media/base/data_buffer.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder_config.h"
@@ -25,36 +21,6 @@
namespace content {
-// This class is needed so that resolving an Update() promise triggers playback
-// of the stream. It intercepts the resolve() call to invoke an additional
-// callback.
-class SessionUpdatedPromise : public media::SimpleCdmPromise {
- public:
- SessionUpdatedPromise(scoped_ptr<media::SimpleCdmPromise> caller_promise,
- base::Closure additional_resolve_cb)
- : caller_promise_(caller_promise.Pass()),
- additional_resolve_cb_(additional_resolve_cb) {}
-
- virtual void resolve() OVERRIDE {
- DCHECK(is_pending_);
- is_pending_ = false;
- additional_resolve_cb_.Run();
- caller_promise_->resolve();
- }
-
- virtual void reject(media::MediaKeys::Exception exception_code,
- uint32 system_code,
- const std::string& error_message) OVERRIDE {
- DCHECK(is_pending_);
- is_pending_ = false;
- caller_promise_->reject(exception_code, system_code, error_message);
- }
-
- protected:
- scoped_ptr<media::SimpleCdmPromise> caller_promise_;
- base::Closure additional_resolve_cb_;
-};
-
scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
const std::string& key_system,
const GURL& security_origin,
@@ -62,7 +28,9 @@ scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb) {
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb) {
std::string plugin_type = GetPepperType(key_system);
DCHECK(!plugin_type.empty());
scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper =
@@ -78,7 +46,9 @@ scoped_ptr<PpapiDecryptor> PpapiDecryptor::Create(
session_message_cb,
session_ready_cb,
session_closed_cb,
- session_error_cb));
+ session_error_cb,
+ session_keys_change_cb,
+ session_expiration_update_cb));
}
PpapiDecryptor::PpapiDecryptor(
@@ -87,12 +57,16 @@ PpapiDecryptor::PpapiDecryptor(
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb)
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb)
: pepper_cdm_wrapper_(pepper_cdm_wrapper.Pass()),
session_message_cb_(session_message_cb),
session_ready_cb_(session_ready_cb),
session_closed_cb_(session_closed_cb),
session_error_cb_(session_error_cb),
+ session_keys_change_cb_(session_keys_change_cb),
+ session_expiration_update_cb_(session_expiration_update_cb),
render_loop_proxy_(base::MessageLoopProxy::current()),
weak_ptr_factory_(this) {
DCHECK(pepper_cdm_wrapper_.get());
@@ -100,6 +74,8 @@ PpapiDecryptor::PpapiDecryptor(
DCHECK(!session_ready_cb_.is_null());
DCHECK(!session_closed_cb_.is_null());
DCHECK(!session_error_cb_.is_null());
+ DCHECK(!session_keys_change_cb.is_null());
+ DCHECK(!session_expiration_update_cb.is_null());
base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr();
CdmDelegate()->Initialize(
@@ -108,6 +84,8 @@ PpapiDecryptor::PpapiDecryptor(
base::Bind(&PpapiDecryptor::OnSessionReady, weak_this),
base::Bind(&PpapiDecryptor::OnSessionClosed, weak_this),
base::Bind(&PpapiDecryptor::OnSessionError, weak_this),
+ base::Bind(&PpapiDecryptor::OnSessionKeysChange, weak_this),
+ base::Bind(&PpapiDecryptor::OnSessionExpirationUpdate, weak_this),
base::Bind(&PpapiDecryptor::OnFatalPluginError, weak_this));
}
@@ -115,6 +93,22 @@ PpapiDecryptor::~PpapiDecryptor() {
pepper_cdm_wrapper_.reset();
}
+void PpapiDecryptor::SetServerCertificate(
+ const uint8* certificate_data,
+ int certificate_data_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ DVLOG(2) << __FUNCTION__;
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
+
+ if (!CdmDelegate()) {
+ promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
+ return;
+ }
+
+ CdmDelegate()->SetServerCertificate(
+ certificate_data, certificate_data_length, promise.Pass());
+}
+
void PpapiDecryptor::CreateSession(
const std::string& init_data_type,
const uint8* init_data,
@@ -146,7 +140,6 @@ void PpapiDecryptor::LoadSession(
promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
return;
}
-
CdmDelegate()->LoadSession(web_session_id, promise.Pass());
}
@@ -161,19 +154,23 @@ void PpapiDecryptor::UpdateSession(
promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
return;
}
+ CdmDelegate()->UpdateSession(web_session_id, response, response_length,
+ promise.Pass());
+}
+
+void PpapiDecryptor::CloseSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- scoped_ptr<SessionUpdatedPromise> session_updated_promise(
- new SessionUpdatedPromise(promise.Pass(),
- base::Bind(&PpapiDecryptor::ResumePlayback,
- weak_ptr_factory_.GetWeakPtr())));
- CdmDelegate()->UpdateSession(
- web_session_id,
- response,
- response_length,
- session_updated_promise.PassAs<media::SimpleCdmPromise>());
+ if (!CdmDelegate()) {
+ promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
+ return;
+ }
+
+ CdmDelegate()->CloseSession(web_session_id, promise.Pass());
}
-void PpapiDecryptor::ReleaseSession(
+void PpapiDecryptor::RemoveSession(
const std::string& web_session_id,
scoped_ptr<media::SimpleCdmPromise> promise) {
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
@@ -183,7 +180,19 @@ void PpapiDecryptor::ReleaseSession(
return;
}
- CdmDelegate()->ReleaseSession(web_session_id, promise.Pass());
+ CdmDelegate()->RemoveSession(web_session_id, promise.Pass());
+}
+
+void PpapiDecryptor::GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
+
+ if (!CdmDelegate()) {
+ promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist.");
+ return;
+ }
+
+ CdmDelegate()->GetUsableKeyIds(web_session_id, promise.Pass());
}
media::Decryptor* PpapiDecryptor::GetDecryptor() {
@@ -398,10 +407,27 @@ void PpapiDecryptor::OnSessionMessage(const std::string& web_session_id,
session_message_cb_.Run(web_session_id, message, destination_url);
}
-void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) {
+void PpapiDecryptor::OnSessionKeysChange(const std::string& web_session_id,
+ bool has_additional_usable_key) {
DCHECK(render_loop_proxy_->BelongsToCurrentThread());
- ResumePlayback();
+ // TODO(jrummell): Handling resume playback should be done in the media
+ // player, not in the Decryptors. http://crbug.com/413413.
+ if (has_additional_usable_key)
+ AttemptToResumePlayback();
+
+ session_keys_change_cb_.Run(web_session_id, has_additional_usable_key);
+}
+
+void PpapiDecryptor::OnSessionExpirationUpdate(
+ const std::string& web_session_id,
+ const base::Time& new_expiry_time) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
+ session_expiration_update_cb_.Run(web_session_id, new_expiry_time);
+}
+
+void PpapiDecryptor::OnSessionReady(const std::string& web_session_id) {
+ DCHECK(render_loop_proxy_->BelongsToCurrentThread());
session_ready_cb_.Run(web_session_id);
}
@@ -419,10 +445,7 @@ void PpapiDecryptor::OnSessionError(const std::string& web_session_id,
web_session_id, exception_code, system_code, error_description);
}
-void PpapiDecryptor::ResumePlayback() {
- // Based on the spec, we need to resume playback when update() completes
- // successfully, or when a session is successfully loaded (triggered by
- // OnSessionReady()). So we choose to call the NewKeyCBs here.
+void PpapiDecryptor::AttemptToResumePlayback() {
if (!new_audio_key_cb_.is_null())
new_audio_key_cb_.Run();
diff --git a/chromium/content/renderer/media/crypto/ppapi_decryptor.h b/chromium/content/renderer/media/crypto/ppapi_decryptor.h
index c09e4b046fd..39c38c210f3 100644
--- a/chromium/content/renderer/media/crypto/ppapi_decryptor.h
+++ b/chromium/content/renderer/media/crypto/ppapi_decryptor.h
@@ -38,57 +38,66 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb);
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb);
- virtual ~PpapiDecryptor();
+ ~PpapiDecryptor() override;
// media::MediaKeys implementation.
- virtual void CreateSession(
- const std::string& init_data_type,
- const uint8* init_data,
- int init_data_length,
- SessionType session_type,
- scoped_ptr<media::NewSessionCdmPromise> promise) OVERRIDE;
- virtual void LoadSession(
- const std::string& web_session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise) OVERRIDE;
- virtual void UpdateSession(
- const std::string& web_session_id,
- const uint8* response,
- int response_length,
- scoped_ptr<media::SimpleCdmPromise> promise) OVERRIDE;
- virtual void ReleaseSession(
- const std::string& web_session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) OVERRIDE;
- virtual Decryptor* GetDecryptor() OVERRIDE;
+ void SetServerCertificate(
+ const uint8* certificate_data,
+ int certificate_data_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ void CreateSession(const std::string& init_data_type,
+ const uint8* init_data,
+ int init_data_length,
+ SessionType session_type,
+ scoped_ptr<media::NewSessionCdmPromise> promise) override;
+ void LoadSession(const std::string& web_session_id,
+ scoped_ptr<media::NewSessionCdmPromise> promise) override;
+ void UpdateSession(const std::string& web_session_id,
+ const uint8* response,
+ int response_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ void CloseSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ void RemoveSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ void GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise) override;
+ Decryptor* GetDecryptor() override;
// media::Decryptor implementation.
- virtual void RegisterNewKeyCB(StreamType stream_type,
- const NewKeyCB& key_added_cb) OVERRIDE;
- virtual void Decrypt(StreamType stream_type,
- const scoped_refptr<media::DecoderBuffer>& encrypted,
- const DecryptCB& decrypt_cb) OVERRIDE;
- virtual void CancelDecrypt(StreamType stream_type) OVERRIDE;
- virtual void InitializeAudioDecoder(const media::AudioDecoderConfig& config,
- const DecoderInitCB& init_cb) OVERRIDE;
- virtual void InitializeVideoDecoder(const media::VideoDecoderConfig& config,
- const DecoderInitCB& init_cb) OVERRIDE;
- virtual void DecryptAndDecodeAudio(
+ void RegisterNewKeyCB(StreamType stream_type,
+ const NewKeyCB& key_added_cb) override;
+ void Decrypt(StreamType stream_type,
+ const scoped_refptr<media::DecoderBuffer>& encrypted,
+ const DecryptCB& decrypt_cb) override;
+ void CancelDecrypt(StreamType stream_type) override;
+ void InitializeAudioDecoder(const media::AudioDecoderConfig& config,
+ const DecoderInitCB& init_cb) override;
+ void InitializeVideoDecoder(const media::VideoDecoderConfig& config,
+ const DecoderInitCB& init_cb) override;
+ void DecryptAndDecodeAudio(
const scoped_refptr<media::DecoderBuffer>& encrypted,
- const AudioDecodeCB& audio_decode_cb) OVERRIDE;
- virtual void DecryptAndDecodeVideo(
+ const AudioDecodeCB& audio_decode_cb) override;
+ void DecryptAndDecodeVideo(
const scoped_refptr<media::DecoderBuffer>& encrypted,
- const VideoDecodeCB& video_decode_cb) OVERRIDE;
- virtual void ResetDecoder(StreamType stream_type) OVERRIDE;
- virtual void DeinitializeDecoder(StreamType stream_type) OVERRIDE;
+ const VideoDecodeCB& video_decode_cb) override;
+ void ResetDecoder(StreamType stream_type) override;
+ void DeinitializeDecoder(StreamType stream_type) override;
private:
- PpapiDecryptor(const std::string& key_system,
- scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
- const media::SessionMessageCB& session_message_cb,
- const media::SessionReadyCB& session_ready_cb,
- const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb);
+ PpapiDecryptor(
+ const std::string& key_system,
+ scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb);
void OnDecoderInitialized(StreamType stream_type, bool success);
@@ -96,6 +105,10 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
void OnSessionMessage(const std::string& web_session_id,
const std::vector<uint8>& message,
const GURL& destination_url);
+ void OnSessionKeysChange(const std::string& web_session_id,
+ bool has_additional_usable_key);
+ void OnSessionExpirationUpdate(const std::string& web_session_id,
+ const base::Time& new_expiry_time);
void OnSessionReady(const std::string& web_session_id);
void OnSessionClosed(const std::string& web_session_id);
void OnSessionError(const std::string& web_session_id,
@@ -103,8 +116,7 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
uint32 system_code,
const std::string& error_description);
- // On a successful Update() or SessionReady event, trigger playback to resume.
- void ResumePlayback();
+ void AttemptToResumePlayback();
// Callback to notify that a fatal error happened in |plugin_cdm_delegate_|.
// The error is terminal and |plugin_cdm_delegate_| should not be used after
@@ -122,6 +134,8 @@ class PpapiDecryptor : public media::MediaKeys, public media::Decryptor {
media::SessionReadyCB session_ready_cb_;
media::SessionClosedCB session_closed_cb_;
media::SessionErrorCB session_error_cb_;
+ media::SessionKeysChangeCB session_keys_change_cb_;
+ media::SessionExpirationUpdateCB session_expiration_update_cb_;
scoped_refptr<base::MessageLoopProxy> render_loop_proxy_;
diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.cc b/chromium/content/renderer/media/crypto/proxy_decryptor.cc
index 28cd421e85f..44a30fd1f84 100644
--- a/chromium/content/renderer/media/crypto/proxy_decryptor.cc
+++ b/chromium/content/renderer/media/crypto/proxy_decryptor.cc
@@ -10,19 +10,11 @@
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
-#include "content/renderer/media/crypto/content_decryption_module_factory.h"
-#include "media/base/cdm_promise.h"
+#include "media/base/cdm_callback_promise.h"
+#include "media/base/cdm_factory.h"
#include "media/cdm/json_web_key.h"
#include "media/cdm/key_system_names.h"
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/pepper_cdm_wrapper.h"
-#endif // defined(ENABLE_PEPPER_CDMS)
-
-#if defined(ENABLE_BROWSER_CDMS)
-#include "content/renderer/media/crypto/renderer_cdm_manager.h"
-#endif // defined(ENABLE_BROWSER_CDMS)
-
namespace content {
// Special system code to signal a closed persistent session in a SessionError()
@@ -30,30 +22,14 @@ namespace content {
// EME API.
const int kSessionClosedSystemCode = 29127;
-ProxyDecryptor::ProxyDecryptor(
-#if defined(ENABLE_PEPPER_CDMS)
- const CreatePepperCdmCB& create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
-#endif // defined(ENABLE_PEPPER_CDMS)
- const KeyAddedCB& key_added_cb,
- const KeyErrorCB& key_error_cb,
- const KeyMessageCB& key_message_cb)
- :
-#if defined(ENABLE_PEPPER_CDMS)
- create_pepper_cdm_cb_(create_pepper_cdm_cb),
-#elif defined(ENABLE_BROWSER_CDMS)
- manager_(manager),
- cdm_id_(RendererCdmManager::kInvalidCdmId),
-#endif // defined(ENABLE_PEPPER_CDMS)
- key_added_cb_(key_added_cb),
+ProxyDecryptor::ProxyDecryptor(const KeyAddedCB& key_added_cb,
+ const KeyErrorCB& key_error_cb,
+ const KeyMessageCB& key_message_cb)
+ : key_added_cb_(key_added_cb),
key_error_cb_(key_error_cb),
key_message_cb_(key_message_cb),
is_clear_key_(false),
weak_ptr_factory_(this) {
-#if defined(ENABLE_PEPPER_CDMS)
- DCHECK(!create_pepper_cdm_cb_.is_null());
-#endif // defined(ENABLE_PEPPER_CDMS)
DCHECK(!key_added_cb_.is_null());
DCHECK(!key_error_cb_.is_null());
DCHECK(!key_message_cb_.is_null());
@@ -70,16 +46,17 @@ media::Decryptor* ProxyDecryptor::GetDecryptor() {
#if defined(ENABLE_BROWSER_CDMS)
int ProxyDecryptor::GetCdmId() {
- return cdm_id_;
+ return media_keys_->GetCdmId();
}
#endif
-bool ProxyDecryptor::InitializeCDM(const std::string& key_system,
+bool ProxyDecryptor::InitializeCDM(media::CdmFactory* cdm_factory,
+ const std::string& key_system,
const GURL& security_origin) {
DVLOG(1) << "InitializeCDM: key_system = " << key_system;
DCHECK(!media_keys_);
- media_keys_ = CreateMediaKeys(key_system, security_origin);
+ media_keys_ = CreateMediaKeys(cdm_factory, key_system, security_origin);
if (!media_keys_)
return false;
@@ -95,41 +72,59 @@ bool HasHeader(const uint8* data, int data_length, const std::string& header) {
std::equal(data, data + header.size(), header.begin());
}
-bool ProxyDecryptor::GenerateKeyRequest(const std::string& content_type,
+// Removes the first |length| items from |data|.
+void StripHeader(std::vector<uint8>& data, size_t length) {
+ data.erase(data.begin(), data.begin() + length);
+}
+
+bool ProxyDecryptor::GenerateKeyRequest(const std::string& init_data_type,
const uint8* init_data,
int init_data_length) {
DVLOG(1) << "GenerateKeyRequest()";
const char kPrefixedApiPersistentSessionHeader[] = "PERSISTENT|";
const char kPrefixedApiLoadSessionHeader[] = "LOAD_SESSION|";
- bool loadSession =
- HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader);
- bool persistent = HasHeader(
- init_data, init_data_length, kPrefixedApiPersistentSessionHeader);
+ SessionCreationType session_creation_type = TemporarySession;
+ std::vector<uint8> init_data_vector(init_data, init_data + init_data_length);
+ if (HasHeader(init_data, init_data_length, kPrefixedApiLoadSessionHeader)) {
+ session_creation_type = LoadSession;
+ StripHeader(init_data_vector, strlen(kPrefixedApiLoadSessionHeader));
+ } else if (HasHeader(init_data,
+ init_data_length,
+ kPrefixedApiPersistentSessionHeader)) {
+ session_creation_type = PersistentSession;
+ StripHeader(init_data_vector, strlen(kPrefixedApiPersistentSessionHeader));
+ }
scoped_ptr<media::NewSessionCdmPromise> promise(
- new media::NewSessionCdmPromise(
+ new media::CdmCallbackPromise<std::string>(
base::Bind(&ProxyDecryptor::SetSessionId,
weak_ptr_factory_.GetWeakPtr(),
- persistent || loadSession),
+ session_creation_type),
base::Bind(&ProxyDecryptor::OnSessionError,
weak_ptr_factory_.GetWeakPtr(),
std::string()))); // No session id until created.
+ uint8* init_data_vector_data =
+ (init_data_vector.size() > 0) ? &init_data_vector[0] : nullptr;
- if (loadSession) {
+ if (session_creation_type == LoadSession) {
media_keys_->LoadSession(
- std::string(reinterpret_cast<const char*>(
- init_data + strlen(kPrefixedApiLoadSessionHeader)),
- init_data_length - strlen(kPrefixedApiLoadSessionHeader)),
+ std::string(reinterpret_cast<const char*>(init_data_vector_data),
+ init_data_vector.size()),
promise.Pass());
return true;
}
media::MediaKeys::SessionType session_type =
- persistent ? media::MediaKeys::PERSISTENT_SESSION
- : media::MediaKeys::TEMPORARY_SESSION;
- media_keys_->CreateSession(
- content_type, init_data, init_data_length, session_type, promise.Pass());
+ session_creation_type == PersistentSession
+ ? media::MediaKeys::PERSISTENT_SESSION
+ : media::MediaKeys::TEMPORARY_SESSION;
+
+ media_keys_->CreateSession(init_data_type,
+ init_data_vector_data,
+ init_data_vector.size(),
+ session_type,
+ promise.Pass());
return true;
}
@@ -157,13 +152,13 @@ void ProxyDecryptor::AddKey(const uint8* key,
}
}
- scoped_ptr<media::SimpleCdmPromise> promise(
- new media::SimpleCdmPromise(base::Bind(&ProxyDecryptor::OnSessionReady,
- weak_ptr_factory_.GetWeakPtr(),
- web_session_id),
- base::Bind(&ProxyDecryptor::OnSessionError,
- weak_ptr_factory_.GetWeakPtr(),
- web_session_id)));
+ scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>(
+ base::Bind(&ProxyDecryptor::OnSessionReady,
+ weak_ptr_factory_.GetWeakPtr(),
+ web_session_id),
+ base::Bind(&ProxyDecryptor::OnSessionError,
+ weak_ptr_factory_.GetWeakPtr(),
+ web_session_id)));
// EME WD spec only supports a single array passed to the CDM. For
// Clear Key using v0.1b, both arrays are used (|init_data| is key_id).
@@ -194,45 +189,61 @@ void ProxyDecryptor::AddKey(const uint8* key,
void ProxyDecryptor::CancelKeyRequest(const std::string& web_session_id) {
DVLOG(1) << "CancelKeyRequest()";
- scoped_ptr<media::SimpleCdmPromise> promise(
- new media::SimpleCdmPromise(base::Bind(&ProxyDecryptor::OnSessionClosed,
- weak_ptr_factory_.GetWeakPtr(),
- web_session_id),
- base::Bind(&ProxyDecryptor::OnSessionError,
- weak_ptr_factory_.GetWeakPtr(),
- web_session_id)));
- media_keys_->ReleaseSession(web_session_id, promise.Pass());
+ scoped_ptr<media::SimpleCdmPromise> promise(new media::CdmCallbackPromise<>(
+ base::Bind(&ProxyDecryptor::OnSessionClosed,
+ weak_ptr_factory_.GetWeakPtr(),
+ web_session_id),
+ base::Bind(&ProxyDecryptor::OnSessionError,
+ weak_ptr_factory_.GetWeakPtr(),
+ web_session_id)));
+ media_keys_->RemoveSession(web_session_id, promise.Pass());
}
scoped_ptr<media::MediaKeys> ProxyDecryptor::CreateMediaKeys(
+ media::CdmFactory* cdm_factory,
const std::string& key_system,
const GURL& security_origin) {
- return ContentDecryptionModuleFactory::Create(
+ base::WeakPtr<ProxyDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr();
+ return cdm_factory->Create(
key_system,
security_origin,
-#if defined(ENABLE_PEPPER_CDMS)
- create_pepper_cdm_cb_,
-#elif defined(ENABLE_BROWSER_CDMS)
- manager_,
- &cdm_id_,
-#endif // defined(ENABLE_PEPPER_CDMS)
- base::Bind(&ProxyDecryptor::OnSessionMessage,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&ProxyDecryptor::OnSessionReady,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&ProxyDecryptor::OnSessionClosed,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&ProxyDecryptor::OnSessionError,
- weak_ptr_factory_.GetWeakPtr()));
+ base::Bind(&ProxyDecryptor::OnSessionMessage, weak_this),
+ base::Bind(&ProxyDecryptor::OnSessionReady, weak_this),
+ base::Bind(&ProxyDecryptor::OnSessionClosed, weak_this),
+ base::Bind(&ProxyDecryptor::OnSessionError, weak_this),
+ base::Bind(&ProxyDecryptor::OnSessionKeysChange, weak_this),
+ base::Bind(&ProxyDecryptor::OnSessionExpirationUpdate, weak_this));
}
void ProxyDecryptor::OnSessionMessage(const std::string& web_session_id,
const std::vector<uint8>& message,
const GURL& destination_url) {
// Assumes that OnSessionCreated() has been called before this.
+
+ // For ClearKey, convert the message from JSON into just passing the key
+ // as the message. If unable to extract the key, return the message unchanged.
+ if (is_clear_key_) {
+ std::vector<uint8> key;
+ if (media::ExtractFirstKeyIdFromLicenseRequest(message, &key)) {
+ key_message_cb_.Run(web_session_id, key, destination_url);
+ return;
+ }
+ }
+
key_message_cb_.Run(web_session_id, message, destination_url);
}
+void ProxyDecryptor::OnSessionKeysChange(const std::string& web_session_id,
+ bool has_additional_usable_key) {
+ // EME v0.1b doesn't support this event.
+}
+
+void ProxyDecryptor::OnSessionExpirationUpdate(
+ const std::string& web_session_id,
+ const base::Time& new_expiry_time) {
+ // EME v0.1b doesn't support this event.
+}
+
void ProxyDecryptor::OnSessionReady(const std::string& web_session_id) {
key_added_cb_.Run(web_session_id);
}
@@ -286,9 +297,16 @@ void ProxyDecryptor::OnSessionError(const std::string& web_session_id,
key_error_cb_.Run(web_session_id, error_code, system_code);
}
-void ProxyDecryptor::SetSessionId(bool persistent,
+void ProxyDecryptor::SetSessionId(SessionCreationType session_type,
const std::string& web_session_id) {
- active_sessions_.insert(std::make_pair(web_session_id, persistent));
+ // Loaded sessions are considered persistent.
+ bool is_persistent =
+ session_type == PersistentSession || session_type == LoadSession;
+ active_sessions_.insert(std::make_pair(web_session_id, is_persistent));
+
+ // For LoadSession(), generate the SessionReady event.
+ if (session_type == LoadSession)
+ OnSessionReady(web_session_id);
}
} // namespace content
diff --git a/chromium/content/renderer/media/crypto/proxy_decryptor.h b/chromium/content/renderer/media/crypto/proxy_decryptor.h
index e4fd7eace5e..62f2e8eb884 100644
--- a/chromium/content/renderer/media/crypto/proxy_decryptor.h
+++ b/chromium/content/renderer/media/crypto/proxy_decryptor.h
@@ -15,17 +15,13 @@
#include "media/base/decryptor.h"
#include "media/base/media_keys.h"
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/pepper_cdm_wrapper.h"
-#endif
-
class GURL;
-namespace content {
+namespace media {
+class CdmFactory;
+}
-#if defined(ENABLE_BROWSER_CDMS)
-class RendererCdmManager;
-#endif // defined(ENABLE_BROWSER_CDMS)
+namespace content {
// ProxyDecryptor is for EME v0.1b only. It should not be used for the WD API.
// A decryptor proxy that creates a real decryptor object on demand and
@@ -46,15 +42,9 @@ class ProxyDecryptor {
const std::vector<uint8>& message,
const GURL& destination_url)> KeyMessageCB;
- ProxyDecryptor(
-#if defined(ENABLE_PEPPER_CDMS)
- const CreatePepperCdmCB& create_pepper_cdm_cb,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
-#endif // defined(ENABLE_PEPPER_CDMS)
- const KeyAddedCB& key_added_cb,
- const KeyErrorCB& key_error_cb,
- const KeyMessageCB& key_message_cb);
+ ProxyDecryptor(const KeyAddedCB& key_added_cb,
+ const KeyErrorCB& key_error_cb,
+ const KeyMessageCB& key_message_cb);
virtual ~ProxyDecryptor();
// Returns the Decryptor associated with this object. May be NULL if no
@@ -68,11 +58,12 @@ class ProxyDecryptor {
#endif
// Only call this once.
- bool InitializeCDM(const std::string& key_system,
+ bool InitializeCDM(media::CdmFactory* cdm_factory,
+ const std::string& key_system,
const GURL& security_origin);
// May only be called after InitializeCDM() succeeds.
- bool GenerateKeyRequest(const std::string& type,
+ bool GenerateKeyRequest(const std::string& init_data_type,
const uint8* init_data,
int init_data_length);
void AddKey(const uint8* key, int key_length,
@@ -82,13 +73,19 @@ class ProxyDecryptor {
private:
// Helper function to create MediaKeys to handle the given |key_system|.
- scoped_ptr<media::MediaKeys> CreateMediaKeys(const std::string& key_system,
- const GURL& security_origin);
+ scoped_ptr<media::MediaKeys> CreateMediaKeys(
+ media::CdmFactory* cdm_factory,
+ const std::string& key_system,
+ const GURL& security_origin);
// Callbacks for firing session events.
void OnSessionMessage(const std::string& web_session_id,
const std::vector<uint8>& message,
const GURL& default_url);
+ void OnSessionKeysChange(const std::string& web_session_id,
+ bool has_additional_usable_key);
+ void OnSessionExpirationUpdate(const std::string& web_session_id,
+ const base::Time& new_expiry_time);
void OnSessionReady(const std::string& web_session_id);
void OnSessionClosed(const std::string& web_session_id);
void OnSessionError(const std::string& web_session_id,
@@ -96,16 +93,15 @@ class ProxyDecryptor {
uint32 system_code,
const std::string& error_message);
- // Called when a session is actually created or loaded.
- void SetSessionId(bool persistent, const std::string& web_session_id);
+ enum SessionCreationType {
+ TemporarySession,
+ PersistentSession,
+ LoadSession
+ };
-#if defined(ENABLE_PEPPER_CDMS)
- // Callback to create the Pepper plugin.
- CreatePepperCdmCB create_pepper_cdm_cb_;
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager_;
- int cdm_id_;
-#endif // defined(ENABLE_PEPPER_CDMS)
+ // Called when a session is actually created or loaded.
+ void SetSessionId(SessionCreationType session_type,
+ const std::string& web_session_id);
// The real MediaKeys that manages key operations for the ProxyDecryptor.
scoped_ptr<media::MediaKeys> media_keys_;
@@ -120,6 +116,10 @@ class ProxyDecryptor {
bool is_clear_key_;
+#if defined(ENABLE_BROWSER_CDMS)
+ int cdm_id_;
+#endif
+
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<ProxyDecryptor> weak_ptr_factory_;
diff --git a/chromium/content/renderer/media/crypto/proxy_media_keys.cc b/chromium/content/renderer/media/crypto/proxy_media_keys.cc
index 68a68b3bc37..e62c6cea1fd 100644
--- a/chromium/content/renderer/media/crypto/proxy_media_keys.cc
+++ b/chromium/content/renderer/media/crypto/proxy_media_keys.cc
@@ -22,8 +22,13 @@ scoped_ptr<ProxyMediaKeys> ProxyMediaKeys::Create(
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb) {
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb) {
DCHECK(manager);
+
+ // TODO(jrummell): Add support for SessionKeysChangeCB and
+ // SessionExpirationUpdateCB.
scoped_ptr<ProxyMediaKeys> proxy_media_keys(
new ProxyMediaKeys(manager,
session_message_cb,
@@ -48,6 +53,13 @@ ProxyMediaKeys::~ProxyMediaKeys() {
session_id_to_promise_map_.clear();
}
+void ProxyMediaKeys::SetServerCertificate(
+ const uint8* certificate_data,
+ int certificate_data_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented.");
+}
+
void ProxyMediaKeys::CreateSession(
const std::string& init_data_type,
const uint8* init_data,
@@ -57,9 +69,9 @@ void ProxyMediaKeys::CreateSession(
// TODO(xhwang): Move these checks up to blink and DCHECK here.
// See http://crbug.com/342510
CdmHostMsg_CreateSession_ContentType create_session_content_type;
- if (init_data_type == "audio/mp4" || init_data_type == "video/mp4") {
+ if (init_data_type == "cenc") {
create_session_content_type = CREATE_SESSION_TYPE_MP4;
- } else if (init_data_type == "audio/webm" || init_data_type == "video/webm") {
+ } else if (init_data_type == "webm") {
create_session_content_type = CREATE_SESSION_TYPE_WEBM;
} else {
DLOG(ERROR) << "Unsupported EME CreateSession content type of "
@@ -72,7 +84,7 @@ void ProxyMediaKeys::CreateSession(
}
uint32 session_id = CreateSessionId();
- SavePromise(session_id, promise.PassAs<media::CdmPromise>());
+ SavePromise(session_id, promise.Pass());
manager_->CreateSession(
cdm_id_,
session_id,
@@ -100,26 +112,40 @@ void ProxyMediaKeys::UpdateSession(
return;
}
- SavePromise(session_id, promise.PassAs<media::CdmPromise>());
+ SavePromise(session_id, promise.Pass());
manager_->UpdateSession(
cdm_id_,
session_id,
std::vector<uint8>(response, response + response_length));
}
-void ProxyMediaKeys::ReleaseSession(
- const std::string& web_session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+void ProxyMediaKeys::CloseSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
uint32 session_id = LookupSessionId(web_session_id);
if (!session_id) {
promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist.");
return;
}
- SavePromise(session_id, promise.PassAs<media::CdmPromise>());
+ SavePromise(session_id, promise.Pass());
manager_->ReleaseSession(cdm_id_, session_id);
}
+void ProxyMediaKeys::RemoveSession(
+ const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented.");
+}
+
+void ProxyMediaKeys::GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise) {
+ promise->reject(NOT_SUPPORTED_ERROR, 0, "Not yet implemented.");
+}
+
+int ProxyMediaKeys::GetCdmId() const {
+ return cdm_id_;
+}
+
void ProxyMediaKeys::OnSessionCreated(uint32 session_id,
const std::string& web_session_id) {
AssignWebSessionId(session_id, web_session_id);
@@ -196,10 +222,6 @@ void ProxyMediaKeys::OnSessionError(uint32 session_id,
web_session_id, exception_code, system_code, std::string());
}
-int ProxyMediaKeys::GetCdmId() const {
- return cdm_id_;
-}
-
ProxyMediaKeys::ProxyMediaKeys(
RendererCdmManager* manager,
const media::SessionMessageCB& session_message_cb,
diff --git a/chromium/content/renderer/media/crypto/proxy_media_keys.h b/chromium/content/renderer/media/crypto/proxy_media_keys.h
index 4ebd4c120f0..6b4df648276 100644
--- a/chromium/content/renderer/media/crypto/proxy_media_keys.h
+++ b/chromium/content/renderer/media/crypto/proxy_media_keys.h
@@ -30,28 +30,41 @@ class ProxyMediaKeys : public media::MediaKeys {
const media::SessionMessageCB& session_message_cb,
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb);
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb);
virtual ~ProxyMediaKeys();
// MediaKeys implementation.
+ virtual void SetServerCertificate(
+ const uint8* certificate_data,
+ int certificate_data_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
virtual void CreateSession(
const std::string& init_data_type,
const uint8* init_data,
int init_data_length,
SessionType session_type,
- scoped_ptr<media::NewSessionCdmPromise> promise) OVERRIDE;
+ scoped_ptr<media::NewSessionCdmPromise> promise) override;
virtual void LoadSession(
const std::string& web_session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise) OVERRIDE;
+ scoped_ptr<media::NewSessionCdmPromise> promise) override;
virtual void UpdateSession(
const std::string& web_session_id,
const uint8* response,
int response_length,
- scoped_ptr<media::SimpleCdmPromise> promise) OVERRIDE;
- virtual void ReleaseSession(
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ virtual void CloseSession(
const std::string& web_session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) OVERRIDE;
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ virtual void RemoveSession(
+ const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise) override;
+ virtual void GetUsableKeyIds(
+ const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise) override;
+ virtual int GetCdmId() const override;
// Callbacks.
void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
@@ -64,8 +77,6 @@ class ProxyMediaKeys : public media::MediaKeys {
media::MediaKeys::KeyError error_code,
uint32 system_code);
- int GetCdmId() const;
-
private:
// The Android-specific code that handles sessions uses integer session ids
// (basically a reference id), but media::MediaKeys bases everything on
diff --git a/chromium/content/renderer/media/crypto/render_cdm_factory.cc b/chromium/content/renderer/media/crypto/render_cdm_factory.cc
new file mode 100644
index 00000000000..63fec99ed31
--- /dev/null
+++ b/chromium/content/renderer/media/crypto/render_cdm_factory.cc
@@ -0,0 +1,83 @@
+// Copyright 2013 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 "content/renderer/media/crypto/render_cdm_factory.h"
+
+#include "base/logging.h"
+#include "content/renderer/media/crypto/key_systems.h"
+#include "media/cdm/aes_decryptor.h"
+#include "url/gurl.h"
+
+#if defined(ENABLE_PEPPER_CDMS)
+#include "content/renderer/media/crypto/ppapi_decryptor.h"
+#elif defined(ENABLE_BROWSER_CDMS)
+#include "content/renderer/media/crypto/proxy_media_keys.h"
+#endif // defined(ENABLE_PEPPER_CDMS)
+
+namespace content {
+
+#if defined(ENABLE_PEPPER_CDMS)
+RenderCdmFactory::RenderCdmFactory(
+ const CreatePepperCdmCB& create_pepper_cdm_cb)
+ : create_pepper_cdm_cb_(create_pepper_cdm_cb) {
+}
+#elif defined(ENABLE_BROWSER_CDMS)
+RenderCdmFactory::RenderCdmFactory(RendererCdmManager* manager)
+ : manager_(manager) {
+}
+#else
+RenderCdmFactory::RenderCdmFactory() {
+}
+#endif // defined(ENABLE_PEPPER_CDMS)
+
+RenderCdmFactory::~RenderCdmFactory() {
+}
+
+scoped_ptr<media::MediaKeys> RenderCdmFactory::Create(
+ const std::string& key_system,
+ const GURL& security_origin,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb) {
+ // TODO(jrummell): Pass |security_origin| to all constructors.
+ // TODO(jrummell): Enable the following line once blink code updated to
+ // check the security origin before calling.
+ // DCHECK(security_origin.is_valid());
+
+ if (CanUseAesDecryptor(key_system)) {
+ return scoped_ptr<media::MediaKeys>(new media::AesDecryptor(
+ session_message_cb, session_closed_cb, session_keys_change_cb));
+ }
+
+#if defined(ENABLE_PEPPER_CDMS)
+ return scoped_ptr<media::MediaKeys>(
+ PpapiDecryptor::Create(key_system,
+ security_origin,
+ create_pepper_cdm_cb_,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb,
+ session_keys_change_cb,
+ session_expiration_update_cb));
+#elif defined(ENABLE_BROWSER_CDMS)
+ return scoped_ptr<media::MediaKeys>(
+ ProxyMediaKeys::Create(key_system,
+ security_origin,
+ manager_,
+ session_message_cb,
+ session_ready_cb,
+ session_closed_cb,
+ session_error_cb,
+ session_keys_change_cb,
+ session_expiration_update_cb));
+#else
+ return nullptr;
+#endif // defined(ENABLE_PEPPER_CDMS)
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/crypto/render_cdm_factory.h b/chromium/content/renderer/media/crypto/render_cdm_factory.h
new file mode 100644
index 00000000000..f09f01bf433
--- /dev/null
+++ b/chromium/content/renderer/media/crypto/render_cdm_factory.h
@@ -0,0 +1,62 @@
+// Copyright 2013 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 CONTENT_RENDERER_MEDIA_CRYPTO_RENDER_CDM_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_CRYPTO_RENDER_CDM_FACTORY_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "media/base/cdm_factory.h"
+#include "media/base/media_keys.h"
+
+#if defined(ENABLE_PEPPER_CDMS)
+#include "content/renderer/media/crypto/pepper_cdm_wrapper.h"
+#endif
+
+class GURL;
+
+namespace content {
+
+#if defined(ENABLE_BROWSER_CDMS)
+class RendererCdmManager;
+#endif
+
+class RenderCdmFactory : public media::CdmFactory {
+ public:
+#if defined(ENABLE_PEPPER_CDMS)
+ explicit RenderCdmFactory(const CreatePepperCdmCB& create_pepper_cdm_cb);
+#elif defined(ENABLE_BROWSER_CDMS)
+ explicit RenderCdmFactory(RendererCdmManager* manager);
+#else
+ RenderCdmFactory();
+#endif // defined(ENABLE_PEPPER_CDMS)
+
+ ~RenderCdmFactory() override;
+
+ scoped_ptr<media::MediaKeys> Create(
+ const std::string& key_system,
+ const GURL& security_origin,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb)
+ override;
+
+ private:
+#if defined(ENABLE_PEPPER_CDMS)
+ CreatePepperCdmCB create_pepper_cdm_cb_;
+#elif defined(ENABLE_BROWSER_CDMS)
+ // The |manager_| is a per render frame object owned by RenderFrameImpl.
+ RendererCdmManager* manager_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(RenderCdmFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_CRYPTO_RENDER_CDM_FACTORY_H_
diff --git a/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc b/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc
index ba2e8783756..3bfdc6e0709 100644
--- a/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc
+++ b/chromium/content/renderer/media/crypto/renderer_cdm_manager.cc
@@ -18,7 +18,7 @@ const size_t kMaxSessionMessageLength = 10240; // 10 KB
RendererCdmManager::RendererCdmManager(RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
- next_cdm_id_(kInvalidCdmId + 1) {
+ next_cdm_id_(media::MediaKeys::kInvalidCdmId + 1) {
}
RendererCdmManager::~RendererCdmManager() {
@@ -127,7 +127,7 @@ void RendererCdmManager::OnSessionError(int cdm_id,
int RendererCdmManager::RegisterMediaKeys(ProxyMediaKeys* media_keys) {
int cdm_id = next_cdm_id_++;
- DCHECK_NE(cdm_id, kInvalidCdmId);
+ DCHECK_NE(cdm_id, media::MediaKeys::kInvalidCdmId);
DCHECK(!ContainsKey(proxy_media_keys_map_, cdm_id));
proxy_media_keys_map_[cdm_id] = media_keys;
return cdm_id;
diff --git a/chromium/content/renderer/media/crypto/renderer_cdm_manager.h b/chromium/content/renderer/media/crypto/renderer_cdm_manager.h
index a5ff82fc213..4944144685d 100644
--- a/chromium/content/renderer/media/crypto/renderer_cdm_manager.h
+++ b/chromium/content/renderer/media/crypto/renderer_cdm_manager.h
@@ -26,14 +26,12 @@ class ProxyMediaKeys;
// Class for managing all the CDM objects in the same RenderFrame.
class RendererCdmManager : public RenderFrameObserver {
public:
- static const int kInvalidCdmId = 0;
-
// Constructs a RendererCdmManager object for the |render_frame|.
explicit RendererCdmManager(RenderFrame* render_frame);
virtual ~RendererCdmManager();
// RenderFrameObserver overrides.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ virtual bool OnMessageReceived(const IPC::Message& msg) override;
// Encrypted media related methods.
void InitializeCdm(int cdm_id,
diff --git a/chromium/content/renderer/media/media_stream.cc b/chromium/content/renderer/media/media_stream.cc
index b555a75f2d3..245409a73c6 100644
--- a/chromium/content/renderer/media/media_stream.cc
+++ b/chromium/content/renderer/media/media_stream.cc
@@ -40,7 +40,7 @@ MediaStream::~MediaStream() {
webrtc::MediaStreamInterface* MediaStream::GetWebRtcAdapter(
const blink::WebMediaStream& stream) {
- DCHECK(webrtc_media_stream_);
+ DCHECK(webrtc_media_stream_.get());
DCHECK(thread_checker_.CalledOnValidThread());
return webrtc_media_stream_.get();
}
diff --git a/chromium/content/renderer/media/media_stream_audio_level_calculator.cc b/chromium/content/renderer/media/media_stream_audio_level_calculator.cc
index a136e32ae10..9994b695e11 100644
--- a/chromium/content/renderer/media/media_stream_audio_level_calculator.cc
+++ b/chromium/content/renderer/media/media_stream_audio_level_calculator.cc
@@ -38,9 +38,11 @@ MediaStreamAudioLevelCalculator::MediaStreamAudioLevelCalculator()
MediaStreamAudioLevelCalculator::~MediaStreamAudioLevelCalculator() {
}
-int MediaStreamAudioLevelCalculator::Calculate(const int16* audio_data,
- int number_of_channels,
- int number_of_frames) {
+int MediaStreamAudioLevelCalculator::Calculate(
+ const int16* audio_data,
+ int number_of_channels,
+ int number_of_frames,
+ bool force_report_nonzero_energy) {
DCHECK(thread_checker_.CalledOnValidThread());
// |level_| is updated every 10 callbacks. For the case where callback comes
// every 10ms, |level_| will be updated approximately every 100ms.
@@ -50,7 +52,8 @@ int MediaStreamAudioLevelCalculator::Calculate(const int16* audio_data,
max_amplitude_ = std::max(max_amplitude_, max);
if (counter_++ == kUpdateFrequency) {
- level_ = max_amplitude_;
+ level_ = (max_amplitude_ == 0 ?
+ force_report_nonzero_energy : max_amplitude_);
// Decay the absolute maximum amplitude by 1/4.
max_amplitude_ >>= 2;
diff --git a/chromium/content/renderer/media/media_stream_audio_level_calculator.h b/chromium/content/renderer/media/media_stream_audio_level_calculator.h
index 41c9c34f7be..48dda4ce0db 100644
--- a/chromium/content/renderer/media/media_stream_audio_level_calculator.h
+++ b/chromium/content/renderer/media/media_stream_audio_level_calculator.h
@@ -21,8 +21,14 @@ class MediaStreamAudioLevelCalculator {
// Calculates the signal level of the audio data.
// Returns the absolute value of the amplitude of the signal.
+ // |force_report_nonzero_energy| is a flag forcing the calculator to
+ // report nonzero energy even if the energy of the processed audio is zero.
+ // Since |audio_data| is post processed data, and the audio processing might
+ // zero all the audio data, when the caller detects the pre processed data
+ // contain energy, it could pass |force_report_nonzero_energy| as true to
+ // force calculator to report 1 as energy when |audio_data| is all zero.
int Calculate(const int16* audio_data, int number_of_channels,
- int number_of_frames);
+ int number_of_frames, bool force_report_nonzero_energy);
private:
// Used to DCHECK that the constructor and Calculate() are always called on
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.cc b/chromium/content/renderer/media/media_stream_audio_processor.cc
index 2e7a40db18c..548e74f5a2a 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor.cc
@@ -6,6 +6,9 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
+#if defined(OS_MACOSX)
+#include "base/metrics/field_trial.h"
+#endif
#include "base/metrics/histogram.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/media_stream_audio_processor_options.h"
@@ -31,10 +34,33 @@ const int kAudioProcessingSampleRate = 16000;
const int kAudioProcessingSampleRate = 32000;
#endif
const int kAudioProcessingNumberOfChannels = 1;
-const AudioProcessing::ChannelLayout kAudioProcessingChannelLayout =
- AudioProcessing::kMono;
-const int kMaxNumberOfBuffersInFifo = 2;
+AudioProcessing::ChannelLayout MapLayout(media::ChannelLayout media_layout) {
+ switch (media_layout) {
+ case media::CHANNEL_LAYOUT_MONO:
+ return AudioProcessing::kMono;
+ case media::CHANNEL_LAYOUT_STEREO:
+ return AudioProcessing::kStereo;
+ case media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC:
+ return AudioProcessing::kStereoAndKeyboard;
+ default:
+ NOTREACHED() << "Layout not supported: " << media_layout;
+ return AudioProcessing::kMono;
+ }
+}
+
+// This is only used for playout data where only max two channels is supported.
+AudioProcessing::ChannelLayout ChannelsToLayout(int num_channels) {
+ switch (num_channels) {
+ case 1:
+ return AudioProcessing::kMono;
+ case 2:
+ return AudioProcessing::kStereo;
+ default:
+ NOTREACHED() << "Channels not supported: " << num_channels;
+ return AudioProcessing::kMono;
+ }
+}
// Used by UMA histograms and entries shouldn't be re-ordered or removed.
enum AudioTrackProcessingStates {
@@ -51,122 +77,132 @@ void RecordProcessingState(AudioTrackProcessingStates state) {
} // namespace
-class MediaStreamAudioProcessor::MediaStreamAudioConverter
- : public media::AudioConverter::InputCallback {
+// Wraps AudioBus to provide access to the array of channel pointers, since this
+// is the type webrtc::AudioProcessing deals in. The array is refreshed on every
+// channel_ptrs() call, and will be valid until the underlying AudioBus pointers
+// are changed, e.g. through calls to SetChannelData() or SwapChannels().
+//
+// All methods are called on one of the capture or render audio threads
+// exclusively.
+class MediaStreamAudioBus {
public:
- MediaStreamAudioConverter(const media::AudioParameters& source_params,
- const media::AudioParameters& sink_params)
- : source_params_(source_params),
- sink_params_(sink_params),
- audio_converter_(source_params, sink_params_, false) {
- // An instance of MediaStreamAudioConverter may be created in the main
- // render thread and used in the audio thread, for example, the
- // |MediaStreamAudioProcessor::capture_converter_|.
+ MediaStreamAudioBus(int channels, int frames)
+ : bus_(media::AudioBus::Create(channels, frames)),
+ channel_ptrs_(new float*[channels]) {
+ // May be created in the main render thread and used in the audio threads.
thread_checker_.DetachFromThread();
- audio_converter_.AddInput(this);
-
- // Create and initialize audio fifo and audio bus wrapper.
- // The size of the FIFO should be at least twice of the source buffer size
- // or twice of the sink buffer size. Also, FIFO needs to have enough space
- // to store pre-processed data before passing the data to
- // webrtc::AudioProcessing, which requires 10ms as packet size.
- int max_frame_size = std::max(source_params_.frames_per_buffer(),
- sink_params_.frames_per_buffer());
- int buffer_size = std::max(
- kMaxNumberOfBuffersInFifo * max_frame_size,
- kMaxNumberOfBuffersInFifo * source_params_.sample_rate() / 100);
- fifo_.reset(new media::AudioFifo(source_params_.channels(), buffer_size));
-
- // TODO(xians): Use CreateWrapper to save one memcpy.
- audio_wrapper_ = media::AudioBus::Create(sink_params_.channels(),
- sink_params_.frames_per_buffer());
}
- virtual ~MediaStreamAudioConverter() {
- audio_converter_.RemoveInput(this);
- }
-
- void Push(const media::AudioBus* audio_source) {
- // Called on the audio thread, which is the capture audio thread for
- // |MediaStreamAudioProcessor::capture_converter_|, and render audio thread
- // for |MediaStreamAudioProcessor::render_converter_|.
- // And it must be the same thread as calling Convert().
+ media::AudioBus* bus() {
DCHECK(thread_checker_.CalledOnValidThread());
- fifo_->Push(audio_source);
+ return bus_.get();
}
- bool Convert(webrtc::AudioFrame* out, bool audio_mirroring) {
- // Called on the audio thread, which is the capture audio thread for
- // |MediaStreamAudioProcessor::capture_converter_|, and render audio thread
- // for |MediaStreamAudioProcessor::render_converter_|.
+ float* const* channel_ptrs() {
DCHECK(thread_checker_.CalledOnValidThread());
- // Return false if there is not enough data in the FIFO, this happens when
- // fifo_->frames() / source_params_.sample_rate() is less than
- // sink_params.frames_per_buffer() / sink_params.sample_rate().
- if (fifo_->frames() * sink_params_.sample_rate() <
- sink_params_.frames_per_buffer() * source_params_.sample_rate()) {
- return false;
+ for (int i = 0; i < bus_->channels(); ++i) {
+ channel_ptrs_[i] = bus_->channel(i);
}
+ return channel_ptrs_.get();
+ }
+
+ private:
+ base::ThreadChecker thread_checker_;
+ scoped_ptr<media::AudioBus> bus_;
+ scoped_ptr<float*[]> channel_ptrs_;
+};
- // Convert data to the output format, this will trigger ProvideInput().
- audio_converter_.Convert(audio_wrapper_.get());
- DCHECK_EQ(audio_wrapper_->frames(), sink_params_.frames_per_buffer());
+// Wraps AudioFifo to provide a cleaner interface to MediaStreamAudioProcessor.
+// It avoids the FIFO when the source and destination frames match. All methods
+// are called on one of the capture or render audio threads exclusively. If
+// |source_channels| is larger than |destination_channels|, only the first
+// |destination_channels| are kept from the source.
+class MediaStreamAudioFifo {
+ public:
+ MediaStreamAudioFifo(int source_channels,
+ int destination_channels,
+ int source_frames,
+ int destination_frames)
+ : source_channels_(source_channels),
+ source_frames_(source_frames),
+ destination_(
+ new MediaStreamAudioBus(destination_channels, destination_frames)),
+ data_available_(false) {
+ DCHECK_GE(source_channels, destination_channels);
+
+ if (source_channels > destination_channels) {
+ audio_source_intermediate_ =
+ media::AudioBus::CreateWrapper(destination_channels);
+ }
- // Swap channels before interleaving the data if |audio_mirroring| is
- // set to true.
- if (audio_mirroring &&
- sink_params_.channel_layout() == media::CHANNEL_LAYOUT_STEREO) {
- // Swap the first and second channels.
- audio_wrapper_->SwapChannels(0, 1);
+ if (source_frames != destination_frames) {
+ // Since we require every Push to be followed by as many Consumes as
+ // possible, twice the larger of the two is a (probably) loose upper bound
+ // on the FIFO size.
+ const int fifo_frames = 2 * std::max(source_frames, destination_frames);
+ fifo_.reset(new media::AudioFifo(destination_channels, fifo_frames));
}
- // TODO(xians): Figure out a better way to handle the interleaved and
- // deinterleaved format switching.
- audio_wrapper_->ToInterleaved(audio_wrapper_->frames(),
- sink_params_.bits_per_sample() / 8,
- out->data_);
+ // May be created in the main render thread and used in the audio threads.
+ thread_checker_.DetachFromThread();
+ }
- out->samples_per_channel_ = sink_params_.frames_per_buffer();
- out->sample_rate_hz_ = sink_params_.sample_rate();
- out->speech_type_ = webrtc::AudioFrame::kNormalSpeech;
- out->vad_activity_ = webrtc::AudioFrame::kVadUnknown;
- out->num_channels_ = sink_params_.channels();
+ void Push(const media::AudioBus* source) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(source->channels(), source_channels_);
+ DCHECK_EQ(source->frames(), source_frames_);
+
+ const media::AudioBus* source_to_push = source;
+
+ if (audio_source_intermediate_) {
+ for (int i = 0; i < destination_->bus()->channels(); ++i) {
+ audio_source_intermediate_->SetChannelData(
+ i,
+ const_cast<float*>(source->channel(i)));
+ }
+ audio_source_intermediate_->set_frames(source->frames());
+ source_to_push = audio_source_intermediate_.get();
+ }
- return true;
+ if (fifo_) {
+ fifo_->Push(source_to_push);
+ } else {
+ source_to_push->CopyTo(destination_->bus());
+ data_available_ = true;
+ }
}
- const media::AudioParameters& source_parameters() const {
- return source_params_;
- }
- const media::AudioParameters& sink_parameters() const {
- return sink_params_;
- }
+ // Returns true if there are destination_frames() of data available to be
+ // consumed, and otherwise false.
+ bool Consume(MediaStreamAudioBus** destination) {
+ DCHECK(thread_checker_.CalledOnValidThread());
- private:
- // AudioConverter::InputCallback implementation.
- virtual double ProvideInput(media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) OVERRIDE {
- // Called on realtime audio thread.
- // TODO(xians): Figure out why the first Convert() triggers ProvideInput
- // two times.
- if (fifo_->frames() < audio_bus->frames())
- return 0;
-
- fifo_->Consume(audio_bus, 0, audio_bus->frames());
-
- // Return 1.0 to indicate no volume scaling on the data.
- return 1.0;
+ if (fifo_) {
+ if (fifo_->frames() < destination_->bus()->frames())
+ return false;
+
+ fifo_->Consume(destination_->bus(), 0, destination_->bus()->frames());
+ } else {
+ if (!data_available_)
+ return false;
+
+ // The data was already copied to |destination_| in this case.
+ data_available_ = false;
+ }
+
+ *destination = destination_.get();
+ return true;
}
+ private:
base::ThreadChecker thread_checker_;
- const media::AudioParameters source_params_;
- const media::AudioParameters sink_params_;
-
- // TODO(xians): consider using SincResampler to save some memcpy.
- // Handles mixing and resampling between input and output parameters.
- media::AudioConverter audio_converter_;
- scoped_ptr<media::AudioBus> audio_wrapper_;
+ const int source_channels_; // For a DCHECK.
+ const int source_frames_; // For a DCHECK.
+ scoped_ptr<media::AudioBus> audio_source_intermediate_;
+ scoped_ptr<MediaStreamAudioBus> destination_;
scoped_ptr<media::AudioFifo> fifo_;
+ // Only used when the FIFO is disabled;
+ bool data_available_;
};
bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() {
@@ -191,7 +227,7 @@ MediaStreamAudioProcessor::MediaStreamAudioProcessor(
// In unit tests not creating a message filter, |aec_dump_message_filter_|
// will be NULL. We can just ignore that. Other unit tests and browser tests
// ensure that we do get the filter when we should.
- if (aec_dump_message_filter_)
+ if (aec_dump_message_filter_.get())
aec_dump_message_filter_->AddDelegate(this);
}
}
@@ -202,12 +238,12 @@ MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
}
void MediaStreamAudioProcessor::OnCaptureFormatChanged(
- const media::AudioParameters& source_params) {
+ const media::AudioParameters& input_format) {
DCHECK(main_thread_checker_.CalledOnValidThread());
// There is no need to hold a lock here since the caller guarantees that
// there is no more PushCaptureData() and ProcessAndConsumeData() callbacks
// on the capture thread.
- InitializeCaptureConverter(source_params);
+ InitializeCaptureFifo(input_format);
// Reset the |capture_thread_checker_| since the capture data will come from
// a new capture thread.
@@ -217,12 +253,8 @@ void MediaStreamAudioProcessor::OnCaptureFormatChanged(
void MediaStreamAudioProcessor::PushCaptureData(
const media::AudioBus* audio_source) {
DCHECK(capture_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(audio_source->channels(),
- capture_converter_->source_parameters().channels());
- DCHECK_EQ(audio_source->frames(),
- capture_converter_->source_parameters().frames_per_buffer());
- capture_converter_->Push(audio_source);
+ capture_fifo_->Push(audio_source);
}
bool MediaStreamAudioProcessor::ProcessAndConsumeData(
@@ -231,12 +263,31 @@ bool MediaStreamAudioProcessor::ProcessAndConsumeData(
DCHECK(capture_thread_checker_.CalledOnValidThread());
TRACE_EVENT0("audio", "MediaStreamAudioProcessor::ProcessAndConsumeData");
- if (!capture_converter_->Convert(&capture_frame_, audio_mirroring_))
+ MediaStreamAudioBus* process_bus;
+ if (!capture_fifo_->Consume(&process_bus))
return false;
- *new_volume = ProcessData(&capture_frame_, capture_delay, volume,
- key_pressed);
- *out = capture_frame_.data_;
+ // Use the process bus directly if audio processing is disabled.
+ MediaStreamAudioBus* output_bus = process_bus;
+ *new_volume = 0;
+ if (audio_processing_) {
+ output_bus = output_bus_.get();
+ *new_volume = ProcessData(process_bus->channel_ptrs(),
+ process_bus->bus()->frames(), capture_delay,
+ volume, key_pressed, output_bus->channel_ptrs());
+ }
+
+ // Swap channels before interleaving the data.
+ if (audio_mirroring_ &&
+ output_format_.channel_layout() == media::CHANNEL_LAYOUT_STEREO) {
+ // Swap the first and second channels.
+ output_bus->bus()->SwapChannels(0, 1);
+ }
+
+ output_bus->bus()->ToInterleaved(output_bus->bus()->frames(),
+ sizeof(int16),
+ output_data_.get());
+ *out = output_data_.get();
return true;
}
@@ -248,7 +299,7 @@ void MediaStreamAudioProcessor::Stop() {
stopped_ = true;
- if (aec_dump_message_filter_) {
+ if (aec_dump_message_filter_.get()) {
aec_dump_message_filter_->RemoveDelegate(this);
aec_dump_message_filter_ = NULL;
}
@@ -265,11 +316,11 @@ void MediaStreamAudioProcessor::Stop() {
}
const media::AudioParameters& MediaStreamAudioProcessor::InputFormat() const {
- return capture_converter_->source_parameters();
+ return input_format_;
}
const media::AudioParameters& MediaStreamAudioProcessor::OutputFormat() const {
- return capture_converter_->sink_parameters();
+ return output_format_;
}
void MediaStreamAudioProcessor::OnAecDumpFile(
@@ -308,12 +359,18 @@ void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
std::numeric_limits<base::subtle::Atomic32>::max());
base::subtle::Release_Store(&render_delay_ms_, audio_delay_milliseconds);
- InitializeRenderConverterIfNeeded(sample_rate, audio_bus->channels(),
- audio_bus->frames());
-
- render_converter_->Push(audio_bus);
- while (render_converter_->Convert(&render_frame_, false))
- audio_processing_->AnalyzeReverseStream(&render_frame_);
+ InitializeRenderFifoIfNeeded(sample_rate, audio_bus->channels(),
+ audio_bus->frames());
+
+ render_fifo_->Push(audio_bus);
+ MediaStreamAudioBus* analysis_bus;
+ while (render_fifo_->Consume(&analysis_bus)) {
+ audio_processing_->AnalyzeReverseStream(
+ analysis_bus->channel_ptrs(),
+ analysis_bus->bus()->frames(),
+ sample_rate,
+ ChannelsToLayout(audio_bus->channels()));
+ }
}
void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() {
@@ -321,17 +378,20 @@ void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() {
// There is no need to hold a lock here since the caller guarantees that
// there is no more OnPlayoutData() callback on the render thread.
render_thread_checker_.DetachFromThread();
- render_converter_.reset();
+ render_fifo_.reset();
}
void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) {
stats->typing_noise_detected =
(base::subtle::Acquire_Load(&typing_detected_) != false);
GetAecStats(audio_processing_.get(), stats);
+ if (echo_information_)
+ echo_information_.get()->UpdateAecDelayStats(stats->echo_delay_median_ms);
}
void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
const blink::WebMediaConstraints& constraints, int effects) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(!audio_processing_);
MediaAudioConstraints audio_constraints(constraints, effects);
@@ -382,32 +442,35 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
return;
}
+ // Experimental options provided at creation.
+ webrtc::Config config;
+ if (goog_experimental_aec)
+ config.Set<webrtc::DelayCorrection>(new webrtc::DelayCorrection(true));
+ if (goog_experimental_ns)
+ config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(true));
+#if defined(OS_MACOSX)
+ if (base::FieldTrialList::FindFullName("NoReportedDelayOnMac") == "Enabled")
+ config.Set<webrtc::ReportedDelay>(new webrtc::ReportedDelay(false));
+#endif
+
// Create and configure the webrtc::AudioProcessing.
- audio_processing_.reset(webrtc::AudioProcessing::Create());
- CHECK_EQ(0, audio_processing_->Initialize(kAudioProcessingSampleRate,
- kAudioProcessingSampleRate,
- kAudioProcessingSampleRate,
- kAudioProcessingChannelLayout,
- kAudioProcessingChannelLayout,
- kAudioProcessingChannelLayout));
+ audio_processing_.reset(webrtc::AudioProcessing::Create(config));
// Enable the audio processing components.
if (echo_cancellation) {
EnableEchoCancellation(audio_processing_.get());
- if (goog_experimental_aec)
- EnableExperimentalEchoCancellation(audio_processing_.get());
-
if (playout_data_source_)
playout_data_source_->AddPlayoutSink(this);
+
+ // Prepare for logging echo information. If there are data remaining in
+ // |echo_information_| we simply discard it.
+ echo_information_.reset(new EchoInformation());
}
if (goog_ns)
EnableNoiseSuppression(audio_processing_.get());
- if (goog_experimental_ns)
- EnableExperimentalNoiseSuppression(audio_processing_.get());
-
if (goog_high_pass_filter)
EnableHighPassFilter(audio_processing_.get());
@@ -424,82 +487,111 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
RecordProcessingState(AUDIO_PROCESSING_ENABLED);
}
-void MediaStreamAudioProcessor::InitializeCaptureConverter(
- const media::AudioParameters& source_params) {
+void MediaStreamAudioProcessor::InitializeCaptureFifo(
+ const media::AudioParameters& input_format) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK(source_params.IsValid());
-
- // Create and initialize audio converter for the source data.
- // When the webrtc AudioProcessing is enabled, the sink format of the
- // converter will be the same as the post-processed data format, which is
- // 32k mono for desktops and 16k mono for Android. When the AudioProcessing
- // is disabled, the sink format will be the same as the source format.
- const int sink_sample_rate = audio_processing_ ?
- kAudioProcessingSampleRate : source_params.sample_rate();
- const media::ChannelLayout sink_channel_layout = audio_processing_ ?
+ DCHECK(input_format.IsValid());
+ input_format_ = input_format;
+
+ // TODO(ajm): For now, we assume fixed parameters for the output when audio
+ // processing is enabled, to match the previous behavior. We should either
+ // use the input parameters (in which case, audio processing will convert
+ // at output) or ideally, have a backchannel from the sink to know what
+ // format it would prefer.
+ const int output_sample_rate = audio_processing_ ?
+ kAudioProcessingSampleRate : input_format.sample_rate();
+ media::ChannelLayout output_channel_layout = audio_processing_ ?
media::GuessChannelLayout(kAudioProcessingNumberOfChannels) :
- source_params.channel_layout();
-
- // WebRtc AudioProcessing requires 10ms as its packet size. We use this
- // native size when processing is enabled. While processing is disabled, and
- // the source is running with a buffer size smaller than 10ms buffer, we use
- // same buffer size as the incoming format to avoid extra FIFO for WebAudio.
- int sink_buffer_size = sink_sample_rate / 100;
- if (!audio_processing_ &&
- source_params.frames_per_buffer() < sink_buffer_size) {
- sink_buffer_size = source_params.frames_per_buffer();
+ input_format.channel_layout();
+
+ // The output channels from the fifo is normally the same as input.
+ int fifo_output_channels = input_format.channels();
+
+ // Special case for if we have a keyboard mic channel on the input and no
+ // audio processing is used. We will then have the fifo strip away that
+ // channel. So we use stereo as output layout, and also change the output
+ // channels for the fifo.
+ if (input_format.channel_layout() ==
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC &&
+ !audio_processing_) {
+ output_channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ fifo_output_channels = ChannelLayoutToChannelCount(output_channel_layout);
}
- media::AudioParameters sink_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY, sink_channel_layout,
- sink_sample_rate, 16, sink_buffer_size);
- capture_converter_.reset(
- new MediaStreamAudioConverter(source_params, sink_params));
+ // webrtc::AudioProcessing requires a 10 ms chunk size. We use this native
+ // size when processing is enabled. When disabled we use the same size as
+ // the source if less than 10 ms.
+ //
+ // TODO(ajm): This conditional buffer size appears to be assuming knowledge of
+ // the sink based on the source parameters. PeerConnection sinks seem to want
+ // 10 ms chunks regardless, while WebAudio sinks want less, and we're assuming
+ // we can identify WebAudio sinks by the input chunk size. Less fragile would
+ // be to have the sink actually tell us how much it wants (as in the above
+ // TODO).
+ int processing_frames = input_format.sample_rate() / 100;
+ int output_frames = output_sample_rate / 100;
+ if (!audio_processing_ && input_format.frames_per_buffer() < output_frames) {
+ processing_frames = input_format.frames_per_buffer();
+ output_frames = processing_frames;
+ }
+
+ output_format_ = media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ output_channel_layout,
+ output_sample_rate,
+ 16,
+ output_frames);
+
+ capture_fifo_.reset(
+ new MediaStreamAudioFifo(input_format.channels(),
+ fifo_output_channels,
+ input_format.frames_per_buffer(),
+ processing_frames));
+
+ if (audio_processing_) {
+ output_bus_.reset(new MediaStreamAudioBus(output_format_.channels(),
+ output_frames));
+ }
+ output_data_.reset(new int16[output_format_.GetBytesPerBuffer() /
+ sizeof(int16)]);
}
-void MediaStreamAudioProcessor::InitializeRenderConverterIfNeeded(
+void MediaStreamAudioProcessor::InitializeRenderFifoIfNeeded(
int sample_rate, int number_of_channels, int frames_per_buffer) {
DCHECK(render_thread_checker_.CalledOnValidThread());
- // TODO(xians): Figure out if we need to handle the buffer size change.
- if (render_converter_.get() &&
- render_converter_->source_parameters().sample_rate() == sample_rate &&
- render_converter_->source_parameters().channels() == number_of_channels) {
- // Do nothing if the |render_converter_| has been setup properly.
+ if (render_fifo_.get() &&
+ render_format_.sample_rate() == sample_rate &&
+ render_format_.channels() == number_of_channels &&
+ render_format_.frames_per_buffer() == frames_per_buffer) {
+ // Do nothing if the |render_fifo_| has been setup properly.
return;
}
- // Create and initialize audio converter for the render data.
- // webrtc::AudioProcessing accepts the same format as what it uses to process
- // capture data, which is 32k mono for desktops and 16k mono for Android.
- media::AudioParameters source_params(
+ render_format_ = media::AudioParameters(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::GuessChannelLayout(number_of_channels), sample_rate, 16,
+ media::GuessChannelLayout(number_of_channels),
+ sample_rate,
+ 16,
frames_per_buffer);
- media::AudioParameters sink_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, kAudioProcessingSampleRate, 16,
- kAudioProcessingSampleRate / 100);
- render_converter_.reset(
- new MediaStreamAudioConverter(source_params, sink_params));
- render_data_bus_ = media::AudioBus::Create(number_of_channels,
- frames_per_buffer);
+
+ const int analysis_frames = sample_rate / 100; // 10 ms chunks.
+ render_fifo_.reset(
+ new MediaStreamAudioFifo(number_of_channels,
+ number_of_channels,
+ frames_per_buffer,
+ analysis_frames));
}
-int MediaStreamAudioProcessor::ProcessData(webrtc::AudioFrame* audio_frame,
+int MediaStreamAudioProcessor::ProcessData(const float* const* process_ptrs,
+ int process_frames,
base::TimeDelta capture_delay,
int volume,
- bool key_pressed) {
+ bool key_pressed,
+ float* const* output_ptrs) {
+ DCHECK(audio_processing_);
DCHECK(capture_thread_checker_.CalledOnValidThread());
- if (!audio_processing_)
- return 0;
TRACE_EVENT0("audio", "MediaStreamAudioProcessor::ProcessData");
- DCHECK_EQ(audio_processing_->input_sample_rate_hz(),
- capture_converter_->sink_parameters().sample_rate());
- DCHECK_EQ(audio_processing_->num_input_channels(),
- capture_converter_->sink_parameters().channels());
- DCHECK_EQ(audio_processing_->num_output_channels(),
- capture_converter_->sink_parameters().channels());
base::subtle::Atomic32 render_delay_ms =
base::subtle::Acquire_Load(&render_delay_ms_);
@@ -512,28 +604,34 @@ int MediaStreamAudioProcessor::ProcessData(webrtc::AudioFrame* audio_frame,
<< "ms; render delay: " << render_delay_ms << "ms";
}
- audio_processing_->set_stream_delay_ms(total_delay_ms);
+ webrtc::AudioProcessing* ap = audio_processing_.get();
+ ap->set_stream_delay_ms(total_delay_ms);
DCHECK_LE(volume, WebRtcAudioDeviceImpl::kMaxVolumeLevel);
- webrtc::GainControl* agc = audio_processing_->gain_control();
+ webrtc::GainControl* agc = ap->gain_control();
int err = agc->set_stream_analog_level(volume);
DCHECK_EQ(err, 0) << "set_stream_analog_level() error: " << err;
- audio_processing_->set_stream_key_pressed(key_pressed);
+ ap->set_stream_key_pressed(key_pressed);
- err = audio_processing_->ProcessStream(audio_frame);
+ err = ap->ProcessStream(process_ptrs,
+ process_frames,
+ input_format_.sample_rate(),
+ MapLayout(input_format_.channel_layout()),
+ output_format_.sample_rate(),
+ MapLayout(output_format_.channel_layout()),
+ output_ptrs);
DCHECK_EQ(err, 0) << "ProcessStream() error: " << err;
- if (typing_detector_ &&
- audio_frame->vad_activity_ != webrtc::AudioFrame::kVadUnknown) {
- bool vad_active =
- (audio_frame->vad_activity_ == webrtc::AudioFrame::kVadActive);
- bool typing_detected = typing_detector_->Process(key_pressed, vad_active);
- base::subtle::Release_Store(&typing_detected_, typing_detected);
+ if (typing_detector_) {
+ webrtc::VoiceDetection* vad = ap->voice_detection();
+ DCHECK(vad->is_enabled());
+ bool detected = typing_detector_->Process(key_pressed,
+ vad->stream_has_voice());
+ base::subtle::Release_Store(&typing_detected_, detected);
}
- // Return 0 if the volume has not been changed, otherwise return the new
- // volume.
+ // Return 0 if the volume hasn't been changed, and otherwise the new volume.
return (agc->stream_analog_level() == volume) ?
0 : agc->stream_analog_level();
}
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.h b/chromium/content/renderer/media/media_stream_audio_processor.h
index 035a87edcd0..a905b3f6518 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor.h
+++ b/chromium/content/renderer/media/media_stream_audio_processor.h
@@ -35,6 +35,9 @@ class TypingDetection;
namespace content {
+class EchoInformation;
+class MediaStreamAudioBus;
+class MediaStreamAudioFifo;
class RTCMediaConstraints;
using webrtc::AudioProcessorInterface;
@@ -59,30 +62,32 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
int effects,
WebRtcPlayoutDataSource* playout_data_source);
- // Called when format of the capture data has changed.
- // Called on the main render thread. The caller is responsible for stopping
+ // Called when the format of the capture data has changed.
+ // Called on the main render thread. The caller is responsible for stopping
// the capture thread before calling this method.
// After this method, the capture thread will be changed to a new capture
// thread.
void OnCaptureFormatChanged(const media::AudioParameters& source_params);
- // Pushes capture data in |audio_source| to the internal FIFO.
+ // Pushes capture data in |audio_source| to the internal FIFO. Each call to
+ // this method should be followed by calls to ProcessAndConsumeData() while
+ // it returns false, to pull out all available data.
// Called on the capture audio thread.
void PushCaptureData(const media::AudioBus* audio_source);
// Processes a block of 10 ms data from the internal FIFO and outputs it via
// |out|. |out| is the address of the pointer that will be pointed to
// the post-processed data if the method is returning a true. The lifetime
- // of the data represeted by |out| is guaranteed to outlive the method call.
- // That also says *|out| won't change until this method is called again.
+ // of the data represeted by |out| is guaranteed until this method is called
+ // again.
// |new_volume| receives the new microphone volume from the AGC.
- // The new microphoen volume range is [0, 255], and the value will be 0 if
+ // The new microphone volume range is [0, 255], and the value will be 0 if
// the microphone volume should not be adjusted.
// Returns true if the internal FIFO has at least 10 ms data for processing,
// otherwise false.
- // |capture_delay|, |volume| and |key_pressed| will be passed to
- // webrtc::AudioProcessing to help processing the data.
// Called on the capture audio thread.
+ //
+ // TODO(ajm): Don't we want this to output float?
bool ProcessAndConsumeData(base::TimeDelta capture_delay,
int volume,
bool key_pressed,
@@ -93,10 +98,9 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// this method.
void Stop();
- // The audio format of the input to the processor.
+ // The audio formats of the capture input to and output from the processor.
+ // Must only be called on the main render or audio capture threads.
const media::AudioParameters& InputFormat() const;
-
- // The audio format of the output from the processor.
const media::AudioParameters& OutputFormat() const;
// Accessor to check if the audio processing is enabled or not.
@@ -104,93 +108,90 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// AecDumpMessageFilter::AecDumpDelegate implementation.
// Called on the main render thread.
- virtual void OnAecDumpFile(
- const IPC::PlatformFileForTransit& file_handle) OVERRIDE;
- virtual void OnDisableAecDump() OVERRIDE;
- virtual void OnIpcClosing() OVERRIDE;
+ void OnAecDumpFile(const IPC::PlatformFileForTransit& file_handle) override;
+ void OnDisableAecDump() override;
+ void OnIpcClosing() override;
protected:
- friend class base::RefCountedThreadSafe<MediaStreamAudioProcessor>;
- virtual ~MediaStreamAudioProcessor();
+ ~MediaStreamAudioProcessor() override;
private:
friend class MediaStreamAudioProcessorTest;
-
- class MediaStreamAudioConverter;
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamAudioProcessorTest,
+ GetAecDumpMessageFilter);
// WebRtcPlayoutDataSource::Sink implementation.
- virtual void OnPlayoutData(media::AudioBus* audio_bus,
- int sample_rate,
- int audio_delay_milliseconds) OVERRIDE;
- virtual void OnPlayoutDataSourceChanged() OVERRIDE;
+ void OnPlayoutData(media::AudioBus* audio_bus,
+ int sample_rate,
+ int audio_delay_milliseconds) override;
+ void OnPlayoutDataSourceChanged() override;
// webrtc::AudioProcessorInterface implementation.
// This method is called on the libjingle thread.
- virtual void GetStats(AudioProcessorStats* stats) OVERRIDE;
+ void GetStats(AudioProcessorStats* stats) override;
// Helper to initialize the WebRtc AudioProcessing.
void InitializeAudioProcessingModule(
const blink::WebMediaConstraints& constraints, int effects);
// Helper to initialize the capture converter.
- void InitializeCaptureConverter(const media::AudioParameters& source_params);
+ void InitializeCaptureFifo(const media::AudioParameters& input_format);
// Helper to initialize the render converter.
- void InitializeRenderConverterIfNeeded(int sample_rate,
- int number_of_channels,
- int frames_per_buffer);
+ void InitializeRenderFifoIfNeeded(int sample_rate,
+ int number_of_channels,
+ int frames_per_buffer);
// Called by ProcessAndConsumeData().
// Returns the new microphone volume in the range of |0, 255].
// When the volume does not need to be updated, it returns 0.
- int ProcessData(webrtc::AudioFrame* audio_frame,
+ int ProcessData(const float* const* process_ptrs,
+ int process_frames,
base::TimeDelta capture_delay,
int volume,
- bool key_pressed);
+ bool key_pressed,
+ float* const* output_ptrs);
// Cached value for the render delay latency. This member is accessed by
// both the capture audio thread and the render audio thread.
base::subtle::Atomic32 render_delay_ms_;
- // webrtc::AudioProcessing module which does AEC, AGC, NS, HighPass filter,
- // ..etc.
+ // Module to handle processing and format conversion.
scoped_ptr<webrtc::AudioProcessing> audio_processing_;
- // Converter used for the down-mixing and resampling of the capture data.
- scoped_ptr<MediaStreamAudioConverter> capture_converter_;
-
- // AudioFrame used to hold the output of |capture_converter_|.
- webrtc::AudioFrame capture_frame_;
+ // FIFO to provide 10 ms capture chunks.
+ scoped_ptr<MediaStreamAudioFifo> capture_fifo_;
+ // Receives processing output.
+ scoped_ptr<MediaStreamAudioBus> output_bus_;
+ // Receives interleaved int16 data for output.
+ scoped_ptr<int16[]> output_data_;
- // Converter used for the down-mixing and resampling of the render data when
- // the AEC is enabled.
- scoped_ptr<MediaStreamAudioConverter> render_converter_;
+ // FIFO to provide 10 ms render chunks when the AEC is enabled.
+ scoped_ptr<MediaStreamAudioFifo> render_fifo_;
- // AudioFrame used to hold the output of |render_converter_|.
- webrtc::AudioFrame render_frame_;
-
- // Data bus to help converting interleaved data to an AudioBus.
- scoped_ptr<media::AudioBus> render_data_bus_;
+ // These are mutated on the main render thread in OnCaptureFormatChanged().
+ // The caller guarantees this does not run concurrently with accesses on the
+ // capture audio thread.
+ media::AudioParameters input_format_;
+ media::AudioParameters output_format_;
+ // Only used on the render audio thread.
+ media::AudioParameters render_format_;
// Raw pointer to the WebRtcPlayoutDataSource, which is valid for the
// lifetime of RenderThread.
WebRtcPlayoutDataSource* playout_data_source_;
- // Used to DCHECK that the destructor is called on the main render thread.
+ // Used to DCHECK that some methods are called on the main render thread.
base::ThreadChecker main_thread_checker_;
-
// Used to DCHECK that some methods are called on the capture audio thread.
base::ThreadChecker capture_thread_checker_;
-
- // Used to DCHECK that PushRenderData() is called on the render audio thread.
+ // Used to DCHECK that some methods are called on the render audio thread.
base::ThreadChecker render_thread_checker_;
- // Flag to enable the stereo channels mirroring.
+ // Flag to enable stereo channel mirroring.
bool audio_mirroring_;
- // Used by the typing detection.
scoped_ptr<webrtc::TypingDetection> typing_detector_;
-
// This flag is used to show the result of typing detection.
// It can be accessed by the capture audio thread and by the libjingle thread
// which calls GetStats().
@@ -201,6 +202,12 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// Flag to avoid executing Stop() more than once.
bool stopped_;
+
+ // Object for logging echo information when the AEC is enabled. Accessible by
+ // the libjingle thread through GetStats().
+ scoped_ptr<EchoInformation> echo_information_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioProcessor);
};
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
index 5ebb2a2a91e..537ef908b14 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_options.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
@@ -4,13 +4,14 @@
#include "content/renderer/media/media_stream_audio_processor_options.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
-#include "base/path_service.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "content/common/media/media_stream_options.h"
#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_source.h"
@@ -49,11 +50,11 @@ struct {
} const kDefaultAudioConstraints[] = {
{ MediaAudioConstraints::kEchoCancellation, true },
{ MediaAudioConstraints::kGoogEchoCancellation, true },
-#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
- // Enable the extended filter mode AEC on platforms with known echo issues.
- { MediaAudioConstraints::kGoogExperimentalEchoCancellation, true },
-#else
+#if defined(OS_ANDROID) || defined(OS_IOS)
{ MediaAudioConstraints::kGoogExperimentalEchoCancellation, false },
+#else
+ // Enable the extended filter mode AEC on all non-mobile platforms.
+ { MediaAudioConstraints::kGoogExperimentalEchoCancellation, true },
#endif
{ MediaAudioConstraints::kGoogAutoGainControl, true },
{ MediaAudioConstraints::kGoogExperimentalAutoGainControl, true },
@@ -73,12 +74,37 @@ bool IsAudioProcessingConstraint(const std::string& key) {
return key != kMediaStreamAudioDucking;
}
-} // namespace
+// Used to log echo quality based on delay estimates.
+enum DelayBasedEchoQuality {
+ DELAY_BASED_ECHO_QUALITY_GOOD = 0,
+ DELAY_BASED_ECHO_QUALITY_SPURIOUS,
+ DELAY_BASED_ECHO_QUALITY_BAD,
+ DELAY_BASED_ECHO_QUALITY_MAX
+};
+
+DelayBasedEchoQuality EchoDelayFrequencyToQuality(float delay_frequency) {
+ const float kEchoDelayFrequencyLowerLimit = 0.1f;
+ const float kEchoDelayFrequencyUpperLimit = 0.8f;
+ // DELAY_BASED_ECHO_QUALITY_GOOD
+ // delay is out of bounds during at most 10 % of the time.
+ // DELAY_BASED_ECHO_QUALITY_SPURIOUS
+ // delay is out of bounds 10-80 % of the time.
+ // DELAY_BASED_ECHO_QUALITY_BAD
+ // delay is mostly out of bounds >= 80 % of the time.
+ if (delay_frequency <= kEchoDelayFrequencyLowerLimit)
+ return DELAY_BASED_ECHO_QUALITY_GOOD;
+ else if (delay_frequency < kEchoDelayFrequencyUpperLimit)
+ return DELAY_BASED_ECHO_QUALITY_SPURIOUS;
+ else
+ return DELAY_BASED_ECHO_QUALITY_BAD;
+}
+
+} // namespace
// TODO(xians): Remove this method after the APM in WebRtc is deprecated.
void MediaAudioConstraints::ApplyFixedAudioConstraints(
RTCMediaConstraints* constraints) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
+ for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
bool already_set_value;
if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key,
&already_set_value, NULL)) {
@@ -119,7 +145,7 @@ bool MediaAudioConstraints::NeedsAudioProcessing() {
if (GetEchoCancellationProperty())
return true;
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
+ for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
// |kEchoCancellation| and |kGoogEchoCancellation| have been convered by
// GetEchoCancellationProperty().
if (kDefaultAudioConstraints[i].key != kEchoCancellation &&
@@ -169,7 +195,7 @@ bool MediaAudioConstraints::IsValid() {
}
bool valid = false;
- for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++j) {
+ for (size_t j = 0; j < arraysize(kDefaultAudioConstraints); ++j) {
if (key == kDefaultAudioConstraints[j].key) {
bool value = false;
valid = GetMandatoryConstraintValueAsBoolean(constraints_, key, &value);
@@ -195,7 +221,7 @@ bool MediaAudioConstraints::GetDefaultValueForConstraint(
IsAudioProcessingConstraint(key))
return false;
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDefaultAudioConstraints); ++i) {
+ for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
if (kDefaultAudioConstraints[i].key == key)
return kDefaultAudioConstraints[i].value;
}
@@ -203,6 +229,55 @@ bool MediaAudioConstraints::GetDefaultValueForConstraint(
return false;
}
+EchoInformation::EchoInformation()
+ : echo_poor_delay_counts_(0),
+ echo_total_delay_counts_(0),
+ last_log_time_(base::TimeTicks::Now()) {}
+
+EchoInformation::~EchoInformation() {}
+
+void EchoInformation::UpdateAecDelayStats(int delay) {
+ // One way to get an indication of how well the echo cancellation performs is
+ // to compare the, by AEC, estimated delay with the AEC filter length.
+ // |kMaxAecFilterLengthMs| is the maximum delay we can allow before we
+ // consider the AEC to fail. This value should not be larger than the filter
+ // length used inside AEC. This is for now set to match the extended filter
+ // mode which is turned on for all platforms.
+ const int kMaxAecFilterLengthMs = 128;
+ if ((delay < -2) || (delay > kMaxAecFilterLengthMs)) {
+ // The |delay| is out of bounds which indicates that the echo cancellation
+ // filter can not handle the echo. Hence, we have a potential full echo
+ // case. |delay| values {-1, -2} are reserved for errors.
+ ++echo_poor_delay_counts_;
+ }
+ ++echo_total_delay_counts_;
+ LogAecDelayStats();
+}
+
+void EchoInformation::LogAecDelayStats() {
+ // We update the UMA statistics every 5 seconds.
+ const int kTimeBetweenLogsInSeconds = 5;
+ const base::TimeDelta time_since_last_log =
+ base::TimeTicks::Now() - last_log_time_;
+ if (time_since_last_log.InSeconds() < kTimeBetweenLogsInSeconds)
+ return;
+
+ // Calculate how frequent the AEC delay was out of bounds since last time we
+ // updated UMA histograms. Then store the result into one of three histogram
+ // buckets; see DelayBasedEchoQuality.
+ float poor_delay_frequency = 0.f;
+ if (echo_total_delay_counts_ > 0) {
+ poor_delay_frequency = static_cast<float>(echo_poor_delay_counts_) /
+ static_cast<float>(echo_total_delay_counts_);
+ UMA_HISTOGRAM_ENUMERATION("Media.AecDelayBasedQuality",
+ EchoDelayFrequencyToQuality(poor_delay_frequency),
+ DELAY_BASED_ECHO_QUALITY_MAX);
+ }
+ echo_poor_delay_counts_ = 0;
+ echo_total_delay_counts_ = 0;
+ last_log_time_ = base::TimeTicks::Now();
+}
+
void EnableEchoCancellation(AudioProcessing* audio_processing) {
#if defined(OS_ANDROID) || defined(OS_IOS)
const std::string group_name =
@@ -233,10 +308,6 @@ void EnableNoiseSuppression(AudioProcessing* audio_processing) {
CHECK_EQ(err, 0);
}
-void EnableExperimentalNoiseSuppression(AudioProcessing* audio_processing) {
- CHECK_EQ(audio_processing->EnableExperimentalNs(true), 0);
-}
-
void EnableHighPassFilter(AudioProcessing* audio_processing) {
CHECK_EQ(audio_processing->high_pass_filter()->Enable(true), 0);
}
@@ -252,12 +323,6 @@ void EnableTypingDetection(AudioProcessing* audio_processing,
typing_detector->SetParameters(0, 0, 0, 0, 0, 100);
}
-void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing) {
- webrtc::Config config;
- config.Set<webrtc::DelayCorrection>(new webrtc::DelayCorrection(true));
- audio_processing->SetExtraOptions(config);
-}
-
void StartEchoCancellationDump(AudioProcessing* audio_processing,
base::File aec_dump_file) {
DCHECK(aec_dump_file.IsValid());
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.h b/chromium/content/renderer/media/media_stream_audio_processor_options.h
index 468355547f5..66476597d7f 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_options.h
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/files/file.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -88,15 +89,35 @@ class CONTENT_EXPORT MediaAudioConstraints {
bool default_audio_processing_constraint_value_;
};
+// A helper class to log echo information in general and Echo Cancellation
+// quality in particular.
+class CONTENT_EXPORT EchoInformation {
+ public:
+ EchoInformation();
+ virtual ~EchoInformation();
+
+ // Updates delay statistics with a new |delay|.
+ void UpdateAecDelayStats(int delay);
+
+ private:
+ // Updates UMA histograms with an interval of |kTimeBetweenLogsInSeconds|.
+ void LogAecDelayStats();
+
+ // Counters for determining how often the estimated delay in the AEC is out of
+ // bounds.
+ int echo_poor_delay_counts_;
+ int echo_total_delay_counts_;
+ base::TimeTicks last_log_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(EchoInformation);
+};
+
// Enables the echo cancellation in |audio_processing|.
void EnableEchoCancellation(AudioProcessing* audio_processing);
// Enables the noise suppression in |audio_processing|.
void EnableNoiseSuppression(AudioProcessing* audio_processing);
-// Enables the experimental noise suppression in |audio_processing|.
-void EnableExperimentalNoiseSuppression(AudioProcessing* audio_processing);
-
// Enables the high pass filter in |audio_processing|.
void EnableHighPassFilter(AudioProcessing* audio_processing);
@@ -104,9 +125,6 @@ void EnableHighPassFilter(AudioProcessing* audio_processing);
void EnableTypingDetection(AudioProcessing* audio_processing,
webrtc::TypingDetection* typing_detector);
-// Enables the experimental echo cancellation in |audio_processing|.
-void EnableExperimentalEchoCancellation(AudioProcessing* audio_processing);
-
// Starts the echo cancellation dump in |audio_processing|.
void StartEchoCancellationDump(AudioProcessing* audio_processing,
base::File aec_dump_file);
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
index d9cddf47005..91d7b32847d 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "base/command_line.h"
-#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/aligned_memory.h"
#include "base/path_service.h"
@@ -40,6 +40,8 @@ const int kAudioProcessingNumberOfChannel = 1;
// The number of packers used for testing.
const int kNumberOfPacketsForTest = 100;
+const int kMaxNumberOfPlayoutDataChannels = 2;
+
void ReadDataFromSpeechFile(char* data, int length) {
base::FilePath file;
CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file));
@@ -79,6 +81,19 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
const int16* data_ptr = reinterpret_cast<const int16*>(capture_data.get());
scoped_ptr<media::AudioBus> data_bus = media::AudioBus::Create(
params.channels(), params.frames_per_buffer());
+
+ // |data_bus_playout| is used if the number of capture channels is larger
+ // that max allowed playout channels. |data_bus_playout_to_use| points to
+ // the AudioBus to use, either |data_bus| or |data_bus_playout|.
+ scoped_ptr<media::AudioBus> data_bus_playout;
+ media::AudioBus* data_bus_playout_to_use = data_bus.get();
+ if (params.channels() > kMaxNumberOfPlayoutDataChannels) {
+ data_bus_playout =
+ media::AudioBus::CreateWrapper(kMaxNumberOfPlayoutDataChannels);
+ data_bus_playout->set_frames(params.frames_per_buffer());
+ data_bus_playout_to_use = data_bus_playout.get();
+ }
+
for (int i = 0; i < kNumberOfPacketsForTest; ++i) {
data_bus->FromInterleaved(data_ptr, data_bus->frames(), 2);
audio_processor->PushCaptureData(data_bus.get());
@@ -94,8 +109,14 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
const bool is_aec_enabled = ap && ap->echo_cancellation()->is_enabled();
#endif
if (is_aec_enabled) {
- audio_processor->OnPlayoutData(data_bus.get(), params.sample_rate(),
- 10);
+ if (params.channels() > kMaxNumberOfPlayoutDataChannels) {
+ for (int i = 0; i < kMaxNumberOfPlayoutDataChannels; ++i) {
+ data_bus_playout->SetChannelData(
+ i, const_cast<float*>(data_bus->channel(i)));
+ }
+ }
+ audio_processor->OnPlayoutData(data_bus_playout_to_use,
+ params.sample_rate(), 10);
}
int16* output = NULL;
@@ -162,13 +183,13 @@ TEST_F(MediaStreamAudioProcessorTest, WithoutAudioProcessing) {
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get()));
EXPECT_FALSE(audio_processor->has_audio_processing());
audio_processor->OnCaptureFormatChanged(params_);
- ProcessDataAndVerifyFormat(audio_processor,
+ ProcessDataAndVerifyFormat(audio_processor.get(),
params_.sample_rate(),
params_.channels(),
params_.sample_rate() / 100);
@@ -182,14 +203,14 @@ TEST_F(MediaStreamAudioProcessorTest, WithAudioProcessing) {
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get()));
EXPECT_TRUE(audio_processor->has_audio_processing());
audio_processor->OnCaptureFormatChanged(params_);
- VerifyDefaultComponents(audio_processor);
+ VerifyDefaultComponents(audio_processor.get());
- ProcessDataAndVerifyFormat(audio_processor,
+ ProcessDataAndVerifyFormat(audio_processor.get(),
kAudioProcessingSampleRate,
kAudioProcessingNumberOfChannel,
kAudioProcessingSampleRate / 100);
@@ -207,13 +228,13 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
tab_constraint_factory.AddMandatory(kMediaStreamSource,
tab_string);
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
tab_constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get()));
EXPECT_FALSE(audio_processor->has_audio_processing());
audio_processor->OnCaptureFormatChanged(params_);
- ProcessDataAndVerifyFormat(audio_processor,
+ ProcessDataAndVerifyFormat(audio_processor.get(),
params_.sample_rate(),
params_.channels(),
params_.sample_rate() / 100);
@@ -224,7 +245,7 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
const std::string system_string = kMediaStreamSourceSystem;
system_constraint_factory.AddMandatory(kMediaStreamSource,
system_string);
- audio_processor = new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ audio_processor = new rtc::RefCountedObject<MediaStreamAudioProcessor>(
system_constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get());
EXPECT_FALSE(audio_processor->has_audio_processing());
@@ -241,13 +262,13 @@ TEST_F(MediaStreamAudioProcessorTest, TurnOffDefaultConstraints) {
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get()));
EXPECT_FALSE(audio_processor->has_audio_processing());
audio_processor->OnCaptureFormatChanged(params_);
- ProcessDataAndVerifyFormat(audio_processor,
+ ProcessDataAndVerifyFormat(audio_processor.get(),
params_.sample_rate(),
params_.channels(),
params_.sample_rate() / 100);
@@ -357,7 +378,7 @@ TEST_F(MediaStreamAudioProcessorTest, TestAllSampleRates) {
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get()));
EXPECT_TRUE(audio_processor->has_audio_processing());
@@ -372,9 +393,9 @@ TEST_F(MediaStreamAudioProcessorTest, TestAllSampleRates) {
media::CHANNEL_LAYOUT_STEREO, kSupportedSampleRates[i], 16,
buffer_size);
audio_processor->OnCaptureFormatChanged(params);
- VerifyDefaultComponents(audio_processor);
+ VerifyDefaultComponents(audio_processor.get());
- ProcessDataAndVerifyFormat(audio_processor,
+ ProcessDataAndVerifyFormat(audio_processor.get(),
kAudioProcessingSampleRate,
kAudioProcessingNumberOfChannel,
kAudioProcessingSampleRate / 100);
@@ -385,6 +406,28 @@ TEST_F(MediaStreamAudioProcessorTest, TestAllSampleRates) {
audio_processor = NULL;
}
+// Test that if we have an AEC dump message filter created, we are getting it
+// correctly in MSAP. Any IPC messages will be deleted since no sender in the
+// filter will be created.
+TEST_F(MediaStreamAudioProcessorTest, GetAecDumpMessageFilter) {
+ base::MessageLoopForUI message_loop;
+ scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_(
+ new AecDumpMessageFilter(message_loop.message_loop_proxy(),
+ message_loop.message_loop_proxy()));
+
+ MockMediaConstraintFactory constraint_factory;
+ scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
+ new WebRtcAudioDeviceImpl());
+ scoped_refptr<MediaStreamAudioProcessor> audio_processor(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
+ constraint_factory.CreateWebMediaConstraints(), 0,
+ webrtc_audio_device.get()));
+
+ EXPECT_TRUE(audio_processor->aec_dump_message_filter_.get());
+
+ audio_processor = NULL;
+}
+
TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
// Set up the correct constraints to turn off the audio processing and turn
// on the stereo channels mirroring.
@@ -396,7 +439,7 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
constraint_factory.CreateWebMediaConstraints(), 0,
webrtc_audio_device.get()));
EXPECT_FALSE(audio_processor->has_audio_processing());
@@ -447,4 +490,59 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
audio_processor = NULL;
}
+TEST_F(MediaStreamAudioProcessorTest, TestWithKeyboardMicChannel) {
+ MockMediaConstraintFactory constraint_factory;
+ constraint_factory.AddMandatory(
+ MediaAudioConstraints::kGoogExperimentalNoiseSuppression, true);
+ scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
+ new WebRtcAudioDeviceImpl());
+ scoped_refptr<MediaStreamAudioProcessor> audio_processor(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
+ constraint_factory.CreateWebMediaConstraints(), 0,
+ webrtc_audio_device.get()));
+ EXPECT_TRUE(audio_processor->has_audio_processing());
+
+ media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC,
+ 48000, 16, 512);
+ audio_processor->OnCaptureFormatChanged(params);
+
+ ProcessDataAndVerifyFormat(audio_processor.get(),
+ kAudioProcessingSampleRate,
+ kAudioProcessingNumberOfChannel,
+ kAudioProcessingSampleRate / 100);
+ // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
+ // |audio_processor|.
+ audio_processor = NULL;
+}
+
+TEST_F(MediaStreamAudioProcessorTest,
+ TestWithKeyboardMicChannelWithoutProcessing) {
+ // Setup the audio processor with disabled flag on.
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kDisableAudioTrackProcessing);
+ MockMediaConstraintFactory constraint_factory;
+ scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
+ new WebRtcAudioDeviceImpl());
+ scoped_refptr<MediaStreamAudioProcessor> audio_processor(
+ new rtc::RefCountedObject<MediaStreamAudioProcessor>(
+ constraint_factory.CreateWebMediaConstraints(), 0,
+ webrtc_audio_device.get()));
+ EXPECT_FALSE(audio_processor->has_audio_processing());
+
+ media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC,
+ 48000, 16, 512);
+ audio_processor->OnCaptureFormatChanged(params);
+
+ ProcessDataAndVerifyFormat(
+ audio_processor.get(),
+ params.sample_rate(),
+ media::ChannelLayoutToChannelCount(media::CHANNEL_LAYOUT_STEREO),
+ params.sample_rate() / 100);
+ // Set |audio_processor| to NULL to make sure |webrtc_audio_device| outlives
+ // |audio_processor|.
+ audio_processor = NULL;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_sink_owner.h b/chromium/content/renderer/media/media_stream_audio_sink_owner.h
index 6fcabbd3580..23acf69d716 100644
--- a/chromium/content/renderer/media/media_stream_audio_sink_owner.h
+++ b/chromium/content/renderer/media/media_stream_audio_sink_owner.h
@@ -20,24 +20,24 @@ class MediaStreamAudioSinkOwner : public MediaStreamAudioTrackSink {
explicit MediaStreamAudioSinkOwner(MediaStreamAudioSink* sink);
// MediaStreamAudioTrackSink implementation.
- virtual int OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- const std::vector<int>& channels,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE;
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
- virtual void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual bool IsEqual(const MediaStreamAudioSink* other) const OVERRIDE;
- virtual bool IsEqual(const PeerConnectionAudioSink* other) const OVERRIDE;
+ int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) override;
+ void OnSetFormat(const media::AudioParameters& params) override;
+ void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) override;
+ void Reset() override;
+ bool IsEqual(const MediaStreamAudioSink* other) const override;
+ bool IsEqual(const PeerConnectionAudioSink* other) const override;
protected:
- virtual ~MediaStreamAudioSinkOwner() {}
+ ~MediaStreamAudioSinkOwner() override {}
private:
mutable base::Lock lock_;
diff --git a/chromium/content/renderer/media/media_stream_audio_source.cc b/chromium/content/renderer/media/media_stream_audio_source.cc
index 069f4e3825d..dad7699e850 100644
--- a/chromium/content/renderer/media/media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/media_stream_audio_source.cc
@@ -4,14 +4,28 @@
#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/render_view_impl.h"
+
namespace content {
+namespace {
+// TODO(miu): This is a temporary hack until the Chrome audio vertical is
+// migrated for the Cross-Site Isolation project. http://crbug.com/392596
+int ToRenderViewId(int render_frame_id) {
+ RenderFrameImpl* const frame =
+ RenderFrameImpl::FromRoutingID(render_frame_id);
+ RenderViewImpl* const view = frame ? frame->render_view() : NULL;
+ return view ? view->GetRoutingID() : -1;
+}
+} // namespace
+
MediaStreamAudioSource::MediaStreamAudioSource(
- int render_view_id,
+ int render_frame_id,
const StreamDeviceInfo& device_info,
const SourceStoppedCallback& stop_callback,
PeerConnectionDependencyFactory* factory)
- : render_view_id_(render_view_id),
+ : render_view_id_(ToRenderViewId(render_frame_id)),
factory_(factory) {
SetDeviceInfo(device_info);
SetStopCallback(stop_callback);
@@ -34,23 +48,23 @@ void MediaStreamAudioSource::AddTrack(
const blink::WebMediaConstraints& constraints,
const ConstraintsCallback& callback) {
// TODO(xians): Properly implement for audio sources.
- if (!local_audio_source_) {
+ if (!local_audio_source_.get()) {
if (!factory_->InitializeMediaStreamAudioSource(render_view_id_,
constraints,
this)) {
// The source failed to start.
- // MediaStreamImpl rely on the |stop_callback| to be triggered when the
- // last track is removed from the source. But in this case, the source is
- // is not even started. So we need to fail both adding the track and
- // trigger |stop_callback|.
- callback.Run(this, false);
+ // UserMediaClientImpl rely on the |stop_callback| to be triggered when
+ // the last track is removed from the source. But in this case, the
+ // source is is not even started. So we need to fail both adding the
+ // track and trigger |stop_callback|.
+ callback.Run(this, MEDIA_DEVICE_TRACK_START_FAILURE, "");
StopSource();
return;
}
}
factory_->CreateLocalAudioTrack(track);
- callback.Run(this, true);
+ callback.Run(this, MEDIA_DEVICE_OK, "");
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_source.h b/chromium/content/renderer/media/media_stream_audio_source.h
index 29f1d4cfbaa..23e68f69c33 100644
--- a/chromium/content/renderer/media/media_stream_audio_source.h
+++ b/chromium/content/renderer/media/media_stream_audio_source.h
@@ -17,7 +17,7 @@ namespace content {
class CONTENT_EXPORT MediaStreamAudioSource
: NON_EXPORTED_BASE(public MediaStreamSource) {
public:
- MediaStreamAudioSource(int render_view_id,
+ MediaStreamAudioSource(int render_frame_id,
const StreamDeviceInfo& device_info,
const SourceStoppedCallback& stop_callback,
PeerConnectionDependencyFactory* factory);
@@ -32,8 +32,8 @@ class CONTENT_EXPORT MediaStreamAudioSource
local_audio_source_ = source;
}
- void SetAudioCapturer(WebRtcAudioCapturer* capturer) {
- DCHECK(!audio_capturer_);
+ void SetAudioCapturer(const scoped_refptr<WebRtcAudioCapturer>& capturer) {
+ DCHECK(!audio_capturer_.get());
audio_capturer_ = capturer;
}
@@ -46,18 +46,18 @@ class CONTENT_EXPORT MediaStreamAudioSource
}
protected:
- virtual void DoStopSource() OVERRIDE;
+ void DoStopSource() override;
private:
- int render_view_id_; // Render view ID that created this source.
+ const int render_view_id_; // Render view ID that created this source.
+ PeerConnectionDependencyFactory* const factory_;
+
// This member holds an instance of webrtc::LocalAudioSource. This is used
// as a container for audio options.
scoped_refptr<webrtc::AudioSourceInterface> local_audio_source_;
scoped_refptr<WebRtcAudioCapturer> audio_capturer_;
- PeerConnectionDependencyFactory* factory_;
-
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioSource);
};
diff --git a/chromium/content/renderer/media/media_stream_center.cc b/chromium/content/renderer/media/media_stream_center.cc
index 9d663497f3b..f5f5e7ad6d9 100644
--- a/chromium/content/renderer/media/media_stream_center.cc
+++ b/chromium/content/renderer/media/media_stream_center.cc
@@ -86,23 +86,10 @@ void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track,
MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
PeerConnectionDependencyFactory* factory)
- : rtc_factory_(factory), next_request_id_(0) {}
+ : rtc_factory_(factory) {}
MediaStreamCenter::~MediaStreamCenter() {}
-bool MediaStreamCenter::getMediaStreamTrackSources(
- const blink::WebMediaStreamTrackSourcesRequest& request) {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableDeviceEnumeration)) {
- int request_id = next_request_id_++;
- requests_.insert(std::make_pair(request_id, request));
- RenderThread::Get()->Send(new MediaStreamHostMsg_GetSources(
- request_id, GURL(request.origin().utf8())));
- return true;
- }
- return false;
-}
-
void MediaStreamCenter::didCreateMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack";
@@ -206,48 +193,4 @@ bool MediaStreamCenter::didRemoveMediaStreamTrack(
return native_stream->RemoveTrack(track);
}
-bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MediaStreamCenter, message)
- IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK,
- OnGetSourcesComplete)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void MediaStreamCenter::OnGetSourcesComplete(
- int request_id,
- const content::StreamDeviceInfoArray& devices) {
- RequestMap::iterator request_it = requests_.find(request_id);
- DCHECK(request_it != requests_.end());
-
- blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size());
- for (size_t i = 0; i < devices.size(); ++i) {
- const MediaStreamDevice& device = devices[i].device;
- DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE ||
- device.type == MEDIA_DEVICE_VIDEO_CAPTURE);
- blink::WebSourceInfo::VideoFacingMode video_facing;
- switch (device.video_facing) {
- case MEDIA_VIDEO_FACING_USER:
- video_facing = blink::WebSourceInfo::VideoFacingModeUser;
- break;
- case MEDIA_VIDEO_FACING_ENVIRONMENT:
- video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment;
- break;
- default:
- video_facing = blink::WebSourceInfo::VideoFacingModeNone;
- }
-
- sourceInfos[i]
- .initialize(blink::WebString::fromUTF8(device.id),
- device.type == MEDIA_DEVICE_AUDIO_CAPTURE
- ? blink::WebSourceInfo::SourceKindAudio
- : blink::WebSourceInfo::SourceKindVideo,
- blink::WebString::fromUTF8(device.name),
- video_facing);
- }
- request_it->second.requestSucceeded(sourceInfos);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_center.h b/chromium/content/renderer/media/media_stream_center.h
index d2dfa98cd5d..ef4fbaa0db5 100644
--- a/chromium/content/renderer/media/media_stream_center.h
+++ b/chromium/content/renderer/media/media_stream_center.h
@@ -26,66 +26,48 @@ namespace content {
class PeerConnectionDependencyFactory;
class CONTENT_EXPORT MediaStreamCenter
- : NON_EXPORTED_BASE(public blink::WebMediaStreamCenter),
- public RenderProcessObserver {
+ : NON_EXPORTED_BASE(public blink::WebMediaStreamCenter) {
public:
MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
PeerConnectionDependencyFactory* factory);
virtual ~MediaStreamCenter();
private:
- virtual bool getMediaStreamTrackSources(
- const blink::WebMediaStreamTrackSourcesRequest& request) OVERRIDE;
-
virtual void didCreateMediaStreamTrack(
- const blink::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
virtual void didEnableMediaStreamTrack(
- const blink::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
virtual void didDisableMediaStreamTrack(
- const blink::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
virtual void didStopLocalMediaStream(
- const blink::WebMediaStream& stream) OVERRIDE;
+ const blink::WebMediaStream& stream) override;
virtual bool didStopMediaStreamTrack(
- const blink::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
virtual blink::WebAudioSourceProvider*
createWebAudioSourceFromMediaStreamTrack(
- const blink::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
virtual void didCreateMediaStream(
- blink::WebMediaStream& stream) OVERRIDE;
+ blink::WebMediaStream& stream) override;
virtual bool didAddMediaStreamTrack(
const blink::WebMediaStream& stream,
- const blink::WebMediaStreamTrack& track) OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
virtual bool didRemoveMediaStreamTrack(
const blink::WebMediaStream& stream,
- const blink::WebMediaStreamTrack& track) OVERRIDE;
-
- // RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
-
- void OnGetSourcesComplete(int request_id,
- const content::StreamDeviceInfoArray& devices);
+ const blink::WebMediaStreamTrack& track) override;
// |rtc_factory_| is a weak pointer and is owned by the RenderThreadImpl.
// It is valid as long as RenderThreadImpl exist.
PeerConnectionDependencyFactory* rtc_factory_;
- // A strictly increasing id that's used to label incoming GetSources()
- // requests.
- int next_request_id_;
-
- typedef std::map<int, blink::WebMediaStreamTrackSourcesRequest> RequestMap;
- // Maps request ids to request objects.
- RequestMap requests_;
-
DISALLOW_COPY_AND_ASSIGN(MediaStreamCenter);
};
diff --git a/chromium/content/renderer/media/media_stream_constraints_util.cc b/chromium/content/renderer/media/media_stream_constraints_util.cc
index ddc223dacc6..7846582457a 100644
--- a/chromium/content/renderer/media/media_stream_constraints_util.cc
+++ b/chromium/content/renderer/media/media_stream_constraints_util.cc
@@ -38,6 +38,13 @@ bool GetConstraintValueAsInteger(const blink::WebMediaConstraints& constraints,
GetOptionalConstraintValueAsInteger(constraints, name, value);
}
+bool GetConstraintValueAsDouble(const blink::WebMediaConstraints& constraints,
+ const std::string& name,
+ double* value) {
+ return GetMandatoryConstraintValueAsDouble(constraints, name, value) ||
+ GetOptionalConstraintValueAsDouble(constraints, name, value);
+}
+
bool GetConstraintValueAsString(const blink::WebMediaConstraints& constraints,
const std::string& name,
std::string* value) {
diff --git a/chromium/content/renderer/media/media_stream_constraints_util.h b/chromium/content/renderer/media/media_stream_constraints_util.h
index 2068588b99f..71e9a492d18 100644
--- a/chromium/content/renderer/media/media_stream_constraints_util.h
+++ b/chromium/content/renderer/media/media_stream_constraints_util.h
@@ -32,6 +32,14 @@ bool CONTENT_EXPORT GetConstraintValueAsInteger(
const std::string& name,
int* value);
+// Method to get double precision value of constraint with |name| from
+// constraints. Returns true if the constraint is specified in either mandatory
+// or Optional constraints.
+bool CONTENT_EXPORT GetConstraintValueAsDouble(
+ const blink::WebMediaConstraints& constraints,
+ const std::string& name,
+ double* value);
+
// Method to get std::string value of constraint with |name| from constraints.
// Returns true if the constraint is specified in either mandatory or Optional
// constraints.
diff --git a/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc b/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc
index 37e7df66ddf..09b95110c45 100644
--- a/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc
@@ -51,6 +51,48 @@ TEST_F(MediaStreamConstraintsUtilTest, BooleanConstraints) {
EXPECT_FALSE(value_false);
}
+TEST_F(MediaStreamConstraintsUtilTest, MandatoryDoubleConstraints) {
+ MockMediaConstraintFactory constraint_factory;
+ const std::string test_key = "test key";
+ const double test_value= 0.01f;
+
+ constraint_factory.AddMandatory(test_key, test_value);
+ blink::WebMediaConstraints constraints =
+ constraint_factory.CreateWebMediaConstraints();
+
+ double value;
+ EXPECT_FALSE(GetOptionalConstraintValueAsDouble(constraints, test_key,
+ &value));
+ EXPECT_TRUE(GetMandatoryConstraintValueAsDouble(constraints, test_key,
+ &value));
+ EXPECT_EQ(test_value, value);
+
+ value = 0;
+ EXPECT_TRUE(GetConstraintValueAsDouble(constraints, test_key, &value));
+ EXPECT_EQ(test_value, value);
+}
+
+TEST_F(MediaStreamConstraintsUtilTest, OptionalDoubleConstraints) {
+ MockMediaConstraintFactory constraint_factory;
+ const std::string test_key = "test key";
+ const double test_value= 0.01f;
+
+ constraint_factory.AddOptional(test_key, test_value);
+ blink::WebMediaConstraints constraints =
+ constraint_factory.CreateWebMediaConstraints();
+
+ double value;
+ EXPECT_FALSE(GetMandatoryConstraintValueAsDouble(constraints, test_key,
+ &value));
+ EXPECT_TRUE(GetOptionalConstraintValueAsDouble(constraints, test_key,
+ &value));
+ EXPECT_EQ(test_value, value);
+
+ value = 0;
+ EXPECT_TRUE(GetConstraintValueAsDouble(constraints, test_key, &value));
+ EXPECT_EQ(test_value, value);
+}
+
TEST_F(MediaStreamConstraintsUtilTest, IntConstraints) {
MockMediaConstraintFactory constraint_factory;
int width = 600;
diff --git a/chromium/content/renderer/media/media_stream_dispatcher.cc b/chromium/content/renderer/media/media_stream_dispatcher.cc
index 2f93d53de9a..361a4ceae92 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher.cc
+++ b/chromium/content/renderer/media/media_stream_dispatcher.cc
@@ -5,11 +5,10 @@
#include "content/renderer/media/media_stream_dispatcher.h"
#include "base/logging.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "content/common/media/media_stream_messages.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_impl.h"
+#include "media/audio/audio_parameters.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "url/gurl.h"
@@ -62,9 +61,8 @@ struct MediaStreamDispatcher::Stream {
StreamDeviceInfoArray video_array;
};
-MediaStreamDispatcher::MediaStreamDispatcher(RenderViewImpl* render_view)
- : RenderViewObserver(render_view),
- main_loop_(base::MessageLoopProxy::current()),
+MediaStreamDispatcher::MediaStreamDispatcher(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame),
next_ipc_id_(0) {
}
@@ -75,7 +73,7 @@ void MediaStreamDispatcher::GenerateStream(
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
const StreamOptions& components,
const GURL& security_origin) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")";
requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
@@ -87,7 +85,7 @@ void MediaStreamDispatcher::GenerateStream(
void MediaStreamDispatcher::CancelGenerateStream(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "MediaStreamDispatcher::CancelGenerateStream"
<< ", {request_id = " << request_id << "}";
@@ -105,6 +103,7 @@ void MediaStreamDispatcher::CancelGenerateStream(
void MediaStreamDispatcher::StopStreamDevice(
const StreamDeviceInfo& device_info) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "MediaStreamDispatcher::StopStreamDevice"
<< ", {device_id = " << device_info.device.id << "}";
// Remove |device_info| from all streams in |label_stream_map_|.
@@ -134,9 +133,8 @@ void MediaStreamDispatcher::EnumerateDevices(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
MediaStreamType type,
- const GURL& security_origin,
- bool hide_labels_if_no_access) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ const GURL& security_origin) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
type == MEDIA_DEVICE_VIDEO_CAPTURE ||
type == MEDIA_DEVICE_AUDIO_OUTPUT);
@@ -152,14 +150,13 @@ void MediaStreamDispatcher::EnumerateDevices(
Send(new MediaStreamHostMsg_EnumerateDevices(routing_id(),
next_ipc_id_++,
type,
- security_origin,
- hide_labels_if_no_access));
+ security_origin));
}
void MediaStreamDispatcher::StopEnumerateDevices(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "MediaStreamDispatcher::StopEnumerateDevices("
<< request_id << ")";
for (RequestList::iterator it = requests_.begin(); it != requests_.end();
@@ -179,7 +176,7 @@ void MediaStreamDispatcher::OpenDevice(
const std::string& device_id,
MediaStreamType type,
const GURL& security_origin) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "MediaStreamDispatcher::OpenDevice(" << request_id << ")";
requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
@@ -197,7 +194,7 @@ void MediaStreamDispatcher::CancelOpenDevice(
}
void MediaStreamDispatcher::CloseDevice(const std::string& label) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!label.empty());
DVLOG(1) << "MediaStreamDispatcher::CloseDevice"
<< ", {label = " << label << "}";
@@ -210,6 +207,10 @@ void MediaStreamDispatcher::CloseDevice(const std::string& label) {
Send(new MediaStreamHostMsg_CloseDevice(routing_id(), label));
}
+void MediaStreamDispatcher::OnDestruct() {
+ // Do not self-destruct. UserMediaClientImpl owns |this|.
+}
+
bool MediaStreamDispatcher::Send(IPC::Message* message) {
if (!RenderThread::Get()) {
delete message;
@@ -244,7 +245,7 @@ void MediaStreamDispatcher::OnStreamGenerated(
const std::string& label,
const StreamDeviceInfoArray& audio_array,
const StreamDeviceInfoArray& video_array) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
for (RequestList::iterator it = requests_.begin();
it != requests_.end(); ++it) {
@@ -270,7 +271,7 @@ void MediaStreamDispatcher::OnStreamGenerated(
void MediaStreamDispatcher::OnStreamGenerationFailed(
int request_id,
content::MediaStreamRequestResult result) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
for (RequestList::iterator it = requests_.begin();
it != requests_.end(); ++it) {
Request& request = *it;
@@ -289,7 +290,7 @@ void MediaStreamDispatcher::OnStreamGenerationFailed(
void MediaStreamDispatcher::OnDeviceStopped(
const std::string& label,
const StreamDeviceInfo& device_info) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "MediaStreamDispatcher::OnDeviceStopped("
<< "{label = " << label << "})"
<< ", {device_id = " << device_info.device.id << "})";
@@ -316,7 +317,7 @@ void MediaStreamDispatcher::OnDeviceStopped(
void MediaStreamDispatcher::OnDevicesEnumerated(
int request_id,
const StreamDeviceInfoArray& device_array) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_GE(request_id, 0);
for (RequestList::iterator it = requests_.begin(); it != requests_.end();
@@ -332,7 +333,7 @@ void MediaStreamDispatcher::OnDeviceOpened(
int request_id,
const std::string& label,
const StreamDeviceInfo& device_info) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
for (RequestList::iterator it = requests_.begin();
it != requests_.end(); ++it) {
Request& request = *it;
@@ -359,7 +360,7 @@ void MediaStreamDispatcher::OnDeviceOpened(
}
void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) {
- DCHECK(main_loop_->BelongsToCurrentThread());
+ DCHECK(thread_checker_.CalledOnValidThread());
for (RequestList::iterator it = requests_.begin();
it != requests_.end(); ++it) {
Request& request = *it;
@@ -377,6 +378,7 @@ void MediaStreamDispatcher::OnDeviceOpenFailed(int request_id) {
int MediaStreamDispatcher::audio_session_id(const std::string& label,
int index) {
+ DCHECK(thread_checker_.CalledOnValidThread());
LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end() ||
it->second.audio_array.size() <= static_cast<size_t>(index)) {
@@ -386,11 +388,13 @@ int MediaStreamDispatcher::audio_session_id(const std::string& label,
}
bool MediaStreamDispatcher::IsStream(const std::string& label) {
+ DCHECK(thread_checker_.CalledOnValidThread());
return label_stream_map_.find(label) != label_stream_map_.end();
}
int MediaStreamDispatcher::video_session_id(const std::string& label,
int index) {
+ DCHECK(thread_checker_.CalledOnValidThread());
LabelStreamMap::iterator it = label_stream_map_.find(label);
if (it == label_stream_map_.end() ||
it->second.video_array.size() <= static_cast<size_t>(index)) {
@@ -399,4 +403,19 @@ int MediaStreamDispatcher::video_session_id(const std::string& label,
return it->second.video_array[index].session_id;
}
+bool MediaStreamDispatcher::IsAudioDuckingActive() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ LabelStreamMap::const_iterator stream_it = label_stream_map_.begin();
+ while (stream_it != label_stream_map_.end()) {
+ const StreamDeviceInfoArray& audio_array = stream_it->second.audio_array;
+ for (StreamDeviceInfoArray::const_iterator device_it = audio_array.begin();
+ device_it != audio_array.end(); ++device_it) {
+ if (device_it->device.input.effects & media::AudioParameters::DUCKING)
+ return true;
+ }
+ ++stream_it;
+ }
+ return false;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_dispatcher.h b/chromium/content/renderer/media/media_stream_dispatcher.h
index b7c666080fa..74a06dc384a 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher.h
+++ b/chromium/content/renderer/media/media_stream_dispatcher.h
@@ -13,9 +13,10 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
-#include "content/public/renderer/render_view_observer.h"
+#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
namespace base {
@@ -24,19 +25,17 @@ class MessageLoopProxy;
namespace content {
-class RenderViewImpl;
-
// MediaStreamDispatcher is a delegate for the Media Stream API messages.
// MediaStreams are used by WebKit to open media devices such as Video Capture
// and Audio input devices.
// It's the complement of MediaStreamDispatcherHost (owned by
// BrowserRenderProcessHost).
class CONTENT_EXPORT MediaStreamDispatcher
- : public RenderViewObserver,
+ : public RenderFrameObserver,
public base::SupportsWeakPtr<MediaStreamDispatcher> {
public:
- explicit MediaStreamDispatcher(RenderViewImpl* render_view);
- virtual ~MediaStreamDispatcher();
+ explicit MediaStreamDispatcher(RenderFrame* render_frame);
+ ~MediaStreamDispatcher() override;
// Request a new media stream to be created.
// This can be used either by WebKit or a plugin.
@@ -56,15 +55,11 @@ class CONTENT_EXPORT MediaStreamDispatcher
virtual void StopStreamDevice(const StreamDeviceInfo& device_info);
// Request to enumerate devices.
- // If |hide_labels_if_no_access| is true, labels will be empty in the
- // response if permission has not been granted for the device type. This
- // should normally be true.
virtual void EnumerateDevices(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
MediaStreamType type,
- const GURL& security_origin,
- bool hide_labels_if_no_access);
+ const GURL& security_origin);
// Request to stop enumerating devices.
void StopEnumerateDevices(
@@ -95,6 +90,11 @@ class CONTENT_EXPORT MediaStreamDispatcher
// Returns an audio session_id given a label and an index.
virtual int audio_session_id(const std::string& label, int index);
+ // Returns true if an audio input stream is currently active that was opened
+ // with audio ducking enabled. This is information is used when playing out
+ // audio so that rendered audio can be excluded from the ducking operation.
+ bool IsAudioDuckingActive() const;
+
protected:
int GetNextIpcIdForTest() { return next_ipc_id_; }
@@ -102,6 +102,7 @@ class CONTENT_EXPORT MediaStreamDispatcher
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, BasicVideoDevice);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, TestFailure);
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, CancelGenerateStream);
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, CheckDuckingState);
struct Request;
@@ -109,11 +110,12 @@ class CONTENT_EXPORT MediaStreamDispatcher
// opened it.
struct Stream;
- // RenderViewObserver OVERRIDE.
- virtual bool Send(IPC::Message* message) OVERRIDE;
+ // RenderFrameObserver override.
+ void OnDestruct() override;
+ bool Send(IPC::Message* message) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Messages from the browser.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
void OnStreamGenerated(
int request_id,
const std::string& label,
@@ -134,7 +136,7 @@ class CONTENT_EXPORT MediaStreamDispatcher
void OnDeviceOpenFailed(int request_id);
// Used for DCHECKs so methods calls won't execute in the wrong thread.
- scoped_refptr<base::MessageLoopProxy> main_loop_;
+ base::ThreadChecker thread_checker_;
int next_ipc_id_;
typedef std::map<std::string, Stream> LabelStreamMap;
diff --git a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
index 7637e4f968b..32acc882544 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -12,6 +12,7 @@
#include "content/public/common/media_stream_request.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
+#include "media/audio/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -36,11 +37,11 @@ class MockMediaStreamDispatcherEventHandler
MockMediaStreamDispatcherEventHandler()
: request_id_(-1) {}
- virtual void OnStreamGenerated(
+ void OnStreamGenerated(
int request_id,
- const std::string &label,
+ const std::string& label,
const StreamDeviceInfoArray& audio_device_array,
- const StreamDeviceInfoArray& video_device_array) OVERRIDE {
+ const StreamDeviceInfoArray& video_device_array) override {
request_id_ = request_id;
label_ = label;
if (audio_device_array.size()) {
@@ -53,14 +54,14 @@ class MockMediaStreamDispatcherEventHandler
}
}
- virtual void OnStreamGenerationFailed(
+ void OnStreamGenerationFailed(
int request_id,
- content::MediaStreamRequestResult result) OVERRIDE {
+ content::MediaStreamRequestResult result) override {
request_id_ = request_id;
}
- virtual void OnDeviceStopped(const std::string& label,
- const StreamDeviceInfo& device_info) OVERRIDE {
+ void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) override {
device_stopped_label_ = label;
if (IsVideoMediaType(device_info.device.type)) {
EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_, device_info));
@@ -70,23 +71,19 @@ class MockMediaStreamDispatcherEventHandler
}
}
- virtual void OnDevicesEnumerated(
- int request_id,
- const StreamDeviceInfoArray& device_array) OVERRIDE {
+ void OnDevicesEnumerated(int request_id,
+ const StreamDeviceInfoArray& device_array) override {
request_id_ = request_id;
}
- virtual void OnDeviceOpened(
- int request_id,
- const std::string& label,
- const StreamDeviceInfo& video_device) OVERRIDE {
+ void OnDeviceOpened(int request_id,
+ const std::string& label,
+ const StreamDeviceInfo& video_device) override {
request_id_ = request_id;
label_ = label;
}
- virtual void OnDeviceOpenFailed(int request_id) OVERRIDE {
- request_id_ = request_id;
- }
+ void OnDeviceOpenFailed(int request_id) override { request_id_ = request_id; }
void ResetStoredParameters() {
request_id_ = -1;
@@ -108,7 +105,7 @@ class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher {
MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {}
using MediaStreamDispatcher::GetNextIpcIdForTest;
- using RenderViewObserver::OnMessageReceived;
+ using RenderFrameObserver::OnMessageReceived;
};
class MediaStreamDispatcherTest : public ::testing::Test {
@@ -226,15 +223,13 @@ TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
dispatcher->EnumerateDevices(
kRequestId1, handler1.get()->AsWeakPtr(),
kVideoType,
- security_origin,
- false);
+ security_origin);
int ipc_request_id2 = dispatcher->next_ipc_id_;
EXPECT_NE(ipc_request_id1, ipc_request_id2);
dispatcher->EnumerateDevices(
kRequestId2, handler2.get()->AsWeakPtr(),
kVideoType,
- security_origin,
- false);
+ security_origin);
EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
StreamDeviceInfoArray video_device_array(1);
@@ -410,4 +405,66 @@ TEST_F(MediaStreamDispatcherTest, DeviceClosed) {
StreamDeviceInfo::kNoId);
}
+TEST_F(MediaStreamDispatcherTest, CheckDuckingState) {
+ scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
+ scoped_ptr<MockMediaStreamDispatcherEventHandler>
+ handler(new MockMediaStreamDispatcherEventHandler);
+ StreamOptions components(true, false); // audio only.
+ int ipc_request_id1 = dispatcher->next_ipc_id_;
+
+ dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
+ components, GURL());
+ EXPECT_EQ(1u, dispatcher->requests_.size());
+
+ // Ducking isn't active at this point.
+ EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
+
+ // Complete the creation of stream1 with a single audio track that has
+ // ducking enabled.
+ StreamDeviceInfoArray audio_device_array(1);
+ StreamDeviceInfo& audio_device_info = audio_device_array[0];
+ audio_device_info.device.name = "Microphone";
+ audio_device_info.device.type = kAudioType;
+ audio_device_info.session_id = kAudioSessionId;
+ audio_device_info.device.input.effects = media::AudioParameters::DUCKING;
+
+ StreamDeviceInfoArray video_device_array; // Empty for this test.
+
+ const char kStreamLabel[] = "stream1";
+ dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
+ kRouteId, ipc_request_id1, kStreamLabel,
+ audio_device_array, video_device_array));
+ EXPECT_EQ(handler->request_id_, kRequestId1);
+ EXPECT_EQ(0u, dispatcher->requests_.size());
+
+ // Ducking should now be reported as active.
+ EXPECT_TRUE(dispatcher->IsAudioDuckingActive());
+
+ // Stop the device (removes the stream).
+ dispatcher->OnMessageReceived(
+ MediaStreamMsg_DeviceStopped(kRouteId, kStreamLabel,
+ handler->audio_device_));
+
+ // Ducking should now be reported as inactive again.
+ EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
+
+ // Now do the same sort of test with the DUCKING flag off.
+ audio_device_info.device.input.effects =
+ media::AudioParameters::ECHO_CANCELLER;
+
+ dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
+ kRouteId, ipc_request_id1, kStreamLabel,
+ audio_device_array, video_device_array));
+ EXPECT_EQ(handler->request_id_, kRequestId1);
+ EXPECT_EQ(0u, dispatcher->requests_.size());
+
+ // Ducking should still be reported as not active.
+ EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
+
+ // Stop the device (removes the stream).
+ dispatcher->OnMessageReceived(
+ MediaStreamMsg_DeviceStopped(kRouteId, kStreamLabel,
+ handler->audio_device_));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_impl.cc b/chromium/content/renderer/media/media_stream_impl.cc
deleted file mode 100644
index 79f86a83217..00000000000
--- a/chromium/content/renderer/media/media_stream_impl.cc
+++ /dev/null
@@ -1,938 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/media/media_stream_impl.h"
-
-#include <utility>
-
-#include "base/hash.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/renderer/media/media_stream.h"
-#include "content/renderer/media/media_stream_audio_source.h"
-#include "content/renderer/media/media_stream_dispatcher.h"
-#include "content/renderer/media/media_stream_video_capturer_source.h"
-#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/peer_connection_tracker.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
-#include "content/renderer/media/webrtc_audio_capturer.h"
-#include "content/renderer/media/webrtc_logging.h"
-#include "content/renderer/media/webrtc_uma_histograms.h"
-#include "content/renderer/render_thread_impl.h"
-#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-
-namespace content {
-namespace {
-
-void CopyStreamConstraints(const blink::WebMediaConstraints& constraints,
- StreamOptions::Constraints* mandatory,
- StreamOptions::Constraints* optional) {
- blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
- constraints.getMandatoryConstraints(mandatory_constraints);
- for (size_t i = 0; i < mandatory_constraints.size(); i++) {
- mandatory->push_back(StreamOptions::Constraint(
- mandatory_constraints[i].m_name.utf8(),
- mandatory_constraints[i].m_value.utf8()));
- }
-
- blink::WebVector<blink::WebMediaConstraint> optional_constraints;
- constraints.getOptionalConstraints(optional_constraints);
- for (size_t i = 0; i < optional_constraints.size(); i++) {
- optional->push_back(StreamOptions::Constraint(
- optional_constraints[i].m_name.utf8(),
- optional_constraints[i].m_value.utf8()));
- }
-}
-
-static int g_next_request_id = 0;
-
-} // namespace
-
-struct MediaStreamImpl::MediaDevicesRequestInfo {
- MediaDevicesRequestInfo(const blink::WebMediaDevicesRequest& request,
- int audio_input_request_id,
- int video_input_request_id,
- int audio_output_request_id)
- : request(request),
- audio_input_request_id(audio_input_request_id),
- video_input_request_id(video_input_request_id),
- audio_output_request_id(audio_output_request_id),
- has_audio_input_returned(false),
- has_video_input_returned(false),
- has_audio_output_returned(false) {}
-
- blink::WebMediaDevicesRequest request;
- int audio_input_request_id;
- int video_input_request_id;
- int audio_output_request_id;
- bool has_audio_input_returned;
- bool has_video_input_returned;
- bool has_audio_output_returned;
- StreamDeviceInfoArray audio_input_devices;
- StreamDeviceInfoArray video_input_devices;
- StreamDeviceInfoArray audio_output_devices;
-};
-
-MediaStreamImpl::MediaStreamImpl(
- RenderView* render_view,
- MediaStreamDispatcher* media_stream_dispatcher,
- PeerConnectionDependencyFactory* dependency_factory)
- : RenderViewObserver(render_view),
- dependency_factory_(dependency_factory),
- media_stream_dispatcher_(media_stream_dispatcher) {
-}
-
-MediaStreamImpl::~MediaStreamImpl() {
-}
-
-void MediaStreamImpl::requestUserMedia(
- const blink::WebUserMediaRequest& user_media_request) {
- // Save histogram data so we can see how much GetUserMedia is used.
- // The histogram counts the number of calls to the JS API
- // webGetUserMedia.
- UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA);
- DCHECK(CalledOnValidThread());
-
- if (RenderThreadImpl::current()) {
- RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia(
- user_media_request);
- }
-
- int request_id = g_next_request_id++;
- StreamOptions options;
- blink::WebLocalFrame* frame = NULL;
- GURL security_origin;
- bool enable_automatic_output_device_selection = false;
-
- // |user_media_request| can't be mocked. So in order to test at all we check
- // if it isNull.
- if (user_media_request.isNull()) {
- // We are in a test.
- options.audio_requested = true;
- options.video_requested = true;
- } else {
- if (user_media_request.audio()) {
- options.audio_requested = true;
- CopyStreamConstraints(user_media_request.audioConstraints(),
- &options.mandatory_audio,
- &options.optional_audio);
-
- // Check if this input device should be used to select a matching output
- // device for audio rendering.
- std::string enable;
- if (options.GetFirstAudioConstraintByName(
- kMediaStreamRenderToAssociatedSink, &enable, NULL) &&
- LowerCaseEqualsASCII(enable, "true")) {
- enable_automatic_output_device_selection = true;
- }
- }
- if (user_media_request.video()) {
- options.video_requested = true;
- CopyStreamConstraints(user_media_request.videoConstraints(),
- &options.mandatory_video,
- &options.optional_video);
- }
-
- security_origin = GURL(user_media_request.securityOrigin().toString());
- // Get the WebFrame that requested a MediaStream.
- // The frame is needed to tell the MediaStreamDispatcher when a stream goes
- // out of scope.
- frame = user_media_request.ownerDocument().frame();
- DCHECK(frame);
- }
-
- DVLOG(1) << "MediaStreamImpl::requestUserMedia(" << request_id << ", [ "
- << "audio=" << (options.audio_requested)
- << " select associated sink: "
- << enable_automatic_output_device_selection
- << ", video=" << (options.video_requested) << " ], "
- << security_origin.spec() << ")";
-
- std::string audio_device_id;
- bool mandatory_audio;
- options.GetFirstAudioConstraintByName(kMediaStreamSourceInfoId,
- &audio_device_id, &mandatory_audio);
- std::string video_device_id;
- bool mandatory_video;
- options.GetFirstVideoConstraintByName(kMediaStreamSourceInfoId,
- &video_device_id, &mandatory_video);
-
- WebRtcLogMessage(base::StringPrintf(
- "MSI::requestUserMedia. request_id=%d"
- ", audio source id=%s mandatory= %s "
- ", video source id=%s mandatory= %s",
- request_id,
- audio_device_id.c_str(),
- mandatory_audio ? "true":"false",
- video_device_id.c_str(),
- mandatory_video ? "true":"false"));
-
- user_media_requests_.push_back(
- new UserMediaRequestInfo(request_id, frame, user_media_request,
- enable_automatic_output_device_selection));
-
- media_stream_dispatcher_->GenerateStream(
- request_id,
- AsWeakPtr(),
- options,
- security_origin);
-}
-
-void MediaStreamImpl::cancelUserMediaRequest(
- const blink::WebUserMediaRequest& user_media_request) {
- DCHECK(CalledOnValidThread());
- UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request);
- if (request) {
- // We can't abort the stream generation process.
- // Instead, erase the request. Once the stream is generated we will stop the
- // stream if the request does not exist.
- DeleteUserMediaRequestInfo(request);
- }
-}
-
-void MediaStreamImpl::requestMediaDevices(
- const blink::WebMediaDevicesRequest& media_devices_request) {
- UpdateWebRTCMethodCount(WEBKIT_GET_MEDIA_DEVICES);
- DCHECK(CalledOnValidThread());
-
- int audio_input_request_id = g_next_request_id++;
- int video_input_request_id = g_next_request_id++;
- int audio_output_request_id = g_next_request_id++;
-
- // |media_devices_request| can't be mocked, so in tests it will be empty (the
- // underlying pointer is null). In order to use this function in a test we
- // need to check if it isNull.
- GURL security_origin;
- if (!media_devices_request.isNull())
- security_origin = GURL(media_devices_request.securityOrigin().toString());
-
- DVLOG(1) << "MediaStreamImpl::requestMediaDevices(" << audio_input_request_id
- << ", " << video_input_request_id << ", " << audio_output_request_id
- << ", " << security_origin.spec() << ")";
-
- media_devices_requests_.push_back(new MediaDevicesRequestInfo(
- media_devices_request,
- audio_input_request_id,
- video_input_request_id,
- audio_output_request_id));
-
- media_stream_dispatcher_->EnumerateDevices(
- audio_input_request_id,
- AsWeakPtr(),
- MEDIA_DEVICE_AUDIO_CAPTURE,
- security_origin,
- true);
-
- media_stream_dispatcher_->EnumerateDevices(
- video_input_request_id,
- AsWeakPtr(),
- MEDIA_DEVICE_VIDEO_CAPTURE,
- security_origin,
- true);
-
- media_stream_dispatcher_->EnumerateDevices(
- audio_output_request_id,
- AsWeakPtr(),
- MEDIA_DEVICE_AUDIO_OUTPUT,
- security_origin,
- true);
-}
-
-void MediaStreamImpl::cancelMediaDevicesRequest(
- const blink::WebMediaDevicesRequest& media_devices_request) {
- DCHECK(CalledOnValidThread());
- MediaDevicesRequestInfo* request =
- FindMediaDevicesRequestInfo(media_devices_request);
- if (!request)
- return;
-
- // Cancel device enumeration.
- media_stream_dispatcher_->StopEnumerateDevices(
- request->audio_input_request_id,
- AsWeakPtr());
- media_stream_dispatcher_->StopEnumerateDevices(
- request->video_input_request_id,
- AsWeakPtr());
- media_stream_dispatcher_->StopEnumerateDevices(
- request->audio_output_request_id,
- AsWeakPtr());
- DeleteMediaDevicesRequestInfo(request);
-}
-
-// Callback from MediaStreamDispatcher.
-// The requested stream have been generated by the MediaStreamDispatcher.
-void MediaStreamImpl::OnStreamGenerated(
- int request_id,
- const std::string& label,
- const StreamDeviceInfoArray& audio_array,
- const StreamDeviceInfoArray& video_array) {
- DCHECK(CalledOnValidThread());
- DVLOG(1) << "MediaStreamImpl::OnStreamGenerated stream:" << label;
-
- UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(request_id);
- if (!request_info) {
- // This can happen if the request is canceled or the frame reloads while
- // MediaStreamDispatcher is processing the request.
- // Only stop the device if the device is not used in another MediaStream.
- for (StreamDeviceInfoArray::const_iterator device_it = audio_array.begin();
- device_it != audio_array.end(); ++device_it) {
- if (!FindLocalSource(*device_it))
- media_stream_dispatcher_->StopStreamDevice(*device_it);
- }
-
- for (StreamDeviceInfoArray::const_iterator device_it = video_array.begin();
- device_it != video_array.end(); ++device_it) {
- if (!FindLocalSource(*device_it))
- media_stream_dispatcher_->StopStreamDevice(*device_it);
- }
-
- DVLOG(1) << "Request ID not found";
- return;
- }
- request_info->generated = true;
-
- // WebUserMediaRequest don't have an implementation in unit tests.
- // Therefore we need to check for isNull here and initialize the
- // constraints.
- blink::WebUserMediaRequest* request = &(request_info->request);
- blink::WebMediaConstraints audio_constraints;
- blink::WebMediaConstraints video_constraints;
- if (request->isNull()) {
- audio_constraints.initialize();
- video_constraints.initialize();
- } else {
- audio_constraints = request->audioConstraints();
- video_constraints = request->videoConstraints();
- }
-
- blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector(
- audio_array.size());
- CreateAudioTracks(audio_array, audio_constraints, &audio_track_vector,
- request_info);
-
- blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
- video_array.size());
- CreateVideoTracks(video_array, video_constraints, &video_track_vector,
- request_info);
-
- blink::WebString webkit_id = base::UTF8ToUTF16(label);
- blink::WebMediaStream* web_stream = &(request_info->web_stream);
-
- web_stream->initialize(webkit_id, audio_track_vector,
- video_track_vector);
- web_stream->setExtraData(
- new MediaStream(
- *web_stream));
-
- // Wait for the tracks to be started successfully or to fail.
- request_info->CallbackOnTracksStarted(
- base::Bind(&MediaStreamImpl::OnCreateNativeTracksCompleted, AsWeakPtr()));
-}
-
-// Callback from MediaStreamDispatcher.
-// The requested stream failed to be generated.
-void MediaStreamImpl::OnStreamGenerationFailed(
- int request_id,
- content::MediaStreamRequestResult result) {
- DCHECK(CalledOnValidThread());
- DVLOG(1) << "MediaStreamImpl::OnStreamGenerationFailed("
- << request_id << ")";
- UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(request_id);
- if (!request_info) {
- // This can happen if the request is canceled or the frame reloads while
- // MediaStreamDispatcher is processing the request.
- DVLOG(1) << "Request ID not found";
- return;
- }
-
- GetUserMediaRequestFailed(&request_info->request, result);
- DeleteUserMediaRequestInfo(request_info);
-}
-
-// Callback from MediaStreamDispatcher.
-// The browser process has stopped a device used by a MediaStream.
-void MediaStreamImpl::OnDeviceStopped(
- const std::string& label,
- const StreamDeviceInfo& device_info) {
- DCHECK(CalledOnValidThread());
- DVLOG(1) << "MediaStreamImpl::OnDeviceStopped("
- << "{device_id = " << device_info.device.id << "})";
-
- const blink::WebMediaStreamSource* source_ptr = FindLocalSource(device_info);
- if (!source_ptr) {
- // This happens if the same device is used in several guM requests or
- // if a user happen stop a track from JS at the same time
- // as the underlying media device is unplugged from the system.
- return;
- }
- // By creating |source| it is guaranteed that the blink::WebMediaStreamSource
- // object is valid during the cleanup.
- blink::WebMediaStreamSource source(*source_ptr);
- StopLocalSource(source, false);
-
- for (LocalStreamSources::iterator device_it = local_sources_.begin();
- device_it != local_sources_.end(); ++device_it) {
- if (device_it->source.id() == source.id()) {
- local_sources_.erase(device_it);
- break;
- }
- }
-}
-
-void MediaStreamImpl::InitializeSourceObject(
- const StreamDeviceInfo& device,
- blink::WebMediaStreamSource::Type type,
- const blink::WebMediaConstraints& constraints,
- blink::WebFrame* frame,
- blink::WebMediaStreamSource* webkit_source) {
- const blink::WebMediaStreamSource* existing_source =
- FindLocalSource(device);
- if (existing_source) {
- *webkit_source = *existing_source;
- DVLOG(1) << "Source already exist. Reusing source with id "
- << webkit_source->id().utf8();
- return;
- }
-
- webkit_source->initialize(
- base::UTF8ToUTF16(device.device.id),
- type,
- base::UTF8ToUTF16(device.device.name));
-
- DVLOG(1) << "Initialize source object :"
- << "id = " << webkit_source->id().utf8()
- << ", name = " << webkit_source->name().utf8();
-
- if (type == blink::WebMediaStreamSource::TypeVideo) {
- webkit_source->setExtraData(
- CreateVideoSource(
- device,
- base::Bind(&MediaStreamImpl::OnLocalSourceStopped, AsWeakPtr())));
- } else {
- DCHECK_EQ(blink::WebMediaStreamSource::TypeAudio, type);
- MediaStreamAudioSource* audio_source(
- new MediaStreamAudioSource(
- RenderViewObserver::routing_id(),
- device,
- base::Bind(&MediaStreamImpl::OnLocalSourceStopped, AsWeakPtr()),
- dependency_factory_));
- webkit_source->setExtraData(audio_source);
- }
- local_sources_.push_back(LocalStreamSource(frame, *webkit_source));
-}
-
-MediaStreamVideoSource* MediaStreamImpl::CreateVideoSource(
- const StreamDeviceInfo& device,
- const MediaStreamSource::SourceStoppedCallback& stop_callback) {
- return new content::MediaStreamVideoCapturerSource(
- device,
- stop_callback,
- new VideoCapturerDelegate(device));
-}
-
-void MediaStreamImpl::CreateVideoTracks(
- const StreamDeviceInfoArray& devices,
- const blink::WebMediaConstraints& constraints,
- blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
- UserMediaRequestInfo* request) {
- DCHECK_EQ(devices.size(), webkit_tracks->size());
-
- for (size_t i = 0; i < devices.size(); ++i) {
- blink::WebMediaStreamSource webkit_source;
- InitializeSourceObject(devices[i],
- blink::WebMediaStreamSource::TypeVideo,
- constraints,
- request->frame,
- &webkit_source);
- (*webkit_tracks)[i] =
- request->CreateAndStartVideoTrack(webkit_source, constraints);
- }
-}
-
-void MediaStreamImpl::CreateAudioTracks(
- const StreamDeviceInfoArray& devices,
- const blink::WebMediaConstraints& constraints,
- blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
- UserMediaRequestInfo* request) {
- DCHECK_EQ(devices.size(), webkit_tracks->size());
-
- // Log the device names for this request.
- for (StreamDeviceInfoArray::const_iterator it = devices.begin();
- it != devices.end(); ++it) {
- WebRtcLogMessage(base::StringPrintf(
- "Generated media stream for request id %d contains audio device name"
- " \"%s\"",
- request->request_id,
- it->device.name.c_str()));
- }
-
- StreamDeviceInfoArray overridden_audio_array = devices;
- if (!request->enable_automatic_output_device_selection) {
- // If the GetUserMedia request did not explicitly set the constraint
- // kMediaStreamRenderToAssociatedSink, the output device parameters must
- // be removed.
- for (StreamDeviceInfoArray::iterator it = overridden_audio_array.begin();
- it != overridden_audio_array.end(); ++it) {
- it->device.matched_output_device_id = "";
- it->device.matched_output = MediaStreamDevice::AudioDeviceParameters();
- }
- }
-
- for (size_t i = 0; i < overridden_audio_array.size(); ++i) {
- blink::WebMediaStreamSource webkit_source;
- InitializeSourceObject(overridden_audio_array[i],
- blink::WebMediaStreamSource::TypeAudio,
- constraints,
- request->frame,
- &webkit_source);
- (*webkit_tracks)[i].initialize(webkit_source);
- request->StartAudioTrack((*webkit_tracks)[i], constraints);
- }
-}
-
-void MediaStreamImpl::OnCreateNativeTracksCompleted(
- UserMediaRequestInfo* request,
- content::MediaStreamRequestResult result) {
- DVLOG(1) << "MediaStreamImpl::OnCreateNativeTracksComplete("
- << "{request_id = " << request->request_id << "} "
- << "{result = " << result << "})";
- if (result == content::MEDIA_DEVICE_OK)
- GetUserMediaRequestSucceeded(request->web_stream, &request->request);
- else
- GetUserMediaRequestFailed(&request->request, result);
-
- DeleteUserMediaRequestInfo(request);
-}
-
-void MediaStreamImpl::OnDevicesEnumerated(
- int request_id,
- const StreamDeviceInfoArray& device_array) {
- DVLOG(1) << "MediaStreamImpl::OnDevicesEnumerated(" << request_id << ")";
-
- MediaDevicesRequestInfo* request = FindMediaDevicesRequestInfo(request_id);
- DCHECK(request);
-
- if (request_id == request->audio_input_request_id) {
- request->has_audio_input_returned = true;
- DCHECK(request->audio_input_devices.empty());
- request->audio_input_devices = device_array;
- } else if (request_id == request->video_input_request_id) {
- request->has_video_input_returned = true;
- DCHECK(request->video_input_devices.empty());
- request->video_input_devices = device_array;
- } else {
- DCHECK_EQ(request->audio_output_request_id, request_id);
- request->has_audio_output_returned = true;
- DCHECK(request->audio_output_devices.empty());
- request->audio_output_devices = device_array;
- }
-
- if (!request->has_audio_input_returned ||
- !request->has_video_input_returned ||
- !request->has_audio_output_returned) {
- // Wait for the rest of the devices to complete.
- return;
- }
-
- // All devices are ready for copying. We use a hashed audio output device id
- // as the group id for input and output audio devices. If an input device
- // doesn't have an associated output device, we use the input device's own id.
- // We don't support group id for video devices, that's left empty.
- blink::WebVector<blink::WebMediaDeviceInfo>
- devices(request->audio_input_devices.size() +
- request->video_input_devices.size() +
- request->audio_output_devices.size());
- for (size_t i = 0; i < request->audio_input_devices.size(); ++i) {
- const MediaStreamDevice& device = request->audio_input_devices[i].device;
- DCHECK_EQ(device.type, MEDIA_DEVICE_AUDIO_CAPTURE);
- std::string group_id = base::UintToString(base::Hash(
- !device.matched_output_device_id.empty() ?
- device.matched_output_device_id :
- device.id));
- devices[i].initialize(
- blink::WebString::fromUTF8(device.id),
- blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
- blink::WebString::fromUTF8(device.name),
- blink::WebString::fromUTF8(group_id));
- }
- size_t offset = request->audio_input_devices.size();
- for (size_t i = 0; i < request->video_input_devices.size(); ++i) {
- const MediaStreamDevice& device = request->video_input_devices[i].device;
- DCHECK_EQ(device.type, MEDIA_DEVICE_VIDEO_CAPTURE);
- devices[offset + i].initialize(
- blink::WebString::fromUTF8(device.id),
- blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
- blink::WebString::fromUTF8(device.name),
- blink::WebString());
- }
- offset += request->video_input_devices.size();
- for (size_t i = 0; i < request->audio_output_devices.size(); ++i) {
- const MediaStreamDevice& device = request->audio_output_devices[i].device;
- DCHECK_EQ(device.type, MEDIA_DEVICE_AUDIO_OUTPUT);
- devices[offset + i].initialize(
- blink::WebString::fromUTF8(device.id),
- blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput,
- blink::WebString::fromUTF8(device.name),
- blink::WebString::fromUTF8(base::UintToString(base::Hash(device.id))));
- }
-
- EnumerateDevicesSucceded(&request->request, devices);
-
- // Cancel device enumeration.
- media_stream_dispatcher_->StopEnumerateDevices(
- request->audio_input_request_id,
- AsWeakPtr());
- media_stream_dispatcher_->StopEnumerateDevices(
- request->video_input_request_id,
- AsWeakPtr());
- media_stream_dispatcher_->StopEnumerateDevices(
- request->audio_output_request_id,
- AsWeakPtr());
-
- DeleteMediaDevicesRequestInfo(request);
-}
-
-void MediaStreamImpl::OnDeviceOpened(
- int request_id,
- const std::string& label,
- const StreamDeviceInfo& video_device) {
- DVLOG(1) << "MediaStreamImpl::OnDeviceOpened("
- << request_id << ", " << label << ")";
- NOTIMPLEMENTED();
-}
-
-void MediaStreamImpl::OnDeviceOpenFailed(int request_id) {
- DVLOG(1) << "MediaStreamImpl::VideoDeviceOpenFailed("
- << request_id << ")";
- NOTIMPLEMENTED();
-}
-
-void MediaStreamImpl::GetUserMediaRequestSucceeded(
- const blink::WebMediaStream& stream,
- blink::WebUserMediaRequest* request_info) {
- DVLOG(1) << "MediaStreamImpl::GetUserMediaRequestSucceeded";
- request_info->requestSucceeded(stream);
-}
-
-void MediaStreamImpl::GetUserMediaRequestFailed(
- blink::WebUserMediaRequest* request_info,
- content::MediaStreamRequestResult result) {
- switch (result) {
- case MEDIA_DEVICE_OK:
- NOTREACHED();
- break;
- case MEDIA_DEVICE_PERMISSION_DENIED:
- request_info->requestDenied();
- break;
- case MEDIA_DEVICE_PERMISSION_DISMISSED:
- request_info->requestFailedUASpecific("PermissionDismissedError");
- break;
- case MEDIA_DEVICE_INVALID_STATE:
- request_info->requestFailedUASpecific("InvalidStateError");
- break;
- case MEDIA_DEVICE_NO_HARDWARE:
- request_info->requestFailedUASpecific("DevicesNotFoundError");
- break;
- case MEDIA_DEVICE_INVALID_SECURITY_ORIGIN:
- request_info->requestFailedUASpecific("InvalidSecurityOriginError");
- break;
- case MEDIA_DEVICE_TAB_CAPTURE_FAILURE:
- request_info->requestFailedUASpecific("TabCaptureError");
- break;
- case MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE:
- request_info->requestFailedUASpecific("ScreenCaptureError");
- break;
- case MEDIA_DEVICE_CAPTURE_FAILURE:
- request_info->requestFailedUASpecific("DeviceCaptureError");
- break;
- case MEDIA_DEVICE_TRACK_START_FAILURE:
- request_info->requestFailedUASpecific("TrackStartError");
- break;
- default:
- request_info->requestFailed();
- break;
- }
-}
-
-void MediaStreamImpl::EnumerateDevicesSucceded(
- blink::WebMediaDevicesRequest* request,
- blink::WebVector<blink::WebMediaDeviceInfo>& devices) {
- request->requestSucceeded(devices);
-}
-
-const blink::WebMediaStreamSource* MediaStreamImpl::FindLocalSource(
- const StreamDeviceInfo& device) const {
- for (LocalStreamSources::const_iterator it = local_sources_.begin();
- it != local_sources_.end(); ++it) {
- MediaStreamSource* source =
- static_cast<MediaStreamSource*>(it->source.extraData());
- const StreamDeviceInfo& active_device = source->device_info();
- if (active_device.device.id == device.device.id &&
- active_device.device.type == device.device.type &&
- active_device.session_id == device.session_id) {
- return &it->source;
- }
- }
- return NULL;
-}
-
-MediaStreamImpl::UserMediaRequestInfo*
-MediaStreamImpl::FindUserMediaRequestInfo(int request_id) {
- UserMediaRequests::iterator it = user_media_requests_.begin();
- for (; it != user_media_requests_.end(); ++it) {
- if ((*it)->request_id == request_id)
- return (*it);
- }
- return NULL;
-}
-
-MediaStreamImpl::UserMediaRequestInfo*
-MediaStreamImpl::FindUserMediaRequestInfo(
- const blink::WebUserMediaRequest& request) {
- UserMediaRequests::iterator it = user_media_requests_.begin();
- for (; it != user_media_requests_.end(); ++it) {
- if ((*it)->request == request)
- return (*it);
- }
- return NULL;
-}
-
-void MediaStreamImpl::DeleteUserMediaRequestInfo(
- UserMediaRequestInfo* request) {
- UserMediaRequests::iterator it = user_media_requests_.begin();
- for (; it != user_media_requests_.end(); ++it) {
- if ((*it) == request) {
- user_media_requests_.erase(it);
- return;
- }
- }
- NOTREACHED();
-}
-
-MediaStreamImpl::MediaDevicesRequestInfo*
-MediaStreamImpl::FindMediaDevicesRequestInfo(
- int request_id) {
- MediaDevicesRequests::iterator it = media_devices_requests_.begin();
- for (; it != media_devices_requests_.end(); ++it) {
- if ((*it)->audio_input_request_id == request_id ||
- (*it)->video_input_request_id == request_id ||
- (*it)->audio_output_request_id == request_id) {
- return (*it);
- }
- }
- return NULL;
-}
-
-MediaStreamImpl::MediaDevicesRequestInfo*
-MediaStreamImpl::FindMediaDevicesRequestInfo(
- const blink::WebMediaDevicesRequest& request) {
- MediaDevicesRequests::iterator it = media_devices_requests_.begin();
- for (; it != media_devices_requests_.end(); ++it) {
- if ((*it)->request == request)
- return (*it);
- }
- return NULL;
-}
-
-void MediaStreamImpl::DeleteMediaDevicesRequestInfo(
- MediaDevicesRequestInfo* request) {
- MediaDevicesRequests::iterator it = media_devices_requests_.begin();
- for (; it != media_devices_requests_.end(); ++it) {
- if ((*it) == request) {
- media_devices_requests_.erase(it);
- return;
- }
- }
- NOTREACHED();
-}
-
-void MediaStreamImpl::FrameDetached(blink::WebFrame* frame) {
- // Do same thing as FrameWillClose.
- FrameWillClose(frame);
-}
-
-void MediaStreamImpl::FrameWillClose(blink::WebFrame* frame) {
- // Loop through all UserMediaRequests and find the requests that belong to the
- // frame that is being closed.
- UserMediaRequests::iterator request_it = user_media_requests_.begin();
- while (request_it != user_media_requests_.end()) {
- if ((*request_it)->frame == frame) {
- DVLOG(1) << "MediaStreamImpl::FrameWillClose: "
- << "Cancel user media request " << (*request_it)->request_id;
- // If the request is not generated, it means that a request
- // has been sent to the MediaStreamDispatcher to generate a stream
- // but MediaStreamDispatcher has not yet responded and we need to cancel
- // the request.
- if (!(*request_it)->generated) {
- media_stream_dispatcher_->CancelGenerateStream(
- (*request_it)->request_id, AsWeakPtr());
- }
- request_it = user_media_requests_.erase(request_it);
- } else {
- ++request_it;
- }
- }
-
- // Loop through all current local sources and stop the sources that were
- // created by the frame that will be closed.
- LocalStreamSources::iterator sources_it = local_sources_.begin();
- while (sources_it != local_sources_.end()) {
- if (sources_it->frame == frame) {
- StopLocalSource(sources_it->source, true);
- sources_it = local_sources_.erase(sources_it);
- } else {
- ++sources_it;
- }
- }
-}
-
-void MediaStreamImpl::OnLocalSourceStopped(
- const blink::WebMediaStreamSource& source) {
- DCHECK(CalledOnValidThread());
- DVLOG(1) << "MediaStreamImpl::OnLocalSourceStopped";
-
- bool device_found = false;
- for (LocalStreamSources::iterator device_it = local_sources_.begin();
- device_it != local_sources_.end(); ++device_it) {
- if (device_it->source.id() == source.id()) {
- device_found = true;
- local_sources_.erase(device_it);
- break;
- }
- }
- CHECK(device_found);
-
- MediaStreamSource* source_impl =
- static_cast<MediaStreamSource*> (source.extraData());
- media_stream_dispatcher_->StopStreamDevice(source_impl->device_info());
-}
-
-void MediaStreamImpl::StopLocalSource(
- const blink::WebMediaStreamSource& source,
- bool notify_dispatcher) {
- MediaStreamSource* source_impl =
- static_cast<MediaStreamSource*> (source.extraData());
- DVLOG(1) << "MediaStreamImpl::StopLocalSource("
- << "{device_id = " << source_impl->device_info().device.id << "})";
-
- if (notify_dispatcher)
- media_stream_dispatcher_->StopStreamDevice(source_impl->device_info());
-
- source_impl->ResetSourceStoppedCallback();
- source_impl->StopSource();
-}
-
-MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo(
- int request_id,
- blink::WebFrame* frame,
- const blink::WebUserMediaRequest& request,
- bool enable_automatic_output_device_selection)
- : request_id(request_id),
- generated(false),
- enable_automatic_output_device_selection(
- enable_automatic_output_device_selection),
- frame(frame),
- request(request),
- request_failed_(false) {
-}
-
-MediaStreamImpl::UserMediaRequestInfo::~UserMediaRequestInfo() {
- DVLOG(1) << "~UserMediaRequestInfo";
-}
-
-void MediaStreamImpl::UserMediaRequestInfo::StartAudioTrack(
- const blink::WebMediaStreamTrack& track,
- const blink::WebMediaConstraints& constraints) {
- DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
- MediaStreamAudioSource* native_source =
- static_cast <MediaStreamAudioSource*>(track.source().extraData());
- DCHECK(native_source);
-
- sources_.push_back(track.source());
- sources_waiting_for_callback_.push_back(native_source);
- native_source->AddTrack(
- track, constraints, base::Bind(
- &MediaStreamImpl::UserMediaRequestInfo::OnTrackStarted,
- AsWeakPtr()));
-}
-
-blink::WebMediaStreamTrack
-MediaStreamImpl::UserMediaRequestInfo::CreateAndStartVideoTrack(
- const blink::WebMediaStreamSource& source,
- const blink::WebMediaConstraints& constraints) {
- DCHECK(source.type() == blink::WebMediaStreamSource::TypeVideo);
- MediaStreamVideoSource* native_source =
- MediaStreamVideoSource::GetVideoSource(source);
- DCHECK(native_source);
- sources_.push_back(source);
- sources_waiting_for_callback_.push_back(native_source);
- return MediaStreamVideoTrack::CreateVideoTrack(
- native_source, constraints, base::Bind(
- &MediaStreamImpl::UserMediaRequestInfo::OnTrackStarted,
- AsWeakPtr()),
- true);
-}
-
-void MediaStreamImpl::UserMediaRequestInfo::CallbackOnTracksStarted(
- const ResourcesReady& callback) {
- DCHECK(ready_callback_.is_null());
- ready_callback_ = callback;
- CheckAllTracksStarted();
-}
-
-void MediaStreamImpl::UserMediaRequestInfo::OnTrackStarted(
- MediaStreamSource* source, bool success) {
- DVLOG(1) << "OnTrackStarted result " << success;
- std::vector<MediaStreamSource*>::iterator it =
- std::find(sources_waiting_for_callback_.begin(),
- sources_waiting_for_callback_.end(),
- source);
- DCHECK(it != sources_waiting_for_callback_.end());
- sources_waiting_for_callback_.erase(it);
- // All tracks must be started successfully. Otherwise the request is a
- // failure.
- if (!success)
- request_failed_ = true;
- CheckAllTracksStarted();
-}
-
-void MediaStreamImpl::UserMediaRequestInfo::CheckAllTracksStarted() {
- if (!ready_callback_.is_null() && sources_waiting_for_callback_.empty()) {
- ready_callback_.Run(
- this,
- request_failed_ ? MEDIA_DEVICE_TRACK_START_FAILURE : MEDIA_DEVICE_OK);
- }
-}
-
-bool MediaStreamImpl::UserMediaRequestInfo::IsSourceUsed(
- const blink::WebMediaStreamSource& source) const {
- for (std::vector<blink::WebMediaStreamSource>::const_iterator source_it =
- sources_.begin();
- source_it != sources_.end(); ++source_it) {
- if (source_it->id() == source.id())
- return true;
- }
- return false;
-}
-
-void MediaStreamImpl::UserMediaRequestInfo::RemoveSource(
- const blink::WebMediaStreamSource& source) {
- for (std::vector<blink::WebMediaStreamSource>::iterator it =
- sources_.begin();
- it != sources_.end(); ++it) {
- if (source.id() == it->id()) {
- sources_.erase(it);
- return;
- }
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_impl.h b/chromium/content/renderer/media/media_stream_impl.h
deleted file mode 100644
index ad960201f36..00000000000
--- a/chromium/content/renderer/media/media_stream_impl.h
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_MEDIA_MEDIA_STREAM_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/common/content_export.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
-#include "content/renderer/media/media_stream_source.h"
-#include "third_party/WebKit/public/platform/WebMediaStream.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebMediaDevicesRequest.h"
-#include "third_party/WebKit/public/web/WebUserMediaClient.h"
-#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
-
-namespace content {
-class PeerConnectionDependencyFactory;
-class MediaStreamDispatcher;
-class MediaStreamVideoSource;
-class VideoCapturerDelegate;
-
-// MediaStreamImpl is a delegate for the Media Stream GetUserMedia API.
-// It ties together WebKit and MediaStreamManager
-// (via MediaStreamDispatcher and MediaStreamDispatcherHost)
-// in the browser process. It must be created, called and destroyed on the
-// render thread.
-// MediaStreamImpl have weak pointers to a MediaStreamDispatcher.
-class CONTENT_EXPORT MediaStreamImpl
- : public RenderViewObserver,
- NON_EXPORTED_BASE(public blink::WebUserMediaClient),
- public MediaStreamDispatcherEventHandler,
- public base::SupportsWeakPtr<MediaStreamImpl>,
- NON_EXPORTED_BASE(public base::NonThreadSafe) {
- public:
- MediaStreamImpl(
- RenderView* render_view,
- MediaStreamDispatcher* media_stream_dispatcher,
- PeerConnectionDependencyFactory* dependency_factory);
- virtual ~MediaStreamImpl();
-
- // blink::WebUserMediaClient implementation
- virtual void requestUserMedia(
- const blink::WebUserMediaRequest& user_media_request);
- virtual void cancelUserMediaRequest(
- const blink::WebUserMediaRequest& user_media_request);
- virtual void requestMediaDevices(
- const blink::WebMediaDevicesRequest& media_devices_request) OVERRIDE;
- virtual void cancelMediaDevicesRequest(
- const blink::WebMediaDevicesRequest& media_devices_request) OVERRIDE;
-
- // MediaStreamDispatcherEventHandler implementation.
- virtual void OnStreamGenerated(
- int request_id,
- const std::string& label,
- const StreamDeviceInfoArray& audio_array,
- const StreamDeviceInfoArray& video_array) OVERRIDE;
- virtual void OnStreamGenerationFailed(
- int request_id,
- content::MediaStreamRequestResult result) OVERRIDE;
- virtual void OnDeviceStopped(const std::string& label,
- const StreamDeviceInfo& device_info) OVERRIDE;
- virtual void OnDevicesEnumerated(
- int request_id,
- const StreamDeviceInfoArray& device_array) OVERRIDE;
- virtual void OnDeviceOpened(
- int request_id,
- const std::string& label,
- const StreamDeviceInfo& device_info) OVERRIDE;
- virtual void OnDeviceOpenFailed(int request_id) OVERRIDE;
-
- // RenderViewObserver OVERRIDE
- virtual void FrameDetached(blink::WebFrame* frame) OVERRIDE;
- virtual void FrameWillClose(blink::WebFrame* frame) OVERRIDE;
-
- protected:
- // Called when |source| has been stopped from JavaScript.
- void OnLocalSourceStopped(const blink::WebMediaStreamSource& source);
-
- // These methods are virtual for test purposes. A test can override them to
- // test requesting local media streams. The function notifies WebKit that the
- // |request| have completed.
- virtual void GetUserMediaRequestSucceeded(
- const blink::WebMediaStream& stream,
- blink::WebUserMediaRequest* request_info);
- virtual void GetUserMediaRequestFailed(
- blink::WebUserMediaRequest* request_info,
- content::MediaStreamRequestResult result);
- virtual void EnumerateDevicesSucceded(
- blink::WebMediaDevicesRequest* request,
- blink::WebVector<blink::WebMediaDeviceInfo>& devices);
- // Creates a MediaStreamVideoSource object.
- // This is virtual for test purposes.
- virtual MediaStreamVideoSource* CreateVideoSource(
- const StreamDeviceInfo& device,
- const MediaStreamSource::SourceStoppedCallback& stop_callback);
-
- private:
- // Class for storing information about a WebKit request to create a
- // MediaStream.
- class UserMediaRequestInfo
- : public base::SupportsWeakPtr<UserMediaRequestInfo> {
- public:
- typedef base::Callback<void(UserMediaRequestInfo* request_info,
- content::MediaStreamRequestResult result)>
- ResourcesReady;
-
- UserMediaRequestInfo(int request_id,
- blink::WebFrame* frame,
- const blink::WebUserMediaRequest& request,
- bool enable_automatic_output_device_selection);
- ~UserMediaRequestInfo();
- int request_id;
- // True if MediaStreamDispatcher has generated the stream, see
- // OnStreamGenerated.
- bool generated;
- const bool enable_automatic_output_device_selection;
- blink::WebFrame* frame; // WebFrame that requested the MediaStream.
- blink::WebMediaStream web_stream;
- blink::WebUserMediaRequest request;
-
- void StartAudioTrack(const blink::WebMediaStreamTrack& track,
- const blink::WebMediaConstraints& constraints);
-
- blink::WebMediaStreamTrack CreateAndStartVideoTrack(
- const blink::WebMediaStreamSource& source,
- const blink::WebMediaConstraints& constraints);
-
- // Triggers |callback| when all sources used in this request have either
- // successfully started, or a source has failed to start.
- void CallbackOnTracksStarted(const ResourcesReady& callback);
-
- bool IsSourceUsed(const blink::WebMediaStreamSource& source) const;
- void RemoveSource(const blink::WebMediaStreamSource& source);
-
- bool AreAllSourcesRemoved() const { return sources_.empty(); }
-
- private:
- void OnTrackStarted(MediaStreamSource* source, bool success);
- void CheckAllTracksStarted();
-
- ResourcesReady ready_callback_;
- bool request_failed_;
- // Sources used in this request.
- std::vector<blink::WebMediaStreamSource> sources_;
- std::vector<MediaStreamSource*> sources_waiting_for_callback_;
- };
- typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests;
-
- struct LocalStreamSource {
- LocalStreamSource(blink::WebFrame* frame,
- const blink::WebMediaStreamSource& source)
- : frame(frame), source(source) {
- }
- // |frame| is the WebFrame that requested |source|. NULL in unit tests.
- // TODO(perkj): Change so that |frame| is not NULL in unit tests.
- blink::WebFrame* frame;
- blink::WebMediaStreamSource source;
- };
- typedef std::vector<LocalStreamSource> LocalStreamSources;
-
- struct MediaDevicesRequestInfo;
- typedef ScopedVector<MediaDevicesRequestInfo> MediaDevicesRequests;
-
- // Creates a WebKit representation of stream sources based on
- // |devices| from the MediaStreamDispatcher.
- void InitializeSourceObject(
- const StreamDeviceInfo& device,
- blink::WebMediaStreamSource::Type type,
- const blink::WebMediaConstraints& constraints,
- blink::WebFrame* frame,
- blink::WebMediaStreamSource* webkit_source);
-
- void CreateVideoTracks(
- const StreamDeviceInfoArray& devices,
- const blink::WebMediaConstraints& constraints,
- blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
- UserMediaRequestInfo* request);
-
- void CreateAudioTracks(
- const StreamDeviceInfoArray& devices,
- const blink::WebMediaConstraints& constraints,
- blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
- UserMediaRequestInfo* request);
-
- // Callback function triggered when all native versions of the
- // underlying media sources and tracks have been created and started.
- void OnCreateNativeTracksCompleted(
- UserMediaRequestInfo* request,
- content::MediaStreamRequestResult result);
-
- UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id);
- UserMediaRequestInfo* FindUserMediaRequestInfo(
- const blink::WebUserMediaRequest& request);
- void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request);
-
- MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(int request_id);
- MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(
- const blink::WebMediaDevicesRequest& request);
- void DeleteMediaDevicesRequestInfo(MediaDevicesRequestInfo* request);
-
- // Returns the source that use a device with |device.session_id|
- // and |device.device.id|. NULL if such source doesn't exist.
- const blink::WebMediaStreamSource* FindLocalSource(
- const StreamDeviceInfo& device) const;
-
- void StopLocalSource(const blink::WebMediaStreamSource& source,
- bool notify_dispatcher);
-
- // Weak ref to a PeerConnectionDependencyFactory, owned by the RenderThread.
- // It's valid for the lifetime of RenderThread.
- // TODO(xians): Remove this dependency once audio do not need it for local
- // audio.
- PeerConnectionDependencyFactory* dependency_factory_;
-
- // media_stream_dispatcher_ is a weak reference, owned by RenderView. It's
- // valid for the lifetime of RenderView.
- MediaStreamDispatcher* media_stream_dispatcher_;
-
- LocalStreamSources local_sources_;
-
- UserMediaRequests user_media_requests_;
-
- // Requests to enumerate media devices.
- MediaDevicesRequests media_devices_requests_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_IMPL_H_
diff --git a/chromium/content/renderer/media/media_stream_impl_unittest.cc b/chromium/content/renderer/media/media_stream_impl_unittest.cc
deleted file mode 100644
index cddf1192150..00000000000
--- a/chromium/content/renderer/media/media_stream_impl_unittest.cc
+++ /dev/null
@@ -1,475 +0,0 @@
-// Copyright (c) 2012 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/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/child_process.h"
-#include "content/renderer/media/media_stream.h"
-#include "content/renderer/media/media_stream_impl.h"
-#include "content/renderer/media/media_stream_track.h"
-#include "content/renderer/media/mock_media_stream_dispatcher.h"
-#include "content/renderer/media/mock_media_stream_video_source.h"
-#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
-#include "third_party/WebKit/public/platform/WebMediaStream.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-
-namespace content {
-
-class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource {
- public:
- MockMediaStreamVideoCapturerSource(
- const StreamDeviceInfo& device,
- const SourceStoppedCallback& stop_callback,
- PeerConnectionDependencyFactory* factory)
- : MockMediaStreamVideoSource(false) {
- SetDeviceInfo(device);
- SetStopCallback(stop_callback);
- }
-};
-
-class MediaStreamImplUnderTest : public MediaStreamImpl {
- public:
- enum RequestState {
- REQUEST_NOT_STARTED,
- REQUEST_NOT_COMPLETE,
- REQUEST_SUCCEEDED,
- REQUEST_FAILED,
- };
-
- MediaStreamImplUnderTest(MediaStreamDispatcher* media_stream_dispatcher,
- PeerConnectionDependencyFactory* dependency_factory)
- : MediaStreamImpl(NULL, media_stream_dispatcher, dependency_factory),
- state_(REQUEST_NOT_STARTED),
- result_(NUM_MEDIA_REQUEST_RESULTS),
- factory_(dependency_factory),
- video_source_(NULL) {
- }
-
- void RequestUserMedia() {
- blink::WebUserMediaRequest user_media_request;
- state_ = REQUEST_NOT_COMPLETE;
- requestUserMedia(user_media_request);
- }
-
- void RequestMediaDevices() {
- blink::WebMediaDevicesRequest media_devices_request;
- state_ = REQUEST_NOT_COMPLETE;
- requestMediaDevices(media_devices_request);
- }
-
- virtual void GetUserMediaRequestSucceeded(
- const blink::WebMediaStream& stream,
- blink::WebUserMediaRequest* request_info) OVERRIDE {
- last_generated_stream_ = stream;
- state_ = REQUEST_SUCCEEDED;
- }
-
- virtual void GetUserMediaRequestFailed(
- blink::WebUserMediaRequest* request_info,
- content::MediaStreamRequestResult result) OVERRIDE {
- last_generated_stream_.reset();
- state_ = REQUEST_FAILED;
- result_ = result;
- }
-
- virtual void EnumerateDevicesSucceded(
- blink::WebMediaDevicesRequest* request,
- blink::WebVector<blink::WebMediaDeviceInfo>& devices) OVERRIDE {
- state_ = REQUEST_SUCCEEDED;
- last_devices_ = devices;
- }
-
- virtual MediaStreamVideoSource* CreateVideoSource(
- const StreamDeviceInfo& device,
- const MediaStreamSource::SourceStoppedCallback& stop_callback) OVERRIDE {
- video_source_ = new MockMediaStreamVideoCapturerSource(device,
- stop_callback,
- factory_);
- return video_source_;
- }
-
- const blink::WebMediaStream& last_generated_stream() {
- return last_generated_stream_;
- }
-
- const blink::WebVector<blink::WebMediaDeviceInfo>& last_devices() {
- return last_devices_;
- }
-
- void ClearLastGeneratedStream() {
- last_generated_stream_.reset();
- }
-
- MockMediaStreamVideoCapturerSource* last_created_video_source() const {
- return video_source_;
- }
-
- RequestState request_state() const { return state_; }
- content::MediaStreamRequestResult error_reason() const { return result_; }
-
- private:
- blink::WebMediaStream last_generated_stream_;
- RequestState state_;
- content::MediaStreamRequestResult result_;
- blink::WebVector<blink::WebMediaDeviceInfo> last_devices_;
- PeerConnectionDependencyFactory* factory_;
- MockMediaStreamVideoCapturerSource* video_source_;
-};
-
-class MediaStreamImplTest : public ::testing::Test {
- public:
- virtual void SetUp() {
- // Create our test object.
- child_process_.reset(new ChildProcess());
- ms_dispatcher_.reset(new MockMediaStreamDispatcher());
- dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
- ms_impl_.reset(new MediaStreamImplUnderTest(ms_dispatcher_.get(),
- dependency_factory_.get()));
- }
-
- blink::WebMediaStream RequestLocalMediaStream() {
- ms_impl_->RequestUserMedia();
- FakeMediaStreamDispatcherRequestUserMediaComplete();
- StartMockedVideoSource();
-
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED,
- ms_impl_->request_state());
-
- blink::WebMediaStream desc = ms_impl_->last_generated_stream();
- content::MediaStream* native_stream =
- content::MediaStream::GetMediaStream(desc);
- if (!native_stream) {
- ADD_FAILURE();
- return desc;
- }
-
- blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
- desc.audioTracks(audio_tracks);
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
- desc.videoTracks(video_tracks);
-
- EXPECT_EQ(1u, audio_tracks.size());
- EXPECT_EQ(1u, video_tracks.size());
- EXPECT_NE(audio_tracks[0].id(), video_tracks[0].id());
- return desc;
- }
-
- void FakeMediaStreamDispatcherRequestUserMediaComplete() {
- // Audio request ID is used as the shared request ID.
- ms_impl_->OnStreamGenerated(ms_dispatcher_->audio_input_request_id(),
- ms_dispatcher_->stream_label(),
- ms_dispatcher_->audio_input_array(),
- ms_dispatcher_->video_array());
- }
-
- void FakeMediaStreamDispatcherRequestMediaDevicesComplete() {
- ms_impl_->OnDevicesEnumerated(ms_dispatcher_->audio_input_request_id(),
- ms_dispatcher_->audio_input_array());
- ms_impl_->OnDevicesEnumerated(ms_dispatcher_->audio_output_request_id(),
- ms_dispatcher_->audio_output_array());
- ms_impl_->OnDevicesEnumerated(ms_dispatcher_->video_request_id(),
- ms_dispatcher_->video_array());
- }
-
- void StartMockedVideoSource() {
- MockMediaStreamVideoCapturerSource* video_source =
- ms_impl_->last_created_video_source();
- if (video_source->SourceHasAttemptedToStart())
- video_source->StartMockedSource();
- }
-
- void FailToStartMockedVideoSource() {
- MockMediaStreamVideoCapturerSource* video_source =
- ms_impl_->last_created_video_source();
- if (video_source->SourceHasAttemptedToStart())
- video_source->FailToStartMockedSource();
- }
-
- void FailToCreateNextAudioCapturer() {
- dependency_factory_->FailToCreateNextAudioCapturer();
- }
-
- protected:
- base::MessageLoop message_loop_;
- scoped_ptr<ChildProcess> child_process_;
- scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher_;
- scoped_ptr<MediaStreamImplUnderTest> ms_impl_;
- scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
-};
-
-TEST_F(MediaStreamImplTest, GenerateMediaStream) {
- // Generate a stream with both audio and video.
- blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
-}
-
-// Test that the same source object is used if two MediaStreams are generated
-// using the same source.
-TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithSameSource) {
- blink::WebMediaStream desc1 = RequestLocalMediaStream();
- blink::WebMediaStream desc2 = RequestLocalMediaStream();
-
- blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
- desc1.videoTracks(desc1_video_tracks);
- blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
- desc2.videoTracks(desc2_video_tracks);
- EXPECT_EQ(desc1_video_tracks[0].source().id(),
- desc2_video_tracks[0].source().id());
-
- EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
- desc2_video_tracks[0].source().extraData());
-
- blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
- desc1.audioTracks(desc1_audio_tracks);
- blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
- desc2.audioTracks(desc2_audio_tracks);
- EXPECT_EQ(desc1_audio_tracks[0].source().id(),
- desc2_audio_tracks[0].source().id());
-
- EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
- desc2_audio_tracks[0].source().extraData());
-}
-
-// Test that the same source object is not used if two MediaStreams are
-// generated using different sources.
-TEST_F(MediaStreamImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
- blink::WebMediaStream desc1 = RequestLocalMediaStream();
- // Make sure another device is selected (another |session_id|) in the next
- // gUM request.
- ms_dispatcher_->IncrementSessionId();
- blink::WebMediaStream desc2 = RequestLocalMediaStream();
-
- blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
- desc1.videoTracks(desc1_video_tracks);
- blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
- desc2.videoTracks(desc2_video_tracks);
- EXPECT_NE(desc1_video_tracks[0].source().id(),
- desc2_video_tracks[0].source().id());
-
- EXPECT_NE(desc1_video_tracks[0].source().extraData(),
- desc2_video_tracks[0].source().extraData());
-
- blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
- desc1.audioTracks(desc1_audio_tracks);
- blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
- desc2.audioTracks(desc2_audio_tracks);
- EXPECT_NE(desc1_audio_tracks[0].source().id(),
- desc2_audio_tracks[0].source().id());
-
- EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
- desc2_audio_tracks[0].source().extraData());
-}
-
-TEST_F(MediaStreamImplTest, StopLocalTracks) {
- // Generate a stream with both audio and video.
- blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
-
- blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
- mixed_desc.audioTracks(audio_tracks);
- MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
- audio_track->Stop();
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
-
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
- mixed_desc.videoTracks(video_tracks);
- MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
- video_track->Stop();
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-// This test that a source is not stopped even if the tracks in a
-// MediaStream is stopped if there are two MediaStreams with tracks using the
-// same device. The source is stopped
-// if there are no more MediaStream tracks using the device.
-TEST_F(MediaStreamImplTest, StopLocalTracksWhenTwoStreamUseSameDevices) {
- // Generate a stream with both audio and video.
- blink::WebMediaStream desc1 = RequestLocalMediaStream();
- blink::WebMediaStream desc2 = RequestLocalMediaStream();
-
- blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1;
- desc1.audioTracks(audio_tracks1);
- MediaStreamTrack* audio_track1 = MediaStreamTrack::GetTrack(audio_tracks1[0]);
- audio_track1->Stop();
- EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
-
- blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2;
- desc2.audioTracks(audio_tracks2);
- MediaStreamTrack* audio_track2 = MediaStreamTrack::GetTrack(audio_tracks2[0]);
- audio_track2->Stop();
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
-
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks1;
- desc1.videoTracks(video_tracks1);
- MediaStreamTrack* video_track1 = MediaStreamTrack::GetTrack(video_tracks1[0]);
- video_track1->Stop();
- EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
-
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks2;
- desc2.videoTracks(video_tracks2);
- MediaStreamTrack* video_track2 = MediaStreamTrack::GetTrack(video_tracks2[0]);
- video_track2->Stop();
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-TEST_F(MediaStreamImplTest, StopSourceWhenMediaStreamGoesOutOfScope) {
- // Generate a stream with both audio and video.
- RequestLocalMediaStream();
- // Makes sure the test itself don't hold a reference to the created
- // MediaStream.
- ms_impl_->ClearLastGeneratedStream();
-
- // Expect the sources to be stopped when the MediaStream goes out of scope.
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-// Test that the MediaStreams are deleted if the owning WebFrame is deleted.
-// In the unit test the owning frame is NULL.
-TEST_F(MediaStreamImplTest, FrameWillClose) {
- // Test a stream with both audio and video.
- blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
- blink::WebMediaStream desc2 = RequestLocalMediaStream();
-
- // Test that the MediaStreams are deleted if the owning WebFrame is deleted.
- // In the unit test the owning frame is NULL.
- ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-// This test what happens if a video source to a MediaSteam fails to start.
-TEST_F(MediaStreamImplTest, MediaVideoSourceFailToStart) {
- ms_impl_->RequestUserMedia();
- FakeMediaStreamDispatcherRequestUserMediaComplete();
- FailToStartMockedVideoSource();
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
- ms_impl_->request_state());
- EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
- ms_impl_->error_reason());
- EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-// This test what happens if an audio source fail to initialize.
-TEST_F(MediaStreamImplTest, MediaAudioSourceFailToInitialize) {
- FailToCreateNextAudioCapturer();
- ms_impl_->RequestUserMedia();
- FakeMediaStreamDispatcherRequestUserMediaComplete();
- StartMockedVideoSource();
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_FAILED,
- ms_impl_->request_state());
- EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
- ms_impl_->error_reason());
- EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-// This test what happens if MediaStreamImpl is deleted before a source has
-// started.
-TEST_F(MediaStreamImplTest, MediaStreamImplShutDown) {
- ms_impl_->RequestUserMedia();
- FakeMediaStreamDispatcherRequestUserMediaComplete();
- EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
- ms_impl_->request_state());
- ms_impl_.reset();
-}
-
-// This test what happens if the WebFrame is closed while the MediaStream is
-// being generated by the MediaStreamDispatcher.
-TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingStream) {
- ms_impl_->RequestUserMedia();
- ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
- ms_impl_->request_state());
-}
-
-// This test what happens if the WebFrame is closed while the sources are being
-// started.
-TEST_F(MediaStreamImplTest, ReloadFrameWhileGeneratingSources) {
- ms_impl_->RequestUserMedia();
- FakeMediaStreamDispatcherRequestUserMediaComplete();
- EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_NOT_COMPLETE,
- ms_impl_->request_state());
-}
-
-// This test what happens if stop is called on a track after the frame has
-// been reloaded.
-TEST_F(MediaStreamImplTest, StopTrackAfterReload) {
- blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
- EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
- ms_impl_->FrameWillClose(NULL);
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-
- blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
- mixed_desc.audioTracks(audio_tracks);
- MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
- audio_track->Stop();
- EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
-
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
- mixed_desc.videoTracks(video_tracks);
- MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
- video_track->Stop();
- EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
-}
-
-TEST_F(MediaStreamImplTest, EnumerateMediaDevices) {
- ms_impl_->RequestMediaDevices();
- FakeMediaStreamDispatcherRequestMediaDevicesComplete();
-
- EXPECT_EQ(MediaStreamImplUnderTest::REQUEST_SUCCEEDED,
- ms_impl_->request_state());
-
- // Audio input device with matched output ID.
- EXPECT_FALSE(ms_impl_->last_devices()[0].deviceId().isEmpty());
- EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
- ms_impl_->last_devices()[0].kind());
- EXPECT_FALSE(ms_impl_->last_devices()[0].label().isEmpty());
- EXPECT_FALSE(ms_impl_->last_devices()[0].groupId().isEmpty());
-
- // Audio input device without matched output ID.
- EXPECT_FALSE(ms_impl_->last_devices()[1].deviceId().isEmpty());
- EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
- ms_impl_->last_devices()[1].kind());
- EXPECT_FALSE(ms_impl_->last_devices()[1].label().isEmpty());
- EXPECT_FALSE(ms_impl_->last_devices()[1].groupId().isEmpty());
-
- // Video input device.
- EXPECT_FALSE(ms_impl_->last_devices()[2].deviceId().isEmpty());
- EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
- ms_impl_->last_devices()[2].kind());
- EXPECT_FALSE(ms_impl_->last_devices()[2].label().isEmpty());
- EXPECT_TRUE(ms_impl_->last_devices()[2].groupId().isEmpty());
-
- // Audio output device.
- EXPECT_FALSE(ms_impl_->last_devices()[3].deviceId().isEmpty());
- EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput,
- ms_impl_->last_devices()[3].kind());
- EXPECT_FALSE(ms_impl_->last_devices()[3].label().isEmpty());
- EXPECT_FALSE(ms_impl_->last_devices()[3].groupId().isEmpty());
-
- // Verfify group IDs.
- EXPECT_TRUE(ms_impl_->last_devices()[0].groupId().equals(
- ms_impl_->last_devices()[3].groupId()));
- EXPECT_FALSE(ms_impl_->last_devices()[1].groupId().equals(
- ms_impl_->last_devices()[3].groupId()));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_renderer_factory.cc b/chromium/content/renderer/media/media_stream_renderer_factory.cc
index 628364465aa..df633bd8efa 100644
--- a/chromium/content/renderer/media/media_stream_renderer_factory.cc
+++ b/chromium/content/renderer/media/media_stream_renderer_factory.cc
@@ -76,6 +76,7 @@ scoped_refptr<WebRtcAudioRenderer> CreateRemoteAudioRenderer(
}
return new WebRtcAudioRenderer(
+ GetPeerConnectionDependencyFactory()->GetWebRtcSignalingThread(),
stream, routing_id, render_frame_id, session_id,
sample_rate, buffer_size);
}
diff --git a/chromium/content/renderer/media/media_stream_source.h b/chromium/content/renderer/media/media_stream_source.h
index 18821c38cf5..05aae2ad56a 100644
--- a/chromium/content/renderer/media/media_stream_source.h
+++ b/chromium/content/renderer/media/media_stream_source.h
@@ -25,7 +25,9 @@ class CONTENT_EXPORT MediaStreamSource
SourceStoppedCallback;
typedef base::Callback<void(MediaStreamSource* source,
- bool success)> ConstraintsCallback;
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name)>
+ ConstraintsCallback;
// Source constraints key for
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html.
diff --git a/chromium/content/renderer/media/media_stream_track.cc b/chromium/content/renderer/media/media_stream_track.cc
index 529bc384e89..70ebca194cc 100644
--- a/chromium/content/renderer/media/media_stream_track.cc
+++ b/chromium/content/renderer/media/media_stream_track.cc
@@ -10,6 +10,7 @@
namespace content {
+// static
MediaStreamTrack* MediaStreamTrack::GetTrack(
const blink::WebMediaStreamTrack& track) {
if (track.isNull())
@@ -17,31 +18,16 @@ MediaStreamTrack* MediaStreamTrack::GetTrack(
return static_cast<MediaStreamTrack*>(track.extraData());
}
-MediaStreamTrack::MediaStreamTrack(
- webrtc::MediaStreamTrackInterface* track, bool is_local_track)
- : track_(track),
- is_local_track_(is_local_track) {
+MediaStreamTrack::MediaStreamTrack(bool is_local_track)
+ : is_local_track_(is_local_track) {
}
MediaStreamTrack::~MediaStreamTrack() {
}
-void MediaStreamTrack::SetEnabled(bool enabled) {
- if (track_)
- track_->set_enabled(enabled);
-}
-
-void MediaStreamTrack::Stop() {
- // Stop means that a track should be stopped permanently. But
- // since there is no proper way of doing that on a remote track, we can
- // at least disable the track. Blink will not call down to the content layer
- // after a track has been stopped.
- if (track_)
- track_->set_enabled(false);
-}
-
webrtc::AudioTrackInterface* MediaStreamTrack::GetAudioAdapter() {
- return static_cast<webrtc::AudioTrackInterface*>(track_.get());
+ NOTREACHED();
+ return nullptr;
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_track.h b/chromium/content/renderer/media/media_stream_track.h
index 456005d4d05..14b991aeb88 100644
--- a/chromium/content/renderer/media/media_stream_track.h
+++ b/chromium/content/renderer/media/media_stream_track.h
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_
-#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_
+#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_H_
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
@@ -24,33 +25,29 @@ namespace content {
class CONTENT_EXPORT MediaStreamTrack
: NON_EXPORTED_BASE(public blink::WebMediaStreamTrack::ExtraData) {
public:
- MediaStreamTrack(webrtc::MediaStreamTrackInterface* track,
- bool is_local_track);
+ explicit MediaStreamTrack(bool is_local_track);
virtual ~MediaStreamTrack();
static MediaStreamTrack* GetTrack(
const blink::WebMediaStreamTrack& track);
- // If a subclass overrides this method it has to call the base class.
- virtual void SetEnabled(bool enabled);
+ virtual void SetEnabled(bool enabled) = 0;
- // TODO(xians): Make this pure virtual when Stop[Track] has been
- // implemented for remote audio tracks.
- virtual void Stop();
+ virtual void Stop() = 0;
+ // TODO(tommi, xians): Remove this method.
virtual webrtc::AudioTrackInterface* GetAudioAdapter();
- bool is_local_track () const { return is_local_track_; }
+ bool is_local_track() const { return is_local_track_; }
protected:
- scoped_refptr<webrtc::MediaStreamTrackInterface> track_;
-
- private:
const bool is_local_track_;
+ base::ThreadChecker thread_checker_;
+
DISALLOW_COPY_AND_ASSIGN(MediaStreamTrack);
};
} // namespace content
-#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_EXTRA_DATA_H_
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_TRACK_H_
diff --git a/chromium/content/renderer/media/media_stream_video_capture_source_unittest.cc b/chromium/content/renderer/media/media_stream_video_capture_source_unittest.cc
index fca4562a93d..038acef7709 100644
--- a/chromium/content/renderer/media/media_stream_video_capture_source_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_capture_source_unittest.cc
@@ -15,6 +15,7 @@
#include "media/base/bind_to_current_loop.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
namespace content {
@@ -37,20 +38,28 @@ class MediaStreamVideoCapturerSourceTest : public testing::Test {
public:
MediaStreamVideoCapturerSourceTest()
: child_process_(new ChildProcess()),
- source_(NULL) {
+ source_(NULL),
+ source_stopped_(false) {
+ }
+
+ void TearDown() override {
+ webkit_source_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
}
void InitWithDeviceInfo(const StreamDeviceInfo& device_info) {
delegate_ = new MockVideoCapturerDelegate(device_info);
source_ = new MediaStreamVideoCapturerSource(
device_info,
- MediaStreamSource::SourceStoppedCallback(),
+ base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
+ base::Unretained(this)),
delegate_);
webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
blink::WebMediaStreamSource::TypeVideo,
base::UTF8ToUTF16("dummy_source_name"));
webkit_source_.setExtraData(source_);
+ webkit_source_id_ = webkit_source_.id();
}
blink::WebMediaStreamTrack StartSource() {
@@ -69,8 +78,15 @@ class MediaStreamVideoCapturerSourceTest : public testing::Test {
return *static_cast<MockVideoCapturerDelegate*>(delegate_.get());
}
+ void OnSourceStopped(const blink::WebMediaStreamSource& source) {
+ source_stopped_ = true;
+ EXPECT_EQ(source.id(), webkit_source_id_);
+ }
+
protected:
- void OnConstraintsApplied(MediaStreamSource* source, bool success) {
+ void OnConstraintsApplied(MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
}
base::MessageLoopForUI message_loop_;
@@ -78,6 +94,8 @@ class MediaStreamVideoCapturerSourceTest : public testing::Test {
blink::WebMediaStreamSource webkit_source_;
MediaStreamVideoCapturerSource* source_; // owned by webkit_source.
scoped_refptr<VideoCapturerDelegate> delegate_;
+ blink::WebString webkit_source_id_;
+ bool source_stopped_;
};
TEST_F(MediaStreamVideoCapturerSourceTest, TabCaptureAllowResolutionChange) {
@@ -86,7 +104,8 @@ TEST_F(MediaStreamVideoCapturerSourceTest, TabCaptureAllowResolutionChange) {
InitWithDeviceInfo(device_info);
EXPECT_CALL(mock_delegate(), StartCapture(
- testing::Field(&media::VideoCaptureParams::allow_resolution_change, true),
+ testing::Field(&media::VideoCaptureParams::resolution_change_policy,
+ media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT),
testing::_,
testing::_)).Times(1);
blink::WebMediaStreamTrack track = StartSource();
@@ -101,7 +120,8 @@ TEST_F(MediaStreamVideoCapturerSourceTest,
InitWithDeviceInfo(device_info);
EXPECT_CALL(mock_delegate(), StartCapture(
- testing::Field(&media::VideoCaptureParams::allow_resolution_change, true),
+ testing::Field(&media::VideoCaptureParams::resolution_change_policy,
+ media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT),
testing::_,
testing::_)).Times(1);
blink::WebMediaStreamTrack track = StartSource();
@@ -115,12 +135,14 @@ TEST_F(MediaStreamVideoCapturerSourceTest, Ended) {
delegate_ = new VideoCapturerDelegate(device_info);
source_ = new MediaStreamVideoCapturerSource(
device_info,
- MediaStreamSource::SourceStoppedCallback(),
+ base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
+ base::Unretained(this)),
delegate_);
webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
blink::WebMediaStreamSource::TypeVideo,
base::UTF8ToUTF16("dummy_source_name"));
webkit_source_.setExtraData(source_);
+ webkit_source_id_ = webkit_source_.id();
blink::WebMediaStreamTrack track = StartSource();
message_loop_.RunUntilIdle();
@@ -129,10 +151,13 @@ TEST_F(MediaStreamVideoCapturerSourceTest, Ended) {
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
webkit_source_.readyState());
+ EXPECT_FALSE(source_stopped_);
delegate_->OnStateUpdateOnRenderThread(VIDEO_CAPTURE_STATE_ERROR);
message_loop_.RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
webkit_source_.readyState());
+ // Verify that MediaStreamSource::SourceStoppedCallback has been triggered.
+ EXPECT_TRUE(source_stopped_);
}
class FakeMediaStreamVideoSink : public MediaStreamVideoSink {
@@ -172,7 +197,7 @@ TEST_F(MediaStreamVideoCapturerSourceTest, CaptureTime) {
testing::SaveArg<2>(&running_cb)));
EXPECT_CALL(mock_delegate(), StopCapture());
blink::WebMediaStreamTrack track = StartSource();
- running_cb.Run(true);
+ running_cb.Run(MEDIA_DEVICE_OK);
base::RunLoop run_loop;
base::TimeTicks reference_capture_time =
diff --git a/chromium/content/renderer/media/media_stream_video_capturer_source.cc b/chromium/content/renderer/media/media_stream_video_capturer_source.cc
index f4555afb4f0..7dcd92e3739 100644
--- a/chromium/content/renderer/media/media_stream_video_capturer_source.cc
+++ b/chromium/content/renderer/media/media_stream_video_capturer_source.cc
@@ -30,6 +30,9 @@ const SourceVideoResolution kVideoResolutions[] = {{1920, 1080},
// Frame rates for sources with no support for capability enumeration.
const int kVideoFrameRates[] = {30, 60};
+// Hard upper-bound frame rate for tab/desktop capture.
+const double kMaxScreenCastFrameRate = 120.0;
+
} // namespace
namespace content {
@@ -38,8 +41,7 @@ VideoCapturerDelegate::VideoCapturerDelegate(
const StreamDeviceInfo& device_info)
: session_id_(device_info.session_id),
is_screen_cast_(device_info.device.type == MEDIA_TAB_VIDEO_CAPTURE ||
- device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE),
- got_first_frame_(false) {
+ device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
DVLOG(3) << "VideoCapturerDelegate::ctor";
// NULL in unit test.
@@ -60,23 +62,24 @@ VideoCapturerDelegate::~VideoCapturerDelegate() {
void VideoCapturerDelegate::GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) {
- DVLOG(3) << "GetCurrentSupportedFormats("
- << " { max_requested_height = " << max_requested_height << "})"
- << " { max_requested_width = " << max_requested_width << "})";
+ DVLOG(3)
+ << "GetCurrentSupportedFormats("
+ << " { max_requested_height = " << max_requested_height << "})"
+ << " { max_requested_width = " << max_requested_width << "})"
+ << " { max_requested_frame_rate = " << max_requested_frame_rate << "})";
if (is_screen_cast_) {
- media::VideoCaptureFormats formats;
const int width = max_requested_width ?
max_requested_width : MediaStreamVideoSource::kDefaultWidth;
const int height = max_requested_height ?
max_requested_height : MediaStreamVideoSource::kDefaultHeight;
- formats.push_back(
- media::VideoCaptureFormat(
- gfx::Size(width, height),
- MediaStreamVideoSource::kDefaultFrameRate,
- media::PIXEL_FORMAT_I420));
- callback.Run(formats);
+ callback.Run(media::VideoCaptureFormats(1, media::VideoCaptureFormat(
+ gfx::Size(width, height),
+ static_cast<float>(std::min(kMaxScreenCastFrameRate,
+ max_requested_frame_rate)),
+ media::PIXEL_FORMAT_I420)));
return;
}
@@ -103,7 +106,6 @@ void VideoCapturerDelegate::StartCapture(
DCHECK(params.requested_format.IsValid());
DCHECK(thread_checker_.CalledOnValidThread());
running_callback_ = running_callback;
- got_first_frame_ = false;
// NULL in unit test.
if (!RenderThreadImpl::current())
@@ -137,11 +139,12 @@ void VideoCapturerDelegate::OnStateUpdateOnRenderThread(
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << "OnStateUpdateOnRenderThread state = " << state;
if (state == VIDEO_CAPTURE_STATE_STARTED && !running_callback_.is_null()) {
- running_callback_.Run(true);
+ running_callback_.Run(MEDIA_DEVICE_OK);
return;
}
if (state > VIDEO_CAPTURE_STATE_STARTED && !running_callback_.is_null()) {
- base::ResetAndReturn(&running_callback_).Run(false);
+ base::ResetAndReturn(&running_callback_).Run(
+ MEDIA_DEVICE_TRACK_START_FAILURE);
}
}
@@ -218,20 +221,24 @@ MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) {
delegate_->GetCurrentSupportedFormats(
max_requested_width,
max_requested_height,
+ max_requested_frame_rate,
callback);
}
void MediaStreamVideoCapturerSource::StartSourceImpl(
- const media::VideoCaptureParams& params,
+ const media::VideoCaptureFormat& format,
const VideoCaptureDeliverFrameCB& frame_callback) {
- media::VideoCaptureParams new_params(params);
+ media::VideoCaptureParams new_params;
+ new_params.requested_format = format;
if (device_info().device.type == MEDIA_TAB_VIDEO_CAPTURE ||
device_info().device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
- new_params.allow_resolution_change = true;
+ new_params.resolution_change_policy =
+ media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT;
}
delegate_->StartCapture(
new_params,
diff --git a/chromium/content/renderer/media/media_stream_video_capturer_source.h b/chromium/content/renderer/media/media_stream_video_capturer_source.h
index dcffa02d371..e22b6db9c60 100644
--- a/chromium/content/renderer/media/media_stream_video_capturer_source.h
+++ b/chromium/content/renderer/media/media_stream_video_capturer_source.h
@@ -22,18 +22,19 @@ namespace content {
class CONTENT_EXPORT VideoCapturerDelegate
: public base::RefCountedThreadSafe<VideoCapturerDelegate> {
public:
- typedef base::Callback<void(bool running)> RunningCallback;
+ typedef base::Callback<void(MediaStreamRequestResult result)> RunningCallback;
- explicit VideoCapturerDelegate(
- const StreamDeviceInfo& device_info);
+ explicit VideoCapturerDelegate(const StreamDeviceInfo& device_info);
// Collects the formats that can currently be used.
- // |max_requested_height| and |max_requested_width| is used by Tab and Screen
- // capture to decide what resolution to generate.
- // |callback| is triggered when the formats have been collected.
+ // |max_requested_height|, |max_requested_width|, and
+ // |max_requested_frame_rate| is used by Tab and Screen capture to decide what
+ // resolution/framerate to generate. |callback| is triggered when the formats
+ // have been collected.
virtual void GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback);
// Starts capturing frames using the resolution in |params|.
@@ -70,7 +71,6 @@ class CONTENT_EXPORT VideoCapturerDelegate
base::Closure stop_capture_cb_;
bool is_screen_cast_;
- bool got_first_frame_;
// |running_callback| is provided to this class in StartCapture and must be
// valid until StopCapture is called.
@@ -100,16 +100,17 @@ class CONTENT_EXPORT MediaStreamVideoCapturerSource
protected:
// Implements MediaStreamVideoSource.
- virtual void GetCurrentSupportedFormats(
+ void GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
- const VideoCaptureDeviceFormatsCB& callback) OVERRIDE;
+ double max_requested_frame_rate,
+ const VideoCaptureDeviceFormatsCB& callback) override;
- virtual void StartSourceImpl(
- const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& frame_callback) OVERRIDE;
+ void StartSourceImpl(
+ const media::VideoCaptureFormat& format,
+ const VideoCaptureDeliverFrameCB& frame_callback) override;
- virtual void StopSourceImpl() OVERRIDE;
+ void StopSourceImpl() override;
private:
// The delegate that provides video frames.
diff --git a/chromium/content/renderer/media/media_stream_video_source.cc b/chromium/content/renderer/media/media_stream_video_source.cc
index 65ece681c14..6855adef140 100644
--- a/chromium/content/renderer/media/media_stream_video_source.cc
+++ b/chromium/content/renderer/media/media_stream_video_source.cc
@@ -42,6 +42,7 @@ const char* kSupportedConstraints[] = {
const int MediaStreamVideoSource::kDefaultWidth = 640;
const int MediaStreamVideoSource::kDefaultHeight = 480;
const int MediaStreamVideoSource::kDefaultFrameRate = 30;
+const int MediaStreamVideoSource::kUnknownFrameRate = 0;
namespace {
@@ -172,9 +173,9 @@ bool UpdateFormatForConstraint(
} else if (constraint_name == MediaStreamVideoSource::kMaxHeight) {
return value > 0.0;
} else if (constraint_name == MediaStreamVideoSource::kMinFrameRate) {
- return (value <= format->frame_rate);
+ return (value > 0.0) && (value <= format->frame_rate);
} else if (constraint_name == MediaStreamVideoSource::kMaxFrameRate) {
- if (value == 0.0) {
+ if (value <= 0.0) {
// The frame rate is set by constraint.
// Don't allow 0 as frame rate if it is a mandatory constraint.
// Set the frame rate to 1 if it is not mandatory.
@@ -219,7 +220,8 @@ void FilterFormatsByConstraint(
// Returns the media::VideoCaptureFormats that matches |constraints|.
media::VideoCaptureFormats FilterFormats(
const blink::WebMediaConstraints& constraints,
- const media::VideoCaptureFormats& supported_formats) {
+ const media::VideoCaptureFormats& supported_formats,
+ blink::WebString* unsatisfied_constraint) {
if (constraints.isNull()) {
return supported_formats;
}
@@ -250,13 +252,32 @@ media::VideoCaptureFormats FilterFormats(
if (min_width > max_width || min_height > max_height)
return media::VideoCaptureFormats();
+ double min_frame_rate = 0.0f;
+ double max_frame_rate = 0.0f;
+ if (GetConstraintValueAsDouble(constraints,
+ MediaStreamVideoSource::kMaxFrameRate,
+ &max_frame_rate) &&
+ GetConstraintValueAsDouble(constraints,
+ MediaStreamVideoSource::kMinFrameRate,
+ &min_frame_rate)) {
+ if (min_frame_rate > max_frame_rate) {
+ DLOG(WARNING) << "Wrong requested frame rate.";
+ return media::VideoCaptureFormats();
+ }
+ }
+
blink::WebVector<blink::WebMediaConstraint> mandatory;
blink::WebVector<blink::WebMediaConstraint> optional;
constraints.getMandatoryConstraints(mandatory);
constraints.getOptionalConstraints(optional);
media::VideoCaptureFormats candidates = supported_formats;
- for (size_t i = 0; i < mandatory.size(); ++i)
+ for (size_t i = 0; i < mandatory.size(); ++i) {
FilterFormatsByConstraint(mandatory[i], true, &candidates);
+ if (candidates.empty()) {
+ *unsatisfied_constraint = mandatory[i].m_name;
+ return candidates;
+ }
+ }
if (candidates.empty())
return candidates;
@@ -342,7 +363,7 @@ MediaStreamVideoSource::MediaStreamVideoSource()
}
MediaStreamVideoSource::~MediaStreamVideoSource() {
- DVLOG(3) << "~MediaStreamVideoSource()";
+ DCHECK(CalledOnValidThread());
}
void MediaStreamVideoSource::AddTrack(
@@ -371,10 +392,17 @@ void MediaStreamVideoSource::AddTrack(
GetMandatoryConstraintValueAsInteger(constraints, kMaxHeight,
&max_requested_height);
+ double max_requested_frame_rate;
+ if (!GetConstraintValueAsDouble(constraints, kMaxFrameRate,
+ &max_requested_frame_rate)) {
+ max_requested_frame_rate = kDefaultFrameRate;
+ }
+
state_ = RETRIEVING_CAPABILITIES;
GetCurrentSupportedFormats(
max_requested_width,
max_requested_height,
+ max_requested_frame_rate,
base::Bind(&MediaStreamVideoSource::OnSupportedFormats,
weak_factory_.GetWeakPtr()));
@@ -430,6 +458,7 @@ void MediaStreamVideoSource::DoStopSource() {
DVLOG(3) << "DoStopSource()";
if (state_ == ENDED)
return;
+ track_adapter_->StopFrameMonitoring();
StopSourceImpl();
state_ = ENDED;
SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
@@ -451,21 +480,17 @@ void MediaStreamVideoSource::OnSupportedFormats(
}
state_ = STARTING;
- DVLOG(3) << "Starting the capturer with"
- << " width = " << current_format_.frame_size.width()
- << " height = " << current_format_.frame_size.height()
- << " frame rate = " << current_format_.frame_rate;
+ DVLOG(3) << "Starting the capturer with " << current_format_.ToString();
- media::VideoCaptureParams params;
- params.requested_format = current_format_;
StartSourceImpl(
- params,
+ current_format_,
base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_));
}
bool MediaStreamVideoSource::FindBestFormatWithConstraints(
const media::VideoCaptureFormats& formats,
media::VideoCaptureFormat* best_format) {
+ DCHECK(CalledOnValidThread());
// Find the first constraints that we can fulfill.
for (std::vector<RequestedConstraints>::iterator request_it =
requested_constraints_.begin();
@@ -480,8 +505,9 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
*best_format = media::VideoCaptureFormat();
return true;
}
+ blink::WebString unsatisfied_constraint;
media::VideoCaptureFormats filtered_formats =
- FilterFormats(requested_constraints, formats);
+ FilterFormats(requested_constraints, formats, &unsatisfied_constraint);
if (filtered_formats.size() > 0) {
// A request with constraints that can be fulfilled.
GetBestCaptureFormat(filtered_formats,
@@ -493,17 +519,21 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
return false;
}
-void MediaStreamVideoSource::OnStartDone(bool success) {
+void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) {
DCHECK(CalledOnValidThread());
- DVLOG(3) << "OnStartDone({success =" << success << "})";
- if (success) {
+ DVLOG(3) << "OnStartDone({result =" << result << "})";
+ if (result == MEDIA_DEVICE_OK) {
DCHECK_EQ(STARTING, state_);
state_ = STARTED;
SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
+
+ track_adapter_->StartFrameMonitoring(
+ current_format_.frame_rate,
+ base::Bind(&MediaStreamVideoSource::SetMutedState,
+ weak_factory_.GetWeakPtr()));
+
} else {
- state_ = ENDED;
- SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
- StopSourceImpl();
+ StopSource();
}
// This object can be deleted after calling FinalizeAddTrack. See comment in
@@ -512,6 +542,7 @@ void MediaStreamVideoSource::OnStartDone(bool success) {
}
void MediaStreamVideoSource::FinalizeAddTrack() {
+ DCHECK(CalledOnValidThread());
media::VideoCaptureFormats formats;
formats.push_back(current_format_);
@@ -519,17 +550,18 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
callbacks.swap(requested_constraints_);
for (std::vector<RequestedConstraints>::iterator it = callbacks.begin();
it != callbacks.end(); ++it) {
- // The track has been added successfully if the source has started and
- // there are either no mandatory constraints and the source doesn't expose
- // its format capabilities, or the constraints and the format match.
- // For example, a remote source doesn't expose its format capabilities.
- bool success =
- state_ == STARTED &&
- ((!current_format_.IsValid() && !HasMandatoryConstraints(
- it->constraints)) ||
- !FilterFormats(it->constraints, formats).empty());
-
- if (success) {
+ MediaStreamRequestResult result = MEDIA_DEVICE_OK;
+ blink::WebString unsatisfied_constraint;
+
+ if (HasMandatoryConstraints(it->constraints) &&
+ FilterFormats(it->constraints, formats,
+ &unsatisfied_constraint).empty())
+ result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
+
+ if (state_ != STARTED && result == MEDIA_DEVICE_OK)
+ result = MEDIA_DEVICE_TRACK_START_FAILURE;
+
+ if (result == MEDIA_DEVICE_OK) {
int max_width;
int max_height;
GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height);
@@ -538,29 +570,46 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
GetDesiredMinAndMaxAspectRatio(it->constraints,
&min_aspect_ratio,
&max_aspect_ratio);
- track_adapter_->AddTrack(it->track,it->frame_callback,
+ double max_frame_rate = 0.0f;
+ GetConstraintValueAsDouble(it->constraints,
+ kMaxFrameRate, &max_frame_rate);
+
+ track_adapter_->AddTrack(it->track, it->frame_callback,
max_width, max_height,
- min_aspect_ratio, max_aspect_ratio);
+ min_aspect_ratio, max_aspect_ratio,
+ max_frame_rate);
}
- DVLOG(3) << "FinalizeAddTrack() success " << success;
+ DVLOG(3) << "FinalizeAddTrack() result " << result;
- if (!it->callback.is_null())
- it->callback.Run(this, success);
+ if (!it->callback.is_null()) {
+ it->callback.Run(this, result, unsatisfied_constraint);
+ }
}
}
void MediaStreamVideoSource::SetReadyState(
blink::WebMediaStreamSource::ReadyState state) {
- if (!owner().isNull()) {
+ DVLOG(3) << "MediaStreamVideoSource::SetReadyState state " << state;
+ DCHECK(CalledOnValidThread());
+ if (!owner().isNull())
owner().setReadyState(state);
- }
for (std::vector<MediaStreamVideoTrack*>::iterator it = tracks_.begin();
it != tracks_.end(); ++it) {
(*it)->OnReadyStateChanged(state);
}
}
+void MediaStreamVideoSource::SetMutedState(bool muted_state) {
+ DVLOG(3) << "MediaStreamVideoSource::SetMutedState state=" << muted_state;
+ DCHECK(CalledOnValidThread());
+ if (!owner().isNull()) {
+ owner().setReadyState(muted_state
+ ? blink::WebMediaStreamSource::ReadyStateMuted
+ : blink::WebMediaStreamSource::ReadyStateLive);
+ }
+}
+
MediaStreamVideoSource::RequestedConstraints::RequestedConstraints(
MediaStreamVideoTrack* track,
const VideoCaptureDeliverFrameCB& frame_callback,
diff --git a/chromium/content/renderer/media/media_stream_video_source.h b/chromium/content/renderer/media/media_stream_video_source.h
index 45d2b03082d..e06dfc1708d 100644
--- a/chromium/content/renderer/media/media_stream_video_source.h
+++ b/chromium/content/renderer/media/media_stream_video_source.h
@@ -35,9 +35,9 @@ class VideoTrackAdapter;
// on a PeerConnection or a source created in NaCl.
// All methods calls will be done from the main render thread.
//
-// When the first track is added to the source by calling AddTrack
-// the MediaStreamVideoSource implementation calls GetCurrentSupportedFormats.
-// the source implementation must call OnSupportedFormats.
+// When the first track is added to the source by calling AddTrack, the
+// MediaStreamVideoSource implementation calls GetCurrentSupportedFormats.
+// The source implementation must call OnSupportedFormats.
// MediaStreamVideoSource then match the constraints provided in AddTrack with
// the formats and call StartSourceImpl. The source implementation must call
// OnStartDone when the underlying source has been started or failed to start.
@@ -81,13 +81,17 @@ class CONTENT_EXPORT MediaStreamVideoSource
static const int kDefaultWidth;
static const int kDefaultHeight;
static const int kDefaultFrameRate;
+ static const int kUnknownFrameRate;
protected:
- virtual void DoStopSource() OVERRIDE;
+ void DoStopSource() override;
// Sets ready state and notifies the ready state to all registered tracks.
virtual void SetReadyState(blink::WebMediaStreamSource::ReadyState state);
+ // Sets muted state and notifies it to all registered tracks.
+ virtual void SetMutedState(bool state);
+
// An implementation must fetch the formats that can currently be used by
// the source and call OnSupportedFormats when done.
// |max_requested_height| and |max_requested_width| is the max height and
@@ -97,18 +101,17 @@ class CONTENT_EXPORT MediaStreamVideoSource
virtual void GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) = 0;
// An implementation must start capture frames using the resolution in
// |params|. When the source has started or the source failed to start
// OnStartDone must be called. An implementation must call
- // invoke |frame_callback| on the IO thread with the captured frames.
- // TODO(perkj): pass a VideoCaptureFormats instead of VideoCaptureParams for
- // subclasses to customize.
+ // |frame_callback| on the IO thread with the captured frames.
virtual void StartSourceImpl(
- const media::VideoCaptureParams& params,
+ const media::VideoCaptureFormat& format,
const VideoCaptureDeliverFrameCB& frame_callback) = 0;
- void OnStartDone(bool success);
+ void OnStartDone(MediaStreamRequestResult result);
// An implementation must immediately stop capture video frames and must not
// call OnSupportedFormats after this method has been called. After this
diff --git a/chromium/content/renderer/media/media_stream_video_source_unittest.cc b/chromium/content/renderer/media/media_stream_video_source_unittest.cc
index d47fae5bdd6..15ba1092823 100644
--- a/chromium/content/renderer/media/media_stream_video_source_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_source_unittest.cc
@@ -18,6 +18,11 @@
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::SaveArg;
namespace content {
@@ -32,6 +37,8 @@ class MediaStreamVideoSourceTest
: child_process_(new ChildProcess()),
number_of_successful_constraints_applied_(0),
number_of_failed_constraints_applied_(0),
+ result_(MEDIA_DEVICE_OK),
+ result_name_(""),
mock_source_(new MockMediaStreamVideoSource(true)) {
media::VideoCaptureFormats formats;
formats.push_back(media::VideoCaptureFormat(
@@ -49,6 +56,11 @@ class MediaStreamVideoSourceTest
webkit_source_.setExtraData(mock_source_);
}
+ void TearDown() override {
+ webkit_source_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
protected:
// Create a track that's associated with |webkit_source_|.
blink::WebMediaStreamTrack CreateTrack(
@@ -71,10 +83,10 @@ class MediaStreamVideoSourceTest
blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
mock_source_->CompleteGetSupportedFormats();
- const media::VideoCaptureParams& format = mock_source()->start_params();
- EXPECT_EQ(expected_width, format.requested_format.frame_size.width());
- EXPECT_EQ(expected_height, format.requested_format.frame_size.height());
- EXPECT_EQ(expected_frame_rate, format.requested_format.frame_rate);
+ const media::VideoCaptureFormat& format = mock_source()->start_format();
+ EXPECT_EQ(expected_width, format.frame_size.width());
+ EXPECT_EQ(expected_height, format.frame_size.height());
+ EXPECT_EQ(expected_frame_rate, format.frame_rate);
EXPECT_EQ(0, NumberOfSuccessConstraintsCallbacks());
mock_source_->StartMockedSource();
@@ -92,6 +104,9 @@ class MediaStreamVideoSourceTest
return number_of_failed_constraints_applied_;
}
+ content::MediaStreamRequestResult error_type() const { return result_; }
+ blink::WebString error_name() const { return result_name_; }
+
MockMediaStreamVideoSource* mock_source() { return mock_source_; }
// Test that the source crops/scales to the requested width and
@@ -189,19 +204,28 @@ class MediaStreamVideoSourceTest
MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
}
+ void SetSourceSupportedFormats(const media::VideoCaptureFormats& formats) {
+ mock_source_->SetSupportedFormats(formats);
+ }
+
void ReleaseTrackAndSourceOnAddTrackCallback(
const blink::WebMediaStreamTrack& track_to_release) {
track_to_release_ = track_to_release;
}
private:
- void OnConstraintsApplied(MediaStreamSource* source, bool success) {
+ void OnConstraintsApplied(MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
ASSERT_EQ(source, webkit_source_.extraData());
- if (success)
+ if (result == MEDIA_DEVICE_OK) {
++number_of_successful_constraints_applied_;
- else
+ } else {
+ result_ = result;
+ result_name_ = result_name;
++number_of_failed_constraints_applied_;
+ }
if (!track_to_release_.isNull()) {
mock_source_ = NULL;
@@ -214,6 +238,8 @@ class MediaStreamVideoSourceTest
blink::WebMediaStreamTrack track_to_release_;
int number_of_successful_constraints_applied_;
int number_of_failed_constraints_applied_;
+ content::MediaStreamRequestResult result_;
+ blink::WebString result_name_;
blink::WebMediaStreamSource webkit_source_;
// |mock_source_| is owned by |webkit_source_|.
MockMediaStreamVideoSource* mock_source_;
@@ -357,6 +383,16 @@ TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
}
+TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) {
+ MockMediaConstraintFactory factory;
+ factory.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 25);
+ factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
+ blink::WebMediaStreamTrack track = CreateTrack(
+ "123", factory.CreateWebMediaConstraints());
+ mock_source()->CompleteGetSupportedFormats();
+ EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
+}
+
// Test that its safe to release the last reference of a blink track and the
// source during the callback if adding a track succeeds.
TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
@@ -394,10 +430,10 @@ TEST_F(MediaStreamVideoSourceTest, OptionalAspectRatioTooHigh) {
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
- const media::VideoCaptureParams& params = mock_source()->start_params();
+ const media::VideoCaptureFormat& format = mock_source()->start_format();
double aspect_ratio =
- static_cast<double>(params.requested_format.frame_size.width()) /
- params.requested_format.frame_size.height();
+ static_cast<double>(format.frame_size.width()) /
+ format.frame_size.height();
EXPECT_LT(aspect_ratio, 2);
}
@@ -426,6 +462,8 @@ TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryConstraint) {
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
+ EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED, error_type());
+ EXPECT_EQ("weird key", error_name());
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
}
@@ -599,6 +637,25 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
640, 360);
}
+TEST_F(MediaStreamVideoSourceTest,
+ TwoTracksWithSecondTrackFrameRateHigherThanFirst) {
+ MockMediaConstraintFactory factory1;
+ factory1.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 15);
+ factory1.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
+
+ blink::WebMediaStreamTrack track1 =
+ CreateTrackAndStartSource(factory1.CreateWebMediaConstraints(),
+ MediaStreamVideoSource::kDefaultWidth,
+ MediaStreamVideoSource::kDefaultHeight,
+ 15);
+
+ MockMediaConstraintFactory factory2;
+ factory2.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 30);
+ blink::WebMediaStreamTrack track2 = CreateTrack(
+ "123", factory2.CreateWebMediaConstraints());
+ EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
+}
+
// Test that a source can change the frame resolution on the fly and that
// tracks sinks get the new frame size unless constraints force the frame to be
// cropped.
@@ -691,4 +748,49 @@ TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
}
+// Test that a source producing no frames change the source readyState to muted.
+// that in a reasonable time frame the muted state turns to false.
+TEST_F(MediaStreamVideoSourceTest, MutedSource) {
+ // Setup the source for support a frame rate of 2000fps in order to test
+ // the muted event faster. This is since the frame monitoring uses
+ // PostDelayedTask that is dependent on the source frame rate.
+ media::VideoCaptureFormats formats;
+ formats.push_back(media::VideoCaptureFormat(
+ gfx::Size(640, 480), 2000, media::PIXEL_FORMAT_I420));
+ SetSourceSupportedFormats(formats);
+
+ MockMediaConstraintFactory factory;
+ blink::WebMediaStreamTrack track =
+ CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
+ 640, 480, 2000);
+ MockMediaStreamVideoSink sink;
+ MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
+ EXPECT_EQ(track.source().readyState(),
+ blink::WebMediaStreamSource::ReadyStateLive);
+
+ base::RunLoop run_loop;
+ base::Closure quit_closure = run_loop.QuitClosure();
+ bool muted_state = false;
+ EXPECT_CALL(*mock_source(), DoSetMutedState(_))
+ .WillOnce(DoAll(SaveArg<0>(&muted_state), RunClosure(quit_closure)));
+ run_loop.Run();
+ EXPECT_EQ(muted_state, true);
+
+ EXPECT_EQ(track.source().readyState(),
+ blink::WebMediaStreamSource::ReadyStateMuted);
+
+ base::RunLoop run_loop2;
+ base::Closure quit_closure2 = run_loop2.QuitClosure();
+ EXPECT_CALL(*mock_source(), DoSetMutedState(_))
+ .WillOnce(DoAll(SaveArg<0>(&muted_state), RunClosure(quit_closure2)));
+ DeliverVideoFrameAndWaitForRenderer(640, 480, &sink);
+ run_loop2.Run();
+
+ EXPECT_EQ(muted_state, false);
+ EXPECT_EQ(track.source().readyState(),
+ blink::WebMediaStreamSource::ReadyStateLive);
+
+ MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_video_track.cc b/chromium/content/renderer/media/media_stream_video_track.cc
index 0ad7159255d..04d8817cca4 100644
--- a/chromium/content/renderer/media/media_stream_video_track.cc
+++ b/chromium/content/renderer/media/media_stream_video_track.cc
@@ -4,86 +4,172 @@
#include "content/renderer/media/media_stream_video_track.h"
+#include <utility>
+
#include "base/bind.h"
-#include "content/renderer/media/video_frame_deliverer.h"
-#include "media/base/bind_to_current_loop.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
namespace content {
-// Helper class used for delivering video frames to MediaStreamSinks on the
-// IO-thread.
-// Frames are delivered to an instance of this class from a
-// MediaStreamVideoSource on the IO-thread to the method DeliverFrameOnIO.
-// Frames are only delivered to the sinks if the track is enabled.
-class MediaStreamVideoTrack::FrameDeliverer : public VideoFrameDeliverer {
+namespace {
+void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
+ // |callback| will be deleted when this exits.
+}
+} // namespace
+
+// MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering
+// VideoCaptureDeliverFrameCB on the main render thread to receive video frames
+// on the IO-thread.
+// Frames are only delivered to the sinks if the track is enabled. If the track
+// is disabled, a black frame is instead forwarded to the sinks at the same
+// frame rate.
+class MediaStreamVideoTrack::FrameDeliverer
+ : public base::RefCountedThreadSafe<FrameDeliverer> {
public:
FrameDeliverer(
- const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy,
- bool enabled)
- : VideoFrameDeliverer(io_message_loop_proxy),
- enabled_(enabled) {
- }
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop,
+ bool enabled);
- // Add |sink| to receive state changes on the main render thread.
- // Video frames will be delivered to |callback| on the IO thread.
- void AddSink(MediaStreamVideoSink* sink,
- const VideoCaptureDeliverFrameCB& callback) {
- DCHECK(thread_checker().CalledOnValidThread());
- DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
- sinks_.push_back(sink);
- AddCallback(sink, callback);
- }
+ void SetEnabled(bool enabled);
- void RemoveSink(MediaStreamVideoSink* sink) {
- DCHECK(thread_checker().CalledOnValidThread());
- std::vector<MediaStreamVideoSink*>::iterator it =
- std::find(sinks_.begin(), sinks_.end(), sink);
- DCHECK(it != sinks_.end());
- sinks_.erase(it);
- RemoveCallback(sink);
- }
+ // Add |callback| to receive video frames on the IO-thread.
+ // Must be called on the main render thread.
+ void AddCallback(void* id, const VideoCaptureDeliverFrameCB& callback);
- void SetEnabled(bool enabled) {
- DCHECK(thread_checker().CalledOnValidThread());
- io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO,
- this, enabled));
- }
+ // Removes |callback| associated with |id| from receiving video frames if |id|
+ // has been added. It is ok to call RemoveCallback even if the |id| has not
+ // been added. Note that the added callback will be reset on the main thread.
+ // Must be called on the main render thread.
+ void RemoveCallback(void* id);
- virtual void DeliverFrameOnIO(
- const scoped_refptr<media::VideoFrame>& frame,
- const media::VideoCaptureFormat& format,
- const base::TimeTicks& estimated_capture_time) OVERRIDE {
- DCHECK(io_message_loop()->BelongsToCurrentThread());
- if (!enabled_)
- return;
- VideoFrameDeliverer::DeliverFrameOnIO(frame, format,
- estimated_capture_time);
- }
+ // Triggers all registered callbacks with |frame|, |format| and
+ // |estimated_capture_time| as parameters. Must be called on the IO-thread.
+ void DeliverFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format,
+ const base::TimeTicks& estimated_capture_time);
- const std::vector<MediaStreamVideoSink*>& sinks() const { return sinks_; }
-
- protected:
- virtual ~FrameDeliverer() {
- DCHECK(sinks_.empty());
- }
+ private:
+ friend class base::RefCountedThreadSafe<FrameDeliverer>;
+ virtual ~FrameDeliverer();
+ void AddCallbackOnIO(void* id, const VideoCaptureDeliverFrameCB& callback);
+ void RemoveCallbackOnIO(
+ void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop);
- void SetEnabledOnIO(bool enabled) {
- DCHECK(io_message_loop()->BelongsToCurrentThread());
- enabled_ = enabled;
- }
+ void SetEnabledOnIO(bool enabled);
+ // Returns |black_frame_| where the size and time stamp is set to the same as
+ // as in |reference_frame|.
+ const scoped_refptr<media::VideoFrame>& GetBlackFrame(
+ const scoped_refptr<media::VideoFrame>& reference_frame);
- private:
- // The below members are used on the main render thread.
- std::vector<MediaStreamVideoSink*> sinks_;
+ // Used to DCHECK that AddCallback and RemoveCallback are called on the main
+ // render thread.
+ base::ThreadChecker thread_checker_;
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_;
- // The below parameters are used on the IO-thread.
bool enabled_;
+ scoped_refptr<media::VideoFrame> black_frame_;
+
+ typedef std::pair<void*, VideoCaptureDeliverFrameCB> VideoIdCallbackPair;
+ std::vector<VideoIdCallbackPair> callbacks_;
DISALLOW_COPY_AND_ASSIGN(FrameDeliverer);
};
+MediaStreamVideoTrack::FrameDeliverer::FrameDeliverer(
+ const scoped_refptr<base::MessageLoopProxy>& io_message_loop, bool enabled)
+ : io_message_loop_(io_message_loop),
+ enabled_(enabled) {
+ DCHECK(io_message_loop_.get());
+}
+
+MediaStreamVideoTrack::FrameDeliverer::~FrameDeliverer() {
+ DCHECK(callbacks_.empty());
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::AddCallback(
+ void* id,
+ const VideoCaptureDeliverFrameCB& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&FrameDeliverer::AddCallbackOnIO,
+ this, id, callback));
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::AddCallbackOnIO(
+ void* id,
+ const VideoCaptureDeliverFrameCB& callback) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ callbacks_.push_back(std::make_pair(id, callback));
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::RemoveCallback(void* id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&FrameDeliverer::RemoveCallbackOnIO,
+ this, id, base::MessageLoopProxy::current()));
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::RemoveCallbackOnIO(
+ void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
+ for (; it != callbacks_.end(); ++it) {
+ if (it->first == id) {
+ // Callback is copied to heap and then deleted on the target thread.
+ scoped_ptr<VideoCaptureDeliverFrameCB> callback;
+ callback.reset(new VideoCaptureDeliverFrameCB(it->second));
+ callbacks_.erase(it);
+ message_loop->PostTask(
+ FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback)));
+ return;
+ }
+ }
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::SetEnabled(bool enabled) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&FrameDeliverer::SetEnabledOnIO,
+ this, enabled));
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::SetEnabledOnIO(bool enabled) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ enabled_ = enabled;
+ if (enabled_)
+ black_frame_ = NULL;
+}
+
+void MediaStreamVideoTrack::FrameDeliverer::DeliverFrameOnIO(
+ const scoped_refptr<media::VideoFrame>& frame,
+ const media::VideoCaptureFormat& format,
+ const base::TimeTicks& estimated_capture_time) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ const scoped_refptr<media::VideoFrame>& video_frame =
+ enabled_ ? frame : GetBlackFrame(frame);
+
+ for (std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
+ it != callbacks_.end(); ++it) {
+ it->second.Run(video_frame, format, estimated_capture_time);
+ }
+}
+
+const scoped_refptr<media::VideoFrame>&
+MediaStreamVideoTrack::FrameDeliverer::GetBlackFrame(
+ const scoped_refptr<media::VideoFrame>& reference_frame) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ if (!black_frame_.get() ||
+ black_frame_->natural_size() != reference_frame->natural_size())
+ black_frame_ =
+ media::VideoFrame::CreateBlackFrame(reference_frame->natural_size());
+
+ black_frame_->set_timestamp(reference_frame->timestamp());
+ return black_frame_;
+}
+
// static
blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
MediaStreamVideoSource* source,
@@ -110,7 +196,7 @@ MediaStreamVideoTrack::MediaStreamVideoTrack(
const blink::WebMediaConstraints& constraints,
const MediaStreamVideoSource::ConstraintsCallback& callback,
bool enabled)
- : MediaStreamTrack(NULL, true),
+ : MediaStreamTrack(true),
frame_deliverer_(
new MediaStreamVideoTrack::FrameDeliverer(source->io_message_loop(),
enabled)),
@@ -126,6 +212,7 @@ MediaStreamVideoTrack::MediaStreamVideoTrack(
MediaStreamVideoTrack::~MediaStreamVideoTrack() {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(sinks_.empty());
Stop();
DVLOG(3) << "~MediaStreamVideoTrack()";
}
@@ -133,22 +220,25 @@ MediaStreamVideoTrack::~MediaStreamVideoTrack() {
void MediaStreamVideoTrack::AddSink(
MediaStreamVideoSink* sink, const VideoCaptureDeliverFrameCB& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
- frame_deliverer_->AddSink(sink, callback);
+ DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
+ sinks_.push_back(sink);
+ frame_deliverer_->AddCallback(sink, callback);
}
void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
DCHECK(thread_checker_.CalledOnValidThread());
- frame_deliverer_->RemoveSink(sink);
+ std::vector<MediaStreamVideoSink*>::iterator it =
+ std::find(sinks_.begin(), sinks_.end(), sink);
+ DCHECK(it != sinks_.end());
+ sinks_.erase(it);
+ frame_deliverer_->RemoveCallback(sink);
}
void MediaStreamVideoTrack::SetEnabled(bool enabled) {
DCHECK(thread_checker_.CalledOnValidThread());
- MediaStreamTrack::SetEnabled(enabled);
-
frame_deliverer_->SetEnabled(enabled);
- const std::vector<MediaStreamVideoSink*>& sinks = frame_deliverer_->sinks();
- for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks.begin();
- it != sinks.end(); ++it) {
+ for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks_.begin();
+ it != sinks_.end(); ++it) {
(*it)->OnEnabledChanged(enabled);
}
}
@@ -165,9 +255,8 @@ void MediaStreamVideoTrack::Stop() {
void MediaStreamVideoTrack::OnReadyStateChanged(
blink::WebMediaStreamSource::ReadyState state) {
DCHECK(thread_checker_.CalledOnValidThread());
- const std::vector<MediaStreamVideoSink*>& sinks = frame_deliverer_->sinks();
- for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks.begin();
- it != sinks.end(); ++it) {
+ for (std::vector<MediaStreamVideoSink*>::const_iterator it = sinks_.begin();
+ it != sinks_.end(); ++it) {
(*it)->OnReadyStateChanged(state);
}
}
diff --git a/chromium/content/renderer/media/media_stream_video_track.h b/chromium/content/renderer/media/media_stream_video_track.h
index 040686c5828..c3b5ed9de73 100644
--- a/chromium/content/renderer/media/media_stream_video_track.h
+++ b/chromium/content/renderer/media/media_stream_video_track.h
@@ -41,16 +41,17 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
static MediaStreamVideoTrack* GetVideoTrack(
const blink::WebMediaStreamTrack& track);
- // Constructor for local video tracks.
- MediaStreamVideoTrack(
- MediaStreamVideoSource* source,
- const blink::WebMediaConstraints& constraints,
- const MediaStreamVideoSource::ConstraintsCallback& callback,
- bool enabled);
+ // Constructor for video tracks.
+ MediaStreamVideoTrack(
+ MediaStreamVideoSource* source,
+ const blink::WebMediaConstraints& constraints,
+ const MediaStreamVideoSource::ConstraintsCallback& callback,
+ bool enabled);
virtual ~MediaStreamVideoTrack();
- virtual void SetEnabled(bool enabled) OVERRIDE;
- virtual void Stop() OVERRIDE;
+ void SetEnabled(bool enabled) override;
+
+ void Stop() override;
void OnReadyStateChanged(blink::WebMediaStreamSource::ReadyState state);
@@ -80,6 +81,8 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
const VideoCaptureDeliverFrameCB& callback);
void RemoveSink(MediaStreamVideoSink* sink);
+ std::vector<MediaStreamVideoSink*> sinks_;
+
// |FrameDeliverer| is an internal helper object used for delivering video
// frames on the IO-thread using callbacks to all registered tracks.
class FrameDeliverer;
diff --git a/chromium/content/renderer/media/media_stream_video_track_unittest.cc b/chromium/content/renderer/media/media_stream_video_track_unittest.cc
index 9b281a67d15..4c319ac910d 100644
--- a/chromium/content/renderer/media/media_stream_video_track_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_track_unittest.cc
@@ -15,9 +15,13 @@
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
namespace content {
+const uint8 kBlackValue = 0x00;
+const uint8 kColorValue = 0xAB;
+
ACTION_P(RunClosure, closure) {
closure.Run();
}
@@ -34,7 +38,11 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
blink_source_.setExtraData(mock_source_);
}
- virtual ~MediaStreamVideoTrackTest() {
+ ~MediaStreamVideoTrackTest() override {}
+
+ void TearDown() override {
+ blink_source_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
}
void DeliverVideoFrameAndWaitForRenderer(MockMediaStreamVideoSink* sink) {
@@ -43,9 +51,10 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
EXPECT_CALL(*sink, OnVideoFrame()).WillOnce(
RunClosure(quit_closure));
scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::CreateBlackFrame(
+ media::VideoFrame::CreateColorFrame(
gfx::Size(MediaStreamVideoSource::kDefaultWidth,
- MediaStreamVideoSource::kDefaultHeight));
+ MediaStreamVideoSource::kDefaultHeight),
+ kColorValue, kColorValue, kColorValue, base::TimeDelta());
mock_source()->DeliverVideoFrame(frame);
run_loop.Run();
}
@@ -163,24 +172,20 @@ TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
DeliverVideoFrameAndWaitForRenderer(&sink);
EXPECT_EQ(1, sink.number_of_frames());
+ EXPECT_EQ(kColorValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
video_track->SetEnabled(false);
EXPECT_FALSE(sink.enabled());
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::CreateBlackFrame(
- gfx::Size(MediaStreamVideoSource::kDefaultWidth,
- MediaStreamVideoSource::kDefaultHeight));
- mock_source()->DeliverVideoFrame(frame);
- // Wait for the IO thread to complete delivering frames.
- io_message_loop()->RunUntilIdle();
- EXPECT_EQ(1, sink.number_of_frames());
+ DeliverVideoFrameAndWaitForRenderer(&sink);
+ EXPECT_EQ(2, sink.number_of_frames());
+ EXPECT_EQ(kBlackValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
video_track->SetEnabled(true);
EXPECT_TRUE(sink.enabled());
- mock_source()->DeliverVideoFrame(frame);
DeliverVideoFrameAndWaitForRenderer(&sink);
- EXPECT_EQ(2, sink.number_of_frames());
+ EXPECT_EQ(3, sink.number_of_frames());
+ EXPECT_EQ(kColorValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
}
diff --git a/chromium/content/renderer/media/midi_dispatcher.cc b/chromium/content/renderer/media/midi_dispatcher.cc
index cbbd876332b..b281389ee54 100644
--- a/chromium/content/renderer/media/midi_dispatcher.cc
+++ b/chromium/content/renderer/media/midi_dispatcher.cc
@@ -46,13 +46,10 @@ void MidiDispatcher::cancelSysexPermissionRequest(
const WebMIDIPermissionRequest& request) {
for (Requests::iterator it(&requests_); !it.IsAtEnd(); it.Advance()) {
WebMIDIPermissionRequest* value = it.GetCurrentValue();
- if (value->equals(request)) {
- base::string16 origin = request.securityOrigin().toString();
- Send(new MidiHostMsg_CancelSysExPermissionRequest(
- routing_id(), it.GetCurrentKey(), GURL(origin)));
- requests_.Remove(it.GetCurrentKey());
- break;
- }
+ if (!value->equals(request))
+ continue;
+ requests_.Remove(it.GetCurrentKey());
+ break;
}
}
diff --git a/chromium/content/renderer/media/midi_dispatcher.h b/chromium/content/renderer/media/midi_dispatcher.h
index 0d40f46d26e..cfa77ee9b7b 100644
--- a/chromium/content/renderer/media/midi_dispatcher.h
+++ b/chromium/content/renderer/media/midi_dispatcher.h
@@ -28,7 +28,7 @@ class MidiDispatcher : public RenderFrameObserver,
private:
// RenderFrameObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// blink::WebMIDIClient implementation.
virtual void requestSysexPermission(
diff --git a/chromium/content/renderer/media/midi_message_filter.cc b/chromium/content/renderer/media/midi_message_filter.cc
index e6a7f8067be..982281f72d6 100644
--- a/chromium/content/renderer/media/midi_message_filter.cc
+++ b/chromium/content/renderer/media/midi_message_filter.cc
@@ -4,6 +4,8 @@
#include "content/renderer/media/midi_message_filter.h"
+#include <algorithm>
+
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
@@ -22,17 +24,82 @@ static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024; // 10 MB.
namespace content {
+// TODO(crbug.com/425389): Rewrite this class as a RenderFrameObserver.
MidiMessageFilter::MidiMessageFilter(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
- : sender_(NULL),
+ : sender_(nullptr),
io_message_loop_(io_message_loop),
main_message_loop_(base::MessageLoopProxy::current()),
- next_available_id_(0),
- unacknowledged_bytes_sent_(0) {
+ session_result_(media::MIDI_NOT_INITIALIZED),
+ unacknowledged_bytes_sent_(0u) {
}
MidiMessageFilter::~MidiMessageFilter() {}
+void MidiMessageFilter::AddClient(blink::WebMIDIAccessorClient* client) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ TRACE_EVENT0("midi", "MidiMessageFilter::AddClient");
+ clients_waiting_session_queue_.push_back(client);
+ if (session_result_ != media::MIDI_NOT_INITIALIZED) {
+ HandleClientAdded(session_result_);
+ } else if (clients_waiting_session_queue_.size() == 1u) {
+ io_message_loop_->PostTask(FROM_HERE,
+ base::Bind(&MidiMessageFilter::StartSessionOnIOThread, this));
+ }
+}
+
+void MidiMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ clients_.erase(client);
+ ClientsQueue::iterator it = std::find(clients_waiting_session_queue_.begin(),
+ clients_waiting_session_queue_.end(),
+ client);
+ if (it != clients_waiting_session_queue_.end())
+ clients_waiting_session_queue_.erase(it);
+ if (clients_.empty() && clients_waiting_session_queue_.empty()) {
+ session_result_ = media::MIDI_NOT_INITIALIZED;
+ inputs_.clear();
+ outputs_.clear();
+ io_message_loop_->PostTask(FROM_HERE,
+ base::Bind(&MidiMessageFilter::EndSessionOnIOThread, this));
+ }
+}
+
+void MidiMessageFilter::SendMidiData(uint32 port,
+ const uint8* data,
+ size_t length,
+ double timestamp) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ if ((kMaxUnacknowledgedBytesSent - unacknowledged_bytes_sent_) < length) {
+ // TODO(toyoshim): buffer up the data to send at a later time.
+ // For now we're just dropping these bytes on the floor.
+ return;
+ }
+
+ unacknowledged_bytes_sent_ += length;
+ std::vector<uint8> v(data, data + length);
+ io_message_loop_->PostTask(FROM_HERE, base::Bind(
+ &MidiMessageFilter::SendMidiDataOnIOThread, this, port, v, timestamp));
+}
+
+void MidiMessageFilter::StartSessionOnIOThread() {
+ TRACE_EVENT0("midi", "MidiMessageFilter::StartSessionOnIOThread");
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ Send(new MidiHostMsg_StartSession());
+}
+
+void MidiMessageFilter::SendMidiDataOnIOThread(uint32 port,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ Send(new MidiHostMsg_SendData(port, data, timestamp));
+}
+
+void MidiMessageFilter::EndSessionOnIOThread() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ Send(new MidiHostMsg_EndSession());
+}
+
void MidiMessageFilter::Send(IPC::Message* message) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
if (!sender_) {
@@ -47,6 +114,8 @@ bool MidiMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MidiMessageFilter, message)
IPC_MESSAGE_HANDLER(MidiMsg_SessionStarted, OnSessionStarted)
+ IPC_MESSAGE_HANDLER(MidiMsg_AddInputPort, OnAddInputPort)
+ IPC_MESSAGE_HANDLER(MidiMsg_AddOutputPort, OnAddOutputPort)
IPC_MESSAGE_HANDLER(MidiMsg_DataReceived, OnDataReceived)
IPC_MESSAGE_HANDLER(MidiMsg_AcknowledgeSentData, OnAcknowledgeSentData)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -61,7 +130,6 @@ void MidiMessageFilter::OnFilterAdded(IPC::Sender* sender) {
void MidiMessageFilter::OnFilterRemoved() {
DCHECK(io_message_loop_->BelongsToCurrentThread());
-
// Once removed, a filter will not be used again. At this time all
// delegates must be notified so they release their reference.
OnChannelClosing();
@@ -69,74 +137,56 @@ void MidiMessageFilter::OnFilterRemoved() {
void MidiMessageFilter::OnChannelClosing() {
DCHECK(io_message_loop_->BelongsToCurrentThread());
- sender_ = NULL;
+ sender_ = nullptr;
}
-void MidiMessageFilter::StartSession(blink::WebMIDIAccessorClient* client) {
- // Generate and keep track of a "client id" which is sent to the browser
- // to ask permission to talk to MIDI hardware.
- // This id is handed back when we receive the answer in OnAccessApproved().
- if (clients_.find(client) == clients_.end()) {
- int client_id = next_available_id_++;
- clients_[client] = client_id;
-
- io_message_loop_->PostTask(FROM_HERE,
- base::Bind(&MidiMessageFilter::StartSessionOnIOThread, this,
- client_id));
- }
+void MidiMessageFilter::OnSessionStarted(media::MidiResult result) {
+ TRACE_EVENT0("midi", "MidiMessageFilter::OnSessionStarted");
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ // Handle on the main JS thread.
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiMessageFilter::HandleClientAdded, this, result));
}
-void MidiMessageFilter::StartSessionOnIOThread(int client_id) {
- Send(new MidiHostMsg_StartSession(client_id));
+void MidiMessageFilter::OnAddInputPort(media::MidiPortInfo info) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiMessageFilter::HandleAddInputPort, this, info));
}
-void MidiMessageFilter::RemoveClient(blink::WebMIDIAccessorClient* client) {
- ClientsMap::iterator i = clients_.find(client);
- if (i != clients_.end())
- clients_.erase(i);
+void MidiMessageFilter::OnAddOutputPort(media::MidiPortInfo info) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiMessageFilter::HandleAddOutputPort, this, info));
}
-// Received from browser.
-
-void MidiMessageFilter::OnSessionStarted(
- int client_id,
- media::MidiResult result,
- MidiPortInfoList inputs,
- MidiPortInfoList outputs) {
+void MidiMessageFilter::OnDataReceived(uint32 port,
+ const std::vector<uint8>& data,
+ double timestamp) {
+ TRACE_EVENT0("midi", "MidiMessageFilter::OnDataReceived");
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
// Handle on the main JS thread.
main_message_loop_->PostTask(
FROM_HERE,
- base::Bind(&MidiMessageFilter::HandleSessionStarted, this,
- client_id, result, inputs, outputs));
+ base::Bind(&MidiMessageFilter::HandleDataReceived, this, port, data,
+ timestamp));
}
-void MidiMessageFilter::HandleSessionStarted(
- int client_id,
- media::MidiResult result,
- MidiPortInfoList inputs,
- MidiPortInfoList outputs) {
- blink::WebMIDIAccessorClient* client = GetClientFromId(client_id);
- if (!client)
- return;
-
- if (result == media::MIDI_OK) {
- // Add the client's input and output ports.
- for (size_t i = 0; i < inputs.size(); ++i) {
- client->didAddInputPort(
- base::UTF8ToUTF16(inputs[i].id),
- base::UTF8ToUTF16(inputs[i].manufacturer),
- base::UTF8ToUTF16(inputs[i].name),
- base::UTF8ToUTF16(inputs[i].version));
- }
+void MidiMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ main_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&MidiMessageFilter::HandleAckknowledgeSentData, this,
+ bytes_sent));
+}
- for (size_t i = 0; i < outputs.size(); ++i) {
- client->didAddOutputPort(
- base::UTF8ToUTF16(outputs[i].id),
- base::UTF8ToUTF16(outputs[i].manufacturer),
- base::UTF8ToUTF16(outputs[i].name),
- base::UTF8ToUTF16(outputs[i].version));
- }
- }
+void MidiMessageFilter::HandleClientAdded(media::MidiResult result) {
+ TRACE_EVENT0("midi", "MidiMessageFilter::HandleClientAdded");
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ session_result_ = result;
std::string error;
std::string message;
switch (result) {
@@ -155,82 +205,64 @@ void MidiMessageFilter::HandleSessionStarted(
message = "Unknown internal error occurred.";
break;
}
- client->didStartSession(result == media::MIDI_OK, base::UTF8ToUTF16(error),
- base::UTF8ToUTF16(message));
-}
-
-blink::WebMIDIAccessorClient*
-MidiMessageFilter::GetClientFromId(int client_id) {
- // Iterating like this seems inefficient, but in practice there generally
- // will be very few clients (usually one). Additionally, this lookup
- // usually happens one time during page load. So the performance hit is
- // negligible.
- for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i) {
- if ((*i).second == client_id)
- return (*i).first;
+ base::string16 error16 = base::UTF8ToUTF16(error);
+ base::string16 message16 = base::UTF8ToUTF16(message);
+ for (blink::WebMIDIAccessorClient* client : clients_waiting_session_queue_) {
+ if (result == media::MIDI_OK) {
+ // Add the client's input and output ports.
+ const bool active = true;
+ for (const auto& info : inputs_) {
+ client->didAddInputPort(
+ base::UTF8ToUTF16(info.id),
+ base::UTF8ToUTF16(info.manufacturer),
+ base::UTF8ToUTF16(info.name),
+ base::UTF8ToUTF16(info.version),
+ active);
+ }
+
+ for (const auto& info : outputs_) {
+ client->didAddOutputPort(
+ base::UTF8ToUTF16(info.id),
+ base::UTF8ToUTF16(info.manufacturer),
+ base::UTF8ToUTF16(info.name),
+ base::UTF8ToUTF16(info.version),
+ active);
+ }
+ }
+ client->didStartSession(result == media::MIDI_OK, error16, message16);
+ clients_.insert(client);
}
- return NULL;
+ clients_waiting_session_queue_.clear();
}
-void MidiMessageFilter::OnDataReceived(uint32 port,
- const std::vector<uint8>& data,
- double timestamp) {
- TRACE_EVENT0("midi", "MidiMessageFilter::OnDataReceived");
-
- main_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&MidiMessageFilter::HandleDataReceived, this,
- port, data, timestamp));
+void MidiMessageFilter::HandleAddInputPort(media::MidiPortInfo info) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ inputs_.push_back(info);
+ // TODO(toyoshim): Notify to clients that were already added.
}
-void MidiMessageFilter::OnAcknowledgeSentData(size_t bytes_sent) {
- DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
- if (unacknowledged_bytes_sent_ >= bytes_sent)
- unacknowledged_bytes_sent_ -= bytes_sent;
+void MidiMessageFilter::HandleAddOutputPort(media::MidiPortInfo info) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ outputs_.push_back(info);
+ // TODO(toyoshim): Notify to clients that were already added.
}
void MidiMessageFilter::HandleDataReceived(uint32 port,
const std::vector<uint8>& data,
double timestamp) {
- DCHECK(!data.empty());
TRACE_EVENT0("midi", "MidiMessageFilter::HandleDataReceived");
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ DCHECK(!data.empty());
- for (ClientsMap::iterator i = clients_.begin(); i != clients_.end(); ++i)
- (*i).first->didReceiveMIDIData(port, &data[0], data.size(), timestamp);
-}
-
-void MidiMessageFilter::SendMidiData(uint32 port,
- const uint8* data,
- size_t length,
- double timestamp) {
- if (length > kMaxUnacknowledgedBytesSent) {
- // TODO(toyoshim): buffer up the data to send at a later time.
- // For now we're just dropping these bytes on the floor.
- return;
- }
-
- std::vector<uint8> v(data, data + length);
- io_message_loop_->PostTask(FROM_HERE,
- base::Bind(&MidiMessageFilter::SendMidiDataOnIOThread, this,
- port, v, timestamp));
+ for (blink::WebMIDIAccessorClient* client : clients_)
+ client->didReceiveMIDIData(port, &data[0], data.size(), timestamp);
}
-void MidiMessageFilter::SendMidiDataOnIOThread(uint32 port,
- const std::vector<uint8>& data,
- double timestamp) {
- size_t n = data.size();
- if (n > kMaxUnacknowledgedBytesSent ||
- unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent ||
- n + unacknowledged_bytes_sent_ > kMaxUnacknowledgedBytesSent) {
- // TODO(toyoshim): buffer up the data to send at a later time.
- // For now we're just dropping these bytes on the floor.
- return;
- }
-
- unacknowledged_bytes_sent_ += n;
-
- // Send to the browser.
- Send(new MidiHostMsg_SendData(port, data, timestamp));
+void MidiMessageFilter::HandleAckknowledgeSentData(size_t bytes_sent) {
+ DCHECK(main_message_loop_->BelongsToCurrentThread());
+ DCHECK_GE(unacknowledged_bytes_sent_, bytes_sent);
+ if (unacknowledged_bytes_sent_ >= bytes_sent)
+ unacknowledged_bytes_sent_ -= bytes_sent;
}
} // namespace content
diff --git a/chromium/content/renderer/media/midi_message_filter.h b/chromium/content/renderer/media/midi_message_filter.h
index e8de64d7fbd..f7e1a8474a4 100644
--- a/chromium/content/renderer/media/midi_message_filter.h
+++ b/chromium/content/renderer/media/midi_message_filter.h
@@ -5,7 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
#define CONTENT_RENDERER_MEDIA_MIDI_MESSAGE_FILTER_H_
-#include <map>
+#include <set>
#include <vector>
#include "base/memory/scoped_ptr.h"
@@ -29,9 +29,7 @@ class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter {
// Each client registers for MIDI access here.
// If permission is granted, then the client's
- // addInputPort() and addOutputPort() methods will be called,
- // giving the client access to receive and send data.
- void StartSession(blink::WebMIDIAccessorClient* client);
+ void AddClient(blink::WebMIDIAccessorClient* client);
void RemoveClient(blink::WebMIDIAccessorClient* client);
// A client will only be able to call this method if it has a suitable
@@ -47,24 +45,37 @@ class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter {
}
protected:
- virtual ~MidiMessageFilter();
+ ~MidiMessageFilter() override;
private:
+ void StartSessionOnIOThread();
+
+ void SendMidiDataOnIOThread(uint32 port,
+ const std::vector<uint8>& data,
+ double timestamp);
+
+ void EndSessionOnIOThread();
+
// Sends an IPC message using |sender_|.
void Send(IPC::Message* message);
// IPC::MessageFilter override. Called on |io_message_loop|.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
// Called when the browser process has approved (or denied) access to
// MIDI hardware.
- void OnSessionStarted(int client_id,
- media::MidiResult result,
- media::MidiPortInfoList inputs,
- media::MidiPortInfoList outputs);
+ void OnSessionStarted(media::MidiResult result);
+
+ // These functions are called in 2 cases:
+ // (1) Just before calling |OnSessionStarted|, to notify the recipient about
+ // existing ports.
+ // (2) To notify the recipient that a new device was connected and that new
+ // ports have been created.
+ void OnAddInputPort(media::MidiPortInfo info);
+ void OnAddOutputPort(media::MidiPortInfo info);
// Called when the browser process has sent MIDI data containing one or
// more messages.
@@ -77,22 +88,17 @@ class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter {
// sending too much data before knowing how much has already been sent.
void OnAcknowledgeSentData(size_t bytes_sent);
- void HandleSessionStarted(int client_id,
- media::MidiResult result,
- media::MidiPortInfoList inputs,
- media::MidiPortInfoList outputs);
+ // Following methods, Handle*, run on |main_message_loop_|.
+ void HandleClientAdded(media::MidiResult result);
+
+ void HandleAddInputPort(media::MidiPortInfo info);
+ void HandleAddOutputPort(media::MidiPortInfo info);
void HandleDataReceived(uint32 port,
const std::vector<uint8>& data,
double timestamp);
- void StartSessionOnIOThread(int client_id);
-
- void SendMidiDataOnIOThread(uint32 port,
- const std::vector<uint8>& data,
- double timestamp);
-
- blink::WebMIDIAccessorClient* GetClientFromId(int client_id);
+ void HandleAckknowledgeSentData(size_t bytes_sent);
// IPC sender for Send(); must only be accessed on |io_message_loop_|.
IPC::Sender* sender_;
@@ -103,15 +109,24 @@ class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter {
// Main thread's message loop.
scoped_refptr<base::MessageLoopProxy> main_message_loop_;
+ /*
+ * Notice: Following members are designed to be accessed only on
+ * |main_message_loop_|.
+ */
// Keeps track of all MIDI clients.
- // We map client to "client id" used to track permission.
- // When access has been approved, we add the input and output ports to
- // the client, allowing it to actually receive and send MIDI data.
- typedef std::map<blink::WebMIDIAccessorClient*, int> ClientsMap;
- ClientsMap clients_;
-
- // Dishes out client ids.
- int next_available_id_;
+ typedef std::set<blink::WebMIDIAccessorClient*> ClientsSet;
+ ClientsSet clients_;
+
+ // Represents clients that are waiting for a session being open.
+ typedef std::vector<blink::WebMIDIAccessorClient*> ClientsQueue;
+ ClientsQueue clients_waiting_session_queue_;
+
+ // Represents a result on starting a session. Can be accessed only on
+ media::MidiResult session_result_;
+
+ // Holds MidiPortInfoList for input ports and output ports.
+ media::MidiPortInfoList inputs_;
+ media::MidiPortInfoList outputs_;
size_t unacknowledged_bytes_sent_;
diff --git a/chromium/content/renderer/media/mock_media_stream_dispatcher.cc b/chromium/content/renderer/media/mock_media_stream_dispatcher.cc
index 32ac1de61d3..4c5becfd8d4 100644
--- a/chromium/content/renderer/media/mock_media_stream_dispatcher.cc
+++ b/chromium/content/renderer/media/mock_media_stream_dispatcher.cc
@@ -44,7 +44,7 @@ void MockMediaStreamDispatcher::GenerateStream(
AddAudioInputDeviceToArray(false);
}
if (components.video_requested) {
- AddVideoDeviceToArray();
+ AddVideoDeviceToArray(true);
}
++request_stream_counter_;
}
@@ -59,8 +59,7 @@ void MockMediaStreamDispatcher::EnumerateDevices(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
MediaStreamType type,
- const GURL& security_origin,
- bool hide_labels_if_no_access) {
+ const GURL& security_origin) {
if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
audio_input_request_id_ = request_id;
audio_input_array_.clear();
@@ -73,7 +72,8 @@ void MockMediaStreamDispatcher::EnumerateDevices(
} else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
video_request_id_ = request_id;
video_array_.clear();
- AddVideoDeviceToArray();
+ AddVideoDeviceToArray(true);
+ AddVideoDeviceToArray(false);
}
}
@@ -110,6 +110,7 @@ void MockMediaStreamDispatcher::AddAudioInputDeviceToArray(
audio.device.id = "audio_input_device_id" + base::IntToString(session_id_);
audio.device.name = "microphone";
audio.device.type = MEDIA_DEVICE_AUDIO_CAPTURE;
+ audio.device.video_facing = MEDIA_VIDEO_FACING_NONE;
if (matched_output) {
audio.device.matched_output_device_id =
kAudioOutputDeviceIdPrefix + base::IntToString(session_id_);
@@ -123,15 +124,18 @@ void MockMediaStreamDispatcher::AddAudioOutputDeviceToArray() {
audio.device.id = kAudioOutputDeviceIdPrefix + base::IntToString(session_id_);
audio.device.name = "speaker";
audio.device.type = MEDIA_DEVICE_AUDIO_OUTPUT;
+ audio.device.video_facing = MEDIA_VIDEO_FACING_NONE;
audio.session_id = session_id_;
audio_output_array_.push_back(audio);
}
-void MockMediaStreamDispatcher::AddVideoDeviceToArray() {
+void MockMediaStreamDispatcher::AddVideoDeviceToArray(bool facing_user) {
StreamDeviceInfo video;
video.device.id = "video_device_id" + base::IntToString(session_id_);
video.device.name = "usb video camera";
video.device.type = MEDIA_DEVICE_VIDEO_CAPTURE;
+ video.device.video_facing = facing_user ? MEDIA_VIDEO_FACING_USER
+ : MEDIA_VIDEO_FACING_ENVIRONMENT;
video.session_id = session_id_;
video_array_.push_back(video);
}
diff --git a/chromium/content/renderer/media/mock_media_stream_dispatcher.h b/chromium/content/renderer/media/mock_media_stream_dispatcher.h
index eed1f572051..d77327a04a6 100644
--- a/chromium/content/renderer/media/mock_media_stream_dispatcher.h
+++ b/chromium/content/renderer/media/mock_media_stream_dispatcher.h
@@ -16,27 +16,26 @@ namespace content {
class MockMediaStreamDispatcher : public MediaStreamDispatcher {
public:
MockMediaStreamDispatcher();
- virtual ~MockMediaStreamDispatcher();
+ ~MockMediaStreamDispatcher() override;
- virtual void GenerateStream(
+ void GenerateStream(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
const StreamOptions& components,
- const GURL& url) OVERRIDE;
- virtual void CancelGenerateStream(
+ const GURL& url) override;
+ void CancelGenerateStream(
int request_id,
- const base::WeakPtr<MediaStreamDispatcherEventHandler>&
- event_handler) OVERRIDE;
- virtual void EnumerateDevices(
+ const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler)
+ override;
+ void EnumerateDevices(
int request_id,
const base::WeakPtr<MediaStreamDispatcherEventHandler>& event_handler,
MediaStreamType type,
- const GURL& security_origin,
- bool hide_labels_if_no_access) OVERRIDE;
- virtual void StopStreamDevice(const StreamDeviceInfo& device_info) OVERRIDE;
- virtual bool IsStream(const std::string& label) OVERRIDE;
- virtual int video_session_id(const std::string& label, int index) OVERRIDE;
- virtual int audio_session_id(const std::string& label, int index) OVERRIDE;
+ const GURL& security_origin) override;
+ void StopStreamDevice(const StreamDeviceInfo& device_info) override;
+ bool IsStream(const std::string& label) override;
+ int video_session_id(const std::string& label, int index) override;
+ int audio_session_id(const std::string& label, int index) override;
int audio_input_request_id() const { return audio_input_request_id_; }
int audio_output_request_id() const { return audio_output_request_id_; }
@@ -59,7 +58,7 @@ class MockMediaStreamDispatcher : public MediaStreamDispatcher {
private:
void AddAudioInputDeviceToArray(bool matched_output);
void AddAudioOutputDeviceToArray();
- void AddVideoDeviceToArray();
+ void AddVideoDeviceToArray(bool facing_user);
int audio_input_request_id_;
int audio_output_request_id_; // Only used for EnumerateDevices.
diff --git a/chromium/content/renderer/media/mock_media_stream_registry.h b/chromium/content/renderer/media/mock_media_stream_registry.h
index ac0ffa1db62..ccae8809ec7 100644
--- a/chromium/content/renderer/media/mock_media_stream_registry.h
+++ b/chromium/content/renderer/media/mock_media_stream_registry.h
@@ -18,8 +18,7 @@ class MockMediaStreamRegistry : public MediaStreamRegistryInterface {
void Init(const std::string& stream_label);
void AddVideoTrack(const std::string& track_id);
- virtual blink::WebMediaStream GetMediaStream(
- const std::string& url) OVERRIDE;
+ blink::WebMediaStream GetMediaStream(const std::string& url) override;
const blink::WebMediaStream test_stream() const;
diff --git a/chromium/content/renderer/media/mock_media_stream_video_sink.cc b/chromium/content/renderer/media/mock_media_stream_video_sink.cc
index 347ca62e728..7a054ab3f71 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_sink.cc
+++ b/chromium/content/renderer/media/mock_media_stream_video_sink.cc
@@ -31,6 +31,7 @@ void MockMediaStreamVideoSink::DeliverVideoFrame(
const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format,
const base::TimeTicks& estimated_capture_time) {
+ last_frame_ = frame;
++number_of_frames_;
format_ = frame->format();
frame_size_ = frame->natural_size();
diff --git a/chromium/content/renderer/media/mock_media_stream_video_sink.h b/chromium/content/renderer/media/mock_media_stream_video_sink.h
index 682a617f167..eeb976a08e0 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_sink.h
+++ b/chromium/content/renderer/media/mock_media_stream_video_sink.h
@@ -20,8 +20,8 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink {
virtual ~MockMediaStreamVideoSink();
virtual void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
- virtual void OnEnabledChanged(bool enabled) OVERRIDE;
+ blink::WebMediaStreamSource::ReadyState state) override;
+ virtual void OnEnabledChanged(bool enabled) override;
// Triggered when OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame)
// is called.
@@ -32,6 +32,7 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink {
int number_of_frames() const { return number_of_frames_; }
media::VideoFrame::Format format() const { return format_; }
gfx::Size frame_size() const { return frame_size_; }
+ scoped_refptr<media::VideoFrame> last_frame() const { return last_frame_; };
bool enabled() const { return enabled_; }
blink::WebMediaStreamSource::ReadyState state() const { return state_; }
@@ -47,6 +48,7 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink {
media::VideoFrame::Format format_;
blink::WebMediaStreamSource::ReadyState state_;
gfx::Size frame_size_;
+ scoped_refptr<media::VideoFrame> last_frame_;
base::WeakPtrFactory<MockMediaStreamVideoSink> weak_factory_;
};
diff --git a/chromium/content/renderer/media/mock_media_stream_video_source.cc b/chromium/content/renderer/media/mock_media_stream_video_source.cc
index b1e58f3957b..19f7b6f74d1 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_source.cc
+++ b/chromium/content/renderer/media/mock_media_stream_video_source.cc
@@ -15,6 +15,7 @@ MockMediaStreamVideoSource::MockMediaStreamVideoSource(
: manual_get_supported_formats_(manual_get_supported_formats),
max_requested_height_(0),
max_requested_width_(0),
+ max_requested_frame_rate_(0.0),
attempted_to_start_(false) {
supported_formats_.push_back(
media::VideoCaptureFormat(
@@ -29,13 +30,13 @@ MockMediaStreamVideoSource::~MockMediaStreamVideoSource() {}
void MockMediaStreamVideoSource::StartMockedSource() {
DCHECK(attempted_to_start_);
attempted_to_start_ = false;
- OnStartDone(true);
+ OnStartDone(MEDIA_DEVICE_OK);
}
void MockMediaStreamVideoSource::FailToStartMockedSource() {
DCHECK(attempted_to_start_);
attempted_to_start_ = false;
- OnStartDone(false);
+ OnStartDone(MEDIA_DEVICE_TRACK_START_FAILURE);
}
void MockMediaStreamVideoSource::CompleteGetSupportedFormats() {
@@ -46,10 +47,12 @@ void MockMediaStreamVideoSource::CompleteGetSupportedFormats() {
void MockMediaStreamVideoSource::GetCurrentSupportedFormats(
int max_requested_height,
int max_requested_width,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) {
DCHECK(formats_callback_.is_null());
max_requested_height_ = max_requested_height;
max_requested_width_ = max_requested_width;
+ max_requested_frame_rate_ = max_requested_frame_rate;
if (manual_get_supported_formats_) {
formats_callback_ = callback;
@@ -59,10 +62,10 @@ void MockMediaStreamVideoSource::GetCurrentSupportedFormats(
}
void MockMediaStreamVideoSource::StartSourceImpl(
- const media::VideoCaptureParams& params,
+ const media::VideoCaptureFormat& format,
const VideoCaptureDeliverFrameCB& frame_callback) {
DCHECK(frame_callback_.is_null());
- params_ = params;
+ format_ = format;
attempted_to_start_ = true;
frame_callback_ = frame_callback;
}
@@ -76,7 +79,7 @@ void MockMediaStreamVideoSource::DeliverVideoFrame(
io_message_loop()->PostTask(
FROM_HERE,
base::Bind(&MockMediaStreamVideoSource::DeliverVideoFrameOnIO,
- base::Unretained(this), frame, params_.requested_format,
+ base::Unretained(this), frame, format_,
base::TimeTicks(), frame_callback_));
}
diff --git a/chromium/content/renderer/media/mock_media_stream_video_source.h b/chromium/content/renderer/media/mock_media_stream_video_source.h
index ad7463b6d4c..9602b2fb38e 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_source.h
+++ b/chromium/content/renderer/media/mock_media_stream_video_source.h
@@ -7,6 +7,8 @@
#include "content/renderer/media/media_stream_video_source.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
namespace content {
class MockMediaStreamVideoSource : public MediaStreamVideoSource {
@@ -14,6 +16,8 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource {
explicit MockMediaStreamVideoSource(bool manual_get_supported_formats);
virtual ~MockMediaStreamVideoSource();
+ MOCK_METHOD1(DoSetMutedState, void(bool muted_state));
+
// Simulate that the underlying source start successfully.
void StartMockedSource();
@@ -35,9 +39,15 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource {
void CompleteGetSupportedFormats();
- const media::VideoCaptureParams& start_params() const { return params_; }
+ const media::VideoCaptureFormat& start_format() const { return format_; }
int max_requested_height() const { return max_requested_height_; }
int max_requested_width() const { return max_requested_width_; }
+ double max_requested_frame_rate() const { return max_requested_frame_rate_; }
+
+ virtual void SetMutedState(bool muted_state) override {
+ MediaStreamVideoSource::SetMutedState(muted_state);
+ DoSetMutedState(muted_state);
+ }
protected:
void DeliverVideoFrameOnIO(const scoped_refptr<media::VideoFrame>& frame,
@@ -49,18 +59,20 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource {
virtual void GetCurrentSupportedFormats(
int max_requested_height,
int max_requested_width,
- const VideoCaptureDeviceFormatsCB& callback) OVERRIDE;
+ double max_requested_frame_rate,
+ const VideoCaptureDeviceFormatsCB& callback) override;
virtual void StartSourceImpl(
- const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& frame_callback) OVERRIDE;
- virtual void StopSourceImpl() OVERRIDE;
+ const media::VideoCaptureFormat& format,
+ const VideoCaptureDeliverFrameCB& frame_callback) override;
+ virtual void StopSourceImpl() override;
private:
- media::VideoCaptureParams params_;
+ media::VideoCaptureFormat format_;
media::VideoCaptureFormats supported_formats_;
bool manual_get_supported_formats_;
int max_requested_height_;
int max_requested_width_;
+ double max_requested_frame_rate_;
bool attempted_to_start_;
VideoCaptureDeviceFormatsCB formats_callback_;
VideoCaptureDeliverFrameCB frame_callback_;
diff --git a/chromium/content/renderer/media/mock_peer_connection_impl.cc b/chromium/content/renderer/media/mock_peer_connection_impl.cc
index 41fa2d1a5d5..6df5a327a21 100644
--- a/chromium/content/renderer/media/mock_peer_connection_impl.cc
+++ b/chromium/content/renderer/media/mock_peer_connection_impl.cc
@@ -25,21 +25,17 @@ namespace content {
class MockStreamCollection : public webrtc::StreamCollectionInterface {
public:
- virtual size_t count() OVERRIDE {
- return streams_.size();
- }
- virtual MediaStreamInterface* at(size_t index) OVERRIDE {
- return streams_[index];
- }
- virtual MediaStreamInterface* find(const std::string& label) OVERRIDE {
+ size_t count() override { return streams_.size(); }
+ MediaStreamInterface* at(size_t index) override { return streams_[index]; }
+ MediaStreamInterface* find(const std::string& label) override {
for (size_t i = 0; i < streams_.size(); ++i) {
if (streams_[i]->label() == label)
return streams_[i];
}
return NULL;
}
- virtual webrtc::MediaStreamTrackInterface* FindAudioTrack(
- const std::string& id) OVERRIDE {
+ webrtc::MediaStreamTrackInterface* FindAudioTrack(
+ const std::string& id) override {
for (size_t i = 0; i < streams_.size(); ++i) {
webrtc::MediaStreamTrackInterface* track =
streams_.at(i)->FindAudioTrack(id);
@@ -48,8 +44,8 @@ class MockStreamCollection : public webrtc::StreamCollectionInterface {
}
return NULL;
}
- virtual webrtc::MediaStreamTrackInterface* FindVideoTrack(
- const std::string& id) OVERRIDE {
+ webrtc::MediaStreamTrackInterface* FindVideoTrack(
+ const std::string& id) override {
for (size_t i = 0; i < streams_.size(); ++i) {
webrtc::MediaStreamTrackInterface* track =
streams_.at(i)->FindVideoTrack(id);
@@ -72,10 +68,10 @@ class MockStreamCollection : public webrtc::StreamCollectionInterface {
}
protected:
- virtual ~MockStreamCollection() {}
+ ~MockStreamCollection() override {}
private:
- typedef std::vector<talk_base::scoped_refptr<MediaStreamInterface> >
+ typedef std::vector<rtc::scoped_refptr<MediaStreamInterface> >
StreamVector;
StreamVector streams_;
};
@@ -90,65 +86,48 @@ class MockDataChannel : public webrtc::DataChannelInterface {
config_(*config) {
}
- virtual void RegisterObserver(
- webrtc::DataChannelObserver* observer) OVERRIDE {
- }
+ void RegisterObserver(webrtc::DataChannelObserver* observer) override {}
- virtual void UnregisterObserver() OVERRIDE {
- }
+ void UnregisterObserver() override {}
- virtual std::string label() const OVERRIDE {
- return label_;
- }
+ std::string label() const override { return label_; }
- virtual bool reliable() const OVERRIDE {
- return reliable_;
- }
+ bool reliable() const override { return reliable_; }
- virtual bool ordered() const OVERRIDE {
- return config_.ordered;
- }
+ bool ordered() const override { return config_.ordered; }
- virtual unsigned short maxRetransmitTime() const OVERRIDE {
+ unsigned short maxRetransmitTime() const override {
return config_.maxRetransmitTime;
}
- virtual unsigned short maxRetransmits() const OVERRIDE {
+ unsigned short maxRetransmits() const override {
return config_.maxRetransmits;
}
- virtual std::string protocol() const OVERRIDE {
- return config_.protocol;
- }
+ std::string protocol() const override { return config_.protocol; }
- virtual bool negotiated() const OVERRIDE {
- return config_.negotiated;
- }
+ bool negotiated() const override { return config_.negotiated; }
- virtual int id() const OVERRIDE {
+ int id() const override {
NOTIMPLEMENTED();
return 0;
}
- virtual DataState state() const OVERRIDE {
- return state_;
- }
+ DataState state() const override { return state_; }
- virtual uint64 buffered_amount() const OVERRIDE {
+ uint64 buffered_amount() const override {
NOTIMPLEMENTED();
return 0;
}
- virtual void Close() OVERRIDE {
- state_ = webrtc::DataChannelInterface::kClosing;
- }
+ void Close() override { state_ = webrtc::DataChannelInterface::kClosing; }
- virtual bool Send(const webrtc::DataBuffer& buffer) OVERRIDE {
+ bool Send(const webrtc::DataBuffer& buffer) override {
return state_ == webrtc::DataChannelInterface::kOpen;
}
protected:
- virtual ~MockDataChannel() {}
+ ~MockDataChannel() override {}
private:
std::string label_;
@@ -164,37 +143,29 @@ class MockDtmfSender : public DtmfSenderInterface {
observer_(NULL),
duration_(0),
inter_tone_gap_(0) {}
- virtual void RegisterObserver(
- DtmfSenderObserverInterface* observer) OVERRIDE {
+ void RegisterObserver(DtmfSenderObserverInterface* observer) override {
observer_ = observer;
}
- virtual void UnregisterObserver() OVERRIDE {
- observer_ = NULL;
- }
- virtual bool CanInsertDtmf() OVERRIDE {
- return true;
- }
- virtual bool InsertDtmf(const std::string& tones, int duration,
- int inter_tone_gap) OVERRIDE {
+ void UnregisterObserver() override { observer_ = NULL; }
+ bool CanInsertDtmf() override { return true; }
+ bool InsertDtmf(const std::string& tones,
+ int duration,
+ int inter_tone_gap) override {
tones_ = tones;
duration_ = duration;
inter_tone_gap_ = inter_tone_gap;
return true;
}
- virtual const AudioTrackInterface* track() const OVERRIDE {
- return track_.get();
- }
- virtual std::string tones() const OVERRIDE {
- return tones_;
- }
- virtual int duration() const OVERRIDE { return duration_; }
- virtual int inter_tone_gap() const OVERRIDE { return inter_tone_gap_; }
+ const AudioTrackInterface* track() const override { return track_.get(); }
+ std::string tones() const override { return tones_; }
+ int duration() const override { return duration_; }
+ int inter_tone_gap() const override { return inter_tone_gap_; }
protected:
- virtual ~MockDtmfSender() {}
+ ~MockDtmfSender() override {}
private:
- talk_base::scoped_refptr<AudioTrackInterface> track_;
+ rtc::scoped_refptr<AudioTrackInterface> track_;
DtmfSenderObserverInterface* observer_;
std::string tones_;
int duration_;
@@ -205,14 +176,16 @@ const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";
MockPeerConnectionImpl::MockPeerConnectionImpl(
- MockPeerConnectionDependencyFactory* factory)
+ MockPeerConnectionDependencyFactory* factory,
+ webrtc::PeerConnectionObserver* observer)
: dependency_factory_(factory),
- local_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
- remote_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
+ local_streams_(new rtc::RefCountedObject<MockStreamCollection>),
+ remote_streams_(new rtc::RefCountedObject<MockStreamCollection>),
hint_audio_(false),
hint_video_(false),
getstats_result_(true),
- sdp_mline_index_(-1) {
+ sdp_mline_index_(-1),
+ observer_(observer) {
ON_CALL(*this, SetLocalDescription(_, _)).WillByDefault(testing::Invoke(
this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
ON_CALL(*this, SetRemoteDescription(_, _)).WillByDefault(testing::Invoke(
@@ -221,19 +194,17 @@ MockPeerConnectionImpl::MockPeerConnectionImpl(
MockPeerConnectionImpl::~MockPeerConnectionImpl() {}
-talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
+rtc::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::local_streams() {
return local_streams_;
}
-talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
+rtc::scoped_refptr<webrtc::StreamCollectionInterface>
MockPeerConnectionImpl::remote_streams() {
return remote_streams_;
}
-bool MockPeerConnectionImpl::AddStream(
- MediaStreamInterface* local_stream,
- const MediaConstraintsInterface* constraints) {
+bool MockPeerConnectionImpl::AddStream(MediaStreamInterface* local_stream) {
DCHECK(stream_label_.empty());
stream_label_ = local_stream->label();
local_streams_->AddStream(local_stream);
@@ -247,18 +218,18 @@ void MockPeerConnectionImpl::RemoveStream(
local_streams_->RemoveStream(local_stream);
}
-talk_base::scoped_refptr<DtmfSenderInterface>
+rtc::scoped_refptr<DtmfSenderInterface>
MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
if (!track) {
return NULL;
}
- return new talk_base::RefCountedObject<MockDtmfSender>(track);
+ return new rtc::RefCountedObject<MockDtmfSender>(track);
}
-talk_base::scoped_refptr<webrtc::DataChannelInterface>
+rtc::scoped_refptr<webrtc::DataChannelInterface>
MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
const webrtc::DataChannelInit* config) {
- return new talk_base::RefCountedObject<MockDataChannel>(label, config);
+ return new rtc::RefCountedObject<MockDataChannel>(label, config);
}
bool MockPeerConnectionImpl::GetStats(
@@ -269,30 +240,35 @@ bool MockPeerConnectionImpl::GetStats(
return false;
DCHECK_EQ(kStatsOutputLevelStandard, level);
- std::vector<webrtc::StatsReport> reports(track ? 1 : 2);
- webrtc::StatsReport& report = reports[0];
- report.id = "1234";
- report.type = "ssrc";
- report.timestamp = 42;
- webrtc::StatsReport::Value value;
- value.name = "trackname";
- value.value = "trackvalue";
- report.values.push_back(value);
+ webrtc::StatsReport report1, report2;
+ report1.id = "1234";
+ report1.type = "ssrc";
+ report1.timestamp = 42;
+ report1.values.push_back(
+ webrtc::StatsReport::Value(
+ webrtc::StatsReport::kStatsValueNameFingerprint,
+ "trackvalue"));
+
+ webrtc::StatsReports reports;
+ reports.push_back(&report1);
+
// If selector is given, we pass back one report.
// If selector is not given, we pass back two.
if (!track) {
- webrtc::StatsReport& report2 = reports[1];
report2.id = "nontrack";
report2.type = "generic";
report2.timestamp = 44;
- report2.values.push_back(value);
- value.name = "somename";
- value.value = "somevalue";
- report2.values.push_back(value);
+ report2.values.push_back(
+ webrtc::StatsReport::Value(
+ webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
+ "somevalue"));
+ reports.push_back(&report2);
}
+
// Note that the callback is synchronous, not asynchronous; it will
// happen before the request call completes.
observer->OnComplete(reports);
+
return true;
}
diff --git a/chromium/content/renderer/media/mock_peer_connection_impl.h b/chromium/content/renderer/media/mock_peer_connection_impl.h
index d563746aeed..5e892944547 100644
--- a/chromium/content/renderer/media/mock_peer_connection_impl.h
+++ b/chromium/content/renderer/media/mock_peer_connection_impl.h
@@ -21,23 +21,23 @@ class MockStreamCollection;
class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
public:
- explicit MockPeerConnectionImpl(MockPeerConnectionDependencyFactory* factory);
+ explicit MockPeerConnectionImpl(MockPeerConnectionDependencyFactory* factory,
+ webrtc::PeerConnectionObserver* observer);
// PeerConnectionInterface implementation.
- virtual talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
- local_streams() OVERRIDE;
- virtual talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
- remote_streams() OVERRIDE;
+ virtual rtc::scoped_refptr<webrtc::StreamCollectionInterface>
+ local_streams() override;
+ virtual rtc::scoped_refptr<webrtc::StreamCollectionInterface>
+ remote_streams() override;
virtual bool AddStream(
- webrtc::MediaStreamInterface* local_stream,
- const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
+ webrtc::MediaStreamInterface* local_stream) override;
virtual void RemoveStream(
- webrtc::MediaStreamInterface* local_stream) OVERRIDE;
- virtual talk_base::scoped_refptr<webrtc::DtmfSenderInterface>
- CreateDtmfSender(webrtc::AudioTrackInterface* track) OVERRIDE;
- virtual talk_base::scoped_refptr<webrtc::DataChannelInterface>
+ webrtc::MediaStreamInterface* local_stream) override;
+ virtual rtc::scoped_refptr<webrtc::DtmfSenderInterface>
+ CreateDtmfSender(webrtc::AudioTrackInterface* track) override;
+ virtual rtc::scoped_refptr<webrtc::DataChannelInterface>
CreateDataChannel(const std::string& label,
- const webrtc::DataChannelInit* config) OVERRIDE;
+ const webrtc::DataChannelInit* config) override;
virtual bool GetStats(webrtc::StatsObserver* observer,
webrtc::MediaStreamTrackInterface* track) {
@@ -45,43 +45,43 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
}
virtual bool GetStats(webrtc::StatsObserver* observer,
webrtc::MediaStreamTrackInterface* track,
- StatsOutputLevel level) OVERRIDE;
+ StatsOutputLevel level) override;
// Set Call this function to make sure next call to GetStats fail.
void SetGetStatsResult(bool result) { getstats_result_ = result; }
- virtual SignalingState signaling_state() OVERRIDE {
+ virtual SignalingState signaling_state() override {
NOTIMPLEMENTED();
return PeerConnectionInterface::kStable;
}
- virtual IceState ice_state() OVERRIDE {
+ virtual IceState ice_state() override {
NOTIMPLEMENTED();
return PeerConnectionInterface::kIceNew;
}
- virtual IceConnectionState ice_connection_state() OVERRIDE {
+ virtual IceConnectionState ice_connection_state() override {
NOTIMPLEMENTED();
return PeerConnectionInterface::kIceConnectionNew;
}
- virtual IceGatheringState ice_gathering_state() OVERRIDE {
+ virtual IceGatheringState ice_gathering_state() override {
NOTIMPLEMENTED();
return PeerConnectionInterface::kIceGatheringNew;
}
- virtual void Close() OVERRIDE {
+ virtual void Close() override {
NOTIMPLEMENTED();
}
virtual const webrtc::SessionDescriptionInterface* local_description()
- const OVERRIDE;
+ const override;
virtual const webrtc::SessionDescriptionInterface* remote_description()
- const OVERRIDE;
+ const override;
// JSEP01 APIs
virtual void CreateOffer(
webrtc::CreateSessionDescriptionObserver* observer,
- const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
+ const webrtc::MediaConstraintsInterface* constraints) override;
virtual void CreateAnswer(
webrtc::CreateSessionDescriptionObserver* observer,
- const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
+ const webrtc::MediaConstraintsInterface* constraints) override;
MOCK_METHOD2(SetLocalDescription,
void(webrtc::SetSessionDescriptionObserver* observer,
webrtc::SessionDescriptionInterface* desc));
@@ -96,10 +96,10 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
webrtc::SessionDescriptionInterface* desc);
virtual bool UpdateIce(
const IceServers& configuration,
- const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
+ const webrtc::MediaConstraintsInterface* constraints) override;
virtual bool AddIceCandidate(
- const webrtc::IceCandidateInterface* candidate) OVERRIDE;
- virtual void RegisterUMAObserver(webrtc::UMAObserver* observer) OVERRIDE;
+ const webrtc::IceCandidateInterface* candidate) override;
+ virtual void RegisterUMAObserver(webrtc::UMAObserver* observer) override;
void AddRemoteStream(webrtc::MediaStreamInterface* stream);
@@ -113,6 +113,9 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
webrtc::SessionDescriptionInterface* created_session_description() const {
return created_sessiondescription_.get();
}
+ webrtc::PeerConnectionObserver* observer() {
+ return observer_;
+ }
static const char kDummyOffer[];
static const char kDummyAnswer[];
@@ -124,8 +127,8 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
MockPeerConnectionDependencyFactory* dependency_factory_;
std::string stream_label_;
- talk_base::scoped_refptr<MockStreamCollection> local_streams_;
- talk_base::scoped_refptr<MockStreamCollection> remote_streams_;
+ rtc::scoped_refptr<MockStreamCollection> local_streams_;
+ rtc::scoped_refptr<MockStreamCollection> remote_streams_;
scoped_ptr<webrtc::SessionDescriptionInterface> local_desc_;
scoped_ptr<webrtc::SessionDescriptionInterface> remote_desc_;
scoped_ptr<webrtc::SessionDescriptionInterface> created_sessiondescription_;
@@ -136,6 +139,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
std::string sdp_mid_;
int sdp_mline_index_;
std::string ice_sdp_;
+ webrtc::PeerConnectionObserver* observer_;
DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionImpl);
};
diff --git a/chromium/content/renderer/media/native_handle_impl.h b/chromium/content/renderer/media/native_handle_impl.h
index 36c5dab6751..20a4f038c6f 100644
--- a/chromium/content/renderer/media/native_handle_impl.h
+++ b/chromium/content/renderer/media/native_handle_impl.h
@@ -15,11 +15,11 @@ class NativeHandleImpl : public webrtc::NativeHandle {
public:
// Wraps a video frame in the handle.
explicit NativeHandleImpl(scoped_refptr<media::VideoFrame> frame);
- virtual ~NativeHandleImpl();
+ ~NativeHandleImpl() override;
// Retrieves the video frame in the handle. The frame is still ref-counted by
// the handle. The ref count decreases when NativeHandleImpl is destroyed.
- virtual void* GetHandle() OVERRIDE;
+ void* GetHandle() override;
private:
scoped_refptr<media::VideoFrame> frame_;
diff --git a/chromium/content/renderer/media/peer_connection_audio_sink_owner.h b/chromium/content/renderer/media/peer_connection_audio_sink_owner.h
index 289a3f477a7..0aaa0ea40b4 100644
--- a/chromium/content/renderer/media/peer_connection_audio_sink_owner.h
+++ b/chromium/content/renderer/media/peer_connection_audio_sink_owner.h
@@ -20,24 +20,24 @@ class PeerConnectionAudioSinkOwner : public MediaStreamAudioTrackSink {
explicit PeerConnectionAudioSinkOwner(PeerConnectionAudioSink* sink);
// MediaStreamAudioTrackSink implementation.
- virtual int OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- const std::vector<int>& channels,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE;
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
- virtual void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual bool IsEqual(const MediaStreamAudioSink* other) const OVERRIDE;
- virtual bool IsEqual(const PeerConnectionAudioSink* other) const OVERRIDE;
+ int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) override;
+ void OnSetFormat(const media::AudioParameters& params) override;
+ void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) override;
+ void Reset() override;
+ bool IsEqual(const MediaStreamAudioSink* other) const override;
+ bool IsEqual(const PeerConnectionAudioSink* other) const override;
protected:
- virtual ~PeerConnectionAudioSinkOwner() {}
+ ~PeerConnectionAudioSinkOwner() override {}
private:
mutable base::Lock lock_;
diff --git a/chromium/content/renderer/media/peer_connection_identity_service.cc b/chromium/content/renderer/media/peer_connection_identity_service.cc
index f7bc8568102..d81320b9e6c 100644
--- a/chromium/content/renderer/media/peer_connection_identity_service.cc
+++ b/chromium/content/renderer/media/peer_connection_identity_service.cc
@@ -4,56 +4,95 @@
#include "content/renderer/media/peer_connection_identity_service.h"
+#include "base/bind.h"
+#include "base/thread_task_runner_handle.h"
#include "content/renderer/media/webrtc_identity_service.h"
#include "content/renderer/render_thread_impl.h"
namespace content {
+namespace {
+// Bridges identity requests between the main render thread and libjingle's
+// signaling thread.
+class RequestHandler : public base::RefCountedThreadSafe<RequestHandler> {
+ public:
+ RequestHandler(const GURL& origin,
+ webrtc::DTLSIdentityRequestObserver* observer,
+ const std::string& identity_name,
+ const std::string& common_name)
+ : signaling_thread_(base::ThreadTaskRunnerHandle::Get()),
+ observer_(observer), origin_(origin), identity_name_(identity_name),
+ common_name_(common_name) {}
+
+ void RequestIdentityOnUIThread() {
+ int request_id = RenderThreadImpl::current()->get_webrtc_identity_service()
+ ->RequestIdentity(origin_, identity_name_, common_name_,
+ base::Bind(&RequestHandler::OnIdentityReady, this),
+ base::Bind(&RequestHandler::OnRequestFailed, this));
+ DCHECK_NE(request_id, 0);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<RequestHandler>;
+ ~RequestHandler() {
+ DCHECK(!observer_.get());
+ }
+
+ void OnIdentityReady(
+ const std::string& certificate,
+ const std::string& private_key) {
+ signaling_thread_->PostTask(FROM_HERE,
+ base::Bind(&webrtc::DTLSIdentityRequestObserver::OnSuccess, observer_,
+ certificate, private_key));
+ signaling_thread_->PostTask(FROM_HERE,
+ base::Bind(&RequestHandler::EnsureReleaseObserverOnSignalingThread,
+ this));
+ }
+
+ void OnRequestFailed(int error) {
+ signaling_thread_->PostTask(FROM_HERE,
+ base::Bind(&webrtc::DTLSIdentityRequestObserver::OnFailure, observer_,
+ error));
+ signaling_thread_->PostTask(FROM_HERE,
+ base::Bind(&RequestHandler::EnsureReleaseObserverOnSignalingThread,
+ this));
+ }
+
+ void EnsureReleaseObserverOnSignalingThread() {
+ DCHECK(signaling_thread_->BelongsToCurrentThread());
+ observer_ = nullptr;
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
+ scoped_refptr<webrtc::DTLSIdentityRequestObserver> observer_;
+ const GURL origin_;
+ const std::string identity_name_;
+ const std::string common_name_;
+};
+} // namespace
PeerConnectionIdentityService::PeerConnectionIdentityService(const GURL& origin)
- : origin_(origin), pending_observer_(NULL), pending_request_id_(0) {}
+ : main_thread_(base::ThreadTaskRunnerHandle::Get()), origin_(origin) {
+ signaling_thread_.DetachFromThread();
+ DCHECK(main_thread_.get());
+}
PeerConnectionIdentityService::~PeerConnectionIdentityService() {
- if (pending_observer_)
- RenderThreadImpl::current()->get_webrtc_identity_service()
- ->CancelRequest(pending_request_id_);
+ // Typically destructed on libjingle's signaling thread.
}
bool PeerConnectionIdentityService::RequestIdentity(
const std::string& identity_name,
const std::string& common_name,
webrtc::DTLSIdentityRequestObserver* observer) {
+ DCHECK(signaling_thread_.CalledOnValidThread());
DCHECK(observer);
- if (pending_observer_)
- return false;
-
- pending_observer_ = observer;
- pending_request_id_ = RenderThreadImpl::current()
- ->get_webrtc_identity_service()->RequestIdentity(
- origin_,
- identity_name,
- common_name,
- base::Bind(&PeerConnectionIdentityService::OnIdentityReady,
- base::Unretained(this)),
- base::Bind(&PeerConnectionIdentityService::OnRequestFailed,
- base::Unretained(this)));
- return true;
-}
-
-void PeerConnectionIdentityService::OnIdentityReady(
- const std::string& certificate,
- const std::string& private_key) {
- pending_observer_->OnSuccess(certificate, private_key);
- ResetPendingRequest();
-}
-void PeerConnectionIdentityService::OnRequestFailed(int error) {
- pending_observer_->OnFailure(error);
- ResetPendingRequest();
-}
+ scoped_refptr<RequestHandler> handler(
+ new RequestHandler(origin_, observer, identity_name, common_name));
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RequestHandler::RequestIdentityOnUIThread, handler));
-void PeerConnectionIdentityService::ResetPendingRequest() {
- pending_observer_ = NULL;
- pending_request_id_ = 0;
+ return true;
}
} // namespace content
diff --git a/chromium/content/renderer/media/peer_connection_identity_service.h b/chromium/content/renderer/media/peer_connection_identity_service.h
index b68cafa135d..91b12ef12fd 100644
--- a/chromium/content/renderer/media/peer_connection_identity_service.h
+++ b/chromium/content/renderer/media/peer_connection_identity_service.h
@@ -6,8 +6,11 @@
#define CONTENT_RENDERER_MEDIA_PEER_CONNECTION_IDENTITY_SERVICE_H_
#include <string>
+#include <vector>
#include "base/basictypes.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
#include "content/public/renderer/render_process_observer.h"
#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
#include "url/gurl.h"
@@ -21,26 +24,20 @@ class PeerConnectionIdentityService
public:
explicit PeerConnectionIdentityService(const GURL& origin);
- virtual ~PeerConnectionIdentityService();
+ ~PeerConnectionIdentityService() override;
// webrtc::DTLSIdentityServiceInterface implementation.
- virtual bool RequestIdentity(
- const std::string& identity_name,
- const std::string& common_name,
- webrtc::DTLSIdentityRequestObserver* observer) OVERRIDE;
+ bool RequestIdentity(const std::string& identity_name,
+ const std::string& common_name,
+ webrtc::DTLSIdentityRequestObserver* observer) override;
private:
- void OnIdentityReady(const std::string& certificate,
- const std::string& private_key);
- void OnRequestFailed(int error);
+ base::ThreadChecker signaling_thread_;
- void ResetPendingRequest();
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
// The origin of the DTLS connection.
- GURL origin_;
- talk_base::scoped_refptr<webrtc::DTLSIdentityRequestObserver>
- pending_observer_;
- int pending_request_id_;
+ const GURL origin_;
DISALLOW_COPY_AND_ASSIGN(PeerConnectionIdentityService);
};
diff --git a/chromium/content/renderer/media/peer_connection_tracker.cc b/chromium/content/renderer/media/peer_connection_tracker.cc
index a9873971be8..25f1b2df9aa 100644
--- a/chromium/content/renderer/media/peer_connection_tracker.cc
+++ b/chromium/content/renderer/media/peer_connection_tracker.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "content/renderer/media/peer_connection_tracker.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/rtc_peer_connection_handler.h"
@@ -36,6 +38,29 @@ static string SerializeServers(
return result;
}
+static RTCMediaConstraints GetNativeMediaConstraints(
+ const blink::WebMediaConstraints& constraints) {
+ RTCMediaConstraints native_constraints;
+
+ if (constraints.isNull())
+ return native_constraints;
+
+ blink::WebVector<blink::WebMediaConstraint> mandatory;
+ constraints.getMandatoryConstraints(mandatory);
+ for (size_t i = 0; i < mandatory.size(); ++i) {
+ native_constraints.AddMandatory(
+ mandatory[i].m_name.utf8(), mandatory[i].m_value.utf8(), false);
+ }
+
+ blink::WebVector<blink::WebMediaConstraint> optional;
+ constraints.getOptionalConstraints(optional);
+ for (size_t i = 0; i < optional.size(); ++i) {
+ native_constraints.AddOptional(
+ optional[i].m_name.utf8(), optional[i].m_value.utf8(), false);
+ }
+ return native_constraints;
+}
+
static string SerializeMediaConstraints(
const RTCMediaConstraints& constraints) {
string result;
@@ -98,6 +123,28 @@ static string SerializeMediaDescriptor(
return result;
}
+static std::string SerializeIceTransportType(
+ webrtc::PeerConnectionInterface::IceTransportsType type) {
+ string transport_type;
+ switch (type) {
+ case webrtc::PeerConnectionInterface::kNone:
+ transport_type = "none";
+ break;
+ case webrtc::PeerConnectionInterface::kRelay:
+ transport_type = "relay";
+ break;
+ case webrtc::PeerConnectionInterface::kAll:
+ transport_type = "all";
+ break;
+ case webrtc::PeerConnectionInterface::kNoHost:
+ transport_type = "noHost";
+ break;
+ default:
+ NOTREACHED();
+ };
+ return transport_type;
+}
+
#define GET_STRING_OF_STATE(state) \
case WebRTCPeerConnectionHandlerClient::state: \
result = #state; \
@@ -169,7 +216,7 @@ static base::DictionaryValue* GetDictValueStats(
dict->Set("values", values);
for (size_t i = 0; i < report.values.size(); ++i) {
- values->AppendString(report.values[i].name);
+ values->AppendString(report.values[i].display_name());
values->AppendString(report.values[i].value);
}
return dict;
@@ -198,28 +245,43 @@ static base::DictionaryValue* GetDictValue(const webrtc::StatsReport& report) {
class InternalStatsObserver : public webrtc::StatsObserver {
public:
InternalStatsObserver(int lid)
- : lid_(lid){}
+ : lid_(lid), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
- virtual void OnComplete(
- const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
- base::ListValue list;
+ void OnComplete(const std::vector<webrtc::StatsReport>& reports) override {
+ scoped_ptr<base::ListValue> list(new base::ListValue());
for (size_t i = 0; i < reports.size(); ++i) {
base::DictionaryValue* report = GetDictValue(reports[i]);
if (report)
- list.Append(report);
+ list->Append(report);
}
- if (!list.empty())
- RenderThreadImpl::current()->Send(
- new PeerConnectionTrackerHost_AddStats(lid_, list));
+ if (!list->empty()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&InternalStatsObserver::OnCompleteImpl,
+ base::Passed(&list), lid_));
+ }
}
protected:
- virtual ~InternalStatsObserver() {}
+ ~InternalStatsObserver() override {
+ // Will be destructed on libjingle's signaling thread.
+ // The signaling thread is where libjingle's objects live and from where
+ // libjingle makes callbacks. This may or may not be the same thread as
+ // the main thread.
+ }
private:
- int lid_;
+ // Static since |this| will most likely have been deleted by the time we
+ // get here.
+ static void OnCompleteImpl(scoped_ptr<base::ListValue> list, int lid) {
+ DCHECK(!list->empty());
+ RenderThreadImpl::current()->Send(
+ new PeerConnectionTrackerHost_AddStats(lid, *list.get()));
+ }
+
+ const int lid_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
};
PeerConnectionTracker::PeerConnectionTracker() : next_lid_(1) {
@@ -233,35 +295,51 @@ bool PeerConnectionTracker::OnControlMessageReceived(
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PeerConnectionTracker, message)
IPC_MESSAGE_HANDLER(PeerConnectionTracker_GetAllStats, OnGetAllStats)
+ IPC_MESSAGE_HANDLER(PeerConnectionTracker_OnSuspend, OnSuspend)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PeerConnectionTracker::OnGetAllStats() {
+ DCHECK(main_thread_.CalledOnValidThread());
+
+ const std::string empty_track_id;
for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
it != peer_connection_id_map_.end(); ++it) {
+ rtc::scoped_refptr<InternalStatsObserver> observer(
+ new rtc::RefCountedObject<InternalStatsObserver>(it->second));
- talk_base::scoped_refptr<InternalStatsObserver> observer(
- new talk_base::RefCountedObject<InternalStatsObserver>(it->second));
-
+ // The last type parameter is ignored when the track id is empty.
it->first->GetStats(
observer,
- NULL,
- webrtc::PeerConnectionInterface::kStatsOutputLevelDebug);
+ webrtc::PeerConnectionInterface::kStatsOutputLevelDebug,
+ empty_track_id, blink::WebMediaStreamSource::TypeAudio);
+ }
+}
+
+void PeerConnectionTracker::OnSuspend() {
+ DCHECK(main_thread_.CalledOnValidThread());
+ for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
+ it != peer_connection_id_map_.end(); ++it) {
+ it->first->CloseClientPeerConnection();
}
}
void PeerConnectionTracker::RegisterPeerConnection(
RTCPeerConnectionHandler* pc_handler,
- const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const RTCMediaConstraints& constraints,
const blink::WebFrame* frame) {
+ DCHECK(main_thread_.CalledOnValidThread());
DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
PeerConnectionInfo info;
info.lid = GetNextLocalID();
- info.servers = SerializeServers(servers);
+ info.rtc_configuration =
+ "{ servers: " + SerializeServers(config.servers) + ", " +
+ "iceTransportType: " + SerializeIceTransportType(config.type) + " }";
+
info.constraints = SerializeMediaConstraints(constraints);
info.url = frame->document().url().spec();
RenderThreadImpl::current()->Send(
@@ -274,6 +352,7 @@ void PeerConnectionTracker::RegisterPeerConnection(
void PeerConnectionTracker::UnregisterPeerConnection(
RTCPeerConnectionHandler* pc_handler) {
+ DCHECK(main_thread_.CalledOnValidThread());
DVLOG(1) << "PeerConnectionTracker::UnregisterPeerConnection()";
std::map<RTCPeerConnectionHandler*, int>::iterator it =
@@ -294,6 +373,7 @@ void PeerConnectionTracker::UnregisterPeerConnection(
void PeerConnectionTracker::TrackCreateOffer(
RTCPeerConnectionHandler* pc_handler,
const RTCMediaConstraints& constraints) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, "createOffer",
"constraints: {" + SerializeMediaConstraints(constraints) + "}");
@@ -302,6 +382,7 @@ void PeerConnectionTracker::TrackCreateOffer(
void PeerConnectionTracker::TrackCreateAnswer(
RTCPeerConnectionHandler* pc_handler,
const RTCMediaConstraints& constraints) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, "createAnswer",
"constraints: {" + SerializeMediaConstraints(constraints) + "}");
@@ -309,11 +390,8 @@ void PeerConnectionTracker::TrackCreateAnswer(
void PeerConnectionTracker::TrackSetSessionDescription(
RTCPeerConnectionHandler* pc_handler,
- const blink::WebRTCSessionDescription& desc,
- Source source) {
- string sdp = base::UTF16ToUTF8(desc.sdp());
- string type = base::UTF16ToUTF8(desc.type());
-
+ const std::string& sdp, const std::string& type, Source source) {
+ DCHECK(main_thread_.CalledOnValidThread());
string value = "type: " + type + ", sdp: " + sdp;
SendPeerConnectionUpdate(
pc_handler,
@@ -323,31 +401,50 @@ void PeerConnectionTracker::TrackSetSessionDescription(
void PeerConnectionTracker::TrackUpdateIce(
RTCPeerConnectionHandler* pc_handler,
- const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const RTCMediaConstraints& options) {
- string servers_string = "servers: " + SerializeServers(servers);
+ DCHECK(main_thread_.CalledOnValidThread());
+ string servers_string = "servers: " + SerializeServers(config.servers);
+
+ string transport_type =
+ "iceTransportType: " + SerializeIceTransportType(config.type);
+
string constraints =
"constraints: {" + SerializeMediaConstraints(options) + "}";
SendPeerConnectionUpdate(
- pc_handler, "updateIce", servers_string + ", " + constraints);
+ pc_handler,
+ "updateIce",
+ servers_string + ", " + transport_type + ", " + constraints);
}
void PeerConnectionTracker::TrackAddIceCandidate(
RTCPeerConnectionHandler* pc_handler,
const blink::WebRTCICECandidate& candidate,
- Source source) {
- string value = "mid: " + base::UTF16ToUTF8(candidate.sdpMid()) + ", " +
- "candidate: " + base::UTF16ToUTF8(candidate.candidate());
- SendPeerConnectionUpdate(
- pc_handler,
- source == SOURCE_LOCAL ? "onIceCandidate" : "addIceCandidate", value);
+ Source source,
+ bool succeeded) {
+ DCHECK(main_thread_.CalledOnValidThread());
+ string value =
+ "sdpMid: " + base::UTF16ToUTF8(candidate.sdpMid()) + ", " +
+ "sdpMLineIndex: " + base::IntToString(candidate.sdpMLineIndex()) + ", " +
+ "candidate: " + base::UTF16ToUTF8(candidate.candidate());
+
+ // OnIceCandidate always succeeds as it's a callback from the browser.
+ DCHECK(source != SOURCE_LOCAL || succeeded);
+
+ string event =
+ (source == SOURCE_LOCAL) ? "onIceCandidate"
+ : (succeeded ? "addIceCandidate"
+ : "addIceCandidateFailed");
+
+ SendPeerConnectionUpdate(pc_handler, event, value);
}
void PeerConnectionTracker::TrackAddStream(
RTCPeerConnectionHandler* pc_handler,
const blink::WebMediaStream& stream,
- Source source){
+ Source source) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
SerializeMediaDescriptor(stream));
@@ -357,6 +454,7 @@ void PeerConnectionTracker::TrackRemoveStream(
RTCPeerConnectionHandler* pc_handler,
const blink::WebMediaStream& stream,
Source source){
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
SerializeMediaDescriptor(stream));
@@ -366,6 +464,7 @@ void PeerConnectionTracker::TrackCreateDataChannel(
RTCPeerConnectionHandler* pc_handler,
const webrtc::DataChannelInterface* data_channel,
Source source) {
+ DCHECK(main_thread_.CalledOnValidThread());
string value = "label: " + data_channel->label() +
", reliable: " + (data_channel->reliable() ? "true" : "false");
SendPeerConnectionUpdate(
@@ -375,12 +474,14 @@ void PeerConnectionTracker::TrackCreateDataChannel(
}
void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(pc_handler, "stop", std::string());
}
void PeerConnectionTracker::TrackSignalingStateChange(
RTCPeerConnectionHandler* pc_handler,
WebRTCPeerConnectionHandlerClient::SignalingState state) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, "signalingStateChange", GetSignalingStateString(state));
}
@@ -388,6 +489,7 @@ void PeerConnectionTracker::TrackSignalingStateChange(
void PeerConnectionTracker::TrackIceConnectionStateChange(
RTCPeerConnectionHandler* pc_handler,
WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, "iceConnectionStateChange",
GetIceConnectionStateString(state));
@@ -396,6 +498,7 @@ void PeerConnectionTracker::TrackIceConnectionStateChange(
void PeerConnectionTracker::TrackIceGatheringStateChange(
RTCPeerConnectionHandler* pc_handler,
WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(
pc_handler, "iceGatheringStateChange",
GetIceGatheringStateString(state));
@@ -404,6 +507,7 @@ void PeerConnectionTracker::TrackIceGatheringStateChange(
void PeerConnectionTracker::TrackSessionDescriptionCallback(
RTCPeerConnectionHandler* pc_handler, Action action,
const string& callback_type, const string& value) {
+ DCHECK(main_thread_.CalledOnValidThread());
string update_type;
switch (action) {
case ACTION_SET_LOCAL_DESCRIPTION:
@@ -429,20 +533,25 @@ void PeerConnectionTracker::TrackSessionDescriptionCallback(
void PeerConnectionTracker::TrackOnRenegotiationNeeded(
RTCPeerConnectionHandler* pc_handler) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
}
void PeerConnectionTracker::TrackCreateDTMFSender(
RTCPeerConnectionHandler* pc_handler,
const blink::WebMediaStreamTrack& track) {
+ DCHECK(main_thread_.CalledOnValidThread());
SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
base::UTF16ToUTF8(track.id()));
}
void PeerConnectionTracker::TrackGetUserMedia(
const blink::WebUserMediaRequest& user_media_request) {
- RTCMediaConstraints audio_constraints(user_media_request.audioConstraints());
- RTCMediaConstraints video_constraints(user_media_request.videoConstraints());
+ DCHECK(main_thread_.CalledOnValidThread());
+ RTCMediaConstraints audio_constraints(
+ GetNativeMediaConstraints(user_media_request.audioConstraints()));
+ RTCMediaConstraints video_constraints(
+ GetNativeMediaConstraints(user_media_request.videoConstraints()));
RenderThreadImpl::current()->Send(new PeerConnectionTrackerHost_GetUserMedia(
user_media_request.securityOrigin().toString().utf8(),
@@ -453,6 +562,7 @@ void PeerConnectionTracker::TrackGetUserMedia(
}
int PeerConnectionTracker::GetNextLocalID() {
+ DCHECK(main_thread_.CalledOnValidThread());
return next_lid_++;
}
@@ -460,6 +570,7 @@ void PeerConnectionTracker::SendPeerConnectionUpdate(
RTCPeerConnectionHandler* pc_handler,
const std::string& type,
const std::string& value) {
+ DCHECK(main_thread_.CalledOnValidThread());
if (peer_connection_id_map_.find(pc_handler) == peer_connection_id_map_.end())
return;
diff --git a/chromium/content/renderer/media/peer_connection_tracker.h b/chromium/content/renderer/media/peer_connection_tracker.h
index 406b7ac4b53..08f908607fe 100644
--- a/chromium/content/renderer/media/peer_connection_tracker.h
+++ b/chromium/content/renderer/media/peer_connection_tracker.h
@@ -8,6 +8,8 @@
#include <map>
#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "content/public/renderer/render_process_observer.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
@@ -33,10 +35,12 @@ class RTCPeerConnectionHandler;
// This class collects data about each peer connection,
// sends it to the browser process, and handles messages
// from the browser process.
-class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
+class CONTENT_EXPORT PeerConnectionTracker
+ : public RenderProcessObserver,
+ public base::SupportsWeakPtr<PeerConnectionTracker> {
public:
PeerConnectionTracker();
- virtual ~PeerConnectionTracker();
+ ~PeerConnectionTracker() override;
enum Source {
SOURCE_LOCAL,
@@ -51,7 +55,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
};
// RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& message) override;
//
// The following methods send an update to the browser process when a
@@ -69,7 +73,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// page in which the PeerConnection is created.
void RegisterPeerConnection(
RTCPeerConnectionHandler* pc_handler,
- const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const RTCMediaConstraints& constraints,
const blink::WebFrame* frame);
@@ -87,18 +91,20 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// Sends an update when setLocalDescription or setRemoteDescription is called.
virtual void TrackSetSessionDescription(
RTCPeerConnectionHandler* pc_handler,
- const blink::WebRTCSessionDescription& desc, Source source);
+ const std::string& sdp, const std::string& type, Source source);
// Sends an update when Ice candidates are updated.
virtual void TrackUpdateIce(
RTCPeerConnectionHandler* pc_handler,
- const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const RTCMediaConstraints& options);
// Sends an update when an Ice candidate is added.
virtual void TrackAddIceCandidate(
RTCPeerConnectionHandler* pc_handler,
- const blink::WebRTCICECandidate& candidate, Source source);
+ const blink::WebRTCICECandidate& candidate,
+ Source source,
+ bool succeeded);
// Sends an update when a media stream is added.
virtual void TrackAddStream(
@@ -161,6 +167,9 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// IPC Message handler for getting all stats.
void OnGetAllStats();
+ // Called when the browser process reports a suspend event from the OS.
+ void OnSuspend();
+
void SendPeerConnectionUpdate(RTCPeerConnectionHandler* pc_handler,
const std::string& callback_type,
const std::string& value);
@@ -171,6 +180,7 @@ class CONTENT_EXPORT PeerConnectionTracker : public RenderProcessObserver {
// This keeps track of the next available local ID.
int next_lid_;
+ base::ThreadChecker main_thread_;
DISALLOW_COPY_AND_ASSIGN(PeerConnectionTracker);
};
diff --git a/chromium/content/renderer/media/preload.h b/chromium/content/renderer/media/preload.h
deleted file mode 100644
index 8fefd93687e..00000000000
--- a/chromium/content/renderer/media/preload.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_PRELOAD_H_
-#define CONTENT_RENDERER_MEDIA_PRELOAD_H_
-
-namespace content {
-
-// Used to specify video preload states. They are "hints" to the browser about
-// how aggressively the browser should load and buffer data.
-// Please see the HTML5 spec for the descriptions of these values:
-// http://www.w3.org/TR/html5/video.html#attr-media-preload
-//
-// Enum values must match the values in WebCore::MediaPlayer::Preload and
-// there will be assertions at compile time if they do not match.
-enum Preload {
- NONE,
- METADATA,
- AUTO,
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_PRELOAD_H_
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.cc b/chromium/content/renderer/media/remote_media_stream_impl.cc
index d2421310ef8..06f41772d44 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.cc
+++ b/chromium/content/renderer/media/remote_media_stream_impl.cc
@@ -6,142 +6,309 @@
#include <string>
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "content/renderer/media/media_stream.h"
+#include "content/renderer/media/media_stream_track.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/webrtc/media_stream_remote_video_source.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "third_party/WebKit/public/platform/WebString.h"
namespace content {
-
namespace {
-void InitializeWebkitTrack(webrtc::MediaStreamTrackInterface* track,
- blink::WebMediaStreamTrack* webkit_track,
- blink::WebMediaStreamSource::Type type) {
- blink::WebMediaStreamSource webkit_source;
- blink::WebString webkit_track_id(base::UTF8ToUTF16(track->id()));
-
- webkit_source.initialize(webkit_track_id, type, webkit_track_id);
- webkit_track->initialize(webkit_track_id, webkit_source);
+template <typename WebRtcTrackVector, typename AdapterType>
+void CreateAdaptersForTracks(
+ const WebRtcTrackVector& tracks,
+ std::vector<scoped_refptr<AdapterType>>* observers,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread) {
+ for (auto& track : tracks)
+ observers->push_back(new AdapterType(main_thread, track));
+}
- if (type == blink::WebMediaStreamSource::TypeVideo) {
- MediaStreamRemoteVideoSource* video_source =
- new MediaStreamRemoteVideoSource(
- static_cast<webrtc::VideoTrackInterface*>(track));
- webkit_source.setExtraData(video_source);
- // Initial constraints must be provided to a MediaStreamVideoTrack. But
- // no constraints are available initially on a remote video track.
- blink::WebMediaConstraints constraints;
- constraints.initialize();
- webkit_track->setExtraData(
- new MediaStreamVideoTrack(video_source, constraints,
- MediaStreamVideoSource::ConstraintsCallback(),
- track->enabled()));
- } else {
- DCHECK(type == blink::WebMediaStreamSource::TypeAudio);
- content::PeerConnectionDependencyFactory::AddNativeAudioTrackToBlinkTrack(
- track, *webkit_track, false);
+template<typename VectorType>
+bool IsTrackInVector(const VectorType& v, const std::string& id) {
+ for (const auto& t : v) {
+ if (t->id() == id)
+ return true;
}
+ return false;
}
-
} // namespace
+// TODO(tommi): Move this class to a separate set of files.
+class RemoteMediaStreamAudioTrack : public MediaStreamTrack {
+ public:
+ RemoteMediaStreamAudioTrack(
+ const scoped_refptr<webrtc::AudioTrackInterface>& track,
+ const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread)
+ : MediaStreamTrack(false), track_(track),
+ signaling_thread_(signaling_thread) {
+ }
+
+ ~RemoteMediaStreamAudioTrack() override {}
+
+ private:
+ void SetEnabled(bool enabled) override {
+ track_->set_enabled(enabled);
+ }
+
+ void Stop() override {
+ // Stop means that a track should be stopped permanently. But
+ // since there is no proper way of doing that on a remote track, we can
+ // at least disable the track. Blink will not call down to the content layer
+ // after a track has been stopped.
+ SetEnabled(false);
+ }
+
+ private:
+ const scoped_refptr<webrtc::AudioTrackInterface> track_;
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
+};
+
// Base class used for mapping between webrtc and blink MediaStream tracks.
// An instance of a RemoteMediaStreamTrackAdapter is stored in
// RemoteMediaStreamImpl per remote audio and video track.
-class RemoteMediaStreamTrackAdapter {
+template<typename WebRtcMediaStreamTrackType>
+class RemoteMediaStreamTrackAdapter
+ : public base::RefCountedThreadSafe<
+ RemoteMediaStreamTrackAdapter<WebRtcMediaStreamTrackType>> {
public:
- RemoteMediaStreamTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track,
- const blink::WebMediaStreamTrack& webkit_track)
- : webrtc_track_(webrtc_track),
- webkit_track_(webkit_track) {
+ RemoteMediaStreamTrackAdapter(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ WebRtcMediaStreamTrackType* webrtc_track)
+ : main_thread_(main_thread), webrtc_track_(webrtc_track),
+ id_(webrtc_track->id()) {
+ }
+
+ const scoped_refptr<WebRtcMediaStreamTrackType>& observed_track() {
+ return webrtc_track_;
}
+ blink::WebMediaStreamTrack* webkit_track() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(!webkit_track_.isNull());
+ return &webkit_track_;
+ }
+
+ const std::string& id() const { return id_; }
+
+ bool initialized() const {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ return !webkit_track_.isNull();
+ }
+
+ void Initialize() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(!initialized());
+ webkit_initialize_.Run();
+ webkit_initialize_.Reset();
+ DCHECK(initialized());
+ }
+
+ protected:
+ friend class base::RefCountedThreadSafe<
+ RemoteMediaStreamTrackAdapter<WebRtcMediaStreamTrackType>>;
+
virtual ~RemoteMediaStreamTrackAdapter() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
}
- webrtc::MediaStreamTrackInterface* observed_track() {
- return webrtc_track_.get();
+ void InitializeWebkitTrack(blink::WebMediaStreamSource::Type type) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(webkit_track_.isNull());
+
+ blink::WebString webkit_track_id(base::UTF8ToUTF16(id_));
+ blink::WebMediaStreamSource webkit_source;
+ webkit_source.initialize(webkit_track_id, type, webkit_track_id);
+ webkit_track_.initialize(webkit_track_id, webkit_source);
+ DCHECK(!webkit_track_.isNull());
}
- const blink::WebMediaStreamTrack& webkit_track() { return webkit_track_; }
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ // This callback will be run when Initialize() is called and then freed.
+ // The callback is used by derived classes to bind objects that need to be
+ // instantiated and initialized on the signaling thread but then moved to
+ // and used on the main thread when initializing the webkit object(s).
+ base::Callback<void()> webkit_initialize_;
private:
- scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
+ const scoped_refptr<WebRtcMediaStreamTrackType> webrtc_track_;
blink::WebMediaStreamTrack webkit_track_;
+ // const copy of the webrtc track id that allows us to check it from both the
+ // main and signaling threads without incurring a synchronous thread hop.
+ const std::string id_;
DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackAdapter);
};
-static content::RemoteMediaStreamTrackAdapter* FindTrackObserver(
- webrtc::MediaStreamTrackInterface* track,
- const ScopedVector<content::RemoteMediaStreamTrackAdapter>& observers) {
- ScopedVector<content::RemoteMediaStreamTrackAdapter>::const_iterator it =
- observers.begin();
- for (; it != observers.end(); ++it) {
- if ((*it)->observed_track() == track)
- return *it;
+class RemoteVideoTrackAdapter
+ : public RemoteMediaStreamTrackAdapter<webrtc::VideoTrackInterface> {
+ public:
+ // Called on the signaling thread
+ RemoteVideoTrackAdapter(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::VideoTrackInterface* webrtc_track)
+ : RemoteMediaStreamTrackAdapter(main_thread, webrtc_track) {
+ source_observer_ = new MediaStreamRemoteVideoSource::Observer(main_thread,
+ observed_track().get());
+ // Here, we use base::Unretained() to avoid a circular reference.
+ webkit_initialize_ = base::Bind(
+ &RemoteVideoTrackAdapter::InitializeWebkitVideoTrack,
+ base::Unretained(this), observed_track()->enabled());
}
- return NULL;
-}
-// RemoteAudioMediaStreamTrackAdapter is responsible for listening on state
+ protected:
+ ~RemoteVideoTrackAdapter() override {
+ // If the source_observer_ is valid at this point, then that means we
+ // haven't been initialized and we need to unregister the observer before
+ // it gets automatically deleted. We can't unregister from the destructor
+ // of the observer because at that point, the refcount will be 0 and we
+ // could receive an event during that time which would attempt to increment
+ // the refcount while we're running the dtor on this thread...
+ if (source_observer_.get()) {
+ DCHECK(!initialized());
+ source_observer_->Unregister();
+ }
+
+ // TODO(tommi): There's got to be a smarter way of solving this.
+ // We should probably separate the implementation of the observer itself
+ // and the ownerof the weakptr to the main thread's implementation of
+ // OnChanged.
+ }
+
+ private:
+ void InitializeWebkitVideoTrack(bool enabled) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ scoped_ptr<MediaStreamRemoteVideoSource> video_source(
+ new MediaStreamRemoteVideoSource(source_observer_));
+ // Now that we're being initialized, we do not want to unregister the
+ // observer in the dtor. This will be done when the source goes out of
+ // scope. A source can be shared by more than one tracks (e.g via cloning)
+ // so we must not unregister an observer that belongs to a live source.
+ source_observer_ = nullptr;
+ InitializeWebkitTrack(blink::WebMediaStreamSource::TypeVideo);
+ webkit_track()->source().setExtraData(video_source.get());
+ // Initial constraints must be provided to a MediaStreamVideoTrack. But
+ // no constraints are available initially on a remote video track.
+ blink::WebMediaConstraints constraints;
+ constraints.initialize();
+ MediaStreamVideoTrack* media_stream_track =
+ new MediaStreamVideoTrack(video_source.release(), constraints,
+ MediaStreamVideoSource::ConstraintsCallback(), enabled);
+ webkit_track()->setExtraData(media_stream_track);
+ }
+
+ // We hold on to the source observer in case we don't get initialized and
+ // need to unregister it in the dtor.
+ // TODO(tommi): There has to be a more elegant solution.
+ scoped_refptr<MediaStreamRemoteVideoSource::Observer> source_observer_;
+};
+
+// RemoteAudioTrackAdapter is responsible for listening on state
// change notifications on a remote webrtc audio MediaStreamTracks and notify
// WebKit.
-class RemoteAudioMediaStreamTrackAdapter
- : public RemoteMediaStreamTrackAdapter,
- public webrtc::ObserverInterface,
- public base::NonThreadSafe {
+class RemoteAudioTrackAdapter
+ : public RemoteMediaStreamTrackAdapter<webrtc::AudioTrackInterface>,
+ public webrtc::ObserverInterface {
public:
- RemoteAudioMediaStreamTrackAdapter(
- webrtc::MediaStreamTrackInterface* webrtc_track,
- const blink::WebMediaStreamTrack& webkit_track);
- virtual ~RemoteAudioMediaStreamTrackAdapter();
+ RemoteAudioTrackAdapter(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::AudioTrackInterface* webrtc_track);
+
+ void Unregister();
+
+ protected:
+ ~RemoteAudioTrackAdapter() override;
private:
+ void InitializeWebkitAudioTrack(
+ scoped_ptr<RemoteMediaStreamAudioTrack> media_stream_track);
+
// webrtc::ObserverInterface implementation.
- virtual void OnChanged() OVERRIDE;
+ void OnChanged() override;
+
+ void OnChangedOnMainThread(
+ webrtc::MediaStreamTrackInterface::TrackState state);
+
+#if DCHECK_IS_ON
+ bool unregistered_;
+#endif
webrtc::MediaStreamTrackInterface::TrackState state_;
- DISALLOW_COPY_AND_ASSIGN(RemoteAudioMediaStreamTrackAdapter);
+ DISALLOW_COPY_AND_ASSIGN(RemoteAudioTrackAdapter);
};
-RemoteAudioMediaStreamTrackAdapter::RemoteAudioMediaStreamTrackAdapter(
- webrtc::MediaStreamTrackInterface* webrtc_track,
- const blink::WebMediaStreamTrack& webkit_track)
- : RemoteMediaStreamTrackAdapter(webrtc_track, webkit_track),
+// Called on the signaling thread.
+RemoteAudioTrackAdapter::RemoteAudioTrackAdapter(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::AudioTrackInterface* webrtc_track)
+ : RemoteMediaStreamTrackAdapter(main_thread, webrtc_track),
+#if DCHECK_IS_ON
+ unregistered_(false),
+#endif
state_(observed_track()->state()) {
observed_track()->RegisterObserver(this);
+ scoped_ptr<RemoteMediaStreamAudioTrack> media_stream_track(
+ new RemoteMediaStreamAudioTrack(observed_track().get(),
+ base::ThreadTaskRunnerHandle::Get()));
+ // Here, we use base::Unretained() to avoid a circular reference.
+ webkit_initialize_ = base::Bind(
+ &RemoteAudioTrackAdapter::InitializeWebkitAudioTrack,
+ base::Unretained(this), base::Passed(&media_stream_track));
}
-RemoteAudioMediaStreamTrackAdapter::~RemoteAudioMediaStreamTrackAdapter() {
+RemoteAudioTrackAdapter::~RemoteAudioTrackAdapter() {
+#if DCHECK_IS_ON
+ DCHECK(unregistered_);
+#endif
+}
+
+void RemoteAudioTrackAdapter::Unregister() {
+#if DCHECK_IS_ON
+ DCHECK(!unregistered_);
+ unregistered_ = true;
+#endif
observed_track()->UnregisterObserver(this);
}
-void RemoteAudioMediaStreamTrackAdapter::OnChanged() {
- DCHECK(CalledOnValidThread());
+void RemoteAudioTrackAdapter::InitializeWebkitAudioTrack(
+ scoped_ptr<RemoteMediaStreamAudioTrack> media_stream_track) {
+ InitializeWebkitTrack(blink::WebMediaStreamSource::TypeAudio);
+ webkit_track()->setExtraData(media_stream_track.release());
+}
+
+void RemoteAudioTrackAdapter::OnChanged() {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RemoteAudioTrackAdapter::OnChangedOnMainThread,
+ this, observed_track()->state()));
+}
+
+void RemoteAudioTrackAdapter::OnChangedOnMainThread(
+ webrtc::MediaStreamTrackInterface::TrackState state) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
- webrtc::MediaStreamTrackInterface::TrackState state =
- observed_track()->state();
- if (state == state_)
+ if (state == state_ || !initialized())
return;
state_ = state;
+
switch (state) {
case webrtc::MediaStreamTrackInterface::kInitializing:
// Ignore the kInitializing state since there is no match in
// WebMediaStreamSource::ReadyState.
break;
case webrtc::MediaStreamTrackInterface::kLive:
- webkit_track().source().setReadyState(
+ webkit_track()->source().setReadyState(
blink::WebMediaStreamSource::ReadyStateLive);
break;
case webrtc::MediaStreamTrackInterface::kEnded:
- webkit_track().source().setReadyState(
+ webkit_track()->source().setReadyState(
blink::WebMediaStreamSource::ReadyStateEnded);
break;
default:
@@ -150,108 +317,156 @@ void RemoteAudioMediaStreamTrackAdapter::OnChanged() {
}
}
-RemoteMediaStreamImpl::RemoteMediaStreamImpl(
+RemoteMediaStreamImpl::Observer::Observer(
+ const base::WeakPtr<RemoteMediaStreamImpl>& media_stream,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::MediaStreamInterface* webrtc_stream)
- : webrtc_stream_(webrtc_stream) {
+ : media_stream_(media_stream),
+ main_thread_(main_thread),
+ webrtc_stream_(webrtc_stream) {
webrtc_stream_->RegisterObserver(this);
+}
- webrtc::AudioTrackVector webrtc_audio_tracks =
- webrtc_stream_->GetAudioTracks();
+RemoteMediaStreamImpl::Observer::~Observer() {
+ DCHECK(!webrtc_stream_.get()) << "Unregister hasn't been called";
+}
+
+void RemoteMediaStreamImpl::Observer::InitializeOnMainThread(
+ const std::string& label) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (media_stream_)
+ media_stream_->InitializeOnMainThread(label);
+}
+
+void RemoteMediaStreamImpl::Observer::Unregister() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ webrtc_stream_->UnregisterObserver(this);
+ // Since we're guaranteed to not get further notifications, it's safe to
+ // release the webrtc_stream_ here.
+ webrtc_stream_ = nullptr;
+}
+
+void RemoteMediaStreamImpl::Observer::OnChanged() {
+ scoped_ptr<RemoteAudioTrackAdapters> audio(new RemoteAudioTrackAdapters());
+ scoped_ptr<RemoteVideoTrackAdapters> video(new RemoteVideoTrackAdapters());
+
+ CreateAdaptersForTracks(
+ webrtc_stream_->GetAudioTracks(), audio.get(), main_thread_);
+ CreateAdaptersForTracks(
+ webrtc_stream_->GetVideoTracks(), video.get(), main_thread_);
+
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RemoteMediaStreamImpl::Observer::OnChangedOnMainThread,
+ this, base::Passed(&audio), base::Passed(&video)));
+}
+
+void RemoteMediaStreamImpl::Observer::OnChangedOnMainThread(
+ scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ scoped_ptr<RemoteVideoTrackAdapters> video_tracks) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (media_stream_)
+ media_stream_->OnChanged(audio_tracks.Pass(), video_tracks.Pass());
+}
+
+// Called on the signaling thread.
+RemoteMediaStreamImpl::RemoteMediaStreamImpl(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::MediaStreamInterface* webrtc_stream)
+ : signaling_thread_(base::ThreadTaskRunnerHandle::Get()),
+ weak_factory_(this),
+ observer_(new RemoteMediaStreamImpl::Observer(weak_factory_.GetWeakPtr(),
+ main_thread, webrtc_stream)) {
+ CreateAdaptersForTracks(webrtc_stream->GetAudioTracks(),
+ &audio_track_observers_, main_thread);
+ CreateAdaptersForTracks(webrtc_stream->GetVideoTracks(),
+ &video_track_observers_, main_thread);
+
+ main_thread->PostTask(FROM_HERE,
+ base::Bind(&RemoteMediaStreamImpl::Observer::InitializeOnMainThread,
+ observer_, webrtc_stream->label()));
+}
+
+RemoteMediaStreamImpl::~RemoteMediaStreamImpl() {
+ DCHECK(observer_->main_thread()->BelongsToCurrentThread());
+ for (auto& track : audio_track_observers_)
+ track->Unregister();
+ observer_->Unregister();
+}
+
+void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label) {
+ DCHECK(observer_->main_thread()->BelongsToCurrentThread());
blink::WebVector<blink::WebMediaStreamTrack> webkit_audio_tracks(
- webrtc_audio_tracks.size());
-
- // Initialize WebKit audio tracks.
- size_t i = 0;
- for (; i < webrtc_audio_tracks.size(); ++i) {
- webrtc::AudioTrackInterface* audio_track = webrtc_audio_tracks[i];
- DCHECK(audio_track);
- InitializeWebkitTrack(audio_track, &webkit_audio_tracks[i],
- blink::WebMediaStreamSource::TypeAudio);
- audio_track_observers_.push_back(
- new RemoteAudioMediaStreamTrackAdapter(audio_track,
- webkit_audio_tracks[i]));
+ audio_track_observers_.size());
+ for (size_t i = 0; i < audio_track_observers_.size(); ++i) {
+ audio_track_observers_[i]->Initialize();
+ webkit_audio_tracks[i] = *audio_track_observers_[i]->webkit_track();
}
- // Initialize WebKit video tracks.
- webrtc::VideoTrackVector webrtc_video_tracks =
- webrtc_stream_->GetVideoTracks();
blink::WebVector<blink::WebMediaStreamTrack> webkit_video_tracks(
- webrtc_video_tracks.size());
- for (i = 0; i < webrtc_video_tracks.size(); ++i) {
- webrtc::VideoTrackInterface* video_track = webrtc_video_tracks[i];
- DCHECK(video_track);
- InitializeWebkitTrack(video_track, &webkit_video_tracks[i],
- blink::WebMediaStreamSource::TypeVideo);
- video_track_observers_.push_back(
- new RemoteMediaStreamTrackAdapter(video_track,
- webkit_video_tracks[i]));
+ video_track_observers_.size());
+ for (size_t i = 0; i < video_track_observers_.size(); ++i) {
+ video_track_observers_[i]->Initialize();
+ webkit_video_tracks[i] = *video_track_observers_[i]->webkit_track();
}
- webkit_stream_.initialize(base::UTF8ToUTF16(webrtc_stream->label()),
+ webkit_stream_.initialize(base::UTF8ToUTF16(label),
webkit_audio_tracks, webkit_video_tracks);
- webkit_stream_.setExtraData(new MediaStream(webrtc_stream));
-}
-
-RemoteMediaStreamImpl::~RemoteMediaStreamImpl() {
- webrtc_stream_->UnregisterObserver(this);
+ webkit_stream_.setExtraData(new MediaStream(observer_->stream().get()));
}
-void RemoteMediaStreamImpl::OnChanged() {
- // Find removed audio tracks.
- ScopedVector<RemoteMediaStreamTrackAdapter>::iterator audio_it =
- audio_track_observers_.begin();
+void RemoteMediaStreamImpl::OnChanged(
+ scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ scoped_ptr<RemoteVideoTrackAdapters> video_tracks) {
+ // Find removed tracks.
+ auto audio_it = audio_track_observers_.begin();
while (audio_it != audio_track_observers_.end()) {
- std::string track_id = (*audio_it)->observed_track()->id();
- if (webrtc_stream_->FindAudioTrack(track_id) == NULL) {
- webkit_stream_.removeTrack((*audio_it)->webkit_track());
+ if (!IsTrackInVector(*audio_tracks.get(), (*audio_it)->id())) {
+ (*audio_it)->Unregister();
+ webkit_stream_.removeTrack(*(*audio_it)->webkit_track());
audio_it = audio_track_observers_.erase(audio_it);
} else {
++audio_it;
}
}
- // Find removed video tracks.
- ScopedVector<RemoteMediaStreamTrackAdapter>::iterator video_it =
- video_track_observers_.begin();
+ auto video_it = video_track_observers_.begin();
while (video_it != video_track_observers_.end()) {
- std::string track_id = (*video_it)->observed_track()->id();
- if (webrtc_stream_->FindVideoTrack(track_id) == NULL) {
- webkit_stream_.removeTrack((*video_it)->webkit_track());
+ if (!IsTrackInVector(*video_tracks.get(), (*video_it)->id())) {
+ webkit_stream_.removeTrack(*(*video_it)->webkit_track());
video_it = video_track_observers_.erase(video_it);
} else {
++video_it;
}
}
- // Find added audio tracks.
- webrtc::AudioTrackVector webrtc_audio_tracks =
- webrtc_stream_->GetAudioTracks();
- for (webrtc::AudioTrackVector::iterator it = webrtc_audio_tracks.begin();
- it != webrtc_audio_tracks.end(); ++it) {
- if (!FindTrackObserver(*it, audio_track_observers_)) {
- blink::WebMediaStreamTrack new_track;
- InitializeWebkitTrack(*it, &new_track,
- blink::WebMediaStreamSource::TypeAudio);
- audio_track_observers_.push_back(
- new RemoteAudioMediaStreamTrackAdapter(*it, new_track));
- webkit_stream_.addTrack(new_track);
+ // Find added tracks.
+ for (auto& track : *audio_tracks.get()) {
+ if (!IsTrackInVector(audio_track_observers_, track->id())) {
+ track->Initialize();
+ audio_track_observers_.push_back(track);
+ webkit_stream_.addTrack(*track->webkit_track());
+ // Set the track to null to avoid unregistering it below now that it's
+ // been associated with a media stream.
+ track = nullptr;
}
}
// Find added video tracks.
- webrtc::VideoTrackVector webrtc_video_tracks =
- webrtc_stream_->GetVideoTracks();
- for (webrtc::VideoTrackVector::iterator it = webrtc_video_tracks.begin();
- it != webrtc_video_tracks.end(); ++it) {
- if (!FindTrackObserver(*it, video_track_observers_)) {
- blink::WebMediaStreamTrack new_track;
- InitializeWebkitTrack(*it, &new_track,
- blink::WebMediaStreamSource::TypeVideo);
- video_track_observers_.push_back(
- new RemoteMediaStreamTrackAdapter(*it, new_track));
- webkit_stream_.addTrack(new_track);
+ for (const auto& track : *video_tracks.get()) {
+ if (!IsTrackInVector(video_track_observers_, track->id())) {
+ track->Initialize();
+ video_track_observers_.push_back(track);
+ webkit_stream_.addTrack(*track->webkit_track());
}
}
+
+ // Unregister all the audio track observers that were not used.
+ // We need to do this before destruction since the observers can't unregister
+ // from within the dtor due to a race.
+ for (auto& track : *audio_tracks.get()) {
+ if (track.get())
+ track->Unregister();
+ }
}
} // namespace content
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.h b/chromium/content/renderer/media/remote_media_stream_impl.h
index 6b1554aff06..0c230bac73f 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.h
+++ b/chromium/content/renderer/media/remote_media_stream_impl.h
@@ -8,8 +8,10 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_vector.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
@@ -18,29 +20,82 @@
namespace content {
-class RemoteMediaStreamTrackAdapter;
+class RemoteAudioTrackAdapter;
+class RemoteVideoTrackAdapter;
// RemoteMediaStreamImpl serves as a container and glue between remote webrtc
// MediaStreams and WebKit MediaStreams. For each remote MediaStream received
// on a PeerConnection a RemoteMediaStreamImpl instance is created and
// owned by RtcPeerConnection.
-class CONTENT_EXPORT RemoteMediaStreamImpl
- : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
- NON_EXPORTED_BASE(public base::NonThreadSafe) {
+class CONTENT_EXPORT RemoteMediaStreamImpl {
public:
- explicit RemoteMediaStreamImpl(
+ RemoteMediaStreamImpl(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::MediaStreamInterface* webrtc_stream);
- virtual ~RemoteMediaStreamImpl();
+ ~RemoteMediaStreamImpl();
const blink::WebMediaStream& webkit_stream() { return webkit_stream_; }
+ const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() {
+ return observer_->stream();
+ }
private:
- // webrtc::ObserverInterface implementation.
- virtual void OnChanged() OVERRIDE;
+ typedef std::vector<scoped_refptr<RemoteAudioTrackAdapter>>
+ RemoteAudioTrackAdapters;
+ typedef std::vector<scoped_refptr<RemoteVideoTrackAdapter>>
+ RemoteVideoTrackAdapters;
- scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
- ScopedVector<RemoteMediaStreamTrackAdapter> video_track_observers_;
- ScopedVector<RemoteMediaStreamTrackAdapter> audio_track_observers_;
+ void InitializeOnMainThread(const std::string& label);
+
+ class Observer
+ : NON_EXPORTED_BASE(public webrtc::ObserverInterface),
+ public base::RefCountedThreadSafe<Observer> {
+ public:
+ Observer(const base::WeakPtr<RemoteMediaStreamImpl>& media_stream,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::MediaStreamInterface* webrtc_stream);
+
+ const scoped_refptr<webrtc::MediaStreamInterface>& stream() const {
+ return webrtc_stream_;
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread() const {
+ return main_thread_;
+ }
+
+ void InitializeOnMainThread(const std::string& label);
+
+ // Uninitializes the observer, unregisteres from receiving notifications
+ // and releases the webrtc stream.
+ // Note: Must be called from the main thread before releasing the main
+ // reference.
+ void Unregister();
+
+ private:
+ friend class base::RefCountedThreadSafe<Observer>;
+ ~Observer() override;
+
+ // webrtc::ObserverInterface implementation.
+ void OnChanged() override;
+
+ void OnChangedOnMainThread(
+ scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ scoped_ptr<RemoteVideoTrackAdapters> video_tracks);
+
+ base::WeakPtr<RemoteMediaStreamImpl> media_stream_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
+ };
+
+ void OnChanged(scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ scoped_ptr<RemoteVideoTrackAdapters> video_tracks);
+
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
+ base::WeakPtrFactory<RemoteMediaStreamImpl> weak_factory_;
+ const scoped_refptr<Observer> observer_; // must be after weak_factory_
+
+ RemoteVideoTrackAdapters video_track_observers_;
+ RemoteAudioTrackAdapters audio_track_observers_;
blink::WebMediaStream webkit_stream_;
DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamImpl);
diff --git a/chromium/content/renderer/media/render_media_log.h b/chromium/content/renderer/media/render_media_log.h
index 9aac107c4c6..dbadfa5e5f1 100644
--- a/chromium/content/renderer/media/render_media_log.h
+++ b/chromium/content/renderer/media/render_media_log.h
@@ -27,13 +27,13 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
RenderMediaLog();
// MediaLog implementation.
- virtual void AddEvent(scoped_ptr<media::MediaLogEvent> event) OVERRIDE;
+ void AddEvent(scoped_ptr<media::MediaLogEvent> event) override;
// Will reset |last_ipc_send_time_| with the value of NowTicks().
void SetTickClockForTesting(scoped_ptr<base::TickClock> tick_clock);
private:
- virtual ~RenderMediaLog();
+ ~RenderMediaLog() override;
scoped_refptr<base::MessageLoopProxy> render_loop_;
scoped_ptr<base::TickClock> tick_clock_;
diff --git a/chromium/content/renderer/media/render_media_log_unittest.cc b/chromium/content/renderer/media/render_media_log_unittest.cc
index 83708aa49e2..a5d25cee3d6 100644
--- a/chromium/content/renderer/media/render_media_log_unittest.cc
+++ b/chromium/content/renderer/media/render_media_log_unittest.cc
@@ -18,7 +18,7 @@ class RenderMediaLogTest : public testing::Test {
log_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
}
- virtual ~RenderMediaLogTest() {}
+ ~RenderMediaLogTest() override {}
void AddEvent(media::MediaLogEvent::Type type) {
log_->AddEvent(log_->CreateEvent(type));
diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
index 94e0d78217f..ab3d2f76c2a 100644
--- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
+++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -10,7 +10,9 @@
#include "base/bind.h"
#include "content/child/child_thread.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
@@ -25,14 +27,14 @@ namespace content {
scoped_refptr<RendererGpuVideoAcceleratorFactories>
RendererGpuVideoAcceleratorFactories::Create(
GpuChannelHost* gpu_channel_host,
- const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider) {
scoped_refptr<RendererGpuVideoAcceleratorFactories> factories =
new RendererGpuVideoAcceleratorFactories(
- gpu_channel_host, message_loop_proxy, context_provider);
+ gpu_channel_host, task_runner, context_provider);
// Post task from outside constructor, since AddRef()/Release() is unsafe from
// within.
- message_loop_proxy->PostTask(
+ task_runner->PostTask(
FROM_HERE,
base::Bind(&RendererGpuVideoAcceleratorFactories::BindContext,
factories));
@@ -41,9 +43,9 @@ RendererGpuVideoAcceleratorFactories::Create(
RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
GpuChannelHost* gpu_channel_host,
- const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
- : task_runner_(message_loop_proxy),
+ : task_runner_(task_runner),
gpu_channel_host_(gpu_channel_host),
context_provider_(context_provider),
thread_safe_sender_(ChildThread::current()->thread_safe_sender()) {}
@@ -59,16 +61,29 @@ void RendererGpuVideoAcceleratorFactories::BindContext() {
WebGraphicsContext3DCommandBufferImpl*
RendererGpuVideoAcceleratorFactories::GetContext3d() {
DCHECK(task_runner_->BelongsToCurrentThread());
- if (!context_provider_)
+ if (!context_provider_.get())
return NULL;
if (context_provider_->IsContextLost()) {
context_provider_->VerifyContexts();
context_provider_ = NULL;
+ gl_helper_.reset(NULL);
return NULL;
}
return context_provider_->WebContext3D();
}
+GLHelper* RendererGpuVideoAcceleratorFactories::GetGLHelper() {
+ if (!GetContext3d())
+ return NULL;
+
+ if (gl_helper_.get() == NULL) {
+ gl_helper_.reset(new GLHelper(GetContext3d()->GetImplementation(),
+ GetContext3d()->GetContextSupport()));
+ }
+
+ return gl_helper_.get();
+}
+
scoped_ptr<media::VideoDecodeAccelerator>
RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
DCHECK(task_runner_->BelongsToCurrentThread());
@@ -178,59 +193,29 @@ void RendererGpuVideoAcceleratorFactories::ReadPixels(
const SkBitmap& pixels) {
DCHECK(task_runner_->BelongsToCurrentThread());
+ GLHelper* gl_helper = GetGLHelper();
WebGraphicsContext3DCommandBufferImpl* context = GetContext3d();
- if (!context)
- return;
- gpu::gles2::GLES2Implementation* gles2 = context->GetImplementation();
+ if (!gl_helper || !context)
+ return;
+ // Copy texture from texture_id to tmp_texture as texture might be external
+ // (GL_TEXTURE_EXTERNAL_OES)
GLuint tmp_texture;
- gles2->GenTextures(1, &tmp_texture);
- gles2->BindTexture(GL_TEXTURE_2D, tmp_texture);
- gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gles2->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ tmp_texture = gl_helper->CreateTexture();
context->copyTextureCHROMIUM(
GL_TEXTURE_2D, texture_id, tmp_texture, 0, GL_RGBA, GL_UNSIGNED_BYTE);
- GLuint fb;
- gles2->GenFramebuffers(1, &fb);
- gles2->BindFramebuffer(GL_FRAMEBUFFER, fb);
- gles2->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0);
- gles2->PixelStorei(GL_PACK_ALIGNMENT, 4);
-
-#if SK_B32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_R32_SHIFT == 16 && \
- SK_A32_SHIFT == 24
- GLenum skia_format = GL_BGRA_EXT;
- GLenum read_format = GL_BGRA_EXT;
- GLint supported_format = 0;
- GLint supported_type = 0;
- gles2->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &supported_format);
- gles2->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &supported_type);
- if (supported_format != GL_BGRA_EXT || supported_type != GL_UNSIGNED_BYTE) {
- read_format = GL_RGBA;
- }
-#elif SK_R32_SHIFT == 0 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 16 && \
- SK_A32_SHIFT == 24
- GLenum skia_format = GL_RGBA;
- GLenum read_format = GL_RGBA;
-#else
-#error Unexpected Skia ARGB_8888 layout!
-#endif
- gles2->ReadPixels(visible_rect.x(),
- visible_rect.y(),
- visible_rect.width(),
- visible_rect.height(),
- read_format,
- GL_UNSIGNED_BYTE,
- pixels.pixelRef()->pixels());
- gles2->DeleteFramebuffers(1, &fb);
- gles2->DeleteTextures(1, &tmp_texture);
-
- if (skia_format != read_format) {
- DCHECK(read_format == GL_RGBA);
+ unsigned char* pixel_data =
+ static_cast<unsigned char*>(pixels.pixelRef()->pixels());
+
+ if (gl_helper->IsReadbackConfigSupported(pixels.colorType())) {
+ gl_helper->ReadbackTextureSync(
+ tmp_texture, visible_rect, pixel_data, pixels.colorType());
+ } else if (pixels.colorType() == kN32_SkColorType) {
+ gl_helper->ReadbackTextureSync(
+ tmp_texture, visible_rect, pixel_data, kRGBA_8888_SkColorType);
+
int pixel_count = visible_rect.width() * visible_rect.height();
uint32_t* pixels_ptr = static_cast<uint32_t*>(pixels.pixelRef()->pixels());
for (int i = 0; i < pixel_count; ++i) {
@@ -243,9 +228,11 @@ void RendererGpuVideoAcceleratorFactories::ReadPixels(
(b << SK_B32_SHIFT) |
(a << SK_A32_SHIFT);
}
+ } else {
+ NOTREACHED();
}
- DCHECK_EQ(gles2->GetError(), static_cast<GLenum>(GL_NO_ERROR));
+ gl_helper->DeleteTexture(tmp_texture);
}
base::SharedMemory* RendererGpuVideoAcceleratorFactories::CreateSharedMemory(
@@ -259,4 +246,12 @@ RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
return task_runner_;
}
+std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+RendererGpuVideoAcceleratorFactories::
+ GetVideoEncodeAcceleratorSupportedProfiles() {
+ return GpuVideoEncodeAcceleratorHost::ConvertGpuToMediaProfiles(
+ gpu_channel_host_->gpu_info()
+ .video_encode_accelerator_supported_profiles);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
index ffbc0abe664..47232307f27 100644
--- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
+++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
@@ -22,6 +22,7 @@ class WaitableEvent;
namespace content {
class ContextProviderCommandBuffer;
+class GLHelper;
class GpuChannelHost;
class WebGraphicsContext3DCommandBufferImpl;
@@ -32,7 +33,7 @@ class WebGraphicsContext3DCommandBufferImpl;
//
// The RendererGpuVideoAcceleratorFactories can be constructed on any thread,
// but subsequent calls to all public methods of the class must be called from
-// the |message_loop_proxy_|, as provided during construction.
+// the |task_runner_|, as provided during construction.
class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
: public media::GpuVideoAcceleratorFactories {
public:
@@ -40,36 +41,38 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
// use. Safe to call from any thread.
static scoped_refptr<RendererGpuVideoAcceleratorFactories> Create(
GpuChannelHost* gpu_channel_host,
- const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider);
// media::GpuVideoAcceleratorFactories implementation.
- virtual scoped_ptr<media::VideoDecodeAccelerator>
- CreateVideoDecodeAccelerator() OVERRIDE;
- virtual scoped_ptr<media::VideoEncodeAccelerator>
- CreateVideoEncodeAccelerator() OVERRIDE;
+ scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
+ override;
+ scoped_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
+ override;
// Creates textures and produces them into mailboxes. Returns true on success
// or false on failure.
- virtual bool CreateTextures(int32 count,
- const gfx::Size& size,
- std::vector<uint32>* texture_ids,
- std::vector<gpu::Mailbox>* texture_mailboxes,
- uint32 texture_target) OVERRIDE;
- virtual void DeleteTexture(uint32 texture_id) OVERRIDE;
- virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE;
- virtual void ReadPixels(uint32 texture_id,
- const gfx::Rect& visible_rect,
- const SkBitmap& pixels) OVERRIDE;
- virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
- virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() OVERRIDE;
+ bool CreateTextures(int32 count,
+ const gfx::Size& size,
+ std::vector<uint32>* texture_ids,
+ std::vector<gpu::Mailbox>* texture_mailboxes,
+ uint32 texture_target) override;
+ void DeleteTexture(uint32 texture_id) override;
+ void WaitSyncPoint(uint32 sync_point) override;
+ void ReadPixels(uint32 texture_id,
+ const gfx::Rect& visible_rect,
+ const SkBitmap& pixels) override;
+ base::SharedMemory* CreateSharedMemory(size_t size) override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
+ std::vector<media::VideoEncodeAccelerator::SupportedProfile>
+ GetVideoEncodeAcceleratorSupportedProfiles() override;
private:
friend class base::RefCountedThreadSafe<RendererGpuVideoAcceleratorFactories>;
RendererGpuVideoAcceleratorFactories(
GpuChannelHost* gpu_channel_host,
- const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider);
- virtual ~RendererGpuVideoAcceleratorFactories();
+ ~RendererGpuVideoAcceleratorFactories() override;
// Helper to bind |context_provider| to the |task_runner_| thread after
// construction.
@@ -78,10 +81,12 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
// Helper to get a pointer to the WebGraphicsContext3DCommandBufferImpl,
// if it has not been lost yet.
WebGraphicsContext3DCommandBufferImpl* GetContext3d();
+ GLHelper* GetGLHelper();
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_refptr<GpuChannelHost> gpu_channel_host_;
scoped_refptr<ContextProviderCommandBuffer> context_provider_;
+ scoped_ptr<GLHelper> gl_helper_;
// For sending requests to allocate shared memory in the Browser process.
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
index 0f06a89aa94..03817fca750 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -33,10 +33,9 @@ class RendererWebAudioDeviceImpl
virtual double sampleRate();
// AudioRendererSink::RenderCallback implementation.
- virtual int Render(media::AudioBus* dest,
- int audio_delay_milliseconds) OVERRIDE;
+ int Render(media::AudioBus* dest, int audio_delay_milliseconds) override;
- virtual void OnRenderError() OVERRIDE;
+ void OnRenderError() override;
private:
const media::AudioParameters params_;
diff --git a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc
index 75b6b972005..b67f48a7ae6 100644
--- a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc
+++ b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.cc
@@ -21,7 +21,7 @@ RendererWebMIDIAccessorImpl::~RendererWebMIDIAccessorImpl() {
}
void RendererWebMIDIAccessorImpl::startSession() {
- midi_message_filter()->StartSession(client_);
+ midi_message_filter()->AddClient(client_);
}
void RendererWebMIDIAccessorImpl::sendMIDIData(
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.cc b/chromium/content/renderer/media/rtc_data_channel_handler.cc
index 1fe4de11756..084a02018cb 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler.cc
+++ b/chromium/content/renderer/media/rtc_data_channel_handler.cc
@@ -7,9 +7,13 @@
#include <limits>
#include <string>
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
namespace content {
@@ -32,101 +36,197 @@ void IncrementCounter(DataChannelCounters counter) {
} // namespace
+// Implementation of DataChannelObserver that receives events on libjingle's
+// signaling thread and forwards them over to the main thread for handling.
+// Since the handler's lifetime is scoped potentially narrower than what
+// the callbacks allow for, we use reference counting here to make sure
+// all callbacks have a valid pointer but won't do anything if the handler
+// has gone away.
+RtcDataChannelHandler::Observer::Observer(
+ RtcDataChannelHandler* handler,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::DataChannelInterface* channel)
+ : handler_(handler), main_thread_(main_thread), channel_(channel) {
+ channel_->RegisterObserver(this);
+}
+
+RtcDataChannelHandler::Observer::~Observer() {}
+
+const scoped_refptr<base::SingleThreadTaskRunner>&
+RtcDataChannelHandler::Observer::main_thread() const {
+ return main_thread_;
+}
+
+const scoped_refptr<webrtc::DataChannelInterface>&
+RtcDataChannelHandler::Observer::channel() const {
+ return channel_;
+}
+
+void RtcDataChannelHandler::Observer::ClearHandler() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ handler_ = nullptr;
+}
+
+void RtcDataChannelHandler::Observer::OnStateChange() {
+ main_thread_->PostTask(FROM_HERE, base::Bind(
+ &RtcDataChannelHandler::Observer::OnStateChangeImpl, this,
+ channel_->state()));
+}
+
+void RtcDataChannelHandler::Observer::OnMessage(
+ const webrtc::DataBuffer& buffer) {
+ // TODO(tommi): Figure out a way to transfer ownership of the buffer without
+ // having to create a copy. See webrtc bug 3967.
+ scoped_ptr<webrtc::DataBuffer> new_buffer(new webrtc::DataBuffer(buffer));
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RtcDataChannelHandler::Observer::OnMessageImpl, this,
+ base::Passed(&new_buffer)));
+}
+
+void RtcDataChannelHandler::Observer::OnStateChangeImpl(
+ webrtc::DataChannelInterface::DataState state) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (handler_)
+ handler_->OnStateChange(state);
+}
+
+void RtcDataChannelHandler::Observer::OnMessageImpl(
+ scoped_ptr<webrtc::DataBuffer> buffer) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (handler_)
+ handler_->OnMessage(buffer.Pass());
+}
+
RtcDataChannelHandler::RtcDataChannelHandler(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::DataChannelInterface* channel)
- : channel_(channel),
+ : observer_(new Observer(this, main_thread, channel)),
webkit_client_(NULL) {
- DVLOG(1) << "::ctor";
- channel_->RegisterObserver(this);
+ DVLOG(1) << "RtcDataChannelHandler " << channel->label();
+
+ // Detach from the ctor thread since we can be constructed on either the main
+ // or signaling threads.
+ thread_checker_.DetachFromThread();
IncrementCounter(CHANNEL_CREATED);
- if (isReliable())
+ if (channel->reliable())
IncrementCounter(CHANNEL_RELIABLE);
- if (ordered())
+ if (channel->ordered())
IncrementCounter(CHANNEL_ORDERED);
- if (negotiated())
+ if (channel->negotiated())
IncrementCounter(CHANNEL_NEGOTIATED);
UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmits",
- maxRetransmits(), 0,
+ channel->maxRetransmits(), 0,
std::numeric_limits<unsigned short>::max(), 50);
UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.DataChannelMaxRetransmitTime",
- maxRetransmitTime(), 0,
+ channel->maxRetransmitTime(), 0,
std::numeric_limits<unsigned short>::max(), 50);
}
RtcDataChannelHandler::~RtcDataChannelHandler() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "::dtor";
- channel_->UnregisterObserver();
+ observer_->ClearHandler();
}
void RtcDataChannelHandler::setClient(
blink::WebRTCDataChannelHandlerClient* client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
webkit_client_ = client;
}
blink::WebString RtcDataChannelHandler::label() {
- return base::UTF8ToUTF16(channel_->label());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return base::UTF8ToUTF16(channel()->label());
}
bool RtcDataChannelHandler::isReliable() {
- return channel_->reliable();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->reliable();
}
bool RtcDataChannelHandler::ordered() const {
- return channel_->ordered();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->ordered();
}
unsigned short RtcDataChannelHandler::maxRetransmitTime() const {
- return channel_->maxRetransmitTime();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->maxRetransmitTime();
}
unsigned short RtcDataChannelHandler::maxRetransmits() const {
- return channel_->maxRetransmits();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->maxRetransmits();
}
blink::WebString RtcDataChannelHandler::protocol() const {
- return base::UTF8ToUTF16(channel_->protocol());
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return base::UTF8ToUTF16(channel()->protocol());
}
bool RtcDataChannelHandler::negotiated() const {
- return channel_->negotiated();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->negotiated();
}
unsigned short RtcDataChannelHandler::id() const {
- return channel_->id();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->id();
}
unsigned long RtcDataChannelHandler::bufferedAmount() {
- return channel_->buffered_amount();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return channel()->buffered_amount();
}
bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) {
+ DCHECK(thread_checker_.CalledOnValidThread());
std::string utf8_buffer = base::UTF16ToUTF8(data);
- talk_base::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length());
+ rtc::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length());
webrtc::DataBuffer data_buffer(buffer, false);
RecordMessageSent(data_buffer.size());
- return channel_->Send(data_buffer);
+ return channel()->Send(data_buffer);
}
bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) {
- talk_base::Buffer buffer(data, length);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ rtc::Buffer buffer(data, length);
webrtc::DataBuffer data_buffer(buffer, true);
RecordMessageSent(data_buffer.size());
- return channel_->Send(data_buffer);
+ return channel()->Send(data_buffer);
}
void RtcDataChannelHandler::close() {
- channel_->Close();
+ DCHECK(thread_checker_.CalledOnValidThread());
+ channel()->Close();
+ // Note that even though Close() will run synchronously, the readyState has
+ // not changed yet since the state changes that occured on the signaling
+ // thread have been posted to this thread and will be delivered later.
+ // To work around this, we could have a nested loop here and deliver the
+ // callbacks before running from this function, but doing so can cause
+ // undesired side effects in webkit, so we don't, and instead rely on the
+ // user of the API handling readyState notifications.
+}
+
+const scoped_refptr<webrtc::DataChannelInterface>&
+RtcDataChannelHandler::channel() const {
+ return observer_->channel();
}
-void RtcDataChannelHandler::OnStateChange() {
+void RtcDataChannelHandler::OnStateChange(
+ webrtc::DataChannelInterface::DataState state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "OnStateChange " << state;
+
if (!webkit_client_) {
- LOG(ERROR) << "WebRTCDataChannelHandlerClient not set.";
+ // If this happens, the web application will not get notified of changes.
+ NOTREACHED() << "WebRTCDataChannelHandlerClient not set.";
return;
}
- DVLOG(1) << "OnStateChange " << channel_->state();
- switch (channel_->state()) {
+
+ switch (state) {
case webrtc::DataChannelInterface::kConnecting:
webkit_client_->didChangeReadyState(
blink::WebRTCDataChannelHandlerClient::ReadyStateConnecting);
@@ -150,17 +250,21 @@ void RtcDataChannelHandler::OnStateChange() {
}
}
-void RtcDataChannelHandler::OnMessage(const webrtc::DataBuffer& buffer) {
+void RtcDataChannelHandler::OnMessage(scoped_ptr<webrtc::DataBuffer> buffer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!webkit_client_) {
- LOG(ERROR) << "WebRTCDataChannelHandlerClient not set.";
+ // If this happens, the web application will not get notified of changes.
+ NOTREACHED() << "WebRTCDataChannelHandlerClient not set.";
return;
}
- if (buffer.binary) {
- webkit_client_->didReceiveRawData(buffer.data.data(), buffer.data.length());
+ if (buffer->binary) {
+ webkit_client_->didReceiveRawData(buffer->data.data(),
+ buffer->data.length());
} else {
base::string16 utf16;
- if (!base::UTF8ToUTF16(buffer.data.data(), buffer.data.length(), &utf16)) {
+ if (!base::UTF8ToUTF16(buffer->data.data(), buffer->data.length(),
+ &utf16)) {
LOG(ERROR) << "Failed convert received data to UTF16";
return;
}
@@ -181,7 +285,7 @@ void RtcDataChannelHandler::RecordMessageSent(size_t num_bytes) {
const int kMaxBucketSize = 100 * 1024 * 1024;
const int kNumBuckets = 50;
- if (isReliable()) {
+ if (channel()->reliable()) {
UMA_HISTOGRAM_CUSTOM_COUNTS("WebRTC.ReliableDataChannelMessageSize",
num_bytes,
1, kMaxBucketSize, kNumBuckets);
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.h b/chromium/content/renderer/media/rtc_data_channel_handler.h
index 1be7e87dd01..79addde1728 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler.h
+++ b/chromium/content/renderer/media/rtc_data_channel_handler.h
@@ -6,7 +6,9 @@
#define CONTENT_RENDERER_MEDIA_RTC_DATA_CHANNEL_HANDLER_H_
#include "base/memory/ref_counted.h"
-#include "base/threading/non_thread_safe.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelHandler.h"
@@ -21,37 +23,78 @@ namespace content {
// Callbacks to the webrtc::DataChannelObserver implementation also occur on
// the main render thread.
class CONTENT_EXPORT RtcDataChannelHandler
- : NON_EXPORTED_BASE(public blink::WebRTCDataChannelHandler),
- NON_EXPORTED_BASE(public webrtc::DataChannelObserver),
- NON_EXPORTED_BASE(public base::NonThreadSafe) {
+ : NON_EXPORTED_BASE(public blink::WebRTCDataChannelHandler) {
public:
- explicit RtcDataChannelHandler(webrtc::DataChannelInterface* channel);
+ // This object can* be constructed on libjingle's signaling thread and then
+ // ownership is passed to the UI thread where it's eventually given to WebKit.
+ // The reason we must construct and hook ourselves up as an observer on the
+ // signaling thread is to avoid missing out on any state changes or messages
+ // that may occur before we've fully connected with webkit.
+ // This period is basically between when the ctor is called and until
+ // setClient is called.
+ // * For local data channels, the object will be construced on the main thread
+ // and we don't have the issue described above.
+ RtcDataChannelHandler(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::DataChannelInterface* channel);
virtual ~RtcDataChannelHandler();
// blink::WebRTCDataChannelHandler implementation.
virtual void setClient(
- blink::WebRTCDataChannelHandlerClient* client) OVERRIDE;
- virtual blink::WebString label() OVERRIDE;
- virtual bool isReliable() OVERRIDE;
- virtual bool ordered() const OVERRIDE;
- virtual unsigned short maxRetransmitTime() const OVERRIDE;
- virtual unsigned short maxRetransmits() const OVERRIDE;
- virtual blink::WebString protocol() const OVERRIDE;
- virtual bool negotiated() const OVERRIDE;
- virtual unsigned short id() const OVERRIDE;
- virtual unsigned long bufferedAmount() OVERRIDE;
- virtual bool sendStringData(const blink::WebString& data) OVERRIDE;
- virtual bool sendRawData(const char* data, size_t length) OVERRIDE;
- virtual void close() OVERRIDE;
-
- // webrtc::DataChannelObserver implementation.
- virtual void OnStateChange() OVERRIDE;
- virtual void OnMessage(const webrtc::DataBuffer& buffer) OVERRIDE;
+ blink::WebRTCDataChannelHandlerClient* client) override;
+ virtual blink::WebString label() override;
+ virtual bool isReliable() override;
+ virtual bool ordered() const override;
+ virtual unsigned short maxRetransmitTime() const override;
+ virtual unsigned short maxRetransmits() const override;
+ virtual blink::WebString protocol() const override;
+ virtual bool negotiated() const override;
+ virtual unsigned short id() const override;
+ virtual unsigned long bufferedAmount() override;
+ virtual bool sendStringData(const blink::WebString& data) override;
+ virtual bool sendRawData(const char* data, size_t length) override;
+ virtual void close() override;
+
+ const scoped_refptr<webrtc::DataChannelInterface>& channel() const;
private:
+ void OnStateChange(webrtc::DataChannelInterface::DataState state);
+ void OnMessage(scoped_ptr<webrtc::DataBuffer> buffer);
void RecordMessageSent(size_t num_bytes);
- scoped_refptr<webrtc::DataChannelInterface> channel_;
+ class CONTENT_EXPORT Observer
+ : public NON_EXPORTED_BASE(
+ base::RefCountedThreadSafe<RtcDataChannelHandler::Observer>),
+ public NON_EXPORTED_BASE(webrtc::DataChannelObserver) {
+ public:
+ Observer(RtcDataChannelHandler* handler,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::DataChannelInterface* channel);
+
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread() const;
+ const scoped_refptr<webrtc::DataChannelInterface>& channel() const;
+
+ void ClearHandler();
+
+ private:
+ friend class base::RefCountedThreadSafe<RtcDataChannelHandler::Observer>;
+ ~Observer() override;
+
+ // webrtc::DataChannelObserver implementation.
+ void OnStateChange() override;
+ void OnMessage(const webrtc::DataBuffer& buffer) override;
+
+ void OnStateChangeImpl(webrtc::DataChannelInterface::DataState state);
+ void OnMessageImpl(scoped_ptr<webrtc::DataBuffer> buffer);
+
+ RtcDataChannelHandler* handler_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ const scoped_refptr<webrtc::DataChannelInterface> channel_;
+ };
+
+ scoped_refptr<Observer> observer_;
+ base::ThreadChecker thread_checker_;
+
blink::WebRTCDataChannelHandlerClient* webkit_client_;
};
diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc b/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc
index 23c5cc18f88..3aea3d15fe0 100644
--- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc
+++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.cc
@@ -6,18 +6,53 @@
#include <string>
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_checker.h"
using webrtc::DtmfSenderInterface;
namespace content {
+class RtcDtmfSenderHandler::Observer :
+ public base::RefCountedThreadSafe<Observer>,
+ public webrtc::DtmfSenderObserverInterface {
+ public:
+ explicit Observer(const base::WeakPtr<RtcDtmfSenderHandler>& handler)
+ : main_thread_(base::MessageLoopProxy::current()), handler_(handler) {}
+
+ private:
+ friend class base::RefCountedThreadSafe<Observer>;
+
+ ~Observer() override {}
+
+ void OnToneChange(const std::string& tone) override {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RtcDtmfSenderHandler::Observer::OnToneChangeOnMainThread,
+ this, tone));
+ }
+
+ void OnToneChangeOnMainThread(const std::string& tone) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (handler_)
+ handler_->OnToneChange(tone);
+ }
+
+ base::ThreadChecker thread_checker_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ base::WeakPtr<RtcDtmfSenderHandler> handler_;
+};
+
RtcDtmfSenderHandler::RtcDtmfSenderHandler(DtmfSenderInterface* dtmf_sender)
: dtmf_sender_(dtmf_sender),
- webkit_client_(NULL) {
+ webkit_client_(NULL),
+ weak_factory_(this),
+ observer_(new Observer(weak_factory_.GetWeakPtr())) {
DVLOG(1) << "::ctor";
- dtmf_sender_->RegisterObserver(this);
+ dtmf_sender_->RegisterObserver(observer_.get());
}
RtcDtmfSenderHandler::~RtcDtmfSenderHandler() {
diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
index 3f77525fb5e..eecad4b898e 100644
--- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
+++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebRTCDTMFSenderHandler.h"
@@ -24,26 +25,29 @@ namespace content {
// occur on the main render thread.
class CONTENT_EXPORT RtcDtmfSenderHandler
: NON_EXPORTED_BASE(public blink::WebRTCDTMFSenderHandler),
- NON_EXPORTED_BASE(public webrtc::DtmfSenderObserverInterface),
NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
explicit RtcDtmfSenderHandler(webrtc::DtmfSenderInterface* dtmf_sender);
virtual ~RtcDtmfSenderHandler();
// blink::WebRTCDTMFSenderHandler implementation.
- virtual void setClient(
- blink::WebRTCDTMFSenderHandlerClient* client) OVERRIDE;
- virtual blink::WebString currentToneBuffer() OVERRIDE;
- virtual bool canInsertDTMF() OVERRIDE;
- virtual bool insertDTMF(const blink::WebString& tones, long duration,
- long interToneGap) OVERRIDE;
+ void setClient(
+ blink::WebRTCDTMFSenderHandlerClient* client) override;
+ blink::WebString currentToneBuffer() override;
+ bool canInsertDTMF() override;
+ bool insertDTMF(const blink::WebString& tones, long duration,
+ long interToneGap) override;
- // webrtc::DtmfSenderObserverInterface implementation.
- virtual void OnToneChange(const std::string& tone) OVERRIDE;
+ void OnToneChange(const std::string& tone);
private:
scoped_refptr<webrtc::DtmfSenderInterface> dtmf_sender_;
blink::WebRTCDTMFSenderHandlerClient* webkit_client_;
+ base::WeakPtrFactory<RtcDtmfSenderHandler> weak_factory_;
+ class Observer;
+ scoped_refptr<Observer> observer_; // must be after weak_factory_
+
+ DISALLOW_COPY_AND_ASSIGN(RtcDtmfSenderHandler);
};
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_media_constraints.h b/chromium/content/renderer/media/rtc_media_constraints.h
index b1247363dc6..2c6ab27cef9 100644
--- a/chromium/content/renderer/media/rtc_media_constraints.h
+++ b/chromium/content/renderer/media/rtc_media_constraints.h
@@ -24,9 +24,9 @@ class CONTENT_EXPORT RTCMediaConstraints
RTCMediaConstraints();
explicit RTCMediaConstraints(
const blink::WebMediaConstraints& constraints);
- virtual ~RTCMediaConstraints();
- virtual const Constraints& GetMandatory() const OVERRIDE;
- virtual const Constraints& GetOptional() const OVERRIDE;
+ ~RTCMediaConstraints() override;
+ const Constraints& GetMandatory() const override;
+ const Constraints& GetOptional() const override;
// Adds a mandatory constraint, optionally overriding an existing one.
// If the constraint is already set and |override_if_exists| is false,
// the function will return false, otherwise true.
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
index b8c39be0ce6..54c500141b5 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
@@ -16,6 +16,7 @@
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/media_stream_track.h"
#include "content/renderer/media/peer_connection_tracker.h"
@@ -30,16 +31,26 @@
#include "content/renderer/media/webrtc_uma_histograms.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
#include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
+#include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
#include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
#include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
#include "third_party/WebKit/public/platform/WebURL.h"
+using webrtc::DataChannelInterface;
+using webrtc::IceCandidateInterface;
+using webrtc::MediaStreamInterface;
+using webrtc::PeerConnectionInterface;
+using webrtc::PeerConnectionObserver;
+using webrtc::StatsReport;
+using webrtc::StatsReportCopyable;
+using webrtc::StatsReports;
+
namespace content {
+namespace {
// Converter functions from libjingle types to WebKit types.
blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
@@ -59,7 +70,7 @@ GetWebKitIceGatheringState(
}
}
-static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
+blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
GetWebKitIceConnectionState(
webrtc::PeerConnectionInterface::IceConnectionState ice_state) {
using blink::WebRTCPeerConnectionHandlerClient;
@@ -84,7 +95,7 @@ GetWebKitIceConnectionState(
}
}
-static blink::WebRTCPeerConnectionHandlerClient::SignalingState
+blink::WebRTCPeerConnectionHandlerClient::SignalingState
GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
using blink::WebRTCPeerConnectionHandlerClient;
switch (state) {
@@ -107,32 +118,64 @@ GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) {
}
}
-static blink::WebRTCSessionDescription
+blink::WebRTCSessionDescription CreateWebKitSessionDescription(
+ const std::string& sdp, const std::string& type) {
+ blink::WebRTCSessionDescription description;
+ description.initialize(base::UTF8ToUTF16(type), base::UTF8ToUTF16(sdp));
+ return description;
+}
+
+blink::WebRTCSessionDescription
CreateWebKitSessionDescription(
const webrtc::SessionDescriptionInterface* native_desc) {
- blink::WebRTCSessionDescription description;
if (!native_desc) {
LOG(ERROR) << "Native session description is null.";
- return description;
+ return blink::WebRTCSessionDescription();
}
std::string sdp;
if (!native_desc->ToString(&sdp)) {
LOG(ERROR) << "Failed to get SDP string of native session description.";
- return description;
+ return blink::WebRTCSessionDescription();
}
- description.initialize(base::UTF8ToUTF16(native_desc->type()),
- base::UTF8ToUTF16(sdp));
- return description;
+ return CreateWebKitSessionDescription(sdp, native_desc->type());
+}
+
+void RunClosureWithTrace(const base::Closure& closure,
+ const char* trace_event_name) {
+ TRACE_EVENT0("webrtc", trace_event_name);
+ closure.Run();
+}
+
+void RunSynchronousClosure(const base::Closure& closure,
+ const char* trace_event_name,
+ base::WaitableEvent* event) {
+ {
+ TRACE_EVENT0("webrtc", trace_event_name);
+ closure.Run();
+ }
+ event->Signal();
+}
+
+void GetSdpAndTypeFromSessionDescription(
+ const base::Callback<const webrtc::SessionDescriptionInterface*()>&
+ description_callback,
+ std::string* sdp, std::string* type) {
+ const webrtc::SessionDescriptionInterface* description =
+ description_callback.Run();
+ if (description) {
+ description->ToString(sdp);
+ *type = description->type();
+ }
}
// Converter functions from WebKit types to libjingle types.
-static void GetNativeIceServers(
+void GetNativeRtcConfiguration(
const blink::WebRTCConfiguration& server_configuration,
- webrtc::PeerConnectionInterface::IceServers* servers) {
- if (server_configuration.isNull() || !servers)
+ webrtc::PeerConnectionInterface::RTCConfiguration* config) {
+ if (server_configuration.isNull() || !config)
return;
for (size_t i = 0; i < server_configuration.numberOfServers(); ++i) {
webrtc::PeerConnectionInterface::IceServer server;
@@ -141,36 +184,58 @@ static void GetNativeIceServers(
server.username = base::UTF16ToUTF8(webkit_server.username());
server.password = base::UTF16ToUTF8(webkit_server.credential());
server.uri = webkit_server.uri().spec();
- servers->push_back(server);
+ config->servers.push_back(server);
+ }
+
+ switch (server_configuration.iceTransports()) {
+ case blink::WebRTCIceTransportsNone:
+ config->type = webrtc::PeerConnectionInterface::kNone;
+ break;
+ case blink::WebRTCIceTransportsRelay:
+ config->type = webrtc::PeerConnectionInterface::kRelay;
+ break;
+ case blink::WebRTCIceTransportsAll:
+ config->type = webrtc::PeerConnectionInterface::kAll;
+ break;
+ default:
+ NOTREACHED();
}
}
class SessionDescriptionRequestTracker {
public:
- SessionDescriptionRequestTracker(RTCPeerConnectionHandler* handler,
- PeerConnectionTracker::Action action)
- : handler_(handler), action_(action) {}
+ SessionDescriptionRequestTracker(
+ const base::WeakPtr<RTCPeerConnectionHandler>& handler,
+ const base::WeakPtr<PeerConnectionTracker>& tracker,
+ PeerConnectionTracker::Action action)
+ : handler_(handler), tracker_(tracker), action_(action) {}
void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) {
- std::string value;
- if (desc) {
- desc->ToString(&value);
- value = "type: " + desc->type() + ", sdp: " + value;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (tracker_ && handler_) {
+ std::string value;
+ if (desc) {
+ desc->ToString(&value);
+ value = "type: " + desc->type() + ", sdp: " + value;
+ }
+ tracker_->TrackSessionDescriptionCallback(
+ handler_.get(), action_, "OnSuccess", value);
}
- if (handler_->peer_connection_tracker())
- handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
- handler_, action_, "OnSuccess", value);
}
void TrackOnFailure(const std::string& error) {
- if (handler_->peer_connection_tracker())
- handler_->peer_connection_tracker()->TrackSessionDescriptionCallback(
- handler_, action_, "OnFailure", error);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (handler_ && tracker_) {
+ tracker_->TrackSessionDescriptionCallback(
+ handler_.get(), action_, "OnFailure", error);
+ }
}
private:
- RTCPeerConnectionHandler* handler_;
+ const base::WeakPtr<RTCPeerConnectionHandler> handler_;
+ const base::WeakPtr<PeerConnectionTracker> tracker_;
PeerConnectionTracker::Action action_;
+ base::ThreadChecker thread_checker_;
};
// Class mapping responses from calls to libjingle CreateOffer/Answer and
@@ -179,25 +244,42 @@ class CreateSessionDescriptionRequest
: public webrtc::CreateSessionDescriptionObserver {
public:
explicit CreateSessionDescriptionRequest(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
const blink::WebRTCSessionDescriptionRequest& request,
- RTCPeerConnectionHandler* handler,
+ const base::WeakPtr<RTCPeerConnectionHandler>& handler,
+ const base::WeakPtr<PeerConnectionTracker>& tracker,
PeerConnectionTracker::Action action)
- : webkit_request_(request), tracker_(handler, action) {}
+ : main_thread_(main_thread),
+ webkit_request_(request),
+ tracker_(handler, tracker, action) {
+ }
+
+ void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&CreateSessionDescriptionRequest::OnSuccess, this, desc));
+ return;
+ }
- virtual void OnSuccess(webrtc::SessionDescriptionInterface* desc) OVERRIDE {
tracker_.TrackOnSuccess(desc);
webkit_request_.requestSucceeded(CreateWebKitSessionDescription(desc));
delete desc;
}
- virtual void OnFailure(const std::string& error) OVERRIDE {
+ void OnFailure(const std::string& error) override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&CreateSessionDescriptionRequest::OnFailure, this, error));
+ return;
+ }
+
tracker_.TrackOnFailure(error);
webkit_request_.requestFailed(base::UTF8ToUTF16(error));
}
protected:
- virtual ~CreateSessionDescriptionRequest() {}
+ ~CreateSessionDescriptionRequest() override {}
- private:
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
blink::WebRTCSessionDescriptionRequest webkit_request_;
SessionDescriptionRequestTracker tracker_;
};
@@ -208,24 +290,40 @@ class SetSessionDescriptionRequest
: public webrtc::SetSessionDescriptionObserver {
public:
explicit SetSessionDescriptionRequest(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
const blink::WebRTCVoidRequest& request,
- RTCPeerConnectionHandler* handler,
+ const base::WeakPtr<RTCPeerConnectionHandler>& handler,
+ const base::WeakPtr<PeerConnectionTracker>& tracker,
PeerConnectionTracker::Action action)
- : webkit_request_(request), tracker_(handler, action) {}
+ : main_thread_(main_thread),
+ webkit_request_(request),
+ tracker_(handler, tracker, action) {
+ }
- virtual void OnSuccess() OVERRIDE {
+ void OnSuccess() override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&SetSessionDescriptionRequest::OnSuccess, this));
+ return;
+ }
tracker_.TrackOnSuccess(NULL);
webkit_request_.requestSucceeded();
}
- virtual void OnFailure(const std::string& error) OVERRIDE {
+ void OnFailure(const std::string& error) override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&SetSessionDescriptionRequest::OnFailure, this, error));
+ return;
+ }
tracker_.TrackOnFailure(error);
webkit_request_.requestFailed(base::UTF8ToUTF16(error));
}
protected:
- virtual ~SetSessionDescriptionRequest() {}
+ ~SetSessionDescriptionRequest() override {}
private:
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
blink::WebRTCVoidRequest webkit_request_;
SessionDescriptionRequestTracker tracker_;
};
@@ -235,56 +333,143 @@ class SetSessionDescriptionRequest
class StatsResponse : public webrtc::StatsObserver {
public:
explicit StatsResponse(const scoped_refptr<LocalRTCStatsRequest>& request)
- : request_(request.get()), response_(request_->createResponse().get()) {
+ : request_(request.get()),
+ main_thread_(base::ThreadTaskRunnerHandle::Get()) {
// Measure the overall time it takes to satisfy a getStats request.
TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
+ signaling_thread_checker_.DetachFromThread();
}
- virtual void OnComplete(
- const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
- TRACE_EVENT0("webrtc", "StatsResponse::OnComplete")
- for (std::vector<webrtc::StatsReport>::const_iterator it = reports.begin();
- it != reports.end(); ++it) {
- if (it->values.size() > 0) {
- AddReport(*it);
- }
+ void OnComplete(const StatsReports& reports) override {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
+ // TODO(tommi): Get rid of these string copies somehow.
+ // We can't use webkit objects directly since they use a single threaded
+ // heap allocator.
+ scoped_ptr<std::vector<StatsReportCopyable>> report_copies(
+ new std::vector<StatsReportCopyable>());
+ report_copies->reserve(reports.size());
+ for (auto it : reports)
+ report_copies->push_back(StatsReportCopyable(*it));
+
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&StatsResponse::DeliverCallback, this,
+ base::Passed(&report_copies)));
+ }
+
+ private:
+ void DeliverCallback(scoped_ptr<std::vector<StatsReportCopyable>> reports) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
+
+ rtc::scoped_refptr<LocalRTCStatsResponse> response(
+ request_->createResponse().get());
+ for (const auto& report : *reports.get()) {
+ if (report.values.size() > 0)
+ AddReport(response.get(), report);
}
// Record the getSync operation as done before calling into Blink so that
// we don't skew the perf measurements of the native code with whatever the
// callback might be doing.
TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
+ request_->requestSucceeded(response);
+ request_ = nullptr; // must be freed on the main thread.
+ }
- request_->requestSucceeded(response_);
+ void AddReport(LocalRTCStatsResponse* response, const StatsReport& report) {
+ int idx = response->addReport(blink::WebString::fromUTF8(report.id),
+ blink::WebString::fromUTF8(report.type),
+ report.timestamp);
+ for (const auto& value : report.values) {
+ response->addStatistic(idx,
+ blink::WebString::fromUTF8(value.display_name()),
+ blink::WebString::fromUTF8(value.value));
+ }
}
- private:
- void AddReport(const webrtc::StatsReport& report) {
- int idx = response_->addReport(blink::WebString::fromUTF8(report.id),
- blink::WebString::fromUTF8(report.type),
- report.timestamp);
- for (webrtc::StatsReport::Values::const_iterator value_it =
- report.values.begin();
- value_it != report.values.end(); ++value_it) {
- AddStatistic(idx, value_it->name, value_it->value);
+ rtc::scoped_refptr<LocalRTCStatsRequest> request_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ base::ThreadChecker signaling_thread_checker_;
+};
+
+void GetStatsOnSignalingThread(
+ const scoped_refptr<webrtc::PeerConnectionInterface>& pc,
+ webrtc::PeerConnectionInterface::StatsOutputLevel level,
+ const scoped_refptr<webrtc::StatsObserver>& observer,
+ const std::string track_id, blink::WebMediaStreamSource::Type track_type) {
+ TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
+
+ scoped_refptr<webrtc::MediaStreamTrackInterface> track;
+ if (!track_id.empty()) {
+ if (track_type == blink::WebMediaStreamSource::TypeAudio) {
+ track = pc->local_streams()->FindAudioTrack(track_id);
+ if (!track.get())
+ track = pc->remote_streams()->FindAudioTrack(track_id);
+ } else {
+ DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track_type);
+ track = pc->local_streams()->FindVideoTrack(track_id);
+ if (!track.get())
+ track = pc->remote_streams()->FindVideoTrack(track_id);
+ }
+
+ if (!track.get()) {
+ DVLOG(1) << "GetStats: Track not found.";
+ observer->OnComplete(StatsReports());
+ return;
}
}
- void AddStatistic(int idx, const std::string& name,
- const std::string& value) {
- response_->addStatistic(idx,
- blink::WebString::fromUTF8(name),
- blink::WebString::fromUTF8(value));
+ if (!pc->GetStats(observer.get(), track.get(), level)) {
+ DVLOG(1) << "GetStats failed.";
+ observer->OnComplete(StatsReports());
}
+}
- talk_base::scoped_refptr<LocalRTCStatsRequest> request_;
- talk_base::scoped_refptr<LocalRTCStatsResponse> response_;
+class PeerConnectionUMAObserver : public webrtc::UMAObserver {
+ public:
+ PeerConnectionUMAObserver() {}
+ ~PeerConnectionUMAObserver() override {}
+
+ void IncrementCounter(
+ webrtc::PeerConnectionUMAMetricsCounter counter) override {
+ // Runs on libjingle's signaling thread.
+ UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
+ counter,
+ webrtc::kBoundary);
+ }
+
+ void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type,
+ int value) override {
+ // Runs on libjingle's signaling thread.
+ switch (type) {
+ case webrtc::kTimeToConnect:
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "WebRTC.PeerConnection.TimeToConnect",
+ base::TimeDelta::FromMilliseconds(value));
+ break;
+ case webrtc::kNetworkInterfaces_IPv4:
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
+ value);
+ break;
+ case webrtc::kNetworkInterfaces_IPv6:
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
+ value);
+ break;
+ default:
+ NOTREACHED();
+ }
+ }
};
+base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
+ g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
// Implementation of LocalRTCStatsRequest.
LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl)
- : impl_(impl),
- response_(NULL) {
+ : impl_(impl) {
}
LocalRTCStatsRequest::LocalRTCStatsRequest() {}
@@ -299,10 +484,8 @@ blink::WebMediaStreamTrack LocalRTCStatsRequest::component() const {
}
scoped_refptr<LocalRTCStatsResponse> LocalRTCStatsRequest::createResponse() {
- DCHECK(!response_);
- response_ = new talk_base::RefCountedObject<LocalRTCStatsResponse>(
- impl_.createResponse());
- return response_.get();
+ return scoped_refptr<LocalRTCStatsResponse>(
+ new rtc::RefCountedObject<LocalRTCStatsResponse>(impl_.createResponse()));
}
void LocalRTCStatsRequest::requestSucceeded(
@@ -327,46 +510,137 @@ void LocalRTCStatsResponse::addStatistic(size_t report,
impl_.addStatistic(report, name, value);
}
-namespace {
-
-class PeerConnectionUMAObserver : public webrtc::UMAObserver {
+// Receives notifications from a PeerConnection object about state changes,
+// track addition/removal etc. The callbacks we receive here come on the
+// signaling thread, so this class takes care of delivering them to an
+// RTCPeerConnectionHandler instance on the main thread.
+// In order to do safe PostTask-ing, the class is reference counted and
+// checks for the existence of the RTCPeerConnectionHandler instance before
+// delivering callbacks on the main thread.
+class RTCPeerConnectionHandler::Observer
+ : public base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>,
+ public PeerConnectionObserver {
public:
- PeerConnectionUMAObserver() {}
- virtual ~PeerConnectionUMAObserver() {}
+ Observer(const base::WeakPtr<RTCPeerConnectionHandler>& handler)
+ : handler_(handler), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
- virtual void IncrementCounter(
- webrtc::PeerConnectionUMAMetricsCounter counter) OVERRIDE {
- UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
- counter,
- webrtc::kBoundary);
+ protected:
+ friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>;
+ virtual ~Observer() {}
+
+ void OnSignalingChange(
+ PeerConnectionInterface::SignalingState new_state) override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange,
+ this, new_state));
+ } else if (handler_) {
+ handler_->OnSignalingChange(new_state);
+ }
}
- virtual void AddHistogramSample(
- webrtc::PeerConnectionUMAMetricsName type, int value) OVERRIDE {
- switch (type) {
- case webrtc::kTimeToConnect:
- UMA_HISTOGRAM_MEDIUM_TIMES(
- "WebRTC.PeerConnection.TimeToConnect",
- base::TimeDelta::FromMilliseconds(value));
- break;
- case webrtc::kNetworkInterfaces_IPv4:
- UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
- value);
- break;
- case webrtc::kNetworkInterfaces_IPv6:
- UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
- value);
- break;
- default:
- NOTREACHED();
+ void OnAddStream(MediaStreamInterface* stream) override {
+ DCHECK(stream);
+ scoped_ptr<RemoteMediaStreamImpl> remote_stream(
+ new RemoteMediaStreamImpl(main_thread_, stream));
+
+ // The webkit object owned by RemoteMediaStreamImpl, will be initialized
+ // asynchronously and the posted task will execude after that initialization
+ // is done.
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl,
+ this, base::Passed(&remote_stream)));
+ }
+
+ void OnRemoveStream(MediaStreamInterface* stream) override {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl,
+ this, make_scoped_refptr(stream)));
+ }
+
+ void OnDataChannel(DataChannelInterface* data_channel) override {
+ scoped_ptr<RtcDataChannelHandler> handler(
+ new RtcDataChannelHandler(main_thread_, data_channel));
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
+ this, base::Passed(&handler)));
+ }
+
+ void OnRenegotiationNeeded() override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded,
+ this));
+ } else if (handler_) {
+ handler_->OnRenegotiationNeeded();
}
}
-};
-base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
- g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
+ void OnIceConnectionChange(
+ PeerConnectionInterface::IceConnectionState new_state) override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(
+ &RTCPeerConnectionHandler::Observer::OnIceConnectionChange, this,
+ new_state));
+ } else if (handler_) {
+ handler_->OnIceConnectionChange(new_state);
+ }
+ }
-} // namespace
+ void OnIceGatheringChange(
+ PeerConnectionInterface::IceGatheringState new_state) override {
+ if (!main_thread_->BelongsToCurrentThread()) {
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange,
+ this, new_state));
+ } else if (handler_) {
+ handler_->OnIceGatheringChange(new_state);
+ }
+ }
+
+ void OnIceCandidate(const IceCandidateInterface* candidate) override {
+ std::string sdp;
+ if (!candidate->ToString(&sdp)) {
+ NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
+ return;
+ }
+
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl,
+ this, sdp, candidate->sdp_mid(), candidate->sdp_mline_index(),
+ candidate->candidate().component(),
+ candidate->candidate().address().family()));
+ }
+
+ void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
+ DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
+ if (handler_)
+ handler_->OnAddStream(stream.Pass());
+ }
+
+ void OnRemoveStreamImpl(const scoped_refptr<MediaStreamInterface>& stream) {
+ if (handler_)
+ handler_->OnRemoveStream(stream);
+ }
+
+ void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
+ if (handler_)
+ handler_->OnDataChannel(handler.Pass());
+ }
+
+ void OnIceCandidateImpl(const std::string& sdp, const std::string& sdp_mid,
+ int sdp_mline_index, int component, int address_family) {
+ if (handler_) {
+ handler_->OnIceCandidate(sdp, sdp_mid, sdp_mline_index, component,
+ address_family);
+ }
+ }
+
+ private:
+ const base::WeakPtr<RTCPeerConnectionHandler> handler_;
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+};
RTCPeerConnectionHandler::RTCPeerConnectionHandler(
blink::WebRTCPeerConnectionHandlerClient* client,
@@ -374,12 +648,18 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler(
: client_(client),
dependency_factory_(dependency_factory),
frame_(NULL),
- peer_connection_tracker_(NULL),
- num_data_channels_created_(0) {
+ num_data_channels_created_(0),
+ num_local_candidates_ipv4_(0),
+ num_local_candidates_ipv6_(0),
+ weak_factory_(this) {
g_peer_connection_handlers.Get().insert(this);
}
RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ stop();
+
g_peer_connection_handlers.Get().erase(this);
if (peer_connection_tracker_)
peer_connection_tracker_->UnregisterPeerConnection(this);
@@ -394,14 +674,41 @@ void RTCPeerConnectionHandler::DestructAllHandlers() {
std::set<RTCPeerConnectionHandler*> handlers(
g_peer_connection_handlers.Get().begin(),
g_peer_connection_handlers.Get().end());
- for (std::set<RTCPeerConnectionHandler*>::iterator handler = handlers.begin();
- handler != handlers.end();
- ++handler) {
- (*handler)->client_->releasePeerConnectionHandler();
+ for (auto handler : handlers) {
+ if (handler->client_)
+ handler->client_->releasePeerConnectionHandler();
+ }
+}
+
+// static
+void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
+ const blink::WebRTCOfferOptions& options,
+ RTCMediaConstraints* output) {
+ output->AddMandatory(
+ webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
+ options.offerToReceiveAudio() > 0 ? "true" : "false",
+ true);
+
+ output->AddMandatory(
+ webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
+ options.offerToReceiveVideo() > 0 ? "true" : "false",
+ true);
+
+ if (!options.voiceActivityDetection()) {
+ output->AddMandatory(
+ webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
+ "false",
+ true);
+ }
+
+ if (options.iceRestart()) {
+ output->AddMandatory(
+ webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
}
}
void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(frame);
frame_ = frame;
}
@@ -409,28 +716,32 @@ void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
bool RTCPeerConnectionHandler::initialize(
const blink::WebRTCConfiguration& server_configuration,
const blink::WebMediaConstraints& options) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(frame_);
peer_connection_tracker_ =
- RenderThreadImpl::current()->peer_connection_tracker();
+ RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
- webrtc::PeerConnectionInterface::IceServers servers;
- GetNativeIceServers(server_configuration, &servers);
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ GetNativeRtcConfiguration(server_configuration, &config);
RTCMediaConstraints constraints(options);
- native_peer_connection_ =
- dependency_factory_->CreatePeerConnection(
- servers, &constraints, frame_, this);
+ peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
+ native_peer_connection_ = dependency_factory_->CreatePeerConnection(
+ config, &constraints, frame_, peer_connection_observer_.get());
+
if (!native_peer_connection_.get()) {
LOG(ERROR) << "Failed to initialize native PeerConnection.";
return false;
}
- if (peer_connection_tracker_)
+
+ if (peer_connection_tracker_) {
peer_connection_tracker_->RegisterPeerConnection(
- this, servers, constraints, frame_);
+ this, config, constraints, frame_);
+ }
- uma_observer_ = new talk_base::RefCountedObject<PeerConnectionUMAObserver>();
+ uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
native_peer_connection_->RegisterUMAObserver(uma_observer_.get());
return true;
}
@@ -438,14 +749,15 @@ bool RTCPeerConnectionHandler::initialize(
bool RTCPeerConnectionHandler::InitializeForTest(
const blink::WebRTCConfiguration& server_configuration,
const blink::WebMediaConstraints& options,
- PeerConnectionTracker* peer_connection_tracker) {
- webrtc::PeerConnectionInterface::IceServers servers;
- GetNativeIceServers(server_configuration, &servers);
+ const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ GetNativeRtcConfiguration(server_configuration, &config);
+ peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
RTCMediaConstraints constraints(options);
- native_peer_connection_ =
- dependency_factory_->CreatePeerConnection(
- servers, &constraints, NULL, this);
+ native_peer_connection_ = dependency_factory_->CreatePeerConnection(
+ config, &constraints, NULL, peer_connection_observer_.get());
if (!native_peer_connection_.get()) {
LOG(ERROR) << "Failed to initialize native PeerConnection.";
return false;
@@ -457,9 +769,16 @@ bool RTCPeerConnectionHandler::InitializeForTest(
void RTCPeerConnectionHandler::createOffer(
const blink::WebRTCSessionDescriptionRequest& request,
const blink::WebMediaConstraints& options) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
+
scoped_refptr<CreateSessionDescriptionRequest> description_request(
- new talk_base::RefCountedObject<CreateSessionDescriptionRequest>(
- request, this, PeerConnectionTracker::ACTION_CREATE_OFFER));
+ new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
+ base::ThreadTaskRunnerHandle::Get(), request,
+ weak_factory_.GetWeakPtr(), peer_connection_tracker_,
+ PeerConnectionTracker::ACTION_CREATE_OFFER));
+
+ // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
RTCMediaConstraints constraints(options);
native_peer_connection_->CreateOffer(description_request.get(), &constraints);
@@ -467,12 +786,38 @@ void RTCPeerConnectionHandler::createOffer(
peer_connection_tracker_->TrackCreateOffer(this, constraints);
}
+void RTCPeerConnectionHandler::createOffer(
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebRTCOfferOptions& options) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
+
+ scoped_refptr<CreateSessionDescriptionRequest> description_request(
+ new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
+ base::ThreadTaskRunnerHandle::Get(), request,
+ weak_factory_.GetWeakPtr(), peer_connection_tracker_,
+ PeerConnectionTracker::ACTION_CREATE_OFFER));
+
+ // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
+ RTCMediaConstraints constraints;
+ ConvertOfferOptionsToConstraints(options, &constraints);
+ native_peer_connection_->CreateOffer(description_request.get(), &constraints);
+
+ if (peer_connection_tracker_)
+ peer_connection_tracker_->TrackCreateOffer(this, constraints);
+}
+
void RTCPeerConnectionHandler::createAnswer(
const blink::WebRTCSessionDescriptionRequest& request,
const blink::WebMediaConstraints& options) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
scoped_refptr<CreateSessionDescriptionRequest> description_request(
- new talk_base::RefCountedObject<CreateSessionDescriptionRequest>(
- request, this, PeerConnectionTracker::ACTION_CREATE_ANSWER));
+ new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
+ base::ThreadTaskRunnerHandle::Get(), request,
+ weak_factory_.GetWeakPtr(), peer_connection_tracker_,
+ PeerConnectionTracker::ACTION_CREATE_ANSWER));
+ // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
RTCMediaConstraints constraints(options);
native_peer_connection_->CreateAnswer(description_request.get(),
&constraints);
@@ -484,9 +829,17 @@ void RTCPeerConnectionHandler::createAnswer(
void RTCPeerConnectionHandler::setLocalDescription(
const blink::WebRTCVoidRequest& request,
const blink::WebRTCSessionDescription& description) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
+
+ std::string sdp = base::UTF16ToUTF8(description.sdp());
+ std::string type = base::UTF16ToUTF8(description.type());
+
webrtc::SdpParseError error;
+ // Since CreateNativeSessionDescription uses the dependency factory, we need
+ // to make this call on the current thread to be safe.
webrtc::SessionDescriptionInterface* native_desc =
- CreateNativeSessionDescription(description, &error);
+ CreateNativeSessionDescription(sdp, type, &error);
if (!native_desc) {
std::string reason_str = "Failed to parse SessionDescription. ";
reason_str.append(error.line);
@@ -496,22 +849,39 @@ void RTCPeerConnectionHandler::setLocalDescription(
request.requestFailed(blink::WebString::fromUTF8(reason_str));
return;
}
- if (peer_connection_tracker_)
+
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackSetSessionDescription(
- this, description, PeerConnectionTracker::SOURCE_LOCAL);
+ this, sdp, type, PeerConnectionTracker::SOURCE_LOCAL);
+ }
scoped_refptr<SetSessionDescriptionRequest> set_request(
- new talk_base::RefCountedObject<SetSessionDescriptionRequest>(
- request, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
- native_peer_connection_->SetLocalDescription(set_request.get(), native_desc);
+ new rtc::RefCountedObject<SetSessionDescriptionRequest>(
+ base::ThreadTaskRunnerHandle::Get(), request,
+ weak_factory_.GetWeakPtr(), peer_connection_tracker_,
+ PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
+
+ signaling_thread()->PostTask(FROM_HERE,
+ base::Bind(&RunClosureWithTrace,
+ base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
+ native_peer_connection_, set_request,
+ base::Unretained(native_desc)),
+ "SetLocalDescription"));
}
void RTCPeerConnectionHandler::setRemoteDescription(
const blink::WebRTCVoidRequest& request,
const blink::WebRTCSessionDescription& description) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
+ std::string sdp = base::UTF16ToUTF8(description.sdp());
+ std::string type = base::UTF16ToUTF8(description.type());
+
webrtc::SdpParseError error;
+ // Since CreateNativeSessionDescription uses the dependency factory, we need
+ // to make this call on the current thread to be safe.
webrtc::SessionDescriptionInterface* native_desc =
- CreateNativeSessionDescription(description, &error);
+ CreateNativeSessionDescription(sdp, type, &error);
if (!native_desc) {
std::string reason_str = "Failed to parse SessionDescription. ";
reason_str.append(error.line);
@@ -521,87 +891,130 @@ void RTCPeerConnectionHandler::setRemoteDescription(
request.requestFailed(blink::WebString::fromUTF8(reason_str));
return;
}
- if (peer_connection_tracker_)
+
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackSetSessionDescription(
- this, description, PeerConnectionTracker::SOURCE_REMOTE);
+ this, sdp, type, PeerConnectionTracker::SOURCE_REMOTE);
+ }
scoped_refptr<SetSessionDescriptionRequest> set_request(
- new talk_base::RefCountedObject<SetSessionDescriptionRequest>(
- request, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
- native_peer_connection_->SetRemoteDescription(set_request.get(), native_desc);
+ new rtc::RefCountedObject<SetSessionDescriptionRequest>(
+ base::ThreadTaskRunnerHandle::Get(), request,
+ weak_factory_.GetWeakPtr(), peer_connection_tracker_,
+ PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
+ signaling_thread()->PostTask(FROM_HERE,
+ base::Bind(&RunClosureWithTrace,
+ base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
+ native_peer_connection_, set_request,
+ base::Unretained(native_desc)),
+ "SetRemoteDescription"));
}
blink::WebRTCSessionDescription
RTCPeerConnectionHandler::localDescription() {
- const webrtc::SessionDescriptionInterface* native_desc =
- native_peer_connection_->local_description();
- blink::WebRTCSessionDescription description =
- CreateWebKitSessionDescription(native_desc);
- return description;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
+
+ // Since local_description returns a pointer to a non-reference-counted object
+ // that lives on the signaling thread, we cannot fetch a pointer to it and use
+ // it directly here. Instead, we access the object completely on the signaling
+ // thread.
+ std::string sdp, type;
+ base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
+ base::Bind(&webrtc::PeerConnectionInterface::local_description,
+ native_peer_connection_);
+ RunSynchronousClosureOnSignalingThread(
+ base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
+ base::Unretained(&sdp), base::Unretained(&type)),
+ "localDescription");
+
+ return CreateWebKitSessionDescription(sdp, type);
}
blink::WebRTCSessionDescription
RTCPeerConnectionHandler::remoteDescription() {
- const webrtc::SessionDescriptionInterface* native_desc =
- native_peer_connection_->remote_description();
- blink::WebRTCSessionDescription description =
- CreateWebKitSessionDescription(native_desc);
- return description;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
+ // Since local_description returns a pointer to a non-reference-counted object
+ // that lives on the signaling thread, we cannot fetch a pointer to it and use
+ // it directly here. Instead, we access the object completely on the signaling
+ // thread.
+ std::string sdp, type;
+ base::Callback<const webrtc::SessionDescriptionInterface*()> description_cb =
+ base::Bind(&webrtc::PeerConnectionInterface::remote_description,
+ native_peer_connection_);
+ RunSynchronousClosureOnSignalingThread(
+ base::Bind(&GetSdpAndTypeFromSessionDescription, description_cb,
+ base::Unretained(&sdp), base::Unretained(&type)),
+ "remoteDescription");
+
+ return CreateWebKitSessionDescription(sdp, type);
}
bool RTCPeerConnectionHandler::updateICE(
const blink::WebRTCConfiguration& server_configuration,
const blink::WebMediaConstraints& options) {
- webrtc::PeerConnectionInterface::IceServers servers;
- GetNativeIceServers(server_configuration, &servers);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ GetNativeRtcConfiguration(server_configuration, &config);
RTCMediaConstraints constraints(options);
if (peer_connection_tracker_)
- peer_connection_tracker_->TrackUpdateIce(this, servers, constraints);
+ peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
- return native_peer_connection_->UpdateIce(servers,
- &constraints);
+ return native_peer_connection_->UpdateIce(config.servers, &constraints);
}
bool RTCPeerConnectionHandler::addICECandidate(
- const blink::WebRTCVoidRequest& request,
- const blink::WebRTCICECandidate& candidate) {
+ const blink::WebRTCVoidRequest& request,
+ const blink::WebRTCICECandidate& candidate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
// Libjingle currently does not accept callbacks for addICECandidate.
// For that reason we are going to call callbacks from here.
+
+ // TODO(tommi): Instead of calling addICECandidate here, we can do a
+ // PostTaskAndReply kind of a thing.
bool result = addICECandidate(candidate);
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult,
- base::Unretained(this), request, result));
+ weak_factory_.GetWeakPtr(), request, result));
// On failure callback will be triggered.
return true;
}
bool RTCPeerConnectionHandler::addICECandidate(
const blink::WebRTCICECandidate& candidate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
dependency_factory_->CreateIceCandidate(
base::UTF16ToUTF8(candidate.sdpMid()),
candidate.sdpMLineIndex(),
base::UTF16ToUTF8(candidate.candidate())));
- if (!native_candidate) {
+ bool return_value = false;
+
+ if (native_candidate) {
+ return_value =
+ native_peer_connection_->AddIceCandidate(native_candidate.get());
+ LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
+ } else {
LOG(ERROR) << "Could not create native ICE candidate.";
- return false;
}
- bool return_value =
- native_peer_connection_->AddIceCandidate(native_candidate.get());
- LOG_IF(ERROR, !return_value) << "Error processing ICE candidate.";
-
- if (peer_connection_tracker_)
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackAddIceCandidate(
- this, candidate, PeerConnectionTracker::SOURCE_REMOTE);
-
+ this, candidate, PeerConnectionTracker::SOURCE_REMOTE, return_value);
+ }
return return_value;
}
void RTCPeerConnectionHandler::OnaddICECandidateResult(
const blink::WebRTCVoidRequest& webkit_request, bool result) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
if (!result) {
// We don't have the actual error code from the libjingle, so for now
// using a generic error string.
@@ -615,7 +1028,8 @@ void RTCPeerConnectionHandler::OnaddICECandidateResult(
bool RTCPeerConnectionHandler::addStream(
const blink::WebMediaStream& stream,
const blink::WebMediaConstraints& options) {
-
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
local_streams_.begin(); adapter_it != local_streams_.end();
++adapter_it) {
@@ -626,9 +1040,10 @@ bool RTCPeerConnectionHandler::addStream(
}
}
- if (peer_connection_tracker_)
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackAddStream(
this, stream, PeerConnectionTracker::SOURCE_LOCAL);
+ }
PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
@@ -641,11 +1056,22 @@ bool RTCPeerConnectionHandler::addStream(
webrtc_stream);
RTCMediaConstraints constraints(options);
- return native_peer_connection_->AddStream(webrtc_stream, &constraints);
+ if (!constraints.GetMandatory().empty() ||
+ !constraints.GetOptional().empty()) {
+ // TODO(perkj): |mediaConstraints| is the name of the optional constraints
+ // argument in RTCPeerConnection.idl. It has been removed from the spec and
+ // should be removed from blink as well.
+ LOG(WARNING)
+ << "mediaConstraints is not a supported argument to addStream.";
+ }
+
+ return native_peer_connection_->AddStream(webrtc_stream);
}
void RTCPeerConnectionHandler::removeStream(
const blink::WebMediaStream& stream) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
// Find the webrtc stream.
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream;
for (ScopedVector<WebRtcMediaStreamAdapter>::iterator adapter_it =
@@ -657,77 +1083,70 @@ void RTCPeerConnectionHandler::removeStream(
break;
}
}
- DCHECK(webrtc_stream);
- native_peer_connection_->RemoveStream(webrtc_stream);
+ DCHECK(webrtc_stream.get());
+ // TODO(tommi): Make this async (PostTaskAndReply).
+ native_peer_connection_->RemoveStream(webrtc_stream.get());
- if (peer_connection_tracker_)
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackRemoveStream(
this, stream, PeerConnectionTracker::SOURCE_LOCAL);
+ }
PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
- webrtc_stream);
+ webrtc_stream.get());
}
void RTCPeerConnectionHandler::getStats(
const blink::WebRTCStatsRequest& request) {
+ DCHECK(thread_checker_.CalledOnValidThread());
scoped_refptr<LocalRTCStatsRequest> inner_request(
- new talk_base::RefCountedObject<LocalRTCStatsRequest>(request));
- getStats(inner_request.get());
+ new rtc::RefCountedObject<LocalRTCStatsRequest>(request));
+ getStats(inner_request);
}
-void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest* request) {
- talk_base::scoped_refptr<webrtc::StatsObserver> observer(
- new talk_base::RefCountedObject<StatsResponse>(request));
- webrtc::MediaStreamTrackInterface* track = NULL;
+void RTCPeerConnectionHandler::getStats(
+ const scoped_refptr<LocalRTCStatsRequest>& request) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
+
+
+ rtc::scoped_refptr<webrtc::StatsObserver> observer(
+ new rtc::RefCountedObject<StatsResponse>(request));
+
+ std::string track_id;
+ blink::WebMediaStreamSource::Type track_type =
+ blink::WebMediaStreamSource::TypeAudio;
if (request->hasSelector()) {
- blink::WebMediaStreamSource::Type type =
- request->component().source().type();
- std::string track_id = request->component().id().utf8();
- if (type == blink::WebMediaStreamSource::TypeAudio) {
- track =
- native_peer_connection_->local_streams()->FindAudioTrack(track_id);
- if (!track) {
- track =
- native_peer_connection_->remote_streams()->FindAudioTrack(track_id);
- }
- } else {
- DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, type);
- track =
- native_peer_connection_->local_streams()->FindVideoTrack(track_id);
- if (!track) {
- track =
- native_peer_connection_->remote_streams()->FindVideoTrack(track_id);
- }
- }
- if (!track) {
- DVLOG(1) << "GetStats: Track not found.";
- // TODO(hta): Consider how to get an error back.
- std::vector<webrtc::StatsReport> no_reports;
- observer->OnComplete(no_reports);
- return;
- }
+ track_type = request->component().source().type();
+ track_id = request->component().id().utf8();
}
- GetStats(observer,
- track,
- webrtc::PeerConnectionInterface::kStatsOutputLevelStandard);
+
+ GetStats(observer, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard,
+ track_id, track_type);
}
+// TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
void RTCPeerConnectionHandler::GetStats(
webrtc::StatsObserver* observer,
- webrtc::MediaStreamTrackInterface* track,
- webrtc::PeerConnectionInterface::StatsOutputLevel level) {
- TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::GetStats");
- if (!native_peer_connection_->GetStats(observer, track, level)) {
- DVLOG(1) << "GetStats failed.";
- // TODO(hta): Consider how to get an error back.
- std::vector<webrtc::StatsReport> no_reports;
- observer->OnComplete(no_reports);
- return;
- }
+ webrtc::PeerConnectionInterface::StatsOutputLevel level,
+ const std::string& track_id,
+ blink::WebMediaStreamSource::Type track_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ signaling_thread()->PostTask(FROM_HERE,
+ base::Bind(&GetStatsOnSignalingThread, native_peer_connection_, level,
+ make_scoped_refptr(observer), track_id, track_type));
+}
+
+void RTCPeerConnectionHandler::CloseClientPeerConnection() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (client_)
+ client_->closePeerConnection();
}
blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
const blink::WebString& label, const blink::WebRTCDataChannelInit& init) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label);
webrtc::DataChannelInit config;
@@ -741,39 +1160,44 @@ blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::createDataChannel(
config.maxRetransmitTime = init.maxRetransmitTime;
config.protocol = base::UTF16ToUTF8(init.protocol);
- talk_base::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
+ rtc::scoped_refptr<webrtc::DataChannelInterface> webrtc_channel(
native_peer_connection_->CreateDataChannel(base::UTF16ToUTF8(label),
&config));
if (!webrtc_channel) {
DLOG(ERROR) << "Could not create native data channel.";
return NULL;
}
- if (peer_connection_tracker_)
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackCreateDataChannel(
this, webrtc_channel.get(), PeerConnectionTracker::SOURCE_LOCAL);
+ }
++num_data_channels_created_;
- return new RtcDataChannelHandler(webrtc_channel);
+ return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
+ webrtc_channel);
}
blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
const blink::WebMediaStreamTrack& track) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
DVLOG(1) << "createDTMFSender.";
MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track);
- if (!native_track ||
+ if (!native_track || !native_track->is_local_track() ||
track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
- DLOG(ERROR) << "Could not create DTMF sender from a non-audio track.";
- return NULL;
+ DLOG(ERROR) << "The DTMF sender requires a local audio track.";
+ return nullptr;
}
- webrtc::AudioTrackInterface* audio_track = native_track->GetAudioAdapter();
- talk_base::scoped_refptr<webrtc::DtmfSenderInterface> sender(
- native_peer_connection_->CreateDtmfSender(audio_track));
+ scoped_refptr<webrtc::AudioTrackInterface> audio_track =
+ native_track->GetAudioAdapter();
+ rtc::scoped_refptr<webrtc::DtmfSenderInterface> sender(
+ native_peer_connection_->CreateDtmfSender(audio_track.get()));
if (!sender) {
DLOG(ERROR) << "Could not create native DTMF sender.";
- return NULL;
+ return nullptr;
}
if (peer_connection_tracker_)
peer_connection_tracker_->TrackCreateDTMFSender(this, track);
@@ -782,90 +1206,144 @@ blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
}
void RTCPeerConnectionHandler::stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "RTCPeerConnectionHandler::stop";
+ if (!client_ || !native_peer_connection_.get())
+ return; // Already stopped.
+
if (peer_connection_tracker_)
peer_connection_tracker_->TrackStop(this);
+
native_peer_connection_->Close();
-}
-void RTCPeerConnectionHandler::OnError() {
- // TODO(perkj): Implement.
- NOTIMPLEMENTED();
+ // The client_ pointer is not considered valid after this point and no further
+ // callbacks must be made.
+ client_ = nullptr;
}
void RTCPeerConnectionHandler::OnSignalingChange(
webrtc::PeerConnectionInterface::SignalingState new_state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
+
blink::WebRTCPeerConnectionHandlerClient::SignalingState state =
GetWebKitSignalingState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackSignalingStateChange(this, state);
- client_->didChangeSignalingState(state);
+ if (client_)
+ client_->didChangeSignalingState(state);
}
// Called any time the IceConnectionState changes
void RTCPeerConnectionHandler::OnIceConnectionChange(
webrtc::PeerConnectionInterface::IceConnectionState new_state) {
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) {
+ ice_connection_checking_start_ = base::TimeTicks::Now();
+ } else if (new_state ==
+ webrtc::PeerConnectionInterface::kIceConnectionConnected) {
+ // If the state becomes connected, send the time needed for PC to become
+ // connected from checking to UMA. UMA data will help to know how much
+ // time needed for PC to connect with remote peer.
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "WebRTC.PeerConnection.TimeToConnect",
+ base::TimeTicks::Now() - ice_connection_checking_start_);
+ }
+
track_metrics_.IceConnectionChange(new_state);
blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
GetWebKitIceConnectionState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackIceConnectionStateChange(this, state);
- client_->didChangeICEConnectionState(state);
+ if(client_)
+ client_->didChangeICEConnectionState(state);
}
// Called any time the IceGatheringState changes
void RTCPeerConnectionHandler::OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
+
if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
// If ICE gathering is completed, generate a NULL ICE candidate,
// to signal end of candidates.
- blink::WebRTCICECandidate null_candidate;
- client_->didGenerateICECandidate(null_candidate);
+ if (client_) {
+ blink::WebRTCICECandidate null_candidate;
+ client_->didGenerateICECandidate(null_candidate);
+ }
+
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
+ num_local_candidates_ipv4_);
+
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
+ num_local_candidates_ipv6_);
+ } else if (new_state ==
+ webrtc::PeerConnectionInterface::kIceGatheringGathering) {
+ // ICE restarts will change gathering state back to "gathering",
+ // reset the counter.
+ num_local_candidates_ipv6_ = 0;
+ num_local_candidates_ipv4_ = 0;
}
blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state =
GetWebKitIceGatheringState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
- client_->didChangeICEGatheringState(state);
+ if (client_)
+ client_->didChangeICEGatheringState(state);
}
-void RTCPeerConnectionHandler::OnAddStream(
- webrtc::MediaStreamInterface* stream_interface) {
- DCHECK(stream_interface);
- DCHECK(remote_streams_.find(stream_interface) == remote_streams_.end());
+void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
+ if (peer_connection_tracker_)
+ peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
+ if (client_)
+ client_->negotiationNeeded();
+}
- RemoteMediaStreamImpl* remote_stream =
- new RemoteMediaStreamImpl(stream_interface);
+void RTCPeerConnectionHandler::OnAddStream(
+ scoped_ptr<RemoteMediaStreamImpl> stream) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
+ remote_streams_.end());
+ DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
+
+ // Ownership is with remote_streams_ now.
+ RemoteMediaStreamImpl* s = stream.release();
remote_streams_.insert(
std::pair<webrtc::MediaStreamInterface*, RemoteMediaStreamImpl*> (
- stream_interface, remote_stream));
+ s->webrtc_stream().get(), s));
- if (peer_connection_tracker_)
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackAddStream(
- this, remote_stream->webkit_stream(),
- PeerConnectionTracker::SOURCE_REMOTE);
+ this, s->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE);
+ }
PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
- stream_interface);
-
- client_->didAddRemoteStream(remote_stream->webkit_stream());
+ s->webrtc_stream().get());
+ if (client_)
+ client_->didAddRemoteStream(s->webkit_stream());
}
void RTCPeerConnectionHandler::OnRemoveStream(
- webrtc::MediaStreamInterface* stream_interface) {
- DCHECK(stream_interface);
- RemoteStreamMap::iterator it = remote_streams_.find(stream_interface);
+ const scoped_refptr<webrtc::MediaStreamInterface>& stream) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
+ RemoteStreamMap::iterator it = remote_streams_.find(stream.get());
if (it == remote_streams_.end()) {
NOTREACHED() << "Stream not found";
return;
}
track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
- stream_interface);
+ stream.get());
PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
@@ -873,59 +1351,62 @@ void RTCPeerConnectionHandler::OnRemoveStream(
DCHECK(!webkit_stream.isNull());
remote_streams_.erase(it);
- if (peer_connection_tracker_)
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackRemoveStream(
this, webkit_stream, PeerConnectionTracker::SOURCE_REMOTE);
-
- client_->didRemoveRemoteStream(webkit_stream);
-}
-
-void RTCPeerConnectionHandler::OnIceCandidate(
- const webrtc::IceCandidateInterface* candidate) {
- DCHECK(candidate);
- std::string sdp;
- if (!candidate->ToString(&sdp)) {
- NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
- return;
}
- blink::WebRTCICECandidate web_candidate;
- web_candidate.initialize(base::UTF8ToUTF16(sdp),
- base::UTF8ToUTF16(candidate->sdp_mid()),
- candidate->sdp_mline_index());
- if (peer_connection_tracker_)
- peer_connection_tracker_->TrackAddIceCandidate(
- this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL);
- client_->didGenerateICECandidate(web_candidate);
+ if (client_)
+ client_->didRemoveRemoteStream(webkit_stream);
}
void RTCPeerConnectionHandler::OnDataChannel(
- webrtc::DataChannelInterface* data_channel) {
- if (peer_connection_tracker_)
+ scoped_ptr<RtcDataChannelHandler> handler) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
+
+ if (peer_connection_tracker_) {
peer_connection_tracker_->TrackCreateDataChannel(
- this, data_channel, PeerConnectionTracker::SOURCE_REMOTE);
+ this, handler->channel().get(), PeerConnectionTracker::SOURCE_REMOTE);
+ }
- DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
- << data_channel->label();
- client_->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel));
+ if (client_)
+ client_->didAddRemoteDataChannel(handler.release());
}
-void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
- if (peer_connection_tracker_)
- peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
- client_->negotiationNeeded();
-}
+void RTCPeerConnectionHandler::OnIceCandidate(
+ const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index,
+ int component, int address_family) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
+ blink::WebRTCICECandidate web_candidate;
+ web_candidate.initialize(base::UTF8ToUTF16(sdp),
+ base::UTF8ToUTF16(sdp_mid),
+ sdp_mline_index);
+ if (peer_connection_tracker_) {
+ peer_connection_tracker_->TrackAddIceCandidate(
+ this, web_candidate, PeerConnectionTracker::SOURCE_LOCAL, true);
+ }
-PeerConnectionTracker* RTCPeerConnectionHandler::peer_connection_tracker() {
- return peer_connection_tracker_;
+ // Only the first m line's first component is tracked to avoid
+ // miscounting when doing BUNDLE or rtcp mux.
+ if (sdp_mline_index == 0 && component == 1) {
+ if (address_family == AF_INET) {
+ ++num_local_candidates_ipv4_;
+ } else if (address_family == AF_INET6) {
+ ++num_local_candidates_ipv6_;
+ } else {
+ NOTREACHED();
+ }
+ }
+ if (client_)
+ client_->didGenerateICECandidate(web_candidate);
}
webrtc::SessionDescriptionInterface*
RTCPeerConnectionHandler::CreateNativeSessionDescription(
- const blink::WebRTCSessionDescription& description,
+ const std::string& sdp, const std::string& type,
webrtc::SdpParseError* error) {
- std::string sdp = base::UTF16ToUTF8(description.sdp());
- std::string type = base::UTF16ToUTF8(description.type());
webrtc::SessionDescriptionInterface* native_desc =
dependency_factory_->CreateSessionDescription(type, sdp, error);
@@ -935,4 +1416,28 @@ RTCPeerConnectionHandler::CreateNativeSessionDescription(
return native_desc;
}
+scoped_refptr<base::SingleThreadTaskRunner>
+RTCPeerConnectionHandler::signaling_thread() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return dependency_factory_->GetWebRtcSignalingThread();
+}
+
+void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
+ const base::Closure& closure,
+ const char* trace_event_name) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread());
+ if (!thread.get() || thread->BelongsToCurrentThread()) {
+ TRACE_EVENT0("webrtc", trace_event_name);
+ closure.Run();
+ } else {
+ base::WaitableEvent event(false, false);
+ thread->PostTask(FROM_HERE,
+ base::Bind(&RunSynchronousClosure, closure,
+ base::Unretained(trace_event_name),
+ base::Unretained(&event)));
+ event.Wait();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.h b/chromium/content/renderer/media/rtc_peer_connection_handler.h
index 558ecbf631d..08003a95743 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.h
@@ -11,8 +11,13 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc/media_stream_track_metrics.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandler.h"
#include "third_party/WebKit/public/platform/WebRTCStatsRequest.h"
#include "third_party/WebKit/public/platform/WebRTCStatsResponse.h"
@@ -20,6 +25,7 @@
namespace blink {
class WebFrame;
class WebRTCDataChannelHandler;
+class WebRTCOfferOptions;
}
namespace content {
@@ -27,11 +33,13 @@ namespace content {
class PeerConnectionDependencyFactory;
class PeerConnectionTracker;
class RemoteMediaStreamImpl;
+class RtcDataChannelHandler;
+class RTCMediaConstraints;
class WebRtcMediaStreamAdapter;
// Mockable wrapper for blink::WebRTCStatsResponse
class CONTENT_EXPORT LocalRTCStatsResponse
- : public NON_EXPORTED_BASE(talk_base::RefCountInterface) {
+ : public NON_EXPORTED_BASE(rtc::RefCountInterface) {
public:
explicit LocalRTCStatsResponse(const blink::WebRTCStatsResponse& impl)
: impl_(impl) {
@@ -44,7 +52,7 @@ class CONTENT_EXPORT LocalRTCStatsResponse
blink::WebString name, blink::WebString value);
protected:
- virtual ~LocalRTCStatsResponse() {}
+ ~LocalRTCStatsResponse() override {}
// Constructor for creating mocks.
LocalRTCStatsResponse() {}
@@ -54,7 +62,7 @@ class CONTENT_EXPORT LocalRTCStatsResponse
// Mockable wrapper for blink::WebRTCStatsRequest
class CONTENT_EXPORT LocalRTCStatsRequest
- : public NON_EXPORTED_BASE(talk_base::RefCountInterface) {
+ : public NON_EXPORTED_BASE(rtc::RefCountInterface) {
public:
explicit LocalRTCStatsRequest(blink::WebRTCStatsRequest impl);
// Constructor for testing.
@@ -66,11 +74,10 @@ class CONTENT_EXPORT LocalRTCStatsRequest
virtual scoped_refptr<LocalRTCStatsResponse> createResponse();
protected:
- virtual ~LocalRTCStatsRequest();
+ ~LocalRTCStatsRequest() override;
private:
blink::WebRTCStatsRequest impl_;
- talk_base::scoped_refptr<LocalRTCStatsResponse> response_;
};
// RTCPeerConnectionHandler is a delegate for the RTC PeerConnection API
@@ -80,8 +87,7 @@ class CONTENT_EXPORT LocalRTCStatsRequest
// Callbacks to the webrtc::PeerConnectionObserver implementation also occur on
// the main render thread.
class CONTENT_EXPORT RTCPeerConnectionHandler
- : NON_EXPORTED_BASE(public blink::WebRTCPeerConnectionHandler),
- NON_EXPORTED_BASE(public webrtc::PeerConnectionObserver) {
+ : NON_EXPORTED_BASE(public blink::WebRTCPeerConnectionHandler) {
public:
RTCPeerConnectionHandler(
blink::WebRTCPeerConnectionHandlerClient* client,
@@ -91,120 +97,146 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// Destroy all existing RTCPeerConnectionHandler objects.
static void DestructAllHandlers();
+ static void ConvertOfferOptionsToConstraints(
+ const blink::WebRTCOfferOptions& options,
+ RTCMediaConstraints* output);
+
void associateWithFrame(blink::WebFrame* frame);
// Initialize method only used for unit test.
bool InitializeForTest(
const blink::WebRTCConfiguration& server_configuration,
const blink::WebMediaConstraints& options,
- PeerConnectionTracker* peer_connection_tracker);
+ const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker);
// blink::WebRTCPeerConnectionHandler implementation
virtual bool initialize(
const blink::WebRTCConfiguration& server_configuration,
- const blink::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebMediaConstraints& options) override;
virtual void createOffer(
const blink::WebRTCSessionDescriptionRequest& request,
- const blink::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebMediaConstraints& options) override;
+ virtual void createOffer(
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebRTCOfferOptions& options) override;
+
virtual void createAnswer(
const blink::WebRTCSessionDescriptionRequest& request,
- const blink::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebMediaConstraints& options) override;
virtual void setLocalDescription(
const blink::WebRTCVoidRequest& request,
- const blink::WebRTCSessionDescription& description) OVERRIDE;
+ const blink::WebRTCSessionDescription& description) override;
virtual void setRemoteDescription(
const blink::WebRTCVoidRequest& request,
- const blink::WebRTCSessionDescription& description) OVERRIDE;
+ const blink::WebRTCSessionDescription& description) override;
virtual blink::WebRTCSessionDescription localDescription()
- OVERRIDE;
+ override;
virtual blink::WebRTCSessionDescription remoteDescription()
- OVERRIDE;
+ override;
virtual bool updateICE(
const blink::WebRTCConfiguration& server_configuration,
- const blink::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebMediaConstraints& options) override;
virtual bool addICECandidate(
- const blink::WebRTCICECandidate& candidate) OVERRIDE;
+ const blink::WebRTCICECandidate& candidate) override;
virtual bool addICECandidate(
const blink::WebRTCVoidRequest& request,
- const blink::WebRTCICECandidate& candidate) OVERRIDE;
+ const blink::WebRTCICECandidate& candidate) override;
virtual void OnaddICECandidateResult(const blink::WebRTCVoidRequest& request,
bool result);
virtual bool addStream(
const blink::WebMediaStream& stream,
- const blink::WebMediaConstraints& options) OVERRIDE;
+ const blink::WebMediaConstraints& options) override;
virtual void removeStream(
- const blink::WebMediaStream& stream) OVERRIDE;
+ const blink::WebMediaStream& stream) override;
virtual void getStats(
- const blink::WebRTCStatsRequest& request) OVERRIDE;
+ const blink::WebRTCStatsRequest& request) override;
virtual blink::WebRTCDataChannelHandler* createDataChannel(
const blink::WebString& label,
- const blink::WebRTCDataChannelInit& init) OVERRIDE;
+ const blink::WebRTCDataChannelInit& init) override;
virtual blink::WebRTCDTMFSenderHandler* createDTMFSender(
- const blink::WebMediaStreamTrack& track) OVERRIDE;
- virtual void stop() OVERRIDE;
-
- // webrtc::PeerConnectionObserver implementation
- virtual void OnError() OVERRIDE;
- // Triggered when the SignalingState changed.
- virtual void OnSignalingChange(
- webrtc::PeerConnectionInterface::SignalingState new_state) OVERRIDE;
- virtual void OnAddStream(webrtc::MediaStreamInterface* stream) OVERRIDE;
- virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) OVERRIDE;
- virtual void OnIceCandidate(
- const webrtc::IceCandidateInterface* candidate) OVERRIDE;
- virtual void OnIceConnectionChange(
- webrtc::PeerConnectionInterface::IceConnectionState new_state) OVERRIDE;
- virtual void OnIceGatheringChange(
- webrtc::PeerConnectionInterface::IceGatheringState new_state) OVERRIDE;
-
- virtual void OnDataChannel(
- webrtc::DataChannelInterface* data_channel) OVERRIDE;
- virtual void OnRenegotiationNeeded() OVERRIDE;
+ const blink::WebMediaStreamTrack& track) override;
+ virtual void stop() override;
// Delegate functions to allow for mocking of WebKit interfaces.
// getStats takes ownership of request parameter.
- virtual void getStats(LocalRTCStatsRequest* request);
+ virtual void getStats(const scoped_refptr<LocalRTCStatsRequest>& request);
- // Calls GetStats on |native_peer_connection_|.
+ // Asynchronously calls native_peer_connection_->getStats on the signaling
+ // thread. If the |track_id| is empty, the |track_type| parameter is ignored.
void GetStats(webrtc::StatsObserver* observer,
- webrtc::MediaStreamTrackInterface* track,
- webrtc::PeerConnectionInterface::StatsOutputLevel level);
+ webrtc::PeerConnectionInterface::StatsOutputLevel level,
+ const std::string& track_id,
+ blink::WebMediaStreamSource::Type track_type);
- PeerConnectionTracker* peer_connection_tracker();
+ // Tells the |client_| to close RTCPeerConnection.
+ void CloseClientPeerConnection();
protected:
webrtc::PeerConnectionInterface* native_peer_connection() {
return native_peer_connection_.get();
}
+ class Observer;
+ friend class Observer;
+
+ void OnSignalingChange(
+ webrtc::PeerConnectionInterface::SignalingState new_state);
+ void OnIceConnectionChange(
+ webrtc::PeerConnectionInterface::IceConnectionState new_state);
+ void OnIceGatheringChange(
+ webrtc::PeerConnectionInterface::IceGatheringState new_state);
+ void OnRenegotiationNeeded();
+ void OnAddStream(scoped_ptr<RemoteMediaStreamImpl> stream);
+ void OnRemoveStream(
+ const scoped_refptr<webrtc::MediaStreamInterface>& stream);
+ void OnDataChannel(scoped_ptr<RtcDataChannelHandler> handler);
+ void OnIceCandidate(const std::string& sdp, const std::string& sdp_mid,
+ int sdp_mline_index, int component, int address_family);
+
private:
webrtc::SessionDescriptionInterface* CreateNativeSessionDescription(
- const blink::WebRTCSessionDescription& description,
+ const std::string& sdp, const std::string& type,
webrtc::SdpParseError* error);
+ // Virtual to allow mocks to override.
+ virtual scoped_refptr<base::SingleThreadTaskRunner> signaling_thread() const;
+
+ void RunSynchronousClosureOnSignalingThread(const base::Closure& closure,
+ const char* trace_event_name);
+
+ base::ThreadChecker thread_checker_;
+
// |client_| is a weak pointer, and is valid until stop() has returned.
blink::WebRTCPeerConnectionHandlerClient* client_;
// |dependency_factory_| is a raw pointer, and is valid for the lifetime of
// RenderThreadImpl.
- PeerConnectionDependencyFactory* dependency_factory_;
+ PeerConnectionDependencyFactory* const dependency_factory_;
blink::WebFrame* frame_;
ScopedVector<WebRtcMediaStreamAdapter> local_streams_;
- PeerConnectionTracker* peer_connection_tracker_;
+ base::WeakPtr<PeerConnectionTracker> peer_connection_tracker_;
MediaStreamTrackMetrics track_metrics_;
// Counter for a UMA stat reported at destruction time.
int num_data_channels_created_;
+ // Counter for number of IPv4 and IPv6 local candidates.
+ int num_local_candidates_ipv4_;
+ int num_local_candidates_ipv6_;
+
+ // To make sure the observer is released after the native_peer_connection_,
+ // it has to come first.
+ scoped_refptr<Observer> peer_connection_observer_;
+
// |native_peer_connection_| is the libjingle native PeerConnection object.
scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_;
@@ -212,6 +244,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
content::RemoteMediaStreamImpl*> RemoteStreamMap;
RemoteStreamMap remote_streams_;
scoped_refptr<webrtc::UMAObserver> uma_observer_;
+ base::TimeTicks ice_connection_checking_start_;
+ base::WeakPtrFactory<RTCPeerConnectionHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RTCPeerConnectionHandler);
};
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index 7ed95ffb2af..2ee286a5eff 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -7,13 +7,16 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_source.h"
#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "content/renderer/media/mock_peer_connection_impl.h"
#include "content/renderer/media/mock_web_rtc_peer_connection_handler_client.h"
@@ -22,7 +25,7 @@
#include "content/renderer/media/rtc_peer_connection_handler.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
-#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
@@ -40,6 +43,7 @@
#include "third_party/WebKit/public/platform/WebRTCStatsRequest.h"
#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
static const char kDummySdp[] = "dummy sdp";
@@ -49,9 +53,14 @@ using blink::WebRTCPeerConnectionHandlerClient;
using testing::NiceMock;
using testing::_;
using testing::Ref;
+using testing::SaveArg;
namespace content {
+ACTION_P2(ExitMessageLoop, message_loop, quit_closure) {
+ message_loop->PostTask(FROM_HERE, quit_closure);
+}
+
class MockRTCStatsResponse : public LocalRTCStatsResponse {
public:
MockRTCStatsResponse()
@@ -59,16 +68,16 @@ class MockRTCStatsResponse : public LocalRTCStatsResponse {
statistic_count_(0) {
}
- virtual size_t addReport(blink::WebString type,
- blink::WebString id,
- double timestamp) OVERRIDE {
+ size_t addReport(blink::WebString type,
+ blink::WebString id,
+ double timestamp) override {
++report_count_;
return report_count_;
}
- virtual void addStatistic(size_t report,
- blink::WebString name, blink::WebString value)
- OVERRIDE {
+ void addStatistic(size_t report,
+ blink::WebString name,
+ blink::WebString value) override {
++statistic_count_;
}
int report_count() const { return report_count_; }
@@ -85,20 +94,15 @@ class MockRTCStatsRequest : public LocalRTCStatsRequest {
: has_selector_(false),
request_succeeded_called_(false) {}
- virtual bool hasSelector() const OVERRIDE {
- return has_selector_;
- }
- virtual blink::WebMediaStreamTrack component() const OVERRIDE {
- return component_;
- }
- virtual scoped_refptr<LocalRTCStatsResponse> createResponse() OVERRIDE {
+ bool hasSelector() const override { return has_selector_; }
+ blink::WebMediaStreamTrack component() const override { return component_; }
+ scoped_refptr<LocalRTCStatsResponse> createResponse() override {
DCHECK(!response_.get());
- response_ = new talk_base::RefCountedObject<MockRTCStatsResponse>();
+ response_ = new rtc::RefCountedObject<MockRTCStatsResponse>();
return response_;
}
- virtual void requestSucceeded(const LocalRTCStatsResponse* response)
- OVERRIDE {
+ void requestSucceeded(const LocalRTCStatsResponse* response) override {
EXPECT_EQ(response, response_.get());
request_succeeded_called_ = true;
}
@@ -136,20 +140,20 @@ class MockPeerConnectionTracker : public PeerConnectionTracker {
MOCK_METHOD2(TrackCreateAnswer,
void(RTCPeerConnectionHandler* pc_handler,
const RTCMediaConstraints& constraints));
- MOCK_METHOD3(TrackSetSessionDescription,
+ MOCK_METHOD4(TrackSetSessionDescription,
void(RTCPeerConnectionHandler* pc_handler,
- const blink::WebRTCSessionDescription& desc,
+ const std::string& sdp, const std::string& type,
Source source));
MOCK_METHOD3(
TrackUpdateIce,
void(RTCPeerConnectionHandler* pc_handler,
- const std::vector<
- webrtc::PeerConnectionInterface::IceServer>& servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const RTCMediaConstraints& options));
- MOCK_METHOD3(TrackAddIceCandidate,
+ MOCK_METHOD4(TrackAddIceCandidate,
void(RTCPeerConnectionHandler* pc_handler,
const blink::WebRTCICECandidate& candidate,
- Source source));
+ Source source,
+ bool succeeded));
MOCK_METHOD3(TrackAddStream,
void(RTCPeerConnectionHandler* pc_handler,
const blink::WebMediaStream& stream,
@@ -195,6 +199,15 @@ class RTCPeerConnectionHandlerUnderTest : public RTCPeerConnectionHandler {
return static_cast<MockPeerConnectionImpl*>(
RTCPeerConnectionHandler::native_peer_connection());
}
+
+ webrtc::PeerConnectionObserver* observer() {
+ return native_peer_connection()->observer();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner>
+ signaling_thread() const override {
+ return base::ThreadTaskRunnerHandle::Get();
+ }
};
class RTCPeerConnectionHandlerTest : public ::testing::Test {
@@ -203,22 +216,30 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
child_process_.reset(new ChildProcess());
}
- virtual void SetUp() {
+ void SetUp() override {
mock_client_.reset(new NiceMock<MockWebRTCPeerConnectionHandlerClient>());
mock_dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
pc_handler_.reset(
- new RTCPeerConnectionHandlerUnderTest(mock_client_.get(),
- mock_dependency_factory_.get()));
+ new RTCPeerConnectionHandlerUnderTest(
+ mock_client_.get(), mock_dependency_factory_.get()));
mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>());
blink::WebRTCConfiguration config;
blink::WebMediaConstraints constraints;
- EXPECT_TRUE(pc_handler_->InitializeForTest(config, constraints,
- mock_tracker_.get()));
+ EXPECT_TRUE(pc_handler_->InitializeForTest(
+ config, constraints, mock_tracker_.get()->AsWeakPtr()));
mock_peer_connection_ = pc_handler_->native_peer_connection();
ASSERT_TRUE(mock_peer_connection_);
}
+ void TearDown() override {
+ pc_handler_.reset();
+ mock_tracker_.reset();
+ mock_dependency_factory_.reset();
+ mock_client_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
// Creates a WebKit local MediaStream.
blink::WebMediaStream CreateLocalMediaStream(
const std::string& stream_label) {
@@ -241,17 +262,25 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
static_cast<size_t>(1));
audio_tracks[0].initialize(audio_source.id(), audio_source);
- audio_tracks[0].setExtraData(
- new MediaStreamTrack(
- WebRtcLocalAudioTrackAdapter::Create(audio_track_label,
- NULL),
- true));
+ StreamDeviceInfo device_info(MEDIA_DEVICE_AUDIO_CAPTURE, "Mock device",
+ "mock_device_id");
+ MockMediaConstraintFactory constraint_factory;
+ const blink::WebMediaConstraints constraints =
+ constraint_factory.CreateWebMediaConstraints();
+ scoped_refptr<WebRtcAudioCapturer> capturer(
+ WebRtcAudioCapturer::CreateCapturer(
+ -1, device_info, constraints, nullptr, nullptr));
+ scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
+ WebRtcLocalAudioTrackAdapter::Create(audio_track_label, nullptr));
+ scoped_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get(), capturer, nullptr));
+ audio_tracks[0].setExtraData(native_track.release());
blink::WebVector<blink::WebMediaStreamTrack> video_tracks(
static_cast<size_t>(1));
- blink::WebMediaConstraints constraints;
- constraints.initialize();
+ blink::WebMediaConstraints video_constraints;
+ video_constraints.initialize();
video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack(
- native_video_source, constraints,
+ native_video_source, video_constraints,
MediaStreamVideoSource::ConstraintsCallback(), true);
blink::WebMediaStream local_stream;
@@ -278,7 +307,6 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
stream->AddTrack(video_track.get());
}
if (!audio_track_label.empty()) {
- scoped_refptr<WebRtcAudioCapturer> capturer;
scoped_refptr<webrtc::AudioTrackInterface> audio_track(
WebRtcLocalAudioTrackAdapter::Create(audio_track_label, NULL));
stream->AddTrack(audio_track.get());
@@ -337,11 +365,13 @@ TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) {
// before |mock_peer_connection| is called.
testing::InSequence sequence;
EXPECT_CALL(*mock_tracker_.get(),
- TrackSetSessionDescription(pc_handler_.get(), Ref(description),
+ TrackSetSessionDescription(pc_handler_.get(), kDummySdp,
+ kDummySdpType,
PeerConnectionTracker::SOURCE_LOCAL));
EXPECT_CALL(*mock_peer_connection_, SetLocalDescription(_, _));
pc_handler_->setLocalDescription(request, description);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(description.type(), pc_handler_->localDescription().type());
EXPECT_EQ(description.sdp(), pc_handler_->localDescription().sdp());
@@ -361,11 +391,13 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
// before |mock_peer_connection| is called.
testing::InSequence sequence;
EXPECT_CALL(*mock_tracker_.get(),
- TrackSetSessionDescription(pc_handler_.get(), Ref(description),
+ TrackSetSessionDescription(pc_handler_.get(), kDummySdp,
+ kDummySdpType,
PeerConnectionTracker::SOURCE_REMOTE));
EXPECT_CALL(*mock_peer_connection_, SetRemoteDescription(_, _));
pc_handler_->setRemoteDescription(request, description);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(description.type(), pc_handler_->remoteDescription().type());
EXPECT_EQ(description.sdp(), pc_handler_->remoteDescription().sdp());
@@ -389,16 +421,17 @@ TEST_F(RTCPeerConnectionHandlerTest, updateICE) {
TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) {
blink::WebRTCICECandidate candidate;
- candidate.initialize(kDummySdp, "mid", 1);
+ candidate.initialize(kDummySdp, "sdpMid", 1);
EXPECT_CALL(*mock_tracker_.get(),
TrackAddIceCandidate(pc_handler_.get(),
testing::Ref(candidate),
- PeerConnectionTracker::SOURCE_REMOTE));
+ PeerConnectionTracker::SOURCE_REMOTE,
+ true));
EXPECT_TRUE(pc_handler_->addICECandidate(candidate));
EXPECT_EQ(kDummySdp, mock_peer_connection_->ice_sdp());
EXPECT_EQ(1, mock_peer_connection_->sdp_mline_index());
- EXPECT_EQ("mid", mock_peer_connection_->sdp_mid());
+ EXPECT_EQ("sdpMid", mock_peer_connection_->sdp_mid());
}
TEST_F(RTCPeerConnectionHandlerTest, addAndRemoveStream) {
@@ -460,19 +493,20 @@ TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) {
TEST_F(RTCPeerConnectionHandlerTest, GetStatsNoSelector) {
scoped_refptr<MockRTCStatsRequest> request(
- new talk_base::RefCountedObject<MockRTCStatsRequest>());
+ new rtc::RefCountedObject<MockRTCStatsRequest>());
pc_handler_->getStats(request.get());
- // Note that callback gets executed synchronously by mock.
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(request->result());
EXPECT_LT(1, request->result()->report_count());
}
TEST_F(RTCPeerConnectionHandlerTest, GetStatsAfterClose) {
scoped_refptr<MockRTCStatsRequest> request(
- new talk_base::RefCountedObject<MockRTCStatsRequest>());
+ new rtc::RefCountedObject<MockRTCStatsRequest>());
pc_handler_->stop();
+ base::RunLoop().RunUntilIdle();
pc_handler_->getStats(request.get());
- // Note that callback gets executed synchronously by mock.
+ base::RunLoop().RunUntilIdle();
ASSERT_TRUE(request->result());
EXPECT_LT(1, request->result()->report_count());
}
@@ -487,16 +521,18 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) {
ASSERT_LE(1ul, tracks.size());
scoped_refptr<MockRTCStatsRequest> request(
- new talk_base::RefCountedObject<MockRTCStatsRequest>());
+ new rtc::RefCountedObject<MockRTCStatsRequest>());
request->setSelector(tracks[0]);
pc_handler_->getStats(request.get());
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, request->result()->report_count());
}
TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) {
scoped_refptr<webrtc::MediaStreamInterface> stream(
AddRemoteMockMediaStream("remote_stream", "video", "audio"));
- pc_handler_->OnAddStream(stream.get());
+ pc_handler_->observer()->OnAddStream(stream.get());
+ base::RunLoop().RunUntilIdle();
const blink::WebMediaStream& remote_stream = mock_client_->remote_stream();
blink::WebVector<blink::WebMediaStreamTrack> tracks;
@@ -504,9 +540,10 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) {
ASSERT_LE(1ul, tracks.size());
scoped_refptr<MockRTCStatsRequest> request(
- new talk_base::RefCountedObject<MockRTCStatsRequest>());
+ new rtc::RefCountedObject<MockRTCStatsRequest>());
request->setSelector(tracks[0]);
pc_handler_->getStats(request.get());
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, request->result()->report_count());
}
@@ -523,9 +560,10 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithBadSelector) {
mock_peer_connection_->SetGetStatsResult(false);
scoped_refptr<MockRTCStatsRequest> request(
- new talk_base::RefCountedObject<MockRTCStatsRequest>());
+ new rtc::RefCountedObject<MockRTCStatsRequest>());
request->setSelector(component);
pc_handler_->getStats(request.get());
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, request->result()->report_count());
}
@@ -539,7 +577,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) {
WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer));
EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer));
- pc_handler_->OnSignalingChange(new_state);
+ pc_handler_->observer()->OnSignalingChange(new_state);
new_state = webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
@@ -547,7 +585,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) {
WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer));
EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer));
- pc_handler_->OnSignalingChange(new_state);
+ pc_handler_->observer()->OnSignalingChange(new_state);
new_state = webrtc::PeerConnectionInterface::kHaveLocalOffer;
EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
@@ -555,7 +593,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) {
WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer));
EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer));
- pc_handler_->OnSignalingChange(new_state);
+ pc_handler_->observer()->OnSignalingChange(new_state);
new_state = webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
@@ -563,7 +601,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) {
WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer));
EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer));
- pc_handler_->OnSignalingChange(new_state);
+ pc_handler_->observer()->OnSignalingChange(new_state);
new_state = webrtc::PeerConnectionInterface::kClosed;
EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
@@ -571,7 +609,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) {
WebRTCPeerConnectionHandlerClient::SignalingStateClosed));
EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
WebRTCPeerConnectionHandlerClient::SignalingStateClosed));
- pc_handler_->OnSignalingChange(new_state);
+ pc_handler_->observer()->OnSignalingChange(new_state);
}
TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
@@ -584,7 +622,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionChecking;
EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
@@ -592,7 +630,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionConnected;
EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
@@ -600,7 +638,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionCompleted;
EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
@@ -608,7 +646,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionFailed;
EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
@@ -616,7 +654,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
@@ -624,7 +662,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceConnectionClosed;
EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
@@ -632,7 +670,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed));
EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed));
- pc_handler_->OnIceConnectionChange(new_state);
+ pc_handler_->observer()->OnIceConnectionChange(new_state);
}
TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
@@ -655,13 +693,13 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
webrtc::PeerConnectionInterface::IceGatheringState new_state =
webrtc::PeerConnectionInterface::kIceGatheringNew;
- pc_handler_->OnIceGatheringChange(new_state);
+ pc_handler_->observer()->OnIceGatheringChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceGatheringGathering;
- pc_handler_->OnIceGatheringChange(new_state);
+ pc_handler_->observer()->OnIceGatheringChange(new_state);
new_state = webrtc::PeerConnectionInterface::kIceGatheringComplete;
- pc_handler_->OnIceGatheringChange(new_state);
+ pc_handler_->observer()->OnIceGatheringChange(new_state);
// Check NULL candidate after ice gathering is completed.
EXPECT_EQ("", mock_client_->candidate_mid());
@@ -693,8 +731,10 @@ TEST_F(RTCPeerConnectionHandlerTest, OnAddAndOnRemoveStream) {
testing::Property(&blink::WebMediaStream::id,
base::UTF8ToUTF16(remote_stream_label))));
- pc_handler_->OnAddStream(remote_stream.get());
- pc_handler_->OnRemoveStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream.get());
+ base::RunLoop().RunUntilIdle();
+ pc_handler_->observer()->OnRemoveStream(remote_stream.get());
+ base::RunLoop().RunUntilIdle();
}
// This test that WebKit is notified about remote track state changes.
@@ -707,7 +747,8 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
testing::Property(&blink::WebMediaStream::id,
base::UTF8ToUTF16(remote_stream_label))));
- pc_handler_->OnAddStream(remote_stream.get());
+ pc_handler_->observer()->OnAddStream(remote_stream.get());
+ base::RunLoop().RunUntilIdle();
const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
@@ -716,31 +757,40 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
audio_tracks[0].source().readyState());
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
- webkit_stream.videoTracks(video_tracks);
+ webkit_stream.videoTracks(video_tracks);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
video_tracks[0].source().readyState());
remote_stream->GetAudioTracks()[0]->set_state(
webrtc::MediaStreamTrackInterface::kEnded);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
audio_tracks[0].source().readyState());
remote_stream->GetVideoTracks()[0]->set_state(
webrtc::MediaStreamTrackInterface::kEnded);
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
video_tracks[0].source().readyState());
}
TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
std::string remote_stream_label("remote_stream");
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
- AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+ base::RunLoop run_loop;
+ // Grab the added media stream when it's been successfully added to the PC.
+ blink::WebMediaStream webkit_stream;
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
testing::Property(&blink::WebMediaStream::id,
- base::UTF8ToUTF16(remote_stream_label))));
- pc_handler_->OnAddStream(remote_stream.get());
- const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+ base::UTF8ToUTF16(remote_stream_label))))
+ .WillOnce(
+ DoAll(SaveArg<0>(&webkit_stream),
+ ExitMessageLoop(&message_loop_, run_loop.QuitClosure())));
+
+ scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+ pc_handler_->observer()->OnAddStream(remote_stream.get());
+ run_loop.Run();
{
// Test in a small scope so that |audio_tracks| don't hold on to destroyed
@@ -754,6 +804,7 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
scoped_refptr<webrtc::AudioTrackInterface> webrtc_track =
remote_stream->GetAudioTracks()[0].get();
remote_stream->RemoveTrack(webrtc_track.get());
+ base::RunLoop().RunUntilIdle();
{
blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1;
@@ -761,8 +812,11 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
EXPECT_EQ(0u, modified_audio_tracks1.size());
}
+ blink::WebHeap::collectGarbageForTesting();
+
// Add the WebRtc audio track again.
remote_stream->AddTrack(webrtc_track.get());
+ base::RunLoop().RunUntilIdle();
blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks2;
webkit_stream.audioTracks(modified_audio_tracks2);
EXPECT_EQ(1u, modified_audio_tracks2.size());
@@ -770,14 +824,21 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
std::string remote_stream_label("remote_stream");
- scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
- AddRemoteMockMediaStream(remote_stream_label, "video", "video"));
+ base::RunLoop run_loop;
+ // Grab the added media stream when it's been successfully added to the PC.
+ blink::WebMediaStream webkit_stream;
EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
testing::Property(&blink::WebMediaStream::id,
- base::UTF8ToUTF16(remote_stream_label))));
- pc_handler_->OnAddStream(remote_stream.get());
- const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
+ base::UTF8ToUTF16(remote_stream_label))))
+ .WillOnce(
+ DoAll(SaveArg<0>(&webkit_stream),
+ ExitMessageLoop(&message_loop_, run_loop.QuitClosure())));
+
+ scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+ pc_handler_->observer()->OnAddStream(remote_stream.get());
+ run_loop.Run();
{
// Test in a small scope so that |video_tracks| don't hold on to destroyed
@@ -791,30 +852,98 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
scoped_refptr<webrtc::VideoTrackInterface> webrtc_track =
remote_stream->GetVideoTracks()[0].get();
remote_stream->RemoveTrack(webrtc_track.get());
+ base::RunLoop().RunUntilIdle();
{
blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1;
webkit_stream.videoTracks(modified_video_tracks1);
EXPECT_EQ(0u, modified_video_tracks1.size());
}
+ blink::WebHeap::collectGarbageForTesting();
+
// Add the WebRtc video track again.
remote_stream->AddTrack(webrtc_track.get());
+ base::RunLoop().RunUntilIdle();
blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks2;
webkit_stream.videoTracks(modified_video_tracks2);
EXPECT_EQ(1u, modified_video_tracks2.size());
}
+TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddTracksFromRemoteStream) {
+ std::string remote_stream_label("remote_stream");
+ base::RunLoop run_loop;
+
+ // Grab the added media stream when it's been successfully added to the PC.
+ blink::WebMediaStream webkit_stream;
+ EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
+ testing::Property(&blink::WebMediaStream::id,
+ base::UTF8ToUTF16(remote_stream_label))))
+ .WillOnce(
+ DoAll(SaveArg<0>(&webkit_stream),
+ ExitMessageLoop(&message_loop_, run_loop.QuitClosure())));
+
+ scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+ pc_handler_->observer()->OnAddStream(remote_stream.get());
+ run_loop.Run();
+
+ {
+ // Test in a small scope so that |audio_tracks| don't hold on to destroyed
+ // source later.
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ webkit_stream.audioTracks(audio_tracks);
+ EXPECT_EQ(1u, audio_tracks.size());
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ webkit_stream.videoTracks(video_tracks);
+ EXPECT_EQ(1u, video_tracks.size());
+ }
+
+ // Remove the Webrtc tracks from the MediaStream.
+ auto audio_track = remote_stream->GetAudioTracks()[0];
+ EXPECT_TRUE(remote_stream->RemoveTrack(audio_track.get()));
+ auto video_track = remote_stream->GetVideoTracks()[0];
+ EXPECT_TRUE(remote_stream->RemoveTrack(video_track.get()));
+ base::RunLoop().RunUntilIdle();
+
+ {
+ blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks;
+ webkit_stream.audioTracks(modified_audio_tracks);
+ EXPECT_EQ(0u, modified_audio_tracks.size());
+ blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks;
+ webkit_stream.videoTracks(modified_video_tracks);
+ EXPECT_EQ(0u, modified_video_tracks.size());
+ }
+
+ blink::WebHeap::collectGarbageForTesting();
+
+ // Add the tracks again.
+ remote_stream->AddTrack(audio_track.get());
+ base::RunLoop().RunUntilIdle();
+ remote_stream->AddTrack(video_track.get());
+ base::RunLoop().RunUntilIdle();
+
+ blink::WebHeap::collectGarbageForTesting();
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ webkit_stream.audioTracks(audio_tracks);
+ EXPECT_EQ(1u, audio_tracks.size());
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ webkit_stream.videoTracks(video_tracks);
+ EXPECT_EQ(1u, video_tracks.size());
+}
+
TEST_F(RTCPeerConnectionHandlerTest, OnIceCandidate) {
testing::InSequence sequence;
EXPECT_CALL(*mock_tracker_.get(),
TrackAddIceCandidate(pc_handler_.get(), _,
- PeerConnectionTracker::SOURCE_LOCAL));
+ PeerConnectionTracker::SOURCE_LOCAL, true));
EXPECT_CALL(*mock_client_.get(), didGenerateICECandidate(_));
scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
- mock_dependency_factory_->CreateIceCandidate("mid", 1, kDummySdp));
- pc_handler_->OnIceCandidate(native_candidate.get());
- EXPECT_EQ("mid", mock_client_->candidate_mid());
+ mock_dependency_factory_->CreateIceCandidate("sdpMid", 1, kDummySdp));
+ pc_handler_->observer()->OnIceCandidate(native_candidate.get());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ("sdpMid", mock_client_->candidate_mid());
EXPECT_EQ(1, mock_client_->candidate_mlineindex());
EXPECT_EQ(kDummySdp, mock_client_->candidate_sdp());
}
@@ -824,7 +953,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnRenegotiationNeeded) {
EXPECT_CALL(*mock_tracker_.get(),
TrackOnRenegotiationNeeded(pc_handler_.get()));
EXPECT_CALL(*mock_client_.get(), negotiationNeeded());
- pc_handler_->OnRenegotiationNeeded();
+ pc_handler_->observer()->OnRenegotiationNeeded();
}
TEST_F(RTCPeerConnectionHandlerTest, CreateDataChannel) {
diff --git a/chromium/content/renderer/media/rtc_video_decoder.cc b/chromium/content/renderer/media/rtc_video_decoder.cc
index 3987767b353..60ae893d9d4 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder.cc
@@ -61,13 +61,9 @@ RTCVideoDecoder::SHMBuffer::~SHMBuffer() { shm->Close(); }
RTCVideoDecoder::BufferData::BufferData(int32 bitstream_buffer_id,
uint32_t timestamp,
- int width,
- int height,
size_t size)
: bitstream_buffer_id(bitstream_buffer_id),
timestamp(timestamp),
- width(width),
- height(height),
size(size) {}
RTCVideoDecoder::BufferData::BufferData() {}
@@ -75,8 +71,10 @@ RTCVideoDecoder::BufferData::BufferData() {}
RTCVideoDecoder::BufferData::~BufferData() {}
RTCVideoDecoder::RTCVideoDecoder(
+ webrtc::VideoCodecType type,
const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories)
- : factories_(factories),
+ : video_codec_type_(type),
+ factories_(factories),
decoder_texture_target_(0),
next_picture_buffer_id_(0),
state_(UNINITIALIZED),
@@ -118,7 +116,10 @@ scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
media::VideoCodecProfile profile;
switch (type) {
case webrtc::kVideoCodecVP8:
- profile = media::VP8PROFILE_MAIN;
+ profile = media::VP8PROFILE_ANY;
+ break;
+ case webrtc::kVideoCodecH264:
+ profile = media::H264PROFILE_MAIN;
break;
default:
DVLOG(2) << "Video codec not supported:" << type;
@@ -126,7 +127,7 @@ scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
}
base::WaitableEvent waiter(true, false);
- decoder.reset(new RTCVideoDecoder(factories));
+ decoder.reset(new RTCVideoDecoder(type, factories));
decoder->factories_->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&RTCVideoDecoder::CreateVDA,
@@ -134,7 +135,7 @@ scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
profile,
&waiter));
waiter.Wait();
- // vda can be NULL if VP8 is not supported.
+ // vda can be NULL if the codec is not supported.
if (decoder->vda_ != NULL) {
decoder->state_ = INITIALIZED;
} else {
@@ -146,8 +147,9 @@ scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
int32_t RTCVideoDecoder::InitDecode(const webrtc::VideoCodec* codecSettings,
int32_t /*numberOfCores*/) {
DVLOG(2) << "InitDecode";
- DCHECK_EQ(codecSettings->codecType, webrtc::kVideoCodecVP8);
- if (codecSettings->codecSpecific.VP8.feedbackModeOn) {
+ DCHECK_EQ(video_codec_type_, codecSettings->codecType);
+ if (codecSettings->codecType == webrtc::kVideoCodecVP8 &&
+ codecSettings->codecSpecific.VP8.feedbackModeOn) {
LOG(ERROR) << "Feedback mode not supported";
return RecordInitDecodeUMA(WEBRTC_VIDEO_CODEC_ERROR);
}
@@ -227,8 +229,6 @@ int32_t RTCVideoDecoder::Decode(
// Create buffer metadata.
BufferData buffer_data(next_bitstream_buffer_id_,
inputImage._timeStamp,
- frame_size_.width(),
- frame_size_.height(),
inputImage._length);
// Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & ID_LAST;
@@ -364,13 +364,21 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
}
const media::PictureBuffer& pb = it->second;
+ // Validate picture rectangle from GPU.
+ if (picture.visible_rect().IsEmpty() ||
+ !gfx::Rect(pb.size()).Contains(picture.visible_rect())) {
+ NOTREACHED() << "Invalid picture size from VDA: "
+ << picture.visible_rect().ToString() << " should fit in "
+ << pb.size().ToString();
+ NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
+ return;
+ }
+
// Create a media::VideoFrame.
- uint32_t timestamp = 0, width = 0, height = 0;
- size_t size = 0;
- GetBufferData(
- picture.bitstream_buffer_id(), &timestamp, &width, &height, &size);
+ uint32_t timestamp = 0;
+ GetBufferData(picture.bitstream_buffer_id(), &timestamp);
scoped_refptr<media::VideoFrame> frame =
- CreateVideoFrame(picture, pb, timestamp, width, height, size);
+ CreateVideoFrame(picture, pb, timestamp);
bool inserted =
picture_buffers_at_display_.insert(std::make_pair(
picture.picture_buffer_id(),
@@ -380,7 +388,11 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
// Create a WebRTC video frame.
webrtc::RefCountImpl<NativeHandleImpl>* handle =
new webrtc::RefCountImpl<NativeHandleImpl>(frame);
- webrtc::TextureVideoFrame decoded_image(handle, width, height, timestamp, 0);
+ webrtc::TextureVideoFrame decoded_image(handle,
+ picture.visible_rect().width(),
+ picture.visible_rect().height(),
+ timestamp,
+ 0);
// Invoke decode callback. WebRTC expects no callback after Reset or Release.
{
@@ -423,11 +435,8 @@ static void ReadPixelsSync(
scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
const media::Picture& picture,
const media::PictureBuffer& pb,
- uint32_t timestamp,
- uint32_t width,
- uint32_t height,
- size_t size) {
- gfx::Rect visible_rect(width, height);
+ uint32_t timestamp) {
+ gfx::Rect visible_rect(picture.visible_rect());
DCHECK(decoder_texture_target_);
// Convert timestamp from 90KHz to ms.
base::TimeDelta timestamp_ms = base::TimeDelta::FromInternalValue(
@@ -639,11 +648,9 @@ void RTCVideoDecoder::ReleaseMailbox(
const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
int64 picture_buffer_id,
uint32 texture_id,
- const std::vector<uint32>& release_sync_points) {
+ uint32 release_sync_point) {
DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
-
- for (size_t i = 0; i < release_sync_points.size(); i++)
- factories->WaitSyncPoint(release_sync_points[i]);
+ factories->WaitSyncPoint(release_sync_point);
if (decoder) {
decoder->ReusePictureBuffer(picture_buffer_id);
@@ -779,18 +786,13 @@ void RTCVideoDecoder::RecordBufferData(const BufferData& buffer_data) {
}
void RTCVideoDecoder::GetBufferData(int32 bitstream_buffer_id,
- uint32_t* timestamp,
- uint32_t* width,
- uint32_t* height,
- size_t* size) {
+ uint32_t* timestamp) {
for (std::list<BufferData>::iterator it = input_buffer_data_.begin();
it != input_buffer_data_.end();
++it) {
if (it->bitstream_buffer_id != bitstream_buffer_id)
continue;
*timestamp = it->timestamp;
- *width = it->width;
- *height = it->height;
return;
}
NOTREACHED() << "Missing bitstream buffer id: " << bitstream_buffer_id;
diff --git a/chromium/content/renderer/media/rtc_video_decoder.h b/chromium/content/renderer/media/rtc_video_decoder.h
index d1a04e5cd9b..29adee642e6 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.h
+++ b/chromium/content/renderer/media/rtc_video_decoder.h
@@ -45,7 +45,7 @@ class CONTENT_EXPORT RTCVideoDecoder
: NON_EXPORTED_BASE(public webrtc::VideoDecoder),
public media::VideoDecodeAccelerator::Client {
public:
- virtual ~RTCVideoDecoder();
+ ~RTCVideoDecoder() override;
// Creates a RTCVideoDecoder. Returns NULL if failed. The video decoder will
// run on the message loop of |factories|.
@@ -55,35 +55,34 @@ class CONTENT_EXPORT RTCVideoDecoder
// webrtc::VideoDecoder implementation.
// Called on WebRTC DecodingThread.
- virtual int32_t InitDecode(const webrtc::VideoCodec* codecSettings,
- int32_t numberOfCores) OVERRIDE;
+ int32_t InitDecode(const webrtc::VideoCodec* codecSettings,
+ int32_t numberOfCores) override;
// Called on WebRTC DecodingThread.
- virtual int32_t Decode(
- const webrtc::EncodedImage& inputImage,
- bool missingFrames,
- const webrtc::RTPFragmentationHeader* fragmentation,
- const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL,
- int64_t renderTimeMs = -1) OVERRIDE;
+ int32_t Decode(const webrtc::EncodedImage& inputImage,
+ bool missingFrames,
+ const webrtc::RTPFragmentationHeader* fragmentation,
+ const webrtc::CodecSpecificInfo* codecSpecificInfo = NULL,
+ int64_t renderTimeMs = -1) override;
// Called on WebRTC DecodingThread.
- virtual int32_t RegisterDecodeCompleteCallback(
- webrtc::DecodedImageCallback* callback) OVERRIDE;
+ int32_t RegisterDecodeCompleteCallback(
+ webrtc::DecodedImageCallback* callback) override;
// Called on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
- virtual int32_t Release() OVERRIDE;
+ int32_t Release() override;
// Called on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
- virtual int32_t Reset() OVERRIDE;
+ int32_t Reset() override;
// VideoDecodeAccelerator::Client implementation.
- virtual void ProvidePictureBuffers(uint32 count,
- const gfx::Size& size,
- uint32 texture_target) OVERRIDE;
- virtual void DismissPictureBuffer(int32 id) OVERRIDE;
- virtual void PictureReady(const media::Picture& picture) OVERRIDE;
- virtual void NotifyEndOfBitstreamBuffer(int32 id) OVERRIDE;
- virtual void NotifyFlushDone() OVERRIDE;
- virtual void NotifyResetDone() OVERRIDE;
- virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE;
+ void ProvidePictureBuffers(uint32 count,
+ const gfx::Size& size,
+ uint32 texture_target) override;
+ void DismissPictureBuffer(int32 id) override;
+ void PictureReady(const media::Picture& picture) override;
+ void NotifyEndOfBitstreamBuffer(int32 id) override;
+ void NotifyFlushDone() override;
+ void NotifyResetDone() override;
+ void NotifyError(media::VideoDecodeAccelerator::Error error) override;
private:
class SHMBuffer;
@@ -91,15 +90,11 @@ class CONTENT_EXPORT RTCVideoDecoder
struct BufferData {
BufferData(int32 bitstream_buffer_id,
uint32_t timestamp,
- int width,
- int height,
size_t size);
BufferData();
~BufferData();
int32 bitstream_buffer_id;
uint32_t timestamp; // in 90KHz
- uint32_t width;
- uint32_t height;
size_t size; // buffer size
};
@@ -107,6 +102,7 @@ class CONTENT_EXPORT RTCVideoDecoder
FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsFirstBufferAfterReset);
RTCVideoDecoder(
+ webrtc::VideoCodecType type,
const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories);
// Requests a buffer to be decoded by VDA.
@@ -138,10 +134,7 @@ class CONTENT_EXPORT RTCVideoDecoder
scoped_refptr<media::VideoFrame> CreateVideoFrame(
const media::Picture& picture,
const media::PictureBuffer& pb,
- uint32_t timestamp,
- uint32_t width,
- uint32_t height,
- size_t size);
+ uint32_t timestamp);
// Resets VDA.
void ResetInternal();
@@ -152,7 +145,7 @@ class CONTENT_EXPORT RTCVideoDecoder
const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
int64 picture_buffer_id,
uint32 texture_id,
- const std::vector<uint32>& release_sync_points);
+ uint32 release_sync_point);
// Tells VDA that a picture buffer can be recycled.
void ReusePictureBuffer(int64 picture_buffer_id);
@@ -176,11 +169,7 @@ class CONTENT_EXPORT RTCVideoDecoder
// Stores the buffer metadata to |input_buffer_data_|.
void RecordBufferData(const BufferData& buffer_data);
// Gets the buffer metadata from |input_buffer_data_|.
- void GetBufferData(int32 bitstream_buffer_id,
- uint32_t* timestamp,
- uint32_t* width,
- uint32_t* height,
- size_t* size);
+ void GetBufferData(int32 bitstream_buffer_id, uint32_t* timestamp);
// Records the result of InitDecode to UMA and returns |status|.
int32_t RecordInitDecodeUMA(int32_t status);
@@ -202,6 +191,9 @@ class CONTENT_EXPORT RTCVideoDecoder
// The hardware video decoder.
scoped_ptr<media::VideoDecodeAccelerator> vda_;
+ // The video codec type, as reported by WebRTC.
+ const webrtc::VideoCodecType video_codec_type_;
+
// The size of the incoming video frames.
gfx::Size frame_size_;
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory.h b/chromium/content/renderer/media/rtc_video_decoder_factory.h
index d40203f002d..19c8519b384 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory.h
+++ b/chromium/content/renderer/media/rtc_video_decoder_factory.h
@@ -27,16 +27,16 @@ class CONTENT_EXPORT RTCVideoDecoderFactory
public:
explicit RTCVideoDecoderFactory(
const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories);
- virtual ~RTCVideoDecoderFactory();
+ ~RTCVideoDecoderFactory() override;
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
- virtual webrtc::VideoDecoder* CreateVideoDecoder(webrtc::VideoCodecType type)
- OVERRIDE;
+ webrtc::VideoDecoder* CreateVideoDecoder(
+ webrtc::VideoCodecType type) override;
// Runs on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
- virtual void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) OVERRIDE;
+ void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override;
private:
scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
diff --git a/chromium/content/renderer/media/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
index e6dfe3eeaa1..4500355bdd6 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
@@ -31,25 +31,23 @@ class RTCVideoDecoderTest : public ::testing::Test,
memset(&codec_, 0, sizeof(codec_));
}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
ASSERT_TRUE(vda_thread_.Start());
vda_task_runner_ = vda_thread_.message_loop_proxy();
mock_vda_ = new media::MockVideoDecodeAccelerator;
- EXPECT_CALL(*mock_gpu_factories_, GetTaskRunner())
+ EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
.WillRepeatedly(Return(vda_task_runner_));
- EXPECT_CALL(*mock_gpu_factories_, DoCreateVideoDecodeAccelerator())
+ EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
.WillRepeatedly(Return(mock_vda_));
- EXPECT_CALL(*mock_gpu_factories_, CreateSharedMemory(_))
+ EXPECT_CALL(*mock_gpu_factories_.get(), CreateSharedMemory(_))
.WillRepeatedly(Return(static_cast<base::SharedMemory*>(NULL)));
EXPECT_CALL(*mock_vda_, Initialize(_, _))
.Times(1)
.WillRepeatedly(Return(true));
EXPECT_CALL(*mock_vda_, Destroy()).Times(1);
- rtc_decoder_ =
- RTCVideoDecoder::Create(webrtc::kVideoCodecVP8, mock_gpu_factories_);
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
VLOG(2) << "TearDown";
EXPECT_TRUE(vda_thread_.IsRunning());
RunUntilIdle(); // Wait until all callbascks complete.
@@ -59,15 +57,21 @@ class RTCVideoDecoderTest : public ::testing::Test,
vda_thread_.Stop();
}
- virtual int32_t Decoded(webrtc::I420VideoFrame& decoded_image) OVERRIDE {
+ int32_t Decoded(webrtc::I420VideoFrame& decoded_image) override {
VLOG(2) << "Decoded";
EXPECT_EQ(vda_task_runner_, base::MessageLoopProxy::current());
return WEBRTC_VIDEO_CODEC_OK;
}
+ void CreateDecoder(webrtc::VideoCodecType codec_type) {
+ VLOG(2) << "CreateDecoder";
+ codec_.codecType = codec_type;
+ rtc_decoder_ =
+ RTCVideoDecoder::Create(codec_type, mock_gpu_factories_);
+ }
+
void Initialize() {
VLOG(2) << "Initialize";
- codec_.codecType = webrtc::kVideoCodecVP8;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
rtc_decoder_->RegisterDecodeCompleteCallback(this));
@@ -104,24 +108,32 @@ class RTCVideoDecoderTest : public ::testing::Test,
};
TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
scoped_ptr<RTCVideoDecoder> null_rtc_decoder(
RTCVideoDecoder::Create(webrtc::kVideoCodecI420, mock_gpu_factories_));
EXPECT_EQ(NULL, null_rtc_decoder.get());
}
+TEST_F(RTCVideoDecoderTest, CreateAndInitSucceedsForH264Codec) {
+ CreateDecoder(webrtc::kVideoCodecH264);
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
+}
+
TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
- codec_.codecType = webrtc::kVideoCodecVP8;
+ CreateDecoder(webrtc::kVideoCodecVP8);
codec_.codecSpecific.VP8.feedbackModeOn = true;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
webrtc::EncodedImage input_image;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
Initialize();
webrtc::EncodedImage input_image;
input_image._completeFrame = false;
@@ -130,6 +142,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
Initialize();
webrtc::EncodedImage input_image;
input_image._completeFrame = true;
@@ -139,6 +152,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
}
TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
Initialize();
EXPECT_CALL(*mock_vda_, Reset())
.WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
@@ -146,6 +160,7 @@ TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
}
TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
Initialize();
EXPECT_CALL(*mock_vda_, Reset())
.WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
@@ -153,6 +168,7 @@ TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
}
TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
EXPECT_CALL(*mock_vda_, Reset())
.WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
Initialize();
@@ -162,6 +178,7 @@ TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
}
TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
RTCVideoDecoder::ID_INVALID));
@@ -187,6 +204,7 @@ TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
}
TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
+ CreateDecoder(webrtc::kVideoCodecVP8);
EXPECT_TRUE(
rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
EXPECT_FALSE(
diff --git a/chromium/content/renderer/media/rtc_video_encoder.cc b/chromium/content/renderer/media/rtc_video_encoder.cc
index 22f17a17836..517b2d9c5d6 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/rtc_video_encoder.cc
@@ -16,6 +16,7 @@
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
#include "media/filters/gpu_video_accelerator_factories.h"
+#include "media/filters/h264_parser.h"
#include "media/video/video_encode_accelerator.h"
#include "third_party/webrtc/system_wrappers/interface/tick_util.h"
@@ -27,6 +28,64 @@
namespace content {
+namespace {
+
+// Translate from webrtc::VideoCodecType and webrtc::VideoCodec to
+// media::VideoCodecProfile.
+media::VideoCodecProfile WebRTCVideoCodecToVideoCodecProfile(
+ webrtc::VideoCodecType type, const webrtc::VideoCodec* codec_settings) {
+ DCHECK_EQ(type, codec_settings->codecType);
+ switch (type) {
+ case webrtc::kVideoCodecVP8:
+ return media::VP8PROFILE_ANY;
+ case webrtc::kVideoCodecH264: {
+ switch (codec_settings->codecSpecific.H264.profile) {
+ case webrtc::kProfileBase:
+ return media::H264PROFILE_BASELINE;
+ case webrtc::kProfileMain:
+ return media::H264PROFILE_MAIN;
+ }
+ }
+ default:
+ NOTREACHED() << "Unrecognized video codec type";
+ return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ }
+}
+
+// Populates struct webrtc::RTPFragmentationHeader for H264 codec.
+// Each entry specifies the offset and length (excluding start code) of a NALU.
+// Returns true if successful.
+bool GetRTPFragmentationHeaderH264(webrtc::RTPFragmentationHeader* header,
+ const uint8_t* data, uint32_t length) {
+ media::H264Parser parser;
+ parser.SetStream(data, length);
+
+ std::vector<media::H264NALU> nalu_vector;
+ while (true) {
+ media::H264NALU nalu;
+ const media::H264Parser::Result result = parser.AdvanceToNextNALU(&nalu);
+ if (result == media::H264Parser::kOk) {
+ nalu_vector.push_back(nalu);
+ } else if (result == media::H264Parser::kEOStream) {
+ break;
+ } else {
+ DLOG(ERROR) << "Unexpected H264 parser result";
+ return false;
+ }
+ }
+
+ header->VerifyAndAllocateFragmentationHeader(nalu_vector.size());
+ for (size_t i = 0; i < nalu_vector.size(); ++i) {
+ header->fragmentationOffset[i] = nalu_vector[i].data - data;
+ header->fragmentationLength[i] = nalu_vector[i].size;
+ header->fragmentationPlType[i] = 0;
+ header->fragmentationTimeDiff[i] = 0;
+ }
+ return true;
+}
+
+} // namespace
+
// This private class of RTCVideoEncoder does the actual work of communicating
// with a media::VideoEncodeAccelerator for handling video encoding. It can
// be created on any thread, but should subsequently be posted to (and Destroy()
@@ -76,13 +135,13 @@ class RTCVideoEncoder::Impl
void Destroy();
// media::VideoEncodeAccelerator::Client implementation.
- virtual void RequireBitstreamBuffers(unsigned int input_count,
- const gfx::Size& input_coded_size,
- size_t output_buffer_size) OVERRIDE;
- virtual void BitstreamBufferReady(int32 bitstream_buffer_id,
- size_t payload_size,
- bool key_frame) OVERRIDE;
- virtual void NotifyError(media::VideoEncodeAccelerator::Error error) OVERRIDE;
+ void RequireBitstreamBuffers(unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) override;
+ void BitstreamBufferReady(int32 bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame) override;
+ void NotifyError(media::VideoEncodeAccelerator::Error error) override;
private:
friend class base::RefCountedThreadSafe<Impl>;
@@ -94,7 +153,7 @@ class RTCVideoEncoder::Impl
kOutputBufferCount = 3,
};
- virtual ~Impl();
+ ~Impl() override;
// Perform encoding on an input frame from the input queue.
void EncodeOneFrame();
@@ -445,7 +504,7 @@ void RTCVideoEncoder::Impl::EncodeOneFrame() {
input_buffer->handle(),
base::TimeDelta(),
base::Bind(&RTCVideoEncoder::Impl::EncodeFrameFinished, this, index));
- if (!frame) {
+ if (!frame.get()) {
DLOG(ERROR) << "Impl::EncodeOneFrame(): failed to create frame";
NOTIFY_ERROR(media::VideoEncodeAccelerator::kPlatformFailureError);
return;
@@ -509,21 +568,20 @@ void RTCVideoEncoder::Impl::SignalAsyncWaiter(int32_t retval) {
RTCVideoEncoder::RTCVideoEncoder(
webrtc::VideoCodecType type,
- media::VideoCodecProfile profile,
const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
: video_codec_type_(type),
- video_codec_profile_(profile),
gpu_factories_(gpu_factories),
encoded_image_callback_(NULL),
impl_status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED),
weak_factory_(this) {
- DVLOG(1) << "RTCVideoEncoder(): profile=" << profile;
+ DVLOG(1) << "RTCVideoEncoder(): codec type=" << type;
}
RTCVideoEncoder::~RTCVideoEncoder() {
+ DVLOG(3) << "~RTCVideoEncoder";
DCHECK(thread_checker_.CalledOnValidThread());
Release();
- DCHECK(!impl_);
+ DCHECK(!impl_.get());
}
int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
@@ -534,7 +592,10 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
<< ", height=" << codec_settings->height
<< ", startBitrate=" << codec_settings->startBitrate;
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!impl_);
+ DCHECK(!impl_.get());
+
+ media::VideoCodecProfile profile = WebRTCVideoCodecToVideoCodecProfile(
+ video_codec_type_, codec_settings);
weak_factory_.InvalidateWeakPtrs();
impl_ = new Impl(weak_factory_.GetWeakPtr(), gpu_factories_);
@@ -546,13 +607,13 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings,
impl_,
gfx::Size(codec_settings->width, codec_settings->height),
codec_settings->startBitrate,
- video_codec_profile_,
+ profile,
&initialization_waiter,
&initialization_retval));
// webrtc::VideoEncoder expects this call to be synchronous.
initialization_waiter.Wait();
- RecordInitEncodeUMA(initialization_retval);
+ RecordInitEncodeUMA(initialization_retval, profile);
return initialization_retval;
}
@@ -561,9 +622,7 @@ int32_t RTCVideoEncoder::Encode(
const webrtc::CodecSpecificInfo* codec_specific_info,
const std::vector<webrtc::VideoFrameType>* frame_types) {
DVLOG(3) << "Encode()";
- // TODO(sheu): figure out why this check fails.
- // DCHECK(thread_checker_.CalledOnValidThread());
- if (!impl_) {
+ if (!impl_.get()) {
DVLOG(3) << "Encode(): returning impl_status_=" << impl_status_;
return impl_status_;
}
@@ -591,7 +650,7 @@ int32_t RTCVideoEncoder::RegisterEncodeCompleteCallback(
webrtc::EncodedImageCallback* callback) {
DVLOG(3) << "RegisterEncodeCompleteCallback()";
DCHECK(thread_checker_.CalledOnValidThread());
- if (!impl_) {
+ if (!impl_.get()) {
DVLOG(3) << "RegisterEncodeCompleteCallback(): returning " << impl_status_;
return impl_status_;
}
@@ -604,7 +663,7 @@ int32_t RTCVideoEncoder::Release() {
DVLOG(3) << "Release()";
DCHECK(thread_checker_.CalledOnValidThread());
- if (impl_) {
+ if (impl_.get()) {
gpu_factories_->GetTaskRunner()->PostTask(
FROM_HERE, base::Bind(&RTCVideoEncoder::Impl::Destroy, impl_));
impl_ = NULL;
@@ -617,7 +676,6 @@ int32_t RTCVideoEncoder::Release() {
int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
DVLOG(3) << "SetChannelParameters(): packet_loss=" << packet_loss
<< ", rtt=" << rtt;
- DCHECK(thread_checker_.CalledOnValidThread());
// Ignored.
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -625,8 +683,7 @@ int32_t RTCVideoEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
DVLOG(3) << "SetRates(): new_bit_rate=" << new_bit_rate
<< ", frame_rate=" << frame_rate;
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!impl_) {
+ if (!impl_.get()) {
DVLOG(3) << "SetRates(): returning " << impl_status_;
return impl_status_;
}
@@ -651,6 +708,30 @@ void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
if (!encoded_image_callback_)
return;
+ webrtc::RTPFragmentationHeader header;
+ memset(&header, 0, sizeof(header));
+ switch (video_codec_type_) {
+ case webrtc::kVideoCodecVP8:
+ // Generate a header describing a single fragment.
+ header.VerifyAndAllocateFragmentationHeader(1);
+ header.fragmentationOffset[0] = 0;
+ header.fragmentationLength[0] = image->_length;
+ header.fragmentationPlType[0] = 0;
+ header.fragmentationTimeDiff[0] = 0;
+ break;
+ case webrtc::kVideoCodecH264:
+ if (!GetRTPFragmentationHeaderH264(
+ &header, image->_buffer, image->_length)) {
+ DLOG(ERROR) << "Failed to get RTP fragmentation header for H264";
+ NotifyError(WEBRTC_VIDEO_CODEC_ERROR);
+ return;
+ }
+ break;
+ default:
+ NOTREACHED() << "Invalid video codec type";
+ return;
+ }
+
webrtc::CodecSpecificInfo info;
memset(&info, 0, sizeof(info));
info.codecType = video_codec_type_;
@@ -660,15 +741,6 @@ void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
info.codecSpecific.VP8.keyIdx = -1;
}
- // Generate a header describing a single fragment.
- webrtc::RTPFragmentationHeader header;
- memset(&header, 0, sizeof(header));
- header.VerifyAndAllocateFragmentationHeader(1);
- header.fragmentationOffset[0] = 0;
- header.fragmentationLength[0] = image->_length;
- header.fragmentationPlType[0] = 0;
- header.fragmentationTimeDiff[0] = 0;
-
int32_t retval = encoded_image_callback_->Encoded(*image, &info, &header);
if (retval < 0) {
DVLOG(2) << "ReturnEncodedImage(): encoded_image_callback_ returned "
@@ -694,12 +766,13 @@ void RTCVideoEncoder::NotifyError(int32_t error) {
impl_ = NULL;
}
-void RTCVideoEncoder::RecordInitEncodeUMA(int32_t init_retval) {
+void RTCVideoEncoder::RecordInitEncodeUMA(
+ int32_t init_retval, media::VideoCodecProfile profile) {
UMA_HISTOGRAM_BOOLEAN("Media.RTCVideoEncoderInitEncodeSuccess",
init_retval == WEBRTC_VIDEO_CODEC_OK);
if (init_retval == WEBRTC_VIDEO_CODEC_OK) {
UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoEncoderProfile",
- video_codec_profile_,
+ profile,
media::VIDEO_CODEC_PROFILE_MAX + 1);
}
}
diff --git a/chromium/content/renderer/media/rtc_video_encoder.h b/chromium/content/renderer/media/rtc_video_encoder.h
index eb1677ea5f6..68ac9d04b60 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.h
+++ b/chromium/content/renderer/media/rtc_video_encoder.h
@@ -35,33 +35,35 @@ namespace content {
// webrtc::VideoEncoder class for WebRTC. Internally, VEA methods are
// trampolined to a private RTCVideoEncoder::Impl instance. The Impl class runs
// on the worker thread queried from the |gpu_factories_|, which is presently
-// the media thread. RTCVideoEncoder itself is run and destroyed on the thread
-// it is constructed on, which is presently the libjingle worker thread.
-// Callbacks from the Impl due to its VEA::Client notifications are also posted
-// back to RTCVideoEncoder on this thread.
+// the media thread. RTCVideoEncoder is sychronized by webrtc::VideoSender.
+// webrtc::VideoEncoder methods do not run concurrently. RTCVideoEncoder is run
+// and destroyed on the thread it is constructed on, which is presently the
+// libjingle worker thread. Encode is run on ViECaptureThread. SetRates and
+// SetChannelParameters are run on ProcessThread or the libjingle worker thread.
+// Callbacks from the Impl due to its VEA::Client notifications are posted back
+// to RTCVideoEncoder on the libjingle worker thread.
class CONTENT_EXPORT RTCVideoEncoder
: NON_EXPORTED_BASE(public webrtc::VideoEncoder) {
public:
RTCVideoEncoder(
webrtc::VideoCodecType type,
- media::VideoCodecProfile profile,
const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories);
- virtual ~RTCVideoEncoder();
+ ~RTCVideoEncoder() override;
// webrtc::VideoEncoder implementation. Tasks are posted to |impl_| using the
// appropriate VEA methods.
- virtual int32_t InitEncode(const webrtc::VideoCodec* codec_settings,
- int32_t number_of_cores,
- uint32_t max_payload_size) OVERRIDE;
- virtual int32_t Encode(
+ int32_t InitEncode(const webrtc::VideoCodec* codec_settings,
+ int32_t number_of_cores,
+ uint32_t max_payload_size) override;
+ int32_t Encode(
const webrtc::I420VideoFrame& input_image,
const webrtc::CodecSpecificInfo* codec_specific_info,
- const std::vector<webrtc::VideoFrameType>* frame_types) OVERRIDE;
- virtual int32_t RegisterEncodeCompleteCallback(
- webrtc::EncodedImageCallback* callback) OVERRIDE;
- virtual int32_t Release() OVERRIDE;
- virtual int32_t SetChannelParameters(uint32_t packet_loss, int rtt) OVERRIDE;
- virtual int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) OVERRIDE;
+ const std::vector<webrtc::VideoFrameType>* frame_types) override;
+ int32_t RegisterEncodeCompleteCallback(
+ webrtc::EncodedImageCallback* callback) override;
+ int32_t Release() override;
+ int32_t SetChannelParameters(uint32_t packet_loss, int rtt) override;
+ int32_t SetRates(uint32_t new_bit_rate, uint32_t frame_rate) override;
private:
class Impl;
@@ -74,16 +76,14 @@ class CONTENT_EXPORT RTCVideoEncoder
void NotifyError(int32_t error);
- void RecordInitEncodeUMA(int32_t init_retval);
+ void RecordInitEncodeUMA(int32_t init_retval,
+ media::VideoCodecProfile profile);
base::ThreadChecker thread_checker_;
// The video codec type, as reported to WebRTC.
const webrtc::VideoCodecType video_codec_type_;
- // The video codec profile, to configure the encoder to encode to.
- const media::VideoCodecProfile video_codec_profile_;
-
// Factory for creating VEAs, shared memory buffers, etc.
scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
diff --git a/chromium/content/renderer/media/rtc_video_encoder_factory.cc b/chromium/content/renderer/media/rtc_video_encoder_factory.cc
index 777d69f83c9..2182f222796 100644
--- a/chromium/content/renderer/media/rtc_video_encoder_factory.cc
+++ b/chromium/content/renderer/media/rtc_video_encoder_factory.cc
@@ -4,7 +4,9 @@
#include "content/renderer/media/rtc_video_encoder_factory.h"
+#include "base/command_line.h"
#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
+#include "content/public/common/content_switches.h"
#include "content/renderer/media/rtc_video_encoder.h"
#include "media/filters/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator.h"
@@ -14,45 +16,28 @@ namespace content {
namespace {
// Translate from media::VideoEncodeAccelerator::SupportedProfile to
-// cricket::WebRtcVideoEncoderFactory::VideoCodec
-cricket::WebRtcVideoEncoderFactory::VideoCodec VEAToWebRTCCodec(
+// one or more instances of cricket::WebRtcVideoEncoderFactory::VideoCodec
+void VEAToWebRTCCodecs(
+ std::vector<cricket::WebRtcVideoEncoderFactory::VideoCodec>* codecs,
const media::VideoEncodeAccelerator::SupportedProfile& profile) {
- webrtc::VideoCodecType type = webrtc::kVideoCodecUnknown;
- std::string name;
- int width = 0, height = 0, fps = 0;
+ int width = profile.max_resolution.width();
+ int height = profile.max_resolution.height();
+ int fps = profile.max_framerate_numerator;
+ DCHECK_EQ(profile.max_framerate_denominator, 1U);
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (profile.profile >= media::VP8PROFILE_MIN &&
profile.profile <= media::VP8PROFILE_MAX) {
- type = webrtc::kVideoCodecVP8;
- name = "VP8";
+ if (cmd_line->HasSwitch(switches::kEnableWebRtcHWVp8Encoding)) {
+ codecs->push_back(cricket::WebRtcVideoEncoderFactory::VideoCodec(
+ webrtc::kVideoCodecVP8, "VP8", width, height, fps));
+ }
} else if (profile.profile >= media::H264PROFILE_MIN &&
profile.profile <= media::H264PROFILE_MAX) {
- type = webrtc::kVideoCodecGeneric;
- name = "CAST1";
- }
-
- if (type != webrtc::kVideoCodecUnknown) {
- width = profile.max_resolution.width();
- height = profile.max_resolution.height();
- fps = profile.max_framerate.numerator;
- DCHECK_EQ(profile.max_framerate.denominator, 1U);
- }
-
- return cricket::WebRtcVideoEncoderFactory::VideoCodec(
- type, name, width, height, fps);
-}
-
-// Translate from cricket::WebRtcVideoEncoderFactory::VideoCodec to
-// media::VideoCodecProfile. Pick a default profile for each codec type.
-media::VideoCodecProfile WebRTCCodecToVideoCodecProfile(
- webrtc::VideoCodecType type) {
- switch (type) {
- case webrtc::kVideoCodecVP8:
- return media::VP8PROFILE_MAIN;
- case webrtc::kVideoCodecGeneric:
- return media::H264PROFILE_MAIN;
- default:
- return media::VIDEO_CODEC_PROFILE_UNKNOWN;
+ if (cmd_line->HasSwitch(switches::kEnableWebRtcHWH264Encoding)) {
+ codecs->push_back(cricket::WebRtcVideoEncoderFactory::VideoCodec(
+ webrtc::kVideoCodecH264, "H264", width, height, fps));
+ }
}
}
@@ -61,14 +46,10 @@ media::VideoCodecProfile WebRTCCodecToVideoCodecProfile(
RTCVideoEncoderFactory::RTCVideoEncoderFactory(
const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories)
: gpu_factories_(gpu_factories) {
- // Query media::VideoEncodeAccelerator (statically) for our supported codecs.
std::vector<media::VideoEncodeAccelerator::SupportedProfile> profiles =
- GpuVideoEncodeAcceleratorHost::GetSupportedProfiles();
- for (size_t i = 0; i < profiles.size(); ++i) {
- VideoCodec codec = VEAToWebRTCCodec(profiles[i]);
- if (codec.type != webrtc::kVideoCodecUnknown)
- codecs_.push_back(codec);
- }
+ gpu_factories_->GetVideoEncodeAcceleratorSupportedProfiles();
+ for (size_t i = 0; i < profiles.size(); ++i)
+ VEAToWebRTCCodecs(&codecs_, profiles[i]);
}
RTCVideoEncoderFactory::~RTCVideoEncoderFactory() {}
@@ -84,16 +65,9 @@ webrtc::VideoEncoder* RTCVideoEncoderFactory::CreateVideoEncoder(
}
if (!found)
return NULL;
- return new RTCVideoEncoder(
- type, WebRTCCodecToVideoCodecProfile(type), gpu_factories_);
+ return new RTCVideoEncoder(type, gpu_factories_);
}
-void RTCVideoEncoderFactory::AddObserver(Observer* observer) {
- // No-op: our codec list is populated on installation.
-}
-
-void RTCVideoEncoderFactory::RemoveObserver(Observer* observer) {}
-
const std::vector<cricket::WebRtcVideoEncoderFactory::VideoCodec>&
RTCVideoEncoderFactory::codecs() const {
return codecs_;
diff --git a/chromium/content/renderer/media/rtc_video_encoder_factory.h b/chromium/content/renderer/media/rtc_video_encoder_factory.h
index b9971bfeb0a..986e983461c 100644
--- a/chromium/content/renderer/media/rtc_video_encoder_factory.h
+++ b/chromium/content/renderer/media/rtc_video_encoder_factory.h
@@ -27,15 +27,13 @@ class CONTENT_EXPORT RTCVideoEncoderFactory
public:
explicit RTCVideoEncoderFactory(
const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories);
- virtual ~RTCVideoEncoderFactory();
+ ~RTCVideoEncoderFactory() override;
// cricket::WebRtcVideoEncoderFactory implementation.
- virtual webrtc::VideoEncoder* CreateVideoEncoder(
- webrtc::VideoCodecType type) OVERRIDE;
- virtual void AddObserver(Observer* observer) OVERRIDE;
- virtual void RemoveObserver(Observer* observer) OVERRIDE;
- virtual const std::vector<VideoCodec>& codecs() const OVERRIDE;
- virtual void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) OVERRIDE;
+ webrtc::VideoEncoder* CreateVideoEncoder(
+ webrtc::VideoCodecType type) override;
+ const std::vector<VideoCodec>& codecs() const override;
+ void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override;
private:
const scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
diff --git a/chromium/content/renderer/media/rtc_video_renderer.cc b/chromium/content/renderer/media/rtc_video_renderer.cc
index c45a24a2f68..323f0a3d795 100644
--- a/chromium/content/renderer/media/rtc_video_renderer.cc
+++ b/chromium/content/renderer/media/rtc_video_renderer.cc
@@ -81,12 +81,6 @@ void RTCVideoRenderer::OnReadyStateChanged(
RenderSignalingFrame();
}
-void RTCVideoRenderer::OnEnabledChanged(bool enabled) {
- DCHECK(message_loop_proxy_->BelongsToCurrentThread());
- if (!enabled)
- RenderSignalingFrame();
-}
-
void RTCVideoRenderer::OnVideoFrame(
const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format,
@@ -108,7 +102,7 @@ void RTCVideoRenderer::OnVideoFrame(
void RTCVideoRenderer::RenderSignalingFrame() {
// This is necessary to make sure audio can play if the video tag src is
- // a MediaStream video track that has been rejected, ended or disabled.
+ // a MediaStream video track that has been rejected or ended.
// It also ensure that the renderer don't hold a reference to a real video
// frame if no more frames are provided. This is since there might be a
// finite number of available buffers. E.g, video that
diff --git a/chromium/content/renderer/media/rtc_video_renderer.h b/chromium/content/renderer/media/rtc_video_renderer.h
index e205b6b5f8d..699fe84d2ef 100644
--- a/chromium/content/renderer/media/rtc_video_renderer.h
+++ b/chromium/content/renderer/media/rtc_video_renderer.h
@@ -39,13 +39,13 @@ class CONTENT_EXPORT RTCVideoRenderer
const RepaintCB& repaint_cb);
// VideoFrameProvider implementation. Called on the main thread.
- virtual void Start() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void Play() OVERRIDE;
- virtual void Pause() OVERRIDE;
+ void Start() override;
+ void Stop() override;
+ void Play() override;
+ void Pause() override;
protected:
- virtual ~RTCVideoRenderer();
+ ~RTCVideoRenderer() override;
private:
enum State {
@@ -59,9 +59,8 @@ class CONTENT_EXPORT RTCVideoRenderer
const base::TimeTicks& estimated_capture_time);
// VideoTrackSink implementation. Called on the main thread.
- virtual void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
- virtual void OnEnabledChanged(bool enabled) OVERRIDE;
+ void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) override;
void RenderSignalingFrame();
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink.cc b/chromium/content/renderer/media/speech_recognition_audio_sink.cc
new file mode 100644
index 00000000000..c51c695c879
--- /dev/null
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink.cc
@@ -0,0 +1,190 @@
+// Copyright 2014 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 "content/renderer/media/speech_recognition_audio_sink.h"
+
+#include "base/logging.h"
+#include "base/memory/shared_memory.h"
+#include "base/time/time.h"
+#include "content/renderer/media/media_stream_audio_source.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_fifo.h"
+
+namespace content {
+
+SpeechRecognitionAudioSink::SpeechRecognitionAudioSink(
+ const blink::WebMediaStreamTrack& track,
+ const media::AudioParameters& params,
+ const base::SharedMemoryHandle memory,
+ scoped_ptr<base::SyncSocket> socket,
+ const OnStoppedCB& on_stopped_cb)
+ : track_(track),
+ shared_memory_(memory, false),
+ socket_(socket.Pass()),
+ output_params_(params),
+ track_stopped_(false),
+ buffer_index_(0),
+ on_stopped_cb_(on_stopped_cb) {
+ DCHECK(socket_.get());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DCHECK(params.IsValid());
+ DCHECK(IsSupportedTrack(track));
+ const size_t kSharedMemorySize = sizeof(media::AudioInputBufferParameters) +
+ media::AudioBus::CalculateMemorySize(params);
+ CHECK(shared_memory_.Map(kSharedMemorySize));
+
+ media::AudioInputBuffer* buffer =
+ static_cast<media::AudioInputBuffer*>(shared_memory_.memory());
+
+ // The peer must manage their own counter and reset it to 0.
+ DCHECK_EQ(0U, buffer->params.size);
+ output_bus_ = media::AudioBus::WrapMemory(params, buffer->audio);
+
+ // Connect this audio sink to the track
+ MediaStreamAudioSink::AddToAudioTrack(this, track_);
+}
+
+SpeechRecognitionAudioSink::~SpeechRecognitionAudioSink() {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ if (audio_converter_.get())
+ audio_converter_->RemoveInput(this);
+
+ // Notify the track before this sink goes away.
+ if (!track_stopped_)
+ MediaStreamAudioSink::RemoveFromAudioTrack(this, track_);
+}
+
+// static
+bool SpeechRecognitionAudioSink::IsSupportedTrack(
+ const blink::WebMediaStreamTrack& track) {
+ if (track.source().type() != blink::WebMediaStreamSource::TypeAudio)
+ return false;
+
+ MediaStreamAudioSource* native_source =
+ static_cast<MediaStreamAudioSource*>(track.source().extraData());
+ if (!native_source)
+ return false;
+
+ const StreamDeviceInfo& device_info = native_source->device_info();
+ // Purposely only support tracks from an audio device. Dissallow WebAudio.
+ return (device_info.device.type == content::MEDIA_DEVICE_AUDIO_CAPTURE);
+}
+
+void SpeechRecognitionAudioSink::OnSetFormat(
+ const media::AudioParameters& input_params) {
+ DCHECK(input_params.IsValid());
+ DCHECK_LE(
+ input_params.frames_per_buffer() * 1000 / input_params.sample_rate(),
+ output_params_.frames_per_buffer() * 1000 / output_params_.sample_rate());
+
+ // Detach the thread here because it will be a new capture thread
+ // calling OnSetFormat() and OnData() if the source is restarted.
+ capture_thread_checker_.DetachFromThread();
+
+ input_params_ = input_params;
+ fifo_buffer_size_ =
+ std::ceil(output_params_.frames_per_buffer() *
+ static_cast<double>(input_params_.sample_rate()) /
+ output_params_.sample_rate());
+ DCHECK_GE(fifo_buffer_size_, input_params_.frames_per_buffer());
+
+ // Allows for some delays on the peer.
+ static const int kNumberOfBuffersInFifo = 2;
+ int frames_in_fifo = kNumberOfBuffersInFifo * fifo_buffer_size_;
+ fifo_.reset(new media::AudioFifo(input_params.channels(), frames_in_fifo));
+ input_bus_ = media::AudioBus::Create(input_params.channels(),
+ input_params.frames_per_buffer());
+
+ // Create the audio converter with |disable_fifo| as false so that the
+ // converter will request input_params.frames_per_buffer() each time.
+ // This will not increase the complexity as there is only one client to
+ // the converter.
+ audio_converter_.reset(
+ new media::AudioConverter(input_params, output_params_, false));
+ audio_converter_->AddInput(this);
+}
+
+void SpeechRecognitionAudioSink::OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DCHECK(!track_stopped_);
+
+ if (state == blink::WebMediaStreamSource::ReadyStateEnded) {
+ track_stopped_ = true;
+
+ if (!on_stopped_cb_.is_null())
+ on_stopped_cb_.Run();
+ }
+}
+
+void SpeechRecognitionAudioSink::OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(input_bus_->frames(), number_of_frames);
+ DCHECK_EQ(input_bus_->channels(), number_of_channels);
+ if (fifo_->frames() + number_of_frames > fifo_->max_frames()) {
+ // This would indicate a serious issue with the browser process or the
+ // SyncSocket and/or SharedMemory. We drop any previous buffers and try to
+ // recover by resuming where the peer left of.
+ DLOG(ERROR) << "Audio FIFO overflow";
+ fifo_->Clear();
+ buffer_index_ = GetAudioInputBuffer()->params.size;
+ }
+ // TODO(xians): A better way to handle the interleaved and deinterleaved
+ // format switching, see issue/317710.
+ input_bus_->FromInterleaved(audio_data, number_of_frames,
+ sizeof(audio_data[0]));
+
+ fifo_->Push(input_bus_.get());
+ // Wait for FIFO to have at least |fifo_buffer_size_| frames ready.
+ if (fifo_->frames() < fifo_buffer_size_)
+ return;
+
+ // Make sure the previous output buffer was consumed by the peer before we
+ // send the next buffer.
+ // The peer must write to it (incrementing by 1) once the the buffer was
+ // consumed. This is intentional not to block this audio capturing thread.
+ if (buffer_index_ != GetAudioInputBuffer()->params.size) {
+ DVLOG(1) << "Buffer synchronization lag";
+ return;
+ }
+
+ audio_converter_->Convert(output_bus_.get());
+
+ // Notify peer to consume buffer |buffer_index_| on |output_bus_|.
+ const size_t bytes_sent =
+ socket_->Send(&buffer_index_, sizeof(buffer_index_));
+ if (bytes_sent != sizeof(buffer_index_)) {
+ // The send ocasionally fails if the user changes their input audio device.
+ DVLOG(1) << "Failed sending buffer index to peer";
+ // We have discarded this buffer, but could still recover on the next one.
+ return;
+ }
+
+ // Count the sent buffer. We expect the peer to do the same on their end.
+ ++buffer_index_;
+}
+
+double SpeechRecognitionAudioSink::ProvideInput(media::AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ if (fifo_->frames() >= audio_bus->frames())
+ fifo_->Consume(audio_bus, 0, audio_bus->frames());
+ else
+ audio_bus->Zero();
+
+ // Return volume greater than zero to indicate we have more data.
+ return 1.0;
+}
+
+media::AudioInputBuffer*
+SpeechRecognitionAudioSink::GetAudioInputBuffer() const {
+ DCHECK(capture_thread_checker_.CalledOnValidThread());
+ DCHECK(shared_memory_.memory());
+ return static_cast<media::AudioInputBuffer*>(shared_memory_.memory());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink.h b/chromium/content/renderer/media/speech_recognition_audio_sink.h
new file mode 100644
index 00000000000..bef5e46d447
--- /dev/null
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink.h
@@ -0,0 +1,121 @@
+// Copyright 2014 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 CONTENT_RENDERER_MEDIA_SPEECH_RECOGNITION_AUDIO_SINK_H_
+#define CONTENT_RENDERER_MEDIA_SPEECH_RECOGNITION_AUDIO_SINK_H_
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_converter.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+
+namespace media {
+class AudioBus;
+class AudioFifo;
+}
+
+namespace content {
+
+// SpeechRecognitionAudioSink works as an audio sink to the
+// WebRtcLocalAudioTrack. It stores the capture data into a FIFO.
+// When the FIFO has enough data for resampling, it converts it,
+// passes the buffer to the WebSpeechRecognizer via SharedMemory
+// and notifies it via SyncSocket followed by incrementing the |buffer_index_|.
+// WebSpeechRecognizer increments the shared buffer index to synchronize.
+class CONTENT_EXPORT SpeechRecognitionAudioSink
+ : NON_EXPORTED_BASE(public media::AudioConverter::InputCallback),
+ NON_EXPORTED_BASE(public MediaStreamAudioSink) {
+ public:
+ typedef base::Callback<void()> OnStoppedCB;
+
+ // Socket ownership is transferred to the class via constructor.
+ SpeechRecognitionAudioSink(const blink::WebMediaStreamTrack& track,
+ const media::AudioParameters& params,
+ const base::SharedMemoryHandle memory,
+ scoped_ptr<base::SyncSocket> socket,
+ const OnStoppedCB& on_stopped_cb);
+
+ ~SpeechRecognitionAudioSink() override;
+
+ // Returns whether the provided track is supported.
+ static bool IsSupportedTrack(const blink::WebMediaStreamTrack& track);
+
+ private:
+ // content::MediaStreamAudioSink implementation.
+ void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) override;
+
+ void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) override;
+ void OnSetFormat(const media::AudioParameters& params) override;
+
+ // media::AudioConverter::Inputcallback implementation.
+ double ProvideInput(media::AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) override;
+
+ // Returns the pointer to the audio input buffer mapped in the shared memory.
+ media::AudioInputBuffer* GetAudioInputBuffer() const;
+
+ // Number of frames per buffer in FIFO. When the buffer is full we convert and
+ // consume it on the |output_bus_|. Size of the buffer depends on the
+ // resampler. Example: for 44.1 to 16.0 conversion, it should be 4100 frames.
+ int fifo_buffer_size_;
+
+ // Used to DCHECK that some methods are called on the main render thread.
+ base::ThreadChecker main_render_thread_checker_;
+
+ // Used to DCHECK that some methods are called on the capture audio thread.
+ base::ThreadChecker capture_thread_checker_;
+
+ // The audio track that this audio sink is connected to.
+ const blink::WebMediaStreamTrack track_;
+
+ // Shared memory used by audio buses on both browser and renderer processes.
+ base::SharedMemory shared_memory_;
+
+ // Socket for synchronization of audio bus reads/writes.
+ // Created on the renderer client and passed here. Accessed on capture thread.
+ scoped_ptr<base::SyncSocket> socket_;
+
+ // Used as a resampler to deliver appropriate format to speech recognition.
+ scoped_ptr<media::AudioConverter> audio_converter_;
+
+ // FIFO is used for queuing audio frames before we resample.
+ scoped_ptr<media::AudioFifo> fifo_;
+
+ // Audio delivered from source.
+ scoped_ptr<media::AudioBus> input_bus_;
+
+ // Audio bus shared with the browser process via |shared_memory_|.
+ scoped_ptr<media::AudioBus> output_bus_;
+
+ // Params of the source audio. Can change when |OnSetFormat()| occurs.
+ media::AudioParameters input_params_;
+
+ // Params used by speech recognition.
+ const media::AudioParameters output_params_;
+
+ // Whether the track has been stopped.
+ bool track_stopped_;
+
+ // Local counter of audio buffers for synchronization.
+ uint32 buffer_index_;
+
+ // Callback for the renderer client. Called when the audio track was stopped.
+ const OnStoppedCB on_stopped_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionAudioSink);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_SPEECH_RECOGNITION_AUDIO_SINK_H_
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc b/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc
new file mode 100644
index 00000000000..4366309f1ed
--- /dev/null
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc
@@ -0,0 +1,514 @@
+// Copyright 2014 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 "content/renderer/media/speech_recognition_audio_sink.h"
+
+#include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+
+namespace {
+
+// Supported speech recognition audio parameters.
+const int kSpeechRecognitionSampleRate = 16000;
+const int kSpeechRecognitionFramesPerBuffer = 1600;
+
+// Input audio format.
+const media::AudioParameters::Format kInputFormat =
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
+const media::ChannelLayout kInputChannelLayout = media::CHANNEL_LAYOUT_MONO;
+const int kInputChannels = 1;
+const int kInputBitsPerSample = 16;
+
+// Output audio format.
+const media::AudioParameters::Format kOutputFormat =
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
+const media::ChannelLayout kOutputChannelLayout = media::CHANNEL_LAYOUT_STEREO;
+const int kOutputChannels = 2;
+const int kOutputBitsPerSample = 16;
+
+// Mocked out sockets used for Send/Receive.
+// Data is written and read from a shared buffer used as a FIFO and there is
+// no blocking. |OnSendCB| is used to trigger a |Receive| on the other socket.
+class MockSyncSocket : public base::SyncSocket {
+ public:
+ // This allows for 2 requests in queue between the |MockSyncSocket|s.
+ static const int kSharedBufferSize = 8;
+
+ // Buffer to be shared between two |MockSyncSocket|s. Allocated on heap.
+ struct SharedBuffer {
+ SharedBuffer() : data(), start(0), length(0) {}
+
+ uint8 data[kSharedBufferSize];
+ size_t start;
+ size_t length;
+ };
+
+ // Callback used for pairing an A.Send() with B.Receieve() without blocking.
+ typedef base::Callback<void()> OnSendCB;
+
+ explicit MockSyncSocket(SharedBuffer* shared_buffer)
+ : buffer_(shared_buffer),
+ in_failure_mode_(false) {}
+
+ MockSyncSocket(SharedBuffer* shared_buffer, const OnSendCB& on_send_cb)
+ : buffer_(shared_buffer),
+ on_send_cb_(on_send_cb),
+ in_failure_mode_(false) {}
+
+ size_t Send(const void* buffer, size_t length) override;
+ size_t Receive(void* buffer, size_t length) override;
+
+ // When |in_failure_mode_| == true, the socket fails to send.
+ void SetFailureMode(bool in_failure_mode) {
+ in_failure_mode_ = in_failure_mode;
+ }
+
+ private:
+ SharedBuffer* buffer_;
+ const OnSendCB on_send_cb_;
+ bool in_failure_mode_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSyncSocket);
+};
+
+// base::SyncSocket implementation
+size_t MockSyncSocket::Send(const void* buffer, size_t length) {
+ if (in_failure_mode_)
+ return 0;
+
+ const uint8* b = static_cast<const uint8*>(buffer);
+ for (size_t i = 0; i < length; ++i, ++buffer_->length)
+ buffer_->data[buffer_->start + buffer_->length] = b[i];
+
+ on_send_cb_.Run();
+ return length;
+}
+
+size_t MockSyncSocket::Receive(void* buffer, size_t length) {
+ uint8* b = static_cast<uint8*>(buffer);
+ for (size_t i = buffer_->start; i < buffer_->length; ++i, ++buffer_->start)
+ b[i] = buffer_->data[buffer_->start];
+
+ // Since buffer is used sequentially, we can reset the buffer indices here.
+ buffer_->start = buffer_->length = 0;
+ return length;
+}
+
+// This fake class is the consumer used to verify behaviour of the producer.
+// The |Initialize()| method shows what the consumer should be responsible for
+// in the production code (minus the mocks).
+class FakeSpeechRecognizer {
+ public:
+ FakeSpeechRecognizer() : is_responsive_(true) {}
+
+ void Initialize(
+ const blink::WebMediaStreamTrack& track,
+ const media::AudioParameters& sink_params,
+ base::SharedMemoryHandle* foreign_memory_handle) {
+ // Shared memory is allocated, mapped and shared.
+ const uint32 kSharedMemorySize =
+ sizeof(media::AudioInputBufferParameters) +
+ media::AudioBus::CalculateMemorySize(sink_params);
+ shared_memory_.reset(new base::SharedMemory());
+ ASSERT_TRUE(shared_memory_->CreateAndMapAnonymous(kSharedMemorySize));
+ memset(shared_memory_->memory(), 0, kSharedMemorySize);
+ ASSERT_TRUE(shared_memory_->ShareToProcess(base::GetCurrentProcessHandle(),
+ foreign_memory_handle));
+
+ // Wrap the shared memory for the audio bus.
+ media::AudioInputBuffer* buffer =
+ static_cast<media::AudioInputBuffer*>(shared_memory_->memory());
+
+ audio_track_bus_ = media::AudioBus::WrapMemory(sink_params, buffer->audio);
+ audio_track_bus_->Zero();
+
+ // Reference to the counter used to synchronize.
+ buffer->params.size = 0U;
+
+ // Create a shared buffer for the |MockSyncSocket|s.
+ shared_buffer_.reset(new MockSyncSocket::SharedBuffer());
+
+ // Local socket will receive signals from the producer.
+ receiving_socket_.reset(new MockSyncSocket(shared_buffer_.get()));
+
+ // We automatically trigger a Receive when data is sent over the socket.
+ sending_socket_ = new MockSyncSocket(
+ shared_buffer_.get(),
+ base::Bind(&FakeSpeechRecognizer::EmulateReceiveThreadLoopIteration,
+ base::Unretained(this)));
+
+ // This is usually done to pair the sockets. Here it's not effective.
+ base::SyncSocket::CreatePair(receiving_socket_.get(), sending_socket_);
+ }
+
+ // Emulates a single iteraton of a thread receiving on the socket.
+ // This would normally be done on a receiving thread's task on the browser.
+ void EmulateReceiveThreadLoopIteration() {
+ if (!is_responsive_)
+ return;
+
+ const int kSize = sizeof(media::AudioInputBufferParameters().size);
+ receiving_socket_->Receive(&(GetAudioInputBuffer()->params.size), kSize);
+
+ // Notify the producer that the audio buffer has been consumed.
+ GetAudioInputBuffer()->params.size++;
+ }
+
+ // Used to simulate an unresponsive behaviour of the consumer.
+ void SimulateResponsiveness(bool is_responsive) {
+ is_responsive_ = is_responsive;
+ }
+
+ media::AudioInputBuffer * GetAudioInputBuffer() const {
+ return static_cast<media::AudioInputBuffer*>(shared_memory_->memory());
+ }
+
+ MockSyncSocket* sending_socket() { return sending_socket_; }
+ media::AudioBus* audio_bus() const { return audio_track_bus_.get(); }
+
+
+ private:
+ bool is_responsive_;
+
+ // Shared memory for the audio and synchronization.
+ scoped_ptr<base::SharedMemory> shared_memory_;
+
+ // Fake sockets and their shared buffer.
+ scoped_ptr<MockSyncSocket::SharedBuffer> shared_buffer_;
+ scoped_ptr<MockSyncSocket> receiving_socket_;
+ MockSyncSocket* sending_socket_;
+
+ // Audio bus wrapping the shared memory from the renderer.
+ scoped_ptr<media::AudioBus> audio_track_bus_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeSpeechRecognizer);
+};
+
+} // namespace
+
+namespace content {
+
+class SpeechRecognitionAudioSinkTest : public testing::Test {
+ public:
+ SpeechRecognitionAudioSinkTest() {}
+
+ ~SpeechRecognitionAudioSinkTest() {}
+
+ // Initializes the producer and consumer with specified audio parameters.
+ // Returns the minimal number of input audio buffers which need to be captured
+ // before they get sent to the consumer.
+ uint32 Initialize(int input_sample_rate,
+ int input_frames_per_buffer,
+ int output_sample_rate,
+ int output_frames_per_buffer) {
+ // Audio Environment setup.
+ source_params_.Reset(kInputFormat,
+ kInputChannelLayout,
+ kInputChannels,
+ input_sample_rate,
+ kInputBitsPerSample,
+ input_frames_per_buffer);
+ sink_params_.Reset(kOutputFormat,
+ kOutputChannelLayout,
+ kOutputChannels,
+ output_sample_rate,
+ kOutputBitsPerSample,
+ output_frames_per_buffer);
+ source_data_.reset(new int16[input_frames_per_buffer * kInputChannels]{});
+
+ // Prepare the track and audio source.
+ blink::WebMediaStreamTrack blink_track;
+ PrepareBlinkTrackOfType(MEDIA_DEVICE_AUDIO_CAPTURE, &blink_track);
+
+ // Get the native track from the blink track and initialize.
+ native_track_ =
+ static_cast<WebRtcLocalAudioTrack*>(blink_track.extraData());
+ native_track_->OnSetFormat(source_params_);
+
+ // Create and initialize the consumer.
+ recognizer_.reset(new FakeSpeechRecognizer());
+ base::SharedMemoryHandle foreign_memory_handle;
+ recognizer_->Initialize(blink_track, sink_params_, &foreign_memory_handle);
+
+ // Create the producer.
+ scoped_ptr<base::SyncSocket> sending_socket(recognizer_->sending_socket());
+ speech_audio_sink_.reset(new SpeechRecognitionAudioSink(
+ blink_track, sink_params_, foreign_memory_handle,
+ sending_socket.Pass(),
+ base::Bind(&SpeechRecognitionAudioSinkTest::StoppedCallback,
+ base::Unretained(this))));
+
+ // Return number of buffers needed to trigger resampling and consumption.
+ return static_cast<uint32>(std::ceil(
+ static_cast<double>(output_frames_per_buffer * input_sample_rate) /
+ (input_frames_per_buffer * output_sample_rate)));
+ }
+
+ // Mock callback expected to be called when the track is stopped.
+ MOCK_METHOD0(StoppedCallback, void());
+
+ protected:
+ // Prepares a blink track of a given MediaStreamType and attaches the native
+ // track which can be used to capture audio data and pass it to the producer.
+ static void PrepareBlinkTrackOfType(
+ const MediaStreamType device_type,
+ blink::WebMediaStreamTrack* blink_track) {
+ StreamDeviceInfo device_info(device_type, "Mock device",
+ "mock_device_id");
+ MockMediaConstraintFactory constraint_factory;
+ const blink::WebMediaConstraints constraints =
+ constraint_factory.CreateWebMediaConstraints();
+ scoped_refptr<WebRtcAudioCapturer> capturer(
+ WebRtcAudioCapturer::CreateCapturer(-1, device_info, constraints, NULL,
+ NULL));
+ scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
+ WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
+ scoped_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
+ blink::WebMediaStreamSource blink_audio_source;
+ blink_audio_source.initialize(base::UTF8ToUTF16("dummy_source_id"),
+ blink::WebMediaStreamSource::TypeAudio,
+ base::UTF8ToUTF16("dummy_source_name"));
+ MediaStreamSource::SourceStoppedCallback cb;
+ blink_audio_source.setExtraData(
+ new MediaStreamAudioSource(-1, device_info, cb, NULL));
+ blink_track->initialize(blink::WebString::fromUTF8("dummy_track"),
+ blink_audio_source);
+ blink_track->setExtraData(native_track.release());
+ }
+
+ // Emulates an audio capture device capturing data from the source.
+ inline void CaptureAudio(const uint32 buffers) {
+ for (uint32 i = 0; i < buffers; ++i)
+ native_track()->Capture(source_data(),
+ base::TimeDelta::FromMilliseconds(0), 1, false,
+ false, false);
+ }
+
+ // Used to simulate a problem with sockets.
+ void SetFailureModeOnForeignSocket(bool in_failure_mode) {
+ recognizer()->sending_socket()->SetFailureMode(in_failure_mode);
+ }
+
+ // Helper method for verifying captured audio data has been consumed.
+ inline void AssertConsumedBuffers(const uint32 buffer_index) {
+ ASSERT_EQ(buffer_index, recognizer()->GetAudioInputBuffer()->params.size);
+ }
+
+ // Helper method for providing audio data to producer and verifying it was
+ // consumed on the recognizer.
+ inline void CaptureAudioAndAssertConsumedBuffers(const uint32 buffers,
+ const uint32 buffer_index) {
+ CaptureAudio(buffers);
+ AssertConsumedBuffers(buffer_index);
+ }
+
+ // Helper method to capture and assert consumption at different sample rates
+ // and audio buffer sizes.
+ inline void AssertConsumptionForAudioParameters(
+ const int input_sample_rate,
+ const int input_frames_per_buffer,
+ const int output_sample_rate,
+ const int output_frames_per_buffer,
+ const uint32 consumptions) {
+ const uint32 kBuffersPerNotification = Initialize(input_sample_rate,
+ input_frames_per_buffer,
+ output_sample_rate,
+ output_frames_per_buffer);
+ AssertConsumedBuffers(0U);
+
+ for (uint32 i = 1U; i <= consumptions; ++i) {
+ CaptureAudio(kBuffersPerNotification);
+ ASSERT_EQ(i, recognizer()->GetAudioInputBuffer()->params.size)
+ << "Tested at rates: "
+ << "In(" << input_sample_rate << ", " << input_frames_per_buffer
+ << ") "
+ << "Out(" << output_sample_rate << ", " << output_frames_per_buffer
+ << ")";
+ }
+ }
+
+ int16* source_data() { return source_data_.get(); }
+
+ FakeSpeechRecognizer* recognizer() { return recognizer_.get(); }
+
+ const media::AudioParameters& sink_params() { return sink_params_; }
+
+ WebRtcLocalAudioTrack* native_track() { return native_track_; }
+
+ private:
+ // Producer.
+ scoped_ptr<SpeechRecognitionAudioSink> speech_audio_sink_;
+
+ // Consumer.
+ scoped_ptr<FakeSpeechRecognizer> recognizer_;
+
+ // Audio related members.
+ scoped_ptr<int16[]> source_data_;
+ media::AudioParameters source_params_;
+ media::AudioParameters sink_params_;
+ WebRtcLocalAudioTrack* native_track_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionAudioSinkTest);
+};
+
+// Not all types of tracks are supported. This test checks if that policy is
+// implemented correctly.
+TEST_F(SpeechRecognitionAudioSinkTest, CheckIsSupportedAudioTrack) {
+ typedef std::map<MediaStreamType, bool> SupportedTrackPolicy;
+
+ // This test must be aligned with the policy of supported tracks.
+ SupportedTrackPolicy p;
+ p[MEDIA_NO_SERVICE] = false;
+ p[MEDIA_DEVICE_AUDIO_CAPTURE] = true; // The only one supported for now.
+ p[MEDIA_DEVICE_VIDEO_CAPTURE] = false;
+ p[MEDIA_TAB_AUDIO_CAPTURE] = false;
+ p[MEDIA_TAB_VIDEO_CAPTURE] = false;
+ p[MEDIA_DESKTOP_VIDEO_CAPTURE] = false;
+ p[MEDIA_LOOPBACK_AUDIO_CAPTURE] = false;
+ p[MEDIA_DEVICE_AUDIO_OUTPUT] = false;
+
+ // Ensure this test gets updated along with |content::MediaStreamType| enum.
+ EXPECT_EQ(NUM_MEDIA_TYPES, p.size());
+
+ // Check the the entire policy.
+ for (SupportedTrackPolicy::iterator it = p.begin(); it != p.end(); ++it) {
+ blink::WebMediaStreamTrack blink_track;
+ PrepareBlinkTrackOfType(it->first, &blink_track);
+ ASSERT_EQ(
+ it->second,
+ SpeechRecognitionAudioSink::IsSupportedTrack(blink_track));
+ }
+}
+
+// Checks if the producer can support the listed range of input sample rates
+// and associated buffer sizes.
+TEST_F(SpeechRecognitionAudioSinkTest, RecognizerNotifiedOnSocket) {
+ const size_t kNumAudioParamTuples = 24;
+ const int kAudioParams[kNumAudioParamTuples][2] = {
+ {8000, 80}, {8000, 800}, {16000, 160}, {16000, 1600},
+ {24000, 240}, {24000, 2400}, {32000, 320}, {32000, 3200},
+ {44100, 441}, {44100, 4410}, {48000, 480}, {48000, 4800},
+ {96000, 960}, {96000, 9600}, {11025, 111}, {11025, 1103},
+ {22050, 221}, {22050, 2205}, {88200, 882}, {88200, 8820},
+ {176400, 1764}, {176400, 17640}, {192000, 1920}, {192000, 19200}};
+
+ // Check all listed tuples of input sample rates and buffers sizes.
+ for (size_t i = 0; i < kNumAudioParamTuples; ++i) {
+ AssertConsumptionForAudioParameters(
+ kAudioParams[i][0], kAudioParams[i][1],
+ kSpeechRecognitionSampleRate, kSpeechRecognitionFramesPerBuffer, 3U);
+ }
+}
+
+// Checks that the input data is getting resampled to the target sample rate.
+TEST_F(SpeechRecognitionAudioSinkTest, AudioDataIsResampledOnSink) {
+ EXPECT_GE(kInputChannels, 1);
+ EXPECT_GE(kOutputChannels, 1);
+
+ // Input audio is sampled at 44.1 KHz with data chunks of 10ms. Desired output
+ // is corresponding to the speech recognition engine requirements: 16 KHz with
+ // 100 ms chunks (1600 frames per buffer).
+ const uint32 kBuffersPerNotification = Initialize(44100, 441, 16000, 1600);
+ // Fill audio input frames with 0, 1, 2, 3, ..., 440.
+ const uint32 kSourceDataLength = 441 * kInputChannels;
+ for (uint32 i = 0; i < kSourceDataLength; ++i) {
+ for (int c = 0; c < kInputChannels; ++c)
+ source_data()[i * kInputChannels + c] = i;
+ }
+
+ // Prepare sink audio bus and data for rendering.
+ media::AudioBus* sink_bus = recognizer()->audio_bus();
+ const uint32 kSinkDataLength = 1600 * kOutputChannels;
+ int16 sink_data[kSinkDataLength] = {0};
+
+ // Render the audio data from the recognizer.
+ sink_bus->ToInterleaved(sink_bus->frames(),
+ sink_params().bits_per_sample() / 8, sink_data);
+
+ // Checking only a fraction of the sink frames.
+ const uint32 kNumFramesToTest = 12;
+
+ // Check all channels are zeroed out before we trigger resampling.
+ for (uint32 i = 0; i < kNumFramesToTest; ++i) {
+ for (int c = 0; c < kOutputChannels; ++c)
+ EXPECT_EQ(0, sink_data[i * kOutputChannels + c]);
+ }
+
+ // Trigger the speech sink to resample the input data.
+ AssertConsumedBuffers(0U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+
+ // Render the audio data from the recognizer.
+ sink_bus->ToInterleaved(sink_bus->frames(),
+ sink_params().bits_per_sample() / 8, sink_data);
+
+ // Resampled data expected frames. Extracted based on |source_data()|.
+ const int16 kExpectedData[kNumFramesToTest] = {0, 2, 5, 8, 11, 13,
+ 16, 19, 22, 24, 27, 30};
+
+ // Check all channels have the same resampled data.
+ for (uint32 i = 0; i < kNumFramesToTest; ++i) {
+ for (int c = 0; c < kOutputChannels; ++c)
+ EXPECT_EQ(kExpectedData[i], sink_data[i * kOutputChannels + c]);
+ }
+}
+
+// Checks that the producer does not misbehave when a socket failure occurs.
+TEST_F(SpeechRecognitionAudioSinkTest, SyncSocketFailsSendingData) {
+ const uint32 kBuffersPerNotification = Initialize(44100, 441, 16000, 1600);
+ // Start with no problems on the socket.
+ AssertConsumedBuffers(0U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+
+ // A failure occurs (socket cannot send).
+ SetFailureModeOnForeignSocket(true);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+}
+
+// A very unlikely scenario in which the peer is not synchronizing for a long
+// time (e.g. 300 ms) which results in dropping cached buffers and restarting.
+// We check that the FIFO overflow does not occur and that the producer is able
+// to resume.
+TEST_F(SpeechRecognitionAudioSinkTest, RepeatedSycnhronizationLag) {
+ const uint32 kBuffersPerNotification = Initialize(44100, 441, 16000, 1600);
+
+ // Start with no synchronization problems.
+ AssertConsumedBuffers(0U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+
+ // Consumer gets out of sync.
+ recognizer()->SimulateResponsiveness(false);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+
+ // Consumer recovers.
+ recognizer()->SimulateResponsiveness(true);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 2U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 3U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 4U);
+}
+
+// Checks that an OnStoppedCallback is issued when the track is stopped.
+TEST_F(SpeechRecognitionAudioSinkTest, OnReadyStateChangedOccured) {
+ const uint32 kBuffersPerNotification = Initialize(44100, 441, 16000, 1600);
+ AssertConsumedBuffers(0U);
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+ EXPECT_CALL(*this, StoppedCallback()).Times(1);
+
+ native_track()->Stop();
+ CaptureAudioAndAssertConsumedBuffers(kBuffersPerNotification, 1U);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/test_response_generator.cc b/chromium/content/renderer/media/test_response_generator.cc
deleted file mode 100644
index 64f82e78f50..00000000000
--- a/chromium/content/renderer/media/test_response_generator.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/test_response_generator.h"
-
-#include "base/format_macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/net_errors.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-
-using blink::WebString;
-using blink::WebURLError;
-using blink::WebURLResponse;
-
-namespace content {
-
-TestResponseGenerator::TestResponseGenerator(const GURL& gurl,
- int64 content_length)
- : gurl_(gurl),
- content_length_(content_length) {
-}
-
-WebURLError TestResponseGenerator::GenerateError() {
- WebURLError error;
- error.reason = net::ERR_ABORTED;
- error.domain = WebString::fromUTF8(net::kErrorDomain);
- return error;
-}
-
-WebURLResponse TestResponseGenerator::Generate200() {
- WebURLResponse response(gurl_);
- response.setHTTPStatusCode(200);
-
- response.setHTTPHeaderField(
- WebString::fromUTF8("Content-Length"),
- WebString::fromUTF8(base::Int64ToString(content_length_)));
- response.setExpectedContentLength(content_length_);
- return response;
-}
-
-WebURLResponse TestResponseGenerator::Generate206(int64 first_byte_offset) {
- return Generate206(first_byte_offset, kNormal);
-}
-
-WebURLResponse TestResponseGenerator::Generate206(int64 first_byte_offset,
- Flags flags) {
- int64 range_content_length = content_length_ - first_byte_offset;
- int64 last_byte_offset = content_length_ - 1;
-
- WebURLResponse response(gurl_);
- response.setHTTPStatusCode(206);
-
- if ((flags & kNoAcceptRanges) == 0) {
- response.setHTTPHeaderField(WebString::fromUTF8("Accept-Ranges"),
- WebString::fromUTF8("bytes"));
- }
-
- if ((flags & kNoContentRange) == 0) {
- std::string content_range = base::StringPrintf(
- "bytes %" PRId64 "-%" PRId64 "/",
- first_byte_offset, last_byte_offset);
- if (flags & kNoContentRangeInstanceSize)
- content_range += "*";
- else
- content_range += base::StringPrintf("%" PRId64, content_length_);
- response.setHTTPHeaderField(WebString::fromUTF8("Content-Range"),
- WebString::fromUTF8(content_range));
- }
-
- if ((flags & kNoContentLength) == 0) {
- response.setHTTPHeaderField(
- WebString::fromUTF8("Content-Length"),
- WebString::fromUTF8(base::Int64ToString(range_content_length)));
- response.setExpectedContentLength(range_content_length);
- }
- return response;
-}
-
-WebURLResponse TestResponseGenerator::Generate404() {
- WebURLResponse response(gurl_);
- response.setHTTPStatusCode(404);
- return response;
-}
-
-WebURLResponse TestResponseGenerator::GenerateFileResponse(
- int64 first_byte_offset) {
- WebURLResponse response(gurl_);
- response.setHTTPStatusCode(0);
-
- if (first_byte_offset >= 0) {
- response.setExpectedContentLength(content_length_ - first_byte_offset);
- } else {
- response.setExpectedContentLength(-1);
- }
- return response;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/test_response_generator.h b/chromium/content/renderer/media/test_response_generator.h
deleted file mode 100644
index dcbcc0544e4..00000000000
--- a/chromium/content/renderer/media/test_response_generator.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_TEST_RESPONSE_GENERATOR_H_
-#define CONTENT_RENDERER_MEDIA_TEST_RESPONSE_GENERATOR_H_
-
-#include "base/basictypes.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// Generates WebURLErrors and WebURLResponses suitable for testing purposes.
-class TestResponseGenerator {
- public:
- enum Flags {
- kNormal = 0,
- kNoAcceptRanges = 1 << 0, // Don't include Accept-Ranges in 206 response.
- kNoContentRange = 1 << 1, // Don't include Content-Range in 206 response.
- kNoContentLength = 1 << 2, // Don't include Content-Length in 206 response.
- kNoContentRangeInstanceSize = 1 << 3, // Content-Range: N-M/* in 206.
- };
-
- // Build an HTTP response generator for the given URL. |content_length| is
- // used to generate Content-Length and Content-Range headers.
- TestResponseGenerator(const GURL& gurl, int64 content_length);
-
- // Generates a WebURLError object.
- blink::WebURLError GenerateError();
-
- // Generates a regular HTTP 200 response.
- blink::WebURLResponse Generate200();
-
- // Generates a regular HTTP 206 response starting from |first_byte_offset|
- // until the end of the resource.
- blink::WebURLResponse Generate206(int64 first_byte_offset);
-
- // Generates a custom HTTP 206 response starting from |first_byte_offset|
- // until the end of the resource. You can tweak what gets included in the
- // headers via |flags|.
- blink::WebURLResponse Generate206(int64 first_byte_offset, Flags flags);
-
- // Generates a regular HTTP 404 response.
- blink::WebURLResponse Generate404();
-
- // Generates a file:// response starting from |first_byte_offset| until the
- // end of the resource.
- //
- // If |first_byte_offset| is negative a response containing no content length
- // will be returned.
- blink::WebURLResponse GenerateFileResponse(int64 first_byte_offset);
-
- int64 content_length() { return content_length_; }
-
- private:
- GURL gurl_;
- int64 content_length_;
-
- DISALLOW_COPY_AND_ASSIGN(TestResponseGenerator);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_TEST_RESPONSE_GENERATOR_H_
diff --git a/chromium/content/renderer/media/texttrack_impl.cc b/chromium/content/renderer/media/texttrack_impl.cc
deleted file mode 100644
index 1e24f9bad65..00000000000
--- a/chromium/content/renderer/media/texttrack_impl.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/texttrack_impl.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "content/renderer/media/webinbandtexttrack_impl.h"
-#include "media/base/bind_to_current_loop.h"
-#include "third_party/WebKit/public/platform/WebInbandTextTrackClient.h"
-#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
-
-namespace content {
-
-TextTrackImpl::TextTrackImpl(
- const scoped_refptr<base::MessageLoopProxy>& message_loop,
- blink::WebMediaPlayerClient* client,
- scoped_ptr<WebInbandTextTrackImpl> text_track)
- : message_loop_(message_loop),
- client_(client),
- text_track_(text_track.Pass()) {
- client_->addTextTrack(text_track_.get());
-}
-
-TextTrackImpl::~TextTrackImpl() {
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&TextTrackImpl::OnRemoveTrack,
- client_,
- base::Passed(&text_track_)));
-}
-
-void TextTrackImpl::addWebVTTCue(const base::TimeDelta& start,
- const base::TimeDelta& end,
- const std::string& id,
- const std::string& content,
- const std::string& settings) {
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&TextTrackImpl::OnAddCue,
- text_track_.get(),
- start, end,
- id, content, settings));
-}
-
-void TextTrackImpl::OnAddCue(WebInbandTextTrackImpl* text_track,
- const base::TimeDelta& start,
- const base::TimeDelta& end,
- const std::string& id,
- const std::string& content,
- const std::string& settings) {
- if (blink::WebInbandTextTrackClient* client = text_track->client()) {
- client->addWebVTTCue(start.InSecondsF(),
- end.InSecondsF(),
- blink::WebString::fromUTF8(id),
- blink::WebString::fromUTF8(content),
- blink::WebString::fromUTF8(settings));
- }
-}
-
-void TextTrackImpl::OnRemoveTrack(
- blink::WebMediaPlayerClient* client,
- scoped_ptr<WebInbandTextTrackImpl> text_track) {
- if (text_track->client())
- client->removeTextTrack(text_track.get());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/texttrack_impl.h b/chromium/content/renderer/media/texttrack_impl.h
deleted file mode 100644
index 3285b60ed10..00000000000
--- a/chromium/content/renderer/media/texttrack_impl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_TEXTTRACK_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_TEXTTRACK_IMPL_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "media/base/text_track.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace blink {
-class WebInbandTextTrackClient;
-class WebMediaPlayerClient;
-}
-
-namespace content {
-
-class WebInbandTextTrackImpl;
-
-class TextTrackImpl : public media::TextTrack {
- public:
- // Constructor assumes ownership of the |text_track| object.
- TextTrackImpl(const scoped_refptr<base::MessageLoopProxy>& message_loop,
- blink::WebMediaPlayerClient* client,
- scoped_ptr<WebInbandTextTrackImpl> text_track);
-
- virtual ~TextTrackImpl();
-
- virtual void addWebVTTCue(const base::TimeDelta& start,
- const base::TimeDelta& end,
- const std::string& id,
- const std::string& content,
- const std::string& settings) OVERRIDE;
-
- private:
- static void OnAddCue(WebInbandTextTrackImpl* text_track,
- const base::TimeDelta& start,
- const base::TimeDelta& end,
- const std::string& id,
- const std::string& content,
- const std::string& settings);
-
- static void OnRemoveTrack(blink::WebMediaPlayerClient* client,
- scoped_ptr<WebInbandTextTrackImpl> text_track);
-
- scoped_refptr<base::MessageLoopProxy> message_loop_;
- blink::WebMediaPlayerClient* client_;
- scoped_ptr<WebInbandTextTrackImpl> text_track_;
- DISALLOW_COPY_AND_ASSIGN(TextTrackImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_TEXTTRACK_IMPL_H_
-
diff --git a/chromium/content/renderer/media/user_media_client_impl.cc b/chromium/content/renderer/media/user_media_client_impl.cc
new file mode 100644
index 00000000000..047e07ae4fd
--- /dev/null
+++ b/chromium/content/renderer/media/user_media_client_impl.cc
@@ -0,0 +1,1070 @@
+// Copyright (c) 2012 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 "content/renderer/media/user_media_client_impl.h"
+
+#include <utility>
+
+#include "base/hash.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/renderer/render_frame.h"
+#include "content/renderer/media/media_stream.h"
+#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/media/media_stream_dispatcher.h"
+#include "content/renderer/media/media_stream_video_capturer_source.h"
+#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/peer_connection_tracker.h"
+#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
+#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_logging.h"
+#include "content/renderer/media/webrtc_uma_histograms.h"
+#include "content/renderer/render_thread_impl.h"
+#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+#include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+
+namespace content {
+namespace {
+
+void CopyStreamConstraints(const blink::WebMediaConstraints& constraints,
+ StreamOptions::Constraints* mandatory,
+ StreamOptions::Constraints* optional) {
+ blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
+ constraints.getMandatoryConstraints(mandatory_constraints);
+ for (size_t i = 0; i < mandatory_constraints.size(); i++) {
+ mandatory->push_back(StreamOptions::Constraint(
+ mandatory_constraints[i].m_name.utf8(),
+ mandatory_constraints[i].m_value.utf8()));
+ }
+
+ blink::WebVector<blink::WebMediaConstraint> optional_constraints;
+ constraints.getOptionalConstraints(optional_constraints);
+ for (size_t i = 0; i < optional_constraints.size(); i++) {
+ optional->push_back(StreamOptions::Constraint(
+ optional_constraints[i].m_name.utf8(),
+ optional_constraints[i].m_value.utf8()));
+ }
+}
+
+static int g_next_request_id = 0;
+
+} // namespace
+
+struct UserMediaClientImpl::MediaDevicesRequestInfo {
+ MediaDevicesRequestInfo(const blink::WebMediaDevicesRequest& request,
+ int audio_input_request_id,
+ int video_input_request_id,
+ int audio_output_request_id)
+ : media_devices_request(request),
+ audio_input_request_id(audio_input_request_id),
+ video_input_request_id(video_input_request_id),
+ audio_output_request_id(audio_output_request_id),
+ has_audio_input_returned(false),
+ has_video_input_returned(false),
+ has_audio_output_returned(false) {}
+
+ MediaDevicesRequestInfo(
+ const blink::WebMediaStreamTrackSourcesRequest& request,
+ int audio_input_request_id,
+ int video_input_request_id)
+ : sources_request(request),
+ audio_input_request_id(audio_input_request_id),
+ video_input_request_id(video_input_request_id),
+ audio_output_request_id(-1),
+ has_audio_input_returned(false),
+ has_video_input_returned(false),
+ has_audio_output_returned(false) {}
+
+ bool IsSourcesRequest() {
+ // We can't check isNull() on |media_devices_request| and |sources_request|,
+ // because in unit tests they will always be null.
+ return audio_output_request_id == -1;
+ }
+
+ blink::WebMediaDevicesRequest media_devices_request;
+ blink::WebMediaStreamTrackSourcesRequest sources_request;
+ int audio_input_request_id;
+ int video_input_request_id;
+ int audio_output_request_id;
+ bool has_audio_input_returned;
+ bool has_video_input_returned;
+ bool has_audio_output_returned;
+ StreamDeviceInfoArray audio_input_devices;
+ StreamDeviceInfoArray video_input_devices;
+ StreamDeviceInfoArray audio_output_devices;
+};
+
+UserMediaClientImpl::UserMediaClientImpl(
+ RenderFrame* render_frame,
+ PeerConnectionDependencyFactory* dependency_factory,
+ scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher)
+ : RenderFrameObserver(render_frame),
+ dependency_factory_(dependency_factory),
+ media_stream_dispatcher_(media_stream_dispatcher.Pass()),
+ weak_factory_(this) {
+ DCHECK(dependency_factory_);
+ DCHECK(media_stream_dispatcher_.get());
+}
+
+UserMediaClientImpl::~UserMediaClientImpl() {
+ // Force-close all outstanding user media requests and local sources here,
+ // before the outstanding WeakPtrs are invalidated, to ensure a clean
+ // shutdown.
+ FrameWillClose();
+}
+
+void UserMediaClientImpl::requestUserMedia(
+ const blink::WebUserMediaRequest& user_media_request) {
+ // Save histogram data so we can see how much GetUserMedia is used.
+ // The histogram counts the number of calls to the JS API
+ // webGetUserMedia.
+ UpdateWebRTCMethodCount(WEBKIT_GET_USER_MEDIA);
+ DCHECK(CalledOnValidThread());
+
+ if (RenderThreadImpl::current()) {
+ RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia(
+ user_media_request);
+ }
+
+ int request_id = g_next_request_id++;
+ StreamOptions options;
+ GURL security_origin;
+ bool enable_automatic_output_device_selection = false;
+
+ // |user_media_request| can't be mocked. So in order to test at all we check
+ // if it isNull.
+ if (user_media_request.isNull()) {
+ // We are in a test.
+ options.audio_requested = true;
+ options.video_requested = true;
+ } else {
+ if (user_media_request.audio()) {
+ options.audio_requested = true;
+ CopyStreamConstraints(user_media_request.audioConstraints(),
+ &options.mandatory_audio,
+ &options.optional_audio);
+
+ // Check if this input device should be used to select a matching output
+ // device for audio rendering.
+ std::string enable;
+ if (options.GetFirstAudioConstraintByName(
+ kMediaStreamRenderToAssociatedSink, &enable, NULL) &&
+ LowerCaseEqualsASCII(enable, "true")) {
+ enable_automatic_output_device_selection = true;
+ }
+ }
+ if (user_media_request.video()) {
+ options.video_requested = true;
+ CopyStreamConstraints(user_media_request.videoConstraints(),
+ &options.mandatory_video,
+ &options.optional_video);
+ }
+
+ security_origin = GURL(user_media_request.securityOrigin().toString());
+ DCHECK(render_frame()->GetWebFrame() ==
+ static_cast<blink::WebFrame*>(
+ user_media_request.ownerDocument().frame()));
+ }
+
+ DVLOG(1) << "UserMediaClientImpl::requestUserMedia(" << request_id << ", [ "
+ << "audio=" << (options.audio_requested)
+ << " select associated sink: "
+ << enable_automatic_output_device_selection
+ << ", video=" << (options.video_requested) << " ], "
+ << security_origin.spec() << ")";
+
+ std::string audio_device_id;
+ bool mandatory_audio;
+ options.GetFirstAudioConstraintByName(kMediaStreamSourceInfoId,
+ &audio_device_id, &mandatory_audio);
+ std::string video_device_id;
+ bool mandatory_video;
+ options.GetFirstVideoConstraintByName(kMediaStreamSourceInfoId,
+ &video_device_id, &mandatory_video);
+
+ WebRtcLogMessage(base::StringPrintf(
+ "MSI::requestUserMedia. request_id=%d"
+ ", audio source id=%s mandatory= %s "
+ ", video source id=%s mandatory= %s",
+ request_id,
+ audio_device_id.c_str(),
+ mandatory_audio ? "true":"false",
+ video_device_id.c_str(),
+ mandatory_video ? "true":"false"));
+
+ user_media_requests_.push_back(
+ new UserMediaRequestInfo(request_id, user_media_request,
+ enable_automatic_output_device_selection));
+
+ media_stream_dispatcher_->GenerateStream(
+ request_id,
+ weak_factory_.GetWeakPtr(),
+ options,
+ security_origin);
+}
+
+void UserMediaClientImpl::cancelUserMediaRequest(
+ const blink::WebUserMediaRequest& user_media_request) {
+ DCHECK(CalledOnValidThread());
+ UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request);
+ if (request) {
+ // We can't abort the stream generation process.
+ // Instead, erase the request. Once the stream is generated we will stop the
+ // stream if the request does not exist.
+ LogUserMediaRequestWithNoResult(MEDIA_STREAM_REQUEST_EXPLICITLY_CANCELLED);
+ DeleteUserMediaRequestInfo(request);
+ }
+}
+
+void UserMediaClientImpl::requestMediaDevices(
+ const blink::WebMediaDevicesRequest& media_devices_request) {
+ UpdateWebRTCMethodCount(WEBKIT_GET_MEDIA_DEVICES);
+ DCHECK(CalledOnValidThread());
+
+ int audio_input_request_id = g_next_request_id++;
+ int video_input_request_id = g_next_request_id++;
+ int audio_output_request_id = g_next_request_id++;
+
+ // |media_devices_request| can't be mocked, so in tests it will be empty (the
+ // underlying pointer is null). In order to use this function in a test we
+ // need to check if it isNull.
+ GURL security_origin;
+ if (!media_devices_request.isNull())
+ security_origin = GURL(media_devices_request.securityOrigin().toString());
+
+ DVLOG(1) << "UserMediaClientImpl::requestMediaDevices("
+ << audio_input_request_id
+ << ", " << video_input_request_id << ", " << audio_output_request_id
+ << ", " << security_origin.spec() << ")";
+
+ media_devices_requests_.push_back(new MediaDevicesRequestInfo(
+ media_devices_request,
+ audio_input_request_id,
+ video_input_request_id,
+ audio_output_request_id));
+
+ media_stream_dispatcher_->EnumerateDevices(
+ audio_input_request_id,
+ weak_factory_.GetWeakPtr(),
+ MEDIA_DEVICE_AUDIO_CAPTURE,
+ security_origin);
+
+ media_stream_dispatcher_->EnumerateDevices(
+ video_input_request_id,
+ weak_factory_.GetWeakPtr(),
+ MEDIA_DEVICE_VIDEO_CAPTURE,
+ security_origin);
+
+ media_stream_dispatcher_->EnumerateDevices(
+ audio_output_request_id,
+ weak_factory_.GetWeakPtr(),
+ MEDIA_DEVICE_AUDIO_OUTPUT,
+ security_origin);
+}
+
+void UserMediaClientImpl::cancelMediaDevicesRequest(
+ const blink::WebMediaDevicesRequest& media_devices_request) {
+ DCHECK(CalledOnValidThread());
+ MediaDevicesRequestInfo* request =
+ FindMediaDevicesRequestInfo(media_devices_request);
+ if (!request)
+ return;
+ CancelAndDeleteMediaDevicesRequest(request);
+}
+
+void UserMediaClientImpl::requestSources(
+ const blink::WebMediaStreamTrackSourcesRequest& sources_request) {
+ // We don't call UpdateWebRTCMethodCount() here to track the API count in UMA
+ // stats. This is instead counted in MediaStreamTrack::getSources in blink.
+ DCHECK(CalledOnValidThread());
+
+ int audio_input_request_id = g_next_request_id++;
+ int video_input_request_id = g_next_request_id++;
+
+ // |sources_request| can't be mocked, so in tests it will be empty (the
+ // underlying pointer is null). In order to use this function in a test we
+ // need to check if it isNull.
+ GURL security_origin;
+ if (!sources_request.isNull())
+ security_origin = GURL(sources_request.origin().utf8());
+
+ DVLOG(1) << "UserMediaClientImpl::requestSources("
+ << audio_input_request_id
+ << ", " << video_input_request_id
+ << ", " << security_origin.spec() << ")";
+
+ media_devices_requests_.push_back(new MediaDevicesRequestInfo(
+ sources_request,
+ audio_input_request_id,
+ video_input_request_id));
+
+ media_stream_dispatcher_->EnumerateDevices(
+ audio_input_request_id,
+ weak_factory_.GetWeakPtr(),
+ MEDIA_DEVICE_AUDIO_CAPTURE,
+ security_origin);
+
+ media_stream_dispatcher_->EnumerateDevices(
+ video_input_request_id,
+ weak_factory_.GetWeakPtr(),
+ MEDIA_DEVICE_VIDEO_CAPTURE,
+ security_origin);
+}
+
+// Callback from MediaStreamDispatcher.
+// The requested stream have been generated by the MediaStreamDispatcher.
+void UserMediaClientImpl::OnStreamGenerated(
+ int request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& audio_array,
+ const StreamDeviceInfoArray& video_array) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "UserMediaClientImpl::OnStreamGenerated stream:" << label;
+
+ UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(request_id);
+ if (!request_info) {
+ // This can happen if the request is canceled or the frame reloads while
+ // MediaStreamDispatcher is processing the request.
+ DVLOG(1) << "Request ID not found";
+ OnStreamGeneratedForCancelledRequest(audio_array, video_array);
+ return;
+ }
+ request_info->generated = true;
+
+ // WebUserMediaRequest don't have an implementation in unit tests.
+ // Therefore we need to check for isNull here and initialize the
+ // constraints.
+ blink::WebUserMediaRequest* request = &(request_info->request);
+ blink::WebMediaConstraints audio_constraints;
+ blink::WebMediaConstraints video_constraints;
+ if (request->isNull()) {
+ audio_constraints.initialize();
+ video_constraints.initialize();
+ } else {
+ audio_constraints = request->audioConstraints();
+ video_constraints = request->videoConstraints();
+ }
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector(
+ audio_array.size());
+ CreateAudioTracks(audio_array, audio_constraints, &audio_track_vector,
+ request_info);
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
+ video_array.size());
+ CreateVideoTracks(video_array, video_constraints, &video_track_vector,
+ request_info);
+
+ blink::WebString webkit_id = base::UTF8ToUTF16(label);
+ blink::WebMediaStream* web_stream = &(request_info->web_stream);
+
+ web_stream->initialize(webkit_id, audio_track_vector,
+ video_track_vector);
+ web_stream->setExtraData(
+ new MediaStream(
+ *web_stream));
+
+ // Wait for the tracks to be started successfully or to fail.
+ request_info->CallbackOnTracksStarted(
+ base::Bind(&UserMediaClientImpl::OnCreateNativeTracksCompleted,
+ weak_factory_.GetWeakPtr()));
+}
+
+void UserMediaClientImpl::OnStreamGeneratedForCancelledRequest(
+ const StreamDeviceInfoArray& audio_array,
+ const StreamDeviceInfoArray& video_array) {
+ // Only stop the device if the device is not used in another MediaStream.
+ for (StreamDeviceInfoArray::const_iterator device_it = audio_array.begin();
+ device_it != audio_array.end(); ++device_it) {
+ if (!FindLocalSource(*device_it))
+ media_stream_dispatcher_->StopStreamDevice(*device_it);
+ }
+
+ for (StreamDeviceInfoArray::const_iterator device_it = video_array.begin();
+ device_it != video_array.end(); ++device_it) {
+ if (!FindLocalSource(*device_it))
+ media_stream_dispatcher_->StopStreamDevice(*device_it);
+ }
+}
+
+void UserMediaClientImpl::FinalizeEnumerateDevices(
+ MediaDevicesRequestInfo* request) {
+ // All devices are ready for copying. We use a hashed audio output device id
+ // as the group id for input and output audio devices. If an input device
+ // doesn't have an associated output device, we use the input device's own id.
+ // We don't support group id for video devices, that's left empty.
+ blink::WebVector<blink::WebMediaDeviceInfo>
+ devices(request->audio_input_devices.size() +
+ request->video_input_devices.size() +
+ request->audio_output_devices.size());
+ for (size_t i = 0; i < request->audio_input_devices.size(); ++i) {
+ const MediaStreamDevice& device = request->audio_input_devices[i].device;
+ DCHECK_EQ(device.type, MEDIA_DEVICE_AUDIO_CAPTURE);
+ std::string group_id = base::UintToString(base::Hash(
+ !device.matched_output_device_id.empty() ?
+ device.matched_output_device_id :
+ device.id));
+ devices[i].initialize(
+ blink::WebString::fromUTF8(device.id),
+ blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
+ blink::WebString::fromUTF8(device.name),
+ blink::WebString::fromUTF8(group_id));
+ }
+ size_t offset = request->audio_input_devices.size();
+ for (size_t i = 0; i < request->video_input_devices.size(); ++i) {
+ const MediaStreamDevice& device = request->video_input_devices[i].device;
+ DCHECK_EQ(device.type, MEDIA_DEVICE_VIDEO_CAPTURE);
+ devices[offset + i].initialize(
+ blink::WebString::fromUTF8(device.id),
+ blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
+ blink::WebString::fromUTF8(device.name),
+ blink::WebString());
+ }
+ offset += request->video_input_devices.size();
+ for (size_t i = 0; i < request->audio_output_devices.size(); ++i) {
+ const MediaStreamDevice& device = request->audio_output_devices[i].device;
+ DCHECK_EQ(device.type, MEDIA_DEVICE_AUDIO_OUTPUT);
+ devices[offset + i].initialize(
+ blink::WebString::fromUTF8(device.id),
+ blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput,
+ blink::WebString::fromUTF8(device.name),
+ blink::WebString::fromUTF8(base::UintToString(base::Hash(device.id))));
+ }
+
+ EnumerateDevicesSucceded(&request->media_devices_request, devices);
+}
+
+void UserMediaClientImpl::FinalizeEnumerateSources(
+ MediaDevicesRequestInfo* request) {
+ blink::WebVector<blink::WebSourceInfo>
+ sources(request->audio_input_devices.size() +
+ request->video_input_devices.size());
+ for (size_t i = 0; i < request->audio_input_devices.size(); ++i) {
+ const MediaStreamDevice& device = request->audio_input_devices[i].device;
+ DCHECK_EQ(device.type, MEDIA_DEVICE_AUDIO_CAPTURE);
+ std::string group_id = base::UintToString(base::Hash(
+ !device.matched_output_device_id.empty() ?
+ device.matched_output_device_id :
+ device.id));
+ sources[i].initialize(blink::WebString::fromUTF8(device.id),
+ blink::WebSourceInfo::SourceKindAudio,
+ blink::WebString::fromUTF8(device.name),
+ blink::WebSourceInfo::VideoFacingModeNone);
+ }
+ size_t offset = request->audio_input_devices.size();
+ for (size_t i = 0; i < request->video_input_devices.size(); ++i) {
+ const MediaStreamDevice& device = request->video_input_devices[i].device;
+ DCHECK_EQ(device.type, MEDIA_DEVICE_VIDEO_CAPTURE);
+ blink::WebSourceInfo::VideoFacingMode video_facing;
+ switch (device.video_facing) {
+ case MEDIA_VIDEO_FACING_USER:
+ video_facing = blink::WebSourceInfo::VideoFacingModeUser;
+ break;
+ case MEDIA_VIDEO_FACING_ENVIRONMENT:
+ video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment;
+ break;
+ default:
+ video_facing = blink::WebSourceInfo::VideoFacingModeNone;
+ }
+ sources[offset + i].initialize(blink::WebString::fromUTF8(device.id),
+ blink::WebSourceInfo::SourceKindVideo,
+ blink::WebString::fromUTF8(device.name),
+ video_facing);
+ }
+
+ EnumerateSourcesSucceded(&request->sources_request, sources);
+}
+
+// Callback from MediaStreamDispatcher.
+// The requested stream failed to be generated.
+void UserMediaClientImpl::OnStreamGenerationFailed(
+ int request_id,
+ MediaStreamRequestResult result) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "UserMediaClientImpl::OnStreamGenerationFailed("
+ << request_id << ")";
+ UserMediaRequestInfo* request_info = FindUserMediaRequestInfo(request_id);
+ if (!request_info) {
+ // This can happen if the request is canceled or the frame reloads while
+ // MediaStreamDispatcher is processing the request.
+ DVLOG(1) << "Request ID not found";
+ return;
+ }
+
+ GetUserMediaRequestFailed(&request_info->request, result);
+ DeleteUserMediaRequestInfo(request_info);
+}
+
+// Callback from MediaStreamDispatcher.
+// The browser process has stopped a device used by a MediaStream.
+void UserMediaClientImpl::OnDeviceStopped(
+ const std::string& label,
+ const StreamDeviceInfo& device_info) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "UserMediaClientImpl::OnDeviceStopped("
+ << "{device_id = " << device_info.device.id << "})";
+
+ const blink::WebMediaStreamSource* source_ptr = FindLocalSource(device_info);
+ if (!source_ptr) {
+ // This happens if the same device is used in several guM requests or
+ // if a user happen stop a track from JS at the same time
+ // as the underlying media device is unplugged from the system.
+ return;
+ }
+ // By creating |source| it is guaranteed that the blink::WebMediaStreamSource
+ // object is valid during the cleanup.
+ blink::WebMediaStreamSource source(*source_ptr);
+ StopLocalSource(source, false);
+
+ for (LocalStreamSources::iterator device_it = local_sources_.begin();
+ device_it != local_sources_.end(); ++device_it) {
+ if (device_it->id() == source.id()) {
+ local_sources_.erase(device_it);
+ break;
+ }
+ }
+}
+
+void UserMediaClientImpl::InitializeSourceObject(
+ const StreamDeviceInfo& device,
+ blink::WebMediaStreamSource::Type type,
+ const blink::WebMediaConstraints& constraints,
+ blink::WebMediaStreamSource* webkit_source) {
+ const blink::WebMediaStreamSource* existing_source =
+ FindLocalSource(device);
+ if (existing_source) {
+ *webkit_source = *existing_source;
+ DVLOG(1) << "Source already exist. Reusing source with id "
+ << webkit_source->id().utf8();
+ return;
+ }
+
+ webkit_source->initialize(
+ base::UTF8ToUTF16(device.device.id),
+ type,
+ base::UTF8ToUTF16(device.device.name));
+
+ DVLOG(1) << "Initialize source object :"
+ << "id = " << webkit_source->id().utf8()
+ << ", name = " << webkit_source->name().utf8();
+
+ if (type == blink::WebMediaStreamSource::TypeVideo) {
+ webkit_source->setExtraData(
+ CreateVideoSource(
+ device,
+ base::Bind(&UserMediaClientImpl::OnLocalSourceStopped,
+ weak_factory_.GetWeakPtr())));
+ } else {
+ DCHECK_EQ(blink::WebMediaStreamSource::TypeAudio, type);
+ MediaStreamAudioSource* audio_source(
+ new MediaStreamAudioSource(
+ RenderFrameObserver::routing_id(),
+ device,
+ base::Bind(&UserMediaClientImpl::OnLocalSourceStopped,
+ weak_factory_.GetWeakPtr()),
+ dependency_factory_));
+ webkit_source->setExtraData(audio_source);
+ }
+ local_sources_.push_back(*webkit_source);
+}
+
+MediaStreamVideoSource* UserMediaClientImpl::CreateVideoSource(
+ const StreamDeviceInfo& device,
+ const MediaStreamSource::SourceStoppedCallback& stop_callback) {
+ return new content::MediaStreamVideoCapturerSource(
+ device,
+ stop_callback,
+ new VideoCapturerDelegate(device));
+}
+
+void UserMediaClientImpl::CreateVideoTracks(
+ const StreamDeviceInfoArray& devices,
+ const blink::WebMediaConstraints& constraints,
+ blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
+ UserMediaRequestInfo* request) {
+ DCHECK_EQ(devices.size(), webkit_tracks->size());
+
+ for (size_t i = 0; i < devices.size(); ++i) {
+ blink::WebMediaStreamSource webkit_source;
+ InitializeSourceObject(devices[i],
+ blink::WebMediaStreamSource::TypeVideo,
+ constraints,
+ &webkit_source);
+ (*webkit_tracks)[i] =
+ request->CreateAndStartVideoTrack(webkit_source, constraints);
+ }
+}
+
+void UserMediaClientImpl::CreateAudioTracks(
+ const StreamDeviceInfoArray& devices,
+ const blink::WebMediaConstraints& constraints,
+ blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
+ UserMediaRequestInfo* request) {
+ DCHECK_EQ(devices.size(), webkit_tracks->size());
+
+ // Log the device names for this request.
+ for (StreamDeviceInfoArray::const_iterator it = devices.begin();
+ it != devices.end(); ++it) {
+ WebRtcLogMessage(base::StringPrintf(
+ "Generated media stream for request id %d contains audio device name"
+ " \"%s\"",
+ request->request_id,
+ it->device.name.c_str()));
+ }
+
+ StreamDeviceInfoArray overridden_audio_array = devices;
+ if (!request->enable_automatic_output_device_selection) {
+ // If the GetUserMedia request did not explicitly set the constraint
+ // kMediaStreamRenderToAssociatedSink, the output device parameters must
+ // be removed.
+ for (StreamDeviceInfoArray::iterator it = overridden_audio_array.begin();
+ it != overridden_audio_array.end(); ++it) {
+ it->device.matched_output_device_id = "";
+ it->device.matched_output = MediaStreamDevice::AudioDeviceParameters();
+ }
+ }
+
+ for (size_t i = 0; i < overridden_audio_array.size(); ++i) {
+ blink::WebMediaStreamSource webkit_source;
+ InitializeSourceObject(overridden_audio_array[i],
+ blink::WebMediaStreamSource::TypeAudio,
+ constraints,
+ &webkit_source);
+ (*webkit_tracks)[i].initialize(webkit_source);
+ request->StartAudioTrack((*webkit_tracks)[i], constraints);
+ }
+}
+
+void UserMediaClientImpl::OnCreateNativeTracksCompleted(
+ UserMediaRequestInfo* request,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
+ DVLOG(1) << "UserMediaClientImpl::OnCreateNativeTracksComplete("
+ << "{request_id = " << request->request_id << "} "
+ << "{result = " << result << "})";
+ if (result == content::MEDIA_DEVICE_OK)
+ GetUserMediaRequestSucceeded(request->web_stream, &request->request);
+ else
+ GetUserMediaRequestTrackStartedFailed(&request->request,
+ result,
+ result_name);
+
+ DeleteUserMediaRequestInfo(request);
+}
+
+void UserMediaClientImpl::OnDevicesEnumerated(
+ int request_id,
+ const StreamDeviceInfoArray& device_array) {
+ DVLOG(1) << "UserMediaClientImpl::OnDevicesEnumerated(" << request_id << ")";
+
+ MediaDevicesRequestInfo* request = FindMediaDevicesRequestInfo(request_id);
+ DCHECK(request);
+
+ if (request_id == request->audio_input_request_id) {
+ request->has_audio_input_returned = true;
+ DCHECK(request->audio_input_devices.empty());
+ request->audio_input_devices = device_array;
+ } else if (request_id == request->video_input_request_id) {
+ request->has_video_input_returned = true;
+ DCHECK(request->video_input_devices.empty());
+ request->video_input_devices = device_array;
+ } else {
+ DCHECK_EQ(request->audio_output_request_id, request_id);
+ request->has_audio_output_returned = true;
+ DCHECK(request->audio_output_devices.empty());
+ request->audio_output_devices = device_array;
+ }
+
+ if (!request->has_audio_input_returned ||
+ !request->has_video_input_returned ||
+ (!request->IsSourcesRequest() && !request->has_audio_output_returned)) {
+ // Wait for the rest of the devices to complete.
+ return;
+ }
+
+ if (request->IsSourcesRequest())
+ FinalizeEnumerateSources(request);
+ else
+ FinalizeEnumerateDevices(request);
+
+ CancelAndDeleteMediaDevicesRequest(request);
+}
+
+void UserMediaClientImpl::OnDeviceOpened(
+ int request_id,
+ const std::string& label,
+ const StreamDeviceInfo& video_device) {
+ DVLOG(1) << "UserMediaClientImpl::OnDeviceOpened("
+ << request_id << ", " << label << ")";
+ NOTIMPLEMENTED();
+}
+
+void UserMediaClientImpl::OnDeviceOpenFailed(int request_id) {
+ DVLOG(1) << "UserMediaClientImpl::VideoDeviceOpenFailed("
+ << request_id << ")";
+ NOTIMPLEMENTED();
+}
+
+void UserMediaClientImpl::GetUserMediaRequestSucceeded(
+ const blink::WebMediaStream& stream,
+ blink::WebUserMediaRequest* request_info) {
+ DVLOG(1) << "UserMediaClientImpl::GetUserMediaRequestSucceeded";
+ LogUserMediaRequestResult(MEDIA_DEVICE_OK);
+ request_info->requestSucceeded(stream);
+}
+
+void UserMediaClientImpl::GetUserMediaRequestFailed(
+ blink::WebUserMediaRequest* request_info,
+ MediaStreamRequestResult result) {
+ LogUserMediaRequestResult(result);
+ switch (result) {
+ case MEDIA_DEVICE_OK:
+ NOTREACHED();
+ break;
+ case MEDIA_DEVICE_PERMISSION_DENIED:
+ request_info->requestDenied();
+ break;
+ case MEDIA_DEVICE_PERMISSION_DISMISSED:
+ request_info->requestFailedUASpecific("PermissionDismissedError");
+ break;
+ case MEDIA_DEVICE_INVALID_STATE:
+ request_info->requestFailedUASpecific("InvalidStateError");
+ break;
+ case MEDIA_DEVICE_NO_HARDWARE:
+ request_info->requestFailedUASpecific("DevicesNotFoundError");
+ break;
+ case MEDIA_DEVICE_INVALID_SECURITY_ORIGIN:
+ request_info->requestFailedUASpecific("InvalidSecurityOriginError");
+ break;
+ case MEDIA_DEVICE_TAB_CAPTURE_FAILURE:
+ request_info->requestFailedUASpecific("TabCaptureError");
+ break;
+ case MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE:
+ request_info->requestFailedUASpecific("ScreenCaptureError");
+ break;
+ case MEDIA_DEVICE_CAPTURE_FAILURE:
+ request_info->requestFailedUASpecific("DeviceCaptureError");
+ break;
+ default:
+ NOTREACHED();
+ request_info->requestFailed();
+ break;
+ }
+}
+
+void UserMediaClientImpl::GetUserMediaRequestTrackStartedFailed(
+ blink::WebUserMediaRequest* request_info,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
+ switch (result) {
+ case MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED:
+ request_info->requestFailedConstraint(result_name);
+ break;
+ case MEDIA_DEVICE_TRACK_START_FAILURE:
+ request_info->requestFailedUASpecific("TrackStartError");
+ break;
+ default:
+ NOTREACHED();
+ request_info->requestFailed();
+ break;
+ }
+}
+
+void UserMediaClientImpl::EnumerateDevicesSucceded(
+ blink::WebMediaDevicesRequest* request,
+ blink::WebVector<blink::WebMediaDeviceInfo>& devices) {
+ request->requestSucceeded(devices);
+}
+
+void UserMediaClientImpl::EnumerateSourcesSucceded(
+ blink::WebMediaStreamTrackSourcesRequest* request,
+ blink::WebVector<blink::WebSourceInfo>& sources) {
+ request->requestSucceeded(sources);
+}
+
+const blink::WebMediaStreamSource* UserMediaClientImpl::FindLocalSource(
+ const StreamDeviceInfo& device) const {
+ for (LocalStreamSources::const_iterator it = local_sources_.begin();
+ it != local_sources_.end(); ++it) {
+ MediaStreamSource* const source =
+ static_cast<MediaStreamSource*>(it->extraData());
+ const StreamDeviceInfo& active_device = source->device_info();
+ if (active_device.device.id == device.device.id &&
+ active_device.device.type == device.device.type &&
+ active_device.session_id == device.session_id) {
+ return &(*it);
+ }
+ }
+ return NULL;
+}
+
+UserMediaClientImpl::UserMediaRequestInfo*
+UserMediaClientImpl::FindUserMediaRequestInfo(int request_id) {
+ UserMediaRequests::iterator it = user_media_requests_.begin();
+ for (; it != user_media_requests_.end(); ++it) {
+ if ((*it)->request_id == request_id)
+ return (*it);
+ }
+ return NULL;
+}
+
+UserMediaClientImpl::UserMediaRequestInfo*
+UserMediaClientImpl::FindUserMediaRequestInfo(
+ const blink::WebUserMediaRequest& request) {
+ UserMediaRequests::iterator it = user_media_requests_.begin();
+ for (; it != user_media_requests_.end(); ++it) {
+ if ((*it)->request == request)
+ return (*it);
+ }
+ return NULL;
+}
+
+void UserMediaClientImpl::DeleteUserMediaRequestInfo(
+ UserMediaRequestInfo* request) {
+ UserMediaRequests::iterator it = user_media_requests_.begin();
+ for (; it != user_media_requests_.end(); ++it) {
+ if ((*it) == request) {
+ user_media_requests_.erase(it);
+ return;
+ }
+ }
+ NOTREACHED();
+}
+
+void UserMediaClientImpl::DeleteAllUserMediaRequests() {
+ UserMediaRequests::iterator request_it = user_media_requests_.begin();
+ while (request_it != user_media_requests_.end()) {
+ DVLOG(1) << "UserMediaClientImpl@" << this
+ << "::DeleteAllUserMediaRequests: "
+ << "Cancel user media request " << (*request_it)->request_id;
+ // If the request is not generated, it means that a request
+ // has been sent to the MediaStreamDispatcher to generate a stream
+ // but MediaStreamDispatcher has not yet responded and we need to cancel
+ // the request.
+ if (!(*request_it)->generated) {
+ DCHECK(!(*request_it)->HasPendingSources());
+ media_stream_dispatcher_->CancelGenerateStream(
+ (*request_it)->request_id, weak_factory_.GetWeakPtr());
+ LogUserMediaRequestWithNoResult(MEDIA_STREAM_REQUEST_NOT_GENERATED);
+ } else {
+ DCHECK((*request_it)->HasPendingSources());
+ LogUserMediaRequestWithNoResult(
+ MEDIA_STREAM_REQUEST_PENDING_MEDIA_TRACKS);
+ }
+ request_it = user_media_requests_.erase(request_it);
+ }
+}
+
+UserMediaClientImpl::MediaDevicesRequestInfo*
+UserMediaClientImpl::FindMediaDevicesRequestInfo(
+ int request_id) {
+ MediaDevicesRequests::iterator it = media_devices_requests_.begin();
+ for (; it != media_devices_requests_.end(); ++it) {
+ if ((*it)->audio_input_request_id == request_id ||
+ (*it)->video_input_request_id == request_id ||
+ (*it)->audio_output_request_id == request_id) {
+ return (*it);
+ }
+ }
+ return NULL;
+}
+
+UserMediaClientImpl::MediaDevicesRequestInfo*
+UserMediaClientImpl::FindMediaDevicesRequestInfo(
+ const blink::WebMediaDevicesRequest& request) {
+ MediaDevicesRequests::iterator it = media_devices_requests_.begin();
+ for (; it != media_devices_requests_.end(); ++it) {
+ if ((*it)->media_devices_request == request)
+ return (*it);
+ }
+ return NULL;
+}
+
+void UserMediaClientImpl::CancelAndDeleteMediaDevicesRequest(
+ MediaDevicesRequestInfo* request) {
+ MediaDevicesRequests::iterator it = media_devices_requests_.begin();
+ for (; it != media_devices_requests_.end(); ++it) {
+ if ((*it) == request) {
+ // Cancel device enumeration.
+ media_stream_dispatcher_->StopEnumerateDevices(
+ request->audio_input_request_id, weak_factory_.GetWeakPtr());
+ media_stream_dispatcher_->StopEnumerateDevices(
+ request->video_input_request_id, weak_factory_.GetWeakPtr());
+ media_stream_dispatcher_->StopEnumerateDevices(
+ request->audio_output_request_id, weak_factory_.GetWeakPtr());
+
+ media_devices_requests_.erase(it);
+ return;
+ }
+ }
+ NOTREACHED();
+}
+
+void UserMediaClientImpl::FrameWillClose() {
+ // Cancel all outstanding UserMediaRequests.
+ DeleteAllUserMediaRequests();
+
+ // Loop through all current local sources and stop the sources.
+ LocalStreamSources::iterator sources_it = local_sources_.begin();
+ while (sources_it != local_sources_.end()) {
+ StopLocalSource(*sources_it, true);
+ sources_it = local_sources_.erase(sources_it);
+ }
+}
+
+void UserMediaClientImpl::OnLocalSourceStopped(
+ const blink::WebMediaStreamSource& source) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "UserMediaClientImpl::OnLocalSourceStopped";
+
+ bool device_found = false;
+ for (LocalStreamSources::iterator device_it = local_sources_.begin();
+ device_it != local_sources_.end(); ++device_it) {
+ if (device_it->id() == source.id()) {
+ device_found = true;
+ local_sources_.erase(device_it);
+ break;
+ }
+ }
+ CHECK(device_found);
+
+ MediaStreamSource* source_impl =
+ static_cast<MediaStreamSource*>(source.extraData());
+ media_stream_dispatcher_->StopStreamDevice(source_impl->device_info());
+}
+
+void UserMediaClientImpl::StopLocalSource(
+ const blink::WebMediaStreamSource& source,
+ bool notify_dispatcher) {
+ MediaStreamSource* source_impl =
+ static_cast<MediaStreamSource*>(source.extraData());
+ DVLOG(1) << "UserMediaClientImpl::StopLocalSource("
+ << "{device_id = " << source_impl->device_info().device.id << "})";
+
+ if (notify_dispatcher)
+ media_stream_dispatcher_->StopStreamDevice(source_impl->device_info());
+
+ source_impl->ResetSourceStoppedCallback();
+ source_impl->StopSource();
+}
+
+UserMediaClientImpl::UserMediaRequestInfo::UserMediaRequestInfo(
+ int request_id,
+ const blink::WebUserMediaRequest& request,
+ bool enable_automatic_output_device_selection)
+ : request_id(request_id),
+ generated(false),
+ enable_automatic_output_device_selection(
+ enable_automatic_output_device_selection),
+ request(request),
+ request_result_(MEDIA_DEVICE_OK),
+ request_result_name_("") {
+}
+
+UserMediaClientImpl::UserMediaRequestInfo::~UserMediaRequestInfo() {
+ DVLOG(1) << "~UserMediaRequestInfo";
+}
+
+void UserMediaClientImpl::UserMediaRequestInfo::StartAudioTrack(
+ const blink::WebMediaStreamTrack& track,
+ const blink::WebMediaConstraints& constraints) {
+ DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
+ MediaStreamAudioSource* native_source =
+ static_cast <MediaStreamAudioSource*>(track.source().extraData());
+ DCHECK(native_source);
+
+ sources_.push_back(track.source());
+ sources_waiting_for_callback_.push_back(native_source);
+ native_source->AddTrack(
+ track, constraints, base::Bind(
+ &UserMediaClientImpl::UserMediaRequestInfo::OnTrackStarted,
+ AsWeakPtr()));
+}
+
+blink::WebMediaStreamTrack
+UserMediaClientImpl::UserMediaRequestInfo::CreateAndStartVideoTrack(
+ const blink::WebMediaStreamSource& source,
+ const blink::WebMediaConstraints& constraints) {
+ DCHECK(source.type() == blink::WebMediaStreamSource::TypeVideo);
+ MediaStreamVideoSource* native_source =
+ MediaStreamVideoSource::GetVideoSource(source);
+ DCHECK(native_source);
+ sources_.push_back(source);
+ sources_waiting_for_callback_.push_back(native_source);
+ return MediaStreamVideoTrack::CreateVideoTrack(
+ native_source, constraints, base::Bind(
+ &UserMediaClientImpl::UserMediaRequestInfo::OnTrackStarted,
+ AsWeakPtr()),
+ true);
+}
+
+void UserMediaClientImpl::UserMediaRequestInfo::CallbackOnTracksStarted(
+ const ResourcesReady& callback) {
+ DCHECK(ready_callback_.is_null());
+ ready_callback_ = callback;
+ CheckAllTracksStarted();
+}
+
+void UserMediaClientImpl::UserMediaRequestInfo::OnTrackStarted(
+ MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
+ DVLOG(1) << "OnTrackStarted result " << result;
+ std::vector<MediaStreamSource*>::iterator it =
+ std::find(sources_waiting_for_callback_.begin(),
+ sources_waiting_for_callback_.end(),
+ source);
+ DCHECK(it != sources_waiting_for_callback_.end());
+ sources_waiting_for_callback_.erase(it);
+ // All tracks must be started successfully. Otherwise the request is a
+ // failure.
+ if (result != MEDIA_DEVICE_OK) {
+ request_result_ = result;
+ request_result_name_ = result_name;
+ }
+
+ CheckAllTracksStarted();
+}
+
+void UserMediaClientImpl::UserMediaRequestInfo::CheckAllTracksStarted() {
+ if (!ready_callback_.is_null() && sources_waiting_for_callback_.empty()) {
+ ready_callback_.Run(this, request_result_, request_result_name_);
+ }
+}
+
+bool UserMediaClientImpl::UserMediaRequestInfo::IsSourceUsed(
+ const blink::WebMediaStreamSource& source) const {
+ for (std::vector<blink::WebMediaStreamSource>::const_iterator source_it =
+ sources_.begin();
+ source_it != sources_.end(); ++source_it) {
+ if (source_it->id() == source.id())
+ return true;
+ }
+ return false;
+}
+
+void UserMediaClientImpl::UserMediaRequestInfo::RemoveSource(
+ const blink::WebMediaStreamSource& source) {
+ for (std::vector<blink::WebMediaStreamSource>::iterator it =
+ sources_.begin();
+ it != sources_.end(); ++it) {
+ if (source.id() == it->id()) {
+ sources_.erase(it);
+ return;
+ }
+ }
+}
+
+bool UserMediaClientImpl::UserMediaRequestInfo::HasPendingSources() const {
+ return !sources_waiting_for_callback_.empty();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/user_media_client_impl.h b/chromium/content/renderer/media/user_media_client_impl.h
new file mode 100644
index 00000000000..9ec1e7367dd
--- /dev/null
+++ b/chromium/content/renderer/media/user_media_client_impl.h
@@ -0,0 +1,258 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
+#include "content/renderer/media/media_stream_source.h"
+#include "third_party/WebKit/public/platform/WebMediaStream.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/WebKit/public/platform/WebSourceInfo.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/web/WebMediaDevicesRequest.h"
+#include "third_party/WebKit/public/web/WebUserMediaClient.h"
+#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+namespace content {
+class PeerConnectionDependencyFactory;
+class MediaStreamDispatcher;
+class MediaStreamVideoSource;
+class VideoCapturerDelegate;
+
+// UserMediaClientImpl is a delegate for the Media Stream GetUserMedia API.
+// It ties together WebKit and MediaStreamManager
+// (via MediaStreamDispatcher and MediaStreamDispatcherHost)
+// in the browser process. It must be created, called and destroyed on the
+// render thread.
+class CONTENT_EXPORT UserMediaClientImpl
+ : public RenderFrameObserver,
+ NON_EXPORTED_BASE(public blink::WebUserMediaClient),
+ public MediaStreamDispatcherEventHandler,
+ NON_EXPORTED_BASE(public base::NonThreadSafe) {
+ public:
+ // |render_frame| and |dependency_factory| must outlive this instance.
+ UserMediaClientImpl(
+ RenderFrame* render_frame,
+ PeerConnectionDependencyFactory* dependency_factory,
+ scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher);
+ virtual ~UserMediaClientImpl();
+
+ MediaStreamDispatcher* media_stream_dispatcher() const {
+ return media_stream_dispatcher_.get();
+ }
+
+ // blink::WebUserMediaClient implementation
+ virtual void requestUserMedia(
+ const blink::WebUserMediaRequest& user_media_request);
+ virtual void cancelUserMediaRequest(
+ const blink::WebUserMediaRequest& user_media_request);
+ virtual void requestMediaDevices(
+ const blink::WebMediaDevicesRequest& media_devices_request) override;
+ virtual void cancelMediaDevicesRequest(
+ const blink::WebMediaDevicesRequest& media_devices_request) override;
+ virtual void requestSources(
+ const blink::WebMediaStreamTrackSourcesRequest& sources_request) override;
+
+ // MediaStreamDispatcherEventHandler implementation.
+ void OnStreamGenerated(int request_id,
+ const std::string& label,
+ const StreamDeviceInfoArray& audio_array,
+ const StreamDeviceInfoArray& video_array) override;
+ void OnStreamGenerationFailed(int request_id,
+ MediaStreamRequestResult result) override;
+ void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) override;
+ void OnDevicesEnumerated(int request_id,
+ const StreamDeviceInfoArray& device_array) override;
+ void OnDeviceOpened(int request_id,
+ const std::string& label,
+ const StreamDeviceInfo& device_info) override;
+ void OnDeviceOpenFailed(int request_id) override;
+
+ // RenderFrameObserver override
+ void FrameWillClose() override;
+
+ protected:
+ // Called when |source| has been stopped from JavaScript.
+ void OnLocalSourceStopped(const blink::WebMediaStreamSource& source);
+
+ // These methods are virtual for test purposes. A test can override them to
+ // test requesting local media streams. The function notifies WebKit that the
+ // |request| have completed.
+ virtual void GetUserMediaRequestSucceeded(
+ const blink::WebMediaStream& stream,
+ blink::WebUserMediaRequest* request_info);
+ virtual void GetUserMediaRequestFailed(
+ blink::WebUserMediaRequest* request_info,
+ MediaStreamRequestResult result);
+ virtual void GetUserMediaRequestTrackStartedFailed(
+ blink::WebUserMediaRequest* request_info,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name);
+ virtual void EnumerateDevicesSucceded(
+ blink::WebMediaDevicesRequest* request,
+ blink::WebVector<blink::WebMediaDeviceInfo>& devices);
+ virtual void EnumerateSourcesSucceded(
+ blink::WebMediaStreamTrackSourcesRequest* request,
+ blink::WebVector<blink::WebSourceInfo>& sources);
+ // Creates a MediaStreamVideoSource object.
+ // This is virtual for test purposes.
+ virtual MediaStreamVideoSource* CreateVideoSource(
+ const StreamDeviceInfo& device,
+ const MediaStreamSource::SourceStoppedCallback& stop_callback);
+
+ private:
+ // Class for storing information about a WebKit request to create a
+ // MediaStream.
+ class UserMediaRequestInfo
+ : public base::SupportsWeakPtr<UserMediaRequestInfo> {
+ public:
+ typedef base::Callback<void(UserMediaRequestInfo* request_info,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name)>
+ ResourcesReady;
+
+ UserMediaRequestInfo(int request_id,
+ const blink::WebUserMediaRequest& request,
+ bool enable_automatic_output_device_selection);
+ ~UserMediaRequestInfo();
+ int request_id;
+ // True if MediaStreamDispatcher has generated the stream, see
+ // OnStreamGenerated.
+ bool generated;
+ const bool enable_automatic_output_device_selection;
+ blink::WebMediaStream web_stream;
+ blink::WebUserMediaRequest request;
+
+ void StartAudioTrack(const blink::WebMediaStreamTrack& track,
+ const blink::WebMediaConstraints& constraints);
+
+ blink::WebMediaStreamTrack CreateAndStartVideoTrack(
+ const blink::WebMediaStreamSource& source,
+ const blink::WebMediaConstraints& constraints);
+
+ // Triggers |callback| when all sources used in this request have either
+ // successfully started, or a source has failed to start.
+ void CallbackOnTracksStarted(const ResourcesReady& callback);
+
+ bool IsSourceUsed(const blink::WebMediaStreamSource& source) const;
+ void RemoveSource(const blink::WebMediaStreamSource& source);
+
+ bool HasPendingSources() const;
+
+ private:
+ void OnTrackStarted(
+ MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name);
+ void CheckAllTracksStarted();
+
+ ResourcesReady ready_callback_;
+ MediaStreamRequestResult request_result_;
+ blink::WebString request_result_name_;
+ // Sources used in this request.
+ std::vector<blink::WebMediaStreamSource> sources_;
+ std::vector<MediaStreamSource*> sources_waiting_for_callback_;
+ };
+ typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests;
+
+ typedef std::vector<blink::WebMediaStreamSource> LocalStreamSources;
+
+ struct MediaDevicesRequestInfo;
+ typedef ScopedVector<MediaDevicesRequestInfo> MediaDevicesRequests;
+
+ // Creates a WebKit representation of stream sources based on
+ // |devices| from the MediaStreamDispatcher.
+ void InitializeSourceObject(
+ const StreamDeviceInfo& device,
+ blink::WebMediaStreamSource::Type type,
+ const blink::WebMediaConstraints& constraints,
+ blink::WebMediaStreamSource* webkit_source);
+
+ void CreateVideoTracks(
+ const StreamDeviceInfoArray& devices,
+ const blink::WebMediaConstraints& constraints,
+ blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
+ UserMediaRequestInfo* request);
+
+ void CreateAudioTracks(
+ const StreamDeviceInfoArray& devices,
+ const blink::WebMediaConstraints& constraints,
+ blink::WebVector<blink::WebMediaStreamTrack>* webkit_tracks,
+ UserMediaRequestInfo* request);
+
+ // Callback function triggered when all native versions of the
+ // underlying media sources and tracks have been created and started.
+ void OnCreateNativeTracksCompleted(
+ UserMediaRequestInfo* request,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name);
+
+ void OnStreamGeneratedForCancelledRequest(
+ const StreamDeviceInfoArray& audio_array,
+ const StreamDeviceInfoArray& video_array);
+
+ void FinalizeEnumerateDevices(MediaDevicesRequestInfo* request);
+ void FinalizeEnumerateSources(MediaDevicesRequestInfo* request);
+
+ UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id);
+ UserMediaRequestInfo* FindUserMediaRequestInfo(
+ const blink::WebUserMediaRequest& request);
+ void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request);
+ void DeleteAllUserMediaRequests();
+
+ MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(int request_id);
+ MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(
+ const blink::WebMediaDevicesRequest& request);
+ void CancelAndDeleteMediaDevicesRequest(MediaDevicesRequestInfo* request);
+
+ // Returns the source that use a device with |device.session_id|
+ // and |device.device.id|. NULL if such source doesn't exist.
+ const blink::WebMediaStreamSource* FindLocalSource(
+ const StreamDeviceInfo& device) const;
+
+ void StopLocalSource(const blink::WebMediaStreamSource& source,
+ bool notify_dispatcher);
+
+ // Weak ref to a PeerConnectionDependencyFactory, owned by the RenderThread.
+ // It's valid for the lifetime of RenderThread.
+ // TODO(xians): Remove this dependency once audio do not need it for local
+ // audio.
+ PeerConnectionDependencyFactory* const dependency_factory_;
+
+ // UserMediaClientImpl owns MediaStreamDispatcher instead of RenderFrameImpl
+ // (or RenderFrameObserver) to ensure tear-down occurs in the right order.
+ const scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher_;
+
+ LocalStreamSources local_sources_;
+
+ UserMediaRequests user_media_requests_;
+
+ // Requests to enumerate media devices.
+ MediaDevicesRequests media_devices_requests_;
+
+ // Note: This member must be the last to ensure all outstanding weak pointers
+ // are invalidated first.
+ base::WeakPtrFactory<UserMediaClientImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserMediaClientImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
diff --git a/chromium/content/renderer/media/user_media_client_impl_unittest.cc b/chromium/content/renderer/media/user_media_client_impl_unittest.cc
new file mode 100644
index 00000000000..35c41a064cd
--- /dev/null
+++ b/chromium/content/renderer/media/user_media_client_impl_unittest.cc
@@ -0,0 +1,580 @@
+// Copyright (c) 2012 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/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/child/child_process.h"
+#include "content/renderer/media/media_stream.h"
+#include "content/renderer/media/media_stream_track.h"
+#include "content/renderer/media/mock_media_stream_dispatcher.h"
+#include "content/renderer/media/mock_media_stream_video_source.h"
+#include "content/renderer/media/user_media_client_impl.h"
+#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
+#include "third_party/WebKit/public/platform/WebMediaStream.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
+
+namespace content {
+
+class MockMediaStreamVideoCapturerSource : public MockMediaStreamVideoSource {
+ public:
+ MockMediaStreamVideoCapturerSource(
+ const StreamDeviceInfo& device,
+ const SourceStoppedCallback& stop_callback,
+ PeerConnectionDependencyFactory* factory)
+ : MockMediaStreamVideoSource(false) {
+ SetDeviceInfo(device);
+ SetStopCallback(stop_callback);
+ }
+};
+
+class UserMediaClientImplUnderTest : public UserMediaClientImpl {
+ public:
+ enum RequestState {
+ REQUEST_NOT_STARTED,
+ REQUEST_NOT_COMPLETE,
+ REQUEST_SUCCEEDED,
+ REQUEST_FAILED,
+ };
+
+ UserMediaClientImplUnderTest(
+ PeerConnectionDependencyFactory* dependency_factory,
+ scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher)
+ : UserMediaClientImpl(
+ NULL, dependency_factory, media_stream_dispatcher.Pass()),
+ state_(REQUEST_NOT_STARTED),
+ result_(NUM_MEDIA_REQUEST_RESULTS),
+ result_name_(""),
+ factory_(dependency_factory),
+ video_source_(NULL) {
+ }
+
+ void RequestUserMedia() {
+ blink::WebUserMediaRequest user_media_request;
+ state_ = REQUEST_NOT_COMPLETE;
+ requestUserMedia(user_media_request);
+ }
+
+ void RequestMediaDevices() {
+ blink::WebMediaDevicesRequest media_devices_request;
+ state_ = REQUEST_NOT_COMPLETE;
+ requestMediaDevices(media_devices_request);
+ }
+
+ void RequestSources() {
+ blink::WebMediaStreamTrackSourcesRequest sources_request;
+ state_ = REQUEST_NOT_COMPLETE;
+ requestSources(sources_request);
+ }
+
+ void GetUserMediaRequestSucceeded(
+ const blink::WebMediaStream& stream,
+ blink::WebUserMediaRequest* request_info) override {
+ last_generated_stream_ = stream;
+ state_ = REQUEST_SUCCEEDED;
+ }
+
+ void GetUserMediaRequestFailed(
+ blink::WebUserMediaRequest* request_info,
+ content::MediaStreamRequestResult result) override {
+ last_generated_stream_.reset();
+ state_ = REQUEST_FAILED;
+ result_ = result;
+ }
+
+ void GetUserMediaRequestTrackStartedFailed(
+ blink::WebUserMediaRequest* request_info,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) override {
+ last_generated_stream_.reset();
+ state_ = REQUEST_FAILED;
+ result_ = result;
+ result_name_ = result_name;
+ }
+
+ void EnumerateDevicesSucceded(
+ blink::WebMediaDevicesRequest* request,
+ blink::WebVector<blink::WebMediaDeviceInfo>& devices) override {
+ state_ = REQUEST_SUCCEEDED;
+ last_devices_ = devices;
+ }
+
+ void EnumerateSourcesSucceded(
+ blink::WebMediaStreamTrackSourcesRequest* request,
+ blink::WebVector<blink::WebSourceInfo>& sources) override {
+ state_ = REQUEST_SUCCEEDED;
+ last_sources_ = sources;
+ }
+
+ MediaStreamVideoSource* CreateVideoSource(
+ const StreamDeviceInfo& device,
+ const MediaStreamSource::SourceStoppedCallback& stop_callback) override {
+ video_source_ = new MockMediaStreamVideoCapturerSource(device,
+ stop_callback,
+ factory_);
+ return video_source_;
+ }
+
+ const blink::WebMediaStream& last_generated_stream() {
+ return last_generated_stream_;
+ }
+
+ const blink::WebVector<blink::WebMediaDeviceInfo>& last_devices() {
+ return last_devices_;
+ }
+
+ const blink::WebVector<blink::WebSourceInfo>& last_sources() {
+ return last_sources_;
+ }
+
+ void ClearLastGeneratedStream() {
+ last_generated_stream_.reset();
+ }
+
+ MockMediaStreamVideoCapturerSource* last_created_video_source() const {
+ return video_source_;
+ }
+
+ RequestState request_state() const { return state_; }
+ content::MediaStreamRequestResult error_reason() const { return result_; }
+ blink::WebString error_name() const { return result_name_; }
+
+ private:
+ blink::WebMediaStream last_generated_stream_;
+ RequestState state_;
+ content::MediaStreamRequestResult result_;
+ blink::WebString result_name_;
+ blink::WebVector<blink::WebMediaDeviceInfo> last_devices_;
+ blink::WebVector<blink::WebSourceInfo> last_sources_;
+ PeerConnectionDependencyFactory* factory_;
+ MockMediaStreamVideoCapturerSource* video_source_;
+};
+
+class UserMediaClientImplTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ // Create our test object.
+ child_process_.reset(new ChildProcess());
+ dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
+ ms_dispatcher_ = new MockMediaStreamDispatcher();
+ used_media_impl_.reset(new UserMediaClientImplUnderTest(
+ dependency_factory_.get(),
+ scoped_ptr<MediaStreamDispatcher>(ms_dispatcher_).Pass()));
+ }
+
+ void TearDown() override {
+ used_media_impl_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
+ blink::WebMediaStream RequestLocalMediaStream() {
+ used_media_impl_->RequestUserMedia();
+ FakeMediaStreamDispatcherRequestUserMediaComplete();
+ StartMockedVideoSource();
+
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_SUCCEEDED,
+ used_media_impl_->request_state());
+
+ blink::WebMediaStream desc = used_media_impl_->last_generated_stream();
+ content::MediaStream* native_stream =
+ content::MediaStream::GetMediaStream(desc);
+ if (!native_stream) {
+ ADD_FAILURE();
+ return desc;
+ }
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ desc.audioTracks(audio_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ desc.videoTracks(video_tracks);
+
+ EXPECT_EQ(1u, audio_tracks.size());
+ EXPECT_EQ(1u, video_tracks.size());
+ EXPECT_NE(audio_tracks[0].id(), video_tracks[0].id());
+ return desc;
+ }
+
+ void FakeMediaStreamDispatcherRequestUserMediaComplete() {
+ // Audio request ID is used as the shared request ID.
+ used_media_impl_->OnStreamGenerated(
+ ms_dispatcher_->audio_input_request_id(),
+ ms_dispatcher_->stream_label(),
+ ms_dispatcher_->audio_input_array(),
+ ms_dispatcher_->video_array());
+ }
+
+ void FakeMediaStreamDispatcherRequestMediaDevicesComplete() {
+ used_media_impl_->OnDevicesEnumerated(
+ ms_dispatcher_->audio_input_request_id(),
+ ms_dispatcher_->audio_input_array());
+ used_media_impl_->OnDevicesEnumerated(
+ ms_dispatcher_->audio_output_request_id(),
+ ms_dispatcher_->audio_output_array());
+ used_media_impl_->OnDevicesEnumerated(
+ ms_dispatcher_->video_request_id(),
+ ms_dispatcher_->video_array());
+ }
+
+ void FakeMediaStreamDispatcherRequestSourcesComplete() {
+ used_media_impl_->OnDevicesEnumerated(
+ ms_dispatcher_->audio_input_request_id(),
+ ms_dispatcher_->audio_input_array());
+ used_media_impl_->OnDevicesEnumerated(
+ ms_dispatcher_->video_request_id(),
+ ms_dispatcher_->video_array());
+ }
+
+ void StartMockedVideoSource() {
+ MockMediaStreamVideoCapturerSource* video_source =
+ used_media_impl_->last_created_video_source();
+ if (video_source->SourceHasAttemptedToStart())
+ video_source->StartMockedSource();
+ }
+
+ void FailToStartMockedVideoSource() {
+ MockMediaStreamVideoCapturerSource* video_source =
+ used_media_impl_->last_created_video_source();
+ if (video_source->SourceHasAttemptedToStart())
+ video_source->FailToStartMockedSource();
+ blink::WebHeap::collectGarbageForTesting();
+ }
+
+ void FailToCreateNextAudioCapturer() {
+ dependency_factory_->FailToCreateNextAudioCapturer();
+ blink::WebHeap::collectGarbageForTesting();
+ }
+
+ protected:
+ base::MessageLoop message_loop_;
+ scoped_ptr<ChildProcess> child_process_;
+ MockMediaStreamDispatcher* ms_dispatcher_; // Owned by |used_media_impl_|.
+ scoped_ptr<UserMediaClientImplUnderTest> used_media_impl_;
+ scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
+};
+
+TEST_F(UserMediaClientImplTest, GenerateMediaStream) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
+}
+
+// Test that the same source object is used if two MediaStreams are generated
+// using the same source.
+TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithSameSource) {
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
+ desc1.videoTracks(desc1_video_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
+ desc2.videoTracks(desc2_video_tracks);
+ EXPECT_EQ(desc1_video_tracks[0].source().id(),
+ desc2_video_tracks[0].source().id());
+
+ EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
+ desc2_video_tracks[0].source().extraData());
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
+ desc1.audioTracks(desc1_audio_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
+ desc2.audioTracks(desc2_audio_tracks);
+ EXPECT_EQ(desc1_audio_tracks[0].source().id(),
+ desc2_audio_tracks[0].source().id());
+
+ EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
+ desc2_audio_tracks[0].source().extraData());
+}
+
+// Test that the same source object is not used if two MediaStreams are
+// generated using different sources.
+TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ // Make sure another device is selected (another |session_id|) in the next
+ // gUM request.
+ ms_dispatcher_->IncrementSessionId();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks;
+ desc1.videoTracks(desc1_video_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks;
+ desc2.videoTracks(desc2_video_tracks);
+ EXPECT_NE(desc1_video_tracks[0].source().id(),
+ desc2_video_tracks[0].source().id());
+
+ EXPECT_NE(desc1_video_tracks[0].source().extraData(),
+ desc2_video_tracks[0].source().extraData());
+
+ blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
+ desc1.audioTracks(desc1_audio_tracks);
+ blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks;
+ desc2.audioTracks(desc2_audio_tracks);
+ EXPECT_NE(desc1_audio_tracks[0].source().id(),
+ desc2_audio_tracks[0].source().id());
+
+ EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
+ desc2_audio_tracks[0].source().extraData());
+}
+
+TEST_F(UserMediaClientImplTest, StopLocalTracks) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ mixed_desc.audioTracks(audio_tracks);
+ MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
+ audio_track->Stop();
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ mixed_desc.videoTracks(video_tracks);
+ MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
+ video_track->Stop();
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// This test that a source is not stopped even if the tracks in a
+// MediaStream is stopped if there are two MediaStreams with tracks using the
+// same device. The source is stopped
+// if there are no more MediaStream tracks using the device.
+TEST_F(UserMediaClientImplTest, StopLocalTracksWhenTwoStreamUseSameDevices) {
+ // Generate a stream with both audio and video.
+ blink::WebMediaStream desc1 = RequestLocalMediaStream();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1;
+ desc1.audioTracks(audio_tracks1);
+ MediaStreamTrack* audio_track1 = MediaStreamTrack::GetTrack(audio_tracks1[0]);
+ audio_track1->Stop();
+ EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2;
+ desc2.audioTracks(audio_tracks2);
+ MediaStreamTrack* audio_track2 = MediaStreamTrack::GetTrack(audio_tracks2[0]);
+ audio_track2->Stop();
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks1;
+ desc1.videoTracks(video_tracks1);
+ MediaStreamTrack* video_track1 = MediaStreamTrack::GetTrack(video_tracks1[0]);
+ video_track1->Stop();
+ EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks2;
+ desc2.videoTracks(video_tracks2);
+ MediaStreamTrack* video_track2 = MediaStreamTrack::GetTrack(video_tracks2[0]);
+ video_track2->Stop();
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+TEST_F(UserMediaClientImplTest, StopSourceWhenMediaStreamGoesOutOfScope) {
+ // Generate a stream with both audio and video.
+ RequestLocalMediaStream();
+ // Makes sure the test itself don't hold a reference to the created
+ // MediaStream.
+ used_media_impl_->ClearLastGeneratedStream();
+ blink::WebHeap::collectGarbageForTesting();
+
+ // Expect the sources to be stopped when the MediaStream goes out of scope.
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// Test that the MediaStreams are deleted if the owning WebFrame is closing.
+// In the unit test the owning frame is NULL.
+TEST_F(UserMediaClientImplTest, FrameWillClose) {
+ // Test a stream with both audio and video.
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
+ blink::WebMediaStream desc2 = RequestLocalMediaStream();
+ used_media_impl_->FrameWillClose();
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// This test what happens if a video source to a MediaSteam fails to start.
+TEST_F(UserMediaClientImplTest, MediaVideoSourceFailToStart) {
+ used_media_impl_->RequestUserMedia();
+ FakeMediaStreamDispatcherRequestUserMediaComplete();
+ FailToStartMockedVideoSource();
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_FAILED,
+ used_media_impl_->request_state());
+ EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
+ used_media_impl_->error_reason());
+ blink::WebHeap::collectGarbageForTesting();
+ EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// This test what happens if an audio source fail to initialize.
+TEST_F(UserMediaClientImplTest, MediaAudioSourceFailToInitialize) {
+ FailToCreateNextAudioCapturer();
+ used_media_impl_->RequestUserMedia();
+ FakeMediaStreamDispatcherRequestUserMediaComplete();
+ StartMockedVideoSource();
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_FAILED,
+ used_media_impl_->request_state());
+ EXPECT_EQ(MEDIA_DEVICE_TRACK_START_FAILURE,
+ used_media_impl_->error_reason());
+ blink::WebHeap::collectGarbageForTesting();
+ EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+// This test what happens if UserMediaClientImpl is deleted before a source has
+// started.
+TEST_F(UserMediaClientImplTest, MediaStreamImplShutDown) {
+ used_media_impl_->RequestUserMedia();
+ FakeMediaStreamDispatcherRequestUserMediaComplete();
+ EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_NOT_COMPLETE,
+ used_media_impl_->request_state());
+ used_media_impl_.reset();
+}
+
+// This test what happens if the WebFrame is closed while the MediaStream is
+// being generated by the MediaStreamDispatcher.
+TEST_F(UserMediaClientImplTest, ReloadFrameWhileGeneratingStream) {
+ used_media_impl_->RequestUserMedia();
+ used_media_impl_->FrameWillClose();
+ EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
+ EXPECT_EQ(0, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(0, ms_dispatcher_->stop_video_device_counter());
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_NOT_COMPLETE,
+ used_media_impl_->request_state());
+}
+
+// This test what happens if the WebFrame is closed while the sources are being
+// started.
+TEST_F(UserMediaClientImplTest, ReloadFrameWhileGeneratingSources) {
+ used_media_impl_->RequestUserMedia();
+ FakeMediaStreamDispatcherRequestUserMediaComplete();
+ EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
+ used_media_impl_->FrameWillClose();
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_NOT_COMPLETE,
+ used_media_impl_->request_state());
+}
+
+// This test what happens if stop is called on a track after the frame has
+// been reloaded.
+TEST_F(UserMediaClientImplTest, StopTrackAfterReload) {
+ blink::WebMediaStream mixed_desc = RequestLocalMediaStream();
+ EXPECT_EQ(1, ms_dispatcher_->request_stream_counter());
+ used_media_impl_->FrameWillClose();
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+
+ blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
+ mixed_desc.audioTracks(audio_tracks);
+ MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]);
+ audio_track->Stop();
+ EXPECT_EQ(1, ms_dispatcher_->stop_audio_device_counter());
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
+ mixed_desc.videoTracks(video_tracks);
+ MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]);
+ video_track->Stop();
+ EXPECT_EQ(1, ms_dispatcher_->stop_video_device_counter());
+}
+
+TEST_F(UserMediaClientImplTest, EnumerateMediaDevices) {
+ used_media_impl_->RequestMediaDevices();
+ FakeMediaStreamDispatcherRequestMediaDevicesComplete();
+
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_SUCCEEDED,
+ used_media_impl_->request_state());
+ EXPECT_EQ(static_cast<size_t>(5), used_media_impl_->last_devices().size());
+
+ // Audio input device with matched output ID.
+ const blink::WebMediaDeviceInfo* device =
+ &used_media_impl_->last_devices()[0];
+ EXPECT_FALSE(device->deviceId().isEmpty());
+ EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
+ device->kind());
+ EXPECT_FALSE(device->label().isEmpty());
+ EXPECT_FALSE(device->groupId().isEmpty());
+
+ // Audio input device without matched output ID.
+ device = &used_media_impl_->last_devices()[1];
+ EXPECT_FALSE(device->deviceId().isEmpty());
+ EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput,
+ device->kind());
+ EXPECT_FALSE(device->label().isEmpty());
+ EXPECT_FALSE(device->groupId().isEmpty());
+
+ // Video input devices.
+ device = &used_media_impl_->last_devices()[2];
+ EXPECT_FALSE(device->deviceId().isEmpty());
+ EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
+ device->kind());
+ EXPECT_FALSE(device->label().isEmpty());
+ EXPECT_TRUE(device->groupId().isEmpty());
+
+ device = &used_media_impl_->last_devices()[3];
+ EXPECT_FALSE(device->deviceId().isEmpty());
+ EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindVideoInput,
+ device->kind());
+ EXPECT_FALSE(device->label().isEmpty());
+ EXPECT_TRUE(device->groupId().isEmpty());
+
+ // Audio output device.
+ device = &used_media_impl_->last_devices()[4];
+ EXPECT_FALSE(device->deviceId().isEmpty());
+ EXPECT_EQ(blink::WebMediaDeviceInfo::MediaDeviceKindAudioOutput,
+ device->kind());
+ EXPECT_FALSE(device->label().isEmpty());
+ EXPECT_FALSE(device->groupId().isEmpty());
+
+ // Verfify group IDs.
+ EXPECT_TRUE(used_media_impl_->last_devices()[0].groupId().equals(
+ used_media_impl_->last_devices()[4].groupId()));
+ EXPECT_FALSE(used_media_impl_->last_devices()[1].groupId().equals(
+ used_media_impl_->last_devices()[4].groupId()));
+}
+
+TEST_F(UserMediaClientImplTest, EnumerateSources) {
+ used_media_impl_->RequestSources();
+ FakeMediaStreamDispatcherRequestSourcesComplete();
+
+ EXPECT_EQ(UserMediaClientImplUnderTest::REQUEST_SUCCEEDED,
+ used_media_impl_->request_state());
+ EXPECT_EQ(static_cast<size_t>(4), used_media_impl_->last_sources().size());
+
+ // Audio input devices.
+ const blink::WebSourceInfo* source = &used_media_impl_->last_sources()[0];
+ EXPECT_FALSE(source->id().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::SourceKindAudio, source->kind());
+ EXPECT_FALSE(source->label().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeNone, source->facing());
+
+ source = &used_media_impl_->last_sources()[1];
+ EXPECT_FALSE(source->id().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::SourceKindAudio, source->kind());
+ EXPECT_FALSE(source->label().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeNone, source->facing());
+
+ // Video input device user facing.
+ source = &used_media_impl_->last_sources()[2];
+ EXPECT_FALSE(source->id().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::SourceKindVideo, source->kind());
+ EXPECT_FALSE(source->label().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeUser, source->facing());
+
+ // Video input device environment facing.
+ source = &used_media_impl_->last_sources()[3];
+ EXPECT_FALSE(source->id().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::SourceKindVideo, source->kind());
+ EXPECT_FALSE(source->label().isEmpty());
+ EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeEnvironment, source->facing());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc
index a9d6240ea1c..9688b464680 100644
--- a/chromium/content/renderer/media/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture_impl.cc
@@ -73,7 +73,10 @@ void VideoCaptureImpl::DeInit() {
void VideoCaptureImpl::SuspendCapture(bool suspend) {
DCHECK(thread_checker_.CalledOnValidThread());
- suspended_ = suspend;
+ Send(suspend ?
+ static_cast<IPC::Message*>(new VideoCaptureHostMsg_Pause(device_id_)) :
+ static_cast<IPC::Message*>(
+ new VideoCaptureHostMsg_Resume(device_id_, session_id_, params_)));
}
void VideoCaptureImpl::StartCapture(
@@ -103,8 +106,8 @@ void VideoCaptureImpl::StartCapture(
clients_[client_id] = client_info;
// TODO(sheu): Allowing resolution change will require that all
// outstanding clients of a capture session support resolution change.
- DCHECK_EQ(params_.allow_resolution_change,
- params.allow_resolution_change);
+ DCHECK_EQ(params_.resolution_change_policy,
+ params.resolution_change_policy);
} else if (state_ == VIDEO_CAPTURE_STATE_STOPPING) {
clients_pending_on_restart_[client_id] = client_info;
DVLOG(1) << "StartCapture: Got new resolution "
@@ -199,13 +202,14 @@ void VideoCaptureImpl::OnBufferDestroyed(int buffer_id) {
if (iter == client_buffers_.end())
return;
- DCHECK(!iter->second || iter->second->HasOneRef())
+ DCHECK(!iter->second.get() || iter->second->HasOneRef())
<< "Instructed to delete buffer we are still using.";
client_buffers_.erase(iter);
}
void VideoCaptureImpl::OnBufferReceived(int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -213,8 +217,7 @@ void VideoCaptureImpl::OnBufferReceived(int buffer_id,
DCHECK_EQ(format.pixel_format, media::PIXEL_FORMAT_I420);
if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
- Send(new VideoCaptureHostMsg_BufferReady(
- device_id_, buffer_id, std::vector<uint32>()));
+ Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0));
return;
}
@@ -236,8 +239,8 @@ void VideoCaptureImpl::OnBufferReceived(int buffer_id,
media::VideoFrame::WrapExternalPackedMemory(
media::VideoFrame::I420,
last_frame_format_.frame_size,
- gfx::Rect(last_frame_format_.frame_size),
- last_frame_format_.frame_size,
+ visible_rect,
+ gfx::Size(visible_rect.width(), visible_rect.height()),
reinterpret_cast<uint8*>(buffer->buffer->memory()),
buffer->buffer_size,
buffer->buffer->handle(),
@@ -247,7 +250,7 @@ void VideoCaptureImpl::OnBufferReceived(int buffer_id,
weak_factory_.GetWeakPtr(),
buffer_id,
buffer,
- std::vector<uint32>())));
+ 0)));
for (ClientInfoMap::iterator it = clients_.begin(); it != clients_.end();
++it) {
@@ -265,8 +268,7 @@ void VideoCaptureImpl::OnMailboxBufferReceived(
DCHECK(thread_checker_.CalledOnValidThread());
if (state_ != VIDEO_CAPTURE_STATE_STARTED || suspended_) {
- Send(new VideoCaptureHostMsg_BufferReady(
- device_id_, buffer_id, std::vector<uint32>()));
+ Send(new VideoCaptureHostMsg_BufferReady(device_id_, buffer_id, 0));
return;
}
@@ -296,10 +298,10 @@ void VideoCaptureImpl::OnMailboxBufferReceived(
void VideoCaptureImpl::OnClientBufferFinished(
int buffer_id,
const scoped_refptr<ClientBuffer>& /* ignored_buffer */,
- const std::vector<uint32>& release_sync_points) {
+ uint32 release_sync_point) {
DCHECK(thread_checker_.CalledOnValidThread());
Send(new VideoCaptureHostMsg_BufferReady(
- device_id_, buffer_id, release_sync_points));
+ device_id_, buffer_id, release_sync_point));
}
void VideoCaptureImpl::OnStateChanged(VideoCaptureState state) {
diff --git a/chromium/content/renderer/media/video_capture_impl.h b/chromium/content/renderer/media/video_capture_impl.h
index 160f0bf95c8..4b39d549d02 100644
--- a/chromium/content/renderer/media/video_capture_impl.h
+++ b/chromium/content/renderer/media/video_capture_impl.h
@@ -48,7 +48,7 @@ namespace content {
class CONTENT_EXPORT VideoCaptureImpl
: public VideoCaptureMessageFilter::Delegate {
public:
- virtual ~VideoCaptureImpl();
+ ~VideoCaptureImpl() override;
VideoCaptureImpl(media::VideoCaptureSessionId session_id,
VideoCaptureMessageFilter* filter);
@@ -108,29 +108,30 @@ class CONTENT_EXPORT VideoCaptureImpl
typedef std::map<int, ClientInfo> ClientInfoMap;
// VideoCaptureMessageFilter::Delegate interface.
- virtual void OnBufferCreated(base::SharedMemoryHandle handle,
- int length,
- int buffer_id) OVERRIDE;
- virtual void OnBufferDestroyed(int buffer_id) OVERRIDE;
- virtual void OnBufferReceived(int buffer_id,
- const media::VideoCaptureFormat& format,
- base::TimeTicks) OVERRIDE;
- virtual void OnMailboxBufferReceived(int buffer_id,
- const gpu::MailboxHolder& mailbox_holder,
- const media::VideoCaptureFormat& format,
- base::TimeTicks timestamp) OVERRIDE;
- virtual void OnStateChanged(VideoCaptureState state) OVERRIDE;
- virtual void OnDeviceSupportedFormatsEnumerated(
- const media::VideoCaptureFormats& supported_formats) OVERRIDE;
- virtual void OnDeviceFormatsInUseReceived(
- const media::VideoCaptureFormats& formats_in_use) OVERRIDE;
- virtual void OnDelegateAdded(int32 device_id) OVERRIDE;
+ void OnBufferCreated(base::SharedMemoryHandle handle,
+ int length,
+ int buffer_id) override;
+ void OnBufferDestroyed(int buffer_id) override;
+ void OnBufferReceived(int buffer_id,
+ const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
+ base::TimeTicks) override;
+ void OnMailboxBufferReceived(int buffer_id,
+ const gpu::MailboxHolder& mailbox_holder,
+ const media::VideoCaptureFormat& format,
+ base::TimeTicks timestamp) override;
+ void OnStateChanged(VideoCaptureState state) override;
+ void OnDeviceSupportedFormatsEnumerated(
+ const media::VideoCaptureFormats& supported_formats) override;
+ void OnDeviceFormatsInUseReceived(
+ const media::VideoCaptureFormats& formats_in_use) override;
+ void OnDelegateAdded(int32 device_id) override;
// Sends an IPC message to browser process when all clients are done with the
// buffer.
void OnClientBufferFinished(int buffer_id,
const scoped_refptr<ClientBuffer>& buffer,
- const std::vector<uint32>& release_sync_points);
+ uint32 release_sync_point);
void StopDevice();
void RestartCapture();
diff --git a/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc b/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
index 7ab67a45632..a688c12b57b 100644
--- a/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
@@ -35,9 +35,7 @@ class MockVideoCaptureImpl : public VideoCaptureImpl {
destruct_callback_(destruct_callback) {
}
- virtual ~MockVideoCaptureImpl() {
- destruct_callback_.Run();
- }
+ ~MockVideoCaptureImpl() override { destruct_callback_.Run(); }
private:
base::Closure destruct_callback_;
@@ -51,12 +49,12 @@ class MockVideoCaptureImplManager : public VideoCaptureImplManager {
base::Closure destruct_video_capture_callback)
: destruct_video_capture_callback_(
destruct_video_capture_callback) {}
- virtual ~MockVideoCaptureImplManager() {}
+ ~MockVideoCaptureImplManager() override {}
protected:
- virtual VideoCaptureImpl* CreateVideoCaptureImplForTesting(
+ VideoCaptureImpl* CreateVideoCaptureImplForTesting(
media::VideoCaptureSessionId id,
- VideoCaptureMessageFilter* filter) const OVERRIDE {
+ VideoCaptureMessageFilter* filter) const override {
return new MockVideoCaptureImpl(id,
filter,
destruct_video_capture_callback_);
diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc
index 19e481d92aa..8c75e47663a 100644
--- a/chromium/content/renderer/media/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc
@@ -40,10 +40,10 @@ class VideoCaptureImplTest : public ::testing::Test {
VideoCaptureMessageFilter* filter)
: VideoCaptureImpl(id, filter) {
}
- virtual ~MockVideoCaptureImpl() {}
+ ~MockVideoCaptureImpl() override {}
// Override Send() to mimic device to send events.
- virtual void Send(IPC::Message* message) OVERRIDE {
+ void Send(IPC::Message* message) override {
CHECK(message);
// In this method, messages are sent to the according handlers as if
@@ -80,7 +80,7 @@ class VideoCaptureImplTest : public ::testing::Test {
void DeviceReceiveEmptyBuffer(int device_id,
int buffer_id,
- const std::vector<uint32>& sync_points) {}
+ uint32 sync_point) {}
void DeviceGetSupportedFormats(int device_id,
media::VideoCaptureSessionId session_id) {
diff --git a/chromium/content/renderer/media/video_capture_message_filter.cc b/chromium/content/renderer/media/video_capture_message_filter.cc
index 50345260b18..7157407fff2 100644
--- a/chromium/content/renderer/media/video_capture_message_filter.cc
+++ b/chromium/content/renderer/media/video_capture_message_filter.cc
@@ -114,8 +114,7 @@ void VideoCaptureMessageFilter::OnBufferCreated(
// Send the buffer back to Host in case it's waiting for all buffers
// to be returned.
base::SharedMemory::CloseHandle(handle);
- Send(new VideoCaptureHostMsg_BufferReady(
- device_id, buffer_id, std::vector<uint32>()));
+ Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0));
return;
}
@@ -126,6 +125,7 @@ void VideoCaptureMessageFilter::OnBufferReceived(
int device_id,
int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) {
Delegate* delegate = find_delegate(device_id);
if (!delegate) {
@@ -134,12 +134,11 @@ void VideoCaptureMessageFilter::OnBufferReceived(
// Send the buffer back to Host in case it's waiting for all buffers
// to be returned.
- Send(new VideoCaptureHostMsg_BufferReady(
- device_id, buffer_id, std::vector<uint32>()));
+ Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0));
return;
}
- delegate->OnBufferReceived(buffer_id, format, timestamp);
+ delegate->OnBufferReceived(buffer_id, format, visible_rect, timestamp);
}
void VideoCaptureMessageFilter::OnMailboxBufferReceived(
@@ -156,8 +155,7 @@ void VideoCaptureMessageFilter::OnMailboxBufferReceived(
// Send the buffer back to Host in case it's waiting for all buffers
// to be returned.
- Send(new VideoCaptureHostMsg_BufferReady(
- device_id, buffer_id, std::vector<uint32>()));
+ Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0));
return;
}
diff --git a/chromium/content/renderer/media/video_capture_message_filter.h b/chromium/content/renderer/media/video_capture_message_filter.h
index b6faa03fa97..c55d17f59ea 100644
--- a/chromium/content/renderer/media/video_capture_message_filter.h
+++ b/chromium/content/renderer/media/video_capture_message_filter.h
@@ -38,6 +38,7 @@ class CONTENT_EXPORT VideoCaptureMessageFilter : public IPC::MessageFilter {
// Called when a video frame buffer is received from the browser process.
virtual void OnBufferReceived(int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp) = 0;
// Called when a video mailbox buffer is received from the browser process.
@@ -79,13 +80,13 @@ class CONTENT_EXPORT VideoCaptureMessageFilter : public IPC::MessageFilter {
virtual bool Send(IPC::Message* message);
// IPC::MessageFilter override. Called on IO thread.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
protected:
- virtual ~VideoCaptureMessageFilter();
+ ~VideoCaptureMessageFilter() override;
private:
typedef std::map<int32, Delegate*> Delegates;
@@ -104,6 +105,7 @@ class CONTENT_EXPORT VideoCaptureMessageFilter : public IPC::MessageFilter {
void OnBufferReceived(int device_id,
int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp);
// Receive a filled texture mailbox buffer from browser process.
diff --git a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
index 742de87e14f..4633585164c 100644
--- a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -29,9 +29,10 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
int length,
int buffer_id));
MOCK_METHOD1(OnBufferDestroyed, void(int buffer_id));
- MOCK_METHOD3(OnBufferReceived,
+ MOCK_METHOD4(OnBufferReceived,
void(int buffer_id,
const media::VideoCaptureFormat& format,
+ const gfx::Rect& visible_rect,
base::TimeTicks timestamp));
MOCK_METHOD4(OnMailboxBufferReceived,
void(int buffer_id,
@@ -44,7 +45,7 @@ class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate {
MOCK_METHOD1(OnDeviceFormatsInUseReceived,
void(const media::VideoCaptureFormats& formats_in_use));
- virtual void OnDelegateAdded(int32 device_id) OVERRIDE {
+ virtual void OnDelegateAdded(int32 device_id) override {
ASSERT_TRUE(device_id != 0);
ASSERT_TRUE(device_id_ == 0);
device_id_ = device_id;
@@ -94,10 +95,11 @@ TEST(VideoCaptureMessageFilterTest, Basic) {
const media::VideoCaptureFormat shm_format(
gfx::Size(234, 512), 30, media::PIXEL_FORMAT_I420);
media::VideoCaptureFormat saved_format;
- EXPECT_CALL(delegate, OnBufferReceived(buffer_id, _, timestamp))
+ EXPECT_CALL(delegate, OnBufferReceived(buffer_id, _, _, timestamp))
.WillRepeatedly(SaveArg<1>(&saved_format));
filter->OnMessageReceived(VideoCaptureMsg_BufferReady(
- delegate.device_id(), buffer_id, shm_format, timestamp));
+ delegate.device_id(), buffer_id, shm_format, gfx::Rect(234, 512),
+ timestamp));
Mock::VerifyAndClearExpectations(&delegate);
EXPECT_EQ(shm_format.frame_size, saved_format.frame_size);
EXPECT_EQ(shm_format.frame_rate, saved_format.frame_rate);
diff --git a/chromium/content/renderer/media/video_frame_compositor.cc b/chromium/content/renderer/media/video_frame_compositor.cc
deleted file mode 100644
index 3fa8042f1f2..00000000000
--- a/chromium/content/renderer/media/video_frame_compositor.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 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 "content/renderer/media/video_frame_compositor.h"
-
-#include "media/base/video_frame.h"
-
-namespace content {
-
-static bool IsOpaque(const scoped_refptr<media::VideoFrame>& frame) {
- switch (frame->format()) {
- case media::VideoFrame::UNKNOWN:
- case media::VideoFrame::YV12:
- case media::VideoFrame::YV12J:
- case media::VideoFrame::YV16:
- case media::VideoFrame::I420:
- case media::VideoFrame::YV24:
- case media::VideoFrame::NV12:
- return true;
-
- case media::VideoFrame::YV12A:
-#if defined(VIDEO_HOLE)
- case media::VideoFrame::HOLE:
-#endif // defined(VIDEO_HOLE)
- case media::VideoFrame::NATIVE_TEXTURE:
- break;
- }
- return false;
-}
-
-VideoFrameCompositor::VideoFrameCompositor(
- const base::Callback<void(gfx::Size)>& natural_size_changed_cb,
- const base::Callback<void(bool)>& opacity_changed_cb)
- : natural_size_changed_cb_(natural_size_changed_cb),
- opacity_changed_cb_(opacity_changed_cb),
- client_(NULL) {
-}
-
-VideoFrameCompositor::~VideoFrameCompositor() {
- if (client_)
- client_->StopUsingProvider();
-}
-
-void VideoFrameCompositor::SetVideoFrameProviderClient(
- cc::VideoFrameProvider::Client* client) {
- if (client_)
- client_->StopUsingProvider();
- client_ = client;
-}
-
-scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() {
- return current_frame_;
-}
-
-void VideoFrameCompositor::PutCurrentFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
-}
-
-void VideoFrameCompositor::UpdateCurrentFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
- if (current_frame_ &&
- current_frame_->natural_size() != frame->natural_size()) {
- natural_size_changed_cb_.Run(frame->natural_size());
- }
-
- if (!current_frame_ || IsOpaque(current_frame_) != IsOpaque(frame)) {
- opacity_changed_cb_.Run(IsOpaque(frame));
- }
-
- current_frame_ = frame;
-
- if (client_)
- client_->DidReceiveFrame();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/video_frame_compositor.h b/chromium/content/renderer/media/video_frame_compositor.h
deleted file mode 100644
index 91e5d0cd17e..00000000000
--- a/chromium/content/renderer/media/video_frame_compositor.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
-#define CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "cc/layers/video_frame_provider.h"
-#include "content/common/content_export.h"
-#include "ui/gfx/size.h"
-
-namespace media {
-class VideoFrame;
-}
-
-namespace content {
-
-// VideoFrameCompositor handles incoming frames by notifying the compositor and
-// dispatching callbacks when detecting changes in video frames.
-//
-// Typical usage is to deliver ready-to-be-displayed video frames to
-// UpdateCurrentFrame() so that VideoFrameCompositor can take care of tracking
-// changes in video frames and firing callbacks as needed.
-//
-// VideoFrameCompositor must live on the same thread as the compositor.
-class CONTENT_EXPORT VideoFrameCompositor
- : NON_EXPORTED_BASE(public cc::VideoFrameProvider) {
- public:
- // |natural_size_changed_cb| is run with the new natural size of the video
- // frame whenever a change in natural size is detected. It is not called the
- // first time UpdateCurrentFrame() is called. Run on the same thread as the
- // caller of UpdateCurrentFrame().
- //
- // |opacity_changed_cb| is run when a change in opacity is detected. It *is*
- // called the first time UpdateCurrentFrame() is called. Run on the same
- // thread as the caller of UpdateCurrentFrame().
- //
- // TODO(scherkus): Investigate the inconsistency between the callbacks with
- // respect to why we don't call |natural_size_changed_cb| on the first frame.
- // I suspect it was for historical reasons that no longer make sense.
- VideoFrameCompositor(
- const base::Callback<void(gfx::Size)>& natural_size_changed_cb,
- const base::Callback<void(bool)>& opacity_changed_cb);
- virtual ~VideoFrameCompositor();
-
- // cc::VideoFrameProvider implementation.
- virtual void SetVideoFrameProviderClient(
- cc::VideoFrameProvider::Client* client) OVERRIDE;
- virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
- virtual void PutCurrentFrame(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE;
-
- // Updates the current frame and notifies the compositor.
- void UpdateCurrentFrame(const scoped_refptr<media::VideoFrame>& frame);
-
- private:
- base::Callback<void(gfx::Size)> natural_size_changed_cb_;
- base::Callback<void(bool)> opacity_changed_cb_;
-
- cc::VideoFrameProvider::Client* client_;
-
- scoped_refptr<media::VideoFrame> current_frame_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositor);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
diff --git a/chromium/content/renderer/media/video_frame_compositor_unittest.cc b/chromium/content/renderer/media/video_frame_compositor_unittest.cc
deleted file mode 100644
index 6669825e913..00000000000
--- a/chromium/content/renderer/media/video_frame_compositor_unittest.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2014 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/bind.h"
-#include "cc/layers/video_frame_provider.h"
-#include "content/renderer/media/video_frame_compositor.h"
-#include "media/base/video_frame.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-using media::VideoFrame;
-
-class VideoFrameCompositorTest : public testing::Test,
- public cc::VideoFrameProvider::Client {
- public:
- VideoFrameCompositorTest()
- : compositor_(new VideoFrameCompositor(
- base::Bind(&VideoFrameCompositorTest::NaturalSizeChanged,
- base::Unretained(this)),
- base::Bind(&VideoFrameCompositorTest::OpacityChanged,
- base::Unretained(this)))),
- did_receive_frame_count_(0),
- natural_size_changed_count_(0),
- opacity_changed_count_(0),
- opaque_(false) {
- compositor_->SetVideoFrameProviderClient(this);
- }
-
- virtual ~VideoFrameCompositorTest() {
- compositor_->SetVideoFrameProviderClient(NULL);
- }
-
- VideoFrameCompositor* compositor() { return compositor_.get(); }
- int did_receive_frame_count() { return did_receive_frame_count_; }
- int natural_size_changed_count() { return natural_size_changed_count_; }
- gfx::Size natural_size() { return natural_size_; }
-
- int opacity_changed_count() { return opacity_changed_count_; }
- bool opaque() { return opaque_; }
-
- private:
- // cc::VideoFrameProvider::Client implementation.
- virtual void StopUsingProvider() OVERRIDE {}
- virtual void DidReceiveFrame() OVERRIDE {
- ++did_receive_frame_count_;
- }
- virtual void DidUpdateMatrix(const float* matrix) OVERRIDE {}
-
- void NaturalSizeChanged(gfx::Size natural_size) {
- ++natural_size_changed_count_;
- natural_size_ = natural_size;
- }
-
- void OpacityChanged(bool opaque) {
- ++opacity_changed_count_;
- opaque_ = opaque;
- }
-
- scoped_ptr<VideoFrameCompositor> compositor_;
- int did_receive_frame_count_;
- int natural_size_changed_count_;
- gfx::Size natural_size_;
- int opacity_changed_count_;
- bool opaque_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositorTest);
-};
-
-TEST_F(VideoFrameCompositorTest, InitialValues) {
- EXPECT_FALSE(compositor()->GetCurrentFrame());
-}
-
-TEST_F(VideoFrameCompositorTest, UpdateCurrentFrame) {
- scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame();
-
- // Should notify compositor synchronously.
- EXPECT_EQ(0, did_receive_frame_count());
- compositor()->UpdateCurrentFrame(expected);
- scoped_refptr<VideoFrame> actual = compositor()->GetCurrentFrame();
- EXPECT_EQ(expected, actual);
- EXPECT_EQ(1, did_receive_frame_count());
-}
-
-TEST_F(VideoFrameCompositorTest, NaturalSizeChanged) {
- gfx::Size initial_size(8, 8);
- scoped_refptr<VideoFrame> initial_frame =
- VideoFrame::CreateBlackFrame(initial_size);
-
- gfx::Size larger_size(16, 16);
- scoped_refptr<VideoFrame> larger_frame =
- VideoFrame::CreateBlackFrame(larger_size);
-
- // Initial expectations.
- EXPECT_EQ(0, natural_size().width());
- EXPECT_EQ(0, natural_size().height());
- EXPECT_EQ(0, natural_size_changed_count());
-
- // Callback isn't fired for the first frame.
- compositor()->UpdateCurrentFrame(initial_frame);
- EXPECT_EQ(0, natural_size().width());
- EXPECT_EQ(0, natural_size().height());
- EXPECT_EQ(0, natural_size_changed_count());
-
- // Callback should be fired once.
- compositor()->UpdateCurrentFrame(larger_frame);
- EXPECT_EQ(larger_size.width(), natural_size().width());
- EXPECT_EQ(larger_size.height(), natural_size().height());
- EXPECT_EQ(1, natural_size_changed_count());
-
- compositor()->UpdateCurrentFrame(larger_frame);
- EXPECT_EQ(larger_size.width(), natural_size().width());
- EXPECT_EQ(larger_size.height(), natural_size().height());
- EXPECT_EQ(1, natural_size_changed_count());
-
- // Callback is fired once more when switching back to initial size.
- compositor()->UpdateCurrentFrame(initial_frame);
- EXPECT_EQ(initial_size.width(), natural_size().width());
- EXPECT_EQ(initial_size.height(), natural_size().height());
- EXPECT_EQ(2, natural_size_changed_count());
-
- compositor()->UpdateCurrentFrame(initial_frame);
- EXPECT_EQ(initial_size.width(), natural_size().width());
- EXPECT_EQ(initial_size, natural_size());
- EXPECT_EQ(2, natural_size_changed_count());
-}
-
-TEST_F(VideoFrameCompositorTest, OpacityChanged) {
- gfx::Size size(8, 8);
- gfx::Rect rect(gfx::Point(0, 0), size);
- scoped_refptr<VideoFrame> opaque_frame = VideoFrame::CreateFrame(
- VideoFrame::YV12, size, rect, size, base::TimeDelta());
- scoped_refptr<VideoFrame> not_opaque_frame = VideoFrame::CreateFrame(
- VideoFrame::YV12A, size, rect, size, base::TimeDelta());
-
- // Initial expectations.
- EXPECT_FALSE(opaque());
- EXPECT_EQ(0, opacity_changed_count());
-
- // Callback is fired for the first frame.
- compositor()->UpdateCurrentFrame(not_opaque_frame);
- EXPECT_FALSE(opaque());
- EXPECT_EQ(1, opacity_changed_count());
-
- // Callback shouldn't be first subsequent times with same opaqueness.
- compositor()->UpdateCurrentFrame(not_opaque_frame);
- EXPECT_FALSE(opaque());
- EXPECT_EQ(1, opacity_changed_count());
-
- // Callback is fired when using opacity changes.
- compositor()->UpdateCurrentFrame(opaque_frame);
- EXPECT_TRUE(opaque());
- EXPECT_EQ(2, opacity_changed_count());
-
- // Callback shouldn't be first subsequent times with same opaqueness.
- compositor()->UpdateCurrentFrame(opaque_frame);
- EXPECT_TRUE(opaque());
- EXPECT_EQ(2, opacity_changed_count());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/video_frame_deliverer.cc b/chromium/content/renderer/media/video_frame_deliverer.cc
deleted file mode 100644
index 05c77496790..00000000000
--- a/chromium/content/renderer/media/video_frame_deliverer.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2014 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 "content/renderer/media/video_frame_deliverer.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-
-namespace content {
-namespace {
-void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
- // |callback| will be deleted when this exits.
-}
-} // namespace
-
-VideoFrameDeliverer::VideoFrameDeliverer(
- const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
- : io_message_loop_(io_message_loop) {
- DCHECK(io_message_loop_);
-}
-
-VideoFrameDeliverer::~VideoFrameDeliverer() {
- DCHECK(callbacks_.empty());
-}
-
-void VideoFrameDeliverer::AddCallback(
- void* id,
- const VideoCaptureDeliverFrameCB& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- io_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoFrameDeliverer::AddCallbackOnIO,
- this, id, callback));
-}
-
-void VideoFrameDeliverer::AddCallbackOnIO(
- void* id,
- const VideoCaptureDeliverFrameCB& callback) {
- DCHECK(io_message_loop_->BelongsToCurrentThread());
- callbacks_.push_back(std::make_pair(id, callback));
-}
-
-void VideoFrameDeliverer::RemoveCallback(void* id) {
- DCHECK(thread_checker_.CalledOnValidThread());
- io_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&VideoFrameDeliverer::RemoveCallbackOnIO,
- this, id, base::MessageLoopProxy::current()));
-}
-
-void VideoFrameDeliverer::RemoveCallbackOnIO(
- void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop) {
- DCHECK(io_message_loop_->BelongsToCurrentThread());
- std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
- for (; it != callbacks_.end(); ++it) {
- if (it->first == id) {
- // Callback is copied to heap and then deleted on the target thread.
- // The following code ensures that the callback is not referenced on
- // the stack.
- scoped_ptr<VideoCaptureDeliverFrameCB> callback;
- {
- callback.reset(new VideoCaptureDeliverFrameCB(it->second));
- callbacks_.erase(it);
- }
- message_loop->PostTask(
- FROM_HERE, base::Bind(&ResetCallback, base::Passed(&callback)));
- return;
- }
- }
-}
-
-void VideoFrameDeliverer::DeliverFrameOnIO(
- const scoped_refptr<media::VideoFrame>& frame,
- const media::VideoCaptureFormat& format,
- const base::TimeTicks& estimated_capture_time) {
- DCHECK(io_message_loop_->BelongsToCurrentThread());
- for (std::vector<VideoIdCallbackPair>::iterator it = callbacks_.begin();
- it != callbacks_.end(); ++it) {
- it->second.Run(frame, format, estimated_capture_time);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/video_frame_deliverer.h b/chromium/content/renderer/media/video_frame_deliverer.h
deleted file mode 100644
index a1f4b9d4f6a..00000000000
--- a/chromium/content/renderer/media/video_frame_deliverer.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_MEDIA_VIDEO_FRAME_DELIVERER_H_
-#define CONTENT_RENDERER_MEDIA_VIDEO_FRAME_DELIVERER_H_
-
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/media/video_capture.h"
-#include "content/public/renderer/media_stream_video_sink.h"
-#include "media/base/video_frame.h"
-
-namespace content {
-
-// VideoFrameDeliverer is a helper class used for registering
-// VideoCaptureDeliverFrameCB on the main render thread to receive video frames
-// on the IO-thread.
-// Its used by MediaStreamVideoTrack.
-class VideoFrameDeliverer
- : public base::RefCountedThreadSafe<VideoFrameDeliverer> {
- public:
- explicit VideoFrameDeliverer(
- const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
-
- // Add |callback| to receive video frames on the IO-thread.
- // Must be called on the main render thread.
- void AddCallback(void* id, const VideoCaptureDeliverFrameCB& callback);
-
- // Removes |callback| associated with |id| from receiving video frames if |id|
- // has been added. It is ok to call RemoveCallback even if the |id| has not
- // been added. Note that the added callback will be reset on the main thread.
- // Must be called on the main render thread.
- void RemoveCallback(void* id);
-
- // Triggers all registered callbacks with |frame|, |format| and
- // |estimated_capture_time| as parameters. Must be called on the IO-thread.
- virtual void DeliverFrameOnIO(
- const scoped_refptr<media::VideoFrame>& frame,
- const media::VideoCaptureFormat& format,
- const base::TimeTicks& estimated_capture_time);
-
- const scoped_refptr<base::MessageLoopProxy>& io_message_loop() const {
- return io_message_loop_;
- }
-
- protected:
- void AddCallbackOnIO(void* id, const VideoCaptureDeliverFrameCB& callback);
-
- // Callback will be removed and then reset on the designated message loop.
- // It is ok to call RemoveCallback even if |id| has not been added.
- void RemoveCallbackOnIO(
- void* id, const scoped_refptr<base::MessageLoopProxy>& message_loop);
-
- protected:
- virtual ~VideoFrameDeliverer();
- const base::ThreadChecker& thread_checker() const {
- return thread_checker_;
- }
-
- private:
- friend class base::RefCountedThreadSafe<VideoFrameDeliverer>;
-
- // Used to DCHECK that AddCallback and RemoveCallback are called on the main
- // render thread.
- base::ThreadChecker thread_checker_;
- scoped_refptr<base::MessageLoopProxy> io_message_loop_;
-
- typedef std::pair<void*, VideoCaptureDeliverFrameCB> VideoIdCallbackPair;
- std::vector<VideoIdCallbackPair> callbacks_;
-
- DISALLOW_COPY_AND_ASSIGN(VideoFrameDeliverer);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_VIDEO_FRAME_DELIVERER_H_
diff --git a/chromium/content/renderer/media/video_source_handler.cc b/chromium/content/renderer/media/video_source_handler.cc
index a91ac3b0884..b3d8238f2e3 100644
--- a/chromium/content/renderer/media/video_source_handler.cc
+++ b/chromium/content/renderer/media/video_source_handler.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
@@ -32,7 +33,7 @@ class PpFrameReceiver : public MediaStreamVideoSink {
weak_factory_(this) {
}
- virtual ~PpFrameReceiver() {}
+ ~PpFrameReceiver() override {}
void SetReader(FrameReaderInterface* reader) {
if (reader) {
@@ -56,6 +57,7 @@ class PpFrameReceiver : public MediaStreamVideoSink {
const scoped_refptr<media::VideoFrame>& frame,
const media::VideoCaptureFormat& format,
const base::TimeTicks& estimated_capture_time) {
+ TRACE_EVENT0("video", "PpFrameReceiver::OnVideoFrame");
if (reader_) {
reader_->GotFrame(frame);
}
diff --git a/chromium/content/renderer/media/video_source_handler.h b/chromium/content/renderer/media/video_source_handler.h
index ead167a0a5b..323a2d8a721 100644
--- a/chromium/content/renderer/media/video_source_handler.h
+++ b/chromium/content/renderer/media/video_source_handler.h
@@ -28,7 +28,7 @@ class PpFrameReceiver;
class CONTENT_EXPORT FrameReaderInterface {
public:
// Got a new captured frame.
- virtual bool GotFrame(const scoped_refptr<media::VideoFrame>& frame) = 0;
+ virtual void GotFrame(const scoped_refptr<media::VideoFrame>& frame) = 0;
protected:
virtual ~FrameReaderInterface() {}
diff --git a/chromium/content/renderer/media/video_source_handler_unittest.cc b/chromium/content/renderer/media/video_source_handler_unittest.cc
index 94dce46a195..31c96fe1c37 100644
--- a/chromium/content/renderer/media/video_source_handler_unittest.cc
+++ b/chromium/content/renderer/media/video_source_handler_unittest.cc
@@ -17,6 +17,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
namespace content {
@@ -26,10 +27,8 @@ static const std::string kUnknownStreamUrl = "unknown_stream_url";
class FakeFrameReader : public FrameReaderInterface {
public:
- virtual bool GotFrame(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE {
+ void GotFrame(const scoped_refptr<media::VideoFrame>& frame) override {
last_frame_ = frame;
- return true;
}
const media::VideoFrame* last_frame() {
@@ -44,17 +43,23 @@ class VideoSourceHandlerTest : public ::testing::Test {
public:
VideoSourceHandlerTest()
: child_process_(new ChildProcess()),
- registry_() {
- handler_.reset(new VideoSourceHandler(&registry_));
- registry_.Init(kTestStreamUrl);
- registry_.AddVideoTrack(kTestVideoTrackId);
+ registry_(new MockMediaStreamRegistry()) {
+ handler_.reset(new VideoSourceHandler(registry_.get()));
+ registry_->Init(kTestStreamUrl);
+ registry_->AddVideoTrack(kTestVideoTrackId);
+ }
+
+ void TearDown() override {
+ registry_.reset();
+ handler_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
}
protected:
base::MessageLoop message_loop_;
scoped_ptr<ChildProcess> child_process_;
scoped_ptr<VideoSourceHandler> handler_;
- MockMediaStreamRegistry registry_;
+ scoped_ptr<MockMediaStreamRegistry> registry_;
};
TEST_F(VideoSourceHandlerTest, OpenClose) {
diff --git a/chromium/content/renderer/media/video_track_adapter.cc b/chromium/content/renderer/media/video_track_adapter.cc
index 461b16638f6..ada3502173e 100644
--- a/chromium/content/renderer/media/video_track_adapter.cc
+++ b/chromium/content/renderer/media/video_track_adapter.cc
@@ -11,12 +11,24 @@
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/location.h"
+#include "base/metrics/histogram.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/video_util.h"
namespace content {
namespace {
+// Amount of frame intervals to wait before considering the source as muted, for
+// the first frame and under normal conditions, respectively. First frame might
+// take longer to arrive due to source startup.
+const float kFirstFrameTimeoutInFrameIntervals = 100.0f;
+const float kNormalFrameTimeoutInFrameIntervals = 25.0f;
+
+// Min delta time between two frames allowed without being dropped if a max
+// frame rate is specified.
+const int kMinTimeInMsBetweenFrames = 5;
+
// Empty method used for keeping a reference to the original media::VideoFrame
// in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed.
// The reference to |frame| is kept in the closure that calls this method.
@@ -40,10 +52,10 @@ class VideoTrackAdapter::VideoFrameResolutionAdapter
public:
VideoFrameResolutionAdapter(
scoped_refptr<base::SingleThreadTaskRunner> render_message_loop,
- int max_width,
- int max_height,
+ const gfx::Size& max_size,
double min_aspect_ratio,
- double max_aspect_ratio);
+ double max_aspect_ratio,
+ double max_frame_rate);
// Add |callback| to receive video frames on the IO-thread.
// |callback| will however be released on the main render thread.
@@ -60,10 +72,10 @@ class VideoTrackAdapter::VideoFrameResolutionAdapter
const base::TimeTicks& estimated_capture_time);
// Returns true if all arguments match with the output of this adapter.
- bool ConstraintsMatch(int max_width,
- int max_height,
+ bool ConstraintsMatch(const gfx::Size& max_size,
double min_aspect_ratio,
- double max_aspect_ratio) const;
+ double max_aspect_ratio,
+ double max_frame_rate) const;
bool IsEmpty() const;
@@ -76,6 +88,11 @@ class VideoTrackAdapter::VideoFrameResolutionAdapter
const media::VideoCaptureFormat& format,
const base::TimeTicks& estimated_capture_time);
+ // Returns |true| if the input frame rate is higher that the requested max
+ // frame rate and |frame| should be dropped.
+ bool MaybeDropFrame(const scoped_refptr<media::VideoFrame>& frame,
+ float source_frame_rate);
+
// Bound to the IO-thread.
base::ThreadChecker io_thread_checker_;
@@ -87,6 +104,11 @@ class VideoTrackAdapter::VideoFrameResolutionAdapter
double min_aspect_ratio_;
double max_aspect_ratio_;
+ double frame_rate_;
+ base::TimeDelta last_time_stamp_;
+ double max_frame_rate_;
+ double keep_frame_counter_;
+
typedef std::pair<const void*, VideoCaptureDeliverFrameCB>
VideoIdCallbackPair;
std::vector<VideoIdCallbackPair> callbacks_;
@@ -97,23 +119,27 @@ class VideoTrackAdapter::VideoFrameResolutionAdapter
VideoTrackAdapter::
VideoFrameResolutionAdapter::VideoFrameResolutionAdapter(
scoped_refptr<base::SingleThreadTaskRunner> render_message_loop,
- int max_width,
- int max_height,
+ const gfx::Size& max_size,
double min_aspect_ratio,
- double max_aspect_ratio)
+ double max_aspect_ratio,
+ double max_frame_rate)
: renderer_task_runner_(render_message_loop),
- max_frame_size_(max_width, max_height),
+ max_frame_size_(max_size),
min_aspect_ratio_(min_aspect_ratio),
- max_aspect_ratio_(max_aspect_ratio) {
- DCHECK(renderer_task_runner_);
+ max_aspect_ratio_(max_aspect_ratio),
+ frame_rate_(MediaStreamVideoSource::kDefaultFrameRate),
+ max_frame_rate_(max_frame_rate),
+ keep_frame_counter_(0.0f) {
+ DCHECK(renderer_task_runner_.get());
DCHECK(io_thread_checker_.CalledOnValidThread());
DCHECK_GE(max_aspect_ratio_, min_aspect_ratio_);
CHECK_NE(0, max_aspect_ratio_);
DVLOG(3) << "VideoFrameResolutionAdapter("
- << "{ max_width =" << max_width << "}, "
- << "{ max_height =" << max_height << "}, "
+ << "{ max_width =" << max_frame_size_.width() << "}, "
+ << "{ max_height =" << max_frame_size_.height() << "}, "
<< "{ min_aspect_ratio =" << min_aspect_ratio << "}, "
- << "{ max_aspect_ratio_ =" << max_aspect_ratio_ << "}) ";
+ << "{ max_aspect_ratio_ =" << max_aspect_ratio_ << "}"
+ << "{ max_frame_rate_ =" << max_frame_rate_ << "}) ";
}
VideoTrackAdapter::
@@ -127,6 +153,10 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame(
const media::VideoCaptureFormat& format,
const base::TimeTicks& estimated_capture_time) {
DCHECK(io_thread_checker_.CalledOnValidThread());
+
+ if (MaybeDropFrame(frame, format.frame_rate))
+ return;
+
// TODO(perkj): Allow cropping / scaling of textures once
// http://crbug/362521 is fixed.
if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) {
@@ -195,6 +225,56 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame(
DoDeliverFrame(video_frame, format, estimated_capture_time);
}
+bool VideoTrackAdapter::VideoFrameResolutionAdapter::MaybeDropFrame(
+ const scoped_refptr<media::VideoFrame>& frame,
+ float source_frame_rate) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+
+ // Do not drop frames if max frame rate hasn't been specified or the source
+ // frame rate is known and is lower than max.
+ if (max_frame_rate_ == 0.0f ||
+ (source_frame_rate > 0 &&
+ source_frame_rate <= max_frame_rate_)) {
+ return false;
+ }
+
+ base::TimeDelta delta = frame->timestamp() - last_time_stamp_;
+ if (delta.InMilliseconds() < kMinTimeInMsBetweenFrames) {
+ // We have seen video frames being delivered from camera devices back to
+ // back. The simple AR filter for frame rate calculation is too short to
+ // handle that. http://crbug/394315
+ // TODO(perkj): Can we come up with a way to fix the times stamps and the
+ // timing when frames are delivered so all frames can be used?
+ // The time stamps are generated by Chrome and not the actual device.
+ // Most likely the back to back problem is caused by software and not the
+ // actual camera.
+ DVLOG(3) << "Drop frame since delta time since previous frame is "
+ << delta.InMilliseconds() << "ms.";
+ return true;
+ }
+ last_time_stamp_ = frame->timestamp();
+ if (delta == last_time_stamp_) // First received frame.
+ return false;
+ // Calculate the frame rate using a simple AR filter.
+ // Use a simple filter with 0.1 weight of the current sample.
+ frame_rate_ = 100 / delta.InMillisecondsF() + 0.9 * frame_rate_;
+
+ // Prefer to not drop frames.
+ if (max_frame_rate_ + 0.5f > frame_rate_)
+ return false; // Keep this frame.
+
+ // The input frame rate is higher than requested.
+ // Decide if we should keep this frame or drop it.
+ keep_frame_counter_ += max_frame_rate_ / frame_rate_;
+ if (keep_frame_counter_ >= 1) {
+ keep_frame_counter_ -= 1;
+ // Keep the frame.
+ return false;
+ }
+ DVLOG(3) << "Drop frame. Input frame_rate_ " << frame_rate_ << ".";
+ return true;
+}
+
void VideoTrackAdapter::
VideoFrameResolutionAdapter::DoDeliverFrame(
const scoped_refptr<media::VideoFrame>& frame,
@@ -236,15 +316,15 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::RemoveCallback(
}
bool VideoTrackAdapter::VideoFrameResolutionAdapter::ConstraintsMatch(
- int max_width,
- int max_height,
+ const gfx::Size& max_size,
double min_aspect_ratio,
- double max_aspect_ratio) const {
+ double max_aspect_ratio,
+ double max_frame_rate) const {
DCHECK(io_thread_checker_.CalledOnValidThread());
- return max_frame_size_.width() == max_width &&
- max_frame_size_.height() == max_height &&
+ return max_frame_size_ == max_size &&
min_aspect_ratio_ == min_aspect_ratio &&
- max_aspect_ratio_ == max_aspect_ratio;
+ max_aspect_ratio_ == max_aspect_ratio &&
+ max_frame_rate_ == max_frame_rate;
}
bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const {
@@ -255,51 +335,58 @@ bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const {
VideoTrackAdapter::VideoTrackAdapter(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
: io_message_loop_(io_message_loop),
- renderer_task_runner_(base::MessageLoopProxy::current()) {
- DCHECK(io_message_loop_);
+ renderer_task_runner_(base::MessageLoopProxy::current()),
+ monitoring_frame_rate_(false),
+ muted_state_(false),
+ frame_counter_(0),
+ source_frame_rate_(0.0f) {
+ DCHECK(io_message_loop_.get());
}
VideoTrackAdapter::~VideoTrackAdapter() {
DCHECK(adapters_.empty());
}
-void VideoTrackAdapter::AddTrack(const MediaStreamVideoTrack* track,
- VideoCaptureDeliverFrameCB frame_callback,
- int max_width,
- int max_height,
- double min_aspect_ratio,
- double max_aspect_ratio) {
+void VideoTrackAdapter::AddTrack(
+ const MediaStreamVideoTrack* track,
+ VideoCaptureDeliverFrameCB frame_callback,
+ int max_width,
+ int max_height,
+ double min_aspect_ratio,
+ double max_aspect_ratio,
+ double max_frame_rate) {
DCHECK(thread_checker_.CalledOnValidThread());
+
io_message_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoTrackAdapter::AddTrackOnIO,
- this, track, frame_callback, max_width, max_height,
- min_aspect_ratio, max_aspect_ratio));
+ this, track, frame_callback, gfx::Size(max_width, max_height),
+ min_aspect_ratio, max_aspect_ratio, max_frame_rate));
}
void VideoTrackAdapter::AddTrackOnIO(
const MediaStreamVideoTrack* track,
VideoCaptureDeliverFrameCB frame_callback,
- int max_width,
- int max_height,
+ const gfx::Size& max_frame_size,
double min_aspect_ratio,
- double max_aspect_ratio) {
+ double max_aspect_ratio,
+ double max_frame_rate) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
scoped_refptr<VideoFrameResolutionAdapter> adapter;
for (FrameAdapters::const_iterator it = adapters_.begin();
it != adapters_.end(); ++it) {
- if ((*it)->ConstraintsMatch(max_width, max_height, min_aspect_ratio,
- max_aspect_ratio)) {
+ if ((*it)->ConstraintsMatch(max_frame_size, min_aspect_ratio,
+ max_aspect_ratio, max_frame_rate)) {
adapter = it->get();
break;
}
}
- if (!adapter) {
+ if (!adapter.get()) {
adapter = new VideoFrameResolutionAdapter(renderer_task_runner_,
- max_width,
- max_height,
+ max_frame_size,
min_aspect_ratio,
- max_aspect_ratio);
+ max_aspect_ratio,
+ max_frame_rate);
adapters_.push_back(adapter);
}
@@ -313,6 +400,53 @@ void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) {
base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track));
}
+void VideoTrackAdapter::StartFrameMonitoring(
+ double source_frame_rate,
+ const OnMutedCallback& on_muted_callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ VideoTrackAdapter::OnMutedCallback bound_on_muted_callback =
+ media::BindToCurrentLoop(on_muted_callback);
+
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoTrackAdapter::StartFrameMonitoringOnIO,
+ this, bound_on_muted_callback, source_frame_rate));
+}
+
+void VideoTrackAdapter::StartFrameMonitoringOnIO(
+ const OnMutedCallback& on_muted_callback,
+ double source_frame_rate) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ DCHECK(!monitoring_frame_rate_);
+
+ monitoring_frame_rate_ = true;
+
+ // If the source does not know the frame rate, set one by default.
+ if (source_frame_rate == 0.0f)
+ source_frame_rate = MediaStreamVideoSource::kDefaultFrameRate;
+ source_frame_rate_ = source_frame_rate;
+ DVLOG(1) << "Monitoring frame creation, first (large) delay: "
+ << (kFirstFrameTimeoutInFrameIntervals / source_frame_rate_) << "s";
+ io_message_loop_->PostDelayedTask(FROM_HERE,
+ base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this,
+ on_muted_callback, frame_counter_),
+ base::TimeDelta::FromSecondsD(kFirstFrameTimeoutInFrameIntervals /
+ source_frame_rate_));
+}
+
+void VideoTrackAdapter::StopFrameMonitoring() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ io_message_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoTrackAdapter::StopFrameMonitoringOnIO, this));
+}
+
+void VideoTrackAdapter::StopFrameMonitoringOnIO() {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+ monitoring_frame_rate_ = false;
+}
+
void VideoTrackAdapter::RemoveTrackOnIO(const MediaStreamVideoTrack* track) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
for (FrameAdapters::iterator it = adapters_.begin();
@@ -331,10 +465,35 @@ void VideoTrackAdapter::DeliverFrameOnIO(
const base::TimeTicks& estimated_capture_time) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO");
+ ++frame_counter_;
for (FrameAdapters::iterator it = adapters_.begin();
it != adapters_.end(); ++it) {
(*it)->DeliverFrame(frame, format, estimated_capture_time);
}
}
+void VideoTrackAdapter::CheckFramesReceivedOnIO(
+ const OnMutedCallback& set_muted_state_callback,
+ uint64 old_frame_counter_snapshot) {
+ DCHECK(io_message_loop_->BelongsToCurrentThread());
+
+ if (!monitoring_frame_rate_)
+ return;
+
+ DVLOG_IF(1, old_frame_counter_snapshot == frame_counter_)
+ << "No frames have passed, setting source as Muted.";
+
+ bool muted_state = old_frame_counter_snapshot == frame_counter_;
+ if (muted_state_ != muted_state) {
+ set_muted_state_callback.Run(muted_state);
+ muted_state_ = muted_state;
+ }
+
+ io_message_loop_->PostDelayedTask(FROM_HERE,
+ base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this,
+ set_muted_state_callback, frame_counter_),
+ base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals /
+ source_frame_rate_));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/video_track_adapter.h b/chromium/content/renderer/media/video_track_adapter.h
index 6060708ca51..1a616126985 100644
--- a/chromium/content/renderer/media/video_track_adapter.h
+++ b/chromium/content/renderer/media/video_track_adapter.h
@@ -27,6 +27,8 @@ namespace content {
class VideoTrackAdapter
: public base::RefCountedThreadSafe<VideoTrackAdapter> {
public:
+ typedef base::Callback<void(bool mute_state)> OnMutedCallback;
+
explicit VideoTrackAdapter(
const scoped_refptr<base::MessageLoopProxy>& io_message_loop);
@@ -34,11 +36,14 @@ class VideoTrackAdapter
// a resolution within the boundaries of the arguments.
// Must be called on the main render thread. |frame_callback| is guaranteed to
// be released on the main render thread.
+ // |source_frame_rate| is used to calculate a prudent interval to check for
+ // passing frames and inform of the result via |on_muted_state_callback|.
void AddTrack(const MediaStreamVideoTrack* track,
VideoCaptureDeliverFrameCB frame_callback,
int max_width, int max_height,
double min_aspect_ratio,
- double max_aspect_ratio);
+ double max_aspect_ratio,
+ double max_frame_rate);
void RemoveTrack(const MediaStreamVideoTrack* track);
// Delivers |frame| to all tracks that have registered a callback.
@@ -53,6 +58,13 @@ class VideoTrackAdapter
return io_message_loop_;
}
+ // Start monitor that frames are delivered to this object. I.E, that
+ // |DeliverFrameOnIO| is called with a frame rate of |source_frame_rate|.
+ // |on_muted_callback| is triggered on the main render thread.
+ void StartFrameMonitoring(double source_frame_rate,
+ const OnMutedCallback& on_muted_callback);
+ void StopFrameMonitoring();
+
private:
virtual ~VideoTrackAdapter();
friend class base::RefCountedThreadSafe<VideoTrackAdapter>;
@@ -60,11 +72,22 @@ class VideoTrackAdapter
void AddTrackOnIO(
const MediaStreamVideoTrack* track,
VideoCaptureDeliverFrameCB frame_callback,
- int max_width, int max_height,
+ const gfx::Size& max_frame_size,
double min_aspect_ratio,
- double max_aspect_ratio);
+ double max_aspect_ratio,
+ double max_frame_rate);
void RemoveTrackOnIO(const MediaStreamVideoTrack* track);
+ void StartFrameMonitoringOnIO(
+ const OnMutedCallback& on_muted_state_callback,
+ double source_frame_rate);
+ void StopFrameMonitoringOnIO();
+
+ // Compare |frame_counter_snapshot| with the current |frame_counter_|, and
+ // inform of the situation (muted, not muted) via |set_muted_state_callback|.
+ void CheckFramesReceivedOnIO(const OnMutedCallback& set_muted_state_callback,
+ uint64 old_frame_counter_snapshot);
+
// |thread_checker_| is bound to the main render thread.
base::ThreadChecker thread_checker_;
@@ -82,6 +105,20 @@ class VideoTrackAdapter
FrameAdapters;
FrameAdapters adapters_;
+ // Set to true if frame monitoring has been started. It is only accessed on
+ // the IO-thread.
+ bool monitoring_frame_rate_;
+
+ // Keeps track of it frames have been received. It is only accessed on the
+ // IO-thread.
+ bool muted_state_;
+
+ // Running frame counter, accessed on the IO-thread.
+ uint64 frame_counter_;
+
+ // Frame rate configured on the video source, accessed on the IO-thread.
+ float source_frame_rate_;
+
DISALLOW_COPY_AND_ASSIGN(VideoTrackAdapter);
};
diff --git a/chromium/content/renderer/media/webaudio_capturer_source.cc b/chromium/content/renderer/media/webaudio_capturer_source.cc
index 7076c24f329..e175ad293d9 100644
--- a/chromium/content/renderer/media/webaudio_capturer_source.cc
+++ b/chromium/content/renderer/media/webaudio_capturer_source.cc
@@ -48,7 +48,7 @@ void WebAudioCapturerSource::setFormat(
// as buffer size since that is the native buffer size of WebRtc packet
// running on.
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- channel_layout, number_of_channels, 0, sample_rate, 16,
+ channel_layout, number_of_channels, sample_rate, 16,
sample_rate / 100);
audio_format_changed_ = true;
@@ -127,7 +127,7 @@ void WebAudioCapturerSource::consumeAudio(
params_.bits_per_sample() / 8,
audio_data_.get());
track_->Capture(audio_data_.get(), delay, volume, key_pressed,
- need_audio_processing);
+ need_audio_processing, false);
}
}
diff --git a/chromium/content/renderer/media/webaudio_capturer_source.h b/chromium/content/renderer/media/webaudio_capturer_source.h
index fdd3f9c68ff..6382bd31830 100644
--- a/chromium/content/renderer/media/webaudio_capturer_source.h
+++ b/chromium/content/renderer/media/webaudio_capturer_source.h
@@ -34,11 +34,11 @@ class WebAudioCapturerSource
// WebAudioDestinationConsumer implementation.
// setFormat() is called early on, so that we can configure the audio track.
- virtual void setFormat(size_t number_of_channels, float sample_rate) OVERRIDE;
+ virtual void setFormat(size_t number_of_channels, float sample_rate) override;
// MediaStreamAudioDestinationNode periodically calls consumeAudio().
// Called on the WebAudio audio thread.
virtual void consumeAudio(const blink::WebVector<const float*>& audio_data,
- size_t number_of_frames) OVERRIDE;
+ size_t number_of_frames) override;
// Called when the WebAudioCapturerSource is hooking to a media audio track.
// |track| is the sink of the data flow. |source_provider| is the source of
diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl.cc b/chromium/content/renderer/media/webaudiosourceprovider_impl.cc
deleted file mode 100644
index 4d878ce4ba7..00000000000
--- a/chromium/content/renderer/media/webaudiosourceprovider_impl.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/webaudiosourceprovider_impl.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/logging.h"
-#include "media/base/bind_to_current_loop.h"
-#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
-
-using blink::WebVector;
-
-namespace content {
-
-namespace {
-
-// Simple helper class for Try() locks. Lock is Try()'d on construction and
-// must be checked via the locked() attribute. If acquisition was successful
-// the lock will be released upon destruction.
-// TODO(dalecurtis): This should probably move to base/ if others start using
-// this pattern.
-class AutoTryLock {
- public:
- explicit AutoTryLock(base::Lock& lock)
- : lock_(lock),
- acquired_(lock_.Try()) {}
-
- bool locked() const { return acquired_; }
-
- ~AutoTryLock() {
- if (acquired_) {
- lock_.AssertAcquired();
- lock_.Release();
- }
- }
-
- private:
- base::Lock& lock_;
- const bool acquired_;
- DISALLOW_COPY_AND_ASSIGN(AutoTryLock);
-};
-
-} // namespace
-
-WebAudioSourceProviderImpl::WebAudioSourceProviderImpl(
- const scoped_refptr<media::AudioRendererSink>& sink)
- : channels_(0),
- sample_rate_(0),
- volume_(1.0),
- state_(kStopped),
- renderer_(NULL),
- client_(NULL),
- sink_(sink),
- weak_factory_(this) {}
-
-WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() {
-}
-
-void WebAudioSourceProviderImpl::setClient(
- blink::WebAudioSourceProviderClient* client) {
- base::AutoLock auto_lock(sink_lock_);
- if (client && client != client_) {
- // Detach the audio renderer from normal playback.
- sink_->Stop();
-
- // The client will now take control by calling provideInput() periodically.
- client_ = client;
-
- set_format_cb_ = media::BindToCurrentLoop(base::Bind(
- &WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr()));
-
- // If |renderer_| is set, then run |set_format_cb_| to send |client_|
- // the current format info. If |renderer_| is not set, then |set_format_cb_|
- // will get called when Initialize() is called.
- // Note: Always using |set_format_cb_| ensures we have the same
- // locking order when calling into |client_|.
- if (renderer_)
- base::ResetAndReturn(&set_format_cb_).Run();
- } else if (!client && client_) {
- // Restore normal playback.
- client_ = NULL;
- sink_->SetVolume(volume_);
- if (state_ >= kStarted)
- sink_->Start();
- if (state_ >= kPlaying)
- sink_->Play();
- }
-}
-
-void WebAudioSourceProviderImpl::provideInput(
- const WebVector<float*>& audio_data, size_t number_of_frames) {
- if (!bus_wrapper_ ||
- static_cast<size_t>(bus_wrapper_->channels()) != audio_data.size()) {
- bus_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size());
- }
-
- bus_wrapper_->set_frames(number_of_frames);
- for (size_t i = 0; i < audio_data.size(); ++i)
- bus_wrapper_->SetChannelData(i, audio_data[i]);
-
- // Use a try lock to avoid contention in the real-time audio thread.
- AutoTryLock auto_try_lock(sink_lock_);
- if (!auto_try_lock.locked() || state_ != kPlaying) {
- // Provide silence if we failed to acquire the lock or the source is not
- // running.
- bus_wrapper_->Zero();
- return;
- }
-
- DCHECK(renderer_);
- DCHECK(client_);
- DCHECK_EQ(channels_, bus_wrapper_->channels());
- const size_t frames = renderer_->Render(bus_wrapper_.get(), 0);
- if (frames < number_of_frames)
- bus_wrapper_->ZeroFramesPartial(frames, number_of_frames - frames);
- bus_wrapper_->Scale(volume_);
-}
-
-void WebAudioSourceProviderImpl::Start() {
- base::AutoLock auto_lock(sink_lock_);
- DCHECK_EQ(state_, kStopped);
- state_ = kStarted;
- if (!client_)
- sink_->Start();
-}
-
-void WebAudioSourceProviderImpl::Stop() {
- base::AutoLock auto_lock(sink_lock_);
- state_ = kStopped;
- if (!client_)
- sink_->Stop();
-}
-
-void WebAudioSourceProviderImpl::Play() {
- base::AutoLock auto_lock(sink_lock_);
- DCHECK_EQ(state_, kStarted);
- state_ = kPlaying;
- if (!client_)
- sink_->Play();
-}
-
-void WebAudioSourceProviderImpl::Pause() {
- base::AutoLock auto_lock(sink_lock_);
- DCHECK(state_ == kPlaying || state_ == kStarted);
- state_ = kStarted;
- if (!client_)
- sink_->Pause();
-}
-
-bool WebAudioSourceProviderImpl::SetVolume(double volume) {
- base::AutoLock auto_lock(sink_lock_);
- volume_ = volume;
- if (!client_)
- sink_->SetVolume(volume);
- return true;
-}
-
-void WebAudioSourceProviderImpl::Initialize(
- const media::AudioParameters& params,
- RenderCallback* renderer) {
- base::AutoLock auto_lock(sink_lock_);
- CHECK(!renderer_);
- renderer_ = renderer;
-
- DCHECK_EQ(state_, kStopped);
- sink_->Initialize(params, renderer);
-
- // Keep track of the format in case the client hasn't yet been set.
- channels_ = params.channels();
- sample_rate_ = params.sample_rate();
-
- if (!set_format_cb_.is_null())
- base::ResetAndReturn(&set_format_cb_).Run();
-}
-
-void WebAudioSourceProviderImpl::OnSetFormat() {
- base::AutoLock auto_lock(sink_lock_);
- if (!client_)
- return;
-
- // Inform Blink about the audio stream format.
- client_->setFormat(channels_, sample_rate_);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl.h b/chromium/content/renderer/media/webaudiosourceprovider_impl.h
deleted file mode 100644
index aca9d830021..00000000000
--- a/chromium/content/renderer/media/webaudiosourceprovider_impl.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_
-
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "media/base/audio_renderer_sink.h"
-#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-
-namespace blink {
-class WebAudioSourceProviderClient;
-}
-
-namespace content {
-
-// WebAudioSourceProviderImpl provides a bridge between classes:
-// blink::WebAudioSourceProvider <---> media::AudioRendererSink
-//
-// WebAudioSourceProviderImpl wraps an existing audio sink that is used unless
-// WebKit has set a client via setClient(). While a client is set WebKit will
-// periodically call provideInput() to render a certain number of audio
-// sample-frames using the sink's RenderCallback to get the data.
-//
-// All calls are protected by a lock.
-class CONTENT_EXPORT WebAudioSourceProviderImpl
- : NON_EXPORTED_BASE(public blink::WebAudioSourceProvider),
- NON_EXPORTED_BASE(public media::AudioRendererSink) {
- public:
- explicit WebAudioSourceProviderImpl(
- const scoped_refptr<media::AudioRendererSink>& sink);
-
- // blink::WebAudioSourceProvider implementation.
- virtual void setClient(blink::WebAudioSourceProviderClient* client);
- virtual void provideInput(const blink::WebVector<float*>& audio_data,
- size_t number_of_frames);
-
- // media::AudioRendererSink implementation.
- virtual void Start() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void Play() OVERRIDE;
- virtual void Pause() OVERRIDE;
- virtual bool SetVolume(double volume) OVERRIDE;
- virtual void Initialize(const media::AudioParameters& params,
- RenderCallback* renderer) OVERRIDE;
-
- protected:
- virtual ~WebAudioSourceProviderImpl();
-
- private:
- // Calls setFormat() on |client_| from the Blink renderer thread.
- void OnSetFormat();
-
- // Closure that posts a task to call OnSetFormat() on the renderer thread.
- base::Closure set_format_cb_;
-
- // Set to true when Initialize() is called.
- int channels_;
- int sample_rate_;
- double volume_;
-
- // Tracks the current playback state.
- enum PlaybackState { kStopped, kStarted, kPlaying };
- PlaybackState state_;
-
- // Where audio comes from.
- media::AudioRendererSink::RenderCallback* renderer_;
-
- // When set via setClient() it overrides |sink_| for consuming audio.
- blink::WebAudioSourceProviderClient* client_;
-
- // Where audio ends up unless overridden by |client_|.
- base::Lock sink_lock_;
- scoped_refptr<media::AudioRendererSink> sink_;
- scoped_ptr<media::AudioBus> bus_wrapper_;
-
- // NOTE: Weak pointers must be invalidated before all other member variables.
- base::WeakPtrFactory<WebAudioSourceProviderImpl> weak_factory_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(WebAudioSourceProviderImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBAUDIOSOURCEPROVIDER_IMPL_H_
diff --git a/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc b/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc
deleted file mode 100644
index 8a59822debc..00000000000
--- a/chromium/content/renderer/media/webaudiosourceprovider_impl_unittest.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright 2013 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/message_loop.h"
-#include "base/run_loop.h"
-#include "content/renderer/media/webaudiosourceprovider_impl.h"
-#include "media/audio/audio_parameters.h"
-#include "media/base/fake_audio_render_callback.h"
-#include "media/base/mock_audio_renderer_sink.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
-
-namespace content {
-
-namespace {
-const float kTestVolume = 0.25;
-} // namespace
-
-class WebAudioSourceProviderImplTest
- : public testing::Test,
- public blink::WebAudioSourceProviderClient {
- public:
- WebAudioSourceProviderImplTest()
- : params_(media::AudioParameters::AUDIO_PCM_LINEAR,
- media::CHANNEL_LAYOUT_STEREO, 48000, 16, 64),
- fake_callback_(0.1),
- mock_sink_(new media::MockAudioRendererSink()),
- wasp_impl_(new WebAudioSourceProviderImpl(mock_sink_)) {
- }
-
- virtual ~WebAudioSourceProviderImplTest() {}
-
- void CallAllSinkMethodsAndVerify(bool verify) {
- testing::InSequence s;
-
- EXPECT_CALL(*mock_sink_.get(), Start()).Times(verify);
- wasp_impl_->Start();
-
- EXPECT_CALL(*mock_sink_.get(), Play()).Times(verify);
- wasp_impl_->Play();
-
- EXPECT_CALL(*mock_sink_.get(), Pause()).Times(verify);
- wasp_impl_->Pause();
-
- EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume)).Times(verify);
- wasp_impl_->SetVolume(kTestVolume);
-
- EXPECT_CALL(*mock_sink_.get(), Stop()).Times(verify);
- wasp_impl_->Stop();
-
- testing::Mock::VerifyAndClear(mock_sink_.get());
- }
-
- void SetClient(blink::WebAudioSourceProviderClient* client) {
- testing::InSequence s;
-
- if (client) {
- EXPECT_CALL(*mock_sink_.get(), Stop());
- EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
- }
- wasp_impl_->setClient(client);
- base::RunLoop().RunUntilIdle();
-
- testing::Mock::VerifyAndClear(mock_sink_.get());
- testing::Mock::VerifyAndClear(this);
- }
-
- bool CompareBusses(const media::AudioBus* bus1, const media::AudioBus* bus2) {
- EXPECT_EQ(bus1->channels(), bus2->channels());
- EXPECT_EQ(bus1->frames(), bus2->frames());
- for (int ch = 0; ch < bus1->channels(); ++ch) {
- if (memcmp(bus1->channel(ch), bus2->channel(ch),
- sizeof(*bus1->channel(ch)) * bus1->frames()) != 0) {
- return false;
- }
- }
- return true;
- }
-
- // blink::WebAudioSourceProviderClient implementation.
- MOCK_METHOD2(setFormat, void(size_t numberOfChannels, float sampleRate));
-
- protected:
- media::AudioParameters params_;
- media::FakeAudioRenderCallback fake_callback_;
- scoped_refptr<media::MockAudioRendererSink> mock_sink_;
- scoped_refptr<WebAudioSourceProviderImpl> wasp_impl_;
- base::MessageLoop message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(WebAudioSourceProviderImplTest);
-};
-
-TEST_F(WebAudioSourceProviderImplTest, SetClientBeforeInitialize) {
- // setClient() with a NULL client should do nothing if no client is set.
- wasp_impl_->setClient(NULL);
-
- EXPECT_CALL(*mock_sink_.get(), Stop());
- wasp_impl_->setClient(this);
- base::RunLoop().RunUntilIdle();
-
- // When Initialize() is called after setClient(), the params should propagate
- // to the client via setFormat() during the call.
- EXPECT_CALL(*this, setFormat(params_.channels(), params_.sample_rate()));
- wasp_impl_->Initialize(params_, &fake_callback_);
- base::RunLoop().RunUntilIdle();
-
- // setClient() with the same client should do nothing.
- wasp_impl_->setClient(this);
- base::RunLoop().RunUntilIdle();
-}
-
-// Verify AudioRendererSink functionality w/ and w/o a client.
-TEST_F(WebAudioSourceProviderImplTest, SinkMethods) {
- wasp_impl_->Initialize(params_, &fake_callback_);
- ASSERT_EQ(mock_sink_->callback(), &fake_callback_);
-
- // Without a client all WASP calls should fall through to the underlying sink.
- CallAllSinkMethodsAndVerify(true);
-
- // With a client no calls should reach the Stop()'d sink. Also, setClient()
- // should propagate the params provided during Initialize() at call time.
- SetClient(this);
- CallAllSinkMethodsAndVerify(false);
-
- // Removing the client should cause WASP to revert to the underlying sink.
- EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume));
- SetClient(NULL);
- CallAllSinkMethodsAndVerify(true);
-}
-
-// Verify underlying sink state is restored after client removal.
-TEST_F(WebAudioSourceProviderImplTest, SinkStateRestored) {
- wasp_impl_->Initialize(params_, &fake_callback_);
-
- // Verify state set before the client is set propagates back afterward.
- EXPECT_CALL(*mock_sink_.get(), Start());
- wasp_impl_->Start();
- SetClient(this);
-
- EXPECT_CALL(*mock_sink_.get(), SetVolume(1.0));
- EXPECT_CALL(*mock_sink_.get(), Start());
- SetClient(NULL);
-
- // Verify state set while the client was attached propagates back afterward.
- SetClient(this);
- wasp_impl_->Play();
- wasp_impl_->SetVolume(kTestVolume);
-
- EXPECT_CALL(*mock_sink_.get(), SetVolume(kTestVolume));
- EXPECT_CALL(*mock_sink_.get(), Start());
- EXPECT_CALL(*mock_sink_.get(), Play());
- SetClient(NULL);
-}
-
-// Test the AudioRendererSink state machine and its effects on provideInput().
-TEST_F(WebAudioSourceProviderImplTest, ProvideInput) {
- scoped_ptr<media::AudioBus> bus1 = media::AudioBus::Create(params_);
- scoped_ptr<media::AudioBus> bus2 = media::AudioBus::Create(params_);
-
- // Point the WebVector into memory owned by |bus1|.
- blink::WebVector<float*> audio_data(static_cast<size_t>(bus1->channels()));
- for (size_t i = 0; i < audio_data.size(); ++i)
- audio_data[i] = bus1->channel(i);
-
- // Verify provideInput() works before Initialize() and returns silence.
- bus1->channel(0)[0] = 1;
- bus2->Zero();
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
-
- wasp_impl_->Initialize(params_, &fake_callback_);
- SetClient(this);
-
- // Verify provideInput() is muted prior to Start() and no calls to the render
- // callback have occurred.
- bus1->channel(0)[0] = 1;
- bus2->Zero();
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
- ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1);
-
- wasp_impl_->Start();
-
- // Ditto for Play().
- bus1->channel(0)[0] = 1;
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
- ASSERT_EQ(fake_callback_.last_audio_delay_milliseconds(), -1);
-
- wasp_impl_->Play();
-
- // Now we should get real audio data.
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_FALSE(CompareBusses(bus1.get(), bus2.get()));
-
- // Ensure volume adjustment is working.
- fake_callback_.reset();
- fake_callback_.Render(bus2.get(), 0);
- bus2->Scale(kTestVolume);
-
- fake_callback_.reset();
- wasp_impl_->SetVolume(kTestVolume);
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
-
- // Pause should return to silence.
- wasp_impl_->Pause();
- bus1->channel(0)[0] = 1;
- bus2->Zero();
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
-
- // Ensure if a renderer properly fill silence for partial Render() calls by
- // configuring the fake callback to return half the data. After these calls
- // bus1 is full of junk data, and bus2 is partially filled.
- wasp_impl_->SetVolume(1);
- fake_callback_.Render(bus1.get(), 0);
- fake_callback_.reset();
- fake_callback_.Render(bus2.get(), 0);
- bus2->ZeroFramesPartial(bus2->frames() / 2,
- bus2->frames() - bus2->frames() / 2);
- fake_callback_.reset();
- fake_callback_.set_half_fill(true);
- wasp_impl_->Play();
-
- // Play should return real audio data again, but the last half should be zero.
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
-
- // Stop() should return silence.
- wasp_impl_->Stop();
- bus1->channel(0)[0] = 1;
- bus2->Zero();
- wasp_impl_->provideInput(audio_data, params_.frames_per_buffer());
- ASSERT_TRUE(CompareBusses(bus1.get(), bus2.get()));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc
index c1e455e56fe..c2070ba5f03 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc
+++ b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.cc
@@ -4,9 +4,6 @@
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
-#include <map>
-#include <vector>
-
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/logging.h"
@@ -15,30 +12,19 @@
#include "content/renderer/media/cdm_session_adapter.h"
#include "content/renderer/media/crypto/key_systems.h"
#include "content/renderer/media/webcontentdecryptionmodulesession_impl.h"
+#include "media/base/cdm_promise.h"
#include "media/base/media_keys.h"
+#include "media/blink/cdm_result_promise.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "url/gurl.h"
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
-#endif
-
namespace content {
WebContentDecryptionModuleImpl* WebContentDecryptionModuleImpl::Create(
-#if defined(ENABLE_PEPPER_CDMS)
- blink::WebLocalFrame* frame,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
-#endif
+ media::CdmFactory* cdm_factory,
const blink::WebSecurityOrigin& security_origin,
const base::string16& key_system) {
-#if defined(ENABLE_PEPPER_CDMS)
- DCHECK(frame);
-#elif defined(ENABLE_BROWSER_CDMS)
- DCHECK(manager);
-#endif
DCHECK(!security_origin.isNull());
DCHECK(!key_system.empty());
@@ -63,13 +49,7 @@ WebContentDecryptionModuleImpl* WebContentDecryptionModuleImpl::Create(
GURL security_origin_as_gurl(security_origin.toString());
if (!adapter->Initialize(
-#if defined(ENABLE_PEPPER_CDMS)
- base::Bind(&PepperCdmWrapperImpl::Create, frame),
-#elif defined(ENABLE_BROWSER_CDMS)
- manager,
-#endif
- key_system_ascii,
- security_origin_as_gurl)) {
+ cdm_factory, key_system_ascii, security_origin_as_gurl)) {
return NULL;
}
@@ -78,16 +58,36 @@ WebContentDecryptionModuleImpl* WebContentDecryptionModuleImpl::Create(
WebContentDecryptionModuleImpl::WebContentDecryptionModuleImpl(
scoped_refptr<CdmSessionAdapter> adapter)
- : adapter_(adapter) {}
+ : adapter_(adapter) {
+}
WebContentDecryptionModuleImpl::~WebContentDecryptionModuleImpl() {
}
// The caller owns the created session.
blink::WebContentDecryptionModuleSession*
+WebContentDecryptionModuleImpl::createSession() {
+ return adapter_->CreateSession();
+}
+
+blink::WebContentDecryptionModuleSession*
WebContentDecryptionModuleImpl::createSession(
blink::WebContentDecryptionModuleSession::Client* client) {
- return adapter_->CreateSession(client);
+ WebContentDecryptionModuleSessionImpl* session = adapter_->CreateSession();
+ session->setClientInterface(client);
+ return session;
+}
+
+void WebContentDecryptionModuleImpl::setServerCertificate(
+ const uint8* server_certificate,
+ size_t server_certificate_length,
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(server_certificate);
+ adapter_->SetServerCertificate(
+ server_certificate,
+ server_certificate_length,
+ scoped_ptr<media::SimpleCdmPromise>(
+ new media::CdmResultPromise<>(result, std::string())));
}
media::Decryptor* WebContentDecryptionModuleImpl::GetDecryptor() {
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h
index 871ca27f4a9..c535db7f415 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h
+++ b/chromium/content/renderer/media/webcontentdecryptionmodule_impl.h
@@ -5,12 +5,11 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBCONTENTDECRYPTIONMODULE_IMPL_H_
#define CONTENT_RENDERER_MEDIA_WEBCONTENTDECRYPTIONMODULE_IMPL_H_
-#include <string>
-
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h"
+#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
namespace blink {
#if defined(ENABLE_PEPPER_CDMS)
@@ -20,6 +19,7 @@ class WebSecurityOrigin;
}
namespace media {
+class CdmFactory;
class Decryptor;
class MediaKeys;
}
@@ -27,20 +27,13 @@ class MediaKeys;
namespace content {
class CdmSessionAdapter;
-#if defined(ENABLE_BROWSER_CDMS)
-class RendererCdmManager;
-#endif
class WebContentDecryptionModuleSessionImpl;
class WebContentDecryptionModuleImpl
: public blink::WebContentDecryptionModule {
public:
static WebContentDecryptionModuleImpl* Create(
-#if defined(ENABLE_PEPPER_CDMS)
- blink::WebLocalFrame* frame,
-#elif defined(ENABLE_BROWSER_CDMS)
- RendererCdmManager* manager,
-#endif
+ media::CdmFactory* cdm_factory,
const blink::WebSecurityOrigin& security_origin,
const base::string16& key_system);
@@ -59,9 +52,16 @@ class WebContentDecryptionModuleImpl
#endif // defined(ENABLE_BROWSER_CDMS)
// blink::WebContentDecryptionModule implementation.
+ virtual blink::WebContentDecryptionModuleSession* createSession();
+ // TODO(jrummell): Remove this method once blink updated.
virtual blink::WebContentDecryptionModuleSession* createSession(
blink::WebContentDecryptionModuleSession::Client* client);
+ virtual void setServerCertificate(
+ const uint8* server_certificate,
+ size_t server_certificate_length,
+ blink::WebContentDecryptionModuleResult result);
+
private:
// Takes reference to |adapter|.
WebContentDecryptionModuleImpl(scoped_refptr<CdmSessionAdapter> adapter);
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
index 50ebcd09f85..871c31fb3ee 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
+++ b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.cc
@@ -11,15 +11,19 @@
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/cdm_session_adapter.h"
#include "media/base/cdm_promise.h"
+#include "media/base/media_keys.h"
+#include "media/blink/cdm_result_promise.h"
+#include "media/blink/new_session_cdm_result_promise.h"
#include "third_party/WebKit/public/platform/WebURL.h"
namespace content {
+const char kCreateSessionUMAName[] = "CreateSession";
+const char kLoadSessionUMAName[] = "LoadSession";
+
WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
- Client* client,
const scoped_refptr<CdmSessionAdapter>& adapter)
: adapter_(adapter),
- client_(client),
is_closed_(false),
weak_ptr_factory_(this) {
}
@@ -27,7 +31,11 @@ WebContentDecryptionModuleSessionImpl::WebContentDecryptionModuleSessionImpl(
WebContentDecryptionModuleSessionImpl::
~WebContentDecryptionModuleSessionImpl() {
if (!web_session_id_.empty())
- adapter_->RemoveSession(web_session_id_);
+ adapter_->UnregisterSession(web_session_id_);
+}
+
+void WebContentDecryptionModuleSessionImpl::setClientInterface(Client* client) {
+ client_ = client;
}
blink::WebString WebContentDecryptionModuleSessionImpl::sessionId() const {
@@ -38,14 +46,40 @@ void WebContentDecryptionModuleSessionImpl::initializeNewSession(
const blink::WebString& init_data_type,
const uint8* init_data,
size_t init_data_length) {
+ // TODO(jrummell): Remove once blink updated.
+ NOTREACHED();
+}
+
+void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
+ size_t response_length) {
+ // TODO(jrummell): Remove once blink updated.
+ NOTREACHED();
+}
+
+void WebContentDecryptionModuleSessionImpl::release() {
+ // TODO(jrummell): Remove once blink updated.
+ NOTREACHED();
+}
+
+void WebContentDecryptionModuleSessionImpl::initializeNewSession(
+ const blink::WebString& init_data_type,
+ const uint8* init_data,
+ size_t init_data_length,
+ const blink::WebString& session_type,
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(web_session_id_.empty());
+
// TODO(ddorwin): Guard against this in supported types check and remove this.
// Chromium only supports ASCII MIME types.
if (!base::IsStringASCII(init_data_type)) {
NOTREACHED();
- OnSessionError(media::MediaKeys::NOT_SUPPORTED_ERROR,
- 0,
- "The initialization data type " + init_data_type.utf8() +
- " is not supported by the key system.");
+ std::string message = "The initialization data type " +
+ init_data_type.utf8() +
+ " is not supported by the key system.";
+ result.completeWithError(
+ blink::WebContentDecryptionModuleExceptionNotSupportedError,
+ 0,
+ blink::WebString::fromUTF8(message));
return;
}
@@ -54,82 +88,123 @@ void WebContentDecryptionModuleSessionImpl::initializeNewSession(
<< "init_data_type '" << init_data_type_as_ascii
<< "' may be a MIME type";
- scoped_ptr<media::NewSessionCdmPromise> promise(
- new media::NewSessionCdmPromise(
- base::Bind(&WebContentDecryptionModuleSessionImpl::SessionCreated,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
- weak_ptr_factory_.GetWeakPtr())));
- adapter_->InitializeNewSession(init_data_type_as_ascii,
- init_data,
- init_data_length,
- media::MediaKeys::TEMPORARY_SESSION,
- promise.Pass());
+ adapter_->InitializeNewSession(
+ init_data_type_as_ascii,
+ init_data,
+ init_data_length,
+ media::MediaKeys::TEMPORARY_SESSION,
+ scoped_ptr<media::NewSessionCdmPromise>(
+ new media::NewSessionCdmResultPromise(
+ result,
+ adapter_->GetKeySystemUMAPrefix() + kCreateSessionUMAName,
+ base::Bind(
+ &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
+ base::Unretained(this)))));
}
-void WebContentDecryptionModuleSessionImpl::update(const uint8* response,
- size_t response_length) {
+void WebContentDecryptionModuleSessionImpl::load(
+ const blink::WebString& session_id,
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(!session_id.isEmpty());
+ DCHECK(web_session_id_.empty());
+
+ adapter_->LoadSession(
+ base::UTF16ToASCII(session_id),
+ scoped_ptr<media::NewSessionCdmPromise>(
+ new media::NewSessionCdmResultPromise(
+ result,
+ adapter_->GetKeySystemUMAPrefix() + kLoadSessionUMAName,
+ base::Bind(
+ &WebContentDecryptionModuleSessionImpl::OnSessionInitialized,
+ base::Unretained(this)))));
+}
+
+void WebContentDecryptionModuleSessionImpl::update(
+ const uint8* response,
+ size_t response_length,
+ blink::WebContentDecryptionModuleResult result) {
DCHECK(response);
- scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
- base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionReady,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
- weak_ptr_factory_.GetWeakPtr())));
+ DCHECK(!web_session_id_.empty());
adapter_->UpdateSession(
- web_session_id_, response, response_length, promise.Pass());
+ web_session_id_,
+ response,
+ response_length,
+ scoped_ptr<media::SimpleCdmPromise>(
+ new media::CdmResultPromise<>(result, std::string())));
}
-void WebContentDecryptionModuleSessionImpl::release() {
- scoped_ptr<media::SimpleCdmPromise> promise(new media::SimpleCdmPromise(
- base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionClosed,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&WebContentDecryptionModuleSessionImpl::OnSessionError,
- weak_ptr_factory_.GetWeakPtr())));
- adapter_->ReleaseSession(web_session_id_, promise.Pass());
+void WebContentDecryptionModuleSessionImpl::close(
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(!web_session_id_.empty());
+ adapter_->CloseSession(
+ web_session_id_,
+ scoped_ptr<media::SimpleCdmPromise>(
+ new media::CdmResultPromise<>(result, std::string())));
+}
+
+void WebContentDecryptionModuleSessionImpl::remove(
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(!web_session_id_.empty());
+ adapter_->RemoveSession(
+ web_session_id_,
+ scoped_ptr<media::SimpleCdmPromise>(
+ new media::CdmResultPromise<>(result, std::string())));
+}
+
+void WebContentDecryptionModuleSessionImpl::getUsableKeyIds(
+ blink::WebContentDecryptionModuleResult result) {
+ DCHECK(!web_session_id_.empty());
+ adapter_->GetUsableKeyIds(
+ web_session_id_,
+ scoped_ptr<media::KeyIdsPromise>(
+ new media::CdmResultPromise<media::KeyIdsVector>(result,
+ std::string())));
+}
+
+void WebContentDecryptionModuleSessionImpl::release(
+ blink::WebContentDecryptionModuleResult result) {
+ close(result);
}
void WebContentDecryptionModuleSessionImpl::OnSessionMessage(
const std::vector<uint8>& message,
const GURL& destination_url) {
+ DCHECK(client_) << "Client not set before message event";
client_->message(
message.empty() ? NULL : &message[0], message.size(), destination_url);
}
-void WebContentDecryptionModuleSessionImpl::OnSessionReady() {
- client_->ready();
+void WebContentDecryptionModuleSessionImpl::OnSessionKeysChange(
+ bool has_additional_usable_key) {
+ // TODO(jrummell): Update this once Blink client supports this.
}
-void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
- if (!is_closed_) {
- is_closed_ = true;
- client_->close();
- }
+void WebContentDecryptionModuleSessionImpl::OnSessionExpirationUpdate(
+ const base::Time& new_expiry_time) {
+ client_->expirationChanged(new_expiry_time.ToJsTime());
}
-void WebContentDecryptionModuleSessionImpl::OnSessionError(
- media::MediaKeys::Exception exception_code,
- uint32 system_code,
- const std::string& error_message) {
- // Convert |exception_code| back to MediaKeyErrorCode if possible.
- // TODO(jrummell): Update this conversion when promises flow
- // back into blink:: (as blink:: will have its own error definition).
- switch (exception_code) {
- case media::MediaKeys::CLIENT_ERROR:
- client_->error(Client::MediaKeyErrorCodeClient, system_code);
- break;
- default:
- // This will include all other CDM4 errors and any error generated
- // by CDM5 or later.
- client_->error(Client::MediaKeyErrorCodeUnknown, system_code);
- break;
- }
+void WebContentDecryptionModuleSessionImpl::OnSessionClosed() {
+ if (is_closed_)
+ return;
+
+ is_closed_ = true;
+ client_->close();
}
-void WebContentDecryptionModuleSessionImpl::SessionCreated(
+blink::WebContentDecryptionModuleResult::SessionStatus
+WebContentDecryptionModuleSessionImpl::OnSessionInitialized(
const std::string& web_session_id) {
+ // CDM will return NULL if the session to be loaded can't be found.
+ if (web_session_id.empty())
+ return blink::WebContentDecryptionModuleResult::SessionNotFound;
+
DCHECK(web_session_id_.empty()) << "Session ID may not be changed once set.";
web_session_id_ = web_session_id;
- adapter_->RegisterSession(web_session_id_, weak_ptr_factory_.GetWeakPtr());
+ return adapter_->RegisterSession(web_session_id_,
+ weak_ptr_factory_.GetWeakPtr())
+ ? blink::WebContentDecryptionModuleResult::NewSession
+ : blink::WebContentDecryptionModuleResult::SessionAlreadyExists;
}
} // namespace content
diff --git a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h
index f1d889bb09d..c54c2180113 100644
--- a/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h
+++ b/chromium/content/renderer/media/webcontentdecryptionmodulesession_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBCONTENTDECRYPTIONMODULESESSION_IMPL_H_
#define CONTENT_RENDERER_MEDIA_WEBCONTENTDECRYPTIONMODULESESSION_IMPL_H_
+#include <map>
#include <string>
#include <vector>
@@ -27,29 +28,47 @@ class WebContentDecryptionModuleSessionImpl
: public blink::WebContentDecryptionModuleSession {
public:
WebContentDecryptionModuleSessionImpl(
- Client* client,
const scoped_refptr<CdmSessionAdapter>& adapter);
virtual ~WebContentDecryptionModuleSessionImpl();
// blink::WebContentDecryptionModuleSession implementation.
+ virtual void setClientInterface(Client* client);
virtual blink::WebString sessionId() const;
+ // TODO(jrummell): Remove the next 3 methods once blink updated.
virtual void initializeNewSession(const blink::WebString& mime_type,
const uint8* init_data,
size_t init_data_length);
virtual void update(const uint8* response, size_t response_length);
virtual void release();
+ virtual void initializeNewSession(
+ const blink::WebString& init_data_type,
+ const uint8* init_data,
+ size_t init_data_length,
+ const blink::WebString& session_type,
+ blink::WebContentDecryptionModuleResult result);
+ virtual void load(const blink::WebString& session_id,
+ blink::WebContentDecryptionModuleResult result);
+ virtual void update(const uint8* response,
+ size_t response_length,
+ blink::WebContentDecryptionModuleResult result);
+ virtual void close(blink::WebContentDecryptionModuleResult result);
+ virtual void remove(blink::WebContentDecryptionModuleResult result);
+ virtual void getUsableKeyIds(blink::WebContentDecryptionModuleResult result);
+
+ // TODO(jrummell): Remove the next method once blink updated.
+ virtual void release(blink::WebContentDecryptionModuleResult result);
// Callbacks.
void OnSessionMessage(const std::vector<uint8>& message,
const GURL& destination_url);
- void OnSessionReady();
+ void OnSessionKeysChange(bool has_additional_usable_key);
+ void OnSessionExpirationUpdate(const base::Time& new_expiry_time);
void OnSessionClosed();
- void OnSessionError(media::MediaKeys::Exception exception_code,
- uint32 system_code,
- const std::string& error_message);
private:
- void SessionCreated(const std::string& web_session_id);
+ // Called when a new session is created.
+ blink::WebContentDecryptionModuleResult::SessionStatus OnSessionInitialized(
+ const std::string& web_session_id);
scoped_refptr<CdmSessionAdapter> adapter_;
diff --git a/chromium/content/renderer/media/webinbandtexttrack_impl.cc b/chromium/content/renderer/media/webinbandtexttrack_impl.cc
deleted file mode 100644
index e83af8f3451..00000000000
--- a/chromium/content/renderer/media/webinbandtexttrack_impl.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/webinbandtexttrack_impl.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-WebInbandTextTrackImpl::WebInbandTextTrackImpl(
- Kind kind,
- const blink::WebString& label,
- const blink::WebString& language,
- const blink::WebString& id,
- int index)
- : client_(NULL),
- kind_(kind),
- label_(label),
- language_(language),
- id_(id),
- index_(index) {
-}
-
-WebInbandTextTrackImpl::~WebInbandTextTrackImpl() {
- DCHECK(!client_);
-}
-
-void WebInbandTextTrackImpl::setClient(
- blink::WebInbandTextTrackClient* client) {
- client_ = client;
-}
-
-blink::WebInbandTextTrackClient* WebInbandTextTrackImpl::client() {
- return client_;
-}
-
-WebInbandTextTrackImpl::Kind WebInbandTextTrackImpl::kind() const {
- return kind_;
-}
-
-blink::WebString WebInbandTextTrackImpl::label() const {
- return label_;
-}
-
-blink::WebString WebInbandTextTrackImpl::language() const {
- return language_;
-}
-
-blink::WebString WebInbandTextTrackImpl::id() const {
- return id_;
-}
-
-int WebInbandTextTrackImpl::textTrackIndex() const {
- return index_;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webinbandtexttrack_impl.h b/chromium/content/renderer/media/webinbandtexttrack_impl.h
deleted file mode 100644
index 293fbd3fac9..00000000000
--- a/chromium/content/renderer/media/webinbandtexttrack_impl.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_
-
-#include "third_party/WebKit/public/platform/WebInbandTextTrack.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-
-namespace content {
-
-class WebInbandTextTrackImpl : public blink::WebInbandTextTrack {
- public:
- WebInbandTextTrackImpl(Kind kind,
- const blink::WebString& label,
- const blink::WebString& language,
- const blink::WebString& id,
- int index);
- virtual ~WebInbandTextTrackImpl();
-
- virtual void setClient(blink::WebInbandTextTrackClient* client);
- virtual blink::WebInbandTextTrackClient* client();
-
- virtual Kind kind() const;
-
- virtual blink::WebString label() const;
- virtual blink::WebString language() const;
- virtual blink::WebString id() const;
-
- virtual int textTrackIndex() const;
-
- private:
- blink::WebInbandTextTrackClient* client_;
- Kind kind_;
- blink::WebString label_;
- blink::WebString language_;
- blink::WebString id_;
- int index_;
- DISALLOW_COPY_AND_ASSIGN(WebInbandTextTrackImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBINBANDTEXTTRACK_IMPL_H_
diff --git a/chromium/content/renderer/media/webmediaplayer_delegate.h b/chromium/content/renderer/media/webmediaplayer_delegate.h
deleted file mode 100644
index 868abce6407..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_delegate.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_
-#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_
-
-namespace blink {
-class WebMediaPlayer;
-}
-namespace content {
-
-// An interface to allow a WebMediaPlayerImpl to communicate changes of state
-// to objects that need to know.
-class WebMediaPlayerDelegate {
- public:
- WebMediaPlayerDelegate() {}
-
- // The specified player started playing media.
- virtual void DidPlay(blink::WebMediaPlayer* player) = 0;
-
- // The specified player stopped playing media.
- virtual void DidPause(blink::WebMediaPlayer* player) = 0;
-
- // The specified player was destroyed. Do not call any methods on it.
- virtual void PlayerGone(blink::WebMediaPlayer* player) = 0;
-
- protected:
- virtual ~WebMediaPlayerDelegate() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_DELEGATE_H_
diff --git a/chromium/content/renderer/media/webmediaplayer_impl.cc b/chromium/content/renderer/media/webmediaplayer_impl.cc
deleted file mode 100644
index 12153eea808..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_impl.cc
+++ /dev/null
@@ -1,1354 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/webmediaplayer_impl.h"
-
-#include <algorithm>
-#include <limits>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/debug/alias.h"
-#include "base/debug/crash_logging.h"
-#include "base/debug/trace_event.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/metrics/histogram.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "cc/layers/video_layer.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
-#include "content/renderer/media/buffered_data_source.h"
-#include "content/renderer/media/crypto/key_systems.h"
-#include "content/renderer/media/render_media_log.h"
-#include "content/renderer/media/texttrack_impl.h"
-#include "content/renderer/media/webaudiosourceprovider_impl.h"
-#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
-#include "content/renderer/media/webinbandtexttrack_impl.h"
-#include "content/renderer/media/webmediaplayer_delegate.h"
-#include "content/renderer/media/webmediaplayer_params.h"
-#include "content/renderer/media/webmediaplayer_util.h"
-#include "content/renderer/media/webmediasource_impl.h"
-#include "content/renderer/pepper/pepper_webplugin_impl.h"
-#include "content/renderer/render_thread_impl.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "gpu/command_buffer/common/mailbox_holder.h"
-#include "media/audio/null_audio_sink.h"
-#include "media/base/audio_hardware_config.h"
-#include "media/base/bind_to_current_loop.h"
-#include "media/base/filter_collection.h"
-#include "media/base/limits.h"
-#include "media/base/media_log.h"
-#include "media/base/media_switches.h"
-#include "media/base/pipeline.h"
-#include "media/base/text_renderer.h"
-#include "media/base/video_frame.h"
-#include "media/filters/audio_renderer_impl.h"
-#include "media/filters/chunk_demuxer.h"
-#include "media/filters/ffmpeg_audio_decoder.h"
-#include "media/filters/ffmpeg_demuxer.h"
-#include "media/filters/ffmpeg_video_decoder.h"
-#include "media/filters/gpu_video_accelerator_factories.h"
-#include "media/filters/gpu_video_decoder.h"
-#include "media/filters/opus_audio_decoder.h"
-#include "media/filters/video_renderer_impl.h"
-#include "media/filters/vpx_video_decoder.h"
-#include "third_party/WebKit/public/platform/WebContentDecryptionModule.h"
-#include "third_party/WebKit/public/platform/WebMediaSource.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "v8/include/v8.h"
-
-#if defined(ENABLE_PEPPER_CDMS)
-#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
-#endif
-
-using blink::WebCanvas;
-using blink::WebMediaPlayer;
-using blink::WebRect;
-using blink::WebSize;
-using blink::WebString;
-using media::PipelineStatus;
-
-namespace {
-
-// Amount of extra memory used by each player instance reported to V8.
-// It is not exact number -- first, it differs on different platforms,
-// and second, it is very hard to calculate. Instead, use some arbitrary
-// value that will cause garbage collection from time to time. We don't want
-// it to happen on every allocation, but don't want 5k players to sit in memory
-// either. Looks that chosen constant achieves both goals, at least for audio
-// objects. (Do not worry about video objects yet, JS programs do not create
-// thousands of them...)
-const int kPlayerExtraMemory = 1024 * 1024;
-
-// Limits the range of playback rate.
-//
-// TODO(kylep): Revisit these.
-//
-// Vista has substantially lower performance than XP or Windows7. If you speed
-// up a video too much, it can't keep up, and rendering stops updating except on
-// the time bar. For really high speeds, audio becomes a bottleneck and we just
-// use up the data we have, which may not achieve the speed requested, but will
-// not crash the tab.
-//
-// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
-// like a busy loop). It gets unresponsive, although its not completely dead.
-//
-// Also our timers are not very accurate (especially for ogg), which becomes
-// evident at low speeds and on Vista. Since other speeds are risky and outside
-// the norms, we think 1/16x to 16x is a safe and useful range for now.
-const double kMinRate = 0.0625;
-const double kMaxRate = 16.0;
-
-// Prefix for histograms related to Encrypted Media Extensions.
-const char* kMediaEme = "Media.EME.";
-
-} // namespace
-
-namespace content {
-
-class BufferedDataSourceHostImpl;
-
-#define COMPILE_ASSERT_MATCHING_ENUM(name) \
- COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
- static_cast<int>(BufferedResourceLoader::k ## name), \
- mismatching_enums)
-COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
-COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
-COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
-#undef COMPILE_ASSERT_MATCHING_ENUM
-
-#define BIND_TO_RENDER_LOOP(function) \
- (DCHECK(main_loop_->BelongsToCurrentThread()), \
- media::BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
-
-static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
- const std::string& error) {
- media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
-}
-
-WebMediaPlayerImpl::WebMediaPlayerImpl(
- blink::WebLocalFrame* frame,
- blink::WebMediaPlayerClient* client,
- base::WeakPtr<WebMediaPlayerDelegate> delegate,
- const WebMediaPlayerParams& params)
- : frame_(frame),
- network_state_(WebMediaPlayer::NetworkStateEmpty),
- ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
- main_loop_(base::MessageLoopProxy::current()),
- media_loop_(
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()),
- media_log_(new RenderMediaLog()),
- pipeline_(media_loop_, media_log_.get()),
- opaque_(false),
- paused_(true),
- seeking_(false),
- playback_rate_(0.0f),
- pending_seek_(false),
- pending_seek_seconds_(0.0f),
- client_(client),
- delegate_(delegate),
- defer_load_cb_(params.defer_load_cb()),
- accelerated_compositing_reported_(false),
- incremented_externally_allocated_memory_(false),
- gpu_factories_(RenderThreadImpl::current()->GetGpuFactories()),
- supports_save_(true),
- chunk_demuxer_(NULL),
- // Threaded compositing isn't enabled universally yet.
- compositor_task_runner_(
- RenderThreadImpl::current()->compositor_message_loop_proxy()
- ? RenderThreadImpl::current()->compositor_message_loop_proxy()
- : base::MessageLoopProxy::current()),
- compositor_(new VideoFrameCompositor(
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
- text_track_index_(0),
- web_cdm_(NULL) {
- media_log_->AddEvent(
- media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
-
- // |gpu_factories_| requires that its entry points be called on its
- // |GetTaskRunner()|. Since |pipeline_| will own decoders created from the
- // factories, require that their message loops are identical.
- DCHECK(!gpu_factories_ || (gpu_factories_->GetTaskRunner() == media_loop_));
-
- // Let V8 know we started new thread if we did not do it yet.
- // Made separate task to avoid deletion of player currently being created.
- // Also, delaying GC until after player starts gets rid of starting lag --
- // collection happens in parallel with playing.
- //
- // TODO(enal): remove when we get rid of per-audio-stream thread.
- main_loop_->PostTask(
- FROM_HERE,
- base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory,
- AsWeakPtr()));
-
- // Use the null sink if no sink was provided.
- audio_source_provider_ = new WebAudioSourceProviderImpl(
- params.audio_renderer_sink().get()
- ? params.audio_renderer_sink()
- : new media::NullAudioSink(media_loop_));
-}
-
-WebMediaPlayerImpl::~WebMediaPlayerImpl() {
- client_->setWebLayer(NULL);
-
- DCHECK(main_loop_->BelongsToCurrentThread());
- media_log_->AddEvent(
- media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
-
- if (delegate_.get())
- delegate_->PlayerGone(this);
-
- // Abort any pending IO so stopping the pipeline doesn't get blocked.
- if (data_source_)
- data_source_->Abort();
- if (chunk_demuxer_) {
- chunk_demuxer_->Shutdown();
- chunk_demuxer_ = NULL;
- }
-
- gpu_factories_ = NULL;
-
- // Make sure to kill the pipeline so there's no more media threads running.
- // Note: stopping the pipeline might block for a long time.
- base::WaitableEvent waiter(false, false);
- pipeline_.Stop(
- base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
- waiter.Wait();
-
- compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
-
- // Let V8 know we are not using extra resources anymore.
- if (incremented_externally_allocated_memory_) {
- v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
- -kPlayerExtraMemory);
- incremented_externally_allocated_memory_ = false;
- }
-}
-
-void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
- CORSMode cors_mode) {
- DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
- << cors_mode << ")";
- if (!defer_load_cb_.is_null()) {
- defer_load_cb_.Run(base::Bind(
- &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
- return;
- }
- DoLoad(load_type, url, cors_mode);
-}
-
-void WebMediaPlayerImpl::DoLoad(LoadType load_type,
- const blink::WebURL& url,
- CORSMode cors_mode) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- GURL gurl(url);
- ReportMediaSchemeUma(gurl);
-
- // Set subresource URL for crash reporting.
- base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
-
- load_type_ = load_type;
-
- // Handle any volume/preload changes that occurred before load().
- setVolume(client_->volume());
- setPreload(client_->preload());
-
- SetNetworkState(WebMediaPlayer::NetworkStateLoading);
- SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
- media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
-
- // Media source pipelines can start immediately.
- if (load_type == LoadTypeMediaSource) {
- supports_save_ = false;
- StartPipeline();
- return;
- }
-
- // Otherwise it's a regular request which requires resolving the URL first.
- data_source_.reset(new BufferedDataSource(
- url,
- static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
- main_loop_,
- frame_,
- media_log_.get(),
- &buffered_data_source_host_,
- base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
- data_source_->Initialize(
- base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
-}
-
-void WebMediaPlayerImpl::play() {
- DVLOG(1) << __FUNCTION__;
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- paused_ = false;
- pipeline_.SetPlaybackRate(playback_rate_);
- if (data_source_)
- data_source_->MediaIsPlaying();
-
- media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
-
- if (delegate_.get())
- delegate_->DidPlay(this);
-}
-
-void WebMediaPlayerImpl::pause() {
- DVLOG(1) << __FUNCTION__;
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- paused_ = true;
- pipeline_.SetPlaybackRate(0.0f);
- if (data_source_)
- data_source_->MediaIsPaused();
- paused_time_ = pipeline_.GetMediaTime();
-
- media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
-
- if (delegate_.get())
- delegate_->DidPause(this);
-}
-
-bool WebMediaPlayerImpl::supportsSave() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
- return supports_save_;
-}
-
-void WebMediaPlayerImpl::seek(double seconds) {
- DVLOG(1) << __FUNCTION__ << "(" << seconds << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
- SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
-
- base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
-
- if (seeking_) {
- pending_seek_ = true;
- pending_seek_seconds_ = seconds;
- if (chunk_demuxer_)
- chunk_demuxer_->CancelPendingSeek(seek_time);
- return;
- }
-
- media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
-
- // Update our paused time.
- if (paused_)
- paused_time_ = seek_time;
-
- seeking_ = true;
-
- if (chunk_demuxer_)
- chunk_demuxer_->StartWaitingForSeek(seek_time);
-
- // Kick off the asynchronous seek!
- pipeline_.Seek(
- seek_time,
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek));
-}
-
-void WebMediaPlayerImpl::setRate(double rate) {
- DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- // TODO(kylep): Remove when support for negatives is added. Also, modify the
- // following checks so rewind uses reasonable values also.
- if (rate < 0.0)
- return;
-
- // Limit rates to reasonable values by clamping.
- if (rate != 0.0) {
- if (rate < kMinRate)
- rate = kMinRate;
- else if (rate > kMaxRate)
- rate = kMaxRate;
- }
-
- playback_rate_ = rate;
- if (!paused_) {
- pipeline_.SetPlaybackRate(rate);
- if (data_source_)
- data_source_->MediaPlaybackRateChanged(rate);
- }
-}
-
-void WebMediaPlayerImpl::setVolume(double volume) {
- DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- pipeline_.SetVolume(volume);
-}
-
-#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
- COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
- static_cast<int>(content::chromium_name), \
- mismatching_enums)
-COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
-COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
-COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
-#undef COMPILE_ASSERT_MATCHING_ENUM
-
-void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
- DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (data_source_)
- data_source_->SetPreload(static_cast<content::Preload>(preload));
-}
-
-bool WebMediaPlayerImpl::hasVideo() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- return pipeline_metadata_.has_video;
-}
-
-bool WebMediaPlayerImpl::hasAudio() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- return pipeline_metadata_.has_audio;
-}
-
-blink::WebSize WebMediaPlayerImpl::naturalSize() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- return blink::WebSize(pipeline_metadata_.natural_size);
-}
-
-bool WebMediaPlayerImpl::paused() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- return pipeline_.GetPlaybackRate() == 0.0f;
-}
-
-bool WebMediaPlayerImpl::seeking() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
- return false;
-
- return seeking_;
-}
-
-double WebMediaPlayerImpl::duration() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
- return std::numeric_limits<double>::quiet_NaN();
-
- return GetPipelineDuration();
-}
-
-double WebMediaPlayerImpl::timelineOffset() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (pipeline_metadata_.timeline_offset.is_null())
- return std::numeric_limits<double>::quiet_NaN();
-
- return pipeline_metadata_.timeline_offset.ToJsTime();
-}
-
-double WebMediaPlayerImpl::currentTime() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
- return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF();
-}
-
-WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
- return network_state_;
-}
-
-WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
- return ready_state_;
-}
-
-blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
- media::Ranges<base::TimeDelta> buffered_time_ranges =
- pipeline_.GetBufferedTimeRanges();
- buffered_data_source_host_.AddBufferedTimeRanges(
- &buffered_time_ranges, pipeline_.GetMediaDuration());
- return ConvertToWebTimeRanges(buffered_time_ranges);
-}
-
-double WebMediaPlayerImpl::maxTimeSeekable() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- // If we haven't even gotten to ReadyStateHaveMetadata yet then just
- // return 0 so that the seekable range is empty.
- if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
- return 0.0;
-
- // We don't support seeking in streaming media.
- if (data_source_ && data_source_->IsStreaming())
- return 0.0;
- return duration();
-}
-
-bool WebMediaPlayerImpl::didLoadingProgress() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- bool pipeline_progress = pipeline_.DidLoadingProgress();
- bool data_progress = buffered_data_source_host_.DidLoadingProgress();
- return pipeline_progress || data_progress;
-}
-
-void WebMediaPlayerImpl::paint(WebCanvas* canvas,
- const WebRect& rect,
- unsigned char alpha) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
-
- if (!accelerated_compositing_reported_) {
- accelerated_compositing_reported_ = true;
- // Normally paint() is only called in non-accelerated rendering, but there
- // are exceptions such as webgl where compositing is used in the WebView but
- // video frames are still rendered to a canvas.
- UMA_HISTOGRAM_BOOLEAN(
- "Media.AcceleratedCompositingActive",
- frame_->view()->isAcceleratedCompositingActive());
- }
-
- // TODO(scherkus): Clarify paint() API contract to better understand when and
- // why it's being called. For example, today paint() is called when:
- // - We haven't reached HAVE_CURRENT_DATA and need to paint black
- // - We're painting to a canvas
- // See http://crbug.com/341225 http://crbug.com/342621 for details.
- scoped_refptr<media::VideoFrame> video_frame =
- GetCurrentFrameFromCompositor();
-
- gfx::Rect gfx_rect(rect);
- skcanvas_video_renderer_.Paint(video_frame.get(), canvas, gfx_rect, alpha);
-}
-
-bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
- if (data_source_)
- return data_source_->HasSingleOrigin();
- return true;
-}
-
-bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
- if (data_source_)
- return data_source_->DidPassCORSAccessCheck();
- return false;
-}
-
-double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
- return ConvertSecondsToTimestamp(timeValue).InSecondsF();
-}
-
-unsigned WebMediaPlayerImpl::decodedFrameCount() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- media::PipelineStatistics stats = pipeline_.GetStatistics();
- return stats.video_frames_decoded;
-}
-
-unsigned WebMediaPlayerImpl::droppedFrameCount() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- media::PipelineStatistics stats = pipeline_.GetStatistics();
- return stats.video_frames_dropped;
-}
-
-unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- media::PipelineStatistics stats = pipeline_.GetStatistics();
- return stats.audio_bytes_decoded;
-}
-
-unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- media::PipelineStatistics stats = pipeline_.GetStatistics();
- return stats.video_bytes_decoded;
-}
-
-bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
- blink::WebGraphicsContext3D* web_graphics_context,
- unsigned int texture,
- unsigned int level,
- unsigned int internal_format,
- unsigned int type,
- bool premultiply_alpha,
- bool flip_y) {
- TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
-
- scoped_refptr<media::VideoFrame> video_frame =
- GetCurrentFrameFromCompositor();
-
- if (!video_frame)
- return false;
- if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
- return false;
-
- const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
- if (mailbox_holder->texture_target != GL_TEXTURE_2D)
- return false;
-
- // Since this method changes which texture is bound to the TEXTURE_2D target,
- // ideally it would restore the currently-bound texture before returning.
- // The cost of getIntegerv is sufficiently high, however, that we want to
- // avoid it in user builds. As a result assume (below) that |texture| is
- // bound when this method is called, and only verify this fact when
- // DCHECK_IS_ON.
-#if DCHECK_IS_ON
- GLint bound_texture = 0;
- web_graphics_context->getIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture);
- DCHECK_EQ(static_cast<GLuint>(bound_texture), texture);
-#endif
-
- uint32 source_texture = web_graphics_context->createTexture();
-
- web_graphics_context->waitSyncPoint(mailbox_holder->sync_point);
- web_graphics_context->bindTexture(GL_TEXTURE_2D, source_texture);
- web_graphics_context->consumeTextureCHROMIUM(GL_TEXTURE_2D,
- mailbox_holder->mailbox.name);
-
- // The video is stored in a unmultiplied format, so premultiply
- // if necessary.
- web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
- premultiply_alpha);
- // Application itself needs to take care of setting the right flip_y
- // value down to get the expected result.
- // flip_y==true means to reverse the video orientation while
- // flip_y==false means to keep the intrinsic orientation.
- web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
- web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D,
- source_texture,
- texture,
- level,
- internal_format,
- type);
- web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
- web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
- false);
-
- // Restore the state for TEXTURE_2D binding point as mentioned above.
- web_graphics_context->bindTexture(GL_TEXTURE_2D, texture);
-
- web_graphics_context->deleteTexture(source_texture);
- web_graphics_context->flush();
- video_frame->AppendReleaseSyncPoint(web_graphics_context->insertSyncPoint());
- return true;
-}
-
-// Helper functions to report media EME related stats to UMA. They follow the
-// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and
-// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
-// that UMA_* macros require the names to be constant throughout the process'
-// lifetime.
-static void EmeUMAHistogramEnumeration(const std::string& key_system,
- const std::string& method,
- int sample,
- int boundary_value) {
- base::LinearHistogram::FactoryGet(
- kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
- 1, boundary_value, boundary_value + 1,
- base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
-}
-
-static void EmeUMAHistogramCounts(const std::string& key_system,
- const std::string& method,
- int sample) {
- // Use the same parameters as UMA_HISTOGRAM_COUNTS.
- base::Histogram::FactoryGet(
- kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
- 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
-}
-
-// Helper enum for reporting generateKeyRequest/addKey histograms.
-enum MediaKeyException {
- kUnknownResultId,
- kSuccess,
- kKeySystemNotSupported,
- kInvalidPlayerState,
- kMaxMediaKeyException
-};
-
-static MediaKeyException MediaKeyExceptionForUMA(
- WebMediaPlayer::MediaKeyException e) {
- switch (e) {
- case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
- return kKeySystemNotSupported;
- case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
- return kInvalidPlayerState;
- case WebMediaPlayer::MediaKeyExceptionNoError:
- return kSuccess;
- default:
- return kUnknownResultId;
- }
-}
-
-// Helper for converting |key_system| name and exception |e| to a pair of enum
-// values from above, for reporting to UMA.
-static void ReportMediaKeyExceptionToUMA(const std::string& method,
- const std::string& key_system,
- WebMediaPlayer::MediaKeyException e) {
- MediaKeyException result_id = MediaKeyExceptionForUMA(e);
- DCHECK_NE(result_id, kUnknownResultId) << e;
- EmeUMAHistogramEnumeration(
- key_system, method, result_id, kMaxMediaKeyException);
-}
-
-// Convert a WebString to ASCII, falling back on an empty string in the case
-// of a non-ASCII string.
-static std::string ToASCIIOrEmpty(const blink::WebString& string) {
- return base::IsStringASCII(string) ? base::UTF16ToASCII(string)
- : std::string();
-}
-
-WebMediaPlayer::MediaKeyException
-WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
- const unsigned char* init_data,
- unsigned init_data_length) {
- DVLOG(1) << "generateKeyRequest: " << base::string16(key_system) << ": "
- << std::string(reinterpret_cast<const char*>(init_data),
- static_cast<size_t>(init_data_length));
-
- std::string ascii_key_system =
- GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
-
- WebMediaPlayer::MediaKeyException e =
- GenerateKeyRequestInternal(ascii_key_system, init_data, init_data_length);
- ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e);
- return e;
-}
-
-// Guess the type of |init_data|. This is only used to handle some corner cases
-// so we keep it as simple as possible without breaking major use cases.
-static std::string GuessInitDataType(const unsigned char* init_data,
- unsigned init_data_length) {
- // Most WebM files use KeyId of 16 bytes. MP4 init data are always >16 bytes.
- if (init_data_length == 16)
- return "video/webm";
-
- return "video/mp4";
-}
-
-WebMediaPlayer::MediaKeyException
-WebMediaPlayerImpl::GenerateKeyRequestInternal(const std::string& key_system,
- const unsigned char* init_data,
- unsigned init_data_length) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (!IsConcreteSupportedKeySystem(key_system))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- // We do not support run-time switching between key systems for now.
- if (current_key_system_.empty()) {
- if (!proxy_decryptor_) {
- proxy_decryptor_.reset(new ProxyDecryptor(
-#if defined(ENABLE_PEPPER_CDMS)
- // Create() must be called synchronously as |frame_| may not be
- // valid afterwards.
- base::Bind(&PepperCdmWrapperImpl::Create, frame_),
-#elif defined(ENABLE_BROWSER_CDMS)
-#error Browser side CDM in WMPI for prefixed EME API not supported yet.
-#endif
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyAdded),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyError),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyMessage)));
- }
-
- GURL security_origin(frame_->document().securityOrigin().toString());
- if (!proxy_decryptor_->InitializeCDM(key_system, security_origin))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- if (proxy_decryptor_ && !decryptor_ready_cb_.is_null()) {
- base::ResetAndReturn(&decryptor_ready_cb_)
- .Run(proxy_decryptor_->GetDecryptor());
- }
-
- current_key_system_ = key_system;
- } else if (key_system != current_key_system_) {
- return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
- }
-
- std::string init_data_type = init_data_type_;
- if (init_data_type.empty())
- init_data_type = GuessInitDataType(init_data, init_data_length);
-
- // TODO(xhwang): We assume all streams are from the same container (thus have
- // the same "type") for now. In the future, the "type" should be passed down
- // from the application.
- if (!proxy_decryptor_->GenerateKeyRequest(
- init_data_type, init_data, init_data_length)) {
- current_key_system_.clear();
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
- }
-
- return WebMediaPlayer::MediaKeyExceptionNoError;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
- const WebString& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const WebString& session_id) {
- DVLOG(1) << "addKey: " << base::string16(key_system) << ": "
- << std::string(reinterpret_cast<const char*>(key),
- static_cast<size_t>(key_length)) << ", "
- << std::string(reinterpret_cast<const char*>(init_data),
- static_cast<size_t>(init_data_length)) << " ["
- << base::string16(session_id) << "]";
-
- std::string ascii_key_system =
- GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
- std::string ascii_session_id = ToASCIIOrEmpty(session_id);
-
- WebMediaPlayer::MediaKeyException e = AddKeyInternal(ascii_key_system,
- key,
- key_length,
- init_data,
- init_data_length,
- ascii_session_id);
- ReportMediaKeyExceptionToUMA("addKey", ascii_key_system, e);
- return e;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::AddKeyInternal(
- const std::string& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const std::string& session_id) {
- DCHECK(key);
- DCHECK_GT(key_length, 0u);
-
- if (!IsConcreteSupportedKeySystem(key_system))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- if (current_key_system_.empty() || key_system != current_key_system_)
- return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
-
- proxy_decryptor_->AddKey(
- key, key_length, init_data, init_data_length, session_id);
- return WebMediaPlayer::MediaKeyExceptionNoError;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
- const WebString& key_system,
- const WebString& session_id) {
- DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": "
- << " [" << base::string16(session_id) << "]";
-
- std::string ascii_key_system =
- GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
- std::string ascii_session_id = ToASCIIOrEmpty(session_id);
-
- WebMediaPlayer::MediaKeyException e =
- CancelKeyRequestInternal(ascii_key_system, ascii_session_id);
- ReportMediaKeyExceptionToUMA("cancelKeyRequest", ascii_key_system, e);
- return e;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::CancelKeyRequestInternal(
- const std::string& key_system,
- const std::string& session_id) {
- if (!IsConcreteSupportedKeySystem(key_system))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- if (current_key_system_.empty() || key_system != current_key_system_)
- return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
-
- proxy_decryptor_->CancelKeyRequest(session_id);
- return WebMediaPlayer::MediaKeyExceptionNoError;
-}
-
-void WebMediaPlayerImpl::setContentDecryptionModule(
- blink::WebContentDecryptionModule* cdm) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
- if (!cdm)
- return;
-
- web_cdm_ = ToWebContentDecryptionModuleImpl(cdm);
-
- if (web_cdm_ && !decryptor_ready_cb_.is_null())
- base::ResetAndReturn(&decryptor_ready_cb_).Run(web_cdm_->GetDecryptor());
-}
-
-void WebMediaPlayerImpl::InvalidateOnMainThread() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- TRACE_EVENT0("media", "WebMediaPlayerImpl::InvalidateOnMainThread");
-
- client_->repaint();
-}
-
-void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) {
- DVLOG(1) << __FUNCTION__ << "(" << status << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
- seeking_ = false;
- if (pending_seek_) {
- pending_seek_ = false;
- seek(pending_seek_seconds_);
- return;
- }
-
- if (status != media::PIPELINE_OK) {
- OnPipelineError(status);
- return;
- }
-
- // Update our paused time.
- if (paused_)
- paused_time_ = pipeline_.GetMediaTime();
-
- client_->timeChanged();
-}
-
-void WebMediaPlayerImpl::OnPipelineEnded() {
- DVLOG(1) << __FUNCTION__;
- DCHECK(main_loop_->BelongsToCurrentThread());
- client_->timeChanged();
-}
-
-void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- DCHECK_NE(error, media::PIPELINE_OK);
-
- if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
- // Any error that occurs before reaching ReadyStateHaveMetadata should
- // be considered a format error.
- SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
-
- // TODO(scherkus): This should be handled by HTMLMediaElement and controls
- // should know when to invalidate themselves http://crbug.com/337015
- InvalidateOnMainThread();
- return;
- }
-
- SetNetworkState(PipelineErrorToNetworkState(error));
-
- if (error == media::PIPELINE_ERROR_DECRYPT)
- EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1);
-
- // TODO(scherkus): This should be handled by HTMLMediaElement and controls
- // should know when to invalidate themselves http://crbug.com/337015
- InvalidateOnMainThread();
-}
-
-void WebMediaPlayerImpl::OnPipelineMetadata(
- media::PipelineMetadata metadata) {
- DVLOG(1) << __FUNCTION__;
-
- pipeline_metadata_ = metadata;
-
- SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
-
- if (hasVideo()) {
- DCHECK(!video_weblayer_);
- video_weblayer_.reset(
- new WebLayerImpl(cc::VideoLayer::Create(compositor_)));
- video_weblayer_->setOpaque(opaque_);
- client_->setWebLayer(video_weblayer_.get());
- }
-
- // TODO(scherkus): This should be handled by HTMLMediaElement and controls
- // should know when to invalidate themselves http://crbug.com/337015
- InvalidateOnMainThread();
-}
-
-void WebMediaPlayerImpl::OnPipelinePrerollCompleted() {
- DVLOG(1) << __FUNCTION__;
-
- // Only transition to ReadyStateHaveEnoughData if we don't have
- // any pending seeks because the transition can cause Blink to
- // report that the most recent seek has completed.
- if (!pending_seek_) {
- SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
-
- // TODO(scherkus): This should be handled by HTMLMediaElement and controls
- // should know when to invalidate themselves http://crbug.com/337015
- InvalidateOnMainThread();
- }
-}
-
-void WebMediaPlayerImpl::OnDemuxerOpened() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- client_->mediaSourceOpened(new WebMediaSourceImpl(
- chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
-}
-
-void WebMediaPlayerImpl::OnKeyAdded(const std::string& session_id) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
- client_->keyAdded(
- WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
- WebString::fromUTF8(session_id));
-}
-
-void WebMediaPlayerImpl::OnNeedKey(const std::string& type,
- const std::vector<uint8>& init_data) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- // Do not fire NeedKey event if encrypted media is not enabled.
- if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() &&
- !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) {
- return;
- }
-
- UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);
-
- DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_);
- if (init_data_type_.empty())
- init_data_type_ = type;
-
- const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
- client_->keyNeeded(
- WebString::fromUTF8(type), init_data_ptr, init_data.size());
-}
-
-void WebMediaPlayerImpl::OnAddTextTrack(
- const media::TextTrackConfig& config,
- const media::AddTextTrackDoneCB& done_cb) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- const WebInbandTextTrackImpl::Kind web_kind =
- static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
- const blink::WebString web_label =
- blink::WebString::fromUTF8(config.label());
- const blink::WebString web_language =
- blink::WebString::fromUTF8(config.language());
- const blink::WebString web_id =
- blink::WebString::fromUTF8(config.id());
-
- scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
- new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id,
- text_track_index_++));
-
- scoped_ptr<media::TextTrack> text_track(
- new TextTrackImpl(main_loop_, client_, web_inband_text_track.Pass()));
-
- done_cb.Run(text_track.Pass());
-}
-
-void WebMediaPlayerImpl::OnKeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- uint32 system_code) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
- error_code, media::MediaKeys::kMaxKeyError);
-
- unsigned short short_system_code = 0;
- if (system_code > std::numeric_limits<unsigned short>::max()) {
- LOG(WARNING) << "system_code exceeds unsigned short limit.";
- short_system_code = std::numeric_limits<unsigned short>::max();
- } else {
- short_system_code = static_cast<unsigned short>(system_code);
- }
-
- client_->keyError(
- WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
- WebString::fromUTF8(session_id),
- static_cast<blink::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
- short_system_code);
-}
-
-void WebMediaPlayerImpl::OnKeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const GURL& destination_url) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- DCHECK(destination_url.is_empty() || destination_url.is_valid());
-
- client_->keyMessage(
- WebString::fromUTF8(GetPrefixedKeySystemName(current_key_system_)),
- WebString::fromUTF8(session_id),
- message.empty() ? NULL : &message[0],
- message.size(),
- destination_url);
-}
-
-void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (!success) {
- SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
-
- // TODO(scherkus): This should be handled by HTMLMediaElement and controls
- // should know when to invalidate themselves http://crbug.com/337015
- InvalidateOnMainThread();
- return;
- }
-
- StartPipeline();
-}
-
-void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
- if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
- SetNetworkState(WebMediaPlayer::NetworkStateIdle);
- else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
- SetNetworkState(WebMediaPlayer::NetworkStateLoading);
- media_log_->AddEvent(
- media_log_->CreateBooleanEvent(
- media::MediaLogEvent::NETWORK_ACTIVITY_SET,
- "is_downloading_data", is_downloading));
-}
-
-void WebMediaPlayerImpl::StartPipeline() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
-
- // Keep track if this is a MSE or non-MSE playback.
- UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
- (load_type_ == LoadTypeMediaSource));
-
- media::LogCB mse_log_cb;
-
- // Figure out which demuxer to use.
- if (load_type_ != LoadTypeMediaSource) {
- DCHECK(!chunk_demuxer_);
- DCHECK(data_source_);
-
- demuxer_.reset(new media::FFmpegDemuxer(
- media_loop_, data_source_.get(),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
- media_log_));
- } else {
- DCHECK(!chunk_demuxer_);
- DCHECK(!data_source_);
-
- mse_log_cb = base::Bind(&LogMediaSourceError, media_log_);
-
- chunk_demuxer_ = new media::ChunkDemuxer(
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
- mse_log_cb,
- true);
- demuxer_.reset(chunk_demuxer_);
- }
-
- scoped_ptr<media::FilterCollection> filter_collection(
- new media::FilterCollection());
- filter_collection->SetDemuxer(demuxer_.get());
-
- media::SetDecryptorReadyCB set_decryptor_ready_cb =
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetDecryptorReadyCB);
-
- // Create our audio decoders and renderer.
- ScopedVector<media::AudioDecoder> audio_decoders;
- audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_,
- mse_log_cb));
- audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_));
-
- scoped_ptr<media::AudioRenderer> audio_renderer(new media::AudioRendererImpl(
- media_loop_,
- audio_source_provider_.get(),
- audio_decoders.Pass(),
- set_decryptor_ready_cb,
- RenderThreadImpl::current()->GetAudioHardwareConfig()));
- filter_collection->SetAudioRenderer(audio_renderer.Pass());
-
- // Create our video decoders and renderer.
- ScopedVector<media::VideoDecoder> video_decoders;
-
- if (gpu_factories_.get()) {
- video_decoders.push_back(
- new media::GpuVideoDecoder(gpu_factories_, media_log_));
- }
-
-#if !defined(MEDIA_DISABLE_LIBVPX)
- video_decoders.push_back(new media::VpxVideoDecoder(media_loop_));
-#endif // !defined(MEDIA_DISABLE_LIBVPX)
-
- video_decoders.push_back(new media::FFmpegVideoDecoder(media_loop_));
-
- scoped_ptr<media::VideoRenderer> video_renderer(
- new media::VideoRendererImpl(
- media_loop_,
- video_decoders.Pass(),
- set_decryptor_ready_cb,
- base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
- true));
- filter_collection->SetVideoRenderer(video_renderer.Pass());
-
- if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) {
- scoped_ptr<media::TextRenderer> text_renderer(
- new media::TextRenderer(
- media_loop_,
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack)));
-
- filter_collection->SetTextRenderer(text_renderer.Pass());
- }
-
- // ... and we're ready to go!
- seeking_ = true;
- pipeline_.Start(
- filter_collection.Pass(),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelinePrerollCompleted),
- BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged));
-}
-
-void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
- DVLOG(1) << __FUNCTION__ << "(" << state << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
- network_state_ = state;
- // Always notify to ensure client has the latest value.
- client_->networkStateChanged();
-}
-
-void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
- DVLOG(1) << __FUNCTION__ << "(" << state << ")";
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
- data_source_->assume_fully_buffered() &&
- network_state_ == WebMediaPlayer::NetworkStateLoading)
- SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
-
- ready_state_ = state;
- // Always notify to ensure client has the latest value.
- client_->readyStateChanged();
-}
-
-blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
- return audio_source_provider_.get();
-}
-
-void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() {
- DCHECK(main_loop_->BelongsToCurrentThread());
- incremented_externally_allocated_memory_ = true;
- v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
- kPlayerExtraMemory);
-}
-
-double WebMediaPlayerImpl::GetPipelineDuration() const {
- base::TimeDelta duration = pipeline_.GetMediaDuration();
-
- // Return positive infinity if the resource is unbounded.
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
- if (duration == media::kInfiniteDuration())
- return std::numeric_limits<double>::infinity();
-
- return duration.InSecondsF();
-}
-
-void WebMediaPlayerImpl::OnDurationChanged() {
- if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
- return;
-
- client_->durationChanged();
-}
-
-void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
- TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
-
- media_log_->AddEvent(
- media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
- pipeline_metadata_.natural_size = size;
-
- client_->sizeChanged();
-}
-
-void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
- DCHECK(main_loop_->BelongsToCurrentThread());
- DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
-
- opaque_ = opaque;
- if (video_weblayer_)
- video_weblayer_->setOpaque(opaque_);
-}
-
-void WebMediaPlayerImpl::FrameReady(
- const scoped_refptr<media::VideoFrame>& frame) {
- compositor_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&VideoFrameCompositor::UpdateCurrentFrame,
- base::Unretained(compositor_),
- frame));
-}
-
-void WebMediaPlayerImpl::SetDecryptorReadyCB(
- const media::DecryptorReadyCB& decryptor_ready_cb) {
- DCHECK(main_loop_->BelongsToCurrentThread());
-
- // Cancels the previous decryptor request.
- if (decryptor_ready_cb.is_null()) {
- if (!decryptor_ready_cb_.is_null())
- base::ResetAndReturn(&decryptor_ready_cb_).Run(NULL);
- return;
- }
-
- // TODO(xhwang): Support multiple decryptor notification request (e.g. from
- // video and audio). The current implementation is okay for the current
- // media pipeline since we initialize audio and video decoders in sequence.
- // But WebMediaPlayerImpl should not depend on media pipeline's implementation
- // detail.
- DCHECK(decryptor_ready_cb_.is_null());
-
- // Mixed use of prefixed and unprefixed EME APIs is disallowed by Blink.
- DCHECK(!proxy_decryptor_ || !web_cdm_);
-
- if (proxy_decryptor_) {
- decryptor_ready_cb.Run(proxy_decryptor_->GetDecryptor());
- return;
- }
-
- if (web_cdm_) {
- decryptor_ready_cb.Run(web_cdm_->GetDecryptor());
- return;
- }
-
- decryptor_ready_cb_ = decryptor_ready_cb;
-}
-
-static void GetCurrentFrameAndSignal(
- VideoFrameCompositor* compositor,
- scoped_refptr<media::VideoFrame>* video_frame_out,
- base::WaitableEvent* event) {
- TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
- *video_frame_out = compositor->GetCurrentFrame();
- event->Signal();
-}
-
-scoped_refptr<media::VideoFrame>
-WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
- TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
- if (compositor_task_runner_->BelongsToCurrentThread())
- return compositor_->GetCurrentFrame();
-
- // Use a posted task and waitable event instead of a lock otherwise
- // WebGL/Canvas can see different content than what the compositor is seeing.
- scoped_refptr<media::VideoFrame> video_frame;
- base::WaitableEvent event(false, false);
- compositor_task_runner_->PostTask(FROM_HERE,
- base::Bind(&GetCurrentFrameAndSignal,
- base::Unretained(compositor_),
- &video_frame,
- &event));
- event.Wait();
- return video_frame;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webmediaplayer_impl.h b/chromium/content/renderer/media/webmediaplayer_impl.h
deleted file mode 100644
index ad932b885ae..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_impl.h
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread.h"
-#include "content/renderer/media/buffered_data_source_host_impl.h"
-#include "content/renderer/media/crypto/proxy_decryptor.h"
-#include "content/renderer/media/video_frame_compositor.h"
-#include "media/base/audio_renderer_sink.h"
-#include "media/base/decryptor.h"
-// TODO(xhwang): Remove when we remove prefixed EME implementation.
-#include "media/base/media_keys.h"
-#include "media/base/pipeline.h"
-#include "media/base/text_track.h"
-#include "media/filters/skcanvas_video_renderer.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
-#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
-#include "url/gurl.h"
-
-class RenderAudioSourceProvider;
-
-namespace blink {
-class WebContentDecryptionModule;
-class WebLocalFrame;
-}
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace media {
-class ChunkDemuxer;
-class GpuVideoAcceleratorFactories;
-class MediaLog;
-}
-
-
-namespace content {
-class BufferedDataSource;
-class VideoFrameCompositor;
-class WebAudioSourceProviderImpl;
-class WebContentDecryptionModuleImpl;
-class WebLayerImpl;
-class WebMediaPlayerDelegate;
-class WebMediaPlayerParams;
-class WebTextTrackImpl;
-
-// The canonical implementation of blink::WebMediaPlayer that's backed by
-// media::Pipeline. Handles normal resource loading, Media Source, and
-// Encrypted Media.
-class WebMediaPlayerImpl
- : public blink::WebMediaPlayer,
- public base::SupportsWeakPtr<WebMediaPlayerImpl> {
- public:
- // Constructs a WebMediaPlayer implementation using Chromium's media stack.
- // |delegate| may be null.
- WebMediaPlayerImpl(blink::WebLocalFrame* frame,
- blink::WebMediaPlayerClient* client,
- base::WeakPtr<WebMediaPlayerDelegate> delegate,
- const WebMediaPlayerParams& params);
- virtual ~WebMediaPlayerImpl();
-
- virtual void load(LoadType load_type,
- const blink::WebURL& url,
- CORSMode cors_mode);
-
- // Playback controls.
- virtual void play();
- virtual void pause();
- virtual bool supportsSave() const;
- virtual void seek(double seconds);
- virtual void setRate(double rate);
- virtual void setVolume(double volume);
- virtual void setPreload(blink::WebMediaPlayer::Preload preload);
- virtual blink::WebTimeRanges buffered() const;
- virtual double maxTimeSeekable() const;
-
- // Methods for painting.
- virtual void paint(blink::WebCanvas* canvas,
- const blink::WebRect& rect,
- unsigned char alpha);
-
- // True if the loaded media has a playable video/audio track.
- virtual bool hasVideo() const;
- virtual bool hasAudio() const;
-
- // Dimensions of the video.
- virtual blink::WebSize naturalSize() const;
-
- // Getters of playback state.
- virtual bool paused() const;
- virtual bool seeking() const;
- virtual double duration() const;
- virtual double timelineOffset() const;
- virtual double currentTime() const;
-
- // Internal states of loading and network.
- // TODO(hclam): Ask the pipeline about the state rather than having reading
- // them from members which would cause race conditions.
- virtual blink::WebMediaPlayer::NetworkState networkState() const;
- virtual blink::WebMediaPlayer::ReadyState readyState() const;
-
- virtual bool didLoadingProgress();
-
- virtual bool hasSingleSecurityOrigin() const;
- virtual bool didPassCORSAccessCheck() const;
-
- virtual double mediaTimeForTimeValue(double timeValue) const;
-
- virtual unsigned decodedFrameCount() const;
- virtual unsigned droppedFrameCount() const;
- virtual unsigned audioDecodedByteCount() const;
- virtual unsigned videoDecodedByteCount() const;
-
- virtual bool copyVideoTextureToPlatformTexture(
- blink::WebGraphicsContext3D* web_graphics_context,
- unsigned int texture,
- unsigned int level,
- unsigned int internal_format,
- unsigned int type,
- bool premultiply_alpha,
- bool flip_y);
-
- virtual blink::WebAudioSourceProvider* audioSourceProvider();
-
- virtual MediaKeyException generateKeyRequest(
- const blink::WebString& key_system,
- const unsigned char* init_data,
- unsigned init_data_length);
-
- virtual MediaKeyException addKey(const blink::WebString& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const blink::WebString& session_id);
-
- virtual MediaKeyException cancelKeyRequest(
- const blink::WebString& key_system,
- const blink::WebString& session_id);
-
- virtual void setContentDecryptionModule(
- blink::WebContentDecryptionModule* cdm);
-
- // Notifies blink that the entire media element region has been invalidated.
- // This path is slower than notifying the compositor directly as it performs
- // more work and can trigger layouts. It should only be used in two cases:
- // 1) Major state changes (e.g., first frame available, run time error
- // occured)
- // 2) Compositing not available
- void InvalidateOnMainThread();
-
- void OnPipelineSeek(media::PipelineStatus status);
- void OnPipelineEnded();
- void OnPipelineError(media::PipelineStatus error);
- void OnPipelineMetadata(media::PipelineMetadata metadata);
- void OnPipelinePrerollCompleted();
- void OnDemuxerOpened();
- void OnKeyAdded(const std::string& session_id);
- void OnKeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- uint32 system_code);
- void OnKeyMessage(const std::string& session_id,
- const std::vector<uint8>& message,
- const GURL& destination_url);
- void OnNeedKey(const std::string& type,
- const std::vector<uint8>& init_data);
- void OnAddTextTrack(const media::TextTrackConfig& config,
- const media::AddTextTrackDoneCB& done_cb);
-
- private:
- // Called after |defer_load_cb_| has decided to allow the load. If
- // |defer_load_cb_| is null this is called immediately.
- void DoLoad(LoadType load_type,
- const blink::WebURL& url,
- CORSMode cors_mode);
-
- // Called after asynchronous initialization of a data source completed.
- void DataSourceInitialized(bool success);
-
- // Called when the data source is downloading or paused.
- void NotifyDownloading(bool is_downloading);
-
- // Finishes starting the pipeline due to a call to load().
- void StartPipeline();
-
- // Helpers that set the network/ready state and notifies the client if
- // they've changed.
- void SetNetworkState(blink::WebMediaPlayer::NetworkState state);
- void SetReadyState(blink::WebMediaPlayer::ReadyState state);
-
- // Lets V8 know that player uses extra resources not managed by V8.
- void IncrementExternallyAllocatedMemory();
-
- // Actually do the work for generateKeyRequest/addKey so they can easily
- // report results to UMA.
- MediaKeyException GenerateKeyRequestInternal(const std::string& key_system,
- const unsigned char* init_data,
- unsigned init_data_length);
- MediaKeyException AddKeyInternal(const std::string& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const std::string& session_id);
- MediaKeyException CancelKeyRequestInternal(const std::string& key_system,
- const std::string& session_id);
-
- // Gets the duration value reported by the pipeline.
- double GetPipelineDuration() const;
-
- // Callbacks from |pipeline_| that are forwarded to |client_|.
- void OnDurationChanged();
- void OnNaturalSizeChanged(gfx::Size size);
- void OnOpacityChanged(bool opaque);
-
- // Called by VideoRendererImpl on its internal thread with the new frame to be
- // painted.
- void FrameReady(const scoped_refptr<media::VideoFrame>& frame);
-
- // Requests that this object notifies when a decryptor is ready through the
- // |decryptor_ready_cb| provided.
- // If |decryptor_ready_cb| is null, the existing callback will be fired with
- // NULL immediately and reset.
- void SetDecryptorReadyCB(const media::DecryptorReadyCB& decryptor_ready_cb);
-
- // Returns the current video frame from |compositor_|. Blocks until the
- // compositor can return the frame.
- scoped_refptr<media::VideoFrame> GetCurrentFrameFromCompositor();
-
- blink::WebLocalFrame* frame_;
-
- // TODO(hclam): get rid of these members and read from the pipeline directly.
- blink::WebMediaPlayer::NetworkState network_state_;
- blink::WebMediaPlayer::ReadyState ready_state_;
-
- // Message loops for posting tasks on Chrome's main thread. Also used
- // for DCHECKs so methods calls won't execute in the wrong thread.
- const scoped_refptr<base::MessageLoopProxy> main_loop_;
-
- scoped_refptr<base::MessageLoopProxy> media_loop_;
- scoped_refptr<media::MediaLog> media_log_;
- media::Pipeline pipeline_;
-
- // The currently selected key system. Empty string means that no key system
- // has been selected.
- std::string current_key_system_;
-
- // The LoadType passed in the |load_type| parameter of the load() call.
- LoadType load_type_;
-
- // Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize().
- media::PipelineMetadata pipeline_metadata_;
-
- // Whether the video is known to be opaque or not.
- bool opaque_;
-
- // Playback state.
- //
- // TODO(scherkus): we have these because Pipeline favours the simplicity of a
- // single "playback rate" over worrying about paused/stopped etc... It forces
- // all clients to manage the pause+playback rate externally, but is that
- // really a bad thing?
- //
- // TODO(scherkus): since SetPlaybackRate(0) is asynchronous and we don't want
- // to hang the render thread during pause(), we record the time at the same
- // time we pause and then return that value in currentTime(). Otherwise our
- // clock can creep forward a little bit while the asynchronous
- // SetPlaybackRate(0) is being executed.
- bool paused_;
- bool seeking_;
- double playback_rate_;
- base::TimeDelta paused_time_;
-
- // Seek gets pending if another seek is in progress. Only last pending seek
- // will have effect.
- bool pending_seek_;
- double pending_seek_seconds_;
-
- blink::WebMediaPlayerClient* client_;
-
- base::WeakPtr<WebMediaPlayerDelegate> delegate_;
-
- base::Callback<void(const base::Closure&)> defer_load_cb_;
-
- // Since accelerated compositing status is only known after the first layout,
- // we delay reporting it to UMA until that time.
- bool accelerated_compositing_reported_;
-
- bool incremented_externally_allocated_memory_;
-
- // Factories for supporting video accelerators. May be null.
- scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories_;
-
- // Routes audio playback to either AudioRendererSink or WebAudio.
- scoped_refptr<WebAudioSourceProviderImpl> audio_source_provider_;
-
- bool supports_save_;
-
- // These two are mutually exclusive:
- // |data_source_| is used for regular resource loads.
- // |chunk_demuxer_| is used for Media Source resource loads.
- //
- // |demuxer_| will contain the appropriate demuxer based on which resource
- // load strategy we're using.
- scoped_ptr<BufferedDataSource> data_source_;
- scoped_ptr<media::Demuxer> demuxer_;
- media::ChunkDemuxer* chunk_demuxer_;
-
- BufferedDataSourceHostImpl buffered_data_source_host_;
-
- // Temporary for EME v0.1. In the future the init data type should be passed
- // through GenerateKeyRequest() directly from WebKit.
- std::string init_data_type_;
-
- // Video rendering members.
- scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
- VideoFrameCompositor* compositor_; // Deleted on |compositor_task_runner_|.
- media::SkCanvasVideoRenderer skcanvas_video_renderer_;
-
- // The compositor layer for displaying the video content when using composited
- // playback.
- scoped_ptr<WebLayerImpl> video_weblayer_;
-
- // Text track objects get a unique index value when they're created.
- int text_track_index_;
-
- // Manages decryption keys and decrypts encrypted frames.
- scoped_ptr<ProxyDecryptor> proxy_decryptor_;
-
- // Non-owned pointer to the CDM. Updated via calls to
- // setContentDecryptionModule().
- WebContentDecryptionModuleImpl* web_cdm_;
-
- media::DecryptorReadyCB decryptor_ready_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_IMPL_H_
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.cc b/chromium/content/renderer/media/webmediaplayer_ms.cc
index b466d3168aa..83f082ad07e 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms.cc
@@ -10,18 +10,19 @@
#include "base/callback.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/layers/video_layer.h"
#include "content/public/renderer/render_view.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/media/media_stream_audio_renderer.h"
#include "content/renderer/media/media_stream_renderer_factory.h"
#include "content/renderer/media/video_frame_provider.h"
-#include "content/renderer/media/webmediaplayer_delegate.h"
-#include "content/renderer/media/webmediaplayer_util.h"
#include "content/renderer/render_frame_impl.h"
#include "media/base/media_log.h"
#include "media/base/video_frame.h"
+#include "media/base/video_rotation.h"
#include "media/base/video_util.h"
+#include "media/blink/webmediaplayer_delegate.h"
+#include "media/blink/webmediaplayer_util.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -80,13 +81,14 @@ namespace content {
WebMediaPlayerMS::WebMediaPlayerMS(
blink::WebFrame* frame,
blink::WebMediaPlayerClient* client,
- base::WeakPtr<WebMediaPlayerDelegate> delegate,
+ base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
media::MediaLog* media_log,
scoped_ptr<MediaStreamRendererFactory> factory)
: frame_(frame),
network_state_(WebMediaPlayer::NetworkStateEmpty),
ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
buffered_(static_cast<size_t>(1)),
+ volume_(1.0f),
client_(client),
delegate_(delegate),
paused_(true),
@@ -135,7 +137,6 @@ void WebMediaPlayerMS::load(LoadType load_type,
GURL gurl(url);
- setVolume(GetClient()->volume());
SetNetworkState(WebMediaPlayer::NetworkStateLoading);
SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
@@ -152,8 +153,10 @@ void WebMediaPlayerMS::load(LoadType load_type,
frame->GetRoutingID());
if (video_frame_provider_.get() || audio_renderer_.get()) {
- if (audio_renderer_.get())
+ if (audio_renderer_.get()) {
+ audio_renderer_->SetVolume(volume_);
audio_renderer_->Start();
+ }
if (video_frame_provider_.get()) {
video_frame_provider_->Start();
@@ -207,7 +210,7 @@ void WebMediaPlayerMS::pause() {
media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
- if (!current_frame_)
+ if (!current_frame_.get())
return;
// Copy the frame so that rendering can show the last received frame.
@@ -234,10 +237,10 @@ void WebMediaPlayerMS::setRate(double rate) {
void WebMediaPlayerMS::setVolume(double volume) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!audio_renderer_.get())
- return;
DVLOG(1) << "WebMediaPlayerMS::setVolume(volume=" << volume << ")";
- audio_renderer_->SetVolume(volume);
+ volume_ = volume;
+ if (audio_renderer_.get())
+ audio_renderer_->SetVolume(volume_);
}
void WebMediaPlayerMS::setPreload(WebMediaPlayer::Preload preload) {
@@ -306,9 +309,9 @@ blink::WebTimeRanges WebMediaPlayerMS::buffered() const {
return buffered_;
}
-double WebMediaPlayerMS::maxTimeSeekable() const {
+blink::WebTimeRanges WebMediaPlayerMS::seekable() const {
DCHECK(thread_checker_.CalledOnValidThread());
- return 0.0;
+ return blink::WebTimeRanges();
}
bool WebMediaPlayerMS::didLoadingProgress() {
@@ -316,14 +319,16 @@ bool WebMediaPlayerMS::didLoadingProgress() {
return true;
}
-void WebMediaPlayerMS::paint(WebCanvas* canvas,
- const WebRect& rect,
- unsigned char alpha) {
+void WebMediaPlayerMS::paint(blink::WebCanvas* canvas,
+ const blink::WebRect& rect,
+ unsigned char alpha,
+ SkXfermode::Mode mode) {
DVLOG(3) << "WebMediaPlayerMS::paint";
DCHECK(thread_checker_.CalledOnValidThread());
gfx::RectF dest_rect(rect.x, rect.y, rect.width, rect.height);
- video_renderer_.Paint(current_frame_.get(), canvas, dest_rect, alpha);
+ video_renderer_.Paint(
+ current_frame_, canvas, dest_rect, alpha, mode, media::VIDEO_ROTATION_0);
{
base::AutoLock auto_lock(current_frame_lock_);
@@ -343,7 +348,7 @@ bool WebMediaPlayerMS::didPassCORSAccessCheck() const {
}
double WebMediaPlayerMS::mediaTimeForTimeValue(double timeValue) const {
- return ConvertSecondsToTimestamp(timeValue).InSecondsF();
+ return media::ConvertSecondsToTimestamp(timeValue).InSecondsF();
}
unsigned WebMediaPlayerMS::decodedFrameCount() const {
@@ -413,8 +418,9 @@ void WebMediaPlayerMS::OnFrameAvailable(
SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
GetClient()->sizeChanged();
- if (video_frame_provider_) {
- video_weblayer_.reset(new WebLayerImpl(cc::VideoLayer::Create(this)));
+ if (video_frame_provider_.get()) {
+ video_weblayer_.reset(new cc_blink::WebLayerImpl(
+ cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0)));
video_weblayer_->setOpaque(true);
GetClient()->setWebLayer(video_weblayer_.get());
}
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.h b/chromium/content/renderer/media/webmediaplayer_ms.h
index 7e8944ad920..38667777dc9 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/webmediaplayer_ms.h
@@ -23,15 +23,17 @@ class WebMediaPlayerClient;
namespace media {
class MediaLog;
+class WebMediaPlayerDelegate;
}
+namespace cc_blink {
+class WebLayerImpl;
+}
namespace content {
class MediaStreamAudioRenderer;
class MediaStreamRendererFactory;
class VideoFrameProvider;
-class WebLayerImpl;
-class WebMediaPlayerDelegate;
// WebMediaPlayerMS delegates calls from WebCore::MediaPlayerPrivate to
// Chrome's media player when "src" is from media stream.
@@ -56,7 +58,7 @@ class WebMediaPlayerMS
// a MediaStreamClient which provides VideoFrameProvider.
WebMediaPlayerMS(blink::WebFrame* frame,
blink::WebMediaPlayerClient* client,
- base::WeakPtr<WebMediaPlayerDelegate> delegate,
+ base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
media::MediaLog* media_log,
scoped_ptr<MediaStreamRendererFactory> factory);
virtual ~WebMediaPlayerMS();
@@ -74,12 +76,13 @@ class WebMediaPlayerMS
virtual void setVolume(double volume);
virtual void setPreload(blink::WebMediaPlayer::Preload preload);
virtual blink::WebTimeRanges buffered() const;
- virtual double maxTimeSeekable() const;
+ virtual blink::WebTimeRanges seekable() const;
// Methods for painting.
virtual void paint(blink::WebCanvas* canvas,
const blink::WebRect& rect,
- unsigned char alpha);
+ unsigned char alpha,
+ SkXfermode::Mode mode);
// True if the loaded media has a playable video/audio track.
virtual bool hasVideo() const;
@@ -111,11 +114,10 @@ class WebMediaPlayerMS
virtual unsigned videoDecodedByteCount() const;
// VideoFrameProvider implementation.
- virtual void SetVideoFrameProviderClient(
- cc::VideoFrameProvider::Client* client) OVERRIDE;
- virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
- virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
- OVERRIDE;
+ void SetVideoFrameProviderClient(
+ cc::VideoFrameProvider::Client* client) override;
+ scoped_refptr<media::VideoFrame> GetCurrentFrame() override;
+ void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) override;
private:
// The callback for VideoFrameProvider to signal a new frame is available.
@@ -141,12 +143,14 @@ class WebMediaPlayerMS
blink::WebTimeRanges buffered_;
+ float volume_;
+
// Used for DCHECKs to ensure methods calls executed in the correct thread.
base::ThreadChecker thread_checker_;
blink::WebMediaPlayerClient* client_;
- base::WeakPtr<WebMediaPlayerDelegate> delegate_;
+ base::WeakPtr<media::WebMediaPlayerDelegate> delegate_;
// Specify content:: to disambiguate from cc::.
scoped_refptr<content::VideoFrameProvider> video_frame_provider_;
@@ -166,7 +170,7 @@ class WebMediaPlayerMS
base::Lock current_frame_lock_;
bool pending_repaint_;
- scoped_ptr<WebLayerImpl> video_weblayer_;
+ scoped_ptr<cc_blink::WebLayerImpl> video_weblayer_;
// A pointer back to the compositor to inform it about state changes. This is
// not NULL while the compositor is actively using this webmediaplayer.
diff --git a/chromium/content/renderer/media/webmediaplayer_params.cc b/chromium/content/renderer/media/webmediaplayer_params.cc
deleted file mode 100644
index ddcd21341a3..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_params.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/webmediaplayer_params.h"
-
-#include "media/base/audio_renderer_sink.h"
-
-namespace content {
-
-WebMediaPlayerParams::WebMediaPlayerParams(
- const base::Callback<void(const base::Closure&)>& defer_load_cb,
- const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink)
- : defer_load_cb_(defer_load_cb),
- audio_renderer_sink_(audio_renderer_sink) {
-}
-
-WebMediaPlayerParams::~WebMediaPlayerParams() {}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webmediaplayer_params.h b/chromium/content/renderer/media/webmediaplayer_params.h
deleted file mode 100644
index 9fa96e1af26..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_params.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_
-#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-
-namespace media {
-class AudioRendererSink;
-}
-
-namespace content {
-
-// Holds parameters for constructing WebMediaPlayerImpl without having
-// to plumb arguments through various abstraction layers.
-class WebMediaPlayerParams {
- public:
- // Parameters may be null.
- WebMediaPlayerParams(
- const base::Callback<void(const base::Closure&)>& defer_load_cb,
- const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink);
- ~WebMediaPlayerParams();
-
- base::Callback<void(const base::Closure&)> defer_load_cb() const {
- return defer_load_cb_;
- }
-
- const scoped_refptr<media::AudioRendererSink>& audio_renderer_sink() const {
- return audio_renderer_sink_;
- }
-
- private:
- base::Callback<void(const base::Closure&)> defer_load_cb_;
- scoped_refptr<media::AudioRendererSink> audio_renderer_sink_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(WebMediaPlayerParams);
-};
-
-} // namespace media
-
-#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_PARAMS_H_
diff --git a/chromium/content/renderer/media/webmediaplayer_util.cc b/chromium/content/renderer/media/webmediaplayer_util.cc
deleted file mode 100644
index 6d1b1e25aa8..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_util.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/webmediaplayer_util.h"
-
-#include <math.h>
-
-#include "base/metrics/histogram.h"
-#include "media/base/media_keys.h"
-#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
-
-namespace content {
-
-// Compile asserts shared by all platforms.
-
-#define COMPILE_ASSERT_MATCHING_ENUM(name) \
- COMPILE_ASSERT( \
- static_cast<int>(blink::WebMediaPlayerClient::MediaKeyErrorCode ## name) == \
- static_cast<int>(media::MediaKeys::k ## name ## Error), \
- mismatching_enums)
-COMPILE_ASSERT_MATCHING_ENUM(Unknown);
-COMPILE_ASSERT_MATCHING_ENUM(Client);
-#undef COMPILE_ASSERT_MATCHING_ENUM
-
-base::TimeDelta ConvertSecondsToTimestamp(double seconds) {
- double microseconds = seconds * base::Time::kMicrosecondsPerSecond;
- return base::TimeDelta::FromMicroseconds(
- microseconds > 0 ? microseconds + 0.5 : ceil(microseconds - 0.5));
-}
-
-blink::WebTimeRanges ConvertToWebTimeRanges(
- const media::Ranges<base::TimeDelta>& ranges) {
- blink::WebTimeRanges result(ranges.size());
- for (size_t i = 0; i < ranges.size(); ++i) {
- result[i].start = ranges.start(i).InSecondsF();
- result[i].end = ranges.end(i).InSecondsF();
- }
- return result;
-}
-
-blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
- media::PipelineStatus error) {
- DCHECK_NE(error, media::PIPELINE_OK);
-
- switch (error) {
- case media::PIPELINE_ERROR_NETWORK:
- case media::PIPELINE_ERROR_READ:
- return blink::WebMediaPlayer::NetworkStateNetworkError;
-
- // TODO(vrk): Because OnPipelineInitialize() directly reports the
- // NetworkStateFormatError instead of calling OnPipelineError(), I believe
- // this block can be deleted. Should look into it! (crbug.com/126070)
- case media::PIPELINE_ERROR_INITIALIZATION_FAILED:
- case media::PIPELINE_ERROR_COULD_NOT_RENDER:
- case media::PIPELINE_ERROR_URL_NOT_FOUND:
- case media::DEMUXER_ERROR_COULD_NOT_OPEN:
- case media::DEMUXER_ERROR_COULD_NOT_PARSE:
- case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
- case media::DECODER_ERROR_NOT_SUPPORTED:
- return blink::WebMediaPlayer::NetworkStateFormatError;
-
- case media::PIPELINE_ERROR_DECODE:
- case media::PIPELINE_ERROR_ABORT:
- case media::PIPELINE_ERROR_OPERATION_PENDING:
- case media::PIPELINE_ERROR_INVALID_STATE:
- return blink::WebMediaPlayer::NetworkStateDecodeError;
-
- case media::PIPELINE_ERROR_DECRYPT:
- // TODO(xhwang): Change to use NetworkStateDecryptError once it's added in
- // Webkit (see http://crbug.com/124486).
- return blink::WebMediaPlayer::NetworkStateDecodeError;
-
- case media::PIPELINE_OK:
- NOTREACHED() << "Unexpected status! " << error;
- }
- return blink::WebMediaPlayer::NetworkStateFormatError;
-}
-
-namespace {
-
-// Helper enum for reporting scheme histograms.
-enum URLSchemeForHistogram {
- kUnknownURLScheme,
- kMissingURLScheme,
- kHttpURLScheme,
- kHttpsURLScheme,
- kFtpURLScheme,
- kChromeExtensionURLScheme,
- kJavascriptURLScheme,
- kFileURLScheme,
- kBlobURLScheme,
- kDataURLScheme,
- kFileSystemScheme,
- kMaxURLScheme = kFileSystemScheme // Must be equal to highest enum value.
-};
-
-URLSchemeForHistogram URLScheme(const GURL& url) {
- if (!url.has_scheme()) return kMissingURLScheme;
- if (url.SchemeIs("http")) return kHttpURLScheme;
- if (url.SchemeIs("https")) return kHttpsURLScheme;
- if (url.SchemeIs("ftp")) return kFtpURLScheme;
- if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme;
- if (url.SchemeIs("javascript")) return kJavascriptURLScheme;
- if (url.SchemeIs("file")) return kFileURLScheme;
- if (url.SchemeIs("blob")) return kBlobURLScheme;
- if (url.SchemeIs("data")) return kDataURLScheme;
- if (url.SchemeIs("filesystem")) return kFileSystemScheme;
-
- return kUnknownURLScheme;
-}
-
-} // namespace
-
-void ReportMediaSchemeUma(const GURL& url) {
- UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webmediaplayer_util.h b/chromium/content/renderer/media/webmediaplayer_util.h
deleted file mode 100644
index d401c39089c..00000000000
--- a/chromium/content/renderer/media/webmediaplayer_util.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_UTIL_H_
-#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_UTIL_H_
-
-#include "base/time/time.h"
-#include "media/base/pipeline_status.h"
-#include "media/base/ranges.h"
-#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
-#include "third_party/WebKit/public/platform/WebTimeRange.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// Platform independent method for converting and rounding floating point
-// seconds to an int64 timestamp.
-//
-// Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details.
-base::TimeDelta ConvertSecondsToTimestamp(double seconds);
-
-blink::WebTimeRanges ConvertToWebTimeRanges(
- const media::Ranges<base::TimeDelta>& ranges);
-
-blink::WebMediaPlayer::NetworkState PipelineErrorToNetworkState(
- media::PipelineStatus error);
-
-// Report the scheme of Media URIs.
-void ReportMediaSchemeUma(const GURL& url);
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_UTIL_H_
diff --git a/chromium/content/renderer/media/webmediasource_impl.cc b/chromium/content/renderer/media/webmediasource_impl.cc
deleted file mode 100644
index b3078f7edcd..00000000000
--- a/chromium/content/renderer/media/webmediasource_impl.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/webmediasource_impl.h"
-
-#include "base/guid.h"
-#include "content/renderer/media/websourcebuffer_impl.h"
-#include "media/filters/chunk_demuxer.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-
-using ::blink::WebString;
-using ::blink::WebMediaSource;
-
-namespace content {
-
-#define COMPILE_ASSERT_MATCHING_STATUS_ENUM(webkit_name, chromium_name) \
- COMPILE_ASSERT(static_cast<int>(WebMediaSource::webkit_name) == \
- static_cast<int>(media::ChunkDemuxer::chromium_name), \
- mismatching_status_enums)
-COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddStatusOk, kOk);
-COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddStatusNotSupported, kNotSupported);
-COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddStatusReachedIdLimit, kReachedIdLimit);
-#undef COMPILE_ASSERT_MATCHING_STATUS_ENUM
-
-WebMediaSourceImpl::WebMediaSourceImpl(
- media::ChunkDemuxer* demuxer, media::LogCB log_cb)
- : demuxer_(demuxer),
- log_cb_(log_cb) {
- DCHECK(demuxer_);
-}
-
-WebMediaSourceImpl::~WebMediaSourceImpl() {}
-
-WebMediaSource::AddStatus WebMediaSourceImpl::addSourceBuffer(
- const blink::WebString& type,
- const blink::WebVector<blink::WebString>& codecs,
- blink::WebSourceBuffer** source_buffer) {
- std::string id = base::GenerateGUID();
- std::vector<std::string> new_codecs(codecs.size());
- for (size_t i = 0; i < codecs.size(); ++i)
- new_codecs[i] = codecs[i].utf8().data();
-
- WebMediaSource::AddStatus result =
- static_cast<WebMediaSource::AddStatus>(
- demuxer_->AddId(id, type.utf8().data(), new_codecs));
-
- if (result == WebMediaSource::AddStatusOk)
- *source_buffer = new WebSourceBufferImpl(id, demuxer_);
-
- return result;
-}
-
-double WebMediaSourceImpl::duration() {
- return demuxer_->GetDuration();
-}
-
-void WebMediaSourceImpl::setDuration(double new_duration) {
- DCHECK_GE(new_duration, 0);
- demuxer_->SetDuration(new_duration);
-}
-
-void WebMediaSourceImpl::markEndOfStream(
- WebMediaSource::EndOfStreamStatus status) {
- media::PipelineStatus pipeline_status = media::PIPELINE_OK;
-
- switch (status) {
- case WebMediaSource::EndOfStreamStatusNoError:
- break;
- case WebMediaSource::EndOfStreamStatusNetworkError:
- pipeline_status = media::PIPELINE_ERROR_NETWORK;
- break;
- case WebMediaSource::EndOfStreamStatusDecodeError:
- pipeline_status = media::PIPELINE_ERROR_DECODE;
- break;
- }
-
- demuxer_->MarkEndOfStream(pipeline_status);
-}
-
-void WebMediaSourceImpl::unmarkEndOfStream() {
- demuxer_->UnmarkEndOfStream();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webmediasource_impl.h b/chromium/content/renderer/media/webmediasource_impl.h
deleted file mode 100644
index c788a663079..00000000000
--- a/chromium/content/renderer/media/webmediasource_impl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBMEDIASOURCE_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_WEBMEDIASOURCE_IMPL_H_
-
-#include <string>
-#include <vector>
-
-#include "media/base/media_log.h"
-#include "third_party/WebKit/public/platform/WebMediaSource.h"
-
-namespace media {
-class ChunkDemuxer;
-}
-
-namespace content {
-
-class WebMediaSourceImpl : public blink::WebMediaSource {
- public:
- WebMediaSourceImpl(media::ChunkDemuxer* demuxer, media::LogCB log_cb);
- virtual ~WebMediaSourceImpl();
-
- // blink::WebMediaSource implementation.
- virtual AddStatus addSourceBuffer(
- const blink::WebString& type,
- const blink::WebVector<blink::WebString>& codecs,
- blink::WebSourceBuffer** source_buffer);
- virtual double duration();
- virtual void setDuration(double duration);
- virtual void markEndOfStream(EndOfStreamStatus status);
- virtual void unmarkEndOfStream();
-
- private:
- media::ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl.
- media::LogCB log_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(WebMediaSourceImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBMEDIASOURCE_IMPL_H_
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index 3b93cdf5d3c..66de365164b 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -6,8 +6,10 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/debug/trace_event.h"
#include "base/location.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/threading/thread_checker.h"
#include "content/renderer/media/native_handle_impl.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
@@ -29,13 +31,13 @@ class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
protected:
friend class base::RefCountedThreadSafe<RemoteVideoSourceDelegate>;
- virtual ~RemoteVideoSourceDelegate();
+ ~RemoteVideoSourceDelegate() override;
// Implements webrtc::VideoRendererInterface used for receiving video frames
// from the PeerConnection video track. May be called on a libjingle internal
// thread.
- virtual void SetSize(int width, int height) OVERRIDE;
- virtual void RenderFrame(const cricket::VideoFrame* frame) OVERRIDE;
+ void SetSize(int width, int height) override;
+ void RenderFrame(const cricket::VideoFrame* frame) override;
void DoRenderFrameOnIOThread(scoped_refptr<media::VideoFrame> video_frame,
const media::VideoCaptureFormat& format);
@@ -71,8 +73,9 @@ RemoteVideoSourceDelegate::SetSize(int width, int height) {
void MediaStreamRemoteVideoSource::
RemoteVideoSourceDelegate::RenderFrame(
const cricket::VideoFrame* frame) {
+ TRACE_EVENT0("webrtc", "RemoteVideoSourceDelegate::RenderFrame");
base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
- frame->GetElapsedTime() / talk_base::kNumNanosecsPerMicrosec);
+ frame->GetElapsedTime() / rtc::kNumNanosecsPerMicrosec);
scoped_refptr<media::VideoFrame> video_frame;
if (frame->GetNativeHandle() != NULL) {
@@ -106,7 +109,7 @@ RemoteVideoSourceDelegate::RenderFrame(
media::VideoCaptureFormat format(
gfx::Size(video_frame->natural_size().width(),
video_frame->natural_size().height()),
- MediaStreamVideoSource::kDefaultFrameRate,
+ MediaStreamVideoSource::kUnknownFrameRate,
pixel_format);
io_message_loop_->PostTask(
@@ -120,26 +123,96 @@ RemoteVideoSourceDelegate::DoRenderFrameOnIOThread(
scoped_refptr<media::VideoFrame> video_frame,
const media::VideoCaptureFormat& format) {
DCHECK(io_message_loop_->BelongsToCurrentThread());
+ TRACE_EVENT0("webrtc", "RemoteVideoSourceDelegate::DoRenderFrameOnIOThread");
// TODO(hclam): Give the estimated capture time.
frame_callback_.Run(video_frame, format, base::TimeTicks());
}
+MediaStreamRemoteVideoSource::Observer::Observer(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::VideoTrackInterface* track)
+ : main_thread_(main_thread),
+#if DCHECK_IS_ON
+ source_set_(false),
+#endif
+ track_(track),
+ state_(track->state()) {
+ track->RegisterObserver(this);
+}
+
+const scoped_refptr<webrtc::VideoTrackInterface>&
+MediaStreamRemoteVideoSource::Observer::track() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ return track_;
+}
+
+webrtc::MediaStreamTrackInterface::TrackState
+MediaStreamRemoteVideoSource::Observer::state() const {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ return state_;
+}
+
+void MediaStreamRemoteVideoSource::Observer::Unregister() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ track_->UnregisterObserver(this);
+ track_ = nullptr;
+}
+
+MediaStreamRemoteVideoSource::Observer::~Observer() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(!track_.get());
+}
+
+void MediaStreamRemoteVideoSource::Observer::SetSource(
+ const base::WeakPtr<MediaStreamRemoteVideoSource>& source) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ DCHECK(!source_);
+ source_ = source;
+#if DCHECK_IS_ON
+ // |source_set_| means that there is a MediaStreamRemoteVideoSource that
+ // should handle all state changes. Since an Observer is always created when
+ // a remote MediaStream changes in RemoteMediaStreamImpl::Observer::OnChanged,
+ // it can happen that an Observer is created but SetSource is never called.
+ source_set_ = true;
+#endif
+}
+
+void MediaStreamRemoteVideoSource::Observer::OnChanged() {
+ webrtc::MediaStreamTrackInterface::TrackState state = track_->state();
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&MediaStreamRemoteVideoSource::Observer::OnChangedImpl,
+ this, state));
+}
+
+void MediaStreamRemoteVideoSource::Observer::OnChangedImpl(
+ webrtc::MediaStreamTrackInterface::TrackState state) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+#if DCHECK_IS_ON
+ DCHECK(source_ || !source_set_) << "Dropping a state change event. " << state;
+#endif
+ if (source_ && state != state_)
+ source_->OnChanged(state);
+ state_ = state;
+}
+
MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
- webrtc::VideoTrackInterface* remote_track)
- : remote_track_(remote_track),
- last_state_(remote_track->state()) {
- remote_track_->RegisterObserver(this);
+ const scoped_refptr<MediaStreamRemoteVideoSource::Observer>& observer)
+ : observer_(observer), weak_factory_(this) {
+ observer->SetSource(weak_factory_.GetWeakPtr());
}
MediaStreamRemoteVideoSource::~MediaStreamRemoteVideoSource() {
- remote_track_->UnregisterObserver(this);
+ DCHECK(CalledOnValidThread());
+ observer_->Unregister();
+ observer_ = nullptr;
}
void MediaStreamRemoteVideoSource::GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(CalledOnValidThread());
media::VideoCaptureFormats formats;
// Since the remote end is free to change the resolution at any point in time
// the supported formats are unknown.
@@ -147,46 +220,43 @@ void MediaStreamRemoteVideoSource::GetCurrentSupportedFormats(
}
void MediaStreamRemoteVideoSource::StartSourceImpl(
- const media::VideoCaptureParams& params,
+ const media::VideoCaptureFormat& format,
const VideoCaptureDeliverFrameCB& frame_callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!delegate_);
+ DCHECK(CalledOnValidThread());
+ DCHECK(!delegate_.get());
delegate_ = new RemoteVideoSourceDelegate(io_message_loop(), frame_callback);
- remote_track_->AddRenderer(delegate_);
- OnStartDone(true);
+ observer_->track()->AddRenderer(delegate_.get());
+ OnStartDone(MEDIA_DEVICE_OK);
}
void MediaStreamRemoteVideoSource::StopSourceImpl() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(CalledOnValidThread());
DCHECK(state() != MediaStreamVideoSource::ENDED);
- remote_track_->RemoveRenderer(delegate_);
+ observer_->track()->RemoveRenderer(delegate_.get());
}
webrtc::VideoRendererInterface*
MediaStreamRemoteVideoSource::RenderInterfaceForTest() {
- return delegate_;
-}
-
-void MediaStreamRemoteVideoSource::OnChanged() {
- DCHECK(thread_checker_.CalledOnValidThread());
- webrtc::MediaStreamTrackInterface::TrackState state = remote_track_->state();
- if (state != last_state_) {
- last_state_ = state;
- switch (state) {
- case webrtc::MediaStreamTrackInterface::kInitializing:
- // Ignore the kInitializing state since there is no match in
- // WebMediaStreamSource::ReadyState.
- break;
- case webrtc::MediaStreamTrackInterface::kLive:
- SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
- break;
- case webrtc::MediaStreamTrackInterface::kEnded:
- SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
- break;
- default:
- NOTREACHED();
- break;
- }
+ return delegate_.get();
+}
+
+void MediaStreamRemoteVideoSource::OnChanged(
+ webrtc::MediaStreamTrackInterface::TrackState state) {
+ DCHECK(CalledOnValidThread());
+ switch (state) {
+ case webrtc::MediaStreamTrackInterface::kInitializing:
+ // Ignore the kInitializing state since there is no match in
+ // WebMediaStreamSource::ReadyState.
+ break;
+ case webrtc::MediaStreamTrackInterface::kLive:
+ SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
+ break;
+ case webrtc::MediaStreamTrackInterface::kEnded:
+ SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
+ break;
+ default:
+ NOTREACHED();
+ break;
}
}
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h
index 76041ee8d79..4833da530fe 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h
@@ -5,7 +5,8 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_REMOTE_VIDEO_SOURCE_H_
-#include "base/threading/thread_checker.h"
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
@@ -18,44 +19,82 @@ namespace content {
// to make sure there is no difference between a video track where the source is
// a local source and a video track where the source is a remote video track.
class CONTENT_EXPORT MediaStreamRemoteVideoSource
- : public MediaStreamVideoSource,
- NON_EXPORTED_BASE(public webrtc::ObserverInterface) {
+ : public MediaStreamVideoSource {
public:
- explicit MediaStreamRemoteVideoSource(
- webrtc::VideoTrackInterface* remote_track);
+ class CONTENT_EXPORT Observer
+ : public base::RefCountedThreadSafe<Observer>,
+ NON_EXPORTED_BASE(public webrtc::ObserverInterface) {
+ public:
+ Observer(const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::VideoTrackInterface* track);
+
+ const scoped_refptr<webrtc::VideoTrackInterface>& track();
+ webrtc::MediaStreamTrackInterface::TrackState state() const;
+
+ // This needs to be called by the owner of the observer instance before
+ // the owner releases its reference.
+ // The reason for this is to avoid a potential race when unregistration is
+ // done from the main thread while an event is being delivered on the
+ // signaling thread. If, on the main thread, we're releasing the last
+ // reference to the observer and attempt to unregister from the observer's
+ // dtor, and at the same time receive an OnChanged event on the signaling
+ // thread, we will attempt to increment the refcount in the callback
+ // from 0 to 1 while the object is being freed. Not good.
+ void Unregister();
+
+ private:
+ friend class base::RefCountedThreadSafe<Observer>;
+ ~Observer() override;
+
+ friend class MediaStreamRemoteVideoSource;
+ void SetSource(const base::WeakPtr<MediaStreamRemoteVideoSource>& source);
+
+ // webrtc::ObserverInterface implementation.
+ void OnChanged() override;
+
+ void OnChangedImpl(webrtc::MediaStreamTrackInterface::TrackState state);
+
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ base::WeakPtr<MediaStreamRemoteVideoSource> source_;
+#if DCHECK_IS_ON
+ bool source_set_;
+#endif
+ scoped_refptr<webrtc::VideoTrackInterface> track_;
+ webrtc::MediaStreamTrackInterface::TrackState state_;
+ };
+
+ MediaStreamRemoteVideoSource(const scoped_refptr<Observer>& observer);
virtual ~MediaStreamRemoteVideoSource();
protected:
// Implements MediaStreamVideoSource.
- virtual void GetCurrentSupportedFormats(
+ void GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
- const VideoCaptureDeviceFormatsCB& callback) OVERRIDE;
+ double max_requested_frame_rate,
+ const VideoCaptureDeviceFormatsCB& callback) override;
- virtual void StartSourceImpl(
- const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& frame_callback) OVERRIDE;
+ void StartSourceImpl(
+ const media::VideoCaptureFormat& format,
+ const VideoCaptureDeliverFrameCB& frame_callback) override;
- virtual void StopSourceImpl() OVERRIDE;
+ void StopSourceImpl() override;
// Used by tests to test that a frame can be received and that the
// MediaStreamRemoteVideoSource behaves as expected.
webrtc::VideoRendererInterface* RenderInterfaceForTest();
private:
- // webrtc::ObserverInterface implementation.
- virtual void OnChanged() OVERRIDE;
+ friend class Observer;
+ void OnChanged(webrtc::MediaStreamTrackInterface::TrackState state);
- scoped_refptr<webrtc::VideoTrackInterface> remote_track_;
- webrtc::MediaStreamTrackInterface::TrackState last_state_;
+ scoped_refptr<Observer> observer_;
// Internal class used for receiving frames from the webrtc track on a
// libjingle thread and forward it to the IO-thread.
class RemoteVideoSourceDelegate;
scoped_refptr<RemoteVideoSourceDelegate> delegate_;
-
- // Bound to the render thread.
- base::ThreadChecker thread_checker_;
+ base::WeakPtrFactory<MediaStreamRemoteVideoSource> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamRemoteVideoSource);
};
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index c6b50ec25eb..4026f43c5f4 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -5,6 +5,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/mock_media_stream_video_sink.h"
@@ -12,6 +13,7 @@
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
namespace content {
@@ -23,10 +25,10 @@ ACTION_P(RunClosure, closure) {
class MediaStreamRemoteVideoSourceUnderTest
: public MediaStreamRemoteVideoSource {
public:
- MediaStreamRemoteVideoSourceUnderTest(webrtc::VideoTrackInterface* track)
- : MediaStreamRemoteVideoSource(track) {
+ MediaStreamRemoteVideoSourceUnderTest(const scoped_refptr<Observer>& observer)
+ : MediaStreamRemoteVideoSource(observer) {
}
- using MediaStreamRemoteVideoSource::RenderInterfaceForTest;
+ using MediaStreamRemoteVideoSource::RenderInterfaceForTest;
};
class MediaStreamRemoteVideoSourceTest
@@ -35,12 +37,12 @@ class MediaStreamRemoteVideoSourceTest
MediaStreamRemoteVideoSourceTest()
: child_process_(new ChildProcess()),
mock_factory_(new MockPeerConnectionDependencyFactory()),
- webrtc_video_track_(
- mock_factory_->CreateLocalVideoTrack(
- "test",
- static_cast<cricket::VideoCapturer*>(NULL))),
- remote_source_(
- new MediaStreamRemoteVideoSourceUnderTest(webrtc_video_track_)),
+ webrtc_video_track_(mock_factory_->CreateLocalVideoTrack(
+ "test",
+ static_cast<cricket::VideoCapturer*>(NULL))),
+ observer_(new MediaStreamRemoteVideoSource::Observer(
+ base::ThreadTaskRunnerHandle::Get(), webrtc_video_track_.get())),
+ remote_source_(new MediaStreamRemoteVideoSourceUnderTest(observer_)),
number_of_successful_constraints_applied_(0),
number_of_failed_constraints_applied_(0) {
webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
@@ -49,21 +51,26 @@ class MediaStreamRemoteVideoSourceTest
webkit_source_.setExtraData(remote_source_);
}
+ void TearDown() override {
+ webkit_source_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
MediaStreamRemoteVideoSourceUnderTest* source() {
return remote_source_;
}
- MediaStreamVideoTrack* CreateTrack() {
- bool enabled = true;
- blink::WebMediaConstraints constraints;
- constraints.initialize();
- return new MediaStreamVideoTrack(
- source(),
- constraints,
- base::Bind(
- &MediaStreamRemoteVideoSourceTest::OnConstraintsApplied,
- base::Unretained(this)),
- enabled);
+ MediaStreamVideoTrack* CreateTrack() {
+ bool enabled = true;
+ blink::WebMediaConstraints constraints;
+ constraints.initialize();
+ return new MediaStreamVideoTrack(
+ source(),
+ constraints,
+ base::Bind(
+ &MediaStreamRemoteVideoSourceTest::OnConstraintsApplied,
+ base::Unretained(this)),
+ enabled);
}
int NumberOfSuccessConstraintsCallbacks() const {
@@ -84,9 +91,11 @@ class MediaStreamRemoteVideoSourceTest
}
private:
- void OnConstraintsApplied(MediaStreamSource* source, bool success) {
+ void OnConstraintsApplied(MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
ASSERT_EQ(source, remote_source_);
- if (success)
+ if (result == MEDIA_DEVICE_OK)
++number_of_successful_constraints_applied_;
else
++number_of_failed_constraints_applied_;
@@ -96,6 +105,7 @@ class MediaStreamRemoteVideoSourceTest
scoped_ptr<ChildProcess> child_process_;
scoped_ptr<MockPeerConnectionDependencyFactory> mock_factory_;
scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track_;
+ scoped_refptr<MediaStreamRemoteVideoSource::Observer> observer_;
// |remote_source_| is owned by |webkit_source_|.
MediaStreamRemoteVideoSourceUnderTest* remote_source_;
blink::WebMediaStreamSource webkit_source_;
@@ -131,6 +141,7 @@ TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
webkit_source().readyState());
StopWebRtcTrack();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
webkit_source().readyState());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink.state());
diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc
index 736cac3ffc0..d6962c3f91c 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc
@@ -9,6 +9,7 @@
#include <string>
#include "base/md5.h"
+#include "base/thread_task_runner_handle.h"
#include "content/common/media/media_stream_track_metrics_host_messages.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
@@ -20,38 +21,103 @@ using webrtc::PeerConnectionInterface;
using webrtc::VideoTrackVector;
namespace content {
+namespace {
+typedef std::set<std::string> IdSet;
+
+template <class T>
+IdSet GetTrackIds(const std::vector<rtc::scoped_refptr<T>>& tracks) {
+ IdSet track_ids;
+ for (const auto& track : tracks)
+ track_ids.insert(track->id());
+ return track_ids;
+}
-class MediaStreamTrackMetricsObserver : public webrtc::ObserverInterface {
+// TODO(tommi): Consolidate this and TrackObserver since these implementations
+// are fundamentally achieving the same thing (aside from specific logic inside
+// the OnChanged callbacks).
+class MediaStreamObserver
+ : public base::RefCountedThreadSafe<MediaStreamObserver>,
+ public webrtc::ObserverInterface {
+ public:
+ typedef base::Callback<
+ void(const IdSet& audio_track_ids, const IdSet& video_track_ids)>
+ OnChangedCallback;
+
+ MediaStreamObserver(
+ const OnChangedCallback& callback,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
+ webrtc::MediaStreamInterface* stream)
+ : main_thread_(main_thread), stream_(stream), callback_(callback) {
+ signaling_thread_.DetachFromThread();
+ stream_->RegisterObserver(this);
+ }
+
+ const scoped_refptr<webrtc::MediaStreamInterface>& stream() const {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ return stream_;
+ }
+
+ void Unregister() {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ callback_.Reset();
+ stream_->UnregisterObserver(this);
+ stream_ = nullptr;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<MediaStreamObserver>;
+ ~MediaStreamObserver() override {
+ DCHECK(!stream_.get()) << "must have been unregistered before deleting";
+ }
+
+ // webrtc::ObserverInterface implementation.
+ void OnChanged() override {
+ DCHECK(signaling_thread_.CalledOnValidThread());
+ main_thread_->PostTask(FROM_HERE,
+ base::Bind(&MediaStreamObserver::OnChangedOnMainThread, this,
+ GetTrackIds(stream_->GetAudioTracks()),
+ GetTrackIds(stream_->GetVideoTracks())));
+ }
+
+ void OnChangedOnMainThread(const IdSet& audio_track_ids,
+ const IdSet& video_track_ids) {
+ DCHECK(main_thread_->BelongsToCurrentThread());
+ if (!callback_.is_null())
+ callback_.Run(audio_track_ids, video_track_ids);
+ }
+
+ const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
+ scoped_refptr<webrtc::MediaStreamInterface> stream_;
+ OnChangedCallback callback_; // Only touched on the main thread.
+ base::ThreadChecker signaling_thread_;
+};
+
+} // namespace
+
+class MediaStreamTrackMetricsObserver {
public:
MediaStreamTrackMetricsObserver(
MediaStreamTrackMetrics::StreamType stream_type,
MediaStreamInterface* stream,
MediaStreamTrackMetrics* owner);
- virtual ~MediaStreamTrackMetricsObserver();
+ ~MediaStreamTrackMetricsObserver();
// Sends begin/end messages for all tracks currently tracked.
void SendLifetimeMessages(MediaStreamTrackMetrics::LifetimeEvent event);
- MediaStreamInterface* stream() { return stream_; }
- MediaStreamTrackMetrics::StreamType stream_type() { return stream_type_; }
-
- private:
- typedef std::set<std::string> IdSet;
+ MediaStreamInterface* stream() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return observer_->stream().get();
+ }
- // webrtc::ObserverInterface implementation.
- virtual void OnChanged() OVERRIDE;
-
- template <class T>
- IdSet GetTrackIds(const std::vector<talk_base::scoped_refptr<T> >& tracks) {
- IdSet track_ids;
- typename std::vector<talk_base::scoped_refptr<T> >::const_iterator it =
- tracks.begin();
- for (; it != tracks.end(); ++it) {
- track_ids.insert((*it)->id());
- }
- return track_ids;
+ MediaStreamTrackMetrics::StreamType stream_type() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return stream_type_;
}
+ private:
+ void OnChanged(const IdSet& audio_track_ids, const IdSet& video_track_ids);
+
void ReportAddedAndRemovedTracks(
const IdSet& new_ids,
const IdSet& old_ids,
@@ -72,10 +138,11 @@ class MediaStreamTrackMetricsObserver : public webrtc::ObserverInterface {
IdSet video_track_ids_;
MediaStreamTrackMetrics::StreamType stream_type_;
- talk_base::scoped_refptr<MediaStreamInterface> stream_;
+ scoped_refptr<MediaStreamObserver> observer_;
// Non-owning.
MediaStreamTrackMetrics* owner_;
+ base::ThreadChecker thread_checker_;
};
namespace {
@@ -101,20 +168,26 @@ MediaStreamTrackMetricsObserver::MediaStreamTrackMetricsObserver(
MediaStreamTrackMetrics* owner)
: has_reported_start_(false),
has_reported_end_(false),
+ audio_track_ids_(GetTrackIds(stream->GetAudioTracks())),
+ video_track_ids_(GetTrackIds(stream->GetVideoTracks())),
stream_type_(stream_type),
- stream_(stream),
+ observer_(new MediaStreamObserver(
+ base::Bind(&MediaStreamTrackMetricsObserver::OnChanged,
+ base::Unretained(this)),
+ base::ThreadTaskRunnerHandle::Get(),
+ stream)),
owner_(owner) {
- OnChanged(); // To populate initial tracks.
- stream_->RegisterObserver(this);
}
MediaStreamTrackMetricsObserver::~MediaStreamTrackMetricsObserver() {
- stream_->UnregisterObserver(this);
+ DCHECK(thread_checker_.CalledOnValidThread());
+ observer_->Unregister();
SendLifetimeMessages(MediaStreamTrackMetrics::DISCONNECTED);
}
void MediaStreamTrackMetricsObserver::SendLifetimeMessages(
MediaStreamTrackMetrics::LifetimeEvent event) {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (event == MediaStreamTrackMetrics::CONNECTED) {
// Both ICE CONNECTED and COMPLETED can trigger the first
// start-of-life event, so we only report the first.
@@ -146,33 +219,31 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages(
}
}
-void MediaStreamTrackMetricsObserver::OnChanged() {
- AudioTrackVector all_audio_tracks = stream_->GetAudioTracks();
- IdSet all_audio_track_ids = GetTrackIds(all_audio_tracks);
-
- VideoTrackVector all_video_tracks = stream_->GetVideoTracks();
- IdSet all_video_track_ids = GetTrackIds(all_video_tracks);
+void MediaStreamTrackMetricsObserver::OnChanged(
+ const IdSet& audio_track_ids, const IdSet& video_track_ids) {
+ DCHECK(thread_checker_.CalledOnValidThread());
// We only report changes after our initial report, and never after
// our last report.
if (has_reported_start_ && !has_reported_end_) {
- ReportAddedAndRemovedTracks(all_audio_track_ids,
+ ReportAddedAndRemovedTracks(audio_track_ids,
audio_track_ids_,
MediaStreamTrackMetrics::AUDIO_TRACK);
- ReportAddedAndRemovedTracks(all_video_track_ids,
+ ReportAddedAndRemovedTracks(video_track_ids,
video_track_ids_,
MediaStreamTrackMetrics::VIDEO_TRACK);
}
// We always update our sets of tracks.
- audio_track_ids_ = all_audio_track_ids;
- video_track_ids_ = all_video_track_ids;
+ audio_track_ids_ = audio_track_ids;
+ video_track_ids_ = video_track_ids;
}
void MediaStreamTrackMetricsObserver::ReportAddedAndRemovedTracks(
const IdSet& new_ids,
const IdSet& old_ids,
MediaStreamTrackMetrics::TrackType track_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(has_reported_start_ && !has_reported_end_);
IdSet added_tracks = base::STLSetDifference<IdSet>(new_ids, old_ids);
@@ -187,6 +258,7 @@ void MediaStreamTrackMetricsObserver::ReportTracks(
const IdSet& ids,
MediaStreamTrackMetrics::TrackType track_type,
MediaStreamTrackMetrics::LifetimeEvent event) {
+ DCHECK(thread_checker_.CalledOnValidThread());
for (IdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
owner_->SendLifetimeMessage(*it, track_type, event, stream_type_);
}
diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
index 343ab3033ec..d18c04f9e4c 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/threading/thread.h"
#include "content/renderer/media/webrtc/media_stream_track_metrics.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -26,7 +30,7 @@ class MockAudioTrackInterface : public AudioTrackInterface {
explicit MockAudioTrackInterface(const std::string& id) : id_(id) {}
virtual ~MockAudioTrackInterface() {}
- virtual std::string id() const OVERRIDE { return id_; }
+ virtual std::string id() const override { return id_; }
MOCK_METHOD1(RegisterObserver, void(ObserverInterface*));
MOCK_METHOD1(UnregisterObserver, void(ObserverInterface*));
@@ -49,7 +53,7 @@ class MockVideoTrackInterface : public VideoTrackInterface {
explicit MockVideoTrackInterface(const std::string& id) : id_(id) {}
virtual ~MockVideoTrackInterface() {}
- virtual std::string id() const OVERRIDE { return id_; }
+ virtual std::string id() const override { return id_; }
MOCK_METHOD1(RegisterObserver, void(ObserverInterface*));
MOCK_METHOD1(UnregisterObserver, void(ObserverInterface*));
@@ -78,26 +82,69 @@ class MockMediaStreamTrackMetrics : public MediaStreamTrackMetrics {
class MediaStreamTrackMetricsTest : public testing::Test {
public:
- virtual void SetUp() OVERRIDE {
+ MediaStreamTrackMetricsTest() : signaling_thread_("signaling_thread") {}
+ void SetUp() override {
metrics_.reset(new MockMediaStreamTrackMetrics());
- stream_ = new talk_base::RefCountedObject<MockMediaStream>("stream");
+ stream_ = new rtc::RefCountedObject<MockMediaStream>("stream");
+ signaling_thread_.Start();
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
+ signaling_thread_.Stop();
metrics_.reset();
stream_ = NULL;
}
+ // Adds an audio track to |stream_| on the signaling thread to simulate how
+ // notifications will be fired in Chrome.
+ template <typename TrackType>
+ void AddTrack(TrackType* track) {
+ // Explicitly casting to this type is necessary since the
+ // MediaStreamInterface has two methods with the same name.
+ typedef bool (MediaStreamInterface::*AddTrack)(TrackType*);
+ base::RunLoop run_loop;
+ signaling_thread_.task_runner()->PostTaskAndReply(FROM_HERE,
+ base::Bind(
+ base::IgnoreResult<AddTrack>(&MediaStreamInterface::AddTrack),
+ stream_, track),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ template <typename TrackType>
+ void RemoveTrack(TrackType* track) {
+ // Explicitly casting to this type is necessary since the
+ // MediaStreamInterface has two methods with the same name.
+ typedef bool (MediaStreamInterface::*RemoveTrack)(TrackType*);
+ base::RunLoop run_loop;
+ signaling_thread_.task_runner()->PostTaskAndReply(FROM_HERE,
+ base::Bind(
+ base::IgnoreResult<RemoveTrack>(&MediaStreamInterface::RemoveTrack),
+ stream_, track),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Convenience methods to cast the mock track types into their webrtc
+ // equivalents.
+ void AddAudioTrack(AudioTrackInterface* track) { AddTrack(track); }
+ void RemoveAudioTrack(AudioTrackInterface* track) { RemoveTrack(track); }
+ void AddVideoTrack(VideoTrackInterface* track) { AddTrack(track); }
+ void RemoveVideoTrack(VideoTrackInterface* track) { RemoveTrack(track); }
+
scoped_refptr<MockAudioTrackInterface> MakeAudioTrack(std::string id) {
- return new talk_base::RefCountedObject<MockAudioTrackInterface>(id);
+ return new rtc::RefCountedObject<MockAudioTrackInterface>(id);
}
scoped_refptr<MockVideoTrackInterface> MakeVideoTrack(std::string id) {
- return new talk_base::RefCountedObject<MockVideoTrackInterface>(id);
+ return new rtc::RefCountedObject<MockVideoTrackInterface>(id);
}
scoped_ptr<MockMediaStreamTrackMetrics> metrics_;
scoped_refptr<MediaStreamInterface> stream_;
+
+ base::MessageLoopForUI message_loop_;
+ base::Thread signaling_thread_;
};
TEST_F(MediaStreamTrackMetricsTest, MakeUniqueId) {
@@ -135,9 +182,9 @@ TEST_F(MediaStreamTrackMetricsTest, MakeUniqueId) {
TEST_F(MediaStreamTrackMetricsTest, BasicRemoteStreams) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
- stream_->AddTrack(audio);
- stream_->AddTrack(video);
- metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ stream_->AddTrack(video.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio",
@@ -169,9 +216,9 @@ TEST_F(MediaStreamTrackMetricsTest, BasicRemoteStreams) {
TEST_F(MediaStreamTrackMetricsTest, BasicLocalStreams) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
- stream_->AddTrack(audio);
- stream_->AddTrack(video);
- metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ stream_->AddTrack(video.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio",
@@ -216,9 +263,9 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamAddedAferIceConnect) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
- stream_->AddTrack(audio);
- stream_->AddTrack(video);
- metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ stream_->AddTrack(video.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
}
TEST_F(MediaStreamTrackMetricsTest, RemoteStreamAddedAferIceConnect) {
@@ -238,16 +285,16 @@ TEST_F(MediaStreamTrackMetricsTest, RemoteStreamAddedAferIceConnect) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
- stream_->AddTrack(audio);
- stream_->AddTrack(video);
- metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ stream_->AddTrack(video.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get());
}
TEST_F(MediaStreamTrackMetricsTest, RemoteStreamTrackAdded) {
scoped_refptr<MockAudioTrackInterface> initial(MakeAudioTrack("initial"));
scoped_refptr<MockAudioTrackInterface> added(MakeAudioTrack("added"));
- stream_->AddTrack(initial);
- metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+ stream_->AddTrack(initial.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("initial",
@@ -262,7 +309,7 @@ TEST_F(MediaStreamTrackMetricsTest, RemoteStreamTrackAdded) {
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::CONNECTED,
MediaStreamTrackMetrics::RECEIVED_STREAM));
- stream_->AddTrack(added);
+ AddAudioTrack(added.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("initial",
@@ -280,9 +327,9 @@ TEST_F(MediaStreamTrackMetricsTest, RemoteStreamTrackAdded) {
TEST_F(MediaStreamTrackMetricsTest, LocalStreamTrackRemoved) {
scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first"));
scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second"));
- stream_->AddTrack(first);
- stream_->AddTrack(second);
- metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ stream_->AddTrack(first.get());
+ stream_->AddTrack(second.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("first",
@@ -302,7 +349,7 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamTrackRemoved) {
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->RemoveTrack(first);
+ stream_->RemoveTrack(first.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("second",
@@ -315,13 +362,13 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamTrackRemoved) {
TEST_F(MediaStreamTrackMetricsTest, LocalStreamModificationsBeforeAndAfter) {
scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first"));
scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second"));
- stream_->AddTrack(first);
- metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ stream_->AddTrack(first.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
// This gets added after we start observing, but no lifetime message
// should be sent at this point since the call is not connected. It
// should get sent only once it gets connected.
- stream_->AddTrack(second);
+ AddAudioTrack(second.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("first",
@@ -350,13 +397,13 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamModificationsBeforeAndAfter) {
// This happens after the call is disconnected so no lifetime
// message should be sent.
- stream_->RemoveTrack(first);
+ RemoveAudioTrack(first.get());
}
TEST_F(MediaStreamTrackMetricsTest, RemoteStreamMultipleDisconnects) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
- stream_->AddTrack(audio);
- metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio",
@@ -374,13 +421,13 @@ TEST_F(MediaStreamTrackMetricsTest, RemoteStreamMultipleDisconnects) {
metrics_->IceConnectionChange(
PeerConnectionInterface::kIceConnectionDisconnected);
metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
- stream_->RemoveTrack(audio);
+ RemoveAudioTrack(audio.get());
}
TEST_F(MediaStreamTrackMetricsTest, RemoteStreamConnectDisconnectTwice) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
- stream_->AddTrack(audio);
- metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get());
for (size_t i = 0; i < 2; ++i) {
EXPECT_CALL(*metrics_,
@@ -400,15 +447,15 @@ TEST_F(MediaStreamTrackMetricsTest, RemoteStreamConnectDisconnectTwice) {
PeerConnectionInterface::kIceConnectionDisconnected);
}
- stream_->RemoveTrack(audio);
+ RemoveAudioTrack(audio.get());
}
TEST_F(MediaStreamTrackMetricsTest, LocalStreamRemovedNoDisconnect) {
scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
- stream_->AddTrack(audio);
- stream_->AddTrack(video);
- metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ stream_->AddTrack(audio.get());
+ stream_->AddTrack(video.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio",
@@ -433,7 +480,7 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamRemovedNoDisconnect) {
MediaStreamTrackMetrics::VIDEO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
}
TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) {
@@ -443,9 +490,9 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) {
scoped_refptr<MockVideoTrackInterface> video1(MakeVideoTrack("video1"));
scoped_refptr<MockVideoTrackInterface> video2(MakeVideoTrack("video2"));
scoped_refptr<MockVideoTrackInterface> video3(MakeVideoTrack("video3"));
- stream_->AddTrack(audio1);
- stream_->AddTrack(video1);
- metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ stream_->AddTrack(audio1.get());
+ stream_->AddTrack(video1.get());
+ metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio1",
@@ -465,33 +512,33 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) {
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::CONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->AddTrack(audio2);
+ AddAudioTrack(audio2.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("video2",
MediaStreamTrackMetrics::VIDEO_TRACK,
MediaStreamTrackMetrics::CONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->AddTrack(video2);
+ AddVideoTrack(video2.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio1",
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->RemoveTrack(audio1);
+ RemoveAudioTrack(audio1.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio3",
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::CONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->AddTrack(audio3);
+ AddAudioTrack(audio3.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("video3",
MediaStreamTrackMetrics::VIDEO_TRACK,
MediaStreamTrackMetrics::CONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->AddTrack(video3);
+ AddVideoTrack(video3.get());
// Add back audio1
EXPECT_CALL(*metrics_,
@@ -499,33 +546,33 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) {
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::CONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->AddTrack(audio1);
+ AddAudioTrack(audio1.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio2",
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->RemoveTrack(audio2);
+ RemoveAudioTrack(audio2.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("video2",
MediaStreamTrackMetrics::VIDEO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->RemoveTrack(video2);
+ RemoveVideoTrack(video2.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio1",
MediaStreamTrackMetrics::AUDIO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->RemoveTrack(audio1);
+ RemoveAudioTrack(audio1.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("video1",
MediaStreamTrackMetrics::VIDEO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- stream_->RemoveTrack(video1);
+ RemoveVideoTrack(video1.get());
EXPECT_CALL(*metrics_,
SendLifetimeMessage("audio3",
@@ -537,7 +584,7 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) {
MediaStreamTrackMetrics::VIDEO_TRACK,
MediaStreamTrackMetrics::DISCONNECTED,
MediaStreamTrackMetrics::SENT_STREAM));
- metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+ metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get());
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
index 7048d935d45..ca3f29851a3 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
@@ -14,8 +14,8 @@
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
-#include "third_party/libjingle/source/talk/base/scoped_ref_ptr.h"
#include "third_party/libjingle/source/talk/media/base/videocapturer.h"
+#include "third_party/webrtc/base/scoped_ref_ptr.h"
using webrtc::AudioSourceInterface;
using webrtc::AudioTrackInterface;
@@ -90,13 +90,13 @@ VideoTrackVector MockMediaStream::GetVideoTracks() {
return video_track_vector_;
}
-talk_base::scoped_refptr<AudioTrackInterface> MockMediaStream::FindAudioTrack(
+rtc::scoped_refptr<AudioTrackInterface> MockMediaStream::FindAudioTrack(
const std::string& track_id) {
AudioTrackVector::iterator it = FindTrack(&audio_track_vector_, track_id);
return it == audio_track_vector_.end() ? NULL : *it;
}
-talk_base::scoped_refptr<VideoTrackInterface> MockMediaStream::FindVideoTrack(
+rtc::scoped_refptr<VideoTrackInterface> MockMediaStream::FindVideoTrack(
const std::string& track_id) {
VideoTrackVector::iterator it = FindTrack(&video_track_vector_, track_id);
return it == video_track_vector_.end() ? NULL : *it;
@@ -131,8 +131,7 @@ class MockRtcVideoCapturer : public WebRtcVideoCapturerAdapter {
height_(0) {
}
- virtual void OnFrameCaptured(
- const scoped_refptr<media::VideoFrame>& frame) OVERRIDE {
+ void OnFrameCaptured(const scoped_refptr<media::VideoFrame>& frame) override {
++number_of_capturered_frames_;
width_ = frame->visible_rect().width();
height_ = frame->visible_rect().height();
@@ -176,8 +175,7 @@ bool MockVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) {
MockAudioSource::MockAudioSource(
const webrtc::MediaConstraintsInterface* constraints)
- : observer_(NULL),
- state_(MediaSourceInterface::kLive),
+ : state_(MediaSourceInterface::kLive),
optional_constraints_(constraints->GetOptional()),
mandatory_constraints_(constraints->GetMandatory()) {
}
@@ -185,12 +183,13 @@ MockAudioSource::MockAudioSource(
MockAudioSource::~MockAudioSource() {}
void MockAudioSource::RegisterObserver(webrtc::ObserverInterface* observer) {
- observer_ = observer;
+ DCHECK(observers_.find(observer) == observers_.end());
+ observers_.insert(observer);
}
void MockAudioSource::UnregisterObserver(webrtc::ObserverInterface* observer) {
- DCHECK(observer_ == observer);
- observer_ = NULL;
+ DCHECK(observers_.find(observer) != observers_.end());
+ observers_.erase(observer);
}
webrtc::MediaSourceInterface::SourceState MockAudioSource::state() const {
@@ -291,7 +290,6 @@ MockWebRtcVideoTrack::MockWebRtcVideoTrack(
id_(id),
state_(MediaStreamTrackInterface::kLive),
source_(source),
- observer_(NULL),
renderer_(NULL) {
}
@@ -327,18 +325,19 @@ bool MockWebRtcVideoTrack::set_enabled(bool enable) {
bool MockWebRtcVideoTrack::set_state(TrackState new_state) {
state_ = new_state;
- if (observer_)
- observer_->OnChanged();
+ for (auto& o : observers_)
+ o->OnChanged();
return true;
}
void MockWebRtcVideoTrack::RegisterObserver(ObserverInterface* observer) {
- observer_ = observer;
+ DCHECK(observers_.find(observer) == observers_.end());
+ observers_.insert(observer);
}
void MockWebRtcVideoTrack::UnregisterObserver(ObserverInterface* observer) {
- DCHECK(observer_ == observer);
- observer_ = NULL;
+ DCHECK(observers_.find(observer) != observers_.end());
+ observers_.erase(observer);
}
VideoSourceInterface* MockWebRtcVideoTrack::GetSource() const {
@@ -352,41 +351,39 @@ class MockSessionDescription : public SessionDescriptionInterface {
: type_(type),
sdp_(sdp) {
}
- virtual ~MockSessionDescription() {}
- virtual cricket::SessionDescription* description() OVERRIDE {
+ ~MockSessionDescription() override {}
+ cricket::SessionDescription* description() override {
NOTIMPLEMENTED();
return NULL;
}
- virtual const cricket::SessionDescription* description() const OVERRIDE {
+ const cricket::SessionDescription* description() const override {
NOTIMPLEMENTED();
return NULL;
}
- virtual std::string session_id() const OVERRIDE {
+ std::string session_id() const override {
NOTIMPLEMENTED();
return std::string();
}
- virtual std::string session_version() const OVERRIDE {
+ std::string session_version() const override {
NOTIMPLEMENTED();
return std::string();
}
- virtual std::string type() const OVERRIDE {
- return type_;
- }
- virtual bool AddCandidate(const IceCandidateInterface* candidate) OVERRIDE {
+ std::string type() const override { return type_; }
+ bool AddCandidate(const IceCandidateInterface* candidate) override {
NOTIMPLEMENTED();
return false;
}
- virtual size_t number_of_mediasections() const OVERRIDE {
+ size_t number_of_mediasections() const override {
NOTIMPLEMENTED();
return 0;
}
- virtual const IceCandidateCollection* candidates(
- size_t mediasection_index) const OVERRIDE {
+ const IceCandidateCollection* candidates(
+ size_t mediasection_index) const override {
NOTIMPLEMENTED();
return NULL;
}
- virtual bool ToString(std::string* out) const OVERRIDE {
+ bool ToString(std::string* out) const override {
*out = sdp_;
return true;
}
@@ -404,22 +401,14 @@ class MockIceCandidate : public IceCandidateInterface {
: sdp_mid_(sdp_mid),
sdp_mline_index_(sdp_mline_index),
sdp_(sdp) {
+ // Assign an valid address to |candidate_| to pass assert in code.
+ candidate_.set_address(rtc::SocketAddress("127.0.0.1", 5000));
}
- virtual ~MockIceCandidate() {}
- virtual std::string sdp_mid() const OVERRIDE {
- return sdp_mid_;
- }
- virtual int sdp_mline_index() const OVERRIDE {
- return sdp_mline_index_;
- }
- virtual const cricket::Candidate& candidate() const OVERRIDE {
- // This function should never be called. It will intentionally crash. The
- // base class forces us to return a reference.
- NOTREACHED();
- cricket::Candidate* candidate = NULL;
- return *candidate;
- }
- virtual bool ToString(std::string* out) const OVERRIDE {
+ ~MockIceCandidate() override {}
+ std::string sdp_mid() const override { return sdp_mid_; }
+ int sdp_mline_index() const override { return sdp_mline_index_; }
+ const cricket::Candidate& candidate() const override { return candidate_; }
+ bool ToString(std::string* out) const override {
*out = sdp_;
return true;
}
@@ -428,6 +417,7 @@ class MockIceCandidate : public IceCandidateInterface {
std::string sdp_mid_;
int sdp_mline_index_;
std::string sdp_;
+ cricket::Candidate candidate_;
};
MockPeerConnectionDependencyFactory::MockPeerConnectionDependencyFactory()
@@ -439,18 +429,18 @@ MockPeerConnectionDependencyFactory::~MockPeerConnectionDependencyFactory() {}
scoped_refptr<webrtc::PeerConnectionInterface>
MockPeerConnectionDependencyFactory::CreatePeerConnection(
- const webrtc::PeerConnectionInterface::IceServers& ice_servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* frame,
webrtc::PeerConnectionObserver* observer) {
- return new talk_base::RefCountedObject<MockPeerConnectionImpl>(this);
+ return new rtc::RefCountedObject<MockPeerConnectionImpl>(this, observer);
}
scoped_refptr<webrtc::AudioSourceInterface>
MockPeerConnectionDependencyFactory::CreateLocalAudioSource(
const webrtc::MediaConstraintsInterface* constraints) {
last_audio_source_ =
- new talk_base::RefCountedObject<MockAudioSource>(constraints);
+ new rtc::RefCountedObject<MockAudioSource>(constraints);
return last_audio_source_;
}
@@ -464,7 +454,7 @@ scoped_refptr<webrtc::VideoSourceInterface>
MockPeerConnectionDependencyFactory::CreateVideoSource(
cricket::VideoCapturer* capturer,
const blink::WebMediaConstraints& constraints) {
- last_video_source_ = new talk_base::RefCountedObject<MockVideoSource>();
+ last_video_source_ = new rtc::RefCountedObject<MockVideoSource>();
last_video_source_->SetVideoCapturer(capturer);
return last_video_source_;
}
@@ -478,7 +468,7 @@ MockPeerConnectionDependencyFactory::CreateWebAudioSource(
scoped_refptr<webrtc::MediaStreamInterface>
MockPeerConnectionDependencyFactory::CreateLocalMediaStream(
const std::string& label) {
- return new talk_base::RefCountedObject<MockMediaStream>(label);
+ return new rtc::RefCountedObject<MockMediaStream>(label);
}
scoped_refptr<webrtc::VideoTrackInterface>
@@ -486,7 +476,7 @@ MockPeerConnectionDependencyFactory::CreateLocalVideoTrack(
const std::string& id,
webrtc::VideoSourceInterface* source) {
scoped_refptr<webrtc::VideoTrackInterface> track(
- new talk_base::RefCountedObject<MockWebRtcVideoTrack>(
+ new rtc::RefCountedObject<MockWebRtcVideoTrack>(
id, source));
return track;
}
@@ -496,11 +486,11 @@ MockPeerConnectionDependencyFactory::CreateLocalVideoTrack(
const std::string& id,
cricket::VideoCapturer* capturer) {
scoped_refptr<MockVideoSource> source =
- new talk_base::RefCountedObject<MockVideoSource>();
+ new rtc::RefCountedObject<MockVideoSource>();
source->SetVideoCapturer(capturer);
return
- new talk_base::RefCountedObject<MockWebRtcVideoTrack>(id, source.get());
+ new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, source.get());
}
SessionDescriptionInterface*
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h
index 12f4d24d863..b04282411c7 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h
@@ -17,13 +17,14 @@
namespace content {
class WebAudioCapturerSource;
+typedef std::set<webrtc::ObserverInterface*> ObserverSet;
class MockVideoRenderer : public cricket::VideoRenderer {
public:
MockVideoRenderer();
- virtual ~MockVideoRenderer();
- virtual bool SetSize(int width, int height, int reserved) OVERRIDE;
- virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE;
+ ~MockVideoRenderer() override;
+ bool SetSize(int width, int height, int reserved) override;
+ bool RenderFrame(const cricket::VideoFrame* frame) override;
int width() const { return width_; }
int height() const { return height_; }
@@ -39,14 +40,14 @@ class MockVideoSource : public webrtc::VideoSourceInterface {
public:
MockVideoSource();
- virtual void RegisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual void UnregisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual MediaSourceInterface::SourceState state() const OVERRIDE;
- virtual cricket::VideoCapturer* GetVideoCapturer() OVERRIDE;
- virtual void AddSink(cricket::VideoRenderer* output) OVERRIDE;
- virtual void RemoveSink(cricket::VideoRenderer* output) OVERRIDE;
- virtual cricket::VideoRenderer* FrameInput() OVERRIDE;
- virtual const cricket::VideoOptions* options() const OVERRIDE;
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+ MediaSourceInterface::SourceState state() const override;
+ cricket::VideoCapturer* GetVideoCapturer() override;
+ void AddSink(cricket::VideoRenderer* output) override;
+ void RemoveSink(cricket::VideoRenderer* output) override;
+ cricket::VideoRenderer* FrameInput() override;
+ const cricket::VideoOptions* options() const override;
// Changes the state of the source to live and notifies the observer.
void SetLive();
@@ -61,7 +62,7 @@ class MockVideoSource : public webrtc::VideoSourceInterface {
int GetFrameNum() const;
protected:
- virtual ~MockVideoSource();
+ ~MockVideoSource() override;
private:
void FireOnChanged();
@@ -77,9 +78,9 @@ class MockAudioSource : public webrtc::AudioSourceInterface {
explicit MockAudioSource(
const webrtc::MediaConstraintsInterface* constraints);
- virtual void RegisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual void UnregisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual MediaSourceInterface::SourceState state() const OVERRIDE;
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+ MediaSourceInterface::SourceState state() const override;
// Changes the state of the source to live and notifies the observer.
void SetLive();
@@ -96,10 +97,10 @@ class MockAudioSource : public webrtc::AudioSourceInterface {
}
protected:
- virtual ~MockAudioSource();
+ ~MockAudioSource() override;
private:
- webrtc::ObserverInterface* observer_;
+ ObserverSet observers_;
MediaSourceInterface::SourceState state_;
webrtc::MediaConstraintsInterface::Constraints optional_constraints_;
webrtc::MediaConstraintsInterface::Constraints mandatory_constraints_;
@@ -109,28 +110,27 @@ class MockWebRtcVideoTrack : public webrtc::VideoTrackInterface {
public:
MockWebRtcVideoTrack(const std::string& id,
webrtc::VideoSourceInterface* source);
- virtual void AddRenderer(webrtc::VideoRendererInterface* renderer) OVERRIDE;
- virtual void RemoveRenderer(
- webrtc::VideoRendererInterface* renderer) OVERRIDE;
- virtual std::string kind() const OVERRIDE;
- virtual std::string id() const OVERRIDE;
- virtual bool enabled() const OVERRIDE;
- virtual TrackState state() const OVERRIDE;
- virtual bool set_enabled(bool enable) OVERRIDE;
- virtual bool set_state(TrackState new_state) OVERRIDE;
- virtual void RegisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual void UnregisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual webrtc::VideoSourceInterface* GetSource() const OVERRIDE;
+ void AddRenderer(webrtc::VideoRendererInterface* renderer) override;
+ void RemoveRenderer(webrtc::VideoRendererInterface* renderer) override;
+ std::string kind() const override;
+ std::string id() const override;
+ bool enabled() const override;
+ TrackState state() const override;
+ bool set_enabled(bool enable) override;
+ bool set_state(TrackState new_state) override;
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
+ webrtc::VideoSourceInterface* GetSource() const override;
protected:
- virtual ~MockWebRtcVideoTrack();
+ ~MockWebRtcVideoTrack() override;
private:
bool enabled_;
std::string id_;
TrackState state_;
scoped_refptr<webrtc::VideoSourceInterface> source_;
- webrtc::ObserverInterface* observer_;
+ ObserverSet observers_;
webrtc::VideoRendererInterface* renderer_;
};
@@ -138,22 +138,22 @@ class MockMediaStream : public webrtc::MediaStreamInterface {
public:
explicit MockMediaStream(const std::string& label);
- virtual bool AddTrack(webrtc::AudioTrackInterface* track) OVERRIDE;
- virtual bool AddTrack(webrtc::VideoTrackInterface* track) OVERRIDE;
- virtual bool RemoveTrack(webrtc::AudioTrackInterface* track) OVERRIDE;
- virtual bool RemoveTrack(webrtc::VideoTrackInterface* track) OVERRIDE;
- virtual std::string label() const OVERRIDE;
- virtual webrtc::AudioTrackVector GetAudioTracks() OVERRIDE;
- virtual webrtc::VideoTrackVector GetVideoTracks() OVERRIDE;
- virtual talk_base::scoped_refptr<webrtc::AudioTrackInterface>
- FindAudioTrack(const std::string& track_id) OVERRIDE;
- virtual talk_base::scoped_refptr<webrtc::VideoTrackInterface>
- FindVideoTrack(const std::string& track_id) OVERRIDE;
- virtual void RegisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
- virtual void UnregisterObserver(webrtc::ObserverInterface* observer) OVERRIDE;
+ bool AddTrack(webrtc::AudioTrackInterface* track) override;
+ bool AddTrack(webrtc::VideoTrackInterface* track) override;
+ bool RemoveTrack(webrtc::AudioTrackInterface* track) override;
+ bool RemoveTrack(webrtc::VideoTrackInterface* track) override;
+ std::string label() const override;
+ webrtc::AudioTrackVector GetAudioTracks() override;
+ webrtc::VideoTrackVector GetVideoTracks() override;
+ rtc::scoped_refptr<webrtc::AudioTrackInterface> FindAudioTrack(
+ const std::string& track_id) override;
+ rtc::scoped_refptr<webrtc::VideoTrackInterface> FindVideoTrack(
+ const std::string& track_id) override;
+ void RegisterObserver(webrtc::ObserverInterface* observer) override;
+ void UnregisterObserver(webrtc::ObserverInterface* observer) override;
protected:
- virtual ~MockMediaStream();
+ ~MockMediaStream() override;
private:
void NotifyObservers();
@@ -162,7 +162,6 @@ class MockMediaStream : public webrtc::MediaStreamInterface {
webrtc::AudioTrackVector audio_track_vector_;
webrtc::VideoTrackVector video_track_vector_;
- typedef std::set<webrtc::ObserverInterface*> ObserverSet;
ObserverSet observers_;
};
@@ -172,51 +171,49 @@ class MockPeerConnectionDependencyFactory
: public PeerConnectionDependencyFactory {
public:
MockPeerConnectionDependencyFactory();
- virtual ~MockPeerConnectionDependencyFactory();
+ ~MockPeerConnectionDependencyFactory() override;
- virtual scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
- const webrtc::PeerConnectionInterface::IceServers& ice_servers,
+ scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* frame,
- webrtc::PeerConnectionObserver* observer) OVERRIDE;
- virtual scoped_refptr<webrtc::AudioSourceInterface>
- CreateLocalAudioSource(
- const webrtc::MediaConstraintsInterface* constraints) OVERRIDE;
- virtual WebRtcVideoCapturerAdapter* CreateVideoCapturer(
- bool is_screen_capture) OVERRIDE;
- virtual scoped_refptr<webrtc::VideoSourceInterface>
- CreateVideoSource(
- cricket::VideoCapturer* capturer,
- const blink::WebMediaConstraints& constraints) OVERRIDE;
- virtual scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource(
- blink::WebMediaStreamSource* source) OVERRIDE;
- virtual scoped_refptr<webrtc::MediaStreamInterface>
- CreateLocalMediaStream(const std::string& label) OVERRIDE;
- virtual scoped_refptr<webrtc::VideoTrackInterface>
- CreateLocalVideoTrack(const std::string& id,
- webrtc::VideoSourceInterface* source) OVERRIDE;
- virtual scoped_refptr<webrtc::VideoTrackInterface>
- CreateLocalVideoTrack(const std::string& id,
- cricket::VideoCapturer* capturer) OVERRIDE;
- virtual webrtc::SessionDescriptionInterface* CreateSessionDescription(
+ webrtc::PeerConnectionObserver* observer) override;
+ scoped_refptr<webrtc::AudioSourceInterface> CreateLocalAudioSource(
+ const webrtc::MediaConstraintsInterface* constraints) override;
+ WebRtcVideoCapturerAdapter* CreateVideoCapturer(
+ bool is_screen_capture) override;
+ scoped_refptr<webrtc::VideoSourceInterface> CreateVideoSource(
+ cricket::VideoCapturer* capturer,
+ const blink::WebMediaConstraints& constraints) override;
+ scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource(
+ blink::WebMediaStreamSource* source) override;
+ scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(
+ const std::string& label) override;
+ scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
+ const std::string& id,
+ webrtc::VideoSourceInterface* source) override;
+ scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
+ const std::string& id,
+ cricket::VideoCapturer* capturer) override;
+ webrtc::SessionDescriptionInterface* CreateSessionDescription(
const std::string& type,
const std::string& sdp,
- webrtc::SdpParseError* error) OVERRIDE;
- virtual webrtc::IceCandidateInterface* CreateIceCandidate(
+ webrtc::SdpParseError* error) override;
+ webrtc::IceCandidateInterface* CreateIceCandidate(
const std::string& sdp_mid,
int sdp_mline_index,
- const std::string& sdp) OVERRIDE;
+ const std::string& sdp) override;
- virtual scoped_refptr<WebRtcAudioCapturer> CreateAudioCapturer(
- int render_view_id, const StreamDeviceInfo& device_info,
+ scoped_refptr<WebRtcAudioCapturer> CreateAudioCapturer(
+ int render_view_id,
+ const StreamDeviceInfo& device_info,
const blink::WebMediaConstraints& constraints,
- MediaStreamAudioSource* audio_source) OVERRIDE;
+ MediaStreamAudioSource* audio_source) override;
void FailToCreateNextAudioCapturer() {
fail_to_create_next_audio_capturer_ = true;
}
- virtual void StartLocalAudioTrack(
- WebRtcLocalAudioTrack* audio_track) OVERRIDE;
+ void StartLocalAudioTrack(WebRtcLocalAudioTrack* audio_track) override;
MockAudioSource* last_audio_source() { return last_audio_source_.get(); }
MockVideoSource* last_video_source() { return last_video_source_.get(); }
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index f2f7f1d109b..1bc3c0536a0 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -27,6 +27,7 @@
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "content/renderer/media/webrtc_logging.h"
#include "content/renderer/media/webrtc_uma_histograms.h"
#include "content/renderer/p2p/ipc_network_manager.h"
#include "content/renderer/p2p/ipc_socket_factory.h"
@@ -44,7 +45,7 @@
#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
#if defined(USE_OPENSSL)
-#include "third_party/libjingle/source/talk/base/ssladapter.h"
+#include "third_party/webrtc/base/ssladapter.h"
#else
#include "net/socket/nss_ssl_util.h"
#endif
@@ -74,7 +75,7 @@ struct {
void HarmonizeConstraintsAndEffects(RTCMediaConstraints* constraints,
int* effects) {
if (*effects != media::AudioParameters::NO_EFFECTS) {
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kConstraintEffectMap); ++i) {
+ for (size_t i = 0; i < arraysize(kConstraintEffectMap); ++i) {
bool value;
size_t is_mandatory = 0;
if (!webrtc::FindConstraint(constraints,
@@ -98,6 +99,14 @@ void HarmonizeConstraintsAndEffects(RTCMediaConstraints* constraints,
}
DVLOG(1) << "Disabling constraint: "
<< kConstraintEffectMap[i].constraint;
+ } else if (kConstraintEffectMap[i].effect ==
+ media::AudioParameters::DUCKING && value && !is_mandatory) {
+ // Special handling of the DUCKING flag that sets the optional
+ // constraint to |false| to match what the device will support.
+ constraints->AddOptional(kConstraintEffectMap[i].constraint,
+ webrtc::MediaConstraintsInterface::kValueFalse, true);
+ // No need to modify |effects| since the ducking flag is already off.
+ DCHECK((*effects & media::AudioParameters::DUCKING) == 0);
}
}
}
@@ -107,25 +116,22 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
public:
P2PPortAllocatorFactory(
P2PSocketDispatcher* socket_dispatcher,
- talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
- blink::WebFrame* web_frame)
+ rtc::NetworkManager* network_manager,
+ rtc::PacketSocketFactory* socket_factory)
: socket_dispatcher_(socket_dispatcher),
network_manager_(network_manager),
- socket_factory_(socket_factory),
- web_frame_(web_frame) {
+ socket_factory_(socket_factory) {
}
- virtual cricket::PortAllocator* CreatePortAllocator(
+ cricket::PortAllocator* CreatePortAllocator(
const std::vector<StunConfiguration>& stun_servers,
- const std::vector<TurnConfiguration>& turn_configurations) OVERRIDE {
- CHECK(web_frame_);
+ const std::vector<TurnConfiguration>& turn_configurations) override {
P2PPortAllocator::Config config;
- if (stun_servers.size() > 0) {
- config.stun_server = stun_servers[0].server.hostname();
- config.stun_server_port = stun_servers[0].server.port();
+ for (size_t i = 0; i < stun_servers.size(); ++i) {
+ config.stun_servers.insert(rtc::SocketAddress(
+ stun_servers[i].server.hostname(),
+ stun_servers[i].server.port()));
}
- config.legacy_relay = false;
for (size_t i = 0; i < turn_configurations.size(); ++i) {
P2PPortAllocator::Config::RelayServerConfig relay_config;
relay_config.server_address = turn_configurations[i].server.hostname();
@@ -135,30 +141,26 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
relay_config.transport_type = turn_configurations[i].transport_type;
relay_config.secure = turn_configurations[i].secure;
config.relays.push_back(relay_config);
- }
- // Use first turn server as the stun server.
- if (turn_configurations.size() > 0) {
- config.stun_server = config.relays[0].server_address;
- config.stun_server_port = config.relays[0].port;
+ // Use turn servers as stun servers.
+ config.stun_servers.insert(rtc::SocketAddress(
+ turn_configurations[i].server.hostname(),
+ turn_configurations[i].server.port()));
}
return new P2PPortAllocator(
- web_frame_, socket_dispatcher_.get(), network_manager_,
- socket_factory_, config);
+ socket_dispatcher_.get(), network_manager_, socket_factory_, config);
}
protected:
- virtual ~P2PPortAllocatorFactory() {}
+ ~P2PPortAllocatorFactory() override {}
private:
scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
// |network_manager_| and |socket_factory_| are a weak references, owned by
// PeerConnectionDependencyFactory.
- talk_base::NetworkManager* network_manager_;
- talk_base::PacketSocketFactory* socket_factory_;
- // Raw ptr to the WebFrame that created the P2PPortAllocatorFactory.
- blink::WebFrame* web_frame_;
+ rtc::NetworkManager* network_manager_;
+ rtc::PacketSocketFactory* socket_factory_;
};
PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
@@ -167,12 +169,13 @@ PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
p2p_socket_dispatcher_(p2p_socket_dispatcher),
signaling_thread_(NULL),
worker_thread_(NULL),
+ chrome_signaling_thread_("Chrome_libJingle_Signaling"),
chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
}
PeerConnectionDependencyFactory::~PeerConnectionDependencyFactory() {
CleanupPeerConnectionFactory();
- if (aec_dump_message_filter_)
+ if (aec_dump_message_filter_.get())
aec_dump_message_filter_->RemoveDelegate(this);
}
@@ -208,15 +211,17 @@ bool PeerConnectionDependencyFactory::InitializeMediaStreamAudioSource(
CreateAudioCapturer(render_view_id, device_info, audio_constraints,
source_data));
if (!capturer.get()) {
- DLOG(WARNING) << "Failed to create the capturer for device "
- << device_info.device.id;
+ const std::string log_string =
+ "PCDF::InitializeMediaStreamAudioSource: fails to create capturer";
+ WebRtcLogMessage(log_string);
+ DVLOG(1) << log_string;
// TODO(xians): Don't we need to check if source_observer is observing
// something? If not, then it looks like we have a leak here.
// OTOH, if it _is_ observing something, then the callback might
// be called multiple times which is likely also a bug.
return false;
}
- source_data->SetAudioCapturer(capturer);
+ source_data->SetAudioCapturer(capturer.get());
// Creates a LocalAudioSource object which holds audio options.
// TODO(xians): The option should apply to the track instead of the source.
@@ -229,7 +234,7 @@ bool PeerConnectionDependencyFactory::InitializeMediaStreamAudioSource(
DLOG(WARNING) << "Failed to create rtc LocalAudioSource.";
return false;
}
- source_data->SetLocalAudioSource(rtc_source);
+ source_data->SetLocalAudioSource(rtc_source.get());
return true;
}
@@ -240,7 +245,7 @@ PeerConnectionDependencyFactory::CreateVideoCapturer(
// before we can use an instance of a WebRtcVideoCapturerAdapter. This is
// since the base class of WebRtcVideoCapturerAdapter is a
// cricket::VideoCapturer and it uses the libjingle thread wrappers.
- if (!GetPcFactory())
+ if (!GetPcFactory().get())
return NULL;
return new WebRtcVideoCapturerAdapter(is_screeencast);
}
@@ -257,9 +262,9 @@ PeerConnectionDependencyFactory::CreateVideoSource(
const scoped_refptr<webrtc::PeerConnectionFactoryInterface>&
PeerConnectionDependencyFactory::GetPcFactory() {
- if (!pc_factory_)
+ if (!pc_factory_.get())
CreatePeerConnectionFactory();
- CHECK(pc_factory_);
+ CHECK(pc_factory_.get());
return pc_factory_;
}
@@ -269,15 +274,16 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
DCHECK(!worker_thread_);
DCHECK(!network_manager_);
DCHECK(!socket_factory_);
+ DCHECK(!chrome_signaling_thread_.IsRunning());
DCHECK(!chrome_worker_thread_.IsRunning());
DVLOG(1) << "PeerConnectionDependencyFactory::CreatePeerConnectionFactory()";
+ // To allow sending to the signaling/worker threads.
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
- signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
- CHECK(signaling_thread_);
+ CHECK(chrome_signaling_thread_.Start());
CHECK(chrome_worker_thread_.Start());
base::WaitableEvent start_worker_event(true, false);
@@ -286,22 +292,21 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
base::Unretained(this),
&worker_thread_,
&start_worker_event));
- start_worker_event.Wait();
- CHECK(worker_thread_);
base::WaitableEvent create_network_manager_event(true, false);
chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
&PeerConnectionDependencyFactory::CreateIpcNetworkManagerOnWorkerThread,
base::Unretained(this),
&create_network_manager_event));
+
+ start_worker_event.Wait();
create_network_manager_event.Wait();
- socket_factory_.reset(
- new IpcPacketSocketFactory(p2p_socket_dispatcher_.get()));
+ CHECK(worker_thread_);
// Init SSL, which will be needed by PeerConnection.
#if defined(USE_OPENSSL)
- if (!talk_base::InitializeSSL()) {
+ if (!rtc::InitializeSSL()) {
LOG(ERROR) << "Failed on InitializeSSL.";
NOTREACHED();
return;
@@ -311,19 +316,53 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
net::EnsureNSSSSLInit();
#endif
+ base::WaitableEvent start_signaling_event(true, false);
+ chrome_signaling_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &PeerConnectionDependencyFactory::InitializeSignalingThread,
+ base::Unretained(this),
+ RenderThreadImpl::current()->GetGpuFactories(),
+ &start_signaling_event));
+
+ // TODO(xians): Remove the following code after kDisableAudioTrackProcessing
+ // is removed.
+ if (!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
+ aec_dump_message_filter_ = AecDumpMessageFilter::Get();
+ // In unit tests not creating a message filter, |aec_dump_message_filter_|
+ // will be NULL. We can just ignore that. Other unit tests and browser tests
+ // ensure that we do get the filter when we should.
+ if (aec_dump_message_filter_.get())
+ aec_dump_message_filter_->AddDelegate(this);
+ }
+
+ start_signaling_event.Wait();
+ CHECK(signaling_thread_);
+}
+
+void PeerConnectionDependencyFactory::InitializeSignalingThread(
+ const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories,
+ base::WaitableEvent* event) {
+ DCHECK(chrome_signaling_thread_.task_runner()->BelongsToCurrentThread());
+ DCHECK(worker_thread_);
+ DCHECK(p2p_socket_dispatcher_.get());
+
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
+
+ EnsureWebRtcAudioDeviceImpl();
+
+ socket_factory_.reset(
+ new IpcPacketSocketFactory(p2p_socket_dispatcher_.get()));
+
scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
- scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories =
- RenderThreadImpl::current()->GetGpuFactories();
- if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding)) {
- if (gpu_factories)
+ if (gpu_factories.get()) {
+ if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWDecoding))
decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
- }
- if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
- if (gpu_factories)
+ if (!cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
encoder_factory.reset(new RTCVideoEncoderFactory(gpu_factories));
}
@@ -332,33 +371,18 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
encoder_factory.reset();
#endif
- EnsureWebRtcAudioDeviceImpl();
-
- scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
- webrtc::CreatePeerConnectionFactory(worker_thread_,
- signaling_thread_,
- audio_device_.get(),
- encoder_factory.release(),
- decoder_factory.release()));
- CHECK(factory);
+ pc_factory_ = webrtc::CreatePeerConnectionFactory(
+ worker_thread_, signaling_thread_, audio_device_.get(),
+ encoder_factory.release(), decoder_factory.release());
+ CHECK(pc_factory_.get());
- pc_factory_ = factory;
webrtc::PeerConnectionFactoryInterface::Options factory_options;
factory_options.disable_sctp_data_channels = false;
factory_options.disable_encryption =
cmd_line->HasSwitch(switches::kDisableWebRtcEncryption);
pc_factory_->SetOptions(factory_options);
- // TODO(xians): Remove the following code after kDisableAudioTrackProcessing
- // is removed.
- if (!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
- aec_dump_message_filter_ = AecDumpMessageFilter::Get();
- // In unit tests not creating a message filter, |aec_dump_message_filter_|
- // will be NULL. We can just ignore that. Other unit tests and browser tests
- // ensure that we do get the filter when we should.
- if (aec_dump_message_filter_)
- aec_dump_message_filter_->AddDelegate(this);
- }
+ event->Signal();
}
bool PeerConnectionDependencyFactory::PeerConnectionFactoryCreated() {
@@ -367,31 +391,30 @@ bool PeerConnectionDependencyFactory::PeerConnectionFactoryCreated() {
scoped_refptr<webrtc::PeerConnectionInterface>
PeerConnectionDependencyFactory::CreatePeerConnection(
- const webrtc::PeerConnectionInterface::IceServers& ice_servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* web_frame,
webrtc::PeerConnectionObserver* observer) {
CHECK(web_frame);
CHECK(observer);
- if (!GetPcFactory())
+ if (!GetPcFactory().get())
return NULL;
scoped_refptr<P2PPortAllocatorFactory> pa_factory =
- new talk_base::RefCountedObject<P2PPortAllocatorFactory>(
+ new rtc::RefCountedObject<P2PPortAllocatorFactory>(
p2p_socket_dispatcher_.get(),
network_manager_,
- socket_factory_.get(),
- web_frame);
+ socket_factory_.get());
PeerConnectionIdentityService* identity_service =
new PeerConnectionIdentityService(
GURL(web_frame->document().url().spec()).GetOrigin());
- return GetPcFactory()->CreatePeerConnection(ice_servers,
- constraints,
- pa_factory.get(),
- identity_service,
- observer).get();
+ return GetPcFactory()->CreatePeerConnection(config,
+ constraints,
+ pa_factory.get(),
+ identity_service,
+ observer).get();
}
scoped_refptr<webrtc::MediaStreamInterface>
@@ -441,10 +464,8 @@ void PeerConnectionDependencyFactory::CreateLocalAudioTrack(
// TODO(xians): Merge |source| to the capturer(). We can't do this today
// because only one capturer() is supported while one |source| is created
// for each audio track.
- scoped_ptr<WebRtcLocalAudioTrack> audio_track(
- new WebRtcLocalAudioTrack(adapter,
- source_data->GetAudioCapturer(),
- webaudio_source));
+ scoped_ptr<WebRtcLocalAudioTrack> audio_track(new WebRtcLocalAudioTrack(
+ adapter.get(), source_data->GetAudioCapturer(), webaudio_source.get()));
StartLocalAudioTrack(audio_track.get());
@@ -541,7 +562,7 @@ PeerConnectionDependencyFactory::GetWebRtcAudioDevice() {
}
void PeerConnectionDependencyFactory::InitializeWorkerThread(
- talk_base::Thread** thread,
+ rtc::Thread** thread,
base::WaitableEvent* event) {
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
@@ -599,28 +620,18 @@ PeerConnectionDependencyFactory::CreateAudioCapturer(
audio_source);
}
-void PeerConnectionDependencyFactory::AddNativeAudioTrackToBlinkTrack(
- webrtc::MediaStreamTrackInterface* native_track,
- const blink::WebMediaStreamTrack& webkit_track,
- bool is_local_track) {
- DCHECK(!webkit_track.isNull() && !webkit_track.extraData());
- DCHECK_EQ(blink::WebMediaStreamSource::TypeAudio,
- webkit_track.source().type());
- blink::WebMediaStreamTrack track = webkit_track;
-
- DVLOG(1) << "AddNativeTrackToBlinkTrack() audio";
- track.setExtraData(
- new MediaStreamTrack(
- static_cast<webrtc::AudioTrackInterface*>(native_track),
- is_local_track));
-}
-
scoped_refptr<base::MessageLoopProxy>
PeerConnectionDependencyFactory::GetWebRtcWorkerThread() const {
DCHECK(CalledOnValidThread());
return chrome_worker_thread_.message_loop_proxy();
}
+scoped_refptr<base::MessageLoopProxy>
+PeerConnectionDependencyFactory::GetWebRtcSignalingThread() const {
+ DCHECK(CalledOnValidThread());
+ return chrome_signaling_thread_.message_loop_proxy();
+}
+
void PeerConnectionDependencyFactory::OnAecDumpFile(
const IPC::PlatformFileForTransit& file_handle) {
DCHECK(CalledOnValidThread());
@@ -648,7 +659,7 @@ void PeerConnectionDependencyFactory::OnIpcClosing() {
}
void PeerConnectionDependencyFactory::EnsureWebRtcAudioDeviceImpl() {
- if (audio_device_)
+ if (audio_device_.get())
return;
audio_device_ = new WebRtcAudioDeviceImpl();
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index 51699359eb0..67eae9d0ec4 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -22,7 +22,7 @@ namespace base {
class WaitableEvent;
}
-namespace talk_base {
+namespace rtc {
class NetworkManager;
class PacketSocketFactory;
class Thread;
@@ -103,7 +103,7 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
// The PeerConnection object is owned by PeerConnectionHandler.
virtual scoped_refptr<webrtc::PeerConnectionInterface>
CreatePeerConnection(
- const webrtc::PeerConnectionInterface::IceServers& ice_servers,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config,
const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* web_frame,
webrtc::PeerConnectionObserver* observer);
@@ -123,20 +123,15 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
WebRtcAudioDeviceImpl* GetWebRtcAudioDevice();
- static void AddNativeAudioTrackToBlinkTrack(
- webrtc::MediaStreamTrackInterface* native_track,
- const blink::WebMediaStreamTrack& webkit_track,
- bool is_local_track);
-
scoped_refptr<base::MessageLoopProxy> GetWebRtcWorkerThread() const;
+ scoped_refptr<base::MessageLoopProxy> GetWebRtcSignalingThread() const;
// AecDumpMessageFilter::AecDumpDelegate implementation.
// TODO(xians): Remove when option to disable audio track processing is
// removed.
- virtual void OnAecDumpFile(
- const IPC::PlatformFileForTransit& file_handle) OVERRIDE;
- virtual void OnDisableAecDump() OVERRIDE;
- virtual void OnIpcClosing() OVERRIDE;
+ void OnAecDumpFile(const IPC::PlatformFileForTransit& file_handle) override;
+ void OnDisableAecDump() override;
+ void OnIpcClosing() override;
protected:
// Asks the PeerConnection factory to create a Local Audio Source.
@@ -179,7 +174,11 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
// creating PeerConnection objects.
void CreatePeerConnectionFactory();
- void InitializeWorkerThread(talk_base::Thread** thread,
+ void InitializeSignalingThread(
+ const scoped_refptr<media::GpuVideoAcceleratorFactories>& gpu_factories,
+ base::WaitableEvent* event);
+
+ void InitializeWorkerThread(rtc::Thread** thread,
base::WaitableEvent* event);
void CreateIpcNetworkManagerOnWorkerThread(base::WaitableEvent* event);
@@ -206,8 +205,9 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
// PeerConnection threads. signaling_thread_ is created from the
// "current" chrome thread.
- talk_base::Thread* signaling_thread_;
- talk_base::Thread* worker_thread_;
+ rtc::Thread* signaling_thread_;
+ rtc::Thread* worker_thread_;
+ base::Thread chrome_signaling_thread_;
base::Thread chrome_worker_thread_;
DISALLOW_COPY_AND_ASSIGN(PeerConnectionDependencyFactory);
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc
index 72f564e40ad..4009d978371 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/message_loop/message_loop.h"
#include "content/renderer/media/mock_web_rtc_peer_connection_handler_client.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -11,11 +12,12 @@ namespace content {
class PeerConnectionDependencyFactoryTest : public ::testing::Test {
public:
- virtual void SetUp() {
+ void SetUp() override {
dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
}
protected:
+ base::MessageLoop message_loop_;
scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
};
diff --git a/chromium/content/renderer/media/webrtc/video_destination_handler.cc b/chromium/content/renderer/media/webrtc/video_destination_handler.cc
index 84594bbaff5..6e254699f83 100644
--- a/chromium/content/renderer/media/webrtc/video_destination_handler.cc
+++ b/chromium/content/renderer/media/webrtc/video_destination_handler.cc
@@ -7,6 +7,7 @@
#include <string>
#include "base/base64.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -83,6 +84,7 @@ PpFrameWriter::~PpFrameWriter() {
void PpFrameWriter::GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) {
DCHECK(CalledOnValidThread());
DVLOG(3) << "PpFrameWriter::GetCurrentSupportedFormats()";
@@ -93,22 +95,25 @@ void PpFrameWriter::GetCurrentSupportedFormats(
}
void PpFrameWriter::StartSourceImpl(
- const media::VideoCaptureParams& params,
+ const media::VideoCaptureFormat& format,
const VideoCaptureDeliverFrameCB& frame_callback) {
DCHECK(CalledOnValidThread());
- DCHECK(!delegate_);
+ DCHECK(!delegate_.get());
DVLOG(3) << "PpFrameWriter::StartSourceImpl()";
delegate_ = new FrameWriterDelegate(io_message_loop(), frame_callback);
- OnStartDone(true);
+ OnStartDone(MEDIA_DEVICE_OK);
}
void PpFrameWriter::StopSourceImpl() {
DCHECK(CalledOnValidThread());
}
+// Note: PutFrame must copy or process image_data directly in this function,
+// because it may be overwritten as soon as we return from this function.
void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
int64 time_stamp_ns) {
DCHECK(CalledOnValidThread());
+ TRACE_EVENT0("video", "PpFrameWriter::PutFrame");
DVLOG(3) << "PpFrameWriter::PutFrame()";
if (!image_data) {
@@ -128,7 +133,15 @@ void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
return;
}
- const gfx::Size frame_size(bitmap->width(), bitmap->height());
+ const uint8* src_data = static_cast<uint8*>(bitmap->getPixels());
+ const int src_stride = static_cast<int>(bitmap->rowBytes());
+ const int width = bitmap->width();
+ const int height = bitmap->height();
+
+ // We only support PP_IMAGEDATAFORMAT_BGRA_PREMUL at the moment.
+ DCHECK(image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL);
+
+ const gfx::Size frame_size(width, height);
if (state() != MediaStreamVideoSource::STARTED)
return;
@@ -136,27 +149,24 @@ void PpFrameWriter::PutFrame(PPB_ImageData_Impl* image_data,
const base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
time_stamp_ns / base::Time::kNanosecondsPerMicrosecond);
- // TODO(perkj): It would be more efficient to use I420 here. Using YV12 will
- // force a copy into a tightly packed I420 frame in
- // WebRtcVideoCapturerAdapter before the frame is delivered to libJingle.
- // crbug/359587.
scoped_refptr<media::VideoFrame> new_frame =
frame_pool_.CreateFrame(media::VideoFrame::YV12, frame_size,
gfx::Rect(frame_size), frame_size, timestamp);
media::VideoCaptureFormat format(
frame_size,
- MediaStreamVideoSource::kDefaultFrameRate,
+ MediaStreamVideoSource::kUnknownFrameRate,
media::PIXEL_FORMAT_YV12);
- libyuv::BGRAToI420(reinterpret_cast<uint8*>(bitmap->getPixels()),
- bitmap->rowBytes(),
+ libyuv::ARGBToI420(src_data,
+ src_stride,
new_frame->data(media::VideoFrame::kYPlane),
new_frame->stride(media::VideoFrame::kYPlane),
new_frame->data(media::VideoFrame::kUPlane),
new_frame->stride(media::VideoFrame::kUPlane),
new_frame->data(media::VideoFrame::kVPlane),
new_frame->stride(media::VideoFrame::kVPlane),
- frame_size.width(), frame_size.height());
+ width,
+ height);
delegate_->DeliverFrame(new_frame, format);
}
@@ -174,7 +184,7 @@ class PpFrameWriterProxy : public FrameWriterInterface {
virtual ~PpFrameWriterProxy() {}
virtual void PutFrame(PPB_ImageData_Impl* image_data,
- int64 time_stamp_ns) OVERRIDE {
+ int64 time_stamp_ns) override {
writer_->PutFrame(image_data, time_stamp_ns);
}
diff --git a/chromium/content/renderer/media/webrtc/video_destination_handler.h b/chromium/content/renderer/media/webrtc/video_destination_handler.h
index e84fdd603df..2855e6feb82 100644
--- a/chromium/content/renderer/media/webrtc/video_destination_handler.h
+++ b/chromium/content/renderer/media/webrtc/video_destination_handler.h
@@ -46,17 +46,18 @@ class CONTENT_EXPORT PpFrameWriter
// FrameWriterInterface implementation.
// This method will be called by the Pepper host from render thread.
virtual void PutFrame(PPB_ImageData_Impl* image_data,
- int64 time_stamp_ns) OVERRIDE;
+ int64 time_stamp_ns) override;
protected:
// MediaStreamVideoSource implementation.
- virtual void GetCurrentSupportedFormats(
+ void GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
- const VideoCaptureDeviceFormatsCB& callback) OVERRIDE;
- virtual void StartSourceImpl(
- const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& frame_callback) OVERRIDE;
- virtual void StopSourceImpl() OVERRIDE;
+ double max_requested_frame_rate,
+ const VideoCaptureDeviceFormatsCB& callback) override;
+ void StartSourceImpl(
+ const media::VideoCaptureFormat& format,
+ const VideoCaptureDeliverFrameCB& frame_callback) override;
+ void StopSourceImpl() override;
private:
media::VideoFramePool frame_pool_;
@@ -89,4 +90,3 @@ class CONTENT_EXPORT VideoDestinationHandler {
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_VIDEO_DESTINATION_HANDLER_H_
-
diff --git a/chromium/content/renderer/media/webrtc/video_destination_handler_unittest.cc b/chromium/content/renderer/media/webrtc/video_destination_handler_unittest.cc
index 49e9cf7ebcd..806b6f468cd 100644
--- a/chromium/content/renderer/media/webrtc/video_destination_handler_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/video_destination_handler_unittest.cc
@@ -20,6 +20,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
using ::testing::_;
@@ -40,8 +41,9 @@ class VideoDestinationHandlerTest : public PpapiUnittest {
registry_->Init(kTestStreamUrl);
}
- virtual void TearDown() {
+ void TearDown() override {
registry_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
PpapiUnittest::TearDown();
}
@@ -94,11 +96,16 @@ TEST_F(VideoDestinationHandlerTest, PutFrame) {
EXPECT_CALL(sink, OnVideoFrame()).WillOnce(
RunClosure(quit_closure));
- frame_writer->PutFrame(image, 10);
+ frame_writer->PutFrame(image.get(), 10);
run_loop.Run();
+ // Run all pending tasks to let the the test clean up before the test ends.
+ // This is due to that
+ // FrameWriterDelegate::FrameWriterDelegate::DeliverFrame use
+ // PostTaskAndReply to the IO thread and expects the reply to process
+ // on the main render thread to clean up its resources. However, the
+ // QuitClosure above ends before that.
+ base::MessageLoop::current()->RunUntilIdle();
}
- // TODO(perkj): Verify that the track output I420 when
- // https://codereview.chromium.org/213423006/ is landed.
EXPECT_EQ(1, sink.number_of_frames());
native_track->RemoveSink(&sink);
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h
index c1be09a3dac..91d8fa1e8f6 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h
@@ -23,17 +23,17 @@ class WebRtcAudioSinkAdapter : public MediaStreamAudioSink {
public:
explicit WebRtcAudioSinkAdapter(
webrtc::AudioTrackSinkInterface* sink);
- virtual ~WebRtcAudioSinkAdapter();
+ ~WebRtcAudioSinkAdapter() override;
bool IsEqual(const webrtc::AudioTrackSinkInterface* other) const;
private:
// MediaStreamAudioSink implementation.
- virtual void OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames) OVERRIDE;
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
+ void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) override;
+ void OnSetFormat(const media::AudioParameters& params) override;
webrtc::AudioTrackSinkInterface* const sink_;
diff --git a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
index d94edb83d47..f23e403c60d 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
@@ -6,8 +6,10 @@
#include "base/logging.h"
#include "content/renderer/media/media_stream_audio_processor.h"
+#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_audio_sink_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
+#include "content/renderer/render_thread_impl.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
namespace content {
@@ -18,19 +20,35 @@ scoped_refptr<WebRtcLocalAudioTrackAdapter>
WebRtcLocalAudioTrackAdapter::Create(
const std::string& label,
webrtc::AudioSourceInterface* track_source) {
- talk_base::RefCountedObject<WebRtcLocalAudioTrackAdapter>* adapter =
- new talk_base::RefCountedObject<WebRtcLocalAudioTrackAdapter>(
- label, track_source);
+ // TODO(tommi): Change this so that the signaling thread is one of the
+ // parameters to this method.
+ scoped_refptr<base::MessageLoopProxy> signaling_thread;
+ RenderThreadImpl* current = RenderThreadImpl::current();
+ if (current) {
+ PeerConnectionDependencyFactory* pc_factory =
+ current->GetPeerConnectionDependencyFactory();
+ signaling_thread = pc_factory->GetWebRtcSignalingThread();
+ }
+
+ LOG_IF(ERROR, !signaling_thread.get()) << "No signaling thread!";
+
+ rtc::RefCountedObject<WebRtcLocalAudioTrackAdapter>* adapter =
+ new rtc::RefCountedObject<WebRtcLocalAudioTrackAdapter>(
+ label, track_source, signaling_thread);
return adapter;
}
WebRtcLocalAudioTrackAdapter::WebRtcLocalAudioTrackAdapter(
const std::string& label,
- webrtc::AudioSourceInterface* track_source)
+ webrtc::AudioSourceInterface* track_source,
+ const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread)
: webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
owner_(NULL),
track_source_(track_source),
+ signaling_thread_(signaling_thread),
signal_level_(0) {
+ signaling_thread_checker_.DetachFromThread();
+ capture_thread_.DetachFromThread();
}
WebRtcLocalAudioTrackAdapter::~WebRtcLocalAudioTrackAdapter() {
@@ -44,6 +62,11 @@ void WebRtcLocalAudioTrackAdapter::Initialize(WebRtcLocalAudioTrack* owner) {
void WebRtcLocalAudioTrackAdapter::SetAudioProcessor(
const scoped_refptr<MediaStreamAudioProcessor>& processor) {
+ // SetAudioProcessor will be called when a new capture thread has been
+ // initialized, so we need to detach from any current capture thread we're
+ // checking and attach to the current one.
+ capture_thread_.DetachFromThread();
+ DCHECK(capture_thread_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
audio_processor_ = processor;
}
@@ -52,8 +75,24 @@ std::string WebRtcLocalAudioTrackAdapter::kind() const {
return kAudioTrackKind;
}
+bool WebRtcLocalAudioTrackAdapter::set_enabled(bool enable) {
+ // If we're not called on the signaling thread, we need to post a task to
+ // change the state on the correct thread.
+ if (signaling_thread_.get() && !signaling_thread_->BelongsToCurrentThread()) {
+ signaling_thread_->PostTask(FROM_HERE,
+ base::Bind(
+ base::IgnoreResult(&WebRtcLocalAudioTrackAdapter::set_enabled),
+ this, enable));
+ return true;
+ }
+
+ return webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>::
+ set_enabled(enable);
+}
+
void WebRtcLocalAudioTrackAdapter::AddSink(
webrtc::AudioTrackSinkInterface* sink) {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
DCHECK(sink);
#ifndef NDEBUG
// Verify that |sink| has not been added.
@@ -72,6 +111,7 @@ void WebRtcLocalAudioTrackAdapter::AddSink(
void WebRtcLocalAudioTrackAdapter::RemoveSink(
webrtc::AudioTrackSinkInterface* sink) {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
DCHECK(sink);
for (ScopedVector<WebRtcAudioSinkAdapter>::iterator it =
sink_adapters_.begin();
@@ -85,7 +125,8 @@ void WebRtcLocalAudioTrackAdapter::RemoveSink(
}
bool WebRtcLocalAudioTrackAdapter::GetSignalLevel(int* level) {
- base::AutoLock auto_lock(lock_);
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
+
// It is required to provide the signal level after audio processing. In
// case the audio processing is not enabled for the track, we return
// false here in order not to overwrite the value from WebRTC.
@@ -94,27 +135,32 @@ bool WebRtcLocalAudioTrackAdapter::GetSignalLevel(int* level) {
if (!MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled())
return false;
+ base::AutoLock auto_lock(lock_);
*level = signal_level_;
return true;
}
-talk_base::scoped_refptr<webrtc::AudioProcessorInterface>
+rtc::scoped_refptr<webrtc::AudioProcessorInterface>
WebRtcLocalAudioTrackAdapter::GetAudioProcessor() {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
return audio_processor_.get();
}
std::vector<int> WebRtcLocalAudioTrackAdapter::VoeChannels() const {
+ DCHECK(capture_thread_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
return voe_channels_;
}
void WebRtcLocalAudioTrackAdapter::SetSignalLevel(int signal_level) {
+ DCHECK(capture_thread_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
signal_level_ = signal_level;
}
void WebRtcLocalAudioTrackAdapter::AddChannel(int channel_id) {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::AddChannel(channel_id="
<< channel_id << ")";
base::AutoLock auto_lock(lock_);
@@ -129,6 +175,7 @@ void WebRtcLocalAudioTrackAdapter::AddChannel(int channel_id) {
}
void WebRtcLocalAudioTrackAdapter::RemoveChannel(int channel_id) {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::RemoveChannel(channel_id="
<< channel_id << ")";
base::AutoLock auto_lock(lock_);
@@ -139,6 +186,7 @@ void WebRtcLocalAudioTrackAdapter::RemoveChannel(int channel_id) {
}
webrtc::AudioSourceInterface* WebRtcLocalAudioTrackAdapter::GetSource() const {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
return track_source_;
}
diff --git a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
index b35ad4a01ea..52bcd928059 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
@@ -9,7 +9,9 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreamtrack.h"
#include "third_party/libjingle/source/talk/media/base/audiorenderer.h"
@@ -40,9 +42,10 @@ class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
WebRtcLocalAudioTrackAdapter(
const std::string& label,
- webrtc::AudioSourceInterface* track_source);
+ webrtc::AudioSourceInterface* track_source,
+ const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread);
- virtual ~WebRtcLocalAudioTrackAdapter();
+ ~WebRtcLocalAudioTrackAdapter() override;
void Initialize(WebRtcLocalAudioTrack* owner);
@@ -59,31 +62,35 @@ class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
void SetAudioProcessor(
const scoped_refptr<MediaStreamAudioProcessor>& processor);
- private:
// webrtc::MediaStreamTrack implementation.
- virtual std::string kind() const OVERRIDE;
+ std::string kind() const override;
+ bool set_enabled(bool enable) override;
+ private:
// webrtc::AudioTrackInterface implementation.
- virtual void AddSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE;
- virtual void RemoveSink(webrtc::AudioTrackSinkInterface* sink) OVERRIDE;
- virtual bool GetSignalLevel(int* level) OVERRIDE;
- virtual talk_base::scoped_refptr<webrtc::AudioProcessorInterface>
- GetAudioProcessor() OVERRIDE;
+ void AddSink(webrtc::AudioTrackSinkInterface* sink) override;
+ void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override;
+ bool GetSignalLevel(int* level) override;
+ rtc::scoped_refptr<webrtc::AudioProcessorInterface> GetAudioProcessor()
+ override;
// cricket::AudioCapturer implementation.
- virtual void AddChannel(int channel_id) OVERRIDE;
- virtual void RemoveChannel(int channel_id) OVERRIDE;
+ void AddChannel(int channel_id) override;
+ void RemoveChannel(int channel_id) override;
// webrtc::AudioTrackInterface implementation.
- virtual webrtc::AudioSourceInterface* GetSource() const OVERRIDE;
- virtual cricket::AudioRenderer* GetRenderer() OVERRIDE;
+ webrtc::AudioSourceInterface* GetSource() const override;
+ cricket::AudioRenderer* GetRenderer() override;
// Weak reference.
WebRtcLocalAudioTrack* owner_;
// The source of the audio track which handles the audio constraints.
// TODO(xians): merge |track_source_| to |capturer_| in WebRtcLocalAudioTrack.
- talk_base::scoped_refptr<webrtc::AudioSourceInterface> track_source_;
+ rtc::scoped_refptr<webrtc::AudioSourceInterface> track_source_;
+
+ // Libjingle's signaling thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
// The audio processsor that applies audio processing on the data of audio
// track.
@@ -99,6 +106,10 @@ class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
// The amplitude of the signal.
int signal_level_;
+ // Thread checker for libjingle's signaling thread.
+ base::ThreadChecker signaling_thread_checker_;
+ base::ThreadChecker capture_thread_;
+
// Protects |voe_channels_|, |audio_processor_| and |signal_level_|.
mutable base::Lock lock_;
};
diff --git a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc
index 693067ac939..184240cf380 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc
@@ -41,11 +41,11 @@ class WebRtcLocalAudioTrackAdapterTest : public ::testing::Test {
capturer_ = WebRtcAudioCapturer::CreateCapturer(
-1, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", ""),
constraint_factory.CreateWebMediaConstraints(), NULL, NULL);
- track_.reset(new WebRtcLocalAudioTrack(adapter_, capturer_, NULL));
+ track_.reset(new WebRtcLocalAudioTrack(adapter_.get(), capturer_, NULL));
}
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
track_->OnSetFormat(params_);
EXPECT_TRUE(track_->GetAudioAdapter()->enabled());
}
@@ -74,14 +74,14 @@ TEST_F(WebRtcLocalAudioTrackAdapterTest, AddAndRemoveSink) {
EXPECT_CALL(*sink,
OnData(_, 16, params_.sample_rate(), params_.channels(),
params_.frames_per_buffer()));
- track_->Capture(data.get(), base::TimeDelta(), 255, false, false);
+ track_->Capture(data.get(), base::TimeDelta(), 255, false, false, false);
// Remove the sink from the webrtc track.
webrtc_track->RemoveSink(sink.get());
sink.reset();
// Verify that no more callback gets into the sink.
- track_->Capture(data.get(), base::TimeDelta(), 255, false, false);
+ track_->Capture(data.get(), base::TimeDelta(), 255, false, false, false);
}
TEST_F(WebRtcLocalAudioTrackAdapterTest, GetSignalLevel) {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc
index 0751238daf3..3903f67201f 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc
@@ -64,7 +64,7 @@ void WebRtcMediaStreamAdapter::TrackRemoved(
for (ScopedVector<WebRtcVideoTrackAdapter>::iterator it =
video_adapters_.begin(); it != video_adapters_.end(); ++it) {
- if ((*it)->webrtc_video_track() == webrtc_track) {
+ if ((*it)->webrtc_video_track() == webrtc_track.get()) {
video_adapters_.erase(it);
break;
}
@@ -93,7 +93,7 @@ void WebRtcMediaStreamAdapter::CreateAudioTrack(
const blink::WebMediaStreamSource& source = track.source();
MediaStreamAudioSource* audio_source =
static_cast<MediaStreamAudioSource*>(source.extraData());
- if (audio_source && audio_source->GetAudioCapturer())
+ if (audio_source && audio_source->GetAudioCapturer().get())
audio_source->GetAudioCapturer()->EnablePeerConnectionMode();
webrtc_media_stream_->AddTrack(native_track->GetAudioAdapter());
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
index d5983224ed3..ff3ff336f91 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT WebRtcMediaStreamAdapter
public:
WebRtcMediaStreamAdapter(const blink::WebMediaStream& web_stream,
PeerConnectionDependencyFactory* factory);
- virtual ~WebRtcMediaStreamAdapter();
+ ~WebRtcMediaStreamAdapter() override;
bool IsEqual(const blink::WebMediaStream& web_stream) {
return web_stream_.extraData() == web_stream.extraData();
@@ -43,8 +43,8 @@ class CONTENT_EXPORT WebRtcMediaStreamAdapter
protected:
// MediaStreamObserver implementation.
- virtual void TrackAdded(const blink::WebMediaStreamTrack& track) OVERRIDE;
- virtual void TrackRemoved(const blink::WebMediaStreamTrack& track) OVERRIDE;
+ void TrackAdded(const blink::WebMediaStreamTrack& track) override;
+ void TrackRemoved(const blink::WebMediaStreamTrack& track) override;
private:
void CreateAudioTrack(const blink::WebMediaStreamTrack& track);
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
index a5eced1d87a..7070965888b 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
@@ -9,25 +9,33 @@
#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
namespace content {
class WebRtcMediaStreamAdapterTest : public ::testing::Test {
public:
- virtual void SetUp() {
+ void SetUp() override {
child_process_.reset(new ChildProcess());
dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
}
+ void TearDown() override {
+ adapter_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
blink::WebMediaStream CreateBlinkMediaStream(bool audio, bool video) {
blink::WebVector<blink::WebMediaStreamTrack> audio_track_vector(
audio ? static_cast<size_t>(1) : 0);
@@ -39,12 +47,20 @@ class WebRtcMediaStreamAdapterTest : public ::testing::Test {
audio_source.setExtraData(new MediaStreamAudioSource());
audio_track_vector[0].initialize(audio_source);
- MediaStreamTrack* native_track =
- new MediaStreamTrack(
- WebRtcLocalAudioTrackAdapter::Create(
- audio_track_vector[0].id().utf8(), NULL),
- true);
- audio_track_vector[0].setExtraData(native_track);
+ StreamDeviceInfo device_info(MEDIA_DEVICE_AUDIO_CAPTURE, "Mock device",
+ "mock_device_id");
+ MockMediaConstraintFactory constraint_factory;
+ const blink::WebMediaConstraints constraints =
+ constraint_factory.CreateWebMediaConstraints();
+ scoped_refptr<WebRtcAudioCapturer> capturer(
+ WebRtcAudioCapturer::CreateCapturer(
+ -1, device_info, constraints, nullptr, nullptr));
+ scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
+ WebRtcLocalAudioTrackAdapter::Create(
+ audio_track_vector[0].id().utf8(), nullptr));
+ scoped_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get(), capturer, nullptr));
+ audio_track_vector[0].setExtraData(native_track.release());
}
blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
index 603edb3780a..06533e53214 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -8,21 +8,323 @@
#include "base/debug/trace_event.h"
#include "base/memory/aligned_memory.h"
#include "media/base/video_frame.h"
+#include "media/base/video_frame_pool.h"
+#include "third_party/libjingle/source/talk/media/base/videoframe.h"
+#include "third_party/libjingle/source/talk/media/base/videoframefactory.h"
+#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
+#include "third_party/libyuv/include/libyuv/convert_from.h"
#include "third_party/libyuv/include/libyuv/scale.h"
namespace content {
+namespace {
+
+// Empty method used for keeping a reference to the original media::VideoFrame.
+// The reference to |frame| is kept in the closure that calls this method.
+void ReleaseOriginalFrame(const scoped_refptr<media::VideoFrame>& frame) {
+}
+
+// Thin map between an existing media::VideoFrame and cricket::VideoFrame to
+// avoid premature deep copies.
+// This implementation is only safe to use in a const context and should never
+// be written to.
+class VideoFrameWrapper : public cricket::VideoFrame {
+ public:
+ VideoFrameWrapper(const scoped_refptr<media::VideoFrame>& frame,
+ int64 elapsed_time)
+ : frame_(media::VideoFrame::WrapVideoFrame(
+ frame,
+ frame->visible_rect(),
+ frame->natural_size(),
+ base::Bind(&ReleaseOriginalFrame, frame))),
+ elapsed_time_(elapsed_time) {}
+
+ VideoFrame* Copy() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return new VideoFrameWrapper(frame_, elapsed_time_);
+ }
+
+ size_t GetWidth() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return static_cast<size_t>(frame_->visible_rect().width());
+ }
+
+ size_t GetHeight() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return static_cast<size_t>(frame_->visible_rect().height());
+ }
+
+ const uint8* GetYPlane() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->visible_data(media::VideoFrame::kYPlane);
+ }
+
+ const uint8* GetUPlane() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->visible_data(media::VideoFrame::kUPlane);
+ }
+
+ const uint8* GetVPlane() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->visible_data(media::VideoFrame::kVPlane);
+ }
+
+ uint8* GetYPlane() override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->visible_data(media::VideoFrame::kYPlane);
+ }
+
+ uint8* GetUPlane() override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->visible_data(media::VideoFrame::kUPlane);
+ }
+
+ uint8* GetVPlane() override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->visible_data(media::VideoFrame::kVPlane);
+ }
+
+ int32 GetYPitch() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->stride(media::VideoFrame::kYPlane);
+ }
+
+ int32 GetUPitch() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->stride(media::VideoFrame::kUPlane);
+ }
+
+ int32 GetVPitch() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->stride(media::VideoFrame::kVPlane);
+ }
+
+ void* GetNativeHandle() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return NULL;
+ }
+
+ size_t GetPixelWidth() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return 1;
+ }
+ size_t GetPixelHeight() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return 1;
+ }
+
+ int64 GetElapsedTime() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return elapsed_time_;
+ }
+
+ int64 GetTimeStamp() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return frame_->timestamp().InMicroseconds() *
+ base::Time::kNanosecondsPerMicrosecond;
+ }
+
+ void SetElapsedTime(int64 elapsed_time) override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ elapsed_time_ = elapsed_time;
+ }
+
+ void SetTimeStamp(int64 time_stamp) override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Round to closest microsecond.
+ frame_->set_timestamp(base::TimeDelta::FromMicroseconds(
+ (time_stamp + base::Time::kNanosecondsPerMicrosecond / 2) /
+ base::Time::kNanosecondsPerMicrosecond));
+ }
+
+ int GetRotation() const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return 0;
+ }
+
+ // TODO(magjed): Refactor into base class.
+ size_t ConvertToRgbBuffer(uint32 to_fourcc,
+ uint8* buffer,
+ size_t size,
+ int stride_rgb) const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ const size_t needed = std::abs(stride_rgb) * GetHeight();
+ if (size < needed) {
+ DLOG(WARNING) << "RGB buffer is not large enough";
+ return needed;
+ }
+
+ if (libyuv::ConvertFromI420(GetYPlane(),
+ GetYPitch(),
+ GetUPlane(),
+ GetUPitch(),
+ GetVPlane(),
+ GetVPitch(),
+ buffer,
+ stride_rgb,
+ static_cast<int>(GetWidth()),
+ static_cast<int>(GetHeight()),
+ to_fourcc)) {
+ DLOG(ERROR) << "RGB type not supported: " << to_fourcc;
+ return 0; // 0 indicates error
+ }
+ return needed;
+ }
+
+ // The rest of the public methods are NOTIMPLEMENTED.
+ bool InitToBlack(int w,
+ int h,
+ size_t pixel_width,
+ size_t pixel_height,
+ int64 elapsed_time,
+ int64 time_stamp) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ bool Reset(uint32 fourcc,
+ int w,
+ int h,
+ int dw,
+ int dh,
+ uint8* sample,
+ size_t sample_size,
+ size_t pixel_width,
+ size_t pixel_height,
+ int64 elapsed_time,
+ int64 time_stamp,
+ int rotation) override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ bool MakeExclusive() override {
+ NOTIMPLEMENTED();
+ return false;
+ }
+
+ size_t CopyToBuffer(uint8* buffer, size_t size) const override {
+ NOTIMPLEMENTED();
+ return 0;
+ }
+
+ protected:
+ // TODO(magjed): Refactor as a static method in WebRtcVideoFrame.
+ VideoFrame* CreateEmptyFrame(int w,
+ int h,
+ size_t pixel_width,
+ size_t pixel_height,
+ int64 elapsed_time,
+ int64 time_stamp) const override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ VideoFrame* frame = new cricket::WebRtcVideoFrame();
+ frame->InitToBlack(
+ w, h, pixel_width, pixel_height, elapsed_time, time_stamp);
+ return frame;
+ }
+
+ private:
+ scoped_refptr<media::VideoFrame> frame_;
+ int64 elapsed_time_;
+ base::ThreadChecker thread_checker_;
+};
+
+} // anonymous namespace
+
+// A cricket::VideoFrameFactory for media::VideoFrame. The purpose of this
+// class is to avoid a premature frame copy. A media::VideoFrame is injected
+// with SetFrame, and converted into a cricket::VideoFrame with
+// CreateAliasedFrame. SetFrame should be called before CreateAliasedFrame
+// for every frame.
+class WebRtcVideoCapturerAdapter::MediaVideoFrameFactory
+ : public cricket::VideoFrameFactory {
+ public:
+ void SetFrame(const scoped_refptr<media::VideoFrame>& frame,
+ int64_t elapsed_time) {
+ DCHECK(frame.get());
+ // Create a CapturedFrame that only contains header information, not the
+ // actual pixel data.
+ captured_frame_.width = frame->natural_size().width();
+ captured_frame_.height = frame->natural_size().height();
+ captured_frame_.elapsed_time = elapsed_time;
+ captured_frame_.time_stamp = frame->timestamp().InMicroseconds() *
+ base::Time::kNanosecondsPerMicrosecond;
+ captured_frame_.pixel_height = 1;
+ captured_frame_.pixel_width = 1;
+ captured_frame_.rotation = 0;
+ captured_frame_.data = NULL;
+ captured_frame_.data_size = cricket::CapturedFrame::kUnknownDataSize;
+ captured_frame_.fourcc = static_cast<uint32>(cricket::FOURCC_ANY);
+
+ frame_ = frame;
+ }
+
+ void ReleaseFrame() { frame_ = NULL; }
+
+ const cricket::CapturedFrame* GetCapturedFrame() const {
+ return &captured_frame_;
+ }
+
+ cricket::VideoFrame* CreateAliasedFrame(
+ const cricket::CapturedFrame* captured_frame,
+ int dst_width,
+ int dst_height) const override {
+ // Check that captured_frame is actually our frame.
+ DCHECK(captured_frame == &captured_frame_);
+ DCHECK(frame_.get());
+
+ scoped_refptr<media::VideoFrame> video_frame = frame_;
+ // Check if scaling is needed.
+ if (dst_width != frame_->visible_rect().width() ||
+ dst_height != frame_->visible_rect().height()) {
+ video_frame =
+ scaled_frame_pool_.CreateFrame(media::VideoFrame::I420,
+ gfx::Size(dst_width, dst_height),
+ gfx::Rect(0, 0, dst_width, dst_height),
+ gfx::Size(dst_width, dst_height),
+ frame_->timestamp());
+ libyuv::I420Scale(frame_->visible_data(media::VideoFrame::kYPlane),
+ frame_->stride(media::VideoFrame::kYPlane),
+ frame_->visible_data(media::VideoFrame::kUPlane),
+ frame_->stride(media::VideoFrame::kUPlane),
+ frame_->visible_data(media::VideoFrame::kVPlane),
+ frame_->stride(media::VideoFrame::kVPlane),
+ frame_->visible_rect().width(),
+ frame_->visible_rect().height(),
+ video_frame->data(media::VideoFrame::kYPlane),
+ video_frame->stride(media::VideoFrame::kYPlane),
+ video_frame->data(media::VideoFrame::kUPlane),
+ video_frame->stride(media::VideoFrame::kUPlane),
+ video_frame->data(media::VideoFrame::kVPlane),
+ video_frame->stride(media::VideoFrame::kVPlane),
+ dst_width,
+ dst_height,
+ libyuv::kFilterBilinear);
+ }
+
+ // Create a shallow cricket::VideoFrame wrapper around the
+ // media::VideoFrame. The caller has ownership of the returned frame.
+ return new VideoFrameWrapper(video_frame, captured_frame_.elapsed_time);
+ }
+
+ private:
+ scoped_refptr<media::VideoFrame> frame_;
+ cricket::CapturedFrame captured_frame_;
+ // This is used only if scaling is needed.
+ mutable media::VideoFramePool scaled_frame_pool_;
+};
WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast)
: is_screencast_(is_screencast),
running_(false),
- buffer_(NULL),
- buffer_size_(0) {
+ first_frame_timestamp_(media::kNoTimestamp()),
+ frame_factory_(new MediaVideoFrameFactory) {
thread_checker_.DetachFromThread();
+ // The base class takes ownership of the frame factory.
+ set_frame_factory(frame_factory_);
}
WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() {
DVLOG(3) << " WebRtcVideoCapturerAdapter::dtor";
- base::AlignedFree(buffer_);
}
cricket::CaptureState WebRtcVideoCapturerAdapter::Start(
@@ -53,10 +355,10 @@ bool WebRtcVideoCapturerAdapter::IsRunning() {
bool WebRtcVideoCapturerAdapter::GetPreferredFourccs(
std::vector<uint32>* fourccs) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (!fourccs)
- return false;
- fourccs->push_back(cricket::FOURCC_I420);
- return true;
+ DCHECK(!fourccs || fourccs->empty());
+ if (fourccs)
+ fourccs->push_back(cricket::FOURCC_I420);
+ return fourccs != NULL;
}
bool WebRtcVideoCapturerAdapter::IsScreencast() const {
@@ -97,97 +399,18 @@ void WebRtcVideoCapturerAdapter::OnFrameCaptured(
if (first_frame_timestamp_ == media::kNoTimestamp())
first_frame_timestamp_ = frame->timestamp();
- cricket::CapturedFrame captured_frame;
- captured_frame.width = frame->natural_size().width();
- captured_frame.height = frame->natural_size().height();
- // cricket::CapturedFrame time is in nanoseconds.
- captured_frame.elapsed_time =
+ const int64 elapsed_time =
(frame->timestamp() - first_frame_timestamp_).InMicroseconds() *
base::Time::kNanosecondsPerMicrosecond;
- captured_frame.time_stamp = frame->timestamp().InMicroseconds() *
- base::Time::kNanosecondsPerMicrosecond;
- captured_frame.pixel_height = 1;
- captured_frame.pixel_width = 1;
-
- // TODO(perkj):
- // Libjingle expects contiguous layout of image planes as input.
- // The only format where that is true in Chrome is I420 where the
- // coded_size == natural_size().
- if (frame->format() != media::VideoFrame::I420 ||
- frame->coded_size() != frame->natural_size()) {
- // Cropping / Scaling and or switching UV planes is needed.
- UpdateI420Buffer(frame);
- captured_frame.data = buffer_;
- captured_frame.data_size = buffer_size_;
- captured_frame.fourcc = cricket::FOURCC_I420;
- } else {
- captured_frame.fourcc = media::VideoFrame::I420 == frame->format() ?
- cricket::FOURCC_I420 : cricket::FOURCC_YV12;
- captured_frame.data = frame->data(0);
- captured_frame.data_size =
- media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
- }
+
+ // Inject the frame via the VideoFrameFractory.
+ DCHECK(frame_factory_ == frame_factory());
+ frame_factory_->SetFrame(frame, elapsed_time);
// This signals to libJingle that a new VideoFrame is available.
- // libJingle have no assumptions on what thread this signal come from.
- SignalFrameCaptured(this, &captured_frame);
-}
+ SignalFrameCaptured(this, frame_factory_->GetCapturedFrame());
-void WebRtcVideoCapturerAdapter::UpdateI420Buffer(
- const scoped_refptr<media::VideoFrame>& src) {
- DCHECK(thread_checker_.CalledOnValidThread());
- const int dst_width = src->natural_size().width();
- const int dst_height = src->natural_size().height();
- DCHECK(src->visible_rect().width() >= dst_width &&
- src->visible_rect().height() >= dst_height);
-
- const gfx::Rect& visible_rect = src->visible_rect();
-
- const uint8* src_y = src->data(media::VideoFrame::kYPlane) +
- visible_rect.y() * src->stride(media::VideoFrame::kYPlane) +
- visible_rect.x();
- const uint8* src_u = src->data(media::VideoFrame::kUPlane) +
- visible_rect.y() / 2 * src->stride(media::VideoFrame::kUPlane) +
- visible_rect.x() / 2;
- const uint8* src_v = src->data(media::VideoFrame::kVPlane) +
- visible_rect.y() / 2 * src->stride(media::VideoFrame::kVPlane) +
- visible_rect.x() / 2;
-
- const size_t dst_size =
- media::VideoFrame::AllocationSize(src->format(), src->natural_size());
-
- if (dst_size != buffer_size_) {
- base::AlignedFree(buffer_);
- buffer_ = reinterpret_cast<uint8*>(
- base::AlignedAlloc(dst_size + media::VideoFrame::kFrameSizePadding,
- media::VideoFrame::kFrameAddressAlignment));
- buffer_size_ = dst_size;
- }
-
- uint8* dst_y = buffer_;
- const int dst_stride_y = dst_width;
- uint8* dst_u = dst_y + dst_width * dst_height;
- const int dst_halfwidth = (dst_width + 1) / 2;
- const int dst_halfheight = (dst_height + 1) / 2;
- uint8* dst_v = dst_u + dst_halfwidth * dst_halfheight;
-
- libyuv::I420Scale(src_y,
- src->stride(media::VideoFrame::kYPlane),
- src_u,
- src->stride(media::VideoFrame::kUPlane),
- src_v,
- src->stride(media::VideoFrame::kVPlane),
- visible_rect.width(),
- visible_rect.height(),
- dst_y,
- dst_stride_y,
- dst_u,
- dst_halfwidth,
- dst_v,
- dst_halfwidth,
- dst_width,
- dst_height,
- libyuv::kFilterBilinear);
+ frame_factory_->ReleaseFrame(); // Release the frame ASAP.
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
index 0f38f6b9ed7..f70ae8949d2 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
@@ -29,7 +29,7 @@ class CONTENT_EXPORT WebRtcVideoCapturerAdapter
: NON_EXPORTED_BASE(public cricket::VideoCapturer) {
public:
explicit WebRtcVideoCapturerAdapter(bool is_screencast);
- virtual ~WebRtcVideoCapturerAdapter();
+ ~WebRtcVideoCapturerAdapter() override;
// OnFrameCaptured delivers video frames to libjingle. It must be called on
// libjingles worker thread.
@@ -39,16 +39,14 @@ class CONTENT_EXPORT WebRtcVideoCapturerAdapter
private:
// cricket::VideoCapturer implementation.
// These methods are accessed from a libJingle worker thread.
- virtual cricket::CaptureState Start(
- const cricket::VideoFormat& capture_format) OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual bool IsRunning() OVERRIDE;
- virtual bool GetPreferredFourccs(std::vector<uint32>* fourccs) OVERRIDE;
- virtual bool GetBestCaptureFormat(const cricket::VideoFormat& desired,
- cricket::VideoFormat* best_format) OVERRIDE;
- virtual bool IsScreencast() const OVERRIDE;
-
- void UpdateI420Buffer(const scoped_refptr<media::VideoFrame>& src);
+ cricket::CaptureState Start(
+ const cricket::VideoFormat& capture_format) override;
+ void Stop() override;
+ bool IsRunning() override;
+ bool GetPreferredFourccs(std::vector<uint32>* fourccs) override;
+ bool GetBestCaptureFormat(const cricket::VideoFormat& desired,
+ cricket::VideoFormat* best_format) override;
+ bool IsScreencast() const override;
// |thread_checker_| is bound to the libjingle worker thread.
base::ThreadChecker thread_checker_;
@@ -56,12 +54,11 @@ class CONTENT_EXPORT WebRtcVideoCapturerAdapter
const bool is_screencast_;
bool running_;
base::TimeDelta first_frame_timestamp_;
- // |buffer_| used if cropping is needed. It is created only if needed and
- // owned by WebRtcVideoCapturerAdapter. If its created, it exists until
- // WebRtcVideoCapturerAdapter is destroyed.
- uint8* buffer_;
- size_t buffer_size_;
- scoped_ptr<cricket::CapturedFrame> captured_frame_;
+
+ // This is an alias to the frame_factory_ in the base class
+ // cricket::VideoCapturer.
+ class MediaVideoFrameFactory;
+ MediaVideoFrameFactory* frame_factory_;
DISALLOW_COPY_AND_ASSIGN(WebRtcVideoCapturerAdapter);
};
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
index 250124d0b82..1e580931117 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc
@@ -21,7 +21,7 @@ class WebRtcVideoCapturerAdapterTest
adapter_.SignalFrameCaptured.connect(
this, &WebRtcVideoCapturerAdapterTest::OnFrameCaptured);
}
- virtual ~WebRtcVideoCapturerAdapterTest() {}
+ ~WebRtcVideoCapturerAdapterTest() override {}
void TestSourceCropFrame(int capture_width,
int capture_height,
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_track_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_track_adapter.h
index 0ff7a6ffd99..a073e5b0006 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_track_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_track_adapter.h
@@ -31,7 +31,7 @@ class WebRtcVideoTrackAdapter : public MediaStreamVideoSink {
public:
WebRtcVideoTrackAdapter(const blink::WebMediaStreamTrack& track,
PeerConnectionDependencyFactory* factory);
- virtual ~WebRtcVideoTrackAdapter();
+ ~WebRtcVideoTrackAdapter() override;
webrtc::VideoTrackInterface* webrtc_video_track() {
return video_track_.get();
@@ -39,7 +39,7 @@ class WebRtcVideoTrackAdapter : public MediaStreamVideoSink {
protected:
// Implementation of MediaStreamSink.
- virtual void OnEnabledChanged(bool enabled) OVERRIDE;
+ void OnEnabledChanged(bool enabled) override;
private:
// Used to DCHECK that we are called on the correct thread.
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.cc b/chromium/content/renderer/media/webrtc_audio_capturer.cc
index e47beeada95..45034e8b2f4 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_capturer.cc
@@ -23,28 +23,19 @@ namespace content {
namespace {
-// Supported hardware sample rates for input and output sides.
-#if defined(OS_WIN) || defined(OS_MACOSX)
-// media::GetAudioInputHardwareSampleRate() asks the audio layer
-// for its current sample rate (set by the user) on Windows and Mac OS X.
-// The listed rates below adds restrictions and WebRtcAudioDeviceImpl::Init()
-// will fail if the user selects any rate outside these ranges.
-const int kValidInputRates[] =
- {192000, 96000, 48000, 44100, 32000, 16000, 8000};
-#elif defined(OS_LINUX) || defined(OS_OPENBSD)
-const int kValidInputRates[] = {48000, 44100};
-#elif defined(OS_ANDROID)
-const int kValidInputRates[] = {48000, 44100};
-#else
-const int kValidInputRates[] = {44100};
-#endif
-
-// Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments
-// for semantics. This value was arbitrarily chosen, but seems to work well.
-const int kPowerMonitorTimeConstantMs = 10;
+// Method to check if any of the data in |audio_source| has energy.
+bool HasDataEnergy(const media::AudioBus& audio_source) {
+ for (int ch = 0; ch < audio_source.channels(); ++ch) {
+ const float* channel_ptr = audio_source.channel(ch);
+ for (int frame = 0; frame < audio_source.frames(); ++frame) {
+ if (channel_ptr[frame] != 0)
+ return true;
+ }
+ }
-// The time between two audio power level samples.
-const int kPowerMonitorLogIntervalSeconds = 10;
+ // All the data is zero.
+ return false;
+}
} // namespace
@@ -60,14 +51,16 @@ class WebRtcAudioCapturer::TrackOwner
base::TimeDelta delay,
double volume,
bool key_pressed,
- bool need_audio_processing) {
+ bool need_audio_processing,
+ bool force_report_nonzero_energy) {
base::AutoLock lock(lock_);
if (delegate_) {
delegate_->Capture(audio_data,
delay,
volume,
key_pressed,
- need_audio_processing);
+ need_audio_processing,
+ force_report_nonzero_energy);
}
}
@@ -172,6 +165,24 @@ bool WebRtcAudioCapturer::Initialize() {
media::ChannelLayout channel_layout = static_cast<media::ChannelLayout>(
device_info_.device.input.channel_layout);
+
+ // If KEYBOARD_MIC effect is set, change the layout to the corresponding
+ // layout that includes the keyboard mic.
+ if ((device_info_.device.input.effects &
+ media::AudioParameters::KEYBOARD_MIC) &&
+ MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() &&
+ audio_constraints.GetProperty(
+ MediaAudioConstraints::kGoogExperimentalNoiseSuppression)) {
+ if (channel_layout == media::CHANNEL_LAYOUT_STEREO) {
+ channel_layout = media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC;
+ DVLOG(1) << "Changed stereo layout to stereo + keyboard mic layout due "
+ << "to KEYBOARD_MIC effect.";
+ } else {
+ DVLOG(1) << "KEYBOARD_MIC effect ignored, not compatible with layout "
+ << channel_layout;
+ }
+ }
+
DVLOG(1) << "Audio input hardware channel layout: " << channel_layout;
UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioInputChannelLayout",
channel_layout, media::CHANNEL_LAYOUT_MAX + 1);
@@ -196,17 +207,6 @@ bool WebRtcAudioCapturer::Initialize() {
device_info_.device.input.sample_rate);
}
- // Verify that the reported input hardware sample rate is supported
- // on the current platform.
- if (std::find(&kValidInputRates[0],
- &kValidInputRates[0] + arraysize(kValidInputRates),
- device_info_.device.input.sample_rate) ==
- &kValidInputRates[arraysize(kValidInputRates)]) {
- DLOG(ERROR) << device_info_.device.input.sample_rate
- << " is not a supported input rate.";
- return false;
- }
-
// Create and configure the default audio capturing source.
SetCapturerSource(AudioDeviceFactory::NewInputDevice(render_view_id_),
channel_layout,
@@ -227,9 +227,10 @@ WebRtcAudioCapturer::WebRtcAudioCapturer(
WebRtcAudioDeviceImpl* audio_device,
MediaStreamAudioSource* audio_source)
: constraints_(constraints),
- audio_processor_(
- new talk_base::RefCountedObject<MediaStreamAudioProcessor>(
- constraints, device_info.device.input.effects, audio_device)),
+ audio_processor_(new rtc::RefCountedObject<MediaStreamAudioProcessor>(
+ constraints,
+ device_info.device.input.effects,
+ audio_device)),
running_(false),
render_view_id_(render_view_id),
device_info_(device_info),
@@ -238,10 +239,7 @@ WebRtcAudioCapturer::WebRtcAudioCapturer(
key_pressed_(false),
need_audio_processing_(false),
audio_device_(audio_device),
- audio_source_(audio_source),
- audio_power_monitor_(
- device_info_.device.input.sample_rate,
- base::TimeDelta::FromMilliseconds(kPowerMonitorTimeConstantMs)) {
+ audio_source_(audio_source) {
DVLOG(1) << "WebRtcAudioCapturer::WebRtcAudioCapturer()";
}
@@ -264,7 +262,7 @@ void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) {
// Add with a tag, so we remember to call OnSetFormat() on the new
// track.
scoped_refptr<TrackOwner> track_owner(new TrackOwner(track));
- tracks_.AddAndTag(track_owner);
+ tracks_.AddAndTag(track_owner.get());
}
}
@@ -327,7 +325,7 @@ void WebRtcAudioCapturer::SetCapturerSource(
// bits_per_sample is always 16 for now.
int buffer_size = GetBufferSize(sample_rate);
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- channel_layout, 0, sample_rate,
+ channel_layout, sample_rate,
16, buffer_size,
device_info_.device.input.effects);
@@ -387,7 +385,7 @@ void WebRtcAudioCapturer::Start() {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioCapturer::Start()";
base::AutoLock auto_lock(lock_);
- if (running_ || !source_)
+ if (running_ || !source_.get())
return;
// Start the data source, i.e., start capturing data from the current source.
@@ -509,19 +507,11 @@ void WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source,
(*it)->SetAudioProcessor(audio_processor_);
}
- if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() >
- kPowerMonitorLogIntervalSeconds) {
- audio_power_monitor_.Scan(*audio_source, audio_source->frames());
-
- last_audio_level_log_time_ = base::TimeTicks::Now();
-
- std::pair<float, bool> result =
- audio_power_monitor_.ReadCurrentPowerAndClip();
- WebRtcLogMessage(base::StringPrintf(
- "WAC::Capture: current_audio_power=%.2fdBFS.", result.first));
-
- audio_power_monitor_.Reset();
- }
+ // Figure out if the pre-processed data has any energy or not, the
+ // information will be passed to the track to force the calculator
+ // to report energy in case the post-processed data is zeroed by the audio
+ // processing.
+ const bool force_report_nonzero_energy = HasDataEnergy(*audio_source);
// Push the data to the processor for processing.
audio_processor_->PushCaptureData(audio_source);
@@ -536,7 +526,7 @@ void WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source,
for (TrackList::ItemList::const_iterator it = tracks.begin();
it != tracks.end(); ++it) {
(*it)->Capture(output, audio_delay, current_volume, key_pressed,
- need_audio_processing);
+ need_audio_processing, force_report_nonzero_energy);
}
if (new_volume) {
@@ -554,8 +544,8 @@ void WebRtcAudioCapturer::OnCaptureError() {
media::AudioParameters WebRtcAudioCapturer::source_audio_parameters() const {
base::AutoLock auto_lock(lock_);
- return audio_processor_ ?
- audio_processor_->InputFormat() : media::AudioParameters();
+ return audio_processor_.get() ? audio_processor_->InputFormat()
+ : media::AudioParameters();
}
bool WebRtcAudioCapturer::GetPairedOutputParameters(
@@ -589,10 +579,13 @@ int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
// Use the native hardware buffer size in non peer connection mode when the
// platform is using a native buffer size smaller than the PeerConnection
- // buffer size.
+ // buffer size and audio processing is off.
int hardware_buffer_size = device_info_.device.input.frames_per_buffer;
if (!peer_connection_mode_ && hardware_buffer_size &&
- hardware_buffer_size <= peer_connection_buffer_size) {
+ hardware_buffer_size <= peer_connection_buffer_size &&
+ !audio_processor_->has_audio_processing()) {
+ DVLOG(1) << "WebRtcAudioCapturer is using hardware buffer size "
+ << hardware_buffer_size;
return hardware_buffer_size;
}
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.h b/chromium/content/renderer/media/webrtc_audio_capturer.h
index d77a107dbca..d98db0f106c 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer.h
+++ b/chromium/content/renderer/media/webrtc_audio_capturer.h
@@ -17,7 +17,6 @@
#include "content/common/media/media_stream_options.h"
#include "content/renderer/media/tagged_list.h"
#include "media/audio/audio_input_device.h"
-#include "media/audio/audio_power_monitor.h"
#include "media/base/audio_capturer_source.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
@@ -119,7 +118,7 @@ class CONTENT_EXPORT WebRtcAudioCapturer
protected:
friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
- virtual ~WebRtcAudioCapturer();
+ ~WebRtcAudioCapturer() override;
private:
class TrackOwner;
@@ -133,11 +132,11 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// AudioCapturerSource::CaptureCallback implementation.
// Called on the AudioInputDevice audio thread.
- virtual void Capture(const media::AudioBus* audio_source,
- int audio_delay_milliseconds,
- double volume,
- bool key_pressed) OVERRIDE;
- virtual void OnCaptureError() OVERRIDE;
+ void Capture(const media::AudioBus* audio_source,
+ int audio_delay_milliseconds,
+ double volume,
+ bool key_pressed) override;
+ void OnCaptureError() override;
// Initializes the default audio capturing source using the provided render
// view id and device information. Return true if success, otherwise false.
@@ -217,12 +216,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// WebRtcAudioCapturer.
MediaStreamAudioSource* const audio_source_;
- // Audio power monitor for logging audio power level.
- media::AudioPowerMonitor audio_power_monitor_;
-
- // Records when the last time audio power level is logged.
- base::TimeTicks last_audio_level_log_time_;
-
DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturer);
};
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
index 0011f763059..9b2741041d2 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
@@ -45,7 +45,7 @@ class MockPeerConnectionAudioSink : public PeerConnectionAudioSink {
int number_of_channels, int number_of_frames,
const std::vector<int>& channels,
int audio_delay_milliseconds, int current_volume,
- bool need_audio_processing, bool key_pressed) OVERRIDE {
+ bool need_audio_processing, bool key_pressed) override {
EXPECT_EQ(sample_rate, params_.sample_rate());
EXPECT_EQ(number_of_channels, params_.channels());
EXPECT_EQ(number_of_frames, params_.frames_per_buffer());
@@ -59,7 +59,7 @@ class MockPeerConnectionAudioSink : public PeerConnectionAudioSink {
int current_volume,
bool need_audio_processing,
bool key_pressed));
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE {
+ virtual void OnSetFormat(const media::AudioParameters& params) override {
params_ = params;
FormatIsSet();
}
@@ -105,7 +105,7 @@ class WebRtcAudioCapturerTest : public testing::Test {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- track_.reset(new WebRtcLocalAudioTrack(adapter, capturer_, NULL));
+ track_.reset(new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
track_->Start();
// Connect a mock sink to the track.
@@ -124,13 +124,15 @@ class WebRtcAudioCapturerTest : public testing::Test {
audio_bus->Zero();
media::AudioCapturerSource::CaptureCallback* callback =
- static_cast<media::AudioCapturerSource::CaptureCallback*>(capturer_);
+ static_cast<media::AudioCapturerSource::CaptureCallback*>(
+ capturer_.get());
// Verify the sink is getting the correct values.
EXPECT_CALL(*sink, FormatIsSet());
EXPECT_CALL(*sink,
OnDataCallback(_, _, delay_ms, expected_volume_value,
- need_audio_processing, key_pressed));
+ need_audio_processing, key_pressed))
+ .Times(AtLeast(1));
callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
// Verify the cached values in the capturer fits what we expect.
@@ -184,7 +186,7 @@ TEST_F(WebRtcAudioCapturerTest, FailToCreateCapturerWithWrongConstraints) {
params_.frames_per_buffer()),
constraint_factory.CreateWebMediaConstraints(), NULL, NULL)
);
- EXPECT_TRUE(capturer == NULL);
+ EXPECT_TRUE(capturer.get() == NULL);
}
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
index 1339a6f4cb8..49e90683afd 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
@@ -32,27 +32,37 @@ WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
is_audio_track_processing_enabled_(
MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
+ // This object can be constructed on either the signaling thread or the main
+ // thread, so we need to detach these thread checkers here and have them
+ // initialize automatically when the first methods are called.
+ signaling_thread_checker_.DetachFromThread();
+ main_thread_checker_.DetachFromThread();
+
+ worker_thread_checker_.DetachFromThread();
}
WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() {
DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()";
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_thread_checker_.CalledOnValidThread());
Terminate();
}
int32_t WebRtcAudioDeviceImpl::AddRef() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ // We can be AddRefed and released on both the UI thread as well as
+ // libjingle's signaling thread.
return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1);
}
int32_t WebRtcAudioDeviceImpl::Release() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ // We can be AddRefed and released on both the UI thread as well as
+ // libjingle's signaling thread.
int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1);
if (ret == 0) {
delete this;
}
return ret;
}
+
int WebRtcAudioDeviceImpl::OnData(const int16* audio_data,
int sample_rate,
int number_of_channels,
@@ -62,6 +72,7 @@ int WebRtcAudioDeviceImpl::OnData(const int16* audio_data,
int current_volume,
bool need_audio_processing,
bool key_pressed) {
+ DCHECK(worker_thread_checker_.CalledOnValidThread());
int total_delay_ms = 0;
{
base::AutoLock auto_lock(lock_);
@@ -201,9 +212,9 @@ void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
}
void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_EQ(renderer, renderer_);
+ DCHECK(main_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
+ DCHECK_EQ(renderer, renderer_.get());
// Notify the playout sink of the change.
for (PlayoutDataSinkList::const_iterator it = playout_sinks_.begin();
it != playout_sinks_.end(); ++it) {
@@ -217,7 +228,8 @@ void WebRtcAudioDeviceImpl::RemoveAudioRenderer(WebRtcAudioRenderer* renderer) {
int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback(
webrtc::AudioTransport* audio_callback) {
DVLOG(1) << "WebRtcAudioDeviceImpl::RegisterAudioCallback()";
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ base::AutoLock lock(lock_);
DCHECK_EQ(audio_transport_callback_ == NULL, audio_callback != NULL);
audio_transport_callback_ = audio_callback;
return 0;
@@ -225,7 +237,7 @@ int32_t WebRtcAudioDeviceImpl::RegisterAudioCallback(
int32_t WebRtcAudioDeviceImpl::Init() {
DVLOG(1) << "WebRtcAudioDeviceImpl::Init()";
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
// We need to return a success to continue the initialization of WebRtc VoE
// because failure on the capturer_ initialization should not prevent WebRTC
@@ -237,7 +249,7 @@ int32_t WebRtcAudioDeviceImpl::Init() {
int32_t WebRtcAudioDeviceImpl::Terminate() {
DVLOG(1) << "WebRtcAudioDeviceImpl::Terminate()";
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
// Calling Terminate() multiple times in a row is OK.
if (!initialized_)
@@ -265,102 +277,110 @@ int32_t WebRtcAudioDeviceImpl::Terminate() {
}
bool WebRtcAudioDeviceImpl::Initialized() const {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
return initialized_;
}
int32_t WebRtcAudioDeviceImpl::PlayoutIsAvailable(bool* available) {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
*available = initialized_;
return 0;
}
bool WebRtcAudioDeviceImpl::PlayoutIsInitialized() const {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
return initialized_;
}
int32_t WebRtcAudioDeviceImpl::RecordingIsAvailable(bool* available) {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ base::AutoLock auto_lock(lock_);
*available = (!capturers_.empty());
return 0;
}
bool WebRtcAudioDeviceImpl::RecordingIsInitialized() const {
DVLOG(1) << "WebRtcAudioDeviceImpl::RecordingIsInitialized()";
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ base::AutoLock auto_lock(lock_);
return (!capturers_.empty());
}
int32_t WebRtcAudioDeviceImpl::StartPlayout() {
DVLOG(1) << "WebRtcAudioDeviceImpl::StartPlayout()";
- LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing";
- {
- base::AutoLock auto_lock(lock_);
- if (!audio_transport_callback_)
- return 0;
- }
-
- if (playing_) {
- // webrtc::VoiceEngine assumes that it is OK to call Start() twice and
- // that the call is ignored the second time.
+ DCHECK(worker_thread_checker_.CalledOnValidThread());
+ base::AutoLock auto_lock(lock_);
+ if (!audio_transport_callback_) {
+ LOG(ERROR) << "Audio transport is missing";
return 0;
}
+ // webrtc::VoiceEngine assumes that it is OK to call Start() twice and
+ // that the call is ignored the second time.
playing_ = true;
return 0;
}
int32_t WebRtcAudioDeviceImpl::StopPlayout() {
DVLOG(1) << "WebRtcAudioDeviceImpl::StopPlayout()";
- if (!playing_) {
- // webrtc::VoiceEngine assumes that it is OK to call Stop() just in case.
- return 0;
- }
-
+ DCHECK(initialized_);
+ // Can be called both from the worker thread (e.g. when called from webrtc)
+ // or the signaling thread (e.g. when we call it ourselves internally).
+ // The order in this check is important so that we won't incorrectly
+ // initialize worker_thread_checker_ on the signaling thread.
+ DCHECK(signaling_thread_checker_.CalledOnValidThread() ||
+ worker_thread_checker_.CalledOnValidThread());
+ base::AutoLock auto_lock(lock_);
+ // webrtc::VoiceEngine assumes that it is OK to call Stop() multiple times.
playing_ = false;
return 0;
}
bool WebRtcAudioDeviceImpl::Playing() const {
+ DCHECK(worker_thread_checker_.CalledOnValidThread());
+ base::AutoLock auto_lock(lock_);
return playing_;
}
int32_t WebRtcAudioDeviceImpl::StartRecording() {
DVLOG(1) << "WebRtcAudioDeviceImpl::StartRecording()";
+ DCHECK(worker_thread_checker_.CalledOnValidThread());
DCHECK(initialized_);
- LOG_IF(ERROR, !audio_transport_callback_) << "Audio transport is missing";
+ base::AutoLock auto_lock(lock_);
if (!audio_transport_callback_) {
+ LOG(ERROR) << "Audio transport is missing";
return -1;
}
- {
- base::AutoLock auto_lock(lock_);
- if (recording_)
- return 0;
-
- recording_ = true;
- }
+ recording_ = true;
return 0;
}
int32_t WebRtcAudioDeviceImpl::StopRecording() {
DVLOG(1) << "WebRtcAudioDeviceImpl::StopRecording()";
- {
- base::AutoLock auto_lock(lock_);
- if (!recording_)
- return 0;
-
- recording_ = false;
- }
+ DCHECK(initialized_);
+ // Can be called both from the worker thread (e.g. when called from webrtc)
+ // or the signaling thread (e.g. when we call it ourselves internally).
+ // The order in this check is important so that we won't incorrectly
+ // initialize worker_thread_checker_ on the signaling thread.
+ DCHECK(signaling_thread_checker_.CalledOnValidThread() ||
+ worker_thread_checker_.CalledOnValidThread());
+ base::AutoLock auto_lock(lock_);
+ recording_ = false;
return 0;
}
bool WebRtcAudioDeviceImpl::Recording() const {
+ DCHECK(worker_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
return recording_;
}
int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) {
DVLOG(1) << "WebRtcAudioDeviceImpl::SetMicrophoneVolume(" << volume << ")";
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
DCHECK(initialized_);
// Only one microphone is supported at the moment, which is represented by
@@ -376,6 +396,7 @@ int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) {
// TODO(henrika): sort out calling thread once we start using this API.
int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const {
DVLOG(1) << "WebRtcAudioDeviceImpl::MicrophoneVolume()";
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
// We only support one microphone now, which is accessed via the default
// capturer.
DCHECK(initialized_);
@@ -390,24 +411,36 @@ int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const {
int32_t WebRtcAudioDeviceImpl::MaxMicrophoneVolume(uint32_t* max_volume) const {
DCHECK(initialized_);
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
*max_volume = kMaxVolumeLevel;
return 0;
}
int32_t WebRtcAudioDeviceImpl::MinMicrophoneVolume(uint32_t* min_volume) const {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
*min_volume = 0;
return 0;
}
int32_t WebRtcAudioDeviceImpl::StereoPlayoutIsAvailable(bool* available) const {
DCHECK(initialized_);
- *available = renderer_ && renderer_->channels() == 2;
+ // This method is called during initialization on the signaling thread and
+ // then later on the worker thread. Due to this we cannot DCHECK on what
+ // thread we're on since it might incorrectly initialize the
+ // worker_thread_checker_.
+ base::AutoLock auto_lock(lock_);
+ *available = renderer_.get() && renderer_->channels() == 2;
return 0;
}
int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable(
bool* available) const {
DCHECK(initialized_);
+ // This method is called during initialization on the signaling thread and
+ // then later on the worker thread. Due to this we cannot DCHECK on what
+ // thread we're on since it might incorrectly initialize the
+ // worker_thread_checker_.
+
// TODO(xians): These kind of hardware methods do not make much sense since we
// support multiple sources. Remove or figure out new APIs for such methods.
scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
@@ -419,12 +452,14 @@ int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable(
}
int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const {
+ DCHECK(worker_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
*delay_ms = static_cast<uint16_t>(output_delay_ms_);
return 0;
}
int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
*delay_ms = static_cast<uint16_t>(input_delay_ms_);
return 0;
@@ -432,6 +467,7 @@ int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const {
int32_t WebRtcAudioDeviceImpl::RecordingSampleRate(
uint32_t* sample_rate) const {
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
// We use the default capturer as the recording sample rate.
scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
if (!capturer.get())
@@ -444,12 +480,13 @@ int32_t WebRtcAudioDeviceImpl::RecordingSampleRate(
int32_t WebRtcAudioDeviceImpl::PlayoutSampleRate(
uint32_t* sample_rate) const {
- *sample_rate = renderer_ ? renderer_->sample_rate() : 0;
+ DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ *sample_rate = renderer_.get() ? renderer_->sample_rate() : 0;
return 0;
}
bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(renderer);
base::AutoLock auto_lock(lock_);
@@ -465,22 +502,21 @@ bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) {
void WebRtcAudioDeviceImpl::AddAudioCapturer(
const scoped_refptr<WebRtcAudioCapturer>& capturer) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
- DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(capturer.get());
DCHECK(!capturer->device_id().empty());
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) ==
- capturers_.end());
- capturers_.push_back(capturer);
- }
+
+ base::AutoLock auto_lock(lock_);
+ DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) ==
+ capturers_.end());
+ capturers_.push_back(capturer);
}
void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
const scoped_refptr<WebRtcAudioCapturer>& capturer) {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
- DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(capturer.get());
base::AutoLock auto_lock(lock_);
capturers_.remove(capturer);
@@ -488,6 +524,12 @@ void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
scoped_refptr<WebRtcAudioCapturer>
WebRtcAudioDeviceImpl::GetDefaultCapturer() const {
+ // Called on the signaling thread (during initialization), worker
+ // thread during capture or main thread for a WebAudio source.
+ // We can't DCHECK on those three checks here since GetDefaultCapturer
+ // may be the first call and therefore could incorrectly initialize the
+ // thread checkers.
+ DCHECK(initialized_);
base::AutoLock auto_lock(lock_);
// Use the last |capturer| which is from the latest getUserMedia call as
// the default capture device.
@@ -496,7 +538,7 @@ WebRtcAudioDeviceImpl::GetDefaultCapturer() const {
void WebRtcAudioDeviceImpl::AddPlayoutSink(
WebRtcPlayoutDataSource::Sink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(sink);
base::AutoLock auto_lock(lock_);
DCHECK(std::find(playout_sinks_.begin(), playout_sinks_.end(), sink) ==
@@ -506,7 +548,7 @@ void WebRtcAudioDeviceImpl::AddPlayoutSink(
void WebRtcAudioDeviceImpl::RemovePlayoutSink(
WebRtcPlayoutDataSource::Sink* sink) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(sink);
base::AutoLock auto_lock(lock_);
playout_sinks_.remove(sink);
@@ -516,13 +558,14 @@ bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer(
int* session_id,
int* output_sample_rate,
int* output_frames_per_buffer) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ base::AutoLock lock(lock_);
// If there is no capturer or there are more than one open capture devices,
// return false.
- if (capturers_.empty() || capturers_.size() > 1)
+ if (capturers_.size() != 1)
return false;
- return GetDefaultCapturer()->GetPairedOutputParameters(
+ return capturers_.back()->GetPairedOutputParameters(
session_id, output_sample_rate, output_frames_per_buffer);
}
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc_audio_device_impl.h
index e53125de036..debb4b71b2e 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.h
@@ -283,48 +283,50 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
// The creator must call AddRef() after construction and use Release()
// to release the reference and delete this object.
// Called on the main render thread.
- virtual int32_t AddRef() OVERRIDE;
- virtual int32_t Release() OVERRIDE;
+ int32_t AddRef() override;
+ int32_t Release() override;
+ private:
// webrtc::AudioDeviceModule implementation.
// All implemented methods are called on the main render thread unless
// anything else is stated.
- virtual int32_t RegisterAudioCallback(webrtc::AudioTransport* audio_callback)
- OVERRIDE;
+ int32_t RegisterAudioCallback(
+ webrtc::AudioTransport* audio_callback) override;
- virtual int32_t Init() OVERRIDE;
- virtual int32_t Terminate() OVERRIDE;
- virtual bool Initialized() const OVERRIDE;
+ int32_t Init() override;
+ int32_t Terminate() override;
+ bool Initialized() const override;
- virtual int32_t PlayoutIsAvailable(bool* available) OVERRIDE;
- virtual bool PlayoutIsInitialized() const OVERRIDE;
- virtual int32_t RecordingIsAvailable(bool* available) OVERRIDE;
- virtual bool RecordingIsInitialized() const OVERRIDE;
+ int32_t PlayoutIsAvailable(bool* available) override;
+ bool PlayoutIsInitialized() const override;
+ int32_t RecordingIsAvailable(bool* available) override;
+ bool RecordingIsInitialized() const override;
// All Start/Stop methods are called on a libJingle worker thread.
- virtual int32_t StartPlayout() OVERRIDE;
- virtual int32_t StopPlayout() OVERRIDE;
- virtual bool Playing() const OVERRIDE;
- virtual int32_t StartRecording() OVERRIDE;
- virtual int32_t StopRecording() OVERRIDE;
- virtual bool Recording() const OVERRIDE;
+ int32_t StartPlayout() override;
+ int32_t StopPlayout() override;
+ bool Playing() const override;
+ int32_t StartRecording() override;
+ int32_t StopRecording() override;
+ bool Recording() const override;
// Called on the AudioInputDevice worker thread.
- virtual int32_t SetMicrophoneVolume(uint32_t volume) OVERRIDE;
+ int32_t SetMicrophoneVolume(uint32_t volume) override;
// TODO(henrika): sort out calling thread once we start using this API.
- virtual int32_t MicrophoneVolume(uint32_t* volume) const OVERRIDE;
+ int32_t MicrophoneVolume(uint32_t* volume) const override;
- virtual int32_t MaxMicrophoneVolume(uint32_t* max_volume) const OVERRIDE;
- virtual int32_t MinMicrophoneVolume(uint32_t* min_volume) const OVERRIDE;
- virtual int32_t StereoPlayoutIsAvailable(bool* available) const OVERRIDE;
- virtual int32_t StereoRecordingIsAvailable(bool* available) const OVERRIDE;
- virtual int32_t PlayoutDelay(uint16_t* delay_ms) const OVERRIDE;
- virtual int32_t RecordingDelay(uint16_t* delay_ms) const OVERRIDE;
- virtual int32_t RecordingSampleRate(uint32_t* sample_rate) const OVERRIDE;
- virtual int32_t PlayoutSampleRate(uint32_t* sample_rate) const OVERRIDE;
+ int32_t MaxMicrophoneVolume(uint32_t* max_volume) const override;
+ int32_t MinMicrophoneVolume(uint32_t* min_volume) const override;
+ int32_t StereoPlayoutIsAvailable(bool* available) const override;
+ int32_t StereoRecordingIsAvailable(bool* available) const override;
+ int32_t PlayoutDelay(uint16_t* delay_ms) const override;
+ int32_t RecordingDelay(uint16_t* delay_ms) const override;
+ int32_t RecordingSampleRate(uint32_t* sample_rate) const override;
+ int32_t PlayoutSampleRate(uint32_t* sample_rate) const override;
+ public:
// Sets the |renderer_|, returns false if |renderer_| already exists.
// Called on the main renderer thread.
bool SetAudioRenderer(WebRtcAudioRenderer* renderer);
@@ -359,41 +361,44 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
class RenderBuffer;
// Make destructor private to ensure that we can only be deleted by Release().
- virtual ~WebRtcAudioDeviceImpl();
+ ~WebRtcAudioDeviceImpl() override;
// PeerConnectionAudioSink implementation.
// Called on the AudioInputDevice worker thread.
- virtual int OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames,
- const std::vector<int>& channels,
- int audio_delay_milliseconds,
- int current_volume,
- bool need_audio_processing,
- bool key_pressed) OVERRIDE;
+ int OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames,
+ const std::vector<int>& channels,
+ int audio_delay_milliseconds,
+ int current_volume,
+ bool need_audio_processing,
+ bool key_pressed) override;
// Called on the AudioInputDevice worker thread.
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
+ void OnSetFormat(const media::AudioParameters& params) override;
// WebRtcAudioRendererSource implementation.
// Called on the AudioOutputDevice worker thread.
- virtual void RenderData(media::AudioBus* audio_bus,
- int sample_rate,
- int audio_delay_milliseconds,
- base::TimeDelta* current_time) OVERRIDE;
+ void RenderData(media::AudioBus* audio_bus,
+ int sample_rate,
+ int audio_delay_milliseconds,
+ base::TimeDelta* current_time) override;
// Called on the main render thread.
- virtual void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) OVERRIDE;
+ void RemoveAudioRenderer(WebRtcAudioRenderer* renderer) override;
// WebRtcPlayoutDataSource implementation.
- virtual void AddPlayoutSink(WebRtcPlayoutDataSource::Sink* sink) OVERRIDE;
- virtual void RemovePlayoutSink(WebRtcPlayoutDataSource::Sink* sink) OVERRIDE;
-
- // Used to DCHECK that we are called on the correct thread.
- base::ThreadChecker thread_checker_;
+ void AddPlayoutSink(WebRtcPlayoutDataSource::Sink* sink) override;
+ void RemovePlayoutSink(WebRtcPlayoutDataSource::Sink* sink) override;
+
+ // Used to check methods that run on the main render thread.
+ base::ThreadChecker main_thread_checker_;
+ // Used to check methods that are called on libjingle's signaling thread.
+ base::ThreadChecker signaling_thread_checker_;
+ base::ThreadChecker worker_thread_checker_;
int ref_count_;
diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
index fad4f3f6a1f..00c6a231a8a 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
@@ -28,87 +28,82 @@ class CONTENT_EXPORT WebRtcAudioDeviceNotImpl
// TODO(henrika): it is possible to add functionality in these methods.
// Only adding very basic support for now without triggering any callback
// in the webrtc::AudioDeviceObserver interface.
- virtual int32_t ChangeUniqueId(const int32_t id) OVERRIDE;
- virtual int32_t TimeUntilNextProcess() OVERRIDE;
- virtual int32_t Process() OVERRIDE;
+ int32_t ChangeUniqueId(const int32_t id) override;
+ int32_t TimeUntilNextProcess() override;
+ int32_t Process() override;
// Methods in webrtc::AudioDeviceModule which are not yet implemented.
// The idea is that we can move methods from this class to the real
// implementation in WebRtcAudioDeviceImpl when needed.
- virtual int32_t RegisterEventObserver(
- webrtc::AudioDeviceObserver* event_callback) OVERRIDE;
- virtual int32_t ActiveAudioLayer(AudioLayer* audio_layer) const OVERRIDE;
- virtual webrtc::AudioDeviceModule::ErrorCode LastError() const OVERRIDE;
- virtual int16_t PlayoutDevices() OVERRIDE;
- virtual int16_t RecordingDevices() OVERRIDE;
- virtual int32_t PlayoutDeviceName(
- uint16_t index, char name[webrtc::kAdmMaxDeviceNameSize],
- char guid[webrtc::kAdmMaxGuidSize]) OVERRIDE;
- virtual int32_t RecordingDeviceName(
- uint16_t index, char name[webrtc::kAdmMaxDeviceNameSize],
- char guid[webrtc::kAdmMaxGuidSize]) OVERRIDE;
- virtual int32_t SetPlayoutDevice(uint16_t index) OVERRIDE;
- virtual int32_t SetPlayoutDevice(WindowsDeviceType device) OVERRIDE;
- virtual int32_t SetRecordingDevice(uint16_t index) OVERRIDE;
- virtual int32_t SetRecordingDevice(WindowsDeviceType device) OVERRIDE;
- virtual int32_t InitPlayout() OVERRIDE;
- virtual int32_t InitRecording() OVERRIDE;
- virtual int32_t SetWaveOutVolume(uint16_t volume_left,
- uint16_t volume_right) OVERRIDE;
- virtual int32_t WaveOutVolume(uint16_t* volume_left,
- uint16_t* volume_right) const OVERRIDE;
- virtual int32_t InitSpeaker() OVERRIDE;
- virtual bool SpeakerIsInitialized() const OVERRIDE;
- virtual int32_t InitMicrophone() OVERRIDE;
- virtual bool MicrophoneIsInitialized() const OVERRIDE;
- virtual int32_t SpeakerVolumeIsAvailable(bool* available) OVERRIDE;
- virtual int32_t SetSpeakerVolume(uint32_t volume) OVERRIDE;
- virtual int32_t SpeakerVolume(uint32_t* volume) const OVERRIDE;
- virtual int32_t MaxSpeakerVolume(uint32_t* max_volume) const OVERRIDE;
- virtual int32_t MinSpeakerVolume(uint32_t* min_volume) const OVERRIDE;
- virtual int32_t SpeakerVolumeStepSize(uint16_t* step_size) const OVERRIDE;
- virtual int32_t MicrophoneVolumeIsAvailable(bool* available) OVERRIDE;
- virtual int32_t MicrophoneVolumeStepSize(
- uint16_t* step_size) const OVERRIDE;
- virtual int32_t SpeakerMuteIsAvailable(bool* available) OVERRIDE;
- virtual int32_t SetSpeakerMute(bool enable) OVERRIDE;
- virtual int32_t SpeakerMute(bool* enabled) const OVERRIDE;
- virtual int32_t MicrophoneMuteIsAvailable(bool* available) OVERRIDE;
- virtual int32_t SetMicrophoneMute(bool enable) OVERRIDE;
- virtual int32_t MicrophoneMute(bool* enabled) const OVERRIDE;
- virtual int32_t MicrophoneBoostIsAvailable(bool* available) OVERRIDE;
- virtual int32_t SetMicrophoneBoost(bool enable) OVERRIDE;
- virtual int32_t MicrophoneBoost(bool* enabled) const OVERRIDE;
- virtual int32_t SetStereoPlayout(bool enable) OVERRIDE;
- virtual int32_t StereoPlayout(bool* enabled) const OVERRIDE;
- virtual int32_t SetStereoRecording(bool enable) OVERRIDE;
- virtual int32_t StereoRecording(bool* enabled) const OVERRIDE;
- virtual int32_t SetRecordingChannel(const ChannelType channel) OVERRIDE;
- virtual int32_t RecordingChannel(ChannelType* channel) const OVERRIDE;
- virtual int32_t SetPlayoutBuffer(
- const BufferType type, uint16_t size_ms) OVERRIDE;
- virtual int32_t PlayoutBuffer(
- BufferType* type, uint16_t* size_ms) const OVERRIDE;
- virtual int32_t CPULoad(uint16_t* load) const OVERRIDE;
- virtual int32_t StartRawOutputFileRecording(
- const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) OVERRIDE;
- virtual int32_t StopRawOutputFileRecording() OVERRIDE;
- virtual int32_t StartRawInputFileRecording(
- const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) OVERRIDE;
- virtual int32_t StopRawInputFileRecording() OVERRIDE;
- virtual int32_t SetRecordingSampleRate(
- const uint32_t samples_per_sec) OVERRIDE;
- virtual int32_t SetPlayoutSampleRate(
- const uint32_t samples_per_sec) OVERRIDE;
- virtual int32_t ResetAudioDevice() OVERRIDE;
- virtual int32_t SetLoudspeakerStatus(bool enable) OVERRIDE;
- virtual int32_t GetLoudspeakerStatus(bool* enabled) const OVERRIDE;
- virtual int32_t SetAGC(bool enable) OVERRIDE;
- virtual bool AGC() const OVERRIDE;
+ int32_t RegisterEventObserver(
+ webrtc::AudioDeviceObserver* event_callback) override;
+ int32_t ActiveAudioLayer(AudioLayer* audio_layer) const override;
+ webrtc::AudioDeviceModule::ErrorCode LastError() const override;
+ int16_t PlayoutDevices() override;
+ int16_t RecordingDevices() override;
+ int32_t PlayoutDeviceName(uint16_t index,
+ char name[webrtc::kAdmMaxDeviceNameSize],
+ char guid[webrtc::kAdmMaxGuidSize]) override;
+ int32_t RecordingDeviceName(uint16_t index,
+ char name[webrtc::kAdmMaxDeviceNameSize],
+ char guid[webrtc::kAdmMaxGuidSize]) override;
+ int32_t SetPlayoutDevice(uint16_t index) override;
+ int32_t SetPlayoutDevice(WindowsDeviceType device) override;
+ int32_t SetRecordingDevice(uint16_t index) override;
+ int32_t SetRecordingDevice(WindowsDeviceType device) override;
+ int32_t InitPlayout() override;
+ int32_t InitRecording() override;
+ int32_t SetWaveOutVolume(uint16_t volume_left,
+ uint16_t volume_right) override;
+ int32_t WaveOutVolume(uint16_t* volume_left,
+ uint16_t* volume_right) const override;
+ int32_t InitSpeaker() override;
+ bool SpeakerIsInitialized() const override;
+ int32_t InitMicrophone() override;
+ bool MicrophoneIsInitialized() const override;
+ int32_t SpeakerVolumeIsAvailable(bool* available) override;
+ int32_t SetSpeakerVolume(uint32_t volume) override;
+ int32_t SpeakerVolume(uint32_t* volume) const override;
+ int32_t MaxSpeakerVolume(uint32_t* max_volume) const override;
+ int32_t MinSpeakerVolume(uint32_t* min_volume) const override;
+ int32_t SpeakerVolumeStepSize(uint16_t* step_size) const override;
+ int32_t MicrophoneVolumeIsAvailable(bool* available) override;
+ int32_t MicrophoneVolumeStepSize(uint16_t* step_size) const override;
+ int32_t SpeakerMuteIsAvailable(bool* available) override;
+ int32_t SetSpeakerMute(bool enable) override;
+ int32_t SpeakerMute(bool* enabled) const override;
+ int32_t MicrophoneMuteIsAvailable(bool* available) override;
+ int32_t SetMicrophoneMute(bool enable) override;
+ int32_t MicrophoneMute(bool* enabled) const override;
+ int32_t MicrophoneBoostIsAvailable(bool* available) override;
+ int32_t SetMicrophoneBoost(bool enable) override;
+ int32_t MicrophoneBoost(bool* enabled) const override;
+ int32_t SetStereoPlayout(bool enable) override;
+ int32_t StereoPlayout(bool* enabled) const override;
+ int32_t SetStereoRecording(bool enable) override;
+ int32_t StereoRecording(bool* enabled) const override;
+ int32_t SetRecordingChannel(const ChannelType channel) override;
+ int32_t RecordingChannel(ChannelType* channel) const override;
+ int32_t SetPlayoutBuffer(const BufferType type, uint16_t size_ms) override;
+ int32_t PlayoutBuffer(BufferType* type, uint16_t* size_ms) const override;
+ int32_t CPULoad(uint16_t* load) const override;
+ int32_t StartRawOutputFileRecording(
+ const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) override;
+ int32_t StopRawOutputFileRecording() override;
+ int32_t StartRawInputFileRecording(
+ const char pcm_file_name_utf8[webrtc::kAdmMaxFileNameSize]) override;
+ int32_t StopRawInputFileRecording() override;
+ int32_t SetRecordingSampleRate(const uint32_t samples_per_sec) override;
+ int32_t SetPlayoutSampleRate(const uint32_t samples_per_sec) override;
+ int32_t ResetAudioDevice() override;
+ int32_t SetLoudspeakerStatus(bool enable) override;
+ int32_t GetLoudspeakerStatus(bool* enabled) const override;
+ int32_t SetAGC(bool enable) override;
+ bool AGC() const override;
protected:
- virtual ~WebRtcAudioDeviceNotImpl() {};
+ ~WebRtcAudioDeviceNotImpl() override{};
private:
base::TimeTicks last_process_time_;
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc_audio_renderer.cc
index f86c8cc6673..862c3fd72ac 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.cc
@@ -9,8 +9,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_logging.h"
+#include "content/renderer/render_frame_impl.h"
#include "media/audio/audio_output_device.h"
#include "media/audio/audio_parameters.h"
#include "media/audio/sample_rates.h"
@@ -27,68 +29,10 @@ namespace content {
namespace {
-// Supported hardware sample rates for output sides.
-#if defined(OS_WIN) || defined(OS_MACOSX)
-// AudioHardwareConfig::GetOutputSampleRate() asks the audio layer for its
-// current sample rate (set by the user) on Windows and Mac OS X. The listed
-// rates below adds restrictions and Initialize() will fail if the user selects
-// any rate outside these ranges.
-const int kValidOutputRates[] = {96000, 48000, 44100, 32000, 16000};
-#elif defined(OS_LINUX) || defined(OS_OPENBSD)
-const int kValidOutputRates[] = {48000, 44100};
-#elif defined(OS_ANDROID)
-// TODO(leozwang): We want to use native sampling rate on Android to achieve
-// low latency, currently 16000 is used to work around audio problem on some
-// Android devices.
-const int kValidOutputRates[] = {48000, 44100, 16000};
-#else
-const int kValidOutputRates[] = {44100};
-#endif
-
-// TODO(xians): Merge the following code to WebRtcAudioCapturer, or remove.
-enum AudioFramesPerBuffer {
- k160,
- k320,
- k440,
- k480,
- k640,
- k880,
- k960,
- k1440,
- k1920,
- kUnexpectedAudioBufferSize // Must always be last!
-};
-
-// Helper method to convert integral values to their respective enum values
-// above, or kUnexpectedAudioBufferSize if no match exists.
-// We map 441 to k440 to avoid changes in the XML part for histograms.
-// It is still possible to map the histogram result to the actual buffer size.
-// See http://crbug.com/243450 for details.
-AudioFramesPerBuffer AsAudioFramesPerBuffer(int frames_per_buffer) {
- switch (frames_per_buffer) {
- case 160: return k160;
- case 320: return k320;
- case 441: return k440;
- case 480: return k480;
- case 640: return k640;
- case 880: return k880;
- case 960: return k960;
- case 1440: return k1440;
- case 1920: return k1920;
- }
- return kUnexpectedAudioBufferSize;
-}
-
-void AddHistogramFramesPerBuffer(int param) {
- AudioFramesPerBuffer afpb = AsAudioFramesPerBuffer(param);
- if (afpb != kUnexpectedAudioBufferSize) {
- UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputFramesPerBuffer",
- afpb, kUnexpectedAudioBufferSize);
- } else {
- // Report unexpected sample rates using a unique histogram name.
- UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputFramesPerBufferUnexpected", param);
- }
-}
+// We add a UMA histogram measuring the execution time of the Render() method
+// every |kNumCallbacksBetweenRenderTimeHistograms| callback. Assuming 10ms
+// between each callback leads to one UMA update each 100ms.
+const int kNumCallbacksBetweenRenderTimeHistograms = 10;
// This is a simple wrapper class that's handed out to users of a shared
// WebRtcAudioRenderer instance. This class maintains the per-user 'playing'
@@ -114,13 +58,13 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
}
protected:
- virtual ~SharedAudioRenderer() {
+ ~SharedAudioRenderer() override {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << __FUNCTION__;
Stop();
}
- virtual void Start() OVERRIDE {
+ void Start() override {
DCHECK(thread_checker_.CalledOnValidThread());
if (started_)
return;
@@ -128,7 +72,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
delegate_->Start();
}
- virtual void Play() OVERRIDE {
+ void Play() override {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(started_);
if (playing_state_.playing())
@@ -137,7 +81,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
on_play_state_changed_.Run(media_stream_, &playing_state_);
}
- virtual void Pause() OVERRIDE {
+ void Pause() override {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(started_);
if (!playing_state_.playing())
@@ -146,7 +90,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
on_play_state_changed_.Run(media_stream_, &playing_state_);
}
- virtual void Stop() OVERRIDE {
+ void Stop() override {
DCHECK(thread_checker_.CalledOnValidThread());
if (!started_)
return;
@@ -155,19 +99,19 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
delegate_->Stop();
}
- virtual void SetVolume(float volume) OVERRIDE {
+ void SetVolume(float volume) override {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(volume >= 0.0f && volume <= 1.0f);
playing_state_.set_volume(volume);
on_play_state_changed_.Run(media_stream_, &playing_state_);
}
- virtual base::TimeDelta GetCurrentRenderTime() const OVERRIDE {
+ base::TimeDelta GetCurrentRenderTime() const override {
DCHECK(thread_checker_.CalledOnValidThread());
return delegate_->GetCurrentRenderTime();
}
- virtual bool IsLocalRenderer() const OVERRIDE {
+ bool IsLocalRenderer() const override {
DCHECK(thread_checker_.CalledOnValidThread());
return delegate_->IsLocalRenderer();
}
@@ -181,9 +125,58 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
OnPlayStateChanged on_play_state_changed_;
};
+// Returns either AudioParameters::NO_EFFECTS or AudioParameters::DUCKING
+// depending on whether or not an input element is currently open with
+// ducking enabled.
+int GetCurrentDuckingFlag(int render_frame_id) {
+ RenderFrameImpl* const frame =
+ RenderFrameImpl::FromRoutingID(render_frame_id);
+ MediaStreamDispatcher* const dispatcher = frame ?
+ frame->GetMediaStreamDispatcher() : NULL;
+ if (dispatcher && dispatcher->IsAudioDuckingActive()) {
+ return media::AudioParameters::DUCKING;
+ }
+
+ return media::AudioParameters::NO_EFFECTS;
+}
+
} // namespace
+int WebRtcAudioRenderer::GetOptimalBufferSize(int sample_rate,
+ int hardware_buffer_size) {
+ // Use native hardware buffer size as default. On Windows, we strive to open
+ // up using this native hardware buffer size to achieve best
+ // possible performance and to ensure that no FIFO is needed on the browser
+ // side to match the client request. That is why there is no #if case for
+ // Windows below.
+ int frames_per_buffer = hardware_buffer_size;
+
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+ // On Linux and MacOS, the low level IO implementations on the browser side
+ // supports all buffer size the clients want. We use the native peer
+ // connection buffer size (10ms) to achieve best possible performance.
+ frames_per_buffer = sample_rate / 100;
+#elif defined(OS_ANDROID)
+ // TODO(henrika): Keep tuning this scheme and espcicially for low-latency
+ // cases. Might not be possible to come up with the perfect solution using
+ // the render side only.
+ int frames_per_10ms = sample_rate / 100;
+ if (frames_per_buffer < 2 * frames_per_10ms) {
+ // Examples of low-latency frame sizes and the resulting |buffer_size|:
+ // Nexus 7 : 240 audio frames => 2*480 = 960
+ // Nexus 10 : 256 => 2*441 = 882
+ // Galaxy Nexus: 144 => 2*441 = 882
+ frames_per_buffer = 2 * frames_per_10ms;
+ DVLOG(1) << "Low-latency output detected on Android";
+ }
+#endif
+
+ DVLOG(1) << "Using sink output buffer size: " << frames_per_buffer;
+ return frames_per_buffer;
+}
+
WebRtcAudioRenderer::WebRtcAudioRenderer(
+ const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread,
const scoped_refptr<webrtc::MediaStreamInterface>& media_stream,
int source_render_view_id,
int source_render_frame_id,
@@ -194,6 +187,7 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(
source_render_view_id_(source_render_view_id),
source_render_frame_id_(source_render_frame_id),
session_id_(session_id),
+ signaling_thread_(signaling_thread),
media_stream_(media_stream),
source_(NULL),
play_ref_count_(0),
@@ -201,15 +195,18 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(
audio_delay_milliseconds_(0),
fifo_delay_milliseconds_(0),
sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 0, sample_rate, 16,
- frames_per_buffer, media::AudioParameters::DUCKING) {
+ media::CHANNEL_LAYOUT_STEREO, sample_rate, 16,
+ frames_per_buffer,
+ GetCurrentDuckingFlag(source_render_frame_id)),
+ render_callback_count_(0) {
WebRtcLogMessage(base::StringPrintf(
"WAR::WAR. source_render_view_id=%d"
- ", session_id=%d, sample_rate=%d, frames_per_buffer=%d",
+ ", session_id=%d, sample_rate=%d, frames_per_buffer=%d, effects=%i",
source_render_view_id,
session_id,
sample_rate,
- frames_per_buffer));
+ frames_per_buffer,
+ sink_params_.effects()));
}
WebRtcAudioRenderer::~WebRtcAudioRenderer() {
@@ -247,16 +244,6 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
sample_rate);
}
- // Verify that the reported output hardware sample rate is supported
- // on the current platform.
- if (std::find(&kValidOutputRates[0],
- &kValidOutputRates[0] + arraysize(kValidOutputRates),
- sample_rate) ==
- &kValidOutputRates[arraysize(kValidOutputRates)]) {
- DLOG(ERROR) << sample_rate << " is not a supported output rate.";
- return false;
- }
-
// Set up audio parameters for the source, i.e., the WebRTC client.
// The WebRTC client only supports multiples of 10ms as buffer size where
@@ -266,34 +253,14 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
DVLOG(1) << "Using WebRTC output buffer size: " << frames_per_10ms;
source_params.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- sink_params_.channel_layout(), sink_params_.channels(), 0,
+ sink_params_.channel_layout(), sink_params_.channels(),
sample_rate, 16, frames_per_10ms);
- // Update audio parameters for the sink, i.e., the native audio output stream.
- // We strive to open up using native parameters to achieve best possible
- // performance and to ensure that no FIFO is needed on the browser side to
- // match the client request. Any mismatch between the source and the sink is
- // taken care of in this class instead using a pull FIFO.
-
- // Use native output size as default.
- int frames_per_buffer = sink_params_.frames_per_buffer();
-#if defined(OS_ANDROID)
- // TODO(henrika): Keep tuning this scheme and espcicially for low-latency
- // cases. Might not be possible to come up with the perfect solution using
- // the render side only.
- if (frames_per_buffer < 2 * frames_per_10ms) {
- // Examples of low-latency frame sizes and the resulting |buffer_size|:
- // Nexus 7 : 240 audio frames => 2*480 = 960
- // Nexus 10 : 256 => 2*441 = 882
- // Galaxy Nexus: 144 => 2*441 = 882
- frames_per_buffer = 2 * frames_per_10ms;
- DVLOG(1) << "Low-latency output detected on Android";
- }
-#endif
- DVLOG(1) << "Using sink output buffer size: " << frames_per_buffer;
+ const int frames_per_buffer =
+ GetOptimalBufferSize(sample_rate, sink_params_.frames_per_buffer());
sink_params_.Reset(sink_params_.format(), sink_params_.channel_layout(),
- sink_params_.channels(), 0, sample_rate, 16,
+ sink_params_.channels(), sample_rate, 16,
frames_per_buffer);
// Create a FIFO if re-buffering is required to match the source input with
@@ -332,11 +299,6 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
// User must call Play() before any audio can be heard.
state_ = PAUSED;
- UMA_HISTOGRAM_ENUMERATION("WebRTC.AudioOutputFramesPerBuffer",
- source_params.frames_per_buffer(),
- kUnexpectedAudioBufferSize);
- AddHistogramFramesPerBuffer(source_params.frames_per_buffer());
-
return true;
}
@@ -367,6 +329,7 @@ void WebRtcAudioRenderer::Play() {
return;
playing_state_.set_playing(true);
+ render_callback_count_ = 0;
OnPlayStateChanged(media_stream_, &playing_state_);
}
@@ -486,6 +449,7 @@ void WebRtcAudioRenderer::OnRenderError() {
// Called by AudioPullFifo when more data is necessary.
void WebRtcAudioRenderer::SourceCallback(
int fifo_frame_delay, media::AudioBus* audio_bus) {
+ base::TimeTicks start_time = base::TimeTicks::Now() ;
DVLOG(2) << "WebRtcAudioRenderer::SourceCallback("
<< fifo_frame_delay << ", "
<< audio_bus->frames() << ")";
@@ -504,6 +468,12 @@ void WebRtcAudioRenderer::SourceCallback(
// return here and ensure that the returned value in Render() is 0.
if (state_ != PLAYING)
audio_bus->Zero();
+
+ if (++render_callback_count_ == kNumCallbacksBetweenRenderTimeHistograms) {
+ base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
+ render_callback_count_ = 0;
+ UMA_HISTOGRAM_TIMES("WebRTC.AudioRenderTimes", elapsed);
+ }
}
void WebRtcAudioRenderer::UpdateSourceVolume(
@@ -531,7 +501,15 @@ void WebRtcAudioRenderer::UpdateSourceVolume(
volume = 10.0f;
DVLOG(1) << "Setting remote source volume: " << volume;
- source->SetVolume(volume);
+ if (!signaling_thread_->BelongsToCurrentThread()) {
+ // Libjingle hands out proxy objects in most cases, but the audio source
+ // object is an exception (bug?). So, to work around that, we need to make
+ // sure we call SetVolume on the signaling thread.
+ signaling_thread_->PostTask(FROM_HERE,
+ base::Bind(&webrtc::AudioSourceInterface::SetVolume, source, volume));
+ } else {
+ source->SetVolume(volume);
+ }
}
bool WebRtcAudioRenderer::AddPlayingState(
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.h b/chromium/content/renderer/media/webrtc_audio_renderer.h
index 61b0b24d141..d6bd923de8b 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.h
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.h
@@ -69,7 +69,12 @@ class CONTENT_EXPORT WebRtcAudioRenderer
float volume_;
};
+
+ // Returns platform specific optimal buffer size for rendering audio.
+ static int GetOptimalBufferSize(int sample_rate, int hardware_buffer_size);
+
WebRtcAudioRenderer(
+ const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread,
const scoped_refptr<webrtc::MediaStreamInterface>& media_stream,
int source_render_view_id,
int source_render_frame_id,
@@ -99,18 +104,19 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// Accessors to the sink audio parameters.
int channels() const { return sink_params_.channels(); }
int sample_rate() const { return sink_params_.sample_rate(); }
+ int frames_per_buffer() const { return sink_params_.frames_per_buffer(); }
private:
// MediaStreamAudioRenderer implementation. This is private since we want
// callers to use proxy objects.
// TODO(tommi): Make the MediaStreamAudioRenderer implementation a pimpl?
- virtual void Start() OVERRIDE;
- virtual void Play() OVERRIDE;
- virtual void Pause() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void SetVolume(float volume) OVERRIDE;
- virtual base::TimeDelta GetCurrentRenderTime() const OVERRIDE;
- virtual bool IsLocalRenderer() const OVERRIDE;
+ void Start() override;
+ void Play() override;
+ void Pause() override;
+ void Stop() override;
+ void SetVolume(float volume) override;
+ base::TimeDelta GetCurrentRenderTime() const override;
+ bool IsLocalRenderer() const override;
// Called when an audio renderer, either the main or a proxy, starts playing.
// Here we maintain a reference count of how many renderers are currently
@@ -123,7 +129,7 @@ class CONTENT_EXPORT WebRtcAudioRenderer
void EnterPauseState();
protected:
- virtual ~WebRtcAudioRenderer();
+ ~WebRtcAudioRenderer() override;
private:
enum State {
@@ -148,9 +154,8 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// media::AudioRendererSink::RenderCallback implementation.
// These two methods are called on the AudioOutputDevice worker thread.
- virtual int Render(media::AudioBus* audio_bus,
- int audio_delay_milliseconds) OVERRIDE;
- virtual void OnRenderError() OVERRIDE;
+ int Render(media::AudioBus* audio_bus, int audio_delay_milliseconds) override;
+ void OnRenderError() override;
// Called by AudioPullFifo when more data is necessary.
// This method is called on the AudioOutputDevice worker thread.
@@ -185,6 +190,8 @@ class CONTENT_EXPORT WebRtcAudioRenderer
const int source_render_frame_id_;
const int session_id_;
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
+
// The sink (destination) for rendered audio.
scoped_refptr<media::AudioOutputDevice> sink_;
@@ -229,6 +236,10 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// before being destructed (PlayingState object goes out of scope).
SourcePlayingStates source_playing_states_;
+ // Used for triggering new UMA histogram. Counts number of render
+ // callbacks modulo |kNumCallbacksBetweenRenderTimeHistograms|.
+ int render_callback_count_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioRenderer);
};
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc b/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc
index 3cf1b523806..545236492c1 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc
@@ -24,6 +24,9 @@ namespace content {
namespace {
+const int kHardwareSampleRate = 44100;
+const int kHardwareBufferSize = 512;
+
class MockAudioOutputIPC : public media::AudioOutputIPC {
public:
MockAudioOutputIPC() {}
@@ -87,11 +90,13 @@ class WebRtcAudioRendererTest : public testing::Test {
message_loop_->message_loop_proxy())),
factory_(new MockAudioDeviceFactory()),
source_(new MockAudioRendererSource()),
- stream_(new talk_base::RefCountedObject<MockMediaStream>("label")),
- renderer_(new WebRtcAudioRenderer(stream_, 1, 1, 1, 44100, 441)) {
+ stream_(new rtc::RefCountedObject<MockMediaStream>("label")),
+ renderer_(new WebRtcAudioRenderer(message_loop_->message_loop_proxy(),
+ stream_, 1, 1, 1, 44100,
+ kHardwareBufferSize)) {
EXPECT_CALL(*factory_.get(), CreateOutputDevice(1))
- .WillOnce(Return(mock_output_device_));
- EXPECT_CALL(*mock_output_device_, Start());
+ .WillOnce(Return(mock_output_device_.get()));
+ EXPECT_CALL(*mock_output_device_.get(), Start());
EXPECT_TRUE(renderer_->Initialize(source_.get()));
renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_);
}
@@ -114,7 +119,7 @@ TEST_F(WebRtcAudioRendererTest, StopRenderer) {
// |renderer_| has only one proxy, stopping the proxy should stop the sink of
// |renderer_|.
- EXPECT_CALL(*mock_output_device_, Stop());
+ EXPECT_CALL(*mock_output_device_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
}
@@ -136,19 +141,40 @@ TEST_F(WebRtcAudioRendererTest, MultipleRenderers) {
// Stop the |renderer_proxy_| should not stop the sink since it is used by
// other proxies.
- EXPECT_CALL(*mock_output_device_, Stop()).Times(0);
+ EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0);
renderer_proxy_->Stop();
for (int i = 0; i < kNumberOfRendererProxy; ++i) {
if (i != kNumberOfRendererProxy -1) {
- EXPECT_CALL(*mock_output_device_, Stop()).Times(0);
+ EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0);
} else {
// When the last proxy is stopped, the sink will stop.
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
- EXPECT_CALL(*mock_output_device_, Stop());
+ EXPECT_CALL(*mock_output_device_.get(), Stop());
}
renderer_proxies_[i]->Stop();
}
}
+// Verify that the sink of the renderer is using the expected sample rate and
+// buffer size.
+TEST_F(WebRtcAudioRendererTest, VerifySinkParameters) {
+ renderer_proxy_->Start();
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+ static const int kExpectedBufferSize = kHardwareSampleRate / 100;
+#elif defined(OS_ANDROID)
+ static const int kExpectedBufferSize = 2 * kHardwareSampleRate / 100;
+#else
+ // Windows.
+ static const int kExpectedBufferSize = kHardwareBufferSize;
+#endif
+ EXPECT_EQ(kExpectedBufferSize, renderer_->frames_per_buffer());
+ EXPECT_EQ(kHardwareSampleRate, renderer_->sample_rate());
+ EXPECT_EQ(2, renderer_->channels());
+
+ EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
+ renderer_proxy_->Stop();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_identity_service.h b/chromium/content/renderer/media/webrtc_identity_service.h
index 756148e55b8..12b25497de4 100644
--- a/chromium/content/renderer/media/webrtc_identity_service.h
+++ b/chromium/content/renderer/media/webrtc_identity_service.h
@@ -28,7 +28,7 @@ class CONTENT_EXPORT WebRTCIdentityService : public RenderProcessObserver {
typedef base::Callback<void(int error)> FailureCallback;
WebRTCIdentityService();
- virtual ~WebRTCIdentityService();
+ ~WebRTCIdentityService() override;
// Sends an identity request.
//
@@ -58,7 +58,7 @@ class CONTENT_EXPORT WebRTCIdentityService : public RenderProcessObserver {
// For unittest to override.
virtual bool Send(IPC::Message* message);
// RenderProcessObserver implementation. Protected for testing.
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& message) override;
private:
struct RequestInfo {
diff --git a/chromium/content/renderer/media/webrtc_identity_service_unittest.cc b/chromium/content/renderer/media/webrtc_identity_service_unittest.cc
index 856865d86c2..38059714f21 100644
--- a/chromium/content/renderer/media/webrtc_identity_service_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_identity_service_unittest.cc
@@ -22,13 +22,13 @@ static const int FAKE_ERROR = 100;
class WebRTCIdentityServiceForTest : public WebRTCIdentityService {
public:
- virtual bool Send(IPC::Message* message) OVERRIDE {
+ bool Send(IPC::Message* message) override {
messages_.push_back(*message);
delete message;
return true;
}
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool OnControlMessageReceived(const IPC::Message& message) override {
return WebRTCIdentityService::OnControlMessageReceived(message);
}
diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
index 1deb11e26ef..dd657eb7c3e 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
@@ -10,10 +10,13 @@
#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
#include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
+#include "content/renderer/media/webrtc_audio_renderer.h"
+#include "content/renderer/render_frame_impl.h"
#include "media/audio/audio_output_device.h"
+#include "media/base/audio_block_fifo.h"
#include "media/base/audio_bus.h"
-#include "media/base/audio_fifo.h"
namespace content {
@@ -40,8 +43,10 @@ int WebRtcLocalAudioRenderer::Render(
// Provide data by reading from the FIFO if the FIFO contains enough
// to fulfill the request.
- if (loopback_fifo_->frames() >= audio_bus->frames()) {
- loopback_fifo_->Consume(audio_bus, 0, audio_bus->frames());
+ if (loopback_fifo_->available_blocks()) {
+ const media::AudioBus* audio_data = loopback_fifo_->Consume();
+ DCHECK_EQ(audio_data->frames(), audio_bus->frames());
+ audio_data->CopyTo(audio_bus);
} else {
audio_bus->Zero();
// This warning is perfectly safe if it happens for the first audio
@@ -68,14 +73,8 @@ void WebRtcLocalAudioRenderer::OnData(const int16* audio_data,
return;
// Push captured audio to FIFO so it can be read by a local sink.
- if (loopback_fifo_->frames() + number_of_frames <=
- loopback_fifo_->max_frames()) {
- scoped_ptr<media::AudioBus> audio_source = media::AudioBus::Create(
- number_of_channels, number_of_frames);
- audio_source->FromInterleaved(audio_data,
- audio_source->frames(),
- sizeof(audio_data[0]));
- loopback_fifo_->Push(audio_source.get());
+ if (loopback_fifo_->GetUnfilledFrames() >= number_of_frames) {
+ loopback_fifo_->Push(audio_data, number_of_frames, sizeof(audio_data[0]));
const base::TimeTicks now = base::TimeTicks::Now();
total_render_time_ += now - last_render_time_;
@@ -93,44 +92,6 @@ void WebRtcLocalAudioRenderer::OnSetFormat(
capture_thread_checker_.DetachFromThread();
DCHECK(capture_thread_checker_.CalledOnValidThread());
- // Reset the |source_params_|, |sink_params_| and |loopback_fifo_| to match
- // the new format.
- {
- base::AutoLock auto_lock(thread_lock_);
- if (source_params_ == params)
- return;
-
- source_params_ = params;
-
- sink_params_ = media::AudioParameters(source_params_.format(),
- source_params_.channel_layout(), source_params_.channels(),
- source_params_.input_channels(), source_params_.sample_rate(),
- source_params_.bits_per_sample(),
-#if defined(OS_ANDROID)
- // On Android, input and output use the same sample rate. In order to
- // use the low latency mode, we need to use the buffer size suggested by
- // the AudioManager for the sink. It will later be used to decide
- // the buffer size of the shared memory buffer.
- frames_per_buffer_,
-#else
- 2 * source_params_.frames_per_buffer(),
-#endif
- // If DUCKING is enabled on the source, it needs to be enabled on the
- // sink as well.
- source_params_.effects());
-
- // TODO(henrika): we could add a more dynamic solution here but I prefer
- // a fixed size combined with bad audio at overflow. The alternative is
- // that we start to build up latency and that can be more difficult to
- // detect. Tests have shown that the FIFO never contains more than 2 or 3
- // audio frames but I have selected a max size of ten buffers just
- // in case since these tests were performed on a 16 core, 64GB Win 7
- // machine. We could also add some sort of error notifier in this area if
- // the FIFO overflows.
- loopback_fifo_.reset(new media::AudioFifo(
- params.channels(), 10 * params.frames_per_buffer()));
- }
-
// Post a task on the main render thread to reconfigure the |sink_| with the
// new format.
message_loop_->PostTask(
@@ -193,7 +154,7 @@ void WebRtcLocalAudioRenderer::Stop() {
// Stop the output audio stream, i.e, stop asking for data to render.
// It is safer to call Stop() on the |sink_| to clean up the resources even
// when the |sink_| is never started.
- if (sink_) {
+ if (sink_.get()) {
sink_->Stop();
sink_ = NULL;
}
@@ -278,10 +239,11 @@ void WebRtcLocalAudioRenderer::MaybeStartSink() {
if (!sink_.get() || !source_params_.IsValid())
return;
- base::AutoLock auto_lock(thread_lock_);
-
- // Clear up the old data in the FIFO.
- loopback_fifo_->Clear();
+ {
+ // Clear up the old data in the FIFO.
+ base::AutoLock auto_lock(thread_lock_);
+ loopback_fifo_->Clear();
+ }
if (!sink_params_.IsValid() || !playing_ || !volume_ || sink_started_)
return;
@@ -300,7 +262,54 @@ void WebRtcLocalAudioRenderer::ReconfigureSink(
DVLOG(1) << "WebRtcLocalAudioRenderer::ReconfigureSink()";
- if (!sink_)
+ int implicit_ducking_effect = 0;
+ RenderFrameImpl* const frame =
+ RenderFrameImpl::FromRoutingID(source_render_frame_id_);
+ MediaStreamDispatcher* const dispatcher = frame ?
+ frame->GetMediaStreamDispatcher() : NULL;
+ if (dispatcher && dispatcher->IsAudioDuckingActive()) {
+ DVLOG(1) << "Forcing DUCKING to be ON for output";
+ implicit_ducking_effect = media::AudioParameters::DUCKING;
+ } else {
+ DVLOG(1) << "DUCKING not forced ON for output";
+ }
+
+ if (source_params_.Equals(params))
+ return;
+
+ // Reset the |source_params_|, |sink_params_| and |loopback_fifo_| to match
+ // the new format.
+
+ source_params_ = params;
+
+ sink_params_ = media::AudioParameters(source_params_.format(),
+ source_params_.channel_layout(), source_params_.sample_rate(),
+ source_params_.bits_per_sample(),
+ WebRtcAudioRenderer::GetOptimalBufferSize(source_params_.sample_rate(),
+ frames_per_buffer_),
+ // If DUCKING is enabled on the source, it needs to be enabled on the
+ // sink as well.
+ source_params_.effects() | implicit_ducking_effect);
+
+ {
+ // TODO(henrika): we could add a more dynamic solution here but I prefer
+ // a fixed size combined with bad audio at overflow. The alternative is
+ // that we start to build up latency and that can be more difficult to
+ // detect. Tests have shown that the FIFO never contains more than 2 or 3
+ // audio frames but I have selected a max size of ten buffers just
+ // in case since these tests were performed on a 16 core, 64GB Win 7
+ // machine. We could also add some sort of error notifier in this area if
+ // the FIFO overflows.
+ const int blocks_of_buffers =
+ 10 * params.frames_per_buffer() / sink_params_.frames_per_buffer() + 1;
+ media::AudioBlockFifo* new_fifo = new media::AudioBlockFifo(
+ params.channels(), sink_params_.frames_per_buffer(), blocks_of_buffers);
+
+ base::AutoLock auto_lock(thread_lock_);
+ loopback_fifo_.reset(new_fifo);
+ }
+
+ if (!sink_.get())
return; // WebRtcLocalAudioRenderer has not yet been started.
// Stop |sink_| and re-create a new one to be initialized with different audio
@@ -309,6 +318,7 @@ void WebRtcLocalAudioRenderer::ReconfigureSink(
sink_->Stop();
sink_started_ = false;
}
+
sink_ = AudioDeviceFactory::NewOutputDevice(source_render_view_id_,
source_render_frame_id_);
MaybeStartSink();
diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.h b/chromium/content/renderer/media/webrtc_local_audio_renderer.h
index 39f13f2520b..95987f4d870 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_renderer.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_renderer.h
@@ -21,7 +21,7 @@
namespace media {
class AudioBus;
-class AudioFifo;
+class AudioBlockFifo;
class AudioOutputDevice;
class AudioParameters;
}
@@ -58,39 +58,38 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer
// MediaStreamAudioRenderer implementation.
// Called on the main thread.
- virtual void Start() OVERRIDE;
- virtual void Stop() OVERRIDE;
- virtual void Play() OVERRIDE;
- virtual void Pause() OVERRIDE;
- virtual void SetVolume(float volume) OVERRIDE;
- virtual base::TimeDelta GetCurrentRenderTime() const OVERRIDE;
- virtual bool IsLocalRenderer() const OVERRIDE;
+ void Start() override;
+ void Stop() override;
+ void Play() override;
+ void Pause() override;
+ void SetVolume(float volume) override;
+ base::TimeDelta GetCurrentRenderTime() const override;
+ bool IsLocalRenderer() const override;
const base::TimeDelta& total_render_time() const {
return total_render_time_;
}
protected:
- virtual ~WebRtcLocalAudioRenderer();
+ ~WebRtcLocalAudioRenderer() override;
private:
// MediaStreamAudioSink implementation.
// Called on the AudioInputDevice worker thread.
- virtual void OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames) OVERRIDE;
+ void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) override;
// Called on the AudioInputDevice worker thread.
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
+ void OnSetFormat(const media::AudioParameters& params) override;
// media::AudioRendererSink::RenderCallback implementation.
// Render() is called on the AudioOutputDevice thread and OnRenderError()
// on the IO thread.
- virtual int Render(media::AudioBus* audio_bus,
- int audio_delay_milliseconds) OVERRIDE;
- virtual void OnRenderError() OVERRIDE;
+ int Render(media::AudioBus* audio_bus, int audio_delay_milliseconds) override;
+ void OnRenderError() override;
// Initializes and starts the |sink_| if
// we have received valid |source_params_| &&
@@ -124,7 +123,7 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer
scoped_refptr<media::AudioOutputDevice> sink_;
// Contains copies of captured audio frames.
- scoped_ptr<media::AudioFifo> loopback_fifo_;
+ scoped_ptr<media::AudioBlockFifo> loopback_fifo_;
// Stores last time a render callback was received. The time difference
// between a new time stamp and this value can be used to derive the
@@ -135,9 +134,11 @@ class CONTENT_EXPORT WebRtcLocalAudioRenderer
base::TimeDelta total_render_time_;
// The audio parameters of the capture source.
+ // Must only be touched on the main thread.
media::AudioParameters source_params_;
// The audio parameters used by the sink.
+ // Must only be touched on the main thread.
media::AudioParameters sink_params_;
// Set when playing, cleared when paused.
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
index 10ee943f00f..92539843864 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc
@@ -36,7 +36,7 @@ WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider(
int sample_rate = hardware_config->GetOutputSampleRate();
sink_params_.Reset(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 2, 0, sample_rate, 16,
+ media::CHANNEL_LAYOUT_STEREO, 2, sample_rate, 16,
kWebAudioRenderBufferSize);
}
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
index 9abd89f9569..24e873ced11 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
@@ -53,24 +53,24 @@ class CONTENT_EXPORT WebRtcLocalAudioSourceProvider
virtual ~WebRtcLocalAudioSourceProvider();
// MediaStreamAudioSink implementation.
- virtual void OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames) OVERRIDE;
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
- virtual void OnReadyStateChanged(
- blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
+ void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) override;
+ void OnSetFormat(const media::AudioParameters& params) override;
+ void OnReadyStateChanged(
+ blink::WebMediaStreamSource::ReadyState state) override;
// blink::WebAudioSourceProvider implementation.
- virtual void setClient(blink::WebAudioSourceProviderClient* client) OVERRIDE;
+ virtual void setClient(blink::WebAudioSourceProviderClient* client) override;
virtual void provideInput(const blink::WebVector<float*>& audio_data,
- size_t number_of_frames) OVERRIDE;
+ size_t number_of_frames) override;
// media::AudioConverter::Inputcallback implementation.
// This function is triggered by provideInput()on the WebAudio audio thread,
// so it has been under the protection of |lock_|.
- virtual double ProvideInput(media::AudioBus* audio_bus,
- base::TimeDelta buffer_delay) OVERRIDE;
+ double ProvideInput(media::AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) override;
// Method to allow the unittests to inject its own sink parameters to avoid
// query the hardware.
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
index 3374b7488d1..5b6499b2aa8 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
@@ -13,17 +13,18 @@
#include "media/base/audio_bus.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
namespace content {
class WebRtcLocalAudioSourceProviderTest : public testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
source_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_MONO, 1, 0, 48000, 16, 480);
+ media::CHANNEL_LAYOUT_MONO, 1, 48000, 16, 480);
sink_params_.Reset(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 2, 0, 44100, 16,
+ media::CHANNEL_LAYOUT_STEREO, 2, 44100, 16,
WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize);
const int length =
source_params_.frames_per_buffer() * source_params_.channels();
@@ -37,7 +38,7 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> native_track(
- new WebRtcLocalAudioTrack(adapter, capturer, NULL));
+ new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
blink::WebMediaStreamSource audio_source;
audio_source.initialize(base::UTF8ToUTF16("dummy_source_id"),
blink::WebMediaStreamSource::TypeAudio,
@@ -50,6 +51,12 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
source_provider_->OnSetFormat(source_params_);
}
+ void TearDown() override {
+ source_provider_.reset();
+ blink_track_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
media::AudioParameters source_params_;
scoped_ptr<int16[]> source_data_;
media::AudioParameters sink_params_;
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.cc b/chromium/content/renderer/media/webrtc_local_audio_track.cc
index 95f34f64ea3..8fc1e4f9ae0 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_track.cc
@@ -20,11 +20,12 @@ WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
WebRtcLocalAudioTrackAdapter* adapter,
const scoped_refptr<WebRtcAudioCapturer>& capturer,
WebAudioCapturerSource* webaudio_source)
- : MediaStreamTrack(adapter, true),
+ : MediaStreamTrack(true),
adapter_(adapter),
capturer_(capturer),
webaudio_source_(webaudio_source) {
DCHECK(capturer.get() || webaudio_source);
+ signal_thread_checker_.DetachFromThread();
adapter_->Initialize(this);
@@ -42,13 +43,14 @@ void WebRtcLocalAudioTrack::Capture(const int16* audio_data,
base::TimeDelta delay,
int volume,
bool key_pressed,
- bool need_audio_processing) {
+ bool need_audio_processing,
+ bool force_report_nonzero_energy) {
DCHECK(capture_thread_checker_.CalledOnValidThread());
// Calculate the signal level regardless if the track is disabled or enabled.
int signal_level = level_calculator_->Calculate(
audio_data, audio_parameters_.channels(),
- audio_parameters_.frames_per_buffer());
+ audio_parameters_.frames_per_buffer(), force_report_nonzero_energy);
adapter_->SetSignalLevel(signal_level);
scoped_refptr<WebRtcAudioCapturer> capturer;
@@ -86,7 +88,7 @@ void WebRtcLocalAudioTrack::Capture(const int16* audio_data,
volume,
need_audio_processing,
key_pressed);
- if (new_volume != 0 && capturer.get() && !webaudio_source_) {
+ if (new_volume != 0 && capturer.get() && !webaudio_source_.get()) {
// Feed the new volume to WebRtc while changing the volume on the
// browser.
capturer->SetVolume(new_volume);
@@ -121,7 +123,11 @@ void WebRtcLocalAudioTrack::SetAudioProcessor(
}
void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ // This method is called from webrtc, on the signaling thread, when the local
+ // description is set and from the main thread from WebMediaPlayerMS::load
+ // (via WebRtcLocalAudioRenderer::Start).
+ DCHECK(main_render_thread_checker_.CalledOnValidThread() ||
+ signal_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
base::AutoLock auto_lock(lock_);
@@ -135,17 +141,22 @@ void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
// we remember to call OnSetFormat() on the new sink.
scoped_refptr<MediaStreamAudioTrackSink> sink_owner(
new MediaStreamAudioSinkOwner(sink));
- sinks_.AddAndTag(sink_owner);
+ sinks_.AddAndTag(sink_owner.get());
}
void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ // See AddSink for additional context. When local audio is stopped from
+ // webrtc, we'll be called here on the signaling thread.
+ DCHECK(main_render_thread_checker_.CalledOnValidThread() ||
+ signal_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::RemoveSink()";
- base::AutoLock auto_lock(lock_);
-
- scoped_refptr<MediaStreamAudioTrackSink> removed_item = sinks_.Remove(
- MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink));
+ scoped_refptr<MediaStreamAudioTrackSink> removed_item;
+ {
+ base::AutoLock auto_lock(lock_);
+ removed_item = sinks_.Remove(
+ MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink));
+ }
// Clear the delegate to ensure that no more capture callbacks will
// be sent to this sink. Also avoids a possible crash which can happen
@@ -169,7 +180,7 @@ void WebRtcLocalAudioTrack::AddSink(PeerConnectionAudioSink* sink) {
// we remember to call OnSetFormat() on the new sink.
scoped_refptr<MediaStreamAudioTrackSink> sink_owner(
new PeerConnectionAudioSinkOwner(sink));
- sinks_.AddAndTag(sink_owner);
+ sinks_.AddAndTag(sink_owner.get());
}
void WebRtcLocalAudioTrack::RemoveSink(PeerConnectionAudioSink* sink) {
@@ -211,6 +222,12 @@ void WebRtcLocalAudioTrack::Start() {
}
}
+void WebRtcLocalAudioTrack::SetEnabled(bool enabled) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (adapter_.get())
+ adapter_->set_enabled(enabled);
+}
+
void WebRtcLocalAudioTrack::Stop() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
@@ -248,4 +265,9 @@ void WebRtcLocalAudioTrack::Stop() {
}
}
+webrtc::AudioTrackInterface* WebRtcLocalAudioTrack::GetAudioAdapter() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return adapter_.get();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.h b/chromium/content/renderer/media/webrtc_local_audio_track.h
index c2cb81b3703..fa8b05995bb 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_track.h
@@ -60,9 +60,15 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
// should be called only once when audio track is created.
void Start();
+ // Overrides for MediaStreamTrack.
+
+ void SetEnabled(bool enabled) override;
+
// Stops the local audio track. Called on the main render thread and
// should be called only once when audio track going away.
- virtual void Stop() OVERRIDE;
+ void Stop() override;
+
+ webrtc::AudioTrackInterface* GetAudioAdapter() override;
// Method called by the capturer to deliver the capture data.
// Called on the capture audio thread.
@@ -70,7 +76,8 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
base::TimeDelta delay,
int volume,
bool key_pressed,
- bool need_audio_processing);
+ bool need_audio_processing,
+ bool force_report_nonzero_energy);
// Method called by the capturer to set the audio parameters used by source
// of the capture data..
@@ -87,8 +94,8 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
typedef TaggedList<MediaStreamAudioTrackSink> SinkList;
// All usage of libjingle is through this adapter. The adapter holds
- // a reference on this object, but not vice versa.
- WebRtcLocalAudioTrackAdapter* adapter_;
+ // a pointer to this object, but no reference.
+ const scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_;
// The provider of captured data to render.
scoped_refptr<WebRtcAudioCapturer> capturer_;
@@ -104,6 +111,8 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
// Used to DCHECK that some methods are called on the main render thread.
base::ThreadChecker main_render_thread_checker_;
+ // Tests that methods are called on libjingle's signaling thread.
+ base::ThreadChecker signal_thread_checker_;
// Used to DCHECK that some methods are called on the capture audio thread.
base::ThreadChecker capture_thread_checker_;
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
index 3f542fb6e8b..35ab61eb4aa 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
@@ -16,6 +16,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+#include "third_party/WebKit/public/web/WebHeap.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
using ::testing::_;
@@ -44,10 +45,10 @@ class FakeAudioThread : public base::PlatformThread::Delegate {
audio_bus_ = media::AudioBus::Create(params);
}
- virtual ~FakeAudioThread() { DCHECK(thread_.is_null()); }
+ ~FakeAudioThread() override { DCHECK(thread_.is_null()); }
// base::PlatformThread::Delegate:
- virtual void ThreadMain() OVERRIDE {
+ void ThreadMain() override {
while (true) {
if (closure_.IsSignaled())
return;
@@ -97,17 +98,17 @@ class MockCapturerSource : public media::AudioCapturerSource {
virtual void Initialize(const media::AudioParameters& params,
CaptureCallback* callback,
- int session_id) OVERRIDE {
+ int session_id) override {
DCHECK(params.IsValid());
params_ = params;
OnInitialize(params, callback, session_id);
}
- virtual void Start() OVERRIDE {
+ virtual void Start() override {
audio_thread_.reset(new FakeAudioThread(capturer_, params_));
audio_thread_->Start();
OnStart();
}
- virtual void Stop() OVERRIDE {
+ virtual void Stop() override {
audio_thread_->Stop();
audio_thread_.reset();
OnStop();
@@ -134,7 +135,7 @@ class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
int audio_delay_milliseconds,
int current_volume,
bool need_audio_processing,
- bool key_pressed) OVERRIDE {
+ bool key_pressed) override {
EXPECT_EQ(params_.sample_rate(), sample_rate);
EXPECT_EQ(params_.channels(), number_of_channels);
EXPECT_EQ(params_.frames_per_buffer(), number_of_frames);
@@ -167,9 +168,9 @@ class MockMediaStreamAudioSink : public PeerConnectionAudioSink {
class WebRtcLocalAudioTrackTest : public ::testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 2, 0, 48000, 16, 480);
+ media::CHANNEL_LAYOUT_STEREO, 2, 48000, 16, 480);
MockMediaConstraintFactory constraint_factory;
blink_source_.initialize("dummy", blink::WebMediaStreamSource::TypeAudio,
"dummy");
@@ -181,7 +182,7 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
capturer_ = WebRtcAudioCapturer::CreateCapturer(
-1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
audio_source);
- audio_source->SetAudioCapturer(capturer_);
+ audio_source->SetAudioCapturer(capturer_.get());
capturer_source_ = new MockCapturerSource(capturer_.get());
EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_.get(), -1))
.WillOnce(Return());
@@ -190,6 +191,11 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
capturer_->SetCapturerSourceForTesting(capturer_source_, params_);
}
+ void TearDown() override {
+ blink_source_.reset();
+ blink::WebHeap::collectAllGarbageForTesting();
+ }
+
media::AudioParameters params_;
blink::WebMediaStreamSource blink_source_;
scoped_refptr<MockCapturerSource> capturer_source_;
@@ -204,7 +210,7 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
track->Start();
EXPECT_TRUE(track->GetAudioAdapter()->enabled());
@@ -238,7 +244,7 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
track->Start();
EXPECT_TRUE(track->GetAudioAdapter()->enabled());
EXPECT_TRUE(track->GetAudioAdapter()->set_enabled(false));
@@ -272,7 +278,7 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track_1(
- new WebRtcLocalAudioTrack(adapter_1, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
track_1->Start();
EXPECT_TRUE(track_1->GetAudioAdapter()->enabled());
scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
@@ -290,7 +296,7 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track_2(
- new WebRtcLocalAudioTrack(adapter_2, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
track_2->Start();
EXPECT_TRUE(track_2->GetAudioAdapter()->enabled());
@@ -329,7 +335,7 @@ TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
track->Start();
// When the track goes away, it will automatically stop the
@@ -345,13 +351,13 @@ TEST_F(WebRtcLocalAudioTrackTest, StartTwoAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track1(
- new WebRtcLocalAudioTrack(adapter1, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter1.get(), capturer_, NULL));
track1->Start();
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track2(
- new WebRtcLocalAudioTrack(adapter2, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter2.get(), capturer_, NULL));
track2->Start();
track1->Stop();
@@ -368,7 +374,7 @@ TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track_1(
- new WebRtcLocalAudioTrack(adapter_1, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
track_1->Start();
// Verify the data flow by connecting the sink to |track_1|.
@@ -386,7 +392,7 @@ TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track_2(
- new WebRtcLocalAudioTrack(adapter_2, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
track_2->Start();
// Stop the capturer will clear up the track lists in the capturer.
@@ -404,13 +410,21 @@ TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
capturer_->Stop();
}
+// Contains data races reported by tsan: crbug.com/404133
+#if defined(THREAD_SANITIZER)
+ #define DISABLE_ON_TSAN(function) DISABLED_##function
+#else
+ #define DISABLE_ON_TSAN(function) function
+#endif
+
// Create a new capturer with new source, connect it to a new audio track.
-TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) {
+TEST_F(WebRtcLocalAudioTrackTest,
+ DISABLE_ON_TSAN(ConnectTracksToDifferentCapturers)) {
// Setup the first audio track and start it.
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track_1(
- new WebRtcLocalAudioTrack(adapter_1, capturer_, NULL));
+ new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
track_1->Start();
// Verify the data flow by connecting the |sink_1| to |track_1|.
@@ -443,7 +457,7 @@ TEST_F(WebRtcLocalAudioTrackTest, ConnectTracksToDifferentCapturers) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track_2(
- new WebRtcLocalAudioTrack(adapter_2, new_capturer, NULL));
+ new WebRtcLocalAudioTrack(adapter_2.get(), new_capturer, NULL));
track_2->Start();
// Verify the data flow by connecting the |sink_2| to |track_2|.
@@ -497,7 +511,7 @@ TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter, capturer, NULL));
+ new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
track->Start();
// Verify the data flow by connecting the |sink| to |track|.
@@ -518,7 +532,7 @@ TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
EXPECT_EQ(expected_buffer_size, sink->audio_params().frames_per_buffer());
// Stopping the new source will stop the second track.
- EXPECT_CALL(*source, OnStop()).Times(1);
+ EXPECT_CALL(*source.get(), OnStop()).Times(1);
capturer->Stop();
// Even though this test don't use |capturer_source_| it will be stopped
diff --git a/chromium/content/renderer/media/webrtc_logging.cc b/chromium/content/renderer/media/webrtc_logging.cc
index 96868a6836c..17e5c574542 100644
--- a/chromium/content/renderer/media/webrtc_logging.cc
+++ b/chromium/content/renderer/media/webrtc_logging.cc
@@ -6,7 +6,7 @@
#include "base/time/time.h"
#include "content/public/renderer/webrtc_log_message_delegate.h"
-#include "third_party/libjingle/overrides/talk/base/logging.h"
+#include "third_party/webrtc/overrides/webrtc/base/logging.h"
namespace content {
@@ -22,7 +22,7 @@ void InitWebRtcLoggingDelegate(WebRtcLogMessageDelegate* delegate) {
void InitWebRtcLogging() {
// Log messages from Libjingle should not have timestamps.
- talk_base::InitDiagnosticLoggingDelegateFunction(&WebRtcLogMessage);
+ rtc::InitDiagnosticLoggingDelegateFunction(&WebRtcLogMessage);
}
void WebRtcLogMessage(const std::string& message) {
diff --git a/chromium/content/renderer/media/webrtc_uma_histograms.cc b/chromium/content/renderer/media/webrtc_uma_histograms.cc
index 16da393073e..3e804e1d0b8 100644
--- a/chromium/content/renderer/media/webrtc_uma_histograms.cc
+++ b/chromium/content/renderer/media/webrtc_uma_histograms.cc
@@ -8,6 +8,17 @@
namespace content {
+void LogUserMediaRequestWithNoResult(MediaStreamRequestState state) {
+ UMA_HISTOGRAM_ENUMERATION("WebRTC.UserMediaRequest.NoResultState",
+ state,
+ NUM_MEDIA_STREAM_REQUEST_WITH_NO_RESULT);
+}
+
+void LogUserMediaRequestResult(MediaStreamRequestResult result) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "WebRTC.UserMediaRequest.Result", result, NUM_MEDIA_REQUEST_RESULTS);
+}
+
void UpdateWebRTCMethodCount(JavaScriptAPIName api_name) {
DVLOG(3) << "Incrementing WebRTC.webkitApiCount for " << api_name;
UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCount", api_name, INVALID_NAME);
diff --git a/chromium/content/renderer/media/webrtc_uma_histograms.h b/chromium/content/renderer/media/webrtc_uma_histograms.h
index 2dfb032db1b..2ab6f6d6536 100644
--- a/chromium/content/renderer/media/webrtc_uma_histograms.h
+++ b/chromium/content/renderer/media/webrtc_uma_histograms.h
@@ -8,9 +8,27 @@
#include "base/memory/singleton.h"
#include "base/threading/non_thread_safe.h"
#include "content/common/content_export.h"
+#include "content/public/common/media_stream_request.h"
namespace content {
+// Used to investigate where UserMediaRequests end up.
+// Only UserMediaRequests that do not log with LogUserMediaRequestResult
+// should call LogUserMediaRequestWithNoResult.
+//
+// Elements in this enum should not be deleted or rearranged; the only
+// permitted operation is to add new elements before
+// NUM_MEDIA_STREAM_REQUEST_WITH_NO_RESULT.
+enum MediaStreamRequestState {
+ MEDIA_STREAM_REQUEST_EXPLICITLY_CANCELLED = 0,
+ MEDIA_STREAM_REQUEST_NOT_GENERATED = 1,
+ MEDIA_STREAM_REQUEST_PENDING_MEDIA_TRACKS = 2,
+ NUM_MEDIA_STREAM_REQUEST_WITH_NO_RESULT
+};
+
+void LogUserMediaRequestWithNoResult(MediaStreamRequestState state);
+void LogUserMediaRequestResult(MediaStreamRequestResult result);
+
// Helper enum used for histogramming calls to WebRTC APIs from JavaScript.
enum JavaScriptAPIName {
WEBKIT_GET_USER_MEDIA,
diff --git a/chromium/content/renderer/media/websourcebuffer_impl.cc b/chromium/content/renderer/media/websourcebuffer_impl.cc
deleted file mode 100644
index 1b8e4fa1435..00000000000
--- a/chromium/content/renderer/media/websourcebuffer_impl.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2013 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 "content/renderer/media/websourcebuffer_impl.h"
-
-#include <limits>
-
-#include "base/float_util.h"
-#include "media/filters/chunk_demuxer.h"
-
-namespace content {
-
-static base::TimeDelta DoubleToTimeDelta(double time) {
- DCHECK(!base::IsNaN(time));
- DCHECK_NE(time, -std::numeric_limits<double>::infinity());
-
- if (time == std::numeric_limits<double>::infinity())
- return media::kInfiniteDuration();
-
- // Don't use base::TimeDelta::Max() here, as we want the largest finite time
- // delta.
- base::TimeDelta max_time = base::TimeDelta::FromInternalValue(kint64max - 1);
- double max_time_in_seconds = max_time.InSecondsF();
-
- if (time >= max_time_in_seconds)
- return max_time;
-
- return base::TimeDelta::FromMicroseconds(
- time * base::Time::kMicrosecondsPerSecond);
-}
-
-WebSourceBufferImpl::WebSourceBufferImpl(
- const std::string& id, media::ChunkDemuxer* demuxer)
- : id_(id),
- demuxer_(demuxer),
- append_window_end_(media::kInfiniteDuration()) {
- DCHECK(demuxer_);
-}
-
-WebSourceBufferImpl::~WebSourceBufferImpl() {
- DCHECK(!demuxer_) << "Object destroyed w/o removedFromMediaSource() call";
-}
-
-bool WebSourceBufferImpl::setMode(WebSourceBuffer::AppendMode mode) {
- if (demuxer_->IsParsingMediaSegment(id_))
- return false;
-
- switch (mode) {
- case WebSourceBuffer::AppendModeSegments:
- demuxer_->SetSequenceMode(id_, false);
- return true;
- case WebSourceBuffer::AppendModeSequence:
- demuxer_->SetSequenceMode(id_, true);
- return true;
- }
-
- NOTREACHED();
- return false;
-}
-
-blink::WebTimeRanges WebSourceBufferImpl::buffered() {
- media::Ranges<base::TimeDelta> ranges = demuxer_->GetBufferedRanges(id_);
- blink::WebTimeRanges result(ranges.size());
- for (size_t i = 0; i < ranges.size(); i++) {
- result[i].start = ranges.start(i).InSecondsF();
- result[i].end = ranges.end(i).InSecondsF();
- }
- return result;
-}
-
-void WebSourceBufferImpl::append(
- const unsigned char* data,
- unsigned length,
- double* timestamp_offset) {
- base::TimeDelta old_offset = timestamp_offset_;
- demuxer_->AppendData(id_, data, length,
- append_window_start_, append_window_end_,
- &timestamp_offset_);
-
- // Coded frame processing may update the timestamp offset. If the caller
- // provides a non-NULL |timestamp_offset| and frame processing changes the
- // timestamp offset, report the new offset to the caller. Do not update the
- // caller's offset otherwise, to preserve any pre-existing value that may have
- // more than microsecond precision.
- if (timestamp_offset && old_offset != timestamp_offset_)
- *timestamp_offset = timestamp_offset_.InSecondsF();
-}
-
-void WebSourceBufferImpl::abort() {
- demuxer_->Abort(id_,
- append_window_start_, append_window_end_,
- &timestamp_offset_);
-
- // TODO(wolenetz): abort should be able to modify the caller timestamp offset
- // (just like WebSourceBufferImpl::append).
- // See http://crbug.com/370229 for further details.
-}
-
-void WebSourceBufferImpl::remove(double start, double end) {
- DCHECK_GE(start, 0);
- DCHECK_GE(end, 0);
- demuxer_->Remove(id_, DoubleToTimeDelta(start), DoubleToTimeDelta(end));
-}
-
-bool WebSourceBufferImpl::setTimestampOffset(double offset) {
- if (demuxer_->IsParsingMediaSegment(id_))
- return false;
-
- timestamp_offset_ = DoubleToTimeDelta(offset);
-
- // http://www.w3.org/TR/media-source/#widl-SourceBuffer-timestampOffset
- // Step 6: If the mode attribute equals "sequence", then set the group start
- // timestamp to new timestamp offset.
- demuxer_->SetGroupStartTimestampIfInSequenceMode(id_, timestamp_offset_);
- return true;
-}
-
-void WebSourceBufferImpl::setAppendWindowStart(double start) {
- DCHECK_GE(start, 0);
- append_window_start_ = DoubleToTimeDelta(start);
-}
-
-void WebSourceBufferImpl::setAppendWindowEnd(double end) {
- DCHECK_GE(end, 0);
- append_window_end_ = DoubleToTimeDelta(end);
-}
-
-void WebSourceBufferImpl::removedFromMediaSource() {
- demuxer_->RemoveId(id_);
- demuxer_ = NULL;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/websourcebuffer_impl.h b/chromium/content/renderer/media/websourcebuffer_impl.h
deleted file mode 100644
index b0e4fa686ae..00000000000
--- a/chromium/content/renderer/media/websourcebuffer_impl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2013 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 CONTENT_RENDERER_MEDIA_WEBSOURCEBUFFER_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_WEBSOURCEBUFFER_IMPL_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/time/time.h"
-#include "third_party/WebKit/public/platform/WebSourceBuffer.h"
-
-namespace media {
-class ChunkDemuxer;
-}
-
-namespace content {
-
-class WebSourceBufferImpl : public blink::WebSourceBuffer {
- public:
- WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer);
- virtual ~WebSourceBufferImpl();
-
- // blink::WebSourceBuffer implementation.
- virtual bool setMode(AppendMode mode);
- virtual blink::WebTimeRanges buffered();
- virtual void append(
- const unsigned char* data,
- unsigned length,
- double* timestamp_offset);
- virtual void abort();
- virtual void remove(double start, double end);
- virtual bool setTimestampOffset(double offset);
- virtual void setAppendWindowStart(double start);
- virtual void setAppendWindowEnd(double end);
- virtual void removedFromMediaSource();
-
- private:
- std::string id_;
- media::ChunkDemuxer* demuxer_; // Owned by WebMediaPlayerImpl.
-
- // Controls the offset applied to timestamps when processing appended media
- // segments. It is initially 0, which indicates that no offset is being
- // applied. Both setTimestampOffset() and append() may update this value.
- base::TimeDelta timestamp_offset_;
-
- base::TimeDelta append_window_start_;
- base::TimeDelta append_window_end_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSourceBufferImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBSOURCEBUFFER_IMPL_H_
diff --git a/chromium/content/renderer/memory_benchmarking_extension.cc b/chromium/content/renderer/memory_benchmarking_extension.cc
index f6b9c7df375..0f5320daa06 100644
--- a/chromium/content/renderer/memory_benchmarking_extension.cc
+++ b/chromium/content/renderer/memory_benchmarking_extension.cc
@@ -5,6 +5,7 @@
#include "content/renderer/memory_benchmarking_extension.h"
#include "content/common/memory_benchmark_messages.h"
+#include "content/renderer/chrome_object_extensions_utils.h"
#include "content/renderer/render_thread_impl.h"
#include "gin/arguments.h"
#include "gin/handle.h"
@@ -35,13 +36,8 @@ void MemoryBenchmarkingExtension::Install(blink::WebFrame* frame) {
if (controller.IsEmpty())
return;
- v8::Handle<v8::Object> global = context->Global();
- v8::Handle<v8::Object> chrome =
- global->Get(gin::StringToV8(isolate, "chrome"))->ToObject();
- if (chrome.IsEmpty()) {
- chrome = v8::Object::New(isolate);
- global->Set(gin::StringToV8(isolate, "chrome"), chrome);
- }
+ v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
+ context->Global());
chrome->Set(gin::StringToV8(isolate, "memoryBenchmarking"),
controller.ToV8());
}
diff --git a/chromium/content/renderer/memory_benchmarking_extension.h b/chromium/content/renderer/memory_benchmarking_extension.h
index 27439e818cf..afbaf24b868 100644
--- a/chromium/content/renderer/memory_benchmarking_extension.h
+++ b/chromium/content/renderer/memory_benchmarking_extension.h
@@ -27,11 +27,11 @@ class MemoryBenchmarkingExtension
private:
MemoryBenchmarkingExtension();
- virtual ~MemoryBenchmarkingExtension();
+ ~MemoryBenchmarkingExtension() override;
// gin::Wrappable.
- virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) OVERRIDE;
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
bool IsHeapProfilerRunning();
diff --git a/chromium/content/renderer/message_delivery_policy.h b/chromium/content/renderer/message_delivery_policy.h
new file mode 100644
index 00000000000..4ad9b2f1a11
--- /dev/null
+++ b/chromium/content/renderer/message_delivery_policy.h
@@ -0,0 +1,25 @@
+// Copyright 2014 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 CONTENT_RENDERER_MESSAGE_DELIVERY_POLICY_H_
+#define CONTENT_RENDERER_MESSAGE_DELIVERY_POLICY_H_
+
+namespace content {
+
+enum MessageDeliveryPolicy {
+ // If a commit was requested before the message was enqueued the message
+ // will be delivered with the swap corresponding to that commit. Otherwise
+ // the message will be sent immediately using regular IPC.
+ // If the commit is aborted or optimized out the message is sent using regular
+ // IPC.
+ MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE,
+ // The message will be delivered with the next swap.
+ // If the swap is optimized out, the message is sent using regular IPC.
+ // If the swap fails the message remains enqueued.
+ MESSAGE_DELIVERY_POLICY_WITH_NEXT_SWAP,
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MESSAGE_DELIVERY_POLICY_H_
diff --git a/chromium/content/renderer/mhtml_generator.h b/chromium/content/renderer/mhtml_generator.h
index 8f162eafb0e..8a65b46afb4 100644
--- a/chromium/content/renderer/mhtml_generator.h
+++ b/chromium/content/renderer/mhtml_generator.h
@@ -15,11 +15,11 @@ class RenderViewImpl;
class MHTMLGenerator : public RenderViewObserver {
public:
explicit MHTMLGenerator(RenderViewImpl* render_view);
- virtual ~MHTMLGenerator();
+ ~MHTMLGenerator() override;
private:
// RenderViewObserver implementation:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnSavePageAsMHTML(int job_id,
IPC::PlatformFileForTransit file_for_transit);
diff --git a/chromium/content/renderer/mojo/service_registry_js_wrapper.cc b/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
new file mode 100644
index 00000000000..73a591e3906
--- /dev/null
+++ b/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 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 "content/renderer/mojo/service_registry_js_wrapper.h"
+
+#include "content/common/mojo/service_registry_impl.h"
+#include "content/public/common/service_registry.h"
+#include "mojo/edk/js/handle.h"
+
+namespace content {
+
+gin::WrapperInfo ServiceRegistryJsWrapper::kWrapperInfo = {
+ gin::kEmbedderNativeGin};
+const char ServiceRegistryJsWrapper::kModuleName[] =
+ "content/public/renderer/service_provider";
+
+ServiceRegistryJsWrapper::~ServiceRegistryJsWrapper() {
+}
+
+// static
+gin::Handle<ServiceRegistryJsWrapper> ServiceRegistryJsWrapper::Create(
+ v8::Isolate* isolate,
+ ServiceRegistry* service_registry) {
+ return gin::CreateHandle(
+ isolate,
+ new ServiceRegistryJsWrapper(
+ static_cast<ServiceRegistryImpl*>(service_registry)->GetWeakPtr()));
+}
+
+gin::ObjectTemplateBuilder ServiceRegistryJsWrapper::GetObjectTemplateBuilder(
+ v8::Isolate* isolate) {
+ return Wrappable<ServiceRegistryJsWrapper>::GetObjectTemplateBuilder(isolate).
+ SetMethod("connectToService",
+ &ServiceRegistryJsWrapper::ConnectToService);
+}
+
+mojo::Handle ServiceRegistryJsWrapper::ConnectToService(
+ const std::string& service_name) {
+ mojo::MessagePipe pipe;
+ if (service_registry_)
+ service_registry_->ConnectToRemoteService(service_name,
+ pipe.handle0.Pass());
+ return pipe.handle1.release();
+}
+
+ServiceRegistryJsWrapper::ServiceRegistryJsWrapper(
+ base::WeakPtr<ServiceRegistry> service_registry)
+ : service_registry_(service_registry) {
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/mojo/service_registry_js_wrapper.h b/chromium/content/renderer/mojo/service_registry_js_wrapper.h
new file mode 100644
index 00000000000..2be7f9557b8
--- /dev/null
+++ b/chromium/content/renderer/mojo/service_registry_js_wrapper.h
@@ -0,0 +1,51 @@
+// Copyright 2014 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 CONTENT_RENDERER_MOJO_SERVICE_REGISTRY_JS_WRAPPER_H_
+#define CONTENT_RENDERER_MOJO_SERVICE_REGISTRY_JS_WRAPPER_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/wrappable.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace content {
+
+class ServiceRegistry;
+
+// A JS wrapper around ServiceRegistry that allows connecting to remote
+// services.
+class CONTENT_EXPORT ServiceRegistryJsWrapper
+ : public gin::Wrappable<ServiceRegistryJsWrapper> {
+ public:
+ ~ServiceRegistryJsWrapper() override;
+ static gin::Handle<ServiceRegistryJsWrapper> Create(
+ v8::Isolate* isolate,
+ ServiceRegistry* service_registry);
+
+ // gin::Wrappable<ServiceRegistryJsWrapper> overrides.
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
+
+ // JS interface implementation.
+ mojo::Handle ConnectToService(const std::string& service_name);
+
+ static gin::WrapperInfo kWrapperInfo;
+ static const char kModuleName[];
+
+ private:
+ explicit ServiceRegistryJsWrapper(
+ base::WeakPtr<ServiceRegistry> service_registry);
+
+ base::WeakPtr<ServiceRegistry> service_registry_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceRegistryJsWrapper);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MOJO_SERVICE_REGISTRY_JS_WRAPPER_H_
diff --git a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
index ef18331d530..2a0fd6b4778 100644
--- a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
+++ b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc
@@ -28,14 +28,14 @@ class MockLockTarget : public MouseLockDispatcher::LockTarget {
// fixture containing a RenderViewImpl view() and interacting to that interface.
class MouseLockDispatcherTest : public RenderViewTest {
public:
- virtual void SetUp() {
+ void SetUp() override {
RenderViewTest::SetUp();
route_id_ = view()->GetRoutingID();
target_ = new MockLockTarget();
alternate_target_ = new MockLockTarget();
}
- virtual void TearDown() {
+ void TearDown() override {
RenderViewTest::TearDown();
delete target_;
delete alternate_target_;
diff --git a/chromium/content/renderer/net_info_helper.cc b/chromium/content/renderer/net_info_helper.cc
index a833368ba7a..84b9d24a280 100644
--- a/chromium/content/renderer/net_info_helper.cc
+++ b/chromium/content/renderer/net_info_helper.cc
@@ -11,7 +11,7 @@ NetConnectionTypeToWebConnectionType(
net::NetworkChangeNotifier::ConnectionType net_type) {
switch (net_type) {
case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
- return blink::ConnectionTypeOther;
+ return blink::ConnectionTypeUnknown;
case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
return blink::ConnectionTypeEthernet;
case net::NetworkChangeNotifier::CONNECTION_WIFI:
diff --git a/chromium/content/renderer/notification_icon_loader.cc b/chromium/content/renderer/notification_icon_loader.cc
new file mode 100644
index 00000000000..d535837dbf9
--- /dev/null
+++ b/chromium/content/renderer/notification_icon_loader.cc
@@ -0,0 +1,83 @@
+// Copyright 2014 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 "content/renderer/notification_icon_loader.h"
+
+#include "base/logging.h"
+#include "content/child/image_decoder.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebURLLoader.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+using blink::WebURL;
+using blink::WebURLError;
+using blink::WebURLLoader;
+using blink::WebURLRequest;
+
+namespace content {
+
+NotificationIconLoader::NotificationIconLoader(
+ int notification_id,
+ const DownloadCompletedCallback& callback)
+ : notification_id_(notification_id),
+ callback_(callback),
+ completed_(false) {}
+
+NotificationIconLoader::~NotificationIconLoader() {}
+
+void NotificationIconLoader::Start(const WebURL& icon_url) {
+ DCHECK(!loader_);
+
+ WebURLRequest request(icon_url);
+ request.setRequestContext(WebURLRequest::RequestContextImage);
+
+ loader_.reset(blink::Platform::current()->createURLLoader());
+ loader_->loadAsynchronously(request, this);
+}
+
+void NotificationIconLoader::Cancel() {
+ DCHECK(loader_);
+
+ completed_ = true;
+ loader_->cancel();
+}
+
+void NotificationIconLoader::didReceiveData(
+ WebURLLoader* loader,
+ const char* data,
+ int data_length,
+ int encoded_data_length) {
+ DCHECK(!completed_);
+ DCHECK_GT(data_length, 0);
+
+ buffer_.insert(buffer_.end(), data, data + data_length);
+}
+
+void NotificationIconLoader::didFinishLoading(
+ WebURLLoader* loader,
+ double finish_time,
+ int64_t total_encoded_data_length) {
+ DCHECK(!completed_);
+
+ SkBitmap icon;
+ if (!buffer_.empty()) {
+ ImageDecoder decoder;
+ icon = decoder.Decode(&buffer_[0], buffer_.size());
+ }
+
+ completed_ = true;
+ callback_.Run(notification_id_, icon);
+}
+
+void NotificationIconLoader::didFail(
+ WebURLLoader* loader, const WebURLError& error) {
+ if (completed_)
+ return;
+
+ completed_ = true;
+ callback_.Run(notification_id_, SkBitmap());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/notification_icon_loader.h b/chromium/content/renderer/notification_icon_loader.h
new file mode 100644
index 00000000000..5bb95f80479
--- /dev/null
+++ b/chromium/content/renderer/notification_icon_loader.h
@@ -0,0 +1,73 @@
+// Copyright 2014 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 CONTENT_RENDERER_NOTIFICATION_ICON_LOADER_H_
+#define CONTENT_RENDERER_NOTIFICATION_ICON_LOADER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
+
+class SkBitmap;
+
+namespace blink {
+class WebURL;
+struct WebURLError;
+class WebURLLoader;
+}
+
+namespace content {
+
+// Downloads the icon associated with a notification and decodes the received
+// image. This must be completed before notifications are shown to the user.
+// Icon downloaders must not be re-used for multiple notifications or icons.
+class NotificationIconLoader : public blink::WebURLLoaderClient {
+ typedef base::Callback<void(int, const SkBitmap&)> DownloadCompletedCallback;
+
+ public:
+ NotificationIconLoader(int notification_id,
+ const DownloadCompletedCallback& callback);
+
+ virtual ~NotificationIconLoader();
+
+ // Downloads the notification's image and invokes the callback with the
+ // decoded SkBitmap when the download has succeeded, or with an empty SkBitmap
+ // in case the download has failed.
+ void Start(const blink::WebURL& icon_url);
+
+ // Cancels the current image download. The callback will not be invoked.
+ void Cancel();
+
+ // blink::WebURLLoaderClient implementation.
+ virtual void didReceiveData(blink::WebURLLoader* loader,
+ const char* data,
+ int data_length,
+ int encoded_data_length);
+ virtual void didFinishLoading(blink::WebURLLoader* loader,
+ double finish_time,
+ int64_t total_encoded_data_length);
+ virtual void didFail(blink::WebURLLoader* loader,
+ const blink::WebURLError& error);
+
+ int notification_id() const {
+ return notification_id_;
+ }
+
+ private:
+ int notification_id_;
+ DownloadCompletedCallback callback_;
+
+ scoped_ptr<blink::WebURLLoader> loader_;
+ bool completed_;
+
+ std::vector<uint8_t> buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationIconLoader);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_NOTIFICATION_ICON_LOADER_H_
diff --git a/chromium/content/renderer/notification_permission_dispatcher.cc b/chromium/content/renderer/notification_permission_dispatcher.cc
new file mode 100644
index 00000000000..92d5529122b
--- /dev/null
+++ b/chromium/content/renderer/notification_permission_dispatcher.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 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 "content/renderer/notification_permission_dispatcher.h"
+
+#include "content/common/platform_notification_messages.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
+#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
+#include "url/gurl.h"
+
+namespace content {
+
+NotificationPermissionDispatcher::NotificationPermissionDispatcher(
+ RenderFrame* render_frame) : RenderFrameObserver(render_frame) {
+}
+
+NotificationPermissionDispatcher::~NotificationPermissionDispatcher() {
+}
+
+void NotificationPermissionDispatcher::RequestPermission(
+ const blink::WebSecurityOrigin& origin,
+ blink::WebNotificationPermissionCallback* callback) {
+ int request_id = pending_requests_.Add(callback);
+ Send(new PlatformNotificationHostMsg_RequestPermission(
+ routing_id(), GURL(origin.toString()), request_id));
+}
+
+bool NotificationPermissionDispatcher::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(NotificationPermissionDispatcher, message)
+ IPC_MESSAGE_HANDLER(PlatformNotificationMsg_PermissionRequestComplete,
+ OnPermissionRequestComplete);
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void NotificationPermissionDispatcher::OnPermissionRequestComplete(
+ int request_id, blink::WebNotificationPermission result) {
+ blink::WebNotificationPermissionCallback* callback =
+ pending_requests_.Lookup(request_id);
+ DCHECK(callback);
+
+ callback->permissionRequestComplete(result);
+ pending_requests_.Remove(request_id);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/notification_permission_dispatcher.h b/chromium/content/renderer/notification_permission_dispatcher.h
new file mode 100644
index 00000000000..c01b0632784
--- /dev/null
+++ b/chromium/content/renderer/notification_permission_dispatcher.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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 CONTENT_RENDERER_NOTIFICATION_PERMISSION_DISPATCHER_H_
+#define CONTENT_RENDERER_NOTIFICATION_PERMISSION_DISPATCHER_H_
+
+#include "base/id_map.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/public/platform/WebNotificationPermission.h"
+
+namespace blink {
+class WebNotificationPermissionCallback;
+class WebSecurityOrigin;
+}
+
+namespace content {
+
+// Dispatcher for Web Notification permission requests.
+class NotificationPermissionDispatcher : public RenderFrameObserver {
+ public:
+ explicit NotificationPermissionDispatcher(RenderFrame* render_frame);
+ ~NotificationPermissionDispatcher() override;
+
+ // Requests permission to display Web Notifications for |origin|. The callback
+ // will be invoked when the permission status is available. This class will
+ // take ownership of |callback|.
+ void RequestPermission(
+ const blink::WebSecurityOrigin& origin,
+ blink::WebNotificationPermissionCallback* callback);
+
+ private:
+ // RenderFrameObserver implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnPermissionRequestComplete(
+ int request_id, blink::WebNotificationPermission result);
+
+ // Tracks the active notification permission requests. This class takes
+ // ownership of the created WebNotificationPermissionCallback objects.
+ IDMap<blink::WebNotificationPermissionCallback, IDMapOwnPointer>
+ pending_requests_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotificationPermissionDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_NOTIFICATION_PERMISSION_DISPATCHER_H_
diff --git a/chromium/content/renderer/notification_provider.cc b/chromium/content/renderer/notification_provider.cc
index 79325dcb7ad..b5e749386cc 100644
--- a/chromium/content/renderer/notification_provider.cc
+++ b/chromium/content/renderer/notification_provider.cc
@@ -4,55 +4,92 @@
#include "content/renderer/notification_provider.h"
+#include <vector>
+
#include "base/strings/string_util.h"
#include "content/common/desktop_notification_messages.h"
#include "content/common/frame_messages.h"
+#include "content/renderer/notification_icon_loader.h"
#include "content/renderer/render_frame_impl.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebNotificationPermissionCallback.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
using blink::WebDocument;
using blink::WebNotification;
using blink::WebNotificationPresenter;
-using blink::WebNotificationPermissionCallback;
using blink::WebSecurityOrigin;
using blink::WebString;
-using blink::WebURL;
-using blink::WebUserGestureIndicator;
namespace content {
-
NotificationProvider::NotificationProvider(RenderFrame* render_frame)
- : RenderFrameObserver(render_frame) {
-}
+ : RenderFrameObserver(render_frame) {}
-NotificationProvider::~NotificationProvider() {
-}
+NotificationProvider::~NotificationProvider() {}
bool NotificationProvider::show(const WebNotification& notification) {
- WebDocument document = render_frame()->GetWebFrame()->document();
int notification_id = manager_.RegisterNotification(notification);
+ if (notification.iconURL().isEmpty()) {
+ DisplayNotification(notification_id, SkBitmap());
+ return true;
+ }
+
+ scoped_ptr<NotificationIconLoader> loader(
+ new NotificationIconLoader(
+ notification_id,
+ base::Bind(&NotificationProvider::DisplayNotification,
+ base::Unretained(this))));
+
+ loader->Start(notification.iconURL());
+
+ pending_notifications_.push_back(loader.release());
+ return true;
+}
+
+void NotificationProvider::DisplayNotification(int notification_id,
+ const SkBitmap& icon) {
+ WebDocument document = render_frame()->GetWebFrame()->document();
+ WebNotification notification;
+
+ if (!manager_.GetNotification(notification_id, &notification)) {
+ NOTREACHED();
+ return;
+ }
+
+ RemovePendingNotification(notification_id);
ShowDesktopNotificationHostMsgParams params;
params.origin = GURL(document.securityOrigin().toString());
- params.icon_url = notification.iconURL();
+ params.icon = icon;
params.title = notification.title();
params.body = notification.body();
params.direction = notification.direction();
params.replace_id = notification.replaceId();
- return Send(new DesktopNotificationHostMsg_Show(
- routing_id(), notification_id, params));
+
+ Send(new DesktopNotificationHostMsg_Show(routing_id(),
+ notification_id,
+ params));
+}
+
+bool NotificationProvider::RemovePendingNotification(int notification_id) {
+ PendingNotifications::iterator iter = pending_notifications_.begin();
+ for (; iter != pending_notifications_.end(); ++iter) {
+ if ((*iter)->notification_id() != notification_id)
+ continue;
+
+ pending_notifications_.erase(iter);
+ return true;
+ }
+
+ return false;
}
void NotificationProvider::cancel(const WebNotification& notification) {
int id;
bool id_found = manager_.GetId(notification, id);
- // Won't be found if the notification has already been closed by the user.
- if (id_found)
+ // Won't be found if the notification has already been closed by the user,
+ // or if the notification's icon is still being requested.
+ if (id_found && !RemovePendingNotification(id))
Send(new DesktopNotificationHostMsg_Cancel(routing_id(), id));
}
@@ -61,13 +98,15 @@ void NotificationProvider::objectDestroyed(
int id;
bool id_found = manager_.GetId(notification, id);
// Won't be found if the notification has already been closed by the user.
- if (id_found)
+ if (id_found) {
+ RemovePendingNotification(id);
manager_.UnregisterNotification(id);
+ }
}
WebNotificationPresenter::Permission NotificationProvider::checkPermission(
const WebSecurityOrigin& origin) {
- int permission;
+ int permission = WebNotificationPresenter::PermissionNotAllowed;
Send(new DesktopNotificationHostMsg_CheckPermission(
routing_id(),
GURL(origin.toString()),
@@ -75,24 +114,12 @@ WebNotificationPresenter::Permission NotificationProvider::checkPermission(
return static_cast<WebNotificationPresenter::Permission>(permission);
}
-void NotificationProvider::requestPermission(
- const WebSecurityOrigin& origin,
- WebNotificationPermissionCallback* callback) {
- int id = manager_.RegisterPermissionRequest(callback);
-
- Send(new DesktopNotificationHostMsg_RequestPermission(
- routing_id(), GURL(origin.toString()), id));
-}
-
bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostDisplay, OnDisplay);
- IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostError, OnError);
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClose, OnClose);
IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PostClick, OnClick);
- IPC_MESSAGE_HANDLER(DesktopNotificationMsg_PermissionRequestDone,
- OnPermissionRequestComplete);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -111,15 +138,6 @@ void NotificationProvider::OnDisplay(int id) {
notification.dispatchDisplayEvent();
}
-void NotificationProvider::OnError(int id) {
- WebNotification notification;
- bool found = manager_.GetNotification(id, &notification);
- // |found| may be false if the WebNotification went out of scope in
- // the page before the error occurred.
- if (found)
- notification.dispatchErrorEvent(WebString());
-}
-
void NotificationProvider::OnClose(int id, bool by_user) {
WebNotification notification;
bool found = manager_.GetNotification(id, &notification);
@@ -140,13 +158,6 @@ void NotificationProvider::OnClick(int id) {
notification.dispatchClickEvent();
}
-void NotificationProvider::OnPermissionRequestComplete(int id) {
- WebNotificationPermissionCallback* callback = manager_.GetCallback(id);
- DCHECK(callback);
- callback->permissionRequestComplete();
- manager_.OnPermissionRequestComplete(id);
-}
-
void NotificationProvider::OnNavigate() {
manager_.Clear();
}
diff --git a/chromium/content/renderer/notification_provider.h b/chromium/content/renderer/notification_provider.h
index 5162c14426e..7428e2f5da1 100644
--- a/chromium/content/renderer/notification_provider.h
+++ b/chromium/content/renderer/notification_provider.h
@@ -5,46 +5,55 @@
#ifndef CONTENT_RENDERER_NOTIFICATION_PROVIDER_H_
#define CONTENT_RENDERER_NOTIFICATION_PROVIDER_H_
+#include "base/memory/scoped_vector.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/active_notification_tracker.h"
#include "third_party/WebKit/public/web/WebNotification.h"
#include "third_party/WebKit/public/web/WebNotificationPresenter.h"
-namespace blink {
-class WebNotificationPermissionCallback;
-}
+class SkBitmap;
namespace content {
+class NotificationIconLoader;
+
// NotificationProvider class is owned by the RenderFrame. Only to be used on
// the main thread.
class NotificationProvider : public RenderFrameObserver,
public blink::WebNotificationPresenter {
public:
explicit NotificationProvider(RenderFrame* render_frame);
- virtual ~NotificationProvider();
+ ~NotificationProvider() override;
private:
// RenderFrameObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
- // blink::WebNotificationPresenter interface.
+ // blink::WebNotificationPresenter implementation.
virtual bool show(const blink::WebNotification& proxy);
virtual void cancel(const blink::WebNotification& proxy);
virtual void objectDestroyed(const blink::WebNotification& proxy);
virtual blink::WebNotificationPresenter::Permission checkPermission(
const blink::WebSecurityOrigin& origin);
- virtual void requestPermission(const blink::WebSecurityOrigin& origin,
- blink::WebNotificationPermissionCallback* callback);
+
+ // Sends an IPC to the browser process to display the notification identified
+ // by |notification|, accompanied by the downloaded icon.
+ void DisplayNotification(int notification_id, const SkBitmap& icon);
+
+ // Removes the IconDownload object associated with |notification_id|, stopping
+ // any in-progress download. Returns whether the notification was removed.
+ bool RemovePendingNotification(int notification_id);
// IPC handlers.
void OnDisplay(int id);
- void OnError(int id);
void OnClose(int id, bool by_user);
void OnClick(int id);
- void OnPermissionRequestComplete(int id);
void OnNavigate();
+ // A vector tracking notifications whose icon is still being downloaded.
+ typedef ScopedVector<NotificationIconLoader> PendingNotifications;
+ PendingNotifications pending_notifications_;
+
// A tracker object which manages the active notifications and the IDs
// that are used to refer to them over IPC.
ActiveNotificationTracker manager_;
diff --git a/chromium/content/renderer/npapi/plugin_channel_host.h b/chromium/content/renderer/npapi/plugin_channel_host.h
index 6e613463dba..a76f8240bfa 100644
--- a/chromium/content/renderer/npapi/plugin_channel_host.h
+++ b/chromium/content/renderer/npapi/plugin_channel_host.h
@@ -25,21 +25,21 @@ class PluginChannelHost : public NPChannelBase {
const IPC::ChannelHandle& channel_handle,
base::MessageLoopProxy* ipc_message_loop);
- virtual bool Init(base::MessageLoopProxy* ipc_message_loop,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) OVERRIDE;
+ bool Init(base::MessageLoopProxy* ipc_message_loop,
+ bool create_pipe_now,
+ base::WaitableEvent* shutdown_event) override;
- virtual int GenerateRouteID() OVERRIDE;
+ int GenerateRouteID() override;
void AddRoute(int route_id, IPC::Listener* listener,
NPObjectBase* npobject);
void RemoveRoute(int route_id);
// NPChannelBase override:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// IPC::Listener override
- virtual void OnChannelError() OVERRIDE;
+ void OnChannelError() override;
static void Broadcast(IPC::Message* message) {
NPChannelBase::Broadcast(message);
@@ -50,11 +50,11 @@ class PluginChannelHost : public NPChannelBase {
private:
// Called on the render thread
PluginChannelHost();
- virtual ~PluginChannelHost();
+ ~PluginChannelHost() override;
static NPChannelBase* ClassFactory() { return new PluginChannelHost(); }
- virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& message) override;
void OnSetException(const std::string& message);
void OnPluginShuttingDown();
diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
index 1943e802259..3576b19fa0d 100644
--- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
+++ b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
@@ -9,7 +9,7 @@
#include "base/auto_reset.h"
#include "base/basictypes.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -101,8 +101,7 @@ class ResourceClientProxy : public WebPluginResourceClient {
multibyte_response_expected_(false) {
}
- virtual ~ResourceClientProxy() {
- }
+ ~ResourceClientProxy() override {}
void Initialize(unsigned long resource_id, const GURL& url, int notify_id) {
resource_id_ = resource_id;
@@ -119,17 +118,17 @@ class ResourceClientProxy : public WebPluginResourceClient {
}
// PluginResourceClient implementation:
- virtual void WillSendRequest(const GURL& url, int http_status_code) OVERRIDE {
+ void WillSendRequest(const GURL& url, int http_status_code) override {
DCHECK(channel_.get() != NULL);
channel_->Send(new PluginMsg_WillSendRequest(
instance_id_, resource_id_, url, http_status_code));
}
- virtual void DidReceiveResponse(const std::string& mime_type,
- const std::string& headers,
- uint32 expected_length,
- uint32 last_modified,
- bool request_is_seekable) OVERRIDE {
+ void DidReceiveResponse(const std::string& mime_type,
+ const std::string& headers,
+ uint32 expected_length,
+ uint32 last_modified,
+ bool request_is_seekable) override {
DCHECK(channel_.get() != NULL);
PluginMsg_DidReceiveResponseParams params;
params.id = resource_id_;
@@ -144,9 +143,9 @@ class ResourceClientProxy : public WebPluginResourceClient {
channel_->Send(new PluginMsg_DidReceiveResponse(instance_id_, params));
}
- virtual void DidReceiveData(const char* buffer,
- int length,
- int data_offset) OVERRIDE {
+ void DidReceiveData(const char* buffer,
+ int length,
+ int data_offset) override {
DCHECK(channel_.get() != NULL);
DCHECK_GT(length, 0);
std::vector<char> data;
@@ -159,7 +158,7 @@ class ResourceClientProxy : public WebPluginResourceClient {
data, data_offset));
}
- virtual void DidFinishLoading(unsigned long resource_id) OVERRIDE {
+ void DidFinishLoading(unsigned long resource_id) override {
DCHECK(channel_.get() != NULL);
DCHECK_EQ(resource_id, resource_id_);
channel_->Send(new PluginMsg_DidFinishLoading(instance_id_, resource_id_));
@@ -167,7 +166,7 @@ class ResourceClientProxy : public WebPluginResourceClient {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
- virtual void DidFail(unsigned long resource_id) OVERRIDE {
+ void DidFail(unsigned long resource_id) override {
DCHECK(channel_.get() != NULL);
DCHECK_EQ(resource_id, resource_id_);
channel_->Send(new PluginMsg_DidFail(instance_id_, resource_id_));
@@ -175,13 +174,11 @@ class ResourceClientProxy : public WebPluginResourceClient {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
- virtual bool IsMultiByteResponseExpected() OVERRIDE {
+ bool IsMultiByteResponseExpected() override {
return multibyte_response_expected_;
}
- virtual int ResourceId() OVERRIDE {
- return resource_id_;
- }
+ int ResourceId() override { return resource_id_; }
private:
scoped_refptr<PluginChannelHost> channel_;
@@ -313,7 +310,7 @@ bool WebPluginDelegateProxy::Initialize(
// shouldn't happen, since if we got here the plugin should exist) or the
// plugin crashed on initialization.
if (!info_.path.empty()) {
- render_view_->main_render_frame()->PluginCrashed(
+ render_view_->GetMainRenderFrame()->PluginCrashed(
info_.path, base::kNullProcessId);
LOG(ERROR) << "Plug-in crashed on start";
@@ -486,8 +483,8 @@ void WebPluginDelegateProxy::OnChannelError() {
}
plugin_->Invalidate();
}
- if (!channel_host_->expecting_shutdown()) {
- render_view_->main_render_frame()->PluginCrashed(
+ if (channel_host_.get() && !channel_host_->expecting_shutdown()) {
+ render_view_->GetMainRenderFrame()->PluginCrashed(
info_.path, channel_host_->peer_pid());
}
@@ -525,6 +522,9 @@ static void CopyTransportDIBHandleForMessage(
void WebPluginDelegateProxy::SendUpdateGeometry(
bool bitmaps_changed) {
+ if (!channel_host_.get())
+ return;
+
PluginMsg_UpdateGeometry_Param param;
param.window_rect = plugin_rect_;
param.clip_rect = clip_rect_;
@@ -730,6 +730,9 @@ NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
if (npobject_)
return WebBindings::retainObject(npobject_);
+ if (!channel_host_.get())
+ return NULL;
+
int route_id = MSG_ROUTING_NONE;
Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id));
if (route_id == MSG_ROUTING_NONE)
@@ -769,7 +772,7 @@ void WebPluginDelegateProxy::SetFocus(bool focused) {
bool WebPluginDelegateProxy::HandleInputEvent(
const WebInputEvent& event,
WebCursor::CursorInfo* cursor_info) {
- bool handled;
+ bool handled = false;
WebCursor cursor;
// A windowless plugin can enter a modal loop in the context of a
// NPP_HandleEvent call, in which case we need to pump messages to
@@ -917,13 +920,11 @@ void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type,
if (!render_view_)
return;
- ViewHostMsg_TextInputState_Params p;
- p.type = static_cast<ui::TextInputType>(input_type);
- p.mode = ui::TEXT_INPUT_MODE_DEFAULT;
- p.can_compose_inline = true;
-
- render_view_->Send(new ViewHostMsg_TextInputStateChanged(
- render_view_->routing_id(), p));
+ render_view_->Send(new ViewHostMsg_TextInputTypeChanged(
+ render_view_->routing_id(),
+ static_cast<ui::TextInputType>(input_type),
+ ui::TEXT_INPUT_MODE_DEFAULT,
+ true, 0));
ViewHostMsg_SelectionBounds_Params bounds_params;
bounds_params.anchor_rect = bounds_params.focus_rect = caret_rect;
diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
index 6df1ab72333..5b8c62c6aa1 100644
--- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
+++ b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
@@ -56,23 +56,24 @@ class WebPluginDelegateProxy
RenderFrameImpl* render_frame);
// WebPluginDelegate implementation:
- virtual void PluginDestroyed() OVERRIDE;
- virtual bool Initialize(const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) OVERRIDE;
- virtual void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) OVERRIDE;
- virtual void Paint(SkCanvas* canvas, const gfx::Rect& rect) OVERRIDE;
- virtual NPObject* GetPluginScriptableObject() OVERRIDE;
- virtual struct _NPP* GetPluginNPP() OVERRIDE;
- virtual bool GetFormValue(base::string16* value) OVERRIDE;
- virtual void DidFinishLoadWithReason(const GURL& url, NPReason reason,
- int notify_id) OVERRIDE;
- virtual void SetFocus(bool focused) OVERRIDE;
- virtual bool HandleInputEvent(const blink::WebInputEvent& event,
- WebCursor::CursorInfo* cursor) OVERRIDE;
- virtual int GetProcessId() OVERRIDE;
+ void PluginDestroyed() override;
+ bool Initialize(const GURL& url,
+ const std::vector<std::string>& arg_names,
+ const std::vector<std::string>& arg_values,
+ bool load_manually) override;
+ void UpdateGeometry(const gfx::Rect& window_rect,
+ const gfx::Rect& clip_rect) override;
+ void Paint(SkCanvas* canvas, const gfx::Rect& rect) override;
+ NPObject* GetPluginScriptableObject() override;
+ struct _NPP* GetPluginNPP() override;
+ bool GetFormValue(base::string16* value) override;
+ void DidFinishLoadWithReason(const GURL& url,
+ NPReason reason,
+ int notify_id) override;
+ void SetFocus(bool focused) override;
+ bool HandleInputEvent(const blink::WebInputEvent& event,
+ WebCursor::CursorInfo* cursor) override;
+ int GetProcessId() override;
// Informs the plugin that its containing content view has gained or lost
// first responder status.
@@ -104,48 +105,50 @@ class WebPluginDelegateProxy
#endif
// IPC::Listener implementation:
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ void OnChannelError() override;
// IPC::Sender implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
-
- virtual void SendJavaScriptStream(const GURL& url,
- const std::string& result,
- bool success,
- int notify_id) OVERRIDE;
-
- virtual void DidReceiveManualResponse(const GURL& url,
- const std::string& mime_type,
- const std::string& headers,
- uint32 expected_length,
- uint32 last_modified) OVERRIDE;
- virtual void DidReceiveManualData(const char* buffer, int length) OVERRIDE;
- virtual void DidFinishManualLoading() OVERRIDE;
- virtual void DidManualLoadFail() OVERRIDE;
- virtual WebPluginResourceClient* CreateResourceClient(
- unsigned long resource_id, const GURL& url, int notify_id) OVERRIDE;
- virtual WebPluginResourceClient* CreateSeekableResourceClient(
- unsigned long resource_id, int range_request_id) OVERRIDE;
- virtual void FetchURL(unsigned long resource_id,
- int notify_id,
- const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& method,
- const char* buf,
- unsigned int len,
- const GURL& referrer,
- bool notify_redirects,
- bool is_plugin_src_load,
- int origin_pid,
- int render_frame_id,
- int render_view_id) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+
+ void SendJavaScriptStream(const GURL& url,
+ const std::string& result,
+ bool success,
+ int notify_id) override;
+
+ void DidReceiveManualResponse(const GURL& url,
+ const std::string& mime_type,
+ const std::string& headers,
+ uint32 expected_length,
+ uint32 last_modified) override;
+ void DidReceiveManualData(const char* buffer, int length) override;
+ void DidFinishManualLoading() override;
+ void DidManualLoadFail() override;
+ WebPluginResourceClient* CreateResourceClient(unsigned long resource_id,
+ const GURL& url,
+ int notify_id) override;
+ WebPluginResourceClient* CreateSeekableResourceClient(
+ unsigned long resource_id,
+ int range_request_id) override;
+ void FetchURL(unsigned long resource_id,
+ int notify_id,
+ const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& method,
+ const char* buf,
+ unsigned int len,
+ const GURL& referrer,
+ bool notify_redirects,
+ bool is_plugin_src_load,
+ int origin_pid,
+ int render_frame_id,
+ int render_view_id) override;
gfx::PluginWindowHandle GetPluginWindowHandle();
protected:
friend class base::DeleteHelper<WebPluginDelegateProxy>;
- virtual ~WebPluginDelegateProxy();
+ ~WebPluginDelegateProxy() override;
private:
struct SharedBitmap {
diff --git a/chromium/content/renderer/npapi/webplugin_impl.cc b/chromium/content/renderer/npapi/webplugin_impl.cc
index 91e16b073d1..4370dec7922 100644
--- a/chromium/content/renderer/npapi/webplugin_impl.cc
+++ b/chromium/content/renderer/npapi/webplugin_impl.cc
@@ -14,8 +14,10 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/layers/io_surface_layer.h"
#include "content/child/appcache/web_application_cache_host_impl.h"
+#include "content/child/multipart_response_delegate.h"
#include "content/child/npapi/plugin_host.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/child/npapi/webplugin_delegate_impl.h"
@@ -24,7 +26,6 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/npapi/webplugin_delegate_proxy.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_process.h"
@@ -57,12 +58,11 @@
#include "ui/gfx/rect.h"
#include "url/gurl.h"
#include "url/url_util.h"
-#include "webkit/child/multipart_response_delegate.h"
+using blink::WebCString;
using blink::WebCanvas;
using blink::WebConsoleMessage;
using blink::WebCookieJar;
-using blink::WebCString;
using blink::WebCursorInfo;
using blink::WebData;
using blink::WebDataSource;
@@ -85,7 +85,6 @@ using blink::WebURLRequest;
using blink::WebURLResponse;
using blink::WebVector;
using blink::WebView;
-using webkit_glue::MultipartResponseDelegate;
namespace content {
@@ -545,10 +544,10 @@ WebPluginImpl::WebPluginImpl(
ignore_response_error_(false),
file_path_(file_path),
mime_type_(base::UTF16ToASCII(params.mimeType)),
- weak_factory_(this),
- loader_client_(this) {
+ loader_client_(this),
+ weak_factory_(this) {
DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
- StringToLowerASCII(&mime_type_);
+ base::StringToLowerASCII(&mime_type_);
for (size_t i = 0; i < params.attributeNames.size(); ++i) {
arg_names_.push_back(params.attributeNames[i].utf8());
@@ -735,6 +734,8 @@ WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame(
request.setFirstPartyForCookies(
webframe_->document().firstPartyForCookies());
request.setHasUserGesture(popups_allowed);
+ // ServiceWorker is disabled for NPAPI.
+ request.setSkipServiceWorker(true);
if (len > 0) {
if (!SetPostData(&request, buf, len)) {
// Uhoh - we're in trouble. There isn't a good way
@@ -852,7 +853,7 @@ void WebPluginImpl::AcceleratedPluginSwappedIOSurface() {
if (next_io_surface_id_) {
if (!io_surface_layer_.get()) {
io_surface_layer_ = cc::IOSurfaceLayer::Create();
- web_layer_.reset(new WebLayerImpl(io_surface_layer_));
+ web_layer_.reset(new cc_blink::WebLayerImpl(io_surface_layer_));
container_->setWebLayer(web_layer_.get());
}
io_surface_layer_->SetIOSurfaceProperties(
@@ -1048,7 +1049,7 @@ void WebPluginImpl::didReceiveResponse(WebURLLoader* loader,
// destroy the stream and invoke the NPP_DestroyStream function on the
// plugin if the HTTP request fails.
const GURL& url = response.url();
- if (url.SchemeIs("http") || url.SchemeIs("https")) {
+ if (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme)) {
if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) {
// The plugin instance could be in the process of deletion here.
// Verify if the WebPluginResourceClient instance still exists before
@@ -1171,7 +1172,7 @@ void WebPluginImpl::HandleURLRequestInternal(const char* url,
// in which case we route the output to the plugin rather than routing it
// to the plugin's frame.
bool is_javascript_url =
- url::FindAndCompareScheme(url, strlen(url), "javascript", NULL);
+ url::FindAndCompareScheme(url, strlen(url), url::kJavaScriptScheme, NULL);
RoutingStatus routing_status = RouteToFrame(
url, is_javascript_url, popups_allowed, method, target, buf, len,
notify_id, referrer_flag);
@@ -1284,8 +1285,13 @@ bool WebPluginImpl::InitiateHTTPRequest(unsigned long resource_id,
info.request.setFirstPartyForCookies(
webframe_->document().firstPartyForCookies());
info.request.setRequestorProcessID(delegate_->GetProcessId());
- info.request.setTargetType(WebURLRequest::TargetIsObject);
+ // TODO(mkwst): Is this a request for a plugin object itself
+ // (RequestContextObject), or a request that the plugin makes
+ // (RequestContextPlugin)?
+ info.request.setRequestContext(WebURLRequest::RequestContextPlugin);
info.request.setHTTPMethod(WebString::fromUTF8(method));
+ // ServiceWorker is disabled for NPAPI.
+ info.request.setSkipServiceWorker(true);
info.pending_failure_notification = false;
info.notify_redirects = notify_redirects;
info.is_plugin_src_load = is_plugin_src_load;
diff --git a/chromium/content/renderer/npapi/webplugin_impl.h b/chromium/content/renderer/npapi/webplugin_impl.h
index b8b59d56c2d..6115d08346f 100644
--- a/chromium/content/renderer/npapi/webplugin_impl.h
+++ b/chromium/content/renderer/npapi/webplugin_impl.h
@@ -38,11 +38,8 @@ class WebURLLoader;
class WebURLRequest;
}
-namespace webkit_glue {
-class MultipartResponseDelegate;
-} // namespace webkit_glue
-
namespace content {
+class MultipartResponseDelegate;
class RenderFrameImpl;
class RenderViewImpl;
class WebPluginDelegateProxy;
@@ -59,7 +56,7 @@ class WebPluginImpl : public WebPlugin,
const base::FilePath& file_path,
const base::WeakPtr<RenderViewImpl>& render_view,
RenderFrameImpl* render_frame);
- virtual ~WebPluginImpl();
+ ~WebPluginImpl() override;
// Helper function for sorting post data.
CONTENT_EXPORT static bool SetPostData(blink::WebURLRequest* request,
@@ -94,43 +91,41 @@ class WebPluginImpl : public WebPlugin,
virtual void didFailLoadingFrameRequest(
const blink::WebURL& url, void* notify_data,
const blink::WebURLError& error);
- virtual bool isPlaceholder() OVERRIDE;
+ virtual bool isPlaceholder() override;
// WebPlugin implementation:
- virtual void SetWindow(gfx::PluginWindowHandle window) OVERRIDE;
- virtual void SetAcceptsInputEvents(bool accepts) OVERRIDE;
- virtual void WillDestroyWindow(gfx::PluginWindowHandle window) OVERRIDE;
- virtual void CancelResource(unsigned long id) OVERRIDE;
- virtual void Invalidate() OVERRIDE;
- virtual void InvalidateRect(const gfx::Rect& rect) OVERRIDE;
- virtual NPObject* GetWindowScriptNPObject() OVERRIDE;
- virtual NPObject* GetPluginElement() OVERRIDE;
- virtual bool FindProxyForUrl(const GURL& url,
- std::string* proxy_list) OVERRIDE;
- virtual void SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) OVERRIDE;
- virtual std::string GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) OVERRIDE;
- virtual void HandleURLRequest(const char* url,
- const char *method,
- const char* target,
- const char* buf,
- unsigned int len,
- int notify_id,
- bool popups_allowed,
- bool notify_redirects) OVERRIDE;
- virtual void CancelDocumentLoad() OVERRIDE;
- virtual void InitiateHTTPRangeRequest(const char* url,
- const char* range_info,
- int pending_request_id) OVERRIDE;
- virtual void DidStartLoading() OVERRIDE;
- virtual void DidStopLoading() OVERRIDE;
- virtual bool IsOffTheRecord() OVERRIDE;
- virtual void SetDeferResourceLoading(unsigned long resource_id,
- bool defer) OVERRIDE;
- virtual void URLRedirectResponse(bool allow, int resource_id) OVERRIDE;
- virtual bool CheckIfRunInsecureContent(const GURL& url) OVERRIDE;
+ void SetWindow(gfx::PluginWindowHandle window) override;
+ void SetAcceptsInputEvents(bool accepts) override;
+ void WillDestroyWindow(gfx::PluginWindowHandle window) override;
+ void CancelResource(unsigned long id) override;
+ void Invalidate() override;
+ void InvalidateRect(const gfx::Rect& rect) override;
+ NPObject* GetWindowScriptNPObject() override;
+ NPObject* GetPluginElement() override;
+ bool FindProxyForUrl(const GURL& url, std::string* proxy_list) override;
+ void SetCookie(const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& cookie) override;
+ std::string GetCookies(const GURL& url,
+ const GURL& first_party_for_cookies) override;
+ void HandleURLRequest(const char* url,
+ const char* method,
+ const char* target,
+ const char* buf,
+ unsigned int len,
+ int notify_id,
+ bool popups_allowed,
+ bool notify_redirects) override;
+ void CancelDocumentLoad() override;
+ void InitiateHTTPRangeRequest(const char* url,
+ const char* range_info,
+ int pending_request_id) override;
+ void DidStartLoading() override;
+ void DidStopLoading() override;
+ bool IsOffTheRecord() override;
+ void SetDeferResourceLoading(unsigned long resource_id, bool defer) override;
+ void URLRedirectResponse(bool allow, int resource_id) override;
+ bool CheckIfRunInsecureContent(const GURL& url) override;
#if defined(OS_WIN)
void SetWindowlessData(HANDLE pump_messages_event,
gfx::NativeViewId dummy_activation_window) { }
@@ -138,13 +133,13 @@ class WebPluginImpl : public WebPlugin,
void ReportExecutableMemory(size_t size) { }
#endif
#if defined(OS_MACOSX)
- virtual WebPluginAcceleratedSurface* GetAcceleratedSurface(
- gfx::GpuPreference gpu_preference) OVERRIDE;
- virtual void AcceleratedPluginEnabledRendering() OVERRIDE;
- virtual void AcceleratedPluginAllocatedIOSurface(int32 width,
- int32 height,
- uint32 surface_id) OVERRIDE;
- virtual void AcceleratedPluginSwappedIOSurface() OVERRIDE;
+ WebPluginAcceleratedSurface* GetAcceleratedSurface(
+ gfx::GpuPreference gpu_preference) override;
+ void AcceleratedPluginEnabledRendering() override;
+ void AcceleratedPluginAllocatedIOSurface(int32 width,
+ int32 height,
+ uint32 surface_id) override;
+ void AcceleratedPluginSwappedIOSurface() override;
#endif
private:
@@ -295,8 +290,7 @@ class WebPluginImpl : public WebPlugin,
// Unique identifier for this plugin, used to track script objects.
struct _NPP* npp_;
- typedef std::map<WebPluginResourceClient*,
- webkit_glue::MultipartResponseDelegate*>
+ typedef std::map<WebPluginResourceClient*, MultipartResponseDelegate*>
MultiPartResponseHandlerMap;
// Tracks HTTP multipart response handlers instantiated for
// a WebPluginResourceClient instance.
@@ -328,35 +322,33 @@ class WebPluginImpl : public WebPlugin,
std::vector<std::string> arg_names_;
std::vector<std::string> arg_values_;
- base::WeakPtrFactory<WebPluginImpl> weak_factory_;
-
class LoaderClient : public blink::WebURLLoaderClient {
public:
LoaderClient(WebPluginImpl*);
virtual void willSendRequest(blink::WebURLLoader*,
blink::WebURLRequest&,
- const blink::WebURLResponse&) OVERRIDE;
+ const blink::WebURLResponse&) override;
virtual void didSendData(blink::WebURLLoader*,
unsigned long long bytesSent,
- unsigned long long totalBytesToBeSent) OVERRIDE;
+ unsigned long long totalBytesToBeSent) override;
virtual void didReceiveResponse(blink::WebURLLoader*,
- const blink::WebURLResponse&) OVERRIDE;
+ const blink::WebURLResponse&) override;
virtual void didDownloadData(blink::WebURLLoader*,
int dataLength,
- int encodedDataLength) OVERRIDE;
+ int encodedDataLength) override;
virtual void didReceiveData(blink::WebURLLoader*,
const char* data,
int dataLength,
- int encodedDataLength) OVERRIDE;
+ int encodedDataLength) override;
virtual void didReceiveCachedMetadata(blink::WebURLLoader*,
const char* data,
- int dataLength) OVERRIDE;
+ int dataLength) override;
virtual void didFinishLoading(blink::WebURLLoader*,
double finishTime,
- int64_t total_encoded_data_length) OVERRIDE;
+ int64_t total_encoded_data_length) override;
virtual void didFail(blink::WebURLLoader*,
- const blink::WebURLError&) OVERRIDE;
+ const blink::WebURLError&) override;
private:
WebPluginImpl* parent_;
@@ -364,6 +356,8 @@ class WebPluginImpl : public WebPlugin,
LoaderClient loader_client_;
+ base::WeakPtrFactory<WebPluginImpl> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(WebPluginImpl);
};
diff --git a/chromium/content/renderer/p2p/OWNERS b/chromium/content/renderer/p2p/OWNERS
index b67eda40c6a..5e2b3d678cd 100644
--- a/chromium/content/renderer/p2p/OWNERS
+++ b/chromium/content/renderer/p2p/OWNERS
@@ -1 +1,2 @@
sergeyu@chromium.org
+juberti@chromium.org
diff --git a/chromium/content/renderer/p2p/host_address_request.cc b/chromium/content/renderer/p2p/host_address_request.cc
index 72e7c4673c8..e21e0aae227 100644
--- a/chromium/content/renderer/p2p/host_address_request.cc
+++ b/chromium/content/renderer/p2p/host_address_request.cc
@@ -29,7 +29,7 @@ P2PAsyncAddressResolver::~P2PAsyncAddressResolver() {
DCHECK(!registered_);
}
-void P2PAsyncAddressResolver::Start(const talk_base::SocketAddress& host_name,
+void P2PAsyncAddressResolver::Start(const rtc::SocketAddress& host_name,
const DoneCallback& done_callback) {
DCHECK(delegate_message_loop_->BelongsToCurrentThread());
DCHECK_EQ(STATE_CREATED, state_);
@@ -51,7 +51,7 @@ void P2PAsyncAddressResolver::Cancel() {
}
void P2PAsyncAddressResolver::DoSendRequest(
- const talk_base::SocketAddress& host_name,
+ const rtc::SocketAddress& host_name,
const DoneCallback& done_callback) {
DCHECK(ipc_message_loop_->BelongsToCurrentThread());
diff --git a/chromium/content/renderer/p2p/host_address_request.h b/chromium/content/renderer/p2p/host_address_request.h
index 7c90b800495..ab454868dfc 100644
--- a/chromium/content/renderer/p2p/host_address_request.h
+++ b/chromium/content/renderer/p2p/host_address_request.h
@@ -11,7 +11,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "net/base/net_util.h"
-#include "third_party/libjingle/source/talk/base/asyncresolverinterface.h"
+#include "third_party/webrtc/base/asyncresolverinterface.h"
namespace base {
class MessageLoop;
@@ -31,7 +31,7 @@ class P2PAsyncAddressResolver
P2PAsyncAddressResolver(P2PSocketDispatcher* dispatcher);
// Start address resolve process.
- void Start(const talk_base::SocketAddress& addr,
+ void Start(const rtc::SocketAddress& addr,
const DoneCallback& done_callback);
// Clients must unregister before exiting for cleanup.
void Cancel();
@@ -49,7 +49,7 @@ class P2PAsyncAddressResolver
virtual ~P2PAsyncAddressResolver();
- void DoSendRequest(const talk_base::SocketAddress& host_name,
+ void DoSendRequest(const rtc::SocketAddress& host_name,
const DoneCallback& done_callback);
void DoUnregister();
void OnResponse(const net::IPAddressList& address);
@@ -65,7 +65,7 @@ class P2PAsyncAddressResolver
// Accessed on the IPC thread only.
int32 request_id_;
bool registered_;
- std::vector<talk_base::IPAddress> addresses_;
+ std::vector<rtc::IPAddress> addresses_;
DoneCallback done_callback_;
DISALLOW_COPY_AND_ASSIGN(P2PAsyncAddressResolver);
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.cc b/chromium/content/renderer/p2p/ipc_network_manager.cc
index 9cf6cf5013e..ec48e4006a1 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.cc
+++ b/chromium/content/renderer/p2p/ipc_network_manager.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "content/renderer/p2p/ipc_network_manager.h"
-
+#include <string>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/histogram.h"
@@ -15,37 +15,37 @@ namespace content {
namespace {
-talk_base::AdapterType ConvertConnectionTypeToAdapterType(
+rtc::AdapterType ConvertConnectionTypeToAdapterType(
net::NetworkChangeNotifier::ConnectionType type) {
switch (type) {
case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
- return talk_base::ADAPTER_TYPE_UNKNOWN;
+ return rtc::ADAPTER_TYPE_UNKNOWN;
case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
- return talk_base::ADAPTER_TYPE_ETHERNET;
+ return rtc::ADAPTER_TYPE_ETHERNET;
case net::NetworkChangeNotifier::CONNECTION_WIFI:
- return talk_base::ADAPTER_TYPE_WIFI;
+ return rtc::ADAPTER_TYPE_WIFI;
case net::NetworkChangeNotifier::CONNECTION_2G:
case net::NetworkChangeNotifier::CONNECTION_3G:
case net::NetworkChangeNotifier::CONNECTION_4G:
- return talk_base::ADAPTER_TYPE_CELLULAR;
+ return rtc::ADAPTER_TYPE_CELLULAR;
default:
- return talk_base::ADAPTER_TYPE_UNKNOWN;
+ return rtc::ADAPTER_TYPE_UNKNOWN;
}
}
} // namespace
-IpcNetworkManager::IpcNetworkManager(P2PSocketDispatcher* socket_dispatcher)
- : socket_dispatcher_(socket_dispatcher),
+IpcNetworkManager::IpcNetworkManager(NetworkListManager* network_list_manager)
+ : network_list_manager_(network_list_manager),
start_count_(0),
network_list_received_(false),
weak_factory_(this) {
- socket_dispatcher_->AddNetworkListObserver(this);
+ network_list_manager_->AddNetworkListObserver(this);
}
IpcNetworkManager::~IpcNetworkManager() {
DCHECK(!start_count_);
- socket_dispatcher_->RemoveNetworkListObserver(this);
+ network_list_manager_->RemoveNetworkListObserver(this);
}
void IpcNetworkManager::StartUpdating() {
@@ -71,11 +71,9 @@ void IpcNetworkManager::OnNetworkListChanged(
if (!network_list_received_)
network_list_received_ = true;
- // Note: 32 and 64 are the arbitrary(kind of) prefix length used to
- // differentiate IPv4 and IPv6 addresses.
- // talk_base::Network uses these prefix_length to compare network
+ // rtc::Network uses these prefix_length to compare network
// interfaces discovered.
- std::vector<talk_base::Network*> networks;
+ std::vector<rtc::Network*> networks;
int ipv4_interfaces = 0;
int ipv6_interfaces = 0;
for (net::NetworkInterfaceList::const_iterator it = list.begin();
@@ -83,21 +81,31 @@ void IpcNetworkManager::OnNetworkListChanged(
if (it->address.size() == net::kIPv4AddressSize) {
uint32 address;
memcpy(&address, &it->address[0], sizeof(uint32));
- address = talk_base::NetworkToHost32(address);
- talk_base::Network* network = new talk_base::Network(
- it->name, it->name, talk_base::IPAddress(address), 32,
- ConvertConnectionTypeToAdapterType(it->type));
- network->AddIP(talk_base::IPAddress(address));
+ address = rtc::NetworkToHost32(address);
+ rtc::IPAddress prefix =
+ rtc::TruncateIP(rtc::IPAddress(address), it->network_prefix);
+ rtc::Network* network =
+ new rtc::Network(it->name,
+ it->name,
+ prefix,
+ it->network_prefix,
+ ConvertConnectionTypeToAdapterType(it->type));
+ network->AddIP(rtc::IPAddress(address));
networks.push_back(network);
++ipv4_interfaces;
} else if (it->address.size() == net::kIPv6AddressSize) {
in6_addr address;
memcpy(&address, &it->address[0], sizeof(in6_addr));
- talk_base::IPAddress ip6_addr(address);
- if (!talk_base::IPIsPrivate(ip6_addr)) {
- talk_base::Network* network = new talk_base::Network(
- it->name, it->name, ip6_addr, 64,
- ConvertConnectionTypeToAdapterType(it->type));
+ rtc::IPAddress ip6_addr(address);
+ if (!rtc::IPIsPrivate(ip6_addr)) {
+ rtc::IPAddress prefix =
+ rtc::TruncateIP(rtc::IPAddress(ip6_addr), it->network_prefix);
+ rtc::Network* network =
+ new rtc::Network(it->name,
+ it->name,
+ prefix,
+ it->network_prefix,
+ ConvertConnectionTypeToAdapterType(it->type));
network->AddIP(ip6_addr);
networks.push_back(network);
++ipv6_interfaces;
@@ -105,29 +113,26 @@ void IpcNetworkManager::OnNetworkListChanged(
}
}
- if (ipv4_interfaces > 0) {
- UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
- ipv4_interfaces);
- }
- if (ipv6_interfaces > 0) {
- UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
- ipv6_interfaces);
- }
+ // Send interface counts to UMA.
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
+ ipv4_interfaces);
+ UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
+ ipv6_interfaces);
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kAllowLoopbackInPeerConnection)) {
std::string name_v4("loopback_ipv4");
- talk_base::IPAddress ip_address_v4(INADDR_LOOPBACK);
- talk_base::Network* network_v4 = new talk_base::Network(
- name_v4, name_v4, ip_address_v4, 32, talk_base::ADAPTER_TYPE_UNKNOWN);
+ rtc::IPAddress ip_address_v4(INADDR_LOOPBACK);
+ rtc::Network* network_v4 = new rtc::Network(
+ name_v4, name_v4, ip_address_v4, 32, rtc::ADAPTER_TYPE_UNKNOWN);
network_v4->AddIP(ip_address_v4);
networks.push_back(network_v4);
std::string name_v6("loopback_ipv6");
- talk_base::IPAddress ip_address_v6(in6addr_loopback);
- talk_base::Network* network_v6 = new talk_base::Network(
- name_v6, name_v6, ip_address_v6, 64, talk_base::ADAPTER_TYPE_UNKNOWN);
+ rtc::IPAddress ip_address_v6(in6addr_loopback);
+ rtc::Network* network_v6 = new rtc::Network(
+ name_v6, name_v6, ip_address_v6, 64, rtc::ADAPTER_TYPE_UNKNOWN);
network_v6->AddIP(ip_address_v6);
networks.push_back(network_v6);
}
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.h b/chromium/content/renderer/p2p/ipc_network_manager.h
index 06931dc7f46..81f673cdffe 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.h
+++ b/chromium/content/renderer/p2p/ipc_network_manager.h
@@ -10,32 +10,31 @@
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/renderer/p2p/network_list_manager.h"
#include "content/renderer/p2p/network_list_observer.h"
-#include "content/renderer/p2p/socket_dispatcher.h"
-#include "third_party/libjingle/source/talk/base/network.h"
+#include "third_party/webrtc/base/network.h"
namespace content {
// IpcNetworkManager is a NetworkManager for libjingle that gets a
// list of network interfaces from the browser.
-class IpcNetworkManager : public talk_base::NetworkManagerBase,
+class IpcNetworkManager : public rtc::NetworkManagerBase,
public NetworkListObserver {
public:
- // Constructor doesn't take ownership of the |socket_dispatcher|.
- CONTENT_EXPORT IpcNetworkManager(P2PSocketDispatcher* socket_dispatcher);
- virtual ~IpcNetworkManager();
+ // Constructor doesn't take ownership of the |network_list_manager|.
+ CONTENT_EXPORT IpcNetworkManager(NetworkListManager* network_list_manager);
+ ~IpcNetworkManager() override;
- virtual void StartUpdating() OVERRIDE;
- virtual void StopUpdating() OVERRIDE;
+ void StartUpdating() override;
+ void StopUpdating() override;
// P2PSocketDispatcher::NetworkListObserver interface.
- virtual void OnNetworkListChanged(
- const net::NetworkInterfaceList& list) OVERRIDE;
+ void OnNetworkListChanged(const net::NetworkInterfaceList& list) override;
private:
void SendNetworksChangedSignal();
- P2PSocketDispatcher* socket_dispatcher_;
+ NetworkListManager* network_list_manager_;
int start_count_;
bool network_list_received_;
diff --git a/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc b/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
new file mode 100644
index 00000000000..85c63229c79
--- /dev/null
+++ b/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
@@ -0,0 +1,115 @@
+// Copyright 2014 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/memory/scoped_ptr.h"
+#include "content/renderer/p2p/ipc_network_manager.h"
+#include "content/renderer/p2p/network_list_manager.h"
+#include "net/base/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+class MockP2PSocketDispatcher : public NetworkListManager {
+ public:
+ void AddNetworkListObserver(
+ NetworkListObserver* network_list_observer) override {}
+
+ void RemoveNetworkListObserver(
+ NetworkListObserver* network_list_observer) override {}
+
+ ~MockP2PSocketDispatcher() override {}
+};
+
+} // namespace
+
+// 2 IPv6 addresses with only last digit different.
+static const char kIPv6PublicAddrString1[] =
+ "2401:fa00:4:1000:be30:5bff:fee5:c3";
+static const char kIPv6PublicAddrString2[] =
+ "2401:fa00:4:1000:be30:5bff:fee5:c4";
+
+class IpcNetworkManagerTest : public testing::Test {
+ public:
+ IpcNetworkManagerTest()
+ : network_list_manager_(new MockP2PSocketDispatcher()),
+ network_manager_(new IpcNetworkManager(network_list_manager_.get())) {}
+
+ protected:
+ scoped_ptr<MockP2PSocketDispatcher> network_list_manager_;
+ scoped_ptr<IpcNetworkManager> network_manager_;
+};
+
+// Test overall logic of IpcNetworkManager on OnNetworkListChanged
+// that it should group addresses with the same network key under
+// single Network class. This also tests the logic inside
+// IpcNetworkManager in addition to MergeNetworkList.
+// TODO(guoweis): disable this test case for now until fix for webrtc
+// issue 19249005 integrated into chromium
+TEST_F(IpcNetworkManagerTest, DISABLED_TestMergeNetworkList) {
+ net::NetworkInterfaceList list;
+ net::IPAddressNumber ip_number;
+ std::vector<rtc::Network*> networks;
+ rtc::IPAddress ip_address;
+
+ // Add 2 networks with the same prefix and prefix length.
+ EXPECT_TRUE(net::ParseIPLiteralToNumber(kIPv6PublicAddrString1, &ip_number));
+ list.push_back(
+ net::NetworkInterface("em1",
+ "em1",
+ 0,
+ net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
+ ip_number,
+ 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ EXPECT_TRUE(net::ParseIPLiteralToNumber(kIPv6PublicAddrString2, &ip_number));
+ list.push_back(
+ net::NetworkInterface("em1",
+ "em1",
+ 0,
+ net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
+ ip_number,
+ 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ network_manager_->OnNetworkListChanged(list);
+ network_manager_->GetNetworks(&networks);
+ EXPECT_EQ(1uL, networks.size());
+ EXPECT_EQ(2uL, networks[0]->GetIPs().size());
+
+ // Add another network with different prefix length, should result in
+ // a different network.
+ networks.clear();
+ list.push_back(
+ net::NetworkInterface("em1",
+ "em1",
+ 0,
+ net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
+ ip_number,
+ 48,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ network_manager_->OnNetworkListChanged(list);
+
+ network_manager_->GetNetworks(&networks);
+
+ // Verify we have 2 networks now.
+ EXPECT_EQ(2uL, networks.size());
+ // Verify the network with prefix length of 64 has 2 IP addresses.
+ EXPECT_EQ(64, networks[1]->prefix_length());
+ EXPECT_EQ(2uL, networks[1]->GetIPs().size());
+ EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString1, &ip_address));
+ EXPECT_EQ(networks[1]->GetIPs()[0], ip_address);
+ EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString2, &ip_address));
+ EXPECT_EQ(networks[1]->GetIPs()[1], ip_address);
+ // Verify the network with prefix length of 48 has 2 IP addresses.
+ EXPECT_EQ(48, networks[0]->prefix_length());
+ EXPECT_EQ(1uL, networks[0]->GetIPs().size());
+ EXPECT_TRUE(rtc::IPFromString(kIPv6PublicAddrString2, &ip_address));
+ EXPECT_EQ(networks[0]->GetIPs()[0], ip_address);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.cc b/chromium/content/renderer/p2p/ipc_socket_factory.cc
index 43b6d163ff4..27d6825b3e5 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.cc
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.cc
@@ -11,6 +11,7 @@
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "base/threading/non_thread_safe.h"
#include "content/renderer/media/webrtc_logging.h"
@@ -19,7 +20,7 @@
#include "content/renderer/p2p/socket_client_impl.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "jingle/glue/utils.h"
-#include "third_party/libjingle/source/talk/base/asyncpacketsocket.h"
+#include "third_party/webrtc/base/asyncpacketsocket.h"
namespace content {
@@ -36,22 +37,22 @@ bool IsTcpClientSocket(P2PSocketType type) {
(type == P2P_SOCKET_STUN_TLS_CLIENT);
}
-bool JingleSocketOptionToP2PSocketOption(talk_base::Socket::Option option,
+bool JingleSocketOptionToP2PSocketOption(rtc::Socket::Option option,
P2PSocketOption* ipc_option) {
switch (option) {
- case talk_base::Socket::OPT_RCVBUF:
+ case rtc::Socket::OPT_RCVBUF:
*ipc_option = P2P_SOCKET_OPT_RCVBUF;
break;
- case talk_base::Socket::OPT_SNDBUF:
+ case rtc::Socket::OPT_SNDBUF:
*ipc_option = P2P_SOCKET_OPT_SNDBUF;
break;
- case talk_base::Socket::OPT_DSCP:
+ case rtc::Socket::OPT_DSCP:
*ipc_option = P2P_SOCKET_OPT_DSCP;
break;
- case talk_base::Socket::OPT_DONTFRAGMENT:
- case talk_base::Socket::OPT_NODELAY:
- case talk_base::Socket::OPT_IPV6_V6ONLY:
- case talk_base::Socket::OPT_RTP_SENDTIME_EXTN_ID:
+ case rtc::Socket::OPT_DONTFRAGMENT:
+ case rtc::Socket::OPT_NODELAY:
+ case rtc::Socket::OPT_IPV6_V6ONLY:
+ case rtc::Socket::OPT_RTP_SENDTIME_EXTN_ID:
return false; // Not supported by the chrome sockets.
default:
NOTREACHED();
@@ -61,47 +62,50 @@ bool JingleSocketOptionToP2PSocketOption(talk_base::Socket::Option option,
}
// TODO(miu): This needs tuning. http://crbug.com/237960
-const size_t kMaximumInFlightBytes = 64 * 1024; // 64 KB
+// http://crbug.com/427555
+const size_t kMaximumInFlightBytes = 256 * 1024; // 256 KB
-// IpcPacketSocket implements talk_base::AsyncPacketSocket interface
+// IpcPacketSocket implements rtc::AsyncPacketSocket interface
// using P2PSocketClient that works over IPC-channel. It must be used
// on the thread it was created.
-class IpcPacketSocket : public talk_base::AsyncPacketSocket,
+class IpcPacketSocket : public rtc::AsyncPacketSocket,
public P2PSocketClientDelegate {
public:
IpcPacketSocket();
- virtual ~IpcPacketSocket();
+ ~IpcPacketSocket() override;
// Always takes ownership of client even if initialization fails.
bool Init(P2PSocketType type, P2PSocketClientImpl* client,
- const talk_base::SocketAddress& local_address,
- const talk_base::SocketAddress& remote_address);
-
- // talk_base::AsyncPacketSocket interface.
- virtual talk_base::SocketAddress GetLocalAddress() const OVERRIDE;
- virtual talk_base::SocketAddress GetRemoteAddress() const OVERRIDE;
- virtual int Send(const void *pv, size_t cb,
- const talk_base::PacketOptions& options) OVERRIDE;
- virtual int SendTo(const void *pv, size_t cb,
- const talk_base::SocketAddress& addr,
- const talk_base::PacketOptions& options) OVERRIDE;
- virtual int Close() OVERRIDE;
- virtual State GetState() const OVERRIDE;
- virtual int GetOption(talk_base::Socket::Option option, int* value) OVERRIDE;
- virtual int SetOption(talk_base::Socket::Option option, int value) OVERRIDE;
- virtual int GetError() const OVERRIDE;
- virtual void SetError(int error) OVERRIDE;
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address);
+
+ // rtc::AsyncPacketSocket interface.
+ rtc::SocketAddress GetLocalAddress() const override;
+ rtc::SocketAddress GetRemoteAddress() const override;
+ int Send(const void* pv,
+ size_t cb,
+ const rtc::PacketOptions& options) override;
+ int SendTo(const void* pv,
+ size_t cb,
+ const rtc::SocketAddress& addr,
+ const rtc::PacketOptions& options) override;
+ int Close() override;
+ State GetState() const override;
+ int GetOption(rtc::Socket::Option option, int* value) override;
+ int SetOption(rtc::Socket::Option option, int value) override;
+ int GetError() const override;
+ void SetError(int error) override;
// P2PSocketClientDelegate implementation.
- virtual void OnOpen(const net::IPEndPoint& address) OVERRIDE;
- virtual void OnIncomingTcpConnection(
- const net::IPEndPoint& address,
- P2PSocketClient* client) OVERRIDE;
- virtual void OnSendComplete() OVERRIDE;
- virtual void OnError() OVERRIDE;
- virtual void OnDataReceived(const net::IPEndPoint& address,
- const std::vector<char>& data,
- const base::TimeTicks& timestamp) OVERRIDE;
+ void OnOpen(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) override;
+ void OnIncomingTcpConnection(const net::IPEndPoint& address,
+ P2PSocketClient* client) override;
+ void OnSendComplete() override;
+ void OnError() override;
+ void OnDataReceived(const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ const base::TimeTicks& timestamp) override;
private:
enum InternalState {
@@ -112,14 +116,18 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
IS_ERROR,
};
+ // Increment the counter for consecutive bytes discarded as socket is running
+ // out of buffer.
+ void IncrementDiscardCounters(size_t bytes_discarded);
+
// Update trace of send throttling internal state. This should be called
// immediately after any changes to |send_bytes_available_| and/or
// |in_flight_packet_sizes_|.
void TraceSendThrottlingState() const;
void InitAcceptedTcp(P2PSocketClient* client,
- const talk_base::SocketAddress& local_address,
- const talk_base::SocketAddress& remote_address);
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address);
int DoSetOption(P2PSocketOption option, int value);
@@ -134,10 +142,10 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
// Local address is allocated by the browser process, and the
// renderer side doesn't know the address until it receives OnOpen()
// event from the browser.
- talk_base::SocketAddress local_address_;
+ rtc::SocketAddress local_address_;
// Remote address for client TCP connections.
- talk_base::SocketAddress remote_address_;
+ rtc::SocketAddress remote_address_;
// Current state of the object.
InternalState state_;
@@ -159,6 +167,15 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
int error_;
int options_[P2P_SOCKET_OPT_MAX];
+ // Track the maximum and current consecutive bytes discarded due to not enough
+ // send_bytes_available_.
+ size_t max_discard_bytes_sequence_;
+ size_t current_discard_bytes_sequence_;
+
+ // Track the total number of packets and the number of packets discarded.
+ size_t packets_discarded_;
+ size_t total_packets_;
+
DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket);
};
@@ -168,24 +185,23 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
// of MT sig slots clients must call disconnect. This class is to make sure
// we destruct from the same thread on which is created.
class AsyncAddressResolverImpl : public base::NonThreadSafe,
- public talk_base::AsyncResolverInterface {
+ public rtc::AsyncResolverInterface {
public:
AsyncAddressResolverImpl(P2PSocketDispatcher* dispatcher);
- virtual ~AsyncAddressResolverImpl();
+ ~AsyncAddressResolverImpl() override;
- // talk_base::AsyncResolverInterface interface.
- virtual void Start(const talk_base::SocketAddress& addr) OVERRIDE;
- virtual bool GetResolvedAddress(
- int family, talk_base::SocketAddress* addr) const OVERRIDE;
- virtual int GetError() const OVERRIDE;
- virtual void Destroy(bool wait) OVERRIDE;
+ // rtc::AsyncResolverInterface interface.
+ void Start(const rtc::SocketAddress& addr) override;
+ bool GetResolvedAddress(int family, rtc::SocketAddress* addr) const override;
+ int GetError() const override;
+ void Destroy(bool wait) override;
private:
virtual void OnAddressResolved(const net::IPAddressList& addresses);
scoped_refptr<P2PAsyncAddressResolver> resolver_;
int port_; // Port number in |addr| from Start() method.
- std::vector<talk_base::IPAddress> addresses_; // Resolved addresses.
+ std::vector<rtc::IPAddress> addresses_; // Resolved addresses.
};
IpcPacketSocket::IpcPacketSocket()
@@ -194,7 +210,11 @@ IpcPacketSocket::IpcPacketSocket()
state_(IS_UNINITIALIZED),
send_bytes_available_(kMaximumInFlightBytes),
writable_signal_expected_(false),
- error_(0) {
+ error_(0),
+ max_discard_bytes_sequence_(0),
+ current_discard_bytes_sequence_(0),
+ packets_discarded_(0),
+ total_packets_(0) {
COMPILE_ASSERT(kMaximumInFlightBytes > 0, would_send_at_zero_rate);
std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX),
kDefaultNonSetOptionValue);
@@ -205,6 +225,14 @@ IpcPacketSocket::~IpcPacketSocket() {
state_ == IS_ERROR) {
Close();
}
+
+ UMA_HISTOGRAM_COUNTS_10000("WebRTC.ApplicationMaxConsecutiveBytesDiscard",
+ max_discard_bytes_sequence_);
+
+ if (total_packets_ > 0) {
+ UMA_HISTOGRAM_PERCENTAGE("WebRTC.ApplicationPercentPacketsDiscarded",
+ (packets_discarded_ * 100) / total_packets_);
+ }
}
void IpcPacketSocket::TraceSendThrottlingState() const {
@@ -214,10 +242,19 @@ void IpcPacketSocket::TraceSendThrottlingState() const {
in_flight_packet_sizes_.size());
}
+void IpcPacketSocket::IncrementDiscardCounters(size_t bytes_discarded) {
+ current_discard_bytes_sequence_ += bytes_discarded;
+ packets_discarded_++;
+
+ if (current_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
+ max_discard_bytes_sequence_ = current_discard_bytes_sequence_;
+ }
+}
+
bool IpcPacketSocket::Init(P2PSocketType type,
P2PSocketClientImpl* client,
- const talk_base::SocketAddress& local_address,
- const talk_base::SocketAddress& remote_address) {
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
DCHECK_EQ(state_, IS_UNINITIALIZED);
@@ -234,10 +271,18 @@ bool IpcPacketSocket::Init(P2PSocketType type,
}
net::IPEndPoint remote_endpoint;
- if (!remote_address.IsNil() &&
- !jingle_glue::SocketAddressToIPEndPoint(
- remote_address, &remote_endpoint)) {
- return false;
+ if (!remote_address.IsNil()) {
+ DCHECK(IsTcpClientSocket(type_));
+
+ if (remote_address.IsUnresolvedIP()) {
+ remote_endpoint =
+ net::IPEndPoint(net::IPAddressNumber(), remote_address.port());
+ } else {
+ if (!jingle_glue::SocketAddressToIPEndPoint(remote_address,
+ &remote_endpoint)) {
+ return false;
+ }
+ }
}
// We need to send both resolved and unresolved address in Init. Unresolved
@@ -252,8 +297,8 @@ bool IpcPacketSocket::Init(P2PSocketType type,
void IpcPacketSocket::InitAcceptedTcp(
P2PSocketClient* client,
- const talk_base::SocketAddress& local_address,
- const talk_base::SocketAddress& remote_address) {
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
DCHECK_EQ(state_, IS_UNINITIALIZED);
@@ -265,26 +310,26 @@ void IpcPacketSocket::InitAcceptedTcp(
client_->SetDelegate(this);
}
-// talk_base::AsyncPacketSocket interface.
-talk_base::SocketAddress IpcPacketSocket::GetLocalAddress() const {
+// rtc::AsyncPacketSocket interface.
+rtc::SocketAddress IpcPacketSocket::GetLocalAddress() const {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
return local_address_;
}
-talk_base::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
+rtc::SocketAddress IpcPacketSocket::GetRemoteAddress() const {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
return remote_address_;
}
int IpcPacketSocket::Send(const void *data, size_t data_size,
- const talk_base::PacketOptions& options) {
+ const rtc::PacketOptions& options) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
return SendTo(data, data_size, remote_address_, options);
}
int IpcPacketSocket::SendTo(const void *data, size_t data_size,
- const talk_base::SocketAddress& address,
- const talk_base::PacketOptions& options) {
+ const rtc::SocketAddress& address,
+ const rtc::PacketOptions& options) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
switch (state_) {
@@ -307,6 +352,8 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
return 0;
}
+ total_packets_++;
+
if (data_size > send_bytes_available_) {
TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
TRACE_EVENT_SCOPE_THREAD,
@@ -321,11 +368,17 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
}
error_ = EWOULDBLOCK;
+ IncrementDiscardCounters(data_size);
return -1;
+ } else {
+ current_discard_bytes_sequence_ = 0;
}
net::IPEndPoint address_chrome;
if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
+ VLOG(1) << "Failed to convert remote address to IPEndPoint: address = "
+ << address.ToSensitiveString() << ", remote_address_ = "
+ << remote_address_.ToSensitiveString();
NOTREACHED();
error_ = EINVAL;
return -1;
@@ -352,7 +405,7 @@ int IpcPacketSocket::Close() {
return 0;
}
-talk_base::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
+rtc::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
switch (state_) {
@@ -379,7 +432,7 @@ talk_base::AsyncPacketSocket::State IpcPacketSocket::GetState() const {
return STATE_CLOSED;
}
-int IpcPacketSocket::GetOption(talk_base::Socket::Option option, int* value) {
+int IpcPacketSocket::GetOption(rtc::Socket::Option option, int* value) {
P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
if (!JingleSocketOptionToP2PSocketOption(option, &p2p_socket_option)) {
// unsupported option.
@@ -390,7 +443,7 @@ int IpcPacketSocket::GetOption(talk_base::Socket::Option option, int* value) {
return 0;
}
-int IpcPacketSocket::SetOption(talk_base::Socket::Option option, int value) {
+int IpcPacketSocket::SetOption(rtc::Socket::Option option, int value) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
P2PSocketOption p2p_socket_option = P2P_SOCKET_OPT_MAX;
@@ -426,10 +479,11 @@ void IpcPacketSocket::SetError(int error) {
error_ = error;
}
-void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) {
+void IpcPacketSocket::OnOpen(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
- if (!jingle_glue::IPEndPointToSocketAddress(address, &local_address_)) {
+ if (!jingle_glue::IPEndPointToSocketAddress(local_address, &local_address_)) {
// Always expect correct IPv4 address to be allocated.
NOTREACHED();
OnError();
@@ -446,8 +500,24 @@ void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) {
}
SignalAddressReady(this, local_address_);
- if (IsTcpClientSocket(type_))
+ if (IsTcpClientSocket(type_)) {
+ // If remote address is unresolved, set resolved remote IP address received
+ // in the callback. This address will be used while sending the packets
+ // over the network.
+ if (remote_address_.IsUnresolvedIP()) {
+ rtc::SocketAddress jingle_socket_address;
+ if (!jingle_glue::IPEndPointToSocketAddress(
+ remote_address, &jingle_socket_address)) {
+ NOTREACHED();
+ }
+ // Set only the IP address.
+ remote_address_.SetResolvedIP(jingle_socket_address.ipaddr());
+ }
+
+ // SignalConnect after updating the |remote_address_| so that the listener
+ // can get the resolved remote address.
SignalConnect(this);
+ }
}
void IpcPacketSocket::OnIncomingTcpConnection(
@@ -457,7 +527,7 @@ void IpcPacketSocket::OnIncomingTcpConnection(
scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
- talk_base::SocketAddress remote_address;
+ rtc::SocketAddress remote_address;
if (!jingle_glue::IPEndPointToSocketAddress(address, &remote_address)) {
// Always expect correct IPv4 address to be allocated.
NOTREACHED();
@@ -502,7 +572,7 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
const base::TimeTicks& timestamp) {
DCHECK_EQ(base::MessageLoop::current(), message_loop_);
- talk_base::SocketAddress address_lj;
+ rtc::SocketAddress address_lj;
if (!jingle_glue::IPEndPointToSocketAddress(address, &address_lj)) {
// We should always be able to convert address here because we
// don't expect IPv6 address on IPv4 connections.
@@ -510,7 +580,7 @@ void IpcPacketSocket::OnDataReceived(const net::IPEndPoint& address,
return;
}
- talk_base::PacketTime packet_time(timestamp.ToInternalValue(), 0);
+ rtc::PacketTime packet_time(timestamp.ToInternalValue(), 0);
SignalReadPacket(this, &data[0], data.size(), address_lj,
packet_time);
}
@@ -523,7 +593,7 @@ AsyncAddressResolverImpl::AsyncAddressResolverImpl(
AsyncAddressResolverImpl::~AsyncAddressResolverImpl() {
}
-void AsyncAddressResolverImpl::Start(const talk_base::SocketAddress& addr) {
+void AsyncAddressResolverImpl::Start(const rtc::SocketAddress& addr) {
DCHECK(CalledOnValidThread());
// Copy port number from |addr|. |port_| must be copied
// when resolved address is returned in GetResolvedAddress.
@@ -535,7 +605,7 @@ void AsyncAddressResolverImpl::Start(const talk_base::SocketAddress& addr) {
}
bool AsyncAddressResolverImpl::GetResolvedAddress(
- int family, talk_base::SocketAddress* addr) const {
+ int family, rtc::SocketAddress* addr) const {
DCHECK(CalledOnValidThread());
if (addresses_.empty())
@@ -568,7 +638,7 @@ void AsyncAddressResolverImpl::OnAddressResolved(
const net::IPAddressList& addresses) {
DCHECK(CalledOnValidThread());
for (size_t i = 0; i < addresses.size(); ++i) {
- talk_base::SocketAddress socket_address;
+ rtc::SocketAddress socket_address;
if (!jingle_glue::IPEndPointToSocketAddress(
net::IPEndPoint(addresses[i], 0), &socket_address)) {
NOTREACHED();
@@ -588,54 +658,54 @@ IpcPacketSocketFactory::IpcPacketSocketFactory(
IpcPacketSocketFactory::~IpcPacketSocketFactory() {
}
-talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
- const talk_base::SocketAddress& local_address, int min_port, int max_port) {
- talk_base::SocketAddress crome_address;
+rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateUdpSocket(
+ const rtc::SocketAddress& local_address, uint16 min_port, uint16 max_port) {
+ rtc::SocketAddress crome_address;
P2PSocketClientImpl* socket_client =
new P2PSocketClientImpl(socket_dispatcher_);
scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
// TODO(sergeyu): Respect local_address and port limits here (need
// to pass them over IPC channel to the browser).
if (!socket->Init(P2P_SOCKET_UDP, socket_client,
- local_address, talk_base::SocketAddress())) {
+ local_address, rtc::SocketAddress())) {
return NULL;
}
return socket.release();
}
-talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
- const talk_base::SocketAddress& local_address, int min_port, int max_port,
+rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateServerTcpSocket(
+ const rtc::SocketAddress& local_address, uint16 min_port, uint16 max_port,
int opts) {
// TODO(sergeyu): Implement SSL support.
- if (opts & talk_base::PacketSocketFactory::OPT_SSLTCP)
+ if (opts & rtc::PacketSocketFactory::OPT_SSLTCP)
return NULL;
- P2PSocketType type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ?
+ P2PSocketType type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
P2P_SOCKET_STUN_TCP_SERVER : P2P_SOCKET_TCP_SERVER;
P2PSocketClientImpl* socket_client =
new P2PSocketClientImpl(socket_dispatcher_);
scoped_ptr<IpcPacketSocket> socket(new IpcPacketSocket());
if (!socket->Init(type, socket_client, local_address,
- talk_base::SocketAddress())) {
+ rtc::SocketAddress())) {
return NULL;
}
return socket.release();
}
-talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
- const talk_base::SocketAddress& local_address,
- const talk_base::SocketAddress& remote_address,
- const talk_base::ProxyInfo& proxy_info,
+rtc::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address,
+ const rtc::ProxyInfo& proxy_info,
const std::string& user_agent, int opts) {
P2PSocketType type;
- if (opts & talk_base::PacketSocketFactory::OPT_SSLTCP) {
- type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ?
+ if (opts & rtc::PacketSocketFactory::OPT_SSLTCP) {
+ type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
P2P_SOCKET_STUN_SSLTCP_CLIENT : P2P_SOCKET_SSLTCP_CLIENT;
- } else if (opts & talk_base::PacketSocketFactory::OPT_TLS) {
- type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ?
+ } else if (opts & rtc::PacketSocketFactory::OPT_TLS) {
+ type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
P2P_SOCKET_STUN_TLS_CLIENT : P2P_SOCKET_TLS_CLIENT;
} else {
- type = (opts & talk_base::PacketSocketFactory::OPT_STUN) ?
+ type = (opts & rtc::PacketSocketFactory::OPT_STUN) ?
P2P_SOCKET_STUN_TCP_CLIENT : P2P_SOCKET_TCP_CLIENT;
}
P2PSocketClientImpl* socket_client =
@@ -646,7 +716,7 @@ talk_base::AsyncPacketSocket* IpcPacketSocketFactory::CreateClientTcpSocket(
return socket.release();
}
-talk_base::AsyncResolverInterface*
+rtc::AsyncResolverInterface*
IpcPacketSocketFactory::CreateAsyncResolver() {
scoped_ptr<AsyncAddressResolverImpl> resolver(
new AsyncAddressResolverImpl(socket_dispatcher_));
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.h b/chromium/content/renderer/p2p/ipc_socket_factory.h
index cba98b3c0d0..157032216c9 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.h
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.h
@@ -8,39 +8,40 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/p2p/base/packetsocketfactory.h"
+#include "third_party/webrtc/p2p/base/packetsocketfactory.h"
namespace content {
class P2PSocketDispatcher;
-// IpcPacketSocketFactory implements talk_base::PacketSocketFactory
+// IpcPacketSocketFactory implements rtc::PacketSocketFactory
// interface for libjingle using IPC-based P2P sockets. The class must
// be used on a thread that is a libjingle thread (implements
-// talk_base::Thread) and also has associated base::MessageLoop. Each
+// rtc::Thread) and also has associated base::MessageLoop. Each
// socket created by the factory must be used on the thread it was
// created on.
-class IpcPacketSocketFactory : public talk_base::PacketSocketFactory {
+class IpcPacketSocketFactory : public rtc::PacketSocketFactory {
public:
CONTENT_EXPORT explicit IpcPacketSocketFactory(
P2PSocketDispatcher* socket_dispatcher);
- virtual ~IpcPacketSocketFactory();
-
- virtual talk_base::AsyncPacketSocket* CreateUdpSocket(
- const talk_base::SocketAddress& local_address,
- int min_port, int max_port) OVERRIDE;
- virtual talk_base::AsyncPacketSocket* CreateServerTcpSocket(
- const talk_base::SocketAddress& local_address,
- int min_port,
- int max_port,
- int opts) OVERRIDE;
- virtual talk_base::AsyncPacketSocket* CreateClientTcpSocket(
- const talk_base::SocketAddress& local_address,
- const talk_base::SocketAddress& remote_address,
- const talk_base::ProxyInfo& proxy_info,
+ ~IpcPacketSocketFactory() override;
+
+ rtc::AsyncPacketSocket* CreateUdpSocket(
+ const rtc::SocketAddress& local_address,
+ uint16 min_port,
+ uint16 max_port) override;
+ rtc::AsyncPacketSocket* CreateServerTcpSocket(
+ const rtc::SocketAddress& local_address,
+ uint16 min_port,
+ uint16 max_port,
+ int opts) override;
+ rtc::AsyncPacketSocket* CreateClientTcpSocket(
+ const rtc::SocketAddress& local_address,
+ const rtc::SocketAddress& remote_address,
+ const rtc::ProxyInfo& proxy_info,
const std::string& user_agent,
- int opts) OVERRIDE;
- virtual talk_base::AsyncResolverInterface* CreateAsyncResolver() OVERRIDE;
+ int opts) override;
+ rtc::AsyncResolverInterface* CreateAsyncResolver() override;
private:
P2PSocketDispatcher* socket_dispatcher_;
diff --git a/chromium/content/renderer/p2p/network_list_manager.h b/chromium/content/renderer/p2p/network_list_manager.h
new file mode 100644
index 00000000000..c0e0f58bdae
--- /dev/null
+++ b/chromium/content/renderer/p2p/network_list_manager.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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.
+
+// NetworkListManager interface is introduced to enable unit test on
+// IpcNetworkManager such that it doesn't depend on implementation of
+// P2PSocketDispatcher.
+
+#ifndef CONTENT_RENDERER_P2P_NETWORK_LIST_MANAGER_H_
+#define CONTENT_RENDERER_P2P_NETWORK_LIST_MANAGER_H_
+
+namespace content {
+
+class NetworkListObserver;
+
+class CONTENT_EXPORT NetworkListManager {
+ public:
+ // Add a new network list observer. Each observer is called
+ // immidiately after it is registered and then later whenever
+ // network configuration changes. Can be called on any thread. The
+ // observer is always called on the thread it was added.
+ virtual void AddNetworkListObserver(
+ NetworkListObserver* network_list_observer) = 0;
+
+ // Removes network list observer. Must be called on the thread on
+ // which the observer was added.
+ virtual void RemoveNetworkListObserver(
+ NetworkListObserver* network_list_observer) = 0;
+
+ protected:
+ // Marked as protected to prevent explicit deletion, as
+ // P2PSocketDispatcher is not owned by IpcNetworkManager.
+ virtual ~NetworkListManager() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_P2P_NETWORK_LIST_MANAGER_H_
diff --git a/chromium/content/renderer/p2p/port_allocator.cc b/chromium/content/renderer/p2p/port_allocator.cc
index 61cfefd4901..7beb3ecc444 100644
--- a/chromium/content/renderer/p2p/port_allocator.cc
+++ b/chromium/content/renderer/p2p/port_allocator.cc
@@ -4,56 +4,10 @@
#include "content/renderer/p2p/port_allocator.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "content/public/common/content_switches.h"
-#include "net/base/escape.h"
-#include "net/base/ip_endpoint.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLLoader.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
-
-using blink::WebString;
-using blink::WebURL;
-using blink::WebURLLoader;
-using blink::WebURLLoaderOptions;
-using blink::WebURLRequest;
-using blink::WebURLResponse;
-
namespace content {
-namespace {
-
-// URL used to create a relay session.
-const char kCreateRelaySessionURL[] = "/create_session";
-
-// Number of times we will try to request relay session.
-const int kRelaySessionRetries = 3;
-
-// Manimum relay server size we would try to parse.
-const int kMaximumRelayResponseSize = 102400;
-
-bool ParsePortNumber(
- const std::string& string, int* value) {
- if (!base::StringToInt(string, value) || *value <= 0 || *value >= 65536) {
- LOG(ERROR) << "Received invalid port number from relay server: " << string;
- return false;
- }
- return true;
-}
-
-} // namespace
-
P2PPortAllocator::Config::Config()
- : stun_server_port(0),
- legacy_relay(true),
- disable_tcp_transport(false) {
+ : disable_tcp_transport(false) {
}
P2PPortAllocator::Config::~Config() {
@@ -67,13 +21,11 @@ P2PPortAllocator::Config::RelayServerConfig::~RelayServerConfig() {
}
P2PPortAllocator::P2PPortAllocator(
- blink::WebFrame* web_frame,
P2PSocketDispatcher* socket_dispatcher,
- talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
+ rtc::NetworkManager* network_manager,
+ rtc::PacketSocketFactory* socket_factory,
const Config& config)
: cricket::BasicPortAllocator(network_manager, socket_factory),
- web_frame_(web_frame),
socket_dispatcher_(socket_dispatcher),
config_(config) {
uint32 flags = 0;
@@ -101,166 +53,21 @@ P2PPortAllocatorSession::P2PPortAllocatorSession(
int component,
const std::string& ice_username_fragment,
const std::string& ice_password)
- : cricket::BasicPortAllocatorSession(
- allocator, content_name, component,
- ice_username_fragment, ice_password),
- allocator_(allocator),
- relay_session_attempts_(0),
- relay_udp_port_(0),
- relay_tcp_port_(0),
- relay_ssltcp_port_(0),
- pending_relay_requests_(0) {
+ : cricket::BasicPortAllocatorSession(allocator,
+ content_name,
+ component,
+ ice_username_fragment,
+ ice_password),
+ allocator_(allocator) {
}
P2PPortAllocatorSession::~P2PPortAllocatorSession() {
}
-void P2PPortAllocatorSession::didReceiveData(
- WebURLLoader* loader, const char* data,
- int data_length, int encoded_data_length) {
- DCHECK_EQ(loader, relay_session_request_.get());
- if (static_cast<int>(relay_session_response_.size()) + data_length >
- kMaximumRelayResponseSize) {
- LOG(ERROR) << "Response received from the server is too big.";
- loader->cancel();
- return;
- }
- relay_session_response_.append(data, data + data_length);
-}
-
-void P2PPortAllocatorSession::didFinishLoading(
- WebURLLoader* loader, double finish_time,
- int64_t total_encoded_data_length) {
- ParseRelayResponse();
-}
-
-void P2PPortAllocatorSession::didFail(blink::WebURLLoader* loader,
- const blink::WebURLError& error) {
- DCHECK_EQ(loader, relay_session_request_.get());
- DCHECK_NE(error.reason, 0);
-
- LOG(ERROR) << "Relay session request failed.";
-
- // Retry the request.
- AllocateLegacyRelaySession();
-}
-
void P2PPortAllocatorSession::GetPortConfigurations() {
- if (allocator_->config_.legacy_relay) {
- AllocateLegacyRelaySession();
- }
- AddConfig();
-}
-
-void P2PPortAllocatorSession::AllocateLegacyRelaySession() {
- if (allocator_->config_.relays.empty())
- return;
- // If we are using legacy relay, we will have only one entry in relay server
- // list.
- P2PPortAllocator::Config::RelayServerConfig relay_config =
- allocator_->config_.relays[0];
-
- if (relay_session_attempts_ > kRelaySessionRetries)
- return;
- relay_session_attempts_++;
-
- relay_session_response_.clear();
-
- WebURLLoaderOptions options;
- options.allowCredentials = false;
-
- options.crossOriginRequestPolicy =
- WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl;
-
- relay_session_request_.reset(
- allocator_->web_frame_->createAssociatedURLLoader(options));
- if (!relay_session_request_) {
- LOG(ERROR) << "Failed to create URL loader.";
- return;
- }
-
- std::string url = "https://" + relay_config.server_address +
- kCreateRelaySessionURL +
- "?username=" + net::EscapeUrlEncodedData(username(), true) +
- "&password=" + net::EscapeUrlEncodedData(password(), true);
-
- WebURLRequest request;
- request.initialize();
- request.setURL(WebURL(GURL(url)));
- request.setAllowStoredCredentials(false);
- request.setCachePolicy(WebURLRequest::ReloadIgnoringCacheData);
- request.setHTTPMethod("GET");
- request.addHTTPHeaderField(
- WebString::fromUTF8("X-Talk-Google-Relay-Auth"),
- WebString::fromUTF8(relay_config.password));
- request.addHTTPHeaderField(
- WebString::fromUTF8("X-Google-Relay-Auth"),
- WebString::fromUTF8(relay_config.username));
- request.addHTTPHeaderField(WebString::fromUTF8("X-Stream-Type"),
- WebString::fromUTF8("chromoting"));
-
- relay_session_request_->loadAsynchronously(request, this);
-}
-
-void P2PPortAllocatorSession::ParseRelayResponse() {
- std::vector<std::pair<std::string, std::string> > value_pairs;
- if (!base::SplitStringIntoKeyValuePairs(relay_session_response_, '=', '\n',
- &value_pairs)) {
- LOG(ERROR) << "Received invalid response from relay server";
- return;
- }
-
- relay_ip_.Clear();
- relay_udp_port_ = 0;
- relay_tcp_port_ = 0;
- relay_ssltcp_port_ = 0;
-
- for (std::vector<std::pair<std::string, std::string> >::iterator
- it = value_pairs.begin();
- it != value_pairs.end(); ++it) {
- std::string key;
- std::string value;
- base::TrimWhitespaceASCII(it->first, base::TRIM_ALL, &key);
- base::TrimWhitespaceASCII(it->second, base::TRIM_ALL, &value);
-
- if (key == "username") {
- if (value != username()) {
- LOG(ERROR) << "When creating relay session received user name "
- " that was different from the value specified in the query.";
- return;
- }
- } else if (key == "password") {
- if (value != password()) {
- LOG(ERROR) << "When creating relay session received password "
- "that was different from the value specified in the query.";
- return;
- }
- } else if (key == "relay.ip") {
- relay_ip_.SetIP(value);
- if (relay_ip_.ip() == 0) {
- LOG(ERROR) << "Received unresolved relay server address: " << value;
- return;
- }
- } else if (key == "relay.udp_port") {
- if (!ParsePortNumber(value, &relay_udp_port_))
- return;
- } else if (key == "relay.tcp_port") {
- if (!ParsePortNumber(value, &relay_tcp_port_))
- return;
- } else if (key == "relay.ssltcp_port") {
- if (!ParsePortNumber(value, &relay_ssltcp_port_))
- return;
- }
- }
-
- AddConfig();
-}
-
-void P2PPortAllocatorSession::AddConfig() {
const P2PPortAllocator::Config& config = allocator_->config_;
cricket::PortConfiguration* port_config = new cricket::PortConfiguration(
- talk_base::SocketAddress(config.stun_server, config.stun_server_port),
- std::string(), std::string());
+ config.stun_servers, std::string(), std::string());
for (size_t i = 0; i < config.relays.size(); ++i) {
cricket::RelayCredentials credentials(config.relays[i].username,
@@ -278,7 +85,7 @@ void P2PPortAllocatorSession::AddConfig() {
}
relay_server.ports.push_back(cricket::ProtocolAddress(
- talk_base::SocketAddress(config.relays[i].server_address,
+ rtc::SocketAddress(config.relays[i].server_address,
config.relays[i].port),
protocol,
config.relays[i].secure));
diff --git a/chromium/content/renderer/p2p/port_allocator.h b/chromium/content/renderer/p2p/port_allocator.h
index 8ff20a546f0..3cb1377a1de 100644
--- a/chromium/content/renderer/p2p/port_allocator.h
+++ b/chromium/content/renderer/p2p/port_allocator.h
@@ -5,26 +5,13 @@
#ifndef CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
#define CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/net_util.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h"
-
-namespace blink {
-class WebFrame;
-class WebURLLoader;
-} // namespace blink
+#include "third_party/webrtc/p2p/client/basicportallocator.h"
namespace content {
-class P2PHostAddressRequest;
class P2PPortAllocatorSession;
class P2PSocketDispatcher;
-// TODO(sergeyu): There is overlap between this class and HttpPortAllocator.
-// Refactor this class to inherit from HttpPortAllocator to avoid code
-// duplication.
class P2PPortAllocator : public cricket::BasicPortAllocator {
public:
struct Config {
@@ -43,42 +30,36 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
bool secure;
};
- // STUN server address and port.
- std::string stun_server;
- int stun_server_port;
+ std::set<rtc::SocketAddress> stun_servers;
std::vector<RelayServerConfig> relays;
- bool legacy_relay;
// Disable TCP-based transport when set to true.
bool disable_tcp_transport;
};
- P2PPortAllocator(blink::WebFrame* web_frame,
- P2PSocketDispatcher* socket_dispatcher,
- talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
+ P2PPortAllocator(P2PSocketDispatcher* socket_dispatcher,
+ rtc::NetworkManager* network_manager,
+ rtc::PacketSocketFactory* socket_factory,
const Config& config);
- virtual ~P2PPortAllocator();
+ ~P2PPortAllocator() override;
- virtual cricket::PortAllocatorSession* CreateSessionInternal(
+ cricket::PortAllocatorSession* CreateSessionInternal(
const std::string& content_name,
int component,
const std::string& ice_username_fragment,
- const std::string& ice_password) OVERRIDE;
+ const std::string& ice_password) override;
private:
friend class P2PPortAllocatorSession;
- blink::WebFrame* web_frame_;
P2PSocketDispatcher* socket_dispatcher_;
Config config_;
DISALLOW_COPY_AND_ASSIGN(P2PPortAllocator);
};
-class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession,
- public blink::WebURLLoaderClient {
+class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession {
public:
P2PPortAllocatorSession(
P2PPortAllocator* allocator,
@@ -86,41 +67,15 @@ class P2PPortAllocatorSession : public cricket::BasicPortAllocatorSession,
int component,
const std::string& ice_username_fragment,
const std::string& ice_password);
- virtual ~P2PPortAllocatorSession();
-
- // blink::WebURLLoaderClient overrides.
- virtual void didReceiveData(blink::WebURLLoader* loader,
- const char* data,
- int data_length,
- int encoded_data_length) OVERRIDE;
- virtual void didFinishLoading(blink::WebURLLoader* loader,
- double finish_time,
- int64_t total_encoded_data_length) OVERRIDE;
- virtual void didFail(blink::WebURLLoader* loader,
- const blink::WebURLError& error) OVERRIDE;
+ ~P2PPortAllocatorSession() override;
protected:
// Overrides for cricket::BasicPortAllocatorSession.
- virtual void GetPortConfigurations() OVERRIDE;
+ void GetPortConfigurations() override;
private:
- // This method allocates non-TURN relay sessions.
- void AllocateLegacyRelaySession();
- void ParseRelayResponse();
-
- void AddConfig();
-
P2PPortAllocator* allocator_;
- scoped_ptr<blink::WebURLLoader> relay_session_request_;
- int relay_session_attempts_;
- std::string relay_session_response_;
- talk_base::SocketAddress relay_ip_;
- int relay_udp_port_;
- int relay_tcp_port_;
- int relay_ssltcp_port_;
- int pending_relay_requests_;
-
DISALLOW_COPY_AND_ASSIGN(P2PPortAllocatorSession);
};
diff --git a/chromium/content/renderer/p2p/socket_client.h b/chromium/content/renderer/p2p/socket_client.h
index 5d1ecb5db90..d92407cd5c9 100644
--- a/chromium/content/renderer/p2p/socket_client.h
+++ b/chromium/content/renderer/p2p/socket_client.h
@@ -11,7 +11,7 @@
#include "content/common/p2p_socket_type.h"
#include "net/base/ip_endpoint.h"
-namespace talk_base {
+namespace rtc {
struct PacketOptions;
};
@@ -44,7 +44,7 @@ class P2PSocketClient : public base::RefCountedThreadSafe<P2PSocketClient> {
// |dscp|.
virtual void SendWithDscp(const net::IPEndPoint& address,
const std::vector<char>& data,
- const talk_base::PacketOptions& options) = 0;
+ const rtc::PacketOptions& options) = 0;
virtual void SetOption(P2PSocketOption option, int value) = 0;
diff --git a/chromium/content/renderer/p2p/socket_client_delegate.h b/chromium/content/renderer/p2p/socket_client_delegate.h
index c3794636a33..204d5cd4aab 100644
--- a/chromium/content/renderer/p2p/socket_client_delegate.h
+++ b/chromium/content/renderer/p2p/socket_client_delegate.h
@@ -22,7 +22,8 @@ class P2PSocketClientDelegate {
// Called after the socket has been opened with the local endpoint address
// as argument. Please note that in the precence of multiple interfaces,
// you should not rely on the local endpoint address if possible.
- virtual void OnOpen(const net::IPEndPoint& address) = 0;
+ virtual void OnOpen(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) = 0;
// For a socket that is listening on incoming TCP connectsion, this
// function is called when a new client connects.
diff --git a/chromium/content/renderer/p2p/socket_client_impl.cc b/chromium/content/renderer/p2p/socket_client_impl.cc
index ee7929d34ff..1425151089c 100644
--- a/chromium/content/renderer/p2p/socket_client_impl.cc
+++ b/chromium/content/renderer/p2p/socket_client_impl.cc
@@ -72,7 +72,7 @@ void P2PSocketClientImpl::DoInit(P2PSocketType type,
void P2PSocketClientImpl::SendWithDscp(
const net::IPEndPoint& address,
const std::vector<char>& data,
- const talk_base::PacketOptions& options) {
+ const rtc::PacketOptions& options) {
if (!ipc_message_loop_->BelongsToCurrentThread()) {
ipc_message_loop_->PostTask(
FROM_HERE, base::Bind(
@@ -92,7 +92,7 @@ void P2PSocketClientImpl::SendWithDscp(
void P2PSocketClientImpl::Send(const net::IPEndPoint& address,
const std::vector<char>& data) {
- talk_base::PacketOptions options(talk_base::DSCP_DEFAULT);
+ rtc::PacketOptions options(rtc::DSCP_DEFAULT);
SendWithDscp(address, data, options);
}
@@ -143,21 +143,25 @@ void P2PSocketClientImpl::SetDelegate(P2PSocketClientDelegate* delegate) {
delegate_ = delegate;
}
-void P2PSocketClientImpl::OnSocketCreated(const net::IPEndPoint& address) {
+void P2PSocketClientImpl::OnSocketCreated(
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
DCHECK(ipc_message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, STATE_OPENING);
state_ = STATE_OPEN;
delegate_message_loop_->PostTask(
FROM_HERE,
- base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated, this, address));
+ base::Bind(&P2PSocketClientImpl::DeliverOnSocketCreated, this,
+ local_address, remote_address));
}
void P2PSocketClientImpl::DeliverOnSocketCreated(
- const net::IPEndPoint& address) {
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
DCHECK(delegate_message_loop_->BelongsToCurrentThread());
if (delegate_)
- delegate_->OnOpen(address);
+ delegate_->OnOpen(local_address, remote_address);
}
void P2PSocketClientImpl::OnIncomingTcpConnection(
diff --git a/chromium/content/renderer/p2p/socket_client_impl.h b/chromium/content/renderer/p2p/socket_client_impl.h
index fb4703d73a7..4cda52ddb87 100644
--- a/chromium/content/renderer/p2p/socket_client_impl.h
+++ b/chromium/content/renderer/p2p/socket_client_impl.h
@@ -40,25 +40,25 @@ class P2PSocketClientImpl : public P2PSocketClient {
P2PSocketClientDelegate* delegate);
// Send the |data| to the |address|.
- virtual void Send(const net::IPEndPoint& address,
- const std::vector<char>& data) OVERRIDE;
+ void Send(const net::IPEndPoint& address,
+ const std::vector<char>& data) override;
// Send the |data| to the |address| using Differentiated Services Code Point
// |dscp|.
- virtual void SendWithDscp(const net::IPEndPoint& address,
- const std::vector<char>& data,
- const talk_base::PacketOptions& options) OVERRIDE;
+ void SendWithDscp(const net::IPEndPoint& address,
+ const std::vector<char>& data,
+ const rtc::PacketOptions& options) override;
// Setting socket options.
- virtual void SetOption(P2PSocketOption option, int value) OVERRIDE;
+ void SetOption(P2PSocketOption option, int value) override;
// Must be called before the socket is destroyed. The delegate may
// not be called after |closed_task| is executed.
- virtual void Close() OVERRIDE;
+ void Close() override;
- virtual int GetSocketID() const OVERRIDE;
+ int GetSocketID() const override;
- virtual void SetDelegate(P2PSocketClientDelegate* delegate) OVERRIDE;
+ void SetDelegate(P2PSocketClientDelegate* delegate) override;
private:
enum State {
@@ -71,10 +71,11 @@ class P2PSocketClientImpl : public P2PSocketClient {
friend class P2PSocketDispatcher;
- virtual ~P2PSocketClientImpl();
+ ~P2PSocketClientImpl() override;
// Message handlers that run on IPC thread.
- void OnSocketCreated(const net::IPEndPoint& address);
+ void OnSocketCreated(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address);
void OnIncomingTcpConnection(const net::IPEndPoint& address);
void OnSendComplete(int packet_id);
void OnSendComplete();
@@ -84,7 +85,8 @@ class P2PSocketClientImpl : public P2PSocketClient {
const base::TimeTicks& timestamp);
// Proxy methods that deliver messages to the delegate thread.
- void DeliverOnSocketCreated(const net::IPEndPoint& address);
+ void DeliverOnSocketCreated(const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address);
void DeliverOnIncomingTcpConnection(
const net::IPEndPoint& address,
scoped_refptr<P2PSocketClient> new_client);
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.cc b/chromium/content/renderer/p2p/socket_dispatcher.cc
index fd8aaf93ee2..f189354478a 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.cc
+++ b/chromium/content/renderer/p2p/socket_dispatcher.cc
@@ -139,10 +139,12 @@ void P2PSocketDispatcher::OnGetHostAddressResult(
}
void P2PSocketDispatcher::OnSocketCreated(
- int socket_id, const net::IPEndPoint& address) {
+ int socket_id,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address) {
P2PSocketClientImpl* client = GetClient(socket_id);
if (client) {
- client->OnSocketCreated(address);
+ client->OnSocketCreated(local_address, remote_address);
}
}
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.h b/chromium/content/renderer/p2p/socket_dispatcher.h
index b0e9b299f30..69cb21f5359 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.h
+++ b/chromium/content/renderer/p2p/socket_dispatcher.h
@@ -30,6 +30,7 @@
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/common/p2p_socket_type.h"
+#include "content/renderer/p2p/network_list_manager.h"
#include "ipc/message_filter.h"
#include "net/base/net_util.h"
@@ -48,22 +49,19 @@ class P2PAsyncAddressResolver;
class P2PSocketClientImpl;
class RenderViewImpl;
-class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter {
+class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter,
+ public NetworkListManager {
public:
explicit P2PSocketDispatcher(base::MessageLoopProxy* ipc_message_loop);
- // Add a new network list observer. Each observer is called
- // immidiately after it is registered and then later whenever
- // network configuration changes. Can be called on any thread. The
- // observer is always called on the thread it was added.
- void AddNetworkListObserver(NetworkListObserver* network_list_observer);
-
- // Removes network list observer. Must be called on the thread on
- // which the observer was added.
- void RemoveNetworkListObserver(NetworkListObserver* network_list_observer);
+ // NetworkListManager interface:
+ void AddNetworkListObserver(
+ NetworkListObserver* network_list_observer) override;
+ void RemoveNetworkListObserver(
+ NetworkListObserver* network_list_observer) override;
protected:
- virtual ~P2PSocketDispatcher();
+ ~P2PSocketDispatcher() override;
private:
friend class P2PAsyncAddressResolver;
@@ -73,10 +71,10 @@ class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter {
virtual void Send(IPC::Message* message);
// IPC::MessageFilter override. Called on IO thread.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelClosing() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelClosing() override;
// Returns the IO message loop.
base::MessageLoopProxy* message_loop();
@@ -94,7 +92,9 @@ class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter {
void OnNetworkListChanged(const net::NetworkInterfaceList& networks);
void OnGetHostAddressResult(int32 request_id,
const net::IPAddressList& addresses);
- void OnSocketCreated(int socket_id, const net::IPEndPoint& address);
+ void OnSocketCreated(int socket_id,
+ const net::IPEndPoint& local_address,
+ const net::IPEndPoint& remote_address);
void OnIncomingTcpConnection(int socket_id, const net::IPEndPoint& address);
void OnSendComplete(int socket_id);
void OnError(int socket_id);
diff --git a/chromium/content/renderer/pepper/OWNERS b/chromium/content/renderer/pepper/OWNERS
index ddbd3b66d38..084010f0221 100644
--- a/chromium/content/renderer/pepper/OWNERS
+++ b/chromium/content/renderer/pepper/OWNERS
@@ -2,7 +2,6 @@ bbudge@chromium.org
dmichael@chromium.org
raymes@chromium.org
teravest@chromium.org
-yzshen@chromium.org
per-file usb_key_code_*=garykac@chromium.org
per-file usb_key_code_*=wez@chromium.org
diff --git a/chromium/content/renderer/pepper/audio_helper.cc b/chromium/content/renderer/pepper/audio_helper.cc
index 2ce1ae44d64..ad6e8f87583 100644
--- a/chromium/content/renderer/pepper/audio_helper.cc
+++ b/chromium/content/renderer/pepper/audio_helper.cc
@@ -5,7 +5,6 @@
#include "content/renderer/pepper/audio_helper.h"
#include "base/logging.h"
-#include "content/renderer/pepper/common.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
diff --git a/chromium/content/renderer/pepper/common.h b/chromium/content/renderer/pepper/common.h
deleted file mode 100644
index 02df9ef6ac8..00000000000
--- a/chromium/content/renderer/pepper/common.h
+++ /dev/null
@@ -1,19 +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 CONTENT_RENDERER_PEPPER_COMMON_H_
-#define CONTENT_RENDERER_PEPPER_COMMON_H_
-
-#include "ppapi/c/pp_bool.h"
-#include "ppapi/c/pp_var.h"
-
-namespace content {
-
-inline PP_Bool BoolToPPBool(bool value) { return value ? PP_TRUE : PP_FALSE; }
-
-inline bool PPBoolToBool(PP_Bool value) { return (PP_TRUE == value); }
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_COMMON_H_
diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.cc b/chromium/content/renderer/pepper/content_decryptor_delegate.cc
index 8692c1ce643..ded599bf2f3 100644
--- a/chromium/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/chromium/content/renderer/pepper/content_decryptor_delegate.cc
@@ -7,7 +7,9 @@
#include "base/callback_helpers.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/numerics/safe_conversions.h"
+#include "content/renderer/media/crypto/key_systems.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
#include "media/base/audio_buffer.h"
#include "media/base/audio_decoder_config.h"
@@ -17,10 +19,13 @@
#include "media/base/data_buffer.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
+#include "media/base/limits.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
+#include "ppapi/shared_impl/array_var.h"
#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/shared_impl/time_conversion.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"
#include "ppapi/thunk/enter.h"
@@ -29,10 +34,12 @@
using media::CdmPromise;
using media::Decryptor;
+using media::KeyIdsPromise;
using media::MediaKeys;
using media::NewSessionCdmPromise;
using media::SimpleCdmPromise;
using ppapi::ArrayBufferVar;
+using ppapi::ArrayVar;
using ppapi::PpapiGlobals;
using ppapi::ScopedPPResource;
using ppapi::StringVar;
@@ -90,7 +97,7 @@ bool CopyStringToArray(const std::string& str, uint8 (&array)[array_size]) {
//
// Returns true if |block_info| is successfully filled. Returns false
// otherwise.
-static bool MakeEncryptedBlockInfo(
+bool MakeEncryptedBlockInfo(
const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
uint32_t request_id,
PP_EncryptedBlockInfo* block_info) {
@@ -161,10 +168,8 @@ PP_VideoCodec MediaVideoCodecToPpVideoCodec(media::VideoCodec codec) {
PP_VideoCodecProfile MediaVideoCodecProfileToPpVideoCodecProfile(
media::VideoCodecProfile profile) {
switch (profile) {
- // TODO(xhwang): VP8 and VP9 do not have profiles. Clean up
- // media::VideoCodecProfile and remove these two cases.
- case media::VP8PROFILE_MAIN:
- case media::VP9PROFILE_MAIN:
+ case media::VP8PROFILE_ANY:
+ case media::VP9PROFILE_ANY:
return PP_VIDEOCODECPROFILE_NOT_NEEDED;
case media::H264PROFILE_BASELINE:
return PP_VIDEOCODECPROFILE_H264_BASELINE;
@@ -286,6 +291,16 @@ MediaKeys::Exception PpExceptionTypeToMediaException(
}
}
+// TODO(xhwang): Unify EME UMA reporting code when prefixed EME is deprecated.
+// See http://crbug.com/412987 for details.
+void ReportSystemCodeUMA(const std::string& key_system, uint32 system_code) {
+ // Sparse histogram macro does not cache the histogram, so it's safe to use
+ // macro with non-static histogram name here.
+ UMA_HISTOGRAM_SPARSE_SLOWLY(
+ "Media.EME." + KeySystemNameForUMA(key_system) + ".SystemCode",
+ system_code);
+}
+
} // namespace
ContentDecryptorDelegate::ContentDecryptorDelegate(
@@ -312,6 +327,8 @@ void ContentDecryptorDelegate::Initialize(
const media::SessionReadyCB& session_ready_cb,
const media::SessionClosedCB& session_closed_cb,
const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb,
const base::Closure& fatal_plugin_error_cb) {
DCHECK(!key_system.empty());
DCHECK(key_system_.empty());
@@ -321,6 +338,8 @@ void ContentDecryptorDelegate::Initialize(
session_ready_cb_ = session_ready_cb;
session_closed_cb_ = session_closed_cb;
session_error_cb_ = session_error_cb;
+ session_keys_change_cb_ = session_keys_change_cb;
+ session_expiration_update_cb_ = session_expiration_update_cb;
fatal_plugin_error_cb_ = fatal_plugin_error_cb;
plugin_decryption_interface_->Initialize(
@@ -332,13 +351,33 @@ void ContentDecryptorDelegate::InstanceCrashed() {
SatisfyAllPendingCallbacksOnError();
}
+void ContentDecryptorDelegate::SetServerCertificate(
+ const uint8_t* certificate,
+ uint32_t certificate_length,
+ scoped_ptr<media::SimpleCdmPromise> promise) {
+ if (!certificate ||
+ certificate_length < media::limits::kMinCertificateLength ||
+ certificate_length > media::limits::kMaxCertificateLength) {
+ promise->reject(
+ media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect certificate.");
+ return;
+ }
+
+ uint32_t promise_id = SavePromise(promise.Pass());
+ PP_Var certificate_array =
+ PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
+ certificate_length, certificate);
+ plugin_decryption_interface_->SetServerCertificate(
+ pp_instance_, promise_id, certificate_array);
+}
+
void ContentDecryptorDelegate::CreateSession(
const std::string& init_data_type,
const uint8* init_data,
int init_data_length,
MediaKeys::SessionType session_type,
scoped_ptr<NewSessionCdmPromise> promise) {
- uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
+ uint32_t promise_id = SavePromise(promise.Pass());
PP_Var init_data_array =
PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
init_data_length, init_data);
@@ -353,7 +392,7 @@ void ContentDecryptorDelegate::CreateSession(
void ContentDecryptorDelegate::LoadSession(
const std::string& web_session_id,
scoped_ptr<NewSessionCdmPromise> promise) {
- uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
+ uint32_t promise_id = SavePromise(promise.Pass());
plugin_decryption_interface_->LoadSession(
pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id));
}
@@ -363,7 +402,7 @@ void ContentDecryptorDelegate::UpdateSession(
const uint8* response,
int response_length,
scoped_ptr<SimpleCdmPromise> promise) {
- uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
+ uint32_t promise_id = SavePromise(promise.Pass());
PP_Var response_array =
PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar(
response_length, response);
@@ -374,11 +413,45 @@ void ContentDecryptorDelegate::UpdateSession(
response_array);
}
-void ContentDecryptorDelegate::ReleaseSession(
+void ContentDecryptorDelegate::CloseSession(
+ const std::string& web_session_id,
+ scoped_ptr<SimpleCdmPromise> promise) {
+ if (web_session_id.length() > media::limits::kMaxWebSessionIdLength) {
+ promise->reject(
+ media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect session.");
+ return;
+ }
+
+ uint32_t promise_id = SavePromise(promise.Pass());
+ plugin_decryption_interface_->CloseSession(
+ pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id));
+}
+
+void ContentDecryptorDelegate::RemoveSession(
const std::string& web_session_id,
scoped_ptr<SimpleCdmPromise> promise) {
- uint32_t promise_id = SavePromise(promise.PassAs<CdmPromise>());
- plugin_decryption_interface_->ReleaseSession(
+ if (web_session_id.length() > media::limits::kMaxWebSessionIdLength) {
+ promise->reject(
+ media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect session.");
+ return;
+ }
+
+ uint32_t promise_id = SavePromise(promise.Pass());
+ plugin_decryption_interface_->RemoveSession(
+ pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id));
+}
+
+void ContentDecryptorDelegate::GetUsableKeyIds(
+ const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise) {
+ if (web_session_id.length() > media::limits::kMaxWebSessionIdLength) {
+ promise->reject(
+ media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect session.");
+ return;
+ }
+
+ uint32_t promise_id = SavePromise(promise.Pass());
+ plugin_decryption_interface_->GetUsableKeyIds(
pp_instance_, promise_id, StringVar::StringToPPVar(web_session_id));
}
@@ -627,26 +700,70 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
void ContentDecryptorDelegate::OnPromiseResolved(uint32 promise_id) {
scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
- if (promise) {
- SimpleCdmPromise* simple_promise(
- static_cast<SimpleCdmPromise*>(promise.get()));
- simple_promise->resolve();
+ if (!promise ||
+ promise->GetResolveParameterType() != media::CdmPromise::VOID_TYPE) {
+ NOTREACHED();
+ return;
}
+
+ SimpleCdmPromise* simple_promise =
+ static_cast<SimpleCdmPromise*>(promise.get());
+ simple_promise->resolve();
}
void ContentDecryptorDelegate::OnPromiseResolvedWithSession(
uint32 promise_id,
PP_Var web_session_id) {
scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
+ if (!promise ||
+ promise->GetResolveParameterType() != media::CdmPromise::STRING_TYPE) {
+ NOTREACHED();
+ return;
+ }
StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
DCHECK(web_session_id_string);
- if (promise) {
- NewSessionCdmPromise* session_promise(
- static_cast<NewSessionCdmPromise*>(promise.get()));
- session_promise->resolve(web_session_id_string->value());
+ NewSessionCdmPromise* session_promise =
+ static_cast<NewSessionCdmPromise*>(promise.get());
+ session_promise->resolve(web_session_id_string->value());
+}
+
+void ContentDecryptorDelegate::OnPromiseResolvedWithKeyIds(
+ uint32 promise_id,
+ PP_Var key_ids_array) {
+ scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
+
+ ArrayVar* key_ids = ArrayVar::FromPPVar(key_ids_array);
+ DCHECK(key_ids && key_ids->GetLength() <= media::limits::kMaxKeyIds);
+ media::KeyIdsVector key_ids_vector;
+ if (key_ids && key_ids->GetLength() <= media::limits::kMaxKeyIds) {
+ for (size_t i = 0; i < key_ids->GetLength(); ++i) {
+ ArrayBufferVar* array_buffer = ArrayBufferVar::FromPPVar(key_ids->Get(i));
+
+ if (!array_buffer ||
+ array_buffer->ByteLength() < media::limits::kMinKeyIdLength ||
+ array_buffer->ByteLength() > media::limits::kMaxKeyIdLength) {
+ NOTREACHED();
+ continue;
+ }
+
+ std::vector<uint8> key_id;
+ const uint8* data = static_cast<const uint8*>(array_buffer->Map());
+ key_id.assign(data, data + array_buffer->ByteLength());
+ key_ids_vector.push_back(key_id);
+ }
}
+
+ if (!promise ||
+ promise->GetResolveParameterType() !=
+ media::CdmPromise::KEY_IDS_VECTOR_TYPE) {
+ NOTREACHED();
+ return;
+ }
+
+ KeyIdsPromise* key_ids_promise(static_cast<KeyIdsPromise*>(promise.get()));
+ key_ids_promise->resolve(key_ids_vector);
}
void ContentDecryptorDelegate::OnPromiseRejected(
@@ -654,10 +771,13 @@ void ContentDecryptorDelegate::OnPromiseRejected(
PP_CdmExceptionCode exception_code,
uint32 system_code,
PP_Var error_description) {
+ ReportSystemCodeUMA(key_system_, system_code);
+
StringVar* error_description_string = StringVar::FromPPVar(error_description);
DCHECK(error_description_string);
scoped_ptr<CdmPromise> promise = TakePromise(promise_id);
+ DCHECK(promise);
if (promise) {
promise->reject(PpExceptionTypeToMediaException(exception_code),
system_code,
@@ -695,6 +815,32 @@ void ContentDecryptorDelegate::OnSessionMessage(PP_Var web_session_id,
web_session_id_string->value(), message_vector, verified_gurl);
}
+void ContentDecryptorDelegate::OnSessionKeysChange(
+ PP_Var web_session_id,
+ PP_Bool has_additional_usable_key) {
+ if (session_keys_change_cb_.is_null())
+ return;
+
+ StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
+ DCHECK(web_session_id_string);
+
+ session_keys_change_cb_.Run(web_session_id_string->value(),
+ PP_ToBool(has_additional_usable_key));
+}
+
+void ContentDecryptorDelegate::OnSessionExpirationChange(
+ PP_Var web_session_id,
+ PP_Time new_expiry_time) {
+ if (session_expiration_update_cb_.is_null())
+ return;
+
+ StringVar* web_session_id_string = StringVar::FromPPVar(web_session_id);
+ DCHECK(web_session_id_string);
+
+ session_expiration_update_cb_.Run(web_session_id_string->value(),
+ ppapi::PPTimeToTime(new_expiry_time));
+}
+
void ContentDecryptorDelegate::OnSessionReady(PP_Var web_session_id) {
if (session_ready_cb_.is_null())
return;
@@ -720,6 +866,8 @@ void ContentDecryptorDelegate::OnSessionError(
PP_CdmExceptionCode exception_code,
uint32 system_code,
PP_Var error_description) {
+ ReportSystemCodeUMA(key_system_, system_code);
+
if (session_error_cb_.is_null())
return;
diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.h b/chromium/content/renderer/pepper/content_decryptor_delegate.h
index 182d6a66257..5fb3fb233b3 100644
--- a/chromium/content/renderer/pepper/content_decryptor_delegate.h
+++ b/chromium/content/renderer/pepper/content_decryptor_delegate.h
@@ -20,6 +20,7 @@
#include "media/base/decryptor.h"
#include "media/base/media_keys.h"
#include "media/base/sample_format.h"
+#include "ppapi/c/pp_time.h"
#include "ppapi/c/private/pp_content_decryptor.h"
#include "ppapi/c/private/ppp_content_decryptor_private.h"
#include "ui/gfx/size.h"
@@ -45,16 +46,22 @@ class ContentDecryptorDelegate {
~ContentDecryptorDelegate();
// This object should not be accessed after |fatal_plugin_error_cb| is called.
- void Initialize(const std::string& key_system,
- const media::SessionMessageCB& session_message_cb,
- const media::SessionReadyCB& session_ready_cb,
- const media::SessionClosedCB& session_closed_cb,
- const media::SessionErrorCB& session_error_cb,
- const base::Closure& fatal_plugin_error_cb);
+ void Initialize(
+ const std::string& key_system,
+ const media::SessionMessageCB& session_message_cb,
+ const media::SessionReadyCB& session_ready_cb,
+ const media::SessionClosedCB& session_closed_cb,
+ const media::SessionErrorCB& session_error_cb,
+ const media::SessionKeysChangeCB& session_keys_change_cb,
+ const media::SessionExpirationUpdateCB& session_expiration_update_cb,
+ const base::Closure& fatal_plugin_error_cb);
void InstanceCrashed();
// Provides access to PPP_ContentDecryptor_Private.
+ void SetServerCertificate(const uint8_t* certificate,
+ uint32_t certificate_length,
+ scoped_ptr<media::SimpleCdmPromise> promise);
void CreateSession(const std::string& init_data_type,
const uint8* init_data,
int init_data_length,
@@ -66,8 +73,12 @@ class ContentDecryptorDelegate {
const uint8* response,
int response_length,
scoped_ptr<media::SimpleCdmPromise> promise);
- void ReleaseSession(const std::string& web_session_id,
- scoped_ptr<media::SimpleCdmPromise> promise);
+ void CloseSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise);
+ void RemoveSession(const std::string& web_session_id,
+ scoped_ptr<media::SimpleCdmPromise> promise);
+ void GetUsableKeyIds(const std::string& web_session_id,
+ scoped_ptr<media::KeyIdsPromise> promise);
bool Decrypt(media::Decryptor::StreamType stream_type,
const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
const media::Decryptor::DecryptCB& decrypt_cb);
@@ -93,6 +104,7 @@ class ContentDecryptorDelegate {
// PPB_ContentDecryptor_Private dispatching methods.
void OnPromiseResolved(uint32 promise_id);
void OnPromiseResolvedWithSession(uint32 promise_id, PP_Var web_session_id);
+ void OnPromiseResolvedWithKeyIds(uint32 promise_id, PP_Var key_ids_array);
void OnPromiseRejected(uint32 promise_id,
PP_CdmExceptionCode exception_code,
uint32 system_code,
@@ -100,6 +112,10 @@ class ContentDecryptorDelegate {
void OnSessionMessage(PP_Var web_session_id,
PP_Var message,
PP_Var destination_url);
+ void OnSessionKeysChange(PP_Var web_session_id,
+ PP_Bool has_additional_usable_key);
+ void OnSessionExpirationChange(PP_Var web_session_id,
+ PP_Time new_expiry_time);
void OnSessionReady(PP_Var web_session_id);
void OnSessionClosed(PP_Var web_session_id);
void OnSessionError(PP_Var web_session_id,
@@ -206,6 +222,8 @@ class ContentDecryptorDelegate {
media::SessionReadyCB session_ready_cb_;
media::SessionClosedCB session_closed_cb_;
media::SessionErrorCB session_error_cb_;
+ media::SessionKeysChangeCB session_keys_change_cb_;
+ media::SessionExpirationUpdateCB session_expiration_update_cb_;
// Callback to notify that unexpected error happened and |this| should not
// be used anymore.
diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index 07afe47fa82..93306eb5865 100644
--- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -16,7 +16,6 @@
#include "content/renderer/pepper/pepper_graphics_2d_host.h"
#include "content/renderer/pepper/pepper_media_stream_video_track_host.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/pepper/pepper_truetype_font_host.h"
#include "content/renderer/pepper/pepper_url_loader_host.h"
#include "content/renderer/pepper/pepper_video_capture_host.h"
#include "content/renderer/pepper/pepper_video_decoder_host.h"
@@ -35,15 +34,20 @@
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
+#if defined(OS_WIN)
+#include "base/command_line.h"
+#include "base/win/windows_version.h"
+#include "content/public/common/content_switches.h"
+#endif
+
using ppapi::host::ResourceHost;
-using ppapi::proxy::SerializedTrueTypeFontDesc;
using ppapi::UnpackMessage;
namespace content {
-#if defined(ENABLE_WEBRTC)
namespace {
+#if defined(ENABLE_WEBRTC)
bool CanUseMediaStreamAPI(const RendererPpapiHost* host, PP_Instance instance) {
blink::WebPluginContainer* container =
host->GetContainerForInstance(instance);
@@ -55,9 +59,35 @@ bool CanUseMediaStreamAPI(const RendererPpapiHost* host, PP_Instance instance) {
GetContentClient()->renderer();
return content_renderer_client->AllowPepperMediaStreamAPI(document_url);
}
+#endif // defined(ENABLE_WEBRTC)
+
+bool CanUseCompositorAPI(const RendererPpapiHost* host, PP_Instance instance) {
+ blink::WebPluginContainer* container =
+ host->GetContainerForInstance(instance);
+ if (!container)
+ return false;
+
+ GURL document_url = container->element().document().url();
+ ContentRendererClient* content_renderer_client =
+ GetContentClient()->renderer();
+ return content_renderer_client->IsPluginAllowedToUseCompositorAPI(
+ document_url);
+}
+
+bool CanUseVideoDecodeAPI(const RendererPpapiHost* host, PP_Instance instance) {
+ blink::WebPluginContainer* container =
+ host->GetContainerForInstance(instance);
+ if (!container)
+ return false;
+
+ GURL document_url = container->element().document().url();
+ ContentRendererClient* content_renderer_client =
+ GetContentClient()->renderer();
+ return content_renderer_client->IsPluginAllowedToUseVideoDecodeAPI(
+ document_url);
+}
} // namespace
-#endif // defined(ENABLE_WEBRTC)
ContentRendererPepperHostFactory::ContentRendererPepperHostFactory(
RendererPpapiHostImpl* host)
@@ -84,9 +114,11 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
// Public interfaces.
switch (message.type()) {
case PpapiHostMsg_Compositor_Create::ID: {
- return scoped_ptr<ResourceHost>(
- new PepperCompositorHost(host_, instance, params.pp_resource()));
- }
+ if (!CanUseCompositorAPI(host_, instance))
+ return scoped_ptr<ResourceHost>();
+ return scoped_ptr<ResourceHost>(
+ new PepperCompositorHost(host_, instance, params.pp_resource()));
+ }
case PpapiHostMsg_FileRef_CreateForFileAPI::ID: {
PP_Resource file_system;
std::string internal_path;
@@ -116,8 +148,24 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
NOTREACHED();
return scoped_ptr<ResourceHost>();
}
+ ppapi::PPB_ImageData_Shared::ImageDataType image_type =
+ ppapi::PPB_ImageData_Shared::PLATFORM;
+#if defined(OS_WIN)
+ // If Win32K lockdown mitigations are enabled for Windows 8 and beyond
+ // we use the SIMPLE image data type as the PLATFORM image data type
+ // calls GDI functions to create DIB sections etc which fail in Win32K
+ // lockdown mode.
+ // TODO(ananta)
+ // Look into whether this causes a loss of functionality. From cursory
+ // testing things seem to work well.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWin32kRendererLockDown) &&
+ base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ image_type = ppapi::PPB_ImageData_Shared::SIMPLE;
+ }
+#endif
scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl(
- instance, ppapi::PPB_ImageData_Shared::PLATFORM));
+ instance, image_type));
return scoped_ptr<ResourceHost>(
PepperGraphics2DHost::Create(host_,
instance,
@@ -129,9 +177,12 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
case PpapiHostMsg_URLLoader_Create::ID:
return scoped_ptr<ResourceHost>(new PepperURLLoaderHost(
host_, false, instance, params.pp_resource()));
- case PpapiHostMsg_VideoDecoder_Create::ID:
+ case PpapiHostMsg_VideoDecoder_Create::ID: {
+ if (!CanUseVideoDecodeAPI(host_, instance))
+ return scoped_ptr<ResourceHost>();
return scoped_ptr<ResourceHost>(
new PepperVideoDecoderHost(host_, instance, params.pp_resource()));
+ }
case PpapiHostMsg_WebSocket_Create::ID:
return scoped_ptr<ResourceHost>(
new PepperWebSocketHost(host_, instance, params.pp_resource()));
@@ -162,20 +213,6 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
case PpapiHostMsg_FileChooser_Create::ID:
return scoped_ptr<ResourceHost>(
new PepperFileChooserHost(host_, instance, params.pp_resource()));
- case PpapiHostMsg_TrueTypeFont_Create::ID: {
- SerializedTrueTypeFontDesc desc;
- if (!UnpackMessage<PpapiHostMsg_TrueTypeFont_Create>(message, &desc)) {
- NOTREACHED();
- return scoped_ptr<ResourceHost>();
- }
- // Check that the family name is valid UTF-8 before passing it to the
- // host OS.
- if (base::IsStringUTF8(desc.family)) {
- return scoped_ptr<ResourceHost>(new PepperTrueTypeFontHost(
- host_, instance, params.pp_resource(), desc));
- }
- break; // Drop through and return null host.
- }
case PpapiHostMsg_VideoCapture_Create::ID: {
PepperVideoCaptureHost* host =
new PepperVideoCaptureHost(host_, instance, params.pp_resource());
diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h
index 8618b8b886d..9a4ef85687f 100644
--- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h
+++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h
@@ -21,13 +21,13 @@ class RenderViewImpl;
class ContentRendererPepperHostFactory : public ppapi::host::HostFactory {
public:
explicit ContentRendererPepperHostFactory(RendererPpapiHostImpl* host);
- virtual ~ContentRendererPepperHostFactory();
+ ~ContentRendererPepperHostFactory() override;
- virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
ppapi::host::PpapiHost* host,
const ppapi::proxy::ResourceMessageCallParams& params,
PP_Instance instance,
- const IPC::Message& message) OVERRIDE;
+ const IPC::Message& message) override;
private:
const ppapi::PpapiPermissions& GetPermissions() const;
diff --git a/chromium/content/renderer/pepper/event_conversion.cc b/chromium/content/renderer/pepper/event_conversion.cc
index d08e3d5553d..4de55559fff 100644
--- a/chromium/content/renderer/pepper/event_conversion.cc
+++ b/chromium/content/renderer/pepper/event_conversion.cc
@@ -4,8 +4,6 @@
#include "content/renderer/pepper/event_conversion.h"
-#include <map>
-
#include "base/basictypes.h"
#include "base/i18n/char_iterator.h"
#include "base/logging.h"
@@ -15,7 +13,6 @@
#include "base/strings/utf_string_conversion_utils.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/input/web_touch_event_traits.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/usb_key_code_conversion.h"
#include "ppapi/c/pp_input_event.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h"
@@ -216,11 +213,27 @@ void AppendMouseWheelEvent(const WebInputEvent& event,
result_events->push_back(result);
}
+enum IncludedTouchPointTypes {
+ ALL, // All pointers targetting the plugin.
+ ACTIVE, // Only pointers that are currently down.
+ CHANGED // Only pointers that have changed since the previous event.
+};
void SetPPTouchPoints(const WebTouchPoint* touches,
uint32_t touches_length,
+ IncludedTouchPointTypes included_types,
std::vector<PP_TouchPoint>* result) {
for (uint32_t i = 0; i < touches_length; i++) {
const WebTouchPoint& touch_point = touches[i];
+ if (included_types == ACTIVE &&
+ (touch_point.state == WebTouchPoint::StateReleased ||
+ touch_point.state == WebTouchPoint::StateCancelled)) {
+ continue;
+ }
+ if (included_types == CHANGED &&
+ (touch_point.state == WebTouchPoint::StateUndefined ||
+ touch_point.state == WebTouchPoint::StateStationary)) {
+ continue;
+ }
PP_TouchPoint pp_pt;
pp_pt.id = touch_point.id;
pp_pt.position.x = touch_point.position.x;
@@ -240,52 +253,67 @@ void AppendTouchEvent(const WebInputEvent& event,
InputEventData result = GetEventWithCommonFieldsAndType(event);
SetPPTouchPoints(
- touch_event.touches, touch_event.touchesLength, &result.touches);
- SetPPTouchPoints(touch_event.changedTouches,
- touch_event.changedTouchesLength,
+ touch_event.touches, touch_event.touchesLength, ACTIVE, &result.touches);
+ SetPPTouchPoints(touch_event.touches,
+ touch_event.touchesLength,
+ CHANGED,
&result.changed_touches);
- SetPPTouchPoints(touch_event.targetTouches,
- touch_event.targetTouchesLength,
+ SetPPTouchPoints(touch_event.touches,
+ touch_event.touchesLength,
+ ALL,
&result.target_touches);
result_events->push_back(result);
}
-// Structure used to map touch point id's to touch states. Since the pepper
-// touch event structure does not have states for individual touch points and
-// instead relies on the event type in combination with the set of touch lists,
-// we have to set the state for the changed touches to be the same as the event
-// type and all others to be 'stationary.'
-typedef std::map<uint32_t, WebTouchPoint::State> TouchStateMap;
-
-void SetWebTouchPoints(const std::vector<PP_TouchPoint>& pp_touches,
- const TouchStateMap& states_map,
- WebTouchPoint* web_touches,
- uint32_t* web_touches_length) {
-
- for (uint32_t i = 0;
- i < pp_touches.size() && i < WebTouchEvent::touchesLengthCap;
- i++) {
- WebTouchPoint pt;
+WebTouchPoint CreateWebTouchPoint(const PP_TouchPoint& pp_pt,
+ WebTouchPoint::State state) {
+ WebTouchPoint pt;
+ pt.id = pp_pt.id;
+ pt.position.x = pp_pt.position.x;
+ pt.position.y = pp_pt.position.y;
+ // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
+ pt.screenPosition.x = 0;
+ pt.screenPosition.y = 0;
+ pt.force = pp_pt.pressure;
+ pt.radiusX = pp_pt.radius.x;
+ pt.radiusY = pp_pt.radius.y;
+ pt.rotationAngle = pp_pt.rotation_angle;
+ pt.state = state;
+ return pt;
+}
+
+bool HasTouchPointWithId(const WebTouchPoint* web_touches,
+ uint32_t web_touches_length,
+ uint32_t id) {
+ // Note: A brute force search to find the (potentially) existing touch point
+ // is cheap given the small bound on |WebTouchEvent::touchesLengthCap|.
+ for (uint32_t i = 0; i < web_touches_length; ++i) {
+ if (web_touches[i].id == static_cast<int>(id))
+ return true;
+ }
+ return false;
+}
+
+void SetWebTouchPointsIfNotYetSet(const std::vector<PP_TouchPoint>& pp_touches,
+ WebTouchPoint::State state,
+ WebTouchPoint* web_touches,
+ uint32_t* web_touches_length) {
+ const uint32_t initial_web_touches_length = *web_touches_length;
+ const uint32_t touches_length =
+ std::min(static_cast<uint32_t>(pp_touches.size()),
+ static_cast<uint32_t>(WebTouchEvent::touchesLengthCap));
+ for (uint32_t i = 0; i < touches_length; ++i) {
+ const uint32_t touch_index = *web_touches_length;
+ if (touch_index >= static_cast<uint32_t>(WebTouchEvent::touchesLengthCap))
+ return;
+
const PP_TouchPoint& pp_pt = pp_touches[i];
- pt.id = pp_pt.id;
-
- if (states_map.find(pt.id) == states_map.end())
- pt.state = WebTouchPoint::StateStationary;
- else
- pt.state = states_map.find(pt.id)->second;
-
- pt.position.x = pp_pt.position.x;
- pt.position.y = pp_pt.position.y;
- // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
- pt.screenPosition.x = 0;
- pt.screenPosition.y = 0;
- pt.force = pp_pt.pressure;
- pt.radiusX = pp_pt.radius.x;
- pt.radiusY = pp_pt.radius.y;
- pt.rotationAngle = pp_pt.rotation_angle;
- web_touches[i] = pt;
- (*web_touches_length)++;
+ if (HasTouchPointWithId(web_touches, initial_web_touches_length, pp_pt.id))
+ continue;
+
+ web_touches[touch_index] = CreateWebTouchPoint(pp_pt, state);
+ ++(*web_touches_length);
}
}
@@ -315,35 +343,18 @@ WebTouchEvent* BuildTouchEvent(const InputEventData& event) {
}
WebTouchEventTraits::ResetType(
type, PPTimeTicksToEventTime(event.event_time_stamp), web_event);
-
- TouchStateMap states_map;
- for (uint32_t i = 0; i < event.changed_touches.size(); i++)
- states_map[event.changed_touches[i].id] = state;
-
- SetWebTouchPoints(event.changed_touches,
- states_map,
- web_event->changedTouches,
- &web_event->changedTouchesLength);
-
- SetWebTouchPoints(
- event.touches, states_map, web_event->touches, &web_event->touchesLength);
-
- SetWebTouchPoints(event.target_touches,
- states_map,
- web_event->targetTouches,
- &web_event->targetTouchesLength);
-
- if (web_event->type == WebInputEvent::TouchEnd ||
- web_event->type == WebInputEvent::TouchCancel) {
- SetWebTouchPoints(event.changed_touches,
- states_map,
- web_event->touches,
- &web_event->touchesLength);
- SetWebTouchPoints(event.changed_touches,
- states_map,
- web_event->targetTouches,
- &web_event->targetTouchesLength);
- }
+ web_event->touchesLength = 0;
+
+ // First add all changed touches, then add only the remaining unset
+ // (stationary) touches.
+ SetWebTouchPointsIfNotYetSet(event.changed_touches,
+ state,
+ web_event->touches,
+ &web_event->touchesLength);
+ SetWebTouchPointsIfNotYetSet(event.touches,
+ WebTouchPoint::StateStationary,
+ web_event->touches,
+ &web_event->touchesLength);
return web_event;
}
@@ -732,7 +743,7 @@ PP_InputEvent_Class ClassifyInputEvent(WebInputEvent::Type type) {
return PP_INPUTEVENT_CLASS_TOUCH;
case WebInputEvent::Undefined:
default:
- NOTREACHED();
+ CHECK(WebInputEvent::isGestureEventType(type));
return PP_InputEvent_Class(0);
}
}
diff --git a/chromium/content/renderer/pepper/event_conversion.h b/chromium/content/renderer/pepper/event_conversion.h
index 59b8678ada8..c9725d3f7e7 100644
--- a/chromium/content/renderer/pepper/event_conversion.h
+++ b/chromium/content/renderer/pepper/event_conversion.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/memory/linked_ptr.h"
+#include "content/common/content_export.h"
#include "ppapi/c/ppb_input_event.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -27,12 +28,14 @@ namespace content {
// Converts the given WebKit event to one or possibly multiple PP_InputEvents.
// The generated events will be filled into the given vector. On failure, no
// events will ge generated and the vector will be empty.
-void CreateInputEventData(const blink::WebInputEvent& event,
- std::vector<ppapi::InputEventData>* pp_events);
+CONTENT_EXPORT void CreateInputEventData(
+ const blink::WebInputEvent& event,
+ std::vector<ppapi::InputEventData>* pp_events);
// Creates a WebInputEvent from the given PP_InputEvent. If it fails, returns
// NULL. The caller owns the created object on success.
-blink::WebInputEvent* CreateWebInputEvent(const ppapi::InputEventData& event);
+CONTENT_EXPORT blink::WebInputEvent* CreateWebInputEvent(
+ const ppapi::InputEventData& event);
// Creates an array of WebInputEvents to make the given event look like a user
// input event on all platforms. |plugin_x| and |plugin_y| should be the
diff --git a/chromium/content/renderer/pepper/event_conversion_unittest.cc b/chromium/content/renderer/pepper/event_conversion_unittest.cc
new file mode 100644
index 00000000000..8a22a939e8d
--- /dev/null
+++ b/chromium/content/renderer/pepper/event_conversion_unittest.cc
@@ -0,0 +1,145 @@
+// Copyright 2014 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/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/renderer/pepper/event_conversion.h"
+#include "ppapi/shared_impl/ppb_input_event_shared.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class EventConversionTest : public ::testing::Test {
+ protected:
+ void CompareWebTouchEvents(const blink::WebTouchEvent& expected,
+ const blink::WebTouchEvent& actual) {
+ EXPECT_EQ(expected.type, actual.type);
+ ASSERT_EQ(expected.touchesLength, actual.touchesLength);
+ for (size_t i = 0; i < expected.touchesLength; ++i) {
+ size_t j = 0;
+ for (; j < actual.touchesLength; ++j) {
+ if (actual.touches[j].id == expected.touches[i].id)
+ break;
+ }
+ ASSERT_NE(j, actual.touchesLength);
+ EXPECT_EQ(expected.touches[i].id, actual.touches[j].id);
+ EXPECT_EQ(expected.touches[i].state, actual.touches[j].state);
+ EXPECT_EQ(expected.touches[i].position.x, actual.touches[j].position.x);
+ EXPECT_EQ(expected.touches[i].position.y, actual.touches[j].position.y);
+ EXPECT_EQ(expected.touches[i].radiusX, actual.touches[j].radiusX);
+ EXPECT_EQ(expected.touches[i].radiusY, actual.touches[j].radiusY);
+ EXPECT_EQ(expected.touches[i].rotationAngle,
+ actual.touches[j].rotationAngle);
+ EXPECT_EQ(expected.touches[i].force, actual.touches[j].force);
+ }
+ }
+};
+
+TEST_F(EventConversionTest, TouchStart) {
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(1.f, 2.f);
+
+ std::vector<ppapi::InputEventData> pp_events;
+ CreateInputEventData(touch, &pp_events);
+ ASSERT_EQ(1U, pp_events.size());
+
+ const ppapi::InputEventData& pp_event = pp_events[0];
+ ASSERT_EQ(PP_INPUTEVENT_TYPE_TOUCHSTART, pp_event.event_type);
+ ASSERT_EQ(1U, pp_event.touches.size());
+ ASSERT_EQ(1U, pp_event.changed_touches.size());
+ ASSERT_EQ(1U, pp_event.target_touches.size());
+
+ scoped_ptr<blink::WebInputEvent> event_out(CreateWebInputEvent(pp_event));
+ const blink::WebTouchEvent* touch_out =
+ static_cast<const blink::WebTouchEvent*>(event_out.get());
+ ASSERT_TRUE(touch_out);
+ EXPECT_EQ(touch.type, touch_out->type);
+ EXPECT_EQ(touch.touchesLength, touch_out->touchesLength);
+ CompareWebTouchEvents(touch, *touch_out);
+}
+
+TEST_F(EventConversionTest, TouchMove) {
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(1.f, 2.f);
+ touch.ResetPoints();
+ touch.PressPoint(3.f, 4.f);
+ touch.ResetPoints();
+ touch.MovePoint(1, 5.f, 6.f);
+
+ std::vector<ppapi::InputEventData> pp_events;
+ CreateInputEventData(touch, &pp_events);
+ ASSERT_EQ(1U, pp_events.size());
+
+ const ppapi::InputEventData& pp_event = pp_events[0];
+ ASSERT_EQ(PP_INPUTEVENT_TYPE_TOUCHMOVE, pp_event.event_type);
+ ASSERT_EQ(2U, pp_event.touches.size());
+ ASSERT_EQ(1U, pp_event.changed_touches.size());
+ ASSERT_EQ(2U, pp_event.target_touches.size());
+
+ scoped_ptr<blink::WebInputEvent> event_out(CreateWebInputEvent(pp_event));
+ const blink::WebTouchEvent* touch_out =
+ static_cast<const blink::WebTouchEvent*>(event_out.get());
+ ASSERT_TRUE(touch_out);
+ EXPECT_EQ(touch.type, touch_out->type);
+ EXPECT_EQ(touch.touchesLength, touch_out->touchesLength);
+ CompareWebTouchEvents(touch, *touch_out);
+}
+
+TEST_F(EventConversionTest, TouchEnd) {
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(1.f, 2.f);
+ touch.ResetPoints();
+ touch.PressPoint(3.f, 4.f);
+ touch.ResetPoints();
+ touch.ReleasePoint(0);
+
+ std::vector<ppapi::InputEventData> pp_events;
+ CreateInputEventData(touch, &pp_events);
+ ASSERT_EQ(1U, pp_events.size());
+
+ const ppapi::InputEventData& pp_event = pp_events[0];
+ ASSERT_EQ(PP_INPUTEVENT_TYPE_TOUCHEND, pp_event.event_type);
+ ASSERT_EQ(1U, pp_event.touches.size());
+ ASSERT_EQ(1U, pp_event.changed_touches.size());
+ ASSERT_EQ(2U, pp_event.target_touches.size());
+
+ scoped_ptr<blink::WebInputEvent> event_out(CreateWebInputEvent(pp_event));
+ const blink::WebTouchEvent* touch_out =
+ static_cast<const blink::WebTouchEvent*>(event_out.get());
+ ASSERT_TRUE(touch_out);
+ EXPECT_EQ(touch.type, touch_out->type);
+ ASSERT_EQ(touch.touchesLength, touch_out->touchesLength);
+ CompareWebTouchEvents(touch, *touch_out);
+}
+
+TEST_F(EventConversionTest, TouchCancel) {
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(1.f, 2.f);
+ touch.ResetPoints();
+ touch.PressPoint(3.f, 4.f);
+ touch.ResetPoints();
+ touch.CancelPoint(1);
+ touch.CancelPoint(0);
+
+ std::vector<ppapi::InputEventData> pp_events;
+ CreateInputEventData(touch, &pp_events);
+ ASSERT_EQ(1U, pp_events.size());
+
+ const ppapi::InputEventData& pp_event = pp_events[0];
+ ASSERT_EQ(PP_INPUTEVENT_TYPE_TOUCHCANCEL, pp_event.event_type);
+ ASSERT_EQ(0U, pp_event.touches.size());
+ ASSERT_EQ(2U, pp_event.changed_touches.size());
+ ASSERT_EQ(2U, pp_event.target_touches.size());
+
+ scoped_ptr<blink::WebInputEvent> event_out(CreateWebInputEvent(pp_event));
+ const blink::WebTouchEvent* touch_out =
+ static_cast<const blink::WebTouchEvent*>(event_out.get());
+ ASSERT_TRUE(touch_out);
+ EXPECT_EQ(touch.type, touch_out->type);
+ EXPECT_EQ(touch.touchesLength, touch_out->touchesLength);
+ CompareWebTouchEvents(touch, *touch_out);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
index 99a0cee43a4..b5dcbe68926 100644
--- a/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
+++ b/chromium/content/renderer/pepper/fake_pepper_plugin_instance.h
@@ -12,37 +12,35 @@ namespace content {
class FakePepperPluginInstance : public PepperPluginInstance {
public:
- virtual ~FakePepperPluginInstance();
+ ~FakePepperPluginInstance() override;
// PepperPluginInstance overrides.
- virtual content::RenderView* GetRenderView() OVERRIDE;
- virtual blink::WebPluginContainer* GetContainer() OVERRIDE;
- virtual v8::Isolate* GetIsolate() const OVERRIDE;
- virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
- virtual const GURL& GetPluginURL() OVERRIDE;
- virtual base::FilePath GetModulePath() OVERRIDE;
- virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
- float scale) OVERRIDE;
- virtual PP_ExternalPluginResult SwitchToOutOfProcessProxy(
+ content::RenderView* GetRenderView() override;
+ blink::WebPluginContainer* GetContainer() override;
+ v8::Isolate* GetIsolate() const override;
+ ppapi::VarTracker* GetVarTracker() override;
+ const GURL& GetPluginURL() override;
+ base::FilePath GetModulePath() override;
+ PP_Resource CreateImage(gfx::ImageSkia* source_image, float scale) override;
+ PP_ExternalPluginResult SwitchToOutOfProcessProxy(
const base::FilePath& file_path,
ppapi::PpapiPermissions permissions,
const IPC::ChannelHandle& channel_handle,
base::ProcessId plugin_pid,
- int plugin_child_id) OVERRIDE;
- virtual void SetAlwaysOnTop(bool on_top) OVERRIDE;
- virtual bool IsFullPagePlugin() OVERRIDE;
- virtual bool FlashSetFullscreen(bool fullscreen, bool delay_report) OVERRIDE;
- virtual bool IsRectTopmost(const gfx::Rect& rect) OVERRIDE;
- virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
- const char* target,
- bool from_user_action) OVERRIDE;
- virtual int MakePendingFileRefRendererHost(const base::FilePath& path)
- OVERRIDE;
- virtual void SetEmbedProperty(PP_Var key, PP_Var value) OVERRIDE;
- virtual void SetSelectedText(const base::string16& selected_text) OVERRIDE;
- virtual void SetLinkUnderCursor(const std::string& url) OVERRIDE;
- virtual void SetTextInputType(ui::TextInputType type) OVERRIDE;
- virtual void PostMessageToJavaScript(PP_Var message) OVERRIDE;
+ int plugin_child_id) override;
+ void SetAlwaysOnTop(bool on_top) override;
+ bool IsFullPagePlugin() override;
+ bool FlashSetFullscreen(bool fullscreen, bool delay_report) override;
+ bool IsRectTopmost(const gfx::Rect& rect) override;
+ int32_t Navigate(const ppapi::URLRequestInfoData& request,
+ const char* target,
+ bool from_user_action) override;
+ int MakePendingFileRefRendererHost(const base::FilePath& path) override;
+ void SetEmbedProperty(PP_Var key, PP_Var value) override;
+ void SetSelectedText(const base::string16& selected_text) override;
+ void SetLinkUnderCursor(const std::string& url) override;
+ void SetTextInputType(ui::TextInputType type) override;
+ void PostMessageToJavaScript(PP_Var message) override;
private:
GURL gurl_;
diff --git a/chromium/content/renderer/pepper/host_array_buffer_var.h b/chromium/content/renderer/pepper/host_array_buffer_var.h
index 12ae7291221..9722f5fe058 100644
--- a/chromium/content/renderer/pepper/host_array_buffer_var.h
+++ b/chromium/content/renderer/pepper/host_array_buffer_var.h
@@ -22,18 +22,17 @@ class HostArrayBufferVar : public ppapi::ArrayBufferVar {
base::SharedMemoryHandle handle);
// ArrayBufferVar implementation.
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual uint32 ByteLength() OVERRIDE;
- virtual bool CopyToNewShmem(PP_Instance instance,
- int* host_shm_handle_id,
- base::SharedMemoryHandle* plugin_shm_handle)
- OVERRIDE;
+ void* Map() override;
+ void Unmap() override;
+ uint32 ByteLength() override;
+ bool CopyToNewShmem(PP_Instance instance,
+ int* host_shm_handle_id,
+ base::SharedMemoryHandle* plugin_shm_handle) override;
blink::WebArrayBuffer& webkit_buffer() { return buffer_; }
private:
- virtual ~HostArrayBufferVar();
+ ~HostArrayBufferVar() override;
blink::WebArrayBuffer buffer_;
// Tracks whether the data in the buffer is valid.
diff --git a/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc b/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc
index 606d2815c41..df05521fbca 100644
--- a/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc
+++ b/chromium/content/renderer/pepper/host_dispatcher_wrapper.cc
@@ -32,7 +32,7 @@ HostDispatcherWrapper::~HostDispatcherWrapper() {}
bool HostDispatcherWrapper::Init(const IPC::ChannelHandle& channel_handle,
PP_GetInterface_Func local_get_interface,
const ppapi::Preferences& preferences,
- PepperHungPluginFilter* filter) {
+ scoped_refptr<PepperHungPluginFilter> filter) {
if (channel_handle.name.empty())
return false;
@@ -44,7 +44,13 @@ bool HostDispatcherWrapper::Init(const IPC::ChannelHandle& channel_handle,
dispatcher_delegate_.reset(new PepperProxyChannelDelegateImpl);
dispatcher_.reset(new ppapi::proxy::HostDispatcher(
- module_->pp_module(), local_get_interface, filter, permissions_));
+ module_->pp_module(), local_get_interface, permissions_));
+ // The HungPluginFilter needs to know when we are blocked on a sync message
+ // to the plugin. Note the filter outlives the dispatcher, so there is no
+ // need to remove it as an observer.
+ dispatcher_->AddSyncMessageStatusObserver(filter.get());
+ // Guarantee the hung_plugin_filter_ outlives |dispatcher_|.
+ hung_plugin_filter_ = filter;
if (!dispatcher_->InitHostWithChannel(dispatcher_delegate_.get(),
peer_pid_,
@@ -55,6 +61,9 @@ bool HostDispatcherWrapper::Init(const IPC::ChannelHandle& channel_handle,
dispatcher_delegate_.reset();
return false;
}
+ // HungPluginFilter needs to listen for some messages on the IO thread.
+ dispatcher_->AddIOThreadMessageFilter(filter);
+
dispatcher_->channel()->SetRestrictDispatchChannelGroup(
kRendererRestrictDispatchGroup_Pepper);
return true;
diff --git a/chromium/content/renderer/pepper/host_dispatcher_wrapper.h b/chromium/content/renderer/pepper/host_dispatcher_wrapper.h
index e5349178ed2..fc5655de918 100644
--- a/chromium/content/renderer/pepper/host_dispatcher_wrapper.h
+++ b/chromium/content/renderer/pepper/host_dispatcher_wrapper.h
@@ -5,7 +5,9 @@
#ifndef CONTENT_RENDERER_PEPPER_HOST_DISPATCHER_WRAPPER_H_
#define CONTENT_RENDERER_PEPPER_HOST_DISPATCHER_WRAPPER_H_
+#include "base/memory/ref_counted.h"
#include "base/process/process_handle.h"
+#include "content/renderer/pepper/pepper_hung_plugin_filter.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/ppp.h"
#include "ppapi/proxy/host_dispatcher.h"
@@ -34,7 +36,7 @@ class HostDispatcherWrapper {
bool Init(const IPC::ChannelHandle& channel_handle,
PP_GetInterface_Func local_get_interface,
const ppapi::Preferences& preferences,
- PepperHungPluginFilter* filter);
+ scoped_refptr<PepperHungPluginFilter> filter);
// Implements GetInterface for the proxied plugin.
const void* GetProxiedInterface(const char* name);
@@ -69,6 +71,9 @@ class HostDispatcherWrapper {
scoped_ptr<ppapi::proxy::HostDispatcher> dispatcher_;
scoped_ptr<ppapi::proxy::ProxyChannel::Delegate> dispatcher_delegate_;
+ // We hold the hung_plugin_filter_ to guarantee it outlives |dispatcher_|,
+ // since it is an observer of |dispatcher_| for sync calls.
+ scoped_refptr<PepperHungPluginFilter> hung_plugin_filter_;
};
} // namespace content
diff --git a/chromium/content/renderer/pepper/host_globals.h b/chromium/content/renderer/pepper/host_globals.h
index f91a65c7818..9ce071cc0b1 100644
--- a/chromium/content/renderer/pepper/host_globals.h
+++ b/chromium/content/renderer/pepper/host_globals.h
@@ -20,7 +20,7 @@ class PluginModule;
class HostGlobals : public ppapi::PpapiGlobals {
public:
HostGlobals();
- virtual ~HostGlobals();
+ ~HostGlobals() override;
// Getter for the global singleton. Generally, you should use
// PpapiGlobals::Get() when possible. Use this only when you need some
@@ -31,27 +31,26 @@ class HostGlobals : public ppapi::PpapiGlobals {
}
// PpapiGlobals implementation.
- virtual ppapi::ResourceTracker* GetResourceTracker() OVERRIDE;
- virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
- virtual ppapi::CallbackTracker* GetCallbackTrackerForInstance(
- PP_Instance instance) OVERRIDE;
- virtual ppapi::thunk::PPB_Instance_API* GetInstanceAPI(PP_Instance instance)
- OVERRIDE;
- virtual ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
- PP_Instance instance) OVERRIDE;
- virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE;
- virtual std::string GetCmdLine() OVERRIDE;
- virtual void PreCacheFontForFlash(const void* logfontw) OVERRIDE;
- virtual void LogWithSource(PP_Instance instance,
- PP_LogLevel level,
- const std::string& source,
- const std::string& value) OVERRIDE;
- virtual void BroadcastLogWithSource(PP_Module module,
- PP_LogLevel level,
- const std::string& source,
- const std::string& value) OVERRIDE;
- virtual ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
- virtual base::TaskRunner* GetFileTaskRunner() OVERRIDE;
+ ppapi::ResourceTracker* GetResourceTracker() override;
+ ppapi::VarTracker* GetVarTracker() override;
+ ppapi::CallbackTracker* GetCallbackTrackerForInstance(
+ PP_Instance instance) override;
+ ppapi::thunk::PPB_Instance_API* GetInstanceAPI(PP_Instance instance) override;
+ ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
+ PP_Instance instance) override;
+ PP_Module GetModuleForInstance(PP_Instance instance) override;
+ std::string GetCmdLine() override;
+ void PreCacheFontForFlash(const void* logfontw) override;
+ void LogWithSource(PP_Instance instance,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) override;
+ void BroadcastLogWithSource(PP_Module module,
+ PP_LogLevel level,
+ const std::string& source,
+ const std::string& value) override;
+ ppapi::MessageLoopShared* GetCurrentMessageLoop() override;
+ base::TaskRunner* GetFileTaskRunner() override;
HostVarTracker* host_var_tracker() { return &host_var_tracker_; }
@@ -88,7 +87,7 @@ class HostGlobals : public ppapi::PpapiGlobals {
private:
// PpapiGlobals overrides.
- virtual bool IsHostGlobals() const OVERRIDE;
+ bool IsHostGlobals() const override;
static HostGlobals* host_globals_;
diff --git a/chromium/content/renderer/pepper/host_resource_var.h b/chromium/content/renderer/pepper/host_resource_var.h
index 1e8928a94f5..152b9a99b1f 100644
--- a/chromium/content/renderer/pepper/host_resource_var.h
+++ b/chromium/content/renderer/pepper/host_resource_var.h
@@ -32,16 +32,16 @@ class HostResourceVar : public ppapi::ResourceVar {
const IPC::Message& creation_message);
// ResourceVar override.
- virtual PP_Resource GetPPResource() const OVERRIDE;
- virtual int GetPendingRendererHostId() const OVERRIDE;
- virtual int GetPendingBrowserHostId() const OVERRIDE;
- virtual const IPC::Message* GetCreationMessage() const OVERRIDE;
- virtual bool IsPending() const OVERRIDE;
+ PP_Resource GetPPResource() const override;
+ int GetPendingRendererHostId() const override;
+ int GetPendingBrowserHostId() const override;
+ const IPC::Message* GetCreationMessage() const override;
+ bool IsPending() const override;
void set_pending_browser_host_id(int id) { pending_browser_host_id_ = id; }
protected:
- virtual ~HostResourceVar();
+ ~HostResourceVar() override;
private:
// Real resource ID in the plugin. 0 if one has not yet been created
diff --git a/chromium/content/renderer/pepper/host_var_tracker.cc b/chromium/content/renderer/pepper/host_var_tracker.cc
index 700fbaf28be..494d9b9a173 100644
--- a/chromium/content/renderer/pepper/host_var_tracker.cc
+++ b/chromium/content/renderer/pepper/host_var_tracker.cc
@@ -6,16 +6,37 @@
#include "base/logging.h"
#include "content/renderer/pepper/host_array_buffer_var.h"
+#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/host_resource_var.h"
-#include "content/renderer/pepper/npobject_var.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/v8object_var.h"
#include "ppapi/c/pp_var.h"
using ppapi::ArrayBufferVar;
-using ppapi::NPObjectVar;
+using ppapi::V8ObjectVar;
namespace content {
+HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(V8ObjectVar* object_var)
+ : instance(object_var->instance()->pp_instance()) {
+ v8::Local<v8::Object> object = object_var->GetHandle();
+ hash = object.IsEmpty() ? 0 : object->GetIdentityHash();
+}
+
+HostVarTracker::V8ObjectVarKey::V8ObjectVarKey(PP_Instance instance,
+ v8::Handle<v8::Object> object)
+ : instance(instance),
+ hash(object.IsEmpty() ? 0 : object->GetIdentityHash()) {}
+
+HostVarTracker::V8ObjectVarKey::~V8ObjectVarKey() {}
+
+bool HostVarTracker::V8ObjectVarKey::operator<(
+ const V8ObjectVarKey& other) const {
+ if (instance == other.instance)
+ return hash < other.hash;
+ return instance < other.instance;
+}
+
HostVarTracker::HostVarTracker()
: VarTracker(SINGLE_THREADED), last_shared_memory_map_id_(0) {}
@@ -31,74 +52,44 @@ ArrayBufferVar* HostVarTracker::CreateShmArrayBuffer(
return new HostArrayBufferVar(size_in_bytes, handle);
}
-void HostVarTracker::AddNPObjectVar(NPObjectVar* object_var) {
+void HostVarTracker::AddV8ObjectVar(V8ObjectVar* object_var) {
CheckThreadingPreconditions();
-
- InstanceMap::iterator found_instance =
- instance_map_.find(object_var->pp_instance());
- if (found_instance == instance_map_.end()) {
- // Lazily create the instance map.
- DCHECK(object_var->pp_instance() != 0);
- found_instance =
- instance_map_.insert(std::make_pair(
- object_var->pp_instance(),
- linked_ptr<NPObjectToNPObjectVarMap>(
- new NPObjectToNPObjectVarMap))).first;
- }
- NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
-
- DCHECK(np_object_map->find(object_var->np_object()) == np_object_map->end())
- << "NPObjectVar already in map";
- np_object_map->insert(std::make_pair(object_var->np_object(), object_var));
+ v8::HandleScope handle_scope(object_var->instance()->GetIsolate());
+ DCHECK(GetForV8Object(object_var->instance()->pp_instance(),
+ object_var->GetHandle()) == object_map_.end());
+ object_map_.insert(std::make_pair(V8ObjectVarKey(object_var), object_var));
}
-void HostVarTracker::RemoveNPObjectVar(NPObjectVar* object_var) {
+void HostVarTracker::RemoveV8ObjectVar(V8ObjectVar* object_var) {
CheckThreadingPreconditions();
-
- InstanceMap::iterator found_instance =
- instance_map_.find(object_var->pp_instance());
- if (found_instance == instance_map_.end()) {
- NOTREACHED() << "NPObjectVar has invalid instance.";
- return;
- }
- NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
-
- NPObjectToNPObjectVarMap::iterator found_object =
- np_object_map->find(object_var->np_object());
- if (found_object == np_object_map->end()) {
- NOTREACHED() << "NPObjectVar not registered.";
- return;
- }
- if (found_object->second != object_var) {
- NOTREACHED() << "NPObjectVar doesn't match.";
- return;
- }
- np_object_map->erase(found_object);
+ v8::HandleScope handle_scope(object_var->instance()->GetIsolate());
+ ObjectMap::iterator it = GetForV8Object(
+ object_var->instance()->pp_instance(), object_var->GetHandle());
+ DCHECK(it != object_map_.end());
+ object_map_.erase(it);
}
-NPObjectVar* HostVarTracker::NPObjectVarForNPObject(PP_Instance instance,
- NPObject* np_object) {
+PP_Var HostVarTracker::V8ObjectVarForV8Object(PP_Instance instance,
+ v8::Handle<v8::Object> object) {
CheckThreadingPreconditions();
-
- InstanceMap::iterator found_instance = instance_map_.find(instance);
- if (found_instance == instance_map_.end())
- return NULL; // No such instance.
- NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
-
- NPObjectToNPObjectVarMap::iterator found_object =
- np_object_map->find(np_object);
- if (found_object == np_object_map->end())
- return NULL; // No such object.
- return found_object->second;
+ ObjectMap::const_iterator it = GetForV8Object(instance, object);
+ if (it == object_map_.end())
+ return (new V8ObjectVar(instance, object))->GetPPVar();
+ return it->second->GetPPVar();
}
-int HostVarTracker::GetLiveNPObjectVarsForInstance(PP_Instance instance) const {
+int HostVarTracker::GetLiveV8ObjectVarsForTest(PP_Instance instance) {
CheckThreadingPreconditions();
-
- InstanceMap::const_iterator found = instance_map_.find(instance);
- if (found == instance_map_.end())
- return 0;
- return static_cast<int>(found->second->size());
+ int count = 0;
+ // Use a key with an empty handle to find the v8 object var in the map with
+ // the given instance and the lowest hash.
+ V8ObjectVarKey key(instance, v8::Handle<v8::Object>());
+ ObjectMap::const_iterator it = object_map_.lower_bound(key);
+ while (it != object_map_.end() && it->first.instance == instance) {
+ ++count;
+ ++it;
+ }
+ return count;
}
PP_Var HostVarTracker::MakeResourcePPVarFromMessage(
@@ -116,27 +107,27 @@ ppapi::ResourceVar* HostVarTracker::MakeResourceVar(PP_Resource pp_resource) {
return new HostResourceVar(pp_resource);
}
-void HostVarTracker::DidDeleteInstance(PP_Instance instance) {
+void HostVarTracker::DidDeleteInstance(PP_Instance pp_instance) {
CheckThreadingPreconditions();
- InstanceMap::iterator found_instance = instance_map_.find(instance);
- if (found_instance == instance_map_.end())
- return; // Nothing to do.
- NPObjectToNPObjectVarMap* np_object_map = found_instance->second.get();
-
- // Force delete all var references. ForceReleaseNPObject() will cause
+ PepperPluginInstanceImpl* instance =
+ HostGlobals::Get()->GetInstance(pp_instance);
+ v8::HandleScope handle_scope(instance->GetIsolate());
+ // Force delete all var references. ForceReleaseV8Object() will cause
// this object, and potentially others it references, to be removed from
- // |np_object_map|.
- while (!np_object_map->empty()) {
- ForceReleaseNPObject(np_object_map->begin()->second);
+ // |live_vars_|.
+
+ // Use a key with an empty handle to find the v8 object var in the map with
+ // the given instance and the lowest hash.
+ V8ObjectVarKey key(pp_instance, v8::Handle<v8::Object>());
+ ObjectMap::iterator it = object_map_.lower_bound(key);
+ while (it != object_map_.end() && it->first.instance == pp_instance) {
+ ForceReleaseV8Object(it->second);
+ object_map_.erase(it++);
}
-
- // Remove the record for this instance since it should be empty.
- DCHECK(np_object_map->empty());
- instance_map_.erase(found_instance);
}
-void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) {
+void HostVarTracker::ForceReleaseV8Object(ppapi::V8ObjectVar* object_var) {
object_var->InstanceDeleted();
VarMap::iterator iter = live_vars_.find(object_var->GetExistingVarID());
if (iter == live_vars_.end()) {
@@ -148,6 +139,19 @@ void HostVarTracker::ForceReleaseNPObject(ppapi::NPObjectVar* object_var) {
DeleteObjectInfoIfNecessary(iter);
}
+HostVarTracker::ObjectMap::iterator HostVarTracker::GetForV8Object(
+ PP_Instance instance,
+ v8::Handle<v8::Object> object) {
+ std::pair<ObjectMap::iterator, ObjectMap::iterator> range =
+ object_map_.equal_range(V8ObjectVarKey(instance, object));
+
+ for (ObjectMap::iterator it = range.first; it != range.second; ++it) {
+ if (object == it->second->GetHandle())
+ return it;
+ }
+ return object_map_.end();
+}
+
int HostVarTracker::TrackSharedMemoryHandle(PP_Instance instance,
base::SharedMemoryHandle handle,
uint32 size_in_bytes) {
diff --git a/chromium/content/renderer/pepper/host_var_tracker.h b/chromium/content/renderer/pepper/host_var_tracker.h
index 6abbf869765..0be5d1d2eb6 100644
--- a/chromium/content/renderer/pepper/host_var_tracker.h
+++ b/chromium/content/renderer/pepper/host_var_tracker.h
@@ -18,82 +18,82 @@
#include "ppapi/shared_impl/host_resource.h"
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/var_tracker.h"
-
-typedef struct NPObject NPObject;
+#include "v8/include/v8.h"
namespace ppapi {
class ArrayBufferVar;
-class NPObjectVar;
+class V8ObjectVar;
class Var;
}
namespace content {
-// Adds NPObject var tracking to the standard PPAPI VarTracker for use in the
-// renderer.
class HostVarTracker : public ppapi::VarTracker {
public:
HostVarTracker();
- virtual ~HostVarTracker();
-
- // Tracks all live NPObjectVar. This is so we can map between instance +
- // NPObject and get the NPObjectVar corresponding to it. This Add/Remove
- // function is called by the NPObjectVar when it is created and
- // destroyed.
- void AddNPObjectVar(ppapi::NPObjectVar* object_var);
- void RemoveNPObjectVar(ppapi::NPObjectVar* object_var);
-
- // Looks up a previously registered NPObjectVar for the given NPObject and
- // instance. Returns NULL if there is no NPObjectVar corresponding to the
- // given NPObject for the given instance. See AddNPObjectVar above.
- ppapi::NPObjectVar* NPObjectVarForNPObject(PP_Instance instance,
- NPObject* np_object);
-
- // Returns the number of NPObjectVar's associated with the given instance.
+ ~HostVarTracker() override;
+
+ // Tracks all live V8ObjectVar. This is so we can map between instance +
+ // V8Object and get the V8ObjectVar corresponding to it. This Add/Remove
+ // function is called by the V8ObjectVar when it is created and destroyed.
+ void AddV8ObjectVar(ppapi::V8ObjectVar* object_var);
+ void RemoveV8ObjectVar(ppapi::V8ObjectVar* object_var);
+ // Creates or retrieves a V8ObjectVar.
+ PP_Var V8ObjectVarForV8Object(PP_Instance instance,
+ v8::Handle<v8::Object> object);
+ // Returns the number of V8ObjectVars associated with the given instance.
// Returns 0 if the instance isn't known.
- CONTENT_EXPORT int GetLiveNPObjectVarsForInstance(PP_Instance instance) const;
+ CONTENT_EXPORT int GetLiveV8ObjectVarsForTest(PP_Instance instance);
// VarTracker public implementation.
- virtual PP_Var MakeResourcePPVarFromMessage(
- PP_Instance instance,
- const IPC::Message& creation_message,
- int pending_renderer_id,
- int pending_browser_id) OVERRIDE;
- virtual ppapi::ResourceVar* MakeResourceVar(PP_Resource pp_resource) OVERRIDE;
- virtual void DidDeleteInstance(PP_Instance instance) OVERRIDE;
-
- virtual int TrackSharedMemoryHandle(PP_Instance instance,
- base::SharedMemoryHandle file,
- uint32 size_in_bytes) OVERRIDE;
- virtual bool StopTrackingSharedMemoryHandle(int id,
- PP_Instance instance,
- base::SharedMemoryHandle* handle,
- uint32* size_in_bytes) OVERRIDE;
+ PP_Var MakeResourcePPVarFromMessage(PP_Instance instance,
+ const IPC::Message& creation_message,
+ int pending_renderer_id,
+ int pending_browser_id) override;
+ ppapi::ResourceVar* MakeResourceVar(PP_Resource pp_resource) override;
+ void DidDeleteInstance(PP_Instance pp_instance) override;
+
+ int TrackSharedMemoryHandle(PP_Instance instance,
+ base::SharedMemoryHandle file,
+ uint32 size_in_bytes) override;
+ bool StopTrackingSharedMemoryHandle(int id,
+ PP_Instance instance,
+ base::SharedMemoryHandle* handle,
+ uint32* size_in_bytes) override;
private:
// VarTracker private implementation.
- virtual ppapi::ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes)
- OVERRIDE;
- virtual ppapi::ArrayBufferVar* CreateShmArrayBuffer(
+ ppapi::ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) override;
+ ppapi::ArrayBufferVar* CreateShmArrayBuffer(
uint32 size_in_bytes,
- base::SharedMemoryHandle handle) OVERRIDE;
+ base::SharedMemoryHandle handle) override;
// Clear the reference count of the given object and remove it from
// live_vars_.
- void ForceReleaseNPObject(ppapi::NPObjectVar* object_var);
-
- typedef std::map<NPObject*, ppapi::NPObjectVar*> NPObjectToNPObjectVarMap;
-
- // Lists all known NPObjects, first indexed by the corresponding instance,
- // then by the NPObject*. This allows us to look up an NPObjectVar given
- // these two pieces of information.
- //
- // The instance map is lazily managed, so we'll add the
- // NPObjectToNPObjectVarMap lazily when the first NPObject var is created,
- // and delete it when it's empty.
- typedef std::map<PP_Instance, linked_ptr<NPObjectToNPObjectVarMap> >
- InstanceMap;
- InstanceMap instance_map_;
+ void ForceReleaseV8Object(ppapi::V8ObjectVar* object_var);
+
+ // A non-unique, ordered key for a V8ObjectVar. Contains the hash of the v8
+ // and the instance it is associated with.
+ struct V8ObjectVarKey {
+ explicit V8ObjectVarKey(ppapi::V8ObjectVar* object_var);
+ V8ObjectVarKey(PP_Instance i, v8::Handle<v8::Object> object);
+ ~V8ObjectVarKey();
+
+ bool operator<(const V8ObjectVarKey& other) const;
+
+ PP_Instance instance;
+ int hash;
+ };
+ typedef std::multimap<V8ObjectVarKey, ppapi::V8ObjectVar*> ObjectMap;
+
+ // Returns an iterator into |object_map| which points to V8Object which
+ // is associated with the given instance and object.
+ ObjectMap::iterator GetForV8Object(PP_Instance instance,
+ v8::Handle<v8::Object> object);
+
+
+ // A multimap of V8ObjectVarKey -> ObjectMap.
+ ObjectMap object_map_;
// Tracks all shared memory handles used for transmitting array buffers.
struct SharedMemoryMapEntry {
diff --git a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
index 07b759dce69..32e9e56ea89 100644
--- a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
+++ b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
@@ -2,56 +2,67 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/host_var_tracker.h"
#include "content/renderer/pepper/mock_resource.h"
-#include "content/renderer/pepper/npapi_glue.h"
-#include "content/renderer/pepper/npobject_var.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_try_catch.h"
+#include "content/renderer/pepper/v8_var_converter.h"
+#include "content/renderer/pepper/v8object_var.h"
#include "content/test/ppapi_unittest.h"
+#include "gin/handle.h"
+#include "gin/wrappable.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppp_instance.h"
-#include "third_party/npapi/bindings/npruntime.h"
#include "third_party/WebKit/public/web/WebBindings.h"
-using ppapi::NPObjectVar;
+using ppapi::V8ObjectVar;
namespace content {
namespace {
-// Tracked NPObjects -----------------------------------------------------------
+int g_v8objects_alive = 0;
-int g_npobjects_alive = 0;
+class MyObject : public gin::Wrappable<MyObject> {
+ public:
+ static gin::WrapperInfo kWrapperInfo;
-void TrackedClassDeallocate(NPObject* npobject) {
- g_npobjects_alive--;
- delete npobject;
-}
+ static v8::Handle<v8::Value> Create(v8::Isolate* isolate) {
+ return gin::CreateHandle(isolate, new MyObject()).ToV8();
+ }
-NPClass g_tracked_npclass = {
- NP_CLASS_STRUCT_VERSION, NULL, &TrackedClassDeallocate, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, };
+ private:
+ MyObject() { ++g_v8objects_alive; }
+ ~MyObject() override { --g_v8objects_alive; }
-// Returns a new tracked NPObject with a refcount of 1. You'll want to put this
-// in a NPObjectReleaser to free this ref when the test completes.
-NPObject* NewTrackedNPObject() {
- NPObject* object = new NPObject;
- object->_class = &g_tracked_npclass;
- object->referenceCount = 1;
+ DISALLOW_COPY_AND_ASSIGN(MyObject);
+};
- g_npobjects_alive++;
- return object;
-}
+gin::WrapperInfo MyObject::kWrapperInfo = {gin::kEmbedderNativeGin};
-struct ReleaseNPObject {
- void operator()(NPObject* o) const { blink::WebBindings::releaseObject(o); }
-};
+class PepperTryCatchForTest : public PepperTryCatch {
+ public:
+ PepperTryCatchForTest(PepperPluginInstanceImpl* instance,
+ V8VarConverter* converter)
+ : PepperTryCatch(instance, converter),
+ handle_scope_(instance->GetIsolate()),
+ context_scope_(v8::Context::New(instance->GetIsolate())) {}
+
+ void SetException(const char* message) override { NOTREACHED(); }
+ bool HasException() override { return false; }
+ v8::Handle<v8::Context> GetContext() override {
+ return instance_->GetIsolate()->GetCurrentContext();
+ }
-// Handles automatically releasing a reference to the NPObject on destruction.
-// It's assumed the input has a ref already taken.
-typedef scoped_ptr<NPObject, ReleaseNPObject> NPObjectReleaser;
+ private:
+ v8::HandleScope handle_scope_;
+ v8::Context::Scope context_scope_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTryCatchForTest);
+};
} // namespace
@@ -59,58 +70,72 @@ class HostVarTrackerTest : public PpapiUnittest {
public:
HostVarTrackerTest() {}
+ void TearDown() override {
+ v8::Isolate::GetCurrent()->RequestGarbageCollectionForTesting(
+ v8::Isolate::kFullGarbageCollection);
+ EXPECT_EQ(0, g_v8objects_alive);
+ PpapiUnittest::TearDown();
+ }
+
HostVarTracker& tracker() { return *HostGlobals::Get()->host_var_tracker(); }
};
TEST_F(HostVarTrackerTest, DeleteObjectVarWithInstance) {
+ v8::Isolate* test_isolate = v8::Isolate::GetCurrent();
+
// Make a second instance (the test harness already creates & manages one).
scoped_refptr<PepperPluginInstanceImpl> instance2(
PepperPluginInstanceImpl::Create(NULL, module(), NULL, GURL()));
PP_Instance pp_instance2 = instance2->pp_instance();
- // Make an object var.
- NPObjectReleaser npobject(NewTrackedNPObject());
- NPObjectToPPVarForTest(instance2.get(), npobject.get());
-
- EXPECT_EQ(1, g_npobjects_alive);
- EXPECT_EQ(1, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
+ {
+ V8VarConverter converter(
+ instance2->pp_instance(), V8VarConverter::kAllowObjectVars);
+ PepperTryCatchForTest try_catch(instance2.get(), &converter);
+ // Make an object var.
+ ppapi::ScopedPPVar var = try_catch.FromV8(MyObject::Create(test_isolate));
+ EXPECT_EQ(1, g_v8objects_alive);
+ EXPECT_EQ(1, tracker().GetLiveV8ObjectVarsForTest(pp_instance2));
+ // Purposely leak the var.
+ var.Release();
+ }
// Free the instance, this should release the ObjectVar.
instance2 = NULL;
- EXPECT_EQ(0, tracker().GetLiveNPObjectVarsForInstance(pp_instance2));
+ EXPECT_EQ(0, tracker().GetLiveV8ObjectVarsForTest(pp_instance2));
}
-// Make sure that using the same NPObject should give the same PP_Var
+// Make sure that using the same v8 object should give the same PP_Var
// each time.
TEST_F(HostVarTrackerTest, ReuseVar) {
- NPObjectReleaser npobject(NewTrackedNPObject());
+ V8VarConverter converter(
+ instance()->pp_instance(), V8VarConverter::kAllowObjectVars);
+ PepperTryCatchForTest try_catch(instance(), &converter);
- PP_Var pp_object1 = NPObjectToPPVarForTest(instance(), npobject.get());
- PP_Var pp_object2 = NPObjectToPPVarForTest(instance(), npobject.get());
+ v8::Handle<v8::Value> v8_object = MyObject::Create(v8::Isolate::GetCurrent());
+ ppapi::ScopedPPVar pp_object1 = try_catch.FromV8(v8_object);
+ ppapi::ScopedPPVar pp_object2 = try_catch.FromV8(v8_object);
// The two results should be the same.
- EXPECT_EQ(pp_object1.value.as_id, pp_object2.value.as_id);
+ EXPECT_EQ(pp_object1.get().value.as_id, pp_object2.get().value.as_id);
- // The objects should be able to get us back to the associated NPObject.
- // This ObjectVar must be released before we do NPObjectToPPVarForTest again
- // below so it gets freed and we get a new identifier.
+ // The objects should be able to get us back to the associated v8 object.
{
- scoped_refptr<NPObjectVar> check_object(NPObjectVar::FromPPVar(pp_object1));
+ scoped_refptr<V8ObjectVar> check_object(
+ V8ObjectVar::FromPPVar(pp_object1.get()));
ASSERT_TRUE(check_object.get());
- EXPECT_EQ(instance()->pp_instance(), check_object->pp_instance());
- EXPECT_EQ(npobject.get(), check_object->np_object());
+ EXPECT_EQ(instance(), check_object->instance());
+ EXPECT_EQ(v8_object, check_object->GetHandle());
}
// Remove both of the refs we made above.
- ppapi::VarTracker* var_tracker = ppapi::PpapiGlobals::Get()->GetVarTracker();
- var_tracker->ReleaseVar(static_cast<int32_t>(pp_object2.value.as_id));
- var_tracker->ReleaseVar(static_cast<int32_t>(pp_object1.value.as_id));
+ pp_object1 = ppapi::ScopedPPVar();
+ pp_object2 = ppapi::ScopedPPVar();
// Releasing the resource should free the internal ref, and so making a new
// one now should generate a new ID.
- PP_Var pp_object3 = NPObjectToPPVarForTest(instance(), npobject.get());
- EXPECT_NE(pp_object1.value.as_id, pp_object3.value.as_id);
- var_tracker->ReleaseVar(static_cast<int32_t>(pp_object3.value.as_id));
+ ppapi::ScopedPPVar pp_object3 = try_catch.FromV8(v8_object);
+ EXPECT_NE(pp_object1.get().value.as_id, pp_object3.get().value.as_id);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/message_channel.cc b/chromium/content/renderer/pepper/message_channel.cc
index 2fd4410bda3..1a4e6383b52 100644
--- a/chromium/content/renderer/pepper/message_channel.cc
+++ b/chromium/content/renderer/pepper/message_channel.cc
@@ -11,10 +11,15 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "content/renderer/pepper/host_array_buffer_var.h"
-#include "content/renderer/pepper/npapi_glue.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_try_catch.h"
#include "content/renderer/pepper/plugin_module.h"
-#include "content/renderer/pepper/v8_var_converter.h"
+#include "content/renderer/pepper/plugin_object.h"
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/function_template.h"
+#include "gin/object_template_builder.h"
+#include "gin/public/gin_embedders.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
#include "ppapi/shared_impl/var.h"
@@ -55,217 +60,6 @@ const char kVarToV8ConversionError[] =
"argument from a PP_Var to a Javascript value. It may have cycles or be of "
"an unsupported type.";
-// Helper function to get the MessageChannel that is associated with an
-// NPObject*.
-MessageChannel* ToMessageChannel(NPObject* object) {
- return static_cast<MessageChannel::MessageChannelNPObject*>(object)
- ->message_channel.get();
-}
-
-NPObject* ToPassThroughObject(NPObject* object) {
- MessageChannel* channel = ToMessageChannel(object);
- return channel ? channel->passthrough_object() : NULL;
-}
-
-// Return true iff |identifier| is equal to |string|.
-bool IdentifierIs(NPIdentifier identifier, const char string[]) {
- return WebBindings::getStringIdentifier(string) == identifier;
-}
-
-bool HasDevChannelPermission(NPObject* channel_object) {
- MessageChannel* channel = ToMessageChannel(channel_object);
- if (!channel)
- return false;
- return channel->instance()->module()->permissions().HasPermission(
- ppapi::PERMISSION_DEV_CHANNEL);
-}
-
-//------------------------------------------------------------------------------
-// Implementations of NPClass functions. These are here to:
-// - Implement postMessage behavior.
-// - Forward calls to the 'passthrough' object to allow backwards-compatibility
-// with GetInstanceObject() objects.
-//------------------------------------------------------------------------------
-NPObject* MessageChannelAllocate(NPP npp, NPClass* the_class) {
- return new MessageChannel::MessageChannelNPObject;
-}
-
-void MessageChannelDeallocate(NPObject* object) {
- MessageChannel::MessageChannelNPObject* instance =
- static_cast<MessageChannel::MessageChannelNPObject*>(object);
- delete instance;
-}
-
-bool MessageChannelHasMethod(NPObject* np_obj, NPIdentifier name) {
- if (!np_obj)
- return false;
-
- if (IdentifierIs(name, kPostMessage))
- return true;
- if (IdentifierIs(name, kPostMessageAndAwaitResponse) &&
- HasDevChannelPermission(np_obj)) {
- return true;
- }
- // Other method names we will pass to the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::hasMethod(NULL, passthrough, name);
- return false;
-}
-
-bool MessageChannelInvoke(NPObject* np_obj,
- NPIdentifier name,
- const NPVariant* args,
- uint32 arg_count,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- MessageChannel* message_channel = ToMessageChannel(np_obj);
- if (!message_channel)
- return false;
-
- // Check to see if we should handle this function ourselves.
- if (IdentifierIs(name, kPostMessage) && (arg_count == 1)) {
- message_channel->PostMessageToNative(&args[0]);
- return true;
- } else if (IdentifierIs(name, kPostMessageAndAwaitResponse) &&
- (arg_count == 1) &&
- HasDevChannelPermission(np_obj)) {
- message_channel->PostBlockingMessageToNative(&args[0], result);
- return true;
- }
-
- // Other method calls we will pass to the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough) {
- return WebBindings::invoke(
- NULL, passthrough, name, args, arg_count, result);
- }
- return false;
-}
-
-bool MessageChannelInvokeDefault(NPObject* np_obj,
- const NPVariant* args,
- uint32 arg_count,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough) {
- return WebBindings::invokeDefault(
- NULL, passthrough, args, arg_count, result);
- }
- return false;
-}
-
-bool MessageChannelHasProperty(NPObject* np_obj, NPIdentifier name) {
- if (!np_obj)
- return false;
-
- MessageChannel* message_channel = ToMessageChannel(np_obj);
- if (message_channel) {
- if (message_channel->GetReadOnlyProperty(name, NULL))
- return true;
- }
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::hasProperty(NULL, passthrough, name);
- return false;
-}
-
-bool MessageChannelGetProperty(NPObject* np_obj,
- NPIdentifier name,
- NPVariant* result) {
- if (!np_obj)
- return false;
-
- // Don't allow getting the postMessage functions.
- if (IdentifierIs(name, kPostMessage))
- return false;
- if (IdentifierIs(name, kPostMessageAndAwaitResponse) &&
- HasDevChannelPermission(np_obj)) {
- return false;
- }
- MessageChannel* message_channel = ToMessageChannel(np_obj);
- if (message_channel) {
- if (message_channel->GetReadOnlyProperty(name, result))
- return true;
- }
-
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::getProperty(NULL, passthrough, name, result);
- return false;
-}
-
-bool MessageChannelSetProperty(NPObject* np_obj,
- NPIdentifier name,
- const NPVariant* variant) {
- if (!np_obj)
- return false;
-
- // Don't allow setting the postMessage functions.
- if (IdentifierIs(name, kPostMessage))
- return false;
- if (IdentifierIs(name, kPostMessageAndAwaitResponse) &&
- HasDevChannelPermission(np_obj)) {
- return false;
- }
- // Invoke on the passthrough object, if we have one.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough)
- return WebBindings::setProperty(NULL, passthrough, name, variant);
- return false;
-}
-
-bool MessageChannelEnumerate(NPObject* np_obj,
- NPIdentifier** value,
- uint32_t* count) {
- if (!np_obj)
- return false;
-
- // Invoke on the passthrough object, if we have one, to enumerate its
- // properties.
- NPObject* passthrough = ToPassThroughObject(np_obj);
- if (passthrough) {
- bool success = WebBindings::enumerate(NULL, passthrough, value, count);
- if (success) {
- // Add postMessage to the list and return it.
- if (std::numeric_limits<size_t>::max() / sizeof(NPIdentifier) <=
- static_cast<size_t>(*count) + 1) // Else, "always false" x64 warning.
- return false;
- NPIdentifier* new_array = static_cast<NPIdentifier*>(
- std::malloc(sizeof(NPIdentifier) * (*count + 1)));
- std::memcpy(new_array, *value, sizeof(NPIdentifier) * (*count));
- new_array[*count] = WebBindings::getStringIdentifier(kPostMessage);
- std::free(*value);
- *value = new_array;
- ++(*count);
- return true;
- }
- }
-
- // Otherwise, build an array that includes only postMessage.
- *value = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier)));
- (*value)[0] = WebBindings::getStringIdentifier(kPostMessage);
- *count = 1;
- return true;
-}
-
-NPClass message_channel_class = {
- NP_CLASS_STRUCT_VERSION, &MessageChannelAllocate,
- &MessageChannelDeallocate, NULL,
- &MessageChannelHasMethod, &MessageChannelInvoke,
- &MessageChannelInvokeDefault, &MessageChannelHasProperty,
- &MessageChannelGetProperty, &MessageChannelSetProperty,
- NULL, &MessageChannelEnumerate, };
-
} // namespace
// MessageChannel --------------------------------------------------------------
@@ -287,55 +81,32 @@ struct MessageChannel::VarConversionResult {
bool conversion_completed_;
};
-MessageChannel::MessageChannelNPObject::MessageChannelNPObject() {}
+// static
+gin::WrapperInfo MessageChannel::kWrapperInfo = {gin::kEmbedderNativeGin};
+
+// static
+MessageChannel* MessageChannel::Create(PepperPluginInstanceImpl* instance,
+ v8::Persistent<v8::Object>* result) {
+ MessageChannel* message_channel = new MessageChannel(instance);
+ v8::HandleScope handle_scope(instance->GetIsolate());
+ v8::Context::Scope context_scope(instance->GetMainWorldContext());
+ gin::Handle<MessageChannel> handle =
+ gin::CreateHandle(instance->GetIsolate(), message_channel);
+ result->Reset(instance->GetIsolate(), handle.ToV8()->ToObject());
+ return message_channel;
+}
-MessageChannel::MessageChannelNPObject::~MessageChannelNPObject() {}
+MessageChannel::~MessageChannel() {
+ UnregisterSyncMessageStatusObserver();
-MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance)
- : instance_(instance),
- passthrough_object_(NULL),
- np_object_(NULL),
- early_message_queue_state_(QUEUE_MESSAGES),
- weak_ptr_factory_(this) {
- // Now create an NPObject for receiving calls to postMessage. This sets the
- // reference count to 1. We release it in the destructor.
- NPObject* obj = WebBindings::createObject(instance_->instanceNPP(),
- &message_channel_class);
- DCHECK(obj);
- np_object_ = static_cast<MessageChannel::MessageChannelNPObject*>(obj);
- np_object_->message_channel = weak_ptr_factory_.GetWeakPtr();
+ passthrough_object_.Reset();
+ if (instance_)
+ instance_->MessageChannelDestroyed();
}
-void MessageChannel::EnqueuePluginMessage(const NPVariant* variant) {
- plugin_message_queue_.push_back(VarConversionResult());
- if (variant->type == NPVariantType_Object) {
- // Convert NPVariantType_Object in to an appropriate PP_Var like Dictionary,
- // Array, etc. Note NPVariantToVar would convert to an "Object" PP_Var,
- // which we don't support for Messaging.
-
- // Calling WebBindings::toV8Value creates a wrapper around NPVariant so it
- // won't result in a deep copy.
- v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(variant);
- V8VarConverter v8_var_converter(instance_->pp_instance());
- V8VarConverter::VarResult conversion_result =
- v8_var_converter.FromV8Value(
- v8_value,
- v8::Isolate::GetCurrent()->GetCurrentContext(),
- base::Bind(&MessageChannel::FromV8ValueComplete,
- weak_ptr_factory_.GetWeakPtr(),
- &plugin_message_queue_.back()));
- if (conversion_result.completed_synchronously) {
- plugin_message_queue_.back().ConversionCompleted(
- conversion_result.var,
- conversion_result.success);
- }
- } else {
- plugin_message_queue_.back().ConversionCompleted(
- ScopedPPVar(ScopedPPVar::PassRef(),
- NPVariantToPPVar(instance(), variant)),
- true);
- DCHECK(plugin_message_queue_.back().var().get().type != PP_VARTYPE_OBJECT);
- }
+void MessageChannel::InstanceDeleted() {
+ UnregisterSyncMessageStatusObserver();
+ instance_ = NULL;
}
void MessageChannel::PostMessageToJavaScript(PP_Var message_data) {
@@ -343,22 +114,14 @@ void MessageChannel::PostMessageToJavaScript(PP_Var message_data) {
// Because V8 is probably not on the stack for Native->JS calls, we need to
// enter the appropriate context for the plugin.
- WebPluginContainer* container = instance_->container();
- // It's possible that container() is NULL if the plugin has been removed from
- // the DOM (but the PluginInstance is not destroyed yet).
- if (!container)
- return;
-
- v8::Local<v8::Context> context =
- container->element().document().frame()->mainWorldScriptContext();
- // If the page is being destroyed, the context may be empty.
+ v8::Local<v8::Context> context = instance_->GetMainWorldContext();
if (context.IsEmpty())
return;
+
v8::Context::Scope context_scope(context);
v8::Handle<v8::Value> v8_val;
- if (!V8VarConverter(instance_->pp_instance())
- .ToV8Value(message_data, context, &v8_val)) {
+ if (!var_converter_.ToV8Value(message_data, context, &v8_val)) {
PpapiGlobals::Get()->LogWithSource(instance_->pp_instance(),
PP_LOGLEVEL_ERROR,
std::string(),
@@ -369,112 +132,182 @@ void MessageChannel::PostMessageToJavaScript(PP_Var message_data) {
WebSerializedScriptValue serialized_val =
WebSerializedScriptValue::serialize(v8_val);
- if (early_message_queue_state_ != SEND_DIRECTLY) {
+ if (js_message_queue_state_ != SEND_DIRECTLY) {
// We can't just PostTask here; the messages would arrive out of
// order. Instead, we queue them up until we're ready to post
// them.
- early_message_queue_.push_back(serialized_val);
+ js_message_queue_.push_back(serialized_val);
} else {
// The proxy sent an asynchronous message, so the plugin is already
// unblocked. Therefore, there's no need to PostTask.
- DCHECK(early_message_queue_.empty());
+ DCHECK(js_message_queue_.empty());
PostMessageToJavaScriptImpl(serialized_val);
}
}
void MessageChannel::Start() {
- // We PostTask here instead of draining the message queue directly
- // since we haven't finished initializing the PepperWebPluginImpl yet, so
- // the plugin isn't available in the DOM.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&MessageChannel::DrainEarlyMessageQueue,
- weak_ptr_factory_.GetWeakPtr()));
-}
+ DCHECK_EQ(WAITING_TO_START, js_message_queue_state_);
+ DCHECK_EQ(WAITING_TO_START, plugin_message_queue_state_);
+
+ ppapi::proxy::HostDispatcher* dispatcher =
+ ppapi::proxy::HostDispatcher::GetForInstance(instance_->pp_instance());
+ // The dispatcher is NULL for in-process.
+ if (dispatcher) {
+ unregister_observer_callback_ =
+ dispatcher->AddSyncMessageStatusObserver(this);
+ }
-void MessageChannel::FromV8ValueComplete(VarConversionResult* result_holder,
- const ScopedPPVar& result,
- bool success) {
- result_holder->ConversionCompleted(result, success);
+ // We can't drain the JS message queue directly since we haven't finished
+ // initializing the PepperWebPluginImpl yet, so the plugin isn't available in
+ // the DOM.
+ DrainJSMessageQueueSoon();
+
+ plugin_message_queue_state_ = SEND_DIRECTLY;
DrainCompletedPluginMessages();
}
-void MessageChannel::DrainCompletedPluginMessages() {
- if (early_message_queue_state_ == QUEUE_MESSAGES)
- return;
+void MessageChannel::SetPassthroughObject(v8::Handle<v8::Object> passthrough) {
+ passthrough_object_.Reset(instance_->GetIsolate(), passthrough);
+}
- while (!plugin_message_queue_.empty() &&
- plugin_message_queue_.front().conversion_completed()) {
- const VarConversionResult& front = plugin_message_queue_.front();
- if (front.success()) {
- instance_->HandleMessage(front.var());
- } else {
- PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(),
- PP_LOGLEVEL_ERROR,
- std::string(),
- kV8ToVarConversionError);
- }
- plugin_message_queue_.pop_front();
+void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) {
+ StringVar* key_string = StringVar::FromPPVar(key);
+ if (key_string) {
+ internal_named_properties_[key_string->value()] = ScopedPPVar(value);
+ } else {
+ NOTREACHED();
}
}
-void MessageChannel::DrainEarlyMessageQueue() {
- DCHECK(early_message_queue_state_ == QUEUE_MESSAGES);
+MessageChannel::MessageChannel(PepperPluginInstanceImpl* instance)
+ : gin::NamedPropertyInterceptor(instance->GetIsolate(), this),
+ instance_(instance),
+ js_message_queue_state_(WAITING_TO_START),
+ blocking_message_depth_(0),
+ plugin_message_queue_state_(WAITING_TO_START),
+ var_converter_(instance->pp_instance(),
+ V8VarConverter::kDisallowObjectVars),
+ weak_ptr_factory_(this) {
+}
+
+gin::ObjectTemplateBuilder MessageChannel::GetObjectTemplateBuilder(
+ v8::Isolate* isolate) {
+ return Wrappable<MessageChannel>::GetObjectTemplateBuilder(isolate)
+ .AddNamedPropertyInterceptor();
+}
- // Take a reference on the PluginInstance. This is because JavaScript code
- // may delete the plugin, which would destroy the PluginInstance and its
- // corresponding MessageChannel.
- scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_);
- while (!early_message_queue_.empty()) {
- PostMessageToJavaScriptImpl(early_message_queue_.front());
- early_message_queue_.pop_front();
+void MessageChannel::BeginBlockOnSyncMessage() {
+ js_message_queue_state_ = QUEUE_MESSAGES;
+ ++blocking_message_depth_;
+}
+
+void MessageChannel::EndBlockOnSyncMessage() {
+ DCHECK_GT(blocking_message_depth_, 0);
+ --blocking_message_depth_;
+ if (!blocking_message_depth_)
+ DrainJSMessageQueueSoon();
+}
+
+v8::Local<v8::Value> MessageChannel::GetNamedProperty(
+ v8::Isolate* isolate,
+ const std::string& identifier) {
+ if (!instance_)
+ return v8::Local<v8::Value>();
+
+ PepperTryCatchV8 try_catch(instance_, &var_converter_, isolate);
+ if (identifier == kPostMessage) {
+ return gin::CreateFunctionTemplate(isolate,
+ base::Bind(&MessageChannel::PostMessageToNative,
+ weak_ptr_factory_.GetWeakPtr()))->GetFunction();
+ } else if (identifier == kPostMessageAndAwaitResponse) {
+ return gin::CreateFunctionTemplate(isolate,
+ base::Bind(&MessageChannel::PostBlockingMessageToNative,
+ weak_ptr_factory_.GetWeakPtr()))->GetFunction();
}
- early_message_queue_state_ = SEND_DIRECTLY;
- DrainCompletedPluginMessages();
+ std::map<std::string, ScopedPPVar>::const_iterator it =
+ internal_named_properties_.find(identifier);
+ if (it != internal_named_properties_.end()) {
+ v8::Handle<v8::Value> result = try_catch.ToV8(it->second.get());
+ if (try_catch.ThrowException())
+ return v8::Local<v8::Value>();
+ return result;
+ }
+
+ PluginObject* plugin_object = GetPluginObject(isolate);
+ if (plugin_object)
+ return plugin_object->GetNamedProperty(isolate, identifier);
+ return v8::Local<v8::Value>();
}
-void MessageChannel::PostMessageToJavaScriptImpl(
- const WebSerializedScriptValue& message_data) {
- DCHECK(instance_);
+bool MessageChannel::SetNamedProperty(v8::Isolate* isolate,
+ const std::string& identifier,
+ v8::Local<v8::Value> value) {
+ if (!instance_)
+ return false;
+ PepperTryCatchV8 try_catch(instance_, &var_converter_, isolate);
+ if (identifier == kPostMessage ||
+ identifier == kPostMessageAndAwaitResponse) {
+ try_catch.ThrowException("Cannot set properties with the name postMessage"
+ "or postMessageAndAwaitResponse");
+ return true;
+ }
- WebPluginContainer* container = instance_->container();
- // It's possible that container() is NULL if the plugin has been removed from
- // the DOM (but the PluginInstance is not destroyed yet).
- if (!container)
- return;
+ // TODO(raymes): This is only used by the gTalk plugin which is deprecated.
+ // Remove passthrough of SetProperty calls as soon as it is removed.
+ PluginObject* plugin_object = GetPluginObject(isolate);
+ if (plugin_object)
+ return plugin_object->SetNamedProperty(isolate, identifier, value);
- WebDOMEvent event =
- container->element().document().createEvent("MessageEvent");
- WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
- msg_event.initMessageEvent("message", // type
- false, // canBubble
- false, // cancelable
- message_data, // data
- "", // origin [*]
- NULL, // source [*]
- ""); // lastEventId
- // [*] Note that the |origin| is only specified for cross-document and server-
- // sent messages, while |source| is only specified for cross-document
- // messages:
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html
- // This currently behaves like Web Workers. On Firefox, Chrome, and Safari
- // at least, postMessage on Workers does not provide the origin or source.
- // TODO(dmichael): Add origin if we change to a more iframe-like origin
- // policy (see crbug.com/81537)
- container->element().dispatchEvent(msg_event);
+ return false;
+}
+
+std::vector<std::string> MessageChannel::EnumerateNamedProperties(
+ v8::Isolate* isolate) {
+ std::vector<std::string> result;
+ PluginObject* plugin_object = GetPluginObject(isolate);
+ if (plugin_object)
+ result = plugin_object->EnumerateNamedProperties(isolate);
+ result.push_back(kPostMessage);
+ result.push_back(kPostMessageAndAwaitResponse);
+ return result;
}
-void MessageChannel::PostMessageToNative(const NPVariant* message_data) {
+void MessageChannel::PostMessageToNative(gin::Arguments* args) {
+ if (!instance_)
+ return;
+ if (args->Length() != 1) {
+ // TODO(raymes): Consider throwing an exception here. We don't now for
+ // backward compatibility.
+ return;
+ }
+
+ v8::Handle<v8::Value> message_data;
+ if (!args->GetNext(&message_data)) {
+ NOTREACHED();
+ }
+
EnqueuePluginMessage(message_data);
DrainCompletedPluginMessages();
}
-void MessageChannel::PostBlockingMessageToNative(const NPVariant* message_data,
- NPVariant* np_result) {
- if (early_message_queue_state_ == QUEUE_MESSAGES) {
- WebBindings::setException(
- np_object_,
+void MessageChannel::PostBlockingMessageToNative(gin::Arguments* args) {
+ if (!instance_)
+ return;
+ PepperTryCatchV8 try_catch(instance_, &var_converter_, args->isolate());
+ if (args->Length() != 1) {
+ try_catch.ThrowException(
+ "postMessageAndAwaitResponse requires one argument");
+ return;
+ }
+
+ v8::Handle<v8::Value> message_data;
+ if (!args->GetNext(&message_data)) {
+ NOTREACHED();
+ }
+
+ if (plugin_message_queue_state_ == WAITING_TO_START) {
+ try_catch.ThrowException(
"Attempted to call a synchronous method on a plugin that was not "
"yet loaded.");
return;
@@ -490,96 +323,148 @@ void MessageChannel::PostBlockingMessageToNative(const NPVariant* message_data,
// TODO(dmichael): Fix this.
// See https://code.google.com/p/chromium/issues/detail?id=367896#c4
if (!plugin_message_queue_.empty()) {
- WebBindings::setException(
- np_object_,
+ try_catch.ThrowException(
"Failed to convert parameter synchronously, because a prior "
"call to postMessage contained a type which required asynchronous "
"transfer which has not completed. Not all types are supported yet by "
"postMessageAndAwaitResponse. See crbug.com/367896.");
return;
}
- ScopedPPVar param;
- if (message_data->type == NPVariantType_Object) {
- // Convert NPVariantType_Object in to an appropriate PP_Var like Dictionary,
- // Array, etc. Note NPVariantToVar would convert to an "Object" PP_Var,
- // which we don't support for Messaging.
- v8::Handle<v8::Value> v8_value = WebBindings::toV8Value(message_data);
- V8VarConverter v8_var_converter(instance_->pp_instance());
- bool success = v8_var_converter.FromV8ValueSync(
- v8_value,
- v8::Isolate::GetCurrent()->GetCurrentContext(),
- &param);
- if (!success) {
- WebBindings::setException(
- np_object_,
- "Failed to convert the given parameter to a PP_Var to send to "
- "the plugin.");
- return;
- }
- } else {
- param = ScopedPPVar(ScopedPPVar::PassRef(),
- NPVariantToPPVar(instance(), message_data));
- }
+ ScopedPPVar param = try_catch.FromV8(message_data);
+ if (try_catch.ThrowException())
+ return;
+
ScopedPPVar pp_result;
bool was_handled = instance_->HandleBlockingMessage(param, &pp_result);
if (!was_handled) {
- WebBindings::setException(
- np_object_,
+ try_catch.ThrowException(
"The plugin has not registered a handler for synchronous messages. "
"See the documentation for PPB_Messaging::RegisterMessageHandler "
"and PPP_MessageHandler.");
return;
}
- v8::Handle<v8::Value> v8_val;
- if (!V8VarConverter(instance_->pp_instance()).ToV8Value(
- pp_result.get(),
- v8::Isolate::GetCurrent()->GetCurrentContext(),
- &v8_val)) {
- WebBindings::setException(
- np_object_,
- "Failed to convert the plugin's result to a JavaScript type.");
+ v8::Handle<v8::Value> v8_result = try_catch.ToV8(pp_result.get());
+ if (try_catch.ThrowException())
return;
- }
- // Success! Convert the result to an NPVariant.
- WebBindings::toNPVariant(v8_val, NULL, np_result);
+
+ args->Return(v8_result);
}
-MessageChannel::~MessageChannel() {
- WebBindings::releaseObject(np_object_);
- if (passthrough_object_)
- WebBindings::releaseObject(passthrough_object_);
+void MessageChannel::PostMessageToJavaScriptImpl(
+ const WebSerializedScriptValue& message_data) {
+ DCHECK(instance_);
+
+ WebPluginContainer* container = instance_->container();
+ // It's possible that container() is NULL if the plugin has been removed from
+ // the DOM (but the PluginInstance is not destroyed yet).
+ if (!container)
+ return;
+
+ WebDOMEvent event =
+ container->element().document().createEvent("MessageEvent");
+ WebDOMMessageEvent msg_event = event.to<WebDOMMessageEvent>();
+ msg_event.initMessageEvent("message", // type
+ false, // canBubble
+ false, // cancelable
+ message_data, // data
+ "", // origin [*]
+ NULL, // source [*]
+ ""); // lastEventId
+ // [*] Note that the |origin| is only specified for cross-document and server-
+ // sent messages, while |source| is only specified for cross-document
+ // messages:
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html
+ // This currently behaves like Web Workers. On Firefox, Chrome, and Safari
+ // at least, postMessage on Workers does not provide the origin or source.
+ // TODO(dmichael): Add origin if we change to a more iframe-like origin
+ // policy (see crbug.com/81537)
+ container->element().dispatchEvent(msg_event);
}
-void MessageChannel::SetPassthroughObject(NPObject* passthrough) {
- // Retain the passthrough object; We need to ensure it lives as long as this
- // MessageChannel.
- if (passthrough)
- WebBindings::retainObject(passthrough);
+PluginObject* MessageChannel::GetPluginObject(v8::Isolate* isolate) {
+ return PluginObject::FromV8Object(isolate,
+ v8::Local<v8::Object>::New(isolate, passthrough_object_));
+}
- // If we had a passthrough set already, release it. Note that we retain the
- // incoming passthrough object first, so that we behave correctly if anyone
- // invokes:
- // SetPassthroughObject(passthrough_object());
- if (passthrough_object_)
- WebBindings::releaseObject(passthrough_object_);
+void MessageChannel::EnqueuePluginMessage(v8::Handle<v8::Value> v8_value) {
+ plugin_message_queue_.push_back(VarConversionResult());
+ // Convert the v8 value in to an appropriate PP_Var like Dictionary,
+ // Array, etc. (We explicitly don't want an "Object" PP_Var, which we don't
+ // support for Messaging.)
+ // TODO(raymes): Possibly change this to use TryCatch to do the conversion and
+ // throw an exception if necessary.
+ V8VarConverter::VarResult conversion_result =
+ var_converter_.FromV8Value(
+ v8_value,
+ v8::Isolate::GetCurrent()->GetCurrentContext(),
+ base::Bind(&MessageChannel::FromV8ValueComplete,
+ weak_ptr_factory_.GetWeakPtr(),
+ &plugin_message_queue_.back()));
+ if (conversion_result.completed_synchronously) {
+ plugin_message_queue_.back().ConversionCompleted(
+ conversion_result.var,
+ conversion_result.success);
+ }
+}
- passthrough_object_ = passthrough;
+void MessageChannel::FromV8ValueComplete(VarConversionResult* result_holder,
+ const ScopedPPVar& result,
+ bool success) {
+ if (!instance_)
+ return;
+ result_holder->ConversionCompleted(result, success);
+ DrainCompletedPluginMessages();
}
-bool MessageChannel::GetReadOnlyProperty(NPIdentifier key,
- NPVariant* value) const {
- std::map<NPIdentifier, ScopedPPVar>::const_iterator it =
- internal_properties_.find(key);
- if (it != internal_properties_.end()) {
- if (value)
- return PPVarToNPVariant(it->second.get(), value);
- return true;
+void MessageChannel::DrainCompletedPluginMessages() {
+ DCHECK(instance_);
+ if (plugin_message_queue_state_ == WAITING_TO_START)
+ return;
+
+ while (!plugin_message_queue_.empty() &&
+ plugin_message_queue_.front().conversion_completed()) {
+ const VarConversionResult& front = plugin_message_queue_.front();
+ if (front.success()) {
+ instance_->HandleMessage(front.var());
+ } else {
+ PpapiGlobals::Get()->LogWithSource(instance()->pp_instance(),
+ PP_LOGLEVEL_ERROR,
+ std::string(),
+ kV8ToVarConversionError);
+ }
+ plugin_message_queue_.pop_front();
}
- return false;
}
-void MessageChannel::SetReadOnlyProperty(PP_Var key, PP_Var value) {
- internal_properties_[PPVarToNPIdentifier(key)] = ScopedPPVar(value);
+void MessageChannel::DrainJSMessageQueue() {
+ if (!instance_)
+ return;
+ if (js_message_queue_state_ == SEND_DIRECTLY)
+ return;
+
+ // Take a reference on the PluginInstance. This is because JavaScript code
+ // may delete the plugin, which would destroy the PluginInstance and its
+ // corresponding MessageChannel.
+ scoped_refptr<PepperPluginInstanceImpl> instance_ref(instance_);
+ while (!js_message_queue_.empty()) {
+ PostMessageToJavaScriptImpl(js_message_queue_.front());
+ js_message_queue_.pop_front();
+ }
+ js_message_queue_state_ = SEND_DIRECTLY;
+}
+
+void MessageChannel::DrainJSMessageQueueSoon() {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MessageChannel::DrainJSMessageQueue,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void MessageChannel::UnregisterSyncMessageStatusObserver() {
+ if (!unregister_observer_callback_.is_null()) {
+ unregister_observer_callback_.Run();
+ unregister_observer_callback_.Reset();
+ }
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/message_channel.h b/chromium/content/renderer/pepper/message_channel.h
index 8c744a04419..4889777ed76 100644
--- a/chromium/content/renderer/pepper/message_channel.h
+++ b/chromium/content/renderer/pepper/message_channel.h
@@ -9,20 +9,31 @@
#include <list>
#include <map>
+#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
+#include "content/renderer/pepper/v8_var_converter.h"
+#include "gin/handle.h"
+#include "gin/interceptor.h"
+#include "gin/wrappable.h"
+#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/shared_impl/resource.h"
#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
-#include "third_party/npapi/bindings/npruntime.h"
+#include "v8/include/v8.h"
struct PP_Var;
+namespace gin {
+class Arguments;
+} // namespace gin
+
namespace ppapi {
class ScopedPPVar;
-}
+} // namespace ppapi
namespace content {
class PepperPluginInstanceImpl;
+class PluginObject;
// MessageChannel implements bidirectional postMessage functionality, allowing
// calls from JavaScript to plugins and vice-versa. See
@@ -37,63 +48,99 @@ class PepperPluginInstanceImpl;
// - The message target won't be limited to instance, and should support
// either plugin-provided or JS objects.
// TODO(dmichael): Add support for separate MessagePorts.
-class MessageChannel {
+class MessageChannel :
+ public gin::Wrappable<MessageChannel>,
+ public gin::NamedPropertyInterceptor,
+ public ppapi::proxy::HostDispatcher::SyncMessageStatusObserver {
public:
- // MessageChannelNPObject is a simple struct that adds a pointer back to a
- // MessageChannel instance. This way, we can use an NPObject to allow
- // JavaScript interactions without forcing MessageChannel to inherit from
- // NPObject.
- struct MessageChannelNPObject : public NPObject {
- MessageChannelNPObject();
- ~MessageChannelNPObject();
-
- base::WeakPtr<MessageChannel> message_channel;
- };
+ static gin::WrapperInfo kWrapperInfo;
- explicit MessageChannel(PepperPluginInstanceImpl* instance);
- ~MessageChannel();
+ // Creates a MessageChannel, returning a pointer to it and sets |result| to
+ // the v8 object which is backed by the message channel. The returned pointer
+ // is only valid as long as the object in |result| is alive.
+ static MessageChannel* Create(PepperPluginInstanceImpl* instance,
+ v8::Persistent<v8::Object>* result);
+
+ ~MessageChannel() override;
+
+ // Called when the instance is deleted. The MessageChannel might outlive the
+ // plugin instance because it is garbage collected.
+ void InstanceDeleted();
// Post a message to the onmessage handler for this channel's instance
// asynchronously.
void PostMessageToJavaScript(PP_Var message_data);
- // Post a message to the plugin's HandleMessage function for this channel's
- // instance.
- void PostMessageToNative(const NPVariant* message_data);
- // Post a message to the plugin's HandleBlocking Message function for this
- // channel's instance synchronously, and return a result.
- void PostBlockingMessageToNative(const NPVariant* message_data,
- NPVariant* np_result);
+ // Messages are queued initially. After the PepperPluginInstanceImpl is ready
+ // to send and handle messages, users of MessageChannel should call
+ // Start().
+ void Start();
- // Return the NPObject* to which we should forward any calls which aren't
- // related to postMessage. Note that this can be NULL; it only gets set if
+ // Set the V8Object to which we should forward any calls which aren't
+ // related to postMessage. Note that this can be empty; it only gets set if
// there is a scriptable 'InstanceObject' associated with this channel's
// instance.
- NPObject* passthrough_object() { return passthrough_object_; }
- void SetPassthroughObject(NPObject* passthrough);
-
- NPObject* np_object() { return np_object_; }
+ void SetPassthroughObject(v8::Handle<v8::Object> passthrough);
PepperPluginInstanceImpl* instance() { return instance_; }
- // Messages are queued initially. After the PepperPluginInstanceImpl is ready
- // to send and handle messages, users of MessageChannel should call
- // Start().
- void Start();
-
- bool GetReadOnlyProperty(NPIdentifier key, NPVariant* value) const;
void SetReadOnlyProperty(PP_Var key, PP_Var value);
private:
- // Struct for storing the result of a NPVariant being converted to a PP_Var.
+ // Struct for storing the result of a v8 object being converted to a PP_Var.
struct VarConversionResult;
- void EnqueuePluginMessage(const NPVariant* variant);
+ explicit MessageChannel(PepperPluginInstanceImpl* instance);
+
+ // gin::NamedPropertyInterceptor
+ v8::Local<v8::Value> GetNamedProperty(v8::Isolate* isolate,
+ const std::string& property) override;
+ bool SetNamedProperty(v8::Isolate* isolate,
+ const std::string& property,
+ v8::Local<v8::Value> value) override;
+ std::vector<std::string> EnumerateNamedProperties(
+ v8::Isolate* isolate) override;
+
+ // gin::Wrappable
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
+
+ // ppapi::proxy::HostDispatcher::SyncMessageStatusObserver
+ void BeginBlockOnSyncMessage() override;
+ void EndBlockOnSyncMessage() override;
+
+ // Post a message to the plugin's HandleMessage function for this channel's
+ // instance.
+ void PostMessageToNative(gin::Arguments* args);
+ // Post a message to the plugin's HandleBlocking Message function for this
+ // channel's instance synchronously, and return a result.
+ void PostBlockingMessageToNative(gin::Arguments* args);
+
+ // Post a message to the onmessage handler for this channel's instance
+ // synchronously. This is used by PostMessageToJavaScript.
+ void PostMessageToJavaScriptImpl(
+ const blink::WebSerializedScriptValue& message_data);
+
+ PluginObject* GetPluginObject(v8::Isolate* isolate);
+
+ void EnqueuePluginMessage(v8::Handle<v8::Value> v8_value);
void FromV8ValueComplete(VarConversionResult* result_holder,
const ppapi::ScopedPPVar& result_var,
bool success);
+
+ // Drain the queue of messages that are going to the plugin. All "completed"
+ // messages at the head of the queue will be sent; any messages awaiting
+ // conversion as well as messages after that in the queue will not be sent.
void DrainCompletedPluginMessages();
+ // Drain the queue of messages that are going to JavaScript.
+ void DrainJSMessageQueue();
+ // PostTask to call DrainJSMessageQueue() soon. Use this when you want to
+ // send the messages, but can't immediately (e.g., because the instance is
+ // not ready or JavaScript is on the stack).
+ void DrainJSMessageQueueSoon();
+
+ void UnregisterSyncMessageStatusObserver();
PepperPluginInstanceImpl* instance_;
@@ -102,27 +149,23 @@ class MessageChannel {
// postMessage. This is necessary to support backwards-compatibility, and
// also trusted plugins for which we will continue to support synchronous
// scripting.
- NPObject* passthrough_object_;
-
- // The NPObject we use to expose postMessage to JavaScript.
- MessageChannelNPObject* np_object_;
+ v8::Persistent<v8::Object> passthrough_object_;
- // Post a message to the onmessage handler for this channel's instance
- // synchronously. This is used by PostMessageToJavaScript.
- void PostMessageToJavaScriptImpl(
- const blink::WebSerializedScriptValue& message_data);
- // Post a message to the PPP_Instance HandleMessage function for this
- // channel's instance. This is used by PostMessageToNative.
- void PostMessageToNativeImpl(PP_Var message_data);
-
- void DrainEarlyMessageQueue();
-
- std::deque<blink::WebSerializedScriptValue> early_message_queue_;
- enum EarlyMessageQueueState {
- QUEUE_MESSAGES, // Queue JS messages.
- SEND_DIRECTLY, // Post JS messages directly.
+ enum MessageQueueState {
+ WAITING_TO_START, // Waiting for Start() to be called. Queue messages.
+ QUEUE_MESSAGES, // Queue messages temporarily.
+ SEND_DIRECTLY, // Post messages directly.
};
- EarlyMessageQueueState early_message_queue_state_;
+
+ // This queue stores values being posted to JavaScript.
+ std::deque<blink::WebSerializedScriptValue> js_message_queue_;
+ MessageQueueState js_message_queue_state_;
+ // When the renderer is sending a blocking message to the plugin, we will
+ // queue Plugin->JS messages temporarily to avoid re-entering JavaScript. This
+ // counts how many blocking renderer->plugin messages are on the stack so that
+ // we only begin sending messages to JavaScript again when the depth reaches
+ // zero.
+ int blocking_message_depth_;
// This queue stores vars that are being sent to the plugin. Because
// conversion can happen asynchronously for object types, the queue stores
@@ -133,8 +176,15 @@ class MessageChannel {
// calls to push_back or pop_front; hence why we're using list. (deque would
// probably also work, but is less clearly specified).
std::list<VarConversionResult> plugin_message_queue_;
+ MessageQueueState plugin_message_queue_state_;
+
+ std::map<std::string, ppapi::ScopedPPVar> internal_named_properties_;
+
+ V8VarConverter var_converter_;
- std::map<NPIdentifier, ppapi::ScopedPPVar> internal_properties_;
+ // A callback to invoke at shutdown to ensure we unregister ourselves as
+ // Observers for sync messages.
+ base::Closure unregister_observer_callback_;
// This is used to ensure pending tasks will not fire after this object is
// destroyed.
diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
index 62c9d650f1b..74cff72a40d 100644
--- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
+++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h
@@ -23,7 +23,7 @@ class MockRendererPpapiHost : public RendererPpapiHost {
// This function takes the RenderView and instance that the mock resource
// host will be associated with.
MockRendererPpapiHost(RenderView* render_view, PP_Instance instance);
- virtual ~MockRendererPpapiHost();
+ ~MockRendererPpapiHost() override;
ppapi::proxy::ResourceMessageTestSink& sink() { return sink_; }
PP_Instance pp_instance() const { return pp_instance_; }
@@ -32,34 +32,30 @@ class MockRendererPpapiHost : public RendererPpapiHost {
void set_has_user_gesture(bool gesture) { has_user_gesture_ = gesture; }
// RendererPpapiHost.
- virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE;
- virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE;
- virtual PepperPluginInstance* GetPluginInstance(PP_Instance instance) const
- OVERRIDE;
- virtual RenderFrame* GetRenderFrameForInstance(PP_Instance instance) const
- OVERRIDE;
- virtual RenderView* GetRenderViewForInstance(PP_Instance instance) const
- OVERRIDE;
- virtual blink::WebPluginContainer* GetContainerForInstance(
- PP_Instance instance) const OVERRIDE;
- virtual base::ProcessId GetPluginPID() const OVERRIDE;
- virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE;
- virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE;
- virtual gfx::Point PluginPointToRenderFrame(PP_Instance instance,
- const gfx::Point& pt) const
- OVERRIDE;
- virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ ppapi::host::PpapiHost* GetPpapiHost() override;
+ bool IsValidInstance(PP_Instance instance) const override;
+ PepperPluginInstance* GetPluginInstance(PP_Instance instance) const override;
+ RenderFrame* GetRenderFrameForInstance(PP_Instance instance) const override;
+ RenderView* GetRenderViewForInstance(PP_Instance instance) const override;
+ blink::WebPluginContainer* GetContainerForInstance(
+ PP_Instance instance) const override;
+ base::ProcessId GetPluginPID() const override;
+ bool HasUserGesture(PP_Instance instance) const override;
+ int GetRoutingIDForWidget(PP_Instance instance) const override;
+ gfx::Point PluginPointToRenderFrame(PP_Instance instance,
+ const gfx::Point& pt) const override;
+ IPC::PlatformFileForTransit ShareHandleWithRemote(
base::PlatformFile handle,
- bool should_close_source) OVERRIDE;
- virtual bool IsRunningInProcess() const OVERRIDE;
- virtual std::string GetPluginName() const OVERRIDE;
- virtual void SetToExternalPluginHost() OVERRIDE;
- virtual void CreateBrowserResourceHosts(
+ bool should_close_source) override;
+ bool IsRunningInProcess() const override;
+ std::string GetPluginName() const override;
+ void SetToExternalPluginHost() override;
+ void CreateBrowserResourceHosts(
PP_Instance instance,
const std::vector<IPC::Message>& nested_msgs,
- const base::Callback<void(const std::vector<int>&)>& callback) const
- OVERRIDE;
- virtual GURL GetDocumentURL(PP_Instance instance) const OVERRIDE;
+ const base::Callback<void(const std::vector<int>&)>& callback)
+ const override;
+ GURL GetDocumentURL(PP_Instance instance) const override;
private:
ppapi::proxy::ResourceMessageTestSink sink_;
diff --git a/chromium/content/renderer/pepper/mock_resource.h b/chromium/content/renderer/pepper/mock_resource.h
index d7a09c3a44a..20ce44ff138 100644
--- a/chromium/content/renderer/pepper/mock_resource.h
+++ b/chromium/content/renderer/pepper/mock_resource.h
@@ -18,7 +18,7 @@ class MockResource : public ppapi::Resource {
: Resource(ppapi::OBJECT_IS_IMPL, instance) {}
private:
- virtual ~MockResource() {}
+ ~MockResource() override {}
};
} // namespace content
diff --git a/chromium/content/renderer/pepper/npapi_glue.cc b/chromium/content/renderer/pepper/npapi_glue.cc
deleted file mode 100644
index 990d3302e89..00000000000
--- a/chromium/content/renderer/pepper/npapi_glue.cc
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright (c) 2011 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 "content/renderer/pepper/npapi_glue.h"
-
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_util.h"
-#include "content/renderer/pepper/host_array_buffer_var.h"
-#include "content/renderer/pepper/host_globals.h"
-#include "content/renderer/pepper/host_var_tracker.h"
-#include "content/renderer/pepper/npobject_var.h"
-#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/pepper/plugin_module.h"
-#include "content/renderer/pepper/plugin_object.h"
-#include "ppapi/c/pp_var.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/npruntime.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "v8/include/v8.h"
-
-using ppapi::NPObjectVar;
-using ppapi::PpapiGlobals;
-using ppapi::StringVar;
-using ppapi::Var;
-using blink::WebArrayBuffer;
-using blink::WebBindings;
-using blink::WebLocalFrame;
-using blink::WebPluginContainer;
-
-namespace content {
-
-namespace {
-
-const char kInvalidPluginValue[] = "Error: Plugin returned invalid value.";
-
-PP_Var NPObjectToPPVarImpl(PepperPluginInstanceImpl* instance,
- NPObject* object,
- v8::Local<v8::Context> context) {
- DCHECK(object);
- if (context.IsEmpty())
- return PP_MakeUndefined();
- v8::Context::Scope context_scope(context);
-
- WebArrayBuffer buffer;
- // TODO(dmichael): Should I protect against duplicate Vars representing the
- // same array buffer? It's probably not worth the trouble, since it will only
- // affect in-process plugins.
- if (WebBindings::getArrayBuffer(object, &buffer)) {
- scoped_refptr<HostArrayBufferVar> buffer_var(
- new HostArrayBufferVar(buffer));
- return buffer_var->GetPPVar();
- }
- scoped_refptr<NPObjectVar> object_var(
- HostGlobals::Get()->host_var_tracker()->NPObjectVarForNPObject(
- instance->pp_instance(), object));
- if (!object_var.get()) { // No object for this module yet, make a new one.
- object_var = new NPObjectVar(instance->pp_instance(), object);
- }
- return object_var->GetPPVar();
-}
-
-} // namespace
-
-// Utilities -------------------------------------------------------------------
-
-bool PPVarToNPVariant(PP_Var var, NPVariant* result) {
- switch (var.type) {
- case PP_VARTYPE_UNDEFINED:
- VOID_TO_NPVARIANT(*result);
- break;
- case PP_VARTYPE_NULL:
- NULL_TO_NPVARIANT(*result);
- break;
- case PP_VARTYPE_BOOL:
- BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
- break;
- case PP_VARTYPE_INT32:
- INT32_TO_NPVARIANT(var.value.as_int, *result);
- break;
- case PP_VARTYPE_DOUBLE:
- DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
- break;
- case PP_VARTYPE_STRING: {
- StringVar* string = StringVar::FromPPVar(var);
- if (!string) {
- VOID_TO_NPVARIANT(*result);
- return false;
- }
- const std::string& value = string->value();
- char* c_string = static_cast<char*>(malloc(value.size()));
- memcpy(c_string, value.data(), value.size());
- STRINGN_TO_NPVARIANT(c_string, value.size(), *result);
- break;
- }
- case PP_VARTYPE_OBJECT: {
- scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
- if (!object.get()) {
- VOID_TO_NPVARIANT(*result);
- return false;
- }
- OBJECT_TO_NPVARIANT(WebBindings::retainObject(object->np_object()),
- *result);
- break;
- }
- // The following types are not supported for use with PPB_Var_Deprecated,
- // because PPB_Var_Deprecated is only for trusted plugins, and the trusted
- // plugins we have don't need these types. We can add support in the future
- // if it becomes necessary.
- case PP_VARTYPE_ARRAY:
- case PP_VARTYPE_DICTIONARY:
- case PP_VARTYPE_ARRAY_BUFFER:
- case PP_VARTYPE_RESOURCE:
- VOID_TO_NPVARIANT(*result);
- break;
- }
- return true;
-}
-
-PP_Var NPVariantToPPVar(PepperPluginInstanceImpl* instance,
- const NPVariant* variant) {
- switch (variant->type) {
- case NPVariantType_Void:
- return PP_MakeUndefined();
- case NPVariantType_Null:
- return PP_MakeNull();
- case NPVariantType_Bool:
- return PP_MakeBool(PP_FromBool(NPVARIANT_TO_BOOLEAN(*variant)));
- case NPVariantType_Int32:
- return PP_MakeInt32(NPVARIANT_TO_INT32(*variant));
- case NPVariantType_Double:
- return PP_MakeDouble(NPVARIANT_TO_DOUBLE(*variant));
- case NPVariantType_String:
- return StringVar::StringToPPVar(
- NPVARIANT_TO_STRING(*variant).UTF8Characters,
- NPVARIANT_TO_STRING(*variant).UTF8Length);
- case NPVariantType_Object:
- return NPObjectToPPVar(instance, NPVARIANT_TO_OBJECT(*variant));
- }
- NOTREACHED();
- return PP_MakeUndefined();
-}
-
-NPIdentifier PPVarToNPIdentifier(PP_Var var) {
- switch (var.type) {
- case PP_VARTYPE_STRING: {
- StringVar* string = StringVar::FromPPVar(var);
- if (!string)
- return NULL;
- return WebBindings::getStringIdentifier(string->value().c_str());
- }
- case PP_VARTYPE_INT32:
- return WebBindings::getIntIdentifier(var.value.as_int);
- default:
- return NULL;
- }
-}
-
-PP_Var NPIdentifierToPPVar(NPIdentifier id) {
- const NPUTF8* string_value = NULL;
- int32_t int_value = 0;
- bool is_string = false;
- WebBindings::extractIdentifierData(id, string_value, int_value, is_string);
- if (is_string)
- return StringVar::StringToPPVar(string_value);
-
- return PP_MakeInt32(int_value);
-}
-
-PP_Var NPObjectToPPVar(PepperPluginInstanceImpl* instance, NPObject* object) {
- WebPluginContainer* container = instance->container();
- // It's possible that container() is NULL if the plugin has been removed from
- // the DOM (but the PluginInstance is not destroyed yet).
- if (!container)
- return PP_MakeUndefined();
- WebLocalFrame* frame = container->element().document().frame();
- if (!frame)
- return PP_MakeUndefined();
-
- v8::HandleScope scope(instance->GetIsolate());
- v8::Local<v8::Context> context = frame->mainWorldScriptContext();
- return NPObjectToPPVarImpl(instance, object, context);
-}
-
-PP_Var NPObjectToPPVarForTest(PepperPluginInstanceImpl* instance,
- NPObject* object) {
- v8::Isolate* test_isolate = v8::Isolate::New();
- PP_Var result = PP_MakeUndefined();
- {
- v8::HandleScope scope(test_isolate);
- v8::Isolate::Scope isolate_scope(test_isolate);
- v8::Local<v8::Context> context = v8::Context::New(test_isolate);
- result = NPObjectToPPVarImpl(instance, object, context);
- }
- test_isolate->Dispose();
- return result;
-}
-
-// PPResultAndExceptionToNPResult ----------------------------------------------
-
-PPResultAndExceptionToNPResult::PPResultAndExceptionToNPResult(
- NPObject* object_var,
- NPVariant* np_result)
- : object_var_(object_var),
- np_result_(np_result),
- exception_(PP_MakeUndefined()),
- success_(false),
- checked_exception_(false) {}
-
-PPResultAndExceptionToNPResult::~PPResultAndExceptionToNPResult() {
- // The user should have called SetResult or CheckExceptionForNoResult
- // before letting this class go out of scope, or the exception will have
- // been lost.
- DCHECK(checked_exception_);
-
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(exception_);
-}
-
-// Call this with the return value of the PPAPI function. It will convert
-// the result to the NPVariant output parameter and pass any exception on to
-// the JS engine. It will update the success flag and return it.
-bool PPResultAndExceptionToNPResult::SetResult(PP_Var result) {
- DCHECK(!checked_exception_); // Don't call more than once.
- DCHECK(np_result_); // Should be expecting a result.
-
- checked_exception_ = true;
-
- if (has_exception()) {
- ThrowException();
- success_ = false;
- } else if (!PPVarToNPVariant(result, np_result_)) {
- WebBindings::setException(object_var_, kInvalidPluginValue);
- success_ = false;
- } else {
- success_ = true;
- }
-
- // No matter what happened, we need to release the reference to the
- // value passed in. On success, a reference to this value will be in
- // the np_result_.
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(result);
- return success_;
-}
-
-// Call this after calling a PPAPI function that could have set the
-// exception. It will pass the exception on to the JS engine and update
-// the success flag.
-//
-// The success flag will be returned.
-bool PPResultAndExceptionToNPResult::CheckExceptionForNoResult() {
- DCHECK(!checked_exception_); // Don't call more than once.
- DCHECK(!np_result_); // Can't have a result when doing this.
-
- checked_exception_ = true;
-
- if (has_exception()) {
- ThrowException();
- success_ = false;
- return false;
- }
- success_ = true;
- return true;
-}
-
-// Call this to ignore any exception. This prevents the DCHECK from failing
-// in the destructor.
-void PPResultAndExceptionToNPResult::IgnoreException() {
- checked_exception_ = true;
-}
-
-// Throws the current exception to JS. The exception must be set.
-void PPResultAndExceptionToNPResult::ThrowException() {
- StringVar* string = StringVar::FromPPVar(exception_);
- if (string)
- WebBindings::setException(object_var_, string->value().c_str());
-}
-
-// PPVarArrayFromNPVariantArray ------------------------------------------------
-
-PPVarArrayFromNPVariantArray::PPVarArrayFromNPVariantArray(
- PepperPluginInstanceImpl* instance,
- size_t size,
- const NPVariant* variants)
- : size_(size) {
- if (size_ > 0) {
- array_.reset(new PP_Var[size_]);
- for (size_t i = 0; i < size_; i++)
- array_[i] = NPVariantToPPVar(instance, &variants[i]);
- }
-}
-
-PPVarArrayFromNPVariantArray::~PPVarArrayFromNPVariantArray() {
- ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
- for (size_t i = 0; i < size_; i++)
- var_tracker->ReleaseVar(array_[i]);
-}
-
-// PPVarFromNPObject -----------------------------------------------------------
-
-PPVarFromNPObject::PPVarFromNPObject(PepperPluginInstanceImpl* instance,
- NPObject* object)
- : var_(NPObjectToPPVar(instance, object)) {}
-
-PPVarFromNPObject::~PPVarFromNPObject() {
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var_);
-}
-
-// NPObjectAccessorWithIdentifier ----------------------------------------------
-
-NPObjectAccessorWithIdentifier::NPObjectAccessorWithIdentifier(
- NPObject* object,
- NPIdentifier identifier,
- bool allow_integer_identifier)
- : object_(PluginObject::FromNPObject(object)),
- identifier_(PP_MakeUndefined()) {
- if (object_) {
- identifier_ = NPIdentifierToPPVar(identifier);
- if (identifier_.type == PP_VARTYPE_INT32 && !allow_integer_identifier)
- identifier_.type = PP_VARTYPE_UNDEFINED; // Mark it invalid.
- }
-}
-
-NPObjectAccessorWithIdentifier::~NPObjectAccessorWithIdentifier() {
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(identifier_);
-}
-
-// TryCatch --------------------------------------------------------------------
-
-TryCatch::TryCatch(PP_Var* exception)
- : has_exception_(exception && exception->type != PP_VARTYPE_UNDEFINED),
- exception_(exception) {
- WebBindings::pushExceptionHandler(&TryCatch::Catch, this);
-}
-
-TryCatch::~TryCatch() { WebBindings::popExceptionHandler(); }
-
-void TryCatch::SetException(const char* message) {
- if (!has_exception()) {
- has_exception_ = true;
- if (exception_) {
- if (!message)
- message = "Unknown exception.";
- *exception_ = ppapi::StringVar::StringToPPVar(message, strlen(message));
- }
- }
-}
-
-// static
-void TryCatch::Catch(void* self, const char* message) {
- static_cast<TryCatch*>(self)->SetException(message);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/npapi_glue.h b/chromium/content/renderer/pepper/npapi_glue.h
deleted file mode 100644
index 7bcbbff969b..00000000000
--- a/chromium/content/renderer/pepper/npapi_glue.h
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright (c) 2011 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 CONTENT_RENDERER_PEPPER_NPAPI_GLUE_H_
-#define CONTENT_RENDERER_PEPPER_NPAPI_GLUE_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "ppapi/c/pp_module.h"
-#include "ppapi/c/pp_var.h"
-
-struct NPObject;
-typedef struct _NPVariant NPVariant;
-typedef void* NPIdentifier;
-
-namespace content {
-
-class PepperPluginInstanceImpl;
-class PluginObject;
-
-// Utilities -------------------------------------------------------------------
-
-// Converts the given PP_Var to an NPVariant, returning true on success.
-// False means that the given variant is invalid. In this case, the result
-// NPVariant will be set to a void one.
-//
-// The contents of the PP_Var will be copied unless the PP_Var corresponds to
-// an object.
-bool PPVarToNPVariant(PP_Var var, NPVariant* result);
-
-// Returns a PP_Var that corresponds to the given NPVariant. The contents of
-// the NPVariant will be copied unless the NPVariant corresponds to an
-// object. This will handle all Variant types including POD, strings, and
-// objects.
-//
-// The returned PP_Var will have a refcount of 1, this passing ownership of
-// the reference to the caller. This is suitable for returning to a plugin.
-PP_Var NPVariantToPPVar(PepperPluginInstanceImpl* instance,
- const NPVariant* variant);
-
-// Returns a NPIdentifier that corresponds to the given PP_Var. The contents
-// of the PP_Var will be copied. Returns 0 if the given PP_Var is not a a
-// string or integer type.
-NPIdentifier PPVarToNPIdentifier(PP_Var var);
-
-// Returns a PP_Var corresponding to the given identifier. In the case of
-// a string identifier, the returned string will have a reference count of 1.
-PP_Var NPIdentifierToPPVar(NPIdentifier id);
-
-// Helper function to create a PP_Var of type object that contains the given
-// NPObject for use byt he given module. Calling this function multiple times
-// given the same module + NPObject results in the same PP_Var, assuming that
-// there is still a PP_Var with a reference open to it from the previous
-// call.
-//
-// The instance is necessary because we can have different instances pointing to
-// the same NPObject, and we want to keep their refs separate.
-//
-// If no ObjectVar currently exists corresponding to the NPObject, one is
-// created associated with the given module.
-//
-// Note: this could easily be changed to take a PP_Instance instead if that
-// makes certain calls in the future easier. Currently all callers have a
-// PluginInstance so that's what we use here.
-CONTENT_EXPORT PP_Var
- NPObjectToPPVar(PepperPluginInstanceImpl* instance, NPObject* object);
-
-// This version creates a default v8::Context rather than using the one from
-// the container of |instance|. It is only for use in unit tests, where we don't
-// have a real container for |instance|.
-CONTENT_EXPORT PP_Var NPObjectToPPVarForTest(PepperPluginInstanceImpl* instance,
- NPObject* object);
-
-// PPResultAndExceptionToNPResult ----------------------------------------------
-
-// Convenience object for converting a PPAPI call that can throw an exception
-// and optionally return a value, back to the NPAPI layer which expects a
-// NPVariant as a result.
-//
-// Normal usage is that you will pass the result of exception() to the
-// PPAPI function as the exception output parameter. Then you will either
-// call SetResult with the result of the PPAPI call, or
-// CheckExceptionForNoResult if the PPAPI call doesn't return a PP_Var.
-//
-// Both SetResult and CheckExceptionForNoResult will throw an exception to
-// the JavaScript library if the plugin reported an exception. SetResult
-// will additionally convert the result to an NPVariant and write it to the
-// output parameter given in the constructor.
-class PPResultAndExceptionToNPResult {
- public:
- // The object_var parameter is the object to associate any exception with.
- // It may not be NULL.
- //
- // The np_result parameter is the NPAPI result output parameter. This may be
- // NULL if there is no NPVariant result (like for HasProperty). If this is
- // specified, you must call SetResult() to set it. If it is not, you must
- // call CheckExceptionForNoResult to do the exception checking with no result
- // conversion.
- PPResultAndExceptionToNPResult(NPObject* object_var, NPVariant* np_result);
-
- ~PPResultAndExceptionToNPResult();
-
- // Returns true if an exception has been set.
- bool has_exception() const { return exception_.type != PP_VARTYPE_UNDEFINED; }
-
- // Returns a pointer to the exception. You would pass this to the PPAPI
- // function as the exception parameter. If it is set to non-void, this object
- // will take ownership of destroying it.
- PP_Var* exception() { return &exception_; }
-
- // Returns true if everything succeeded with no exception. This is valid only
- // after calling SetResult/CheckExceptionForNoResult.
- bool success() const { return success_; }
-
- // Call this with the return value of the PPAPI function. It will convert
- // the result to the NPVariant output parameter and pass any exception on to
- // the JS engine. It will update the success flag and return it.
- bool SetResult(PP_Var result);
-
- // Call this after calling a PPAPI function that could have set the
- // exception. It will pass the exception on to the JS engine and update
- // the success flag.
- //
- // The success flag will be returned.
- bool CheckExceptionForNoResult();
-
- // Call this to ignore any exception. This prevents the DCHECK from failing
- // in the destructor.
- void IgnoreException();
-
- private:
- // Throws the current exception to JS. The exception must be set.
- void ThrowException();
-
- NPObject* object_var_; // Non-owning ref (see constructor).
- NPVariant* np_result_; // Output value, possibly NULL (see constructor).
- PP_Var exception_; // Exception set by the PPAPI call. We own a ref to it.
- bool success_; // See the success() function above.
- bool checked_exception_; // SetResult/CheckExceptionForNoResult was called.
-
- DISALLOW_COPY_AND_ASSIGN(PPResultAndExceptionToNPResult);
-};
-
-// PPVarArrayFromNPVariantArray ------------------------------------------------
-
-// Converts an array of NPVariants to an array of PP_Var, and scopes the
-// ownership of the PP_Var. This is used when converting argument lists from
-// WebKit to the plugin.
-class PPVarArrayFromNPVariantArray {
- public:
- PPVarArrayFromNPVariantArray(PepperPluginInstanceImpl* instance,
- size_t size,
- const NPVariant* variants);
- ~PPVarArrayFromNPVariantArray();
-
- PP_Var* array() { return array_.get(); }
-
- private:
- size_t size_;
- scoped_ptr<PP_Var[]> array_;
-
- DISALLOW_COPY_AND_ASSIGN(PPVarArrayFromNPVariantArray);
-};
-
-// PPVarFromNPObject -----------------------------------------------------------
-
-// Converts an NPObject tp PP_Var, and scopes the ownership of the PP_Var. This
-// is used when converting 'this' pointer from WebKit to the plugin.
-class PPVarFromNPObject {
- public:
- PPVarFromNPObject(PepperPluginInstanceImpl* instance, NPObject* object);
- ~PPVarFromNPObject();
-
- PP_Var var() const { return var_; }
-
- private:
- const PP_Var var_;
-
- DISALLOW_COPY_AND_ASSIGN(PPVarFromNPObject);
-};
-
-// NPObjectAccessorWithIdentifier ----------------------------------------------
-
-// Helper class for our NPObject wrapper. This converts a call from WebKit
-// where it gives us an NPObject and an NPIdentifier to an easily-accessible
-// ObjectVar (corresponding to the NPObject) and PP_Var (corresponding to the
-// NPIdentifier).
-//
-// If the NPObject or identifier is invalid, we'll set is_valid() to false.
-// The caller should check is_valid() before doing anything with the class.
-//
-// JS can't have integer functions, so when dealing with these, we don't want
-// to allow integer identifiers. The calling code can decode if it wants to
-// allow integer identifiers (like for property access) or prohibit them
-// (like for method calling) by setting |allow_integer_identifier|. If this
-// is false and the identifier is an integer, we'll set is_valid() to false.
-//
-// Getting an integer identifier in this case should be impossible. V8
-// shouldn't be allowing this, and the Pepper Var calls from the plugin are
-// supposed to error out before calling into V8 (which will then call us back).
-// Aside from an egregious error, the only time this could happen is an NPAPI
-// plugin calling us.
-class NPObjectAccessorWithIdentifier {
- public:
- NPObjectAccessorWithIdentifier(NPObject* object,
- NPIdentifier identifier,
- bool allow_integer_identifier);
- ~NPObjectAccessorWithIdentifier();
-
- // Returns true if both the object and identifier are valid.
- bool is_valid() const {
- return object_ && identifier_.type != PP_VARTYPE_UNDEFINED;
- }
-
- PluginObject* object() { return object_; }
- PP_Var identifier() const { return identifier_; }
-
- private:
- PluginObject* object_;
- PP_Var identifier_;
-
- DISALLOW_COPY_AND_ASSIGN(NPObjectAccessorWithIdentifier);
-};
-
-// TryCatch --------------------------------------------------------------------
-
-// Instantiate this object on the stack to catch V8 exceptions and pass them
-// to an optional out parameter supplied by the plugin.
-class TryCatch {
- public:
- // The given exception may be NULL if the consumer isn't interested in
- // catching exceptions. If non-NULL, the given var will be updated if any
- // exception is thrown (so it must outlive the TryCatch object).
- TryCatch(PP_Var* exception);
- ~TryCatch();
-
- // Returns true is an exception has been thrown. This can be true immediately
- // after construction if the var passed to the constructor is non-void.
- bool has_exception() const { return has_exception_; }
-
- // Sets the given exception. If an exception has been previously set, this
- // function will do nothing (normally you want only the first exception).
- void SetException(const char* message);
-
- private:
- static void Catch(void* self, const char* message);
-
- // True if an exception has been thrown. Since the exception itself may be
- // NULL if the plugin isn't interested in getting the exception, this will
- // always indicate if SetException has been called, regardless of whether
- // the exception itself has been stored.
- bool has_exception_;
-
- // May be null if the consumer isn't interesting in catching exceptions.
- PP_Var* exception_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_NPAPI_GLUE_H_
diff --git a/chromium/content/renderer/pepper/npobject_var.cc b/chromium/content/renderer/pepper/npobject_var.cc
deleted file mode 100644
index 50ccf87b4df..00000000000
--- a/chromium/content/renderer/pepper/npobject_var.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2011 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 "content/renderer/pepper/npobject_var.h"
-
-#include "base/logging.h"
-#include "content/renderer/pepper/host_globals.h"
-#include "content/renderer/pepper/host_var_tracker.h"
-#include "ppapi/c/pp_var.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-using blink::WebBindings;
-
-namespace ppapi {
-
-// NPObjectVar -----------------------------------------------------------------
-
-NPObjectVar::NPObjectVar(PP_Instance instance, NPObject* np_object)
- : pp_instance_(instance), np_object_(np_object) {
- WebBindings::retainObject(np_object_);
- content::HostGlobals::Get()->host_var_tracker()->AddNPObjectVar(this);
-}
-
-NPObjectVar::~NPObjectVar() {
- if (pp_instance())
- content::HostGlobals::Get()->host_var_tracker()->RemoveNPObjectVar(this);
- WebBindings::releaseObject(np_object_);
-}
-
-NPObjectVar* NPObjectVar::AsNPObjectVar() { return this; }
-
-PP_VarType NPObjectVar::GetType() const { return PP_VARTYPE_OBJECT; }
-
-void NPObjectVar::InstanceDeleted() {
- DCHECK(pp_instance_);
- content::HostGlobals::Get()->host_var_tracker()->RemoveNPObjectVar(this);
- pp_instance_ = 0;
-}
-
-// static
-scoped_refptr<NPObjectVar> NPObjectVar::FromPPVar(PP_Var var) {
- if (var.type != PP_VARTYPE_OBJECT)
- return scoped_refptr<NPObjectVar>(NULL);
- scoped_refptr<Var> var_object(
- PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
- if (!var_object.get())
- return scoped_refptr<NPObjectVar>();
- return scoped_refptr<NPObjectVar>(var_object->AsNPObjectVar());
-}
-
-} // namespace ppapi
diff --git a/chromium/content/renderer/pepper/npobject_var.h b/chromium/content/renderer/pepper/npobject_var.h
deleted file mode 100644
index 68f90970893..00000000000
--- a/chromium/content/renderer/pepper/npobject_var.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_PEPPER_NPOBJECT_VAR_H_
-#define CONTENT_RENDERER_PEPPER_NPOBJECT_VAR_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "ppapi/c/pp_instance.h"
-#include "ppapi/shared_impl/var.h"
-#include "content/common/content_export.h"
-
-typedef struct NPObject NPObject;
-typedef struct _NPVariant NPVariant;
-typedef void* NPIdentifier;
-
-namespace ppapi {
-
-// NPObjectVar -----------------------------------------------------------------
-
-// Represents a JavaScript object Var. By itself, this represents random
-// NPObjects that a given plugin (identified by the resource's module) wants to
-// reference. If two different modules reference the same NPObject (like the
-// "window" object), then there will be different NPObjectVar's (and hence
-// PP_Var IDs) for each module. This allows us to track all references owned by
-// a given module and free them when the plugin exits independently of other
-// plugins that may be running at the same time.
-class NPObjectVar : public Var {
- public:
- // You should always use FromNPObject to create an NPObjectVar. This function
- // guarantees that we maintain the 1:1 mapping between NPObject and
- // NPObjectVar.
- NPObjectVar(PP_Instance instance, NPObject* np_object);
-
- // Var overrides.
- virtual NPObjectVar* AsNPObjectVar() OVERRIDE;
- virtual PP_VarType GetType() const OVERRIDE;
-
- // Returns the underlying NPObject corresponding to this NPObjectVar.
- // Guaranteed non-NULL.
- NPObject* np_object() const { return np_object_; }
-
- // Notification that the instance was deleted, the internal reference will be
- // zeroed out.
- void InstanceDeleted();
-
- // Possibly 0 if the object has outlived its instance.
- PP_Instance pp_instance() const { return pp_instance_; }
-
- // Helper function that converts a PP_Var to an object. This will return NULL
- // if the PP_Var is not of object type or the object is invalid.
- CONTENT_EXPORT static scoped_refptr<NPObjectVar> FromPPVar(PP_Var var);
-
- private:
- virtual ~NPObjectVar();
-
- // Possibly 0 if the object has outlived its instance.
- PP_Instance pp_instance_;
-
- // Guaranteed non-NULL, this is the underlying object used by WebKit. We
- // hold a reference to this object.
- NPObject* np_object_;
-
- DISALLOW_COPY_AND_ASSIGN(NPObjectVar);
-};
-
-} // ppapi
-
-#endif // CONTENT_RENDERER_PEPPER_NPOBJECT_VAR_H_
diff --git a/chromium/content/renderer/pepper/pepper_audio_input_host.cc b/chromium/content/renderer/pepper/pepper_audio_input_host.cc
index a86e1775d34..0da9cd1d99c 100644
--- a/chromium/content/renderer/pepper/pepper_audio_input_host.cc
+++ b/chromium/content/renderer/pepper/pepper_audio_input_host.cc
@@ -10,7 +10,7 @@
#include "content/renderer/pepper/pepper_platform_audio_input.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
#include "ipc/ipc_message.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
@@ -46,8 +46,8 @@ PepperAudioInputHost::PepperAudioInputHost(RendererPpapiHostImpl* host,
renderer_ppapi_host_(host),
audio_input_(NULL),
enumeration_helper_(this,
- PepperMediaDeviceManager::GetForRenderView(
- host->GetRenderViewForInstance(pp_instance())),
+ PepperMediaDeviceManager::GetForRenderFrame(
+ host->GetRenderFrameForInstance(pp_instance())),
PP_DEVICETYPE_DEV_AUDIOCAPTURE,
host->GetDocumentURL(instance)) {}
@@ -98,16 +98,14 @@ int32_t PepperAudioInputHost::OnOpen(ppapi::host::HostMessageContext* context,
// When it is done, we'll get called back on StreamCreated() or
// StreamCreationFailed().
- RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
- renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()));
-
- audio_input_ =
- PepperPlatformAudioInput::Create(render_view->AsWeakPtr(),
- device_id,
- document_url,
- static_cast<int>(sample_rate),
- static_cast<int>(sample_frame_count),
- this);
+ audio_input_ = PepperPlatformAudioInput::Create(
+ renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance())->
+ GetRoutingID(),
+ device_id,
+ document_url,
+ static_cast<int>(sample_rate),
+ static_cast<int>(sample_frame_count),
+ this);
if (audio_input_) {
open_context_ = context->MakeReplyMessageContext();
return PP_OK_COMPLETIONPENDING;
diff --git a/chromium/content/renderer/pepper/pepper_audio_input_host.h b/chromium/content/renderer/pepper/pepper_audio_input_host.h
index 40f98b0db7f..91a4b1f374e 100644
--- a/chromium/content/renderer/pepper/pepper_audio_input_host.h
+++ b/chromium/content/renderer/pepper/pepper_audio_input_host.h
@@ -27,11 +27,11 @@ class PepperAudioInputHost : public ppapi::host::ResourceHost {
PepperAudioInputHost(RendererPpapiHostImpl* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperAudioInputHost();
+ ~PepperAudioInputHost() override;
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// Called when the stream is created.
void StreamCreated(base::SharedMemoryHandle shared_memory_handle,
diff --git a/chromium/content/renderer/pepper/pepper_broker.cc b/chromium/content/renderer/pepper/pepper_broker.cc
index 851408f0b27..b1e06260b50 100644
--- a/chromium/content/renderer/pepper/pepper_broker.cc
+++ b/chromium/content/renderer/pepper/pepper_broker.cc
@@ -88,7 +88,7 @@ int32_t PepperBrokerDispatcherWrapper::SendHandleToBroker(
if (foreign_socket_handle == IPC::InvalidPlatformFileForTransit())
return PP_ERROR_FAILED;
- int32_t result;
+ int32_t result = PP_ERROR_FAILED;
if (!dispatcher_->Send(new PpapiMsg_ConnectToPlugin(
instance, foreign_socket_handle, &result))) {
// The plugin did not receive the handle, so it must be closed.
diff --git a/chromium/content/renderer/pepper/pepper_browser_connection.h b/chromium/content/renderer/pepper/pepper_browser_connection.h
index c79a6ec1e1a..241d6123d9e 100644
--- a/chromium/content/renderer/pepper/pepper_browser_connection.h
+++ b/chromium/content/renderer/pepper/pepper_browser_connection.h
@@ -32,9 +32,9 @@ class PepperBrowserConnection
typedef base::Callback<void(const std::vector<int>&)>
PendingResourceIDCallback;
explicit PepperBrowserConnection(RenderFrame* render_frame);
- virtual ~PepperBrowserConnection();
+ ~PepperBrowserConnection() override;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// TODO(teravest): Instead of having separate methods per message, we should
// add generic functionality similar to PluginResource::Call().
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.cc b/chromium/content/renderer/pepper/pepper_compositor_host.cc
index f7e32b65f48..284d36c3cae 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.cc
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.cc
@@ -219,19 +219,19 @@ void PepperCompositorHost::UpdateLayer(
new_layer->common.clip_rect.size.width != 0 ||
new_layer->common.clip_rect.size.height != 0) {
scoped_refptr<cc::Layer> clip_parent = layer->parent();
- if (clip_parent == layer_) {
+ if (clip_parent.get() == layer_.get()) {
// Create a clip parent layer, if it does not exist.
clip_parent = cc::Layer::Create();
clip_parent->SetMasksToBounds(true);
clip_parent->SetIsDrawable(true);
- layer_->ReplaceChild(layer, clip_parent);
+ layer_->ReplaceChild(layer.get(), clip_parent);
clip_parent->AddChild(layer);
}
gfx::Point position = PP_ToGfxPoint(new_layer->common.clip_rect.point);
clip_parent->SetPosition(position);
clip_parent->SetBounds(PP_ToGfxSize(new_layer->common.clip_rect.size));
layer->SetPosition(gfx::Point(-position.x(), -position.y()));
- } else if (layer->parent() != layer_) {
+ } else if (layer->parent() != layer_.get()) {
// Remove the clip parent layer.
layer_->ReplaceChild(layer->parent(), layer);
layer->SetPosition(gfx::Point());
@@ -252,13 +252,16 @@ void PepperCompositorHost::UpdateLayer(
if (!old_layer ||
new_layer->common.resource_id != old_layer->common.resource_id) {
cc::TextureMailbox mailbox(new_layer->texture->mailbox,
- GL_TEXTURE_2D,
+ new_layer->texture->target,
new_layer->texture->sync_point);
texture_layer->SetTextureMailbox(mailbox,
cc::SingleReleaseCallback::Create(
base::Bind(&PepperCompositorHost::ResourceReleased,
weak_factory_.GetWeakPtr(),
- new_layer->common.resource_id)));;
+ new_layer->common.resource_id)));
+ // TODO(penghuang): get a damage region from the application and
+ // pass it to SetNeedsDisplayRect().
+ texture_layer->SetNeedsDisplay();
}
texture_layer->SetPremultipliedAlpha(new_layer->texture->premult_alpha);
gfx::RectF rect = PP_ToGfxRectF(new_layer->texture->source_rect);
@@ -290,6 +293,9 @@ void PepperCompositorHost::UpdateLayer(
weak_factory_.GetWeakPtr(),
new_layer->common.resource_id,
base::Passed(&image_shm))));
+ // TODO(penghuang): get a damage region from the application and
+ // pass it to SetNeedsDisplayRect().
+ image_layer->SetNeedsDisplay();
// ImageData is always premultiplied alpha.
image_layer->SetPremultipliedAlpha(true);
@@ -348,11 +354,11 @@ int32_t PepperCompositorHost::OnHostMsgCommitLayers(
for (size_t i = 0; i < layers.size(); ++i) {
const ppapi::CompositorLayerData* pp_layer = &layers[i];
LayerData* data = i >= layers_.size() ? NULL : &layers_[i];
- DCHECK(!data || data->cc_layer);
+ DCHECK(!data || data->cc_layer.get());
scoped_refptr<cc::Layer> cc_layer = data ? data->cc_layer : NULL;
ppapi::CompositorLayerData* old_layer = data ? &data->pp_layer : NULL;
- if (!cc_layer) {
+ if (!cc_layer.get()) {
if (pp_layer->color)
cc_layer = cc::SolidColorLayer::Create();
else if (pp_layer->texture || pp_layer->image)
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.h b/chromium/content/renderer/pepper/pepper_compositor_host.h
index de2f72bac25..d0ecac0b800 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.h
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.h
@@ -42,7 +42,7 @@ class PepperCompositorHost : public ppapi::host::ResourceHost {
void ViewFlushedPaint();
private:
- virtual ~PepperCompositorHost();
+ ~PepperCompositorHost() override;
void ImageReleased(int32_t id,
const scoped_ptr<base::SharedMemory>& shared_memory,
@@ -58,12 +58,12 @@ class PepperCompositorHost : public ppapi::host::ResourceHost {
scoped_ptr<base::SharedMemory> image_shm);
// ResourceMessageHandler overrides:
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// ppapi::host::ResourceHost overrides:
- virtual bool IsCompositorHost() OVERRIDE;
+ bool IsCompositorHost() override;
// Message handlers:
int32_t OnHostMsgCommitLayers(
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
index d983f4a5816..edc0840bb92 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.cc
@@ -46,6 +46,7 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
// EnumerateDevicesCallbackBody() to ensure that we always call |callback|
// asynchronously.
sync_call_ = true;
+ DCHECK(owner_->delegate_);
request_id_ = owner_->delegate_->EnumerateDevices(
owner_->device_type_,
owner_->document_url_,
@@ -54,7 +55,7 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
}
~ScopedRequest() {
- if (requested_) {
+ if (requested_ && owner_->delegate_) {
owner_->delegate_->StopEnumerateDevices(request_id_);
}
}
@@ -91,7 +92,7 @@ class PepperDeviceEnumerationHostHelper::ScopedRequest
PepperDeviceEnumerationHostHelper::PepperDeviceEnumerationHostHelper(
ppapi::host::ResourceHost* resource_host,
- Delegate* delegate,
+ base::WeakPtr<Delegate> delegate,
PP_DeviceType_Dev device_type,
const GURL& document_url)
: resource_host_(resource_host),
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
index 088d4661c0e..ea1a7fcb975 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "ppapi/c/dev/ppb_device_ref_dev.h"
#include "ppapi/host/host_message_context.h"
@@ -58,7 +59,7 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
// |resource_host| and |delegate| must outlive this object.
PepperDeviceEnumerationHostHelper(ppapi::host::ResourceHost* resource_host,
- Delegate* delegate,
+ base::WeakPtr<Delegate> delegate,
PP_DeviceType_Dev device_type,
const GURL& document_url);
~PepperDeviceEnumerationHostHelper();
@@ -93,7 +94,7 @@ class CONTENT_EXPORT PepperDeviceEnumerationHostHelper {
// Non-owning pointers.
ppapi::host::ResourceHost* resource_host_;
- Delegate* delegate_;
+ base::WeakPtr<Delegate> delegate_;
PP_DeviceType_Dev device_type_;
GURL document_url_;
diff --git a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
index a9b2579ce66..c51502ed44d 100644
--- a/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_device_enumeration_host_helper_unittest.cc
@@ -7,6 +7,7 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/memory/weak_ptr.h"
#include "content/renderer/pepper/pepper_device_enumeration_host_helper.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/host_message_context.h"
@@ -24,22 +25,22 @@ namespace content {
namespace {
-class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate {
+class TestDelegate : public PepperDeviceEnumerationHostHelper::Delegate,
+ public base::SupportsWeakPtr<TestDelegate> {
public:
TestDelegate() : last_used_id_(0) {}
- virtual ~TestDelegate() { CHECK(callbacks_.empty()); }
+ ~TestDelegate() override { CHECK(callbacks_.empty()); }
- virtual int EnumerateDevices(PP_DeviceType_Dev /* type */,
- const GURL& /* document_url */,
- const EnumerateDevicesCallback& callback)
- OVERRIDE {
+ int EnumerateDevices(PP_DeviceType_Dev /* type */,
+ const GURL& /* document_url */,
+ const EnumerateDevicesCallback& callback) override {
last_used_id_++;
callbacks_[last_used_id_] = callback;
return last_used_id_;
}
- virtual void StopEnumerateDevices(int request_id) OVERRIDE {
+ void StopEnumerateDevices(int request_id) override {
std::map<int, EnumerateDevicesCallback>::iterator iter =
callbacks_.find(request_id);
CHECK(iter != callbacks_.end());
@@ -76,11 +77,11 @@ class PepperDeviceEnumerationHostHelperTest : public testing::Test {
: ppapi_host_(&sink_, ppapi::PpapiPermissions()),
resource_host_(&ppapi_host_, 12345, 67890),
device_enumeration_(&resource_host_,
- &delegate_,
+ delegate_.AsWeakPtr(),
PP_DEVICETYPE_DEV_AUDIOCAPTURE,
GURL("http://example.com")) {}
- virtual ~PepperDeviceEnumerationHostHelperTest() {}
+ ~PepperDeviceEnumerationHostHelperTest() override {}
void SimulateMonitorDeviceChangeReceived(uint32_t callback_id) {
PpapiHostMsg_DeviceEnumeration_MonitorDeviceChange msg(callback_id);
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
index d067c201e39..63cd7a6e65d 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -94,11 +94,7 @@ void PepperFileChooserHost::StoreChosenFiles(
std::vector<base::FilePath> file_paths;
std::vector<std::string> display_names;
for (size_t i = 0; i < files.size(); i++) {
-#if defined(OS_WIN)
- base::FilePath file_path(base::UTF8ToWide(files[i].path));
-#else
- base::FilePath file_path(files[i].path);
-#endif
+ base::FilePath file_path = base::FilePath::FromUTF8Unsafe(files[i].path);
file_paths.push_back(file_path);
create_msgs.push_back(PpapiHostMsg_FileRef_CreateForRawFS(file_path));
display_names.push_back(files[i].display_name);
@@ -145,13 +141,14 @@ int32_t PepperFileChooserHost::OnShow(
} else {
params.multiSelect = open_multiple;
}
- std::vector<blink::WebString> mine_types(accept_mime_types.size());
+ std::vector<blink::WebString> mime_types(accept_mime_types.size());
for (size_t i = 0; i < accept_mime_types.size(); i++) {
- mine_types[i] = blink::WebString::fromUTF8(accept_mime_types[i].data(),
+ mime_types[i] = blink::WebString::fromUTF8(accept_mime_types[i].data(),
accept_mime_types[i].size());
}
- params.acceptTypes = mine_types;
+ params.acceptTypes = mime_types;
params.directory = false;
+ params.needLocalPath = true;
handler_ = new CompletionHandler(AsWeakPtr());
RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.h b/chromium/content/renderer/pepper/pepper_file_chooser_host.h
index 52f7c5f5bdb..4ae861a1660 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.h
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.h
@@ -38,11 +38,11 @@ class CONTENT_EXPORT PepperFileChooserHost
PepperFileChooserHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperFileChooserHost();
+ ~PepperFileChooserHost() override;
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
void StoreChosenFiles(const std::vector<ChosenFileInfo>& files);
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
index 3868b54d8a2..3df6520440e 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
@@ -5,6 +5,7 @@
#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "content/common/view_messages.h"
+#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/test/render_view_test.h"
#include "content/renderer/pepper/mock_renderer_ppapi_host.h"
@@ -23,7 +24,6 @@
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/test_globals.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/shell_dialogs/selected_file_info.h"
namespace content {
@@ -33,14 +33,14 @@ class PepperFileChooserHostTest : public RenderViewTest {
public:
PepperFileChooserHostTest() : pp_instance_(123456) {}
- virtual void SetUp() {
+ void SetUp() override {
SetContentClient(&client_);
RenderViewTest::SetUp();
ppapi::ProxyLock::DisableLockingOnThreadForTest();
globals_.GetResourceTracker()->DidCreateInstance(pp_instance_);
}
- virtual void TearDown() {
+ void TearDown() override {
globals_.GetResourceTracker()->DidDeleteInstance(pp_instance_);
RenderViewTest::TearDown();
@@ -100,10 +100,10 @@ TEST_F(PepperFileChooserHostTest, Show) {
// Send a chooser reply to the render view. Note our reply path has to have a
// path separator so we include both a Unix and a Windows one.
- ui::SelectedFileInfo selected_info;
+ content::FileChooserFileInfo selected_info;
selected_info.display_name = FILE_PATH_LITERAL("Hello, world");
- selected_info.local_path = base::FilePath(FILE_PATH_LITERAL("myp\\ath/foo"));
- std::vector<ui::SelectedFileInfo> selected_info_vector;
+ selected_info.file_path = base::FilePath(FILE_PATH_LITERAL("myp\\ath/foo"));
+ std::vector<content::FileChooserFileInfo> selected_info_vector;
selected_info_vector.push_back(selected_info);
RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_);
ViewMsg_RunFileChooserResponse response(view_impl->routing_id(),
diff --git a/chromium/content/renderer/pepper/pepper_file_ref_renderer_host.h b/chromium/content/renderer/pepper/pepper_file_ref_renderer_host.h
index 9cfc65f657d..cfa36b2d83e 100644
--- a/chromium/content/renderer/pepper/pepper_file_ref_renderer_host.h
+++ b/chromium/content/renderer/pepper/pepper_file_ref_renderer_host.h
@@ -35,17 +35,17 @@ class PepperFileRefRendererHost : public ppapi::host::ResourceHost {
PP_Resource resource,
const base::FilePath& external_path);
- virtual ~PepperFileRefRendererHost();
+ ~PepperFileRefRendererHost() override;
PP_FileSystemType GetFileSystemType() const;
GURL GetFileSystemURL() const;
base::FilePath GetExternalFilePath() const;
// ppapi::host::ResourceHost override.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
- virtual bool IsFileRefHost() OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
+ bool IsFileRefHost() override;
private:
PP_FileSystemType file_system_type_;
diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.cc b/chromium/content/renderer/pepper/pepper_file_system_host.cc
index 036d319a612..69945341014 100644
--- a/chromium/content/renderer/pepper/pepper_file_system_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_system_host.cc
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "content/child/child_thread.h"
#include "content/child/fileapi/file_system_dispatcher.h"
+#include "content/common/pepper_file_util.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_ppapi_host.h"
@@ -17,10 +18,10 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/file_system_util.h"
#include "ppapi/shared_impl/file_type_conversion.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "webkit/common/fileapi/file_system_util.h"
namespace content {
@@ -91,9 +92,9 @@ int32_t PepperFileSystemHost::OnHostMsgOpen(
return PP_ERROR_INPROGRESS;
called_open_ = true;
- fileapi::FileSystemType file_system_type =
- ppapi::PepperFileSystemTypeToFileSystemType(type_);
- if (file_system_type == fileapi::kFileSystemTypeUnknown)
+ storage::FileSystemType file_system_type =
+ PepperFileSystemTypeToFileSystemType(type_);
+ if (file_system_type == storage::kFileSystemTypeUnknown)
return PP_ERROR_FAILED;
GURL document_url = renderer_ppapi_host_->GetDocumentURL(pp_instance());
@@ -123,7 +124,7 @@ int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem(
called_open_ = true;
// Do a sanity check.
- if (!fileapi::ValidateIsolatedFileSystemId(fsid))
+ if (!storage::ValidateIsolatedFileSystemId(fsid))
return PP_ERROR_BADARGUMENT;
RenderView* view =
@@ -135,7 +136,7 @@ int32_t PepperFileSystemHost::OnHostMsgInitIsolatedFileSystem(
const std::string root_name = ppapi::IsolatedFileSystemTypeToRootName(type);
if (root_name.empty())
return PP_ERROR_BADARGUMENT;
- root_url_ = GURL(fileapi::GetIsolatedFileSystemRootURIString(
+ root_url_ = GURL(storage::GetIsolatedFileSystemRootURIString(
url.GetOrigin(), fsid, root_name));
opened_ = true;
return PP_OK;
diff --git a/chromium/content/renderer/pepper/pepper_file_system_host.h b/chromium/content/renderer/pepper/pepper_file_system_host.h
index e1657a1d50b..23d7c49a2cb 100644
--- a/chromium/content/renderer/pepper/pepper_file_system_host.h
+++ b/chromium/content/renderer/pepper/pepper_file_system_host.h
@@ -39,13 +39,13 @@ class PepperFileSystemHost
PP_Resource resource,
const GURL& root_url,
PP_FileSystemType type);
- virtual ~PepperFileSystemHost();
+ ~PepperFileSystemHost() override;
// ppapi::host::ResourceHost override.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
- virtual bool IsFileSystemHost() OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
+ bool IsFileSystemHost() override;
// Supports FileRefs direct access on the host side.
PP_FileSystemType GetType() const { return type_; }
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index a33b994d81b..790ac761421 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -13,7 +13,6 @@
#include "content/child/child_shared_bitmap_manager.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/renderer_ppapi_host.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/gfx_conversion.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
@@ -308,6 +307,7 @@ bool PepperGraphics2DHost::BindToInstance(
new_instance->InvalidateRect(gfx::Rect());
}
+ cached_bitmap_.reset();
texture_mailbox_modified_ = true;
bound_instance_ = new_instance;
@@ -359,7 +359,7 @@ void PepperGraphics2DHost::Paint(blink::WebCanvas* canvas,
// Copy to device independent bitmap when target canvas doesn't support
// platform paint.
if (!skia::SupportsPlatformPaint(canvas))
- backing_bitmap.copyTo(&image, kPMColor_SkColorType);
+ backing_bitmap.copyTo(&image, kN32_SkColorType);
else
image = backing_bitmap;
@@ -404,11 +404,15 @@ PPB_ImageData_Impl* PepperGraphics2DHost::ImageData() {
}
gfx::Size PepperGraphics2DHost::Size() const {
- if (!image_data_)
+ if (!image_data_.get())
return gfx::Size();
return gfx::Size(image_data_->width(), image_data_->height());
}
+void PepperGraphics2DHost::ClearCache() {
+ cached_bitmap_.reset();
+}
+
int32_t PepperGraphics2DHost::OnHostMsgPaintImageData(
ppapi::host::HostMessageContext* context,
const ppapi::HostResource& image_data,
@@ -548,9 +552,17 @@ int32_t PepperGraphics2DHost::OnHostMsgReadImageData(
return ReadImageData(image, &top_left) ? PP_OK : PP_ERROR_FAILED;
}
-void ReleaseCallback(scoped_ptr<cc::SharedBitmap> bitmap,
- uint32 sync_point,
- bool lost_resource) {}
+void PepperGraphics2DHost::ReleaseCallback(scoped_ptr<cc::SharedBitmap> bitmap,
+ const gfx::Size& bitmap_size,
+ uint32 sync_point,
+ bool lost_resource) {
+ cached_bitmap_.reset();
+ // Only keep around a cached bitmap if the plugin is currently drawing (has
+ // need_flush_ack_ set).
+ if (need_flush_ack_ && bound_instance_)
+ cached_bitmap_ = bitmap.Pass();
+ cached_bitmap_size_ = bitmap_size;
+}
bool PepperGraphics2DHost::PrepareTextureMailbox(
cc::TextureMailbox* mailbox,
@@ -559,10 +571,18 @@ bool PepperGraphics2DHost::PrepareTextureMailbox(
return false;
// TODO(jbauman): Send image_data_ through mailbox to avoid copy.
gfx::Size pixel_image_size(image_data_->width(), image_data_->height());
- scoped_ptr<cc::SharedBitmap> shared_bitmap =
- RenderThreadImpl::current()
- ->shared_bitmap_manager()
- ->AllocateSharedBitmap(pixel_image_size);
+ scoped_ptr<cc::SharedBitmap> shared_bitmap;
+ if (cached_bitmap_) {
+ if (cached_bitmap_size_ == pixel_image_size)
+ shared_bitmap = cached_bitmap_.Pass();
+ else
+ cached_bitmap_.reset();
+ }
+ if (!shared_bitmap) {
+ shared_bitmap = RenderThreadImpl::current()
+ ->shared_bitmap_manager()
+ ->AllocateSharedBitmap(pixel_image_size);
+ }
if (!shared_bitmap)
return false;
void* src = image_data_->Map();
@@ -573,7 +593,10 @@ bool PepperGraphics2DHost::PrepareTextureMailbox(
*mailbox = cc::TextureMailbox(shared_bitmap->memory(), pixel_image_size);
*release_callback = cc::SingleReleaseCallback::Create(
- base::Bind(&ReleaseCallback, base::Passed(&shared_bitmap)));
+ base::Bind(&PepperGraphics2DHost::ReleaseCallback,
+ this->AsWeakPtr(),
+ base::Passed(&shared_bitmap),
+ pixel_image_size));
texture_mailbox_modified_ = false;
return true;
}
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
index 25df4d179a9..7347a0ace3d 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h
@@ -20,6 +20,7 @@
#include "ui/gfx/size.h"
namespace cc {
+class SharedBitmap;
class SingleReleaseCallback;
class TextureMailbox;
}
@@ -50,13 +51,13 @@ class CONTENT_EXPORT PepperGraphics2DHost
PP_Bool is_always_opaque,
scoped_refptr<PPB_ImageData_Impl> backing_store);
- virtual ~PepperGraphics2DHost();
+ ~PepperGraphics2DHost() override;
// ppapi::host::ResourceHost override.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
- virtual bool IsGraphics2DHost() OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
+ bool IsGraphics2DHost() override;
bool ReadImageData(PP_Resource image, const PP_Point* top_left);
// Assciates this device with the given plugin instance. You can pass NULL
@@ -85,6 +86,8 @@ class CONTENT_EXPORT PepperGraphics2DHost
PPB_ImageData_Impl* ImageData();
gfx::Size Size() const;
+ void ClearCache();
+
private:
PepperGraphics2DHost(RendererPpapiHost* host,
PP_Instance instance,
@@ -157,6 +160,11 @@ class CONTENT_EXPORT PepperGraphics2DHost
gfx::Rect* op_rect,
gfx::Point* delta);
+ void ReleaseCallback(scoped_ptr<cc::SharedBitmap> bitmap,
+ const gfx::Size& bitmap_size,
+ uint32 sync_point,
+ bool lost_resource);
+
RendererPpapiHost* renderer_ppapi_host_;
scoped_refptr<PPB_ImageData_Impl> image_data_;
@@ -193,6 +201,11 @@ class CONTENT_EXPORT PepperGraphics2DHost
bool texture_mailbox_modified_;
bool is_using_texture_layer_;
+ // This is a bitmap that was recently released by the compositor and may be
+ // used to transfer bytes to the compositor again.
+ scoped_ptr<cc::SharedBitmap> cached_bitmap_;
+ gfx::Size cached_bitmap_size_;
+
friend class PepperGraphics2DHostTest;
DISALLOW_COPY_AND_ASSIGN(PepperGraphics2DHost);
};
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc
index 8914a3d8011..b0f7bdff37e 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host_unittest.cc
@@ -33,7 +33,7 @@ class PepperGraphics2DHostTest : public testing::Test {
PepperGraphics2DHostTest() : renderer_ppapi_host_(NULL, 12345) {}
- virtual ~PepperGraphics2DHostTest() {
+ ~PepperGraphics2DHostTest() override {
ppapi::ProxyAutoLock proxy_lock;
host_.reset();
}
@@ -85,8 +85,7 @@ class PepperGraphics2DHostTest : public testing::Test {
int height = plugin_rect.point.y + plugin_rect.size.height;
if (bitmap->isNull() || bitmap->width() != width ||
bitmap->height() != height) {
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height);
- bitmap->allocPixels();
+ bitmap->allocN32Pixels(width, height);
}
bitmap->eraseColor(0);
}
@@ -148,7 +147,7 @@ TEST_F(PepperGraphics2DHostTest, ConvertToLogicalPixels) {
// Check negative scroll deltas
{10, 10, 20, 20, 5, 5, 10, 10, -6, -4, -3, -2, 0.5, true},
{10, 10, 20, 20, 5, 5, 10, 10, -6, -3, -3, -1, 0.5, false}, };
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ for (size_t i = 0; i < arraysize(tests); ++i) {
gfx::Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
gfx::Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
gfx::Rect orig = r1;
diff --git a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h
index e7457fd1132..286fdfa4cc8 100644
--- a/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h
+++ b/chromium/content/renderer/pepper/pepper_hung_plugin_filter.h
@@ -26,9 +26,10 @@ namespace content {
// thread. This is important since when we're blocked on a sync message to a
// hung plugin, the main thread is frozen.
//
-// NOTE: This class is refcounted (via SyncMessageStatusReceiver).
+// NOTE: This class is refcounted (via IPC::MessageFilter).
class PepperHungPluginFilter
- : public ppapi::proxy::HostDispatcher::SyncMessageStatusReceiver {
+ : public ppapi::proxy::HostDispatcher::SyncMessageStatusObserver,
+ public IPC::MessageFilter {
public:
// The |frame_routing_id| is the ID of the render_frame so that this class can
// send messages to the browser via that frame's route. The |plugin_child_id|
@@ -39,17 +40,17 @@ class PepperHungPluginFilter
int plugin_child_id);
// SyncMessageStatusReceiver implementation.
- virtual void BeginBlockOnSyncMessage() OVERRIDE;
- virtual void EndBlockOnSyncMessage() OVERRIDE;
+ void BeginBlockOnSyncMessage() override;
+ void EndBlockOnSyncMessage() override;
// MessageFilter implementation.
- virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE;
- virtual void OnFilterRemoved() OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnFilterAdded(IPC::Sender* sender) override;
+ void OnFilterRemoved() override;
+ void OnChannelError() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
protected:
- virtual ~PepperHungPluginFilter();
+ ~PepperHungPluginFilter() override;
private:
// Makes sure that the hung timer is scheduled.
diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
index 596f149cc18..627c1f8c84b 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.cc
@@ -11,6 +11,7 @@
#include "content/child/browser_font_resource_trusted.h"
#include "content/renderer/pepper/pepper_in_process_router.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/ppapi_preferences_builder.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/render_view_impl.h"
#include "ipc/ipc_message.h"
@@ -52,8 +53,8 @@ PP_Resource PepperInProcessResourceCreation::CreateBrowserFont(
const PP_BrowserFont_Trusted_Description* description) {
if (!BrowserFontResource_Trusted::IsPPFontDescriptionValid(*description))
return 0;
- ppapi::Preferences prefs(
- host_impl_->GetRenderViewForInstance(instance)->GetWebkitPreferences());
+ ppapi::Preferences prefs(PpapiPreferencesBuilder::Build(
+ host_impl_->GetRenderViewForInstance(instance)->GetWebkitPreferences()));
return (new BrowserFontResource_Trusted(
host_impl_->in_process_router()->GetPluginConnection(instance),
instance,
diff --git a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h
index 2718912da07..9f8075708bd 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h
+++ b/chromium/content/renderer/pepper/pepper_in_process_resource_creation.h
@@ -38,31 +38,31 @@ class PepperInProcessResourceCreation : public ResourceCreationImpl {
public:
PepperInProcessResourceCreation(RendererPpapiHostImpl* host_impl,
PepperPluginInstanceImpl* instance);
- virtual ~PepperInProcessResourceCreation();
+ ~PepperInProcessResourceCreation() override;
// ResourceCreation_API implementation.
- virtual PP_Resource CreateBrowserFont(
+ PP_Resource CreateBrowserFont(
PP_Instance instance,
- const PP_BrowserFont_Trusted_Description* description) OVERRIDE;
- virtual PP_Resource CreateFileChooser(PP_Instance instance,
- PP_FileChooserMode_Dev mode,
- const PP_Var& accept_types) OVERRIDE;
- virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateFileRef(PP_Instance instance,
- const ppapi::FileRefCreateInfo& create_info)
- OVERRIDE;
- virtual PP_Resource CreateFileSystem(PP_Instance instance,
- PP_FileSystemType type) OVERRIDE;
- virtual PP_Resource CreateGraphics2D(PP_Instance pp_instance,
- const PP_Size* size,
- PP_Bool is_always_opaque) OVERRIDE;
- virtual PP_Resource CreatePrinting(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateTrueTypeFont(
+ const PP_BrowserFont_Trusted_Description* description) override;
+ PP_Resource CreateFileChooser(PP_Instance instance,
+ PP_FileChooserMode_Dev mode,
+ const PP_Var& accept_types) override;
+ PP_Resource CreateFileIO(PP_Instance instance) override;
+ PP_Resource CreateFileRef(
PP_Instance instance,
- const struct PP_TrueTypeFontDesc_Dev* desc) OVERRIDE;
- virtual PP_Resource CreateURLLoader(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateURLRequestInfo(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateWebSocket(PP_Instance instance) OVERRIDE;
+ const ppapi::FileRefCreateInfo& create_info) override;
+ PP_Resource CreateFileSystem(PP_Instance instance,
+ PP_FileSystemType type) override;
+ PP_Resource CreateGraphics2D(PP_Instance pp_instance,
+ const PP_Size* size,
+ PP_Bool is_always_opaque) override;
+ PP_Resource CreatePrinting(PP_Instance instance) override;
+ PP_Resource CreateTrueTypeFont(
+ PP_Instance instance,
+ const struct PP_TrueTypeFontDesc_Dev* desc) override;
+ PP_Resource CreateURLLoader(PP_Instance instance) override;
+ PP_Resource CreateURLRequestInfo(PP_Instance instance) override;
+ PP_Resource CreateWebSocket(PP_Instance instance) override;
private:
// Non-owning pointer to the host for the current plugin.
diff --git a/chromium/content/renderer/pepper/pepper_in_process_router.cc b/chromium/content/renderer/pepper/pepper_in_process_router.cc
index 9194f12fb7f..b6fd7b4e23e 100644
--- a/chromium/content/renderer/pepper/pepper_in_process_router.cc
+++ b/chromium/content/renderer/pepper/pepper_in_process_router.cc
@@ -24,11 +24,9 @@ class PepperInProcessRouter::Channel : public IPC::Sender {
Channel(const base::Callback<bool(IPC::Message*)>& callback)
: callback_(callback) {}
- virtual ~Channel() {}
+ ~Channel() override {}
- virtual bool Send(IPC::Message* message) OVERRIDE {
- return callback_.Run(message);
- }
+ bool Send(IPC::Message* message) override { return callback_.Run(message); }
private:
base::Callback<bool(IPC::Message*)> callback_;
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.cc b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
index b36df317788..676b2fb44b9 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.cc
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "content/renderer/media/media_stream_dispatcher.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
#include "ppapi/shared_impl/ppb_device_ref_shared.h"
namespace content {
@@ -16,25 +16,28 @@ namespace {
ppapi::DeviceRefData FromStreamDeviceInfo(const StreamDeviceInfo& info) {
ppapi::DeviceRefData data;
data.id = info.device.id;
- data.name = info.device.name;
+ // Some Flash content can't handle an empty string, so stick a space in to
+ // make them happy. See crbug.com/408404.
+ data.name = info.device.name.empty() ? std::string(" ") : info.device.name;
data.type = PepperMediaDeviceManager::FromMediaStreamType(info.device.type);
return data;
}
} // namespace
-PepperMediaDeviceManager* PepperMediaDeviceManager::GetForRenderView(
- RenderView* render_view) {
+base::WeakPtr<PepperMediaDeviceManager>
+PepperMediaDeviceManager::GetForRenderFrame(
+ RenderFrame* render_frame) {
PepperMediaDeviceManager* handler =
- PepperMediaDeviceManager::Get(render_view);
+ PepperMediaDeviceManager::Get(render_frame);
if (!handler)
- handler = new PepperMediaDeviceManager(render_view);
- return handler;
+ handler = new PepperMediaDeviceManager(render_frame);
+ return handler->AsWeakPtr();
}
-PepperMediaDeviceManager::PepperMediaDeviceManager(RenderView* render_view)
- : RenderViewObserver(render_view),
- RenderViewObserverTracker<PepperMediaDeviceManager>(render_view),
+PepperMediaDeviceManager::PepperMediaDeviceManager(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame),
+ RenderFrameObserverTracker<PepperMediaDeviceManager>(render_frame),
next_id_(1) {}
PepperMediaDeviceManager::~PepperMediaDeviceManager() {
@@ -50,12 +53,11 @@ int PepperMediaDeviceManager::EnumerateDevices(
int request_id = next_id_++;
#if defined(ENABLE_WEBRTC)
- GetRenderViewImpl()->media_stream_dispatcher()->EnumerateDevices(
+ GetMediaStreamDispatcher()->EnumerateDevices(
request_id,
AsWeakPtr(),
PepperMediaDeviceManager::FromPepperDeviceType(type),
- document_url.GetOrigin(),
- false);
+ document_url.GetOrigin());
#else
base::MessageLoop::current()->PostTask(
FROM_HERE,
@@ -76,10 +78,20 @@ void PepperMediaDeviceManager::StopEnumerateDevices(int request_id) {
// of EnumerateDevices.
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&MediaStreamDispatcher::StopEnumerateDevices,
- GetRenderViewImpl()->media_stream_dispatcher()->AsWeakPtr(),
- request_id,
- AsWeakPtr()));
+ base::Bind(&PepperMediaDeviceManager::StopEnumerateDevicesDelayed,
+ AsWeakPtr(),
+ request_id));
+#endif
+}
+
+void PepperMediaDeviceManager::StopEnumerateDevicesDelayed(int request_id) {
+#if defined(ENABLE_WEBRTC)
+ // This method is being invoked by the message loop at some unknown
+ // point-in-time after StopEnumerateDevices(). Therefore, check that
+ // render_frame() is not NULL, in order to guarantee
+ // GetMediaStreamDispatcher() won't return NULL.
+ if (render_frame())
+ GetMediaStreamDispatcher()->StopEnumerateDevices(request_id, AsWeakPtr());
#endif
}
@@ -91,7 +103,7 @@ int PepperMediaDeviceManager::OpenDevice(PP_DeviceType_Dev type,
int request_id = next_id_++;
#if defined(ENABLE_WEBRTC)
- GetRenderViewImpl()->media_stream_dispatcher()->OpenDevice(
+ GetMediaStreamDispatcher()->OpenDevice(
request_id,
AsWeakPtr(),
device_id,
@@ -112,14 +124,13 @@ void PepperMediaDeviceManager::CancelOpenDevice(int request_id) {
open_callbacks_.erase(request_id);
#if defined(ENABLE_WEBRTC)
- GetRenderViewImpl()->media_stream_dispatcher()->CancelOpenDevice(request_id,
- AsWeakPtr());
+ GetMediaStreamDispatcher()->CancelOpenDevice(request_id, AsWeakPtr());
#endif
}
void PepperMediaDeviceManager::CloseDevice(const std::string& label) {
#if defined(ENABLE_WEBRTC)
- GetRenderViewImpl()->media_stream_dispatcher()->CloseDevice(label);
+ GetMediaStreamDispatcher()->CloseDevice(label);
#endif
}
@@ -128,11 +139,9 @@ int PepperMediaDeviceManager::GetSessionID(PP_DeviceType_Dev type,
#if defined(ENABLE_WEBRTC)
switch (type) {
case PP_DEVICETYPE_DEV_AUDIOCAPTURE:
- return GetRenderViewImpl()->media_stream_dispatcher()->audio_session_id(
- label, 0);
+ return GetMediaStreamDispatcher()->audio_session_id(label, 0);
case PP_DEVICETYPE_DEV_VIDEOCAPTURE:
- return GetRenderViewImpl()->media_stream_dispatcher()->video_session_id(
- label, 0);
+ return GetMediaStreamDispatcher()->video_session_id(label, 0);
default:
NOTREACHED();
return 0;
@@ -236,8 +245,13 @@ void PepperMediaDeviceManager::NotifyDeviceOpened(int request_id,
callback.Run(request_id, succeeded, label);
}
-RenderViewImpl* PepperMediaDeviceManager::GetRenderViewImpl() {
- return static_cast<RenderViewImpl*>(render_view());
+MediaStreamDispatcher* PepperMediaDeviceManager::GetMediaStreamDispatcher()
+ const {
+ DCHECK(render_frame());
+ MediaStreamDispatcher* const dispatcher =
+ static_cast<RenderFrameImpl*>(render_frame())->GetMediaStreamDispatcher();
+ DCHECK(dispatcher);
+ return dispatcher;
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_media_device_manager.h b/chromium/content/renderer/pepper/pepper_media_device_manager.h
index 6fa7d7a044b..6fd8ded682c 100644
--- a/chromium/content/renderer/pepper/pepper_media_device_manager.h
+++ b/chromium/content/renderer/pepper/pepper_media_device_manager.h
@@ -8,30 +8,30 @@
#include <map>
#include "base/memory/weak_ptr.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/render_frame_observer_tracker.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
#include "content/renderer/pepper/pepper_device_enumeration_host_helper.h"
-#include "content/public/renderer/render_view_observer_tracker.h"
-#include "content/public/renderer/render_view_observer.h"
namespace content {
-class RenderViewImpl;
+class MediaStreamDispatcher;
class PepperMediaDeviceManager
: public MediaStreamDispatcherEventHandler,
public PepperDeviceEnumerationHostHelper::Delegate,
- public RenderViewObserver,
- public RenderViewObserverTracker<PepperMediaDeviceManager>,
+ public RenderFrameObserver,
+ public RenderFrameObserverTracker<PepperMediaDeviceManager>,
public base::SupportsWeakPtr<PepperMediaDeviceManager> {
public:
- static PepperMediaDeviceManager* GetForRenderView(RenderView* render_view);
- virtual ~PepperMediaDeviceManager();
+ static base::WeakPtr<PepperMediaDeviceManager> GetForRenderFrame(
+ RenderFrame* render_frame);
+ ~PepperMediaDeviceManager() override;
// PepperDeviceEnumerationHostHelper::Delegate implementation:
- virtual int EnumerateDevices(PP_DeviceType_Dev type,
- const GURL& document_url,
- const EnumerateDevicesCallback& callback)
- OVERRIDE;
- virtual void StopEnumerateDevices(int request_id) OVERRIDE;
+ int EnumerateDevices(PP_DeviceType_Dev type,
+ const GURL& document_url,
+ const EnumerateDevicesCallback& callback) override;
+ void StopEnumerateDevices(int request_id) override;
typedef base::Callback<void(int /* request_id */,
bool /* succeeded */,
@@ -55,36 +55,40 @@ class PepperMediaDeviceManager
int GetSessionID(PP_DeviceType_Dev type, const std::string& label);
// MediaStreamDispatcherEventHandler implementation.
- virtual void OnStreamGenerated(
+ void OnStreamGenerated(
int request_id,
const std::string& label,
const StreamDeviceInfoArray& audio_device_array,
- const StreamDeviceInfoArray& video_device_array) OVERRIDE;
- virtual void OnStreamGenerationFailed(
+ const StreamDeviceInfoArray& video_device_array) override;
+ void OnStreamGenerationFailed(
int request_id,
- content::MediaStreamRequestResult result) OVERRIDE;
- virtual void OnDeviceStopped(const std::string& label,
- const StreamDeviceInfo& device_info) OVERRIDE;
- virtual void OnDevicesEnumerated(int request_id,
- const StreamDeviceInfoArray& device_array)
- OVERRIDE;
- virtual void OnDeviceOpened(int request_id,
- const std::string& label,
- const StreamDeviceInfo& device_info) OVERRIDE;
- virtual void OnDeviceOpenFailed(int request_id) OVERRIDE;
+ content::MediaStreamRequestResult result) override;
+ void OnDeviceStopped(const std::string& label,
+ const StreamDeviceInfo& device_info) override;
+ void OnDevicesEnumerated(int request_id,
+ const StreamDeviceInfoArray& device_array) override;
+ void OnDeviceOpened(int request_id,
+ const std::string& label,
+ const StreamDeviceInfo& device_info) override;
+ void OnDeviceOpenFailed(int request_id) override;
// Stream type conversion.
static MediaStreamType FromPepperDeviceType(PP_DeviceType_Dev type);
static PP_DeviceType_Dev FromMediaStreamType(MediaStreamType type);
private:
- PepperMediaDeviceManager(RenderView* render_view);
+ explicit PepperMediaDeviceManager(RenderFrame* render_frame);
+
+ // Called by StopEnumerateDevices() after returing to the event loop, to avoid
+ // a reentrancy problem.
+ void StopEnumerateDevicesDelayed(int request_id);
void NotifyDeviceOpened(int request_id,
bool succeeded,
const std::string& label);
- RenderViewImpl* GetRenderViewImpl();
+
+ MediaStreamDispatcher* GetMediaStreamDispatcher() const;
int next_id_;
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc b/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc
index d972c2c061e..72279f65290 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc
+++ b/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.cc
@@ -16,6 +16,7 @@
#include "ppapi/c/ppb_audio_buffer.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/host_message_context.h"
+#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "ppapi/shared_impl/media_stream_buffer.h"
@@ -26,8 +27,9 @@ using ppapi::MediaStreamAudioTrackShared;
namespace {
-// Max audio buffer duration in milliseconds.
-const uint32_t kMaxDuration = 10;
+// Audio buffer durations in milliseconds.
+const uint32_t kMinDuration = 10;
+const uint32_t kDefaultDuration = 10;
const int32_t kDefaultNumberOfBuffers = 4;
const int32_t kMaxNumberOfBuffers = 1000; // 10 sec
@@ -65,10 +67,15 @@ PepperMediaStreamAudioTrackHost::AudioSink::AudioSink(
PepperMediaStreamAudioTrackHost* host)
: host_(host),
buffer_data_size_(0),
+ active_buffer_index_(-1),
+ active_buffers_generation_(0),
+ active_buffer_offset_(0),
+ buffers_generation_(0),
main_message_loop_proxy_(base::MessageLoopProxy::current()),
- weak_factory_(this),
number_of_buffers_(kDefaultNumberOfBuffers),
- bytes_per_second_(0) {}
+ bytes_per_second_(0),
+ user_buffer_duration_(kDefaultDuration),
+ weak_factory_(this) {}
PepperMediaStreamAudioTrackHost::AudioSink::~AudioSink() {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
@@ -82,51 +89,108 @@ void PepperMediaStreamAudioTrackHost::AudioSink::EnqueueBuffer(int32_t index) {
buffers_.push_back(index);
}
-void PepperMediaStreamAudioTrackHost::AudioSink::Configure(
- int32_t number_of_buffers) {
+int32_t PepperMediaStreamAudioTrackHost::AudioSink::Configure(
+ int32_t number_of_buffers, int32_t duration,
+ const ppapi::host::ReplyMessageContext& context) {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
+
+ if (pending_configure_reply_.is_valid()) {
+ return PP_ERROR_INPROGRESS;
+ }
+ pending_configure_reply_ = context;
+
bool changed = false;
if (number_of_buffers != number_of_buffers_)
changed = true;
+ if (duration != 0 && duration != user_buffer_duration_) {
+ user_buffer_duration_ = duration;
+ changed = true;
+ }
number_of_buffers_ = number_of_buffers;
- // Initialize later in OnSetFormat if bytes_per_second_ is not know yet.
- if (changed && bytes_per_second_ > 0)
- InitBuffers();
+ if (changed) {
+ // Initialize later in OnSetFormat if bytes_per_second_ is not known yet.
+ if (bytes_per_second_ > 0 && bytes_per_frame_ > 0)
+ InitBuffers();
+ } else {
+ SendConfigureReply(PP_OK);
+ }
+ return PP_OK_COMPLETIONPENDING;
+}
+
+void PepperMediaStreamAudioTrackHost::AudioSink::SendConfigureReply(
+ int32_t result) {
+ if (pending_configure_reply_.is_valid()) {
+ pending_configure_reply_.params.set_result(result);
+ host_->host()->SendReply(
+ pending_configure_reply_,
+ PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply());
+ pending_configure_reply_ = ppapi::host::ReplyMessageContext();
+ }
}
void PepperMediaStreamAudioTrackHost::AudioSink::SetFormatOnMainThread(
- int bytes_per_second) {
+ int bytes_per_second, int bytes_per_frame) {
bytes_per_second_ = bytes_per_second;
+ bytes_per_frame_ = bytes_per_frame;
InitBuffers();
}
void PepperMediaStreamAudioTrackHost::AudioSink::InitBuffers() {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
+ {
+ base::AutoLock lock(lock_);
+ // Clear |buffers_|, so the audio thread will drop all incoming audio data.
+ buffers_.clear();
+ buffers_generation_++;
+ }
+ int32_t frame_rate = bytes_per_second_ / bytes_per_frame_;
+ base::CheckedNumeric<int32_t> frames_per_buffer = user_buffer_duration_;
+ frames_per_buffer *= frame_rate;
+ frames_per_buffer /= base::Time::kMillisecondsPerSecond;
+ base::CheckedNumeric<int32_t> buffer_audio_size =
+ frames_per_buffer * bytes_per_frame_;
// The size is slightly bigger than necessary, because 8 extra bytes are
- // added into the struct. Also see |MediaStreamBuffer|.
- base::CheckedNumeric<int32_t> buffer_size = bytes_per_second_;
- buffer_size *= kMaxDuration;
- buffer_size /= base::Time::kMillisecondsPerSecond;
+ // added into the struct. Also see |MediaStreamBuffer|. Also, the size of the
+ // buffer may be larger than requested, since the size of each buffer will be
+ // 4-byte aligned.
+ base::CheckedNumeric<int32_t> buffer_size = buffer_audio_size;
buffer_size += sizeof(ppapi::MediaStreamBuffer::Audio);
+ DCHECK_GT(buffer_size.ValueOrDie(), 0);
+
+ // We don't need to hold |lock_| during |host->InitBuffers()| call, because
+ // we just cleared |buffers_| , so the audio thread will drop all incoming
+ // audio data, and not use buffers in |host_|.
bool result = host_->InitBuffers(number_of_buffers_,
buffer_size.ValueOrDie(),
kRead);
- // TODO(penghuang): Send PP_ERROR_NOMEMORY to plugin.
- CHECK(result);
+ if (!result) {
+ SendConfigureReply(PP_ERROR_NOMEMORY);
+ return;
+ }
+
+ // Fill the |buffers_|, so the audio thread can continue receiving audio data.
base::AutoLock lock(lock_);
- buffers_.clear();
+ output_buffer_size_ = buffer_audio_size.ValueOrDie();
for (int32_t i = 0; i < number_of_buffers_; ++i) {
int32_t index = host_->buffer_manager()->DequeueBuffer();
DCHECK_GE(index, 0);
buffers_.push_back(index);
}
+
+ SendConfigureReply(PP_OK);
}
void PepperMediaStreamAudioTrackHost::AudioSink::
- SendEnqueueBufferMessageOnMainThread(int32_t index) {
+ SendEnqueueBufferMessageOnMainThread(int32_t index,
+ int32_t buffers_generation) {
DCHECK_EQ(main_message_loop_proxy_, base::MessageLoopProxy::current());
- host_->SendEnqueueBufferMessageToPlugin(index);
+ // If |InitBuffers()| is called after this task being posted from the audio
+ // thread, the buffer should become invalid already. We should ignore it.
+ // And because only the main thread modifies the |buffers_generation_|,
+ // so we don't need to lock |lock_| here (main thread).
+ if (buffers_generation == buffers_generation_)
+ host_->SendEnqueueBufferMessageToPlugin(index);
}
void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
@@ -137,34 +201,76 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
DCHECK(audio_data);
DCHECK_EQ(sample_rate, audio_params_.sample_rate());
DCHECK_EQ(number_of_channels, audio_params_.channels());
+ // Here, |number_of_frames| and |audio_params_.frames_per_buffer()| refer to
+ // the incomming audio buffer. However, this doesn't necessarily equal
+ // |buffer->number_of_samples|, which is configured by the user when they set
+ // buffer duration.
DCHECK_EQ(number_of_frames, audio_params_.frames_per_buffer());
- int32_t index = -1;
- {
- base::AutoLock lock(lock_);
- if (!buffers_.empty()) {
- index = buffers_.front();
+
+ const uint32_t bytes_per_frame = number_of_channels *
+ audio_params_.bits_per_sample() / 8;
+
+ int frames_remaining = number_of_frames;
+ base::TimeDelta timestamp_offset;
+
+ base::AutoLock lock(lock_);
+ while (frames_remaining) {
+ if (active_buffers_generation_ != buffers_generation_) {
+ // Buffers have changed, so drop the active buffer.
+ active_buffer_index_ = -1;
+ }
+ if (active_buffer_index_ == -1 && !buffers_.empty()) {
+ active_buffers_generation_ = buffers_generation_;
+ active_buffer_offset_ = 0;
+ active_buffer_index_ = buffers_.front();
buffers_.pop_front();
}
- }
+ if (active_buffer_index_ == -1) {
+ // Eek! We're dropping frames. Bad, bad, bad!
+ break;
+ }
- if (index != -1) {
// TODO(penghuang): support re-sampling, etc.
ppapi::MediaStreamBuffer::Audio* buffer =
- &(host_->buffer_manager()->GetBufferPointer(index)->audio);
- buffer->header.size = host_->buffer_manager()->buffer_size();
- buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO;
- buffer->timestamp = timestamp_.InMillisecondsF();
- buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate);
- buffer->number_of_channels = number_of_channels;
- buffer->number_of_samples = number_of_channels * number_of_frames;
- buffer->data_size = buffer_data_size_;
- memcpy(buffer->data, audio_data, buffer_data_size_);
-
- main_message_loop_proxy_->PostTask(
- FROM_HERE,
- base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread,
- weak_factory_.GetWeakPtr(),
- index));
+ &(host_->buffer_manager()->GetBufferPointer(active_buffer_index_)
+ ->audio);
+ if (active_buffer_offset_ == 0) {
+ // The active buffer is new, so initialise the header and metadata fields.
+ buffer->header.size = host_->buffer_manager()->buffer_size();
+ buffer->header.type = ppapi::MediaStreamBuffer::TYPE_AUDIO;
+ buffer->timestamp = (timestamp_ + timestamp_offset).InMillisecondsF();
+ buffer->sample_rate = static_cast<PP_AudioBuffer_SampleRate>(sample_rate);
+ buffer->data_size = output_buffer_size_;
+ buffer->number_of_channels = number_of_channels;
+ buffer->number_of_samples = buffer->data_size * number_of_channels /
+ bytes_per_frame;
+ }
+ uint32_t buffer_bytes_remaining =
+ buffer->data_size - active_buffer_offset_;
+ DCHECK_EQ(buffer_bytes_remaining % bytes_per_frame, 0U);
+ uint32_t incoming_bytes_remaining = frames_remaining * bytes_per_frame;
+ uint32_t bytes_to_copy = std::min(buffer_bytes_remaining,
+ incoming_bytes_remaining);
+ uint32_t frames_to_copy = bytes_to_copy / bytes_per_frame;
+ DCHECK_EQ(bytes_to_copy % bytes_per_frame, 0U);
+ memcpy(buffer->data + active_buffer_offset_,
+ audio_data, bytes_to_copy);
+ active_buffer_offset_ += bytes_to_copy;
+ audio_data += bytes_to_copy / sizeof(*audio_data);
+ frames_remaining -= frames_to_copy;
+ timestamp_offset += base::TimeDelta::FromMilliseconds(
+ frames_to_copy * base::Time::kMillisecondsPerSecond / sample_rate);
+
+ DCHECK_LE(active_buffer_offset_, buffer->data_size);
+ if (active_buffer_offset_ == buffer->data_size) {
+ main_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioSink::SendEnqueueBufferMessageOnMainThread,
+ weak_factory_.GetWeakPtr(),
+ active_buffer_index_,
+ buffers_generation_));
+ active_buffer_index_ = -1;
+ }
}
timestamp_ += buffer_duration_;
}
@@ -172,7 +278,12 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnData(const int16* audio_data,
void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
const AudioParameters& params) {
DCHECK(params.IsValid());
- DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMaxDuration);
+ // TODO(amistry): How do you handle the case where the user configures a
+ // duration that's shorter than the received buffer duration? One option is to
+ // double buffer, where the size of the intermediate ring buffer is at least
+ // max(user requested duration, received buffer duration). There are other
+ // ways of dealing with it, but which one is "correct"?
+ DCHECK_LE(params.GetBufferDuration().InMilliseconds(), kMinDuration);
DCHECK_EQ(params.bits_per_sample(), 16);
DCHECK_NE(GetPPSampleRate(params.sample_rate()),
PP_AUDIOBUFFER_SAMPLERATE_UNKNOWN);
@@ -192,11 +303,13 @@ void PepperMediaStreamAudioTrackHost::AudioSink::OnSetFormat(
audio_thread_checker_.DetachFromThread();
original_audio_params_ = params;
+ int bytes_per_frame = params.channels() * params.bits_per_sample() / 8;
main_message_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&AudioSink::SetFormatOnMainThread,
weak_factory_.GetWeakPtr(),
- params.GetBytesPerSecond()));
+ params.GetBytesPerSecond(),
+ bytes_per_frame));
}
}
@@ -236,10 +349,8 @@ int32_t PepperMediaStreamAudioTrackHost::OnHostMsgConfigure(
int32_t buffers = attributes.buffers
? std::min(kMaxNumberOfBuffers, attributes.buffers)
: kDefaultNumberOfBuffers;
- audio_sink_.Configure(buffers);
-
- context->reply_msg = PpapiPluginMsg_MediaStreamAudioTrack_ConfigureReply();
- return PP_OK;
+ return audio_sink_.Configure(buffers, attributes.duration,
+ context->MakeReplyMessageContext());
}
void PepperMediaStreamAudioTrackHost::OnClose() {
@@ -247,6 +358,7 @@ void PepperMediaStreamAudioTrackHost::OnClose() {
MediaStreamAudioSink::RemoveFromAudioTrack(&audio_sink_, track_);
connected_ = false;
}
+ audio_sink_.SendConfigureReply(PP_ERROR_ABORTED);
}
void PepperMediaStreamAudioTrackHost::OnNewBufferEnqueued() {
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.h b/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.h
index 348103c9928..1580441fc11 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.h
+++ b/chromium/content/renderer/pepper/pepper_media_stream_audio_track_host.h
@@ -15,6 +15,7 @@
#include "content/public/renderer/media_stream_audio_sink.h"
#include "content/renderer/pepper/pepper_media_stream_track_host_base.h"
#include "media/audio/audio_parameters.h"
+#include "ppapi/host/host_message_context.h"
#include "ppapi/shared_impl/media_stream_audio_track_shared.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
@@ -37,7 +38,7 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
class AudioSink : public MediaStreamAudioSink {
public:
explicit AudioSink(PepperMediaStreamAudioTrackHost* host);
- virtual ~AudioSink();
+ ~AudioSink() override;
// Enqueues a free buffer index into |buffers_| which will be used for
// sending audio samples to plugin.
@@ -45,24 +46,29 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
void EnqueueBuffer(int32_t index);
// This function is called on the main thread.
- void Configure(int32_t number_of_buffers);
+ int32_t Configure(int32_t number_of_buffers, int32_t duration,
+ const ppapi::host::ReplyMessageContext& context);
+
+ // Send a reply to the currently pending |Configure()| request.
+ void SendConfigureReply(int32_t result);
private:
// Initializes buffers on the main thread.
- void SetFormatOnMainThread(int bytes_per_second);
+ void SetFormatOnMainThread(int bytes_per_second, int bytes_per_frame);
void InitBuffers();
// Send enqueue buffer message on the main thread.
- void SendEnqueueBufferMessageOnMainThread(int32_t index);
+ void SendEnqueueBufferMessageOnMainThread(int32_t index,
+ int32_t buffers_generation);
// MediaStreamAudioSink overrides:
// These two functions should be called on the audio thread.
- virtual void OnData(const int16* audio_data,
- int sample_rate,
- int number_of_channels,
- int number_of_frames) OVERRIDE;
- virtual void OnSetFormat(const media::AudioParameters& params) OVERRIDE;
+ void OnData(const int16* audio_data,
+ int sample_rate,
+ int number_of_channels,
+ int number_of_frames) override;
+ void OnSetFormat(const media::AudioParameters& params) override;
// Unowned host which is available during the AudioSink's lifespan.
// It is mainly used in the main thread. But the audio thread will use
@@ -92,33 +98,62 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
// Access only on the audio thread.
uint32_t buffer_data_size_;
- // A lock to protect the index queue |buffers_|.
+ // Index of the currently active buffer.
+ // Access only on the audio thread.
+ int active_buffer_index_;
+
+ // Generation of buffers corresponding to the currently active
+ // buffer. Used to make sure the active buffer is still valid.
+ // Access only on the audio thread.
+ int32_t active_buffers_generation_;
+
+ // Current offset, in bytes, within the currently active buffer.
+ // Access only on the audio thread.
+ uint32_t active_buffer_offset_;
+
+ // A lock to protect the index queue |buffers_|, |buffers_generation_|,
+ // buffers in |host_->buffer_manager()|, and |output_buffer_size_|.
base::Lock lock_;
// A queue for free buffer indices.
std::deque<int32_t> buffers_;
+ // Generation of buffers. It is increased by every |InitBuffers()| call.
+ int32_t buffers_generation_;
+
+ // Intended size of each output buffer.
+ int32_t output_buffer_size_;
+
scoped_refptr<base::MessageLoopProxy> main_message_loop_proxy_;
base::ThreadChecker audio_thread_checker_;
- base::WeakPtrFactory<AudioSink> weak_factory_;
-
// Number of buffers.
int32_t number_of_buffers_;
// Number of bytes per second.
int bytes_per_second_;
+ // Number of bytes per frame = channels * bytes per sample.
+ int bytes_per_frame_;
+
+ // User-configured buffer duration, in milliseconds.
+ int32_t user_buffer_duration_;
+
+ // Pending |Configure()| reply context.
+ ppapi::host::ReplyMessageContext pending_configure_reply_;
+
+ base::WeakPtrFactory<AudioSink> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AudioSink);
};
- virtual ~PepperMediaStreamAudioTrackHost();
+ ~PepperMediaStreamAudioTrackHost() override;
// ResourceMessageHandler overrides:
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// Message handlers:
int32_t OnHostMsgConfigure(
@@ -126,13 +161,13 @@ class PepperMediaStreamAudioTrackHost : public PepperMediaStreamTrackHostBase {
const ppapi::MediaStreamAudioTrackShared::Attributes& attributes);
// PepperMediaStreamTrackHostBase overrides:
- virtual void OnClose() OVERRIDE;
+ void OnClose() override;
// MediaStreamBufferManager::Delegate overrides:
- virtual void OnNewBufferEnqueued() OVERRIDE;
+ void OnNewBufferEnqueued() override;
// ResourceHost overrides:
- virtual void DidConnectPendingHostToResource() OVERRIDE;
+ void DidConnectPendingHostToResource() override;
blink::WebMediaStreamTrack track_;
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc b/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc
index 9ad40a9cf08..c7713135a15 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc
+++ b/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc
@@ -38,6 +38,8 @@ bool PepperMediaStreamTrackHostBase::InitBuffers(int32_t number_of_buffers,
static_cast<int32_t>(sizeof(ppapi::MediaStreamBuffer::Header)));
// Make each buffer 4 byte aligned.
base::CheckedNumeric<int32_t> buffer_size_aligned = buffer_size;
+ // TODO(amistry): "buffer size" might not == "buffer stride", in the same way
+ // that width != stride in an image buffer.
buffer_size_aligned += (4 - buffer_size % 4);
// TODO(penghuang): |HostAllocateSharedMemoryBuffer| uses sync IPC. We should
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.h b/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.h
index 37ebd611515..ddfac9cb7d9 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.h
+++ b/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.h
@@ -21,7 +21,7 @@ class PepperMediaStreamTrackHostBase
PepperMediaStreamTrackHostBase(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperMediaStreamTrackHostBase();
+ ~PepperMediaStreamTrackHostBase() override;
enum TrackType {
kRead,
@@ -46,9 +46,9 @@ class PepperMediaStreamTrackHostBase
void SendEnqueueBuffersMessageToPlugin(const std::vector<int32_t>& indices);
// ResourceMessageHandler overrides:
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// Message handlers:
virtual int32_t OnHostMsgEnqueueBuffer(
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
index 5df6f2df9a5..ade9cafb3a1 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
+++ b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
@@ -20,7 +20,7 @@
#include "ppapi/shared_impl/media_stream_buffer.h"
// IS_ALIGNED is also defined in
-// third_party/libjingle/overrides/talk/base/basictypes.h
+// third_party/webrtc/overrides/webrtc/base/basictypes.h
// TODO(ronghuawu): Avoid undef.
#undef IS_ALIGNED
#include "third_party/libyuv/include/libyuv.h"
@@ -385,7 +385,7 @@ void PepperMediaStreamVideoTrackHost::OnVideoFrame(
const scoped_refptr<VideoFrame>& frame,
const media::VideoCaptureFormat& format,
const base::TimeTicks& estimated_capture_time) {
- DCHECK(frame);
+ DCHECK(frame.get());
// TODO(penghuang): Check |frame->end_of_stream()| and close the track.
PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format());
if (ppformat == PP_VIDEOFRAME_FORMAT_UNKNOWN)
@@ -404,7 +404,6 @@ void PepperMediaStreamVideoTrackHost::OnVideoFrame(
return;
}
- CHECK(frame->coded_size() == source_frame_size_) << "Frame size is changed";
CHECK_EQ(ppformat, source_frame_format_) << "Frame format is changed.";
gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_);
@@ -426,6 +425,7 @@ void PepperMediaStreamVideoTrackHost::OnVideoFrame(
void PepperMediaStreamVideoTrackHost::GetCurrentSupportedFormats(
int max_requested_width, int max_requested_height,
+ double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) {
if (type_ != kWrite) {
DVLOG(1) << "GetCurrentSupportedFormats is only supported in output mode.";
@@ -442,7 +442,7 @@ void PepperMediaStreamVideoTrackHost::GetCurrentSupportedFormats(
}
void PepperMediaStreamVideoTrackHost::StartSourceImpl(
- const media::VideoCaptureParams& params,
+ const media::VideoCaptureFormat& format,
const VideoCaptureDeliverFrameCB& frame_callback) {
output_started_ = true;
frame_deliverer_ = new FrameDeliverer(io_message_loop(), frame_callback);
@@ -538,8 +538,10 @@ void PepperMediaStreamVideoTrackHost::InitBlinkTrack() {
}
void PepperMediaStreamVideoTrackHost::OnTrackStarted(
- MediaStreamSource* source, bool success) {
- DVLOG(3) << "OnTrackStarted result: " << success;
+ MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name) {
+ DVLOG(3) << "OnTrackStarted result: " << result;
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
index 178eaefbd10..1ed80524550 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
+++ b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
@@ -37,7 +37,7 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
PP_Instance instance,
PP_Resource resource);
- virtual bool IsMediaStreamVideoTrackHost() OVERRIDE;
+ bool IsMediaStreamVideoTrackHost() override;
blink::WebMediaStreamTrack track() { return track_; }
@@ -48,9 +48,9 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
void InitBuffers();
// PepperMediaStreamTrackHostBase overrides:
- virtual void OnClose() OVERRIDE;
- virtual int32_t OnHostMsgEnqueueBuffer(
- ppapi::host::HostMessageContext* context, int32_t index) OVERRIDE;
+ void OnClose() override;
+ int32_t OnHostMsgEnqueueBuffer(ppapi::host::HostMessageContext* context,
+ int32_t index) override;
// Sends frame with |index| to |track_|.
int32_t SendFrameToTrack(int32_t index);
@@ -60,24 +60,25 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
const base::TimeTicks& estimated_capture_time);
// MediaStreamVideoSource overrides:
- virtual void GetCurrentSupportedFormats(
+ void GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
- const VideoCaptureDeviceFormatsCB& callback) OVERRIDE;
+ double max_requested_frame_rate,
+ const VideoCaptureDeviceFormatsCB& callback) override;
- virtual void StartSourceImpl(
- const media::VideoCaptureParams& params,
- const VideoCaptureDeliverFrameCB& frame_callback) OVERRIDE;
+ void StartSourceImpl(
+ const media::VideoCaptureFormat& format,
+ const VideoCaptureDeliverFrameCB& frame_callback) override;
- virtual void StopSourceImpl() OVERRIDE;
+ void StopSourceImpl() override;
// ResourceHost overrides:
- virtual void DidConnectPendingHostToResource() OVERRIDE;
+ void DidConnectPendingHostToResource() override;
// ResourceMessageHandler overrides:
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// Message handlers:
int32_t OnHostMsgConfigure(
@@ -85,7 +86,9 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
const ppapi::MediaStreamVideoTrackShared::Attributes& attributes);
void InitBlinkTrack();
- void OnTrackStarted(MediaStreamSource* source, bool success);
+ void OnTrackStarted(MediaStreamSource* source,
+ MediaStreamRequestResult result,
+ const blink::WebString& result_name);
blink::WebMediaStreamTrack track_;
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
index ed2bbcfc4fb..9b461206805 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc
@@ -12,6 +12,7 @@
#include "content/renderer/media/audio_input_message_filter.h"
#include "content/renderer/pepper/pepper_audio_input_host.h"
#include "content/renderer/pepper/pepper_media_device_manager.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "media/audio/audio_manager_base.h"
@@ -22,7 +23,7 @@ namespace content {
// static
PepperPlatformAudioInput* PepperPlatformAudioInput::Create(
- const base::WeakPtr<RenderViewImpl>& render_view,
+ int render_frame_id,
const std::string& device_id,
const GURL& document_url,
int sample_rate,
@@ -30,7 +31,7 @@ PepperPlatformAudioInput* PepperPlatformAudioInput::Create(
PepperAudioInputHost* client) {
scoped_refptr<PepperPlatformAudioInput> audio_input(
new PepperPlatformAudioInput());
- if (audio_input->Initialize(render_view,
+ if (audio_input->Initialize(render_frame_id,
device_id,
document_url,
sample_rate,
@@ -139,12 +140,13 @@ PepperPlatformAudioInput::PepperPlatformAudioInput()
: client_(NULL),
main_message_loop_proxy_(base::MessageLoopProxy::current()),
io_message_loop_proxy_(ChildProcess::current()->io_message_loop_proxy()),
+ render_frame_id_(MSG_ROUTING_NONE),
create_stream_sent_(false),
pending_open_device_(false),
pending_open_device_id_(-1) {}
bool PepperPlatformAudioInput::Initialize(
- const base::WeakPtr<RenderViewImpl>& render_view,
+ int render_frame_id,
const std::string& device_id,
const GURL& document_url,
int sample_rate,
@@ -152,20 +154,24 @@ bool PepperPlatformAudioInput::Initialize(
PepperAudioInputHost* client) {
DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
- if (!render_view.get() || !client)
+ RenderFrameImpl* const render_frame =
+ RenderFrameImpl::FromRoutingID(render_frame_id);
+ if (!render_frame || !client)
+ return false;
+
+ render_frame_id_ = render_frame_id;
+ client_ = client;
+
+ if (!GetMediaDeviceManager())
return false;
ipc_ = RenderThreadImpl::current()
->audio_input_message_filter()
- ->CreateAudioInputIPC(render_view->GetRoutingID());
-
- render_view_ = render_view;
- client_ = client;
+ ->CreateAudioInputIPC(render_frame->render_view()->GetRoutingID());
params_.Reset(media::AudioParameters::AUDIO_PCM_LINEAR,
media::CHANNEL_LAYOUT_MONO,
ppapi::kAudioInputChannels,
- 0,
sample_rate,
ppapi::kBitsPerAudioInputSample,
frames_per_buffer);
@@ -230,12 +236,13 @@ void PepperPlatformAudioInput::OnDeviceOpened(int request_id,
pending_open_device_ = false;
pending_open_device_id_ = -1;
- if (succeeded && render_view_.get()) {
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ if (succeeded && device_manager) {
DCHECK(!label.empty());
label_ = label;
if (client_) {
- int session_id = GetMediaDeviceManager()->GetSessionID(
+ int session_id = device_manager->GetSessionID(
PP_DEVICETYPE_DEV_AUDIOCAPTURE, label);
io_message_loop_proxy_->PostTask(
FROM_HERE,
@@ -254,16 +261,18 @@ void PepperPlatformAudioInput::OnDeviceOpened(int request_id,
void PepperPlatformAudioInput::CloseDevice() {
DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
- if (render_view_.get()) {
- if (!label_.empty()) {
- GetMediaDeviceManager()->CloseDevice(label_);
- label_.clear();
- }
- if (pending_open_device_) {
- GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_);
- pending_open_device_ = false;
- pending_open_device_id_ = -1;
- }
+ if (!label_.empty()) {
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ if (device_manager)
+ device_manager->CloseDevice(label_);
+ label_.clear();
+ }
+ if (pending_open_device_) {
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ if (device_manager)
+ device_manager->CancelOpenDevice(pending_open_device_id_);
+ pending_open_device_ = false;
+ pending_open_device_id_ = -1;
}
}
@@ -275,7 +284,12 @@ void PepperPlatformAudioInput::NotifyStreamCreationFailed() {
}
PepperMediaDeviceManager* PepperPlatformAudioInput::GetMediaDeviceManager() {
- return PepperMediaDeviceManager::GetForRenderView(render_view_.get());
+ DCHECK(main_message_loop_proxy_->BelongsToCurrentThread());
+
+ RenderFrameImpl* const render_frame =
+ RenderFrameImpl::FromRoutingID(render_frame_id_);
+ return render_frame ?
+ PepperMediaDeviceManager::GetForRenderFrame(render_frame).get() : NULL;
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.h b/chromium/content/renderer/pepper/pepper_platform_audio_input.h
index 56a701aeeb7..a567ed4cb00 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_input.h
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.h
@@ -29,7 +29,6 @@ namespace content {
class PepperAudioInputHost;
class PepperMediaDeviceManager;
-class RenderViewImpl;
// PepperPlatformAudioInput is operated on two threads: the main thread (the
// thread on which objects are created) and the I/O thread. All public methods,
@@ -45,7 +44,7 @@ class PepperPlatformAudioInput
// Factory function, returns NULL on failure. StreamCreated() will be called
// when the stream is created.
static PepperPlatformAudioInput* Create(
- const base::WeakPtr<RenderViewImpl>& render_view,
+ int render_frame_id,
const std::string& device_id,
const GURL& document_url,
int sample_rate,
@@ -59,24 +58,23 @@ class PepperPlatformAudioInput
void ShutDown();
// media::AudioInputIPCDelegate.
- virtual void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle,
- int length,
- int total_segments) OVERRIDE;
- virtual void OnVolume(double volume) OVERRIDE;
- virtual void OnStateChanged(media::AudioInputIPCDelegate::State state)
- OVERRIDE;
- virtual void OnIPCClosed() OVERRIDE;
+ void OnStreamCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ int length,
+ int total_segments) override;
+ void OnVolume(double volume) override;
+ void OnStateChanged(media::AudioInputIPCDelegate::State state) override;
+ void OnIPCClosed() override;
protected:
- virtual ~PepperPlatformAudioInput();
+ ~PepperPlatformAudioInput() override;
private:
friend class base::RefCountedThreadSafe<PepperPlatformAudioInput>;
PepperPlatformAudioInput();
- bool Initialize(const base::WeakPtr<RenderViewImpl>& render_view,
+ bool Initialize(int render_frame_id,
const std::string& device_id,
const GURL& document_url,
int sample_rate,
@@ -93,6 +91,8 @@ class PepperPlatformAudioInput
void CloseDevice();
void NotifyStreamCreationFailed();
+ // Can return NULL if the RenderFrame referenced by |render_frame_id_| has
+ // gone away.
PepperMediaDeviceManager* GetMediaDeviceManager();
// The client to notify when the stream is created. THIS MUST ONLY BE
@@ -106,8 +106,8 @@ class PepperPlatformAudioInput
scoped_refptr<base::MessageLoopProxy> main_message_loop_proxy_;
scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
- // THIS MUST ONLY BE ACCESSED ON THE MAIN THREAD.
- base::WeakPtr<RenderViewImpl> render_view_;
+ // The frame containing the Pepper widget.
+ int render_frame_id_;
// The unique ID to identify the opened device. THIS MUST ONLY BE ACCESSED ON
// THE MAIN THREAD.
diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.h b/chromium/content/renderer/pepper/pepper_platform_audio_output.h
index 725d42f03a8..8c1c45cd9be 100644
--- a/chromium/content/renderer/pepper/pepper_platform_audio_output.h
+++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.h
@@ -48,15 +48,14 @@ class PepperPlatformAudioOutput
void ShutDown();
// media::AudioOutputIPCDelegate implementation.
- virtual void OnStateChanged(media::AudioOutputIPCDelegate::State state)
- OVERRIDE;
- virtual void OnStreamCreated(base::SharedMemoryHandle handle,
- base::SyncSocket::Handle socket_handle,
- int length) OVERRIDE;
- virtual void OnIPCClosed() OVERRIDE;
+ void OnStateChanged(media::AudioOutputIPCDelegate::State state) override;
+ void OnStreamCreated(base::SharedMemoryHandle handle,
+ base::SyncSocket::Handle socket_handle,
+ int length) override;
+ void OnIPCClosed() override;
protected:
- virtual ~PepperPlatformAudioOutput();
+ ~PepperPlatformAudioOutput() override;
private:
friend class base::RefCountedThreadSafe<PepperPlatformAudioOutput>;
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
index 74eea87f684..0d011f3fdc4 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
@@ -10,19 +10,19 @@
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/pepper/pepper_media_device_manager.h"
#include "content/renderer/pepper/pepper_video_capture_host.h"
+#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_impl.h"
#include "media/base/bind_to_current_loop.h"
#include "url/gurl.h"
namespace content {
PepperPlatformVideoCapture::PepperPlatformVideoCapture(
- const base::WeakPtr<RenderViewImpl>& render_view,
+ int render_frame_id,
const std::string& device_id,
const GURL& document_url,
PepperVideoCaptureHost* handler)
- : render_view_(render_view),
+ : render_frame_id_(render_frame_id),
device_id_(device_id),
session_id_(0),
handler_(handler),
@@ -31,8 +31,9 @@ PepperPlatformVideoCapture::PepperPlatformVideoCapture(
weak_factory_(this) {
// We need to open the device and obtain the label and session ID before
// initializing.
- if (render_view_.get()) {
- pending_open_device_id_ = GetMediaDeviceManager()->OpenDevice(
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ if (device_manager) {
+ pending_open_device_id_ = device_manager->OpenDevice(
PP_DEVICETYPE_DEV_VIDEOCAPTURE,
device_id,
document_url,
@@ -75,16 +76,18 @@ void PepperPlatformVideoCapture::DetachEventHandler() {
release_device_cb_.Run();
release_device_cb_.Reset();
}
- if (render_view_.get()) {
- if (!label_.empty()) {
- GetMediaDeviceManager()->CloseDevice(label_);
- label_.clear();
- }
- if (pending_open_device_) {
- GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_);
- pending_open_device_ = false;
- pending_open_device_id_ = -1;
- }
+ if (!label_.empty()) {
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ if (device_manager)
+ device_manager->CloseDevice(label_);
+ label_.clear();
+ }
+ if (pending_open_device_) {
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ if (device_manager)
+ device_manager->CancelOpenDevice(pending_open_device_id_);
+ pending_open_device_ = false;
+ pending_open_device_id_ = -1;
}
}
@@ -101,10 +104,11 @@ void PepperPlatformVideoCapture::OnDeviceOpened(int request_id,
pending_open_device_ = false;
pending_open_device_id_ = -1;
- succeeded = succeeded && render_view_.get();
+ PepperMediaDeviceManager* const device_manager = GetMediaDeviceManager();
+ succeeded = succeeded && device_manager;
if (succeeded) {
label_ = label;
- session_id_ = GetMediaDeviceManager()->GetSessionID(
+ session_id_ = device_manager->GetSessionID(
PP_DEVICETYPE_DEV_VIDEOCAPTURE, label);
VideoCaptureImplManager* manager =
RenderThreadImpl::current()->video_capture_impl_manager();
@@ -145,7 +149,10 @@ void PepperPlatformVideoCapture::OnFrameReady(
}
PepperMediaDeviceManager* PepperPlatformVideoCapture::GetMediaDeviceManager() {
- return PepperMediaDeviceManager::GetForRenderView(render_view_.get());
+ RenderFrameImpl* const render_frame =
+ RenderFrameImpl::FromRoutingID(render_frame_id_);
+ return render_frame ?
+ PepperMediaDeviceManager::GetForRenderFrame(render_frame).get() : NULL;
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.h b/chromium/content/renderer/pepper/pepper_platform_video_capture.h
index e31b8c7d6a9..2412f492bd6 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.h
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.h
@@ -22,12 +22,11 @@ class GURL;
namespace content {
class PepperMediaDeviceManager;
class PepperVideoCaptureHost;
-class RenderViewImpl;
// This object must only be used on the thread it's constructed on.
class PepperPlatformVideoCapture {
public:
- PepperPlatformVideoCapture(const base::WeakPtr<RenderViewImpl>& render_view,
+ PepperPlatformVideoCapture(int render_frame_id,
const std::string& device_id,
const GURL& document_url,
PepperVideoCaptureHost* handler);
@@ -46,11 +45,13 @@ class PepperPlatformVideoCapture {
const media::VideoCaptureFormat& format,
const base::TimeTicks& estimated_capture_time);
+ // Can return NULL if the RenderFrame referenced by |render_frame_id_| has
+ // gone away.
PepperMediaDeviceManager* GetMediaDeviceManager();
- base::WeakPtr<RenderViewImpl> render_view_;
+ const int render_frame_id_;
+ const std::string device_id_;
- std::string device_id_;
std::string label_;
int session_id_;
base::Closure release_device_cb_;
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 4aaad86e0db..5886cf1f71f 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -11,22 +11,25 @@
#include "base/logging.h"
#include "base/memory/linked_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_offset_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "cc/base/latency_info_swap_promise.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/layers/texture_layer.h"
#include "cc/trees/layer_tree_host.h"
#include "content/common/content_constants_internal.h"
+#include "content/common/frame_messages.h"
#include "content/common/input/web_input_event_traits.h"
+#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/page_zoom.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/gpu/render_widget_compositor.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/content_decryptor_delegate.h"
#include "content/renderer/pepper/event_conversion.h"
#include "content/renderer/pepper/fullscreen_container.h"
@@ -34,15 +37,19 @@
#include "content/renderer/pepper/host_dispatcher_wrapper.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/message_channel.h"
-#include "content/renderer/pepper/npapi_glue.h"
#include "content/renderer/pepper/pepper_browser_connection.h"
#include "content/renderer/pepper/pepper_compositor_host.h"
#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
#include "content/renderer/pepper/pepper_graphics_2d_host.h"
#include "content/renderer/pepper/pepper_in_process_router.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_plugin_instance_throttler.h"
+#include "content/renderer/pepper/pepper_try_catch.h"
#include "content/renderer/pepper/pepper_url_loader_host.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/plugin_object.h"
+#include "content/renderer/pepper/plugin_power_saver_helper.h"
+#include "content/renderer/pepper/ppapi_preferences_builder.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
@@ -92,11 +99,9 @@
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_buffer_api.h"
-#include "printing/metafile.h"
#include "printing/metafile_skia_wrapper.h"
-#include "printing/units.h"
+#include "printing/pdf_metafile_skia.h"
#include "skia/ext/platform_canvas.h"
-#include "skia/ext/platform_device.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "third_party/WebKit/public/platform/WebGamepads.h"
#include "third_party/WebKit/public/platform/WebRect.h"
@@ -115,33 +120,24 @@
#include "third_party/WebKit/public/web/WebPrintParams.h"
#include "third_party/WebKit/public/web/WebPrintScalingOption.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
+#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkRect.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/range/range.h"
-#include "ui/gfx/rect_conversions.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
#include "v8/include/v8.h"
#if defined(OS_CHROMEOS)
#include "ui/events/keycodes/keyboard_codes_posix.h"
#endif
-#if defined(OS_MACOSX)
-#include "printing/metafile_impl.h"
-#endif // defined(OS_MACOSX)
-
#if defined(OS_WIN)
#include "base/metrics/histogram.h"
#include "base/win/windows_version.h"
#include "skia/ext/platform_canvas.h"
-#include "ui/gfx/codec/jpeg_codec.h"
-#include "ui/gfx/gdi_util.h"
#endif
using base::StringPrintf;
@@ -189,37 +185,15 @@ using blink::WebView;
namespace content {
-#if defined(OS_WIN)
-// Exported by pdf.dll
-typedef bool (*RenderPDFPageToDCProc)(const unsigned char* pdf_buffer,
- int buffer_size,
- int page_number,
- HDC dc,
- int dpi_x,
- int dpi_y,
- int bounds_origin_x,
- int bounds_origin_y,
- int bounds_width,
- int bounds_height,
- bool fit_to_bounds,
- bool stretch_to_bounds,
- bool keep_aspect_ratio,
- bool center_in_bounds,
- bool autorotate);
-
-void DrawEmptyRectangle(HDC dc) {
- // TODO(sanjeevr): This is a temporary hack. If we output a JPEG
- // to the EMF, the EnumEnhMetaFile call fails in the browser
- // process. The failure also happens if we output nothing here.
- // We need to investigate the reason for this failure and fix it.
- // In the meantime this temporary hack of drawing an empty
- // rectangle in the DC gets us by.
- Rectangle(dc, 0, 0, 0, 0);
-}
-#endif // defined(OS_WIN)
-
namespace {
+static const int kInfiniteRatio = 99999;
+
+#define UMA_HISTOGRAM_ASPECT_RATIO(name, width, height) \
+ UMA_HISTOGRAM_SPARSE_SLOWLY( \
+ name, \
+ (height) ? ((width) * 100) / (height) : kInfiniteRatio);
+
// Check PP_TextInput_Type and ui::TextInputType are kept in sync.
COMPILE_ASSERT(int(ui::TEXT_INPUT_TYPE_NONE) == int(PP_TEXTINPUT_TYPE_NONE),
mismatching_enums);
@@ -393,14 +367,13 @@ class PluginInstanceLockTarget : public MouseLockDispatcher::LockTarget {
PluginInstanceLockTarget(PepperPluginInstanceImpl* plugin)
: plugin_(plugin) {}
- virtual void OnLockMouseACK(bool succeeded) OVERRIDE {
+ void OnLockMouseACK(bool succeeded) override {
plugin_->OnLockMouseACK(succeeded);
}
- virtual void OnMouseLockLost() OVERRIDE { plugin_->OnMouseLockLost(); }
+ void OnMouseLockLost() override { plugin_->OnMouseLockLost(); }
- virtual bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event)
- OVERRIDE {
+ bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event) override {
plugin_->HandleMouseLockedInputEvent(event);
return true;
}
@@ -426,6 +399,77 @@ void InitLatencyInfo(ui::LatencyInfo* new_latency,
}
}
+// Histogram tracking prevalence of tiny Flash instances. Units in pixels.
+enum PluginFlashTinyContentSize {
+ TINY_CONTENT_SIZE_1_1 = 0,
+ TINY_CONTENT_SIZE_5_5 = 1,
+ TINY_CONTENT_SIZE_10_10 = 2,
+ TINY_CONTENT_SIZE_LARGE = 3,
+ TINY_CONTENT_SIZE_NUM_ITEMS
+};
+
+// How the throttled power saver is unthrottled, if ever.
+// These numeric values are used in UMA logs; do not change them.
+enum PowerSaverUnthrottleMethod {
+ UNTHROTTLE_METHOD_NEVER = 0,
+ UNTHROTTLE_METHOD_BY_CLICK = 1,
+ UNTHROTTLE_METHOD_BY_WHITELIST = 2,
+ UNTHROTTLE_METHOD_NUM_ITEMS
+};
+
+const char kFlashClickSizeAspectRatioHistogram[] =
+ "Plugin.Flash.ClickSize.AspectRatio";
+const char kFlashClickSizeHeightHistogram[] = "Plugin.Flash.ClickSize.Height";
+const char kFlashClickSizeWidthHistogram[] = "Plugin.Flash.ClickSize.Width";
+const char kFlashTinyContentSizeHistogram[] = "Plugin.Flash.TinyContentSize";
+const char kPowerSaverUnthrottleHistogram[] = "Plugin.PowerSaver.Unthrottle";
+
+// Record size metrics for all Flash instances.
+void RecordFlashSizeMetric(int width, int height) {
+ PluginFlashTinyContentSize size = TINY_CONTENT_SIZE_LARGE;
+
+ if (width <= 1 && height <= 1)
+ size = TINY_CONTENT_SIZE_1_1;
+ else if (width <= 5 && height <= 5)
+ size = TINY_CONTENT_SIZE_5_5;
+ else if (width <= 10 && height <= 10)
+ size = TINY_CONTENT_SIZE_10_10;
+
+ UMA_HISTOGRAM_ENUMERATION(kFlashTinyContentSizeHistogram, size,
+ TINY_CONTENT_SIZE_NUM_ITEMS);
+}
+
+// Records size metrics for Flash instances that are clicked.
+void RecordFlashClickSizeMetric(int width, int height) {
+ base::HistogramBase* width_histogram = base::LinearHistogram::FactoryGet(
+ kFlashClickSizeWidthHistogram,
+ 0, // minimum width
+ 500, // maximum width
+ 100, // number of buckets.
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ width_histogram->Add(width);
+
+ base::HistogramBase* height_histogram = base::LinearHistogram::FactoryGet(
+ kFlashClickSizeHeightHistogram,
+ 0, // minimum height
+ 400, // maximum height
+ 100, // number of buckets.
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ height_histogram->Add(height);
+
+ UMA_HISTOGRAM_ASPECT_RATIO(kFlashClickSizeAspectRatioHistogram, width,
+ height);
+}
+
+void RecordUnthrottleMethodMetric(PowerSaverUnthrottleMethod method) {
+ UMA_HISTOGRAM_ENUMERATION(kPowerSaverUnthrottleHistogram, method,
+ UNTHROTTLE_METHOD_NUM_ITEMS);
+}
+
+bool IsFlashPlugin(PluginModule* module) {
+ return module->name() == kFlashPluginName;
+}
+
} // namespace
// static
@@ -440,8 +484,12 @@ PepperPluginInstanceImpl* PepperPluginInstanceImpl::Create(
PPP_Instance_Combined::Create(get_plugin_interface_func);
if (!ppp_instance_combined)
return NULL;
- return new PepperPluginInstanceImpl(
- render_frame, module, ppp_instance_combined, container, plugin_url);
+
+ return new PepperPluginInstanceImpl(render_frame,
+ module,
+ ppp_instance_combined,
+ container,
+ plugin_url);
}
PepperPluginInstanceImpl::ExternalDocumentLoader::ExternalDocumentLoader()
@@ -522,6 +570,10 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
layer_bound_to_fullscreen_(false),
layer_is_hardware_(false),
plugin_url_(plugin_url),
+ has_been_clicked_(false),
+ power_saver_enabled_(false),
+ is_peripheral_content_(false),
+ plugin_throttled_(false),
full_frame_(false),
sent_initial_did_change_view_(false),
bound_graphics_2d_platform_(NULL),
@@ -534,7 +586,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
plugin_mouse_lock_interface_(NULL),
plugin_pdf_interface_(NULL),
plugin_private_interface_(NULL),
- plugin_selection_interface_(NULL),
plugin_textinput_interface_(NULL),
plugin_zoom_interface_(NULL),
checked_for_plugin_input_event_interface_(false),
@@ -547,6 +598,7 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
fullscreen_container_(NULL),
flash_fullscreen_(false),
desired_fullscreen_state_(false),
+ message_channel_(NULL),
sad_plugin_(NULL),
input_event_mask_(0),
filtered_input_event_mask_(0),
@@ -559,7 +611,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
pending_user_gesture_(0.0),
document_loader_(NULL),
external_document_load_(false),
- npp_(new NPP_t),
isolate_(v8::Isolate::GetCurrent()),
is_deleted_(false),
last_input_number_(0),
@@ -620,8 +671,11 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
DCHECK(!fullscreen_container_);
- // Free all the plugin objects. This will automatically clear the back-
- // pointer from the NPObject so WebKit can't call into the plugin any more.
+ if (plugin_throttled_)
+ RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_NEVER);
+
+ // Notify all the plugin objects of deletion. This will prevent blink from
+ // calling into the plugin any more.
//
// Swap out the set so we can delete from it (the objects will try to
// unregister themselves inside the delete call).
@@ -629,8 +683,13 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
live_plugin_objects_.swap(plugin_object_copy);
for (PluginObjectSet::iterator i = plugin_object_copy.begin();
i != plugin_object_copy.end();
- ++i)
- delete *i;
+ ++i) {
+ (*i)->InstanceDeleted();
+ }
+
+ if (message_channel_)
+ message_channel_->InstanceDeleted();
+ message_channel_object_.Reset();
if (TrackedCallback::IsPending(lock_mouse_callback_))
lock_mouse_callback_->Abort();
@@ -661,6 +720,34 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
// If a method needs to access a member of the instance after the call has
// returned, then it needs to keep its own reference on the stack.
+v8::Local<v8::Object> PepperPluginInstanceImpl::GetMessageChannelObject() {
+ return v8::Local<v8::Object>::New(isolate_, message_channel_object_);
+}
+
+void PepperPluginInstanceImpl::MessageChannelDestroyed() {
+ message_channel_ = NULL;
+ message_channel_object_.Reset();
+}
+
+v8::Local<v8::Context> PepperPluginInstanceImpl::GetMainWorldContext() {
+ if (!container_)
+ return v8::Handle<v8::Context>();
+
+ if (container_->element().isNull())
+ return v8::Handle<v8::Context>();
+
+ if (container_->element().document().isNull())
+ return v8::Handle<v8::Context>();
+
+ if (!container_->element().document().frame())
+ return v8::Handle<v8::Context>();
+
+ v8::Local<v8::Context> context =
+ container_->element().document().frame()->mainWorldScriptContext();
+ DCHECK(context->GetIsolate() == isolate_);
+ return context;
+}
+
void PepperPluginInstanceImpl::Delete() {
is_deleted_ = true;
@@ -675,7 +762,8 @@ void PepperPluginInstanceImpl::Delete() {
// release our last reference to the "InstanceObject" and will probably
// destroy it. We want to do this prior to calling DidDestroy in case the
// destructor of the instance object tries to use the instance.
- message_channel_->SetPassthroughObject(NULL);
+ if (message_channel_)
+ message_channel_->SetPassthroughObject(v8::Handle<v8::Object>());
// If this is a NaCl plugin instance, shut down the NaCl plugin by calling
// its DidDestroy. Don't call DidDestroy on the untrusted plugin instance,
// since there is little that it can do at this point.
@@ -735,7 +823,7 @@ void PepperPluginInstanceImpl::InvalidateRect(const gfx::Rect& rect) {
}
cc::Layer* layer =
- texture_layer_ ? texture_layer_.get() : compositor_layer_.get();
+ texture_layer_.get() ? texture_layer_.get() : compositor_layer_.get();
if (layer) {
if (rect.IsEmpty()) {
layer->SetNeedsDisplay();
@@ -749,14 +837,14 @@ void PepperPluginInstanceImpl::ScrollRect(int dx,
int dy,
const gfx::Rect& rect) {
cc::Layer* layer =
- texture_layer_ ? texture_layer_.get() : compositor_layer_.get();
+ texture_layer_.get() ? texture_layer_.get() : compositor_layer_.get();
if (layer) {
InvalidateRect(rect);
} else if (fullscreen_container_) {
fullscreen_container_->ScrollRect(dx, dy, rect);
} else {
if (full_frame_ && !IsViewAccelerated()) {
- container_->scrollRect(dx, dy, rect);
+ container_->scrollRect(rect);
} else {
// Can't do optimized scrolling since there could be other elements on top
// of us or the view renders via the accelerated compositor which is
@@ -837,17 +925,56 @@ bool PepperPluginInstanceImpl::Initialize(
bool full_frame) {
if (!render_frame_)
return false;
- message_channel_.reset(new MessageChannel(this));
+
+ blink::WebRect bounds = container_->element().boundsInViewportSpace();
+ if (IsFlashPlugin(module_.get())) {
+ RenderThread::Get()->RecordAction(
+ base::UserMetricsAction("Flash.PluginInstanceCreated"));
+ RecordFlashSizeMetric(bounds.width, bounds.height);
+ }
+
+ PluginPowerSaverHelper* power_saver_helper =
+ render_frame_->plugin_power_saver_helper();
+ GURL content_origin = plugin_url_.GetOrigin();
+
+ bool cross_origin = false;
+ is_peripheral_content_ =
+ IsFlashPlugin(module_.get()) &&
+ power_saver_helper->ShouldThrottleContent(content_origin, bounds.width,
+ bounds.height, &cross_origin);
+
+ power_saver_enabled_ = is_peripheral_content_ &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnablePluginPowerSaver);
+
+ if (is_peripheral_content_) {
+ // To collect UMAs, register peripheral content even if we don't throttle.
+ power_saver_helper->RegisterPeripheralPlugin(
+ content_origin,
+ base::Bind(
+ &PepperPluginInstanceImpl::DisablePowerSaverByRetroactiveWhitelist,
+ weak_factory_.GetWeakPtr()));
+
+ if (power_saver_enabled_) {
+ throttler_.reset(new PepperPluginInstanceThrottler(
+ base::Bind(&PepperPluginInstanceImpl::SetPluginThrottled,
+ weak_factory_.GetWeakPtr(), true /* throttled */)));
+ }
+ } else if (cross_origin) {
+ power_saver_helper->WhitelistContentOrigin(content_origin);
+ }
+
+ message_channel_ = MessageChannel::Create(this, &message_channel_object_);
full_frame_ = full_frame;
UpdateTouchEventRequest();
container_->setWantsWheelEvents(IsAcceptingWheelEvents());
- SetGPUHistogram(
- ppapi::Preferences(render_frame_->render_view()->webkit_preferences()),
- arg_names,
- arg_values);
+ SetGPUHistogram(ppapi::Preferences(PpapiPreferencesBuilder::Build(
+ render_frame_->render_view()->webkit_preferences())),
+ arg_names,
+ arg_values);
argn_ = arg_names;
argv_ = arg_values;
@@ -860,9 +987,11 @@ bool PepperPluginInstanceImpl::Initialize(
// messages. (E.g., NaCl trusted plugin starting a child NaCl app.)
//
// A host for external plugins will call ResetAsProxied later, at which point
- // we can Start() the message_channel_.
- if (success && (!module_->renderer_ppapi_host()->IsExternalPluginHost()))
- message_channel_->Start();
+ // we can Start() the MessageChannel.
+ if (success && (!module_->renderer_ppapi_host()->IsExternalPluginHost())) {
+ if (message_channel_)
+ message_channel_->Start();
+ }
return success;
}
@@ -1090,6 +1219,25 @@ bool PepperPluginInstanceImpl::HandleInputEvent(
WebCursorInfo* cursor_info) {
TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleInputEvent");
+ if (event.type == blink::WebInputEvent::MouseDown && !has_been_clicked_ &&
+ IsFlashPlugin(module_.get())) {
+ has_been_clicked_ = true;
+ blink::WebRect bounds = container_->element().boundsInViewportSpace();
+ RecordFlashClickSizeMetric(bounds.width, bounds.height);
+ }
+
+ if (event.type == blink::WebInputEvent::MouseUp && is_peripheral_content_) {
+ is_peripheral_content_ = false;
+ power_saver_enabled_ = false;
+
+ RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_BY_CLICK);
+
+ if (plugin_throttled_) {
+ SetPluginThrottled(false /* throttled */);
+ return true;
+ }
+ }
+
if (!render_frame_)
return false;
if (WebInputEvent::isMouseEventType(event.type)) {
@@ -1165,6 +1313,8 @@ bool PepperPluginInstanceImpl::HandleInputEvent(
void PepperPluginInstanceImpl::HandleMessage(ScopedPPVar message) {
TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleMessage");
+ if (is_deleted_)
+ return;
ppapi::proxy::HostDispatcher* dispatcher =
ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
if (!dispatcher || (message.get().type == PP_VARTYPE_OBJECT)) {
@@ -1183,6 +1333,8 @@ void PepperPluginInstanceImpl::HandleMessage(ScopedPPVar message) {
bool PepperPluginInstanceImpl::HandleBlockingMessage(ScopedPPVar message,
ScopedPPVar* result) {
TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleBlockingMessage");
+ if (is_deleted_)
+ return false;
ppapi::proxy::HostDispatcher* dispatcher =
ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
if (!dispatcher || (message.get().type == PP_VARTYPE_OBJECT)) {
@@ -1206,10 +1358,12 @@ bool PepperPluginInstanceImpl::HandleBlockingMessage(ScopedPPVar message,
return was_handled;
}
-PP_Var PepperPluginInstanceImpl::GetInstanceObject() {
+PP_Var PepperPluginInstanceImpl::GetInstanceObject(v8::Isolate* isolate) {
// Keep a reference on the stack. See NOTE above.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
+ DCHECK_EQ(isolate, isolate_);
+
// If the plugin supports the private instance interface, try to retrieve its
// instance object.
if (LoadPrivateInterface())
@@ -1333,6 +1487,8 @@ void PepperPluginInstanceImpl::ViewFlushedPaint() {
void PepperPluginInstanceImpl::SetSelectedText(
const base::string16& selected_text) {
selected_text_ = selected_text;
+ gfx::Range range(0, selected_text.length());
+ render_frame_->SetSelectedText(selected_text, 0, range);
}
void PepperPluginInstanceImpl::SetLinkUnderCursor(const std::string& url) {
@@ -1345,13 +1501,24 @@ void PepperPluginInstanceImpl::SetTextInputType(ui::TextInputType type) {
}
void PepperPluginInstanceImpl::PostMessageToJavaScript(PP_Var message) {
- message_channel_->PostMessageToJavaScript(message);
+ if (message_channel_)
+ message_channel_->PostMessageToJavaScript(message);
}
int32_t PepperPluginInstanceImpl::RegisterMessageHandler(
PP_Instance instance,
void* user_data,
- const PPP_MessageHandler_0_1* handler,
+ const PPP_MessageHandler_0_2* handler,
+ PP_Resource message_loop) {
+ // Not supported in-process.
+ NOTIMPLEMENTED();
+ return PP_ERROR_FAILED;
+}
+
+int32_t PepperPluginInstanceImpl::RegisterMessageHandler_1_1_Deprecated(
+ PP_Instance instance,
+ void* user_data,
+ const PPP_MessageHandler_0_1_Deprecated* handler,
PP_Resource message_loop) {
// Not supported in-process.
NOTIMPLEMENTED();
@@ -1364,20 +1531,7 @@ void PepperPluginInstanceImpl::UnregisterMessageHandler(PP_Instance instance) {
}
base::string16 PepperPluginInstanceImpl::GetSelectedText(bool html) {
- // Keep a reference on the stack. See NOTE above.
- scoped_refptr<PepperPluginInstanceImpl> ref(this);
- if (!LoadSelectionInterface())
- return selected_text_;
-
- PP_Var rv = plugin_selection_interface_->GetSelectedText(pp_instance(),
- PP_FromBool(html));
- StringVar* string = StringVar::FromPPVar(rv);
- base::string16 selection;
- if (string)
- selection = base::UTF8ToUTF16(string->value());
- // Release the ref the plugin transfered to us.
- HostGlobals::Get()->GetVarTracker()->ReleaseVar(rv);
- return selection;
+ return selected_text_;
}
base::string16 PepperPluginInstanceImpl::GetLinkAtPosition(
@@ -1517,7 +1671,7 @@ bool PepperPluginInstanceImpl::LoadPrivateInterface() {
// If this is *not* a NaCl plugin, original_module_ will never be set; we talk
// to the "real" module.
scoped_refptr<PluginModule> module =
- original_module_ ? original_module_ : module_;
+ original_module_.get() ? original_module_ : module_;
// Only check for the interface if the plugin has private permission.
if (!module->permissions().HasPermission(ppapi::PERMISSION_PRIVATE))
return false;
@@ -1529,14 +1683,6 @@ bool PepperPluginInstanceImpl::LoadPrivateInterface() {
return !!plugin_private_interface_;
}
-bool PepperPluginInstanceImpl::LoadSelectionInterface() {
- if (!plugin_selection_interface_) {
- plugin_selection_interface_ = static_cast<const PPP_Selection_Dev*>(
- module_->GetPluginInterface(PPP_SELECTION_DEV_INTERFACE));
- }
- return !!plugin_selection_interface_;
-}
-
bool PepperPluginInstanceImpl::LoadTextInputInterface() {
if (!plugin_textinput_interface_) {
plugin_textinput_interface_ = static_cast<const PPP_TextInput_Dev*>(
@@ -1556,7 +1702,7 @@ bool PepperPluginInstanceImpl::LoadZoomInterface() {
}
void PepperPluginInstanceImpl::UpdateLayerTransform() {
- if (!bound_graphics_2d_platform_ || !texture_layer_) {
+ if (!bound_graphics_2d_platform_ || !texture_layer_.get()) {
// Currently the transform is only applied for Graphics2D.
return;
}
@@ -1642,25 +1788,35 @@ void PepperPluginInstanceImpl::SendDidChangeView() {
if (module()->is_crashed())
return;
+ // When plugin is throttled, send ViewData indicating it's in the background.
+ const ppapi::ViewData& view_data =
+ plugin_throttled_ ? empty_view_data_ : view_data_;
+
if (view_change_weak_ptr_factory_.HasWeakPtrs() ||
(sent_initial_did_change_view_ &&
- last_sent_view_data_.Equals(view_data_)))
+ last_sent_view_data_.Equals(view_data)))
return; // Nothing to update.
sent_initial_did_change_view_ = true;
- last_sent_view_data_ = view_data_;
+ last_sent_view_data_ = view_data;
ScopedPPResource resource(
ScopedPPResource::PassRef(),
- (new PPB_View_Shared(ppapi::OBJECT_IS_IMPL, pp_instance(), view_data_))
+ (new PPB_View_Shared(ppapi::OBJECT_IS_IMPL, pp_instance(), view_data))
->GetReference());
UpdateLayerTransform();
+ if (bound_graphics_2d_platform_ &&
+ (!view_data.is_page_visible ||
+ PP_ToGfxRect(view_data.clip_rect).IsEmpty())) {
+ bound_graphics_2d_platform_->ClearCache();
+ }
+
// It's possible that Delete() has been called but the renderer hasn't
// released its reference to this object yet.
if (instance_interface_) {
instance_interface_->DidChangeView(
- pp_instance(), resource, &view_data_.rect, &view_data_.clip_rect);
+ pp_instance(), resource, &view_data.rect, &view_data.clip_rect);
}
}
@@ -1731,17 +1887,16 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
bool PepperPluginInstanceImpl::PrintPage(int page_number,
blink::WebCanvas* canvas) {
-#if defined(ENABLE_FULL_PRINTING)
+#if defined(ENABLE_PRINTING)
DCHECK(plugin_print_interface_);
PP_PrintPageNumberRange_Dev page_range;
page_range.first_page_number = page_range.last_page_number = page_number;
// The canvas only has a metafile on it for print preview.
bool save_for_later =
(printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas) != NULL);
-#if defined(OS_MACOSX) || \
- (defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING))
+#if defined(OS_MACOSX)
save_for_later = save_for_later && skia::IsPreviewMetafile(*canvas);
-#endif
+#endif // defined(OS_MACOSX)
if (save_for_later) {
ranges_.push_back(page_range);
canvas_ = skia::SharePtr(canvas);
@@ -1749,7 +1904,7 @@ bool PepperPluginInstanceImpl::PrintPage(int page_number,
} else {
return PrintPageHelper(&page_range, 1, canvas);
}
-#else // defined(ENABLED_PRINTING)
+#else // ENABLE_PRINTING
return false;
#endif
}
@@ -1916,7 +2071,7 @@ bool PepperPluginInstanceImpl::IsViewAccelerated() {
bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output,
blink::WebCanvas* canvas) {
-#if defined(ENABLE_FULL_PRINTING)
+#if defined(ENABLE_PRINTING)
ppapi::thunk::EnterResourceNoLock<PPB_Buffer_API> enter(print_output, true);
if (enter.failed())
return false;
@@ -1926,94 +2081,15 @@ bool PepperPluginInstanceImpl::PrintPDFOutput(PP_Resource print_output,
NOTREACHED();
return false;
}
-#if defined(OS_WIN)
- // For Windows, we need the PDF DLL to render the output PDF to a DC.
- HMODULE pdf_module = GetModuleHandle(L"pdf.dll");
- if (!pdf_module)
- return false;
- RenderPDFPageToDCProc render_proc = reinterpret_cast<RenderPDFPageToDCProc>(
- GetProcAddress(pdf_module, "RenderPDFPageToDC"));
- if (!render_proc)
- return false;
-#endif // defined(OS_WIN)
- bool ret = false;
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
- // On Linux we just set the final bits in the native metafile
- // (NativeMetafile and PreviewMetafile must have compatible formats,
- // i.e. both PDF for this to work).
- printing::Metafile* metafile =
+ printing::PdfMetafileSkia* metafile =
printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas);
- DCHECK(metafile != NULL);
if (metafile)
- ret = metafile->InitFromData(mapper.data(), mapper.size());
-#elif defined(OS_WIN)
- printing::Metafile* metafile =
- printing::MetafileSkiaWrapper::GetMetafileFromCanvas(*canvas);
- if (metafile) {
- // We only have a metafile when doing print preview, so we just want to
- // pass the PDF off to preview.
- ret = metafile->InitFromData(mapper.data(), mapper.size());
- } else {
- // On Windows, we now need to render the PDF to the DC that backs the
- // supplied canvas.
- HDC dc = skia::BeginPlatformPaint(canvas);
- DrawEmptyRectangle(dc);
- gfx::Size size_in_pixels;
- size_in_pixels.set_width(
- printing::ConvertUnit(current_print_settings_.printable_area.size.width,
- static_cast<int>(printing::kPointsPerInch),
- current_print_settings_.dpi));
- size_in_pixels.set_height(printing::ConvertUnit(
- current_print_settings_.printable_area.size.height,
- static_cast<int>(printing::kPointsPerInch),
- current_print_settings_.dpi));
- // We need to scale down DC to fit an entire page into DC available area.
- // First, we'll try to use default scaling based on the 72dpi that is
- // used in webkit for printing.
- // If default scaling is not enough to fit the entire PDF without
- // Current metafile is based on screen DC and have current screen size.
- // Writing outside of those boundaries will result in the cut-off output.
- // On metafiles (this is the case here), scaling down will still record
- // original coordinates and we'll be able to print in full resolution.
- // Before playback we'll need to counter the scaling up that will happen
- // in the browser (printed_document_win.cc).
- double dynamic_scale = gfx::CalculatePageScale(
- dc, size_in_pixels.width(), size_in_pixels.height());
- double page_scale = static_cast<double>(printing::kPointsPerInch) /
- static_cast<double>(current_print_settings_.dpi);
-
- if (dynamic_scale < page_scale) {
- page_scale = dynamic_scale;
- printing::MetafileSkiaWrapper::SetCustomScaleOnCanvas(*canvas,
- page_scale);
- }
+ return metafile->InitFromData(mapper.data(), mapper.size());
- gfx::ScaleDC(dc, page_scale);
-
- ret = render_proc(static_cast<unsigned char*>(mapper.data()),
- mapper.size(),
- 0,
- dc,
- current_print_settings_.dpi,
- current_print_settings_.dpi,
- 0,
- 0,
- size_in_pixels.width(),
- size_in_pixels.height(),
- true,
- false,
- true,
- true,
- true);
- skia::EndPlatformPaint(canvas);
- }
-#endif // defined(OS_WIN)
-
- return ret;
-#else // defined(ENABLE_FULL_PRINTING)
+ NOTREACHED();
+#endif // ENABLE_PRINTING
return false;
-#endif
}
void PepperPluginInstanceImpl::UpdateLayer(bool device_changed) {
@@ -2031,16 +2107,15 @@ void PepperPluginInstanceImpl::UpdateLayer(bool device_changed) {
bool want_texture_layer = want_3d_layer || want_2d_layer;
bool want_compositor_layer = !!bound_compositor_;
- if (!device_changed &&
- (want_texture_layer == !!texture_layer_.get()) &&
+ if (!device_changed && (want_texture_layer == !!texture_layer_.get()) &&
(want_3d_layer == layer_is_hardware_) &&
- (want_compositor_layer == !!compositor_layer_) &&
+ (want_compositor_layer == !!compositor_layer_.get()) &&
layer_bound_to_fullscreen_ == !!fullscreen_container_) {
UpdateLayerTransform();
return;
}
- if (texture_layer_ || compositor_layer_) {
+ if (texture_layer_.get() || compositor_layer_.get()) {
if (!layer_bound_to_fullscreen_)
container_->setWebLayer(NULL);
else if (fullscreen_container_)
@@ -2071,10 +2146,10 @@ void PepperPluginInstanceImpl::UpdateLayer(bool device_changed) {
// wmode=transparent was specified.
opaque = opaque || fullscreen_container_;
texture_layer_->SetContentsOpaque(opaque);
- web_layer_.reset(new WebLayerImpl(texture_layer_));
+ web_layer_.reset(new cc_blink::WebLayerImpl(texture_layer_));
} else if (want_compositor_layer) {
compositor_layer_ = bound_compositor_->layer();
- web_layer_.reset(new WebLayerImpl(compositor_layer_));
+ web_layer_.reset(new cc_blink::WebLayerImpl(compositor_layer_));
}
if (web_layer_) {
@@ -2349,68 +2424,79 @@ PP_Var PepperPluginInstanceImpl::GetWindowObject(PP_Instance instance) {
if (!container_)
return PP_MakeUndefined();
+ V8VarConverter converter(pp_instance_, V8VarConverter::kAllowObjectVars);
+ PepperTryCatchVar try_catch(this, &converter, NULL);
WebLocalFrame* frame = container_->element().document().frame();
- if (!frame)
+ if (!frame) {
+ try_catch.SetException("No frame exists for window object.");
return PP_MakeUndefined();
+ }
- return NPObjectToPPVar(this, frame->windowObject());
+ ScopedPPVar result =
+ try_catch.FromV8(frame->mainWorldScriptContext()->Global());
+ DCHECK(!try_catch.HasException());
+ return result.Release();
}
PP_Var PepperPluginInstanceImpl::GetOwnerElementObject(PP_Instance instance) {
if (!container_)
return PP_MakeUndefined();
- return NPObjectToPPVar(this, container_->scriptableObjectForElement());
+ V8VarConverter converter(pp_instance_, V8VarConverter::kAllowObjectVars);
+ PepperTryCatchVar try_catch(this, &converter, NULL);
+ ScopedPPVar result = try_catch.FromV8(container_->v8ObjectForElement());
+ DCHECK(!try_catch.HasException());
+ return result.Release();
}
PP_Var PepperPluginInstanceImpl::ExecuteScript(PP_Instance instance,
- PP_Var script,
+ PP_Var script_var,
PP_Var* exception) {
+ if (!container_)
+ return PP_MakeUndefined();
+
// Executing the script may remove the plugin from the DOM, so we need to keep
// a reference to ourselves so that we can still process the result after the
// WebBindings::evaluate() below.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
- TryCatch try_catch(exception);
- if (try_catch.has_exception())
- return PP_MakeUndefined();
+ V8VarConverter converter(pp_instance_, V8VarConverter::kAllowObjectVars);
+ PepperTryCatchVar try_catch(this, &converter, exception);
- // Convert the script into an inconvenient NPString object.
- StringVar* script_string = StringVar::FromPPVar(script);
- if (!script_string) {
- try_catch.SetException("Script param to ExecuteScript must be a string.");
+ // Check for an exception due to the context being destroyed.
+ if (try_catch.HasException())
return PP_MakeUndefined();
- }
- NPString np_script;
- np_script.UTF8Characters = script_string->value().c_str();
- np_script.UTF8Length = script_string->value().length();
- // Get the current frame to pass to the evaluate function.
WebLocalFrame* frame = container_->element().document().frame();
if (!frame) {
try_catch.SetException("No frame to execute script in.");
return PP_MakeUndefined();
}
- NPVariant result;
- bool ok = false;
+ StringVar* script_string_var = StringVar::FromPPVar(script_var);
+ if (!script_string_var) {
+ try_catch.SetException("Script param to ExecuteScript must be a string.");
+ return PP_MakeUndefined();
+ }
+
+ std::string script_string = script_string_var->value();
+ blink::WebScriptSource script(
+ blink::WebString::fromUTF8(script_string.c_str()));
+ v8::Handle<v8::Value> result;
if (IsProcessingUserGesture()) {
blink::WebScopedUserGesture user_gesture(CurrentUserGestureToken());
- ok =
- WebBindings::evaluate(NULL, frame->windowObject(), &np_script, &result);
+ result = frame->executeScriptAndReturnValue(script);
} else {
- ok =
- WebBindings::evaluate(NULL, frame->windowObject(), &np_script, &result);
- }
- if (!ok) {
- // TryCatch doesn't catch the exceptions properly. Since this is only for
- // a trusted API, just set to a general exception message.
- try_catch.SetException("Exception caught");
- WebBindings::releaseVariantValue(&result);
- return PP_MakeUndefined();
+ result = frame->executeScriptAndReturnValue(script);
}
- PP_Var ret = NPVariantToPPVar(this, &result);
- WebBindings::releaseVariantValue(&result);
- return ret;
+ // Check for an exception due to the context being destroyed.
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+
+ ScopedPPVar var_result = try_catch.FromV8(result);
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+
+ return var_result.Release();
}
uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputSampleRate(
@@ -2449,6 +2535,13 @@ void PepperPluginInstanceImpl::PromiseResolvedWithSession(
web_session_id_var);
}
+void PepperPluginInstanceImpl::PromiseResolvedWithKeyIds(PP_Instance instance,
+ uint32 promise_id,
+ PP_Var key_ids_var) {
+ content_decryptor_delegate_->OnPromiseResolvedWithKeyIds(promise_id,
+ key_ids_var);
+}
+
void PepperPluginInstanceImpl::PromiseRejected(
PP_Instance instance,
uint32 promise_id,
@@ -2467,6 +2560,22 @@ void PepperPluginInstanceImpl::SessionMessage(PP_Instance instance,
web_session_id_var, message_var, destination_url_var);
}
+void PepperPluginInstanceImpl::SessionKeysChange(
+ PP_Instance instance,
+ PP_Var web_session_id_var,
+ PP_Bool has_additional_usable_key) {
+ content_decryptor_delegate_->OnSessionKeysChange(web_session_id_var,
+ has_additional_usable_key);
+}
+
+void PepperPluginInstanceImpl::SessionExpirationChange(
+ PP_Instance instance,
+ PP_Var web_session_id_var,
+ PP_Time new_expiry_time) {
+ content_decryptor_delegate_->OnSessionExpirationChange(web_session_id_var,
+ new_expiry_time);
+}
+
void PepperPluginInstanceImpl::SessionReady(PP_Instance instance,
PP_Var web_session_id_var) {
content_decryptor_delegate_->OnSessionReady(web_session_id_var);
@@ -2619,7 +2728,7 @@ ppapi::Resource* PepperPluginInstanceImpl::GetSingletonResource(
case ppapi::GAMEPAD_SINGLETON_ID:
return gamepad_impl_.get();
case ppapi::UMA_SINGLETON_ID: {
- if (!uma_private_impl_) {
+ if (!uma_private_impl_.get()) {
RendererPpapiHostImpl* host_impl = module_->renderer_ppapi_host();
if (host_impl->in_process_router()) {
uma_private_impl_ = new ppapi::proxy::UMAPrivateResource(
@@ -2848,7 +2957,7 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanRequest(PP_Instance instance,
if (!gurl.is_valid())
return PP_FALSE;
- return BoolToPPBool(security_origin.canRequest(gurl));
+ return PP_FromBool(security_origin.canRequest(gurl));
}
PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument(
@@ -2862,7 +2971,7 @@ PP_Bool PepperPluginInstanceImpl::DocumentCanAccessDocument(
if (!SecurityOriginForInstance(instance, &target_origin))
return PP_FALSE;
- return BoolToPPBool(our_origin.canAccess(target_origin));
+ return PP_FromBool(our_origin.canAccess(target_origin));
}
PP_Var PepperPluginInstanceImpl::GetDocumentURL(
@@ -2929,7 +3038,6 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
plugin_pdf_interface_ = NULL;
checked_for_plugin_pdf_interface_ = false;
plugin_private_interface_ = NULL;
- plugin_selection_interface_ = NULL;
plugin_textinput_interface_ = NULL;
plugin_zoom_interface_ = NULL;
@@ -2939,7 +3047,8 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
if (!instance_interface_->DidCreate(
pp_instance(), argn_.size(), argn_array.get(), argv_array.get()))
return PP_EXTERNAL_PLUGIN_ERROR_INSTANCE;
- message_channel_->Start();
+ if (message_channel_)
+ message_channel_->Start();
// Clear sent_initial_did_change_view_ and cancel any pending DidChangeView
// event. This way, SendDidChangeView will send the "current" view
@@ -2968,8 +3077,6 @@ bool PepperPluginInstanceImpl::IsValidInstanceOf(PluginModule* module) {
return module == module_.get() || module == original_module_.get();
}
-NPP PepperPluginInstanceImpl::instanceNPP() { return npp_.get(); }
-
PepperPluginInstance* PepperPluginInstance::Get(PP_Instance instance_id) {
return HostGlobals::Get()->GetInstance(instance_id);
}
@@ -3143,7 +3250,7 @@ int32_t PepperPluginInstanceImpl::Navigate(
web_request.setHasUserGesture(from_user_action);
GURL gurl(web_request.url());
- if (gurl.SchemeIs("javascript")) {
+ if (gurl.SchemeIs(url::kJavaScriptScheme)) {
// In imitation of the NPAPI implementation, only |target_frame == frame| is
// allowed for security reasons.
WebFrame* target_frame =
@@ -3176,7 +3283,8 @@ int PepperPluginInstanceImpl::MakePendingFileRefRendererHost(
}
void PepperPluginInstanceImpl::SetEmbedProperty(PP_Var key, PP_Var value) {
- message_channel_->SetReadOnlyProperty(key, value);
+ if (message_channel_)
+ message_channel_->SetReadOnlyProperty(key, value);
}
bool PepperPluginInstanceImpl::CanAccessMainFrame() const {
@@ -3312,4 +3420,24 @@ void PepperPluginInstanceImpl::DidDataFromWebURLResponse(
}
}
+void PepperPluginInstanceImpl::SetPluginThrottled(bool throttled) {
+ // Do not throttle if we've already disabled power saver.
+ if (!power_saver_enabled_ && throttled)
+ return;
+
+ plugin_throttled_ = throttled;
+ SendDidChangeView();
+}
+
+void PepperPluginInstanceImpl::DisablePowerSaverByRetroactiveWhitelist() {
+ if (!is_peripheral_content_)
+ return;
+
+ is_peripheral_content_ = false;
+ power_saver_enabled_ = false;
+ SetPluginThrottled(false);
+
+ RecordUnthrottleMethodMetric(UNTHROTTLE_METHOD_BY_WHITELIST);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
index ee66136bd4a..c056a93bc11 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -23,6 +23,7 @@
#include "content/public/renderer/pepper_plugin_instance.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/mouse_lock_dispatcher.h"
+#include "gin/handle.h"
#include "ppapi/c/dev/pp_cursor_type_dev.h"
#include "ppapi/c/dev/ppp_printing_dev.h"
#include "ppapi/c/dev/ppp_selection_dev.h"
@@ -59,6 +60,7 @@
#include "ui/events/latency_info.h"
#include "ui/gfx/rect.h"
#include "url/gurl.h"
+#include "v8/include/v8.h"
struct PP_Point;
struct _NPP;
@@ -94,10 +96,6 @@ struct PPP_Instance_Combined;
class ScopedPPVar;
}
-namespace v8 {
-class Isolate;
-}
-
namespace content {
class ContentDecryptorDelegate;
@@ -105,6 +103,7 @@ class FullscreenContainer;
class MessageChannel;
class PepperCompositorHost;
class PepperGraphics2DHost;
+class PepperPluginInstanceThrottler;
class PluginModule;
class PluginObject;
class PPB_Graphics3D_Impl;
@@ -134,7 +133,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
const GURL& plugin_url);
RenderFrameImpl* render_frame() const { return render_frame_; }
PluginModule* module() const { return module_.get(); }
- MessageChannel& message_channel() { return *message_channel_; }
blink::WebPluginContainer* container() const { return container_; }
@@ -146,6 +144,19 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
return *resource_creation_.get();
}
+ MessageChannel* message_channel() { return message_channel_; }
+ v8::Local<v8::Object> GetMessageChannelObject();
+ // Called when |message_channel_| is destroyed as it may be destroyed prior to
+ // the plugin being destroyed.
+ void MessageChannelDestroyed();
+
+ // Return the v8 context for the frame that the plugin is contained in. Care
+ // should be taken to use the correct context for plugin<->JS interactions.
+ // In cases where JS calls into the plugin, the caller's context should
+ // typically be used. When calling from the plugin into JS, this context
+ // should typically used.
+ v8::Local<v8::Context> GetMainWorldContext();
+
// Does some pre-destructor cleanup on the instance. This is necessary
// because some cleanup depends on the plugin instance still existing (like
// calling the plugin's DidDestroy function). This function is called from
@@ -189,7 +200,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool HandleDocumentLoad(const blink::WebURLResponse& response);
bool HandleInputEvent(const blink::WebInputEvent& event,
blink::WebCursorInfo* cursor_info);
- PP_Var GetInstanceObject();
+ PP_Var GetInstanceObject(v8::Isolate* isolate);
void ViewChanged(const gfx::Rect& position,
const gfx::Rect& clip,
const std::vector<gfx::Rect>& cut_outs_rects);
@@ -346,163 +357,160 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
ContentDecryptorDelegate* GetContentDecryptorDelegate();
// PluginInstance implementation
- virtual RenderView* GetRenderView() OVERRIDE;
- virtual blink::WebPluginContainer* GetContainer() OVERRIDE;
- virtual v8::Isolate* GetIsolate() const OVERRIDE;
- virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
- virtual const GURL& GetPluginURL() OVERRIDE;
- virtual base::FilePath GetModulePath() OVERRIDE;
- virtual PP_Resource CreateImage(gfx::ImageSkia* source_image,
- float scale) OVERRIDE;
- virtual PP_ExternalPluginResult SwitchToOutOfProcessProxy(
+ RenderView* GetRenderView() override;
+ blink::WebPluginContainer* GetContainer() override;
+ v8::Isolate* GetIsolate() const override;
+ ppapi::VarTracker* GetVarTracker() override;
+ const GURL& GetPluginURL() override;
+ base::FilePath GetModulePath() override;
+ PP_Resource CreateImage(gfx::ImageSkia* source_image, float scale) override;
+ PP_ExternalPluginResult SwitchToOutOfProcessProxy(
const base::FilePath& file_path,
ppapi::PpapiPermissions permissions,
const IPC::ChannelHandle& channel_handle,
base::ProcessId plugin_pid,
- int plugin_child_id) OVERRIDE;
- virtual void SetAlwaysOnTop(bool on_top) OVERRIDE;
- virtual bool IsFullPagePlugin() OVERRIDE;
- virtual bool FlashSetFullscreen(bool fullscreen, bool delay_report) OVERRIDE;
- virtual bool IsRectTopmost(const gfx::Rect& rect) OVERRIDE;
- virtual int32_t Navigate(const ppapi::URLRequestInfoData& request,
- const char* target,
- bool from_user_action) OVERRIDE;
- virtual int MakePendingFileRefRendererHost(const base::FilePath& path)
- OVERRIDE;
- virtual void SetEmbedProperty(PP_Var key, PP_Var value) OVERRIDE;
- virtual void SetSelectedText(const base::string16& selected_text) OVERRIDE;
- virtual void SetLinkUnderCursor(const std::string& url) OVERRIDE;
- virtual void SetTextInputType(ui::TextInputType type) OVERRIDE;
- virtual void PostMessageToJavaScript(PP_Var message) OVERRIDE;
+ int plugin_child_id) override;
+ void SetAlwaysOnTop(bool on_top) override;
+ bool IsFullPagePlugin() override;
+ bool FlashSetFullscreen(bool fullscreen, bool delay_report) override;
+ bool IsRectTopmost(const gfx::Rect& rect) override;
+ int32_t Navigate(const ppapi::URLRequestInfoData& request,
+ const char* target,
+ bool from_user_action) override;
+ int MakePendingFileRefRendererHost(const base::FilePath& path) override;
+ void SetEmbedProperty(PP_Var key, PP_Var value) override;
+ void SetSelectedText(const base::string16& selected_text) override;
+ void SetLinkUnderCursor(const std::string& url) override;
+ void SetTextInputType(ui::TextInputType type) override;
+ void PostMessageToJavaScript(PP_Var message) override;
// PPB_Instance_API implementation.
- virtual PP_Bool BindGraphics(PP_Instance instance,
- PP_Resource device) OVERRIDE;
- virtual PP_Bool IsFullFrame(PP_Instance instance) OVERRIDE;
- virtual const ppapi::ViewData* GetViewData(PP_Instance instance) OVERRIDE;
- virtual PP_Bool FlashIsFullscreen(PP_Instance instance) OVERRIDE;
- virtual PP_Var GetWindowObject(PP_Instance instance) OVERRIDE;
- virtual PP_Var GetOwnerElementObject(PP_Instance instance) OVERRIDE;
- virtual PP_Var ExecuteScript(PP_Instance instance,
- PP_Var script,
- PP_Var* exception) OVERRIDE;
- virtual uint32_t GetAudioHardwareOutputSampleRate(PP_Instance instance)
- OVERRIDE;
- virtual uint32_t GetAudioHardwareOutputBufferSize(PP_Instance instance)
- OVERRIDE;
- virtual PP_Var GetDefaultCharSet(PP_Instance instance) OVERRIDE;
- virtual void SetPluginToHandleFindRequests(PP_Instance) OVERRIDE;
- virtual void NumberOfFindResultsChanged(PP_Instance instance,
- int32_t total,
- PP_Bool final_result) OVERRIDE;
- virtual void SelectedFindResultChanged(PP_Instance instance,
- int32_t index) OVERRIDE;
- virtual void SetTickmarks(PP_Instance instance,
- const PP_Rect* tickmarks,
- uint32_t count) OVERRIDE;
- virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE;
- virtual PP_Bool SetFullscreen(PP_Instance instance,
- PP_Bool fullscreen) OVERRIDE;
- virtual PP_Bool GetScreenSize(PP_Instance instance, PP_Size* size) OVERRIDE;
- virtual ppapi::Resource* GetSingletonResource(PP_Instance instance,
- ppapi::SingletonResourceID id)
- OVERRIDE;
- virtual int32_t RequestInputEvents(PP_Instance instance,
- uint32_t event_classes) OVERRIDE;
- virtual int32_t RequestFilteringInputEvents(PP_Instance instance,
- uint32_t event_classes) OVERRIDE;
- virtual void ClearInputEventRequest(PP_Instance instance,
- uint32_t event_classes) OVERRIDE;
- virtual void StartTrackingLatency(PP_Instance instance) OVERRIDE;
- virtual void ZoomChanged(PP_Instance instance, double factor) OVERRIDE;
- virtual void ZoomLimitsChanged(PP_Instance instance,
- double minimum_factor,
- double maximum_factor) OVERRIDE;
- virtual void PostMessage(PP_Instance instance, PP_Var message) OVERRIDE;
- virtual int32_t RegisterMessageHandler(PP_Instance instance,
- void* user_data,
- const PPP_MessageHandler_0_1* handler,
- PP_Resource message_loop) OVERRIDE;
- virtual void UnregisterMessageHandler(PP_Instance instance) OVERRIDE;
- virtual PP_Bool SetCursor(PP_Instance instance,
- PP_MouseCursor_Type type,
- PP_Resource image,
- const PP_Point* hot_spot) OVERRIDE;
- virtual int32_t LockMouse(PP_Instance instance,
- scoped_refptr<ppapi::TrackedCallback> callback)
- OVERRIDE;
- virtual void UnlockMouse(PP_Instance instance) OVERRIDE;
- virtual void SetTextInputType(PP_Instance instance,
- PP_TextInput_Type type) OVERRIDE;
- virtual void UpdateCaretPosition(PP_Instance instance,
- const PP_Rect& caret,
- const PP_Rect& bounding_box) OVERRIDE;
- virtual void CancelCompositionText(PP_Instance instance) OVERRIDE;
- virtual void SelectionChanged(PP_Instance instance) OVERRIDE;
- virtual void UpdateSurroundingText(PP_Instance instance,
- const char* text,
- uint32_t caret,
- uint32_t anchor) OVERRIDE;
- virtual PP_Var ResolveRelativeToDocument(PP_Instance instance,
- PP_Var relative,
- PP_URLComponents_Dev* components)
- OVERRIDE;
- virtual PP_Bool DocumentCanRequest(PP_Instance instance, PP_Var url) OVERRIDE;
- virtual PP_Bool DocumentCanAccessDocument(PP_Instance instance,
- PP_Instance target) OVERRIDE;
- virtual PP_Var GetDocumentURL(PP_Instance instance,
- PP_URLComponents_Dev* components) OVERRIDE;
- virtual PP_Var GetPluginInstanceURL(PP_Instance instance,
- PP_URLComponents_Dev* components)
- OVERRIDE;
- virtual PP_Var GetPluginReferrerURL(PP_Instance instance,
- PP_URLComponents_Dev* components)
- OVERRIDE;
+ PP_Bool BindGraphics(PP_Instance instance, PP_Resource device) override;
+ PP_Bool IsFullFrame(PP_Instance instance) override;
+ const ppapi::ViewData* GetViewData(PP_Instance instance) override;
+ PP_Bool FlashIsFullscreen(PP_Instance instance) override;
+ PP_Var GetWindowObject(PP_Instance instance) override;
+ PP_Var GetOwnerElementObject(PP_Instance instance) override;
+ PP_Var ExecuteScript(PP_Instance instance,
+ PP_Var script,
+ PP_Var* exception) override;
+ uint32_t GetAudioHardwareOutputSampleRate(PP_Instance instance) override;
+ uint32_t GetAudioHardwareOutputBufferSize(PP_Instance instance) override;
+ PP_Var GetDefaultCharSet(PP_Instance instance) override;
+ void SetPluginToHandleFindRequests(PP_Instance) override;
+ void NumberOfFindResultsChanged(PP_Instance instance,
+ int32_t total,
+ PP_Bool final_result) override;
+ void SelectedFindResultChanged(PP_Instance instance, int32_t index) override;
+ void SetTickmarks(PP_Instance instance,
+ const PP_Rect* tickmarks,
+ uint32_t count) override;
+ PP_Bool IsFullscreen(PP_Instance instance) override;
+ PP_Bool SetFullscreen(PP_Instance instance, PP_Bool fullscreen) override;
+ PP_Bool GetScreenSize(PP_Instance instance, PP_Size* size) override;
+ ppapi::Resource* GetSingletonResource(PP_Instance instance,
+ ppapi::SingletonResourceID id) override;
+ int32_t RequestInputEvents(PP_Instance instance,
+ uint32_t event_classes) override;
+ int32_t RequestFilteringInputEvents(PP_Instance instance,
+ uint32_t event_classes) override;
+ void ClearInputEventRequest(PP_Instance instance,
+ uint32_t event_classes) override;
+ void StartTrackingLatency(PP_Instance instance) override;
+ void ZoomChanged(PP_Instance instance, double factor) override;
+ void ZoomLimitsChanged(PP_Instance instance,
+ double minimum_factor,
+ double maximum_factor) override;
+ void PostMessage(PP_Instance instance, PP_Var message) override;
+ int32_t RegisterMessageHandler(PP_Instance instance,
+ void* user_data,
+ const PPP_MessageHandler_0_2* handler,
+ PP_Resource message_loop) override;
+ int32_t RegisterMessageHandler_1_1_Deprecated(
+ PP_Instance instance,
+ void* user_data,
+ const PPP_MessageHandler_0_1_Deprecated* handler,
+ PP_Resource message_loop) override;
+ void UnregisterMessageHandler(PP_Instance instance) override;
+ PP_Bool SetCursor(PP_Instance instance,
+ PP_MouseCursor_Type type,
+ PP_Resource image,
+ const PP_Point* hot_spot) override;
+ int32_t LockMouse(PP_Instance instance,
+ scoped_refptr<ppapi::TrackedCallback> callback) override;
+ void UnlockMouse(PP_Instance instance) override;
+ void SetTextInputType(PP_Instance instance, PP_TextInput_Type type) override;
+ void UpdateCaretPosition(PP_Instance instance,
+ const PP_Rect& caret,
+ const PP_Rect& bounding_box) override;
+ void CancelCompositionText(PP_Instance instance) override;
+ void SelectionChanged(PP_Instance instance) override;
+ void UpdateSurroundingText(PP_Instance instance,
+ const char* text,
+ uint32_t caret,
+ uint32_t anchor) override;
+ PP_Var ResolveRelativeToDocument(PP_Instance instance,
+ PP_Var relative,
+ PP_URLComponents_Dev* components) override;
+ PP_Bool DocumentCanRequest(PP_Instance instance, PP_Var url) override;
+ PP_Bool DocumentCanAccessDocument(PP_Instance instance,
+ PP_Instance target) override;
+ PP_Var GetDocumentURL(PP_Instance instance,
+ PP_URLComponents_Dev* components) override;
+ PP_Var GetPluginInstanceURL(PP_Instance instance,
+ PP_URLComponents_Dev* components) override;
+ PP_Var GetPluginReferrerURL(PP_Instance instance,
+ PP_URLComponents_Dev* components) override;
// PPB_ContentDecryptor_Private implementation.
- virtual void PromiseResolved(PP_Instance instance,
- uint32 promise_id) OVERRIDE;
- virtual void PromiseResolvedWithSession(PP_Instance instance,
- uint32 promise_id,
- PP_Var web_session_id_var) OVERRIDE;
- virtual void PromiseRejected(PP_Instance instance,
- uint32 promise_id,
- PP_CdmExceptionCode exception_code,
- uint32 system_code,
- PP_Var error_description_var) OVERRIDE;
- virtual void SessionMessage(PP_Instance instance,
- PP_Var web_session_id_var,
- PP_Var message_var,
- PP_Var destination_url_var) OVERRIDE;
- virtual void SessionReady(PP_Instance instance,
- PP_Var web_session_id_var) OVERRIDE;
- virtual void SessionClosed(PP_Instance instance,
- PP_Var web_session_id_var) OVERRIDE;
- virtual void SessionError(PP_Instance instance,
- PP_Var web_session_id_var,
- PP_CdmExceptionCode exception_code,
- uint32 system_code,
- PP_Var error_description_var) OVERRIDE;
- virtual void DeliverBlock(PP_Instance instance,
- PP_Resource decrypted_block,
- const PP_DecryptedBlockInfo* block_info) OVERRIDE;
- virtual void DecoderInitializeDone(PP_Instance instance,
- PP_DecryptorStreamType decoder_type,
- uint32_t request_id,
- PP_Bool success) OVERRIDE;
- virtual void DecoderDeinitializeDone(PP_Instance instance,
- PP_DecryptorStreamType decoder_type,
- uint32_t request_id) OVERRIDE;
- virtual void DecoderResetDone(PP_Instance instance,
- PP_DecryptorStreamType decoder_type,
- uint32_t request_id) OVERRIDE;
- virtual void DeliverFrame(PP_Instance instance,
- PP_Resource decrypted_frame,
- const PP_DecryptedFrameInfo* frame_info) OVERRIDE;
- virtual void DeliverSamples(PP_Instance instance,
- PP_Resource audio_frames,
- const PP_DecryptedSampleInfo* sample_info)
- OVERRIDE;
+ void PromiseResolved(PP_Instance instance, uint32 promise_id) override;
+ void PromiseResolvedWithSession(PP_Instance instance,
+ uint32 promise_id,
+ PP_Var web_session_id_var) override;
+ void PromiseResolvedWithKeyIds(PP_Instance instance,
+ uint32 promise_id,
+ PP_Var key_ids_var) override;
+ void PromiseRejected(PP_Instance instance,
+ uint32 promise_id,
+ PP_CdmExceptionCode exception_code,
+ uint32 system_code,
+ PP_Var error_description_var) override;
+ void SessionMessage(PP_Instance instance,
+ PP_Var web_session_id_var,
+ PP_Var message_var,
+ PP_Var destination_url_var) override;
+ void SessionKeysChange(PP_Instance instance,
+ PP_Var web_session_id_var,
+ PP_Bool has_additional_usable_key) override;
+ void SessionExpirationChange(PP_Instance instance,
+ PP_Var web_session_id_var,
+ PP_Time new_expiry_time) override;
+ void SessionReady(PP_Instance instance, PP_Var web_session_id_var) override;
+ void SessionClosed(PP_Instance instance, PP_Var web_session_id_var) override;
+ void SessionError(PP_Instance instance,
+ PP_Var web_session_id_var,
+ PP_CdmExceptionCode exception_code,
+ uint32 system_code,
+ PP_Var error_description_var) override;
+ void DeliverBlock(PP_Instance instance,
+ PP_Resource decrypted_block,
+ const PP_DecryptedBlockInfo* block_info) override;
+ void DecoderInitializeDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id,
+ PP_Bool success) override;
+ void DecoderDeinitializeDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) override;
+ void DecoderResetDone(PP_Instance instance,
+ PP_DecryptorStreamType decoder_type,
+ uint32_t request_id) override;
+ void DeliverFrame(PP_Instance instance,
+ PP_Resource decrypted_frame,
+ const PP_DecryptedFrameInfo* frame_info) override;
+ void DeliverSamples(PP_Instance instance,
+ PP_Resource audio_frames,
+ const PP_DecryptedSampleInfo* sample_info) override;
// Reset this instance as proxied. Assigns the instance a new module, resets
// cached interfaces to point to the out-of-process proxy and re-sends
@@ -518,27 +526,24 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// the given module.
bool IsValidInstanceOf(PluginModule* module);
- // Returns the plugin NPP identifier that this plugin will use to identify
- // itself when making NPObject scripting calls to WebBindings.
- struct _NPP* instanceNPP();
-
// cc::TextureLayerClient implementation.
- virtual bool PrepareTextureMailbox(
+ bool PrepareTextureMailbox(
cc::TextureMailbox* mailbox,
scoped_ptr<cc::SingleReleaseCallback>* release_callback,
- bool use_shared_memory) OVERRIDE;
+ bool use_shared_memory) override;
// RenderFrameObserver
- virtual void OnDestruct() OVERRIDE;
+ void OnDestruct() override;
void AddLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
private:
friend class base::RefCounted<PepperPluginInstanceImpl>;
+ friend class PpapiPluginInstanceTest;
friend class PpapiUnittest;
// Delete should be called by the WebPlugin before this destructor.
- virtual ~PepperPluginInstanceImpl();
+ ~PepperPluginInstanceImpl() override;
// Class to record document load notifications and play them back once the
// real document loader becomes available. Used only by external instances.
@@ -573,12 +578,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
public:
GamepadImpl();
// Resource implementation.
- virtual ppapi::thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() OVERRIDE;
- virtual void Sample(PP_Instance instance,
- PP_GamepadsSampleData* data) OVERRIDE;
+ ppapi::thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() override;
+ void Sample(PP_Instance instance, PP_GamepadsSampleData* data) override;
private:
- virtual ~GamepadImpl();
+ ~GamepadImpl() override;
};
// See the static Create functions above for creating PepperPluginInstanceImpl
@@ -597,7 +601,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
bool LoadPdfInterface();
bool LoadPrintInterface();
bool LoadPrivateInterface();
- bool LoadSelectionInterface();
bool LoadTextInputInterface();
bool LoadZoomInterface();
@@ -684,6 +687,9 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
int pending_host_id,
const ppapi::URLResponseInfoData& data);
+ void SetPluginThrottled(bool throttled);
+ void DisablePowerSaverByRetroactiveWhitelist();
+
RenderFrameImpl* render_frame_;
base::Closure instance_deleted_callback_;
scoped_refptr<PluginModule> module_;
@@ -707,6 +713,27 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// Plugin URL.
GURL plugin_url_;
+ // Set to true first time plugin is clicked. Used to collect metrics.
+ bool has_been_clicked_;
+
+ // Indicates whether this plugin may be throttled to reduce power consumption.
+ // |power_saver_enabled_| implies |is_peripheral_content_|.
+ bool power_saver_enabled_;
+
+ // Indicates whether this plugin was found to be peripheral content.
+ // This is separately tracked from |power_saver_enabled_| to collect UMAs.
+ // Always true if |power_saver_enabled_| is true.
+ bool is_peripheral_content_;
+
+ // Indicates if the plugin is currently throttled.
+ bool plugin_throttled_;
+
+ // Fake view data used by the Power Saver feature to throttle plugins.
+ const ppapi::ViewData empty_view_data_;
+
+ // Responsible for turning on throttling if Power Saver is on.
+ scoped_ptr<PepperPluginInstanceThrottler> throttler_;
+
// Indicates whether this is a full frame instance, which means it represents
// an entire document rather than an embed tag.
bool full_frame_;
@@ -747,7 +774,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
const PPP_MouseLock* plugin_mouse_lock_interface_;
const PPP_Pdf* plugin_pdf_interface_;
const PPP_Instance_Private* plugin_private_interface_;
- const PPP_Selection_Dev* plugin_selection_interface_;
const PPP_TextInput_Dev* plugin_textinput_interface_;
const PPP_Zoom_Dev* plugin_zoom_interface_;
@@ -830,7 +856,11 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// The MessageChannel used to implement bidirectional postMessage for the
// instance.
- scoped_ptr<MessageChannel> message_channel_;
+ v8::Persistent<v8::Object> message_channel_object_;
+
+ // A pointer to the MessageChannel underlying |message_channel_object_|. It is
+ // only valid as long as |message_channel_object_| is alive.
+ MessageChannel* message_channel_;
// Bitmap for crashed plugin. Lazily initialized, non-owning pointer.
SkBitmap* sad_plugin_;
@@ -880,10 +910,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// The link currently under the cursor.
base::string16 link_under_cursor_;
- // Dummy NPP value used when calling in to WebBindings, to allow the bindings
- // to correctly track NPObjects belonging to this plugin instance.
- scoped_ptr<struct _NPP> npp_;
-
// We store the isolate at construction so that we can be sure to use the
// Isolate in which this Instance was created when interacting with v8.
v8::Isolate* isolate_;
@@ -907,7 +933,6 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
base::WeakPtrFactory<PepperPluginInstanceImpl> view_change_weak_ptr_factory_;
base::WeakPtrFactory<PepperPluginInstanceImpl> weak_factory_;
- friend class PpapiPluginInstanceTest;
DISALLOW_COPY_AND_ASSIGN(PepperPluginInstanceImpl);
};
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_throttler.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_throttler.cc
new file mode 100644
index 00000000000..f1d02b9e068
--- /dev/null
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_throttler.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 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 "content/renderer/pepper/pepper_plugin_instance_throttler.h"
+
+#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
+
+namespace content {
+
+namespace {
+
+// When we give up waiting for a suitable preview frame, and simply suspend
+// the plugin where it's at. In milliseconds.
+const int kThrottleTimeout = 5000;
+}
+
+PepperPluginInstanceThrottler::PepperPluginInstanceThrottler(
+ const base::Closure& throttle_closure) {
+ DCHECK(!throttle_closure.is_null());
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, throttle_closure,
+ base::TimeDelta::FromMilliseconds(kThrottleTimeout));
+}
+
+PepperPluginInstanceThrottler::~PepperPluginInstanceThrottler() {
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_throttler.h b/chromium/content/renderer/pepper/pepper_plugin_instance_throttler.h
new file mode 100644
index 00000000000..15a5c10af3c
--- /dev/null
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_throttler.h
@@ -0,0 +1,29 @@
+// Copyright 2014 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 CONTENT_RENDERER_PEPPER_PEPPER_PLUGIN_INSTANCE_THROTTLER_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_PLUGIN_INSTANCE_THROTTLER_H_
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+
+namespace content {
+
+// Throttles Pepper Plugin instances in Power Saver mode. Currently just a
+// stub implementation that engages throttling after a fixed timeout.
+// In the future, will examine plugin frames to find a suitable preview
+// image before engaging throttling.
+class PepperPluginInstanceThrottler {
+ public:
+ // |throttle_closure| is called to engage throttling.
+ explicit PepperPluginInstanceThrottler(const base::Closure& throttle_closure);
+
+ virtual ~PepperPluginInstanceThrottler();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PepperPluginInstanceThrottler);
+};
+}
+
+#endif // CONTENT_RENDERER_PEPPER_PEPPER_PLUGIN_INSTANCE_THROTTLER_H_
diff --git a/chromium/content/renderer/pepper/pepper_plugin_registry.cc b/chromium/content/renderer/pepper/pepper_plugin_registry.cc
index 11ec935c4e9..38a4aa3db76 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_registry.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_registry.cc
@@ -117,6 +117,7 @@ void PepperPluginRegistry::Initialize() {
scoped_refptr<PluginModule> module =
new PluginModule(current.name,
+ current.version,
current.path,
ppapi::PpapiPermissions(current.permissions));
AddLiveModule(current.path, module.get());
diff --git a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h
index f4d58ebc006..e6b9cd51ad6 100644
--- a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h
+++ b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h
@@ -13,15 +13,15 @@ namespace content {
class PepperProxyChannelDelegateImpl
: public ppapi::proxy::ProxyChannel::Delegate {
public:
- virtual ~PepperProxyChannelDelegateImpl();
+ ~PepperProxyChannelDelegateImpl() override;
// ProxyChannel::Delegate implementation.
- virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE;
- virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE;
- virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ base::MessageLoopProxy* GetIPCMessageLoop() override;
+ base::WaitableEvent* GetShutdownEvent() override;
+ IPC::PlatformFileForTransit ShareHandleWithRemote(
base::PlatformFile handle,
base::ProcessId remote_pid,
- bool should_close_source) OVERRIDE;
+ bool should_close_source) override;
};
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font.h b/chromium/content/renderer/pepper/pepper_truetype_font.h
deleted file mode 100644
index 8eb6bd7adbc..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_RENDERER_PEPPER_PEPPER_TRUETYPE_FONT_H_
-#define CONTENT_RENDERER_PEPPER_PEPPER_TRUETYPE_FONT_H_
-
-#include <string>
-#include <vector>
-
-#include "ppapi/proxy/serialized_structs.h"
-
-namespace content {
-
-class PepperTrueTypeFont {
- public:
- // Creates a font matching the given descriptor. The exact font that is
- // returned will depend on the host platform's font matching and fallback
- // algorithm.
- static PepperTrueTypeFont* Create(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
- virtual ~PepperTrueTypeFont() {}
-
- // Returns true if the font was successfully created, false otherwise.
- virtual bool IsValid() = 0;
-
- // Returns a description of the actual font. Use this to see the actual
- // characteristics of the font after running the host platform's font matching
- // and fallback algorithm. Returns PP_OK on success, a Pepper error code on
- // failure. 'desc' is written only on success.
- virtual int32_t Describe(ppapi::proxy::SerializedTrueTypeFontDesc* desc) = 0;
-
- // Retrieves an array of TrueType table tags contained in this font. Returns
- // the number of tags on success, a Pepper error code on failure. 'tags' are
- // written only on success.
- virtual int32_t GetTableTags(std::vector<uint32_t>* tags) = 0;
-
- // Gets a TrueType font table corresponding to the given tag. The 'offset' and
- // 'max_data_length' parameters determine what part of the table is returned.
- // Returns the data size in bytes on success, a Pepper error code on failure.
- // 'data' is written only on success.
- virtual int32_t GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_PEPPER_TRUETYPE_FONT_H_
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_android.cc b/chromium/content/renderer/pepper/pepper_truetype_font_android.cc
deleted file mode 100644
index d65a1f92c18..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font_android.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2013 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/logging.h"
-#include "content/renderer/pepper/pepper_truetype_font.h"
-
-namespace content {
-
-// static
-PepperTrueTypeFont* PepperTrueTypeFont::Create(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
- NOTIMPLEMENTED(); // Font API isn't implemented on Android.
- return 0;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_host.cc b/chromium/content/renderer/pepper/pepper_truetype_font_host.cc
deleted file mode 100644
index fc993935443..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font_host.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2013 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 "content/renderer/pepper/pepper_truetype_font_host.h"
-
-#include "base/bind.h"
-#include "content/public/renderer/renderer_ppapi_host.h"
-#include "content/renderer/pepper/pepper_truetype_font.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/host/dispatch_host_message.h"
-#include "ppapi/host/host_message_context.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/proxy/ppapi_messages.h"
-
-using ppapi::host::HostMessageContext;
-using ppapi::host::ReplyMessageContext;
-
-namespace content {
-
-PepperTrueTypeFontHost::PepperTrueTypeFontHost(
- RendererPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource,
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc)
- : ResourceHost(host->GetPpapiHost(), instance, resource),
- renderer_ppapi_host_(host),
- font_(PepperTrueTypeFont::Create(desc)),
- weak_factory_(this) {}
-
-PepperTrueTypeFontHost::~PepperTrueTypeFontHost() {}
-
-int32_t PepperTrueTypeFontHost::OnResourceMessageReceived(
- const IPC::Message& msg,
- HostMessageContext* context) {
- if (!host()->permissions().HasPermission(ppapi::PERMISSION_DEV))
- return PP_ERROR_FAILED;
-
- PPAPI_BEGIN_MESSAGE_MAP(PepperTrueTypeFontHost, msg)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TrueTypeFont_Describe,
- OnHostMsgDescribe)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TrueTypeFont_GetTableTags,
- OnHostMsgGetTableTags)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TrueTypeFont_GetTable,
- OnHostMsgGetTable)
- PPAPI_END_MESSAGE_MAP()
- return PP_ERROR_FAILED;
-}
-
-int32_t PepperTrueTypeFontHost::OnHostMsgDescribe(HostMessageContext* context) {
- if (!font_->IsValid())
- return PP_ERROR_FAILED;
-
- ppapi::proxy::SerializedTrueTypeFontDesc desc;
- ReplyMessageContext reply_context = context->MakeReplyMessageContext();
- reply_context.params.set_result(font_->Describe(&desc));
- host()->SendReply(reply_context,
- PpapiPluginMsg_TrueTypeFont_DescribeReply(desc));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperTrueTypeFontHost::OnHostMsgGetTableTags(
- HostMessageContext* context) {
- if (!font_->IsValid())
- return PP_ERROR_FAILED;
-
- std::vector<uint32_t> tags;
- ReplyMessageContext reply_context = context->MakeReplyMessageContext();
- reply_context.params.set_result(font_->GetTableTags(&tags));
- host()->SendReply(reply_context,
- PpapiPluginMsg_TrueTypeFont_GetTableTagsReply(tags));
- return PP_OK_COMPLETIONPENDING;
-}
-
-int32_t PepperTrueTypeFontHost::OnHostMsgGetTable(HostMessageContext* context,
- uint32_t table,
- int32_t offset,
- int32_t max_data_length) {
- if (!font_->IsValid())
- return PP_ERROR_FAILED;
- if (offset < 0 || max_data_length < 0)
- return PP_ERROR_BADARGUMENT;
-
- std::string data;
- ReplyMessageContext reply_context = context->MakeReplyMessageContext();
- reply_context.params.set_result(
- font_->GetTable(table, offset, max_data_length, &data));
- host()->SendReply(reply_context,
- PpapiPluginMsg_TrueTypeFont_GetTableReply(data));
- return PP_OK_COMPLETIONPENDING;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_host.h b/chromium/content/renderer/pepper/pepper_truetype_font_host.h
deleted file mode 100644
index 27ff397222b..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font_host.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2013 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 CONTENT_RENDERER_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
-#define CONTENT_RENDERER_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "content/renderer/pepper/pepper_truetype_font.h"
-#include "ppapi/host/resource_host.h"
-
-namespace content {
-
-class RendererPpapiHost;
-
-class CONTENT_EXPORT PepperTrueTypeFontHost : public ppapi::host::ResourceHost {
- public:
- PepperTrueTypeFontHost(RendererPpapiHost* host,
- PP_Instance instance,
- PP_Resource resource,
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
-
- virtual ~PepperTrueTypeFontHost();
-
- virtual int32_t OnResourceMessageReceived(
- const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
-
- private:
- int32_t OnHostMsgDescribe(ppapi::host::HostMessageContext* context);
- int32_t OnHostMsgGetTableTags(ppapi::host::HostMessageContext* context);
- int32_t OnHostMsgGetTable(ppapi::host::HostMessageContext* context,
- uint32_t table,
- int32_t offset,
- int32_t max_data_length);
-
- RendererPpapiHost* renderer_ppapi_host_;
- scoped_ptr<PepperTrueTypeFont> font_;
-
- base::WeakPtrFactory<PepperTrueTypeFontHost> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_PEPPER_PEPPER_TRUETYPE_FONT_HOST_H_
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_linux.cc b/chromium/content/renderer/pepper/pepper_truetype_font_linux.cc
deleted file mode 100644
index c54a5148a1a..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font_linux.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2013 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/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/sys_byteorder.h"
-#include "content/public/common/child_process_sandbox_support_linux.h"
-#include "content/renderer/pepper/pepper_truetype_font.h"
-#include "ppapi/c/dev/ppb_truetype_font_dev.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
-
-namespace content {
-
-namespace {
-
-class PepperTrueTypeFontLinux : public PepperTrueTypeFont {
- public:
- explicit PepperTrueTypeFontLinux(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
- virtual ~PepperTrueTypeFontLinux() OVERRIDE;
-
- // PepperTrueTypeFont overrides.
- virtual bool IsValid() OVERRIDE;
- virtual int32_t Describe(ppapi::proxy::SerializedTrueTypeFontDesc* desc)
- OVERRIDE;
- virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
- virtual int32_t GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) OVERRIDE;
-
- private:
- // Save creation parameters here and use these to implement Describe.
- // TODO(bbudge) Modify content API to return results of font matching and
- // fallback.
- ppapi::proxy::SerializedTrueTypeFontDesc desc_;
- int fd_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontLinux);
-};
-
-PepperTrueTypeFontLinux::PepperTrueTypeFontLinux(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc)
- : desc_(desc) {
- // If no face is provided, convert family to the platform defaults. These
- // names should be mapped by FontConfig to an appropriate default font.
- if (desc_.family.empty()) {
- switch (desc_.generic_family) {
- case PP_TRUETYPEFONTFAMILY_SERIF:
- desc_.family = "serif";
- break;
- case PP_TRUETYPEFONTFAMILY_SANSSERIF:
- desc_.family = "sans-serif";
- break;
- case PP_TRUETYPEFONTFAMILY_CURSIVE:
- desc_.family = "cursive";
- break;
- case PP_TRUETYPEFONTFAMILY_FANTASY:
- desc_.family = "fantasy";
- break;
- case PP_TRUETYPEFONTFAMILY_MONOSPACE:
- desc_.family = "monospace";
- break;
- }
- }
-
- fd_ = MatchFontWithFallback(desc_.family.c_str(),
- desc_.weight >= PP_TRUETYPEFONTWEIGHT_BOLD,
- desc_.style & PP_TRUETYPEFONTSTYLE_ITALIC,
- desc_.charset,
- PP_BROWSERFONT_TRUSTED_FAMILY_DEFAULT);
-}
-
-PepperTrueTypeFontLinux::~PepperTrueTypeFontLinux() {}
-
-bool PepperTrueTypeFontLinux::IsValid() { return fd_ != -1; }
-
-int32_t PepperTrueTypeFontLinux::Describe(
- ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
- *desc = desc_;
- return PP_OK;
-}
-
-int32_t PepperTrueTypeFontLinux::GetTableTags(std::vector<uint32_t>* tags) {
- // Get the 2 byte numTables field at an offset of 4 in the font.
- uint8_t num_tables_buf[2];
- size_t output_length = sizeof(num_tables_buf);
- if (!GetFontTable(fd_,
- 0 /* tag */,
- 4 /* offset */,
- reinterpret_cast<uint8_t*>(&num_tables_buf),
- &output_length))
- return PP_ERROR_FAILED;
- DCHECK(output_length == sizeof(num_tables_buf));
- // Font data is stored in big-endian order.
- uint16_t num_tables = (num_tables_buf[0] << 8) | num_tables_buf[1];
-
- // The font has a header, followed by n table entries in its directory.
- static const size_t kFontHeaderSize = 12;
- static const size_t kTableEntrySize = 16;
- output_length = num_tables * kTableEntrySize;
- scoped_ptr<uint8_t[]> table_entries(new uint8_t[output_length]);
- // Get the table directory entries, which follow the font header.
- if (!GetFontTable(fd_,
- 0 /* tag */,
- kFontHeaderSize /* offset */,
- table_entries.get(),
- &output_length))
- return PP_ERROR_FAILED;
- DCHECK(output_length == num_tables * kTableEntrySize);
-
- tags->resize(num_tables);
- for (uint16_t i = 0; i < num_tables; i++) {
- uint8_t* entry = table_entries.get() + i * kTableEntrySize;
- uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
- static_cast<uint32_t>(entry[1]) << 16 |
- static_cast<uint32_t>(entry[2]) << 8 |
- static_cast<uint32_t>(entry[3]);
- (*tags)[i] = tag;
- }
-
- return num_tables;
-}
-
-int32_t PepperTrueTypeFontLinux::GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) {
- // Get the size of the font data first.
- size_t table_size = 0;
- // Tags are byte swapped on Linux.
- table_tag = base::ByteSwap(table_tag);
- if (!GetFontTable(fd_, table_tag, offset, NULL, &table_size))
- return PP_ERROR_FAILED;
- // Only retrieve as much as the caller requested.
- table_size = std::min(table_size, static_cast<size_t>(max_data_length));
- data->resize(table_size);
- if (!GetFontTable(fd_,
- table_tag,
- offset,
- reinterpret_cast<uint8_t*>(&(*data)[0]),
- &table_size))
- return PP_ERROR_FAILED;
-
- return base::checked_cast<int32_t>(table_size);
-}
-
-} // namespace
-
-// static
-PepperTrueTypeFont* PepperTrueTypeFont::Create(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
- return new PepperTrueTypeFontLinux(desc);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_mac.mm b/chromium/content/renderer/pepper/pepper_truetype_font_mac.mm
deleted file mode 100644
index 19e74749506..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font_mac.mm
+++ /dev/null
@@ -1,408 +0,0 @@
-// Copyright (c) 2013 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 "content/renderer/pepper/pepper_truetype_font.h"
-
-#import <ApplicationServices/ApplicationServices.h>
-
-#include <stdio.h>
-
-#include "base/compiler_specific.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/sys_byteorder.h"
-#include "ppapi/c/dev/ppb_truetype_font_dev.h"
-#include "ppapi/c/pp_errors.h"
-
-namespace content {
-
-namespace {
-
-static bool FindFloat(CFDictionaryRef dict, CFStringRef name, float* value) {
- CFNumberRef num;
- return
- CFDictionaryGetValueIfPresent(dict, name,
- reinterpret_cast<const void**>(&num)) &&
- CFNumberIsFloatType(num) &&
- CFNumberGetValue(num, kCFNumberFloatType, value);
-}
-
-float GetMacWeight(PP_TrueTypeFontWeight_Dev weight) {
- // Map values from NORMAL (400) to HEAVY (900) to the range [0 .. 1], and
- // values below NORMAL to the range [-0.6 .. 0]. NORMAL should map to 0.
- float normal = PP_TRUETYPEFONTWEIGHT_NORMAL;
- float heavy = PP_TRUETYPEFONTWEIGHT_HEAVY;
- return (weight - normal) / (heavy - normal);
-}
-
-PP_TrueTypeFontWeight_Dev GetPepperWeight(float weight) {
- // Perform the inverse mapping of GetMacWeight.
- return static_cast<PP_TrueTypeFontWeight_Dev>(
- weight * (PP_TRUETYPEFONTWEIGHT_HEAVY - PP_TRUETYPEFONTWEIGHT_NORMAL) +
- PP_TRUETYPEFONTWEIGHT_NORMAL);
-}
-
-float GetMacWidth(PP_TrueTypeFontWidth_Dev width) {
- // Map values from NORMAL (4) to ULTRA_EXPANDED (8) to the range [0 .. 1],
- // and values below NORMAL to the range [-1 .. 0]. Normal should map to 0.
- float normal = PP_TRUETYPEFONTWIDTH_NORMAL;
- float ultra_expanded = PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED;
- return (width - normal) / (ultra_expanded - normal);
-}
-
-PP_TrueTypeFontWidth_Dev GetPepperWidth(float width) {
- // Perform the inverse mapping of GetMacWeight.
- return static_cast<PP_TrueTypeFontWidth_Dev>(
- width *
- (PP_TRUETYPEFONTWIDTH_ULTRAEXPANDED - PP_TRUETYPEFONTWIDTH_NORMAL) +
- PP_TRUETYPEFONTWIDTH_NORMAL);
-}
-
-#define MAKE_TABLE_TAG(a, b, c, d) ((a) << 24) + ((b) << 16) + ((c) << 8) + (d)
-
-// TrueType font header and table entry structs. See
-// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
-struct FontHeader {
- int32_t font_type;
- uint16_t num_tables;
- uint16_t search_range;
- uint16_t entry_selector;
- uint16_t range_shift;
-};
-static_assert(sizeof(FontHeader) == 12, "FontHeader wrong size");
-
-struct FontDirectoryEntry {
- uint32_t tag;
- uint32_t checksum;
- uint32_t offset;
- uint32_t logical_length;
-};
-static_assert(sizeof(FontDirectoryEntry) == 16,
- "FontDirectoryEntry wrong size");
-
-uint32_t CalculateChecksum(char* table, int32_t table_length) {
- uint32_t sum = 0;
- uint32_t* current = reinterpret_cast<uint32_t*>(table);
- uint32_t length = (table_length + 3) / 4;
- // Raw font data is big-endian.
- while (length-- > 0)
- sum += base::NetToHost32(*current++);
- return sum;
-}
-
-class PepperTrueTypeFontMac : public PepperTrueTypeFont {
- public:
- explicit PepperTrueTypeFontMac(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
- virtual ~PepperTrueTypeFontMac() OVERRIDE;
-
- // PepperTrueTypeFont overrides.
- virtual bool IsValid() OVERRIDE;
- virtual int32_t Describe(
- ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE;
- virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
- virtual int32_t GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) OVERRIDE;
- private:
- virtual int32_t GetEntireFont(int32_t offset,
- int32_t max_data_length,
- std::string* data);
-
- base::ScopedCFTypeRef<CTFontRef> font_ref_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontMac);
-};
-
-PepperTrueTypeFontMac::PepperTrueTypeFontMac(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
- // Create attributes and traits dictionaries.
- base::ScopedCFTypeRef<CFMutableDictionaryRef> attributes_ref(
- CFDictionaryCreateMutable(kCFAllocatorDefault,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
-
- base::ScopedCFTypeRef<CFMutableDictionaryRef> traits_ref(
- CFDictionaryCreateMutable(kCFAllocatorDefault,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- if (!attributes_ref || !traits_ref)
- return;
-
- CFDictionaryAddValue(attributes_ref, kCTFontTraitsAttribute, traits_ref);
-
- // Use symbolic traits to specify traits when possible.
- CTFontSymbolicTraits symbolic_traits = 0;
- if (desc.style & PP_TRUETYPEFONTSTYLE_ITALIC)
- symbolic_traits |= kCTFontItalicTrait;
- if (desc.weight == PP_TRUETYPEFONTWEIGHT_BOLD)
- symbolic_traits |= kCTFontBoldTrait;
- if (desc.width == PP_TRUETYPEFONTWIDTH_CONDENSED)
- symbolic_traits |= kCTFontCondensedTrait;
- else if (desc.width == PP_TRUETYPEFONTWIDTH_EXPANDED)
- symbolic_traits |= kCTFontExpandedTrait;
-
- base::ScopedCFTypeRef<CFNumberRef> symbolic_traits_ref(CFNumberCreate(
- kCFAllocatorDefault, kCFNumberSInt32Type, &symbolic_traits));
- if (!symbolic_traits_ref)
- return;
- CFDictionaryAddValue(traits_ref, kCTFontSymbolicTrait, symbolic_traits_ref);
-
- // Font family matching doesn't work using family classes in symbolic traits.
- // Instead, map generic_family to font families that are always available.
- std::string family(desc.family);
- if (family.empty()) {
- switch (desc.generic_family) {
- case PP_TRUETYPEFONTFAMILY_SERIF:
- family = "Times";
- break;
- case PP_TRUETYPEFONTFAMILY_SANSSERIF:
- family = "Helvetica";
- break;
- case PP_TRUETYPEFONTFAMILY_CURSIVE:
- family = "Apple Chancery";
- break;
- case PP_TRUETYPEFONTFAMILY_FANTASY:
- family = "Papyrus";
- break;
- case PP_TRUETYPEFONTFAMILY_MONOSPACE:
- family = "Courier";
- break;
- }
- }
-
- base::ScopedCFTypeRef<CFStringRef> name_ref(
- base::SysUTF8ToCFStringRef(family));
- if (name_ref)
- CFDictionaryAddValue(attributes_ref, kCTFontFamilyNameAttribute, name_ref);
-
- if (desc.weight != PP_TRUETYPEFONTWEIGHT_NORMAL &&
- desc.weight != PP_TRUETYPEFONTWEIGHT_BOLD) {
- float weight = GetMacWeight(desc.weight);
- base::ScopedCFTypeRef<CFNumberRef> weight_trait_ref(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &weight));
- if (weight_trait_ref)
- CFDictionaryAddValue(traits_ref, kCTFontWeightTrait, weight_trait_ref);
- }
-
- if (desc.width != PP_TRUETYPEFONTWIDTH_NORMAL &&
- desc.width != PP_TRUETYPEFONTWIDTH_CONDENSED &&
- desc.width != PP_TRUETYPEFONTWIDTH_EXPANDED) {
- float width = GetMacWidth(desc.width);
- base::ScopedCFTypeRef<CFNumberRef> width_trait_ref(
- CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat32Type, &width));
- if (width_trait_ref)
- CFDictionaryAddValue(traits_ref, kCTFontWidthTrait, width_trait_ref);
- }
-
- base::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
- CTFontDescriptorCreateWithAttributes(attributes_ref));
-
- if (desc_ref)
- font_ref_.reset(CTFontCreateWithFontDescriptor(desc_ref, 0, NULL));
-}
-
-PepperTrueTypeFontMac::~PepperTrueTypeFontMac() {
-}
-
-bool PepperTrueTypeFontMac::IsValid() {
- return font_ref_.get() != NULL;
-}
-
-int32_t PepperTrueTypeFontMac::Describe(
- ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
- if (!IsValid())
- return PP_ERROR_FAILED;
-
- base::ScopedCFTypeRef<CTFontDescriptorRef> desc_ref(
- CTFontCopyFontDescriptor(font_ref_));
-
- base::ScopedCFTypeRef<CFStringRef> family_name_ref(
- base::mac::CFCast<CFStringRef>(
- CTFontDescriptorCopyAttribute(desc_ref, kCTFontFamilyNameAttribute)));
- desc->family = base::SysCFStringRefToUTF8(family_name_ref);
-
- base::ScopedCFTypeRef<CFDictionaryRef> traits_ref(
- base::mac::CFCast<CFDictionaryRef>(
- CTFontDescriptorCopyAttribute(desc_ref, kCTFontTraitsAttribute)));
-
- desc->style = PP_TRUETYPEFONTSTYLE_NORMAL;
- CTFontSymbolicTraits symbolic_traits(CTFontGetSymbolicTraits(font_ref_));
- if (symbolic_traits & kCTFontItalicTrait)
- desc->style = static_cast<PP_TrueTypeFontStyle_Dev>(
- desc->style | PP_TRUETYPEFONTSTYLE_ITALIC);
- if (symbolic_traits & kCTFontBoldTrait) {
- desc->weight = PP_TRUETYPEFONTWEIGHT_BOLD;
- } else {
- float weight;
- if (FindFloat(traits_ref, kCTFontWeightTrait, &weight))
- desc->weight = GetPepperWeight(weight);
- }
- if (symbolic_traits & kCTFontCondensedTrait) {
- desc->width = PP_TRUETYPEFONTWIDTH_CONDENSED;
- } else if (symbolic_traits & kCTFontExpandedTrait) {
- desc->width = PP_TRUETYPEFONTWIDTH_EXPANDED;
- } else {
- float width;
- if (FindFloat(traits_ref, kCTFontWidthTrait, &width))
- desc->width = GetPepperWidth(width);
- }
-
- // Character set isn't supported on Mac.
- desc->charset = PP_TRUETYPEFONTCHARSET_DEFAULT;
- return PP_OK;
-}
-
-int32_t PepperTrueTypeFontMac::GetTableTags(std::vector<uint32_t>* tags) {
- base::ScopedCFTypeRef<CFArrayRef> tag_array(
- CTFontCopyAvailableTables(font_ref_, kCTFontTableOptionNoOptions));
- if (!tag_array)
- return PP_ERROR_FAILED;
-
- // Items returned by CTFontCopyAvailableTables are not boxed. Whose bright
- // idea was this?
- CFIndex length = CFArrayGetCount(tag_array);
- tags->resize(length);
- for (CFIndex i = 0; i < length; ++i) {
- (*tags)[i] =
- reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(tag_array, i));
- }
- return length;
-}
-
-int32_t PepperTrueTypeFontMac::GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) {
- if (!table_tag)
- return GetEntireFont(offset, max_data_length, data);
-
- base::ScopedCFTypeRef<CFDataRef> table_ref(
- CTFontCopyTable(font_ref_,
- static_cast<CTFontTableTag>(table_tag),
- kCTFontTableOptionNoOptions));
- if (!table_ref)
- return PP_ERROR_FAILED;
-
- CFIndex table_size = CFDataGetLength(table_ref);
- CFIndex safe_offset =
- std::min(base::checked_cast<CFIndex>(offset), table_size);
- CFIndex safe_length =
- std::min(table_size - safe_offset,
- base::checked_cast<CFIndex>(max_data_length));
- data->resize(safe_length);
- CFDataGetBytes(table_ref, CFRangeMake(safe_offset, safe_length),
- reinterpret_cast<UInt8*>(&(*data)[0]));
-
- return safe_length;
-}
-
-int32_t PepperTrueTypeFontMac::GetEntireFont(int32_t offset,
- int32_t max_data_length,
- std::string* data) {
- // Reconstruct the font header, table directory, and tables.
- std::vector<uint32_t> table_tags;
- int32_t table_count = GetTableTags(&table_tags);
- if (table_count < 0)
- return table_count; // PPAPI error code.
-
- // Allocate enough room for the header and the table directory entries.
- std::string font(sizeof(FontHeader) +
- sizeof(FontDirectoryEntry) * table_count, 0);
- // Map the OS X font type value to a TrueType scalar type.
- base::ScopedCFTypeRef<CFNumberRef> font_type_ref(
- base::mac::CFCast<CFNumberRef>(
- CTFontCopyAttribute(font_ref_, kCTFontFormatAttribute)));
- int32_t font_type;
- CFNumberGetValue(font_type_ref, kCFNumberSInt32Type, &font_type);
- switch (font_type) {
- case kCTFontFormatOpenTypePostScript:
- font_type = MAKE_TABLE_TAG('O', 'T', 'T', 'O');
- break;
- case kCTFontFormatTrueType:
- case kCTFontFormatBitmap:
- font_type = MAKE_TABLE_TAG('t', 'r', 'u', 'e');
- break;
- case kCTFontFormatPostScript:
- font_type = MAKE_TABLE_TAG('t', 'y', 'p', '1');
- break;
- case kCTFontFormatOpenTypeTrueType:
- case kCTFontFormatUnrecognized:
- default:
- font_type = MAKE_TABLE_TAG(0, 1, 0, 0);
- break;
- }
-
- // Calculate the rest of the header values.
- uint16_t num_tables = base::checked_cast<uint16_t>(table_count);
- uint16_t entry_selector = 0;
- uint16_t search_range = 1;
- while (search_range < num_tables >> 1) {
- entry_selector++;
- search_range <<= 1;
- }
- search_range <<= 4;
- uint16_t range_shift = (num_tables << 4) - search_range;
-
- // Write the header, with values in big-endian order.
- FontHeader* font_header = reinterpret_cast<FontHeader*>(&font[0]);
- font_header->font_type = base::HostToNet32(font_type);
- font_header->num_tables = base::HostToNet16(num_tables);
- font_header->search_range = base::HostToNet16(search_range);
- font_header->entry_selector = base::HostToNet16(entry_selector);
- font_header->range_shift = base::HostToNet16(range_shift);
-
- for (int32_t i = 0; i < table_count; i++) {
- // Get the table data.
- std::string table;
- int32_t table_size = GetTable(table_tags[i],
- 0, std::numeric_limits<int32_t>::max(),
- &table);
- if (table_size < 0)
- return table_size; // PPAPI error code.
-
- // Append it to the font data so far, and zero pad so tables stay aligned.
- size_t table_offset = font.size();
- font.append(table);
- size_t padding = font.size() & 0x3;
- font.append(padding, 0);
-
- // Fill in the directory entry for this table.
- FontDirectoryEntry* entry = reinterpret_cast<FontDirectoryEntry*>(
- &font[0] + sizeof(FontHeader) + i * sizeof(FontDirectoryEntry));
- entry->tag = base::HostToNet32(table_tags[i]);
- entry->checksum = base::HostToNet32(
- CalculateChecksum(&font[table_offset], table_size));
- entry->offset = base::HostToNet32(table_offset);
- entry->logical_length = base::HostToNet32(table_size);
- // TODO(bbudge) set the 'head' table checksumAdjustment.
- }
-
- // Extract a substring if the caller specified an offset or max data length.
- int32_t font_size = base::checked_cast<int32_t>(font.size());
- int32_t safe_offset = std::min(offset, font_size);
- int32_t safe_length = std::min(font_size - safe_offset, max_data_length);
- if (safe_offset || safe_length != font_size)
- font = font.substr(safe_offset, safe_length);
-
- data->clear();
- data->swap(font);
- return safe_length;
-}
-
-} // namespace
-
-// static
-PepperTrueTypeFont* PepperTrueTypeFont::Create(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
- return new PepperTrueTypeFontMac(desc);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_truetype_font_win.cc b/chromium/content/renderer/pepper/pepper_truetype_font_win.cc
deleted file mode 100644
index 9b8cdb482b0..00000000000
--- a/chromium/content/renderer/pepper/pepper_truetype_font_win.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (c) 2013 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 "content/renderer/pepper/pepper_truetype_font.h"
-
-#include <windows.h>
-#include <set>
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/sys_byteorder.h"
-#include "base/win/scoped_hdc.h"
-#include "base/win/scoped_select_object.h"
-#include "content/public/renderer/render_thread.h"
-#include "ppapi/c/dev/ppb_truetype_font_dev.h"
-#include "ppapi/c/pp_errors.h"
-
-namespace content {
-
-namespace {
-
-class PepperTrueTypeFontWin : public PepperTrueTypeFont {
- public:
- explicit PepperTrueTypeFontWin(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
- virtual ~PepperTrueTypeFontWin();
-
- // PepperTrueTypeFont overrides.
- virtual bool IsValid() OVERRIDE;
- virtual int32_t Describe(ppapi::proxy::SerializedTrueTypeFontDesc* desc)
- OVERRIDE;
- virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
- virtual int32_t GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) OVERRIDE;
-
- private:
- DWORD GetFontData(HDC hdc,
- DWORD table,
- DWORD offset,
- LPVOID buffer,
- DWORD length);
-
- HFONT font_;
-
- DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
-};
-
-PepperTrueTypeFontWin::PepperTrueTypeFontWin(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
- DWORD pitch_and_family = DEFAULT_PITCH;
- switch (desc.generic_family) {
- case PP_TRUETYPEFONTFAMILY_SERIF:
- pitch_and_family |= FF_ROMAN;
- break;
- case PP_TRUETYPEFONTFAMILY_SANSSERIF:
- pitch_and_family |= FF_SWISS;
- break;
- case PP_TRUETYPEFONTFAMILY_CURSIVE:
- pitch_and_family |= FF_SCRIPT;
- break;
- case PP_TRUETYPEFONTFAMILY_FANTASY:
- pitch_and_family |= FF_DECORATIVE;
- break;
- case PP_TRUETYPEFONTFAMILY_MONOSPACE:
- pitch_and_family |= FF_MODERN;
- break;
- }
- // TODO(bbudge) support widths (extended, condensed).
-
- font_ = CreateFont(0 /* height */,
- 0 /* width */,
- 0 /* escapement */,
- 0 /* orientation */,
- desc.weight, // our weight enum matches Windows.
- (desc.style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
- 0 /* underline */,
- 0 /* strikeout */,
- desc.charset, // our charset enum matches Windows.
- OUT_OUTLINE_PRECIS, // truetype and other outline fonts
- CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,
- pitch_and_family,
- base::UTF8ToUTF16(desc.family).c_str());
-}
-
-PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {}
-
-bool PepperTrueTypeFontWin::IsValid() { return font_ != NULL; }
-
-int32_t PepperTrueTypeFontWin::Describe(
- ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
- LOGFONT font_desc;
- if (!::GetObject(font_, sizeof(LOGFONT), &font_desc))
- return PP_ERROR_FAILED;
-
- switch (font_desc.lfPitchAndFamily & 0xF0) { // Top 4 bits are family.
- case FF_ROMAN:
- desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
- break;
- case FF_SWISS:
- desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
- break;
- case FF_SCRIPT:
- desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
- break;
- case FF_DECORATIVE:
- desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
- break;
- case FF_MODERN:
- desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
- break;
- }
-
- desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC
- : PP_TRUETYPEFONTSTYLE_NORMAL;
- desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight);
- desc->width = PP_TRUETYPEFONTWIDTH_NORMAL;
- desc->charset = static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
-
- // To get the face name, select the font and query for the name. GetObject
- // doesn't fill in the name field of the LOGFONT structure.
- base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
- if (hdc) {
- base::win::ScopedSelectObject select_object(hdc, font_);
- WCHAR name[LF_FACESIZE];
- GetTextFace(hdc, LF_FACESIZE, name);
- desc->family = base::UTF16ToUTF8(name);
- }
- return PP_OK;
-}
-
-DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
- DWORD table,
- DWORD offset,
- void* buffer,
- DWORD length) {
- // If this is a zero byte read, return a successful result.
- if (buffer && !length)
- return 0;
-
- DWORD result = ::GetFontData(hdc, table, offset, buffer, length);
- if (result == GDI_ERROR) {
- // The font may not be cached by the OS, causing an attempt to read it in
- // the renderer process to fail. Attempt to pre-cache it.
- LOGFONTW logfont;
- if (!::GetObject(font_, sizeof(LOGFONTW), &logfont))
- return GDI_ERROR;
- RenderThread* render_thread = RenderThread::Get();
- if (!render_thread)
- return GDI_ERROR;
- render_thread->PreCacheFont(logfont);
-
- result = ::GetFontData(hdc, table, offset, buffer, length);
- }
- return result;
-}
-
-int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
- base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
- if (!hdc)
- return PP_ERROR_FAILED;
-
- base::win::ScopedSelectObject select_object(hdc, font_);
-
- // Get the whole font header.
- static const DWORD kFontHeaderSize = 12;
- uint8_t header_buf[kFontHeaderSize];
- if (GetFontData(hdc, 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
- return PP_ERROR_FAILED;
-
- // The numTables follows a 4 byte scalerType tag. Font data is stored in
- // big-endian order.
- DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
-
- // The size in bytes of an entry in the table directory.
- static const DWORD kDirectoryEntrySize = 16;
- DWORD directory_size = num_tables * kDirectoryEntrySize;
- scoped_ptr<uint8_t[]> directory(new uint8_t[directory_size]);
- // Get the table directory entries after the font header.
- if (GetFontData(
- hdc, 0 /* tag */, kFontHeaderSize, directory.get(), directory_size) ==
- GDI_ERROR)
- return PP_ERROR_FAILED;
-
- tags->resize(num_tables);
- for (DWORD i = 0; i < num_tables; i++) {
- const uint8_t* entry = directory.get() + i * kDirectoryEntrySize;
- uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
- static_cast<uint32_t>(entry[1]) << 16 |
- static_cast<uint32_t>(entry[2]) << 8 |
- static_cast<uint32_t>(entry[3]);
- (*tags)[i] = tag;
- }
-
- return num_tables;
-}
-
-int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
- int32_t offset,
- int32_t max_data_length,
- std::string* data) {
- base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
- if (!hdc)
- return PP_ERROR_FAILED;
-
- base::win::ScopedSelectObject select_object(hdc, font_);
-
- // Tags are byte swapped on Windows.
- table_tag = base::ByteSwap(table_tag);
- // Get the size of the font table first.
- DWORD table_size = GetFontData(hdc, table_tag, 0, NULL, 0);
- if (table_size == GDI_ERROR)
- return PP_ERROR_FAILED;
-
- DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
- DWORD safe_length =
- std::min(table_size - safe_offset, static_cast<DWORD>(max_data_length));
- data->resize(safe_length);
- if (safe_length == 0) {
- table_size = 0;
- } else {
- table_size = GetFontData(hdc,
- table_tag,
- safe_offset,
- reinterpret_cast<uint8_t*>(&(*data)[0]),
- safe_length);
- if (table_size == GDI_ERROR)
- return PP_ERROR_FAILED;
- }
- return static_cast<int32_t>(table_size);
-}
-
-} // namespace
-
-// static
-PepperTrueTypeFont* PepperTrueTypeFont::Create(
- const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
- return new PepperTrueTypeFontWin(desc);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_try_catch.cc b/chromium/content/renderer/pepper/pepper_try_catch.cc
new file mode 100644
index 00000000000..ec843692214
--- /dev/null
+++ b/chromium/content/renderer/pepper/pepper_try_catch.cc
@@ -0,0 +1,173 @@
+// Copyright 2014 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 "content/renderer/pepper/pepper_try_catch.h"
+
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/v8_var_converter.h"
+#include "gin/converter.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/var_tracker.h"
+
+namespace content {
+
+namespace {
+
+const char kConversionException[] =
+ "Error: Failed conversion between PP_Var and V8 value";
+const char kInvalidException[] = "Error: An invalid exception was thrown.";
+
+} // namespace
+
+PepperTryCatch::PepperTryCatch(PepperPluginInstanceImpl* instance,
+ V8VarConverter* var_converter)
+ : instance_(instance), var_converter_(var_converter) {}
+
+PepperTryCatch::~PepperTryCatch() {}
+
+v8::Handle<v8::Value> PepperTryCatch::ToV8(PP_Var var) {
+ if (HasException()) {
+ SetException(kConversionException);
+ return v8::Handle<v8::Value>();
+ }
+
+ v8::Handle<v8::Value> result;
+ bool success = var_converter_->ToV8Value(var, GetContext(), &result);
+ if (!success) {
+ SetException(kConversionException);
+ return v8::Handle<v8::Value>();
+ }
+ return result;
+}
+
+ppapi::ScopedPPVar PepperTryCatch::FromV8(v8::Handle<v8::Value> v8_value) {
+ if (HasException() || v8_value.IsEmpty()) {
+ SetException(kConversionException);
+ return ppapi::ScopedPPVar();
+ }
+ ppapi::ScopedPPVar result;
+ bool success =
+ var_converter_->FromV8ValueSync(v8_value, GetContext(), &result);
+ if (!success) {
+ SetException(kConversionException);
+ return ppapi::ScopedPPVar();
+ }
+ return result;
+}
+
+PepperTryCatchV8::PepperTryCatchV8(PepperPluginInstanceImpl* instance,
+ V8VarConverter* var_converter,
+ v8::Isolate* isolate)
+ : PepperTryCatch(instance, var_converter),
+ exception_(PP_MakeUndefined()) {
+ // Typically when using PepperTryCatchV8 we are passed an isolate. We verify
+ // that this isolate is the same as the plugin isolate.
+ DCHECK(isolate == instance_->GetIsolate());
+
+ // We assume that a handle scope and context has been setup by the user of
+ // this class. This is typically true because this class is used when calling
+ // into the plugin from JavaScript. We want to use whatever v8 context the
+ // caller is in.
+}
+
+PepperTryCatchV8::~PepperTryCatchV8() {
+ ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(exception_);
+}
+
+bool PepperTryCatchV8::HasException() {
+ return GetContext().IsEmpty() || exception_.type != PP_VARTYPE_UNDEFINED;
+}
+
+v8::Handle<v8::Context> PepperTryCatchV8::GetContext() {
+ // When calling from JS into the plugin always use the current context.
+ return instance_->GetIsolate()->GetCurrentContext();
+}
+
+bool PepperTryCatchV8::ThrowException() {
+ if (!HasException())
+ return false;
+
+ // If there is no context then we have an exception but we don't try to throw
+ // it into v8.
+ if (GetContext().IsEmpty())
+ return true;
+
+ std::string message(kInvalidException);
+ ppapi::StringVar* message_var = ppapi::StringVar::FromPPVar(exception_);
+ if (message_var)
+ message = message_var->value();
+ instance_->GetIsolate()->ThrowException(v8::Exception::Error(
+ gin::StringToV8(instance_->GetIsolate(), message)));
+
+ ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(exception_);
+ exception_ = PP_MakeUndefined();
+ return true;
+}
+
+void PepperTryCatchV8::ThrowException(const char* message) {
+ SetException(message);
+ ThrowException();
+}
+
+void PepperTryCatchV8::SetException(const char* message) {
+ if (HasException())
+ return;
+
+ exception_ = ppapi::StringVar::StringToPPVar(message);
+}
+
+PepperTryCatchVar::PepperTryCatchVar(PepperPluginInstanceImpl* instance,
+ V8VarConverter* var_converter,
+ PP_Var* exception)
+ : PepperTryCatch(instance, var_converter),
+ handle_scope_(instance_->GetIsolate()),
+ context_(GetContext()),
+ exception_(exception),
+ exception_is_set_(false) {
+ // We switch to the plugin context if it's not empty.
+ if (!context_.IsEmpty())
+ context_->Enter();
+}
+
+PepperTryCatchVar::~PepperTryCatchVar() {
+ if (!context_.IsEmpty())
+ context_->Exit();
+}
+
+bool PepperTryCatchVar::HasException() {
+ if (exception_is_set_)
+ return true;
+
+ std::string exception_message;
+ if (GetContext().IsEmpty()) {
+ exception_message = "The v8 context has been destroyed.";
+ } else if (try_catch_.HasCaught()) {
+ v8::String::Utf8Value utf8(try_catch_.Message()->Get());
+ exception_message = std::string(*utf8, utf8.length());
+ }
+
+ if (!exception_message.empty()) {
+ exception_is_set_ = true;
+ if (exception_)
+ *exception_ = ppapi::StringVar::StringToPPVar(exception_message);
+ }
+
+ return exception_is_set_;
+}
+
+v8::Handle<v8::Context> PepperTryCatchVar::GetContext() {
+ // When calling into JS from the plugin, always use the plugin context.
+ return instance_->GetMainWorldContext();
+}
+
+void PepperTryCatchVar::SetException(const char* message) {
+ if (exception_is_set_)
+ return;
+
+ if (exception_)
+ *exception_ = ppapi::StringVar::StringToPPVar(message, strlen(message));
+ exception_is_set_ = true;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_try_catch.h b/chromium/content/renderer/pepper/pepper_try_catch.h
new file mode 100644
index 00000000000..72d03bf928a
--- /dev/null
+++ b/chromium/content/renderer/pepper/pepper_try_catch.h
@@ -0,0 +1,108 @@
+// Copyright 2014 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 CONTENT_RENDERER_PEPPER_PEPPER_TRY_CATCH_H_
+#define CONTENT_RENDERER_PEPPER_PEPPER_TRY_CATCH_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "content/common/content_export.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "v8/include/v8.h"
+
+namespace content {
+
+class PepperPluginInstanceImpl;
+class V8VarConverter;
+
+// Base class for scripting TryCatch helpers.
+class CONTENT_EXPORT PepperTryCatch {
+ public:
+ // PepperTryCatch objects should only be used as stack variables. This object
+ // takes a reference on the given PepperPluginInstanceImpl.
+ PepperTryCatch(PepperPluginInstanceImpl* instance,
+ V8VarConverter* var_converter);
+ virtual ~PepperTryCatch();
+
+ virtual void SetException(const char* message) = 0;
+ virtual bool HasException() = 0;
+ // Gets the context to execute scripts in.
+ virtual v8::Handle<v8::Context> GetContext() = 0;
+
+ // Convenience functions for doing conversions to/from V8 values and sets an
+ // exception if there is an error in the conversion.
+ v8::Handle<v8::Value> ToV8(PP_Var var);
+ ppapi::ScopedPPVar FromV8(v8::Handle<v8::Value> v8_value);
+
+ protected:
+ // Make sure that |instance_| is alive for the lifetime of PepperTryCatch.
+ // PepperTryCatch is used mostly in Pepper scripting code, where it can be
+ // possible to enter JavaScript synchronously which can cause the plugin to
+ // be deleted.
+ //
+ // Note that PepperTryCatch objects should only ever be on the stack, so this
+ // shouldn't keep the instance around for too long.
+ scoped_refptr<PepperPluginInstanceImpl> instance_;
+
+ V8VarConverter* var_converter_;
+};
+
+// Catches var exceptions and emits a v8 exception.
+class PepperTryCatchV8 : public PepperTryCatch {
+ public:
+ PepperTryCatchV8(PepperPluginInstanceImpl* instance,
+ V8VarConverter* var_converter,
+ v8::Isolate* isolate);
+ ~PepperTryCatchV8() override;
+
+ bool ThrowException();
+ void ThrowException(const char* message);
+ PP_Var* exception() { return &exception_; }
+
+ // PepperTryCatch
+ void SetException(const char* message) override;
+ bool HasException() override;
+ v8::Handle<v8::Context> GetContext() override;
+
+ private:
+ PP_Var exception_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTryCatchV8);
+};
+
+// Catches v8 exceptions and emits a var exception.
+class PepperTryCatchVar : public PepperTryCatch {
+ public:
+ // The PP_Var exception will be placed in |exception|. The user of this class
+ // is responsible for managing the lifetime of the exception. It is valid to
+ // pass NULL for |exception| in which case no exception will be set.
+ PepperTryCatchVar(PepperPluginInstanceImpl* instance,
+ V8VarConverter* var_converter,
+ PP_Var* exception);
+ ~PepperTryCatchVar() override;
+
+ // PepperTryCatch
+ void SetException(const char* message) override;
+ bool HasException() override;
+ v8::Handle<v8::Context> GetContext() override;
+
+ private:
+ // Code which uses PepperTryCatchVar doesn't typically have a HandleScope,
+ // make one for them. Note that this class is always allocated on the stack.
+ v8::HandleScope handle_scope_;
+
+ v8::Handle<v8::Context> context_;
+
+ v8::TryCatch try_catch_;
+
+ PP_Var* exception_;
+ bool exception_is_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperTryCatchVar);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PEPPER_TRY_CATCH_H_
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
index 7b01400c2e6..5f70dfa83b7 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
@@ -257,8 +257,12 @@ int32_t PepperURLLoaderHost::InternalOnHostMsgOpen(
return PP_ERROR_FAILED;
}
- web_request.setTargetType(WebURLRequest::TargetIsObject);
+ web_request.setRequestContext(WebURLRequest::RequestContextPlugin);
web_request.setRequestorProcessID(renderer_ppapi_host_->GetPluginPID());
+ // The requests from the plugins with private permission which can bypass same
+ // origin must skip the ServiceWorker.
+ web_request.setSkipServiceWorker(
+ host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE));
WebURLLoaderOptions options;
if (has_universal_access_) {
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.h b/chromium/content/renderer/pepper/pepper_url_loader_host.h
index e2986595069..8a784ef09b7 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.h
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.h
@@ -37,9 +37,9 @@ class PepperURLLoaderHost : public ppapi::host::ResourceHost,
virtual ~PepperURLLoaderHost();
// ResourceHost implementation.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// blink::WebURLLoaderClient implementation.
virtual void willSendRequest(blink::WebURLLoader* loader,
@@ -65,7 +65,7 @@ class PepperURLLoaderHost : public ppapi::host::ResourceHost,
private:
// ResourceHost protected overrides.
- virtual void DidConnectPendingHostToResource() OVERRIDE;
+ void DidConnectPendingHostToResource() override;
// IPC messages
int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
diff --git a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
index 44936c287be..e9008ec5800 100644
--- a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
@@ -53,9 +53,11 @@ namespace content {
class URLRequestInfoTest : public RenderViewTest {
public:
- URLRequestInfoTest() : pp_instance_(1234) {}
+ // Note: using -1 as the instance value allows code in
+ // url_request_info_util.cc to detect that this is a test instance.
+ URLRequestInfoTest() : pp_instance_(-1) {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewTest::SetUp();
ppapi::ProxyLock::DisableLockingOnThreadForTest();
@@ -66,7 +68,7 @@ class URLRequestInfoTest : public RenderViewTest {
ppapi::proxy::Connection(), pp_instance_, URLRequestInfoData());
}
- virtual void TearDown() OVERRIDE {
+ void TearDown() override {
test_globals_.GetResourceTracker()->DidDeleteInstance(pp_instance_);
RenderViewTest::TearDown();
}
@@ -130,7 +132,7 @@ TEST_F(URLRequestInfoTest, GetInterface) {
}
TEST_F(URLRequestInfoTest, AsURLRequestInfo) {
- EXPECT_EQ(info_, info_->AsPPB_URLRequestInfo_API());
+ EXPECT_EQ(info_.get(), info_->AsPPB_URLRequestInfo_API());
}
TEST_F(URLRequestInfoTest, StreamToFile) {
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.cc b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
index 71bebb30ebd..6e8ea32f8b0 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
@@ -9,7 +9,7 @@
#include "content/renderer/pepper/pepper_platform_video_capture.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_frame_impl.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h"
#include "ppapi/host/dispatch_host_message.h"
@@ -42,8 +42,8 @@ PepperVideoCaptureHost::PepperVideoCaptureHost(RendererPpapiHostImpl* host,
buffer_count_hint_(0),
status_(PP_VIDEO_CAPTURE_STATUS_STOPPED),
enumeration_helper_(this,
- PepperMediaDeviceManager::GetForRenderView(
- host->GetRenderViewForInstance(pp_instance())),
+ PepperMediaDeviceManager::GetForRenderFrame(
+ host->GetRenderFrameForInstance(pp_instance())),
PP_DEVICETYPE_DEV_VIDEOCAPTURE,
host->GetDocumentURL(instance)) {
}
@@ -114,7 +114,9 @@ void PepperVideoCaptureHost::PostErrorReply() {
// the capture.
SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPED, true);
host()->SendUnsolicitedReply(
- pp_resource(), PpapiPluginMsg_VideoCapture_OnError(PP_ERROR_FAILED));
+ pp_resource(),
+ PpapiPluginMsg_VideoCapture_OnError(
+ static_cast<uint32_t>(PP_ERROR_FAILED)));
}
void PepperVideoCaptureHost::OnFrameReady(
@@ -259,11 +261,12 @@ int32_t PepperVideoCaptureHost::OnOpen(
if (!document_url.is_valid())
return PP_ERROR_FAILED;
- RenderViewImpl* render_view = static_cast<RenderViewImpl*>(
- renderer_ppapi_host_->GetRenderViewForInstance(pp_instance()));
-
platform_video_capture_.reset(new PepperPlatformVideoCapture(
- render_view->AsWeakPtr(), device_id, document_url, this));
+ renderer_ppapi_host_->GetRenderFrameForInstance(pp_instance())->
+ GetRoutingID(),
+ device_id,
+ document_url,
+ this));
open_reply_context_ = context->MakeReplyMessageContext();
@@ -354,7 +357,6 @@ void PepperVideoCaptureHost::SetRequestedInfo(
gfx::Size(device_info.width, device_info.height),
frames_per_second,
media::PIXEL_FORMAT_I420);
- video_capture_params_.allow_resolution_change = false;
}
void PepperVideoCaptureHost::DetachPlatformVideoCapture() {
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.h b/chromium/content/renderer/pepper/pepper_video_capture_host.h
index 8326c5ec1aa..3c5ec12d15a 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.h
@@ -31,13 +31,13 @@ class PepperVideoCaptureHost : public ppapi::host::ResourceHost {
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperVideoCaptureHost();
+ ~PepperVideoCaptureHost() override;
bool Init();
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// These methods are called by PepperPlatformVideoCapture only.
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
index abcab8f1b89..02e14f3be5c 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
@@ -9,6 +9,7 @@
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/renderer_ppapi_host.h"
+#include "content/renderer/pepper/gfx_conversion.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/pepper/video_decoder_shim.h"
#include "media/video/video_decode_accelerator.h"
@@ -53,10 +54,10 @@ media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) {
return media::H264PROFILE_STEREOHIGH;
case PP_VIDEOPROFILE_H264MULTIVIEWHIGH:
return media::H264PROFILE_MULTIVIEWHIGH;
- case PP_VIDEOPROFILE_VP8MAIN:
- return media::VP8PROFILE_MAIN;
- case PP_VIDEOPROFILE_VP9MAIN:
- return media::VP9PROFILE_MAIN;
+ case PP_VIDEOPROFILE_VP8_ANY:
+ return media::VP8PROFILE_ANY;
+ case PP_VIDEOPROFILE_VP9_ANY:
+ return media::VP9PROFILE_ANY;
// No default case, to catch unhandled PP_VideoProfile values.
}
@@ -111,7 +112,7 @@ int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
ppapi::host::HostMessageContext* context,
const ppapi::HostResource& graphics_context,
PP_VideoProfile profile,
- bool allow_software_fallback) {
+ PP_HardwareAcceleration acceleration) {
if (initialized_)
return PP_ERROR_FAILED;
@@ -128,25 +129,30 @@ int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
media::VideoCodecProfile media_profile = PepperToMediaVideoProfile(profile);
- // This is not synchronous, but subsequent IPC messages will be buffered, so
- // it is okay to immediately send IPC messages through the returned channel.
- GpuChannelHost* channel = graphics3d->channel();
- DCHECK(channel);
- decoder_ = channel->CreateVideoDecoder(command_buffer_route_id);
- if (decoder_ && decoder_->Initialize(media_profile, this)) {
- initialized_ = true;
- return PP_OK;
+ if (acceleration != PP_HARDWAREACCELERATION_NONE) {
+ // This is not synchronous, but subsequent IPC messages will be buffered, so
+ // it is okay to immediately send IPC messages through the returned channel.
+ GpuChannelHost* channel = graphics3d->channel();
+ DCHECK(channel);
+ decoder_ = channel->CreateVideoDecoder(command_buffer_route_id);
+ if (decoder_ && decoder_->Initialize(media_profile, this)) {
+ initialized_ = true;
+ return PP_OK;
+ }
+ decoder_.reset();
+ if (acceleration == PP_HARDWAREACCELERATION_ONLY)
+ return PP_ERROR_NOTSUPPORTED;
}
- decoder_.reset();
-
- if (!allow_software_fallback)
- return PP_ERROR_NOTSUPPORTED;
+#if defined(OS_ANDROID)
+ return PP_ERROR_NOTSUPPORTED;
+#else
decoder_.reset(new VideoDecoderShim(this));
initialize_reply_context_ = context->MakeReplyMessageContext();
decoder_->Initialize(media_profile, this);
return PP_OK_COMPLETIONPENDING;
+#endif
}
int32_t PepperVideoDecoderHost::OnHostMsgGetShm(
@@ -309,10 +315,13 @@ void PepperVideoDecoderHost::ProvidePictureBuffers(
}
void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) {
- host()->SendUnsolicitedReply(
- pp_resource(),
- PpapiPluginMsg_VideoDecoder_PictureReady(picture.bitstream_buffer_id(),
- picture.picture_buffer_id()));
+ // Don't bother validating the visible rect, since the plugin process is less
+ // trusted than the gpu process.
+ PP_Rect visible_rect = PP_FromGfxRect(picture.visible_rect());
+ host()->SendUnsolicitedReply(pp_resource(),
+ PpapiPluginMsg_VideoDecoder_PictureReady(
+ picture.bitstream_buffer_id(),
+ picture.picture_buffer_id(), visible_rect));
}
void PepperVideoDecoderHost::DismissPictureBuffer(int32 picture_buffer_id) {
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.h b/chromium/content/renderer/pepper/pepper_video_decoder_host.h
index e76f95c4bf6..fab65d891ad 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT PepperVideoDecoderHost
PepperVideoDecoderHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperVideoDecoderHost();
+ ~PepperVideoDecoderHost() override;
private:
struct PendingDecode {
@@ -52,25 +52,25 @@ class CONTENT_EXPORT PepperVideoDecoderHost
friend class VideoDecoderShim;
// ResourceHost implementation.
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// media::VideoDecodeAccelerator::Client implementation.
- virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
- const gfx::Size& dimensions,
- uint32 texture_target) OVERRIDE;
- virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void PictureReady(const media::Picture& picture) OVERRIDE;
- virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE;
- virtual void NotifyFlushDone() OVERRIDE;
- virtual void NotifyResetDone() OVERRIDE;
- virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE;
+ void ProvidePictureBuffers(uint32 requested_num_of_buffers,
+ const gfx::Size& dimensions,
+ uint32 texture_target) override;
+ void DismissPictureBuffer(int32 picture_buffer_id) override;
+ void PictureReady(const media::Picture& picture) override;
+ void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) override;
+ void NotifyFlushDone() override;
+ void NotifyResetDone() override;
+ void NotifyError(media::VideoDecodeAccelerator::Error error) override;
int32_t OnHostMsgInitialize(ppapi::host::HostMessageContext* context,
const ppapi::HostResource& graphics_context,
PP_VideoProfile profile,
- bool allow_software_fallback);
+ PP_HardwareAcceleration acceleration);
int32_t OnHostMsgGetShm(ppapi::host::HostMessageContext* context,
uint32_t shm_id,
uint32_t shm_size);
diff --git a/chromium/content/renderer/pepper/pepper_video_destination_host.h b/chromium/content/renderer/pepper/pepper_video_destination_host.h
index 277b6681fc5..3eb2b222625 100644
--- a/chromium/content/renderer/pepper/pepper_video_destination_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_destination_host.h
@@ -24,11 +24,11 @@ class CONTENT_EXPORT PepperVideoDestinationHost
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperVideoDestinationHost();
+ ~PepperVideoDestinationHost() override;
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
private:
int32_t OnHostMsgOpen(ppapi::host::HostMessageContext* context,
diff --git a/chromium/content/renderer/pepper/pepper_video_source_host.cc b/chromium/content/renderer/pepper/pepper_video_source_host.cc
index d90ed26e8e7..b75eabb0535 100644
--- a/chromium/content/renderer/pepper/pepper_video_source_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_source_host.cc
@@ -12,6 +12,7 @@
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppb_image_data_proxy.h"
#include "ppapi/shared_impl/scoped_pp_resource.h"
@@ -27,23 +28,13 @@ namespace content {
PepperVideoSourceHost::FrameReceiver::FrameReceiver(
const base::WeakPtr<PepperVideoSourceHost>& host)
- : host_(host),
- main_message_loop_proxy_(base::MessageLoopProxy::current()) {}
+ : host_(host) {}
PepperVideoSourceHost::FrameReceiver::~FrameReceiver() {}
-bool PepperVideoSourceHost::FrameReceiver::GotFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
- // It's not safe to access the host from this thread, so post a task to our
- // main thread to transfer the new frame.
- main_message_loop_proxy_->PostTask(
- FROM_HERE, base::Bind(&FrameReceiver::OnGotFrame, this, frame));
-
- return true;
-}
-
-void PepperVideoSourceHost::FrameReceiver::OnGotFrame(
+void PepperVideoSourceHost::FrameReceiver::GotFrame(
const scoped_refptr<media::VideoFrame>& frame) {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (host_.get()) {
// Hold a reference to the new frame and release the previous.
host_->last_frame_ = frame;
@@ -62,6 +53,7 @@ PepperVideoSourceHost::PepperVideoSourceHost(RendererPpapiHost* host,
get_frame_pending_(false),
weak_factory_(this) {
frame_receiver_ = new FrameReceiver(weak_factory_.GetWeakPtr());
+ memset(&shared_image_desc_, 0, sizeof(shared_image_desc_));
}
PepperVideoSourceHost::~PepperVideoSourceHost() { Close(); }
@@ -129,45 +121,85 @@ void PepperVideoSourceHost::SendGetFrameReply() {
const int dst_width = frame->visible_rect().width();
const int dst_height = frame->visible_rect().height();
- PP_ImageDataDesc image_desc;
+ // Note: We try to reuse the shared memory for the previous frame here. This
+ // means that the previous frame may be overwritten and is no longer valid
+ // after calling this function again.
IPC::PlatformFileForTransit image_handle;
uint32_t byte_count;
- ppapi::ScopedPPResource resource(
- ppapi::ScopedPPResource::PassRef(),
- ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
- pp_instance(),
- ppapi::PPB_ImageData_Shared::SIMPLE,
- PP_IMAGEDATAFORMAT_BGRA_PREMUL,
- PP_MakeSize(dst_width, dst_height),
- false /* init_to_zero */,
- &image_desc,
- &image_handle,
- &byte_count));
- if (!resource.get()) {
- SendGetFrameErrorReply(PP_ERROR_FAILED);
- return;
+ if (shared_image_.get() && dst_width == shared_image_->width() &&
+ dst_height == shared_image_->height()) {
+ // We have already allocated the correct size in shared memory. We need to
+ // duplicate the handle for IPC however, which will close down the
+ // duplicated handle when it's done.
+ int local_fd = 0;
+ if (shared_image_->GetSharedMemory(&local_fd, &byte_count) != PP_OK) {
+ SendGetFrameErrorReply(PP_ERROR_FAILED);
+ return;
+ }
+
+ ppapi::proxy::HostDispatcher* dispatcher =
+ ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
+ if (!dispatcher) {
+ SendGetFrameErrorReply(PP_ERROR_FAILED);
+ return;
+ }
+
+#if defined(OS_WIN)
+ image_handle = dispatcher->ShareHandleWithRemote(
+ reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd)), false);
+#elif defined(OS_POSIX)
+ image_handle = dispatcher->ShareHandleWithRemote(local_fd, false);
+#else
+#error Not implemented.
+#endif
+ } else {
+ // We need to allocate new shared memory.
+ shared_image_ = NULL; // Release any previous image.
+
+ ppapi::ScopedPPResource resource(
+ ppapi::ScopedPPResource::PassRef(),
+ ppapi::proxy::PPB_ImageData_Proxy::CreateImageData(
+ pp_instance(),
+ ppapi::PPB_ImageData_Shared::SIMPLE,
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL,
+ PP_MakeSize(dst_width, dst_height),
+ false /* init_to_zero */,
+ &shared_image_desc_,
+ &image_handle,
+ &byte_count));
+ if (!resource) {
+ SendGetFrameErrorReply(PP_ERROR_FAILED);
+ return;
+ }
+
+ ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
+ enter_resource(resource, false);
+ if (enter_resource.failed()) {
+ SendGetFrameErrorReply(PP_ERROR_FAILED);
+ return;
+ }
+
+ shared_image_ = static_cast<PPB_ImageData_Impl*>(enter_resource.object());
+ if (!shared_image_.get()) {
+ SendGetFrameErrorReply(PP_ERROR_FAILED);
+ return;
+ }
+
+ DCHECK(!shared_image_->IsMapped()); // New memory should not be mapped.
+ if (!shared_image_->Map() || !shared_image_->GetMappedBitmap() ||
+ !shared_image_->GetMappedBitmap()->getPixels()) {
+ shared_image_ = NULL;
+ SendGetFrameErrorReply(PP_ERROR_FAILED);
+ return;
+ }
}
- ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_ImageData_API>
- enter_resource(resource, false);
- if (enter_resource.failed()) {
- SendGetFrameErrorReply(PP_ERROR_FAILED);
- return;
- }
-
- PPB_ImageData_Impl* image_data =
- static_cast<PPB_ImageData_Impl*>(enter_resource.object());
- ImageDataAutoMapper mapper(image_data);
- if (!mapper.is_valid()) {
- SendGetFrameErrorReply(PP_ERROR_FAILED);
- return;
- }
-
- const SkBitmap* bitmap = image_data->GetMappedBitmap();
+ const SkBitmap* bitmap = shared_image_->GetMappedBitmap();
if (!bitmap) {
SendGetFrameErrorReply(PP_ERROR_FAILED);
return;
}
+
uint8_t* bitmap_pixels = static_cast<uint8_t*>(bitmap->getPixels());
if (!bitmap_pixels) {
SendGetFrameErrorReply(PP_ERROR_FAILED);
@@ -192,7 +224,7 @@ void PepperVideoSourceHost::SendGetFrameReply() {
const uint8* src_v = frame->data(media::VideoFrame::kVPlane) +
(center * vert_crop + horiz_crop) / 2;
- libyuv::I420ToBGRA(src_y,
+ libyuv::I420ToARGB(src_y,
frame->stride(media::VideoFrame::kYPlane),
src_u,
frame->stride(media::VideoFrame::kUPlane),
@@ -204,10 +236,10 @@ void PepperVideoSourceHost::SendGetFrameReply() {
dst_height);
ppapi::HostResource host_resource;
- host_resource.SetHostResource(pp_instance(), resource.get());
+ host_resource.SetHostResource(pp_instance(), shared_image_->GetReference());
// Convert a video timestamp to a PP_TimeTicks (a double, in seconds).
- PP_TimeTicks timestamp = frame->timestamp().InSecondsF();
+ const PP_TimeTicks timestamp = frame->timestamp().InSecondsF();
ppapi::proxy::SerializedHandle serialized_handle;
serialized_handle.set_shmem(image_handle, byte_count);
@@ -215,12 +247,9 @@ void PepperVideoSourceHost::SendGetFrameReply() {
host()->SendReply(reply_context_,
PpapiPluginMsg_VideoSource_GetFrameReply(
- host_resource, image_desc, timestamp));
+ host_resource, shared_image_desc_, timestamp));
reply_context_ = ppapi::host::ReplyMessageContext();
-
- // Keep a reference once we know this method succeeds.
- resource.Release();
}
void PepperVideoSourceHost::SendGetFrameErrorReply(int32_t error) {
@@ -238,6 +267,8 @@ void PepperVideoSourceHost::Close() {
source_handler_.reset(NULL);
stream_url_.clear();
+
+ shared_image_ = NULL;
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_video_source_host.h b/chromium/content/renderer/pepper/pepper_video_source_host.h
index a1414ceadeb..6010aad4ca2 100644
--- a/chromium/content/renderer/pepper/pepper_video_source_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_source_host.h
@@ -9,9 +9,11 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/renderer/media/video_source_handler.h"
#include "ppapi/c/pp_time.h"
+#include "ppapi/c/ppb_image_data.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
@@ -19,6 +21,7 @@ struct PP_ImageDataDesc;
namespace content {
+class PPB_ImageData_Impl;
class RendererPpapiHost;
class CONTENT_EXPORT PepperVideoSourceHost : public ppapi::host::ResourceHost {
@@ -27,11 +30,11 @@ class CONTENT_EXPORT PepperVideoSourceHost : public ppapi::host::ResourceHost {
PP_Instance instance,
PP_Resource resource);
- virtual ~PepperVideoSourceHost();
+ ~PepperVideoSourceHost() override;
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
private:
// This helper object receives frames on a video worker thread and passes
@@ -42,17 +45,15 @@ class CONTENT_EXPORT PepperVideoSourceHost : public ppapi::host::ResourceHost {
explicit FrameReceiver(const base::WeakPtr<PepperVideoSourceHost>& host);
// FrameReaderInterface implementation.
- virtual bool GotFrame(const scoped_refptr<media::VideoFrame>& frame)
- OVERRIDE;
-
- void OnGotFrame(const scoped_refptr<media::VideoFrame>& frame);
+ void GotFrame(const scoped_refptr<media::VideoFrame>& frame) override;
private:
friend class base::RefCountedThreadSafe<FrameReceiver>;
- virtual ~FrameReceiver();
+ ~FrameReceiver() override;
base::WeakPtr<PepperVideoSourceHost> host_;
- scoped_refptr<base::MessageLoopProxy> main_message_loop_proxy_;
+ // |thread_checker_| is bound to the main render thread.
+ base::ThreadChecker thread_checker_;
};
friend class FrameReceiver;
@@ -79,6 +80,13 @@ class CONTENT_EXPORT PepperVideoSourceHost : public ppapi::host::ResourceHost {
std::string stream_url_;
scoped_refptr<media::VideoFrame> last_frame_;
bool get_frame_pending_;
+ // We use only one ImageData resource in order to avoid allocating
+ // shared memory repeatedly. We send the same one each time the plugin
+ // requests a frame. For this to work, the plugin must finish using
+ // the ImageData it receives prior to calling GetFrame, and not access
+ // the ImageData until it gets its next callback to GetFrame.
+ scoped_refptr<PPB_ImageData_Impl> shared_image_;
+ PP_ImageDataDesc shared_image_desc_;
base::WeakPtrFactory<PepperVideoSourceHost> weak_factory_;
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
index 828da7a3d87..ecdd9e5b857 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -11,9 +11,9 @@
#include "content/public/common/page_zoom.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/pepper/message_channel.h"
-#include "content/renderer/pepper/npobject_var.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
+#include "content/renderer/pepper/v8object_var.h"
#include "content/renderer/render_frame_impl.h"
#include "ppapi/shared_impl/ppapi_globals.h"
#include "ppapi/shared_impl/var_tracker.h"
@@ -31,7 +31,7 @@
#include "third_party/WebKit/public/web/WebPrintScalingOption.h"
#include "url/gurl.h"
-using ppapi::NPObjectVar;
+using ppapi::V8ObjectVar;
using blink::WebCanvas;
using blink::WebPlugin;
using blink::WebPluginContainer;
@@ -126,29 +126,30 @@ void PepperWebPluginImpl::destroy() {
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-NPObject* PepperWebPluginImpl::scriptableObject() {
+v8::Local<v8::Object> PepperWebPluginImpl::v8ScriptableObject(
+ v8::Isolate* isolate) {
// Call through the plugin to get its instance object. The plugin should pass
// us a reference which we release in destroy().
if (instance_object_.type == PP_VARTYPE_UNDEFINED)
- instance_object_ = instance_->GetInstanceObject();
+ instance_object_ = instance_->GetInstanceObject(isolate);
// GetInstanceObject talked to the plugin which may have removed the instance
// from the DOM, in which case instance_ would be NULL now.
if (!instance_.get())
- return NULL;
+ return v8::Local<v8::Object>();
- scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(instance_object_));
+ scoped_refptr<V8ObjectVar> object_var(
+ V8ObjectVar::FromPPVar(instance_object_));
// If there's an InstanceObject, tell the Instance's MessageChannel to pass
// any non-postMessage calls to it.
- if (object.get()) {
- instance_->message_channel().SetPassthroughObject(object->np_object());
+ if (object_var.get()) {
+ MessageChannel* message_channel = instance_->message_channel();
+ if (message_channel)
+ message_channel->SetPassthroughObject(object_var->GetHandle());
}
- NPObject* message_channel_np_object(instance_->message_channel().np_object());
- // The object is expected to be retained before it is returned.
- blink::WebBindings::retainObject(message_channel_np_object);
- return message_channel_np_object;
-}
-NPP PepperWebPluginImpl::pluginNPP() { return instance_->instanceNPP(); }
+ v8::Handle<v8::Object> result = instance_->GetMessageChannelObject();
+ return result;
+}
bool PepperWebPluginImpl::getFormValue(WebString& value) { return false; }
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
index cee66902371..c11bcebce3b 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
@@ -41,8 +41,8 @@ class PepperWebPluginImpl : public blink::WebPlugin {
virtual blink::WebPluginContainer* container() const;
virtual bool initialize(blink::WebPluginContainer* container);
virtual void destroy();
- virtual NPObject* scriptableObject();
- virtual struct _NPP* pluginNPP();
+ virtual v8::Local<v8::Object> v8ScriptableObject(
+ v8::Isolate* isolate) override;
virtual bool getFormValue(blink::WebString& value);
virtual void paint(blink::WebCanvas* canvas, const blink::WebRect& rect);
virtual void updateGeometry(
@@ -74,16 +74,16 @@ class PepperWebPluginImpl : public blink::WebPlugin {
int identifier);
virtual void selectFindResult(bool forward);
virtual void stopFind();
- virtual bool supportsPaginatedPrint() OVERRIDE;
- virtual bool isPrintScalingDisabled() OVERRIDE;
+ virtual bool supportsPaginatedPrint() override;
+ virtual bool isPrintScalingDisabled() override;
- virtual int printBegin(const blink::WebPrintParams& print_params) OVERRIDE;
- virtual bool printPage(int page_number, blink::WebCanvas* canvas) OVERRIDE;
- virtual void printEnd() OVERRIDE;
+ virtual int printBegin(const blink::WebPrintParams& print_params) override;
+ virtual bool printPage(int page_number, blink::WebCanvas* canvas) override;
+ virtual void printEnd() override;
- virtual bool canRotateView() OVERRIDE;
- virtual void rotateView(RotationType type) OVERRIDE;
- virtual bool isPlaceholder() OVERRIDE;
+ virtual bool canRotateView() override;
+ virtual void rotateView(RotationType type) override;
+ virtual bool isPlaceholder() override;
private:
friend class base::DeleteHelper<PepperWebPluginImpl>;
diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.cc b/chromium/content/renderer/pepper/pepper_websocket_host.cc
index 9b74ccc2dc5..6b55bb6975b 100644
--- a/chromium/content/renderer/pepper/pepper_websocket_host.cc
+++ b/chromium/content/renderer/pepper/pepper_websocket_host.cc
@@ -194,8 +194,10 @@ void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount,
}
// Disconnect.
- if (websocket_)
+ if (websocket_) {
websocket_->disconnect();
+ websocket_.reset();
+ }
}
int32_t PepperWebSocketHost::OnHostMsgConnect(
diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.h b/chromium/content/renderer/pepper/pepper_websocket_host.h
index 091b3e12791..8b8c841be5f 100644
--- a/chromium/content/renderer/pepper/pepper_websocket_host.h
+++ b/chromium/content/renderer/pepper/pepper_websocket_host.h
@@ -34,9 +34,9 @@ class CONTENT_EXPORT PepperWebSocketHost
PP_Resource resource);
virtual ~PepperWebSocketHost();
- virtual int32_t OnResourceMessageReceived(
+ int32_t OnResourceMessageReceived(
const IPC::Message& msg,
- ppapi::host::HostMessageContext* context) OVERRIDE;
+ ppapi::host::HostMessageContext* context) override;
// WebSocketClient implementation.
virtual void didConnect();
diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc
index 48add88a06a..9a467940d41 100644
--- a/chromium/content/renderer/pepper/plugin_module.cc
+++ b/chromium/content/renderer/pepper/plugin_module.cc
@@ -16,12 +16,12 @@
#include "build/build_config.h"
#include "content/common/view_messages.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/host_dispatcher_wrapper.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_hung_plugin_filter.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_plugin_registry.h"
+#include "content/renderer/pepper/ppapi_preferences_builder.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "content/renderer/pepper/ppb_proxy_impl.h"
#include "content/renderer/pepper/ppb_scrollbar_impl.h"
@@ -207,9 +207,9 @@ void CallOnMainThread(int delay_in_msec,
}
PP_Bool IsMainThread() {
- return BoolToPPBool(PpapiGlobals::Get()
- ->GetMainThreadMessageLoop()
- ->BelongsToCurrentThread());
+ return PP_FromBool(PpapiGlobals::Get()
+ ->GetMainThreadMessageLoop()
+ ->BelongsToCurrentThread());
}
const PPB_Core core_interface = {&AddRefResource, &ReleaseResource,
@@ -224,7 +224,7 @@ PP_Bool ReadImageData(PP_Resource device_context_2d,
EnterResource<PPB_Graphics2D_API> enter(device_context_2d, true);
if (enter.failed())
return PP_FALSE;
- return BoolToPPBool(enter.object()->ReadImageData(image, top_left));
+ return PP_FromBool(enter.object()->ReadImageData(image, top_left));
}
void RunMessageLoop(PP_Instance instance) {
@@ -281,12 +281,17 @@ void SetMinimumArrayBufferSizeForShmem(PP_Instance /*instance*/,
// Does nothing. Not needed in-process.
}
+void RunV8GC(PP_Instance instance) {
+ content::PepperPluginInstance::Get(instance)->GetIsolate()->
+ RequestGarbageCollectionForTesting(v8::Isolate::kFullGarbageCollection);
+}
+
const PPB_Testing_Private testing_interface = {
&ReadImageData, &RunMessageLoop,
&QuitMessageLoop, &GetLiveObjectsForInstance,
&IsOutOfProcess, &SimulateInputEvent,
&GetDocumentURL, &GetLiveVars,
- &SetMinimumArrayBufferSizeForShmem};
+ &SetMinimumArrayBufferSizeForShmem,&RunV8GC};
// GetInterface ----------------------------------------------------------------
@@ -390,6 +395,7 @@ void CreateHostForInProcessModule(RenderFrameImpl* render_frame,
// PluginModule ----------------------------------------------------------------
PluginModule::PluginModule(const std::string& name,
+ const std::string& version,
const base::FilePath& path,
const ppapi::PpapiPermissions& perms)
: callback_tracker_(new ppapi::CallbackTracker),
@@ -398,6 +404,7 @@ PluginModule::PluginModule(const std::string& name,
broker_(NULL),
library_(NULL),
name_(name),
+ version_(version),
path_(path),
permissions_(ppapi::PpapiPermissions::GetForCommandLine(perms.GetBits())),
reserve_instance_id_(NULL) {
@@ -490,7 +497,7 @@ PluginModule::CreateModuleForExternalPluginInstance() {
// Create a new module, but don't set the lifetime delegate. This isn't a
// plugin in the usual sense, so it isn't tracked by the browser.
scoped_refptr<PluginModule> external_plugin_module(
- new PluginModule(name_, path_, permissions_));
+ new PluginModule(name_, version_, path_, permissions_));
return external_plugin_module;
}
@@ -597,7 +604,7 @@ void PluginModule::SetReserveInstanceIDCallback(
bool PluginModule::ReserveInstanceID(PP_Instance instance) {
if (reserve_instance_id_)
- return PPBoolToBool(reserve_instance_id_(pp_module_, instance));
+ return PP_ToBool(reserve_instance_id_(pp_module_, instance));
return true; // Instance ID is usable.
}
@@ -620,11 +627,11 @@ RendererPpapiHostImpl* PluginModule::CreateOutOfProcessModule(
path, render_frame->GetRoutingID(), plugin_child_id));
scoped_ptr<HostDispatcherWrapper> dispatcher(new HostDispatcherWrapper(
this, peer_pid, plugin_child_id, permissions, is_external));
- if (!dispatcher->Init(
- channel_handle,
- &GetInterface,
- ppapi::Preferences(render_frame->render_view()->webkit_preferences()),
- hung_filter.get()))
+ if (!dispatcher->Init(channel_handle,
+ &GetInterface,
+ ppapi::Preferences(PpapiPreferencesBuilder::Build(
+ render_frame->render_view()->webkit_preferences())),
+ hung_filter.get()))
return NULL;
RendererPpapiHostImpl* host_impl =
@@ -691,7 +698,7 @@ scoped_refptr<PluginModule> PluginModule::Create(
// Out of process: have the browser start the plugin process for us.
IPC::ChannelHandle channel_handle;
- base::ProcessId peer_pid;
+ base::ProcessId peer_pid = 0;
int plugin_child_id = 0;
render_frame->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
path, &channel_handle, &peer_pid, &plugin_child_id));
@@ -704,7 +711,7 @@ scoped_refptr<PluginModule> PluginModule::Create(
// AddLiveModule must be called before any early returns since the
// module's destructor will remove itself.
- module = new PluginModule(info->name, path, permissions);
+ module = new PluginModule(info->name, info->version, path, permissions);
PepperPluginRegistry::GetInstance()->AddLiveModule(path, module.get());
if (!module->CreateOutOfProcessModule(render_frame,
diff --git a/chromium/content/renderer/pepper/plugin_module.h b/chromium/content/renderer/pepper/plugin_module.h
index dd25ecf8cb7..535ee257649 100644
--- a/chromium/content/renderer/pepper/plugin_module.h
+++ b/chromium/content/renderer/pepper/plugin_module.h
@@ -70,6 +70,7 @@ class CONTENT_EXPORT PluginModule : public base::RefCounted<PluginModule>,
// all plugin modules. In practice it will be a global singleton that
// tracks which modules are alive.
PluginModule(const std::string& name,
+ const std::string& version,
const base::FilePath& path,
const ppapi::PpapiPermissions& perms);
@@ -134,6 +135,7 @@ class CONTENT_EXPORT PluginModule : public base::RefCounted<PluginModule>,
PP_Module pp_module() const { return pp_module_; }
const std::string& name() const { return name_; }
+ const std::string& version() const { return version_; }
const base::FilePath& path() const { return path_; }
const ppapi::PpapiPermissions& permissions() const { return permissions_; }
@@ -256,8 +258,9 @@ class CONTENT_EXPORT PluginModule : public base::RefCounted<PluginModule>,
// presence of the host_dispatcher_wrapper_ value.
PepperPluginInfo::EntryPoints entry_points_;
- // The name and file location of the module.
+ // The name, version, and file location of the module.
const std::string name_;
+ const std::string version_;
const base::FilePath path_;
ppapi::PpapiPermissions permissions_;
diff --git a/chromium/content/renderer/pepper/plugin_object.cc b/chromium/content/renderer/pepper/plugin_object.cc
index 6de7ce19efb..729b4801452 100644
--- a/chromium/content/renderer/pepper/plugin_object.cc
+++ b/chromium/content/renderer/pepper/plugin_object.cc
@@ -4,14 +4,23 @@
#include "content/renderer/pepper/plugin_object.h"
+#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "content/renderer/pepper/npapi_glue.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_try_catch.h"
#include "content/renderer/pepper/plugin_module.h"
+#include "content/renderer/pepper/v8_var_converter.h"
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/function_template.h"
+#include "gin/handle.h"
+#include "gin/interceptor.h"
+#include "gin/object_template_builder.h"
+#include "gin/public/gin_embedders.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/c/dev/ppp_class_deprecated.h"
#include "ppapi/c/pp_resource.h"
@@ -20,14 +29,12 @@
#include "ppapi/shared_impl/resource_tracker.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/npruntime.h"
using ppapi::PpapiGlobals;
+using ppapi::ScopedPPVar;
+using ppapi::ScopedPPVarArray;
using ppapi::StringVar;
using ppapi::Var;
-using blink::WebBindings;
namespace content {
@@ -35,332 +42,230 @@ namespace {
const char kInvalidValueException[] = "Error: Invalid value";
-// NPObject implementation in terms of PPP_Class_Deprecated --------------------
+} // namespace
-NPObject* WrapperClass_Allocate(NPP npp, NPClass* unused) {
- return PluginObject::AllocateObjectWrapper();
-}
+// PluginObject ----------------------------------------------------------------
-void WrapperClass_Deallocate(NPObject* np_object) {
- PluginObject* plugin_object = PluginObject::FromNPObject(np_object);
- if (plugin_object) {
- plugin_object->ppp_class()->Deallocate(plugin_object->ppp_class_data());
- delete plugin_object;
+PluginObject::~PluginObject() {
+ if (instance_) {
+ ppp_class_->Deallocate(ppp_class_data_);
+ instance_->RemovePluginObject(this);
}
- delete np_object;
}
-void WrapperClass_Invalidate(NPObject* object) {}
-
-bool WrapperClass_HasMethod(NPObject* object, NPIdentifier method_name) {
- NPObjectAccessorWithIdentifier accessor(object, method_name, false);
- if (!accessor.is_valid())
- return false;
+// static
+gin::WrapperInfo PluginObject::kWrapperInfo = {gin::kEmbedderNativeGin};
- PPResultAndExceptionToNPResult result_converter(
- accessor.object()->GetNPObject(), NULL);
- bool rv = accessor.object()->ppp_class()->HasMethod(
- accessor.object()->ppp_class_data(),
- accessor.identifier(),
- result_converter.exception());
- result_converter.CheckExceptionForNoResult();
- return rv;
+// static
+PluginObject* PluginObject::FromV8Object(v8::Isolate* isolate,
+ v8::Handle<v8::Object> v8_object) {
+ PluginObject* plugin_object;
+ if (!v8_object.IsEmpty() &&
+ gin::ConvertFromV8(isolate, v8_object, &plugin_object)) {
+ return plugin_object;
+ }
+ return NULL;
}
-bool WrapperClass_Invoke(NPObject* object,
- NPIdentifier method_name,
- const NPVariant* argv,
- uint32_t argc,
- NPVariant* result) {
- NPObjectAccessorWithIdentifier accessor(object, method_name, false);
- if (!accessor.is_valid())
- return false;
-
- PPResultAndExceptionToNPResult result_converter(
- accessor.object()->GetNPObject(), result);
- PPVarArrayFromNPVariantArray args(accessor.object()->instance(), argc, argv);
-
- // For the OOP plugin case we need to grab a reference on the plugin module
- // object to ensure that it is not destroyed courtsey an incoming
- // ExecuteScript call which destroys the plugin module and in turn the
- // dispatcher.
- scoped_refptr<PluginModule> ref(accessor.object()->instance()->module());
-
- return result_converter.SetResult(
- accessor.object()->ppp_class()->Call(accessor.object()->ppp_class_data(),
- accessor.identifier(),
- argc,
- args.array(),
- result_converter.exception()));
+// static
+PP_Var PluginObject::Create(PepperPluginInstanceImpl* instance,
+ const PPP_Class_Deprecated* ppp_class,
+ void* ppp_class_data) {
+ V8VarConverter var_converter(instance->pp_instance(),
+ V8VarConverter::kAllowObjectVars);
+ PepperTryCatchVar try_catch(instance, &var_converter, NULL);
+ gin::Handle<PluginObject> object =
+ gin::CreateHandle(instance->GetIsolate(),
+ new PluginObject(instance, ppp_class, ppp_class_data));
+ ScopedPPVar result = try_catch.FromV8(object.ToV8());
+ DCHECK(!try_catch.HasException());
+ return result.Release();
}
-bool WrapperClass_InvokeDefault(NPObject* np_object,
- const NPVariant* argv,
- uint32_t argc,
- NPVariant* result) {
- PluginObject* obj = PluginObject::FromNPObject(np_object);
- if (!obj)
- return false;
-
- PPVarArrayFromNPVariantArray args(obj->instance(), argc, argv);
- PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result);
-
- // For the OOP plugin case we need to grab a reference on the plugin module
- // object to ensure that it is not destroyed courtsey an incoming
- // ExecuteScript call which destroys the plugin module and in turn the
- // dispatcher.
- scoped_refptr<PluginModule> ref(obj->instance()->module());
-
- result_converter.SetResult(
- obj->ppp_class()->Call(obj->ppp_class_data(),
- PP_MakeUndefined(),
- argc,
- args.array(),
- result_converter.exception()));
- return result_converter.success();
+v8::Local<v8::Value> PluginObject::GetNamedProperty(
+ v8::Isolate* isolate,
+ const std::string& identifier) {
+ ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
+ StringVar::StringToPPVar(identifier));
+ return GetPropertyOrMethod(instance_->GetIsolate(), identifier_var.get());
}
-bool WrapperClass_HasProperty(NPObject* object, NPIdentifier property_name) {
- NPObjectAccessorWithIdentifier accessor(object, property_name, true);
- if (!accessor.is_valid())
+bool PluginObject::SetNamedProperty(v8::Isolate* isolate,
+ const std::string& identifier,
+ v8::Local<v8::Value> value) {
+ if (!instance_)
return false;
-
- PPResultAndExceptionToNPResult result_converter(
- accessor.object()->GetNPObject(), NULL);
- bool rv = accessor.object()->ppp_class()->HasProperty(
- accessor.object()->ppp_class_data(),
- accessor.identifier(),
- result_converter.exception());
- result_converter.CheckExceptionForNoResult();
- return rv;
-}
-
-bool WrapperClass_GetProperty(NPObject* object,
- NPIdentifier property_name,
- NPVariant* result) {
- NPObjectAccessorWithIdentifier accessor(object, property_name, true);
- if (!accessor.is_valid())
+ ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
+ StringVar::StringToPPVar(identifier));
+ V8VarConverter var_converter(instance_->pp_instance(),
+ V8VarConverter::kAllowObjectVars);
+ PepperTryCatchV8 try_catch(instance_, &var_converter, isolate);
+
+ bool has_property =
+ ppp_class_->HasProperty(ppp_class_data_, identifier_var.get(),
+ try_catch.exception());
+ if (try_catch.ThrowException())
return false;
- PPResultAndExceptionToNPResult result_converter(
- accessor.object()->GetNPObject(), result);
- return result_converter.SetResult(accessor.object()->ppp_class()->GetProperty(
- accessor.object()->ppp_class_data(),
- accessor.identifier(),
- result_converter.exception()));
-}
-
-bool WrapperClass_SetProperty(NPObject* object,
- NPIdentifier property_name,
- const NPVariant* value) {
- NPObjectAccessorWithIdentifier accessor(object, property_name, true);
- if (!accessor.is_valid())
+ if (!has_property)
return false;
- PPResultAndExceptionToNPResult result_converter(
- accessor.object()->GetNPObject(), NULL);
- PP_Var value_var = NPVariantToPPVar(accessor.object()->instance(), value);
- accessor.object()->ppp_class()->SetProperty(
- accessor.object()->ppp_class_data(),
- accessor.identifier(),
- value_var,
- result_converter.exception());
- PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(value_var);
- return result_converter.CheckExceptionForNoResult();
-}
-
-bool WrapperClass_RemoveProperty(NPObject* object, NPIdentifier property_name) {
- NPObjectAccessorWithIdentifier accessor(object, property_name, true);
- if (!accessor.is_valid())
+ ScopedPPVar var = try_catch.FromV8(value);
+ if (try_catch.ThrowException())
return false;
- PPResultAndExceptionToNPResult result_converter(
- accessor.object()->GetNPObject(), NULL);
- accessor.object()->ppp_class()->RemoveProperty(
- accessor.object()->ppp_class_data(),
- accessor.identifier(),
- result_converter.exception());
- return result_converter.CheckExceptionForNoResult();
-}
+ ppp_class_->SetProperty(ppp_class_data_, identifier_var.get(), var.get(),
+ try_catch.exception());
-bool WrapperClass_Enumerate(NPObject* object,
- NPIdentifier** values,
- uint32_t* count) {
- *values = NULL;
- *count = 0;
- PluginObject* obj = PluginObject::FromNPObject(object);
- if (!obj)
- return false;
+ // If the plugin threw an exception, then throw a V8 version of it to
+ // JavaScript. Either way, return true, because we successfully dispatched
+ // the call to the plugin.
+ try_catch.ThrowException();
+ return true;
+}
- uint32_t property_count = 0;
- PP_Var* properties = NULL; // Must be freed!
- PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), NULL);
- obj->ppp_class()->GetAllPropertyNames(obj->ppp_class_data(),
- &property_count,
- &properties,
- result_converter.exception());
-
- // Convert the array of PP_Var to an array of NPIdentifiers. If any
- // conversions fail, we will set the exception.
- if (!result_converter.has_exception()) {
- if (property_count > 0) {
- *values = static_cast<NPIdentifier*>(
- calloc(property_count, sizeof(NPIdentifier)));
- *count = 0; // Will be the number of items successfully converted.
- for (uint32_t i = 0; i < property_count; ++i) {
- if (!((*values)[i] = PPVarToNPIdentifier(properties[i]))) {
- // Throw an exception for the failed convertion.
- *result_converter.exception() =
- StringVar::StringToPPVar(kInvalidValueException);
- break;
- }
- (*count)++;
- }
-
- if (result_converter.has_exception()) {
- // We don't actually have to free the identifiers we converted since
- // all identifiers leak anyway :( .
- free(*values);
- *values = NULL;
- *count = 0;
- }
+std::vector<std::string> PluginObject::EnumerateNamedProperties(
+ v8::Isolate* isolate) {
+ std::vector<std::string> result;
+ if (!instance_)
+ return result;
+
+ V8VarConverter var_converter(instance_->pp_instance(),
+ V8VarConverter::kAllowObjectVars);
+ PepperTryCatchV8 try_catch(instance_, &var_converter, isolate);
+
+ PP_Var* name_vars;
+ uint32_t count = 0;
+ ppp_class_->GetAllPropertyNames(ppp_class_data_, &count, &name_vars,
+ try_catch.exception());
+ ScopedPPVarArray scoped_name_vars(
+ ScopedPPVarArray::PassPPBMemoryAllocatedArray(), name_vars, count);
+
+ if (try_catch.ThrowException())
+ return result;
+
+ for (uint32_t i = 0; i < count; ++i) {
+ StringVar* string_var = StringVar::FromPPVar(name_vars[i]);
+ if (string_var) {
+ result.push_back(string_var->value());
+ } else {
+ try_catch.ThrowException(kInvalidValueException);
+ result.clear();
+ return result;
}
}
- // This will actually throw the exception, either from GetAllPropertyNames,
- // or if anything was set during the conversion process.
- result_converter.CheckExceptionForNoResult();
-
- // Release the PP_Var that the plugin allocated. On success, they will all
- // be converted to NPVariants, and on failure, we want them to just go away.
- ppapi::VarTracker* var_tracker = PpapiGlobals::Get()->GetVarTracker();
- for (uint32_t i = 0; i < property_count; ++i)
- var_tracker->ReleaseVar(properties[i]);
- free(properties);
- return result_converter.success();
+ return result;
}
-bool WrapperClass_Construct(NPObject* object,
- const NPVariant* argv,
- uint32_t argc,
- NPVariant* result) {
- PluginObject* obj = PluginObject::FromNPObject(object);
- if (!obj)
- return false;
-
- PPVarArrayFromNPVariantArray args(obj->instance(), argc, argv);
- PPResultAndExceptionToNPResult result_converter(obj->GetNPObject(), result);
- return result_converter.SetResult(obj->ppp_class()->Construct(
- obj->ppp_class_data(), argc, args.array(), result_converter.exception()));
+void PluginObject::InstanceDeleted() {
+ instance_ = NULL;
}
-const NPClass wrapper_class = {
- NP_CLASS_STRUCT_VERSION, WrapperClass_Allocate,
- WrapperClass_Deallocate, WrapperClass_Invalidate,
- WrapperClass_HasMethod, WrapperClass_Invoke,
- WrapperClass_InvokeDefault, WrapperClass_HasProperty,
- WrapperClass_GetProperty, WrapperClass_SetProperty,
- WrapperClass_RemoveProperty, WrapperClass_Enumerate,
- WrapperClass_Construct};
-
-} // namespace
-
-// PluginObject ----------------------------------------------------------------
-
-struct PluginObject::NPObjectWrapper : public NPObject {
- // Points to the var object that owns this wrapper. This value may be NULL
- // if there is no var owning this wrapper. This can happen if the plugin
- // releases all references to the var, but a reference to the underlying
- // NPObject is still held by script on the page.
- PluginObject* obj;
-};
-
PluginObject::PluginObject(PepperPluginInstanceImpl* instance,
- NPObjectWrapper* object_wrapper,
const PPP_Class_Deprecated* ppp_class,
void* ppp_class_data)
- : instance_(instance),
- object_wrapper_(object_wrapper),
+ : gin::NamedPropertyInterceptor(instance->GetIsolate(), this),
+ instance_(instance),
ppp_class_(ppp_class),
- ppp_class_data_(ppp_class_data) {
- // Make the object wrapper refer back to this class so our NPObject
- // implementation can call back into the Pepper layer.
- object_wrapper_->obj = this;
+ ppp_class_data_(ppp_class_data),
+ weak_factory_(this) {
instance_->AddPluginObject(this);
}
-PluginObject::~PluginObject() {
- // The wrapper we made for this NPObject may still have a reference to it
- // from JavaScript, so we clear out its ObjectVar back pointer which will
- // cause all calls "up" to the plugin to become NOPs. Our ObjectVar base
- // class will release our reference to the object, which may or may not
- // delete the NPObject.
- DCHECK(object_wrapper_->obj == this);
- object_wrapper_->obj = NULL;
- instance_->RemovePluginObject(this);
+gin::ObjectTemplateBuilder PluginObject::GetObjectTemplateBuilder(
+ v8::Isolate* isolate) {
+ return Wrappable<PluginObject>::GetObjectTemplateBuilder(isolate)
+ .AddNamedPropertyInterceptor();
}
-PP_Var PluginObject::Create(PepperPluginInstanceImpl* instance,
- const PPP_Class_Deprecated* ppp_class,
- void* ppp_class_data) {
- // This will internally end up calling our AllocateObjectWrapper via the
- // WrapperClass_Allocated function which will have created an object wrapper
- // appropriate for this class (derived from NPObject).
- NPObjectWrapper* wrapper =
- static_cast<NPObjectWrapper*>(WebBindings::createObject(
- instance->instanceNPP(), const_cast<NPClass*>(&wrapper_class)));
-
- // This object will register itself both with the NPObject and with the
- // PluginModule. The NPObject will normally handle its lifetime, and it
- // will get deleted in the destroy method. It may also get deleted when the
- // plugin module is deallocated.
- new PluginObject(instance, wrapper, ppp_class, ppp_class_data);
-
- // We can just use a normal ObjectVar to refer to this object from the
- // plugin. It will hold a ref to the underlying NPObject which will in turn
- // hold our pluginObject.
- PP_Var obj_var(NPObjectToPPVar(instance, wrapper));
-
- // Note that the ObjectVar constructor incremented the reference count, and so
- // did WebBindings::createObject above. Now that the PP_Var has taken
- // ownership, we need to release to balance out the createObject reference
- // count bump.
- WebBindings::releaseObject(wrapper);
- return obj_var;
+v8::Local<v8::Value> PluginObject::GetPropertyOrMethod(v8::Isolate* isolate,
+ PP_Var identifier_var) {
+ if (!instance_)
+ return v8::Local<v8::Value>();
+
+ V8VarConverter var_converter(instance_->pp_instance(),
+ V8VarConverter::kAllowObjectVars);
+ PepperTryCatchV8 try_catch(instance_, &var_converter, isolate);
+ bool has_property =
+ ppp_class_->HasProperty(ppp_class_data_, identifier_var,
+ try_catch.exception());
+ if (try_catch.ThrowException())
+ return v8::Local<v8::Value>();
+
+ if (has_property) {
+ ScopedPPVar result_var(ScopedPPVar::PassRef(),
+ ppp_class_->GetProperty(ppp_class_data_, identifier_var,
+ try_catch.exception()));
+ if (try_catch.ThrowException())
+ return v8::Local<v8::Value>();
+
+ v8::Handle<v8::Value> result = try_catch.ToV8(result_var.get());
+ if (try_catch.ThrowException())
+ return v8::Local<v8::Value>();
+
+ return result;
+ }
+
+ bool has_method = identifier_var.type == PP_VARTYPE_STRING &&
+ ppp_class_->HasMethod(ppp_class_data_, identifier_var,
+ try_catch.exception());
+ if (try_catch.ThrowException())
+ return v8::Local<v8::Value>();
+
+ if (has_method) {
+ const std::string& identifier =
+ StringVar::FromPPVar(identifier_var)->value();
+ return gin::CreateFunctionTemplate(isolate,
+ base::Bind(&PluginObject::Call,
+ weak_factory_.GetWeakPtr(),
+ identifier))->GetFunction();
+ }
+
+ return v8::Local<v8::Value>();
}
-NPObject* PluginObject::GetNPObject() const { return object_wrapper_; }
+void PluginObject::Call(const std::string& identifier,
+ gin::Arguments* args) {
+ if (!instance_)
+ return;
+
+ V8VarConverter var_converter(instance_->pp_instance(),
+ V8VarConverter::kAllowObjectVars);
+ PepperTryCatchV8 try_catch(instance_, &var_converter, args->isolate());
+ ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
+ StringVar::StringToPPVar(identifier));
+ ScopedPPVarArray argument_vars(args->Length());
+
+ for (uint32_t i = 0; i < argument_vars.size(); ++i) {
+ v8::Handle<v8::Value> arg;
+ if (!args->GetNext(&arg)) {
+ NOTREACHED();
+ }
-// static
-bool PluginObject::IsInstanceOf(NPObject* np_object,
- const PPP_Class_Deprecated* ppp_class,
- void** ppp_class_data) {
- // Validate that this object is implemented by our wrapper class before
- // trying to get the PluginObject.
- if (np_object->_class != &wrapper_class)
- return false;
+ argument_vars.Set(i, try_catch.FromV8(arg));
+ if (try_catch.ThrowException())
+ return;
+ }
- PluginObject* plugin_object = FromNPObject(np_object);
- if (!plugin_object)
- return false; // Object is no longer alive.
+ // For the OOP plugin case we need to grab a reference on the plugin module
+ // object to ensure that it is not destroyed courtesy an incoming
+ // ExecuteScript call which destroys the plugin module and in turn the
+ // dispatcher.
+ scoped_refptr<PluginModule> ref(instance_->module());
- if (plugin_object->ppp_class() != ppp_class)
- return false;
- if (ppp_class_data)
- *ppp_class_data = plugin_object->ppp_class_data();
- return true;
-}
+ ScopedPPVar result_var(ScopedPPVar::PassRef(),
+ ppp_class_->Call(ppp_class_data_, identifier_var.get(),
+ argument_vars.size(), argument_vars.get(),
+ try_catch.exception()));
+ if (try_catch.ThrowException())
+ return;
-// static
-PluginObject* PluginObject::FromNPObject(NPObject* object) {
- return static_cast<NPObjectWrapper*>(object)->obj;
-}
+ v8::Handle<v8::Value> result = try_catch.ToV8(result_var.get());
+ if (try_catch.ThrowException())
+ return;
-// static
-NPObject* PluginObject::AllocateObjectWrapper() {
- NPObjectWrapper* wrapper = new NPObjectWrapper;
- memset(wrapper, 0, sizeof(NPObjectWrapper));
- return wrapper;
+ args->Return(result);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/plugin_object.h b/chromium/content/renderer/pepper/plugin_object.h
index 62ffd2ebfbd..4dec6205d58 100644
--- a/chromium/content/renderer/pepper/plugin_object.h
+++ b/chromium/content/renderer/pepper/plugin_object.h
@@ -8,11 +8,16 @@
#include <string>
#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "gin/interceptor.h"
+#include "gin/wrappable.h"
+#include "ppapi/c/pp_var.h"
-struct PP_Var;
struct PPP_Class_Deprecated;
-typedef struct NPObject NPObject;
-typedef struct _NPVariant NPVariant;
+
+namespace gin {
+ class Arguments;
+} // namespace gin
namespace content {
@@ -22,9 +27,17 @@ class PepperPluginInstanceImpl;
//
// In contrast, a var of type PP_VARTYPE_OBJECT is a reference to a JS object,
// which might be implemented by the plugin (here) or by the JS engine.
-class PluginObject {
+class PluginObject : public gin::Wrappable<PluginObject>,
+ public gin::NamedPropertyInterceptor {
public:
- virtual ~PluginObject();
+ static gin::WrapperInfo kWrapperInfo;
+
+ ~PluginObject() override;
+
+ // Returns the PluginObject which is contained in the given v8 object, or NULL
+ // if the object isn't backed by a PluginObject.
+ static PluginObject* FromV8Object(v8::Isolate* isolate,
+ v8::Handle<v8::Object> v8_object);
// Allocates a new PluginObject and returns it as a PP_Var with a
// refcount of 1.
@@ -32,61 +45,43 @@ class PluginObject {
const PPP_Class_Deprecated* ppp_class,
void* ppp_class_data);
- PepperPluginInstanceImpl* instance() const { return instance_; }
+ // gin::NamedPropertyInterceptor
+ v8::Local<v8::Value> GetNamedProperty(v8::Isolate* isolate,
+ const std::string& property) override;
+ bool SetNamedProperty(v8::Isolate* isolate,
+ const std::string& property,
+ v8::Local<v8::Value> value) override;
+ std::vector<std::string> EnumerateNamedProperties(
+ v8::Isolate* isolate) override;
const PPP_Class_Deprecated* ppp_class() { return ppp_class_; }
- void* ppp_class_data() {
- return ppp_class_data_;
- };
-
- NPObject* GetNPObject() const;
-
- // Returns true if the given var is an object implemented by the same plugin
- // that owns the var object, and that the class matches. If it matches,
- // returns true and places the class data into |*ppp_class_data| (which can
- // optionally be NULL if no class data is desired).
- static bool IsInstanceOf(NPObject* np_object,
- const PPP_Class_Deprecated* ppp_class,
- void** ppp_class_data);
-
- // Converts the given NPObject to the corresponding ObjectVar.
- //
- // The given NPObject must be one corresponding to a PluginObject or this
- // will crash. If the object is a PluginObject but the plugin has gone
- // away (the object could still be alive because of a reference from JS),
- // then the return value will be NULL.
- static PluginObject* FromNPObject(NPObject* object);
-
- // Allocates a plugin wrapper object and returns it as an NPObject. This is
- // used internally only.
- static NPObject* AllocateObjectWrapper();
+ void* ppp_class_data() { return ppp_class_data_; }
- private:
- struct NPObjectWrapper;
+ // Called when the instance is destroyed.
+ void InstanceDeleted();
- // This object must be created using the CreateObject function of the which
- // will set up the correct NPObject.
- //
- // The NPObjectWrapper (an NPObject) should already have the reference
- // incremented on it, and this class will take ownership of that reference.
+ private:
PluginObject(PepperPluginInstanceImpl* instance,
- NPObjectWrapper* object_wrapper,
const PPP_Class_Deprecated* ppp_class,
void* ppp_class_data);
- PepperPluginInstanceImpl* instance_;
+ // gin::Wrappable
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
+
+ // Helper method to get named properties.
+ v8::Local<v8::Value> GetPropertyOrMethod(v8::Isolate* isolate,
+ PP_Var identifier_var);
- // Holds a pointer to the NPObject wrapper backing the var. This class
- // derives from NPObject and we hold a reference to it, so it must be
- // refcounted. When the type is not an object, this value will be NULL.
- //
- // We don't actually own this pointer, it's the NPObject that actually
- // owns us.
- NPObjectWrapper* object_wrapper_;
+ void Call(const std::string& identifier, gin::Arguments* args);
+
+ PepperPluginInstanceImpl* instance_;
const PPP_Class_Deprecated* ppp_class_;
void* ppp_class_data_;
+ base::WeakPtrFactory<PluginObject> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(PluginObject);
};
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
new file mode 100644
index 00000000000..3c60c16d2db
--- /dev/null
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
@@ -0,0 +1,157 @@
+// Copyright 2014 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/callback.h"
+#include "base/metrics/histogram.h"
+#include "content/common/frame_messages.h"
+#include "content/public/renderer/document_state.h"
+#include "content/public/renderer/navigation_state.h"
+#include "content/public/renderer/render_frame.h"
+#include "content/renderer/pepper/plugin_power_saver_helper.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebView.h"
+
+namespace content {
+
+namespace {
+
+// Initial decision of the peripheral content decision.
+// These numeric values are used in UMA logs; do not change them.
+enum PeripheralHeuristicDecision {
+ HEURISTIC_DECISION_PERIPHERAL = 0,
+ HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN = 1,
+ HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG = 2,
+ HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED = 3,
+ HEURISTIC_DECISION_NUM_ITEMS
+};
+
+const char kPeripheralHeuristicHistogram[] =
+ "Plugin.PowerSaver.PeripheralHeuristic";
+
+// Maximum dimensions plug-in content may have while still being considered
+// peripheral content. These match the sizes used by Safari.
+const int kPeripheralContentMaxWidth = 400;
+const int kPeripheralContentMaxHeight = 300;
+
+void RecordDecisionMetric(PeripheralHeuristicDecision decision) {
+ UMA_HISTOGRAM_ENUMERATION(kPeripheralHeuristicHistogram, decision,
+ HEURISTIC_DECISION_NUM_ITEMS);
+}
+
+} // namespace
+
+PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(
+ const GURL& content_origin,
+ const base::Closure& unthrottle_callback)
+ : content_origin(content_origin), unthrottle_callback(unthrottle_callback) {
+}
+
+PluginPowerSaverHelper::PeripheralPlugin::~PeripheralPlugin() {
+}
+
+PluginPowerSaverHelper::PluginPowerSaverHelper(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame) {
+}
+
+PluginPowerSaverHelper::~PluginPowerSaverHelper() {
+}
+
+void PluginPowerSaverHelper::DidCommitProvisionalLoad(bool is_new_navigation) {
+ blink::WebFrame* frame = render_frame()->GetWebFrame();
+ if (frame->parent())
+ return; // Not a top-level navigation.
+
+ DocumentState* document_state =
+ DocumentState::FromDataSource(frame->dataSource());
+ NavigationState* navigation_state = document_state->navigation_state();
+ if (!navigation_state->was_within_same_page())
+ origin_whitelist_.clear();
+}
+
+bool PluginPowerSaverHelper::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PluginPowerSaverHelper, message)
+ IPC_MESSAGE_HANDLER(FrameMsg_UpdatePluginContentOriginWhitelist,
+ OnUpdatePluginContentOriginWhitelist)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PluginPowerSaverHelper::OnUpdatePluginContentOriginWhitelist(
+ const std::set<GURL>& origin_whitelist) {
+ origin_whitelist_ = origin_whitelist;
+
+ // Check throttled plugin instances to see if any can be unthrottled.
+ auto it = peripheral_plugins_.begin();
+ while (it != peripheral_plugins_.end()) {
+ if (origin_whitelist.count(it->content_origin)) {
+ it->unthrottle_callback.Run();
+ it = peripheral_plugins_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+bool PluginPowerSaverHelper::ShouldThrottleContent(const GURL& content_origin,
+ int width,
+ int height,
+ bool* cross_origin) const {
+ DCHECK(cross_origin);
+ *cross_origin = true;
+
+ // TODO(alexmos): Update this to use the origin of the RemoteFrame when 426512
+ // is fixed. For now, case 3 in the class level comment doesn't work in
+ // --site-per-process mode.
+ blink::WebFrame* main_frame =
+ render_frame()->GetWebFrame()->view()->mainFrame();
+ if (main_frame->isWebRemoteFrame()) {
+ RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL);
+ return true;
+ }
+
+ // All same-origin plugin content is essential.
+ GURL main_frame_origin = GURL(main_frame->document().url()).GetOrigin();
+ if (content_origin == main_frame_origin) {
+ RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_SAME_ORIGIN);
+ *cross_origin = false;
+ return false;
+ }
+
+ // Whitelisted plugin origins are also essential.
+ if (origin_whitelist_.count(content_origin)) {
+ RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_WHITELISTED);
+ return false;
+ }
+
+ // Cross-origin plugin content is peripheral if smaller than a maximum size.
+ bool content_is_small = width < kPeripheralContentMaxWidth ||
+ height < kPeripheralContentMaxHeight;
+
+ if (content_is_small)
+ RecordDecisionMetric(HEURISTIC_DECISION_PERIPHERAL);
+ else
+ RecordDecisionMetric(HEURISTIC_DECISION_ESSENTIAL_CROSS_ORIGIN_BIG);
+
+ return content_is_small;
+}
+
+void PluginPowerSaverHelper::RegisterPeripheralPlugin(
+ const GURL& content_origin,
+ const base::Closure& unthrottle_callback) {
+ peripheral_plugins_.push_back(
+ PeripheralPlugin(content_origin, unthrottle_callback));
+}
+
+void PluginPowerSaverHelper::WhitelistContentOrigin(
+ const GURL& content_origin) {
+ if (origin_whitelist_.insert(content_origin).second) {
+ Send(new FrameHostMsg_PluginContentOriginAllowed(
+ render_frame()->GetRoutingID(), content_origin));
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.h b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
new file mode 100644
index 00000000000..e4678a63464
--- /dev/null
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
@@ -0,0 +1,77 @@
+// Copyright 2014 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 CONTENT_RENDERER_PEPPER_PLUGIN_POWER_SAVER_HELPER_H_
+#define CONTENT_RENDERER_PEPPER_PLUGIN_POWER_SAVER_HELPER_H_
+
+#include <set>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// PluginPowerSaverWhitelist manages the plugin content origin whitelist for
+// a single render frame.
+class CONTENT_EXPORT PluginPowerSaverHelper : public RenderFrameObserver {
+ public:
+ explicit PluginPowerSaverHelper(RenderFrame* render_frame);
+ virtual ~PluginPowerSaverHelper();
+
+ // Returns true if this plugin should have power saver enabled.
+ //
+ // Power Saver is enabled for plugin content that are cross-origin and
+ // heuristically determined to be not the "main attraction" of the webpage.
+ //
+ // Plugin content is defined to be cross-origin when the plugin source's
+ // origin differs from the top level frame's origin. For example:
+ // - Cross-origin: a.com -> b.com/plugin.swf
+ // - Cross-origin: a.com -> b.com/iframe.html -> b.com/plugin.swf
+ // - Same-origin: a.com -> b.com/iframe-to-a.html -> a.com/plugin.swf
+ //
+ // |cross_origin| may not be NULL.
+ bool ShouldThrottleContent(const GURL& content_origin,
+ int width,
+ int height,
+ bool* cross_origin) const;
+
+ // Registers a plugin that has been marked peripheral. If the origin
+ // whitelist is later updated and includes |content_origin|, then
+ // |unthrottle_callback| will be called.
+ void RegisterPeripheralPlugin(const GURL& content_origin,
+ const base::Closure& unthrottle_callback);
+
+ void WhitelistContentOrigin(const GURL& content_origin);
+
+ private:
+ struct PeripheralPlugin {
+ PeripheralPlugin(const GURL& content_origin,
+ const base::Closure& unthrottle_callback);
+ ~PeripheralPlugin();
+
+ GURL content_origin;
+ base::Closure unthrottle_callback;
+ };
+
+ // RenderFrameObserver implementation.
+ void DidCommitProvisionalLoad(bool is_new_navigation) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnUpdatePluginContentOriginWhitelist(
+ const std::set<GURL>& origin_whitelist);
+
+ // Local copy of the whitelist for the entire tab.
+ std::set<GURL> origin_whitelist_;
+
+ // Set of peripheral plugins eligible to be unthrottled ex post facto.
+ std::vector<PeripheralPlugin> peripheral_plugins_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginPowerSaverHelper);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PLUGIN_POWER_SAVER_HELPER_H_
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
new file mode 100644
index 00000000000..0cdec0f3140
--- /dev/null
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper_browsertest.cc
@@ -0,0 +1,116 @@
+// Copyright 2014 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/run_loop.h"
+#include "content/common/frame_messages.h"
+#include "content/common/view_message_enums.h"
+#include "content/public/test/render_view_test.h"
+#include "content/renderer/pepper/plugin_power_saver_helper.h"
+#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/render_view_impl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class PluginPowerSaverHelperTest : public RenderViewTest {
+ public:
+ PluginPowerSaverHelperTest() : sink_(NULL) {}
+
+ RenderFrameImpl* frame() {
+ return static_cast<RenderFrameImpl*>(view_->GetMainRenderFrame());
+ }
+
+ PluginPowerSaverHelper* power_saver_helper() {
+ return frame()->plugin_power_saver_helper();
+ }
+
+ void SetUp() override {
+ RenderViewTest::SetUp();
+ sink_ = &render_thread_->sink();
+ }
+
+ protected:
+ IPC::TestSink* sink_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginPowerSaverHelperTest);
+};
+
+TEST_F(PluginPowerSaverHelperTest, AllowSameOrigin) {
+ bool cross_origin = false;
+ EXPECT_FALSE(power_saver_helper()->ShouldThrottleContent(
+ GURL(), 100, 100, &cross_origin));
+ EXPECT_FALSE(cross_origin);
+
+ EXPECT_FALSE(power_saver_helper()->ShouldThrottleContent(
+ GURL(), 1000, 1000, &cross_origin));
+ EXPECT_FALSE(cross_origin);
+}
+
+TEST_F(PluginPowerSaverHelperTest, DisallowCrossOriginUnlessLarge) {
+ bool cross_origin = false;
+ EXPECT_TRUE(power_saver_helper()->ShouldThrottleContent(
+ GURL("http://other.com"), 100, 100, &cross_origin));
+ EXPECT_TRUE(cross_origin);
+
+ EXPECT_FALSE(power_saver_helper()->ShouldThrottleContent(
+ GURL("http://other.com"), 1000, 1000, &cross_origin));
+ EXPECT_TRUE(cross_origin);
+}
+
+TEST_F(PluginPowerSaverHelperTest, TemporaryOriginWhitelist) {
+ bool cross_origin = false;
+ EXPECT_TRUE(power_saver_helper()->ShouldThrottleContent(
+ GURL("http://other.com"), 100, 100, &cross_origin));
+ EXPECT_TRUE(cross_origin);
+
+ // Clear out other messages so we find just the plugin power saver IPCs.
+ sink_->ClearMessages();
+
+ power_saver_helper()->WhitelistContentOrigin(GURL("http://other.com"));
+ EXPECT_FALSE(power_saver_helper()->ShouldThrottleContent(
+ GURL("http://other.com"), 100, 100, &cross_origin));
+ EXPECT_TRUE(cross_origin);
+
+ // Test that we've sent an IPC to the browser.
+ ASSERT_EQ(1u, sink_->message_count());
+ const IPC::Message* msg = sink_->GetMessageAt(0);
+ EXPECT_EQ(FrameHostMsg_PluginContentOriginAllowed::ID, msg->type());
+ FrameHostMsg_PluginContentOriginAllowed::Param params;
+ FrameHostMsg_PluginContentOriginAllowed::Read(msg, &params);
+ EXPECT_EQ(GURL("http://other.com"), params.a);
+}
+
+TEST_F(PluginPowerSaverHelperTest, UnthrottleOnExPostFactoWhitelist) {
+ base::RunLoop loop;
+ power_saver_helper()->RegisterPeripheralPlugin(GURL("http://other.com"),
+ loop.QuitClosure());
+
+ std::set<GURL> origin_whitelist;
+ origin_whitelist.insert(GURL("http://other.com"));
+ frame()->OnMessageReceived(FrameMsg_UpdatePluginContentOriginWhitelist(
+ frame()->GetRoutingID(), origin_whitelist));
+
+ // Runs until the unthrottle closure is run.
+ loop.Run();
+}
+
+TEST_F(PluginPowerSaverHelperTest, ClearWhitelistOnNavigate) {
+ power_saver_helper()->WhitelistContentOrigin(GURL("http://other.com"));
+
+ bool cross_origin = false;
+ EXPECT_FALSE(power_saver_helper()->ShouldThrottleContent(
+ GURL("http://other.com"), 100, 100, &cross_origin));
+ EXPECT_TRUE(cross_origin);
+
+ LoadHTML("<html></html>");
+
+ EXPECT_TRUE(power_saver_helper()->ShouldThrottleContent(
+ GURL("http://other.com"), 100, 100, &cross_origin));
+ EXPECT_TRUE(cross_origin);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/ppapi_preferences_builder.cc b/chromium/content/renderer/pepper/ppapi_preferences_builder.cc
new file mode 100644
index 00000000000..34d3f4355d6
--- /dev/null
+++ b/chromium/content/renderer/pepper/ppapi_preferences_builder.cc
@@ -0,0 +1,32 @@
+// Copyright 2014 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 "content/renderer/pepper/ppapi_preferences_builder.h"
+
+#include "content/public/common/web_preferences.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+
+namespace content {
+
+ppapi::Preferences PpapiPreferencesBuilder::Build(
+ const WebPreferences& prefs) {
+ ppapi::Preferences ppapi_prefs;
+ ppapi_prefs.standard_font_family_map = prefs.standard_font_family_map;
+ ppapi_prefs.fixed_font_family_map = prefs.fixed_font_family_map;
+ ppapi_prefs.serif_font_family_map = prefs.serif_font_family_map;
+ ppapi_prefs.sans_serif_font_family_map = prefs.sans_serif_font_family_map;
+ ppapi_prefs.default_font_size = prefs.default_font_size;
+ ppapi_prefs.default_fixed_font_size = prefs.default_fixed_font_size;
+ ppapi_prefs.number_of_cpu_cores = prefs.number_of_cpu_cores;
+ ppapi_prefs.is_3d_supported = prefs.flash_3d_enabled;
+ ppapi_prefs.is_stage3d_supported = prefs.flash_stage3d_enabled;
+ ppapi_prefs.is_stage3d_baseline_supported =
+ prefs.flash_stage3d_baseline_enabled;
+ ppapi_prefs.is_webgl_supported = prefs.experimental_webgl_enabled;
+ ppapi_prefs.is_accelerated_video_decode_enabled =
+ prefs.pepper_accelerated_video_decode_enabled;
+ return ppapi_prefs;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/pepper/ppapi_preferences_builder.h b/chromium/content/renderer/pepper/ppapi_preferences_builder.h
new file mode 100644
index 00000000000..6a8004accaf
--- /dev/null
+++ b/chromium/content/renderer/pepper/ppapi_preferences_builder.h
@@ -0,0 +1,23 @@
+// Copyright 2014 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 CONTENT_RENDERER_PEPPER_PPAPI_PREFERENCES_BUILDER_H_
+#define CONTENT_RENDERER_PEPPER_PPAPI_PREFERENCES_BUILDER_H_
+
+namespace ppapi {
+struct Preferences;
+}
+
+namespace content {
+
+struct WebPreferences;
+
+class PpapiPreferencesBuilder {
+ public:
+ static ppapi::Preferences Build(const WebPreferences& prefs);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PEPPER_PPAPI_PREFERENCES_BUILDER_H_
diff --git a/chromium/content/renderer/pepper/ppb_audio_impl.cc b/chromium/content/renderer/pepper/ppb_audio_impl.cc
index 652c697c27a..6db6edf410d 100644
--- a/chromium/content/renderer/pepper/ppb_audio_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_audio_impl.cc
@@ -5,7 +5,6 @@
#include "content/renderer/pepper/ppb_audio_impl.h"
#include "base/logging.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/pepper_platform_audio_output.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_frame_impl.h"
@@ -58,7 +57,7 @@ PP_Bool PPB_Audio_Impl::StartPlayback() {
if (playing())
return PP_TRUE;
SetStartPlaybackState();
- return BoolToPPBool(audio_->StartPlayback());
+ return PP_FromBool(audio_->StartPlayback());
}
PP_Bool PPB_Audio_Impl::StopPlayback() {
diff --git a/chromium/content/renderer/pepper/ppb_audio_impl.h b/chromium/content/renderer/pepper/ppb_audio_impl.h
index ecd49eb8438..3348527028e 100644
--- a/chromium/content/renderer/pepper/ppb_audio_impl.h
+++ b/chromium/content/renderer/pepper/ppb_audio_impl.h
@@ -33,25 +33,24 @@ class PPB_Audio_Impl : public ppapi::Resource,
explicit PPB_Audio_Impl(PP_Instance instance);
// Resource overrides.
- virtual ppapi::thunk::PPB_Audio_API* AsPPB_Audio_API() OVERRIDE;
+ ppapi::thunk::PPB_Audio_API* AsPPB_Audio_API() override;
// PPB_Audio_API implementation.
- virtual PP_Resource GetCurrentConfig() OVERRIDE;
- virtual PP_Bool StartPlayback() OVERRIDE;
- virtual PP_Bool StopPlayback() OVERRIDE;
- virtual int32_t Open(PP_Resource config_id,
- scoped_refptr<ppapi::TrackedCallback> create_callback)
- OVERRIDE;
- virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE;
- virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE;
+ PP_Resource GetCurrentConfig() override;
+ PP_Bool StartPlayback() override;
+ PP_Bool StopPlayback() override;
+ int32_t Open(PP_Resource config_id,
+ scoped_refptr<ppapi::TrackedCallback> create_callback) override;
+ int32_t GetSyncSocket(int* sync_socket) override;
+ int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) override;
private:
- virtual ~PPB_Audio_Impl();
+ ~PPB_Audio_Impl() override;
// AudioHelper implementation.
- virtual void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle,
- size_t shared_memory_size_,
- base::SyncSocket::Handle socket) OVERRIDE;
+ void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle,
+ size_t shared_memory_size_,
+ base::SyncSocket::Handle socket) override;
// AudioConfig used for creating this Audio object. We own a ref.
ppapi::ScopedPPResource config_;
diff --git a/chromium/content/renderer/pepper/ppb_broker_impl.cc b/chromium/content/renderer/pepper/ppb_broker_impl.cc
index f75d56c53d4..33181a25d6d 100644
--- a/chromium/content/renderer/pepper/ppb_broker_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_broker_impl.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "content/common/view_messages.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_broker.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
diff --git a/chromium/content/renderer/pepper/ppb_broker_impl.h b/chromium/content/renderer/pepper/ppb_broker_impl.h
index 0e77218b20f..0f7485535d5 100644
--- a/chromium/content/renderer/pepper/ppb_broker_impl.h
+++ b/chromium/content/renderer/pepper/ppb_broker_impl.h
@@ -33,12 +33,12 @@ class PPB_Broker_Impl : public ppapi::Resource,
explicit PPB_Broker_Impl(PP_Instance instance);
// Resource override.
- virtual ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() OVERRIDE;
+ ppapi::thunk::PPB_Broker_API* AsPPB_Broker_API() override;
// PPB_BrokerTrusted implementation.
- virtual int32_t Connect(
- scoped_refptr<ppapi::TrackedCallback> connect_callback) OVERRIDE;
- virtual int32_t GetHandle(int32_t* handle) OVERRIDE;
+ int32_t Connect(
+ scoped_refptr<ppapi::TrackedCallback> connect_callback) override;
+ int32_t GetHandle(int32_t* handle) override;
// Returns the URL of the document this plug-in runs in. This is necessary to
// decide whether to grant access to the PPAPI broker.
@@ -47,10 +47,10 @@ class PPB_Broker_Impl : public ppapi::Resource,
void BrokerConnected(int32_t handle, int32_t result);
private:
- virtual ~PPB_Broker_Impl();
+ ~PPB_Broker_Impl() override;
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnPpapiBrokerChannelCreated(base::ProcessId broker_pid,
const IPC::ChannelHandle& handle);
diff --git a/chromium/content/renderer/pepper/ppb_buffer_impl.cc b/chromium/content/renderer/pepper/ppb_buffer_impl.cc
index 453e7168719..4ad4b2824d9 100644
--- a/chromium/content/renderer/pepper/ppb_buffer_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_buffer_impl.cc
@@ -8,9 +8,9 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/render_thread_impl.h"
#include "ppapi/c/dev/ppb_buffer_dev.h"
+#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
diff --git a/chromium/content/renderer/pepper/ppb_buffer_impl.h b/chromium/content/renderer/pepper/ppb_buffer_impl.h
index 76526229a4a..b2067809a2b 100644
--- a/chromium/content/renderer/pepper/ppb_buffer_impl.h
+++ b/chromium/content/renderer/pepper/ppb_buffer_impl.h
@@ -27,19 +27,19 @@ class PPB_Buffer_Impl : public ppapi::Resource,
uint32_t size() const { return size_; }
// Resource overrides.
- virtual ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() OVERRIDE;
+ ppapi::thunk::PPB_Buffer_API* AsPPB_Buffer_API() override;
// PPB_Buffer_API implementation.
- virtual PP_Bool Describe(uint32_t* size_in_bytes) OVERRIDE;
- virtual PP_Bool IsMapped() OVERRIDE;
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
+ PP_Bool Describe(uint32_t* size_in_bytes) override;
+ PP_Bool IsMapped() override;
+ void* Map() override;
+ void Unmap() override;
// Trusted.
- virtual int32_t GetSharedMemory(int* handle) OVERRIDE;
+ int32_t GetSharedMemory(int* handle) override;
private:
- virtual ~PPB_Buffer_Impl();
+ ~PPB_Buffer_Impl() override;
explicit PPB_Buffer_Impl(PP_Instance instance);
bool Init(uint32_t size);
diff --git a/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.h b/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.h
index b26d4ce23f6..29c4e1b1665 100644
--- a/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.h
+++ b/chromium/content/renderer/pepper/ppb_flash_message_loop_impl.h
@@ -20,20 +20,19 @@ class PPB_Flash_MessageLoop_Impl
static PP_Resource Create(PP_Instance instance);
// Resource.
- virtual ppapi::thunk::PPB_Flash_MessageLoop_API* AsPPB_Flash_MessageLoop_API()
- OVERRIDE;
+ ppapi::thunk::PPB_Flash_MessageLoop_API* AsPPB_Flash_MessageLoop_API()
+ override;
// PPB_Flash_MessageLoop_API implementation.
- virtual int32_t Run() OVERRIDE;
- virtual void Quit() OVERRIDE;
- virtual void RunFromHostProxy(const RunFromHostProxyCallback& callback)
- OVERRIDE;
+ int32_t Run() override;
+ void Quit() override;
+ void RunFromHostProxy(const RunFromHostProxyCallback& callback) override;
private:
class State;
explicit PPB_Flash_MessageLoop_Impl(PP_Instance instance);
- virtual ~PPB_Flash_MessageLoop_Impl();
+ ~PPB_Flash_MessageLoop_Impl() override;
// If |callback| is valid, it will be called when the message loop is signaled
// to quit, and the result passed into it will be the same value as what this
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
index d40f2202ebb..12d1db923a1 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -11,6 +11,7 @@
#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/web_preferences.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
@@ -25,7 +26,6 @@
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "webkit/common/webpreferences.h"
using ppapi::thunk::EnterResourceNoLock;
using ppapi::thunk::PPB_Graphics3D_API;
@@ -81,9 +81,12 @@ PP_Resource PPB_Graphics3D_Impl::Create(PP_Instance instance,
}
// static
-PP_Resource PPB_Graphics3D_Impl::CreateRaw(PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list) {
+PP_Resource PPB_Graphics3D_Impl::CreateRaw(
+ PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state_handle) {
PPB_Graphics3D_API* share_api = NULL;
if (share_context) {
EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
@@ -93,7 +96,8 @@ PP_Resource PPB_Graphics3D_Impl::CreateRaw(PP_Instance instance,
}
scoped_refptr<PPB_Graphics3D_Impl> graphics_3d(
new PPB_Graphics3D_Impl(instance));
- if (!graphics_3d->InitRaw(share_api, attrib_list))
+ if (!graphics_3d->InitRaw(share_api, attrib_list, capabilities,
+ shared_state_handle))
return 0;
return graphics_3d->GetReference();
}
@@ -137,6 +141,14 @@ uint32_t PPB_Graphics3D_Impl::InsertSyncPoint() {
return command_buffer_->InsertSyncPoint();
}
+uint32_t PPB_Graphics3D_Impl::InsertFutureSyncPoint() {
+ return command_buffer_->InsertFutureSyncPoint();
+}
+
+void PPB_Graphics3D_Impl::RetireSyncPoint(uint32_t sync_point) {
+ return command_buffer_->RetireSyncPoint(sync_point);
+}
+
bool PPB_Graphics3D_Impl::BindToInstance(bool bind) {
bound_to_instance_ = bind;
return true;
@@ -190,8 +202,10 @@ int32 PPB_Graphics3D_Impl::DoSwapBuffers() {
commit_pending_ = true;
} else {
// Wait for the command to complete on the GPU to allow for throttling.
- command_buffer_->Echo(base::Bind(&PPB_Graphics3D_Impl::OnSwapBuffers,
- weak_ptr_factory_.GetWeakPtr()));
+ command_buffer_->SignalSyncPoint(
+ sync_point_,
+ base::Bind(&PPB_Graphics3D_Impl::OnSwapBuffers,
+ weak_ptr_factory_.GetWeakPtr()));
}
return PP_OK_COMPLETIONPENDING;
@@ -199,7 +213,7 @@ int32 PPB_Graphics3D_Impl::DoSwapBuffers() {
bool PPB_Graphics3D_Impl::Init(PPB_Graphics3D_API* share_context,
const int32_t* attrib_list) {
- if (!InitRaw(share_context, attrib_list))
+ if (!InitRaw(share_context, attrib_list, NULL, NULL))
return false;
gpu::gles2::GLES2Implementation* share_gles2 = NULL;
@@ -211,8 +225,11 @@ bool PPB_Graphics3D_Impl::Init(PPB_Graphics3D_API* share_context,
return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize, share_gles2);
}
-bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
- const int32_t* attrib_list) {
+bool PPB_Graphics3D_Impl::InitRaw(
+ PPB_Graphics3D_API* share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state_handle) {
PepperPluginInstanceImpl* plugin_instance =
HostGlobals::Get()->GetInstance(pp_instance());
if (!plugin_instance)
@@ -281,6 +298,10 @@ bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
return false;
if (!command_buffer_->Initialize())
return false;
+ if (shared_state_handle)
+ *shared_state_handle = command_buffer_->GetSharedStateHandle();
+ if (capabilities)
+ *capabilities = command_buffer_->GetCapabilities();
mailbox_ = gpu::Mailbox::Generate();
if (!command_buffer_->ProduceFrontBuffer(mailbox_))
return false;
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
index c3520c05a03..5fcd1638a7b 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -5,11 +5,16 @@
#ifndef CONTENT_RENDERER_PEPPER_PPB_GRAPHICS_3D_IMPL_H_
#define CONTENT_RENDERER_PEPPER_PPB_GRAPHICS_3D_IMPL_H_
+#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
#include "ppapi/shared_impl/resource.h"
+namespace gpu {
+struct Capabilities;
+}
+
namespace content {
class CommandBufferProxyImpl;
class GpuChannelHost;
@@ -19,22 +24,26 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
static PP_Resource Create(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list);
- static PP_Resource CreateRaw(PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list);
+ static PP_Resource CreateRaw(
+ PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state_handle);
// PPB_Graphics3D_API trusted implementation.
- virtual PP_Bool SetGetBuffer(int32_t transfer_buffer_id) OVERRIDE;
- virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(uint32_t size,
- int32* id) OVERRIDE;
- virtual PP_Bool DestroyTransferBuffer(int32_t id) OVERRIDE;
- virtual PP_Bool Flush(int32_t put_offset) OVERRIDE;
- virtual gpu::CommandBuffer::State WaitForTokenInRange(int32_t start,
- int32_t end) OVERRIDE;
- virtual gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start,
- int32_t end)
- OVERRIDE;
- virtual uint32_t InsertSyncPoint() OVERRIDE;
+ PP_Bool SetGetBuffer(int32_t transfer_buffer_id) override;
+ scoped_refptr<gpu::Buffer> CreateTransferBuffer(uint32_t size,
+ int32* id) override;
+ PP_Bool DestroyTransferBuffer(int32_t id) override;
+ PP_Bool Flush(int32_t put_offset) override;
+ gpu::CommandBuffer::State WaitForTokenInRange(int32_t start,
+ int32_t end) override;
+ gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start,
+ int32_t end) override;
+ uint32_t InsertSyncPoint() override;
+ uint32_t InsertFutureSyncPoint() override;
+ void RetireSyncPoint(uint32_t) override;
// Binds/unbinds the graphics of this context with the associated instance.
// Returns true if binding/unbinding is successful.
@@ -55,20 +64,23 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
int GetCommandBufferRouteId();
- GpuChannelHost* channel() { return channel_; }
+ GpuChannelHost* channel() { return channel_.get(); }
protected:
- virtual ~PPB_Graphics3D_Impl();
+ ~PPB_Graphics3D_Impl() override;
// ppapi::PPB_Graphics3D_Shared overrides.
- virtual gpu::CommandBuffer* GetCommandBuffer() OVERRIDE;
- virtual gpu::GpuControl* GetGpuControl() OVERRIDE;
- virtual int32 DoSwapBuffers() OVERRIDE;
+ gpu::CommandBuffer* GetCommandBuffer() override;
+ gpu::GpuControl* GetGpuControl() override;
+ int32 DoSwapBuffers() override;
private:
explicit PPB_Graphics3D_Impl(PP_Instance instance);
bool Init(PPB_Graphics3D_API* share_context, const int32_t* attrib_list);
- bool InitRaw(PPB_Graphics3D_API* share_context, const int32_t* attrib_list);
+ bool InitRaw(PPB_Graphics3D_API* share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state_handle);
// Notifications received from the GPU process.
void OnSwapBuffers();
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.cc b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
index 086eee299a9..28f23c99c71 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/view_messages.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/render_thread_impl.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_instance.h"
@@ -259,8 +258,8 @@ bool ImageDataSimpleBackend::Init(PPB_ImageData_Impl* impl,
int width,
int height,
bool init_to_zero) {
- skia_bitmap_.setConfig(
- SkBitmap::kARGB_8888_Config, impl->width(), impl->height());
+ skia_bitmap_.setInfo(
+ SkImageInfo::MakeN32Premul(impl->width(), impl->height()));
shared_memory_.reset(
RenderThread::Get()
->HostAllocateSharedMemoryBuffer(skia_bitmap_.getSize())
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.h b/chromium/content/renderer/pepper/ppb_image_data_impl.h
index 3ec7986ceb5..61f2b70276d 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.h
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.h
@@ -84,21 +84,21 @@ class CONTENT_EXPORT PPB_ImageData_Impl
TransportDIB* GetTransportDIB() const;
// Resource override.
- virtual ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() OVERRIDE;
+ ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() override;
// PPB_ImageData_API implementation.
- virtual PP_Bool Describe(PP_ImageDataDesc* desc) OVERRIDE;
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
- virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
- virtual SkCanvas* GetCanvas() OVERRIDE;
- virtual void SetIsCandidateForReuse() OVERRIDE;
+ PP_Bool Describe(PP_ImageDataDesc* desc) override;
+ void* Map() override;
+ void Unmap() override;
+ int32_t GetSharedMemory(int* handle, uint32_t* byte_count) override;
+ SkCanvas* GetPlatformCanvas() override;
+ SkCanvas* GetCanvas() override;
+ void SetIsCandidateForReuse() override;
const SkBitmap* GetMappedBitmap() const;
private:
- virtual ~PPB_ImageData_Impl();
+ ~PPB_ImageData_Impl() override;
PP_ImageDataFormat format_;
int width_;
@@ -113,22 +113,22 @@ class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
// |is_browser_allocated| indicates whether the backing shared memory should
// be allocated by the browser process.
ImageDataPlatformBackend(bool is_browser_allocated);
- virtual ~ImageDataPlatformBackend();
+ ~ImageDataPlatformBackend() override;
// PPB_ImageData_Impl::Backend implementation.
- virtual bool Init(PPB_ImageData_Impl* impl,
- PP_ImageDataFormat format,
- int width,
- int height,
- bool init_to_zero) OVERRIDE;
- virtual bool IsMapped() const OVERRIDE;
- virtual TransportDIB* GetTransportDIB() const OVERRIDE;
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
- virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
- virtual SkCanvas* GetCanvas() OVERRIDE;
- virtual const SkBitmap* GetMappedBitmap() const OVERRIDE;
+ bool Init(PPB_ImageData_Impl* impl,
+ PP_ImageDataFormat format,
+ int width,
+ int height,
+ bool init_to_zero) override;
+ bool IsMapped() const override;
+ TransportDIB* GetTransportDIB() const override;
+ void* Map() override;
+ void Unmap() override;
+ int32_t GetSharedMemory(int* handle, uint32_t* byte_count) override;
+ SkCanvas* GetPlatformCanvas() override;
+ SkCanvas* GetCanvas() override;
+ const SkBitmap* GetMappedBitmap() const override;
private:
// This will be NULL before initialization, and if this PPB_ImageData_Impl is
@@ -148,22 +148,22 @@ class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
class ImageDataSimpleBackend : public PPB_ImageData_Impl::Backend {
public:
ImageDataSimpleBackend();
- virtual ~ImageDataSimpleBackend();
+ ~ImageDataSimpleBackend() override;
// PPB_ImageData_Impl::Backend implementation.
- virtual bool Init(PPB_ImageData_Impl* impl,
- PP_ImageDataFormat format,
- int width,
- int height,
- bool init_to_zero) OVERRIDE;
- virtual bool IsMapped() const OVERRIDE;
- virtual TransportDIB* GetTransportDIB() const OVERRIDE;
- virtual void* Map() OVERRIDE;
- virtual void Unmap() OVERRIDE;
- virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) OVERRIDE;
- virtual SkCanvas* GetPlatformCanvas() OVERRIDE;
- virtual SkCanvas* GetCanvas() OVERRIDE;
- virtual const SkBitmap* GetMappedBitmap() const OVERRIDE;
+ bool Init(PPB_ImageData_Impl* impl,
+ PP_ImageDataFormat format,
+ int width,
+ int height,
+ bool init_to_zero) override;
+ bool IsMapped() const override;
+ TransportDIB* GetTransportDIB() const override;
+ void* Map() override;
+ void Unmap() override;
+ int32_t GetSharedMemory(int* handle, uint32_t* byte_count) override;
+ SkCanvas* GetPlatformCanvas() override;
+ SkCanvas* GetCanvas() override;
+ const SkBitmap* GetMappedBitmap() const override;
private:
scoped_ptr<base::SharedMemory> shared_memory_;
diff --git a/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc b/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc
index e276e52e942..93b333b0c6f 100644
--- a/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_scrollbar_impl.cc
@@ -7,13 +7,13 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/event_conversion.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "ppapi/c/dev/ppp_scrollbar_dev.h"
+#include "ppapi/c/pp_bool.h"
#include "ppapi/thunk/thunk.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
diff --git a/chromium/content/renderer/pepper/ppb_scrollbar_impl.h b/chromium/content/renderer/pepper/ppb_scrollbar_impl.h
index 6eeee80ea34..3c94ad8e86e 100644
--- a/chromium/content/renderer/pepper/ppb_scrollbar_impl.h
+++ b/chromium/content/renderer/pepper/ppb_scrollbar_impl.h
@@ -25,39 +25,38 @@ class PPB_Scrollbar_Impl : public PPB_Widget_Impl,
static PP_Resource Create(PP_Instance instance, bool vertical);
// Resource overrides.
- virtual PPB_Scrollbar_API* AsPPB_Scrollbar_API() OVERRIDE;
- virtual void InstanceWasDeleted() OVERRIDE;
+ PPB_Scrollbar_API* AsPPB_Scrollbar_API() override;
+ void InstanceWasDeleted() override;
// PPB_Scrollbar_API implementation.
- virtual uint32_t GetThickness() OVERRIDE;
- virtual bool IsOverlay() OVERRIDE;
- virtual uint32_t GetValue() OVERRIDE;
- virtual void SetValue(uint32_t value) OVERRIDE;
- virtual void SetDocumentSize(uint32_t size) OVERRIDE;
- virtual void SetTickMarks(const PP_Rect* tick_marks, uint32_t count) OVERRIDE;
- virtual void ScrollBy(PP_ScrollBy_Dev unit, int32_t multiplier) OVERRIDE;
+ uint32_t GetThickness() override;
+ bool IsOverlay() override;
+ uint32_t GetValue() override;
+ void SetValue(uint32_t value) override;
+ void SetDocumentSize(uint32_t size) override;
+ void SetTickMarks(const PP_Rect* tick_marks, uint32_t count) override;
+ void ScrollBy(PP_ScrollBy_Dev unit, int32_t multiplier) override;
private:
- virtual ~PPB_Scrollbar_Impl();
+ ~PPB_Scrollbar_Impl() override;
explicit PPB_Scrollbar_Impl(PP_Instance instance);
void Init(bool vertical);
// PPB_Widget private implementation.
- virtual PP_Bool PaintInternal(const gfx::Rect& rect,
- PPB_ImageData_Impl* image) OVERRIDE;
- virtual PP_Bool HandleEventInternal(const ppapi::InputEventData& data)
- OVERRIDE;
- virtual void SetLocationInternal(const PP_Rect* location) OVERRIDE;
+ PP_Bool PaintInternal(const gfx::Rect& rect,
+ PPB_ImageData_Impl* image) override;
+ PP_Bool HandleEventInternal(const ppapi::InputEventData& data) override;
+ void SetLocationInternal(const PP_Rect* location) override;
// blink::WebPluginScrollbarClient implementation.
- virtual void valueChanged(blink::WebPluginScrollbar* scrollbar) OVERRIDE;
- virtual void overlayChanged(blink::WebPluginScrollbar* scrollbar) OVERRIDE;
+ virtual void valueChanged(blink::WebPluginScrollbar* scrollbar) override;
+ virtual void overlayChanged(blink::WebPluginScrollbar* scrollbar) override;
virtual void invalidateScrollbarRect(blink::WebPluginScrollbar* scrollbar,
- const blink::WebRect& rect) OVERRIDE;
+ const blink::WebRect& rect) override;
virtual void getTickmarks(blink::WebPluginScrollbar* scrollbar,
blink::WebVector<blink::WebRect>* tick_marks) const
- OVERRIDE;
+ override;
void NotifyInvalidate();
diff --git a/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc b/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc
index f8fdd1431bf..c5a93e2f389 100644
--- a/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_var_deprecated_impl.cc
@@ -6,316 +6,273 @@
#include <limits>
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/host_globals.h"
-#include "content/renderer/pepper/npapi_glue.h"
-#include "content/renderer/pepper/npobject_var.h"
+#include "content/renderer/pepper/message_channel.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "content/renderer/pepper/pepper_try_catch.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/plugin_object.h"
+#include "content/renderer/pepper/v8object_var.h"
#include "ppapi/c/dev/ppb_var_deprecated.h"
#include "ppapi/c/ppb_var.h"
-#include "ppapi/c/pp_var.h"
#include "ppapi/shared_impl/ppb_var_shared.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
-using ppapi::NPObjectVar;
+using ppapi::V8ObjectVar;
using ppapi::PpapiGlobals;
+using ppapi::ScopedPPVar;
+using ppapi::ScopedPPVarArray;
using ppapi::StringVar;
using ppapi::Var;
-using blink::WebBindings;
namespace content {
namespace {
+const char kInvalidIdentifierException[] = "Error: Invalid identifier.";
const char kInvalidObjectException[] = "Error: Invalid object";
-const char kInvalidPropertyException[] = "Error: Invalid property";
-const char kInvalidValueException[] = "Error: Invalid value";
-const char kUnableToGetPropertyException[] = "Error: Unable to get property";
-const char kUnableToSetPropertyException[] = "Error: Unable to set property";
-const char kUnableToRemovePropertyException[] =
- "Error: Unable to remove property";
-const char kUnableToGetAllPropertiesException[] =
- "Error: Unable to get all properties";
const char kUnableToCallMethodException[] = "Error: Unable to call method";
-const char kUnableToConstructException[] = "Error: Unable to construct";
-
-// ---------------------------------------------------------------------------
-// Utilities
-
-// Converts the given PP_Var to an NPVariant, returning true on success.
-// False means that the given variant is invalid. In this case, the result
-// NPVariant will be set to a void one.
-//
-// The contents of the PP_Var will NOT be copied, so you need to ensure that
-// the PP_Var remains valid while the resultant NPVariant is in use.
-bool PPVarToNPVariantNoCopy(PP_Var var, NPVariant* result) {
- switch (var.type) {
- case PP_VARTYPE_UNDEFINED:
- VOID_TO_NPVARIANT(*result);
- break;
- case PP_VARTYPE_NULL:
- NULL_TO_NPVARIANT(*result);
- break;
- case PP_VARTYPE_BOOL:
- BOOLEAN_TO_NPVARIANT(var.value.as_bool, *result);
- break;
- case PP_VARTYPE_INT32:
- INT32_TO_NPVARIANT(var.value.as_int, *result);
- break;
- case PP_VARTYPE_DOUBLE:
- DOUBLE_TO_NPVARIANT(var.value.as_double, *result);
- break;
- case PP_VARTYPE_STRING: {
- StringVar* string = StringVar::FromPPVar(var);
- if (!string) {
- VOID_TO_NPVARIANT(*result);
- return false;
- }
- const std::string& value = string->value();
- STRINGN_TO_NPVARIANT(value.c_str(), value.size(), *result);
- break;
- }
- case PP_VARTYPE_OBJECT: {
- scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
- if (!object.get()) {
- VOID_TO_NPVARIANT(*result);
- return false;
- }
- OBJECT_TO_NPVARIANT(object->np_object(), *result);
- break;
- }
- default:
- VOID_TO_NPVARIANT(*result);
- return false;
- }
- return true;
-}
-// ObjectAccessorTryCatch ------------------------------------------------------
-
-// Automatically sets up a TryCatch for accessing the object identified by the
-// given PP_Var. The module from the object will be used for the exception
-// strings generated by the TryCatch.
-//
-// This will automatically retrieve the ObjectVar from the object and throw
-// an exception if it's invalid. At the end of construction, if there is no
-// exception, you know that there is no previously set exception, that the
-// object passed in is valid and ready to use (via the object() getter), and
-// that the TryCatch's pp_module() getter is also set up properly and ready to
-// use.
-class ObjectAccessorTryCatch : public TryCatch {
+class ObjectAccessor {
public:
- ObjectAccessorTryCatch(PP_Var object, PP_Var* exception)
- : TryCatch(exception), object_(NPObjectVar::FromPPVar(object)) {
- if (!object_.get()) {
- SetException(kInvalidObjectException);
+ ObjectAccessor(PP_Var var)
+ : object_var_(V8ObjectVar::FromPPVar(var).get()),
+ instance_(object_var_ ? object_var_->instance() : NULL) {
+ if (instance_) {
+ converter_.reset(new V8VarConverter(instance_->pp_instance(),
+ V8VarConverter::kAllowObjectVars));
}
}
- NPObjectVar* object() { return object_.get(); }
-
- PepperPluginInstanceImpl* GetPluginInstance() {
- return HostGlobals::Get()->GetInstance(object()->pp_instance());
- }
-
- protected:
- scoped_refptr<NPObjectVar> object_;
-
- DISALLOW_COPY_AND_ASSIGN(ObjectAccessorTryCatch);
-};
-
-// ObjectAccessiorWithIdentifierTryCatch ---------------------------------------
-
-// Automatically sets up a TryCatch for accessing the identifier on the given
-// object. This just extends ObjectAccessorTryCatch to additionally convert
-// the given identifier to an NPIdentifier and validate it, throwing an
-// exception if it's invalid.
-//
-// At the end of construction, if there is no exception, you know that there is
-// no previously set exception, that the object passed in is valid and ready to
-// use (via the object() getter), that the identifier is valid and ready to
-// use (via the identifier() getter), and that the TryCatch's pp_module() getter
-// is also set up properly and ready to use.
-class ObjectAccessorWithIdentifierTryCatch : public ObjectAccessorTryCatch {
- public:
- ObjectAccessorWithIdentifierTryCatch(PP_Var object,
- PP_Var identifier,
- PP_Var* exception)
- : ObjectAccessorTryCatch(object, exception), identifier_(0) {
- if (!has_exception()) {
- identifier_ = PPVarToNPIdentifier(identifier);
- if (!identifier_)
- SetException(kInvalidPropertyException);
- }
+ // Check if the object is valid. If it isn't, set an exception and return
+ // false.
+ bool IsValid(PP_Var* exception) {
+ // If we already have an exception, then the call is invalid according to
+ // the unittests.
+ if (exception && exception->type != PP_VARTYPE_UNDEFINED)
+ return false;
+ if (instance_)
+ return true;
+ if (exception)
+ *exception = ppapi::StringVar::StringToPPVar(kInvalidObjectException);
+ return false;
}
-
- NPIdentifier identifier() const { return identifier_; }
+ // Lazily grab the object so that the handle is created in the current handle
+ // scope.
+ v8::Handle<v8::Object> GetObject() { return object_var_->GetHandle(); }
+ PepperPluginInstanceImpl* instance() { return instance_; }
+ V8VarConverter* converter() { return converter_.get(); }
private:
- NPIdentifier identifier_;
-
- DISALLOW_COPY_AND_ASSIGN(ObjectAccessorWithIdentifierTryCatch);
+ V8ObjectVar* object_var_;
+ PepperPluginInstanceImpl* instance_;
+ scoped_ptr<V8VarConverter> converter_;
};
-PP_Bool HasProperty(PP_Var var, PP_Var name, PP_Var* exception) {
- ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
- if (accessor.has_exception())
- return PP_FALSE;
- return BoolToPPBool(WebBindings::hasProperty(
- NULL, accessor.object()->np_object(), accessor.identifier()));
+bool IsValidIdentifer(PP_Var identifier, PP_Var* exception) {
+ if (identifier.type == PP_VARTYPE_INT32 ||
+ identifier.type == PP_VARTYPE_STRING) {
+ return true;
+ }
+ if (exception)
+ *exception = ppapi::StringVar::StringToPPVar(kInvalidIdentifierException);
+ return false;
}
bool HasPropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
- return PPBoolToBool(HasProperty(var, name, exception));
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
+ return false;
+
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+ v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+ if (try_catch.HasException())
+ return false;
+
+ bool result = accessor.GetObject()->Has(v8_name);
+ if (try_catch.HasException())
+ return false;
+ return result;
}
bool HasMethodDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
- ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
- if (accessor.has_exception())
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
+ return false;
+
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+ v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+ if (try_catch.HasException())
+ return false;
+
+ bool result = accessor.GetObject()->Has(v8_name) &&
+ accessor.GetObject()->Get(v8_name)->IsFunction();
+ if (try_catch.HasException())
return false;
- return WebBindings::hasMethod(
- NULL, accessor.object()->np_object(), accessor.identifier());
+ return result;
}
PP_Var GetProperty(PP_Var var, PP_Var name, PP_Var* exception) {
- ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
- if (accessor.has_exception())
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
return PP_MakeUndefined();
- NPVariant result;
- if (!WebBindings::getProperty(NULL,
- accessor.object()->np_object(),
- accessor.identifier(),
- &result)) {
- // An exception may have been raised.
- accessor.SetException(kUnableToGetPropertyException);
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+ v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+ if (try_catch.HasException())
return PP_MakeUndefined();
- }
- PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
- WebBindings::releaseVariantValue(&result);
- return ret;
+ ScopedPPVar result_var = try_catch.FromV8(accessor.GetObject()->Get(v8_name));
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+
+ return result_var.Release();
}
void EnumerateProperties(PP_Var var,
uint32_t* property_count,
PP_Var** properties,
PP_Var* exception) {
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception))
+ return;
+
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+
*properties = NULL;
*property_count = 0;
- ObjectAccessorTryCatch accessor(var, exception);
- if (accessor.has_exception())
- return;
-
- NPIdentifier* identifiers = NULL;
- uint32_t count = 0;
- if (!WebBindings::enumerate(
- NULL, accessor.object()->np_object(), &identifiers, &count)) {
- accessor.SetException(kUnableToGetAllPropertiesException);
+ v8::Local<v8::Array> identifiers = accessor.GetObject()->GetPropertyNames();
+ if (try_catch.HasException())
return;
+ ScopedPPVarArray identifier_vars(identifiers->Length());
+ for (uint32_t i = 0; i < identifiers->Length(); ++i) {
+ ScopedPPVar var = try_catch.FromV8(identifiers->Get(i));
+ if (try_catch.HasException())
+ return;
+ identifier_vars.Set(i, var);
}
- if (count == 0)
- return;
-
- *property_count = count;
- *properties = static_cast<PP_Var*>(malloc(sizeof(PP_Var) * count));
- for (uint32_t i = 0; i < count; ++i) {
- (*properties)[i] = NPIdentifierToPPVar(identifiers[i]);
- }
- free(identifiers);
+ size_t size = identifier_vars.size();
+ *properties = identifier_vars.Release(
+ ScopedPPVarArray::PassPPBMemoryAllocatedArray());
+ *property_count = size;
}
void SetPropertyDeprecated(PP_Var var,
PP_Var name,
PP_Var value,
PP_Var* exception) {
- ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
- if (accessor.has_exception())
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
return;
- NPVariant variant;
- if (!PPVarToNPVariantNoCopy(value, &variant)) {
- accessor.SetException(kInvalidValueException);
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+ v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+ v8::Handle<v8::Value> v8_value = try_catch.ToV8(value);
+
+ if (try_catch.HasException())
return;
- }
- if (!WebBindings::setProperty(NULL,
- accessor.object()->np_object(),
- accessor.identifier(),
- &variant))
- accessor.SetException(kUnableToSetPropertyException);
+
+ accessor.GetObject()->Set(v8_name, v8_value);
+ try_catch.HasException(); // Ensure an exception gets set if one occured.
}
void DeletePropertyDeprecated(PP_Var var, PP_Var name, PP_Var* exception) {
- ObjectAccessorWithIdentifierTryCatch accessor(var, name, exception);
- if (accessor.has_exception())
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception) || !IsValidIdentifer(name, exception))
+ return;
+
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+ v8::Handle<v8::Value> v8_name = try_catch.ToV8(name);
+
+ if (try_catch.HasException())
return;
- if (!WebBindings::removeProperty(
- NULL, accessor.object()->np_object(), accessor.identifier()))
- accessor.SetException(kUnableToRemovePropertyException);
+ accessor.GetObject()->Delete(v8_name);
+ try_catch.HasException(); // Ensure an exception gets set if one occured.
}
-PP_Var InternalCallDeprecated(ObjectAccessorTryCatch* accessor,
+PP_Var CallDeprecatedInternal(PP_Var var,
PP_Var method_name,
uint32_t argc,
PP_Var* argv,
PP_Var* exception) {
- NPIdentifier identifier;
+ ObjectAccessor accessor(var);
+ if (!accessor.IsValid(exception))
+ return PP_MakeUndefined();
+
+ // If the method name is undefined, set it to the empty string to trigger
+ // calling |var| as a function.
+ ScopedPPVar scoped_name(method_name);
if (method_name.type == PP_VARTYPE_UNDEFINED) {
- identifier = NULL;
- } else if (method_name.type == PP_VARTYPE_STRING) {
- // Specifically allow only string functions to be called.
- identifier = PPVarToNPIdentifier(method_name);
- if (!identifier) {
- accessor->SetException(kInvalidPropertyException);
- return PP_MakeUndefined();
- }
- } else {
- accessor->SetException(kInvalidPropertyException);
+ scoped_name = ScopedPPVar(ScopedPPVar::PassRef(),
+ StringVar::StringToPPVar(""));
+ }
+
+ PepperTryCatchVar try_catch(accessor.instance(), accessor.converter(),
+ exception);
+ v8::Handle<v8::Value> v8_method_name = try_catch.ToV8(scoped_name.get());
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+
+ if (!v8_method_name->IsString()) {
+ try_catch.SetException(kUnableToCallMethodException);
return PP_MakeUndefined();
}
- scoped_ptr<NPVariant[]> args;
- if (argc) {
- args.reset(new NPVariant[argc]);
- for (uint32_t i = 0; i < argc; ++i) {
- if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
- // This argument was invalid, throw an exception & give up.
- accessor->SetException(kInvalidValueException);
- return PP_MakeUndefined();
- }
- }
+ v8::Handle<v8::Object> function = accessor.GetObject();
+ v8::Handle<v8::Object> recv =
+ accessor.instance()->GetMainWorldContext()->Global();
+ if (v8_method_name.As<v8::String>()->Length() != 0) {
+ function = function->Get(v8_method_name)->ToObject();
+ recv = accessor.GetObject();
}
- bool ok;
-
- NPVariant result;
- if (identifier) {
- ok = WebBindings::invoke(NULL,
- accessor->object()->np_object(),
- identifier,
- args.get(),
- argc,
- &result);
- } else {
- ok = WebBindings::invokeDefault(
- NULL, accessor->object()->np_object(), args.get(), argc, &result);
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+
+ if (!function->IsFunction()) {
+ try_catch.SetException(kUnableToCallMethodException);
+ return PP_MakeUndefined();
}
- if (!ok) {
- // An exception may have been raised.
- accessor->SetException(kUnableToCallMethodException);
+ scoped_ptr<v8::Handle<v8::Value>[] > converted_args(
+ new v8::Handle<v8::Value>[argc]);
+ for (uint32_t i = 0; i < argc; ++i) {
+ converted_args[i] = try_catch.ToV8(argv[i]);
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+ }
+
+ blink::WebPluginContainer* container = accessor.instance()->container();
+ blink::WebLocalFrame* frame = NULL;
+ if (container)
+ frame = container->element().document().frame();
+
+ if (!frame) {
+ try_catch.SetException("No frame to execute script in.");
return PP_MakeUndefined();
}
- PP_Var ret = NPVariantToPPVar(accessor->GetPluginInstance(), &result);
- WebBindings::releaseVariantValue(&result);
- return ret;
+ v8::Handle<v8::Value> result = frame->callFunctionEvenIfScriptDisabled(
+ function.As<v8::Function>(), recv, argc, converted_args.get());
+ ScopedPPVar result_var = try_catch.FromV8(result);
+
+ if (try_catch.HasException())
+ return PP_MakeUndefined();
+
+ return result_var.Release();
}
PP_Var CallDeprecated(PP_Var var,
@@ -323,57 +280,42 @@ PP_Var CallDeprecated(PP_Var var,
uint32_t argc,
PP_Var* argv,
PP_Var* exception) {
- ObjectAccessorTryCatch accessor(var, exception);
- if (accessor.has_exception())
- return PP_MakeUndefined();
- PepperPluginInstanceImpl* plugin = accessor.GetPluginInstance();
- if (plugin && plugin->IsProcessingUserGesture()) {
- blink::WebScopedUserGesture user_gesture(plugin->CurrentUserGestureToken());
- return InternalCallDeprecated(
- &accessor, method_name, argc, argv, exception);
+ ObjectAccessor accessor(var);
+ if (accessor.instance() && accessor.instance()->IsProcessingUserGesture()) {
+ blink::WebScopedUserGesture user_gesture(
+ accessor.instance()->CurrentUserGestureToken());
+ return CallDeprecatedInternal(var, method_name, argc, argv, exception);
}
- return InternalCallDeprecated(&accessor, method_name, argc, argv, exception);
+ return CallDeprecatedInternal(var, method_name, argc, argv, exception);
}
PP_Var Construct(PP_Var var, uint32_t argc, PP_Var* argv, PP_Var* exception) {
- ObjectAccessorTryCatch accessor(var, exception);
- if (accessor.has_exception())
- return PP_MakeUndefined();
-
- scoped_ptr<NPVariant[]> args;
- if (argc) {
- args.reset(new NPVariant[argc]);
- for (uint32_t i = 0; i < argc; ++i) {
- if (!PPVarToNPVariantNoCopy(argv[i], &args[i])) {
- // This argument was invalid, throw an exception & give up.
- accessor.SetException(kInvalidValueException);
- return PP_MakeUndefined();
- }
- }
- }
-
- NPVariant result;
- if (!WebBindings::construct(
- NULL, accessor.object()->np_object(), args.get(), argc, &result)) {
- // An exception may have been raised.
- accessor.SetException(kUnableToConstructException);
- return PP_MakeUndefined();
- }
-
- PP_Var ret = NPVariantToPPVar(accessor.GetPluginInstance(), &result);
- WebBindings::releaseVariantValue(&result);
- return ret;
+ // Deprecated.
+ NOTREACHED();
+ return PP_MakeUndefined();
}
bool IsInstanceOfDeprecated(PP_Var var,
const PPP_Class_Deprecated* ppp_class,
void** ppp_class_data) {
- scoped_refptr<NPObjectVar> object(NPObjectVar::FromPPVar(var));
+ scoped_refptr<V8ObjectVar> object(V8ObjectVar::FromPPVar(var));
if (!object.get())
return false; // Not an object at all.
- return PluginObject::IsInstanceOf(
- object->np_object(), ppp_class, ppp_class_data);
+ v8::HandleScope handle_scope(object->instance()->GetIsolate());
+ v8::Handle<v8::Context> context = object->instance()->GetMainWorldContext();
+ if (context.IsEmpty())
+ return false;
+ v8::Context::Scope context_scope(context);
+ PluginObject* plugin_object = PluginObject::FromV8Object(
+ object->instance()->GetIsolate(), object->GetHandle());
+ if (plugin_object && plugin_object->ppp_class() == ppp_class) {
+ if (ppp_class_data)
+ *ppp_class_data = plugin_object->ppp_class_data();
+ return true;
+ }
+
+ return false;
}
PP_Var CreateObjectDeprecated(PP_Instance pp_instance,
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
index 4a3cde418a2..53b2ef96b91 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
@@ -10,7 +10,6 @@
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
@@ -66,8 +65,8 @@ media::VideoCodecProfile PPToMediaProfile(
return media::H264PROFILE_STEREOHIGH;
case PP_VIDEODECODER_H264PROFILE_MULTIVIEWHIGH:
return media::H264PROFILE_MULTIVIEWHIGH;
- case PP_VIDEODECODER_VP8PROFILE_MAIN:
- return media::VP8PROFILE_MAIN;
+ case PP_VIDEODECODER_VP8PROFILE_ANY:
+ return media::VP8PROFILE_ANY;
default:
return media::VIDEO_CODEC_PROFILE_UNKNOWN;
}
@@ -247,6 +246,8 @@ void PPB_VideoDecoder_Impl::ProvidePictureBuffers(
}
void PPB_VideoDecoder_Impl::PictureReady(const media::Picture& picture) {
+ // So far picture.visible_rect is not used. If used, visible_rect should
+ // be validated since it comes from GPU process and may not be trustworthy.
DCHECK(RenderThreadImpl::current());
if (!ppp_videodecoder_)
return;
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.h b/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
index c099950f97d..e3037b9eb5a 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
@@ -32,32 +32,28 @@ class PPB_VideoDecoder_Impl : public ppapi::PPB_VideoDecoder_Shared,
PP_VideoDecoder_Profile profile);
// PPB_VideoDecoder_Dev_API implementation.
- virtual int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
- scoped_refptr<ppapi::TrackedCallback> callback)
- OVERRIDE;
- virtual void AssignPictureBuffers(uint32_t no_of_buffers,
- const PP_PictureBuffer_Dev* buffers)
- OVERRIDE;
- virtual void ReusePictureBuffer(int32_t picture_buffer_id) OVERRIDE;
- virtual int32_t Flush(scoped_refptr<ppapi::TrackedCallback> callback)
- OVERRIDE;
- virtual int32_t Reset(scoped_refptr<ppapi::TrackedCallback> callback)
- OVERRIDE;
- virtual void Destroy() OVERRIDE;
+ int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer,
+ scoped_refptr<ppapi::TrackedCallback> callback) override;
+ void AssignPictureBuffers(uint32_t no_of_buffers,
+ const PP_PictureBuffer_Dev* buffers) override;
+ void ReusePictureBuffer(int32_t picture_buffer_id) override;
+ int32_t Flush(scoped_refptr<ppapi::TrackedCallback> callback) override;
+ int32_t Reset(scoped_refptr<ppapi::TrackedCallback> callback) override;
+ void Destroy() override;
// media::VideoDecodeAccelerator::Client implementation.
- virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers,
- const gfx::Size& dimensions,
- uint32 texture_target) OVERRIDE;
- virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void PictureReady(const media::Picture& picture) OVERRIDE;
- virtual void NotifyError(media::VideoDecodeAccelerator::Error error) OVERRIDE;
- virtual void NotifyFlushDone() OVERRIDE;
- virtual void NotifyEndOfBitstreamBuffer(int32 buffer_id) OVERRIDE;
- virtual void NotifyResetDone() OVERRIDE;
+ void ProvidePictureBuffers(uint32 requested_num_of_buffers,
+ const gfx::Size& dimensions,
+ uint32 texture_target) override;
+ void DismissPictureBuffer(int32 picture_buffer_id) override;
+ void PictureReady(const media::Picture& picture) override;
+ void NotifyError(media::VideoDecodeAccelerator::Error error) override;
+ void NotifyFlushDone() override;
+ void NotifyEndOfBitstreamBuffer(int32 buffer_id) override;
+ void NotifyResetDone() override;
private:
- virtual ~PPB_VideoDecoder_Impl();
+ ~PPB_VideoDecoder_Impl() override;
explicit PPB_VideoDecoder_Impl(PP_Instance instance);
bool Init(PP_Resource graphics_context,
diff --git a/chromium/content/renderer/pepper/ppb_widget_impl.h b/chromium/content/renderer/pepper/ppb_widget_impl.h
index db6feb34e51..001b96ffaaf 100644
--- a/chromium/content/renderer/pepper/ppb_widget_impl.h
+++ b/chromium/content/renderer/pepper/ppb_widget_impl.h
@@ -28,20 +28,20 @@ class PPB_Widget_Impl : public ppapi::Resource,
explicit PPB_Widget_Impl(PP_Instance instance);
// Resource overrides.
- virtual ppapi::thunk::PPB_Widget_API* AsPPB_Widget_API() OVERRIDE;
+ ppapi::thunk::PPB_Widget_API* AsPPB_Widget_API() override;
// PPB_WidgetAPI implementation.
- virtual PP_Bool Paint(const PP_Rect* rect, PP_Resource) OVERRIDE;
- virtual PP_Bool HandleEvent(PP_Resource pp_input_event) OVERRIDE;
- virtual PP_Bool GetLocation(PP_Rect* location) OVERRIDE;
- virtual void SetLocation(const PP_Rect* location) OVERRIDE;
- virtual void SetScale(float scale) OVERRIDE;
+ PP_Bool Paint(const PP_Rect* rect, PP_Resource) override;
+ PP_Bool HandleEvent(PP_Resource pp_input_event) override;
+ PP_Bool GetLocation(PP_Rect* location) override;
+ void SetLocation(const PP_Rect* location) override;
+ void SetScale(float scale) override;
// Notifies the plugin instance that the given rect needs to be repainted.
void Invalidate(const PP_Rect* dirty);
protected:
- virtual ~PPB_Widget_Impl();
+ ~PPB_Widget_Impl() override;
virtual PP_Bool PaintInternal(const gfx::Rect& rect,
PPB_ImageData_Impl* image) = 0;
diff --git a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h
index a30735dc3c4..f8f7aac5402 100644
--- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h
+++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h
@@ -36,7 +36,7 @@ class PluginModule;
// This class is attached to a PluginModule which manages our lifetime.
class RendererPpapiHostImpl : public RendererPpapiHost {
public:
- virtual ~RendererPpapiHostImpl();
+ ~RendererPpapiHostImpl() override;
// Factory functions to create in process or out-of-process host impls. The
// host will be created and associated with the given module, which must not
@@ -76,34 +76,30 @@ class RendererPpapiHostImpl : public RendererPpapiHost {
bool IsExternalPluginHost() const;
// RendererPpapiHost implementation.
- virtual ppapi::host::PpapiHost* GetPpapiHost() OVERRIDE;
- virtual bool IsValidInstance(PP_Instance instance) const OVERRIDE;
- virtual PepperPluginInstance* GetPluginInstance(PP_Instance instance) const
- OVERRIDE;
- virtual RenderFrame* GetRenderFrameForInstance(PP_Instance instance) const
- OVERRIDE;
- virtual RenderView* GetRenderViewForInstance(PP_Instance instance) const
- OVERRIDE;
- virtual blink::WebPluginContainer* GetContainerForInstance(
- PP_Instance instance) const OVERRIDE;
- virtual base::ProcessId GetPluginPID() const OVERRIDE;
- virtual bool HasUserGesture(PP_Instance instance) const OVERRIDE;
- virtual int GetRoutingIDForWidget(PP_Instance instance) const OVERRIDE;
- virtual gfx::Point PluginPointToRenderFrame(PP_Instance instance,
- const gfx::Point& pt) const
- OVERRIDE;
- virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
+ ppapi::host::PpapiHost* GetPpapiHost() override;
+ bool IsValidInstance(PP_Instance instance) const override;
+ PepperPluginInstance* GetPluginInstance(PP_Instance instance) const override;
+ RenderFrame* GetRenderFrameForInstance(PP_Instance instance) const override;
+ RenderView* GetRenderViewForInstance(PP_Instance instance) const override;
+ blink::WebPluginContainer* GetContainerForInstance(
+ PP_Instance instance) const override;
+ base::ProcessId GetPluginPID() const override;
+ bool HasUserGesture(PP_Instance instance) const override;
+ int GetRoutingIDForWidget(PP_Instance instance) const override;
+ gfx::Point PluginPointToRenderFrame(PP_Instance instance,
+ const gfx::Point& pt) const override;
+ IPC::PlatformFileForTransit ShareHandleWithRemote(
base::PlatformFile handle,
- bool should_close_source) OVERRIDE;
- virtual bool IsRunningInProcess() const OVERRIDE;
- virtual std::string GetPluginName() const OVERRIDE;
- virtual void SetToExternalPluginHost() OVERRIDE;
- virtual void CreateBrowserResourceHosts(
+ bool should_close_source) override;
+ bool IsRunningInProcess() const override;
+ std::string GetPluginName() const override;
+ void SetToExternalPluginHost() override;
+ void CreateBrowserResourceHosts(
PP_Instance instance,
const std::vector<IPC::Message>& nested_msgs,
- const base::Callback<void(const std::vector<int>&)>& callback) const
- OVERRIDE;
- virtual GURL GetDocumentURL(PP_Instance instance) const OVERRIDE;
+ const base::Callback<void(const std::vector<int>&)>& callback)
+ const override;
+ GURL GetDocumentURL(PP_Instance instance) const override;
private:
RendererPpapiHostImpl(PluginModule* module,
diff --git a/chromium/content/renderer/pepper/resource_converter.cc b/chromium/content/renderer/pepper/resource_converter.cc
index 8192f0c7a41..2af3bba3e77 100644
--- a/chromium/content/renderer/pepper/resource_converter.cc
+++ b/chromium/content/renderer/pepper/resource_converter.cc
@@ -16,13 +16,13 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/resource_var.h"
#include "ppapi/shared_impl/scoped_pp_var.h"
+#include "storage/common/fileapi/file_system_util.h"
#include "third_party/WebKit/public/platform/WebFileSystem.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/web/WebDOMFileSystem.h"
#include "third_party/WebKit/public/web/WebDOMMediaStreamTrack.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "webkit/common/fileapi/file_system_util.h"
using ppapi::ResourceVar;
@@ -57,23 +57,23 @@ PP_FileSystemType WebFileSystemTypeToPPAPI(blink::WebFileSystem::Type type) {
}
}
-// Converts a fileapi::FileSystemType to a blink::WebFileSystemType.
+// Converts a storage::FileSystemType to a blink::WebFileSystemType.
// Returns true on success, false if |type| does not correspond to a
// WebFileSystemType.
bool FileApiFileSystemTypeToWebFileSystemType(
- fileapi::FileSystemType type,
+ storage::FileSystemType type,
blink::WebFileSystemType* result_type) {
switch (type) {
- case fileapi::kFileSystemTypeTemporary:
+ case storage::kFileSystemTypeTemporary:
*result_type = blink::WebFileSystemTypeTemporary;
return true;
- case fileapi::kFileSystemTypePersistent:
+ case storage::kFileSystemTypePersistent:
*result_type = blink::WebFileSystemTypePersistent;
return true;
- case fileapi::kFileSystemTypeIsolated:
+ case storage::kFileSystemTypeIsolated:
*result_type = blink::WebFileSystemTypeIsolated;
return true;
- case fileapi::kFileSystemTypeExternal:
+ case storage::kFileSystemTypeExternal:
*result_type = blink::WebFileSystemTypeExternal;
return true;
default:
@@ -126,11 +126,11 @@ bool ResourceHostToDOMFileSystem(
v8::Handle<v8::Value>* dom_file_system) {
GURL root_url = file_system_host->GetRootUrl();
GURL origin;
- fileapi::FileSystemType type;
+ storage::FileSystemType type;
base::FilePath virtual_path;
- fileapi::ParseFileSystemSchemeURL(root_url, &origin, &type, &virtual_path);
+ storage::ParseFileSystemSchemeURL(root_url, &origin, &type, &virtual_path);
- std::string name = fileapi::GetFileSystemName(origin, type);
+ std::string name = storage::GetFileSystemName(origin, type);
blink::WebFileSystemType blink_type;
if (!FileApiFileSystemTypeToWebFileSystemType(type, &blink_type))
return false;
@@ -197,9 +197,8 @@ bool DOMMediaStreamTrackToResource(
ResourceConverter::~ResourceConverter() {}
-ResourceConverterImpl::ResourceConverterImpl(PP_Instance instance,
- RendererPpapiHost* host)
- : instance_(instance), host_(host) {}
+ResourceConverterImpl::ResourceConverterImpl(PP_Instance instance)
+ : instance_(instance) {}
ResourceConverterImpl::~ResourceConverterImpl() {
// Verify Flush() was called.
@@ -213,6 +212,7 @@ bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Object> val,
bool* was_resource) {
v8::Context::Scope context_scope(context);
v8::HandleScope handle_scope(context->GetIsolate());
+ RendererPpapiHost* host = RendererPpapiHost::GetForPPInstance(instance_);
*was_resource = false;
@@ -223,7 +223,7 @@ bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Object> val,
scoped_ptr<IPC::Message> create_message;
scoped_ptr<IPC::Message> browser_host_create_message;
if (!DOMFileSystemToResource(instance_,
- host_,
+ host,
dom_file_system,
&pending_renderer_id,
&create_message,
@@ -246,7 +246,7 @@ bool ResourceConverterImpl::FromV8Value(v8::Handle<v8::Object> val,
int pending_renderer_id;
scoped_ptr<IPC::Message> create_message;
if (!DOMMediaStreamTrackToResource(instance_,
- host_,
+ host,
dom_media_stream_track,
&pending_renderer_id,
&create_message)) {
@@ -276,7 +276,7 @@ bool ResourceConverterImpl::NeedsFlush() {
}
void ResourceConverterImpl::Flush(const base::Callback<void(bool)>& callback) {
- host_->CreateBrowserResourceHosts(
+ RendererPpapiHost::GetForPPInstance(instance_)->CreateBrowserResourceHosts(
instance_,
browser_host_create_messages_,
base::Bind(&FlushComplete, callback, browser_vars_));
diff --git a/chromium/content/renderer/pepper/resource_converter.h b/chromium/content/renderer/pepper/resource_converter.h
index 842f7c72324..d669e7464b4 100644
--- a/chromium/content/renderer/pepper/resource_converter.h
+++ b/chromium/content/renderer/pepper/resource_converter.h
@@ -27,8 +27,6 @@ class ScopedPPVar;
namespace content {
-class RendererPpapiHost;
-
// This class is responsible for converting V8 vars to Pepper resources.
class CONTENT_EXPORT ResourceConverter {
public:
@@ -65,20 +63,20 @@ class CONTENT_EXPORT ResourceConverter {
class ResourceConverterImpl : public ResourceConverter {
public:
- ResourceConverterImpl(PP_Instance instance, RendererPpapiHost* host);
- virtual ~ResourceConverterImpl();
+ explicit ResourceConverterImpl(PP_Instance instance);
+ ~ResourceConverterImpl() override;
// ResourceConverter overrides.
- virtual void Reset() OVERRIDE;
- virtual bool NeedsFlush() OVERRIDE;
- virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE;
- virtual bool FromV8Value(v8::Handle<v8::Object> val,
- v8::Handle<v8::Context> context,
- PP_Var* result,
- bool* was_resource) OVERRIDE;
- virtual bool ToV8Value(const PP_Var& var,
- v8::Handle<v8::Context> context,
- v8::Handle<v8::Value>* result) OVERRIDE;
+ void Reset() override;
+ bool NeedsFlush() override;
+ void Flush(const base::Callback<void(bool)>& callback) override;
+ bool FromV8Value(v8::Handle<v8::Object> val,
+ v8::Handle<v8::Context> context,
+ PP_Var* result,
+ bool* was_resource) override;
+ bool ToV8Value(const PP_Var& var,
+ v8::Handle<v8::Context> context,
+ v8::Handle<v8::Value>* result) override;
private:
// Creates a resource var with the given |pending_renderer_id| and
@@ -97,8 +95,6 @@ class ResourceConverterImpl : public ResourceConverter {
// The instance this ResourceConverter is associated with.
PP_Instance instance_;
- // The RendererPpapiHost to use to create browser hosts.
- RendererPpapiHost* host_;
// A list of the messages to create the browser hosts. This is a parallel
// array to |browser_vars|. It is kept as a parallel array so that it can be
diff --git a/chromium/content/renderer/pepper/resource_creation_impl.cc b/chromium/content/renderer/pepper/resource_creation_impl.cc
index a4fb6c26564..4a693256ae0 100644
--- a/chromium/content/renderer/pepper/resource_creation_impl.cc
+++ b/chromium/content/renderer/pepper/resource_creation_impl.cc
@@ -4,7 +4,6 @@
#include "content/renderer/pepper/resource_creation_impl.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/ppb_audio_impl.h"
#include "content/renderer/pepper/ppb_broker_impl.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
@@ -13,13 +12,21 @@
#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "content/renderer/pepper/ppb_scrollbar_impl.h"
#include "content/renderer/pepper/ppb_video_decoder_impl.h"
+#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_var.h"
#include "ppapi/shared_impl/ppb_audio_config_shared.h"
#include "ppapi/shared_impl/ppb_audio_shared.h"
#include "ppapi/shared_impl/ppb_image_data_shared.h"
#include "ppapi/shared_impl/ppb_input_event_shared.h"
#include "ppapi/shared_impl/var.h"
+#if defined(OS_WIN)
+#include "base/command_line.h"
+#include "base/win/windows_version.h"
+#include "content/public/common/content_switches.h"
+#endif
+
using ppapi::InputEventData;
using ppapi::PPB_InputEvent_Shared;
using ppapi::StringVar;
@@ -105,8 +112,11 @@ PP_Resource ResourceCreationImpl::CreateGraphics3D(PP_Instance instance,
PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
PP_Instance instance,
PP_Resource share_context,
- const int32_t* attrib_list) {
- return PPB_Graphics3D_Impl::CreateRaw(instance, share_context, attrib_list);
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state) {
+ return PPB_Graphics3D_Impl::CreateRaw(instance, share_context, attrib_list,
+ capabilities, shared_state);
}
PP_Resource ResourceCreationImpl::CreateHostResolver(PP_Instance instance) {
@@ -122,6 +132,20 @@ PP_Resource ResourceCreationImpl::CreateImageData(PP_Instance instance,
PP_ImageDataFormat format,
const PP_Size* size,
PP_Bool init_to_zero) {
+#if defined(OS_WIN)
+ // If Win32K lockdown mitigations are enabled for Windows 8 and beyond,
+ // we use the SIMPLE image data type as the PLATFORM image data type
+ // calls GDI functions to create DIB sections etc which fail in Win32K
+ // lockdown mode.
+ // TODO(ananta)
+ // Look into whether this causes a loss of functionality. From cursory
+ // testing things seem to work well.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWin32kRendererLockDown) &&
+ base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ return CreateImageDataSimple(instance, format, size, init_to_zero);
+ }
+#endif
return PPB_ImageData_Impl::Create(instance,
ppapi::PPB_ImageData_Shared::PLATFORM,
format,
diff --git a/chromium/content/renderer/pepper/resource_creation_impl.h b/chromium/content/renderer/pepper/resource_creation_impl.h
index d2b20dd2177..52c44fc06f1 100644
--- a/chromium/content/renderer/pepper/resource_creation_impl.h
+++ b/chromium/content/renderer/pepper/resource_creation_impl.h
@@ -20,128 +20,121 @@ class PepperPluginInstanceImpl;
class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
public:
explicit ResourceCreationImpl(PepperPluginInstanceImpl* instance);
- virtual ~ResourceCreationImpl();
+ ~ResourceCreationImpl() override;
// ResourceCreationAPI implementation.
- virtual PP_Resource CreateAudio1_0(PP_Instance instance,
- PP_Resource config_id,
- PPB_Audio_Callback_1_0 audio_callback,
- void* user_data) OVERRIDE;
- virtual PP_Resource CreateAudio(PP_Instance instance,
- PP_Resource config_id,
- PPB_Audio_Callback audio_callback,
- void* user_data) OVERRIDE;
- virtual PP_Resource CreateAudioTrusted(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateAudioConfig(PP_Instance instance,
- PP_AudioSampleRate sample_rate,
- uint32_t sample_frame_count) OVERRIDE;
- virtual PP_Resource CreateAudioInput(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateCompositor(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateBuffer(PP_Instance instance,
- uint32_t size) OVERRIDE;
- virtual PP_Resource CreateFlashDRM(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateFlashFontFile(
+ PP_Resource CreateAudio1_0(PP_Instance instance,
+ PP_Resource config_id,
+ PPB_Audio_Callback_1_0 audio_callback,
+ void* user_data) override;
+ PP_Resource CreateAudio(PP_Instance instance,
+ PP_Resource config_id,
+ PPB_Audio_Callback audio_callback,
+ void* user_data) override;
+ PP_Resource CreateAudioTrusted(PP_Instance instance) override;
+ PP_Resource CreateAudioConfig(PP_Instance instance,
+ PP_AudioSampleRate sample_rate,
+ uint32_t sample_frame_count) override;
+ PP_Resource CreateAudioInput(PP_Instance instance) override;
+ PP_Resource CreateCompositor(PP_Instance instance) override;
+ PP_Resource CreateBroker(PP_Instance instance) override;
+ PP_Resource CreateBuffer(PP_Instance instance, uint32_t size) override;
+ PP_Resource CreateFlashDRM(PP_Instance instance) override;
+ PP_Resource CreateFlashFontFile(
PP_Instance instance,
const PP_BrowserFont_Trusted_Description* description,
- PP_PrivateFontCharset charset) OVERRIDE;
- virtual PP_Resource CreateFlashMenu(PP_Instance instance,
- const PP_Flash_Menu* menu_data) OVERRIDE;
- virtual PP_Resource CreateFlashMessageLoop(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateGraphics3D(PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list) OVERRIDE;
- virtual PP_Resource CreateGraphics3DRaw(PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list) OVERRIDE;
- virtual PP_Resource CreateHostResolver(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateImageData(PP_Instance instance,
- PP_ImageDataFormat format,
- const PP_Size* size,
- PP_Bool init_to_zero) OVERRIDE;
- virtual PP_Resource CreateImageDataSimple(PP_Instance instance,
- PP_ImageDataFormat format,
- const PP_Size* size,
- PP_Bool init_to_zero) OVERRIDE;
- virtual PP_Resource CreateIMEInputEvent(PP_Instance instance,
- PP_InputEvent_Type type,
- PP_TimeTicks time_stamp,
- struct PP_Var text,
- uint32_t segment_number,
- const uint32_t* segment_offsets,
- int32_t target_segment,
- uint32_t selection_start,
- uint32_t selection_end) OVERRIDE;
- virtual PP_Resource CreateKeyboardInputEvent_1_0(PP_Instance instance,
- PP_InputEvent_Type type,
- PP_TimeTicks time_stamp,
- uint32_t modifiers,
- uint32_t key_code,
- PP_Var character_text)
- OVERRIDE;
- virtual PP_Resource CreateKeyboardInputEvent_1_2(PP_Instance instance,
- PP_InputEvent_Type type,
- PP_TimeTicks time_stamp,
- uint32_t modifiers,
- uint32_t key_code,
- PP_Var character_text,
- PP_Var code) OVERRIDE;
- virtual PP_Resource CreateMediaStreamVideoTrack(
- PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateMouseInputEvent(
+ PP_PrivateFontCharset charset) override;
+ PP_Resource CreateFlashMenu(PP_Instance instance,
+ const PP_Flash_Menu* menu_data) override;
+ PP_Resource CreateFlashMessageLoop(PP_Instance instance) override;
+ PP_Resource CreateGraphics3D(PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list) override;
+ PP_Resource CreateGraphics3DRaw(
PP_Instance instance,
- PP_InputEvent_Type type,
- PP_TimeTicks time_stamp,
- uint32_t modifiers,
- PP_InputEvent_MouseButton mouse_button,
- const PP_Point* mouse_position,
- int32_t click_count,
- const PP_Point* mouse_movement) OVERRIDE;
- virtual PP_Resource CreateNetAddressFromIPv4Address(
+ PP_Resource share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state) override;
+ PP_Resource CreateHostResolver(PP_Instance instance) override;
+ PP_Resource CreateHostResolverPrivate(PP_Instance instance) override;
+ PP_Resource CreateImageData(PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) override;
+ PP_Resource CreateImageDataSimple(PP_Instance instance,
+ PP_ImageDataFormat format,
+ const PP_Size* size,
+ PP_Bool init_to_zero) override;
+ PP_Resource CreateIMEInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) override;
+ PP_Resource CreateKeyboardInputEvent_1_0(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ uint32_t key_code,
+ PP_Var character_text) override;
+ PP_Resource CreateKeyboardInputEvent_1_2(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ uint32_t key_code,
+ PP_Var character_text,
+ PP_Var code) override;
+ PP_Resource CreateMediaStreamVideoTrack(PP_Instance instance) override;
+ PP_Resource CreateMouseInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ PP_InputEvent_MouseButton mouse_button,
+ const PP_Point* mouse_position,
+ int32_t click_count,
+ const PP_Point* mouse_movement) override;
+ PP_Resource CreateNetAddressFromIPv4Address(
PP_Instance instance,
- const PP_NetAddress_IPv4* ipv4_addr) OVERRIDE;
- virtual PP_Resource CreateNetAddressFromIPv6Address(
+ const PP_NetAddress_IPv4* ipv4_addr) override;
+ PP_Resource CreateNetAddressFromIPv6Address(
PP_Instance instance,
- const PP_NetAddress_IPv6* ipv6_addr) OVERRIDE;
- virtual PP_Resource CreateNetAddressFromNetAddressPrivate(
+ const PP_NetAddress_IPv6* ipv6_addr) override;
+ PP_Resource CreateNetAddressFromNetAddressPrivate(
PP_Instance instance,
- const PP_NetAddress_Private& private_addr) OVERRIDE;
- virtual PP_Resource CreateNetworkMonitor(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreatePlatformVerificationPrivate(PP_Instance instance)
- OVERRIDE;
- virtual PP_Resource CreateScrollbar(PP_Instance instance,
- PP_Bool vertical) OVERRIDE;
- virtual PP_Resource CreateOutputProtectionPrivate(PP_Instance instance)
- OVERRIDE;
- virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateTCPServerSocketPrivate(PP_Instance instance)
- OVERRIDE;
- virtual PP_Resource CreateTCPSocket1_0(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateTouchInputEvent(PP_Instance instance,
- PP_InputEvent_Type type,
- PP_TimeTicks time_stamp,
- uint32_t modifiers) OVERRIDE;
- virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateVideoCapture(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateVideoDecoder(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateVideoDecoderDev(PP_Instance instance,
- PP_Resource graphics3d_id,
- PP_VideoDecoder_Profile profile)
- OVERRIDE;
- virtual PP_Resource CreateVideoDestination(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateVideoSource(PP_Instance instance) OVERRIDE;
- virtual PP_Resource CreateWheelInputEvent(PP_Instance instance,
- PP_TimeTicks time_stamp,
- uint32_t modifiers,
- const PP_FloatPoint* wheel_delta,
- const PP_FloatPoint* wheel_ticks,
- PP_Bool scroll_by_page) OVERRIDE;
- virtual PP_Resource CreateX509CertificatePrivate(PP_Instance instance)
- OVERRIDE;
+ const PP_NetAddress_Private& private_addr) override;
+ PP_Resource CreateNetworkMonitor(PP_Instance instance) override;
+ PP_Resource CreatePlatformVerificationPrivate(PP_Instance instance) override;
+ PP_Resource CreateScrollbar(PP_Instance instance, PP_Bool vertical) override;
+ PP_Resource CreateOutputProtectionPrivate(PP_Instance instance) override;
+ PP_Resource CreateTalk(PP_Instance instance) override;
+ PP_Resource CreateTCPServerSocketPrivate(PP_Instance instance) override;
+ PP_Resource CreateTCPSocket1_0(PP_Instance instance) override;
+ PP_Resource CreateTCPSocket(PP_Instance instance) override;
+ PP_Resource CreateTCPSocketPrivate(PP_Instance instance) override;
+ PP_Resource CreateTouchInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers) override;
+ PP_Resource CreateUDPSocket(PP_Instance instance) override;
+ PP_Resource CreateUDPSocketPrivate(PP_Instance instance) override;
+ PP_Resource CreateVideoCapture(PP_Instance instance) override;
+ PP_Resource CreateVideoDecoder(PP_Instance instance) override;
+ PP_Resource CreateVideoDecoderDev(PP_Instance instance,
+ PP_Resource graphics3d_id,
+ PP_VideoDecoder_Profile profile) override;
+ PP_Resource CreateVideoDestination(PP_Instance instance) override;
+ PP_Resource CreateVideoSource(PP_Instance instance) override;
+ PP_Resource CreateWheelInputEvent(PP_Instance instance,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ const PP_FloatPoint* wheel_delta,
+ const PP_FloatPoint* wheel_ticks,
+ PP_Bool scroll_by_page) override;
+ PP_Resource CreateX509CertificatePrivate(PP_Instance instance) override;
private:
DISALLOW_COPY_AND_ASSIGN(ResourceCreationImpl);
diff --git a/chromium/content/renderer/pepper/url_request_info_util.cc b/chromium/content/renderer/pepper/url_request_info_util.cc
index 2596a09017c..4b70190b9ba 100644
--- a/chromium/content/renderer/pepper/url_request_info_util.cc
+++ b/chromium/content/renderer/pepper/url_request_info_util.cc
@@ -8,7 +8,6 @@
#include "base/strings/string_util.h"
#include "content/child/request_extra_data.h"
#include "content/common/fileapi/file_system_messages.h"
-#include "content/renderer/pepper/common.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
@@ -16,6 +15,8 @@
#include "content/renderer/pepper/renderer_ppapi_host_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "net/http/http_util.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_var.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/url_request_info_data.h"
#include "ppapi/shared_impl/var.h"
@@ -102,6 +103,42 @@ bool ValidateURLRequestData(const URLRequestInfoData& data) {
return true;
}
+std::string FilterStringForXRequestedWithValue(const std::string& s) {
+ std::string rv;
+ rv.reserve(s.length());
+ for (size_t i = 0; i < s.length(); i++) {
+ char c = s[i];
+ // Allow ASCII digits, letters, periods, commas, and underscores. (Ignore
+ // all other characters.)
+ if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') || (c == '.') || (c == ',') || (c == '_'))
+ rv.push_back(c);
+ }
+ return rv;
+}
+
+// Returns an appropriate value for the X-Requested-With header for plugins that
+// present an X-Requested-With header. Returns a blank string for other plugins.
+// We produce a user-agent-like string (eating spaces and other undesired
+// characters) like "ShockwaveFlash/11.5.31.135" from the plugin name and
+// version.
+std::string MakeXRequestedWithValue(const std::string& name,
+ const std::string& version) {
+ std::string rv = FilterStringForXRequestedWithValue(name);
+ if (rv.empty())
+ return std::string();
+
+ // Apply to a narrow list of plugins only.
+ if (rv != "ShockwaveFlash" && rv != "PPAPITests")
+ return std::string();
+
+ std::string filtered_version = FilterStringForXRequestedWithValue(version);
+ if (!filtered_version.empty())
+ rv += "/" + filtered_version;
+
+ return rv;
+}
+
} // namespace
bool CreateWebURLRequest(PP_Instance instance,
@@ -114,6 +151,21 @@ bool CreateWebURLRequest(PP_Instance instance,
if (!ValidateURLRequestData(*data))
return false;
+ std::string name_version;
+
+ // Allow instance to be 0 or -1 for testing purposes.
+ if (instance && instance != -1) {
+ PepperPluginInstanceImpl* instance_impl =
+ HostGlobals::Get()->GetInstance(instance);
+ if (instance_impl) {
+ name_version = MakeXRequestedWithValue(
+ instance_impl->module()->name(),
+ instance_impl->module()->version());
+ }
+ } else {
+ name_version = "internal_testing_only";
+ }
+
dest->initialize();
dest->setURL(frame->document().completeURL(WebString::fromUTF8(data->url)));
dest->setDownloadToFile(data->stream_to_file);
@@ -170,12 +222,15 @@ bool CreateWebURLRequest(PP_Instance instance,
WebString::fromUTF8(data->custom_content_transfer_encoding));
}
- if (data->has_custom_user_agent) {
- bool was_after_preconnect_request = false;
+ if (data->has_custom_user_agent || !name_version.empty()) {
RequestExtraData* extra_data = new RequestExtraData();
- extra_data->set_custom_user_agent(
- WebString::fromUTF8(data->custom_user_agent));
- extra_data->set_was_after_preconnect_request(was_after_preconnect_request);
+ if (data->has_custom_user_agent) {
+ extra_data->set_custom_user_agent(
+ WebString::fromUTF8(data->custom_user_agent));
+ }
+ if (!name_version.empty()) {
+ extra_data->set_requested_with(WebString::fromUTF8(name_version));
+ }
dest->setExtraData(extra_data);
}
@@ -186,7 +241,7 @@ bool URLRequestRequiresUniversalAccess(const URLRequestInfoData& data) {
return data.has_custom_referrer_url ||
data.has_custom_content_transfer_encoding ||
data.has_custom_user_agent ||
- url::FindAndCompareScheme(data.url, "javascript", NULL);
+ url::FindAndCompareScheme(data.url, url::kJavaScriptScheme, NULL);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc
index 8b9a4a52181..09ff82bb04a 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion_linux.cc
@@ -17,13 +17,12 @@ uint32_t UsbKeyCodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
// the XKB driver. We should detect between "XKB", "kbd" and "evdev" at
// run-time and re-map accordingly, but that's not possible here, inside the
// sandbox.
- ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToUsbKeycode(key_event.nativeKeyCode);
+ return ui::KeycodeConverter::NativeKeycodeToUsbKeycode(
+ key_event.nativeKeyCode);
}
const char* CodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
- ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToCode(key_event.nativeKeyCode);
+ return ui::KeycodeConverter::NativeKeycodeToCode(key_event.nativeKeyCode);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc
index c701b48453c..784fdd0c602 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion_mac.cc
@@ -13,13 +13,12 @@ using blink::WebKeyboardEvent;
namespace content {
uint32_t UsbKeyCodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
- ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToUsbKeycode(key_event.nativeKeyCode);
+ return ui::KeycodeConverter::NativeKeycodeToUsbKeycode(
+ key_event.nativeKeyCode);
}
const char* CodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
- ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToCode(key_event.nativeKeyCode);
+ return ui::KeycodeConverter::NativeKeycodeToCode(key_event.nativeKeyCode);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc b/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc
index c9e0592b843..3dfa807c7b8 100644
--- a/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc
+++ b/chromium/content/renderer/pepper/usb_key_code_conversion_win.cc
@@ -18,8 +18,7 @@ uint32_t UsbKeyCodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
if ((key_event.nativeKeyCode & (1 << 24)) != 0)
scancode |= 0xe000;
- ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToUsbKeycode(scancode);
+ return ui::KeycodeConverter::NativeKeycodeToUsbKeycode(scancode);
}
const char* CodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
@@ -28,8 +27,7 @@ const char* CodeForKeyboardEvent(const WebKeyboardEvent& key_event) {
if ((key_event.nativeKeyCode & (1 << 24)) != 0)
scancode |= 0xe000;
- ui::KeycodeConverter* key_converter = ui::KeycodeConverter::GetInstance();
- return key_converter->NativeKeycodeToCode(scancode);
+ return ui::KeycodeConverter::NativeKeycodeToCode(scancode);
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/v8_var_converter.cc b/chromium/content/renderer/pepper/v8_var_converter.cc
index b09fccd63e4..42d744d2872 100644
--- a/chromium/content/renderer/pepper/v8_var_converter.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter.cc
@@ -15,7 +15,9 @@
#include "base/memory/scoped_ptr.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/pepper/host_array_buffer_var.h"
+#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/resource_converter.h"
+#include "content/renderer/pepper/v8object_var.h"
#include "ppapi/shared_impl/array_var.h"
#include "ppapi/shared_impl/dictionary_var.h"
#include "ppapi/shared_impl/var.h"
@@ -28,6 +30,7 @@ using ppapi::ArrayVar;
using ppapi::DictionaryVar;
using ppapi::ScopedPPVar;
using ppapi::StringVar;
+using ppapi::V8ObjectVar;
using std::make_pair;
namespace {
@@ -44,21 +47,16 @@ struct HashedHandle {
HashedHandle(v8::Handle<v8::Object> h) : handle(h) {}
size_t hash() const { return handle->GetIdentityHash(); }
bool operator==(const HashedHandle& h) const { return handle == h.handle; }
- bool operator<(const HashedHandle& h) const { return hash() < h.hash(); }
v8::Handle<v8::Object> handle;
};
} // namespace
namespace BASE_HASH_NAMESPACE {
-#if defined(COMPILER_GCC)
template <>
struct hash<HashedHandle> {
size_t operator()(const HashedHandle& handle) const { return handle.hash(); }
};
-#elif defined(COMPILER_MSVC)
-inline size_t hash_value(const HashedHandle& handle) { return handle.hash(); }
-#endif
} // namespace BASE_HASH_NAMESPACE
namespace content {
@@ -80,6 +78,7 @@ typedef base::hash_set<HashedHandle> ParentHandleSet;
// value was created as a result of calling the function.
bool GetOrCreateV8Value(v8::Handle<v8::Context> context,
const PP_Var& var,
+ V8VarConverter::AllowObjectVars object_vars_allowed,
v8::Handle<v8::Value>* result,
bool* did_create,
VarHandleMap* visited_ids,
@@ -150,9 +149,25 @@ bool GetOrCreateV8Value(v8::Handle<v8::Context> context,
case PP_VARTYPE_DICTIONARY:
*result = v8::Object::New(isolate);
break;
- case PP_VARTYPE_OBJECT:
- result->Clear();
- return false;
+ case PP_VARTYPE_OBJECT: {
+ // If object vars are disallowed, we should never be passed an object var
+ // to convert. Also, we should never expect to convert an object var which
+ // is nested inside an array or dictionary.
+ if (object_vars_allowed == V8VarConverter::kDisallowObjectVars ||
+ visited_ids->size() != 0) {
+ NOTREACHED();
+ result->Clear();
+ return false;
+ }
+ scoped_refptr<V8ObjectVar> v8_object_var = V8ObjectVar::FromPPVar(var);
+ if (!v8_object_var.get()) {
+ NOTREACHED();
+ result->Clear();
+ return false;
+ }
+ *result = v8_object_var->GetHandle();
+ break;
+ }
case PP_VARTYPE_RESOURCE:
if (!resource_converter->ToV8Value(var, context, result)) {
result->Clear();
@@ -174,6 +189,8 @@ bool GetOrCreateV8Value(v8::Handle<v8::Context> context,
// calling the function.
bool GetOrCreateVar(v8::Handle<v8::Value> val,
v8::Handle<v8::Context> context,
+ PP_Instance instance,
+ V8VarConverter::AllowObjectVars object_vars_allowed,
PP_Var* result,
bool* did_create,
HandleVarMap* visited_handles,
@@ -197,6 +214,7 @@ bool GetOrCreateVar(v8::Handle<v8::Value> val,
}
}
+ v8::Isolate* isolate = context->GetIsolate();
if (val->IsUndefined()) {
*result = PP_MakeUndefined();
} else if (val->IsNull()) {
@@ -210,16 +228,27 @@ bool GetOrCreateVar(v8::Handle<v8::Value> val,
} else if (val->IsString() || val->IsStringObject()) {
v8::String::Utf8Value utf8(val->ToString());
*result = StringVar::StringToPPVar(std::string(*utf8, utf8.length()));
- } else if (val->IsArray()) {
- *result = (new ArrayVar())->GetPPVar();
} else if (val->IsObject()) {
+ // For any other v8 objects, the conversion happens as follows:
+ // 1) If the object is an array buffer, return an ArrayBufferVar.
+ // 2) If object vars are allowed, return the object wrapped as a
+ // V8ObjectVar. This is to maintain backward compatibility with
+ // synchronous scripting in Flash.
+ // 3) If the object is an array, return an ArrayVar.
+ // 4) If the object can be converted to a resource, return the ResourceVar.
+ // 5) Otherwise return a DictionaryVar.
scoped_ptr<blink::WebArrayBuffer> web_array_buffer(
- blink::WebArrayBufferConverter::createFromV8Value(
- val, context->GetIsolate()));
+ blink::WebArrayBufferConverter::createFromV8Value(val, isolate));
if (web_array_buffer.get()) {
scoped_refptr<HostArrayBufferVar> buffer_var(
new HostArrayBufferVar(*web_array_buffer));
*result = buffer_var->GetPPVar();
+ } else if (object_vars_allowed == V8VarConverter::kAllowObjectVars) {
+ v8::Handle<v8::Object> object = val->ToObject();
+ *result = content::HostGlobals::Get()->
+ host_var_tracker()->V8ObjectVarForV8Object(instance, object);
+ } else if (val->IsArray()) {
+ *result = (new ArrayVar())->GetPPVar();
} else {
bool was_resource;
if (!resource_converter->FromV8Value(
@@ -251,15 +280,17 @@ bool CanHaveChildren(PP_Var var) {
} // namespace
-V8VarConverter::V8VarConverter(PP_Instance instance)
- : message_loop_proxy_(base::MessageLoopProxy::current()) {
- resource_converter_.reset(new ResourceConverterImpl(
- instance, RendererPpapiHost::GetForPPInstance(instance)));
+V8VarConverter::V8VarConverter(PP_Instance instance,
+ AllowObjectVars object_vars_allowed)
+ : instance_(instance),
+ object_vars_allowed_(object_vars_allowed) {
+ resource_converter_.reset(new ResourceConverterImpl(instance));
}
V8VarConverter::V8VarConverter(PP_Instance instance,
scoped_ptr<ResourceConverter> resource_converter)
- : message_loop_proxy_(base::MessageLoopProxy::current()),
+ : instance_(instance),
+ object_vars_allowed_(kDisallowObjectVars),
resource_converter_(resource_converter.release()) {}
V8VarConverter::~V8VarConverter() {}
@@ -305,6 +336,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
bool did_create = false;
if (!GetOrCreateV8Value(context,
current_var,
+ object_vars_allowed_,
&current_v8,
&did_create,
&visited_ids,
@@ -334,6 +366,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
v8::Handle<v8::Value> child_v8;
if (!GetOrCreateV8Value(context,
child_var,
+ object_vars_allowed_,
&child_v8,
&did_create,
&visited_ids,
@@ -369,6 +402,7 @@ bool V8VarConverter::ToV8Value(const PP_Var& var,
v8::Handle<v8::Value> child_v8;
if (!GetOrCreateV8Value(context,
child_var,
+ object_vars_allowed_,
&child_v8,
&did_create,
&visited_ids,
@@ -455,6 +489,8 @@ bool V8VarConverter::FromV8ValueInternal(
bool did_create = false;
if (!GetOrCreateVar(current_v8,
context,
+ instance_,
+ object_vars_allowed_,
&current_var,
&did_create,
&visited_handles,
@@ -492,6 +528,8 @@ bool V8VarConverter::FromV8ValueInternal(
PP_Var child_var;
if (!GetOrCreateVar(child_v8,
context,
+ instance_,
+ object_vars_allowed_,
&child_var,
&did_create,
&visited_handles,
@@ -541,6 +579,8 @@ bool V8VarConverter::FromV8ValueInternal(
PP_Var child_var;
if (!GetOrCreateVar(child_v8,
context,
+ instance_,
+ object_vars_allowed_,
&child_var,
&did_create,
&visited_handles,
diff --git a/chromium/content/renderer/pepper/v8_var_converter.h b/chromium/content/renderer/pepper/v8_var_converter.h
index 42ef7a647f5..c03701d4c71 100644
--- a/chromium/content/renderer/pepper/v8_var_converter.h
+++ b/chromium/content/renderer/pepper/v8_var_converter.h
@@ -21,7 +21,14 @@ class ResourceConverter;
class CONTENT_EXPORT V8VarConverter {
public:
- explicit V8VarConverter(PP_Instance instance);
+ // Whether or not to allow converting object vars. If they are not allowed
+ // and they are passed in, conversion will fail.
+ enum AllowObjectVars {
+ kDisallowObjectVars,
+ kAllowObjectVars
+ };
+ V8VarConverter(PP_Instance instance, AllowObjectVars object_vars_allowed);
+
// Constructor for testing.
V8VarConverter(PP_Instance instance,
scoped_ptr<ResourceConverter> resource_converter);
@@ -71,8 +78,10 @@ class CONTENT_EXPORT V8VarConverter {
v8::Handle<v8::Context> context,
ppapi::ScopedPPVar* result_var);
- // The message loop to run the callback to |FromV8Value| from.
- scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ PP_Instance instance_;
+
+ // Whether or not to support conversion to PP_VARTYPE_OBJECT.
+ AllowObjectVars object_vars_allowed_;
// The converter to use for converting V8 vars to resources.
scoped_ptr<ResourceConverter> resource_converter_;
diff --git a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
index 9492a431a4d..f43d66a0fce 100644
--- a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -50,22 +50,22 @@ void FromV8ValueComplete(const ScopedPPVar& scoped_var,
class MockResourceConverter : public content::ResourceConverter {
public:
- virtual ~MockResourceConverter() {}
- virtual void Reset() OVERRIDE {}
- virtual bool NeedsFlush() OVERRIDE { return false; }
- virtual void Flush(const base::Callback<void(bool)>& callback) OVERRIDE {
+ ~MockResourceConverter() override {}
+ void Reset() override {}
+ bool NeedsFlush() override { return false; }
+ void Flush(const base::Callback<void(bool)>& callback) override {
NOTREACHED();
}
- virtual bool FromV8Value(v8::Handle<v8::Object> val,
- v8::Handle<v8::Context> context,
- PP_Var* result,
- bool* was_resource) OVERRIDE {
+ bool FromV8Value(v8::Handle<v8::Object> val,
+ v8::Handle<v8::Context> context,
+ PP_Var* result,
+ bool* was_resource) override {
*was_resource = false;
return true;
}
- virtual bool ToV8Value(const PP_Var& var,
- v8::Handle<v8::Context> context,
- v8::Handle<v8::Value>* result) OVERRIDE {
+ bool ToV8Value(const PP_Var& var,
+ v8::Handle<v8::Context> context,
+ v8::Handle<v8::Value>* result) override {
return false;
}
};
@@ -169,16 +169,16 @@ class V8VarConverterTest : public testing::Test {
dummy,
scoped_ptr<ResourceConverter>(new MockResourceConverter).Pass()));
}
- virtual ~V8VarConverterTest() {}
+ ~V8VarConverterTest() override {}
// testing::Test implementation.
- virtual void SetUp() {
+ void SetUp() override {
ProxyLock::Acquire();
v8::HandleScope handle_scope(isolate_);
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
}
- virtual void TearDown() {
+ void TearDown() override {
context_.Reset();
ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty());
ProxyLock::Release();
diff --git a/chromium/content/renderer/pepper/v8object_var.cc b/chromium/content/renderer/pepper/v8object_var.cc
new file mode 100644
index 00000000000..faf8bef8e7a
--- /dev/null
+++ b/chromium/content/renderer/pepper/v8object_var.cc
@@ -0,0 +1,62 @@
+// Copyright 2014 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 "content/renderer/pepper/v8object_var.h"
+
+#include "base/logging.h"
+#include "content/public/renderer/pepper_plugin_instance.h"
+#include "content/renderer/pepper/host_globals.h"
+#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
+#include "ppapi/c/pp_var.h"
+
+namespace ppapi {
+
+// V8ObjectVar -----------------------------------------------------------------
+
+V8ObjectVar::V8ObjectVar(PP_Instance instance,
+ v8::Handle<v8::Object> v8_object)
+ : instance_(content::HostGlobals::Get()->GetInstance(instance)) {
+ v8_object_.Reset(instance_->GetIsolate(), v8_object);
+ content::HostGlobals::Get()->host_var_tracker()->AddV8ObjectVar(this);
+}
+
+V8ObjectVar::~V8ObjectVar() {
+ if (instance_)
+ content::HostGlobals::Get()->host_var_tracker()->RemoveV8ObjectVar(this);
+ v8_object_.Reset();
+}
+
+V8ObjectVar* V8ObjectVar::AsV8ObjectVar() {
+ return this;
+}
+
+PP_VarType V8ObjectVar::GetType() const {
+ return PP_VARTYPE_OBJECT;
+}
+
+v8::Local<v8::Object> V8ObjectVar::GetHandle() const {
+ if (instance_)
+ return v8::Local<v8::Object>::New(instance_->GetIsolate(), v8_object_);
+ return v8::Local<v8::Object>();
+}
+
+void V8ObjectVar::InstanceDeleted() {
+ // This is called by the HostVarTracker which will take care of removing us
+ // from its set.
+ DCHECK(instance_);
+ instance_ = NULL;
+}
+
+// static
+scoped_refptr<V8ObjectVar> V8ObjectVar::FromPPVar(PP_Var var) {
+ if (var.type != PP_VARTYPE_OBJECT)
+ return scoped_refptr<V8ObjectVar>(NULL);
+ scoped_refptr<Var> var_object(
+ PpapiGlobals::Get()->GetVarTracker()->GetVar(var));
+ if (!var_object.get())
+ return scoped_refptr<V8ObjectVar>();
+ return scoped_refptr<V8ObjectVar>(var_object->AsV8ObjectVar());
+}
+
+} // namespace ppapi
diff --git a/chromium/content/renderer/pepper/v8object_var.h b/chromium/content/renderer/pepper/v8object_var.h
new file mode 100644
index 00000000000..0480fbe8245
--- /dev/null
+++ b/chromium/content/renderer/pepper/v8object_var.h
@@ -0,0 +1,66 @@
+// Copyright 2014 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 CONTENT_RENDERER_PEPPER_V8OBJECT_VAR_H_
+#define CONTENT_RENDERER_PEPPER_V8OBJECT_VAR_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/shared_impl/var.h"
+#include "v8/include/v8.h"
+
+namespace content {
+class PepperPluginInstanceImpl;
+} // namespace content
+
+namespace ppapi {
+
+// V8ObjectVar -----------------------------------------------------------------
+
+// Represents a JavaScript object Var. By itself, this represents random
+// v8 objects that a given plugin (identified by the resource's module) wants to
+// reference. If two different modules reference the same v8 object (like the
+// "window" object), then there will be different V8ObjectVar's (and hence
+// PP_Var IDs) for each module. This allows us to track all references owned by
+// a given module and free them when the plugin exits independently of other
+// plugins that may be running at the same time.
+class CONTENT_EXPORT V8ObjectVar : public Var {
+ public:
+ V8ObjectVar(PP_Instance instance, v8::Handle<v8::Object> v8_object);
+
+ // Var overrides.
+ V8ObjectVar* AsV8ObjectVar() override;
+ PP_VarType GetType() const override;
+
+ // Returns the underlying v8 object corresponding to this V8ObjectVar. This
+ // should only be used on the stack.
+ v8::Local<v8::Object> GetHandle() const;
+
+ // Notification that the instance was deleted, the internal reference will be
+ // zeroed out.
+ void InstanceDeleted();
+
+ // Possibly NULL if the object has outlived its instance.
+ content::PepperPluginInstanceImpl* instance() const { return instance_; }
+
+ // Helper function that converts a PP_Var to an object. This will return NULL
+ // if the PP_Var is not of object type or the object is invalid.
+ static scoped_refptr<V8ObjectVar> FromPPVar(PP_Var var);
+
+ private:
+ ~V8ObjectVar() override;
+
+ content::PepperPluginInstanceImpl* instance_;
+
+ v8::Persistent<v8::Object> v8_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(V8ObjectVar);
+};
+
+} // ppapi
+
+#endif // CONTENT_RENDERER_PEPPER_V8OBJECT_VAR_H_
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc
index 50a63989278..9bad6c044db 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_decoder_shim.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/numerics/safe_conversions.h"
+#include "base/single_thread_task_runner.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/pepper/pepper_video_decoder_host.h"
#include "content/renderer/render_thread_impl.h"
@@ -47,11 +48,14 @@ VideoDecoderShim::PendingDecode::~PendingDecode() {
struct VideoDecoderShim::PendingFrame {
explicit PendingFrame(uint32_t decode_id);
- PendingFrame(uint32_t decode_id, const gfx::Size& size);
+ PendingFrame(uint32_t decode_id,
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect);
~PendingFrame();
const uint32_t decode_id;
- const gfx::Size size;
+ const gfx::Size coded_size;
+ const gfx::Rect visible_rect;
std::vector<uint8_t> argb_pixels;
private:
@@ -64,10 +68,12 @@ VideoDecoderShim::PendingFrame::PendingFrame(uint32_t decode_id)
}
VideoDecoderShim::PendingFrame::PendingFrame(uint32_t decode_id,
- const gfx::Size& size)
+ const gfx::Size& coded_size,
+ const gfx::Rect& visible_rect)
: decode_id(decode_id),
- size(size),
- argb_pixels(size.width() * size.height() * 4) {
+ coded_size(coded_size),
+ visible_rect(visible_rect),
+ argb_pixels(coded_size.width() * coded_size.height() * 4) {
}
VideoDecoderShim::PendingFrame::~PendingFrame() {
@@ -125,19 +131,22 @@ VideoDecoderShim::DecoderImpl::~DecoderImpl() {
void VideoDecoderShim::DecoderImpl::Initialize(
media::VideoDecoderConfig config) {
DCHECK(!decoder_);
+#if !defined(MEDIA_DISABLE_LIBVPX)
if (config.codec() == media::kCodecVP9) {
decoder_.reset(
new media::VpxVideoDecoder(base::MessageLoopProxy::current()));
- } else {
+ } else
+#endif
+ {
scoped_ptr<media::FFmpegVideoDecoder> ffmpeg_video_decoder(
new media::FFmpegVideoDecoder(base::MessageLoopProxy::current()));
ffmpeg_video_decoder->set_decode_nalus(true);
decoder_ = ffmpeg_video_decoder.Pass();
}
max_decodes_at_decoder_ = decoder_->GetMaxDecodeRequests();
- // We can use base::Unretained() safely in decoder callbacks because we call
- // VideoDecoder::Stop() before deletion. Stop() guarantees there will be no
- // outstanding callbacks after it returns.
+ // We can use base::Unretained() safely in decoder callbacks because
+ // |decoder_| is owned by DecoderImpl. During Stop(), the |decoder_| will be
+ // destroyed and all outstanding callbacks will be fired.
decoder_->Initialize(
config,
true /* low_delay */,
@@ -178,7 +187,7 @@ void VideoDecoderShim::DecoderImpl::Stop() {
// again.
while (!pending_decodes_.empty())
pending_decodes_.pop();
- decoder_->Stop();
+ decoder_.reset();
// This instance is deleted once we exit this scope.
}
@@ -255,7 +264,8 @@ void VideoDecoderShim::DecoderImpl::OnOutputComplete(
const scoped_refptr<media::VideoFrame>& frame) {
scoped_ptr<PendingFrame> pending_frame;
if (!frame->end_of_stream()) {
- pending_frame.reset(new PendingFrame(decode_id_, frame->coded_size()));
+ pending_frame.reset(new PendingFrame(
+ decode_id_, frame->coded_size(), frame->visible_rect()));
// Convert the VideoFrame pixels to ABGR to match VideoDecodeAccelerator.
libyuv::I420ToABGR(frame->data(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kYPlane),
@@ -285,16 +295,16 @@ void VideoDecoderShim::DecoderImpl::OnResetComplete() {
VideoDecoderShim::VideoDecoderShim(PepperVideoDecoderHost* host)
: state_(UNINITIALIZED),
host_(host),
- media_message_loop_(
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy()),
+ media_task_runner_(
+ RenderThreadImpl::current()->GetMediaThreadTaskRunner()),
context_provider_(
RenderThreadImpl::current()->SharedMainThreadContextProvider()),
texture_pool_size_(0),
num_pending_decodes_(0),
weak_ptr_factory_(this) {
DCHECK(host_);
- DCHECK(media_message_loop_);
- DCHECK(context_provider_);
+ DCHECK(media_task_runner_.get());
+ DCHECK(context_provider_.get());
decoder_impl_.reset(new DecoderImpl(weak_ptr_factory_.GetWeakPtr()));
}
@@ -313,7 +323,7 @@ VideoDecoderShim::~VideoDecoderShim() {
// The callback now holds the only reference to the DecoderImpl, which will be
// deleted when Stop completes.
- media_message_loop_->PostTask(
+ media_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoDecoderShim::DecoderImpl::Stop,
base::Owned(decoder_impl_.release())));
@@ -345,7 +355,7 @@ bool VideoDecoderShim::Initialize(
0 /* extra_data_size */,
false /* decryption */);
- media_message_loop_->PostTask(
+ media_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoDecoderShim::DecoderImpl::Initialize,
base::Unretained(decoder_impl_.get()),
@@ -363,7 +373,7 @@ void VideoDecoderShim::Decode(const media::BitstreamBuffer& bitstream_buffer) {
const uint8_t* buffer = host_->DecodeIdToAddress(bitstream_buffer.id());
DCHECK(buffer);
- media_message_loop_->PostTask(
+ media_task_runner_->PostTask(
FROM_HERE,
base::Bind(
&VideoDecoderShim::DecoderImpl::Decode,
@@ -385,12 +395,9 @@ void VideoDecoderShim::AssignPictureBuffers(
GLuint num_textures = base::checked_cast<GLuint>(buffers.size());
std::vector<uint32_t> local_texture_ids(num_textures);
gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
- gles2->GenTextures(num_textures, &local_texture_ids.front());
for (uint32_t i = 0; i < num_textures; i++) {
- gles2->ActiveTexture(GL_TEXTURE0);
- gles2->BindTexture(GL_TEXTURE_2D, local_texture_ids[i]);
- gles2->ConsumeTextureCHROMIUM(GL_TEXTURE_2D,
- pending_texture_mailboxes_[i].name);
+ local_texture_ids[i] = gles2->CreateAndConsumeTextureCHROMIUM(
+ GL_TEXTURE_2D, pending_texture_mailboxes_[i].name);
// Map the plugin texture id to the local texture id.
uint32_t plugin_texture_id = buffers[i].texture_id();
texture_id_map_[plugin_texture_id] = local_texture_ids[i];
@@ -423,7 +430,7 @@ void VideoDecoderShim::Reset() {
DCHECK(RenderThreadImpl::current());
DCHECK_EQ(state_, DECODING);
state_ = RESETTING;
- media_message_loop_->PostTask(
+ media_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoDecoderShim::DecoderImpl::Reset,
base::Unretained(decoder_impl_.get())));
@@ -470,7 +477,7 @@ void VideoDecoderShim::OnOutputComplete(scoped_ptr<PendingFrame> frame) {
DCHECK(host_);
if (!frame->argb_pixels.empty()) {
- if (texture_size_ != frame->size) {
+ if (texture_size_ != frame->coded_size) {
// If the size has changed, all current textures must be dismissed. Add
// all textures to |textures_to_dismiss_| and dismiss any that aren't in
// use by the plugin. We will dismiss the rest as they are recycled.
@@ -492,10 +499,10 @@ void VideoDecoderShim::OnOutputComplete(scoped_ptr<PendingFrame> frame) {
pending_texture_mailboxes_.push_back(gpu::Mailbox::Generate());
host_->RequestTextures(texture_pool_size_,
- frame->size,
+ frame->coded_size,
GL_TEXTURE_2D,
pending_texture_mailboxes_);
- texture_size_ = frame->size;
+ texture_size_ = frame->coded_size;
}
pending_frames_.push(linked_ptr<PendingFrame>(frame.release()));
@@ -527,7 +534,8 @@ void VideoDecoderShim::SendPictures() {
GL_UNSIGNED_BYTE,
&frame->argb_pixels.front());
- host_->PictureReady(media::Picture(texture_id, frame->decode_id));
+ host_->PictureReady(
+ media::Picture(texture_id, frame->decode_id, frame->visible_rect));
pending_frames_.pop();
}
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.h b/chromium/content/renderer/pepper/video_decoder_shim.h
index aa33a7485f5..42335c1f87c 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.h
+++ b/chromium/content/renderer/pepper/video_decoder_shim.h
@@ -13,13 +13,16 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "media/base/video_decoder_config.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/pp_codecs.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace gpu {
namespace gles2 {
class GLES2Interface;
@@ -47,19 +50,18 @@ class PepperVideoDecoderHost;
class VideoDecoderShim : public media::VideoDecodeAccelerator {
public:
explicit VideoDecoderShim(PepperVideoDecoderHost* host);
- virtual ~VideoDecoderShim();
+ ~VideoDecoderShim() override;
// media::VideoDecodeAccelerator implementation.
- virtual bool Initialize(
- media::VideoCodecProfile profile,
- media::VideoDecodeAccelerator::Client* client) OVERRIDE;
- virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
- virtual void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
- virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
- virtual void Flush() OVERRIDE;
- virtual void Reset() OVERRIDE;
- virtual void Destroy() OVERRIDE;
+ bool Initialize(media::VideoCodecProfile profile,
+ media::VideoDecodeAccelerator::Client* client) override;
+ void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
+ void AssignPictureBuffers(
+ const std::vector<media::PictureBuffer>& buffers) override;
+ void ReusePictureBuffer(int32 picture_buffer_id) override;
+ void Flush() override;
+ void Reset() override;
+ void Destroy() override;
private:
enum State {
@@ -89,7 +91,7 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator {
State state_;
PepperVideoDecoderHost* host_;
- scoped_refptr<base::MessageLoopProxy> media_message_loop_;
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
scoped_refptr<webkit::gpu::ContextProviderWebContext> context_provider_;
// The current decoded frame size.
diff --git a/chromium/content/renderer/push_messaging_dispatcher.cc b/chromium/content/renderer/push_messaging_dispatcher.cc
index 136862caef2..e387d3972d9 100644
--- a/chromium/content/renderer/push_messaging_dispatcher.cc
+++ b/chromium/content/renderer/push_messaging_dispatcher.cc
@@ -4,20 +4,26 @@
#include "content/renderer/push_messaging_dispatcher.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/child/service_worker/web_service_worker_provider_impl.h"
#include "content/common/push_messaging_messages.h"
-#include "content/renderer/render_view_impl.h"
+#include "content/renderer/manifest/manifest_manager.h"
+#include "content/renderer/render_frame_impl.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/platform/WebPushError.h"
#include "third_party/WebKit/public/platform/WebPushRegistration.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerProvider.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "url/gurl.h"
using blink::WebString;
namespace content {
-PushMessagingDispatcher::PushMessagingDispatcher(RenderViewImpl* render_view)
- : RenderViewObserver(render_view) {}
+PushMessagingDispatcher::PushMessagingDispatcher(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame) {
+}
PushMessagingDispatcher::~PushMessagingDispatcher() {}
@@ -26,18 +32,60 @@ bool PushMessagingDispatcher::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(PushMessagingDispatcher, message)
IPC_MESSAGE_HANDLER(PushMessagingMsg_RegisterSuccess, OnRegisterSuccess)
IPC_MESSAGE_HANDLER(PushMessagingMsg_RegisterError, OnRegisterError)
+ IPC_MESSAGE_HANDLER(PushMessagingMsg_PermissionStatusResult,
+ OnPermissionStatus)
+ IPC_MESSAGE_HANDLER(PushMessagingMsg_PermissionStatusFailure,
+ OnPermissionStatusFailure)
+
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void PushMessagingDispatcher::registerPushMessaging(
- const WebString& sender_id,
- blink::WebPushRegistrationCallbacks* callbacks) {
+ blink::WebPushRegistrationCallbacks* callbacks,
+ blink::WebServiceWorkerProvider* service_worker_provider) {
+ RenderFrameImpl::FromRoutingID(routing_id())->manifest_manager()->GetManifest(
+ base::Bind(&PushMessagingDispatcher::DoRegister,
+ base::Unretained(this),
+ callbacks,
+ service_worker_provider));
+}
+
+void PushMessagingDispatcher::DoRegister(
+ blink::WebPushRegistrationCallbacks* callbacks,
+ blink::WebServiceWorkerProvider* service_worker_provider,
+ const Manifest& manifest) {
DCHECK(callbacks);
int callbacks_id = registration_callbacks_.Add(callbacks);
+ int service_worker_provider_id = static_cast<WebServiceWorkerProviderImpl*>(
+ service_worker_provider)->provider_id();
+
+ std::string sender_id = manifest.gcm_sender_id.is_null()
+ ? std::string() : base::UTF16ToUTF8(manifest.gcm_sender_id.string());
+ if (sender_id.empty()) {
+ OnRegisterError(callbacks_id, PUSH_REGISTRATION_STATUS_NO_SENDER_ID);
+ return;
+ }
+
Send(new PushMessagingHostMsg_Register(
- routing_id(), callbacks_id, sender_id.utf8()));
+ routing_id(),
+ callbacks_id,
+ manifest.gcm_sender_id.is_null()
+ ? std::string()
+ : base::UTF16ToUTF8(manifest.gcm_sender_id.string()),
+ blink::WebUserGestureIndicator::isProcessingUserGesture(),
+ service_worker_provider_id));
+}
+
+void PushMessagingDispatcher::getPermissionStatus(
+ blink::WebPushPermissionStatusCallback* callback,
+ blink::WebServiceWorkerProvider* service_worker_provider) {
+ int permission_callback_id = permission_check_callbacks_.Add(callback);
+ int service_worker_provider_id = static_cast<WebServiceWorkerProviderImpl*>(
+ service_worker_provider)->provider_id();
+ Send(new PushMessagingHostMsg_PermissionStatus(
+ routing_id(), service_worker_provider_id, permission_callback_id));
}
void PushMessagingDispatcher::OnRegisterSuccess(
@@ -56,18 +104,33 @@ void PushMessagingDispatcher::OnRegisterSuccess(
registration_callbacks_.Remove(callbacks_id);
}
-void PushMessagingDispatcher::OnRegisterError(int32 callbacks_id) {
- const std::string kAbortErrorReason = "Registration failed.";
+void PushMessagingDispatcher::OnRegisterError(int32 callbacks_id,
+ PushRegistrationStatus status) {
blink::WebPushRegistrationCallbacks* callbacks =
registration_callbacks_.Lookup(callbacks_id);
CHECK(callbacks);
- scoped_ptr<blink::WebPushError> error(
- new blink::WebPushError(
- blink::WebPushError::ErrorTypeAbort,
- WebString::fromUTF8(kAbortErrorReason)));
+ scoped_ptr<blink::WebPushError> error(new blink::WebPushError(
+ blink::WebPushError::ErrorTypeAbort,
+ WebString::fromUTF8(PushRegistrationStatusToString(status))));
callbacks->onError(error.release());
registration_callbacks_.Remove(callbacks_id);
}
+void PushMessagingDispatcher::OnPermissionStatus(
+ int32 callback_id,
+ blink::WebPushPermissionStatus status) {
+ blink::WebPushPermissionStatusCallback* callback =
+ permission_check_callbacks_.Lookup(callback_id);
+ callback->onSuccess(&status);
+ permission_check_callbacks_.Remove(callback_id);
+}
+
+void PushMessagingDispatcher::OnPermissionStatusFailure(int32 callback_id) {
+ blink::WebPushPermissionStatusCallback* callback =
+ permission_check_callbacks_.Lookup(callback_id);
+ callback->onError();
+ permission_check_callbacks_.Remove(callback_id);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/push_messaging_dispatcher.h b/chromium/content/renderer/push_messaging_dispatcher.h
index ad441b24f03..6c472dd96b2 100644
--- a/chromium/content/renderer/push_messaging_dispatcher.h
+++ b/chromium/content/renderer/push_messaging_dispatcher.h
@@ -8,8 +8,10 @@
#include <string>
#include "base/id_map.h"
-#include "content/public/renderer/render_view_observer.h"
+#include "content/public/common/push_messaging_status.h"
+#include "content/public/renderer/render_frame_observer.h"
#include "third_party/WebKit/public/platform/WebPushClient.h"
+#include "third_party/WebKit/public/platform/WebPushPermissionStatus.h"
class GURL;
@@ -18,35 +20,49 @@ class Message;
} // namespace IPC
namespace blink {
-class WebString;
+class WebServiceWorkerProvider;
} // namespace blink
namespace content {
-class RenderViewImpl;
-class PushMessagingDispatcher : public RenderViewObserver,
+struct Manifest;
+
+class PushMessagingDispatcher : public RenderFrameObserver,
public blink::WebPushClient {
public:
- explicit PushMessagingDispatcher(RenderViewImpl* render_view);
+ explicit PushMessagingDispatcher(RenderFrame* render_frame);
virtual ~PushMessagingDispatcher();
private:
- // RenderView::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ // RenderFrame::Observer implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
// WebPushClient implementation.
virtual void registerPushMessaging(
- const blink::WebString& sender_id,
- blink::WebPushRegistrationCallbacks* callbacks) OVERRIDE;
+ blink::WebPushRegistrationCallbacks* callbacks,
+ blink::WebServiceWorkerProvider* service_worker_provider); // override
+ virtual void getPermissionStatus(
+ blink::WebPushPermissionStatusCallback* callback,
+ blink::WebServiceWorkerProvider* service_worker_provider); // override
+
+ void DoRegister(blink::WebPushRegistrationCallbacks* callbacks,
+ blink::WebServiceWorkerProvider* service_worker_provider,
+ const Manifest& manifest);
void OnRegisterSuccess(int32 callbacks_id,
const GURL& endpoint,
const std::string& registration_id);
- void OnRegisterError(int32 callbacks_id);
+ void OnRegisterError(int32 callbacks_id, PushRegistrationStatus status);
+
+ void OnPermissionStatus(int32 callback_id,
+ blink::WebPushPermissionStatus status);
+ void OnPermissionStatusFailure(int32 callback_id);
IDMap<blink::WebPushRegistrationCallbacks, IDMapOwnPointer>
registration_callbacks_;
+ IDMap<blink::WebPushPermissionStatusCallback, IDMapOwnPointer>
+ permission_check_callbacks_;
DISALLOW_COPY_AND_ASSIGN(PushMessagingDispatcher);
};
diff --git a/chromium/content/renderer/push_permission_dispatcher.cc b/chromium/content/renderer/push_permission_dispatcher.cc
new file mode 100644
index 00000000000..d5ced151a9b
--- /dev/null
+++ b/chromium/content/renderer/push_permission_dispatcher.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 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 "content/renderer/push_permission_dispatcher.h"
+
+#include "content/common/push_messaging_messages.h"
+#include "content/renderer/render_frame_impl.h"
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
+
+namespace content {
+
+PushPermissionDispatcher::PushPermissionDispatcher(RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame) {
+}
+
+PushPermissionDispatcher::~PushPermissionDispatcher() {
+}
+
+void PushPermissionDispatcher::RequestPermission(blink::WebCallback* callback) {
+ DCHECK(callback);
+ int request_id = callbacks_.Add(callback);
+ Send(new PushMessagingHostMsg_RequestPermission(
+ routing_id(),
+ request_id,
+ blink::WebUserGestureIndicator::isProcessingUserGesture()));
+}
+
+bool PushPermissionDispatcher::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PushPermissionDispatcher, message)
+ IPC_MESSAGE_HANDLER(PushMessagingMsg_RequestPermissionResponse,
+ OnRequestPermissionResponse)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void PushPermissionDispatcher::OnRequestPermissionResponse(int32 request_id) {
+ blink::WebCallback* callback = callbacks_.Lookup(request_id);
+ CHECK(callback);
+
+ callback->run();
+ callbacks_.Remove(request_id);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/push_permission_dispatcher.h b/chromium/content/renderer/push_permission_dispatcher.h
new file mode 100644
index 00000000000..b4bb3bcd594
--- /dev/null
+++ b/chromium/content/renderer/push_permission_dispatcher.h
@@ -0,0 +1,41 @@
+// Copyright 2014 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 CONTENT_RENDERER_PUSH_PERMISSION_DISPATCHER_H_
+#define CONTENT_RENDERER_PUSH_PERMISSION_DISPATCHER_H_
+
+#include "base/id_map.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "ipc/ipc_message.h"
+#include "third_party/WebKit/public/platform/WebCallback.h"
+
+namespace content {
+
+// Dispatcher for Push API permission requests.
+class PushPermissionDispatcher : public RenderFrameObserver {
+ public:
+ explicit PushPermissionDispatcher(RenderFrame* render_frame);
+ ~PushPermissionDispatcher() override;
+
+ // Requests permission to use the Push API for |origin|. The callback
+ // will be invoked when the permission status is available. This class will
+ // take ownership of |callback|.
+ void RequestPermission(blink::WebCallback* callback);
+
+ private:
+ // RenderFrame::Observer implementation.
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ void OnRequestPermissionResponse(int32 request_id);
+
+ // Tracks the active permission requests. This class takes ownership of the
+ // callback objects.
+ IDMap<blink::WebCallback, IDMapOwnPointer> callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(PushPermissionDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_PUSH_PERMISSION_DISPATCHER_H_
diff --git a/chromium/content/renderer/render_font_warmup_win.cc b/chromium/content/renderer/render_font_warmup_win.cc
new file mode 100644
index 00000000000..90bbab220bb
--- /dev/null
+++ b/chromium/content/renderer/render_font_warmup_win.cc
@@ -0,0 +1,204 @@
+// Copyright 2014 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 "content/public/renderer/render_font_warmup_win.h"
+
+#include <dwrite.h>
+
+#include "base/debug/alias.h"
+#include "base/logging.h"
+#include "base/win/iat_patch_function.h"
+#include "base/win/windows_version.h"
+#include "content/renderer/renderer_font_platform_win.h"
+#include "third_party/WebKit/public/web/win/WebFontRendering.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
+
+namespace content {
+
+namespace {
+
+SkFontMgr* g_warmup_fontmgr = NULL;
+
+base::win::IATPatchFunction g_iat_patch_open_sc_manager;
+base::win::IATPatchFunction g_iat_patch_close_service_handle;
+base::win::IATPatchFunction g_iat_patch_open_service;
+base::win::IATPatchFunction g_iat_patch_start_service;
+base::win::IATPatchFunction g_iat_patch_nt_connect_port;
+
+// These are from ntddk.h
+#if !defined(STATUS_ACCESS_DENIED)
+#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
+#endif
+
+typedef LONG NTSTATUS;
+
+SC_HANDLE WINAPI OpenSCManagerWPatch(const wchar_t* machine_name,
+ const wchar_t* database_name,
+ DWORD access_mask) {
+ ::SetLastError(0);
+ return reinterpret_cast<SC_HANDLE>(0xdeadbeef);
+}
+
+SC_HANDLE WINAPI OpenServiceWPatch(SC_HANDLE sc_manager,
+ const wchar_t* service_name,
+ DWORD access_mask) {
+ ::SetLastError(0);
+ return reinterpret_cast<SC_HANDLE>(0xdeadbabe);
+}
+
+BOOL WINAPI CloseServiceHandlePatch(SC_HANDLE service_handle) {
+ if (service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbabe) &&
+ service_handle != reinterpret_cast<SC_HANDLE>(0xdeadbeef))
+ CHECK(false);
+ ::SetLastError(0);
+ return TRUE;
+}
+
+BOOL WINAPI StartServiceWPatch(SC_HANDLE service,
+ DWORD args,
+ const wchar_t** arg_vectors) {
+ if (service != reinterpret_cast<SC_HANDLE>(0xdeadbabe))
+ CHECK(false);
+ ::SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+}
+
+NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle,
+ void* port_name,
+ void* object_attribs,
+ void* port_attribs,
+ DWORD flags,
+ void* server_sid,
+ void* message,
+ DWORD* buffer_length,
+ void* out_message_attributes,
+ void* in_message_attributes,
+ void* time_out) {
+ return STATUS_ACCESS_DENIED;
+}
+
+// Directwrite connects to the font cache service to retrieve information about
+// fonts installed on the system etc. This works well outside the sandbox and
+// within the sandbox as long as the lpc connection maintained by the current
+// process with the font cache service remains valid. It appears that there
+// are cases when this connection is dropped after which directwrite is unable
+// to connect to the font cache service which causes problems with characters
+// disappearing.
+// Directwrite has fallback code to enumerate fonts if it is unable to connect
+// to the font cache service. We need to intercept the following APIs to
+// ensure that it does not connect to the font cache service.
+// NtALpcConnectPort
+// OpenSCManagerW
+// OpenServiceW
+// StartServiceW
+// CloseServiceHandle.
+// These are all IAT patched.
+void PatchServiceManagerCalls() {
+ static bool is_patched = false;
+ if (is_patched)
+ return;
+ const char* service_provider_dll =
+ (base::win::GetVersion() >= base::win::VERSION_WIN8 ?
+ "api-ms-win-service-management-l1-1-0.dll" : "advapi32.dll");
+
+ is_patched = true;
+
+ DWORD patched = g_iat_patch_open_sc_manager.Patch(L"dwrite.dll",
+ service_provider_dll, "OpenSCManagerW", OpenSCManagerWPatch);
+ DCHECK(patched == 0);
+
+ patched = g_iat_patch_close_service_handle.Patch(L"dwrite.dll",
+ service_provider_dll, "CloseServiceHandle", CloseServiceHandlePatch);
+ DCHECK(patched == 0);
+
+ patched = g_iat_patch_open_service.Patch(L"dwrite.dll",
+ service_provider_dll, "OpenServiceW", OpenServiceWPatch);
+ DCHECK(patched == 0);
+
+ patched = g_iat_patch_start_service.Patch(L"dwrite.dll",
+ service_provider_dll, "StartServiceW", StartServiceWPatch);
+ DCHECK(patched == 0);
+
+ patched = g_iat_patch_nt_connect_port.Patch(L"dwrite.dll",
+ "ntdll.dll", "NtAlpcConnectPort", NtALpcConnectPortPatch);
+ DCHECK(patched == 0);
+}
+
+// Windows-only DirectWrite support. These warm up the DirectWrite paths
+// before sandbox lock down to allow Skia access to the Font Manager service.
+void CreateDirectWriteFactory(IDWriteFactory** factory) {
+ typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
+ HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
+ // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
+ if (!dwrite_dll) {
+ DWORD load_library_get_last_error = GetLastError();
+ base::debug::Alias(&dwrite_dll);
+ base::debug::Alias(&load_library_get_last_error);
+ CHECK(false);
+ }
+
+ PatchServiceManagerCalls();
+
+ DWriteCreateFactoryProc dwrite_create_factory_proc =
+ reinterpret_cast<DWriteCreateFactoryProc>(
+ GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
+ // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
+ if (!dwrite_create_factory_proc) {
+ DWORD get_proc_address_get_last_error = GetLastError();
+ base::debug::Alias(&dwrite_create_factory_proc);
+ base::debug::Alias(&get_proc_address_get_last_error);
+ CHECK(false);
+ }
+ CHECK(SUCCEEDED(
+ dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_ISOLATED,
+ __uuidof(IDWriteFactory),
+ reinterpret_cast<IUnknown**>(factory))));
+}
+
+HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory,
+ IDWriteFontCollection** col,
+ BOOL checkUpdates) {
+ // We always return pre-created font collection from here.
+ IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory);
+ DCHECK(custom_collection != NULL);
+ *col = custom_collection;
+ return S_OK;
+}
+
+void PatchDWriteFactory(IDWriteFactory* factory) {
+ const unsigned int kGetSystemFontCollectionVTableIndex = 3;
+
+ PROC* vtable = *reinterpret_cast<PROC**>(factory);
+ PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex];
+ void* stub_function = &StubFontCollection;
+ base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC));
+}
+
+} // namespace
+
+void DoPreSandboxWarmupForTypeface(SkTypeface* typeface) {
+ SkPaint paint_warmup;
+ paint_warmup.setTypeface(typeface);
+ wchar_t glyph = L'S';
+ paint_warmup.measureText(&glyph, 2);
+}
+
+SkFontMgr* GetPreSandboxWarmupFontMgr() {
+ if (!g_warmup_fontmgr) {
+ IDWriteFactory* factory;
+ CreateDirectWriteFactory(&factory);
+
+ IDWriteFontCollection* collection = GetCustomFontCollection(factory);
+
+ PatchDWriteFactory(factory);
+
+ blink::WebFontRendering::setDirectWriteFactory(factory);
+ g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory);
+ }
+ return g_warmup_fontmgr;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index a1445e681ee..6088aba4230 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -23,29 +23,36 @@
#include "content/child/plugin_messages.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/request_extra_data.h"
+#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_network_provider.h"
+#include "content/child/service_worker/service_worker_provider_context.h"
#include "content/child/service_worker/web_service_worker_provider_impl.h"
-#include "content/child/web_socket_stream_handle_impl.h"
+#include "content/child/web_url_loader_impl.h"
+#include "content/child/web_url_request_util.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/child/websocket_bridge.h"
+#include "content/child/weburlresponse_extradata_impl.h"
#include "content/common/clipboard_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/service_worker/service_worker_types.h"
-#include "content/common/socket_stream_handle_data.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
+#include "content/public/common/page_state.h"
+#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
+#include "content/public/renderer/browser_plugin_delegate.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/context_menu_client.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/navigation_state.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/accessibility/renderer_accessibility.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
@@ -53,25 +60,32 @@
#include "content/renderer/context_menu_params_builder.h"
#include "content/renderer/devtools/devtools_agent.h"
#include "content/renderer/dom_automation_controller.h"
+#include "content/renderer/dom_utils.h"
+#include "content/renderer/external_popup_menu.h"
#include "content/renderer/geolocation_dispatcher.h"
#include "content/renderer/history_controller.h"
#include "content/renderer/history_serialization.h"
#include "content/renderer/image_loading_helper.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/internal_document_state_data.h"
-#include "content/renderer/java/java_bridge_dispatcher.h"
+#include "content/renderer/manifest/manifest_manager.h"
#include "content/renderer/media/audio_renderer_mixer_manager.h"
+#include "content/renderer/media/crypto/encrypted_media_player_support_impl.h"
+#include "content/renderer/media/crypto/render_cdm_factory.h"
#include "content/renderer/media/media_stream_dispatcher.h"
-#include "content/renderer/media/media_stream_impl.h"
#include "content/renderer/media/media_stream_renderer_factory.h"
#include "content/renderer/media/midi_dispatcher.h"
#include "content/renderer/media/render_media_log.h"
+#include "content/renderer/media/user_media_client_impl.h"
#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
-#include "content/renderer/media/webmediaplayer_impl.h"
#include "content/renderer/media/webmediaplayer_ms.h"
-#include "content/renderer/media/webmediaplayer_params.h"
+#include "content/renderer/mojo/service_registry_js_wrapper.h"
+#include "content/renderer/notification_permission_dispatcher.h"
#include "content/renderer/notification_provider.h"
#include "content/renderer/npapi/plugin_channel_host.h"
+#include "content/renderer/push_messaging_dispatcher.h"
+#include "content/renderer/push_permission_dispatcher.h"
+#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
@@ -82,7 +96,14 @@
#include "content/renderer/shared_worker_repository.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "content/renderer/websharedworker_proxy.h"
+#include "gin/modules/module_registry.h"
#include "media/base/audio_renderer_mixer_input.h"
+#include "media/base/renderer.h"
+#include "media/blink/webmediaplayer_impl.h"
+#include "media/blink/webmediaplayer_params.h"
+#include "media/filters/gpu_video_accelerator_factories.h"
+#include "mojo/edk/js/core.h"
+#include "mojo/edk/js/support.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
@@ -101,6 +122,7 @@
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
+#include "third_party/WebKit/public/web/WebPluginPlaceholder.h"
#include "third_party/WebKit/public/web/WebRange.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSearchableFormData.h"
@@ -109,7 +131,6 @@
#include "third_party/WebKit/public/web/WebSurroundingText.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "webkit/child/weburlresponse_extradata_impl.h"
#if defined(ENABLE_PLUGINS)
#include "content/renderer/npapi/webplugin_impl.h"
@@ -117,6 +138,7 @@
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
#include "content/renderer/pepper/plugin_module.h"
+#include "content/renderer/pepper/plugin_power_saver_helper.h"
#endif
#if defined(ENABLE_WEBRTC)
@@ -128,12 +150,15 @@
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/renderer/android/synchronous_compositor_factory.h"
+#include "content/renderer/java/gin_java_bridge_dispatcher.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/android/stream_texture_factory_impl.h"
#include "content/renderer/media/android/webmediaplayer_android.h"
#endif
-#if defined(ENABLE_BROWSER_CDMS)
+#if defined(ENABLE_PEPPER_CDMS)
+#include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
+#elif defined(ENABLE_BROWSER_CDMS)
#include "content/renderer/media/crypto/renderer_cdm_manager.h"
#endif
@@ -142,6 +167,8 @@ using blink::WebData;
using blink::WebDataSource;
using blink::WebDocument;
using blink::WebElement;
+using blink::WebExternalPopupMenu;
+using blink::WebExternalPopupMenuClient;
using blink::WebFrame;
using blink::WebHistoryItem;
using blink::WebHTTPBody;
@@ -152,6 +179,7 @@ using blink::WebNavigationPolicy;
using blink::WebNavigationType;
using blink::WebNode;
using blink::WebPluginParams;
+using blink::WebPopupMenuInfo;
using blink::WebRange;
using blink::WebReferrerPolicy;
using blink::WebScriptSource;
@@ -170,7 +198,6 @@ using blink::WebVector;
using blink::WebView;
using base::Time;
using base::TimeDelta;
-using webkit_glue::WebURLResponseExtraDataImpl;
namespace content {
@@ -257,7 +284,6 @@ NOINLINE static void MaybeTriggerAsanError(const GURL& url) {
const char kCorruptHeapBlock[] = "/corrupt-heap-block";
const char kCorruptHeap[] = "/corrupt-heap";
#endif
- const int kArraySize = 5;
if (!url.DomainIs(kCrashDomain, sizeof(kCrashDomain) - 1))
return;
@@ -346,6 +372,109 @@ static bool IsNonLocalTopLevelNavigation(const GURL& url,
return false;
}
+WebURLRequest CreateURLRequestForNavigation(
+ const CommonNavigationParams& common_params,
+ const RequestNavigationParams& request_params,
+ scoped_ptr<StreamOverrideParameters> stream_override,
+ bool is_view_source_mode_enabled) {
+ WebURLRequest request(common_params.url);
+ if (is_view_source_mode_enabled)
+ request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
+
+ if (common_params.referrer.url.is_valid()) {
+ WebString web_referrer = WebSecurityPolicy::generateReferrerHeader(
+ common_params.referrer.policy,
+ common_params.url,
+ WebString::fromUTF8(common_params.referrer.url.spec()));
+ if (!web_referrer.isEmpty())
+ request.setHTTPReferrer(web_referrer, common_params.referrer.policy);
+ }
+
+ if (!request_params.extra_headers.empty()) {
+ for (net::HttpUtil::HeadersIterator i(request_params.extra_headers.begin(),
+ request_params.extra_headers.end(),
+ "\n");
+ i.GetNext();) {
+ request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
+ WebString::fromUTF8(i.values()));
+ }
+ }
+
+ if (request_params.is_post) {
+ request.setHTTPMethod(WebString::fromUTF8("POST"));
+
+ // Set post data.
+ WebHTTPBody http_body;
+ http_body.initialize();
+ const char* data = NULL;
+ if (request_params.browser_initiated_post_data.size()) {
+ data = reinterpret_cast<const char*>(
+ &request_params.browser_initiated_post_data.front());
+ }
+ http_body.appendData(
+ WebData(data, request_params.browser_initiated_post_data.size()));
+ request.setHTTPBody(http_body);
+ }
+
+ RequestExtraData* extra_data = new RequestExtraData();
+ extra_data->set_stream_override(stream_override.Pass());
+ request.setExtraData(extra_data);
+ return request;
+}
+
+void UpdateFrameNavigationTiming(WebFrame* frame,
+ base::TimeTicks browser_navigation_start,
+ base::TimeTicks renderer_navigation_start) {
+ // The browser provides the navigation_start time to bootstrap the
+ // Navigation Timing information for the browser-initiated navigations. In
+ // case of cross-process navigations, this carries over the time of
+ // finishing the onbeforeunload handler of the previous page.
+ DCHECK(!browser_navigation_start.is_null());
+ if (frame->provisionalDataSource()) {
+ // |browser_navigation_start| is likely before this process existed, so we
+ // can't use InterProcessTimeTicksConverter. We need at least to ensure
+ // that the browser-side navigation start we set is not later than the one
+ // on the renderer side.
+ base::TimeTicks navigation_start = std::min(
+ browser_navigation_start, renderer_navigation_start);
+ double navigation_start_seconds =
+ (navigation_start - base::TimeTicks()).InSecondsF();
+ frame->provisionalDataSource()->setNavigationStartTime(
+ navigation_start_seconds);
+ // TODO(clamy): We need to provide additional timing values for the
+ // Navigation Timing API to work with browser-side navigations.
+ }
+}
+
+// PlzNavigate
+FrameHostMsg_BeginNavigation_Params MakeBeginNavigationParams(
+ const blink::WebURLRequest& request) {
+ FrameHostMsg_BeginNavigation_Params params;
+ params.method = request.httpMethod().latin1();
+ params.headers = GetWebURLRequestHeaders(request);
+ params.load_flags = GetLoadFlagsForWebURLRequest(request);
+ // TODO(clamy): fill the http body.
+ params.has_user_gesture = request.hasUserGesture();
+ return params;
+}
+
+// PlzNavigate
+CommonNavigationParams MakeCommonNavigationParams(
+ const blink::WebURLRequest& request) {
+ const RequestExtraData kEmptyData;
+ const RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request.extraData());
+ if (!extra_data)
+ extra_data = &kEmptyData;
+ CommonNavigationParams params;
+ params.url = request.url();
+ params.referrer = Referrer(
+ GURL(request.httpHeaderField(WebString::fromUTF8("Referer")).latin1()),
+ request.referrerPolicy());
+ params.transition = extra_data->transition_type();
+ return params;
+}
+
} // namespace
static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
@@ -372,10 +501,47 @@ RenderFrameImpl* RenderFrameImpl::FromRoutingID(int32 routing_id) {
}
// static
+void RenderFrameImpl::CreateFrame(int routing_id,
+ int parent_routing_id,
+ int proxy_routing_id) {
+ // TODO(nasko): For now, this message is only sent for subframes, as the
+ // top level frame is created when the RenderView is created through the
+ // ViewMsg_New IPC.
+ CHECK_NE(MSG_ROUTING_NONE, parent_routing_id);
+
+ blink::WebLocalFrame* web_frame;
+ RenderFrameImpl* render_frame;
+ if (proxy_routing_id == MSG_ROUTING_NONE) {
+ RenderFrameProxy* parent_proxy =
+ RenderFrameProxy::FromRoutingID(parent_routing_id);
+ // If the browser is sending a valid parent routing id, it should already
+ // be created and registered.
+ CHECK(parent_proxy);
+ blink::WebRemoteFrame* parent_web_frame = parent_proxy->web_frame();
+
+ // Create the RenderFrame and WebLocalFrame, linking the two.
+ render_frame =
+ RenderFrameImpl::Create(parent_proxy->render_view(), routing_id);
+ web_frame = parent_web_frame->createLocalChild("", render_frame);
+ } else {
+ RenderFrameProxy* proxy =
+ RenderFrameProxy::FromRoutingID(proxy_routing_id);
+ CHECK(proxy);
+ render_frame = RenderFrameImpl::Create(proxy->render_view(), routing_id);
+ web_frame = blink::WebLocalFrame::create(render_frame);
+ render_frame->proxy_routing_id_ = proxy_routing_id;
+ web_frame->initializeToReplaceRemoteFrame(proxy->web_frame());
+ }
+ render_frame->SetWebFrame(web_frame);
+ render_frame->Initialize();
+}
+
+// static
RenderFrame* RenderFrame::FromWebFrame(blink::WebFrame* web_frame) {
return RenderFrameImpl::FromWebFrame(web_frame);
}
+// static
RenderFrameImpl* RenderFrameImpl::FromWebFrame(blink::WebFrame* web_frame) {
FrameMap::iterator iter = g_frame_map.Get().find(web_frame);
if (iter != g_frame_map.Get().end())
@@ -398,10 +564,15 @@ RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
is_swapped_out_(false),
render_frame_proxy_(NULL),
is_detaching_(false),
+ proxy_routing_id_(MSG_ROUTING_NONE),
+#if defined(ENABLE_PLUGINS)
+ plugin_power_saver_helper_(NULL),
+#endif
cookie_jar_(this),
selection_text_offset_(0),
selection_range_(gfx::Range::InvalidRange()),
handling_select_range_(false),
+ notification_permission_dispatcher_(NULL),
notification_provider_(NULL),
web_user_media_client_(NULL),
midi_dispatcher_(NULL),
@@ -411,35 +582,53 @@ RenderFrameImpl::RenderFrameImpl(RenderViewImpl* render_view, int routing_id)
#if defined(ENABLE_BROWSER_CDMS)
cdm_manager_(NULL),
#endif
+#if defined(VIDEO_HOLE)
+ contains_media_player_(false),
+#endif
geolocation_dispatcher_(NULL),
+ push_messaging_dispatcher_(NULL),
screen_orientation_dispatcher_(NULL),
+ manifest_manager_(NULL),
+ accessibility_mode_(AccessibilityModeOff),
+ renderer_accessibility_(NULL),
weak_factory_(this) {
- RenderThread::Get()->AddRoute(routing_id_, this);
-
std::pair<RoutingIDFrameMap::iterator, bool> result =
g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this));
CHECK(result.second) << "Inserting a duplicate item.";
+ RenderThread::Get()->AddRoute(routing_id_, this);
+
render_view_->RegisterRenderFrame(this);
+ // Everything below subclasses RenderFrameObserver and is automatically
+ // deleted when the RenderFrame gets deleted.
#if defined(OS_ANDROID)
- new JavaBridgeDispatcher(this);
+ new GinJavaBridgeDispatcher(this);
+#endif
+
+#if defined(ENABLE_PLUGINS)
+ plugin_power_saver_helper_ = new PluginPowerSaverHelper(this);
#endif
#if defined(ENABLE_NOTIFICATIONS)
notification_provider_ = new NotificationProvider(this);
#endif
+
+ manifest_manager_ = new ManifestManager(this);
}
RenderFrameImpl::~RenderFrameImpl() {
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
-#if defined(OS_ANDROID) && defined(VIDEO_HOLE)
- if (media_player_manager_)
+#if defined(VIDEO_HOLE)
+ if (contains_media_player_)
render_view_->UnregisterVideoHoleFrame(this);
#endif
+ if (render_frame_proxy_)
+ delete render_frame_proxy_;
+
render_view_->UnregisterRenderFrame(this);
g_routing_id_frame_map.Get().erase(routing_id_);
RenderThread::Get()->RemoveRoute(routing_id_);
@@ -477,6 +666,10 @@ RenderWidget* RenderFrameImpl::GetRenderWidget() {
void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) {
FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
DidCreatePepperPlugin(host));
+ if (host->GetPluginName() == kFlashPluginName) {
+ RenderThread::Get()->RecordAction(
+ base::UserMetricsAction("FrameLoadWithFlash"));
+ }
}
void RenderFrameImpl::PepperDidChangeCursor(
@@ -501,10 +694,9 @@ void RenderFrameImpl::PepperTextInputTypeChanged(
if (instance != render_view_->focused_pepper_plugin())
return;
- GetRenderWidget()->UpdateTextInputState(
- RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
- if (render_view_->renderer_accessibility())
- render_view_->renderer_accessibility()->FocusedNodeChanged(WebNode());
+ GetRenderWidget()->UpdateTextInputType();
+ if (renderer_accessibility())
+ renderer_accessibility()->FocusedNodeChanged(WebNode());
}
void RenderFrameImpl::PepperCaretPositionChanged(
@@ -518,7 +710,7 @@ void RenderFrameImpl::PepperCancelComposition(
PepperPluginInstanceImpl* instance) {
if (instance != render_view_->focused_pepper_plugin())
return;
- Send(new ViewHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));;
+ Send(new InputHostMsg_ImeCancelComposition(render_view_->GetRoutingID()));;
#if defined(OS_MACOSX) || defined(USE_AURA)
GetRenderWidget()->UpdateCompositionInfo(true);
#endif
@@ -572,7 +764,6 @@ void RenderFrameImpl::SimulateImeConfirmComposition(
render_view_->OnImeConfirmComposition(text, replacement_range, false);
}
-
void RenderFrameImpl::OnImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
@@ -652,18 +843,31 @@ void RenderFrameImpl::OnImeConfirmComposition(
pepper_composition_text_.clear();
}
-#endif // ENABLE_PLUGINS
+PluginPowerSaverHelper* RenderFrameImpl::plugin_power_saver_helper() {
+ DCHECK(plugin_power_saver_helper_);
+ return plugin_power_saver_helper_;
+}
+#endif // defined(ENABLE_PLUGINS)
+
+MediaStreamDispatcher* RenderFrameImpl::GetMediaStreamDispatcher() {
+ if (!web_user_media_client_)
+ InitializeUserMediaClient();
+ return web_user_media_client_ ?
+ web_user_media_client_->media_stream_dispatcher() : NULL;
+}
bool RenderFrameImpl::Send(IPC::Message* message) {
if (is_detaching_) {
delete message;
return false;
}
- if (is_swapped_out_ || render_view_->is_swapped_out()) {
+ if (frame_->parent() == NULL &&
+ (is_swapped_out_ || render_view_->is_swapped_out())) {
if (!SwappedOutMessages::CanSendWhileSwappedOut(message)) {
delete message;
return false;
}
+
// In most cases, send IPCs through the proxy when swapped out. In some
// calls the associated RenderViewImpl routing id is used to send
// messages, so don't use the proxy.
@@ -674,8 +878,22 @@ bool RenderFrameImpl::Send(IPC::Message* message) {
return RenderThread::Get()->Send(message);
}
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+void RenderFrameImpl::DidHideExternalPopupMenu() {
+ // We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close
+ // is called. Otherwise, createExternalPopupMenu() for new popup will fail.
+ external_popup_menu_.reset();
+}
+#endif
+
bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
- GetContentClient()->SetActiveURL(frame_->document().url());
+ // TODO(kenrb): document() should not be null, but as a transitional step
+ // we have RenderFrameProxy 'wrapping' a RenderFrameImpl, passing messages
+ // to this method. This happens for a top-level remote frame, where a
+ // document-less RenderFrame is replaced by a RenderFrameProxy but kept
+ // around and is still able to receive messages.
+ if (!frame_->document().isNull())
+ GetContentClient()->SetActiveURL(frame_->document().url());
ObserverListBase<RenderFrameObserver>::Iterator it(observers_);
RenderFrameObserver* observer;
@@ -689,6 +907,7 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_Navigate, OnNavigate)
IPC_MESSAGE_HANDLER(FrameMsg_BeforeUnload, OnBeforeUnload)
IPC_MESSAGE_HANDLER(FrameMsg_SwapOut, OnSwapOut)
+ IPC_MESSAGE_HANDLER(FrameMsg_Stop, OnStop)
IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed)
IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction,
OnCustomContextMenuAction)
@@ -702,23 +921,37 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
+ IPC_MESSAGE_HANDLER(InputMsg_MoveRangeSelectionExtent,
+ OnMoveRangeSelectionExtent)
IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
+ IPC_MESSAGE_HANDLER(InputMsg_ExtendSelectionAndDelete,
+ OnExtendSelectionAndDelete)
+ IPC_MESSAGE_HANDLER(InputMsg_SetCompositionFromExistingText,
+ OnSetCompositionFromExistingText)
IPC_MESSAGE_HANDLER(FrameMsg_CSSInsertRequest, OnCSSInsertRequest)
IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequest,
OnJavaScriptExecuteRequest)
+ IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequestForTests,
+ OnJavaScriptExecuteRequestForTests)
IPC_MESSAGE_HANDLER(FrameMsg_SetEditableSelectionOffsets,
OnSetEditableSelectionOffsets)
- IPC_MESSAGE_HANDLER(FrameMsg_SetCompositionFromExistingText,
- OnSetCompositionFromExistingText)
- IPC_MESSAGE_HANDLER(FrameMsg_ExtendSelectionAndDelete,
- OnExtendSelectionAndDelete)
+ IPC_MESSAGE_HANDLER(FrameMsg_SetupTransitionView, OnSetupTransitionView)
+ IPC_MESSAGE_HANDLER(FrameMsg_BeginExitTransition, OnBeginExitTransition)
IPC_MESSAGE_HANDLER(FrameMsg_Reload, OnReload)
IPC_MESSAGE_HANDLER(FrameMsg_TextSurroundingSelectionRequest,
OnTextSurroundingSelectionRequest)
IPC_MESSAGE_HANDLER(FrameMsg_AddStyleSheetByURL,
OnAddStyleSheetByURL)
-#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(FrameMsg_SetAccessibilityMode,
+ OnSetAccessibilityMode)
+ IPC_MESSAGE_HANDLER(FrameMsg_DisownOpener, OnDisownOpener)
+ IPC_MESSAGE_HANDLER(FrameMsg_RequestNavigation, OnRequestNavigation)
+ IPC_MESSAGE_HANDLER(FrameMsg_CommitNavigation, OnCommitNavigation)
+#if defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
+#elif defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
#endif
IPC_END_MESSAGE_MAP()
@@ -727,63 +960,41 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
}
void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
- MaybeHandleDebugURL(params.url);
- if (!render_view_->webview())
- return;
-
- FOR_EACH_OBSERVER(
- RenderViewObserver, render_view_->observers_, Navigate(params.url));
-
- bool is_reload = RenderViewImpl::IsReload(params);
+ TRACE_EVENT2("navigation", "RenderFrameImpl::OnNavigate",
+ "id", routing_id_,
+ "url", params.common_params.url.possibly_invalid_spec());
+ bool is_reload =
+ RenderViewImpl::IsReload(params.common_params.navigation_type);
WebURLRequest::CachePolicy cache_policy =
WebURLRequest::UseProtocolCachePolicy;
-
- // If this is a stale back/forward (due to a recent navigation the browser
- // didn't know about), ignore it.
- if (render_view_->IsBackForwardToStaleEntry(params, is_reload))
+ if (!RenderFrameImpl::PrepareRenderViewForNavigation(
+ params.common_params.url, params.common_params.navigation_type,
+ params.commit_params.page_state, true, params.pending_history_list_offset,
+ params.page_id, &is_reload, &cache_policy)) {
return;
-
- // Swap this renderer back in if necessary.
- if (render_view_->is_swapped_out_) {
- // We marked the view as hidden when swapping the view out, so be sure to
- // reset the visibility state before navigating to the new URL.
- render_view_->webview()->setVisibilityState(
- render_view_->visibilityState(), false);
-
- // If this is an attempt to reload while we are swapped out, we should not
- // reload swappedout://, but the previous page, which is stored in
- // params.state. Setting is_reload to false will treat this like a back
- // navigation to accomplish that.
- is_reload = false;
- cache_policy = WebURLRequest::ReloadIgnoringCacheData;
-
- // We refresh timezone when a view is swapped in since timezone
- // can get out of sync when the system timezone is updated while
- // the view is swapped out.
- RenderThreadImpl::NotifyTimezoneChange();
-
- render_view_->SetSwappedOut(false);
- is_swapped_out_ = false;
}
+ int pending_history_list_offset = params.pending_history_list_offset;
+ int current_history_list_offset = params.current_history_list_offset;
+ int current_history_list_length = params.current_history_list_length;
if (params.should_clear_history_list) {
- CHECK_EQ(params.pending_history_list_offset, -1);
- CHECK_EQ(params.current_history_list_offset, -1);
- CHECK_EQ(params.current_history_list_length, 0);
+ CHECK_EQ(pending_history_list_offset, -1);
+ CHECK_EQ(current_history_list_offset, -1);
+ CHECK_EQ(current_history_list_length, 0);
}
- render_view_->history_list_offset_ = params.current_history_list_offset;
- render_view_->history_list_length_ = params.current_history_list_length;
+ render_view_->history_list_offset_ = current_history_list_offset;
+ render_view_->history_list_length_ = current_history_list_length;
if (render_view_->history_list_length_ >= 0) {
render_view_->history_page_ids_.resize(
render_view_->history_list_length_, -1);
}
- if (params.pending_history_list_offset >= 0 &&
- params.pending_history_list_offset < render_view_->history_list_length_) {
- render_view_->history_page_ids_[params.pending_history_list_offset] =
+ if (pending_history_list_offset >= 0 &&
+ pending_history_list_offset < render_view_->history_list_length_) {
+ render_view_->history_page_ids_[pending_history_list_offset] =
params.page_id;
}
- GetContentClient()->SetActiveURL(params.url);
+ GetContentClient()->SetActiveURL(params.common_params.url);
WebFrame* frame = frame_;
if (!params.frame_to_navigate.empty()) {
@@ -809,20 +1020,20 @@ void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
// back/forward navigation event.
if (is_reload) {
bool reload_original_url =
- (params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
- bool ignore_cache = (params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
+ (params.common_params.navigation_type ==
+ FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
+ bool ignore_cache = (params.common_params.navigation_type ==
+ FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
if (reload_original_url)
- frame->reloadWithOverrideURL(params.url, true);
+ frame->reloadWithOverrideURL(params.common_params.url, true);
else
frame->reload(ignore_cache);
- } else if (params.page_state.IsValid()) {
+ } else if (params.commit_params.page_state.IsValid()) {
// We must know the page ID of the page we are navigating back to.
DCHECK_NE(params.page_id, -1);
scoped_ptr<HistoryEntry> entry =
- PageStateToHistoryEntry(params.page_state);
+ PageStateToHistoryEntry(params.commit_params.page_state);
if (entry) {
// Ensure we didn't save the swapped out URL in UpdateState, since the
// browser should never be telling us to navigate to swappedout://.
@@ -832,7 +1043,8 @@ void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
} else if (!params.base_url_for_data_url.is_empty()) {
// A loadData request with a specified base URL.
std::string mime_type, charset, data;
- if (net::DataURL::Parse(params.url, &mime_type, &charset, &data)) {
+ if (net::DataURL::Parse(
+ params.common_params.url, &mime_type, &charset, &data)) {
frame->loadData(
WebData(data.c_str(), data.length()),
WebString::fromUTF8(mime_type),
@@ -841,76 +1053,46 @@ void RenderFrameImpl::OnNavigate(const FrameMsg_Navigate_Params& params) {
params.history_url_for_data_url,
false);
} else {
- CHECK(false) <<
- "Invalid URL passed: " << params.url.possibly_invalid_spec();
+ CHECK(false) << "Invalid URL passed: "
+ << params.common_params.url.possibly_invalid_spec();
}
} else {
// Navigate to the given URL.
- WebURLRequest request(params.url);
+ WebURLRequest request =
+ CreateURLRequestForNavigation(params.common_params,
+ params.request_params,
+ scoped_ptr<StreamOverrideParameters>(),
+ frame->isViewSourceModeEnabled());
// A session history navigation should have been accompanied by state.
CHECK_EQ(params.page_id, -1);
- if (frame->isViewSourceModeEnabled())
- request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
-
- if (params.referrer.url.is_valid()) {
- WebString referrer = WebSecurityPolicy::generateReferrerHeader(
- params.referrer.policy,
- params.url,
- WebString::fromUTF8(params.referrer.url.spec()));
- if (!referrer.isEmpty())
- request.setHTTPReferrer(referrer, params.referrer.policy);
- }
-
- if (!params.extra_headers.empty()) {
- for (net::HttpUtil::HeadersIterator i(params.extra_headers.begin(),
- params.extra_headers.end(), "\n");
- i.GetNext(); ) {
- request.addHTTPHeaderField(WebString::fromUTF8(i.name()),
- WebString::fromUTF8(i.values()));
- }
- }
-
- if (params.is_post) {
- request.setHTTPMethod(WebString::fromUTF8("POST"));
-
- // Set post data.
- WebHTTPBody http_body;
- http_body.initialize();
- const char* data = NULL;
- if (params.browser_initiated_post_data.size()) {
- data = reinterpret_cast<const char*>(
- &params.browser_initiated_post_data.front());
- }
- http_body.appendData(
- WebData(data, params.browser_initiated_post_data.size()));
- request.setHTTPBody(http_body);
- }
-
+ // Record this before starting the load, we need a lower bound of this time
+ // to sanitize the navigationStart override set below.
+ base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
frame->loadRequest(request);
- // If this is a cross-process navigation, the browser process will send
- // along the proper navigation start value.
- if (!params.browser_navigation_start.is_null() &&
- frame->provisionalDataSource()) {
- // browser_navigation_start is likely before this process existed, so we
- // can't use InterProcessTimeTicksConverter. Instead, the best we can do
- // is just ensure we don't report a bogus value in the future.
- base::TimeTicks navigation_start = std::min(
- base::TimeTicks::Now(), params.browser_navigation_start);
- double navigation_start_seconds =
- (navigation_start - base::TimeTicks()).InSecondsF();
- frame->provisionalDataSource()->setNavigationStartTime(
- navigation_start_seconds);
- }
+ UpdateFrameNavigationTiming(
+ frame, params.commit_params.browser_navigation_start,
+ renderer_navigation_start);
}
// In case LoadRequest failed before DidCreateDataSource was called.
render_view_->pending_navigation_params_.reset();
}
+void RenderFrameImpl::BindServiceRegistry(
+ mojo::ScopedMessagePipeHandle service_provider_handle) {
+ service_registry_.BindRemoteServiceProvider(service_provider_handle.Pass());
+}
+
+ManifestManager* RenderFrameImpl::manifest_manager() {
+ return manifest_manager_;
+}
+
void RenderFrameImpl::OnBeforeUnload() {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::OnBeforeUnload",
+ "id", routing_id_);
// TODO(creis): Right now, this is only called on the main frame. Make the
// browser process send dispatchBeforeUnloadEvent to every frame that needs
// it.
@@ -925,29 +1107,38 @@ void RenderFrameImpl::OnBeforeUnload() {
}
void RenderFrameImpl::OnSwapOut(int proxy_routing_id) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::OnSwapOut", "id", routing_id_);
RenderFrameProxy* proxy = NULL;
+ bool is_site_per_process =
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess);
+ bool is_main_frame = !frame_->parent();
// Only run unload if we're not swapped out yet, but send the ack either way.
if (!is_swapped_out_ || !render_view_->is_swapped_out_) {
// Swap this RenderFrame out so the frame can navigate to a page rendered by
// a different process. This involves running the unload handler and
- // clearing the page. Once WasSwappedOut is called, we also allow this
- // process to exit if there are no other active RenderFrames in it.
+ // clearing the page. We also allow this process to exit if there are no
+ // other active RenderFrames in it.
- // Send an UpdateState message before we get swapped out. Create the
- // RenderFrameProxy as well so its routing id is registered for receiving
- // IPC messages.
+ // Send an UpdateState message before we get swapped out.
render_view_->SyncNavigationState();
- proxy = RenderFrameProxy::CreateFrameProxy(proxy_routing_id, routing_id_);
+
+ // If we need a proxy to replace this, create it now so its routing id is
+ // registered for receiving IPC messages.
+ if (proxy_routing_id != MSG_ROUTING_NONE) {
+ proxy = RenderFrameProxy::CreateProxyToReplaceFrame(this,
+ proxy_routing_id);
+ }
// Synchronously run the unload handler before sending the ACK.
// TODO(creis): Call dispatchUnloadEvent unconditionally here to support
// unload on subframes as well.
- if (!frame_->parent())
+ if (is_main_frame)
frame_->dispatchUnloadEvent();
// Swap out and stop sending any IPC messages that are not ACKs.
- if (!frame_->parent())
+ // TODO(nasko): Do we need RenderFrameImpl::is_swapped_out_ anymore?
+ if (is_main_frame)
render_view_->SetSwappedOut(true);
is_swapped_out_ = true;
@@ -957,26 +1148,24 @@ void RenderFrameImpl::OnSwapOut(int proxy_routing_id) {
// TODO(creis): Should we be stopping all frames here and using
// StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
// frame?
- if (!frame_->parent())
- render_view_->OnStop();
- else
- frame_->stopLoading();
+ OnStop();
- // Let subframes know that the frame is now rendered remotely, for the
- // purposes of compositing and input events.
- if (frame_->parent())
- frame_->setIsRemote(true);
+ // Transfer settings such as initial drawing parameters to the remote frame,
+ // if one is created, that will replace this frame.
+ if (!is_main_frame && proxy)
+ proxy->web_frame()->initializeFromFrame(frame_);
// Replace the page with a blank dummy URL. The unload handler will not be
// run a second time, thanks to a check in FrameLoader::stopLoading.
// TODO(creis): Need to add a better way to do this that avoids running the
// beforeunload handler. For now, we just run it a second time silently.
- render_view_->NavigateToSwappedOutURL(frame_);
+ if (!is_site_per_process || is_main_frame)
+ render_view_->NavigateToSwappedOutURL(frame_);
// Let WebKit know that this view is hidden so it can drop resources and
// stop compositing.
// TODO(creis): Support this for subframes as well.
- if (!frame_->parent()) {
+ if (is_main_frame) {
render_view_->webview()->setVisibilityState(
blink::WebPageVisibilityStateHidden, false);
}
@@ -984,15 +1173,28 @@ void RenderFrameImpl::OnSwapOut(int proxy_routing_id) {
// It is now safe to show modal dialogs again.
// TODO(creis): Deal with modal dialogs from subframes.
- if (!frame_->parent())
+ if (is_main_frame)
render_view_->suppress_dialogs_until_swap_out_ = false;
Send(new FrameHostMsg_SwapOut_ACK(routing_id_));
// Now that all of the cleanup is complete and the browser side is notified,
// start using the RenderFrameProxy, if one is created.
- if (proxy)
- set_render_frame_proxy(proxy);
+ if (proxy) {
+ if (!is_main_frame) {
+ frame_->swap(proxy->web_frame());
+ if (is_site_per_process) {
+ // TODO(nasko): delete the frame here, since we've replaced it with a
+ // proxy.
+ }
+ } else {
+ set_render_frame_proxy(proxy);
+ }
+ }
+
+ // Safe to exit if no one else is using the process.
+ if (is_main_frame)
+ render_view_->WasSwappedOut();
}
void RenderFrameImpl::OnContextMenuClosed(
@@ -1006,6 +1208,11 @@ void RenderFrameImpl::OnContextMenuClosed(
pending_context_menus_.Remove(custom_context.request_id);
}
} else {
+ if (custom_context.link_followed.is_valid()) {
+ frame_->sendPings(
+ DomUtils::ExtractParentAnchorNode(context_menu_node_),
+ custom_context.link_followed);
+ }
// Internal request, forward to WebKit.
context_menu_node_.reset();
}
@@ -1078,13 +1285,13 @@ void RenderFrameImpl::OnSelectAll() {
frame_->executeCommand(WebString::fromUTF8("SelectAll"), GetFocusedElement());
}
-void RenderFrameImpl::OnSelectRange(const gfx::Point& start,
- const gfx::Point& end) {
+void RenderFrameImpl::OnSelectRange(const gfx::Point& base,
+ const gfx::Point& extent) {
// This IPC is dispatched by RenderWidgetHost, so use its routing id.
- Send(new ViewHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
+ Send(new InputHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
- frame_->selectRange(start, end);
+ frame_->selectRange(base, extent);
}
void RenderFrameImpl::OnUnselect() {
@@ -1092,6 +1299,15 @@ void RenderFrameImpl::OnUnselect() {
frame_->executeCommand(WebString::fromUTF8("Unselect"), GetFocusedElement());
}
+void RenderFrameImpl::OnMoveRangeSelectionExtent(const gfx::Point& point) {
+ // This IPC is dispatched by RenderWidgetHost, so use its routing id.
+ Send(new InputHostMsg_MoveRangeSelectionExtent_ACK(
+ GetRenderWidget()->routing_id()));
+
+ base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+ frame_->moveRangeSelectionExtent(point);
+}
+
void RenderFrameImpl::OnReplace(const base::string16& text) {
if (!frame_->hasSelection())
frame_->selectWordAroundCaret();
@@ -1120,6 +1336,29 @@ void RenderFrameImpl::OnJavaScriptExecuteRequest(
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
v8::Handle<v8::Value> result =
frame_->executeScriptAndReturnValue(WebScriptSource(jscript));
+
+ HandleJavascriptExecutionResult(jscript, id, notify_result, result);
+}
+
+void RenderFrameImpl::OnJavaScriptExecuteRequestForTests(
+ const base::string16& jscript,
+ int id,
+ bool notify_result) {
+ TRACE_EVENT_INSTANT0("test_tracing", "OnJavaScriptExecuteRequestForTests",
+ TRACE_EVENT_SCOPE_THREAD);
+
+ v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
+ v8::Handle<v8::Value> result =
+ frame_->executeScriptAndReturnValueForTests(WebScriptSource(jscript));
+
+ HandleJavascriptExecutionResult(jscript, id, notify_result, result);
+}
+
+void RenderFrameImpl::HandleJavascriptExecutionResult(
+ const base::string16& jscript,
+ int id,
+ bool notify_result,
+ v8::Handle<v8::Value> result) {
if (notify_result) {
base::ListValue list;
if (!result.IsEmpty()) {
@@ -1161,6 +1400,61 @@ void RenderFrameImpl::OnExtendSelectionAndDelete(int before, int after) {
frame_->extendSelectionAndDelete(before, after);
}
+void RenderFrameImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
+ if (accessibility_mode_ == new_mode)
+ return;
+ accessibility_mode_ = new_mode;
+ if (renderer_accessibility_) {
+ // Note: this isn't called automatically by the destructor because
+ // there'd be no point in calling it in frame teardown, only if there's
+ // an accessibility mode change but the frame is persisting.
+ renderer_accessibility_->DisableAccessibility();
+
+ delete renderer_accessibility_;
+ renderer_accessibility_ = NULL;
+ }
+ if (accessibility_mode_ == AccessibilityModeOff)
+ return;
+
+ if (accessibility_mode_ & AccessibilityModeFlagFullTree)
+ renderer_accessibility_ = new RendererAccessibility(this);
+}
+
+void RenderFrameImpl::OnDisownOpener() {
+ // TODO(creis): We should only see this for main frames for now. To support
+ // disowning the opener on subframes, we will need to move WebContentsImpl's
+ // opener_ to FrameTreeNode.
+ CHECK(!frame_->parent());
+
+ if (frame_->opener())
+ frame_->setOpener(NULL);
+}
+
+#if defined(OS_ANDROID)
+void RenderFrameImpl::OnSelectPopupMenuItems(
+ bool canceled,
+ const std::vector<int>& selected_indices) {
+ // It is possible to receive more than one of these calls if the user presses
+ // a select faster than it takes for the show-select-popup IPC message to make
+ // it to the browser UI thread. Ignore the extra-messages.
+ // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
+ if (!external_popup_menu_)
+ return;
+
+ external_popup_menu_->DidSelectItems(canceled, selected_indices);
+ external_popup_menu_.reset();
+}
+#endif
+
+#if defined(OS_MACOSX)
+void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
+ if (external_popup_menu_ == NULL)
+ return;
+ external_popup_menu_->DidSelectItem(selected_index);
+ external_popup_menu_.reset();
+}
+#endif
+
void RenderFrameImpl::OnReload(bool ignore_cache) {
frame_->reload(ignore_cache);
}
@@ -1189,24 +1483,14 @@ void RenderFrameImpl::OnAddStyleSheetByURL(const std::string& url) {
frame_->addStyleSheetByURL(WebString::fromUTF8(url));
}
-bool RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
- const base::string16& selection_text,
- size_t selection_text_offset,
- const gfx::Range& selection_range,
- const ContextMenuParams& params) {
- base::string16 trimmed_selection_text;
- if (!selection_text.empty() && !selection_range.is_empty()) {
- const int start = selection_range.GetMin() - selection_text_offset;
- const size_t length = selection_range.length();
- if (start >= 0 && start + length <= selection_text.length()) {
- base::TrimWhitespace(selection_text.substr(start, length), base::TRIM_ALL,
- &trimmed_selection_text);
- }
- }
- base::string16 trimmed_params_text;
- base::TrimWhitespace(params.selection_text, base::TRIM_ALL,
- &trimmed_params_text);
- return trimmed_params_text != trimmed_selection_text;
+void RenderFrameImpl::OnSetupTransitionView(const std::string& markup) {
+ frame_->document().setIsTransitionDocument();
+ frame_->navigateToSandboxedMarkup(WebData(markup.data(), markup.length()));
+}
+
+void RenderFrameImpl::OnBeginExitTransition(const std::string& css_selector) {
+ frame_->document().setIsTransitionDocument();
+ frame_->document().beginExitTransition(WebString::fromUTF8(css_selector));
}
bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
@@ -1258,7 +1542,7 @@ int RenderFrameImpl::GetRoutingID() {
return routing_id_;
}
-blink::WebFrame* RenderFrameImpl::GetWebFrame() {
+blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() {
DCHECK(frame_);
return frame_;
}
@@ -1322,8 +1606,61 @@ void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
OnJavaScriptExecuteRequest(javascript, 0, false);
}
+ServiceRegistry* RenderFrameImpl::GetServiceRegistry() {
+ return &service_registry_;
+}
+
+bool RenderFrameImpl::IsFTPDirectoryListing() {
+ WebURLResponseExtraDataImpl* extra_data =
+ GetExtraDataFromResponse(frame_->dataSource()->response());
+ return extra_data ? extra_data->is_ftp_directory_listing() : false;
+}
+
+void RenderFrameImpl::AttachGuest(int element_instance_id) {
+ render_view_->GetBrowserPluginManager()->Attach(element_instance_id);
+}
+
+void RenderFrameImpl::SetSelectedText(const base::string16& selection_text,
+ size_t offset,
+ const gfx::Range& range) {
+ // Use the routing id of Render Widget Host.
+ Send(new ViewHostMsg_SelectionChanged(GetRenderWidget()->routing_id(),
+ selection_text,
+ offset,
+ range));
+}
+
+void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context) {
+ gin::ModuleRegistry* registry = gin::ModuleRegistry::From(context);
+ if (registry->available_modules().count(mojo::js::Core::kModuleName))
+ return;
+
+ v8::HandleScope handle_scope(isolate);
+ registry->AddBuiltinModule(
+ isolate, mojo::js::Core::kModuleName, mojo::js::Core::GetModule(isolate));
+ registry->AddBuiltinModule(isolate,
+ mojo::js::Support::kModuleName,
+ mojo::js::Support::GetModule(isolate));
+ registry->AddBuiltinModule(
+ isolate,
+ ServiceRegistryJsWrapper::kModuleName,
+ ServiceRegistryJsWrapper::Create(isolate, &service_registry_).ToV8());
+}
+
// blink::WebFrameClient implementation ----------------------------------------
+blink::WebPluginPlaceholder* RenderFrameImpl::createPluginPlaceholder(
+ blink::WebLocalFrame* frame,
+ const blink::WebPluginParams& params) {
+ DCHECK_EQ(frame_, frame);
+ return GetContentClient()
+ ->renderer()
+ ->CreatePluginPlaceholder(this, frame, params)
+ .release();
+}
+
blink::WebPlugin* RenderFrameImpl::createPlugin(
blink::WebLocalFrame* frame,
const blink::WebPluginParams& params) {
@@ -1334,9 +1671,12 @@ blink::WebPlugin* RenderFrameImpl::createPlugin(
return plugin;
}
- if (base::UTF16ToASCII(params.mimeType) == kBrowserPluginMimeType) {
+ if (base::UTF16ToUTF8(params.mimeType) == kBrowserPluginMimeType) {
+ scoped_ptr<BrowserPluginDelegate> browser_plugin_delegate(
+ GetContentClient()->renderer()->CreateBrowserPluginDelegate(this,
+ kBrowserPluginMimeType, GURL(params.url)));
return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
- render_view_.get(), frame, false);
+ render_view_.get(), frame, browser_plugin_delegate.Pass());
}
#if defined(ENABLE_PLUGINS)
@@ -1349,9 +1689,12 @@ blink::WebPlugin* RenderFrameImpl::createPlugin(
if (!found)
return NULL;
- if (info.type == content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
+ if (info.type == WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) {
+ scoped_ptr<BrowserPluginDelegate> browser_plugin_delegate(
+ GetContentClient()->renderer()->CreateBrowserPluginDelegate(
+ this, mime_type, GURL(params.url)));
return render_view_->GetBrowserPluginManager()->CreateBrowserPlugin(
- render_view_.get(), frame, true);
+ render_view_.get(), frame, browser_plugin_delegate.Pass());
}
@@ -1367,22 +1710,45 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
blink::WebLocalFrame* frame,
const blink::WebURL& url,
blink::WebMediaPlayerClient* client) {
+ return createMediaPlayer(frame, url, client, NULL);
+}
+
+blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
+ blink::WebLocalFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client,
+ blink::WebContentDecryptionModule* initial_cdm) {
+#if defined(VIDEO_HOLE)
+ if (!contains_media_player_) {
+ render_view_->RegisterVideoHoleFrame(this);
+ contains_media_player_ = true;
+ }
+#endif // defined(VIDEO_HOLE)
+
blink::WebMediaStream web_stream(
blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
if (!web_stream.isNull())
return CreateWebMediaPlayerForMediaStream(url, client);
#if defined(OS_ANDROID)
- return CreateAndroidWebMediaPlayer(url, client);
+ return CreateAndroidWebMediaPlayer(url, client, initial_cdm);
#else
- WebMediaPlayerParams params(
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ media::WebMediaPlayerParams params(
base::Bind(&ContentRendererClient::DeferMediaLoad,
base::Unretained(GetContentClient()->renderer()),
static_cast<RenderFrame*>(this)),
- RenderThreadImpl::current()->GetAudioRendererMixerManager()->CreateInput(
- render_view_->routing_id_, routing_id_));
- return new WebMediaPlayerImpl(frame, client, weak_factory_.GetWeakPtr(),
- params);
+ render_thread->GetAudioRendererMixerManager()->CreateInput(
+ render_view_->routing_id_, routing_id_),
+ *render_thread->GetAudioHardwareConfig(),
+ new RenderMediaLog(),
+ render_thread->GetGpuFactories(),
+ render_thread->GetMediaThreadTaskRunner(),
+ render_thread->compositor_message_loop_proxy(),
+ base::Bind(&EncryptedMediaPlayerSupportImpl::Create),
+ initial_cdm);
+ return new media::WebMediaPlayerImpl(
+ frame, client, weak_factory_.GetWeakPtr(), nullptr, params);
#endif // defined(OS_ANDROID)
}
@@ -1392,14 +1758,18 @@ RenderFrameImpl::createContentDecryptionModule(
const blink::WebSecurityOrigin& security_origin,
const blink::WebString& key_system) {
DCHECK(!frame_ || frame_ == frame);
- return WebContentDecryptionModuleImpl::Create(
+
#if defined(ENABLE_PEPPER_CDMS)
- frame,
+ RenderCdmFactory cdm_factory(
+ base::Bind(&PepperCdmWrapperImpl::Create, frame));
#elif defined(ENABLE_BROWSER_CDMS)
- GetCdmManager(),
+ RenderCdmFactory cdm_factory(GetCdmManager());
+#else
+ RenderCdmFactory cdm_factory;
#endif
- security_origin,
- key_system);
+
+ return WebContentDecryptionModuleImpl::Create(&cdm_factory, security_origin,
+ key_system);
}
blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
@@ -1423,6 +1793,31 @@ RenderFrameImpl::createWorkerPermissionClientProxy(
this, frame);
}
+WebExternalPopupMenu* RenderFrameImpl::createExternalPopupMenu(
+ const WebPopupMenuInfo& popup_menu_info,
+ WebExternalPopupMenuClient* popup_menu_client) {
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ // An IPC message is sent to the browser to build and display the actual
+ // popup. The user could have time to click a different select by the time
+ // the popup is shown. In that case external_popup_menu_ is non NULL.
+ // By returning NULL in that case, we instruct Blink to cancel that new
+ // popup. So from the user perspective, only the first one will show, and
+ // will have to close the first one before another one can be shown.
+ if (external_popup_menu_)
+ return NULL;
+ external_popup_menu_.reset(
+ new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
+ if (render_view_->screen_metrics_emulator_) {
+ render_view_->SetExternalPopupOriginAdjustmentsForEmulation(
+ external_popup_menu_.get(),
+ render_view_->screen_metrics_emulator_.get());
+ }
+ return external_popup_menu_.get();
+#else
+ return NULL;
+#endif
+}
+
blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebLocalFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
return &cookie_jar_;
@@ -1553,6 +1948,7 @@ void RenderFrameImpl::frameFocused() {
void RenderFrameImpl::willClose(blink::WebFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FrameWillClose());
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
FrameWillClose(frame));
}
@@ -1635,26 +2031,16 @@ void RenderFrameImpl::loadURLExternally(
if (policy == blink::WebNavigationPolicyDownload) {
render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
request.url(), referrer,
- suggested_name, false));
- } else if (policy == blink::WebNavigationPolicyDownloadTo) {
- render_view_->Send(new ViewHostMsg_DownloadUrl(render_view_->GetRoutingID(),
- request.url(), referrer,
- suggested_name, true));
+ suggested_name));
} else {
OpenURL(frame, request.url(), referrer, policy);
}
}
blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
- blink::WebLocalFrame* frame,
- blink::WebDataSource::ExtraData* extra_data,
- const blink::WebURLRequest& request,
- blink::WebNavigationType type,
- blink::WebNavigationPolicy default_policy,
- bool is_redirect) {
- DCHECK(!frame_ || frame_ == frame);
- return DecidePolicyForNavigation(
- this, frame, extra_data, request, type, default_policy, is_redirect);
+ const NavigationPolicyInfo& info) {
+ DCHECK(!frame_ || frame_ == info.frame);
+ return DecidePolicyForNavigation(this, info);
}
blink::WebHistoryItem RenderFrameImpl::historyItemForNewChildFrame(
@@ -1680,9 +2066,9 @@ void RenderFrameImpl::willSubmitForm(blink::WebLocalFrame* frame,
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentState(document_state);
- if (PageTransitionCoreTypeIs(navigation_state->transition_type(),
- PAGE_TRANSITION_LINK)) {
- navigation_state->set_transition_type(PAGE_TRANSITION_FORM_SUBMIT);
+ if (ui::PageTransitionCoreTypeIs(navigation_state->transition_type(),
+ ui::PAGE_TRANSITION_LINK)) {
+ navigation_state->set_transition_type(ui::PAGE_TRANSITION_FORM_SUBMIT);
}
// Save these to be processed when the ensuing navigation is committed.
@@ -1715,7 +2101,8 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame,
network_provider.Pass());
}
-void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame) {
+void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame,
+ bool is_transition_navigation) {
DCHECK(!frame_ || frame_ == frame);
WebDataSource* ds = frame->provisionalDataSource();
@@ -1724,6 +2111,8 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame) {
if (!ds)
return;
+ TRACE_EVENT2("navigation", "RenderFrameImpl::didStartProvisionalLoad",
+ "id", routing_id_, "url", ds->request().url().string().utf8());
DocumentState* document_state = DocumentState::FromDataSource(ds);
// We should only navigate to swappedout:// when is_swapped_out_ is true.
@@ -1752,45 +2141,27 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame) {
// marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we
// handle loading of error pages.
document_state->navigation_state()->set_transition_type(
- PAGE_TRANSITION_AUTO_SUBFRAME);
+ ui::PAGE_TRANSITION_AUTO_SUBFRAME);
}
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
DidStartProvisionalLoad(frame));
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidStartProvisionalLoad());
- int parent_routing_id = frame->parent() ?
- FromWebFrame(frame->parent())->GetRoutingID() : -1;
Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
- routing_id_, parent_routing_id, ds->request().url()));
+ routing_id_, ds->request().url(), is_transition_navigation));
}
void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
blink::WebLocalFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
render_view_->history_controller()->RemoveChildrenForRedirect(this);
- if (frame->parent())
- return;
- // Received a redirect on the main frame.
- WebDataSource* data_source = frame->provisionalDataSource();
- if (!data_source) {
- // Should only be invoked when we have a data source.
- NOTREACHED();
- return;
- }
- std::vector<GURL> redirects;
- GetRedirectChain(data_source, &redirects);
- if (redirects.size() >= 2) {
- Send(new FrameHostMsg_DidRedirectProvisionalLoad(
- routing_id_,
- render_view_->page_id_,
- redirects[redirects.size() - 2],
- redirects.back()));
- }
}
void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame* frame,
const blink::WebURLError& error) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didFailProvisionalLoad",
+ "id", routing_id_);
DCHECK(!frame_ || frame_ == frame);
WebDataSource* ds = frame->provisionalDataSource();
DCHECK(ds);
@@ -1813,7 +2184,6 @@ void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame* frame,
EqualsASCII(failed_request.httpMethod(), "POST"));
FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
- params.frame_unique_name = frame->uniqueName();
params.error_code = error.reason;
GetContentClient()->renderer()->GetNavigationErrorStrings(
render_view_.get(),
@@ -1867,8 +2237,8 @@ void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame* frame,
// state into account, if a location.replace() failed.
bool replace =
navigation_state->pending_page_id() != -1 ||
- PageTransitionCoreTypeIs(navigation_state->transition_type(),
- PAGE_TRANSITION_AUTO_SUBFRAME);
+ ui::PageTransitionCoreTypeIs(navigation_state->transition_type(),
+ ui::PAGE_TRANSITION_AUTO_SUBFRAME);
// If we failed on a browser initiated request, then make sure that our error
// page load is regarded as the same browser initiated request.
@@ -1881,7 +2251,7 @@ void RenderFrameImpl::didFailProvisionalLoad(blink::WebLocalFrame* frame,
navigation_state->pending_history_list_offset();
render_view_->pending_navigation_params_->should_clear_history_list =
navigation_state->history_list_was_cleared();
- render_view_->pending_navigation_params_->transition =
+ render_view_->pending_navigation_params_->common_params.transition =
navigation_state->transition_type();
render_view_->pending_navigation_params_->request_time =
document_state->request_time();
@@ -1897,11 +2267,22 @@ void RenderFrameImpl::didCommitProvisionalLoad(
blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type) {
+ TRACE_EVENT2("navigation", "RenderFrameImpl::didCommitProvisionalLoad",
+ "id", routing_id_,
+ "url", GetLoadingUrl().possibly_invalid_spec());
DCHECK(!frame_ || frame_ == frame);
DocumentState* document_state =
DocumentState::FromDataSource(frame->dataSource());
NavigationState* navigation_state = document_state->navigation_state();
+ if (proxy_routing_id_ != MSG_ROUTING_NONE) {
+ RenderFrameProxy* proxy =
+ RenderFrameProxy::FromRoutingID(proxy_routing_id_);
+ CHECK(proxy);
+ proxy->web_frame()->swap(frame_);
+ proxy_routing_id_ = MSG_ROUTING_NONE;
+ }
+
// When we perform a new navigation, we need to update the last committed
// session history entry with state for the page we are leaving. Do this
// before updating the HistoryController state.
@@ -1976,6 +2357,10 @@ void RenderFrameImpl::didCommitProvisionalLoad(
}
}
+ bool sent = Send(
+ new FrameHostMsg_DidAssignPageId(routing_id_, render_view_->page_id_));
+ CHECK(sent); // http://crbug.com/407376
+
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_,
DidCommitProvisionalLoad(frame, is_new_navigation));
FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
@@ -1997,7 +2382,7 @@ void RenderFrameImpl::didCommitProvisionalLoad(
// new navigation.
navigation_state->set_request_committed(true);
- UpdateURL(frame);
+ SendDidCommitProvisionalLoad(frame);
// Check whether we have new encoding name.
UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
@@ -2053,7 +2438,6 @@ void RenderFrameImpl::didReceiveTitle(blink::WebLocalFrame* frame,
base::string16 shortened_title = title16.substr(0, kMaxTitleChars);
Send(new FrameHostMsg_UpdateTitle(routing_id_,
- render_view_->page_id_,
shortened_title, direction));
}
@@ -2069,6 +2453,8 @@ void RenderFrameImpl::didChangeIcon(blink::WebLocalFrame* frame,
}
void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame* frame) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didFinishDocumentLoad",
+ "id", routing_id_);
DCHECK(!frame_ || frame_ == frame);
WebDataSource* ds = frame->dataSource();
DocumentState* document_state = DocumentState::FromDataSource(ds);
@@ -2092,6 +2478,8 @@ void RenderFrameImpl::didHandleOnloadEvents(blink::WebLocalFrame* frame) {
void RenderFrameImpl::didFailLoad(blink::WebLocalFrame* frame,
const blink::WebURLError& error) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didFailLoad",
+ "id", routing_id_);
DCHECK(!frame_ || frame_ == frame);
// TODO(nasko): Move implementation here. No state needed.
WebDataSource* ds = frame->dataSource();
@@ -2116,6 +2504,8 @@ void RenderFrameImpl::didFailLoad(blink::WebLocalFrame* frame,
}
void RenderFrameImpl::didFinishLoad(blink::WebLocalFrame* frame) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didFinishLoad",
+ "id", routing_id_);
DCHECK(!frame_ || frame_ == frame);
WebDataSource* ds = frame->dataSource();
DocumentState* document_state = DocumentState::FromDataSource(ds);
@@ -2142,6 +2532,8 @@ void RenderFrameImpl::didFinishLoad(blink::WebLocalFrame* frame) {
void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didNavigateWithinPage",
+ "id", routing_id_);
DCHECK(!frame_ || frame_ == frame);
// If this was a reference fragment navigation that we initiated, then we
// could end up having a non-null pending navigation params. We just need to
@@ -2167,6 +2559,42 @@ void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame) {
render_view_->didUpdateCurrentHistoryItem(frame);
}
+// TODO(zhenw): This will be removed once the blink side implementation is done.
+void RenderFrameImpl::addNavigationTransitionData(
+ const blink::WebString& allowed_destination_host_pattern,
+ const blink::WebString& selector,
+ const blink::WebString& markup) {
+ FrameHostMsg_AddNavigationTransitionData_Params params;
+ params.render_frame_id = routing_id_;
+ params.allowed_destination_host_pattern =
+ allowed_destination_host_pattern.utf8();
+ params.selector = selector.utf8();
+ params.markup = markup.utf8();
+
+ Send(new FrameHostMsg_AddNavigationTransitionData(params));
+}
+
+void RenderFrameImpl::addNavigationTransitionData(
+ const blink::WebString& allowed_destination_host_pattern,
+ const blink::WebString& selector,
+ const blink::WebString& markup,
+ const blink::WebVector<blink::WebString>& web_names,
+ const blink::WebVector<blink::WebRect>& web_rects) {
+ FrameHostMsg_AddNavigationTransitionData_Params params;
+ params.render_frame_id = routing_id_;
+ params.allowed_destination_host_pattern =
+ allowed_destination_host_pattern.utf8();
+ params.selector = selector.utf8();
+ params.markup = markup.utf8();
+ params.elements.resize(web_names.size());
+ for (size_t i = 0; i < web_names.size(); i++) {
+ params.elements[i].name = web_names[i].utf8();
+ params.elements[i].rect = gfx::Rect(web_rects[i]);
+ }
+
+ Send(new FrameHostMsg_AddNavigationTransitionData(params));
+}
+
void RenderFrameImpl::didChangeThemeColor() {
if (frame_->parent())
return;
@@ -2175,6 +2603,17 @@ void RenderFrameImpl::didChangeThemeColor() {
routing_id_, frame_->document().themeColor()));
}
+void RenderFrameImpl::requestNotificationPermission(
+ const blink::WebSecurityOrigin& origin,
+ blink::WebNotificationPermissionCallback* callback) {
+ if (!notification_permission_dispatcher_) {
+ notification_permission_dispatcher_ =
+ new NotificationPermissionDispatcher(this);
+ }
+
+ notification_permission_dispatcher_->RequestPermission(origin, callback);
+}
+
blink::WebNotificationPresenter* RenderFrameImpl::notificationPresenter() {
return notification_provider_;
}
@@ -2186,14 +2625,17 @@ void RenderFrameImpl::didChangeSelection(bool is_empty_selection) {
if (is_empty_selection)
selection_text_.clear();
- // UpdateTextInputState should be called before SyncSelectionIfRequired.
- // UpdateTextInputState may send TextInputStateChanged to notify the focus
+ // UpdateTextInputType should be called before SyncSelectionIfRequired.
+ // UpdateTextInputType may send TextInputTypeChanged to notify the focus
// was changed, and SyncSelectionIfRequired may send SelectionChanged
// to notify the selection was changed. Focus change should be notified
// before selection change.
- GetRenderWidget()->UpdateTextInputState(
- RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
+ GetRenderWidget()->UpdateTextInputType();
SyncSelectionIfRequired();
+#if defined(OS_ANDROID)
+ GetRenderWidget()->UpdateTextInputState(RenderWidget::NO_SHOW_IME,
+ RenderWidget::FROM_NON_IME);
+#endif
}
blink::WebColorChooser* RenderFrameImpl::createColorChooser(
@@ -2202,9 +2644,9 @@ blink::WebColorChooser* RenderFrameImpl::createColorChooser(
const blink::WebVector<blink::WebColorSuggestion>& suggestions) {
RendererWebColorChooserImpl* color_chooser =
new RendererWebColorChooserImpl(this, client);
- std::vector<content::ColorSuggestion> color_suggestions;
+ std::vector<ColorSuggestion> color_suggestions;
for (size_t i = 0; i < suggestions.size(); i++) {
- color_suggestions.push_back(content::ColorSuggestion(suggestions[i]));
+ color_suggestions.push_back(ColorSuggestion(suggestions[i]));
}
color_chooser->Open(static_cast<SkColor>(initial_color), color_suggestions);
return color_chooser;
@@ -2269,27 +2711,10 @@ bool RenderFrameImpl::runModalBeforeUnloadDialog(
void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
ContextMenuParams params = ContextMenuParamsBuilder::Build(data);
params.source_type = GetRenderWidget()->context_menu_source_type();
- if (params.source_type == ui::MENU_SOURCE_TOUCH_EDIT_MENU) {
- params.x = GetRenderWidget()->touch_editing_context_menu_location().x();
- params.y = GetRenderWidget()->touch_editing_context_menu_location().y();
- }
GetRenderWidget()->OnShowHostContextMenu(&params);
-
- // Plugins, e.g. PDF, don't currently update the render view when their
- // selected text changes, but the context menu params do contain the updated
- // selection. If that's the case, update the render view's state just prior
- // to showing the context menu.
- // TODO(asvitkine): http://crbug.com/152432
- if (ShouldUpdateSelectionTextFromContextMenuParams(
- selection_text_, selection_text_offset_, selection_range_, params)) {
- selection_text_ = params.selection_text;
- // TODO(asvitkine): Text offset and range is not available in this case.
- selection_text_offset_ = 0;
- selection_range_ = gfx::Range(0, selection_text_.length());
- // This IPC is dispatched by RenderWidetHost, so use its routing ID.
- Send(new ViewHostMsg_SelectionChanged(
- GetRenderWidget()->routing_id(), selection_text_,
- selection_text_offset_, selection_range_));
+ if (GetRenderWidget()->has_host_context_menu_location()) {
+ params.x = GetRenderWidget()->host_context_menu_location().x();
+ params.y = GetRenderWidget()->host_context_menu_location().y();
}
// Serializing a GURL longer than kMaxURLChars will fail, so don't do
@@ -2316,24 +2741,6 @@ void RenderFrameImpl::clearContextMenu() {
context_menu_node_.reset();
}
-void RenderFrameImpl::willRequestAfterPreconnect(
- blink::WebLocalFrame* frame,
- blink::WebURLRequest& request) {
- DCHECK(!frame_ || frame_ == frame);
- // FIXME(kohei): This will never be set.
- WebString custom_user_agent;
-
- DCHECK(!request.extraData());
-
- bool was_after_preconnect_request = true;
- // The args after |was_after_preconnect_request| are not used, and set to
- // correct values at |willSendRequest|.
- RequestExtraData* extra_data = new RequestExtraData();
- extra_data->set_custom_user_agent(custom_user_agent);
- extra_data->set_was_after_preconnect_request(was_after_preconnect_request);
- request.setExtraData(extra_data);
-}
-
void RenderFrameImpl::willSendRequest(
blink::WebLocalFrame* frame,
unsigned identifier,
@@ -2347,23 +2754,31 @@ void RenderFrameImpl::willSendRequest(
// Set the first party for cookies url if it has not been set yet (new
// requests). For redirects, it is updated by WebURLLoaderImpl.
if (request.firstPartyForCookies().isEmpty()) {
- if (request.targetType() == blink::WebURLRequest::TargetIsMainFrame) {
+ if (request.frameType() == blink::WebURLRequest::FrameTypeTopLevel) {
request.setFirstPartyForCookies(request.url());
} else {
- request.setFirstPartyForCookies(
- frame->top()->document().firstPartyForCookies());
+ // TODO(nasko): When the top-level frame is remote, there is no document.
+ // This is broken and should be fixed to propagate the first party.
+ WebFrame* top = frame->top();
+ if (top->isWebLocalFrame()) {
+ request.setFirstPartyForCookies(
+ frame->top()->document().firstPartyForCookies());
+ }
}
}
WebFrame* top_frame = frame->top();
- if (!top_frame)
+ // TODO(nasko): Hack around asking about top-frame data source. This means
+ // for out-of-process iframes we are treating the current frame as the
+ // top-level frame, which is wrong.
+ if (!top_frame || top_frame->isWebRemoteFrame())
top_frame = frame;
WebDataSource* provisional_data_source = top_frame->provisionalDataSource();
WebDataSource* top_data_source = top_frame->dataSource();
WebDataSource* data_source =
provisional_data_source ? provisional_data_source : top_data_source;
- PageTransition transition_type = PAGE_TRANSITION_LINK;
+ ui::PageTransition transition_type = ui::PAGE_TRANSITION_LINK;
DocumentState* document_state = DocumentState::FromDataSource(data_source);
DCHECK(document_state);
InternalDocumentStateData* internal_data =
@@ -2387,34 +2802,48 @@ void RenderFrameImpl::willSendRequest(
// The request's extra data may indicate that we should set a custom user
// agent. This needs to be done here, after WebKit is through with setting the
- // user agent on its own.
+ // user agent on its own. Similarly, it may indicate that we should set an
+ // X-Requested-With header. This must be done here to avoid breaking CORS
+ // checks.
+ // PlzNavigate: there may also be a stream url associated with the request.
WebString custom_user_agent;
- bool was_after_preconnect_request = false;
+ WebString requested_with;
+ scoped_ptr<StreamOverrideParameters> stream_override;
if (request.extraData()) {
RequestExtraData* old_extra_data =
- static_cast<RequestExtraData*>(
- request.extraData());
- custom_user_agent = old_extra_data->custom_user_agent();
- was_after_preconnect_request =
- old_extra_data->was_after_preconnect_request();
+ static_cast<RequestExtraData*>(request.extraData());
+ custom_user_agent = old_extra_data->custom_user_agent();
if (!custom_user_agent.isNull()) {
if (custom_user_agent.isEmpty())
request.clearHTTPHeaderField("User-Agent");
else
request.setHTTPHeaderField("User-Agent", custom_user_agent);
}
+
+ requested_with = old_extra_data->requested_with();
+ if (!requested_with.isNull()) {
+ if (requested_with.isEmpty())
+ request.clearHTTPHeaderField("X-Requested-With");
+ else
+ request.setHTTPHeaderField("X-Requested-With", requested_with);
+ }
+ stream_override = old_extra_data->TakeStreamOverrideOwnership();
}
// Add the default accept header for frame request if it has not been set
// already.
- if ((request.targetType() == blink::WebURLRequest::TargetIsMainFrame ||
- request.targetType() == blink::WebURLRequest::TargetIsSubframe) &&
+ if ((request.frameType() == blink::WebURLRequest::FrameTypeTopLevel ||
+ request.frameType() == blink::WebURLRequest::FrameTypeNested) &&
request.httpHeaderField(WebString::fromUTF8(kAcceptHeader)).isEmpty()) {
request.setHTTPHeaderField(WebString::fromUTF8(kAcceptHeader),
WebString::fromUTF8(kDefaultAcceptHeader));
}
+ // Add an empty HTTP origin header for non GET methods if none is currently
+ // present.
+ request.addHTTPOriginIfNeeded(WebString());
+
// Attach |should_replace_current_entry| state to requests so that, should
// this navigation later require a request transfer, all state is preserved
// when it is re-created in the new process.
@@ -2432,8 +2861,8 @@ void RenderFrameImpl::willSendRequest(
}
int provider_id = kInvalidServiceWorkerProviderId;
- if (request.targetType() == blink::WebURLRequest::TargetIsMainFrame ||
- request.targetType() == blink::WebURLRequest::TargetIsSubframe) {
+ if (request.frameType() == blink::WebURLRequest::FrameTypeTopLevel ||
+ request.frameType() == blink::WebURLRequest::FrameTypeNested) {
// |provisionalDataSource| may be null in some content::ResourceFetcher
// use cases, we don't hook those requests.
if (frame->provisionalDataSource()) {
@@ -2449,12 +2878,20 @@ void RenderFrameImpl::willSendRequest(
provider_id = provider->provider_id();
}
- int parent_routing_id = frame->parent() ?
- FromWebFrame(frame->parent())->GetRoutingID() : -1;
+ WebFrame* parent = frame->parent();
+ int parent_routing_id = MSG_ROUTING_NONE;
+ if (!parent) {
+ parent_routing_id = -1;
+ } else if (parent->isWebLocalFrame()) {
+ parent_routing_id = FromWebFrame(parent)->GetRoutingID();
+ } else {
+ parent_routing_id = RenderFrameProxy::FromWebFrame(parent)->routing_id();
+ }
+
RequestExtraData* extra_data = new RequestExtraData();
extra_data->set_visibility_state(render_view_->visibilityState());
extra_data->set_custom_user_agent(custom_user_agent);
- extra_data->set_was_after_preconnect_request(was_after_preconnect_request);
+ extra_data->set_requested_with(requested_with);
extra_data->set_render_frame_id(routing_id_);
extra_data->set_is_main_frame(frame == top_frame);
extra_data->set_frame_origin(
@@ -2469,6 +2906,7 @@ void RenderFrameImpl::willSendRequest(
extra_data->set_transferred_request_request_id(
navigation_state->transferred_request_request_id());
extra_data->set_service_worker_provider_id(provider_id);
+ extra_data->set_stream_override(stream_override.Pass());
request.setExtraData(extra_data);
DocumentState* top_document_state =
@@ -2476,11 +2914,8 @@ void RenderFrameImpl::willSendRequest(
if (top_document_state) {
// TODO(gavinp): separate out prefetching and prerender field trials
// if the rel=prerender rel type is sticking around.
- if (request.targetType() == WebURLRequest::TargetIsPrefetch)
+ if (request.requestContext() == WebURLRequest::RequestContextPrefetch)
top_document_state->set_was_prefetcher(true);
-
- if (was_after_preconnect_request)
- top_document_state->set_was_after_preconnect_request(true);
}
// This is an instance where we embed a copy of the routing id
@@ -2534,8 +2969,7 @@ void RenderFrameImpl::didReceiveResponse(
int http_status_code = response.httpStatusCode();
// Record page load flags.
- WebURLResponseExtraDataImpl* extra_data =
- GetExtraDataFromResponse(response);
+ WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
if (extra_data) {
document_state->set_was_fetched_via_spdy(
extra_data->was_fetched_via_spdy());
@@ -2549,6 +2983,8 @@ void RenderFrameImpl::didReceiveResponse(
extra_data->connection_info());
document_state->set_was_fetched_via_proxy(
extra_data->was_fetched_via_proxy());
+ document_state->set_proxy_server(
+ extra_data->proxy_server());
}
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentState(document_state);
@@ -2594,7 +3030,7 @@ void RenderFrameImpl::didLoadResourceFromMemoryCache(
// prevent large (1M+) data: URLs from crashing in the IPC system, we simply
// filter them out here.
GURL url(request.url());
- if (url.SchemeIs("data"))
+ if (url.SchemeIs(url::kDataScheme))
return;
// Let the browser know we loaded a resource from the memory cache. This
@@ -2605,7 +3041,7 @@ void RenderFrameImpl::didLoadResourceFromMemoryCache(
response.securityInfo(),
request.httpMethod().utf8(),
response.mimeType().utf8(),
- ResourceType::FromTargetType(request.targetType())));
+ WebURLRequestToResourceType(request)));
}
void RenderFrameImpl::didDisplayInsecureContent(blink::WebLocalFrame* frame) {
@@ -2668,6 +3104,10 @@ void RenderFrameImpl::didFirstVisuallyNonEmptyLayout(
GetRenderWidget()->DidChangeBodyBackgroundColor(
render_view_->webwidget_->backgroundColor());
#endif
+
+ GetRenderWidget()->QueueMessage(
+ new FrameHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_),
+ MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
}
void RenderFrameImpl::didChangeScrollOffset(blink::WebLocalFrame* frame) {
@@ -2719,18 +3159,13 @@ void RenderFrameImpl::requestStorageQuota(
return;
}
ChildThread::current()->quota_dispatcher()->RequestStorageQuota(
- render_view_->GetRoutingID(), GURL(origin.toString()),
- static_cast<quota::StorageType>(type), requested_size,
+ render_view_->GetRoutingID(),
+ GURL(origin.toString()),
+ static_cast<storage::StorageType>(type),
+ requested_size,
QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
}
-void RenderFrameImpl::willOpenSocketStream(
- blink::WebSocketStreamHandle* handle) {
- WebSocketStreamHandleImpl* impl =
- static_cast<WebSocketStreamHandleImpl*>(handle);
- impl->SetUserData(handle, new SocketStreamHandleData(routing_id_));
-}
-
void RenderFrameImpl::willOpenWebSocket(blink::WebSocketHandle* handle) {
WebSocketBridge* impl = static_cast<WebSocketBridge*>(handle);
impl->set_render_frame_id(routing_id_);
@@ -2742,6 +3177,18 @@ blink::WebGeolocationClient* RenderFrameImpl::geolocationClient() {
return geolocation_dispatcher_;
}
+void RenderFrameImpl::requestPushPermission(blink::WebCallback* callback) {
+ if (!push_permission_dispatcher_)
+ push_permission_dispatcher_ = new PushPermissionDispatcher(this);
+ push_permission_dispatcher_->RequestPermission(callback);
+}
+
+blink::WebPushClient* RenderFrameImpl::pushClient() {
+ if (!push_messaging_dispatcher_)
+ push_messaging_dispatcher_ = new PushMessagingDispatcher(this);
+ return push_messaging_dispatcher_;
+}
+
void RenderFrameImpl::willStartUsingPeerConnectionHandler(
blink::WebLocalFrame* frame,
blink::WebRTCPeerConnectionHandler* handler) {
@@ -2752,10 +3199,8 @@ void RenderFrameImpl::willStartUsingPeerConnectionHandler(
}
blink::WebUserMediaClient* RenderFrameImpl::userMediaClient() {
- // This can happen in tests, in which case it's OK to return NULL.
- if (!InitializeUserMediaClient())
- return NULL;
-
+ if (!web_user_media_client_)
+ InitializeUserMediaClient();
return web_user_media_client_;
}
@@ -2776,6 +3221,7 @@ bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
return false;
ViewMsg_PostMessage_Params params;
+ params.is_data_raw_string = false;
params.data = event.data().toString();
params.source_origin = event.origin();
if (!target_origin.isNull())
@@ -2813,11 +3259,22 @@ bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
blink::WebString RenderFrameImpl::userAgentOverride(blink::WebLocalFrame* frame,
const blink::WebURL& url) {
DCHECK(!frame_ || frame_ == frame);
+ std::string user_agent_override_for_url =
+ GetContentClient()->renderer()->GetUserAgentOverrideForURL(GURL(url));
+ if (!user_agent_override_for_url.empty())
+ return WebString::fromUTF8(user_agent_override_for_url);
+
if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
render_view_->renderer_preferences_.user_agent_override.empty()) {
return blink::WebString();
}
+ // TODO(nasko): When the top-level frame is remote, there is no WebDataSource
+ // associated with it, so the checks below are not valid. Temporarily
+ // return early and fix properly as part of https://crbug.com/426555.
+ if (render_view_->webview()->mainFrame()->isWebRemoteFrame())
+ return blink::WebString();
+
// If we're in the middle of committing a load, the data source we need
// will still be provisional.
WebFrame* main_frame = render_view_->webview()->mainFrame();
@@ -2866,16 +3323,6 @@ void RenderFrameImpl::didLoseWebGLContext(blink::WebLocalFrame* frame,
arb_robustness_status_code));
}
-void RenderFrameImpl::forwardInputEvent(const blink::WebInputEvent* event) {
- Send(new FrameHostMsg_ForwardInputEvent(routing_id_, event));
-}
-
-void RenderFrameImpl::initializeChildFrame(const blink::WebRect& frame_rect,
- float scale_factor) {
- Send(new FrameHostMsg_InitializeChildFrame(
- routing_id_, frame_rect, scale_factor));
-}
-
blink::WebScreenOrientationClient*
RenderFrameImpl::webScreenOrientationClient() {
if (!screen_orientation_dispatcher_)
@@ -2883,10 +3330,54 @@ blink::WebScreenOrientationClient*
return screen_orientation_dispatcher_;
}
+bool RenderFrameImpl::isControlledByServiceWorker(WebDataSource& data_source) {
+ ServiceWorkerNetworkProvider* provider =
+ ServiceWorkerNetworkProvider::FromDocumentState(
+ DocumentState::FromDataSource(&data_source));
+ return provider->context()->controller_handle_id() !=
+ kInvalidServiceWorkerHandleId;
+}
+
+int64_t RenderFrameImpl::serviceWorkerID(WebDataSource& data_source) {
+ ServiceWorkerNetworkProvider* provider =
+ ServiceWorkerNetworkProvider::FromDocumentState(
+ DocumentState::FromDataSource(&data_source));
+
+ if (provider->context()->controller())
+ return provider->context()->controller()->version_id();
+ return kInvalidServiceWorkerVersionId;
+}
+
+void RenderFrameImpl::postAccessibilityEvent(const blink::WebAXObject& obj,
+ blink::WebAXEvent event) {
+ HandleWebAccessibilityEvent(obj, event);
+}
+
+void RenderFrameImpl::handleAccessibilityFindInPageResult(
+ int identifier,
+ int match_index,
+ const blink::WebAXObject& start_object,
+ int start_offset,
+ const blink::WebAXObject& end_object,
+ int end_offset) {
+ if (renderer_accessibility_) {
+ renderer_accessibility_->HandleAccessibilityFindInPageResult(
+ identifier, match_index, start_object, start_offset,
+ end_object, end_offset);
+ }
+}
+
+void RenderFrameImpl::didChangeManifest(blink::WebLocalFrame* frame)
+{
+ DCHECK(!frame_ || frame_ == frame);
+
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeManifest());
+}
+
void RenderFrameImpl::DidPlay(blink::WebMediaPlayer* player) {
Send(new FrameHostMsg_MediaPlayingNotification(
routing_id_, reinterpret_cast<int64>(player), player->hasVideo(),
- player->hasAudio()));
+ player->hasAudio(), player->isRemote()));
}
void RenderFrameImpl::DidPause(blink::WebMediaPlayer* player) {
@@ -2908,6 +3399,11 @@ void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) {
}
void RenderFrameImpl::OnStop() {
+ DCHECK(frame_);
+ frame_->stopLoading();
+ if (!frame_->parent())
+ FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers_, OnStop());
+
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnStop());
}
@@ -2924,7 +3420,7 @@ bool RenderFrameImpl::IsHidden() {
}
// Tell the embedding application that the URL of the active page has changed.
-void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
+void RenderFrameImpl::SendDidCommitProvisionalLoad(blink::WebFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
WebDataSource* ds = frame->dataSource();
DCHECK(ds);
@@ -2939,10 +3435,18 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.http_status_code = response.httpStatusCode();
+ params.url_is_unreachable = ds->hasUnreachableURL();
params.is_post = false;
params.post_id = -1;
params.page_id = render_view_->page_id_;
- params.frame_unique_name = frame->uniqueName();
+ // We need to track the RenderViewHost routing_id because of downstream
+ // dependencies (crbug.com/392171 DownloadRequestHandle, SaveFileManager,
+ // ResourceDispatcherHostImpl, MediaStreamUIProxy,
+ // SpeechRecognitionDispatcherHost and possibly others). They look up the view
+ // based on the ID stored in the resource requests. Once those dependencies
+ // are unwound or moved to RenderFrameHost (crbug.com/304341) we can move the
+ // client to be based on the routing_id of the RenderFrameHost.
+ params.render_view_routing_id = render_view_->routing_id();
params.socket_address.set_host(response.remoteIPAddress().utf8());
params.socket_address.set_port(response.remotePort());
WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
@@ -2994,6 +3498,8 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
// Reset the zoom levels for plugins.
render_view_->webview()->setZoomLevel(0);
} else {
+ // If the zoom level is not found, then do nothing. In-page navigation
+ // relies on not changing the zoom level in this case.
if (host_zoom != render_view_->host_zoom_levels_.end())
render_view_->webview()->setZoomLevel(host_zoom->second);
}
@@ -3009,7 +3515,7 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
params.contents_mime_type = ds->response().mimeType().utf8();
params.transition = navigation_state->transition_type();
- if (!PageTransitionIsMainFrame(params.transition)) {
+ if (!ui::PageTransitionIsMainFrame(params.transition)) {
// If the main frame does a load, it should not be reported as a subframe
// navigation. This can occur in the following case:
// 1. You're on a site with frames.
@@ -3021,7 +3527,7 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
// We don't want that, because any navigation that changes the toplevel
// frame should be tracked as a toplevel navigation (this allows us to
// update the URL bar, etc).
- params.transition = PAGE_TRANSITION_LINK;
+ params.transition = ui::PAGE_TRANSITION_LINK;
}
// If the page contained a client redirect (meta refresh, document.loc...),
@@ -3029,8 +3535,8 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
if (ds->isClientRedirect()) {
params.referrer =
Referrer(params.redirects[0], ds->request().referrerPolicy());
- params.transition = static_cast<PageTransition>(
- params.transition | PAGE_TRANSITION_CLIENT_REDIRECT);
+ params.transition = ui::PageTransitionFromInt(
+ params.transition | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
} else {
params.referrer = RenderViewImpl::GetReferrerFromRequest(
frame, ds->request());
@@ -3067,12 +3573,13 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
// Subframe navigation: the type depends on whether this navigation
// generated a new session history entry. When they do generate a session
// history entry, it means the user initiated the navigation and we should
- // mark it as such. This test checks if this is the first time UpdateURL
- // has been called since WillNavigateToURL was called to initiate the load.
+ // mark it as such. This test checks if this is the first time
+ // SendDidCommitProvisionalLoad has been called since WillNavigateToURL was
+ // called to initiate the load.
if (render_view_->page_id_ > render_view_->last_page_id_sent_to_browser_)
- params.transition = PAGE_TRANSITION_MANUAL_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
else
- params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
+ params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
DCHECK(!navigation_state->history_list_was_cleared());
params.history_list_was_cleared = false;
@@ -3088,7 +3595,7 @@ void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
// If we end up reusing this WebRequest (for example, due to a #ref click),
// we don't want the transition type to persist. Just clear it.
- navigation_state->set_transition_type(PAGE_TRANSITION_LINK);
+ navigation_state->set_transition_type(ui::PAGE_TRANSITION_LINK);
}
WebElement RenderFrameImpl::GetFocusedElement() {
@@ -3100,11 +3607,15 @@ WebElement RenderFrameImpl::GetFocusedElement() {
}
void RenderFrameImpl::didStartLoading(bool to_different_document) {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didStartLoading",
+ "id", routing_id_);
render_view_->FrameDidStartLoading(frame_);
Send(new FrameHostMsg_DidStartLoading(routing_id_, to_different_document));
}
void RenderFrameImpl::didStopLoading() {
+ TRACE_EVENT1("navigation", "RenderFrameImpl::didStopLoading",
+ "id", routing_id_);
render_view_->FrameDidStopLoading(frame_);
Send(new FrameHostMsg_DidStopLoading(routing_id_));
}
@@ -3113,78 +3624,169 @@ void RenderFrameImpl::didChangeLoadProgress(double load_progress) {
Send(new FrameHostMsg_DidChangeLoadProgress(routing_id_, load_progress));
}
+void RenderFrameImpl::HandleWebAccessibilityEvent(
+ const blink::WebAXObject& obj, blink::WebAXEvent event) {
+ if (renderer_accessibility_)
+ renderer_accessibility_->HandleWebAccessibilityEvent(obj, event);
+}
+
+void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) {
+ if (renderer_accessibility_)
+ renderer_accessibility_->FocusedNodeChanged(node);
+}
+
+// PlzNavigate
+void RenderFrameImpl::OnRequestNavigation(
+ const CommonNavigationParams& common_params,
+ const RequestNavigationParams& request_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+
+ // TODO(clamy): Execute the beforeunload event.
+
+ WebURLRequest request =
+ CreateURLRequestForNavigation(common_params,
+ request_params,
+ scoped_ptr<StreamOverrideParameters>(),
+ frame_->isViewSourceModeEnabled());
+
+ // Note: At this stage, the goal is to apply all the modifications the
+ // renderer wants to make to the request, and then send it to the browser, so
+ // that the actual network request can be started. Ideally, all such
+ // modifications should take place in willSendRequest, and in the
+ // implementation of willSendRequest for the various InspectorAgents
+ // (devtools).
+ //
+ // TODO(clamy): Apply devtools override.
+ // TODO(clamy): Make sure that navigation requests are not modified somewhere
+ // else in blink.
+ willSendRequest(frame_, 0, request, blink::WebURLResponse());
+
+ // TODO(clamy): Same-document navigations should not be sent back to the
+ // browser.
+ Send(new FrameHostMsg_BeginNavigation(routing_id_,
+ MakeBeginNavigationParams(request),
+ MakeCommonNavigationParams(request)));
+}
+
+// PlzNavigate
+void RenderFrameImpl::OnCommitNavigation(
+ const ResourceResponseHead& response,
+ const GURL& stream_url,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params) {
+ CHECK(CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBrowserSideNavigation));
+ bool is_reload = false;
+ WebURLRequest::CachePolicy cache_policy =
+ WebURLRequest::UseProtocolCachePolicy;
+ if (!RenderFrameImpl::PrepareRenderViewForNavigation(
+ common_params.url, common_params.navigation_type,
+ commit_params.page_state, false, -1, -1, &is_reload, &cache_policy)) {
+ return;
+ }
+
+ GetContentClient()->SetActiveURL(common_params.url);
+
+ // Create a WebURLRequest that blink can use to get access to the body of the
+ // response through a stream in the browser. Blink will then commit the
+ // navigation.
+ // TODO(clamy): Have the navigation commit directly, without going through
+ // loading a WebURLRequest.
+ scoped_ptr<StreamOverrideParameters> stream_override(
+ new StreamOverrideParameters());
+ stream_override->stream_url = stream_url;
+ stream_override->response = response;
+ WebURLRequest request =
+ CreateURLRequestForNavigation(common_params,
+ RequestNavigationParams(),
+ stream_override.Pass(),
+ frame_->isViewSourceModeEnabled());
+
+ // Record this before starting the load. A lower bound of this time is needed
+ // to sanitize the navigationStart override set below.
+ base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
+ frame_->loadRequest(request);
+ UpdateFrameNavigationTiming(
+ frame_, commit_params.browser_navigation_start,
+ renderer_navigation_start);
+}
+
WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
RenderFrame* render_frame,
- WebFrame* frame,
- WebDataSource::ExtraData* extraData,
- const WebURLRequest& request,
- WebNavigationType type,
- WebNavigationPolicy default_policy,
- bool is_redirect) {
+ const NavigationPolicyInfo& info) {
#ifdef OS_ANDROID
// The handlenavigation API is deprecated and will be removed once
// crbug.com/325351 is resolved.
- if (request.url() != GURL(kSwappedOutURL) &&
+ if (info.urlRequest.url() != GURL(kSwappedOutURL) &&
GetContentClient()->renderer()->HandleNavigation(
render_frame,
- static_cast<DocumentState*>(extraData),
+ static_cast<DocumentState*>(info.extraData),
render_view_->opener_id_,
- frame,
- request,
- type,
- default_policy,
- is_redirect)) {
+ info.frame,
+ info.urlRequest,
+ info.navigationType,
+ info.defaultPolicy,
+ info.isRedirect)) {
return blink::WebNavigationPolicyIgnore;
}
#endif
- Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
+ Referrer referrer(RenderViewImpl::GetReferrerFromRequest(info.frame,
+ info.urlRequest));
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+
+ bool is_subframe = !!info.frame->parent();
- if (is_swapped_out_ || render_view_->is_swapped_out()) {
- if (request.url() != GURL(kSwappedOutURL)) {
- // Targeted links may try to navigate a swapped out frame. Allow the
- // browser process to navigate the tab instead. Note that it is also
- // possible for non-targeted navigations (from this view) to arrive
- // here just after we are swapped out. It's ok to send them to the
- // browser, as long as they're for the top level frame.
- // TODO(creis): Ensure this supports targeted form submissions when
- // fixing http://crbug.com/101395.
- if (frame->parent() == NULL) {
- OpenURL(frame, request.url(), referrer, default_policy);
- return blink::WebNavigationPolicyIgnore; // Suppress the load here.
+ if (command_line.HasSwitch(switches::kSitePerProcess) && is_subframe) {
+ // There's no reason to ignore navigations on subframes, since the swap out
+ // logic no longer applies.
+ } else {
+ if (is_swapped_out_ || render_view_->is_swapped_out()) {
+ if (info.urlRequest.url() != GURL(kSwappedOutURL)) {
+ // Targeted links may try to navigate a swapped out frame. Allow the
+ // browser process to navigate the tab instead. Note that it is also
+ // possible for non-targeted navigations (from this view) to arrive
+ // here just after we are swapped out. It's ok to send them to the
+ // browser, as long as they're for the top level frame.
+ // TODO(creis): Ensure this supports targeted form submissions when
+ // fixing http://crbug.com/101395.
+ if (info.frame->parent() == NULL) {
+ OpenURL(info.frame, info.urlRequest.url(), referrer,
+ info.defaultPolicy);
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
+ }
+
+ // We should otherwise ignore in-process iframe navigations, if they
+ // arrive just after we are swapped out.
+ return blink::WebNavigationPolicyIgnore;
}
- // We should otherwise ignore in-process iframe navigations, if they
- // arrive just after we are swapped out.
- return blink::WebNavigationPolicyIgnore;
+ // Allow kSwappedOutURL to complete.
+ return info.defaultPolicy;
}
-
- // Allow kSwappedOutURL to complete.
- return default_policy;
}
// Webkit is asking whether to navigate to a new URL.
// This is fine normally, except if we're showing UI from one security
// context and they're trying to navigate to a different context.
- const GURL& url = request.url();
+ const GURL& url = info.urlRequest.url();
// A content initiated navigation may have originated from a link-click,
// script, drag-n-drop operation, etc.
- bool is_content_initiated = static_cast<DocumentState*>(extraData)->
+ bool is_content_initiated = static_cast<DocumentState*>(info.extraData)->
navigation_state()->is_content_initiated();
// Experimental:
- // If --enable-strict-site-isolation or --site-per-process is enabled, send
- // all top-level navigations to the browser to let it swap processes when
- // crossing site boundaries. This is currently expected to break some script
- // calls and navigations, such as form submissions.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ // If --enable-strict-site-isolation is enabled, send all top-level
+ // navigations to the browser to let it swap processes when crossing site
+ // boundaries. This is currently expected to break some script calls and
+ // navigations, such as form submissions.
bool force_swap_due_to_flag =
- command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
- command_line.HasSwitch(switches::kSitePerProcess);
+ command_line.HasSwitch(switches::kEnableStrictSiteIsolation);
if (force_swap_due_to_flag &&
- !frame->parent() && (is_content_initiated || is_redirect)) {
- WebString origin_str = frame->document().securityOrigin().toString();
+ !info.frame->parent() && (is_content_initiated || info.isRedirect)) {
+ WebString origin_str = info.frame->document().securityOrigin().toString();
GURL frame_url(origin_str.utf8().data());
// TODO(cevans): revisit whether this site check is still necessary once
// crbug.com/101395 is fixed.
@@ -3193,33 +3795,35 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
frame_url,
url,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
- OpenURL(frame, url, referrer, default_policy);
+ // Only keep same-site (domain + scheme) and data URLs in the same process.
+ bool is_same_site =
+ (same_domain_or_host && frame_url.scheme() == url.scheme()) ||
+ url.SchemeIs(url::kDataScheme);
+ if (!is_same_site) {
+ OpenURL(info.frame, url, referrer, info.defaultPolicy);
return blink::WebNavigationPolicyIgnore;
}
}
// If the browser is interested, then give it a chance to look at the request.
if (is_content_initiated) {
- bool is_form_post = ((type == blink::WebNavigationTypeFormSubmitted) ||
- (type == blink::WebNavigationTypeFormResubmitted)) &&
- EqualsASCII(request.httpMethod(), "POST");
+ bool is_form_post =
+ ((info.navigationType == blink::WebNavigationTypeFormSubmitted) ||
+ (info.navigationType == blink::WebNavigationTypeFormResubmitted)) &&
+ EqualsASCII(info.urlRequest.httpMethod(), "POST");
bool browser_handles_request =
render_view_->renderer_preferences_
.browser_handles_non_local_top_level_requests
- && IsNonLocalTopLevelNavigation(url, frame, type, is_form_post);
+ && IsNonLocalTopLevelNavigation(url, info.frame, info.navigationType,
+ is_form_post);
if (!browser_handles_request) {
- browser_handles_request = IsTopLevelNavigation(frame) &&
+ browser_handles_request = IsTopLevelNavigation(info.frame) &&
render_view_->renderer_preferences_
.browser_handles_all_top_level_requests;
}
if (browser_handles_request) {
- // Reset these counters as the RenderView could be reused for the next
- // navigation.
- render_view_->page_id_ = -1;
- render_view_->last_page_id_sent_to_browser_ = -1;
- OpenURL(frame, url, referrer, default_policy);
+ OpenURL(info.frame, url, referrer, info.defaultPolicy);
return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
}
@@ -3228,7 +3832,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// subsequent checks. For a popup, the document's URL may become the opener
// window's URL if the opener has called document.write().
// See http://crbug.com/93517.
- GURL old_url(frame->dataSource()->request().url());
+ GURL old_url(info.frame->dataSource()->request().url());
// Detect when we're crossing a permission-based boundary (e.g. into or out of
// an extension or app origin, leaving a WebUI page, etc). We only care about
@@ -3243,7 +3847,7 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
// browser process, and issue a special POST navigation in WebKit (via
// FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
// for examples of how to send the httpBody data.
- if (!frame->parent() && is_content_initiated &&
+ if (!info.frame->parent() && is_content_initiated &&
!url.SchemeIs(url::kAboutScheme)) {
bool send_referrer = false;
@@ -3261,15 +3865,16 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
(cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
url.SchemeIs(kViewSourceScheme) ||
- (frame->isViewSourceModeEnabled() &&
- type != blink::WebNavigationTypeReload);
+ (info.frame->isViewSourceModeEnabled() &&
+ info.navigationType != blink::WebNavigationTypeReload);
if (!should_fork && url.SchemeIs(url::kFileScheme)) {
// Fork non-file to file opens. Check the opener URL if this is the
// initial navigation in a newly opened window.
GURL source_url(old_url);
- if (is_initial_navigation && source_url.is_empty() && frame->opener())
- source_url = frame->opener()->top()->document().url();
+ if (is_initial_navigation && source_url.is_empty() &&
+ info.frame->opener())
+ source_url = info.frame->opener()->top()->document().url();
DCHECK(!source_url.is_empty());
should_fork = !source_url.SchemeIs(url::kFileScheme);
}
@@ -3277,13 +3882,13 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
if (!should_fork) {
// Give the embedder a chance.
should_fork = GetContentClient()->renderer()->ShouldFork(
- frame, url, request.httpMethod().utf8(), is_initial_navigation,
- is_redirect, &send_referrer);
+ info.frame, url, info.urlRequest.httpMethod().utf8(),
+ is_initial_navigation, info.isRedirect, &send_referrer);
}
if (should_fork) {
- OpenURL(
- frame, url, send_referrer ? referrer : Referrer(), default_policy);
+ OpenURL(info.frame, url, send_referrer ? referrer : Referrer(),
+ info.defaultPolicy);
return blink::WebNavigationPolicyIgnore; // Suppress the load here.
}
}
@@ -3310,23 +3915,23 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
render_view_->historyForwardListCount() < 1 &&
// The parent page must have set the child's window.opener to null before
// redirecting to the desired URL.
- frame->opener() == NULL &&
+ info.frame->opener() == NULL &&
// Must be a top-level frame.
- frame->parent() == NULL &&
+ info.frame->parent() == NULL &&
// Must not have issued the request from this page.
is_content_initiated &&
// Must be targeted at the current tab.
- default_policy == blink::WebNavigationPolicyCurrentTab &&
+ info.defaultPolicy == blink::WebNavigationPolicyCurrentTab &&
// Must be a JavaScript navigation, which appears as "other".
- type == blink::WebNavigationTypeOther;
+ info.navigationType == blink::WebNavigationTypeOther;
if (is_fork) {
// Open the URL via the browser, not via WebKit.
- OpenURL(frame, url, Referrer(), default_policy);
+ OpenURL(info.frame, url, Referrer(), info.defaultPolicy);
return blink::WebNavigationPolicyIgnore;
}
- return default_policy;
+ return info.defaultPolicy;
}
void RenderFrameImpl::OpenURL(WebFrame* frame,
@@ -3432,39 +4037,26 @@ void RenderFrameImpl::SyncSelectionIfRequired() {
selection_text_ = text;
selection_text_offset_ = offset;
selection_range_ = range;
- // This IPC is dispatched by RenderWidetHost, so use its routing ID.
- Send(new ViewHostMsg_SelectionChanged(
- GetRenderWidget()->routing_id(), text, offset, range));
+ SetSelectedText(text, offset, range);
}
GetRenderWidget()->UpdateSelectionBounds();
}
-bool RenderFrameImpl::InitializeUserMediaClient() {
- if (web_user_media_client_)
- return true;
-
+void RenderFrameImpl::InitializeUserMediaClient() {
if (!RenderThreadImpl::current()) // Will be NULL during unit tests.
- return false;
+ return;
#if defined(OS_ANDROID)
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebRTC))
- return false;
+ return;
#endif
#if defined(ENABLE_WEBRTC)
- if (!render_view_->media_stream_dispatcher_) {
- render_view_->media_stream_dispatcher_ =
- new MediaStreamDispatcher(render_view_.get());
- }
-
- MediaStreamImpl* media_stream_impl = new MediaStreamImpl(
- render_view_.get(),
- render_view_->media_stream_dispatcher_,
- RenderThreadImpl::current()->GetPeerConnectionDependencyFactory());
- web_user_media_client_ = media_stream_impl;
- return true;
-#else
- return false;
+ DCHECK(!web_user_media_client_);
+ web_user_media_client_ = new UserMediaClientImpl(
+ this,
+ RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(),
+ make_scoped_ptr(new MediaStreamDispatcher(this)).Pass());
#endif
}
@@ -3496,6 +4088,55 @@ RenderFrameImpl::CreateRendererFactory() {
#endif
}
+bool RenderFrameImpl::PrepareRenderViewForNavigation(
+ const GURL& url,
+ FrameMsg_Navigate_Type::Value navigate_type,
+ const PageState& state,
+ bool check_history,
+ int pending_history_list_offset,
+ int32 page_id,
+ bool* is_reload,
+ WebURLRequest::CachePolicy* cache_policy) {
+ MaybeHandleDebugURL(url);
+ if (!render_view_->webview())
+ return false;
+
+ FOR_EACH_OBSERVER(
+ RenderViewObserver, render_view_->observers_, Navigate(url));
+
+ // If this is a stale back/forward (due to a recent navigation the browser
+ // didn't know about), ignore it.
+ if (check_history && render_view_->IsBackForwardToStaleEntry(
+ state, pending_history_list_offset, page_id, *is_reload))
+ return false;
+
+ if (!render_view_->is_swapped_out_ ||
+ GetWebFrame() != render_view_->webview()->mainFrame())
+ return true;
+
+ // This is a swapped out main frame, so swap the renderer back in.
+ // We marked the view as hidden when swapping the view out, so be sure to
+ // reset the visibility state before navigating to the new URL.
+ render_view_->webview()->setVisibilityState(
+ render_view_->visibilityState(), false);
+
+ // If this is an attempt to reload while we are swapped out, we should not
+ // reload swappedout://, but the previous page, which is stored in
+ // params.state. Setting is_reload to false will treat this like a back
+ // navigation to accomplish that.
+ *is_reload = false;
+ *cache_policy = WebURLRequest::ReloadIgnoringCacheData;
+
+ // We refresh timezone when a view is swapped in since timezone
+ // can get out of sync when the system timezone is updated while
+ // the view is swapped out.
+ RenderThreadImpl::NotifyTimezoneChange();
+
+ render_view_->SetSwappedOut(false);
+ is_swapped_out_ = false;
+ return true;
+}
+
GURL RenderFrameImpl::GetLoadingUrl() const {
WebDataSource* ds = frame_->dataSource();
if (ds->hasUnreachableURL())
@@ -3508,8 +4149,9 @@ GURL RenderFrameImpl::GetLoadingUrl() const {
#if defined(OS_ANDROID)
WebMediaPlayer* RenderFrameImpl::CreateAndroidWebMediaPlayer(
- const blink::WebURL& url,
- WebMediaPlayerClient* client) {
+ const blink::WebURL& url,
+ WebMediaPlayerClient* client,
+ blink::WebContentDecryptionModule* initial_cdm) {
GpuChannelHost* gpu_channel_host =
RenderThreadImpl::current()->EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE);
@@ -3541,18 +4183,15 @@ WebMediaPlayer* RenderFrameImpl::CreateAndroidWebMediaPlayer(
weak_factory_.GetWeakPtr(),
GetMediaPlayerManager(),
GetCdmManager(),
+ initial_cdm,
stream_texture_factory,
- RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy(),
+ RenderThreadImpl::current()->GetMediaThreadTaskRunner(),
new RenderMediaLog());
}
RendererMediaPlayerManager* RenderFrameImpl::GetMediaPlayerManager() {
- if (!media_player_manager_) {
+ if (!media_player_manager_)
media_player_manager_ = new RendererMediaPlayerManager(this);
-#if defined(VIDEO_HOLE)
- render_view_->RegisterVideoHoleFrame(this);
-#endif // defined(VIDEO_HOLE)
- }
return media_player_manager_;
}
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index 09d220cf51e..77d49414589 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -14,13 +14,17 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
+#include "content/common/accessibility_mode_enums.h"
+#include "content/common/frame_message_enums.h"
+#include "content/common/mojo/service_registry_impl.h"
#include "content/public/common/javascript_message_type.h"
#include "content/public/common/referrer.h"
#include "content/public/renderer/render_frame.h"
-#include "content/renderer/media/webmediaplayer_delegate.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/renderer_webcookiejar_impl.h"
#include "ipc/ipc_message.h"
+#include "media/blink/webmediaplayer_delegate.h"
+#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebFrameClient.h"
#include "third_party/WebKit/public/web/WebHistoryCommitType.h"
@@ -30,16 +34,19 @@
#include "content/renderer/media/android/renderer_media_player_manager.h"
#endif
+class GURL;
class TransportDIB;
+struct FrameHostMsg_AddNavigationTransitionData_Params;
struct FrameMsg_Navigate_Params;
+struct FrameMsg_RequestNavigation_Params;
namespace blink {
class WebGeolocationClient;
-class WebInputEvent;
class WebMouseEvent;
class WebContentDecryptionModule;
class WebMediaPlayer;
class WebNotificationPresenter;
+class WebPushClient;
class WebSecurityOrigin;
struct WebCompositionUnderline;
struct WebContextMenuData;
@@ -55,11 +62,20 @@ class Rect;
namespace content {
class ChildFrameCompositingHelper;
+class ExternalPopupMenu;
class GeolocationDispatcher;
+class ManifestManager;
+class MediaStreamDispatcher;
class MediaStreamRendererFactory;
class MidiDispatcher;
+class NotificationPermissionDispatcher;
class NotificationProvider;
+class PageState;
class PepperPluginInstanceImpl;
+class PluginPowerSaverHelper;
+class PushMessagingDispatcher;
+class PushPermissionDispatcher;
+class RendererAccessibility;
class RendererCdmManager;
class RendererMediaPlayerManager;
class RendererPpapiHost;
@@ -68,19 +84,39 @@ class RenderViewImpl;
class RenderWidget;
class RenderWidgetFullscreenPepper;
class ScreenOrientationDispatcher;
+class UserMediaClientImpl;
+struct CommitNavigationParams;
+struct CommonNavigationParams;
struct CustomContextMenuContext;
+struct RequestNavigationParams;
+struct ResourceResponseHead;
class CONTENT_EXPORT RenderFrameImpl
: public RenderFrame,
NON_EXPORTED_BASE(public blink::WebFrameClient),
- NON_EXPORTED_BASE(public WebMediaPlayerDelegate) {
+ NON_EXPORTED_BASE(public media::WebMediaPlayerDelegate) {
public:
// Creates a new RenderFrame. |render_view| is the RenderView object that this
// frame belongs to.
// Callers *must* call |SetWebFrame| immediately after creation.
+ // Note: This is called only when RenderFrame is created by Blink through
+ // createChildFrame.
// TODO(creis): We should structure this so that |SetWebFrame| isn't needed.
static RenderFrameImpl* Create(RenderViewImpl* render_view, int32 routing_id);
+ // Creates a new RenderFrame with |routing_id| as a child of the RenderFrame
+ // identified by |parent_routing_id| or as the top-level frame if the latter
+ // is MSG_ROUTING_NONE. If |proxy_routing_id| is MSG_ROUTING_NONE, it creates
+ // the Blink WebLocalFrame and inserts it in the proper place in the frame
+ // tree. Otherwise, the frame is semi-orphaned until it commits, at which
+ // point it replaces the proxy identified by |proxy_routing_id|.
+ // Note: This is called only when RenderFrame is being created in response to
+ // IPC message from the browser process. All other frame creation is driven
+ // through Blink and Create.
+ static void CreateFrame(int routing_id,
+ int parent_routing_id,
+ int proxy_routing_id);
+
// Returns the RenderFrameImpl for the given routing ID.
static RenderFrameImpl* FromRoutingID(int routing_id);
@@ -126,9 +162,6 @@ class CONTENT_EXPORT RenderFrameImpl
// spot.
void Initialize();
- // Notification from RenderView.
- virtual void OnStop();
-
// Notifications from RenderWidget.
void WasHidden();
void WasShown();
@@ -143,6 +176,22 @@ class CONTENT_EXPORT RenderFrameImpl
virtual void didStopLoading();
virtual void didChangeLoadProgress(double load_progress);
+ AccessibilityMode accessibility_mode() {
+ return accessibility_mode_;
+ }
+
+ RendererAccessibility* renderer_accessibility() {
+ return renderer_accessibility_;
+ }
+
+ void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
+ blink::WebAXEvent event);
+
+ // TODO(dmazzoni): the only reason this is here is to plumb it through to
+ // RendererAccessibility. It should be part of RenderFrameObserver, once
+ // blink has a separate accessibility tree per frame.
+ void FocusedNodeChanged(const blink::WebNode& node);
+
#if defined(ENABLE_PLUGINS)
// Notification that a PPAPI plugin has been created.
void PepperPluginCreated(RendererPpapiHost* host);
@@ -188,48 +237,73 @@ class CONTENT_EXPORT RenderFrameImpl
// TODO(jam): remove these once the IPC handler moves from RenderView to
// RenderFrame.
void OnImeSetComposition(
- const base::string16& text,
- const std::vector<blink::WebCompositionUnderline>& underlines,
- int selection_start,
- int selection_end);
- void OnImeConfirmComposition(
- const base::string16& text,
- const gfx::Range& replacement_range,
- bool keep_selection);
-#endif // ENABLE_PLUGINS
+ const base::string16& text,
+ const std::vector<blink::WebCompositionUnderline>& underlines,
+ int selection_start,
+ int selection_end);
+ void OnImeConfirmComposition(const base::string16& text,
+ const gfx::Range& replacement_range,
+ bool keep_selection);
+
+ PluginPowerSaverHelper* plugin_power_saver_helper();
+#endif // defined(ENABLE_PLUGINS)
+
+ // May return NULL in some cases, especially if userMediaClient() returns
+ // NULL.
+ MediaStreamDispatcher* GetMediaStreamDispatcher();
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ void DidHideExternalPopupMenu();
+#endif
// IPC::Sender
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// RenderFrame implementation:
- virtual RenderView* GetRenderView() OVERRIDE;
- virtual int GetRoutingID() OVERRIDE;
- virtual blink::WebFrame* GetWebFrame() OVERRIDE;
- virtual WebPreferences& GetWebkitPreferences() OVERRIDE;
- virtual int ShowContextMenu(ContextMenuClient* client,
- const ContextMenuParams& params) OVERRIDE;
- virtual void CancelContextMenu(int request_id) OVERRIDE;
- virtual blink::WebNode GetContextMenuNode() const OVERRIDE;
- virtual blink::WebPlugin* CreatePlugin(
- blink::WebFrame* frame,
- const WebPluginInfo& info,
- const blink::WebPluginParams& params) OVERRIDE;
- virtual void LoadURLExternally(blink::WebLocalFrame* frame,
- const blink::WebURLRequest& request,
- blink::WebNavigationPolicy policy) OVERRIDE;
- virtual void ExecuteJavaScript(const base::string16& javascript) OVERRIDE;
- virtual bool IsHidden() OVERRIDE;
+ RenderView* GetRenderView() override;
+ int GetRoutingID() override;
+ blink::WebLocalFrame* GetWebFrame() override;
+ WebPreferences& GetWebkitPreferences() override;
+ int ShowContextMenu(ContextMenuClient* client,
+ const ContextMenuParams& params) override;
+ void CancelContextMenu(int request_id) override;
+ blink::WebNode GetContextMenuNode() const override;
+ blink::WebPlugin* CreatePlugin(blink::WebFrame* frame,
+ const WebPluginInfo& info,
+ const blink::WebPluginParams& params) override;
+ void LoadURLExternally(blink::WebLocalFrame* frame,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationPolicy policy) override;
+ void ExecuteJavaScript(const base::string16& javascript) override;
+ bool IsHidden() override;
+ ServiceRegistry* GetServiceRegistry() override;
+ bool IsFTPDirectoryListing() override;
+ void AttachGuest(int element_instance_id) override;
+ void SetSelectedText(const base::string16& selection_text,
+ size_t offset,
+ const gfx::Range& range) override;
+ void EnsureMojoBuiltinsAreAvailable(v8::Isolate* isolate,
+ v8::Handle<v8::Context> context) override;
// blink::WebFrameClient implementation:
+ blink::WebPluginPlaceholder* createPluginPlaceholder(
+ blink::WebLocalFrame*,
+ const blink::WebPluginParams&) override;
virtual blink::WebPlugin* createPlugin(blink::WebLocalFrame* frame,
const blink::WebPluginParams& params);
+ // TODO(jrummell): Remove this method once blink updated.
virtual blink::WebMediaPlayer* createMediaPlayer(
blink::WebLocalFrame* frame,
const blink::WebURL& url,
blink::WebMediaPlayerClient* client);
+ virtual blink::WebMediaPlayer* createMediaPlayer(
+ blink::WebLocalFrame* frame,
+ const blink::WebURL& url,
+ blink::WebMediaPlayerClient* client,
+ blink::WebContentDecryptionModule* initial_cdm);
virtual blink::WebContentDecryptionModule* createContentDecryptionModule(
blink::WebLocalFrame* frame,
const blink::WebSecurityOrigin& security_origin,
@@ -239,6 +313,9 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebApplicationCacheHostClient* client);
virtual blink::WebWorkerPermissionClientProxy*
createWorkerPermissionClientProxy(blink::WebLocalFrame* frame);
+ virtual blink::WebExternalPopupMenu* createExternalPopupMenu(
+ const blink::WebPopupMenuInfo& popup_menu_info,
+ blink::WebExternalPopupMenuClient* popup_menu_client);
virtual blink::WebCookieJar* cookieJar(blink::WebLocalFrame* frame);
virtual blink::WebServiceWorkerProvider* createServiceWorkerProvider(
blink::WebLocalFrame* frame);
@@ -267,12 +344,7 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebString& suggested_name);
// The WebDataSource::ExtraData* is assumed to be a DocumentState* subclass.
virtual blink::WebNavigationPolicy decidePolicyForNavigation(
- blink::WebLocalFrame* frame,
- blink::WebDataSource::ExtraData* extra_data,
- const blink::WebURLRequest& request,
- blink::WebNavigationType type,
- blink::WebNavigationPolicy default_policy,
- bool is_redirect);
+ const NavigationPolicyInfo& info);
virtual blink::WebHistoryItem historyItemForNewChildFrame(
blink::WebFrame* frame);
virtual void willSendSubmitEvent(blink::WebLocalFrame* frame,
@@ -281,7 +353,8 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebFormElement& form);
virtual void didCreateDataSource(blink::WebLocalFrame* frame,
blink::WebDataSource* datasource);
- virtual void didStartProvisionalLoad(blink::WebLocalFrame* frame);
+ virtual void didStartProvisionalLoad(blink::WebLocalFrame* frame,
+ bool is_transition_navigation);
virtual void didReceiveServerRedirectForProvisionalLoad(
blink::WebLocalFrame* frame);
virtual void didFailProvisionalLoad(
@@ -307,7 +380,20 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type);
virtual void didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame);
+ virtual void addNavigationTransitionData(
+ const blink::WebString& allowedDestinationOrigin,
+ const blink::WebString& selector,
+ const blink::WebString& markup);
+ virtual void addNavigationTransitionData(
+ const blink::WebString& allowedDestinationOrigin,
+ const blink::WebString& selector,
+ const blink::WebString& markup,
+ const blink::WebVector<blink::WebString>& web_names,
+ const blink::WebVector<blink::WebRect>& web_rects);
virtual void didChangeThemeColor();
+ virtual void requestNotificationPermission(
+ const blink::WebSecurityOrigin& origin,
+ blink::WebNotificationPermissionCallback* callback);
virtual blink::WebNotificationPresenter* notificationPresenter();
virtual void didChangeSelection(bool is_empty_selection);
virtual blink::WebColorChooser* createColorChooser(
@@ -323,8 +409,6 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebString& message);
virtual void showContextMenu(const blink::WebContextMenuData& data);
virtual void clearContextMenu();
- virtual void willRequestAfterPreconnect(blink::WebLocalFrame* frame,
- blink::WebURLRequest& request);
virtual void willSendRequest(blink::WebLocalFrame* frame,
unsigned identifier,
blink::WebURLRequest& request,
@@ -363,10 +447,10 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebStorageQuotaType type,
unsigned long long requested_size,
blink::WebStorageQuotaCallbacks callbacks);
- virtual void willOpenSocketStream(
- blink::WebSocketStreamHandle* handle);
virtual void willOpenWebSocket(blink::WebSocketHandle* handle);
virtual blink::WebGeolocationClient* geolocationClient();
+ virtual void requestPushPermission(blink::WebCallback* callback);
+ virtual blink::WebPushClient* pushClient();
virtual void willStartUsingPeerConnectionHandler(
blink::WebLocalFrame* frame,
blink::WebRTCPeerConnectionHandler* handler);
@@ -383,35 +467,56 @@ class CONTENT_EXPORT RenderFrameImpl
virtual bool allowWebGL(blink::WebLocalFrame* frame, bool default_value);
virtual void didLoseWebGLContext(blink::WebLocalFrame* frame,
int arb_robustness_status_code);
- virtual void forwardInputEvent(const blink::WebInputEvent* event);
- virtual void initializeChildFrame(const blink::WebRect& frame_rect,
- float scale_factor);
virtual blink::WebScreenOrientationClient* webScreenOrientationClient();
+ virtual bool isControlledByServiceWorker(blink::WebDataSource& data_source);
+ virtual int64_t serviceWorkerID(blink::WebDataSource& data_source);
+ virtual void postAccessibilityEvent(const blink::WebAXObject& obj,
+ blink::WebAXEvent event);
+ virtual void handleAccessibilityFindInPageResult(
+ int identifier,
+ int match_index,
+ const blink::WebAXObject& start_object,
+ int start_offset,
+ const blink::WebAXObject& end_object,
+ int end_offset);
+ virtual void didChangeManifest(blink::WebLocalFrame*);
// WebMediaPlayerDelegate implementation:
- virtual void DidPlay(blink::WebMediaPlayer* player) OVERRIDE;
- virtual void DidPause(blink::WebMediaPlayer* player) OVERRIDE;
- virtual void PlayerGone(blink::WebMediaPlayer* player) OVERRIDE;
+ void DidPlay(blink::WebMediaPlayer* player) override;
+ void DidPause(blink::WebMediaPlayer* player) override;
+ void PlayerGone(blink::WebMediaPlayer* player) override;
// TODO(nasko): Make all tests in RenderViewImplTest friends and then move
// this back to private member.
void OnNavigate(const FrameMsg_Navigate_Params& params);
+ // Binds this render frame's service registry to a handle to the remote
+ // service registry.
+ void BindServiceRegistry(
+ mojo::ScopedMessagePipeHandle service_provider_handle);
+
+ ManifestManager* manifest_manager();
+
protected:
RenderFrameImpl(RenderViewImpl* render_view, int32 routing_id);
private:
friend class RenderFrameObserver;
+ friend class RendererAccessibilityTest;
+ FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuDisplayNoneTest, SelectItem);
+ FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange);
+ FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, NormalCase);
+ FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate);
FRIEND_TEST_ALL_PREFIXES(RendererAccessibilityTest,
AccessibilityMessagesQueueWhileSwappedOut);
- FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest,
- ShouldUpdateSelectionTextFromContextMenuParams);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
OnExtendSelectionAndDelete);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ReloadWhileSwappedOut);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendSwapOutACK);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
SetEditableSelectionAndComposition);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+ OnSetAccessibilityMode);
typedef std::map<GURL, double> HostZoomLevels;
@@ -419,7 +524,8 @@ class CONTENT_EXPORT RenderFrameImpl
void AddObserver(RenderFrameObserver* observer);
void RemoveObserver(RenderFrameObserver* observer);
- void UpdateURL(blink::WebFrame* frame);
+ // Builds and sends DidCommitProvisionalLoad to the host.
+ void SendDidCommitProvisionalLoad(blink::WebFrame* frame);
// Gets the focused element. If no such element exists then the element will
// be NULL.
@@ -431,6 +537,7 @@ class CONTENT_EXPORT RenderFrameImpl
// content/common/*_messages.h for the message that the function is handling.
void OnBeforeUnload();
void OnSwapOut(int proxy_routing_id);
+ void OnStop();
void OnShowContextMenu(const gfx::Point& location);
void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
@@ -443,14 +550,18 @@ class CONTENT_EXPORT RenderFrameImpl
void OnPasteAndMatchStyle();
void OnDelete();
void OnSelectAll();
- void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
+ void OnSelectRange(const gfx::Point& base, const gfx::Point& extent);
void OnUnselect();
+ void OnMoveRangeSelectionExtent(const gfx::Point& point);
void OnReplace(const base::string16& text);
void OnReplaceMisspelling(const base::string16& text);
void OnCSSInsertRequest(const std::string& css);
void OnJavaScriptExecuteRequest(const base::string16& javascript,
int id,
bool notify_result);
+ void OnJavaScriptExecuteRequestForTests(const base::string16& javascript,
+ int id,
+ bool notify_result);
void OnSetEditableSelectionOffsets(int start, int end);
void OnSetCompositionFromExistingText(
int start, int end,
@@ -459,19 +570,30 @@ class CONTENT_EXPORT RenderFrameImpl
void OnReload(bool ignore_cache);
void OnTextSurroundingSelectionRequest(size_t max_length);
void OnAddStyleSheetByURL(const std::string& url);
-#if defined(OS_MACOSX)
+ void OnSetupTransitionView(const std::string& markup);
+ void OnBeginExitTransition(const std::string& css_selector);
+ void OnSetAccessibilityMode(AccessibilityMode new_mode);
+ void OnDisownOpener();
+#if defined(OS_ANDROID)
+ void OnSelectPopupMenuItems(bool canceled,
+ const std::vector<int>& selected_indices);
+#elif defined(OS_MACOSX)
+ void OnSelectPopupMenuItem(int selected_index);
void OnCopyToFindPboard();
#endif
+ // PlzNavigate
+ void OnRequestNavigation(const CommonNavigationParams& common_params,
+ const RequestNavigationParams& request_params);
+ void OnCommitNavigation(const ResourceResponseHead& response,
+ const GURL& stream_url,
+ const CommonNavigationParams& common_params,
+ const CommitNavigationParams& commit_params);
+
// Virtual since overridden by WebTestProxy for layout tests.
virtual blink::WebNavigationPolicy DecidePolicyForNavigation(
RenderFrame* render_frame,
- blink::WebFrame* frame,
- blink::WebDataSource::ExtraData* extraData,
- const blink::WebURLRequest& request,
- blink::WebNavigationType type,
- blink::WebNavigationPolicy default_policy,
- bool is_redirect);
+ const NavigationPolicyInfo& info);
void OpenURL(blink::WebFrame* frame,
const GURL& url,
const Referrer& referrer,
@@ -499,14 +621,6 @@ class CONTENT_EXPORT RenderFrameImpl
// selection handles in sync with the webpage.
void SyncSelectionIfRequired();
- // Returns whether |params.selection_text| should be synchronized to the
- // browser before bringing up the context menu. Static for testing.
- static bool ShouldUpdateSelectionTextFromContextMenuParams(
- const base::string16& selection_text,
- size_t selection_text_offset,
- const gfx::Range& selection_range,
- const ContextMenuParams& params);
-
bool RunJavaScriptMessage(JavaScriptMessageType type,
const base::string16& message,
const base::string16& default_value,
@@ -518,10 +632,15 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebURLError& error,
bool replace);
- // Initializes |web_user_media_client_|, returning true if successful. Returns
- // false if it wasn't possible to create a MediaStreamClient (e.g., WebRTC is
- // disabled) in which case |web_user_media_client_| is NULL.
- bool InitializeUserMediaClient();
+ void HandleJavascriptExecutionResult(const base::string16& javascript,
+ int id,
+ bool notify_result,
+ v8::Handle<v8::Value> result);
+
+ // Initializes |web_user_media_client_|. If this fails, because it wasn't
+ // possible to create a MediaStreamClient (e.g., WebRTC is disabled), then
+ // |web_user_media_client_| will remain NULL.
+ void InitializeUserMediaClient();
blink::WebMediaPlayer* CreateWebMediaPlayerForMediaStream(
const blink::WebURL& url,
@@ -531,13 +650,26 @@ class CONTENT_EXPORT RenderFrameImpl
// The method is virtual so that layouttests can override it.
virtual scoped_ptr<MediaStreamRendererFactory> CreateRendererFactory();
+ // Checks that the RenderView is ready to display the navigation to |url|. If
+ // the return value is false, the navigation should be abandonned.
+ bool PrepareRenderViewForNavigation(
+ const GURL& url,
+ FrameMsg_Navigate_Type::Value navigate_type,
+ const PageState& state,
+ bool check_history,
+ int pending_history_list_offset,
+ int32 page_id,
+ bool* is_reload,
+ blink::WebURLRequest::CachePolicy* cache_policy);
+
// Returns the URL being loaded by the |frame_|'s request.
GURL GetLoadingUrl() const;
#if defined(OS_ANDROID)
blink::WebMediaPlayer* CreateAndroidWebMediaPlayer(
const blink::WebURL& url,
- blink::WebMediaPlayerClient* client);
+ blink::WebMediaPlayerClient* client,
+ blink::WebContentDecryptionModule* initial_cdm);
RendererMediaPlayerManager* GetMediaPlayerManager();
#endif
@@ -558,10 +690,18 @@ class CONTENT_EXPORT RenderFrameImpl
RenderFrameProxy* render_frame_proxy_;
bool is_detaching_;
+ // If this frame was created to replace a proxy, this will store the routing
+ // id of the proxy to replace at commit-time, at which time it will be
+ // cleared.
+ // TODO(creis): Remove this after switching to PlzNavigate.
+ int proxy_routing_id_;
+
#if defined(ENABLE_PLUGINS)
// Current text input composition text. Empty if no composition is in
// progress.
base::string16 pepper_composition_text_;
+
+ PluginPowerSaverHelper* plugin_power_saver_helper_;
#endif
RendererWebCookieJarImpl cookie_jar_;
@@ -606,10 +746,15 @@ class CONTENT_EXPORT RenderFrameImpl
// along with the RenderFrame automatically. This is why we just store weak
// references.
+ // Dispatches permission requests for Web Notifications.
+ NotificationPermissionDispatcher* notification_permission_dispatcher_;
+
// Holds a reference to the service which provides desktop notifications.
+ // TODO(peter) Remove this once Web Notifications are routed through Platform.
NotificationProvider* notification_provider_;
- blink::WebUserMediaClient* web_user_media_client_;
+ // Destroyed via the RenderFrameObserver::OnDestruct() mechanism.
+ UserMediaClientImpl* web_user_media_client_;
// MidiClient attached to this frame; lazily initialized.
MidiDispatcher* midi_dispatcher_;
@@ -628,12 +773,44 @@ class CONTENT_EXPORT RenderFrameImpl
RendererCdmManager* cdm_manager_;
#endif
- // The geolocation dispatcher attached to this view, lazily initialized.
+#if defined(VIDEO_HOLE)
+ // Whether or not this RenderFrameImpl contains a media player. Used to
+ // register as an observer for video-hole-specific events.
+ bool contains_media_player_;
+#endif
+
+ // The geolocation dispatcher attached to this frame, lazily initialized.
GeolocationDispatcher* geolocation_dispatcher_;
- // The screen orientation dispatcher attached to the view, lazily initialized.
+ // Dispatches permission requests for the Push API. Lazily initialized.
+ PushPermissionDispatcher* push_permission_dispatcher_;
+
+ // The push messaging dispatcher attached to this frame, lazily initialized.
+ // TODO(mvanouwerkerk): Route this functionality through Platform.
+ PushMessagingDispatcher* push_messaging_dispatcher_;
+
+ ServiceRegistryImpl service_registry_;
+
+ // The screen orientation dispatcher attached to the frame, lazily
+ // initialized.
ScreenOrientationDispatcher* screen_orientation_dispatcher_;
+ // The Manifest Manager handles the manifest requests from the browser
+ // process.
+ ManifestManager* manifest_manager_;
+
+ // The current accessibility mode.
+ AccessibilityMode accessibility_mode_;
+
+ // Only valid if |accessibility_mode_| is anything other than
+ // AccessibilityModeOff.
+ RendererAccessibility* renderer_accessibility_;
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ // The external popup for the currently showing select popup.
+ scoped_ptr<ExternalPopupMenu> external_popup_menu_;
+#endif
+
base::WeakPtrFactory<RenderFrameImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
diff --git a/chromium/content/renderer/render_frame_impl_unittest.cc b/chromium/content/renderer/render_frame_impl_unittest.cc
deleted file mode 100644
index 30c04f61724..00000000000
--- a/chromium/content/renderer/render_frame_impl_unittest.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 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/strings/utf_string_conversions.h"
-#include "content/public/common/context_menu_params.h"
-#include "content/renderer/render_frame_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/range/range.h"
-
-namespace content {
-
-TEST(RenderFrameImplTest, ShouldUpdateSelectionTextFromContextMenuParams) {
- struct {
- const char* selection_text;
- size_t selection_text_offset;
- gfx::Range selection_range;
- const char* params_selection_text;
- bool expected_result;
- } cases[] = {
- { "test", 0, gfx::Range(0, 4), "test", false },
- { "zebestest", 0, gfx::Range(2, 6), "best", false },
- { "zebestest", 2, gfx::Range(2, 6), "best", true },
- { "test", 0, gfx::Range(0, 4), "hello", true },
- { "best test", 0, gfx::Range(0, 4), "best ", false },
- { "best test", 0, gfx::Range(0, 5), "best", false },
- };
-
- ContextMenuParams params;
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
- params.selection_text = base::UTF8ToUTF16(cases[i].params_selection_text);
- EXPECT_EQ(cases[i].expected_result,
- RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
- base::UTF8ToUTF16(cases[i].selection_text),
- cases[i].selection_text_offset,
- cases[i].selection_range,
- params));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc
index 2e85a52ded0..6b8c760fe24 100644
--- a/chromium/content/renderer/render_frame_proxy.cc
+++ b/chromium/content/renderer/render_frame_proxy.cc
@@ -7,30 +7,76 @@
#include <map>
#include "base/lazy_instance.h"
+#include "content/child/webmessageportchannel_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/swapped_out_messages.h"
+#include "content/common/view_messages.h"
#include "content/renderer/child_frame_compositing_helper.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
namespace content {
namespace {
+// Facilitates lookup of RenderFrameProxy by routing_id.
typedef std::map<int, RenderFrameProxy*> RoutingIDProxyMap;
static base::LazyInstance<RoutingIDProxyMap> g_routing_id_proxy_map =
LAZY_INSTANCE_INITIALIZER;
+// Facilitates lookup of RenderFrameProxy by WebFrame.
+typedef std::map<blink::WebFrame*, RenderFrameProxy*> FrameMap;
+base::LazyInstance<FrameMap> g_frame_map = LAZY_INSTANCE_INITIALIZER;
+
} // namespace
// static
-RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(int routing_id,
- int frame_routing_id) {
- DCHECK_NE(routing_id, MSG_ROUTING_NONE);
- RenderFrameProxy* proxy = new RenderFrameProxy(routing_id, frame_routing_id);
- return proxy;
+RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame(
+ RenderFrameImpl* frame_to_replace,
+ int routing_id) {
+ CHECK_NE(routing_id, MSG_ROUTING_NONE);
+
+ scoped_ptr<RenderFrameProxy> proxy(
+ new RenderFrameProxy(routing_id, frame_to_replace->GetRoutingID()));
+
+ // When a RenderFrame is replaced by a RenderProxy, the WebRemoteFrame should
+ // always come from WebRemoteFrame::create and a call to WebFrame::swap must
+ // follow later.
+ blink::WebRemoteFrame* web_frame = blink::WebRemoteFrame::create(proxy.get());
+ proxy->Init(web_frame, frame_to_replace->render_view());
+ return proxy.release();
+}
+
+RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
+ int routing_id,
+ int parent_routing_id,
+ int render_view_routing_id) {
+ scoped_ptr<RenderFrameProxy> proxy(
+ new RenderFrameProxy(routing_id, MSG_ROUTING_NONE));
+ RenderViewImpl* render_view = NULL;
+ blink::WebRemoteFrame* web_frame = NULL;
+ if (parent_routing_id == MSG_ROUTING_NONE) {
+ // Create a top level frame.
+ render_view = RenderViewImpl::FromRoutingID(render_view_routing_id);
+ web_frame = blink::WebRemoteFrame::create(proxy.get());
+ render_view->webview()->setMainFrame(web_frame);
+ } else {
+ // Create a frame under an existing parent. The parent is always expected
+ // to be a RenderFrameProxy, because navigations initiated by local frames
+ // should not wind up here.
+ RenderFrameProxy* parent =
+ RenderFrameProxy::FromRoutingID(parent_routing_id);
+ web_frame = parent->web_frame()->createRemoteChild("", proxy.get());
+ render_view = parent->render_view();
+ }
+
+ proxy->Init(web_frame, render_view);
+
+ return proxy.release();
}
// static
@@ -40,31 +86,58 @@ RenderFrameProxy* RenderFrameProxy::FromRoutingID(int32 routing_id) {
return it == proxies->end() ? NULL : it->second;
}
+// static
+RenderFrameProxy* RenderFrameProxy::FromWebFrame(blink::WebFrame* web_frame) {
+ FrameMap::iterator iter = g_frame_map.Get().find(web_frame);
+ if (iter != g_frame_map.Get().end()) {
+ RenderFrameProxy* proxy = iter->second;
+ DCHECK_EQ(web_frame, proxy->web_frame());
+ return proxy;
+ }
+ return NULL;
+}
+
RenderFrameProxy::RenderFrameProxy(int routing_id, int frame_routing_id)
: routing_id_(routing_id),
- frame_routing_id_(frame_routing_id) {
+ frame_routing_id_(frame_routing_id),
+ web_frame_(NULL),
+ render_view_(NULL) {
std::pair<RoutingIDProxyMap::iterator, bool> result =
- g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this));
+ g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this));
CHECK(result.second) << "Inserting a duplicate item.";
RenderThread::Get()->AddRoute(routing_id_, this);
-
- render_frame_ = RenderFrameImpl::FromRoutingID(frame_routing_id);
- CHECK(render_frame_);
- render_frame_->render_view()->RegisterRenderFrameProxy(this);
}
RenderFrameProxy::~RenderFrameProxy() {
- render_frame_->render_view()->UnregisterRenderFrameProxy(this);
+ render_view()->UnregisterRenderFrameProxy(this);
+
+ FrameMap::iterator it = g_frame_map.Get().find(web_frame_);
+ CHECK(it != g_frame_map.Get().end());
+ CHECK_EQ(it->second, this);
+ g_frame_map.Get().erase(it);
+
RenderThread::Get()->RemoveRoute(routing_id_);
g_routing_id_proxy_map.Get().erase(routing_id_);
}
-blink::WebFrame* RenderFrameProxy::GetWebFrame() {
- return render_frame_->GetWebFrame();
+void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
+ RenderViewImpl* render_view) {
+ CHECK(web_frame);
+ CHECK(render_view);
+
+ web_frame_ = web_frame;
+ render_view_ = render_view;
+
+ // TODO(nick): Should all RenderFrameProxies remain observers of their views?
+ render_view_->RegisterRenderFrameProxy(this);
+
+ std::pair<FrameMap::iterator, bool> result =
+ g_frame_map.Get().insert(std::make_pair(web_frame_, this));
+ CHECK(result.second) << "Inserted a duplicate item.";
}
void RenderFrameProxy::DidCommitCompositorFrame() {
- if (compositing_helper_)
+ if (compositing_helper_.get())
compositing_helper_->DidCommitCompositorFrame();
}
@@ -73,16 +146,19 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg)
IPC_MESSAGE_HANDLER(FrameMsg_DeleteProxy, OnDeleteProxy)
IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone)
- IPC_MESSAGE_HANDLER(FrameMsg_BuffersSwapped, OnBuffersSwapped)
IPC_MESSAGE_HANDLER_GENERIC(FrameMsg_CompositorFrameSwapped,
OnCompositorFrameSwapped(msg))
+ IPC_MESSAGE_HANDLER(FrameMsg_DisownOpener, OnDisownOpener)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
- if (!handled)
- return render_frame_->OnMessageReceived(msg);
+ // If |handled| is true, |this| may have been deleted.
+ if (handled)
+ return true;
- return handled;
+ RenderFrameImpl* render_frame =
+ RenderFrameImpl::FromRoutingID(frame_routing_id_);
+ return render_frame && render_frame->OnMessageReceived(msg);
}
bool RenderFrameProxy::Send(IPC::Message* message) {
@@ -95,35 +171,15 @@ bool RenderFrameProxy::Send(IPC::Message* message) {
}
void RenderFrameProxy::OnDeleteProxy() {
- RenderFrameImpl* render_frame =
- RenderFrameImpl::FromRoutingID(frame_routing_id_);
- CHECK(render_frame);
- render_frame->set_render_frame_proxy(NULL);
-
- delete this;
+ DCHECK(web_frame_->isWebRemoteFrame());
+ web_frame_->detach();
}
void RenderFrameProxy::OnChildFrameProcessGone() {
- if (compositing_helper_)
+ if (compositing_helper_.get())
compositing_helper_->ChildFrameGone();
}
-void RenderFrameProxy::OnBuffersSwapped(
- const FrameMsg_BuffersSwapped_Params& params) {
- if (!compositing_helper_.get()) {
- compositing_helper_ =
- ChildFrameCompositingHelper::CreateCompositingHelperForRenderFrame(
- GetWebFrame(), this, routing_id_);
- compositing_helper_->EnableCompositing(true);
- }
- compositing_helper_->OnBuffersSwapped(
- params.size,
- params.mailbox,
- params.gpu_route_id,
- params.gpu_host_id,
- render_frame_->render_view()->GetWebView()->deviceScaleFactor());
-}
-
void RenderFrameProxy::OnCompositorFrameSwapped(const IPC::Message& message) {
FrameMsg_CompositorFrameSwapped::Param param;
if (!FrameMsg_CompositorFrameSwapped::Read(&message, &param))
@@ -134,8 +190,7 @@ void RenderFrameProxy::OnCompositorFrameSwapped(const IPC::Message& message) {
if (!compositing_helper_.get()) {
compositing_helper_ =
- ChildFrameCompositingHelper::CreateCompositingHelperForRenderFrame(
- GetWebFrame(), this, routing_id_);
+ ChildFrameCompositingHelper::CreateForRenderFrameProxy(this);
compositing_helper_->EnableCompositing(true);
}
compositing_helper_->OnCompositorFrameSwapped(frame.Pass(),
@@ -145,4 +200,101 @@ void RenderFrameProxy::OnCompositorFrameSwapped(const IPC::Message& message) {
param.a.shared_memory_handle);
}
+void RenderFrameProxy::OnDisownOpener() {
+ // TODO(creis): We should only see this for main frames for now. To support
+ // disowning the opener on subframes, we will need to move WebContentsImpl's
+ // opener_ to FrameTreeNode.
+ CHECK(!web_frame_->parent());
+
+ // When there is a RenderFrame for this proxy, tell it to disown its opener.
+ // TODO(creis): Remove this when we only have WebRemoteFrames and make sure
+ // they know they have an opener.
+ RenderFrameImpl* render_frame =
+ RenderFrameImpl::FromRoutingID(frame_routing_id_);
+ if (render_frame) {
+ if (render_frame->GetWebFrame()->opener())
+ render_frame->GetWebFrame()->setOpener(NULL);
+ return;
+ }
+
+ if (web_frame_->opener())
+ web_frame_->setOpener(NULL);
+}
+
+void RenderFrameProxy::frameDetached() {
+ if (web_frame_->parent())
+ web_frame_->parent()->removeChild(web_frame_);
+
+ web_frame_->close();
+ delete this;
+}
+
+void RenderFrameProxy::postMessageEvent(
+ blink::WebLocalFrame* source_frame,
+ blink::WebRemoteFrame* target_frame,
+ blink::WebSecurityOrigin target_origin,
+ blink::WebDOMMessageEvent event) {
+ DCHECK(!web_frame_ || web_frame_ == target_frame);
+
+ ViewMsg_PostMessage_Params params;
+ params.is_data_raw_string = false;
+ params.data = event.data().toString();
+ params.source_origin = event.origin();
+ if (!target_origin.isNull())
+ params.target_origin = target_origin.toString();
+
+ blink::WebMessagePortChannelArray channels = event.releaseChannels();
+ if (!channels.isEmpty()) {
+ std::vector<int> message_port_ids(channels.size());
+ // Extract the port IDs from the channel array.
+ for (size_t i = 0; i < channels.size(); ++i) {
+ WebMessagePortChannelImpl* webchannel =
+ static_cast<WebMessagePortChannelImpl*>(channels[i]);
+ message_port_ids[i] = webchannel->message_port_id();
+ webchannel->QueueMessages();
+ DCHECK_NE(message_port_ids[i], MSG_ROUTING_NONE);
+ }
+ params.message_port_ids = message_port_ids;
+ }
+
+ // Include the routing ID for the source frame (if one exists), which the
+ // browser process will translate into the routing ID for the equivalent
+ // frame in the target process.
+ params.source_routing_id = MSG_ROUTING_NONE;
+ if (source_frame) {
+ RenderViewImpl* source_view =
+ RenderViewImpl::FromWebView(source_frame->view());
+ if (source_view)
+ params.source_routing_id = source_view->routing_id();
+ }
+
+ Send(new ViewHostMsg_RouteMessageEvent(render_view_->GetRoutingID(), params));
+}
+
+void RenderFrameProxy::initializeChildFrame(
+ const blink::WebRect& frame_rect,
+ float scale_factor) {
+ Send(new FrameHostMsg_InitializeChildFrame(
+ routing_id_, frame_rect, scale_factor));
+}
+
+void RenderFrameProxy::navigate(const blink::WebURLRequest& request,
+ bool should_replace_current_entry) {
+ FrameHostMsg_OpenURL_Params params;
+ params.url = request.url();
+ params.referrer = Referrer(
+ GURL(request.httpHeaderField(blink::WebString::fromUTF8("Referer"))),
+ request.referrerPolicy());
+ params.disposition = CURRENT_TAB;
+ params.should_replace_current_entry = should_replace_current_entry;
+ params.user_gesture =
+ blink::WebUserGestureIndicator::isProcessingUserGesture();
+ blink::WebUserGestureIndicator::consumeUserGesture();
+ Send(new FrameHostMsg_OpenURL(routing_id_, params));
+}
+
+void RenderFrameProxy::forwardInputEvent(const blink::WebInputEvent* event) {
+ Send(new FrameHostMsg_ForwardInputEvent(routing_id_, event));
+}
+
} // namespace
diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h
index 54c63619290..2afd45383e3 100644
--- a/chromium/content/renderer/render_frame_proxy.h
+++ b/chromium/content/renderer/render_frame_proxy.h
@@ -11,12 +11,16 @@
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
-#include "third_party/WebKit/public/web/WebFrameClient.h"
#include "third_party/WebKit/public/web/WebRemoteFrame.h"
+#include "third_party/WebKit/public/web/WebRemoteFrameClient.h"
struct FrameMsg_BuffersSwapped_Params;
struct FrameMsg_CompositorFrameSwapped_Params;
+namespace blink {
+class WebInputEvent;
+}
+
namespace content {
class ChildFrameCompositingHelper;
@@ -46,47 +50,94 @@ class RenderViewImpl;
class CONTENT_EXPORT RenderFrameProxy
: public IPC::Listener,
public IPC::Sender,
- NON_EXPORTED_BASE(public blink::WebFrameClient) {
+ NON_EXPORTED_BASE(public blink::WebRemoteFrameClient) {
public:
+ // This method should be used to create a RenderFrameProxy, which will replace
+ // an existing RenderFrame during its cross-process navigation from the
+ // current process to a different one. |routing_id| will be ID of the newly
+ // created RenderFrameProxy. |frame_to_replace| is the frame that the new
+ // proxy will eventually swap places with.
+ static RenderFrameProxy* CreateProxyToReplaceFrame(
+ RenderFrameImpl* frame_to_replace,
+ int routing_id);
+
+ // This method should be used to create a RenderFrameProxy, when there isn't
+ // an existing RenderFrame. It should be called to construct a local
+ // representation of a RenderFrame that has been created in another process --
+ // for example, after a cross-process navigation or after the addition of a
+ // new frame local to some other process. |routing_id| will be the ID of the
+ // newly created RenderFrameProxy. |parent_routing_id| is the routing ID of
+ // the RenderFrameProxy to which the new frame is parented.
+ // |render_view_routing_id| identifies the RenderView to be associated with
+ // this frame.
+ //
+ // |parent_routing_id| always identifies a RenderFrameProxy (never a
+ // RenderFrame) because a new child of a local frame should always start out
+ // as a frame, not a proxy.
static RenderFrameProxy* CreateFrameProxy(int routing_id,
- int frame_routing_id);
+ int parent_routing_id,
+ int render_view_routing_id);
// Returns the RenderFrameProxy for the given routing ID.
static RenderFrameProxy* FromRoutingID(int routing_id);
- virtual ~RenderFrameProxy();
+ // Returns the RenderFrameProxy given a WebFrame.
+ static RenderFrameProxy* FromWebFrame(blink::WebFrame* web_frame);
- // IPC::Sender
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ ~RenderFrameProxy() override;
- RenderFrameImpl* render_frame() {
- return render_frame_;
- }
+ // IPC::Sender
+ bool Send(IPC::Message* msg) override;
// Out-of-process child frames receive a signal from RenderWidgetCompositor
// when a compositor frame has committed.
void DidCommitCompositorFrame();
+ int routing_id() { return routing_id_; }
+ RenderViewImpl* render_view() { return render_view_; }
+ blink::WebRemoteFrame* web_frame() { return web_frame_; }
+
+ // blink::WebRemoteFrameClient implementation:
+ virtual void frameDetached();
+ virtual void postMessageEvent(
+ blink::WebLocalFrame* sourceFrame,
+ blink::WebRemoteFrame* targetFrame,
+ blink::WebSecurityOrigin target,
+ blink::WebDOMMessageEvent event);
+ virtual void initializeChildFrame(
+ const blink::WebRect& frame_rect,
+ float scale_factor);
+ virtual void navigate(const blink::WebURLRequest& request,
+ bool should_replace_current_entry);
+ virtual void forwardInputEvent(const blink::WebInputEvent* event);
+
private:
RenderFrameProxy(int routing_id, int frame_routing_id);
+ void Init(blink::WebRemoteFrame* frame, RenderViewImpl* render_view);
+
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// IPC handlers
void OnDeleteProxy();
void OnChildFrameProcessGone();
- void OnBuffersSwapped(const FrameMsg_BuffersSwapped_Params& params);
void OnCompositorFrameSwapped(const IPC::Message& message);
+ void OnDisownOpener();
- blink::WebFrame* GetWebFrame();
+ // The routing ID by which this RenderFrameProxy is known.
+ const int routing_id_;
- int routing_id_;
- int frame_routing_id_;
- RenderFrameImpl* render_frame_;
+ // The routing ID of the local RenderFrame (if any) which this
+ // RenderFrameProxy is meant to replace in the frame tree.
+ const int frame_routing_id_;
+ // Stores the WebRemoteFrame we are associated with.
+ blink::WebRemoteFrame* web_frame_;
scoped_refptr<ChildFrameCompositingHelper> compositing_helper_;
+ RenderViewImpl* render_view_;
+
DISALLOW_COPY_AND_ASSIGN(RenderFrameProxy);
};
diff --git a/chromium/content/renderer/render_process.h b/chromium/content/renderer/render_process.h
index 76b88e60220..07c53e13127 100644
--- a/chromium/content/renderer/render_process.h
+++ b/chromium/content/renderer/render_process.h
@@ -19,7 +19,7 @@ namespace content {
class RenderProcess : public ChildProcess {
public:
RenderProcess() {}
- virtual ~RenderProcess() {}
+ ~RenderProcess() override {}
// Keep track of the cumulative set of enabled bindings for this process,
// across any view.
diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc
index c05a19e2134..421e60bcf96 100644
--- a/chromium/content/renderer/render_process_impl.cc
+++ b/chromium/content/renderer/render_process_impl.cc
@@ -15,16 +15,13 @@
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/sys_info.h"
#include "content/child/site_isolation_policy.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/content_renderer_client.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "v8/include/v8.h"
-#if defined(OS_ANDROID)
-#include "base/android/sys_utils.h"
-#endif
-
namespace content {
RenderProcessImpl::RenderProcessImpl()
@@ -46,13 +43,11 @@ RenderProcessImpl::RenderProcessImpl()
}
#endif
-#if defined(OS_ANDROID)
- if (base::android::SysUtils::IsLowEndDevice()) {
+ if (base::SysInfo::IsLowEndDevice()) {
std::string optimize_flag("--optimize-for-size");
v8::V8::SetFlagsFromString(optimize_flag.c_str(),
static_cast<int>(optimize_flag.size()));
}
-#endif
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
diff --git a/chromium/content/renderer/render_process_impl.h b/chromium/content/renderer/render_process_impl.h
index 97c1244a232..7b441e2c4cb 100644
--- a/chromium/content/renderer/render_process_impl.h
+++ b/chromium/content/renderer/render_process_impl.h
@@ -15,11 +15,11 @@ namespace content {
class RenderProcessImpl : public RenderProcess {
public:
RenderProcessImpl();
- virtual ~RenderProcessImpl();
+ ~RenderProcessImpl() override;
// RenderProcess implementation.
- virtual void AddBindings(int bindings) OVERRIDE;
- virtual int GetEnabledBindings() const OVERRIDE;
+ void AddBindings(int bindings) override;
+ int GetEnabledBindings() const override;
private:
// Bitwise-ORed set of extra bindings that have been enabled anywhere in this
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index 0c4634508ec..6984b137743 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -15,11 +15,14 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/discardable_memory.h"
+#include "base/memory/discardable_memory_emulated.h"
+#include "base/memory/discardable_memory_shmem_allocator.h"
#include "base/memory/shared_memory.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/metrics/stats_table.h"
#include "base/path_service.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
@@ -28,10 +31,15 @@
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "cc/base/switches.h"
+#include "cc/blink/web_external_bitmap_impl.h"
+#include "cc/blink/web_layer_impl.h"
#include "cc/resources/raster_worker_pool.h"
#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/appcache/appcache_frontend_impl.h"
+#include "content/child/child_discardable_shared_memory_manager.h"
+#include "content/child/child_gpu_memory_buffer_manager.h"
#include "content/child/child_histogram_message_filter.h"
+#include "content/child/content_child_helpers.h"
#include "content/child/db_message_filter.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_message_filter.h"
@@ -46,12 +54,12 @@
#include "content/common/content_constants_internal.h"
#include "content/common/database_messages.h"
#include "content/common/dom_storage/dom_storage_messages.h"
+#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/gpu/gpu_messages.h"
#include "content/common/gpu/gpu_process_launch_causes.h"
-#include "content/common/mojo/mojo_service_names.h"
+#include "content/common/render_frame_setup.mojom.h"
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
@@ -63,15 +71,11 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_process_observer.h"
#include "content/public/renderer/render_view_visitor.h"
-#include "content/renderer/compositor_bindings/web_external_bitmap_impl.h"
-#include "content/renderer/compositor_bindings/web_layer_impl.h"
#include "content/renderer/devtools/devtools_agent_filter.h"
#include "content/renderer/dom_storage/dom_storage_dispatcher.h"
#include "content/renderer/dom_storage/webstoragearea_impl.h"
#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
-#include "content/renderer/gamepad_shared_memory_reader.h"
#include "content/renderer/gpu/compositor_output_surface.h"
-#include "content/renderer/gpu/gpu_benchmarking_extension.h"
#include "content/renderer/input/input_event_filter.h"
#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/media/aec_dump_message_filter.h"
@@ -80,26 +84,23 @@
#include "content/renderer/media/audio_renderer_mixer_manager.h"
#include "content/renderer/media/media_stream_center.h"
#include "content/renderer/media/midi_message_filter.h"
-#include "content/renderer/media/peer_connection_tracker.h"
#include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
-#include "content/renderer/media/rtc_peer_connection_handler.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_message_filter.h"
-#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
-#include "content/renderer/media/webrtc_identity_service.h"
#include "content/renderer/net_info_helper.h"
#include "content/renderer/p2p/socket_dispatcher.h"
+#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_view_impl.h"
-#include "content/renderer/renderer_webkitplatformsupport_impl.h"
+#include "content/renderer/renderer_blink_platform_impl.h"
+#include "content/renderer/scheduler/renderer_scheduler.h"
#include "content/renderer/service_worker/embedded_worker_context_message_filter.h"
#include "content/renderer/service_worker/embedded_worker_dispatcher.h"
#include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
-#include "content/renderer/web_ui_setup_impl.h"
-#include "grit/content_resources.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_forwarding_message_filter.h"
#include "ipc/ipc_platform_file.h"
+#include "ipc/mojo/ipc_channel_mojo.h"
#include "media/base/audio_hardware_config.h"
#include "media/base/media.h"
#include "media/filters/gpu_video_accelerator_factories.h"
@@ -108,6 +109,7 @@
#include "net/base/net_util.h"
#include "skia/ext/event_tracer_impl.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebThread.h"
#include "third_party/WebKit/public/web/WebColorName.h"
#include "third_party/WebKit/public/web/WebDatabase.h"
#include "third_party/WebKit/public/web/WebDocument.h"
@@ -151,6 +153,13 @@
#include "content/renderer/npapi/plugin_channel_host.h"
#endif
+#if defined(ENABLE_WEBRTC)
+#include "content/renderer/media/peer_connection_tracker.h"
+#include "content/renderer/media/rtc_peer_connection_handler.h"
+#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
+#include "content/renderer/media/webrtc_identity_service.h"
+#endif
+
using base::ThreadRestrictions;
using blink::WebDocument;
using blink::WebFrame;
@@ -166,11 +175,16 @@ namespace content {
namespace {
const int64 kInitialIdleHandlerDelayMs = 1000;
-const int64 kShortIdleHandlerDelayMs = 1000;
const int64 kLongIdleHandlerDelayMs = 30*1000;
-const int kIdleCPUUsageThresholdInPercents = 3;
-const int kMinRasterThreads = 1;
-const int kMaxRasterThreads = 64;
+
+// Maximum allocation size allowed for image scaling filters that
+// require pre-scaling. Skia will fallback to a filter that doesn't
+// require pre-scaling if the default filter would require an
+// allocation that exceeds this limit.
+const size_t kImageCacheSingleAllocationByteLimit = 64 * 1024 * 1024;
+
+const size_t kEmulatedDiscardableMemoryBytesToKeepWhenWidgetsHidden =
+ 4 * 1024 * 1024;
// Keep the global RenderThreadImpl in a TLS slot so it is impossible to access
// incorrectly from the wrong thread.
@@ -186,7 +200,7 @@ class RenderViewZoomer : public RenderViewVisitor {
zoom_level_(zoom_level) {
}
- virtual bool Visit(RenderView* render_view) OVERRIDE {
+ bool Visit(RenderView* render_view) override {
WebView* webview = render_view->GetWebView();
WebDocument document = webview->mainFrame()->document();
@@ -266,8 +280,75 @@ void NotifyTimezoneChangeOnThisThread() {
v8::Date::DateTimeConfigurationChangeNotification(isolate);
}
+class RenderFrameSetupImpl : public mojo::InterfaceImpl<RenderFrameSetup> {
+ public:
+ RenderFrameSetupImpl()
+ : routing_id_highmark_(-1) {
+ }
+
+ void GetServiceProviderForFrame(
+ int32_t frame_routing_id,
+ mojo::InterfaceRequest<mojo::ServiceProvider> request) override {
+ // TODO(morrita): This is for investigating http://crbug.com/415059 and
+ // should be removed once it is fixed.
+ CHECK_LT(routing_id_highmark_, frame_routing_id);
+ routing_id_highmark_ = frame_routing_id;
+
+ RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(frame_routing_id);
+ // We can receive a GetServiceProviderForFrame message for a frame not yet
+ // created due to a race between the message and a ViewMsg_New IPC that
+ // triggers creation of the RenderFrame we want.
+ if (!frame) {
+ RenderThreadImpl::current()->RegisterPendingRenderFrameConnect(
+ frame_routing_id, request.PassMessagePipe());
+ return;
+ }
+
+ frame->BindServiceRegistry(request.PassMessagePipe());
+ }
+
+ private:
+ int32_t routing_id_highmark_;
+};
+
+void CreateRenderFrameSetup(mojo::InterfaceRequest<RenderFrameSetup> request) {
+ mojo::BindToRequest(new RenderFrameSetupImpl(), &request);
+}
+
+bool ShouldUseMojoChannel() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableRendererMojoChannel) ||
+ IPC::ChannelMojo::ShouldBeUsed();
+}
+
+blink::WebGraphicsContext3D::Attributes GetOffscreenAttribs() {
+ blink::WebGraphicsContext3D::Attributes attributes;
+ attributes.shareResources = true;
+ attributes.depth = false;
+ attributes.stencil = false;
+ attributes.antialias = false;
+ attributes.noAutomaticFlushes = true;
+ return attributes;
+}
+
} // namespace
+// For measuring memory usage after each task. Behind a command line flag.
+class MemoryObserver : public base::MessageLoop::TaskObserver {
+ public:
+ MemoryObserver() {}
+ ~MemoryObserver() override {}
+
+ void WillProcessTask(const base::PendingTask& pending_task) override {}
+
+ void DidProcessTask(const base::PendingTask& pending_task) override {
+ LOCAL_HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryObserver);
+};
+
RenderThreadImpl::HistogramCustomizer::HistogramCustomizer() {
custom_histograms_.insert("V8.MemoryExternalFragmentationTotal");
custom_histograms_.insert("V8.MemoryHeapSampleTotalCommitted");
@@ -317,12 +398,13 @@ RenderThreadImpl* RenderThreadImpl::current() {
// When we run plugins in process, we actually run them on the render thread,
// which means that we need to make the render thread pump UI events.
-RenderThreadImpl::RenderThreadImpl() {
+RenderThreadImpl::RenderThreadImpl()
+ : ChildThread(Options(ShouldUseMojoChannel())) {
Init();
}
RenderThreadImpl::RenderThreadImpl(const std::string& channel_name)
- : ChildThread(channel_name) {
+ : ChildThread(Options(channel_name, ShouldUseMojoChannel())) {
Init();
}
@@ -358,6 +440,7 @@ void RenderThreadImpl::Init() {
dom_storage_dispatcher_.reset(new DomStorageDispatcher());
main_thread_indexed_db_dispatcher_.reset(new IndexedDBDispatcher(
thread_safe_sender()));
+ renderer_scheduler_ = RendererScheduler::Create();
embedded_worker_dispatcher_.reset(new EmbeddedWorkerDispatcher());
media_stream_center_ = NULL;
@@ -406,17 +489,19 @@ void RenderThreadImpl::Init() {
InitSkiaEventTracer();
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking))
- RegisterExtension(GpuBenchmarkingExtension::Get());
is_impl_side_painting_enabled_ =
command_line.HasSwitch(switches::kEnableImplSidePainting);
- WebLayerImpl::SetImplSidePaintingEnabled(is_impl_side_painting_enabled_);
+ cc_blink::WebLayerImpl::SetImplSidePaintingEnabled(
+ is_impl_side_painting_enabled_);
- is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy) &&
- !command_line.HasSwitch(switches::kDisableZeroCopy);
+ is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy);
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
is_one_copy_enabled_ = command_line.HasSwitch(switches::kEnableOneCopy);
+#else
+ is_one_copy_enabled_ = !command_line.HasSwitch(switches::kDisableOneCopy);
+#endif
if (command_line.HasSwitch(switches::kDisableLCDText)) {
is_lcd_text_enabled_ = false;
@@ -443,12 +528,6 @@ void RenderThreadImpl::Init() {
is_distance_field_text_enabled_ = false;
}
- is_low_res_tiling_enabled_ = true;
- if (command_line.HasSwitch(switches::kDisableLowResTiling) &&
- !command_line.HasSwitch(switches::kEnableLowResTiling)) {
- is_low_res_tiling_enabled_ = false;
- }
-
// Note that under Linux, the media library will normally already have
// been initialized by the Zygote before this instance became a Renderer.
base::FilePath media_path;
@@ -482,32 +561,33 @@ void RenderThreadImpl::Init() {
base::DiscardableMemory::SetPreferredType(type);
- // Allow discardable memory implementations to register memory pressure
- // listeners.
- base::DiscardableMemory::RegisterMemoryPressureListeners();
-
- // AllocateGpuMemoryBuffer must be used exclusively on one thread but
- // it doesn't have to be the same thread RenderThreadImpl is created on.
- allocate_gpu_memory_buffer_thread_checker_.DetachFromThread();
-
- if (command_line.HasSwitch(switches::kNumRasterThreads)) {
- int num_raster_threads;
+ if (is_impl_side_painting_enabled_) {
+ int num_raster_threads = 0;
std::string string_value =
command_line.GetSwitchValueASCII(switches::kNumRasterThreads);
- if (base::StringToInt(string_value, &num_raster_threads) &&
- num_raster_threads >= kMinRasterThreads &&
- num_raster_threads <= kMaxRasterThreads) {
- cc::RasterWorkerPool::SetNumRasterThreads(num_raster_threads);
- } else {
- LOG(WARNING) << "Failed to parse switch " <<
- switches::kNumRasterThreads << ": " << string_value;
- }
+ bool parsed_num_raster_threads =
+ base::StringToInt(string_value, &num_raster_threads);
+ DCHECK(parsed_num_raster_threads) << string_value;
+ DCHECK_GT(num_raster_threads, 0);
+ cc::RasterWorkerPool::SetNumRasterThreads(num_raster_threads);
}
+ base::DiscardableMemoryShmemAllocator::SetInstance(
+ ChildThread::discardable_shared_memory_manager());
+
+ service_registry()->AddService<RenderFrameSetup>(
+ base::Bind(CreateRenderFrameSetup));
+
TRACE_EVENT_END_ETW("RenderThreadImpl::Init", 0, "");
}
RenderThreadImpl::~RenderThreadImpl() {
+ for (std::map<int, mojo::MessagePipeHandle>::iterator it =
+ pending_render_frame_connects_.begin();
+ it != pending_render_frame_connects_.end();
+ ++it) {
+ mojo::CloseRaw(it->second);
+ }
}
void RenderThreadImpl::Shutdown() {
@@ -516,14 +596,19 @@ void RenderThreadImpl::Shutdown() {
ChildThread::Shutdown();
+ if (memory_observer_) {
+ message_loop()->RemoveTaskObserver(memory_observer_.get());
+ memory_observer_.reset();
+ }
+
// Wait for all databases to be closed.
- if (webkit_platform_support_) {
+ if (blink_platform_impl_) {
// WaitForAllDatabasesToClose might run a nested message loop. To avoid
// processing timer events while we're already in the process of shutting
// down blink, put a ScopePageLoadDeferrer on the stack.
WebView::willEnterModalLoop();
- webkit_platform_support_->web_database_observer_impl()->
- WaitForAllDatabasesToClose();
+ blink_platform_impl_->web_database_observer_impl()
+ ->WaitForAllDatabasesToClose();
WebView::didExitModalLoop();
}
@@ -536,9 +621,6 @@ void RenderThreadImpl::Shutdown() {
RemoveFilter(audio_input_message_filter_.get());
audio_input_message_filter_ = NULL;
- RemoveFilter(audio_message_filter_.get());
- audio_message_filter_ = NULL;
-
#if defined(ENABLE_WEBRTC)
RTCPeerConnectionHandler::DestructAllHandlers();
@@ -560,6 +642,11 @@ void RenderThreadImpl::Shutdown() {
}
media_thread_.reset();
+
+ // AudioMessageFilter may be accessed on |media_thread_|, so shutdown after.
+ RemoveFilter(audio_message_filter_.get());
+ audio_message_filter_ = NULL;
+
compositor_thread_.reset();
input_handler_manager_.reset();
if (input_event_filter_.get()) {
@@ -576,7 +663,9 @@ void RenderThreadImpl::Shutdown() {
// hold pointers to V8 objects (e.g., via pending requests).
main_thread_indexed_db_dispatcher_.reset();
- if (webkit_platform_support_)
+ main_thread_compositor_task_runner_ = NULL;
+
+ if (blink_platform_impl_)
blink::shutdown();
lazy_tls.Pointer()->Set(NULL);
@@ -617,7 +706,7 @@ bool RenderThreadImpl::Send(IPC::Message* msg) {
if (pumping_events) {
if (suspend_webkit_shared_timer)
- webkit_platform_support_->SuspendSharedTimer();
+ blink_platform_impl_->SuspendSharedTimer();
if (notify_webkit_of_modal_loop)
WebView::willEnterModalLoop();
@@ -646,7 +735,7 @@ bool RenderThreadImpl::Send(IPC::Message* msg) {
WebView::didExitModalLoop();
if (suspend_webkit_shared_timer)
- webkit_platform_support_->ResumeSharedTimer();
+ blink_platform_impl_->ResumeSharedTimer();
}
return rv;
@@ -681,6 +770,18 @@ scoped_refptr<base::MessageLoopProxy>
void RenderThreadImpl::AddRoute(int32 routing_id, IPC::Listener* listener) {
ChildThread::GetRouter()->AddRoute(routing_id, listener);
+ std::map<int, mojo::MessagePipeHandle>::iterator it =
+ pending_render_frame_connects_.find(routing_id);
+ if (it == pending_render_frame_connects_.end())
+ return;
+
+ RenderFrameImpl* frame = RenderFrameImpl::FromRoutingID(routing_id);
+ if (!frame)
+ return;
+
+ mojo::ScopedMessagePipeHandle handle(it->second);
+ pending_render_frame_connects_.erase(it);
+ frame->BindServiceRegistry(handle.Pass());
}
void RenderThreadImpl::RemoveRoute(int32 routing_id) {
@@ -704,6 +805,15 @@ void RenderThreadImpl::RemoveEmbeddedWorkerRoute(int32 routing_id) {
}
}
+void RenderThreadImpl::RegisterPendingRenderFrameConnect(
+ int routing_id,
+ mojo::ScopedMessagePipeHandle handle) {
+ std::pair<std::map<int, mojo::MessagePipeHandle>::iterator, bool> result =
+ pending_render_frame_connects_.insert(
+ std::make_pair(routing_id, handle.release()));
+ CHECK(result.second) << "Inserting a duplicate item.";
+}
+
int RenderThreadImpl::GenerateRoutingID() {
int routing_id = MSG_ROUTING_NONE;
Send(new ViewHostMsg_GenerateRoutingID(&routing_id));
@@ -732,11 +842,12 @@ void RenderThreadImpl::SetResourceDispatcherDelegate(
}
void RenderThreadImpl::EnsureWebKitInitialized() {
- if (webkit_platform_support_)
+ if (blink_platform_impl_)
return;
- webkit_platform_support_.reset(new RendererWebKitPlatformSupportImpl);
- blink::initialize(webkit_platform_support_.get());
+ blink_platform_impl_.reset(
+ new RendererBlinkPlatformImpl(renderer_scheduler_.get()));
+ blink::initialize(blink_platform_impl_.get());
v8::Isolate* isolate = blink::mainThreadIsolate();
@@ -746,7 +857,10 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- bool enable = command_line.HasSwitch(switches::kEnableThreadedCompositing);
+ main_thread_compositor_task_runner_ =
+ renderer_scheduler()->CompositorTaskRunner();
+
+ bool enable = !command_line.HasSwitch(switches::kDisableThreadedCompositing);
if (enable) {
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
@@ -777,7 +891,9 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
#endif
if (!input_handler_manager_client) {
input_event_filter_ =
- new InputEventFilter(this, compositor_message_loop_proxy_);
+ new InputEventFilter(this,
+ main_thread_compositor_task_runner_,
+ compositor_message_loop_proxy_);
AddFilter(input_event_filter_.get());
input_handler_manager_client = input_event_filter_.get();
}
@@ -796,10 +912,6 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
CompositorOutputSurface::CreateFilter(output_surface_loop.get());
AddFilter(compositor_output_surface_filter_.get());
- gamepad_shared_memory_reader_.reset(
- new GamepadSharedMemoryReader(webkit_platform_support_.get()));
- AddObserver(gamepad_shared_memory_reader_.get());
-
RenderThreadImpl::RegisterSchemes();
EnableBlinkPlatformLogChannels(
@@ -808,7 +920,6 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
if (!media::IsMediaLibraryInitialized()) {
- WebRuntimeFeatures::enableMediaPlayer(false);
WebRuntimeFeatures::enableWebAudio(false);
}
@@ -820,13 +931,21 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
ScheduleIdleHandler(kLongIdleHandlerDelayMs);
- SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction);
+ cc_blink::SetSharedMemoryAllocationFunction(AllocateSharedMemoryFunction);
// Limit use of the scaled image cache to when deferred image decoding is
// enabled.
if (!command_line.HasSwitch(switches::kEnableDeferredImageDecoding) &&
!is_impl_side_painting_enabled_)
- SkGraphics::SetImageCacheByteLimit(0u);
+ SkGraphics::SetResourceCacheTotalByteLimit(0u);
+
+ SkGraphics::SetResourceCacheSingleAllocationByteLimit(
+ kImageCacheSingleAllocationByteLimit);
+
+ if (command_line.HasSwitch(switches::kMemoryMetrics)) {
+ memory_observer_.reset(new MemoryObserver());
+ message_loop()->AddTaskObserver(memory_observer_.get());
+ }
}
void RenderThreadImpl::RegisterSchemes() {
@@ -893,37 +1012,49 @@ void RenderThreadImpl::IdleHandler() {
GetContentClient()->renderer()->
RunIdleHandlerWhenWidgetsHidden();
if (run_in_foreground_tab) {
- IdleHandlerInForegroundTab();
+ if (idle_notifications_to_skip_ > 0) {
+ --idle_notifications_to_skip_;
+ } else {
+ base::allocator::ReleaseFreeMemory();
+ base::DiscardableMemory::ReduceMemoryUsage();
+ }
+ ScheduleIdleHandler(kLongIdleHandlerDelayMs);
return;
}
base::allocator::ReleaseFreeMemory();
+ base::DiscardableMemory::ReleaseFreeMemory();
// Continue the idle timer if the webkit shared timer is not suspended or
// something is left to do.
bool continue_timer = !webkit_shared_timer_suspended_;
- if (!v8::V8::IdleNotification()) {
+ if (blink::mainThreadIsolate() &&
+ !blink::mainThreadIsolate()->IdleNotification(1000)) {
continue_timer = true;
}
if (!base::DiscardableMemory::ReduceMemoryUsage()) {
continue_timer = true;
}
- // Schedule next invocation.
+ // Schedule next invocation. When the tab is originally hidden, an invocation
+ // is scheduled for kInitialIdleHandlerDelayMs in
+ // RenderThreadImpl::WidgetHidden in order to race to a minimal heap.
+ // After that, idle calls can be much less frequent, so run at a maximum of
+ // once every kLongIdleHandlerDelayMs.
// Dampen the delay using the algorithm (if delay is in seconds):
// delay = delay + 1 / (delay + 2)
// Using floor(delay) has a dampening effect such as:
- // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
+ // 30s, 30, 30, 31, 31, 31, 31, 32, 32, ...
// If the delay is in milliseconds, the above formula is equivalent to:
// delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2)
// which is equivalent to
// delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000).
- // Note that idle_notification_delay_in_ms_ would be reset to
- // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden.
if (continue_timer) {
- ScheduleIdleHandler(idle_notification_delay_in_ms_ +
- 1000000 / (idle_notification_delay_in_ms_ + 2000));
+ ScheduleIdleHandler(
+ std::max(kLongIdleHandlerDelayMs,
+ idle_notification_delay_in_ms_ +
+ 1000000 / (idle_notification_delay_in_ms_ + 2000)));
} else {
idle_timer_.Stop();
@@ -932,40 +1063,6 @@ void RenderThreadImpl::IdleHandler() {
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification());
}
-void RenderThreadImpl::IdleHandlerInForegroundTab() {
- // Increase the delay in the same way as in IdleHandler,
- // but make it periodic by reseting it once it is too big.
- int64 new_delay_ms = idle_notification_delay_in_ms_ +
- 1000000 / (idle_notification_delay_in_ms_ + 2000);
- if (new_delay_ms >= kLongIdleHandlerDelayMs)
- new_delay_ms = kShortIdleHandlerDelayMs;
-
- if (idle_notifications_to_skip_ > 0) {
- idle_notifications_to_skip_--;
- } else {
- int cpu_usage = 0;
- Send(new ViewHostMsg_GetCPUUsage(&cpu_usage));
- // Idle notification hint roughly specifies the expected duration of the
- // idle pause. We set it proportional to the idle timer delay.
- int idle_hint = static_cast<int>(new_delay_ms / 10);
- if (cpu_usage < kIdleCPUUsageThresholdInPercents) {
- base::allocator::ReleaseFreeMemory();
-
- bool finished_idle_work = true;
- if (!v8::V8::IdleNotification(idle_hint))
- finished_idle_work = false;
- if (!base::DiscardableMemory::ReduceMemoryUsage())
- finished_idle_work = false;
-
- // V8 finished collecting garbage and discardable memory system has no
- // more idle work left.
- if (finished_idle_work)
- new_delay_ms = kLongIdleHandlerDelayMs;
- }
- }
- ScheduleIdleHandler(new_delay_ms);
-}
-
int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
return idle_notification_delay_in_ms_;
}
@@ -1000,12 +1097,12 @@ RenderThreadImpl::GetGpuFactories() {
scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel();
const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
scoped_refptr<media::GpuVideoAcceleratorFactories> gpu_factories;
- scoped_refptr<base::MessageLoopProxy> media_loop_proxy =
- GetMediaThreadMessageLoopProxy();
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner =
+ GetMediaThreadTaskRunner();
if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
- if (!gpu_va_context_provider_ ||
+ if (!gpu_va_context_provider_.get() ||
gpu_va_context_provider_->DestroyedOnMainThread()) {
- if (!gpu_channel_host) {
+ if (!gpu_channel_host.get()) {
gpu_channel_host = EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE);
}
@@ -1023,21 +1120,16 @@ RenderThreadImpl::GetGpuFactories() {
"GPU-VideoAccelerator-Offscreen");
}
}
- if (gpu_va_context_provider_) {
+ if (gpu_va_context_provider_.get()) {
gpu_factories = RendererGpuVideoAcceleratorFactories::Create(
- gpu_channel_host, media_loop_proxy, gpu_va_context_provider_);
+ gpu_channel_host.get(), media_task_runner, gpu_va_context_provider_);
}
return gpu_factories;
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
RenderThreadImpl::CreateOffscreenContext3d() {
- blink::WebGraphicsContext3D::Attributes attributes;
- attributes.shareResources = true;
- attributes.depth = false;
- attributes.stencil = false;
- attributes.antialias = false;
- attributes.noAutomaticFlushes = true;
+ blink::WebGraphicsContext3D::Attributes attributes(GetOffscreenAttribs());
bool lose_context_when_out_of_memory = true;
scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
@@ -1055,20 +1147,24 @@ RenderThreadImpl::CreateOffscreenContext3d() {
scoped_refptr<webkit::gpu::ContextProviderWebContext>
RenderThreadImpl::SharedMainThreadContextProvider() {
DCHECK(IsMainThread());
+ if (!shared_main_thread_contexts_.get() ||
+ shared_main_thread_contexts_->DestroyedOnMainThread()) {
+ shared_main_thread_contexts_ = NULL;
#if defined(OS_ANDROID)
- if (SynchronousCompositorFactory* factory =
- SynchronousCompositorFactory::GetInstance())
- return factory->GetSharedOffscreenContextProviderForMainThread();
+ if (SynchronousCompositorFactory* factory =
+ SynchronousCompositorFactory::GetInstance()) {
+ shared_main_thread_contexts_ = factory->CreateOffscreenContextProvider(
+ GetOffscreenAttribs(), "Offscreen-MainThread");
+ }
#endif
-
- if (!shared_main_thread_contexts_ ||
- shared_main_thread_contexts_->DestroyedOnMainThread()) {
- shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
- CreateOffscreenContext3d(), "Offscreen-MainThread");
+ if (!shared_main_thread_contexts_.get()) {
+ shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create(
+ CreateOffscreenContext3d(), "Offscreen-MainThread");
+ }
+ if (shared_main_thread_contexts_.get() &&
+ !shared_main_thread_contexts_->BindToCurrentThread())
+ shared_main_thread_contexts_ = NULL;
}
- if (shared_main_thread_contexts_ &&
- !shared_main_thread_contexts_->BindToCurrentThread())
- shared_main_thread_contexts_ = NULL;
return shared_main_thread_contexts_;
}
@@ -1116,6 +1212,10 @@ void RenderThreadImpl::ReleaseCachedFonts() {
#endif // OS_WIN
+ServiceRegistry* RenderThreadImpl::GetServiceRegistry() {
+ return service_registry();
+}
+
bool RenderThreadImpl::IsMainThread() {
return !!current();
}
@@ -1156,59 +1256,6 @@ CreateCommandBufferResult RenderThreadImpl::CreateViewCommandBuffer(
return result;
}
-void RenderThreadImpl::CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback) {
- NOTREACHED();
-}
-
-void RenderThreadImpl::DeleteImage(int32 image_id, int32 sync_point) {
- NOTREACHED();
-}
-
-scoped_ptr<gfx::GpuMemoryBuffer> RenderThreadImpl::AllocateGpuMemoryBuffer(
- size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage) {
- DCHECK(allocate_gpu_memory_buffer_thread_checker_.CalledOnValidThread());
-
- if (!GpuMemoryBufferImpl::IsFormatValid(internalformat))
- return scoped_ptr<gfx::GpuMemoryBuffer>();
-
- gfx::GpuMemoryBufferHandle handle;
- bool success;
- IPC::Message* message = new ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer(
- width, height, internalformat, usage, &handle);
-
- // Allow calling this from the compositor thread.
- if (base::MessageLoop::current() == message_loop())
- success = ChildThread::Send(message);
- else
- success = sync_message_filter()->Send(message);
-
- if (!success)
- return scoped_ptr<gfx::GpuMemoryBuffer>();
-
- return GpuMemoryBufferImpl::CreateFromHandle(
- handle, gfx::Size(width, height), internalformat)
- .PassAs<gfx::GpuMemoryBuffer>();
-}
-
-void RenderThreadImpl::ConnectToService(
- const mojo::String& service_url,
- const mojo::String& service_name,
- mojo::ScopedMessagePipeHandle message_pipe,
- const mojo::String& requestor_url) {
- // TODO(darin): Invent some kind of registration system to use here.
- if (service_url.To<base::StringPiece>() == kRendererService_WebUISetup) {
- WebUISetupImpl::Bind(message_pipe.Pass());
- } else {
- NOTREACHED() << "Unknown service name";
- }
-}
-
void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
suspend_webkit_shared_timer_ = false;
}
@@ -1217,13 +1264,6 @@ void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() {
notify_webkit_of_modal_loop_ = false;
}
-void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme,
- const std::string& host,
- double zoom_level) {
- RenderViewZoomer zoomer(scheme, host, zoom_level);
- RenderView::ForEach(&zoomer);
-}
-
bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
ObserverListBase<RenderProcessObserver>::Iterator it(observers_);
RenderProcessObserver* observer;
@@ -1241,12 +1281,13 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderThreadImpl, msg)
+ IPC_MESSAGE_HANDLER(FrameMsg_NewFrame, OnCreateNewFrame)
+ IPC_MESSAGE_HANDLER(FrameMsg_NewFrameProxy, OnCreateNewFrameProxy)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentURL,
OnSetZoomLevelForCurrentURL)
// TODO(port): removed from render_messages_internal.h;
// is there a new non-windows message I should add here?
IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
- IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
IPC_MESSAGE_HANDLER(ViewMsg_NetworkTypeChanged, OnNetworkTypeChanged)
IPC_MESSAGE_HANDLER(ViewMsg_TempCrashWithData, OnTempCrashWithData)
IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateNewSharedWorker)
@@ -1258,11 +1299,34 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateScrollbarTheme, OnUpdateScrollbarTheme)
#endif
+#if defined(ENABLE_PLUGINS)
+ IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache, OnPurgePluginListCache)
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+void RenderThreadImpl::OnCreateNewFrame(int routing_id,
+ int parent_routing_id,
+ int proxy_routing_id) {
+ RenderFrameImpl::CreateFrame(routing_id, parent_routing_id, proxy_routing_id);
+}
+
+void RenderThreadImpl::OnCreateNewFrameProxy(int routing_id,
+ int parent_routing_id,
+ int render_view_routing_id) {
+ RenderFrameProxy::CreateFrameProxy(
+ routing_id, parent_routing_id, render_view_routing_id);
+}
+
+void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme,
+ const std::string& host,
+ double zoom_level) {
+ RenderViewZoomer zoomer(scheme, host, zoom_level);
+ RenderView::ForEach(&zoomer);
+}
+
void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) {
EnsureWebKitInitialized();
// When bringing in render_view, also bring in webkit's glue and jsbindings.
@@ -1281,8 +1345,7 @@ void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) {
params.hidden,
params.never_visible,
params.next_page_id,
- params.screen_info,
- params.accessibility_mode);
+ params.screen_info);
}
GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
@@ -1321,9 +1384,12 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
// implementation of GpuChannelHostFactory.
io_message_loop_proxy_ = ChildProcess::current()->io_message_loop_proxy();
- gpu_channel_ = GpuChannelHost::Create(
- this, gpu_info, channel_handle,
- ChildProcess::current()->GetShutDownEvent());
+ gpu_channel_ =
+ GpuChannelHost::Create(this,
+ gpu_info,
+ channel_handle,
+ ChildProcess::current()->GetShutDownEvent(),
+ gpu_memory_buffer_manager());
return gpu_channel_.get();
}
@@ -1342,7 +1408,6 @@ blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
if (!media_stream_center_) {
scoped_ptr<MediaStreamCenter> media_stream_center(
new MediaStreamCenter(client, GetPeerConnectionDependencyFactory()));
- AddObserver(media_stream_center.get());
media_stream_center_ = media_stream_center.release();
}
}
@@ -1350,10 +1415,12 @@ blink::WebMediaStreamCenter* RenderThreadImpl::CreateMediaStreamCenter(
return media_stream_center_;
}
+#if defined(ENABLE_WEBRTC)
PeerConnectionDependencyFactory*
RenderThreadImpl::GetPeerConnectionDependencyFactory() {
return peer_connection_factory_.get();
}
+#endif
GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
if (!gpu_channel_.get())
@@ -1365,18 +1432,20 @@ GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
return gpu_channel_.get();
}
+#if defined(ENABLE_PLUGINS)
void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
EnsureWebKitInitialized();
// The call below will cause a GetPlugins call with refresh=true, but at this
// point we already know that the browser has refreshed its list, so disable
// refresh temporarily to prevent each renderer process causing the list to be
// regenerated.
- webkit_platform_support_->set_plugin_refresh_allowed(false);
+ blink_platform_impl_->set_plugin_refresh_allowed(false);
blink::resetPluginCache(reload_pages);
- webkit_platform_support_->set_plugin_refresh_allowed(true);
+ blink_platform_impl_->set_plugin_refresh_allowed(true);
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, PluginListChanged());
}
+#endif
void RenderThreadImpl::OnNetworkTypeChanged(
net::NetworkChangeNotifier::ConnectionType type) {
@@ -1395,18 +1464,19 @@ void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
}
void RenderThreadImpl::OnUpdateTimezone() {
+ if (!blink_platform_impl_)
+ return;
NotifyTimezoneChange();
}
-
#if defined(OS_ANDROID)
void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) {
if (suspend_webkit_shared_timer_) {
EnsureWebKitInitialized();
if (suspend) {
- webkit_platform_support_->SuspendSharedTimer();
+ blink_platform_impl_->SuspendSharedTimer();
} else {
- webkit_platform_support_->ResumeSharedTimer();
+ blink_platform_impl_->ResumeSharedTimer();
}
webkit_shared_timer_suspended_ = suspend;
}
@@ -1422,8 +1492,8 @@ void RenderThreadImpl::OnUpdateScrollbarTheme(
bool redraw) {
EnsureWebKitInitialized();
static_cast<WebScrollbarBehaviorImpl*>(
- webkit_platform_support_->scrollbarBehavior())->set_jump_on_track_click(
- jump_on_track_click);
+ blink_platform_impl_->scrollbarBehavior())
+ ->set_jump_on_track_click(jump_on_track_click);
blink::WebScrollbarTheme::updateScrollbars(initial_button_delay,
autoscroll_button_delay,
preferred_scroller_style,
@@ -1446,12 +1516,16 @@ void RenderThreadImpl::OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
base::allocator::ReleaseFreeMemory();
- if (memory_pressure_level ==
- base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL) {
- // Trigger full v8 garbage collection on critical memory notification.
- v8::V8::LowMemoryNotification();
+ // Trigger full v8 garbage collection on critical memory notification. This
+ // will potentially hang the renderer for a long time, however, when we
+ // receive a memory pressure notification, we might be about to be killed.
+ if (blink_platform_impl_ && blink::mainThreadIsolate()) {
+ blink::mainThreadIsolate()->LowMemoryNotification();
+ }
- if (webkit_platform_support_) {
+ if (memory_pressure_level ==
+ base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
+ if (blink_platform_impl_) {
// Clear the image cache. Do not call into blink if it is not initialized.
blink::WebImageCache::clear();
}
@@ -1460,10 +1534,6 @@ void RenderThreadImpl::OnMemoryPressure(
// limit.
size_t font_cache_limit = SkGraphics::SetFontCacheLimit(0);
SkGraphics::SetFontCacheLimit(font_cache_limit);
- } else {
- // Otherwise trigger a couple of v8 GCs using IdleNotification.
- if (!v8::V8::IdleNotification())
- v8::V8::IdleNotification();
}
}
@@ -1477,8 +1547,8 @@ RenderThreadImpl::GetFileThreadMessageLoopProxy() {
return file_thread_->message_loop_proxy();
}
-scoped_refptr<base::MessageLoopProxy>
-RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
+scoped_refptr<base::SingleThreadTaskRunner>
+RenderThreadImpl::GetMediaThreadTaskRunner() {
DCHECK(message_loop() == base::MessageLoop::current());
if (!media_thread_) {
media_thread_.reset(new base::Thread("Media"));
@@ -1492,20 +1562,8 @@ RenderThreadImpl::GetMediaThreadMessageLoopProxy() {
return media_thread_->message_loop_proxy();
}
-void RenderThreadImpl::SetFlingCurveParameters(
- const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen) {
- webkit_platform_support_->SetFlingCurveParameters(new_touchpad,
- new_touchscreen);
-
-}
-
void RenderThreadImpl::SampleGamepads(blink::WebGamepads* data) {
- gamepad_shared_memory_reader_->SampleGamepads(*data);
-}
-
-void RenderThreadImpl::SetGamepadListener(blink::WebGamepadListener* listener) {
- gamepad_shared_memory_reader_->SetGamepadListener(listener);
+ blink_platform_impl_->sampleGamepads(*data);
}
void RenderThreadImpl::WidgetCreated() {
@@ -1521,12 +1579,12 @@ void RenderThreadImpl::WidgetHidden() {
hidden_widget_count_++;
if (widget_count_ && hidden_widget_count_ == widget_count_) {
-#if !defined(SYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE)
- // TODO(vollick): Remove this this heavy-handed approach once we're polling
- // the real system memory pressure.
- base::MemoryPressureListener::NotifyMemoryPressure(
- base::MemoryPressureListener::MEMORY_PRESSURE_MODERATE);
-#endif
+ // TODO(reveman): Remove this when we have a better mechanism to prevent
+ // total discardable memory used by all renderers from growing too large.
+ base::internal::DiscardableMemoryEmulated::
+ ReduceMemoryUsageUntilWithinLimit(
+ kEmulatedDiscardableMemoryBytesToKeepWhenWidgetsHidden);
+
if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
ScheduleIdleHandler(kInitialIdleHandlerDelayMs);
}
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index f725af5a190..831c9822220 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -36,7 +36,6 @@ struct WorkerProcessMsg_CreateWorker_Params;
namespace blink {
class WebGamepads;
-class WebGamepadListener;
class WebGraphicsContext3D;
class WebMediaStreamCenter;
class WebMediaStreamCenterClient;
@@ -44,6 +43,7 @@ class WebMediaStreamCenterClient;
namespace base {
class MessageLoopProxy;
+class SingleThreadTaskRunner;
class Thread;
}
@@ -84,20 +84,21 @@ class DBMessageFilter;
class DevToolsAgentFilter;
class DomStorageDispatcher;
class EmbeddedWorkerDispatcher;
-class GamepadSharedMemoryReader;
class GpuChannelHost;
class IndexedDBDispatcher;
class InputEventFilter;
class InputHandlerManager;
class MediaStreamCenter;
+class MemoryObserver;
class PeerConnectionDependencyFactory;
class MidiMessageFilter;
class NetInfoDispatcher;
class P2PSocketDispatcher;
class PeerConnectionTracker;
-class RendererDemuxerAndroid;
-class RendererWebKitPlatformSupportImpl;
class RenderProcessObserver;
+class RendererBlinkPlatformImpl;
+class RendererDemuxerAndroid;
+class RendererScheduler;
class VideoCaptureImplManager;
class WebGraphicsContext3DCommandBufferImpl;
class WebRTCIdentityService;
@@ -120,8 +121,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
RenderThreadImpl();
// Constructor that's used when running in single process mode.
explicit RenderThreadImpl(const std::string& channel_name);
- virtual ~RenderThreadImpl();
- virtual void Shutdown() OVERRIDE;
+ ~RenderThreadImpl() override;
+ void Shutdown() override;
// When initializing WebKit, ensure that any schemes needed for the content
// module are registered properly. Static to allow sharing with tests.
@@ -132,41 +133,41 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
static void NotifyTimezoneChange();
// RenderThread implementation:
- virtual bool Send(IPC::Message* msg) OVERRIDE;
- virtual base::MessageLoop* GetMessageLoop() OVERRIDE;
- virtual IPC::SyncChannel* GetChannel() OVERRIDE;
- virtual std::string GetLocale() OVERRIDE;
- virtual IPC::SyncMessageFilter* GetSyncMessageFilter() OVERRIDE;
- virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy()
- OVERRIDE;
- virtual void AddRoute(int32 routing_id, IPC::Listener* listener) OVERRIDE;
- virtual void RemoveRoute(int32 routing_id) OVERRIDE;
- virtual int GenerateRoutingID() OVERRIDE;
- virtual void AddFilter(IPC::MessageFilter* filter) OVERRIDE;
- virtual void RemoveFilter(IPC::MessageFilter* filter) OVERRIDE;
- virtual void AddObserver(RenderProcessObserver* observer) OVERRIDE;
- virtual void RemoveObserver(RenderProcessObserver* observer) OVERRIDE;
- virtual void SetResourceDispatcherDelegate(
- ResourceDispatcherDelegate* delegate) OVERRIDE;
- virtual void EnsureWebKitInitialized() OVERRIDE;
- virtual void RecordAction(const base::UserMetricsAction& action) OVERRIDE;
- virtual void RecordComputedAction(const std::string& action) OVERRIDE;
- virtual scoped_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
- size_t buffer_size) OVERRIDE;
- virtual void RegisterExtension(v8::Extension* extension) OVERRIDE;
- virtual void ScheduleIdleHandler(int64 initial_delay_ms) OVERRIDE;
- virtual void IdleHandler() OVERRIDE;
- virtual int64 GetIdleNotificationDelayInMs() const OVERRIDE;
- virtual void SetIdleNotificationDelayInMs(
- int64 idle_notification_delay_in_ms) OVERRIDE;
- virtual void UpdateHistograms(int sequence_number) OVERRIDE;
- virtual int PostTaskToAllWebWorkers(const base::Closure& closure) OVERRIDE;
- virtual bool ResolveProxy(const GURL& url, std::string* proxy_list) OVERRIDE;
- virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+ base::MessageLoop* GetMessageLoop() override;
+ IPC::SyncChannel* GetChannel() override;
+ std::string GetLocale() override;
+ IPC::SyncMessageFilter* GetSyncMessageFilter() override;
+ scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() override;
+ void AddRoute(int32 routing_id, IPC::Listener* listener) override;
+ void RemoveRoute(int32 routing_id) override;
+ int GenerateRoutingID() override;
+ void AddFilter(IPC::MessageFilter* filter) override;
+ void RemoveFilter(IPC::MessageFilter* filter) override;
+ void AddObserver(RenderProcessObserver* observer) override;
+ void RemoveObserver(RenderProcessObserver* observer) override;
+ void SetResourceDispatcherDelegate(
+ ResourceDispatcherDelegate* delegate) override;
+ void EnsureWebKitInitialized() override;
+ void RecordAction(const base::UserMetricsAction& action) override;
+ void RecordComputedAction(const std::string& action) override;
+ scoped_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
+ size_t buffer_size) override;
+ void RegisterExtension(v8::Extension* extension) override;
+ void ScheduleIdleHandler(int64 initial_delay_ms) override;
+ void IdleHandler() override;
+ int64 GetIdleNotificationDelayInMs() const override;
+ void SetIdleNotificationDelayInMs(
+ int64 idle_notification_delay_in_ms) override;
+ void UpdateHistograms(int sequence_number) override;
+ int PostTaskToAllWebWorkers(const base::Closure& closure) override;
+ bool ResolveProxy(const GURL& url, std::string* proxy_list) override;
+ base::WaitableEvent* GetShutdownEvent() override;
#if defined(OS_WIN)
- virtual void PreCacheFont(const LOGFONT& log_font) OVERRIDE;
- virtual void ReleaseCachedFonts() OVERRIDE;
+ virtual void PreCacheFont(const LOGFONT& log_font) override;
+ virtual void ReleaseCachedFonts() override;
#endif
+ ServiceRegistry* GetServiceRegistry() override;
// Synchronously establish a channel to the GPU plugin if not previously
// established or if it has been lost (for example if the GPU plugin crashed).
@@ -193,9 +194,19 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
layout_test_mode_ = layout_test_mode;
}
- RendererWebKitPlatformSupportImpl* webkit_platform_support() const {
- DCHECK(webkit_platform_support_);
- return webkit_platform_support_.get();
+ RendererScheduler* renderer_scheduler() const {
+ DCHECK(renderer_scheduler_);
+ return renderer_scheduler_.get();
+ }
+
+ RendererBlinkPlatformImpl* blink_platform_impl() const {
+ DCHECK(blink_platform_impl_);
+ return blink_platform_impl_.get();
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner>
+ main_thread_compositor_task_runner() const {
+ return main_thread_compositor_task_runner_;
}
IPC::ForwardingMessageFilter* compositor_output_surface_filter() const {
@@ -223,8 +234,6 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
return is_impl_side_painting_enabled_;
}
- bool is_low_res_tiling_enabled() const { return is_low_res_tiling_enabled_; }
-
bool is_lcd_text_enabled() const { return is_lcd_text_enabled_; }
bool is_distance_field_text_enabled() const {
@@ -270,6 +279,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
blink::WebMediaStreamCenter* CreateMediaStreamCenter(
blink::WebMediaStreamCenterClient* client);
+#if defined(ENABLE_WEBRTC)
// Returns a factory used for creating RTC PeerConnection objects.
PeerConnectionDependencyFactory* GetPeerConnectionDependencyFactory();
@@ -281,15 +291,12 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
P2PSocketDispatcher* p2p_socket_dispatcher() {
return p2p_socket_dispatcher_.get();
}
+#endif
VideoCaptureImplManager* video_capture_impl_manager() const {
return vc_manager_.get();
}
- GamepadSharedMemoryReader* gamepad_shared_memory_reader() const {
- return gamepad_shared_memory_reader_.get();
- }
-
// Get the GPU channel. Returns NULL if the channel is not established or
// has been lost.
GpuChannelHost* GetGpuChannel();
@@ -299,10 +306,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// on the renderer's main thread.
scoped_refptr<base::MessageLoopProxy> GetFileThreadMessageLoopProxy();
- // Returns a MessageLoopProxy instance corresponding to the message loop
+ // Returns a SingleThreadTaskRunner instance corresponding to the message loop
// of the thread on which media operations should be run. Must be called
// on the renderer's main thread.
- scoped_refptr<base::MessageLoopProxy> GetMediaThreadMessageLoopProxy();
+ scoped_refptr<base::SingleThreadTaskRunner> GetMediaThreadTaskRunner();
// Causes the idle handler to skip sending idle notifications
// on the two next scheduled calls, so idle notifications are
@@ -381,16 +388,9 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
return &histogram_customizer_;
}
- void SetFlingCurveParameters(const std::vector<float>& new_touchpad,
- const std::vector<float>& new_touchscreen);
-
// Retrieve current gamepad data.
void SampleGamepads(blink::WebGamepads* data);
- // Set a listener for gamepad connected/disconnected events.
- // A non-null listener must be set first before calling SampleGamepads.
- void SetGamepadListener(blink::WebGamepadListener* listener);
-
// Called by a RenderWidget when it is created or destroyed. This
// allows the process to know when there are no visible widgets.
void WidgetCreated();
@@ -401,46 +401,39 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
void AddEmbeddedWorkerRoute(int32 routing_id, IPC::Listener* listener);
void RemoveEmbeddedWorkerRoute(int32 routing_id);
+ void RegisterPendingRenderFrameConnect(int routing_id,
+ mojo::ScopedMessagePipeHandle handle);
+
private:
// ChildThread
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& msg) override;
// GpuChannelHostFactory implementation:
- virtual bool IsMainThread() OVERRIDE;
- virtual base::MessageLoop* GetMainLoop() OVERRIDE;
- virtual scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() OVERRIDE;
- virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(
- size_t size) OVERRIDE;
- virtual CreateCommandBufferResult CreateViewCommandBuffer(
+ bool IsMainThread() override;
+ base::MessageLoop* GetMainLoop() override;
+ scoped_refptr<base::MessageLoopProxy> GetIOLoopProxy() override;
+ scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) override;
+ CreateCommandBufferResult CreateViewCommandBuffer(
int32 surface_id,
const GPUCreateCommandBufferConfig& init_params,
- int32 route_id) OVERRIDE;
- virtual void CreateImage(
- gfx::PluginWindowHandle window,
- int32 image_id,
- const CreateImageCallback& callback) OVERRIDE;
- virtual void DeleteImage(int32 image_id, int32 sync_point) OVERRIDE;
- virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
- size_t width,
- size_t height,
- unsigned internalformat,
- unsigned usage) OVERRIDE;
-
- // mojo::ServiceProvider implementation:
- virtual void ConnectToService(
- const mojo::String& service_url,
- const mojo::String& service_name,
- mojo::ScopedMessagePipeHandle message_pipe,
- const mojo::String& requestor_url) OVERRIDE;
+ int32 route_id) override;
void Init();
+ void OnCreateNewFrame(int routing_id,
+ int parent_routing_id,
+ int proxy_routing_id);
+ void OnCreateNewFrameProxy(int routing_id,
+ int parent_routing_id,
+ int render_view_routing_id);
void OnSetZoomLevelForCurrentURL(const std::string& scheme,
const std::string& host,
double zoom_level);
void OnCreateNewView(const ViewMsg_New_Params& params);
void OnTransferBitmap(const SkBitmap& bitmap, int resource_id);
+#if defined(ENABLE_PLUGINS)
void OnPurgePluginListCache(bool reload_pages);
+#endif
void OnNetworkTypeChanged(net::NetworkChangeNotifier::ConnectionType type);
void OnGetAccessibilityTree();
void OnTempCrashWithData(const GURL& data);
@@ -460,15 +453,14 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
void OnCreateNewSharedWorker(
const WorkerProcessMsg_CreateWorker_Params& params);
- void IdleHandlerInForegroundTab();
-
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateOffscreenContext3d();
// These objects live solely on the render thread.
scoped_ptr<AppCacheDispatcher> appcache_dispatcher_;
scoped_ptr<DomStorageDispatcher> dom_storage_dispatcher_;
scoped_ptr<IndexedDBDispatcher> main_thread_indexed_db_dispatcher_;
- scoped_ptr<RendererWebKitPlatformSupportImpl> webkit_platform_support_;
+ scoped_ptr<RendererScheduler> renderer_scheduler_;
+ scoped_ptr<RendererBlinkPlatformImpl> blink_platform_impl_;
scoped_ptr<EmbeddedWorkerDispatcher> embedded_worker_dispatcher_;
// Used on the render thread and deleted by WebKit at shutdown.
@@ -484,6 +476,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
#endif
scoped_refptr<DevToolsAgentFilter> devtools_agent_message_filter_;
+#if defined(ENABLE_WEBRTC)
scoped_ptr<PeerConnectionDependencyFactory> peer_connection_factory_;
// This is used to communicate to the browser process the status
@@ -492,6 +485,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
// Dispatches all P2P sockets.
scoped_refptr<P2PSocketDispatcher> p2p_socket_dispatcher_;
+#endif
// Used on the render thread.
scoped_ptr<VideoCaptureImplManager> vc_manager_;
@@ -549,7 +543,8 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_ptr<InputHandlerManager> input_handler_manager_;
scoped_refptr<IPC::ForwardingMessageFilter> compositor_output_surface_filter_;
- scoped_refptr<ContextProviderCommandBuffer> shared_main_thread_contexts_;
+ scoped_refptr<webkit::gpu::ContextProviderWebContext>
+ shared_main_thread_contexts_;
ObserverList<RenderProcessObserver> observers_;
@@ -562,25 +557,26 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread,
scoped_ptr<base::MemoryPressureListener> memory_pressure_listener_;
+#if defined(ENABLE_WEBRTC)
scoped_ptr<WebRTCIdentityService> webrtc_identity_service_;
+#endif
- scoped_ptr<GamepadSharedMemoryReader> gamepad_shared_memory_reader_;
+ scoped_ptr<MemoryObserver> memory_observer_;
- // TODO(reveman): Allow AllocateGpuMemoryBuffer to be called from
- // multiple threads. Current allocation mechanism for IOSurface
- // backed GpuMemoryBuffers prevent this. crbug.com/325045
- base::ThreadChecker allocate_gpu_memory_buffer_thread_checker_;
+ scoped_refptr<base::SingleThreadTaskRunner>
+ main_thread_compositor_task_runner_;
// Compositor settings
bool is_gpu_rasterization_enabled_;
bool is_gpu_rasterization_forced_;
bool is_impl_side_painting_enabled_;
- bool is_low_res_tiling_enabled_;
bool is_lcd_text_enabled_;
bool is_distance_field_text_enabled_;
bool is_zero_copy_enabled_;
bool is_one_copy_enabled_;
+ std::map<int, mojo::MessagePipeHandle> pending_render_frame_connects_;
+
DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl);
};
diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc
index 11d486ee2ce..e98822e222c 100644
--- a/chromium/content/renderer/render_thread_impl_browsertest.cc
+++ b/chromium/content/renderer/render_thread_impl_browsertest.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "base/command_line.h"
+#include "base/memory/discardable_memory.h"
+#include "base/memory/scoped_vector.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
@@ -17,14 +19,12 @@ namespace {
class RenderThreadImplBrowserTest : public testing::Test {
public:
- virtual ~RenderThreadImplBrowserTest() {}
+ ~RenderThreadImplBrowserTest() override {}
};
class DummyListener : public IPC::Listener {
public:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
- return true;
- }
+ bool OnMessageReceived(const IPC::Message& message) override { return true; }
};
void CheckRenderThreadInputHandlerManager(RenderThreadImpl* thread) {
@@ -43,9 +43,6 @@ void CheckRenderThreadInputHandlerManager(RenderThreadImpl* thread) {
#endif
TEST_F(RenderThreadImplBrowserTest,
MAYBE_InputHandlerManagerDestroyedAfterCompositorThread) {
- CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableThreadedCompositing);
-
ContentClient content_client;
ContentBrowserClient content_browser_client;
ContentRendererClient content_renderer_client;
@@ -73,5 +70,63 @@ TEST_F(RenderThreadImplBrowserTest,
base::Bind(&CheckRenderThreadInputHandlerManager, thread));
}
+// Checks that emulated discardable memory is discarded when the last widget
+// is hidden.
+// Disabled under LeakSanitizer due to memory leaks.
+#if defined(LEAK_SANITIZER)
+#define MAYBE_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden \
+ DISABLED_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden
+#else
+#define MAYBE_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden \
+ EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden
+#endif
+TEST_F(RenderThreadImplBrowserTest,
+ MAYBE_EmulatedDiscardableMemoryDiscardedWhenWidgetsHidden) {
+ ContentClient content_client;
+ ContentBrowserClient content_browser_client;
+ ContentRendererClient content_renderer_client;
+ SetContentClient(&content_client);
+ SetBrowserClientForTesting(&content_browser_client);
+ SetRendererClientForTesting(&content_renderer_client);
+ base::MessageLoopForIO message_loop_;
+
+ std::string channel_id =
+ IPC::Channel::GenerateVerifiedChannelID(std::string());
+ DummyListener dummy_listener;
+ scoped_ptr<IPC::Channel> channel(
+ IPC::Channel::CreateServer(channel_id, &dummy_listener));
+ ASSERT_TRUE(channel->Connect());
+
+ scoped_ptr<MockRenderProcess> mock_process(new MockRenderProcess);
+ // Owned by mock_process.
+ RenderThreadImpl* thread = new RenderThreadImpl(channel_id);
+ thread->EnsureWebKitInitialized();
+ thread->WidgetCreated();
+
+ // Allocate 128MB of discardable memory.
+ ScopedVector<base::DiscardableMemory> discardable_memory;
+ for (int i = 0; i < 32; ++i) {
+ discardable_memory.push_back(
+ base::DiscardableMemory::CreateLockedMemoryWithType(
+ base::DISCARDABLE_MEMORY_TYPE_EMULATED, 4 * 1024 * 1024).release());
+ ASSERT_TRUE(discardable_memory.back());
+ discardable_memory.back()->Unlock();
+ }
+
+ // Hide all widgets.
+ thread->WidgetHidden();
+
+ // Count how much memory is left, should be at most one block.
+ int blocks_left = 0;
+ for (auto iter = discardable_memory.begin(); iter != discardable_memory.end();
+ ++iter) {
+ if ((*iter)->Lock() == base::DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS)
+ ++blocks_left;
+ }
+ EXPECT_LE(blocks_left, 1);
+
+ thread->WidgetDestroyed();
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/renderer/render_thread_impl_unittest.cc b/chromium/content/renderer/render_thread_impl_unittest.cc
index 89cafc16b7a..659eba4410e 100644
--- a/chromium/content/renderer/render_thread_impl_unittest.cc
+++ b/chromium/content/renderer/render_thread_impl_unittest.cc
@@ -14,9 +14,10 @@ class RenderThreadImplUnittest : public testing::Test {
RenderThreadImplUnittest()
: kCustomizableHistogram_("Histogram1"),
kNormalHistogram_("Histogram2") {}
- virtual ~RenderThreadImplUnittest() {}
+ ~RenderThreadImplUnittest() override {}
+
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
histogram_customizer_.custom_histograms_.clear();
histogram_customizer_.custom_histograms_.insert(kCustomizableHistogram_);
}
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index 2fc0a9cdb98..7dc2da83b50 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/memory/shared_memory.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "base/win/windows_version.h"
#include "content/child/request_extra_data.h"
#include "content/child/service_worker/service_worker_network_provider.h"
@@ -25,17 +26,16 @@
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/navigation_state.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/frame_load_waiter.h"
#include "content/public/test/render_view_test.h"
#include "content/public/test/test_utils.h"
#include "content/renderer/accessibility/renderer_accessibility.h"
-#include "content/renderer/accessibility/renderer_accessibility_complete.h"
-#include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
#include "content/renderer/history_controller.h"
#include "content/renderer/history_serialization.h"
+#include "content/renderer/render_process.h"
#include "content/renderer/render_view_impl.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
-#include "content/test/frame_load_waiter.h"
#include "content/test/mock_keyboard.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.h"
@@ -48,6 +48,7 @@
#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebPerformance.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
@@ -63,6 +64,7 @@
#include <X11/Xlib.h>
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/test/events_test_utils.h"
#include "ui/events/test/events_test_utils_x11.h"
#endif
@@ -100,7 +102,7 @@ int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) {
{ MockKeyboard::RIGHT_ALT, ui::EF_ALT_DOWN },
};
int flags = 0;
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kModifierMap); ++i) {
+ for (size_t i = 0; i < arraysize(kModifierMap); ++i) {
if (kModifierMap[i].src & modifiers) {
flags |= kModifierMap[i].dst;
}
@@ -111,24 +113,26 @@ int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) {
class WebUITestWebUIControllerFactory : public WebUIControllerFactory {
public:
- virtual WebUIController* CreateWebUIControllerForURL(
- WebUI* web_ui, const GURL& url) const OVERRIDE {
+ WebUIController* CreateWebUIControllerForURL(WebUI* web_ui,
+ const GURL& url) const override {
return NULL;
}
- virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+ const GURL& url) const override {
return WebUI::kNoWebUI;
}
- virtual bool UseWebUIForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return HasWebUIScheme(url);
}
- virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
- const GURL& url) const OVERRIDE {
+ bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+ const GURL& url) const override {
return HasWebUIScheme(url);
}
};
+} // namespace
+
class RenderViewImplTest : public RenderViewTest {
public:
RenderViewImplTest() {
@@ -136,9 +140,9 @@ class RenderViewImplTest : public RenderViewTest {
mock_keyboard_.reset(new MockKeyboard());
}
- virtual ~RenderViewImplTest() {}
+ ~RenderViewImplTest() override {}
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
RenderViewTest::SetUp();
// Enable Blink's experimental and test only features so that test code
// does not have to bother enabling each feature.
@@ -150,6 +154,10 @@ class RenderViewImplTest : public RenderViewTest {
return static_cast<RenderViewImpl*>(view_);
}
+ int view_page_id() {
+ return view()->page_id_;
+ }
+
RenderFrameImpl* frame() {
return static_cast<RenderFrameImpl*>(view()->GetMainRenderFrame());
}
@@ -180,7 +188,7 @@ class RenderViewImplTest : public RenderViewTest {
// WM_CHAR sends a composed Unicode character.
MSG msg1 = { NULL, WM_KEYDOWN, key_code, 0 };
#if defined(USE_AURA)
- ui::KeyEvent evt1(msg1, false);
+ ui::KeyEvent evt1(msg1);
NativeWebKeyboardEvent keydown_event(&evt1);
#else
NativeWebKeyboardEvent keydown_event(msg1);
@@ -189,7 +197,7 @@ class RenderViewImplTest : public RenderViewTest {
MSG msg2 = { NULL, WM_CHAR, (*output)[0], 0 };
#if defined(USE_AURA)
- ui::KeyEvent evt2(msg2, true);
+ ui::KeyEvent evt2(msg2);
NativeWebKeyboardEvent char_event(&evt2);
#else
NativeWebKeyboardEvent char_event(msg2);
@@ -198,7 +206,7 @@ class RenderViewImplTest : public RenderViewTest {
MSG msg3 = { NULL, WM_KEYUP, key_code, 0 };
#if defined(USE_AURA)
- ui::KeyEvent evt3(msg3, false);
+ ui::KeyEvent evt3(msg3);
NativeWebKeyboardEvent keyup_event(&evt3);
#else
NativeWebKeyboardEvent keyup_event(msg3);
@@ -216,21 +224,27 @@ class RenderViewImplTest : public RenderViewTest {
xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
static_cast<ui::KeyboardCode>(key_code),
flags);
- ui::KeyEvent event1(xevent, false);
+ ui::KeyEvent event1(xevent);
NativeWebKeyboardEvent keydown_event(&event1);
SendNativeKeyEvent(keydown_event);
+ // X11 doesn't actually have native character events, but give the test
+ // what it wants.
xevent.InitKeyEvent(ui::ET_KEY_PRESSED,
static_cast<ui::KeyboardCode>(key_code),
flags);
- ui::KeyEvent event2(xevent, true);
+ ui::KeyEvent event2(xevent);
+ event2.set_character(GetCharacterFromKeyCode(event2.key_code(),
+ event2.flags()));
+ ui::KeyEventTestApi test_event2(&event2);
+ test_event2.set_is_char(true);
NativeWebKeyboardEvent char_event(&event2);
SendNativeKeyEvent(char_event);
xevent.InitKeyEvent(ui::ET_KEY_RELEASED,
static_cast<ui::KeyboardCode>(key_code),
flags);
- ui::KeyEvent event3(xevent, false);
+ ui::KeyEvent event3(xevent);
NativeWebKeyboardEvent keyup_event(&event3);
SendNativeKeyEvent(keyup_event);
@@ -241,29 +255,21 @@ class RenderViewImplTest : public RenderViewTest {
#elif defined(USE_OZONE)
const int flags = ConvertMockKeyboardModifier(modifiers);
- // Ozone's native events are ui::Events. So first create the "native" event,
- // then create the actual ui::KeyEvent with the native event.
- ui::KeyEvent keydown_native_event(ui::ET_KEY_PRESSED,
- static_cast<ui::KeyboardCode>(key_code),
- flags,
- true);
- ui::KeyEvent keydown_event(&keydown_native_event, false);
+ ui::KeyEvent keydown_event(ui::ET_KEY_PRESSED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags);
NativeWebKeyboardEvent keydown_web_event(&keydown_event);
SendNativeKeyEvent(keydown_web_event);
- ui::KeyEvent char_native_event(ui::ET_KEY_PRESSED,
- static_cast<ui::KeyboardCode>(key_code),
- flags,
- true);
- ui::KeyEvent char_event(&char_native_event, true);
+ ui::KeyEvent char_event(keydown_event.GetCharacter(),
+ static_cast<ui::KeyboardCode>(key_code),
+ flags);
NativeWebKeyboardEvent char_web_event(&char_event);
SendNativeKeyEvent(char_web_event);
- ui::KeyEvent keyup_native_event(ui::ET_KEY_RELEASED,
- static_cast<ui::KeyboardCode>(key_code),
- flags,
- true);
- ui::KeyEvent keyup_event(&keyup_native_event, false);
+ ui::KeyEvent keyup_event(ui::ET_KEY_RELEASED,
+ static_cast<ui::KeyboardCode>(key_code),
+ flags);
NativeWebKeyboardEvent keyup_web_event(&keyup_event);
SendNativeKeyEvent(keyup_web_event);
@@ -281,7 +287,53 @@ class RenderViewImplTest : public RenderViewTest {
scoped_ptr<MockKeyboard> mock_keyboard_;
};
-} // namespace
+TEST_F(RenderViewImplTest, SaveImageFromDataURL) {
+ const IPC::Message* msg1 = render_thread_->sink().GetFirstMessageMatching(
+ ViewHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_FALSE(msg1);
+ render_thread_->sink().ClearMessages();
+
+ const std::string image_data_url =
+ "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
+
+ view()->saveImageFromDataURL(WebString::fromUTF8(image_data_url));
+ ProcessPendingMessages();
+ const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching(
+ ViewHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_TRUE(msg2);
+
+ ViewHostMsg_SaveImageFromDataURL::Param param1;
+ ViewHostMsg_SaveImageFromDataURL::Read(msg2, &param1);
+ EXPECT_EQ(param1.b.length(), image_data_url.length());
+ EXPECT_EQ(param1.b, image_data_url);
+
+ ProcessPendingMessages();
+ render_thread_->sink().ClearMessages();
+
+ const std::string large_data_url(1024 * 1024 * 10 - 1, 'd');
+
+ view()->saveImageFromDataURL(WebString::fromUTF8(large_data_url));
+ ProcessPendingMessages();
+ const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching(
+ ViewHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_TRUE(msg3);
+
+ ViewHostMsg_SaveImageFromDataURL::Param param2;
+ ViewHostMsg_SaveImageFromDataURL::Read(msg3, &param2);
+ EXPECT_EQ(param2.b.length(), large_data_url.length());
+ EXPECT_EQ(param2.b, large_data_url);
+
+ ProcessPendingMessages();
+ render_thread_->sink().ClearMessages();
+
+ const std::string exceeded_data_url(1024 * 1024 * 10 + 1, 'd');
+
+ view()->saveImageFromDataURL(WebString::fromUTF8(exceeded_data_url));
+ ProcessPendingMessages();
+ const IPC::Message* msg4 = render_thread_->sink().GetFirstMessageMatching(
+ ViewHostMsg_SaveImageFromDataURL::ID);
+ EXPECT_FALSE(msg4);
+}
// Test that we get form state change notifications when input fields change.
TEST_F(RenderViewImplTest, DISABLED_OnNavStateChanged) {
@@ -309,18 +361,20 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
FrameMsg_Navigate_Params nav_params;
// An http url will trigger a resource load so cannot be used here.
- nav_params.url = GURL("data:text/html,<div>Page</div>");
- nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- nav_params.transition = PAGE_TRANSITION_TYPED;
+ nav_params.common_params.url = GURL("data:text/html,<div>Page</div>");
+ nav_params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ nav_params.common_params.transition = ui::PAGE_TRANSITION_TYPED;
nav_params.page_id = -1;
- nav_params.is_post = true;
+ nav_params.request_params.is_post = true;
+ nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
// Set up post data.
const unsigned char* raw_data = reinterpret_cast<const unsigned char*>(
"post \0\ndata");
const unsigned int length = 11;
const std::vector<unsigned char> post_data(raw_data, raw_data + length);
- nav_params.browser_initiated_post_data = post_data;
+ nav_params.request_params.browser_initiated_post_data = post_data;
frame()->OnNavigate(nav_params);
ProcessPendingMessages();
@@ -357,36 +411,34 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
// Navigations to normal HTTP URLs can be handled locally.
blink::WebURLRequest request(GURL("http://foo.com"));
+ blink::WebFrameClient::NavigationPolicyInfo policy_info(request);
+ policy_info.frame = GetMainFrame();
+ policy_info.extraData = &state;
+ policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
+ policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
blink::WebNavigationPolicy policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- request,
- blink::WebNavigationTypeLinkClicked,
- blink::WebNavigationPolicyCurrentTab,
- false);
+ policy_info);
EXPECT_EQ(blink::WebNavigationPolicyCurrentTab, policy);
// Verify that form posts to WebUI URLs will be sent to the browser process.
blink::WebURLRequest form_request(GURL("chrome://foo"));
+ blink::WebFrameClient::NavigationPolicyInfo form_policy_info(form_request);
+ form_policy_info.frame = GetMainFrame();
+ form_policy_info.extraData = &state;
+ form_policy_info.navigationType = blink::WebNavigationTypeFormSubmitted;
+ form_policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
form_request.setHTTPMethod("POST");
- policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- form_request,
- blink::WebNavigationTypeFormSubmitted,
- blink::WebNavigationPolicyCurrentTab,
- false);
+ policy = frame()->decidePolicyForNavigation(form_policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Verify that popup links to WebUI URLs also are sent to browser.
blink::WebURLRequest popup_request(GURL("chrome://foo"));
- policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- popup_request,
- blink::WebNavigationTypeLinkClicked,
- blink::WebNavigationPolicyNewForegroundTab,
- false);
+ blink::WebFrameClient::NavigationPolicyInfo popup_policy_info(popup_request);
+ popup_policy_info.frame = GetMainFrame();
+ popup_policy_info.extraData = &state;
+ popup_policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
+ popup_policy_info.defaultPolicy = blink::WebNavigationPolicyNewForegroundTab;
+ policy = frame()->decidePolicyForNavigation(popup_policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
}
@@ -408,14 +460,16 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyHandlesAllTopLevel) {
};
blink::WebURLRequest request(GURL("http://foo.com"));
+ blink::WebFrameClient::NavigationPolicyInfo policy_info(request);
+ policy_info.frame = GetMainFrame();
+ policy_info.extraData = &state;
+ policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
+
for (size_t i = 0; i < arraysize(kNavTypes); ++i) {
+ policy_info.navigationType = kNavTypes[i];
+
blink::WebNavigationPolicy policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- request,
- kNavTypes[i],
- blink::WebNavigationPolicyCurrentTab,
- false);
+ policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
}
}
@@ -429,36 +483,35 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
// Navigations to normal HTTP URLs will be sent to browser process.
blink::WebURLRequest request(GURL("http://foo.com"));
+ blink::WebFrameClient::NavigationPolicyInfo policy_info(request);
+ policy_info.frame = GetMainFrame();
+ policy_info.extraData = &state;
+ policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
+ policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
+
blink::WebNavigationPolicy policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- request,
- blink::WebNavigationTypeLinkClicked,
- blink::WebNavigationPolicyCurrentTab,
- false);
+ policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Navigations to WebUI URLs will also be sent to browser process.
blink::WebURLRequest webui_request(GURL("chrome://foo"));
- policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- webui_request,
- blink::WebNavigationTypeLinkClicked,
- blink::WebNavigationPolicyCurrentTab,
- false);
+ blink::WebFrameClient::NavigationPolicyInfo webui_policy_info(webui_request);
+ webui_policy_info.frame = GetMainFrame();
+ webui_policy_info.extraData = &state;
+ webui_policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
+ webui_policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
+ policy = frame()->decidePolicyForNavigation(webui_policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Verify that form posts to data URLs will be sent to the browser process.
blink::WebURLRequest data_request(GURL("data:text/html,foo"));
+ blink::WebFrameClient::NavigationPolicyInfo data_policy_info(data_request);
+ data_policy_info.frame = GetMainFrame();
+ data_policy_info.extraData = &state;
+ data_policy_info.navigationType = blink::WebNavigationTypeFormSubmitted;
+ data_policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
data_request.setHTTPMethod("POST");
- policy = frame()->decidePolicyForNavigation(
- GetMainFrame(),
- &state,
- data_request,
- blink::WebNavigationTypeFormSubmitted,
- blink::WebNavigationPolicyCurrentTab,
- false);
+ policy = frame()->decidePolicyForNavigation(data_policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Verify that a popup that creates a view first and then navigates to a
@@ -469,14 +522,13 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
GetMainFrame(), popup_request, blink::WebWindowFeatures(), "foo",
blink::WebNavigationPolicyNewForegroundTab, false);
RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view);
+ blink::WebFrameClient::NavigationPolicyInfo popup_policy_info(popup_request);
+ popup_policy_info.frame = new_web_view->mainFrame()->toWebLocalFrame();
+ popup_policy_info.extraData = &state;
+ popup_policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
+ popup_policy_info.defaultPolicy = blink::WebNavigationPolicyNewForegroundTab;
policy = static_cast<RenderFrameImpl*>(new_view->GetMainRenderFrame())->
- decidePolicyForNavigation(
- new_web_view->mainFrame()->toWebLocalFrame(),
- &state,
- popup_request,
- blink::WebNavigationTypeLinkClicked,
- blink::WebNavigationPolicyNewForegroundTab,
- false);
+ decidePolicyForNavigation(popup_policy_info);
EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
// Clean up after the new view so we don't leak it.
@@ -488,13 +540,16 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
// already swapped out. http://crbug.com/93427.
TEST_F(RenderViewImplTest, SendSwapOutACK) {
LoadHTML("<div>Page A</div>");
- int initial_page_id = view()->GetPageId();
+ int initial_page_id = view_page_id();
+
+ // Increment the ref count so that we don't exit when swapping out.
+ RenderProcess::current()->AddRefProcess();
// Respond to a swap out request.
- view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
+ view()->GetMainRenderFrame()->OnSwapOut(kProxyRoutingId);
// Ensure the swap out commits synchronously.
- EXPECT_NE(initial_page_id, view()->GetPageId());
+ EXPECT_NE(initial_page_id, view_page_id());
// Check for a valid OnSwapOutACK.
const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
@@ -504,7 +559,7 @@ TEST_F(RenderViewImplTest, SendSwapOutACK) {
// It is possible to get another swap out request. Ensure that we send
// an ACK, even if we don't have to do anything else.
render_thread_->sink().ClearMessages();
- view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
+ view()->GetMainRenderFrame()->OnSwapOut(kProxyRoutingId);
const IPC::Message* msg2 = render_thread_->sink().GetUniqueMessageMatching(
FrameHostMsg_SwapOut_ACK::ID);
ASSERT_TRUE(msg2);
@@ -512,13 +567,15 @@ TEST_F(RenderViewImplTest, SendSwapOutACK) {
// If we navigate back to this RenderView, ensure we don't send a state
// update for the swapped out URL. (http://crbug.com/72235)
FrameMsg_Navigate_Params nav_params;
- nav_params.url = GURL("data:text/html,<div>Page B</div>");
- nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- nav_params.transition = PAGE_TRANSITION_TYPED;
+ nav_params.common_params.url = GURL("data:text/html,<div>Page B</div>");
+ nav_params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ nav_params.common_params.transition = ui::PAGE_TRANSITION_TYPED;
nav_params.current_history_list_length = 1;
nav_params.current_history_list_offset = 0;
nav_params.pending_history_list_offset = 1;
nav_params.page_id = -1;
+ nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(nav_params);
ProcessPendingMessages();
const IPC::Message* msg3 = render_thread_->sink().GetUniqueMessageMatching(
@@ -549,18 +606,20 @@ TEST_F(RenderViewImplTest, ReloadWhileSwappedOut) {
// Back to page A (page_id 1) and commit.
FrameMsg_Navigate_Params params_A;
- params_A.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params_A.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params_A.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params_A.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_A.current_history_list_length = 2;
params_A.current_history_list_offset = 1;
params_A.pending_history_list_offset = 0;
params_A.page_id = 1;
- params_A.page_state = state_A;
+ params_A.commit_params.page_state = state_A;
+ params_A.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params_A);
ProcessPendingMessages();
// Respond to a swap out request.
- view()->main_render_frame()->OnSwapOut(kProxyRoutingId);
+ view()->GetMainRenderFrame()->OnSwapOut(kProxyRoutingId);
// Check for a OnSwapOutACK.
const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
@@ -573,14 +632,16 @@ TEST_F(RenderViewImplTest, ReloadWhileSwappedOut) {
// provisional load in the renderer process, after we unload the old page).
// Ensure the old page gets reloaded, not swappedout://.
FrameMsg_Navigate_Params nav_params;
- nav_params.url = GURL("data:text/html,<div>Page A</div>");
- nav_params.navigation_type = FrameMsg_Navigate_Type::RELOAD;
- nav_params.transition = PAGE_TRANSITION_RELOAD;
+ nav_params.common_params.url = GURL("data:text/html,<div>Page A</div>");
+ nav_params.common_params.navigation_type = FrameMsg_Navigate_Type::RELOAD;
+ nav_params.common_params.transition = ui::PAGE_TRANSITION_RELOAD;
nav_params.current_history_list_length = 2;
nav_params.current_history_list_offset = 0;
nav_params.pending_history_list_offset = 0;
nav_params.page_id = 1;
- nav_params.page_state = state_A;
+ nav_params.commit_params.page_state = state_A;
+ nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(nav_params);
ProcessPendingMessages();
@@ -652,13 +713,15 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
// Go back to C and commit, preparing for our real test.
FrameMsg_Navigate_Params params_C;
- params_C.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params_C.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params_C.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params_C.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_C.current_history_list_length = 4;
params_C.current_history_list_offset = 3;
params_C.pending_history_list_offset = 2;
params_C.page_id = 3;
- params_C.page_state = state_C;
+ params_C.commit_params.page_state = state_C;
+ params_C.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params_C);
ProcessPendingMessages();
render_thread_->sink().ClearMessages();
@@ -669,24 +732,28 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
// Back to page B (page_id 2), without committing.
FrameMsg_Navigate_Params params_B;
- params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params_B.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params_B.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params_B.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_B.current_history_list_length = 4;
params_B.current_history_list_offset = 2;
params_B.pending_history_list_offset = 1;
params_B.page_id = 2;
- params_B.page_state = state_B;
+ params_B.commit_params.page_state = state_B;
+ params_B.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params_B);
// Back to page A (page_id 1) and commit.
FrameMsg_Navigate_Params params;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_B.current_history_list_length = 4;
params_B.current_history_list_offset = 2;
params_B.pending_history_list_offset = 0;
params.page_id = 1;
- params.page_state = state_A;
+ params.commit_params.page_state = state_A;
+ params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params);
ProcessPendingMessages();
@@ -734,13 +801,15 @@ TEST_F(RenderViewImplTest, StaleNavigationsIgnored) {
// Back to page A (page_id 1) and commit.
FrameMsg_Navigate_Params params_A;
- params_A.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params_A.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params_A.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params_A.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_A.current_history_list_length = 2;
params_A.current_history_list_offset = 1;
params_A.pending_history_list_offset = 0;
params_A.page_id = 1;
- params_A.page_state = state_A;
+ params_A.commit_params.page_state = state_A;
+ params_A.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params_A);
ProcessPendingMessages();
@@ -752,13 +821,16 @@ TEST_F(RenderViewImplTest, StaleNavigationsIgnored) {
// The browser then sends a stale navigation to B, which should be ignored.
FrameMsg_Navigate_Params params_B;
- params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params_B.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params_B.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params_B.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_B.current_history_list_length = 2;
params_B.current_history_list_offset = 0;
params_B.pending_history_list_offset = 1;
params_B.page_id = 2;
- params_B.page_state = state_A; // Doesn't matter, just has to be present.
+ params_B.commit_params.page_state =
+ state_A; // Doesn't matter, just has to be present.
+ params_B.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params_B);
// State should be unchanged.
@@ -819,13 +891,15 @@ TEST_F(RenderViewImplTest, DontIgnoreBackAfterNavEntryLimit) {
// It has now dropped the first entry, but the renderer isn't notified.
// Ensure that going back to page B (page_id 2) at offset 0 is successful.
FrameMsg_Navigate_Params params_B;
- params_B.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params_B.transition = PAGE_TRANSITION_FORWARD_BACK;
+ params_B.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params_B.common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
params_B.current_history_list_length = 2;
params_B.current_history_list_offset = 1;
params_B.pending_history_list_offset = 0;
params_B.page_id = 2;
- params_B.page_state = state_B;
+ params_B.commit_params.page_state = state_B;
+ params_B.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params_B);
ProcessPendingMessages();
@@ -898,16 +972,17 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) {
// Update the IME status and verify if our IME backend sends an IPC message
// to activate IMEs.
- view()->UpdateTextInputState(
- RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
+ view()->UpdateTextInputType();
const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
EXPECT_TRUE(msg != NULL);
- EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
- ViewHostMsg_TextInputStateChanged::Param params;
- ViewHostMsg_TextInputStateChanged::Read(msg, &params);
- ViewHostMsg_TextInputState_Params p = params.a;
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, p.type);
- EXPECT_EQ(true, p.can_compose_inline);
+ EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
+ ViewHostMsg_TextInputTypeChanged::Param params;
+ ViewHostMsg_TextInputTypeChanged::Read(msg, &params);
+ ui::TextInputType type = params.a;
+ ui::TextInputMode input_mode = params.b;
+ bool can_compose_inline = params.c;
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_TEXT, type);
+ EXPECT_EQ(true, can_compose_inline);
// Move the input focus to the second <input> element, where we should
// de-activate IMEs.
@@ -917,34 +992,36 @@ TEST_F(RenderViewImplTest, OnImeTypeChanged) {
// Update the IME status and verify if our IME backend sends an IPC message
// to de-activate IMEs.
- view()->UpdateTextInputState(
- RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
+ view()->UpdateTextInputType();
msg = render_thread_->sink().GetMessageAt(0);
EXPECT_TRUE(msg != NULL);
- EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
- ViewHostMsg_TextInputStateChanged::Read(msg, &params);
- EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, params.a.type);
-
- for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kInputModeTestCases); j++) {
- const InputModeTestCase* test_case = &kInputModeTestCases[j];
+ EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
+ ViewHostMsg_TextInputTypeChanged::Read(msg, & params);
+ type = params.a;
+ input_mode = params.b;
+ EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, type);
+
+ for (size_t i = 0; i < arraysize(kInputModeTestCases); i++) {
+ const InputModeTestCase* test_case = &kInputModeTestCases[i];
std::string javascript =
base::StringPrintf("document.getElementById('%s').focus();",
test_case->input_id);
// Move the input focus to the target <input> element, where we should
// activate IMEs.
- ExecuteJavaScript(javascript.c_str());
+ ExecuteJavaScriptAndReturnIntValue(base::ASCIIToUTF16(javascript), NULL);
ProcessPendingMessages();
render_thread_->sink().ClearMessages();
// Update the IME status and verify if our IME backend sends an IPC
// message to activate IMEs.
- view()->UpdateTextInputState(
- RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
- msg = render_thread_->sink().GetMessageAt(0);
+ view()->UpdateTextInputType();
+ const IPC::Message* msg = render_thread_->sink().GetMessageAt(0);
EXPECT_TRUE(msg != NULL);
- EXPECT_EQ(ViewHostMsg_TextInputStateChanged::ID, msg->type());
- ViewHostMsg_TextInputStateChanged::Read(msg, &params);
- EXPECT_EQ(test_case->expected_mode, params.a.mode);
+ EXPECT_EQ(ViewHostMsg_TextInputTypeChanged::ID, msg->type());
+ ViewHostMsg_TextInputTypeChanged::Read(msg, & params);
+ type = params.a;
+ input_mode = params.b;
+ EXPECT_EQ(test_case->expected_mode, input_mode);
}
}
}
@@ -1019,7 +1096,7 @@ TEST_F(RenderViewImplTest, ImeComposition) {
{IME_CONFIRMCOMPOSITION, false, -1, -1, L"", L"\xC548\xB155"},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kImeMessages); i++) {
+ for (size_t i = 0; i < arraysize(kImeMessages); i++) {
const ImeMessage* ime_message = &kImeMessages[i];
switch (ime_message->command) {
case IME_INITIALIZE:
@@ -1073,8 +1150,7 @@ TEST_F(RenderViewImplTest, ImeComposition) {
// Update the status of our IME back-end.
// TODO(hbono): we should verify messages to be sent from the back-end.
- view()->UpdateTextInputState(
- RenderWidget::NO_SHOW_IME, RenderWidget::FROM_NON_IME);
+ view()->UpdateTextInputType();
ProcessPendingMessages();
render_thread_->sink().ClearMessages();
@@ -1114,7 +1190,7 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) {
{ blink::WebTextDirectionRightToLeft, L"\x000A" L"rtl,rtl" },
{ blink::WebTextDirectionLeftToRight, L"\x000A" L"ltr,ltr" },
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTextDirection); ++i) {
+ for (size_t i = 0; i < arraysize(kTextDirection); ++i) {
// Set the text direction of the <textarea> element.
ExecuteJavaScript("document.getElementById('test').focus();");
view()->OnSetTextDirection(kTextDirection[i].direction);
@@ -1202,7 +1278,7 @@ TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) {
MockKeyboard::LAYOUT_UNITED_STATES,
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
+ for (size_t i = 0; i < arraysize(kLayouts); ++i) {
// For each key code, we send three keyboard events.
// * we press only the key;
// * we press the key and a left-shift key, and;
@@ -1221,7 +1297,7 @@ TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) {
};
MockKeyboard::Layout layout = kLayouts[i];
- for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifierData); ++j) {
+ for (size_t j = 0; j < arraysize(kModifierData); ++j) {
// Virtual key codes used for this test.
static const int kKeyCodes[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
@@ -1247,7 +1323,7 @@ TEST_F(RenderViewImplTest, MAYBE_OnHandleKeyboardEvent) {
};
MockKeyboard::Modifiers modifiers = kModifierData[j].modifiers;
- for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
+ for (size_t k = 0; k < arraysize(kKeyCodes); ++k) {
// Send a keyboard event to the RenderView object.
// We should test a keyboard event only when the given keyboard-layout
// driver is installed in a PC and the driver can assign a Unicode
@@ -1437,7 +1513,7 @@ TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
},
};
- for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLayouts); ++i) {
+ for (size_t i = 0; i < arraysize(kLayouts); ++i) {
// Load an HTML page consisting of one <div> element.
// This <div> element is used by the EditorClientImpl class to insert
// characters received through the RenderWidget::OnHandleInputEvent()
@@ -1468,7 +1544,7 @@ TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
};
MockKeyboard::Layout layout = kLayouts[i].layout;
- for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kModifiers); ++j) {
+ for (size_t j = 0; j < arraysize(kModifiers); ++j) {
// Virtual key codes used for this test.
static const int kKeyCodes[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
@@ -1494,7 +1570,7 @@ TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
};
MockKeyboard::Modifiers modifiers = kModifiers[j];
- for (size_t k = 0; k < ARRAYSIZE_UNSAFE(kKeyCodes); ++k) {
+ for (size_t k = 0; k < arraysize(kKeyCodes); ++k) {
// Send a keyboard event to the RenderView object.
// We should test a keyboard event only when the given keyboard-layout
// driver is installed in a PC and the driver can assign a Unicode
@@ -1531,12 +1607,14 @@ TEST_F(RenderViewImplTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
// but won't complete synchronously.
FrameMsg_Navigate_Params params;
params.page_id = -1;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params.url = GURL("data:text/html,test data");
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.common_params.url = GURL("data:text/html,test data");
+ params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params);
// An error occurred.
- view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
+ view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
// Frame should exit view-source mode.
EXPECT_FALSE(web_frame->isViewSourceModeEnabled());
}
@@ -1553,12 +1631,14 @@ TEST_F(RenderViewImplTest, DidFailProvisionalLoadWithErrorForCancellation) {
// but won't complete synchronously.
FrameMsg_Navigate_Params params;
params.page_id = -1;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params.url = GURL("data:text/html,test data");
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.common_params.url = GURL("data:text/html,test data");
+ params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params);
// A cancellation occurred.
- view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
+ view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
// Frame should stay in view-source mode.
EXPECT_TRUE(web_frame->isViewSourceModeEnabled());
}
@@ -1934,13 +2014,15 @@ TEST_F(RenderViewImplTest, ZoomLimit) {
FrameMsg_Navigate_Params params;
params.page_id = -1;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
// Verifies navigation to a URL with preset zoom level indeed sets the level.
// Regression test for http://crbug.com/139559, where the level was not
// properly set when it is out of the default zoom limits of WebView.
- params.url = GURL("data:text/html,min_zoomlimit_test");
- view()->OnSetZoomLevelForLoadingURL(params.url, kMinZoomLevel);
+ params.common_params.url = GURL("data:text/html,min_zoomlimit_test");
+ view()->OnSetZoomLevelForLoadingURL(params.common_params.url, kMinZoomLevel);
frame()->OnNavigate(params);
ProcessPendingMessages();
EXPECT_DOUBLE_EQ(kMinZoomLevel, view()->GetWebView()->zoomLevel());
@@ -1948,8 +2030,8 @@ TEST_F(RenderViewImplTest, ZoomLimit) {
// It should work even when the zoom limit is temporarily changed in the page.
view()->GetWebView()->zoomLimitsChanged(ZoomFactorToZoomLevel(1.0),
ZoomFactorToZoomLevel(1.0));
- params.url = GURL("data:text/html,max_zoomlimit_test");
- view()->OnSetZoomLevelForLoadingURL(params.url, kMaxZoomLevel);
+ params.common_params.url = GURL("data:text/html,max_zoomlimit_test");
+ view()->OnSetZoomLevelForLoadingURL(params.common_params.url, kMaxZoomLevel);
frame()->OnNavigate(params);
ProcessPendingMessages();
EXPECT_DOUBLE_EQ(kMaxZoomLevel, view()->GetWebView()->zoomLevel());
@@ -2011,14 +2093,16 @@ TEST_F(RenderViewImplTest, NavigateFrame) {
// Navigate the frame only.
FrameMsg_Navigate_Params nav_params;
- nav_params.url = GURL("data:text/html,world");
- nav_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- nav_params.transition = PAGE_TRANSITION_TYPED;
+ nav_params.common_params.url = GURL("data:text/html,world");
+ nav_params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ nav_params.common_params.transition = ui::PAGE_TRANSITION_TYPED;
nav_params.current_history_list_length = 1;
nav_params.current_history_list_offset = 0;
nav_params.pending_history_list_offset = 1;
nav_params.page_id = -1;
nav_params.frame_to_navigate = "frame";
+ nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(nav_params);
FrameLoadWaiter(
RenderFrame::FromWebFrame(frame()->GetWebFrame()->firstChild())).Wait();
@@ -2067,7 +2151,7 @@ TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
for (size_t i = 0; i < render_thread_->sink().message_count(); ++i) {
const uint32 type = render_thread_->sink().GetMessageAt(i)->type();
- if (type == ViewHostMsg_TextInputStateChanged::ID) {
+ if (type == ViewHostMsg_TextInputTypeChanged::ID) {
is_input_type_called = true;
last_input_type = i;
} else if (type == ViewHostMsg_SelectionChanged::ID) {
@@ -2085,7 +2169,7 @@ TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
class SuppressErrorPageTest : public RenderViewTest {
public:
- virtual ContentRendererClient* CreateContentRendererClient() OVERRIDE {
+ ContentRendererClient* CreateContentRendererClient() override {
return new TestContentRendererClient;
}
@@ -2100,18 +2184,17 @@ class SuppressErrorPageTest : public RenderViewTest {
private:
class TestContentRendererClient : public ContentRendererClient {
public:
- virtual bool ShouldSuppressErrorPage(RenderFrame* render_frame,
- const GURL& url) OVERRIDE {
+ bool ShouldSuppressErrorPage(RenderFrame* render_frame,
+ const GURL& url) override {
return url == GURL("http://example.com/suppress");
}
- virtual void GetNavigationErrorStrings(
- content::RenderView* render_view,
- blink::WebFrame* frame,
- const blink::WebURLRequest& failed_request,
- const blink::WebURLError& error,
- std::string* error_html,
- base::string16* error_description) OVERRIDE {
+ void GetNavigationErrorStrings(content::RenderView* render_view,
+ blink::WebFrame* frame,
+ const blink::WebURLRequest& failed_request,
+ const blink::WebURLError& error,
+ std::string* error_html,
+ base::string16* error_description) override {
if (error_html)
*error_html = "A suffusion of yellow.";
}
@@ -2136,12 +2219,14 @@ TEST_F(SuppressErrorPageTest, MAYBE_Suppresses) {
// but won't complete synchronously.
FrameMsg_Navigate_Params params;
params.page_id = -1;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params.url = GURL("data:text/html,test data");
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.common_params.url = GURL("data:text/html,test data");
+ params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params);
// An error occurred.
- view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
+ view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
const int kMaxOutputCharacters = 22;
EXPECT_EQ("",
base::UTF16ToASCII(web_frame->contentAsText(kMaxOutputCharacters)));
@@ -2165,12 +2250,14 @@ TEST_F(SuppressErrorPageTest, MAYBE_DoesNotSuppress) {
// but won't complete synchronously.
FrameMsg_Navigate_Params params;
params.page_id = -1;
- params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- params.url = GURL("data:text/html,test data");
+ params.common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
+ params.common_params.url = GURL("data:text/html,test data");
+ params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
frame()->OnNavigate(params);
// An error occurred.
- view()->main_render_frame()->didFailProvisionalLoad(web_frame, error);
+ view()->GetMainRenderFrame()->didFailProvisionalLoad(web_frame, error);
// The error page itself is loaded asynchronously.
FrameLoadWaiter(frame()).Wait();
const int kMaxOutputCharacters = 22;
@@ -2302,7 +2389,7 @@ TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
// See that subresource requests are also tagged with the provider's id.
EXPECT_EQ(frame(), RenderFrameImpl::FromWebFrame(GetMainFrame()));
blink::WebURLRequest request(GURL("http://foo.com"));
- request.setTargetType(blink::WebURLRequest::TargetIsSubresource);
+ request.setRequestContext(blink::WebURLRequest::RequestContextSubresource);
blink::WebURLResponse redirect_response;
frame()->willSendRequest(GetMainFrame(), 0, request, redirect_response);
extra_data = static_cast<RequestExtraData*>(request.extraData());
@@ -2312,30 +2399,20 @@ TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
}
TEST_F(RenderViewImplTest, OnSetAccessibilityMode) {
- ASSERT_EQ(AccessibilityModeOff, view()->accessibility_mode());
- ASSERT_EQ((RendererAccessibility*) NULL, view()->renderer_accessibility());
-
- view()->OnSetAccessibilityMode(AccessibilityModeTreeOnly);
- ASSERT_EQ(AccessibilityModeTreeOnly, view()->accessibility_mode());
- ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
- ASSERT_EQ(RendererAccessibilityTypeComplete,
- view()->renderer_accessibility()->GetType());
-
- view()->OnSetAccessibilityMode(AccessibilityModeOff);
- ASSERT_EQ(AccessibilityModeOff, view()->accessibility_mode());
- ASSERT_EQ((RendererAccessibility*) NULL, view()->renderer_accessibility());
-
- view()->OnSetAccessibilityMode(AccessibilityModeComplete);
- ASSERT_EQ(AccessibilityModeComplete, view()->accessibility_mode());
- ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
- ASSERT_EQ(RendererAccessibilityTypeComplete,
- view()->renderer_accessibility()->GetType());
-
- view()->OnSetAccessibilityMode(AccessibilityModeEditableTextOnly);
- ASSERT_EQ(AccessibilityModeEditableTextOnly, view()->accessibility_mode());
- ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
- ASSERT_EQ(RendererAccessibilityTypeFocusOnly,
- view()->renderer_accessibility()->GetType());
+ ASSERT_EQ(AccessibilityModeOff, frame()->accessibility_mode());
+ ASSERT_EQ((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+
+ frame()->OnSetAccessibilityMode(AccessibilityModeTreeOnly);
+ ASSERT_EQ(AccessibilityModeTreeOnly, frame()->accessibility_mode());
+ ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+
+ frame()->OnSetAccessibilityMode(AccessibilityModeOff);
+ ASSERT_EQ(AccessibilityModeOff, frame()->accessibility_mode());
+ ASSERT_EQ((RendererAccessibility*) NULL, frame()->renderer_accessibility());
+
+ frame()->OnSetAccessibilityMode(AccessibilityModeComplete);
+ ASSERT_EQ(AccessibilityModeComplete, frame()->accessibility_mode());
+ ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
}
TEST_F(RenderViewImplTest, ScreenMetricsEmulation) {
@@ -2368,4 +2445,53 @@ TEST_F(RenderViewImplTest, ScreenMetricsEmulation) {
// Don't disable here to test that emulation is being shutdown properly.
}
+// Sanity checks for the Navigation Timing API |navigationStart| override. We
+// are asserting only most basic constraints, as TimeTicks (passed as the
+// override) are not comparable with the wall time (returned by the Blink API).
+TEST_F(RenderViewImplTest, NavigationStartOverride) {
+ // Verify that a navigation that claims to have started at the earliest
+ // possible TimeTicks is indeed reported as one that started before
+ // OnNavigate() is called.
+ base::Time before_navigation = base::Time::Now();
+ FrameMsg_Navigate_Params early_nav_params;
+ early_nav_params.common_params.url = GURL("data:text/html,<div>Page</div>");
+ early_nav_params.common_params.navigation_type =
+ FrameMsg_Navigate_Type::NORMAL;
+ early_nav_params.common_params.transition = ui::PAGE_TRANSITION_TYPED;
+ early_nav_params.page_id = -1;
+ early_nav_params.request_params.is_post = true;
+ early_nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::FromInternalValue(1);
+
+ frame()->OnNavigate(early_nav_params);
+ ProcessPendingMessages();
+
+ base::Time early_nav_reported_start =
+ base::Time::FromDoubleT(GetMainFrame()->performance().navigationStart());
+ EXPECT_LT(early_nav_reported_start, before_navigation);
+
+ // Verify that a navigation that claims to have started in the future - 42
+ // days from now is *not* reported as one that starts in the future; as we
+ // sanitize the override allowing a maximum of ::Now().
+ FrameMsg_Navigate_Params late_nav_params;
+ late_nav_params.common_params.url =
+ GURL("data:text/html,<div>Another page</div>");
+ late_nav_params.common_params.navigation_type =
+ FrameMsg_Navigate_Type::NORMAL;
+ late_nav_params.common_params.transition = ui::PAGE_TRANSITION_TYPED;
+ late_nav_params.page_id = -1;
+ late_nav_params.request_params.is_post = true;
+ late_nav_params.commit_params.browser_navigation_start =
+ base::TimeTicks::Now() + base::TimeDelta::FromDays(42);
+
+ frame()->OnNavigate(late_nav_params);
+ ProcessPendingMessages();
+ base::Time after_navigation =
+ base::Time::Now() + base::TimeDelta::FromDays(1);
+
+ base::Time late_nav_reported_start =
+ base::Time::FromDoubleT(GetMainFrame()->performance().navigationStart());
+ EXPECT_LE(late_nav_reported_start, after_navigation);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_view_browsertest_mac.mm b/chromium/content/renderer/render_view_browsertest_mac.mm
index b2473c6f40a..6730da746aa 100644
--- a/chromium/content/renderer/render_view_browsertest_mac.mm
+++ b/chromium/content/renderer/render_view_browsertest_mac.mm
@@ -6,14 +6,14 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/native_web_keyboard_event.h"
+#include "content/public/common/web_preferences.h"
#include "content/public/test/render_view_test.h"
#include "content/renderer/render_view_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#include "webkit/common/webpreferences.h"
-#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h> // for the kVK_* constants.
+#include <Cocoa/Cocoa.h>
namespace content {
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index f5bd5eb75d9..0c839e267a3 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -22,7 +22,6 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
-#include "base/path_service.h"
#include "base/process/kill.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
@@ -40,6 +39,7 @@
#include "content/child/npapi/webplugin_delegate_impl.h"
#include "content/child/request_extra_data.h"
#include "content/child/webmessageportchannel_impl.h"
+#include "content/common/content_constants_internal.h"
#include "content/common/database_messages.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/common/drag_messages.h"
@@ -47,7 +47,6 @@
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/input_messages.h"
#include "content/common/pepper_messages.h"
-#include "content/common/socket_stream_handle_data.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
#include "content/public/common/bindings_policy.h"
@@ -56,29 +55,27 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/favicon_url.h"
+#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
+#include "content/public/common/page_state.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/ssl_status.h"
#include "content/public/common/three_d_api_types.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
+#include "content/public/common/web_preferences.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/navigation_state.h"
#include "content/public/renderer/render_view_observer.h"
#include "content/public/renderer/render_view_visitor.h"
-#include "content/public/renderer/web_preferences.h"
-#include "content/renderer/accessibility/renderer_accessibility.h"
-#include "content/renderer/accessibility/renderer_accessibility_complete.h"
-#include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
-#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
#include "content/renderer/devtools/devtools_agent.h"
#include "content/renderer/disambiguation_popup_helper.h"
#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
#include "content/renderer/drop_data_builder.h"
-#include "content/renderer/external_popup_menu.h"
+#include "content/renderer/gpu/gpu_benchmarking_extension.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/history_controller.h"
#include "content/renderer/history_serialization.h"
@@ -87,12 +84,10 @@
#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/video_capture_impl_manager.h"
-#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/memory_benchmarking_extension.h"
#include "content/renderer/mhtml_generator.h"
-#include "content/renderer/push_messaging_dispatcher.h"
+#include "content/renderer/net_info_helper.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
@@ -114,7 +109,6 @@
#include "content/renderer/web_ui_mojo.h"
#include "content/renderer/websharedworker_proxy.h"
#include "media/audio/audio_output_device.h"
-#include "media/base/filter_collection.h"
#include "media/base/media_switches.h"
#include "media/filters/audio_renderer_impl.h"
#include "media/filters/gpu_video_accelerator_factories.h"
@@ -123,7 +117,9 @@
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_util.h"
+#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCString.h"
+#include "third_party/WebKit/public/platform/WebConnectionType.h"
#include "third_party/WebKit/public/platform/WebDragData.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
#include "third_party/WebKit/public/platform/WebImage.h"
@@ -131,7 +127,6 @@
#include "third_party/WebKit/public/platform/WebPoint.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
-#include "third_party/WebKit/public/platform/WebSocketStreamHandle.h"
#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -157,11 +152,14 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebGlyphCache.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
+#include "third_party/WebKit/public/web/WebHitTestResult.h"
#include "third_party/WebKit/public/web/WebInputElement.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
+#include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
#include "third_party/WebKit/public/web/WebNodeList.h"
#include "third_party/WebKit/public/web/WebPageSerializer.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
@@ -169,6 +167,7 @@
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebPluginDocument.h"
#include "third_party/WebKit/public/web/WebRange.h"
+#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSearchableFormData.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
@@ -179,6 +178,8 @@
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
#include "third_party/WebKit/public/web/default/WebRenderTheme.h"
+#include "third_party/icu/source/common/unicode/uchar.h"
+#include "third_party/icu/source/common/unicode/uscript.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/events/latency_info.h"
@@ -187,9 +188,7 @@
#include "ui/gfx/rect.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/size_conversions.h"
-#include "ui/shell_dialogs/selected_file_info.h"
#include "v8/include/v8.h"
-#include "webkit/child/weburlresponse_extradata_impl.h"
#if defined(OS_ANDROID)
#include <cpu-features.h>
@@ -199,10 +198,8 @@
#include "content/renderer/android/email_detector.h"
#include "content/renderer/android/phone_number_detector.h"
#include "net/android/network_library.h"
-#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebFloatRect.h"
-#include "third_party/WebKit/public/web/WebHitTestResult.h"
#include "ui/gfx/rect_f.h"
#elif defined(OS_WIN)
@@ -223,6 +220,7 @@
#if defined(ENABLE_WEBRTC)
#include "content/renderer/media/rtc_peer_connection_handler.h"
+#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#endif
using blink::WebAXObject;
@@ -241,8 +239,6 @@ using blink::WebDragData;
using blink::WebDragOperation;
using blink::WebDragOperationsMask;
using blink::WebElement;
-using blink::WebExternalPopupMenu;
-using blink::WebExternalPopupMenuClient;
using blink::WebFileChooserCompletion;
using blink::WebFindOptions;
using blink::WebFormControlElement;
@@ -271,7 +267,6 @@ using blink::WebPluginAction;
using blink::WebPluginContainer;
using blink::WebPluginDocument;
using blink::WebPoint;
-using blink::WebPopupMenuInfo;
using blink::WebRange;
using blink::WebRect;
using blink::WebReferrerPolicy;
@@ -282,7 +277,6 @@ using blink::WebSecurityPolicy;
using blink::WebSerializedScriptValue;
using blink::WebSettings;
using blink::WebSize;
-using blink::WebSocketStreamHandle;
using blink::WebStorageNamespace;
using blink::WebStorageQuotaCallbacks;
using blink::WebStorageQuotaError;
@@ -300,9 +294,10 @@ using blink::WebVector;
using blink::WebView;
using blink::WebWidget;
using blink::WebWindowFeatures;
+using blink::WebNetworkStateNotifier;
+using blink::WebRuntimeFeatures;
using base::Time;
using base::TimeDelta;
-using webkit_glue::WebURLResponseExtraDataImpl;
#if defined(OS_ANDROID)
using blink::WebContentDetectionResult;
@@ -342,12 +337,10 @@ static RenderViewImpl* (*g_create_render_view_impl)(RenderViewImplParams*) =
NULL;
// static
-bool RenderViewImpl::IsReload(const FrameMsg_Navigate_Params& params) {
- return
- params.navigation_type == FrameMsg_Navigate_Type::RELOAD ||
- params.navigation_type == FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE ||
- params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
+bool RenderViewImpl::IsReload(FrameMsg_Navigate_Type::Value navigation_type) {
+ return navigation_type == FrameMsg_Navigate_Type::RELOAD ||
+ navigation_type == FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE ||
+ navigation_type == FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
}
// static
@@ -394,39 +387,15 @@ static bool DeviceScaleEnsuresTextQuality(float device_scale_factor) {
}
-static bool ShouldUseFixedPositionCompositing(float device_scale_factor) {
- // Compositing for fixed-position elements is dependent on
- // device_scale_factor if no flag is set. http://crbug.com/172738
+static bool PreferCompositingToLCDText(float device_scale_factor) {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- if (command_line.HasSwitch(switches::kDisableCompositingForFixedPosition))
+ if (command_line.HasSwitch(switches::kDisablePreferCompositingToLCDText))
return false;
-
- if (command_line.HasSwitch(switches::kEnableCompositingForFixedPosition))
+ if (command_line.HasSwitch(switches::kEnablePreferCompositingToLCDText))
return true;
-
- return DeviceScaleEnsuresTextQuality(device_scale_factor);
-}
-
-static bool ShouldUseAcceleratedCompositingForOverflowScroll(
- float device_scale_factor) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- if (command_line.HasSwitch(switches::kDisableAcceleratedOverflowScroll))
- return false;
-
- if (command_line.HasSwitch(switches::kEnableAcceleratedOverflowScroll))
- return true;
-
- return DeviceScaleEnsuresTextQuality(device_scale_factor);
-}
-
-static bool ShouldUseCompositedScrollingForFrames(
- float device_scale_factor) {
if (RenderThreadImpl::current() &&
!RenderThreadImpl::current()->is_lcd_text_enabled())
return true;
-
return DeviceScaleEnsuresTextQuality(device_scale_factor);
}
@@ -445,23 +414,6 @@ static bool ShouldUseTransitionCompositing(float device_scale_factor) {
return false;
}
-static bool ShouldUseAcceleratedFixedRootBackground(float device_scale_factor) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
-
- if (command_line.HasSwitch(switches::kDisableAcceleratedFixedRootBackground))
- return false;
-
- if (command_line.HasSwitch(switches::kEnableAcceleratedFixedRootBackground))
- return true;
-
- return DeviceScaleEnsuresTextQuality(device_scale_factor);
-}
-
-static bool ShouldUseExpandedHeuristicsForGpuRasterization() {
- return base::FieldTrialList::FindFullName(
- "GpuRasterizationExpandedContentWhitelist") == "Enabled";
-}
-
static FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) {
switch (type) {
case blink::WebIconURL::TypeFavicon:
@@ -503,19 +455,16 @@ class WebWidgetLockTarget : public MouseLockDispatcher::LockTarget {
explicit WebWidgetLockTarget(blink::WebWidget* webwidget)
: webwidget_(webwidget) {}
- virtual void OnLockMouseACK(bool succeeded) OVERRIDE {
+ void OnLockMouseACK(bool succeeded) override {
if (succeeded)
webwidget_->didAcquirePointerLock();
else
webwidget_->didNotAcquirePointerLock();
}
- virtual void OnMouseLockLost() OVERRIDE {
- webwidget_->didLosePointerLock();
- }
+ void OnMouseLockLost() override { webwidget_->didLosePointerLock(); }
- virtual bool HandleMouseLockedInputEvent(
- const blink::WebMouseEvent &event) OVERRIDE {
+ bool HandleMouseLockedInputEvent(const blink::WebMouseEvent& event) override {
// The WebWidget handles mouse lock in WebKit's handleInputEvent().
return false;
}
@@ -609,6 +558,87 @@ WebDragData DropDataToWebDragData(const DropData& drop_data) {
return result;
}
+typedef void (*SetFontFamilyWrapper)(blink::WebSettings*,
+ const base::string16&,
+ UScriptCode);
+
+void SetStandardFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setStandardFontFamily(font, script);
+}
+
+void SetFixedFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setFixedFontFamily(font, script);
+}
+
+void SetSerifFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setSerifFontFamily(font, script);
+}
+
+void SetSansSerifFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setSansSerifFontFamily(font, script);
+}
+
+void SetCursiveFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setCursiveFontFamily(font, script);
+}
+
+void SetFantasyFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setFantasyFontFamily(font, script);
+}
+
+void SetPictographFontFamilyWrapper(WebSettings* settings,
+ const base::string16& font,
+ UScriptCode script) {
+ settings->setPictographFontFamily(font, script);
+}
+
+// If |scriptCode| is a member of a family of "similar" script codes, returns
+// the script code in that family that is used by WebKit for font selection
+// purposes. For example, USCRIPT_KATAKANA_OR_HIRAGANA and USCRIPT_JAPANESE are
+// considered equivalent for the purposes of font selection. WebKit uses the
+// script code USCRIPT_KATAKANA_OR_HIRAGANA. So, if |scriptCode| is
+// USCRIPT_JAPANESE, the function returns USCRIPT_KATAKANA_OR_HIRAGANA. WebKit
+// uses different scripts than the ones in Chrome pref names because the version
+// of ICU included on certain ports does not have some of the newer scripts. If
+// |scriptCode| is not a member of such a family, returns |scriptCode|.
+UScriptCode GetScriptForWebSettings(UScriptCode scriptCode) {
+ switch (scriptCode) {
+ case USCRIPT_HIRAGANA:
+ case USCRIPT_KATAKANA:
+ case USCRIPT_JAPANESE:
+ return USCRIPT_KATAKANA_OR_HIRAGANA;
+ case USCRIPT_KOREAN:
+ return USCRIPT_HANGUL;
+ default:
+ return scriptCode;
+ }
+}
+
+void ApplyFontsFromMap(const ScriptFontFamilyMap& map,
+ SetFontFamilyWrapper setter,
+ WebSettings* settings) {
+ for (ScriptFontFamilyMap::const_iterator it = map.begin(); it != map.end();
+ ++it) {
+ int32 script = u_getPropertyValueEnum(UCHAR_SCRIPT, (it->first).c_str());
+ if (script >= 0 && script < USCRIPT_CODE_LIMIT) {
+ UScriptCode code = static_cast<UScriptCode>(script);
+ (*setter)(settings, it->second, GetScriptForWebSettings(code));
+ }
+ }
+}
+
} // namespace
RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
@@ -637,13 +667,9 @@ RenderViewImpl::RenderViewImpl(RenderViewImplParams* params)
top_controls_constraints_(cc::BOTH),
#endif
has_scrolled_focused_editable_node_into_rect_(false),
- push_messaging_dispatcher_(NULL),
speech_recognition_dispatcher_(NULL),
- media_stream_dispatcher_(NULL),
browser_plugin_manager_(NULL),
devtools_agent_(NULL),
- accessibility_mode_(AccessibilityModeOff),
- renderer_accessibility_(NULL),
mouse_lock_dispatcher_(NULL),
#if defined(OS_ANDROID)
expected_content_intent_id_(0),
@@ -677,14 +703,6 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
WebLocalFrame* web_frame = WebLocalFrame::create(main_render_frame_.get());
main_render_frame_->SetWebFrame(web_frame);
- if (params->proxy_routing_id != MSG_ROUTING_NONE) {
- CHECK(params->swapped_out);
- RenderFrameProxy* proxy =
- RenderFrameProxy::CreateFrameProxy(params->proxy_routing_id,
- params->main_frame_routing_id);
- main_render_frame_->set_render_frame_proxy(proxy);
- }
-
webwidget_ = WebView::create(this);
webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_));
@@ -697,7 +715,7 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
const std::string region_code =
command_line.HasSwitch(switches::kNetworkCountryIso)
? command_line.GetSwitchValueASCII(switches::kNetworkCountryIso)
- : net::android::GetTelephonyNetworkOperator();
+ : net::android::GetTelephonyNetworkCountryIso();
content_detectors_.push_back(linked_ptr<ContentDetector>(
new AddressDetector()));
content_detectors_.push_back(linked_ptr<ContentDetector>(
@@ -726,25 +744,35 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
g_view_map.Get().insert(std::make_pair(webview(), this));
g_routing_id_view_map.Get().insert(std::make_pair(routing_id_, this));
webview()->setDeviceScaleFactor(device_scale_factor_);
- webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
- ShouldUseFixedPositionCompositing(device_scale_factor_));
- webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
- ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
+ webview()->settings()->setPreferCompositingToLCDTextEnabled(
+ PreferCompositingToLCDText(device_scale_factor_));
webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
ShouldUseTransitionCompositing(device_scale_factor_));
- webview()->settings()->setAcceleratedCompositingForFixedRootBackgroundEnabled(
- ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
- webview()->settings()->setCompositedScrollingForFramesEnabled(
- ShouldUseCompositedScrollingForFrames(device_scale_factor_));
- webview()->settings()->setUseExpandedHeuristicsForGpuRasterization(
- ShouldUseExpandedHeuristicsForGpuRasterization());
+ webview()->settings()->setThreadedScrollingEnabled(
+ !command_line.HasSwitch(switches::kDisableThreadedScrolling));
+ webview()->settings()->setRootLayerScrolls(
+ command_line.HasSwitch(switches::kRootLayerScrolls));
ApplyWebPreferences(webkit_preferences_, webview());
webview()->settings()->setAllowConnectingInsecureWebSocket(
command_line.HasSwitch(switches::kAllowInsecureWebSocketFromHttpsOrigin));
- webview()->setMainFrame(main_render_frame_->GetWebFrame());
+ RenderFrameProxy* proxy = NULL;
+ if (params->proxy_routing_id != MSG_ROUTING_NONE) {
+ CHECK(params->swapped_out);
+ proxy = RenderFrameProxy::CreateProxyToReplaceFrame(
+ main_render_frame_.get(), params->proxy_routing_id);
+ main_render_frame_->set_render_frame_proxy(proxy);
+ }
+
+ // In --site-per-process, just use the WebRemoteFrame as the main frame.
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
+ proxy) {
+ webview()->setMainFrame(proxy->web_frame());
+ } else {
+ webview()->setMainFrame(main_render_frame_->GetWebFrame());
+ }
main_render_frame_->Initialize();
if (switches::IsTouchDragDropEnabled())
@@ -762,11 +790,6 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
OnSetRendererPrefs(params->renderer_prefs);
-#if defined(ENABLE_WEBRTC)
- if (!media_stream_dispatcher_)
- media_stream_dispatcher_ = new MediaStreamDispatcher(this);
-#endif
-
new MHTMLGenerator(this);
#if defined(OS_MACOSX)
new TextInputClientObserver(this);
@@ -782,9 +805,6 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
history_controller_.reset(new HistoryController(this));
- // Create renderer_accessibility_ if needed.
- OnSetAccessibilityMode(params->accessibility_mode);
-
new IdleUserDetector(this);
if (command_line.HasSwitch(switches::kDomAutomationController))
@@ -806,7 +826,7 @@ void RenderViewImpl::Initialize(RenderViewImplParams* params) {
// If we are initially swapped out, navigate to kSwappedOutURL.
// This ensures we are in a unique origin that others cannot script.
- if (is_swapped_out_)
+ if (is_swapped_out_ && webview()->mainFrame()->isWebLocalFrame())
NavigateToSwappedOutURL(webview()->mainFrame());
}
@@ -888,6 +908,224 @@ void RenderView::ForEach(RenderViewVisitor* visitor) {
}
/*static*/
+void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
+ WebView* web_view) {
+ WebSettings* settings = web_view->settings();
+ ApplyFontsFromMap(prefs.standard_font_family_map,
+ SetStandardFontFamilyWrapper, settings);
+ ApplyFontsFromMap(prefs.fixed_font_family_map,
+ SetFixedFontFamilyWrapper, settings);
+ ApplyFontsFromMap(prefs.serif_font_family_map,
+ SetSerifFontFamilyWrapper, settings);
+ ApplyFontsFromMap(prefs.sans_serif_font_family_map,
+ SetSansSerifFontFamilyWrapper, settings);
+ ApplyFontsFromMap(prefs.cursive_font_family_map,
+ SetCursiveFontFamilyWrapper, settings);
+ ApplyFontsFromMap(prefs.fantasy_font_family_map,
+ SetFantasyFontFamilyWrapper, settings);
+ ApplyFontsFromMap(prefs.pictograph_font_family_map,
+ SetPictographFontFamilyWrapper, settings);
+ settings->setDefaultFontSize(prefs.default_font_size);
+ settings->setDefaultFixedFontSize(prefs.default_fixed_font_size);
+ settings->setMinimumFontSize(prefs.minimum_font_size);
+ settings->setMinimumLogicalFontSize(prefs.minimum_logical_font_size);
+ settings->setDefaultTextEncodingName(
+ base::ASCIIToUTF16(prefs.default_encoding));
+ settings->setJavaScriptEnabled(prefs.javascript_enabled);
+ settings->setWebSecurityEnabled(prefs.web_security_enabled);
+ settings->setJavaScriptCanOpenWindowsAutomatically(
+ prefs.javascript_can_open_windows_automatically);
+ settings->setLoadsImagesAutomatically(prefs.loads_images_automatically);
+ settings->setImagesEnabled(prefs.images_enabled);
+ settings->setPluginsEnabled(prefs.plugins_enabled);
+ settings->setDOMPasteAllowed(prefs.dom_paste_enabled);
+ settings->setShrinksStandaloneImagesToFit(
+ prefs.shrinks_standalone_images_to_fit);
+ settings->setUsesEncodingDetector(prefs.uses_universal_detector);
+ settings->setTextAreasAreResizable(prefs.text_areas_are_resizable);
+ settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows);
+ settings->setDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled);
+ settings->setJavaScriptCanAccessClipboard(
+ prefs.javascript_can_access_clipboard);
+ WebRuntimeFeatures::enableXSLT(prefs.xslt_enabled);
+ WebRuntimeFeatures::enableSlimmingPaint(prefs.slimming_paint_enabled);
+ settings->setXSSAuditorEnabled(prefs.xss_auditor_enabled);
+ settings->setDNSPrefetchingEnabled(prefs.dns_prefetching_enabled);
+ settings->setLocalStorageEnabled(prefs.local_storage_enabled);
+ settings->setSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled);
+ WebRuntimeFeatures::enableDatabase(prefs.databases_enabled);
+ settings->setOfflineWebApplicationCacheEnabled(
+ prefs.application_cache_enabled);
+ settings->setCaretBrowsingEnabled(prefs.caret_browsing_enabled);
+ settings->setHyperlinkAuditingEnabled(prefs.hyperlink_auditing_enabled);
+ settings->setCookieEnabled(prefs.cookie_enabled);
+ settings->setNavigateOnDragDrop(prefs.navigate_on_drag_drop);
+
+ settings->setJavaEnabled(prefs.java_enabled);
+
+ // By default, allow_universal_access_from_file_urls is set to false and thus
+ // we mitigate attacks from local HTML files by not granting file:// URLs
+ // universal access. Only test shell will enable this.
+ settings->setAllowUniversalAccessFromFileURLs(
+ prefs.allow_universal_access_from_file_urls);
+ settings->setAllowFileAccessFromFileURLs(
+ prefs.allow_file_access_from_file_urls);
+
+ // Enable the web audio API if requested on the command line.
+ settings->setWebAudioEnabled(prefs.webaudio_enabled);
+
+ // Enable experimental WebGL support if requested on command line
+ // and support is compiled in.
+ settings->setExperimentalWebGLEnabled(prefs.experimental_webgl_enabled);
+
+ // Disable GL multisampling if requested on command line.
+ settings->setOpenGLMultisamplingEnabled(prefs.gl_multisampling_enabled);
+
+ // Enable WebGL errors to the JS console if requested.
+ settings->setWebGLErrorsToConsoleEnabled(
+ prefs.webgl_errors_to_console_enabled);
+
+ // Uses the mock theme engine for scrollbars.
+ settings->setMockScrollbarsEnabled(prefs.mock_scrollbars_enabled);
+
+ settings->setLayerSquashingEnabled(prefs.layer_squashing_enabled);
+
+ // Enable gpu-accelerated 2d canvas if requested on the command line.
+ settings->setAccelerated2dCanvasEnabled(prefs.accelerated_2d_canvas_enabled);
+
+ settings->setMinimumAccelerated2dCanvasSize(
+ prefs.minimum_accelerated_2d_canvas_size);
+
+ // Disable antialiasing for 2d canvas if requested on the command line.
+ settings->setAntialiased2dCanvasEnabled(
+ !prefs.antialiased_2d_canvas_disabled);
+
+ // Enabled antialiasing of clips for 2d canvas if requested on the command
+ // line.
+ settings->setAntialiasedClips2dCanvasEnabled(
+ prefs.antialiased_clips_2d_canvas_enabled);
+
+ // Set MSAA sample count for 2d canvas if requested on the command line (or
+ // default value if not).
+ settings->setAccelerated2dCanvasMSAASampleCount(
+ prefs.accelerated_2d_canvas_msaa_sample_count);
+
+ // Enable container culling if requested on the command line.
+ settings->setContainerCullingEnabled(prefs.container_culling_enabled);
+
+ WebRuntimeFeatures::enableTextBlobs(prefs.text_blobs_enabled);
+
+ settings->setAsynchronousSpellCheckingEnabled(
+ prefs.asynchronous_spell_checking_enabled);
+ settings->setUnifiedTextCheckerEnabled(prefs.unified_textchecker_enabled);
+
+ // Tabs to link is not part of the settings. WebCore calls
+ // ChromeClient::tabsToLinks which is part of the glue code.
+ web_view->setTabsToLinks(prefs.tabs_to_links);
+
+ settings->setAllowDisplayOfInsecureContent(
+ prefs.allow_displaying_insecure_content);
+ settings->setAllowRunningOfInsecureContent(
+ prefs.allow_running_insecure_content);
+ settings->setPasswordEchoEnabled(prefs.password_echo_enabled);
+ settings->setShouldPrintBackgrounds(prefs.should_print_backgrounds);
+ settings->setShouldClearDocumentBackground(
+ prefs.should_clear_document_background);
+ settings->setEnableScrollAnimator(prefs.enable_scroll_animator);
+
+ settings->setRegionBasedColumnsEnabled(prefs.region_based_columns_enabled);
+
+ WebRuntimeFeatures::enableTouch(prefs.touch_enabled);
+ settings->setMaxTouchPoints(prefs.pointer_events_max_touch_points);
+ settings->setDeviceSupportsTouch(prefs.device_supports_touch);
+ settings->setDeviceSupportsMouse(prefs.device_supports_mouse);
+ settings->setEnableTouchAdjustment(prefs.touch_adjustment_enabled);
+
+ settings->setDeferredImageDecodingEnabled(
+ prefs.deferred_image_decoding_enabled);
+ WebRuntimeFeatures::enableImageColorProfiles(
+ prefs.image_color_profiles_enabled);
+ settings->setShouldRespectImageOrientation(
+ prefs.should_respect_image_orientation);
+
+ settings->setUnsafePluginPastingEnabled(false);
+ settings->setEditingBehavior(
+ static_cast<WebSettings::EditingBehavior>(prefs.editing_behavior));
+
+ settings->setSupportsMultipleWindows(prefs.supports_multiple_windows);
+
+ settings->setViewportEnabled(prefs.viewport_enabled);
+ settings->setLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale);
+ settings->setViewportMetaEnabled(prefs.viewport_meta_enabled);
+ settings->setMainFrameResizesAreOrientationChanges(
+ prefs.main_frame_resizes_are_orientation_changes);
+
+ settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled);
+
+ settings->setSpatialNavigationEnabled(prefs.spatial_navigation_enabled);
+
+ settings->setSelectionIncludesAltImageText(true);
+
+ settings->setV8CacheOptions(
+ static_cast<WebSettings::V8CacheOptions>(prefs.v8_cache_options));
+
+ settings->setV8ScriptStreamingEnabled(prefs.v8_script_streaming_enabled);
+ settings->setV8ScriptStreamingMode(
+ static_cast<WebSettings::V8ScriptStreamingMode>(
+ prefs.v8_script_streaming_mode));
+
+#if defined(OS_ANDROID)
+ settings->setAllowCustomScrollbarInMainFrame(false);
+ settings->setTextAutosizingEnabled(prefs.text_autosizing_enabled);
+ settings->setAccessibilityFontScaleFactor(prefs.font_scale_factor);
+ settings->setDeviceScaleAdjustment(prefs.device_scale_adjustment);
+ settings->setFullscreenSupported(prefs.fullscreen_supported);
+ web_view->setIgnoreViewportTagScaleLimits(prefs.force_enable_zoom);
+ settings->setAutoZoomFocusedNodeToLegibleScale(true);
+ settings->setDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled);
+ settings->setMediaControlsOverlayPlayButtonEnabled(true);
+ settings->setMediaPlaybackRequiresUserGesture(
+ prefs.user_gesture_required_for_media_playback);
+ settings->setDefaultVideoPosterURL(
+ base::ASCIIToUTF16(prefs.default_video_poster_url.spec()));
+ settings->setSupportDeprecatedTargetDensityDPI(
+ prefs.support_deprecated_target_density_dpi);
+ settings->setUseLegacyBackgroundSizeShorthandBehavior(
+ prefs.use_legacy_background_size_shorthand_behavior);
+ settings->setWideViewportQuirkEnabled(prefs.wide_viewport_quirk);
+ settings->setUseWideViewport(prefs.use_wide_viewport);
+ settings->setForceZeroLayoutHeight(prefs.force_zero_layout_height);
+ settings->setViewportMetaLayoutSizeQuirk(
+ prefs.viewport_meta_layout_size_quirk);
+ settings->setViewportMetaMergeContentQuirk(
+ prefs.viewport_meta_merge_content_quirk);
+ settings->setViewportMetaNonUserScalableQuirk(
+ prefs.viewport_meta_non_user_scalable_quirk);
+ settings->setViewportMetaZeroValuesQuirk(
+ prefs.viewport_meta_zero_values_quirk);
+ settings->setClobberUserAgentInitialScaleQuirk(
+ prefs.clobber_user_agent_initial_scale_quirk);
+ settings->setIgnoreMainFrameOverflowHiddenQuirk(
+ prefs.ignore_main_frame_overflow_hidden_quirk);
+ settings->setReportScreenSizeInPhysicalPixelsQuirk(
+ prefs.report_screen_size_in_physical_pixels_quirk);
+ settings->setMainFrameClipsContent(false);
+ settings->setShrinksStandaloneImagesToFit(false);
+ settings->setShrinksViewportContentToFit(true);
+#endif
+
+ WebNetworkStateNotifier::setOnLine(prefs.is_online);
+ WebNetworkStateNotifier::setWebConnectionType(
+ NetConnectionTypeToWebConnectionType(prefs.connection_type));
+ settings->setPinchVirtualViewportEnabled(
+ prefs.pinch_virtual_viewport_enabled);
+
+ settings->setPinchOverlayScrollbarThickness(
+ prefs.pinch_overlay_scrollbar_thickness);
+ settings->setUseSolidColorScrollbars(prefs.use_solid_color_scrollbars);
+}
+
+/*static*/
RenderViewImpl* RenderViewImpl::Create(
int32 opener_id,
bool window_was_created_with_opener,
@@ -904,8 +1142,7 @@ RenderViewImpl* RenderViewImpl::Create(
bool hidden,
bool never_visible,
int32 next_page_id,
- const blink::WebScreenInfo& screen_info,
- AccessibilityMode accessibility_mode) {
+ const blink::WebScreenInfo& screen_info) {
DCHECK(routing_id != MSG_ROUTING_NONE);
RenderViewImplParams params(opener_id,
window_was_created_with_opener,
@@ -922,8 +1159,7 @@ RenderViewImpl* RenderViewImpl::Create(
hidden,
never_visible,
next_page_id,
- screen_info,
- accessibility_mode);
+ screen_info);
RenderViewImpl* render_view = NULL;
if (g_create_render_view_impl)
render_view = g_create_render_view_impl(&params);
@@ -977,7 +1213,7 @@ void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
else if (focused_pepper_plugin_ == instance)
focused_pepper_plugin_ = NULL;
- UpdateTextInputState(NO_SHOW_IME, FROM_NON_IME);
+ UpdateTextInputType();
UpdateSelectionBounds();
}
@@ -1016,6 +1252,20 @@ void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
Send(new ViewHostMsg_PluginFocusChanged(routing_id(), focused, plugin_id));
}
+void RenderViewImpl::OnGetRenderedText() {
+ if (!webview())
+ return;
+ // Get rendered text from WebLocalFrame.
+ // TODO: Currently IPC truncates any data that has a
+ // size > kMaximumMessageSize. May be split the text into smaller chunks and
+ // send back using multiple IPC. See http://crbug.com/393444.
+ static const size_t kMaximumMessageSize = 8 * 1024 * 1024;
+ std::string text = webview()->mainFrame()->contentAsText(
+ kMaximumMessageSize).utf8();
+
+ Send(new ViewMsg_GetRenderedTextCompleted(routing_id(), text));
+}
+
void RenderViewImpl::StartPluginIme() {
IPC::Message* msg = new ViewHostMsg_StartPluginIme(routing_id());
// This message can be sent during event-handling, and needs to be delivered
@@ -1039,7 +1289,7 @@ bool RenderViewImpl::HasIMETextFocus() {
bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
WebFrame* main_frame = webview() ? webview()->mainFrame() : NULL;
- if (main_frame)
+ if (main_frame && main_frame->isWebLocalFrame())
GetContentClient()->SetActiveURL(main_frame->document().url());
ObserverListBase<RenderViewObserver>::Iterator it(observers_);
@@ -1056,7 +1306,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
OnScrollFocusedEditableNodeIntoRect)
IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
- IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
IPC_MESSAGE_HANDLER(ViewMsg_SaveImageAt, OnSaveImageAt)
IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
@@ -1111,25 +1360,24 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryLengthAndPrune,
OnSetHistoryLengthAndPrune)
IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
- IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode)
- IPC_MESSAGE_HANDLER(ViewMsg_DisownOpener, OnDisownOpener)
IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupBitmap,
OnReleaseDisambiguationPopupBitmap)
IPC_MESSAGE_HANDLER(ViewMsg_WindowSnapshotCompleted,
OnWindowSnapshotCompleted)
+ IPC_MESSAGE_HANDLER(ViewMsg_ForceRedraw, OnForceRedraw)
IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
OnActivateNearestFindResult)
IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects, OnFindMatchRects)
- IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
OnUpdateTopControlsState)
IPC_MESSAGE_HANDLER(ViewMsg_ExtractSmartClipData, OnExtractSmartClipData)
#elif defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(ViewMsg_GetRenderedText,
+ OnGetRenderedText)
IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
OnPluginImeCompositionCompleted)
- IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
IPC_MESSAGE_HANDLER(ViewMsg_SetInLiveResize, OnSetInLiveResize)
IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
@@ -1153,13 +1401,14 @@ void RenderViewImpl::OnSelectWordAroundCaret() {
handling_input_event_ = false;
}
-bool RenderViewImpl::IsBackForwardToStaleEntry(
- const FrameMsg_Navigate_Params& params,
- bool is_reload) {
+bool RenderViewImpl::IsBackForwardToStaleEntry(const PageState& state,
+ int pending_history_list_offset,
+ int32 page_id,
+ bool is_reload) {
// Make sure this isn't a back/forward to an entry we have already cropped
// or replaced from our history, before the browser knew about it. If so,
// a new navigation has committed in the mean time, and we can ignore this.
- bool is_back_forward = !is_reload && params.page_state.IsValid();
+ bool is_back_forward = !is_reload && state.IsValid();
// Note: if the history_list_length_ is 0 for a back/forward, we must be
// restoring from a previous session. We'll update our state in OnNavigate.
@@ -1170,34 +1419,26 @@ bool RenderViewImpl::IsBackForwardToStaleEntry(
// Check for whether the forward history has been cropped due to a recent
// navigation the browser didn't know about.
- if (params.pending_history_list_offset >= history_list_length_)
+ if (pending_history_list_offset >= history_list_length_)
return true;
// Check for whether this entry has been replaced with a new one.
int expected_page_id =
- history_page_ids_[params.pending_history_list_offset];
- if (expected_page_id > 0 && params.page_id != expected_page_id) {
- if (params.page_id < expected_page_id)
+ history_page_ids_[pending_history_list_offset];
+ if (expected_page_id > 0 && page_id != expected_page_id) {
+ if (page_id < expected_page_id)
return true;
// Otherwise we've removed an earlier entry and should have shifted all
// entries left. For now, it's ok to lazily update the list.
// TODO(creis): Notify all live renderers when we remove entries from
// the front of the list, so that we don't hit this case.
- history_page_ids_[params.pending_history_list_offset] = params.page_id;
+ history_page_ids_[pending_history_list_offset] = page_id;
}
return false;
}
-// Stop loading the current page.
-void RenderViewImpl::OnStop() {
- if (webview())
- webview()->mainFrame()->stopLoading();
- FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnStop());
- main_render_frame_->OnStop();
-}
-
void RenderViewImpl::OnCopyImageAt(int x, int y) {
webview()->copyImageAt(WebPoint(x, y));
}
@@ -1208,10 +1449,8 @@ void RenderViewImpl::OnSaveImageAt(int x, int y) {
void RenderViewImpl::OnUpdateTargetURLAck() {
// Check if there is a targeturl waiting to be sent.
- if (target_url_status_ == TARGET_PENDING) {
- Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_,
- pending_target_url_));
- }
+ if (target_url_status_ == TARGET_PENDING)
+ Send(new ViewHostMsg_UpdateTargetURL(routing_id_, pending_target_url_));
target_url_status_ = TARGET_NONE;
}
@@ -1229,7 +1468,7 @@ void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
if (!webview())
return;
- Send(new ViewHostMsg_MoveCaret_ACK(routing_id_));
+ Send(new InputHostMsg_MoveCaret_ACK(routing_id_));
webview()->focusedFrame()->moveCaretSelection(point);
}
@@ -1333,7 +1572,7 @@ void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) {
int id = next_snapshot_id_++;
pending_snapshots_.insert(std::make_pair(id, callback));
ui::LatencyInfo latency_info;
- latency_info.AddLatencyNumber(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
+ latency_info.AddLatencyNumber(ui::WINDOW_OLD_SNAPSHOT_FRAME_NUMBER_COMPONENT,
0,
id);
scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor;
@@ -1344,6 +1583,21 @@ void RenderViewImpl::GetWindowSnapshot(const WindowSnapshotCallback& callback) {
ScheduleCompositeWithForcedRedraw();
}
+void RenderViewImpl::OnForceRedraw(int id) {
+ ui::LatencyInfo latency_info;
+ if (id) {
+ latency_info.AddLatencyNumber(ui::WINDOW_SNAPSHOT_FRAME_NUMBER_COMPONENT,
+ 0,
+ id);
+ }
+ scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor;
+ if (RenderWidgetCompositor* rwc = compositor()) {
+ latency_info_swap_promise_monitor =
+ rwc->CreateLatencyInfoSwapPromiseMonitor(&latency_info).Pass();
+ }
+ ScheduleCompositeWithForcedRedraw();
+}
+
void RenderViewImpl::OnWindowSnapshotCompleted(const int snapshot_id,
const gfx::Size& size, const std::vector<unsigned char>& png) {
@@ -1399,7 +1653,7 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
int32 routing_id = MSG_ROUTING_NONE;
int32 main_frame_routing_id = MSG_ROUTING_NONE;
int32 surface_id = 0;
- int64 cloned_session_storage_namespace_id;
+ int64 cloned_session_storage_namespace_id = 0;
RenderThread::Get()->Send(
new ViewHostMsg_CreateWindow(params,
@@ -1439,8 +1693,7 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
params.disposition == NEW_BACKGROUND_TAB, // hidden
never_visible,
1, // next_page_id
- screen_info_,
- accessibility_mode_);
+ screen_info_);
view->opened_by_user_gesture_ = params.user_gesture;
// Record whether the creator frame is trying to suppress the opener field.
@@ -1461,30 +1714,6 @@ WebWidget* RenderViewImpl::createPopupMenu(blink::WebPopupType popup_type) {
return widget->webwidget();
}
-WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu(
- const WebPopupMenuInfo& popup_menu_info,
- WebExternalPopupMenuClient* popup_menu_client) {
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
- // An IPC message is sent to the browser to build and display the actual
- // popup. The user could have time to click a different select by the time
- // the popup is shown. In that case external_popup_menu_ is non NULL.
- // By returning NULL in that case, we instruct WebKit to cancel that new
- // popup. So from the user perspective, only the first one will show, and
- // will have to close the first one before another one can be shown.
- if (external_popup_menu_)
- return NULL;
- external_popup_menu_.reset(
- new ExternalPopupMenu(this, popup_menu_info, popup_menu_client));
- if (screen_metrics_emulator_) {
- SetExternalPopupOriginAdjustmentsForEmulation(
- external_popup_menu_.get(), screen_metrics_emulator_.get());
- }
- return external_popup_menu_.get();
-#else
- return NULL;
-#endif
-}
-
WebStorageNamespace* RenderViewImpl::createSessionStorageNamespace() {
CHECK(session_storage_namespace_id_ != kInvalidSessionStorageNamespaceId);
return new WebStorageNamespaceImpl(session_storage_namespace_id_);
@@ -1495,6 +1724,13 @@ void RenderViewImpl::printPage(WebLocalFrame* frame) {
PrintPage(frame, handling_input_event_));
}
+void RenderViewImpl::saveImageFromDataURL(const blink::WebString& data_url) {
+ // Note: We should basically send GURL but we use size-limited string instead
+ // in order to send a larger data url to save a image for <canvas> or <img>.
+ if (data_url.length() < kMaxLengthOfDataURLString)
+ Send(new ViewHostMsg_SaveImageFromDataURL(routing_id_, data_url.utf8()));
+}
+
bool RenderViewImpl::enumerateChosenDirectory(
const WebString& path,
WebFileChooserCompletion* chooser_completion) {
@@ -1526,7 +1762,7 @@ void RenderViewImpl::FrameDidStopLoading(WebFrame* frame) {
}
void RenderViewImpl::didCancelCompositionOnSelectionChange() {
- Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
+ Send(new InputHostMsg_ImeCancelComposition(routing_id()));
}
bool RenderViewImpl::handleCurrentKeyboardEvent() {
@@ -1576,6 +1812,7 @@ bool RenderViewImpl::runFileChooser(
ipc_params.accept_types.reserve(params.acceptTypes.size());
for (size_t i = 0; i < params.acceptTypes.size(); ++i)
ipc_params.accept_types.push_back(params.acceptTypes[i]);
+ ipc_params.need_local_path = params.needLocalPath;
#if defined(OS_ANDROID)
ipc_params.capture = params.useMediaCapture;
#endif
@@ -1583,29 +1820,44 @@ bool RenderViewImpl::runFileChooser(
return ScheduleFileChooser(ipc_params, chooser_completion);
}
+void RenderViewImpl::SetValidationMessageDirection(
+ base::string16* wrapped_main_text,
+ blink::WebTextDirection main_text_hint,
+ base::string16* wrapped_sub_text,
+ blink::WebTextDirection sub_text_hint) {
+ if (main_text_hint == blink::WebTextDirectionLeftToRight) {
+ *wrapped_main_text =
+ base::i18n::GetDisplayStringInLTRDirectionality(*wrapped_main_text);
+ } else if (main_text_hint == blink::WebTextDirectionRightToLeft &&
+ !base::i18n::IsRTL()) {
+ base::i18n::WrapStringWithRTLFormatting(wrapped_main_text);
+ }
+
+ if (!wrapped_sub_text->empty()) {
+ if (sub_text_hint == blink::WebTextDirectionLeftToRight) {
+ *wrapped_sub_text =
+ base::i18n::GetDisplayStringInLTRDirectionality(*wrapped_sub_text);
+ } else if (sub_text_hint == blink::WebTextDirectionRightToLeft) {
+ base::i18n::WrapStringWithRTLFormatting(wrapped_sub_text);
+ }
+ }
+}
+
void RenderViewImpl::showValidationMessage(
const blink::WebRect& anchor_in_root_view,
const blink::WebString& main_text,
+ blink::WebTextDirection main_text_hint,
const blink::WebString& sub_text,
- blink::WebTextDirection hint) {
+ blink::WebTextDirection sub_text_hint) {
base::string16 wrapped_main_text = main_text;
base::string16 wrapped_sub_text = sub_text;
- if (hint == blink::WebTextDirectionLeftToRight) {
- wrapped_main_text =
- base::i18n::GetDisplayStringInLTRDirectionality(wrapped_main_text);
- if (!wrapped_sub_text.empty()) {
- wrapped_sub_text =
- base::i18n::GetDisplayStringInLTRDirectionality(wrapped_sub_text);
- }
- } else if (hint == blink::WebTextDirectionRightToLeft
- && !base::i18n::IsRTL()) {
- base::i18n::WrapStringWithRTLFormatting(&wrapped_main_text);
- if (!wrapped_sub_text.empty()) {
- base::i18n::WrapStringWithRTLFormatting(&wrapped_sub_text);
- }
- }
+
+ SetValidationMessageDirection(
+ &wrapped_main_text, main_text_hint, &wrapped_sub_text, sub_text_hint);
+
Send(new ViewHostMsg_ShowValidationMessage(
- routing_id(), anchor_in_root_view, wrapped_main_text, wrapped_sub_text));
+ routing_id(), AdjustValidationMessageAnchor(anchor_in_root_view),
+ wrapped_main_text, wrapped_sub_text));
}
void RenderViewImpl::hideValidationMessage() {
@@ -1614,8 +1866,8 @@ void RenderViewImpl::hideValidationMessage() {
void RenderViewImpl::moveValidationMessage(
const blink::WebRect& anchor_in_root_view) {
- Send(new ViewHostMsg_MoveValidationMessage(routing_id(),
- anchor_in_root_view));
+ Send(new ViewHostMsg_MoveValidationMessage(
+ routing_id(), AdjustValidationMessageAnchor(anchor_in_root_view)));
}
void RenderViewImpl::setStatusText(const WebString& text) {
@@ -1640,7 +1892,7 @@ void RenderViewImpl::UpdateTargetURL(const GURL& url,
// see |ParamTraits<GURL>|.
if (latest_url.possibly_invalid_spec().size() > GetMaxURLChars())
latest_url = GURL();
- Send(new ViewHostMsg_UpdateTargetURL(routing_id_, page_id_, latest_url));
+ Send(new ViewHostMsg_UpdateTargetURL(routing_id_, latest_url));
target_url_ = latest_url;
target_url_status_ = TARGET_INFLIGHT;
}
@@ -1723,6 +1975,9 @@ void RenderViewImpl::focusedNodeChanged(const WebNode& node) {
Send(new ViewHostMsg_FocusedNodeChanged(routing_id_, IsEditableNode(node)));
FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusedNodeChanged(node));
+
+ // TODO(dmazzoni): this should be part of RenderFrameObserver.
+ GetMainRenderFrame()->FocusedNodeChanged(node);
}
void RenderViewImpl::didUpdateLayout() {
@@ -1753,20 +2008,6 @@ int RenderViewImpl::historyForwardListCount() {
return history_list_length_ - historyBackListCount() - 1;
}
-void RenderViewImpl::postAccessibilityEvent(
- const WebAXObject& obj, blink::WebAXEvent event) {
- if (renderer_accessibility_) {
- renderer_accessibility_->HandleWebAccessibilityEvent(obj, event);
- }
-}
-
-void RenderViewImpl::didUpdateInspectorSetting(const WebString& key,
- const WebString& value) {
- Send(new ViewHostMsg_UpdateInspectorSetting(routing_id_,
- key.utf8(),
- value.utf8()));
-}
-
// blink::WebWidgetClient ----------------------------------------------------
void RenderViewImpl::didFocus() {
@@ -1806,15 +2047,6 @@ void RenderViewImpl::show(WebNavigationPolicy policy) {
DCHECK(opener_id_ != MSG_ROUTING_NONE);
- // Force new windows to a popup if they were not opened with a user gesture.
- if (!opened_by_user_gesture_) {
- // We exempt background tabs for compat with older versions of Chrome.
- // TODO(darin): This seems bogus. These should have a user gesture, so
- // we probably don't need this check.
- if (policy != blink::WebNavigationPolicyNewBackgroundTab)
- policy = blink::WebNavigationPolicyNewPopup;
- }
-
// NOTE: initial_pos_ may still have its default values at this point, but
// that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
// browser process will impose a default position otherwise.
@@ -1873,14 +2105,25 @@ void RenderViewImpl::didHandleGestureEvent(
bool event_cancelled) {
RenderWidget::didHandleGestureEvent(event, event_cancelled);
+ if (!event_cancelled) {
+ FOR_EACH_OBSERVER(
+ RenderViewObserver, observers_, DidHandleGestureEvent(event));
+ }
+
+ // TODO(ananta): Piggyback off existing IPCs to communicate this information,
+ // crbug/420130.
+#if defined(OS_WIN)
if (event.type != blink::WebGestureEvent::GestureTap)
return;
+ // TODO(estade): hit test the event against focused node to make sure
+ // the tap actually hit the focused node.
blink::WebTextInputType text_input_type =
GetWebView()->textInputInfo().type;
Send(new ViewHostMsg_FocusedNodeTouched(
routing_id(), text_input_type != blink::WebTextInputTypeNone));
+#endif
}
void RenderViewImpl::initializeLayerTreeView() {
@@ -1891,16 +2134,23 @@ void RenderViewImpl::initializeLayerTreeView() {
if (webview() && webview()->devToolsAgent())
webview()->devToolsAgent()->setLayerTreeId(rwc->GetLayerTreeId());
-#if !defined(OS_MACOSX) // many events are unhandled - http://crbug.com/138003
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- // render_thread may be NULL in tests.
- InputHandlerManager* input_handler_manager =
- render_thread ? render_thread->input_handler_manager() : NULL;
- if (input_handler_manager) {
- input_handler_manager->AddInputHandler(
- routing_id_, rwc->GetInputHandler(), AsWeakPtr());
- }
+ bool use_threaded_event_handling = true;
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // Development flag because many events are still unhandled on Mac.
+ // http://crbug.com/138003
+ use_threaded_event_handling = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableThreadedEventHandlingMac);
#endif
+ if (use_threaded_event_handling) {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ // render_thread may be NULL in tests.
+ InputHandlerManager* input_handler_manager =
+ render_thread ? render_thread->input_handler_manager() : NULL;
+ if (input_handler_manager) {
+ input_handler_manager->AddInputHandler(
+ routing_id_, rwc->GetInputHandler(), AsWeakPtr());
+ }
+ }
}
// blink::WebFrameClient -----------------------------------------------------
@@ -1962,6 +2212,7 @@ void RenderViewImpl::didCreateDataSource(WebLocalFrame* frame,
// Carry over the user agent override flag, if it exists.
if (content_initiated && webview() && webview()->mainFrame() &&
+ webview()->mainFrame()->isWebLocalFrame() &&
webview()->mainFrame()->dataSource()) {
DocumentState* old_document_state =
DocumentState::FromDataSource(webview()->mainFrame()->dataSource());
@@ -1997,9 +2248,9 @@ void RenderViewImpl::didCreateDataSource(WebLocalFrame* frame,
const WebURLRequest& original_request = ds->originalRequest();
const GURL referrer(
original_request.httpHeaderField(WebString::fromUTF8("Referer")));
- if (!referrer.is_empty() &&
- DocumentState::FromDataSource(
- old_frame->dataSource())->was_prefetcher()) {
+ if (!referrer.is_empty() && old_frame->isWebLocalFrame() &&
+ DocumentState::FromDataSource(old_frame->dataSource())
+ ->was_prefetcher()) {
for (; old_frame; old_frame = old_frame->traverseNext(false)) {
WebDataSource* old_frame_ds = old_frame->dataSource();
if (old_frame_ds && referrer == GURL(old_frame_ds->request().url())) {
@@ -2045,8 +2296,8 @@ void RenderViewImpl::PopulateDocumentStateFromPending(
InternalDocumentStateData* internal_data =
InternalDocumentStateData::FromDocumentState(document_state);
- if (!params.url.SchemeIs(url::kJavaScriptScheme) &&
- params.navigation_type == FrameMsg_Navigate_Type::RESTORE) {
+ if (!params.common_params.url.SchemeIs(url::kJavaScriptScheme) &&
+ params.common_params.navigation_type == FrameMsg_Navigate_Type::RESTORE) {
// We're doing a load of a page that was restored from the last session. By
// default this prefers the cache over loading (LOAD_PREFERRING_CACHE) which
// can result in stale data for pages that are set to expire. We explicitly
@@ -2061,17 +2312,18 @@ void RenderViewImpl::PopulateDocumentStateFromPending(
WebURLRequest::UseProtocolCachePolicy);
}
- if (IsReload(params))
+ if (IsReload(params.common_params.navigation_type))
document_state->set_load_type(DocumentState::RELOAD);
- else if (params.page_state.IsValid())
+ else if (params.commit_params.page_state.IsValid())
document_state->set_load_type(DocumentState::HISTORY_LOAD);
else
document_state->set_load_type(DocumentState::NORMAL_LOAD);
- internal_data->set_is_overriding_user_agent(params.is_overriding_user_agent);
+ internal_data->set_is_overriding_user_agent(
+ params.commit_params.is_overriding_user_agent);
internal_data->set_must_reset_scroll_and_scale_state(
- params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
+ params.common_params.navigation_type ==
+ FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
document_state->set_can_load_local_resources(params.can_load_local_resources);
}
@@ -2082,20 +2334,20 @@ NavigationState* RenderViewImpl::CreateNavigationStateFromPending() {
// A navigation resulting from loading a javascript URL should not be treated
// as a browser initiated event. Instead, we want it to look as if the page
// initiated any load resulting from JS execution.
- if (!params.url.SchemeIs(url::kJavaScriptScheme)) {
+ if (!params.common_params.url.SchemeIs(url::kJavaScriptScheme)) {
navigation_state = NavigationState::CreateBrowserInitiated(
params.page_id,
params.pending_history_list_offset,
params.should_clear_history_list,
- params.transition);
+ params.common_params.transition);
navigation_state->set_should_replace_current_entry(
params.should_replace_current_entry);
navigation_state->set_transferred_request_child_id(
params.transferred_request_child_id);
navigation_state->set_transferred_request_request_id(
params.transferred_request_request_id);
- navigation_state->set_allow_download(params.allow_download);
- navigation_state->set_extra_headers(params.extra_headers);
+ navigation_state->set_allow_download(params.common_params.allow_download);
+ navigation_state->set_extra_headers(params.request_params.extra_headers);
} else {
navigation_state = NavigationState::CreateContentInitiated();
}
@@ -2135,6 +2387,9 @@ void RenderViewImpl::didClearWindowObject(WebLocalFrame* frame) {
if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking))
SkiaBenchmarking::Install(frame);
+ if (command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking))
+ GpuBenchmarking::Install(frame);
+
if (command_line.HasSwitch(switches::kEnableMemoryBenchmarking))
MemoryBenchmarkingExtension::Install(frame);
}
@@ -2191,16 +2446,9 @@ BrowserPluginManager* RenderViewImpl::GetBrowserPluginManager() {
return browser_plugin_manager_.get();
}
-void RenderViewImpl::UpdateScrollState(WebFrame* frame) {
- Send(new ViewHostMsg_DidChangeScrollOffset(routing_id_));
-}
-
void RenderViewImpl::didChangeScrollOffset(WebLocalFrame* frame) {
StartNavStateSyncTimerIfNecessary();
- if (webview()->mainFrame() == frame)
- UpdateScrollState(frame);
-
FOR_EACH_OBSERVER(
RenderViewObserver, observers_, DidChangeScrollOffset(frame));
}
@@ -2241,7 +2489,7 @@ bool RenderViewImpl::Send(IPC::Message* message) {
return RenderWidget::Send(message);
}
-RenderFrame* RenderViewImpl::GetMainRenderFrame() {
+RenderFrameImpl* RenderViewImpl::GetMainRenderFrame() {
return main_render_frame_.get();
}
@@ -2249,10 +2497,6 @@ int RenderViewImpl::GetRoutingID() const {
return routing_id_;
}
-int RenderViewImpl::GetPageId() const {
- return page_id_;
-}
-
gfx::Size RenderViewImpl::GetSize() const {
return size();
}
@@ -2291,8 +2535,11 @@ bool RenderViewImpl::IsEditableNode(const WebNode& node) const {
if (node.isElementNode()) {
const WebElement& element = node.toConst<WebElement>();
- if (element.isTextFormControlElement())
- return true;
+ if (element.isTextFormControlElement()) {
+ if (!(element.hasAttribute("readonly") ||
+ element.hasAttribute("disabled")))
+ return true;
+ }
// Also return true if it has an ARIA role of 'textbox'.
for (unsigned i = 0; i < element.attributeCount(); ++i) {
@@ -2307,6 +2554,13 @@ bool RenderViewImpl::IsEditableNode(const WebNode& node) const {
return false;
}
+bool RenderViewImpl::NodeContainsPoint(const WebNode& node,
+ const gfx::Point& point) const {
+ blink::WebHitTestResult hit_test =
+ webview()->hitTestResultAt(WebPoint(point.x(), point.y()));
+ return node.containsIncludingShadowDOM(hit_test.node());
+}
+
bool RenderViewImpl::ShouldDisplayScrollbars(int width, int height) const {
return (!send_preferred_size_changes_ ||
(disable_scrollbars_size_limit_.width() <= width ||
@@ -2344,7 +2598,8 @@ blink::WebPlugin* RenderViewImpl::GetWebPluginForFind() {
return NULL;
WebFrame* main_frame = webview()->mainFrame();
- if (main_frame->document().isPluginDocument())
+ if (main_frame->isWebLocalFrame() &&
+ main_frame->document().isPluginDocument())
return webview()->mainFrame()->document().to<WebPluginDocument>().plugin();
#if defined(ENABLE_PLUGINS)
@@ -2641,6 +2896,22 @@ void RenderViewImpl::OnPostMessageEvent(
base::MessageLoopProxy::current().get());
}
+ WebSerializedScriptValue serialized_script_value;
+ if (params.is_data_raw_string) {
+ v8::HandleScope handle_scope(blink::mainThreadIsolate());
+ v8::Local<v8::Context> context = frame->mainWorldScriptContext();
+ v8::Context::Scope context_scope(context);
+ V8ValueConverterImpl converter;
+ converter.SetDateAllowed(true);
+ converter.SetRegExpAllowed(true);
+ scoped_ptr<base::Value> value(new base::StringValue(params.data));
+ v8::Handle<v8::Value> result_value = converter.ToV8Value(value.get(),
+ context);
+ serialized_script_value = WebSerializedScriptValue::serialize(result_value);
+ } else {
+ serialized_script_value = WebSerializedScriptValue::fromString(params.data);
+ }
+
// Create an event with the message. The final parameter to initMessageEvent
// is the last event ID, which is not used with postMessage.
WebDOMEvent event = frame->document().createEvent("MessageEvent");
@@ -2648,7 +2919,7 @@ void RenderViewImpl::OnPostMessageEvent(
msg_event.initMessageEvent("message",
// |canBubble| and |cancellable| are always false
false, false,
- WebSerializedScriptValue::fromString(params.data),
+ serialized_script_value,
params.source_origin, source_frame, "", channels);
// We must pass in the target_origin to do the security check on this side,
@@ -2746,7 +3017,7 @@ void RenderViewImpl::OnEnumerateDirectoryResponse(
}
void RenderViewImpl::OnFileChooserResponse(
- const std::vector<ui::SelectedFileInfo>& files) {
+ const std::vector<content::FileChooserFileInfo>& files) {
// This could happen if we navigated to a different page before the user
// closed the chooser.
if (file_chooser_completions_.empty())
@@ -2757,9 +3028,15 @@ void RenderViewImpl::OnFileChooserResponse(
files.size());
for (size_t i = 0; i < files.size(); ++i) {
WebFileChooserCompletion::SelectedFileInfo selected_file;
- selected_file.path = files[i].local_path.AsUTF16Unsafe();
+ selected_file.path = files[i].file_path.AsUTF16Unsafe();
selected_file.displayName =
base::FilePath(files[i].display_name).AsUTF16Unsafe();
+ if (files[i].file_system_url.is_valid()) {
+ selected_file.fileSystemURL = files[i].file_system_url;
+ selected_file.length = files[i].length;
+ selected_file.modificationTime = files[i].modification_time.ToDoubleT();
+ selected_file.isDirectory = files[i].is_directory;
+ }
selected_files[i] = selected_file;
}
@@ -2794,7 +3071,7 @@ void RenderViewImpl::OnDisableAutoResize(const gfx::Size& new_size) {
if (!new_size.IsEmpty()) {
Resize(new_size,
physical_backing_size_,
- overdraw_bottom_height_,
+ top_controls_layout_height_,
visible_viewport_size_,
resizer_rect_,
is_fullscreen_,
@@ -2842,14 +3119,10 @@ void RenderViewImpl::OnSetRendererPrefs(
}
#endif // defined(USE_DEFAULT_RENDER_THEME)
- if (RenderThreadImpl::current()) // Will be NULL during unit tests.
- RenderThreadImpl::current()->SetFlingCurveParameters(
- renderer_prefs.touchpad_fling_profile,
- renderer_prefs.touchscreen_fling_profile);
-
// If the zoom level for this page matches the old zoom default, and this
// is not a plugin, update the zoom level to match the new default.
- if (webview() && !webview()->mainFrame()->document().isPluginDocument() &&
+ if (webview() && webview()->mainFrame()->isWebLocalFrame() &&
+ !webview()->mainFrame()->document().isPluginDocument() &&
!ZoomValuesEqual(old_zoom_level,
renderer_preferences_.default_zoom_level) &&
ZoomValuesEqual(webview()->zoomLevel(), old_zoom_level)) {
@@ -2875,7 +3148,7 @@ void RenderViewImpl::OnOrientationChange() {
observers_,
OrientationChangeEvent());
- webview()->mainFrame()->sendOrientationChangeEvent();
+ webview()->mainFrame()->toWebLocalFrame()->sendOrientationChangeEvent();
}
void RenderViewImpl::OnPluginActionAt(const gfx::Point& location,
@@ -2961,7 +3234,8 @@ void RenderViewImpl::NavigateToSwappedOutURL(blink::WebFrame* frame) {
CHECK(is_swapped_out_ || rf->is_swapped_out());
GURL swappedOutURL(kSwappedOutURL);
WebURLRequest request(swappedOutURL);
- frame->loadRequest(request);
+ if (frame->isWebLocalFrame())
+ frame->loadRequest(request);
}
void RenderViewImpl::OnClosePage() {
@@ -2997,6 +3271,7 @@ void RenderViewImpl::OnMoveOrResizeStarted() {
}
void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
+ TRACE_EVENT0("renderer", "RenderViewImpl::OnResize");
if (webview()) {
webview()->hidePopups();
if (send_preferred_size_changes_) {
@@ -3004,7 +3279,6 @@ void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
ShouldDisplayScrollbars(params.new_size.width(),
params.new_size.height()));
}
- UpdateScrollState(webview()->mainFrame());
}
gfx::Size old_visible_viewport_size = visible_viewport_size_;
@@ -3013,6 +3287,10 @@ void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
if (old_visible_viewport_size != visible_viewport_size_)
has_scrolled_focused_editable_node_into_rect_ = false;
+
+ FOR_EACH_OBSERVER(RenderViewObserver,
+ observers_,
+ Resized());
}
void RenderViewImpl::DidInitiatePaint() {
@@ -3063,19 +3341,22 @@ void RenderViewImpl::DidFlushPaint() {
return;
WebFrame* main_frame = webview()->mainFrame();
+ for (WebFrame* frame = main_frame; frame;
+ frame = frame->traverseNext(false)) {
+ // TODO(nasko): This is a hack for the case in which the top-level
+ // frame is being rendered in another process. It will not
+ // behave correctly for out of process iframes.
+ if (frame->isWebLocalFrame()) {
+ main_frame = frame;
+ break;
+ }
+ }
// If we have a provisional frame we are between the start and commit stages
// of loading and we don't want to save stats.
if (!main_frame->provisionalDataSource()) {
WebDataSource* ds = main_frame->dataSource();
DocumentState* document_state = DocumentState::FromDataSource(ds);
- InternalDocumentStateData* data =
- InternalDocumentStateData::FromDocumentState(document_state);
- if (data->did_first_visually_non_empty_layout() &&
- !data->did_first_visually_non_empty_paint()) {
- data->set_did_first_visually_non_empty_paint(true);
- Send(new ViewHostMsg_DidFirstVisuallyNonEmptyPaint(routing_id_));
- }
// TODO(jar): The following code should all be inside a method, probably in
// NavigatorState.
@@ -3091,7 +3372,19 @@ void RenderViewImpl::DidFlushPaint() {
}
gfx::Vector2d RenderViewImpl::GetScrollOffset() {
- WebSize scroll_offset = webview()->mainFrame()->scrollOffset();
+ WebFrame* main_frame = webview()->mainFrame();
+ for (WebFrame* frame = main_frame; frame;
+ frame = frame->traverseNext(false)) {
+ // TODO(nasko): This is a hack for the case in which the top-level
+ // frame is being rendered in another process. It will not
+ // behave correctly for out of process iframes.
+ if (frame->isWebLocalFrame()) {
+ main_frame = frame;
+ break;
+ }
+ }
+
+ WebSize scroll_offset = main_frame->scrollOffset();
return gfx::Vector2d(scroll_offset.width, scroll_offset.height);
}
@@ -3107,25 +3400,6 @@ void RenderViewImpl::OnSetBackgroundOpaque(bool opaque) {
compositor_->setHasTransparentBackground(!opaque);
}
-void RenderViewImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
- if (accessibility_mode_ == new_mode)
- return;
- accessibility_mode_ = new_mode;
- if (renderer_accessibility_) {
- delete renderer_accessibility_;
- renderer_accessibility_ = NULL;
- }
- if (accessibility_mode_ == AccessibilityModeOff)
- return;
-
- if (accessibility_mode_ & AccessibilityModeFlagFullTree)
- renderer_accessibility_ = new RendererAccessibilityComplete(this);
-#if !defined(OS_ANDROID)
- else
- renderer_accessibility_ = new RendererAccessibilityFocusOnly(this);
-#endif
-}
-
void RenderViewImpl::OnSetActive(bool active) {
if (webview())
webview()->setIsActive(active);
@@ -3268,8 +3542,9 @@ void RenderViewImpl::OnWasHidden() {
#endif // ENABLE_PLUGINS
}
-void RenderViewImpl::OnWasShown(bool needs_repainting) {
- RenderWidget::OnWasShown(needs_repainting);
+void RenderViewImpl::OnWasShown(bool needs_repainting,
+ const ui::LatencyInfo& latency_info) {
+ RenderWidget::OnWasShown(needs_repainting, latency_info);
#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
RenderThreadImpl::current()->video_capture_impl_manager()->
@@ -3297,7 +3572,7 @@ void RenderViewImpl::OnWasShown(bool needs_repainting) {
GURL RenderViewImpl::GetURLForGraphicsContext3D() {
DCHECK(webview());
- if (webview()->mainFrame())
+ if (webview()->mainFrame()->isWebLocalFrame())
return GURL(webview()->mainFrame()->document().url());
else
return GURL("chrome://gpu/RenderViewImpl::CreateGraphicsContext3D");
@@ -3419,35 +3694,34 @@ void RenderViewImpl::SetDeviceScaleFactor(float device_scale_factor) {
RenderWidget::SetDeviceScaleFactor(device_scale_factor);
if (webview()) {
webview()->setDeviceScaleFactor(device_scale_factor);
- webview()->settings()->setAcceleratedCompositingForFixedPositionEnabled(
- ShouldUseFixedPositionCompositing(device_scale_factor_));
- webview()->settings()->setAcceleratedCompositingForOverflowScrollEnabled(
- ShouldUseAcceleratedCompositingForOverflowScroll(device_scale_factor_));
+ webview()->settings()->setPreferCompositingToLCDTextEnabled(
+ PreferCompositingToLCDText(device_scale_factor_));
webview()->settings()->setAcceleratedCompositingForTransitionEnabled(
ShouldUseTransitionCompositing(device_scale_factor_));
- webview()->settings()->
- setAcceleratedCompositingForFixedRootBackgroundEnabled(
- ShouldUseAcceleratedFixedRootBackground(device_scale_factor_));
- webview()->settings()->setCompositedScrollingForFramesEnabled(
- ShouldUseCompositedScrollingForFrames(device_scale_factor_));
}
if (auto_resize_mode_)
AutoResizeCompositor();
if (browser_plugin_manager_.get())
- browser_plugin_manager_->UpdateDeviceScaleFactor(device_scale_factor_);
+ browser_plugin_manager_->UpdateDeviceScaleFactor();
}
bool RenderViewImpl::SetDeviceColorProfile(
const std::vector<char>& profile) {
bool changed = RenderWidget::SetDeviceColorProfile(profile);
if (changed && webview()) {
- // TODO(noel): notify the webview() of the color profile change so it
- // can update and repaint all color profiled page elements.
+ WebVector<char> colorProfile = profile;
+ webview()->setDeviceColorProfile(colorProfile);
}
return changed;
}
+void RenderViewImpl::ResetDeviceColorProfileForTesting() {
+ RenderWidget::ResetDeviceColorProfileForTesting();
+ if (webview())
+ webview()->resetDeviceColorProfile();
+}
+
ui::TextInputType RenderViewImpl::GetTextInputType() {
#if defined(ENABLE_PLUGINS)
if (focused_pepper_plugin_)
@@ -3472,7 +3746,7 @@ void RenderViewImpl::GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) {
RenderWidget::GetSelectionBounds(start, end);
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
void RenderViewImpl::GetCompositionCharacterBounds(
std::vector<gfx::Rect>* bounds) {
DCHECK(bounds);
@@ -3617,8 +3891,6 @@ void RenderViewImpl::zoomLimitsChanged(double minimum_level,
void RenderViewImpl::zoomLevelChanged() {
double zoom_level = webview()->zoomLevel();
- FOR_EACH_OBSERVER(RenderViewObserver, observers_, ZoomLevelChanged());
-
// Do not send empty URLs to the browser when we are just setting the default
// zoom level (from RendererPreferences) before the first navigation.
if (!webview()->mainFrame()->document().url().isEmpty()) {
@@ -3639,22 +3911,25 @@ double RenderViewImpl::zoomFactorToZoomLevel(double factor) const {
}
void RenderViewImpl::registerProtocolHandler(const WebString& scheme,
- const WebURL& base_url,
const WebURL& url,
const WebString& title) {
bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
- GURL base(base_url);
- GURL absolute_url = base.Resolve(base::UTF16ToUTF8(url.string()));
- if (base.GetOrigin() != absolute_url.GetOrigin()) {
- return;
- }
Send(new ViewHostMsg_RegisterProtocolHandler(routing_id_,
base::UTF16ToUTF8(scheme),
- absolute_url,
+ url,
title,
user_gesture));
}
+void RenderViewImpl::unregisterProtocolHandler(const WebString& scheme,
+ const WebURL& url) {
+ bool user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
+ Send(new ViewHostMsg_UnregisterProtocolHandler(routing_id_,
+ base::UTF16ToUTF8(scheme),
+ url,
+ user_gesture));
+}
+
blink::WebPageVisibilityState RenderViewImpl::visibilityState() const {
blink::WebPageVisibilityState current_state = is_hidden() ?
blink::WebPageVisibilityStateHidden :
@@ -3669,9 +3944,9 @@ blink::WebPageVisibilityState RenderViewImpl::visibilityState() const {
}
blink::WebPushClient* RenderViewImpl::webPushClient() {
- if (!push_messaging_dispatcher_)
- push_messaging_dispatcher_ = new PushMessagingDispatcher(this);
- return push_messaging_dispatcher_;
+ // TODO(mvanouwerkerk): Remove this method once the Push API code in Blink
+ // has also switched over to Frame.
+ return main_render_frame_->pushClient();
}
void RenderViewImpl::draggableRegionsChanged() {
@@ -3746,44 +4021,14 @@ void RenderViewImpl::DismissDateTimeDialog() {
#endif // defined(OS_ANDROID)
-#if defined(OS_MACOSX)
-void RenderViewImpl::OnSelectPopupMenuItem(int selected_index) {
- if (external_popup_menu_ == NULL)
- return;
- external_popup_menu_->DidSelectItem(selected_index);
- external_popup_menu_.reset();
-}
-#endif
-
-#if defined(OS_ANDROID)
-void RenderViewImpl::OnSelectPopupMenuItems(
- bool canceled,
- const std::vector<int>& selected_indices) {
- // It is possible to receive more than one of these calls if the user presses
- // a select faster than it takes for the show-select-popup IPC message to make
- // it to the browser UI thread. Ignore the extra-messages.
- // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
- if (!external_popup_menu_)
- return;
-
- external_popup_menu_->DidSelectItems(canceled, selected_indices);
- external_popup_menu_.reset();
-}
-#endif
-
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
-void RenderViewImpl::DidHideExternalPopupMenu() {
- // We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close
- // is called. Otherwise, createExternalPopupMenu() for new popup will fail.
- external_popup_menu_.reset();
-}
-#endif
-
-void RenderViewImpl::OnShowContextMenu(const gfx::Point& location) {
- context_menu_source_type_ = ui::MENU_SOURCE_TOUCH_EDIT_MENU;
- touch_editing_context_menu_location_ = location;
+void RenderViewImpl::OnShowContextMenu(
+ ui::MenuSourceType source_type, const gfx::Point& location) {
+ context_menu_source_type_ = source_type;
+ has_host_context_menu_location_ = true;
+ host_context_menu_location_ = location;
if (webview())
webview()->showContextMenu();
+ has_host_context_menu_location_ = false;
}
void RenderViewImpl::OnEnableViewSourceMode() {
@@ -3795,34 +4040,30 @@ void RenderViewImpl::OnEnableViewSourceMode() {
main_frame->enableViewSourceMode(true);
}
-void RenderViewImpl::OnDisownOpener() {
- if (!webview())
- return;
-
- WebFrame* main_frame = webview()->mainFrame();
- if (main_frame && main_frame->opener())
- main_frame->setOpener(NULL);
-}
-
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
bool RenderViewImpl::didTapMultipleTargets(
- const blink::WebGestureEvent& event,
+ const WebSize& inner_viewport_offset,
+ const WebRect& touch_rect,
const WebVector<WebRect>& target_rects) {
+ if (!switches::IsLinkDisambiguationPopupEnabled())
+ return false;
+
// Never show a disambiguation popup when accessibility is enabled,
// as this interferes with "touch exploration".
- bool matchesAccessibilityModeComplete =
- (accessibility_mode_ & AccessibilityModeComplete) ==
- AccessibilityModeComplete;
- if (matchesAccessibilityModeComplete)
+ AccessibilityMode accessibility_mode =
+ GetMainRenderFrame()->accessibility_mode();
+ bool matches_accessibility_mode_complete =
+ (accessibility_mode & AccessibilityModeComplete) ==
+ AccessibilityModeComplete;
+ if (matches_accessibility_mode_complete)
return false;
- gfx::Rect finger_rect(
- event.x - event.data.tap.width / 2, event.y - event.data.tap.height / 2,
- event.data.tap.width, event.data.tap.height);
+ // The touch_rect, target_rects and zoom_rect are in the outer viewport
+ // reference frame.
gfx::Rect zoom_rect;
float new_total_scale =
DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
- finger_rect, target_rects, GetSize(),
+ touch_rect, target_rects, GetSize(),
gfx::Rect(webview()->mainFrame()->visibleContentRect()).size(),
device_scale_factor_ * webview()->pageScaleFactor(), &zoom_rect);
if (!new_total_scale)
@@ -3862,8 +4103,13 @@ bool RenderViewImpl::didTapMultipleTargets(
webwidget_->paintCompositedDeprecated(&canvas, zoom_rect);
}
+ gfx::Rect zoom_rect_in_screen =
+ zoom_rect - gfx::Vector2d(inner_viewport_offset.width,
+ inner_viewport_offset.height);
+
gfx::Rect physical_window_zoom_rect = gfx::ToEnclosingRect(
- ClientRectToPhysicalWindowRect(gfx::RectF(zoom_rect)));
+ ClientRectToPhysicalWindowRect(gfx::RectF(zoom_rect_in_screen)));
+
Send(new ViewHostMsg_ShowDisambiguationPopup(routing_id_,
physical_window_zoom_rect,
canvas_size,
@@ -3880,7 +4126,7 @@ bool RenderViewImpl::didTapMultipleTargets(
return handled;
}
-#endif
+#endif // defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
unsigned RenderViewImpl::GetLocalSessionHistoryLengthForTesting() const {
return history_list_length_;
@@ -3905,39 +4151,10 @@ void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
params.screen_info = screen_info_;
params.screen_info.deviceScaleFactor = factor;
params.new_size = size();
+ params.visible_viewport_size = visible_viewport_size_;
params.physical_backing_size =
gfx::ToCeiledSize(gfx::ScaleSize(size(), factor));
- params.overdraw_bottom_height = 0.f;
- params.resizer_rect = WebRect();
- params.is_fullscreen = is_fullscreen();
- OnResize(params);
-}
-
-void RenderViewImpl::SetScreenOrientationForTesting(
- const blink::WebScreenOrientationType& orientation) {
- ViewMsg_Resize_Params params;
- params.screen_info = screen_info_;
- params.screen_info.orientationType = orientation;
- // FIXME(ostap): This relationship between orientationType and
- // orientationAngle is temporary. The test should be able to specify
- // the angle in addition to the orientation type.
- switch (orientation) {
- case blink::WebScreenOrientationLandscapePrimary:
- params.screen_info.orientationAngle = 90;
- break;
- case blink::WebScreenOrientationLandscapeSecondary:
- params.screen_info.orientationAngle = -90;
- break;
- case blink::WebScreenOrientationPortraitSecondary:
- params.screen_info.orientationAngle = 180;
- break;
- default:
- params.screen_info.orientationAngle = 0;
- }
- params.new_size = size();
- params.physical_backing_size = gfx::ToCeiledSize(
- gfx::ScaleSize(size(), params.screen_info.deviceScaleFactor));
- params.overdraw_bottom_height = 0.f;
+ params.top_controls_layout_height = 0.f;
params.resizer_rect = WebRect();
params.is_fullscreen = is_fullscreen();
OnResize(params);
@@ -3953,7 +4170,7 @@ void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) {
rootWindowRect().y,
new_size.width(),
new_size.height());
- ResizeSynchronously(new_position);
+ ResizeSynchronously(new_position, new_size);
}
void RenderViewImpl::UseSynchronousResizeModeForTesting(bool enable) {
@@ -3992,6 +4209,11 @@ void RenderViewImpl::DidStopLoadingIcons() {
if (TouchEnabled())
icon_types |= WebIconURL::TypeTouchPrecomposed | WebIconURL::TypeTouch;
+ // Favicons matter only for the top-level frame. If it is a WebRemoteFrame,
+ // just return early.
+ if (webview()->mainFrame()->isWebRemoteFrame())
+ return;
+
WebVector<WebIconURL> icon_urls =
webview()->mainFrame()->iconURLs(icon_types);
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index 324c4c77eeb..67adc197503 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -26,19 +26,21 @@
#include "content/common/content_export.h"
#include "content/common/drag_event_source_info.h"
#include "content/common/edit_command.h"
+#include "content/common/frame_message_enums.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/navigation_gesture.h"
+#include "content/common/navigation_params.h"
#include "content/common/view_message_enums.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/referrer.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/stop_find_action.h"
#include "content/public/common/top_controls_state.h"
+#include "content/public/common/web_preferences.h"
#include "content/public/renderer/render_view.h"
#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_widget.h"
-#include "content/renderer/renderer_date_time_picker.h"
#include "content/renderer/stats_collection_observer.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
@@ -57,10 +59,10 @@
#include "third_party/WebKit/public/web/WebViewClient.h"
#include "ui/base/window_open_disposition.h"
#include "ui/surface/transport_dib.h"
-#include "webkit/common/webpreferences.h"
#if defined(OS_ANDROID)
#include "content/renderer/android/content_detector.h"
+#include "content/renderer/android/renderer_date_time_picker.h"
#include "third_party/WebKit/public/web/WebContentDetectionResult.h"
#endif
@@ -82,10 +84,6 @@ namespace base {
class CommandLine;
}
-namespace ui {
-struct SelectedFileInfo;
-} // namespace ui
-
namespace blink {
class WebApplicationCacheHost;
class WebApplicationCacheHostClient;
@@ -101,7 +99,6 @@ class WebPeerConnection00HandlerClient;
class WebMouseEvent;
class WebPeerConnectionHandler;
class WebPeerConnectionHandlerClient;
-class WebSocketStreamHandle;
class WebSpeechRecognizer;
class WebStorageNamespace;
class WebTouchEvent;
@@ -118,29 +115,23 @@ struct WebWindowFeatures;
#if defined(OS_ANDROID)
class WebHitTestResult;
#endif
-}
-
-namespace webkit_glue {
-class WebURLResponseExtraDataImpl;
-}
+} // namespace blink
namespace content {
+
class BrowserPluginManager;
class DevToolsAgent;
class DocumentState;
-class ExternalPopupMenu;
-class FaviconHelper;
class HistoryController;
class HistoryEntry;
class ImageResourceFetcher;
-class MediaStreamDispatcher;
class MouseLockDispatcher;
class NavigationState;
+class PageState;
class PepperPluginInstanceImpl;
-class PushMessagingDispatcher;
+class RenderViewImplTest;
class RenderViewObserver;
class RenderViewTest;
-class RendererAccessibility;
class RendererDateTimePicker;
class RendererWebColorChooserImpl;
class SpeechRecognitionDispatcher;
@@ -148,6 +139,7 @@ class WebPluginDelegateProxy;
struct DropData;
struct FaviconURL;
struct FileChooserParams;
+struct FileChooserFileInfo;
struct RenderViewImplParams;
#if defined(OS_ANDROID)
@@ -156,7 +148,7 @@ class WebMediaPlayerProxyAndroid;
//
// RenderView is an object that manages a WebView object, and provides a
-// communication interface with an embedding application process
+// communication interface with an embedding application process.
//
class CONTENT_EXPORT RenderViewImpl
: public RenderWidget,
@@ -186,8 +178,7 @@ class CONTENT_EXPORT RenderViewImpl
bool hidden,
bool never_visible,
int32 next_page_id,
- const blink::WebScreenInfo& screen_info,
- AccessibilityMode accessibility_mode);
+ const blink::WebScreenInfo& screen_info);
// Used by content_layouttest_support to hook into the creation of
// RenderViewImpls.
@@ -219,21 +210,6 @@ class CONTENT_EXPORT RenderViewImpl
send_content_state_immediately_ = value;
}
- RenderFrameImpl* main_render_frame() { return main_render_frame_.get(); }
-
- // TODO(jam): move to RenderFrameImpl
- MediaStreamDispatcher* media_stream_dispatcher() {
- return media_stream_dispatcher_;
- }
-
- AccessibilityMode accessibility_mode() {
- return accessibility_mode_;
- }
-
- RendererAccessibility* renderer_accessibility() {
- return renderer_accessibility_;
- }
-
MouseLockDispatcher* mouse_lock_dispatcher() {
return mouse_lock_dispatcher_;
}
@@ -267,9 +243,6 @@ class CONTENT_EXPORT RenderViewImpl
#if defined(OS_ANDROID)
void DismissDateTimeDialog();
#endif
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
- void DidHideExternalPopupMenu();
-#endif
bool is_loading() const { return frames_in_progress_ != 0; }
@@ -354,12 +327,9 @@ class CONTENT_EXPORT RenderViewImpl
// Change the device scale factor and force the compositor to resize.
void SetDeviceScaleFactorForTesting(float factor);
- // Change screen orientation and force the compositor to resize.
- void SetScreenOrientationForTesting(
- const blink::WebScreenOrientationType& orientation);
-
// Change the device ICC color profile while running a layout test.
void SetDeviceColorProfileForTesting(const std::vector<char>& color_profile);
+ void ResetDeviceColorProfileForTesting() override;
// Used to force the size of a window when running layout tests.
void ForceResizeForTesting(const gfx::Size& new_size);
@@ -373,7 +343,7 @@ class CONTENT_EXPORT RenderViewImpl
// IPC::Listener implementation ----------------------------------------------
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// blink::WebWidgetClient implementation ------------------------------------
@@ -388,8 +358,8 @@ class CONTENT_EXPORT RenderViewImpl
virtual void requestPointerUnlock();
virtual bool isPointerLocked();
virtual void didHandleGestureEvent(const blink::WebGestureEvent& event,
- bool event_cancelled) OVERRIDE;
- virtual void initializeLayerTreeView() OVERRIDE;
+ bool event_cancelled) override;
+ virtual void initializeLayerTreeView() override;
// blink::WebViewClient implementation --------------------------------------
@@ -400,26 +370,29 @@ class CONTENT_EXPORT RenderViewImpl
blink::WebNavigationPolicy policy,
bool suppress_opener);
virtual blink::WebWidget* createPopupMenu(blink::WebPopupType popup_type);
- virtual blink::WebExternalPopupMenu* createExternalPopupMenu(
- const blink::WebPopupMenuInfo& popup_menu_info,
- blink::WebExternalPopupMenuClient* popup_menu_client);
virtual blink::WebStorageNamespace* createSessionStorageNamespace();
virtual void printPage(blink::WebLocalFrame* frame);
virtual bool enumerateChosenDirectory(
const blink::WebString& path,
blink::WebFileChooserCompletion* chooser_completion);
+ virtual void saveImageFromDataURL(const blink::WebString& data_url);
virtual void didCancelCompositionOnSelectionChange();
virtual bool handleCurrentKeyboardEvent();
virtual bool runFileChooser(
const blink::WebFileChooserParams& params,
blink::WebFileChooserCompletion* chooser_completion);
+ void SetValidationMessageDirection(base::string16* main_text,
+ blink::WebTextDirection main_text_hint,
+ base::string16* sub_text,
+ blink::WebTextDirection sub_text_hint);
virtual void showValidationMessage(const blink::WebRect& anchor_in_root_view,
const blink::WebString& main_text,
+ blink::WebTextDirection main_text_hint,
const blink::WebString& sub_text,
- blink::WebTextDirection hint) OVERRIDE;
- virtual void hideValidationMessage() OVERRIDE;
+ blink::WebTextDirection hint) override;
+ virtual void hideValidationMessage() override;
virtual void moveValidationMessage(
- const blink::WebRect& anchor_in_root_view) OVERRIDE;
+ const blink::WebRect& anchor_in_root_view) override;
virtual void setStatusText(const blink::WebString& text);
virtual void setMouseOverURL(const blink::WebURL& url);
virtual void setKeyboardFocusURL(const blink::WebURL& url);
@@ -433,28 +406,26 @@ class CONTENT_EXPORT RenderViewImpl
virtual void focusPrevious();
virtual void focusedNodeChanged(const blink::WebNode& node);
virtual void didUpdateLayout();
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(TOOLKIT_VIEWS)
virtual bool didTapMultipleTargets(
- const blink::WebGestureEvent& event,
+ const blink::WebSize& inner_viewport_offset,
+ const blink::WebRect& touch_rect,
const blink::WebVector<blink::WebRect>& target_rects);
#endif
virtual blink::WebString acceptLanguages();
virtual void navigateBackForwardSoon(int offset);
virtual int historyBackListCount();
virtual int historyForwardListCount();
- virtual void postAccessibilityEvent(
- const blink::WebAXObject& obj, blink::WebAXEvent event);
- virtual void didUpdateInspectorSetting(const blink::WebString& key,
- const blink::WebString& value);
virtual blink::WebSpeechRecognizer* speechRecognizer();
virtual void zoomLimitsChanged(double minimum_level, double maximum_level);
virtual void zoomLevelChanged();
virtual double zoomLevelToZoomFactor(double zoom_level) const;
virtual double zoomFactorToZoomLevel(double factor) const;
virtual void registerProtocolHandler(const blink::WebString& scheme,
- const blink::WebURL& base_url,
const blink::WebURL& url,
const blink::WebString& title);
+ virtual void unregisterProtocolHandler(const blink::WebString& scheme,
+ const blink::WebURL& url);
virtual blink::WebPageVisibilityState visibilityState() const;
virtual blink::WebPushClient* webPushClient();
virtual void draggableRegionsChanged();
@@ -477,36 +448,37 @@ class CONTENT_EXPORT RenderViewImpl
virtual void didSerializeDataForFrame(
const blink::WebURL& frame_url,
const blink::WebCString& data,
- PageSerializationStatus status) OVERRIDE;
+ PageSerializationStatus status) override;
// RenderView implementation -------------------------------------------------
- virtual bool Send(IPC::Message* message) OVERRIDE;
- virtual RenderFrame* GetMainRenderFrame() OVERRIDE;
- virtual int GetRoutingID() const OVERRIDE;
- virtual int GetPageId() const OVERRIDE;
- virtual gfx::Size GetSize() const OVERRIDE;
- virtual WebPreferences& GetWebkitPreferences() OVERRIDE;
- virtual void SetWebkitPreferences(const WebPreferences& preferences) OVERRIDE;
- virtual blink::WebView* GetWebView() OVERRIDE;
- virtual blink::WebElement GetFocusedElement() const OVERRIDE;
- virtual bool IsEditableNode(const blink::WebNode& node) const OVERRIDE;
- virtual bool ShouldDisplayScrollbars(int width, int height) const OVERRIDE;
- virtual int GetEnabledBindings() const OVERRIDE;
- virtual bool GetContentStateImmediately() const OVERRIDE;
- virtual blink::WebPageVisibilityState GetVisibilityState() const OVERRIDE;
- virtual void DidStartLoading() OVERRIDE;
- virtual void DidStopLoading() OVERRIDE;
- virtual void Repaint(const gfx::Size& size) OVERRIDE;
- virtual void SetEditCommandForNextKeyEvent(const std::string& name,
- const std::string& value) OVERRIDE;
- virtual void ClearEditCommands() OVERRIDE;
- virtual SSLStatus GetSSLStatusOfFrame(blink::WebFrame* frame) const OVERRIDE;
- virtual const std::string& GetAcceptLanguages() const OVERRIDE;
+ bool Send(IPC::Message* message) override;
+ RenderFrameImpl* GetMainRenderFrame() override;
+ int GetRoutingID() const override;
+ gfx::Size GetSize() const override;
+ WebPreferences& GetWebkitPreferences() override;
+ void SetWebkitPreferences(const WebPreferences& preferences) override;
+ blink::WebView* GetWebView() override;
+ blink::WebElement GetFocusedElement() const override;
+ bool IsEditableNode(const blink::WebNode& node) const override;
+ bool NodeContainsPoint(const blink::WebNode& node,
+ const gfx::Point& point) const override;
+ bool ShouldDisplayScrollbars(int width, int height) const override;
+ int GetEnabledBindings() const override;
+ bool GetContentStateImmediately() const override;
+ blink::WebPageVisibilityState GetVisibilityState() const override;
+ void DidStartLoading() override;
+ void DidStopLoading() override;
+ void Repaint(const gfx::Size& size) override;
+ void SetEditCommandForNextKeyEvent(const std::string& name,
+ const std::string& value) override;
+ void ClearEditCommands() override;
+ SSLStatus GetSSLStatusOfFrame(blink::WebFrame* frame) const override;
+ const std::string& GetAcceptLanguages() const override;
#if defined(OS_ANDROID)
virtual void UpdateTopControlsState(TopControlsState constraints,
TopControlsState current,
- bool animate) OVERRIDE;
+ bool animate) override;
#endif
bool uses_temporary_zoom_level() const { return uses_temporary_zoom_level_; }
@@ -521,77 +493,71 @@ class CONTENT_EXPORT RenderViewImpl
protected:
// RenderWidget overrides:
- virtual void OnClose() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void OnResize(const ViewMsg_Resize_Params& params) OVERRIDE;
- virtual void DidInitiatePaint() OVERRIDE;
- virtual void DidFlushPaint() OVERRIDE;
- virtual gfx::Vector2d GetScrollOffset() OVERRIDE;
- virtual void DidHandleKeyEvent() OVERRIDE;
- virtual bool WillHandleMouseEvent(
- const blink::WebMouseEvent& event) OVERRIDE;
- virtual bool WillHandleGestureEvent(
- const blink::WebGestureEvent& event) OVERRIDE;
- virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) OVERRIDE;
- virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) OVERRIDE;
- virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE;
- virtual void OnSetFocus(bool enable) OVERRIDE;
- virtual void OnWasHidden() OVERRIDE;
- virtual void OnWasShown(bool needs_repainting) OVERRIDE;
- virtual GURL GetURLForGraphicsContext3D() OVERRIDE;
- virtual void OnImeSetComposition(
+ void OnClose() override;
+ void Close() override;
+ void OnResize(const ViewMsg_Resize_Params& params) override;
+ void DidInitiatePaint() override;
+ void DidFlushPaint() override;
+ gfx::Vector2d GetScrollOffset() override;
+ void DidHandleKeyEvent() override;
+ bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override;
+ bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override;
+ void DidHandleMouseEvent(const blink::WebMouseEvent& event) override;
+ void DidHandleTouchEvent(const blink::WebTouchEvent& event) override;
+ bool HasTouchEventHandlersAt(const gfx::Point& point) const override;
+ void OnSetFocus(bool enable) override;
+ void OnWasHidden() override;
+ void OnWasShown(bool needs_repainting,
+ const ui::LatencyInfo& latency_info) override;
+ GURL GetURLForGraphicsContext3D() override;
+ void OnImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
int selection_start,
- int selection_end) OVERRIDE;
- virtual void OnImeConfirmComposition(const base::string16& text,
- const gfx::Range& replacement_range,
- bool keep_selection) OVERRIDE;
- virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
- virtual bool SetDeviceColorProfile(
- const std::vector<char>& color_profile) OVERRIDE;
- virtual void OnOrientationChange() OVERRIDE;
- virtual ui::TextInputType GetTextInputType() OVERRIDE;
- virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) OVERRIDE;
-#if defined(OS_MACOSX) || defined(USE_AURA)
- virtual void GetCompositionCharacterBounds(
- std::vector<gfx::Rect>* character_bounds) OVERRIDE;
- virtual void GetCompositionRange(gfx::Range* range) OVERRIDE;
+ int selection_end) override;
+ void OnImeConfirmComposition(const base::string16& text,
+ const gfx::Range& replacement_range,
+ bool keep_selection) override;
+ void SetDeviceScaleFactor(float device_scale_factor) override;
+ bool SetDeviceColorProfile(const std::vector<char>& color_profile) override;
+ void OnOrientationChange() override;
+ ui::TextInputType GetTextInputType() override;
+ void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) override;
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
+ void GetCompositionCharacterBounds(
+ std::vector<gfx::Rect>* character_bounds) override;
+ void GetCompositionRange(gfx::Range* range) override;
#endif
- virtual bool CanComposeInline() OVERRIDE;
- virtual void DidCommitCompositorFrame() OVERRIDE;
- virtual void InstrumentWillBeginFrame(int frame_id) OVERRIDE;
- virtual void InstrumentDidBeginFrame() OVERRIDE;
- virtual void InstrumentDidCancelFrame() OVERRIDE;
- virtual void InstrumentWillComposite() OVERRIDE;
+ bool CanComposeInline() override;
+ void DidCommitCompositorFrame() override;
+ void InstrumentWillBeginFrame(int frame_id) override;
+ void InstrumentDidBeginFrame() override;
+ void InstrumentDidCancelFrame() override;
+ void InstrumentWillComposite() override;
protected:
explicit RenderViewImpl(RenderViewImplParams* params);
void Initialize(RenderViewImplParams* params);
- virtual void SetScreenMetricsEmulationParameters(
- float device_scale_factor,
- const gfx::Point& root_layer_offset,
- float root_layer_scale) OVERRIDE;
+ void SetScreenMetricsEmulationParameters(float device_scale_factor,
+ const gfx::Point& root_layer_offset,
+ float root_layer_scale) override;
// Do not delete directly. This class is reference counted.
virtual ~RenderViewImpl();
private:
// For unit tests.
- friend class ExternalPopupMenuTest;
friend class PepperDeviceTest;
- friend class RendererAccessibilityTest;
+ friend class RenderViewImplTest;
friend class RenderViewTest;
+ friend class RendererAccessibilityTest;
// TODO(nasko): Temporarily friend RenderFrameImpl, so we don't duplicate
// utility functions needed in both classes, while we move frame specific
// code away from this class.
friend class RenderFrameImpl;
- FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange);
- FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, NormalCase);
- FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, DecideNavigationPolicyForWebUI);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
DidFailProvisionalLoadWithErrorForError);
@@ -606,7 +572,6 @@ class CONTENT_EXPORT RenderViewImpl
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnHandleKeyboardEvent);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnImeTypeChanged);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavStateChanged);
- FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetAccessibilityMode);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetTextDirection);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnUpdateWebPreferences);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
@@ -654,7 +619,7 @@ class CONTENT_EXPORT RenderViewImpl
void didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame);
void didChangeScrollOffset(blink::WebLocalFrame* frame);
- static bool IsReload(const FrameMsg_Navigate_Params& params);
+ static bool IsReload(FrameMsg_Navigate_Type::Value navigation_type);
static Referrer GetReferrerFromRequest(
blink::WebFrame* frame,
@@ -669,9 +634,6 @@ class CONTENT_EXPORT RenderViewImpl
// Sends a message and runs a nested message loop.
bool SendAndRunNestedMessageLoop(IPC::SyncMessage* message);
- // Called when the "pinned to left/right edge" state needs to be updated.
- void UpdateScrollState(blink::WebFrame* frame);
-
// IPC message handlers ------------------------------------------------------
//
// The documentation for these functions should be in
@@ -685,7 +647,8 @@ class CONTENT_EXPORT RenderViewImpl
void OnCancelDownload(int32 download_id);
void OnClearFocusedElement();
void OnClosePage();
- void OnShowContextMenu(const gfx::Point& location);
+ void OnShowContextMenu(ui::MenuSourceType source_type,
+ const gfx::Point& location);
void OnCopyImageAt(int x, int y);
void OnSaveImageAt(int x, int y);
void OnDeterminePageLanguage();
@@ -714,7 +677,7 @@ class CONTENT_EXPORT RenderViewImpl
void OnEnumerateDirectoryResponse(int id,
const std::vector<base::FilePath>& paths);
void OnFileChooserResponse(
- const std::vector<ui::SelectedFileInfo>& files);
+ const std::vector<content::FileChooserFileInfo>& files);
void OnFind(int request_id,
const base::string16&,
const blink::WebFindOptions&);
@@ -731,7 +694,6 @@ class CONTENT_EXPORT RenderViewImpl
void OnPostMessageEvent(const ViewMsg_PostMessage_Params& params);
void OnReleaseDisambiguationPopupBitmap(const cc::SharedBitmapId& id);
void OnResetPageEncodingToDefault();
- void OnSetAccessibilityMode(AccessibilityMode new_mode);
void OnSetActive(bool active);
void OnSetBackgroundOpaque(bool opaque);
void OnExitFullscreen();
@@ -742,7 +704,6 @@ class CONTENT_EXPORT RenderViewImpl
void OnSetWebUIProperty(const std::string& name, const std::string& value);
void OnSetZoomLevelForLoadingURL(const GURL& url, double zoom_level);
void OnSetZoomLevelForView(bool uses_temporary_zoom_level, double level);
- void OnStop();
void OnStopFinding(StopFindAction action);
void OnSuppressDialogsUntilSwapOut();
void OnThemeChanged();
@@ -750,24 +711,22 @@ class CONTENT_EXPORT RenderViewImpl
void OnUpdateWebPreferences(const WebPreferences& prefs);
void OnZoom(PageZoom zoom);
void OnEnableViewSourceMode();
- void OnDisownOpener();
void OnWindowSnapshotCompleted(const int snapshot_id,
const gfx::Size& size, const std::vector<unsigned char>& png);
+ void OnForceRedraw(int request_id);
void OnSelectWordAroundCaret();
#if defined(OS_ANDROID)
void OnActivateNearestFindResult(int request_id, float x, float y);
void OnFindMatchRects(int current_version);
- void OnSelectPopupMenuItems(bool canceled,
- const std::vector<int>& selected_indices);
void OnUndoScrollFocusedEditableNodeIntoRect();
void OnUpdateTopControlsState(bool enable_hiding,
bool enable_showing,
bool animate);
void OnExtractSmartClipData(const gfx::Rect& rect);
#elif defined(OS_MACOSX)
+ void OnGetRenderedText();
void OnPluginImeCompositionCompleted(const base::string16& text,
int plugin_id);
- void OnSelectPopupMenuItem(int selected_index);
void OnSetInLiveResize(bool in_live_resize);
void OnSetWindowVisibility(bool visible);
void OnWindowFrameChanged(const gfx::Rect& window_frame,
@@ -781,27 +740,15 @@ class CONTENT_EXPORT RenderViewImpl
// Check whether the preferred size has changed.
void CheckPreferredSize();
- // This callback is triggered when DownloadFavicon completes, either
- // succesfully or with a failure. See DownloadFavicon for more
- // details.
- void DidDownloadFavicon(ImageResourceFetcher* fetcher,
- const SkBitmap& image);
-
- // Requests to download a favicon image. When done, the RenderView is notified
- // by way of DidDownloadFavicon. Returns true if the request was successfully
- // started, false otherwise. id is used to uniquely identify the request and
- // passed back to the DidDownloadFavicon method. If the image has multiple
- // frames, the frame whose size is image_size is returned. If the image
- // doesn't have a frame at the specified size, the first is returned.
- bool DownloadFavicon(int id, const GURL& image_url, int image_size);
-
// Called to get the WebPlugin to handle find requests in the document.
// Returns NULL if there is no such WebPlugin.
blink::WebPlugin* GetWebPluginForFind();
// Returns true if the |params| navigation is to an entry that has been
// cropped due to a recent navigation the browser did not know about.
- bool IsBackForwardToStaleEntry(const FrameMsg_Navigate_Params& params,
+ bool IsBackForwardToStaleEntry(const PageState& state,
+ int pending_history_list_offset,
+ int32 page_id,
bool is_reload);
// Make the given |frame| show an empty, unscriptable page.
@@ -1042,28 +989,15 @@ class CONTENT_EXPORT RenderViewImpl
// along with the RenderView automatically. This is why we just store
// weak references.
- // The push messaging dispatcher attached to this view, lazily initialized.
- PushMessagingDispatcher* push_messaging_dispatcher_;
-
// The speech recognition dispatcher attached to this view, lazily
// initialized.
SpeechRecognitionDispatcher* speech_recognition_dispatcher_;
- // MediaStream dispatcher attached to this view; lazily initialized.
- MediaStreamDispatcher* media_stream_dispatcher_;
-
// BrowserPluginManager attached to this view; lazily initialized.
scoped_refptr<BrowserPluginManager> browser_plugin_manager_;
DevToolsAgent* devtools_agent_;
- // The current accessibility mode.
- AccessibilityMode accessibility_mode_;
-
- // Only valid if |accessibility_mode_| is anything other than
- // AccessibilityModeOff.
- RendererAccessibility* renderer_accessibility_;
-
// Mouse Lock dispatcher attached to this view.
MouseLockDispatcher* mouse_lock_dispatcher_;
@@ -1139,11 +1073,6 @@ class CONTENT_EXPORT RenderViewImpl
// Shall be cleared as soon as the next key event is processed.
EditCommands edit_commands_;
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
- // The external popup for the currently showing select popup.
- scoped_ptr<ExternalPopupMenu> external_popup_menu_;
-#endif
-
// All the registered observers. We expect this list to be small, so vector
// is fine.
ObserverList<RenderViewObserver> observers_;
diff --git a/chromium/content/renderer/render_view_impl_android.cc b/chromium/content/renderer/render_view_impl_android.cc
index 679da548f91..50b10aa5667 100644
--- a/chromium/content/renderer/render_view_impl_android.cc
+++ b/chromium/content/renderer/render_view_impl_android.cc
@@ -14,9 +14,12 @@
namespace content {
// Check content::TopControlsState and cc::TopControlsState are kept in sync.
-COMPILE_ASSERT(int(SHOWN) == int(cc::SHOWN), mismatching_enums);
-COMPILE_ASSERT(int(HIDDEN) == int(cc::HIDDEN), mismatching_enums);
-COMPILE_ASSERT(int(BOTH) == int(cc::BOTH), mismatching_enums);
+COMPILE_ASSERT(int(TOP_CONTROLS_STATE_SHOWN) == int(cc::SHOWN),
+ mismatching_enums);
+COMPILE_ASSERT(int(TOP_CONTROLS_STATE_HIDDEN) == int(cc::HIDDEN),
+ mismatching_enums);
+COMPILE_ASSERT(int(TOP_CONTROLS_STATE_BOTH) == int(cc::BOTH),
+ mismatching_enums);
cc::TopControlsState ContentToCcTopControlsState(
TopControlsState state) {
@@ -65,8 +68,12 @@ void RenderViewImpl::didScrollWithKeyboard(const blink::WebSize& delta) {
}
void RenderViewImpl::OnExtractSmartClipData(const gfx::Rect& rect) {
+ blink::WebString clip_text;
+ blink::WebString clip_html;
+ blink::WebRect clip_rect;
+ webview()->extractSmartClipData(rect, clip_text, clip_html, clip_rect);
Send(new ViewHostMsg_SmartClipDataExtracted(
- routing_id_, webview()->getSmartClipData(rect)));
+ routing_id_, clip_text, clip_html, clip_rect));
}
} // namespace content
diff --git a/chromium/content/renderer/render_view_impl_params.cc b/chromium/content/renderer/render_view_impl_params.cc
index 81522d8edc5..6864a3d0edc 100644
--- a/chromium/content/renderer/render_view_impl_params.cc
+++ b/chromium/content/renderer/render_view_impl_params.cc
@@ -22,8 +22,7 @@ RenderViewImplParams::RenderViewImplParams(
bool hidden,
bool never_visible,
int32 next_page_id,
- const blink::WebScreenInfo& screen_info,
- AccessibilityMode accessibility_mode)
+ const blink::WebScreenInfo& screen_info)
: opener_id(opener_id),
window_was_created_with_opener(window_was_created_with_opener),
renderer_prefs(renderer_prefs),
@@ -39,8 +38,7 @@ RenderViewImplParams::RenderViewImplParams(
hidden(hidden),
never_visible(never_visible),
next_page_id(next_page_id),
- screen_info(screen_info),
- accessibility_mode(accessibility_mode) {}
+ screen_info(screen_info) {}
RenderViewImplParams::~RenderViewImplParams() {}
diff --git a/chromium/content/renderer/render_view_impl_params.h b/chromium/content/renderer/render_view_impl_params.h
index a439447d689..ad9a26c61d3 100644
--- a/chromium/content/renderer/render_view_impl_params.h
+++ b/chromium/content/renderer/render_view_impl_params.h
@@ -11,8 +11,6 @@
#include "content/common/content_export.h"
#include "content/common/view_message_enums.h"
-struct WebPreferences;
-
namespace blink {
struct WebScreenInfo;
}
@@ -20,6 +18,7 @@ struct WebScreenInfo;
namespace content {
struct RendererPreferences;
+struct WebPreferences;
// Container for all parameters passed to RenderViewImpl's constructor.
struct CONTENT_EXPORT RenderViewImplParams {
@@ -38,8 +37,7 @@ struct CONTENT_EXPORT RenderViewImplParams {
bool hidden,
bool never_visible,
int32 next_page_id,
- const blink::WebScreenInfo& screen_info,
- AccessibilityMode accessibility_mode);
+ const blink::WebScreenInfo& screen_info);
~RenderViewImplParams();
int32 opener_id;
@@ -58,7 +56,6 @@ struct CONTENT_EXPORT RenderViewImplParams {
bool never_visible;
int32 next_page_id;
const blink::WebScreenInfo& screen_info;
- AccessibilityMode accessibility_mode;
};
} // namespace content
diff --git a/chromium/content/renderer/render_view_linux.cc b/chromium/content/renderer/render_view_linux.cc
index 41f558c2085..f4ef02e7435 100644
--- a/chromium/content/renderer/render_view_linux.cc
+++ b/chromium/content/renderer/render_view_linux.cc
@@ -11,19 +11,20 @@ using blink::WebFontRendering;
namespace content {
-static SkPaint::Hinting RendererPreferencesToSkiaHinting(
+namespace {
+
+SkPaint::Hinting RendererPreferencesToSkiaHinting(
const RendererPreferences& prefs) {
if (!prefs.should_antialias_text) {
// When anti-aliasing is off, GTK maps all non-zero hinting settings to
// 'Normal' hinting so we do the same. Otherwise, folks who have 'Slight'
// hinting selected will see readable text in everything expect Chromium.
switch (prefs.hinting) {
- case RENDERER_PREFERENCES_HINTING_NONE:
+ case gfx::FontRenderParams::HINTING_NONE:
return SkPaint::kNo_Hinting;
- case RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT:
- case RENDERER_PREFERENCES_HINTING_SLIGHT:
- case RENDERER_PREFERENCES_HINTING_MEDIUM:
- case RENDERER_PREFERENCES_HINTING_FULL:
+ case gfx::FontRenderParams::HINTING_SLIGHT:
+ case gfx::FontRenderParams::HINTING_MEDIUM:
+ case gfx::FontRenderParams::HINTING_FULL:
return SkPaint::kNormal_Hinting;
default:
NOTREACHED();
@@ -32,85 +33,62 @@ static SkPaint::Hinting RendererPreferencesToSkiaHinting(
}
switch (prefs.hinting) {
- case RENDERER_PREFERENCES_HINTING_SYSTEM_DEFAULT:
- return SkPaint::kNormal_Hinting;
- case RENDERER_PREFERENCES_HINTING_NONE:
- return SkPaint::kNo_Hinting;
- case RENDERER_PREFERENCES_HINTING_SLIGHT:
- return SkPaint::kSlight_Hinting;
- case RENDERER_PREFERENCES_HINTING_MEDIUM:
- return SkPaint::kNormal_Hinting;
- case RENDERER_PREFERENCES_HINTING_FULL:
- return SkPaint::kFull_Hinting;
- default:
- NOTREACHED();
- return SkPaint::kNormal_Hinting;
- }
-}
-
-static SkFontHost::LCDOrder RendererPreferencesToSkiaLCDOrder(
- RendererPreferencesSubpixelRenderingEnum subpixel) {
- switch (subpixel) {
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB:
- return SkFontHost::kRGB_LCDOrder;
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR:
- return SkFontHost::kBGR_LCDOrder;
- default:
- NOTREACHED();
- return SkFontHost::kRGB_LCDOrder;
- }
-}
-
-static SkFontHost::LCDOrientation
- RendererPreferencesToSkiaLCDOrientation(
- RendererPreferencesSubpixelRenderingEnum subpixel) {
- switch (subpixel) {
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_RGB:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_BGR:
- return SkFontHost::kHorizontal_LCDOrientation;
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VRGB:
- case RENDERER_PREFERENCES_SUBPIXEL_RENDERING_VBGR:
- return SkFontHost::kVertical_LCDOrientation;
- default:
- NOTREACHED();
- return SkFontHost::kHorizontal_LCDOrientation;
- }
+ case gfx::FontRenderParams::HINTING_NONE: return SkPaint::kNo_Hinting;
+ case gfx::FontRenderParams::HINTING_SLIGHT: return SkPaint::kSlight_Hinting;
+ case gfx::FontRenderParams::HINTING_MEDIUM: return SkPaint::kNormal_Hinting;
+ case gfx::FontRenderParams::HINTING_FULL: return SkPaint::kFull_Hinting;
+ default:
+ NOTREACHED();
+ return SkPaint::kNormal_Hinting;
+ }
}
-static bool RendererPreferencesToAntiAliasFlag(
+SkFontHost::LCDOrder RendererPreferencesToSkiaLCDOrder(
const RendererPreferences& prefs) {
- return prefs.should_antialias_text;
+ switch (prefs.subpixel_rendering) {
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
+ return SkFontHost::kRGB_LCDOrder;
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
+ return SkFontHost::kBGR_LCDOrder;
+ default:
+ NOTREACHED();
+ return SkFontHost::kRGB_LCDOrder;
+ }
}
-static bool RendererPreferencesToSubpixelRenderingFlag(
+SkFontHost::LCDOrientation RendererPreferencesToSkiaLCDOrientation(
const RendererPreferences& prefs) {
- if (prefs.subpixel_rendering !=
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_SYSTEM_DEFAULT &&
- prefs.subpixel_rendering !=
- RENDERER_PREFERENCES_SUBPIXEL_RENDERING_NONE) {
- return true;
+ switch (prefs.subpixel_rendering) {
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
+ return SkFontHost::kHorizontal_LCDOrientation;
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
+ case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
+ return SkFontHost::kVertical_LCDOrientation;
+ default:
+ NOTREACHED();
+ return SkFontHost::kHorizontal_LCDOrientation;
}
- return false;
}
+} // namespace
+
void RenderViewImpl::UpdateFontRenderingFromRendererPrefs() {
const RendererPreferences& prefs = renderer_preferences_;
WebFontRendering::setHinting(RendererPreferencesToSkiaHinting(prefs));
WebFontRendering::setAutoHint(prefs.use_autohinter);
WebFontRendering::setUseBitmaps(prefs.use_bitmaps);
- WebFontRendering::setLCDOrder(
- RendererPreferencesToSkiaLCDOrder(prefs.subpixel_rendering));
+ WebFontRendering::setLCDOrder(RendererPreferencesToSkiaLCDOrder(prefs));
WebFontRendering::setLCDOrientation(
- RendererPreferencesToSkiaLCDOrientation(prefs.subpixel_rendering));
- WebFontRendering::setAntiAlias(RendererPreferencesToAntiAliasFlag(prefs));
+ RendererPreferencesToSkiaLCDOrientation(prefs));
+ WebFontRendering::setAntiAlias(prefs.should_antialias_text);
WebFontRendering::setSubpixelRendering(
- RendererPreferencesToSubpixelRenderingFlag(prefs));
+ prefs.subpixel_rendering !=
+ gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE);
WebFontRendering::setSubpixelPositioning(prefs.use_subpixel_positioning);
}
diff --git a/chromium/content/renderer/render_view_mouse_lock_dispatcher.h b/chromium/content/renderer/render_view_mouse_lock_dispatcher.h
index 4e16c5797a4..a2ee5b563ce 100644
--- a/chromium/content/renderer/render_view_mouse_lock_dispatcher.h
+++ b/chromium/content/renderer/render_view_mouse_lock_dispatcher.h
@@ -18,15 +18,15 @@ class RenderViewMouseLockDispatcher : public MouseLockDispatcher,
public RenderViewObserver {
public:
explicit RenderViewMouseLockDispatcher(RenderViewImpl* render_view_impl);
- virtual ~RenderViewMouseLockDispatcher();
+ ~RenderViewMouseLockDispatcher() override;
private:
// MouseLockDispatcher implementation.
- virtual void SendLockMouseRequest(bool unlocked_by_target) OVERRIDE;
- virtual void SendUnlockMouseRequest() OVERRIDE;
+ void SendLockMouseRequest(bool unlocked_by_target) override;
+ void SendUnlockMouseRequest() override;
// RenderView::Observer implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnLockMouseACK(bool succeeded);
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index d91647ea5ab..2592258bd63 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -16,6 +16,7 @@
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "cc/debug/benchmark_instrumentation.h"
@@ -37,7 +38,9 @@
#include "content/renderer/gpu/compositor_output_surface.h"
#include "content/renderer/gpu/compositor_software_output_device.h"
#include "content/renderer/gpu/delegated_compositor_output_surface.h"
+#include "content/renderer/gpu/frame_swap_message_queue.h"
#include "content/renderer/gpu/mailbox_output_surface.h"
+#include "content/renderer/gpu/queue_message_swap_promise.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/input_handler_manager.h"
@@ -46,7 +49,7 @@
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/renderer_webkitplatformsupport_impl.h"
+#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/resizing_mode_selector.h"
#include "ipc/ipc_sync_message.h"
#include "skia/ext/platform_canvas.h"
@@ -61,6 +64,7 @@
#include "third_party/WebKit/public/web/WebPopupMenu.h"
#include "third_party/WebKit/public/web/WebPopupMenuInfo.h"
#include "third_party/WebKit/public/web/WebRange.h"
+#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/skia/include/core/SkShader.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/frame_time.h"
@@ -73,7 +77,7 @@
#if defined(OS_ANDROID)
#include <android/keycodes.h>
-#include "base/android/sys_utils.h"
+#include "base/android/build_info.h"
#include "content/renderer/android/synchronous_compositor_factory.h"
#endif
@@ -149,6 +153,11 @@ ui::TextInputMode ConvertInputMode(const blink::WebString& input_mode) {
return it->second;
}
+bool IsThreadedCompositingEnabled() {
+ content::RenderThreadImpl* impl = content::RenderThreadImpl::current();
+ return impl && !!impl->compositor_message_loop_proxy().get();
+}
+
// TODO(brianderson): Replace the hard-coded threshold with a fraction of
// the BeginMainFrame interval.
// 4166us will allow 1/4 of a 60Hz interval or 1/2 of a 120Hz interval to
@@ -185,10 +194,11 @@ class RenderWidget::ScreenMetricsEmulator {
void OnUpdateScreenRectsMessage(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
void OnShowContextMenu(ContextMenuParams* params);
+ gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
private:
void Reapply();
- void Apply(float overdraw_bottom_height,
+ void Apply(float top_controls_layout_height,
gfx::Rect resizer_rect,
bool is_fullscreen);
@@ -225,7 +235,7 @@ RenderWidget::ScreenMetricsEmulator::ScreenMetricsEmulator(
original_screen_info_ = widget_->screen_info_;
original_view_screen_rect_ = widget_->view_screen_rect_;
original_window_screen_rect_ = widget_->window_screen_rect_;
- Apply(widget_->overdraw_bottom_height_, widget_->resizer_rect_,
+ Apply(widget_->top_controls_layout_height_, widget_->resizer_rect_,
widget_->is_fullscreen_);
}
@@ -236,9 +246,13 @@ RenderWidget::ScreenMetricsEmulator::~ScreenMetricsEmulator() {
widget_->SetScreenMetricsEmulationParameters(0.f, gfx::Point(), 1.f);
widget_->view_screen_rect_ = original_view_screen_rect_;
widget_->window_screen_rect_ = original_window_screen_rect_;
- widget_->Resize(original_size_, original_physical_backing_size_,
- widget_->overdraw_bottom_height_, original_visible_viewport_size_,
- widget_->resizer_rect_, widget_->is_fullscreen_, NO_RESIZE_ACK);
+ widget_->Resize(original_size_,
+ original_physical_backing_size_,
+ widget_->top_controls_layout_height_,
+ original_visible_viewport_size_,
+ widget_->resizer_rect_,
+ widget_->is_fullscreen_,
+ NO_RESIZE_ACK);
}
void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams(
@@ -248,12 +262,12 @@ void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams(
}
void RenderWidget::ScreenMetricsEmulator::Reapply() {
- Apply(widget_->overdraw_bottom_height_, widget_->resizer_rect_,
+ Apply(widget_->top_controls_layout_height_, widget_->resizer_rect_,
widget_->is_fullscreen_);
}
void RenderWidget::ScreenMetricsEmulator::Apply(
- float overdraw_bottom_height,
+ float top_controls_layout_height,
gfx::Rect resizer_rect,
bool is_fullscreen) {
applied_widget_rect_.set_size(gfx::Size(params_.viewSize));
@@ -312,7 +326,7 @@ void RenderWidget::ScreenMetricsEmulator::Apply(
gfx::Size physical_backing_size = gfx::ToCeiledSize(gfx::ScaleSize(
original_size_, original_screen_info_.deviceScaleFactor));
widget_->Resize(applied_widget_rect_.size(), physical_backing_size,
- overdraw_bottom_height, applied_widget_rect_.size(), resizer_rect,
+ top_controls_layout_height, applied_widget_rect_.size(), resizer_rect,
is_fullscreen, NO_RESIZE_ACK);
}
@@ -324,7 +338,7 @@ void RenderWidget::ScreenMetricsEmulator::OnResizeMessage(
original_physical_backing_size_ = params.physical_backing_size;
original_screen_info_ = params.screen_info;
original_visible_viewport_size_ = params.visible_viewport_size;
- Apply(params.overdraw_bottom_height, params.resizer_rect,
+ Apply(params.top_controls_layout_height, params.resizer_rect,
params.is_fullscreen);
if (need_ack) {
@@ -351,6 +365,14 @@ void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu(
params->y += offset_.y();
}
+gfx::Rect RenderWidget::ScreenMetricsEmulator::AdjustValidationMessageAnchor(
+ const gfx::Rect& anchor) {
+ gfx::Rect scaled = gfx::ToEnclosedRect(gfx::ScaleRect(anchor, scale_));
+ scaled.set_x(scaled.x() + offset_.x());
+ scaled.set_y(scaled.y() + offset_.y());
+ return scaled;
+}
+
// RenderWidget ---------------------------------------------------------------
RenderWidget::RenderWidget(blink::WebPopupType popup_type,
@@ -363,7 +385,7 @@ RenderWidget::RenderWidget(blink::WebPopupType popup_type,
webwidget_(NULL),
opener_id_(MSG_ROUTING_NONE),
init_complete_(false),
- overdraw_bottom_height_(0.f),
+ top_controls_layout_height_(0.f),
next_paint_flags_(0),
auto_resize_mode_(false),
need_update_rect_for_auto_resize_(false),
@@ -377,17 +399,18 @@ RenderWidget::RenderWidget(blink::WebPopupType popup_type,
handling_event_type_(WebInputEvent::Undefined),
ignore_ack_for_mouse_move_from_debugger_(false),
closing_(false),
+ host_closing_(false),
is_swapped_out_(swapped_out),
input_method_is_active_(false),
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT),
+ text_input_flags_(0),
can_compose_inline_(true),
popup_type_(popup_type),
pending_window_rect_count_(0),
suppress_next_char_events_(false),
screen_info_(screen_info),
device_scale_factor_(screen_info_.deviceScaleFactor),
- is_threaded_compositing_enabled_(false),
current_event_latency_info_(NULL),
next_output_surface_id_(0),
#if defined(OS_ANDROID)
@@ -396,14 +419,14 @@ RenderWidget::RenderWidget(blink::WebPopupType popup_type,
body_background_color_(SK_ColorWHITE),
#endif
popup_origin_scale_for_emulation_(0.f),
+ frame_swap_message_queue_(new FrameSwapMessageQueue()),
resizing_mode_selector_(new ResizingModeSelector()),
- context_menu_source_type_(ui::MENU_SOURCE_MOUSE) {
+ context_menu_source_type_(ui::MENU_SOURCE_MOUSE),
+ has_host_context_menu_location_(false) {
if (!swapped_out)
RenderProcess::current()->AddRefProcess();
DCHECK(RenderThread::Get());
- is_threaded_compositing_enabled_ =
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableThreadedCompositing);
+ device_color_profile_.push_back('0');
}
RenderWidget::~RenderWidget() {
@@ -497,13 +520,20 @@ void RenderWidget::SetSwappedOut(bool is_swapped_out) {
// If we are swapping out, we will call ReleaseProcess, allowing the process
// to exit if all of its RenderViews are swapped out. We wait until the
- // WasSwappedOut call to do this, to avoid showing the sad tab.
+ // WasSwappedOut call to do this, to allow the unload handler to finish.
// If we are swapping in, we call AddRefProcess to prevent the process from
// exiting.
- if (!is_swapped_out)
+ if (!is_swapped_out_)
RenderProcess::current()->AddRefProcess();
}
+void RenderWidget::WasSwappedOut() {
+ // If we have been swapped out and no one else is using this process,
+ // it's safe to exit now.
+ CHECK(is_swapped_out_);
+ RenderProcess::current()->ReleaseProcess();
+}
+
void RenderWidget::EnableScreenMetricsEmulation(
const WebDeviceEmulationParams& params) {
if (!screen_metrics_emulator_)
@@ -527,6 +557,12 @@ void RenderWidget::SetPopupOriginAdjustmentsForEmulation(
device_scale_factor_ = screen_info_.deviceScaleFactor;
}
+gfx::Rect RenderWidget::AdjustValidationMessageAnchor(const gfx::Rect& anchor) {
+ if (screen_metrics_emulator_)
+ return screen_metrics_emulator_->AdjustValidationMessageAnchor(anchor);
+ return anchor;
+}
+
void RenderWidget::SetScreenMetricsEmulationParameters(
float device_scale_factor,
const gfx::Point& root_layer_offset,
@@ -565,6 +601,8 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(InputMsg_HandleInputEvent, OnHandleInputEvent)
IPC_MESSAGE_HANDLER(InputMsg_CursorVisibilityChange,
OnCursorVisibilityChange)
+ IPC_MESSAGE_HANDLER(InputMsg_ImeSetComposition, OnImeSetComposition)
+ IPC_MESSAGE_HANDLER(InputMsg_ImeConfirmComposition, OnImeConfirmComposition)
IPC_MESSAGE_HANDLER(InputMsg_MouseCaptureLost, OnMouseCaptureLost)
IPC_MESSAGE_HANDLER(InputMsg_SetFocus, OnSetFocus)
IPC_MESSAGE_HANDLER(InputMsg_SyntheticGestureCompleted,
@@ -572,17 +610,15 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
+ IPC_MESSAGE_HANDLER(ViewMsg_ColorProfile, OnColorProfile)
IPC_MESSAGE_HANDLER(ViewMsg_ChangeResizeRect, OnChangeResizeRect)
IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown)
- IPC_MESSAGE_HANDLER(ViewMsg_WasSwappedOut, OnWasSwappedOut)
IPC_MESSAGE_HANDLER(ViewMsg_SetInputMethodActive, OnSetInputMethodActive)
IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowShown, OnCandidateWindowShown)
IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowUpdated,
OnCandidateWindowUpdated)
IPC_MESSAGE_HANDLER(ViewMsg_CandidateWindowHidden, OnCandidateWindowHidden)
- IPC_MESSAGE_HANDLER(ViewMsg_ImeSetComposition, OnImeSetComposition)
- IPC_MESSAGE_HANDLER(ViewMsg_ImeConfirmComposition, OnImeConfirmComposition)
IPC_MESSAGE_HANDLER(ViewMsg_Repaint, OnRepaint)
IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection)
IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
@@ -615,7 +651,7 @@ bool RenderWidget::Send(IPC::Message* message) {
void RenderWidget::Resize(const gfx::Size& new_size,
const gfx::Size& physical_backing_size,
- float overdraw_bottom_height,
+ float top_controls_layout_height,
const gfx::Size& visible_viewport_size,
const gfx::Rect& resizer_rect,
bool is_fullscreen,
@@ -633,11 +669,11 @@ void RenderWidget::Resize(const gfx::Size& new_size,
if (compositor_) {
compositor_->setViewportSize(new_size, physical_backing_size);
- compositor_->SetOverdrawBottomHeight(overdraw_bottom_height);
+ compositor_->SetTopControlsLayoutHeight(top_controls_layout_height);
}
physical_backing_size_ = physical_backing_size;
- overdraw_bottom_height_ = overdraw_bottom_height;
+ top_controls_layout_height_ = top_controls_layout_height;
visible_viewport_size_ = visible_viewport_size;
resizer_rect_ = resizer_rect;
@@ -647,6 +683,8 @@ void RenderWidget::Resize(const gfx::Size& new_size,
WillToggleFullscreen();
is_fullscreen_ = is_fullscreen;
+ webwidget_->setTopControlsLayoutHeight(top_controls_layout_height);
+
if (size_ != new_size) {
size_ = new_size;
@@ -680,9 +718,16 @@ void RenderWidget::Resize(const gfx::Size& new_size,
DCHECK(resize_ack != SEND_RESIZE_ACK || next_paint_is_resize_ack());
}
-void RenderWidget::ResizeSynchronously(const gfx::Rect& new_position) {
- Resize(new_position.size(), new_position.size(), overdraw_bottom_height_,
- visible_viewport_size_, gfx::Rect(), is_fullscreen_, NO_RESIZE_ACK);
+void RenderWidget::ResizeSynchronously(
+ const gfx::Rect& new_position,
+ const gfx::Size& visible_viewport_size) {
+ Resize(new_position.size(),
+ new_position.size(),
+ top_controls_layout_height_,
+ visible_viewport_size,
+ gfx::Rect(),
+ is_fullscreen_,
+ NO_RESIZE_ACK);
view_screen_rect_ = new_position;
window_screen_rect_ = new_position;
if (!did_show_)
@@ -735,13 +780,18 @@ void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) {
screen_info_ = params.screen_info;
SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
Resize(params.new_size, params.physical_backing_size,
- params.overdraw_bottom_height, params.visible_viewport_size,
- params.resizer_rect, params.is_fullscreen, SEND_RESIZE_ACK);
+ params.top_controls_layout_height,
+ params.visible_viewport_size, params.resizer_rect,
+ params.is_fullscreen, SEND_RESIZE_ACK);
if (orientation_changed)
OnOrientationChange();
}
+void RenderWidget::OnColorProfile(const std::vector<char>& color_profile) {
+ SetDeviceColorProfile(color_profile);
+}
+
void RenderWidget::OnChangeResizeRect(const gfx::Rect& resizer_rect) {
if (resizer_rect_ == resizer_rect)
return;
@@ -758,7 +808,8 @@ void RenderWidget::OnWasHidden() {
WasHidden());
}
-void RenderWidget::OnWasShown(bool needs_repainting) {
+void RenderWidget::OnWasShown(bool needs_repainting,
+ const ui::LatencyInfo& latency_info) {
TRACE_EVENT0("renderer", "RenderWidget::OnWasShown");
// During shutdown we can just ignore this message.
if (!webwidget_)
@@ -773,19 +824,15 @@ void RenderWidget::OnWasShown(bool needs_repainting) {
return;
// Generate a full repaint.
- if (compositor_)
+ if (compositor_) {
+ ui::LatencyInfo swap_latency_info(latency_info);
+ scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor(
+ compositor_->CreateLatencyInfoSwapPromiseMonitor(&swap_latency_info));
compositor_->SetNeedsForcedRedraw();
+ }
scheduleComposite();
}
-void RenderWidget::OnWasSwappedOut() {
- // If we have been swapped out and no one else is using this process,
- // it's safe to exit now. If we get swapped back in, we will call
- // AddRefProcess in SetSwappedOut.
- if (is_swapped_out_)
- RenderProcess::current()->ReleaseProcess();
-}
-
void RenderWidget::OnRequestMoveAck() {
DCHECK(pending_window_rect_count_);
pending_window_rect_count_--;
@@ -803,7 +850,8 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
SynchronousCompositorFactory::GetInstance()) {
- return factory->CreateOutputSurface(routing_id());
+ return factory->CreateOutputSurface(routing_id(),
+ frame_swap_message_queue_);
}
#endif
@@ -824,52 +872,51 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
uint32 output_surface_id = next_output_surface_id_++;
if (command_line.HasSwitch(switches::kEnableDelegatedRenderer)) {
- DCHECK(is_threaded_compositing_enabled_);
+ DCHECK(IsThreadedCompositingEnabled());
return scoped_ptr<cc::OutputSurface>(
- new DelegatedCompositorOutputSurface(
- routing_id(),
- output_surface_id,
- context_provider));
+ new DelegatedCompositorOutputSurface(routing_id(),
+ output_surface_id,
+ context_provider,
+ frame_swap_message_queue_));
}
if (!context_provider.get()) {
scoped_ptr<cc::SoftwareOutputDevice> software_device(
new CompositorSoftwareOutputDevice());
- return scoped_ptr<cc::OutputSurface>(new CompositorOutputSurface(
- routing_id(),
- output_surface_id,
- NULL,
- software_device.Pass(),
- true));
+ return scoped_ptr<cc::OutputSurface>(
+ new CompositorOutputSurface(routing_id(),
+ output_surface_id,
+ NULL,
+ software_device.Pass(),
+ frame_swap_message_queue_,
+ true));
}
if (command_line.HasSwitch(cc::switches::kCompositeToMailbox)) {
// Composite-to-mailbox is currently used for layout tests in order to cause
// them to draw inside in the renderer to do the readback there. This should
// no longer be the case when crbug.com/311404 is fixed.
- DCHECK(is_threaded_compositing_enabled_ ||
+ DCHECK(IsThreadedCompositingEnabled() ||
RenderThreadImpl::current()->layout_test_mode());
cc::ResourceFormat format = cc::RGBA_8888;
-#if defined(OS_ANDROID)
- if (base::android::SysUtils::IsLowEndDevice())
+ if (base::SysInfo::IsLowEndDevice())
format = cc::RGB_565;
-#endif
return scoped_ptr<cc::OutputSurface>(
- new MailboxOutputSurface(
- routing_id(),
- output_surface_id,
- context_provider,
- scoped_ptr<cc::SoftwareOutputDevice>(),
- format));
+ new MailboxOutputSurface(routing_id(),
+ output_surface_id,
+ context_provider,
+ scoped_ptr<cc::SoftwareOutputDevice>(),
+ frame_swap_message_queue_,
+ format));
}
bool use_swap_compositor_frame_message = false;
return scoped_ptr<cc::OutputSurface>(
- new CompositorOutputSurface(
- routing_id(),
- output_surface_id,
- context_provider,
- scoped_ptr<cc::SoftwareOutputDevice>(),
- use_swap_compositor_frame_message));
+ new CompositorOutputSurface(routing_id(),
+ output_surface_id,
+ context_provider,
+ scoped_ptr<cc::SoftwareOutputDevice>(),
+ frame_swap_message_queue_,
+ use_swap_compositor_frame_message));
}
void RenderWidget::OnSwapBuffersAborted() {
@@ -898,6 +945,23 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
return;
base::AutoReset<WebInputEvent::Type> handling_event_type_resetter(
&handling_event_type_, input_event->type);
+#if defined(OS_ANDROID)
+ // On Android, when a key is pressed or sent from the Keyboard using IME,
+ // |AdapterInputConnection| generates input key events to make sure all JS
+ // listeners that monitor KeyUp and KeyDown events receive the proper key
+ // code. Since this input key event comes from IME, we need to set the
+ // IME event guard here to make sure it does not interfere with other IME
+ // events.
+ scoped_ptr<ImeEventGuard> ime_event_guard_maybe;
+ if (WebInputEvent::isKeyboardEventType(input_event->type)) {
+ const WebKeyboardEvent& key_event =
+ *static_cast<const WebKeyboardEvent*>(input_event);
+ // Some keys are special and it's essential that no events get blocked.
+ if (key_event.nativeKeyCode != AKEYCODE_TAB &&
+ key_event.nativeKeyCode != AKEYCODE_DPAD_CENTER)
+ ime_event_guard_maybe.reset(new ImeEventGuard(this));
+ }
+#endif
base::AutoReset<const ui::LatencyInfo*> resetter(&current_event_latency_info_,
&latency_info);
@@ -1018,13 +1082,9 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
}
}
- // Unconsumed touchmove acks should never be throttled as they're required to
- // dispatch compositor-handled scroll gestures.
bool event_type_can_be_rate_limited =
input_event->type == WebInputEvent::MouseMove ||
- input_event->type == WebInputEvent::MouseWheel ||
- (input_event->type == WebInputEvent::TouchMove &&
- ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
+ input_event->type == WebInputEvent::MouseWheel;
bool frame_pending = compositor_ && compositor_->BeginMainFrameRequested();
@@ -1158,31 +1218,37 @@ void RenderWidget::AutoResizeCompositor() {
}
void RenderWidget::initializeLayerTreeView() {
- compositor_ = RenderWidgetCompositor::Create(
- this, is_threaded_compositing_enabled_);
+ DCHECK(!host_closing_);
+
+ compositor_ =
+ RenderWidgetCompositor::Create(this, IsThreadedCompositingEnabled());
compositor_->setViewportSize(size_, physical_backing_size_);
if (init_complete_)
StartCompositor();
}
-blink::WebLayerTreeView* RenderWidget::layerTreeView() {
- return compositor_.get();
+void RenderWidget::DestroyLayerTreeView() {
+ // Always send this notification to prevent new layer tree views from
+ // being created, even if one hasn't been created yet.
+ if (webwidget_)
+ webwidget_->willCloseLayerTreeView();
+ compositor_.reset();
}
-void RenderWidget::suppressCompositorScheduling(bool enable) {
- if (compositor_)
- compositor_->SetSuppressScheduleComposite(enable);
+blink::WebLayerTreeView* RenderWidget::layerTreeView() {
+ return compositor_.get();
}
void RenderWidget::willBeginCompositorFrame() {
TRACE_EVENT0("gpu", "RenderWidget::willBeginCompositorFrame");
- DCHECK(RenderThreadImpl::current()->compositor_message_loop_proxy().get());
-
// The following two can result in further layout and possibly
// enable GPU acceleration so they need to be called before any painting
// is done.
+ UpdateTextInputType();
+#if defined(OS_ANDROID)
UpdateTextInputState(NO_SHOW_IME, FROM_NON_IME);
+#endif
UpdateSelectionBounds();
}
@@ -1200,6 +1266,59 @@ void RenderWidget::DidCommitCompositorFrame() {
#endif // defined(VIDEO_HOLE)
}
+// static
+scoped_ptr<cc::SwapPromise> RenderWidget::QueueMessageImpl(
+ IPC::Message* msg,
+ MessageDeliveryPolicy policy,
+ FrameSwapMessageQueue* frame_swap_message_queue,
+ scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
+ bool commit_requested,
+ int source_frame_number) {
+ if (policy == MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE &&
+ // No need for lock: this gets changed only on this thread.
+ !commit_requested &&
+ // No need for lock: Messages are only enqueued from this thread, if we
+ // don't have any now, no other thread will add any.
+ frame_swap_message_queue->Empty()) {
+ sync_message_filter->Send(msg);
+ return nullptr;
+ }
+
+ bool first_message_for_frame = false;
+ frame_swap_message_queue->QueueMessageForFrame(policy,
+ source_frame_number,
+ make_scoped_ptr(msg),
+ &first_message_for_frame);
+ if (first_message_for_frame) {
+ scoped_ptr<cc::SwapPromise> promise(new QueueMessageSwapPromise(
+ sync_message_filter, frame_swap_message_queue, source_frame_number));
+ return promise;
+ }
+ return nullptr;
+}
+
+void RenderWidget::QueueMessage(IPC::Message* msg,
+ MessageDeliveryPolicy policy) {
+ // RenderThreadImpl::current() is NULL in some tests.
+ if (!compositor_ || !RenderThreadImpl::current()) {
+ Send(msg);
+ return;
+ }
+
+ scoped_ptr<cc::SwapPromise> swap_promise =
+ QueueMessageImpl(msg,
+ policy,
+ frame_swap_message_queue_.get(),
+ RenderThreadImpl::current()->sync_message_filter(),
+ compositor_->commitRequested(),
+ compositor_->GetSourceFrameNumber());
+
+ if (swap_promise) {
+ compositor_->QueueSwapPromise(swap_promise.Pass());
+ compositor_->SetNeedsCommit();
+ }
+}
+
void RenderWidget::didCommitAndDrawCompositorFrame() {
// NOTE: Tests may break if this event is renamed or moved. See
// tab_capture_performancetest.cc.
@@ -1224,8 +1343,6 @@ void RenderWidget::didCompleteSwapBuffers() {
params.view_size = size_;
params.plugin_window_moves.swap(plugin_window_moves_);
params.flags = next_paint_flags_;
- params.scroll_offset = GetScrollOffset();
- params.scale_factor = device_scale_factor_;
Send(new ViewHostMsg_UpdateRect(routing_id_, params));
next_paint_flags_ = 0;
@@ -1282,6 +1399,12 @@ void RenderWidget::didBlur() {
}
void RenderWidget::DoDeferredClose() {
+ // No more compositing is possible. This prevents shutdown races between
+ // previously posted CreateOutputSurface tasks and the host being unable to
+ // create them because the close message was handled.
+ DestroyLayerTreeView();
+ // Also prevent new compositors from being created.
+ host_closing_ = true;
Send(new ViewHostMsg_Close(routing_id_));
}
@@ -1302,7 +1425,7 @@ void RenderWidget::closeWidgetSoon() {
// could be closed before the JS finishes executing. So instead, post a
// message back to the message loop, which won't run until the JS is
// complete, and then the Close message can be sent.
- base::MessageLoop::current()->PostTask(
+ base::MessageLoop::current()->PostNonNestableTask(
FROM_HERE, base::Bind(&RenderWidget::DoDeferredClose, this));
}
@@ -1321,9 +1444,8 @@ void RenderWidget::QueueSyntheticGesture(
void RenderWidget::Close() {
screen_metrics_emulator_.reset();
+ DestroyLayerTreeView();
if (webwidget_) {
- webwidget_->willCloseLayerTreeView();
- compositor_.reset();
webwidget_->close();
webwidget_ = NULL;
}
@@ -1359,7 +1481,7 @@ void RenderWidget::setWindowRect(const WebRect& rect) {
initial_pos_ = pos;
}
} else {
- ResizeSynchronously(pos);
+ ResizeSynchronously(pos, visible_viewport_size_);
}
}
@@ -1417,9 +1539,9 @@ void RenderWidget::OnImeSetComposition(
// If we failed to set the composition text, then we need to let the browser
// process to cancel the input method's ongoing composition session, to make
// sure we are in a consistent state.
- Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
+ Send(new InputHostMsg_ImeCancelComposition(routing_id()));
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
UpdateCompositionInfo(true);
#endif
}
@@ -1438,7 +1560,7 @@ void RenderWidget::OnImeConfirmComposition(const base::string16& text,
else
webwidget_->confirmComposition(WebWidget::DoNotKeepSelection);
handling_input_event_ = false;
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
UpdateCompositionInfo(true);
#endif
}
@@ -1484,11 +1606,17 @@ void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id()));
}
-#if defined(OS_ANDROID)
+void RenderWidget::showImeIfNeeded() {
+ OnShowImeIfNeeded();
+}
+
void RenderWidget::OnShowImeIfNeeded() {
+#if defined(OS_ANDROID) || defined(USE_AURA)
UpdateTextInputState(SHOW_IME_IF_NEEDED, FROM_NON_IME);
+#endif
}
+#if defined(OS_ANDROID)
void RenderWidget::IncrementOutstandingImeEventAcks() {
++outstanding_ime_acks_;
}
@@ -1543,6 +1671,12 @@ bool RenderWidget::SetDeviceColorProfile(
return true;
}
+void RenderWidget::ResetDeviceColorProfileForTesting() {
+ if (!device_color_profile_.empty())
+ device_color_profile_.clear();
+ device_color_profile_.push_back('0');
+}
+
void RenderWidget::OnOrientationChange() {
}
@@ -1624,6 +1758,47 @@ void RenderWidget::FinishHandlingImeEvent() {
#endif
}
+void RenderWidget::UpdateTextInputType() {
+ // On Windows, not only an IME but also an on-screen keyboard relies on the
+ // latest TextInputType to optimize its layout and functionality. Thus
+ // |input_method_is_active_| is no longer an appropriate condition to suppress
+ // TextInputTypeChanged IPC on Windows.
+ // TODO(yukawa, yoichio): Consider to stop checking |input_method_is_active_|
+ // on other platforms as well as Windows if the overhead is acceptable.
+#if !defined(OS_WIN)
+ if (!input_method_is_active_)
+ return;
+#endif
+
+ ui::TextInputType new_type = GetTextInputType();
+ if (IsDateTimeInput(new_type))
+ return; // Not considered as a text input field in WebKit/Chromium.
+
+ bool new_can_compose_inline = CanComposeInline();
+
+ blink::WebTextInputInfo new_info;
+ if (webwidget_)
+ new_info = webwidget_->textInputInfo();
+ const ui::TextInputMode new_mode = ConvertInputMode(new_info.inputMode);
+ int new_flags = new_info.flags;
+
+ if (text_input_type_ != new_type
+ || can_compose_inline_ != new_can_compose_inline
+ || text_input_mode_ != new_mode
+ || text_input_flags_ != new_flags) {
+ Send(new ViewHostMsg_TextInputTypeChanged(routing_id(),
+ new_type,
+ new_mode,
+ new_can_compose_inline,
+ new_flags));
+ text_input_type_ = new_type;
+ can_compose_inline_ = new_can_compose_inline;
+ text_input_mode_ = new_mode;
+ text_input_flags_ = new_flags;
+ }
+}
+
+#if defined(OS_ANDROID) || defined(USE_AURA)
void RenderWidget::UpdateTextInputState(ShowIme show_ime,
ChangeSource change_source) {
if (handling_ime_event_)
@@ -1637,7 +1812,6 @@ void RenderWidget::UpdateTextInputState(ShowIme show_ime,
blink::WebTextInputInfo new_info;
if (webwidget_)
new_info = webwidget_->textInputInfo();
- const ui::TextInputMode new_mode = ConvertInputMode(new_info.inputMode);
bool new_can_compose_inline = CanComposeInline();
@@ -1645,7 +1819,6 @@ void RenderWidget::UpdateTextInputState(ShowIme show_ime,
// shown.
if (show_ime == SHOW_IME_IF_NEEDED ||
(text_input_type_ != new_type ||
- text_input_mode_ != new_mode ||
text_input_info_ != new_info ||
can_compose_inline_ != new_can_compose_inline)
#if defined(OS_ANDROID)
@@ -1654,7 +1827,7 @@ void RenderWidget::UpdateTextInputState(ShowIme show_ime,
) {
ViewHostMsg_TextInputState_Params p;
p.type = new_type;
- p.mode = new_mode;
+ p.flags = new_info.flags;
p.value = new_info.value.utf8();
p.selection_start = new_info.selectionStart;
p.selection_end = new_info.selectionEnd;
@@ -1672,14 +1845,22 @@ void RenderWidget::UpdateTextInputState(ShowIme show_ime,
IncrementOutstandingImeEventAcks();
text_field_is_dirty_ = false;
#endif
+#if defined(USE_AURA)
+ Send(new ViewHostMsg_TextInputTypeChanged(routing_id(),
+ new_type,
+ text_input_mode_,
+ new_can_compose_inline,
+ new_info.flags));
+#endif
Send(new ViewHostMsg_TextInputStateChanged(routing_id(), p));
text_input_info_ = new_info;
text_input_type_ = new_type;
- text_input_mode_ = new_mode;
can_compose_inline_ = new_can_compose_inline;
+ text_input_flags_ = new_info.flags;
}
}
+#endif
void RenderWidget::GetSelectionBounds(gfx::Rect* focus, gfx::Rect* anchor) {
WebRect focus_webrect;
@@ -1695,17 +1876,23 @@ void RenderWidget::UpdateSelectionBounds() {
if (handling_ime_event_)
return;
- ViewHostMsg_SelectionBounds_Params params;
- GetSelectionBounds(&params.anchor_rect, &params.focus_rect);
- if (selection_anchor_rect_ != params.anchor_rect ||
- selection_focus_rect_ != params.focus_rect) {
- selection_anchor_rect_ = params.anchor_rect;
- selection_focus_rect_ = params.focus_rect;
- webwidget_->selectionTextDirection(params.focus_dir, params.anchor_dir);
- params.is_anchor_first = webwidget_->isSelectionAnchorFirst();
- Send(new ViewHostMsg_SelectionBoundsChanged(routing_id_, params));
+ // With composited selection updates, the selection bounds will be reported
+ // directly by the compositor, in which case explicit IPC selection
+ // notifications should be suppressed.
+ if (!blink::WebRuntimeFeatures::isCompositedSelectionUpdateEnabled()) {
+ ViewHostMsg_SelectionBounds_Params params;
+ GetSelectionBounds(&params.anchor_rect, &params.focus_rect);
+ if (selection_anchor_rect_ != params.anchor_rect ||
+ selection_focus_rect_ != params.focus_rect) {
+ selection_anchor_rect_ = params.anchor_rect;
+ selection_focus_rect_ = params.focus_rect;
+ webwidget_->selectionTextDirection(params.focus_dir, params.anchor_dir);
+ params.is_anchor_first = webwidget_->isSelectionAnchorFirst();
+ Send(new ViewHostMsg_SelectionBoundsChanged(routing_id_, params));
+ }
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
UpdateCompositionInfo(false);
#endif
}
@@ -1760,8 +1947,15 @@ ui::TextInputType RenderWidget::GetTextInputType() {
return ui::TEXT_INPUT_TYPE_NONE;
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
void RenderWidget::UpdateCompositionInfo(bool should_update_range) {
+#if defined(OS_ANDROID)
+ // Sending composition info makes sense only in Lollipop (API level 21)
+ // and above due to the API availability.
+ if (base::android::BuildInfo::GetInstance()->sdk_int() < 21)
+ return;
+#endif
+
gfx::Range range = gfx::Range();
if (should_update_range) {
GetCompositionRange(&range);
@@ -1775,7 +1969,7 @@ void RenderWidget::UpdateCompositionInfo(bool should_update_range) {
return;
composition_character_bounds_ = character_bounds;
composition_range_ = range;
- Send(new ViewHostMsg_ImeCompositionRangeChanged(
+ Send(new InputHostMsg_ImeCompositionRangeChanged(
routing_id(), composition_range_, composition_character_bounds_));
}
@@ -1850,10 +2044,10 @@ void RenderWidget::resetInputMethod() {
// If a composition text exists, then we need to let the browser process
// to cancel the input method's ongoing composition session.
if (webwidget_->confirmComposition())
- Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
+ Send(new InputHostMsg_ImeCancelComposition(routing_id()));
}
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
UpdateCompositionInfo(true);
#endif
}
@@ -1864,9 +2058,14 @@ void RenderWidget::didHandleGestureEvent(
#if defined(OS_ANDROID) || defined(USE_AURA)
if (event_cancelled)
return;
- if (event.type == WebInputEvent::GestureTap ||
- event.type == WebInputEvent::GestureLongPress) {
+ if (event.type == WebInputEvent::GestureTap) {
UpdateTextInputState(SHOW_IME_IF_NEEDED, FROM_NON_IME);
+ } else if (event.type == WebInputEvent::GestureLongPress) {
+ DCHECK(webwidget_);
+ if (webwidget_->textInputInfo().value.isEmpty())
+ UpdateTextInputState(NO_SHOW_IME, FROM_NON_IME);
+ else
+ UpdateTextInputState(SHOW_IME_IF_NEEDED, FROM_NON_IME);
}
#endif
}
@@ -1978,7 +2177,7 @@ RenderWidget::CreateGraphicsContext3D() {
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
scoped_refptr<GpuChannelHost> gpu_channel_host(
RenderThreadImpl::current()->EstablishGpuChannelSync(cause));
- if (!gpu_channel_host)
+ if (!gpu_channel_host.get())
return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
// Explicitly disable antialiasing for the compositor. As of the time of
@@ -2006,7 +2205,7 @@ RenderWidget::CreateGraphicsContext3D() {
// uploads, after which we are just wasting memory. Since we don't
// know our upload throughput yet, this just caps our memory usage.
size_t divider = 1;
- if (base::android::SysUtils::IsLowEndDevice())
+ if (base::SysInfo::IsLowEndDevice())
divider = 6;
// For reference Nexus10 can upload 1MB in about 2.5ms.
const double max_mb_uploaded_per_ms = 2.0 / (5 * divider);
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index cfba42a5d59..523a38e2c52 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -10,17 +10,17 @@
#include "base/auto_reset.h"
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "cc/debug/rendering_stats_instrumentation.h"
#include "content/common/content_export.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/input/synthetic_gesture_params.h"
+#include "content/renderer/message_delivery_policy.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "third_party/WebKit/public/platform/WebRect.h"
@@ -49,6 +49,7 @@ class ViewHostMsg_UpdateRect;
namespace IPC {
class SyncMessage;
+class SyncMessageFilter;
}
namespace blink {
@@ -59,7 +60,10 @@ class WebMouseEvent;
class WebTouchEvent;
}
-namespace cc { class OutputSurface; }
+namespace cc {
+class OutputSurface;
+class SwapPromise;
+}
namespace gfx {
class Range;
@@ -67,6 +71,7 @@ class Range;
namespace content {
class ExternalPopupMenu;
+class FrameSwapMessageQueue;
class PepperPluginInstanceImpl;
class RenderFrameImpl;
class RenderFrameProxy;
@@ -105,9 +110,13 @@ class CONTENT_EXPORT RenderWidget
bool closing() const { return closing_; }
bool is_swapped_out() { return is_swapped_out_; }
ui::MenuSourceType context_menu_source_type() {
- return context_menu_source_type_; }
- gfx::Point touch_editing_context_menu_location() {
- return touch_editing_context_menu_location_;
+ return context_menu_source_type_;
+ }
+ bool has_host_context_menu_location() {
+ return has_host_context_menu_location_;
+ }
+ gfx::Point host_context_menu_location() {
+ return host_context_menu_location_;
}
// Functions to track out-of-process frames for special notifications.
@@ -125,13 +134,12 @@ class CONTENT_EXPORT RenderWidget
#endif // defined(VIDEO_HOLE)
// IPC::Listener
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// IPC::Sender
- virtual bool Send(IPC::Message* msg) OVERRIDE;
+ bool Send(IPC::Message* msg) override;
// blink::WebWidgetClient
- virtual void suppressCompositorScheduling(bool enable);
virtual void willBeginCompositorFrame();
virtual void didAutoResize(const blink::WebSize& new_size);
virtual void initializeLayerTreeView();
@@ -157,10 +165,14 @@ class CONTENT_EXPORT RenderWidget
virtual void resetInputMethod();
virtual void didHandleGestureEvent(const blink::WebGestureEvent& event,
bool event_cancelled);
+ virtual void showImeIfNeeded();
// Begins the compositor's scheduler to start producing frames.
void StartCompositor();
+ // Stop compositing.
+ void DestroyLayerTreeView();
+
// Called when a plugin is moved. These events are queued up and sent with
// the next paint or scroll message to the host.
void SchedulePluginMove(const WebPluginGeometry& move);
@@ -192,6 +204,18 @@ class CONTENT_EXPORT RenderWidget
// Notifies about a compositor frame commit operation having finished.
virtual void DidCommitCompositorFrame();
+ // Deliveres |message| together with compositor state change updates. The
+ // exact behavior depends on |policy|.
+ // This mechanism is not a drop-in replacement for IPC: messages sent this way
+ // will not be automatically available to BrowserMessageFilter, for example.
+ // FIFO ordering is preserved between messages enqueued with the same
+ // |policy|, the ordering between messages enqueued for different policies is
+ // undefined.
+ //
+ // |msg| message to send, ownership of |msg| is transferred.
+ // |policy| see the comment on MessageDeliveryPolicy.
+ void QueueMessage(IPC::Message* msg, MessageDeliveryPolicy policy);
+
// Handle common setup/teardown for handling IME events.
void StartHandlingImeEvent();
void FinishHandlingImeEvent();
@@ -225,6 +249,7 @@ class CONTENT_EXPORT RenderWidget
const blink::WebDeviceEmulationParams& params);
void DisableScreenMetricsEmulation();
void SetPopupOriginAdjustmentsForEmulation(ScreenMetricsEmulator* emulator);
+ gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
void ScheduleCompositeWithForcedRedraw();
@@ -234,6 +259,10 @@ class CONTENT_EXPORT RenderWidget
void OnSwapBuffersComplete();
void OnSwapBuffersAborted();
+ // Checks if the text input state and compose inline mode have been changed.
+ // If they are changed, the new value will be sent to the browser process.
+ void UpdateTextInputType();
+
// Checks if the selection bounds have been changed. If they are changed,
// the new value will be sent to the browser process.
void UpdateSelectionBounds();
@@ -242,6 +271,7 @@ class CONTENT_EXPORT RenderWidget
void OnShowHostContextMenu(ContextMenuParams* params);
+#if defined(OS_ANDROID) || defined(USE_AURA)
enum ShowIme {
SHOW_IME_IF_NEEDED,
NO_SHOW_IME,
@@ -259,11 +289,13 @@ class CONTENT_EXPORT RenderWidget
// IME events. This is when the text change did not originate from the IME in
// the browser side, such as changes by JavaScript or autofill.
void UpdateTextInputState(ShowIme show_ime, ChangeSource change_source);
+#endif
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
// Checks if the composition range or composition character bounds have been
// changed. If they are changed, the new value will be sent to the browser
- // process.
+ // process. This method does nothing when the browser process is not able to
+ // handle composition range and composition character bounds.
void UpdateCompositionInfo(bool should_update_range);
#endif
@@ -289,7 +321,7 @@ class CONTENT_EXPORT RenderWidget
bool hidden,
bool never_visible);
- virtual ~RenderWidget();
+ ~RenderWidget() override;
// Initializes this view with the given opener. CompleteInit must be called
// later.
@@ -309,6 +341,10 @@ class CONTENT_EXPORT RenderWidget
// active RenderWidgets.
void SetSwappedOut(bool is_swapped_out);
+ // Allows the process to exit once the unload handler has finished, if there
+ // are no other active RenderWidgets.
+ void WasSwappedOut();
+
void FlushPendingInputEventAck();
void DoDeferredClose();
void DoDeferredSetWindowRect(const blink::WebRect& pos);
@@ -316,13 +352,15 @@ class CONTENT_EXPORT RenderWidget
// Resizes the render widget.
void Resize(const gfx::Size& new_size,
const gfx::Size& physical_backing_size,
- float overdraw_bottom_height,
+ float top_controls_layout_height,
const gfx::Size& visible_viewport_size,
const gfx::Rect& resizer_rect,
bool is_fullscreen,
ResizeAck resize_ack);
// Used to force the size of a window when running layout tests.
- void ResizeSynchronously(const gfx::Rect& new_position);
+ void ResizeSynchronously(
+ const gfx::Rect& new_position,
+ const gfx::Size& visible_viewport_size);
virtual void SetScreenMetricsEmulationParameters(
float device_scale_factor,
const gfx::Point& root_layer_offset,
@@ -342,10 +380,11 @@ class CONTENT_EXPORT RenderWidget
virtual void OnClose();
void OnCreatingNewAck();
virtual void OnResize(const ViewMsg_Resize_Params& params);
+ void OnColorProfile(const std::vector<char>& color_profile);
void OnChangeResizeRect(const gfx::Rect& resizer_rect);
virtual void OnWasHidden();
- virtual void OnWasShown(bool needs_repainting);
- virtual void OnWasSwappedOut();
+ virtual void OnWasShown(bool needs_repainting,
+ const ui::LatencyInfo& latency_info);
void OnCreateVideoAck(int32 video_id);
void OnUpdateVideoAck(int32 video_id);
void OnRequestMoveAck();
@@ -367,9 +406,9 @@ class CONTENT_EXPORT RenderWidget
void OnGetFPS();
void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
-#if defined(OS_ANDROID)
void OnShowImeIfNeeded();
+#if defined(OS_ANDROID)
// Whenever an IME event that needs an acknowledgement is sent to the browser,
// the number of outstanding IME events that needs acknowledgement should be
// incremented. All IME events will be dropped until we receive an ack from
@@ -387,6 +426,7 @@ class CONTENT_EXPORT RenderWidget
virtual void SetDeviceScaleFactor(float device_scale_factor);
virtual bool SetDeviceColorProfile(const std::vector<char>& color_profile);
+ virtual void ResetDeviceColorProfileForTesting();
virtual void OnOrientationChange();
@@ -417,13 +457,23 @@ class CONTENT_EXPORT RenderWidget
void set_next_paint_is_resize_ack();
void set_next_paint_is_repaint_ack();
+ // QueueMessage implementation extracted into a static method for easy
+ // testing.
+ static scoped_ptr<cc::SwapPromise> QueueMessageImpl(
+ IPC::Message* msg,
+ MessageDeliveryPolicy policy,
+ FrameSwapMessageQueue* frame_swap_message_queue,
+ scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
+ bool commit_requested,
+ int source_frame_number);
+
// Override point to obtain that the current input method state and caret
// position.
virtual ui::TextInputType GetTextInputType();
virtual ui::TextInputType WebKitToUiTextInputType(
blink::WebTextInputType type);
-#if defined(OS_MACOSX) || defined(USE_AURA)
+#if defined(OS_MACOSX) || defined(USE_AURA) || defined(OS_ANDROID)
// Override point to obtain that the current composition character bounds.
// In the case of surrogate pairs, the character is treated as two characters:
// the bounds for first character is actual one, and the bounds for second
@@ -536,9 +586,9 @@ class CONTENT_EXPORT RenderWidget
// The size of the view's backing surface in non-DPI-adjusted pixels.
gfx::Size physical_backing_size_;
- // The height of the physical backing surface that is overdrawn opaquely in
- // the browser, for example by an on-screen-keyboard (in DPI-adjusted pixels).
- float overdraw_bottom_height_;
+ // The amount that the viewport size given to Blink was shrunk by the URL-bar
+ // (always 0 on platforms where URL-bar hiding isn't supported).
+ float top_controls_layout_height_;
// The size of the visible viewport in DPI-adjusted pixels.
gfx::Size visible_viewport_size_;
@@ -588,6 +638,9 @@ class CONTENT_EXPORT RenderWidget
// be sent, except for a Close.
bool closing_;
+ // True if it is known that the host is in the process of being shut down.
+ bool host_closing_;
+
// Whether this RenderWidget is currently swapped out, such that the view is
// being rendered by another process. If all RenderWidgets in a process are
// swapped out, the process can exit.
@@ -605,6 +658,9 @@ class CONTENT_EXPORT RenderWidget
// Stores the current text input mode of |webwidget_|.
ui::TextInputMode text_input_mode_;
+ // Stores the current text input flags of |webwidget_|.
+ int text_input_flags_;
+
// Stores the current type of composition text rendering of |webwidget_|.
bool can_compose_inline_;
@@ -658,9 +714,6 @@ class CONTENT_EXPORT RenderWidget
std::queue<SyntheticGestureCompletionCallback>
pending_synthetic_gesture_callbacks_;
- // Specified whether the compositor will run in its own thread.
- bool is_threaded_compositing_enabled_;
-
const ui::LatencyInfo* current_event_latency_info_;
uint32 next_output_surface_id_;
@@ -689,6 +742,7 @@ class CONTENT_EXPORT RenderWidget
gfx::Point popup_screen_origin_for_emulation_;
float popup_origin_scale_for_emulation_;
+ scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
scoped_ptr<ResizingModeSelector> resizing_mode_selector_;
// Lists of RenderFrameProxy objects that need to be notified of
@@ -704,7 +758,8 @@ class CONTENT_EXPORT RenderWidget
ObserverList<RenderFrameImpl> render_frames_;
ui::MenuSourceType context_menu_source_type_;
- gfx::Point touch_editing_context_menu_location_;
+ bool has_host_context_menu_location_;
+ gfx::Point host_context_menu_location_;
DISALLOW_COPY_AND_ASSIGN(RenderWidget);
};
diff --git a/chromium/content/renderer/render_widget_fullscreen.h b/chromium/content/renderer/render_widget_fullscreen.h
index 4b65b887809..83ce34952e9 100644
--- a/chromium/content/renderer/render_widget_fullscreen.h
+++ b/chromium/content/renderer/render_widget_fullscreen.h
@@ -18,7 +18,7 @@ class RenderWidgetFullscreen : public RenderWidget {
protected:
RenderWidgetFullscreen(const blink::WebScreenInfo& screen_info);
- virtual ~RenderWidgetFullscreen();
+ ~RenderWidgetFullscreen() override;
virtual blink::WebWidget* CreateWebWidget();
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
index 2fa03147816..f58304ef1df 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
@@ -50,12 +50,12 @@ namespace {
class FullscreenMouseLockDispatcher : public MouseLockDispatcher {
public:
explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget);
- virtual ~FullscreenMouseLockDispatcher();
+ ~FullscreenMouseLockDispatcher() override;
private:
// MouseLockDispatcher implementation.
- virtual void SendLockMouseRequest(bool unlocked_by_target) OVERRIDE;
- virtual void SendUnlockMouseRequest() OVERRIDE;
+ void SendLockMouseRequest(bool unlocked_by_target) override;
+ void SendUnlockMouseRequest() override;
RenderWidgetFullscreenPepper* widget_;
@@ -300,7 +300,6 @@ void RenderWidgetFullscreenPepper::InvalidateRect(const blink::WebRect& rect) {
void RenderWidgetFullscreenPepper::ScrollRect(
int dx, int dy, const blink::WebRect& rect) {
- didScrollRect(dx, dy, rect);
}
void RenderWidgetFullscreenPepper::Destroy() {
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h
index 5fdb0e0f12e..24808e8f54b 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.h
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h
@@ -31,16 +31,16 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
const blink::WebScreenInfo& screen_info);
// pepper::FullscreenContainer API.
- virtual void Invalidate() OVERRIDE;
- virtual void InvalidateRect(const blink::WebRect& rect) OVERRIDE;
- virtual void ScrollRect(int dx, int dy, const blink::WebRect& rect) OVERRIDE;
- virtual void Destroy() OVERRIDE;
- virtual void DidChangeCursor(const blink::WebCursorInfo& cursor) OVERRIDE;
- virtual void SetLayer(blink::WebLayer* layer) OVERRIDE;
+ void Invalidate() override;
+ void InvalidateRect(const blink::WebRect& rect) override;
+ void ScrollRect(int dx, int dy, const blink::WebRect& rect) override;
+ void Destroy() override;
+ void DidChangeCursor(const blink::WebCursorInfo& cursor) override;
+ void SetLayer(blink::WebLayer* layer) override;
// IPC::Listener implementation. This overrides the implementation
// in RenderWidgetFullscreen.
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& msg) override;
// Could be NULL when this widget is closing.
PepperPluginInstanceImpl* plugin() const { return plugin_; }
@@ -53,20 +53,20 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
RenderWidgetFullscreenPepper(PepperPluginInstanceImpl* plugin,
const GURL& active_url,
const blink::WebScreenInfo& screen_info);
- virtual ~RenderWidgetFullscreenPepper();
+ ~RenderWidgetFullscreenPepper() override;
// RenderWidget API.
- virtual void DidInitiatePaint() OVERRIDE;
- virtual void DidFlushPaint() OVERRIDE;
- virtual void Close() OVERRIDE;
- virtual void OnResize(const ViewMsg_Resize_Params& params) OVERRIDE;
+ void DidInitiatePaint() override;
+ void DidFlushPaint() override;
+ void Close() override;
+ void OnResize(const ViewMsg_Resize_Params& params) override;
// RenderWidgetFullscreen API.
- virtual blink::WebWidget* CreateWebWidget() OVERRIDE;
+ blink::WebWidget* CreateWebWidget() override;
// RenderWidget overrides.
- virtual GURL GetURLForGraphicsContext3D() OVERRIDE;
- virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
+ GURL GetURLForGraphicsContext3D() override;
+ void SetDeviceScaleFactor(float device_scale_factor) override;
private:
// URL that is responsible for this widget, passed to ggl::CreateViewContext.
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
index f8f145dd567..e0dbc83d614 100644
--- a/chromium/content/renderer/render_widget_unittest.cc
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -20,7 +20,7 @@ namespace content {
class RenderWidgetUnittest : public testing::Test {
public:
RenderWidgetUnittest() {}
- virtual ~RenderWidgetUnittest() {}
+ ~RenderWidgetUnittest() override {}
private:
MockRenderProcess render_process_;
@@ -49,10 +49,10 @@ class TouchableRenderWidget : public RenderWidget {
IPC::TestSink* sink() { return &sink_; }
protected:
- virtual ~TouchableRenderWidget() {}
+ ~TouchableRenderWidget() override {}
// Overridden from RenderWidget:
- virtual bool HasTouchEventHandlersAt(const gfx::Point& point) const OVERRIDE {
+ bool HasTouchEventHandlersAt(const gfx::Point& point) const override {
for (std::vector<gfx::Rect>::const_iterator iter = rects_.begin();
iter != rects_.end(); ++iter) {
if ((*iter).Contains(point))
@@ -61,7 +61,7 @@ class TouchableRenderWidget : public RenderWidget {
return false;
}
- virtual bool Send(IPC::Message* msg) OVERRIDE {
+ bool Send(IPC::Message* msg) override {
sink_.OnMessageReceived(*msg);
delete msg;
return true;
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc
new file mode 100644
index 00000000000..2aa359bd43f
--- /dev/null
+++ b/chromium/content/renderer/renderer_blink_platform_impl.cc
@@ -0,0 +1,1233 @@
+// Copyright (c) 2012 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 "content/renderer/renderer_blink_platform_impl.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/shared_memory.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/child/bluetooth/web_bluetooth_impl.h"
+#include "content/child/database_util.h"
+#include "content/child/file_info_util.h"
+#include "content/child/fileapi/webfilesystem_impl.h"
+#include "content/child/indexed_db/webidbfactory_impl.h"
+#include "content/child/npapi/npobject_util.h"
+#include "content/child/quota_dispatcher.h"
+#include "content/child/quota_message_filter.h"
+#include "content/child/simple_webmimeregistry_impl.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/child/web_database_observer_impl.h"
+#include "content/child/webblobregistry_impl.h"
+#include "content/child/webfileutilities_impl.h"
+#include "content/child/webmessageportchannel_impl.h"
+#include "content/common/file_utilities_messages.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/mime_registry_messages.h"
+#include "content/common/view_messages.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/webplugininfo.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/renderer/battery_status/battery_status_dispatcher.h"
+#include "content/renderer/device_sensors/device_light_event_pump.h"
+#include "content/renderer/device_sensors/device_motion_event_pump.h"
+#include "content/renderer/device_sensors/device_orientation_event_pump.h"
+#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
+#include "content/renderer/gamepad_shared_memory_reader.h"
+#include "content/renderer/media/audio_decoder.h"
+#include "content/renderer/media/crypto/key_systems.h"
+#include "content/renderer/media/renderer_webaudiodevice_impl.h"
+#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
+#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
+#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/renderer_clipboard_client.h"
+#include "content/renderer/scheduler/renderer_scheduler.h"
+#include "content/renderer/scheduler/web_scheduler_impl.h"
+#include "content/renderer/screen_orientation/screen_orientation_observer.h"
+#include "content/renderer/webclipboard_impl.h"
+#include "content/renderer/webgraphicscontext3d_provider_impl.h"
+#include "content/renderer/webpublicsuffixlist_impl.h"
+#include "gpu/config/gpu_info.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "media/audio/audio_output_device.h"
+#include "media/base/audio_hardware_config.h"
+#include "media/filters/stream_parser_factory.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_util.h"
+#include "storage/common/quota/quota_types.h"
+#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
+#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
+#include "third_party/WebKit/public/platform/WebDeviceLightListener.h"
+#include "third_party/WebKit/public/platform/WebDeviceMotionListener.h"
+#include "third_party/WebKit/public/platform/WebDeviceOrientationListener.h"
+#include "third_party/WebKit/public/platform/WebFileInfo.h"
+#include "third_party/WebKit/public/platform/WebGamepads.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamCenter.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
+#include "third_party/WebKit/public/platform/WebPluginListBuilder.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "ui/gfx/color_profile.h"
+#include "url/gurl.h"
+#include "webkit/common/gpu/context_provider_web_context.h"
+
+#if defined(OS_ANDROID)
+#include "content/renderer/android/synchronous_compositor_factory.h"
+#include "content/renderer/media/android/audio_decoder_android.h"
+#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "content/common/mac/font_descriptor.h"
+#include "content/common/mac/font_loader.h"
+#include "content/renderer/webscrollbarbehavior_impl_mac.h"
+#include "third_party/WebKit/public/platform/mac/WebSandboxSupport.h"
+#endif
+
+#if defined(OS_POSIX)
+#include "base/file_descriptor_posix.h"
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+#include <map>
+#include <string>
+
+#include "base/synchronization/lock.h"
+#include "content/common/child_process_sandbox_support_impl_linux.h"
+#include "third_party/WebKit/public/platform/linux/WebFallbackFont.h"
+#include "third_party/WebKit/public/platform/linux/WebSandboxSupport.h"
+#include "third_party/icu/source/common/unicode/utf16.h"
+#endif
+#endif
+
+#if defined(OS_WIN)
+#include "content/common/child_process_messages.h"
+#include "third_party/WebKit/public/platform/win/WebSandboxSupport.h"
+#endif
+
+#if defined(USE_AURA)
+#include "content/renderer/webscrollbarbehavior_impl_gtkoraura.h"
+#elif !defined(OS_MACOSX)
+#include "third_party/WebKit/public/platform/WebScrollbarBehavior.h"
+#define WebScrollbarBehaviorImpl blink::WebScrollbarBehavior
+#endif
+
+#if defined(ENABLE_WEBRTC)
+#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
+#endif
+
+using blink::Platform;
+using blink::WebAudioDevice;
+using blink::WebBlobRegistry;
+using blink::WebDatabaseObserver;
+using blink::WebFileInfo;
+using blink::WebFileSystem;
+using blink::WebGamepad;
+using blink::WebGamepads;
+using blink::WebIDBFactory;
+using blink::WebMIDIAccessor;
+using blink::WebMediaStreamCenter;
+using blink::WebMediaStreamCenterClient;
+using blink::WebMimeRegistry;
+using blink::WebRTCPeerConnectionHandler;
+using blink::WebRTCPeerConnectionHandlerClient;
+using blink::WebStorageNamespace;
+using blink::WebString;
+using blink::WebURL;
+using blink::WebVector;
+
+namespace content {
+
+namespace {
+
+bool g_sandbox_enabled = true;
+double g_test_device_light_data = -1;
+base::LazyInstance<blink::WebDeviceMotionData>::Leaky
+ g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<blink::WebDeviceOrientationData>::Leaky
+ g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER;
+// Set in startListening() when running layout tests, unset in stopListening(),
+// not owned by us.
+blink::WebBatteryStatusListener* g_test_battery_status_listener = nullptr;
+
+} // namespace
+
+//------------------------------------------------------------------------------
+
+class RendererBlinkPlatformImpl::MimeRegistry
+ : public SimpleWebMimeRegistryImpl {
+ public:
+ virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
+ const blink::WebString& mime_type,
+ const blink::WebString& codecs,
+ const blink::WebString& key_system);
+ virtual bool supportsMediaSourceMIMEType(const blink::WebString& mime_type,
+ const blink::WebString& codecs);
+ virtual bool supportsEncryptedMediaMIMEType(const WebString& key_system,
+ const WebString& mime_type,
+ const WebString& codecs) override;
+ virtual blink::WebString mimeTypeForExtension(
+ const blink::WebString& file_extension);
+ virtual blink::WebString mimeTypeFromFile(
+ const blink::WebString& file_path);
+};
+
+class RendererBlinkPlatformImpl::FileUtilities : public WebFileUtilitiesImpl {
+ public:
+ explicit FileUtilities(ThreadSafeSender* sender)
+ : thread_safe_sender_(sender) {}
+ virtual bool getFileInfo(const WebString& path, WebFileInfo& result);
+ private:
+ bool SendSyncMessageFromAnyThread(IPC::SyncMessage* msg) const;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+};
+
+#if defined(OS_ANDROID)
+// WebKit doesn't use WebSandboxSupport on android so we don't need to
+// implement anything here.
+class RendererBlinkPlatformImpl::SandboxSupport {};
+#else
+class RendererBlinkPlatformImpl::SandboxSupport
+ : public blink::WebSandboxSupport {
+ public:
+ virtual ~SandboxSupport() {}
+
+#if defined(OS_WIN)
+ virtual bool ensureFontLoaded(HFONT);
+#elif defined(OS_MACOSX)
+ virtual bool loadFont(
+ NSFont* src_font,
+ CGFontRef* container,
+ uint32* font_id);
+#elif defined(OS_POSIX)
+ virtual void getFallbackFontForCharacter(
+ blink::WebUChar32 character,
+ const char* preferred_locale,
+ blink::WebFallbackFont* fallbackFont);
+ virtual void getRenderStyleForStrike(
+ const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out);
+
+ private:
+ // WebKit likes to ask us for the correct font family to use for a set of
+ // unicode code points. It needs this information frequently so we cache it
+ // here.
+ base::Lock unicode_font_families_mutex_;
+ std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
+#endif
+};
+#endif // defined(OS_ANDROID)
+
+//------------------------------------------------------------------------------
+
+RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
+ RendererScheduler* renderer_scheduler)
+ : web_scheduler_(new WebSchedulerImpl(renderer_scheduler)),
+ clipboard_client_(new RendererClipboardClient),
+ clipboard_(new WebClipboardImpl(clipboard_client_.get())),
+ mime_registry_(new RendererBlinkPlatformImpl::MimeRegistry),
+ sudden_termination_disables_(0),
+ plugin_refresh_allowed_(true),
+ default_task_runner_(renderer_scheduler->DefaultTaskRunner()),
+ child_thread_loop_(base::MessageLoopProxy::current()),
+ web_scrollbar_behavior_(new WebScrollbarBehaviorImpl),
+ bluetooth_(new WebBluetoothImpl) {
+ if (g_sandbox_enabled && sandboxEnabled()) {
+ sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport);
+ } else {
+ DVLOG(1) << "Disabling sandbox support for testing.";
+ }
+
+ // ChildThread may not exist in some tests.
+ if (ChildThread::current()) {
+ sync_message_filter_ = ChildThread::current()->sync_message_filter();
+ thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
+ quota_message_filter_ = ChildThread::current()->quota_message_filter();
+ blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
+ web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_.get()));
+ web_database_observer_impl_.reset(
+ new WebDatabaseObserverImpl(sync_message_filter_.get()));
+ }
+}
+
+RendererBlinkPlatformImpl::~RendererBlinkPlatformImpl() {
+ WebFileSystemImpl::DeleteThreadSpecificInstance();
+}
+
+//------------------------------------------------------------------------------
+
+void RendererBlinkPlatformImpl::callOnMainThread(void (*func)(void*),
+ void* context) {
+ default_task_runner_->PostTask(FROM_HERE, base::Bind(func, context));
+}
+
+blink::WebScheduler* RendererBlinkPlatformImpl::scheduler() {
+ return web_scheduler_.get();
+}
+
+blink::WebClipboard* RendererBlinkPlatformImpl::clipboard() {
+ blink::WebClipboard* clipboard =
+ GetContentClient()->renderer()->OverrideWebClipboard();
+ if (clipboard)
+ return clipboard;
+ return clipboard_.get();
+}
+
+blink::WebMimeRegistry* RendererBlinkPlatformImpl::mimeRegistry() {
+ return mime_registry_.get();
+}
+
+blink::WebFileUtilities* RendererBlinkPlatformImpl::fileUtilities() {
+ if (!file_utilities_) {
+ file_utilities_.reset(new FileUtilities(thread_safe_sender_.get()));
+ file_utilities_->set_sandbox_enabled(sandboxEnabled());
+ }
+ return file_utilities_.get();
+}
+
+blink::WebSandboxSupport* RendererBlinkPlatformImpl::sandboxSupport() {
+#if defined(OS_ANDROID)
+ // WebKit doesn't use WebSandboxSupport on android.
+ return NULL;
+#else
+ return sandbox_support_.get();
+#endif
+}
+
+blink::WebCookieJar* RendererBlinkPlatformImpl::cookieJar() {
+ NOTREACHED() << "Use WebFrameClient::cookieJar() instead!";
+ return NULL;
+}
+
+blink::WebThemeEngine* RendererBlinkPlatformImpl::themeEngine() {
+ blink::WebThemeEngine* theme_engine =
+ GetContentClient()->renderer()->OverrideThemeEngine();
+ if (theme_engine)
+ return theme_engine;
+ return BlinkPlatformImpl::themeEngine();
+}
+
+bool RendererBlinkPlatformImpl::sandboxEnabled() {
+ // As explained in Platform.h, this function is used to decide
+ // whether to allow file system operations to come out of WebKit or not.
+ // Even if the sandbox is disabled, there's no reason why the code should
+ // act any differently...unless we're in single process mode. In which
+ // case, we have no other choice. Platform.h discourages using
+ // this switch unless absolutely necessary, so hopefully we won't end up
+ // with too many code paths being different in single-process mode.
+ return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
+}
+
+unsigned long long RendererBlinkPlatformImpl::visitedLinkHash(
+ const char* canonical_url,
+ size_t length) {
+ return GetContentClient()->renderer()->VisitedLinkHash(canonical_url, length);
+}
+
+bool RendererBlinkPlatformImpl::isLinkVisited(unsigned long long link_hash) {
+ return GetContentClient()->renderer()->IsLinkVisited(link_hash);
+}
+
+void RendererBlinkPlatformImpl::createMessageChannel(
+ blink::WebMessagePortChannel** channel1,
+ blink::WebMessagePortChannel** channel2) {
+ WebMessagePortChannelImpl::CreatePair(
+ child_thread_loop_.get(), channel1, channel2);
+}
+
+blink::WebPrescientNetworking*
+RendererBlinkPlatformImpl::prescientNetworking() {
+ return GetContentClient()->renderer()->GetPrescientNetworking();
+}
+
+void RendererBlinkPlatformImpl::cacheMetadata(const blink::WebURL& url,
+ double response_time,
+ const char* data,
+ size_t size) {
+ // Let the browser know we generated cacheable metadata for this resource. The
+ // browser may cache it and return it on subsequent responses to speed
+ // the processing of this resource.
+ std::vector<char> copy(data, data + size);
+ RenderThread::Get()->Send(
+ new ViewHostMsg_DidGenerateCacheableMetadata(url, response_time, copy));
+}
+
+WebString RendererBlinkPlatformImpl::defaultLocale() {
+ return base::ASCIIToUTF16(RenderThread::Get()->GetLocale());
+}
+
+void RendererBlinkPlatformImpl::suddenTerminationChanged(bool enabled) {
+ if (enabled) {
+ // We should not get more enables than disables, but we want it to be a
+ // non-fatal error if it does happen.
+ DCHECK_GT(sudden_termination_disables_, 0);
+ sudden_termination_disables_ = std::max(sudden_termination_disables_ - 1,
+ 0);
+ if (sudden_termination_disables_ != 0)
+ return;
+ } else {
+ sudden_termination_disables_++;
+ if (sudden_termination_disables_ != 1)
+ return;
+ }
+
+ RenderThread* thread = RenderThread::Get();
+ if (thread) // NULL in unittests.
+ thread->Send(new ViewHostMsg_SuddenTerminationChanged(enabled));
+}
+
+WebStorageNamespace* RendererBlinkPlatformImpl::createLocalStorageNamespace() {
+ return new WebStorageNamespaceImpl();
+}
+
+
+//------------------------------------------------------------------------------
+
+WebIDBFactory* RendererBlinkPlatformImpl::idbFactory() {
+ return web_idb_factory_.get();
+}
+
+//------------------------------------------------------------------------------
+
+WebFileSystem* RendererBlinkPlatformImpl::fileSystem() {
+ return WebFileSystemImpl::ThreadSpecificInstance(child_thread_loop_.get());
+}
+
+//------------------------------------------------------------------------------
+
+WebMimeRegistry::SupportsType
+RendererBlinkPlatformImpl::MimeRegistry::supportsMediaMIMEType(
+ const WebString& mime_type,
+ const WebString& codecs,
+ const WebString& key_system) {
+ const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
+ // Not supporting the container is a flat-out no.
+ if (!net::IsSupportedMediaMimeType(mime_type_ascii))
+ return IsNotSupported;
+
+ if (!key_system.isEmpty()) {
+ // Check whether the key system is supported with the mime_type and codecs.
+
+ // Chromium only supports ASCII parameters.
+ if (!base::IsStringASCII(key_system))
+ return IsNotSupported;
+
+ std::string key_system_ascii =
+ GetUnprefixedKeySystemName(base::UTF16ToASCII(key_system));
+ std::vector<std::string> strict_codecs;
+ net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, true);
+
+ if (!IsSupportedKeySystemWithMediaMimeType(
+ mime_type_ascii, strict_codecs, key_system_ascii)) {
+ return IsNotSupported;
+ }
+
+ // Continue processing the mime_type and codecs.
+ }
+
+ // Check list of strict codecs to see if it is supported.
+ if (net::IsStrictMediaMimeType(mime_type_ascii)) {
+ // Check if the codecs are a perfect match.
+ std::vector<std::string> strict_codecs;
+ net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, false);
+ return static_cast<WebMimeRegistry::SupportsType> (
+ net::IsSupportedStrictMediaMimeType(mime_type_ascii, strict_codecs));
+ }
+
+ // If we don't recognize the codec, it's possible we support it.
+ std::vector<std::string> parsed_codecs;
+ net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codecs, true);
+ if (!net::AreSupportedMediaCodecs(parsed_codecs))
+ return MayBeSupported;
+
+ // Otherwise we have a perfect match.
+ return IsSupported;
+}
+
+bool RendererBlinkPlatformImpl::MimeRegistry::supportsMediaSourceMIMEType(
+ const blink::WebString& mime_type,
+ const WebString& codecs) {
+ const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
+ std::vector<std::string> parsed_codec_ids;
+ net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codec_ids, false);
+ if (mime_type_ascii.empty())
+ return false;
+ return media::StreamParserFactory::IsTypeSupported(
+ mime_type_ascii, parsed_codec_ids);
+}
+
+bool RendererBlinkPlatformImpl::MimeRegistry::supportsEncryptedMediaMIMEType(
+ const WebString& key_system,
+ const WebString& mime_type,
+ const WebString& codecs) {
+ // Chromium only supports ASCII parameters.
+ if (!base::IsStringASCII(key_system) || !base::IsStringASCII(mime_type) ||
+ !base::IsStringASCII(codecs)) {
+ return false;
+ }
+
+ if (key_system.isEmpty())
+ return false;
+
+ const std::string mime_type_ascii = base::UTF16ToASCII(mime_type);
+
+ std::vector<std::string> codec_vector;
+ bool strip_suffix = !net::IsStrictMediaMimeType(mime_type_ascii);
+ net::ParseCodecString(base::UTF16ToASCII(codecs), &codec_vector,
+ strip_suffix);
+
+ return IsSupportedKeySystemWithMediaMimeType(
+ mime_type_ascii, codec_vector, base::UTF16ToASCII(key_system));
+}
+
+WebString RendererBlinkPlatformImpl::MimeRegistry::mimeTypeForExtension(
+ const WebString& file_extension) {
+ if (IsPluginProcess())
+ return SimpleWebMimeRegistryImpl::mimeTypeForExtension(file_extension);
+
+ // The sandbox restricts our access to the registry, so we need to proxy
+ // these calls over to the browser process.
+ std::string mime_type;
+ RenderThread::Get()->Send(
+ new MimeRegistryMsg_GetMimeTypeFromExtension(
+ base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type));
+ return base::ASCIIToUTF16(mime_type);
+}
+
+WebString RendererBlinkPlatformImpl::MimeRegistry::mimeTypeFromFile(
+ const WebString& file_path) {
+ if (IsPluginProcess())
+ return SimpleWebMimeRegistryImpl::mimeTypeFromFile(file_path);
+
+ // The sandbox restricts our access to the registry, so we need to proxy
+ // these calls over to the browser process.
+ std::string mime_type;
+ RenderThread::Get()->Send(new MimeRegistryMsg_GetMimeTypeFromFile(
+ base::FilePath::FromUTF16Unsafe(file_path),
+ &mime_type));
+ return base::ASCIIToUTF16(mime_type);
+}
+
+//------------------------------------------------------------------------------
+
+bool RendererBlinkPlatformImpl::FileUtilities::getFileInfo(
+ const WebString& path,
+ WebFileInfo& web_file_info) {
+ base::File::Info file_info;
+ base::File::Error status = base::File::FILE_ERROR_MAX;
+ if (!SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileInfo(
+ base::FilePath::FromUTF16Unsafe(path), &file_info, &status)) ||
+ status != base::File::FILE_OK) {
+ return false;
+ }
+ FileInfoToWebFileInfo(file_info, &web_file_info);
+ web_file_info.platformPath = path;
+ return true;
+}
+
+bool RendererBlinkPlatformImpl::FileUtilities::SendSyncMessageFromAnyThread(
+ IPC::SyncMessage* msg) const {
+ base::TimeTicks begin = base::TimeTicks::Now();
+ const bool success = thread_safe_sender_->Send(msg);
+ base::TimeDelta delta = base::TimeTicks::Now() - begin;
+ UMA_HISTOGRAM_TIMES("RendererSyncIPC.ElapsedTime", delta);
+ return success;
+}
+
+//------------------------------------------------------------------------------
+
+#if defined(OS_WIN)
+
+bool RendererBlinkPlatformImpl::SandboxSupport::ensureFontLoaded(HFONT font) {
+ LOGFONT logfont;
+ GetObject(font, sizeof(LOGFONT), &logfont);
+ RenderThread::Get()->PreCacheFont(logfont);
+ return true;
+}
+
+#elif defined(OS_MACOSX)
+
+bool RendererBlinkPlatformImpl::SandboxSupport::loadFont(NSFont* src_font,
+ CGFontRef* out,
+ uint32* font_id) {
+ uint32 font_data_size;
+ FontDescriptor src_font_descriptor(src_font);
+ base::SharedMemoryHandle font_data;
+ if (!RenderThread::Get()->Send(new ViewHostMsg_LoadFont(
+ src_font_descriptor, &font_data_size, &font_data, font_id))) {
+ *out = NULL;
+ *font_id = 0;
+ return false;
+ }
+
+ if (font_data_size == 0 || font_data == base::SharedMemory::NULLHandle() ||
+ *font_id == 0) {
+ LOG(ERROR) << "Bad response from ViewHostMsg_LoadFont() for " <<
+ src_font_descriptor.font_name;
+ *out = NULL;
+ *font_id = 0;
+ return false;
+ }
+
+ // TODO(jeremy): Need to call back into WebKit to make sure that the font
+ // isn't already activated, based on the font id. If it's already
+ // activated, don't reactivate it here - crbug.com/72727 .
+
+ return FontLoader::CGFontRefFromBuffer(font_data, font_data_size, out);
+}
+
+#elif defined(OS_ANDROID)
+
+// WebKit doesn't use WebSandboxSupport on android so we don't need to
+// implement anything here. This is cleaner to support than excluding the
+// whole class for android.
+
+#elif defined(OS_POSIX)
+
+void RendererBlinkPlatformImpl::SandboxSupport::getFallbackFontForCharacter(
+ blink::WebUChar32 character,
+ const char* preferred_locale,
+ blink::WebFallbackFont* fallbackFont) {
+ base::AutoLock lock(unicode_font_families_mutex_);
+ const std::map<int32_t, blink::WebFallbackFont>::const_iterator iter =
+ unicode_font_families_.find(character);
+ if (iter != unicode_font_families_.end()) {
+ fallbackFont->name = iter->second.name;
+ fallbackFont->filename = iter->second.filename;
+ fallbackFont->fontconfigInterfaceId = iter->second.fontconfigInterfaceId;
+ fallbackFont->ttcIndex = iter->second.ttcIndex;
+ fallbackFont->isBold = iter->second.isBold;
+ fallbackFont->isItalic = iter->second.isItalic;
+ return;
+ }
+
+ GetFallbackFontForCharacter(character, preferred_locale, fallbackFont);
+ unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
+}
+
+void RendererBlinkPlatformImpl::SandboxSupport::getRenderStyleForStrike(
+ const char* family,
+ int sizeAndStyle,
+ blink::WebFontRenderStyle* out) {
+ GetRenderStyleForStrike(family, sizeAndStyle, out);
+}
+
+#endif
+
+//------------------------------------------------------------------------------
+
+Platform::FileHandle RendererBlinkPlatformImpl::databaseOpenFile(
+ const WebString& vfs_file_name,
+ int desired_flags) {
+ return DatabaseUtil::DatabaseOpenFile(
+ vfs_file_name, desired_flags, sync_message_filter_.get());
+}
+
+int RendererBlinkPlatformImpl::databaseDeleteFile(
+ const WebString& vfs_file_name,
+ bool sync_dir) {
+ return DatabaseUtil::DatabaseDeleteFile(
+ vfs_file_name, sync_dir, sync_message_filter_.get());
+}
+
+long RendererBlinkPlatformImpl::databaseGetFileAttributes(
+ const WebString& vfs_file_name) {
+ return DatabaseUtil::DatabaseGetFileAttributes(vfs_file_name,
+ sync_message_filter_.get());
+}
+
+long long RendererBlinkPlatformImpl::databaseGetFileSize(
+ const WebString& vfs_file_name) {
+ return DatabaseUtil::DatabaseGetFileSize(vfs_file_name,
+ sync_message_filter_.get());
+}
+
+long long RendererBlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
+ const WebString& origin_identifier) {
+ return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
+ sync_message_filter_.get());
+}
+
+bool RendererBlinkPlatformImpl::canAccelerate2dCanvas() {
+ RenderThreadImpl* thread = RenderThreadImpl::current();
+ GpuChannelHost* host = thread->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_CANVAS_2D);
+ if (!host)
+ return false;
+
+ return host->gpu_info().SupportsAccelerated2dCanvas();
+}
+
+bool RendererBlinkPlatformImpl::isThreadedCompositingEnabled() {
+ RenderThreadImpl* thread = RenderThreadImpl::current();
+ // thread can be NULL in tests.
+ return thread && thread->compositor_message_loop_proxy().get();
+}
+
+double RendererBlinkPlatformImpl::audioHardwareSampleRate() {
+ RenderThreadImpl* thread = RenderThreadImpl::current();
+ return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
+}
+
+size_t RendererBlinkPlatformImpl::audioHardwareBufferSize() {
+ RenderThreadImpl* thread = RenderThreadImpl::current();
+ return thread->GetAudioHardwareConfig()->GetOutputBufferSize();
+}
+
+unsigned RendererBlinkPlatformImpl::audioHardwareOutputChannels() {
+ RenderThreadImpl* thread = RenderThreadImpl::current();
+ return thread->GetAudioHardwareConfig()->GetOutputChannels();
+}
+
+WebDatabaseObserver* RendererBlinkPlatformImpl::databaseObserver() {
+ return web_database_observer_impl_.get();
+}
+
+WebAudioDevice* RendererBlinkPlatformImpl::createAudioDevice(
+ size_t buffer_size,
+ unsigned input_channels,
+ unsigned channels,
+ double sample_rate,
+ WebAudioDevice::RenderCallback* callback,
+ const blink::WebString& input_device_id) {
+ // Use a mock for testing.
+ blink::WebAudioDevice* mock_device =
+ GetContentClient()->renderer()->OverrideCreateAudioDevice(sample_rate);
+ if (mock_device)
+ return mock_device;
+
+ // The |channels| does not exactly identify the channel layout of the
+ // device. The switch statement below assigns a best guess to the channel
+ // layout based on number of channels.
+ // TODO(crogers): WebKit should give the channel layout instead of the hard
+ // channel count.
+ media::ChannelLayout layout = media::CHANNEL_LAYOUT_UNSUPPORTED;
+ switch (channels) {
+ case 1:
+ layout = media::CHANNEL_LAYOUT_MONO;
+ break;
+ case 2:
+ layout = media::CHANNEL_LAYOUT_STEREO;
+ break;
+ case 3:
+ layout = media::CHANNEL_LAYOUT_2_1;
+ break;
+ case 4:
+ layout = media::CHANNEL_LAYOUT_4_0;
+ break;
+ case 5:
+ layout = media::CHANNEL_LAYOUT_5_0;
+ break;
+ case 6:
+ layout = media::CHANNEL_LAYOUT_5_1;
+ break;
+ case 7:
+ layout = media::CHANNEL_LAYOUT_7_0;
+ break;
+ case 8:
+ layout = media::CHANNEL_LAYOUT_7_1;
+ break;
+ default:
+ layout = media::CHANNEL_LAYOUT_STEREO;
+ }
+
+ int session_id = 0;
+ if (input_device_id.isNull() ||
+ !base::StringToInt(base::UTF16ToUTF8(input_device_id), &session_id)) {
+ if (input_channels > 0)
+ DLOG(WARNING) << "createAudioDevice(): request for audio input ignored";
+
+ input_channels = 0;
+ }
+
+ media::AudioParameters params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ layout, static_cast<int>(sample_rate), 16, buffer_size,
+ media::AudioParameters::NO_EFFECTS);
+
+ return new RendererWebAudioDeviceImpl(params, callback, session_id);
+}
+
+#if defined(OS_ANDROID)
+bool RendererBlinkPlatformImpl::loadAudioResource(
+ blink::WebAudioBus* destination_bus,
+ const char* audio_file_data,
+ size_t data_size) {
+ return DecodeAudioFileData(destination_bus,
+ audio_file_data,
+ data_size,
+ thread_safe_sender_);
+}
+#else
+bool RendererBlinkPlatformImpl::loadAudioResource(
+ blink::WebAudioBus* destination_bus,
+ const char* audio_file_data,
+ size_t data_size) {
+ return DecodeAudioFileData(
+ destination_bus, audio_file_data, data_size);
+}
+#endif // defined(OS_ANDROID)
+
+//------------------------------------------------------------------------------
+
+blink::WebMIDIAccessor* RendererBlinkPlatformImpl::createMIDIAccessor(
+ blink::WebMIDIAccessorClient* client) {
+ blink::WebMIDIAccessor* accessor =
+ GetContentClient()->renderer()->OverrideCreateMIDIAccessor(client);
+ if (accessor)
+ return accessor;
+
+ return new RendererWebMIDIAccessorImpl(client);
+}
+
+void RendererBlinkPlatformImpl::getPluginList(
+ bool refresh,
+ blink::WebPluginListBuilder* builder) {
+#if defined(ENABLE_PLUGINS)
+ std::vector<WebPluginInfo> plugins;
+ if (!plugin_refresh_allowed_)
+ refresh = false;
+ RenderThread::Get()->Send(
+ new ViewHostMsg_GetPlugins(refresh, &plugins));
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ const WebPluginInfo& plugin = plugins[i];
+
+ builder->addPlugin(
+ plugin.name, plugin.desc,
+ plugin.path.BaseName().AsUTF16Unsafe());
+
+ for (size_t j = 0; j < plugin.mime_types.size(); ++j) {
+ const WebPluginMimeType& mime_type = plugin.mime_types[j];
+
+ builder->addMediaTypeToLastPlugin(
+ WebString::fromUTF8(mime_type.mime_type), mime_type.description);
+
+ for (size_t k = 0; k < mime_type.file_extensions.size(); ++k) {
+ builder->addFileExtensionToLastMediaType(
+ WebString::fromUTF8(mime_type.file_extensions[k]));
+ }
+ }
+ }
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebPublicSuffixList* RendererBlinkPlatformImpl::publicSuffixList() {
+ return &public_suffix_list_;
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebString RendererBlinkPlatformImpl::signedPublicKeyAndChallengeString(
+ unsigned key_size_index,
+ const blink::WebString& challenge,
+ const blink::WebURL& url) {
+ std::string signed_public_key;
+ RenderThread::Get()->Send(new ViewHostMsg_Keygen(
+ static_cast<uint32>(key_size_index),
+ challenge.utf8(),
+ GURL(url),
+ &signed_public_key));
+ return WebString::fromUTF8(signed_public_key);
+}
+
+//------------------------------------------------------------------------------
+
+void RendererBlinkPlatformImpl::screenColorProfile(
+ WebVector<char>* to_profile) {
+#if defined(OS_WIN)
+ // On Windows screen color profile is only available in the browser.
+ std::vector<char> profile;
+ // This Send() can be called from any impl-side thread. Use a thread
+ // safe send to avoid crashing trying to access RenderThread::Get(),
+ // which is not accessible from arbitrary threads.
+ thread_safe_sender_->Send(
+ new ViewHostMsg_GetMonitorColorProfile(&profile));
+ *to_profile = profile;
+#else
+ // On other platforms, the primary monitor color profile can be read
+ // directly.
+ gfx::ColorProfile profile;
+ *to_profile = profile.profile();
+#endif
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebScrollbarBehavior* RendererBlinkPlatformImpl::scrollbarBehavior() {
+ return web_scrollbar_behavior_.get();
+}
+
+//------------------------------------------------------------------------------
+
+WebBlobRegistry* RendererBlinkPlatformImpl::blobRegistry() {
+ // blob_registry_ can be NULL when running some tests.
+ return blob_registry_.get();
+}
+
+//------------------------------------------------------------------------------
+
+void RendererBlinkPlatformImpl::sampleGamepads(WebGamepads& gamepads) {
+ PlatformEventObserverBase* observer =
+ platform_event_observers_.Lookup(blink::WebPlatformEventGamepad);
+ if (!observer)
+ return;
+ static_cast<RendererGamepadProvider*>(observer)->SampleGamepads(gamepads);
+}
+
+//------------------------------------------------------------------------------
+
+WebRTCPeerConnectionHandler*
+RendererBlinkPlatformImpl::createRTCPeerConnectionHandler(
+ WebRTCPeerConnectionHandlerClient* client) {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ DCHECK(render_thread);
+ if (!render_thread)
+ return NULL;
+
+#if defined(ENABLE_WEBRTC)
+ WebRTCPeerConnectionHandler* peer_connection_handler =
+ GetContentClient()->renderer()->OverrideCreateWebRTCPeerConnectionHandler(
+ client);
+ if (peer_connection_handler)
+ return peer_connection_handler;
+
+ PeerConnectionDependencyFactory* rtc_dependency_factory =
+ render_thread->GetPeerConnectionDependencyFactory();
+ return rtc_dependency_factory->CreateRTCPeerConnectionHandler(client);
+#else
+ return NULL;
+#endif // defined(ENABLE_WEBRTC)
+}
+
+//------------------------------------------------------------------------------
+
+WebMediaStreamCenter* RendererBlinkPlatformImpl::createMediaStreamCenter(
+ WebMediaStreamCenterClient* client) {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ DCHECK(render_thread);
+ if (!render_thread)
+ return NULL;
+ return render_thread->CreateMediaStreamCenter(client);
+}
+
+// static
+bool RendererBlinkPlatformImpl::SetSandboxEnabledForTesting(bool enable) {
+ bool was_enabled = g_sandbox_enabled;
+ g_sandbox_enabled = enable;
+ return was_enabled;
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebSpeechSynthesizer* RendererBlinkPlatformImpl::createSpeechSynthesizer(
+ blink::WebSpeechSynthesizerClient* client) {
+ return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
+}
+
+//------------------------------------------------------------------------------
+
+bool RendererBlinkPlatformImpl::processMemorySizesInBytes(
+ size_t* private_bytes,
+ size_t* shared_bytes) {
+ content::RenderThread::Get()->Send(
+ new ViewHostMsg_GetProcessMemorySizes(private_bytes, shared_bytes));
+ return true;
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebGraphicsContext3D*
+RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes) {
+ return createOffscreenGraphicsContext3D(attributes, NULL);
+}
+
+blink::WebGraphicsContext3D*
+RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ blink::WebGraphicsContext3D* share_context) {
+ return createOffscreenGraphicsContext3D(attributes, share_context, NULL);
+}
+
+blink::WebGraphicsContext3D*
+RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ blink::WebGraphicsContext3D* share_context,
+ blink::WebGLInfo* gl_info) {
+ if (!RenderThreadImpl::current())
+ return NULL;
+
+#if defined(OS_ANDROID)
+ if (SynchronousCompositorFactory* factory =
+ SynchronousCompositorFactory::GetInstance()) {
+ scoped_ptr<webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl>
+ in_process_context(
+ factory->CreateOffscreenGraphicsContext3D(attributes));
+ if (!in_process_context ||
+ !in_process_context->InitializeOnCurrentThread())
+ return NULL;
+ return in_process_context.release();
+ }
+#endif
+
+ scoped_refptr<GpuChannelHost> gpu_channel_host(
+ RenderThreadImpl::current()->EstablishGpuChannelSync(
+ CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
+
+ if (gpu_channel_host.get() && gl_info) {
+ const gpu::GPUInfo& gpu_info = gpu_channel_host->gpu_info();
+ gl_info->vendorInfo.assign(blink::WebString::fromUTF8(gpu_info.gl_vendor));
+ gl_info->rendererInfo.assign(
+ blink::WebString::fromUTF8(gpu_info.gl_renderer));
+ gl_info->driverVersion.assign(
+ blink::WebString::fromUTF8(gpu_info.gl_version));
+ }
+
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
+ bool lose_context_when_out_of_memory = false;
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
+ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
+ gpu_channel_host.get(),
+ attributes,
+ lose_context_when_out_of_memory,
+ GURL(attributes.topDocumentURL),
+ limits,
+ static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context)));
+
+ // Most likely the GPU process exited and the attempt to reconnect to it
+ // failed. Need to try to restore the context again later.
+ if (!context || !context->InitializeOnCurrentThread())
+ return NULL;
+ return context.release();
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebGraphicsContext3DProvider*
+RendererBlinkPlatformImpl::createSharedOffscreenGraphicsContext3DProvider() {
+ scoped_refptr<webkit::gpu::ContextProviderWebContext> provider =
+ RenderThreadImpl::current()->SharedMainThreadContextProvider();
+ if (!provider.get())
+ return NULL;
+ return new WebGraphicsContext3DProviderImpl(provider);
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebCompositorSupport* RendererBlinkPlatformImpl::compositorSupport() {
+ return &compositor_support_;
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebString RendererBlinkPlatformImpl::convertIDNToUnicode(
+ const blink::WebString& host,
+ const blink::WebString& languages) {
+ return net::IDNToUnicode(host.utf8(), languages.utf8());
+}
+
+//------------------------------------------------------------------------------
+
+// static
+void RendererBlinkPlatformImpl::SetMockDeviceLightDataForTesting(double data) {
+ g_test_device_light_data = data;
+}
+
+//------------------------------------------------------------------------------
+
+// static
+void RendererBlinkPlatformImpl::SetMockDeviceMotionDataForTesting(
+ const blink::WebDeviceMotionData& data) {
+ g_test_device_motion_data.Get() = data;
+}
+
+//------------------------------------------------------------------------------
+
+// static
+void RendererBlinkPlatformImpl::SetMockDeviceOrientationDataForTesting(
+ const blink::WebDeviceOrientationData& data) {
+ g_test_device_orientation_data.Get() = data;
+}
+
+//------------------------------------------------------------------------------
+
+void RendererBlinkPlatformImpl::vibrate(unsigned int milliseconds) {
+ RenderThread::Get()->Send(
+ new ViewHostMsg_Vibrate(base::checked_cast<int64>(milliseconds)));
+}
+
+void RendererBlinkPlatformImpl::cancelVibration() {
+ RenderThread::Get()->Send(new ViewHostMsg_CancelVibration());
+}
+
+//------------------------------------------------------------------------------
+
+// static
+PlatformEventObserverBase*
+RendererBlinkPlatformImpl::CreatePlatformEventObserverFromType(
+ blink::WebPlatformEventType type) {
+ RenderThread* thread = RenderThreadImpl::current();
+
+ // When running layout tests, those observers should not listen to the actual
+ // hardware changes. In order to make that happen, they will receive a null
+ // thread.
+ if (thread && RenderThreadImpl::current()->layout_test_mode())
+ thread = NULL;
+
+ switch (type) {
+ case blink::WebPlatformEventDeviceMotion:
+ return new DeviceMotionEventPump(thread);
+ case blink::WebPlatformEventDeviceOrientation:
+ return new DeviceOrientationEventPump(thread);
+ case blink::WebPlatformEventDeviceLight:
+ return new DeviceLightEventPump(thread);
+ case blink::WebPlatformEventGamepad:
+ return new GamepadSharedMemoryReader(thread);
+ case blink::WebPlatformEventScreenOrientation:
+ return new ScreenOrientationObserver();
+ default:
+ // A default statement is required to prevent compilation errors when
+ // Blink adds a new type.
+ VLOG(1) << "RendererBlinkPlatformImpl::startListening() with "
+ "unknown type.";
+ }
+
+ return NULL;
+}
+
+void RendererBlinkPlatformImpl::SetPlatformEventObserverForTesting(
+ blink::WebPlatformEventType type,
+ scoped_ptr<PlatformEventObserverBase> observer) {
+ DCHECK(type != blink::WebPlatformEventBattery);
+
+ if (platform_event_observers_.Lookup(type))
+ platform_event_observers_.Remove(type);
+ platform_event_observers_.AddWithID(observer.release(), type);
+}
+
+void RendererBlinkPlatformImpl::startListening(
+ blink::WebPlatformEventType type,
+ blink::WebPlatformEventListener* listener) {
+ if (type == blink::WebPlatformEventBattery) {
+ if (RenderThreadImpl::current() &&
+ RenderThreadImpl::current()->layout_test_mode()) {
+ g_test_battery_status_listener =
+ static_cast<blink::WebBatteryStatusListener*>(listener);
+ } else {
+ battery_status_dispatcher_.reset(new BatteryStatusDispatcher(
+ static_cast<blink::WebBatteryStatusListener*>(listener)));
+ }
+ return;
+ }
+
+ PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type);
+ if (!observer) {
+ observer = CreatePlatformEventObserverFromType(type);
+ if (!observer)
+ return;
+ platform_event_observers_.AddWithID(observer, static_cast<int32>(type));
+ }
+ observer->Start(listener);
+
+ // Device events (motion, orientation and light) expect to get an event fired
+ // as soon as a listener is registered if a fake data was passed before.
+ // TODO(mlamouri,timvolodine): make those send mock values directly instead of
+ // using this broken pattern.
+ if (RenderThreadImpl::current() &&
+ RenderThreadImpl::current()->layout_test_mode() &&
+ (type == blink::WebPlatformEventDeviceMotion ||
+ type == blink::WebPlatformEventDeviceOrientation ||
+ type == blink::WebPlatformEventDeviceLight)) {
+ SendFakeDeviceEventDataForTesting(type);
+ }
+}
+
+void RendererBlinkPlatformImpl::SendFakeDeviceEventDataForTesting(
+ blink::WebPlatformEventType type) {
+ PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type);
+ CHECK(observer);
+
+ void* data = 0;
+
+ switch (type) {
+ case blink::WebPlatformEventDeviceMotion:
+ if (!(g_test_device_motion_data == 0))
+ data = &g_test_device_motion_data.Get();
+ break;
+ case blink::WebPlatformEventDeviceOrientation:
+ if (!(g_test_device_orientation_data == 0))
+ data = &g_test_device_orientation_data.Get();
+ break;
+ case blink::WebPlatformEventDeviceLight:
+ if (g_test_device_light_data >= 0)
+ data = &g_test_device_light_data;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ if (!data)
+ return;
+
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&PlatformEventObserverBase::SendFakeDataForTesting,
+ base::Unretained(observer), data));
+}
+
+void RendererBlinkPlatformImpl::stopListening(
+ blink::WebPlatformEventType type) {
+ if (type == blink::WebPlatformEventBattery) {
+ g_test_battery_status_listener = nullptr;
+ battery_status_dispatcher_.reset();
+ return;
+ }
+
+ PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type);
+ if (!observer)
+ return;
+ observer->Stop();
+}
+
+//------------------------------------------------------------------------------
+
+void RendererBlinkPlatformImpl::queryStorageUsageAndQuota(
+ const blink::WebURL& storage_partition,
+ blink::WebStorageQuotaType type,
+ blink::WebStorageQuotaCallbacks callbacks) {
+ if (!thread_safe_sender_.get() || !quota_message_filter_.get())
+ return;
+ QuotaDispatcher::ThreadSpecificInstance(thread_safe_sender_.get(),
+ quota_message_filter_.get())
+ ->QueryStorageUsageAndQuota(
+ storage_partition,
+ static_cast<storage::StorageType>(type),
+ QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
+}
+
+//------------------------------------------------------------------------------
+
+blink::WebBluetooth* RendererBlinkPlatformImpl::bluetooth() {
+ return bluetooth_.get();
+}
+
+//------------------------------------------------------------------------------
+
+void RendererBlinkPlatformImpl::MockBatteryStatusChangedForTesting(
+ const blink::WebBatteryStatus& status) {
+ if (!g_test_battery_status_listener)
+ return;
+ g_test_battery_status_listener->updateBatteryStatus(status);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h
new file mode 100644
index 00000000000..f4f84deb08f
--- /dev/null
+++ b/chromium/content/renderer/renderer_blink_platform_impl.h
@@ -0,0 +1,264 @@
+// Copyright (c) 2012 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 CONTENT_RENDERER_RENDERER_BLINK_PLATFORM_IMPL_H_
+#define CONTENT_RENDERER_RENDERER_BLINK_PLATFORM_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "base/id_map.h"
+#include "base/memory/scoped_ptr.h"
+#include "cc/blink/web_compositor_support_impl.h"
+#include "content/child/blink_platform_impl.h"
+#include "content/common/content_export.h"
+#include "content/renderer/webpublicsuffixlist_impl.h"
+#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
+#include "third_party/WebKit/public/platform/WebIDBFactory.h"
+#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace cc {
+class ContextProvider;
+}
+
+namespace IPC {
+class SyncMessageFilter;
+}
+
+namespace blink {
+class WebBatteryStatus;
+class WebDeviceMotionData;
+class WebDeviceOrientationData;
+class WebGraphicsContext3DProvider;
+}
+
+namespace content {
+class BatteryStatusDispatcher;
+class DeviceLightEventPump;
+class DeviceMotionEventPump;
+class DeviceOrientationEventPump;
+class PlatformEventObserverBase;
+class QuotaMessageFilter;
+class RendererClipboardClient;
+class RendererScheduler;
+class RenderView;
+class ThreadSafeSender;
+class WebBluetoothImpl;
+class WebClipboardImpl;
+class WebDatabaseObserverImpl;
+class WebFileSystemImpl;
+class WebSchedulerImpl;
+
+class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
+ public:
+ RendererBlinkPlatformImpl(RendererScheduler* renderer_scheduler);
+ virtual ~RendererBlinkPlatformImpl();
+
+ void set_plugin_refresh_allowed(bool plugin_refresh_allowed) {
+ plugin_refresh_allowed_ = plugin_refresh_allowed;
+ }
+ // Platform methods:
+ virtual void callOnMainThread(void (*func)(void*), void* context);
+ virtual blink::WebClipboard* clipboard();
+ virtual blink::WebMimeRegistry* mimeRegistry();
+ virtual blink::WebFileUtilities* fileUtilities();
+ virtual blink::WebSandboxSupport* sandboxSupport();
+ virtual blink::WebCookieJar* cookieJar();
+ virtual blink::WebThemeEngine* themeEngine();
+ virtual blink::WebSpeechSynthesizer* createSpeechSynthesizer(
+ blink::WebSpeechSynthesizerClient* client);
+ virtual bool sandboxEnabled();
+ virtual unsigned long long visitedLinkHash(
+ const char* canonicalURL, size_t length);
+ virtual bool isLinkVisited(unsigned long long linkHash);
+ virtual void createMessageChannel(blink::WebMessagePortChannel** channel1,
+ blink::WebMessagePortChannel** channel2);
+ virtual blink::WebPrescientNetworking* prescientNetworking();
+ virtual void cacheMetadata(
+ const blink::WebURL&, double, const char*, size_t);
+ virtual blink::WebString defaultLocale();
+ virtual void suddenTerminationChanged(bool enabled);
+ virtual blink::WebStorageNamespace* createLocalStorageNamespace();
+ virtual blink::Platform::FileHandle databaseOpenFile(
+ const blink::WebString& vfs_file_name, int desired_flags);
+ virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
+ bool sync_dir);
+ virtual long databaseGetFileAttributes(
+ const blink::WebString& vfs_file_name);
+ virtual long long databaseGetFileSize(
+ const blink::WebString& vfs_file_name);
+ virtual long long databaseGetSpaceAvailableForOrigin(
+ const blink::WebString& origin_identifier);
+ virtual blink::WebString signedPublicKeyAndChallengeString(
+ unsigned key_size_index,
+ const blink::WebString& challenge,
+ const blink::WebURL& url);
+ virtual void getPluginList(bool refresh,
+ blink::WebPluginListBuilder* builder);
+ virtual blink::WebPublicSuffixList* publicSuffixList();
+ virtual void screenColorProfile(blink::WebVector<char>* to_profile);
+ virtual blink::WebScrollbarBehavior* scrollbarBehavior();
+ virtual blink::WebIDBFactory* idbFactory();
+ virtual blink::WebFileSystem* fileSystem();
+ virtual bool canAccelerate2dCanvas();
+ virtual bool isThreadedCompositingEnabled();
+ virtual double audioHardwareSampleRate();
+ virtual size_t audioHardwareBufferSize();
+ virtual unsigned audioHardwareOutputChannels();
+ virtual blink::WebDatabaseObserver* databaseObserver();
+
+ virtual blink::WebAudioDevice* createAudioDevice(
+ size_t buffer_size, unsigned input_channels, unsigned channels,
+ double sample_rate, blink::WebAudioDevice::RenderCallback* callback,
+ const blink::WebString& input_device_id);
+
+ virtual bool loadAudioResource(
+ blink::WebAudioBus* destination_bus, const char* audio_file_data,
+ size_t data_size);
+
+ virtual blink::WebMIDIAccessor*
+ createMIDIAccessor(blink::WebMIDIAccessorClient* client);
+
+ virtual blink::WebBlobRegistry* blobRegistry();
+ virtual void sampleGamepads(blink::WebGamepads&);
+ virtual blink::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler(
+ blink::WebRTCPeerConnectionHandlerClient* client);
+ virtual blink::WebMediaStreamCenter* createMediaStreamCenter(
+ blink::WebMediaStreamCenterClient* client);
+ virtual bool processMemorySizesInBytes(
+ size_t* private_bytes, size_t* shared_bytes);
+ virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes);
+ virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ blink::WebGraphicsContext3D* share_context);
+ virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
+ const blink::WebGraphicsContext3D::Attributes& attributes,
+ blink::WebGraphicsContext3D* share_context,
+ blink::WebGLInfo* gl_info);
+ virtual blink::WebGraphicsContext3DProvider*
+ createSharedOffscreenGraphicsContext3DProvider();
+ virtual blink::WebCompositorSupport* compositorSupport();
+ virtual blink::WebString convertIDNToUnicode(
+ const blink::WebString& host, const blink::WebString& languages);
+ virtual void startListening(blink::WebPlatformEventType,
+ blink::WebPlatformEventListener*);
+ virtual void stopListening(blink::WebPlatformEventType);
+ virtual void queryStorageUsageAndQuota(
+ const blink::WebURL& storage_partition,
+ blink::WebStorageQuotaType,
+ blink::WebStorageQuotaCallbacks);
+ virtual blink::WebBluetooth* bluetooth();
+ virtual void vibrate(unsigned int milliseconds);
+ virtual void cancelVibration();
+ virtual blink::WebScheduler* scheduler();
+
+ // Set the PlatformEventObserverBase in |platform_event_observers_| associated
+ // with |type| to |observer|. If there was already an observer associated to
+ // the given |type|, it will be replaced.
+ // Note that |observer| will be owned by this object after the call.
+ void SetPlatformEventObserverForTesting(
+ blink::WebPlatformEventType type,
+ scoped_ptr<PlatformEventObserverBase> observer);
+
+ // Disables the WebSandboxSupport implementation for testing.
+ // Tests that do not set up a full sandbox environment should call
+ // SetSandboxEnabledForTesting(false) _before_ creating any instances
+ // of this class, to ensure that we don't attempt to use sandbox-related
+ // file descriptors or other resources.
+ //
+ // Returns the previous |enable| value.
+ static bool SetSandboxEnabledForTesting(bool enable);
+
+ // Set a double to return when setDeviceLightListener is invoked.
+ static void SetMockDeviceLightDataForTesting(double data);
+ // Set WebDeviceMotionData to return when setDeviceMotionListener is invoked.
+ static void SetMockDeviceMotionDataForTesting(
+ const blink::WebDeviceMotionData& data);
+ // Set WebDeviceOrientationData to return when setDeviceOrientationListener
+ // is invoked.
+ static void SetMockDeviceOrientationDataForTesting(
+ const blink::WebDeviceOrientationData& data);
+
+ // Notifies blink::WebBatteryStatusListener that battery status has changed.
+ void MockBatteryStatusChangedForTesting(
+ const blink::WebBatteryStatus& status);
+
+ WebDatabaseObserverImpl* web_database_observer_impl() {
+ return web_database_observer_impl_.get();
+ }
+
+ WebBluetoothImpl* BluetoothImplForTesting() { return bluetooth_.get(); }
+
+ private:
+ bool CheckPreparsedJsCachingEnabled() const;
+
+ // Factory that takes a type and return PlatformEventObserverBase that matches
+ // it.
+ static PlatformEventObserverBase* CreatePlatformEventObserverFromType(
+ blink::WebPlatformEventType type);
+
+ // Use the data previously set via SetMockDevice...DataForTesting() and send
+ // them to the registered listener.
+ void SendFakeDeviceEventDataForTesting(blink::WebPlatformEventType type);
+
+ scoped_ptr<WebSchedulerImpl> web_scheduler_;
+
+ scoped_ptr<RendererClipboardClient> clipboard_client_;
+ scoped_ptr<WebClipboardImpl> clipboard_;
+
+ class FileUtilities;
+ scoped_ptr<FileUtilities> file_utilities_;
+
+ class MimeRegistry;
+ scoped_ptr<MimeRegistry> mime_registry_;
+
+ class SandboxSupport;
+ scoped_ptr<SandboxSupport> sandbox_support_;
+
+ // This counter keeps track of the number of times sudden termination is
+ // enabled or disabled. It starts at 0 (enabled) and for every disable
+ // increments by 1, for every enable decrements by 1. When it reaches 0,
+ // we tell the browser to enable fast termination.
+ int sudden_termination_disables_;
+
+ // If true, then a GetPlugins call is allowed to rescan the disk.
+ bool plugin_refresh_allowed_;
+
+ scoped_ptr<blink::WebIDBFactory> web_idb_factory_;
+
+ scoped_ptr<blink::WebBlobRegistry> blob_registry_;
+
+ WebPublicSuffixListImpl public_suffix_list_;
+
+ scoped_ptr<DeviceLightEventPump> device_light_event_pump_;
+ scoped_ptr<DeviceMotionEventPump> device_motion_event_pump_;
+ scoped_ptr<DeviceOrientationEventPump> device_orientation_event_pump_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ scoped_refptr<base::MessageLoopProxy> child_thread_loop_;
+ scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
+ scoped_refptr<ThreadSafeSender> thread_safe_sender_;
+ scoped_refptr<QuotaMessageFilter> quota_message_filter_;
+
+ scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
+
+ cc_blink::WebCompositorSupportImpl compositor_support_;
+
+ scoped_ptr<blink::WebScrollbarBehavior> web_scrollbar_behavior_;
+
+ scoped_ptr<BatteryStatusDispatcher> battery_status_dispatcher_;
+
+ scoped_ptr<WebBluetoothImpl> bluetooth_;
+
+ IDMap<PlatformEventObserverBase, IDMapOwnPointer> platform_event_observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererBlinkPlatformImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_RENDERER_BLINK_PLATFORM_IMPL_H_
diff --git a/chromium/content/renderer/renderer_clipboard_client.cc b/chromium/content/renderer/renderer_clipboard_client.cc
index e4f275c92eb..1e2953ea989 100644
--- a/chromium/content/renderer/renderer_clipboard_client.cc
+++ b/chromium/content/renderer/renderer_clipboard_client.cc
@@ -23,11 +23,11 @@ namespace {
class RendererClipboardWriteContext : public ClipboardClient::WriteContext {
public:
RendererClipboardWriteContext();
- virtual ~RendererClipboardWriteContext();
- virtual void WriteBitmapFromPixels(ui::Clipboard::ObjectMap* objects,
- const void* pixels,
- const gfx::Size& size) OVERRIDE;
- virtual void Flush(const ui::Clipboard::ObjectMap& objects) OVERRIDE;
+ ~RendererClipboardWriteContext() override;
+ void WriteBitmapFromPixels(ui::Clipboard::ObjectMap* objects,
+ const void* pixels,
+ const gfx::Size& size) override;
+ void Flush(const ui::Clipboard::ObjectMap& objects) override;
private:
scoped_ptr<base::SharedMemory> shared_buf_;
@@ -116,7 +116,7 @@ uint64 RendererClipboardClient::GetSequenceNumber(ui::ClipboardType type) {
bool RendererClipboardClient::IsFormatAvailable(content::ClipboardFormat format,
ui::ClipboardType type) {
- bool result;
+ bool result = false;
RenderThreadImpl::current()->Send(
new ClipboardHostMsg_IsFormatAvailable(format, type, &result));
return result;
@@ -156,7 +156,7 @@ void RendererClipboardClient::ReadRTF(ui::ClipboardType type,
void RendererClipboardClient::ReadImage(ui::ClipboardType type,
std::string* data) {
base::SharedMemoryHandle image_handle;
- uint32 image_size;
+ uint32 image_size = 0;
RenderThreadImpl::current()->Send(
new ClipboardHostMsg_ReadImage(type, &image_handle, &image_size));
if (base::SharedMemory::IsHandleValid(image_handle)) {
diff --git a/chromium/content/renderer/renderer_clipboard_client.h b/chromium/content/renderer/renderer_clipboard_client.h
index ebf46ad75d3..de9e9c14864 100644
--- a/chromium/content/renderer/renderer_clipboard_client.h
+++ b/chromium/content/renderer/renderer_clipboard_client.h
@@ -14,29 +14,28 @@ namespace content {
class RendererClipboardClient : public ClipboardClient {
public:
RendererClipboardClient();
- virtual ~RendererClipboardClient();
+ ~RendererClipboardClient() override;
- virtual ui::Clipboard* GetClipboard() OVERRIDE;
- virtual uint64 GetSequenceNumber(ui::ClipboardType type) OVERRIDE;
- virtual bool IsFormatAvailable(ClipboardFormat format,
- ui::ClipboardType type) OVERRIDE;
- virtual void Clear(ui::ClipboardType type) OVERRIDE;
- virtual void ReadAvailableTypes(ui::ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) OVERRIDE;
- virtual void ReadText(ui::ClipboardType type,
- base::string16* result) OVERRIDE;
- virtual void ReadHTML(ui::ClipboardType type,
- base::string16* markup,
- GURL* url,
- uint32* fragment_start,
- uint32* fragment_end) OVERRIDE;
- virtual void ReadRTF(ui::ClipboardType type, std::string* result) OVERRIDE;
- virtual void ReadImage(ui::ClipboardType type, std::string* data) OVERRIDE;
- virtual void ReadCustomData(ui::ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* data) OVERRIDE;
- virtual WriteContext* CreateWriteContext() OVERRIDE;
+ ui::Clipboard* GetClipboard() override;
+ uint64 GetSequenceNumber(ui::ClipboardType type) override;
+ bool IsFormatAvailable(ClipboardFormat format,
+ ui::ClipboardType type) override;
+ void Clear(ui::ClipboardType type) override;
+ void ReadAvailableTypes(ui::ClipboardType type,
+ std::vector<base::string16>* types,
+ bool* contains_filenames) override;
+ void ReadText(ui::ClipboardType type, base::string16* result) override;
+ void ReadHTML(ui::ClipboardType type,
+ base::string16* markup,
+ GURL* url,
+ uint32* fragment_start,
+ uint32* fragment_end) override;
+ void ReadRTF(ui::ClipboardType type, std::string* result) override;
+ void ReadImage(ui::ClipboardType type, std::string* data) override;
+ void ReadCustomData(ui::ClipboardType clipboard_type,
+ const base::string16& type,
+ base::string16* data) override;
+ WriteContext* CreateWriteContext() override;
};
} // namespace content
diff --git a/chromium/content/renderer/renderer_date_time_picker.cc b/chromium/content/renderer/renderer_date_time_picker.cc
deleted file mode 100644
index 592e2491451..00000000000
--- a/chromium/content/renderer/renderer_date_time_picker.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/renderer_date_time_picker.h"
-
-#include "base/strings/string_util.h"
-#include "content/common/view_messages.h"
-#include "content/renderer/date_time_suggestion_builder.h"
-#include "content/renderer/render_view_impl.h"
-#include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h"
-#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
-#include "third_party/WebKit/public/web/WebDateTimeInputType.h"
-#include "ui/base/ime/text_input_type.h"
-
-using blink::WebString;
-
-namespace content {
-
-static ui::TextInputType ToTextInputType(int type) {
- switch (type) {
- case blink::WebDateTimeInputTypeDate:
- return ui::TEXT_INPUT_TYPE_DATE;
- break;
- case blink::WebDateTimeInputTypeDateTime:
- return ui::TEXT_INPUT_TYPE_DATE_TIME;
- break;
- case blink::WebDateTimeInputTypeDateTimeLocal:
- return ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
- break;
- case blink::WebDateTimeInputTypeMonth:
- return ui::TEXT_INPUT_TYPE_MONTH;
- break;
- case blink::WebDateTimeInputTypeTime:
- return ui::TEXT_INPUT_TYPE_TIME;
- break;
- case blink::WebDateTimeInputTypeWeek:
- return ui::TEXT_INPUT_TYPE_WEEK;
- break;
- case blink::WebDateTimeInputTypeNone:
- default:
- return ui::TEXT_INPUT_TYPE_NONE;
- }
-}
-
-RendererDateTimePicker::RendererDateTimePicker(
- RenderViewImpl* sender,
- const blink::WebDateTimeChooserParams& params,
- blink::WebDateTimeChooserCompletion* completion)
- : RenderViewObserver(sender),
- chooser_params_(params),
- chooser_completion_(completion) {
-}
-
-RendererDateTimePicker::~RendererDateTimePicker() {
-}
-
-bool RendererDateTimePicker::Open() {
- ViewHostMsg_DateTimeDialogValue_Params message;
- message.dialog_type = ToTextInputType(chooser_params_.type);
- message.dialog_value = chooser_params_.doubleValue;
- message.minimum = chooser_params_.minimum;
- message.maximum = chooser_params_.maximum;
- message.step = chooser_params_.step;
- for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) {
- message.suggestions.push_back(
- DateTimeSuggestionBuilder::Build(chooser_params_.suggestions[i]));
- }
- Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message));
- return true;
-}
-
-bool RendererDateTimePicker::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(RendererDateTimePicker, message)
- IPC_MESSAGE_HANDLER(ViewMsg_ReplaceDateTime, OnReplaceDateTime)
- IPC_MESSAGE_HANDLER(ViewMsg_CancelDateTimeDialog, OnCancel)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void RendererDateTimePicker::OnReplaceDateTime(double value) {
- if (chooser_completion_)
- chooser_completion_->didChooseValue(value);
-#if defined(OS_ANDROID)
- static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
-#endif
-}
-
-void RendererDateTimePicker::OnCancel() {
- if (chooser_completion_)
- chooser_completion_->didCancelChooser();
-#if defined(OS_ANDROID)
- static_cast<RenderViewImpl*>(render_view())->DismissDateTimeDialog();
-#endif
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/renderer_date_time_picker.h b/chromium/content/renderer/renderer_date_time_picker.h
deleted file mode 100644
index 7a780c7826d..00000000000
--- a/chromium/content/renderer/renderer_date_time_picker.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_RENDERER_DATE_TIME_PICKER_H_
-#define CONTENT_RENDERER_RENDERER_DATE_TIME_PICKER_H_
-
-#include "base/basictypes.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
-
-struct ViewHostMsg_DateTimeDialogValue_Params;
-
-namespace blink {
-class WebDateTimeChooserCompletion;
-} // namespace blink
-
-namespace content {
-class RenderViewImpl;
-
-class RendererDateTimePicker : public RenderViewObserver {
- public:
- RendererDateTimePicker(
- RenderViewImpl* sender,
- const blink::WebDateTimeChooserParams& params,
- blink::WebDateTimeChooserCompletion* completion);
- virtual ~RendererDateTimePicker();
-
- bool Open();
-
- private:
- void OnReplaceDateTime(double value);
- void OnCancel();
-
- // RenderViewObserver
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
-
- blink::WebDateTimeChooserParams chooser_params_;
- blink::WebDateTimeChooserCompletion* chooser_completion_; // Not owned by us
-
- DISALLOW_COPY_AND_ASSIGN(RendererDateTimePicker);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_RENDERER_DATE_TIME_PICKER_H_
diff --git a/chromium/content/renderer/renderer_font_platform_win.cc b/chromium/content/renderer/renderer_font_platform_win.cc
new file mode 100644
index 00000000000..380bbd44669
--- /dev/null
+++ b/chromium/content/renderer/renderer_font_platform_win.cc
@@ -0,0 +1,423 @@
+// Copyright 2014 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 "content/renderer/renderer_font_platform_win.h"
+
+#include <dwrite.h>
+#include <string>
+#include <vector>
+#include <wrl/implements.h>
+#include <wrl/wrappers/corewrappers.h>
+
+#include "base/debug/alias.h"
+#include "base/debug/crash_logging.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/metrics/histogram.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "base/win/iat_patch_function.h"
+#include "base/win/registry.h"
+#include "base/win/scoped_comptr.h"
+
+namespace {
+
+namespace mswr = Microsoft::WRL;
+namespace mswrw = Microsoft::WRL::Wrappers;
+
+static const char kFontKeyName[] = "font_key_name";
+
+class FontCollectionLoader
+ : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+ IDWriteFontCollectionLoader> {
+ public:
+ // IDWriteFontCollectionLoader methods.
+ virtual HRESULT STDMETHODCALLTYPE
+ CreateEnumeratorFromKey(IDWriteFactory* factory,
+ void const* key,
+ UINT32 key_size,
+ IDWriteFontFileEnumerator** file_enumerator);
+
+ static HRESULT Initialize(IDWriteFactory* factory);
+
+ UINT32 GetFontMapSize();
+
+ std::wstring GetFontNameFromKey(UINT32 idx);
+
+ bool LoadFontListFromRegistry();
+ bool LoadRestrictedFontList();
+
+ FontCollectionLoader() {};
+ virtual ~FontCollectionLoader() {};
+
+ private:
+ mswr::ComPtr<IDWriteFontFileLoader> file_loader_;
+
+ std::vector<std::wstring> reg_fonts_;
+};
+
+mswr::ComPtr<FontCollectionLoader> g_font_loader;
+
+class FontFileStream
+ : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+ IDWriteFontFileStream> {
+ public:
+ // IDWriteFontFileStream methods.
+ virtual HRESULT STDMETHODCALLTYPE
+ ReadFileFragment(void const** fragment_start,
+ UINT64 file_offset,
+ UINT64 fragment_size,
+ void** context) {
+ if (!memory_.get() || !memory_->IsValid() ||
+ file_offset >= memory_->length() ||
+ (file_offset + fragment_size) > memory_->length())
+ return E_FAIL;
+
+ *fragment_start = static_cast<BYTE const*>(memory_->data()) +
+ static_cast<size_t>(file_offset);
+ *context = NULL;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* context) {}
+
+ virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) {
+ if (!memory_.get() || !memory_->IsValid())
+ return E_FAIL;
+
+ *file_size = memory_->length();
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) {
+ if (!memory_.get() || !memory_->IsValid())
+ return E_FAIL;
+
+ // According to MSDN article http://goo.gl/rrSYzi the "last modified time"
+ // is used by DirectWrite font selection algorithms to determine whether
+ // one font resource is more up to date than another one.
+ // So by returning 0 we are assuming that it will treat all fonts to be
+ // equally up to date.
+ // TODO(shrikant): We should further investigate this.
+ *last_write_time = 0;
+ return S_OK;
+ }
+
+ FontFileStream::FontFileStream() : font_key_(0) {
+ };
+
+ HRESULT RuntimeClassInitialize(UINT32 font_key) {
+ base::FilePath path;
+ PathService::Get(base::DIR_WINDOWS_FONTS, &path);
+ std::wstring font_key_name(g_font_loader->GetFontNameFromKey(font_key));
+ path = path.Append(font_key_name.c_str());
+ memory_.reset(new base::MemoryMappedFile());
+
+ // Put some debug information on stack.
+ WCHAR font_name[256];
+ path.value().copy(font_name, arraysize(font_name));
+ base::debug::Alias(font_name);
+
+ if (!memory_->Initialize(path)) {
+ memory_.reset();
+ return E_FAIL;
+ }
+
+ font_key_ = font_key;
+
+ base::debug::SetCrashKeyValue(kFontKeyName,
+ base::WideToUTF8(font_key_name));
+ return S_OK;
+ }
+
+ virtual ~FontFileStream() {}
+
+ UINT32 font_key_;
+ scoped_ptr<base::MemoryMappedFile> memory_;
+};
+
+class FontFileLoader
+ : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+ IDWriteFontFileLoader> {
+ public:
+ // IDWriteFontFileLoader methods.
+ virtual HRESULT STDMETHODCALLTYPE
+ CreateStreamFromKey(void const* ref_key,
+ UINT32 ref_key_size,
+ IDWriteFontFileStream** stream) {
+ if (ref_key_size != sizeof(UINT32))
+ return E_FAIL;
+
+ UINT32 font_key = *static_cast<const UINT32*>(ref_key);
+ mswr::ComPtr<FontFileStream> font_stream;
+ HRESULT hr = mswr::MakeAndInitialize<FontFileStream>(&font_stream,
+ font_key);
+ if (SUCCEEDED(hr)) {
+ *stream = font_stream.Detach();
+ return S_OK;
+ }
+ return E_FAIL;
+ }
+
+ FontFileLoader() {}
+ virtual ~FontFileLoader() {}
+};
+
+class FontFileEnumerator
+ : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
+ IDWriteFontFileEnumerator> {
+ public:
+ // IDWriteFontFileEnumerator methods.
+ virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) {
+ *has_current_file = FALSE;
+
+ if (current_file_)
+ current_file_.ReleaseAndGetAddressOf();
+
+ if (font_idx_ < g_font_loader->GetFontMapSize()) {
+ HRESULT hr =
+ factory_->CreateCustomFontFileReference(&font_idx_,
+ sizeof(UINT32),
+ file_loader_.Get(),
+ current_file_.GetAddressOf());
+ DCHECK(SUCCEEDED(hr));
+ *has_current_file = TRUE;
+ font_idx_++;
+ }
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE
+ GetCurrentFontFile(IDWriteFontFile** font_file) {
+ if (!current_file_) {
+ *font_file = NULL;
+ return E_FAIL;
+ }
+
+ *font_file = current_file_.Detach();
+ return S_OK;
+ }
+
+ FontFileEnumerator(const void* keys,
+ UINT32 buffer_size,
+ IDWriteFactory* factory,
+ IDWriteFontFileLoader* file_loader)
+ : factory_(factory), file_loader_(file_loader), font_idx_(0) {}
+
+ virtual ~FontFileEnumerator() {}
+
+ mswr::ComPtr<IDWriteFactory> factory_;
+ mswr::ComPtr<IDWriteFontFile> current_file_;
+ mswr::ComPtr<IDWriteFontFileLoader> file_loader_;
+ UINT32 font_idx_;
+};
+
+// IDWriteFontCollectionLoader methods.
+HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey(
+ IDWriteFactory* factory,
+ void const* key,
+ UINT32 key_size,
+ IDWriteFontFileEnumerator** file_enumerator) {
+ *file_enumerator = mswr::Make<FontFileEnumerator>(
+ key, key_size, factory, file_loader_.Get()).Detach();
+ return S_OK;
+}
+
+// static
+HRESULT FontCollectionLoader::Initialize(IDWriteFactory* factory) {
+ DCHECK(g_font_loader == NULL);
+
+ g_font_loader = mswr::Make<FontCollectionLoader>();
+ if (!g_font_loader) {
+ DCHECK(FALSE);
+ return E_FAIL;
+ }
+
+ CHECK(g_font_loader->LoadFontListFromRegistry());
+
+ g_font_loader->file_loader_ = mswr::Make<FontFileLoader>().Detach();
+
+ factory->RegisterFontFileLoader(g_font_loader->file_loader_.Get());
+ factory->RegisterFontCollectionLoader(g_font_loader.Get());
+
+ return S_OK;
+}
+
+UINT32 FontCollectionLoader::GetFontMapSize() {
+ return reg_fonts_.size();
+}
+
+std::wstring FontCollectionLoader::GetFontNameFromKey(UINT32 idx) {
+ DCHECK(idx < reg_fonts_.size());
+ return reg_fonts_[idx];
+}
+
+bool FontCollectionLoader::LoadFontListFromRegistry() {
+ const wchar_t kFontsRegistry[] =
+ L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
+ CHECK(reg_fonts_.empty());
+ base::win::RegKey regkey;
+ if (regkey.Open(HKEY_LOCAL_MACHINE, kFontsRegistry, KEY_READ) !=
+ ERROR_SUCCESS) {
+ return false;
+ }
+
+ base::FilePath system_font_path;
+ PathService::Get(base::DIR_WINDOWS_FONTS, &system_font_path);
+
+ std::wstring name;
+ std::wstring value;
+ for (DWORD idx = 0; idx < regkey.GetValueCount(); idx++) {
+ if (regkey.GetValueNameAt(idx, &name) == ERROR_SUCCESS &&
+ regkey.ReadValue(name.c_str(), &value) == ERROR_SUCCESS) {
+ base::FilePath path(value.c_str());
+ // We need to check if file name is the only component that exists,
+ // we will ignore all other registry entries.
+ std::vector<base::FilePath::StringType> components;
+ path.GetComponents(&components);
+ if (components.size() == 1 ||
+ base::FilePath::CompareEqualIgnoreCase(system_font_path.value(),
+ path.DirName().value())) {
+ reg_fonts_.push_back(path.BaseName().value());
+ }
+ }
+ }
+ UMA_HISTOGRAM_COUNTS("DirectWrite.Fonts.Loaded", reg_fonts_.size());
+ UMA_HISTOGRAM_COUNTS("DirectWrite.Fonts.Ignored",
+ regkey.GetValueCount() - reg_fonts_.size());
+ return true;
+}
+
+// This list is mainly based on prefs/prefs_tab_helper.cc kFontDefaults.
+const wchar_t* kRestrictedFontSet[] = {
+ // These are the "Web Safe" fonts.
+ L"times.ttf", // IDS_STANDARD_FONT_FAMILY
+ L"timesbd.ttf", // IDS_STANDARD_FONT_FAMILY
+ L"timesbi.ttf", // IDS_STANDARD_FONT_FAMILY
+ L"timesi.ttf", // IDS_STANDARD_FONT_FAMILY
+ L"cour.ttf", // IDS_FIXED_FONT_FAMILY
+ L"courbd.ttf", // IDS_FIXED_FONT_FAMILY
+ L"courbi.ttf", // IDS_FIXED_FONT_FAMILY
+ L"couri.ttf", // IDS_FIXED_FONT_FAMILY
+ L"consola.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
+ L"consolab.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
+ L"consolai.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
+ L"consolaz.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
+ L"arial.ttf", // IDS_SANS_SERIF_FONT_FAMILY
+ L"arialbd.ttf", // IDS_SANS_SERIF_FONT_FAMILY
+ L"arialbi.ttf", // IDS_SANS_SERIF_FONT_FAMILY
+ L"ariali.ttf", // IDS_SANS_SERIF_FONT_FAMILY
+ L"comic.ttf", // IDS_CURSIVE_FONT_FAMILY
+ L"comicbd.ttf", // IDS_CURSIVE_FONT_FAMILY
+ L"comici.ttf", // IDS_CURSIVE_FONT_FAMILY
+ L"comicz.ttf", // IDS_CURSIVE_FONT_FAMILY
+ L"impact.ttf", // IDS_FANTASY_FONT_FAMILY
+ L"georgia.ttf",
+ L"georgiab.ttf",
+ L"georgiai.ttf",
+ L"georgiaz.ttf",
+ L"trebuc.ttf",
+ L"trebucbd.ttf",
+ L"trebucbi.ttf",
+ L"trebucit.ttf",
+ L"verdana.ttf",
+ L"verdanab.ttf",
+ L"verdanai.ttf",
+ L"verdanaz.ttf",
+ L"segoeui.ttf", // IDS_PICTOGRAPH_FONT_FAMILY
+ L"segoeuib.ttf", // IDS_PICTOGRAPH_FONT_FAMILY
+ L"segoeuii.ttf", // IDS_PICTOGRAPH_FONT_FAMILY
+ L"msgothic.ttc", // IDS_STANDARD_FONT_FAMILY_JAPANESE
+ L"msmincho.ttc", // IDS_SERIF_FONT_FAMILY_JAPANESE
+ L"gulim.ttc", // IDS_FIXED_FONT_FAMILY_KOREAN
+ L"batang.ttc", // IDS_SERIF_FONT_FAMILY_KOREAN
+ L"simsun.ttc", // IDS_STANDARD_FONT_FAMILY_SIMPLIFIED_HAN
+ L"mingliu.ttc", // IDS_SERIF_FONT_FAMILY_TRADITIONAL_HAN
+
+ // These are from the Blink fallback list.
+ L"david.ttf", // USCRIPT_HEBREW
+ L"davidbd.ttf", // USCRIPT_HEBREW
+ L"euphemia.ttf", // USCRIPT_CANADIAN_ABORIGINAL
+ L"gautami.ttf", // USCRIPT_TELUGU
+ L"gautamib.ttf", // USCRIPT_TELUGU
+ L"latha.ttf", // USCRIPT_TAMIL
+ L"lathab.ttf", // USCRIPT_TAMIL
+ L"mangal.ttf", // USCRIPT_DEVANAGARI
+ L"mangalb.ttf", // USCRIPT_DEVANAGARI
+ L"monbaiti.ttf", // USCRIPT_MONGOLIAN
+ L"mvboli.ttf", // USCRIPT_THAANA
+ L"plantc.ttf", // USCRIPT_CHEROKEE
+ L"raavi.ttf", // USCRIPT_GURMUKHI
+ L"raavib.ttf", // USCRIPT_GURMUKHI
+ L"shruti.ttf", // USCRIPT_GUJARATI
+ L"shrutib.ttf", // USCRIPT_GUJARATI
+ L"sylfaen.ttf", // USCRIPT_GEORGIAN and USCRIPT_ARMENIAN
+ L"tahoma.ttf", // USCRIPT_ARABIC,
+ L"tahomabd.ttf", // USCRIPT_ARABIC,
+ L"tunga.ttf", // USCRIPT_KANNADA
+ L"tungab.ttf", // USCRIPT_KANNADA
+ L"vrinda.ttf", // USCRIPT_BENGALI
+ L"vrindab.ttf", // USCRIPT_BENGALI
+};
+
+bool FontCollectionLoader::LoadRestrictedFontList() {
+ reg_fonts_.clear();
+ reg_fonts_.assign(kRestrictedFontSet,
+ kRestrictedFontSet + _countof(kRestrictedFontSet));
+ return true;
+}
+
+} // namespace
+
+namespace content {
+
+mswr::ComPtr<IDWriteFontCollection> g_font_collection;
+
+IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory) {
+ if (g_font_collection.Get() != NULL)
+ return g_font_collection.Get();
+
+ base::TimeTicks start_tick = base::TimeTicks::Now();
+
+ FontCollectionLoader::Initialize(factory);
+
+ // We try here to put arbitrary limit on max number of fonts that could
+ // be loaded, otherwise we fallback to restricted set of fonts.
+ const UINT32 kMaxFontThreshold = 1750;
+ HRESULT hr = E_FAIL;
+ if (g_font_loader->GetFontMapSize() < kMaxFontThreshold) {
+ hr = factory->CreateCustomFontCollection(
+ g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());
+ }
+
+ bool loadingRestricted = false;
+ if (FAILED(hr) || !g_font_collection.Get()) {
+ // We will try here just one more time with restricted font set.
+ g_font_loader->LoadRestrictedFontList();
+ hr = factory->CreateCustomFontCollection(
+ g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());
+ }
+
+ base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick;
+ int64 delta = time_delta.ToInternalValue();
+ base::debug::Alias(&delta);
+ UINT32 size = g_font_loader->GetFontMapSize();
+ base::debug::Alias(&size);
+ base::debug::Alias(&loadingRestricted);
+
+ CHECK(SUCCEEDED(hr));
+ CHECK(g_font_collection.Get() != NULL);
+
+ UMA_HISTOGRAM_TIMES("DirectWrite.Fonts.LoadTime", time_delta);
+
+ base::debug::ClearCrashKey(kFontKeyName);
+
+ return g_font_collection.Get();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/renderer_font_platform_win.h b/chromium/content/renderer/renderer_font_platform_win.h
new file mode 100644
index 00000000000..a04901b73d2
--- /dev/null
+++ b/chromium/content/renderer/renderer_font_platform_win.h
@@ -0,0 +1,17 @@
+// Copyright 2014 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_RENDERER_RENDERER_FONT_PLATFORM_WIN_H_
+#define CHROME_RENDERER_RENDERER_FONT_PLATFORM_WIN_H_
+
+struct IDWriteFactory;
+struct IDWriteFontCollection;
+
+namespace content {
+
+IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory);
+
+} // namespace content
+
+#endif // CHROME_RENDERER_RENDERER_FONT_PLATFORM_WIN_H_
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index a64816a6710..e82712cf7e0 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -14,27 +14,24 @@
#include "base/metrics/histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/metrics/stats_counters.h"
-#include "base/path_service.h"
#include "base/pending_task.h"
#include "base/strings/string_util.h"
+#include "base/sys_info.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/timer/hi_res_timer_manager.h"
#include "content/child/child_process.h"
-#include "content/child/content_child_helpers.h"
#include "content/common/content_constants_internal.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/browser_plugin/browser_plugin_manager_impl.h"
-#include "content/renderer/pepper/pepper_plugin_registry.h"
#include "content/renderer/render_process_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_main_platform_delegate.h"
#include "ui/base/ui_base_switches.h"
#if defined(OS_ANDROID)
-#include "base/android/sys_utils.h"
+#include "base/android/library_loader/library_loader_hooks.h"
#include "third_party/skia/include/core/SkGraphics.h"
#endif // OS_ANDROID
@@ -49,6 +46,10 @@
#include "third_party/WebKit/public/web/WebView.h"
#endif // OS_MACOSX
+#if defined(ENABLE_PLUGINS)
+#include "content/renderer/pepper/pepper_plugin_registry.h"
+#endif
+
#if defined(ENABLE_WEBRTC)
#include "third_party/libjingle/overrides/init_webrtc.h"
#endif
@@ -78,13 +79,13 @@ class RendererMessageLoopObserver : public base::MessageLoop::TaskObserver {
: process_times_(base::Histogram::FactoryGet(
"Chrome.ProcMsgL RenderThread",
1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag)) {}
- virtual ~RendererMessageLoopObserver() {}
+ ~RendererMessageLoopObserver() override {}
- virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
+ void WillProcessTask(const base::PendingTask& pending_task) override {
begin_process_message_ = base::TimeTicks::Now();
}
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
+ void DidProcessTask(const base::PendingTask& pending_task) override {
if (!begin_process_message_.is_null())
process_times_->AddTime(base::TimeTicks::Now() - begin_process_message_);
}
@@ -95,22 +96,6 @@ class RendererMessageLoopObserver : public base::MessageLoop::TaskObserver {
DISALLOW_COPY_AND_ASSIGN(RendererMessageLoopObserver);
};
-// For measuring memory usage after each task. Behind a command line flag.
-class MemoryObserver : public base::MessageLoop::TaskObserver {
- public:
- MemoryObserver() {}
- virtual ~MemoryObserver() {}
-
- virtual void WillProcessTask(const base::PendingTask& pending_task) OVERRIDE {
- }
-
- virtual void DidProcessTask(const base::PendingTask& pending_task) OVERRIDE {
- HISTOGRAM_MEMORY_KB("Memory.RendererUsed", GetMemoryUsageKB());
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(MemoryObserver);
-};
-
} // namespace
// mainline routine for running as the Renderer process
@@ -141,7 +126,7 @@ int RendererMain(const MainFunctionParams& parameters) {
#if defined(OS_ANDROID)
const int kMB = 1024 * 1024;
size_t font_cache_limit =
- base::android::SysUtils::IsLowEndDevice() ? kMB : 8 * kMB;
+ base::SysInfo::IsLowEndDevice() ? kMB : 8 * kMB;
SkGraphics::SetFontCacheLimit(font_cache_limit);
#endif
@@ -170,12 +155,6 @@ int RendererMain(const MainFunctionParams& parameters) {
#endif
main_message_loop.AddTaskObserver(&task_observer);
- scoped_ptr<MemoryObserver> memory_observer;
- if (parsed_command_line.HasSwitch(switches::kMemoryMetrics)) {
- memory_observer.reset(new MemoryObserver());
- main_message_loop.AddTaskObserver(memory_observer.get());
- }
-
base::PlatformThread::SetName("CrRendererMain");
bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
@@ -183,6 +162,11 @@ int RendererMain(const MainFunctionParams& parameters) {
// Initialize histogram statistics gathering system.
base::StatisticsRecorder::Initialize();
+#if defined(OS_ANDROID)
+ // If we have a pending chromium android linker histogram, record it.
+ base::android::RecordChromiumAndroidLinkerRendererHistogram();
+#endif
+
// Initialize statistical testing infrastructure. We set the entropy provider
// to NULL to disallow the renderer process from creating its own one-time
// randomized trials; they should be created in the browser process.
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
index 2258b260280..54c68517664 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
@@ -8,7 +8,7 @@
#include <sys/stat.h>
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/logging.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/public/common/content_switches.h"
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_win.cc b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
index 8ec7bcedf49..952d00d3df7 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
@@ -11,7 +11,6 @@
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
-#include "content/common/sandbox_win.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/injection_test_win.h"
#include "content/public/renderer/render_font_warmup_win.h"
@@ -25,6 +24,8 @@
#include "third_party/icu/source/i18n/unicode/timezone.h"
#include "third_party/skia/include/ports/SkFontMgr.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
+#include "ui/gfx/win/direct_write.h"
+#include "ui/gfx/win/dpi.h"
#ifdef ENABLE_VTUNE_JIT_INTERFACE
#include "v8/src/third_party/vtune/v8-vtune.h"
@@ -87,7 +88,7 @@ void RendererMainPlatformDelegate::PlatformInitialize() {
// malicious code if the renderer gets compromised.
bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);
- bool use_direct_write = ShouldUseDirectWrite();
+ bool use_direct_write = gfx::win::ShouldUseDirectWrite();
if (!no_sandbox) {
// ICU DateFormat class (used in base/time_format.cc) needs to get the
// Olson timezone ID by accessing the registry keys under
@@ -106,6 +107,7 @@ void RendererMainPlatformDelegate::PlatformInitialize() {
}
}
blink::WebFontRendering::setUseDirectWrite(use_direct_write);
+ blink::WebFontRendering::setDeviceScaleFactor(gfx::GetDPIScale());
if (use_direct_write) {
blink::WebRuntimeFeatures::enableSubpixelFontScaling(true);
}
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
index 5b781d411d5..42aae612c26 100644
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
+++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
@@ -10,7 +10,6 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
-using appcache::AppCacheBackend;
using blink::WebApplicationCacheHostClient;
using blink::WebConsoleMessage;
@@ -25,7 +24,7 @@ RendererWebApplicationCacheHostImpl::RendererWebApplicationCacheHostImpl(
}
void RendererWebApplicationCacheHostImpl::OnLogMessage(
- appcache::AppCacheLogLevel log_level, const std::string& message) {
+ AppCacheLogLevel log_level, const std::string& message) {
if (RenderThreadImpl::current()->layout_test_mode())
return;
@@ -47,7 +46,7 @@ void RendererWebApplicationCacheHostImpl::OnContentBlocked(
}
void RendererWebApplicationCacheHostImpl::OnCacheSelected(
- const appcache::AppCacheInfo& info) {
+ const AppCacheInfo& info) {
if (!info.manifest_url.is_empty()) {
RenderThreadImpl::current()->Send(new ViewHostMsg_AppCacheAccessed(
routing_id_, info.manifest_url, false));
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
index e7b2bc847fa..c8efaaf9adc 100644
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
+++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.h
@@ -15,13 +15,13 @@ class RendererWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
RendererWebApplicationCacheHostImpl(
RenderViewImpl* render_view,
blink::WebApplicationCacheHostClient* client,
- appcache::AppCacheBackend* backend);
+ AppCacheBackend* backend);
// WebApplicationCacheHostImpl:
- virtual void OnLogMessage(appcache::AppCacheLogLevel log_level,
- const std::string& message) OVERRIDE;
- virtual void OnContentBlocked(const GURL& manifest_url) OVERRIDE;
- virtual void OnCacheSelected(const appcache::AppCacheInfo& info) OVERRIDE;
+ void OnLogMessage(AppCacheLogLevel log_level,
+ const std::string& message) override;
+ void OnContentBlocked(const GURL& manifest_url) override;
+ void OnCacheSelected(const AppCacheInfo& info) override;
private:
RenderViewImpl* GetRenderView();
diff --git a/chromium/content/renderer/renderer_webcolorchooser_impl.h b/chromium/content/renderer/renderer_webcolorchooser_impl.h
index 99bd4013239..36e7fc15c60 100644
--- a/chromium/content/renderer/renderer_webcolorchooser_impl.h
+++ b/chromium/content/renderer/renderer_webcolorchooser_impl.h
@@ -41,8 +41,8 @@ class RendererWebColorChooserImpl : public blink::WebColorChooser,
// Don't destroy the RendererWebColorChooserImpl when the RenderFrame goes
// away. RendererWebColorChooserImpl is owned by
// blink::ColorChooserUIController.
- virtual void OnDestruct() OVERRIDE {}
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ void OnDestruct() override {}
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnDidChooseColorResponse(int color_chooser_id, SkColor color);
void OnDidEndColorChooser(int color_chooser_id);
diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.cc b/chromium/content/renderer/renderer_webcookiejar_impl.cc
index 93d037a32ba..f1d9a587e14 100644
--- a/chromium/content/renderer/renderer_webcookiejar_impl.cc
+++ b/chromium/content/renderer/renderer_webcookiejar_impl.cc
@@ -69,7 +69,7 @@ void RendererWebCookieJarImpl::deleteCookie(
bool RendererWebCookieJarImpl::cookiesEnabled(
const WebURL& url, const WebURL& first_party_for_cookies) {
- bool cookies_enabled;
+ bool cookies_enabled = false;
sender_->Send(new ViewHostMsg_CookiesEnabled(
sender_->GetRoutingID(), url, first_party_for_cookies, &cookies_enabled));
return cookies_enabled;
diff --git a/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc b/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc
deleted file mode 100644
index f39496e64b8..00000000000
--- a/chromium/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ /dev/null
@@ -1,1151 +0,0 @@
-// Copyright (c) 2012 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 "content/renderer/renderer_webkitplatformsupport_impl.h"
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/shared_memory.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/metrics/histogram.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/blink_glue.h"
-#include "content/child/database_util.h"
-#include "content/child/fileapi/webfilesystem_impl.h"
-#include "content/child/indexed_db/webidbfactory_impl.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/quota_dispatcher.h"
-#include "content/child/quota_message_filter.h"
-#include "content/child/simple_webmimeregistry_impl.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/child/web_database_observer_impl.h"
-#include "content/child/webblobregistry_impl.h"
-#include "content/child/webfileutilities_impl.h"
-#include "content/child/webmessageportchannel_impl.h"
-#include "content/common/file_utilities_messages.h"
-#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
-#include "content/common/mime_registry_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/webplugininfo.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/battery_status/battery_status_dispatcher.h"
-#include "content/renderer/battery_status/fake_battery_status_dispatcher.h"
-#include "content/renderer/device_sensors/device_motion_event_pump.h"
-#include "content/renderer/device_sensors/device_orientation_event_pump.h"
-#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
-#include "content/renderer/gamepad_shared_memory_reader.h"
-#include "content/renderer/media/audio_decoder.h"
-#include "content/renderer/media/crypto/key_systems.h"
-#include "content/renderer/media/renderer_webaudiodevice_impl.h"
-#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
-#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
-#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
-#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/renderer_clipboard_client.h"
-#include "content/renderer/screen_orientation/mock_screen_orientation_controller.h"
-#include "content/renderer/webclipboard_impl.h"
-#include "content/renderer/webgraphicscontext3d_provider_impl.h"
-#include "content/renderer/webpublicsuffixlist_impl.h"
-#include "gpu/config/gpu_info.h"
-#include "ipc/ipc_sync_message_filter.h"
-#include "media/audio/audio_output_device.h"
-#include "media/base/audio_hardware_config.h"
-#include "media/filters/stream_parser_factory.h"
-#include "net/base/mime_util.h"
-#include "net/base/net_util.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
-#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
-#include "third_party/WebKit/public/platform/WebDeviceMotionListener.h"
-#include "third_party/WebKit/public/platform/WebDeviceOrientationListener.h"
-#include "third_party/WebKit/public/platform/WebFileInfo.h"
-#include "third_party/WebKit/public/platform/WebGamepads.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamCenter.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
-#include "third_party/WebKit/public/platform/WebPluginListBuilder.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-#include "ui/gfx/color_profile.h"
-#include "url/gurl.h"
-#include "webkit/common/gpu/context_provider_web_context.h"
-#include "webkit/common/quota/quota_types.h"
-
-#if defined(OS_ANDROID)
-#include "content/renderer/android/synchronous_compositor_factory.h"
-#include "content/renderer/media/android/audio_decoder_android.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "content/common/mac/font_descriptor.h"
-#include "content/common/mac/font_loader.h"
-#include "content/renderer/webscrollbarbehavior_impl_mac.h"
-#include "third_party/WebKit/public/platform/mac/WebSandboxSupport.h"
-#endif
-
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-#include <map>
-#include <string>
-
-#include "base/synchronization/lock.h"
-#include "content/common/child_process_sandbox_support_impl_linux.h"
-#include "third_party/WebKit/public/platform/linux/WebFallbackFont.h"
-#include "third_party/WebKit/public/platform/linux/WebSandboxSupport.h"
-#include "third_party/icu/source/common/unicode/utf16.h"
-#endif
-#endif
-
-#if defined(OS_WIN)
-#include "content/common/child_process_messages.h"
-#include "third_party/WebKit/public/platform/win/WebSandboxSupport.h"
-#endif
-
-#if defined(USE_AURA)
-#include "content/renderer/webscrollbarbehavior_impl_gtkoraura.h"
-#elif !defined(OS_MACOSX)
-#include "third_party/WebKit/public/platform/WebScrollbarBehavior.h"
-#define WebScrollbarBehaviorImpl blink::WebScrollbarBehavior
-#endif
-
-using blink::Platform;
-using blink::WebAudioDevice;
-using blink::WebBlobRegistry;
-using blink::WebDatabaseObserver;
-using blink::WebFileInfo;
-using blink::WebFileSystem;
-using blink::WebGamepad;
-using blink::WebGamepads;
-using blink::WebIDBFactory;
-using blink::WebMIDIAccessor;
-using blink::WebMediaStreamCenter;
-using blink::WebMediaStreamCenterClient;
-using blink::WebMimeRegistry;
-using blink::WebRTCPeerConnectionHandler;
-using blink::WebRTCPeerConnectionHandlerClient;
-using blink::WebStorageNamespace;
-using blink::WebString;
-using blink::WebURL;
-using blink::WebVector;
-
-namespace content {
-
-namespace {
-
-static bool g_sandbox_enabled = true;
-base::LazyInstance<blink::WebDeviceMotionData>::Leaky
- g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<blink::WebDeviceOrientationData>::Leaky
- g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<MockScreenOrientationController>::Leaky
- g_test_screen_orientation_controller = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<FakeBatteryStatusDispatcher>::Leaky
- g_test_battery_status_dispatcher = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-//------------------------------------------------------------------------------
-
-class RendererWebKitPlatformSupportImpl::MimeRegistry
- : public SimpleWebMimeRegistryImpl {
- public:
- virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
- const blink::WebString& mime_type,
- const blink::WebString& codecs,
- const blink::WebString& key_system);
- virtual bool supportsMediaSourceMIMEType(const blink::WebString& mime_type,
- const blink::WebString& codecs);
- virtual bool supportsEncryptedMediaMIMEType(const WebString& key_system,
- const WebString& mime_type,
- const WebString& codecs) OVERRIDE;
- virtual blink::WebString mimeTypeForExtension(
- const blink::WebString& file_extension);
- virtual blink::WebString mimeTypeFromFile(
- const blink::WebString& file_path);
-};
-
-class RendererWebKitPlatformSupportImpl::FileUtilities
- : public WebFileUtilitiesImpl {
- public:
- explicit FileUtilities(ThreadSafeSender* sender)
- : thread_safe_sender_(sender) {}
- virtual bool getFileInfo(const WebString& path, WebFileInfo& result);
- private:
- bool SendSyncMessageFromAnyThread(IPC::SyncMessage* msg) const;
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
-};
-
-#if defined(OS_ANDROID)
-// WebKit doesn't use WebSandboxSupport on android so we don't need to
-// implement anything here.
-class RendererWebKitPlatformSupportImpl::SandboxSupport {
-};
-#else
-class RendererWebKitPlatformSupportImpl::SandboxSupport
- : public blink::WebSandboxSupport {
- public:
- virtual ~SandboxSupport() {}
-
-#if defined(OS_WIN)
- virtual bool ensureFontLoaded(HFONT);
-#elif defined(OS_MACOSX)
- virtual bool loadFont(
- NSFont* src_font,
- CGFontRef* container,
- uint32* font_id);
-#elif defined(OS_POSIX)
- virtual void getFallbackFontForCharacter(
- blink::WebUChar32 character,
- const char* preferred_locale,
- blink::WebFallbackFont* fallbackFont);
- virtual void getRenderStyleForStrike(
- const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out);
-
- private:
- // WebKit likes to ask us for the correct font family to use for a set of
- // unicode code points. It needs this information frequently so we cache it
- // here.
- base::Lock unicode_font_families_mutex_;
- std::map<int32_t, blink::WebFallbackFont> unicode_font_families_;
-#endif
-};
-#endif // defined(OS_ANDROID)
-
-//------------------------------------------------------------------------------
-
-RendererWebKitPlatformSupportImpl::RendererWebKitPlatformSupportImpl()
- : clipboard_client_(new RendererClipboardClient),
- clipboard_(new WebClipboardImpl(clipboard_client_.get())),
- mime_registry_(new RendererWebKitPlatformSupportImpl::MimeRegistry),
- sudden_termination_disables_(0),
- plugin_refresh_allowed_(true),
- child_thread_loop_(base::MessageLoopProxy::current()),
- web_scrollbar_behavior_(new WebScrollbarBehaviorImpl),
- gamepad_provider_(NULL) {
- if (g_sandbox_enabled && sandboxEnabled()) {
- sandbox_support_.reset(
- new RendererWebKitPlatformSupportImpl::SandboxSupport);
- } else {
- DVLOG(1) << "Disabling sandbox support for testing.";
- }
-
- // ChildThread may not exist in some tests.
- if (ChildThread::current()) {
- sync_message_filter_ = ChildThread::current()->sync_message_filter();
- thread_safe_sender_ = ChildThread::current()->thread_safe_sender();
- quota_message_filter_ = ChildThread::current()->quota_message_filter();
- blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_));
- web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_));
- web_database_observer_impl_.reset(
- new WebDatabaseObserverImpl(sync_message_filter_));
- }
-}
-
-RendererWebKitPlatformSupportImpl::~RendererWebKitPlatformSupportImpl() {
- WebFileSystemImpl::DeleteThreadSpecificInstance();
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebClipboard* RendererWebKitPlatformSupportImpl::clipboard() {
- blink::WebClipboard* clipboard =
- GetContentClient()->renderer()->OverrideWebClipboard();
- if (clipboard)
- return clipboard;
- return clipboard_.get();
-}
-
-blink::WebMimeRegistry* RendererWebKitPlatformSupportImpl::mimeRegistry() {
- return mime_registry_.get();
-}
-
-blink::WebFileUtilities*
-RendererWebKitPlatformSupportImpl::fileUtilities() {
- if (!file_utilities_) {
- file_utilities_.reset(new FileUtilities(thread_safe_sender_.get()));
- file_utilities_->set_sandbox_enabled(sandboxEnabled());
- }
- return file_utilities_.get();
-}
-
-blink::WebSandboxSupport* RendererWebKitPlatformSupportImpl::sandboxSupport() {
-#if defined(OS_ANDROID)
- // WebKit doesn't use WebSandboxSupport on android.
- return NULL;
-#else
- return sandbox_support_.get();
-#endif
-}
-
-blink::WebCookieJar* RendererWebKitPlatformSupportImpl::cookieJar() {
- NOTREACHED() << "Use WebFrameClient::cookieJar() instead!";
- return NULL;
-}
-
-blink::WebThemeEngine* RendererWebKitPlatformSupportImpl::themeEngine() {
- blink::WebThemeEngine* theme_engine =
- GetContentClient()->renderer()->OverrideThemeEngine();
- if (theme_engine)
- return theme_engine;
- return BlinkPlatformImpl::themeEngine();
-}
-
-bool RendererWebKitPlatformSupportImpl::sandboxEnabled() {
- // As explained in Platform.h, this function is used to decide
- // whether to allow file system operations to come out of WebKit or not.
- // Even if the sandbox is disabled, there's no reason why the code should
- // act any differently...unless we're in single process mode. In which
- // case, we have no other choice. Platform.h discourages using
- // this switch unless absolutely necessary, so hopefully we won't end up
- // with too many code paths being different in single-process mode.
- return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
-}
-
-unsigned long long RendererWebKitPlatformSupportImpl::visitedLinkHash(
- const char* canonical_url,
- size_t length) {
- return GetContentClient()->renderer()->VisitedLinkHash(canonical_url, length);
-}
-
-bool RendererWebKitPlatformSupportImpl::isLinkVisited(
- unsigned long long link_hash) {
- return GetContentClient()->renderer()->IsLinkVisited(link_hash);
-}
-
-void RendererWebKitPlatformSupportImpl::createMessageChannel(
- blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2) {
- WebMessagePortChannelImpl::CreatePair(
- child_thread_loop_.get(), channel1, channel2);
-}
-
-blink::WebPrescientNetworking*
-RendererWebKitPlatformSupportImpl::prescientNetworking() {
- return GetContentClient()->renderer()->GetPrescientNetworking();
-}
-
-bool
-RendererWebKitPlatformSupportImpl::CheckPreparsedJsCachingEnabled() const {
- static bool checked = false;
- static bool result = false;
- if (!checked) {
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- result = command_line.HasSwitch(switches::kEnablePreparsedJsCaching);
- checked = true;
- }
- return result;
-}
-
-void RendererWebKitPlatformSupportImpl::cacheMetadata(
- const blink::WebURL& url,
- double response_time,
- const char* data,
- size_t size) {
- if (!CheckPreparsedJsCachingEnabled())
- return;
-
- // Let the browser know we generated cacheable metadata for this resource. The
- // browser may cache it and return it on subsequent responses to speed
- // the processing of this resource.
- std::vector<char> copy(data, data + size);
- RenderThread::Get()->Send(
- new ViewHostMsg_DidGenerateCacheableMetadata(url, response_time, copy));
-}
-
-WebString RendererWebKitPlatformSupportImpl::defaultLocale() {
- return base::ASCIIToUTF16(RenderThread::Get()->GetLocale());
-}
-
-void RendererWebKitPlatformSupportImpl::suddenTerminationChanged(bool enabled) {
- if (enabled) {
- // We should not get more enables than disables, but we want it to be a
- // non-fatal error if it does happen.
- DCHECK_GT(sudden_termination_disables_, 0);
- sudden_termination_disables_ = std::max(sudden_termination_disables_ - 1,
- 0);
- if (sudden_termination_disables_ != 0)
- return;
- } else {
- sudden_termination_disables_++;
- if (sudden_termination_disables_ != 1)
- return;
- }
-
- RenderThread* thread = RenderThread::Get();
- if (thread) // NULL in unittests.
- thread->Send(new ViewHostMsg_SuddenTerminationChanged(enabled));
-}
-
-WebStorageNamespace*
-RendererWebKitPlatformSupportImpl::createLocalStorageNamespace() {
- return new WebStorageNamespaceImpl();
-}
-
-
-//------------------------------------------------------------------------------
-
-WebIDBFactory* RendererWebKitPlatformSupportImpl::idbFactory() {
- return web_idb_factory_.get();
-}
-
-//------------------------------------------------------------------------------
-
-WebFileSystem* RendererWebKitPlatformSupportImpl::fileSystem() {
- return WebFileSystemImpl::ThreadSpecificInstance(child_thread_loop_.get());
-}
-
-//------------------------------------------------------------------------------
-
-WebMimeRegistry::SupportsType
-RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaMIMEType(
- const WebString& mime_type,
- const WebString& codecs,
- const WebString& key_system) {
- const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
- // Not supporting the container is a flat-out no.
- if (!net::IsSupportedMediaMimeType(mime_type_ascii))
- return IsNotSupported;
-
- if (!key_system.isEmpty()) {
- // Check whether the key system is supported with the mime_type and codecs.
-
- // Chromium only supports ASCII parameters.
- if (!base::IsStringASCII(key_system))
- return IsNotSupported;
-
- std::string key_system_ascii =
- GetUnprefixedKeySystemName(base::UTF16ToASCII(key_system));
- std::vector<std::string> strict_codecs;
- bool strip_suffix = !net::IsStrictMediaMimeType(mime_type_ascii);
- net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, strip_suffix);
-
- if (!IsSupportedKeySystemWithMediaMimeType(
- mime_type_ascii, strict_codecs, key_system_ascii)) {
- return IsNotSupported;
- }
-
- // Continue processing the mime_type and codecs.
- }
-
- // Check list of strict codecs to see if it is supported.
- if (net::IsStrictMediaMimeType(mime_type_ascii)) {
- // Check if the codecs are a perfect match.
- std::vector<std::string> strict_codecs;
- net::ParseCodecString(ToASCIIOrEmpty(codecs), &strict_codecs, false);
- if (net::IsSupportedStrictMediaMimeType(mime_type_ascii, strict_codecs))
- return IsSupported;
-
- // We support the container, but no codecs were specified.
- if (codecs.isNull())
- return MayBeSupported;
-
- return IsNotSupported;
- }
-
- // If we don't recognize the codec, it's possible we support it.
- std::vector<std::string> parsed_codecs;
- net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codecs, true);
- if (!net::AreSupportedMediaCodecs(parsed_codecs))
- return MayBeSupported;
-
- // Otherwise we have a perfect match.
- return IsSupported;
-}
-
-bool
-RendererWebKitPlatformSupportImpl::MimeRegistry::supportsMediaSourceMIMEType(
- const blink::WebString& mime_type,
- const WebString& codecs) {
- const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
- std::vector<std::string> parsed_codec_ids;
- net::ParseCodecString(ToASCIIOrEmpty(codecs), &parsed_codec_ids, false);
- if (mime_type_ascii.empty())
- return false;
- return media::StreamParserFactory::IsTypeSupported(
- mime_type_ascii, parsed_codec_ids);
-}
-
-bool
-RendererWebKitPlatformSupportImpl::MimeRegistry::supportsEncryptedMediaMIMEType(
- const WebString& key_system,
- const WebString& mime_type,
- const WebString& codecs) {
- // Chromium only supports ASCII parameters.
- if (!base::IsStringASCII(key_system) || !base::IsStringASCII(mime_type) ||
- !base::IsStringASCII(codecs)) {
- return false;
- }
-
- if (key_system.isEmpty())
- return false;
-
- const std::string mime_type_ascii = base::UTF16ToASCII(mime_type);
-
- std::vector<std::string> codec_vector;
- bool strip_suffix = !net::IsStrictMediaMimeType(mime_type_ascii);
- net::ParseCodecString(base::UTF16ToASCII(codecs), &codec_vector,
- strip_suffix);
-
- return IsSupportedKeySystemWithMediaMimeType(
- mime_type_ascii, codec_vector, base::UTF16ToASCII(key_system));
-}
-
-WebString
-RendererWebKitPlatformSupportImpl::MimeRegistry::mimeTypeForExtension(
- const WebString& file_extension) {
- if (IsPluginProcess())
- return SimpleWebMimeRegistryImpl::mimeTypeForExtension(file_extension);
-
- // The sandbox restricts our access to the registry, so we need to proxy
- // these calls over to the browser process.
- std::string mime_type;
- RenderThread::Get()->Send(
- new MimeRegistryMsg_GetMimeTypeFromExtension(
- base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type));
- return base::ASCIIToUTF16(mime_type);
-}
-
-WebString RendererWebKitPlatformSupportImpl::MimeRegistry::mimeTypeFromFile(
- const WebString& file_path) {
- if (IsPluginProcess())
- return SimpleWebMimeRegistryImpl::mimeTypeFromFile(file_path);
-
- // The sandbox restricts our access to the registry, so we need to proxy
- // these calls over to the browser process.
- std::string mime_type;
- RenderThread::Get()->Send(new MimeRegistryMsg_GetMimeTypeFromFile(
- base::FilePath::FromUTF16Unsafe(file_path),
- &mime_type));
- return base::ASCIIToUTF16(mime_type);
-}
-
-//------------------------------------------------------------------------------
-
-bool RendererWebKitPlatformSupportImpl::FileUtilities::getFileInfo(
- const WebString& path,
- WebFileInfo& web_file_info) {
- base::File::Info file_info;
- base::File::Error status;
- if (!SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileInfo(
- base::FilePath::FromUTF16Unsafe(path), &file_info, &status)) ||
- status != base::File::FILE_OK) {
- return false;
- }
- FileInfoToWebFileInfo(file_info, &web_file_info);
- web_file_info.platformPath = path;
- return true;
-}
-
-bool RendererWebKitPlatformSupportImpl::FileUtilities::
-SendSyncMessageFromAnyThread(IPC::SyncMessage* msg) const {
- base::TimeTicks begin = base::TimeTicks::Now();
- const bool success = thread_safe_sender_->Send(msg);
- base::TimeDelta delta = base::TimeTicks::Now() - begin;
- UMA_HISTOGRAM_TIMES("RendererSyncIPC.ElapsedTime", delta);
- return success;
-}
-
-//------------------------------------------------------------------------------
-
-#if defined(OS_WIN)
-
-bool RendererWebKitPlatformSupportImpl::SandboxSupport::ensureFontLoaded(
- HFONT font) {
- LOGFONT logfont;
- GetObject(font, sizeof(LOGFONT), &logfont);
- RenderThread::Get()->PreCacheFont(logfont);
- return true;
-}
-
-#elif defined(OS_MACOSX)
-
-bool RendererWebKitPlatformSupportImpl::SandboxSupport::loadFont(
- NSFont* src_font, CGFontRef* out, uint32* font_id) {
- uint32 font_data_size;
- FontDescriptor src_font_descriptor(src_font);
- base::SharedMemoryHandle font_data;
- if (!RenderThread::Get()->Send(new ViewHostMsg_LoadFont(
- src_font_descriptor, &font_data_size, &font_data, font_id))) {
- *out = NULL;
- *font_id = 0;
- return false;
- }
-
- if (font_data_size == 0 || font_data == base::SharedMemory::NULLHandle() ||
- *font_id == 0) {
- LOG(ERROR) << "Bad response from ViewHostMsg_LoadFont() for " <<
- src_font_descriptor.font_name;
- *out = NULL;
- *font_id = 0;
- return false;
- }
-
- // TODO(jeremy): Need to call back into WebKit to make sure that the font
- // isn't already activated, based on the font id. If it's already
- // activated, don't reactivate it here - crbug.com/72727 .
-
- return FontLoader::CGFontRefFromBuffer(font_data, font_data_size, out);
-}
-
-#elif defined(OS_ANDROID)
-
-// WebKit doesn't use WebSandboxSupport on android so we don't need to
-// implement anything here. This is cleaner to support than excluding the
-// whole class for android.
-
-#elif defined(OS_POSIX)
-
-void
-RendererWebKitPlatformSupportImpl::SandboxSupport::getFallbackFontForCharacter(
- blink::WebUChar32 character,
- const char* preferred_locale,
- blink::WebFallbackFont* fallbackFont) {
- base::AutoLock lock(unicode_font_families_mutex_);
- const std::map<int32_t, blink::WebFallbackFont>::const_iterator iter =
- unicode_font_families_.find(character);
- if (iter != unicode_font_families_.end()) {
- fallbackFont->name = iter->second.name;
- fallbackFont->filename = iter->second.filename;
- fallbackFont->ttcIndex = iter->second.ttcIndex;
- fallbackFont->isBold = iter->second.isBold;
- fallbackFont->isItalic = iter->second.isItalic;
- return;
- }
-
- GetFallbackFontForCharacter(character, preferred_locale, fallbackFont);
- unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
-}
-
-void
-RendererWebKitPlatformSupportImpl::SandboxSupport::getRenderStyleForStrike(
- const char* family, int sizeAndStyle, blink::WebFontRenderStyle* out) {
- GetRenderStyleForStrike(family, sizeAndStyle, out);
-}
-
-#endif
-
-//------------------------------------------------------------------------------
-
-Platform::FileHandle
-RendererWebKitPlatformSupportImpl::databaseOpenFile(
- const WebString& vfs_file_name, int desired_flags) {
- return DatabaseUtil::DatabaseOpenFile(
- vfs_file_name, desired_flags, sync_message_filter_.get());
-}
-
-int RendererWebKitPlatformSupportImpl::databaseDeleteFile(
- const WebString& vfs_file_name, bool sync_dir) {
- return DatabaseUtil::DatabaseDeleteFile(
- vfs_file_name, sync_dir, sync_message_filter_.get());
-}
-
-long RendererWebKitPlatformSupportImpl::databaseGetFileAttributes(
- const WebString& vfs_file_name) {
- return DatabaseUtil::DatabaseGetFileAttributes(vfs_file_name,
- sync_message_filter_.get());
-}
-
-long long RendererWebKitPlatformSupportImpl::databaseGetFileSize(
- const WebString& vfs_file_name) {
- return DatabaseUtil::DatabaseGetFileSize(vfs_file_name,
- sync_message_filter_.get());
-}
-
-long long RendererWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
- const WebString& origin_identifier) {
- return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
- sync_message_filter_.get());
-}
-
-bool RendererWebKitPlatformSupportImpl::canAccelerate2dCanvas() {
- RenderThreadImpl* thread = RenderThreadImpl::current();
- GpuChannelHost* host = thread->EstablishGpuChannelSync(
- CAUSE_FOR_GPU_LAUNCH_CANVAS_2D);
- if (!host)
- return false;
-
- return host->gpu_info().SupportsAccelerated2dCanvas();
-}
-
-bool RendererWebKitPlatformSupportImpl::isThreadedCompositingEnabled() {
- RenderThreadImpl* thread = RenderThreadImpl::current();
- // thread can be NULL in tests.
- return thread && thread->compositor_message_loop_proxy().get();
-}
-
-double RendererWebKitPlatformSupportImpl::audioHardwareSampleRate() {
- RenderThreadImpl* thread = RenderThreadImpl::current();
- return thread->GetAudioHardwareConfig()->GetOutputSampleRate();
-}
-
-size_t RendererWebKitPlatformSupportImpl::audioHardwareBufferSize() {
- RenderThreadImpl* thread = RenderThreadImpl::current();
- return thread->GetAudioHardwareConfig()->GetOutputBufferSize();
-}
-
-unsigned RendererWebKitPlatformSupportImpl::audioHardwareOutputChannels() {
- RenderThreadImpl* thread = RenderThreadImpl::current();
- return thread->GetAudioHardwareConfig()->GetOutputChannels();
-}
-
-WebDatabaseObserver* RendererWebKitPlatformSupportImpl::databaseObserver() {
- return web_database_observer_impl_.get();
-}
-
-WebAudioDevice*
-RendererWebKitPlatformSupportImpl::createAudioDevice(
- size_t buffer_size,
- unsigned input_channels,
- unsigned channels,
- double sample_rate,
- WebAudioDevice::RenderCallback* callback,
- const blink::WebString& input_device_id) {
- // Use a mock for testing.
- blink::WebAudioDevice* mock_device =
- GetContentClient()->renderer()->OverrideCreateAudioDevice(sample_rate);
- if (mock_device)
- return mock_device;
-
- // The |channels| does not exactly identify the channel layout of the
- // device. The switch statement below assigns a best guess to the channel
- // layout based on number of channels.
- // TODO(crogers): WebKit should give the channel layout instead of the hard
- // channel count.
- media::ChannelLayout layout = media::CHANNEL_LAYOUT_UNSUPPORTED;
- switch (channels) {
- case 1:
- layout = media::CHANNEL_LAYOUT_MONO;
- break;
- case 2:
- layout = media::CHANNEL_LAYOUT_STEREO;
- break;
- case 3:
- layout = media::CHANNEL_LAYOUT_2_1;
- break;
- case 4:
- layout = media::CHANNEL_LAYOUT_4_0;
- break;
- case 5:
- layout = media::CHANNEL_LAYOUT_5_0;
- break;
- case 6:
- layout = media::CHANNEL_LAYOUT_5_1;
- break;
- case 7:
- layout = media::CHANNEL_LAYOUT_7_0;
- break;
- case 8:
- layout = media::CHANNEL_LAYOUT_7_1;
- break;
- default:
- layout = media::CHANNEL_LAYOUT_STEREO;
- }
-
- int session_id = 0;
- if (input_device_id.isNull() ||
- !base::StringToInt(base::UTF16ToUTF8(input_device_id), &session_id)) {
- if (input_channels > 0)
- DLOG(WARNING) << "createAudioDevice(): request for audio input ignored";
-
- input_channels = 0;
- }
-
- media::AudioParameters params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- layout, input_channels,
- static_cast<int>(sample_rate), 16, buffer_size,
- media::AudioParameters::NO_EFFECTS);
-
- return new RendererWebAudioDeviceImpl(params, callback, session_id);
-}
-
-#if defined(OS_ANDROID)
-bool RendererWebKitPlatformSupportImpl::loadAudioResource(
- blink::WebAudioBus* destination_bus, const char* audio_file_data,
- size_t data_size) {
- return DecodeAudioFileData(destination_bus,
- audio_file_data,
- data_size,
- thread_safe_sender_);
-}
-#else
-bool RendererWebKitPlatformSupportImpl::loadAudioResource(
- blink::WebAudioBus* destination_bus, const char* audio_file_data,
- size_t data_size) {
- return DecodeAudioFileData(
- destination_bus, audio_file_data, data_size);
-}
-#endif // defined(OS_ANDROID)
-
-//------------------------------------------------------------------------------
-
-blink::WebMIDIAccessor*
-RendererWebKitPlatformSupportImpl::createMIDIAccessor(
- blink::WebMIDIAccessorClient* client) {
- blink::WebMIDIAccessor* accessor =
- GetContentClient()->renderer()->OverrideCreateMIDIAccessor(client);
- if (accessor)
- return accessor;
-
- return new RendererWebMIDIAccessorImpl(client);
-}
-
-void RendererWebKitPlatformSupportImpl::getPluginList(
- bool refresh,
- blink::WebPluginListBuilder* builder) {
-#if defined(ENABLE_PLUGINS)
- std::vector<WebPluginInfo> plugins;
- if (!plugin_refresh_allowed_)
- refresh = false;
- RenderThread::Get()->Send(
- new ViewHostMsg_GetPlugins(refresh, &plugins));
- for (size_t i = 0; i < plugins.size(); ++i) {
- const WebPluginInfo& plugin = plugins[i];
-
- builder->addPlugin(
- plugin.name, plugin.desc,
- plugin.path.BaseName().AsUTF16Unsafe());
-
- for (size_t j = 0; j < plugin.mime_types.size(); ++j) {
- const WebPluginMimeType& mime_type = plugin.mime_types[j];
-
- builder->addMediaTypeToLastPlugin(
- WebString::fromUTF8(mime_type.mime_type), mime_type.description);
-
- for (size_t k = 0; k < mime_type.file_extensions.size(); ++k) {
- builder->addFileExtensionToLastMediaType(
- WebString::fromUTF8(mime_type.file_extensions[k]));
- }
- }
- }
-#endif
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebPublicSuffixList*
-RendererWebKitPlatformSupportImpl::publicSuffixList() {
- return &public_suffix_list_;
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebString
-RendererWebKitPlatformSupportImpl::signedPublicKeyAndChallengeString(
- unsigned key_size_index,
- const blink::WebString& challenge,
- const blink::WebURL& url) {
- std::string signed_public_key;
- RenderThread::Get()->Send(new ViewHostMsg_Keygen(
- static_cast<uint32>(key_size_index),
- challenge.utf8(),
- GURL(url),
- &signed_public_key));
- return WebString::fromUTF8(signed_public_key);
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::screenColorProfile(
- WebVector<char>* to_profile) {
-#if defined(OS_WIN)
- // On Windows screen color profile is only available in the browser.
- std::vector<char> profile;
- // This Send() can be called from any impl-side thread. Use a thread
- // safe send to avoid crashing trying to access RenderThread::Get(),
- // which is not accessible from arbitrary threads.
- thread_safe_sender_->Send(
- new ViewHostMsg_GetMonitorColorProfile(&profile));
- *to_profile = profile;
-#else
- // On other platforms, the primary monitor color profile can be read
- // directly.
- gfx::ColorProfile profile;
- *to_profile = profile.profile();
-#endif
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebScrollbarBehavior*
- RendererWebKitPlatformSupportImpl::scrollbarBehavior() {
- return web_scrollbar_behavior_.get();
-}
-
-//------------------------------------------------------------------------------
-
-WebBlobRegistry* RendererWebKitPlatformSupportImpl::blobRegistry() {
- // blob_registry_ can be NULL when running some tests.
- return blob_registry_.get();
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::sampleGamepads(WebGamepads& gamepads) {
- DCHECK(gamepad_provider_);
- gamepad_provider_->SampleGamepads(gamepads);
-}
-
-void RendererWebKitPlatformSupportImpl::setGamepadListener(
- blink::WebGamepadListener* listener) {
- DCHECK(gamepad_provider_);
- gamepad_provider_->SetGamepadListener(listener);
-}
-
-//------------------------------------------------------------------------------
-
-WebRTCPeerConnectionHandler*
-RendererWebKitPlatformSupportImpl::createRTCPeerConnectionHandler(
- WebRTCPeerConnectionHandlerClient* client) {
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- DCHECK(render_thread);
- if (!render_thread)
- return NULL;
-
-#if defined(ENABLE_WEBRTC)
- WebRTCPeerConnectionHandler* peer_connection_handler =
- GetContentClient()->renderer()->OverrideCreateWebRTCPeerConnectionHandler(
- client);
- if (peer_connection_handler)
- return peer_connection_handler;
-
- PeerConnectionDependencyFactory* rtc_dependency_factory =
- render_thread->GetPeerConnectionDependencyFactory();
- return rtc_dependency_factory->CreateRTCPeerConnectionHandler(client);
-#else
- return NULL;
-#endif // defined(ENABLE_WEBRTC)
-}
-
-//------------------------------------------------------------------------------
-
-WebMediaStreamCenter*
-RendererWebKitPlatformSupportImpl::createMediaStreamCenter(
- WebMediaStreamCenterClient* client) {
- RenderThreadImpl* render_thread = RenderThreadImpl::current();
- DCHECK(render_thread);
- if (!render_thread)
- return NULL;
- return render_thread->CreateMediaStreamCenter(client);
-}
-
-// static
-bool RendererWebKitPlatformSupportImpl::SetSandboxEnabledForTesting(
- bool enable) {
- bool was_enabled = g_sandbox_enabled;
- g_sandbox_enabled = enable;
- return was_enabled;
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebSpeechSynthesizer*
-RendererWebKitPlatformSupportImpl::createSpeechSynthesizer(
- blink::WebSpeechSynthesizerClient* client) {
- return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
-}
-
-//------------------------------------------------------------------------------
-
-bool RendererWebKitPlatformSupportImpl::processMemorySizesInBytes(
- size_t* private_bytes, size_t* shared_bytes) {
- content::RenderThread::Get()->Send(
- new ViewHostMsg_GetProcessMemorySizes(private_bytes, shared_bytes));
- return true;
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebGraphicsContext3D*
-RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes) {
- return createOffscreenGraphicsContext3D(attributes, NULL);
-}
-
-blink::WebGraphicsContext3D*
-RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes,
- blink::WebGraphicsContext3D* share_context) {
- if (!RenderThreadImpl::current())
- return NULL;
-
-#if defined(OS_ANDROID)
- if (SynchronousCompositorFactory* factory =
- SynchronousCompositorFactory::GetInstance()) {
- return factory->CreateOffscreenGraphicsContext3D(attributes);
- }
-#endif
-
- scoped_refptr<GpuChannelHost> gpu_channel_host(
- RenderThreadImpl::current()->EstablishGpuChannelSync(
- CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
-
- WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
- bool lose_context_when_out_of_memory = false;
- return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- gpu_channel_host.get(),
- attributes,
- lose_context_when_out_of_memory,
- GURL(attributes.topDocumentURL),
- limits,
- static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context));
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebGraphicsContext3DProvider* RendererWebKitPlatformSupportImpl::
- createSharedOffscreenGraphicsContext3DProvider() {
- scoped_refptr<webkit::gpu::ContextProviderWebContext> provider =
- RenderThreadImpl::current()->SharedMainThreadContextProvider();
- if (!provider)
- return NULL;
- return new WebGraphicsContext3DProviderImpl(provider);
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebCompositorSupport*
-RendererWebKitPlatformSupportImpl::compositorSupport() {
- return &compositor_support_;
-}
-
-//------------------------------------------------------------------------------
-
-blink::WebString RendererWebKitPlatformSupportImpl::convertIDNToUnicode(
- const blink::WebString& host,
- const blink::WebString& languages) {
- return net::IDNToUnicode(host.utf8(), languages.utf8());
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::setDeviceMotionListener(
- blink::WebDeviceMotionListener* listener) {
- if (g_test_device_motion_data == 0) {
- if (!device_motion_event_pump_) {
- device_motion_event_pump_.reset(new DeviceMotionEventPump);
- device_motion_event_pump_->Attach(RenderThreadImpl::current());
- }
- device_motion_event_pump_->SetListener(listener);
- } else if (listener) {
- // Testing mode: just echo the test data to the listener.
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(&blink::WebDeviceMotionListener::didChangeDeviceMotion,
- base::Unretained(listener),
- g_test_device_motion_data.Get()));
- }
-}
-
-// static
-void RendererWebKitPlatformSupportImpl::SetMockDeviceMotionDataForTesting(
- const blink::WebDeviceMotionData& data) {
- g_test_device_motion_data.Get() = data;
-}
-
-// static
-void RendererWebKitPlatformSupportImpl::ResetMockScreenOrientationForTesting()
-{
- if (!(g_test_screen_orientation_controller == 0))
- g_test_screen_orientation_controller.Get().ResetData();
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::setDeviceOrientationListener(
- blink::WebDeviceOrientationListener* listener) {
- if (g_test_device_orientation_data == 0) {
- if (!device_orientation_event_pump_) {
- device_orientation_event_pump_.reset(new DeviceOrientationEventPump);
- device_orientation_event_pump_->Attach(RenderThreadImpl::current());
- }
- device_orientation_event_pump_->SetListener(listener);
- } else if (listener) {
- // Testing mode: just echo the test data to the listener.
- base::MessageLoopProxy::current()->PostTask(
- FROM_HERE,
- base::Bind(
- &blink::WebDeviceOrientationListener::didChangeDeviceOrientation,
- base::Unretained(listener),
- g_test_device_orientation_data.Get()));
- }
-}
-
-// static
-void RendererWebKitPlatformSupportImpl::SetMockDeviceOrientationDataForTesting(
- const blink::WebDeviceOrientationData& data) {
- g_test_device_orientation_data.Get() = data;
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::vibrate(unsigned int milliseconds) {
- RenderThread::Get()->Send(
- new ViewHostMsg_Vibrate(base::checked_cast<int64>(milliseconds)));
-}
-
-void RendererWebKitPlatformSupportImpl::cancelVibration() {
- RenderThread::Get()->Send(new ViewHostMsg_CancelVibration());
-}
-
-//------------------------------------------------------------------------------
-
-// static
-void RendererWebKitPlatformSupportImpl::SetMockScreenOrientationForTesting(
- RenderView* render_view,
- blink::WebScreenOrientationType orientation) {
- g_test_screen_orientation_controller.Get()
- .UpdateDeviceOrientation(render_view, orientation);
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::queryStorageUsageAndQuota(
- const blink::WebURL& storage_partition,
- blink::WebStorageQuotaType type,
- blink::WebStorageQuotaCallbacks callbacks) {
- if (!thread_safe_sender_.get() || !quota_message_filter_.get())
- return;
- QuotaDispatcher::ThreadSpecificInstance(
- thread_safe_sender_.get(),
- quota_message_filter_.get())->QueryStorageUsageAndQuota(
- storage_partition,
- static_cast<quota::StorageType>(type),
- QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
-}
-
-//------------------------------------------------------------------------------
-
-void RendererWebKitPlatformSupportImpl::setBatteryStatusListener(
- blink::WebBatteryStatusListener* listener) {
- if (RenderThreadImpl::current() &&
- RenderThreadImpl::current()->layout_test_mode()) {
- // If we are in test mode, we want to use a fake battery status dispatcher,
- // which does not communicate with the browser process. Battery status
- // changes are signalled by invoking MockBatteryStatusChangedForTesting().
- g_test_battery_status_dispatcher.Get().SetListener(listener);
- return;
- }
-
- if (!battery_status_dispatcher_) {
- battery_status_dispatcher_.reset(
- new BatteryStatusDispatcher(RenderThreadImpl::current()));
- }
- battery_status_dispatcher_->SetListener(listener);
-}
-
-// static
-void RendererWebKitPlatformSupportImpl::MockBatteryStatusChangedForTesting(
- const blink::WebBatteryStatus& status) {
- g_test_battery_status_dispatcher.Get().PostBatteryStatusChange(status);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/renderer_webkitplatformsupport_impl.h b/chromium/content/renderer/renderer_webkitplatformsupport_impl.h
deleted file mode 100644
index 66b269a57b8..00000000000
--- a/chromium/content/renderer/renderer_webkitplatformsupport_impl.h
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_RENDERER_RENDERER_WEBKITPLATFORMSUPPORT_IMPL_H_
-#define CONTENT_RENDERER_RENDERER_WEBKITPLATFORMSUPPORT_IMPL_H_
-
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/child/blink_platform_impl.h"
-#include "content/common/content_export.h"
-#include "content/renderer/compositor_bindings/web_compositor_support_impl.h"
-#include "content/renderer/webpublicsuffixlist_impl.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
-#include "third_party/WebKit/public/platform/WebIDBFactory.h"
-#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace cc {
-class ContextProvider;
-}
-
-namespace IPC {
-class SyncMessageFilter;
-}
-
-namespace blink {
-class WebBatteryStatus;
-class WebDeviceMotionData;
-class WebDeviceOrientationData;
-class WebGraphicsContext3DProvider;
-}
-
-namespace content {
-class BatteryStatusDispatcher;
-class DeviceMotionEventPump;
-class DeviceOrientationEventPump;
-class QuotaMessageFilter;
-class RendererClipboardClient;
-class RenderView;
-class RendererGamepadProvider;
-class ThreadSafeSender;
-class WebClipboardImpl;
-class WebDatabaseObserverImpl;
-class WebFileSystemImpl;
-
-class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
- : public BlinkPlatformImpl {
- public:
- RendererWebKitPlatformSupportImpl();
- virtual ~RendererWebKitPlatformSupportImpl();
-
- void set_plugin_refresh_allowed(bool plugin_refresh_allowed) {
- plugin_refresh_allowed_ = plugin_refresh_allowed;
- }
- // Platform methods:
- virtual blink::WebClipboard* clipboard();
- virtual blink::WebMimeRegistry* mimeRegistry();
- virtual blink::WebFileUtilities* fileUtilities();
- virtual blink::WebSandboxSupport* sandboxSupport();
- virtual blink::WebCookieJar* cookieJar();
- virtual blink::WebThemeEngine* themeEngine();
- virtual blink::WebSpeechSynthesizer* createSpeechSynthesizer(
- blink::WebSpeechSynthesizerClient* client);
- virtual bool sandboxEnabled();
- virtual unsigned long long visitedLinkHash(
- const char* canonicalURL, size_t length);
- virtual bool isLinkVisited(unsigned long long linkHash);
- virtual void createMessageChannel(blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2);
- virtual blink::WebPrescientNetworking* prescientNetworking();
- virtual void cacheMetadata(
- const blink::WebURL&, double, const char*, size_t);
- virtual blink::WebString defaultLocale();
- virtual void suddenTerminationChanged(bool enabled);
- virtual blink::WebStorageNamespace* createLocalStorageNamespace();
- virtual blink::Platform::FileHandle databaseOpenFile(
- const blink::WebString& vfs_file_name, int desired_flags);
- virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
- bool sync_dir);
- virtual long databaseGetFileAttributes(
- const blink::WebString& vfs_file_name);
- virtual long long databaseGetFileSize(
- const blink::WebString& vfs_file_name);
- virtual long long databaseGetSpaceAvailableForOrigin(
- const blink::WebString& origin_identifier);
- virtual blink::WebString signedPublicKeyAndChallengeString(
- unsigned key_size_index,
- const blink::WebString& challenge,
- const blink::WebURL& url);
- virtual void getPluginList(bool refresh,
- blink::WebPluginListBuilder* builder);
- virtual blink::WebPublicSuffixList* publicSuffixList();
- virtual void screenColorProfile(blink::WebVector<char>* to_profile);
- virtual blink::WebScrollbarBehavior* scrollbarBehavior();
- virtual blink::WebIDBFactory* idbFactory();
- virtual blink::WebFileSystem* fileSystem();
- virtual bool canAccelerate2dCanvas();
- virtual bool isThreadedCompositingEnabled();
- virtual double audioHardwareSampleRate();
- virtual size_t audioHardwareBufferSize();
- virtual unsigned audioHardwareOutputChannels();
- virtual blink::WebDatabaseObserver* databaseObserver();
-
- virtual blink::WebAudioDevice* createAudioDevice(
- size_t buffer_size, unsigned input_channels, unsigned channels,
- double sample_rate, blink::WebAudioDevice::RenderCallback* callback,
- const blink::WebString& input_device_id);
-
- virtual bool loadAudioResource(
- blink::WebAudioBus* destination_bus, const char* audio_file_data,
- size_t data_size);
-
- virtual blink::WebMIDIAccessor*
- createMIDIAccessor(blink::WebMIDIAccessorClient* client);
-
- virtual blink::WebBlobRegistry* blobRegistry();
- virtual void sampleGamepads(blink::WebGamepads&);
- virtual void setGamepadListener(blink::WebGamepadListener*);
- virtual blink::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler(
- blink::WebRTCPeerConnectionHandlerClient* client);
- virtual blink::WebMediaStreamCenter* createMediaStreamCenter(
- blink::WebMediaStreamCenterClient* client);
- virtual bool processMemorySizesInBytes(
- size_t* private_bytes, size_t* shared_bytes);
- virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes);
- virtual blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes,
- blink::WebGraphicsContext3D* share_context);
- virtual blink::WebGraphicsContext3DProvider*
- createSharedOffscreenGraphicsContext3DProvider();
- virtual blink::WebCompositorSupport* compositorSupport();
- virtual blink::WebString convertIDNToUnicode(
- const blink::WebString& host, const blink::WebString& languages);
- virtual void setDeviceMotionListener(
- blink::WebDeviceMotionListener* listener);
- virtual void setDeviceOrientationListener(
- blink::WebDeviceOrientationListener* listener);
- virtual void queryStorageUsageAndQuota(
- const blink::WebURL& storage_partition,
- blink::WebStorageQuotaType,
- blink::WebStorageQuotaCallbacks);
- virtual void vibrate(unsigned int milliseconds);
- virtual void cancelVibration();
- virtual void setBatteryStatusListener(
- blink::WebBatteryStatusListener* listener);
-
- void set_gamepad_provider(RendererGamepadProvider* provider) {
- gamepad_provider_ = provider;
- }
-
- // Disables the WebSandboxSupport implementation for testing.
- // Tests that do not set up a full sandbox environment should call
- // SetSandboxEnabledForTesting(false) _before_ creating any instances
- // of this class, to ensure that we don't attempt to use sandbox-related
- // file descriptors or other resources.
- //
- // Returns the previous |enable| value.
- static bool SetSandboxEnabledForTesting(bool enable);
-
- // Set WebDeviceMotionData to return when setDeviceMotionListener is invoked.
- static void SetMockDeviceMotionDataForTesting(
- const blink::WebDeviceMotionData& data);
- // Set WebDeviceOrientationData to return when setDeviceOrientationListener
- // is invoked.
- static void SetMockDeviceOrientationDataForTesting(
- const blink::WebDeviceOrientationData& data);
- // Forces the screen orientation for testing purposes.
- static void SetMockScreenOrientationForTesting(
- RenderView* render_view,
- blink::WebScreenOrientationType);
- // Resets the mock screen orientation data used for testing.
- static void ResetMockScreenOrientationForTesting();
-
- // Notifies blink::WebBatteryStatusListener that battery status has changed.
- static void MockBatteryStatusChangedForTesting(
- const blink::WebBatteryStatus& status);
-
- WebDatabaseObserverImpl* web_database_observer_impl() {
- return web_database_observer_impl_.get();
- }
-
- private:
- bool CheckPreparsedJsCachingEnabled() const;
-
- scoped_ptr<RendererClipboardClient> clipboard_client_;
- scoped_ptr<WebClipboardImpl> clipboard_;
-
- class FileUtilities;
- scoped_ptr<FileUtilities> file_utilities_;
-
- class MimeRegistry;
- scoped_ptr<MimeRegistry> mime_registry_;
-
- class SandboxSupport;
- scoped_ptr<SandboxSupport> sandbox_support_;
-
- // This counter keeps track of the number of times sudden termination is
- // enabled or disabled. It starts at 0 (enabled) and for every disable
- // increments by 1, for every enable decrements by 1. When it reaches 0,
- // we tell the browser to enable fast termination.
- int sudden_termination_disables_;
-
- // If true, then a GetPlugins call is allowed to rescan the disk.
- bool plugin_refresh_allowed_;
-
- scoped_ptr<blink::WebIDBFactory> web_idb_factory_;
-
- scoped_ptr<blink::WebBlobRegistry> blob_registry_;
-
- WebPublicSuffixListImpl public_suffix_list_;
-
- scoped_ptr<DeviceMotionEventPump> device_motion_event_pump_;
- scoped_ptr<DeviceOrientationEventPump> device_orientation_event_pump_;
-
- scoped_refptr<base::MessageLoopProxy> child_thread_loop_;
- scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- scoped_refptr<QuotaMessageFilter> quota_message_filter_;
-
- scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
-
- WebCompositorSupportImpl compositor_support_;
-
- scoped_ptr<blink::WebScrollbarBehavior> web_scrollbar_behavior_;
-
- scoped_ptr<BatteryStatusDispatcher> battery_status_dispatcher_;
-
- RendererGamepadProvider* gamepad_provider_;
-
- DISALLOW_COPY_AND_ASSIGN(RendererWebKitPlatformSupportImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_RENDERER_WEBKITPLATFORMSUPPORT_IMPL_H_
diff --git a/chromium/content/renderer/resource_fetcher_browsertest.cc b/chromium/content/renderer/resource_fetcher_browsertest.cc
index 2919f58f1e7..c016754ef3f 100644
--- a/chromium/content/renderer/resource_fetcher_browsertest.cc
+++ b/chromium/content/renderer/resource_fetcher_browsertest.cc
@@ -108,14 +108,14 @@ FetcherDelegate* FetcherDelegate::instance_ = NULL;
class EvilFetcherDelegate : public FetcherDelegate {
public:
- virtual ~EvilFetcherDelegate() {}
+ ~EvilFetcherDelegate() override {}
void SetFetcher(ResourceFetcher* fetcher) {
fetcher_.reset(fetcher);
}
- virtual void OnURLFetchComplete(const WebURLResponse& response,
- const std::string& data) OVERRIDE {
+ void OnURLFetchComplete(const WebURLResponse& response,
+ const std::string& data) override {
FetcherDelegate::OnURLFetchComplete(response, data);
// Destroy the ResourceFetcher here. We are testing that upon returning
@@ -131,7 +131,7 @@ class EvilFetcherDelegate : public FetcherDelegate {
class ResourceFetcherTests : public ContentBrowserTest {
public:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kSingleProcess);
#if defined(OS_WIN)
// Don't want to try to create a GPU process.
@@ -150,7 +150,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
delegate->WaitForResponse();
@@ -166,7 +169,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
delegate->WaitForResponse();
@@ -183,7 +189,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
GURL url("http://localhost:1339/doesnotexist");
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
delegate->WaitForResponse();
@@ -201,7 +210,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
fetcher->SetTimeout(base::TimeDelta());
@@ -220,7 +232,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
fetcher->SetTimeout(base::TimeDelta());
delegate->SetFetcher(fetcher.release());
@@ -238,7 +253,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
fetcher->SetMethod("POST");
fetcher->SetBody(kBody);
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
delegate->WaitForResponse();
@@ -255,7 +273,10 @@ class ResourceFetcherTests : public ContentBrowserTest {
scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
fetcher->SetHeader("header", kHeader);
- fetcher->Start(frame, WebURLRequest::TargetIsMainFrame,
+ fetcher->Start(frame,
+ WebURLRequest::RequestContextInternal,
+ WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
delegate->NewCallback());
delegate->WaitForResponse();
diff --git a/chromium/content/renderer/savable_resources.cc b/chromium/content/renderer/savable_resources.cc
index 9f456b964cb..958003f8783 100644
--- a/chromium/content/renderer/savable_resources.cc
+++ b/chromium/content/renderer/savable_resources.cc
@@ -70,8 +70,8 @@ void GetSavableResourceLinkForElement(
SavableResourcesResult* result) {
// Handle frame and iframe tag.
- if (element.hasTagName("iframe") ||
- element.hasTagName("frame")) {
+ if (element.hasHTMLTagName("iframe") ||
+ element.hasHTMLTagName("frame")) {
WebFrame* sub_frame = WebLocalFrame::fromFrameOwnerElement(element);
if (sub_frame)
unique_check->frames->push_back(sub_frame);
@@ -90,7 +90,7 @@ void GetSavableResourceLinkForElement(
// Ignore those URLs which are not standard protocols. Because FTP
// protocol does no have cache mechanism, we will skip all
// sub-resources if they use FTP protocol.
- if (!u.SchemeIsHTTPOrHTTPS() && !u.SchemeIs("file"))
+ if (!u.SchemeIsHTTPOrHTTPS() && !u.SchemeIs(url::kFileScheme))
return;
// Ignore duplicated resource link.
if (!unique_check->resources_set->insert(u).second)
diff --git a/chromium/content/renderer/savable_resources_browsertest.cc b/chromium/content/renderer/savable_resources_browsertest.cc
index 730b28b7298..e63a3904c51 100644
--- a/chromium/content/renderer/savable_resources_browsertest.cc
+++ b/chromium/content/renderer/savable_resources_browsertest.cc
@@ -18,7 +18,7 @@ namespace content {
class SavableResourcesTest : public ContentBrowserTest {
public:
- virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ void SetUpCommandLine(CommandLine* command_line) override {
command_line->AppendSwitch(switches::kSingleProcess);
#if defined(OS_WIN)
// Don't want to try to create a GPU process.
diff --git a/chromium/content/renderer/scheduler/null_renderer_scheduler.cc b/chromium/content/renderer/scheduler/null_renderer_scheduler.cc
new file mode 100644
index 00000000000..af9379973ac
--- /dev/null
+++ b/chromium/content/renderer/scheduler/null_renderer_scheduler.cc
@@ -0,0 +1,79 @@
+// Copyright 2014 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 "content/renderer/scheduler/null_renderer_scheduler.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop_proxy.h"
+
+namespace content {
+
+namespace {
+
+class NullIdleTaskRunner : public SingleThreadIdleTaskRunner {
+ public:
+ NullIdleTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ void PostIdleTask(const tracked_objects::Location& from_here,
+ const IdleTask& idle_task) override;
+
+ protected:
+ ~NullIdleTaskRunner() override;
+};
+
+} // namespace
+
+NullIdleTaskRunner::NullIdleTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : SingleThreadIdleTaskRunner(task_runner,
+ base::Callback<void(base::TimeTicks*)>()) {
+}
+
+NullIdleTaskRunner::~NullIdleTaskRunner() {
+}
+
+void NullIdleTaskRunner::PostIdleTask(
+ const tracked_objects::Location& from_here,
+ const IdleTask& idle_task) {
+}
+
+NullRendererScheduler::NullRendererScheduler()
+ : task_runner_(base::MessageLoopProxy::current()),
+ idle_task_runner_(new NullIdleTaskRunner(task_runner_)) {
+}
+
+NullRendererScheduler::~NullRendererScheduler() {
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+NullRendererScheduler::DefaultTaskRunner() {
+ return task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+NullRendererScheduler::CompositorTaskRunner() {
+ return task_runner_;
+}
+
+scoped_refptr<SingleThreadIdleTaskRunner>
+NullRendererScheduler::IdleTaskRunner() {
+ return idle_task_runner_;
+}
+
+void NullRendererScheduler::WillBeginFrame(const cc::BeginFrameArgs& args) {
+}
+
+void NullRendererScheduler::DidCommitFrameToCompositor() {
+}
+
+void NullRendererScheduler::DidReceiveInputEventOnCompositorThread() {
+}
+
+bool NullRendererScheduler::ShouldYieldForHighPriorityWork() {
+ return false;
+}
+
+void NullRendererScheduler::Shutdown() {
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/null_renderer_scheduler.h b/chromium/content/renderer/scheduler/null_renderer_scheduler.h
new file mode 100644
index 00000000000..c5bdb14e558
--- /dev/null
+++ b/chromium/content/renderer/scheduler/null_renderer_scheduler.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_NULL_RENDERER_SCHEDULER_H_
+#define CONTENT_RENDERER_SCHEDULER_NULL_RENDERER_SCHEDULER_H_
+
+#include "content/renderer/scheduler/renderer_scheduler.h"
+
+namespace content {
+
+class NullRendererScheduler : public RendererScheduler {
+ public:
+ NullRendererScheduler();
+ ~NullRendererScheduler() override;
+
+ scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
+ scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() override;
+
+ void WillBeginFrame(const cc::BeginFrameArgs& args) override;
+ void DidCommitFrameToCompositor() override;
+ void DidReceiveInputEventOnCompositorThread() override;
+ bool ShouldYieldForHighPriorityWork() override;
+ void Shutdown() override;
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullRendererScheduler);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_NULL_RENDERER_SCHEDULER_H_
diff --git a/chromium/content/renderer/scheduler/renderer_scheduler.cc b/chromium/content/renderer/scheduler/renderer_scheduler.cc
new file mode 100644
index 00000000000..ec30f7f5eb9
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_scheduler.cc
@@ -0,0 +1,23 @@
+// Copyright 2014 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 "content/renderer/scheduler/renderer_scheduler.h"
+
+#include "content/renderer/scheduler/null_renderer_scheduler.h"
+
+namespace content {
+
+RendererScheduler::RendererScheduler() {
+}
+
+RendererScheduler::~RendererScheduler() {
+}
+
+// static
+scoped_ptr<RendererScheduler> RendererScheduler::Create() {
+ // TODO(rmcilroy): Use the RendererSchedulerImpl when the scheduler is enabled
+ return make_scoped_ptr(new NullRendererScheduler());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/renderer_scheduler.h b/chromium/content/renderer/scheduler/renderer_scheduler.h
new file mode 100644
index 00000000000..39945ae65b3
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_scheduler.h
@@ -0,0 +1,63 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_RENDERER_SCHEDULER_H_
+#define CONTENT_RENDERER_SCHEDULER_RENDERER_SCHEDULER_H_
+
+#include "content/renderer/scheduler/single_thread_idle_task_runner.h"
+#include "content/renderer/scheduler/task_queue_manager.h"
+
+namespace cc {
+struct BeginFrameArgs;
+}
+
+namespace content {
+
+class CONTENT_EXPORT RendererScheduler {
+ public:
+ virtual ~RendererScheduler();
+ static scoped_ptr<RendererScheduler> Create();
+
+ // Returns the default task runner.
+ virtual scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() = 0;
+
+ // Returns the compositor task runner.
+ virtual scoped_refptr<base::SingleThreadTaskRunner>
+ CompositorTaskRunner() = 0;
+
+ // Returns the idle task runner. Tasks posted to this runner may be reordered
+ // relative to other task types and may be starved for an arbitrarily long
+ // time if no idle time is available.
+ virtual scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() = 0;
+
+ // Called to notify about the start of a new frame. Must be called from the
+ // main thread.
+ virtual void WillBeginFrame(const cc::BeginFrameArgs& args) = 0;
+
+ // Called to notify that a previously begun frame was committed. Must be
+ // called from the main thread.
+ virtual void DidCommitFrameToCompositor() = 0;
+
+ // Tells the scheduler that the system received an input event. Called by the
+ // compositor (impl) thread.
+ virtual void DidReceiveInputEventOnCompositorThread() = 0;
+
+ // Returns true if there is high priority work pending on the main thread
+ // and the caller should yield to let the scheduler service that work.
+ // Must be called from the main thread.
+ virtual bool ShouldYieldForHighPriorityWork() = 0;
+
+ // Shuts down the scheduler by dropping any remaining pending work in the work
+ // queues. After this call any work posted to the task runners will be
+ // silently dropped.
+ virtual void Shutdown() = 0;
+
+ protected:
+ RendererScheduler();
+ DISALLOW_COPY_AND_ASSIGN(RendererScheduler);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_RENDERER_SCHEDULER_H_
diff --git a/chromium/content/renderer/scheduler/renderer_scheduler_impl.cc b/chromium/content/renderer/scheduler/renderer_scheduler_impl.cc
new file mode 100644
index 00000000000..aef2bdf7bcc
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_scheduler_impl.cc
@@ -0,0 +1,218 @@
+// Copyright 2014 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 "content/renderer/scheduler/renderer_scheduler_impl.h"
+
+#include "base/bind.h"
+#include "cc/output/begin_frame_args.h"
+#include "content/renderer/scheduler/renderer_task_queue_selector.h"
+#include "ui/gfx/frame_time.h"
+
+namespace content {
+
+RendererSchedulerImpl::RendererSchedulerImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+ : renderer_task_queue_selector_(new RendererTaskQueueSelector()),
+ task_queue_manager_(
+ new TaskQueueManager(TASK_QUEUE_COUNT,
+ main_task_runner,
+ renderer_task_queue_selector_.get())),
+ control_task_runner_(
+ task_queue_manager_->TaskRunnerForQueue(CONTROL_TASK_QUEUE)),
+ default_task_runner_(
+ task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)),
+ compositor_task_runner_(
+ task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)),
+ current_policy_(NORMAL_PRIORITY_POLICY),
+ policy_may_need_update_(&incoming_signals_lock_),
+ weak_factory_(this) {
+ weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr();
+ update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
+ weak_renderer_scheduler_ptr_);
+ end_idle_period_closure_ = base::Bind(&RendererSchedulerImpl::EndIdlePeriod,
+ weak_renderer_scheduler_ptr_);
+ idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner(
+ task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE),
+ base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback,
+ weak_renderer_scheduler_ptr_)));
+ renderer_task_queue_selector_->SetQueuePriority(
+ CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY);
+ renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE);
+ task_queue_manager_->SetAutoPump(IDLE_TASK_QUEUE, false);
+}
+
+RendererSchedulerImpl::~RendererSchedulerImpl() {
+}
+
+void RendererSchedulerImpl::Shutdown() {
+ main_thread_checker_.CalledOnValidThread();
+ task_queue_manager_.reset();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+RendererSchedulerImpl::DefaultTaskRunner() {
+ main_thread_checker_.CalledOnValidThread();
+ return default_task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+RendererSchedulerImpl::CompositorTaskRunner() {
+ main_thread_checker_.CalledOnValidThread();
+ return compositor_task_runner_;
+}
+
+scoped_refptr<SingleThreadIdleTaskRunner>
+RendererSchedulerImpl::IdleTaskRunner() {
+ main_thread_checker_.CalledOnValidThread();
+ return idle_task_runner_;
+}
+
+void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) {
+ main_thread_checker_.CalledOnValidThread();
+ if (!task_queue_manager_)
+ return;
+
+ EndIdlePeriod();
+ estimated_next_frame_begin_ = args.frame_time + args.interval;
+}
+
+void RendererSchedulerImpl::DidCommitFrameToCompositor() {
+ main_thread_checker_.CalledOnValidThread();
+ if (!task_queue_manager_)
+ return;
+
+ base::TimeTicks now(Now());
+ if (now < estimated_next_frame_begin_) {
+ StartIdlePeriod();
+ control_task_runner_->PostDelayedTask(FROM_HERE, end_idle_period_closure_,
+ estimated_next_frame_begin_ - now);
+ }
+}
+
+void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread() {
+ // TODO(rmcilroy): Decide whether only a subset of input events should trigger
+ // compositor priority policy - http://crbug.com/429814.
+ base::AutoLock lock(incoming_signals_lock_);
+ if (last_input_time_.is_null()) {
+ // Update scheduler policy if should start a new compositor policy mode.
+ policy_may_need_update_.SetLocked(true);
+ PostUpdatePolicyOnControlRunner(base::TimeDelta());
+ }
+ last_input_time_ = Now();
+}
+
+bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
+ main_thread_checker_.CalledOnValidThread();
+ if (!task_queue_manager_)
+ return false;
+
+ MaybeUpdatePolicy();
+ // We only yield if we are in the compositor priority and there is compositor
+ // work outstanding. Note: even though the control queue is higher priority
+ // we don't yield for it since these tasks are not user-provided work and they
+ // are only intended to run before the next task, not interrupt the tasks.
+ return SchedulerPolicy() == COMPOSITOR_PRIORITY_POLICY &&
+ !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE);
+}
+
+void RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback(
+ base::TimeTicks* deadline_out) const {
+ main_thread_checker_.CalledOnValidThread();
+ *deadline_out = estimated_next_frame_begin_;
+}
+
+RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const {
+ main_thread_checker_.CalledOnValidThread();
+ return current_policy_;
+}
+
+void RendererSchedulerImpl::MaybeUpdatePolicy() {
+ main_thread_checker_.CalledOnValidThread();
+ if (policy_may_need_update_.IsSet()) {
+ UpdatePolicy();
+ }
+}
+
+void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner(
+ base::TimeDelta delay) {
+ control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_,
+ delay);
+}
+
+void RendererSchedulerImpl::UpdatePolicy() {
+ main_thread_checker_.CalledOnValidThread();
+ if (!task_queue_manager_)
+ return;
+
+ base::AutoLock lock(incoming_signals_lock_);
+ policy_may_need_update_.SetLocked(false);
+
+ Policy new_policy = NORMAL_PRIORITY_POLICY;
+ if (!last_input_time_.is_null()) {
+ base::TimeDelta compositor_priority_duration =
+ base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis);
+ base::TimeTicks compositor_priority_end(last_input_time_ +
+ compositor_priority_duration);
+ base::TimeTicks now(Now());
+ if (compositor_priority_end > now) {
+ PostUpdatePolicyOnControlRunner(compositor_priority_end - now);
+ new_policy = COMPOSITOR_PRIORITY_POLICY;
+ } else {
+ // Null out last_input_time_ to ensure
+ // DidReceiveInputEventOnCompositorThread will post an
+ // UpdatePolicy task when it's next called.
+ last_input_time_ = base::TimeTicks();
+ }
+ }
+
+ if (new_policy == current_policy_)
+ return;
+
+ switch (new_policy) {
+ case COMPOSITOR_PRIORITY_POLICY:
+ renderer_task_queue_selector_->SetQueuePriority(
+ COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY);
+ break;
+ case NORMAL_PRIORITY_POLICY:
+ renderer_task_queue_selector_->SetQueuePriority(
+ COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY);
+ break;
+ }
+ current_policy_ = new_policy;
+}
+
+void RendererSchedulerImpl::StartIdlePeriod() {
+ main_thread_checker_.CalledOnValidThread();
+ renderer_task_queue_selector_->EnableQueue(
+ IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE);
+}
+
+void RendererSchedulerImpl::EndIdlePeriod() {
+ main_thread_checker_.CalledOnValidThread();
+ renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE);
+}
+
+base::TimeTicks RendererSchedulerImpl::Now() const {
+ return gfx::FrameTime::Now();
+}
+
+RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag(
+ base::Lock* write_lock_)
+ : flag_(false), write_lock_(write_lock_) {
+}
+
+RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() {
+}
+
+void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) {
+ write_lock_->AssertAcquired();
+ base::subtle::Release_Store(&flag_, value);
+}
+
+bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const {
+ thread_checker_.CalledOnValidThread();
+ return base::subtle::Acquire_Load(&flag_) != 0;
+}
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/renderer_scheduler_impl.h b/chromium/content/renderer/scheduler/renderer_scheduler_impl.h
new file mode 100644
index 00000000000..e45379be2ed
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_scheduler_impl.h
@@ -0,0 +1,128 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_RENDERER_SCHEDULER_IMPL_H_
+#define CONTENT_RENDERER_SCHEDULER_RENDERER_SCHEDULER_IMPL_H_
+
+#include "base/atomicops.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "content/renderer/scheduler/renderer_scheduler.h"
+#include "content/renderer/scheduler/single_thread_idle_task_runner.h"
+#include "content/renderer/scheduler/task_queue_manager.h"
+
+namespace content {
+
+class RendererTaskQueueSelector;
+
+class CONTENT_EXPORT RendererSchedulerImpl : public RendererScheduler {
+ public:
+ RendererSchedulerImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+ ~RendererSchedulerImpl() override;
+
+ // RendererScheduler implementation:
+ scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
+ scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() override;
+ void WillBeginFrame(const cc::BeginFrameArgs& args) override;
+ void DidCommitFrameToCompositor() override;
+ void DidReceiveInputEventOnCompositorThread() override;
+ bool ShouldYieldForHighPriorityWork() override;
+ void Shutdown() override;
+
+ protected:
+ // Virtual for testing.
+ virtual base::TimeTicks Now() const;
+
+ private:
+ friend class RendererSchedulerImplTest;
+
+ enum QueueId {
+ DEFAULT_TASK_QUEUE,
+ COMPOSITOR_TASK_QUEUE,
+ IDLE_TASK_QUEUE,
+ CONTROL_TASK_QUEUE,
+ // Must be the last entry.
+ TASK_QUEUE_COUNT,
+ };
+
+ enum Policy {
+ NORMAL_PRIORITY_POLICY,
+ COMPOSITOR_PRIORITY_POLICY,
+ };
+
+ class PollableNeedsUpdateFlag {
+ public:
+ PollableNeedsUpdateFlag(base::Lock* write_lock);
+ ~PollableNeedsUpdateFlag();
+
+ // Set the flag. May only be called if |write_lock| is held.
+ void SetLocked(bool value);
+
+ // Returns true iff the flag was set to true.
+ bool IsSet() const;
+
+ private:
+ base::subtle::Atomic32 flag_;
+ base::Lock* write_lock_; // Not owned.
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(PollableNeedsUpdateFlag);
+ };
+
+ // The time we should stay in CompositorPriority mode for after a touch event.
+ static const int kCompositorPriorityAfterTouchMillis = 100;
+
+ // IdleTaskDeadlineSupplier Implementation:
+ void CurrentIdleTaskDeadlineCallback(base::TimeTicks* deadline_out) const;
+
+ // Returns the current scheduler policy. Must be called from the main thread.
+ Policy SchedulerPolicy() const;
+
+ // Posts a call to UpdatePolicy on the control runner to be run after |delay|
+ void PostUpdatePolicyOnControlRunner(base::TimeDelta delay);
+
+ // Update the policy if a new signal has arrived. Must be called from the main
+ // thread.
+ void MaybeUpdatePolicy();
+
+ // Updates the scheduler policy. Must be called from the main thread.
+ void UpdatePolicy();
+
+ // Start and end an idle period.
+ void StartIdlePeriod();
+ void EndIdlePeriod();
+
+ base::ThreadChecker main_thread_checker_;
+ scoped_ptr<RendererTaskQueueSelector> renderer_task_queue_selector_;
+ scoped_ptr<TaskQueueManager> task_queue_manager_;
+ scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+
+ base::Closure update_policy_closure_;
+ base::Closure end_idle_period_closure_;
+
+ // Don't access current_policy_ directly, instead use SchedulerPolicy().
+ Policy current_policy_;
+
+ base::TimeTicks estimated_next_frame_begin_;
+
+ // The incoming_signals_lock_ mutex protects access to last_input_time_
+ // and write access to policy_may_need_update_.
+ base::Lock incoming_signals_lock_;
+ base::TimeTicks last_input_time_;
+ PollableNeedsUpdateFlag policy_may_need_update_;
+
+ base::WeakPtr<RendererSchedulerImpl> weak_renderer_scheduler_ptr_;
+ base::WeakPtrFactory<RendererSchedulerImpl> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_RENDERER_SCHEDULER_IMPL_H_
diff --git a/chromium/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc b/chromium/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc
new file mode 100644
index 00000000000..701a222c71e
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_scheduler_impl_unittest.cc
@@ -0,0 +1,411 @@
+// Copyright 2014 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 "content/renderer/scheduler/renderer_scheduler_impl.h"
+
+#include "base/callback.h"
+#include "cc/output/begin_frame_args.h"
+#include "cc/test/ordered_simple_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class RendererSchedulerImplForTest : public RendererSchedulerImpl {
+ public:
+ RendererSchedulerImplForTest(
+ scoped_refptr<cc::OrderedSimpleTaskRunner> task_runner,
+ scoped_refptr<cc::TestNowSource> clock)
+ : RendererSchedulerImpl(task_runner), clock_(clock) {}
+ ~RendererSchedulerImplForTest() override {}
+
+ protected:
+ base::TimeTicks Now() const override { return clock_->Now(); }
+
+ private:
+ scoped_refptr<cc::TestNowSource> clock_;
+};
+
+class RendererSchedulerImplTest : public testing::Test {
+ public:
+ RendererSchedulerImplTest()
+ : clock_(cc::TestNowSource::Create(5000)),
+ mock_task_runner_(new cc::OrderedSimpleTaskRunner(clock_, false)),
+ scheduler_(new RendererSchedulerImplForTest(mock_task_runner_, clock_)),
+ default_task_runner_(scheduler_->DefaultTaskRunner()),
+ compositor_task_runner_(scheduler_->CompositorTaskRunner()),
+ idle_task_runner_(scheduler_->IdleTaskRunner()) {}
+ ~RendererSchedulerImplTest() override {}
+
+ void RunUntilIdle() { mock_task_runner_->RunUntilIdle(); }
+
+ void EnableIdleTasks() {
+ scheduler_->WillBeginFrame(
+ cc::BeginFrameArgs::Create(clock_->Now(), base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000)));
+ scheduler_->DidCommitFrameToCompositor();
+ }
+
+ protected:
+ scoped_refptr<cc::TestNowSource> clock_;
+ scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+
+ scoped_ptr<RendererSchedulerImpl> scheduler_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererSchedulerImplTest);
+};
+
+void NullTask() {
+}
+
+void OrderedTestTask(int value, int* result) {
+ *result = (*result << 4) | value;
+}
+
+void UnorderedTestTask(int value, int* result) {
+ *result += value;
+}
+
+void AppendToVectorTestTask(std::vector<std::string>* vector,
+ std::string value) {
+ vector->push_back(value);
+}
+
+void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
+ std::string value,
+ base::TimeTicks deadline) {
+ AppendToVectorTestTask(vector, value);
+}
+
+void AppendToVectorReentrantTask(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ std::vector<int>* vector,
+ int* reentrant_count,
+ int max_reentrant_count) {
+ vector->push_back((*reentrant_count)++);
+ if (*reentrant_count < max_reentrant_count) {
+ task_runner->PostTask(
+ FROM_HERE, base::Bind(AppendToVectorReentrantTask, task_runner, vector,
+ reentrant_count, max_reentrant_count));
+ }
+}
+
+void IdleTestTask(bool* task_run,
+ base::TimeTicks* deadline_out,
+ base::TimeTicks deadline) {
+ EXPECT_FALSE(*task_run);
+ *deadline_out = deadline;
+ *task_run = true;
+}
+
+void RepostingIdleTestTask(
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner,
+ int* run_count,
+ base::TimeTicks deadline) {
+ if (*run_count == 0) {
+ idle_task_runner->PostIdleTask(
+ FROM_HERE,
+ base::Bind(&RepostingIdleTestTask, idle_task_runner, run_count));
+ }
+ (*run_count)++;
+}
+
+void UpdateClockToDeadlineIdleTestTask(
+ scoped_refptr<cc::TestNowSource> clock,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ int* run_count,
+ base::TimeTicks deadline) {
+ clock->SetNow(deadline);
+ // Due to the way in which OrderedSimpleTestRunner orders tasks and the fact
+ // that we updated the time within a task, the delayed pending task to call
+ // EndIdlePeriod will not happen until after a TaskQueueManager DoWork, so
+ // post a normal task here to ensure it runs before the next idle task.
+ task_runner->PostTask(FROM_HERE, base::Bind(NullTask));
+ (*run_count)++;
+}
+
+void PostingYieldingTestTask(
+ RendererSchedulerImpl* scheduler,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool simulate_input,
+ bool* should_yield_before,
+ bool* should_yield_after) {
+ *should_yield_before = scheduler->ShouldYieldForHighPriorityWork();
+ task_runner->PostTask(FROM_HERE, base::Bind(NullTask));
+ if (simulate_input) {
+ scheduler->DidReceiveInputEventOnCompositorThread();
+ }
+ *should_yield_after = scheduler->ShouldYieldForHighPriorityWork();
+}
+
+TEST_F(RendererSchedulerImplTest, TestPostDefaultTask) {
+ int result = 0;
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 1, &result));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 2, &result));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 3, &result));
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(OrderedTestTask, 4, &result));
+ RunUntilIdle();
+ EXPECT_EQ(0x1234, result);
+}
+
+TEST_F(RendererSchedulerImplTest, TestPostDefaultAndCompositor) {
+ int result = 0;
+ default_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&UnorderedTestTask, 1, &result));
+ compositor_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&UnorderedTestTask, 2, &result));
+ RunUntilIdle();
+ EXPECT_EQ(3, result);
+}
+
+TEST_F(RendererSchedulerImplTest, TestRentrantTask) {
+ int count = 0;
+ std::vector<int> order;
+ default_task_runner_->PostTask(
+ FROM_HERE, base::Bind(AppendToVectorReentrantTask, default_task_runner_,
+ &order, &count, 5));
+ RunUntilIdle();
+
+ EXPECT_THAT(order, testing::ElementsAre(0, 1, 2, 3, 4));
+}
+
+TEST_F(RendererSchedulerImplTest, TestPostIdleTask) {
+ bool task_run = false;
+ base::TimeTicks expected_deadline =
+ clock_->Now() + base::TimeDelta::FromMilliseconds(2300);
+ base::TimeTicks deadline_in_task;
+
+ clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(100));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::Bind(&IdleTestTask, &task_run, &deadline_in_task));
+
+ RunUntilIdle();
+ EXPECT_FALSE(task_run); // Shouldn't run yet as no WillBeginFrame.
+
+ scheduler_->WillBeginFrame(
+ cc::BeginFrameArgs::Create(clock_->Now(), base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000)));
+ RunUntilIdle();
+ EXPECT_FALSE(task_run); // Shouldn't run as no DidCommitFrameToCompositor.
+
+ clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(1200));
+ scheduler_->DidCommitFrameToCompositor();
+ RunUntilIdle();
+ EXPECT_FALSE(task_run); // We missed the deadline.
+
+ scheduler_->WillBeginFrame(
+ cc::BeginFrameArgs::Create(clock_->Now(), base::TimeTicks(),
+ base::TimeDelta::FromMilliseconds(1000)));
+ clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(800));
+ scheduler_->DidCommitFrameToCompositor();
+ RunUntilIdle();
+ EXPECT_TRUE(task_run);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+TEST_F(RendererSchedulerImplTest, TestRepostingIdleTask) {
+ int run_count = 0;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::Bind(&RepostingIdleTestTask, idle_task_runner_, &run_count));
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ // Reposted tasks shouldn't run until next idle period.
+ RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_EQ(2, run_count);
+}
+
+TEST_F(RendererSchedulerImplTest, TestIdleTaskExceedsDeadline) {
+ mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
+ int run_count = 0;
+
+ // Post two UpdateClockToDeadlineIdleTestTask tasks.
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_,
+ default_task_runner_, &run_count));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::Bind(&UpdateClockToDeadlineIdleTestTask, clock_,
+ default_task_runner_, &run_count));
+
+ EnableIdleTasks();
+ RunUntilIdle();
+ // Only the first idle task should execute since it's used up the deadline.
+ EXPECT_EQ(1, run_count);
+
+ EnableIdleTasks();
+ RunUntilIdle();
+ // Second task should be run on the next idle period.
+ EXPECT_EQ(2, run_count);
+}
+
+TEST_F(RendererSchedulerImplTest, TestDefaultPolicy) {
+ std::vector<std::string> order;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_THAT(order, testing::ElementsAre(std::string("D1"), std::string("C1"),
+ std::string("D2"), std::string("C2"),
+ std::string("I1")));
+}
+
+TEST_F(RendererSchedulerImplTest, TestCompositorPolicy) {
+ std::vector<std::string> order;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorIdleTestTask, &order, std::string("I1")));
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ scheduler_->DidReceiveInputEventOnCompositorThread();
+ EnableIdleTasks();
+ RunUntilIdle();
+ EXPECT_THAT(order, testing::ElementsAre(std::string("C1"), std::string("C2"),
+ std::string("D1"), std::string("D2"),
+ std::string("I1")));
+}
+
+TEST_F(RendererSchedulerImplTest,
+ TestCompositorPolicyDoesNotStarveDefaultTasks) {
+ std::vector<std::string> order;
+
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ for (int i = 0; i < 20; i++) {
+ compositor_task_runner_->PostTask(FROM_HERE, base::Bind(&NullTask));
+ }
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ scheduler_->DidReceiveInputEventOnCompositorThread();
+ RunUntilIdle();
+ // Ensure that the default D1 task gets to run at some point before the final
+ // C2 compositor task.
+ EXPECT_THAT(order, testing::ElementsAre(std::string("C1"), std::string("D1"),
+ std::string("C2")));
+}
+
+TEST_F(RendererSchedulerImplTest, TestCompositorPolicyEnds) {
+ std::vector<std::string> order;
+
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ scheduler_->DidReceiveInputEventOnCompositorThread();
+ RunUntilIdle();
+ EXPECT_THAT(order,
+ testing::ElementsAre(std::string("C1"), std::string("C2"),
+ std::string("D1"), std::string("D2")));
+
+ order.clear();
+ clock_->AdvanceNow(base::TimeDelta::FromMilliseconds(1000));
+
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D1")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C1")));
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("D2")));
+ compositor_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&AppendToVectorTestTask, &order, std::string("C2")));
+
+ // Compositor policy mode should have ended now that the clock has advanced.
+ RunUntilIdle();
+ EXPECT_THAT(order,
+ testing::ElementsAre(std::string("D1"), std::string("C1"),
+ std::string("D2"), std::string("C2")));
+}
+
+TEST_F(RendererSchedulerImplTest, TestShouldYield) {
+ bool should_yield_before = false;
+ bool should_yield_after = false;
+
+ default_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
+ default_task_runner_, false, &should_yield_before,
+ &should_yield_after));
+ RunUntilIdle();
+ // Posting to default runner shouldn't cause yielding.
+ EXPECT_FALSE(should_yield_before);
+ EXPECT_FALSE(should_yield_after);
+
+ default_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
+ compositor_task_runner_, false,
+ &should_yield_before, &should_yield_after));
+ RunUntilIdle();
+ // Posting while not in compositor priority shouldn't cause yielding.
+ EXPECT_FALSE(should_yield_before);
+ EXPECT_FALSE(should_yield_after);
+
+ default_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&PostingYieldingTestTask, scheduler_.get(),
+ compositor_task_runner_, true, &should_yield_before,
+ &should_yield_after));
+ RunUntilIdle();
+ // We should be able to switch to compositor priority mid-task.
+ EXPECT_FALSE(should_yield_before);
+ EXPECT_TRUE(should_yield_after);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/renderer_task_queue_selector.cc b/chromium/content/renderer/scheduler/renderer_task_queue_selector.cc
new file mode 100644
index 00000000000..c804437bd41
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_task_queue_selector.cc
@@ -0,0 +1,122 @@
+// Copyright 2014 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 "content/renderer/scheduler/renderer_task_queue_selector.h"
+
+#include "base/logging.h"
+#include "base/pending_task.h"
+
+namespace content {
+
+RendererTaskQueueSelector::RendererTaskQueueSelector() : starvation_count_(0) {
+}
+
+RendererTaskQueueSelector::~RendererTaskQueueSelector() {
+}
+
+void RendererTaskQueueSelector::RegisterWorkQueues(
+ const std::vector<const base::TaskQueue*>& work_queues) {
+ main_thread_checker_.CalledOnValidThread();
+ work_queues_ = work_queues;
+ for (QueuePriority priority = FIRST_QUEUE_PRIORITY;
+ priority < QUEUE_PRIORITY_COUNT;
+ priority = NextPriority(priority)) {
+ queue_priorities_[priority].clear();
+ }
+ // By default, all work queues are set to normal priority.
+ for (size_t i = 0; i < work_queues.size(); i++) {
+ queue_priorities_[NORMAL_PRIORITY].insert(i);
+ }
+}
+
+void RendererTaskQueueSelector::SetQueuePriority(size_t queue_index,
+ QueuePriority priority) {
+ main_thread_checker_.CalledOnValidThread();
+ DCHECK_LT(queue_index, work_queues_.size());
+ DCHECK_LT(priority, QUEUE_PRIORITY_COUNT);
+ DisableQueue(queue_index);
+ queue_priorities_[priority].insert(queue_index);
+}
+
+void RendererTaskQueueSelector::EnableQueue(size_t queue_index,
+ QueuePriority priority) {
+ SetQueuePriority(queue_index, priority);
+}
+
+void RendererTaskQueueSelector::DisableQueue(size_t queue_index) {
+ main_thread_checker_.CalledOnValidThread();
+ DCHECK_LT(queue_index, work_queues_.size());
+ for (QueuePriority priority = FIRST_QUEUE_PRIORITY;
+ priority < QUEUE_PRIORITY_COUNT;
+ priority = NextPriority(priority)) {
+ queue_priorities_[priority].erase(queue_index);
+ }
+}
+
+bool RendererTaskQueueSelector::IsOlder(const base::TaskQueue* queueA,
+ const base::TaskQueue* queueB) {
+ // Note: the comparison is correct due to the fact that the PendingTask
+ // operator inverts its comparison operation in order to work well in a heap
+ // based priority queue.
+ return queueB->front() < queueA->front();
+}
+
+RendererTaskQueueSelector::QueuePriority
+RendererTaskQueueSelector::NextPriority(QueuePriority priority) {
+ DCHECK(priority < QUEUE_PRIORITY_COUNT);
+ return static_cast<QueuePriority>(static_cast<int>(priority) + 1);
+}
+
+bool RendererTaskQueueSelector::ChooseOldestWithPriority(
+ QueuePriority priority,
+ size_t* out_queue_index) const {
+ bool found_non_empty_queue = false;
+ size_t chosen_queue = 0;
+ for (int queue_index : queue_priorities_[priority]) {
+ if (work_queues_[queue_index]->empty()) {
+ continue;
+ }
+ if (!found_non_empty_queue ||
+ IsOlder(work_queues_[queue_index], work_queues_[chosen_queue])) {
+ found_non_empty_queue = true;
+ chosen_queue = queue_index;
+ }
+ }
+
+ if (found_non_empty_queue) {
+ *out_queue_index = chosen_queue;
+ }
+ return found_non_empty_queue;
+}
+
+bool RendererTaskQueueSelector::SelectWorkQueueToService(
+ size_t* out_queue_index) {
+ main_thread_checker_.CalledOnValidThread();
+ DCHECK(work_queues_.size());
+ // Always service the control queue if it has any work.
+ if (ChooseOldestWithPriority(CONTROL_PRIORITY, out_queue_index)) {
+ return true;
+ }
+ // Select from the normal priority queue if we are starving it.
+ if (starvation_count_ >= kMaxStarvationTasks &&
+ ChooseOldestWithPriority(NORMAL_PRIORITY, out_queue_index)) {
+ starvation_count_ = 0;
+ return true;
+ }
+ // Otherwise choose in priority order.
+ for (QueuePriority priority = HIGH_PRIORITY; priority < QUEUE_PRIORITY_COUNT;
+ priority = NextPriority(priority)) {
+ if (ChooseOldestWithPriority(priority, out_queue_index)) {
+ if (priority == HIGH_PRIORITY) {
+ starvation_count_++;
+ } else {
+ starvation_count_ = 0;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/renderer_task_queue_selector.h b/chromium/content/renderer/scheduler/renderer_task_queue_selector.h
new file mode 100644
index 00000000000..085a628fd54
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_task_queue_selector.h
@@ -0,0 +1,91 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_RENDERER_TASK_QUEUE_SELECTOR_H
+#define CONTENT_RENDERER_SCHEDULER_RENDERER_TASK_QUEUE_SELECTOR_H
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "content/renderer/scheduler/task_queue_selector.h"
+
+namespace content {
+
+// A RendererTaskQueueSelector is a TaskQueueSelector which is used by the
+// RendererScheduler to enable prioritization of particular task queues.
+class CONTENT_EXPORT RendererTaskQueueSelector
+ : NON_EXPORTED_BASE(public TaskQueueSelector) {
+ public:
+ enum QueuePriority {
+ // Queues with control priority will run before any other queue, and will
+ // explicitly starve other queues. Typically this should only be used for
+ // private queues which perform control operations.
+ CONTROL_PRIORITY,
+ // Queues with high priority will be selected preferentially over normal or
+ // best effort queues. The selector will ensure that high priority queues
+ // cannot completely starve normal priority queues.
+ HIGH_PRIORITY,
+ // Queues with normal priority are the default.
+ NORMAL_PRIORITY,
+ // Queues with best effort priority will only be run if all other queues are
+ // empty. They can be starved by the other queues.
+ BEST_EFFORT_PRIORITY,
+ // Must be the last entry.
+ QUEUE_PRIORITY_COUNT,
+ FIRST_QUEUE_PRIORITY = CONTROL_PRIORITY,
+ };
+
+ RendererTaskQueueSelector();
+ ~RendererTaskQueueSelector() override;
+
+ // Set the priority of |queue_index| to |priority|.
+ void SetQueuePriority(size_t queue_index, QueuePriority priority);
+
+ // Enable the |queue_index| with a priority of |priority|. By default all
+ // queues are enabled with normal priority.
+ void EnableQueue(size_t queue_index, QueuePriority priority);
+
+ // Disable the |queue_index|.
+ void DisableQueue(size_t queue_index);
+
+ // TaskQueueSelector implementation:
+ void RegisterWorkQueues(
+ const std::vector<const base::TaskQueue*>& work_queues) override;
+ bool SelectWorkQueueToService(size_t* out_queue_index) override;
+
+ private:
+ // Returns true if queueA contains an older task than queueB.
+ static bool IsOlder(const base::TaskQueue* queueA,
+ const base::TaskQueue* queueB);
+
+ // Returns the priority which is next after |priority|.
+ static QueuePriority NextPriority(QueuePriority priority);
+
+ // Return true if |out_queue_index| indicates the index of the queue with
+ // the oldest pending task from the set of queues of |priority|, or
+ // false if all queues of that priority are empty.
+ bool ChooseOldestWithPriority(QueuePriority priority,
+ size_t* out_queue_index) const;
+
+ // Returns true if |queue_index| is enabled with the given |priority|.
+ bool QueueEnabledWithPriority(size_t queue_index,
+ QueuePriority priority) const;
+
+ // Number of high priority tasks which can be run before a normal priority
+ // task should be selected to prevent starvation.
+ // TODO(rmcilroy): Check if this is a good value.
+ static const size_t kMaxStarvationTasks = 5;
+
+ base::ThreadChecker main_thread_checker_;
+ std::vector<const base::TaskQueue*> work_queues_;
+ std::set<size_t> queue_priorities_[QUEUE_PRIORITY_COUNT];
+ size_t starvation_count_;
+ DISALLOW_COPY_AND_ASSIGN(RendererTaskQueueSelector);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_RENDERER_TASK_QUEUE_SELECTOR_H
diff --git a/chromium/content/renderer/scheduler/renderer_task_queue_selector_unittest.cc b/chromium/content/renderer/scheduler/renderer_task_queue_selector_unittest.cc
new file mode 100644
index 00000000000..5f9197ee158
--- /dev/null
+++ b/chromium/content/renderer/scheduler/renderer_task_queue_selector_unittest.cc
@@ -0,0 +1,201 @@
+// Copyright 2014 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 "content/renderer/scheduler/renderer_task_queue_selector.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/pending_task.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class RendererTaskQueueSelectorTest : public testing::Test {
+ public:
+ RendererTaskQueueSelectorTest()
+ : test_closure_(
+ base::Bind(&RendererTaskQueueSelectorTest::TestFunction)) {}
+ ~RendererTaskQueueSelectorTest() override {}
+
+ std::vector<base::PendingTask> GetTasks(int count) {
+ std::vector<base::PendingTask> tasks;
+ for (int i = 0; i < count; i++) {
+ base::PendingTask task = base::PendingTask(FROM_HERE, test_closure_);
+ task.sequence_num = i;
+ tasks.push_back(task);
+ }
+ return tasks;
+ }
+
+ void PushTasks(const std::vector<base::PendingTask>& tasks,
+ const size_t queue_indices[]) {
+ for (size_t i = 0; i < tasks.size(); i++) {
+ task_queues_[queue_indices[i]]->push(tasks[i]);
+ }
+ }
+
+ std::vector<size_t> PopTasks() {
+ std::vector<size_t> order;
+ size_t chosen_queue_index;
+ while (selector_.SelectWorkQueueToService(&chosen_queue_index)) {
+ order.push_back(chosen_queue_index);
+ task_queues_[chosen_queue_index]->pop();
+ }
+ return order;
+ }
+
+ static void TestFunction() {}
+
+ protected:
+ void SetUp() final {
+ std::vector<const base::TaskQueue*> const_task_queues;
+ for (size_t i = 0; i < kTaskQueueCount; i++) {
+ scoped_ptr<base::TaskQueue> task_queue(new base::TaskQueue());
+ const_task_queues.push_back(task_queue.get());
+ task_queues_.push_back(task_queue.release());
+ }
+ selector_.RegisterWorkQueues(const_task_queues);
+ }
+
+ const size_t kTaskQueueCount = 5;
+ base::Closure test_closure_;
+ RendererTaskQueueSelector selector_;
+ ScopedVector<base::TaskQueue> task_queues_;
+};
+
+TEST_F(RendererTaskQueueSelectorTest, TestDefaultPriority) {
+ std::vector<base::PendingTask> tasks = GetTasks(5);
+ size_t queue_order[] = {4, 3, 2, 1, 0};
+ PushTasks(tasks, queue_order);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestHighPriority) {
+ std::vector<base::PendingTask> tasks = GetTasks(5);
+ size_t queue_order[] = {0, 1, 2, 3, 4};
+ PushTasks(tasks, queue_order);
+ selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 0, 1, 3, 4));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestBestEffortPriority) {
+ std::vector<base::PendingTask> tasks = GetTasks(5);
+ size_t queue_order[] = {0, 1, 2, 3, 4};
+ PushTasks(tasks, queue_order);
+ selector_.SetQueuePriority(0,
+ RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(2, 1, 3, 4, 0));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestControlPriority) {
+ std::vector<base::PendingTask> tasks = GetTasks(5);
+ size_t queue_order[] = {0, 1, 2, 3, 4};
+ PushTasks(tasks, queue_order);
+ selector_.SetQueuePriority(4, RendererTaskQueueSelector::CONTROL_PRIORITY);
+ selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 2, 0, 1, 3));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestDisableEnable) {
+ std::vector<base::PendingTask> tasks = GetTasks(5);
+ size_t queue_order[] = {0, 1, 2, 3, 4};
+ PushTasks(tasks, queue_order);
+ selector_.DisableQueue(2);
+ selector_.DisableQueue(4);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3));
+ selector_.EnableQueue(2, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(2));
+ selector_.EnableQueue(4, RendererTaskQueueSelector::NORMAL_PRIORITY);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(4));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestEmptyQueues) {
+ size_t chosen_queue_index = 0;
+ EXPECT_FALSE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+
+ // Test only disabled queues.
+ std::vector<base::PendingTask> tasks = GetTasks(1);
+ size_t queue_order[] = {0};
+ PushTasks(tasks, queue_order);
+ selector_.DisableQueue(0);
+ EXPECT_FALSE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestDelay) {
+ std::vector<base::PendingTask> tasks = GetTasks(5);
+ tasks[0].delayed_run_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(200);
+ tasks[3].delayed_run_time =
+ base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
+ size_t queue_order[] = {0, 1, 2, 3, 4};
+ PushTasks(tasks, queue_order);
+ EXPECT_THAT(PopTasks(), testing::ElementsAre(1, 2, 4, 3, 0));
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestControlStarvesOthers) {
+ std::vector<base::PendingTask> tasks = GetTasks(4);
+ size_t queue_order[] = {0, 1, 2, 3};
+ PushTasks(tasks, queue_order);
+ selector_.SetQueuePriority(3, RendererTaskQueueSelector::CONTROL_PRIORITY);
+ selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY);
+ selector_.SetQueuePriority(1,
+ RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ for (int i = 0; i < 100; i++) {
+ size_t chosen_queue_index = 0;
+ EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+ EXPECT_EQ(3ul, chosen_queue_index);
+ // Don't remove task from queue to simulate all queues still being full.
+ }
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestHighPriorityDoesNotStarveNormal) {
+ std::vector<base::PendingTask> tasks = GetTasks(3);
+ size_t queue_order[] = {0, 1, 2};
+ PushTasks(tasks, queue_order);
+ selector_.SetQueuePriority(2, RendererTaskQueueSelector::HIGH_PRIORITY);
+ selector_.SetQueuePriority(1,
+ RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ size_t counts[] = {0, 0, 0};
+ for (int i = 0; i < 100; i++) {
+ size_t chosen_queue_index = 0;
+ EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+ counts[chosen_queue_index]++;
+ // Don't remove task from queue to simulate all queues still being full.
+ }
+ EXPECT_GT(counts[0], 0ul); // Check high doesn't starve normal.
+ EXPECT_GT(counts[2], counts[0]); // Check high gets more chance to run.
+ EXPECT_EQ(0ul, counts[1]); // Check best effort is starved.
+}
+
+TEST_F(RendererTaskQueueSelectorTest, TestBestEffortGetsStarved) {
+ std::vector<base::PendingTask> tasks = GetTasks(2);
+ size_t queue_order[] = {0, 1};
+ PushTasks(tasks, queue_order);
+ selector_.SetQueuePriority(0,
+ RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
+ selector_.SetQueuePriority(1, RendererTaskQueueSelector::NORMAL_PRIORITY);
+ size_t chosen_queue_index = 0;
+ for (int i = 0; i < 100; i++) {
+ EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+ EXPECT_EQ(1ul, chosen_queue_index);
+ // Don't remove task from queue to simulate all queues still being full.
+ }
+ selector_.SetQueuePriority(1, RendererTaskQueueSelector::HIGH_PRIORITY);
+ for (int i = 0; i < 100; i++) {
+ EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+ EXPECT_EQ(1ul, chosen_queue_index);
+ // Don't remove task from queue to simulate all queues still being full.
+ }
+ selector_.SetQueuePriority(1, RendererTaskQueueSelector::CONTROL_PRIORITY);
+ for (int i = 0; i < 100; i++) {
+ EXPECT_TRUE(selector_.SelectWorkQueueToService(&chosen_queue_index));
+ EXPECT_EQ(1ul, chosen_queue_index);
+ // Don't remove task from queue to simulate all queues still being full.
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/single_thread_idle_task_runner.cc b/chromium/content/renderer/scheduler/single_thread_idle_task_runner.cc
new file mode 100644
index 00000000000..56cf0e9e5b8
--- /dev/null
+++ b/chromium/content/renderer/scheduler/single_thread_idle_task_runner.cc
@@ -0,0 +1,38 @@
+// Copyright 2014 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 "content/renderer/scheduler/single_thread_idle_task_runner.h"
+
+#include "base/location.h"
+
+namespace content {
+
+SingleThreadIdleTaskRunner::SingleThreadIdleTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ base::Callback<void(base::TimeTicks*)> deadline_supplier)
+ : task_runner_(task_runner), deadline_supplier_(deadline_supplier) {
+}
+
+SingleThreadIdleTaskRunner::~SingleThreadIdleTaskRunner() {
+}
+
+bool SingleThreadIdleTaskRunner::RunsTasksOnCurrentThread() const {
+ return task_runner_->RunsTasksOnCurrentThread();
+}
+
+void SingleThreadIdleTaskRunner::PostIdleTask(
+ const tracked_objects::Location& from_here,
+ const IdleTask& idle_task) {
+ task_runner_->PostTask(
+ from_here,
+ base::Bind(&SingleThreadIdleTaskRunner::RunTask, this, idle_task));
+}
+
+void SingleThreadIdleTaskRunner::RunTask(IdleTask idle_task) {
+ base::TimeTicks deadline;
+ deadline_supplier_.Run(&deadline);
+ idle_task.Run(deadline);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/single_thread_idle_task_runner.h b/chromium/content/renderer/scheduler/single_thread_idle_task_runner.h
new file mode 100644
index 00000000000..79002438781
--- /dev/null
+++ b/chromium/content/renderer/scheduler/single_thread_idle_task_runner.h
@@ -0,0 +1,49 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_SINGLE_THREAD_IDLE_TASK_RUNNER_H_
+#define CONTENT_RENDERER_SCHEDULER_SINGLE_THREAD_IDLE_TASK_RUNNER_H_
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
+
+namespace content {
+
+// A SingleThreadIdleTaskRunner is a task runner for running idle tasks. Idle
+// tasks have an unbound argument which is bound to a deadline
+// (in base::TimeTicks) when they are run. The idle task is expected to
+// complete by this deadline.
+class SingleThreadIdleTaskRunner
+ : public base::RefCountedThreadSafe<SingleThreadIdleTaskRunner> {
+ public:
+ typedef base::Callback<void(base::TimeTicks)> IdleTask;
+
+ SingleThreadIdleTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ base::Callback<void(base::TimeTicks*)> deadline_supplier);
+
+ virtual void PostIdleTask(const tracked_objects::Location& from_here,
+ const IdleTask& idle_task);
+
+ bool RunsTasksOnCurrentThread() const;
+
+ protected:
+ virtual ~SingleThreadIdleTaskRunner();
+
+ private:
+ friend class base::RefCountedThreadSafe<SingleThreadIdleTaskRunner>;
+
+ void RunTask(IdleTask idle_task);
+
+ scoped_refptr<base::TaskRunner> task_runner_;
+ base::Callback<void(base::TimeTicks*)> deadline_supplier_;
+ DISALLOW_COPY_AND_ASSIGN(SingleThreadIdleTaskRunner);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_SINGLE_THREAD_IDLE_TASK_RUNNER_H_
diff --git a/chromium/content/renderer/scheduler/task_queue_manager.cc b/chromium/content/renderer/scheduler/task_queue_manager.cc
new file mode 100644
index 00000000000..658aef72060
--- /dev/null
+++ b/chromium/content/renderer/scheduler/task_queue_manager.cc
@@ -0,0 +1,294 @@
+// Copyright 2014 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 "content/renderer/scheduler/task_queue_manager.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "content/renderer/scheduler/task_queue_selector.h"
+
+namespace content {
+namespace internal {
+
+class TaskQueue : public base::SingleThreadTaskRunner {
+ public:
+ TaskQueue(TaskQueueManager* task_queue_manager);
+
+ // base::SingleThreadTaskRunner implementation.
+ bool RunsTasksOnCurrentThread() const override;
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
+
+ // Adds a task at the end of the incoming task queue and schedules a call to
+ // TaskQueueManager::DoWork() if the incoming queue was empty and automatic
+ // pumping is enabled. Can be called on an arbitrary thread.
+ void EnqueueTask(const base::PendingTask& pending_task);
+
+ bool IsQueueEmpty() const;
+
+ void SetAutoPump(bool auto_pump);
+ void PumpQueue();
+
+ bool UpdateWorkQueue();
+ base::PendingTask TakeTaskFromWorkQueue();
+
+ void WillDeleteTaskQueueManager();
+
+ base::TaskQueue& work_queue() { return work_queue_; }
+
+ private:
+ ~TaskQueue() override;
+
+ void PumpQueueLocked();
+ void EnqueueTaskLocked(const base::PendingTask& pending_task);
+
+ // This lock protects all members except the work queue.
+ mutable base::Lock lock_;
+ TaskQueueManager* task_queue_manager_;
+ base::TaskQueue incoming_queue_;
+ bool auto_pump_;
+
+ base::TaskQueue work_queue_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskQueue);
+};
+
+TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager)
+ : task_queue_manager_(task_queue_manager), auto_pump_(true) {
+}
+
+TaskQueue::~TaskQueue() {
+}
+
+void TaskQueue::WillDeleteTaskQueueManager() {
+ base::AutoLock lock(lock_);
+ task_queue_manager_ = nullptr;
+}
+
+bool TaskQueue::RunsTasksOnCurrentThread() const {
+ base::AutoLock lock(lock_);
+ if (!task_queue_manager_)
+ return false;
+ return task_queue_manager_->RunsTasksOnCurrentThread();
+}
+
+bool TaskQueue::PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ base::AutoLock lock(lock_);
+ if (!task_queue_manager_)
+ return false;
+
+ base::PendingTask pending_task(from_here, task);
+ task_queue_manager_->DidQueueTask(&pending_task);
+
+ if (delay > base::TimeDelta()) {
+ return task_queue_manager_->PostDelayedTask(
+ from_here, Bind(&TaskQueue::EnqueueTask, this, pending_task), delay);
+ }
+ EnqueueTaskLocked(pending_task);
+ return true;
+}
+
+bool TaskQueue::PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ base::AutoLock lock(lock_);
+ if (!task_queue_manager_)
+ return false;
+ return task_queue_manager_->PostNonNestableDelayedTask(
+ from_here, task, delay);
+}
+
+bool TaskQueue::IsQueueEmpty() const {
+ if (!work_queue_.empty())
+ return false;
+
+ {
+ base::AutoLock lock(lock_);
+ return incoming_queue_.empty();
+ }
+}
+
+bool TaskQueue::UpdateWorkQueue() {
+ if (!work_queue_.empty())
+ return true;
+
+ {
+ base::AutoLock lock(lock_);
+ if (!auto_pump_ || incoming_queue_.empty())
+ return false;
+ work_queue_.Swap(&incoming_queue_);
+ return true;
+ }
+}
+
+base::PendingTask TaskQueue::TakeTaskFromWorkQueue() {
+ base::PendingTask pending_task = work_queue_.front();
+ work_queue_.pop();
+ return pending_task;
+}
+
+void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) {
+ base::AutoLock lock(lock_);
+ EnqueueTaskLocked(pending_task);
+}
+
+void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) {
+ lock_.AssertAcquired();
+ if (!task_queue_manager_)
+ return;
+ if (auto_pump_ && incoming_queue_.empty())
+ task_queue_manager_->PostDoWorkOnMainRunner();
+ incoming_queue_.push(pending_task);
+}
+
+void TaskQueue::SetAutoPump(bool auto_pump) {
+ base::AutoLock lock(lock_);
+ if (auto_pump) {
+ auto_pump_ = true;
+ PumpQueueLocked();
+ } else {
+ auto_pump_ = false;
+ }
+}
+
+void TaskQueue::PumpQueueLocked() {
+ lock_.AssertAcquired();
+ while (!incoming_queue_.empty()) {
+ work_queue_.push(incoming_queue_.front());
+ incoming_queue_.pop();
+ }
+ if (!work_queue_.empty())
+ task_queue_manager_->PostDoWorkOnMainRunner();
+}
+
+void TaskQueue::PumpQueue() {
+ base::AutoLock lock(lock_);
+ PumpQueueLocked();
+}
+
+} // namespace
+
+TaskQueueManager::TaskQueueManager(
+ size_t task_queue_count,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ TaskQueueSelector* selector)
+ : main_task_runner_(main_task_runner),
+ selector_(selector),
+ weak_factory_(this) {
+ DCHECK(main_task_runner->RunsTasksOnCurrentThread());
+
+ task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr();
+ for (size_t i = 0; i < task_queue_count; i++) {
+ scoped_refptr<internal::TaskQueue> queue(
+ make_scoped_refptr(new internal::TaskQueue(this)));
+ queues_.push_back(queue);
+ }
+
+ std::vector<const base::TaskQueue*> work_queues;
+ for (const auto& queue: queues_)
+ work_queues.push_back(&queue->work_queue());
+ selector_->RegisterWorkQueues(work_queues);
+}
+
+TaskQueueManager::~TaskQueueManager() {
+ for (auto& queue : queues_)
+ queue->WillDeleteTaskQueueManager();
+}
+
+internal::TaskQueue* TaskQueueManager::Queue(size_t queue_index) const {
+ DCHECK_LT(queue_index, queues_.size());
+ return queues_[queue_index].get();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+TaskQueueManager::TaskRunnerForQueue(size_t queue_index) const {
+ return Queue(queue_index);
+}
+
+bool TaskQueueManager::IsQueueEmpty(size_t queue_index) const {
+ internal::TaskQueue* queue = Queue(queue_index);
+ return queue->IsQueueEmpty();
+}
+
+void TaskQueueManager::SetAutoPump(size_t queue_index, bool auto_pump) {
+ main_thread_checker_.CalledOnValidThread();
+ internal::TaskQueue* queue = Queue(queue_index);
+ queue->SetAutoPump(auto_pump);
+}
+
+void TaskQueueManager::PumpQueue(size_t queue_index) {
+ main_thread_checker_.CalledOnValidThread();
+ internal::TaskQueue* queue = Queue(queue_index);
+ queue->PumpQueue();
+}
+
+bool TaskQueueManager::UpdateWorkQueues() {
+ // TODO(skyostil): This is not efficient when the number of queues grows very
+ // large due to the number of locks taken. Consider optimizing when we get
+ // there.
+ main_thread_checker_.CalledOnValidThread();
+ bool has_work = false;
+ for (auto& queue : queues_)
+ has_work |= queue->UpdateWorkQueue();
+ return has_work;
+}
+
+void TaskQueueManager::PostDoWorkOnMainRunner() {
+ main_task_runner_->PostTask(
+ FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_));
+}
+
+void TaskQueueManager::DoWork() {
+ main_thread_checker_.CalledOnValidThread();
+ if (!UpdateWorkQueues())
+ return;
+
+ size_t queue_index;
+ if (!selector_->SelectWorkQueueToService(&queue_index))
+ return;
+ PostDoWorkOnMainRunner();
+ RunTaskFromWorkQueue(queue_index);
+}
+
+void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) {
+ pending_task->sequence_num = task_sequence_num_.GetNext();
+ task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task);
+}
+
+void TaskQueueManager::RunTaskFromWorkQueue(size_t queue_index) {
+ main_thread_checker_.CalledOnValidThread();
+ internal::TaskQueue* queue = Queue(queue_index);
+ base::PendingTask pending_task = queue->TakeTaskFromWorkQueue();
+ task_annotator_.RunTask(
+ "TaskQueueManager::PostTask", "TaskQueueManager::RunTask", pending_task);
+}
+
+bool TaskQueueManager::RunsTasksOnCurrentThread() const {
+ return main_task_runner_->RunsTasksOnCurrentThread();
+}
+
+bool TaskQueueManager::PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ DCHECK(delay > base::TimeDelta());
+ return main_task_runner_->PostDelayedTask(from_here, task, delay);
+}
+
+bool TaskQueueManager::PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) {
+ // Defer non-nestable work to the main task runner.
+ return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/task_queue_manager.h b/chromium/content/renderer/scheduler/task_queue_manager.h
new file mode 100644
index 00000000000..b1b79357ad3
--- /dev/null
+++ b/chromium/content/renderer/scheduler/task_queue_manager.h
@@ -0,0 +1,118 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_
+#define CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_
+
+#include "base/atomic_sequence_num.h"
+#include "base/debug/task_annotator.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/pending_task.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+
+namespace content {
+namespace internal {
+class TaskQueue;
+}
+class TaskQueueSelector;
+
+// The task queue manager provides N task queues and a selector interface for
+// choosing which task queue to service next. Each task queue consists of two
+// sub queues:
+//
+// 1. Incoming task queue. Tasks that are posted get immediately appended here.
+// When a task is appended into an empty incoming queue, the task manager
+// work function (DoWork) is scheduled to run on the main task runner.
+//
+// 2. Work queue. If a work queue is empty when DoWork() is entered, tasks from
+// the incoming task queue (if any) are moved here. The work queues are
+// registered with the selector as input to the scheduling decision.
+//
+class CONTENT_EXPORT TaskQueueManager {
+ public:
+ // Create a task queue manager with |task_queue_count| task queues.
+ // |main_task_runner| identifies the thread on which where the tasks are
+ // eventually run. |selector| is used to choose which task queue to service.
+ // It should outlive this class.
+ TaskQueueManager(size_t task_queue_count,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
+ TaskQueueSelector* selector);
+ ~TaskQueueManager();
+
+ // Returns the task runner which targets the queue selected by |queue_index|.
+ scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForQueue(
+ size_t queue_index) const;
+
+ // If |auto_pump| is false, tasks posted to the given incoming queue will not
+ // be automatically scheduled for execution or transferred to the work queue.
+ // Instead, the selector should call PumpQueue() when necessary to bring in
+ // new tasks for execution.
+ void SetAutoPump(size_t queue_index, bool auto_pump);
+
+ // Reloads new tasks from the incoming queue for |queue_index| into the work
+ // queue, regardless of whether the work queue is empty or not. After this,
+ // this function ensures that the tasks in the work queue, if any, are
+ // scheduled for execution.
+ //
+ // This function only needs to be called if automatic pumping is disabled
+ // for |queue_index|. See |SetQueueAutoPump|. By default automatic pumping is
+ // enabled for all queues.
+ void PumpQueue(size_t queue_index);
+
+ // Returns true if there no tasks in either the work or incoming task queue
+ // identified by |queue_index|. Note that this function involves taking a
+ // lock, so calling it has some overhead.
+ bool IsQueueEmpty(size_t queue_index) const;
+
+ private:
+ friend class internal::TaskQueue;
+
+ // Called by the task queue to register a new pending task and allocate a
+ // sequence number for it.
+ void DidQueueTask(base::PendingTask* pending_task);
+
+ // Post a task to call DoWork() on the main task runner.
+ void PostDoWorkOnMainRunner();
+
+ // Use the selector to choose a pending task and run it.
+ void DoWork();
+
+ // Reloads any empty work queues which have automatic pumping enabled.
+ // Returns true if any work queue has tasks after doing this.
+ bool UpdateWorkQueues();
+
+ // Runs a single task from the work queue designated by |queue_index|. The
+ // queue must not be empty.
+ void RunTaskFromWorkQueue(size_t queue_index);
+
+ bool RunsTasksOnCurrentThread() const;
+ bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay);
+ bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay);
+ internal::TaskQueue* Queue(size_t queue_index) const;
+
+ std::vector<scoped_refptr<internal::TaskQueue>> queues_;
+ base::AtomicSequenceNumber task_sequence_num_;
+ base::debug::TaskAnnotator task_annotator_;
+
+ base::ThreadChecker main_thread_checker_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ TaskQueueSelector* selector_;
+
+ base::WeakPtr<TaskQueueManager> task_queue_manager_weak_ptr_;
+ base::WeakPtrFactory<TaskQueueManager> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskQueueManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_
diff --git a/chromium/content/renderer/scheduler/task_queue_manager_unittest.cc b/chromium/content/renderer/scheduler/task_queue_manager_unittest.cc
new file mode 100644
index 00000000000..43238250180
--- /dev/null
+++ b/chromium/content/renderer/scheduler/task_queue_manager_unittest.cc
@@ -0,0 +1,358 @@
+// Copyright 2014 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 "content/renderer/scheduler/task_queue_manager.h"
+
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread.h"
+#include "content/renderer/scheduler/task_queue_selector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class SelectorForTest : public TaskQueueSelector {
+ public:
+ SelectorForTest() {}
+
+ void RegisterWorkQueues(
+ const std::vector<const base::TaskQueue*>& work_queues) override {
+ work_queues_ = work_queues;
+ }
+
+ bool SelectWorkQueueToService(size_t* out_queue_index) override {
+ if (queues_to_service_.empty())
+ return false;
+ *out_queue_index = queues_to_service_.front();
+ queues_to_service_.pop_front();
+ return true;
+ }
+
+ void AppendQueueToService(size_t queue_index) {
+ queues_to_service_.push_back(queue_index);
+ }
+
+ const std::vector<const base::TaskQueue*>& work_queues() {
+ return work_queues_;
+ }
+
+ private:
+ std::deque<size_t> queues_to_service_;
+ std::vector<const base::TaskQueue*> work_queues_;
+
+ DISALLOW_COPY_AND_ASSIGN(SelectorForTest);
+};
+
+class TaskQueueManagerTest : public testing::Test {
+ protected:
+ void Initialize(size_t num_queues) {
+ test_task_runner_ = make_scoped_refptr(new base::TestSimpleTaskRunner());
+ selector_ = make_scoped_ptr(new SelectorForTest);
+ manager_ = make_scoped_ptr(
+ new TaskQueueManager(num_queues, test_task_runner_, selector_.get()));
+ }
+
+ scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_;
+ scoped_ptr<SelectorForTest> selector_;
+ scoped_ptr<TaskQueueManager> manager_;
+};
+
+void TestTask(int value, std::vector<int>* out_result) {
+ out_result->push_back(value);
+}
+
+TEST_F(TaskQueueManagerTest, SingleQueuePosting) {
+ Initialize(1u);
+ EXPECT_EQ(1u, selector_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order));
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order));
+
+ selector_->AppendQueueToService(0);
+ selector_->AppendQueueToService(0);
+ selector_->AppendQueueToService(0);
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+ EXPECT_EQ(2, run_order[1]);
+ EXPECT_EQ(3, run_order[2]);
+}
+
+TEST_F(TaskQueueManagerTest, MultiQueuePosting) {
+ Initialize(3u);
+ EXPECT_EQ(3u, selector_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runners[3] = {
+ manager_->TaskRunnerForQueue(0),
+ manager_->TaskRunnerForQueue(1),
+ manager_->TaskRunnerForQueue(2)};
+
+ selector_->AppendQueueToService(0);
+ selector_->AppendQueueToService(1);
+ selector_->AppendQueueToService(2);
+ selector_->AppendQueueToService(0);
+ selector_->AppendQueueToService(1);
+ selector_->AppendQueueToService(2);
+
+ runners[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ runners[0]->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order));
+ runners[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 3, &run_order));
+ runners[1]->PostTask(FROM_HERE, base::Bind(&TestTask, 4, &run_order));
+ runners[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 5, &run_order));
+ runners[2]->PostTask(FROM_HERE, base::Bind(&TestTask, 6, &run_order));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+ EXPECT_EQ(3, run_order[1]);
+ EXPECT_EQ(5, run_order[2]);
+ EXPECT_EQ(2, run_order[3]);
+ EXPECT_EQ(4, run_order[4]);
+ EXPECT_EQ(6, run_order[5]);
+}
+
+TEST_F(TaskQueueManagerTest, NonNestableTaskPosting) {
+ Initialize(1u);
+ EXPECT_EQ(1u, selector_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostNonNestableTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+
+ // Non-nestable tasks never make it to the selector.
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, QueuePolling) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ EXPECT_TRUE(manager_->IsQueueEmpty(0));
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ EXPECT_FALSE(manager_->IsQueueEmpty(0));
+
+ selector_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(manager_->IsQueueEmpty(0));
+}
+
+TEST_F(TaskQueueManagerTest, DelayedTaskPosting) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ selector_->AppendQueueToService(0);
+
+ base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10));
+ runner->PostDelayedTask(
+ FROM_HERE, base::Bind(&TestTask, 1, &run_order), delay);
+ EXPECT_EQ(delay, test_task_runner_->NextPendingTaskDelay());
+ EXPECT_TRUE(manager_->IsQueueEmpty(0));
+ EXPECT_TRUE(run_order.empty());
+
+ // The task is inserted to the incoming queue only after the delay.
+ test_task_runner_->RunPendingTasks();
+ EXPECT_FALSE(manager_->IsQueueEmpty(0));
+ EXPECT_TRUE(run_order.empty());
+
+ // After the delay the task runs normally.
+ selector_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumping) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting a task when pumping is disabled doesn't result in work getting
+ // posted.
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ EXPECT_FALSE(test_task_runner_->HasPendingTask());
+
+ // However polling still works.
+ EXPECT_FALSE(manager_->IsQueueEmpty(0));
+
+ // After pumping the task runs normally.
+ manager_->PumpQueue(0);
+ EXPECT_TRUE(test_task_runner_->HasPendingTask());
+ selector_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumpingToggle) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting a task when pumping is disabled doesn't result in work getting
+ // posted.
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ EXPECT_FALSE(test_task_runner_->HasPendingTask());
+
+ // When pumping is enabled the task runs normally.
+ manager_->SetAutoPump(0, true);
+ EXPECT_TRUE(test_task_runner_->HasPendingTask());
+ selector_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, DenyRunning) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+
+ // Since we haven't appended a work queue to be selected, the task doesn't
+ // run.
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+
+ // Pumping the queue again with a selected work queue runs the task.
+ manager_->PumpQueue(0);
+ selector_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumpingWithDelayedTask) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting a delayed task when pumping will apply the delay, but won't cause
+ // work to executed afterwards.
+ base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10));
+ runner->PostDelayedTask(
+ FROM_HERE, base::Bind(&TestTask, 1, &run_order), delay);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+
+ // After pumping the task runs normally.
+ manager_->PumpQueue(0);
+ EXPECT_TRUE(test_task_runner_->HasPendingTask());
+ selector_->AppendQueueToService(0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+TEST_F(TaskQueueManagerTest, ManualPumpingWithNonEmptyWorkQueue) {
+ Initialize(1u);
+ manager_->SetAutoPump(0, false);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ // Posting two tasks and pumping twice should result in two tasks in the work
+ // queue.
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ manager_->PumpQueue(0);
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 2, &run_order));
+ manager_->PumpQueue(0);
+
+ EXPECT_EQ(2u, selector_->work_queues()[0]->size());
+}
+
+void ReentrantTestTask(scoped_refptr<base::SingleThreadTaskRunner> runner,
+ int countdown,
+ std::vector<int>* out_result) {
+ out_result->push_back(countdown);
+ if (--countdown) {
+ runner->PostTask(FROM_HERE,
+ Bind(&ReentrantTestTask, runner, countdown, out_result));
+ }
+}
+
+TEST_F(TaskQueueManagerTest, ReentrantPosting) {
+ Initialize(1u);
+ EXPECT_EQ(1u, selector_->work_queues().size());
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostTask(FROM_HERE, Bind(&ReentrantTestTask, runner, 3, &run_order));
+
+ selector_->AppendQueueToService(0);
+ selector_->AppendQueueToService(0);
+ selector_->AppendQueueToService(0);
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(3, run_order[0]);
+ EXPECT_EQ(2, run_order[1]);
+ EXPECT_EQ(1, run_order[2]);
+}
+
+TEST_F(TaskQueueManagerTest, NoTasksAfterShutdown) {
+ Initialize(1u);
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+ manager_.reset();
+ selector_.reset();
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, &run_order));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+}
+
+void PostTaskToRunner(scoped_refptr<base::SingleThreadTaskRunner> runner,
+ std::vector<int>* run_order) {
+ runner->PostTask(FROM_HERE, base::Bind(&TestTask, 1, run_order));
+}
+
+TEST_F(TaskQueueManagerTest, PostFromThread) {
+ base::MessageLoop message_loop;
+ selector_ = make_scoped_ptr(new SelectorForTest);
+ manager_ = make_scoped_ptr(
+ new TaskQueueManager(1u, message_loop.task_runner(), selector_.get()));
+
+ std::vector<int> run_order;
+ scoped_refptr<base::SingleThreadTaskRunner> runner =
+ manager_->TaskRunnerForQueue(0);
+
+ base::Thread thread("TestThread");
+ thread.Start();
+ thread.message_loop()->PostTask(
+ FROM_HERE, base::Bind(&PostTaskToRunner, runner, &run_order));
+ thread.Stop();
+
+ selector_->AppendQueueToService(0);
+ message_loop.RunUntilIdle();
+ EXPECT_EQ(1, run_order[0]);
+}
+
+} // namespace
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/task_queue_selector.h b/chromium/content/renderer/scheduler/task_queue_selector.h
new file mode 100644
index 00000000000..afab36aa1a5
--- /dev/null
+++ b/chromium/content/renderer/scheduler/task_queue_selector.h
@@ -0,0 +1,37 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_SELECTOR_H_
+#define CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_SELECTOR_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+
+namespace base {
+class TaskQueue;
+}
+
+namespace content {
+
+class TaskQueueSelector {
+ public:
+ virtual ~TaskQueueSelector() {}
+
+ // Called once to register the work queues to be selected from. This function
+ // is called on the main thread.
+ virtual void RegisterWorkQueues(
+ const std::vector<const base::TaskQueue*>& work_queues) = 0;
+
+ // Called to choose the work queue from which the next task should be taken
+ // and run. Return true if |out_queue| indicates the queue to service or
+ // false to avoid running any task.
+ //
+ // This function is called on the main thread.
+ virtual bool SelectWorkQueueToService(size_t* out_queue_index) = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_SELECTOR_H_
diff --git a/chromium/content/renderer/scheduler/web_scheduler_impl.cc b/chromium/content/renderer/scheduler/web_scheduler_impl.cc
new file mode 100644
index 00000000000..c0a340795b7
--- /dev/null
+++ b/chromium/content/renderer/scheduler/web_scheduler_impl.cc
@@ -0,0 +1,45 @@
+// Copyright 2014 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 "content/renderer/scheduler/web_scheduler_impl.h"
+
+#include "base/bind.h"
+#include "content/renderer/scheduler/renderer_scheduler.h"
+#include "third_party/WebKit/public/platform/WebTraceLocation.h"
+
+namespace content {
+
+WebSchedulerImpl::WebSchedulerImpl(RendererScheduler* renderer_scheduler)
+ : renderer_scheduler_(renderer_scheduler),
+ idle_task_runner_(renderer_scheduler_->IdleTaskRunner()) {
+}
+
+WebSchedulerImpl::~WebSchedulerImpl() {
+}
+
+bool WebSchedulerImpl::shouldYieldForHighPriorityWork() {
+ return renderer_scheduler_->ShouldYieldForHighPriorityWork();
+}
+
+void WebSchedulerImpl::runIdleTask(
+ scoped_ptr<blink::WebScheduler::IdleTask> task,
+ base::TimeTicks deadline) {
+ task->run((deadline - base::TimeTicks()).InSecondsF());
+}
+
+void WebSchedulerImpl::postIdleTask(const blink::WebTraceLocation& web_location,
+ blink::WebScheduler::IdleTask* task) {
+ scoped_ptr<blink::WebScheduler::IdleTask> scoped_task(task);
+ tracked_objects::Location location(web_location.functionName(),
+ web_location.fileName(), -1, nullptr);
+ idle_task_runner_->PostIdleTask(
+ location,
+ base::Bind(&WebSchedulerImpl::runIdleTask, base::Passed(&scoped_task)));
+}
+
+void WebSchedulerImpl::shutdown() {
+ return renderer_scheduler_->Shutdown();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/scheduler/web_scheduler_impl.h b/chromium/content/renderer/scheduler/web_scheduler_impl.h
new file mode 100644
index 00000000000..98bdaafc4dd
--- /dev/null
+++ b/chromium/content/renderer/scheduler/web_scheduler_impl.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_WEB_SCHEDULER_IMPL_H_
+#define CONTENT_RENDERER_SCHEDULER_WEB_SCHEDULER_IMPL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "third_party/WebKit/public/platform/WebScheduler.h"
+
+namespace content {
+
+class RendererScheduler;
+class SingleThreadIdleTaskRunner;
+
+class WebSchedulerImpl : public blink::WebScheduler {
+ public:
+ WebSchedulerImpl(RendererScheduler* renderer_scheduler);
+ ~WebSchedulerImpl() override;
+
+ virtual bool shouldYieldForHighPriorityWork();
+ virtual void postIdleTask(const blink::WebTraceLocation& location,
+ blink::WebScheduler::IdleTask* task);
+ virtual void shutdown();
+
+ private:
+ static void runIdleTask(scoped_ptr<blink::WebScheduler::IdleTask> task,
+ base::TimeTicks deadline);
+
+ RendererScheduler* renderer_scheduler_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SCHEDULER_WEB_SCHEDULER_IMPL_H_
diff --git a/chromium/content/renderer/scoped_clipboard_writer_glue.cc b/chromium/content/renderer/scoped_clipboard_writer_glue.cc
index 37790375303..71471344fd5 100644
--- a/chromium/content/renderer/scoped_clipboard_writer_glue.cc
+++ b/chromium/content/renderer/scoped_clipboard_writer_glue.cc
@@ -8,17 +8,18 @@
namespace content {
ScopedClipboardWriterGlue::ScopedClipboardWriterGlue(ClipboardClient* client)
- : ui::ScopedClipboardWriter(client->GetClipboard(),
- ui::CLIPBOARD_TYPE_COPY_PASTE),
+ : ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE),
context_(client->CreateWriteContext()) {
- // We should never have an instance where both are set.
- DCHECK((clipboard_ && !context_.get()) ||
- (!clipboard_ && context_.get()));
+ DCHECK(context_);
}
ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() {
if (!objects_.empty() && context_) {
context_->Flush(objects_);
+ // TODO(dcheng): Temporary hack while the clipboard IPCs are cleaned up.
+ // This prevents the base class destructor from also trying to (probably
+ // unsuccessfully) flush things to the clipboard.
+ objects_.clear();
}
}
diff --git a/chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.cc b/chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.cc
deleted file mode 100644
index 7f9dd895cb6..00000000000
--- a/chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2014 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 "content/renderer/screen_orientation/mock_screen_orientation_controller.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "content/renderer/render_view_impl.h"
-
-namespace content {
-
-MockScreenOrientationController::MockScreenOrientationController()
- : RenderViewObserver(NULL),
- current_lock_(blink::WebScreenOrientationLockDefault),
- device_orientation_(blink::WebScreenOrientationPortraitPrimary),
- current_orientation_(blink::WebScreenOrientationPortraitPrimary) {
- // Since MockScreenOrientationController is held by LazyInstance reference,
- // add this ref for it.
- AddRef();
-}
-
-MockScreenOrientationController::~MockScreenOrientationController() {
-}
-
-void MockScreenOrientationController::ResetData() {
- if (render_view_impl())
- render_view_impl()->RemoveObserver(this);
-
- current_lock_ = blink::WebScreenOrientationLockDefault;
- device_orientation_ = blink::WebScreenOrientationPortraitPrimary;
- current_orientation_ = blink::WebScreenOrientationPortraitPrimary;
-}
-
-void MockScreenOrientationController::UpdateDeviceOrientation(
- RenderView* render_view,
- blink::WebScreenOrientationType orientation) {
- if (this->render_view()) {
- // Make sure that render_view_ did not change during test.
- DCHECK_EQ(this->render_view(), render_view);
- } else {
- Observe(render_view);
- }
-
- if (device_orientation_ == orientation)
- return;
- device_orientation_ = orientation;
- if (!IsOrientationAllowedByCurrentLock(orientation))
- return;
- UpdateScreenOrientation(orientation);
-}
-
-RenderViewImpl* MockScreenOrientationController::render_view_impl() const {
- return static_cast<RenderViewImpl*>(render_view());
-}
-
-void MockScreenOrientationController::UpdateScreenOrientation(
- blink::WebScreenOrientationType orientation) {
- if (current_orientation_ == orientation)
- return;
- current_orientation_ = orientation;
- if (render_view_impl())
- render_view_impl()->SetScreenOrientationForTesting(orientation);
-}
-
-bool MockScreenOrientationController::IsOrientationAllowedByCurrentLock(
- blink::WebScreenOrientationType orientation) {
- if (current_lock_ == blink::WebScreenOrientationLockDefault ||
- current_lock_ == blink::WebScreenOrientationLockAny) {
- return true;
- }
-
- switch (orientation) {
- case blink::WebScreenOrientationPortraitPrimary:
- return current_lock_ == blink::WebScreenOrientationLockPortraitPrimary ||
- current_lock_ == blink::WebScreenOrientationLockPortrait;
- case blink::WebScreenOrientationPortraitSecondary:
- return current_lock_ ==
- blink::WebScreenOrientationLockPortraitSecondary ||
- current_lock_ == blink::WebScreenOrientationLockPortrait;
- case blink::WebScreenOrientationLandscapePrimary:
- return current_lock_ == blink::WebScreenOrientationLockLandscapePrimary ||
- current_lock_ == blink::WebScreenOrientationLockLandscape;
- case blink::WebScreenOrientationLandscapeSecondary:
- return current_lock_ ==
- blink::WebScreenOrientationLockLandscapeSecondary ||
- current_lock_ == blink::WebScreenOrientationLockLandscape;
- default:
- return false;
- }
-}
-
-void MockScreenOrientationController::OnDestruct() {
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.h b/chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.h
deleted file mode 100644
index 2c9d5a9f77c..00000000000
--- a/chromium/content/renderer/screen_orientation/mock_screen_orientation_controller.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_SCREEN_ORIENTATION_MOCK_SCREEN_ORIENTATION_CONTROLLER_H_
-#define CONTENT_RENDERER_SCREEN_ORIENTATION_MOCK_SCREEN_ORIENTATION_CONTROLLER_H_
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/public/renderer/render_view_observer.h"
-#include "third_party/WebKit/public/platform/WebScreenOrientationLockType.h"
-#include "third_party/WebKit/public/platform/WebScreenOrientationType.h"
-
-namespace content {
-class RenderView;
-class RenderViewImpl;
-
-class MockScreenOrientationController
- : public base::RefCountedThreadSafe<MockScreenOrientationController>,
- public RenderViewObserver {
- public:
- MockScreenOrientationController();
-
- void ResetData();
- void UpdateDeviceOrientation(RenderView* render_view,
- blink::WebScreenOrientationType);
-
- private:
- virtual ~MockScreenOrientationController();
-
- void UpdateScreenOrientation(blink::WebScreenOrientationType);
- bool IsOrientationAllowedByCurrentLock(blink::WebScreenOrientationType);
- RenderViewImpl* render_view_impl() const;
-
- // RenderViewObserver
- virtual void OnDestruct() OVERRIDE;
-
- blink::WebScreenOrientationLockType current_lock_;
- blink::WebScreenOrientationType device_orientation_;
- blink::WebScreenOrientationType current_orientation_;
-
- DISALLOW_COPY_AND_ASSIGN(MockScreenOrientationController);
- friend class base::LazyInstance<MockScreenOrientationController>;
- friend class base::RefCountedThreadSafe<MockScreenOrientationController>;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_SCREEN_ORIENTATION_MOCK_SCREEN_ORIENTATION_CONTROLLER_H_
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
index e67cc73634e..f0060ef0b21 100644
--- a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.cc
@@ -31,21 +31,17 @@ bool ScreenOrientationDispatcher::OnMessageReceived(
return handled;
}
-void ScreenOrientationDispatcher::OnLockSuccess(
- int request_id,
- unsigned angle,
- blink::WebScreenOrientationType orientation) {
+void ScreenOrientationDispatcher::OnLockSuccess(int request_id) {
blink::WebLockOrientationCallback* callback =
pending_callbacks_.Lookup(request_id);
if (!callback)
return;
- callback->onSuccess(angle, orientation);
+ callback->onSuccess();
pending_callbacks_.Remove(request_id);
}
void ScreenOrientationDispatcher::OnLockError(
- int request_id,
- blink::WebLockOrientationCallback::ErrorType error) {
+ int request_id, blink::WebLockOrientationError error) {
blink::WebLockOrientationCallback* callback =
pending_callbacks_.Lookup(request_id);
if (!callback)
@@ -57,8 +53,7 @@ void ScreenOrientationDispatcher::OnLockError(
void ScreenOrientationDispatcher::CancelPendingLocks() {
for (CallbackMap::Iterator<blink::WebLockOrientationCallback>
iterator(&pending_callbacks_); !iterator.IsAtEnd(); iterator.Advance()) {
- iterator.GetCurrentValue()->onError(
- blink::WebLockOrientationCallback::ErrorTypeCanceled);
+ iterator.GetCurrentValue()->onError(blink::WebLockOrientationErrorCanceled);
pending_callbacks_.Remove(iterator.GetCurrentKey());
}
}
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h
index d64fda1514f..27523491ce5 100644
--- a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher.h
@@ -33,19 +33,17 @@ class CONTENT_EXPORT ScreenOrientationDispatcher :
friend class ScreenOrientationDispatcherTest;
// RenderFrameObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// blink::WebScreenOrientationClient implementation.
virtual void lockOrientation(
blink::WebScreenOrientationLockType orientation,
- blink::WebLockOrientationCallback* callback) OVERRIDE;
- virtual void unlockOrientation() OVERRIDE;
+ blink::WebLockOrientationCallback* callback) override;
+ virtual void unlockOrientation() override;
- void OnLockSuccess(int request_id,
- unsigned angle,
- blink::WebScreenOrientationType orientation);
+ void OnLockSuccess(int request_id);
void OnLockError(int request_id,
- blink::WebLockOrientationCallback::ErrorType error);
+ blink::WebLockOrientationError error);
void CancelPendingLocks();
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
index 461533e6304..4d7714169aa 100644
--- a/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_dispatcher_unittest.cc
@@ -32,23 +32,17 @@ class MockLockOrientationCallback :
bool succeeded_;
bool failed_;
- unsigned angle_;
- blink::WebScreenOrientationType orientation_;
- blink::WebLockOrientationCallback::ErrorType error_;
+ blink::WebLockOrientationError error_;
};
explicit MockLockOrientationCallback(LockOrientationResultHolder* results)
: results_(results) {}
- virtual void onSuccess(unsigned angle,
- blink::WebScreenOrientationType orientation) {
+ virtual void onSuccess() {
results_->succeeded_ = true;
- results_->angle_ = angle;
- results_->orientation_ = orientation;
}
- virtual void onError(
- blink::WebLockOrientationCallback::ErrorType error) {
+ virtual void onError(blink::WebLockOrientationError error) {
results_->failed_ = true;
results_->error_ = error;
}
@@ -65,16 +59,14 @@ class ScreenOrientationDispatcherWithSink : public ScreenOrientationDispatcher {
:ScreenOrientationDispatcher(NULL) , sink_(sink) {
}
- virtual bool Send(IPC::Message* message) OVERRIDE {
- return sink_->Send(message);
- }
+ bool Send(IPC::Message* message) override { return sink_->Send(message); }
IPC::TestSink* sink_;
};
class ScreenOrientationDispatcherTest : public testing::Test {
protected:
- virtual void SetUp() OVERRIDE {
+ void SetUp() override {
dispatcher_.reset(new ScreenOrientationDispatcherWithSink(&sink_));
}
@@ -124,8 +116,7 @@ TEST_F(ScreenOrientationDispatcherTest, CancelPending_Unlocking) {
EXPECT_FALSE(callback_results.succeeded_);
EXPECT_TRUE(callback_results.failed_);
- EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeCanceled,
- callback_results.error_);
+ EXPECT_EQ(blink::WebLockOrientationErrorCanceled, callback_results.error_);
}
// Test that calling lockOrientation() twice cancel the first lockOrientation().
@@ -141,20 +132,19 @@ TEST_F(ScreenOrientationDispatcherTest, CancelPending_DoubleLock) {
EXPECT_FALSE(callback_results.succeeded_);
EXPECT_TRUE(callback_results.failed_);
- EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeCanceled,
- callback_results.error_);
+ EXPECT_EQ(blink::WebLockOrientationErrorCanceled, callback_results.error_);
}
// Test that when a LockError message is received, the request is set as failed
// with the correct values.
TEST_F(ScreenOrientationDispatcherTest, LockRequest_Error) {
- std::list<blink::WebLockOrientationCallback::ErrorType> errors;
- errors.push_back(blink::WebLockOrientationCallback::ErrorTypeNotAvailable);
+ std::list<blink::WebLockOrientationError> errors;
+ errors.push_back(blink::WebLockOrientationErrorNotAvailable);
errors.push_back(
- blink::WebLockOrientationCallback::ErrorTypeFullScreenRequired);
- errors.push_back(blink::WebLockOrientationCallback::ErrorTypeCanceled);
+ blink::WebLockOrientationErrorFullScreenRequired);
+ errors.push_back(blink::WebLockOrientationErrorCanceled);
- for (std::list<blink::WebLockOrientationCallback::ErrorType>::const_iterator
+ for (std::list<blink::WebLockOrientationError>::const_iterator
it = errors.begin(); it != errors.end(); ++it) {
MockLockOrientationCallback::LockOrientationResultHolder callback_results;
LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
@@ -173,38 +163,20 @@ TEST_F(ScreenOrientationDispatcherTest, LockRequest_Error) {
}
// Test that when a LockSuccess message is received, the request is set as
-// succeeded with the correct values.
+// succeeded.
TEST_F(ScreenOrientationDispatcherTest, LockRequest_Success) {
- struct ScreenOrientationInformation {
- unsigned angle;
- blink::WebScreenOrientationType type;
- } orientations[] = {
- { 0, blink::WebScreenOrientationPortraitPrimary },
- { 0, blink::WebScreenOrientationLandscapePrimary },
- { 90, blink::WebScreenOrientationPortraitSecondary },
- { 90, blink::WebScreenOrientationLandscapePrimary }
- };
-
- int orientationsCount = 4;
-
- for (int i = 0; i < orientationsCount; ++i) {
- MockLockOrientationCallback::LockOrientationResultHolder callback_results;
- LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
- new MockLockOrientationCallback(&callback_results));
+ MockLockOrientationCallback::LockOrientationResultHolder callback_results;
+ LockOrientation(blink::WebScreenOrientationLockPortraitPrimary,
+ new MockLockOrientationCallback(&callback_results));
- int request_id = GetFirstLockRequestIdFromSink();
- OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
- request_id,
- orientations[i].angle,
- orientations[i].type));
+ int request_id = GetFirstLockRequestIdFromSink();
+ OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
+ request_id));
- EXPECT_TRUE(callback_results.succeeded_);
- EXPECT_FALSE(callback_results.failed_);
- EXPECT_EQ(orientations[i].angle, callback_results.angle_);
- EXPECT_EQ(orientations[i].type, callback_results.orientation_);
+ EXPECT_TRUE(callback_results.succeeded_);
+ EXPECT_FALSE(callback_results.failed_);
- sink().ClearMessages();
- }
+ sink().ClearMessages();
}
// Test an edge case: a LockSuccess is received but it matches no pending
@@ -215,11 +187,8 @@ TEST_F(ScreenOrientationDispatcherTest, SuccessForUnknownRequest) {
new MockLockOrientationCallback(&callback_results));
int request_id = GetFirstLockRequestIdFromSink();
- OnMessageReceived(ScreenOrientationMsg_LockSuccess(
- routing_id(),
- request_id + 1,
- 90,
- blink::WebScreenOrientationLandscapePrimary));
+ OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
+ request_id + 1));
EXPECT_FALSE(callback_results.succeeded_);
EXPECT_FALSE(callback_results.failed_);
@@ -234,9 +203,7 @@ TEST_F(ScreenOrientationDispatcherTest, ErrorForUnknownRequest) {
int request_id = GetFirstLockRequestIdFromSink();
OnMessageReceived(ScreenOrientationMsg_LockError(
- routing_id(),
- request_id + 1,
- blink::WebLockOrientationCallback::ErrorTypeCanceled));
+ routing_id(), request_id + 1, blink::WebLockOrientationErrorCanceled));
EXPECT_FALSE(callback_results.succeeded_);
EXPECT_FALSE(callback_results.failed_);
@@ -261,17 +228,13 @@ TEST_F(ScreenOrientationDispatcherTest, RaceScenario) {
// callback_results1 must be rejected, tested in CancelPending_DoubleLock.
- OnMessageReceived(ScreenOrientationMsg_LockSuccess(
- routing_id(),
- request_id1,
- 0,
- blink::WebScreenOrientationPortraitPrimary));
+ OnMessageReceived(ScreenOrientationMsg_LockSuccess(routing_id(),
+ request_id1));
// First request is still rejected.
EXPECT_FALSE(callback_results1.succeeded_);
EXPECT_TRUE(callback_results1.failed_);
- EXPECT_EQ(blink::WebLockOrientationCallback::ErrorTypeCanceled,
- callback_results1.error_);
+ EXPECT_EQ(blink::WebLockOrientationErrorCanceled, callback_results1.error_);
// Second request is still pending.
EXPECT_FALSE(callback_results2.succeeded_);
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_observer.cc b/chromium/content/renderer/screen_orientation/screen_orientation_observer.cc
new file mode 100644
index 00000000000..8cb05fe3869
--- /dev/null
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_observer.cc
@@ -0,0 +1,33 @@
+// Copyright 2014 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 "content/renderer/screen_orientation/screen_orientation_observer.h"
+
+#include "content/common/screen_orientation_messages.h"
+
+namespace content {
+
+ScreenOrientationObserver::ScreenOrientationObserver() {
+}
+
+ScreenOrientationObserver::~ScreenOrientationObserver() {
+ StopIfObserving();
+}
+
+void ScreenOrientationObserver::Start(
+ blink::WebPlatformEventListener* listener) {
+ // This should never be called with a proper listener.
+ CHECK(listener == 0);
+ PlatformEventObserver<blink::WebPlatformEventListener>::Start(0);
+}
+
+void ScreenOrientationObserver::SendStartMessage() {
+ RenderThread::Get()->Send(new ScreenOrientationHostMsg_StartListening());
+}
+
+void ScreenOrientationObserver::SendStopMessage() {
+ RenderThread::Get()->Send(new ScreenOrientationHostMsg_StopListening());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/screen_orientation/screen_orientation_observer.h b/chromium/content/renderer/screen_orientation/screen_orientation_observer.h
new file mode 100644
index 00000000000..48cca8c08c4
--- /dev/null
+++ b/chromium/content/renderer/screen_orientation/screen_orientation_observer.h
@@ -0,0 +1,32 @@
+// Copyright 2014 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 "content/public/renderer/platform_event_observer.h"
+
+namespace content {
+
+// ScreenOrientationObserver is a helper class implementing the
+// PlatformEventObserver template with blink::WebPlatformEventListener, which is
+// a pure virtual class because it doesn't expect listeners.
+// It is implemented on top of PlatformEventObserver to make sure it follows a
+// common code path even though it only uses part of this code path: it is not
+// expected to receive messages back but should send messages to start/stop
+// listening.
+// The intent of this class is to make sure that platforms that can't listen for
+// display rotations at a marginal cost can be told when to actually do it.
+class ScreenOrientationObserver
+ : public PlatformEventObserver<blink::WebPlatformEventListener> {
+ public:
+ ScreenOrientationObserver();
+ ~ScreenOrientationObserver() override;
+
+ // Overriding this method just to make sure |listener| is always null.
+ void Start(blink::WebPlatformEventListener* listener) override;
+
+ protected:
+ void SendStartMessage() override;
+ void SendStopMessage() override;
+};
+
+}; // namespace content
diff --git a/chromium/content/renderer/service_worker/OWNERS b/chromium/content/renderer/service_worker/OWNERS
index ed6fb7661c0..c84704de993 100644
--- a/chromium/content/renderer/service_worker/OWNERS
+++ b/chromium/content/renderer/service_worker/OWNERS
@@ -1,6 +1,7 @@
michaeln@chromium.org
falken@chromium.org
horo@chromium.org
+nhiroki@chromium.org
# may not be available
kinuko@chromium.org
diff --git a/chromium/content/renderer/service_worker/embedded_worker_context_client.cc b/chromium/content/renderer/service_worker/embedded_worker_context_client.cc
index ea4072db2a5..010ecc71bfd 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_context_client.cc
@@ -4,6 +4,10 @@
#include "content/renderer/service_worker/embedded_worker_context_client.h"
+#include <map>
+#include <string>
+
+#include "base/debug/trace_event.h"
#include "base/lazy_instance.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/pickle.h"
@@ -32,6 +36,8 @@ namespace content {
namespace {
+const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
+
// For now client must be a per-thread instance.
// TODO(kinuko): This needs to be refactored when we start using thread pool
// or having multiple clients per one thread.
@@ -96,6 +102,14 @@ EmbeddedWorkerContextClient::EmbeddedWorkerContextClient(
sender_(ChildThread::current()->thread_safe_sender()),
main_thread_proxy_(base::MessageLoopProxy::current()),
weak_factory_(this) {
+ TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
+ "EmbeddedWorkerContextClient::StartingWorkerContext",
+ this);
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "ServiceWorker",
+ "EmbeddedWorkerContextClient::StartingWorkerContext",
+ this,
+ "PrepareWorker");
}
EmbeddedWorkerContextClient::~EmbeddedWorkerContextClient() {
@@ -120,12 +134,25 @@ blink::WebURL EmbeddedWorkerContextClient::scope() const {
return service_worker_scope_;
}
+blink::WebServiceWorkerCacheStorage*
+ EmbeddedWorkerContextClient::cacheStorage() {
+ return script_context_->cache_storage();
+}
+
+void EmbeddedWorkerContextClient::didPauseAfterDownload() {
+ Send(new EmbeddedWorkerHostMsg_DidPauseAfterDownload(embedded_worker_id_));
+}
+
void EmbeddedWorkerContextClient::getClients(
blink::WebServiceWorkerClientsCallbacks* callbacks) {
DCHECK(script_context_);
script_context_->GetClientDocuments(callbacks);
}
+void EmbeddedWorkerContextClient::workerReadyForInspection() {
+ Send(new EmbeddedWorkerHostMsg_WorkerReadyForInspection(embedded_worker_id_));
+}
+
void EmbeddedWorkerContextClient::workerContextFailedToStart() {
DCHECK(main_thread_proxy_->RunsTasksOnCurrentThread());
DCHECK(!script_context_);
@@ -138,7 +165,7 @@ void EmbeddedWorkerContextClient::workerContextFailedToStart() {
void EmbeddedWorkerContextClient::workerContextStarted(
blink::WebServiceWorkerContextProxy* proxy) {
- DCHECK(!worker_task_runner_);
+ DCHECK(!worker_task_runner_.get());
worker_task_runner_ = new WorkerThreadTaskRunner(
WorkerTaskRunner::Instance()->CurrentWorkerId());
DCHECK_NE(0, WorkerTaskRunner::Instance()->CurrentWorkerId());
@@ -149,7 +176,9 @@ void EmbeddedWorkerContextClient::workerContextStarted(
g_worker_client_tls.Pointer()->Set(this);
script_context_.reset(new ServiceWorkerScriptContext(this, proxy));
- Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(embedded_worker_id_));
+ Send(new EmbeddedWorkerHostMsg_WorkerScriptLoaded(
+ embedded_worker_id_,
+ WorkerTaskRunner::Instance()->CurrentWorkerId()));
// Schedule a task to send back WorkerStarted asynchronously,
// so that at the time we send it we can be sure that the worker
@@ -158,6 +187,16 @@ void EmbeddedWorkerContextClient::workerContextStarted(
FROM_HERE,
base::Bind(&EmbeddedWorkerContextClient::SendWorkerStarted,
weak_factory_.GetWeakPtr()));
+ TRACE_EVENT_ASYNC_STEP_INTO0(
+ "ServiceWorker",
+ "EmbeddedWorkerContextClient::StartingWorkerContext",
+ this,
+ "ExecuteScript");
+}
+
+void EmbeddedWorkerContextClient::didEvaluateWorkerScript(bool success) {
+ Send(new EmbeddedWorkerHostMsg_WorkerScriptEvaluated(
+ embedded_worker_id_, success));
}
void EmbeddedWorkerContextClient::willDestroyWorkerContext() {
@@ -211,8 +250,20 @@ void EmbeddedWorkerContextClient::reportConsoleMessage(
void EmbeddedWorkerContextClient::dispatchDevToolsMessage(
const blink::WebString& message) {
- sender_->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
- worker_devtools_agent_route_id_, message.utf8()));
+ std::string msg(message.utf8());
+
+ if (msg.length() < kMaxMessageChunkSize) {
+ sender_->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
+ worker_devtools_agent_route_id_, msg, msg.size()));
+ return;
+ }
+
+ for (size_t pos = 0; pos < msg.length(); pos += kMaxMessageChunkSize) {
+ sender_->Send(new DevToolsClientMsg_DispatchOnInspectorFrontend(
+ worker_devtools_agent_route_id_,
+ msg.substr(pos, kMaxMessageChunkSize),
+ pos ? 0 : msg.size()));
+ }
}
void EmbeddedWorkerContextClient::saveDevToolsAgentState(
@@ -247,7 +298,7 @@ void EmbeddedWorkerContextClient::didHandleFetchEvent(
int request_id,
const blink::WebServiceWorkerResponse& web_response) {
DCHECK(script_context_);
- std::map<std::string, std::string> headers;
+ ServiceWorkerHeaderMap headers;
const blink::WebVector<blink::WebString>& header_keys =
web_response.getHeaderKeys();
for (size_t i = 0; i < header_keys.size(); ++i) {
@@ -255,10 +306,13 @@ void EmbeddedWorkerContextClient::didHandleFetchEvent(
headers[base::UTF16ToUTF8(key)] =
base::UTF16ToUTF8(web_response.getHeader(key));
}
- ServiceWorkerResponse response(web_response.status(),
+ ServiceWorkerResponse response(web_response.url(),
+ web_response.status(),
web_response.statusText().utf8(),
+ web_response.responseType(),
headers,
- web_response.blobUUID().utf8());
+ web_response.blobUUID().utf8(),
+ web_response.blobSize());
script_context_->DidHandleFetchEvent(
request_id, SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, response);
}
@@ -311,9 +365,10 @@ void EmbeddedWorkerContextClient::OnMessageToWorker(
void EmbeddedWorkerContextClient::SendWorkerStarted() {
DCHECK(worker_task_runner_->RunsTasksOnCurrentThread());
- Send(new EmbeddedWorkerHostMsg_WorkerStarted(
- WorkerTaskRunner::Instance()->CurrentWorkerId(),
- embedded_worker_id_));
+ TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ "EmbeddedWorkerContextClient::StartingWorkerContext",
+ this);
+ Send(new EmbeddedWorkerHostMsg_WorkerStarted(embedded_worker_id_));
}
} // namespace content
diff --git a/chromium/content/renderer/service_worker/embedded_worker_context_client.h b/chromium/content/renderer/service_worker/embedded_worker_context_client.h
index 7d18ec59668..bc92a341b5d 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_context_client.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_
-#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_CONTEXT_CLIENT_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_CONTEXT_CLIENT_H_
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
@@ -60,15 +60,16 @@ class EmbeddedWorkerContextClient
void Send(IPC::Message* message);
- // TODO(kinuko): Deprecate this.
- void SendReplyToBrowser(int request_id, const IPC::Message& message);
-
// WebServiceWorkerContextClient overrides, some of them are just dispatched
// on to script_context_.
virtual blink::WebURL scope() const;
+ virtual blink::WebServiceWorkerCacheStorage* cacheStorage();
+ virtual void didPauseAfterDownload();
virtual void getClients(blink::WebServiceWorkerClientsCallbacks*);
+ virtual void workerReadyForInspection();
virtual void workerContextFailedToStart();
virtual void workerContextStarted(blink::WebServiceWorkerContextProxy* proxy);
+ virtual void didEvaluateWorkerScript(bool success);
virtual void willDestroyWorkerContext();
virtual void workerContextDestroyed();
virtual void reportException(const blink::WebString& error_message,
@@ -102,9 +103,9 @@ class EmbeddedWorkerContextClient
int embedded_worker_id() const { return embedded_worker_id_; }
base::MessageLoopProxy* main_thread_proxy() const {
- return main_thread_proxy_;
+ return main_thread_proxy_.get();
}
- ThreadSafeSender* thread_safe_sender() { return sender_; }
+ ThreadSafeSender* thread_safe_sender() { return sender_.get(); }
private:
void OnMessageToWorker(int thread_id,
@@ -130,4 +131,4 @@ class EmbeddedWorkerContextClient
} // namespace content
-#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_CLIENT_H_
+#endif // CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_CONTEXT_CLIENT_H_
diff --git a/chromium/content/renderer/service_worker/embedded_worker_context_message_filter.h b/chromium/content/renderer/service_worker/embedded_worker_context_message_filter.h
index 1c618df74f8..366c39f0c75 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_context_message_filter.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_context_message_filter.h
@@ -18,13 +18,14 @@ class EmbeddedWorkerContextMessageFilter : public ChildMessageFilter {
EmbeddedWorkerContextMessageFilter();
protected:
- virtual ~EmbeddedWorkerContextMessageFilter();
+ ~EmbeddedWorkerContextMessageFilter() override;
// ChildMessageFilter implementation:
- virtual base::TaskRunner* OverrideTaskRunnerForMessage(
- const IPC::Message& msg) OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
+ base::TaskRunner* OverrideTaskRunnerForMessage(
+ const IPC::Message& msg) override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+ private:
scoped_refptr<base::MessageLoopProxy> main_thread_loop_proxy_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
diff --git a/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc b/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc
index bb76bafc07f..791a2ca9a9d 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc
@@ -36,20 +36,19 @@ bool EmbeddedWorkerDevToolsAgent::OnMessageReceived(
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
OnDispatchOnInspectorBackend)
- IPC_MESSAGE_HANDLER(DevToolsAgentMsg_ResumeWorkerContext,
- OnResumeWorkerContext)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void EmbeddedWorkerDevToolsAgent::OnAttach(const std::string& host_id) {
- webworker_->attachDevTools();
+ webworker_->attachDevTools(WebString::fromUTF8(host_id));
}
void EmbeddedWorkerDevToolsAgent::OnReattach(const std::string& host_id,
const std::string& state) {
- webworker_->reattachDevTools(WebString::fromUTF8(state));
+ webworker_->reattachDevTools(WebString::fromUTF8(host_id),
+ WebString::fromUTF8(state));
}
void EmbeddedWorkerDevToolsAgent::OnDetach() {
@@ -61,8 +60,4 @@ void EmbeddedWorkerDevToolsAgent::OnDispatchOnInspectorBackend(
webworker_->dispatchDevToolsMessage(WebString::fromUTF8(message));
}
-void EmbeddedWorkerDevToolsAgent::OnResumeWorkerContext() {
- webworker_->resumeWorkerContext();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.h b/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.h
index 79ce73eeac7..97c15824fe9 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.h
@@ -25,16 +25,15 @@ class EmbeddedWorkerDevToolsAgent : public IPC::Listener {
public:
EmbeddedWorkerDevToolsAgent(blink::WebEmbeddedWorker* webworker,
int route_id);
- virtual ~EmbeddedWorkerDevToolsAgent();
+ ~EmbeddedWorkerDevToolsAgent() override;
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
void OnAttach(const std::string& host_id);
void OnReattach(const std::string& host_id, const std::string& state);
void OnDetach();
void OnDispatchOnInspectorBackend(const std::string& message);
- void OnResumeWorkerContext();
blink::WebEmbeddedWorker* webworker_;
int route_id_;
diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
index 15ff76a4145..e62bb2e9ce8 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
@@ -52,6 +52,8 @@ bool EmbeddedWorkerDispatcher::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDispatcher, message)
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorker)
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorker)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
+ OnResumeAfterDownload)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -67,6 +69,7 @@ void EmbeddedWorkerDispatcher::WorkerContextDestroyed(
void EmbeddedWorkerDispatcher::OnStartWorker(
const EmbeddedWorkerMsg_StartWorker_Params& params) {
DCHECK(!workers_.Lookup(params.embedded_worker_id));
+ TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerDispatcher::OnStartWorker");
RenderThread::Get()->EnsureWebKitInitialized();
scoped_ptr<WorkerWrapper> wrapper(
new WorkerWrapper(blink::WebEmbeddedWorker::create(
@@ -82,15 +85,21 @@ void EmbeddedWorkerDispatcher::OnStartWorker(
blink::WebEmbeddedWorkerStartData start_data;
start_data.scriptURL = params.script_url;
start_data.userAgent = base::UTF8ToUTF16(GetContentClient()->GetUserAgent());
- start_data.startMode =
- params.pause_on_start ? blink::WebEmbeddedWorkerStartModePauseOnStart
- : blink::WebEmbeddedWorkerStartModeDontPauseOnStart;
+ start_data.pauseAfterDownloadMode =
+ params.pause_after_download ?
+ blink::WebEmbeddedWorkerStartData::PauseAfterDownload :
+ blink::WebEmbeddedWorkerStartData::DontPauseAfterDownload;
+ start_data.waitForDebuggerMode =
+ params.wait_for_debugger ?
+ blink::WebEmbeddedWorkerStartData::WaitForDebugger :
+ blink::WebEmbeddedWorkerStartData::DontWaitForDebugger;
wrapper->worker()->startWorkerContext(start_data);
workers_.AddWithID(wrapper.release(), params.embedded_worker_id);
}
void EmbeddedWorkerDispatcher::OnStopWorker(int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerDispatcher::OnStopWorker");
WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id);
if (!wrapper) {
LOG(WARNING) << "Got OnStopWorker for nonexistent worker";
@@ -103,4 +112,15 @@ void EmbeddedWorkerDispatcher::OnStopWorker(int embedded_worker_id) {
wrapper->worker()->terminateWorkerContext();
}
+void EmbeddedWorkerDispatcher::OnResumeAfterDownload(int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "EmbeddedWorkerDispatcher::OnResumeAfterDownload");
+ WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id);
+ if (!wrapper) {
+ LOG(WARNING) << "Got OnResumeAfterDownload for nonexistent worker";
+ return;
+ }
+ wrapper->worker()->resumeAfterDownload();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
index 4f3434fb5af..170d282071e 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
-#define CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
#include "base/basictypes.h"
#include "base/id_map.h"
@@ -23,10 +23,10 @@ namespace content {
class EmbeddedWorkerDispatcher : public IPC::Listener {
public:
EmbeddedWorkerDispatcher();
- virtual ~EmbeddedWorkerDispatcher();
+ ~EmbeddedWorkerDispatcher() override;
// IPC::Listener overrides.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void WorkerContextDestroyed(int embedded_worker_id);
@@ -35,6 +35,7 @@ class EmbeddedWorkerDispatcher : public IPC::Listener {
void OnStartWorker(const EmbeddedWorkerMsg_StartWorker_Params& params);
void OnStopWorker(int embedded_worker_id);
+ void OnResumeAfterDownload(int embedded_worker_id);
IDMap<WorkerWrapper, IDMapOwnPointer> workers_;
base::WeakPtrFactory<EmbeddedWorkerDispatcher> weak_factory_;
@@ -44,4 +45,4 @@ class EmbeddedWorkerDispatcher : public IPC::Listener {
} // namespace content
-#endif // CONTENT_CHILD_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
+#endif // CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
diff --git a/chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc b/chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc
new file mode 100644
index 00000000000..2f6e1b2121b
--- /dev/null
+++ b/chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.cc
@@ -0,0 +1,542 @@
+// Copyright 2014 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 "content/renderer/service_worker/service_worker_cache_storage_dispatcher.h"
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/common/service_worker/service_worker_messages.h"
+#include "content/public/renderer/render_thread.h"
+#include "content/renderer/service_worker/service_worker_script_context.h"
+#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerCache.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerResponse.h"
+
+namespace content {
+
+using blink::WebServiceWorkerCacheError;
+using blink::WebServiceWorkerRequest;
+
+namespace {
+
+class HeaderVisitor : public blink::WebHTTPHeaderVisitor {
+ public:
+ HeaderVisitor(ServiceWorkerHeaderMap* headers) : headers_(headers) {}
+ virtual ~HeaderVisitor() {}
+
+ virtual void visitHeader(const blink::WebString& name,
+ const blink::WebString& value) {
+ headers_->insert(ServiceWorkerHeaderMap::value_type(
+ base::UTF16ToASCII(name), base::UTF16ToASCII(value)));
+ }
+
+ private:
+ ServiceWorkerHeaderMap* headers_;
+};
+
+scoped_ptr<HeaderVisitor> MakeHeaderVisitor(ServiceWorkerHeaderMap* headers) {
+ return scoped_ptr<HeaderVisitor>(new HeaderVisitor(headers)).Pass();
+}
+
+ServiceWorkerFetchRequest FetchRequestFromWebRequest(
+ const blink::WebServiceWorkerRequest& web_request) {
+ ServiceWorkerHeaderMap headers;
+ web_request.visitHTTPHeaderFields(MakeHeaderVisitor(&headers).get());
+
+ return ServiceWorkerFetchRequest(web_request.url(),
+ base::UTF16ToASCII(web_request.method()),
+ headers, web_request.referrerUrl(),
+ web_request.isReload());
+}
+
+void PopulateWebRequestFromFetchRequest(
+ const ServiceWorkerFetchRequest& request,
+ blink::WebServiceWorkerRequest* web_request) {
+ web_request->setURL(request.url);
+ web_request->setMethod(base::ASCIIToUTF16(request.method));
+ for (ServiceWorkerHeaderMap::const_iterator i = request.headers.begin(),
+ end = request.headers.end();
+ i != end; ++i) {
+ web_request->setHeader(base::ASCIIToUTF16(i->first),
+ base::ASCIIToUTF16(i->second));
+ }
+ web_request->setReferrer(base::ASCIIToUTF16(request.referrer.spec()),
+ blink::WebReferrerPolicy::WebReferrerPolicyNever);
+ web_request->setIsReload(request.is_reload);
+}
+
+blink::WebVector<blink::WebServiceWorkerRequest> WebRequestsFromRequests(
+ const std::vector<ServiceWorkerFetchRequest>& requests) {
+ blink::WebVector<blink::WebServiceWorkerRequest>
+ web_requests(requests.size());
+ for (size_t i = 0; i < requests.size(); ++i)
+ PopulateWebRequestFromFetchRequest(requests[i], &(web_requests[i]));
+ return web_requests;
+}
+
+ServiceWorkerResponse ResponseFromWebResponse(
+ const blink::WebServiceWorkerResponse& web_response) {
+ ServiceWorkerHeaderMap headers;
+ web_response.visitHTTPHeaderFields(MakeHeaderVisitor(&headers).get());
+
+ return ServiceWorkerResponse(web_response.url(),
+ web_response.status(),
+ base::UTF16ToASCII(web_response.statusText()),
+ web_response.responseType(),
+ headers,
+ base::UTF16ToASCII(web_response.blobUUID()),
+ web_response.blobSize());
+}
+
+ServiceWorkerCacheQueryParams QueryParamsFromWebQueryParams(
+ const blink::WebServiceWorkerCache::QueryParams& web_query_params) {
+ ServiceWorkerCacheQueryParams query_params;
+ query_params.ignore_search = web_query_params.ignoreSearch;
+ query_params.ignore_method = web_query_params.ignoreMethod;
+ query_params.ignore_vary = web_query_params.ignoreVary;
+ query_params.prefix_match = web_query_params.prefixMatch;
+
+ return query_params;
+}
+
+ServiceWorkerCacheOperationType CacheOperationTypeFromWebCacheOperationType(
+ blink::WebServiceWorkerCache::OperationType operation_type) {
+ switch (operation_type) {
+ case blink::WebServiceWorkerCache::OperationTypePut:
+ return SERVICE_WORKER_CACHE_OPERATION_TYPE_PUT;
+ case blink::WebServiceWorkerCache::OperationTypeDelete:
+ return SERVICE_WORKER_CACHE_OPERATION_TYPE_DELETE;
+ default:
+ return SERVICE_WORKER_CACHE_OPERATION_TYPE_UNDEFINED;
+ }
+}
+
+ServiceWorkerBatchOperation BatchOperationFromWebBatchOperation(
+ const blink::WebServiceWorkerCache::BatchOperation& web_operation) {
+ ServiceWorkerBatchOperation operation;
+ operation.operation_type =
+ CacheOperationTypeFromWebCacheOperationType(web_operation.operationType);
+ operation.request = FetchRequestFromWebRequest(web_operation.request);
+ operation.response = ResponseFromWebResponse(web_operation.response);
+ operation.match_params =
+ QueryParamsFromWebQueryParams(web_operation.matchParams);
+ return operation;
+}
+
+template<typename T>
+void ClearCallbacksMapWithErrors(T* callbacks_map) {
+ typename T::iterator iter(callbacks_map);
+ while (!iter.IsAtEnd()) {
+ blink::WebServiceWorkerCacheError reason =
+ blink::WebServiceWorkerCacheErrorNotFound;
+ iter.GetCurrentValue()->onError(&reason);
+ callbacks_map->Remove(iter.GetCurrentKey());
+ iter.Advance();
+ }
+}
+
+} // namespace
+
+// The WebCache object is the Chromium side implementation of the Blink
+// WebServiceWorkerCache API. Most of its methods delegate directly to the
+// ServiceWorkerStorage object, which is able to assign unique IDs as well
+// as have a lifetime longer than the requests.
+class ServiceWorkerCacheStorageDispatcher::WebCache
+ : public blink::WebServiceWorkerCache {
+ public:
+ WebCache(base::WeakPtr<ServiceWorkerCacheStorageDispatcher> dispatcher,
+ int cache_id)
+ : dispatcher_(dispatcher),
+ cache_id_(cache_id) {}
+
+ virtual ~WebCache() {
+ if (dispatcher_)
+ dispatcher_->OnWebCacheDestruction(cache_id_);
+ }
+
+ // From blink::WebServiceWorkerCache:
+ virtual void dispatchMatch(CacheMatchCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest& request,
+ const QueryParams& query_params) {
+ if (!dispatcher_)
+ return;
+ dispatcher_->dispatchMatchForCache(cache_id_, callbacks, request,
+ query_params);
+ }
+ virtual void dispatchMatchAll(CacheWithResponsesCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest& request,
+ const QueryParams& query_params) {
+ if (!dispatcher_)
+ return;
+ dispatcher_->dispatchMatchAllForCache(cache_id_, callbacks, request,
+ query_params);
+ }
+ virtual void dispatchKeys(CacheWithRequestsCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest* request,
+ const QueryParams& query_params) {
+ if (!dispatcher_)
+ return;
+ dispatcher_->dispatchKeysForCache(cache_id_, callbacks, request,
+ query_params);
+ }
+ virtual void dispatchBatch(
+ CacheWithResponsesCallbacks* callbacks,
+ const blink::WebVector<BatchOperation>& batch_operations) {
+ if (!dispatcher_)
+ return;
+ dispatcher_->dispatchBatchForCache(cache_id_, callbacks, batch_operations);
+ }
+
+ private:
+ const base::WeakPtr<ServiceWorkerCacheStorageDispatcher> dispatcher_;
+ const int cache_id_;
+};
+
+ServiceWorkerCacheStorageDispatcher::ServiceWorkerCacheStorageDispatcher(
+ ServiceWorkerScriptContext* script_context)
+ : script_context_(script_context),
+ weak_factory_(this) {}
+
+ServiceWorkerCacheStorageDispatcher::~ServiceWorkerCacheStorageDispatcher() {
+ ClearCallbacksMapWithErrors(&has_callbacks_);
+ ClearCallbacksMapWithErrors(&open_callbacks_);
+ ClearCallbacksMapWithErrors(&delete_callbacks_);
+ ClearCallbacksMapWithErrors(&keys_callbacks_);
+
+ ClearCallbacksMapWithErrors(&cache_match_callbacks_);
+ ClearCallbacksMapWithErrors(&cache_match_all_callbacks_);
+ ClearCallbacksMapWithErrors(&cache_keys_callbacks_);
+ ClearCallbacksMapWithErrors(&cache_batch_callbacks_);
+}
+
+bool ServiceWorkerCacheStorageDispatcher::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(ServiceWorkerCacheStorageDispatcher, message)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageHasSuccess,
+ OnCacheStorageHasSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageOpenSuccess,
+ OnCacheStorageOpenSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageDeleteSuccess,
+ OnCacheStorageDeleteSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageKeysSuccess,
+ OnCacheStorageKeysSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageHasError,
+ OnCacheStorageHasError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageOpenError,
+ OnCacheStorageOpenError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageDeleteError,
+ OnCacheStorageDeleteError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheStorageKeysError,
+ OnCacheStorageKeysError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchSuccess,
+ OnCacheMatchSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchAllSuccess,
+ OnCacheMatchAllSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheKeysSuccess,
+ OnCacheKeysSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheBatchSuccess,
+ OnCacheBatchSuccess)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchError,
+ OnCacheMatchError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheMatchAllError,
+ OnCacheMatchAllError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheKeysError,
+ OnCacheKeysError)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CacheBatchError,
+ OnCacheBatchError)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageHasSuccess(
+ int request_id) {
+ CacheStorageCallbacks* callbacks = has_callbacks_.Lookup(request_id);
+ callbacks->onSuccess();
+ has_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageOpenSuccess(
+ int request_id,
+ int cache_id) {
+ WebCache* web_cache = new WebCache(weak_factory_.GetWeakPtr(), cache_id);
+ web_caches_.AddWithID(web_cache, cache_id);
+ CacheStorageWithCacheCallbacks* callbacks =
+ open_callbacks_.Lookup(request_id);
+ callbacks->onSuccess(web_cache);
+ open_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageDeleteSuccess(
+ int request_id) {
+ CacheStorageCallbacks* callbacks = delete_callbacks_.Lookup(request_id);
+ callbacks->onSuccess();
+ delete_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageKeysSuccess(
+ int request_id,
+ const std::vector<base::string16>& keys) {
+ CacheStorageKeysCallbacks* callbacks = keys_callbacks_.Lookup(request_id);
+ blink::WebVector<blink::WebString> webKeys(keys.size());
+ for (size_t i = 0; i < keys.size(); ++i)
+ webKeys[i] = keys[i];
+
+ callbacks->onSuccess(&webKeys);
+ keys_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageHasError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ CacheStorageCallbacks* callbacks = has_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ has_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageOpenError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ CacheStorageWithCacheCallbacks* callbacks =
+ open_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ open_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageDeleteError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ CacheStorageCallbacks* callbacks = delete_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ delete_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheStorageKeysError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ CacheStorageKeysCallbacks* callbacks = keys_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ keys_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheMatchSuccess(
+ int request_id,
+ const ServiceWorkerResponse& response) {
+ blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks =
+ cache_match_callbacks_.Lookup(request_id);
+
+ blink::WebServiceWorkerResponse web_response;
+ PopulateWebResponseFromResponse(response, &web_response);
+ callbacks->onSuccess(&web_response);
+ cache_match_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheMatchAllSuccess(
+ int request_id,
+ const std::vector<ServiceWorkerResponse>& responses) {
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
+ cache_match_all_callbacks_.Lookup(request_id);
+
+ blink::WebVector<blink::WebServiceWorkerResponse>
+ web_responses = WebResponsesFromResponses(responses);
+ callbacks->onSuccess(&web_responses);
+ cache_match_all_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheKeysSuccess(
+
+ int request_id,
+ const std::vector<ServiceWorkerFetchRequest>& requests) {
+ blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks =
+ cache_keys_callbacks_.Lookup(request_id);
+
+ blink::WebVector<blink::WebServiceWorkerRequest>
+ web_requests = WebRequestsFromRequests(requests);
+ callbacks->onSuccess(&web_requests);
+ cache_keys_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheBatchSuccess(
+ int request_id,
+ const std::vector<ServiceWorkerResponse>& responses) {
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
+ cache_batch_callbacks_.Lookup(request_id);
+
+ blink::WebVector<blink::WebServiceWorkerResponse>
+ web_responses = WebResponsesFromResponses(responses);
+ callbacks->onSuccess(&web_responses);
+ cache_batch_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheMatchError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks =
+ cache_match_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ cache_match_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheMatchAllError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
+ cache_match_all_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ cache_match_all_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheKeysError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks =
+ cache_keys_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ cache_keys_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnCacheBatchError(
+ int request_id,
+ blink::WebServiceWorkerCacheError reason) {
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks =
+ cache_batch_callbacks_.Lookup(request_id);
+ callbacks->onError(&reason);
+ cache_batch_callbacks_.Remove(request_id);
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchHas(
+ CacheStorageCallbacks* callbacks,
+ const blink::WebString& cacheName) {
+ int request_id = has_callbacks_.Add(callbacks);
+ script_context_->Send(new ServiceWorkerHostMsg_CacheStorageHas(
+ script_context_->GetRoutingID(), request_id, cacheName));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchOpen(
+ CacheStorageWithCacheCallbacks* callbacks,
+ const blink::WebString& cacheName) {
+ int request_id = open_callbacks_.Add(callbacks);
+ script_context_->Send(new ServiceWorkerHostMsg_CacheStorageOpen(
+ script_context_->GetRoutingID(), request_id, cacheName));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchDelete(
+ CacheStorageCallbacks* callbacks,
+ const blink::WebString& cacheName) {
+ int request_id = delete_callbacks_.Add(callbacks);
+ script_context_->Send(new ServiceWorkerHostMsg_CacheStorageDelete(
+ script_context_->GetRoutingID(), request_id, cacheName));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchKeys(
+ CacheStorageKeysCallbacks* callbacks) {
+ int request_id = keys_callbacks_.Add(callbacks);
+ script_context_->Send(new ServiceWorkerHostMsg_CacheStorageKeys(
+ script_context_->GetRoutingID(), request_id));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchMatchForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest& request,
+ const blink::WebServiceWorkerCache::QueryParams& query_params) {
+ int request_id = cache_match_callbacks_.Add(callbacks);
+
+ script_context_->Send(new ServiceWorkerHostMsg_CacheMatch(
+ script_context_->GetRoutingID(), request_id, cache_id,
+ FetchRequestFromWebRequest(request),
+ QueryParamsFromWebQueryParams(query_params)));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchMatchAllForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest& request,
+ const blink::WebServiceWorkerCache::QueryParams& query_params) {
+ int request_id = cache_match_all_callbacks_.Add(callbacks);
+
+ script_context_->Send(new ServiceWorkerHostMsg_CacheMatchAll(
+ script_context_->GetRoutingID(), request_id, cache_id,
+ FetchRequestFromWebRequest(request),
+ QueryParamsFromWebQueryParams(query_params)));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchKeysForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest* request,
+ const blink::WebServiceWorkerCache::QueryParams& query_params) {
+ int request_id = cache_keys_callbacks_.Add(callbacks);
+
+ script_context_->Send(new ServiceWorkerHostMsg_CacheKeys(
+ script_context_->GetRoutingID(), request_id, cache_id,
+ request ? FetchRequestFromWebRequest(*request)
+ : ServiceWorkerFetchRequest(),
+ QueryParamsFromWebQueryParams(query_params)));
+}
+
+void ServiceWorkerCacheStorageDispatcher::dispatchBatchForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks,
+ const blink::WebVector<
+ blink::WebServiceWorkerCache::BatchOperation>& web_operations) {
+ int request_id = cache_batch_callbacks_.Add(callbacks);
+
+ std::vector<ServiceWorkerBatchOperation> operations;
+ operations.reserve(web_operations.size());
+ for (size_t i = 0; i < web_operations.size(); ++i) {
+ operations.push_back(
+ BatchOperationFromWebBatchOperation(web_operations[i]));
+ }
+
+ script_context_->Send(new ServiceWorkerHostMsg_CacheBatch(
+ script_context_->GetRoutingID(), request_id, cache_id, operations));
+}
+
+void ServiceWorkerCacheStorageDispatcher::OnWebCacheDestruction(int cache_id) {
+ web_caches_.Remove(cache_id);
+ script_context_->Send(new ServiceWorkerHostMsg_CacheClosed(
+ script_context_->GetRoutingID(), cache_id));
+}
+
+void ServiceWorkerCacheStorageDispatcher::PopulateWebResponseFromResponse(
+ const ServiceWorkerResponse& response,
+ blink::WebServiceWorkerResponse* web_response) {
+ web_response->setURL(response.url);
+ web_response->setStatus(response.status_code);
+ web_response->setStatusText(base::ASCIIToUTF16(response.status_text));
+ web_response->setResponseType(response.response_type);
+
+ for (const auto& i : response.headers) {
+ web_response->setHeader(base::ASCIIToUTF16(i.first),
+ base::ASCIIToUTF16(i.second));
+ }
+
+ if (!response.blob_uuid.empty()) {
+ web_response->setBlob(blink::WebString::fromUTF8(response.blob_uuid),
+ response.blob_size);
+ // Let the host know that it can release its reference to the blob.
+ script_context_->Send(new ServiceWorkerHostMsg_BlobDataHandled(
+ script_context_->GetRoutingID(), response.blob_uuid));
+ }
+}
+
+blink::WebVector<blink::WebServiceWorkerResponse>
+ServiceWorkerCacheStorageDispatcher::WebResponsesFromResponses(
+ const std::vector<ServiceWorkerResponse>& responses) {
+ blink::WebVector<blink::WebServiceWorkerResponse> web_responses(
+ responses.size());
+ for (size_t i = 0; i < responses.size(); ++i)
+ PopulateWebResponseFromResponse(responses[i], &(web_responses[i]));
+ return web_responses;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.h b/chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.h
new file mode 100644
index 00000000000..41aa8170522
--- /dev/null
+++ b/chromium/content/renderer/service_worker/service_worker_cache_storage_dispatcher.h
@@ -0,0 +1,159 @@
+// Copyright 2014 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 CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_DISPATCHER_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_DISPATCHER_H_
+
+#include <vector>
+
+#include "base/id_map.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "content/public/renderer/render_process_observer.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerCache.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerCacheStorage.h"
+
+namespace content {
+
+struct ServiceWorkerFetchRequest;
+class ServiceWorkerScriptContext;
+struct ServiceWorkerResponse;
+
+// There is one ServiceWorkerCacheStorageDispatcher per
+// ServiceWorkerScriptContext. It handles CacheStorage operations with messages
+// to/from the browser, creating Cache objects (for which it also handles
+// messages) as it goes.
+
+class ServiceWorkerCacheStorageDispatcher
+ : public blink::WebServiceWorkerCacheStorage {
+ public:
+ explicit ServiceWorkerCacheStorageDispatcher(
+ ServiceWorkerScriptContext* script_context);
+ virtual ~ServiceWorkerCacheStorageDispatcher();
+
+ // ServiceWorkerScriptContext calls our OnMessageReceived directly.
+ bool OnMessageReceived(const IPC::Message& message);
+
+ // Message handlers for CacheStorage messages from the browser process.
+ void OnCacheStorageHasSuccess(int request_id);
+ void OnCacheStorageOpenSuccess(int request_id, int cache_id);
+ void OnCacheStorageDeleteSuccess(int request_id);
+ void OnCacheStorageKeysSuccess(int request_id,
+ const std::vector<base::string16>& keys);
+
+ void OnCacheStorageHasError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+ void OnCacheStorageOpenError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+ void OnCacheStorageDeleteError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+ void OnCacheStorageKeysError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+
+ // Message handlers for Cache messages from the browser process.
+ void OnCacheMatchSuccess(int request_id,
+ const ServiceWorkerResponse& response);
+ void OnCacheMatchAllSuccess(
+ int request_id,
+ const std::vector<ServiceWorkerResponse>& response);
+ void OnCacheKeysSuccess(
+ int request_id,
+ const std::vector<ServiceWorkerFetchRequest>& response);
+ void OnCacheBatchSuccess(int request_id,
+ const std::vector<ServiceWorkerResponse>& response);
+
+ void OnCacheMatchError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+ void OnCacheMatchAllError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+ void OnCacheKeysError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+ void OnCacheBatchError(int request_id,
+ blink::WebServiceWorkerCacheError reason);
+
+ // From WebServiceWorkerCacheStorage:
+ virtual void dispatchHas(CacheStorageCallbacks* callbacks,
+ const blink::WebString& cacheName);
+ virtual void dispatchOpen(CacheStorageWithCacheCallbacks* callbacks,
+ const blink::WebString& cacheName);
+ virtual void dispatchDelete(CacheStorageCallbacks* callbacks,
+ const blink::WebString& cacheName);
+ virtual void dispatchKeys(CacheStorageKeysCallbacks* callbacks);
+
+ // These methods are used by WebCache to forward events to the browser
+ // process.
+ void dispatchMatchForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheMatchCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest& request,
+ const blink::WebServiceWorkerCache::QueryParams& query_params);
+ void dispatchMatchAllForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest& request,
+ const blink::WebServiceWorkerCache::QueryParams& query_params);
+ void dispatchKeysForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheWithRequestsCallbacks* callbacks,
+ const blink::WebServiceWorkerRequest* request,
+ const blink::WebServiceWorkerCache::QueryParams& query_params);
+ void dispatchBatchForCache(
+ int cache_id,
+ blink::WebServiceWorkerCache::CacheWithResponsesCallbacks* callbacks,
+ const blink::WebVector<blink::WebServiceWorkerCache::BatchOperation>&
+ batch_operations);
+
+ void OnWebCacheDestruction(int cache_id);
+
+ private:
+ class WebCache;
+
+ typedef IDMap<CacheStorageCallbacks, IDMapOwnPointer> CallbacksMap;
+ typedef IDMap<CacheStorageWithCacheCallbacks, IDMapOwnPointer>
+ WithCacheCallbacksMap;
+ typedef IDMap<CacheStorageKeysCallbacks, IDMapOwnPointer>
+ KeysCallbacksMap;
+
+ typedef IDMap<blink::WebServiceWorkerCache::CacheMatchCallbacks,
+ IDMapOwnPointer> MatchCallbacksMap;
+ typedef IDMap<blink::WebServiceWorkerCache::CacheWithResponsesCallbacks,
+ IDMapOwnPointer> WithResponsesCallbacksMap;
+ typedef IDMap<blink::WebServiceWorkerCache::CacheWithRequestsCallbacks,
+ IDMapOwnPointer> WithRequestsCallbacksMap;
+
+ void PopulateWebResponseFromResponse(
+ const ServiceWorkerResponse& response,
+ blink::WebServiceWorkerResponse* web_response);
+
+ blink::WebVector<blink::WebServiceWorkerResponse> WebResponsesFromResponses(
+ const std::vector<ServiceWorkerResponse>& responses);
+
+ // Not owned. The script context containing this object.
+ ServiceWorkerScriptContext* script_context_;
+
+ CallbacksMap has_callbacks_;
+ WithCacheCallbacksMap open_callbacks_;
+ CallbacksMap delete_callbacks_;
+ KeysCallbacksMap keys_callbacks_;
+
+ // The individual caches created under this CacheStorage object.
+ IDMap<WebCache, IDMapExternalPointer> web_caches_;
+
+ // These ID maps are held in the CacheStorage object rather than the Cache
+ // object to ensure that the IDs are unique.
+ MatchCallbacksMap cache_match_callbacks_;
+ WithResponsesCallbacksMap cache_match_all_callbacks_;
+ WithRequestsCallbacksMap cache_keys_callbacks_;
+ WithResponsesCallbacksMap cache_batch_callbacks_;
+
+ base::WeakPtrFactory<ServiceWorkerCacheStorageDispatcher> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheStorageDispatcher);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_CACHE_STORAGE_DISPATCHER_H_
diff --git a/chromium/content/renderer/service_worker/service_worker_script_context.cc b/chromium/content/renderer/service_worker/service_worker_script_context.cc
index ad0534134ba..9aa65d5661b 100644
--- a/chromium/content/renderer/service_worker/service_worker_script_context.cc
+++ b/chromium/content/renderer/service_worker/service_worker_script_context.cc
@@ -4,12 +4,15 @@
#include "content/renderer/service_worker/service_worker_script_context.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/renderer/service_worker/embedded_worker_context_client.h"
#include "ipc/ipc_message.h"
+#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerRequest.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -31,12 +34,35 @@ void SendPostMessageToDocumentOnMainThread(
WebMessagePortChannelImpl::ExtractMessagePortIDs(channels.release())));
}
+blink::WebURLRequest::FetchRequestMode GetBlinkFetchRequestMode(
+ FetchRequestMode mode) {
+ return static_cast<blink::WebURLRequest::FetchRequestMode>(mode);
+}
+
+blink::WebURLRequest::FetchCredentialsMode GetBlinkFetchCredentialsMode(
+ FetchCredentialsMode credentials_mode) {
+ return static_cast<blink::WebURLRequest::FetchCredentialsMode>(
+ credentials_mode);
+}
+
+blink::WebURLRequest::RequestContext GetBlinkRequestContext(
+ RequestContextType request_context_type) {
+ return static_cast<blink::WebURLRequest::RequestContext>(
+ request_context_type);
+}
+
+blink::WebURLRequest::FrameType GetBlinkFrameType(
+ RequestContextFrameType frame_type) {
+ return static_cast<blink::WebURLRequest::FrameType>(frame_type);
+}
+
} // namespace
ServiceWorkerScriptContext::ServiceWorkerScriptContext(
EmbeddedWorkerContextClient* embedded_context,
blink::WebServiceWorkerContextProxy* proxy)
- : embedded_context_(embedded_context),
+ : cache_storage_dispatcher_(new ServiceWorkerCacheStorageDispatcher(this)),
+ embedded_context_(embedded_context),
proxy_(proxy) {
}
@@ -51,17 +77,29 @@ void ServiceWorkerScriptContext::OnMessageReceived(
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SyncEvent, OnSyncEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEvent)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GeofencingEvent, OnGeofencingEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker, OnPostMessage)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClientDocuments,
OnDidGetClientDocuments)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
+
+ // TODO(gavinp): Would it be preferable to put an AddListener() method to
+ // EmbeddedWorkerContextClient?
+ if (!handled)
+ handled = cache_storage_dispatcher_->OnMessageReceived(message);
+
DCHECK(handled);
}
void ServiceWorkerScriptContext::DidHandleActivateEvent(
int request_id,
blink::WebServiceWorkerEventResult result) {
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.ActivateEventExecutionTime",
+ base::TimeTicks::Now() - activate_start_timings_[request_id]);
+ activate_start_timings_.erase(request_id);
+
Send(new ServiceWorkerHostMsg_ActivateEventFinished(
GetRoutingID(), request_id, result));
}
@@ -69,6 +107,11 @@ void ServiceWorkerScriptContext::DidHandleActivateEvent(
void ServiceWorkerScriptContext::DidHandleInstallEvent(
int request_id,
blink::WebServiceWorkerEventResult result) {
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.InstallEventExecutionTime",
+ base::TimeTicks::Now() - install_start_timings_[request_id]);
+ install_start_timings_.erase(request_id);
+
Send(new ServiceWorkerHostMsg_InstallEventFinished(
GetRoutingID(), request_id, result));
}
@@ -77,6 +120,11 @@ void ServiceWorkerScriptContext::DidHandleFetchEvent(
int request_id,
ServiceWorkerFetchEventResult result,
const ServiceWorkerResponse& response) {
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.FetchEventExecutionTime",
+ base::TimeTicks::Now() - fetch_start_timings_[request_id]);
+ fetch_start_timings_.erase(request_id);
+
Send(new ServiceWorkerHostMsg_FetchEventFinished(
GetRoutingID(), request_id, result, response));
}
@@ -113,12 +161,22 @@ void ServiceWorkerScriptContext::Send(IPC::Message* message) {
embedded_context_->Send(message);
}
+int ServiceWorkerScriptContext::GetRoutingID() const {
+ return embedded_context_->embedded_worker_id();
+}
+
void ServiceWorkerScriptContext::OnActivateEvent(int request_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnActivateEvent");
+ activate_start_timings_[request_id] = base::TimeTicks::Now();
proxy_->dispatchActivateEvent(request_id);
}
void ServiceWorkerScriptContext::OnInstallEvent(int request_id,
int active_version_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnInstallEvent");
+ install_start_timings_[request_id] = base::TimeTicks::Now();
proxy_->dispatchInstallEvent(request_id);
}
@@ -126,33 +184,67 @@ void ServiceWorkerScriptContext::OnFetchEvent(
int request_id,
const ServiceWorkerFetchRequest& request) {
blink::WebServiceWorkerRequest webRequest;
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnFetchEvent");
webRequest.setURL(blink::WebURL(request.url));
webRequest.setMethod(blink::WebString::fromUTF8(request.method));
- for (std::map<std::string, std::string>::const_iterator it =
- request.headers.begin();
+ for (ServiceWorkerHeaderMap::const_iterator it = request.headers.begin();
it != request.headers.end();
++it) {
webRequest.setHeader(blink::WebString::fromUTF8(it->first),
blink::WebString::fromUTF8(it->second));
}
+ if (!request.blob_uuid.empty()) {
+ webRequest.setBlob(blink::WebString::fromUTF8(request.blob_uuid),
+ request.blob_size);
+ }
+ webRequest.setReferrer(blink::WebString::fromUTF8(request.referrer.spec()),
+ blink::WebReferrerPolicyDefault);
+ webRequest.setMode(GetBlinkFetchRequestMode(request.mode));
+ webRequest.setCredentialsMode(
+ GetBlinkFetchCredentialsMode(request.credentials_mode));
+ webRequest.setRequestContext(
+ GetBlinkRequestContext(request.request_context_type));
+ webRequest.setFrameType(GetBlinkFrameType(request.frame_type));
+ webRequest.setIsReload(request.is_reload);
+ fetch_start_timings_[request_id] = base::TimeTicks::Now();
proxy_->dispatchFetchEvent(request_id, webRequest);
}
void ServiceWorkerScriptContext::OnSyncEvent(int request_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnSyncEvent");
proxy_->dispatchSyncEvent(request_id);
}
void ServiceWorkerScriptContext::OnPushEvent(int request_id,
const std::string& data) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnPushEvent");
proxy_->dispatchPushEvent(request_id, blink::WebString::fromUTF8(data));
Send(new ServiceWorkerHostMsg_PushEventFinished(
GetRoutingID(), request_id));
}
+void ServiceWorkerScriptContext::OnGeofencingEvent(
+ int request_id,
+ blink::WebGeofencingEventType event_type,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnGeofencingEvent");
+ proxy_->dispatchGeofencingEvent(
+ request_id, event_type, blink::WebString::fromUTF8(region_id), region);
+ Send(new ServiceWorkerHostMsg_GeofencingEventFinished(GetRoutingID(),
+ request_id));
+}
+
void ServiceWorkerScriptContext::OnPostMessage(
const base::string16& message,
const std::vector<int>& sent_message_port_ids,
const std::vector<int>& new_routing_ids) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnPostEvent");
std::vector<WebMessagePortChannelImpl*> ports;
if (!sent_message_port_ids.empty()) {
base::MessageLoopProxy* loop_proxy = embedded_context_->main_thread_proxy();
@@ -163,11 +255,19 @@ void ServiceWorkerScriptContext::OnPostMessage(
}
}
+ // dispatchMessageEvent is expected to execute onmessage function
+ // synchronously.
+ base::TimeTicks before = base::TimeTicks::Now();
proxy_->dispatchMessageEvent(message, ports);
+ UMA_HISTOGRAM_TIMES(
+ "ServiceWorker.MessageEventExecutionTime",
+ base::TimeTicks::Now() - before);
}
void ServiceWorkerScriptContext::OnDidGetClientDocuments(
int request_id, const std::vector<int>& client_ids) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerScriptContext::OnDidGetClientDocuments");
blink::WebServiceWorkerClientsCallbacks* callbacks =
pending_clients_callbacks_.Lookup(request_id);
if (!callbacks) {
@@ -181,8 +281,4 @@ void ServiceWorkerScriptContext::OnDidGetClientDocuments(
pending_clients_callbacks_.Remove(request_id);
}
-int ServiceWorkerScriptContext::GetRoutingID() const {
- return embedded_context_->embedded_worker_id();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/service_worker/service_worker_script_context.h b/chromium/content/renderer/service_worker/service_worker_script_context.h
index d7f59b30ea1..f98250d04b1 100644
--- a/chromium/content/renderer/service_worker/service_worker_script_context.h
+++ b/chromium/content/renderer/service_worker/service_worker_script_context.h
@@ -5,19 +5,25 @@
#ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CONTEXT_H_
#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CONTEXT_H_
+#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/id_map.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
+#include "base/time/time.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/renderer/service_worker/service_worker_cache_storage_dispatcher.h"
+#include "third_party/WebKit/public/platform/WebGeofencingEventType.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerClientsInfo.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
namespace blink {
+struct WebCircularGeofencingRegion;
class WebServiceWorkerContextProxy;
}
@@ -57,27 +63,38 @@ class ServiceWorkerScriptContext {
const base::string16& message,
scoped_ptr<blink::WebMessagePortChannelArray> channels);
+ // Send a message to the browser. Takes ownership of |message|.
+ void Send(IPC::Message* message);
+
+ // Get routing_id for sending message to the ServiceWorkerVersion
+ // in the browser process.
+ int GetRoutingID() const;
+
+ blink::WebServiceWorkerCacheStorage* cache_storage() {
+ return cache_storage_dispatcher_.get();
+ }
+
private:
typedef IDMap<blink::WebServiceWorkerClientsCallbacks, IDMapOwnPointer>
ClientsCallbacksMap;
- // Send a message to the browser.
- void Send(IPC::Message* message);
void OnActivateEvent(int request_id);
void OnInstallEvent(int request_id, int active_version_id);
void OnFetchEvent(int request_id, const ServiceWorkerFetchRequest& request);
void OnSyncEvent(int request_id);
void OnPushEvent(int request_id, const std::string& data);
+ void OnGeofencingEvent(int request_id,
+ blink::WebGeofencingEventType event_type,
+ const std::string& region_id,
+ const blink::WebCircularGeofencingRegion& region);
void OnPostMessage(const base::string16& message,
const std::vector<int>& sent_message_port_ids,
const std::vector<int>& new_routing_ids);
void OnDidGetClientDocuments(
int request_id, const std::vector<int>& client_ids);
- // Get routing_id for sending message to the ServiceWorkerVersion
- // in the browser process.
- int GetRoutingID() const;
+ scoped_ptr<ServiceWorkerCacheStorageDispatcher> cache_storage_dispatcher_;
// Not owned; embedded_context_ owns this.
EmbeddedWorkerContextClient* embedded_context_;
@@ -93,6 +110,11 @@ class ServiceWorkerScriptContext {
// Pending callbacks for GetClientDocuments().
ClientsCallbacksMap pending_clients_callbacks_;
+ // Capture timestamps for UMA
+ std::map<int, base::TimeTicks> activate_start_timings_;
+ std::map<int, base::TimeTicks> fetch_start_timings_;
+ std::map<int, base::TimeTicks> install_start_timings_;
+
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptContext);
};
diff --git a/chromium/content/renderer/shared_memory_seqlock_reader.cc b/chromium/content/renderer/shared_memory_seqlock_reader.cc
index 18c7770c252..5cf93478db4 100644
--- a/chromium/content/renderer/shared_memory_seqlock_reader.cc
+++ b/chromium/content/renderer/shared_memory_seqlock_reader.cc
@@ -4,6 +4,7 @@
#include "shared_memory_seqlock_reader.h"
+namespace content {
namespace internal {
SharedMemorySeqLockReaderBase::SharedMemorySeqLockReaderBase() { }
@@ -56,3 +57,4 @@ bool SharedMemorySeqLockReaderBase::FetchFromBuffer(
}
} // namespace internal
+} // namespace content
diff --git a/chromium/content/renderer/shared_memory_seqlock_reader.h b/chromium/content/renderer/shared_memory_seqlock_reader.h
index 1d0e60e6495..7fd7beb95bb 100644
--- a/chromium/content/renderer/shared_memory_seqlock_reader.h
+++ b/chromium/content/renderer/shared_memory_seqlock_reader.h
@@ -10,6 +10,7 @@
#include "base/memory/shared_memory.h"
#include "content/common/shared_memory_seqlock_buffer.h"
+namespace content {
namespace internal {
class SharedMemorySeqLockReaderBase {
@@ -31,8 +32,6 @@ class SharedMemorySeqLockReaderBase {
} // namespace internal
-namespace content {
-
// Template argument Data should be a pod-like structure only containing
// data fields, such that it is copyable by memcpy method.
template<typename Data>
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 5a6236b0871..a2b6639c3b0 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -40,7 +40,7 @@ class SharedWorkerWebApplicationCacheHostImpl
const blink::WebApplicationCacheHost*) {}
virtual void didReceiveResponseForMainResource(const blink::WebURLResponse&) {
}
- virtual void didReceiveDataForMainResource(const char* data, int len) {}
+ virtual void didReceiveDataForMainResource(const char* data, unsigned len) {}
virtual void didFinishLoadingMainResource(bool success) {}
// Cache selection is also different for workers. We know at construction
@@ -51,7 +51,8 @@ class SharedWorkerWebApplicationCacheHostImpl
return true;
}
};
-}
+
+} // namespace
EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
const GURL& url,
@@ -60,7 +61,11 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
blink::WebContentSecurityPolicyType security_policy_type,
bool pause_on_start,
int route_id)
- : route_id_(route_id), name_(name), runing_(false), url_(url) {
+ : route_id_(route_id),
+ name_(name),
+ runing_(false),
+ url_(url),
+ app_cache_host_(nullptr) {
RenderThreadImpl::current()->AddEmbeddedWorkerRoute(route_id_, this);
impl_ = blink::WebSharedWorker::create(this);
if (pause_on_start) {
@@ -96,6 +101,10 @@ void EmbeddedSharedWorkerStub::OnChannelError() {
OnTerminateWorkerContext();
}
+void EmbeddedSharedWorkerStub::workerReadyForInspection() {
+ Send(new WorkerHostMsg_WorkerReadyForInspection(route_id_));
+}
+
void EmbeddedSharedWorkerStub::workerScriptLoaded() {
Send(new WorkerHostMsg_WorkerScriptLoaded(route_id_));
runing_ = true;
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
index ab9b7edd7a6..c710efa0cc1 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -42,27 +42,28 @@ class EmbeddedSharedWorkerStub : public IPC::Listener,
int route_id);
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ void OnChannelError() override;
// blink::WebSharedWorkerClient implementation.
- virtual void workerContextClosed() OVERRIDE;
- virtual void workerContextDestroyed() OVERRIDE;
- virtual void workerScriptLoaded() OVERRIDE;
- virtual void workerScriptLoadFailed() OVERRIDE;
- virtual void selectAppCacheID(long long) OVERRIDE;
- virtual blink::WebNotificationPresenter* notificationPresenter() OVERRIDE;
+ virtual void workerContextClosed() override;
+ virtual void workerContextDestroyed() override;
+ virtual void workerReadyForInspection() override;
+ virtual void workerScriptLoaded() override;
+ virtual void workerScriptLoadFailed() override;
+ virtual void selectAppCacheID(long long) override;
+ virtual blink::WebNotificationPresenter* notificationPresenter() override;
virtual blink::WebApplicationCacheHost* createApplicationCacheHost(
- blink::WebApplicationCacheHostClient*) OVERRIDE;
+ blink::WebApplicationCacheHostClient*) override;
virtual blink::WebWorkerPermissionClientProxy*
createWorkerPermissionClientProxy(
- const blink::WebSecurityOrigin& origin) OVERRIDE;
+ const blink::WebSecurityOrigin& origin) override;
virtual void dispatchDevToolsMessage(
- const blink::WebString& message) OVERRIDE;
- virtual void saveDevToolsAgentState(const blink::WebString& state) OVERRIDE;
+ const blink::WebString& message) override;
+ virtual void saveDevToolsAgentState(const blink::WebString& state) override;
private:
- virtual ~EmbeddedSharedWorkerStub();
+ ~EmbeddedSharedWorkerStub() override;
void Shutdown();
bool Send(IPC::Message* message);
diff --git a/chromium/content/renderer/shared_worker_repository.cc b/chromium/content/renderer/shared_worker_repository.cc
index a34a3317cd3..a883464f9b4 100644
--- a/chromium/content/renderer/shared_worker_repository.cc
+++ b/chromium/content/renderer/shared_worker_repository.cc
@@ -9,7 +9,7 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/websharedworker_proxy.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
namespace content {
diff --git a/chromium/content/renderer/shared_worker_repository.h b/chromium/content/renderer/shared_worker_repository.h
index 4e49217411f..5092e0c6a96 100644
--- a/chromium/content/renderer/shared_worker_repository.h
+++ b/chromium/content/renderer/shared_worker_repository.h
@@ -20,7 +20,7 @@ class SharedWorkerRepository : public RenderFrameObserver,
public blink::WebSharedWorkerRepositoryClient {
public:
explicit SharedWorkerRepository(RenderFrameImpl* render_frame);
- virtual ~SharedWorkerRepository();
+ ~SharedWorkerRepository() override;
// WebSharedWorkerRepositoryClient overrides.
virtual blink::WebSharedWorkerConnector* createSharedWorkerConnector(
@@ -28,8 +28,8 @@ class SharedWorkerRepository : public RenderFrameObserver,
const blink::WebString& name,
DocumentID document_id,
const blink::WebString& content_security_policy,
- blink::WebContentSecurityPolicyType) OVERRIDE;
- virtual void documentDetached(DocumentID document_id) OVERRIDE;
+ blink::WebContentSecurityPolicyType) override;
+ virtual void documentDetached(DocumentID document_id) override;
private:
std::set<DocumentID> documents_with_workers_;
diff --git a/chromium/content/renderer/skia_benchmarking_extension.cc b/chromium/content/renderer/skia_benchmarking_extension.cc
index 568eb058f0b..6645fa0265d 100644
--- a/chromium/content/renderer/skia_benchmarking_extension.cc
+++ b/chromium/content/renderer/skia_benchmarking_extension.cc
@@ -10,6 +10,7 @@
#include "cc/base/math_util.h"
#include "cc/resources/picture.h"
#include "content/public/renderer/v8_value_converter.h"
+#include "content/renderer/chrome_object_extensions_utils.h"
#include "content/renderer/render_thread_impl.h"
#include "gin/arguments.h"
#include "gin/handle.h"
@@ -77,13 +78,8 @@ void SkiaBenchmarking::Install(blink::WebFrame* frame) {
if (controller.IsEmpty())
return;
- v8::Handle<v8::Object> global = context->Global();
- v8::Handle<v8::Object> chrome =
- global->Get(gin::StringToV8(isolate, "chrome"))->ToObject();
- if (chrome.IsEmpty()) {
- chrome = v8::Object::New(isolate);
- global->Set(gin::StringToV8(isolate, "chrome"), chrome);
- }
+ v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
+ context->Global());
chrome->Set(gin::StringToV8(isolate, "skiaBenchmarking"), controller.ToV8());
}
@@ -158,10 +154,7 @@ void SkiaBenchmarking::Rasterize(gin::Arguments* args) {
gfx::Rect snapped_clip = gfx::ToEnclosingRect(clip);
SkBitmap bitmap;
- if (!bitmap.setConfig(SkBitmap::kARGB_8888_Config, snapped_clip.width(),
- snapped_clip.height()))
- return;
- if (!bitmap.allocPixels())
+ if (!bitmap.tryAllocN32Pixels(snapped_clip.width(), snapped_clip.height()))
return;
bitmap.eraseARGB(0, 0, 0, 0);
@@ -235,7 +228,7 @@ void SkiaBenchmarking::GetOps(gin::Arguments* args) {
v8::String::NewFromUtf8(
isolate, SkDrawCommand::GetCommandString(cmd_type)));
- SkTDArray<SkString*>* info = canvas.getCommandInfo(i);
+ const SkTDArray<SkString*>* info = canvas.getCommandInfo(i);
DCHECK(info);
v8::Local<v8::Array> v8_info = v8::Array::New(isolate, info->count());
diff --git a/chromium/content/renderer/skia_benchmarking_extension.h b/chromium/content/renderer/skia_benchmarking_extension.h
index 974ae127b35..2e0faf16d83 100644
--- a/chromium/content/renderer/skia_benchmarking_extension.h
+++ b/chromium/content/renderer/skia_benchmarking_extension.h
@@ -28,11 +28,11 @@ class SkiaBenchmarking : public gin::Wrappable<SkiaBenchmarking> {
private:
SkiaBenchmarking();
- virtual ~SkiaBenchmarking();
+ ~SkiaBenchmarking() override;
// gin::Wrappable.
- virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) OVERRIDE;
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
// Rasterizes a Picture JSON-encoded by cc::Picture::AsValue().
//
diff --git a/chromium/content/renderer/skia_benchmarking_extension_unittest.cc b/chromium/content/renderer/skia_benchmarking_extension_unittest.cc
index 3a6e02ce4e3..1c1bf9a9c0c 100644
--- a/chromium/content/renderer/skia_benchmarking_extension_unittest.cc
+++ b/chromium/content/renderer/skia_benchmarking_extension_unittest.cc
@@ -15,7 +15,7 @@ namespace {
testing::AssertionResult HasInfoField(SkDebugCanvas& canvas, int index,
const char* field) {
- SkTDArray<SkString*>* info = canvas.getCommandInfo(index);
+ const SkTDArray<SkString*>* info = canvas.getCommandInfo(index);
if (info == NULL)
return testing::AssertionFailure() << " command info not found for index "
<< index;
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.cc b/chromium/content/renderer/speech_recognition_dispatcher.cc
index 178abf4610c..dea16bc5cfe 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.cc
+++ b/chromium/content/renderer/speech_recognition_dispatcher.cc
@@ -15,6 +15,10 @@
#include "third_party/WebKit/public/web/WebSpeechRecognitionResult.h"
#include "third_party/WebKit/public/web/WebSpeechRecognizerClient.h"
+#if defined(ENABLE_WEBRTC)
+#include "content/renderer/media/speech_recognition_audio_sink.h"
+#endif
+
using blink::WebVector;
using blink::WebString;
using blink::WebSpeechGrammar;
@@ -29,13 +33,12 @@ SpeechRecognitionDispatcher::SpeechRecognitionDispatcher(
RenderViewImpl* render_view)
: RenderViewObserver(render_view),
recognizer_client_(NULL),
- next_id_(1) {
-}
+ next_id_(1) {}
-SpeechRecognitionDispatcher::~SpeechRecognitionDispatcher() {
-}
+SpeechRecognitionDispatcher::~SpeechRecognitionDispatcher() {}
void SpeechRecognitionDispatcher::AbortAllRecognitions() {
+ ResetAudioSink();
Send(new SpeechRecognitionHostMsg_AbortAllRequests(
routing_id()));
}
@@ -53,6 +56,8 @@ bool SpeechRecognitionDispatcher::OnMessageReceived(
IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_Ended, OnRecognitionEnded)
IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_ResultRetrieved,
OnResultsRetrieved)
+ IPC_MESSAGE_HANDLER(SpeechRecognitionMsg_AudioReceiverReady,
+ OnAudioReceiverReady)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -65,6 +70,29 @@ void SpeechRecognitionDispatcher::start(
DCHECK(!recognizer_client_ || recognizer_client_ == recognizer_client);
recognizer_client_ = recognizer_client;
+#if defined(ENABLE_WEBRTC)
+ const blink::WebMediaStreamTrack track = params.audioTrack();
+ if (!track.isNull()) {
+ // Check if this type of track is allowed by implemented policy.
+ if (SpeechRecognitionAudioSink::IsSupportedTrack(track)) {
+ audio_track_.assign(track);
+ } else {
+ audio_track_.reset();
+ // Notify user that the track used is not supported.
+ recognizer_client_->didReceiveError(
+ handle,
+ WebString("Provided audioTrack is not supported."),
+ WebSpeechRecognizerClient::AudioCaptureError);
+
+ return;
+ }
+ }
+
+ // Destroy any previous instance to detach from the audio track.
+ // Each new session should reinstantiate the provider once the track is ready.
+ ResetAudioSink();
+#endif
+
SpeechRecognitionHostMsg_StartRequest_Params msg_params;
for (size_t i = 0; i < params.grammars().size(); ++i) {
const WebSpeechGrammar& grammar = params.grammars()[i];
@@ -78,6 +106,12 @@ void SpeechRecognitionDispatcher::start(
msg_params.origin_url = params.origin().toString().utf8();
msg_params.render_view_id = routing_id();
msg_params.request_id = GetOrCreateIDForHandle(handle);
+#if defined(ENABLE_WEBRTC)
+ // Fall back to default input when the track is not allowed.
+ msg_params.using_audio_track = !audio_track_.isNull();
+#else
+ msg_params.using_audio_track = false;
+#endif
// The handle mapping will be removed in |OnRecognitionEnd|.
Send(new SpeechRecognitionHostMsg_StartRequest(msg_params));
}
@@ -85,6 +119,7 @@ void SpeechRecognitionDispatcher::start(
void SpeechRecognitionDispatcher::stop(
const WebSpeechRecognitionHandle& handle,
WebSpeechRecognizerClient* recognizer_client) {
+ ResetAudioSink();
// Ignore a |stop| issued without a matching |start|.
if (recognizer_client_ != recognizer_client || !HandleExists(handle))
return;
@@ -95,6 +130,7 @@ void SpeechRecognitionDispatcher::stop(
void SpeechRecognitionDispatcher::abort(
const WebSpeechRecognitionHandle& handle,
WebSpeechRecognizerClient* recognizer_client) {
+ ResetAudioSink();
// Ignore an |abort| issued without a matching |start|.
if (recognizer_client_ != recognizer_client || !HandleExists(handle))
return;
@@ -154,6 +190,7 @@ void SpeechRecognitionDispatcher::OnErrorOccurred(
recognizer_client_->didReceiveNoMatch(GetHandleFromID(request_id),
WebSpeechRecognitionResult());
} else {
+ ResetAudioSink();
recognizer_client_->didReceiveError(
GetHandleFromID(request_id),
WebString(), // TODO(primiano): message?
@@ -174,6 +211,7 @@ void SpeechRecognitionDispatcher::OnRecognitionEnded(int request_id) {
// didEnd may call back synchronously to start a new recognition session,
// and we don't want to delete the handle from the map after that happens.
handle_map_.erase(request_id);
+ ResetAudioSink();
recognizer_client_->didEnd(handle);
}
}
@@ -211,6 +249,29 @@ void SpeechRecognitionDispatcher::OnResultsRetrieved(
GetHandleFromID(request_id), final, provisional);
}
+void SpeechRecognitionDispatcher::OnAudioReceiverReady(
+ int request_id,
+ const media::AudioParameters& params,
+ const base::SharedMemoryHandle memory,
+ const base::SyncSocket::TransitDescriptor descriptor) {
+#if defined(ENABLE_WEBRTC)
+ DCHECK(!speech_audio_sink_.get());
+ if (audio_track_.isNull()) {
+ ResetAudioSink();
+ return;
+ }
+
+ // The instantiation and type of SyncSocket is up to the client since it
+ // is dependency injected to the SpeechRecognitionAudioSink.
+ scoped_ptr<base::SyncSocket> socket(new base::CancelableSyncSocket(
+ base::SyncSocket::UnwrapHandle(descriptor)));
+
+ speech_audio_sink_.reset(new SpeechRecognitionAudioSink(
+ audio_track_, params, memory, socket.Pass(),
+ base::Bind(&SpeechRecognitionDispatcher::ResetAudioSink,
+ base::Unretained(this))));
+#endif
+}
int SpeechRecognitionDispatcher::GetOrCreateIDForHandle(
const WebSpeechRecognitionHandle& handle) {
@@ -239,6 +300,12 @@ bool SpeechRecognitionDispatcher::HandleExists(
return false;
}
+void SpeechRecognitionDispatcher::ResetAudioSink() {
+#if defined(ENABLE_WEBRTC)
+ speech_audio_sink_.reset();
+#endif
+}
+
const WebSpeechRecognitionHandle& SpeechRecognitionDispatcher::GetHandleFromID(
int request_id) {
HandleMap::iterator iter = handle_map_.find(request_id);
diff --git a/chromium/content/renderer/speech_recognition_dispatcher.h b/chromium/content/renderer/speech_recognition_dispatcher.h
index bae0e5d92a4..10241956e81 100644
--- a/chromium/content/renderer/speech_recognition_dispatcher.h
+++ b/chromium/content/renderer/speech_recognition_dispatcher.h
@@ -8,14 +8,25 @@
#include <map>
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/sync_socket.h"
#include "content/public/common/speech_recognition_result.h"
#include "content/public/renderer/render_view_observer.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebSpeechRecognitionHandle.h"
#include "third_party/WebKit/public/web/WebSpeechRecognizer.h"
+namespace media {
+class AudioParameters;
+}
+
namespace content {
class RenderViewImpl;
+#if defined(ENABLE_WEBRTC)
+class SpeechRecognitionAudioSink;
+#endif
struct SpeechRecognitionError;
struct SpeechRecognitionResult;
@@ -33,16 +44,16 @@ class SpeechRecognitionDispatcher : public RenderViewObserver,
private:
// RenderViewObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// blink::WebSpeechRecognizer implementation.
virtual void start(const blink::WebSpeechRecognitionHandle&,
const blink::WebSpeechRecognitionParams&,
- blink::WebSpeechRecognizerClient*) OVERRIDE;
+ blink::WebSpeechRecognizerClient*);
virtual void stop(const blink::WebSpeechRecognitionHandle&,
- blink::WebSpeechRecognizerClient*) OVERRIDE;
+ blink::WebSpeechRecognizerClient*);
virtual void abort(const blink::WebSpeechRecognitionHandle&,
- blink::WebSpeechRecognizerClient*) OVERRIDE;
+ blink::WebSpeechRecognizerClient*);
void OnRecognitionStarted(int request_id);
void OnAudioStarted(int request_id);
@@ -53,6 +64,12 @@ class SpeechRecognitionDispatcher : public RenderViewObserver,
void OnRecognitionEnded(int request_id);
void OnResultsRetrieved(int request_id,
const SpeechRecognitionResults& result);
+ void OnAudioReceiverReady(int session_id,
+ const media::AudioParameters& params,
+ const base::SharedMemoryHandle handle,
+ const base::SyncSocket::TransitDescriptor socket);
+
+ void ResetAudioSink();
int GetOrCreateIDForHandle(const blink::WebSpeechRecognitionHandle& handle);
bool HandleExists(const blink::WebSpeechRecognitionHandle& handle);
@@ -61,6 +78,15 @@ class SpeechRecognitionDispatcher : public RenderViewObserver,
// The WebKit client class that we use to send events back to the JS world.
blink::WebSpeechRecognizerClient* recognizer_client_;
+#if defined(ENABLE_WEBRTC)
+ // Media stream audio track that the speech recognition connects to.
+ // Accessed on the render thread.
+ blink::WebMediaStreamTrack audio_track_;
+
+ // Audio sink used to provide audio from the track.
+ scoped_ptr<SpeechRecognitionAudioSink> speech_audio_sink_;
+#endif
+
typedef std::map<int, blink::WebSpeechRecognitionHandle> HandleMap;
HandleMap handle_map_;
int next_id_;
diff --git a/chromium/content/renderer/stats_collection_controller.cc b/chromium/content/renderer/stats_collection_controller.cc
index 713407942a7..da615e0dde6 100644
--- a/chromium/content/renderer/stats_collection_controller.cc
+++ b/chromium/content/renderer/stats_collection_controller.cc
@@ -47,7 +47,7 @@ bool CurrentRenderViewImpl(RenderViewImpl** out) {
// Example return value:
// {'load_start_ms': 1, 'load_duration_ms': 2.5}
// either value may be null if a web contents hasn't fully loaded.
-// load_start_ms is represented as milliseconds since system boot.
+// load_start_ms is represented as milliseconds since the unix epoch.
void ConvertLoadTimeToJSON(
const base::Time& load_start_time,
const base::Time& load_stop_time,
@@ -57,7 +57,8 @@ void ConvertLoadTimeToJSON(
if (load_start_time.is_null()) {
item.Set("load_start_ms", base::Value::CreateNullValue());
} else {
- item.SetDouble("load_start_ms", load_start_time.ToInternalValue() / 1000);
+ item.SetDouble("load_start_ms", (load_start_time - base::Time::UnixEpoch())
+ .InMillisecondsF());
}
if (load_start_time.is_null() || load_stop_time.is_null()) {
item.Set("load_duration_ms", base::Value::CreateNullValue());
diff --git a/chromium/content/renderer/stats_collection_controller.h b/chromium/content/renderer/stats_collection_controller.h
index 279fed7602d..c36349c51a2 100644
--- a/chromium/content/renderer/stats_collection_controller.h
+++ b/chromium/content/renderer/stats_collection_controller.h
@@ -27,11 +27,11 @@ class StatsCollectionController
private:
StatsCollectionController();
- virtual ~StatsCollectionController();
+ ~StatsCollectionController() override;
// gin::WrappableBase
- virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) OVERRIDE;
+ gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) override;
// Retrieves a histogram and returns a JSON representation of it.
std::string GetHistogram(const std::string& histogram_name);
diff --git a/chromium/content/renderer/stats_collection_observer.h b/chromium/content/renderer/stats_collection_observer.h
index 2717fd943c5..9aba8dc530c 100644
--- a/chromium/content/renderer/stats_collection_observer.h
+++ b/chromium/content/renderer/stats_collection_observer.h
@@ -17,11 +17,11 @@ class RenderViewImpl;
class StatsCollectionObserver : public RenderViewObserver {
public:
explicit StatsCollectionObserver(RenderViewImpl* render_view);
- virtual ~StatsCollectionObserver();
+ ~StatsCollectionObserver() override;
// RenderViewObserver implementation
- virtual void DidStartLoading() OVERRIDE;
- virtual void DidStopLoading() OVERRIDE;
+ void DidStartLoading() override;
+ void DidStopLoading() override;
// Timing for the page load start and stop. These functions may return
// a null time value under various circumstances.
diff --git a/chromium/content/renderer/text_input_client_observer.h b/chromium/content/renderer/text_input_client_observer.h
index a4a471d9654..c8d1b4a2e13 100644
--- a/chromium/content/renderer/text_input_client_observer.h
+++ b/chromium/content/renderer/text_input_client_observer.h
@@ -25,10 +25,10 @@ class RenderViewImpl;
class TextInputClientObserver : public RenderViewObserver {
public:
explicit TextInputClientObserver(RenderViewImpl* render_view);
- virtual ~TextInputClientObserver();
+ ~TextInputClientObserver() override;
// RenderViewObserver overrides:
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
private:
// Returns the WebView of the RenderView.
diff --git a/chromium/content/renderer/v8_value_converter_impl.h b/chromium/content/renderer/v8_value_converter_impl.h
index affbed7353f..decc10b3863 100644
--- a/chromium/content/renderer/v8_value_converter_impl.h
+++ b/chromium/content/renderer/v8_value_converter_impl.h
@@ -26,17 +26,16 @@ class CONTENT_EXPORT V8ValueConverterImpl : public V8ValueConverter {
V8ValueConverterImpl();
// V8ValueConverter implementation.
- virtual void SetDateAllowed(bool val) OVERRIDE;
- virtual void SetRegExpAllowed(bool val) OVERRIDE;
- virtual void SetFunctionAllowed(bool val) OVERRIDE;
- virtual void SetStripNullFromObjects(bool val) OVERRIDE;
- virtual void SetStrategy(Strategy* strategy) OVERRIDE;
- virtual v8::Handle<v8::Value> ToV8Value(
+ void SetDateAllowed(bool val) override;
+ void SetRegExpAllowed(bool val) override;
+ void SetFunctionAllowed(bool val) override;
+ void SetStripNullFromObjects(bool val) override;
+ void SetStrategy(Strategy* strategy) override;
+ v8::Handle<v8::Value> ToV8Value(
const base::Value* value,
- v8::Handle<v8::Context> context) const OVERRIDE;
- virtual base::Value* FromV8Value(
- v8::Handle<v8::Value> value,
- v8::Handle<v8::Context> context) const OVERRIDE;
+ v8::Handle<v8::Context> context) const override;
+ base::Value* FromV8Value(v8::Handle<v8::Value> value,
+ v8::Handle<v8::Context> context) const override;
private:
friend class ScopedAvoidIdentityHashForTesting;
diff --git a/chromium/content/renderer/v8_value_converter_impl_unittest.cc b/chromium/content/renderer/v8_value_converter_impl_unittest.cc
index 6f1302dd5fc..5cd30a9f291 100644
--- a/chromium/content/renderer/v8_value_converter_impl_unittest.cc
+++ b/chromium/content/renderer/v8_value_converter_impl_unittest.cc
@@ -51,15 +51,13 @@ class V8ValueConverterImplTest : public testing::Test {
}
protected:
- virtual void SetUp() {
+ void SetUp() override {
v8::HandleScope handle_scope(isolate_);
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
}
- virtual void TearDown() {
- context_.Reset();
- }
+ void TearDown() override { context_.Reset(); }
std::string GetString(base::DictionaryValue* value, const std::string& key) {
std::string temp;
@@ -716,33 +714,32 @@ class V8ValueConverterOverridingStrategyForTesting
public:
V8ValueConverterOverridingStrategyForTesting()
: reference_value_(NewReferenceValue()) {}
- virtual bool FromV8Object(
- v8::Handle<v8::Object> value,
- base::Value** out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) const OVERRIDE {
+ bool FromV8Object(v8::Handle<v8::Object> value,
+ base::Value** out,
+ v8::Isolate* isolate,
+ const FromV8ValueCallback& callback) const override {
*out = NewReferenceValue();
return true;
}
- virtual bool FromV8Array(v8::Handle<v8::Array> value,
- base::Value** out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) const OVERRIDE {
+ bool FromV8Array(v8::Handle<v8::Array> value,
+ base::Value** out,
+ v8::Isolate* isolate,
+ const FromV8ValueCallback& callback) const override {
*out = NewReferenceValue();
return true;
}
- virtual bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
- base::Value** out,
- v8::Isolate* isolate) const OVERRIDE {
+ bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
+ base::Value** out,
+ v8::Isolate* isolate) const override {
*out = NewReferenceValue();
return true;
}
- virtual bool FromV8Number(v8::Handle<v8::Number> value,
- base::Value** out) const OVERRIDE {
+ bool FromV8Number(v8::Handle<v8::Number> value,
+ base::Value** out) const override {
*out = NewReferenceValue();
return true;
}
- virtual bool FromV8Undefined(base::Value** out) const OVERRIDE {
+ bool FromV8Undefined(base::Value** out) const override {
*out = NewReferenceValue();
return true;
}
@@ -809,31 +806,28 @@ TEST_F(V8ValueConverterImplTest, StrategyOverrides) {
class V8ValueConverterBypassStrategyForTesting
: public V8ValueConverter::Strategy {
public:
- virtual bool FromV8Object(
- v8::Handle<v8::Object> value,
- base::Value** out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) const OVERRIDE {
- return false;
- }
- virtual bool FromV8Array(v8::Handle<v8::Array> value,
- base::Value** out,
- v8::Isolate* isolate,
- const FromV8ValueCallback& callback) const OVERRIDE {
+ bool FromV8Object(v8::Handle<v8::Object> value,
+ base::Value** out,
+ v8::Isolate* isolate,
+ const FromV8ValueCallback& callback) const override {
return false;
}
- virtual bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
- base::Value** out,
- v8::Isolate* isolate) const OVERRIDE {
+ bool FromV8Array(v8::Handle<v8::Array> value,
+ base::Value** out,
+ v8::Isolate* isolate,
+ const FromV8ValueCallback& callback) const override {
return false;
}
- virtual bool FromV8Number(v8::Handle<v8::Number> value,
- base::Value** out) const OVERRIDE {
+ bool FromV8ArrayBuffer(v8::Handle<v8::Object> value,
+ base::Value** out,
+ v8::Isolate* isolate) const override {
return false;
}
- virtual bool FromV8Undefined(base::Value** out) const OVERRIDE {
+ bool FromV8Number(v8::Handle<v8::Number> value,
+ base::Value** out) const override {
return false;
}
+ bool FromV8Undefined(base::Value** out) const override { return false; }
};
// Verify that having a strategy that fallbacks to default behaviour
diff --git a/chromium/content/renderer/web_preferences.cc b/chromium/content/renderer/web_preferences.cc
deleted file mode 100644
index bd975fd85f4..00000000000
--- a/chromium/content/renderer/web_preferences.cc
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2013 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 "content/public/renderer/web_preferences.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "content/renderer/net_info_helper.h"
-#include "third_party/WebKit/public/platform/WebConnectionType.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/WebKit/public/web/WebNetworkStateNotifier.h"
-#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-#include "third_party/WebKit/public/web/WebSettings.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-#include "third_party/icu/source/common/unicode/uscript.h"
-#include "webkit/common/webpreferences.h"
-
-using blink::WebNetworkStateNotifier;
-using blink::WebRuntimeFeatures;
-using blink::WebSettings;
-using blink::WebString;
-using blink::WebURL;
-using blink::WebView;
-
-namespace content {
-
-namespace {
-
-typedef void (*SetFontFamilyWrapper)(blink::WebSettings*,
- const base::string16&,
- UScriptCode);
-
-void setStandardFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setStandardFontFamily(font, script);
-}
-
-void setFixedFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setFixedFontFamily(font, script);
-}
-
-void setSerifFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setSerifFontFamily(font, script);
-}
-
-void setSansSerifFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setSansSerifFontFamily(font, script);
-}
-
-void setCursiveFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setCursiveFontFamily(font, script);
-}
-
-void setFantasyFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setFantasyFontFamily(font, script);
-}
-
-void setPictographFontFamilyWrapper(WebSettings* settings,
- const base::string16& font,
- UScriptCode script) {
- settings->setPictographFontFamily(font, script);
-}
-
-// If |scriptCode| is a member of a family of "similar" script codes, returns
-// the script code in that family that is used by WebKit for font selection
-// purposes. For example, USCRIPT_KATAKANA_OR_HIRAGANA and USCRIPT_JAPANESE are
-// considered equivalent for the purposes of font selection. WebKit uses the
-// script code USCRIPT_KATAKANA_OR_HIRAGANA. So, if |scriptCode| is
-// USCRIPT_JAPANESE, the function returns USCRIPT_KATAKANA_OR_HIRAGANA. WebKit
-// uses different scripts than the ones in Chrome pref names because the version
-// of ICU included on certain ports does not have some of the newer scripts. If
-// |scriptCode| is not a member of such a family, returns |scriptCode|.
-UScriptCode GetScriptForWebSettings(UScriptCode scriptCode) {
- switch (scriptCode) {
- case USCRIPT_HIRAGANA:
- case USCRIPT_KATAKANA:
- case USCRIPT_JAPANESE:
- return USCRIPT_KATAKANA_OR_HIRAGANA;
- case USCRIPT_KOREAN:
- return USCRIPT_HANGUL;
- default:
- return scriptCode;
- }
-}
-
-void ApplyFontsFromMap(const webkit_glue::ScriptFontFamilyMap& map,
- SetFontFamilyWrapper setter,
- WebSettings* settings) {
- for (webkit_glue::ScriptFontFamilyMap::const_iterator it = map.begin();
- it != map.end();
- ++it) {
- int32 script = u_getPropertyValueEnum(UCHAR_SCRIPT, (it->first).c_str());
- if (script >= 0 && script < USCRIPT_CODE_LIMIT) {
- UScriptCode code = static_cast<UScriptCode>(script);
- (*setter)(settings, it->second, GetScriptForWebSettings(code));
- }
- }
-}
-
-} // namespace
-
-void ApplyWebPreferences(const WebPreferences& prefs, WebView* web_view) {
- WebSettings* settings = web_view->settings();
- ApplyFontsFromMap(prefs.standard_font_family_map,
- setStandardFontFamilyWrapper, settings);
- ApplyFontsFromMap(prefs.fixed_font_family_map,
- setFixedFontFamilyWrapper, settings);
- ApplyFontsFromMap(prefs.serif_font_family_map,
- setSerifFontFamilyWrapper, settings);
- ApplyFontsFromMap(prefs.sans_serif_font_family_map,
- setSansSerifFontFamilyWrapper, settings);
- ApplyFontsFromMap(prefs.cursive_font_family_map,
- setCursiveFontFamilyWrapper, settings);
- ApplyFontsFromMap(prefs.fantasy_font_family_map,
- setFantasyFontFamilyWrapper, settings);
- ApplyFontsFromMap(prefs.pictograph_font_family_map,
- setPictographFontFamilyWrapper, settings);
- settings->setDefaultFontSize(prefs.default_font_size);
- settings->setDefaultFixedFontSize(prefs.default_fixed_font_size);
- settings->setMinimumFontSize(prefs.minimum_font_size);
- settings->setMinimumLogicalFontSize(prefs.minimum_logical_font_size);
- settings->setDefaultTextEncodingName(
- base::ASCIIToUTF16(prefs.default_encoding));
- settings->setJavaScriptEnabled(prefs.javascript_enabled);
- settings->setWebSecurityEnabled(prefs.web_security_enabled);
- settings->setJavaScriptCanOpenWindowsAutomatically(
- prefs.javascript_can_open_windows_automatically);
- settings->setLoadsImagesAutomatically(prefs.loads_images_automatically);
- settings->setImagesEnabled(prefs.images_enabled);
- settings->setPluginsEnabled(prefs.plugins_enabled);
- settings->setDOMPasteAllowed(prefs.dom_paste_enabled);
- settings->setNeedsSiteSpecificQuirks(prefs.site_specific_quirks_enabled);
- settings->setShrinksStandaloneImagesToFit(
- prefs.shrinks_standalone_images_to_fit);
- settings->setUsesEncodingDetector(prefs.uses_universal_detector);
- settings->setTextAreasAreResizable(prefs.text_areas_are_resizable);
- settings->setAllowScriptsToCloseWindows(prefs.allow_scripts_to_close_windows);
- settings->setDownloadableBinaryFontsEnabled(prefs.remote_fonts_enabled);
- settings->setJavaScriptCanAccessClipboard(
- prefs.javascript_can_access_clipboard);
- WebRuntimeFeatures::enableXSLT(prefs.xslt_enabled);
- settings->setXSSAuditorEnabled(prefs.xss_auditor_enabled);
- settings->setDNSPrefetchingEnabled(prefs.dns_prefetching_enabled);
- settings->setLocalStorageEnabled(prefs.local_storage_enabled);
- settings->setSyncXHRInDocumentsEnabled(prefs.sync_xhr_in_documents_enabled);
- WebRuntimeFeatures::enableDatabase(prefs.databases_enabled);
- settings->setOfflineWebApplicationCacheEnabled(
- prefs.application_cache_enabled);
- settings->setCaretBrowsingEnabled(prefs.caret_browsing_enabled);
- settings->setHyperlinkAuditingEnabled(prefs.hyperlink_auditing_enabled);
- settings->setCookieEnabled(prefs.cookie_enabled);
- settings->setNavigateOnDragDrop(prefs.navigate_on_drag_drop);
-
- settings->setJavaEnabled(prefs.java_enabled);
-
- // By default, allow_universal_access_from_file_urls is set to false and thus
- // we mitigate attacks from local HTML files by not granting file:// URLs
- // universal access. Only test shell will enable this.
- settings->setAllowUniversalAccessFromFileURLs(
- prefs.allow_universal_access_from_file_urls);
- settings->setAllowFileAccessFromFileURLs(
- prefs.allow_file_access_from_file_urls);
-
- // Enable the web audio API if requested on the command line.
- settings->setWebAudioEnabled(prefs.webaudio_enabled);
-
- // Enable experimental WebGL support if requested on command line
- // and support is compiled in.
- settings->setExperimentalWebGLEnabled(prefs.experimental_webgl_enabled);
-
- // Disable GL multisampling if requested on command line.
- settings->setOpenGLMultisamplingEnabled(prefs.gl_multisampling_enabled);
-
- // Enable WebGL errors to the JS console if requested.
- settings->setWebGLErrorsToConsoleEnabled(
- prefs.webgl_errors_to_console_enabled);
-
- // Uses the mock theme engine for scrollbars.
- settings->setMockScrollbarsEnabled(prefs.mock_scrollbars_enabled);
-
- settings->setLayerSquashingEnabled(prefs.layer_squashing_enabled);
-
- // Enable gpu-accelerated compositing always.
- settings->setAcceleratedCompositingEnabled(true);
-
- // Enable gpu-accelerated 2d canvas if requested on the command line.
- settings->setAccelerated2dCanvasEnabled(prefs.accelerated_2d_canvas_enabled);
-
- settings->setMinimumAccelerated2dCanvasSize(
- prefs.minimum_accelerated_2d_canvas_size);
-
- // Disable antialiasing for 2d canvas if requested on the command line.
- settings->setAntialiased2dCanvasEnabled(
- !prefs.antialiased_2d_canvas_disabled);
-
- // Set MSAA sample count for 2d canvas if requested on the command line (or
- // default value if not).
- settings->setAccelerated2dCanvasMSAASampleCount(
- prefs.accelerated_2d_canvas_msaa_sample_count);
-
- // Enable deferred filter rendering if requested on the command line.
- settings->setDeferredFiltersEnabled(prefs.deferred_filters_enabled);
-
- // Enable container culling if requested on the command line.
- settings->setContainerCullingEnabled(prefs.container_culling_enabled);
-
- // Enable gesture tap highlight if requested on the command line.
- settings->setGestureTapHighlightEnabled(prefs.gesture_tap_highlight_enabled);
-
- // Enabling accelerated layers from the command line enabled accelerated
- // Video.
- settings->setAcceleratedCompositingForVideoEnabled(
- prefs.accelerated_compositing_for_video_enabled);
-
- // WebGL and accelerated 2D canvas are always gpu composited.
- settings->setAcceleratedCompositingForCanvasEnabled(
- prefs.experimental_webgl_enabled || prefs.accelerated_2d_canvas_enabled);
-
- settings->setAsynchronousSpellCheckingEnabled(
- prefs.asynchronous_spell_checking_enabled);
- settings->setUnifiedTextCheckerEnabled(prefs.unified_textchecker_enabled);
-
- for (webkit_glue::WebInspectorPreferences::const_iterator it =
- prefs.inspector_settings.begin();
- it != prefs.inspector_settings.end();
- ++it) {
- web_view->setInspectorSetting(WebString::fromUTF8(it->first),
- WebString::fromUTF8(it->second));
- }
-
- // Tabs to link is not part of the settings. WebCore calls
- // ChromeClient::tabsToLinks which is part of the glue code.
- web_view->setTabsToLinks(prefs.tabs_to_links);
-
- settings->setAllowDisplayOfInsecureContent(
- prefs.allow_displaying_insecure_content);
- settings->setAllowRunningOfInsecureContent(
- prefs.allow_running_insecure_content);
- settings->setPasswordEchoEnabled(prefs.password_echo_enabled);
- settings->setShouldPrintBackgrounds(prefs.should_print_backgrounds);
- settings->setShouldClearDocumentBackground(
- prefs.should_clear_document_background);
- settings->setEnableScrollAnimator(prefs.enable_scroll_animator);
-
- settings->setRegionBasedColumnsEnabled(prefs.region_based_columns_enabled);
-
- WebRuntimeFeatures::enableTouch(prefs.touch_enabled);
- settings->setMaxTouchPoints(prefs.pointer_events_max_touch_points);
- settings->setDeviceSupportsTouch(prefs.device_supports_touch);
- settings->setDeviceSupportsMouse(prefs.device_supports_mouse);
- settings->setEnableTouchAdjustment(prefs.touch_adjustment_enabled);
-
- settings->setDeferredImageDecodingEnabled(
- prefs.deferred_image_decoding_enabled);
- settings->setShouldRespectImageOrientation(
- prefs.should_respect_image_orientation);
-
- settings->setUnsafePluginPastingEnabled(false);
- settings->setEditingBehavior(
- static_cast<WebSettings::EditingBehavior>(prefs.editing_behavior));
-
- settings->setSupportsMultipleWindows(prefs.supports_multiple_windows);
-
- settings->setViewportEnabled(prefs.viewport_enabled);
- settings->setLoadWithOverviewMode(prefs.initialize_at_minimum_page_scale);
- settings->setViewportMetaEnabled(prefs.viewport_meta_enabled);
- settings->setMainFrameResizesAreOrientationChanges(
- prefs.main_frame_resizes_are_orientation_changes);
-
- settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled);
-
- settings->setSpatialNavigationEnabled(prefs.spatial_navigation_enabled);
-
- settings->setSelectionIncludesAltImageText(true);
-
-#if defined(OS_ANDROID)
- settings->setAllowCustomScrollbarInMainFrame(false);
- settings->setTextAutosizingEnabled(prefs.text_autosizing_enabled);
- settings->setAccessibilityFontScaleFactor(prefs.font_scale_factor);
- settings->setDeviceScaleAdjustment(prefs.device_scale_adjustment);
- web_view->setIgnoreViewportTagScaleLimits(prefs.force_enable_zoom);
- settings->setAutoZoomFocusedNodeToLegibleScale(true);
- settings->setDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled);
- settings->setMediaControlsOverlayPlayButtonEnabled(true);
- settings->setMediaPlaybackRequiresUserGesture(
- prefs.user_gesture_required_for_media_playback);
- settings->setDefaultVideoPosterURL(
- base::ASCIIToUTF16(prefs.default_video_poster_url.spec()));
- settings->setSupportDeprecatedTargetDensityDPI(
- prefs.support_deprecated_target_density_dpi);
- settings->setUseLegacyBackgroundSizeShorthandBehavior(
- prefs.use_legacy_background_size_shorthand_behavior);
- settings->setWideViewportQuirkEnabled(prefs.wide_viewport_quirk);
- settings->setUseWideViewport(prefs.use_wide_viewport);
- settings->setViewportMetaLayoutSizeQuirk(
- prefs.viewport_meta_layout_size_quirk);
- settings->setViewportMetaMergeContentQuirk(
- prefs.viewport_meta_merge_content_quirk);
- settings->setViewportMetaNonUserScalableQuirk(
- prefs.viewport_meta_non_user_scalable_quirk);
- settings->setViewportMetaZeroValuesQuirk(
- prefs.viewport_meta_zero_values_quirk);
- settings->setClobberUserAgentInitialScaleQuirk(
- prefs.clobber_user_agent_initial_scale_quirk);
- settings->setIgnoreMainFrameOverflowHiddenQuirk(
- prefs.ignore_main_frame_overflow_hidden_quirk);
- settings->setReportScreenSizeInPhysicalPixelsQuirk(
- prefs.report_screen_size_in_physical_pixels_quirk);
- settings->setMainFrameClipsContent(false);
- settings->setShrinksStandaloneImagesToFit(false);
- settings->setShrinksViewportContentToFit(true);
-#endif
-
- WebNetworkStateNotifier::setOnLine(prefs.is_online);
- WebNetworkStateNotifier::setWebConnectionType(
- NetConnectionTypeToWebConnectionType(prefs.connection_type));
- settings->setPinchVirtualViewportEnabled(
- prefs.pinch_virtual_viewport_enabled);
-
- settings->setPinchOverlayScrollbarThickness(
- prefs.pinch_overlay_scrollbar_thickness);
- settings->setUseSolidColorScrollbars(prefs.use_solid_color_scrollbars);
- settings->setCompositorTouchHitTesting(prefs.compositor_touch_hit_testing);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/web_ui_extension.cc b/chromium/content/renderer/web_ui_extension.cc
index 11565f2b4ac..127912630d8 100644
--- a/chromium/content/renderer/web_ui_extension.cc
+++ b/chromium/content/renderer/web_ui_extension.cc
@@ -12,6 +12,7 @@
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
+#include "content/renderer/chrome_object_extensions_utils.h"
#include "content/renderer/web_ui_extension_data.h"
#include "gin/arguments.h"
#include "gin/function_template.h"
@@ -69,13 +70,8 @@ void WebUIExtension::Install(blink::WebFrame* frame) {
v8::Context::Scope context_scope(context);
- v8::Handle<v8::Object> global = context->Global();
- v8::Handle<v8::Object> chrome =
- global->Get(gin::StringToV8(isolate, "chrome"))->ToObject();
- if (chrome.IsEmpty()) {
- chrome = v8::Object::New(isolate);
- global->Set(gin::StringToSymbol(isolate, "chrome"), chrome);
- }
+ v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
+ context->Global());
chrome->Set(gin::StringToSymbol(isolate, "send"),
gin::CreateFunctionTemplate(
isolate, base::Bind(&WebUIExtension::Send))->GetFunction());
diff --git a/chromium/content/renderer/web_ui_extension_data.h b/chromium/content/renderer/web_ui_extension_data.h
index 0ca151382b1..f45bc466239 100644
--- a/chromium/content/renderer/web_ui_extension_data.h
+++ b/chromium/content/renderer/web_ui_extension_data.h
@@ -19,7 +19,7 @@ class WebUIExtensionData
public RenderViewObserverTracker<WebUIExtensionData> {
public:
explicit WebUIExtensionData(RenderView* render_view);
- virtual ~WebUIExtensionData();
+ ~WebUIExtensionData() override;
// Returns value for a given |key|. Will return an empty string if no such key
// exists in the |variable_map_|.
@@ -27,7 +27,7 @@ class WebUIExtensionData
private:
// RenderViewObserver implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
void OnSetWebUIProperty(const std::string& name, const std::string& value);
diff --git a/chromium/content/renderer/web_ui_mojo.cc b/chromium/content/renderer/web_ui_mojo.cc
index 38c71d5c1c6..968ca523350 100644
--- a/chromium/content/renderer/web_ui_mojo.cc
+++ b/chromium/content/renderer/web_ui_mojo.cc
@@ -48,16 +48,7 @@ void WebUIMojo::MainFrameObserver::DidFinishDocumentLoad() {
WebUIMojo::WebUIMojo(RenderView* render_view)
: RenderViewObserver(render_view),
RenderViewObserverTracker<WebUIMojo>(render_view),
- main_frame_observer_(this),
- did_finish_document_load_(false) {
- CreateContextState();
-}
-
-void WebUIMojo::SetBrowserHandle(mojo::ScopedMessagePipeHandle handle) {
- if (did_finish_document_load_)
- SetHandleOnContextState(handle.Pass());
- else
- pending_handle_ = handle.Pass();
+ main_frame_observer_(this) {
}
WebUIMojo::~WebUIMojo() {
@@ -83,17 +74,10 @@ void WebUIMojo::DestroyContextState(v8::Handle<v8::Context> context) {
}
void WebUIMojo::OnDidFinishDocumentLoad() {
- did_finish_document_load_ = true;
- if (pending_handle_.is_valid())
- SetHandleOnContextState(pending_handle_.Pass());
-}
-
-void WebUIMojo::SetHandleOnContextState(mojo::ScopedMessagePipeHandle handle) {
- DCHECK(did_finish_document_load_);
v8::HandleScope handle_scope(blink::mainThreadIsolate());
WebUIMojoContextState* state = GetContextState();
if (state)
- state->SetHandle(handle.Pass());
+ state->Run();
}
WebUIMojoContextState* WebUIMojo::GetContextState() {
@@ -110,6 +94,10 @@ WebUIMojoContextState* WebUIMojo::GetContextState() {
return context_state ? context_state->state.get() : NULL;
}
+void WebUIMojo::DidCreateDocumentElement(blink::WebLocalFrame* frame) {
+ CreateContextState();
+}
+
void WebUIMojo::DidClearWindowObject(blink::WebLocalFrame* frame) {
if (frame != render_view()->GetWebView()->mainFrame())
return;
@@ -127,7 +115,6 @@ void WebUIMojo::DidClearWindowObject(blink::WebLocalFrame* frame) {
v8::HandleScope handle_scope(blink::mainThreadIsolate());
DestroyContextState(frame->mainWorldScriptContext());
- CreateContextState();
}
} // namespace content
diff --git a/chromium/content/renderer/web_ui_mojo.h b/chromium/content/renderer/web_ui_mojo.h
index 2a645429a2f..dd9e752b238 100644
--- a/chromium/content/renderer/web_ui_mojo.h
+++ b/chromium/content/renderer/web_ui_mojo.h
@@ -30,19 +30,16 @@ class WebUIMojo
public:
explicit WebUIMojo(RenderView* render_view);
- // Sets the handle to the current WebUI.
- void SetBrowserHandle(mojo::ScopedMessagePipeHandle handle);
-
private:
class MainFrameObserver : public RenderFrameObserver {
public:
explicit MainFrameObserver(WebUIMojo* web_ui_mojo);
- virtual ~MainFrameObserver();
+ ~MainFrameObserver() override;
// RenderFrameObserver overrides:
- virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
- int world_id) OVERRIDE;
- virtual void DidFinishDocumentLoad() OVERRIDE;
+ void WillReleaseScriptContext(v8::Handle<v8::Context> context,
+ int world_id) override;
+ void DidFinishDocumentLoad() override;
private:
WebUIMojo* web_ui_mojo_;
@@ -50,35 +47,23 @@ class WebUIMojo
DISALLOW_COPY_AND_ASSIGN(MainFrameObserver);
};
- virtual ~WebUIMojo();
+ ~WebUIMojo() override;
void CreateContextState();
void DestroyContextState(v8::Handle<v8::Context> context);
- // Invoked when the frame finishes loading. Invokes SetHandleOnContextState()
- // if necessary.
+ // Invoked when the frame finishes loading. Invokes Run() on the
+ // WebUIMojoContextState.
void OnDidFinishDocumentLoad();
- // Invokes SetHandle() on the WebUIMojoContextState (if there is one).
- void SetHandleOnContextState(mojo::ScopedMessagePipeHandle handle);
-
WebUIMojoContextState* GetContextState();
// RenderViewObserver overrides:
- virtual void DidClearWindowObject(blink::WebLocalFrame* frame) OVERRIDE;
+ void DidCreateDocumentElement(blink::WebLocalFrame* frame) override;
+ void DidClearWindowObject(blink::WebLocalFrame* frame) override;
MainFrameObserver main_frame_observer_;
- // Set to true in DidFinishDocumentLoad(). 'main' is only executed once this
- // happens.
- bool did_finish_document_load_;
-
- // If SetBrowserHandle() is invoked before the document finishes loading the
- // MessagePipeHandle is stored here. When the document finishes loading
- // SetHandleOnContextState() is invoked to send the handle to the
- // WebUIMojoContextState and ultimately the page.
- mojo::ScopedMessagePipeHandle pending_handle_;
-
DISALLOW_COPY_AND_ASSIGN(WebUIMojo);
};
diff --git a/chromium/content/renderer/web_ui_mojo_context_state.cc b/chromium/content/renderer/web_ui_mojo_context_state.cc
index f1ff5f4896a..ac13448cd30 100644
--- a/chromium/content/renderer/web_ui_mojo_context_state.cc
+++ b/chromium/content/renderer/web_ui_mojo_context_state.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/stl_util.h"
+#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/resource_fetcher.h"
#include "content/renderer/web_ui_runner.h"
#include "gin/converter.h"
@@ -13,9 +14,6 @@
#include "gin/per_context_data.h"
#include "gin/public/context_holder.h"
#include "gin/try_catch.h"
-#include "mojo/bindings/js/core.h"
-#include "mojo/bindings/js/handle.h"
-#include "mojo/bindings/js/support.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
@@ -36,14 +34,11 @@ namespace {
const char kModulePrefix[] = "chrome://mojo/";
void RunMain(base::WeakPtr<gin::Runner> runner,
- mojo::ScopedMessagePipeHandle* handle,
v8::Handle<v8::Value> module) {
v8::Isolate* isolate = runner->GetContextHolder()->isolate();
v8::Handle<v8::Function> start;
CHECK(gin::ConvertFromV8(isolate, module, &start));
- v8::Handle<v8::Value> args[] = {
- gin::ConvertToV8(isolate, mojo::Handle(handle->release().value())) };
- runner->Call(start, runner->global(), 1, args);
+ runner->Call(start, runner->global(), 0, NULL);
}
} // namespace
@@ -59,7 +54,8 @@ WebUIMojoContextState::WebUIMojoContextState(blink::WebFrame* frame,
runner_.reset(new WebUIRunner(frame_, context_holder));
gin::Runner::Scope scoper(runner_.get());
gin::ModuleRegistry::From(context)->AddObserver(this);
- runner_->RegisterBuiltinModules();
+ content::RenderFrame::FromWebFrame(frame)
+ ->EnsureMojoBuiltinsAreAvailable(context_holder->isolate(), context);
gin::ModuleRegistry::InstallGlobals(context->GetIsolate(), context->Global());
// Warning |frame| may be destroyed.
// TODO(sky): add test for this.
@@ -71,14 +67,12 @@ WebUIMojoContextState::~WebUIMojoContextState() {
runner_->GetContextHolder()->context())->RemoveObserver(this);
}
-void WebUIMojoContextState::SetHandle(mojo::ScopedMessagePipeHandle handle) {
+void WebUIMojoContextState::Run() {
gin::ContextHolder* context_holder = runner_->GetContextHolder();
- mojo::ScopedMessagePipeHandle* passed_handle =
- new mojo::ScopedMessagePipeHandle(handle.Pass());
gin::ModuleRegistry::From(context_holder->context())->LoadModule(
context_holder->isolate(),
"main",
- base::Bind(RunMain, runner_->GetWeakPtr(), base::Owned(passed_handle)));
+ base::Bind(RunMain, runner_->GetWeakPtr()));
}
void WebUIMojoContextState::FetchModules(const std::vector<std::string>& ids) {
@@ -102,9 +96,13 @@ void WebUIMojoContextState::FetchModule(const std::string& id) {
fetched_modules_.insert(id);
ResourceFetcher* fetcher = ResourceFetcher::Create(url);
module_fetchers_.push_back(fetcher);
- fetcher->Start(frame_, blink::WebURLRequest::TargetIsScript,
+ fetcher->Start(frame_,
+ blink::WebURLRequest::RequestContextScript,
+ blink::WebURLRequest::FrameTypeNone,
+ ResourceFetcher::PLATFORM_LOADER,
base::Bind(&WebUIMojoContextState::OnFetchModuleComplete,
- base::Unretained(this), fetcher));
+ base::Unretained(this),
+ fetcher));
}
void WebUIMojoContextState::OnFetchModuleComplete(
diff --git a/chromium/content/renderer/web_ui_mojo_context_state.h b/chromium/content/renderer/web_ui_mojo_context_state.h
index e4eb0a4ed58..e8879afa5e8 100644
--- a/chromium/content/renderer/web_ui_mojo_context_state.h
+++ b/chromium/content/renderer/web_ui_mojo_context_state.h
@@ -11,7 +11,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "gin/modules/module_registry_observer.h"
-#include "mojo/public/cpp/system/core.h"
#include "v8/include/v8.h"
namespace blink {
@@ -36,10 +35,9 @@ class WebUIMojoContextState : public gin::ModuleRegistryObserver {
public:
WebUIMojoContextState(blink::WebFrame* frame,
v8::Handle<v8::Context> context);
- virtual ~WebUIMojoContextState();
+ ~WebUIMojoContextState() override;
- // Called once the mojo::Handle is available.
- void SetHandle(mojo::ScopedMessagePipeHandle handle);
+ void Run();
// Returns true if at least one module was added.
bool module_added() const { return module_added_; }
@@ -60,9 +58,9 @@ class WebUIMojoContextState : public gin::ModuleRegistryObserver {
const std::string& data);
// gin::ModuleRegistryObserver overrides:
- virtual void OnDidAddPendingModule(
+ void OnDidAddPendingModule(
const std::string& id,
- const std::vector<std::string>& dependencies) OVERRIDE;
+ const std::vector<std::string>& dependencies) override;
// Frame script is executed in. Also used to download resources.
blink::WebFrame* frame_;
diff --git a/chromium/content/renderer/web_ui_runner.cc b/chromium/content/renderer/web_ui_runner.cc
index a091636cc94..5d6f05cc66a 100644
--- a/chromium/content/renderer/web_ui_runner.cc
+++ b/chromium/content/renderer/web_ui_runner.cc
@@ -4,11 +4,10 @@
#include "content/renderer/web_ui_runner.h"
+#include "content/public/renderer/render_frame.h"
#include "gin/modules/module_registry.h"
#include "gin/per_context_data.h"
#include "gin/public/context_holder.h"
-#include "mojo/bindings/js/core.h"
-#include "mojo/bindings/js/support.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
@@ -36,19 +35,6 @@ WebUIRunner::WebUIRunner(blink::WebFrame* frame,
WebUIRunner::~WebUIRunner() {
}
-void WebUIRunner::RegisterBuiltinModules() {
- gin::ModuleRegistry* registry =
- gin::ModuleRegistry::From(context_holder_->context());
- registry->AddBuiltinModule(context_holder_->isolate(),
- mojo::js::Core::kModuleName,
- mojo::js::Core::GetModule(
- context_holder_->isolate()));
- registry->AddBuiltinModule(context_holder_->isolate(),
- mojo::js::Support::kModuleName,
- mojo::js::Support::GetModule(
- context_holder_->isolate()));
-}
-
void WebUIRunner::Run(const std::string& source,
const std::string& resource_name) {
frame_->executeScript(
diff --git a/chromium/content/renderer/web_ui_runner.h b/chromium/content/renderer/web_ui_runner.h
index 4af80134d48..2f17ab59deb 100644
--- a/chromium/content/renderer/web_ui_runner.h
+++ b/chromium/content/renderer/web_ui_runner.h
@@ -18,18 +18,16 @@ class WebUIRunner : public gin::Runner {
public:
// Does not take ownership of ContextHolder.
WebUIRunner(blink::WebFrame* frame, gin::ContextHolder* context_holder);
- virtual ~WebUIRunner();
-
- void RegisterBuiltinModules();
+ ~WebUIRunner() override;
// Runner overrides:
- virtual void Run(const std::string& source,
- const std::string& resource_name) OVERRIDE;
- virtual v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
- v8::Handle<v8::Value> receiver,
- int argc,
- v8::Handle<v8::Value> argv[]) OVERRIDE;
- virtual gin::ContextHolder* GetContextHolder() OVERRIDE;
+ void Run(const std::string& source,
+ const std::string& resource_name) override;
+ v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
+ v8::Handle<v8::Value> receiver,
+ int argc,
+ v8::Handle<v8::Value> argv[]) override;
+ gin::ContextHolder* GetContextHolder() override;
private:
// Frame to execute script in.
diff --git a/chromium/content/renderer/web_ui_setup_impl.cc b/chromium/content/renderer/web_ui_setup_impl.cc
deleted file mode 100644
index 7cb7cdaa996..00000000000
--- a/chromium/content/renderer/web_ui_setup_impl.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 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 "content/renderer/web_ui_setup_impl.h"
-
-#include "content/public/renderer/render_view.h"
-#include "content/renderer/web_ui_mojo.h"
-
-namespace content {
-
-// static
-void WebUISetupImpl::Bind(mojo::ScopedMessagePipeHandle handle) {
- mojo::BindToPipe(new WebUISetupImpl(), handle.Pass());
-}
-
-void WebUISetupImpl::OnConnectionError() {
- delete this;
-}
-
-void WebUISetupImpl::SetWebUIHandle(
- int32 view_routing_id,
- mojo::ScopedMessagePipeHandle web_ui_handle) {
- RenderView* render_view = RenderView::FromRoutingID(view_routing_id);
- if (!render_view)
- return;
- WebUIMojo* web_ui_mojo = WebUIMojo::Get(render_view);
- if (!web_ui_mojo)
- return;
- web_ui_mojo->SetBrowserHandle(web_ui_handle.Pass());
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/web_ui_setup_impl.h b/chromium/content/renderer/web_ui_setup_impl.h
deleted file mode 100644
index 65234544f02..00000000000
--- a/chromium/content/renderer/web_ui_setup_impl.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 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 CONTENT_RENDERER_WEB_UI_SETUP_IMPL_H_
-#define CONTENT_RENDERER_WEB_UI_SETUP_IMPL_H_
-
-#include "base/basictypes.h"
-#include "content/common/web_ui_setup.mojom.h"
-
-namespace content {
-
-class WebUISetupImpl : public mojo::InterfaceImpl<WebUISetup> {
- public:
- static void Bind(mojo::ScopedMessagePipeHandle handle);
-
- private:
- WebUISetupImpl() {}
-
- virtual void OnConnectionError() OVERRIDE;
-
- // WebUISetup methods:
- virtual void SetWebUIHandle(
- int32_t view_routing_id,
- mojo::ScopedMessagePipeHandle web_ui_handle) OVERRIDE;
-
- DISALLOW_COPY_AND_ASSIGN(WebUISetupImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_WEB_UI_SETUP_IMPL_H_
diff --git a/chromium/content/renderer/webclipboard_impl.cc b/chromium/content/renderer/webclipboard_impl.cc
index 663d6f064f2..e248c517a06 100644
--- a/chromium/content/renderer/webclipboard_impl.cc
+++ b/chromium/content/renderer/webclipboard_impl.cc
@@ -156,7 +156,7 @@ void WebClipboardImpl::writeImage(const WebImage& image,
if (!image.isNull()) {
const SkBitmap& bitmap = image.getSkBitmap();
// WriteBitmapFromPixels expects 32-bit data.
- DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config);
+ DCHECK_EQ(bitmap.colorType(), kN32_SkColorType);
SkAutoLockPixels locked(bitmap);
void *pixels = bitmap.getPixels();
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
index 80c2106408c..69c2e984c1f 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -26,8 +26,8 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
virtual ~WebGraphicsContext3DProviderImpl();
// WebGraphicsContext3DProvider implementation.
- virtual blink::WebGraphicsContext3D* context3d() OVERRIDE;
- virtual GrContext* grContext() OVERRIDE;
+ virtual blink::WebGraphicsContext3D* context3d() override;
+ virtual GrContext* grContext() override;
private:
scoped_refptr<webkit::gpu::ContextProviderWebContext> provider_;
diff --git a/chromium/content/renderer/webscrollbarbehavior_impl_gtkoraura.cc b/chromium/content/renderer/webscrollbarbehavior_impl_gtkoraura.cc
index e9d77bb3f50..8dfa99846be 100644
--- a/chromium/content/renderer/webscrollbarbehavior_impl_gtkoraura.cc
+++ b/chromium/content/renderer/webscrollbarbehavior_impl_gtkoraura.cc
@@ -31,17 +31,31 @@ bool WebScrollbarBehaviorImpl::shouldSnapBackToDragOrigin(
// guessing/extrapolation.
static const int kOffEndMultiplier = 3;
static const int kOffSideMultiplier = 8;
+ static const int kDefaultWinScrollbarThickness = 17;
// Find the rect within which we shouldn't snap, by expanding the track rect
// in both dimensions.
gfx::Rect noSnapRect(scrollbarRect);
- const int thickness = isHorizontal ? noSnapRect.height() : noSnapRect.width();
+ int thickness = isHorizontal ? noSnapRect.height() : noSnapRect.width();
+ // Even if the platform's scrollbar is narrower than the default Windows one,
+ // we still want to provide at least as much slop area, since a slightly
+ // narrower scrollbar doesn't necessarily imply that users will drag
+ // straighter.
+ thickness = std::max(thickness, kDefaultWinScrollbarThickness);
noSnapRect.Inset(
(isHorizontal ? kOffEndMultiplier : kOffSideMultiplier) * -thickness,
(isHorizontal ? kOffSideMultiplier : kOffEndMultiplier) * -thickness);
- // We should snap iff the event is outside our calculated rect.
+ // On most platforms, we should snap iff the event is outside our calculated
+ // rect. On Linux, however, we should not snap for events off the ends, but
+ // not the sides, of the rect.
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ return isHorizontal ?
+ (eventPoint.y < noSnapRect.y() || eventPoint.y >= noSnapRect.bottom()) :
+ (eventPoint.x < noSnapRect.x() || eventPoint.x >= noSnapRect.right());
+#else
return !noSnapRect.Contains(eventPoint);
+#endif
}
} // namespace content
diff --git a/chromium/content/renderer/websharedworker_proxy.h b/chromium/content/renderer/websharedworker_proxy.h
index 0a07489ffcb..ac02826ef55 100644
--- a/chromium/content/renderer/websharedworker_proxy.h
+++ b/chromium/content/renderer/websharedworker_proxy.h
@@ -39,7 +39,7 @@ class WebSharedWorkerProxy : public blink::WebSharedWorkerConnector,
private:
// IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ bool OnMessageReceived(const IPC::Message& message) override;
// Disconnects the worker (stops listening for incoming messages).
void Disconnect();
diff --git a/chromium/content/utility/BUILD.gn b/chromium/content/utility/BUILD.gn
index 1cc0ead94d7..5a23de87f05 100644
--- a/chromium/content/utility/BUILD.gn
+++ b/chromium/content/utility/BUILD.gn
@@ -3,6 +3,10 @@
# found in the LICENSE file.
source_set("utility") {
+ # Only the public target should depend on this. All other targets (even
+ # internal content ones) should depend on the public one.
+ visibility = [ "//content/public/utility:utility_sources" ]
+
sources = [
"in_process_utility_thread.cc",
"in_process_utility_thread.h",
@@ -16,8 +20,10 @@ source_set("utility") {
deps = [
"//base",
"//content:export",
+ "//content/public/child:child_sources",
+ "//content/public/common:common_sources",
"//courgette:courgette_lib",
- "//mojo/public/interfaces/service_provider",
+ "//mojo/public/interfaces/application",
"//third_party/WebKit/public:blink_headers",
]
}
diff --git a/chromium/content/utility/in_process_utility_thread.cc b/chromium/content/utility/in_process_utility_thread.cc
index 8859e518216..a91bac58418 100644
--- a/chromium/content/utility/in_process_utility_thread.cc
+++ b/chromium/content/utility/in_process_utility_thread.cc
@@ -18,7 +18,10 @@ InProcessUtilityThread::InProcessUtilityThread(const std::string& channel_id)
}
InProcessUtilityThread::~InProcessUtilityThread() {
+ // Wait till in-process utility thread finishes clean up.
+ bool previous_value = base::ThreadRestrictions::SetIOAllowed(true);
Stop();
+ base::ThreadRestrictions::SetIOAllowed(previous_value);
}
void InProcessUtilityThread::Init() {
diff --git a/chromium/content/utility/in_process_utility_thread.h b/chromium/content/utility/in_process_utility_thread.h
index 7f4c732667b..00c71a1dd28 100644
--- a/chromium/content/utility/in_process_utility_thread.h
+++ b/chromium/content/utility/in_process_utility_thread.h
@@ -17,12 +17,12 @@ class ChildProcess;
class InProcessUtilityThread : public base::Thread {
public:
InProcessUtilityThread(const std::string& channel_id);
- virtual ~InProcessUtilityThread();
+ ~InProcessUtilityThread() override;
private:
// base::Thread implementation:
- virtual void Init() OVERRIDE;
- virtual void CleanUp() OVERRIDE;
+ void Init() override;
+ void CleanUp() override;
void InitInternal();
diff --git a/chromium/content/utility/utility_main.cc b/chromium/content/utility/utility_main.cc
index a57ea9c88e9..1be9918d823 100644
--- a/chromium/content/utility/utility_main.cc
+++ b/chromium/content/utility/utility_main.cc
@@ -30,7 +30,8 @@ int UtilityMain(const MainFunctionParams& parameters) {
// Initializes the sandbox before any threads are created.
// TODO(jorgelo): move this after GTK initialization when we enable a strict
// Seccomp-BPF policy.
- LinuxSandbox::InitializeSandbox();
+ if (parameters.zygote_child)
+ LinuxSandbox::InitializeSandbox();
#endif
ChildProcess utility_process;
diff --git a/chromium/content/utility/utility_thread_impl.cc b/chromium/content/utility/utility_thread_impl.cc
index c94312f3787..32f9814ee03 100644
--- a/chromium/content/utility/utility_thread_impl.cc
+++ b/chromium/content/utility/utility_thread_impl.cc
@@ -7,18 +7,21 @@
#include <stddef.h>
#include "base/command_line.h"
-#include "base/files/file_path.h"
#include "base/memory/scoped_vector.h"
#include "content/child/blink_platform_impl.h"
#include "content/child/child_process.h"
#include "content/common/child_process_messages.h"
-#include "content/common/plugin_list.h"
#include "content/common/utility_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/utility/content_utility_client.h"
#include "ipc/ipc_sync_channel.h"
#include "third_party/WebKit/public/web/WebKit.h"
+#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
+#include "base/files/file_path.h"
+#include "content/common/plugin_list.h"
+#endif
+
namespace content {
namespace {
@@ -37,7 +40,7 @@ UtilityThreadImpl::UtilityThreadImpl() : single_process_(false) {
}
UtilityThreadImpl::UtilityThreadImpl(const std::string& channel_name)
- : ChildThread(channel_name),
+ : ChildThread(Options(channel_name, false)),
single_process_(true) {
Init();
}
@@ -91,8 +94,8 @@ void UtilityThreadImpl::Init() {
// we run the utility thread on separate thread. This means that if any code
// needs WebKit initialized in the utility process, they need to have
// another path to support single process mode.
- webkit_platform_support_.reset(new BlinkPlatformImpl);
- blink::initialize(webkit_platform_support_.get());
+ blink_platform_impl_.reset(new BlinkPlatformImpl);
+ blink::initialize(blink_platform_impl_.get());
}
GetContentClient()->utility()->UtilityThreadStarted();
}
@@ -105,9 +108,9 @@ bool UtilityThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(UtilityThreadImpl, msg)
IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Started, OnBatchModeStarted)
IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Finished, OnBatchModeFinished)
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER(UtilityMsg_LoadPlugins, OnLoadPlugins)
-#endif // OS_POSIX
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -122,7 +125,7 @@ void UtilityThreadImpl::OnBatchModeFinished() {
ReleaseProcessIfNeeded();
}
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
void UtilityThreadImpl::OnLoadPlugins(
const std::vector<base::FilePath>& plugin_paths) {
PluginList* plugin_list = PluginList::Singleton();
diff --git a/chromium/content/utility/utility_thread_impl.h b/chromium/content/utility/utility_thread_impl.h
index b4b50379a09..5b186fc21cf 100644
--- a/chromium/content/utility/utility_thread_impl.h
+++ b/chromium/content/utility/utility_thread_impl.h
@@ -28,29 +28,29 @@ class UtilityThreadImpl : public UtilityThread,
UtilityThreadImpl();
// Constructor that's used when running in single process mode.
explicit UtilityThreadImpl(const std::string& channel_name);
- virtual ~UtilityThreadImpl();
- virtual void Shutdown() OVERRIDE;
+ ~UtilityThreadImpl() override;
+ void Shutdown() override;
- virtual bool Send(IPC::Message* msg) OVERRIDE;
- virtual void ReleaseProcessIfNeeded() OVERRIDE;
+ bool Send(IPC::Message* msg) override;
+ void ReleaseProcessIfNeeded() override;
#if defined(OS_WIN)
- virtual void PreCacheFont(const LOGFONT& log_font) OVERRIDE;
- virtual void ReleaseCachedFonts() OVERRIDE;
+ virtual void PreCacheFont(const LOGFONT& log_font) override;
+ virtual void ReleaseCachedFonts() override;
#endif
private:
void Init();
// ChildThread implementation.
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message& msg) override;
// IPC message handlers.
void OnBatchModeStarted();
void OnBatchModeFinished();
-#if defined(OS_POSIX)
+#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
void OnLoadPlugins(const std::vector<base::FilePath>& plugin_paths);
-#endif // OS_POSIX
+#endif
// True when we're running in batch mode.
bool batch_mode_;
@@ -58,7 +58,7 @@ class UtilityThreadImpl : public UtilityThread,
// True if running in single process mode.
bool single_process_;
- scoped_ptr<BlinkPlatformImpl> webkit_platform_support_;
+ scoped_ptr<BlinkPlatformImpl> blink_platform_impl_;
DISALLOW_COPY_AND_ASSIGN(UtilityThreadImpl);
};
diff --git a/chromium/content/worker/BUILD.gn b/chromium/content/worker/BUILD.gn
deleted file mode 100644
index 23cfcffd9dc..00000000000
--- a/chromium/content/worker/BUILD.gn
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2014 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.
-
-source_set("worker") {
- visibility = "//content/*"
- sources = [
- "websharedworker_stub.cc",
- "websharedworker_stub.h",
- "websharedworkerclient_proxy.cc",
- "websharedworkerclient_proxy.h",
- "worker_main.cc",
- "shared_worker_permission_client_proxy.cc",
- "shared_worker_permission_client_proxy.h",
- "worker_thread.cc",
- "worker_thread.h",
- "worker_webapplicationcachehost_impl.cc",
- "worker_webapplicationcachehost_impl.h",
- "worker_webkitplatformsupport_impl.cc",
- "worker_webkitplatformsupport_impl.h",
- ]
-
- configs += [ "//content:content_implementation" ]
-
- deps = [
- "//base",
- "//mojo/public/interfaces/service_provider",
- "//skia",
- #"//third_party/WebKit/public:blink", TODO(GYP)
- # TODO(GYP) remove this when blink is enabled:
- "//third_party/WebKit/public:blink_headers",
- ]
-}
-
diff --git a/chromium/content/worker/DEPS b/chromium/content/worker/DEPS
deleted file mode 100644
index 6e9ea80333c..00000000000
--- a/chromium/content/worker/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
- "+content/child",
- "+sandbox/win/src",
- "+v8/include/v8.h",
-]
-
diff --git a/chromium/content/worker/OWNERS b/chromium/content/worker/OWNERS
deleted file mode 100644
index 61fc3fd49ea..00000000000
--- a/chromium/content/worker/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-atwilson@chromium.org
-kinuko@chromium.org
-horo@chromium.org
diff --git a/chromium/content/worker/shared_worker_permission_client_proxy.cc b/chromium/content/worker/shared_worker_permission_client_proxy.cc
deleted file mode 100644
index a7e0671bdac..00000000000
--- a/chromium/content/worker/shared_worker_permission_client_proxy.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 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 "content/worker/shared_worker_permission_client_proxy.h"
-
-#include "content/child/thread_safe_sender.h"
-#include "content/common/worker_messages.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "url/gurl.h"
-
-namespace content {
-
-SharedWorkerPermissionClientProxy::SharedWorkerPermissionClientProxy(
- const GURL& origin_url,
- bool is_unique_origin,
- int routing_id,
- ThreadSafeSender* thread_safe_sender)
- : origin_url_(origin_url),
- is_unique_origin_(is_unique_origin),
- routing_id_(routing_id),
- thread_safe_sender_(thread_safe_sender) {
-}
-
-SharedWorkerPermissionClientProxy::~SharedWorkerPermissionClientProxy() {
-}
-
-bool SharedWorkerPermissionClientProxy::allowDatabase(
- const blink::WebString& name,
- const blink::WebString& display_name,
- unsigned long estimated_size) {
- if (is_unique_origin_)
- return false;
- bool result = false;
- thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowDatabase(
- routing_id_, origin_url_, name, display_name,
- estimated_size, &result));
- return result;
-}
-
-bool SharedWorkerPermissionClientProxy::requestFileSystemAccessSync() {
- if (is_unique_origin_)
- return false;
- bool result = false;
- thread_safe_sender_->Send(
- new WorkerProcessHostMsg_RequestFileSystemAccessSync(
- routing_id_, origin_url_, &result));
- return result;
-}
-
-bool SharedWorkerPermissionClientProxy::allowIndexedDB(
- const blink::WebString& name) {
- if (is_unique_origin_)
- return false;
- bool result = false;
- thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowIndexedDB(
- routing_id_, origin_url_, name, &result));
- return result;
-}
-
-} // namespace content
diff --git a/chromium/content/worker/shared_worker_permission_client_proxy.h b/chromium/content/worker/shared_worker_permission_client_proxy.h
deleted file mode 100644
index 0240738347f..00000000000
--- a/chromium/content/worker/shared_worker_permission_client_proxy.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2013 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 CONTENT_WORKER_SHARED_WORKER_PERMISSION_CLIENT_PROXY_H_
-#define CONTENT_WORKER_SHARED_WORKER_PERMISSION_CLIENT_PROXY_H_
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-#include "third_party/WebKit/public/web/WebWorkerPermissionClientProxy.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class ThreadSafeSender;
-
-// This proxy is created on the main renderer thread then passed onto
-// the blink's worker thread.
-class SharedWorkerPermissionClientProxy
- : public blink::WebWorkerPermissionClientProxy {
- public:
- SharedWorkerPermissionClientProxy(
- const GURL& origin_url,
- bool is_unique_origin,
- int routing_id,
- ThreadSafeSender* thread_safe_sender);
- virtual ~SharedWorkerPermissionClientProxy();
-
- // WebWorkerPermissionClientProxy overrides.
- virtual bool allowDatabase(const blink::WebString& name,
- const blink::WebString& display_name,
- unsigned long estimated_size);
- virtual bool requestFileSystemAccessSync();
- virtual bool allowIndexedDB(const blink::WebString& name);
-
- private:
- const GURL origin_url_;
- const bool is_unique_origin_;
- const int routing_id_;
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedWorkerPermissionClientProxy);
-};
-
-} // namespace content
-
-#endif // CONTENT_WORKER_SHARED_WORKER_PERMISSION_CLIENT_PROXY_H_
diff --git a/chromium/content/worker/websharedworker_stub.cc b/chromium/content/worker/websharedworker_stub.cc
deleted file mode 100644
index b33e707971a..00000000000
--- a/chromium/content/worker/websharedworker_stub.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2012 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 "content/worker/websharedworker_stub.h"
-
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "content/child/child_process.h"
-#include "content/child/child_thread.h"
-#include "content/child/fileapi/file_system_dispatcher.h"
-#include "content/child/shared_worker_devtools_agent.h"
-#include "content/child/webmessageportchannel_impl.h"
-#include "content/common/worker_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/worker/worker_thread.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebSharedWorker.h"
-
-namespace content {
-
-WebSharedWorkerStub::WebSharedWorkerStub(
- const GURL& url,
- const base::string16& name,
- const base::string16& content_security_policy,
- blink::WebContentSecurityPolicyType security_policy_type,
- bool pause_on_start,
- int route_id)
- : route_id_(route_id),
- client_(route_id, this),
- running_(false),
- url_(url) {
-
- WorkerThread* worker_thread = WorkerThread::current();
- DCHECK(worker_thread);
- worker_thread->AddWorkerStub(this);
- // Start processing incoming IPCs for this worker.
- worker_thread->GetRouter()->AddRoute(route_id_, this);
-
- // TODO(atwilson): Add support for NaCl when they support MessagePorts.
- impl_ = blink::WebSharedWorker::create(client());
- if (pause_on_start) {
- // Pause worker context when it starts and wait until either DevTools client
- // is attached or explicit resume notification is received.
- impl_->pauseWorkerContextOnStart();
- }
-
- worker_devtools_agent_.reset(new SharedWorkerDevToolsAgent(route_id, impl_));
- client()->set_devtools_agent(worker_devtools_agent_.get());
- impl_->startWorkerContext(url_, name,
- content_security_policy, security_policy_type);
-}
-
-WebSharedWorkerStub::~WebSharedWorkerStub() {
- impl_->clientDestroyed();
- WorkerThread* worker_thread = WorkerThread::current();
- DCHECK(worker_thread);
- worker_thread->RemoveWorkerStub(this);
- worker_thread->GetRouter()->RemoveRoute(route_id_);
-}
-
-void WebSharedWorkerStub::Shutdown() {
- // The worker has exited - free ourselves and the client.
- delete this;
-}
-
-void WebSharedWorkerStub::EnsureWorkerContextTerminates() {
- client_.EnsureWorkerContextTerminates();
-}
-
-bool WebSharedWorkerStub::OnMessageReceived(const IPC::Message& message) {
- if (worker_devtools_agent_->OnMessageReceived(message))
- return true;
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerStub, message)
- IPC_MESSAGE_HANDLER(WorkerMsg_TerminateWorkerContext,
- OnTerminateWorkerContext)
- IPC_MESSAGE_HANDLER(WorkerMsg_Connect, OnConnect)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void WebSharedWorkerStub::OnChannelError() {
- OnTerminateWorkerContext();
-}
-
-const GURL& WebSharedWorkerStub::url() {
- return url_;
-}
-
-void WebSharedWorkerStub::OnConnect(int sent_message_port_id, int routing_id) {
- WebMessagePortChannelImpl* channel =
- new WebMessagePortChannelImpl(routing_id,
- sent_message_port_id,
- base::MessageLoopProxy::current().get());
- if (running_) {
- impl_->connect(channel);
- WorkerThread::current()->Send(
- new WorkerHostMsg_WorkerConnected(channel->message_port_id(),
- route_id_));
- } else {
- // If two documents try to load a SharedWorker at the same time, the
- // WorkerMsg_Connect for one of the documents can come in before the
- // worker is started. Just queue up the connect and deliver it once the
- // worker starts.
- pending_channels_.push_back(channel);
- }
-}
-
-void WebSharedWorkerStub::OnTerminateWorkerContext() {
- running_ = false;
- // Call the client to make sure context exits.
- EnsureWorkerContextTerminates();
- // This may call "delete this" via WorkerScriptLoadFailed and Shutdown.
- impl_->terminateWorkerContext();
-}
-
-void WebSharedWorkerStub::WorkerScriptLoaded() {
- running_ = true;
- // Process any pending connections.
- for (PendingChannelList::const_iterator iter = pending_channels_.begin();
- iter != pending_channels_.end();
- ++iter) {
- impl_->connect(*iter);
- WorkerThread::current()->Send(
- new WorkerHostMsg_WorkerConnected((*iter)->message_port_id(),
- route_id_));
- }
- pending_channels_.clear();
-}
-
-void WebSharedWorkerStub::WorkerScriptLoadFailed() {
- for (PendingChannelList::const_iterator iter = pending_channels_.begin();
- iter != pending_channels_.end();
- ++iter) {
- blink::WebMessagePortChannel* channel = *iter;
- channel->destroy();
- }
- pending_channels_.clear();
- Shutdown();
-}
-
-} // namespace content
diff --git a/chromium/content/worker/websharedworker_stub.h b/chromium/content/worker/websharedworker_stub.h
deleted file mode 100644
index c1a6287bfb7..00000000000
--- a/chromium/content/worker/websharedworker_stub.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
-#define CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/child/scoped_child_process_reference.h"
-#include "content/worker/websharedworkerclient_proxy.h"
-#include "content/worker/worker_webapplicationcachehost_impl.h"
-#include "ipc/ipc_listener.h"
-#include "third_party/WebKit/public/web/WebSharedWorker.h"
-#include "url/gurl.h"
-
-namespace blink {
-class WebSharedWorker;
-}
-
-namespace content {
-
-class SharedWorkerDevToolsAgent;
-class WebMessagePortChannelImpl;
-
-// This class creates a WebSharedWorker, and translates incoming IPCs to the
-// appropriate WebSharedWorker APIs.
-class WebSharedWorkerStub : public IPC::Listener {
- public:
- WebSharedWorkerStub(const GURL& url,
- const base::string16& name,
- const base::string16& content_security_policy,
- blink::WebContentSecurityPolicyType security_policy_type,
- bool pause_on_start,
- int route_id);
-
- // IPC::Listener implementation.
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
-
- // Invoked when the WebSharedWorkerClientProxy is shutting down.
- void Shutdown();
-
- void WorkerScriptLoaded();
- void WorkerScriptLoadFailed();
-
- // Called after terminating the worker context to make sure that the worker
- // actually terminates (is not stuck in an infinite loop).
- void EnsureWorkerContextTerminates();
-
- WebSharedWorkerClientProxy* client() { return &client_; }
-
- // Returns the script url of this worker.
- const GURL& url();
-
-
- private:
- virtual ~WebSharedWorkerStub();
-
- void OnConnect(int sent_message_port_id, int routing_id);
-
- void OnTerminateWorkerContext();
-
- ScopedChildProcessReference process_ref_;
-
- int route_id_;
-
- // WebSharedWorkerClient that responds to outgoing API calls
- // from the worker object.
- WebSharedWorkerClientProxy client_;
-
- blink::WebSharedWorker* impl_;
- bool running_;
- GURL url_;
- scoped_ptr<SharedWorkerDevToolsAgent> worker_devtools_agent_;
-
- typedef std::vector<WebMessagePortChannelImpl*> PendingChannelList;
- PendingChannelList pending_channels_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSharedWorkerStub);
-};
-
-} // namespace content
-
-#endif // CONTENT_WORKER_WEBSHAREDWORKER_STUB_H_
diff --git a/chromium/content/worker/websharedworkerclient_proxy.cc b/chromium/content/worker/websharedworkerclient_proxy.cc
deleted file mode 100644
index 486479a30d3..00000000000
--- a/chromium/content/worker/websharedworkerclient_proxy.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2012 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 "content/worker/websharedworkerclient_proxy.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "content/child/shared_worker_devtools_agent.h"
-#include "content/child/webmessageportchannel_impl.h"
-#include "content/common/worker_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/worker/shared_worker_permission_client_proxy.h"
-#include "content/worker/websharedworker_stub.h"
-#include "content/worker/worker_thread.h"
-#include "content/worker/worker_webapplicationcachehost_impl.h"
-#include "ipc/ipc_logging.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-
-using blink::WebApplicationCacheHost;
-using blink::WebFrame;
-using blink::WebMessagePortChannel;
-using blink::WebMessagePortChannelArray;
-using blink::WebSecurityOrigin;
-using blink::WebString;
-using blink::WebWorker;
-using blink::WebSharedWorkerClient;
-
-namespace content {
-
-// How long to wait for worker to finish after it's been told to terminate.
-#define kMaxTimeForRunawayWorkerSeconds 3
-
-WebSharedWorkerClientProxy::WebSharedWorkerClientProxy(
- int route_id, WebSharedWorkerStub* stub)
- : route_id_(route_id),
- appcache_host_id_(0),
- stub_(stub),
- weak_factory_(this),
- devtools_agent_(NULL),
- app_cache_host_(NULL) {
-}
-
-WebSharedWorkerClientProxy::~WebSharedWorkerClientProxy() {
-}
-
-void WebSharedWorkerClientProxy::workerContextClosed() {
- Send(new WorkerHostMsg_WorkerContextClosed(route_id_));
-}
-
-void WebSharedWorkerClientProxy::workerContextDestroyed() {
- Send(new WorkerHostMsg_WorkerContextDestroyed(route_id_));
- // Tell the stub that the worker has shutdown - frees this object.
- if (stub_)
- stub_->Shutdown();
-}
-
-void WebSharedWorkerClientProxy::workerScriptLoaded() {
- Send(new WorkerHostMsg_WorkerScriptLoaded(route_id_));
- if (stub_)
- stub_->WorkerScriptLoaded();
-}
-
-void WebSharedWorkerClientProxy::workerScriptLoadFailed() {
- Send(new WorkerHostMsg_WorkerScriptLoadFailed(route_id_));
- if (stub_)
- stub_->WorkerScriptLoadFailed();
-}
-
-void WebSharedWorkerClientProxy::selectAppCacheID(long long app_cache_id) {
- if (app_cache_host_) {
- // app_cache_host_ could become stale as it's owned by blink's
- // DocumentLoader. This method is assumed to be called while it's valid.
- app_cache_host_->backend()->SelectCacheForSharedWorker(
- app_cache_host_->host_id(),
- app_cache_id);
- }
-}
-
-blink::WebNotificationPresenter*
-WebSharedWorkerClientProxy::notificationPresenter() {
- // TODO(johnnyg): Notifications are not yet hooked up to workers.
- // Coming soon.
- NOTREACHED();
- return NULL;
-}
-
-WebApplicationCacheHost* WebSharedWorkerClientProxy::createApplicationCacheHost(
- blink::WebApplicationCacheHostClient* client) {
- DCHECK(!app_cache_host_);
- app_cache_host_ = new WorkerWebApplicationCacheHostImpl(client);
- // Remember the id of the instance we create so we have access to that
- // value when creating nested dedicated workers in createWorker.
- appcache_host_id_ = app_cache_host_->host_id();
- return app_cache_host_;
-}
-
-blink::WebWorkerPermissionClientProxy*
-WebSharedWorkerClientProxy::createWorkerPermissionClientProxy(
- const blink::WebSecurityOrigin& origin) {
- return new SharedWorkerPermissionClientProxy(
- GURL(origin.toString()), origin.isUnique(), route_id_,
- ChildThread::current()->thread_safe_sender());
-}
-
-void WebSharedWorkerClientProxy::dispatchDevToolsMessage(
- const WebString& message) {
- if (devtools_agent_)
- devtools_agent_->SendDevToolsMessage(message);
-}
-
-void WebSharedWorkerClientProxy::saveDevToolsAgentState(
- const blink::WebString& state) {
- if (devtools_agent_)
- devtools_agent_->SaveDevToolsAgentState(state);
-}
-
-bool WebSharedWorkerClientProxy::Send(IPC::Message* message) {
- return WorkerThread::current()->Send(message);
-}
-
-void WebSharedWorkerClientProxy::EnsureWorkerContextTerminates() {
- // This shuts down the process cleanly from the perspective of the browser
- // process, and avoids the crashed worker infobar from appearing to the new
- // page. It's ok to post several of theese, because the first executed task
- // will exit the message loop and subsequent ones won't be executed.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&WebSharedWorkerClientProxy::workerContextDestroyed,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(kMaxTimeForRunawayWorkerSeconds));
-}
-
-} // namespace content
diff --git a/chromium/content/worker/websharedworkerclient_proxy.h b/chromium/content/worker/websharedworkerclient_proxy.h
deleted file mode 100644
index beb3086d756..00000000000
--- a/chromium/content/worker/websharedworkerclient_proxy.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_WORKER_WEBWORKERCLIENT_PROXY_H_
-#define CONTENT_WORKER_WEBWORKERCLIENT_PROXY_H_
-
-#include "base/basictypes.h"
-#include "base/memory/weak_ptr.h"
-#include "ipc/ipc_channel.h"
-#include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
-
-namespace blink {
-class WebApplicationCacheHost;
-class WebApplicationCacheHostClient;
-class WebFrame;
-class WebSecurityOrigin;
-}
-
-namespace content {
-
-class SharedWorkerDevToolsAgent;
-class WebSharedWorkerStub;
-class WorkerWebApplicationCacheHostImpl;
-
-// This class receives IPCs from the renderer and calls the WebCore::Worker
-// implementation (after the data types have been converted by glue code). It
-// is also called by the worker code and converts these function calls into
-// IPCs that are sent to the renderer, where they're converted back to function
-// calls by WebWorkerProxy.
-class WebSharedWorkerClientProxy : public blink::WebSharedWorkerClient {
- public:
- WebSharedWorkerClientProxy(int route_id, WebSharedWorkerStub* stub);
- virtual ~WebSharedWorkerClientProxy();
-
- // WebSharedWorkerClient implementation.
- virtual void workerContextClosed();
- virtual void workerContextDestroyed();
- virtual void workerScriptLoaded();
- virtual void workerScriptLoadFailed();
- virtual void selectAppCacheID(long long app_cache_id);
-
- virtual blink::WebNotificationPresenter* notificationPresenter();
-
- virtual blink::WebApplicationCacheHost* createApplicationCacheHost(
- blink::WebApplicationCacheHostClient* client);
- virtual blink::WebWorkerPermissionClientProxy*
- createWorkerPermissionClientProxy(
- const blink::WebSecurityOrigin& origin);
-
- virtual void dispatchDevToolsMessage(const blink::WebString&);
- virtual void saveDevToolsAgentState(const blink::WebString&);
-
- void EnsureWorkerContextTerminates();
-
- void set_devtools_agent(SharedWorkerDevToolsAgent* devtools_agent) {
- devtools_agent_ = devtools_agent;
- }
-
- private:
- bool Send(IPC::Message* message);
-
- int route_id_;
- int appcache_host_id_;
- WebSharedWorkerStub* stub_;
- base::WeakPtrFactory<WebSharedWorkerClientProxy> weak_factory_;
- SharedWorkerDevToolsAgent* devtools_agent_;
- WorkerWebApplicationCacheHostImpl* app_cache_host_;
-
- DISALLOW_COPY_AND_ASSIGN(WebSharedWorkerClientProxy);
-};
-
-} // namespace content
-
-#endif // CONTENT_WORKER_WEBWORKERCLIENT_PROXY_H_
diff --git a/chromium/content/worker/worker_main.cc b/chromium/content/worker/worker_main.cc
deleted file mode 100644
index 8cc8ed0f220..00000000000
--- a/chromium/content/worker/worker_main.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2011 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/base_switches.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/timer/hi_res_timer_manager.h"
-#include "content/child/child_process.h"
-#include "content/common/sandbox_linux/sandbox_linux.h"
-#include "content/public/common/main_function_params.h"
-#include "content/public/common/sandbox_init.h"
-#include "content/worker/worker_thread.h"
-
-#if defined(OS_WIN)
-#include "sandbox/win/src/sandbox.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "content/common/sandbox_mac.h"
-#endif
-
-namespace content {
-
-// Mainline routine for running as the worker process.
-int WorkerMain(const MainFunctionParams& parameters) {
- // The main message loop of the worker process.
- base::MessageLoop main_message_loop;
- base::PlatformThread::SetName("CrWorkerMain");
- base::debug::TraceLog::GetInstance()->SetProcessName("Shared Web Worker");
-
-#if defined(OS_WIN)
- sandbox::TargetServices* target_services =
- parameters.sandbox_info->target_services;
- if (!target_services)
- return false;
-
- // Cause advapi32 to load before the sandbox is turned on.
- unsigned int dummy_rand;
- rand_s(&dummy_rand);
- // Warm up language subsystems before the sandbox is turned on.
- ::GetUserDefaultLangID();
- ::GetUserDefaultLCID();
-
- target_services->LowerToken();
-#elif defined(OS_MACOSX)
- // Sandbox should already be activated at this point.
- CHECK(Sandbox::SandboxIsCurrentlyActive());
-#elif defined(OS_LINUX)
- // On Linux, the sandbox must be initialized early, before any thread is
- // created.
- LinuxSandbox::InitializeSandbox();
-#endif
-
- ChildProcess worker_process;
- worker_process.set_main_thread(new WorkerThread());
-
- base::HighResolutionTimerManager hi_res_timer_manager;
-
- const CommandLine& parsed_command_line = parameters.command_line;
- if (parsed_command_line.HasSwitch(switches::kWaitForDebugger)) {
- ChildProcess::WaitForDebugger("Worker");
- }
-
- // Load the accelerator table from the browser executable and tell the
- // message loop to use it when translating messages.
- base::MessageLoop::current()->Run();
-
- return 0;
-}
-
-} // namespace content
diff --git a/chromium/content/worker/worker_thread.cc b/chromium/content/worker/worker_thread.cc
deleted file mode 100644
index 687637ba9cc..00000000000
--- a/chromium/content/worker/worker_thread.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2012 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 "content/worker/worker_thread.h"
-
-#include "base/command_line.h"
-#include "base/lazy_instance.h"
-#include "base/threading/thread_local.h"
-#include "content/child/appcache/appcache_dispatcher.h"
-#include "content/child/appcache/appcache_frontend_impl.h"
-#include "content/child/db_message_filter.h"
-#include "content/child/indexed_db/indexed_db_message_filter.h"
-#include "content/child/runtime_features.h"
-#include "content/child/web_database_observer_impl.h"
-#include "content/common/child_process_messages.h"
-#include "content/common/worker_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/worker/websharedworker_stub.h"
-#include "content/worker/worker_webkitplatformsupport_impl.h"
-#include "ipc/ipc_sync_channel.h"
-#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
-#include "third_party/WebKit/public/web/WebDatabase.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-#include "v8/include/v8.h"
-
-using blink::WebRuntimeFeatures;
-
-namespace content {
-
-static base::LazyInstance<base::ThreadLocalPointer<WorkerThread> > lazy_tls =
- LAZY_INSTANCE_INITIALIZER;
-
-WorkerThread::WorkerThread() {
- lazy_tls.Pointer()->Set(this);
- webkit_platform_support_.reset(new WorkerWebKitPlatformSupportImpl(
- thread_safe_sender(),
- sync_message_filter(),
- quota_message_filter()));
-
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
- std::string flags(
- command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
- v8::V8::SetFlagsFromString(flags.c_str(), static_cast<int>(flags.size()));
- }
- SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
-
- blink::initialize(webkit_platform_support_.get());
-
- appcache_dispatcher_.reset(
- new AppCacheDispatcher(this, new AppCacheFrontendImpl()));
-
- db_message_filter_ = new DBMessageFilter();
- channel()->AddFilter(db_message_filter_.get());
-
- indexed_db_message_filter_ = new IndexedDBMessageFilter(
- thread_safe_sender());
- channel()->AddFilter(indexed_db_message_filter_->GetFilter());
-
-}
-
-void WorkerThread::OnShutdown() {
- // The worker process is to be shut down gracefully. Ask the browser
- // process to shut it down forcefully instead and wait on the message, so that
- // there are no races between threads when the process is shutting down.
- Send(new WorkerProcessHostMsg_ForceKillWorker());
-}
-
-WorkerThread::~WorkerThread() {
-}
-
-void WorkerThread::Shutdown() {
- ChildThread::Shutdown();
-
- if (webkit_platform_support_) {
- webkit_platform_support_->web_database_observer_impl()->
- WaitForAllDatabasesToClose();
- }
-
- // Shutdown in reverse of the initialization order.
- indexed_db_message_filter_ = NULL;
-
- channel()->RemoveFilter(db_message_filter_.get());
- db_message_filter_ = NULL;
-
- blink::shutdown();
- lazy_tls.Pointer()->Set(NULL);
-}
-
-WorkerThread* WorkerThread::current() {
- return lazy_tls.Pointer()->Get();
-}
-
-bool WorkerThread::OnControlMessageReceived(const IPC::Message& msg) {
- // Appcache messages are handled by a delegate.
- if (appcache_dispatcher_->OnMessageReceived(msg))
- return true;
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WorkerThread, msg)
- IPC_MESSAGE_HANDLER(WorkerProcessMsg_CreateWorker, OnCreateWorker)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-bool WorkerThread::OnMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WorkerThread, msg)
- IPC_MESSAGE_HANDLER(ChildProcessMsg_Shutdown, OnShutdown)
- IPC_MESSAGE_UNHANDLED(handled = ChildThread::OnMessageReceived(msg))
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void WorkerThread::OnCreateWorker(
- const WorkerProcessMsg_CreateWorker_Params& params) {
- // WebSharedWorkerStub own themselves.
- new WebSharedWorkerStub(
- params.url,
- params.name,
- params.content_security_policy,
- params.security_policy_type,
- params.pause_on_start,
- params.route_id);
-}
-
-// The browser process is likely dead. Terminate all workers.
-void WorkerThread::OnChannelError() {
- set_on_channel_error_called(true);
-
- for (WorkerStubsList::iterator it = worker_stubs_.begin();
- it != worker_stubs_.end(); ++it) {
- (*it)->OnChannelError();
- }
-}
-
-void WorkerThread::RemoveWorkerStub(WebSharedWorkerStub* stub) {
- worker_stubs_.erase(stub);
-}
-
-void WorkerThread::AddWorkerStub(WebSharedWorkerStub* stub) {
- worker_stubs_.insert(stub);
-}
-
-} // namespace content
diff --git a/chromium/content/worker/worker_thread.h b/chromium/content/worker/worker_thread.h
deleted file mode 100644
index 927cd9a2a61..00000000000
--- a/chromium/content/worker/worker_thread.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_WORKER_WORKER_THREAD_H_
-#define CONTENT_WORKER_WORKER_THREAD_H_
-
-#include <set>
-
-#include "content/child/child_thread.h"
-
-struct WorkerProcessMsg_CreateWorker_Params;
-
-namespace content {
-class AppCacheDispatcher;
-class DBMessageFilter;
-class IndexedDBMessageFilter;
-class WebSharedWorkerStub;
-class WorkerWebKitPlatformSupportImpl;
-
-class WorkerThread : public ChildThread {
- public:
- WorkerThread();
- virtual ~WorkerThread();
- virtual void Shutdown() OVERRIDE;
-
- // Returns the one worker thread.
- static WorkerThread* current();
-
- // Invoked from stub constructors/destructors. Stubs own themselves.
- void AddWorkerStub(WebSharedWorkerStub* stub);
- void RemoveWorkerStub(WebSharedWorkerStub* stub);
-
- AppCacheDispatcher* appcache_dispatcher() {
- return appcache_dispatcher_.get();
- }
-
- private:
- virtual bool OnControlMessageReceived(const IPC::Message& msg) OVERRIDE;
- virtual void OnChannelError() OVERRIDE;
- virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE;
-
- void OnCreateWorker(const WorkerProcessMsg_CreateWorker_Params& params);
- void OnShutdown();
-
- scoped_ptr<WorkerWebKitPlatformSupportImpl> webkit_platform_support_;
- scoped_ptr<AppCacheDispatcher> appcache_dispatcher_;
- scoped_refptr<DBMessageFilter> db_message_filter_;
- scoped_refptr<IndexedDBMessageFilter> indexed_db_message_filter_;
-
- typedef std::set<WebSharedWorkerStub*> WorkerStubsList;
- WorkerStubsList worker_stubs_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerThread);
-};
-
-} // namespace content
-
-#endif // CONTENT_WORKER_WORKER_THREAD_H_
diff --git a/chromium/content/worker/worker_webapplicationcachehost_impl.cc b/chromium/content/worker/worker_webapplicationcachehost_impl.cc
deleted file mode 100644
index d591bb443eb..00000000000
--- a/chromium/content/worker/worker_webapplicationcachehost_impl.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2011 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 "content/worker/worker_webapplicationcachehost_impl.h"
-
-#include "content/child/appcache/appcache_dispatcher.h"
-#include "content/worker/worker_thread.h"
-
-namespace content {
-
-WorkerWebApplicationCacheHostImpl::WorkerWebApplicationCacheHostImpl(
- blink::WebApplicationCacheHostClient* client)
- : WebApplicationCacheHostImpl(client,
- WorkerThread::current()->appcache_dispatcher()->backend_proxy()) {
-}
-
-void WorkerWebApplicationCacheHostImpl::willStartMainResourceRequest(
- blink::WebURLRequest&, const blink::WebApplicationCacheHost*) {
-}
-
-void WorkerWebApplicationCacheHostImpl::didReceiveResponseForMainResource(
- const blink::WebURLResponse&) {
-}
-
-void WorkerWebApplicationCacheHostImpl::didReceiveDataForMainResource(
- const char*, int) {
-}
-
-void WorkerWebApplicationCacheHostImpl::didFinishLoadingMainResource(
- bool) {
-}
-
-void WorkerWebApplicationCacheHostImpl::selectCacheWithoutManifest() {
-}
-
-bool WorkerWebApplicationCacheHostImpl::selectCacheWithManifest(
- const blink::WebURL&) {
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/worker/worker_webapplicationcachehost_impl.h b/chromium/content/worker/worker_webapplicationcachehost_impl.h
deleted file mode 100644
index e431e76eb2a..00000000000
--- a/chromium/content/worker/worker_webapplicationcachehost_impl.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 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_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
-#define CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
-
-#include "content/child/appcache/web_application_cache_host_impl.h"
-
-namespace content {
-
-class WorkerWebApplicationCacheHostImpl : public WebApplicationCacheHostImpl {
- public:
- WorkerWebApplicationCacheHostImpl(
- blink::WebApplicationCacheHostClient* client);
-
- // Main resource loading is different for workers. The main resource is
- // loaded by the worker using WorkerScriptLoader.
- // These overrides are stubbed out.
- virtual void willStartMainResourceRequest(
- blink::WebURLRequest&, const blink::WebApplicationCacheHost*);
- virtual void didReceiveResponseForMainResource(
- const blink::WebURLResponse&);
- virtual void didReceiveDataForMainResource(const char* data, int len);
- virtual void didFinishLoadingMainResource(bool success);
-
- // Cache selection is also different for workers. We know at construction
- // time what cache to select and do so then.
- // These overrides are stubbed out.
- virtual void selectCacheWithoutManifest();
- virtual bool selectCacheWithManifest(const blink::WebURL& manifestURL);
-};
-
-} // namespace content
-
-#endif // CHROME_WORKER_WORKER_WEBAPPLICATIONCACHEHOST_IMPL_H_
diff --git a/chromium/content/worker/worker_webkitplatformsupport_impl.cc b/chromium/content/worker/worker_webkitplatformsupport_impl.cc
deleted file mode 100644
index 2f1a9881047..00000000000
--- a/chromium/content/worker/worker_webkitplatformsupport_impl.cc
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright (c) 2012 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 "content/worker/worker_webkitplatformsupport_impl.h"
-
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/blink_glue.h"
-#include "content/child/database_util.h"
-#include "content/child/fileapi/webfilesystem_impl.h"
-#include "content/child/indexed_db/webidbfactory_impl.h"
-#include "content/child/quota_dispatcher.h"
-#include "content/child/quota_message_filter.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/child/web_database_observer_impl.h"
-#include "content/child/webblobregistry_impl.h"
-#include "content/child/webfileutilities_impl.h"
-#include "content/child/webmessageportchannel_impl.h"
-#include "content/common/file_utilities_messages.h"
-#include "content/common/mime_registry_messages.h"
-#include "content/worker/worker_thread.h"
-#include "ipc/ipc_sync_message_filter.h"
-#include "net/base/mime_util.h"
-#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
-#include "third_party/WebKit/public/platform/WebFileInfo.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "webkit/common/quota/quota_types.h"
-
-using blink::Platform;
-using blink::WebBlobRegistry;
-using blink::WebClipboard;
-using blink::WebFileInfo;
-using blink::WebFileSystem;
-using blink::WebFileUtilities;
-using blink::WebMessagePortChannel;
-using blink::WebMimeRegistry;
-using blink::WebSandboxSupport;
-using blink::WebStorageNamespace;
-using blink::WebString;
-using blink::WebURL;
-
-namespace content {
-
-// TODO(kinuko): Probably this could be consolidated into
-// RendererWebKitPlatformSupportImpl::FileUtilities.
-class WorkerWebKitPlatformSupportImpl::FileUtilities
- : public WebFileUtilitiesImpl {
- public:
- explicit FileUtilities(ThreadSafeSender* sender)
- : thread_safe_sender_(sender) {}
- virtual bool getFileInfo(const WebString& path, WebFileInfo& result);
- private:
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
-};
-
-bool WorkerWebKitPlatformSupportImpl::FileUtilities::getFileInfo(
- const WebString& path,
- WebFileInfo& web_file_info) {
- base::File::Info file_info;
- base::File::Error status;
- if (!thread_safe_sender_.get() ||
- !thread_safe_sender_->Send(new FileUtilitiesMsg_GetFileInfo(
- base::FilePath::FromUTF16Unsafe(path), &file_info, &status)) ||
- status != base::File::FILE_OK) {
- return false;
- }
- FileInfoToWebFileInfo(file_info, &web_file_info);
- web_file_info.platformPath = path;
- return true;
-}
-
-//------------------------------------------------------------------------------
-
-WorkerWebKitPlatformSupportImpl::WorkerWebKitPlatformSupportImpl(
- ThreadSafeSender* sender,
- IPC::SyncMessageFilter* sync_message_filter,
- QuotaMessageFilter* quota_message_filter)
- : thread_safe_sender_(sender),
- child_thread_loop_(base::MessageLoopProxy::current()),
- sync_message_filter_(sync_message_filter),
- quota_message_filter_(quota_message_filter) {
- if (sender) {
- blob_registry_.reset(new WebBlobRegistryImpl(sender));
- web_idb_factory_.reset(new WebIDBFactoryImpl(sender));
- web_database_observer_impl_.reset(
- new WebDatabaseObserverImpl(sync_message_filter));
- }
-}
-
-WorkerWebKitPlatformSupportImpl::~WorkerWebKitPlatformSupportImpl() {
- WebFileSystemImpl::DeleteThreadSpecificInstance();
-}
-
-WebClipboard* WorkerWebKitPlatformSupportImpl::clipboard() {
- NOTREACHED();
- return NULL;
-}
-
-WebMimeRegistry* WorkerWebKitPlatformSupportImpl::mimeRegistry() {
- return this;
-}
-
-WebFileSystem* WorkerWebKitPlatformSupportImpl::fileSystem() {
- return WebFileSystemImpl::ThreadSpecificInstance(child_thread_loop_.get());
-}
-
-WebFileUtilities* WorkerWebKitPlatformSupportImpl::fileUtilities() {
- if (!file_utilities_) {
- file_utilities_.reset(new FileUtilities(thread_safe_sender_.get()));
- file_utilities_->set_sandbox_enabled(sandboxEnabled());
- }
- return file_utilities_.get();
-}
-
-WebSandboxSupport* WorkerWebKitPlatformSupportImpl::sandboxSupport() {
- NOTREACHED();
- return NULL;
-}
-
-bool WorkerWebKitPlatformSupportImpl::sandboxEnabled() {
- // Always return true because WebKit should always act as though the Sandbox
- // is enabled for workers. See the comment in WebKitPlatformSupport for
- // more info.
- return true;
-}
-
-unsigned long long WorkerWebKitPlatformSupportImpl::visitedLinkHash(
- const char* canonical_url,
- size_t length) {
- NOTREACHED();
- return 0;
-}
-
-bool WorkerWebKitPlatformSupportImpl::isLinkVisited(
- unsigned long long link_hash) {
- NOTREACHED();
- return false;
-}
-
-void WorkerWebKitPlatformSupportImpl::createMessageChannel(
- blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2) {
- WebMessagePortChannelImpl::CreatePair(
- child_thread_loop_.get(), channel1, channel2);
-}
-
-void WorkerWebKitPlatformSupportImpl::setCookies(
- const WebURL& url,
- const WebURL& first_party_for_cookies,
- const WebString& value) {
- NOTREACHED();
-}
-
-WebString WorkerWebKitPlatformSupportImpl::cookies(
- const WebURL& url, const WebURL& first_party_for_cookies) {
- // WebSocketHandshake may access cookies in worker process.
- return WebString();
-}
-
-WebString WorkerWebKitPlatformSupportImpl::defaultLocale() {
- NOTREACHED();
- return WebString();
-}
-
-WebStorageNamespace*
-WorkerWebKitPlatformSupportImpl::createLocalStorageNamespace() {
- NOTREACHED();
- return 0;
-}
-
-void WorkerWebKitPlatformSupportImpl::dispatchStorageEvent(
- const WebString& key, const WebString& old_value,
- const WebString& new_value, const WebString& origin,
- const blink::WebURL& url, bool is_local_storage) {
- NOTREACHED();
-}
-
-Platform::FileHandle
-WorkerWebKitPlatformSupportImpl::databaseOpenFile(
- const WebString& vfs_file_name, int desired_flags) {
- return DatabaseUtil::DatabaseOpenFile(
- vfs_file_name, desired_flags, sync_message_filter_.get());
-}
-
-int WorkerWebKitPlatformSupportImpl::databaseDeleteFile(
- const WebString& vfs_file_name, bool sync_dir) {
- return DatabaseUtil::DatabaseDeleteFile(
- vfs_file_name, sync_dir, sync_message_filter_.get());
-}
-
-long WorkerWebKitPlatformSupportImpl::databaseGetFileAttributes(
- const WebString& vfs_file_name) {
- return DatabaseUtil::DatabaseGetFileAttributes(vfs_file_name,
- sync_message_filter_.get());
-}
-
-long long WorkerWebKitPlatformSupportImpl::databaseGetFileSize(
- const WebString& vfs_file_name) {
- return DatabaseUtil::DatabaseGetFileSize(vfs_file_name,
- sync_message_filter_.get());
-}
-
-long long WorkerWebKitPlatformSupportImpl::databaseGetSpaceAvailableForOrigin(
- const WebString& origin_identifier) {
- return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
- sync_message_filter_.get());
-}
-
-blink::WebIDBFactory* WorkerWebKitPlatformSupportImpl::idbFactory() {
- if (!web_idb_factory_)
- web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_.get()));
- return web_idb_factory_.get();
-}
-
-blink::WebDatabaseObserver*
-WorkerWebKitPlatformSupportImpl::databaseObserver() {
- return web_database_observer_impl_.get();
-}
-
-WebMimeRegistry::SupportsType
-WorkerWebKitPlatformSupportImpl::supportsMIMEType(
- const WebString&) {
- return WebMimeRegistry::IsSupported;
-}
-
-WebMimeRegistry::SupportsType
-WorkerWebKitPlatformSupportImpl::supportsImageMIMEType(
- const WebString&) {
- NOTREACHED();
- return WebMimeRegistry::IsSupported;
-}
-
-WebMimeRegistry::SupportsType
-WorkerWebKitPlatformSupportImpl::supportsJavaScriptMIMEType(const WebString&) {
- NOTREACHED();
- return WebMimeRegistry::IsSupported;
-}
-
-WebMimeRegistry::SupportsType
-WorkerWebKitPlatformSupportImpl::supportsMediaMIMEType(
- const WebString&, const WebString&, const WebString&) {
- NOTREACHED();
- return WebMimeRegistry::IsSupported;
-}
-
-bool WorkerWebKitPlatformSupportImpl::supportsMediaSourceMIMEType(
- const blink::WebString& mimeType, const blink::WebString& codecs) {
- NOTREACHED();
- return false;
-}
-
-bool WorkerWebKitPlatformSupportImpl::supportsEncryptedMediaMIMEType(
- const blink::WebString& key_system,
- const blink::WebString& mime_type,
- const blink::WebString& codecs) {
- NOTREACHED();
- return false;
-}
-
-WebMimeRegistry::SupportsType
-WorkerWebKitPlatformSupportImpl::supportsNonImageMIMEType(
- const WebString&) {
- NOTREACHED();
- return WebMimeRegistry::IsSupported;
-}
-
-WebString WorkerWebKitPlatformSupportImpl::mimeTypeForExtension(
- const WebString& file_extension) {
- std::string mime_type;
- thread_safe_sender_->Send(new MimeRegistryMsg_GetMimeTypeFromExtension(
- base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type));
- return base::ASCIIToUTF16(mime_type);
-}
-
-WebString WorkerWebKitPlatformSupportImpl::wellKnownMimeTypeForExtension(
- const WebString& file_extension) {
- std::string mime_type;
- net::GetWellKnownMimeTypeFromExtension(
- base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type);
- return base::ASCIIToUTF16(mime_type);
-}
-
-WebString WorkerWebKitPlatformSupportImpl::mimeTypeFromFile(
- const WebString& file_path) {
- std::string mime_type;
- thread_safe_sender_->Send(
- new MimeRegistryMsg_GetMimeTypeFromFile(
- base::FilePath::FromUTF16Unsafe(file_path),
- &mime_type));
- return base::ASCIIToUTF16(mime_type);
-}
-
-WebBlobRegistry* WorkerWebKitPlatformSupportImpl::blobRegistry() {
- return blob_registry_.get();
-}
-
-void WorkerWebKitPlatformSupportImpl::queryStorageUsageAndQuota(
- const blink::WebURL& storage_partition,
- blink::WebStorageQuotaType type,
- blink::WebStorageQuotaCallbacks callbacks) {
- if (!thread_safe_sender_.get() || !quota_message_filter_.get())
- return;
- QuotaDispatcher::ThreadSpecificInstance(
- thread_safe_sender_.get(),
- quota_message_filter_.get())->QueryStorageUsageAndQuota(
- storage_partition,
- static_cast<quota::StorageType>(type),
- QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
-}
-
-} // namespace content
diff --git a/chromium/content/worker/worker_webkitplatformsupport_impl.h b/chromium/content/worker/worker_webkitplatformsupport_impl.h
deleted file mode 100644
index 9fa56d464e9..00000000000
--- a/chromium/content/worker/worker_webkitplatformsupport_impl.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2012 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 CONTENT_WORKER_WORKER_WEBKITPLATFORMSUPPORT_IMPL_H_
-#define CONTENT_WORKER_WORKER_WEBKITPLATFORMSUPPORT_IMPL_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/child/blink_platform_impl.h"
-#include "third_party/WebKit/public/platform/WebIDBFactory.h"
-#include "third_party/WebKit/public/platform/WebMimeRegistry.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace IPC {
-class SyncMessageFilter;
-}
-
-namespace blink {
-class WebFileUtilities;
-}
-
-namespace content {
-class QuotaMessageFilter;
-class ThreadSafeSender;
-class WebDatabaseObserverImpl;
-class WebFileSystemImpl;
-
-class WorkerWebKitPlatformSupportImpl : public BlinkPlatformImpl,
- public blink::WebMimeRegistry {
- public:
- WorkerWebKitPlatformSupportImpl(
- ThreadSafeSender* sender,
- IPC::SyncMessageFilter* sync_message_filter,
- QuotaMessageFilter* quota_message_filter);
- virtual ~WorkerWebKitPlatformSupportImpl();
-
- // WebKitPlatformSupport methods:
- virtual blink::WebClipboard* clipboard();
- virtual blink::WebMimeRegistry* mimeRegistry();
- virtual blink::WebFileSystem* fileSystem();
- virtual blink::WebFileUtilities* fileUtilities();
- virtual blink::WebSandboxSupport* sandboxSupport();
- virtual bool sandboxEnabled();
- virtual unsigned long long visitedLinkHash(const char* canonicalURL,
- size_t length);
- virtual bool isLinkVisited(unsigned long long linkHash);
- virtual void createMessageChannel(blink::WebMessagePortChannel** channel1,
- blink::WebMessagePortChannel** channel2);
- virtual void setCookies(const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies,
- const blink::WebString& value);
- virtual blink::WebString cookies(
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies);
- virtual blink::WebString defaultLocale();
- virtual blink::WebStorageNamespace* createLocalStorageNamespace();
- virtual void dispatchStorageEvent(
- const blink::WebString& key, const blink::WebString& old_value,
- const blink::WebString& new_value, const blink::WebString& origin,
- const blink::WebURL& url, bool is_local_storage);
-
- virtual blink::Platform::FileHandle databaseOpenFile(
- const blink::WebString& vfs_file_name, int desired_flags);
- virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
- bool sync_dir);
- virtual long databaseGetFileAttributes(
- const blink::WebString& vfs_file_name);
- virtual long long databaseGetFileSize(
- const blink::WebString& vfs_file_name);
- virtual long long databaseGetSpaceAvailableForOrigin(
- const blink::WebString& origin_identifier);
- virtual blink::WebBlobRegistry* blobRegistry();
- virtual blink::WebIDBFactory* idbFactory();
- virtual blink::WebDatabaseObserver* databaseObserver();
-
- // WebMimeRegistry methods:
- virtual blink::WebMimeRegistry::SupportsType supportsMIMEType(
- const blink::WebString&);
- virtual blink::WebMimeRegistry::SupportsType supportsImageMIMEType(
- const blink::WebString&);
- virtual blink::WebMimeRegistry::SupportsType supportsJavaScriptMIMEType(
- const blink::WebString&);
- virtual blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
- const blink::WebString&,
- const blink::WebString&,
- const blink::WebString&);
- virtual bool supportsMediaSourceMIMEType(
- const blink::WebString&,
- const blink::WebString&);
- virtual bool supportsEncryptedMediaMIMEType(const blink::WebString&,
- const blink::WebString&,
- const blink::WebString&);
- virtual blink::WebMimeRegistry::SupportsType supportsNonImageMIMEType(
- const blink::WebString&);
- virtual blink::WebString mimeTypeForExtension(const blink::WebString&);
- virtual blink::WebString wellKnownMimeTypeForExtension(
- const blink::WebString&);
- virtual blink::WebString mimeTypeFromFile(const blink::WebString&);
- virtual void queryStorageUsageAndQuota(
- const blink::WebURL& storage_partition,
- blink::WebStorageQuotaType,
- blink::WebStorageQuotaCallbacks) OVERRIDE;
-
- WebDatabaseObserverImpl* web_database_observer_impl() {
- return web_database_observer_impl_.get();
- }
-
- private:
-
- class FileUtilities;
- scoped_ptr<FileUtilities> file_utilities_;
- scoped_ptr<blink::WebBlobRegistry> blob_registry_;
- scoped_ptr<blink::WebIDBFactory> web_idb_factory_;
- scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- scoped_refptr<base::MessageLoopProxy> child_thread_loop_;
- scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
- scoped_refptr<QuotaMessageFilter> quota_message_filter_;
- scoped_ptr<WebDatabaseObserverImpl> web_database_observer_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerWebKitPlatformSupportImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_WORKER_WORKER_WEBKITPLATFORMSUPPORT_IMPL_H_
diff --git a/chromium/content/zygote/OWNERS b/chromium/content/zygote/OWNERS
index 602e00e0750..c2dd4263b5c 100644
--- a/chromium/content/zygote/OWNERS
+++ b/chromium/content/zygote/OWNERS
@@ -1,3 +1,2 @@
-markus@chromium.org
-cevans@chromium.org
jln@chromium.org
+mdempsky@chromium.org
diff --git a/chromium/content/zygote/zygote_linux.cc b/chromium/content/zygote/zygote_linux.cc
index e5e91296da7..a464fcdf6a7 100644
--- a/chromium/content/zygote/zygote_linux.cc
+++ b/chromium/content/zygote/zygote_linux.cc
@@ -12,7 +12,7 @@
#include "base/command_line.h"
#include "base/debug/trace_event.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/linux_util.h"
#include "base/logging.h"
#include "base/macros.h"
diff --git a/chromium/content/zygote/zygote_main_linux.cc b/chromium/content/zygote/zygote_main_linux.cc
index 60f08b6ad63..361511e3737 100644
--- a/chromium/content/zygote/zygote_main_linux.cc
+++ b/chromium/content/zygote/zygote_main_linux.cc
@@ -7,6 +7,7 @@
#include <dlfcn.h>
#include <fcntl.h>
#include <pthread.h>
+#include <signal.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -22,17 +23,16 @@
#include "base/posix/eintr_wrapper.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/rand_util.h"
+#include "base/strings/safe_sprintf.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
#include "build/build_config.h"
#include "content/common/child_process_sandbox_support_impl_linux.h"
#include "content/common/font_config_ipc_linux.h"
-#include "content/common/pepper_plugin_list.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/common/zygote_commands_linux.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
-#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/sandbox_linux.h"
#include "content/public/common/zygote_fork_delegate_linux.h"
#include "content/zygote/zygote_linux.h"
@@ -47,6 +47,15 @@
#include <sys/prctl.h>
#endif
+#if defined(USE_OPENSSL)
+#include <openssl/rand.h>
+#endif
+
+#if defined(ENABLE_PLUGINS)
+#include "content/common/pepper_plugin_list.h"
+#include "content/public/common/pepper_plugin_info.h"
+#endif
+
#if defined(ENABLE_WEBRTC)
#include "third_party/libjingle/overrides/init_webrtc.h"
#endif
@@ -57,6 +66,43 @@
namespace content {
+namespace {
+
+void DoChrootSignalHandler(int) {
+ const int old_errno = errno;
+ const char kFirstMessage[] = "Chroot signal handler called.\n";
+ ignore_result(write(STDERR_FILENO, kFirstMessage, sizeof(kFirstMessage) - 1));
+
+ const int chroot_ret = chroot("/");
+
+ char kSecondMessage[100];
+ const ssize_t printed =
+ base::strings::SafeSPrintf(kSecondMessage,
+ "chroot() returned %d. Errno is %d.\n",
+ chroot_ret,
+ errno);
+ if (printed > 0 && printed < static_cast<ssize_t>(sizeof(kSecondMessage))) {
+ ignore_result(write(STDERR_FILENO, kSecondMessage, printed));
+ }
+ errno = old_errno;
+}
+
+// This is a quick hack to allow testing sandbox crash reports in production
+// binaries.
+// This installs a signal handler for SIGUSR2 that performs a chroot().
+// In most of our BPF policies, it is a "watched" system call which will
+// trigger a SIGSYS signal whose handler will crash.
+// This has been added during the investigation of https://crbug.com/415842.
+void InstallSandboxCrashTestHandler() {
+ struct sigaction act = {};
+ act.sa_handler = DoChrootSignalHandler;
+ CHECK_EQ(0, sigemptyset(&act.sa_mask));
+ act.sa_flags = 0;
+
+ PCHECK(0 == sigaction(SIGUSR2, &act, NULL));
+}
+} // namespace
+
// See http://code.google.com/p/chromium/wiki/LinuxZygote
static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
@@ -312,9 +358,10 @@ static void ZygotePreSandboxInit() {
// successful initialization of NSS which tries to load extra library files.
crypto::LoadNSSLibraries();
#elif defined(USE_OPENSSL)
- // OpenSSL is intentionally not supported in the sandboxed processes, see
- // http://crbug.com/99163. If that ever changes we'll likely need to init
- // OpenSSL here (at least, load the library and error strings).
+ // Read a random byte in order to cause BoringSSL to open a file descriptor
+ // for /dev/urandom.
+ uint8_t scratch;
+ RAND_bytes(&scratch, 1);
#else
// It's possible that another hypothetical crypto stack would not require
// pre-sandbox init, but more likely this is just a build configuration error.
@@ -402,7 +449,12 @@ static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
LOG(ERROR) << "Failed to set non-dumpable flag";
return false;
}
+ } else {
+ // If sandbox debugging is allowed, install a handler for sandbox-related
+ // crash testing.
+ InstallSandboxCrashTestHandler();
}
+
#endif
return true;